18. Workshop Software-Reengineering und -Evolution · Software-Reengineering ... a tool that...

31
18. Workshop Software-Reengineering und -Evolution der GI-Fachgruppe Software-Reengineering (SRE) zusammen mit dem Workshop Design For Future des Arbeitskreises Langlebige Softwaresysteme (L2S2) Bad Honnef 2.-4. Mai 2016

Transcript of 18. Workshop Software-Reengineering und -Evolution · Software-Reengineering ... a tool that...

Page 1: 18. Workshop Software-Reengineering und -Evolution · Software-Reengineering ... a tool that measures code metrics and also outputs results on maintainability. These quantitative

18. Workshop

Software-Reengineering und -Evolution

der GI-Fachgruppe Software-Reengineering (SRE)

zusammen mit dem

Workshop Design For Futuredes Arbeitskreises Langlebige Softwaresysteme (L2S2)

Bad Honnef

2.-4. Mai 2016

!

Page 2: 18. Workshop Software-Reengineering und -Evolution · Software-Reengineering ... a tool that measures code metrics and also outputs results on maintainability. These quantitative

Maintainability is a Versatile Quality Attribute Jens Knodel, Matthias Naab

Fraunhofer IESE Fraunhofer-Platz 1, 67663 Kaiserslautern, Germany

{jens.knodel, matthias.naab}@iese.fraunhofer.de

Abstract— Software architecture evaluation has been widely

accepted as a powerful means to mitigate risks in the design and evolution of software systems. To date we have conducted more than 75 architecture evaluation projects with industrial customers in the past decade. One recurring lesson learned that we experienced across many architecture evaluation projects is that maintainability indeed is a versatile quality attribute and its evaluation requires a mix of quantitative and qualitative checks.

Keywords—software architecture, architecture evaluation, maintainability, reconstruction, reverse engineering, experience report

I. INTRODUCTION There is no doubt about it: the quality attribute

maintainability is crucial for the long-term success of a software system. The evaluation of maintainability consequently plays an important role in software evaluations. It contributes to answering questions like “Is our system a solid basis for the future?” or “Can we make the upcoming changes within a reasonable amount of time and budget?”

Evaluating maintainability can mean to check for different aspects: (1) it can be checked how adequate and maintainable an architecture and the underlying software system is in terms of supporting certain anticipated changes, (2) it can be checked how large the impact of a potential change request is and thus enable effort estimations, (3) it can be checked to which extent rules of good design and coding are adhered to, and (4) it can be checked how readable and understandable (and thus maintainable) the source code is. While the first two address specific properties of the product, the latter two address mental capabilities of software engineers.

The ISO 25010 definition of the quality attribute maintainability reflects this differentiation in its sub-qualities: x Modifiability / changeability are aspects that mainly

determine the overall change effort by the degree to which a concrete change is distributed over the whole system (from local to nearly global). This is mainly determined by major architecture decisions. Whether a change can be performed with low effort (meaning the system is maintainable) can be strongly influenced by architecture decisions, which cannot be measured locally in the code. For example, the requirement to replace the UI framework (e.g., because it is no longer supported by the vendor) might spread out over large parts of a system if there is no clear separation of the UI part and maybe even the concrete technology.

x Readability / analyzability are aspects that are mainly aiming at the understanding of the developers and strongly

depend on the code quality (of course not exclusively; the overall architecture also has some impact here). That is, when developers have to change a certain part of the code, they first have to understand it. Good code quality obviously supports this. There has been a lot of research and numerous approaches exist regarding how to measure what good readability of code means. What is interesting now is that this type of code quality does not depend on the concrete product under development. Rather, it depends on the mental capabilities of the available developers. For example, if methods are too long or the degree of nesting is too high, they are hard to read, or cyclic dependencies are hard to understand. Finding good rules and thresholds thus has to be calibrated in empirical studies observing how well developers can work given certain code characteristics.

II. EVALUATING MAINTAINABILITY Maintainability is a quality attribute with many

indirections. Most of the time, it is not directly visible, in particular not for the end user, often not for the customer, and often not even for the developer. It is very common that there is not so much focus put on maintainability during initial system development (where time to market often predominates). The lack of maintainability and its consequences are perceived in later stages of system evolution and maintenance. Even then, the perception is mainly indirect, visible only in the high cost of changes. Another reason that makes maintainability harder to handle is that it is mostly difficult to precisely formulate maintainability requirements. Anticipated changes can be stated, but often it is pretty open how a system will evolve. In terms of readability, requirements are rather stated in terms of coding conventions than as real requirements.

A. Measuring Maintainability Quantitatively When it comes down to measuring maintainability, this is

not an easy task. In practice, the simple solution is often to buy a tool that measures code metrics and also outputs results on maintainability. These quantitative results can, of course, be valuable. However, they are only part of the answer. They are that part of the answer that deals with the readability / analyzability of the source code. The good thing is that it is easy to codify such rules and quantitative metrics and measure them with standard tools. This is often done in practice.

What is missing are considerations of major architectural decisions and concrete change scenarios of the software system. However, measuring this part of maintainability is not so easy for several reasons:

Page 3: 18. Workshop Software-Reengineering und -Evolution · Software-Reengineering ... a tool that measures code metrics and also outputs results on maintainability. These quantitative

x Measurement needs concrete (anticipated) change requests as a baseline and often change requests that may occur further along in the future are not known yet.

x Measurement is not possible in absolute terms, but rather requires the usage of architecture evaluation techniques, which produce only qualitative results.

x Measurement is only possible manually with the help of experts; tool support is quite limited as the evaluation is individual for each specific product. Thus, this type of measurement is often neglected in practice and, as a consequence, maintainability is not measured sufficiently.

B. Checking Adequacy of Solution Concepts for Maintainability Qualitatively There is no good or bad architecture – an architecture (or

rather the solutions concepts defined by the architecture) always has to be adequate to satisfy requirements of the system at hand. More clarification is needed regarding what talking about the adequacy of “an architecture” means: An architecture is not a monolithic thing: It consists of many architecture decisions that together form the architecture. In the SAC, architecture drivers and architecture decisions are correlated. An architecture decision can support an architecture driver; it can adversely impact the driver; or it can be unrelated. Whenever it is not possible to observe properties in the running system or in local parts of the implementation, architecture becomes the means to provide the right abstractions for evaluating system properties.

Evaluating for maintainability benefits from a sound set of architecture drivers as input. The architecture drivers (in case of maintainability this means potential, possible or concrete change requests) are then evaluated qualitatively, the findings can be aggregated into an overall result. The checking of the adequacy works across “two worlds”: requirements in the problem space and architecture in the solution space. There is no natural traceability relation between requirements and architecture. Rather, architectural decisions are creative solutions, which are often based on best practices and experiences, but sometimes require completely new approaches. This has an impact on the solution adequacy check: It offers limited opportunities for direct tool-supported analyses and is rather an expert-based activity.

The goal is to get the confidence that the solutions are adequate to be prepared towards change. As architecture is always an abstraction of the underlying software system, it typically does not allow for ultra-precise results. Thus, it should be made clear throughout an architecture evaluation which level of confidence needs to be achieved and what this means in terms of investment into evaluation activities.

Another form of qualitative evaluation works without concrete architecture drivers checking for the usage of architectural best practices like patterns or the SOLID principles. While these best practices can greatly support anticipated changes, they still can provide large benefits for unknown changes. However, the confidence achieved is lower.

C. Interpretation of Quantitative and Qualitative Findings The interpretation of the findings is crucial in order to

benefit from the overall evaluation results. The evaluation

reveals typically positive and negative findings about both the code quality and the adequacy of the solution concepts. The interpretation of the findings is context-dependent, based on the underlying evaluation question, the software system under evaluation, and the nature of a finding. In particular in case of negative findings, it is the starting point towards deriving improvement actions.

The nature of findings is characterized by the cause of the finding. Causes can either be based on product properties such as the inherent flaws or weaknesses of the software system or technology and their misusage, or on human capabilities and human limitations in terms of coping with complexity (i.e., comprehensibility) and dealing with continuous change in the evolution of the software system (which is the inevitable characteristic of any successful system).

Typically, findings caused by technologies in use and limitations of human capabilities are more general. They serve to detect risks with respect to best practices, guidelines, misusage, or known pitfalls in the technologies. In practice, it is much easier to aim for such causes because tools can be bought that come, for instance, with predefined rules or standard thresholds and corridors for metrics. They are easy to apply and make people confident that they are doing the right thing to mitigate risks. The downside is that such general-purpose means often do not fit to the evaluation questions driving the architecture evaluation, but this is not discovered.

III. CONCLUSIONS What is common sense for testing (no one would just run

technology-related test cases without testing the product-specific logic of the software system) is not the case for architecture evaluations and source code quality checks. Here, many development organizations and tool vendors claim to be product-specific with a general-purpose technique realized in a quality assurance tool that can be downloaded from the Internet. However, these general-purpose techniques can merely lead to confidence regarding the avoidance of risks with respect to the technology or the limitations of human capabilities. To reliably make statements about the maintainability of a software system, both aspects, quantitative measurement of the source and qualitative evaluation of the adequacy of the solution concept are essential. Our lessons learned for maintainability are partly transferrable to other quality attributes such as performance, security, or reliability exhibit similar properties, meaning that code quality and architectural solution adequacy are both crucial for fulfilling the requirements.

Another characteristic of maintainability (which has increasing importance due to demanding requirements regarding time-to-market) is beyond the paper’s scope: Changing a software system more and more needs a strong and dedicated integration, testing, and delivery pipeline which allows bringing the changed system in production with a high confidence in the resulting quality. This covers process, tooling, and architectural aspects that need to be well aligned to achieve the maintenance and release goals.

REFERENCES [1] J. Knodel, M. Naab: „Pragmatic Evaluation of Software

Architectures“, Springer, ISBN 978-3-319-34176-7, 2016.

Page 4: 18. Workshop Software-Reengineering und -Evolution · Software-Reengineering ... a tool that measures code metrics and also outputs results on maintainability. These quantitative

Schätzung Reengineering Alternative

Harry M. Sneed SoRing Kft. H-1221 Budapest

ZT-Prentner, A1220 Wien [email protected]

Abstrakt: Bei der Auswahl einer geeigneter Migrationsstrategie müssen u.a. die Kosten berücksichtigt werden. Das macht es erforderlich den Aufwand für jedes Alternativ zu schätzen und zu vergleichen. In dem Projekt, das hier geschildert wird gab es drei Alternative, den alten Code direkt 1:1 in Java konvertieren, den alten Code erst zu sanieren und dann in Java transformieren, und den Code komplett neu zu schreiben in Java. Dieser Beitrag beschreibt worum es ging, wie vorgegangen. Da das Migrationsprojekt noch aussteht, ist es zu früh zu sagen welchen Migrationspfad eingeschlagen wird, geschweige denn ob der geschätzte Aufwand auch stimmt. Es geht hier allein um die Schätzmethode. .

Schlüsselwörter: Migration, Reengineering, Software Aufwandsschätzung, Productivity, Risikoanalyse, COCOMO, Data-Point, Function-Point.

1 Hintergrund des Migrationsprojektes Eine mittelständische Speditionsfirma in Österreich steht vor der Notwendigkeit ihr bestehendes AS-400 bzw. I-Series, System für die Steuerung von Transportgütern durch Europa abzulösen. Das alte System ist in der 4GL Sprache Synon von Computer Associates implementiert aus der RPG Code generiert wird. Synon gehört zu den CASE Tools der 80er Jahren und ist eigentlich sehr effektiv. Synon Entwickler können bis zu 100% produktiver als Java Entwickler sein weil sehr viele Business-Funktionen in der Sprache eingebaut sind. Synon baut auf einer Repository auf und verbindet viele Software Entitätentypen mit einander – Bildschirmmasken, Berichte, Schnittstellen, Dateien und Business-Logik Module mit einander. Sie ist auf die AS-400 Maschine zugeschnitten. Nur Synon hat Grenzen was das Mengengerüst anbetrifft und das Zielsystem ist an diese Grenzen gestoßen. Außerdem hat die Sprache auch Grenzen was die Integrierbarkeit und Portierbarkeit anbetrifft. Schließlich ist sie eine Exote in der heutigen IT-Welt. Es gibt kaum noch Entwickler die sie beherrschen. In Anbetracht dieser Defizite wurde entschieden sie abzulösen.

2 Migrationsalternative Aufgrund einer Voruntersuchung wurden drei alternative Migrationsstrategien festgestellt – 1:1

Konversion, Reengineering und Neuentwicklung. Für Konversion und Reenginerering wurden zwei Pilotprojekte mit Ausschnitten aus dem Gesamtsystem durchgeführt um a.) die Machbarkeit und b.) den Aufwand zu ermitteln. Aus dieser Erfahrung wurden die Produktivitätsdaten entnommen. Die Produktivität für die Neuentwicklung in Java wurde aus einem Schwesterprojekt entnommen. Die wichtigsten Codegrößen – Anweisungen, Data-Points, Ojbect-Points und Function-Points wurden mittels einer statischen Analyse aus dem Java Source-Code abgeleitet und justiert nach Komplexität und Qualität. Diese Kenngrößen wurden dann den Aufwandsdaten gegenübergestellt um die mittlere Produktivität von 1,1 Function-Points pro Personentag festzustellen.

3 Zerlegung des Zielsystem Source-Codes Ehe mit der Analyse des Zielsystems begonnen wurde, musste es in 13 Einzelsysteme zerlegt werden. Der Anwender wollte die Möglichkeit haben die Migration schrittweise durchzuführen, also ein Teilsystem nach dem Anderen. Eine betriebswirtschaftliche Analyse ergab dass es im Gesamtsystem 13 einzelne Systeme gab, die funktional voneinander unabhängig waren. Dennoch gab es eine Menge Dateien und Code-Module die in mehreren dieser Teilsysteme vorkamen. Um die Systeme unabhängig voneinander zu migrieren wurden diese Elemente vervielfältigt. In jedes Teilsystem kam eine Kopie. Das hatte zur Folge, dass auch die Source-Bibliotheken reorganisiert werden mussten. Die eine große Source-Bibliothek wurde in 13 einzelne Bibliotheken aufgeteilt und die Duplikate in jene Bibliotheken hineinkopiert zu denen sie gehörten. Dadurch wurde die gesamte Codemenge erhöht aber jedes Teilsystem war vollständig.und konnte als eigenes Projekt geschätzt werden.

4 Messung der Zielsystemgröße Die Größe des Synon Systeme musste indirekt gemessen werden, da es kein Tool gibt die den Synon Source analysieren kann. Im Grunde genommen gibt es gar keine Synon Source, sondern nur eine Repository mit verschiedenen Artifaktentypen. Deshalb wurde der generierte RPG Source für die Messung herangezogen und durch einen Expansionsfaktor von 3:1 in Java Größen umgesetzt, d.h. aus den 7,8 Millionen RPG Statements wurden 2,6 Java statements abgeleitet. Function-Points und Data-Points sind unabhängig von der Programmiersprache. Es folgten aus der Analyse

Page 5: 18. Workshop Software-Reengineering und -Evolution · Software-Reengineering ... a tool that measures code metrics and also outputs results on maintainability. These quantitative

130.954 Data-Points und 32.383 Function-Points. Diese Größen wurden mit den Aufwandsdaten aus der Zielsystementwicklung verglichen um eine Produktivität von 1,9 Function-Points pro Personentag zu errechnen. Diese Produktivitätsrate wurde verifiziert gegen die gebuchten Aufwände anderer Synon Projekte.

5 Ermittlung der Produktivitätsdaten Die Ermittlung der Produktivitätsdaten ist eine der Haupthindernisse zur Schätzung von Aufwand in der Industrie. Die wenigsten Anwenderbetriebe haben sie. Das zwingt die Aufwandschätzer auf Daten aus der Literatur auszuweichen, z.B. die Capers Jones Daten für Function-Point Produktivität [Jone00]. Diese Praxis darf jedoch nur eine Notlösung sein. Die Produktivität variiert so erheblich zwischen Ländern und Anwendern, dass sie kaum geeignet ist. Bereits in einer Studie aus dem Jahr 2000 hat Kathrin Maxwell erwiesen dass es große Unterschiede gibt zwischen Branchen. Banken und Versicherungen sind 100% weniger produktiv als Handelsunternehmen [Maxw2000]. Bei derartig großer Unterschiede ist auf die Produktivitätsdaten aus der Ferne wenig Verlass. Zum Glück konnten die Schätzungen hier auf heimische Produktivitätsdaten aufbauen. Die Produktivität bei einer Neuentwicklung wurde aus dem anderen Java Projekt übernommen. Die Produktivität bei einer 1:1 Konversion wurde aus dem Konversionspilotprojekt übernommen. Sie betrug in etwa das Doppelte der Produktivität in einer Neuentwicklung, d.h. 2,2 Function-Points pro Personentag. Die Produktivität bei dem Reengineering Projekt betrug 60% der Produktivität in einer Neuentwicklung, d.h. 1,75 Function-Points pro Personentag.

6 Aufbau einer Schätzdatenbank Jetzt konnte mit der eigentlichen Kostenkalkulation begonnen werden. Die Größen, Komplexitäten und Qualitäten aus der Codemessung wurden aus der Codemessungsdatenbank in die Schätzdatenbanken übernommen. Da jedes Teilsystem als eigenständiges Projekt zu betrachten war gab es eine eigene Schätzdatenbank für jedes Teilsystem. Die Größenkennzahlen wurden auf der Modulebene geliefert, d.h. es gab eine Zeile in der Schätztabelle für jeden Modul. < Entity = "Component" EName = "BORKOR3" EType = "MODU" > <Component_Attributes> <Nr_Locs>001640</Nr_Locs> <Nr_Stmts>000829</Nr_Stmts> <Nr_Functs>000042</Nr_Functs> <Nr_Variables>000254</Nr_Variables> <Change_Rate>0.000</Change_Rate> </Component_Attributes> </Entity> Man muss bedenken, dass es 5603 Module gab in dem gesamten System. Hinzu kamen die 2426

Bildschirmmasken, die 147 Druckberichte, die 1541 Physical Files und die 115 SQL Datenbanktabellen. Sie und ihre Attributanzahl wurden alle in die Schätzdatenbanken geladen. Anschließend wurden sie aggregiert und durch die Komplexität und Qualität des einzelnen Systems justiert. Zu den reinen Produktdaten kommen in der Schätzdatenbank die Risikodaten, die Produktivitätsdaten und die Einflussfaktoren hinzu. Die Risikodaten wurden aus der Risikoanalyse übernommen. Die Produktivitätsdaten kamen von den Benchmark-Projekten. Lediglich die Einflussfaktoren mussten vom Schätzer eingegeben werden. Damit war die Schätzdatenbank für die Schätzung selbst aufbereitet.

7 Schätzung der Migrationskosten Nachdem die Schätzdaten aufbereitet waren liefen die einzelnen Schätzungen automatisch ab, eine für jede der drei Migrationsvarianten für jedes der 13 Teilsysteme plus das System als Ganzes. Das machte 42 Schätzungen insgesamt. Jede Schätzung wurde nach drei verschiedenen Methoden durchgeführt: COCOMO, Data-Point und Function-Point. Sie konnten alle innerhalb eines Tages durchgezogen werden. Falls etwas geändert werden musste, konnte die Schätzung leicht wiederholt werden. In dem Schätzbericht gibt es neben dem Aufwand auch die Kosten, die erforderliche Personenanzahl und die geschätzte Dauer. Für das gesamte System gab es folgende Schätzungen für 1115 KDSI, 130594 Data-Points und 32380 Function-Points.: x Konversion nach COCOMO = 788 PMs x Konversion nach DataPt = 772 PMs x Konversion nach FunctPt = 846 PMs x Reengineering nach COCOMO = 1011 PMs x Reengineering nach DataPt = 985 PMs x Reengineering nach FunctPt = 1111 PMs x Redevelopment nach COCOMO = 1673 PMs x Redevelopment nach DataPt = 1694 PMs x Redevelopment nach FunctPt = 1835 PMs Eine Untermenge dieser Schätzungen gab es für jedes Teilsystem aufgrund der Größen des Subsystems. Mit diesen Daten wurde der Anwender in die Lage versetzt die alternativen Migrationsansätze nach ihrer Kosten zu vergleichen. Es folgte eine weitere Untersuchung sie nach ihren Nutzen zu vergleichen. Der Nutzen einer Neuentwicklung ist natürlich viel größer als der einer reinen Konversion. Ob er den Kosten ausgleicht ist eine andere Frage. Literaturhinweise: [Maxw00] Maxwell, K./Forseluus, P.: Survey of Software Productivity in Europe, IEEE Software, Jan. 2000, S. 80 [Jone00] Jones, C.: Software Assessments, Benchmarks and best Practices, Addison-Wesley, Reading, MA., 2000

Page 6: 18. Workshop Software-Reengineering und -Evolution · Software-Reengineering ... a tool that measures code metrics and also outputs results on maintainability. These quantitative

Wissensgewinnung und -nutzung in Outsourcing-Projekten

Stephan Tost Sopra Steria Consulting, Hamburg E-Mail: [email protected]

Abstract: Wie schon in [1] festgestellt wurde, sind Application Management Services (AMS) als Outsourcing-Modell für den Betrieb und die Wartung von Softwaresystemen weit verbreitet und auch weiterhin im Fokus der Entscheider (vgl. [2]). Dabei werden verschiedene Phasen in der Zusammenarbeit zwischen Kunde und Dienstleister durchlaufen. Vor Vertragsschluss erfolgt in der Due Diligence eine relativ grobe Betrachtung des Themengebietes. Nach Vertragsschluss beginnt die Übergabephase (Transition); es folgt die Betriebsphase in Verantwortung des Dienstleisters. Am Ende steht die Rücktransition, wobei der Dienstleister die Betreuung der Anwendung wieder an den Kunden oder einen anderen Dienstleister abgibt. Eine der zentralen Herausforderungen eines AMS-Dienstleisters bei einem solchen Projekt, ist die Gewinnung und Erfassung von Wissen um die zu betreuende Systemlandschaft sowie die Schaffung von effizienten Nutzungs- und Pflegemöglichkeiten dieser Informationen. Dieser Beitrag beleuchtet dieses Themengebiet auf Basis von konkreten Projekterfahrungen und gibt Tool- und Vorgehensempfehlungen aus Sicht eines AMS-Dienstleisters.

1 Einführung

1.1 Wissen

Wissen im Umfeld von AMS sind in erster Linie Informationen über die zu betreuenden Komponenten als solche und das Zusammenspiel der Komponenten (untereinander und von/nach außerhalb der Systemlandschaft). Neben reinen entwicklungs-, betriebs- und supporttechnischen Aspekten sind organisatorische und prozessuale Fragestellungen des Kundenumfeldes ebenfalls zu beachten. In den verschiedenen Phasen eines AMS-Engagements (vgl. [1]) fallen Wissensmengen unterschiedlicher Granularität und Qualität an. Es ist für die laufende und jeweils folgenden Phasen enorm hilfreich, dieses Wissen mit Hilfe von geeigneten Werkzeugen und Methoden so zu strukturieren und aufzubereiten, dass die Folgeaktivitäten nahtlos darauf aufbauen und damit arbeiten können. Bereits in der Due Diligence sollte der Grundstein für die spätere Wissensbasis gelegt werden.

1.2 Werkzeuge

Der AMS-Dienstleister wird bei der Organisation des nötigen Wissens nicht ohne Werkzeuge auskommen. Er sollte sich bei der Werkzeugwahl an die Kundensituation anpassen, wenn dort adäquate Werkzeuge vorgehalten werden. Vorteil davon ist u. a., dass der Support der Werkzeuge in der Kundenumgebung (durch und in Verantwortung des Kunden) sichergestellt ist. Außerdem kann bei einer zukünftigen AMS-Rücktransition das operative Geschäft nahtlos weiterlaufen, ohne technische Wissens- oder Werkzeugmigrationen vornehmen zu müssen. Wenn man nicht eine der gängigen IT-Service-Management (ITSM)-Suiten nutzen kann, die alle nötigen Disziplinen integriert abbildet, ist als wichtiges Kriterium bei der Auswahl von Werkzeugen (siehe auch [3]) die Möglichkeit zu nennen, Verknüpfungen zwischen den Systemen herstellen zu können. Neben den jeweiligen Standardwerkzeugen für die gängigen ITSM-Prozesse (vgl. [4]) ist die Nutzung eines Wikis (z. B. Confluence) und eines Ticketingwerkzeuges, (z. B. Jira) schlank und gleichzeitig mächtig genug, um den Verlauf der Projekte extrem positiv zu beeinflussen.

2 Wissensgewinnung und -nutzung

2.1 Wissenstransfer Einer der wichtigsten Aspekte für den AMS-Dienstleister ist es, das vorhandene Wissen bei der Übernahme der Aufgaben (Transition), entgegenzunehmen, zu erhalten und nutzbar zu machen. Ziel muss es sein, das für Betrieb, Weiterentwicklung, Pflege und Support der Anwendungen notwendige Know-how in eine personenunabhängige Form zu bringen, die vom AMS-Team genutzt und gepflegt werden kann. Dazu hat sich das Vorgehen des „Shadowings“ bewährt, wobei der Wissensgeber (Kunde) den Wissensnehmer (Dienstleister) einarbeitet. Parallel dazu ergänzt, aktualisiert oder erstellt der Wissensnehmer die Dokumentation, welche vom Wissensgeber abgenommen wird. Es folgt die Reverse-Shadowing-Phase: Der Wissensnehmer übernimmt die operativen Aufgaben und wird dabei vom Wissensgeber begleitet. Alle Themengebiete müssen vorher klar abgegrenzt und mit eindeutigen

Page 7: 18. Workshop Software-Reengineering und -Evolution · Software-Reengineering ... a tool that measures code metrics and also outputs results on maintainability. These quantitative

Verantwortlichkeiten aus Wissensgeber- und Wissensnehmerteam belegt werden. Damit wird nachvollziehbar, ob alle für den Verantwortungsübergang an den Dienstleister nötigen Informationen übergeben wurden.

2.2 Informationen geordnet ablegen

Kernaufgabe der Transition ist es, die erhaltenen Informationen so abzulegen, dass sie später bei Bedarf zielgerichtet wiedergefunden werden können. Bereits während der Due Diligence ist es möglich, eine erste Struktur der Informationsbasis zu erstellen. Als Rahmen dienen allgemeine Themenfelder (z. B. thematisch geordnete Ansprechpartnerlisten) und natürlich die zu betreuenden Komponenten selbst. Zu Letzteren kann - je nach Umfang der AMS-Aufgabe - eine Basisstruktur definiert werden, die für jede Komponente gleich ist. Somit finden sich die Nutzer themenunabhängig überall zurecht und es kann leicht überprüft werden, ob zu einer Komponente alle benötigten Informationen vorhanden sind. Ebenfalls bewährt hat sich die Anlehnung der Wikistruktur an den Aufbau der Systemlandschaft (Komponenten-Artikel als Subseiten des Artikels des Servers, auf dem die Komponenten laufen). Einmal aufgebaut, ist die Pflege der Informationsbasis elementar für eine langfristige Nutzung. Erfahrungsgemäß ist die Selbstverständlichkeit der Pflege der „lebenden“ Dokumentation stark personenabhängig und sollte von den Mitarbeitern und Projektleitern entsprechend feinfühlig gesteuert werden.

