Daten
wahlergebnisse.sachsen-anhalt.de
Landtags-Wahlkreise (LTWK) mit Wahlbezirken (WBZ) zur Stimmenabgabe der Wahlberechtigten ohne Briefwahl
berechtigt
— Wahlberechtigte im Wahlbezirk
anteil
— Anteil der Stimmen einer Partei im Wahlbezirk (berechnet)
beteiligt
— Wahlbeteiligung im Wahlbezirk (%)
gross_stadt
— Großstadt (Wahlbezirke in Halle oder Magdeburg)
ltwk_nr
— Landtags-Wahlkreis-Nummer (aufsteigend von Norden nach Süden)
raw_ltw <- readxl::read_excel("source__daten-wahl/LT2021_WBZ_tier2.xlsx", na = c("", "-"))
ltw <-
raw_ltw %>%
filter(
wbz_art != "B", # remove mail in ballot ("Briefwahl")
! is.na(ags), berechtigt < 2500
) %>%
mutate(gross_stadt = if_else(str_detect(ltwk, "Halle|Magdeburg"), "ja", "nein"),)
partei_lt <- c("CDU", "AfD", "DIE LINKE", "SPD", "FDP", "GRÜNE")
n_ltwk <- unique(ltw$ltwk_nr) %>% length()
n_wbz <- unique(paste(ltw$ltwk_nr, ltw$wbz_nr)) %>% length()
Anzahl der
- Landtags-Wahlkreise (LTWK) — 41
- Wahlbezirke (WBZ) — 1367
Verteilung
- Anzahl der Wahlberechtigten in Wahlbezirken (WBZ)
- Anzahl der Wahlbezirke (WBZ) in Landtags-Wahlkreisen (LTWK)
ltw_pa1 <-
ltw %>%
select(ags, wbz_nr, gross_stadt, abgegeben, CDU:WiR2020) %>%
pivot_longer(CDU:WiR2020, names_to = "partei", values_to = "stimmen") %>%
mutate(stimmen = if_else(is.na(stimmen), 0, stimmen),
anteil = round(100 * stimmen / abgegeben, 1))
ltw_pa2 <-
ltw_pa1 %>%
mutate(partei = if_else(partei %in% partei_lt, partei, "andere")) %>%
group_by(ags, wbz_nr, gross_stadt, partei) %>%
summarise(anteil = sum(anteil)) %>%
left_join(ltw %>% select(ltwk_nr:gueltig)) %>%
group_by(partei) %>%
mutate(
ltwk_nr = as.integer(ltwk_nr),
anteil_rang = percent_rank(anteil) %>% round(3)
) %>%
arrange(ltwk_nr, gemeinde, wbz)
ltw_pa3 <-
ltw_pa2 %>%
filter(partei != "andere") %>%
mutate(partei = parse_factor(partei, partei_lt))
pl1 <-
ltw %>% count(ltwk, gross_stadt, name = "wahlbezirke") %>%
ggplot(aes(x = wahlbezirke, fill = gross_stadt)) +
geom_density(alpha = 0.6) +
scale_fill_discrete(guide = FALSE) +
ylab("dichte") +
theme(axis.text.y = element_blank())
pl2 <-
ggplot(ltw, aes(x = berechtigt, fill = gross_stadt)) +
geom_density(alpha = 0.6) +
scale_fill_discrete(guide = FALSE) +
ylab("dichte") +
theme(axis.text.y = element_blank())
pl3 <-
ggplot(ltw_pa3, aes(x = partei, y = anteil, colour = gross_stadt)) +
geom_jitter(alpha = 0.2) +
theme(axis.title.x = element_blank())
pl3 / (pl1 + pl2)

Karten
karte_wbz <- read_rds("source__daten-geo/st-wahlbezirke.rds")
karte_land <- read_rds("source__daten-geo/st-land-ne.rds")
karte_stadt <- read_rds("source__daten-geo/st-staedte-wikidata.rds")
karte_strasse_ab <- read_rds("source__daten-geo/st-strassen-ab-osm.rds")
karte_strasse_bu <- read_rds("source__daten-geo/st-strassen-bu-osm.rds")
ltw_pa3_min_max <-
ltw_pa3 %>%
group_by(partei) %>%
summarise(min = min(anteil, na.rm = TRUE) %>% round(),
max = max(anteil, na.rm = TRUE) %>% round()) %>%
mutate(partei_info = glue::glue("{partei} {min}-{max}%"))
pl <-
karte_wbz %>%
right_join(ltw_pa3) %>%
arrange(anteil_rang) %>%
ggplot() +
# geom_sf(data = karte_land, fill = NA ) +
geom_sf(data = karte_strasse_ab, colour = "grey85", size = 0.9) +
geom_sf(data = karte_strasse_bu, colour = "grey80") +
geom_sf(aes(colour = anteil_rang), size = 0.6, alpha = 0.6) +
viridis::scale_colour_viridis(option = "E", direction = -1) +
geom_sf(data = karte_stadt, aes(size = einwohner), colour = "deeppink3", shape = "+", alpha = 0.6) +
scale_size_continuous(range = c(2, 6)) +
facet_wrap(vars(partei)) +
labs(caption = str_replace(paste(ltw_pa3_min_max$partei_info, collapse = ", "), "SPD", "\nSPD")) +
theme_void()
print(pl)
ggsave("z-wahl-st-karte.png", pl)
ggsave("z-wahl-st-karte.pdf", pl, width = 297, height = 210, units = "mm")

Modelle
Parteien (Interaktion)
Modell mit allen Stimmen-Anteilen der Parteien in Wahlbezirken und der Modellierung von Partei-Effekten mit Interaktionen.
# + interact all predictors with "party" (all effects vary by "party")
# + clustered standard errors by electoral district
# mo1 <- lm(anteil ~ berechtigt*partei + gross_stadt*partei + beteiligung*partei + ltwk*partei, data = ltw_pa3)
mo1 <- lm_robust(anteil ~ berechtigt*partei + gross_stadt*partei + beteiligung*partei,
clusters = ltwk, data = ltw_pa3)
# summary(mo1)
# tidy(mo1) %>% DT::datatable() # too many coefficients
party_color <- c("#1F78B4", "#A6CEE3", "#FB9A99", "#E31A1C", "#FDBF6F", "#33A02C")
plot_effects <- function(terms, show_legend = TRUE) {
ggpredict(mo1, terms = terms) %>%
plot(colors = party_color, show.legend = show_legend,
show.title = FALSE, show.y.title = FALSE, limit.range = TRUE)
}
# plot_effects(terms = c("berechtigt", "partei", "gross_stadt"), show_legend = FALSE)
pl1 <- plot_effects(terms = c("berechtigt", "partei"), show_legend = FALSE)
pl2 <- plot_effects(terms = c("beteiligung", "partei"))
pl3 <-
ggpredict(mo1, terms = c("partei", "gross_stadt")) %>%
plot(show.title = FALSE, colors = c("#0571B0", "#CA0020"), show.y.title = FALSE)
(pl1 | pl2 ) / pl3 + plot_layout(heights = c(2, 1))

