Úvod

Jedním z největších překvapení letošních sněmovních voleb je výrazný nepoměr mezi mandáty získanými zástupci České pirátské strany ve srovnání s jejich koaličním partnerem, tedy STAN. Z celkových 37 křesel získali Piráti právě 4, tedy o 18 méně než jim připadá v aktuální Poslanecké sněmovně.

Již brzy po sečtení hlasů se začaly objevovat novinové články s titulky jako Tvrdý náraz Pirátů. Do sněmovny se dostanou jen čtyři. Jinými slovy se poměrně záhy po sečtení hlasů stal tento výsledek předmětem diskuze ve veřejném prostoru, která má potenciál dále eskalovat.

Opakovaně také zaznělo, že se jedná o důsledek tzv. přednostního či preferenčního hlasování, tedy udělení hlasů konkrétním kandidátům ze společné kandidátní listiny. Jak se vlastně preferenční hlasy promítají do celkového pořadí? V dokumentu Metody pro přepočet hlasů na mandáty používané v ČR ve volbách od roku 1990 se dočteme následující:

“Zákon zaváděl také dvě podmínky pro posun kandidáta pro přednostní přidělení mandátu. První podmínkou bylo, že alespoň desetina voličů dané strany využije práva přednostního hlasování a druhou podmínkou bylo získání tolika přednostních hlasů, že to bylo více než polovina hlasů pro tuto stranu, odevzdaných voliči, kteří využili práva přednostního hlasování. Každý volič disponoval čtyřmi přednostními hlasy.”

Jinými slovy musí alespoň 10 % voličů využít možnost preferenčního hlasování, přičemž pro započítání přednosti v pořadí musí být počet hlasů pro kandidáta větší než polovina těchto přednostních hlasů.

Pro zajímavost ČSÚ uvádí poměrně detailní popis toho, jakým způsobem přistupuje k vyhodnocení přednostních hlasů.

Data

Veškerá data pochází ze serveru volby.cz, organizované Českým statistickým úřadem (ČSÚ). Konkrétně jde o Výběr všech platných kandidátů za koalici Pirátů a Starostů a Počty hlasů pro strany.

# First of all, let us load the required packages and set the environment.
ipak <- function(pkg){
  new.pkg <- pkg[!(pkg %in% installed.packages()[, "Package"])]
  if (length(new.pkg)) 
    install.packages(new.pkg, dependencies = TRUE)
  sapply(pkg, require, character.only = TRUE)
}

packages <- c("tidyverse", "highcharter", "htmltools", "shiny")
ipak(packages)

# Globaly round numbers at decimals
options(digits=2)
# Force R to use regular numbers instead of using the e+10-like notation
options(scipen = 999)

# Representation of the table locally
psrk_2 <- read.csv("input_data/psrk_2.csv", 
                             header = TRUE,
                             encoding = "latin3"
                             ) %>%
          unite(full_name, c("PRIJMENI", "JMENO", "TITULPRED", "TITULZA"), sep = " ") %>%
          mutate(full_name = trimws(full_name, "r"),
                 full_name = str_squish(full_name),
                 full_name_join = gsub('. $', ".", full_name))

votes_per_candidates <- read.csv("input_data/votes_per_candidates.csv", 
                             header = TRUE,
                             encoding = "latin3"
                             ) %>%
                        select(-voting_rank) %>%
                        group_by(region_name) %>%
                        mutate(voting_rank = rank(desc(preference_vote_count))) %>%
                        mutate(full_name_join = gsub('. $', ".", candidate_name),
                                is_preferred = case_when(
                                  voting_rank < candidate_rank ~ 1,
                                  voting_rank > candidate_rank ~ 0,
                                  TRUE ~ as.numeric(voting_rank)),
                        candidate_voting_difference = candidate_rank - voting_rank,
                        preference_vote_count = trimws(preference_vote_count, "both")
                        ) %>%
                        arrange(region_id, desc(is_mandate), candidate_rank) %>%
                        inner_join(psrk_2, by = c("full_name_join" = "full_name_join")) %>%
                        select(region_name, candidate_name, is_mandate, is_preferred, candidate_voting_difference,
                               candidate_rank, voting_rank, preference_vote_count, preference_vote_percent,
                               candidate_age, nominating_party, political_party,
                               POVOLANI) %>%
                        mutate(is_mandate_spolu = case_when(
                                (region_name == 'Hl. m. Praha' & voting_rank <= 11) ~ 1,
                                (region_name == 'Středočeský' & voting_rank <= 10) ~ 1,
                                (region_name == 'Jihočeský' & voting_rank <= 5) ~ 1,
                                (region_name == 'Plzeňský' & voting_rank <= 4) ~ 1,
                                (region_name == 'Karlovarský' & voting_rank <= 1) ~ 1,
                                (region_name == 'Ústecký' & voting_rank <= 2) ~ 1,
                                (region_name == 'Liberecký' & voting_rank <= 2) ~ 1,
                                (region_name == 'Královéhradecký' & voting_rank <= 4) ~ 1,
                                (region_name == 'Vysočina' & voting_rank <= 4) ~ 1,
                                (region_name == 'Jihomoravský' & voting_rank <= 9) ~ 1,
                                (region_name == 'Pardubický' & voting_rank <= 4) ~ 1,
                                (region_name == 'Olomoucký' & voting_rank <= 4) ~ 1,
                                (region_name == 'Zlínský' & voting_rank <= 4) ~ 1,
                                (region_name == 'Moravskoslezský' & voting_rank <= 4) ~ 1,
                                TRUE ~ 0
                        ))

mandates_rank <- votes_per_candidates %>%
                  select(voting_rank, region_name) %>%
                  group_by(voting_rank, region_name) %>%
                  summarize(count = n())

votes_per_candidates_outranked <- votes_per_candidates %>%
                                    filter(candidate_voting_difference < 0)

votes_per_candidates_outranked_mandate <- votes_per_candidates %>%
                                            mutate(vote_candidate_difference = voting_rank - candidate_rank) %>%
                                            filter(vote_candidate_difference < 0)

votes_per_country <- read.csv("input_data/votes_per_country.csv", 
                             header = TRUE,
                             encoding = "latin3"
                             ) %>%
                     filter(str_detect(party,'Piráti')) %>%
                     gather(region, votes, `Celkem.ČR`:`Moravsko..slezský.kraj`, factor_key = TRUE)

votes_per_party <- votes_per_candidates %>%
                    group_by(nominating_party) %>%
                    summarize(avg_pref_vote_count = mean(as.numeric(preference_vote_count)))

votes_per_party_no_central_bohemia <- votes_per_candidates %>%
                    filter(region_name != 'Středočeský') %>%
                    group_by(nominating_party) %>%
                    summarize(avg_pref_vote_count = mean(as.numeric(preference_vote_count)))

mandates_all <- votes_per_candidates %>%
              select(is_mandate, nominating_party) %>%
              group_by(nominating_party) %>%
              summarize(mandates_sum = sum(as.integer(is_mandate)))

mandates_like_spolu_all <- votes_per_candidates %>%
              select(is_mandate_spolu, nominating_party) %>%
              group_by(nominating_party) %>%
              summarize(mandates_sum = sum(as.integer(is_mandate_spolu)))

Počty preferenčních hlasů

Nejdříve se podívejme na celkový počet získaných preferenčních hlasů dle jednotlivých krajů. V každém kraji vidíme vyšší počet udělených preferenčních hlasů pro STAN. V průměru získali kandidáti STAN 5 091 preferenčních hlasů napříč kandidátkou a zemí, zatímco Piráti hlasů 2 203. Pokud si odmyslíme nejvýraznější kraj, tedy Středočeský, pro kandidáty STAN je to v průměru 4 400 hlasů a pro Piráty 2 179 hlasů. Napříč republikou tak dostali zástupci STAN v průměru dvojnásobný počet preferenčních hlasů.

votes_per_candidates_outranked_votes_chart <- votes_per_candidates %>%
              select(region_name, preference_vote_count, nominating_party) %>%
              group_by(region_name, nominating_party) %>%
              summarize(vote_candidate_difference_sum = sum(as.integer(preference_vote_count))) %>%
              arrange(region_name, vote_candidate_difference_sum) %>%
              rename(`Kraj` = "region_name",
                     `Hlasy` = "vote_candidate_difference_sum",
                     `Nominující strana` = "nominating_party") %>%
              hchart('column', hcaes(x = Kraj, y = 'Hlasy', group = `Nominující strana`)) %>%
              hc_colors(c("#0073C2FF", "#EFC000FF")) %>%
              hc_tooltip(pointFormat = "{point.Hlasy} preferenčních hlasů") %>%
              hc_chart(style = list(
                                    fontWeight = "bold",
                                    fontSize = 16)) %>%
              hc_add_theme(hc_theme_ffx()) %>%
              hc_legend(align = "center") %>%
              hc_title(text = "Kdo získal kolik preferenčních hlasů?") %>% 
              hc_subtitle(text = "Součet preferenčních hlasů dle stran koalice PirSTAN a krajů.")