2.3 Übersicht schaffen

Es ist enorm hilfreich, wenn alle Beteiligten vom Gleichen sprechen, wenn eine bestimmte Komponente, ein Ablauf, Daten oder übergreifende Zusammenhänge gemeint sind. Dies verkürzt Diskussionen, vermeidet Fehlerpotential, Verzögerungen und Missverständnisse. Es hat sich

gezeigt, dass die Darstellung der kompletten Systemlandschaft in einer graphischen Übersicht

ein hilfreiches Artefakt (wenn nicht gar das wichtigste Artefakt überhaupt) darstellt. Auch wenn eine solche Darstellung (vgl. Abb.1) zunächst höchst komplex und verwirrend zu wirken scheint, erkennt doch jeder Beteiligte „seinen“ Themenbereich darin wieder und kann die Abhängigkeiten und Schnittstellen zu den Nachbarkomponenten verfolgen und verstehen. Wird die Systemübersicht auf Basis der anfallenden Änderungen gepflegt, erhält man ein mächtiges Werkzeug, welches für viele RTB- und CTB-Belange ein höchst hilfreiches Artefakt darstellt.

2.4 Thementracking

Es ist üblich, dass der AMS-Dienstleister von Beginn seines Engagements an den Bedarf hat, jedwede Art von Tasks aufzuwerfen und/oder zu verfolgen. Typische Beispiele sind Optimierungs- und Automatisierungsansätze, die Aufarbeitung von jahrelang verschleppten Aufträgen, die Annäherung an die vorgegebenen Prozesse oder auch reguläre Tätigkeiten z. B. im Rahmen eines Releases. Hierzu ist ein Trackingsystem hilfreich (z. B. Jira), in dem alle anfallenden Aufgaben erfasst, priorisiert, mit Verantwortlichkeiten versehen und dokumentiert werden können. So können - auch über längere Laufzeiten hinweg - Themen, Entwicklungen und vor allem Entscheidungen dokumentiert und somit transparent und nachvollziehbar gemacht werden.

3 Fazit Im Rahmen von Application Management Services ist es elementar wichtig für den Projekterfolg, Transparenz (für Dienstleister und Kunde) in die Systemlandschaft zu bringen. Dazu geeignete Werkzeuge sind die Visualisierung der Systemlandschaft, die strukturierte Ablage und Pflege des operativ notwendigen Wissens und das Tracking von Aufgaben und Optimierungsthemen. Unumgänglich ist es, sich regelmäßig und konsequent mit der Pflege und Aktualisierung der genutzten Informationsbasen zu befassen.

4 Literatur [1] Jens Borchers: Software-Qualitätsmanagement im Rahmen von

Application Management Services, 38. WI-MAW-Rundbrief, FB Wirtschaftsinformatik der Gesellschaft für Informatik, Jahrgang 20, Heft 2, 2014, ISSN 1610-5753

[2] Lünendonk: Software-Modernisierung - Im Spannungsfeld zwischen Zwangsläufigkeit und Aufwand, Whitepaper, http://www.kienbaum.de/Portaldata/1/Resources/downloads/servicespalte/Whitepaper_Softwaremodernisierung_Kienbaum.pdf, Download am 21.03.2016

[3] Software für Wissensmanagement - Vergleich von Wikis, Wissensdatenbanken, Groupware und Suchmaschinen, Pumacy Technologies AG, Berlin, 1. Auflage, Oktober 2014, www.pumacy.de, per E-Mail erhalten am 01.10.2015

[4] ITSM: IT-Service Management, https://de.wikipedia.org/wiki/IT-Service-Management, aufgerufen am 05.04.2016

Abbildung 1: Graphische Darstellung einer komplexen Systemlandschaft

Page 8: 18. Workshop Software-Reengineering und -Evolution · Software-Reengineering ... a tool that measures code metrics and also outputs results on maintainability. These quantitative

Modellbasierte Migration eines komplexen

Versicherungssystems von RPG nach Java

Matthias [email protected]

itemis AG

Bernhard [email protected]

itemis AG

Zusammenfassung

Große Legacy-Systeme auf aktuelle Technologien zumigrieren wird immer haufiger notwendig und ist ei-ne spannende und vielschichtige Aufgabe. In diesemPaper beschreiben wir die Migration eines komple-xen Versicherungssystems von RPG nach Java, mitSchwerpunkt auf UI-Replatforming und Testing.

1 Einleitung

Um im wirtschaftlichen Wettbewerb bestehen zukonnen, mussen sowohl Softwareprodukte als auchIn-House-Entwicklungen mit den sich andernden An-forderungen des Marktes (z.B. Kosten, Entwick-lungsgeschwindigkeit, Technologien) mithalten. Meistreicht es aus, die Softwaresysteme auf der beste-henden Plattform weiterzuentwickeln, aber was wennder Markt fur Plattformen, Programmiersprachenoder Hersteller, an die man sich durch Investiti-on zehn- oder hunderttausender Personentage gebun-den hat, immer weiter schrumpft und die Wettbe-werbsfahigkeit leidet?

In einem Kundenprojekt fur einen großen Anbie-ter von Versicherungssoftware migrierten wir den Le-bensversicherungsteil des Systems von RPG auf Java(JSF, Spring, JPA) mit einem modellbasierten An-satz. Damit transformierten wir 7 Millionen ZeilenLegacy-Code in 3 Millionen Zeilen Java-Code und et-wa 700.000 Zeilen Modellcode. Der Modellcode ist dieBasis fur die Erzeugung beispielsweise von JSF Fa-celets, SQL-Anweisungen, JPA-Mapping-Dateien undIntegrationstests.

Wir beschreiben den angewendeten modellbasier-ten Ansatz, die wichtigsten Teile des Projektes undunsere Erfahrungen.

2 Projektphasen

Das Projekt bestand aus einer Proof-of-Concept-Phase, in der die Machbarkeit des modellbasierten An-satzes verifiziert wurde, und einer Realisierungsphase,in der die Migration umgesetzt wurde.

2.1 Proof of Concept

Wahrend der Proof-of-Concept-Phase erhoben wir inenger Zusammenarbeit mit dem Kunden Anforderun-gen fur die Zielarchitektur, die Migration und den

Entwicklungsprozess. Darauf aufbauend entwarfen wirPrototypen des Zielsystems und domanenspezifischerSprachen (DSL). Mit diesen lassen sich die techni-schen und fachlichen Aspekte nicht nur des bestehen-den Systems, sondern auch kunftiger neu geschriebe-ner Anwendungen abbilden.

2.2 Realisierungsphase

Nachdem sichergestellt war, dass der gewahlte Ansatzerfolgversprechend ist, setzten wir die Migration durchfolgende Punkte um:

• Implementierung der Codegenerierung von RPGnach Java

• Finalisierung der Zielarchitektur• Entwicklung von DSLs und Generatoren fur ver-

schiedene Aspekte des Systems• Entwicklung eines Testverfahrens

3 Modellbasierte Softwaremigration

Abb.1 zeigt eine Ubersicht der modellbasierten Migra-tion. Teile des Systems werden in Modelle uberfuhrt,aus denen Code fur das neue System generiert wird.Hierzu zahlen beispielsweise DSLs fur Datenmodel-lierung, UI und ORM. Andere Systemteile wie dieBusinesslogik werden direkt in die Zielsprache kon-vertiert.

Abbildung 1: Modellbasierte Migration

Durch die unterschiedlichen Arten der Sourcecode-Erzeugung (generiert/konvertiert) war es besonderswichtig, eine funktionierende Continous-Integration-Umgebung aufzubauen.

Page 9: 18. Workshop Software-Reengineering und -Evolution · Software-Reengineering ... a tool that measures code metrics and also outputs results on maintainability. These quantitative

4 UI-Replatforming

Als Zieltechnologie fur die Benutzerschnittstelle wur-de JSF gewahlt. In der Original-Anwendung wurde sieuber Display Files (DSPF) beschrieben, die selbst eineurtumliche DSL fur IBM 5250-Textterminals darstel-len [2]. Aufgrund Anzahl und Große der Eingabeda-teien (uber 1 Mio. LoC) bestand die Herausforderungdarin, die 5250-Dialoge strukturtreu automatisiert inJSF Facelets zu uberfuhren, dabei aber Spielraum furVerbesserungen und Anpassungen an moderne Web-technologien zu lassen. Hierzu wurden DSLs fur eineMVVM-Architektur entwickelt:

• Business Object DSL: Geschaftsobjekte• Viewmodel DSL: UI-Zustand• Screen DSL: UI-Struktur

Mit diesen DSLs lassen sich neu entwickelte JSF-Anwendungen abbilden, aber durch Legacy-Support-Features vor allem in der Viewmodel DSL wird aucheine struktur- und verhaltenstreue Darstellung vonLegacy-Dialogen ermoglicht. Gleichzeitig kann mandurch die Separierung von Dialogstruktur, Dialogzu-stand und Geschaftsobjekten ebendiese unabhangigvoneinander anpassen und wiederverwenden.

Um das Verhalten der Dialoganwendungenmit Java-Enterprise-Mitteln nachzubilden, wardie Entwicklung einer umfangreichen Legacy-Laufzeitumgebung notwendig, die in Kombinationmit den Sprachmitteln der DSLs unter anderemfolgende Unterschiede uberbrucken musste:

• Synchrone vs. asynchrone Benutzerinteraktion• Zustand vs. statische Webseiten• Absolute vs. relative Positionierung• Dicktengleiche vs. proportionale Schrift• Funktionstasten und Schlusselzahlen vs. Hyper-links zur Navigation

Der UI-Zustand wurde in den generierten View-models gehalten, die sofern notig mit der Legacy-Laufzeitumgebung interagierten. Die Positionsinfor-mationen fur die Dialogelemente ließen sich gut in einGrid-Layout uberfuhren.

5 Testen

Mit der wichtigste Teil eines Migrationsprojektes istdas Testen. Durch eine ausreichende Testabdeckungmuss gewahrleistet werden, dass das migrierte Systemsich so verhalt wie das Altsystem. Da fur das Legacy-System keine fur eine Migration ausreichende Testab-deckung vorhanden war, musste eine Moglichkeit ge-funden werden, Tests im Altsystem zu erstellen unddiese in das neue System zu uberfuhren.

Die Altanwendung konnte mittels IBM WebFacingmit einem normalen Browser aufgerufen werden. Dadie migrierte Anwendung auf JSF basiert, entschlos-sen wir uns fur folgenden Testansatz:1. Manuelles Erstellen von Testfallen im Altsystem

durch Aufzeichnen2. Transformieren der aufgezeichneten Testfalle in

die ZielplatformDas verwendete Testwerkzeug zum Aufzeichnen

war Unified Functional Testing (UFT) [3] von HP.Das Format der Testfalle ermoglichte es uns, eine DSLdafur zu erstellen, so dass wir die aufgezeichnetenTestfalle in die Test DSL transformieren konnten. DieTest DSL (siehe Abb.2) ist eine werkzeugunabhangigeSprache zum Beschreiben von Tests im Web, mit be-sonderer Unterstutzung fur mittels Screen-DSL ge-schriebener JSF-Anwendungen.

Im nachsten Schritt transformierten wir die Testsin ausfuhrbare Selenium [1] Tests.

Dieses Verfahren funktioniert nur, wenn die IDsder HTML-Komponenten im Altsystem auf IDs imneuen System gemappt werden konnen. Dies konntenwir sicherstellen und eine ausreichende Testabdeckunggewahrleisten.

package extract_PAR00001

scenario extract_PAR00001 description "extract par00001"

step extract_PAR00001 description "extract par00001" {inputField(id = "userID").setText("testuser")inputField(id = "password").setSecureText("...")button(value = "Log in").click()browser.navigateTo("http://test.i2s.pt/myportal/...")button(tag = "INPUT").click()...assertEquals("CHECK", "1", outputField(id="l1...").getText())

}

Abbildung 2: Test DSL

6 Zusammenfassung

Das Projekt hat bestatigt, dass der modellbasierteMigrationsansatz geeignet ist um ein Legacy-Systemin ein neues System mit moderner Architektur, ak-tueller Programmiersprache und state-of-the-art UI-Technologien zu uberfuhren. Die Zukunftsfahigkeitdes Ergebnisses ist sichergestellt, da auch die Ent-wicklung neuer, mit den migrierten Programmen in-tegrierbarer Anwendungen nach modernen Ansatzenwie Continuous Testing und Continuous Integrationermoglicht wurde.

Literatur

[1] Selenium - Web Browser Automation. http://www.seleniumhq.org/. Accessed: 2016-04-24.

[2] System i: Application Display Programming. Ver-sion 6 Release 1. IBM. 2008.

[3] Testautomatisierung, Unified Functional Testing,UFT — Hewlett Packard Enterprise Deutsch-land. http://www8.hp.com/de/de/software-solutions/unified-functional-automated-

testing/. Accessed: 2016-04-24.

Page 10: 18. Workshop Software-Reengineering und -Evolution · Software-Reengineering ... a tool that measures code metrics and also outputs results on maintainability. These quantitative

A Software Analysis Framework for Automotive Embedded Software

Jochen Quante

Robert Bosch GmbH, Corporate ResearchStuttgart, Germany

[email protected]

Abstract

One major drawback of model based development isthat support by software analysis tools is usually notavailable. This is because each modeling languagewould require specially crafted tools. We present aframework that circumvents this problem by allowingintegrated analysis of di↵erent models from the auto-motive domain. It also exploits certain specialities ofthe domain to realize analyses that would otherwisenot have been possible.

1 Introduction

The trend towards model-based software developmentis quite intense in the automotive domain. Thisparadigm shift has a lot of advantages. For exam-ple, domain specific languages allow engineers to ex-press specifications in a language that is closer to theirdomain. However, it also brings a number of disad-vantages with it. In particular, the models are oftenproprietary, and there is only limited tool support todeal with them. There are hardly any tools for anal-ysis of such models. However, since these models arealso software and underly the same e↵ects as tradi-tional software artifacts, they become large and com-plex as more and more changes and extensions are per-formed [6]. Maintenance and understanding of thesemodels becomes more and more expensive and error-prone. Tools that support these tasks are needed - butit is uneconomic to come up with a new tool for everynew modeling language. In the following, we present aframework that is capable of analyzing di↵erent kindsof models from the automotive domain.

2 Automotive Models

The modeling language ASCET1 is designed for de-veloping embedded automotive software. It supportsblock diagrams, state charts, ESDL code, and C code.Block diagrams support a data flow oriented view onthe software and are quite close to what electrical en-gineers are used to work with. State charts can beused to specify program logics. ESDL is a languagethat is similar to Java and allows textual specification

1http://www.etas.com/en/products/ascet_software_

products.php

of rather control flow centric functions. C code canalso be embedded. All these artifacts are translatedto C code and integrated on the C code level. How-ever, for analyses, it is desirable to do that on themodel level, because this is the level that the devel-oper works with.

3 Architecture

The basic idea is to have an intermediate representa-tion that is capable of expressing certain aspects ofthe di↵erent input models in a uniform way – sim-ilar to what has already been done for integratingdi↵erent textual languages [5]. Since all these lan-guages end up in C code, an intermediate representa-tion on the basis of C code constructs can be used forprocedural aspects and interfaces. Additionally, onemust then ensure traceability – i. e., support naviga-tion from the intermediate representation back to theoriginal model. This representation is then adequatefor performing uniform analyses on all the di↵erentinput models – and also when they cross modelinglanguage borders. Additional languages can then beeasily added by implementing another frontend thattransforms the input model to the uniform intermedi-ate representation.

Figure 1: Framework architecture.

The central layers of the architecture as shown inFigure 1 build on the common intermediate represen-

Page 11: 18. Workshop Software-Reengineering und -Evolution · Software-Reengineering ... a tool that measures code metrics and also outputs results on maintainability. These quantitative

tation and provide advanced analyses. The advantagehere is that all the analyses are readily available forevery modeling language that will be added in thefuture. On top of all that, there are visualizations.Those are partly input model specific, like results thatare shown as an overlay in a block diagram, while oth-ers are independent visualizations of analysis results.

4 Basic Analyses and Interpreter

On this common basis, we perform a number of stan-dard analyses, like control and data flow analysisand alias analysis. The result is a structure that issimilar to the well-known program dependence graph(PDG) [2]. The PDG can directly be used for slicing.Several PDGs that also may originate from di↵erentmodels can be linked together (using inlining) to forma single large PDG that can then be used for furtheranalyses. Inlining is possible here since recursion isnot allowed in our software.

Our framework implements a relaxed version of ab-stract interpretation, compared to Cousot’s orig-inal idea [1]. For us, it is basically the interpreta-tion of a computer program using some abstractionfor values and calculations. It need not necessarilybe monotonic functions over ordered sets. Of course,this implies some di↵erences. For example, loop han-dling is di↵erent (there is not necessarily a fix point).Since we are mostly concerned with analyzing soft-ware that contains very few and limited loops [7], thisseems to be okay. On the other hand, we gain muchmore freedom and flexibility in the choice of the ab-straction, and we will see the benefit of that in theuse cases. The abstract interpreter performs abstractoperations on abstract values and uses an abstractstorage model. The freedom of choice of the abstrac-tion makes it very flexible. For example, the sameinterpreter is used for data flow analysis, partial eval-uation, interval arithmetics, and concolic testing [3] –by just using di↵erent abstractions.

5 Use Cases

The analysis framework is meanwhile used for a num-ber of standard use cases as well as for individual(scripted) analyses. The very first and obvious usecase is signal flow analysis, which corresponds toslicing of models. Slicing simply means to calculateall reachable nodes in the PDG from a given point.Given a starting point, e. g., in an ASCET block dia-gram, we just need to identify the corresponding nodein the PDG, calculate all reachable PDG nodes, andmap the result back to the original model. This high-lighting of signal flows turned out to be very helpfulespecially for calibration engineers, who have to findout which parameters (that they have to adjust) in-fluence which output values.

Another use case of the PDG is C code visu-

alization, which means transforming the code to ablock diagram representation. Since block diagrams

emphasize data flows, and data flows are explicitlyrepresented in the PDG, the transformation is largelystraight-forward. These two use cases are meanwhileavailable as a feature of ETAS’ eHandbook2.

A third use case is partial evaluation. Partialevaluation is the execution of program code with par-tially existing but incomplete assignments of variablesoccurring in a program with concrete values [4]. Byassigning values to only few of the variables, it is of-ten possible to largely reduce the model. This is doneby graying out parts of the model that are not exe-cuted in the given setting. This enables developersto understand a model much more quickly since theycan concentrate on certain scenarios without havingto manually interpret the program. It is also helpfulto be able to assign values to some variables and seethe e↵ect on a local result without having to define theentire environment. The latter is often quite complexand tedious in automotive software.

6 Conclusion

We have presented the basic ideas of our softwareanalysis framework. The main advantage of havinga specialized framework within Bosch are that it canexploit the specialities of automotive software, andthat it can deal with upcoming models. Meanwhile,it is available for everyone within Bosch (“Bosch inter-nal open source”). It is now used for many di↵erentpurposes like test case generation, multicore analyses,security analyses, and others.

References

[1] P. Cousot and R. Cousot. Abstract interpretation: aunified lattice model for static analysis of programs byconstruction or approximation of fixpoints. In Proc. of6th POPL, pages 238–252, 1977.

[2] J. Ferrante, K. J. Ottenstein, and J. D. Warren. Theprogram dependence graph and its use in optimization.ACM TOPLAS, 9(3):319–349, 1987.

[3] A. Ho↵mann, J. Quante, and M. Woehrle. Experiencereport: White box test case generation for automo-tive embedded software. In Workshop Proc. of ICST,TAIC PART, 2016.

[4] N. D. Jones, C. K. Gomard, and P. Sestoft. Par-tial Evaluation and Automatic Program Generation.Prentice Hall International, June 1993. Available fromhttp://www.itu.dk/people/sestoft/pebook/.

[5] R. Koschke, J.-F. Girard, and M. Wurthner. An inter-mediate representation for reverse engineering analy-ses. In Proc. of 5th WCRE, pages 241–250, 1998.

[6] M. M. Lehman and L. A. Belady. Program evolution:processes of software change. Academic Press Profes-sional, Inc., 1985.

[7] V. Schulte-Coerne, A. Thums, and J. Quante. Chal-lenges in reengineering automotive software. In Proc.of 13th CSMR, pages 315–316, 2009.

2http://www.etas.com/en/products/ehandbook-details.

php

Page 12: 18. Workshop Software-Reengineering und -Evolution · Software-Reengineering ... a tool that measures code metrics and also outputs results on maintainability. These quantitative

Analyzing Malware Putty using Function

Alignment in the Binary

Arne Wichmann, Sandro Schulze, Sibylle Schupp

Technische Universitat Hamburg-Harburg, Hamburg, Germany{arne.wichmann, sandro.schulze, schupp}@tuhh.de

This paper shows a representation of executablesand an alignment of functions in an executable tobe used when reverse engineering embedded systems.These techniques are not limited to this applica-tion and can also be used when studying code vari-ations, code clone-and-own scenarios, and when lo-cating hotspots for software quality inspections.

1 Techniques

The proposed applications make use of one alreadypresented technique, namely a scalable representationusing scatter plots of the static control flow of ex-ecutables [7] and an alignment technique based onHirschberg [4], which we have not presented so far.This alignment technique produces an alignment oftwo function sequences using a similarity measure onthe optionally normalized function lengths, which isbased on a previous work that employed more metricsto produce the alignment [6].

The key assumption behind these techniques is thatthe sequence of functions in an executable is mostlystable and invariant against changes in compiler ver-sion, optimisation level, source-code version, and theselected feature set. For example, in a classical C ex-ecutable the code from one source file is transformedinto an object file and several of these, together withsome libraries are linked into one executable, withoutany further changes to their order.

Scalable Representation The scatter plot repre-sentation [7] shows all static control flow referencesof the executable. The raw data used for this are allpairs of program counters and next possible programcounters. This covers the intraprocedural control flow,as well as calls to other functions.

The presentation can use several di↵erent scales onthe axes which allow it to be invariant to di↵erentkinds of distortions: It always plots pairs of sourceand target addresses of a control reference. A rawaddress representation hides the length of the func-tions in the executable. These function lengths canbe seen as the local steepness of a diagonal when thesources are grouped by function. Furthermore, thesource function can be mapped to their position in analignment. The target addresses are indexed to closegaps in the address space, which may occur due to seg-mentation. To make the targets comparable betweentwo executables, their indices are scaled and shifted.

Function Alignment The alignment techniqueuses Hirschberg’s Algorithm to calculate an alignmentof two sequences of functions. The functions are repre-sented either by their raw length or their scaled mean-free length. Individual functions are compared using1/ (1 + |la � lb|) as a similarity measure (1 for iden-tical length, approaching 0 for a growing di↵erence).This allows the alignment calculation to be free of anythreshold to determine identity of two functions. In-stead it maximizes the sum of similarities.

There are several other function comparison algo-rithms available, most notable are BinDi↵ [2], whichcompares the control-flow graphs of individual func-tions and the works of Stojanovic [5] and Berta [1],which calculate complex metrics on functions andthen use information retrieval techniques.

2 Applications

Our techniques allow for a fast visual overview of bothsingle executables and pairs of aligned executables.The structures in the visual overview can be inter-preted by a human inspector and help to identify mod-ules and libraries (coupling in and between modules),and highlight functions and modules with high fan-in(vertical line) or fan-out (horizontal line).

Reverse Engineering Black-Box EmbeddedSystems The techniques were originally developedin a reverse engineering scenario, where one or moreexecutables from otherwise undocumented embeddedsystems are analyzed, to answer high level questionsabout the system. Such a question can for examplebe: What happened in the system to trigger the fault-condition 63? Often there is more than one executableof the system available, because the software was sam-pled from several systems with di↵erent versions.

The plot representation can be used for a first orien-tation in the executable, to identify so-called hotspots,such as printf, and, thus, make the disassembled codemuch more readable. Additionally, some of the pro-gram’s modularization can already be reconstructedfrom the representation (see [7]). In the reverse-engineering scenario, the alignment technique usefulwhen a second executable make the variability explicitor the first has become obsolete and the e↵ort of re-verse engineering the first needs to be preserved.

Clone-and-Own Analysis for Binaries In a sce-nario where code gets cloned and changed in a di↵er-

Page 13: 18. Workshop Software-Reengineering und -Evolution · Software-Reengineering ... a tool that measures code metrics and also outputs results on maintainability. These quantitative

ent (potentially hidden) repository and just a binarygets published, the techniques can be used to showthe changes made to the binary.

A manual inspection of the aligned representationsallows an identification of similar executables both forlicense enforcement (e.g., GPL) and change inspection(analysis of modifications).

Comparing Change Logs and Binaries In ascenario where an outside contractor delivers closedsource binaries and provides information about thechanges made, the alignment techniques can be em-ployed to quickly identify parts of the binary wherethe changes were made.

For most updates, the build process and generalsetup can be assumed as stable, which implies that thetwo executables will be very similar and all changesto the functions will be due to feature additions orbugfixes. In the alignment the function sequence willshow insertions or deletions where features are addedor removed, and the similarities of aligned functionpairs will reflect the bugfixes.

Locating Software Quality Hotspots The lastscenario is the location of hotspots to be analyzed forsoftware quality inspection, based on the representa-tion. It allows one to easily identify frequently usedfunctions and check their quality properties. Addi-tionally it is possible to identify functions that dis-tribute the control flow over large parts of the exe-cutable. Of course, one still has to check manuallywhether such a distribution is actually legitimate (de-bug or shell interfaces) or represents a poor design.

3 Example: Malware Putty

In 2015 a malicious clone of the popular ssh clientPutty was discovered [3]. The inspections showed thatthe main modification was the addition of a functionthat is called during the authentication and leaks thecredentials used. The malicious executable was com-piled using a newer version of Visual C++.

Figure 1 shows the application of the alignmentand representation of the malicious version (left) andversion 0.63 (right) of Putty. The alignment was cal-culated on the scaled function lengths. This allowsthe alignment to be invariant to the changes in thetoolchain. The color of the plot points signifies thesimilarity of function pairs (black is 0, lightblue is 1).The changeset is shown using blue marker lines thatmark functions not present in the opposite executable.

The alignment shows a visually very similar se-quence of functions (diagonals), with high similaritiesbetween the functions. There are several insertionsand deletions marked in the alignment, which suggeststhat the clone is not based on version 0.63 directly.The last part of the diagonal represents the C library,which shows huge di↵erences due to the changed com-piler versions. The malicious function is one of thefunctions added in the MalPutty executable.

MalPutty.exe putty063.exe