Partei · AfD
Mehr-Ebenen-Modell für Stimmen-Anteil der AfD in den Wahlbezirken.
Nutzung von Mehr-Ebenen-Modellen für unterschiedliche Effekte in Landtags-Wahlkreisen mit Zentrierung einiger Variablen (_mittel
— “centering within clusters”).
karte_wbz_xy <- read_csv("source__daten-geo/wahlbezirke.csv") %>% select(wbz, latitude, longitude)
# CWC --centering within clusters
ltw_pa3_mlm <-
ltw_pa3 %>%
left_join(karte_wbz_xy) %>%
group_by(ltwk_nr, partei) %>%
mutate(
berechtigt_mittel = berechtigt - mean(berechtigt, na.rm = TRUE),
beteiligung_mittel = beteiligung - mean(beteiligung, na.rm = TRUE),
breitengrad_mittel = latitude - mean(latitude, na.rm = TRUE),
laengengrad_mittel = longitude - mean(longitude, na.rm = TRUE)
)
lmer_formula <-
as.formula(
# "anteil ~ berechtigt_mittel + beteiligung_mittel + gross_stadt + ltwk_nr + (1 | ltwk)"
"anteil ~ berechtigt_mittel*gross_stadt + beteiligung_mittel*gross_stadt + gross_stadt + breitengrad_mittel + laengengrad_mittel + (1 | ltwk)"
)
partei_auswahl <- "AfD"
ltw_partei <- ltw_pa3_mlm %>% filter(partei == partei_auswahl)
mo2 <- lmer(lmer_formula, data = ltw_partei)
# summary(mo2)
# ## random slope only model not different from random coefficient model ("+ (berechtigt_mittel | ltwk)")
# performance::performance_lrt(mo2a, mo2b)
tidy(mo2) %>%
filter(effect == "fixed") %>%
select(-effect, -group) %>%
mutate_if(is.numeric, round, 3)
plot_effects <- function(term) {
ggemmeans(mo2, terms = c(term, "gross_stadt")) %>%
plot(add.data = TRUE, show.title = FALSE, show.legend = FALSE, show.y.title = FALSE)
}
pl1 <- plot_effects("berechtigt_mittel")
pl2 <- plot_effects("beteiligung_mittel")
# pl3 <- plot_effects("breitengrad_mittel")
# pl4 <- plot_effects("laengengrad_mittel")
pl1 + pl2 # + pl3 + pl4

# predict(mo2, ltw_partei[str_detect(ltw_partei$wbz, "Jerichow, OT Kade"), ]) %>% round(1)
Parteien (einzeln)
Je ein Mehr-Ebenen-Modell zur Bestimmung des Stimmen-Anteils einer Partei in den Wahlbezirken.
ltw_lm <-
ltw_pa3_mlm %>%
group_by(partei) %>%
nest() %>%
mutate(
model = map(data, function(df) lmer(lmer_formula, data = df)),
model_tidy = map(model, tidy),
model_pred1 = map(model, ~ ggemmeans(.x, terms = c("berechtigt_mittel", "gross_stadt"))),
model_pred2 = map(model, ~ ggemmeans(.x, terms = c("beteiligung_mittel", "gross_stadt"))),
model_pred3 = map(model, ~ ggemmeans(.x, terms = c("breitengrad_mittel"))),
model_pred4 = map(model, ~ ggemmeans(.x, terms = c("laengengrad_mittel")))
)
ltw_lm %>%
unnest(model_tidy) %>%
filter(effect == "fixed") %>%
select(-data, -effect, -group, -starts_with("model")) %>%
mutate_if(is.numeric, round, 3) %>%
DT::datatable()
ltw_lm %>%
unnest(model_pred1) %>%
ggplot(aes(x = x, y = predicted)) +
geom_point(aes(x = berechtigt_mittel, y = anteil, colour = gross_stadt), data = ltw_pa3_mlm, alpha = 0.02) +
geom_ribbon(aes(ymin = conf.low, ymax = conf.high, fill = group), alpha = 0.6) +
geom_line(aes(group = group), colour = "gray40") +
xlab("berechtigt_mittel") + ylab("anteil") +
xlim(-1600, 1600) +
guides(colour = FALSE, fill = FALSE) +
facet_wrap(vars(partei))

ltw_lm %>%
unnest(model_pred2) %>%
select(-data, -model, -model_tidy) %>%
ggplot(aes(x = x, y = predicted)) +
geom_point(aes(x = beteiligung_mittel, y = anteil, colour = gross_stadt), data = ltw_pa3_mlm, alpha = 0.02) +
geom_ribbon(aes(ymin = conf.low, ymax = conf.high, fill = group), alpha = 0.6) +
geom_line(aes(group = group), colour = "gray40") +
xlab("beteiligung_mittel") + ylab("anteil") +
xlim(-25, 25) +
guides(colour = FALSE, fill = FALSE) +
facet_wrap(vars(partei))

Geographische Lage
pl1 <-
ltw_lm %>%
unnest(model_pred3) %>%
ggplot(aes(x = x, y = predicted)) +
geom_ribbon(aes(ymin = conf.low, ymax = conf.high), fill = "slategray1") +
geom_line() +
xlab("breitengrad_mittel") + ylab("anteil") +
xlim(-0.22, 0.22) +
facet_wrap(vars(partei))
pl2 <-
ltw_lm %>%
unnest(model_pred4) %>%
ggplot(aes(x = x, y = predicted)) +
geom_ribbon(aes(ymin = conf.low, ymax = conf.high), fill = "slategray1") +
geom_line() +
xlab("laengengrad_mittel") + ylab("anteil") +
facet_wrap(vars(partei))
pl1 / pl2

Beteiligung
Mehr-Ebenen-Modell zur Bestimmung der Wahlbeteiligung in den Wahlbezirken
mo3 <- lmer(beteiligung ~ berechtigt_mittel * gross_stadt + (1 | ltwk), data = ltw_partei)
# summary(mo3)
tidy(mo3) %>%
filter(effect == "fixed") %>%
select(-effect, -group) %>%
mutate_if(is.numeric, round, 3)
ggemmeans(mo3, terms = c("berechtigt_mittel", "gross_stadt")) %>%
plot(add.data = TRUE, show.title = FALSE)