votes_per_candidates_outranked_votes_chart

Pořadí a skokanky

To se jednoznačně projevilo na počtu “přeskákaných pozic”. Tedy, pokud bychom sečetli “bonus pořadí”, ve kterém se odráží pořadí získané preferenční hlasy pro obě strany koalice. Jen s tím rozdílem, že zástupkyním STAN pomohl zisk preferenčních hlasů k lepšímu pořadí výrazněji než těm od Pirátů. Z povahy věci, kdy při omezeném počtu mandátů dle kraje bere ten, kdo získá více preferenčních hlasů, více křesel.

votes_per_candidates_outranked_mandate_chart <- votes_per_candidates_outranked_mandate %>%
              select(region_name, candidate_voting_difference, nominating_party) %>%
              group_by(region_name, nominating_party) %>%
              summarize(vote_candidate_difference_sum = sum(candidate_voting_difference)) %>%
              arrange(region_name, vote_candidate_difference_sum) %>%
              rename(`Kraj` = "region_name",
                     `Bodů` = "vote_candidate_difference_sum",
                     `Nominující strana` = "nominating_party") %>%
              hchart('column', hcaes(x = Kraj, y = 'Bodů', group = `Nominující strana`)) %>%
              hc_colors(c("#0073C2FF", "#EFC000FF")) %>%
              hc_tooltip(pointFormat = "{point.Bodů} bodů pořadí") %>%
              hc_chart(style = list(
                                    fontWeight = "bold",
                                    fontSize = 16)) %>%
              hc_add_theme(hc_theme_ffx()) %>%
              hc_legend(align = "center") %>%
              hc_title(text = "Kdo přeskákal kolik pozic?") %>% 
              hc_subtitle(text = "Suma přeskákaných pozic pořadí dle stran koalice PirSTAN a krajů.")

votes_per_candidates_outranked_mandate_chart

Ztracené pozice

Komplementárně se můžeme ptát, kdo a v jakém kraji pozice ztratil. Byť i kandidáti za Českou pirátskou stranu obdrželi nemalé množství preferenčních hlasů, na první pohled je patrná čistá ztráta pozic napříč kraji:

votes_per_candidates_outranked_chart <- votes_per_candidates_outranked %>%
              select(region_name, candidate_voting_difference, nominating_party) %>%
              group_by(region_name, nominating_party) %>%
              summarize(candidate_voting_difference_sum = sum(candidate_voting_difference)) %>%
              arrange(region_name, candidate_voting_difference_sum) %>%
              rename(`Kraj` = "region_name",
                     `Rozdíl` = "candidate_voting_difference_sum",
                     `Nominující strana` = "nominating_party") %>%
              hchart('column', hcaes(x = Kraj, y = 'Rozdíl', group = `Nominující strana`)) %>%
              hc_colors(c("#0073C2FF", "#EFC000FF")) %>%
              hc_tooltip(pointFormat = "{point.Rozdíl} bodů pořadí") %>%
              hc_chart(style = list(
                                    fontWeight = "bold",
                                    fontSize = 16)) %>%
              hc_add_theme(hc_theme_ffx()) %>%
              hc_legend(align = "center") %>%
              hc_title(text = "Suma 'ztraceného pořadí' dle stran koalice PirSTAN a krajů.") %>%
              hc_subtitle(text = "Kdo přeskákal kolik pozic ve volbě ve srovnání s kandidátkou?")

votes_per_candidates_outranked_chart

Zvolení, zvolené

Jak si vedli konkrétní kandidáti a kandidátky, které nakonec voliči poslali do Poslanecké sněmovny? Kdo jsou nejvýraznější “skokani” a kolik preferenčních hlasů získali? Následující tabulka shrnuje základní údaje a její podbarvení pomáhá při orientaci v tom, kdo si v pořadí polepšil (zelená barva), zůstal na svém (šedá barva) či pohoršil (červená barva).

votes_per_candidates_outranked_mandate_table <- votes_per_candidates %>%
                                            mutate(vote_candidate_difference = voting_rank - candidate_rank) %>%
                                            filter(is_mandate == 1) %>%
    select(region_name, candidate_name, nominating_party, candidate_rank, voting_rank, candidate_voting_difference, preference_vote_count) %>%
    rename("Kraj" = region_name,
         "Kandidát/ka" = candidate_name,
         "Strana" = nominating_party,
         "Rozdíl" = candidate_voting_difference,
         "Pořadí na kandidátce" = candidate_rank,
         "Pořadí ve volbách" = voting_rank,
         "Počet hlasů" = preference_vote_count)

eps <- 1E-5

DT::datatable(votes_per_candidates_outranked_mandate_table, filter = "top",  # allows filtering on each column
    extensions = c(
      "Buttons",  # add download buttons, etc
      "Scroller"  # for scrolling down the rows rather than pagination
    ),
    rownames = FALSE,  # remove rownames
    style = "bootstrap",
    class = 'cell-border display',
    width = "100%",
    options = list(
      pageLength = 40,
      dom = 't',
      # dom = "Blrtip",  # specify content (search box, etc)
      deferRender = TRUE,
      scrollY = 900,
      scroller = TRUE,
        columnDefs = list(list(className = 'dt-center', targets = 0:5))
        )
      ) %>% DT::formatStyle(
        "Rozdíl",
        target = 'row',
        backgroundColor  = DT::styleInterval(cuts = c(-eps, eps), values = c("red", "grey", "green")))

PirSTAN jako SPOLU

Jak by vypadalo rozdělení mandátů, kdyby koalice PirSTAN dosáhla v jednotlivých krajích stejných výsledků jako koalice SPOLU? Předpokládejme, že by výsledné pořadí kandidátů PirSTAN zůstalo stejné, jen by tato koalice získala v každém kraji stejný počet mandátů jako koalice SPOLU. Respektive v krajích, kde získal PirSTAN více mandátů než koalice SPOLU (např. Liberecký kraj), by si ponechali svůj komparativně lepší výsledek.

Z výsledku plyne, že byť by Piráti polepšili nominálně (ze 4 poslanců by se jednalo o 14) i relativně (z 12 % mandátů by šlo o 25 %). Stále to je ale daleko k paritě.

mandates_like_spolu_chart <- votes_per_candidates %>%
              select(region_name, is_mandate_spolu, nominating_party) %>%
              group_by(region_name, nominating_party) %>%
              summarize(mandates_sum = sum(as.integer(is_mandate_spolu))) %>%
              arrange(region_name, mandates_sum) %>%
              rename(`Kraj` = "region_name",
                     `Mandáty` = "mandates_sum",
                     `Nominující strana` = "nominating_party") %>%
              hchart('column', hcaes(x = Kraj, y = 'Mandáty', group = `Nominující strana`)) %>%
              hc_colors(c("#0073C2FF", "#EFC000FF")) %>%
              hc_tooltip(pointFormat = "{point.Mandáty} Mandátů") %>%
              hc_chart(style = list(
                                    fontWeight = "bold",
                                    fontSize = 16)) %>%
              hc_add_theme(hc_theme_ffx()) %>%
              hc_legend(align = "center") %>%
              hc_title(text = "Co kdyby PirSTAN získal podobně mandátů jako SPOLU?") %>% 
              hc_subtitle(text = "Součet modelových mandátů dle stran koalice PirSTAN a krajů jako by šlo o SPOLU.")

mandates_like_spolu_chart

Závěrem

Je samozřejmě otázkou, jestli voliči Pirátské strany pouze aktivně nevyužívali preferenční hlasování (čemuž by nasvědčoval rozdíl mezi předchozími volebními výsledky v posledních letech), případně jestli jejich voliči odešli jinam. První vysvětlení by svědčilo pro zajímavý designový problém preferenčního hlasování.

Neméně zajímavé potom bude sledovat vnitřní dynamiku v rámci koalice. V koaliční smlouvě totiž stojí následující:

“Pokud v důsledku preferenčních hlasů získá mandát poslance jiná koaliční strana než určuje dohodnuté pořadí na kandidátní listině, zohlední koaliční rada a celostátní lídři obou koaličních stran ve svých rozhodnutích vhodnou formu nefinanční kompenzace.”

Jak asi bude vypadat taková “vhodná forma nefinanční kompenzace”?

   

Návrat na Blog.

