Parim koht viienda aastaaja kogemiseks Eestis on Soomaa!

Soomaa

Üleujutuste andmed ja prognoos

Hüdroloogilised tunniandmed

Soomaa pakub huvi eelkõige oma üleujutustega suurvee perioodil ehk viienda aastaaja poolest. Seega tuleks alustuseks vaadata, mis seal toimub sellel aastal ja kuidas on praegused veetasemed ning vooluhulgad. Valitud on 2 hüdroloogilise seire jaama, mis võiksid anda kõige parema info Soomaa hetkeseisu kohta:

Allolevatel graafikutel on kuvatud Aesoo hüdromeetriajaamas mõõdetud vooluhulgad ja veetasemed.

Veevoolu andmed

Aesoo hüdromeetriajaama hüdroloogilise seire veevoolu tunniandmed annavad ülevaate vee liikumisest sellel perioodil. Vooluhulga suurenemine näitab suurvee aja algust ja intensiivsust. Samas mida rohkem vett on jões ja voolab ära seda vähem on seda üleujutatud aladel.

# Äravool
library(dygraphs)
dygraph(hydro_data_1[,c("timeline_ts_utc","Äravool avg"),],
        main = "Äravool keskmine", 
        ylab = "Tunni keskmine äravool, m3/s") %>%
    dyRangeSelector()%>%
    dyRoller(rollPeriod = 24) %>%
    dyOptions(fillGraph = TRUE, fillAlpha = 0.4)

Veetasemed

Aesoo hüdromeetriajaama hüdroloogilise seire veetasemete tunniandmed annavad ülevaate veetasemetest huvipakkuval perioodil. Veetasemed on heaks indikaatoriks, millal on kõige sobivam aeg üleujutusalade külastamiseks. Samas on näha, et veetasemete kõikumisi on mitu mistõttu ka õigeid Soomaa külastusaegu võib olla mitu. Parim aeg suurvee kogemiseks 2024.astal oli ilmselt märtsi alguses kuid ka märtsi lõpus näitavad andmed veetasemete suuremat kõikumist.

# WL-veetasemed
library(dygraphs)
dygraph(hydro_data_1[,c("timeline_ts_utc","WL max","WL min"),],
        main = "Tunni maksimaalne veetase (WL max) ja minimaalne veetase (WL min)", 
        ylab = "veetase, cm") %>%
    dyRangeSelector()%>%
    dyRoller(rollPeriod = 24) %>%
    dyOptions(fillGraph = TRUE, fillAlpha = 0.4)

Meteoroloogilise seire tunniandmed

Soomaa suurvee tulek ja minek on oluliselt seotud meteoroloogiliste näitajatega nagu sademed ja õhutemperatuur. Seega tuleks alustuseks vaadata, mida näitavad andmed suurvee perioodil sellel ja eelmisel aastal. Kuna Soomaa asub kolme meteoroloogiajaama kolmnurgas peagu et keskel, siis sai Välja valitud järgmised kolm meteoroloogiajaama, mis võiks anda kõige parema info:

Allolevatel graafikutel on kuvatud nendes meteoroloogiajaamades mõõdetud temperatuurid ja sademete hulgad.

Õhutemperatuur

Türi, Pärnu ja Viljandi meteoroloogilise seire õhutemperatuuri tunniandmed annavad ülevaate kuidas ilm mõjutab suurvee teket. Mida rohkem on külmakraade ja sademeid talvel seda rohkem talletub vett ja seda rohkem on kevadel suurvett.

# Õhutemp täistunnil
library(dygraphs)
dygraph(kliima_data_TA,
        main = "Õhutemperatuur täistunnil (hetkväärtus)", 
        ylab = "kraad(c)") %>%
    dyRangeSelector()%>%
    dyRoller(rollPeriod = 24) %>%
    dyOptions(fillGraph = TRUE, fillAlpha = 0.2)

Sademed

Türi, Pärnu ja Viljandi meteoroloogilise seire sademete tunniandmed annavad ülevaate kuidas ilm mõjutab suurvee teket. Mida rohkem on külmakraade ja sademeid seda rohkem talletub vett ja seda rohkem on kevadel suurvett.

# Ühe tunni sademete summa
library(dygraphs)
dygraph(kliima_data_PR1H,
        main = "Ühe tunni sademete summa", 
        ylab = "mm")%>%
    dyRangeSelector()%>%
    dyRoller(rollPeriod = 3)%>%
    
    dyOptions(fillGraph = TRUE, fillAlpha = 0.2) 

Andmete võrdlus

Hüdroloogiliste ja meteoroloogiliste andmete võrdlus

Suurvee kõrgaja leidmiseks on vaja vaadata kuidas mõjutavad valitud hüdroloogilised ja meteoroloogilised näitajad üksteist. Kuna andmete skaalad on väga erinevad siis võrdluse saamiseks tuleb andmed enne normaliseerida (nn kaalutud andmed). Et graafik oleks loetav ja tõlgendatav tuleb temperatuuri andmeid ka keskmistada (30 päeva keskmine) Alloleva graafiku normaliseeritud väärtuste põhjal on näha kuidas ilm mõjutab veetasemeid ja äravoolu.

# normaliseeritud väärtus
library(dygraphs)
dygraph(tulemus,
        main = "Normaliseeritud andmed", 
        ylab = " Normaliseeritud väärtus")%>%
    dyRangeSelector()%>%
    dyRoller(rollPeriod = 24)%>%
    dyHighlight(highlightSeriesOpts = list(strokeWidth = 3))%>%
    dyOptions(fillGraph = TRUE, fillAlpha = 0.2) 

Ajaloolised andmed

Pikemas perspektiivis annab olulist infot just mitme aasta andmete võrdlus. Paraku väljastab andmeteenus hetkel hüdroloogilise seire tunniandmeid alates 01.01.2023, Varasemate andmete lisamine andmeteenusesse on pooleli, seega kasutame EstModeli veetasemete andmeid.

# ajalolised Riisa veetasemed
library(dygraphs)
dygraph(hydro_EstModel_riisa[,c("x","min","median","max")],
        main = "2019-2023 aasta Riisa hüdromeetriajaama veetasemed", 
        ylab = "m")%>%
    dyRangeSelector()%>%
    dyHighlight(highlightSeriesOpts = list(strokeWidth = 3))%>%
    dyOptions(fillGraph = TRUE, fillAlpha = 0.2) %>%
    dyRoller(rollPeriod = 7)

Lisaks on suurvesi seotud eelkõige temperatuuriga, seega saab teha 5 aasta temperatuuri andmete võrdlust. Selleks, et graafik väga loetamatuks ei muutuks on kuvatud 5 aasta miinimum, mediaan ja maksimum temperatuurid (2019-2023). Alloleva graafiku mediaani näitaja põhjal võiks arvata, et parim aeg hakata planeerima Soomaa külastust oleks märtsi lõpus. Samas tasub silma peal hoida jooksva aasta temperatuuridel, sest aastate lõikes temperatuur kõigub päris palju ja ilmaolud on muutlikud.

# ajalolised kliima andmed
library(dygraphs)
dygraph(kliima_data_PA[,c("x","min","median","max")],
        main = "2019-2023 aasta temperatuurid", 
        ylab = " kraad(c)")%>%
    dyRangeSelector()%>%
    dyHighlight(highlightSeriesOpts = list(strokeWidth = 3))%>%
    dyOptions(fillGraph = TRUE, fillAlpha = 0.2) %>%
    dyRoller(rollPeriod = 7)

Hüdroloogilised prognoosid

Keskkonnaagentuuri hüdroloogiline prognoos

Aesoo ja Riisa hüdromeetriajaamade hüdroloogilise mudelprognoosi päevaandmed annavad 10 päeva ulatuses prognoosi, mille abil valida kõige õigem hetk, millal minna Soomaale. Keskkonnaagentuuri hüdroloogiline mudelprognoos on koostatud oma ala ekspertide poolt kasutades selleks loodud mudelid. Tasub vaadata ka prognoosi koostamise kirjeldust Graafikutel on toodud Aesoo vooluhulga prognoos ja Riisa veetasemete prognoos.

# max, min, keskmine vooluhulk
library(dygraphs)
dygraph(Aesoo_prognoos[,c("paev","vooluhulga prognoos","max vooluhulk","min vooluhulk","keskmine vooluhulk")],
        main = "Aesoo hüdroloogiline mudelprognoos", 
        ylab = "vooluhulk") %>%
    dyEvent(Aesoo_prognoos[11,c("paev")], "Täna", labelLoc = "bottom") %>%
    dyRangeSelector()%>%
    dyRoller(rollPeriod = 0) %>%
    dyHighlight(highlightSeriesOpts = list(strokeWidth = 3))%>%
    dyOptions(fillGraph = TRUE, fillAlpha = 0.2)
# max min, keskmine veetase
library(dygraphs)
dygraph(Riisa_prognoos[,c("paev","veetaseme prognoos", "max veetase", "min veetase", "keskmine veetase")],
        main = "Riisa hüdroloogiline mudelprognoos", 
        ylab = "veetase") %>%
    dyEvent(Riisa_prognoos[11,c("paev")], "Täna", labelLoc = "bottom") %>%
    dyRangeSelector()%>%
    dyRoller(rollPeriod = 0) %>%
    dyHighlight(highlightSeriesOpts = list(strokeWidth = 3))%>%
    dyOptions(fillGraph = TRUE, fillAlpha = 0.2)

Keskkonnaagentuuri meteorooloogiline prognoos

Lisaks hüdroloogilisele prognoosile tasub vaadata ka Keskkonnaagentuuri meteoroloogilist asukohapõhist prognoosi. Prognoosi andmed on päritud Aesoo hüdromeetriajaama koordinaatide kohta. Ilm on kevadel heitlik, seega parima kogemuse saamiseks tasub lisaks veetasemetele arvestada sademeid, õhutemperatuuri ja tuult. Tasub vaadata ka ilmaprognooside andmestiku kirjeldust

library(dygraphs)
dygraph(kliima_4[,c("aeg","TA","PR1H","Tuul")],
        main = "Meteoroloogiline prognoos Aesmaa jaama koordinaatidel", 
        ylab = "temp(c), tuul(m/s), sademed(mm)") %>%
    dySeries("TA", label = "Temp") %>%
    dySeries("Tuul", label = "Tuul") %>%
    dyRangeSelector()%>%
    dyRoller(rollPeriod = 0) %>%
    dyHighlight(highlightSeriesOpts = list(strokeWidth = 3))%>%
    dyOptions(fillGraph = TRUE, fillAlpha = 0.2,labelsUTC = TRUE)

Teemakaart

Soomaa veevõrk ja seirejaamad

Kaardilt leiad Soomaa lähistel olevad Aesoo ja Riisa hüdromeetriajaamad ning kolm lähimat meteoroloogiajaama, koos täiendava infoga. Lisaks on taustandmeteks veevõrk (järved ja vooluveekogud) ning Soomaa kaitseala. Soomaa rahvuspargi kohta saab täiendavat infot Soomaa külastuskeskusest, mis on ühtlasi ka hea alguspunkt üleujutatud alade külastamiseks.

# Eesti koordinaatsüsteem tuleb täpsustada kuna leaflet kasutab wgs84
library(leaflet)
library(leaflet.extras)
## Teeme valmis kaardi leafletiga
# Tekitame kaardiobjekti
basemap <- leaflet(jaam,
                   width = "100%", 
                   height = "600px",
                   options = leafletOptions(
                       preferCanvas = TRUE, 
                       #worldCopyJump = F, 
                       crs = epsg3301)) %>%
    
    #addTiles(urlTemplate = "//{s}.tile.openstreetmap.org/{z}/{x}/{y}.png", group = "Taustakaart",tileOptions(opacity = 0.9)) %>%
    
    # Lisame kaardile MA aluskaardi VMS teenuse
    addWMSTiles(
        ma_alus,
        #layers = "MA-ALUS",
        layers = "MA-HALLKAART",
        group = "Taustakaart",
        options = WMSTileOptions(format = "image/png",
                                 transparent = TRUE,
                                 opacity=0.3,
                                 minZoom = 1,
                                 maxZoom = 14,
                                 continuousWorld = T)) %>%
    
    # Lisame kaardile vooluveekogude VMS teenuse
    addWMSTiles(
        eelis,
        layers = "eelis:kr_vooluvesi",
        group = "Vooluvesi",
        options = WMSTileOptions(format = "image/png",
                                 transparent = T,
                                 minZoom = 0,
                                 maxZoom = 15,
                                 continuousWorld = T)) %>%
    # Lisame kaardile järvede VMS teenuse
    addWMSTiles(
        eelis,
        layers = "eelis:kr_jarv",
        group = "Järved",
        options = WMSTileOptions(format = "image/png",
                                 transparent = T,
                                 minZoom = 0,
                                 maxZoom = 14,
                                 continuousWorld = T)) %>%
    # Lisame kaardile ramsari alade VMS teenuse
    addWMSTiles(
        eelis,
        layers = "eelis:kr_ramsar",
        group = "Kaitseala",
        options = WMSTileOptions(format = "image/png",
                                 transparent = T,
                                 minZoom = 0,
                                 maxZoom = 14,
                                 continuousWorld = T)) %>%
    
    # Lisame kaardile meteoroloogiajaamad
    addCircleMarkers(radius = 10,
                     #tekitame infoakna
                     lng = ~jaam$lon, 
                     lat = ~jaam$lat,
                     color = "green",
                     group = "Jaamad",
                     popup = paste("Jaama nimi: ", jaam$jaam_nimi, "<br>",
                                   "Jaama nimi (eng): ", jaam$jaam_nimi_eng, "<br>",
                                   "Jaama kood: ", jaam$jaam_kood, "<br>",
                                   "Jaama kõrgus merepinnast(m): ", jaam$korgus_merepinnast_m, "<br>",
                                   "Pikkuskraad: ", jaam$lon, "<br>",
                                   "Laiuskraad: ", jaam$lat, "<br>",
                                   "Jaama algusaeg: ", jaam$jaam_periood_algus, "<br>"),
                     label = ~jaam_nimi) %>%
    
    # Lisame kaardile hüdromeetriajaamad
    addCircleMarkers(radius = 10,
                     lng = ~hydro_jaam$lon, 
                     lat = ~hydro_jaam$lat,
                     color = "#FFC300",
                     group = "Jaamad",
                     #tekitame infoakna
                     popup = paste("Jaama nimi: ", hydro_jaam$jaam_nimi, "<br>",
                                   "Jaama kood: ", hydro_jaam$jaam_kood, "<br>",
                                   "Valgala nimi: ", hydro_jaam$valgala_nimi, "<br>",
                                   "Valgala suurus km2: ", hydro_jaam$valgala_suurus_km2, "<br>",
                                   "Kaugus suudmest km: ", hydro_jaam$kaugus_suudmest_km, "<br>",
                                   "Veekogu nimi: ", hydro_jaam$veekogu_nimi, "<br>",
                                   "Pikkuskraad: ", hydro_jaam$lon, "<br>",
                                   "Laiuskraad: ", hydro_jaam$lat, "<br>"),
                     label = ~hydro_jaam$jaam_nimi) %>%
    
    # Lisame kaardile Soomaa rahvuspargi külastuskeskuse
    addMarkers(#radius = 10,
               lng =  25.031412,
               lat =  58.431158,
               #color = "#FFC300",
               group = "Jaamad",
               #tekitame infoakna
               popup = paste(" ", "Soomaa rahvuspargi külastuskeskus", "<br>",
                             " ", "<b><a href='https://loodusegakoos.ee/kuhuminna/rahvuspargid/soomaa-rahvuspark/10764/'>Külastuskeskuse info</a></b>", "<br>",
                             " ", "<b><a href='https://loodusegakoos.ee/kuhuminna/rahvuspargid/soomaa-rahvuspark/1268/'>Kopraraja lisainfo</a></b>", "<br>",
                             
                             "Pikkuskraad: ", "25.031412", "<br>",
                             "Laiuskraad: ", "58.431158", "<br>"),
               label = "Soomaa rahvuspargi külastuskeskus") %>%
    
    # Jäägem eesti piiridesse seega täpsustame kaardiaknas kuvatavaid piire
    setMaxBounds(21.58448, 60.08641, 28.39045, 57.07625) %>%
    # Lisame legendi
    addLegend(
        title = "Legend",
        position = "bottomright",
        values = c(1, 2,3,4,5),
        labels = c("Vooluvesi", "Järved","meteo. jaamad","hüdro. jaamad","kaitsealad"),
        colors = c("blue", "blue","darkgreen","yellow","lightblue"))%>%
    # Lisame kihtide sisse/välja lülitamise funktsionaalsuse
    addLayersControl(
        #baseGroups = c("Taustakaart","Kaitseala"),
        overlayGroups = c("Vooluvesi","Järved","Jaamad","Kaitseala","Taustakaart"),
        options = layersControlOptions(collapsed = FALSE)) 


# vajadusel saab kaarti ka erladiseisvalt salvestada htmli
#library(plotly) ;htmlwidgets::saveWidget(as_widget(basemap), "basemap.html")
basemap

Soomaa andmelugu

Andmelugu Soomaa näitel

Eesmärk

Keskkonnaagentuuri avaandmete ja andmeteenuste kasutamine Soomaa näitel koostatud rakenduse eesmärgiks on anda ilma- ja keskkonnavaldkonna andmete kasutajatele üks andmelugu, mis oleks samal ajal ka juhendmaterjaliks ja mille koodi saaks kasutada põhjana Keskkonnaagentuuri andmemaailmas orienteeriumiseks ja avaandmete kasutamiseks. Soomaa andmelugu on mõeldud neile, kes on alles alustamas ning soovivad luua enda rakendusi-tööriistu, teha analüüse või kasutada neid andmed muudes infosüsteemides.

Et tegu ei oleks väga igava ja tehnilise juhendiga valisime näiteks ühe konkreetse teema ja huviobjekti.

Teema: Soomaa

Soomaa on üks huvitavamaid vaatamis- ja kogemisväärsusi Eestis, mis muutub aina populaarsemaks ja seda just viiendal aastaajal. Paraku ilm on keeruline nähtus, mis erineb aastate lõikes ning viies aastaaeg ei alga kindla kuupäevaga. Antud andmelugu sisaldab andmepõhist ülevaadet Soomaast, põhifookusega suurvee ajale ja eesmärgiks on anda võimalikult palju avaandmetega seotud infot ühes kohas. Soomaa külastaja või loodusretke korraldaja soovib tõenäoliselt tabada seda kõige õigemat aega külastuseks ehk kus suurvee tasemed on kõige kõrgemad.

Kellele suunatud

Andmelugu on suunatud mitmele kasutajagrupile.

  • Neile, kes lähevad soomaad avastama ja tahavad rihtida seda kõige õigemat suurvee üleujutuste aega.
  • Loodushuvilistele, kes magavad maha üleujutused, kuid lähevad muul ajal Soomaale looduse huvesid nautima.
  • Andmeteadlased, andmeanalüütikud, tudengid ja teadurid, kes soovivad andmeid väärindada ja analüüsida.
  • IT-arendajad/programmeerijad, ettevõtjad või kes vajavad andmeid üle masin-masin liidese.

Keskkonnaagentuuri andmetest tuleb järjepidevalt juurde uusi avaandmete teenuseid ja seega avaadnmete populariseerimise eesmärgiks on suurendada avaandmete kasutamist ning andmetest uue väärtuse loomist.

Andmed

Andmete kasutamise näited R-is illustreerib protsessi, mida tuleb läbida, et andmeid saaks kasutada või väärindada teiste osapoolte poolt. Takistuseks võib olla andmetest arusaamine ja õigete andmeallikate “otsade” leidmine. Andmelugu koos vastava koodiga on loodud selle probleemi lahendamiseks. Andmetest arusaamine võib olla valdkonna välisetele kasutajatele keeruline ja seetõttu oleme antud näite puhul lisanud ohtral linke ja juhismaterjale koodi, et järgmised andmete kasutajad saaksid üles leida vajaliku info ning teaksid kuidas on üles ehitatud meie andmekataloog, sh andmestike/levituse info, andmekirjeldused ja andmeteenused. Kasutatud on erinevaid andmeid erinevatest allikatest, peamiselt andmeteenustena, sealhulgas ruumiandmeteenuseid,

Andmelugu sisaldab järgmisi andmeid:

  • Hüdroloogiline seire
  • Hüdroloogiline mudelprognoos
  • Meteoroloogiline seire
  • Meteoroloogiline asukohapõhine prognoos
  • Seirejaamad
  • Ramsari alad
  • Vooluveekogud
  • Järved
  • Maa-ameti aluskaart (halltoonid)

Soomaa suurvee andmeloo jaoks valiti välja kaks olulisemat hüdromeetriajaama ja kolm lähimat meteoroloogiajaama (vaata kaarti). Lisaks saab lugeda soomaa rahvuspargi ja loodusala kohta ka keskkonnaportaalist ning vaadata seotud objekte ja muud keskkonnainfot.

Andmetöötlus ja skriptid

Koodi kirjutamine ei peaks olema iga kord nullist alustamine, vaid võiks olla hea praktika kohaselt taaskasutamine.Andmeloos on kasutatud erinevat tüüpi andmeid ja iga andmestik on oma spetsiifilises formaadis (nt kuupäevade formaat) siis selle andmeloo koodi taaskasutamise tulemusena saab järgmine andmete ja koodi kasutaja hoida kokku aeg ja närve andmetöötluse osas. Andmeloo mõte on anda põhiinfo andmete kasutamiseks, seega on kood võimalikult puhas ja lihtne ning minimaalselt on kasutatud R-i spetsiifilist süntaksit. R on küllaltki lihtne programmeerimiskeel, mis sobib andmeteaduseks, andmeanalüüsiks ja kiirelt valmivate lahenduste loomiseks või prototüüpimiseks. Sel põhjusel on ka see kood üsna arusaadav ja kasutatav või ülevõetav teistes programmeerimiskeeltes ja keskkondades. Kood on ära toodud andmeloo skriptide sektsioonis ning selle kasutamisel tuleks vaadata ka juhiseid.

Andmete võrdlus ja prognoos

Koodi loetavuse ja arusaadavuse tagamiseks on kasutatud lihtsaid näiteid andmete võrdluseks ja kasutatud peamiselt olemasolevaid prognoosandmeid. Keda huvitab vooluhulkade ja tasemete prognoos Soomaa külastamisel, võiks kindlasti vaadata Keskkonnaagentuuri hüdroloogilist ja meteoroloogilist mudelprognoosi. Lisatud on mõned andmevõrdlused, et näidata nende andmete analüüsi ja väärindamise võimalusi ning anda andmeloo kasutajale võimalus teha ise järeldusi. Andmete kasutamise näidised on olemas ja igaüks saab andmeid edasi analüüsida ja luua endale sobilike prognoosmudeleid ning täiendada selle andmeloo skripte.

Kontakt

Keskkonnaagentuur

Mustamäe tee 33, 10616 Tallinn

+372 666 0901

Juhis

Kuidas kasutada skripte

Siit sektsioonist leiad info kuidas taaskasutada selle andmeloo loomiseks kasutatud koodi.

Andmed on seisuga 04.04.2024 ja ei uuene automaatselt. Seega tuleb andmeid uuendada, et saada ajakohased graafikud

Kood koosneb 2 failist (soomaa.Rmd, Andmed.R)

Faili soomaa.Rmd saab alla laadida kui vajutada päises oleval nupul Code ja valida Download Rmd või siit: soomaa.Rmd

Faili Andmed.R koodi saab kopeerida järgmiselt menüüsakilt Andmed.R või alla laadida siit: Andmed.R

Fail soomaa.Rmd sisaldab ainult graafikute loomiseks vajaliku koodi, kuid mitte andmete sisselugemise ja töötluse koodiosa, sest siis läheks kood väga pikaks ja poleks tagatud loetavus. Fail Andmed.R sisaldab ka graafikute loomise koodi baastasemel, et oleks näha tulemused (graafikud,kaart) ka neil, kes faili soomaa.Rmd ei kasuta.

Juhis andmeloo taasloomiseks:

  1. Tekita skript “Andmed.R”
  2. Lisa allolev kood (“Andmed.R” sektsioonist) enda faili “Andmed.R”
  3. Installeeri vajalikud teegid (library), R-studio pakub seda võimalust skripti päises automaatselt
  4. Jooksuta Andmed.R skripti
  5. Tõmba alla fail nimega soomaa.Rmd
  6. Vajuta soomaa.Rmd päises “run all chunks below”
  7. Peale koodi jooksutamist tuleb luua väljund kasutades konsoolis käsklust:rmarkdown::render(“soomaa.Rmd”)
rmarkdown::render("soomaa.Rmd")

Andmed.R

Koodi nägemiseks Vajuta paremal pool oleval nuppul “show”

###############################
#### Andmetöötluse skript 
# Sisaldab avaandmete andmeteenuste kasutamise näiteid ning viiteid andmete kirjeldustele ja keskkondadele 
# Lisaks peamisi andmetöötluse tegevusi, andmete võrdlusi, graafikute loomist ja kaartide tegemise näiteid
###############################
### Hüdroloogilise seire andmed
## Loeme sisse hüdroloogilise seire andmed (https://keskkonnaportaal.ee/et/avaandmed/keskkonna-ja-ilma-valdkonna-andmeteenused)
# Üldine päring andmetele, et näha mis seal sees on ja kuna päringumaht on piiratud siis filtritega (limiit 20000 rida)
library(jsonlite)
hydro_data <- fromJSON("https://keskkonnaandmed.envir.ee/f_hydroseire?timeline_ts_utc=lt.2023-01-02T03:00:00&timeline_ts_utc=gt.2023-01-01T23:00:00&jaam_kood=eq.41137")

# Meid huvitab aint teatud osa andmestikust, seega vaatame mida saaks välja rookida
names(hydro_data)

# Andmekirjeldusest põhjal võiks meid huvitada tunniandmetest veetase(cm) ja tunni äravool(m3/s)
#https://keskkonnaportaal.ee/et/avaandmed/hudroloogilise-seire-andmestik/hudroloogilise-seire-andmestiku-kirjeldus