Daten
Ergebnisse Parteien
ltw_pa2 %>%
left_join(ltw_pa1) %>%
arrange(ltwk_nr, wbz, desc(anteil)) %>%
select(ltwk, wbz, berechtigt, beteiligung, partei, stimmen, anteil, anteil_rang) %>%
DT::datatable()
Wahlkreise und -bezirke
ltw %>%
group_by(ltwk_nr, ltwk) %>%
select(berechtigt) %>%
skimr::skim() %>%
select(-skim_type, -skim_variable, -n_missing, -complete_rate) %>%
mutate(across(c(numeric.mean, numeric.sd), ~ round(.x, 1))) %>%
rename_with(~ str_replace(.x, fixed("numeric."), "")) %>%
DT::datatable()
karte_wbz %>%
left_join(ltw %>% select(wbz, berechtigt)) %>%
# filter(str_detect(gemeinde, "^Halle")) %>%
ggplot() +
# geom_sf() +
geom_sf(data = karte_strasse_ab, colour = "grey70", size = 1.1) +
geom_sf(data = karte_strasse_bu, colour = "grey60") +
geom_point(
aes(size = berechtigt, geometry = geometry),
colour = "blue", alpha = 0.15, stat = "sf_coordinates"
) +
theme_void()
LS0tCnRpdGxlOiAiTGFuZHRhZ3N3YWhsIFNhY2hzZW4tQW5oYWx0IDIwMjEiCmF1dGhvcjogIkhvbGdlciBEb2VyaW5nIC0tLSBkb2VyaW5nQHVuaS1icmVtZW4uZGUiCmRhdGU6ICJgciBmb3JtYXQoU3lzLnRpbWUoKSwgJyVkICVCICVZLCAlSDolTScpYCIKb3V0cHV0OgogIGh0bWxfbm90ZWJvb2s6CiAgICBjb2RlX2ZvbGRpbmc6IGhpZGUKICAgIHRvYzogeWVzCiAgICB0b2NfZmxvYXQ6IHllcwogIGh0bWxfZG9jdW1lbnQ6CiAgICBkZl9wcmludDogcGFnZWQKICAgIGNvZGVfZm9sZGluZzogaGlkZQogICAgdG9jOiB5ZXMKICAgIHRvY19mbG9hdDogeWVzCi0tLQo8c3R5bGUgdHlwZT0idGV4dC9jc3MiPiA8IS0tIC50YWJsZSB7IHdpZHRoOiBhdXRvIH0gLS0tPiA8L3N0eWxlPgoKYGBge3Igb3B0aW9ucywgaW5jbHVkZT1GQUxTRX0Ka25pdHI6Om9wdHNfa25pdCRzZXQoCiAgIyByZXN1bHRzID0gImhpZGUiLAogICMgY29tbWVudCA9IE5BLAogIG1lc3NhZ2UgPSBGQUxTRSwKICB3YXJuaW5nID0gRkFMU0UsCiAgcGFja2FnZS5zdGFydHVwLm1lc3NhZ2UgPSBGQUxTRQogICkKb3B0aW9ucygKICB0aWR5dmVyc2UucXVpZXQgPSBUUlVFLAogIGRwbHlyLnN1bW1hcmlzZS5pbmZvcm0gPSBGQUxTRSwKICByZWFkci5udW1fY29sdW1ucyA9IDAsCiAga25pdHIua2FibGUuTkEgPSAiIiwKICB3aWR0aCA9IDEwMAopCmBgYAoKYGBge3IgY29yZXBhY2tzfQpsaWJyYXJ5KGxtZTQpICAgICAgICMgbW9kZWxzIC8vIG11bHRpLWxldmVsIApsaWJyYXJ5KGVzdGltYXRyKSAgICMgbW9kZWxzIC8vIHJvYnVzdCBzdGFuZGFyZCBlcnJvcnMKbGlicmFyeShicm9vbSkgICAgICAjIG1vZGVscyAvLyB0aWR5IHJlc3VsdHMKbGlicmFyeShicm9vbS5taXhlZCkKbGlicmFyeShnZ2VmZmVjdHMpICAjIG1vZGVscyAvLyB2aXN1YWxpemUgbW9kZWwgZWZmZWN0cwpsaWJyYXJ5KHBhdGNod29yaykgICMgcGxvdHMgLy8gYXJyYW5nZQpsaWJyYXJ5KHNmKSAgICAgICAgICMgbWFwcwpsaWJyYXJ5KHRpZHl2ZXJzZSkgICMgbG9hZCBsYXN0IHRvIGF2b2lkIG1hc2tpbmcKIyBEVDo6IHNraW1yOjogdmlyaWRpczo6CgpnZ3Bsb3QyOjp0aGVtZV9zZXQodGhlbWVfbWluaW1hbCgpKQpgYGAKCjxwIHN0eWxlPSJwYWdlLWJyZWFrLWJlZm9yZTogYWx3YXlzIj4KCiMjIERhdGVuCgpbd2FobGVyZ2Vibmlzc2Uuc2FjaHNlbi1hbmhhbHQuZGVdKGh0dHBzOi8vd2FobGVyZ2Vibmlzc2Uuc2FjaHNlbi1hbmhhbHQuZGUvd2FobGVuL2x0MjEvYW5kL2x0LmRvd25sb2FkLnBocCkKCkxhbmR0YWdzLVdhaGxrcmVpc2UgKExUV0spIG1pdCBXYWhsYmV6aXJrZW4gKFdCWikgenVyIFN0aW1tZW5hYmdhYmUgZGVyIFdhaGxiZXJlY2h0aWd0ZW4gb2huZSBCcmllZndhaGwKCisgYGJlcmVjaHRpZ3RgIOKAlCBXYWhsYmVyZWNodGlndGUgaW0gV2FobGJlemlyaworIGBhbnRlaWxgIOKAlCBBbnRlaWwgZGVyIFN0aW1tZW4gZWluZXIgUGFydGVpIGltIFdhaGxiZXppcmsgKGJlcmVjaG5ldCkKKyBgYmV0ZWlsaWd0YCDigJQgV2FobGJldGVpbGlndW5nIGltIFdhaGxiZXppcmsgKCUpCisgYGdyb3NzX3N0YWR0YCDigJQgR3Jvw59zdGFkdCAoV2FobGJlemlya2UgaW4gSGFsbGUgb2RlciBNYWdkZWJ1cmcpCisgYGx0d2tfbnJgIOKAlCBMYW5kdGFncy1XYWhsa3JlaXMtTnVtbWVyIChhdWZzdGVpZ2VuZCB2b24gTm9yZGVuIG5hY2ggU8O8ZGVuKQoKLS0tCgpgYGB7cn0KcmF3X2x0dyA8LSByZWFkeGw6OnJlYWRfZXhjZWwoInNvdXJjZV9fZGF0ZW4td2FobC9MVDIwMjFfV0JaX3RpZXIyLnhsc3giLCBuYSA9IGMoIiIsICItIikpCgpsdHcgPC0gCiAgcmF3X2x0dyAlPiUgCiAgZmlsdGVyKAogICAgd2J6X2FydCAhPSAiQiIsICAgICAgICAgICMgcmVtb3ZlIG1haWwgaW4gYmFsbG90ICgiQnJpZWZ3YWhsIikKICAgICEgaXMubmEoYWdzKSwgYmVyZWNodGlndCA8IDI1MDAKICAgICkgJT4lIAogIG11dGF0ZShncm9zc19zdGFkdCA9IGlmX2Vsc2Uoc3RyX2RldGVjdChsdHdrLCAiSGFsbGV8TWFnZGVidXJnIiksICJqYSIsICJuZWluIiksKQoKcGFydGVpX2x0IDwtIGMoIkNEVSIsICJBZkQiLCAiRElFIExJTktFIiwgIlNQRCIsICJGRFAiLCAiR1LDnE5FIikKCm5fbHR3ayA8LSB1bmlxdWUobHR3JGx0d2tfbnIpICU+JSBsZW5ndGgoKQpuX3dieiA8LSB1bmlxdWUocGFzdGUobHR3JGx0d2tfbnIsIGx0dyR3YnpfbnIpKSAlPiUgbGVuZ3RoKCkKYGBgCgpBbnphaGwgZGVyCgorIExhbmR0YWdzLVdhaGxrcmVpc2UgKExUV0spIOKAlCBfX2ByIG5fbHR3a2BfXworIFdhaGxiZXppcmtlIChXQlopIOKAlCBfX2ByIG5fd2J6YF9fCgpWZXJ0ZWlsdW5nCgorIEFuemFobCBkZXIgX1dhaGxiZXJlY2h0aWd0ZW5fIGluIFdhaGxiZXppcmtlbiAoV0JaKQorIEFuemFobCBkZXIgX1dhaGxiZXppcmtlXyAoV0JaKSBpbiBMYW5kdGFncy1XYWhsa3JlaXNlbiAoTFRXSykKCmBgYHtyLCBtZXNzYWdlPUZBTFNFfQpsdHdfcGExIDwtIAogIGx0dyAlPiUKICBzZWxlY3QoYWdzLCB3YnpfbnIsIGdyb3NzX3N0YWR0LCBhYmdlZ2ViZW4sIENEVTpXaVIyMDIwKSAlPiUgCiAgcGl2b3RfbG9uZ2VyKENEVTpXaVIyMDIwLCBuYW1lc190byA9ICJwYXJ0ZWkiLCB2YWx1ZXNfdG8gPSAic3RpbW1lbiIpICU+JSAKICBtdXRhdGUoc3RpbW1lbiA9IGlmX2Vsc2UoaXMubmEoc3RpbW1lbiksIDAsIHN0aW1tZW4pLAogICAgICAgICBhbnRlaWwgPSByb3VuZCgxMDAgKiBzdGltbWVuIC8gYWJnZWdlYmVuLCAxKSkKCmx0d19wYTIgPC0gCiAgbHR3X3BhMSAlPiUgCiAgbXV0YXRlKHBhcnRlaSA9IGlmX2Vsc2UocGFydGVpICVpbiUgcGFydGVpX2x0LCBwYXJ0ZWksICJhbmRlcmUiKSkgJT4lIAogIGdyb3VwX2J5KGFncywgd2J6X25yLCBncm9zc19zdGFkdCwgcGFydGVpKSAlPiUgCiAgc3VtbWFyaXNlKGFudGVpbCA9IHN1bShhbnRlaWwpKSAlPiUgCiAgbGVmdF9qb2luKGx0dyAlPiUgc2VsZWN0KGx0d2tfbnI6Z3VlbHRpZykpICU+JSAKICBncm91cF9ieShwYXJ0ZWkpICU+JSAKICBtdXRhdGUoCiAgICBsdHdrX25yID0gYXMuaW50ZWdlcihsdHdrX25yKSwKICAgIGFudGVpbF9yYW5nID0gcGVyY2VudF9yYW5rKGFudGVpbCkgJT4lIHJvdW5kKDMpCiAgICApICU+JSAKICBhcnJhbmdlKGx0d2tfbnIsIGdlbWVpbmRlLCB3YnopCgpsdHdfcGEzIDwtIAogIGx0d19wYTIgJT4lIAogIGZpbHRlcihwYXJ0ZWkgIT0gImFuZGVyZSIpICU+JSAKICBtdXRhdGUocGFydGVpID0gcGFyc2VfZmFjdG9yKHBhcnRlaSwgcGFydGVpX2x0KSkKYGBgCgoKYGBge3IgcGwtZGVzY3JpcHRpdmUsIG1lc3NhZ2U9RkFMU0V9CnBsMSA8LSAKICBsdHcgJT4lIGNvdW50KGx0d2ssIGdyb3NzX3N0YWR0LCBuYW1lID0gIndhaGxiZXppcmtlIikgJT4lIAogIGdncGxvdChhZXMoeCA9IHdhaGxiZXppcmtlLCBmaWxsID0gZ3Jvc3Nfc3RhZHQpKSArIAogIGdlb21fZGVuc2l0eShhbHBoYSA9IDAuNikgKwogIHNjYWxlX2ZpbGxfZGlzY3JldGUoZ3VpZGUgPSBGQUxTRSkgKwogIHlsYWIoImRpY2h0ZSIpICsKICB0aGVtZShheGlzLnRleHQueSA9IGVsZW1lbnRfYmxhbmsoKSkKCnBsMiA8LSAKICBnZ3Bsb3QobHR3LCBhZXMoeCA9IGJlcmVjaHRpZ3QsIGZpbGwgPSBncm9zc19zdGFkdCkpICsgCiAgZ2VvbV9kZW5zaXR5KGFscGhhID0gMC42KSArCiAgc2NhbGVfZmlsbF9kaXNjcmV0ZShndWlkZSA9IEZBTFNFKSArCiAgeWxhYigiZGljaHRlIikgKwogIHRoZW1lKGF4aXMudGV4dC55ID0gZWxlbWVudF9ibGFuaygpKQoKcGwzIDwtIAogIGdncGxvdChsdHdfcGEzLCBhZXMoeCA9IHBhcnRlaSwgeSA9IGFudGVpbCwgY29sb3VyID0gZ3Jvc3Nfc3RhZHQpKSArCiAgZ2VvbV9qaXR0ZXIoYWxwaGEgPSAwLjIpICsKICB0aGVtZShheGlzLnRpdGxlLnggPSBlbGVtZW50X2JsYW5rKCkpCgpwbDMgLyAocGwxICsgcGwyKQpgYGAKCiMjIEthcnRlbgoKYGBge3IsIG1lc3NhZ2U9RkFMU0UsIGNhY2hlPVRSVUV9CmthcnRlX3dieiA8LSByZWFkX3Jkcygic291cmNlX19kYXRlbi1nZW8vc3Qtd2FobGJlemlya2UucmRzIikKa2FydGVfbGFuZCA8LSByZWFkX3Jkcygic291cmNlX19kYXRlbi1nZW8vc3QtbGFuZC1uZS5yZHMiKQprYXJ0ZV9zdGFkdCA8LSByZWFkX3Jkcygic291cmNlX19kYXRlbi1nZW8vc3Qtc3RhZWR0ZS13aWtpZGF0YS5yZHMiKQprYXJ0ZV9zdHJhc3NlX2FiIDwtIHJlYWRfcmRzKCJzb3VyY2VfX2RhdGVuLWdlby9zdC1zdHJhc3Nlbi1hYi1vc20ucmRzIikKa2FydGVfc3RyYXNzZV9idSA8LSByZWFkX3Jkcygic291cmNlX19kYXRlbi1nZW8vc3Qtc3RyYXNzZW4tYnUtb3NtLnJkcyIpCgpsdHdfcGEzX21pbl9tYXggPC0gCiAgbHR3X3BhMyAlPiUgCiAgZ3JvdXBfYnkocGFydGVpKSAlPiUgCiAgc3VtbWFyaXNlKG1pbiA9IG1pbihhbnRlaWwsIG5hLnJtID0gVFJVRSkgJT4lIHJvdW5kKCksCiAgICAgICAgICAgIG1heCA9IG1heChhbnRlaWwsIG5hLnJtID0gVFJVRSkgJT4lIHJvdW5kKCkpICU+JSAKICBtdXRhdGUocGFydGVpX2luZm8gPSBnbHVlOjpnbHVlKCJ7cGFydGVpfSB7bWlufS17bWF4fSUiKSkgCgpwbCA8LSAKICBrYXJ0ZV93YnogJT4lIAogIHJpZ2h0X2pvaW4obHR3X3BhMykgJT4lIAogIGFycmFuZ2UoYW50ZWlsX3JhbmcpICU+JSAKICBnZ3Bsb3QoKSArIAogICMgZ2VvbV9zZihkYXRhID0ga2FydGVfbGFuZCwgZmlsbCA9IE5BICkgKwogIGdlb21fc2YoZGF0YSA9IGthcnRlX3N0cmFzc2VfYWIsICBjb2xvdXIgPSAiZ3JleTg1Iiwgc2l6ZSA9IDAuOSkgKwogIGdlb21fc2YoZGF0YSA9IGthcnRlX3N0cmFzc2VfYnUsICBjb2xvdXIgPSAiZ3JleTgwIikgKwogIGdlb21fc2YoYWVzKGNvbG91ciA9IGFudGVpbF9yYW5nKSwgc2l6ZSA9IDAuNiwgYWxwaGEgPSAwLjYpICsgCiAgdmlyaWRpczo6c2NhbGVfY29sb3VyX3ZpcmlkaXMob3B0aW9uID0gIkUiLCBkaXJlY3Rpb24gPSAtMSkgKwogIGdlb21fc2YoZGF0YSA9IGthcnRlX3N0YWR0LCBhZXMoc2l6ZSA9IGVpbndvaG5lciksIGNvbG91ciA9ICJkZWVwcGluazMiLCBzaGFwZSA9ICIrIiwgYWxwaGEgPSAwLjYpICsKICBzY2FsZV9zaXplX2NvbnRpbnVvdXMocmFuZ2UgPSBjKDIsIDYpKSArCiAgZmFjZXRfd3JhcCh2YXJzKHBhcnRlaSkpICsKICBsYWJzKGNhcHRpb24gPSBzdHJfcmVwbGFjZShwYXN0ZShsdHdfcGEzX21pbl9tYXgkcGFydGVpX2luZm8sIGNvbGxhcHNlID0gIiwgIiksICJTUEQiLCAiXG5TUEQiKSkgKwogIHRoZW1lX3ZvaWQoKQoKcHJpbnQocGwpCmdnc2F2ZSgiei13YWhsLXN0LWthcnRlLnBuZyIsIHBsKQpnZ3NhdmUoInotd2FobC1zdC1rYXJ0ZS5wZGYiLCBwbCwgd2lkdGggPSAyOTcsIGhlaWdodCA9IDIxMCwgdW5pdHMgPSAibW0iKQpgYGAKCmBgYHtyLCBtZXNzYWdlPUZBTFNFLCBpbmNsdWRlPUZBTFNFLCBldmFsPUZBTFNFfQojIG1hcCB3aXRoIGNvbWJpbmVkIHZvdGUgc2hhcmUgQWZEICsgTElOS0UgCgpwbF9kdCA8LSAKICBrYXJ0ZV93YnogJT4lIAogIHJpZ2h0X2pvaW4obHR3X3BhMykgJT4lIAogIGZpbHRlcihwYXJ0ZWkgJWluJSBjKCJBZkQiLCAiRElFIExJTktFIikpICU+JSAKICBncm91cF9ieShhZ3MsIHdiel9ucikgJT4lIAogIHN1bW1hcmlzZShhZmRfbGlua2UgPSBzdW0oYW50ZWlsLCBuYS5ybSA9IFRSVUUpKQoKZ2dwbG90KHBsX2R0KSArIAogIGdlb21fc2YoYWVzKGNvbG91ciA9IGFmZF9saW5rZSksIHNpemUgPSAxLjAsIGFscGhhID0gMC42KSArIAogIGdlb21fc2YoZGF0YSA9IGthcnRlX2xhbmQsIGZpbGwgPSBOQSApICsKICB2aXJpZGlzOjpzY2FsZV9jb2xvdXJfdmlyaWRpcyhvcHRpb24gPSAiRCIsIGRpcmVjdGlvbiA9IC0xKSArCiAgZ2VvbV9zZihkYXRhID0ga2FydGVfc3RhZHQsIGFlcyhzaXplID0gZWlud29obmVyKSwgY29sb3VyID0gImRlZXBwaW5rMyIsIHNoYXBlID0gIisiLCBhbHBoYSA9IDAuNikgKwogIHNjYWxlX3NpemVfY29udGludW91cyhyYW5nZSA9IGMoMiwgNikpICsKICB0aGVtZV92b2lkKCkKYGBgCgoKIyMgTW9kZWxsZQoKIyMjIFBhcnRlaWVuIChJbnRlcmFrdGlvbikKCk1vZGVsbCBtaXQgYWxsZW4gU3RpbW1lbi1BbnRlaWxlbiBkZXIgUGFydGVpZW4gaW4gV2FobGJlemlya2VuIHVuZCBkZXIgTW9kZWxsaWVydW5nIHZvbiBQYXJ0ZWktRWZmZWt0ZW4gbWl0IEludGVyYWt0aW9uZW4uCgpgYGB7ciwgd2FybmluZz1GQUxTRX0KIyArIGludGVyYWN0IGFsbCBwcmVkaWN0b3JzIHdpdGggInBhcnR5IiAoYWxsIGVmZmVjdHMgdmFyeSBieSAicGFydHkiKQojICsgY2x1c3RlcmVkIHN0YW5kYXJkIGVycm9ycyBieSBlbGVjdG9yYWwgZGlzdHJpY3QKIyBtbzEgPC0gbG0oYW50ZWlsIH4gYmVyZWNodGlndCpwYXJ0ZWkgKyBncm9zc19zdGFkdCpwYXJ0ZWkgKyBiZXRlaWxpZ3VuZypwYXJ0ZWkgKyBsdHdrKnBhcnRlaSwgZGF0YSA9IGx0d19wYTMpCm1vMSA8LSBsbV9yb2J1c3QoYW50ZWlsIH4gYmVyZWNodGlndCpwYXJ0ZWkgKyBncm9zc19zdGFkdCpwYXJ0ZWkgKyBiZXRlaWxpZ3VuZypwYXJ0ZWksCiAgICAgICAgICAgICAgICAgY2x1c3RlcnMgPSBsdHdrLCBkYXRhID0gbHR3X3BhMykKCiMgc3VtbWFyeShtbzEpCiMgdGlkeShtbzEpICU+JSBEVDo6ZGF0YXRhYmxlKCkgICMgdG9vIG1hbnkgY29lZmZpY2llbnRzCgpwYXJ0eV9jb2xvciA8LSBjKCIjMUY3OEI0IiwgIiNBNkNFRTMiLCAiI0ZCOUE5OSIsICIjRTMxQTFDIiwgIiNGREJGNkYiLCAiIzMzQTAyQyIpCgpwbG90X2VmZmVjdHMgPC0gZnVuY3Rpb24odGVybXMsIHNob3dfbGVnZW5kID0gVFJVRSkgewogIGdncHJlZGljdChtbzEsIHRlcm1zID0gdGVybXMpICU+JSAKICAgIHBsb3QoY29sb3JzID0gcGFydHlfY29sb3IsIHNob3cubGVnZW5kID0gc2hvd19sZWdlbmQsCiAgICAgICAgIHNob3cudGl0bGUgPSBGQUxTRSwgc2hvdy55LnRpdGxlID0gRkFMU0UsIGxpbWl0LnJhbmdlID0gVFJVRSkKfQoKIyBwbG90X2VmZmVjdHModGVybXMgPSBjKCJiZXJlY2h0aWd0IiwgInBhcnRlaSIsICJncm9zc19zdGFkdCIpLCBzaG93X2xlZ2VuZCA9IEZBTFNFKQoKcGwxIDwtIHBsb3RfZWZmZWN0cyh0ZXJtcyA9IGMoImJlcmVjaHRpZ3QiLCAicGFydGVpIiksIHNob3dfbGVnZW5kID0gRkFMU0UpCnBsMiA8LSBwbG90X2VmZmVjdHModGVybXMgPSBjKCJiZXRlaWxpZ3VuZyIsICJwYXJ0ZWkiKSkKCnBsMyA8LSAKICBnZ3ByZWRpY3QobW8xLCB0ZXJtcyA9IGMoInBhcnRlaSIsICJncm9zc19zdGFkdCIpKSAlPiUgCiAgcGxvdChzaG93LnRpdGxlID0gRkFMU0UsIGNvbG9ycyA9IGMoIiMwNTcxQjAiLCAiI0NBMDAyMCIpLCBzaG93LnkudGl0bGUgPSBGQUxTRSkKCihwbDEgfCBwbDIgKSAvIHBsMyArIHBsb3RfbGF5b3V0KGhlaWdodHMgPSBjKDIsIDEpKQpgYGAKCiMjIyBQYXJ0ZWkgwrcgYHIgcGFydGVpX2F1c3dhaGxgCgpNZWhyLUViZW5lbi1Nb2RlbGwgZsO8ciBTdGltbWVuLUFudGVpbCBkZXIgX19gciBwYXJ0ZWlfYXVzd2FobGBfXyBpbiBkZW4gV2FobGJlemlya2VuLgoKTnV0enVuZyB2b24gTWVoci1FYmVuZW4tTW9kZWxsZW4gZsO8ciB1bnRlcnNjaGllZGxpY2hlIEVmZmVrdGUgaW4gTGFuZHRhZ3MtV2FobGtyZWlzZW4gbWl0IFplbnRyaWVydW5nIGVpbmlnZXIgVmFyaWFibGVuIChgX21pdHRlbGAg4oCUICJjZW50ZXJpbmcgd2l0aGluIGNsdXN0ZXJzIikuCgoKYGBge3IsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CmthcnRlX3diel94eSA8LSByZWFkX2Nzdigic291cmNlX19kYXRlbi1nZW8vd2FobGJlemlya2UuY3N2IikgJT4lIHNlbGVjdCh3YnosIGxhdGl0dWRlLCBsb25naXR1ZGUpCgojIENXQyAtLWNlbnRlcmluZyB3aXRoaW4gY2x1c3RlcnMKbHR3X3BhM19tbG0gPC0gCiAgbHR3X3BhMyAlPiUgCiAgbGVmdF9qb2luKGthcnRlX3diel94eSkgJT4lIAogIGdyb3VwX2J5KGx0d2tfbnIsIHBhcnRlaSkgJT4lIAogIG11dGF0ZSgKICAgIGJlcmVjaHRpZ3RfbWl0dGVsID0gYmVyZWNodGlndCAtIG1lYW4oYmVyZWNodGlndCwgbmEucm0gPSBUUlVFKSwKICAgIGJldGVpbGlndW5nX21pdHRlbCA9IGJldGVpbGlndW5nIC0gbWVhbihiZXRlaWxpZ3VuZywgbmEucm0gPSBUUlVFKSwKICAgIGJyZWl0ZW5ncmFkX21pdHRlbCA9IGxhdGl0dWRlIC0gbWVhbihsYXRpdHVkZSwgbmEucm0gPSBUUlVFKSwKICAgIGxhZW5nZW5ncmFkX21pdHRlbCA9IGxvbmdpdHVkZSAtIG1lYW4obG9uZ2l0dWRlLCBuYS5ybSA9IFRSVUUpCiAgICApCgpsbWVyX2Zvcm11bGEgPC0gCiAgYXMuZm9ybXVsYSgKICAjICJhbnRlaWwgfiBiZXJlY2h0aWd0X21pdHRlbCArIGJldGVpbGlndW5nX21pdHRlbCArIGdyb3NzX3N0YWR0ICsgbHR3a19uciArICgxIHwgbHR3aykiCiAgImFudGVpbCB+IGJlcmVjaHRpZ3RfbWl0dGVsKmdyb3NzX3N0YWR0ICsgYmV0ZWlsaWd1bmdfbWl0dGVsKmdyb3NzX3N0YWR0ICsgZ3Jvc3Nfc3RhZHQgKyBicmVpdGVuZ3JhZF9taXR0ZWwgKyBsYWVuZ2VuZ3JhZF9taXR0ZWwgKyAoMSB8IGx0d2spIgogICkKCnBhcnRlaV9hdXN3YWhsIDwtICJBZkQiCmx0d19wYXJ0ZWkgPC0gbHR3X3BhM19tbG0gJT4lIGZpbHRlcihwYXJ0ZWkgPT0gcGFydGVpX2F1c3dhaGwpCgptbzIgPC0gbG1lcihsbWVyX2Zvcm11bGEsIGRhdGEgPSBsdHdfcGFydGVpKQojIHN1bW1hcnkobW8yKQoKIyAjIyByYW5kb20gc2xvcGUgb25seSBtb2RlbCBub3QgZGlmZmVyZW50IGZyb20gcmFuZG9tIGNvZWZmaWNpZW50IG1vZGVsICgiKyAoYmVyZWNodGlndF9taXR0ZWwgfCBsdHdrKSIpCiMgcGVyZm9ybWFuY2U6OnBlcmZvcm1hbmNlX2xydChtbzJhLCBtbzJiKSAKCnRpZHkobW8yKSAlPiUgCiAgZmlsdGVyKGVmZmVjdCA9PSAiZml4ZWQiKSAlPiUgCiAgc2VsZWN0KC1lZmZlY3QsIC1ncm91cCkgJT4lIAogIG11dGF0ZV9pZihpcy5udW1lcmljLCByb3VuZCwgMykKYGBgCgoKYGBge3IsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CnBsb3RfZWZmZWN0cyA8LSBmdW5jdGlvbih0ZXJtKSB7CiAgZ2dlbW1lYW5zKG1vMiwgdGVybXMgPSBjKHRlcm0sICJncm9zc19zdGFkdCIpKSAlPiUgCiAgcGxvdChhZGQuZGF0YSA9IFRSVUUsIHNob3cudGl0bGUgPSBGQUxTRSwgc2hvdy5sZWdlbmQgPSBGQUxTRSwgc2hvdy55LnRpdGxlID0gRkFMU0UpCn0KCnBsMSA8LSBwbG90X2VmZmVjdHMoImJlcmVjaHRpZ3RfbWl0dGVsIikKcGwyIDwtIHBsb3RfZWZmZWN0cygiYmV0ZWlsaWd1bmdfbWl0dGVsIikKIyBwbDMgPC0gcGxvdF9lZmZlY3RzKCJicmVpdGVuZ3JhZF9taXR0ZWwiKQojIHBsNCA8LSBwbG90X2VmZmVjdHMoImxhZW5nZW5ncmFkX21pdHRlbCIpCgpwbDEgKyBwbDIgIyArIHBsMyArIHBsNAoKIyBwcmVkaWN0KG1vMiwgbHR3X3BhcnRlaVtzdHJfZGV0ZWN0KGx0d19wYXJ0ZWkkd2J6LCAiSmVyaWNob3csIE9UIEthZGUiKSwgXSkgJT4lIHJvdW5kKDEpCmBgYAoKIyMjIFBhcnRlaWVuIChlaW56ZWxuKQoKSmUgZWluIE1laHItRWJlbmVuLU1vZGVsbCB6dXIgQmVzdGltbXVuZyBkZXMgU3RpbW1lbi1BbnRlaWxzIGVpbmVyIFBhcnRlaSBpbiBkZW4gV2FobGJlemlya2VuLgoKYGBge3IsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9Cmx0d19sbSA8LSAKICBsdHdfcGEzX21sbSAlPiUgCiAgZ3JvdXBfYnkocGFydGVpKSAlPiUgCiAgbmVzdCgpICU+JSAKICBtdXRhdGUoCiAgICBtb2RlbCA9IG1hcChkYXRhLCBmdW5jdGlvbihkZikgbG1lcihsbWVyX2Zvcm11bGEsIGRhdGEgPSBkZikpLAogICAgbW9kZWxfdGlkeSA9IG1hcChtb2RlbCwgdGlkeSksCiAgICBtb2RlbF9wcmVkMSA9IG1hcChtb2RlbCwgfiBnZ2VtbWVhbnMoLngsIHRlcm1zID0gYygiYmVyZWNodGlndF9taXR0ZWwiLCAiZ3Jvc3Nfc3RhZHQiKSkpLAogICAgbW9kZWxfcHJlZDIgPSBtYXAobW9kZWwsIH4gZ2dlbW1lYW5zKC54LCB0ZXJtcyA9IGMoImJldGVpbGlndW5nX21pdHRlbCIsICJncm9zc19zdGFkdCIpKSksCiAgICBtb2RlbF9wcmVkMyA9IG1hcChtb2RlbCwgfiBnZ2VtbWVhbnMoLngsIHRlcm1zID0gYygiYnJlaXRlbmdyYWRfbWl0dGVsIikpKSwKICAgIG1vZGVsX3ByZWQ0ID0gbWFwKG1vZGVsLCB+IGdnZW1tZWFucygueCwgdGVybXMgPSBjKCJsYWVuZ2VuZ3JhZF9taXR0ZWwiKSkpCiAgICApCgpsdHdfbG0gJT4lIAogIHVubmVzdChtb2RlbF90aWR5KSAlPiUKICBmaWx0ZXIoZWZmZWN0ID09ICJmaXhlZCIpICU+JSAKICBzZWxlY3QoLWRhdGEsIC1lZmZlY3QsIC1ncm91cCwgLXN0YXJ0c193aXRoKCJtb2RlbCIpKSAlPiUgCiAgbXV0YXRlX2lmKGlzLm51bWVyaWMsIHJvdW5kLCAzKSAlPiUgCiAgRFQ6OmRhdGF0YWJsZSgpCmBgYAoKCmBgYHtyLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQpsdHdfbG0gJT4lIAogIHVubmVzdChtb2RlbF9wcmVkMSkgJT4lCiAgZ2dwbG90KGFlcyh4ID0geCwgeSA9IHByZWRpY3RlZCkpICsKICBnZW9tX3BvaW50KGFlcyh4ID0gYmVyZWNodGlndF9taXR0ZWwsIHkgPSBhbnRlaWwsIGNvbG91ciA9IGdyb3NzX3N0YWR0KSwgZGF0YSA9IGx0d19wYTNfbWxtLCBhbHBoYSA9IDAuMDIpICsKICBnZW9tX3JpYmJvbihhZXMoeW1pbiA9IGNvbmYubG93LCB5bWF4ID0gY29uZi5oaWdoLCBmaWxsID0gZ3JvdXApLCBhbHBoYSA9IDAuNikgKwogIGdlb21fbGluZShhZXMoZ3JvdXAgPSBncm91cCksIGNvbG91ciA9ICJncmF5NDAiKSArCiAgeGxhYigiYmVyZWNodGlndF9taXR0ZWwiKSArIHlsYWIoImFudGVpbCIpICsKICB4bGltKC0xNjAwLCAxNjAwKSArCiAgZ3VpZGVzKGNvbG91ciA9IEZBTFNFLCBmaWxsID0gRkFMU0UpICsKICBmYWNldF93cmFwKHZhcnMocGFydGVpKSkKCmx0d19sbSAlPiUgCiAgdW5uZXN0KG1vZGVsX3ByZWQyKSAlPiUKICBzZWxlY3QoLWRhdGEsIC1tb2RlbCwgLW1vZGVsX3RpZHkpICU+JSAKICBnZ3Bsb3QoYWVzKHggPSB4LCB5ID0gcHJlZGljdGVkKSkgKwogIGdlb21fcG9pbnQoYWVzKHggPSBiZXRlaWxpZ3VuZ19taXR0ZWwsIHkgPSBhbnRlaWwsIGNvbG91ciA9IGdyb3NzX3N0YWR0KSwgZGF0YSA9IGx0d19wYTNfbWxtLCBhbHBoYSA9IDAuMDIpICsKICBnZW9tX3JpYmJvbihhZXMoeW1pbiA9IGNvbmYubG93LCB5bWF4ID0gY29uZi5oaWdoLCBmaWxsID0gZ3JvdXApLCBhbHBoYSA9IDAuNikgKwogIGdlb21fbGluZShhZXMoZ3JvdXAgPSBncm91cCksIGNvbG91ciA9ICJncmF5NDAiKSArCiAgeGxhYigiYmV0ZWlsaWd1bmdfbWl0dGVsIikgKyB5bGFiKCJhbnRlaWwiKSArCiAgeGxpbSgtMjUsIDI1KSArCiAgZ3VpZGVzKGNvbG91ciA9IEZBTFNFLCBmaWxsID0gRkFMU0UpICsKICBmYWNldF93cmFwKHZhcnMocGFydGVpKSkKYGBgCgpHZW9ncmFwaGlzY2hlIExhZ2UKCmBgYHtyLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQpwbDEgPC0gCiAgbHR3X2xtICU+JSAKICB1bm5lc3QobW9kZWxfcHJlZDMpICU+JQogIGdncGxvdChhZXMoeCA9IHgsIHkgPSBwcmVkaWN0ZWQpKSArCiAgZ2VvbV9yaWJib24oYWVzKHltaW4gPSBjb25mLmxvdywgeW1heCA9IGNvbmYuaGlnaCksIGZpbGwgPSAic2xhdGVncmF5MSIpICsKICBnZW9tX2xpbmUoKSArCiAgeGxhYigiYnJlaXRlbmdyYWRfbWl0dGVsIikgKyB5bGFiKCJhbnRlaWwiKSArCiAgeGxpbSgtMC4yMiwgMC4yMikgKwogIGZhY2V0X3dyYXAodmFycyhwYXJ0ZWkpKQoKcGwyIDwtIAogIGx0d19sbSAlPiUgCiAgdW5uZXN0KG1vZGVsX3ByZWQ0KSAlPiUKICBnZ3Bsb3QoYWVzKHggPSB4LCB5ID0gcHJlZGljdGVkKSkgKwogIGdlb21fcmliYm9uKGFlcyh5bWluID0gY29uZi5sb3csIHltYXggPSBjb25mLmhpZ2gpLCBmaWxsID0gInNsYXRlZ3JheTEiKSArCiAgZ2VvbV9saW5lKCkgKwogIHhsYWIoImxhZW5nZW5ncmFkX21pdHRlbCIpICsgeWxhYigiYW50ZWlsIikgKwogIGZhY2V0X3dyYXAodmFycyhwYXJ0ZWkpKQoKcGwxIC8gcGwyCmBgYAoKIyMjIEJldGVpbGlndW5nCgpNZWhyLUViZW5lbi1Nb2RlbGwgenVyIEJlc3RpbW11bmcgZGVyIFdhaGxiZXRlaWxpZ3VuZyBpbiBkZW4gV2FobGJlemlya2VuCgpgYGB7ciwgd2FybmluZz1GQUxTRX0KbW8zIDwtIGxtZXIoYmV0ZWlsaWd1bmcgfiBiZXJlY2h0aWd0X21pdHRlbCAqIGdyb3NzX3N0YWR0ICsgKDEgfCBsdHdrKSwgZGF0YSA9IGx0d19wYXJ0ZWkpCiMgc3VtbWFyeShtbzMpCgp0aWR5KG1vMykgJT4lIAogIGZpbHRlcihlZmZlY3QgPT0gImZpeGVkIikgJT4lIAogIHNlbGVjdCgtZWZmZWN0LCAtZ3JvdXApICU+JSAKICBtdXRhdGVfaWYoaXMubnVtZXJpYywgcm91bmQsIDMpCgpnZ2VtbWVhbnMobW8zLCB0ZXJtcyA9IGMoImJlcmVjaHRpZ3RfbWl0dGVsIiwgImdyb3NzX3N0YWR0IikpICU+JSAKICBwbG90KGFkZC5kYXRhID0gVFJVRSwgc2hvdy50aXRsZSA9IEZBTFNFKQpgYGAKCiMjIERhdGVuIAoKIyMjIEVyZ2Vibmlzc2UgUGFydGVpZW4KCmBgYHtyLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQpsdHdfcGEyICU+JSAKICBsZWZ0X2pvaW4obHR3X3BhMSkgJT4lIAogIGFycmFuZ2UobHR3a19uciwgd2J6LCBkZXNjKGFudGVpbCkpICU+JSAKICBzZWxlY3QobHR3aywgd2J6LCBiZXJlY2h0aWd0LCBiZXRlaWxpZ3VuZywgcGFydGVpLCBzdGltbWVuLCBhbnRlaWwsIGFudGVpbF9yYW5nKSAlPiUgCiAgRFQ6OmRhdGF0YWJsZSgpCmBgYAojIyMgV2FobGtyZWlzZSB1bmQgLWJlemlya2UKCmBgYHtyLCBtZXNzYWdlPUZBTFNFfQpsdHcgJT4lIAogIGdyb3VwX2J5KGx0d2tfbnIsIGx0d2spICU+JSAKICBzZWxlY3QoYmVyZWNodGlndCkgJT4lIAogIHNraW1yOjpza2ltKCkgJT4lIAogIHNlbGVjdCgtc2tpbV90eXBlLCAtc2tpbV92YXJpYWJsZSwgLW5fbWlzc2luZywgLWNvbXBsZXRlX3JhdGUpICU+JSAKICBtdXRhdGUoYWNyb3NzKGMobnVtZXJpYy5tZWFuLCBudW1lcmljLnNkKSwgfiByb3VuZCgueCwgMSkpKSAlPiUgCiAgcmVuYW1lX3dpdGgofiBzdHJfcmVwbGFjZSgueCwgZml4ZWQoIm51bWVyaWMuIiksICIiKSkgJT4lIAogIERUOjpkYXRhdGFibGUoKQpgYGAKCmBgYHtyLCBldmFsPUZBTFNFfQprYXJ0ZV93YnogJT4lIAogIGxlZnRfam9pbihsdHcgJT4lIHNlbGVjdCh3YnosIGJlcmVjaHRpZ3QpKSAlPiUgCiMgIGZpbHRlcihzdHJfZGV0ZWN0KGdlbWVpbmRlLCAiXkhhbGxlIikpICU+JSAKICBnZ3Bsb3QoKSArCiMgIGdlb21fc2YoKSArCiAgZ2VvbV9zZihkYXRhID0ga2FydGVfc3RyYXNzZV9hYiwgIGNvbG91ciA9ICJncmV5NzAiLCBzaXplID0gMS4xKSArCiAgZ2VvbV9zZihkYXRhID0ga2FydGVfc3RyYXNzZV9idSwgIGNvbG91ciA9ICJncmV5NjAiKSArCiAgZ2VvbV9wb2ludCgKICAgIGFlcyhzaXplID0gYmVyZWNodGlndCwgZ2VvbWV0cnkgPSBnZW9tZXRyeSksCiAgICBjb2xvdXIgPSAiYmx1ZSIsIGFscGhhID0gMC4xNSwgc3RhdCA9ICJzZl9jb29yZGluYXRlcyIKICAgICkgKyAKICB0aGVtZV92b2lkKCkKYGBgCgo=