●●● ●●●●●●●●●●●● ●●● ● ●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●● ●●● ●●●● ●●●●● ● ●●●●●●●●●●●●●●● ●●● ●●●●● ●● ●●●● ●●● ●●●●●●●●●●●●● ●● ●●●●●● ●●●●●●●●●●●● ●●●● ●●●●●●●●●●●●● ●●●●●●●●●● ●●●●●●●●●● ●● ● ●●●● ●●●●●●●●● ●●●●●●●●●●●● ●● ●●●●●●●●● ●●●● ●●●●●●●●●●●●●●●●●●●● ●●●●●● ●●●●●●● ●●●● ●●●●●● ●●● ●●●●●●● ●●●●●●●●●●●●●●●●●●●●● ●●●●● ●● ●●●●●●●● ●●●●●●●●● ●● ●●●●●●●●●●●●●●●●●●●●●● ●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●● ●●●●●●●●●● ●●● ●●●●●●●●●● ●●●● ●●●●●● ●● ● ●●●●●● ●●●●●● ●●●●●● ●●● ●●●●●●● ●●●● ●● ●●●●● ●●●● ●●●●●●●●●●●●●●● ●●●●●●● ●●●● ●● ●●● ●●● ●●●● ●●●●●● ●●●●● ● ●●● ● ●●●●●●●●●●●●●●●●●●●●●●●●● ●●●● ●● ●●●●●●●●●●●●●●●●●●●●●●●●●● ● ●●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●● ●●●● ●●●●●● ●●●●●● ●●●●●●●●●●●●●●●● ●●●● ●●●●●●●●●●●●●●● ●●● ●●●●●●●●●●●●●●●●●●●● ●● ●● ●● ●● ●● ●●● ●●●●●●●●●● ● ●●●● ●●●●●●● ●● ●● ●●●●●●●●●●●●●● ●●●●● ● ●● ●●●●●●●●●●●●●●●● ●●●● ● ●● ●● ●●●●●●●●●●●●●●●●●● ●●●●●● ● ●●●●●●●●●●●●●●●●●●● ●● ●●●●●●●●●●●●● ●●●●●● ●●●●●●●●●●●●●●●● ●●● ●●● ●●●●●● ●●●●●●●●●●● ●●● ●●●● ●●●● ●●●●●●●●●●●●●●● ●●● ●● ●● ●●●●● ●●●●●●●●●●●●●●●●●●●●● ●●● ●●●● ●● ● ●● ●● ●●●●●●●●●●●●●●●●● ● ●●● ● ●●●● ●● ●● ●●●●●●●●●●●●●●●●●●●●●●● ●● ●●●● ●●● ●●● ●●●●●●●●●●●●●●●● ●●● ●●●●● ●● ●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●● ●●● ●●● ●●●● ●●● ●● ●● ●●●● ●●●● ●● ●●●●● ●●●●● ●●● ● ●● ●●●●● ●●●●●●●●●●●●●●●●●●●●●●●● ●●● ●●● ●●●● ●● ●● ●●● ●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●● ●● ●● ●●●●● ●●●●● ●●● ●●● ● ●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●● ●●●● ●●● ●●● ●● ●●● ●●● ●●●●●●●●● ●● ●● ●● ●● ●●●●●●●●●●●●●●●●●●●● ●●● ●● ●●● ●● ● ●● ●● ●● ●● ●●● ●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●● ●● ● ●● ●● ●●● ●●● ● ●●●● ●●●●●● ●●●●●●●● ●● ●●●● ●●●●●● ●●●●● ●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●● ●●●●●●●●●●●●●● ●● ●●●●●●●●●●●●● ●●●●●●● ●●●●●●●●●●●●●●●● ●●●● ●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●● ●●●●●● ●●●●●●●● ●●●●●●●●●●●●●●● ●●● ●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●● ●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●● ●●●●●●●● ●● ●●●●● ●●●●●●●● ●●●●●●●●● ●●●●●●●●●●● ●●●●●●●● ●●●●●●●●●●●●●●●●●●●●● ●●●●●●●●●●● ●●●●●● ●●●●●●●● ●●●●●●●● ●●●●●●●● ●●●●●●●● ●●●●●●● ●●●●●●●● ●●●●● ●●●●●●●●●●● ●●●●●●●●●●●● ●●●●●●●●●●●● ●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●● ●●●●●●●●●●●●●●●● ●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●● ●●●●●●●●●●● ●●●●●●●●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ● ●●●● ●●●●●●●●●●●●●●●● ●●● ● ●●●●● ●●●●●● ●● ●●● ●●●●●●●●●●●●●●●●●●●●●●●● ●●●● ●● ●●● ●● ●●●●●● ●● ●●● ●●●●●●●●●● ● ●●●●● ●●●● ●● ●●●●●●●●●●●●●●●●●●●●●●●●●●● ● ●● ●●●● ●●● ●●●●●●● ●● ●●●●●●●●●●●●●●●●●●●● ●●● ●●●●●● ●●●● ● ●●●●●●●●●●●●●●●●● ●● ●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ● ●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●● ●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●●●●● ●●●●●●●●●●●● ●●●●●● ●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●●●●●●● ●●● ●●●●●●●●●● ● ●● ●● ●●●●●●●● ●●●●● ●●●●● ●●●●●●●●●● ●●●●●●●●●●●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●● ●●●●● ●●● ●●●●●●●●●●●●●● ●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●● ●●●●●●●●●●●●●●●●●●●●●●● ●●● ●● ●●●●●●●● ●●● ●●● ●●●●●●●●●● ●●●● ●●●●●●●●●●● ● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●● ●●●●●●●●●●●● ●●●● ●● ●●●● ●●●●●●●●●●●● ●●●● ●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●● ●● ●●●●● ●●●● ●●● ●●●●●● ● ●● ●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●● ●● ●●●●●● ●●●●●●● ●●●● ●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●● ●●●● ●●● ●●●●●●●●●●●●●●●●●● ●●●●●●●●●●●● ●●●●●●●● ●●●●● ●● ●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●●●●●● ●●●●●●●●● ●●●●●●● ●●●●●●●●●● ●●● ●●●●● ●●●●●●●●●●●●●●●●●●●●●●●● ●●● ●●●●●●●●●●●●●●●●●●●●●●●●● ●● ●●● ● ●● ●● ●●● ●● ●●● ●● ●●●●● ●●● ● ●●●●●●●● ●●●●●●●●●●●●● ●●●● ●●●●●●●●●●●●●●●●●●●●●●●● ●● ●●● ● ●●●●●● ●●●●●●● ●●●●●●●●●●●●●●●●●●●● ●●●●● ●●● ● ●●●●●●●●●● ●●●● ●●●●●●●●●● ●● ●●●●●●●●● ●● ●●●●●●●● ●●●●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●●● ●●●●● ● ●● ●● ●●● ●● ●●●●●●●●●●●●●●●●●●●●●●● ●●●● ●●● ●●● ●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●● ●●●● ●● ●●● ●●●●●●● ●●●●●●●●●●●●●●●● ●●● ●●● ●●● ● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●● ● ● ●●●●●●●● ●●● ●●●●● ● ●●● ●● ●● ●●●● ●●● ●●● ● ●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●● ● ●●●●●●● ●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●● ●●●●● ●●●●●● ●●●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●●●● ● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●● ●●● ●●● ●●●●●●●●●●●●●●● ●● ●●●●● ●●● ●● ●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●● ●●● ●● ●●●●●●●●●● ●●● ● ●●●●●●● ●●●●● ●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●● ●●●● ●●●●●● ●●● ●●●●●● ●● ●● ●●●●●●● ●●● ●●●● ●● ●● ●●●●●●●●●●● ●●●●●●●●●●●●● ●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●● ●●●● ●●●●●●●●●●●●●●● ●● ●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●●●●●●●●●●●● ●●●●●●● ●●●●●● ●●●●●●●●● ●● ●●●● ●●●●●●●●● ●●●●●●●●●●●●●●●● ●●●●●●●● ●● ●●●●●●●●●●●●●●●●●● ●● ● ●● ●●●●●●●●●● ●●● ●●●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●● ●●●●●●●● ●●●●●●●●●●●●●●● ●●●●●●●●●● ●●●●●●●●●●● ●●●●●●●●●●●●●● ●●●●●●●● ●●●●● ●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●● ●● ●●●●● ● ●●●● ●●● ●●●●●●●●●●●● ●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●● ●●●●●● ● ●●●●● ●●● ● ●● ●●●●●● ●●● ● ●●●●●●●●●●●●●●●●●●●●● ●● ●●●● ●●●●●●●●●●●●●●●●●●●●●●● ●●●● ●●●●●●●● ●●● ●●●●●●●●●●●●●● ●●●●●●●●●●●● ●●●●●●● ●●● ●●●●● ●●● ●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ● ●●●●●● ●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●● ●●● ● ●●●● ●●●● ●●●●●● ●●● ●●●●● ●●●●●● ●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ● ●●● ●● ●● ●● ●● ●●● ●●●● ●●●● ● ●●● ●●●●●●● ● ●● ● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●● ●●●● ●●●●●●●●●●●● ● ●●● ● ●●●●● ●●●●●●●●●●●●●● ●●● ● ●●●●●●●●●●●●●●● ● ●● ●●●●●● ●●●● ●● ●●●●●●●●●●●●●●●●●●●●●●●●●● ● ●● ●●● ●●● ●●●● ●●●●●● ●●●●●●●●●●●●●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●● ●●●●●●●● ●●●●●●●●●● ●● ●● ●● ●●●●● ●●●●●●● ●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●● ●● ●●●●●●● ●● ●●●● ●●●●●● ●● ●● ●● ● ●●● ●●● ●●●● ●●● ● ●●● ●●●●●●●●●●●●●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●● ● ●●●●●●●●●●●●●●●●●●●●●● ●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ● ●● ●●●●●● ●● ●●●●●●● ●●● ●●●●●●● ●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●● ●●●●● ●●● ●● ●●●●●● ●●●●● ●●●●●●●●●● ●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●● ● ● ●●●●● ● ●●●●●●● ●● ●●●●● ●● ●●●●●●●●●●●●●●●●●● ●●● ●●● ●●● ●●●● ●●● ●● ●●●●●●●●●●●●●● ●●● ● ●●●●●●●●●●● ●●● ●●● ●● ●●●●●●● ●●●●●● ●●●●●●●●●●● ●● ●● ●●● ●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●● ●●● ●● ●●●●● ●●●● ●● ● ●● ●●●●●●●●●●●● ●●●●●● ●● ●●●● ●●●●● ●●● ●●●● ● ●●●●●●●● ●●●●● ● ●●● ●●● ●●●● ●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●● ●● ●● ●●● ● ●● ●●● ●●●● ●●●● ●●● ●●●●●● ●●●●● ●● ●●●●●●●●● ●●●●●●●●●●●●●● ●●●●●● ●●● ●●● ●●●● ● ●●●●● ●●●●● ●●●●●●●●●● ●● ●●●● ●●●●●●● ●●● ●●●●●●●●●● ●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●● ●●●●●●●● ●● ●●● ●● ●●●●● ●● ●●●● ●●●● ●●● ●● ●●●●● ●●● ●●●●●● ●●●● ●●●● ●●●●●● ●●●● ●●● ●●●●● ●●●●● ●●●●●●●●●●●● ●● ●●●●●●●●●● ●● ● ●●●● ●●●●●● ●●● ●● ●● ● ●●●●● ●●●●● ●●●●●●●● ● ●●● ● ●●● ● ●● ●●● ●●●● ●● ●●● ● ●●●●●●●●●●●●●● ● ●● ●●●● ●●●●●●●●●●●●● ●●●●● ●●●●●●●●●●●●●●●●●●● ●●●●●● ● ●● ●●●●●●● ●● ●●●●●●●●●●● ●● ●●●●●●●●●●● ●● ●●● ●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ● ●●●●●●●●● ●●●●● ●●●●● ●●●●●●●● ●● ●●●● ●●●●● ●●●●●●●●●●●●● ●●●● ●● ●●●●●● ●● ●●●●●● ●●●●●●●●●●● ● ●●●● ●●●●●●●●●●●●●●●●●●●●●● ●●●●●●●●●● ●●●● ●●●●●●●●●●● ● ● ●●●●● ●●●●●●●●●●●●●●●●● ●●● ●●●●●●●●●●●●●●●●● ●●●●● ●●●●●●●●●●● ● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●●● ●●●●●● ●●●●●●●●●●●●●● ●●● ●● ●●●●● ●●● ●●●●●●●●●●● ●●●●●●●●●●●● ●●●●●●●●●●● ●●●●●●●●●●●●●●●●●●● ●●●●●●●●●● ●●●●●●●●●●●●●●●●●●●● ●●● ● ●●●●●●●●●●●●●●●● ●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●● ●●●● ●●● ●●●● ●●● ● ●●● ●●●●●● ●●● ●●●●●●●●●●●●●●●●●● ●●●●●● ●●●● ●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●● ●●●● ●●●● ●●●●●● ●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●● ●●● ● ●●●●●● ●●●● ●● ●●● ●●●● ●●●●●● ● ●●●●● ●●● ● ●●● ●● ●●●● ●●● ●●●●●●●●●●●●●●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●● ●● ●●●●● ●● ●●● ●● ●● ● ●●●● ●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ● ●●●●●● ●●●●● ● ●●●●● ● ●●●●●●●●● ●●●●●●● ● ●●● ●●●●●●● ●●●●●●●● ● ●●●●● ●●●● ● ●●●●●●●●●●● ●●● ●●● ●●●● ●●●●●●●●●●●●●●● ●●●●●●●●●●●● ●●●● ●●●●●●●●●●● ●● ●●●●● ●●●●●● ●●● ● ●●●●●● ●● ●● ●●●●● ●●●● ●● ● ●●●●●●●●● ● ●● ●●●●●● ●●● ●●●● ●●●●● ●●●●●● ● ● ●● ●● ●●●● ●● ●●●●● ●● ● ●●●●●●●●●● ●●●●●●●●● ●●●●●●● ●●● ●●● ●●●●●● ●●●● ●●●●● ●● ●●●● ● ●● ●●●●● ● ●●●● ● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●● ●●●●● ●●●●●●●●●● ●●● ●●●●● ●●●●●●●● ●●●●● ●●●●●●● ●●●●●●● ● ●●●●●●●●●●●●● ● ●●●●●●● ●●● ●●●●●●●●● ●●●●●●●● ●●●●●●●●●●●●●● ●● ●●●● ●● ●●●●●● ●●● ● ●●● ●●●● ●●●●● ● ●● ●●●●●●●● ●●●● ●●●●● ●●●● ●●●●●●●●●●●●●●●● ●●●●●●●● ●●●●●●●● ●●●●●●● ●●●●● ●●● ●●●●●● ●●●●●●●●● ●●● ●● ●●● ●●● ●●●●●●●●●●●● ●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ● ● ●●● ●●●● ●●●● ●● ●●● ● ●●●●●●●●●●●●●●●●● ● ● ●●●●● ● ●● ●●●● ●●●●● ●●●●●● ● ●● ●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●● ●● ●●● ● ●● ●●●● ●●●●● ●●● ●● ●●●● ●●●●●● ●● ●●●●●●●●●●●●●●●●●●●●●● ●●●●●●● ●●●● ●●● ● ●●●●●● ●●●●●●●●●●●●●●●●●●●●●●● ●●●● ●●● ●● ●●● ●● ●● ●● ● ●●●●●●●● ●●● ●●● ● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●●●●● ●●●●●●●●●●●●●● ●●●●● ●●●●●●●●●●●●●●●● ● ●●●●●●●●●●●●●●●●●●● ●●● ●● ●● ●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●● ●●●●●●● ●●●●●●●●●●●●●●● ●● ●●●●● ● ●●● ●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●● ●●●●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●● ●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●●●●●●● ●●●●● ●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●●●●●●●●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●●●●●●● ●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ● ●●●●●● ●●●●●●●● ●● ●●● ●●●●●●●●●●●●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●● ●●●●●●●●●●● ●●●● ●●●● ●● ●●●●● ●●●●●●● ●●●●●●●●●●●●●●●●●● ●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●●●●●●●● ●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●● ●● ●● ●●●●●●●●●●●●●●●●●●●●●● ● ●●● ●●●● ●●●●●●●●●●●● ● ●●● ● ●●●● ●●●●●●●●●●●●●●●●●●●● ● ●● ●●●●●●● ●●●● ●● ●●● ●●●●● ●● ●●● ●●●●● ●●●● ●●●●●●● ●●●●●●● ●●●●●●● ●●●●●●●●●●●● ●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ● ●●●● ●●●●●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●● ●●●● ●●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●● ●●● ●● ●●●●● ●●●●●●●●●●●●●●●●●● ●●● ●●●● ●●●●●●●●● ●● ●●●●●●●●●●● ●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●●●●●●●●●●●●●●●● ●●● ●●● ●● ●● ●●●●●●●● ●●●●●●●●●●●●●●●●● ●● ●●● ●●●●●●●●●●●●●●●●●●●●●● ●●●● ●● ●●● ●● ●● ●●●●●●●●●●● ●●●●●● ●●● ●●●●●●●●●●●●● ●● ●●●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●● ●●● ●●●●● ●●● ●●●●●●●●● ●●●●●● ●●●●●●●●●●● ●●●●●●●●●●●●●● ●●●●●●●●●●●●●● ●●●●●●●●●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●● ●●●●● ● ●● ● ●● ●● ●●● ●●● ●●●● ●● ●●●● ●●●●●●●●●●●●●●●●●●●●● ●●●●● ●●●● ●● ●●●●●●●●●●●●●●●●● ●●● ●● ●● ●●●●●●●●●●●●●●●●●●●●● ●●●● ●●●● ● ●● ●● ●●●●●●●●●●● ●●●●●●●●●●●●●●●● ● ●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●● ●●●●● ●●●●●●●●●●●●●●●●● ●●●●● ●●●●●●●●● ●●●●●●●● ●●● ●●●●●●● ●●●●●●● ●●● ●●●● ●●●●●●● ●●●● ●●●●● ●●●●●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●●● ●●●●●●●●●●●●●●● ●●●● ●●●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●● ●●● ●●●●●●●●●●●●●●● ●●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●● ●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●● ●●●●●●●●●●● ●●●●●●●●● ●● ●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●● ●●●●●●●●● ●●●●●●●●●● ●●●● ● ●●● ●●●●● ●●●●●●●● ●● ●●●●●●●●●●●●●●●● ●●● ●●● ● ●● ●●● ●●●●● ●●●●● ●●●●●●●●●●●●●●●● ●●●● ●●●●●●●●●●●●●●●●●●●●●●● ● ●● ●●● ●●●●● ●● ●●●●●●●●●●●●● ●● ●●● ●●● ●●● ●● ●●●●●●●●●●●●●●●● ●●● ●●●●●●●●●● ●●●● ●●● ●●●●●●●● ● ●● ●●●●●●●●●●●●●●●●●●● ● ●●●● ●●●●●●●●●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ● ●● ●●●●●● ● ●●● ● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●● ● ●●●●● ●●●●●●●●●●●●●●●●●●●● ●●●●● ● ● ●●● ●●●●●● ●●●●●● ●●●●●●●●●●●●●● ●●●●●●●●●●●●●●● ●● ● ●●● ●●● ●●●●●●●●●●●● ● ●● ●●●●●●●●●●●●●● ●●●●●●●●●●●●●● ●●●●●●●●●●●●●●● ●● ●●●● ●●● ●●● ●●●●●●● ●● ●●● ●●●●●●●●● ●●●● ●●●●●●●●●●●●● ●●●●●●●●●●●●●●●●●●●● ●●●●●●●●●●●●●●● ●●●●●●●●●●●● ●●●●●●●●●●●●●●● ●●●●●●●●●●●●●●●●●● ●●●●●●●●●●●●●●●●●●●● ●●●●●●●●●●●●●●●● ●●●●●●● ●●● ●●●●● ●●● ●●●●●●● ●● ●●●●●●●●●●●●● ● ●●●●●●●●●●●●●● ●●●●●●●●●●●●●●●●●●● ●●●●●●●●●●●●●●●● ●●●●●● ●●● ●●●●●●●●●●●●●● ●●●●●●●●●●●●●●● ●●●●●●●● ●●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●●●●●●●●●●●●●●● ●●●●●● ●● ●●●●●●●●●●●●●●● ●●●●●●●●●●●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●●●●●●●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●●●●●●● ●● ●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●● ●●●●●●●●●●●●●●● ●●●●● ●●●●●●●●● ●●●●●●●●● ●●●●●●●●●● ●●● ● ●●●●●●●●●● ●●●● ●●●●●●●●●● ●● ●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●● ●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●● ●●●●●● ●●●● ●● ●● ●●●●● ● ●● ●●●●●●●●●●● ●●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●● ●●●●●●●●●●● ●●●●●●●●●●●●●●●●●● ●●● ●●● ●●●●●●●●●● ●●●●●●●●●●●●●●●●● ● ●●●● ●●●●●●●●●●●●●●●●●●●●●● ●●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●●●● ●●●●●●●●●●● ●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●●●●●●●●●●●●●● ●●● ●●●●● ●●●●●●●● ●●●● ●●●●●●●●●●●●●●● ●●●●● ●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●●●●●●●●●● ●●● ●● ● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ● ●●●●●●●●●● ●●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●●●●●● ●●●●●● ●●●●●●●●●●●●●●●●●●●●● ●●●●●● ●●●●●● ●●●●●●●● ●● ●●●●●●●●● ●●●●●●●● ●●●●●●● ●●●●●●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●● ●●● ●●●●●●●●●●●● ●● ●●●●● ●●●●●●●●●●●●●●●●●● ●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●●●●●●●●●●● ●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●●● ●●●●●●●●●●●●●●●●● ●● ●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●●●●● ●●● ● ●●● ●●●●●● ●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●●●● ●●●●●● ●●●●●●●●●●●● ●● ●●●●●●●●●●●●●●●●●● ●●●●●●●●●●●●●●●●●●●● ●●●●●●● ●●●●●●●●●● ●● ●●●●●●●●●● ●●●●●●●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●● ●●●● ●●●●●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●● ●●●● ●● ●●●●●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●● ●●● ●●●●● ●●●●●● ●●●●● ●●●●●●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●●● ● ●●●● ●●●● ●●●●●● ●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●● ●● ●●●● ●●●●●●● ●●● ●● ● ●●●● ●● ●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●● ●●●●●● ●●●● ●●●● ●●●●●●●● ●●●●●● ●● ●●●●●● ● ●●● ●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●● ●●●● ●● ●●●● ●●●● ●●● ●● ●● ●● ●●● ● ●●●●● ●● ●●● ●●● ●● ●●● ●●●●● ●●●● ●●● ●●●● ●●●● ●●●●● ●● ●●● ●●● ● ●●●● ●● ●●●● ●●●●● ●●● ●● ●●● ● ●●●●●● ●● ●●●●●● ●● ●●● ●● ●●●●●● ●●●●●●● ●●● ●●● ●● ●●●● ●●●● ● ●●●●● ●● ●●● ●●● ●● ●●● ●●●● ●● ●●●● ●● ●●● ●●●● ●● ●● ●●● ●●●●● ●● ●●●●●● ●● ●●● ●●●●● ●●●●●● ●● ● ●● ●●● ●●● ●●●● ● ●●●●●● ●● ●●●● ●● ●● ●●●●● ●● ●●●●●●●● ● ●●● ●● ●●●●●● ●●●●● ●● ●●● ●● ●●● ●●●● ●●● ●●●● ●●●●●● ●●●● ●● ●●●●●●● ●●●● ●● ●●● ● ●●● ●●●●● ●●●● ●●●● ●●● ●●● ●●● ●●● ●●●● ●● ●●● ● ●●●● ●● ●●●●●●● ●●● ●●●●●●●●●●●● ●●●● ●●●●● ●●●●●●● ●●● ●●● ●●●● ●●●●● ●●●● ●●●● ●●● ●● ●●● ●●● ●●● ●● ●●● ● ●● ●●● ● ●●●●● ●● ●●●●● ●● ●● ●●●●●● ●●●●● ● ●● ●●●● ●●●●●●● ●●●● ● ●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●● ●● ●●●●●●●● ●●● ●●●●●●●●●●●●●● ●● ● ●●●●●●●●●●●●●●●●●● ●●●●●●●●●●● ●●●●●●●●●●●●●●● ● ●●●●●●● ● ●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●●●●●● ●●●●●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●●●●●● ●● ●● ●●●●● ●●●●●●●●●●●●●● ●● ●●●●●●● ●●● ●●●●●● ●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●● ●● ●●● ●●● ●●●●●● ●●●● ●● ●●●●●●●●●●●●●●●●●●●●● ●● ●●●●●●●●● ●● ●● ●● ●● ●●●●●●●●● ●●●● ●●●●● ●●●●●●● ●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●● ●●● ●● ● ●●●● ●●● ● ●●●● ● ●●● ●●●●● ●●●●●●●●● ●●●●●●●●●●●●●●●●● ●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●● ●●●●●● ●●●●● ●●●●●●●● ● ● ●●●●●●●●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●● ●●● ●●●●●●●●●●●●●●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●● ●●●●●●●● ●●●●●●●● ●●●●●●●●●●●●●●●●●●●● ●●●● ●●● ●● ●● ●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●●●●● ●●●●●●● ●●●●●●● ●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●●●●●●●●●●● ●●●●●●● ●●●●●● ●●● ●●● ●●● ●●●●●● ●●●●●●●● ●●●●●●●●●●● ●●●●●●● ●●●●●●●● ●●●●●● ●●● ●●●●●●●●●●●●●●●●●● ●●●● ●●●● ●●● ●●● ●● ●●●●●● ●●●●●●●● ●●●●●●●●●●●●●●●●●● ●● ●●● ●●●●● ●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ● ●●● ●● ●●● ●●●● ●●●●● ●● ●●●●●●●●●● ● ●● ●●●●●●●● ●●● ● ●●●●●●●●●●●● ●● ●●● ●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●● ●●●● ●● ●● ●● ●● ●●●●●●●●● ●●●●●● ●●●●● ●●●●●● ●● ●●●●● ●●●●● ●●●●●●●●● ●●● ●●● ●●●●●●●●● ●●●●● ●●●●●●●●●●●●●● ●●●●●●●●●●●●●●●● ●●●●●●●●●●●●●●●●●●●●●● ●●●●●●● ●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●● ●●●● ●●●●●● ●● ●●●●●●● ●●● ●●●●●●●●● ● ●●● ●●●●●●●●●●●●●●● ●● ●●●● ●●●● ●●●●●●●●●●●●●● ●●●●● ●●●●● ●●●●●● ●●●●●●●●●●●● ●●●●●●●●●●●●●● ●●●●● ● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●● ●●●● ●●● ●●● ●● ●●●● ●●● ●● ● ●● ●●● ● ●● ●●● ●●●●● ●●● ●●●●● ● ●● ● ●●●● ●● ●●●●● ● ●●●● ●● ●●●●●●● ●● ●●● ●●●●●● ●●●●● ●●● ●●● ●● ● ● ●● ●● ●● ●●●●●●●●●●●●●●● ●● ●●●●● ●● ●● ●● ●●●● ●●●●● ●●●●●●●●●●●●● ● ●●●● ●● ●●●●●● ● ●● ●●●● ● ●●● ●● ● ●● ● ● ●●●●●●●●●●●●●●●● ●●●●●●●●●●●●● ●●●●●●●●●●●●●●●● ●●●●●●●●●●●●●● ●● ●●● ●●●●●●●●●●●●●●●●●● ● ●● ●●● ●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●● ●● ●●●●●●●●●●●●●● ●● ●● ●●● ●●●●●●●●●●● ●●●●●●● ●● ●● ● ●●●● ● ●●●●● ●●●●●● ●●●●●●●●●●●●●●●●●● ● ● ●● ●●●●●● ●● ●●●● ● ●●●●●●●●●●●●●●●●●●● ●●● ●● ●●●●●●●●●●●●● ●●● ●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●● ●● ●●● ●●● ●●●●●● ●● ●●●●●●● ●● ●●● ●● ●● ●● ●●●●● ●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●● ●●●●●●●●●●●●●● ●●● ● ●●●●●●●●●● ●●●●●●●●●●●● ●●●●●●●●●● ●● ●●●●●●●●●●●● ●●● ●● ●●●●● ●●● ●●●● ●●●●●●●● ●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●● ●● ●●● ●●●●●●●● ●●● ●● ●● ●●● ●●●● ●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●●●● ●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●● ●● ●●●●●●●● ●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●● ●●●●●● ●●● ●●●●●●●●●●●●● ●● ●● ●● ●● ●●●●●●●●● ● ●● ●● ●● ●●●●●● ●● ●●● ●●●●●●● ●●●●●●●●●●●● ●●●● ●●●●●●●●●●●●● ●●● ●● ●●●●●●●●●●●● ●●● ●●●● ●● ●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●● ●● ●●●● ●●●●●●● ●●● ●● ●●● ●● ●●●●●●●●●●●●●●●●● ●●●●●●●●● ●●●●●●●●●●●●●● ●●●●● ●●●● ●●●●●●●●●●●●●● ●●●●●●●●●●●●●●●●●●●●●● ● ●●●●●●● ●● ●●●●●●●● ● ●●●●● ●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●● ●● ●●●●●●●●●●●●●●●●●●●●● ●●● ●●● ●●●●●●●●● ●●●●●●● ●● ●●●●●●●● ● ●●●●●● ●●● ●●●●●●● ●●●●● ●● ●●● ●●●●●●●●● ●● ●●●● ●●●●●●●●●●●● ●● ●●● ●●●●●●●● ●● ●●●● ●● ●●●●●●●●● ●●● ●● ● ●●● ●●●●●●● ●● ●●● ●● ●● ●●●●●●●●●●●●●●●●●●●●● ●● ●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ● ●● ●● ●●● ●● ●●●●●●●●●●●●●●●● ●●●●● ●●●●● ●●●●●●●●●●●●●●● ● ●● ●●●●●● ●●●●●●● ●●● ●●●●●● ● ●●●●● ● ●●●●● ● ●●●●●●●●●● ●● ●●●●●● ●●●●●●●●●●●● ●● ●●●●●●●●●●●●● ● ● ●●● ●● ●●● ●●●●● ●● ●●●●●●●●●●●●●●●●●●●●●●●● ● ●● ●●●●● ●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●●●●●●● ●●●●●●●●●●●●● ●●●●●●●● ●●● ●●●●●●●●●●●●●●●●●●●● ●●●●●●●●●● ●●●●●●●●●●●●●●●●●●●● ●●●●●●●●●●●●●●●● ●●●●●●●●●●●●●●●●●● ● ●●●●●●●●●●●●●●●●●●●● ●●●●●●●●● ●●● ●● ●●●●●●●●●● ●● ●●●●●●●●●● ●●●●●●● ●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●● ●●● ●●● ● ●●●●●●●● ●●● ●● ●●● ● ●●● ●●●● ●● ●● ●●●●● ●●● ●●● ●●●●● ● ● ●●●●●● ●●● ●●●●●●●●● ●●● ●●●●● ●●●●●●● ●●●●●●●● ●●●●● ●●●● ●● ● ●●●●●● ●●●● ●● ●●●●●● ●●● ●● ●●●● ● ●●● ●● ●●●● ●● ● ●●● ●●●● ●● ●●● ●●● ●● ●● ●● ●● ●● ●● ●●● ● ●●● ● ●●●● ● ●● ●● ●●●●● ●● ●●● ● ●● ●●● ●● ●● ●● ●● ●●● ●●●●● ● ●● ●●● ●●●● ● ●●● ●●● ● ●●● ●●● ●●●● ●●● ● ●●●● ●●● ● ●● ●●●●● ●● ●●●●●●●● ●● ●●●● ●●●●●● ●●● ●● ●●●● ●●●●●●●●●●●●●●● ●●●●● ●●●● ●●● ●●●● ●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ● ●●● ●●●●●● ●● ●●● ● ●●●●● ●●● ●●●● ●● ●●●●● ● ●●● ●● ●●●● ● ●●●● ●●● ●●● ●●●●●●●●●●● ●● ●● ●● ● ●●●●●● ●● ●● ●●● ●●● ●●●●● ●●● ● ●● ● ●●●●●● ●● ●● ●●●● ●●● ● ●●● ● ●●●● ●●● ●● ●●●● ●●●● ●●●●●●●● ● ●●● ●● ●● ●●●● ● ●●● ● ●●● ●●●●●●●●●●● ● ●●●●●●● ●●●●● ●●●●●●●●●●●●●●●● ●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●●●●●●●●●●●● ●● ●●● ●●●●●●●●●●●●●●●●●●● ●● ●● ● ●● ● ●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●● ●●●●●●●●●● ●●●●●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●● ●● ●●● ●●● ●● ●●●● ●● ●●●●●●●●●●● ● ●● ●●●●●●●●● ● ●●● ●●●●●● ●● ●●● ●● ●● ●●●●●●●●●●●●●●●●● ●●● ●●●●●●● ● ●●● ●●●●●● ●●●●●●●●●●●●●●●●●●● ●●●● ● ●● ●●●●●●●●●●●●●●●●●●●●●●●●●●● ●● ●●● ●● ●●●● ●●● ● ●●● ●●●●●●●●●●●●●●●● ●● ● ●●● ●●●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●● ●● ●●●●● ●●●●●● ● ●● ●●● ●●● ●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●● ●●● ●●●●●●●●●●●●●●●●● ●●●●●●●●●●●●● ●●●●●●●●●●●●●● ●●●●●●●●●●●●●●● ●●●●● ●●●● ●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●●●●● ● ●●●●●●● ●● ●● ●●●●●●●●●●●●●●●●●●● ●● ●● ●● ● ● ●● ●●●●●● ●●●● ●●●●●●●●●●●●●●● ●●●●●●●●●●●●●●●●●●●● ●●●●● ●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●●●●●●●● ●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●● ●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ● ●●●●●●●●● ●●●●●●● ●●●●●●●●● ●●●●●● ●●●●●●●●●●●●●●● ● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●● ● ●● ●●●●●●●●●● ●●●●●●●●●●●●●● ●●●●●●●●●●●●●●●●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●●●●●● ●●●● ●●● ●●●●●●●●●●●●● ●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●● ●●● ●● ●●●●●● ●●●●● ●●●●●● ●● ●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●●● ●● ●●●●●● ●●●●●●●●●●●●●●● ●●●●● ●●● ●●●●●●●●● ●●●● ●●●●●●●●●●● ●●●●●●●● ● ●●●●●●●●●●●●●●● ●●●● ●● ●●●●●●●● ● ●●● ●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ● ●● ●●●●● ●● ●●●●●● ●●●●●●●●●●●● ●●● ● ●●●● ●●●●●●●● ●●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●● ●● ●● ●●●● ●● ●●●● ●●●●●●●●●●●●●●●●●●● ●●● ●●●●●●●●●●●●●●●●●● ●● ●●●● ●● ●●●● ●● ●●●●●●●●●●●●●●●●●●●●●●●●● ●● ●●●●● ●●●●●●●●● ● ●● ●●●●●●●●●● ●●●●●●●●●●●●●● ●●●● ●●●●●●●●●●●●●●●●●●●●● ●●●●●●●●●●●● ●● ●● ●● ●● ●●●● ●●●●● ●●● ●● ●●●●●● ●●●● ●●●●●●● ●●● ●●●●● ●●●●●●●●●●● ● ● ●●●● ●●● ●● ●●●● ●●●●●●●●●● ● ●● ●●●●●●●●●● ●● ●● ●● ●●●●● ● ●● ●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●● ●●● ● ●●●●● ●●● ●●● ●●●●●●●●●●●●●●●● ●●●● ●●●●● ● ●●● ●●●● ●●●●●● ●●●●● ●● ●●●●●● ●● ●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ● ●●● ● ●●●●●●●●●●● ●●●●● ●●● ●●●●●●●●●●●●● ●● ●● ●●●●●●●●●●●●● ●● ●● ●●●●●●●●● ●●●●●●●●●●●●● ●● ●●●●●●●● ●● ●●●●● ●● ●●●●●●●● ●● ●●● ●● ●●●●●●● ● ●●●●●● ●●●● ●● ●●●●●●●●●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●● ●●●●● ●●●●● ●●●●●●●●●● ●●●●●●● ●●●●●●●●●●●●●●●●● ●● ●● ●●●●●●●●●●●●● ●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●●●●● ●●●●●●●●● ●●● ●● ●●●●●●●●●● ●●●●●●●●●● ●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●● ●●●●●● ●● ●●●●●●●●●●●●●●●●●●● ●●●●●●●●●●●●●●● ●●●●●●●●● ●● ●●● ●●●●●●●●●●● ● ●●● ●●●● ●●●●●● ● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●●●●● ●●●●● ● ●●●●● ●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●● ●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●● ●● ●●●●●●●●●●●●●●●●● ●●●●●●●●●● ●●●●●●●●●●●●●●●●●●●●●● ●●●●●● ●●● ●● ●●●●●●●●●●●●●●●●●● ●●●●●●●●●● ●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●●●●●● ●●●●●●●●●●●●●●● ●●●●●●●●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●● ●● ●●● ●●●●● ●●●●●●●● ● ●●●●●● ●●●●●●● ●●●● ● ●●●●●● ● ●●●●● ●● ●●●●●●● ●●●●●●●●●●●●● ●●● ● ●● ● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●● ●●●● ● ●●● ●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●● ●●●● ●●●●●●●●●●●●●●●●● ●●●●●● ●●● ●●● ●●●●●●●●●●● ●●●●●● ●●● ●●●●●●●● ● ●● ● ●● ● ●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●● ●●●●●●●●● ●●●●●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●● ●●●●●●● ●●●●●●●●●●●●●● ●● ●● ●● ● ●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●● ●●●●●●● ●● ●●●●●●●●●●●●●●● ●●● ●●● ●●● ●●●● ●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●● ●●●●●●●●●●●●●● ●● ●● ●●●●●●● ●●●●●●●●●●● ●●● ●●●● ●●●●●● ●●●●●● ●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●●●●●●●●●● ●●●●●●●●●●●●●●●●● ●●●●●●●●●●●●●●●● ●●●●●●●●●●●●●●●● ●●●●●●●●●●●●●●●●● ●● ●●●●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●● ●●● ● ●●●●●●●●●● ●● ●● ● ●●●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●●●●●●●●●●●● ●●● ●●●●●●●●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●● ●●●●●● ●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●● ●● ● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●●●●● ●●● ● ●● ●●●● ●●●●●●●●●●●●●●●●●●●● ●● ●●● ●● ●●●●●●●●●●●●●●●●●●●●●●● ●●●● ●●● ●● ●●●● ●● ●● ●●● ●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●● ●●● ●●●●●●●● ●●●●●● ●●●●●● ●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●●●●●●●●●●●●●●●● ●●●● ●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●● ●● ●●●● ●● ●● ●●●●●●●●●●●●●●●●●●●●●●●● ●● ●●●●●● ●● ●●●●●●●● ●● ●● ●●●●●●●●●●●●●●●● ●●● ●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●● ●● ●●●●●●●●●● ●●●●●● ●●●●●●●●●● ●● ●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●●●●●●●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●● ●●●●● ●●●●● ●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●● ●● ●● ●●●●●●●●●●●●●● ●● ●●●●●●●●●●●●●●●●●● ●●● ●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●●●●●●●●●● ●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●● ●●● ●● ●● ●● ●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●● ●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●●●●● ●●●●●● ●●●● ●●●●●●●●●● ●●●●●●●●●●●●●●●●●●●●●● ●●●●●●● ●●●●●●●●●● ●●●●●●● ●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●● ● ●●●●● ●●●●●●●●●●●●●●●●●●●● ●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●● ●● ●●●●●●●●● ●● ●● ●● ●●●●●●● ●●● ●●●●●●●● ●●●●●●●●●●●●●●●●● ●●●●●●● ●●●●●●●●●●●●●●●●●●●● ●●●●●●●●●●●●● ●●●●●●●●●●●●● ●●●●●●●●● ●● ●●●● ● ●● ●● ●●●● ●●●●●●●●●●●●●●●●●● ●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●●● ●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●● ●●● ● ●● ●●●●●●● ●● ●● ●● ●● ●●●●●●● ●●●● ●●●●●●● ●●●● ●●● ●●●● ●●●●●●●●●●●●●●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●● ●●●● ● ●●●●●●●●●●●●●●●●●●●●●●●● ●● ●●●●●●●● ●●● ● ●● ●●●●●●●●●●●●●●●● ●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●● ●●●●●●●●●●●●●●●● ●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ● ●● ●●●●● ●●●●●●● ●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●● ●● ●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●● ●● ●● ●● ●●●● ●● ●●●●●●● ●●●●●●●●●●●● ●● ● ●●●●●●●●● ●● ●●● ●● ●●●● ●●●●●●●● ●● ●●●● ●●●●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●● ●●●●●● ●●●●●●●●● ● ●●●●●●●●●●●●●●●●●● ●● ●●● ●● ●●●● ●● ●● ●●●●●●●●●●●●● ● ●●●●●●●●●●●●●●●●●●●●● ●● ●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●● ●●●● ●●●● ●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●● ●●●●●● ●●●●●● ●●●●●●●●●●●●● ●●●● ●●●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●●●● ●●●●●●●●●●●●●●●●● ●●●● ●●●●●●●●●●●●●●●● ● ●●●●●●●●●●●●●●●●●●●●● ●●● ●● ●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●●●●●●●●● ●●●●●●● ●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●● ●●●●●●● ●●●●●● ●●●●●●●●●●●●●●●●●●●● ●●● ● ●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●● ●● ●●●●●● ●●●●●●●●●●●●●●●● ●● ●●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●●● ●●●●●●●●●● ●●●●●●●●●●●●●● ●● ●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●● ●●● ●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●● ●●●●● ●●● ●●● ●● ●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●● ●●●●●● ●● ●●●●●●● ●●●●●●●●●● ●● ●●●●●●●● ●●●●●●●●●●●●● ●●● ●● ●● ● ●●●●●●●●●●●●●●●●●●●●● ●●● ●●●● ● ●●●●●●●● ●●●●●●●●●●●●●●●●●●●● ● ●●●● ●●● ●●● ●● ●● ● ●●●●●●●●●●● ●●●●●● ●●●●●●●●●●●●●●●●●●●● ●● ●●●●●●● ●● ●●●● ●●●●●●● ● ●●●●●●●●●●●●●●●●●●● ●●●●●● ●●●●●●● ●●● ●●●●●●●●● ●●●●●●●●●●●●●● ●●● ●●●●●●●●● ●●● ●●●●●●●●●●●●●●●●●●●●●●●●●● ●● ●●●●●● ●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ● ● ●●●●● ●●●● ●● ●●●●● ●●●●● ● ●●●●●●●● ●●●●●●●●●●●●●●● ●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●● ●●●●●● ●● ●●●●●●●●●●●● ●●● ●●●●● ●●●●● ●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●● ●●● ●●●●●●●●●● ●●●●●●●● ●●●●● ●●●●●●●●●●●●●●●●●●● ●●●● ●●●●●●● ●●●●●●●●●●●●●● ●●●●●●● ●● ●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●● ● ●●●●● ●●●●●● ● ●● ●●● ●● ●●●●●●●●● ●● ●●●●●● ●●●●●●●●●●●●●●● ●●●●●●●● ●●●●●● ●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●●● ●● ●●●●●●●●●● ●●●●●● ●●●●●●● ●●●●● ●●●●●●●●●●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●●●●●●●●●●●●●●● ●●●●● ●●●●●●●●●● ●●●●●●●●● ●●●●● ●●●●●●●●●●●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●● ●●● ●●●●●● ●●●●● ●●●●● ●● ●●●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●● ●● ●●●●●●●●●●● ●●●●●●●●●●● ●●●●●●●●●●●●● ●●●●●●●●●●●●●●●●● ●●●●●●●●●●● ●● ● ●●●●●●●●●●●●●●●●●●●●●● ●●●●●●● ●●●● ●●●● ●●●● ●●●●●●●●●●●●●● ●●● ●● ●●●●●● ●●●●● ●●●●●●●●● ●●● ●● ●●●●●●●●●●●●●●●●●● ●● ●● ●●● ●●●●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●●●●● ●● ●●●●●● ●●●●●●●●●●●●●●●●●●●● ●● ● ●● ●●●●●●●●●●●●●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●● ●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●●●● ●●● ●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●● ●●●●●●●●●●●●●●●● ● ●● ●●●●●● ●●●●●●●●●●● ●● ●●●●● ●●●●●●●●●●●●●●●● ●●●●●●● ●● ●●●●●●●●●●●●●●●●● ●●●●●●● ●●●●●●●●●●●●● ●● ●●●●●●●●●●●● ●●●● ●● ●●●● ● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●● ●●●● ●● ●●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●● ●● ●●●●●●●●●●●● ● ●●● ●●●● ●●●●●●●●●●●●●●●●● ●●●●● ●●●●●●● ● ●●●●● ●●●●● ●●●●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●● ●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●● ●●●●●●●●● ●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●●●●●● ●● ●●●●●●●●●●● ●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ● ●● ●●●● ●● ●●●●●●●●●●● ●●●●●● ●●●●●●●●●●●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●● ●●● ●●● ●●●●●●●●●●●●●●●●● ●●● ●●●● ●●●●●●● ●●●●●●●●● ●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●● ●●●●● ●●●●●●● ●●●● ●●●●●●●●●●●●●●●●●●●●●● ●●● ●● ●●●●● ●●●●●●●●●●●●●●●●●●● ●● ●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●● ●●● ●●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●●●●●●● ●● ●●● ●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●● ●●● ●●●●●● ●●●●●●●●●●●●●●●●●●●● ●●● ●●● ●●●●●●●●●●●● ●●●● ●● ●●●●●●●●●●●●●●●●●●●●●●●●●●● ●● ●● ●● ●●●●●●●●●●●●●●●●●●●●●● ●●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●●●●● ●●●●●●●●●●●●●●●●●●●● ●●●●● ●●●●●●●●●● ●●● ●● ●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●● ●●●●● ●●●●●●● ●●●● ●●●●●●●●● ●● ●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●●●● ●●●●●●●●●● ●●●●●●●●●●●●●●●●● ●●● ●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●● ●● ● ●●● ●●●● ● ●●●●●●●●●●● ●● ●●●● ●●●●●●●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●● ●●● ●●●●●● ●● ●● ●● ●●●●●●●●●●●●●●● ●●●●●● ●●● ●● ●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●● ●●●● ●●●●●●●●● ●●●●●●● ●●●● ●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●● ● ●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●● ●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●

