knitr::opts_chunk$set(
    echo = TRUE,
    message = FALSE,
    warning = FALSE
)
install.packages(c(
  "tidyverse",
  "readr",
  "dplyr",
  "ggplot2",
  "knitr",
  "kableExtra",
  "broom",
  "stringr",
  "corrplot"
), dependencies = TRUE)

Import údajov z .csv

library(readr)
Indian_water_data <- read_csv("Indian_water_data.csv")
head(Indian_water_data)                                             
colnames(Indian_water_data)                                         
 [1] "STN code"                        
 [2] "Monitoring Location"             
 [3] "Year"                            
 [4] "Type Water Body"                 
 [5] "State Name"                      
 [6] "Temperature (C) - Min"           
 [7] "Temperature (C) - Max"           
 [8] "Dissolved - Min"                 
 [9] "Dissolved - Max"                 
[10] "pH - Min"                        
[11] "pH - Max"                        
[12] "Conductivity (µmho/cm) - Min"   
[13] "Conductivity (µmho/cm) - Max"   
[14] "BOD (mg/L) - Min"                
[15] "BOD (mg/L) - Max"                
[16] "NitrateN (mg/L) - Min"           
[17] "NitrateN (mg/L) - Max"           
[18] "Fecal Coliform (MPN/100ml) - Min"
[19] "Fecal Coliform (MPN/100ml) - Max"
[20] "Total Coliform (MPN/100ml) - Min"
[21] "Total Coliform (MPN/100ml) - Max"
[22] "Fecal - Min"                     
[23] "Fecal - Max"                     

Grafy

Scatter plot

library(dplyr)
library(ggplot2)

# Filter pre rok 2021

water_2021 <- Indian_water_data %>% filter(Year == 2021)

# Scatterplot s farbami a vylepšením

ggplot(water_2021, aes(x = `BOD (mg/L) - Max`, y = `Dissolved - Max`)) +
geom_point(aes(color = Year), size = 3) +
scale_color_gradient(low = "blue", high = "red") +  # Farebné zobrazenie bodov
theme_minimal() +
labs(
title = "Vzťah medzi znečistením a kvalitou vody v roku 2021",
x = "BOD (mg/L) - Max (Biochemical Oxygen Demand)",
y = "Dissolved - Max (Rozpustený kyslík)"
) +
theme(legend.position = "bottom")  # Pridanie legendy

Tento graf nám ukazuje vzťah medzi dvoma premennými:

  • BOD (Biochemical Oxygen Demand), čo je indikátor znečistenia vody, meraný ako množstvo kyslíka, ktoré mikroorganizmy spotrebujú na rozklad organických látok vo vode. Vysoká hodnota BOD naznačuje, že voda je viac znečistená.
  • Dissolved Oxygen (Rozpustený kyslík), čo je množstvo kyslíka rozpusteného vo vode. Tento ukazovateľ je dôležitý pre kvalitu vody, pretože mnohé vodné organizmy potrebujú kyslík na prežitie. Nižšie hodnoty rozpusteného kyslíka môžu naznačovať zhoršenú kvalitu vody.

Interpretácia grafu

  • Väčšina hodnôt pre rozpustený kyslík (Dissolved - Max) je v rozmedzí 5 - 10 mg/L, čo je bežná úroveň pre vodu v dobrom stave. Tieto hodnoty sú dostatočné na prežitie väčšiny vodných organizmov.
  • Vysoké hodnoty BOD (až do 80 mg/L) sú zriedkavé a indikujú, že v daných miestach môže byť voda silne znečistená (môže to byť spôsobené napríklad vysokým množstvom organického odpadu).
  • Neexistuje výrazný vzťah medzi BOD a rozpusteným kyslíkom, čo naznačuje, že aj keď vysoký BOD zvyčajne vedie k nižšiemu obsahu kyslíka, v tomto prípade to nie je úplne jednoznačné. Možno existujú aj ďalšie faktory, ktoré ovplyvňujú koncentráciu kyslíka vo vode (napríklad teplota vody alebo iné chemické vlastnosti).

Záver

  • Tento graf ukazuje, že vo väčšine pozorovaných dát za rok 2021 je voda s dostatočným množstvom kyslíka, ale niektoré miesta s vysokým BOD by mohli naznačovať zhoršenú kvalitu vody, najmä tam, kde sú hodnoty BOD veľmi vysoké.
  • Nie je jasný lineárny vzťah medzi znečistením vody a množstvom kyslíka, čo naznačuje, že iné faktory môžu ovplyvňovať kvalitu vody.

Boxplot

ggplot(Indian_water_data, aes(x = factor(Year), y = `Dissolved - Max`, fill = factor(Year))) +
geom_boxplot(color = "black", alpha = 0.6) +
scale_fill_brewer(palette = "Set3") +  # Farebné nastavenie
theme_minimal() +
labs(
title = "Boxplot rozpusteného kyslíka podľa rokov",
x = "Rok",
y = "Dissolved - Max (Rozpustený kyslík)"
)

Na tomto grafe je zobrazený boxplot pre hodnoty rozpusteného kyslíka (Dissolved - Max) v rokoch 2021, 2022, a 2023.

Popis grafu

  • Osa x: roky 2021, 2022, a 2023.
  • Osa y: hodnoty rozpusteného kyslíka medzi 5 a 10 mg/L.
  • Každý boxplot ukazuje:
    • Medián (stredná čierna čiara) pre daný rok.
    • 25. a 75. percentil (horný a dolný okraj boxu).
    • Whiskers (čiary mimo boxu) ukazujú rozsah hodnôt.
    • Outliers (body mimo whiskers) sú odľahlé hodnoty.

Interpretácia grafu

  • 2021: Najnižší medián rozpusteného kyslíka. Vyskytujú sa odľahlé hodnoty.
  • 2022: Hodnoty podobné 2021, ale s vyššou variabilitou. Odľahlé hodnoty nie sú také extrémne.
  • 2023: Najvyšší medián, lepšia kvalita vody, vyššie hodnoty kyslíka. Odľahlé hodnoty sú menej výrazné.

Záver

  • 2023 vykazuje lepšiu kvalitu vody s vyššími hodnotami kyslíka.
  • 2022 má najvyššiu variabilitu, čo naznačuje zmeny v podmienkach.
  • Odľahlé hodnoty v 2021 a 2022 môžu naznačovať miestne znečistenie alebo špecifické udalosti.

Graf naznačuje zlepšenie kvality vody v roku 2023, ale stále sú prítomné odchýlky, ktoré si vyžadujú ďalšiu analýzu.

Heatmapa korelácie

Heatmap korelácie medzi BOD, Dissolved a Teplotou

# Vytvorenie korelačnej matice 
cor_matrix <- cor(Indian_water_data[, c("BOD (mg/L) - Max", "Dissolved - Max", "Temperature (C) - Max")], use = "complete.obs") 
# Vytvorenie heatmapy korelácie 
corrplot(cor_matrix, method = "color", type = "upper", tl.col = "black", tl.srt = 20, col = colorRampPalette(c("blue", "white", "red"))(50))

Tento graf zobrazuje heatmapu korelácie medzi tromi premennými:

  • BOD (mg/L) - Max (Biochemical Oxygen Demand)
  • Dissolved - Max (Rozpustený kyslík)
  • Temperature (C) - Max (Teplota vody)

Popis grafu

  • Farebné bloky ukazujú koreláciu medzi jednotlivými premennými.
  • Korelácie sú zobrazené v rozsahu od -1 do 1, kde:
    • Červená farba znamená silnú pozitívnu koreláciu (t.j. hodnoty rastú spolu).
    • Modrá farba znamená negatívnu koreláciu (t.j. hodnoty rastú opačne).
    • Biela farba znamená slabú alebo žiadnu koreláciu.

Interpretácia grafu

  • BOD vs Dissolved - Max: Korelácia je silne negatívna (červená farba), čo znamená, že vyššie hodnoty BOD sú spojené s nižšími hodnotami rozpusteného kyslíka.
  • BOD vs Temperature: Korelácia je tiež silne negatívna, čo naznačuje, že vyššie teploty môžu byť spojené s vyšším BOD.
  • Dissolved - Max vs Temperature: Korelácia je slabá až nulová (biela farba), čo naznačuje, že teplota nemá výrazný vplyv na množstvo rozpusteného kyslíka.