# Vaatame, mis parameetrid meil andmetes tegelikult on
unique(hydro_data$aegrida_nimi)

# Võtame ainult meid huvitava valiku aga on vaja on kodeerida õigesti andmepäring (https://www.w3schools.com/tags/ref_urlencode.ASP) 
hydro_data <- fromJSON("https://keskkonnaandmed.envir.ee/f_hydroseire?timeline_ts_utc=gt.2023-09-01T23:00:00&aegrida_nimi=in.(WL%20min,WL%20max,%C3%84ravool+avg)&jaam_kood=eq.41137")

# Meil valitud ainult Aesoo hüdromeetriajaam, seega pole vaja jaamade üldandmeid
hydro_data=hydro_data[,c("timeline_ts_utc", "aegrida_nimi","vaartus" )]

# Paneme andmed kõrvuti ühte tabelisse, et saaks graafiku teha
library(tidyr)
hydro_data_1=spread(hydro_data, key = aegrida_nimi, value = vaartus)

# Kontrollime üle, kas on kõik unikaalne
sum(duplicated(hydro_data_1$timeline_ts_utc))

# Kuupäev on erilises vormis ja tuleb vaeva näha, et saaks neist datetime teha mida vajab graafik 
hydro_data_1$timeline_ts_utc= gsub("T"," ",hydro_data_1$timeline_ts_utc)
hydro_data_1$timeline_ts_utc= as.POSIXlt(hydro_data_1$timeline_ts_utc, format='%Y-%m-%d %H:%M:%S',tz = "UTC")

## Teeme graafikud
# Äravool
library(dygraphs)
dygraph(hydro_data_1[,c("timeline_ts_utc","Äravool avg"),],
        main = "Äravool keskmine", 
        ylab = "Tunni keskmine äravool, m3/s") %>%
    dyOptions(fillGraph = TRUE, fillAlpha = 0.4)
# Graafiku järgi on andmetes 16ndal ja 17ndal auk sees

# Veetase
library(dygraphs)
dygraph(hydro_data_1[,c("timeline_ts_utc","WL max","WL min"),],
        main = "Tunni max ja min veetase", 
        ylab = "veetase, cm") %>%
    dyOptions(fillGraph = TRUE, fillAlpha = 0.4)


###############################
### Kliima andmed
## Loeme sisse kliima andmed (https://keskkonnaportaal.ee/et/avaandmed/keskkonna-ja-ilma-valdkonna-andmeteenused)
# Üldine päring andmetele, et näha mis seal sees on ja kuna päringumaht on piiratud siis filtritega (limiit 20000 rida)
library(jsonlite)
kliima_data <- fromJSON("https://keskkonnaandmed.envir.ee/f_kliima_tund?aasta=eq.2023&kuu=gt.10&paev=lt.8&jaam_kood=in.(AJVILJ01,AJPARN01,AJTURI01)")

# Meid huvitab aint teatud osa andmestikust, seega vaatame mida saaks välja rookida
names(kliima_data)

# Andmekirjelduse ütleb meile, et meid võiks huvitada tunniandmetes täistunni õhutemperatuur ning sademete summa
#https://keskkonnaportaal.ee/et/avaandmed/kliimaandmestik/kliimaandmestiku-kirjeldus

# Vaatame, mis parameetrid meil andmetes tegelikult on
unique(kliima_data$element_kood)

# Võtame ainult meid huvitava valiku ja teeme jaamapõhised päringud
# Kuna päringu limiit on 20000 rida siis peame päringud tükeldama näitajate ja jaamade lõikes

# Türi meteoroloogiajaam
kliima_data_1 <- fromJSON("https://keskkonnaandmed.envir.ee/f_kliima_tund?aasta=in.(2023,2024)&jaam_kood=eq.AJTURI01&element_kood=eq.TA")
kliima_data_2 <- fromJSON("https://keskkonnaandmed.envir.ee/f_kliima_tund?aasta=in.(2023,2024)&jaam_kood=eq.AJTURI01&element_kood=eq.PR1H")
# Liidame andmed kokku ja roogime välja mittevajalikud väljad
kliima_data_t=merge(
    kliima_data_1[,c("aasta","kuu","paev","tund","vaartus")], 
    kliima_data_2[,c("aasta","kuu","paev","tund","vaartus")], 
    by=c("aasta","kuu","paev","tund"),all=T,suffixes = c("TA","PR1H"))
names(kliima_data_t) = c("aasta","kuu","paev","tund","TA","PR1H")

# Pärnu rannikujaam
kliima_data_1 <- fromJSON("https://keskkonnaandmed.envir.ee/f_kliima_tund?aasta=in.(2023,2024)&jaam_kood=eq.AJPARN01&element_kood=eq.TA")
kliima_data_2 <- fromJSON("https://keskkonnaandmed.envir.ee/f_kliima_tund?aasta=in.(2023,2024)&jaam_kood=eq.AJPARN01&element_kood=eq.PR1H")
# Liidame andmed kokku ja roogime välja mittevajalikud väljad
kliima_data_p=merge(
    kliima_data_1[,c("aasta","kuu","paev","tund","vaartus")], 
    kliima_data_2[,c("aasta","kuu","paev","tund","vaartus")], 
    by=c("aasta","kuu","paev","tund"),all=T,suffixes = c("TA","PR1H"))
names(kliima_data_p) = c("aasta","kuu","paev","tund","TA","PR1H")

# Viljandi meteoroloogiajaam
kliima_data_1 <- fromJSON("https://keskkonnaandmed.envir.ee/f_kliima_tund?aasta=in.(2023,2024)&jaam_kood=eq.AJVILJ01&element_kood=eq.TA")
kliima_data_2 <- fromJSON("https://keskkonnaandmed.envir.ee/f_kliima_tund?aasta=in.(2023,2024)&jaam_kood=eq.AJVILJ01&element_kood=eq.PR1H")
# Liidame andmed kokku ja roogime välja mittevajalikud väljad
kliima_data_v=merge(
    kliima_data_1[,c("aasta","kuu","paev","tund","vaartus")], 
    kliima_data_2[,c("aasta","kuu","paev","tund","vaartus")], 
    by=c("aasta","kuu","paev","tund"),all=T,suffixes = c("TA","PR1H"))
names(kliima_data_v) = c("aasta","kuu","paev","tund","TA","PR1H")

# Puhastame töölauda
rm(kliima_data_1,kliima_data_2)

# Normaliseerime ajalise mõõtme ja viime selle datetime formaati, et saaks graafikuid teha
kliima_data_t$timeline_ts_utc= paste0(kliima_data_t$aasta,"-",kliima_data_t$kuu,"-",kliima_data_t$paev," ",kliima_data_t$tund,":00:00")
kliima_data_p$timeline_ts_utc= paste0(kliima_data_p$aasta,"-",kliima_data_p$kuu,"-",kliima_data_p$paev," ",kliima_data_p$tund,":00:00")
kliima_data_v$timeline_ts_utc= paste0(kliima_data_v$aasta,"-",kliima_data_v$kuu,"-",kliima_data_v$paev," ",kliima_data_v$tund,":00:00")

# Kuvame andmed et näha mis toimub graafikul
kliima_data_t$timeline_ts_utc= as.POSIXlt(kliima_data_t$timeline_ts_utc, format='%Y-%m-%d %H:%M:%S',tz = "UTC")
kliima_data_p$timeline_ts_utc= as.POSIXlt(kliima_data_p$timeline_ts_utc, format='%Y-%m-%d %H:%M:%S',tz = "UTC")
kliima_data_v$timeline_ts_utc= as.POSIXlt(kliima_data_v$timeline_ts_utc, format='%Y-%m-%d %H:%M:%S',tz = "UTC")

## Teeme graafikud
# Kuna temperatuur ja sademed on hästi võrreldavad erinevate asukohatde lõikes siis paneme jaamade andmed kokku näitaja alusel

# õhutemp täistunnil
kliima_data_TA =merge(kliima_data_t[,c("timeline_ts_utc","TA")],kliima_data_p[,c("timeline_ts_utc","TA")],by="timeline_ts_utc")
kliima_data_TA =merge(kliima_data_TA,kliima_data_v[,c("timeline_ts_utc","TA")],by="timeline_ts_utc")
names(kliima_data_TA)=c("timeline_ts_utc","Türi","Pärnu","Viljandi")
library(dygraphs)
dygraph(kliima_data_TA) %>%
    dyOptions(fillGraph = TRUE, fillAlpha = 0.2)

# Ühe tunni sademete summa
kliima_data_PR1H =merge(kliima_data_t[,c("timeline_ts_utc","PR1H")],kliima_data_p[,c("timeline_ts_utc","PR1H")],by="timeline_ts_utc")
kliima_data_PR1H =merge(kliima_data_PR1H,kliima_data_v[,c("timeline_ts_utc","PR1H")],by="timeline_ts_utc")
names(kliima_data_PR1H)=c("timeline_ts_utc","Türi","Pärnu","Viljandi")
library(dygraphs)
dygraph(kliima_data_PR1H)


###############################
### Andmete võrdlus
## Paneme hüdroloogilised ja meteoroloogilised andmed kokku võrdluse jaoks
kliima_koos= merge(kliima_data_TA,kliima_data_PR1H,by="timeline_ts_utc",suffixes = c(".TA",".PR1H"))
kliima_koos= merge(kliima_koos,hydro_data_1,by="timeline_ts_utc")
# POSIXlt tuleb muuta POSIXct formaati
kliima_koos$timeline_ts_utc= as.POSIXct(kliima_koos$timeline_ts_utc)
# Eemaldame hüdroloogilistes andmetes oleva augu
kliima_koos= kliima_koos[complete.cases(kliima_koos),]
## korrelatsioon
tulemus=cor(kliima_koos[,-1])

# Teeme korrelatsiooni graafiku et näha andmete erinevusi
library(plotly)
plot_ly(x=colnames(tulemus), 
        y=rownames(tulemus),
        z = tulemus, 
        type = "heatmap",
        zauto = F, zmin = 0, zmax = 1,
        colors = colorRamp(c("red", "green"))) %>%
    layout(margin = list(l=120))

# Andmed on kohati suhteliselt võrreldamatud, sest on erineva skaalaga ja tuleks normaliseerida

## Normaliseerime andmed kasutame scale() ja rollmean funktsioone loetava graafiku saamiseks
library(zoo)
x1=scale(kliima_koos[,c(8,9,10)])
x1=cbind(kliima_koos[,"timeline_ts_utc"],as.data.frame(x1))
x2=rollmean(scale(rowMeans(kliima_koos[,c(2,3,4)])),30,fill = 0,align ="right" )
x2=cbind(kliima_koos[,"timeline_ts_utc"],as.data.frame(x2))
names(x2)=c("kliima_koos[, \"timeline_ts_utc\"]","TA")
tulemus= merge(x1,x2,by="kliima_koos[, \"timeline_ts_utc\"]")

# Teeme normaliseeritud andmetega graafiku
library(dygraphs)
dygraph(tulemus,
        main = "Normaliseeritud andmed", 
        ylab = "Normaliseeritud väärtus")%>%
    dyRangeSelector()%>%
    dyRoller(rollPeriod = 0)%>%
    dyOptions(fillGraph = TRUE, fillAlpha = 0.2)


### Võrdleme veetasemete andmeid 5 aasta lõikes
## Hüdro andmed EstModelist
library(jsonlite)
# H-veetase, Q-vooluhulk, T-veetemperatuur
hydro_EstModel_riisa <- fromJSON("https://estmodel.envir.ee/stations/SJA4385000/statistics?parameter=H&start-year=2019&time-step=P1D") # Riisa
hydro_EstModel_riisa$timeline_ts_utc= as.POSIXlt(hydro_EstModel_riisa$startDate, format='%Y-%m-%d',tz = "UTC")
hydro_EstModel_riisa=hydro_EstModel_riisa[,c("timeline_ts_utc", "meanValue")]

# Loome aasta, kuu ja päeva erladi et saaks luua võrdlusi 
library(lubridate)
hydro_EstModel_riisa$aasta= year(hydro_EstModel_riisa$timeline_ts_utc)
hydro_EstModel_riisa$kuu= month(hydro_EstModel_riisa$timeline_ts_utc)
hydro_EstModel_riisa$paev= day(hydro_EstModel_riisa$timeline_ts_utc)

# Normaliseerime ajalise mõõtme 
hydro_EstModel_riisa$timeline_ts_utc= paste0(hydro_EstModel_riisa$kuu,"-",hydro_EstModel_riisa$paev)

# Viskame välja üleliigsed väljad aga jätame sisse kuu ja päeva, et järjekord sassi ei läheks
hydro_EstModel_riisa=hydro_EstModel_riisa[,c("aasta","kuu","paev","timeline_ts_utc","meanValue")]

# Paneme andmed kõrvuti ühte tabelisse, et saaks graafiku teha
library(tidyr)
hydro_EstModel_riisa=spread(hydro_EstModel_riisa, key = aasta, value = meanValue)

# Eemaldame kuu ja päeva
hydro_EstModel_riisa=hydro_EstModel_riisa[,c(3:ncol(hydro_EstModel_riisa))]

#kliima_data_PA$timeline_ts_utc= as.POSIXlt(kliima_data_PA$timeline_ts_utc, format='%m-%d',tz = "UTC")
# Et graafik oleks puhas ja arusaadav arvutame min,max ja keskmise väärtuse
hydro_EstModel_riisa$median = apply(hydro_EstModel_riisa[,c(2:ncol(hydro_EstModel_riisa))], 1, median, na.rm=F)
hydro_EstModel_riisa$min = apply(hydro_EstModel_riisa[,c(2:ncol(hydro_EstModel_riisa))], 1, min, na.rm=F)
hydro_EstModel_riisa$max = apply(hydro_EstModel_riisa[,c(2:ncol(hydro_EstModel_riisa))], 1, max, na.rm=F)

# lisame x päeva numbriliselt, et dygraph oskaks teha õige graafiku aastate lõikes
hydro_EstModel_riisa$x =c(1:nrow(hydro_EstModel_riisa))
# ja teeme kuupäevad
library(lubridate)
hydro_EstModel_riisa$x = parse_date_time(x = hydro_EstModel_riisa$x, orders = "j")
hydro_EstModel_riisa=as.data.frame(hydro_EstModel_riisa)

## Teeme graafikud
library(dygraphs)
dygraph(hydro_EstModel_riisa[,c("x","min","median","max")])%>%
    dyRangeSelector()%>%
    dyOptions(fillGraph = TRUE, fillAlpha = 0.2) %>%
    
    dyRoller(rollPeriod = 10)


### Võrdleme temperatuuri andmeid 5 aasta lõikes
# Loeme sisse 5 aasta  temperatuuri päevaandmed
library(jsonlite)
kliima_data_PA <- fromJSON("https://keskkonnaandmed.envir.ee/f_kliima_paev?jaam_kood=eq.AJTURI01&element_kood=in.(DTA08)&aasta=in.(2019,2020,2021,2022,2023)") #türi

# Normaliseerime ajalise mõõtme 
kliima_data_PA$timeline_ts_utc= paste0(kliima_data_PA$kuu,"-",kliima_data_PA$paev)

# Viskame välja üleliigsed väljad aga jätame sisse kuu ja päeva, et järjekord sassi ei läheks
kliima_data_PA=kliima_data_PA[,c("aasta","kuu","paev","timeline_ts_utc","vaartus")]

# Paneme andmed kõrvuti ühte tabelisse, et saaks graafiku teha
library(tidyr)
kliima_data_PA=spread(kliima_data_PA, key = aasta, value = vaartus)

# Eemaldame kuu ja päeva
kliima_data_PA=kliima_data_PA[,c(3:8)]

#kliima_data_PA$timeline_ts_utc= as.POSIXlt(kliima_data_PA$timeline_ts_utc, format='%m-%d',tz = "UTC")
# Et graafik oleks puhas ja arusaadav arvutame min,max ja keskmise väärtuse
kliima_data_PA$median = apply(kliima_data_PA[,c(2:6)], 1, median, na.rm=F)
kliima_data_PA$min = apply(kliima_data_PA[,c(2:6)], 1, min, na.rm=F)
kliima_data_PA$max = apply(kliima_data_PA[,c(2:6)], 1, max, na.rm=F)

# lisame x päeva numbriliselt, et dygraph oskaks teha õige graafiku aastate lõikes
kliima_data_PA$x =c(1:nrow(kliima_data_PA))
# ja teeme kuupäevad
library(lubridate)
kliima_data_PA$x = parse_date_time(x = kliima_data_PA$x, orders = "j")
kliima_data_PA=as.data.frame(kliima_data_PA)

## Teeme graafikud
library(dygraphs)
dygraph(kliima_data_PA[,c("x","min","median","max")])%>%
    dyRangeSelector()%>%
    dyOptions(fillGraph = TRUE, fillAlpha = 0.2) %>%
    dyRoller(rollPeriod = 10)

###############################
### Hüdroloogiline mudelprognoos
# https://keskkonnaportaal.ee/et/avaandmed/hudroloogiline-mudelprognoos
# Andmed asuvad siin: https://avaandmed.keskkonnaportaal.ee/dhs/Active/documentList.aspx?ViewId=919192b7-3e4e-4694-a3f7-7b856da7aeac
# ID muutuvad, seega tuleb vaada järgi mis on ajakohase faili ID: https://avaandmed.keskkonnaportaal.ee/swagger/index.html
## Loeme sisse Aesoo vooluhulga ja Riisa veetasemete andmed
library(readr)
# Loeme sisse Aesoo vooluhulga andmed
Aesoo_prognoos <- read_table("https://avaandmed.keskkonnaportaal.ee/_vti_bin/RmApi.svc/active/items/1337361/files/1", col_names = FALSE)
# Loeme sisse Riisa veetasemete andmed
Riisa_prognoos <- read_table("https://avaandmed.keskkonnaportaal.ee/_vti_bin/RmApi.svc/active/items/488068/files/1", col_names = FALSE)
# Loeme sisse Riisa vooluhulga andmed aga kuna saame errorit siis jätame välja esialgu
#Riisa_prognoos_vooluhulk <- read_table("https://avaandmed.keskkonnaportaal.ee/_vti_bin/RmApi.svc/active/items/488066/files/1", col_names = FALSE)

# Andmetel pole pealkirju ja need saame siit: https://keskkonnaportaal.ee/et/avaandmed/hudroloogilise-prognoosi-andmestik/hudroloogilise-prognoosi-kirjeldus
names(Aesoo_prognoos) =c("aeg","vooluhulga prognoos","max vooluhulk","min vooluhulk","keskmine vooluhulk","test")
names(Riisa_prognoos) =c("aeg","veetaseme prognoos","max veetase","min veetase","keskmine veetase")

# Kuna andmetes on kuupäevad erilises formaadis (aasta + numbriline päeva arv(julian day)) siis eemaldame aasta 
Aesoo_prognoos$paev = as.numeric(sub("^....", "", Aesoo_prognoos$aeg))
Riisa_prognoos$paev = as.numeric(sub("^....", "", Riisa_prognoos$aeg))

# Ja teeme numbri kuupäevaks
library(lubridate)
Aesoo_prognoos$paev=parse_date_time(x = Aesoo_prognoos$paev, orders = "j")
Riisa_prognoos$paev=parse_date_time(x = Riisa_prognoos$paev, orders = "j")
# viime tagasi data.frame formaati
Aesoo_prognoos=as.data.frame(Aesoo_prognoos)
Riisa_prognoos=as.data.frame(Riisa_prognoos)

## Teeme graafikud
# Aesoo vooluhulk
library(dygraphs)
dygraph(Aesoo_prognoos[,c("paev","vooluhulga prognoos","max vooluhulk","min vooluhulk","keskmine vooluhulk")]) %>%
    dyEvent(Aesoo_prognoos[11,c("paev")], "Täna", labelLoc = "bottom") %>%
    dyOptions(fillGraph = TRUE, fillAlpha = 0.2)
# Riisa veetasemed
library(dygraphs)
dygraph(Riisa_prognoos[,c("paev","veetaseme prognoos", "max veetase", "min veetase", "keskmine veetase")]) %>%
    dyEvent(Riisa_prognoos[11,c("paev")], "Täna", labelLoc = "bottom") %>%
    dyOptions(fillGraph = TRUE, fillAlpha = 0.2)
# kirjelduses on kirjas, et täna on 11 rida aga kuupäev ei klapi. Ilmselt on KP läinud nihkesse (29.02) 

###############################
### Ilmaprognoosid 
## 4 päeva ilmaprognoos Aesoo kohta
# Andmeteenuse info: https://ilmmicroservice.envir.ee/api_doc/#api-Forecasts-GetV1ForecastsModelforecastbylocation
# Loeme sisse Aesoo hüdromeetriajaama ilmaprognoosi andmed ja paneme andmed dataframei
url4= "https://publicapi.envir.ee/v1/forecasts/modelForecastByLocation?latitude=25.061826&longitude=58.515303&outputFormat=application%2Fjson"
kliima_4 <- fromJSON(url4)
kliima_4 =kliima_4$entries$entry
# Väärtused on eraldatud komaga ja ühes tulbas seega lammutame selle erladi tulpadeks
kliima_4 = do.call("rbind", strsplit(kliima_4$vaartus, ","))
kliima_4 = data.frame(apply(kliima_4, 2, as.numeric))

# Ümardame numbrilised andmed
library(dplyr); kliima_4=kliima_4 %>% mutate_if(is.numeric, round, digits=1)
# Kuna andmed ei ole kirjeldatud siis katseeksitus meetodi tulemused
# Esimene väärtus on x13
# Temp on 1 rida, sademed on 6 rida, tuul on 15 rida, õhurõhk on 10 rida
kliima_4 = kliima_4[c(1,6,15,10),c(13:50)]
kliima_4 = as.data.frame(t(kliima_4))

# Kuna aega andmetes ei ole siis arvutame selle positsioonilt x13 ehk kliima_4 algusest
aeg=trunc(Sys.time(),units= "hours")
for (i in 1:nrow(kliima_4)-1) {aeg[i+1]= aeg + hours(i)}
# Lisame ajavektori andmetele
kliima_4$aeg=aeg
# Anname arusaadavad nimed tulpadele
colnames(kliima_4) = c("TA","PR1H","Tuul","Õhurõhk","aeg")

## Teeme graafiku
library(dygraphs)
dygraph(kliima_4[,c("aeg","TA","PR1H","Tuul")],
        main = "Meteoroloogiline prognoos Aesmaa jaama koordinaatidel", 
        ylab = "temp(c), tuul(m/s), sademed(mm)") %>%
    dySeries("TA", label = "temp") %>%
    dySeries("Tuul", label = "Tuul") %>%
    dyRangeSelector()%>%
    dyRoller(rollPeriod = 0) %>%
    dyOptions(fillGraph = TRUE, fillAlpha = 0.2,labelsUTC = TRUE)


## Hetke data koordinaadi põhiselt
url_p=("https://ilmmicroservice.envir.ee/api/forecasts/mobileLocationForecast?latitude=58.515303&longitude=25.061826&stationId=54")
kliima_p <- fromJSON(url_p)
kliima_p =kliima_p$entries$entry
kliima_p=t(kliima_p)
# Millegipärast tulevad andmed Kuusiku jaamast?

###############################
### Teemakaart
## Tekitame jaamade üldandmed
# Kõigepealt Aesoo hüdroloogilise jaam andmed
library(dplyr)
hydro_jaam <- fromJSON("https://keskkonnaandmed.envir.ee/f_hydroseire?timeline_ts_utc=lt.2024-01-02T03:00:00&timeline_ts_utc=gt.2024-01-01T23:00:00&jaam_kood=in.(41137,41140)")

# Andmetes on kaks jaama seega vajame unikaalseid jaama andmeid
hydro_jaam = hydro_jaam[,c("jaam_kood","jaam_nimi","valgala_nimi","valgala_suurus_km2","kaugus_suudmest_km",
                           "jaam_laiuskraad","jaam_pikkuskraad","jaam_taisnimi","veekogu_nimi")]
hydro_jaam = distinct(hydro_jaam)

# Anname veel leafletile asusaadavad koordinaatide nimed (lat,lon)
names(hydro_jaam) = c("jaam_kood","jaam_nimi","valgala_nimi","valgala_suurus_km2","kaugus_suudmest_km",
                      "lat","lon","jaam_taisnimi","veekogu_nimi")

# Siis Türi, Pärnu ja Viljandi meteoroloogiajaamade andmed, mis on eraldi päringuga saadaval
jaam <- fromJSON("https://keskkonnaandmed.envir.ee/f_kliima_jaam_vaatlus?jaam_kood=in.(AJVILJ01,AJPARN01,AJTURI01)")

# Andmetes on kolm jaama seega valime ainult jaamade üldandmed ja seejärel jätame unikaalsed kirjed
jaam = jaam[,c("jaam_kood","jaam_nimi","jaam_nimi_eng","jaam_periood_algus",   
               "jaam_periood_lopp","pikkuskraad","laiuskraad","korgus_merepinnast_m")]
jaam = distinct(jaam)
# Andmetes on 3 pärnu meteoroloogiajaama ja mul on vaja ainult viimast
jaam =jaam[1:3,]
# Anname veel leafletile asusaadavad koordinaatide nimed (lat,lon)
names(jaam) = c("jaam_kood","jaam_nimi","jaam_nimi_eng","jaam_periood_algus",   
                "jaam_periood_lopp","lon","lat","korgus_merepinnast_m")


## Lisames muud taustandmed mida on vaja kaardi tegemiseks
# https://register.keskkonnaportaal.ee/register/internationally-important-area/8957851

# Urlid mida kasutada WMS teenuste puhul
ma_alus <- "https://kaart.maaamet.ee/wms/hallkaart"
eelis <- "https://gsavalik.envir.ee/geoserver/eelis/ows"

# Peaks saama ka otse geojsonit kasutada aga ei õnnestunud toimima saada
# geojson <- jsonlite::fromJSON("https://gsavalik.envir.ee/geoserver/eelis/ows?service=WFS&version=1.0.0&request=GetFeature&typeName=eelis%3Akr_jarv&maxFeatures=50&outputFormat=application%2Fjson")