●●●● ●●●●●●●●● ●● ●●● ●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●● ● ●● ●●●●●●●●●●●●● ●●● ● ●●●●●●●●●●●●●●● ● ●●●●●●●●●●● ● ●●●●●● ●●●●●●●●●●●●●●●●●● ●●●●●●●●●●●●●●●●●●● ●●●● ●●●●●●●●●●●●●●● ●●●●●●●●●●●●● ●● ●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●●●●●●●●●● ●●●● ●●●● ● ●●●●●●● ●●●● ● ●●●●●●●● ●● ●●●●●●●●●●●●●●●●●●●●●●●●● ● ●●●●● ●●●●● ●●●●●●●●●●●●●●●●●● ●●●●●●●●●●●●●●● ●●● ●●●●●●●●●●●● ●●●●●●●●●●●●●● ●●●●●●●●● ●●●●●●●●●●●●●●●●● ●●●●●● ●●●●●●●●●●●●●●●●●● ●● ●●●●●●●●●●●● ●● ●●●●●●●●●●●●●● ●● ●●●●●●●●● ●● ●●●●●●●●●● ● ●●●●●●●●●●● ●●●● ●●●●●●●●● ●●● ●● ●●●●●●●●●●● ●● ●● ●●●●●●●●●●● ●●● ●●●●●●●●● ● ●●● ●●●●●●●●●●●●●●●●●● ●●●● ●●● ●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●● ●●● ●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●● ●● ●●●● ●●● ●● ●●●●●●●●●●●●●●●●●●●●●●● ●●●●● ●● ●●●●●●●●●●●● ●●● ●●●●●●●●●●●●●●●●●●●●●● ●●●●● ●●●● ●● ● ●●●●●● ●●●●●●● ●●●● ●●●●●●● ●● ●● ●●●●●●●●●●●●●● ●●●●● ●●● ●●● ●●●●●●●●●●●●●●●●●●●● ●● ●●●●● ●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●● ●●● ● ●● ●●●●●●●●●●●●●●●●●●●●●● ●●● ●●● ●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●● ●● ●●●●●●●●●●●●●●●● ●●●●● ●●● ●●●● ●●●●●●●●●●●●●● ●●● ●●● ●●●● ●●●● ●●●●●●●●●●●●● ●●● ●●●●●● ●●● ● ●●●●●●●●●●●●●● ●● ●● ●●● ● ●●● ●●● ●● ●● ●●●●●●●●●● ●●● ●● ●● ●● ● ●● ●● ●●●●●●●●●●●●●●●●● ●●●●● ●●●● ●●● ● ●●● ●● ●●●●●●●●●● ●● ● ●● ●● ●● ●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●● ●● ●●●●●●● ●●●● ● ●●● ●●●●● ●●● ●●● ●●● ●●●● ●●●●● ● ●●● ●●●●●●●●●●●●●●●●●●● ●●● ● ●● ● ●●●●● ●● ● ●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●● ●● ●●●● ● ●●●● ●● ●●●●● ● ●● ●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●● ●● ●●●● ●●●●● ●●●●●● ●● ●● ●● ●●●●● ● ●● ● ●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●●● ●● ●● ● ●● ●● ●● ●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●● ●●● ●●●● ●●●● ●●●●● ●● ●●●● ●●●●● ●● ●● ●● ●●● ● ●●● ●●● ●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●●●●●●●● ●●●●●●●●●●●●●●●●●● ●●●● ●●● ●●●●● ●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●● ●● ●● ●●● ●●● ●●●●●●● ●● ●●●●●●●●●●● ●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●● ●●●● ● ●●●●●● ●● ●●●● ●● ●● ●●●●●●● ●●●●●●●●●●●●●●●● ● ●●●●●●●●● ●●●●●●●● ●●●●●●●●●●●●●●●●●●●●●● ●● ●●●●●●●●●●●●●●●● ●●●●●●●● ●●●●●●● ●●●●●●●● ●●●●●●● ●●●●●● ●●●●● ●●●●● ●●●●●●●●●●●●●●●●●●● ●●●●●● ●●●●●●●●●●● ●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●● ●●●●●● ●●●●● ●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●●●●●●●●●● ●●●●●●● ●●●●●●●●●●●●●●●●●●●●●● ●●●●●● ●●●●●●●●●● ●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ● ●●●●●●●● ●●●●●●●●●●● ●●●●● ●●●●● ●●●●● ●●● ●●● ●●●●●●●●●●●●●●●●●●●●●●●●● ●●● ●● ●●●● ●● ●● ●●●●●●● ●●●●●●●●●●●●●● ●● ●● ●●● ●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ● ●● ●●● ●● ●●●●● ●● ●● ●●●● ●●● ●●●●●●●●●●●●●●●●●● ●●●● ●● ●●● ●● ●● ●●●●●●●●●●●●●●●● ●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●●●● ●●●●●●●●●●●●●●●● ●●●●● ●●●● ●●●●●●●●●●●●●●●● ●● ● ●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●●●●●●●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●● ●●●●●●●●●●●●●●●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●●●●●●●●●●●●●●● ●●●●●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●● ●●●●●●●● ●●● ●●●●●●●●●●●● ●●● ●●● ●●●●●● ●●●●●●●● ●● ●●●●●●●●● ●●●●●●●●● ●●● ●● ● ●●●●●●●●●● ●●●● ●●● ●●●●●●●● ●●●●●● ●●●●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●●●●●●●●●●●●●●● ●●●●● ●●●●●● ●●● ●●●●●●●●●●●●●● ●●● ●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●● ●●●●●●●●●●●●●●●● ●●● ●●● ●●●●●●●●●●●●●●●●● ●●●●● ●●●●●●●●●●●●●●●●● ●● ●●●●●●●●●●●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●●●●●● ●● ● ●●●●●● ● ●● ●●●●●●●●●●●●●● ●● ●●●●●●●●●●●● ●● ●● ●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●● ●●●●●●● ● ●●● ●●●● ●● ●●●●●●●●●●● ●● ●●●● ●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●● ●● ●●● ●● ●● ● ●●● ●●●●●●●● ●●●●● ● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●● ● ●●●●●●● ●●● ●●●●●●● ● ●●●● ●● ●●●● ●●●●●●● ●●●●●●● ●●●●●●● ●●●● ●●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●● ●●● ●●●●●● ●● ●●● ●● ●●●●●●●●●●●●●●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●●● ●● ●●●●●●●●●●●●●●●●●●●●● ●● ●● ●●● ●●●● ●●● ● ●●● ● ●●●●● ●● ●●● ●●●●● ●●●●●●●●●●●●●● ●●● ●●●● ●●●● ●●●●●●●●●●●●●●●●● ● ●●●● ●●● ● ●● ● ●● ●●●●●● ●●●●●●●●●●●●●●●●●●●●●●● ● ●●●● ●●●●●●● ●●●●●●●● ● ●● ●●●●●● ●● ●● ●●●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●● ●●●●● ●●●●●● ●● ● ●● ● ●●● ●●●●● ●●●●●●●●●●●●●●●●●●●●● ●●●●●●●●● ●●● ●● ●● ●●● ●●●●●●●●●●●●●●●●●●●●●● ●●● ●●●●● ●● ●● ●● ●●● ●●●●●●●●●●●●●●● ●● ●● ●●● ●● ●●●●● ●●●●●●●●●●●●●●●●●● ●● ●●● ● ●●●●●●● ● ●●● ●●●● ●●●● ●● ●● ●●●● ●● ●● ●● ● ●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●● ●● ●● ●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●● ●●● ●●●●● ● ●● ●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●● ●●● ●●●●● ●●●●●●●●●●●●●●●● ●● ● ●●●●●● ●● ● ● ●●●●●●●●●●●●●● ● ●● ●●●●● ●● ●●●● ●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ● ●●●●●●●● ●●●●●●●●●●●● ●●●●● ●●●● ●●●● ●●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●● ● ● ●● ●●● ●●● ● ●● ●●● ●●●●●●● ●●● ●●●●● ●●●● ●● ●●●●●●●●●●●●●●● ●●●●●●●●●● ●● ●● ●● ●● ●●●● ●● ● ●●●●●●●●●●●●●●●●● ●● ●● ●● ●●●● ●● ●●●●● ●● ●●●●●● ●●●●●●●●●● ●●●●●●●●●●● ●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●● ●●●●● ●●●●●●●●●●● ●● ●●●●●●●●●●●●●●●● ●●●●●●●●●●●●●● ●● ●●●● ●●●●●●●●●●●●●● ●●●●●● ●●● ●●●● ●● ●●●●● ●●●●●●●●●●● ●●●●●●●●●●●●●●●●● ●●●●●●●●● ●● ●●●●●●●●● ●●●●●●●●●●●●●●● ●●● ●● ●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●● ●● ●●●● ●●●●●●●●●●●●●● ●●●●●●●●● ●●●●●● ●● ●●●●●●●●●● ●●●●●●●●●●●●●●●● ●●●●●●● ●●●●●●●● ●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●● ●●●● ●●●●● ●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●●●●●●●● ● ●●● ●● ●●● ●●● ●●●●●●●●●●●●●●●●●●●●●● ●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●● ●● ●●●● ●●●● ●●●● ●●●●●●●● ● ●●● ●●●●●●●●●●●●●●●●● ●●●●●●●●● ●●●●●●●●●●●●●●●●● ●●●●●●●●●●●●●●●●● ●●● ●●●●●●●●● ●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●● ●●●●●●●●●●●● ●●●●●●●●●● ●● ● ●● ●●●●●● ● ●●● ●●●●●●●●●●●●●●●●● ●●●● ●●●● ●●●●●●●●●●●●●●● ●●●●● ●●●●●●●●●●●●●● ● ●●●●●●●●●●● ●●● ● ●●●● ●●●●●●●● ● ●●●●●●●●●●●● ●●● ●● ●●●● ●●●●●●●●● ●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●● ●●●●● ●● ● ●●● ● ●●●● ●●●●● ● ●● ● ●●●●● ●●●●●● ●●● ● ●●●●●●●●●●●●●●●●● ●●●● ● ●●●●●●●●●●●●●●●● ● ●●● ●●● ● ●● ●●●●●●● ●●●●●●●●●●●●●●●●●●● ●●● ●● ●● ●●● ●●●●●●●●●●●●●● ●●●● ●●● ●●● ●●●●● ●●● ●● ●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●●●● ● ●●● ●● ●● ●● ●● ●●●●● ●●●●●● ●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●●●● ● ●●● ●●●● ●● ●●●●● ●●●●●● ●● ●● ●● ●● ●● ●●●●● ● ●● ●●● ●●●● ●●●●●●●●●●●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●● ●●●●●●●● ● ●●●●●●●●●●●●●●●●●●●●●● ●●● ● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ● ●●● ●● ●●●● ●●●●●●● ●●●●● ●●● ●●●●●●● ● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●● ●●●●● ●●●●●● ● ●●●●●●●●●●● ●●●●●●●● ●● ● ●● ●●●●●●●●●●●●●● ●●●● ●●● ● ●●● ●●● ●●●●● ● ●● ●●●● ●● ●● ●●●●●●●●●●●●●●●●●●● ●●● ●●●●● ● ●●●● ●●● ●●●●● ● ●●●●●●●●●●●●●● ● ●● ● ●●●●●●●●●●● ●●● ●● ●●●● ●●●●●●●●●● ●●●●●●●● ●●●●●●●●●●● ●● ●●●● ●● ●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●● ●● ●● ●● ●●●● ●●●●●●● ●●●●●●●● ●●●● ●●●● ●●●● ●●● ●●●●●●●●●●●●●●●●●●●● ●●● ●●●●●● ●●●●●●● ●●●●●● ●● ●●●●●● ●●●● ● ● ●●●● ●●●●●●●● ●●●● ●●●●●●●●●●● ●●● ●● ●●● ●●●●● ●● ●●●●● ●● ●●●●●● ●● ●● ● ●●● ●●●●●●●●●●●●●●●●● ● ●● ●●● ●●●● ●●●●●●●●●● ●● ●●●● ●●●●●●● ●●●● ●●●●●●●● ●● ●●●●●●●● ●● ● ●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ● ●●●●● ●●●●●●●●● ●●●● ●● ●●●●● ●●● ●●●●●●●● ●● ●●● ●●● ●●●●●●●● ●●●●●●●●●●● ●●●●●●●● ● ●●● ●●●● ●● ●●● ●●●●● ●●●● ● ●● ●●●●● ●●●●●●● ●●● ● ●● ●●●●●●●● ●● ●●● ●●● ●●● ●●●●●● ●●● ●● ●●●●●●●●●● ● ● ●● ● ●●● ●●● ●● ●●● ●●● ●● ●● ●● ●●●●●●●●●●●●●●●●●●●● ●●●● ●●●●●● ●●●●●●●●●●●● ● ●●●● ●● ●●●●●●●●●●●●●●●●●●●●●●● ●●● ●● ●● ● ●● ●●●●●●●● ●●● ●●●●●●●●● ●● ● ●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ● ●● ●●●●●●●●● ●●● ●●●●● ●●● ● ●●●●●● ●●● ●●●●●●●●●● ● ●●●● ●●●● ●●●●●●● ●●●●●●●●●●●●●●●● ●●● ● ●● ● ●●●●●●●●●●●●●●●●● ●●●●●●●● ● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●● ●●● ●●● ● ●●●●●●●●●●●●●●●●● ● ●●● ●●●●●●●●●●●●●●●● ●●●●●●● ●●●●●●●● ●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ● ● ●●●● ●●●● ●●●●●● ●●●●●●●●●●●●●●●●●● ●●●● ●● ●●●●●● ●●● ●●●●●●●●●●●● ● ●●●●●●●●●●●●● ●●●●●●●● ●●●●●●●●●●●●●●●●●●●●●● ●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●● ●● ●●●●●●●●●●●●●●●● ●●●● ● ●● ●●●● ●● ● ●●●●●●●●●●●●●●●● ●●●●● ●● ●●●●●●●●●●● ●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●● ●●●●● ●●●●●● ●● ●● ● ●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●● ●●● ●●●●●●●●● ● ●● ●●●●● ●● ●● ●● ●●●●●●●●●●●● ●● ●●●●● ●● ●●● ●●●● ●●● ●●●●●●●●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●● ● ● ●●●●● ●● ●●●●● ● ●● ●●●●● ●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●●● ●●●● ●● ●●● ●●●● ●●●● ●●●●● ●●●●●●●●● ●●●●●●● ● ●●●●●●●●● ● ●●●● ●● ●●●●●●●●●●● ●●●●● ●● ●●●●● ●●●● ●● ●●●●●●●● ●●● ●●●●●●● ●● ●●●● ● ●●●●●●●●● ●●●●● ● ● ●● ● ●●●●● ●●● ●●●●● ●●● ● ●● ● ●●●●●● ● ●●●●●●● ● ●● ●●● ●● ●●●●● ●●● ●●●●●● ●● ●● ●●●● ●●●● ●●●●● ●● ● ●● ●● ●●●● ●● ●●●● ●● ●●●●●●●●●● ●● ●● ●●●● ●●●● ●●●●●●● ●●●● ●●●● ●●●● ●●● ●●● ●●●●● ●●●●● ●●●● ● ●●●●● ●●●●● ● ●●● ●●●● ●● ●● ●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●● ●● ●●●● ● ● ●● ●● ●● ●●●●●●●● ●●● ●●●●●●●●●●● ●● ●●● ●●●●●● ●●●●●●●●● ●●●● ●●●●●●●●●●●●● ●●●● ●●● ●●●●●●●●●●●●● ●●●●●●● ●●●●●● ●● ●●●●●●●●●●●●●●●●●●●●● ●●●●●● ●●●●●●●● ●●●● ●●● ●● ●● ●● ●● ● ●●●●●●●●●●●● ●● ●●● ●●●● ●●●●●●●●●●●● ●●● ●●● ●● ●●●● ●●●● ●●●●●● ●●●● ●●●● ●●●●●●●●●● ●●●● ●●●●●●●●●●●●●●● ●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●● ●●●● ●● ●● ●● ●●●●● ●● ●●●●●●●●●●●●●● ●●●● ●● ● ●●●●●● ●●●●●● ●●●●●●●●● ●●●● ● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●● ● ●● ●● ●●●● ●●● ●● ●● ●●●● ●●●●●●● ● ●● ●●● ●●●●●●●●●●●●●●●●●●●●●●●● ●●●●● ●● ●● ●●●●●●● ●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●● ●● ●● ●● ●●● ●● ●●● ●● ●● ●●●● ●● ●●● ●● ● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●●●●●●●●●●●●●●●●● ●●●●●●●●●●●●●●●●●●● ●●●● ●●●●●●●●●●●●●●●●●●●●●● ●●● ●●● ●●●●●●●●●●●●●●●●● ●●●●●●●●●●●●●●●●●●● ●●●●●● ●● ●● ●●●●●●●●●●●●●●●●● ●●●●●●●●●●●●● ●●●●●●●●●●●● ●●●●●●●●●●●●● ●●●●●●●●●●●●●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●●●●●●●● ●● ●●● ● ●●●●● ●● ● ●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●● ●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●● ●●●●●●●● ●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●● ●● ●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●●●●●●●●●●●●●●●● ● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●● ●●●● ●●● ● ●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●● ●●● ●●●●●●●●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●● ●●●●●● ●●●● ●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●● ●●●● ●●●●●●●●●●● ● ●●●●●●●●●●● ● ●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●● ●●●● ●●●●●●●●●●●● ●●●●● ●●●●●●●● ● ●● ●●●● ●●●●●●●●●●●●● ●●●● ●●●●●●●●●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ● ●●●●●●● ●●●●●●●●● ●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●●●●●●● ●●●●●●●●●●●●●●●●●●● ●●●●●●●●●●●●●●●●● ●●●●●●●●●●●●●●● ●●●● ●● ●● ●●●●●●●●●●●●●●● ●●●●●●●●●●●●●●●●●●●●●● ●● ●● ●● ●● ●● ● ●●●●●●●●●●●●●●●●●● ●●● ●●● ●●● ●●●● ●● ●●●●●●●●●●● ●●● ●●●●●●● ●●●●●●● ●●●●●●● ●●●●●●●●●●●● ●●●●● ●●●●●●●●●●●●●●●●●●●●●●● ●●●● ●● ●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●● ●● ●●●●● ●●●●● ●●●●●●●●●●●●●●●●●●●●●● ●●● ●●● ●●● ●●●●●●●●●●●●●●●●●●●● ●●●●●●● ●● ●●●●●●●●●●●●● ●● ● ●●●●●●●●●●●●●●●●● ● ●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●● ●●●●●●●●●●●●●●●●●●●●●●● ● ●● ●●●●● ●● ●●●● ●●●●●●●●●●●●●●●● ●●●●● ● ●● ●●●●●●●●●●●●●●●●● ●● ● ●●●●●●●● ●●●●● ●●●●● ●●● ●●● ●● ●●●●●●●●●●●●●● ●●●●●●●●●●●● ●●●●●●●●●●●●●●●●●●●●● ●●●●●●●●●● ●●●●●●●●●● ●●●●●●●●●●●●● ●●●●●●●●●●●●● ●●●●●●●●●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●● ●● ●● ●●● ● ●● ●● ●● ● ●●● ●●● ●●●●●●●●●● ●●● ●● ●●● ●●●●●●●●●● ●● ●● ●●●●●●●●●●●●●●● ●● ●● ●●● ●●● ●●●●●●●●●●●●●●●●●● ●●●●●●●●●●●●●● ●● ●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●● ●●● ●●●●●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●●●●●●● ●●● ●●●● ●● ●●●●●●● ●●●● ●● ●●● ●●●● ●●● ●● ●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●● ●●●●●●●●● ●●● ●● ●●●●●●●●●●●●●●●●●●●●●●●●●●● ● ●●●●●●● ●● ●●●●●●●●●●●●●●●●●● ●● ●●● ●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●● ●●●●● ● ●●●●●●●●●●●● ●●●● ●●●●●●●●●●●●●●●●●●●●● ●●●●●●●●●●●● ●●●●●● ● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●● ●●●●●● ●●●●●●●●●●●● ●● ●●● ●●● ●●●●●●●● ● ●●●●●●●●●●●●●●●● ●●●●●●●●●●●●●●● ●●● ●●●● ● ●● ●● ●●●●●●●●● ●●●●●●●●●●● ● ●● ●●●●●●●●●●●●●●●●●● ●● ●● ● ●●● ● ●● ●● ●●●●●●●●●●● ●●●● ●● ●●● ●● ●●● ●●●●●●●●●●●●●●●● ●●●●●●● ●●●●● ●● ●●● ●●●● ●●●●●●●●●●● ●● ●●● ●●●●●●●●●●●●●●●●● ●●● ●●● ●●●●●●●●●●●●●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●● ●●●●●●●●●●●●●●●●●● ●●● ●● ●● ●● ●● ●●● ●●●●●●●●●●●●●●●●●●●●●●●●●● ●● ●●● ●●● ●●● ●●●● ●●●●●●●●●●●●●●●●●●●● ●● ●● ●● ●● ● ●●● ●● ●●●●●●● ●●●●●●●●●●●●●●●●● ●●●●●●●●●●●●●●●●●● ●● ●●●●● ●●●● ●●●● ●●●●●●●●●●● ●●● ●●● ●●●●●●●●●●●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●●●● ●●●●●● ●●●●●● ●●● ●●●●●●●●●●● ●●●●●●●●●●●●●●●●●●●● ●●● ●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●●● ●●●●●●●●●● ●●●●●● ●●● ●●●●●●●●●●●● ●●●●●●●●●●●●●●●●●●● ●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●●●●● ●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●● ●●●●●●●●●●●● ●●●●●●●●●●●●●●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●●●●●●●●●●● ●●●●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●●●●●● ●●●●●●●● ●● ●● ●●●●●● ●●●● ●●● ● ●●●● ●●●●●●●●●● ● ●●● ●●●●●●●● ●●●●●●●●●●●●● ●● ● ●●● ●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●●●●●●●● ●●●●●●●●●●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●● ●●● ●● ●● ●● ●●●● ●● ●● ●● ●● ●●●●●●●●●●●● ●●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●● ●●●●●●●●●●●●●●●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●●●●●●●●●● ●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●● ● ●●●●●●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●● ●●●●● ●●● ● ●●●●●●●●● ●●●●●●●●●●●●● ●● ●●● ●●● ●●●●●●●●●●●●●●●●●● ●● ●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●● ●●●●●●●●●● ●●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●●●●●●●●●●●●●● ●●●●●●●●●●●●● ●●●● ●●●●●●●●●●●●● ●● ●● ●●●● ●●●●●●●●●●●●●●●● ●●●●●●●●●●●●●●●●●●● ●●●● ●● ●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●● ●●●●●●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●● ●●●●●●●●●●●●● ●●●● ●●●●●●●●●●●●●●●●●●●●●●●●● ● ●●●●●●●●●●●●●●●●●● ●●●●●●●●●●●●●●●● ●●●●●●●●● ●●●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●● ●●● ●●●●●●● ●●●●●●●●●●●●●● ●●●●● ●●● ●● ●●●●●●● ●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●●● ●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●●●● ●●●●●●●●●●●●●●●●●● ●●● ●● ●●●●●●●●●●●●●●●●●●●● ●●● ●●●●●●●● ●● ●● ●● ● ●●●●●●● ● ●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●● ●●●●●●● ●●●●●●●●●●●●●● ●●●●● ●●●●●●●●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●● ●●●● ●●●●●●●●● ●●● ●●●●●●● ●●●●●●●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●● ●●●●● ●● ● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●● ●●● ●●●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●● ●●●●●●●●●●●●●●●● ●●● ●●●●●● ●●●●●●●●●● ●●●●●● ●●●●●●●●●●●●●●●●●●●●●●● ●● ●●●● ●●●●● ●●● ●●●●●●●●● ● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●● ●● ●●●●● ●●●●●● ● ●● ●●● ●● ●● ●● ● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●● ●●● ●●●● ●●●●● ●●● ●●●●●● ●●●●●●●●●● ●●●● ●● ● ●●●● ●●●●● ●●●●● ●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●● ● ●●●●●●●●●● ●●● ●●● ●●● ●●● ●●● ●● ●●●● ●●● ●●●● ●●●●●●●● ●● ●●●● ●●●● ●●●●● ●● ●●●● ●●● ●● ●● ●●● ●●● ●● ●●● ●●●●●●● ●● ●●●●● ●●●●●● ●●●●● ●●● ● ●●●● ●●●● ●●● ● ●● ● ●● ● ●●● ●●●● ●● ●● ●● ●● ●●●● ●● ●●● ● ● ●●● ●●● ●●● ●●● ●● ●● ●●● ●●● ●●● ●●● ●● ●●● ● ●● ●● ●●●● ●●●●●●●● ●●● ●●●●● ● ●●●●●●●● ●●● ●●●●● ●●● ●● ●● ●●● ●●● ● ●● ●● ●●● ●●●●● ● ●● ● ●● ●● ●●●●● ●●● ●●● ●●●●●●● ●●● ●●● ●●●● ●● ● ●●●●●● ●●●● ●●●●● ● ● ●●● ●●●● ●●● ●●●● ●●● ●●● ●●●● ●● ●●●●● ● ●● ●●● ●●●●●● ●● ●● ●● ●●● ●●● ● ●●● ●●● ● ●● ●●●●●●●● ●●●● ●●● ●●●● ●●●● ●● ●●●● ●●●●● ●● ●●● ●● ● ●● ●● ●● ●● ●●●●●●●● ● ●●●●●●● ●● ●●● ●●●● ●●● ●●●● ● ● ●●●● ●● ●● ●●●●● ●● ● ●●● ●●● ●● ●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●●●●● ●●●●●● ●●●●●● ●●●● ●● ●●●●●●● ●●● ●● ●●●●●● ● ●●●●●●●●●●● ● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●● ●●●●●●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●●●●● ●●● ●●●● ●●●●●●●●●●●●● ●●●●●● ●●●●●●● ●●● ●●●●● ●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●●●●● ●●●●●●● ●●●●● ●●●●●●●●●● ●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●● ● ●●● ●●● ●●●●●●●● ●●● ●● ●● ●●● ●● ●●●●● ●●●● ●● ●●●●●●●● ●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●● ●●● ●● ● ●●● ●●● ●●●● ●●●●●●● ●●●●●●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●●●● ●●● ●●●●●●●●●●●●●●●●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●● ●● ●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●● ● ●●●●●●●●● ● ●●●●●●●●●●●● ●●●● ●●●●●●●●●●●●●●● ●●●●●●●● ●●●● ●●●● ●●● ●● ●● ●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●● ●●●● ●●●●● ●●●●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●● ●●● ●●●●●●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●●●●●●●●●●●●●●●●● ● ●●●●●●●●●●●●●●●●●● ●● ●●●●●●●●● ● ●●●●●●● ●●●● ●●●●●● ●●●● ●●●●●● ●●●● ●●●●●●●●●●●● ●●●● ●●●●●●●●●●●●● ●●●● ●●●●●●●●●●●●●●●● ●●●●● ●●●●●●●● ●●●● ●●●●●●●●●●●●●●● ●●●●● ●●●●●●●●●●●● ● ●●●●●●●● ●●●● ●●●●●●●●●●●●●●●●●●● ●●●●● ●● ●●●●●●●●● ● ●●●●●●●●●● ●● ●●●●●●●●● ●●●●●●●●● ●●●●● ●●● ●●●●●●●●●●●●●●●●●●●●●●● ●● ●●● ●●●●●● ●● ●●●●●●●●●●●●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●● ●● ●● ●●● ● ●● ●●● ●●●●●●●●●● ●● ●●●● ●●●●●●●●●●● ●●●● ●●●●●●●●●● ●●● ●●●●●●●●●●●●●●● ●●●●●●● ●●● ●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●● ●● ●●●●● ●●● ●● ●●●● ●●● ●●●● ●●● ●●●● ●● ●●●●●●●● ●●●●●●●●●●●●●●●● ●●● ●● ●●●●●●● ● ●●●●●●●●●● ●●●●●●●● ●●● ●●●●● ●●●●●●● ●●● ●●●●●●● ●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●● ●●●●● ●● ● ●●●●● ●●●●● ●● ●●●●●● ●●●●●●●●●●● ●●●●● ●●●●●●●●●●●●●●●● ●●●● ●●● ●● ● ●●● ●●●●●●●●●● ●●●●● ●●● ●●●● ●●●● ●●●●●●●●●● ●●●● ●●●●●●●●●● ●● ●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ● ●● ●● ●● ●●● ●●●● ● ●● ●●●● ●● ● ●●● ●●●●●●● ●●●●● ●●● ●● ●●● ●●● ●●●●●● ●●● ●● ●●● ●● ● ●● ●●●● ●● ●●●●●● ●● ●● ●●● ●●● ●● ●●●●● ●● ● ●● ● ●●● ●● ●●●● ● ●●●●● ● ●● ● ●●●● ●● ●●●● ●●● ●● ●●●●●●●●●●●●●●●●●●●●●●● ●● ●●● ●● ● ●●● ●●● ●● ●●●●● ●● ●● ●●●● ●● ●● ●●●●●●●●●●●●●●●●●● ●●●●●●●●●●●●● ●●●●●●●●●●●●●●●●● ●●●●●●●●●●●●●●●●● ●● ●●●●●●●● ●●●●●●●●●●●●● ●●● ●● ●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●● ●●● ●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●● ●●●● ●● ●● ● ●●● ●●●●● ●●●● ●●●●●●●●●●●●●●● ●● ●●●●● ●●●● ●● ●●●● ● ●●●●●●●●●●●●●●●●●●● ●● ●● ●●●●●●●●●●●●●●●●●●●● ● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●● ●●●●●● ● ●●●● ●● ●● ●●●●●●●●● ● ●●●● ●● ●●●●●● ●●●●● ●● ●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ● ●●●●● ●●●●●●●●● ●●● ●●●●●●●●●●●●● ●●●●●●●●●●● ●●● ●●●●●●●● ●●●●●●●●●●●● ●●● ●●● ●●●● ●● ●● ●●● ●●●●●●●● ●● ●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●● ●●●●●●●●●●●● ●●●● ●● ●●●●● ●●●●● ●●● ●●● ●●●●●● ●●● ●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●●● ●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●● ●●● ●● ●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●● ●●● ●●●● ● ●●●●●●●●●●●●● ●●● ●● ● ●● ●●●●● ●● ●●● ●● ●●●●●●● ●● ●●● ●●●●●●● ●●●●●●●●●●●● ●●● ●●● ●●●●●●●●●●●● ●●●●● ●●●●●●●●●●●●●●● ●●● ●●● ●● ●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●● ●●●● ●●●●●●● ●●● ●●● ●●● ●●●●●●●●●●●●●●●●●●● ●●●●●●●●●●●●● ● ●●●●●●● ●● ●● ●●● ●●●●● ●●●●●●● ●●●●●●●●●●●●●●●● ●●● ●●●●●●●●●●●● ●● ●●●● ●● ●● ●● ●●●●●● ● ●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ● ●● ●●●●●●●●●●●●●●●●●● ●● ●● ●●●●● ●●● ●● ●● ●●●●●●●● ●●● ●●●●●●● ●● ●● ●●● ●●● ● ●●●●●●●● ●● ●●●● ●● ●● ●●●●●●●● ●● ●●●● ●●●●●●●●●●● ●●●●●●● ●● ●●●● ●● ●●●● ●● ●●●●●●● ●● ●● ●●●● ● ●● ●●●●● ●● ●● ● ●● ●● ●●●●●●●●●●●●● ●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●● ●●●●●●●●● ●● ●●●●● ●●●●●●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●● ●● ●●●● ●●● ●●●●●●● ●●● ●●●●●● ●● ● ● ●●● ●● ● ●●● ●●●●●●●●●●●●● ●●●● ●● ●●● ●● ●●●●●●●●●●●●●● ●● ●●●●●●●●●●●●● ●● ●● ● ●●● ●●● ● ●● ● ●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●● ●● ●● ●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●●●●●● ●●●●●● ●● ●●● ● ● ●●●●●●● ●●●●●●●●●●●●●●●● ●●●●● ●●●●●● ●●●● ●●●● ●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●●●●●●●● ● ●● ●● ●● ●● ●●●● ●●●●●●●●●●●●●●●●●● ●●● ●●●●●●● ●● ●●●●●●●●●●●●●● ●●●●●●●●●●●●●●●● ●●● ●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●● ●●●●● ●●● ●●● ●● ●● ●● ● ●●● ●●● ● ● ●●●●●●●●● ●●● ● ●● ●●●● ●● ●●● ●● ●●●●●● ●●●● ●●●● ●● ●● ●●●● ●● ●●● ●● ● ●●● ●●● ●●●● ●●●●● ●●●● ●●●●●●●●●● ●●●● ●●●● ● ●●● ●● ●●● ●●● ●● ●●●● ●● ●●● ●●●● ●● ●● ●● ●● ●●●● ●● ●●● ●●●● ●●●● ●●● ●●● ●●● ●●● ●●●●●● ●● ●●●●● ●●● ●●● ● ●●●●● ●●● ●●●● ●● ●●● ●● ●●● ●●●●●●● ●●● ●● ●●●●●●●● ● ● ●●●● ● ●●●● ●●● ●●●● ●●●● ● ●● ●●●●●●● ●● ●●●● ● ●●●● ●●●●●●● ●●● ●●●●●●●●●●●●●●●●●●● ●●●●●● ●●● ●●● ●●●●● ●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●● ●● ●● ● ● ●● ●● ●●● ● ●● ●●●● ●● ●●●● ●●● ●●●● ●●●● ● ● ●● ● ●●●●● ●●● ●●●● ●●● ● ●● ●●● ●● ●●● ●● ●●● ● ●● ●●●● ●●● ●●●● ●●●●●● ● ●● ● ●● ●●● ●●●●● ●● ● ●● ●●●●● ●● ●●●●● ●●●●●●●●●●●● ●●●● ●● ●●● ●● ●●●●● ●●● ●● ●●●● ●●● ●●● ●●●●●●●● ●●● ●●●●●●●●●●●●●●●●●●●●●● ●●●●●●●●● ●●● ●●● ●●●●●●●●●●●●●●●● ●● ●● ●● ●●●●●● ● ● ● ●● ●●●●●●●●●●●●●●●●●●●●●●●●●●● ● ●●●●●●●● ●● ●●●● ●●●●● ●●●●●●● ●●●●●●●●●●●●●●●●●●●●●● ●● ●●●●●● ●●●●● ●●●●●●●●●●●●●●●● ●● ●●●●● ●●●● ● ●●● ●●● ●● ●● ●●●●●●●● ●● ●●● ●●●●●● ●●●●●●●●●●●●●●●●● ●●●● ●●● ●●● ●● ●●●●●●●●●●● ●●● ●●●●●●●●●●●●●●●●●●●●● ●●●● ●●● ●●● ●●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●● ●● ●●●● ●● ● ●● ●● ●●●●●●●●●●●●●●●●●●●●●●●● ●●●● ● ●● ●●●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●● ●● ●●●●● ● ●● ●●● ● ●●●● ●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●● ●●●● ●●●● ●● ●●●●●●●●●●●●●● ●●●●●●●●●●● ●●●●●●●●●●●●●●●●●●● ●●● ●●●● ●●●● ●●●● ●●● ● ●●●●● ●●●●●●●●●● ● ●●●●●● ●● ●● ●●●●●●●●●●●●●●●● ●●●● ●● ●●● ●●●●●● ●●●●● ● ●●●●●● ●●●●●●●●●●●●●●●●●●●●●● ● ●● ●●●●● ●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●●●●●●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●●●●●●●●●●●●●●●●● ●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●● ●●●● ●●● ●●●●●●● ●● ●●●●●●● ●●●●●●●●●●●●● ●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●● ●●● ●●●● ●●●●● ●●●●●●● ●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●● ●●●●●●●●● ●● ●●●●●●●●●●●●●●●●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●●●● ●●●●●●●●●●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●●●●●●●●●● ● ●●●● ●●●●●●● ●●●●●●●●● ●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ● ●● ●●●●●●● ●●●● ● ●●●●●●●●●● ●●● ●●●●●●●●●● ●● ●●● ●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●● ●●●●●●●●●●●●●●●●●● ●●●● ●●●● ●●●●● ●● ●●●●●●●●● ●●●● ●●●●●●●●●● ●●●●●●●●● ●● ●●●●●●●●●●●● ●●●● ●●●● ●●●●●●●●● ●● ● ●●●●● ●●●●● ●● ●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ● ●●● ●● ●●●●●●●● ●●●●●●●●● ●●●● ●● ●● ●●● ●●●●●● ●●●●●●●● ●●● ●●●●●●●●●●●●●●●●●●●●●●● ● ●●● ●●● ●●● ●●● ●● ●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●● ● ●●●●●●●●●●●●●●●●●●●●● ●●●●● ● ●●● ●●● ●●●●●●●●●●●●●●●●●●●●●●●● ●● ●● ● ● ●●●●●● ●●● ●●●●● ●●● ●●●●●● ●●● ●●●●●●●●●●●● ●●●●● ●●●●●●●●●●●●●●●●●●●●●● ●●●●●●●●●●●●● ●● ●●●● ● ●● ●●●● ●●●●●● ●●● ●●●●●●●●●● ●●●●● ●●●●● ●● ● ●● ●●●●● ●●●●●●●●●●●●●● ●●● ●●●● ●●● ●●●● ●●●●●●●●●●●● ●● ●●●●●●●●● ● ●●● ●●● ●●●●● ● ●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●● ●●●●● ●●●●●●●●●●● ●● ●● ●●●● ●● ●● ● ● ● ●● ● ●●●●●●● ●●●●●● ●● ●●●●●● ●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●● ● ●●●● ●● ●●●●●●● ● ●●●●●● ●● ●●●●●●●●●● ● ●● ●●● ●●●●●●●●●●●●●●●●● ●●● ●●●●●●●●●●● ●●●●●●●●●●●● ●●●● ●●●●●●● ●●●●● ●●● ●●●●● ● ●● ●●●● ● ●●●●●● ●● ●●●●●●● ● ●● ●●● ●● ●● ●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●● ●●● ●●● ●●● ●●●●●● ●●●●● ●●●● ● ●●●●● ●●●●●●●●●●●●●● ●● ●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●● ●●●● ●●● ●●●●● ●●●●●●●●●●●●●●●●● ●●● ●●●● ●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●●● ●● ●●●● ●● ●●●●●●● ●●●●●● ●●●●●●●●●●● ●●●●●●●●● ●● ●●● ●●●●●●●●●● ●● ● ●●●● ●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●● ●●●● ●●●●● ●●●●●●●●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●●●●●● ●●●●●● ●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●● ●●●●● ●● ●●● ●●●●●●● ●●●●●●●●● ●●●●●●●●●●●●●●●●●●●●● ●●●●●●●●● ●● ●●●●●●●●●●●●●●●●● ●●●●●●●●● ●●● ●●●●● ●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●● ●●● ●●● ●●●●●●●●●●●●●●●●●● ●●●●●●●●●●● ●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ● ●●●●●● ●●●●●●●● ●●●● ●● ●●●●●●●● ●●● ●● ●● ●●●●● ●● ● ●● ●●● ●●● ●●●●●●●●●●●●●● ● ●● ● ● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●● ● ●●●●● ●●● ●●●●●● ● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●● ●●● ●● ●●●● ●●●●●●●●●●●●● ●●●●●●●● ●●● ●●●●●● ●● ●●●●●●●●● ●●● ● ●● ●●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●●●●●●● ●●●●●●●●●● ●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●● ●● ●●●●●●●● ●●●● ●●●

