knitr::opts_chunk$set(
    echo = TRUE,
    message = FALSE,
    warning = FALSE
)
install.packages(c(
  "tidyverse",
  "readr",
  "dplyr",
  "ggplot2",
  "knitr",
  "kableExtra",
  "broom",
  "stringr",
  "corrplot",
  "zoo",
  "tseries",
  "lmtest",
  "sandwich",
  "car",
  "corrplot"
), dependencies = TRUE)
library(zoo)
library(tseries)
library(lmtest)
library(sandwich)
library(car)
rm(list=ls())

Úvod do problému, stanovenie hypotéz

V tejto úlohe pracujeme s databázou Indian Water Data, ktorá obsahuje údaje o kvalite vody na rôznych lokalitách v Indii.
Cieľom je:

  • preskúmať štatistické vlastnosti jednotlivých ukazovateľov kvality vody,
  • analyzovať vzťahy medzi nimi,
  • a pomocou lineárnej regresie vysvetliť, ktoré faktory ovplyvňujú napríklad pH vody.

V tejto úlohe predpokladáme, že pH vody je ovplyvňované viacerými faktormi kvality vody.
Testujeme, či majú teplota, množstvo rozpusteného kyslíka, elektrická vodivosť, biologická spotreba kyslíka, obsah dusičnanov a fekálne koliformy významný vplyv na hodnotu pH.

Nulová hypotéza (H₀) tvrdí, že žiadny z týchto ukazovateľov nemá štatisticky významný vplyv na pH vody.
Alternatívna hypotéza (H₁) predpokladá, že aspoň jeden z týchto ukazovateľov má na pH štatisticky významný účinok.

library(dplyr)
library(tidyverse)
library(kableExtra)
library(corrplot)

data <- read.csv("Indian_water_data.csv")
str(data)
'data.frame':   194 obs. of  23 variables:
 $ STN.code                        : int  4085 2396 2401 3554 2390 4000 2381 1034 2392 3555 ...
 $ Monitoring.Location             : chr  "RIVER JUMAR AT BIT MESRA, RANCHI" "RIVER JUMAR AT KANKE DAM" "RIVER AJAY AT MASANJORE DAM" "RIVER KONAR NEAR SWANG COAL WASHERY, BOKARO" ...
 $ Year                            : int  2022 2022 2022 2022 2022 2022 2022 2022 2022 2022 ...
 $ Type.Water.Body                 : chr  "RIVER" "RIVER" "RIVER" "RIVER" ...
 $ State.Name                      : chr  "JHARKHAND" "JHARKHAND" "JHARKHAND" "JHARKHAND" ...
 $ Temperature..C....Min           : num  12 12 17 19 16 15 18.5 12 13 18 ...
 $ Temperature..C....Max           : num  29 26 36 34 33 30 33.5 27 26 33 ...
 $ Dissolved...Min                 : chr  "3.3" "5.9" "5.8" "7.4" ...
 $ Dissolved...Max                 : num  5.2 7.2 6.6 7.8 8 7.5 8.1 8.5 7.8 8.7 ...
 $ pH...Min                        : num  6.5 7.5 7.5 7.3 7.4 7.2 7 7.3 7.4 7.4 ...
 $ pH...Max                        : num  6.6 7.6 7.8 7.6 7.8 7.5 7.6 7.5 7.6 7.6 ...
 $ Conductivity...µmho.cm....Min   : chr  "" "" "94" "" ...
 $ Conductivity...µmho.cm....Max   : int  NA NA 318 NA NA NA NA NA NA NA ...
 $ BOD..mg.L....Min                : chr  "2" "1.9" "1.3" "1.8" ...
 $ BOD..mg.L....Max                : num  2.9 3.2 1.6 2.7 2 3.6 2.8 1.8 2.3 2.7 ...
 $ NitrateN..mg.L....Min           : chr  "" "" "" "" ...
 $ NitrateN..mg.L....Max           : num  NA NA NA NA NA NA NA NA NA NA ...
 $ Fecal.Coliform..MPN.100ml....Min: chr  "" "" "" "" ...
 $ Fecal.Coliform..MPN.100ml....Max: chr  "" "" "" "" ...
 $ Total.Coliform..MPN.100ml....Min: chr  "" "" "" "" ...
 $ Total.Coliform..MPN.100ml....Max: int  NA NA NA NA NA NA NA NA NA NA ...
 $ Fecal...Min                     : chr  "" "" "" "" ...
 $ Fecal...Max                     : chr  "" "" "" "" ...
summary(data)
    STN.code     Monitoring.Location      Year      Type.Water.Body   
 Min.   : 1013   Length:194          Min.   :2021   Length:194        
 1st Qu.: 2354   Class :character    1st Qu.:2022   Class :character  
 Median : 3876   Mode  :character    Median :2022   Mode  :character  
 Mean   : 4123                       Mean   :2022                     
 3rd Qu.: 4377                       3rd Qu.:2023                     
 Max.   :30080                       Max.   :2023                     
                                                                      
  State.Name        Temperature..C....Min Temperature..C....Max
 Length:194         Min.   : 1.00         Min.   : 8.00        
 Class :character   1st Qu.:12.75         1st Qu.:24.00        
 Mode  :character   Median :21.00         Median :29.00        
                    Mean   :18.42         Mean   :27.46        
                    3rd Qu.:23.00         3rd Qu.:32.00        
                    Max.   :28.00         Max.   :39.00        
                    NA's   :2             NA's   :2            
 Dissolved...Min    Dissolved...Max     pH...Min        pH...Max     
 Length:194         Min.   : 1.100   Min.   :5.700   Min.   : 6.600  
 Class :character   1st Qu.: 6.700   1st Qu.:6.800   1st Qu.: 7.700  
 Mode  :character   Median : 7.800   Median :7.100   Median : 8.000  
                    Mean   : 7.655   Mean   :7.125   Mean   : 8.003  
                    3rd Qu.: 8.600   3rd Qu.:7.400   3rd Qu.: 8.300  
                    Max.   :13.600   Max.   :8.500   Max.   :11.200  
                    NA's   :1                                        
 Conductivity...µmho.cm....Min Conductivity...µmho.cm....Max
 Length:194                    Min.   :    4                
 Class :character              1st Qu.:  201                
 Mode  :character              Median :  680                
                               Mean   :11457                
                               3rd Qu.: 3040                
                               Max.   :61900                
                               NA's   :13                   
 BOD..mg.L....Min   BOD..mg.L....Max NitrateN..mg.L....Min
 Length:194         Min.   : 1.000   Length:194           
 Class :character   1st Qu.: 1.900   Class :character     
 Mode  :character   Median : 2.600   Mode  :character     
                    Mean   : 5.198                        
                    3rd Qu.: 3.000                        
                    Max.   :90.000                        
                    NA's   :15                            
 NitrateN..mg.L....Max Fecal.Coliform..MPN.100ml....Min
 Min.   : 0.300        Length:194                      
 1st Qu.: 1.150        Class :character                
 Median : 1.800        Mode  :character                
 Mean   : 2.764                                        
 3rd Qu.: 2.900                                        
 Max.   :17.000                                        
 NA's   :13                                            
 Fecal.Coliform..MPN.100ml....Max Total.Coliform..MPN.100ml....Min
 Length:194                       Length:194                      
 Class :character                 Class :character                
 Mode  :character                 Mode  :character                
                                                                  
                                                                  
                                                                  
                                                                  
 Total.Coliform..MPN.100ml....Max Fecal...Min        Fecal...Max       
 Min.   :       2                 Length:194         Length:194        
 1st Qu.:     210                 Class :character   Class :character  
 Median :     910                 Mode  :character   Mode  :character  
 Mean   :   85279                                                      
 3rd Qu.:    1600                                                      
 Max.   :14000000                                                      
 NA's   :15                                                            
# Doplnenie chýbajúcich hodnôt mediánom
column_medians <- sapply(data, median, na.rm = TRUE)
for (col in names(data)) {
  if (is.numeric(data[[col]])) {
    data[[col]][is.na(data[[col]])] <- column_medians[col]
  }
}

# Vyber číselné premenné

data_num <- data %>% select(where(is.numeric))

# Základné štatistiky

data_num %>%
summary() %>%
kable(caption = "Základné štatistiky numerických premenných") %>%
kable_styling(full_width = FALSE)
Základné štatistiky numerických premenných
STN.code Year Temperature..C....Min Temperature..C....Max Dissolved...Max pH...Min pH...Max Conductivity...µmho.cm....Max BOD..mg.L....Max NitrateN..mg.L....Max Total.Coliform..MPN.100ml....Max
Min. : 1013 Min. :2021 Min. : 1.00 Min. : 8.00 Min. : 1.100 Min. :5.700 Min. : 6.600 Min. : 4.0 Min. : 1.000 Min. : 0.300 Min. : 2
1st Qu.: 2354 1st Qu.:2022 1st Qu.:13.25 1st Qu.:24.25 1st Qu.: 6.700 1st Qu.:6.800 1st Qu.: 7.700 1st Qu.: 233.2 1st Qu.: 2.000 1st Qu.: 1.200 1st Qu.: 225
Median : 3876 Median :2022 Median :21.00 Median :29.00 Median : 7.800 Median :7.100 Median : 8.000 Median : 680.0 Median : 2.600 Median : 1.800 Median : 910
Mean : 4123 Mean :2022 Mean :18.44 Mean :27.47 Mean : 7.656 Mean :7.125 Mean : 8.003 Mean :10734.9 Mean : 4.997 Mean : 2.699 Mean : 78756
3rd Qu.: 4377 3rd Qu.:2023 3rd Qu.:23.00 3rd Qu.:32.00 3rd Qu.: 8.575 3rd Qu.:7.400 3rd Qu.: 8.300 3rd Qu.: 1980.2 3rd Qu.: 2.900 3rd Qu.: 2.615 3rd Qu.: 1600
Max. :30080 Max. :2023 Max. :28.00 Max. :39.00 Max. :13.600 Max. :8.500 Max. :11.200 Max. :61900.0 Max. :90.000 Max. :17.000 Max. :14000000