# Eesti koordinaatsüsteem tuleb täpsustada kuna leaflet kasutab wgs84
library(leaflet)
library(leaflet.extras)
epsg3301 <- leafletCRS(crsClass = "L.Proj.CRS", 
                       code = "EPSG:3301",
                       #proj4def = "+proj=lcc +lat_1=59.33333333333334 +lat_2=58 +lat_0=57.51755393055556 +lon_0=24 +x_0=500000 +y_0=6375000 +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs",
                       proj4def = "+proj=lcc +lat_0=57.5175539305556 +lon_0=24 +lat_1=59.3333333333333 +lat_2=58 +x_0=500000 +y_0=6375000 +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs +type=crs",
                       resolutions = c(2048, 1024, 512, 256, 128, 64, 32, 16, 8, 4, 2, 1, 0.5), # 8192 down to 0.5
                       origin = c(0, 0))

## Teeme valmis kaardi leafletiga
# Tekitame kaardiobjekti
basemap <- leaflet(jaam,
                   width = "100%", 
                   height = "600px",
                   options = leafletOptions(
                       preferCanvas = TRUE, 
                       #worldCopyJump = F, 
                       crs = epsg3301)) %>%
    
    #addTiles(urlTemplate = "//{s}.tile.openstreetmap.org/{z}/{x}/{y}.png", group = "Taustakaart",tileOptions(opacity = 0.9)) %>%
    
    # Lisame kaardile MA aluskaardi VMS teenuse
    addWMSTiles(
        ma_alus,
        #layers = "MA-ALUS",
        layers = "MA-HALLKAART",
        group = "Taustakaart",
        options = WMSTileOptions(format = "image/png",
                                 transparent = TRUE,
                                 opacity=0.3,
                                 minZoom = 1,
                                 maxZoom = 14,
                                 continuousWorld = T)) %>%
    
    # Lisame kaardile vooluveekogude VMS teenuse
    addWMSTiles(
        eelis,
        layers = "eelis:kr_vooluvesi",
        group = "Vooluvesi",
        options = WMSTileOptions(format = "image/png",
                                 transparent = T,
                                 minZoom = 0,
                                 maxZoom = 15,
                                 continuousWorld = T)) %>%
    # Lisame kaardile järvede VMS teenuse
    addWMSTiles(
        eelis,
        layers = "eelis:kr_jarv",
        group = "Järved",
        options = WMSTileOptions(format = "image/png",
                                 transparent = T,
                                 minZoom = 0,
                                 maxZoom = 14,
                                 continuousWorld = T)) %>%
    # Lisame kaardile ramsari alade VMS teenuse
    addWMSTiles(
        eelis,
        layers = "eelis:kr_ramsar",
        group = "Kaitseala",
        options = WMSTileOptions(format = "image/png",
                                 transparent = T,
                                 minZoom = 0,
                                 maxZoom = 14,
                                 continuousWorld = T)) %>%
    
    # Lisame kaardile meteoroloogiajaamad
    addCircleMarkers(radius = 10,
                     #tekitame infoakna
                     lng = ~jaam$lon, 
                     lat = ~jaam$lat,
                     color = "green",
                     group = "Jaamad",
                     popup = paste("Jaama nimi: ", jaam$jaam_nimi, "<br>",
                                   "Jaama nimi (eng): ", jaam$jaam_nimi_eng, "<br>",
                                   "Jaama kood: ", jaam$jaam_kood, "<br>",
                                   "Jaama kõrgus merepinnast(m): ", jaam$korgus_merepinnast_m, "<br>",
                                   "Pikkuskraad: ", jaam$lon, "<br>",
                                   "Laiuskraad: ", jaam$lat, "<br>",
                                   "Jaama algusaeg: ", jaam$jaam_periood_algus, "<br>"),
                     label = ~jaam_nimi) %>%
    
    # Lisame kaardile hüdromeetriajaamad
    addCircleMarkers(radius = 10,
                     lng = ~hydro_jaam$lon, 
                     lat = ~hydro_jaam$lat,
                     color = "#FFC300",
                     group = "Jaamad",
                     #tekitame infoakna
                     popup = paste("Jaama nimi: ", hydro_jaam$jaam_nimi, "<br>",
                                   "Jaama kood: ", hydro_jaam$jaam_kood, "<br>",
                                   "Valgala nimi: ", hydro_jaam$valgala_nimi, "<br>",
                                   "Valgala suurus km2: ", hydro_jaam$valgala_suurus_km2, "<br>",
                                   "Kaugus suudmest km: ", hydro_jaam$kaugus_suudmest_km, "<br>",
                                   "Veekogu nimi: ", hydro_jaam$veekogu_nimi, "<br>",
                                   "Pikkuskraad: ", hydro_jaam$lon, "<br>",
                                   "Laiuskraad: ", hydro_jaam$lat, "<br>"),
                     label = ~hydro_jaam$jaam_nimi) %>%
    
    # Lisame kaardile Soomaa rahvuspargi külastuskeskuse
    addMarkers(#radius = 10,
               lng =  25.031412,
               lat =  58.431158,
               #color = "#FFC300",
               group = "Jaamad",
               #tekitame infoakna
               popup = paste(" ", "Soomaa rahvuspargi külastuskeskus", "<br>",
                             " ", "<b><a href='https://loodusegakoos.ee/kuhuminna/rahvuspargid/soomaa-rahvuspark/10764/'>Külastuskeskuse info</a></b>", "<br>",
                             " ", "<b><a href='https://loodusegakoos.ee/kuhuminna/rahvuspargid/soomaa-rahvuspark/1268/'>Kopraraja lisainfo</a></b>", "<br>",
                             
                             "Pikkuskraad: ", "25.031412", "<br>",
                             "Laiuskraad: ", "58.431158", "<br>"),
               label = "Soomaa rahvuspargi külastuskeskus") %>%
    
    # Jäägem eesti piiridesse seega täpsustame kaardiaknas kuvatavaid piire
    setMaxBounds(21.58448, 60.08641, 28.39045, 57.07625) %>%
    # Lisame legendi
    addLegend(
        title = "Legend",
        position = "bottomright",
        values = c(1, 2,3,4,5),
        labels = c("Vooluvesi", "Järved","meteo. jaamad","hüdro. jaamad","kaitsealad"),
        colors = c("blue", "blue","darkgreen","yellow","lightblue"))%>%
    # Lisame kihtide sisse/välja lülitamise funktsionaalsuse
    addLayersControl(
        #baseGroups = c("Taustakaart","Kaitseala"),
        overlayGroups = c("Vooluvesi","Järved","Jaamad","Kaitseala","Taustakaart"),
        options = layersControlOptions(collapsed = FALSE)) 


# vajadusel saab kaarti ka erladiseisvalt salvestada htmli
#library(plotly) ;htmlwidgets::saveWidget(as_widget(basemap), "basemap.html")
basemap

#rmarkdown::render(“soomaa.Rmd”)