LS0tCnRpdGxlOiAiVnlrcm91xb5rb3bDoW5pLiBQaXJTVEFOLCBwcmVmZXJlbsSNbsOtIGhsYXN5IGEgdm9sYnkgMjAyMSIKYXV0aG9yOiAiVml0IEdhYnJoZWwiCm91dHB1dDogCiAgaHRtbF9ub3RlYm9vazoKICAgIHRoZW1lOiBmbGF0bHkKICAgIGhpZ2hsaWdodDogbW9ub2Nocm9tZQogICAgY3NzOiAvVXNlcnMvdml0Z2FicmhlbC9EZXNrdG9wL1Byb2pla3R5L2RhdGFtdXN0Zmxvdy9wdWJsaWMvY3NzL2NvZGVyLm1pbi5hNGYzMzIyMTNhMjFjZThlYjUyMTY3MGM2MTQ0NzBjNTg5MjNhYWFmMzg1ZTJhNzM5ODJjMzFkZDc2NDJkZWNiLmNzcyAKICAgIGNvZGVfZm9sZGluZzogImhpZGUiCiAgICB0b2M6IHllcwogICAgdG9jX2RlcHRoOiAyCiAgICB0b2NfZmxvYXQ6IHllcwotLS0KCgojIyDDmnZvZAoKSmVkbsOtbSB6IG5lanbEm3TFocOtY2ggcMWZZWt2YXBlbsOtIGxldG/FoW7DrWNoIHNuxJttb3Zuw61jaCB2b2xlYiBqZSB2w71yYXpuw70gbmVwb23Em3IgbWV6aSBtYW5kw6F0eSB6w61za2Fuw71taSB6w6FzdHVwY2kgKsSMZXNrw6kgcGlyw6F0c2vDqSBzdHJhbnkqIHZlIHNyb3Zuw6Fuw60gcyBqZWppY2gga29hbGnEjW7DrW0gcGFydG5lcmVtLCB0ZWR5ICpTVEFOKi4gWiBjZWxrb3bDvWNoICoqMzcga8WZZXNlbCoqIHrDrXNrYWxpICoqUGlyw6F0aSoqIHByw6F2xJsgKio0KiosIHRlZHkgKipvIDE4IG3DqW7EmyoqIG5lxb4gamltIHDFmWlwYWTDoSB2ICoqYWt0dcOhbG7DrSBQb3NsYW5lY2vDqSBzbsSbbW92bsSbKiouIAoKSmnFviBicnp5IHBvIHNlxI10ZW7DrSBobGFzxa8gc2UgemHEjWFseSBvYmpldm92YXQgbm92aW5vdsOpIMSNbMOhbmt5IHMgdGl0dWxreSBqYWtvIFtUdnJkw70gbsOhcmF6IFBpcsOhdMWvLiBEbyBzbsSbbW92bnkgc2UgZG9zdGFub3UgamVuIMSNdHnFmWkuXShodHRwczovL2RvbWFjaS5obi5jei9jMS02Njk4NDQ4MC10dnJkeS1uYXJhei1waXJhdHUtZG8tc25lbW92bnktc2UtZG9zdGFub3UtamVuLXRyaS16Ynl0ZWstbWFuZGF0dS11a29yaXN0aWxpLXN0YXJvc3RvdmUpIEppbsO9bWkgc2xvdnkgc2UgcG9txJtybsSbIHrDoWh5IHBvIHNlxI10ZW7DrSBobGFzxa8gc3RhbCB0ZW50byB2w71zbGVkZWsgcMWZZWRtxJt0ZW0gZGlza3V6ZSB2ZSB2ZcWZZWpuw6ltIHByb3N0b3J1LCBrdGVyw6EgbcOhIHBvdGVuY2nDoWwgZMOhbGUgZXNrYWxvdmF0LiAKCk9wYWtvdmFuxJsgdGFrw6kgemF6bsSbbG8sIMW+ZSBzZSBqZWRuw6EgbyBkxa9zbGVkZWsgdHp2LiBwxZllZG5vc3Ruw61obyDEjWkgcHJlZmVyZW7EjW7DrWhvIGhsYXNvdsOhbsOtLCB0ZWR5IHVkxJtsZW7DrSBobGFzxa8ga29ua3LDqXRuw61tIGthbmRpZMOhdMWvbSB6ZSBzcG9sZcSNbsOpIGthbmRpZMOhdG7DrSBsaXN0aW55LiBKYWsgc2Ugdmxhc3RuxJsgcHJlZmVyZW7EjW7DrSBobGFzeSBwcm9tw610YWrDrSBkbyBjZWxrb3bDqWhvIHBvxZlhZMOtPyBWIGRva3VtZW50dSBbTWV0b2R5IHBybyBwxZllcG/EjWV0IGhsYXPFryBuYSBtYW5kw6F0eSBwb3XFvsOtdmFuw6kgdiDEjFIKdmUgdm9sYsOhY2ggb2Qgcm9rdSAxOTkwXShodHRwczovL3d3dy5jenNvLmN6L2RvY3VtZW50cy8xMDE4MC8yMzE5MDY0My9obGFzeV9tYW5kYXR5X2NyX2FrdDIwMjEucGRmL2UxMmM0YzFlLTVjYmUtNGZhNC04ZGE2LWI0OGVhZWIyNGYyZD92ZXJzaW9uPTEuMCkgc2UgZG/EjXRlbWUgbsOhc2xlZHVqw61jw606IAoKPiAiWsOha29uIHphdsOhZMSbbCB0YWvDqSBkdsSbIHBvZG3DrW5reSBwcm8gcG9zdW4ga2FuZGlkw6F0YSBwcm8gcMWZZWRub3N0bsOtIHDFmWlkxJtsZW7DrSBtYW5kw6F0dS4gUHJ2bsOtIHBvZG3DrW5rb3UgYnlsbywgxb5lIGFsZXNwb8WIIGRlc2V0aW5hIHZvbGnEjcWvIGRhbsOpIHN0cmFueSB2eXXFvmlqZSBwcsOhdmEgcMWZZWRub3N0bsOtaG8gaGxhc292w6Fuw60gYSBkcnVob3UgcG9kbcOtbmtvdSBieWxvIHrDrXNrw6Fuw60gdG9saWthIHDFmWVkbm9zdG7DrWNoCmhsYXPFrywgxb5lIHRvIGJ5bG8gdsOtY2UgbmXFviBwb2xvdmluYSBobGFzxa8gcHJvIHR1dG8gc3RyYW51LCBvZGV2emRhbsO9Y2ggdm9sacSNaSwga3RlxZnDrSB2eXXFvmlsaSBwcsOhdmEgcMWZZWRub3N0bsOtaG8gaGxhc292w6Fuw60uIEthxb5kw70gdm9sacSNIGRpc3Bvbm92YWwgxI10ecWZbWkgcMWZZWRub3N0bsOtbWkgaGxhc3kuIgoKSmluw71taSBzbG92eSBtdXPDrSBhbGVzcG/FiCAxMCAlIHZvbGnEjcWvIHZ5dcW+w610IG1vxb5ub3N0IHByZWZlcmVuxI1uw61obyBobGFzb3bDoW7DrSwgcMWZacSNZW3FviBwcm8gemFwb8SNw610w6Fuw60gcMWZZWRub3N0aSB2IHBvxZlhZMOtIG11c8OtIGLDvXQgcG/EjWV0IGhsYXPFryBwcm8ga2FuZGlkw6F0YSB2xJt0xaHDrSBuZcW+IHBvbG92aW5hIHTEm2NodG8gcMWZZWRub3N0bsOtY2ggaGxhc8WvLgoKUHJvIHphasOtbWF2b3N0IMSMU8OaIHV2w6Fkw60gcG9txJtybsSbIFtkZXRhaWxuw60gcG9waXMgdG9ob10oaHR0cHM6Ly93d3cuY3pzby5jei9kb2N1bWVudHMvMTAxODAvMTYzMzc3NTI2L3BzX3ByaWtsYWR5X3Z5aG9kbm9jZW5pX3ByZWRub3N0bmljaCtobGFzdS5wZGYvNjRjMWM2ODYtYmZmOS00MWRjLWJhNzItMGU3ZmM2YjYwNmY3P3ZlcnNpb249MS4wKSwgamFrw71tIHpwxa9zb2JlbSBwxZlpc3R1cHVqZSBrIHZ5aG9kbm9jZW7DrSBwxZllZG5vc3Ruw61jaCBobGFzxa8uCgojIyBEYXRhCgpWZcWha2Vyw6EgZGF0YSBwb2Now6F6w60gemUgc2VydmVydSBbdm9sYnkuY3pdKGh0dHBzOi8vd3d3LnZvbGJ5LmN6LyksIG9yZ2FuaXpvdmFuw6kgxIxlc2vDvW0gc3RhdGlzdGlja8O9bSDDusWZYWRlbSAoxIxTw5opLiBLb25rcsOpdG7EmyBqZGUgbyBbVsO9YsSbciB2xaFlY2ggcGxhdG7DvWNoIGthbmRpZMOhdMWvIHphIGtvYWxpY2kgUGlyw6F0xa8gYSBTdGFyb3N0xa9dKGh0dHBzOi8vd3d3LnZvbGJ5LmN6L3Bscy9wczIwMjEvcHMxMTE/eGphenlrPUNaJnhrcmFqPTAmeHN0cmFuYT0xNyZ4dj0xJnh0PTEpIGEgW1BvxI10eSBobGFzxa8gcHJvIHN0cmFueV0oUG/EjXR5IGhsYXPFryBwcm8gc3RyYW55KS4KCmBgYHtyLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQojIEZpcnN0IG9mIGFsbCwgbGV0IHVzIGxvYWQgdGhlIHJlcXVpcmVkIHBhY2thZ2VzIGFuZCBzZXQgdGhlIGVudmlyb25tZW50LgppcGFrIDwtIGZ1bmN0aW9uKHBrZyl7CiAgbmV3LnBrZyA8LSBwa2dbIShwa2cgJWluJSBpbnN0YWxsZWQucGFja2FnZXMoKVssICJQYWNrYWdlIl0pXQogIGlmIChsZW5ndGgobmV3LnBrZykpIAogICAgaW5zdGFsbC5wYWNrYWdlcyhuZXcucGtnLCBkZXBlbmRlbmNpZXMgPSBUUlVFKQogIHNhcHBseShwa2csIHJlcXVpcmUsIGNoYXJhY3Rlci5vbmx5ID0gVFJVRSkKfQoKcGFja2FnZXMgPC0gYygidGlkeXZlcnNlIiwgImhpZ2hjaGFydGVyIiwgImh0bWx0b29scyIsICJzaGlueSIpCmlwYWsocGFja2FnZXMpCgojIEdsb2JhbHkgcm91bmQgbnVtYmVycyBhdCBkZWNpbWFscwpvcHRpb25zKGRpZ2l0cz0yKQojIEZvcmNlIFIgdG8gdXNlIHJlZ3VsYXIgbnVtYmVycyBpbnN0ZWFkIG9mIHVzaW5nIHRoZSBlKzEwLWxpa2Ugbm90YXRpb24Kb3B0aW9ucyhzY2lwZW4gPSA5OTkpCgojIFJlcHJlc2VudGF0aW9uIG9mIHRoZSB0YWJsZSBsb2NhbGx5CnBzcmtfMiA8LSByZWFkLmNzdigiaW5wdXRfZGF0YS9wc3JrXzIuY3N2IiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaGVhZGVyID0gVFJVRSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbmNvZGluZyA9ICJsYXRpbjMiCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKSAlPiUKICAgICAgICAgIHVuaXRlKGZ1bGxfbmFtZSwgYygiUFJJSk1FTkkiLCAiSk1FTk8iLCAiVElUVUxQUkVEIiwgIlRJVFVMWkEiKSwgc2VwID0gIiAiKSAlPiUKICAgICAgICAgIG11dGF0ZShmdWxsX25hbWUgPSB0cmltd3MoZnVsbF9uYW1lLCAiciIpLAogICAgICAgICAgICAgICAgIGZ1bGxfbmFtZSA9IHN0cl9zcXVpc2goZnVsbF9uYW1lKSwKICAgICAgICAgICAgICAgICBmdWxsX25hbWVfam9pbiA9IGdzdWIoJy4gJCcsICIuIiwgZnVsbF9uYW1lKSkKCnZvdGVzX3Blcl9jYW5kaWRhdGVzIDwtIHJlYWQuY3N2KCJpbnB1dF9kYXRhL3ZvdGVzX3Blcl9jYW5kaWRhdGVzLmNzdiIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIGhlYWRlciA9IFRSVUUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZW5jb2RpbmcgPSAibGF0aW4zIgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICkgJT4lCiAgICAgICAgICAgICAgICAgICAgICAgIHNlbGVjdCgtdm90aW5nX3JhbmspICU+JQogICAgICAgICAgICAgICAgICAgICAgICBncm91cF9ieShyZWdpb25fbmFtZSkgJT4lCiAgICAgICAgICAgICAgICAgICAgICAgIG11dGF0ZSh2b3RpbmdfcmFuayA9IHJhbmsoZGVzYyhwcmVmZXJlbmNlX3ZvdGVfY291bnQpKSkgJT4lCiAgICAgICAgICAgICAgICAgICAgICAgIG11dGF0ZShmdWxsX25hbWVfam9pbiA9IGdzdWIoJy4gJCcsICIuIiwgY2FuZGlkYXRlX25hbWUpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlzX3ByZWZlcnJlZCA9IGNhc2Vfd2hlbigKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZvdGluZ19yYW5rIDwgY2FuZGlkYXRlX3JhbmsgfiAxLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdm90aW5nX3JhbmsgPiBjYW5kaWRhdGVfcmFuayB+IDAsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBUUlVFIH4gYXMubnVtZXJpYyh2b3RpbmdfcmFuaykpLAogICAgICAgICAgICAgICAgICAgICAgICBjYW5kaWRhdGVfdm90aW5nX2RpZmZlcmVuY2UgPSBjYW5kaWRhdGVfcmFuayAtIHZvdGluZ19yYW5rLAogICAgICAgICAgICAgICAgICAgICAgICBwcmVmZXJlbmNlX3ZvdGVfY291bnQgPSB0cmltd3MocHJlZmVyZW5jZV92b3RlX2NvdW50LCAiYm90aCIpCiAgICAgICAgICAgICAgICAgICAgICAgICkgJT4lCiAgICAgICAgICAgICAgICAgICAgICAgIGFycmFuZ2UocmVnaW9uX2lkLCBkZXNjKGlzX21hbmRhdGUpLCBjYW5kaWRhdGVfcmFuaykgJT4lCiAgICAgICAgICAgICAgICAgICAgICAgIGlubmVyX2pvaW4ocHNya18yLCBieSA9IGMoImZ1bGxfbmFtZV9qb2luIiA9ICJmdWxsX25hbWVfam9pbiIpKSAlPiUKICAgICAgICAgICAgICAgICAgICAgICAgc2VsZWN0KHJlZ2lvbl9uYW1lLCBjYW5kaWRhdGVfbmFtZSwgaXNfbWFuZGF0ZSwgaXNfcHJlZmVycmVkLCBjYW5kaWRhdGVfdm90aW5nX2RpZmZlcmVuY2UsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYW5kaWRhdGVfcmFuaywgdm90aW5nX3JhbmssIHByZWZlcmVuY2Vfdm90ZV9jb3VudCwgcHJlZmVyZW5jZV92b3RlX3BlcmNlbnQsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYW5kaWRhdGVfYWdlLCBub21pbmF0aW5nX3BhcnR5LCBwb2xpdGljYWxfcGFydHksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBQT1ZPTEFOSSkgJT4lCiAgICAgICAgICAgICAgICAgICAgICAgIG11dGF0ZShpc19tYW5kYXRlX3Nwb2x1ID0gY2FzZV93aGVuKAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIChyZWdpb25fbmFtZSA9PSAnSGwuIG0uIFByYWhhJyAmIHZvdGluZ19yYW5rIDw9IDExKSB+IDEsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKHJlZ2lvbl9uYW1lID09ICdTdMWZZWRvxI1lc2vDvScgJiB2b3RpbmdfcmFuayA8PSAxMCkgfiAxLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIChyZWdpb25fbmFtZSA9PSAnSmlob8SNZXNrw70nICYgdm90aW5nX3JhbmsgPD0gNSkgfiAxLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIChyZWdpb25fbmFtZSA9PSAnUGx6ZcWIc2vDvScgJiB2b3RpbmdfcmFuayA8PSA0KSB+IDEsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKHJlZ2lvbl9uYW1lID09ICdLYXJsb3ZhcnNrw70nICYgdm90aW5nX3JhbmsgPD0gMSkgfiAxLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIChyZWdpb25fbmFtZSA9PSAnw5pzdGVja8O9JyAmIHZvdGluZ19yYW5rIDw9IDIpIH4gMSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAocmVnaW9uX25hbWUgPT0gJ0xpYmVyZWNrw70nICYgdm90aW5nX3JhbmsgPD0gMikgfiAxLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIChyZWdpb25fbmFtZSA9PSAnS3LDoWxvdsOpaHJhZGVja8O9JyAmIHZvdGluZ19yYW5rIDw9IDQpIH4gMSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAocmVnaW9uX25hbWUgPT0gJ1Z5c2/EjWluYScgJiB2b3RpbmdfcmFuayA8PSA0KSB+IDEsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKHJlZ2lvbl9uYW1lID09ICdKaWhvbW9yYXZza8O9JyAmIHZvdGluZ19yYW5rIDw9IDkpIH4gMSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAocmVnaW9uX25hbWUgPT0gJ1BhcmR1Ymlja8O9JyAmIHZvdGluZ19yYW5rIDw9IDQpIH4gMSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAocmVnaW9uX25hbWUgPT0gJ09sb21vdWNrw70nICYgdm90aW5nX3JhbmsgPD0gNCkgfiAxLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIChyZWdpb25fbmFtZSA9PSAnWmzDrW5za8O9JyAmIHZvdGluZ19yYW5rIDw9IDQpIH4gMSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAocmVnaW9uX25hbWUgPT0gJ01vcmF2c2tvc2xlenNrw70nICYgdm90aW5nX3JhbmsgPD0gNCkgfiAxLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFRSVUUgfiAwCiAgICAgICAgICAgICAgICAgICAgICAgICkpCgptYW5kYXRlc19yYW5rIDwtIHZvdGVzX3Blcl9jYW5kaWRhdGVzICU+JQogICAgICAgICAgICAgICAgICBzZWxlY3Qodm90aW5nX3JhbmssIHJlZ2lvbl9uYW1lKSAlPiUKICAgICAgICAgICAgICAgICAgZ3JvdXBfYnkodm90aW5nX3JhbmssIHJlZ2lvbl9uYW1lKSAlPiUKICAgICAgICAgICAgICAgICAgc3VtbWFyaXplKGNvdW50ID0gbigpKQoKdm90ZXNfcGVyX2NhbmRpZGF0ZXNfb3V0cmFua2VkIDwtIHZvdGVzX3Blcl9jYW5kaWRhdGVzICU+JQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmaWx0ZXIoY2FuZGlkYXRlX3ZvdGluZ19kaWZmZXJlbmNlIDwgMCkKCnZvdGVzX3Blcl9jYW5kaWRhdGVzX291dHJhbmtlZF9tYW5kYXRlIDwtIHZvdGVzX3Blcl9jYW5kaWRhdGVzICU+JQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG11dGF0ZSh2b3RlX2NhbmRpZGF0ZV9kaWZmZXJlbmNlID0gdm90aW5nX3JhbmsgLSBjYW5kaWRhdGVfcmFuaykgJT4lCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmlsdGVyKHZvdGVfY2FuZGlkYXRlX2RpZmZlcmVuY2UgPCAwKQoKdm90ZXNfcGVyX2NvdW50cnkgPC0gcmVhZC5jc3YoImlucHV0X2RhdGEvdm90ZXNfcGVyX2NvdW50cnkuY3N2IiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaGVhZGVyID0gVFJVRSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbmNvZGluZyA9ICJsYXRpbjMiCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKSAlPiUKICAgICAgICAgICAgICAgICAgICAgZmlsdGVyKHN0cl9kZXRlY3QocGFydHksJ1BpcsOhdGknKSkgJT4lCiAgICAgICAgICAgICAgICAgICAgIGdhdGhlcihyZWdpb24sIHZvdGVzLCBgQ2Vsa2VtLsSMUmA6YE1vcmF2c2tvLi5zbGV6c2vDvS5rcmFqYCwgZmFjdG9yX2tleSA9IFRSVUUpCgp2b3Rlc19wZXJfcGFydHkgPC0gdm90ZXNfcGVyX2NhbmRpZGF0ZXMgJT4lCiAgICAgICAgICAgICAgICAgICAgZ3JvdXBfYnkobm9taW5hdGluZ19wYXJ0eSkgJT4lCiAgICAgICAgICAgICAgICAgICAgc3VtbWFyaXplKGF2Z19wcmVmX3ZvdGVfY291bnQgPSBtZWFuKGFzLm51bWVyaWMocHJlZmVyZW5jZV92b3RlX2NvdW50KSkpCgp2b3Rlc19wZXJfcGFydHlfbm9fY2VudHJhbF9ib2hlbWlhIDwtIHZvdGVzX3Blcl9jYW5kaWRhdGVzICU+JQogICAgICAgICAgICAgICAgICAgIGZpbHRlcihyZWdpb25fbmFtZSAhPSAnU3TFmWVkb8SNZXNrw70nKSAlPiUKICAgICAgICAgICAgICAgICAgICBncm91cF9ieShub21pbmF0aW5nX3BhcnR5KSAlPiUKICAgICAgICAgICAgICAgICAgICBzdW1tYXJpemUoYXZnX3ByZWZfdm90ZV9jb3VudCA9IG1lYW4oYXMubnVtZXJpYyhwcmVmZXJlbmNlX3ZvdGVfY291bnQpKSkKCm1hbmRhdGVzX2FsbCA8LSB2b3Rlc19wZXJfY2FuZGlkYXRlcyAlPiUKICAgICAgICAgICAgICBzZWxlY3QoaXNfbWFuZGF0ZSwgbm9taW5hdGluZ19wYXJ0eSkgJT4lCiAgICAgICAgICAgICAgZ3JvdXBfYnkobm9taW5hdGluZ19wYXJ0eSkgJT4lCiAgICAgICAgICAgICAgc3VtbWFyaXplKG1hbmRhdGVzX3N1bSA9IHN1bShhcy5pbnRlZ2VyKGlzX21hbmRhdGUpKSkKCm1hbmRhdGVzX2xpa2Vfc3BvbHVfYWxsIDwtIHZvdGVzX3Blcl9jYW5kaWRhdGVzICU+JQogICAgICAgICAgICAgIHNlbGVjdChpc19tYW5kYXRlX3Nwb2x1LCBub21pbmF0aW5nX3BhcnR5KSAlPiUKICAgICAgICAgICAgICBncm91cF9ieShub21pbmF0aW5nX3BhcnR5KSAlPiUKICAgICAgICAgICAgICBzdW1tYXJpemUobWFuZGF0ZXNfc3VtID0gc3VtKGFzLmludGVnZXIoaXNfbWFuZGF0ZV9zcG9sdSkpKQpgYGAKCgojIyBQb8SNdHkgcHJlZmVyZW7EjW7DrWNoIGhsYXPFrwoKTmVqZMWZw612ZSBzZSBwb2TDrXZlam1lIG5hIGNlbGtvdsO9IHBvxI1ldCB6w61za2Fuw71jaCBwcmVmZXJlbsSNbsOtY2ggaGxhc8WvIGRsZSBqZWRub3RsaXbDvWNoIGtyYWrFry4gViAqKmthxb5kw6ltIGtyYWppKiogdmlkw61tZSAqKnZ5xaHFocOtIHBvxI1ldCB1ZMSbbGVuw71jaCBwcmVmZXJlbsSNbsOtY2ggaGxhc8WvKiogcHJvICoqU1RBTioqLiBWICoqcHLFr23Em3J1KiogesOtc2thbGkga2FuZGlkw6F0aSAqKlNUQU4gNSAwOTEgcHJlZmVyZW7EjW7DrWNoIGhsYXPFryoqIG5hcMWZw63EjSBrYW5kaWTDoXRrb3UgYSB6ZW3DrSwgemF0w61tY28gKipQaXLDoXRpIGhsYXPFryAyIDIwMyoqLiBQb2t1ZCBzaSAqKm9kbXlzbMOtbWUqKiBuZWp2w71yYXpuxJtqxaHDrSBrcmFqLCB0ZWR5ICoqU3TFmWVkb8SNZXNrw70qKiwgcHJvIGthbmRpZMOhdHkgKipTVEFOKiogamUgdG8gKip2IHByxa9txJtydSA0IDQwMCBobGFzxa8qKiBhIHBybyAqKlBpcsOhdHkgMiAxNzkgaGxhc8WvKiouICoqTmFwxZnDrcSNIHJlcHVibGlrb3UqKiB0YWsgZG9zdGFsaSB6w6FzdHVwY2kgKipTVEFOKiogdiAqKnByxa9txJtydSBkdm9qbsOhc29ibsO9IHBvxI1ldCBwcmVmZXJlbsSNbsOtY2ggaGxhc8WvKiouCgpgYGB7ciwgZXJyb3I9RkFMU0UsIG1lc3NhZ2U9RkFMU0V9CnZvdGVzX3Blcl9jYW5kaWRhdGVzX291dHJhbmtlZF92b3Rlc19jaGFydCA8LSB2b3Rlc19wZXJfY2FuZGlkYXRlcyAlPiUKICAgICAgICAgICAgICBzZWxlY3QocmVnaW9uX25hbWUsIHByZWZlcmVuY2Vfdm90ZV9jb3VudCwgbm9taW5hdGluZ19wYXJ0eSkgJT4lCiAgICAgICAgICAgICAgZ3JvdXBfYnkocmVnaW9uX25hbWUsIG5vbWluYXRpbmdfcGFydHkpICU+JQogICAgICAgICAgICAgIHN1bW1hcml6ZSh2b3RlX2NhbmRpZGF0ZV9kaWZmZXJlbmNlX3N1bSA9IHN1bShhcy5pbnRlZ2VyKHByZWZlcmVuY2Vfdm90ZV9jb3VudCkpKSAlPiUKICAgICAgICAgICAgICBhcnJhbmdlKHJlZ2lvbl9uYW1lLCB2b3RlX2NhbmRpZGF0ZV9kaWZmZXJlbmNlX3N1bSkgJT4lCiAgICAgICAgICAgICAgcmVuYW1lKGBLcmFqYCA9ICJyZWdpb25fbmFtZSIsCiAgICAgICAgICAgICAgICAgICAgIGBIbGFzeWAgPSAidm90ZV9jYW5kaWRhdGVfZGlmZmVyZW5jZV9zdW0iLAogICAgICAgICAgICAgICAgICAgICBgTm9taW51asOtY8OtIHN0cmFuYWAgPSAibm9taW5hdGluZ19wYXJ0eSIpICU+JQogICAgICAgICAgICAgIGhjaGFydCgnY29sdW1uJywgaGNhZXMoeCA9IEtyYWosIHkgPSAnSGxhc3knLCBncm91cCA9IGBOb21pbnVqw61jw60gc3RyYW5hYCkpICU+JQogICAgICAgICAgICAgIGhjX2NvbG9ycyhjKCIjMDA3M0MyRkYiLCAiI0VGQzAwMEZGIikpICU+JQogICAgICAgICAgICAgIGhjX3Rvb2x0aXAocG9pbnRGb3JtYXQgPSAie3BvaW50LkhsYXN5fSBwcmVmZXJlbsSNbsOtY2ggaGxhc8WvIikgJT4lCiAgICAgICAgICAgICAgaGNfY2hhcnQoc3R5bGUgPSBsaXN0KAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmb250V2VpZ2h0ID0gImJvbGQiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmb250U2l6ZSA9IDE2KSkgJT4lCiAgICAgICAgICAgICAgaGNfYWRkX3RoZW1lKGhjX3RoZW1lX2ZmeCgpKSAlPiUKICAgICAgICAgICAgICBoY19sZWdlbmQoYWxpZ24gPSAiY2VudGVyIikgJT4lCiAgICAgICAgICAgICAgaGNfdGl0bGUodGV4dCA9ICJLZG8gesOtc2thbCBrb2xpayBwcmVmZXJlbsSNbsOtY2ggaGxhc8WvPyIpICU+JSAKICAgICAgICAgICAgICBoY19zdWJ0aXRsZSh0ZXh0ID0gIlNvdcSNZXQgcHJlZmVyZW7EjW7DrWNoIGhsYXPFryBkbGUgc3RyYW4ga29hbGljZSBQaXJTVEFOIGEga3JhasWvLiIpCgp2b3Rlc19wZXJfY2FuZGlkYXRlc19vdXRyYW5rZWRfdm90ZXNfY2hhcnQKYGBgCgojIyBQb8WZYWTDrSBhIHNrb2thbmt5CgpUbyBzZSBqZWRub3puYcSNbsSbIHByb2pldmlsbyBuYSBwb8SNdHUgInDFmWVza8Oha2Fuw71jaCBwb3ppYyIuIFRlZHksIHBva3VkIGJ5Y2hvbSBzZcSNZXRsaSAiYm9udXMgcG/FmWFkw60iLCB2ZSBrdGVyw6ltIHNlIG9kcsOhxb7DrSBwb8WZYWTDrSB6w61za2Fuw6kgcHJlZmVyZW7EjW7DrSBobGFzeSBwcm8gb2LEmyBzdHJhbnkga29hbGljZS4gSmVuIHMgdMOtbSByb3pkw61sZW0sIMW+ZSB6w6FzdHVwa3luw61tIFNUQU4gcG9tb2hsIHppc2sgcHJlZmVyZW7EjW7DrWNoIGhsYXPFryBrIGxlcMWhw61tdSBwb8WZYWTDrSB2w71yYXpuxJtqaSBuZcW+IHTEm20gb2QgUGlyw6F0xa8uIFogcG92YWh5IHbEm2NpLCBrZHkgcMWZaSBvbWV6ZW7DqW0gcG/EjXR1IG1hbmTDoXTFryBkbGUga3JhamUgYmVyZSB0ZW4sIGtkbyB6w61za8OhIHbDrWNlIHByZWZlcmVuxI1uw61jaCBobGFzxa8sIHbDrWNlIGvFmWVzZWwuIAoKYGBge3IsIGVycm9yPUZBTFNFLCBtZXNzYWdlPUZBTFNFfQp2b3Rlc19wZXJfY2FuZGlkYXRlc19vdXRyYW5rZWRfbWFuZGF0ZV9jaGFydCA8LSB2b3Rlc19wZXJfY2FuZGlkYXRlc19vdXRyYW5rZWRfbWFuZGF0ZSAlPiUKICAgICAgICAgICAgICBzZWxlY3QocmVnaW9uX25hbWUsIGNhbmRpZGF0ZV92b3RpbmdfZGlmZmVyZW5jZSwgbm9taW5hdGluZ19wYXJ0eSkgJT4lCiAgICAgICAgICAgICAgZ3JvdXBfYnkocmVnaW9uX25hbWUsIG5vbWluYXRpbmdfcGFydHkpICU+JQogICAgICAgICAgICAgIHN1bW1hcml6ZSh2b3RlX2NhbmRpZGF0ZV9kaWZmZXJlbmNlX3N1bSA9IHN1bShjYW5kaWRhdGVfdm90aW5nX2RpZmZlcmVuY2UpKSAlPiUKICAgICAgICAgICAgICBhcnJhbmdlKHJlZ2lvbl9uYW1lLCB2b3RlX2NhbmRpZGF0ZV9kaWZmZXJlbmNlX3N1bSkgJT4lCiAgICAgICAgICAgICAgcmVuYW1lKGBLcmFqYCA9ICJyZWdpb25fbmFtZSIsCiAgICAgICAgICAgICAgICAgICAgIGBCb2TFr2AgPSAidm90ZV9jYW5kaWRhdGVfZGlmZmVyZW5jZV9zdW0iLAogICAgICAgICAgICAgICAgICAgICBgTm9taW51asOtY8OtIHN0cmFuYWAgPSAibm9taW5hdGluZ19wYXJ0eSIpICU+JQogICAgICAgICAgICAgIGhjaGFydCgnY29sdW1uJywgaGNhZXMoeCA9IEtyYWosIHkgPSAnQm9kxa8nLCBncm91cCA9IGBOb21pbnVqw61jw60gc3RyYW5hYCkpICU+JQogICAgICAgICAgICAgIGhjX2NvbG9ycyhjKCIjMDA3M0MyRkYiLCAiI0VGQzAwMEZGIikpICU+JQogICAgICAgICAgICAgIGhjX3Rvb2x0aXAocG9pbnRGb3JtYXQgPSAie3BvaW50LkJvZMWvfSBib2TFryBwb8WZYWTDrSIpICU+JQogICAgICAgICAgICAgIGhjX2NoYXJ0KHN0eWxlID0gbGlzdCgKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9udFdlaWdodCA9ICJib2xkIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9udFNpemUgPSAxNikpICU+JQogICAgICAgICAgICAgIGhjX2FkZF90aGVtZShoY190aGVtZV9mZngoKSkgJT4lCiAgICAgICAgICAgICAgaGNfbGVnZW5kKGFsaWduID0gImNlbnRlciIpICU+JQogICAgICAgICAgICAgIGhjX3RpdGxlKHRleHQgPSAiS2RvIHDFmWVza8Oha2FsIGtvbGlrIHBvemljPyIpICU+JSAKICAgICAgICAgICAgICBoY19zdWJ0aXRsZSh0ZXh0ID0gIlN1bWEgcMWZZXNrw6FrYW7DvWNoIHBvemljIHBvxZlhZMOtIGRsZSBzdHJhbiBrb2FsaWNlIFBpclNUQU4gYSBrcmFqxa8uIikKCnZvdGVzX3Blcl9jYW5kaWRhdGVzX291dHJhbmtlZF9tYW5kYXRlX2NoYXJ0CmBgYAoKIyMgWnRyYWNlbsOpIHBvemljZQoKS29tcGxlbWVudMOhcm7EmyBzZSBtxa/FvmVtZSBwdMOhdCwga2RvIGEgdiBqYWvDqW0ga3JhamkgcG96aWNlIHp0cmF0aWwuIEJ5xaUgaSBrYW5kaWTDoXRpIHphICoqxIxlc2tvdSBwaXLDoXRza291IHN0cmFudSoqIG9iZHLFvmVsaSBuZW1hbMOpIG1ub8W+c3R2w60gcHJlZmVyZW7EjW7DrWNoIGhsYXPFrywgbmEgcHJ2bsOtIHBvaGxlZCBqZSBwYXRybsOhICoqxI1pc3TDoSB6dHLDoXRhIHBvemljIG5hcMWZw63EjSBrcmFqaSoqOgoKCmBgYHtyLCBlcnJvcj1GQUxTRSwgbWVzc2FnZT1GQUxTRX0Kdm90ZXNfcGVyX2NhbmRpZGF0ZXNfb3V0cmFua2VkX2NoYXJ0IDwtIHZvdGVzX3Blcl9jYW5kaWRhdGVzX291dHJhbmtlZCAlPiUKICAgICAgICAgICAgICBzZWxlY3QocmVnaW9uX25hbWUsIGNhbmRpZGF0ZV92b3RpbmdfZGlmZmVyZW5jZSwgbm9taW5hdGluZ19wYXJ0eSkgJT4lCiAgICAgICAgICAgICAgZ3JvdXBfYnkocmVnaW9uX25hbWUsIG5vbWluYXRpbmdfcGFydHkpICU+JQogICAgICAgICAgICAgIHN1bW1hcml6ZShjYW5kaWRhdGVfdm90aW5nX2RpZmZlcmVuY2Vfc3VtID0gc3VtKGNhbmRpZGF0ZV92b3RpbmdfZGlmZmVyZW5jZSkpICU+JQogICAgICAgICAgICAgIGFycmFuZ2UocmVnaW9uX25hbWUsIGNhbmRpZGF0ZV92b3RpbmdfZGlmZmVyZW5jZV9zdW0pICU+JQogICAgICAgICAgICAgIHJlbmFtZShgS3JhamAgPSAicmVnaW9uX25hbWUiLAogICAgICAgICAgICAgICAgICAgICBgUm96ZMOtbGAgPSAiY2FuZGlkYXRlX3ZvdGluZ19kaWZmZXJlbmNlX3N1bSIsCiAgICAgICAgICAgICAgICAgICAgIGBOb21pbnVqw61jw60gc3RyYW5hYCA9ICJub21pbmF0aW5nX3BhcnR5IikgJT4lCiAgICAgICAgICAgICAgaGNoYXJ0KCdjb2x1bW4nLCBoY2Flcyh4ID0gS3JhaiwgeSA9ICdSb3pkw61sJywgZ3JvdXAgPSBgTm9taW51asOtY8OtIHN0cmFuYWApKSAlPiUKICAgICAgICAgICAgICBoY19jb2xvcnMoYygiIzAwNzNDMkZGIiwgIiNFRkMwMDBGRiIpKSAlPiUKICAgICAgICAgICAgICBoY190b29sdGlwKHBvaW50Rm9ybWF0ID0gIntwb2ludC5Sb3pkw61sfSBib2TFryBwb8WZYWTDrSIpICU+JQogICAgICAgICAgICAgIGhjX2NoYXJ0KHN0eWxlID0gbGlzdCgKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9udFdlaWdodCA9ICJib2xkIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9udFNpemUgPSAxNikpICU+JQogICAgICAgICAgICAgIGhjX2FkZF90aGVtZShoY190aGVtZV9mZngoKSkgJT4lCiAgICAgICAgICAgICAgaGNfbGVnZW5kKGFsaWduID0gImNlbnRlciIpICU+JQogICAgICAgICAgICAgIGhjX3RpdGxlKHRleHQgPSAiU3VtYSAnenRyYWNlbsOpaG8gcG/FmWFkw60nIGRsZSBzdHJhbiBrb2FsaWNlIFBpclNUQU4gYSBrcmFqxa8uIikgJT4lCiAgICAgICAgICAgICAgaGNfc3VidGl0bGUodGV4dCA9ICJLZG8gcMWZZXNrw6FrYWwga29saWsgcG96aWMgdmUgdm9sYsSbIHZlIHNyb3Zuw6Fuw60gcyBrYW5kaWTDoXRrb3U/IikKCnZvdGVzX3Blcl9jYW5kaWRhdGVzX291dHJhbmtlZF9jaGFydApgYGAKCiMjIFp2b2xlbsOtLCB6dm9sZW7DqQoKSmFrIHNpIHZlZGxpICoqa29ua3LDqXRuw60ga2FuZGlkw6F0aSBhIGthbmRpZMOhdGt5KiosIGt0ZXLDqSBuYWtvbmVjIHZvbGnEjWkgcG9zbGFsaSBkbyBQb3NsYW5lY2vDqSBzbsSbbW92bnk/IEtkbyBqc291IG5lanbDvXJhem7Em2rFocOtICJza29rYW5pIiBhIGtvbGlrIHByZWZlcmVuxI1uw61jaCBobGFzxa8gesOtc2thbGk/IE7DoXNsZWR1asOtY8OtIHRhYnVsa2Egc2hybnVqZSB6w6FrbGFkbsOtIMO6ZGFqZSBhIGplasOtIHBvZGJhcnZlbsOtIHBvbcOhaMOhIHDFmWkgb3JpZW50YWNpIHYgdG9tLCBrZG8gc2kgdiBwb8WZYWTDrSBwb2xlcMWhaWwgKHplbGVuw6EgYmFydmEpLCB6xa9zdGFsIG5hIHN2w6ltICjFoWVkw6EgYmFydmEpIMSNaSBwb2hvcsWhaWwgKMSNZXJ2ZW7DoSBiYXJ2YSkuCgpgYGB7ciwgZXJyb3I9RkFMU0UsIG1lc3NhZ2U9RkFMU0V9CnZvdGVzX3Blcl9jYW5kaWRhdGVzX291dHJhbmtlZF9tYW5kYXRlX3RhYmxlIDwtIHZvdGVzX3Blcl9jYW5kaWRhdGVzICU+JQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG11dGF0ZSh2b3RlX2NhbmRpZGF0ZV9kaWZmZXJlbmNlID0gdm90aW5nX3JhbmsgLSBjYW5kaWRhdGVfcmFuaykgJT4lCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmlsdGVyKGlzX21hbmRhdGUgPT0gMSkgJT4lCiAgICBzZWxlY3QocmVnaW9uX25hbWUsIGNhbmRpZGF0ZV9uYW1lLCBub21pbmF0aW5nX3BhcnR5LCBjYW5kaWRhdGVfcmFuaywgdm90aW5nX3JhbmssIGNhbmRpZGF0ZV92b3RpbmdfZGlmZmVyZW5jZSwgcHJlZmVyZW5jZV92b3RlX2NvdW50KSAlPiUKICAgIHJlbmFtZSgiS3JhaiIgPSByZWdpb25fbmFtZSwKICAgICAgICAgIkthbmRpZMOhdC9rYSIgPSBjYW5kaWRhdGVfbmFtZSwKICAgICAgICAgIlN0cmFuYSIgPSBub21pbmF0aW5nX3BhcnR5LAogICAgICAgICAiUm96ZMOtbCIgPSBjYW5kaWRhdGVfdm90aW5nX2RpZmZlcmVuY2UsCiAgICAgICAgICJQb8WZYWTDrSBuYSBrYW5kaWTDoXRjZSIgPSBjYW5kaWRhdGVfcmFuaywKICAgICAgICAgIlBvxZlhZMOtIHZlIHZvbGLDoWNoIiA9IHZvdGluZ19yYW5rLAogICAgICAgICAiUG/EjWV0IGhsYXPFryIgPSBwcmVmZXJlbmNlX3ZvdGVfY291bnQpCgplcHMgPC0gMUUtNQoKRFQ6OmRhdGF0YWJsZSh2b3Rlc19wZXJfY2FuZGlkYXRlc19vdXRyYW5rZWRfbWFuZGF0ZV90YWJsZSwgZmlsdGVyID0gInRvcCIsICAjIGFsbG93cyBmaWx0ZXJpbmcgb24gZWFjaCBjb2x1bW4KICAgIGV4dGVuc2lvbnMgPSBjKAogICAgICAiQnV0dG9ucyIsICAjIGFkZCBkb3dubG9hZCBidXR0b25zLCBldGMKICAgICAgIlNjcm9sbGVyIiAgIyBmb3Igc2Nyb2xsaW5nIGRvd24gdGhlIHJvd3MgcmF0aGVyIHRoYW4gcGFnaW5hdGlvbgogICAgKSwKICAgIHJvd25hbWVzID0gRkFMU0UsICAjIHJlbW92ZSByb3duYW1lcwogICAgc3R5bGUgPSAiYm9vdHN0cmFwIiwKICAgIGNsYXNzID0gJ2NlbGwtYm9yZGVyIGRpc3BsYXknLAogICAgd2lkdGggPSAiMTAwJSIsCiAgICBvcHRpb25zID0gbGlzdCgKICAgICAgcGFnZUxlbmd0aCA9IDQwLAogICAgICBkb20gPSAndCcsCiAgICAgICMgZG9tID0gIkJscnRpcCIsICAjIHNwZWNpZnkgY29udGVudCAoc2VhcmNoIGJveCwgZXRjKQogICAgICBkZWZlclJlbmRlciA9IFRSVUUsCiAgICAgIHNjcm9sbFkgPSA5MDAsCiAgICAgIHNjcm9sbGVyID0gVFJVRSwKICAgICAgICBjb2x1bW5EZWZzID0gbGlzdChsaXN0KGNsYXNzTmFtZSA9ICdkdC1jZW50ZXInLCB0YXJnZXRzID0gMDo1KSkKICAgICAgICApCiAgICAgICkgJT4lIERUOjpmb3JtYXRTdHlsZSgKICAgICAgICAiUm96ZMOtbCIsCiAgICAgICAgdGFyZ2V0ID0gJ3JvdycsCiAgICAgICAgYmFja2dyb3VuZENvbG9yICA9IERUOjpzdHlsZUludGVydmFsKGN1dHMgPSBjKC1lcHMsIGVwcyksIHZhbHVlcyA9IGMoInJlZCIsICJncmV5IiwgImdyZWVuIikpKQpgYGAKCiMjIFBpclNUQU4gamFrbyBTUE9MVQoKSmFrIGJ5IHZ5cGFkYWxvIHJvemTEm2xlbsOtIG1hbmTDoXTFrywga2R5Ynkga29hbGljZSBQaXJTVEFOIGRvc8OhaGxhIHYgamVkbm90bGl2w71jaCBrcmFqw61jaCBzdGVqbsO9Y2ggdsO9c2xlZGvFryBqYWtvIGtvYWxpY2UgU1BPTFU/IFDFmWVkcG9rbMOhZGVqbWUsIMW+ZSBieSB2w71zbGVkbsOpIHBvxZlhZMOtIGthbmRpZMOhdMWvIFBpclNUQU4gesWvc3RhbG8gc3Rlam7DqSwgamVuIGJ5IHRhdG8ga29hbGljZSB6w61za2FsYSB2IGthxb5kw6ltIGtyYWppIHN0ZWpuw70gcG/EjWV0IG1hbmTDoXTFryBqYWtvIGtvYWxpY2UgU1BPTFUuIFJlc3Bla3RpdmUgdiBrcmFqw61jaCwga2RlIHrDrXNrYWwgUGlyU1RBTiB2w61jZSBtYW5kw6F0xa8gbmXFviBrb2FsaWNlIFNQT0xVIChuYXDFmS4gTGliZXJlY2vDvSBrcmFqKSwgYnkgc2kgcG9uZWNoYWxpIHN2xa9qIGtvbXBhcmF0aXZuxJsgbGVwxaHDrSB2w71zbGVkZWsuCgpaIHbDvXNsZWRrdSBwbHluZSwgxb5lIGJ5xaUgYnkgKipQaXLDoXRpICBwb2xlcMWhaWxpKiogbm9taW7DoWxuxJsgKHplICoqNCBwb3NsYW5jxa8qKiBieSBzZSBqZWRuYWxvIG8gKioxNCoqKSBpIHJlbGF0aXZuxJsgKHogKioxMiAlIG1hbmTDoXTFryoqIGJ5IMWhbG8gbyAqKjI1ICUqKikuIFN0w6FsZSB0byBqZSBhbGUgZGFsZWtvIGsgcGFyaXTEmy4KCmBgYHtyLCBlcnJvcj1GQUxTRSwgbWVzc2FnZT1GQUxTRX0KbWFuZGF0ZXNfbGlrZV9zcG9sdV9jaGFydCA8LSB2b3Rlc19wZXJfY2FuZGlkYXRlcyAlPiUKICAgICAgICAgICAgICBzZWxlY3QocmVnaW9uX25hbWUsIGlzX21hbmRhdGVfc3BvbHUsIG5vbWluYXRpbmdfcGFydHkpICU+JQogICAgICAgICAgICAgIGdyb3VwX2J5KHJlZ2lvbl9uYW1lLCBub21pbmF0aW5nX3BhcnR5KSAlPiUKICAgICAgICAgICAgICBzdW1tYXJpemUobWFuZGF0ZXNfc3VtID0gc3VtKGFzLmludGVnZXIoaXNfbWFuZGF0ZV9zcG9sdSkpKSAlPiUKICAgICAgICAgICAgICBhcnJhbmdlKHJlZ2lvbl9uYW1lLCBtYW5kYXRlc19zdW0pICU+JQogICAgICAgICAgICAgIHJlbmFtZShgS3JhamAgPSAicmVnaW9uX25hbWUiLAogICAgICAgICAgICAgICAgICAgICBgTWFuZMOhdHlgID0gIm1hbmRhdGVzX3N1bSIsCiAgICAgICAgICAgICAgICAgICAgIGBOb21pbnVqw61jw60gc3RyYW5hYCA9ICJub21pbmF0aW5nX3BhcnR5IikgJT4lCiAgICAgICAgICAgICAgaGNoYXJ0KCdjb2x1bW4nLCBoY2Flcyh4ID0gS3JhaiwgeSA9ICdNYW5kw6F0eScsIGdyb3VwID0gYE5vbWludWrDrWPDrSBzdHJhbmFgKSkgJT4lCiAgICAgICAgICAgICAgaGNfY29sb3JzKGMoIiMwMDczQzJGRiIsICIjRUZDMDAwRkYiKSkgJT4lCiAgICAgICAgICAgICAgaGNfdG9vbHRpcChwb2ludEZvcm1hdCA9ICJ7cG9pbnQuTWFuZMOhdHl9IE1hbmTDoXTFryIpICU+JQogICAgICAgICAgICAgIGhjX2NoYXJ0KHN0eWxlID0gbGlzdCgKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9udFdlaWdodCA9ICJib2xkIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9udFNpemUgPSAxNikpICU+JQogICAgICAgICAgICAgIGhjX2FkZF90aGVtZShoY190aGVtZV9mZngoKSkgJT4lCiAgICAgICAgICAgICAgaGNfbGVnZW5kKGFsaWduID0gImNlbnRlciIpICU+JQogICAgICAgICAgICAgIGhjX3RpdGxlKHRleHQgPSAiQ28ga2R5YnkgUGlyU1RBTiB6w61za2FsIHBvZG9ibsSbIG1hbmTDoXTFryBqYWtvIFNQT0xVPyIpICU+JSAKICAgICAgICAgICAgICBoY19zdWJ0aXRsZSh0ZXh0ID0gIlNvdcSNZXQgbW9kZWxvdsO9Y2ggbWFuZMOhdMWvIGRsZSBzdHJhbiBrb2FsaWNlIFBpclNUQU4gYSBrcmFqxa8gamFrbyBieSDFoWxvIG8gU1BPTFUuIikKCm1hbmRhdGVzX2xpa2Vfc3BvbHVfY2hhcnQKYGBgCgojIyBaw6F2xJtyZW0KCkplIHNhbW96xZllam3EmyBvdMOhemtvdSwgamVzdGxpIHZvbGnEjWkgUGlyw6F0c2vDqSBzdHJhbnkgcG91emUgYWt0aXZuxJsgbmV2eXXFvsOtdmFsaSBwcmVmZXJlbsSNbsOtIGhsYXNvdsOhbsOtICjEjWVtdcW+IGJ5IG5hc3bEm2TEjW92YWwgcm96ZMOtbCBtZXppIHDFmWVkY2hvesOtbWkgdm9sZWJuw61taSB2w71zbGVka3kgdiBwb3NsZWRuw61jaCBsZXRlY2gpLCBwxZnDrXBhZG7EmyBqZXN0bGkgamVqaWNoIHZvbGnEjWkgb2RlxaFsaSBqaW5hbS4gUHJ2bsOtIHZ5c3bEm3RsZW7DrSBieSBzdsSbZMSNaWxvIHBybyB6YWrDrW1hdsO9IGRlc2lnbm92w70gcHJvYmzDqW0gcHJlZmVyZW7EjW7DrWhvIGhsYXNvdsOhbsOtLgoKTmVtw6luxJsgemFqw61tYXbDqSBwb3RvbSBidWRlIHNsZWRvdmF0IHZuaXTFmW7DrSBkeW5hbWlrdSB2IHLDoW1jaSBrb2FsaWNlLiBWIFtrb2FsacSNbsOtIHNtbG91dsSbXShodHRwczovL3d3dy5zdGFyb3N0b3ZlLW5lemF2aXNsaS5jei9mbWZpbGUvMC9maWxlcy8yMDIwJTIwaGxhdm4lQzMlQUQlMjBTVEFOL2tvYWxpY25pLXNtbG91dmEtcGlyYXRpLWEtc3Rhcm9zdG92ZS5wZGYpIHRvdGnFviBzdG9qw60gbsOhc2xlZHVqw61jw606Cgo+ICJQb2t1ZCB2IGTFr3NsZWRrdSBwcmVmZXJlbsSNbsOtY2ggaGxhc8WvIHrDrXNrw6EgbWFuZMOhdCBwb3NsYW5jZSBqaW7DoSBrb2FsacSNbsOtIHN0cmFuYSBuZcW+IHVyxI11amUgZG9ob2RudXTDqSBwb8WZYWTDrSBuYSBrYW5kaWTDoXRuw60gbGlzdGluxJssIHpvaGxlZG7DrSBrb2FsacSNbsOtIHJhZGEgYSBjZWxvc3TDoXRuw60gbMOtZMWZaSBvYm91IGtvYWxpxI1uw61jaCBzdHJhbiB2ZSBzdsO9Y2ggcm96aG9kbnV0w61jaCB2aG9kbm91IGZvcm11IG5lZmluYW7EjW7DrSBrb21wZW56YWNlLiIKCkphayBhc2kgYnVkZSB2eXBhZGF0IHRha292w6Eg4oCcKip2aG9kbsOhIGZvcm1hIG5lZmluYW7EjW7DrSBrb21wZW56YWNlKirigJ0/CgombmJzcDsKJm5ic3A7Cgo8cCBzdHlsZT0idGV4dC1hbGlnbjogY2VudGVyOyI+PGI+TsOhdnJhdCBuYSA8YSBocmVmPSIvcG9zdCI+QmxvZzwvYj48L2E+LjwvcD4=