●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●● ● ●●●●● ●●● ●●● ●● ●● ●● ●●●●●● ●●●● ●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●●●●●● ●● ●●●●●● ●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●●●●●●●●● ●●●●●●●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●●●●●●●●●●●● ●●●●● ●●●●● ●●●● ●●●●●●●●●●●● ●●●●●●●●●●●●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●● ●● ●●● ●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●● ●● ● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●● ●●●●●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●● ●●●●● ●● ●●●●●●● ●●● ●●●●●●●●●●●●●● ●● ●●●●●●●●● ●● ●●●●●●●●●●●●●●●●●●●●●●●● ●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●●●● ●● ●●●●●●●●●●●●●●●●● ●●●●●● ●●●●●●●●●●●●●●●●●●●●●●● ●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●● ●●●●●● ● ●●●●●● ●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ● ●●●●●● ●●●● ●● ● ●●●●●● ●●●● ●●● ●●●● ●●● ●● ●●●●●●●●●●●●●●●●● ●●● ●●●● ●●●●●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●●●●●●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●● ●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●●●●●●●●●●●●●●●● ●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●● ●●●●●●●●●●● ● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●● ●●●●●●●●●● ●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●● ●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●● ●● ●●● ●●●●●●●●●●●●●●●●●●●●●● ●●●● ●●● ●●●●●●●●●●●●●● ●●● ●●●●●●●●●●●●●●●● ●●●●●●●●●● ●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●● ● ●●● ●●● ●●●●●● ●●●●● ●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●●●●●●● ●● ●●●●●● ●● ●●●●●●●●●●●●● ●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●● ●● ●● ●● ●● ●●●● ●●●● ●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●● ●●● ●● ●●●●●●●●●●●●●●●●●●●● ●●● ●●● ●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●● ●●●●●● ●●● ●●● ●●● ●●● ●●●●●●● ●●●●●●●● ●●● ●●●●●●●●●●●●●●●●● ●●●● ●●●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●● ●●●●●●●● ●●● ●●●●●●●●●●●●●●●●●● ●●●● ●●●●●●●●●●●●●●●●● ●●●●●●●●●●●●●●●●●● ●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●● ●●●●●●●●●●● ●●●●●●●●●●●●●●●● ●● ●● ●●●● ●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ● ●●● ●●●●●●●●●●●●●●●● ●●●●●●●●●● ●●●●●●●●●● ●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●● ●●●● ●●●●●●●●●●●●●●●●●●●●●●●● ● ●●●●●●●●●● ●●●●●●● ●●●●●●●●● ●●●●●●●●●●●●●●●●● ● ●●● ●● ●●●● ● ●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●●●●●●●● ●●● ●●●●●●●●●●●●●●●●● ●●●●●●●●●●●●● ●●●●●●●● ●●●●●●●●●●●●●● ●●●●●●●●●●● ●●●●●●● ●●●●●●●●●●●●●●●●●● ●●● ●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●● ●●●●●●●●●●●●●●●●●●●●●●●● ● ●●●●●● ● ●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●● ●●● ●● ●●● ●● ●● ●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●●●●●●●●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●● ● ●●●●●●●●●●●●●●●●●●●● ●●●● ●●●●●● ●● ●●●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ● ●● ●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●●●●●● ●● ●●●●●●●●●●●●●●●●●●●●●● ●●●● ●●●●●●●●●●●●●●●●●●● ● ●●● ●● ●●●● ●●●●● ●●●●●●●●●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●● ●●●●●●●●●●●●●●●●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●● ● ●●● ●●●●●●●●●●●●●●●●● ●●●●●●●●●●●●●●●●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●● ●●●● ● ●●● ●●● ●●●●● ●● ●●●●●●●● ●●●●●●●●●●●●●● ●● ●●● ●● ●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●●●●●●●●● ●●●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●●●●● ●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●● ●●● ●● ●●●●● ●●●●●●●● ●● ●●● ●●●●●●●●●●●●●●●●●● ●●●●●●●●●●●● ●●●●●●●●●●●● ●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●● ●●● ●● ●●● ●●●●●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ● ●●●●● ●●●●●● ●●● ● ●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●●●●●●●●●●●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●●●●●●●●●●●●●●●●● ●●●●●●●●● ● ●● ●●●●●●●●●●●●● ●●●●● ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●●● ●●●● ●●●●●●●●●●●●●●●●●●●●●●