Tento graf nám teda ukazuje, že znečistenie vody (BOD) je negatívne korelované s kvalitou vody (rozpustený kyslík) a teplotou vody.

Základné štatistiky

library(dplyr)
library(knitr)
library(kableExtra)

# základné štatistiky podľa roku

water.stats <- Indian_water_data %>%
group_by(Year) %>%
summarise(
n      = n(),
mean   = mean(`Dissolved - Max`, na.rm = TRUE),
sd     = sd(`Dissolved - Max`, na.rm = TRUE),
min    = min(`Dissolved - Max`, na.rm = TRUE),
q25    = quantile(`Dissolved - Max`, 0.25, na.rm = TRUE),
median = median(`Dissolved - Max`, na.rm = TRUE),
q75    = quantile(`Dissolved - Max`, 0.75, na.rm = TRUE),
max    = max(`Dissolved - Max`, na.rm = TRUE),
.groups = "drop"
)

# Create styled kableExtra table

water.stats %>%
kable(
digits = 2,
caption = "Základné štatistiky pre Dissolved - Max (Rozpustený kyslík) podľa rokov"
) %>%
kable_styling(
full_width = FALSE,
bootstrap_options = c("striped", "hover", "condensed")
) %>%
column_spec(1, bold = TRUE) %>%                     # Zvýrazní prvý stĺpec (Year)
row_spec(0, bold = TRUE, background = "#f2f2f2")   # Štýl hlavičky
Základné štatistiky pre Dissolved - Max (Rozpustený kyslík) podľa rokov
Year n mean sd min q25 median q75 max
2021 44 7.80 1.70 1.4 6.90 8.00 9.40 10.2
2022 53 7.86 1.75 2.9 7.00 7.80 8.50 13.6
2023 97 7.47 1.88 1.1 6.18 7.75 8.72 11.0

Na tejto tabuľke sú uvedené základné štatistiky pre hodnoty Dissolved - Max (Rozpustený kyslík) podľa rokov (2021, 2022, 2023). Z týchto štatistík môžeme vyčítať niekoľko kľúčových informácií:

  • Priemerné hodnoty rozpusteného kyslíka klesli z 7.80 mg/L v roku 2021 na 7.47 mg/L v roku 2023.
  • Variabilita (štandardná odchýlka) sa zvyšuje, čo naznačuje väčšiu rozmanitosť hodnôt v roku 2023 v porovnaní s predchádzajúcimi rokmi.
  • Minimálne hodnoty v roku 2023 boli najnižšie, čo naznačuje nižšiu kvalitu vody v určitých miestach.
  • Medián a 75. percentil naznačujú, že väčšina hodnôt rozpusteného kyslíka sa pohybovala vo vyšších hodnotách v rokoch 2021 a 2022, zatiaľ čo v roku 2023 sa hodnoty trochu znížili.

Táto tabuľka poskytuje užitočné štatistiky na hodnotenie kvality vody v priebehu týchto troch rokov.

Testovanie hypotéz

t-test: Porovnanie priemeru Temperature (C) - Max v rokoch 2021 a 2023

library(kableExtra)

# Vykonanie t-testu

t.test.result <- t.test(
Indian_water_data$`Temperature (C) - Max`[Indian_water_data$Year == 2021],
Indian_water_data$`Temperature (C) - Max`[Indian_water_data$Year == 2023]
)

# Vytvorenie tabuľky s výsledkami t-testu

t.test.summary <- data.frame(
Statistic = c("t-statistic", "df", "p-value", "confidence interval (lower)", "confidence interval (upper)"),
Value = c(t.test.result$statistic,
t.test.result$parameter,
t.test.result$p.value,
t.test.result$conf.int[1],
t.test.result$conf.int[2])
)

# Zobrazenie tabuľky s kableExtra

t.test.summary %>%
kable(caption = "Výsledky t-testu medzi rokmi 2021 a 2023 pre teplotu (C) - Max") %>%
kable_styling(bootstrap_options = c("striped", "hover", "condensed")) %>%
column_spec(1, bold = TRUE) %>%
row_spec(0, bold = TRUE, background = "#f2f2f2")
Výsledky t-testu medzi rokmi 2021 a 2023 pre teplotu (C) - Max
Statistic Value
t-statistic -0.6440985
df 115.7404340
p-value 0.5207859
confidence interval (lower) -3.0826538
confidence interval (upper) 1.5697351

Táto tabuľka zobrazuje výsledky t-testu medzi rokmi 2021 a 2023 pre hodnoty teploty (C) - Max. Z týchto výsledkov môžeme vyčítať:

Výsledky

  • t-statistic: Hodnota t-testu je -0.6441, čo naznačuje, že rozdiel medzi priemernými hodnotami teploty v rokoch 2021 a 2023 nie je veľký.
  • df (degrees of freedom): Počet stupňov voľnosti je 115.74, čo je kombinovaná veľkosť oboch vzoriek.
  • p-value: Hodnota p = 0.5208, ktorá je vyššia ako prah 0.05, znamená, že rozdiel medzi rokmi 2021 a 2023 nie je štatisticky významný.
  • confidence interval (lower): Dolná hranica konfidenčného intervalu je -3.0827.
  • confidence interval (upper): Horná hranica konfidenčného intervalu je 1.5697.

Záver

Na základe p-hodnoty 0.5208 a konfidenčného intervalu, ktorý zahŕňa záporné aj kladné hodnoty, môžeme povedať, že rozdiel medzi teplotami v rokoch 2021 a 2023 nie je štatisticky významný. To znamená, že neexistuje dostatočný dôkaz, že by sa teplota medzi týmito dvoma rokmi výrazne menila.

ANOVA

library(kableExtra)

# Vykonanie ANOVA testu

anova.result <- aov(`Temperature (C) - Max` ~ factor(Year), data = Indian_water_data)

# Zhrnutie výsledkov ANOVA

anova.summary <- summary(anova.result)[[1]]

# Vytvorenie tabuľky s výsledkami ANOVA

anova.table <- data.frame(
Df = anova.summary$Df,
Sum_Sq = anova.summary$`Sum Sq`,
Mean_Sq = anova.summary$`Mean Sq`,
F_value = anova.summary$`F value`,
Pr_F = anova.summary$`Pr(>F)`
)

# Zobrazenie tabuľky s kableExtra

anova.table %>%
kable(caption = "Výsledky ANOVA testu pre teplotu (C) - Max podľa rokov") %>%
kable_styling(bootstrap_options = c("striped", "hover", "condensed")) %>%
column_spec(1, bold = TRUE) %>%
row_spec(0, bold = TRUE, background = "#f2f2f2")
Výsledky ANOVA testu pre teplotu (C) - Max podľa rokov
Df Sum_Sq Mean_Sq F_value Pr_F
2 78.3076 39.15380 0.9008998 0.407941
189 8214.0849 43.46077 NA NA

Táto tabuľka zobrazuje výsledky ANOVA testu pre teplotu (C) - Max podľa rokov.

Výsledky

  • Df (degrees of freedom):
    • 2 pre medzi-skupinovú variabilitu (roky).
    • 189 pre vnútor-skupinovú variabilitu (počet pozorovaní - 1).
  • Sum_Sq (Sum of Squares):
    • Pre medzi-skupinovú variabilitu je 78.3076.
    • Pre vnútor-skupinovú variabilitu je 8214.0849.
  • Mean_Sq (Mean Square):
    • Pre medzi-skupinovú variabilitu je 39.1538.
    • Pre vnútor-skupinovú variabilitu je 43.4608.
  • F_value: Hodnota F testu je 0.9009, čo naznačuje, že rozdiel medzi skupinami (rokmi) nie je výrazný.
  • Pr_F (p-value): Hodnota p je 0.4079, čo je vyššie než bežný prah 0.05, takže rozdiel medzi rokmi nie je štatisticky významný.

Záver

