Angenommen Sie haben einen Cousin in Spanien mit dem Sie regen
Kontakt haben und den Sie auch immer wieder besuchen.
Sie kommen bei einem Besuch in Spanien auf die aktuelle Lage in
seinem Heimatland zu sprechen. Ihr Cousin berichtet über die sehr hohe
Arbeitslosigkeit, insbesondere Jugendarbeitslosigkeit in seinem Land. Er
behauptet, dass Sie dies nicht nachvollziehen könnten, da es in
Deutschland praktisch keine Arbeitslosigkeit gibt. Daheim angekommen
schauen Sie sich die Daten zur Arbeitslosigkeit im Euro-Raum an (was Sie
auch im 2. - 4. RTutor Problem Set machen) und sehen in der Tat, dass
Deutschland eine der niedrigsten Arbeitslosenquoten aller Euro-Länder
hat und Spanien deutlich höhere Arbeitslosenquoten aufweist. Doch hat
ihr Cousin recht, wenn er davon spricht, dass Deutschland keine
Arbeitslosigkeit kennt? Gilt dies für alle Regionen in Deutschland, oder
gibt es auch in Deutschland Regionen mit hohen Arbeitslosenquoten? Wenn
Sie regionale Unterschiede finden, welche Gründe könnte dies haben?
Dem wollen wir in dieser Case-Study auf den Grund gehen.
Ziele der Case Study
Diese Case-Study besteht aus mehreren Teilen und wird Sie durch die
komplette Vorlesung als konkretes Anschauungsobjekt begleiten. Hierbei
dient die Case-Study hauptsächlich dazu, ihnen an einem konkreten und
umfangreichen Beispiel die Kenntnisse für eine erfolgreiche
Projektarbeit zu vermitteln und diese Kenntnisse zu vertiefen. Natürlich
können Sie die Case-Study auch als Referenz heranziehen, wenn Sie ihre
eigene Projektarbeit anfertigen.
Daten beschaffen
Wir wollen uns in dieser Case-Study mit der Pro-Kopf Verschuldung,
der Arbeitslosigkeit und dem BIP in einzelnen Regionen in Deutschland
beschäftigen und hier mögliche regionale Unterschiede aufdecken.
Im Ersten Schritt ist es wichtig sich zu überlegen, woher Sie ihre
Datensätze beziehen. Um makroökonomische Informationen zum BIP oder der
Arbeitslosigkeit zu erhalten empfiehlt es sich immer auf die Seiten des
Statistischen Bundesamtes oder der Bundesagentur für Arbeit zu schauen.
Hier finden Sie z.B. Quartalsinformationen zu BIP und Arbeitslosigkeit
für ganz Deutschland.
In dieser Case-Study wollen wir jedoch etwas feingranularere
Informationen sammeln, und zwar auf Landkreis-, Verwaltungs-, bzw.
Gemeindeebene.
Uns interessieren die Pro-Kopf Verschulung,
Arbeitslosigkeit und das BIP.
Nötige Pakete laden
Bevor wir mit der Analyse starten sollten wir einige Pakete in R
laden, welche wir später verwenden möchten, da sie uns bei der Analyse
unterstützen können. Dies geschieht mit dem library()
Befehl.
(Alternative: Vor jeden Befehl das dazugehörige
Paket schreiben, d.h. statt read_xlsx
könnten wir auch
readxl::read_xlsx
schreiben. Jedoch wollen wir im
Projektkurs immer die Variante mit library()
verwenden.)
library(readxl)
library(tidyverse)
library(skimr)
Daten herunterladen
Mit den Befehlen aus dem readxl
und readr
Paketen könnten Sie direkt URLs einlesen, wenn sich dahinter Text,- bzw.
Excel Datei verbergen, was bei uns der Fall ist. Allerdings sollten wir
davon nur selten Gebrauch machen, denn es könnte immer sein das die
Daten im Internet modifiziert oder unter der vorherigen URL nicht mehr
auffindbar sind. Daher wollen wir die gewünschten Daten, welche wir zur
Analyse benötigen, immer in einem Unterordner data
abspeichern und dann aus diesem Ordner einlesen. So stellen wir sicher,
dass wir immer auf die Daten zurückgreifen können, auch wenn diese aus
dem Netz gelöscht oder modifiziert werden.
Daten können innerhalb von R mit dem Befehl
download.file()
heruntergeladen werden:
# Zuerst sollten Sie prüfen ob der Unterordner "data" bereits bei ihnen exisitert, und falls er nicht existiert sollten Sie diesen erstellen.
# Dies können Sie beispielsweise mit dem folgenden Befehl machen, wenn der Ordner schon existiert wird eine Warnmeldung ausgegeben:
dir.create(file.path(".", "data"))
## Warning in dir.create(file.path(".", "data")): './data' existiert bereits
# Durch die if-Bedingung prüfen Sie, ob die Datei bereits im "data"-Ordner vorhanden ist
# Die neuesten Daten zur Verschuldung auf Landkreisebene stammen aus dem Jahr 2021
if (!file.exists("./data/Schulden_2021.xlsx")){
download.file("https://www.statistikportal.de/sites/default/files/2022-11/Integrierte_Schulden_der_Gemeinden_und_Gemeindeverbaende_2022_Tabellenband.xlsx", "./data/Schulden_2021.xlsx")
}
# Arbeitslose aus dem Jahr 2021
#Zu finden unter: https://statistik.arbeitsagentur.de/SiteGlobals/Forms/Suche/Einzelheftsuche_Formular.html?topic_f=gemeinde-arbeitslose-quoten
if (!file.exists("./data/Arbeitslose_2021.xlsx.zip")){
download.file("https://statistik.arbeitsagentur.de/Statistikdaten/Detail/202112/iiia4/gemeinde-arbeitslose-quoten/arbeitslose-quoten-dlk-0-202112-zip.zip?__blob=publicationFile&v=1", "./data/Arbeitslose_2021.xlsx.zip")
}
# Link für die aktuellen Daten zur Arbeitslosigkeit: https://statistik.arbeitsagentur.de/Statistikdaten/Detail/Aktuell/iiia4/gemeinde-arbeitslose-quoten/arbeitslose-quoten-dlk-0-zip.zip
# BIP pro Gemeinde aus dem Jahr 2022
if (!file.exists("./data/BIP_2022.xlsx")){
download.file("https://www.statistikportal.de/sites/default/files/2023-07/vgrdl_r2b1_bs2022.xlsx", "./data/BIP_2022.xlsx")
}
Die Daten zur Verschuldung wollen wir unter “Schulden_2021.xlsx”, da
die Tabelle zwar in 2022 generiert wurde, sich aber auf das Jahr 2021
bezieht.
Die if
-Bedingung prüft ob der angegebene Datensatz
bereits in unserem “data” Ordner enthalten ist. Wenn dies der Fall ist,
so werden sie nicht mehr erneut heruntergeladen.
Wir haben hier auch die Daten für die Arbeitslosenquote aus dem Jahr
2021 heruntergeladen, da wir die passenden Informationen zur Pro-Kopf
Verschuldung der Gemeinden aus nur aus dem Jahr 2021
online erhalten. Die Daten zur Verschuldung werden alle 4 Jahre vom
Statistischen Bundesamt aktualisiert.
Ich habe ihnen die Links zum neueren Datensätzen für die
Arbeitslosigkeit in den R Chunk geschrieben. Für das BIP haben wir die
neueste Datenreihe von August 2022 bezogen da wir hier Paneldaten haben
und keine Querschnittsdaten (was dies genau heißt wird im Laufe der
Case-Study erläutert).
Daten einlesen
Im nächsten Schritt sollten wir die Daten in R einlesen. Beim
Download haben wir schon an den URLs und auch an den heruntergeladenen
Dateien gesehen, dass es sich bei zwei Downloads um ZIP-Archive (BIP und
Anzahl an Arbeitslosen) handelt. Diese ZIP-Archive können wir mittels R
extrahieren, diese anschließend einlesen und die extrahierte Datei
wieder löschen. Dies hat den Vorteil, dass Sie ihre Dateien platzsparend
auf ihrer Festplatte abspeichern und nur bei Bedarf entsprechend
entpacken.
Anzahl an Arbeitslosen
Im ersten Schritt wollen wir uns mit den Daten zu den Arbeitslosen
beschäftigen und die in dem ZIP-Archiv enthaltenen Dateien in R
einlesen.
ZIP-Archiv entpacken
# Öffnen des ZIP-Archivs
# Es sind zwei Tabellen in dem ZIP Archiv, wir interessieren uns für die Anzahl der Arbeitslosen und wählen diese mit dem kleinen [1] aus
alo_name <- as.character(unzip("./data/Arbeitslose_2021.xlsx.zip", list = TRUE)$Name)
alo_name <- alo_name[1]
unzip("./data/Arbeitslose_2021.xlsx.zip", alo_name)
Ok, nun haben wir die Daten entzipped und sehen, dass es sich um eine
Excel-Datei handelt. Doch diese hat sehr viele unterschiedliche
Tabellenblätter. Wie wissen wir, welches Tabellenblatt für uns von
Interesse ist?
Dies können wir zum Einen mit excel_sheets
herausfinden,
wenn die Tabellenblätter gut benannt sind:
excel_sheets(alo_name)
## [1] "Deckblatt" "Impressum" "Inhaltsverzeichnis"
## [4] "Übersicht_Kreise" "Gesamt" "SGB_III"
## [7] "SGB_II" "Männer" "Frauen"
## [10] "Deutsche" "Ausländer" "AGR15u25"
## [13] "AGR55plus" "AGR55u65" "Langzeitarbeitslos"
## [16] "schwerbehindert" "Hinweis_Alo_Asu" "Statistik-Infoseite"
Da die Tabellenblätter jedoch nicht unbedingt vielsagend beschriftet
sind sollten wir das Tabellenblatt “Inhalt” einlesen und uns dieses
anschauen. Eventuell werden wir hier schlauer.
alo_inhalt <- read_xlsx(alo_name, sheet = "Inhaltsverzeichnis")
head(alo_inhalt, 15)
## # A tibble: 15 × 1
## Inhaltsverzeichnis
## <chr>
## 1 <NA>
## 2 <NA>
## 3 Arbeitslose - Zeitreihe
## 4 <NA>
## 5 <NA>
## 6 Tabelle
## 7 Bestand an Arbeitslosen
## 8 Kreiszusammenfassung
## 9 Übersicht nach Kreisen
## 10 <NA>
## 11 Insgesamt
## 12 Rechtskreis
## 13 SGB III
## 14 SGB II
## 15 Geschlecht
Hier erhalten wir einen Überblick über die Tabellenblätter und wo
welche Informationen abgespeichert sind. Da wir uns für den Bestand an
Arbeitslosen interessieren und hier nicht nach Frauen und Männern
unterscheiden möchten, ist das Tabellenblatt Gesamt
für uns
das richtige.
Alternative: Schauen Sie sich die Excel-Datei in
Excel oder LibreOffice an und entscheiden Sie dann, welches
Tabellenblatt Sie einlesen möchten.
Entpackte Datei einlesen
Nun wissen wir, welches Tabellenblatt die für uns wichtige
Information enthält:
alo <- read_xlsx(alo_name, sheet="Gesamt")
head(alo,10)
## # A tibble: 10 × 27
## ...1 ...2 ...3 ...4 ...5 ...6 ...7 ...8 ...9 ...10 ...11 ...12 ...13
## <chr> <chr> <chr> <chr> <chr> <chr> <chr> <chr> <chr> <chr> <chr> <chr> <chr>
## 1 <NA> <NA> <NA> <NA> <NA> <NA> <NA> <NA> <NA> <NA> <NA> <NA> <NA>
## 2 Best… <NA> <NA> <NA> <NA> <NA> <NA> <NA> <NA> <NA> <NA> <NA> <NA>
## 3 Länd… <NA> <NA> <NA> <NA> <NA> <NA> <NA> <NA> <NA> <NA> <NA> <NA>
## 4 Zeit… <NA> <NA> <NA> <NA> <NA> <NA> <NA> <NA> <NA> <NA> <NA> <NA>
## 5 Rech… <NA> <NA> <NA> <NA> <NA> <NA> <NA> <NA> <NA> <NA> <NA> <NA>
## 6 <NA> <NA> <NA> <NA> <NA> <NA> <NA> <NA> <NA> <NA> <NA> <NA> <NA>
## 7 <NA> <NA> <NA> Aus … <NA> <NA> <NA> <NA> <NA> <NA> <NA> <NA> <NA>
## 8 <NA> Jahr… <NA> Rech… <NA> <NA> <NA> <NA> <NA> <NA> <NA> <NA> <NA>
## 9 <NA> Jahr… Jahr… 43831 43862 43891 43922 43952 43983 44013 44044 44075 44105
## 10 Regi… 2020 2021 1 2 3 4 5 6 7 8 9 10
## # ℹ 14 more variables: ...14 <chr>, ...15 <chr>, ...16 <chr>, ...17 <chr>,
## # ...18 <chr>, ...19 <chr>, ...20 <chr>, ...21 <chr>, ...22 <chr>,
## # ...23 <chr>, ...24 <chr>, ...25 <chr>, ...26 <chr>,
## # Arbeitsmarktstatistik <chr>
Ok. Hier ist es wohl nicht vorteilhaft von der ersten Zeile ab die
Informationen aus dem Tabellenblatt einzulesen. So wie es aussieht sind
in den ersten 5 Zeilen Informationen zum Tabellenblatt und dem
Berichtsjahr enthalten, dann kommt eine leere Zeile und dann kommen die
eigentlichen Spaltenbeschriftungen. Diese sind dann jedoch wiederum in 4
Zeilen unterteilt. Was sind denn hier nun die Spaltenüberschriften, d.h.
die Variablennamen im Datensatz?
Spezifizieren welche Spalten eingelesen werden sollen
Hierzu überlegen wir uns folgendes:
In unserem Fall benötigen wir die Information zur durchschnittlichen
Anzahl aller Arbeitslosen pro Gemeinde aus dem Jahr 2021, d.h. uns
interessiert Spalte ...3
. Weiterhin benötigen wir eine
eindeutig zuzuordenden “Gemeinde-ID” um diese Datenquelle später mit
anderen Datenquellen verbinden zu können. Außerdem wäre der Name der
Gemeinde noch eine wichtig Information. Der einfachste Weg an diese
Information zu gelangen ist die ersten acht Zeilen abzuschneiden und die
Daten erst ab dort einzulesen. Anschließend behalten wir nur die ersten
3 Spalten, da uns nur diese interessieren.
Das wollen wir nun machen:
# Daten einlesen von Tabellenblatt "Gesamt", ohne die ersten 8 Zeilen
alo <- read_xlsx(alo_name, sheet = "Gesamt", skip = 8)
# Die entzippte Datei wieder löschen
unlink(alo_name)
# Nun beschränken wir uns auf die erste und dritte Spalte und trennen den Namen der Region (welcher in Spalte `...1` gelistet wird) und deren "Gemeinde-ID", dem sogenannten "Regionalschluessel" voneinander.
# Die Spalte 3 wollen wir anschließend in "alo" umbenennen
# Weiterhin löschen wir alle Zeilen, für die "alo" auf NA gesetzt ist und die erste Zeile, die alle Arbeitslosen in ganz Deutschland beinhaltet
# Wir speichern den Datensatz als `data_alo` ab
data_alo <- alo %>%
select(c(`...1`, Jahresdurchschnitte, `...3`)) %>%
mutate(Regionalschluessel = str_extract(`...1`, "[[:digit:]]+"),
Gemeinde = str_extract(`...1`, "[A-Z].*")) %>%
mutate(alo = as.numeric(`...3`)) %>%
select(-c(`...1`, Jahresdurchschnitte, `...3`)) %>%
filter(!is.na(alo))
## Warning: There was 1 warning in `mutate()`.
## ℹ In argument: `alo = as.numeric(...3)`.
## Caused by warning:
## ! NAs durch Umwandlung erzeugt
# Die ersten drei Zeilen beinhalten keine nutzlichen Informationen, d.h. wir löschen diese
data_alo <- data_alo[-c(1,2),]
Konsistenzcheck
Nun sollten wir noch die Daten auf Konsistenz prüfen. D.h. machen die
Angaben Sinn und sind die Daten in sich konsistent? Hierfür sollten wir
zum Einen externe Datenquellen untersuchen und zum Anderen die Daten
intern prüfen.
Wir haben hier sehr feingranulare Informationen über die
Arbeitslosenzahl in 2021 vorliegen, jedoch können wir die Daten auch auf
eine höhere Ebene aggregieren und damit leicht mit anderen Quellen
vergleichen. Dies wollen wir hier tun:
- Zunächst lassen wir uns die Anzahl an Arbeitslosen für jedes
Bundesland in 2021 ausgeben. In unserem Datensatz sind dies alle
Datenpunkte mit einem zweistelligen
Regionalschluessel
. Wir
müssen hier beachten, dass die Regionalschluessel
in der
Klasse character
vorliegen, d.h. als Strings und nicht als
Zahl. Deshalb können wir die Anzahl an “Buchstaben” für jeden
Regionalschluessel
zählen. Dies geschieht über den Befehl
nchar()
(number of characters)
- Nun sollten wir eine andere Datenquelle heranziehen und die
Informationen gegenchecken. Bspw. könnten wir die
Anzahl der Arbeitslosen für das Jahr 2021 unterteilt nach Ländern
heranziehen. (Tabellenblatt 8)
check_alo_bundesland <- data_alo %>%
filter(nchar(Regionalschluessel) == 2) %>%
rename(bundesland = Regionalschluessel)
check_alo_bundesland
## # A tibble: 16 × 3
## bundesland Gemeinde alo
## <chr> <chr> <dbl>
## 1 01 Schleswig-Holstein 88865.
## 2 02 Hamburg 80395.
## 3 03 Niedersachsen 243021.
## 4 04 Bremen 39292.
## 5 05 Nordrhein-Westfalen 718220.
## 6 06 Hessen 178086.
## 7 07 Rheinland-Pfalz 112137.
## 8 08 Baden-Württemberg 247774.
## 9 09 Bayern 262186.
## 10 10 Saarland 36156.
## 11 11 Berlin 198401.
## 12 12 Brandenburg 78463.
## 13 13 Mecklenburg-Vorpommern 62410.
## 14 14 Sachsen 124743.
## 15 15 Sachsen-Anhalt 81093.
## 16 16 Thüringen 62249.
Wenn wir die Überprüfung mit der anderen Tabelle der Bundesagentur
für Arbeit machen, dann sind beide Datenreihen identisch.
Nun wollen wir noch die interne Konsistenz überprüfen. Hierfür
berechnen wir die Anzahl an Arbeitslosen für jedes Bundesland als Summe
der Arbeitslosen einer jeden Gemeinde.
# Nur Gemeindedaten nutzen, dann auf Bundeslandebende die Summe aus den Gemeindedaten berechnen
alo_meta <- data_alo %>%
filter(nchar(Regionalschluessel) == 8) %>%
mutate(landkreis = str_extract(Regionalschluessel, "^.{5}"),
bundesland = str_extract(Regionalschluessel, "^.{2}"))
alo_bundesland <- alo_meta %>%
group_by(bundesland) %>%
summarise(total_alo = sum(as.numeric(alo)))
alo_landkreis <- alo_meta %>%
group_by(landkreis) %>%
summarise(total_alo = sum(alo)) %>%
rename(Regionalschluessel = landkreis)
Um einen besseren Überblick zu erhalten können wir unsere berechneten
und die von der Agentur für Arbeit angegebenen Werte miteinander
verbinden und die Differenz zwischen den beiden Tabellen berechnen:
check_consitency <- left_join(check_alo_bundesland, alo_bundesland, by = "bundesland")
check_consitency <- check_consitency %>%
mutate(diff = alo - total_alo)
check_consitency
## # A tibble: 16 × 5
## bundesland Gemeinde alo total_alo diff
## <chr> <chr> <dbl> <dbl> <dbl>
## 1 01 Schleswig-Holstein 88865. 88865. 0
## 2 02 Hamburg 80395. 80395. 0
## 3 03 Niedersachsen 243021. 243021. 0
## 4 04 Bremen 39292. 39292. 0
## 5 05 Nordrhein-Westfalen 718220. 718220. 0
## 6 06 Hessen 178086. 178086. 0
## 7 07 Rheinland-Pfalz 112137. 112137. 0
## 8 08 Baden-Württemberg 247774. 247774. 0
## 9 09 Bayern 262186. 262186. 0
## 10 10 Saarland 36156. 36156. 0
## 11 11 Berlin 198401. 198401. 0
## 12 12 Brandenburg 78463. 78463. 0
## 13 13 Mecklenburg-Vorpommern 62410. 62410. 0
## 14 14 Sachsen 124743. 124743. 0
## 15 15 Sachsen-Anhalt 81093. 81093. 0
## 16 16 Thüringen 62249. 62249. 0
Unsere Analysen zeigen, dass es keine Differenzen zwischen den Daten
gibt, die von der Bundesagentur für Arbeit auf Landes- und Bundesebene
veröffentlichen.
Pro-Kopf Verschuldung
Der nächste Datensatz beinhaltet die Pro-Kopf-Verschuldung der
deutschen Gemeinden. Hier handelt es sich wieder um Querschnittsdaten
auf Gemeindeebene aus dem Jahr 2017.
Diesen Datensatz können wir von der Homepage des Statistischen
Bundesamtes direkt als Excel-Tabelle herunterladen und müssen kein
ZIP-Archiv entpacken. Allerdings sehen wir sehr schnell, das auch dieser
Datensatz seine Tücken beim Einlesen bereithält, insbesondere wenn wir
schauen, welche Tabellenblätter für unsere Analyse relevant sind:
excel_sheets("./data/Schulden_2021.xlsx")
## [1] "Titel" "Impressum" "Inhalt"
## [4] "Abkürzungen" "Erläuterungen" "SH"
## [7] "NI" "NW" "HE"
## [10] "RP" "BW" "BY"
## [13] "SL" "BB" "MV"
## [16] "SN" "ST" "TH"
## [19] "Statistische Ämter"
Mehrere Tabellenblätter einlesen
Nun sind nicht mehr alle Informationen in einem
Tabellenblatt enthalten, sondern jedes Bundesland hat sein
eigenes Tabellenblatt bekommen. Sprich, wir müssen eine Möglichkeit
finden alle Tabellenblätter nacheinander einzulesen und zu
verarbeiten.
Dies wollen wir mit einer for
-Schleife lösen, doch
zuerst schauen wir uns an, welche Informationen wir aus den
Tabellenblättern benötigen:
sh <- read_xlsx("./data/Schulden_2021.xlsx", sheet = "SH")
head(sh,20)
## # A tibble: 20 × 21
## `Zurück zum Inhalt...1` ...2 ...3 ...4 ...5 ...6 ...7 ...8 ...9 ...10
## <chr> <chr> <chr> <chr> <chr> <chr> <chr> <chr> <chr> <chr>
## 1 <NA> <NA> <NA> <NA> <NA> <NA> <NA> <NA> <NA> <NA>
## 2 <NA> <NA> <NA> <NA> <NA> <NA> <NA> <NA> <NA> <NA>
## 3 "Tabelle 1: Schulde… <NA> <NA> <NA> <NA> <NA> <NA> <NA> <NA> <NA>
## 4 "nach Höhe der Beteili… <NA> <NA> <NA> <NA> <NA> <NA> <NA> <NA> <NA>
## 5 "Regional-\r\nschlüsse… Geme… Verw… "Ein… Schu… Verä… "Sch… Schu… <NA> <NA>
## 6 <NA> <NA> <NA> <NA> <NA> <NA> <NA> zusa… Verä… Schu…
## 7 <NA> <NA> <NA> <NA> <NA> <NA> <NA> <NA> <NA> <NA>
## 8 <NA> <NA> <NA> <NA> <NA> <NA> <NA> <NA> <NA> <NA>
## 9 <NA> <NA> <NA> <NA> EUR % "EUR" <NA> % EUR
## 10 <NA> <NA> <NA> <NA> 1 2 "3" 4 5 6
## 11 "010010000000" Flen… krei… "899… 4545… 0 "505… 2310… -9.5 4625…
## 12 "010020000000" Kiel… krei… "245… 1039… 6.1 "422… 5534… 6.7 5531…
## 13 "010030000000" Lübe… krei… "215… 1090… 1.2 "507… 4305… -5.9 4256…
## 14 "010040000000" Neum… krei… "796… 4532… 5.2 "568… 1141… 10.6 1029…
## 15 "01051" Krei… Krei… "{13… 4296… -14.8 "322… 1954… -20.7 1952…
## 16 "010510011011" Brun… amts… "123… 5464… 0.5 "443… 2206… 0 1994…
## 17 "010510044044" Heid… amts… "215… 4285… -5.4 "199… 2508… -9.6 2146…
## 18 "010515163" Amts… Amts… "{15… 8503… -4.2 "54.… 8503… -4.2 8302…
## 19 "010515163003" Aver… amts… "554" 1917… 13.6 "346… 1300… 10.1… 5971…
## 20 "010515163010" Bric… amts… "200" 1176… 22 "588… 8898… 17 1865…
## # ℹ 11 more variables: ...11 <chr>, ...12 <chr>, ...13 <chr>, ...14 <chr>,
## # ...15 <chr>, ...16 <chr>, ...17 <chr>, ...18 <chr>, ...19 <chr>,
## # `Zurück zum Inhalt...20` <chr>, ...21 <chr>
Für uns wichtig sind die Infos bzgl. des “Regionalschlüssels”, der
“Gemeindename”, die “Einwohner” und die “Schulden des öffentlichen
Bereichs insgesamt”. Zur Überprüfung unserer Ergebnisse nehmen wir noch
die “Schulden je Einwohner” mit in unseren Datensatz auf, d.h. die
ersten sechs Spalten. Weiterhin stehen unsere Variablenbezeichnungen in
Zeile 5, d.h. wir ignorieren die ersten 4 Zeilen beim Einlesen.
Der Übersicht halber wollen wir noch eine Spalte hinzufügen, welche
den Namen des Tabellenblattes enthält, welches wir gerade eingelesen
haben.
# Einlesen des Tabellenblattes "SH" ohne die ersten 5 Zeilen und nur die Spalten 1-7
schulden_individuell <- read_xlsx("./data/Schulden_2021.xlsx", sheet = "SH", skip = 5)[1:7]
# Umbenennen der ersten 7 Spalten
colnames(schulden_individuell) <- c("Regionalschluessel", "Gemeinde",
"Verwaltungsform", "Einwohner", "Schulden_gesamt", "Veraenderung_Vorjahr", "Schulden_pro_kopf")
# Zusätzliche Spalte hinzufügen mit dem Namen des Tabellenblattes
schulden_individuell$Bundesland <- "SH"
Ok, nun haben wir die Daten für Schleswig-Holstein eingelesen und
können mit einer for
-Schleife alle weiteren Bundesländer
(Tabellenblätter) in der gleichen Form durchgehen:
# Daten mit for-Schleife einlesen (Struktur gleich wie im vorherigen Chunk)
sheet_names <- excel_sheets("./data/Schulden_2021.xlsx")
# Einlesen der Tabellenblätter 7-18 (alle Bundesländer)
sheet_read <- sheet_names[7:18]
for (i in 1:length(sheet_read)){
tmp <- read_xlsx("./data/Schulden_2021.xlsx", sheet = sheet_read[i], skip = 5)[1:7]
tmp$Bundesland <- sheet_read[i]
colnames(tmp) <- c("Regionalschluessel", "Gemeinde", "Verwaltungsform",
"Einwohner", "Schulden_gesamt", "Veraenderung_Vorjahr", "Schulden_pro_kopf", "Bundesland")
# Daten aller weiteren Tabellenblätter unter den aktuellen Datensatz anheften
schulden_individuell <- bind_rows(schulden_individuell, tmp)
}
Variablen umformen
head(schulden_individuell,30)
## # A tibble: 30 × 8
## Regionalschluessel Gemeinde Verwaltungsform Einwohner Schulden_gesamt
## <chr> <chr> <chr> <chr> <chr>
## 1 <NA> <NA> <NA> <NA> <NA>
## 2 <NA> <NA> <NA> <NA> <NA>
## 3 <NA> <NA> <NA> <NA> <NA>
## 4 <NA> <NA> <NA> <NA> EUR
## 5 <NA> <NA> <NA> <NA> 1
## 6 010010000000 Flensburg, Stadt kreisfreie Sta… 89949 454539445.9700…
## 7 010020000000 Kiel, Landeshau… kreisfreie Sta… 245841 1039095143.430…
## 8 010030000000 Lübeck, Hansest… kreisfreie Sta… 215051 1090890891.450…
## 9 010040000000 Neumünster, Sta… kreisfreie Sta… 79683 453215674.2999…
## 10 01051 Kreisverwaltung… Kreisverwaltung {133 401} 42967438.62000…
## # ℹ 20 more rows
## # ℹ 3 more variables: Veraenderung_Vorjahr <chr>, Schulden_pro_kopf <chr>,
## # Bundesland <chr>
Wir sehen, es gibt immer noch einige Probleme:
Die Werte unserer Variablen stehen nicht direkt unter dem
Variablennamen, das ist für uns nicht optimal und ist der Anordnung in
der Excel Datei geschuldet.
- Dies können wir am einfachsten bereinigen indem wir alle
NA
s im Regionalschlüssel entfernen (kein Regionalschlüssel
bedeutet keine Zuordnung zu einer Region und damit für uns nicht
nachvollziehbar).
Die Variablen “Einwohner”, “Schulden_gesamt” und
“Schulden_pro_Kopf” sind alle als character
hinterlegt
(<chr>
unter dem Variablennamen in der vorherigen
Tabelle), wir wollen diese jedoch in numerischer Form um Berechnungen
durchführen zu können
- Der Grund für die Klasse
character
kann z.B. in Zeile
28 beobachtet werden. Hier wurden geschweifte Klammern verwendet um die
Summe aller Variablen eines Amtsgebiets, Landkreis, Region etc. zu
kennzeichnen.
- Im ersten Schritt wollen wir diese Summen einfach ignorieren da wir
die jeweiligen Summen auch selbst berechnen können.
Die “Veraenderung_Vorjahr” ist für unsere weitere Analyse nicht
relevant, daher wollen wir diese aus dem Datensatz entfernen
Anschließend wollen wir noch den landkreis
als die
ersten 5 Zeichen im Regionalschlüssel definieren.
# Die Daten wurden noch nicht schön eingelesen, in der Excel Tabelle
# waren die Variablennamen über mehrere Reihen gezogen, dies müssen wir noch ausgleichen
schulden_bereinigt <- schulden_individuell %>%
filter(!is.na(Regionalschluessel)) %>%
mutate(Schulden_gesamt = as.numeric(Schulden_gesamt),
Einwohner = as.numeric(Einwohner),
Schulden_pro_kopf = as.numeric(Schulden_pro_kopf)) %>%
mutate(landkreis = str_extract(Regionalschluessel, "^.{5}")) %>%
#manche Landkreise haben keine Infos zu den Einwohnern, diese entfernen wir
filter( !is.na( Einwohner )) %>%
select(-Veraenderung_Vorjahr)
Es wurden immer noch einige NA
s erzeugt. Diese wollen
wir uns noch näher anschauen:
filter(schulden_bereinigt, is.na(Einwohner))
## # A tibble: 0 × 8
## # ℹ 8 variables: Regionalschluessel <chr>, Gemeinde <chr>,
## # Verwaltungsform <chr>, Einwohner <dbl>, Schulden_gesamt <dbl>,
## # Schulden_pro_kopf <dbl>, Bundesland <chr>, landkreis <chr>
Wir müssen wohl noch mehr ausschließen als nur NA
s beim
Regionalschlüssel, insgesamt 2400 Einträge bei denen die Variable
“Einwohner” nicht vorhanden ist. Wir hatten bereits gesehen, dass die
Summe aller Einwohner eines Landkreisen mit { Zahl }
in der
Excel-Datei hervorgehoben wird. Wenn wir hier in R eine Typumwandlung
erzwingen, dann kann R mit den {}
nichts anfangen und gibt
uns deshalb ein NA
aus. Wir können hier alle Einträge, bei
denen die Einwohner ein NA
stehen haben, löschen, da wir
die Daten selbst auf Basis der Informationen zu den Gemeinden des
Landkreises berechnen können.
schulden_bereinigt <- schulden_bereinigt %>%
filter( !is.na( Einwohner ) )
Konsistenzcheck
Berechnung der Schulden pro Kopf von Hand
Um die interne Validität unserer Daten beurteilen zu können wollen
wir im ersten Schritt eine Variable Schulden_pro_Kopf_new
generieren, welche die Schulden_pro_Kopf
von Hand
berechnet. Wie schon im Abschnitt
Variablen umformen erwähnt, müssen wir hierfür jedoch erst folgendes
beachten, bevor wir Berechnungen durchführen können:
- Wir müssen die geschweiften Klammern entfernen (mit
str_remove_all
), als auch die Leerzeichen innerhalb der
Zahlen (z.B. 15 653), was wir mit gsub("[[:space:]]")
erreichen. Tun wir das nicht, so würden wir wieder NA
s im
Datensatz erhalten.
- Durch die ifelse Bedingung wird der Befehl
str_remove_all
nur angewendet, wenn tatsächlich geschweifte
Klammern vorhanden sind
# Erstellen der Vergleichstabelle
schulden_consistency <- schulden_individuell %>%
filter( !is.na(Einwohner) & !is.na(Regionalschluessel) ) %>%
mutate(Schulden_gesamt = ifelse(is.na(as.numeric(Schulden_gesamt))==TRUE,
as.numeric(gsub("[[:space:]]", "", str_remove_all(Schulden_gesamt, "[{}]"))),
as.numeric(Schulden_gesamt)),
Schulden_pro_kopf = ifelse(is.na(as.numeric(Schulden_pro_kopf))==TRUE,
as.numeric(gsub("[[:space:]]", "", str_remove_all(Schulden_pro_kopf, "[{}]"))),
as.numeric(Schulden_pro_kopf)),
Einwohner_num = ifelse(is.na(as.numeric(Einwohner))==TRUE,
as.numeric(gsub("[[:space:]]", "", str_remove_all(Einwohner, "[{}]"))),
as.numeric(Einwohner)),
Schulden_pro_kopf_new = round(Schulden_gesamt / Einwohner_num,2)) %>%
mutate(landkreis = str_extract(Regionalschluessel, "^.{5}"),
differenz = Schulden_pro_kopf - Schulden_pro_kopf_new)
Nun können wir uns anschauen, ob die von uns berechneten und die vom
Statistischen Bundesamt angegebenen Werte zu den “Schulden_pro_Kopf”
signifikant voneinander abweichen:
# range(schulden_consistency$differenz)
# oder schöne skim
skim_without_charts(schulden_consistency$differenz)
Data summary
Name |
schulden_consistency$diff… |
Number of rows |
13114 |
Number of columns |
1 |
_______________________ |
|
Column type frequency: |
|
numeric |
1 |
________________________ |
|
Group variables |
None |
Variable type: numeric
data |
0 |
1 |
0 |
0.09 |
-0.49 |
0 |
0 |
0 |
0.5 |
Die Differenzen liegen zwischen +/- 50 Cent und können vermutlich auf
Rundungsfehler zurückgeführt werden. D.h. hier können wir die vom
statistischen Bundesamt herausgegebenen Berechnungen auf Gemeindeebene
verifizieren.
Vergleich der Schulden pro Kopf auf Landkreisebene
In einem weiteren Konsistenzcheck wollen wir die durchschnittliche
Verschuldung pro Kopf auf Landkreisebene selbst berechnen und diese mit
den vom Statistischen Bundesamt angegebenen Werten in der Tabelle
abgleichen.
Hierfür entnehmen wir der Tabelle zuerst alle Informationen bzgl.
Anzahl der “Einwohner”, “Schulden_gesamt” und “Schulden_pro_Kopf” für
die Landkreise. Im Datensatz sehen wir, dass die Regionalschluessel für
Landkreise die Worte “Summe” und “Kreis” enthalten, wenn das
Statistische Bundesamt die Daten auf Landkreisebene aggregiert. Das
wollen wir im folgenden nutzen:
# Wir filtern alle Reihen heraus, welche "_Summe" oder "Kreis" im Regionalschlüssel aufweisen
# Anschließend berechnen wir die durchschnittliche Verschuldung auf Landkreisebene
avg_versch_kreis <- schulden_consistency %>%
filter(str_detect(Regionalschluessel, "_Summe") & str_detect(Regionalschluessel, "Kreis")) %>%
group_by(landkreis, Gemeinde) %>%
summarise(avg_verschuldung = Schulden_pro_kopf, einwohner = Einwohner_num,
Gesamtschuld = Schulden_gesamt) %>%
arrange(desc(avg_verschuldung))
# Hier berechnen wir die Daten selbst
avg_versch_kreis_calc <- schulden_consistency %>%
# Ersetze Einwohner_num mit 0 für alle Regionalschlüssel kleiner als 12
mutate(Einwohner_num = ifelse(nchar(Regionalschluessel)<12,0, Einwohner_num)) %>%
# Nur Gemeinden betrachten
filter(nchar(Regionalschluessel)>=5 & str_detect(Regionalschluessel, "_Summe")==FALSE) %>%
# Auf Landkreisebene gruppieren
group_by(landkreis) %>%
summarise(einwohner_calc = sum(Einwohner_num), Gesamtschuld_calc = sum(Schulden_gesamt),
avg_verschuldung_calc = round(Gesamtschuld_calc/einwohner_calc,2)) %>%
arrange(desc(avg_verschuldung_calc))
# Verbinde beide Datensätze und berechne ob es siginfikante Abweichungen zwischen
# den ausgegebenen und berechneten Werten gibt
new <- left_join(avg_versch_kreis, avg_versch_kreis_calc, by="landkreis") %>%
mutate(differenz = avg_verschuldung - avg_verschuldung_calc) %>%
arrange( desc(differenz) )
# Ergebnis anschauen
#range(new$differenz)
# oder mit skim
skim_without_charts(new$differenz)
Data summary
Name |
new$differenz |
Number of rows |
294 |
Number of columns |
1 |
_______________________ |
|
Column type frequency: |
|
numeric |
1 |
________________________ |
|
Group variables |
None |
Variable type: numeric
data |
0 |
1 |
-0.52 |
9.01 |
-154.44 |
-0.26 |
0 |
0.27 |
0.5 |
Die Differenzen liegen hier zwischen -154,44 Euro bis +0,50 Euro (im
Durchschnitt bei -0,52 Euro) und können vermutlich auf Rundungsfehler
zurückgeführt werden. D.h. hier können wir die vom statistischen
Bundesamt herausgegebenen Berechnungen auf Landkreisebene verifizieren.
Der Landkreis Lüchow-Dannenberg bildet eine Ausnahme mit -154,44
Euro.
Bruttoinlandsprodukt
Im nächsten Schritt wollen wir uns die Daten zum Bruttoinlandsprodukt
einzelner Landkreise anschauen und diese in R einlesen. Wir haben diese
direkt als Excel Datei heruntergeladen und können die Datei direkt in R
einlesen. Neben dem BIP beziehen wir aus diesem Excel-File die Anzahl an
Erwerbstätigen, mit denen wir später die Arbeitslosenquote berechnen
können und die Anzahl an Einwohner, mit denen wir das BIP-pro-Kopf
berechnen können.
Nur einzelne Spalten einlesen
Folgende Schritte wollen wir in einem Chunk erledigen:
Betrachten der Daten
- Tabellenblatt “1.1” ist für unsere Analyse ausschlaggebend (für das
BIP)
- Tabellenblatt “3.1” ist für die Anzahl an Erwerbstätigen
ausschlaggebend
- Tabellenblatt “5” ist für die Anzahl an Einwohnern
ausschlaggebend
Die ersten vier Zeilen benötigen wir nicht
Die letzte Zeile enthält eine kurze Beschreibung die wir nicht
benötigen -> Vorgehen: Behalte alle Zeilen, bei der
Lfd. Nr.
numerisch ist
Die folgenden Variablen benötigen wir nicht für unsere Analyse
und können entfernt werden: Lfd. Nr.
, EU-Code
,
NUTS 1
, NUTS 2
, NUTS 3
,
Land
, Gebietseinheit
# Blatt 1.1 einlesen und die ersten 4 Zeilen skippen
bip_name <- "./data/BIP_2022.xlsx"
bip <- read_xlsx(bip_name, sheet="1.1", skip = 4)
erwerb <- read_xlsx(bip_name, sheet="3.1", skip = 4)
einwohner <- read_xlsx(bip_name, sheet = "5", skip = 4)
# Zeile löschen in der die `Lfd. Nr.` nicht nummerisch ist
# Zusätzliche Spalten löschen
bip_wide <- bip %>%
filter(is.na(as.numeric(`Lfd. Nr.`))==FALSE) %>%
select(-c(`Lfd. Nr.`, `EU-Code`, `NUTS 1`, `NUTS 2`, `NUTS 3`, Land, Gebietseinheit)) %>%
rename(Regionalschluessel = `Regional-schlüssel`)
# Zeile löschen in der die `Lfd. Nr.` nicht nummerisch ist
# Zusätzliche Spalten löschen
erwerb_wide <- erwerb %>%
filter(is.na(as.numeric(`Lfd. Nr.`))==FALSE) %>%
select(-c(`Lfd. Nr.`, `EU-Code`, `NUTS 1`, `NUTS 2`, `NUTS 3`, Land, Gebietseinheit)) %>%
rename(Regionalschluessel = `Regional-schlüssel`)
einwohner_wide <- einwohner %>%
filter(is.na(as.numeric(`Lfd. Nr.`))==FALSE) %>%
select(-c(`Lfd. Nr.`, `EU-Code`, `NUTS 1`, `NUTS 2`, `NUTS 3`, Land, Gebietseinheit)) %>%
rename(Regionalschluessel = `Regional-schlüssel`)
head(bip_wide)
## # A tibble: 6 × 30
## Regionalschluessel `1992` `1994` `1995` `1996` `1997` `1998` `1999` `2000`
## <chr> <chr> <chr> <chr> <chr> <chr> <chr> <chr> <dbl>
## 1 08 255866.41… 26264… 27174… 27677… 28219… 29109… 30072… 3.09e5
## 2 081 110977.071 11160… 11528… 11678… 12086… 12384… 12779… 1.30e5
## 3 08111 32946.883… 31736… 32281… 32802… 34339… 33553… 35048… 3.53e4
## 4 08115 12090.93 11833… 11937… 12097… 13919… 13679… 14424… 1.39e4
## 5 08116 12275.605 12482… 12748… 13169… 13284… 13952… 14192… 1.44e4
## 6 08117 5062.0370… 5180.… 5447.… 5643.… 5667.… 5838.… 5920.… 6.00e3
## # ℹ 21 more variables: `2001` <dbl>, `2002` <dbl>, `2003` <dbl>, `2004` <dbl>,
## # `2005` <dbl>, `2006` <dbl>, `2007` <dbl>, `2008` <dbl>, `2009` <dbl>,
## # `2010` <dbl>, `2011` <dbl>, `2012` <dbl>, `2013` <dbl>, `2014` <dbl>,
## # `2015` <dbl>, `2016` <dbl>, `2017` <dbl>, `2018` <dbl>, `2019` <dbl>,
## # `2020` <dbl>, `2021` <dbl>
Dieser Datensatz ist ein sogenanntes Panel. In den vorherigen
Datensätzen zur Anzahl der Arbeitslosen und der Pro-Kopf-Verschuldung
hatten wir Querschnittsdaten (d.h. Daten nur das Jahr 2021) gegeben. Nun
haben wir die Entwicklung des BIP, die Anzahl an Erwerbstätigen und die
Anzahl an Einwohnern seit 1992 bis 2021 für alle Landkreise in
Deutschland.
Daten in das long
-Format überführen
Allerdings sind die Datensätze im wide
-Format, d.h.
nicht tidy
und damit nicht so, wie wir ihn gerne hätten.
Erinnern wir uns noch an die Bedingungen damit ein Datensätzen
tidy
ist?
Im nächsten Schritt wollen wir den Datensatz nun ins
long
-Format überführen und nutzen hierfür die Funktion
pivot_longer
:
bip_long <- pivot_longer(bip_wide, cols = c("1992":"2021") , names_to = "Jahr", values_to = "BIP")
# Produziert den folgenden Fehler:
# Fehler: Can't combine `1992` <character> and `2000` <double>.
Leider ist es hier nicht möglich die Datensätze direkt in das
long
-Format zu überführen, insbesondere da die Klassen der
Variablen 1992 bis 1999 character
sind und ab 2000 dann
double
. Dies sagt uns die erscheinende Fehlermeldung:
Fehler: Can’t combine 1992
and
2000
.
Da wir wissen, dass das BIP, die Anzahl an Erwerbstätigen und die
Anzahl an Einwohnern normalerweise numerisch wiedergegeben wird, ist
wohl die Klasse double
korrekt und wir sollten die Spalten
von 1992 bis 1999 entsprechend umformatieren.
#BIP von 1992 - 1999 umformen (als numerische Variable)
bip_double <- bip_wide %>%
select(`1992`:`1999`) %>%
mutate_if(is.character, as.double)
# Erwerbstätige von 1992 - 1999 umformen (als numerische Variable)
erwerb_double <- erwerb_wide %>%
select(`1992`:`1999`) %>%
mutate_if(is.character, as.double)
# Einwohner von 1992 - 1999 umformen (als numerische Variable)
einwohner_double <- einwohner_wide %>%
select(`1992`:`1999`) %>%
mutate_if(is.character, as.double)
Wir bekommen hier eine Warnmeldung das NA
s bei der
Umwandlung erzeugt wurden. Derartige Warnungen sollten wir beachten und
auf den Grund gehen. Nur so wissen wir, ob die Warnung für uns später
unbeabsichtigte Auswirkungen hat.
Hierfür verbinden wir den neuen Datensatz bip_double
mit
unserem bisher bestehenden bip_wide
und betrachten die
Spalten in denen bip_double
NA
s enthält:
bip_wide_test <- bip_wide %>%
bind_cols(bip_double)
head(filter(bip_wide_test, is.na(`1992...31`)))
## # A tibble: 6 × 37
## Regionalschluessel `1992...2` `1994...3` `1995...4` `1996...5` `1997...6`
## <chr> <chr> <chr> <chr> <chr> <chr>
## 1 13003 . . . . .
## 2 13004 . . . . .
## 3 13071 . . . . .
## 4 13072 . . . . .
## 5 13073 . . . . .
## 6 13074 . . . . .
## # ℹ 31 more variables: `1998...7` <chr>, `1999...8` <chr>, `2000` <dbl>,
## # `2001` <dbl>, `2002` <dbl>, `2003` <dbl>, `2004` <dbl>, `2005` <dbl>,
## # `2006` <dbl>, `2007` <dbl>, `2008` <dbl>, `2009` <dbl>, `2010` <dbl>,
## # `2011` <dbl>, `2012` <dbl>, `2013` <dbl>, `2014` <dbl>, `2015` <dbl>,
## # `2016` <dbl>, `2017` <dbl>, `2018` <dbl>, `2019` <dbl>, `2020` <dbl>,
## # `2021` <dbl>, `1992...31` <dbl>, `1994...32` <dbl>, `1995...33` <dbl>,
## # `1996...34` <dbl>, `1997...35` <dbl>, `1998...36` <dbl>, …
Hier sehen wir bereits warum die Klasse der Variablen
1992
bis 1999
character
war und
nicht double
. Für diese Jahre gab es für einige Regionen
(Mecklenburg-Vorpommern und Niedersachen) keine Angaben zum BIP, den
Erwerbstätigen oder den Einwohnern und daher wurden in der Excel Tabelle
-
eingefügt. Daher ist für uns die Umwandlung zu
NA
folgerichtig und wir können die Warnmeldung ignorieren
und nur die transformierten Variablen mit der Klasse double
verwenden:
bip_wide <- bip_wide %>%
select(-(`1992`:`1999`)) %>%
bind_cols(bip_double)
erwerb_wide <- erwerb_wide %>%
select(-(`1992`:`1999`)) %>%
bind_cols(erwerb_double)
einwohner_wide <- einwohner_wide %>%
select(-(`1992`:`1999`)) %>%
bind_cols(einwohner_double)
Nun können wir den Datensatz ins long
-Format
transferieren und nach dem Jahr sortieren. Da die Einwohner und
Erwerbstätigen in 1000 Personen angegeben sind multiplizieren wir unsere
Erwerbstätigen und Einwohner mit 1000. Das BIP ist in 1 Mio. Euro
angegeben, daher die Multiplikation mit 1 Mio.:
# BIP ins long-Format
bip_long <- pivot_longer(bip_wide, cols = c("2000":"1999") , names_to = "Jahr", values_to = "bip") %>%
mutate( Jahr = as.numeric(Jahr),
bip = bip * 1000000) %>%
arrange( Jahr )
# Anzahl der Erwerbstätigen ins long-Format
erwerb_long <- pivot_longer(erwerb_wide, cols = c("2000":"1999") , names_to = "Jahr", values_to = "erw") %>%
mutate( Jahr = as.numeric(Jahr),
erw = erw * 1000) %>%
arrange( Jahr )
# Anzahl der Einwohner ins long-Format
einwohner_long <- pivot_longer(einwohner_wide, cols = c("2000":"1999") , names_to = "Jahr", values_to = "einwohner") %>%
mutate( Jahr = as.numeric(Jahr),
einwohner = einwohner * 1000) %>%
arrange( Jahr )
Konsistenzchecks
Wir haben bereits in dem Abschnitt “Pro-Kopf Verschuldung” die
Einwohner zur Berechnung der Pro-Kopf-Verschuldung für 2021 eingelesen.
Für eine längerfristige Betrachtung konnten wir nun mit dem BIP
Datensatz die Anzahl der Einwohner von 1992 bis 2021 einlesen. In diesem
Konsistenzcheck wollen wir untersuchen ob die Anzahl der Einwohner aus
beiden Datenquellen in 2021 identisch ist. Hierbei ist es natürlich
wichtig, wann die Daten zur Einwohnerzahl erhoben wurden und deshalb
könnten diese auch geringfügig abweichen. Aber dem gehen wir nun auf den
Grund:
schulden_check <- schulden_bereinigt %>%
group_by(landkreis) %>%
summarise( Schulden_pro_kopf_lk = sum(Schulden_gesamt)/sum(Einwohner), Einwohner = sum(Einwohner), Schulden_gesamt = sum(Schulden_gesamt)) %>%
rename(Regionalschluessel = landkreis)
einwohner_check <- left_join(schulden_check, filter(einwohner_long, Jahr == 2021), by=c("Regionalschluessel")) %>%
mutate(diff = Einwohner - einwohner) %>%
arrange(desc(diff))
skim_without_charts(einwohner_check$diff)
Data summary
Name |
einwohner_check$diff |
Number of rows |
396 |
Number of columns |
1 |
_______________________ |
|
Column type frequency: |
|
numeric |
1 |
________________________ |
|
Group variables |
None |
Variable type: numeric
data |
0 |
1 |
-30.9 |
2045.41 |
-6498 |
-194 |
-51 |
68 |
38719 |
head(arrange(einwohner_check, -diff),20)
## # A tibble: 20 × 7
## Regionalschluessel Schulden_pro_kopf_lk Einwohner Schulden_gesamt Jahr
## <chr> <dbl> <dbl> <dbl> <dbl>
## 1 16063 3005. 159507 479301801. 2021
## 2 16066 2520. 123603 311417890. 2021
## 3 16072 3246. 56792 184342541. 2021
## 4 16054 3887. 36182 140637349. 2021
## 5 03453 1229. 175106 215124067. 2021
## 6 07131 1664. 130836 217753384. 2021
## 7 08315 2229. 266344 593631714. 2021
## 8 03458 644. 132650 85434739. 2021
## 9 08125 1209. 347729 420368560. 2021
## 10 01055 2405. 202229 486299418. 2021
## 11 03454 880. 330545 290945029. 2021
## 12 03451 882. 126437 111561230. 2021
## 13 09564 7243. 513452 3718958718. 2021
## 14 01054 3206. 167710 537632139. 2021
## 15 13073 3052. 225994 689657051. 2021
## 16 01060 1943. 279547 543143122. 2021
## 17 09779 1115. 134941 150404373. 2021
## 18 09776 3376. 82492 278533668. 2021
## 19 08317 2654. 433807 1151535035. 2021
## 20 03353 416. 257024 106920639. 2021
## # ℹ 2 more variables: einwohner <dbl>, diff <dbl>
Die Differenz liegt im Durchschnitt bei 31 Einwohnern, was im
Toleranzbereich bei den großen Städte mit mehr als 120.000 Einwohnern
ist. Der einzige extreme Ausreiser ist der Wartburgkreis. Hier gehen die
Einwohnerzahlen um 38 719 Personen auseinander. Laut Wikipedia
waren die Daten bis 2020 ohne die Kreisfreie Stadt Eisenach. Dadurch gab
es laut Wikipedia einen Sprung von 40 933 Personen, die ab 2021 zu den
Einwohnern gezählt wurden, d.h. die Abweichungen in den Einwohnerzahlen
könnten gut im Zeitpunkt der Erhebung der Einwohnerzahlen begründet
sein. Daher werden wir den Differenzen nicht weiter nachgehen.
Um die langfristigen Entwicklungen des BIP pro Kopf zu visualisieren
werden wir die dazugehörigen Einwohnerzahlen aus der Datenquelle zum BIP
verwenden. Für die Pro-Kopf-Verschuldung jedoch die in der “Integrierten
Schulden der Gemeinden” angegebenen Einwohnerzahl.
Kartenmaterial hinzufügen (optional)
Für eine spätere Visualisierung der Daten mittels einer
Deutschlandkarte sollten wir uns noch Informationen zu den einzelnen
Verwaltunsgrenzen als SHAPE-File herunterladen. Diese Informationen sind
über das OpenData
Portal des Bundesamts für Kartographie und Geodäsie verfügbar.
Die
Dokumentation der Daten sollten wir uns immer zuerst anschauen,
bevor wir die Datenquelle herunterladen. Dies gilt nicht nur für die
Geodaten, sondern allgemein für alle Datenreihen.
Wir extrahieren uns hier die Informationen zu den Grenzen der
Gemeinden, Verwaltungseinheiten, Landkreise und Bundesländer und
speichern diese jeweils entsprechend ab. Um Geometriedaten einzulesen
und diese später schön als Karte darstellen zu können müssen wir hier
die Funktion st_read
aus dem sf
-Paket
verwenden:
Da wir nur die Informationen zur Geometrie, z.B. der Landkreisgrenzen
möchten, können wir die anderen Variablen auch aus dem Datensätz
löschen. Wir behalten den Regionalschlüssel (ARS), den Namen des
Kreises/der Gemeinde (GEN) und die Geometrie (geometry).
Wir müssen uns zusätzlich noch etwas mit der Dokumentation des
Kartenmaterials beschäftigen. Da wir nur die Verwaltungseinheiten ohne
die Nord- und Ostsee und ohne den Bodensee darstellen möchten, so müssen
wir noch auf GF = 4 filtern, wie auf Seite 9 der Dokumentation
beschrieben wird (tun wir dies nicht, so hätten wir die Nordseegebiete
doppelt drin):
Grundsätzlich gilt: Jede Verwaltungseinheit besitzt
genau einen Attributsatz mit dem GF-Wert 4. Zusätzlich kann eine
Verwaltungseinheit einen Attributsatz mit dem GF-Wert 2 besitzen.
# Auf GF == 4 filtern und ARS als String speichern (ist aktuell als factor abgespeichert)
landkreise <- landkreise %>%
filter( GF==4 ) %>%
select(ARS, GEN, geometry) %>%
mutate(Regionalschluessel = as.character(ARS))
gemeinden <- gemeinden %>%
filter( GF==4 ) %>%
select(ARS, GEN, geometry) %>%
mutate(Regionalschluessel = as.character(ARS))
bundesland <- bundesland %>%
filter( GF==4 ) %>%
select(ARS, GEN, geometry) %>%
mutate(Regionalschluessel = as.character(ARS))
Datensätze zusammenführen
In diesem letzten Abschnitt möchten wir alles für die nächsten
Schritte der Case Study vorbereiten. Genauer: Wir wollen nicht nur die
Informationen aus den einzelnen Datensätzen, sondern am Besten einen
kombinierten Datensatz analysieren! Hierfür müssen wir zuerst die
Informationen zur Verschuldung auf Landkreisebene aggregieren und die
Daten zum BIP auf das Jahr 2021 einschränken. Anschließend können wir
die Datensätze anhand des Regionalschlüssels miteinander verbinden.
Weiterhin wollen wir die geografischen Daten separat abspeichern und
bei Bedarf anhand des Regionalschlüssels zu unserem Datensatz
hinzumergen. Der Regionalschlüssel dient uns hierbei als eindeutige
Identifikation der jeweiligen Gemeinde.
# Schulden auf Landkreisebene
schulden_kombi <- schulden_bereinigt %>%
group_by(landkreis) %>%
summarise( Schulden_pro_kopf_lk = sum(Schulden_gesamt)/sum(Einwohner), Einwohner = sum(Einwohner), Schulden_gesamt = sum(Schulden_gesamt)) %>%
rename(Regionalschluessel = landkreis)
# Anzahl an Erwerbstätigen für das Jahr 2021
erwerb_kombi <- erwerb_long %>%
filter(nchar(Regionalschluessel) == 5 & Jahr == 2021) %>%
select(-Jahr)
# Anzahl an Einwohner für das Jahr 2021
einwohner_kombi <- einwohner_long %>%
filter(nchar(Regionalschluessel) == 5 & Jahr == 2021) %>%
select(-Jahr)
# Namen der Landkreise
landkreis_name <- landkreise %>%
st_drop_geometry() %>%
select(-ARS) %>%
mutate(bundesland = str_extract(Regionalschluessel, "^.{2}")) %>%
rename(landkreis_name = GEN)
# Namen der Bundesländer
bundesland_name <- bundesland %>%
st_drop_geometry() %>%
select(-ARS) %>%
rename(bundesland = Regionalschluessel,
bundesland_name = GEN)
# Anzahl der Einwohner mit dem BIP verbinden um das BIP pro Kopf berechnen zu können
bip_zeitreihe <- left_join(bip_long, einwohner_long, by=c("Regionalschluessel", "Jahr")) %>%
mutate(bip_pro_kopf = bip / einwohner)
# BIP auf Landkreisebene im Jahr 2021
bip_kombi <- bip_zeitreihe %>%
filter(nchar(Regionalschluessel) == 5 & Jahr == 2021) %>%
select(-c(Jahr, einwohner))
# Datensätze zusammenführen
# Basisdatensatz -> Arbeitslosenzahlen pro Landkreis
# Name der Landkreise zumergen
daten1 <- left_join(alo_landkreis, landkreis_name, by = "Regionalschluessel")
# Namen der Bundesländer zumergen
daten1 <- daten1 %>% mutate(bundesland = str_extract(Regionalschluessel, "^.{2}"))
daten1 <- left_join(daten1, bundesland_name, by = "bundesland")
# Schulden zumergen
daten2 <- left_join(daten1, schulden_kombi, by = "Regionalschluessel")
# BIP zumergen
daten3 <- left_join(daten2, bip_kombi, by = "Regionalschluessel")
# Zahl der Erwerbstätigen zumergen
gesamtdaten <- left_join(daten3, erwerb_kombi, by = "Regionalschluessel")
saveRDS(gesamtdaten, "./data/gesamtdaten.rds")
saveRDS(schulden_bereinigt, "./data/schulden_bereinigt.rds")
saveRDS(bip_zeitreihe, "./data/bip_zeitreihe.rds")
saveRDS(bundesland, "./data/bundesland.rds")
saveRDS(gemeinden, "./data/gemeinden.rds")
saveRDS(landkreise, "./data/landkreise.rds")
Übungsaufgaben
Laden Sie sich das durchschnittliche Arbeitnehmerentgelt
pro Arbeitnehmer und Landkreis auf der Seite der Statistischen Ämter
des Bundes und der Länder herunter und lesen Sie diesen in R ein.
Finden Sie in dem heruntergeladenen Datensatz heraus, was der
Unterschied zwischen Arbeitnehmerentgelt und Bruttolöhne-
und Gehälter ist.
Lesen Sie die für Sie relevante Tabelle Bruttolöhne- und
Gehälter in R ein.
Bereinigen Sie die Tabelle, d.h. der Datensatz sollte danach
tidy
sein.
Berechnen Sie die Bruttolöhne pro Bundesland mit den Bruttolöhnen
der einzelnen Landkreise als Konsistenzcheck.
Vergleichen Sie ihren Datensatz mit dem auf Github
bereitgestellten Datensatz (“einkommen.rds”). Stimmen diese
überein?
Verbinden Sie die Informationen zu den durchschnittlichen
Einkommen mit dem gesamtdatensatz aus dem vorherigen
Abschnitt.
LS0tCnRpdGxlOiAiQ2FzZSBTdHVkeSBmw7xyIERldXRzY2hsYW5kIgpvdXRwdXQ6IAogIGh0bWxfZG9jdW1lbnQ6CiAgICB0aGVtZTogY29zbW8KICAgIGNvZGVfZG93bmxvYWQ6IHRydWUKICAgIGNvZGVfZm9sZGluZzogaGlkZQogICAgdG9jOiB0cnVlCiAgICB0b2NfZmxvYXQ6IHRydWUKLS0tCgpgYGB7ciBzZXR1cCwgaW5jbHVkZT1GQUxTRX0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KGVjaG8gPSBUUlVFLCBtZXNzYWdlPUZBTFNFKQpgYGAKCkFuZ2Vub21tZW4gU2llIGhhYmVuIGVpbmVuIENvdXNpbiBpbiBTcGFuaWVuIG1pdCBkZW0gU2llIHJlZ2VuIEtvbnRha3QgaGFiZW4gdW5kIGRlbiBTaWUgYXVjaCBpbW1lciB3aWVkZXIgYmVzdWNoZW4uCgpTaWUga29tbWVuIGJlaSBlaW5lbSBCZXN1Y2ggaW4gU3BhbmllbiBhdWYgZGllIGFrdHVlbGxlIExhZ2UgaW4gc2VpbmVtIEhlaW1hdGxhbmQgenUgc3ByZWNoZW4uCklociBDb3VzaW4gYmVyaWNodGV0IMO8YmVyIGRpZSBzZWhyIGhvaGUgQXJiZWl0c2xvc2lna2VpdCwgaW5zYmVzb25kZXJlIEp1Z2VuZGFyYmVpdHNsb3NpZ2tlaXQgaW4gc2VpbmVtIExhbmQuCkVyIGJlaGF1cHRldCwgZGFzcyBTaWUgZGllcyBuaWNodCBuYWNodm9sbHppZWhlbiBrw7ZubnRlbiwgZGEgZXMgaW4gRGV1dHNjaGxhbmQgcHJha3Rpc2NoIGtlaW5lIEFyYmVpdHNsb3NpZ2tlaXQgZ2lidC4KRGFoZWltIGFuZ2Vrb21tZW4gc2NoYXVlbiBTaWUgc2ljaCBkaWUgRGF0ZW4genVyIEFyYmVpdHNsb3NpZ2tlaXQgaW0gRXVyby1SYXVtIGFuICh3YXMgU2llIGF1Y2ggaW0gMi4gLSA0LiBSVHV0b3IgUHJvYmxlbSBTZXQgbWFjaGVuKSB1bmQgc2VoZW4gaW4gZGVyIFRhdCwgZGFzcyBEZXV0c2NobGFuZCBlaW5lIGRlciBuaWVkcmlnc3RlbiBBcmJlaXRzbG9zZW5xdW90ZW4gYWxsZXIgRXVyby1Mw6RuZGVyIGhhdCB1bmQgU3BhbmllbiBkZXV0bGljaCBow7ZoZXJlIEFyYmVpdHNsb3NlbnF1b3RlbiBhdWZ3ZWlzdC4KRG9jaCBoYXQgaWhyIENvdXNpbiByZWNodCwgd2VubiBlciBkYXZvbiBzcHJpY2h0LCBkYXNzIERldXRzY2hsYW5kIGtlaW5lIEFyYmVpdHNsb3NpZ2tlaXQga2VubnQ/CkdpbHQgZGllcyBmw7xyIGFsbGUgUmVnaW9uZW4gaW4gRGV1dHNjaGxhbmQsIG9kZXIgZ2lidCBlcyBhdWNoIGluIERldXRzY2hsYW5kIFJlZ2lvbmVuIG1pdCBob2hlbiBBcmJlaXRzbG9zZW5xdW90ZW4/Cldlbm4gU2llIHJlZ2lvbmFsZSBVbnRlcnNjaGllZGUgZmluZGVuLCB3ZWxjaGUgR3LDvG5kZSBrw7ZubnRlIGRpZXMgaGFiZW4/CgpEZW0gd29sbGVuIHdpciBpbiBkaWVzZXIgQ2FzZS1TdHVkeSBhdWYgZGVuIEdydW5kIGdlaGVuLgoKIyBaaWVsZSBkZXIgQ2FzZSBTdHVkeQoKRGllc2UgQ2FzZS1TdHVkeSBiZXN0ZWh0IGF1cyBtZWhyZXJlbiBUZWlsZW4gdW5kIHdpcmQgU2llIGR1cmNoIGRpZSBrb21wbGV0dGUgVm9ybGVzdW5nIGFscyBrb25rcmV0ZXMgQW5zY2hhdXVuZ3NvYmpla3QgYmVnbGVpdGVuLgpIaWVyYmVpIGRpZW50IGRpZSBDYXNlLVN0dWR5IGhhdXB0c8OkY2hsaWNoIGRhenUsIGlobmVuIGFuIGVpbmVtIGtvbmtyZXRlbiB1bmQgdW1mYW5ncmVpY2hlbiBCZWlzcGllbCBkaWUgS2VubnRuaXNzZSBmw7xyIGVpbmUgZXJmb2xncmVpY2hlIFByb2pla3RhcmJlaXQgenUgdmVybWl0dGVsbiB1bmQgZGllc2UgS2VubnRuaXNzZSB6dSB2ZXJ0aWVmZW4uCk5hdMO8cmxpY2gga8O2bm5lbiBTaWUgZGllIENhc2UtU3R1ZHkgYXVjaCBhbHMgUmVmZXJlbnogaGVyYW56aWVoZW4sIHdlbm4gU2llIGlocmUgZWlnZW5lIFByb2pla3RhcmJlaXQgYW5mZXJ0aWdlbi4KCiMgRGF0ZW4gYmVzY2hhZmZlbgoKV2lyIHdvbGxlbiB1bnMgaW4gZGllc2VyIENhc2UtU3R1ZHkgbWl0IGRlciBQcm8tS29wZiBWZXJzY2h1bGR1bmcsIGRlciBBcmJlaXRzbG9zaWdrZWl0IHVuZCBkZW0gQklQIGluIGVpbnplbG5lbiBSZWdpb25lbiBpbiBEZXV0c2NobGFuZCBiZXNjaMOkZnRpZ2VuIHVuZCBoaWVyIG3DtmdsaWNoZSByZWdpb25hbGUgVW50ZXJzY2hpZWRlIGF1ZmRlY2tlbi4KCkltIEVyc3RlbiBTY2hyaXR0IGlzdCBlcyB3aWNodGlnIHNpY2ggenUgw7xiZXJsZWdlbiwgd29oZXIgU2llIGlocmUgRGF0ZW5zw6R0emUgYmV6aWVoZW4uClVtIG1ha3Jvw7Zrb25vbWlzY2hlIEluZm9ybWF0aW9uZW4genVtIEJJUCBvZGVyIGRlciBBcmJlaXRzbG9zaWdrZWl0IHp1IGVyaGFsdGVuIGVtcGZpZWhsdCBlcyBzaWNoIGltbWVyIGF1ZiBkaWUgU2VpdGVuIGRlcyBTdGF0aXN0aXNjaGVuIEJ1bmRlc2FtdGVzIG9kZXIgZGVyIEJ1bmRlc2FnZW50dXIgZsO8ciBBcmJlaXQgenUgc2NoYXVlbi4KSGllciBmaW5kZW4gU2llIHouQi4gUXVhcnRhbHNpbmZvcm1hdGlvbmVuIHp1IEJJUCB1bmQgQXJiZWl0c2xvc2lna2VpdCBmw7xyIGdhbnogRGV1dHNjaGxhbmQuCgpJbiBkaWVzZXIgQ2FzZS1TdHVkeSB3b2xsZW4gd2lyIGplZG9jaCBldHdhcyBmZWluZ3JhbnVsYXJlcmUgSW5mb3JtYXRpb25lbiBzYW1tZWxuLCB1bmQgendhciBhdWYgTGFuZGtyZWlzLSwgVmVyd2FsdHVuZ3MtLCBiencuCkdlbWVpbmRlZWJlbmUuCgpVbnMgaW50ZXJlc3NpZXJlbiBkaWUgKipQcm8tS29wZiBWZXJzY2h1bHVuZyoqLCAqKkFyYmVpdHNsb3NpZ2tlaXQqKiB1bmQgZGFzICoqQklQKiouCgotICAgRGllIEluZm9ybWF0aW9uZW4gw7xiZXIgZGllIFZlcnNjaHVsZHVuZyBkZXIgKipHZW1laW5kZW4qKiBmaW5kZW4gd2lyIGF1ZiBkZW4gU2VpdGVuIGRlcyBTdGF0aXN0aXNjaGVuIEJ1bmRlc2FtdHMgaW0gUmVwb3J0OiBbSW50ZWdyaWVydGUgU2NodWxkZW4gZGVyIEdlbWVpbmRlbiB1bmQgR2VtZWluZGV2ZXJiw6RuZGVdKGh0dHBzOi8vd3d3LnN0YXRpc3Rpa3BvcnRhbC5kZS9kZS92ZXJvZWZmZW50bGljaHVuZ2VuL2ludGVncmllcnRlLXNjaHVsZGVuLWRlci1nZW1laW5kZW4tdW5kLWdlbWVpbmRldmVyYmFlbmRlKS4KLSAgIERpZSBJbmZvcm1hdGlvbmVuIHp1ciBBcmJlaXRzbG9zaWdrZWl0IGF1ZiAqKlZlcndhbHR1bmdzZ2VtZWluc2NoYWZ0c2ViZW5lKiogZmluZGVuIHdpciBhdWYgZGVuIFNlaXRlbiBkZXIgW0J1bmRlc2FnZW50dXIgZsO8ciBBcmJlaXRdKGh0dHBzOi8vc3RhdGlzdGlrLmFyYmVpdHNhZ2VudHVyLmRlL0RFL05hdmlnYXRpb24vU3RhdGlzdGlrZW4vU3RhdGlzdGlrZW4tbmFjaC1SZWdpb25lbi9CQS1HZWJpZXRzc3RydWt0dXItTmF2Lmh0bWwpLgotICAgRGllIEluZm9ybWF0aW9uZW4genVtIEJJUCBhdWYgKipMYW5ka3JlaXNlYmVuZSoqIGZpbmRlbiB3aXIgYXVmIGRlbiBTZWl0ZW4gZGVyIFtTdGF0aXN0aXNjaGVuIMOEbXRlciBkZXMgQnVuZGVzIHVuZCBkZXIgTMOkbmRlcl0oaHR0cHM6Ly93d3cuc3RhdGlzdGlrcG9ydGFsLmRlL2RlL3ZncmRsKS4KCiMjIE7DtnRpZ2UgUGFrZXRlIGxhZGVuCgpCZXZvciB3aXIgbWl0IGRlciBBbmFseXNlIHN0YXJ0ZW4gc29sbHRlbiB3aXIgZWluaWdlIFBha2V0ZSBpbiBSIGxhZGVuLCB3ZWxjaGUgd2lyIHNww6R0ZXIgdmVyd2VuZGVuIG3DtmNodGVuLCBkYSBzaWUgdW5zIGJlaSBkZXIgQW5hbHlzZSB1bnRlcnN0w7x0emVuIGvDtm5uZW4uCkRpZXMgZ2VzY2hpZWh0IG1pdCBkZW0gYGxpYnJhcnkoKWAgQmVmZWhsLgoKKCoqQWx0ZXJuYXRpdmU6KiogVm9yIGplZGVuIEJlZmVobCBkYXMgZGF6dWdlaMO2cmlnZSBQYWtldCBzY2hyZWliZW4sIGQuaC4gc3RhdHQgYHJlYWRfeGxzeGAga8O2bm50ZW4gd2lyIGF1Y2ggYHJlYWR4bDo6cmVhZF94bHN4YCBzY2hyZWliZW4uIEplZG9jaCB3b2xsZW4gd2lyIGltIFByb2pla3RrdXJzIGltbWVyIGRpZSBWYXJpYW50ZSBtaXQgYGxpYnJhcnkoKWAgdmVyd2VuZGVuLikKCmBgYHtyfQpsaWJyYXJ5KHJlYWR4bCkKbGlicmFyeSh0aWR5dmVyc2UpCmxpYnJhcnkoc2tpbXIpCmBgYAoKIyMgRGF0ZW4gaGVydW50ZXJsYWRlbgoKTWl0IGRlbiBCZWZlaGxlbiBhdXMgZGVtIGByZWFkeGxgIHVuZCBgcmVhZHJgIFBha2V0ZW4ga8O2bm50ZW4gU2llIGRpcmVrdCBVUkxzIGVpbmxlc2VuLCB3ZW5uIHNpY2ggZGFoaW50ZXIgVGV4dCwtIGJ6dy4KRXhjZWwgRGF0ZWkgdmVyYmVyZ2VuLCB3YXMgYmVpIHVucyBkZXIgRmFsbCBpc3QuCkFsbGVyZGluZ3Mgc29sbHRlbiB3aXIgZGF2b24gbnVyIHNlbHRlbiBHZWJyYXVjaCBtYWNoZW4sIGRlbm4gZXMga8O2bm50ZSBpbW1lciBzZWluIGRhcyBkaWUgRGF0ZW4gaW0gSW50ZXJuZXQgbW9kaWZpemllcnQgb2RlciB1bnRlciBkZXIgdm9yaGVyaWdlbiBVUkwgbmljaHQgbWVociBhdWZmaW5kYmFyIHNpbmQuCkRhaGVyIHdvbGxlbiB3aXIgZGllIGdld8O8bnNjaHRlbiBEYXRlbiwgd2VsY2hlIHdpciB6dXIgQW5hbHlzZSBiZW7DtnRpZ2VuLCBpbW1lciBpbiBlaW5lbSBVbnRlcm9yZG5lciBgZGF0YWAgYWJzcGVpY2hlcm4gdW5kIGRhbm4gYXVzIGRpZXNlbSBPcmRuZXIgZWlubGVzZW4uClNvIHN0ZWxsZW4gd2lyIHNpY2hlciwgZGFzcyB3aXIgaW1tZXIgYXVmIGRpZSBEYXRlbiB6dXLDvGNrZ3JlaWZlbiBrw7ZubmVuLCBhdWNoIHdlbm4gZGllc2UgYXVzIGRlbSBOZXR6IGdlbMO2c2NodCBvZGVyIG1vZGlmaXppZXJ0IHdlcmRlbi4KCkRhdGVuIGvDtm5uZW4gaW5uZXJoYWxiIHZvbiBSIG1pdCBkZW0gQmVmZWhsIGBkb3dubG9hZC5maWxlKClgIGhlcnVudGVyZ2VsYWRlbiB3ZXJkZW46CgpgYGB7ciAiRG93bmxvYWRfRGF0YSIsIGV2YWw9VH0KIyBadWVyc3Qgc29sbHRlbiBTaWUgcHLDvGZlbiBvYiBkZXIgVW50ZXJvcmRuZXIgImRhdGEiIGJlcmVpdHMgYmVpIGlobmVuIGV4aXNpdGVydCwgdW5kIGZhbGxzIGVyIG5pY2h0IGV4aXN0aWVydCBzb2xsdGVuIFNpZSBkaWVzZW4gZXJzdGVsbGVuLgojIERpZXMga8O2bm5lbiBTaWUgYmVpc3BpZWxzd2Vpc2UgbWl0IGRlbSBmb2xnZW5kZW4gQmVmZWhsIG1hY2hlbiwgd2VubiBkZXIgT3JkbmVyIHNjaG9uIGV4aXN0aWVydCB3aXJkIGVpbmUgV2Fybm1lbGR1bmcgYXVzZ2VnZWJlbjoKCmRpci5jcmVhdGUoZmlsZS5wYXRoKCIuIiwgImRhdGEiKSkKCiMgRHVyY2ggZGllIGlmLUJlZGluZ3VuZyBwcsO8ZmVuIFNpZSwgb2IgZGllIERhdGVpIGJlcmVpdHMgaW0gImRhdGEiLU9yZG5lciB2b3JoYW5kZW4gaXN0CgojIERpZSBuZXVlc3RlbiBEYXRlbiB6dXIgVmVyc2NodWxkdW5nIGF1ZiBMYW5ka3JlaXNlYmVuZSBzdGFtbWVuIGF1cyBkZW0gSmFociAyMDIxCmlmICghZmlsZS5leGlzdHMoIi4vZGF0YS9TY2h1bGRlbl8yMDIxLnhsc3giKSl7CiAgZG93bmxvYWQuZmlsZSgiaHR0cHM6Ly93d3cuc3RhdGlzdGlrcG9ydGFsLmRlL3NpdGVzL2RlZmF1bHQvZmlsZXMvMjAyMi0xMS9JbnRlZ3JpZXJ0ZV9TY2h1bGRlbl9kZXJfR2VtZWluZGVuX3VuZF9HZW1laW5kZXZlcmJhZW5kZV8yMDIyX1RhYmVsbGVuYmFuZC54bHN4IiwgIi4vZGF0YS9TY2h1bGRlbl8yMDIxLnhsc3giKQp9CgojIEFyYmVpdHNsb3NlIGF1cyBkZW0gSmFociAyMDIxCiNadSBmaW5kZW4gdW50ZXI6IGh0dHBzOi8vc3RhdGlzdGlrLmFyYmVpdHNhZ2VudHVyLmRlL1NpdGVHbG9iYWxzL0Zvcm1zL1N1Y2hlL0VpbnplbGhlZnRzdWNoZV9Gb3JtdWxhci5odG1sP3RvcGljX2Y9Z2VtZWluZGUtYXJiZWl0c2xvc2UtcXVvdGVuCmlmICghZmlsZS5leGlzdHMoIi4vZGF0YS9BcmJlaXRzbG9zZV8yMDIxLnhsc3guemlwIikpewogIGRvd25sb2FkLmZpbGUoImh0dHBzOi8vc3RhdGlzdGlrLmFyYmVpdHNhZ2VudHVyLmRlL1N0YXRpc3Rpa2RhdGVuL0RldGFpbC8yMDIxMTIvaWlpYTQvZ2VtZWluZGUtYXJiZWl0c2xvc2UtcXVvdGVuL2FyYmVpdHNsb3NlLXF1b3Rlbi1kbGstMC0yMDIxMTItemlwLnppcD9fX2Jsb2I9cHVibGljYXRpb25GaWxlJnY9MSIsICIuL2RhdGEvQXJiZWl0c2xvc2VfMjAyMS54bHN4LnppcCIpCn0KCiMgTGluayBmw7xyIGRpZSBha3R1ZWxsZW4gRGF0ZW4genVyIEFyYmVpdHNsb3NpZ2tlaXQ6IGh0dHBzOi8vc3RhdGlzdGlrLmFyYmVpdHNhZ2VudHVyLmRlL1N0YXRpc3Rpa2RhdGVuL0RldGFpbC9Ba3R1ZWxsL2lpaWE0L2dlbWVpbmRlLWFyYmVpdHNsb3NlLXF1b3Rlbi9hcmJlaXRzbG9zZS1xdW90ZW4tZGxrLTAtemlwLnppcAoKIyBCSVAgcHJvIEdlbWVpbmRlIGF1cyBkZW0gSmFociAyMDIyCmlmICghZmlsZS5leGlzdHMoIi4vZGF0YS9CSVBfMjAyMi54bHN4IikpewogIGRvd25sb2FkLmZpbGUoImh0dHBzOi8vd3d3LnN0YXRpc3Rpa3BvcnRhbC5kZS9zaXRlcy9kZWZhdWx0L2ZpbGVzLzIwMjMtMDcvdmdyZGxfcjJiMV9iczIwMjIueGxzeCIsICIuL2RhdGEvQklQXzIwMjIueGxzeCIpCn0KCmBgYAoKRGllIERhdGVuIHp1ciBWZXJzY2h1bGR1bmcgd29sbGVuIHdpciB1bnRlciAiU2NodWxkZW5fMjAyMS54bHN4IiwgZGEgZGllIFRhYmVsbGUgendhciBpbiAyMDIyIGdlbmVyaWVydCB3dXJkZSwgc2ljaCBhYmVyIGF1ZiBkYXMgSmFociAyMDIxIGJlemllaHQuCgpEaWUgYGlmYC1CZWRpbmd1bmcgcHLDvGZ0IG9iIGRlciBhbmdlZ2ViZW5lIERhdGVuc2F0eiBiZXJlaXRzIGluIHVuc2VyZW0gImRhdGEiIE9yZG5lciBlbnRoYWx0ZW4gaXN0LgpXZW5uIGRpZXMgZGVyIEZhbGwgaXN0LCBzbyB3ZXJkZW4gc2llIG5pY2h0IG1laHIgZXJuZXV0IGhlcnVudGVyZ2VsYWRlbi4KCldpciBoYWJlbiBoaWVyIGF1Y2ggZGllIERhdGVuIGbDvHIgZGllIEFyYmVpdHNsb3NlbnF1b3RlIGF1cyBkZW0gSmFociAyMDIxIGhlcnVudGVyZ2VsYWRlbiwgZGEgd2lyIGRpZSBwYXNzZW5kZW4gSW5mb3JtYXRpb25lbiB6dXIgUHJvLUtvcGYgVmVyc2NodWxkdW5nIGRlciBHZW1laW5kZW4gYXVzIG51ciBhdXMgZGVtIEphaHIgKioyMDIxKiogb25saW5lIGVyaGFsdGVuLiBEaWUgRGF0ZW4genVyIFZlcnNjaHVsZHVuZyB3ZXJkZW4gYWxsZSA0IEphaHJlIHZvbSBTdGF0aXN0aXNjaGVuIEJ1bmRlc2FtdCBha3R1YWxpc2llcnQuCgpJY2ggaGFiZSBpaG5lbiBkaWUgTGlua3MgenVtIG5ldWVyZW4gRGF0ZW5zw6R0emVuIGbDvHIgZGllIEFyYmVpdHNsb3NpZ2tlaXQgaW4gZGVuIFIgQ2h1bmsgZ2VzY2hyaWViZW4uCkbDvHIgZGFzIEJJUCBoYWJlbiB3aXIgZGllIG5ldWVzdGUgRGF0ZW5yZWloZSB2b24gQXVndXN0IDIwMjIgYmV6b2dlbiBkYSB3aXIgaGllciBQYW5lbGRhdGVuIGhhYmVuIHVuZCBrZWluZSBRdWVyc2Nobml0dHNkYXRlbiAod2FzIGRpZXMgZ2VuYXUgaGVpw590IHdpcmQgaW0gTGF1ZmUgZGVyIENhc2UtU3R1ZHkgZXJsw6R1dGVydCkuCgojIERhdGVuIGVpbmxlc2VuCgpJbSBuw6RjaHN0ZW4gU2Nocml0dCBzb2xsdGVuIHdpciBkaWUgRGF0ZW4gaW4gUiBlaW5sZXNlbi4KQmVpbSBEb3dubG9hZCBoYWJlbiB3aXIgc2Nob24gYW4gZGVuIFVSTHMgdW5kIGF1Y2ggYW4gZGVuIGhlcnVudGVyZ2VsYWRlbmVuIERhdGVpZW4gZ2VzZWhlbiwgZGFzcyBlcyBzaWNoIGJlaSB6d2VpIERvd25sb2FkcyB1bSBaSVAtQXJjaGl2ZSAoQklQIHVuZCBBbnphaGwgYW4gQXJiZWl0c2xvc2VuKSBoYW5kZWx0LgpEaWVzZSBaSVAtQXJjaGl2ZSBrw7ZubmVuIHdpciBtaXR0ZWxzIFIgZXh0cmFoaWVyZW4sIGRpZXNlIGFuc2NobGllw59lbmQgZWlubGVzZW4gdW5kIGRpZSBleHRyYWhpZXJ0ZSBEYXRlaSB3aWVkZXIgbMO2c2NoZW4uCkRpZXMgaGF0IGRlbiBWb3J0ZWlsLCBkYXNzIFNpZSBpaHJlIERhdGVpZW4gcGxhdHpzcGFyZW5kIGF1ZiBpaHJlciBGZXN0cGxhdHRlIGFic3BlaWNoZXJuIHVuZCBudXIgYmVpIEJlZGFyZiBlbnRzcHJlY2hlbmQgZW50cGFja2VuLgoKIyBBbnphaGwgYW4gQXJiZWl0c2xvc2VuCgpJbSBlcnN0ZW4gU2Nocml0dCB3b2xsZW4gd2lyIHVucyBtaXQgZGVuIERhdGVuIHp1IGRlbiBBcmJlaXRzbG9zZW4gYmVzY2jDpGZ0aWdlbiB1bmQgZGllIGluIGRlbSBaSVAtQXJjaGl2IGVudGhhbHRlbmVuIERhdGVpZW4gaW4gUiBlaW5sZXNlbi4KCiMjIFpJUC1BcmNoaXYgZW50cGFja2VuCgpgYGB7cn0KIyDDlmZmbmVuIGRlcyBaSVAtQXJjaGl2cwojIEVzIHNpbmQgendlaSBUYWJlbGxlbiBpbiBkZW0gWklQIEFyY2hpdiwgd2lyIGludGVyZXNzaWVyZW4gdW5zIGbDvHIgZGllIEFuemFobCBkZXIgQXJiZWl0c2xvc2VuIHVuZCB3w6RobGVuIGRpZXNlIG1pdCBkZW0ga2xlaW5lbiBbMV0gYXVzCmFsb19uYW1lIDwtIGFzLmNoYXJhY3Rlcih1bnppcCgiLi9kYXRhL0FyYmVpdHNsb3NlXzIwMjEueGxzeC56aXAiLCBsaXN0ID0gVFJVRSkkTmFtZSkKYWxvX25hbWUgPC0gYWxvX25hbWVbMV0KdW56aXAoIi4vZGF0YS9BcmJlaXRzbG9zZV8yMDIxLnhsc3guemlwIiwgYWxvX25hbWUpCmBgYAoKT2ssIG51biBoYWJlbiB3aXIgZGllIERhdGVuIGVudHppcHBlZCB1bmQgc2VoZW4sIGRhc3MgZXMgc2ljaCB1bSBlaW5lIEV4Y2VsLURhdGVpIGhhbmRlbHQuCkRvY2ggZGllc2UgaGF0IHNlaHIgdmllbGUgdW50ZXJzY2hpZWRsaWNoZSBUYWJlbGxlbmJsw6R0dGVyLgpXaWUgd2lzc2VuIHdpciwgd2VsY2hlcyBUYWJlbGxlbmJsYXR0IGbDvHIgdW5zIHZvbiBJbnRlcmVzc2UgaXN0PwoKRGllcyBrw7ZubmVuIHdpciB6dW0gRWluZW4gbWl0IGBleGNlbF9zaGVldHNgIGhlcmF1c2ZpbmRlbiwgd2VubiBkaWUgVGFiZWxsZW5ibMOkdHRlciBndXQgYmVuYW5udCBzaW5kOgoKYGBge3J9CmV4Y2VsX3NoZWV0cyhhbG9fbmFtZSkKYGBgCgpEYSBkaWUgVGFiZWxsZW5ibMOkdHRlciBqZWRvY2ggbmljaHQgdW5iZWRpbmd0IHZpZWxzYWdlbmQgYmVzY2hyaWZ0ZXQgc2luZCBzb2xsdGVuIHdpciBkYXMgVGFiZWxsZW5ibGF0dCAiSW5oYWx0IiBlaW5sZXNlbiB1bmQgdW5zIGRpZXNlcyBhbnNjaGF1ZW4uCkV2ZW50dWVsbCB3ZXJkZW4gd2lyIGhpZXIgc2NobGF1ZXIuCgpgYGB7ciwgbWVzc2FnZT1GQUxTRX0KYWxvX2luaGFsdCA8LSByZWFkX3hsc3goYWxvX25hbWUsIHNoZWV0ID0gIkluaGFsdHN2ZXJ6ZWljaG5pcyIpCmhlYWQoYWxvX2luaGFsdCwgMTUpCmBgYAoKSGllciBlcmhhbHRlbiB3aXIgZWluZW4gw5xiZXJibGljayDDvGJlciBkaWUgVGFiZWxsZW5ibMOkdHRlciB1bmQgd28gd2VsY2hlIEluZm9ybWF0aW9uZW4gYWJnZXNwZWljaGVydCBzaW5kLgpEYSB3aXIgdW5zIGbDvHIgZGVuIEJlc3RhbmQgYW4gQXJiZWl0c2xvc2VuIGludGVyZXNzaWVyZW4gdW5kIGhpZXIgbmljaHQgbmFjaCBGcmF1ZW4gdW5kIE3DpG5uZXJuIHVudGVyc2NoZWlkZW4gbcO2Y2h0ZW4sIGlzdCBkYXMgVGFiZWxsZW5ibGF0dCBgR2VzYW10YCBmw7xyIHVucyBkYXMgcmljaHRpZ2UuCgoqKkFsdGVybmF0aXZlOioqIFNjaGF1ZW4gU2llIHNpY2ggZGllIEV4Y2VsLURhdGVpIGluIEV4Y2VsIG9kZXIgTGlicmVPZmZpY2UgYW4gdW5kIGVudHNjaGVpZGVuIFNpZSBkYW5uLCB3ZWxjaGVzIFRhYmVsbGVuYmxhdHQgU2llIGVpbmxlc2VuIG3DtmNodGVuLgoKIyMgRW50cGFja3RlIERhdGVpIGVpbmxlc2VuCgpOdW4gd2lzc2VuIHdpciwgd2VsY2hlcyBUYWJlbGxlbmJsYXR0IGRpZSBmw7xyIHVucyB3aWNodGlnZSBJbmZvcm1hdGlvbiBlbnRow6RsdDoKCmBgYHtyLCBtZXNzYWdlPUZBTFNFfQphbG8gPC0gcmVhZF94bHN4KGFsb19uYW1lLCBzaGVldD0iR2VzYW10IikKCmhlYWQoYWxvLDEwKQpgYGAKCk9rLiBIaWVyIGlzdCBlcyB3b2hsIG5pY2h0IHZvcnRlaWxoYWZ0IHZvbiBkZXIgZXJzdGVuIFplaWxlIGFiIGRpZSBJbmZvcm1hdGlvbmVuIGF1cyBkZW0gVGFiZWxsZW5ibGF0dCBlaW56dWxlc2VuLgpTbyB3aWUgZXMgYXVzc2llaHQgc2luZCBpbiBkZW4gZXJzdGVuIDUgWmVpbGVuIEluZm9ybWF0aW9uZW4genVtIFRhYmVsbGVuYmxhdHQgdW5kIGRlbSBCZXJpY2h0c2phaHIgZW50aGFsdGVuLCBkYW5uIGtvbW10IGVpbmUgbGVlcmUgWmVpbGUgdW5kIGRhbm4ga29tbWVuIGRpZSBlaWdlbnRsaWNoZW4gU3BhbHRlbmJlc2NocmlmdHVuZ2VuLgpEaWVzZSBzaW5kIGRhbm4gamVkb2NoIHdpZWRlcnVtIGluIDQgWmVpbGVuIHVudGVydGVpbHQuIFdhcyBzaW5kIGRlbm4gaGllciBudW4gZGllIFNwYWx0ZW7DvGJlcnNjaHJpZnRlbiwgZC5oLiBkaWUgVmFyaWFibGVubmFtZW4gaW0gRGF0ZW5zYXR6PwoKIyMgU3BlemlmaXppZXJlbiB3ZWxjaGUgU3BhbHRlbiBlaW5nZWxlc2VuIHdlcmRlbiBzb2xsZW4KCkhpZXJ6dSDDvGJlcmxlZ2VuIHdpciB1bnMgZm9sZ2VuZGVzOgoKLSAgIFdlbGNoZSBJbmZvcm1hdGlvbiBiZW7DtnRpZ2VuIHdpciBhdXMgZGVyIFRhYmVsbGUKCiAgICAtICAgRGllIEFuemFobCBhbGxlciBBcmJlaXRzbG9zZW4gcHJvIEdlbWVpbmRlIChkLmguIFNHQiBJSSB1bmQgSUlJIGdlbWVpbnNhbSkgKiphdXMgZGVtIEphaHIgMjAyMSoqCiAgICAtICAgRGllIEFuemFobCBkZXIgQXJiZWl0c2xvc2VuIHBybyBHZW1laW5kZSBmw7xyIGVpbmVuIGJlc3RpbW10ZW4gUmVjaHRza3JlaXMgKHouQi4gbnVyIFNHQiBJSSkKICAgIC0gICBEaWUgQW56YWhsIGRlciBBcmJlaXRzbG9zZW4gcHJvIEdlbWVpbmRlIGbDvHIgZWluZW4gYmVzdGltbXRlbiBSZWNodHNrcmVpcyB1bmQgZWluIGJlc3RpbW10ZXMgQWx0ZXIgKHouQi4gU0dCIElJIGFsbGUgdW50ZXIgMjUgSmFocmUpCgotICAgV2llIGvDtm5uZW4gd2lyIGRpZSB2b24gdW5zIGJlbsO2dGlndGUgSW5mb3JtYXRpb24gbcO2Z2xpY2hzdCBlaW5mYWNoIGV4dHJhaGllcmVuCgpJbiB1bnNlcmVtIEZhbGwgYmVuw7Z0aWdlbiB3aXIgZGllIEluZm9ybWF0aW9uIHp1ciBkdXJjaHNjaG5pdHRsaWNoZW4gQW56YWhsIGFsbGVyIEFyYmVpdHNsb3NlbiBwcm8gR2VtZWluZGUgYXVzIGRlbSBKYWhyIDIwMjEsIGQuaC4gdW5zIGludGVyZXNzaWVydCBTcGFsdGUgYC4uLjNgLgpXZWl0ZXJoaW4gYmVuw7Z0aWdlbiB3aXIgZWluZSBlaW5kZXV0aWcgenV6dW9yZGVuZGVuICJHZW1laW5kZS1JRCIgdW0gZGllc2UgRGF0ZW5xdWVsbGUgc3DDpHRlciBtaXQgYW5kZXJlbiBEYXRlbnF1ZWxsZW4gdmVyYmluZGVuIHp1IGvDtm5uZW4uCkF1w59lcmRlbSB3w6RyZSBkZXIgTmFtZSBkZXIgR2VtZWluZGUgbm9jaCBlaW5lIHdpY2h0aWcgSW5mb3JtYXRpb24uCkRlciBlaW5mYWNoc3RlIFdlZyBhbiBkaWVzZSBJbmZvcm1hdGlvbiB6dSBnZWxhbmdlbiBpc3QgZGllIGVyc3RlbiBhY2h0IFplaWxlbiBhYnp1c2NobmVpZGVuIHVuZCBkaWUgRGF0ZW4gZXJzdCBhYiBkb3J0IGVpbnp1bGVzZW4uCkFuc2NobGllw59lbmQgYmVoYWx0ZW4gd2lyIG51ciBkaWUgZXJzdGVuIDMgU3BhbHRlbiwgZGEgdW5zIG51ciBkaWVzZSBpbnRlcmVzc2llcmVuLgoKRGFzIHdvbGxlbiB3aXIgbnVuIG1hY2hlbjoKCmBgYHtyfQojIERhdGVuIGVpbmxlc2VuIHZvbiBUYWJlbGxlbmJsYXR0ICJHZXNhbXQiLCBvaG5lIGRpZSBlcnN0ZW4gOCBaZWlsZW4KYWxvIDwtIHJlYWRfeGxzeChhbG9fbmFtZSwgc2hlZXQgPSAiR2VzYW10Iiwgc2tpcCA9IDgpCgojIERpZSBlbnR6aXBwdGUgRGF0ZWkgd2llZGVyIGzDtnNjaGVuCnVubGluayhhbG9fbmFtZSkKCiMgTnVuIGJlc2NocsOkbmtlbiB3aXIgdW5zIGF1ZiBkaWUgZXJzdGUgdW5kIGRyaXR0ZSBTcGFsdGUgdW5kIHRyZW5uZW4gZGVuIE5hbWVuIGRlciBSZWdpb24gKHdlbGNoZXIgaW4gU3BhbHRlIGAuLi4xYCBnZWxpc3RldCB3aXJkKSB1bmQgZGVyZW4gIkdlbWVpbmRlLUlEIiwgZGVtIHNvZ2VuYW5udGVuICJSZWdpb25hbHNjaGx1ZXNzZWwiIHZvbmVpbmFuZGVyLgojIERpZSBTcGFsdGUgMyB3b2xsZW4gd2lyIGFuc2NobGllw59lbmQgaW4gImFsbyIgdW1iZW5lbm5lbgojIFdlaXRlcmhpbiBsw7ZzY2hlbiB3aXIgYWxsZSBaZWlsZW4sIGbDvHIgZGllICJhbG8iIGF1ZiBOQSBnZXNldHp0IGlzdCB1bmQgZGllIGVyc3RlIFplaWxlLCBkaWUgYWxsZSBBcmJlaXRzbG9zZW4gaW4gZ2FueiBEZXV0c2NobGFuZCBiZWluaGFsdGV0CiMgV2lyIHNwZWljaGVybiBkZW4gRGF0ZW5zYXR6IGFscyBgZGF0YV9hbG9gIGFiCmRhdGFfYWxvIDwtIGFsbyAlPiUgCiAgc2VsZWN0KGMoYC4uLjFgLCBKYWhyZXNkdXJjaHNjaG5pdHRlLCBgLi4uM2ApKSAlPiUKICBtdXRhdGUoUmVnaW9uYWxzY2hsdWVzc2VsID0gc3RyX2V4dHJhY3QoYC4uLjFgLCAiW1s6ZGlnaXQ6XV0rIiksCiAgICAgICAgIEdlbWVpbmRlID0gc3RyX2V4dHJhY3QoYC4uLjFgLCAiW0EtWl0uKiIpKSAlPiUKICBtdXRhdGUoYWxvID0gYXMubnVtZXJpYyhgLi4uM2ApKSAlPiUKICBzZWxlY3QoLWMoYC4uLjFgLCBKYWhyZXNkdXJjaHNjaG5pdHRlLCBgLi4uM2ApKSAlPiUKICBmaWx0ZXIoIWlzLm5hKGFsbykpCgojIERpZSBlcnN0ZW4gZHJlaSBaZWlsZW4gYmVpbmhhbHRlbiBrZWluZSBudXR6bGljaGVuIEluZm9ybWF0aW9uZW4sIGQuaC4gd2lyIGzDtnNjaGVuIGRpZXNlCmRhdGFfYWxvIDwtIGRhdGFfYWxvWy1jKDEsMiksXQpgYGAKCiMjIEtvbnNpc3RlbnpjaGVjawoKTnVuIHNvbGx0ZW4gd2lyIG5vY2ggZGllIERhdGVuIGF1ZiBLb25zaXN0ZW56IHByw7xmZW4uCkQuaC4gbWFjaGVuIGRpZSBBbmdhYmVuIFNpbm4gdW5kIHNpbmQgZGllIERhdGVuIGluIHNpY2gga29uc2lzdGVudD8KSGllcmbDvHIgc29sbHRlbiB3aXIgenVtIEVpbmVuIGV4dGVybmUgRGF0ZW5xdWVsbGVuIHVudGVyc3VjaGVuIHVuZCB6dW0gQW5kZXJlbiBkaWUgRGF0ZW4gaW50ZXJuIHByw7xmZW4uCgpXaXIgaGFiZW4gaGllciBzZWhyIGZlaW5ncmFudWxhcmUgSW5mb3JtYXRpb25lbiDDvGJlciBkaWUgQXJiZWl0c2xvc2VuemFobCBpbiAyMDIxIHZvcmxpZWdlbiwgamVkb2NoIGvDtm5uZW4gd2lyIGRpZSBEYXRlbiBhdWNoIGF1ZiBlaW5lIGjDtmhlcmUgRWJlbmUgYWdncmVnaWVyZW4gdW5kIGRhbWl0IGxlaWNodCBtaXQgYW5kZXJlbiBRdWVsbGVuIHZlcmdsZWljaGVuLgpEaWVzIHdvbGxlbiB3aXIgaGllciB0dW46CgotICAgWnVuw6RjaHN0IGxhc3NlbiB3aXIgdW5zIGRpZSBBbnphaGwgYW4gQXJiZWl0c2xvc2VuIGbDvHIgamVkZXMgQnVuZGVzbGFuZCBpbiAyMDIxIGF1c2dlYmVuLiBJbiB1bnNlcmVtIERhdGVuc2F0eiBzaW5kIGRpZXMgYWxsZSBEYXRlbnB1bmt0ZSBtaXQgZWluZW0gendlaXN0ZWxsaWdlbiBgUmVnaW9uYWxzY2hsdWVzc2VsYC4gV2lyIG3DvHNzZW4gaGllciBiZWFjaHRlbiwgZGFzcyBkaWUgYFJlZ2lvbmFsc2NobHVlc3NlbGAgaW4gZGVyIEtsYXNzZSBgY2hhcmFjdGVyYCB2b3JsaWVnZW4sIGQuaC4gYWxzIFN0cmluZ3MgdW5kIG5pY2h0IGFscyBaYWhsLiBEZXNoYWxiIGvDtm5uZW4gd2lyIGRpZSBBbnphaGwgYW4gIkJ1Y2hzdGFiZW4iIGbDvHIgamVkZW4gYFJlZ2lvbmFsc2NobHVlc3NlbGAgesOkaGxlbi4gRGllcyBnZXNjaGllaHQgw7xiZXIgZGVuIEJlZmVobCBgbmNoYXIoKWAgKG51bWJlciBvZiBjaGFyYWN0ZXJzKQotICAgTnVuIHNvbGx0ZW4gd2lyIGVpbmUgYW5kZXJlIERhdGVucXVlbGxlIGhlcmFuemllaGVuIHVuZCBkaWUgSW5mb3JtYXRpb25lbiBnZWdlbmNoZWNrZW4uIEJzcHcuIGvDtm5udGVuIHdpciBbZGllIEFuemFobCBkZXIgQXJiZWl0c2xvc2VuIGbDvHIgZGFzIEphaHIgMjAyMSB1bnRlcnRlaWx0IG5hY2ggTMOkbmRlcm4gaGVyYW56aWVoZW5dKGh0dHBzOi8vc3RhdGlzdGlrLmFyYmVpdHNhZ2VudHVyLmRlL1N0YXRpc3Rpa2RhdGVuL0RldGFpbC8yMDIxMTIvaWlpYTQvYWt0LWRhdC1qei9ha3QtZGF0LWp6LWQtMC0yMDIxMTIteGxzeC54bHN4KS4gKFRhYmVsbGVuYmxhdHQgOCkKCmBgYHtyfQpjaGVja19hbG9fYnVuZGVzbGFuZCA8LSBkYXRhX2FsbyAlPiUKICBmaWx0ZXIobmNoYXIoUmVnaW9uYWxzY2hsdWVzc2VsKSA9PSAyKSAlPiUKICByZW5hbWUoYnVuZGVzbGFuZCA9IFJlZ2lvbmFsc2NobHVlc3NlbCkKCmNoZWNrX2Fsb19idW5kZXNsYW5kCmBgYAoKV2VubiB3aXIgZGllIMOcYmVycHLDvGZ1bmcgbWl0IGRlciBhbmRlcmVuIFRhYmVsbGUgZGVyIEJ1bmRlc2FnZW50dXIgZsO8ciBBcmJlaXQgbWFjaGVuLCBkYW5uIHNpbmQgYmVpZGUgRGF0ZW5yZWloZW4gaWRlbnRpc2NoLgoKTnVuIHdvbGxlbiB3aXIgbm9jaCBkaWUgaW50ZXJuZSBLb25zaXN0ZW56IMO8YmVycHLDvGZlbi4KSGllcmbDvHIgYmVyZWNobmVuIHdpciBkaWUgQW56YWhsIGFuIEFyYmVpdHNsb3NlbiBmw7xyIGplZGVzIEJ1bmRlc2xhbmQgYWxzIFN1bW1lIGRlciBBcmJlaXRzbG9zZW4gZWluZXIgamVkZW4gR2VtZWluZGUuCgpgYGB7cn0KIyBOdXIgR2VtZWluZGVkYXRlbiBudXR6ZW4sIGRhbm4gYXVmIEJ1bmRlc2xhbmRlYmVuZGUgZGllIFN1bW1lIGF1cyBkZW4gR2VtZWluZGVkYXRlbiBiZXJlY2huZW4KYWxvX21ldGEgPC0gZGF0YV9hbG8gJT4lIAogIGZpbHRlcihuY2hhcihSZWdpb25hbHNjaGx1ZXNzZWwpID09IDgpICU+JQogIG11dGF0ZShsYW5ka3JlaXMgPSBzdHJfZXh0cmFjdChSZWdpb25hbHNjaGx1ZXNzZWwsICJeLns1fSIpLAogICAgICAgICBidW5kZXNsYW5kID0gc3RyX2V4dHJhY3QoUmVnaW9uYWxzY2hsdWVzc2VsLCAiXi57Mn0iKSkKCmFsb19idW5kZXNsYW5kIDwtIGFsb19tZXRhICU+JQogIGdyb3VwX2J5KGJ1bmRlc2xhbmQpICU+JQogIHN1bW1hcmlzZSh0b3RhbF9hbG8gPSBzdW0oYXMubnVtZXJpYyhhbG8pKSkKCmFsb19sYW5ka3JlaXMgPC0gYWxvX21ldGEgJT4lCiAgZ3JvdXBfYnkobGFuZGtyZWlzKSAlPiUKICBzdW1tYXJpc2UodG90YWxfYWxvID0gc3VtKGFsbykpICU+JQogIHJlbmFtZShSZWdpb25hbHNjaGx1ZXNzZWwgPSBsYW5ka3JlaXMpCmBgYAoKVW0gZWluZW4gYmVzc2VyZW4gw5xiZXJibGljayB6dSBlcmhhbHRlbiBrw7ZubmVuIHdpciB1bnNlcmUgYmVyZWNobmV0ZW4gdW5kIGRpZSB2b24gZGVyIEFnZW50dXIgZsO8ciBBcmJlaXQgYW5nZWdlYmVuZW4gV2VydGUgbWl0ZWluYW5kZXIgdmVyYmluZGVuIHVuZCBkaWUgRGlmZmVyZW56IHp3aXNjaGVuIGRlbiBiZWlkZW4gVGFiZWxsZW4gYmVyZWNobmVuOgoKYGBge3J9CmNoZWNrX2NvbnNpdGVuY3kgPC0gbGVmdF9qb2luKGNoZWNrX2Fsb19idW5kZXNsYW5kLCBhbG9fYnVuZGVzbGFuZCwgYnkgPSAiYnVuZGVzbGFuZCIpCgpjaGVja19jb25zaXRlbmN5IDwtIGNoZWNrX2NvbnNpdGVuY3kgJT4lCiAgbXV0YXRlKGRpZmYgPSBhbG8gLSB0b3RhbF9hbG8pCgpjaGVja19jb25zaXRlbmN5CmBgYAoKVW5zZXJlIEFuYWx5c2VuIHplaWdlbiwgZGFzcyBlcyBrZWluZSBEaWZmZXJlbnplbiB6d2lzY2hlbiBkZW4gRGF0ZW4gZ2lidCwgZGllIHZvbiBkZXIgQnVuZGVzYWdlbnR1ciBmw7xyIEFyYmVpdCBhdWYgTGFuZGVzLSB1bmQgQnVuZGVzZWJlbmUgdmVyw7ZmZmVudGxpY2hlbi4KCiMgUHJvLUtvcGYgVmVyc2NodWxkdW5nCgpEZXIgbsOkY2hzdGUgRGF0ZW5zYXR6IGJlaW5oYWx0ZXQgZGllIFByby1Lb3BmLVZlcnNjaHVsZHVuZyBkZXIgZGV1dHNjaGVuIEdlbWVpbmRlbi4KSGllciBoYW5kZWx0IGVzIHNpY2ggd2llZGVyIHVtIFF1ZXJzY2huaXR0c2RhdGVuIGF1ZiBHZW1laW5kZWViZW5lIGF1cyBkZW0gSmFociAyMDE3LgoKRGllc2VuIERhdGVuc2F0eiBrw7ZubmVuIHdpciB2b24gZGVyIEhvbWVwYWdlIGRlcyBTdGF0aXN0aXNjaGVuIEJ1bmRlc2FtdGVzIGRpcmVrdCBhbHMgRXhjZWwtVGFiZWxsZSBoZXJ1bnRlcmxhZGVuIHVuZCBtw7xzc2VuIGtlaW4gWklQLUFyY2hpdiBlbnRwYWNrZW4uCkFsbGVyZGluZ3Mgc2VoZW4gd2lyIHNlaHIgc2NobmVsbCwgZGFzIGF1Y2ggZGllc2VyIERhdGVuc2F0eiBzZWluZSBUw7xja2VuIGJlaW0gRWlubGVzZW4gYmVyZWl0aMOkbHQsIGluc2Jlc29uZGVyZSB3ZW5uIHdpciBzY2hhdWVuLCB3ZWxjaGUgVGFiZWxsZW5ibMOkdHRlciBmw7xyIHVuc2VyZSBBbmFseXNlIHJlbGV2YW50IHNpbmQ6CgpgYGB7cn0KZXhjZWxfc2hlZXRzKCIuL2RhdGEvU2NodWxkZW5fMjAyMS54bHN4IikKYGBgCgojIyBNZWhyZXJlIFRhYmVsbGVuYmzDpHR0ZXIgZWlubGVzZW4KCk51biBzaW5kIG5pY2h0IG1laHIgYWxsZSBJbmZvcm1hdGlvbmVuIGluICoqZWluZW0gVGFiZWxsZW5ibGF0dCoqIGVudGhhbHRlbiwgc29uZGVybiBqZWRlcyBCdW5kZXNsYW5kIGhhdCBzZWluIGVpZ2VuZXMgVGFiZWxsZW5ibGF0dCBiZWtvbW1lbi4KU3ByaWNoLCB3aXIgbcO8c3NlbiBlaW5lIE3DtmdsaWNoa2VpdCBmaW5kZW4gYWxsZSBUYWJlbGxlbmJsw6R0dGVyIG5hY2hlaW5hbmRlciBlaW56dWxlc2VuIHVuZCB6dSB2ZXJhcmJlaXRlbi4KCkRpZXMgd29sbGVuIHdpciBtaXQgZWluZXIgYGZvcmAtU2NobGVpZmUgbMO2c2VuLCBkb2NoIHp1ZXJzdCBzY2hhdWVuIHdpciB1bnMgYW4sIHdlbGNoZSBJbmZvcm1hdGlvbmVuIHdpciBhdXMgZGVuIFRhYmVsbGVuYmzDpHR0ZXJuIGJlbsO2dGlnZW46CgpgYGB7ciwgbWVzc2FnZT1GQUxTRX0Kc2ggPC0gcmVhZF94bHN4KCIuL2RhdGEvU2NodWxkZW5fMjAyMS54bHN4Iiwgc2hlZXQgPSAiU0giKQpoZWFkKHNoLDIwKQpgYGAKCkbDvHIgdW5zIHdpY2h0aWcgc2luZCBkaWUgSW5mb3MgYnpnbC4gZGVzICJSZWdpb25hbHNjaGzDvHNzZWxzIiwgZGVyICJHZW1laW5kZW5hbWUiLCBkaWUgIkVpbndvaG5lciIgdW5kIGRpZSAiU2NodWxkZW4gZGVzIMO2ZmZlbnRsaWNoZW4gQmVyZWljaHMgaW5zZ2VzYW10Ii4KWnVyIMOcYmVycHLDvGZ1bmcgdW5zZXJlciBFcmdlYm5pc3NlIG5laG1lbiB3aXIgbm9jaCBkaWUgIlNjaHVsZGVuIGplIEVpbndvaG5lciIgbWl0IGluIHVuc2VyZW4gRGF0ZW5zYXR6IGF1ZiwgZC5oLgpkaWUgZXJzdGVuIHNlY2hzIFNwYWx0ZW4uCldlaXRlcmhpbiBzdGVoZW4gdW5zZXJlIFZhcmlhYmxlbmJlemVpY2hudW5nZW4gaW4gWmVpbGUgNSwgZC5oLiB3aXIgaWdub3JpZXJlbiBkaWUgZXJzdGVuIDQgWmVpbGVuIGJlaW0gRWlubGVzZW4uCgpEZXIgw5xiZXJzaWNodCBoYWxiZXIgd29sbGVuIHdpciBub2NoIGVpbmUgU3BhbHRlIGhpbnp1ZsO8Z2VuLCB3ZWxjaGUgZGVuIE5hbWVuIGRlcyBUYWJlbGxlbmJsYXR0ZXMgZW50aMOkbHQsIHdlbGNoZXMgd2lyIGdlcmFkZSBlaW5nZWxlc2VuIGhhYmVuLgoKYGBge3IsIG1lc3NhZ2U9RkFMU0V9CiMgRWlubGVzZW4gZGVzIFRhYmVsbGVuYmxhdHRlcyAiU0giIG9obmUgZGllIGVyc3RlbiA1IFplaWxlbiB1bmQgbnVyIGRpZSBTcGFsdGVuIDEtNwpzY2h1bGRlbl9pbmRpdmlkdWVsbCA8LSByZWFkX3hsc3goIi4vZGF0YS9TY2h1bGRlbl8yMDIxLnhsc3giLCBzaGVldCA9ICJTSCIsIHNraXAgPSA1KVsxOjddCiMgVW1iZW5lbm5lbiBkZXIgZXJzdGVuIDcgU3BhbHRlbgpjb2xuYW1lcyhzY2h1bGRlbl9pbmRpdmlkdWVsbCkgPC0gYygiUmVnaW9uYWxzY2hsdWVzc2VsIiwgIkdlbWVpbmRlIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJWZXJ3YWx0dW5nc2Zvcm0iLCAiRWlud29obmVyIiwgIlNjaHVsZGVuX2dlc2FtdCIsICJWZXJhZW5kZXJ1bmdfVm9yamFociIsICJTY2h1bGRlbl9wcm9fa29wZiIpCgojIFp1c8OkdHpsaWNoZSBTcGFsdGUgaGluenVmw7xnZW4gbWl0IGRlbSBOYW1lbiBkZXMgVGFiZWxsZW5ibGF0dGVzCnNjaHVsZGVuX2luZGl2aWR1ZWxsJEJ1bmRlc2xhbmQgPC0gIlNIIgpgYGAKCk9rLCBudW4gaGFiZW4gd2lyIGRpZSBEYXRlbiBmw7xyIFNjaGxlc3dpZy1Ib2xzdGVpbiBlaW5nZWxlc2VuIHVuZCBrw7ZubmVuIG1pdCBlaW5lciBgZm9yYC1TY2hsZWlmZSBhbGxlIHdlaXRlcmVuIEJ1bmRlc2zDpG5kZXIgKFRhYmVsbGVuYmzDpHR0ZXIpIGluIGRlciBnbGVpY2hlbiBGb3JtIGR1cmNoZ2VoZW46CgpgYGB7ciwgbWVzc2FnZT1GQUxTRX0KIyBEYXRlbiBtaXQgZm9yLVNjaGxlaWZlIGVpbmxlc2VuIChTdHJ1a3R1ciBnbGVpY2ggd2llIGltIHZvcmhlcmlnZW4gQ2h1bmspCnNoZWV0X25hbWVzIDwtIGV4Y2VsX3NoZWV0cygiLi9kYXRhL1NjaHVsZGVuXzIwMjEueGxzeCIpCiMgRWlubGVzZW4gZGVyIFRhYmVsbGVuYmzDpHR0ZXIgNy0xOCAoYWxsZSBCdW5kZXNsw6RuZGVyKQpzaGVldF9yZWFkIDwtIHNoZWV0X25hbWVzWzc6MThdCmZvciAoaSBpbiAxOmxlbmd0aChzaGVldF9yZWFkKSl7CiAgdG1wIDwtIHJlYWRfeGxzeCgiLi9kYXRhL1NjaHVsZGVuXzIwMjEueGxzeCIsIHNoZWV0ID0gc2hlZXRfcmVhZFtpXSwgc2tpcCA9IDUpWzE6N10KICB0bXAkQnVuZGVzbGFuZCA8LSBzaGVldF9yZWFkW2ldCiAgY29sbmFtZXModG1wKSA8LSBjKCJSZWdpb25hbHNjaGx1ZXNzZWwiLCAiR2VtZWluZGUiLCAiVmVyd2FsdHVuZ3Nmb3JtIiwgCiAgICAgICAgICAgICAgICAgICAgICJFaW53b2huZXIiLCAiU2NodWxkZW5fZ2VzYW10IiwgIlZlcmFlbmRlcnVuZ19Wb3JqYWhyIiwgIlNjaHVsZGVuX3Byb19rb3BmIiwgIkJ1bmRlc2xhbmQiKQogICMgRGF0ZW4gYWxsZXIgd2VpdGVyZW4gVGFiZWxsZW5ibMOkdHRlciB1bnRlciBkZW4gYWt0dWVsbGVuIERhdGVuc2F0eiBhbmhlZnRlbgogIHNjaHVsZGVuX2luZGl2aWR1ZWxsIDwtIGJpbmRfcm93cyhzY2h1bGRlbl9pbmRpdmlkdWVsbCwgdG1wKQp9CmBgYAoKIyMgVmFyaWFibGVuIHVtZm9ybWVuCgpgYGB7cn0KaGVhZChzY2h1bGRlbl9pbmRpdmlkdWVsbCwzMCkKYGBgCgpXaXIgc2VoZW4sIGVzIGdpYnQgaW1tZXIgbm9jaCBlaW5pZ2UgUHJvYmxlbWU6CgotICAgRGllIFdlcnRlIHVuc2VyZXIgVmFyaWFibGVuIHN0ZWhlbiBuaWNodCBkaXJla3QgdW50ZXIgZGVtIFZhcmlhYmxlbm5hbWVuLCBkYXMgaXN0IGbDvHIgdW5zIG5pY2h0IG9wdGltYWwgdW5kIGlzdCBkZXIgQW5vcmRudW5nIGluIGRlciBFeGNlbCBEYXRlaSBnZXNjaHVsZGV0LgoKICAgIC0gICBEaWVzIGvDtm5uZW4gd2lyIGFtIGVpbmZhY2hzdGVuIGJlcmVpbmlnZW4gaW5kZW0gd2lyIGFsbGUgYE5BYHMgaW0gUmVnaW9uYWxzY2hsw7xzc2VsIGVudGZlcm5lbiAoa2VpbiBSZWdpb25hbHNjaGzDvHNzZWwgYmVkZXV0ZXQga2VpbmUgWnVvcmRudW5nIHp1IGVpbmVyIFJlZ2lvbiB1bmQgZGFtaXQgZsO8ciB1bnMgbmljaHQgbmFjaHZvbGx6aWVoYmFyKS4KCi0gICBEaWUgVmFyaWFibGVuICJFaW53b2huZXIiLCAiU2NodWxkZW5fZ2VzYW10IiB1bmQgIlNjaHVsZGVuX3Byb19Lb3BmIiBzaW5kIGFsbGUgYWxzIGBjaGFyYWN0ZXJgIGhpbnRlcmxlZ3QgKGA8Y2hyPmAgdW50ZXIgZGVtIFZhcmlhYmxlbm5hbWVuIGluIGRlciB2b3JoZXJpZ2VuIFRhYmVsbGUpLCB3aXIgd29sbGVuIGRpZXNlIGplZG9jaCBpbiBudW1lcmlzY2hlciBGb3JtIHVtIEJlcmVjaG51bmdlbiBkdXJjaGbDvGhyZW4genUga8O2bm5lbgoKICAgIC0gICBEZXIgR3J1bmQgZsO8ciBkaWUgS2xhc3NlIGBjaGFyYWN0ZXJgIGthbm4gei5CLiBpbiBaZWlsZSAyOCBiZW9iYWNodGV0IHdlcmRlbi4gSGllciB3dXJkZW4gZ2VzY2h3ZWlmdGUgS2xhbW1lcm4gdmVyd2VuZGV0IHVtIGRpZSBTdW1tZSBhbGxlciBWYXJpYWJsZW4gZWluZXMgQW10c2dlYmlldHMsIExhbmRrcmVpcywgUmVnaW9uIGV0Yy4genUga2VubnplaWNobmVuLgogICAgLSAgIEltIGVyc3RlbiBTY2hyaXR0IHdvbGxlbiB3aXIgZGllc2UgU3VtbWVuIGVpbmZhY2ggaWdub3JpZXJlbiBkYSB3aXIgZGllIGpld2VpbGlnZW4gU3VtbWVuIGF1Y2ggc2VsYnN0IGJlcmVjaG5lbiBrw7ZubmVuLgoKLSBEaWUgIlZlcmFlbmRlcnVuZ19Wb3JqYWhyIiBpc3QgZsO8ciB1bnNlcmUgd2VpdGVyZSBBbmFseXNlIG5pY2h0IHJlbGV2YW50LCBkYWhlciB3b2xsZW4gd2lyIGRpZXNlIGF1cyBkZW0gRGF0ZW5zYXR6IGVudGZlcm5lbgoKQW5zY2hsaWXDn2VuZCB3b2xsZW4gd2lyIG5vY2ggZGVuIGBsYW5ka3JlaXNgIGFscyBkaWUgZXJzdGVuIDUgWmVpY2hlbiBpbSBSZWdpb25hbHNjaGzDvHNzZWwgZGVmaW5pZXJlbi4KCmBgYHtyLCB3YXJuaW5nPUZBTFNFLCBtZXNzYWdlPUZBTFNFfQojIERpZSBEYXRlbiB3dXJkZW4gbm9jaCBuaWNodCBzY2jDtm4gZWluZ2VsZXNlbiwgaW4gZGVyIEV4Y2VsIFRhYmVsbGUgCiMgd2FyZW4gZGllIFZhcmlhYmxlbm5hbWVuIMO8YmVyIG1laHJlcmUgUmVpaGVuIGdlem9nZW4sIGRpZXMgbcO8c3NlbiB3aXIgbm9jaCBhdXNnbGVpY2hlbgpzY2h1bGRlbl9iZXJlaW5pZ3QgPC0gc2NodWxkZW5faW5kaXZpZHVlbGwgJT4lCiAgZmlsdGVyKCFpcy5uYShSZWdpb25hbHNjaGx1ZXNzZWwpKSAlPiUKICBtdXRhdGUoU2NodWxkZW5fZ2VzYW10ID0gYXMubnVtZXJpYyhTY2h1bGRlbl9nZXNhbXQpLAogICAgICAgICBFaW53b2huZXIgPSBhcy5udW1lcmljKEVpbndvaG5lciksCiAgICAgICAgIFNjaHVsZGVuX3Byb19rb3BmID0gYXMubnVtZXJpYyhTY2h1bGRlbl9wcm9fa29wZikpICU+JQogIG11dGF0ZShsYW5ka3JlaXMgPSBzdHJfZXh0cmFjdChSZWdpb25hbHNjaGx1ZXNzZWwsICJeLns1fSIpKSAlPiUKICAjbWFuY2hlIExhbmRrcmVpc2UgaGFiZW4ga2VpbmUgSW5mb3MgenUgZGVuIEVpbndvaG5lcm4sIGRpZXNlIGVudGZlcm5lbiB3aXIKICBmaWx0ZXIoICFpcy5uYSggRWlud29obmVyICkpICU+JQogIHNlbGVjdCgtVmVyYWVuZGVydW5nX1ZvcmphaHIpCgpgYGAKCkVzIHd1cmRlbiBpbW1lciBub2NoIGVpbmlnZSBgTkFgcyBlcnpldWd0LgpEaWVzZSB3b2xsZW4gd2lyIHVucyBub2NoIG7DpGhlciBhbnNjaGF1ZW46CgpgYGB7cn0KZmlsdGVyKHNjaHVsZGVuX2JlcmVpbmlndCwgaXMubmEoRWlud29obmVyKSkKYGBgCgpXaXIgbcO8c3NlbiB3b2hsIG5vY2ggbWVociBhdXNzY2hsaWXDn2VuIGFscyBudXIgYE5BYHMgYmVpbSBSZWdpb25hbHNjaGzDvHNzZWwsIGluc2dlc2FtdCAyNDAwIEVpbnRyw6RnZSBiZWkgZGVuZW4gZGllIFZhcmlhYmxlICJFaW53b2huZXIiIG5pY2h0IHZvcmhhbmRlbiBpc3QuCldpciBoYXR0ZW4gYmVyZWl0cyBnZXNlaGVuLCBkYXNzIGRpZSBTdW1tZSBhbGxlciBFaW53b2huZXIgZWluZXMgTGFuZGtyZWlzZW4gbWl0IGB7IFphaGwgfWAgaW4gZGVyIEV4Y2VsLURhdGVpIGhlcnZvcmdlaG9iZW4gd2lyZC4KV2VubiB3aXIgaGllciBpbiBSIGVpbmUgVHlwdW13YW5kbHVuZyBlcnp3aW5nZW4sIGRhbm4ga2FubiBSIG1pdCBkZW4gYHt9YCBuaWNodHMgYW5mYW5nZW4gdW5kIGdpYnQgdW5zIGRlc2hhbGIgZWluIGBOQWAgYXVzLgpXaXIga8O2bm5lbiBoaWVyIGFsbGUgRWludHLDpGdlLCBiZWkgZGVuZW4gZGllIEVpbndvaG5lciBlaW4gYE5BYCBzdGVoZW4gaGFiZW4sIGzDtnNjaGVuLCBkYSB3aXIgZGllIERhdGVuIHNlbGJzdCBhdWYgQmFzaXMgZGVyIEluZm9ybWF0aW9uZW4genUgZGVuIEdlbWVpbmRlbiBkZXMgTGFuZGtyZWlzZXMgYmVyZWNobmVuIGvDtm5uZW4uCgpgYGB7cn0Kc2NodWxkZW5fYmVyZWluaWd0IDwtIHNjaHVsZGVuX2JlcmVpbmlndCAlPiUKICBmaWx0ZXIoICFpcy5uYSggRWlud29obmVyICkgKQpgYGAKCiMjIEtvbnNpc3RlbnpjaGVjawoKIyMjIEJlcmVjaG51bmcgZGVyIFNjaHVsZGVuIHBybyBLb3BmIHZvbiBIYW5kCgpVbSBkaWUgaW50ZXJuZSBWYWxpZGl0w6R0IHVuc2VyZXIgRGF0ZW4gYmV1cnRlaWxlbiB6dSBrw7ZubmVuIHdvbGxlbiB3aXIgaW0gZXJzdGVuIFNjaHJpdHQgZWluZSBWYXJpYWJsZSBgU2NodWxkZW5fcHJvX0tvcGZfbmV3YCBnZW5lcmllcmVuLCB3ZWxjaGUgZGllIGBTY2h1bGRlbl9wcm9fS29wZmAgdm9uIEhhbmQgYmVyZWNobmV0LgpXaWUgc2Nob24gW2ltIEFic2Nobml0dCBWYXJpYWJsZW4gdW1mb3JtZW5dKCN2YXJpYWJsZW4tdW1mb3JtZW4pIGVyd8OkaG50LCBtw7xzc2VuIHdpciBoaWVyZsO8ciBqZWRvY2ggZXJzdCBmb2xnZW5kZXMgYmVhY2h0ZW4sIGJldm9yIHdpciBCZXJlY2hudW5nZW4gZHVyY2hmw7xocmVuIGvDtm5uZW46CgotICAgV2lyIG3DvHNzZW4gZGllIGdlc2Nod2VpZnRlbiBLbGFtbWVybiBlbnRmZXJuZW4gKG1pdCBgc3RyX3JlbW92ZV9hbGxgKSwgYWxzIGF1Y2ggZGllIExlZXJ6ZWljaGVuIGlubmVyaGFsYiBkZXIgWmFobGVuICh6LkIuIDE1IDY1MyksIHdhcyB3aXIgbWl0IGBnc3ViKCJbWzpzcGFjZTpdXSIpYCBlcnJlaWNoZW4uIFR1biB3aXIgZGFzIG5pY2h0LCBzbyB3w7xyZGVuIHdpciB3aWVkZXIgYE5BYHMgaW0gRGF0ZW5zYXR6IGVyaGFsdGVuLgotICAgRHVyY2ggZGllIGlmZWxzZSBCZWRpbmd1bmcgd2lyZCBkZXIgQmVmZWhsIGBzdHJfcmVtb3ZlX2FsbGAgbnVyIGFuZ2V3ZW5kZXQsIHdlbm4gdGF0c8OkY2hsaWNoIGdlc2Nod2VpZnRlIEtsYW1tZXJuIHZvcmhhbmRlbiBzaW5kCgpgYGB7ciwgd2FybmluZz1GQUxTRSwgbWVzc2FnZT1GQUxTRX0KIyBFcnN0ZWxsZW4gZGVyIFZlcmdsZWljaHN0YWJlbGxlCnNjaHVsZGVuX2NvbnNpc3RlbmN5IDwtIHNjaHVsZGVuX2luZGl2aWR1ZWxsICU+JQogIGZpbHRlciggIWlzLm5hKEVpbndvaG5lcikgJiAhaXMubmEoUmVnaW9uYWxzY2hsdWVzc2VsKSApICU+JQogIG11dGF0ZShTY2h1bGRlbl9nZXNhbXQgPSBpZmVsc2UoaXMubmEoYXMubnVtZXJpYyhTY2h1bGRlbl9nZXNhbXQpKT09VFJVRSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhcy5udW1lcmljKGdzdWIoIltbOnNwYWNlOl1dIiwgIiIsIHN0cl9yZW1vdmVfYWxsKFNjaHVsZGVuX2dlc2FtdCwgIlt7fV0iKSkpLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFzLm51bWVyaWMoU2NodWxkZW5fZ2VzYW10KSksCiAgICAgICAgIFNjaHVsZGVuX3Byb19rb3BmID0gaWZlbHNlKGlzLm5hKGFzLm51bWVyaWMoU2NodWxkZW5fcHJvX2tvcGYpKT09VFJVRSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFzLm51bWVyaWMoZ3N1YigiW1s6c3BhY2U6XV0iLCAiIiwgc3RyX3JlbW92ZV9hbGwoU2NodWxkZW5fcHJvX2tvcGYsICJbe31dIikpKSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFzLm51bWVyaWMoU2NodWxkZW5fcHJvX2tvcGYpKSwKICAgICAgICAgRWlud29obmVyX251bSA9IGlmZWxzZShpcy5uYShhcy5udW1lcmljKEVpbndvaG5lcikpPT1UUlVFLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhcy5udW1lcmljKGdzdWIoIltbOnNwYWNlOl1dIiwgIiIsIHN0cl9yZW1vdmVfYWxsKEVpbndvaG5lciwgIlt7fV0iKSkpLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhcy5udW1lcmljKEVpbndvaG5lcikpLAogICAgICAgICBTY2h1bGRlbl9wcm9fa29wZl9uZXcgPSByb3VuZChTY2h1bGRlbl9nZXNhbXQgLyBFaW53b2huZXJfbnVtLDIpKSAlPiUKICBtdXRhdGUobGFuZGtyZWlzID0gc3RyX2V4dHJhY3QoUmVnaW9uYWxzY2hsdWVzc2VsLCAiXi57NX0iKSwKICAgICAgICAgZGlmZmVyZW56ID0gU2NodWxkZW5fcHJvX2tvcGYgLSBTY2h1bGRlbl9wcm9fa29wZl9uZXcpIApgYGAKCk51biBrw7ZubmVuIHdpciB1bnMgYW5zY2hhdWVuLCBvYiBkaWUgdm9uIHVucyBiZXJlY2huZXRlbiB1bmQgZGllIHZvbSBTdGF0aXN0aXNjaGVuIEJ1bmRlc2FtdCBhbmdlZ2ViZW5lbiBXZXJ0ZSB6dSBkZW4gIlNjaHVsZGVuX3Byb19Lb3BmIiBzaWduaWZpa2FudCB2b25laW5hbmRlciBhYndlaWNoZW46CgpgYGB7cn0KIyByYW5nZShzY2h1bGRlbl9jb25zaXN0ZW5jeSRkaWZmZXJlbnopCiMgb2RlciBzY2jDtm5lIHNraW0Kc2tpbV93aXRob3V0X2NoYXJ0cyhzY2h1bGRlbl9jb25zaXN0ZW5jeSRkaWZmZXJlbnopCmBgYAoKRGllIERpZmZlcmVuemVuIGxpZWdlbiB6d2lzY2hlbiArLy0gNTAgQ2VudCB1bmQga8O2bm5lbiB2ZXJtdXRsaWNoIGF1ZiBSdW5kdW5nc2ZlaGxlciB6dXLDvGNrZ2Vmw7xocnQgd2VyZGVuLgpELmguIGhpZXIga8O2bm5lbiB3aXIgZGllIHZvbSBzdGF0aXN0aXNjaGVuIEJ1bmRlc2FtdCBoZXJhdXNnZWdlYmVuZW4gQmVyZWNobnVuZ2VuIGF1ZiBHZW1laW5kZWViZW5lIHZlcmlmaXppZXJlbi4KCiMjIyBWZXJnbGVpY2ggZGVyIFNjaHVsZGVuIHBybyBLb3BmIGF1ZiBMYW5ka3JlaXNlYmVuZQoKSW4gZWluZW0gd2VpdGVyZW4gS29uc2lzdGVuemNoZWNrIHdvbGxlbiB3aXIgZGllIGR1cmNoc2Nobml0dGxpY2hlIFZlcnNjaHVsZHVuZyBwcm8gS29wZiBhdWYgTGFuZGtyZWlzZWJlbmUgc2VsYnN0IGJlcmVjaG5lbiB1bmQgZGllc2UgbWl0IGRlbiB2b20gU3RhdGlzdGlzY2hlbiBCdW5kZXNhbXQgYW5nZWdlYmVuZW4gV2VydGVuIGluIGRlciBUYWJlbGxlIGFiZ2xlaWNoZW4uCgpIaWVyZsO8ciBlbnRuZWhtZW4gd2lyIGRlciBUYWJlbGxlIHp1ZXJzdCBhbGxlIEluZm9ybWF0aW9uZW4gYnpnbC4KQW56YWhsIGRlciAiRWlud29obmVyIiwgIlNjaHVsZGVuX2dlc2FtdCIgdW5kICJTY2h1bGRlbl9wcm9fS29wZiIgZsO8ciBkaWUgTGFuZGtyZWlzZS4KSW0gRGF0ZW5zYXR6IHNlaGVuIHdpciwgZGFzcyBkaWUgUmVnaW9uYWxzY2hsdWVzc2VsIGbDvHIgTGFuZGtyZWlzZSBkaWUgV29ydGUgIlN1bW1lIiB1bmQgIktyZWlzIiBlbnRoYWx0ZW4sIHdlbm4gZGFzIFN0YXRpc3Rpc2NoZSBCdW5kZXNhbXQgZGllIERhdGVuIGF1ZiBMYW5ka3JlaXNlYmVuZSBhZ2dyZWdpZXJ0LgpEYXMgd29sbGVuIHdpciBpbSBmb2xnZW5kZW4gbnV0emVuOgoKYGBge3J9CiMgV2lyIGZpbHRlcm4gYWxsZSBSZWloZW4gaGVyYXVzLCB3ZWxjaGUgIl9TdW1tZSIgb2RlciAiS3JlaXMiIGltIFJlZ2lvbmFsc2NobMO8c3NlbCBhdWZ3ZWlzZW4KIyBBbnNjaGxpZcOfZW5kIGJlcmVjaG5lbiB3aXIgZGllIGR1cmNoc2Nobml0dGxpY2hlIFZlcnNjaHVsZHVuZyBhdWYgTGFuZGtyZWlzZWJlbmUKYXZnX3ZlcnNjaF9rcmVpcyA8LSBzY2h1bGRlbl9jb25zaXN0ZW5jeSAlPiUKICBmaWx0ZXIoc3RyX2RldGVjdChSZWdpb25hbHNjaGx1ZXNzZWwsICJfU3VtbWUiKSAmIHN0cl9kZXRlY3QoUmVnaW9uYWxzY2hsdWVzc2VsLCAiS3JlaXMiKSkgJT4lCiAgZ3JvdXBfYnkobGFuZGtyZWlzLCBHZW1laW5kZSkgJT4lCiAgc3VtbWFyaXNlKGF2Z192ZXJzY2h1bGR1bmcgPSBTY2h1bGRlbl9wcm9fa29wZiwgZWlud29obmVyID0gRWlud29obmVyX251bSwgCiAgICAgICAgICAgIEdlc2FtdHNjaHVsZCA9IFNjaHVsZGVuX2dlc2FtdCkgJT4lCiAgYXJyYW5nZShkZXNjKGF2Z192ZXJzY2h1bGR1bmcpKQoKIyBIaWVyIGJlcmVjaG5lbiB3aXIgZGllIERhdGVuIHNlbGJzdAphdmdfdmVyc2NoX2tyZWlzX2NhbGMgPC0gc2NodWxkZW5fY29uc2lzdGVuY3kgJT4lCiAgIyBFcnNldHplIEVpbndvaG5lcl9udW0gbWl0IDAgZsO8ciBhbGxlIFJlZ2lvbmFsc2NobMO8c3NlbCBrbGVpbmVyIGFscyAxMgogIG11dGF0ZShFaW53b2huZXJfbnVtID0gaWZlbHNlKG5jaGFyKFJlZ2lvbmFsc2NobHVlc3NlbCk8MTIsMCwgRWlud29obmVyX251bSkpICU+JQogICMgTnVyIEdlbWVpbmRlbiBiZXRyYWNodGVuCiAgZmlsdGVyKG5jaGFyKFJlZ2lvbmFsc2NobHVlc3NlbCk+PTUgJiBzdHJfZGV0ZWN0KFJlZ2lvbmFsc2NobHVlc3NlbCwgIl9TdW1tZSIpPT1GQUxTRSkgJT4lCiAgIyBBdWYgTGFuZGtyZWlzZWJlbmUgZ3J1cHBpZXJlbgogIGdyb3VwX2J5KGxhbmRrcmVpcykgJT4lCiAgc3VtbWFyaXNlKGVpbndvaG5lcl9jYWxjID0gc3VtKEVpbndvaG5lcl9udW0pLCBHZXNhbXRzY2h1bGRfY2FsYyA9IHN1bShTY2h1bGRlbl9nZXNhbXQpLCAKICAgICAgICAgICAgYXZnX3ZlcnNjaHVsZHVuZ19jYWxjID0gcm91bmQoR2VzYW10c2NodWxkX2NhbGMvZWlud29obmVyX2NhbGMsMikpICU+JQogIGFycmFuZ2UoZGVzYyhhdmdfdmVyc2NodWxkdW5nX2NhbGMpKQoKIyBWZXJiaW5kZSBiZWlkZSBEYXRlbnPDpHR6ZSB1bmQgYmVyZWNobmUgb2IgZXMgc2lnaW5maWthbnRlIEFid2VpY2h1bmdlbiB6d2lzY2hlbiAKIyBkZW4gYXVzZ2VnZWJlbmVuIHVuZCBiZXJlY2huZXRlbiBXZXJ0ZW4gZ2lidApuZXcgPC0gbGVmdF9qb2luKGF2Z192ZXJzY2hfa3JlaXMsIGF2Z192ZXJzY2hfa3JlaXNfY2FsYywgYnk9ImxhbmRrcmVpcyIpICU+JQogIG11dGF0ZShkaWZmZXJlbnogPSBhdmdfdmVyc2NodWxkdW5nIC0gYXZnX3ZlcnNjaHVsZHVuZ19jYWxjKSAlPiUKICBhcnJhbmdlKCBkZXNjKGRpZmZlcmVueikgKQpgYGAKCmBgYHtyfQojIEVyZ2VibmlzIGFuc2NoYXVlbgojcmFuZ2UobmV3JGRpZmZlcmVueikKIyBvZGVyIG1pdCBza2ltCnNraW1fd2l0aG91dF9jaGFydHMobmV3JGRpZmZlcmVueikKYGBgCgpEaWUgRGlmZmVyZW56ZW4gbGllZ2VuIGhpZXIgendpc2NoZW4gLTE1NCw0NCBFdXJvIGJpcyArMCw1MCBFdXJvIChpbSBEdXJjaHNjaG5pdHQgYmVpIC0wLDUyIEV1cm8pIHVuZCBrw7ZubmVuIHZlcm11dGxpY2ggYXVmIFJ1bmR1bmdzZmVobGVyIHp1csO8Y2tnZWbDvGhydCB3ZXJkZW4uCkQuaC4gaGllciBrw7ZubmVuIHdpciBkaWUgdm9tIHN0YXRpc3Rpc2NoZW4gQnVuZGVzYW10IGhlcmF1c2dlZ2ViZW5lbiBCZXJlY2hudW5nZW4gYXVmIExhbmRrcmVpc2ViZW5lIHZlcmlmaXppZXJlbi4KRGVyIExhbmRrcmVpcyBMw7xjaG93LURhbm5lbmJlcmcgYmlsZGV0IGVpbmUgQXVzbmFobWUgbWl0IC0xNTQsNDQgRXVyby4KCiMgQnJ1dHRvaW5sYW5kc3Byb2R1a3QKCkltIG7DpGNoc3RlbiBTY2hyaXR0IHdvbGxlbiB3aXIgdW5zIGRpZSBEYXRlbiB6dW0gQnJ1dHRvaW5sYW5kc3Byb2R1a3QgZWluemVsbmVyIExhbmRrcmVpc2UgYW5zY2hhdWVuIHVuZCBkaWVzZSBpbiBSIGVpbmxlc2VuLgpXaXIgaGFiZW4gZGllc2UgZGlyZWt0IGFscyBFeGNlbCBEYXRlaSBoZXJ1bnRlcmdlbGFkZW4gdW5kIGvDtm5uZW4gZGllIERhdGVpIGRpcmVrdCBpbiBSIGVpbmxlc2VuLgpOZWJlbiBkZW0gQklQIGJlemllaGVuIHdpciBhdXMgZGllc2VtIEV4Y2VsLUZpbGUgZGllIEFuemFobCBhbiBFcndlcmJzdMOkdGlnZW4sIG1pdCBkZW5lbiB3aXIgc3DDpHRlciBkaWUgQXJiZWl0c2xvc2VucXVvdGUgYmVyZWNobmVuIGvDtm5uZW4gdW5kIGRpZSBBbnphaGwgYW4gRWlud29obmVyLCBtaXQgZGVuZW4gd2lyIGRhcyBCSVAtcHJvLUtvcGYgYmVyZWNobmVuIGvDtm5uZW4uCgojIyBOdXIgZWluemVsbmUgU3BhbHRlbiBlaW5sZXNlbgoKRm9sZ2VuZGUgU2Nocml0dGUgd29sbGVuIHdpciBpbiBlaW5lbSBDaHVuayBlcmxlZGlnZW46CgotICAgQmV0cmFjaHRlbiBkZXIgRGF0ZW4KCiAgICAtICAgVGFiZWxsZW5ibGF0dCAiMS4xIiBpc3QgZsO8ciB1bnNlcmUgQW5hbHlzZSBhdXNzY2hsYWdnZWJlbmQgKGbDvHIgZGFzIEJJUCkKICAgIC0gICBUYWJlbGxlbmJsYXR0ICIzLjEiIGlzdCBmw7xyIGRpZSBBbnphaGwgYW4gRXJ3ZXJic3TDpHRpZ2VuIGF1c3NjaGxhZ2dlYmVuZAogICAgLSAgIFRhYmVsbGVuYmxhdHQgIjUiIGlzdCBmw7xyIGRpZSBBbnphaGwgYW4gRWlud29obmVybiBhdXNzY2hsYWdnZWJlbmQKCi0gICBEaWUgZXJzdGVuIHZpZXIgWmVpbGVuIGJlbsO2dGlnZW4gd2lyIG5pY2h0CgotICAgRGllIGxldHp0ZSBaZWlsZSBlbnRow6RsdCBlaW5lIGt1cnplIEJlc2NocmVpYnVuZyBkaWUgd2lyIG5pY2h0IGJlbsO2dGlnZW4gLT4gVm9yZ2VoZW46IEJlaGFsdGUgYWxsZSBaZWlsZW4sIGJlaSBkZXIgYExmZC4gTnIuYCBudW1lcmlzY2ggaXN0CgotICAgRGllIGZvbGdlbmRlbiBWYXJpYWJsZW4gYmVuw7Z0aWdlbiB3aXIgbmljaHQgZsO8ciB1bnNlcmUgQW5hbHlzZSB1bmQga8O2bm5lbiBlbnRmZXJudCB3ZXJkZW46IGBMZmQuIE5yLmAsIGBFVS1Db2RlYCwgYE5VVFMgMWAsIGBOVVRTIDJgLCBgTlVUUyAzYCwgYExhbmRgLCBgR2ViaWV0c2VpbmhlaXRgCgpgYGB7ciwgd2FybmluZz1GQUxTRSwgbWVzc2FnZT1GQUxTRX0KIyBCbGF0dCAxLjEgZWlubGVzZW4gdW5kIGRpZSBlcnN0ZW4gNCBaZWlsZW4gc2tpcHBlbgpiaXBfbmFtZSA8LSAiLi9kYXRhL0JJUF8yMDIyLnhsc3giCmJpcCA8LSByZWFkX3hsc3goYmlwX25hbWUsIHNoZWV0PSIxLjEiLCBza2lwID0gNCkKZXJ3ZXJiIDwtIHJlYWRfeGxzeChiaXBfbmFtZSwgc2hlZXQ9IjMuMSIsIHNraXAgPSA0KQplaW53b2huZXIgPC0gcmVhZF94bHN4KGJpcF9uYW1lLCBzaGVldCA9ICI1Iiwgc2tpcCA9IDQpCgojIFplaWxlIGzDtnNjaGVuIGluIGRlciBkaWUgYExmZC4gTnIuYCBuaWNodCBudW1tZXJpc2NoIGlzdAojIFp1c8OkdHpsaWNoZSBTcGFsdGVuIGzDtnNjaGVuCmJpcF93aWRlIDwtIGJpcCAlPiUgCiAgZmlsdGVyKGlzLm5hKGFzLm51bWVyaWMoYExmZC4gTnIuYCkpPT1GQUxTRSkgJT4lCiAgc2VsZWN0KC1jKGBMZmQuIE5yLmAsIGBFVS1Db2RlYCwgYE5VVFMgMWAsIGBOVVRTIDJgLCBgTlVUUyAzYCwgTGFuZCwgR2ViaWV0c2VpbmhlaXQpKSAlPiUKICByZW5hbWUoUmVnaW9uYWxzY2hsdWVzc2VsID0gYFJlZ2lvbmFsLXNjaGzDvHNzZWxgKQoKIyBaZWlsZSBsw7ZzY2hlbiBpbiBkZXIgZGllIGBMZmQuIE5yLmAgbmljaHQgbnVtbWVyaXNjaCBpc3QKIyBadXPDpHR6bGljaGUgU3BhbHRlbiBsw7ZzY2hlbgplcndlcmJfd2lkZSA8LSBlcndlcmIgJT4lIAogIGZpbHRlcihpcy5uYShhcy5udW1lcmljKGBMZmQuIE5yLmApKT09RkFMU0UpICU+JQogIHNlbGVjdCgtYyhgTGZkLiBOci5gLCBgRVUtQ29kZWAsIGBOVVRTIDFgLCBgTlVUUyAyYCwgYE5VVFMgM2AsIExhbmQsIEdlYmlldHNlaW5oZWl0KSkgJT4lCiAgcmVuYW1lKFJlZ2lvbmFsc2NobHVlc3NlbCA9IGBSZWdpb25hbC1zY2hsw7xzc2VsYCkKCmVpbndvaG5lcl93aWRlIDwtIGVpbndvaG5lciAlPiUKICBmaWx0ZXIoaXMubmEoYXMubnVtZXJpYyhgTGZkLiBOci5gKSk9PUZBTFNFKSAlPiUKICBzZWxlY3QoLWMoYExmZC4gTnIuYCwgYEVVLUNvZGVgLCBgTlVUUyAxYCwgYE5VVFMgMmAsIGBOVVRTIDNgLCBMYW5kLCBHZWJpZXRzZWluaGVpdCkpICU+JQogIHJlbmFtZShSZWdpb25hbHNjaGx1ZXNzZWwgPSBgUmVnaW9uYWwtc2NobMO8c3NlbGApCgpoZWFkKGJpcF93aWRlKQpgYGAKCkRpZXNlciBEYXRlbnNhdHogaXN0IGVpbiBzb2dlbmFubnRlcyBQYW5lbC4KSW4gZGVuIHZvcmhlcmlnZW4gRGF0ZW5zw6R0emVuIHp1ciBBbnphaGwgZGVyIEFyYmVpdHNsb3NlbiB1bmQgZGVyIFByby1Lb3BmLVZlcnNjaHVsZHVuZyBoYXR0ZW4gd2lyIFF1ZXJzY2huaXR0c2RhdGVuIChkLmguIERhdGVuIG51ciBkYXMgSmFociAyMDIxKSBnZWdlYmVuLgpOdW4gaGFiZW4gd2lyIGRpZSBFbnR3aWNrbHVuZyBkZXMgQklQLCBkaWUgQW56YWhsIGFuIEVyd2VyYnN0w6R0aWdlbiB1bmQgZGllIEFuemFobCBhbiBFaW53b2huZXJuIHNlaXQgMTk5MiBiaXMgMjAyMSBmw7xyIGFsbGUgTGFuZGtyZWlzZSBpbiBEZXV0c2NobGFuZC4KCiMjIERhdGVuIGluIGRhcyBgbG9uZ2AtRm9ybWF0IMO8YmVyZsO8aHJlbgoKQWxsZXJkaW5ncyBzaW5kIGRpZSBEYXRlbnPDpHR6ZSBpbSBgd2lkZWAtRm9ybWF0LCBkLmguIG5pY2h0IGB0aWR5YCB1bmQgZGFtaXQgbmljaHQgc28sIHdpZSB3aXIgaWhuIGdlcm5lIGjDpHR0ZW4uCkVyaW5uZXJuIHdpciB1bnMgbm9jaCBhbiBkaWUgQmVkaW5ndW5nZW4gZGFtaXQgZWluIERhdGVuc8OkdHplbiBgdGlkeWAgaXN0PwoKSW0gbsOkY2hzdGVuIFNjaHJpdHQgd29sbGVuIHdpciBkZW4gRGF0ZW5zYXR6IG51biBpbnMgYGxvbmdgLUZvcm1hdCDDvGJlcmbDvGhyZW4gdW5kIG51dHplbiBoaWVyZsO8ciBkaWUgRnVua3Rpb24gYHBpdm90X2xvbmdlcmA6CgpgYGB7ciwgZXZhbD1GQUxTRX0KYmlwX2xvbmcgPC0gcGl2b3RfbG9uZ2VyKGJpcF93aWRlLCBjb2xzID0gYygiMTk5MiI6IjIwMjEiKSAsIG5hbWVzX3RvID0gIkphaHIiLCB2YWx1ZXNfdG8gPSAiQklQIikKCiMgUHJvZHV6aWVydCBkZW4gZm9sZ2VuZGVuIEZlaGxlcjoKIyBGZWhsZXI6IENhbid0IGNvbWJpbmUgYDE5OTJgIDxjaGFyYWN0ZXI+IGFuZCBgMjAwMGAgPGRvdWJsZT4uCmBgYAoKTGVpZGVyIGlzdCBlcyBoaWVyIG5pY2h0IG3DtmdsaWNoIGRpZSBEYXRlbnPDpHR6ZSBkaXJla3QgaW4gZGFzIGBsb25nYC1Gb3JtYXQgenUgw7xiZXJmw7xocmVuLCBpbnNiZXNvbmRlcmUgZGEgZGllIEtsYXNzZW4gZGVyIFZhcmlhYmxlbiAxOTkyIGJpcyAxOTk5IGBjaGFyYWN0ZXJgIHNpbmQgdW5kIGFiIDIwMDAgZGFubiBgZG91YmxlYC4KRGllcyBzYWd0IHVucyBkaWUgZXJzY2hlaW5lbmRlIEZlaGxlcm1lbGR1bmc6CgotLS0KCkZlaGxlcjogQ2FuJ3QgY29tYmluZSBgMTk5MmAgPGNoYXJhY3Rlcj4gYW5kIGAyMDAwYCA8ZG91YmxlPi4KCi0tLQoKRGEgd2lyIHdpc3NlbiwgZGFzcyBkYXMgQklQLCBkaWUgQW56YWhsIGFuIEVyd2VyYnN0w6R0aWdlbiB1bmQgZGllIEFuemFobCBhbiBFaW53b2huZXJuIG5vcm1hbGVyd2Vpc2UgbnVtZXJpc2NoIHdpZWRlcmdlZ2ViZW4gd2lyZCwgaXN0IHdvaGwgZGllIEtsYXNzZSBgZG91YmxlYCBrb3JyZWt0IHVuZCB3aXIgc29sbHRlbiBkaWUgU3BhbHRlbiB2b24gMTk5MiBiaXMgMTk5OSBlbnRzcHJlY2hlbmQgdW1mb3JtYXRpZXJlbi4KCmBgYHtyLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQojQklQIHZvbiAxOTkyIC0gMTk5OSB1bWZvcm1lbiAoYWxzIG51bWVyaXNjaGUgVmFyaWFibGUpCmJpcF9kb3VibGUgPC0gYmlwX3dpZGUgJT4lCiAgc2VsZWN0KGAxOTkyYDpgMTk5OWApICU+JQogIG11dGF0ZV9pZihpcy5jaGFyYWN0ZXIsIGFzLmRvdWJsZSkKCiMgRXJ3ZXJic3TDpHRpZ2Ugdm9uIDE5OTIgLSAxOTk5IHVtZm9ybWVuIChhbHMgbnVtZXJpc2NoZSBWYXJpYWJsZSkKZXJ3ZXJiX2RvdWJsZSA8LSBlcndlcmJfd2lkZSAlPiUKICBzZWxlY3QoYDE5OTJgOmAxOTk5YCkgJT4lCiAgbXV0YXRlX2lmKGlzLmNoYXJhY3RlciwgYXMuZG91YmxlKQoKIyBFaW53b2huZXIgdm9uIDE5OTIgLSAxOTk5IHVtZm9ybWVuIChhbHMgbnVtZXJpc2NoZSBWYXJpYWJsZSkKZWlud29obmVyX2RvdWJsZSA8LSBlaW53b2huZXJfd2lkZSAlPiUKICBzZWxlY3QoYDE5OTJgOmAxOTk5YCkgJT4lCiAgbXV0YXRlX2lmKGlzLmNoYXJhY3RlciwgYXMuZG91YmxlKQpgYGAKCldpciBiZWtvbW1lbiBoaWVyIGVpbmUgV2Fybm1lbGR1bmcgZGFzIGBOQWBzIGJlaSBkZXIgVW13YW5kbHVuZyBlcnpldWd0IHd1cmRlbi4KRGVyYXJ0aWdlIFdhcm51bmdlbiBzb2xsdGVuIHdpciBiZWFjaHRlbiB1bmQgYXVmIGRlbiBHcnVuZCBnZWhlbi4KTnVyIHNvIHdpc3NlbiB3aXIsIG9iIGRpZSBXYXJudW5nIGbDvHIgdW5zIHNww6R0ZXIgdW5iZWFic2ljaHRpZ3RlIEF1c3dpcmt1bmdlbiBoYXQuCgpIaWVyZsO8ciB2ZXJiaW5kZW4gd2lyIGRlbiBuZXVlbiBEYXRlbnNhdHogYGJpcF9kb3VibGVgIG1pdCB1bnNlcmVtIGJpc2hlciBiZXN0ZWhlbmRlbiBgYmlwX3dpZGVgIHVuZCBiZXRyYWNodGVuIGRpZSBTcGFsdGVuIGluIGRlbmVuIGBiaXBfZG91YmxlYCBgTkFgcyBlbnRow6RsdDoKCmBgYHtyfQpiaXBfd2lkZV90ZXN0IDwtIGJpcF93aWRlICU+JQogIGJpbmRfY29scyhiaXBfZG91YmxlKQoKaGVhZChmaWx0ZXIoYmlwX3dpZGVfdGVzdCwgaXMubmEoYDE5OTIuLi4zMWApKSkKYGBgCgpIaWVyIHNlaGVuIHdpciBiZXJlaXRzIHdhcnVtIGRpZSBLbGFzc2UgZGVyIFZhcmlhYmxlbiBgMTk5MmAgYmlzIGAxOTk5YCBgY2hhcmFjdGVyYCB3YXIgdW5kIG5pY2h0IGBkb3VibGVgLgpGw7xyIGRpZXNlIEphaHJlIGdhYiBlcyBmw7xyIGVpbmlnZSBSZWdpb25lbiAoTWVja2xlbmJ1cmctVm9ycG9tbWVybiB1bmQgTmllZGVyc2FjaGVuKSBrZWluZSBBbmdhYmVuIHp1bSBCSVAsIGRlbiBFcndlcmJzdMOkdGlnZW4gb2RlciBkZW4gRWlud29obmVybiB1bmQgZGFoZXIgd3VyZGVuIGluIGRlciBFeGNlbCBUYWJlbGxlIGAtYCBlaW5nZWbDvGd0LgpEYWhlciBpc3QgZsO8ciB1bnMgZGllIFVtd2FuZGx1bmcgenUgYE5BYCBmb2xnZXJpY2h0aWcgdW5kIHdpciBrw7ZubmVuIGRpZSBXYXJubWVsZHVuZyBpZ25vcmllcmVuIHVuZCBudXIgZGllIHRyYW5zZm9ybWllcnRlbiBWYXJpYWJsZW4gbWl0IGRlciBLbGFzc2UgYGRvdWJsZWAgdmVyd2VuZGVuOgoKYGBge3J9CmJpcF93aWRlIDwtIGJpcF93aWRlICU+JQogIHNlbGVjdCgtKGAxOTkyYDpgMTk5OWApKSAlPiUKICBiaW5kX2NvbHMoYmlwX2RvdWJsZSkgCgplcndlcmJfd2lkZSA8LSBlcndlcmJfd2lkZSAlPiUKICBzZWxlY3QoLShgMTk5MmA6YDE5OTlgKSkgJT4lCiAgYmluZF9jb2xzKGVyd2VyYl9kb3VibGUpIAoKZWlud29obmVyX3dpZGUgPC0gZWlud29obmVyX3dpZGUgJT4lCiAgc2VsZWN0KC0oYDE5OTJgOmAxOTk5YCkpICU+JQogIGJpbmRfY29scyhlaW53b2huZXJfZG91YmxlKSAKYGBgCgpOdW4ga8O2bm5lbiB3aXIgZGVuIERhdGVuc2F0eiBpbnMgYGxvbmdgLUZvcm1hdCB0cmFuc2ZlcmllcmVuIHVuZCBuYWNoIGRlbSBKYWhyIHNvcnRpZXJlbi4KRGEgZGllIEVpbndvaG5lciB1bmQgRXJ3ZXJic3TDpHRpZ2VuIGluIDEwMDAgUGVyc29uZW4gYW5nZWdlYmVuIHNpbmQgbXVsdGlwbGl6aWVyZW4gd2lyIHVuc2VyZSBFcndlcmJzdMOkdGlnZW4gdW5kIEVpbndvaG5lciBtaXQgMTAwMC4KRGFzIEJJUCBpc3QgaW4gMSBNaW8uCkV1cm8gYW5nZWdlYmVuLCBkYWhlciBkaWUgTXVsdGlwbGlrYXRpb24gbWl0IDEgTWlvLjoKCmBgYHtyfQojIEJJUCBpbnMgbG9uZy1Gb3JtYXQKYmlwX2xvbmcgPC0gcGl2b3RfbG9uZ2VyKGJpcF93aWRlLCBjb2xzID0gYygiMjAwMCI6IjE5OTkiKSAsIG5hbWVzX3RvID0gIkphaHIiLCB2YWx1ZXNfdG8gPSAiYmlwIikgJT4lCiAgbXV0YXRlKCBKYWhyID0gYXMubnVtZXJpYyhKYWhyKSwKICAgICAgICAgIGJpcCA9IGJpcCAqIDEwMDAwMDApICU+JQogIGFycmFuZ2UoIEphaHIgKQoKIyBBbnphaGwgZGVyIEVyd2VyYnN0w6R0aWdlbiBpbnMgbG9uZy1Gb3JtYXQKZXJ3ZXJiX2xvbmcgPC0gcGl2b3RfbG9uZ2VyKGVyd2VyYl93aWRlLCBjb2xzID0gYygiMjAwMCI6IjE5OTkiKSAsIG5hbWVzX3RvID0gIkphaHIiLCB2YWx1ZXNfdG8gPSAiZXJ3IikgJT4lCiAgbXV0YXRlKCBKYWhyID0gYXMubnVtZXJpYyhKYWhyKSwKICAgICAgICAgIGVydyA9IGVydyAqIDEwMDApICU+JQogIGFycmFuZ2UoIEphaHIgKQoKIyBBbnphaGwgZGVyIEVpbndvaG5lciBpbnMgbG9uZy1Gb3JtYXQKZWlud29obmVyX2xvbmcgPC0gcGl2b3RfbG9uZ2VyKGVpbndvaG5lcl93aWRlLCBjb2xzID0gYygiMjAwMCI6IjE5OTkiKSAsIG5hbWVzX3RvID0gIkphaHIiLCB2YWx1ZXNfdG8gPSAiZWlud29obmVyIikgJT4lCiAgbXV0YXRlKCBKYWhyID0gYXMubnVtZXJpYyhKYWhyKSwKICAgICAgICAgIGVpbndvaG5lciA9IGVpbndvaG5lciAqIDEwMDApICU+JQogIGFycmFuZ2UoIEphaHIgKQpgYGAKCiMjIEtvbnNpc3RlbnpjaGVja3MKCldpciBoYWJlbiBiZXJlaXRzIGluIGRlbSBBYnNjaG5pdHQgIlByby1Lb3BmIFZlcnNjaHVsZHVuZyIgZGllIEVpbndvaG5lciB6dXIgQmVyZWNobnVuZyBkZXIgUHJvLUtvcGYtVmVyc2NodWxkdW5nIGbDvHIgMjAyMSBlaW5nZWxlc2VuLgpGw7xyIGVpbmUgbMOkbmdlcmZyaXN0aWdlIEJldHJhY2h0dW5nIGtvbm50ZW4gd2lyIG51biBtaXQgZGVtIEJJUCBEYXRlbnNhdHogZGllIEFuemFobCBkZXIgRWlud29obmVyIHZvbiAxOTkyIGJpcyAyMDIxIGVpbmxlc2VuLgpJbiBkaWVzZW0gS29uc2lzdGVuemNoZWNrIHdvbGxlbiB3aXIgdW50ZXJzdWNoZW4gb2IgZGllIEFuemFobCBkZXIgRWlud29obmVyIGF1cyBiZWlkZW4gRGF0ZW5xdWVsbGVuIGluIDIwMjEgaWRlbnRpc2NoIGlzdC4KSGllcmJlaSBpc3QgZXMgbmF0w7xybGljaCB3aWNodGlnLCB3YW5uIGRpZSBEYXRlbiB6dXIgRWlud29obmVyemFobCBlcmhvYmVuIHd1cmRlbiB1bmQgZGVzaGFsYiBrw7ZubnRlbiBkaWVzZSBhdWNoIGdlcmluZ2bDvGdpZyBhYndlaWNoZW4uCkFiZXIgZGVtIGdlaGVuIHdpciBudW4gYXVmIGRlbiBHcnVuZDoKCmBgYHtyfQpzY2h1bGRlbl9jaGVjayA8LSBzY2h1bGRlbl9iZXJlaW5pZ3QgJT4lCiAgZ3JvdXBfYnkobGFuZGtyZWlzKSAlPiUKICBzdW1tYXJpc2UoIFNjaHVsZGVuX3Byb19rb3BmX2xrID0gc3VtKFNjaHVsZGVuX2dlc2FtdCkvc3VtKEVpbndvaG5lciksIEVpbndvaG5lciA9IHN1bShFaW53b2huZXIpLCBTY2h1bGRlbl9nZXNhbXQgPSBzdW0oU2NodWxkZW5fZ2VzYW10KSkgJT4lCiAgcmVuYW1lKFJlZ2lvbmFsc2NobHVlc3NlbCA9IGxhbmRrcmVpcykKCmVpbndvaG5lcl9jaGVjayA8LSBsZWZ0X2pvaW4oc2NodWxkZW5fY2hlY2ssIGZpbHRlcihlaW53b2huZXJfbG9uZywgSmFociA9PSAyMDIxKSwgYnk9YygiUmVnaW9uYWxzY2hsdWVzc2VsIikpICU+JQogIG11dGF0ZShkaWZmID0gRWlud29obmVyIC0gZWlud29obmVyKSAlPiUKICBhcnJhbmdlKGRlc2MoZGlmZikpCgpza2ltX3dpdGhvdXRfY2hhcnRzKGVpbndvaG5lcl9jaGVjayRkaWZmKQoKaGVhZChhcnJhbmdlKGVpbndvaG5lcl9jaGVjaywgLWRpZmYpLDIwKQpgYGAKCkRpZSBEaWZmZXJlbnogbGllZ3QgaW0gRHVyY2hzY2huaXR0IGJlaSAzMSBFaW53b2huZXJuLCB3YXMgaW0gVG9sZXJhbnpiZXJlaWNoIGJlaSBkZW4gZ3Jvw59lbiBTdMOkZHRlIG1pdCBtZWhyIGFscyAxMjAuMDAwIEVpbndvaG5lcm4gaXN0LgpEZXIgZWluemlnZSBleHRyZW1lIEF1c3JlaXNlciBpc3QgZGVyIFdhcnRidXJna3JlaXMuCkhpZXIgZ2VoZW4gZGllIEVpbndvaG5lcnphaGxlbiB1bSAzOCA3MTkgUGVyc29uZW4gYXVzZWluYW5kZXIuCkxhdXQgW1dpa2lwZWRpYV0oaHR0cHM6Ly9kZS53aWtpcGVkaWEub3JnL3dpa2kvV2FydGJ1cmdrcmVpcyNjaXRlX25vdGUtTWV0YWRhdGVuX0VpbndvaG5lcnphaGxfREUtVEgtMSkgd2FyZW4gZGllIERhdGVuIGJpcyAyMDIwIG9obmUgZGllIEtyZWlzZnJlaWUgU3RhZHQgRWlzZW5hY2guIERhZHVyY2ggZ2FiIGVzIGxhdXQgV2lraXBlZGlhIGVpbmVuIFNwcnVuZyB2b24gNDAgOTMzIFBlcnNvbmVuLCBkaWUgYWIgMjAyMSB6dSBkZW4gRWlud29obmVybiBnZXrDpGhsdCB3dXJkZW4sIGQuaC4gZGllIEFid2VpY2h1bmdlbiBpbiBkZW4gRWlud29obmVyemFobGVuIGvDtm5udGVuIGd1dCBpbSBaZWl0cHVua3QgZGVyIEVyaGVidW5nIGRlciBFaW53b2huZXJ6YWhsZW4gYmVncsO8bmRldCBzZWluLgpEYWhlciB3ZXJkZW4gd2lyIGRlbiBEaWZmZXJlbnplbiBuaWNodCB3ZWl0ZXIgbmFjaGdlaGVuLgoKVW0gZGllIGxhbmdmcmlzdGlnZW4gRW50d2lja2x1bmdlbiBkZXMgQklQIHBybyBLb3BmIHp1IHZpc3VhbGlzaWVyZW4gd2VyZGVuIHdpciBkaWUgZGF6dWdlaMO2cmlnZW4gRWlud29obmVyemFobGVuIGF1cyBkZXIgRGF0ZW5xdWVsbGUgenVtIEJJUCB2ZXJ3ZW5kZW4uCkbDvHIgZGllIFByby1Lb3BmLVZlcnNjaHVsZHVuZyBqZWRvY2ggZGllIGluIGRlciAiSW50ZWdyaWVydGVuIFNjaHVsZGVuIGRlciBHZW1laW5kZW4iIGFuZ2VnZWJlbmVuIEVpbndvaG5lcnphaGwuCgojIEthcnRlbm1hdGVyaWFsIGhpbnp1ZsO8Z2VuIChvcHRpb25hbCkKCkbDvHIgZWluZSBzcMOkdGVyZSBWaXN1YWxpc2llcnVuZyBkZXIgRGF0ZW4gbWl0dGVscyBlaW5lciBEZXV0c2NobGFuZGthcnRlIHNvbGx0ZW4gd2lyIHVucyBub2NoIEluZm9ybWF0aW9uZW4genUgZGVuIGVpbnplbG5lbiBWZXJ3YWx0dW5zZ3JlbnplbiBhbHMgU0hBUEUtRmlsZSBoZXJ1bnRlcmxhZGVuLgpEaWVzZSBJbmZvcm1hdGlvbmVuIHNpbmQgw7xiZXIgZGFzIFtPcGVuRGF0YSBQb3J0YWwgZGVzIEJ1bmRlc2FtdHMgZsO8ciBLYXJ0b2dyYXBoaWUgdW5kIEdlb2TDpHNpZV0oaHR0cHM6Ly9nZHouYmtnLmJ1bmQuZGUvaW5kZXgucGhwL2RlZmF1bHQvb3Blbi1kYXRhL3ZlcndhbHR1bmdzZ2ViaWV0ZS0xLTI1MC0wMDAtZWJlbmVuLXN0YW5kLTAxLTAxLXZnMjUwLWViZW5lbi0wMS0wMS5odG1sKSB2ZXJmw7xnYmFyLgoKW0RpZSBEb2t1bWVudGF0aW9uIGRlciBEYXRlbl0oaHR0cHM6Ly9zZy5nZW9kYXRlbnplbnRydW0uZGUvd2ViX3B1YmxpYy9nZHovZG9rdW1lbnRhdGlvbi9kZXUvdmcyNTAucGRmKSBzb2xsdGVuIHdpciB1bnMgaW1tZXIgenVlcnN0IGFuc2NoYXVlbiwgYmV2b3Igd2lyIGRpZSBEYXRlbnF1ZWxsZSBoZXJ1bnRlcmxhZGVuLgpEaWVzIGdpbHQgbmljaHQgbnVyIGbDvHIgZGllIEdlb2RhdGVuLCBzb25kZXJuIGFsbGdlbWVpbiBmw7xyIGFsbGUgRGF0ZW5yZWloZW4uCgpXaXIgZXh0cmFoaWVyZW4gdW5zIGhpZXIgZGllIEluZm9ybWF0aW9uZW4genUgZGVuIEdyZW56ZW4gZGVyIEdlbWVpbmRlbiwgVmVyd2FsdHVuZ3NlaW5oZWl0ZW4sIExhbmRrcmVpc2UgdW5kIEJ1bmRlc2zDpG5kZXIgdW5kIHNwZWljaGVybiBkaWVzZSBqZXdlaWxzIGVudHNwcmVjaGVuZCBhYi4KVW0gR2VvbWV0cmllZGF0ZW4gZWluenVsZXNlbiB1bmQgZGllc2Ugc3DDpHRlciBzY2jDtm4gYWxzIEthcnRlIGRhcnN0ZWxsZW4genUga8O2bm5lbiBtw7xzc2VuIHdpciBoaWVyIGRpZSBGdW5rdGlvbiBgc3RfcmVhZGAgYXVzIGRlbSBgc2ZgLVBha2V0IHZlcndlbmRlbjoKCmBgYHtyLCBtZXNzYWdlPUZBTFNFLCBpbmNsdWRlPUZBTFNFfQpsaWJyYXJ5KHNmKQoKIyBLYXJ0ZW5tYXRlcmlhbCBHZW1laW5kZWViZW5lCmlmICghZmlsZS5leGlzdHMoIi4vZGF0YS9LYXJ0ZW5tYXRlcmlhbF9EZXV0c2NobGFuZC56aXAiKSl7CiAgZG93bmxvYWQuZmlsZSgiaHR0cHM6Ly9kYXRlbi5nZHouYmtnLmJ1bmQuZGUvcHJvZHVrdGUvdmcvdmcyNTBfZWJlbmVuXzAxMDEvYWt0dWVsbC92ZzI1MF8wMS0wMS5nazMuc2hhcGUuZWJlbmVuLnppcCIsICIuL2RhdGEvS2FydGVubWF0ZXJpYWxfRGV1dHNjaGxhbmQuemlwIikKfQoKIyDDlmZmbmVuIGRlcyBaSVAtT3JkbmVycwprYXJ0ZW5fb3JkbmVyIDwtIGFzLmNoYXJhY3Rlcih1bnppcCgiLi9kYXRhL0thcnRlbm1hdGVyaWFsX0RldXRzY2hsYW5kLnppcCIsIGxpc3QgPSBUUlVFKSROYW1lKQoKIyBXaXIgd29sbGVuIG51ciBkaWUgRGF0ZWkgZW50emlwcGVuCnVuemlwKCIuL2RhdGEvS2FydGVubWF0ZXJpYWxfRGV1dHNjaGxhbmQuemlwIikKCiMgSW5mb3JtYXRpb25lbiB6dSBkZW4gR2VtZWluZGVuIGVpbmxlc2VuIChHRU0pCmdlbWVpbmRlbiA8LSBzdF9yZWFkKGthcnRlbl9vcmRuZXJbNTZdKQoKIyBJbmZvcm1hdGlvbmVuIHp1IFZlcndhbHR1bmdzZWJlbmVuIGVpbmxlc2VuIChWV0cpCnZlcndhbHR1bmcgPC0gc3RfcmVhZChrYXJ0ZW5fb3JkbmVyWzYzXSkKCiMgSW5mb3JtYXRpb25lbiB6dSBkZW4gTGFuZGtyZWlzZW4gZWlubGVzZW4gKEtSUykKbGFuZGtyZWlzZSA8LSBzdF9yZWFkKGthcnRlbl9vcmRuZXJbNjddKQoKIyBJbmZvcm1hdGlvbmVuIHp1IGRlbiBCdW5kc2zDpG5kZXJuIGVpbmxlc2VuIChMQU4pCmJ1bmRlc2xhbmQgPC0gc3RfcmVhZChrYXJ0ZW5fb3JkbmVyWzEyXSkKCiMgTnVuIGvDtm5uZW4gd2lyIGRlbiBlbnR6aXBwdGVuIE9yZG5lciB3aWVkZXIgbMO2c2NoZW4KdW5saW5rKGthcnRlbl9vcmRuZXJbMV0sIHJlY3Vyc2l2ZSA9IFRSVUUpCmBgYAoKRGEgd2lyIG51ciBkaWUgSW5mb3JtYXRpb25lbiB6dXIgR2VvbWV0cmllLCB6LkIuIGRlciBMYW5ka3JlaXNncmVuemVuIG3DtmNodGVuLCBrw7ZubmVuIHdpciBkaWUgYW5kZXJlbiBWYXJpYWJsZW4gYXVjaCBhdXMgZGVtIERhdGVuc8OkdHogbMO2c2NoZW4uCldpciBiZWhhbHRlbiBkZW4gUmVnaW9uYWxzY2hsw7xzc2VsIChBUlMpLCBkZW4gTmFtZW4gZGVzIEtyZWlzZXMvZGVyIEdlbWVpbmRlIChHRU4pIHVuZCBkaWUgR2VvbWV0cmllIChnZW9tZXRyeSkuCgpXaXIgbcO8c3NlbiB1bnMgenVzw6R0emxpY2ggbm9jaCBldHdhcyBtaXQgZGVyIERva3VtZW50YXRpb24gZGVzIEthcnRlbm1hdGVyaWFscyBiZXNjaMOkZnRpZ2VuLgpEYSB3aXIgbnVyIGRpZSBWZXJ3YWx0dW5nc2VpbmhlaXRlbiBvaG5lIGRpZSBOb3JkLSB1bmQgT3N0c2VlIHVuZCBvaG5lIGRlbiBCb2RlbnNlZSBkYXJzdGVsbGVuIG3DtmNodGVuLCBzbyBtw7xzc2VuIHdpciBub2NoIGF1ZiBHRiA9IDQgZmlsdGVybiwgd2llIGF1ZiBTZWl0ZSA5IGRlciBEb2t1bWVudGF0aW9uIGJlc2NocmllYmVuIHdpcmQgKHR1biB3aXIgZGllcyBuaWNodCwgc28gaMOkdHRlbiB3aXIgZGllIE5vcmRzZWVnZWJpZXRlIGRvcHBlbHQgZHJpbik6CgotLS0KCioqR3J1bmRzw6R0emxpY2ggZ2lsdDoqKiBKZWRlIFZlcndhbHR1bmdzZWluaGVpdCBiZXNpdHp0IGdlbmF1IGVpbmVuIEF0dHJpYnV0c2F0eiBtaXQgZGVtIEdGLVdlcnQgNC4KWnVzw6R0emxpY2gga2FubiBlaW5lIFZlcndhbHR1bmdzZWluaGVpdCBlaW5lbiBBdHRyaWJ1dHNhdHogbWl0IGRlbSBHRi1XZXJ0IDIgYmVzaXR6ZW4uCgotLS0KCmBgYHtyfQojIEF1ZiBHRiA9PSA0IGZpbHRlcm4gdW5kIEFSUyBhbHMgU3RyaW5nIHNwZWljaGVybiAoaXN0IGFrdHVlbGwgYWxzIGZhY3RvciBhYmdlc3BlaWNoZXJ0KQpsYW5ka3JlaXNlIDwtIGxhbmRrcmVpc2UgJT4lCiAgZmlsdGVyKCBHRj09NCApICU+JSAKICBzZWxlY3QoQVJTLCBHRU4sIGdlb21ldHJ5KSAlPiUKICBtdXRhdGUoUmVnaW9uYWxzY2hsdWVzc2VsID0gYXMuY2hhcmFjdGVyKEFSUykpCgpnZW1laW5kZW4gPC0gZ2VtZWluZGVuICU+JQogIGZpbHRlciggR0Y9PTQgKSAlPiUKICBzZWxlY3QoQVJTLCBHRU4sIGdlb21ldHJ5KSAlPiUKICBtdXRhdGUoUmVnaW9uYWxzY2hsdWVzc2VsID0gYXMuY2hhcmFjdGVyKEFSUykpCgpidW5kZXNsYW5kIDwtIGJ1bmRlc2xhbmQgJT4lCiAgZmlsdGVyKCBHRj09NCApICU+JQogIHNlbGVjdChBUlMsIEdFTiwgZ2VvbWV0cnkpICU+JQogIG11dGF0ZShSZWdpb25hbHNjaGx1ZXNzZWwgPSBhcy5jaGFyYWN0ZXIoQVJTKSkKCmBgYAoKIyBEYXRlbnPDpHR6ZSB6dXNhbW1lbmbDvGhyZW4KCkluIGRpZXNlbSBsZXR6dGVuIEFic2Nobml0dCBtw7ZjaHRlbiB3aXIgYWxsZXMgZsO8ciBkaWUgbsOkY2hzdGVuIFNjaHJpdHRlIGRlciBDYXNlIFN0dWR5IHZvcmJlcmVpdGVuLgpHZW5hdWVyOiBXaXIgd29sbGVuIG5pY2h0IG51ciBkaWUgSW5mb3JtYXRpb25lbiBhdXMgZGVuIGVpbnplbG5lbiBEYXRlbnPDpHR6ZW4sIHNvbmRlcm4gYW0gQmVzdGVuIGVpbmVuIGtvbWJpbmllcnRlbiBEYXRlbnNhdHogYW5hbHlzaWVyZW4hCkhpZXJmw7xyIG3DvHNzZW4gd2lyIHp1ZXJzdCBkaWUgSW5mb3JtYXRpb25lbiB6dXIgVmVyc2NodWxkdW5nIGF1ZiBMYW5ka3JlaXNlYmVuZSBhZ2dyZWdpZXJlbiB1bmQgZGllIERhdGVuIHp1bSBCSVAgYXVmIGRhcyBKYWhyIDIwMjEgZWluc2NocsOkbmtlbi4KQW5zY2hsaWXDn2VuZCBrw7ZubmVuIHdpciBkaWUgRGF0ZW5zw6R0emUgYW5oYW5kIGRlcyBSZWdpb25hbHNjaGzDvHNzZWxzIG1pdGVpbmFuZGVyIHZlcmJpbmRlbi4KCldlaXRlcmhpbiB3b2xsZW4gd2lyIGRpZSBnZW9ncmFmaXNjaGVuIERhdGVuIHNlcGFyYXQgYWJzcGVpY2hlcm4gdW5kIGJlaSBCZWRhcmYgYW5oYW5kIGRlcyBSZWdpb25hbHNjaGzDvHNzZWxzIHp1IHVuc2VyZW0gRGF0ZW5zYXR6IGhpbnp1bWVyZ2VuLgpEZXIgUmVnaW9uYWxzY2hsw7xzc2VsIGRpZW50IHVucyBoaWVyYmVpIGFscyBlaW5kZXV0aWdlIElkZW50aWZpa2F0aW9uIGRlciBqZXdlaWxpZ2VuIEdlbWVpbmRlLgoKYGBge3J9CiMgU2NodWxkZW4gYXVmIExhbmRrcmVpc2ViZW5lCnNjaHVsZGVuX2tvbWJpIDwtIHNjaHVsZGVuX2JlcmVpbmlndCAlPiUKICBncm91cF9ieShsYW5ka3JlaXMpICU+JQogIHN1bW1hcmlzZSggU2NodWxkZW5fcHJvX2tvcGZfbGsgPSBzdW0oU2NodWxkZW5fZ2VzYW10KS9zdW0oRWlud29obmVyKSwgRWlud29obmVyID0gc3VtKEVpbndvaG5lciksIFNjaHVsZGVuX2dlc2FtdCA9IHN1bShTY2h1bGRlbl9nZXNhbXQpKSAlPiUKICByZW5hbWUoUmVnaW9uYWxzY2hsdWVzc2VsID0gbGFuZGtyZWlzKQoKCiMgQW56YWhsIGFuIEVyd2VyYnN0w6R0aWdlbiBmw7xyIGRhcyBKYWhyIDIwMjEKZXJ3ZXJiX2tvbWJpIDwtIGVyd2VyYl9sb25nICU+JQogIGZpbHRlcihuY2hhcihSZWdpb25hbHNjaGx1ZXNzZWwpID09IDUgJiBKYWhyID09IDIwMjEpICU+JQogIHNlbGVjdCgtSmFocikKCiMgQW56YWhsIGFuIEVpbndvaG5lciBmw7xyIGRhcyBKYWhyIDIwMjEKZWlud29obmVyX2tvbWJpIDwtIGVpbndvaG5lcl9sb25nICU+JQogIGZpbHRlcihuY2hhcihSZWdpb25hbHNjaGx1ZXNzZWwpID09IDUgJiBKYWhyID09IDIwMjEpICU+JQogIHNlbGVjdCgtSmFocikKCiMgTmFtZW4gZGVyIExhbmRrcmVpc2UKbGFuZGtyZWlzX25hbWUgPC0gbGFuZGtyZWlzZSAlPiUgCiAgc3RfZHJvcF9nZW9tZXRyeSgpICU+JQogIHNlbGVjdCgtQVJTKSAlPiUKICBtdXRhdGUoYnVuZGVzbGFuZCA9IHN0cl9leHRyYWN0KFJlZ2lvbmFsc2NobHVlc3NlbCwgIl4uezJ9IikpICU+JQogIHJlbmFtZShsYW5ka3JlaXNfbmFtZSA9IEdFTikKCiMgTmFtZW4gZGVyIEJ1bmRlc2zDpG5kZXIKYnVuZGVzbGFuZF9uYW1lIDwtIGJ1bmRlc2xhbmQgJT4lCiAgc3RfZHJvcF9nZW9tZXRyeSgpICU+JQogIHNlbGVjdCgtQVJTKSAlPiUKICByZW5hbWUoYnVuZGVzbGFuZCA9IFJlZ2lvbmFsc2NobHVlc3NlbCwKICAgICAgICAgYnVuZGVzbGFuZF9uYW1lID0gR0VOKQoKIyBBbnphaGwgZGVyIEVpbndvaG5lciBtaXQgZGVtIEJJUCB2ZXJiaW5kZW4gdW0gZGFzIEJJUCBwcm8gS29wZiBiZXJlY2huZW4genUga8O2bm5lbgpiaXBfemVpdHJlaWhlIDwtIGxlZnRfam9pbihiaXBfbG9uZywgZWlud29obmVyX2xvbmcsIGJ5PWMoIlJlZ2lvbmFsc2NobHVlc3NlbCIsICJKYWhyIikpICU+JQogIG11dGF0ZShiaXBfcHJvX2tvcGYgPSBiaXAgLyBlaW53b2huZXIpCgojIEJJUCBhdWYgTGFuZGtyZWlzZWJlbmUgaW0gSmFociAyMDIxCmJpcF9rb21iaSA8LSBiaXBfemVpdHJlaWhlICU+JQogIGZpbHRlcihuY2hhcihSZWdpb25hbHNjaGx1ZXNzZWwpID09IDUgJiBKYWhyID09IDIwMjEpICU+JQogIHNlbGVjdCgtYyhKYWhyLCBlaW53b2huZXIpKQoKIyBEYXRlbnPDpHR6ZSB6dXNhbW1lbmbDvGhyZW4KCiMgQmFzaXNkYXRlbnNhdHogLT4gQXJiZWl0c2xvc2VuemFobGVuIHBybyBMYW5ka3JlaXMKIyBOYW1lIGRlciBMYW5ka3JlaXNlIHp1bWVyZ2VuCmRhdGVuMSA8LSBsZWZ0X2pvaW4oYWxvX2xhbmRrcmVpcywgbGFuZGtyZWlzX25hbWUsIGJ5ID0gIlJlZ2lvbmFsc2NobHVlc3NlbCIpCiMgTmFtZW4gZGVyIEJ1bmRlc2zDpG5kZXIgenVtZXJnZW4KZGF0ZW4xIDwtIGRhdGVuMSAlPiUgbXV0YXRlKGJ1bmRlc2xhbmQgPSBzdHJfZXh0cmFjdChSZWdpb25hbHNjaGx1ZXNzZWwsICJeLnsyfSIpKQpkYXRlbjEgPC0gbGVmdF9qb2luKGRhdGVuMSwgYnVuZGVzbGFuZF9uYW1lLCBieSA9ICJidW5kZXNsYW5kIikKIyBTY2h1bGRlbiB6dW1lcmdlbgpkYXRlbjIgPC0gbGVmdF9qb2luKGRhdGVuMSwgc2NodWxkZW5fa29tYmksIGJ5ID0gIlJlZ2lvbmFsc2NobHVlc3NlbCIpCiMgQklQIHp1bWVyZ2VuCmRhdGVuMyA8LSBsZWZ0X2pvaW4oZGF0ZW4yLCBiaXBfa29tYmksIGJ5ID0gIlJlZ2lvbmFsc2NobHVlc3NlbCIpCiMgWmFobCBkZXIgRXJ3ZXJic3TDpHRpZ2VuIHp1bWVyZ2VuCmdlc2FtdGRhdGVuIDwtIGxlZnRfam9pbihkYXRlbjMsIGVyd2VyYl9rb21iaSwgYnkgPSAiUmVnaW9uYWxzY2hsdWVzc2VsIikKCnNhdmVSRFMoZ2VzYW10ZGF0ZW4sICIuL2RhdGEvZ2VzYW10ZGF0ZW4ucmRzIikKc2F2ZVJEUyhzY2h1bGRlbl9iZXJlaW5pZ3QsICIuL2RhdGEvc2NodWxkZW5fYmVyZWluaWd0LnJkcyIpCnNhdmVSRFMoYmlwX3plaXRyZWloZSwgIi4vZGF0YS9iaXBfemVpdHJlaWhlLnJkcyIpCnNhdmVSRFMoYnVuZGVzbGFuZCwgIi4vZGF0YS9idW5kZXNsYW5kLnJkcyIpCnNhdmVSRFMoZ2VtZWluZGVuLCAiLi9kYXRhL2dlbWVpbmRlbi5yZHMiKQpzYXZlUkRTKGxhbmRrcmVpc2UsICIuL2RhdGEvbGFuZGtyZWlzZS5yZHMiKQpgYGAKCiMgw5xidW5nc2F1ZmdhYmVuCgpMYWRlbiBTaWUgc2ljaCBkYXMgZHVyY2hzY2huaXR0bGljaGUgW0FyYmVpdG5laG1lcmVudGdlbHQgcHJvIEFyYmVpdG5laG1lciB1bmQgTGFuZGtyZWlzXShodHRwczovL3d3dy5zdGF0aXN0aWtwb3J0YWwuZGUvZGUvdmVyb2VmZmVudGxpY2h1bmdlbi9hcmJlaXRuZWhtZXJlbnRnZWx0KSBhdWYgZGVyIFNlaXRlIGRlciBTdGF0aXN0aXNjaGVuIMOEbXRlciBkZXMgQnVuZGVzIHVuZCBkZXIgTMOkbmRlciBoZXJ1bnRlciB1bmQgbGVzZW4gU2llIGRpZXNlbiBpbiBSIGVpbi4KCjEuICBGaW5kZW4gU2llIGluIGRlbSBoZXJ1bnRlcmdlbGFkZW5lbiBEYXRlbnNhdHogaGVyYXVzLCB3YXMgZGVyIFVudGVyc2NoaWVkIHp3aXNjaGVuICpBcmJlaXRuZWhtZXJlbnRnZWx0KiB1bmQgKkJydXR0b2zDtmhuZS0gdW5kIEdlaMOkbHRlciogaXN0LgoKMi4gIExlc2VuIFNpZSBkaWUgZsO8ciBTaWUgcmVsZXZhbnRlIFRhYmVsbGUgKkJydXR0b2zDtmhuZS0gdW5kIEdlaMOkbHRlciogaW4gUiBlaW4uCgozLiAgQmVyZWluaWdlbiBTaWUgZGllIFRhYmVsbGUsIGQuaC4KICAgIGRlciBEYXRlbnNhdHogc29sbHRlIGRhbmFjaCBgdGlkeWAgc2Vpbi4KCjQuICBCZXJlY2huZW4gU2llIGRpZSBCcnV0dG9sw7ZobmUgcHJvIEJ1bmRlc2xhbmQgbWl0IGRlbiBCcnV0dG9sw7ZobmVuIGRlciBlaW56ZWxuZW4gTGFuZGtyZWlzZSBhbHMgS29uc2lzdGVuemNoZWNrLgoKNS4gIFZlcmdsZWljaGVuIFNpZSBpaHJlbiBEYXRlbnNhdHogbWl0IGRlbSBhdWYgR2l0aHViIGJlcmVpdGdlc3RlbGx0ZW4gRGF0ZW5zYXR6ICgiZWlua29tbWVuLnJkcyIpLgogICAgU3RpbW1lbiBkaWVzZSDDvGJlcmVpbj8KCjYuICBWZXJiaW5kZW4gU2llIGRpZSBJbmZvcm1hdGlvbmVuIHp1IGRlbiBkdXJjaHNjaG5pdHRsaWNoZW4gRWlua29tbWVuIG1pdCBkZW0gKmdlc2FtdGRhdGVuc2F0eiogYXVzIGRlbSB2b3JoZXJpZ2VuIEFic2Nobml0dC4K