0

500

1000

1500

−1 0 1 −1 0 1Scaled Target Address Index

Alig

ned

Func

tion

Inde

x

Figure 1: Alignment of a Malicious Version of Putty(left) with Putty Version 0.63 (right)

By this example, we can demonstrate the afore-mentioned application scenarios. First, the maliciousPutty is a direct example of the clone-and-own sce-nario. Second, the Putty executable is relatively stan-dalone, not depending on a lot of external libraries,and therefore represents the closedness of executablesof embedded systems. Third, since it is unclear onwhich commit exactly the clone was forked, it canpossibly also be closer to Putty 0.64. Selecting such abase executable resembles the analysis of change logs(not shown here). Lastly, the set of changed and in-serted functions can be used to identify the possibleset of malicious functions.

References

[1] K. Berta et al. “Estimation of similarity betweenfunctions extracted from x86 executable files”. In:SJEE (2015).

[2] T. Dullien et al. “Graph-based comparison of ex-ecutable objects”. In: SSTIC (2005).

[3] C. Fry. “Trojanized PuTTY Software”. In: CiscoSecurity Blog (2015). url: http : / / blogs .

cisco . com / security / trojanized - putty -

software.

[4] D. S. Hirschberg. “A Linear Space Algorithm forComputing Maximal Common Subsequences”.In: Com. ACM (1975).

[5] S. Stojanovic et al. “Approach for estimating sim-ilarity between procedures in di↵erently compiledbinaries”. In: IST (2015).

[6] A. Wichmann et al. “Matching Machine-CodeFunctions in Executables within one ProductLine via Bioinformatic Sequence Alignment”. In:MUD (2015).

[7] A. Wichmann et al. “Visual Analysis of ControlCoupling for Executables”. In: WSRE (2015).

Page 14: 18. Workshop Software-Reengineering und -Evolution · Software-Reengineering ... a tool that measures code metrics and also outputs results on maintainability. These quantitative

The Challenge of Indirection: Treating Flags

During Sound Analysis of Machine Code

Sven Mattsen, Sibylle SchuppHamburg University of Technology, Hamburg, Germany

{sven.mattsen, schupp}@tuhh.de

1 Introduction

A key problem in reverse engineering executables is toreconstruct the programs’s control flow, i.e., to con-struct a graph representation of the byte sequences orpaths a computer may execute as instructions. Un-fortunately, exactly computing all feasible paths of aprogram is not possible. Therefore, the task of precisecontrol flow reconstruction and disassembly is also notsolvable in general, and one must be content with anapproximative answer.

Contemporary disassemblers, such as objdump,radare2, and IDAPro either use linear sweep[5] or re-cursive descent[5] techniques, enhanced by heuristics,to compute an approximated disassembly. As a result,they may produce assembly that not only omits pathsthat were feasible in the analyzed binary, but also con-tain paths that were infeasible in the analyzed binary.While this form of approximation is acceptable forcertain tasks, e.g., program understanding, it is un-acceptable for tasks such as verification, where onereasons about statements that must hold on all paths(e.g., there exists no path containing an exploitablesequence).

One approach to enable tasks such as verificationis to allow only overapproximation, i.e., the recon-structed control flow must contain at least all pathsthat are feasible in the analyzed executable, but maycontain additional paths. Tools that overapproximatein this way are called sound. When a verification taskrequires proving that an illegal program state cannotbe reached, a sound disassembly can be used. If noillegal program state can be reached in the sound dis-assembly, no illegal program state is reachable in theoriginal program. If it cannot be shown that no illegalprogram state can be reached in the sound disassem-bly, then it is unclear if a fault exists or not.

In the following sections, we will first explainsound control flow reconstruction via value set anal-ysis[1] (Section 2) and introduce a challenge thatis unique to the analysis of machine code (Section3). In sections 3.2 and 3.3, we will present two ap-proaches to this problem that we implemented in ourBDDStab[4] plug-in for the software analysis frame-work Jakstab[3].

2 Sound Analysis of Machine Code

The most challenging aspect of sound control flow re-construction is to compute a precise set of possible ad-dresses for dynamic jumps, i.e., jumps that use a non-constant target (jmp %eax). In BDDStab, we use ab-stract interpretation techniques, which are commonlyused on structured programs, to statically computean overapproximated set of possible integer values foreach register and memory location. The techniquerequires a memory-e�cient set data structure for in-tegers as well as precise algorithms that model thesemantics of machine instructions on our overapprox-imated sets. We use binary decision diagrams (BDD)to enable size e�cent storage of nearly full sets of 64-bit integers and define our algorithms on the structureof the BDDs rather than the set they represent, whichallows e�cient operations for large sets.

3 Flags in Executables

Besides precise models for bitwise and arithmetic in-structions, computing precise sets of possible valuesalso requires models for conditional branches, wherethe abstract states must be restricted according to thecondition. These models have to account for the dif-ferent ways in which conditional branches operate inmachine code, namely the indirection via flags. Con-sider the following example C code and its correspond-ing assembly:

1 i f ( ( unsigned i n t ) argc < 10)2 re turn 1 ; e l s e re turn 0 ;

1 cmpl $0x9 ,�0x4(%rbp )2 ja $RET13 mov $0x1 ,%eax4 jmp $RET25 RET1: mov $0x0 ,%eax6 RET2: r e tq

The assembly code first uses cmpl to set variousflags that are subsequently used in the jg operation,which jumps depending on the flag values. This be-haviour is di↵erent from the C program in that theC program directly refers to the variable argc in the

Page 15: 18. Workshop Software-Reengineering und -Evolution · Software-Reengineering ... a tool that measures code metrics and also outputs results on maintainability. These quantitative

condition. In the assembly version, however, whenlooking at the jg alone allows only the restriction offlag values, not the value at -0x4(%rbp) which is argc.Because some compilers may interleave other instruc-tions between cmpl and jg, especially on architectureswhere pipelining is heavily influencing the optimal or-der of instructions (MIPS), these two instructions can-not easily be treated as a unitary instruction. Ananalyzer must therefore find a way to restrict the ob-jects of conditions even though they are not explicitlymentioned in the condition of the jump itself.

3.1 Forward Substitution

Our treatment of flags during analysis uses forwardsubstitution as implemented in the binary analysisframework Jakstab[3]. Instead of analyzing on thelevel of assembly, with Jakstab, analyses are definedon an intermediate language that makes all e↵ects ofinstructions explicit. Line 1 (cmpl) and 2 (ja) will betranslated to the following, where PC is the programcounter:

1 CF := ( $0x9 <u �0x4(%rbp ) )2 ZF := ( $0x9 = �0x4(%rbp ) )3 PC := $RET1 i f ˜(%CF | %ZF)

Forward substitution would replace %CF and %ZF

with the right hand side expression of lines 1 and2 in the example. The analyzer’s task is to restrictincoming sets of possible values for the heap value-0x4(%rbp) according to the resulting formula.

3.2 Pattern-based Back Translation

The key observation behind pattern-based backtrans-lation is that the complex formulas that result fromforward substitution are often the result of a compila-tion of much simpler, semantically equivalent formu-las. In our last example, the conditional jump wascaused by a simple unsigned less than, and it shouldbe possible to translate the result of forward substi-tution back to that. To that end, we refined the sim-plification rules in Jakstab, so that they mirror thepatterns for intermediate code generation.

3.3 Constraint Solver

The pattern-based back translation approach does notalways work, e.g., when more complex conditions areused in the source language or when assembly is writ-ten by hand. For these cases, we have developed asimple, overappxomating constraint solver that, givena boolean formula over base constraints such as less

than, greater than and equality predicates, producesoverapproximated sets of possible values for the reg-isters and memory locations refered to in the baseconstraints. This constraint solver uses the fast algo-rithms for and, or, and negation, available for BDDs.The constraint solver recurses on the AST of the con-straint until it reaches a base constraint, generates aset of possible values for all syntactically mentioned

registers and memory locations, and propagates thesesets upwards. Subsequently, these upwards prop-agated sets are intersected for boolean and nodes,unioned for boolean or nodes and complemented forboolean negation. Because the complementation ofan overapproximated set yields an underapproxima-tion, the constraint solver additionally tracks whetheran overapproximation or an underapproximation isneeded for each base constraint, whereby it ensuresto only generate overapproximations at the top ASTnode.

4 Related Work

At its core, the indirection problem of flags in binaryanalysis is a problem of relations between flags andregisters and memory locations. However, the shapeof the relations is not supported by traditional rela-tional analyses such as a�ne relations[2]. Sepp et al.[6] therefore introduce virtual flags and correspond-ing virtual instructions that produce relations that asubsequent a�ne relations analysis supports.

5 Conclusion

We have implemented the pattern-based and con-straint solver approaches in our BDDStab plug-in andfound that the pattern-based back translation ap-proach improves precision in the most frequent casesand additionally simplifies the work for the constraintsolver if simplification does not yield an expressionwithout boolean connectives.

References

[1] G. Balakrishnan and T. Reps. “Analyzing Mem-ory Accesses in x86 Executables”. In: Compiler

Construction. LNCS. 2004, pp. 5–23.

[2] M. Karr. “A�ne relationships among variablesof a program”. In: Acta Informatica (1976),pp. 133–151.

[3] J. Kinder and H. Veith. “Jakstab: A Static Anal-ysis Platform for Binaries”. In: Computer Aided

Verification. LNCS. 2008, pp. 423–427.

[4] S. Mattsen, A. Wichmann, and S. Schupp. “Anon-convex abstract domain for the value analy-sis of binaries”. In: International Conference on

Software Analysis, Evolution and Reengineering.SANER. 2015, pp. 271–280.

[5] B. Schwarz, S. Debray, and G. Andrews. “Disas-sembly of Executable Code Revisited”. In: Work-

ing Conference on Reverse Engineering. WCRE.2002, pp. 45–.

[6] A. Sepp, B. Mihaila, and A. Simon. “PreciseStatic Analysis of Binaries by Extracting Rela-tional Information”. In: Working Conference on

Reverse Engineering. WCRE. 2011, pp. 357–366.

Page 16: 18. Workshop Software-Reengineering und -Evolution · Software-Reengineering ... a tool that measures code metrics and also outputs results on maintainability. These quantitative

Polishing Design Flaw Definitions

Daniel Speicher, B-IT, Universität Bonn, [email protected]

In all methods M of class C, you may useonly methods and fields of the followingtypes and their supertypes: C itself, typesof fields of C, types of parameters of M, orclasses that are instantiated in M.

Figure 1: Law of Demeter, [3]

Every single false positive that an automated de-sign flaw detection tool presents to a developer placesa cognitive burden on him and should thus be avoided.A preliminary yet already quite comprehensive cata-log of false positives was recently presented in [1]. Weelaborated in [5, 4] that developers accept design flawsin the context of specific design ideas, e.g. featureenvy in the context of the visitor pattern. We sug-gested that it should be possible to incorporate suchknowledge into operational design flaw definitions. In-spired by [2] we are convinced that our understandingof the phenomena “design flaw”, “design idea” andtheir conflict could still benefit from an exploratorycase study guided by the following research questions:What is the nature of design ideas that are related todesign flaws? How are both related? What are the con-sequences for operational definitions of design ideasand design flaws?

1 The exploratory case study

In the hope to generate many false positives we applythe rather rigid classical design flaw Law of Deme-ter to the thoughtfully designed classical frameworkJHotDraw 5.1. The Law of Demeter is some-times presented as the motto “Only talk to yourfriends.” - meaning that methods should only accessmembers of certain “friend” types. See Figure 1 for

Figure 2: Partial class diagram for JHotDraw 5.1

our translation of a C++ version to Java1. JHot-Draw is a framework for graphical drawing editorapplications developed by Erich Gamma and others2.To assess the severeness of a potential design flaw, wereview the negative e�ect of not following the Law onencapsulation, coupling, and understandability. Wereview as well the positive e�ects of the two possiblerefactorings of pushing parts of the method that accessthe “stranger” back to a “friend” or lifting accesses to“stranger”’s members forward to a “friend”.

2 Examples of true and false positives

Let us list five potential design flaws.The first threeare in the method constrainX(int) in ElbowHande,which constrains the movement of a LineConnection:private int constrainX(int x) {

LineConnection line = ownerConnection();Figure startFigure = line.start().owner();Rectangle start = startFigure.displayBox();Insets i1 = startFigure.connectionInsets();int r1x = start.x + i1.left;int r1width = start.width - i1.left - i1.right-1;return Geom.range(r1x, r1x + r1width, x);

}

(F1) “line.start()” is a false positive sinceElbowHandle’s only purpose is to manipulate itsLineConnection. This does not show in the type ofa field but in the type of a constructor parameter.3(T1) “start().owner()” is a true positive since thereis no need to know the class Connector here. There isalready a method getStartFigure() that lifts the fig-ure access forward. (F2) “start.x” and all accessesto fields of the class Rectangle should be consideredto be false positives as discussed in the next section.(F3) Accesses to Figure after retrieving the selectionfrom DrawingView are false positives since the indirec-tion is a consequence of the reasonable global designdecision to maintain the Figure selection in one place.(T2) Comments claim that DrawingEditor is a medi-ator. It should thus hide the types of colleagues,but it exposes them through accessors. Potential de-sign flaws in this context should be considered true.

1As the corresponding C++ version in [3] our Java versionis based on classes and not on objects. It is “strict” - meaningthat types of inherited fields are not considered to be “friends”.

2Dirk Riehle made the source and documentation availablein the context of his dissertation at http://dirkriehle.com/computer-science/research/dissertation/appendix-e.html .

3As soon as we consider LineConnection a friend its super-type Figure must be considered a friend as well. Thus the twomethod calls on startFigure are no violations anymore.

Page 17: 18. Workshop Software-Reengineering und -Evolution · Software-Reengineering ... a tool that measures code metrics and also outputs results on maintainability. These quantitative

3 Example review of a potential flaw

As for (F2) we suggest to consider all the 366 accessesto Rectangle that are potential design flaws to be falsepositives. Rectangle should be seen as “everybody’sfriend”, i.e. every method should be allowed to accesstheir members. The concept of a rectangle is partof our elementary common knowledge so that the us-age of Rectangle is easy to understand. Coupling tothis class does not create additional maintenance ef-fort, since its structure is shallow and the class is verystable4. The lifting refactoring is not an option sincethis would mean to replace every method returningone Rectangle with four methods returning an int.In case of (F2) pushing the whole calculation backinto the class Figure could be considered. This wouldindeed improve the encapsulation of Figure. Never-theless, calculating the possible coordinates for theends of a LineConnection is a cohesive responsibilitythat fits well into the ElbowHandle. It is not to expectthat the same functionality in Figure would be usedby other classes. Overall, we suggest that the currentcode is in this respect good enough and that the sameis true for other data classes as well.

4 Amendments based on design ideas

For (F1) we suggested to consider constructor param-eters to play the same role as fields. We can make sim-ilar amendments with respect to parameters and in-stantiations. For (F2) we suggested to consider dataclasses to be “everybody’s friend”. For (F3) we sug-gest to consider the methods returning the selectionto be an “introducing member”, meaning they intro-duce Figure as “friend” to the calling method. Finallywe found reasons to adapt the meaning of “type of”and once for recursion. The review of the potentialdesign flaws led us to make use of design ideas (andlanguage concepts) to complete the design flaw defini-tion. Some facets of Java needed to be covered, e.g.for anonymous inner classes the friends of the enclos-ing method should be as well considered its friends.Some type information was not immediately enoughavailable. Creational patterns are considered as alter-native ways of instantiation. But, there were as wellreal conflicts between the design flaw definition anddesign ideas. We expected design ideas, for which wewould be willing to trade the design flaw as we had dis-cussed in [4, 5]. We found only (F2) and (F3), the eas-ily understandable data classes and the reasonablechoice to localize the information about the selectedfigures in the DrawingView. We found cases, where wehad to resign, because the code that needed to changewas not under our control or followed very establishedconventions, that one might not want to change for thespecific context. The case (T2) of the undutiful medi-

4The class is part of the package java.awt. Its simplicitymakes changes improbable. The mere amount of code depend-ing on it makes changes to it too expensive, i.e. it is as wellstable in the sense of R. C. Martin.

ator DrawingEditor exposing colleagues needs verywell improvement, but is too deeply entrenched in thecurrent design to be solved with isolated refactorings.Therefore one could postpone the decision to refactoruntil a major redesign.

5 From generic to specific design ideas

The design ideas that we discovered range from verygeneric (“anonymous inner class”) to very specific(“DrawingView holds Figure selection”). Our confi-dence ranges from very high (“creation method accessis like instantiation”) to high enough (“data classesare everybody’s friend”). After a thorough discus-sion of the 1215 potential design flaws 67 remain astrue positives and 3 remain undecided. Thus the con-frontation of a thoughtfully designed software systemwith a rigid design flaw definition did indeed resultas intended in many false positives and the very lowprecision 67/1215 = 5.5%. Taking more and morespecific design ideas into account we can increase thisprecision: With respect to Java concepts 472 of the1215 potential flaws can be identified as false 5. Allow-ing some interpretative concepts based on Java (thusslightly reduced confidence), we can reduce the num-ber by further 149 cases6. Further 499 cases can be ex-cluded taking general object oriented design ideas likecreational patterns and data class into account7.Finally, further 25 cases can be identified as false pos-itives based on specific design ideas in JHotDraw 5.18.We reached a precision of 67/(1215-472-149-499-25) =67/70 = 95.7%.

References

[1] F. Arcelli Fontana, J. Dietrich, B. Walter, A. Yamashita,and M. Zanoni. Antipattern and code smell false positives:Preliminary conceptualization and classification. In SANER2016. Osaka, Japan, 2016.

[2] S. Easterbrook, J. Singer, M.-A. Storey, and D. Damian.Selecting Empirical Methods for Software Engineering Re-search. In Guide to Advanced Empirical Software Engineer-ing, pages 285–311. Springer London, 2008.

[3] K. J. Lieberherr and I. M. Holland. Formulations and Ben-efits of the Law of Demeter. ACM SIGPLAN Notices,24(3):67–78, 1989.

[4] D. Speicher. Code Quality Cultivation. In IC3K 2011,Revised Selected Papers. Springer Berlin Heidelberg, 2013.

[5] D. Speicher and S. Jancke. Smell Detection in Context. InWSR 2010, Softwaretechnik-Trends, Band 30, Heft 2, 2010.