Na základe výsledkov ANOVA testu môžeme uzavrieť, že rozdiel medzi teplotami v rokoch 2021 a 2023 nie je štatisticky významný. To znamená, že na základe týchto údajov nemáme dôkaz, že by sa teplota medzi týmito dvoma rokmi líšila.

Linear Regression

library(kableExtra)

# Vykonanie lineárnej regresie

model <- lm(`BOD (mg/L) - Max` ~ `Temperature (C) - Max`, data = Indian_water_data)

# Zhrnutie modelu

model.summary <- summary(model)

# Vytvorenie tabuľky s výsledkami lineárnej regresie

model.table <- data.frame(
Term = rownames(model.summary$coefficients),
Estimate = model.summary$coefficients[, 1],
Std_Error = model.summary$coefficients[, 2],
t_value = model.summary$coefficients[, 3],
Pr_t = model.summary$coefficients[, 4]
)

# Zobrazenie tabuľky s kableExtra

model.table %>%
kable(caption = "Výsledky lineárnej regresie medzi BOD (mg/L) - Max a Teplotou (C) - Max") %>%
kable_styling(bootstrap_options = c("striped", "hover", "condensed")) %>%
column_spec(1, bold = TRUE) %>%
row_spec(0, bold = TRUE, background = "#f2f2f2")
Výsledky lineárnej regresie medzi BOD (mg/L) - Max a Teplotou (C) - Max
Term Estimate Std_Error t_value Pr_t
(Intercept) (Intercept) 3.2019962 3.2534658 0.9841801 0.3263780
`Temperature (C) - Max` `Temperature (C) - Max` 0.0638972 0.1144106 0.5584905 0.5772193

Táto tabuľka zobrazuje výsledky lineárnej regresie medzi BOD (mg/L) - Max a Teplotou (C) - Max.

Výsledky

  • (Intercept): Koeficient pre intercept (priesečník s osou Y) je 3.2019962. To znamená, že keď teplota je 0°C, predpokladaná hodnota BOD je približne 3.2 mg/L.
  • Temperature (C) - Max: Koeficient pre teplotu je 0.0638972, čo naznačuje, že pri každom zvýšení teploty o 1°C sa hodnota BOD zvýši približne o 0.064 mg/L.
  • Std_Error: Štandardná chyba koeficientov, ktorá meria variabilitu odhadovaných hodnôt:
    • Pre intercept je 3.2534658.
    • Pre teplotu je 0.1144106.
  • t_value: Testová hodnota (t-hodnota) pre obidve premenné:
    • Pre intercept je 0.9841801.
    • Pre teplotu je 0.5584905. Tieto hodnoty naznačujú, že t-test pre obe premenné nie je veľmi silný.
  • Pr_t (p-value): P-hodnota pre oba koeficienty:
    • Pre intercept je 0.3263780.
    • Pre teplotu je 0.5772193. Obidve p-hodnoty sú vyššie než bežný prah 0.05, čo znamená, že rozdiely medzi BOD a teplotou nie sú štatisticky významné.

Záver

Výsledky regresie naznačujú, že neexistuje štatisticky významný vzťah medzi teplotou a BOD, pretože p-hodnoty sú väčšie než 0.05. To znamená, že na základe týchto údajov nemáme dostatočný dôkaz, že by zmena teploty mala významný vplyv na hodnoty BOD.