LS0tDQp0aXRsZTogS2Vza2tvbm5hYWdlbnR1dXJpIGF2YWFuZG1ldGUgamEgYW5kbWV0ZWVudXN0ZSBrYXN1dGFtaW5lIFNvb21hYSBuw6RpdGVsDQphdXRob3I6ICJLZXNra29ubmFhZ2VudHV1ciINCmRhdGU6ICIxMC4wNC4yMDI0Ig0Kb3V0cHV0OiANCiAgaHRtbF9kb2N1bWVudDogDQogICAgY3NzOiBDU1NCYWNrZ3JvdW5kcy5jc3MNCiAgICBoaWdobGlnaHQ6IGVzcHJlc3NvDQogICAgY29kZV9mb2xkaW5nOiBoaWRlDQogICAgdGhlbWU6IGNlcnVsZWFuDQogICAgI3RoZW1lOiBmbGF0bHkNCiAgICBjb2RlX2Rvd25sb2FkOiB0cnVlDQotLS0NCg0KYGBge3Igc2V0dXAsIGluY2x1ZGUgPSBGQUxTRX0NCmtuaXRyOjpvcHRzX2NodW5rJHNldChlY2hvID0gVFJVRSkNCmBgYA0KDQoNCmBgYHtyIGVjaG89RkFMU0UsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9DQpsaWJyYXJ5KHBhcnRpY2xlc2pzKQ0KcGFydGljbGVzKCJwYXJ0aWNsZXNqcy1jb25maWcuanNvbiIpDQpgYGANCg0KPiBQYXJpbSBrb2h0IHZpaWVuZGEgYWFzdGFhamEga29nZW1pc2VrcyBFZXN0aXMgb24gU29vbWFhIQ0KDQoNCiMjIFNvb21hYSB7LnRhYnNldH0NCg0KIyMjIMOcbGV1anV0dXN0ZSBhbmRtZWQgamEgcHJvZ25vb3Mgey50YWJzZXQgLnRhYnNldC1mYWRlIC50YWJzZXQtcGlsbHN9DQoNCiMjIyMgSMO8ZHJvbG9vZ2lsaXNlZCB0dW5uaWFuZG1lZA0KDQpTb29tYWEgcGFrdWIgaHV2aSBlZWxrw7VpZ2Ugb21hIMO8bGV1anV0dXN0ZWdhIHN1dXJ2ZWUgcGVyaW9vZGlsIGVoayB2aWllbmRhIGFhc3RhYWphIHBvb2xlc3QuIFNlZWdhIHR1bGVrcyBhbHVzdHVzZWtzIHZhYWRhdGEsIG1pcyBzZWFsIHRvaW11YiBzZWxsZWwgYWFzdGFsIGphIGt1aWRhcyBvbiBwcmFlZ3VzZWQgdmVldGFzZW1lZCBuaW5nIHZvb2x1aHVsZ2FkLiANClZhbGl0dWQgb24gMiBow7xkcm9sb29naWxpc2Ugc2VpcmUgamFhbWEsIG1pcyB2w7Vpa3NpZCBhbmRhIGvDtWlnZSBwYXJlbWEgaW5mbyBTb29tYWEgaGV0a2VzZWlzdSBrb2h0YToNCg0KKyBbQWVzb28gaMO8ZHJvbWVldHJpYWphYW1dKGh0dHBzOi8vd3d3LmlsbWF0ZWVuaXN0dXMuZWUvbWVpc3QvdmFhdGx1c3ZvcmsvYWVzb28taHVkcm9tZWV0cmlhamFhbS8pDQorIFtSaWlzYSBow7xkcm9tZWV0cmlhamFhbV0oaHR0cHM6Ly93d3cuaWxtYXRlZW5pc3R1cy5lZS9tZWlzdC92YWF0bHVzdm9yay9yaWlzYS1odWRyb21lZXRyaWFqYWFtLykNCg0KQWxsb2xldmF0ZWwgZ3JhYWZpa3V0ZWwgb24ga3V2YXR1ZCBBZXNvbyBow7xkcm9tZWV0cmlhamFhbWFzIG3DtcO1ZGV0dWQgdm9vbHVodWxnYWQgamEgdmVldGFzZW1lZC4NCg0KKipWZWV2b29sdSBhbmRtZWQqKg0KDQpBZXNvbyBow7xkcm9tZWV0cmlhamFhbWEgaMO8ZHJvbG9vZ2lsaXNlIHNlaXJlIHZlZXZvb2x1IHR1bm5pYW5kbWVkIGFubmF2YWQgw7xsZXZhYXRlIHZlZSBsaWlrdW1pc2VzdCBzZWxsZWwgcGVyaW9vZGlsLiAgVm9vbHVodWxnYSBzdXVyZW5lbWluZSBuw6RpdGFiIHN1dXJ2ZWUgYWphIGFsZ3VzdCBqYSBpbnRlbnNpaXZzdXN0LiBTYW1hcyBtaWRhIHJvaGtlbSB2ZXR0IG9uIGrDtWVzIGphIHZvb2xhYiDDpHJhIHNlZGEgdsOkaGVtIG9uIHNlZGEgw7xsZXVqdXRhdHVkIGFsYWRlbC4gDQoNCg0KYGBge3IgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0NCiMgw4RyYXZvb2wNCmxpYnJhcnkoZHlncmFwaHMpDQpkeWdyYXBoKGh5ZHJvX2RhdGFfMVssYygidGltZWxpbmVfdHNfdXRjIiwiw4RyYXZvb2wgYXZnIiksXSwNCiAgICAgICAgbWFpbiA9ICLDhHJhdm9vbCBrZXNrbWluZSIsIA0KICAgICAgICB5bGFiID0gIlR1bm5pIGtlc2ttaW5lIMOkcmF2b29sLCBtMy9zIikgJT4lDQogICAgZHlSYW5nZVNlbGVjdG9yKCklPiUNCiAgICBkeVJvbGxlcihyb2xsUGVyaW9kID0gMjQpICU+JQ0KICAgIGR5T3B0aW9ucyhmaWxsR3JhcGggPSBUUlVFLCBmaWxsQWxwaGEgPSAwLjQpDQpgYGANCg0KDQoqKlZlZXRhc2VtZWQqKg0KDQpBZXNvbyBow7xkcm9tZWV0cmlhamFhbWEgaMO8ZHJvbG9vZ2lsaXNlIHNlaXJlIHZlZXRhc2VtZXRlIHR1bm5pYW5kbWVkIGFubmF2YWQgw7xsZXZhYXRlIHZlZXRhc2VtZXRlc3QgaHV2aXBha2t1dmFsIHBlcmlvb2RpbC4gVmVldGFzZW1lZCBvbiBoZWFrcyBpbmRpa2FhdG9yaWtzLCBtaWxsYWwgb24ga8O1aWdlIHNvYml2YW0gYWVnIMO8bGV1anV0dXNhbGFkZSBrw7xsYXN0YW1pc2Vrcy4gU2FtYXMgb24gbsOkaGEsIGV0IHZlZXRhc2VtZXRlIGvDtWlrdW1pc2kgb24gbWl0dSBtaXN0w7V0dHUga2Egw7VpZ2VpZCBTb29tYWEga8O8bGFzdHVzYWVndSB2w7VpYiBvbGxhIG1pdHUuIFBhcmltIGFlZyBzdXVydmVlIGtvZ2VtaXNla3MgMjAyNC5hc3RhbCBvbGkgaWxtc2VsdCBtw6RydHNpIGFsZ3VzZXMga3VpZCBrYSBtw6RydHNpIGzDtXB1cyBuw6RpdGF2YWQgYW5kbWVkIHZlZXRhc2VtZXRlIHN1dXJlbWF0IGvDtWlrdW1pc3QuDQoNCmBgYHtyIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9DQojIFdMLXZlZXRhc2VtZWQNCmxpYnJhcnkoZHlncmFwaHMpDQpkeWdyYXBoKGh5ZHJvX2RhdGFfMVssYygidGltZWxpbmVfdHNfdXRjIiwiV0wgbWF4IiwiV0wgbWluIiksXSwNCiAgICAgICAgbWFpbiA9ICJUdW5uaSBtYWtzaW1hYWxuZSB2ZWV0YXNlIChXTCBtYXgpIGphIG1pbmltYWFsbmUgdmVldGFzZSAoV0wgbWluKSIsIA0KICAgICAgICB5bGFiID0gInZlZXRhc2UsIGNtIikgJT4lDQogICAgZHlSYW5nZVNlbGVjdG9yKCklPiUNCiAgICBkeVJvbGxlcihyb2xsUGVyaW9kID0gMjQpICU+JQ0KICAgIGR5T3B0aW9ucyhmaWxsR3JhcGggPSBUUlVFLCBmaWxsQWxwaGEgPSAwLjQpDQoNCmBgYA0KDQoNCg0KIyMjIyBNZXRlb3JvbG9vZ2lsaXNlIHNlaXJlIHR1bm5pYW5kbWVkDQoNClNvb21hYSBzdXVydmVlIHR1bGVrIGphIG1pbmVrIG9uIG9sdWxpc2VsdCBzZW90dWQgbWV0ZW9yb2xvb2dpbGlzdGUgbsOkaXRhamF0ZWdhIG5hZ3Ugc2FkZW1lZCBqYSDDtWh1dGVtcGVyYXR1dXIuDQpTZWVnYSB0dWxla3MgYWx1c3R1c2VrcyB2YWFkYXRhLCBtaWRhIG7DpGl0YXZhZCBhbmRtZWQgc3V1cnZlZSBwZXJpb29kaWwgc2VsbGVsIGphIGVlbG1pc2VsIGFhc3RhbC4gS3VuYSBTb29tYWEgYXN1YiBrb2xtZSBtZXRlb3JvbG9vZ2lhamFhbWEga29sbW51cmdhcyBwZWFndSBldCBrZXNrZWwsIHNpaXMgc2FpIFbDpGxqYSB2YWxpdHVkIGrDpHJnbWlzZWQga29sbSBtZXRlb3JvbG9vZ2lhamFhbWEsIG1pcyB2w7Vpa3MgYW5kYSBrw7VpZ2UgcGFyZW1hIGluZm86DQoNCisgW1TDvHJpIG1ldGVvcm9sb29naWFqYWFtXShodHRwczovL3d3dy5pbG1hdGVlbmlzdHVzLmVlL21laXN0L3ZhYXRsdXN2b3JrL3R1cmktbWV0ZW9yb2xvb2dpYWphYW0vKQ0KKyBbUMOkcm51IHJhbm5pa3VqYWFtXShodHRwczovL3d3dy5pbG1hdGVlbmlzdHVzLmVlL21laXN0L3ZhYXRsdXN2b3JrL3Bhcm51LXJhbm5pa3VqYWFtLykNCisgW1ZpbGphbmRpIG1ldGVvcm9sb29naWFqYWFtXShodHRwczovL3d3dy5pbG1hdGVlbmlzdHVzLmVlL21laXN0L3ZhYXRsdXN2b3JrL3ZpbGphbmRpLW1ldGVvcm9sb29naWFqYWFtLykNCg0KQWxsb2xldmF0ZWwgZ3JhYWZpa3V0ZWwgb24ga3V2YXR1ZCBuZW5kZXMgbWV0ZW9yb2xvb2dpYWphYW1hZGVzIG3DtcO1ZGV0dWQgdGVtcGVyYXR1dXJpZCBqYSBzYWRlbWV0ZSBodWxnYWQuDQoNCioqw5VodXRlbXBlcmF0dXVyKioNCg0KVMO8cmksIFDDpHJudSBqYSBWaWxqYW5kaSAgbWV0ZW9yb2xvb2dpbGlzZSBzZWlyZSDDtWh1dGVtcGVyYXR1dXJpIHR1bm5pYW5kbWVkIGFubmF2YWQgw7xsZXZhYXRlIGt1aWRhcyBpbG0gbcO1anV0YWIgc3V1cnZlZSB0ZWtldC4gTWlkYSByb2hrZW0gb24ga8O8bG1ha3JhYWRlIGphIHNhZGVtZWlkIHRhbHZlbCBzZWRhIHJvaGtlbSB0YWxsZXR1YiB2ZXR0IGphIHNlZGEgcm9oa2VtIG9uIGtldmFkZWwgc3V1cnZldHQuDQoNCmBgYHtyIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9DQojIMOVaHV0ZW1wIHTDpGlzdHVubmlsDQpsaWJyYXJ5KGR5Z3JhcGhzKQ0KZHlncmFwaChrbGlpbWFfZGF0YV9UQSwNCiAgICAgICAgbWFpbiA9ICLDlWh1dGVtcGVyYXR1dXIgdMOkaXN0dW5uaWwgKGhldGt2w6TDpHJ0dXMpIiwgDQogICAgICAgIHlsYWIgPSAia3JhYWQoYykiKSAlPiUNCiAgICBkeVJhbmdlU2VsZWN0b3IoKSU+JQ0KICAgIGR5Um9sbGVyKHJvbGxQZXJpb2QgPSAyNCkgJT4lDQogICAgZHlPcHRpb25zKGZpbGxHcmFwaCA9IFRSVUUsIGZpbGxBbHBoYSA9IDAuMikNCg0KYGBgDQoNCg0KKipTYWRlbWVkKioNCg0KVMO8cmksIFDDpHJudSBqYSBWaWxqYW5kaSAgbWV0ZW9yb2xvb2dpbGlzZSBzZWlyZSBzYWRlbWV0ZSB0dW5uaWFuZG1lZCBhbm5hdmFkIMO8bGV2YWF0ZSBrdWlkYXMgaWxtIG3DtWp1dGFiIHN1dXJ2ZWUgdGVrZXQuIE1pZGEgcm9oa2VtIG9uIGvDvGxtYWtyYWFkZSBqYSBzYWRlbWVpZCBzZWRhIHJvaGtlbSB0YWxsZXR1YiB2ZXR0IGphIHNlZGEgcm9oa2VtIG9uIGtldmFkZWwgc3V1cnZldHQuDQoNCmBgYHtyIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9DQojIMOcaGUgdHVubmkgc2FkZW1ldGUgc3VtbWENCmxpYnJhcnkoZHlncmFwaHMpDQpkeWdyYXBoKGtsaWltYV9kYXRhX1BSMUgsDQogICAgICAgIG1haW4gPSAiw5xoZSB0dW5uaSBzYWRlbWV0ZSBzdW1tYSIsIA0KICAgICAgICB5bGFiID0gIm1tIiklPiUNCiAgICBkeVJhbmdlU2VsZWN0b3IoKSU+JQ0KICAgIGR5Um9sbGVyKHJvbGxQZXJpb2QgPSAzKSU+JQ0KICAgIA0KICAgIGR5T3B0aW9ucyhmaWxsR3JhcGggPSBUUlVFLCBmaWxsQWxwaGEgPSAwLjIpIA0KDQpgYGANCg0KIyMjIyBBbmRtZXRlIHbDtXJkbHVzDQoNCioqSMO8ZHJvbG9vZ2lsaXN0ZSBqYSBtZXRlb3JvbG9vZ2lsaXN0ZSBhbmRtZXRlIHbDtXJkbHVzKioNCg0KU3V1cnZlZSBrw7VyZ2FqYSBsZWlkbWlzZWtzIG9uIHZhamEgdmFhZGF0YSBrdWlkYXMgbcO1anV0YXZhZCB2YWxpdHVkIGjDvGRyb2xvb2dpbGlzZWQgamEgbWV0ZW9yb2xvb2dpbGlzZWQgbsOkaXRhamFkIMO8a3N0ZWlzdC4gS3VuYSBhbmRtZXRlIHNrYWFsYWQgb24gdsOkZ2EgZXJpbmV2YWQgc2lpcyB2w7VyZGx1c2Ugc2FhbWlzZWtzIHR1bGViIGFuZG1lZCBlbm5lIG5vcm1hbGlzZWVyaWRhIChubiBrYWFsdXR1ZCBhbmRtZWQpLiBFdCBncmFhZmlrIG9sZWtzIGxvZXRhdiBqYSB0w7VsZ2VuZGF0YXYgdHVsZWIgdGVtcGVyYXR1dXJpIGFuZG1laWQga2Ega2Vza21pc3RhZGEgKDMwIHDDpGV2YSBrZXNrbWluZSkNCkFsbG9sZXZhIGdyYWFmaWt1IG5vcm1hbGlzZWVyaXR1ZCB2w6TDpHJ0dXN0ZSBww7VoamFsIG9uIG7DpGhhIGt1aWRhcyBpbG0gbcO1anV0YWIgdmVldGFzZW1laWQgamEgw6RyYXZvb2x1Lg0KDQoNCmBgYHtyIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9DQojIG5vcm1hbGlzZWVyaXR1ZCB2w6TDpHJ0dXMNCmxpYnJhcnkoZHlncmFwaHMpDQpkeWdyYXBoKHR1bGVtdXMsDQogICAgICAgIG1haW4gPSAiTm9ybWFsaXNlZXJpdHVkIGFuZG1lZCIsIA0KICAgICAgICB5bGFiID0gIiBOb3JtYWxpc2Vlcml0dWQgdsOkw6RydHVzIiklPiUNCiAgICBkeVJhbmdlU2VsZWN0b3IoKSU+JQ0KICAgIGR5Um9sbGVyKHJvbGxQZXJpb2QgPSAyNCklPiUNCiAgICBkeUhpZ2hsaWdodChoaWdobGlnaHRTZXJpZXNPcHRzID0gbGlzdChzdHJva2VXaWR0aCA9IDMpKSU+JQ0KICAgIGR5T3B0aW9ucyhmaWxsR3JhcGggPSBUUlVFLCBmaWxsQWxwaGEgPSAwLjIpIA0KYGBgDQoNCioqQWphbG9vbGlzZWQgYW5kbWVkKioNCg0KUGlrZW1hcyBwZXJzcGVrdGlpdmlzIGFubmFiIG9sdWxpc3QgaW5mb3QganVzdCBtaXRtZSBhYXN0YSBhbmRtZXRlIHbDtXJkbHVzLiBQYXJha3UgdsOkbGphc3RhYiBhbmRtZXRlZW51cyBoZXRrZWwgaMO8ZHJvbG9vZ2lsaXNlIHNlaXJlIHR1bm5pYW5kbWVpZCBhbGF0ZXMgMDEuMDEuMjAyMywgVmFyYXNlbWF0ZSBhbmRtZXRlIGxpc2FtaW5lIGFuZG1ldGVlbnVzZXNzZSBvbiBwb29sZWxpLCBzZWVnYSBrYXN1dGFtZSBbRXN0TW9kZWxpIHZlZXRhc2VtZXRlIGFuZG1laWRdKGh0dHBzOi8vZXN0bW9kZWwuYXBwL2V0LyMvbWVhc3VyZW1lbnRzP3N0YXRpb249U0pBNDM4NTAwMCkuDQoNCmBgYHtyIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9DQojIGFqYWxvbGlzZWQgUmlpc2EgdmVldGFzZW1lZA0KbGlicmFyeShkeWdyYXBocykNCmR5Z3JhcGgoaHlkcm9fRXN0TW9kZWxfcmlpc2FbLGMoIngiLCJtaW4iLCJtZWRpYW4iLCJtYXgiKV0sDQogICAgICAgIG1haW4gPSAiMjAxOS0yMDIzIGFhc3RhIFJpaXNhIGjDvGRyb21lZXRyaWFqYWFtYSB2ZWV0YXNlbWVkIiwgDQogICAgICAgIHlsYWIgPSAibSIpJT4lDQogICAgZHlSYW5nZVNlbGVjdG9yKCklPiUNCiAgICBkeUhpZ2hsaWdodChoaWdobGlnaHRTZXJpZXNPcHRzID0gbGlzdChzdHJva2VXaWR0aCA9IDMpKSU+JQ0KICAgIGR5T3B0aW9ucyhmaWxsR3JhcGggPSBUUlVFLCBmaWxsQWxwaGEgPSAwLjIpICU+JQ0KICAgIGR5Um9sbGVyKHJvbGxQZXJpb2QgPSA3KQ0KDQpgYGANCg0KDQpMaXNha3Mgb24gc3V1cnZlc2kgc2VvdHVkIGVlbGvDtWlnZSB0ZW1wZXJhdHV1cmlnYSwgc2VlZ2Egc2FhYiB0ZWhhIDUgYWFzdGEgdGVtcGVyYXR1dXJpIGFuZG1ldGUgdsO1cmRsdXN0LiBTZWxsZWtzLCBldCBncmFhZmlrIHbDpGdhIGxvZXRhbWF0dWtzIGVpIG11dXR1a3Mgb24ga3V2YXR1ZCA1IGFhc3RhIG1paW5pbXVtLCBtZWRpYWFuIGphIG1ha3NpbXVtIHRlbXBlcmF0dXVyaWQgKDIwMTktMjAyMykuIEFsbG9sZXZhIGdyYWFmaWt1IG1lZGlhYW5pIG7DpGl0YWphIHDDtWhqYWwgdsO1aWtzIGFydmF0YSwgZXQgcGFyaW0gYWVnIGhha2F0YSBwbGFuZWVyaW1hIFNvb21hYSBrw7xsYXN0dXN0IG9sZWtzIG3DpHJ0c2kgbMO1cHVzLiBTYW1hcyB0YXN1YiBzaWxtYSBwZWFsIGhvaWRhIGpvb2tzdmEgYWFzdGEgdGVtcGVyYXR1dXJpZGVsLCBzZXN0IGFhc3RhdGUgbMO1aWtlcyB0ZW1wZXJhdHV1ciBrw7VpZ3ViIHDDpHJpcyBwYWxqdSBqYSBpbG1hb2x1ZCBvbiBtdXV0bGlrdWQuDQoNCmBgYHtyIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9DQojIGFqYWxvbGlzZWQga2xpaW1hIGFuZG1lZA0KbGlicmFyeShkeWdyYXBocykNCmR5Z3JhcGgoa2xpaW1hX2RhdGFfUEFbLGMoIngiLCJtaW4iLCJtZWRpYW4iLCJtYXgiKV0sDQogICAgICAgIG1haW4gPSAiMjAxOS0yMDIzIGFhc3RhIHRlbXBlcmF0dXVyaWQiLCANCiAgICAgICAgeWxhYiA9ICIga3JhYWQoYykiKSU+JQ0KICAgIGR5UmFuZ2VTZWxlY3RvcigpJT4lDQogICAgZHlIaWdobGlnaHQoaGlnaGxpZ2h0U2VyaWVzT3B0cyA9IGxpc3Qoc3Ryb2tlV2lkdGggPSAzKSklPiUNCiAgICBkeU9wdGlvbnMoZmlsbEdyYXBoID0gVFJVRSwgZmlsbEFscGhhID0gMC4yKSAlPiUNCiAgICBkeVJvbGxlcihyb2xsUGVyaW9kID0gNykNCg0KYGBgDQoNCg0KIyMjIyBIw7xkcm9sb29naWxpc2VkIHByb2dub29zaWQNCg0KKipLZXNra29ubmFhZ2VudHV1cmkgaMO8ZHJvbG9vZ2lsaW5lIHByb2dub29zKioNCg0KQWVzb28gamEgUmlpc2EgaMO8ZHJvbWVldHJpYWphYW1hZGUgaMO8ZHJvbG9vZ2lsaXNlICBtdWRlbHByb2dub29zaSBww6RldmFhbmRtZWQgYW5uYXZhZCAxMCBww6RldmEgdWxhdHVzZXMgcHJvZ25vb3NpLCBtaWxsZSBhYmlsIHZhbGlkYSBrw7VpZ2Ugw7VpZ2VtIGhldGssIG1pbGxhbCBtaW5uYSBTb29tYWFsZS4gS2Vza2tvbm5hYWdlbnR1dXJpIGjDvGRyb2xvb2dpbGluZSBtdWRlbHByb2dub29zIG9uIGtvb3N0YXR1ZCBvbWEgYWxhIGVrc3BlcnRpZGUgcG9vbHQga2FzdXRhZGVzIHNlbGxla3MgbG9vZHVkIG11ZGVsaWQuIFRhc3ViIHZhYWRhdGEga2EgW3Byb2dub29zaSBrb29zdGFtaXNlIGtpcmplbGR1c3RdKCJodHRwczovL2tlc2trb25uYXBvcnRhYWwuZWUvZXQvYXZhYW5kbWVkL2h1ZHJvbG9vZ2lsaXNlLXByb2dub29zaS1hbmRtZXN0aWsvaHVkcm9sb29naWxpc2UtcHJvZ25vb3NpLWtpcmplbGR1cyIpDQpHcmFhZmlrdXRlbCBvbiB0b29kdWQgQWVzb28gdm9vbHVodWxnYSBwcm9nbm9vcyBqYSBSaWlzYSB2ZWV0YXNlbWV0ZSBwcm9nbm9vcy4NCg0KDQpgYGB7ciBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQ0KIyBtYXgsIG1pbiwga2Vza21pbmUgdm9vbHVodWxrDQpsaWJyYXJ5KGR5Z3JhcGhzKQ0KZHlncmFwaChBZXNvb19wcm9nbm9vc1ssYygicGFldiIsInZvb2x1aHVsZ2EgcHJvZ25vb3MiLCJtYXggdm9vbHVodWxrIiwibWluIHZvb2x1aHVsayIsImtlc2ttaW5lIHZvb2x1aHVsayIpXSwNCiAgICAgICAgbWFpbiA9ICJBZXNvbyBow7xkcm9sb29naWxpbmUgbXVkZWxwcm9nbm9vcyIsIA0KICAgICAgICB5bGFiID0gInZvb2x1aHVsayIpICU+JQ0KICAgIGR5RXZlbnQoQWVzb29fcHJvZ25vb3NbMTEsYygicGFldiIpXSwgIlTDpG5hIiwgbGFiZWxMb2MgPSAiYm90dG9tIikgJT4lDQogICAgZHlSYW5nZVNlbGVjdG9yKCklPiUNCiAgICBkeVJvbGxlcihyb2xsUGVyaW9kID0gMCkgJT4lDQogICAgZHlIaWdobGlnaHQoaGlnaGxpZ2h0U2VyaWVzT3B0cyA9IGxpc3Qoc3Ryb2tlV2lkdGggPSAzKSklPiUNCiAgICBkeU9wdGlvbnMoZmlsbEdyYXBoID0gVFJVRSwgZmlsbEFscGhhID0gMC4yKQ0KDQpgYGANCg0KDQoNCmBgYHtyIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9DQojIG1heCBtaW4sIGtlc2ttaW5lIHZlZXRhc2UNCmxpYnJhcnkoZHlncmFwaHMpDQpkeWdyYXBoKFJpaXNhX3Byb2dub29zWyxjKCJwYWV2IiwidmVldGFzZW1lIHByb2dub29zIiwgIm1heCB2ZWV0YXNlIiwgIm1pbiB2ZWV0YXNlIiwgImtlc2ttaW5lIHZlZXRhc2UiKV0sDQogICAgICAgIG1haW4gPSAiUmlpc2EgaMO8ZHJvbG9vZ2lsaW5lIG11ZGVscHJvZ25vb3MiLCANCiAgICAgICAgeWxhYiA9ICJ2ZWV0YXNlIikgJT4lDQogICAgZHlFdmVudChSaWlzYV9wcm9nbm9vc1sxMSxjKCJwYWV2IildLCAiVMOkbmEiLCBsYWJlbExvYyA9ICJib3R0b20iKSAlPiUNCiAgICBkeVJhbmdlU2VsZWN0b3IoKSU+JQ0KICAgIGR5Um9sbGVyKHJvbGxQZXJpb2QgPSAwKSAlPiUNCiAgICBkeUhpZ2hsaWdodChoaWdobGlnaHRTZXJpZXNPcHRzID0gbGlzdChzdHJva2VXaWR0aCA9IDMpKSU+JQ0KICAgIGR5T3B0aW9ucyhmaWxsR3JhcGggPSBUUlVFLCBmaWxsQWxwaGEgPSAwLjIpDQoNCmBgYA0KDQoqKktlc2trb25uYWFnZW50dXVyaSBtZXRlb3Jvb2xvb2dpbGluZSBwcm9nbm9vcyoqDQoNCkxpc2FrcyBow7xkcm9sb29naWxpc2VsZSBwcm9nbm9vc2lsZSB0YXN1YiB2YWFkYXRhIGthIEtlc2trb25uYWFnZW50dXVyaSBtZXRlb3JvbG9vZ2lsaXN0IGFzdWtvaGFww7VoaXN0IHByb2dub29zaS4gUHJvZ25vb3NpIGFuZG1lZCBvbiBww6RyaXR1ZCBBZXNvbyBow7xkcm9tZWV0cmlhamFhbWEga29vcmRpbmFhdGlkZSBrb2h0YS4gSWxtIG9uIGtldmFkZWwgaGVpdGxpaywgc2VlZ2EgcGFyaW1hIGtvZ2VtdXNlIHNhYW1pc2VrcyB0YXN1YiBsaXNha3MgdmVldGFzZW1ldGVsZSBhcnZlc3RhZGEgc2FkZW1laWQsIMO1aHV0ZW1wZXJhdHV1cmkgamEgdHV1bHQuIFRhc3ViIHZhYWRhdGEga2EgW2lsbWFwcm9nbm9vc2lkZSBhbmRtZXN0aWt1IGtpcmplbGR1c3RdKCJodHRwczovL2tlc2trb25uYXBvcnRhYWwuZWUvZXQvYXZhYW5kbWVkL2lsbWFwcm9nbm9vc2lkIikNCg0KDQpgYGB7ciBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQ0KbGlicmFyeShkeWdyYXBocykNCmR5Z3JhcGgoa2xpaW1hXzRbLGMoImFlZyIsIlRBIiwiUFIxSCIsIlR1dWwiKV0sDQogICAgICAgIG1haW4gPSAiTWV0ZW9yb2xvb2dpbGluZSBwcm9nbm9vcyBBZXNtYWEgamFhbWEga29vcmRpbmFhdGlkZWwiLCANCiAgICAgICAgeWxhYiA9ICJ0ZW1wKGMpLCB0dXVsKG0vcyksIHNhZGVtZWQobW0pIikgJT4lDQogICAgZHlTZXJpZXMoIlRBIiwgbGFiZWwgPSAiVGVtcCIpICU+JQ0KICAgIGR5U2VyaWVzKCJUdXVsIiwgbGFiZWwgPSAiVHV1bCIpICU+JQ0KICAgIGR5UmFuZ2VTZWxlY3RvcigpJT4lDQogICAgZHlSb2xsZXIocm9sbFBlcmlvZCA9IDApICU+JQ0KICAgIGR5SGlnaGxpZ2h0KGhpZ2hsaWdodFNlcmllc09wdHMgPSBsaXN0KHN0cm9rZVdpZHRoID0gMykpJT4lDQogICAgZHlPcHRpb25zKGZpbGxHcmFwaCA9IFRSVUUsIGZpbGxBbHBoYSA9IDAuMixsYWJlbHNVVEMgPSBUUlVFKQ0KYGBgDQoNCg0KIyMjIFRlZW1ha2FhcnQNCg0KKipTb29tYWEgdmVldsO1cmsgamEgc2VpcmVqYWFtYWQqKg0KDQpLYWFyZGlsdCBsZWlhZCBTb29tYWEgbMOkaGlzdGVsIG9sZXZhZCBBZXNvbyBqYSBSaWlzYSBow7xkcm9tZWV0cmlhamFhbWFkIG5pbmcga29sbSBsw6RoaW1hdCBtZXRlb3JvbG9vZ2lhamFhbWEsIGtvb3MgdMOkaWVuZGF2YSBpbmZvZ2EuIExpc2FrcyBvbiB0YXVzdGFuZG1ldGVrcyB2ZWV2w7VyayAoasOkcnZlZCBqYSB2b29sdXZlZWtvZ3VkKSBuaW5nIFNvb21hYSBrYWl0c2VhbGEuIFNvb21hYSByYWh2dXNwYXJnaSBrb2h0YSBzYWFiIHTDpGllbmRhdmF0IGluZm90IFNvb21hYSBrw7xsYXN0dXNrZXNrdXNlc3QsIG1pcyBvbiDDvGh0bGFzaSBrYSBoZWEgYWxndXNwdW5rdCDDvGxldWp1dGF0dWQgYWxhZGUga8O8bGFzdGFtaXNla3MuDQoNCmBgYHtyIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9DQoNCiMgRWVzdGkga29vcmRpbmFhdHPDvHN0ZWVtIHR1bGViIHTDpHBzdXN0YWRhIGt1bmEgbGVhZmxldCBrYXN1dGFiIHdnczg0DQpsaWJyYXJ5KGxlYWZsZXQpDQpsaWJyYXJ5KGxlYWZsZXQuZXh0cmFzKQ0KIyMgVGVlbWUgdmFsbWlzIGthYXJkaSBsZWFmbGV0aWdhDQojIFRla2l0YW1lIGthYXJkaW9iamVrdGkNCmJhc2VtYXAgPC0gbGVhZmxldChqYWFtLA0KICAgICAgICAgICAgICAgICAgIHdpZHRoID0gIjEwMCUiLCANCiAgICAgICAgICAgICAgICAgICBoZWlnaHQgPSAiNjAwcHgiLA0KICAgICAgICAgICAgICAgICAgIG9wdGlvbnMgPSBsZWFmbGV0T3B0aW9ucygNCiAgICAgICAgICAgICAgICAgICAgICAgcHJlZmVyQ2FudmFzID0gVFJVRSwgDQogICAgICAgICAgICAgICAgICAgICAgICN3b3JsZENvcHlKdW1wID0gRiwgDQogICAgICAgICAgICAgICAgICAgICAgIGNycyA9IGVwc2czMzAxKSkgJT4lDQogICAgDQogICAgI2FkZFRpbGVzKHVybFRlbXBsYXRlID0gIi8ve3N9LnRpbGUub3BlbnN0cmVldG1hcC5vcmcve3p9L3t4fS97eX0ucG5nIiwgZ3JvdXAgPSAiVGF1c3Rha2FhcnQiLHRpbGVPcHRpb25zKG9wYWNpdHkgPSAwLjkpKSAlPiUNCiAgICANCiAgICAjIExpc2FtZSBrYWFyZGlsZSBNQSBhbHVza2FhcmRpIFZNUyB0ZWVudXNlDQogICAgYWRkV01TVGlsZXMoDQogICAgICAgIG1hX2FsdXMsDQogICAgICAgICNsYXllcnMgPSAiTUEtQUxVUyIsDQogICAgICAgIGxheWVycyA9ICJNQS1IQUxMS0FBUlQiLA0KICAgICAgICBncm91cCA9ICJUYXVzdGFrYWFydCIsDQogICAgICAgIG9wdGlvbnMgPSBXTVNUaWxlT3B0aW9ucyhmb3JtYXQgPSAiaW1hZ2UvcG5nIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRyYW5zcGFyZW50ID0gVFJVRSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG9wYWNpdHk9MC4zLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWluWm9vbSA9IDEsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYXhab29tID0gMTQsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb250aW51b3VzV29ybGQgPSBUKSkgJT4lDQogICAgDQogICAgIyBMaXNhbWUga2FhcmRpbGUgdm9vbHV2ZWVrb2d1ZGUgVk1TIHRlZW51c2UNCiAgICBhZGRXTVNUaWxlcygNCiAgICAgICAgZWVsaXMsDQogICAgICAgIGxheWVycyA9ICJlZWxpczprcl92b29sdXZlc2kiLA0KICAgICAgICBncm91cCA9ICJWb29sdXZlc2kiLA0KICAgICAgICBvcHRpb25zID0gV01TVGlsZU9wdGlvbnMoZm9ybWF0ID0gImltYWdlL3BuZyIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0cmFuc3BhcmVudCA9IFQsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtaW5ab29tID0gMCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1heFpvb20gPSAxNSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnRpbnVvdXNXb3JsZCA9IFQpKSAlPiUNCiAgICAjIExpc2FtZSBrYWFyZGlsZSBqw6RydmVkZSBWTVMgdGVlbnVzZQ0KICAgIGFkZFdNU1RpbGVzKA0KICAgICAgICBlZWxpcywNCiAgICAgICAgbGF5ZXJzID0gImVlbGlzOmtyX2phcnYiLA0KICAgICAgICBncm91cCA9ICJKw6RydmVkIiwNCiAgICAgICAgb3B0aW9ucyA9IFdNU1RpbGVPcHRpb25zKGZvcm1hdCA9ICJpbWFnZS9wbmciLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdHJhbnNwYXJlbnQgPSBULA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWluWm9vbSA9IDAsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYXhab29tID0gMTQsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb250aW51b3VzV29ybGQgPSBUKSkgJT4lDQogICAgIyBMaXNhbWUga2FhcmRpbGUgcmFtc2FyaSBhbGFkZSBWTVMgdGVlbnVzZQ0KICAgIGFkZFdNU1RpbGVzKA0KICAgICAgICBlZWxpcywNCiAgICAgICAgbGF5ZXJzID0gImVlbGlzOmtyX3JhbXNhciIsDQogICAgICAgIGdyb3VwID0gIkthaXRzZWFsYSIsDQogICAgICAgIG9wdGlvbnMgPSBXTVNUaWxlT3B0aW9ucyhmb3JtYXQgPSAiaW1hZ2UvcG5nIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRyYW5zcGFyZW50ID0gVCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1pblpvb20gPSAwLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWF4Wm9vbSA9IDE0LA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29udGludW91c1dvcmxkID0gVCkpICU+JQ0KICAgIA0KICAgICMgTGlzYW1lIGthYXJkaWxlIG1ldGVvcm9sb29naWFqYWFtYWQNCiAgICBhZGRDaXJjbGVNYXJrZXJzKHJhZGl1cyA9IDEwLA0KICAgICAgICAgICAgICAgICAgICAgI3Rla2l0YW1lIGluZm9ha25hDQogICAgICAgICAgICAgICAgICAgICBsbmcgPSB+amFhbSRsb24sIA0KICAgICAgICAgICAgICAgICAgICAgbGF0ID0gfmphYW0kbGF0LA0KICAgICAgICAgICAgICAgICAgICAgY29sb3IgPSAiZ3JlZW4iLA0KICAgICAgICAgICAgICAgICAgICAgZ3JvdXAgPSAiSmFhbWFkIiwNCiAgICAgICAgICAgICAgICAgICAgIHBvcHVwID0gcGFzdGUoIkphYW1hIG5pbWk6ICIsIGphYW0kamFhbV9uaW1pLCAiPGJyPiIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJKYWFtYSBuaW1pIChlbmcpOiAiLCBqYWFtJGphYW1fbmltaV9lbmcsICI8YnI+IiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkphYW1hIGtvb2Q6ICIsIGphYW0kamFhbV9rb29kLCAiPGJyPiIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJKYWFtYSBrw7VyZ3VzIG1lcmVwaW5uYXN0KG0pOiAiLCBqYWFtJGtvcmd1c19tZXJlcGlubmFzdF9tLCAiPGJyPiIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJQaWtrdXNrcmFhZDogIiwgamFhbSRsb24sICI8YnI+IiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkxhaXVza3JhYWQ6ICIsIGphYW0kbGF0LCAiPGJyPiIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJKYWFtYSBhbGd1c2FlZzogIiwgamFhbSRqYWFtX3Blcmlvb2RfYWxndXMsICI8YnI+IiksDQogICAgICAgICAgICAgICAgICAgICBsYWJlbCA9IH5qYWFtX25pbWkpICU+JQ0KICAgIA0KICAgICMgTGlzYW1lIGthYXJkaWxlIGjDvGRyb21lZXRyaWFqYWFtYWQNCiAgICBhZGRDaXJjbGVNYXJrZXJzKHJhZGl1cyA9IDEwLA0KICAgICAgICAgICAgICAgICAgICAgbG5nID0gfmh5ZHJvX2phYW0kbG9uLCANCiAgICAgICAgICAgICAgICAgICAgIGxhdCA9IH5oeWRyb19qYWFtJGxhdCwNCiAgICAgICAgICAgICAgICAgICAgIGNvbG9yID0gIiNGRkMzMDAiLA0KICAgICAgICAgICAgICAgICAgICAgZ3JvdXAgPSAiSmFhbWFkIiwNCiAgICAgICAgICAgICAgICAgICAgICN0ZWtpdGFtZSBpbmZvYWtuYQ0KICAgICAgICAgICAgICAgICAgICAgcG9wdXAgPSBwYXN0ZSgiSmFhbWEgbmltaTogIiwgaHlkcm9famFhbSRqYWFtX25pbWksICI8YnI+IiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkphYW1hIGtvb2Q6ICIsIGh5ZHJvX2phYW0kamFhbV9rb29kLCAiPGJyPiIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJWYWxnYWxhIG5pbWk6ICIsIGh5ZHJvX2phYW0kdmFsZ2FsYV9uaW1pLCAiPGJyPiIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJWYWxnYWxhIHN1dXJ1cyBrbTI6ICIsIGh5ZHJvX2phYW0kdmFsZ2FsYV9zdXVydXNfa20yLCAiPGJyPiIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJLYXVndXMgc3V1ZG1lc3Qga206ICIsIGh5ZHJvX2phYW0ka2F1Z3VzX3N1dWRtZXN0X2ttLCAiPGJyPiIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJWZWVrb2d1IG5pbWk6ICIsIGh5ZHJvX2phYW0kdmVla29ndV9uaW1pLCAiPGJyPiIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJQaWtrdXNrcmFhZDogIiwgaHlkcm9famFhbSRsb24sICI8YnI+IiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkxhaXVza3JhYWQ6ICIsIGh5ZHJvX2phYW0kbGF0LCAiPGJyPiIpLA0KICAgICAgICAgICAgICAgICAgICAgbGFiZWwgPSB+aHlkcm9famFhbSRqYWFtX25pbWkpICU+JQ0KICAgIA0KICAgICMgTGlzYW1lIGthYXJkaWxlIFNvb21hYSByYWh2dXNwYXJnaSBrw7xsYXN0dXNrZXNrdXNlDQogICAgYWRkTWFya2VycygjcmFkaXVzID0gMTAsDQogICAgICAgICAgICAgICBsbmcgPSAgMjUuMDMxNDEyLA0KICAgICAgICAgICAgICAgbGF0ID0gIDU4LjQzMTE1OCwNCiAgICAgICAgICAgICAgICNjb2xvciA9ICIjRkZDMzAwIiwNCiAgICAgICAgICAgICAgIGdyb3VwID0gIkphYW1hZCIsDQogICAgICAgICAgICAgICAjdGVraXRhbWUgaW5mb2FrbmENCiAgICAgICAgICAgICAgIHBvcHVwID0gcGFzdGUoIiAiLCAiU29vbWFhIHJhaHZ1c3BhcmdpIGvDvGxhc3R1c2tlc2t1cyIsICI8YnI+IiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIiAiLCAiPGI+PGEgaHJlZj0naHR0cHM6Ly9sb29kdXNlZ2Frb29zLmVlL2t1aHVtaW5uYS9yYWh2dXNwYXJnaWQvc29vbWFhLXJhaHZ1c3BhcmsvMTA3NjQvJz5Lw7xsYXN0dXNrZXNrdXNlIGluZm88L2E+PC9iPiIsICI8YnI+IiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIiAiLCAiPGI+PGEgaHJlZj0naHR0cHM6Ly9sb29kdXNlZ2Frb29zLmVlL2t1aHVtaW5uYS9yYWh2dXNwYXJnaWQvc29vbWFhLXJhaHZ1c3BhcmsvMTI2OC8nPktvcHJhcmFqYSBsaXNhaW5mbzwvYT48L2I+IiwgIjxicj4iLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIlBpa2t1c2tyYWFkOiAiLCAiMjUuMDMxNDEyIiwgIjxicj4iLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiTGFpdXNrcmFhZDogIiwgIjU4LjQzMTE1OCIsICI8YnI+IiksDQogICAgICAgICAgICAgICBsYWJlbCA9ICJTb29tYWEgcmFodnVzcGFyZ2kga8O8bGFzdHVza2Vza3VzIikgJT4lDQogICAgDQogICAgIyBKw6TDpGdlbSBlZXN0aSBwaWlyaWRlc3NlIHNlZWdhIHTDpHBzdXN0YW1lIGthYXJkaWFrbmFzIGt1dmF0YXZhaWQgcGlpcmUNCiAgICBzZXRNYXhCb3VuZHMoMjEuNTg0NDgsIDYwLjA4NjQxLCAyOC4zOTA0NSwgNTcuMDc2MjUpICU+JQ0KICAgICMgTGlzYW1lIGxlZ2VuZGkNCiAgICBhZGRMZWdlbmQoDQogICAgICAgIHRpdGxlID0gIkxlZ2VuZCIsDQogICAgICAgIHBvc2l0aW9uID0gImJvdHRvbXJpZ2h0IiwNCiAgICAgICAgdmFsdWVzID0gYygxLCAyLDMsNCw1KSwNCiAgICAgICAgbGFiZWxzID0gYygiVm9vbHV2ZXNpIiwgIkrDpHJ2ZWQiLCJtZXRlby4gamFhbWFkIiwiaMO8ZHJvLiBqYWFtYWQiLCJrYWl0c2VhbGFkIiksDQogICAgICAgIGNvbG9ycyA9IGMoImJsdWUiLCAiYmx1ZSIsImRhcmtncmVlbiIsInllbGxvdyIsImxpZ2h0Ymx1ZSIpKSU+JQ0KICAgICMgTGlzYW1lIGtpaHRpZGUgc2lzc2UvdsOkbGphIGzDvGxpdGFtaXNlIGZ1bmt0c2lvbmFhbHN1c2UNCiAgICBhZGRMYXllcnNDb250cm9sKA0KICAgICAgICAjYmFzZUdyb3VwcyA9IGMoIlRhdXN0YWthYXJ0IiwiS2FpdHNlYWxhIiksDQogICAgICAgIG92ZXJsYXlHcm91cHMgPSBjKCJWb29sdXZlc2kiLCJKw6RydmVkIiwiSmFhbWFkIiwiS2FpdHNlYWxhIiwiVGF1c3Rha2FhcnQiKSwNCiAgICAgICAgb3B0aW9ucyA9IGxheWVyc0NvbnRyb2xPcHRpb25zKGNvbGxhcHNlZCA9IEZBTFNFKSkgDQoNCg0KIyB2YWphZHVzZWwgc2FhYiBrYWFydGkga2EgZXJsYWRpc2Vpc3ZhbHQgc2FsdmVzdGFkYSBodG1saQ0KI2xpYnJhcnkocGxvdGx5KSA7aHRtbHdpZGdldHM6OnNhdmVXaWRnZXQoYXNfd2lkZ2V0KGJhc2VtYXApLCAiYmFzZW1hcC5odG1sIikNCmJhc2VtYXANCg0KYGBgDQoNCg0KIyMjIFNvb21hYSBhbmRtZWx1Z3Ugey50YWJzZXQgLnRhYnNldC1mYWRlIC50YWJzZXQtcGlsbHN9DQoNCiMjIyMgQW5kbWVsdWd1IFNvb21hYSBuw6RpdGVsDQoNCioqRWVzbcOkcmsqKg0KDQpLZXNra29ubmFhZ2VudHV1cmkgYXZhYW5kbWV0ZSBqYSBhbmRtZXRlZW51c3RlIGthc3V0YW1pbmUgU29vbWFhIG7DpGl0ZWwga29vc3RhdHVkIHJha2VuZHVzZSBlZXNtw6RyZ2lrcyBvbiBhbmRhIGlsbWEtIGphIGtlc2trb25uYXZhbGRrb25uYSBhbmRtZXRlIGthc3V0YWphdGVsZSDDvGtzIGFuZG1lbHVndSwgbWlzIG9sZWtzIHNhbWFsIGFqYWwga2EganVoZW5kbWF0ZXJqYWxpa3MgamEgbWlsbGUga29vZGkgc2Fha3Mga2FzdXRhZGEgcMO1aGphbmEgS2Vza2tvbm5hYWdlbnR1dXJpIGFuZG1lbWFhaWxtYXMgb3JpZW50ZWVyaXVtaXNla3MgamEgYXZhYW5kbWV0ZSBrYXN1dGFtaXNla3MuIFNvb21hYSBhbmRtZWx1Z3Ugb24gbcO1ZWxkdWQgbmVpbGUsIGtlcyBvbiBhbGxlcyBhbHVzdGFtYXMgbmluZyBzb292aXZhZCBsdXVhIGVuZGEgcmFrZW5kdXNpLXTDtsO2cmlpc3R1LCB0ZWhhIGFuYWzDvMO8c2UgdsO1aSBrYXN1dGFkYSBuZWlkIGFuZG1lZCBtdXVkZXMgaW5mb3PDvHN0ZWVtaWRlcy4gDQoNCkV0IHRlZ3UgZWkgb2xla3MgdsOkZ2EgaWdhdmEgamEgdGVobmlsaXNlIGp1aGVuZGlnYSB2YWxpc2ltZSBuw6RpdGVrcyDDvGhlIGtvbmtyZWV0c2UgdGVlbWEgamEgaHV2aW9iamVrdGkuIA0KDQoqKlRlZW1hOiBTb29tYWEqKg0KDQpTb29tYWEgb24gw7xrcyBodXZpdGF2YW1haWQgdmFhdGFtaXMtIGphIGtvZ2VtaXN2w6TDpHJzdXNpIEVlc3RpcywgbWlzIG11dXR1YiBhaW5hIHBvcHVsYWFyc2VtYWtzIGphIHNlZGEganVzdCB2aWllbmRhbCBhYXN0YWFqYWwuIFBhcmFrdSBpbG0gb24ga2VlcnVsaW5lIG7DpGh0dXMsIG1pcyBlcmluZWIgYWFzdGF0ZSBsw7Vpa2VzIG5pbmcgdmlpZXMgYWFzdGFhZWcgZWkgYWxnYSBraW5kbGEga3V1cMOkZXZhZ2EuIEFudHVkIGFuZG1lbHVndSBzaXNhbGRhYiBhbmRtZXDDtWhpc3Qgw7xsZXZhYWRldCBTb29tYWFzdCwgcMO1aGlmb29rdXNlZ2Egc3V1cnZlZSBhamFsZSBqYSBlZXNtw6RyZ2lrcyBvbiBhbmRhIHbDtWltYWxpa3VsdCBwYWxqdSBhdmFhbmRtZXRlZ2Egc2VvdHVkIGluZm90IMO8aGVzIGtvaGFzLiBTb29tYWEga8O8bGFzdGFqYSB2w7VpIGxvb2R1c3JldGtlIGtvcnJhbGRhamEgc29vdmliIHTDtWVuw6RvbGlzZWx0IHRhYmFkYSBzZWRhIGvDtWlnZSDDtWlnZW1hdCBhZWdhIGvDvGxhc3R1c2VrcyBlaGsga3VzIHN1dXJ2ZWUgdGFzZW1lZCBvbiBrw7VpZ2Uga8O1cmdlbWFkLiANCg0KKipLZWxsZWxlIHN1dW5hdHVkKioNCg0KQW5kbWVsdWd1IG9uIHN1dW5hdHVkIG1pdG1lbGUga2FzdXRhamFncnVwaWxlLg0KDQorIE5laWxlLCBrZXMgbMOkaGV2YWQgc29vbWFhZCBhdmFzdGFtYSBqYSB0YWhhdmFkIHJpaHRpZGEgc2VkYSBrw7VpZ2Ugw7VpZ2VtYXQgc3V1cnZlZSDDvGxldWp1dHVzdGUgYWVnYS4NCisgTG9vZHVzaHV2aWxpc3RlbGUsIGtlcyBtYWdhdmFkIG1haGEgw7xsZXVqdXR1c2VkLCBrdWlkIGzDpGhldmFkIG11dWwgYWphbCBTb29tYWFsZSBsb29kdXNlIGh1dmVzaWQgbmF1dGltYS4NCisgQW5kbWV0ZWFkbGFzZWQsIGFuZG1lYW5hbMO8w7x0aWt1ZCwgdHVkZW5naWQgamEgdGVhZHVyaWQsIGtlcyBzb292aXZhZCBhbmRtZWlkIHbDpMOkcmluZGFkYSBqYSBhbmFsw7zDvHNpZGEuDQorIElULWFyZW5kYWphZC9wcm9ncmFtbWVlcmlqYWQsIGV0dGV2w7V0amFkIHbDtWkga2VzIHZhamF2YWQgYW5kbWVpZCDDvGxlIG1hc2luLW1hc2luIGxpaWRlc2UuDQoNCktlc2trb25uYWFnZW50dXVyaSBhbmRtZXRlc3QgdHVsZWIgasOkcmplcGlkZXZhbHQganV1cmRlIHV1c2kgYXZhYW5kbWV0ZSB0ZWVudXNlaWQgamEgc2VlZ2EgYXZhYWRubWV0ZSBwb3B1bGFyaXNlZXJpbWlzZSBlZXNtw6RyZ2lrcyBvbiBzdXVyZW5kYWRhIGF2YWFuZG1ldGUga2FzdXRhbWlzdCBuaW5nIGFuZG1ldGVzdCB1dWUgdsOkw6RydHVzZSBsb29taXN0LiANCg0KKipBbmRtZWQqKg0KDQpBbmRtZXRlIGthc3V0YW1pc2UgbsOkaXRlZCBSLWlzIGlsbHVzdHJlZXJpYiBwcm90c2Vzc2ksIG1pZGEgdHVsZWIgbMOkYmlkYSwgZXQgYW5kbWVpZCBzYWFrcyBrYXN1dGFkYSB2w7VpIHbDpMOkcmluZGFkYSB0ZWlzdGUgb3NhcG9vbHRlIHBvb2x0LiBUYWtpc3R1c2VrcyB2w7VpYiBvbGxhIGFuZG1ldGVzdCBhcnVzYWFtaW5lIGphIMO1aWdldGUgYW5kbWVhbGxpa2F0ZSAib3RzYWRlIiBsZWlkbWluZS4gQW5kbWVsdWd1IGtvb3MgdmFzdGF2YSBrb29kaWdhIG9uIGxvb2R1ZCBzZWxsZSBwcm9ibGVlbWkgbGFoZW5kYW1pc2Vrcy4NCkFuZG1ldGVzdCBhcnVzYWFtaW5lIHbDtWliIG9sbGEgdmFsZGtvbm5hIHbDpGxpc2V0ZWxlIGthc3V0YWphdGVsZSBrZWVydWxpbmUgamEgc2VldMO1dHR1IG9sZW1lIGFudHVkIG7DpGl0ZSBwdWh1bCBsaXNhbnVkIG9odHJhbCBsaW5rZSBqYSBqdWhpc21hdGVyamFsZSBrb29kaSwgZXQgasOkcmdtaXNlZCBhbmRtZXRlIGthc3V0YWphZCBzYWFrc2lkIMO8bGVzIGxlaWRhIHZhamFsaWt1IGluZm8gbmluZyB0ZWFrc2lkIGt1aWRhcyBvbiDDvGxlcyBlaGl0YXR1ZCBtZWllIGFuZG1la2F0YWxvb2csIHNoIGFuZG1lc3Rpa2UvbGV2aXR1c2UgaW5mbywgYW5kbWVraXJqZWxkdXNlZCBqYSBhbmRtZXRlZW51c2VkLiBLYXN1dGF0dWQgb24gZXJpbmV2YWlkIGFuZG1laWQgZXJpbmV2YXRlc3QgYWxsaWthdGVzdCwgcGVhbWlzZWx0IGFuZG1ldGVlbnVzdGVuYSwgc2VhbGh1bGdhcyBydXVtaWFuZG1ldGVlbnVzZWlkLA0KDQpBbmRtZWx1Z3Ugc2lzYWxkYWIgasOkcmdtaXNpIGFuZG1laWQ6DQoNCisgSMO8ZHJvbG9vZ2lsaW5lIHNlaXJlDQorIEjDvGRyb2xvb2dpbGluZSBtdWRlbHByb2dub29zDQorIE1ldGVvcm9sb29naWxpbmUgc2VpcmUNCisgTWV0ZW9yb2xvb2dpbGluZSBhc3Vrb2hhcMO1aGluZSBwcm9nbm9vcw0KKyBTZWlyZWphYW1hZA0KKyBSYW1zYXJpIGFsYWQNCisgVm9vbHV2ZWVrb2d1ZA0KKyBKw6RydmVkDQorIE1hYS1hbWV0aSBhbHVza2FhcnQgKGhhbGx0b29uaWQpDQoNClNvb21hYSBzdXVydmVlIGFuZG1lbG9vIGphb2tzIHZhbGl0aSB2w6RsamEga2FrcyBvbHVsaXNlbWF0IGjDvGRyb21lZXRyaWFqYWFtYSBqYSBrb2xtIGzDpGhpbWF0IG1ldGVvcm9sb29naWFqYWFtYSAodmFhdGEga2FhcnRpKS4NCkxpc2FrcyBzYWFiIGx1Z2VkYSBzb29tYWEgcmFodnVzcGFyZ2kgamEgbG9vZHVzYWxhIGtvaHRhIGthIGtlc2trb25uYXBvcnRhYWxpc3QgbmluZyB2YWFkYXRhIHNlb3R1ZCBvYmpla3RlIGphIG11dWQga2Vza2tvbm5haW5mb3QuDQoNCisgW1Nvb21hYSBsb29kdXNhbGFdKGh0dHBzOi8vcmVnaXN0ZXIua2Vza2tvbm5hcG9ydGFhbC5lZS9yZWdpc3Rlci9pbnRlcm5hdGlvbmFsbHktaW1wb3J0YW50LWFyZWEvODk1MzUzMSkgDQorIFtTb29tYWEgUmFodnVzcGFya10oaHR0cHM6Ly9yZWdpc3Rlci5rZXNra29ubmFwb3J0YWFsLmVlL3JlZ2lzdGVyL2ludGVybmF0aW9uYWxseS1pbXBvcnRhbnQtYXJlYS84OTU3ODUxKQ0KDQoqKkFuZG1ldMO2w7Z0bHVzIGphIHNrcmlwdGlkKioNCg0KS29vZGkga2lyanV0YW1pbmUgZWkgcGVha3Mgb2xlbWEgaWdhIGtvcmQgbnVsbGlzdCBhbHVzdGFtaW5lLCB2YWlkIHbDtWlrcyBvbGxhIGhlYSBwcmFrdGlrYSBrb2hhc2VsdCB0YWFza2FzdXRhbWluZS5BbmRtZWxvb3Mgb24ga2FzdXRhdHVkIGVyaW5ldmF0IHTDvMO8cGkgYW5kbWVpZCBqYSBpZ2EgYW5kbWVzdGlrIG9uIG9tYSBzcGV0c2lpZmlsaXNlcyBmb3JtYWFkaXMgKG50IGt1dXDDpGV2YWRlIGZvcm1hYXQpIHNpaXMgc2VsbGUgYW5kbWVsb28ga29vZGkgdGFhc2thc3V0YW1pc2UgdHVsZW11c2VuYSBzYWFiIGrDpHJnbWluZSBhbmRtZXRlIGphIGtvb2RpIGthc3V0YWphIGhvaWRhIGtva2t1IGFlZyBqYSBuw6RydmUgYW5kbWV0w7bDtnRsdXNlIG9zYXMuDQpBbmRtZWxvbyBtw7V0ZSBvbiBhbmRhIHDDtWhpaW5mbyBhbmRtZXRlIGthc3V0YW1pc2Vrcywgc2VlZ2Egb24ga29vZCB2w7VpbWFsaWt1bHQgcHVoYXMgamEgbGlodG5lIG5pbmcgbWluaW1hYWxzZWx0IG9uIGthc3V0YXR1ZCBSLWkgc3BldHNpaWZpbGlzdCBzw7xudGFrc2l0LiBSIG9uIGvDvGxsYWx0a2kgbGlodG5lIHByb2dyYW1tZWVyaW1pc2tlZWwsIG1pcyBzb2JpYiBhbmRtZXRlYWR1c2VrcywgYW5kbWVhbmFsw7zDvHNpa3MgamEga2lpcmVsdCB2YWxtaXZhdGUgbGFoZW5kdXN0ZSBsb29taXNla3MgdsO1aSBwcm90b3TDvMO8cGltaXNla3MuIFNlbCBww7VoanVzZWwgb24ga2Egc2VlIGtvb2Qgw7xzbmEgYXJ1c2FhZGF2IGphIGthc3V0YXRhdiB2w7VpIMO8bGV2w7VldGF2IHRlaXN0ZXMgcHJvZ3JhbW1lZXJpbWlza2VlbHRlcyBqYSBrZXNra29uZGFkZXMuDQpLb29kIG9uIMOkcmEgdG9vZHVkIGFuZG1lbG9vIHNrcmlwdGlkZSBzZWt0c2lvb25pcyBuaW5nIHNlbGxlIGthc3V0YW1pc2VsIHR1bGVrcyB2YWFkYXRhIGthIGp1aGlzZWlkLg0KDQoqKkFuZG1ldGUgdsO1cmRsdXMgamEgcHJvZ25vb3MqKg0KDQpLb29kaSBsb2V0YXZ1c2UgamEgYXJ1c2FhZGF2dXNlIHRhZ2FtaXNla3Mgb24ga2FzdXRhdHVkIGxpaHRzYWlkIG7DpGl0ZWlkIGFuZG1ldGUgdsO1cmRsdXNla3MgamEga2FzdXRhdHVkIHBlYW1pc2VsdCBvbGVtYXNvbGV2YWlkIHByb2dub29zYW5kbWVpZC4NCktlZGEgaHV2aXRhYiB2b29sdWh1bGthZGUgamEgdGFzZW1ldGUgcHJvZ25vb3MgU29vbWFhIGvDvGxhc3RhbWlzZWwsIHbDtWlrcyBraW5kbGFzdGkgdmFhZGF0YSBLZXNra29ubmFhZ2VudHV1cmkgaMO8ZHJvbG9vZ2lsaXN0IGphIG1ldGVvcm9sb29naWxpc3QgbXVkZWxwcm9nbm9vc2kuDQpMaXNhdHVkIG9uIG3DtW5lZCBhbmRtZXbDtXJkbHVzZWQsIGV0IG7DpGlkYXRhIG5lbmRlIGFuZG1ldGUgYW5hbMO8w7xzaSBqYSB2w6TDpHJpbmRhbWlzZSB2w7VpbWFsdXNpIG5pbmcgYW5kYSBhbmRtZWxvbyBrYXN1dGFqYWxlIHbDtWltYWx1cyB0ZWhhIGlzZSBqw6RyZWxkdXNpLiANCkFuZG1ldGUga2FzdXRhbWlzZSBuw6RpZGlzZWQgb24gb2xlbWFzIGphIGlnYcO8a3Mgc2FhYiBhbmRtZWlkIGVkYXNpIGFuYWzDvMO8c2lkYSBqYSBsdXVhIGVuZGFsZSBzb2JpbGlrZSBwcm9nbm9vc211ZGVsZWlkIG5pbmcgdMOkaWVuZGFkYSBzZWxsZSBhbmRtZWxvbyBza3JpcHRlLg0KDQoqKktvbnRha3QqKg0KDQpbS2Vza2tvbm5hYWdlbnR1dXJdKGh0dHBzOi8va2Vza2tvbm5hYWdlbnR1dXIuZWUvKQ0KDQpNdXN0YW3DpGUgdGVlIDMzLCAxMDYxNiBUYWxsaW5uDQoNCiszNzIgNjY2IDA5MDENCg0KPGtsaWVuZGl0dWdpQGVudmlyLmVlPg0KDQoNCiMjIyMgSnVoaXMNCg0KKipLdWlkYXMga2FzdXRhZGEgc2tyaXB0ZSoqDQoNClNpaXQgc2VrdHNpb29uaXN0IGxlaWFkIGluZm8ga3VpZGFzIHRhYXNrYXN1dGFkYSBzZWxsZSBhbmRtZWxvbyBsb29taXNla3Mga2FzdXRhdHVkIGtvb2RpLg0KDQo+QW5kbWVkIG9uIHNlaXN1Z2EgMDQuMDQuMjAyNCBqYSBlaSB1dWVuZSBhdXRvbWFhdHNlbHQuIFNlZWdhIHR1bGViIGFuZG1laWQgdXVlbmRhZGEsIGV0IHNhYWRhIGFqYWtvaGFzZWQgZ3JhYWZpa3VkDQoNCktvb2Qga29vc25lYiAyIGZhaWxpc3QgKHNvb21hYS5SbWQsIEFuZG1lZC5SKQ0KDQpGYWlsaSBzb29tYWEuUm1kIHNhYWIgYWxsYSBsYWFkaWRhIGt1aSB2YWp1dGFkYSBww6Rpc2VzIG9sZXZhbCBudXB1bCAqKkNvZGUqKiBqYSB2YWxpZGEgICoqRG93bmxvYWQgUm1kKiogdsO1aSBzaWl0OiBgciB4ZnVuOjplbWJlZF9maWxlKCdzb29tYWEuUm1kJyx0ZXh0ID0gInNvb21hYS5SbWQiKWANCg0KRmFpbGkgQW5kbWVkLlIga29vZGkgc2FhYiBrb3BlZXJpZGEgasOkcmdtaXNlbHQgbWVuw7zDvHNha2lsdCAqKkFuZG1lZC5SKiogdsO1aSBhbGxhIGxhYWRpZGEgc2lpdDogYHIgeGZ1bjo6ZW1iZWRfZmlsZSgnQW5kbWVkLlInLHRleHQgPSAiQW5kbWVkLlIiKWANCg0KDQoNCkZhaWwgc29vbWFhLlJtZCBzaXNhbGRhYiBhaW51bHQgZ3JhYWZpa3V0ZSBsb29taXNla3MgdmFqYWxpa3Uga29vZGksIGt1aWQgbWl0dGUgYW5kbWV0ZSBzaXNzZWx1Z2VtaXNlIGphIHTDtsO2dGx1c2Uga29vZGlvc2EsIHNlc3Qgc2lpcyBsw6RoZWtzIGtvb2QgdsOkZ2EgcGlrYWtzIGphIHBvbGVrcyB0YWdhdHVkIGxvZXRhdnVzLiBGYWlsIEFuZG1lZC5SIHNpc2FsZGFiIGthIGdyYWFmaWt1dGUgbG9vbWlzZSBrb29kaSBiYWFzdGFzZW1lbCwgZXQgb2xla3MgbsOkaGEgdHVsZW11c2VkIChncmFhZmlrdWQsa2FhcnQpIGthIG5laWwsIGtlcyBmYWlsaSBzb29tYWEuUm1kIGVpIGthc3V0YS4NCg0KSnVoaXMgYW5kbWVsb28gdGFhc2xvb21pc2VrczoNCg0KMS4gVGVraXRhIHNrcmlwdCAiQW5kbWVkLlIiDQoyLiBMaXNhIGFsbG9sZXYga29vZCAoIkFuZG1lZC5SIiBzZWt0c2lvb25pc3QpIGVuZGEgZmFpbGkgIkFuZG1lZC5SIg0KMy4gSW5zdGFsbGVlcmkgdmFqYWxpa3VkIHRlZWdpZCAobGlicmFyeSksIFItc3R1ZGlvIHBha3ViIHNlZGEgdsO1aW1hbHVzdCBza3JpcHRpIHDDpGlzZXMgYXV0b21hYXRzZWx0DQo0LiBKb29rc3V0YSBBbmRtZWQuUiBza3JpcHRpDQo1LiBUw7VtYmEgYWxsYSBmYWlsIG5pbWVnYSBzb29tYWEuUm1kDQo2LiBWYWp1dGEgc29vbWFhLlJtZCBww6Rpc2VzICJydW4gYWxsIGNodW5rcyBiZWxvdyINCjcuIFBlYWxlIGtvb2RpIGpvb2tzdXRhbWlzdCB0dWxlYiBsdXVhIHbDpGxqdW5kIGthc3V0YWRlcyBrb25zb29saXMga8Okc2tsdXN0OnJtYXJrZG93bjo6cmVuZGVyKCJzb29tYWEuUm1kIikNCg0KYGBge3IgZWNobz1UUlVFLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFLCBldmFsPUZBTFNFfQ0Kcm1hcmtkb3duOjpyZW5kZXIoInNvb21hYS5SbWQiKQ0KYGBgDQoNCg0KDQojIyMjIEFuZG1lZC5SDQoNCktvb2RpIG7DpGdlbWlzZWtzIFZhanV0YSBwYXJlbWFsIHBvb2wgb2xldmFsIG51cHB1bCAic2hvdyINCg0KYGBge3IgZWNobz1UUlVFLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFLCBldmFsPUZBTFNFfQ0KDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojIyMjIEFuZG1ldMO2w7Z0bHVzZSBza3JpcHQgDQojIFNpc2FsZGFiIGF2YWFuZG1ldGUgYW5kbWV0ZWVudXN0ZSBrYXN1dGFtaXNlIG7DpGl0ZWlkIG5pbmcgdmlpdGVpZCBhbmRtZXRlIGtpcmplbGR1c3RlbGUgamEga2Vza2tvbmRhZGVsZSANCiMgTGlzYWtzIHBlYW1pc2kgYW5kbWV0w7bDtnRsdXNlIHRlZ2V2dXNpLCBhbmRtZXRlIHbDtXJkbHVzaSwgZ3JhYWZpa3V0ZSBsb29taXN0IGphIGthYXJ0aWRlIHRlZ2VtaXNlIG7DpGl0ZWlkDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojIyMgSMO8ZHJvbG9vZ2lsaXNlIHNlaXJlIGFuZG1lZA0KIyMgTG9lbWUgc2lzc2UgaMO8ZHJvbG9vZ2lsaXNlIHNlaXJlIGFuZG1lZCAoaHR0cHM6Ly9rZXNra29ubmFwb3J0YWFsLmVlL2V0L2F2YWFuZG1lZC9rZXNra29ubmEtamEtaWxtYS12YWxka29ubmEtYW5kbWV0ZWVudXNlZCkNCiMgw5xsZGluZSBww6RyaW5nIGFuZG1ldGVsZSwgZXQgbsOkaGEgbWlzIHNlYWwgc2VlcyBvbiBqYSBrdW5hIHDDpHJpbmd1bWFodCBvbiBwaWlyYXR1ZCBzaWlzIGZpbHRyaXRlZ2EgKGxpbWlpdCAyMDAwMCByaWRhKQ0KbGlicmFyeShqc29ubGl0ZSkNCmh5ZHJvX2RhdGEgPC0gZnJvbUpTT04oImh0dHBzOi8va2Vza2tvbm5hYW5kbWVkLmVudmlyLmVlL2ZfaHlkcm9zZWlyZT90aW1lbGluZV90c191dGM9bHQuMjAyMy0wMS0wMlQwMzowMDowMCZ0aW1lbGluZV90c191dGM9Z3QuMjAyMy0wMS0wMVQyMzowMDowMCZqYWFtX2tvb2Q9ZXEuNDExMzciKQ0KDQojIE1laWQgaHV2aXRhYiBhaW50IHRlYXR1ZCBvc2EgYW5kbWVzdGlrdXN0LCBzZWVnYSB2YWF0YW1lIG1pZGEgc2Fha3MgdsOkbGphIHJvb2tpZGENCm5hbWVzKGh5ZHJvX2RhdGEpDQoNCiMgQW5kbWVraXJqZWxkdXNlc3QgcMO1aGphbCB2w7Vpa3MgbWVpZCBodXZpdGFkYSB0dW5uaWFuZG1ldGVzdCB2ZWV0YXNlKGNtKSBqYSB0dW5uaSDDpHJhdm9vbChtMy9zKQ0KI2h0dHBzOi8va2Vza2tvbm5hcG9ydGFhbC5lZS9ldC9hdmFhbmRtZWQvaHVkcm9sb29naWxpc2Utc2VpcmUtYW5kbWVzdGlrL2h1ZHJvbG9vZ2lsaXNlLXNlaXJlLWFuZG1lc3Rpa3Uta2lyamVsZHVzDQoNCiMgVmFhdGFtZSwgbWlzIHBhcmFtZWV0cmlkIG1laWwgYW5kbWV0ZXMgdGVnZWxpa3VsdCBvbg0KdW5pcXVlKGh5ZHJvX2RhdGEkYWVncmlkYV9uaW1pKQ0KDQojIFbDtXRhbWUgYWludWx0IG1laWQgaHV2aXRhdmEgdmFsaWt1IGFnYSBvbiB2YWphIG9uIGtvZGVlcmlkYSDDtWlnZXN0aSBhbmRtZXDDpHJpbmcgKGh0dHBzOi8vd3d3Lnczc2Nob29scy5jb20vdGFncy9yZWZfdXJsZW5jb2RlLkFTUCkgDQpoeWRyb19kYXRhIDwtIGZyb21KU09OKCJodHRwczovL2tlc2trb25uYWFuZG1lZC5lbnZpci5lZS9mX2h5ZHJvc2VpcmU/dGltZWxpbmVfdHNfdXRjPWd0LjIwMjMtMDktMDFUMjM6MDA6MDAmYWVncmlkYV9uaW1pPWluLihXTCUyMG1pbixXTCUyMG1heCwlQzMlODRyYXZvb2wrYXZnKSZqYWFtX2tvb2Q9ZXEuNDExMzciKQ0KDQojIE1laWwgdmFsaXR1ZCBhaW51bHQgQWVzb28gaMO8ZHJvbWVldHJpYWphYW0sIHNlZWdhIHBvbGUgdmFqYSBqYWFtYWRlIMO8bGRhbmRtZWlkDQpoeWRyb19kYXRhPWh5ZHJvX2RhdGFbLGMoInRpbWVsaW5lX3RzX3V0YyIsICJhZWdyaWRhX25pbWkiLCJ2YWFydHVzIiApXQ0KDQojIFBhbmVtZSBhbmRtZWQga8O1cnZ1dGkgw7xodGUgdGFiZWxpc3NlLCBldCBzYWFrcyBncmFhZmlrdSB0ZWhhDQpsaWJyYXJ5KHRpZHlyKQ0KaHlkcm9fZGF0YV8xPXNwcmVhZChoeWRyb19kYXRhLCBrZXkgPSBhZWdyaWRhX25pbWksIHZhbHVlID0gdmFhcnR1cykNCg0KIyBLb250cm9sbGltZSDDvGxlLCBrYXMgb24ga8O1aWsgdW5pa2FhbG5lDQpzdW0oZHVwbGljYXRlZChoeWRyb19kYXRhXzEkdGltZWxpbmVfdHNfdXRjKSkNCg0KIyBLdXVww6RldiBvbiBlcmlsaXNlcyB2b3JtaXMgamEgdHVsZWIgdmFldmEgbsOkaGEsIGV0IHNhYWtzIG5laXN0IGRhdGV0aW1lIHRlaGEgbWlkYSB2YWphYiBncmFhZmlrIA0KaHlkcm9fZGF0YV8xJHRpbWVsaW5lX3RzX3V0Yz0gZ3N1YigiVCIsIiAiLGh5ZHJvX2RhdGFfMSR0aW1lbGluZV90c191dGMpDQpoeWRyb19kYXRhXzEkdGltZWxpbmVfdHNfdXRjPSBhcy5QT1NJWGx0KGh5ZHJvX2RhdGFfMSR0aW1lbGluZV90c191dGMsIGZvcm1hdD0nJVktJW0tJWQgJUg6JU06JVMnLHR6ID0gIlVUQyIpDQoNCiMjIFRlZW1lIGdyYWFmaWt1ZA0KIyDDhHJhdm9vbA0KbGlicmFyeShkeWdyYXBocykNCmR5Z3JhcGgoaHlkcm9fZGF0YV8xWyxjKCJ0aW1lbGluZV90c191dGMiLCLDhHJhdm9vbCBhdmciKSxdLA0KICAgICAgICBtYWluID0gIsOEcmF2b29sIGtlc2ttaW5lIiwgDQogICAgICAgIHlsYWIgPSAiVHVubmkga2Vza21pbmUgw6RyYXZvb2wsIG0zL3MiKSAlPiUNCiAgICBkeU9wdGlvbnMoZmlsbEdyYXBoID0gVFJVRSwgZmlsbEFscGhhID0gMC40KQ0KIyBHcmFhZmlrdSBqw6RyZ2kgb24gYW5kbWV0ZXMgMTZuZGFsIGphIDE3bmRhbCBhdWsgc2Vlcw0KDQojIFZlZXRhc2UNCmxpYnJhcnkoZHlncmFwaHMpDQpkeWdyYXBoKGh5ZHJvX2RhdGFfMVssYygidGltZWxpbmVfdHNfdXRjIiwiV0wgbWF4IiwiV0wgbWluIiksXSwNCiAgICAgICAgbWFpbiA9ICJUdW5uaSBtYXggamEgbWluIHZlZXRhc2UiLCANCiAgICAgICAgeWxhYiA9ICJ2ZWV0YXNlLCBjbSIpICU+JQ0KICAgIGR5T3B0aW9ucyhmaWxsR3JhcGggPSBUUlVFLCBmaWxsQWxwaGEgPSAwLjQpDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyMjIEtsaWltYSBhbmRtZWQNCiMjIExvZW1lIHNpc3NlIGtsaWltYSBhbmRtZWQgKGh0dHBzOi8va2Vza2tvbm5hcG9ydGFhbC5lZS9ldC9hdmFhbmRtZWQva2Vza2tvbm5hLWphLWlsbWEtdmFsZGtvbm5hLWFuZG1ldGVlbnVzZWQpDQojIMOcbGRpbmUgcMOkcmluZyBhbmRtZXRlbGUsIGV0IG7DpGhhIG1pcyBzZWFsIHNlZXMgb24gamEga3VuYSBww6RyaW5ndW1haHQgb24gcGlpcmF0dWQgc2lpcyBmaWx0cml0ZWdhIChsaW1paXQgMjAwMDAgcmlkYSkNCmxpYnJhcnkoanNvbmxpdGUpDQprbGlpbWFfZGF0YSA8LSBmcm9tSlNPTigiaHR0cHM6Ly9rZXNra29ubmFhbmRtZWQuZW52aXIuZWUvZl9rbGlpbWFfdHVuZD9hYXN0YT1lcS4yMDIzJmt1dT1ndC4xMCZwYWV2PWx0LjgmamFhbV9rb29kPWluLihBSlZJTEowMSxBSlBBUk4wMSxBSlRVUkkwMSkiKQ0KDQojIE1laWQgaHV2aXRhYiBhaW50IHRlYXR1ZCBvc2EgYW5kbWVzdGlrdXN0LCBzZWVnYSB2YWF0YW1lIG1pZGEgc2Fha3MgdsOkbGphIHJvb2tpZGENCm5hbWVzKGtsaWltYV9kYXRhKQ0KDQojIEFuZG1la2lyamVsZHVzZSDDvHRsZWIgbWVpbGUsIGV0IG1laWQgdsO1aWtzIGh1dml0YWRhIHR1bm5pYW5kbWV0ZXMgdMOkaXN0dW5uaSDDtWh1dGVtcGVyYXR1dXIgbmluZyBzYWRlbWV0ZSBzdW1tYQ0KI2h0dHBzOi8va2Vza2tvbm5hcG9ydGFhbC5lZS9ldC9hdmFhbmRtZWQva2xpaW1hYW5kbWVzdGlrL2tsaWltYWFuZG1lc3Rpa3Uta2lyamVsZHVzDQoNCiMgVmFhdGFtZSwgbWlzIHBhcmFtZWV0cmlkIG1laWwgYW5kbWV0ZXMgdGVnZWxpa3VsdCBvbg0KdW5pcXVlKGtsaWltYV9kYXRhJGVsZW1lbnRfa29vZCkNCg0KIyBWw7V0YW1lIGFpbnVsdCBtZWlkIGh1dml0YXZhIHZhbGlrdSBqYSB0ZWVtZSBqYWFtYXDDtWhpc2VkIHDDpHJpbmd1ZA0KIyBLdW5hIHDDpHJpbmd1IGxpbWlpdCBvbiAyMDAwMCByaWRhIHNpaXMgcGVhbWUgcMOkcmluZ3VkIHTDvGtlbGRhbWEgbsOkaXRhamF0ZSBqYSBqYWFtYWRlIGzDtWlrZXMNCg0KIyBUw7xyaSBtZXRlb3JvbG9vZ2lhamFhbQ0Ka2xpaW1hX2RhdGFfMSA8LSBmcm9tSlNPTigiaHR0cHM6Ly9rZXNra29ubmFhbmRtZWQuZW52aXIuZWUvZl9rbGlpbWFfdHVuZD9hYXN0YT1pbi4oMjAyMywyMDI0KSZqYWFtX2tvb2Q9ZXEuQUpUVVJJMDEmZWxlbWVudF9rb29kPWVxLlRBIikNCmtsaWltYV9kYXRhXzIgPC0gZnJvbUpTT04oImh0dHBzOi8va2Vza2tvbm5hYW5kbWVkLmVudmlyLmVlL2Zfa2xpaW1hX3R1bmQ/YWFzdGE9aW4uKDIwMjMsMjAyNCkmamFhbV9rb29kPWVxLkFKVFVSSTAxJmVsZW1lbnRfa29vZD1lcS5QUjFIIikNCiMgTGlpZGFtZSBhbmRtZWQga29ra3UgamEgcm9vZ2ltZSB2w6RsamEgbWl0dGV2YWphbGlrdWQgdsOkbGphZA0Ka2xpaW1hX2RhdGFfdD1tZXJnZSgNCiAgICBrbGlpbWFfZGF0YV8xWyxjKCJhYXN0YSIsImt1dSIsInBhZXYiLCJ0dW5kIiwidmFhcnR1cyIpXSwgDQogICAga2xpaW1hX2RhdGFfMlssYygiYWFzdGEiLCJrdXUiLCJwYWV2IiwidHVuZCIsInZhYXJ0dXMiKV0sIA0KICAgIGJ5PWMoImFhc3RhIiwia3V1IiwicGFldiIsInR1bmQiKSxhbGw9VCxzdWZmaXhlcyA9IGMoIlRBIiwiUFIxSCIpKQ0KbmFtZXMoa2xpaW1hX2RhdGFfdCkgPSBjKCJhYXN0YSIsImt1dSIsInBhZXYiLCJ0dW5kIiwiVEEiLCJQUjFIIikNCg0KIyBQw6RybnUgcmFubmlrdWphYW0NCmtsaWltYV9kYXRhXzEgPC0gZnJvbUpTT04oImh0dHBzOi8va2Vza2tvbm5hYW5kbWVkLmVudmlyLmVlL2Zfa2xpaW1hX3R1bmQ/YWFzdGE9aW4uKDIwMjMsMjAyNCkmamFhbV9rb29kPWVxLkFKUEFSTjAxJmVsZW1lbnRfa29vZD1lcS5UQSIpDQprbGlpbWFfZGF0YV8yIDwtIGZyb21KU09OKCJodHRwczovL2tlc2trb25uYWFuZG1lZC5lbnZpci5lZS9mX2tsaWltYV90dW5kP2Fhc3RhPWluLigyMDIzLDIwMjQpJmphYW1fa29vZD1lcS5BSlBBUk4wMSZlbGVtZW50X2tvb2Q9ZXEuUFIxSCIpDQojIExpaWRhbWUgYW5kbWVkIGtva2t1IGphIHJvb2dpbWUgdsOkbGphIG1pdHRldmFqYWxpa3VkIHbDpGxqYWQNCmtsaWltYV9kYXRhX3A9bWVyZ2UoDQogICAga2xpaW1hX2RhdGFfMVssYygiYWFzdGEiLCJrdXUiLCJwYWV2IiwidHVuZCIsInZhYXJ0dXMiKV0sIA0KICAgIGtsaWltYV9kYXRhXzJbLGMoImFhc3RhIiwia3V1IiwicGFldiIsInR1bmQiLCJ2YWFydHVzIildLCANCiAgICBieT1jKCJhYXN0YSIsImt1dSIsInBhZXYiLCJ0dW5kIiksYWxsPVQsc3VmZml4ZXMgPSBjKCJUQSIsIlBSMUgiKSkNCm5hbWVzKGtsaWltYV9kYXRhX3ApID0gYygiYWFzdGEiLCJrdXUiLCJwYWV2IiwidHVuZCIsIlRBIiwiUFIxSCIpDQoNCiMgVmlsamFuZGkgbWV0ZW9yb2xvb2dpYWphYW0NCmtsaWltYV9kYXRhXzEgPC0gZnJvbUpTT04oImh0dHBzOi8va2Vza2tvbm5hYW5kbWVkLmVudmlyLmVlL2Zfa2xpaW1hX3R1bmQ/YWFzdGE9aW4uKDIwMjMsMjAyNCkmamFhbV9rb29kPWVxLkFKVklMSjAxJmVsZW1lbnRfa29vZD1lcS5UQSIpDQprbGlpbWFfZGF0YV8yIDwtIGZyb21KU09OKCJodHRwczovL2tlc2trb25uYWFuZG1lZC5lbnZpci5lZS9mX2tsaWltYV90dW5kP2Fhc3RhPWluLigyMDIzLDIwMjQpJmphYW1fa29vZD1lcS5BSlZJTEowMSZlbGVtZW50X2tvb2Q9ZXEuUFIxSCIpDQojIExpaWRhbWUgYW5kbWVkIGtva2t1IGphIHJvb2dpbWUgdsOkbGphIG1pdHRldmFqYWxpa3VkIHbDpGxqYWQNCmtsaWltYV9kYXRhX3Y9bWVyZ2UoDQogICAga2xpaW1hX2RhdGFfMVssYygiYWFzdGEiLCJrdXUiLCJwYWV2IiwidHVuZCIsInZhYXJ0dXMiKV0sIA0KICAgIGtsaWltYV9kYXRhXzJbLGMoImFhc3RhIiwia3V1IiwicGFldiIsInR1bmQiLCJ2YWFydHVzIildLCANCiAgICBieT1jKCJhYXN0YSIsImt1dSIsInBhZXYiLCJ0dW5kIiksYWxsPVQsc3VmZml4ZXMgPSBjKCJUQSIsIlBSMUgiKSkNCm5hbWVzKGtsaWltYV9kYXRhX3YpID0gYygiYWFzdGEiLCJrdXUiLCJwYWV2IiwidHVuZCIsIlRBIiwiUFIxSCIpDQoNCiMgUHVoYXN0YW1lIHTDtsO2bGF1ZGENCnJtKGtsaWltYV9kYXRhXzEsa2xpaW1hX2RhdGFfMikNCg0KIyBOb3JtYWxpc2VlcmltZSBhamFsaXNlIG3DtcO1dG1lIGphIHZpaW1lIHNlbGxlIGRhdGV0aW1lIGZvcm1hYXRpLCBldCBzYWFrcyBncmFhZmlrdWlkIHRlaGENCmtsaWltYV9kYXRhX3QkdGltZWxpbmVfdHNfdXRjPSBwYXN0ZTAoa2xpaW1hX2RhdGFfdCRhYXN0YSwiLSIsa2xpaW1hX2RhdGFfdCRrdXUsIi0iLGtsaWltYV9kYXRhX3QkcGFldiwiICIsa2xpaW1hX2RhdGFfdCR0dW5kLCI6MDA6MDAiKQ0Ka2xpaW1hX2RhdGFfcCR0aW1lbGluZV90c191dGM9IHBhc3RlMChrbGlpbWFfZGF0YV9wJGFhc3RhLCItIixrbGlpbWFfZGF0YV9wJGt1dSwiLSIsa2xpaW1hX2RhdGFfcCRwYWV2LCIgIixrbGlpbWFfZGF0YV9wJHR1bmQsIjowMDowMCIpDQprbGlpbWFfZGF0YV92JHRpbWVsaW5lX3RzX3V0Yz0gcGFzdGUwKGtsaWltYV9kYXRhX3YkYWFzdGEsIi0iLGtsaWltYV9kYXRhX3Yka3V1LCItIixrbGlpbWFfZGF0YV92JHBhZXYsIiAiLGtsaWltYV9kYXRhX3YkdHVuZCwiOjAwOjAwIikNCg0KIyBLdXZhbWUgYW5kbWVkIGV0IG7DpGhhIG1pcyB0b2ltdWIgZ3JhYWZpa3VsDQprbGlpbWFfZGF0YV90JHRpbWVsaW5lX3RzX3V0Yz0gYXMuUE9TSVhsdChrbGlpbWFfZGF0YV90JHRpbWVsaW5lX3RzX3V0YywgZm9ybWF0PSclWS0lbS0lZCAlSDolTTolUycsdHogPSAiVVRDIikNCmtsaWltYV9kYXRhX3AkdGltZWxpbmVfdHNfdXRjPSBhcy5QT1NJWGx0KGtsaWltYV9kYXRhX3AkdGltZWxpbmVfdHNfdXRjLCBmb3JtYXQ9JyVZLSVtLSVkICVIOiVNOiVTJyx0eiA9ICJVVEMiKQ0Ka2xpaW1hX2RhdGFfdiR0aW1lbGluZV90c191dGM9IGFzLlBPU0lYbHQoa2xpaW1hX2RhdGFfdiR0aW1lbGluZV90c191dGMsIGZvcm1hdD0nJVktJW0tJWQgJUg6JU06JVMnLHR6ID0gIlVUQyIpDQoNCiMjIFRlZW1lIGdyYWFmaWt1ZA0KIyBLdW5hIHRlbXBlcmF0dXVyIGphIHNhZGVtZWQgb24gaMOkc3RpIHbDtXJyZWxkYXZhZCBlcmluZXZhdGUgYXN1a29oYXRkZSBsw7Vpa2VzIHNpaXMgcGFuZW1lIGphYW1hZGUgYW5kbWVkIGtva2t1IG7DpGl0YWphIGFsdXNlbA0KDQojIMO1aHV0ZW1wIHTDpGlzdHVubmlsDQprbGlpbWFfZGF0YV9UQSA9bWVyZ2Uoa2xpaW1hX2RhdGFfdFssYygidGltZWxpbmVfdHNfdXRjIiwiVEEiKV0sa2xpaW1hX2RhdGFfcFssYygidGltZWxpbmVfdHNfdXRjIiwiVEEiKV0sYnk9InRpbWVsaW5lX3RzX3V0YyIpDQprbGlpbWFfZGF0YV9UQSA9bWVyZ2Uoa2xpaW1hX2RhdGFfVEEsa2xpaW1hX2RhdGFfdlssYygidGltZWxpbmVfdHNfdXRjIiwiVEEiKV0sYnk9InRpbWVsaW5lX3RzX3V0YyIpDQpuYW1lcyhrbGlpbWFfZGF0YV9UQSk9YygidGltZWxpbmVfdHNfdXRjIiwiVMO8cmkiLCJQw6RybnUiLCJWaWxqYW5kaSIpDQpsaWJyYXJ5KGR5Z3JhcGhzKQ0KZHlncmFwaChrbGlpbWFfZGF0YV9UQSkgJT4lDQogICAgZHlPcHRpb25zKGZpbGxHcmFwaCA9IFRSVUUsIGZpbGxBbHBoYSA9IDAuMikNCg0KIyDDnGhlIHR1bm5pIHNhZGVtZXRlIHN1bW1hDQprbGlpbWFfZGF0YV9QUjFIID1tZXJnZShrbGlpbWFfZGF0YV90WyxjKCJ0aW1lbGluZV90c191dGMiLCJQUjFIIildLGtsaWltYV9kYXRhX3BbLGMoInRpbWVsaW5lX3RzX3V0YyIsIlBSMUgiKV0sYnk9InRpbWVsaW5lX3RzX3V0YyIpDQprbGlpbWFfZGF0YV9QUjFIID1tZXJnZShrbGlpbWFfZGF0YV9QUjFILGtsaWltYV9kYXRhX3ZbLGMoInRpbWVsaW5lX3RzX3V0YyIsIlBSMUgiKV0sYnk9InRpbWVsaW5lX3RzX3V0YyIpDQpuYW1lcyhrbGlpbWFfZGF0YV9QUjFIKT1jKCJ0aW1lbGluZV90c191dGMiLCJUw7xyaSIsIlDDpHJudSIsIlZpbGphbmRpIikNCmxpYnJhcnkoZHlncmFwaHMpDQpkeWdyYXBoKGtsaWltYV9kYXRhX1BSMUgpDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyMjIEFuZG1ldGUgdsO1cmRsdXMNCiMjIFBhbmVtZSBow7xkcm9sb29naWxpc2VkIGphIG1ldGVvcm9sb29naWxpc2VkIGFuZG1lZCBrb2trdSB2w7VyZGx1c2UgamFva3MNCmtsaWltYV9rb29zPSBtZXJnZShrbGlpbWFfZGF0YV9UQSxrbGlpbWFfZGF0YV9QUjFILGJ5PSJ0aW1lbGluZV90c191dGMiLHN1ZmZpeGVzID0gYygiLlRBIiwiLlBSMUgiKSkNCmtsaWltYV9rb29zPSBtZXJnZShrbGlpbWFfa29vcyxoeWRyb19kYXRhXzEsYnk9InRpbWVsaW5lX3RzX3V0YyIpDQojIFBPU0lYbHQgdHVsZWIgbXV1dGEgUE9TSVhjdCBmb3JtYWF0aQ0Ka2xpaW1hX2tvb3MkdGltZWxpbmVfdHNfdXRjPSBhcy5QT1NJWGN0KGtsaWltYV9rb29zJHRpbWVsaW5lX3RzX3V0YykNCiMgRWVtYWxkYW1lIGjDvGRyb2xvb2dpbGlzdGVzIGFuZG1ldGVzIG9sZXZhIGF1Z3UNCmtsaWltYV9rb29zPSBrbGlpbWFfa29vc1tjb21wbGV0ZS5jYXNlcyhrbGlpbWFfa29vcyksXQ0KIyMga29ycmVsYXRzaW9vbg0KdHVsZW11cz1jb3Ioa2xpaW1hX2tvb3NbLC0xXSkNCg0KIyBUZWVtZSBrb3JyZWxhdHNpb29uaSBncmFhZmlrdSBldCBuw6RoYSBhbmRtZXRlIGVyaW5ldnVzaQ0KbGlicmFyeShwbG90bHkpDQpwbG90X2x5KHg9Y29sbmFtZXModHVsZW11cyksIA0KICAgICAgICB5PXJvd25hbWVzKHR1bGVtdXMpLA0KICAgICAgICB6ID0gdHVsZW11cywgDQogICAgICAgIHR5cGUgPSAiaGVhdG1hcCIsDQogICAgICAgIHphdXRvID0gRiwgem1pbiA9IDAsIHptYXggPSAxLA0KICAgICAgICBjb2xvcnMgPSBjb2xvclJhbXAoYygicmVkIiwgImdyZWVuIikpKSAlPiUNCiAgICBsYXlvdXQobWFyZ2luID0gbGlzdChsPTEyMCkpDQoNCiMgQW5kbWVkIG9uIGtvaGF0aSBzdWh0ZWxpc2VsdCB2w7VycmVsZGFtYXR1ZCwgc2VzdCBvbiBlcmluZXZhIHNrYWFsYWdhIGphIHR1bGVrcyBub3JtYWxpc2VlcmlkYQ0KDQojIyBOb3JtYWxpc2VlcmltZSBhbmRtZWQga2FzdXRhbWUgc2NhbGUoKSBqYSByb2xsbWVhbiBmdW5rdHNpb29uZSBsb2V0YXZhIGdyYWFmaWt1IHNhYW1pc2Vrcw0KbGlicmFyeSh6b28pDQp4MT1zY2FsZShrbGlpbWFfa29vc1ssYyg4LDksMTApXSkNCngxPWNiaW5kKGtsaWltYV9rb29zWywidGltZWxpbmVfdHNfdXRjIl0sYXMuZGF0YS5mcmFtZSh4MSkpDQp4Mj1yb2xsbWVhbihzY2FsZShyb3dNZWFucyhrbGlpbWFfa29vc1ssYygyLDMsNCldKSksMzAsZmlsbCA9IDAsYWxpZ24gPSJyaWdodCIgKQ0KeDI9Y2JpbmQoa2xpaW1hX2tvb3NbLCJ0aW1lbGluZV90c191dGMiXSxhcy5kYXRhLmZyYW1lKHgyKSkNCm5hbWVzKHgyKT1jKCJrbGlpbWFfa29vc1ssIFwidGltZWxpbmVfdHNfdXRjXCJdIiwiVEEiKQ0KdHVsZW11cz0gbWVyZ2UoeDEseDIsYnk9ImtsaWltYV9rb29zWywgXCJ0aW1lbGluZV90c191dGNcIl0iKQ0KDQojIFRlZW1lIG5vcm1hbGlzZWVyaXR1ZCBhbmRtZXRlZ2EgZ3JhYWZpa3UNCmxpYnJhcnkoZHlncmFwaHMpDQpkeWdyYXBoKHR1bGVtdXMsDQogICAgICAgIG1haW4gPSAiTm9ybWFsaXNlZXJpdHVkIGFuZG1lZCIsIA0KICAgICAgICB5bGFiID0gIk5vcm1hbGlzZWVyaXR1ZCB2w6TDpHJ0dXMiKSU+JQ0KICAgIGR5UmFuZ2VTZWxlY3RvcigpJT4lDQogICAgZHlSb2xsZXIocm9sbFBlcmlvZCA9IDApJT4lDQogICAgZHlPcHRpb25zKGZpbGxHcmFwaCA9IFRSVUUsIGZpbGxBbHBoYSA9IDAuMikNCg0KDQojIyMgVsO1cmRsZW1lIHZlZXRhc2VtZXRlIGFuZG1laWQgNSBhYXN0YSBsw7Vpa2VzDQojIyBIw7xkcm8gYW5kbWVkIEVzdE1vZGVsaXN0DQpsaWJyYXJ5KGpzb25saXRlKQ0KIyBILXZlZXRhc2UsIFEtdm9vbHVodWxrLCBULXZlZXRlbXBlcmF0dXVyDQpoeWRyb19Fc3RNb2RlbF9yaWlzYSA8LSBmcm9tSlNPTigiaHR0cHM6Ly9lc3Rtb2RlbC5lbnZpci5lZS9zdGF0aW9ucy9TSkE0Mzg1MDAwL3N0YXRpc3RpY3M/cGFyYW1ldGVyPUgmc3RhcnQteWVhcj0yMDE5JnRpbWUtc3RlcD1QMUQiKSAjIFJpaXNhDQpoeWRyb19Fc3RNb2RlbF9yaWlzYSR0aW1lbGluZV90c191dGM9IGFzLlBPU0lYbHQoaHlkcm9fRXN0TW9kZWxfcmlpc2Ekc3RhcnREYXRlLCBmb3JtYXQ9JyVZLSVtLSVkJyx0eiA9ICJVVEMiKQ0KaHlkcm9fRXN0TW9kZWxfcmlpc2E9aHlkcm9fRXN0TW9kZWxfcmlpc2FbLGMoInRpbWVsaW5lX3RzX3V0YyIsICJtZWFuVmFsdWUiKV0NCg0KIyBMb29tZSBhYXN0YSwga3V1IGphIHDDpGV2YSBlcmxhZGkgZXQgc2Fha3MgbHV1YSB2w7VyZGx1c2kgDQpsaWJyYXJ5KGx1YnJpZGF0ZSkNCmh5ZHJvX0VzdE1vZGVsX3JpaXNhJGFhc3RhPSB5ZWFyKGh5ZHJvX0VzdE1vZGVsX3JpaXNhJHRpbWVsaW5lX3RzX3V0YykNCmh5ZHJvX0VzdE1vZGVsX3JpaXNhJGt1dT0gbW9udGgoaHlkcm9fRXN0TW9kZWxfcmlpc2EkdGltZWxpbmVfdHNfdXRjKQ0KaHlkcm9fRXN0TW9kZWxfcmlpc2EkcGFldj0gZGF5KGh5ZHJvX0VzdE1vZGVsX3JpaXNhJHRpbWVsaW5lX3RzX3V0YykNCg0KIyBOb3JtYWxpc2VlcmltZSBhamFsaXNlIG3DtcO1dG1lIA0KaHlkcm9fRXN0TW9kZWxfcmlpc2EkdGltZWxpbmVfdHNfdXRjPSBwYXN0ZTAoaHlkcm9fRXN0TW9kZWxfcmlpc2Eka3V1LCItIixoeWRyb19Fc3RNb2RlbF9yaWlzYSRwYWV2KQ0KDQojIFZpc2thbWUgdsOkbGphIMO8bGVsaWlnc2VkIHbDpGxqYWQgYWdhIGrDpHRhbWUgc2lzc2Uga3V1IGphIHDDpGV2YSwgZXQgasOkcmpla29yZCBzYXNzaSBlaSBsw6RoZWtzDQpoeWRyb19Fc3RNb2RlbF9yaWlzYT1oeWRyb19Fc3RNb2RlbF9yaWlzYVssYygiYWFzdGEiLCJrdXUiLCJwYWV2IiwidGltZWxpbmVfdHNfdXRjIiwibWVhblZhbHVlIildDQoNCiMgUGFuZW1lIGFuZG1lZCBrw7VydnV0aSDDvGh0ZSB0YWJlbGlzc2UsIGV0IHNhYWtzIGdyYWFmaWt1IHRlaGENCmxpYnJhcnkodGlkeXIpDQpoeWRyb19Fc3RNb2RlbF9yaWlzYT1zcHJlYWQoaHlkcm9fRXN0TW9kZWxfcmlpc2EsIGtleSA9IGFhc3RhLCB2YWx1ZSA9IG1lYW5WYWx1ZSkNCg0KIyBFZW1hbGRhbWUga3V1IGphIHDDpGV2YQ0KaHlkcm9fRXN0TW9kZWxfcmlpc2E9aHlkcm9fRXN0TW9kZWxfcmlpc2FbLGMoMzpuY29sKGh5ZHJvX0VzdE1vZGVsX3JpaXNhKSldDQoNCiNrbGlpbWFfZGF0YV9QQSR0aW1lbGluZV90c191dGM9IGFzLlBPU0lYbHQoa2xpaW1hX2RhdGFfUEEkdGltZWxpbmVfdHNfdXRjLCBmb3JtYXQ9JyVtLSVkJyx0eiA9ICJVVEMiKQ0KIyBFdCBncmFhZmlrIG9sZWtzIHB1aGFzIGphIGFydXNhYWRhdiBhcnZ1dGFtZSBtaW4sbWF4IGphIGtlc2ttaXNlIHbDpMOkcnR1c2UNCmh5ZHJvX0VzdE1vZGVsX3JpaXNhJG1lZGlhbiA9IGFwcGx5KGh5ZHJvX0VzdE1vZGVsX3JpaXNhWyxjKDI6bmNvbChoeWRyb19Fc3RNb2RlbF9yaWlzYSkpXSwgMSwgbWVkaWFuLCBuYS5ybT1GKQ0KaHlkcm9fRXN0TW9kZWxfcmlpc2EkbWluID0gYXBwbHkoaHlkcm9fRXN0TW9kZWxfcmlpc2FbLGMoMjpuY29sKGh5ZHJvX0VzdE1vZGVsX3JpaXNhKSldLCAxLCBtaW4sIG5hLnJtPUYpDQpoeWRyb19Fc3RNb2RlbF9yaWlzYSRtYXggPSBhcHBseShoeWRyb19Fc3RNb2RlbF9yaWlzYVssYygyOm5jb2woaHlkcm9fRXN0TW9kZWxfcmlpc2EpKV0sIDEsIG1heCwgbmEucm09RikNCg0KIyBsaXNhbWUgeCBww6RldmEgbnVtYnJpbGlzZWx0LCBldCBkeWdyYXBoIG9za2FrcyB0ZWhhIMO1aWdlIGdyYWFmaWt1IGFhc3RhdGUgbMO1aWtlcw0KaHlkcm9fRXN0TW9kZWxfcmlpc2EkeCA9YygxOm5yb3coaHlkcm9fRXN0TW9kZWxfcmlpc2EpKQ0KIyBqYSB0ZWVtZSBrdXVww6RldmFkDQpsaWJyYXJ5KGx1YnJpZGF0ZSkNCmh5ZHJvX0VzdE1vZGVsX3JpaXNhJHggPSBwYXJzZV9kYXRlX3RpbWUoeCA9IGh5ZHJvX0VzdE1vZGVsX3JpaXNhJHgsIG9yZGVycyA9ICJqIikNCmh5ZHJvX0VzdE1vZGVsX3JpaXNhPWFzLmRhdGEuZnJhbWUoaHlkcm9fRXN0TW9kZWxfcmlpc2EpDQoNCiMjIFRlZW1lIGdyYWFmaWt1ZA0KbGlicmFyeShkeWdyYXBocykNCmR5Z3JhcGgoaHlkcm9fRXN0TW9kZWxfcmlpc2FbLGMoIngiLCJtaW4iLCJtZWRpYW4iLCJtYXgiKV0pJT4lDQogICAgZHlSYW5nZVNlbGVjdG9yKCklPiUNCiAgICBkeU9wdGlvbnMoZmlsbEdyYXBoID0gVFJVRSwgZmlsbEFscGhhID0gMC4yKSAlPiUNCiAgICANCiAgICBkeVJvbGxlcihyb2xsUGVyaW9kID0gMTApDQoNCg0KIyMjIFbDtXJkbGVtZSB0ZW1wZXJhdHV1cmkgYW5kbWVpZCA1IGFhc3RhIGzDtWlrZXMNCiMgTG9lbWUgc2lzc2UgNSBhYXN0YSAgdGVtcGVyYXR1dXJpIHDDpGV2YWFuZG1lZA0KbGlicmFyeShqc29ubGl0ZSkNCmtsaWltYV9kYXRhX1BBIDwtIGZyb21KU09OKCJodHRwczovL2tlc2trb25uYWFuZG1lZC5lbnZpci5lZS9mX2tsaWltYV9wYWV2P2phYW1fa29vZD1lcS5BSlRVUkkwMSZlbGVtZW50X2tvb2Q9aW4uKERUQTA4KSZhYXN0YT1pbi4oMjAxOSwyMDIwLDIwMjEsMjAyMiwyMDIzKSIpICN0w7xyaQ0KDQojIE5vcm1hbGlzZWVyaW1lIGFqYWxpc2UgbcO1w7V0bWUgDQprbGlpbWFfZGF0YV9QQSR0aW1lbGluZV90c191dGM9IHBhc3RlMChrbGlpbWFfZGF0YV9QQSRrdXUsIi0iLGtsaWltYV9kYXRhX1BBJHBhZXYpDQoNCiMgVmlza2FtZSB2w6RsamEgw7xsZWxpaWdzZWQgdsOkbGphZCBhZ2EgasOkdGFtZSBzaXNzZSBrdXUgamEgcMOkZXZhLCBldCBqw6RyamVrb3JkIHNhc3NpIGVpIGzDpGhla3MNCmtsaWltYV9kYXRhX1BBPWtsaWltYV9kYXRhX1BBWyxjKCJhYXN0YSIsImt1dSIsInBhZXYiLCJ0aW1lbGluZV90c191dGMiLCJ2YWFydHVzIildDQoNCiMgUGFuZW1lIGFuZG1lZCBrw7VydnV0aSDDvGh0ZSB0YWJlbGlzc2UsIGV0IHNhYWtzIGdyYWFmaWt1IHRlaGENCmxpYnJhcnkodGlkeXIpDQprbGlpbWFfZGF0YV9QQT1zcHJlYWQoa2xpaW1hX2RhdGFfUEEsIGtleSA9IGFhc3RhLCB2YWx1ZSA9IHZhYXJ0dXMpDQoNCiMgRWVtYWxkYW1lIGt1dSBqYSBww6RldmENCmtsaWltYV9kYXRhX1BBPWtsaWltYV9kYXRhX1BBWyxjKDM6OCldDQoNCiNrbGlpbWFfZGF0YV9QQSR0aW1lbGluZV90c191dGM9IGFzLlBPU0lYbHQoa2xpaW1hX2RhdGFfUEEkdGltZWxpbmVfdHNfdXRjLCBmb3JtYXQ9JyVtLSVkJyx0eiA9ICJVVEMiKQ0KIyBFdCBncmFhZmlrIG9sZWtzIHB1aGFzIGphIGFydXNhYWRhdiBhcnZ1dGFtZSBtaW4sbWF4IGphIGtlc2ttaXNlIHbDpMOkcnR1c2UNCmtsaWltYV9kYXRhX1BBJG1lZGlhbiA9IGFwcGx5KGtsaWltYV9kYXRhX1BBWyxjKDI6NildLCAxLCBtZWRpYW4sIG5hLnJtPUYpDQprbGlpbWFfZGF0YV9QQSRtaW4gPSBhcHBseShrbGlpbWFfZGF0YV9QQVssYygyOjYpXSwgMSwgbWluLCBuYS5ybT1GKQ0Ka2xpaW1hX2RhdGFfUEEkbWF4ID0gYXBwbHkoa2xpaW1hX2RhdGFfUEFbLGMoMjo2KV0sIDEsIG1heCwgbmEucm09RikNCg0KIyBsaXNhbWUgeCBww6RldmEgbnVtYnJpbGlzZWx0LCBldCBkeWdyYXBoIG9za2FrcyB0ZWhhIMO1aWdlIGdyYWFmaWt1IGFhc3RhdGUgbMO1aWtlcw0Ka2xpaW1hX2RhdGFfUEEkeCA9YygxOm5yb3coa2xpaW1hX2RhdGFfUEEpKQ0KIyBqYSB0ZWVtZSBrdXVww6RldmFkDQpsaWJyYXJ5KGx1YnJpZGF0ZSkNCmtsaWltYV9kYXRhX1BBJHggPSBwYXJzZV9kYXRlX3RpbWUoeCA9IGtsaWltYV9kYXRhX1BBJHgsIG9yZGVycyA9ICJqIikNCmtsaWltYV9kYXRhX1BBPWFzLmRhdGEuZnJhbWUoa2xpaW1hX2RhdGFfUEEpDQoNCiMjIFRlZW1lIGdyYWFmaWt1ZA0KbGlicmFyeShkeWdyYXBocykNCmR5Z3JhcGgoa2xpaW1hX2RhdGFfUEFbLGMoIngiLCJtaW4iLCJtZWRpYW4iLCJtYXgiKV0pJT4lDQogICAgZHlSYW5nZVNlbGVjdG9yKCklPiUNCiAgICBkeU9wdGlvbnMoZmlsbEdyYXBoID0gVFJVRSwgZmlsbEFscGhhID0gMC4yKSAlPiUNCiAgICBkeVJvbGxlcihyb2xsUGVyaW9kID0gMTApDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMjIyBIw7xkcm9sb29naWxpbmUgbXVkZWxwcm9nbm9vcw0KIyBodHRwczovL2tlc2trb25uYXBvcnRhYWwuZWUvZXQvYXZhYW5kbWVkL2h1ZHJvbG9vZ2lsaW5lLW11ZGVscHJvZ25vb3MNCiMgQW5kbWVkIGFzdXZhZCBzaWluOiBodHRwczovL2F2YWFuZG1lZC5rZXNra29ubmFwb3J0YWFsLmVlL2Rocy9BY3RpdmUvZG9jdW1lbnRMaXN0LmFzcHg/Vmlld0lkPTkxOTE5MmI3LTNlNGUtNDY5NC1hM2Y3LTdiODU2ZGE3YWVhYw0KIyBJRCBtdXV0dXZhZCwgc2VlZ2EgdHVsZWIgdmFhZGEgasOkcmdpIG1pcyBvbiBhamFrb2hhc2UgZmFpbGkgSUQ6IGh0dHBzOi8vYXZhYW5kbWVkLmtlc2trb25uYXBvcnRhYWwuZWUvc3dhZ2dlci9pbmRleC5odG1sDQojIyBMb2VtZSBzaXNzZSBBZXNvbyB2b29sdWh1bGdhIGphIFJpaXNhIHZlZXRhc2VtZXRlIGFuZG1lZA0KbGlicmFyeShyZWFkcikNCiMgTG9lbWUgc2lzc2UgQWVzb28gdm9vbHVodWxnYSBhbmRtZWQNCkFlc29vX3Byb2dub29zIDwtIHJlYWRfdGFibGUoImh0dHBzOi8vYXZhYW5kbWVkLmtlc2trb25uYXBvcnRhYWwuZWUvX3Z0aV9iaW4vUm1BcGkuc3ZjL2FjdGl2ZS9pdGVtcy8xMzM3MzYxL2ZpbGVzLzEiLCBjb2xfbmFtZXMgPSBGQUxTRSkNCiMgTG9lbWUgc2lzc2UgUmlpc2EgdmVldGFzZW1ldGUgYW5kbWVkDQpSaWlzYV9wcm9nbm9vcyA8LSByZWFkX3RhYmxlKCJodHRwczovL2F2YWFuZG1lZC5rZXNra29ubmFwb3J0YWFsLmVlL192dGlfYmluL1JtQXBpLnN2Yy9hY3RpdmUvaXRlbXMvNDg4MDY4L2ZpbGVzLzEiLCBjb2xfbmFtZXMgPSBGQUxTRSkNCiMgTG9lbWUgc2lzc2UgUmlpc2Egdm9vbHVodWxnYSBhbmRtZWQgYWdhIGt1bmEgc2FhbWUgZXJyb3JpdCBzaWlzIGrDpHRhbWUgdsOkbGphIGVzaWFsZ3UNCiNSaWlzYV9wcm9nbm9vc192b29sdWh1bGsgPC0gcmVhZF90YWJsZSgiaHR0cHM6Ly9hdmFhbmRtZWQua2Vza2tvbm5hcG9ydGFhbC5lZS9fdnRpX2Jpbi9SbUFwaS5zdmMvYWN0aXZlL2l0ZW1zLzQ4ODA2Ni9maWxlcy8xIiwgY29sX25hbWVzID0gRkFMU0UpDQoNCiMgQW5kbWV0ZWwgcG9sZSBwZWFsa2lyanUgamEgbmVlZCBzYWFtZSBzaWl0OiBodHRwczovL2tlc2trb25uYXBvcnRhYWwuZWUvZXQvYXZhYW5kbWVkL2h1ZHJvbG9vZ2lsaXNlLXByb2dub29zaS1hbmRtZXN0aWsvaHVkcm9sb29naWxpc2UtcHJvZ25vb3NpLWtpcmplbGR1cw0KbmFtZXMoQWVzb29fcHJvZ25vb3MpID1jKCJhZWciLCJ2b29sdWh1bGdhIHByb2dub29zIiwibWF4IHZvb2x1aHVsayIsIm1pbiB2b29sdWh1bGsiLCJrZXNrbWluZSB2b29sdWh1bGsiLCJ0ZXN0IikNCm5hbWVzKFJpaXNhX3Byb2dub29zKSA9YygiYWVnIiwidmVldGFzZW1lIHByb2dub29zIiwibWF4IHZlZXRhc2UiLCJtaW4gdmVldGFzZSIsImtlc2ttaW5lIHZlZXRhc2UiKQ0KDQojIEt1bmEgYW5kbWV0ZXMgb24ga3V1cMOkZXZhZCBlcmlsaXNlcyBmb3JtYWFkaXMgKGFhc3RhICsgbnVtYnJpbGluZSBww6RldmEgYXJ2KGp1bGlhbiBkYXkpKSBzaWlzIGVlbWFsZGFtZSBhYXN0YSANCkFlc29vX3Byb2dub29zJHBhZXYgPSBhcy5udW1lcmljKHN1YigiXi4uLi4iLCAiIiwgQWVzb29fcHJvZ25vb3MkYWVnKSkNClJpaXNhX3Byb2dub29zJHBhZXYgPSBhcy5udW1lcmljKHN1YigiXi4uLi4iLCAiIiwgUmlpc2FfcHJvZ25vb3MkYWVnKSkNCg0KIyBKYSB0ZWVtZSBudW1icmkga3V1cMOkZXZha3MNCmxpYnJhcnkobHVicmlkYXRlKQ0KQWVzb29fcHJvZ25vb3MkcGFldj1wYXJzZV9kYXRlX3RpbWUoeCA9IEFlc29vX3Byb2dub29zJHBhZXYsIG9yZGVycyA9ICJqIikNClJpaXNhX3Byb2dub29zJHBhZXY9cGFyc2VfZGF0ZV90aW1lKHggPSBSaWlzYV9wcm9nbm9vcyRwYWV2LCBvcmRlcnMgPSAiaiIpDQojIHZpaW1lIHRhZ2FzaSBkYXRhLmZyYW1lIGZvcm1hYXRpDQpBZXNvb19wcm9nbm9vcz1hcy5kYXRhLmZyYW1lKEFlc29vX3Byb2dub29zKQ0KUmlpc2FfcHJvZ25vb3M9YXMuZGF0YS5mcmFtZShSaWlzYV9wcm9nbm9vcykNCg0KIyMgVGVlbWUgZ3JhYWZpa3VkDQojIEFlc29vIHZvb2x1aHVsaw0KbGlicmFyeShkeWdyYXBocykNCmR5Z3JhcGgoQWVzb29fcHJvZ25vb3NbLGMoInBhZXYiLCJ2b29sdWh1bGdhIHByb2dub29zIiwibWF4IHZvb2x1aHVsayIsIm1pbiB2b29sdWh1bGsiLCJrZXNrbWluZSB2b29sdWh1bGsiKV0pICU+JQ0KICAgIGR5RXZlbnQoQWVzb29fcHJvZ25vb3NbMTEsYygicGFldiIpXSwgIlTDpG5hIiwgbGFiZWxMb2MgPSAiYm90dG9tIikgJT4lDQogICAgZHlPcHRpb25zKGZpbGxHcmFwaCA9IFRSVUUsIGZpbGxBbHBoYSA9IDAuMikNCiMgUmlpc2EgdmVldGFzZW1lZA0KbGlicmFyeShkeWdyYXBocykNCmR5Z3JhcGgoUmlpc2FfcHJvZ25vb3NbLGMoInBhZXYiLCJ2ZWV0YXNlbWUgcHJvZ25vb3MiLCAibWF4IHZlZXRhc2UiLCAibWluIHZlZXRhc2UiLCAia2Vza21pbmUgdmVldGFzZSIpXSkgJT4lDQogICAgZHlFdmVudChSaWlzYV9wcm9nbm9vc1sxMSxjKCJwYWV2IildLCAiVMOkbmEiLCBsYWJlbExvYyA9ICJib3R0b20iKSAlPiUNCiAgICBkeU9wdGlvbnMoZmlsbEdyYXBoID0gVFJVRSwgZmlsbEFscGhhID0gMC4yKQ0KIyBraXJqZWxkdXNlcyBvbiBraXJqYXMsIGV0IHTDpG5hIG9uIDExIHJpZGEgYWdhIGt1dXDDpGV2IGVpIGtsYXBpLiBJbG1zZWx0IG9uIEtQIGzDpGludWQgbmloa2Vzc2UgKDI5LjAyKSANCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyMjIElsbWFwcm9nbm9vc2lkIA0KIyMgNCBww6RldmEgaWxtYXByb2dub29zIEFlc29vIGtvaHRhDQojIEFuZG1ldGVlbnVzZSBpbmZvOiBodHRwczovL2lsbW1pY3Jvc2VydmljZS5lbnZpci5lZS9hcGlfZG9jLyNhcGktRm9yZWNhc3RzLUdldFYxRm9yZWNhc3RzTW9kZWxmb3JlY2FzdGJ5bG9jYXRpb24NCiMgTG9lbWUgc2lzc2UgQWVzb28gaMO8ZHJvbWVldHJpYWphYW1hIGlsbWFwcm9nbm9vc2kgYW5kbWVkIGphIHBhbmVtZSBhbmRtZWQgZGF0YWZyYW1laQ0KdXJsND0gImh0dHBzOi8vcHVibGljYXBpLmVudmlyLmVlL3YxL2ZvcmVjYXN0cy9tb2RlbEZvcmVjYXN0QnlMb2NhdGlvbj9sYXRpdHVkZT0yNS4wNjE4MjYmbG9uZ2l0dWRlPTU4LjUxNTMwMyZvdXRwdXRGb3JtYXQ9YXBwbGljYXRpb24lMkZqc29uIg0Ka2xpaW1hXzQgPC0gZnJvbUpTT04odXJsNCkNCmtsaWltYV80ID1rbGlpbWFfNCRlbnRyaWVzJGVudHJ5DQojIFbDpMOkcnR1c2VkIG9uIGVyYWxkYXR1ZCBrb21hZ2EgamEgw7xoZXMgdHVsYmFzIHNlZWdhIGxhbW11dGFtZSBzZWxsZSBlcmxhZGkgdHVscGFkZWtzDQprbGlpbWFfNCA9IGRvLmNhbGwoInJiaW5kIiwgc3Ryc3BsaXQoa2xpaW1hXzQkdmFhcnR1cywgIiwiKSkNCmtsaWltYV80ID0gZGF0YS5mcmFtZShhcHBseShrbGlpbWFfNCwgMiwgYXMubnVtZXJpYykpDQoNCiMgw5xtYXJkYW1lIG51bWJyaWxpc2VkIGFuZG1lZA0KbGlicmFyeShkcGx5cik7IGtsaWltYV80PWtsaWltYV80ICU+JSBtdXRhdGVfaWYoaXMubnVtZXJpYywgcm91bmQsIGRpZ2l0cz0xKQ0KIyBLdW5hIGFuZG1lZCBlaSBvbGUga2lyamVsZGF0dWQgc2lpcyBrYXRzZWVrc2l0dXMgbWVldG9kaSB0dWxlbXVzZWQNCiMgRXNpbWVuZSB2w6TDpHJ0dXMgb24geDEzDQojIFRlbXAgb24gMSByaWRhLCBzYWRlbWVkIG9uIDYgcmlkYSwgdHV1bCBvbiAxNSByaWRhLCDDtWh1csO1aGsgb24gMTAgcmlkYQ0Ka2xpaW1hXzQgPSBrbGlpbWFfNFtjKDEsNiwxNSwxMCksYygxMzo1MCldDQprbGlpbWFfNCA9IGFzLmRhdGEuZnJhbWUodChrbGlpbWFfNCkpDQoNCiMgS3VuYSBhZWdhIGFuZG1ldGVzIGVpIG9sZSBzaWlzIGFydnV0YW1lIHNlbGxlIHBvc2l0c2lvb25pbHQgeDEzIGVoayBrbGlpbWFfNCBhbGd1c2VzdA0KYWVnPXRydW5jKFN5cy50aW1lKCksdW5pdHM9ICJob3VycyIpDQpmb3IgKGkgaW4gMTpucm93KGtsaWltYV80KS0xKSB7YWVnW2krMV09IGFlZyArIGhvdXJzKGkpfQ0KIyBMaXNhbWUgYWphdmVrdG9yaSBhbmRtZXRlbGUNCmtsaWltYV80JGFlZz1hZWcNCiMgQW5uYW1lIGFydXNhYWRhdmFkIG5pbWVkIHR1bHBhZGVsZQ0KY29sbmFtZXMoa2xpaW1hXzQpID0gYygiVEEiLCJQUjFIIiwiVHV1bCIsIsOVaHVyw7VoayIsImFlZyIpDQoNCiMjIFRlZW1lIGdyYWFmaWt1DQpsaWJyYXJ5KGR5Z3JhcGhzKQ0KZHlncmFwaChrbGlpbWFfNFssYygiYWVnIiwiVEEiLCJQUjFIIiwiVHV1bCIpXSwNCiAgICAgICAgbWFpbiA9ICJNZXRlb3JvbG9vZ2lsaW5lIHByb2dub29zIEFlc21hYSBqYWFtYSBrb29yZGluYWF0aWRlbCIsIA0KICAgICAgICB5bGFiID0gInRlbXAoYyksIHR1dWwobS9zKSwgc2FkZW1lZChtbSkiKSAlPiUNCiAgICBkeVNlcmllcygiVEEiLCBsYWJlbCA9ICJ0ZW1wIikgJT4lDQogICAgZHlTZXJpZXMoIlR1dWwiLCBsYWJlbCA9ICJUdXVsIikgJT4lDQogICAgZHlSYW5nZVNlbGVjdG9yKCklPiUNCiAgICBkeVJvbGxlcihyb2xsUGVyaW9kID0gMCkgJT4lDQogICAgZHlPcHRpb25zKGZpbGxHcmFwaCA9IFRSVUUsIGZpbGxBbHBoYSA9IDAuMixsYWJlbHNVVEMgPSBUUlVFKQ0KDQoNCiMjIEhldGtlIGRhdGEga29vcmRpbmFhZGkgcMO1aGlzZWx0DQp1cmxfcD0oImh0dHBzOi8vaWxtbWljcm9zZXJ2aWNlLmVudmlyLmVlL2FwaS9mb3JlY2FzdHMvbW9iaWxlTG9jYXRpb25Gb3JlY2FzdD9sYXRpdHVkZT01OC41MTUzMDMmbG9uZ2l0dWRlPTI1LjA2MTgyNiZzdGF0aW9uSWQ9NTQiKQ0Ka2xpaW1hX3AgPC0gZnJvbUpTT04odXJsX3ApDQprbGlpbWFfcCA9a2xpaW1hX3AkZW50cmllcyRlbnRyeQ0Ka2xpaW1hX3A9dChrbGlpbWFfcCkNCiMgTWlsbGVnaXDDpHJhc3QgdHVsZXZhZCBhbmRtZWQgS3V1c2lrdSBqYWFtYXN0Pw0KDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojIyMgVGVlbWFrYWFydA0KIyMgVGVraXRhbWUgamFhbWFkZSDDvGxkYW5kbWVkDQojIEvDtWlnZXBlYWx0IEFlc29vIGjDvGRyb2xvb2dpbGlzZSBqYWFtIGFuZG1lZA0KbGlicmFyeShkcGx5cikNCmh5ZHJvX2phYW0gPC0gZnJvbUpTT04oImh0dHBzOi8va2Vza2tvbm5hYW5kbWVkLmVudmlyLmVlL2ZfaHlkcm9zZWlyZT90aW1lbGluZV90c191dGM9bHQuMjAyNC0wMS0wMlQwMzowMDowMCZ0aW1lbGluZV90c191dGM9Z3QuMjAyNC0wMS0wMVQyMzowMDowMCZqYWFtX2tvb2Q9aW4uKDQxMTM3LDQxMTQwKSIpDQoNCiMgQW5kbWV0ZXMgb24ga2FrcyBqYWFtYSBzZWVnYSB2YWphbWUgdW5pa2FhbHNlaWQgamFhbWEgYW5kbWVpZA0KaHlkcm9famFhbSA9IGh5ZHJvX2phYW1bLGMoImphYW1fa29vZCIsImphYW1fbmltaSIsInZhbGdhbGFfbmltaSIsInZhbGdhbGFfc3V1cnVzX2ttMiIsImthdWd1c19zdXVkbWVzdF9rbSIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAiamFhbV9sYWl1c2tyYWFkIiwiamFhbV9waWtrdXNrcmFhZCIsImphYW1fdGFpc25pbWkiLCJ2ZWVrb2d1X25pbWkiKV0NCmh5ZHJvX2phYW0gPSBkaXN0aW5jdChoeWRyb19qYWFtKQ0KDQojIEFubmFtZSB2ZWVsIGxlYWZsZXRpbGUgYXN1c2FhZGF2YWQga29vcmRpbmFhdGlkZSBuaW1lZCAobGF0LGxvbikNCm5hbWVzKGh5ZHJvX2phYW0pID0gYygiamFhbV9rb29kIiwiamFhbV9uaW1pIiwidmFsZ2FsYV9uaW1pIiwidmFsZ2FsYV9zdXVydXNfa20yIiwia2F1Z3VzX3N1dWRtZXN0X2ttIiwNCiAgICAgICAgICAgICAgICAgICAgICAibGF0IiwibG9uIiwiamFhbV90YWlzbmltaSIsInZlZWtvZ3VfbmltaSIpDQoNCiMgU2lpcyBUw7xyaSwgUMOkcm51IGphIFZpbGphbmRpIG1ldGVvcm9sb29naWFqYWFtYWRlIGFuZG1lZCwgbWlzIG9uIGVyYWxkaSBww6RyaW5ndWdhIHNhYWRhdmFsDQpqYWFtIDwtIGZyb21KU09OKCJodHRwczovL2tlc2trb25uYWFuZG1lZC5lbnZpci5lZS9mX2tsaWltYV9qYWFtX3ZhYXRsdXM/amFhbV9rb29kPWluLihBSlZJTEowMSxBSlBBUk4wMSxBSlRVUkkwMSkiKQ0KDQojIEFuZG1ldGVzIG9uIGtvbG0gamFhbWEgc2VlZ2EgdmFsaW1lIGFpbnVsdCBqYWFtYWRlIMO8bGRhbmRtZWQgamEgc2VlasOkcmVsIGrDpHRhbWUgdW5pa2FhbHNlZCBraXJqZWQNCmphYW0gPSBqYWFtWyxjKCJqYWFtX2tvb2QiLCJqYWFtX25pbWkiLCJqYWFtX25pbWlfZW5nIiwiamFhbV9wZXJpb29kX2FsZ3VzIiwgICANCiAgICAgICAgICAgICAgICJqYWFtX3Blcmlvb2RfbG9wcCIsInBpa2t1c2tyYWFkIiwibGFpdXNrcmFhZCIsImtvcmd1c19tZXJlcGlubmFzdF9tIildDQpqYWFtID0gZGlzdGluY3QoamFhbSkNCiMgQW5kbWV0ZXMgb24gMyBww6RybnUgbWV0ZW9yb2xvb2dpYWphYW1hIGphIG11bCBvbiB2YWphIGFpbnVsdCB2aWltYXN0DQpqYWFtID1qYWFtWzE6MyxdDQojIEFubmFtZSB2ZWVsIGxlYWZsZXRpbGUgYXN1c2FhZGF2YWQga29vcmRpbmFhdGlkZSBuaW1lZCAobGF0LGxvbikNCm5hbWVzKGphYW0pID0gYygiamFhbV9rb29kIiwiamFhbV9uaW1pIiwiamFhbV9uaW1pX2VuZyIsImphYW1fcGVyaW9vZF9hbGd1cyIsICAgDQogICAgICAgICAgICAgICAgImphYW1fcGVyaW9vZF9sb3BwIiwibG9uIiwibGF0Iiwia29yZ3VzX21lcmVwaW5uYXN0X20iKQ0KDQoNCiMjIExpc2FtZXMgbXV1ZCB0YXVzdGFuZG1lZCBtaWRhIG9uIHZhamEga2FhcmRpIHRlZ2VtaXNla3MNCiMgaHR0cHM6Ly9yZWdpc3Rlci5rZXNra29ubmFwb3J0YWFsLmVlL3JlZ2lzdGVyL2ludGVybmF0aW9uYWxseS1pbXBvcnRhbnQtYXJlYS84OTU3ODUxDQoNCiMgVXJsaWQgbWlkYSBrYXN1dGFkYSBXTVMgdGVlbnVzdGUgcHVodWwNCm1hX2FsdXMgPC0gImh0dHBzOi8va2FhcnQubWFhYW1ldC5lZS93bXMvaGFsbGthYXJ0Ig0KZWVsaXMgPC0gImh0dHBzOi8vZ3NhdmFsaWsuZW52aXIuZWUvZ2Vvc2VydmVyL2VlbGlzL293cyINCg0KIyBQZWFrcyBzYWFtYSBrYSBvdHNlIGdlb2pzb25pdCBrYXN1dGFkYSBhZ2EgZWkgw7VubmVzdHVudWQgdG9pbWltYSBzYWFkYQ0KIyBnZW9qc29uIDwtIGpzb25saXRlOjpmcm9tSlNPTigiaHR0cHM6Ly9nc2F2YWxpay5lbnZpci5lZS9nZW9zZXJ2ZXIvZWVsaXMvb3dzP3NlcnZpY2U9V0ZTJnZlcnNpb249MS4wLjAmcmVxdWVzdD1HZXRGZWF0dXJlJnR5cGVOYW1lPWVlbGlzJTNBa3JfamFydiZtYXhGZWF0dXJlcz01MCZvdXRwdXRGb3JtYXQ9YXBwbGljYXRpb24lMkZqc29uIikNCg0KIyBFZXN0aSBrb29yZGluYWF0c8O8c3RlZW0gdHVsZWIgdMOkcHN1c3RhZGEga3VuYSBsZWFmbGV0IGthc3V0YWIgd2dzODQNCmxpYnJhcnkobGVhZmxldCkNCmxpYnJhcnkobGVhZmxldC5leHRyYXMpDQplcHNnMzMwMSA8LSBsZWFmbGV0Q1JTKGNyc0NsYXNzID0gIkwuUHJvai5DUlMiLCANCiAgICAgICAgICAgICAgICAgICAgICAgY29kZSA9ICJFUFNHOjMzMDEiLA0KICAgICAgICAgICAgICAgICAgICAgICAjcHJvajRkZWYgPSAiK3Byb2o9bGNjICtsYXRfMT01OS4zMzMzMzMzMzMzMzMzNCArbGF0XzI9NTggK2xhdF8wPTU3LjUxNzU1MzkzMDU1NTU2ICtsb25fMD0yNCAreF8wPTUwMDAwMCAreV8wPTYzNzUwMDAgK2VsbHBzPUdSUzgwICt0b3dnczg0PTAsMCwwLDAsMCwwLDAgK3VuaXRzPW0gK25vX2RlZnMiLA0KICAgICAgICAgICAgICAgICAgICAgICBwcm9qNGRlZiA9ICIrcHJvaj1sY2MgK2xhdF8wPTU3LjUxNzU1MzkzMDU1NTYgK2xvbl8wPTI0ICtsYXRfMT01OS4zMzMzMzMzMzMzMzMzICtsYXRfMj01OCAreF8wPTUwMDAwMCAreV8wPTYzNzUwMDAgK2VsbHBzPUdSUzgwICt0b3dnczg0PTAsMCwwLDAsMCwwLDAgK3VuaXRzPW0gK25vX2RlZnMgK3R5cGU9Y3JzIiwNCiAgICAgICAgICAgICAgICAgICAgICAgcmVzb2x1dGlvbnMgPSBjKDIwNDgsIDEwMjQsIDUxMiwgMjU2LCAxMjgsIDY0LCAzMiwgMTYsIDgsIDQsIDIsIDEsIDAuNSksICMgODE5MiBkb3duIHRvIDAuNQ0KICAgICAgICAgICAgICAgICAgICAgICBvcmlnaW4gPSBjKDAsIDApKQ0KDQojIyBUZWVtZSB2YWxtaXMga2FhcmRpIGxlYWZsZXRpZ2ENCiMgVGVraXRhbWUga2FhcmRpb2JqZWt0aQ0KYmFzZW1hcCA8LSBsZWFmbGV0KGphYW0sDQogICAgICAgICAgICAgICAgICAgd2lkdGggPSAiMTAwJSIsIA0KICAgICAgICAgICAgICAgICAgIGhlaWdodCA9ICI2MDBweCIsDQogICAgICAgICAgICAgICAgICAgb3B0aW9ucyA9IGxlYWZsZXRPcHRpb25zKA0KICAgICAgICAgICAgICAgICAgICAgICBwcmVmZXJDYW52YXMgPSBUUlVFLCANCiAgICAgICAgICAgICAgICAgICAgICAgI3dvcmxkQ29weUp1bXAgPSBGLCANCiAgICAgICAgICAgICAgICAgICAgICAgY3JzID0gZXBzZzMzMDEpKSAlPiUNCiAgICANCiAgICAjYWRkVGlsZXModXJsVGVtcGxhdGUgPSAiLy97c30udGlsZS5vcGVuc3RyZWV0bWFwLm9yZy97en0ve3h9L3t5fS5wbmciLCBncm91cCA9ICJUYXVzdGFrYWFydCIsdGlsZU9wdGlvbnMob3BhY2l0eSA9IDAuOSkpICU+JQ0KICAgIA0KICAgICMgTGlzYW1lIGthYXJkaWxlIE1BIGFsdXNrYWFyZGkgVk1TIHRlZW51c2UNCiAgICBhZGRXTVNUaWxlcygNCiAgICAgICAgbWFfYWx1cywNCiAgICAgICAgI2xheWVycyA9ICJNQS1BTFVTIiwNCiAgICAgICAgbGF5ZXJzID0gIk1BLUhBTExLQUFSVCIsDQogICAgICAgIGdyb3VwID0gIlRhdXN0YWthYXJ0IiwNCiAgICAgICAgb3B0aW9ucyA9IFdNU1RpbGVPcHRpb25zKGZvcm1hdCA9ICJpbWFnZS9wbmciLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdHJhbnNwYXJlbnQgPSBUUlVFLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgb3BhY2l0eT0wLjMsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtaW5ab29tID0gMSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1heFpvb20gPSAxNCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnRpbnVvdXNXb3JsZCA9IFQpKSAlPiUNCiAgICANCiAgICAjIExpc2FtZSBrYWFyZGlsZSB2b29sdXZlZWtvZ3VkZSBWTVMgdGVlbnVzZQ0KICAgIGFkZFdNU1RpbGVzKA0KICAgICAgICBlZWxpcywNCiAgICAgICAgbGF5ZXJzID0gImVlbGlzOmtyX3Zvb2x1dmVzaSIsDQogICAgICAgIGdyb3VwID0gIlZvb2x1dmVzaSIsDQogICAgICAgIG9wdGlvbnMgPSBXTVNUaWxlT3B0aW9ucyhmb3JtYXQgPSAiaW1hZ2UvcG5nIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRyYW5zcGFyZW50ID0gVCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1pblpvb20gPSAwLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWF4Wm9vbSA9IDE1LA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29udGludW91c1dvcmxkID0gVCkpICU+JQ0KICAgICMgTGlzYW1lIGthYXJkaWxlIGrDpHJ2ZWRlIFZNUyB0ZWVudXNlDQogICAgYWRkV01TVGlsZXMoDQogICAgICAgIGVlbGlzLA0KICAgICAgICBsYXllcnMgPSAiZWVsaXM6a3JfamFydiIsDQogICAgICAgIGdyb3VwID0gIkrDpHJ2ZWQiLA0KICAgICAgICBvcHRpb25zID0gV01TVGlsZU9wdGlvbnMoZm9ybWF0ID0gImltYWdlL3BuZyIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0cmFuc3BhcmVudCA9IFQsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtaW5ab29tID0gMCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1heFpvb20gPSAxNCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnRpbnVvdXNXb3JsZCA9IFQpKSAlPiUNCiAgICAjIExpc2FtZSBrYWFyZGlsZSByYW1zYXJpIGFsYWRlIFZNUyB0ZWVudXNlDQogICAgYWRkV01TVGlsZXMoDQogICAgICAgIGVlbGlzLA0KICAgICAgICBsYXllcnMgPSAiZWVsaXM6a3JfcmFtc2FyIiwNCiAgICAgICAgZ3JvdXAgPSAiS2FpdHNlYWxhIiwNCiAgICAgICAgb3B0aW9ucyA9IFdNU1RpbGVPcHRpb25zKGZvcm1hdCA9ICJpbWFnZS9wbmciLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdHJhbnNwYXJlbnQgPSBULA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWluWm9vbSA9IDAsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYXhab29tID0gMTQsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb250aW51b3VzV29ybGQgPSBUKSkgJT4lDQogICAgDQogICAgIyBMaXNhbWUga2FhcmRpbGUgbWV0ZW9yb2xvb2dpYWphYW1hZA0KICAgIGFkZENpcmNsZU1hcmtlcnMocmFkaXVzID0gMTAsDQogICAgICAgICAgICAgICAgICAgICAjdGVraXRhbWUgaW5mb2FrbmENCiAgICAgICAgICAgICAgICAgICAgIGxuZyA9IH5qYWFtJGxvbiwgDQogICAgICAgICAgICAgICAgICAgICBsYXQgPSB+amFhbSRsYXQsDQogICAgICAgICAgICAgICAgICAgICBjb2xvciA9ICJncmVlbiIsDQogICAgICAgICAgICAgICAgICAgICBncm91cCA9ICJKYWFtYWQiLA0KICAgICAgICAgICAgICAgICAgICAgcG9wdXAgPSBwYXN0ZSgiSmFhbWEgbmltaTogIiwgamFhbSRqYWFtX25pbWksICI8YnI+IiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkphYW1hIG5pbWkgKGVuZyk6ICIsIGphYW0kamFhbV9uaW1pX2VuZywgIjxicj4iLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiSmFhbWEga29vZDogIiwgamFhbSRqYWFtX2tvb2QsICI8YnI+IiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkphYW1hIGvDtXJndXMgbWVyZXBpbm5hc3QobSk6ICIsIGphYW0ka29yZ3VzX21lcmVwaW5uYXN0X20sICI8YnI+IiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIlBpa2t1c2tyYWFkOiAiLCBqYWFtJGxvbiwgIjxicj4iLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiTGFpdXNrcmFhZDogIiwgamFhbSRsYXQsICI8YnI+IiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkphYW1hIGFsZ3VzYWVnOiAiLCBqYWFtJGphYW1fcGVyaW9vZF9hbGd1cywgIjxicj4iKSwNCiAgICAgICAgICAgICAgICAgICAgIGxhYmVsID0gfmphYW1fbmltaSkgJT4lDQogICAgDQogICAgIyBMaXNhbWUga2FhcmRpbGUgaMO8ZHJvbWVldHJpYWphYW1hZA0KICAgIGFkZENpcmNsZU1hcmtlcnMocmFkaXVzID0gMTAsDQogICAgICAgICAgICAgICAgICAgICBsbmcgPSB+aHlkcm9famFhbSRsb24sIA0KICAgICAgICAgICAgICAgICAgICAgbGF0ID0gfmh5ZHJvX2phYW0kbGF0LA0KICAgICAgICAgICAgICAgICAgICAgY29sb3IgPSAiI0ZGQzMwMCIsDQogICAgICAgICAgICAgICAgICAgICBncm91cCA9ICJKYWFtYWQiLA0KICAgICAgICAgICAgICAgICAgICAgI3Rla2l0YW1lIGluZm9ha25hDQogICAgICAgICAgICAgICAgICAgICBwb3B1cCA9IHBhc3RlKCJKYWFtYSBuaW1pOiAiLCBoeWRyb19qYWFtJGphYW1fbmltaSwgIjxicj4iLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiSmFhbWEga29vZDogIiwgaHlkcm9famFhbSRqYWFtX2tvb2QsICI8YnI+IiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIlZhbGdhbGEgbmltaTogIiwgaHlkcm9famFhbSR2YWxnYWxhX25pbWksICI8YnI+IiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIlZhbGdhbGEgc3V1cnVzIGttMjogIiwgaHlkcm9famFhbSR2YWxnYWxhX3N1dXJ1c19rbTIsICI8YnI+IiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkthdWd1cyBzdXVkbWVzdCBrbTogIiwgaHlkcm9famFhbSRrYXVndXNfc3V1ZG1lc3Rfa20sICI8YnI+IiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIlZlZWtvZ3UgbmltaTogIiwgaHlkcm9famFhbSR2ZWVrb2d1X25pbWksICI8YnI+IiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIlBpa2t1c2tyYWFkOiAiLCBoeWRyb19qYWFtJGxvbiwgIjxicj4iLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiTGFpdXNrcmFhZDogIiwgaHlkcm9famFhbSRsYXQsICI8YnI+IiksDQogICAgICAgICAgICAgICAgICAgICBsYWJlbCA9IH5oeWRyb19qYWFtJGphYW1fbmltaSkgJT4lDQogICAgDQogICAgIyBMaXNhbWUga2FhcmRpbGUgU29vbWFhIHJhaHZ1c3BhcmdpIGvDvGxhc3R1c2tlc2t1c2UNCiAgICBhZGRNYXJrZXJzKCNyYWRpdXMgPSAxMCwNCiAgICAgICAgICAgICAgIGxuZyA9ICAyNS4wMzE0MTIsDQogICAgICAgICAgICAgICBsYXQgPSAgNTguNDMxMTU4LA0KICAgICAgICAgICAgICAgI2NvbG9yID0gIiNGRkMzMDAiLA0KICAgICAgICAgICAgICAgZ3JvdXAgPSAiSmFhbWFkIiwNCiAgICAgICAgICAgICAgICN0ZWtpdGFtZSBpbmZvYWtuYQ0KICAgICAgICAgICAgICAgcG9wdXAgPSBwYXN0ZSgiICIsICJTb29tYWEgcmFodnVzcGFyZ2kga8O8bGFzdHVza2Vza3VzIiwgIjxicj4iLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiICIsICI8Yj48YSBocmVmPSdodHRwczovL2xvb2R1c2VnYWtvb3MuZWUva3VodW1pbm5hL3JhaHZ1c3BhcmdpZC9zb29tYWEtcmFodnVzcGFyay8xMDc2NC8nPkvDvGxhc3R1c2tlc2t1c2UgaW5mbzwvYT48L2I+IiwgIjxicj4iLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiICIsICI8Yj48YSBocmVmPSdodHRwczovL2xvb2R1c2VnYWtvb3MuZWUva3VodW1pbm5hL3JhaHZ1c3BhcmdpZC9zb29tYWEtcmFodnVzcGFyay8xMjY4Lyc+S29wcmFyYWphIGxpc2FpbmZvPC9hPjwvYj4iLCAiPGJyPiIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiUGlra3Vza3JhYWQ6ICIsICIyNS4wMzE0MTIiLCAiPGJyPiIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICJMYWl1c2tyYWFkOiAiLCAiNTguNDMxMTU4IiwgIjxicj4iKSwNCiAgICAgICAgICAgICAgIGxhYmVsID0gIlNvb21hYSByYWh2dXNwYXJnaSBrw7xsYXN0dXNrZXNrdXMiKSAlPiUNCiAgICANCiAgICAjIErDpMOkZ2VtIGVlc3RpIHBpaXJpZGVzc2Ugc2VlZ2EgdMOkcHN1c3RhbWUga2FhcmRpYWtuYXMga3V2YXRhdmFpZCBwaWlyZQ0KICAgIHNldE1heEJvdW5kcygyMS41ODQ0OCwgNjAuMDg2NDEsIDI4LjM5MDQ1LCA1Ny4wNzYyNSkgJT4lDQogICAgIyBMaXNhbWUgbGVnZW5kaQ0KICAgIGFkZExlZ2VuZCgNCiAgICAgICAgdGl0bGUgPSAiTGVnZW5kIiwNCiAgICAgICAgcG9zaXRpb24gPSAiYm90dG9tcmlnaHQiLA0KICAgICAgICB2YWx1ZXMgPSBjKDEsIDIsMyw0LDUpLA0KICAgICAgICBsYWJlbHMgPSBjKCJWb29sdXZlc2kiLCAiSsOkcnZlZCIsIm1ldGVvLiBqYWFtYWQiLCJow7xkcm8uIGphYW1hZCIsImthaXRzZWFsYWQiKSwNCiAgICAgICAgY29sb3JzID0gYygiYmx1ZSIsICJibHVlIiwiZGFya2dyZWVuIiwieWVsbG93IiwibGlnaHRibHVlIikpJT4lDQogICAgIyBMaXNhbWUga2lodGlkZSBzaXNzZS92w6RsamEgbMO8bGl0YW1pc2UgZnVua3RzaW9uYWFsc3VzZQ0KICAgIGFkZExheWVyc0NvbnRyb2woDQogICAgICAgICNiYXNlR3JvdXBzID0gYygiVGF1c3Rha2FhcnQiLCJLYWl0c2VhbGEiKSwNCiAgICAgICAgb3ZlcmxheUdyb3VwcyA9IGMoIlZvb2x1dmVzaSIsIkrDpHJ2ZWQiLCJKYWFtYWQiLCJLYWl0c2VhbGEiLCJUYXVzdGFrYWFydCIpLA0KICAgICAgICBvcHRpb25zID0gbGF5ZXJzQ29udHJvbE9wdGlvbnMoY29sbGFwc2VkID0gRkFMU0UpKSANCg0KDQojIHZhamFkdXNlbCBzYWFiIGthYXJ0aSBrYSBlcmxhZGlzZWlzdmFsdCBzYWx2ZXN0YWRhIGh0bWxpDQojbGlicmFyeShwbG90bHkpIDtodG1sd2lkZ2V0czo6c2F2ZVdpZGdldChhc193aWRnZXQoYmFzZW1hcCksICJiYXNlbWFwLmh0bWwiKQ0KYmFzZW1hcA0KDQpgYGANCg0KDQojcm1hcmtkb3duOjpyZW5kZXIoInNvb21hYS5SbWQiKQ0K