5Everybody’s friends: Collections types (137), java.langtypes (128), the array “field” length (8), public static mem-bers (270). Friends of the enclosing method of an anonymousinner class are friends of any method in this inner class (23).

6Like fields: Constructor parameters (86) - see (F1), Inferredtype in collection field (40). Like parameters: Immediate down-casts of parameters. Introducing members: Designated acces-sors in the JDK (5), System.out (11)

7Like instantiation: Call to factory method (1) or cre-ation method (2), access to singleton (24). Everybody’sfriend: data class (540) - see (F2).

8Taking specific types into account: composites with spe-cific components (5), Clipboard contains Figures (2), collec-tion parameters containing Figures (3). Introducing members:Accessors to the selected Figures in DrawingView (20) - see (F3).

Page 18: 18. Workshop Software-Reengineering und -Evolution · Software-Reengineering ... a tool that measures code metrics and also outputs results on maintainability. These quantitative

Extract Method Refactoring-Vorschl

¨

age automatisch ableiten

Roman HaasTechnische Universitat MunchenLichtenbergstr. 8, 85748 Garching

[email protected]

Benjamin HummelCQSE GmbH

Lichtenbergstr. 8, 85748 [email protected]

Zusammenfassung

Das Extract Method Refactoring ist eine gebrauchli-che Art, zu lange Methoden im Code zu kurzen. Bevoraber Tool-Support fur das Refactoring genutzt werdenkann, mussen Entwickler zunachst geeignete Codezei-len identifizieren – ein zeitintensives und fehleranfalli-ges Unterfangen. Dieses Paper prasentiert einen An-satz, der automatisch Vorschlage fur Extract MethodRefactorings generiert. Dazu werden zunachst allegultigen Extract Method Refactorings berechnet undanschließend diejenigen vorgeschlagen, die die Kom-plexitat des Codes am meisten verringern. Der Ansatzberuht auf einer Scoring-Funktion, deren Gewichtungdurch Learning-to-Rank-Verfahren bestimmt wurde.Wir stellen in diesem Paper auch die wichtigsten Er-gebnisse aus den Learning-to-Rank-Verfahren anhandvon drei Forschungsfragen vor.

1 Einleitung

Eine lange Methode ist ein Bad Smell in einemSoftwaresystem [1] und verschlechtert Lesbarkeit,Verstandlichkeit und Testbarkeit des Codes. Um langeMethoden zu kurzen werden haufig Extract MethodRefactorings genutzt.

Aktuelle IDEs unterstutzen Entwickler bei derDurchfuhrung von Extract Method Refactorings.Hierbei mussen nur die zu extrahierenden Codezei-len ausgewahlt, die Refactoring-Funktion aufgerufenund ein Name fur die neue Methode vergeben werden.Das Extrahieren der Methode wird dann automatischdurchgefuhrt. Dennoch sind diese Refactorings zeitin-tensiv und fehleranfallig, weil der Entwickler vorherinfragekommende Kandidaten bestimmen muss.

Wir stellen in diesem Paper einen Ansatz vor, wieExtract Method Refactoring-Vorschlage fur zu langeMethoden automatisch generiert werden konnen. Da-bei werden zunachst alle moglichen Extract MethodRefactorings generiert und die besten Vorschlage an-hand einer Scoring-Funktion bestimmt. Die Parame-ter der Scoring-Funktion wurden durch die Anwen-dung von Learning-to-Rank-Verfahren ermittelt. In ei-

⇤Das diesem Artikel zugrundeliegende Vorhaben wurde mit

Mitteln des Bundesministeriums f

¨

ur Bildung und Forschung

unter dem F

¨

orderkennzeichen Q-E↵ekt, 01IS15003A gef

¨

ordert.

Die Verantwortung f

¨

ur den Inhalt dieser Ver

¨

o↵entlichung liegt

bei den Autoren.

nem weiteren Schritt wurde die Scoring-Funktion aufBasis der Erkenntnisse aus dem Lernverfahren verein-facht. Der Ansatz wurde in einem Tool zur kontinuier-lichen Softwarequalitatsanalyse fur die Sprachen Javaund C# implementiert.

2 Ansatz

Unser Ansatz besteht aus zwei wesentlichen Schritten:Zunachst werden alle validen Refactoring-Moglichkei-ten (”Kandidaten”) bestimmt und diese anschließendmittels einer Scoring-Funktion gerankt. Die bestenKandidaten werden dann fur ein Extract Method Re-factoring vorgeschlagen.

2.1 Kandidatengenerierung

Ein Kandidat besteht aus einer Sequenz von Codezei-len, die aus der ursprunglichen Methode in eine neueextrahiert werden kann. Wichtigste Einschrankung istdabei, dass die zu extrahierende Methode beispielswei-se bei Java oder C# nicht mehr als einen Ruckgabe-parameter benotigen darf. Um unnutze Vorschlage zuvermeiden, werden nur Kandidaten berucksichtigt, diemindestens drei Statements umfassen und bei denenwenigstens drei Statements (inklusive dem Aufruf derextrahierten Methode) in der ursprunglichen Methodeverbleiben.

2.2 Scoring-Funktion

Die Scoring-Funktion bewertet alle gultigen Kan-didaten hinsichtlich ihres Einflusses auf die Code-Komplexitat der zu langen Methode. Kandidaten, diedie Komplexitat des Codes reduzieren, werden im All-gemeinen besser gerankt, als solche, die die Komple-xitat kaum senken. Als Komplexitatsindikatoren wer-den in der Scoring-Funktion die Reduktion der Langeund der Verschachtelung der einzelnen Methoden be-trachtet. Außerdem wird die Zahl der benotigten Pa-rameter bei der extrahierten Methode berucksichtigtund Zusatzpunkte auf Basis von strukturellen Infor-mationen (Kommentare und leere Zeilen) vergeben.

Details zu unserem Ansatz finden sich auch in [2].

3 Learning to Rank

Um die Scoring-Funktion zu verbessern und den Ein-fluss der einzelnen Komponenten besser zu verste-hen, wurden zwei Learning-to-Rank-Verfahren ge-

1

Page 19: 18. Workshop Software-Reengineering und -Evolution · Software-Reengineering ... a tool that measures code metrics and also outputs results on maintainability. These quantitative

nutzt: SVM-rank von Tsochantaridis et al. [5] undListMLE von Xia et al. [6].

Die Learning-to-Rank-Tools lernen Gewichtungenfur die einzelnen Parameter der Scoring-Funktion.Es werden elf Komplexitatsindikatoren, die Zahl derbenotigten Ein- und Ruckgabeparameter und siebenstrukturelle Informationen als Parameter verwendet.

3.1 Forschungsfragen

Im Rahmen dieses Papers wird auf die folgenden dreiForschungsfragen eingegangen:

• FF1: Welche Parameter sind auf Grundlage derErgebnisse der Learning-to-Rank-Verfahren be-sonders wichtig?

• FF2: Wie stabil sind die gelernten Scoring-Funktionen in der 10-fold-cross Evaluierung?

• FF3: Kann die Scoring-Funktion vereinfacht wer-den?

3.2 Setup

Als Datengrundlage wurden 5-9 zufallig ausgewahl-te, gultige Refactoring-Vorschlage aus 177 wiederumzufallig ausgewahlten zu langen Methoden aus 13 be-kannten Open Source Systemen manuell hinsichtlichihrer Komplexitatsreduktion gerankt.

Wir wendeten ein Kreuzvalidierungsverfahren (10-fold-cross) an, bei dem die Lerndaten in zehn et-wa gleich große Mengen aufgeteilt und in zehnDurchlaufen je neun der Mengen als Lerndaten unddie verbleibende Menge als Testdaten genutzt werden(vgl. auch [4]).

Um die erlernten Scoring-Funktionen hinsichtlichihrer Ranking-Fahigkeit vergleichen zu konnen, wurdedie Normalized Discounted Cumulative Gain Metrik(NDCG, s. auch [3]) genutzt.

3.3 Ergebnisse und Diskussion

Im Folgenden werden die Ergebnisse erlautert.

FF1: Welche Parameter sind auf Grund-

lage der Ergebnisse der Learning-to-Rank-

Verfahren besonders wichtig? ListMLE lernt ei-ne Scoring-Funktion, die besonders viel Gewicht aufdie Reduktion der Lange legt. Die Zahl der benotigtenEingabeparameter hat einen kleinen, aber negativenEinfluss auf den Score. Die strukturellen Informatio-nen sind fur das Ranking relevant, bei weitem abernicht so einflussreich wie die Komplexitatsindikatoren.

SVM-rank zeichnet ein weniger klares Bild. DieKomplexitatsindikatoren und strukturellen Informa-tionen haben einen stark variierenden Einfluss auf dasRanking. Die Zahl der Eingabe- bzw. Ruckgabepara-meter hat negativen Einfluss auf den Score.

FF2: Wie stabil sind die gelernten Scoring-

Funktionen in der 10-fold-cross Evaluierung?

Um die Stabilitat der gelernten Scoring-Funktionen

bewerten zu konnen, haben wir den Variationskoe�zi-enten fur alle Parameter der Scoring-Funktion berech-net. Der Mittelwert liegt hier fur ListMLE bei 0,0087und fur SVM-rank bei 22,522. Der schlechteste Varia-tionskoe�zient bei ListMLE ist immer noch besser alsder beste Variationskoe�zient bei SVM-rank.

Die einzelnen gelernten Scoring-Funktionen vonSVM-rank lassen sich also kaum fur einen Einsatz inder Realitat verallgemeinern. Die Variationskoe�zien-ten fur ListMLE sind nahe Null und deuten damit aufverlasslichere Ergebnisse hin.

FF3: Kann die Scoring-Funktion vereinfacht

werden? In weiterfuhrenden Experimenten konn-ten wir die Zahl der Parameter von zwanzig auf biszu drei reduzieren, ohne die Ranking-Performance derScoring-Funktion deutlich zu verringern.

4 Implementierung

In Teamscale1, einem Werkzeug zur kontinuierli-chen Softwarequalitatsanalyse, konnen Extract Me-thod Refactoring-Vorschlage fur zu lange Methodenaus Java- und C#-Projekten angezeigt werden.

Dabei werden die zu extrahierenden Zeilen hervor-gehoben und die Variablen, die in der extrahiertenMethode als Parameter dienen, farblich markiert.

5 Zusammenfassung

Zu lange Methoden lassen sich mittels Extract Me-thod Refactorings kurzen. Um Zeit zu sparen undFehler zu vermeiden, sind Refactoring-Vorschlage furEntwickler nutzlich. In diesem Paper haben wir einenAnsatz hierfur vorgestellt, der eine gelernte Scoring-Funktion nutzt und in Teamscale, einem Tool zur Soft-warequalitatsanalyse, implementiert ist.

Literatur

[1] M. Fowler. Refactoring : Improving the Design

of Existing Code. Addison-Wesley object techno-logy series. Addison-Wesley, Reading, PA, 1999.

[2] R. Haas and B. Hummel. Deriving extract me-thod refactoring suggestions for long methods. InSWQD, 2016.

[3] L. Hang. A short introduction to learning torank. IEICE Transactions on Information and

Systems, 94(10):1854–1862, 2011.

[4] C. Sammut, editor. Encyclopedia of machine

learning. Springer, New York, 2011.

[5] I. Tsochantaridis, T. Joachims, T. Hofmann, andY. Altun. Large margin methods for structuredand interdependent output variables. Journal of

Machine Learning Research, 6:1453–1484, 2005.

[6] F. Xia, T.-Y. Liu, J. Wang, W. Zhang, and H. Li.Listwise approach to learning to rank: Theoryand algorithm. In 25th ICML, 2008.

1teamscale.eu

Page 20: 18. Workshop Software-Reengineering und -Evolution · Software-Reengineering ... a tool that measures code metrics and also outputs results on maintainability. These quantitative

A Study on Tool Support for Refactoring in Database Applications

Hagen Schink1, Janet Siegmund⇤2, Reimar Schroter*1, Thomas Thum3, and Gunter Saake1

1University of Magdeburg, 2University of Passau, 3TU Braunschweig

Abstract

Refactoring is a widespread method to improve thestructure of an application’s source code without af-fecting the application’s behavior. However, sincerefactorings are defined for single programming lan-guages or programming paradigms, refactorings donot consider the interaction of source code of di↵er-ent programming languages. Thus, refactoring canbreak applications written in di↵erent programminglanguages. We found that our tool improves the pro-ductivity regardless of the participants’ programmingexperience, but there is also room for improvementregarding support for certain refactoring tasks.

1 Introduction

The term refactoring describes changes that alter thestructure but not the semantics of source code. Refac-toring is a widespread methodology in software de-velopment and is supported by state-of-the-art IDEs,such as Eclipse. Developers use refactorings to in-crease the maintainability of source code and to easethe implementation of new features.

The combination of di↵erent general-purpose anddomain-specific languages is common in software de-velopment. Domain-specific languages allow develop-ers a concise implementation of logic of a certain do-main, whereas general-purpose languages support de-velopers in the general application development.

To support refactoring in database applications, wedeveloped the refactoring tool sql-schema-comparer

(SSC) [3]. The aim of our study was to evaluatewhether SSC actually improves the productivity ofdevelopers refactoring a database application.

2 The Tool

SSC uses graphs to detect mismatches between theschema of a relational database and the schema ex-pected by the Java source code that accesses the re-lational database. In Java, the expected schema canbe defined with the Java Persistence API (JPA). Forinstance, for the JPA entity Department in Listing 1,SSC creates one graph with a root node departmentsand the two leaves id and name. Since SSC wouldcreate the same graph for a table departments with

⇤The work of Janet Siegmund and Reimar Schroter has been

supported by the DFG grant SI 2045/2-1 and BMBF grant

01IS14017B, respectively.

Listing 1: JPA entity Department

1 @Entity2 @Table(name=”departments”)3 public class Department implements Serializable {4 // fields and setters omitted for brevity

5 @Id6 public int getId() { return id; }7 public String getName() { return name; }8 }

the two columns id and name, SSC would not de-tect a mismatch between the expected and the actualschema. We implemented a plug-in that integratesSSC in Eclipse. The plug in highlights a↵ected Javaclasses, fields, and methods, if it detects a mismatch.For instance, the plug-in marks a Java class annotatedwith @Entity as erroneous that maps a missing table.

3 Study Method

We o↵ered students of a database course at the Uni-versity of Magdeburg appointments for taking part inour study. The participants had to solve two refac-toring tasks on the source code of the open-sourceprojects Apache Syncope and AppFuse with 77 000and 24 000 lines of Java code, respectively. Bothprojects use JPA to access a relational database. Forthe two refactoring tasks, we prepared two Eclipseprojects with database instances on which we ap-plied a Rename-Column (Task 1) and a Move-Column

refactoring (Task 2) beforehand. The refactoreddatabases cause the projects’ unit tests to fail. Ad-ditionally, for each task we provided the participantswith a description of the refactoring applied to thedatabase instances. We assigned participants ran-domly to a group with or without SSC support. Agroup with SSC support got an Eclipse environmentwith the SSC plug-in pre-installed, whereas the groupwithout SSC support got a plain Eclipse for the exper-iment. The participants had to run the projects’ unittest to ensure their changes fixed the broken applica-tions. We measured the development times as metricfor productivity for each participant. Before the ex-periment started, we used a minimal code exampleto give an introduction to JPA, refactoring, and, ifnecessary, to SSC. In the introduction, we used theRename-Column refactoring as example.

Page 21: 18. Workshop Software-Reengineering und -Evolution · Software-Reengineering ... a tool that measures code metrics and also outputs results on maintainability. These quantitative

Without tool support With tool support

●●

500

1000

1500

Inexperienced Experienced Inexperienced ExperiencedExperience

Tim

e in

sec

onds

Figure 1: Development time distribution for Task 1.

Without tool support With tool support

● ●

500

1000

1500

Inexperienced Experienced Inexperienced ExperiencedExperience

Tim

e in

sec

onds

Figure 2: Development time distribution for Task 2.

4 Results

In the experiment, we collected the development timesof 76 undergraduate and 3 graduate students. As ma-jor confounding parameter, we consider programmingexperience which we measured based on a question-naire [2]. Based on the participants’ experience, wedistinguished inexperienced and experienced partici-pants in the analysis.

Before we analyzed the data, we cleaned the dataset. First, we removed measurements of unsuccessfultasks. We identified an unsuccessful task by a missingsuccessful unit-test run in the unit-test log. Hence,we removed also incomplete tasks, because these missa successful unit-test run, too. After the removal ofunsuccessful tasks, we removed outliers, that is, de-velopment times that deviate more than 1.5 standarddeviations from the mean. Eventually, we got 67 and71 results which we considered for the final analysis.

Figures 1 and 2 present the development timesgrouped by tool support and programming experi-ence. We applied a two-way ANOVA [1] on the re-sults of each task, with the independent variable SSCsupport and the confounding variable programmingexperience as the two factors. For Task 1, the groupswith SSC support were faster than the groups with-out SSC support. The significance test shows a sig-nificant e↵ect of the variable SSC support (p < .01).Considering the means, the performance di↵ers for in-experienced participants by 284.3 seconds and for ex-perienced participants by 53.7 seconds. The resultsshow no significant interaction of SSC support andprogramming experience.

For Task 2, the groups with SSC support wereslower than the experienced group without SSC sup-port, but faster than the inexperienced group withoutSSC support. The results of the significance test show

no significant e↵ect of SSC support, but of program-ming experience (p < .05) on the development time.

5 Discussion and Conclusion

For Task 1, support by SSC allowed participants sig-nificant faster adaption of the broken source code to arenamed column in the database schema, regardless oftheir programming experience. Since all participantsattended the introduction, which shares the same ra-tionale with Task 1, we assume that all participantswere equally prepared for Task 1. Thus, we concludethat the SSC improved the participants’ performancewith its ability to mark the Java source code a↵ectedby the refactored database schema. A plain Eclipsedoes not provide such information.

SSC support has no significant influence on Task 2.However, programming experience shows a significante↵ect on Task 2. The e↵ect of programming expe-rience is independent of SSC support. For Task 2,participants had to adapt the Java source code to amoved column in the database schema. Therefore,the participants had to move specific methods froma source to a target Java class. However, SCC onlyhighlights the a↵ected methods in the source class,but not the target Java class. Thus, participants withSSC support were forced to find a way to complete theadaption without SSC. We assume that experiencedusers were faster to find the target class, irrespectiveof SCC support. One possible reason for the betterperformance of experienced participants could be theability of experienced users to faster adapt to the un-known code base.

The results of Task 1 suggest that SSC can im-prove the performance of developers adapting Javasource code to a database refactoring. However, asthe results of Task 2 suggest, advantages of SSC maybe diminished by an incomplete support of di↵erentrefactoring tasks. However, supporting Task 2 canbe achieved by exposing features that exist in SSC,but not in its Eclipse plug-in used in the experiment.Thus, in our future work, we will focus on integratingmore features of SCC into its Eclipse plug-in and onthe evaluation of di↵erent refactoring scenarios.

References

[1] G. Casella. Statistical Design. Springer-VerlagNew York, 2008.

[2] J. Feigenspan, C. Kastner, J. Liebig, S. Apel,S. Hanenberg, and K. Christian. Measuring Pro-gramming Experience. IEEE International Con-

ference on Program Comprehension, pages 73–82,2012.

[3] H. Schink. Sql-Schema-Comparer: Supportof Multi-Language Refactoring with RelationalDatabases. International Working Conference on

Source Code Analysis and Manipulation, pages164–169, 2013.

Page 22: 18. Workshop Software-Reengineering und -Evolution · Software-Reengineering ... a tool that measures code metrics and also outputs results on maintainability. These quantitative

Developer Experience with the Django Web Framework

(Extended Abstract)

Frederik Rüther Hakan Aksu Ralf LämmelSoftware Languages Team, University of Koblenz-Landau

Abstract

Web frameworks involve many aspects, e.g., forms,model, testing, and migration. Developers differ interms of their per-aspect experience. We describe amethodology for the identification of relevant aspectsof a web app framework, measurement of experienceatoms per developer and per aspect based on the com-mit history of actual projects, and the compilationof developer profiles for summarizing the relevance ofdifferent aspects and the developers’ contribution tothe project. Measurement relies on a rule-based lan-guage. Our case study is concerned with the Python-based Django web app framework and the open sourceDjango-Oscar project from which experience atomswere extracted.

1 Motivation

A typical scrum team consists of developers, a scrummaster, a product owner, and yet others. One of thetypical tasks of a product owner is to organize theproduct backlog which may also include bugs. A taskof the product owner is to assign bugs to persons.Finding suitable persons may be challenging for largeteams with significant fluctuation. Our approach mayrecommend a developer for the assignment based onthe analyzed experience. We assume that necessaryexperience can also be extracted from bug reports andassociated files by essentially the same method. Weapply our approach in a case study to the Django appframework and to the Django-Oscar project on Githubfrom which experience atoms are extracted.

2 Experience atoms

The key idea is to rank developers in terms of aspectsbased on their past commit activities. Experience ismeasured in experience atoms per aspect. We rely onthe following definition [2]: “Experience atoms are el-ementary units of experience. Experience, we assume,is the direct result of a persons activity with respectto a work product, enhancing it or fixing a problem.The smallest meaningful unit of such changes is anexperience atom.”

The process of finding aspects is based on two steps.First, a suitable documentation such as a tutorial

Figure 1: Classification of aspects of experience inDjango projects

(e.g., the Django tutorial1 in the case study) is usedas input; a list of mentioned classes, directories, andfiles is aggregated, subject to a threshold for inclu-sion. Second, all the imports from the project underinvestigation are collected. The list of imports is usedto identify widely used aspects that are not part ofthe documentation from the first step. Both lists arecombined and names are assigned to the items; seeFig. 1 for the result.

3 Rule-based detection

The analysis of a project is based on rules. A rulecan be described as a function that maps source codechanges along commits to identified experience atoms.Such functions are composed from filters operating atdifferent source-code levels and operations that com-bine Boolean values and numbers of experience atoms.

There exist four main filters:

FilenameFilter a condition on the filename ofchanged file.

DirectoryFilter a condition on the directory of achanged file.

1https://docs.djangoproject.com/en/1.9/intro/tutorial01/

Page 23: 18. Workshop Software-Reengineering und -Evolution · Software-Reengineering ... a tool that measures code metrics and also outputs results on maintainability. These quantitative

TextFilter a condition on the text-level content of achanged file.

TreeFilter a condition on the parse tree-level con-tent of a changed file. For instance, one maysearch for specific methods or classes for the sakeof detecting experience atoms for aspects.

Those filters can be combined with the help of op-erations ‘and’, ‘or’, and ‘implies’. Here is an examplefor a rule that uses two filters:

Other/KnowledgeManagement:DirectoryFilter("docs") orFilenameFilter("ReadMe.md")

This rule identifies the aspects KnowledgeManage-

ment if a commit took place in the docs folder or achanged file has the name ReadMe.md. The filters arecombined with an or operation since both operationsindicate that the person has performed a task relatedto knowledge management. The number of changedlines are to be counted as experience atoms.

A recurring detection scenario is that an aspect isassociated with inheritance from a certain frameworkclass. To this end, we leverage a SuperClassFilterwhich is derived from the basic filter TreeFilter andchecks for a specific superclass. For instance:

Model/Data:TextFilter("import django.db.Model") impliesSuperClassFilter("Model")

In this rule, we also check that a specific namespacewas imported to avoid confusion of the Model classwith one from another library.

Aspect Category Count Unit %VCS Administration 134 file 88

HTML Forms 1205 class 55Validation Other 10 function 11

Model Forms 1827 class 54BuildM. Administration 300 file 66

DjangoConfig. Other 3005 file 88Fixture Database 4923 file 92

Templates Other 27140 count 42Django Test 12703 class 72

AdminInterface Model 770 class 82Migration Database 58 class 14Generell Test 16091 file 67

Data Model 20683 class 61KnowledgeM. Other 4962 file 57

Figure 2: Experience of David Winterbottom in theDjango-Oscar project. The last column shows the percent-age of the experience for an aspect in the project. Theunits ‘file’, ‘class’, and ‘function’ refer to the number ofchanged lines in the corresponding scope; the unit ‘count’refers to the number of matches in the changed lines.

4 Developer profile

Fig. 2 shows the experience of the developer with themost commits in the Django project of our case study.While he collected usually the most experience atoms,there are three aspects where he does not own over50 %, namely Templates, Migration, and Validation.

This observation gives insight into the collaborationand the division of responsibilities in the project.

5 Related work

Our work on rule-based detection of experience as-pects (‘skills’) is inspired, for example, by previouswork of Teyton et al. [4]. In this work, skills relatedto Java development, e.g., development of JUnit tests,are analyzed also with the help of a rule-based lan-guage and also based on analyzing the commit history.No general classification of experience aspects is de-veloped though; this work was targeted at industrialcase studies that were using the Java platform.

Matter et al. [1] assign bugs to developers by thesimilarity of the vocabulary in their produced sourcecode and the bug description. Nguyen et al. [3] trackbug reports through their lifecycle. Based on suchhistorical data, a recommendation of a developer fora future assignment is provided. Our approach intro-duces explicitly a high level of abstraction in termsof an up-front classification of experience, subject torule-based detection.

6 Conclusion

Let us return to the motivating scenario on bug as-signment. Given relatively dominant developers suchas David Winterbottom in our case study, it may bean obvious choice to assign ‘all’ bugs to these domina-tors. Obviously, such a naive approach does not scale.In the interest of a division of work, the developerprofiles are to be used to find the ‘next best’ assign-ment, i.e., someone who is sufficiently experienced andavailable overall. Further, the developer profiles alsoreveal aspects (for dominant developers or otherwise)for which other developers would be more ‘qualified’(more experienced) anyhow.

In future work, we plan to validate our approachin terms of the feasibility and accuracy of assigningdevelopers to bugs. For instance, we would like tocompare suggestions based on our approach with someavailable ground truth based on project history.

References

[1] Dominique Matter, Adrian Kuhn, and Oscar Nier-strasz. Assigning Bug Reports Using a Vocabulary-based Expertise Model of Developers. In Proc. MSR

2009. IEEE Computer Society, 2009.[2] Audris Mockus and James D. Herbsleb. Expertise

browser: a quantitative approach to identifying exper-tise. In Proc. ICSE 2002, pages 503–512. ACM, 2002.

[3] Tung Thanh Nguyen, Tien N. Nguyen, EvelynDuesterwald, Tim Klinger, and Peter Santhanam. In-ferring developer expertise through defect analysis. InProc. ICSE 2012, pages 1297–1300. IEEE, 2012.

[4] Cédric Teyton, Marc Palyart, Jean-Rémy Falleri,Floréal Morandat, and Xavier Blanc. Automatic ex-traction of developer expertise. In Proc. EASE 2014,pages 8:1–8:10. ACM, 2014.

Page 24: 18. Workshop Software-Reengineering und -Evolution · Software-Reengineering ... a tool that measures code metrics and also outputs results on maintainability. These quantitative

Similarity management of ‘cloned and owned’ variants

(Extended Abstract)

Thomas Schmorleiz Ralf Lämmel