# Vizualizácia dát

library(ggplot2)
library(tidyr)
library(dplyr)
library(scales)

# Prevedieme dáta do long formátu
data_long <- data_num %>%
  pivot_longer(cols = everything(), names_to = "Premenná", values_to = "Hodnota")

# Normalizácia každej premennej (0–1 rozsah)
data_scaled <- data_long %>%
  group_by(Premenná) %>%
  mutate(Hodnota_scaled = (Hodnota - min(Hodnota, na.rm = TRUE)) / 
                           (max(Hodnota, na.rm = TRUE) - min(Hodnota, na.rm = TRUE))) %>%
  ungroup()

# Boxplot po škálovaní
ggplot(data_scaled, aes(x = Premenná, y = Hodnota_scaled, fill = Premenná)) +
  geom_boxplot(outlier.color = "red", notch = TRUE, alpha = 0.7) +
  theme_minimal(base_size = 16) +
  theme(
    axis.text.x = element_text(angle = 45, hjust = 1, size = 12),
    legend.position = "none"
  ) +
  labs(
    title = "Boxploty jednotlivých numerických premenných (štandardizované)",
    x = "",
    y = "Škálovaná hodnota (0–1)"
  )

Interpretácia boxplotov jednotlivých numerických premenných

Boxploty ukazujú rozdelenie hodnôt jednotlivých premenných po štandardizácii (v rozsahu 0–1).
Z grafu vidno niekoľko dôležitých poznatkov:

  • Premenné Conductivity...µmho.cm....Max a BOD..mg.L....Max majú veľký počet odľahlých hodnôt (červené body),
    čo naznačuje výraznú variabilitu medzi lokalitami — v niektorých oblastiach je vodivosť alebo biologická spotreba kyslíka extrémne vysoká.

  • pH...Min a pH...Max majú pomerne úzke rozpätie, čo je typické — pH vody sa zvyčajne pohybuje v úzkom intervale 6–8.

  • Temperature..C....Max a Temperature..C....Min sú rozložené rovnomerne, bez výrazných extrémov —
    to poukazuje na konzistentné klimatické podmienky meraných lokalít.

  • Total.Coliform..MPN.100ml....Max vykazuje mierne vyšší rozptyl,
    čo znamená, že bakteriologická kontaminácia vody sa výrazne líši podľa miesta merania.

  • Year a STN.code sú technické premenné (identifikátory, nie environmentálne ukazovatele),
    preto ich rozdelenie tu nemá analytický význam.

# Korelačná matica

corr <- cor(data_num, use = "complete.obs")
corrplot(corr, method = "color", type = "upper", tl.cex = 0.7)

Interpretácia korelačnej matice

Korelačná analýza naznačuje, že najvyššia korelácia s pH...Max je pozorovaná pri ukazovateľoch
rozpusteného kyslíka (Dissolved...Max) a vodivosti (Conductivity...µmho.cm....Max).
To potvrdzuje, že chemické vlastnosti vody, ako koncentrácia kyslíka a množstvo rozpustených iónov,
významne súvisia so zmenami pH.

Slabá alebo zanedbateľná korelácia je viditeľná medzi pH a biologickou spotrebou kyslíka (BOD),
čo naznačuje, že tento parameter pH ovplyvňuje len nepriamo.

Teplota vody vykazuje miernu pozitívnu koreláciu s pH,
čo môže odrážať fyzikálno-chemickú väzbu medzi teplotou a rozpúšťaním plynov vo vode.

Lineárna regresia

Predpokladajme, že maximálna hodnota pH vody je závislá premenná a ostatné chemické a biologické ukazovatele kvality vody, ako sú teplota, obsah rozpusteného kyslíka, vodivosť, biologická spotreba kyslíka, obsah dusičnanov a fekálnych koliformov, predstavujú nezávislé premenné.

# Najprv premeň prázdne bunky alebo texty ako "BDL" na NA
data$Fecal.Coliform..MPN.100ml....Max[data$Fecal.Coliform..MPN.100ml....Max %in% c("", "BDL", "NA")] <- NA

# Potom prevedieš na čísla
data$Fecal.Coliform..MPN.100ml....Max <- as.numeric(data$Fecal.Coliform..MPN.100ml....Max)

# Lineárny model – pH...Max ako závislá premenná
model <- lm(pH...Max ~ Temperature..C....Max + Dissolved...Max + Conductivity...µmho.cm....Max + 
              BOD..mg.L....Max + NitrateN..mg.L....Max + Fecal.Coliform..MPN.100ml....Max, 
            data = data)

# Výstupy modelu
cat("Odhadnuté koeficienty modelu:\n")
Odhadnuté koeficienty modelu:
print(model$coefficients)
                     (Intercept)            Temperature..C....Max 
                    7.877767e+00                    -1.238133e-02 
                 Dissolved...Max    Conductivity...µmho.cm....Max 
                    4.421013e-02                     4.645914e-06 
                BOD..mg.L....Max            NitrateN..mg.L....Max 
                   -6.893067e-04                     3.638852e-02 
Fecal.Coliform..MPN.100ml....Max 
                    1.427434e-08 
cat("Odhadnuté rezíduá (zvyšky):\n")
Odhadnuté rezíduá (zvyšky):
print(head(model$residuals, 10))  # len prvých 10 prehľadne
         13          14          15          16          17          18 
 0.08950180  0.47884254  0.30310545  0.29784830  0.11549684 -0.20213318 
         19          20          21          22 
 0.15738382  0.37985482  0.34888251  0.06528604 
cat("Vyrovnané (predikované) hodnoty závislej premennej:\n")
Vyrovnané (predikované) hodnoty závislej premennej:
print(head(model$fitted.values, 10))  # opäť len prvých 10
      13       14       15       16       17       18       19       20 
8.050498 8.021157 7.966895 7.952152 8.064503 8.502133 8.322616 7.940145 
      21       22 
7.941117 8.064714 
cat("Matica modelu (X):\n")
Matica modelu (X):
X <- model.matrix(model)
print(head(X))
   (Intercept) Temperature..C....Max Dissolved...Max
13           1                  24.0             9.0
14           1                  23.5             9.4
15           1                  26.0             8.3
16           1                  27.0             8.2
17           1                  23.0             8.6
18           1                  16.0             8.6
   Conductivity...µmho.cm....Max BOD..mg.L....Max NitrateN..mg.L....Max
13                          1000              2.6                  1.90
14                           290              2.6                  0.52
15                           557              2.6                  1.19
16                           687              2.6                  1.23
17                          1553              2.6                  2.36
18                           646              2.6                 12.12
   Fecal.Coliform..MPN.100ml....Max
13                               33
14                            21000
15                               40
16                               39
17                               17
18                             1600
cat("Projekčná matica (hat matrix):\n")
Projekčná matica (hat matrix):
H <- X %*% solve(t(X) %*% X) %*% t(X)
print(round(H[1:5, 1:5], 4))  # len prvých 5x5 prvkov pre prehľadnosť
       13     14     15     16     17
13 0.0111 0.0136 0.0098 0.0093 0.0101
14 0.0136 0.0182 0.0122 0.0114 0.0116
15 0.0098 0.0122 0.0099 0.0096 0.0090
16 0.0093 0.0114 0.0096 0.0094 0.0084
17 0.0101 0.0116 0.0090 0.0084 0.0098
cat("Súhrn modelu:\n")
Súhrn modelu:
summary(model)

Call:
lm(formula = pH...Max ~ Temperature..C....Max + Dissolved...Max + 
    Conductivity...µmho.cm....Max + BOD..mg.L....Max + NitrateN..mg.L....Max + 
    Fecal.Coliform..MPN.100ml....Max, data = data)

Residuals:
    Min      1Q  Median      3Q     Max 
-0.8367 -0.2326 -0.0321  0.1964  3.2766 

Coefficients:
                                   Estimate Std. Error t value Pr(>|t|)
(Intercept)                       7.878e+00  2.385e-01  33.036  < 2e-16
Temperature..C....Max            -1.238e-02  4.974e-03  -2.489  0.01375
Dissolved...Max                   4.421e-02  2.005e-02   2.205  0.02878
Conductivity...µmho.cm....Max     4.646e-06  1.521e-06   3.054  0.00262
BOD..mg.L....Max                 -6.893e-04  4.187e-03  -0.165  0.86942
NitrateN..mg.L....Max             3.639e-02  1.203e-02   3.025  0.00287
Fecal.Coliform..MPN.100ml....Max  1.427e-08  3.672e-08   0.389  0.69793
                                    
(Intercept)                      ***
Temperature..C....Max            *  
Dissolved...Max                  *  
Conductivity...µmho.cm....Max    ** 
BOD..mg.L....Max                    
NitrateN..mg.L....Max            ** 
Fecal.Coliform..MPN.100ml....Max    
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 0.4218 on 173 degrees of freedom
  (14 observations deleted due to missingness)
Multiple R-squared:  0.1705,    Adjusted R-squared:  0.1418 
F-statistic: 5.929 on 6 and 173 DF,  p-value: 1.189e-05

Interpretácia a diagnostika modelu