LS0tCnRpdGxlOiAiUHLDoWNhIHMgZGF0YWLDoXpvdSAtIGltcG9ydCDDumRham92LCBncmFmeSwgxaF0YXRpc3Rpa3kiCmF1dGhvcjogIlPDoXJhIE5pa29sIFNjaG9sdHpvdsOhIgpkYXRlOiAiT2t0w7NiZXIgMjAyNSIKb3V0cHV0OiAKICBodG1sX25vdGVib29rOgogICAgdG9jOiB0cnVlCiAgICB0b2NfZmxvYXQ6IHRydWUKICAgIHRoZW1lOiB1bml0ZWQKICAgIGhpZ2hsaWdodDogdGFuZ28KICAgIGNzczogc3R5bGUuY3NzCmVkaXRvcl9vcHRpb25zOiAKICBtYXJrZG93bjogCiAgICB3cmFwOiA3MgotLS0KYGBge3J9CmtuaXRyOjpvcHRzX2NodW5rJHNldCgKICAgIGVjaG8gPSBUUlVFLAogICAgbWVzc2FnZSA9IEZBTFNFLAogICAgd2FybmluZyA9IEZBTFNFCikKYGBgCgpgYGB7cn0KaW5zdGFsbC5wYWNrYWdlcyhjKAogICJ0aWR5dmVyc2UiLAogICJyZWFkciIsCiAgImRwbHlyIiwKICAiZ2dwbG90MiIsCiAgImtuaXRyIiwKICAia2FibGVFeHRyYSIsCiAgImJyb29tIiwKICAic3RyaW5nciIsCiAgImNvcnJwbG90IgopLCBkZXBlbmRlbmNpZXMgPSBUUlVFKQpgYGAKIyMgSW1wb3J0IMO6ZGFqb3YgeiAuY3N2CmBgYHtyfQpsaWJyYXJ5KHJlYWRyKQpJbmRpYW5fd2F0ZXJfZGF0YSA8LSByZWFkX2NzdigiSW5kaWFuX3dhdGVyX2RhdGEuY3N2IikKaGVhZChJbmRpYW5fd2F0ZXJfZGF0YSkgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKY29sbmFtZXMoSW5kaWFuX3dhdGVyX2RhdGEpICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKYGBgCgojIEdyYWZ5CgojIyBTY2F0dGVyIHBsb3QKYGBge3J9CmxpYnJhcnkoZHBseXIpCmxpYnJhcnkoZ2dwbG90MikKCiMgRmlsdGVyIHByZSByb2sgMjAyMQoKd2F0ZXJfMjAyMSA8LSBJbmRpYW5fd2F0ZXJfZGF0YSAlPiUgZmlsdGVyKFllYXIgPT0gMjAyMSkKCiMgU2NhdHRlcnBsb3QgcyBmYXJiYW1pIGEgdnlsZXDFoWVuw61tCgpnZ3Bsb3Qod2F0ZXJfMjAyMSwgYWVzKHggPSBgQk9EIChtZy9MKSAtIE1heGAsIHkgPSBgRGlzc29sdmVkIC0gTWF4YCkpICsKZ2VvbV9wb2ludChhZXMoY29sb3IgPSBZZWFyKSwgc2l6ZSA9IDMpICsKc2NhbGVfY29sb3JfZ3JhZGllbnQobG93ID0gImJsdWUiLCBoaWdoID0gInJlZCIpICsgICMgRmFyZWJuw6kgem9icmF6ZW5pZSBib2Rvdgp0aGVtZV9taW5pbWFsKCkgKwpsYWJzKAp0aXRsZSA9ICJWesWlYWggbWVkemkgem5lxI1pc3RlbsOtbSBhIGt2YWxpdG91IHZvZHkgdiByb2t1IDIwMjEiLAp4ID0gIkJPRCAobWcvTCkgLSBNYXggKEJpb2NoZW1pY2FsIE94eWdlbiBEZW1hbmQpIiwKeSA9ICJEaXNzb2x2ZWQgLSBNYXggKFJvenB1c3RlbsO9IGt5c2zDrWspIgopICsKdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gImJvdHRvbSIpICAjIFByaWRhbmllIGxlZ2VuZHkKYGBgClRlbnRvIGdyYWYgbsOhbSB1a2F6dWplIHZ6xaVhaCBtZWR6aSBkdm9tYSBwcmVtZW5uw71taToKCi0gKipCT0QgKEJpb2NoZW1pY2FsIE94eWdlbiBEZW1hbmQpKiosIMSNbyBqZSBpbmRpa8OhdG9yIHpuZcSNaXN0ZW5pYSB2b2R5LCBtZXJhbsO9IGFrbyBtbm/FvnN0dm8ga3lzbMOta2EsIGt0b3LDqSBtaWtyb29yZ2FuaXpteSBzcG90cmVidWrDuiBuYSByb3prbGFkIG9yZ2FuaWNrw71jaCBsw6F0b2sgdm8gdm9kZS4gVnlzb2vDoSBob2Rub3RhIEJPRCBuYXpuYcSNdWplLCDFvmUgdm9kYSBqZSB2aWFjIHpuZcSNaXN0ZW7DoS4KLSAqKkRpc3NvbHZlZCBPeHlnZW4gKFJvenB1c3RlbsO9IGt5c2zDrWspKiosIMSNbyBqZSBtbm/FvnN0dm8ga3lzbMOta2Egcm96cHVzdGVuw6lobyB2byB2b2RlLiBUZW50byB1a2F6b3ZhdGXEviBqZSBkw7RsZcW+aXTDvSBwcmUga3ZhbGl0dSB2b2R5LCBwcmV0b8W+ZSBtbm9ow6kgdm9kbsOpIG9yZ2FuaXpteSBwb3RyZWJ1asO6IGt5c2zDrWsgbmEgcHJlxb5pdGllLiBOacW+xaFpZSBob2Rub3R5IHJvenB1c3RlbsOpaG8ga3lzbMOta2EgbcO0xb51IG5hem5hxI1vdmHFpSB6aG9yxaFlbsO6IGt2YWxpdHUgdm9keS4KCiMjIyBJbnRlcnByZXTDoWNpYSBncmFmdQoKLSBWw6TEjcWhaW5hIGhvZG7DtHQgcHJlICoqcm96cHVzdGVuw70ga3lzbMOtayAoRGlzc29sdmVkIC0gTWF4KSoqIGplIHYgcm96bWVkesOtICoqNSAtIDEwIG1nL0wqKiwgxI1vIGplIGJlxb5uw6Egw7pyb3ZlxYggcHJlIHZvZHUgdiBkb2Jyb20gc3RhdmUuIFRpZXRvIGhvZG5vdHkgc8O6IGRvc3RhdG/EjW7DqSBuYSBwcmXFvml0aWUgdsOkxI3FoWlueSB2b2Ruw71jaCBvcmdhbml6bW92LgotICoqVnlzb2vDqSBob2Rub3R5IEJPRCoqIChhxb4gZG8gKio4MCBtZy9MKiopIHPDuiB6cmllZGthdsOpIGEgaW5kaWt1asO6LCDFvmUgdiBkYW7DvWNoIG1pZXN0YWNoIG3DtMW+ZSBiecWlIHZvZGEgc2lsbmUgem5lxI1pc3RlbsOhIChtw7TFvmUgdG8gYnnFpSBzcMO0c29iZW7DqSBuYXByw61rbGFkIHZ5c29rw71tIG1ub8W+c3R2b20gb3JnYW5pY2vDqWhvIG9kcGFkdSkuCi0gKipOZWV4aXN0dWplIHbDvXJhem7DvSB2esWlYWggbWVkemkgQk9EIGEgcm96cHVzdGVuw71tIGt5c2zDrWtvbSoqLCDEjW8gbmF6bmHEjXVqZSwgxb5lIGFqIGtlxI8gdnlzb2vDvSBCT0QgenZ5xI1ham5lIHZlZGllIGsgbmnFvsWhaWVtdSBvYnNhaHUga3lzbMOta2EsIHYgdG9tdG8gcHLDrXBhZGUgdG8gbmllIGplIMO6cGxuZSBqZWRub3puYcSNbsOpLiBNb8W+bm8gZXhpc3R1asO6IGFqIMSPYWzFoWllIGZha3RvcnksIGt0b3LDqSBvdnBseXbFiHVqw7oga29uY2VudHLDoWNpdSBreXNsw61rYSB2byB2b2RlIChuYXByw61rbGFkIHRlcGxvdGEgdm9keSBhbGVibyBpbsOpIGNoZW1pY2vDqSB2bGFzdG5vc3RpKS4KCiMjIyBaw6F2ZXIKCi0gVGVudG8gZ3JhZiB1a2F6dWplLCDFvmUgdm8gdsOkxI3FoWluZSBwb3pvcm92YW7DvWNoIGTDoXQgemEgcm9rIDIwMjEgamUgdm9kYSBzIGRvc3RhdG/EjW7DvW0gbW5vxb5zdHZvbSBreXNsw61rYSwgYWxlIG5pZWt0b3LDqSBtaWVzdGEgcyB2eXNva8O9bSBCT0QgYnkgbW9obGkgbmF6bmHEjW92YcWlIHpob3LFoWVuw7oga3ZhbGl0dSB2b2R5LCBuYWptw6QgdGFtLCBrZGUgc8O6IGhvZG5vdHkgQk9EIHZlxL5taSB2eXNva8OpLgotIE5pZSBqZSBqYXNuw70gbGluZcOhcm55IHZ6xaVhaCBtZWR6aSB6bmXEjWlzdGVuw61tIHZvZHkgYSBtbm/FvnN0dm9tIGt5c2zDrWthLCDEjW8gbmF6bmHEjXVqZSwgxb5lIGluw6kgZmFrdG9yeSBtw7TFvnUgb3ZwbHl2xYhvdmHFpSBrdmFsaXR1IHZvZHkuCgojIyBCb3hwbG90CmBgYHtyfQpnZ3Bsb3QoSW5kaWFuX3dhdGVyX2RhdGEsIGFlcyh4ID0gZmFjdG9yKFllYXIpLCB5ID0gYERpc3NvbHZlZCAtIE1heGAsIGZpbGwgPSBmYWN0b3IoWWVhcikpKSArCmdlb21fYm94cGxvdChjb2xvciA9ICJibGFjayIsIGFscGhhID0gMC42KSArCnNjYWxlX2ZpbGxfYnJld2VyKHBhbGV0dGUgPSAiU2V0MyIpICsgICMgRmFyZWJuw6kgbmFzdGF2ZW5pZQp0aGVtZV9taW5pbWFsKCkgKwpsYWJzKAp0aXRsZSA9ICJCb3hwbG90IHJvenB1c3RlbsOpaG8ga3lzbMOta2EgcG9kxL5hIHJva292IiwKeCA9ICJSb2siLAp5ID0gIkRpc3NvbHZlZCAtIE1heCAoUm96cHVzdGVuw70ga3lzbMOtaykiCikKYGBgCk5hIHRvbXRvIGdyYWZlIGplIHpvYnJhemVuw70gKipib3hwbG90KiogcHJlIGhvZG5vdHkgKipyb3pwdXN0ZW7DqWhvIGt5c2zDrWthIChEaXNzb2x2ZWQgLSBNYXgpKiogdiByb2tvY2ggKioyMDIxLCAyMDIyLCBhIDIwMjMqKi4KCiMjIyBQb3BpcyBncmFmdQotICoqT3NhIHgqKjogcm9reSAyMDIxLCAyMDIyLCBhIDIwMjMuCi0gKipPc2EgeSoqOiBob2Rub3R5IHJvenB1c3RlbsOpaG8ga3lzbMOta2EgbWVkemkgKio1IGEgMTAgbWcvTCoqLgotIEthxb5kw70gYm94cGxvdCB1a2F6dWplOgogIC0gKipNZWRpw6FuKiogKHN0cmVkbsOhIMSNaWVybmEgxI1pYXJhKSBwcmUgZGFuw70gcm9rLgogIC0gKioyNS4gYSA3NS4gcGVyY2VudGlsKiogKGhvcm7DvSBhIGRvbG7DvSBva3JhaiBib3h1KS4KICAtICoqV2hpc2tlcnMqKiAoxI1pYXJ5IG1pbW8gYm94dSkgdWthenVqw7ogcm96c2FoIGhvZG7DtHQuCiAgLSAqKk91dGxpZXJzKiogKGJvZHkgbWltbyB3aGlza2Vycykgc8O6IG9kxL5haGzDqSBob2Rub3R5LgoKIyMjIEludGVycHJldMOhY2lhIGdyYWZ1Ci0gKioyMDIxKio6IE5ham5pxb7FocOtIG1lZGnDoW4gcm96cHVzdGVuw6lobyBreXNsw61rYS4gVnlza3l0dWrDuiBzYSBvZMS+YWhsw6kgaG9kbm90eS4KLSAqKjIwMjIqKjogSG9kbm90eSBwb2RvYm7DqSAyMDIxLCBhbGUgcyB2ecWhxaFvdSB2YXJpYWJpbGl0b3UuIE9kxL5haGzDqSBob2Rub3R5IG5pZSBzw7ogdGFrw6kgZXh0csOpbW5lLgotICoqMjAyMyoqOiBOYWp2ecWhxaHDrSBtZWRpw6FuLCBsZXDFoWlhIGt2YWxpdGEgdm9keSwgdnnFocWhaWUgaG9kbm90eSBreXNsw61rYS4gT2TEvmFobMOpIGhvZG5vdHkgc8O6IG1lbmVqIHbDvXJhem7DqS4KCiMjIyBaw6F2ZXIKLSAqKjIwMjMqKiB2eWthenVqZSBsZXDFoWl1IGt2YWxpdHUgdm9keSBzIHZ5xaHFocOtbWkgaG9kbm90YW1pIGt5c2zDrWthLgotICoqMjAyMioqIG3DoSBuYWp2ecWhxaFpdSB2YXJpYWJpbGl0dSwgxI1vIG5hem5hxI11amUgem1lbnkgdiBwb2RtaWVua2FjaC4KLSBPZMS+YWhsw6kgaG9kbm90eSB2ICoqMjAyMSoqIGEgKioyMDIyKiogbcO0xb51IG5hem5hxI1vdmHFpSBtaWVzdG5lIHpuZcSNaXN0ZW5pZSBhbGVibyDFoXBlY2lmaWNrw6kgdWRhbG9zdGkuCgpHcmFmIG5hem5hxI11amUgemxlcMWhZW5pZSBrdmFsaXR5IHZvZHkgdiByb2t1IDIwMjMsIGFsZSBzdMOhbGUgc8O6IHByw610b21uw6kgb2RjaMO9bGt5LCBrdG9yw6kgc2kgdnnFvmFkdWrDuiDEj2FsxaFpdSBhbmFsw716dS4KCiMjIEhlYXRtYXBhIGtvcmVsw6FjaWUKIyMjIEhlYXRtYXAga29yZWzDoWNpZSBtZWR6aSBCT0QsIERpc3NvbHZlZCBhIFRlcGxvdG91CmBgYHtyfQojIFZ5dHZvcmVuaWUga29yZWxhxI1uZWogbWF0aWNlIApjb3JfbWF0cml4IDwtIGNvcihJbmRpYW5fd2F0ZXJfZGF0YVssIGMoIkJPRCAobWcvTCkgLSBNYXgiLCAiRGlzc29sdmVkIC0gTWF4IiwgIlRlbXBlcmF0dXJlIChDKSAtIE1heCIpXSwgdXNlID0gImNvbXBsZXRlLm9icyIpIAojIFZ5dHZvcmVuaWUgaGVhdG1hcHkga29yZWzDoWNpZSAKY29ycnBsb3QoY29yX21hdHJpeCwgbWV0aG9kID0gImNvbG9yIiwgdHlwZSA9ICJ1cHBlciIsIHRsLmNvbCA9ICJibGFjayIsIHRsLnNydCA9IDIwLCBjb2wgPSBjb2xvclJhbXBQYWxldHRlKGMoImJsdWUiLCAid2hpdGUiLCAicmVkIikpKDUwKSkKYGBgClRlbnRvIGdyYWYgem9icmF6dWplICoqaGVhdG1hcHUga29yZWzDoWNpZSoqIG1lZHppIHRyb21pIHByZW1lbm7DvW1pOgoKLSAqKkJPRCAobWcvTCkgLSBNYXgqKiAoQmlvY2hlbWljYWwgT3h5Z2VuIERlbWFuZCkKLSAqKkRpc3NvbHZlZCAtIE1heCoqIChSb3pwdXN0ZW7DvSBreXNsw61rKQotICoqVGVtcGVyYXR1cmUgKEMpIC0gTWF4KiogKFRlcGxvdGEgdm9keSkKCiMjIyBQb3BpcyBncmFmdQotICoqRmFyZWJuw6kgYmxva3kqKiB1a2F6dWrDuiBrb3JlbMOhY2l1IG1lZHppIGplZG5vdGxpdsO9bWkgcHJlbWVubsO9bWkuCi0gS29yZWzDoWNpZSBzw7ogem9icmF6ZW7DqSB2IHJvenNhaHUgb2QgKiotMSBkbyAxKiosIGtkZToKICAtICoqxIxlcnZlbsOhIGZhcmJhKiogem5hbWVuw6EgKipzaWxuw7ogcG96aXTDrXZudSBrb3JlbMOhY2l1KiogKHQuai4gaG9kbm90eSByYXN0w7ogc3BvbHUpLgogIC0gKipNb2Ryw6EgZmFyYmEqKiB6bmFtZW7DoSAqKm5lZ2F0w612bnUga29yZWzDoWNpdSoqICh0LmouIGhvZG5vdHkgcmFzdMO6IG9wYcSNbmUpLgogIC0gKipCaWVsYSBmYXJiYSoqIHpuYW1lbsOhICoqc2xhYsO6IGFsZWJvIMW+aWFkbnUga29yZWzDoWNpdSoqLgogIAojIyMgSW50ZXJwcmV0w6FjaWEgZ3JhZnUKLSAqKkJPRCB2cyBEaXNzb2x2ZWQgLSBNYXgqKjogS29yZWzDoWNpYSBqZSAqKnNpbG5lIG5lZ2F0w612bmEqKiAoxI1lcnZlbsOhIGZhcmJhKSwgxI1vIHpuYW1lbsOhLCDFvmUgdnnFocWhaWUgaG9kbm90eSBCT0Qgc8O6IHNwb2plbsOpIHMgbmnFvsWhw61taSBob2Rub3RhbWkgcm96cHVzdGVuw6lobyBreXNsw61rYS4KLSAqKkJPRCB2cyBUZW1wZXJhdHVyZSoqOiBLb3JlbMOhY2lhIGplIHRpZcW+ICoqc2lsbmUgbmVnYXTDrXZuYSoqLCDEjW8gbmF6bmHEjXVqZSwgxb5lIHZ5xaHFoWllIHRlcGxvdHkgbcO0xb51IGJ5xaUgc3BvamVuw6kgcyB2ecWhxaHDrW0gQk9ELgotICoqRGlzc29sdmVkIC0gTWF4IHZzIFRlbXBlcmF0dXJlKio6IEtvcmVsw6FjaWEgamUgKipzbGFiw6EgYcW+IG51bG92w6EqKiAoYmllbGEgZmFyYmEpLCDEjW8gbmF6bmHEjXVqZSwgxb5lIHRlcGxvdGEgbmVtw6EgdsO9cmF6bsO9IHZwbHl2IG5hIG1ub8W+c3R2byByb3pwdXN0ZW7DqWhvIGt5c2zDrWthLgoKVGVudG8gZ3JhZiBuw6FtIHRlZGEgdWthenVqZSwgxb5lICoqem5lxI1pc3RlbmllIHZvZHkqKiAoQk9EKSBqZSBuZWdhdMOtdm5lIGtvcmVsb3ZhbsOpIHMgKiprdmFsaXRvdSB2b2R5KiogKHJvenB1c3RlbsO9IGt5c2zDrWspIGEgKip0ZXBsb3RvdSB2b2R5KiouCgojIFrDoWtsYWRuw6kgxaF0YXRpc3Rpa3kKCmBgYHtyfQpsaWJyYXJ5KGRwbHlyKQpsaWJyYXJ5KGtuaXRyKQpsaWJyYXJ5KGthYmxlRXh0cmEpCgojIHrDoWtsYWRuw6kgxaF0YXRpc3Rpa3kgcG9kxL5hIHJva3UKCndhdGVyLnN0YXRzIDwtIEluZGlhbl93YXRlcl9kYXRhICU+JQpncm91cF9ieShZZWFyKSAlPiUKc3VtbWFyaXNlKApuICAgICAgPSBuKCksCm1lYW4gICA9IG1lYW4oYERpc3NvbHZlZCAtIE1heGAsIG5hLnJtID0gVFJVRSksCnNkICAgICA9IHNkKGBEaXNzb2x2ZWQgLSBNYXhgLCBuYS5ybSA9IFRSVUUpLAptaW4gICAgPSBtaW4oYERpc3NvbHZlZCAtIE1heGAsIG5hLnJtID0gVFJVRSksCnEyNSAgICA9IHF1YW50aWxlKGBEaXNzb2x2ZWQgLSBNYXhgLCAwLjI1LCBuYS5ybSA9IFRSVUUpLAptZWRpYW4gPSBtZWRpYW4oYERpc3NvbHZlZCAtIE1heGAsIG5hLnJtID0gVFJVRSksCnE3NSAgICA9IHF1YW50aWxlKGBEaXNzb2x2ZWQgLSBNYXhgLCAwLjc1LCBuYS5ybSA9IFRSVUUpLAptYXggICAgPSBtYXgoYERpc3NvbHZlZCAtIE1heGAsIG5hLnJtID0gVFJVRSksCi5ncm91cHMgPSAiZHJvcCIKKQoKIyBDcmVhdGUgc3R5bGVkIGthYmxlRXh0cmEgdGFibGUKCndhdGVyLnN0YXRzICU+JQprYWJsZSgKZGlnaXRzID0gMiwKY2FwdGlvbiA9ICJaw6FrbGFkbsOpIMWhdGF0aXN0aWt5IHByZSBEaXNzb2x2ZWQgLSBNYXggKFJvenB1c3RlbsO9IGt5c2zDrWspIHBvZMS+YSByb2tvdiIKKSAlPiUKa2FibGVfc3R5bGluZygKZnVsbF93aWR0aCA9IEZBTFNFLApib290c3RyYXBfb3B0aW9ucyA9IGMoInN0cmlwZWQiLCAiaG92ZXIiLCAiY29uZGVuc2VkIikKKSAlPiUKY29sdW1uX3NwZWMoMSwgYm9sZCA9IFRSVUUpICU+JSAgICAgICAgICAgICAgICAgICAgICMgWnbDvXJhem7DrSBwcnbDvSBzdMS6cGVjIChZZWFyKQpyb3dfc3BlYygwLCBib2xkID0gVFJVRSwgYmFja2dyb3VuZCA9ICIjZjJmMmYyIikgICAjIMWgdMO9bCBobGF2acSNa3kKYGBgCk5hIHRlanRvIHRhYnXEvmtlIHPDuiB1dmVkZW7DqSB6w6FrbGFkbsOpIMWhdGF0aXN0aWt5IHByZSBob2Rub3R5ICoqRGlzc29sdmVkIC0gTWF4KiogKFJvenB1c3RlbsO9IGt5c2zDrWspIHBvZMS+YSByb2tvdiAoKioyMDIxKiosICoqMjAyMioqLCAqKjIwMjMqKikuIFogdMO9Y2h0byDFoXRhdGlzdMOtayBtw7TFvmVtZSB2ecSNw610YcWlIG5pZWtvxL5rbyBrxL7DusSNb3bDvWNoIGluZm9ybcOhY2nDrToKCi0gKipQcmllbWVybsOpIGhvZG5vdHkgcm96cHVzdGVuw6lobyBreXNsw61rYSoqIGtsZXNsaSB6ICoqNy44MCBtZy9MKiogdiByb2t1IDIwMjEgbmEgKio3LjQ3IG1nL0wqKiB2IHJva3UgMjAyMy4KLSAqKlZhcmlhYmlsaXRhKiogKMWhdGFuZGFyZG7DoSBvZGNow71sa2EpIHNhIHp2ecWhdWplLCDEjW8gbmF6bmHEjXVqZSB2w6TEjcWhaXUgcm96bWFuaXRvc8WlIGhvZG7DtHQgdiByb2t1IDIwMjMgdiBwb3Jvdm5hbsOtIHMgcHJlZGNow6FkemFqw7pjaW1pIHJva21pLgotICoqTWluaW3DoWxuZSBob2Rub3R5KiogdiByb2t1IDIwMjMgYm9saSAqKm5ham5pxb7FoWllKiosIMSNbyBuYXpuYcSNdWplIG5pxb7FoWl1IGt2YWxpdHUgdm9keSB2IHVyxI1pdMO9Y2ggbWllc3RhY2guCi0gKipNZWRpw6FuIGEgNzUuIHBlcmNlbnRpbCoqIG5hem5hxI11asO6LCDFvmUgdsOkxI3FoWluYSBob2Ruw7R0IHJvenB1c3RlbsOpaG8ga3lzbMOta2Egc2EgcG9oeWJvdmFsYSB2byB2ecWhxaHDrWNoIGhvZG5vdMOhY2ggdiByb2tvY2ggKioyMDIxKiogYSAqKjIwMjIqKiwgemF0aWHEviDEjW8gdiByb2t1ICoqMjAyMyoqIHNhIGhvZG5vdHkgdHJvY2h1IHpuw63FvmlsaS4KClTDoXRvIHRhYnXEvmthIHBvc2t5dHVqZSB1xb5pdG/EjW7DqSDFoXRhdGlzdGlreSBuYSBob2Rub3RlbmllICoqa3ZhbGl0eSB2b2R5KiogdiBwcmllYmVodSB0w71jaHRvIHRyb2NoIHJva292LgoKIyBUZXN0b3ZhbmllIGh5cG90w6l6CgojIyB0LXRlc3Q6IFBvcm92bmFuaWUgcHJpZW1lcnUgVGVtcGVyYXR1cmUgKEMpIC0gTWF4IHYgcm9rb2NoIDIwMjEgYSAyMDIzCmBgYHtyfQpsaWJyYXJ5KGthYmxlRXh0cmEpCgojIFZ5a29uYW5pZSB0LXRlc3R1Cgp0LnRlc3QucmVzdWx0IDwtIHQudGVzdCgKSW5kaWFuX3dhdGVyX2RhdGEkYFRlbXBlcmF0dXJlIChDKSAtIE1heGBbSW5kaWFuX3dhdGVyX2RhdGEkWWVhciA9PSAyMDIxXSwKSW5kaWFuX3dhdGVyX2RhdGEkYFRlbXBlcmF0dXJlIChDKSAtIE1heGBbSW5kaWFuX3dhdGVyX2RhdGEkWWVhciA9PSAyMDIzXQopCgojIFZ5dHZvcmVuaWUgdGFidcS+a3kgcyB2w71zbGVka2FtaSB0LXRlc3R1Cgp0LnRlc3Quc3VtbWFyeSA8LSBkYXRhLmZyYW1lKApTdGF0aXN0aWMgPSBjKCJ0LXN0YXRpc3RpYyIsICJkZiIsICJwLXZhbHVlIiwgImNvbmZpZGVuY2UgaW50ZXJ2YWwgKGxvd2VyKSIsICJjb25maWRlbmNlIGludGVydmFsICh1cHBlcikiKSwKVmFsdWUgPSBjKHQudGVzdC5yZXN1bHQkc3RhdGlzdGljLAp0LnRlc3QucmVzdWx0JHBhcmFtZXRlciwKdC50ZXN0LnJlc3VsdCRwLnZhbHVlLAp0LnRlc3QucmVzdWx0JGNvbmYuaW50WzFdLAp0LnRlc3QucmVzdWx0JGNvbmYuaW50WzJdKQopCgojIFpvYnJhemVuaWUgdGFidcS+a3kgcyBrYWJsZUV4dHJhCgp0LnRlc3Quc3VtbWFyeSAlPiUKa2FibGUoY2FwdGlvbiA9ICJWw71zbGVka3kgdC10ZXN0dSBtZWR6aSByb2ttaSAyMDIxIGEgMjAyMyBwcmUgdGVwbG90dSAoQykgLSBNYXgiKSAlPiUKa2FibGVfc3R5bGluZyhib290c3RyYXBfb3B0aW9ucyA9IGMoInN0cmlwZWQiLCAiaG92ZXIiLCAiY29uZGVuc2VkIikpICU+JQpjb2x1bW5fc3BlYygxLCBib2xkID0gVFJVRSkgJT4lCnJvd19zcGVjKDAsIGJvbGQgPSBUUlVFLCBiYWNrZ3JvdW5kID0gIiNmMmYyZjIiKQpgYGAKVMOhdG8gdGFidcS+a2Egem9icmF6dWplIHbDvXNsZWRreSAqKnQtdGVzdHUqKiBtZWR6aSByb2ttaSAqKjIwMjEqKiBhICoqMjAyMyoqIHByZSBob2Rub3R5ICoqdGVwbG90eSAoQykgLSBNYXgqKi4gWiB0w71jaHRvIHbDvXNsZWRrb3YgbcO0xb5lbWUgdnnEjcOtdGHFpToKCiMjIyBWw71zbGVka3kKLSAqKnQtc3RhdGlzdGljKio6IEhvZG5vdGEgdC10ZXN0dSBqZSAqKi0wLjY0NDEqKiwgxI1vIG5hem5hxI11amUsIMW+ZSByb3pkaWVsIG1lZHppIHByaWVtZXJuw71taSBob2Rub3RhbWkgdGVwbG90eSB2IHJva29jaCAyMDIxIGEgMjAyMyBuaWUgamUgdmXEvmvDvS4KLSAqKmRmIChkZWdyZWVzIG9mIGZyZWVkb20pKio6IFBvxI1ldCBzdHVwxYhvdiB2b8S+bm9zdGkgamUgKioxMTUuNzQqKiwgxI1vIGplIGtvbWJpbm92YW7DoSB2ZcS+a29zxaUgb2JvY2ggdnpvcmllay4KLSAqKnAtdmFsdWUqKjogSG9kbm90YSAqKnAgPSAwLjUyMDgqKiwga3RvcsOhIGplIHZ5xaHFoWlhIGFrbyBwcmFoICoqMC4wNSoqLCB6bmFtZW7DoSwgxb5lIHJvemRpZWwgbWVkemkgcm9rbWkgMjAyMSBhIDIwMjMgbmllIGplIMWhdGF0aXN0aWNreSB2w716bmFtbsO9LgotICoqY29uZmlkZW5jZSBpbnRlcnZhbCAobG93ZXIpKio6IERvbG7DoSBocmFuaWNhIGtvbmZpZGVuxI1uw6lobyBpbnRlcnZhbHUgamUgKiotMy4wODI3KiouCi0gKipjb25maWRlbmNlIGludGVydmFsICh1cHBlcikqKjogSG9ybsOhIGhyYW5pY2Ega29uZmlkZW7EjW7DqWhvIGludGVydmFsdSBqZSAqKjEuNTY5NyoqLgoKIyMjIFrDoXZlcgpOYSB6w6FrbGFkZSAqKnAtaG9kbm90eSAwLjUyMDgqKiBhICoqa29uZmlkZW7EjW7DqWhvIGludGVydmFsdSoqLCBrdG9yw70gemFoxZXFiGEgesOhcG9ybsOpIGFqIGtsYWRuw6kgaG9kbm90eSwgbcO0xb5lbWUgcG92ZWRhxaUsIMW+ZSAqKnJvemRpZWwgbWVkemkgdGVwbG90YW1pIHYgcm9rb2NoIDIwMjEgYSAyMDIzIG5pZSBqZSDFoXRhdGlzdGlja3kgdsO9em5hbW7DvSoqLiBUbyB6bmFtZW7DoSwgxb5lIG5lZXhpc3R1amUgZG9zdGF0b8SNbsO9IGTDtGtheiwgxb5lIGJ5IHNhIHRlcGxvdGEgbWVkemkgdMO9bWl0byBkdm9tYSByb2ttaSB2w71yYXpuZSBtZW5pbGEuCgojIyBBTk9WQQpgYGB7cn0KbGlicmFyeShrYWJsZUV4dHJhKQoKIyBWeWtvbmFuaWUgQU5PVkEgdGVzdHUKCmFub3ZhLnJlc3VsdCA8LSBhb3YoYFRlbXBlcmF0dXJlIChDKSAtIE1heGAgfiBmYWN0b3IoWWVhciksIGRhdGEgPSBJbmRpYW5fd2F0ZXJfZGF0YSkKCiMgWmhybnV0aWUgdsO9c2xlZGtvdiBBTk9WQQoKYW5vdmEuc3VtbWFyeSA8LSBzdW1tYXJ5KGFub3ZhLnJlc3VsdClbWzFdXQoKIyBWeXR2b3JlbmllIHRhYnXEvmt5IHMgdsO9c2xlZGthbWkgQU5PVkEKCmFub3ZhLnRhYmxlIDwtIGRhdGEuZnJhbWUoCkRmID0gYW5vdmEuc3VtbWFyeSREZiwKU3VtX1NxID0gYW5vdmEuc3VtbWFyeSRgU3VtIFNxYCwKTWVhbl9TcSA9IGFub3ZhLnN1bW1hcnkkYE1lYW4gU3FgLApGX3ZhbHVlID0gYW5vdmEuc3VtbWFyeSRgRiB2YWx1ZWAsClByX0YgPSBhbm92YS5zdW1tYXJ5JGBQcig+RilgCikKCiMgWm9icmF6ZW5pZSB0YWJ1xL5reSBzIGthYmxlRXh0cmEKCmFub3ZhLnRhYmxlICU+JQprYWJsZShjYXB0aW9uID0gIlbDvXNsZWRreSBBTk9WQSB0ZXN0dSBwcmUgdGVwbG90dSAoQykgLSBNYXggcG9kxL5hIHJva292IikgJT4lCmthYmxlX3N0eWxpbmcoYm9vdHN0cmFwX29wdGlvbnMgPSBjKCJzdHJpcGVkIiwgImhvdmVyIiwgImNvbmRlbnNlZCIpKSAlPiUKY29sdW1uX3NwZWMoMSwgYm9sZCA9IFRSVUUpICU+JQpyb3dfc3BlYygwLCBib2xkID0gVFJVRSwgYmFja2dyb3VuZCA9ICIjZjJmMmYyIikKYGBgClTDoXRvIHRhYnXEvmthIHpvYnJhenVqZSB2w71zbGVka3kgKipBTk9WQSoqIHRlc3R1IHByZSB0ZXBsb3R1IChDKSAtIE1heCBwb2TEvmEgcm9rb3YuCgojIyMgVsO9c2xlZGt5CgotICoqRGYgKGRlZ3JlZXMgb2YgZnJlZWRvbSkqKjogCiAgLSAyIHByZSBtZWR6aS1za3VwaW5vdsO6IHZhcmlhYmlsaXR1IChyb2t5KS4KICAtIDE4OSBwcmUgdm7DunRvci1za3VwaW5vdsO6IHZhcmlhYmlsaXR1IChwb8SNZXQgcG96b3JvdmFuw60gLSAxKS4KLSAqKlN1bV9TcSAoU3VtIG9mIFNxdWFyZXMpKio6CiAgLSBQcmUgbWVkemktc2t1cGlub3bDuiB2YXJpYWJpbGl0dSBqZSAqKjc4LjMwNzYqKi4KICAtIFByZSB2bsO6dG9yLXNrdXBpbm92w7ogdmFyaWFiaWxpdHUgamUgKio4MjE0LjA4NDkqKi4KLSAqKk1lYW5fU3EgKE1lYW4gU3F1YXJlKSoqOgogIC0gUHJlIG1lZHppLXNrdXBpbm92w7ogdmFyaWFiaWxpdHUgamUgKiozOS4xNTM4KiouCiAgLSBQcmUgdm7DunRvci1za3VwaW5vdsO6IHZhcmlhYmlsaXR1IGplICoqNDMuNDYwOCoqLgotICoqRl92YWx1ZSoqOiBIb2Rub3RhIEYgdGVzdHUgamUgKiowLjkwMDkqKiwgxI1vIG5hem5hxI11amUsIMW+ZSByb3pkaWVsIG1lZHppIHNrdXBpbmFtaSAocm9rbWkpIG5pZSBqZSB2w71yYXpuw70uCi0gKipQcl9GIChwLXZhbHVlKSoqOiBIb2Rub3RhIHAgamUgKiowLjQwNzkqKiwgxI1vIGplIHZ5xaHFoWllIG5lxb4gYmXFvm7DvSBwcmFoICoqMC4wNSoqLCB0YWvFvmUgcm96ZGllbCBtZWR6aSByb2ttaSAqKm5pZSBqZSDFoXRhdGlzdGlja3kgdsO9em5hbW7DvSoqLgoKIyMjIFrDoXZlcgpOYSB6w6FrbGFkZSB2w71zbGVka292IEFOT1ZBIHRlc3R1IG3DtMW+ZW1lIHV6YXZyaWXFpSwgxb5lICoqcm96ZGllbCBtZWR6aSB0ZXBsb3RhbWkgdiByb2tvY2ggMjAyMSBhIDIwMjMgbmllIGplIMWhdGF0aXN0aWNreSB2w716bmFtbsO9KiouIFRvIHpuYW1lbsOhLCDFvmUgbmEgesOha2xhZGUgdMO9Y2h0byDDumRham92IG5lbcOhbWUgZMO0a2F6LCDFvmUgYnkgc2EgdGVwbG90YSBtZWR6aSB0w71taXRvIGR2b21hIHJva21pIGzDrcWhaWxhLgoKIyMgTGluZWFyIFJlZ3Jlc3Npb24gCmBgYHtyfQpsaWJyYXJ5KGthYmxlRXh0cmEpCgojIFZ5a29uYW5pZSBsaW5lw6FybmVqIHJlZ3Jlc2llCgptb2RlbCA8LSBsbShgQk9EIChtZy9MKSAtIE1heGAgfiBgVGVtcGVyYXR1cmUgKEMpIC0gTWF4YCwgZGF0YSA9IEluZGlhbl93YXRlcl9kYXRhKQoKIyBaaHJudXRpZSBtb2RlbHUKCm1vZGVsLnN1bW1hcnkgPC0gc3VtbWFyeShtb2RlbCkKCiMgVnl0dm9yZW5pZSB0YWJ1xL5reSBzIHbDvXNsZWRrYW1pIGxpbmXDoXJuZWogcmVncmVzaWUKCm1vZGVsLnRhYmxlIDwtIGRhdGEuZnJhbWUoClRlcm0gPSByb3duYW1lcyhtb2RlbC5zdW1tYXJ5JGNvZWZmaWNpZW50cyksCkVzdGltYXRlID0gbW9kZWwuc3VtbWFyeSRjb2VmZmljaWVudHNbLCAxXSwKU3RkX0Vycm9yID0gbW9kZWwuc3VtbWFyeSRjb2VmZmljaWVudHNbLCAyXSwKdF92YWx1ZSA9IG1vZGVsLnN1bW1hcnkkY29lZmZpY2llbnRzWywgM10sClByX3QgPSBtb2RlbC5zdW1tYXJ5JGNvZWZmaWNpZW50c1ssIDRdCikKCiMgWm9icmF6ZW5pZSB0YWJ1xL5reSBzIGthYmxlRXh0cmEKCm1vZGVsLnRhYmxlICU+JQprYWJsZShjYXB0aW9uID0gIlbDvXNsZWRreSBsaW5lw6FybmVqIHJlZ3Jlc2llIG1lZHppIEJPRCAobWcvTCkgLSBNYXggYSBUZXBsb3RvdSAoQykgLSBNYXgiKSAlPiUKa2FibGVfc3R5bGluZyhib290c3RyYXBfb3B0aW9ucyA9IGMoInN0cmlwZWQiLCAiaG92ZXIiLCAiY29uZGVuc2VkIikpICU+JQpjb2x1bW5fc3BlYygxLCBib2xkID0gVFJVRSkgJT4lCnJvd19zcGVjKDAsIGJvbGQgPSBUUlVFLCBiYWNrZ3JvdW5kID0gIiNmMmYyZjIiKQpgYGAKVMOhdG8gdGFidcS+a2Egem9icmF6dWplIHbDvXNsZWRreSAqKmxpbmXDoXJuZWogcmVncmVzaWUqKiBtZWR6aSAqKkJPRCAobWcvTCkgLSBNYXgqKiBhICoqVGVwbG90b3UgKEMpIC0gTWF4KiouCgojIyMgVsO9c2xlZGt5CgotICoqKEludGVyY2VwdCkqKjogS29lZmljaWVudCBwcmUgaW50ZXJjZXB0IChwcmllc2XEjW7DrWsgcyBvc291IFkpIGplICoqMy4yMDE5OTYyKiouIFRvIHpuYW1lbsOhLCDFvmUga2XEjyB0ZXBsb3RhIGplICoqMMKwQyoqLCBwcmVkcG9rbGFkYW7DoSBob2Rub3RhIEJPRCBqZSBwcmlibGnFvm5lICoqMy4yIG1nL0wqKi4KLSAqKlRlbXBlcmF0dXJlIChDKSAtIE1heCoqOiBLb2VmaWNpZW50IHByZSB0ZXBsb3R1IGplICoqMC4wNjM4OTcyKiosIMSNbyBuYXpuYcSNdWplLCDFvmUgcHJpIGthxb5kb20genbDvcWhZW7DrSB0ZXBsb3R5IG8gKioxwrBDKiogc2EgaG9kbm90YSBCT0QgenbDvcWhaSBwcmlibGnFvm5lIG8gKiowLjA2NCBtZy9MKiouCi0gKipTdGRfRXJyb3IqKjogxaB0YW5kYXJkbsOhIGNoeWJhIGtvZWZpY2llbnRvdiwga3RvcsOhIG1lcmlhIHZhcmlhYmlsaXR1IG9kaGFkb3ZhbsO9Y2ggaG9kbsO0dDoKICAtIFByZSBpbnRlcmNlcHQgamUgKiozLjI1MzQ2NTgqKi4KICAtIFByZSB0ZXBsb3R1IGplICoqMC4xMTQ0MTA2KiouCi0gKip0X3ZhbHVlKio6IFRlc3RvdsOhIGhvZG5vdGEgKHQtaG9kbm90YSkgcHJlIG9iaWR2ZSBwcmVtZW5uw6k6CiAgLSBQcmUgaW50ZXJjZXB0IGplICoqMC45ODQxODAxKiouCiAgLSBQcmUgdGVwbG90dSBqZSAqKjAuNTU4NDkwNSoqLiBUaWV0byBob2Rub3R5IG5hem5hxI11asO6LCDFvmUgdC10ZXN0IHByZSBvYmUgcHJlbWVubsOpIG5pZSBqZSB2ZcS+bWkgc2lsbsO9LgotICoqUHJfdCAocC12YWx1ZSkqKjogUC1ob2Rub3RhIHByZSBvYmEga29lZmljaWVudHk6CiAgLSBQcmUgaW50ZXJjZXB0IGplICoqMC4zMjYzNzgwKiouCiAgLSBQcmUgdGVwbG90dSBqZSAqKjAuNTc3MjE5MyoqLiBPYmlkdmUgcC1ob2Rub3R5IHPDuiB2ecWhxaFpZSBuZcW+IGJlxb5uw70gcHJhaCAqKjAuMDUqKiwgxI1vIHpuYW1lbsOhLCDFvmUgKipyb3pkaWVseSBtZWR6aSBCT0QgYSB0ZXBsb3RvdSBuaWUgc8O6IMWhdGF0aXN0aWNreSB2w716bmFtbsOpKiouCgojIyMgWsOhdmVyClbDvXNsZWRreSByZWdyZXNpZSBuYXpuYcSNdWrDuiwgxb5lICoqbmVleGlzdHVqZSDFoXRhdGlzdGlja3kgdsO9em5hbW7DvSB2esWlYWgqKiBtZWR6aSB0ZXBsb3RvdSBhIEJPRCwgcHJldG/FvmUgcC1ob2Rub3R5IHPDuiB2w6TEjcWhaWUgbmXFviAwLjA1LiBUbyB6bmFtZW7DoSwgxb5lIG5hIHrDoWtsYWRlIHTDvWNodG8gw7pkYWpvdiBuZW3DoW1lIGRvc3RhdG/EjW7DvSBkw7RrYXosIMW+ZSBieSB6bWVuYSB0ZXBsb3R5IG1hbGEgdsO9em5hbW7DvSB2cGx5diBuYSBob2Rub3R5IEJPRC4KCgoKCg==