Software Languages Team, University of Koblenz-Landau

Abstract

The ‘clone and own’ approach to software productlines assumes that variants are created by cloning andevolve more or less independently afterwards. We re-search the process to manage similarity of such ‘clonedand owned’ variants along the timeline. The processuses annotations for recording developer intentionsand it leverages automatic change propagation. Wehave applied the process and corresponding tool sup-port in a case study where we manage similarity forclowned-and-owned Haskell-based variants of a simplehuman-resources management system.

1 Introduction

The discipline of clone management studies detection,avoidance, and removal of clones as well as compen-sating activities. For instance, such compensationhelps in the context of the ‘clone-and-own’ approachto managing software variants [7, 8, 4, 1]; the ap-proach is widely established in industry for reasonssuch as developer independence [8, 2]. In our ap-proach, we address the clone-and-own approach bya combination of variability and clone managementwhich we refer to as similarity management. We treatthe variants as a cloning genealogy [5, 9]. Clone de-tection is performed at a granularity level of ‘frag-ments’ by which we mean named abstractions such asmethods or functions. Similarity measures for source-code files, folders, and variants enable exploration ofsimilarity at different levels and, ultimately, similarityimprovement. The developer must decide whether afound similarity is to be maintained or improved. Inthe first case, we speak of a maintenance invariant ;in the second case of a maintenance task.

Summary of the research a) We introduce sim-ilarity measures and classifiers to capture similarityand evolution thereof across clowned-and-owned vari-ants. b) We present a process for similarity manage-ment with activities for analyzing, annotating, main-taining, and improving similarities. c) We devise des-ignated tool support. d) We present a first case studyon similarity management.

All tools and artifacts underlying the case study as

⇤The full paper appeared in the proceedings of SAC 2016.

well as the full paper are available online1.

Research question How to measure similarity ofclowned-and-owned variants and effects of similarity im-provement in a useful manner?

One can define similarity at the fragment-level insome standard way using algorithms such as longestcommon subsequence or Levenshtein distance. How-ever, we seek a deeper understanding of similarity in-cluding the development of fragment sharing on thetime line. We answer the question by researching met-rics such as the number of distinct fragments acrossall variants and the number of variants a fragment isshared in.

2 A process for similarity management

Analysis An automated analysis is applied to thecommit history of given variants, thereby determin-ing how fragment-level similarities evolved over time.For instance, a similarity may be identified as hav-ing ‘diverged from equality’. The same analysis isapplied incrementally whenever the developer makeslocal changes or pulls new versions.

Review Subject to interactive tool support, the de-veloper reviews similarity evolutions sorted by de-creasing similarity measures, i.e., equalities show upat the top. Similarities that are seen as adequate maybe tagged to be taken as invariants such as ‘MaintainEquality’. Similarities that have evolved unreasonablymay be acted upon as follows.

Improvement Option 1: The developer suggestsautomated change propagation to make two fragmentsthe same again. As a side effect, the resulting frag-ment equality is tagged as an invariant that is tobe maintained. Option 2: The developer manually

changes the involved fragments to increase similarity,thereby, again, implicitly tagging the result as an in-variant. Option 3: The developer defers the change,

but tags the similarity evolution at hand with a main-tenance task for a due improvement such as ‘IncreaseSimilarity’.

Reestablishment Subject to interactive tool sup-port, the developer is notified of invariants that have

1http://softlang.uni-koblenz.de/simman

Page 25: 18. Workshop Software-Reengineering und -Evolution · Software-Reengineering ... a tool that measures code metrics and also outputs results on maintainability. These quantitative

Figure 1: Force-driven layout of the variants in the case study: proximity correlates with degree of similarity.

been broken by local or pulled changes, thereby en-couraging the developer to reestablish these invariantsby means of improvement, as discussed before, or topossibly abandon them.

Committal The developer commits the local ver-sion also including the annotations for invariants orpending maintenance tasks. Thereby, developers canmanage similarity collaboratively.

3 Case study

We manage similarity for 101haskell [6] which is aset of 36 Haskell-based variants of a small human-resources management system; 101haskell is part ofthe 101companies chrestomathy [3]. Fig. 1 visual-izes the similarity of the variants in the case studybased on the aggregation of fragment-level similari-ties to the variant level. We dealt with a commithistory with 961 versions, developed over 42 months.We made 345 annotations triggering 448 maintenancetasks: 324 automated and 124 manual changes. Pro-cess execution required only a few hours of systematicwork. Similarity improvement would have been verytedious and time-consuming without the process anddesignated tool support. Also, the established main-tenance invariants help maintaining similarity in thefuture while also relying on change propagation.

References

[1] Michal Antkiewicz, Wenbin Ji, Thorsten Berger,Krzysztof Czarnecki, Thomas Schmorleiz, Ralf Läm-mel, Stefan Stanciulescu, Andrzej Wasowski, and InaSchaefer. Flexible product line engineering with a vir-tual platform. In Proc. of ICSE 2014, pages 532–535.ACM, 2014.

[2] Yael Dubinsky, Julia Rubin, Thorsten Berger, Sla-womir Duszynski, Martin Becker, and Krzysztof Czar-necki. An exploratory study of cloning in industrialsoftware product lines. In Proc. of CSMR 2013, pages25–34. IEEE, 2013.

[3] Jean-Marie Favre, Ralf Lämmel, Thomas Schmorleiz,and Andrei Varanovich. 101companies: A Commu-nity Project on Software Technologies and SoftwareLanguages. In Proc. of TOOLS 2012, pages 58–74.Springer, 2012.

[4] Stefan Fischer, Lukas Linsbauer, Roberto Erick Lopez-Herrejon, and Alexander Egyed. Enhancing clone-and-own with systematic reuse for developing software vari-ants. In Proc. of ICSME 2014, pages 391–400. IEEE,2014.

[5] Miryung Kim and David Notkin. Using a clone ge-nealogy extractor for understanding and supportingevolution of code clones. ACM SIGSOFT SoftwareEngineering Notes, 30(4):1–5, 2005.

[6] Ralf Lämmel, Thomas Schmorleiz, and Andrei Vara-novich. The 101haskell chrestomathy: A whole bunchof learnable lambdas. In Proc. of IFL 2013, pages25:25–25:36. ACM, 2014.

[7] Julia Rubin and Marsha Chechik. A framework formanaging cloned product variants. In Proc. of ICSE2013, pages 1233–1236. IEEE, 2013.

[8] Julia Rubin, Krzysztof Czarnecki, and MarshaChechik. Managing cloned variants: A framework andexperience. In Proc. of SPLC 2013, pages 101–110.ACM, 2013.

[9] Shuai Xie, Foutse Khomh, and Ying Zou. An empiri-cal study of the fault-proneness of clone mutation andclone migration. In Proc. of MSR 2013, pages 149–158.IEEE Press, 2013.

Page 26: 18. Workshop Software-Reengineering und -Evolution · Software-Reengineering ... a tool that measures code metrics and also outputs results on maintainability. These quantitative

Interprocedural PDG-based Code Clone Detection

Torsten Görg University of Stuttgart

Universitätsstr. 38, 70569 Stuttgart, Germany [email protected]

Abstract: This paper suggests a PDG-based code clone detection algorithm that handles procedure calls with summary information about the called procedures in order to improve the precision of the detection results.

1 Introduction One possible approach for code clone detection is using PDGs (Program Dependency Graphs) as intermediate representation [1]. In contrast to other program representations like token streams or abstract syntax trees, PDGs provide a clone detection that is more closely related to the semantics of the analyzed program and provides more precise results. For each clone pair candidate, our approach compares two graph backward slices in the PDGs to decide about the clone property. This reduces clone detection to a graph reachability problem with additional equivalence constraints. Our goal is to detect any PDG subgraph matches even if a subgraph is in the middle of a procedure’s PDG. Because of the runtime complexibility of PDG-based clone detection that is generally cubic in the total number of nodes in all PDGs, in the worst case, one has to handle performance aspects carefully. Especially interprocedurality might threaten an acceptable performance. When the slice matching process reaches procedure call nodes and the called procedure is the same for both slices, the procedure call nodes are obviously equivalent. The case when different procedures are called is more complicated. Conservatively, a procedure call matches any other call, producing many false positives. The opposite rejects any calls of different procedures, resulting in false negatives. A more precise implementation could dive into the details of the called procedures and try to match their bodies for each call. As a procedure is usually called from multiple call sites it would be analyzed repetitively. In the worst case, exponentially many repetitions would be necessary. To avoid this complexity, we calculate summaries instead, following the idea introduced by Reps, Horwitz, and Binkley [2] for interprocedural slicing. They suggest to calculate summary edges that indicate the set of procedure input parameters a procedure

output value is possibly dependent on. Our first approach was to implement exactly this in our clone detector. It models reads and writes on global variables and reference parameters as well as return values as artificial parameters in the intermediate representation. For matching two procedure call nodes that reference different procedures, it looks up the summary edges of these procedures and tries to match the resulting sets of dependencies. The problem with this approach is that it does not provide any information how to map dependencies in the first set to dependencies in the second set. But this information is crucial to continue the matching process behind the procedure call nodes. As an approximation, the matching might assume that the formal parameters are declared in the same order for both procedures and sacrifice the detectability of parameter reordering. But for reads or global variables, this assumption is unrealistic. Our solution is to calculate clones in two passes. Pass 1 is coarse-grained and finds clones that span procedures from their output to their input. Pass 2 is fine-grained and detects any PDG subgraph matches. Summaries of the procedure clones found in pass 1 are used to facilitate finding further procedure clones in pass 1 as well as fine-grained clones in pass 2.

2 Procedure Clone Summaries More exactly, our procedure clones do not necessarily cover whole procedures. For each discriminable component of all output values of a procedure, a separate backward slice is calculated. We call these slices features. In general, a procedure implements multiple features. I.e., an output value of a record type provides separate features for all record components. The elements of an array are viewed as one component with just one slice. A feature is uniquely characterized by the output value component that spans it. The backward slice of a feature is limited by references to input value components of the procedure that contains the feature. The component granularity of input values is the same as described above for output values. Pass 1 of our clone detection compares each feature with the features of all other procedures. We heuristically assume that a feature is not a clone of

Page 27: 18. Workshop Software-Reengineering und -Evolution · Software-Reengineering ... a tool that measures code metrics and also outputs results on maintainability. These quantitative

another feature of the same procedure. If the slices of two features completely match, a feature clone pair is recognized. During the matching process, irrelevant nodes are skipped wherever possible. The clone detector stores a summary of each detected feature clone pair. Such a summary encompasses references to the output value components that characterize the features and a description of the mapping between corresponding input value components. In comparison to procedure clones that have to cover whole procedures, the feature clones approach is more flexible and provides a higher probability to find clones at that coarse granularity level. Nevertheless, for many software systems, we expect only a small number of feature clones. But for the subsequent fine-grained clone detection in pass 2 not only the recognized feature clones are relevant. The negative information that two features are not in a clone relationship is also useful. It can be used to eliminate clone candidates that call these features.

3 Unification of Clone Parameters A full structural congruence of the slices that represent code fragments is not sufficient to decide about the clone property. Additionally, it has to be checked if corresponding input values are consistently referenced. E.g., x + x * y is congruent with a + b * b but not semantically equivalent. This is exactly the difference between type 2 clones and parameterized clones, as defined by Baker [3]. We have integrated a parameter unification in pass 1 that enforces a bijective mapping between the input value components of the matched code fragments. A weaker but still sufficient check allows us to map an input value component of one fragment to a literal value in the other fragment. E.g., x + 3 * y matches a + b * c, although these fragments are not semantically equivalent. The second fragment is more general than the first. A similar situation is a mapping of some input value components of one fragment with multiple input value components of the other one. E.g., x + y * z matches a + a * a. Here, the first fragment is more general than the second. This kind of clone is called surjective clone, because a surjective mapping between the input value components of both fragments exists.

4 Evaluation As an example, we analyse the program gnuplot_x11 from the gnuplot open-source software package. It consists of 75 procedures. A procedure’s average number of features is 20.1, resulting in #feat = 1570 features overall. The

number of feature clone pair candidates is #cand = 1139859, #cand < #feat2 = 2464900. #cand is less than half of #feat2 because of our exclusion of feature clones within the same procedure. Only 42 feature clone pairs are found. This low number of feature clones confirms our expectation. Furthermore, all detected feature clones are rather small. Except of one clone of size 48, the clones do not encompass more than 7 nodes. To evaluate pass 2 we have compared the clone sizes histograms for fine-grained clones without and with usage of feature clones summaries. The usage of summaries shifts the histogram to smaller clones because more matches of call nodes are excluded. This splits clones into smaller ones.

5 Future Work It could be an appropriate heuristic to assume that features of a procedure p1 are usually not clones of features of a procedure p2 if p1 calls directly or indirectly p2. This constraint can be checked by traversing the call graph in topological order. We have to validate this assumption with further experiments. Our current approach supports the matching of code fragments in situations where procedure call nodes occur in both code fragments in corresponding positions. Another interprocedural situation is matching a procedure call with equivalent inlined program code. To support this kind of clone as well, a more comprehensive preparation phase is required. It is not sufficient to compare feature slices with other feature slices. They have to be compared with slices spanned at arbitrary positions inside of procedures. This can be calculated by another pass before pass 2. It has to be evaluated if it is worth to spent the additional effort in contrast to an implementation that dives into the details of the called procedure in such situations. References [1] Raghavan Komondoor and Susan Horwitz, “Using

Slicing to Identify Duplication in Source Code,” in Proc. of the 8th International Symposium on Static Analysis (SAS ’01), London, UK, Springer-Verlag, 2001.

[2] Thomas Reps, Susan Horwitz, and David Binkley, “Interprocedural slicing of computer programs using dependence graphs,” in Proc. Of the ACM SIGPLAN 1988 conference on Programming language design and implementation (PLDI ’88), New York, NY, USA, ACM, 1988.

[3] Brenda S. Baker, “On finding duplication and near-duplication in large software systems,” in Proc. of the Second Working Conference on Reverse Engineering (WCRE '95),Washington, DC, USA, IEEE, 1995.

Page 28: 18. Workshop Software-Reengineering und -Evolution · Software-Reengineering ... a tool that measures code metrics and also outputs results on maintainability. These quantitative

��

� ��

«neg. test successful»

MontiMatcherSimulink

models (slx)

Test specifications

Create control flow

graph (CFG)

MatlabControl«uses»

Trans-formation to

automata

Microsoft Z3-Solver

«uses»

UnfoldVariables

CUDAdomain calculation

«uses»

Lockingfree ports

AD

CFG slicing at output ports

Clonedetection

SimulationPreorder

Fast-Test forpos. Result

Fast-Test for neg. Result

MinimizingAutomata

«pos. test successful»

CompatibilityCheck automata

CompatibilityStatement

AutomataAbstraction

[not compatible]

CalculateCEGAS metric

[compatible]SimilarityStatement

!!!! """" #### ④

$$$$%%%%&&&&''''

(((( ))))

Page 29: 18. Workshop Software-Reengineering und -Evolution · Software-Reengineering ... a tool that measures code metrics and also outputs results on maintainability. These quantitative

��

�� � �

† ‡ k

† ‡ k

§ ¶ k

k

† ‡ § ¶

� � � ��

Page 30: 18. Workshop Software-Reengineering und -Evolution · Software-Reengineering ... a tool that measures code metrics and also outputs results on maintainability. These quantitative

Toolbasierte Software-Migration nach Plan

Christian Becker, Uwe Kaiserpro et con Innovative Informatikanwendungen GmbH, Dittesstraße 15, 09126 Chemnitz

{christian.becker,uwe.kaiser}@proetcon.de

Abstract

Die Firma proetcon hat aus aktuellen und in der Ver-gangenheit realisierten Migrationsprojekten Erfahrungenzu deren Planung und Ablauf gesammelt. Der vorliegendeBeitrag beschreibt einige dieser Erfahrungen und skizziertden Ablauf von toolbasierten Migrationsprojekten.

1 Projektphasen

Die Realisierung eines Migrationsprojektes erfolgt ana-log zu konventionellen Softwareprojekten in verschiede-nen Phasen. Die nachfolgende Grafik stellt den favorisier-ten Ablauf eines Migrationsprojektes verallgemeinert dar:

Die Phasen müssen für jedes konkrete Migrationsprojektund für jeden Kunden entsprechend der dann vorliegendenAnforderungen angepasst werden. Wesentliche Aspektewie die Erstellung einer Studie, die Realisierung eines Pi-loten oder die paketweise, parallele und iterative Durch-führung der Migration und des Tests sind jedoch für jedesMigrationsprojekt gegeben.

2 Studie

Die erste Phase des Projektes beinhaltet das Anfertigen ei-ner Studie. Wesentlicher Bestandteil ist ein Überblick undein Mengengerüst über alle Artefakte (Masken, Program-me, Jobs, Dateien und Tabellen) und Schnittstellen des Ba-sissystems. Bei diesem Reverse Engineering leisten Ana-lysewerkzeuge einen wesentlichen Beitrag. Sie basierenauf Metawerkzeugen, welche projektspezifische Anpas-sungen der Analysewerkzeuge mit überschaubarem Auf-wand ermöglichen. Ein weiterer Bestandteil der Studie istdie eindeutige Definition des Zielsystems und der Migrati-onspfade, d.h., einer Abbildungsvorschrift zur Umsetzungaller Komponenten aus dem Basissystem in das Zielsys-tem. Daraus lässt sich der zu leistende Aufwand ableiten,um eine existierende Toolbox für die Software-Migrationan die kundenspezifischen Projektanforderungen anzupas-sen. Das Spektrum reicht dabei vom „Nichtstun“ bis zurNeuentwicklung, wobei Erfahrungen zeigen, dass es „fer-tige“ Werkzeuge nicht gibt. Ein gewisser Entwicklungs-aufwand ist immer zu leisten und muss natürlich in dieAufwandabschätzungen für das Gesamtprojekt einfließen.Mit den o.g. Analysewerkzeugen lassen sich auch fein-

granulare Statistiken zum Auftreten und zur Häufigkeitvon Codefragmenten ermitteln, welche für die Migrati-on kritisch sind. Neben diesen teilautomatisierten Ana-lysen sind zielgerichtete und individuelle Interviews mitden Entwicklern sowie die Prüfung der bestehenden Doku-mentation ein unverzichtbarer Bestandteil der Analysepha-se. Aus diesen Informationen lässt sich eine Abschätzungdes personellen und zeitlichen Aufwandes vornehmen un-ter der Voraussetzung, dass die vorhandenen Technologi-en und Werkzeuge zum Einsatz kommen. In dieser Stu-die wird dem Kunden also eine „Hausnummer“ genannt,was das Projekt kostet. Aus diesem Grund ist die Erstel-lung der Studie unverzichtbar, auch wenn bereits alter-native Auswertungen zum Basissystem, z.B. durch einenMitbewerber, existieren. In dessen Abschätzung des Auf-wandes kann die Aufwandersparnis, welche durch die Nut-zung der existierenden Migrationstools erreicht wird, nichtenthalten sein.

3 Pilot

Die nächste Phase beinhaltet die Realisierung eines Pi-loten. Die Ergebnisse der Studie werden an einem Aus-schnitt des Basissystems in Form eines vertikalen Durch-stichs prototypisch evaluiert. Beim Piloten handelt es sichum die Migration eines oder mehrerer vollständiger Ge-schäftsprozesse des Basissystems. Alle Artefakte (Mas-ken, Programme, Jobs und Daten) des Basissystems sindenthalten und können deshalb eigenständig getestet wer-den. In dieser Phase werden bereits vorhandene Lösungs-ansätze evaluiert und an die kundenspezifischen Anforde-rungen angepasst. Aufgrund der frühzeitigen Durchfüh-rung dieser Phase werden ggf. Teile des Piloten manuellumgesetzt, da zu diesem Zeitpunkt noch keine ausreichen-de Werkzeugunterstützung existiert. Das Ergebnis ist ne-ben einem „proof of concept“ auch ein technischer Fahr-plan, der für die gesamte Migration gilt. Der Pilot gibt demKunden einen präzisen Ausblick auf das zukünftige, voll-ständig migrierte Zielsystem und ist somit ein wichtigerBestandteil der Risikoabschätzung. Anhand dieser Infor-mationen kann der Kunde aus technischer Sicht die Ent-scheidung über die Weiterführung des Migrationsprojektestreffen.

4 Preengineering

Eine wesentliche Phase eines Migrationsprojektes betrifftdas so genannte Preengineering. Dieser Begriff fokussiertauf Reengineering-Maßnahmen vor der eigentlichen Mi-gration im Basissystem (Sanieren vor Migrieren). Dazugehören z.B. das Aussortieren ungenutzer Programme undAnpassungen am Sourcecode. Typische Preeengineering-Maßnahmen bei einer Sprachmigration von COBOL nachJava sind z.B. das Ersetzen von nicht migrierbaren „GO

Page 31: 18. Workshop Software-Reengineering und -Evolution · Software-Reengineering ... a tool that measures code metrics and also outputs results on maintainability. These quantitative

TO“-Anweisungen durch äquivalenten COBOL-Code, dieEliminierung von Klonen in COBOL-Datenstrukturen [1]oder die Bereinigung der Speicherform COMP/COMP-3für numerische Variablen in den COBOL-Programmen.Dieses Preengineering setzt eine vollständige Datenfluss-analyse der jeweiligen COBOL-Sourcen voraus. Dabeikommen Analyse- und Konvertierungswerkzeuge zumEinsatz. In Abhängigkeit von der Art und Häufigkeit derzu sanierenden Artefakte kann demnach auch eine auto-matisierte Sanierung vorgenommen werden.Eine weitere Aufgabe ist die Aufteilung des Basissystemsin zu migrierende Pakete. Diese Aufteilung wird auf Ba-sis der toolbasierten Analyse von vertikalen Geschäftspro-zessen (zusammenhängende Komponenten von Jobs, Pro-grammen und Daten) und dem Fachwissen des Kundenvorgenommen. Die Größe der einzelnen Pakete ergibt sichaus den verfügbaren personellen und zeitlichen Ressour-cen. Es hat sich bewährt, bei der Planung ein zusätz-liches Paket für vergessene oder unerwartet aufgetauch-

te Programme einzuplanen. Dieses Paket dient gleichzei-tig als zeitlicher Puffer für zusätzlich anfallende Entwick-lungsaufgaben, welche sich während der Migration erge-ben (können).Parallel dazu erfolgen notwendige Arbeiten wie der Auf-bau der Betriebsumgebung sowie die Realisierung vonBuild-, Deployment- und Testprozessen. Alle in derPreengineering-Phase durchgeführten Maßnahmen dienender Minimierung des Aufwandes folgender Projektphasen.

5 Migration und Integrationstest

Die favorisierte Strategie ist die iterative Migration vonPaketen. Jedes Paket besteht aus einer Menge zusammen-hängender und vollständiger Geschäftsprozesse. Die An-zahl der Iterationen wird mindestens durch die Anzahl derPakete bestimmt, wobei sich die Bearbeitung eines Paketsaus folgenden Schritten zusammensetzt: Vorbereitung, Mi-gration, Komponenten- und Integrationstest. Die folgendeGrafik zeigt die Parallelisierung dieser Schritte:

Im Vorbereitungsschritt erfolgen je nach Projekt und Um-fang abschließende Sanierungsarbeiten und die Bereitstel-lung der zu migrierenden Pakete durch den Kunden. An-schließend beginnen die Migrationsarbeiten. Dabei benö-tigt die Datenmigration im Vergleich zur Programm- undJCL-Migration zeitlichen Vorlauf. Auf Grund des umfang-reichen Datenbestandes ist eine große Varianz in der Da-tenqualität zu erwarten. Deshalb, und da ein migrierterDatenbestand Voraussetzung für nachfolgende Tests ist,wird die vollständige Datenmigration als erstes Paket rea-lisiert. Durch die Werkzeugunterstützung wird ein Auto-matisierungsgrad von mehr als 90% bei der Job- und Pro-grammkonvertierung erreicht. Erfahrungen besagen, dass

Jobs und Programme einen Konvertierungsaufwand ge-mäß der 80:20-Regel erfordern (20% des Aufwands ent-fallen auf 80% der Arbeiten). Manuelle Arbeiten entfal-len z.B. auf die Anbindung neuer Schnittstellen und Da-tenbanken, auf lokale Performanceoptimierungen sowieetwaige Neuentwicklungen von Programmen, welche imBasissystem so „schlecht“ programmiert wurden, dass ei-ne Migration nicht lohnt. Nach der Migration durchläuftjedes Paket den Komponenten- und Integrationstest beiproetcon sowie einen weiteren Integrationstest beim Kun-den. Lokalisierte Fehler bei diesen Tests führen unmittel-bar zur Korrektur der Werkzeuge und zur erneuten Migra-tion. Davon profitieren alle nachfolgenden Pakete. Vor je-der Auslieferung eines neuen Pakets wird ein Gesamttestaller bisher migrierten Pakete mit Hilfe von automatisier-ten Testfällen für Batchprogramme und Tests für Online-programme auf Basis normierter Messages durchgeführt[2]. Das iterative Vorgehen bei der paketweisen Migrationminimiert Codefreezes für den Kunden, da bei Notwen-digkeit Programme in späteren Paketen aufgrund von Feh-lerbeseitigung, Optimierung oder Weiterentwicklung be-liebig oft konvertiert werden können. Grundvoraussetzunghierfür ist ein hohes Maß an Automatisierung in der Pro-grammkonvertierung und die parallele, paketweise Migra-tion. Auf dieses Ziel wird seit der Pilotphase hingearbeitet.

6 System- und Abnahmetest

Es finden die üblichen Testphasen Anwendung. Nach Ab-schluss der Migrationsarbeiten folgen System- und Ab-nahmetests durch den Kunden in eigenständigen Phasen,welche durch besonders kurze Fehlerbehebungs- und Aus-lieferungszyklen unterstützt werden. Es wird eine erneute,vollständige Datenmigration zur Aktualisierung des Da-tenbestandes vor Beginn des Abnahmetests vorgeschlagen.Die Inbetriebnahme erfordert ausgereifte Build- und De-ploymentprozesse inkl. einer Fallbackstrategie.

7 Zusammenfassung

Mehrere, erfolgreich realisierte Migrationsprojekte derVergangenheit führten zur Herausbildung der in diesemBeitrag dokumentierten Vorgehensweise. Zusätzlich ist ei-ne Software-Migration auch immer als gemeinsames Pro-jekt zwischen allen Projektpartnern zu planen und zu reali-sieren. Auch für den Kunden bedeutet ein solches Projekteinen nicht unerheblichen Aufwand, welcher entsprechendzu planen ist. Dieser Aufwand wird jedoch durch eine um-fangreiche Werkzeugunterstützung reduziert.

Literaturverzeichnis

[1] Becker, C.; Kaiser, U.: Applikationswissen in derSprachkonvertierung am Beispiel des COBOL-Java-Converters CoJaC. GI-Softwaretechnik-Trends,Band 34, Heft 2.

[2] Uhlig, D.: Testautomatisierung am Beispieldes COBOL-to-Java-Converters CoJaC. GI-Softwaretechnik-Trends, Band 34, Heft 2.