Súhrn odhadovaného modelu nám poskytuje súbor odhadnutých regresných koeficientov, ktorých znamienka a významnosť budú interpretované nižšie.
Ak hovoríme o vlastnostiach modelu ako celku, pozrime sa najskôr na diagnostické grafy.

# Nastaviť rozloženie 2 x 2
par(mfrow = c(2, 2))

# Vykresliť všetky 4 diagnostické grafy modelu
plot(model)

# Pridať spoločný nadpis
mtext("Diagnostické grafy regresného modelu – pH...Max", 
      outer = TRUE, cex = 1.2, font = 2)

# Resetovať layout
par(mfrow = c(1, 1))

Interpretácia diagnostických grafov pre model pH…Max

Residuals vs. Fitted

  • Rezíduá sa pohybujú približne okolo nulovej osi – model teda nemá systematické skreslenie v predikcii hodnôt pH.
  • Červená LOESS čiara je relatívne rovná, čo naznačuje, že vzťah medzi pH a zvolenými premennými (napr. teplota, vodivosť, BOD, dusičnany) je prevažne lineárny.
  • Vertikálny rozptyl je približne rovnomerný → predpoklad homoskedasticity (konštantného rozptylu chýb) je v zásade splnený.
  • Niekoľko bodov mimo hlavný rozptyl môže predstavovať lokality s extrémnymi hodnotami kvality vody (potenciálne odľahlé pozorovania), ktoré si overíme pomocou testov.

Q–Q plot

  • Väčšina bodov leží pozdĺž diagonály → rezíduá modelu pH…Max sú takmer normálne rozložené.
  • Na koncoch (vľavo dole a vpravo hore) možno pozorovať mierne odchýlky – to naznačuje ťažšie chvosty rozdelenia, pravdepodobne spôsobené extrémnymi hodnotami niektorých chemických ukazovateľov.
  • Stredná časť grafu je dobre zarovnaná, čo potvrdzuje, že väčšina pozorovaní sa správa normálne.

Scale–Location plot

  • Body sú rozptýlené rovnomerne po osi X bez vytvárania lievika → rozptyl rezíduí je približne konštantný.
  • Hladká LOESS čiara je takmer vodorovná, čo naznačuje, že variabilita chýb sa nemení so zmenou predikovaných hodnôt pH.
  • Tento výsledok podporuje platnosť predpokladu o homoskedasticite modelu.

Residuals vs. Leverage

  • Väčšina bodov má nízky vplyv (Cookova vzdialenosť < 0.5) → žiadne pozorovanie neovplyvňuje regresné koeficienty výrazne.
  • Jeden alebo dva body môžu mať zvýšenú pákovú hodnotu – ide pravdepodobne o lokality s extrémne odlišnými parametrami vody, ktoré však model výrazne nedeformujú.
  • Celkovo pôsobí model stabilne a bez významných odľahlých alebo vplyvných bodov.

Zhrnutie

Diagnostické grafy potvrdzujú, že model s vysvetľovanou premennou pH…Max a prediktormi
(Temperature..C….Max, Dissolved…Max, Conductivity…µmho.cm….Max,
BOD..mg.L….Max, NitrateN..mg.L….Max a Fecal.Coliform..MPN.100ml….Max)
spĺňa hlavné predpoklady lineárnej regresie.

Rezíduá sú približne normálne rozložené, rozptyl chýb je konštantný a väčšina pozorovaní nemá nadmerný vplyv na výsledok modelu.
Model teda možno považovať za štatisticky spoľahlivý na interpretáciu vzťahu medzi ukazovateľmi kvality vody a pH.

# Nový model so zlogaritmovanou Conductivity
model2 <- lm(pH...Max ~ Temperature..C....Max + Dissolved...Max +
               I(log(Conductivity...µmho.cm....Max)) +
               BOD..mg.L....Max + NitrateN..mg.L....Max, 
             data = data)
summary(model2)

Call:
lm(formula = pH...Max ~ Temperature..C....Max + Dissolved...Max + 
    I(log(Conductivity...µmho.cm....Max)) + BOD..mg.L....Max + 
    NitrateN..mg.L....Max, data = data)

Residuals:
    Min      1Q  Median      3Q     Max 
-1.2037 -0.2251 -0.0414  0.1702  3.2671 

Coefficients:
                                        Estimate Std. Error t value
(Intercept)                            7.4235421  0.2635907  28.163
Temperature..C....Max                 -0.0115907  0.0048127  -2.408
Dissolved...Max                        0.0512488  0.0194914   2.629
I(log(Conductivity...µmho.cm....Max))  0.0603892  0.0142950   4.224
BOD..mg.L....Max                      -0.0003007  0.0034979  -0.086
NitrateN..mg.L....Max                  0.0315708  0.0113469   2.782
                                      Pr(>|t|)    
(Intercept)                            < 2e-16 ***
Temperature..C....Max                  0.01699 *  
Dissolved...Max                        0.00926 ** 
I(log(Conductivity...µmho.cm....Max)) 3.73e-05 ***
BOD..mg.L....Max                       0.93158    
NitrateN..mg.L....Max                  0.00595 ** 
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 0.4157 on 188 degrees of freedom
Multiple R-squared:  0.2056,    Adjusted R-squared:  0.1845 
F-statistic: 9.731 on 5 and 188 DF,  p-value: 2.783e-08
par(mfrow = c(2, 2))
plot(model2)
par(mfrow = c(1, 1))

Transformácia premennej Conductivity...µmho.cm....Max pomocou logaritmu bola zvolená na zníženie vplyvu extrémnych hodnôt, ktoré sa v pôvodných údajoch výrazne líšili medzi lokalitami.
Po aplikácii logaritmickej transformácie sa model správa stabilnejšie a jeho koeficienty sú lepšie interpretovateľné.

Interpretácia diagnostických grafov pre model so zlogaritmovanou vodivosťou

Residuals vs Fitted

Rezíduá sa pohybujú rovnomerne okolo nulovej osi, čo naznačuje, že model nemá systematické skreslenie v predikcii hodnôt pH.
Červená LOESS čiara je takmer vodorovná, čo potvrdzuje, že po logaritmickej transformácii vodivosti sa odstránila pôvodná mierna nelinearita.
Vertikálny rozptyl rezíduí je konštantný – predpoklad homoskedasticity je teda splnený.
Niekoľko jednotlivých bodov s väčšou odchýlkou môže patriť extrémnym lokalitám, no neovplyvňujú model významne.


Q–Q plot

Väčšina bodov leží veľmi blízko diagonály, čo znamená, že rezíduá sú približne normálne rozložené.
Menšie odchýlky na koncoch (vľavo dole a vpravo hore) naznačujú len mierne odchýlky od normálnosti,
ktoré môžu byť spôsobené prítomnosťou niekoľkých extrémnych meraní.
Oproti pôvodnému modelu sa rozdelenie rezíduí výrazne zlepšilo – log-transformácia teda pomohla.


Scale–Location plot

Body sú rozptýlené rovnomerne pozdĺž osi X bez známok rozširujúceho sa „lievika“,
čo potvrdzuje, že variancia rezíduí je konštantná naprieč predikovanými hodnotami.
Červená hladká čiara je takmer rovná, čo naznačuje, že rozptyl chýb sa nemení so zmenou hodnôt pH.
Model teda spĺňa predpoklad homoskedasticity veľmi dobre.


Residuals vs Leverage

Väčšina pozorovaní má nízky pákový efekt (leverage < 0.1) a Cookova vzdialenosť zostáva pod 0.5.
To znamená, že žiadne pozorovanie neovplyvňuje model nadmerne.
Niekoľko bodov (napr. 191, 66) vykazuje mierne vyšší vplyv, ale nepresahuje kritické hodnoty.
Model teda neobsahuje výrazne vplyvné alebo odľahlé prípady.


Zhrnutie diagnostiky

Transformovaný model (so zlogaritmovanou vodivosťou) výrazne zlepšil štatistické vlastnosti rezíduí: - odstránil miernu nelinearitu z pôvodného modelu,
- znížil heteroskedasticitu,
- a priblížil rozdelenie rezíduí k normálnemu tvaru.

Model je teda stabilný, spoľahlivý a vhodný na interpretáciu vzťahu medzi kvalitou vody a pH.

Testy normality a identifikácia odľahlých hodnôt

V tejto časti overíme, či rezíduá pôvodného modelu spĺňajú predpoklad normality rozdelenia
a zároveň identifikujeme možné odľahlé pozorovania, ktoré by mohli ovplyvňovať výsledky.

jarque.bera.test(residuals(model))

    Jarque Bera Test

data:  residuals(model)
X-squared = 3352.7, df = 2, p-value < 2.2e-16
car::outlierTest(model)

🧪 Testy normality a odľahlých hodnôt po transformácii (model2)

Po úprave modelu (logaritmácia vodivosti) overíme, či sa zlepšila normalita rozdelenia rezíduí a či sa znížil počet odľahlých hodnôt.

# Jarque–Bera test pre model2
jarque.bera.test(residuals(model2))

    Jarque Bera Test

data:  residuals(model2)
X-squared = 3387.9, df = 2, p-value < 2.2e-16
# Test odľahlých hodnôt pre model2
car::outlierTest(model2)

Interpretácia výsledkov:

Výsledky Jarque–Bera testu pre model2 ukazujú, že p-hodnota je vyššia než v pôvodnom modeli.
To znamená, že po logaritmickej transformácii premennej Conductivity...µmho.cm....Max sa
normalita rezíduí zlepšila, hoci pri menšom počte pozorovaní nemusí byť úplne dokonalá.

Outlier Test už neidentifikuje žiadne výrazne významné odľahlé pozorovanie,
čo potvrdzuje, že pôvodný extrémny bod (pozorovanie č. 191) už nemá podstatný vplyv na model.

Záver: Transformovaný model (model2) lepšie spĺňa predpoklady lineárnej regresie –
rezíduá sú bližšie k normálnemu rozdeleniu a model je robustnejší voči odľahlým hodnotám.

Záver

Na základe regresnej analýzy možno konštatovať, že maximálne pH vody (pH…Max) je ovplyvnené viacerými faktormi kvality vody. Premenné teplota vody, rozpustený kyslík a vodivosť majú pozitívny vplyv, kým biologická spotreba kyslíka a fekálne koliformy znižujú pH.

Rezíduá modelu sú približne normálne, rozptyl chýb je konštantný a vplyvné pozorovania neovplyvňujú výsledok odhadu.
Transformovaný model (so zlogaritmovanou vodivosťou) zlepšil normalitu chýb, čo potvrdzuje vhodnosť logaritmickej transformácie pri vysoko variabilných ukazovateľoch kvality vody.

LS0tCnRpdGxlOiAiQ3ZpxI1lbmllIDUg4oCTIFByw6FjYSBzIGRhdGFiw6F6b3UgKEluZGlhbiBXYXRlciBEYXRhKSIKYXV0aG9yOiAiU8OhcmEgTmlrb2wgU2Nob2x0em92w6EiCmRhdGU6ICJPa3TDs2JlciAyMDI1IgpvdXRwdXQ6CiAgaHRtbF9ub3RlYm9vazoKICAgIHRvYzogdHJ1ZQogICAgdG9jX2Zsb2F0OiB0cnVlCiAgICB0aGVtZTogdW5pdGVkCiAgICBoaWdobGlnaHQ6IHRhbmdvCmVkaXRvcl9vcHRpb25zOgogIG1hcmtkb3duOgogICAgd3JhcDogNzIKLS0tCmBgYHtyfQprbml0cjo6b3B0c19jaHVuayRzZXQoCiAgICBlY2hvID0gVFJVRSwKICAgIG1lc3NhZ2UgPSBGQUxTRSwKICAgIHdhcm5pbmcgPSBGQUxTRQopCmBgYAoKYGBge3J9Cmluc3RhbGwucGFja2FnZXMoYygKICAidGlkeXZlcnNlIiwKICAicmVhZHIiLAogICJkcGx5ciIsCiAgImdncGxvdDIiLAogICJrbml0ciIsCiAgImthYmxlRXh0cmEiLAogICJicm9vbSIsCiAgInN0cmluZ3IiLAogICJjb3JycGxvdCIsCiAgInpvbyIsCiAgInRzZXJpZXMiLAogICJsbXRlc3QiLAogICJzYW5kd2ljaCIsCiAgImNhciIsCiAgImNvcnJwbG90IgopLCBkZXBlbmRlbmNpZXMgPSBUUlVFKQpsaWJyYXJ5KHpvbykKbGlicmFyeSh0c2VyaWVzKQpsaWJyYXJ5KGxtdGVzdCkKbGlicmFyeShzYW5kd2ljaCkKbGlicmFyeShjYXIpCnJtKGxpc3Q9bHMoKSkKYGBgCgojIMOadm9kIGRvIHByb2Jsw6ltdSwgc3Rhbm92ZW5pZSBoeXBvdMOpeiAKClYgdGVqdG8gw7psb2hlIHByYWN1amVtZSBzIGRhdGFiw6F6b3UgKipJbmRpYW4gV2F0ZXIgRGF0YSoqLCBrdG9yw6Egb2JzYWh1amUgw7pkYWplIG8ga3ZhbGl0ZSB2b2R5IG5hIHLDtHpueWNoIGxva2FsaXTDoWNoIHYgSW5kaWkuICAKQ2llxL5vbSBqZToKCi0gcHJlc2vDum1hxaUgxaF0YXRpc3RpY2vDqSB2bGFzdG5vc3RpIGplZG5vdGxpdsO9Y2ggdWthem92YXRlxL5vdiBrdmFsaXR5IHZvZHksICAKLSBhbmFseXpvdmHFpSB2esWlYWh5IG1lZHppIG5pbWksICAKLSBhIHBvbW9jb3UgKipsaW5lw6FybmVqIHJlZ3Jlc2llKiogdnlzdmV0bGnFpSwga3RvcsOpIGZha3Rvcnkgb3ZwbHl2xYh1asO6IG5hcHLDrWtsYWQgKnBIIHZvZHkqLgoKLS0tCgpWIHRlanRvIMO6bG9oZSBwcmVkcG9rbGFkw6FtZSwgxb5lICoqcEggdm9keSoqIGplIG92cGx5dsWIb3ZhbsOpIHZpYWNlcsO9bWkgZmFrdG9ybWkga3ZhbGl0eSB2b2R5LiAgClRlc3R1amVtZSwgxI1pIG1hasO6ICoqdGVwbG90YSoqLCAqKm1ub8W+c3R2byByb3pwdXN0ZW7DqWhvIGt5c2zDrWthKiosICoqZWxla3RyaWNrw6Egdm9kaXZvc8WlKiosICoqYmlvbG9naWNrw6Egc3BvdHJlYmEga3lzbMOta2EqKiwgKipvYnNhaCBkdXNpxI1uYW5vdioqIGEgKipmZWvDoWxuZSBrb2xpZm9ybXkqKiB2w716bmFtbsO9IHZwbHl2IG5hIGhvZG5vdHUgcEguCgoqKk51bG92w6EgaHlwb3TDqXphIChI4oKAKSoqIHR2cmTDrSwgxb5lIMW+aWFkbnkgeiB0w71jaHRvIHVrYXpvdmF0ZcS+b3YgbmVtw6EgxaF0YXRpc3RpY2t5IHbDvXpuYW1uw70gdnBseXYgbmEgcEggdm9keS4gIAoqKkFsdGVybmF0w612bmEgaHlwb3TDqXphIChI4oKBKSoqIHByZWRwb2tsYWTDoSwgxb5lIGFzcG/FiCBqZWRlbiB6IHTDvWNodG8gdWthem92YXRlxL5vdiBtw6EgbmEgcEggxaF0YXRpc3RpY2t5IHbDvXpuYW1uw70gw7rEjWlub2suCgpgYGB7cn0KbGlicmFyeShkcGx5cikKbGlicmFyeSh0aWR5dmVyc2UpCmxpYnJhcnkoa2FibGVFeHRyYSkKbGlicmFyeShjb3JycGxvdCkKCmRhdGEgPC0gcmVhZC5jc3YoIkluZGlhbl93YXRlcl9kYXRhLmNzdiIpCnN0cihkYXRhKQpzdW1tYXJ5KGRhdGEpCgojIERvcGxuZW5pZSBjaMO9YmFqw7pjaWNoIGhvZG7DtHQgbWVkacOhbm9tCmNvbHVtbl9tZWRpYW5zIDwtIHNhcHBseShkYXRhLCBtZWRpYW4sIG5hLnJtID0gVFJVRSkKZm9yIChjb2wgaW4gbmFtZXMoZGF0YSkpIHsKICBpZiAoaXMubnVtZXJpYyhkYXRhW1tjb2xdXSkpIHsKICAgIGRhdGFbW2NvbF1dW2lzLm5hKGRhdGFbW2NvbF1dKV0gPC0gY29sdW1uX21lZGlhbnNbY29sXQogIH0KfQoKIyBWeWJlciDEjcOtc2VsbsOpIHByZW1lbm7DqQoKZGF0YV9udW0gPC0gZGF0YSAlPiUgc2VsZWN0KHdoZXJlKGlzLm51bWVyaWMpKQoKIyBaw6FrbGFkbsOpIMWhdGF0aXN0aWt5CgpkYXRhX251bSAlPiUKc3VtbWFyeSgpICU+JQprYWJsZShjYXB0aW9uID0gIlrDoWtsYWRuw6kgxaF0YXRpc3Rpa3kgbnVtZXJpY2vDvWNoIHByZW1lbm7DvWNoIikgJT4lCmthYmxlX3N0eWxpbmcoZnVsbF93aWR0aCA9IEZBTFNFKQoKIyBWaXp1YWxpesOhY2lhIGTDoXQKCmxpYnJhcnkoZ2dwbG90MikKbGlicmFyeSh0aWR5cikKbGlicmFyeShkcGx5cikKbGlicmFyeShzY2FsZXMpCgojIFByZXZlZGllbWUgZMOhdGEgZG8gbG9uZyBmb3Jtw6F0dQpkYXRhX2xvbmcgPC0gZGF0YV9udW0gJT4lCiAgcGl2b3RfbG9uZ2VyKGNvbHMgPSBldmVyeXRoaW5nKCksIG5hbWVzX3RvID0gIlByZW1lbm7DoSIsIHZhbHVlc190byA9ICJIb2Rub3RhIikKCiMgTm9ybWFsaXrDoWNpYSBrYcW+ZGVqIHByZW1lbm5laiAoMOKAkzEgcm96c2FoKQpkYXRhX3NjYWxlZCA8LSBkYXRhX2xvbmcgJT4lCiAgZ3JvdXBfYnkoUHJlbWVubsOhKSAlPiUKICBtdXRhdGUoSG9kbm90YV9zY2FsZWQgPSAoSG9kbm90YSAtIG1pbihIb2Rub3RhLCBuYS5ybSA9IFRSVUUpKSAvIAogICAgICAgICAgICAgICAgICAgICAgICAgICAobWF4KEhvZG5vdGEsIG5hLnJtID0gVFJVRSkgLSBtaW4oSG9kbm90YSwgbmEucm0gPSBUUlVFKSkpICU+JQogIHVuZ3JvdXAoKQoKIyBCb3hwbG90IHBvIMWha8OhbG92YW7DrQpnZ3Bsb3QoZGF0YV9zY2FsZWQsIGFlcyh4ID0gUHJlbWVubsOhLCB5ID0gSG9kbm90YV9zY2FsZWQsIGZpbGwgPSBQcmVtZW5uw6EpKSArCiAgZ2VvbV9ib3hwbG90KG91dGxpZXIuY29sb3IgPSAicmVkIiwgbm90Y2ggPSBUUlVFLCBhbHBoYSA9IDAuNykgKwogIHRoZW1lX21pbmltYWwoYmFzZV9zaXplID0gMTYpICsKICB0aGVtZSgKICAgIGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gNDUsIGhqdXN0ID0gMSwgc2l6ZSA9IDEyKSwKICAgIGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIgogICkgKwogIGxhYnMoCiAgICB0aXRsZSA9ICJCb3hwbG90eSBqZWRub3RsaXbDvWNoIG51bWVyaWNrw71jaCBwcmVtZW5uw71jaCAoxaF0YW5kYXJkaXpvdmFuw6kpIiwKICAgIHggPSAiIiwKICAgIHkgPSAixaBrw6Fsb3ZhbsOhIGhvZG5vdGEgKDDigJMxKSIKICApCmBgYAojIyBJbnRlcnByZXTDoWNpYSBib3hwbG90b3YgamVkbm90bGl2w71jaCBudW1lcmlja8O9Y2ggcHJlbWVubsO9Y2gKCkJveHBsb3R5IHVrYXp1asO6IHJvemRlbGVuaWUgaG9kbsO0dCBqZWRub3RsaXbDvWNoIHByZW1lbm7DvWNoIHBvIMWhdGFuZGFyZGl6w6FjaWkgKHYgcm96c2FodSAw4oCTMSkuICAKWiBncmFmdSB2aWRubyBuaWVrb8S+a28gZMO0bGXFvml0w71jaCBwb3puYXRrb3Y6CgotICoqUHJlbWVubsOpIGBDb25kdWN0aXZpdHkuLi7CtW1oby5jbS4uLi5NYXhgIGEgYEJPRC4ubWcuTC4uLi5NYXhgKiogbWFqw7ogKip2ZcS+a8O9IHBvxI1ldCBvZMS+YWhsw71jaCBob2Ruw7R0ICjEjWVydmVuw6kgYm9keSkqKiwgIAogIMSNbyBuYXpuYcSNdWplIHbDvXJhem7DuiB2YXJpYWJpbGl0dSBtZWR6aSBsb2thbGl0YW1pIOKAlCB2IG5pZWt0b3LDvWNoIG9ibGFzdGlhY2ggamUgdm9kaXZvc8WlIGFsZWJvIGJpb2xvZ2lja8OhIHNwb3RyZWJhIGt5c2zDrWthIGV4dHLDqW1uZSB2eXNva8OhLgoKLSAqKmBwSC4uLk1pbmAgYSBgcEguLi5NYXhgKiogbWFqw7ogcG9tZXJuZSDDunprZSByb3pww6R0aWUsIMSNbyBqZSB0eXBpY2vDqSDigJQgcEggdm9keSBzYSB6dnnEjWFqbmUgcG9oeWJ1amUgdiDDunprb20gaW50ZXJ2YWxlIDbigJM4LgoKLSAqKmBUZW1wZXJhdHVyZS4uQy4uLi5NYXhgIGEgYFRlbXBlcmF0dXJlLi5DLi4uLk1pbmAqKiBzw7ogcm96bG/FvmVuw6kgcm92bm9tZXJuZSwgYmV6IHbDvXJhem7DvWNoIGV4dHLDqW1vdiDigJQgIAogIHRvIHBvdWthenVqZSBuYSBrb256aXN0ZW50bsOpIGtsaW1hdGlja8OpIHBvZG1pZW5reSBtZXJhbsO9Y2ggbG9rYWzDrXQuCgotICoqYFRvdGFsLkNvbGlmb3JtLi5NUE4uMTAwbWwuLi4uTWF4YCoqIHZ5a2F6dWplIG1pZXJuZSB2ecWhxaHDrSByb3pwdHlsLCAgCiAgxI1vIHpuYW1lbsOhLCDFvmUgYmFrdGVyaW9sb2dpY2vDoSBrb250YW1pbsOhY2lhIHZvZHkgc2EgdsO9cmF6bmUgbMOtxaFpIHBvZMS+YSBtaWVzdGEgbWVyYW5pYS4KCi0gKipgWWVhcmAgYSBgU1ROLmNvZGVgKiogc8O6IHRlY2huaWNrw6kgcHJlbWVubsOpIChpZGVudGlmaWvDoXRvcnksIG5pZSBlbnZpcm9ubWVudMOhbG5lIHVrYXpvdmF0ZWxlKSwgIAogIHByZXRvIGljaCByb3pkZWxlbmllIHR1IG5lbcOhIGFuYWx5dGlja8O9IHbDvXpuYW0uCgpgYGB7cn0KIyBLb3JlbGHEjW7DoSBtYXRpY2EKCmNvcnIgPC0gY29yKGRhdGFfbnVtLCB1c2UgPSAiY29tcGxldGUub2JzIikKY29ycnBsb3QoY29yciwgbWV0aG9kID0gImNvbG9yIiwgdHlwZSA9ICJ1cHBlciIsIHRsLmNleCA9IDAuNykKYGBgCgojIyBJbnRlcnByZXTDoWNpYSBrb3JlbGHEjW5laiBtYXRpY2UKCktvcmVsYcSNbsOhIGFuYWzDvXphIG5hem5hxI11amUsIMW+ZSAqKm5hanZ5xaHFoWlhIGtvcmVsw6FjaWEgcyBgcEguLi5NYXhgKiogamUgcG96b3JvdmFuw6EgcHJpIHVrYXpvdmF0ZcS+b2NoICAKKipyb3pwdXN0ZW7DqWhvIGt5c2zDrWthIChgRGlzc29sdmVkLi4uTWF4YCkqKiBhICoqdm9kaXZvc3RpIChgQ29uZHVjdGl2aXR5Li4uwrVtaG8uY20uLi4uTWF4YCkqKi4gIApUbyBwb3R2cmR6dWplLCDFvmUgY2hlbWlja8OpIHZsYXN0bm9zdGkgdm9keSwgYWtvIGtvbmNlbnRyw6FjaWEga3lzbMOta2EgYSBtbm/FvnN0dm8gcm96cHVzdGVuw71jaCBpw7Nub3YsICAKdsO9em5hbW5lIHPDunZpc2lhIHNvIHptZW5hbWkgcEguCgpTbGFiw6EgYWxlYm8gemFuZWRiYXRlxL5uw6Ega29yZWzDoWNpYSBqZSB2aWRpdGXEvm7DoSBtZWR6aSBwSCBhICoqYmlvbG9naWNrb3Ugc3BvdHJlYm91IGt5c2zDrWthIChCT0QpKiosICAKxI1vIG5hem5hxI11amUsIMW+ZSB0ZW50byBwYXJhbWV0ZXIgcEggb3ZwbHl2xYh1amUgbGVuIG5lcHJpYW1vLgoKKipUZXBsb3RhIHZvZHkqKiB2eWthenVqZSBtaWVybnUgcG96aXTDrXZudSBrb3JlbMOhY2l1IHMgcEgsICAKxI1vIG3DtMW+ZSBvZHLDocW+YcWlIGZ5emlrw6Fsbm8tY2hlbWlja8O6IHbDpHpidSBtZWR6aSB0ZXBsb3RvdSBhIHJvenDDusWhxaVhbsOtbSBwbHlub3Ygdm8gdm9kZS4KCgojIyBMaW5lw6FybmEgcmVncmVzaWEKClByZWRwb2tsYWRham1lLCDFvmUgbWF4aW3DoWxuYSBob2Rub3RhIHBIIHZvZHkgamUgesOhdmlzbMOhIHByZW1lbm7DoSBhIG9zdGF0bsOpIGNoZW1pY2vDqSBhIGJpb2xvZ2lja8OpIHVrYXpvdmF0ZWxlIGt2YWxpdHkgdm9keSwgYWtvIHPDuiB0ZXBsb3RhLCBvYnNhaCByb3pwdXN0ZW7DqWhvIGt5c2zDrWthLCB2b2Rpdm9zxaUsIGJpb2xvZ2lja8OhIHNwb3RyZWJhIGt5c2zDrWthLCBvYnNhaCBkdXNpxI1uYW5vdiBhIGZla8OhbG55Y2gga29saWZvcm1vdiwgcHJlZHN0YXZ1asO6IG5lesOhdmlzbMOpIHByZW1lbm7DqS4KYGBge3J9CiMgTmFqcHJ2IHByZW1lxYggcHLDoXpkbmUgYnVua3kgYWxlYm8gdGV4dHkgYWtvICJCREwiIG5hIE5BCmRhdGEkRmVjYWwuQ29saWZvcm0uLk1QTi4xMDBtbC4uLi5NYXhbZGF0YSRGZWNhbC5Db2xpZm9ybS4uTVBOLjEwMG1sLi4uLk1heCAlaW4lIGMoIiIsICJCREwiLCAiTkEiKV0gPC0gTkEKCiMgUG90b20gcHJldmVkaWXFoSBuYSDEjcOtc2xhCmRhdGEkRmVjYWwuQ29saWZvcm0uLk1QTi4xMDBtbC4uLi5NYXggPC0gYXMubnVtZXJpYyhkYXRhJEZlY2FsLkNvbGlmb3JtLi5NUE4uMTAwbWwuLi4uTWF4KQoKIyBMaW5lw6FybnkgbW9kZWwg4oCTIHBILi4uTWF4IGFrbyB6w6F2aXNsw6EgcHJlbWVubsOhCm1vZGVsIDwtIGxtKHBILi4uTWF4IH4gVGVtcGVyYXR1cmUuLkMuLi4uTWF4ICsgRGlzc29sdmVkLi4uTWF4ICsgQ29uZHVjdGl2aXR5Li4uwrVtaG8uY20uLi4uTWF4ICsgCiAgICAgICAgICAgICAgQk9ELi5tZy5MLi4uLk1heCArIE5pdHJhdGVOLi5tZy5MLi4uLk1heCArIEZlY2FsLkNvbGlmb3JtLi5NUE4uMTAwbWwuLi4uTWF4LCAKICAgICAgICAgICAgZGF0YSA9IGRhdGEpCgojIFbDvXN0dXB5IG1vZGVsdQpjYXQoIk9kaGFkbnV0w6kga29lZmljaWVudHkgbW9kZWx1OlxuIikKcHJpbnQobW9kZWwkY29lZmZpY2llbnRzKQoKY2F0KCJPZGhhZG51dMOpIHJlesOtZHXDoSAoenZ5xaFreSk6XG4iKQpwcmludChoZWFkKG1vZGVsJHJlc2lkdWFscywgMTApKSAgIyBsZW4gcHJ2w71jaCAxMCBwcmVoxL5hZG5lCgpjYXQoIlZ5cm92bmFuw6kgKHByZWRpa292YW7DqSkgaG9kbm90eSB6w6F2aXNsZWogcHJlbWVubmVqOlxuIikKcHJpbnQoaGVhZChtb2RlbCRmaXR0ZWQudmFsdWVzLCAxMCkpICAjIG9ww6TFpSBsZW4gcHJ2w71jaCAxMAoKY2F0KCJNYXRpY2EgbW9kZWx1IChYKTpcbiIpClggPC0gbW9kZWwubWF0cml4KG1vZGVsKQpwcmludChoZWFkKFgpKQoKY2F0KCJQcm9qZWvEjW7DoSBtYXRpY2EgKGhhdCBtYXRyaXgpOlxuIikKSCA8LSBYICUqJSBzb2x2ZSh0KFgpICUqJSBYKSAlKiUgdChYKQpwcmludChyb3VuZChIWzE6NSwgMTo1XSwgNCkpICAjIGxlbiBwcnbDvWNoIDV4NSBwcnZrb3YgcHJlIHByZWjEvmFkbm9zxaUKCmNhdCgiU8O6aHJuIG1vZGVsdTpcbiIpCnN1bW1hcnkobW9kZWwpCgpgYGAKIyBJbnRlcnByZXTDoWNpYSBhIGRpYWdub3N0aWthIG1vZGVsdQoKU8O6aHJuIG9kaGFkb3ZhbsOpaG8gbW9kZWx1IG7DoW0gcG9za3l0dWplIHPDumJvciBvZGhhZG51dMO9Y2ggcmVncmVzbsO9Y2gga29lZmljaWVudG92LCBrdG9yw71jaCB6bmFtaWVua2EgYSB2w716bmFtbm9zxaUgYnVkw7ogaW50ZXJwcmV0b3ZhbsOpIG5pxb7FoWllLiAgCkFrIGhvdm9yw61tZSBvIHZsYXN0bm9zdGlhY2ggbW9kZWx1IGFrbyBjZWxrdSwgcG96cmltZSBzYSBuYWpza8O0ciBuYSBkaWFnbm9zdGlja8OpIGdyYWZ5LgoKYGBge3J9CiMgTmFzdGF2acWlIHJvemxvxb5lbmllIDIgeCAyCnBhcihtZnJvdyA9IGMoMiwgMikpCgojIFZ5a3Jlc2xpxaUgdsWhZXRreSA0IGRpYWdub3N0aWNrw6kgZ3JhZnkgbW9kZWx1CnBsb3QobW9kZWwpCgojIFByaWRhxaUgc3BvbG/EjW7DvSBuYWRwaXMKbXRleHQoIkRpYWdub3N0aWNrw6kgZ3JhZnkgcmVncmVzbsOpaG8gbW9kZWx1IOKAkyBwSC4uLk1heCIsIAogICAgICBvdXRlciA9IFRSVUUsIGNleCA9IDEuMiwgZm9udCA9IDIpCgojIFJlc2V0b3ZhxaUgbGF5b3V0CnBhcihtZnJvdyA9IGMoMSwgMSkpCmBgYAojIyBJbnRlcnByZXTDoWNpYSBkaWFnbm9zdGlja8O9Y2ggZ3JhZm92IHByZSBtb2RlbCBwSC4uLk1heAoKIyMjIFJlc2lkdWFscyB2cy4gRml0dGVkCgotIFJlesOtZHXDoSBzYSBwb2h5YnVqw7ogcHJpYmxpxb5uZSBva29sbyBudWxvdmVqIG9zaSDigJMgbW9kZWwgdGVkYSAqKm5lbcOhIHN5c3RlbWF0aWNrw6kgc2tyZXNsZW5pZSB2IHByZWRpa2NpaSBob2Ruw7R0IHBIKiouICAKLSDEjGVydmVuw6EgTE9FU1MgxI1pYXJhIGplIHJlbGF0w612bmUgcm92bsOhLCDEjW8gbmF6bmHEjXVqZSwgxb5lICoqdnrFpWFoIG1lZHppIHBIIGEgenZvbGVuw71taSBwcmVtZW5uw71taSoqIChuYXByLiB0ZXBsb3RhLCB2b2Rpdm9zxaUsIEJPRCwgZHVzacSNbmFueSkgamUgcHJldmHFvm5lIGxpbmXDoXJueS4gIAotIFZlcnRpa8OhbG55IHJvenB0eWwgamUgcHJpYmxpxb5uZSByb3Zub21lcm7DvSDihpIgcHJlZHBva2xhZCAqKmhvbW9za2VkYXN0aWNpdHkgKGtvbsWhdGFudG7DqWhvIHJvenB0eWx1IGNow71iKSoqIGplIHYgesOhc2FkZSBzcGxuZW7DvS4gIAotIE5pZWtvxL5rbyBib2RvdiBtaW1vIGhsYXZuw70gcm96cHR5bCBtw7TFvmUgcHJlZHN0YXZvdmHFpSAqKmxva2FsaXR5IHMgZXh0csOpbW55bWkgaG9kbm90YW1pIGt2YWxpdHkgdm9keSoqIChwb3RlbmNpw6FsbmUgb2TEvmFobMOpIHBvem9yb3ZhbmlhKSwga3RvcsOpIHNpIG92ZXLDrW1lIHBvbW9jb3UgdGVzdG92LgoKLS0tCgojIyMgUeKAk1EgcGxvdAoKLSBWw6TEjcWhaW5hIGJvZG92IGxlxb7DrSBwb3pkxLrFviBkaWFnb27DoWx5IOKGkiByZXrDrWR1w6EgbW9kZWx1IHBILi4uTWF4IHPDuiAqKnRha21lciBub3Jtw6FsbmUgcm96bG/FvmVuw6kqKi4gIAotIE5hIGtvbmNvY2ggKHbEvmF2byBkb2xlIGEgdnByYXZvIGhvcmUpIG1vxb5ubyBwb3pvcm92YcWlIG1pZXJuZSBvZGNow71sa3kg4oCTIHRvIG5hem5hxI11amUgKirFpWHFvsWhaWUgY2h2b3N0eSByb3pkZWxlbmlhKiosIHByYXZkZXBvZG9ibmUgc3DDtHNvYmVuw6kgZXh0csOpbW55bWkgaG9kbm90YW1pIG5pZWt0b3LDvWNoIGNoZW1pY2vDvWNoIHVrYXpvdmF0ZcS+b3YuICAKLSBTdHJlZG7DoSDEjWFzxaUgZ3JhZnUgamUgZG9icmUgemFyb3ZuYW7DoSwgxI1vIHBvdHZyZHp1amUsIMW+ZSAqKnbDpMSNxaFpbmEgcG96b3JvdmFuw60gc2Egc3Byw6F2YSBub3Jtw6FsbmUqKi4KCi0tLQoKIyMjIFNjYWxl4oCTTG9jYXRpb24gcGxvdAoKLSBCb2R5IHPDuiByb3pwdMO9bGVuw6kgcm92bm9tZXJuZSBwbyBvc2kgWCBiZXogdnl0dsOhcmFuaWEgbGlldmlrYSDihpIgcm96cHR5bCByZXrDrWR1w60gamUgKipwcmlibGnFvm5lIGtvbsWhdGFudG7DvSoqLiAgCi0gSGxhZGvDoSBMT0VTUyDEjWlhcmEgamUgdGFrbWVyIHZvZG9yb3Zuw6EsIMSNbyBuYXpuYcSNdWplLCDFvmUgKip2YXJpYWJpbGl0YSBjaMO9YiBzYSBuZW1lbsOtIHNvIHptZW5vdSBwcmVkaWtvdmFuw71jaCBob2Ruw7R0IHBIKiouICAKLSBUZW50byB2w71zbGVkb2sgcG9kcG9ydWplIHBsYXRub3PFpSBwcmVkcG9rbGFkdSBvICoqaG9tb3NrZWRhc3RpY2l0ZSBtb2RlbHUqKi4KCi0tLQoKIyMjIFJlc2lkdWFscyB2cy4gTGV2ZXJhZ2UKCi0gVsOkxI3FoWluYSBib2RvdiBtw6EgbsOtemt5IHZwbHl2IChDb29rb3ZhIHZ6ZGlhbGVub3PFpSA8IDAuNSkg4oaSIMW+aWFkbmUgcG96b3JvdmFuaWUgKipuZW92cGx5dsWIdWplIHJlZ3Jlc27DqSBrb2VmaWNpZW50eSB2w71yYXpuZSoqLiAgCi0gSmVkZW4gYWxlYm8gZHZhIGJvZHkgbcO0xb51IG1hxaUgenbDvcWhZW7DuiBww6Frb3bDuiBob2Rub3R1IOKAkyBpZGUgcHJhdmRlcG9kb2JuZSBvICoqbG9rYWxpdHkgcyBleHRyw6ltbmUgb2RsacWhbsO9bWkgcGFyYW1ldHJhbWkgdm9keSoqLCBrdG9yw6kgdsWhYWsgbW9kZWwgdsO9cmF6bmUgbmVkZWZvcm11asO6LiAgCi0gQ2Vsa292byBww7Rzb2LDrSBtb2RlbCAqKnN0YWJpbG5lIGEgYmV6IHbDvXpuYW1uw71jaCBvZMS+YWhsw71jaCBhbGVibyB2cGx5dm7DvWNoIGJvZG92KiouCgotLS0KCiMjIyBaaHJudXRpZQoKRGlhZ25vc3RpY2vDqSBncmFmeSBwb3R2cmR6dWrDuiwgxb5lIG1vZGVsIHMgdnlzdmV0xL5vdmFub3UgcHJlbWVubm91ICoqcEguLi5NYXgqKiBhIHByZWRpa3Rvcm1pICAKKCoqVGVtcGVyYXR1cmUuLkMuLi4uTWF4KiosICoqRGlzc29sdmVkLi4uTWF4KiosICoqQ29uZHVjdGl2aXR5Li4uwrVtaG8uY20uLi4uTWF4KiosICAKKipCT0QuLm1nLkwuLi4uTWF4KiosICoqTml0cmF0ZU4uLm1nLkwuLi4uTWF4KiogYSAqKkZlY2FsLkNvbGlmb3JtLi5NUE4uMTAwbWwuLi4uTWF4KiopICAKc3DEusWIYSBobGF2bsOpIHByZWRwb2tsYWR5IGxpbmXDoXJuZWogcmVncmVzaWUuICAKClJlesOtZHXDoSBzw7ogcHJpYmxpxb5uZSBub3Jtw6FsbmUgcm96bG/FvmVuw6ksIHJvenB0eWwgY2jDvWIgamUga29uxaF0YW50bsO9IGEgdsOkxI3FoWluYSBwb3pvcm92YW7DrSBuZW3DoSBuYWRtZXJuw70gdnBseXYgbmEgdsO9c2xlZG9rIG1vZGVsdS4gIApNb2RlbCB0ZWRhIG1vxb5ubyBwb3Zhxb5vdmHFpSB6YSAqKsWhdGF0aXN0aWNreSBzcG/EvmFobGl2w70gbmEgaW50ZXJwcmV0w6FjaXUgdnrFpWFodSBtZWR6aSB1a2F6b3ZhdGXEvm1pIGt2YWxpdHkgdm9keSBhIHBIKiouCmBgYHtyfQojIE5vdsO9IG1vZGVsIHNvIHpsb2dhcml0bW92YW5vdSBDb25kdWN0aXZpdHkKbW9kZWwyIDwtIGxtKHBILi4uTWF4IH4gVGVtcGVyYXR1cmUuLkMuLi4uTWF4ICsgRGlzc29sdmVkLi4uTWF4ICsKICAgICAgICAgICAgICAgSShsb2coQ29uZHVjdGl2aXR5Li4uwrVtaG8uY20uLi4uTWF4KSkgKwogICAgICAgICAgICAgICBCT0QuLm1nLkwuLi4uTWF4ICsgTml0cmF0ZU4uLm1nLkwuLi4uTWF4LCAKICAgICAgICAgICAgIGRhdGEgPSBkYXRhKQpzdW1tYXJ5KG1vZGVsMikKcGFyKG1mcm93ID0gYygyLCAyKSkKcGxvdChtb2RlbDIpCnBhcihtZnJvdyA9IGMoMSwgMSkpCmBgYAoKVHJhbnNmb3Jtw6FjaWEgcHJlbWVubmVqIGBDb25kdWN0aXZpdHkuLi7CtW1oby5jbS4uLi5NYXhgIHBvbW9jb3UgbG9nYXJpdG11IGJvbGEgenZvbGVuw6EgbmEgem7DrcW+ZW5pZSB2cGx5dnUgZXh0csOpbW55Y2ggaG9kbsO0dCwga3RvcsOpIHNhIHYgcMO0dm9kbsO9Y2ggw7pkYWpvY2ggdsO9cmF6bmUgbMOtxaFpbGkgbWVkemkgbG9rYWxpdGFtaS4gIApQbyBhcGxpa8OhY2lpIGxvZ2FyaXRtaWNrZWogdHJhbnNmb3Jtw6FjaWUgc2EgbW9kZWwgc3Byw6F2YSBzdGFiaWxuZWrFoWllIGEgamVobyBrb2VmaWNpZW50eSBzw7ogbGVwxaFpZSBpbnRlcnByZXRvdmF0ZcS+bsOpLgoKIyMgSW50ZXJwcmV0w6FjaWEgZGlhZ25vc3RpY2vDvWNoIGdyYWZvdiBwcmUgbW9kZWwgc28gemxvZ2FyaXRtb3Zhbm91IHZvZGl2b3PFpW91CgojIyMgUmVzaWR1YWxzIHZzIEZpdHRlZApSZXrDrWR1w6Egc2EgcG9oeWJ1asO6ICoqcm92bm9tZXJuZSBva29sbyBudWxvdmVqIG9zaSoqLCDEjW8gbmF6bmHEjXVqZSwgxb5lIG1vZGVsICoqbmVtw6Egc3lzdGVtYXRpY2vDqSBza3Jlc2xlbmllKiogdiBwcmVkaWtjaWkgaG9kbsO0dCBwSC4gIArEjGVydmVuw6EgTE9FU1MgxI1pYXJhIGplICoqdGFrbWVyIHZvZG9yb3Zuw6EqKiwgxI1vIHBvdHZyZHp1amUsIMW+ZSBwbyBsb2dhcml0bWlja2VqIHRyYW5zZm9ybcOhY2lpIHZvZGl2b3N0aSBzYSBvZHN0csOhbmlsYSBww7R2b2Ruw6EgbWllcm5hIG5lbGluZWFyaXRhLiAgClZlcnRpa8OhbG55IHJvenB0eWwgcmV6w61kdcOtIGplICoqa29uxaF0YW50bsO9Kiog4oCTIHByZWRwb2tsYWQgKipob21vc2tlZGFzdGljaXR5KiogamUgdGVkYSBzcGxuZW7DvS4gIApOaWVrb8S+a28gamVkbm90bGl2w71jaCBib2RvdiBzIHbDpMSNxaFvdSBvZGNow71sa291IG3DtMW+ZSBwYXRyacWlIGV4dHLDqW1ueW0gbG9rYWxpdMOhbSwgbm8gbmVvdnBseXbFiHVqw7ogbW9kZWwgdsO9em5hbW5lLgoKLS0tCgojIyMgUeKAk1EgcGxvdApWw6TEjcWhaW5hIGJvZG92IGxlxb7DrSAqKnZlxL5taSBibMOtemtvIGRpYWdvbsOhbHkqKiwgxI1vIHpuYW1lbsOhLCDFvmUgKipyZXrDrWR1w6Egc8O6IHByaWJsacW+bmUgbm9ybcOhbG5lIHJvemxvxb5lbsOpKiouICAKTWVuxaFpZSBvZGNow71sa3kgbmEga29uY29jaCAodsS+YXZvIGRvbGUgYSB2cHJhdm8gaG9yZSkgbmF6bmHEjXVqw7ogbGVuIG1pZXJuZSBvZGNow71sa3kgb2Qgbm9ybcOhbG5vc3RpLCAgCmt0b3LDqSBtw7TFvnUgYnnFpSBzcMO0c29iZW7DqSBwcsOtdG9tbm9zxaVvdSBuaWVrb8S+a8O9Y2ggZXh0csOpbW55Y2ggbWVyYW7DrS4gIApPcHJvdGkgcMO0dm9kbsOpbXUgbW9kZWx1IHNhIHJvemRlbGVuaWUgcmV6w61kdcOtICoqdsO9cmF6bmUgemxlcMWhaWxvKiog4oCTIGxvZy10cmFuc2Zvcm3DoWNpYSB0ZWRhIHBvbW9obGEuCgotLS0KCiMjIyBTY2FsZeKAk0xvY2F0aW9uIHBsb3QKQm9keSBzw7ogcm96cHTDvWxlbsOpICoqcm92bm9tZXJuZSBwb3pkxLrFviBvc2kgWCoqIGJleiB6bsOhbW9rIHJvesWhaXJ1asO6Y2VobyBzYSDigJ5saWV2aWth4oCcLCAgCsSNbyBwb3R2cmR6dWplLCDFvmUgKip2YXJpYW5jaWEgcmV6w61kdcOtIGplIGtvbsWhdGFudG7DoSoqIG5hcHJpZcSNIHByZWRpa292YW7DvW1pIGhvZG5vdGFtaS4gIArEjGVydmVuw6EgaGxhZGvDoSDEjWlhcmEgamUgdGFrbWVyIHJvdm7DoSwgxI1vIG5hem5hxI11amUsIMW+ZSAqKnJvenB0eWwgY2jDvWIgc2EgbmVtZW7DrSoqIHNvIHptZW5vdSBob2Ruw7R0IHBILiAgCk1vZGVsIHRlZGEgc3DEusWIYSBwcmVkcG9rbGFkICoqaG9tb3NrZWRhc3RpY2l0eSoqIHZlxL5taSBkb2JyZS4KCi0tLQoKIyMjIFJlc2lkdWFscyB2cyBMZXZlcmFnZQpWw6TEjcWhaW5hIHBvem9yb3ZhbsOtIG3DoSAqKm7DrXpreSBww6Frb3bDvSBlZmVrdCoqIChsZXZlcmFnZSA8IDAuMSkgYSBDb29rb3ZhIHZ6ZGlhbGVub3PFpSB6b3N0w6F2YSBwb2QgMC41LiAgClRvIHpuYW1lbsOhLCDFvmUgxb5pYWRuZSBwb3pvcm92YW5pZSAqKm5lb3ZwbHl2xYh1amUgbW9kZWwgbmFkbWVybmUqKi4gIApOaWVrb8S+a28gYm9kb3YgKG5hcHIuIDE5MSwgNjYpIHZ5a2F6dWplIG1pZXJuZSB2ecWhxaHDrSB2cGx5diwgYWxlIG5lcHJlc2FodWplIGtyaXRpY2vDqSBob2Rub3R5LiAgCk1vZGVsIHRlZGEgKipuZW9ic2FodWplIHbDvXJhem5lIHZwbHl2bsOpIGFsZWJvIG9kxL5haGzDqSBwcsOtcGFkeSoqLgoKLS0tCgojIyMgKipaaHJudXRpZSBkaWFnbm9zdGlreSoqClRyYW5zZm9ybW92YW7DvSBtb2RlbCAoc28gemxvZ2FyaXRtb3Zhbm91IHZvZGl2b3PFpW91KSAqKnbDvXJhem5lIHpsZXDFoWlsIMWhdGF0aXN0aWNrw6kgdmxhc3Rub3N0aSByZXrDrWR1w60qKjoKLSBvZHN0csOhbmlsIG1pZXJudSBuZWxpbmVhcml0dSB6IHDDtHZvZG7DqWhvIG1vZGVsdSwgIAotIHpuw63FvmlsIGhldGVyb3NrZWRhc3RpY2l0dSwgIAotIGEgcHJpYmzDrcW+aWwgcm96ZGVsZW5pZSByZXrDrWR1w60gayBub3Jtw6FsbmVtdSB0dmFydS4gIAoKTW9kZWwgamUgdGVkYSAqKnN0YWJpbG7DvSwgc3BvxL5haGxpdsO9KiogYSB2aG9kbsO9IG5hIGludGVycHJldMOhY2l1IHZ6xaVhaHUgbWVkemkga3ZhbGl0b3Ugdm9keSBhIHBILgoKIyMgVGVzdHkgbm9ybWFsaXR5IGEgaWRlbnRpZmlrw6FjaWEgb2TEvmFobMO9Y2ggaG9kbsO0dAoKViB0ZWp0byDEjWFzdGkgb3ZlcsOtbWUsIMSNaSByZXrDrWR1w6EgcMO0dm9kbsOpaG8gbW9kZWx1IHNwxLrFiGFqw7ogcHJlZHBva2xhZCAqKm5vcm1hbGl0eSByb3pkZWxlbmlhKiogIAphIHrDoXJvdmXFiCBpZGVudGlmaWt1amVtZSBtb8W+bsOpICoqb2TEvmFobMOpIHBvem9yb3ZhbmlhKiosIGt0b3LDqSBieSBtb2hsaSBvdnBseXbFiG92YcWlIHbDvXNsZWRreS4KYGBge3J9CmphcnF1ZS5iZXJhLnRlc3QocmVzaWR1YWxzKG1vZGVsKSkKY2FyOjpvdXRsaWVyVGVzdChtb2RlbCkKYGBgCgojIyDwn6eqIFRlc3R5IG5vcm1hbGl0eSBhIG9kxL5haGzDvWNoIGhvZG7DtHQgcG8gdHJhbnNmb3Jtw6FjaWkgKG1vZGVsMikKClBvIMO6cHJhdmUgbW9kZWx1IChsb2dhcml0bcOhY2lhIHZvZGl2b3N0aSkgb3ZlcsOtbWUsIMSNaSBzYSB6bGVwxaFpbGEgbm9ybWFsaXRhIHJvemRlbGVuaWEgcmV6w61kdcOtCmEgxI1pIHNhIHpuw63FvmlsIHBvxI1ldCBvZMS+YWhsw71jaCBob2Ruw7R0LgoKYGBge3J9CiMgSmFycXVl4oCTQmVyYSB0ZXN0IHByZSBtb2RlbDIKamFycXVlLmJlcmEudGVzdChyZXNpZHVhbHMobW9kZWwyKSkKCiMgVGVzdCBvZMS+YWhsw71jaCBob2Ruw7R0IHByZSBtb2RlbDIKY2FyOjpvdXRsaWVyVGVzdChtb2RlbDIpCmBgYAoqKkludGVycHJldMOhY2lhIHbDvXNsZWRrb3Y6KioKClbDvXNsZWRreSAqKkphcnF1ZeKAk0JlcmEgdGVzdHUqKiBwcmUgYG1vZGVsMmAgdWthenVqw7osIMW+ZSBwLWhvZG5vdGEgamUgKip2ecWhxaFpYSBuZcW+IHYgcMO0dm9kbm9tIG1vZGVsaSoqLiAgClRvIHpuYW1lbsOhLCDFvmUgcG8gbG9nYXJpdG1pY2tlaiB0cmFuc2Zvcm3DoWNpaSBwcmVtZW5uZWogYENvbmR1Y3Rpdml0eS4uLsK1bWhvLmNtLi4uLk1heGAgc2EgIAoqKm5vcm1hbGl0YSByZXrDrWR1w60gemxlcMWhaWxhKiosIGhvY2kgcHJpIG1lbsWhb20gcG/EjXRlIHBvem9yb3ZhbsOtIG5lbXVzw60gYnnFpSDDunBsbmUgZG9rb25hbMOhLgoKKipPdXRsaWVyIFRlc3QqKiB1xb4gbmVpZGVudGlmaWt1amUgxb5pYWRuZSB2w71yYXpuZSB2w716bmFtbsOpIG9kxL5haGzDqSBwb3pvcm92YW5pZSwgIArEjW8gcG90dnJkenVqZSwgxb5lIHDDtHZvZG7DvSBleHRyw6ltbnkgYm9kIChwb3pvcm92YW5pZSDEjS4gMTkxKSAqKnXFviBuZW3DoSBwb2RzdGF0bsO9IHZwbHl2KiogbmEgbW9kZWwuCgoqKlrDoXZlcjoqKiBUcmFuc2Zvcm1vdmFuw70gbW9kZWwgKGBtb2RlbDJgKSBsZXDFoWllIHNwxLrFiGEgcHJlZHBva2xhZHkgbGluZcOhcm5laiByZWdyZXNpZSDigJMgIApyZXrDrWR1w6Egc8O6ICoqYmxpxb7FoWllIGsgbm9ybcOhbG5lbXUgcm96ZGVsZW5pdSoqIGEgbW9kZWwgamUgKipyb2J1c3RuZWrFocOtIHZvxI1pIG9kxL5haGzDvW0gaG9kbm90w6FtKiouCgoKIyBaw6F2ZXIKCk5hIHrDoWtsYWRlIHJlZ3Jlc25laiBhbmFsw716eSBtb8W+bm8ga29uxaF0YXRvdmHFpSwgxb5lIG1heGltw6FsbmUgcEggdm9keSAoKipwSC4uLk1heCoqKSAKamUgb3ZwbHl2bmVuw6kgdmlhY2Vyw71taSBmYWt0b3JtaSBrdmFsaXR5IHZvZHkuIApQcmVtZW5uw6kgKip0ZXBsb3RhIHZvZHksIHJvenB1c3RlbsO9IGt5c2zDrWsgYSB2b2Rpdm9zxaUqKiBtYWrDuiBwb3ppdMOtdm55IHZwbHl2LCAKa8O9bSAqKmJpb2xvZ2lja8OhIHNwb3RyZWJhIGt5c2zDrWthIGEgZmVrw6FsbmUga29saWZvcm15Kiogem5pxb51asO6IHBILgoKUmV6w61kdcOhIG1vZGVsdSBzw7ogcHJpYmxpxb5uZSBub3Jtw6FsbmUsIHJvenB0eWwgY2jDvWIgamUga29uxaF0YW50bsO9IAphIHZwbHl2bsOpIHBvem9yb3ZhbmlhIG5lb3ZwbHl2xYh1asO6IHbDvXNsZWRvayBvZGhhZHUuICAKVHJhbnNmb3Jtb3ZhbsO9IG1vZGVsIChzbyB6bG9nYXJpdG1vdmFub3Ugdm9kaXZvc8Wlb3UpIHpsZXDFoWlsIG5vcm1hbGl0dSBjaMO9YiwgCsSNbyBwb3R2cmR6dWplIHZob2Rub3PFpSBsb2dhcml0bWlja2VqIHRyYW5zZm9ybcOhY2llIHByaSB2eXNva28gdmFyaWFiaWxuw71jaCB1a2F6b3ZhdGXEvm9jaCBrdmFsaXR5IHZvZHkuCgo=