knitr::opts_chunk$set(
    echo = TRUE,
    message = FALSE,
    warning = FALSE
)

Práca s údajmi

Tradičná práca s databázou

Príklad

Majme údaje o žiakoch, ktoré predstavujú tri premenné - Meno, Priezvisko a známka:

# Working with data frames

  Meno = c("Diana", "Simona", "Katka")
  Priezvisko = c("Spálová", "Hrušovská", "Vančová")
  známka = c(2, 1, 3)
udaje <- data.frame(Meno,Priezvisko,známka)
print(udaje)
print(udaje$Priezvisko)                 # takto adresujeme jednotlivé premenné v data.frame
[1] "Spálová"   "Hrušovská" "Vančová"  
print(mean(udaje$Priezvisko))           # priemerny vek
[1] NA
print(udaje[Meno=="Simona",])     # adresovanie celého riadku
print(udaje[3,])                 # ina moznost adresovania celeho riadku
print(udaje[,2:3])               # vypisanie druheho a tretieho stlpca tabulky
print(udaje[1,1])                # vypisanie jednej bunky tabulky
[1] "Diana"
summary(udaje)                   # zakladna deskriptivna statistika celej tabulky
     Meno            Priezvisko            známka   
 Length:3           Length:3           Min.   :1.0  
 Class :character   Class :character   1st Qu.:1.5  
 Mode  :character   Mode  :character   Median :2.0  
                                       Mean   :2.0  
                                       3rd Qu.:2.5  
                                       Max.   :3.0  

pridanie stĺpca

Absolvoval <- c(TRUE,TRUE,TRUE)
udaje <- cbind(udaje,Absolvoval)
print(udaje)

pridanie riadku

# New record (must match column order/types)
novy.riadok <- data.frame(Meno = "Andrej", Priezvisko = "Varga", známka = 5,Absolvoval = FALSE)

# Append
udaje <- rbind(udaje, novy.riadok)
print(udaje)
NA

Tabuľky v prostredí kableextra

library(knitr)
library(kableExtra)

# Dáta
Meno <- c("Diana", "Simona", "Katka", "Andrej")
Priezvisko <- c("Spálová", "Hrušovská", "Vančová", "Varga")
Znamka <- c(2, 1, 3, 5)
Absolvoval <- c(TRUE, TRUE, TRUE, FALSE)

udaje <- data.frame(Meno, Priezvisko, Znamka, Absolvoval)

# Tabuľka
kable(
  udaje,
  digits = 1,
  align = c("l", "l", "c", "c"),
  caption = "Toto je tabuľka"
) %>%
  kable_styling(
    bootstrap_options = c("striped", "hover", "condensed", "responsive"),
    full_width = FALSE,
    position = "center"
  )
Toto je tabuľka
Meno Priezvisko Znamka Absolvoval
Diana Spálová 2 TRUE
Simona Hrušovská 1 TRUE
Katka Vančová 3 TRUE
Andrej Varga 5 FALSE
NA
NA
NA
library(knitr)
library(kableExtra)
library(dplyr)

# Dáta
Meno <- c("Diana", "Simona", "Katka", "Andrej")
Priezvisko <- c("Spálová", "Hrušovská", "Vančová", "Varga")
Znamka <- c(2, 1, 3, 5)
Absolvoval <- c(TRUE, TRUE, TRUE, FALSE)

udaje <- data.frame(Meno, Priezvisko, Znamka, Absolvoval)

# Tabuľka s ružovým štýlom
udaje %>%
  kable(
    digits = 1,
    align = c("l", "l", "c", "c"),
    caption = "🌷 Výsledky študentov"
  ) %>%
  kable_styling(
    bootstrap_options = c("striped", "hover", "condensed", "responsive"),
    full_width = FALSE,
    position = "center",
    font_size = 14
  ) %>%
  row_spec(0, bold = TRUE, background = "#f8d7da", color = "#6f1a2e") %>% # hlavička
  row_spec(which(!udaje$Absolvoval), background = "#f3bcc8", color = "black") %>% # neabsolvoval
  row_spec(which(udaje$Absolvoval), background = "#fde2e4", color = "black") %>%  # absolvoval
  column_spec(3, bold = TRUE, color = "#b30059") %>% # známka
  column_spec(4, bold = TRUE)
🌷 Výsledky študentov
Meno Priezvisko Znamka Absolvoval
Diana Spálová 2 TRUE
Simona Hrušovská 1 TRUE
Katka Vančová 3 TRUE
Andrej Varga 5 FALSE
NA

Tidyverse - moderná práca s údajmi

Tidyverse je súbor knižníc, ktoré majú zjednodušiť prácu s údajmi. Majú jednotný komunikačný štandard, vzájomne sa doplňujú.

# Load tidyverse
library(tidyverse)

dplyr - pre manipuláciu s údajmi

Výber a triedenie

udaje <- data.frame(Meno, Priezvisko, Znamka, Absolvoval)

# Výber a následné triedenie
udaje %>%
  filter(Absolvoval == TRUE) %>%       # vyberie len tých, čo absolvovali
  arrange(Znamka) %>%                  # zoradí podľa známky vzostupne
  kable(
    align = c("l", "l", "c", "c"),
    caption = "Študenti, ktorí absolvovali"
  ) %>%
  kable_styling(
    bootstrap_options = c("striped", "hover", "condensed", "responsive"),
    full_width = FALSE,
    position = "center"
  )
Študenti, ktorí absolvovali
Meno Priezvisko Znamka Absolvoval
Simona Hrušovská 1 TRUE
Diana Spálová 2 TRUE
Katka Vančová 3 TRUE

Zoskupenie a sumarizácia

udaje <- data.frame(Meno, Priezvisko, Znamka, Absolvoval)

# Zoskupenie a sumarizácia podľa absolvovania
udaje %>%
  group_by(Absolvoval) %>%                    # zoskupí podľa toho, kto absolvoval
  summarise(
    Priem.Znamka = mean(Znamka),              # priemer známky v skupine
    count = n()                               # počet študentov v skupine
  ) %>%
  kable(
    caption = "Priemerná známka podľa absolvovania",
    col.names = c("Absolvoval", "Priemer známka", "Počet"),
    align = "c"
  ) %>%
  kable_styling(
    bootstrap_options = c("striped", "hover", "condensed", "responsive"),
    full_width = FALSE,
    position = "center"
  )
Priemerná známka podľa absolvovania
Absolvoval Priemer známka Počet
FALSE 5 1
TRUE 2 3

Vytváranie novej premennej

# Vytváranie novej premennej
udaje <- udaje %>%
  mutate(
    Hodnotenie = case_when(
      Znamka == 1 ~ "Výborný",
      Znamka == 2 ~ "Chválitebný",
      Znamka == 3 ~ "Dobrý",
      Znamka == 4 ~ "Dostatočný",
      Znamka == 5 ~ "Nedostatočný"
    )
  )

# Zobrazenie tabuľky
udaje %>%
  kable(
    align = c("l","l","c","c","l"),
    caption = "Študenti s novou premennou Hodnotenie"
  ) %>%
  kable_styling(
    bootstrap_options = c("striped", "hover", "condensed", "responsive"),
    full_width = FALSE,
    position = "center"
  )
Študenti s novou premennou Hodnotenie
Meno Priezvisko Znamka Absolvoval Hodnotenie
Diana Spálová 2 TRUE Chválitebný
Simona Hrušovská 1 TRUE Výborný
Katka Vančová 3 TRUE Dobrý
Andrej Varga 5 FALSE Nedostatočný

Import údajov

Import údajov z .csv alebo .xls

file.exists(“C:/Users/Admin/Documents/R_dataset/student_exam_scores.csv”)

library(readr)

# Načítanie CSV súboru (meno súboru presne také, ako si ho nahrala)
udaje2 <- read_csv("student_exam_scores.csv")

# Pozrieť prvých pár riadkov
head(udaje2)
NA

Grafy

ggplot2 - knižnica pre grafy

ggplot(udaje2, aes(x = hours_studied, y = exam_score, color = attendance_percent)) +
  geom_point(size = 4) +
  scale_color_gradient(low = "#FFD1DC", high = "#FF69B4") +  # pastelové ružové odtiene
  labs(
    title = "Vzťah medzi študijnými hodinami a výsledkom skúšky",
    x = "Hodiny strávené štúdiom",
    y = "Výsledok skúšky",
    color = "Dochádzka (%)"
  ) +
  theme_minimal(base_size = 13)

Scatter plot

library(ggplot2)

ggplot(udaje2, aes(x = hours_studied, y = exam_score, 
                   color = attendance_percent, size = sleep_hours)) +
  geom_point(alpha = 0.8) +
  scale_color_gradientn(
    colors = c("#FFB3BA", "#BAE1FF", "#B3FFBA", "#FFF3BA")  # pastelové farby
  ) +
  labs(
    title = "Vzťah medzi hodinami štúdia, výsledkom skúšky a spánkom",
    x = "Hodiny štúdia",
    y = "Výsledok skúšky",
    color = "Dochádzka (%)",
    size = "Hodiny spánku"
  ) +
  theme_minimal(base_size = 13)

NA
NA
NA

Boxplot

library(ggplot2)
library(dplyr)

# Rozdelenie hours_studied do kategórií
udaje2 <- udaje2 %>%
  mutate(hours_category = cut(hours_studied, breaks = 3, 
                              labels = c("Low", "Medium", "High")))

# Boxplot s rozprávkovými modrými odtieňmi
ggplot(udaje2, aes(x = hours_category, y = exam_score, fill = hours_category)) +
  geom_boxplot(color = "#0D1B2A", size = 1) +  # tmavý kontrastný obrys
  scale_fill_manual(values = c(
    "Low" = "#6CA0DC",     # svetlá, sýta modrá
    "Medium" = "#89CFF0",  # pastelovo modrá
    "High" = "#A2D2FF"     # jemná svetlomodrá
  )) +
  labs(
    title = "Výsledky skúšky podľa kategórie hodín štúdia",
    x = "Hodiny štúdia",
    y = "Výsledok skúšky",
    fill = "Kategória hodín"
  ) +
  theme_minimal(base_size = 13)

NA
NA

Základné štatistiky.

knitr - tabuľka

library(dplyr)
library(knitr)

# Summarise basic statistics for udaje3
udaje2.stats <- udaje2 %>%
  summarise(
    n = n(),
    hours_mean = mean(hours_studied, na.rm = TRUE),
    hours_sd   = sd(hours_studied, na.rm = TRUE),
    hours_min  = min(hours_studied, na.rm = TRUE),
    hours_q25  = quantile(hours_studied, 0.25, na.rm = TRUE),
    hours_median = median(hours_studied, na.rm = TRUE),
    hours_q75  = quantile(hours_studied, 0.75, na.rm = TRUE),
    hours_max  = max(hours_studied, na.rm = TRUE),
    
    sleep_mean = mean(sleep_hours, na.rm = TRUE),
    sleep_sd   = sd(sleep_hours, na.rm = TRUE),
    sleep_min  = min(sleep_hours, na.rm = TRUE),
    sleep_q25  = quantile(sleep_hours, 0.25, na.rm = TRUE),
    sleep_median = median(sleep_hours, na.rm = TRUE),
    sleep_q75  = quantile(sleep_hours, 0.75, na.rm = TRUE),
    sleep_max  = max(sleep_hours, na.rm = TRUE),
    
    attendance_mean = mean(attendance_percent, na.rm = TRUE),
    attendance_sd   = sd(attendance_percent, na.rm = TRUE),
    attendance_min  = min(attendance_percent, na.rm = TRUE),
    attendance_q25  = quantile(attendance_percent, 0.25, na.rm = TRUE),
    attendance_median = median(attendance_percent, na.rm = TRUE),
    attendance_q75  = quantile(attendance_percent, 0.75, na.rm = TRUE),
    attendance_max  = max(attendance_percent, na.rm = TRUE),
    
    previous_mean = mean(previous_scores, na.rm = TRUE),
    previous_sd   = sd(previous_scores, na.rm = TRUE),
    previous_min  = min(previous_scores, na.rm = TRUE),
    previous_q25  = quantile(previous_scores, 0.25, na.rm = TRUE),
    previous_median = median(previous_scores, na.rm = TRUE),
    previous_q75  = quantile(previous_scores, 0.75, na.rm = TRUE),
    previous_max  = max(previous_scores, na.rm = TRUE),
    
    exam_mean = mean(exam_score, na.rm = TRUE),
    exam_sd   = sd(exam_score, na.rm = TRUE),
    exam_min  = min(exam_score, na.rm = TRUE),
    exam_q25  = quantile(exam_score, 0.25, na.rm = TRUE),
    exam_median = median(exam_score, na.rm = TRUE),
    exam_q75  = quantile(exam_score, 0.75, na.rm = TRUE),
    exam_max  = max(exam_score, na.rm = TRUE)
  )

# Vytvorenie tabuľky
kable(udaje2.stats, digits = 2, caption = "Basic statistics for udaje2")
Basic statistics for udaje2
n hours_mean hours_sd hours_min hours_q25 hours_median hours_q75 hours_max sleep_mean sleep_sd sleep_min sleep_q25 sleep_median sleep_q75 sleep_max attendance_mean attendance_sd attendance_min attendance_q25 attendance_median attendance_q75 attendance_max previous_mean previous_sd previous_min previous_q25 previous_median previous_q75 previous_max exam_mean exam_sd exam_min exam_q25 exam_median exam_q75 exam_max
200 6.33 3.23 1 3.5 6.15 9 12 6.62 1.5 4 5.3 6.7 8.03 9 74.83 14.25 50.3 62.2 75.25 87.43 100 66.8 15.66 40 54 67.5 80 95 33.95 6.79 17.1 29.5 34.05 38.75 51.3
NA
NA

t-test: Porovnanie priemeru ESG indexu v rokoch 2013 a 2015

library(dplyr)

# Rozdelenie na dve skupiny podľa mediánu hodín štúdia
udaje2 <- udaje2 %>%
  mutate(hours_group = ifelse(hours_studied <= median(hours_studied), "Low", "High"))

# T-test medzi Low a High skupinou
t.test.result <- t.test(
  exam_score ~ hours_group,
  data = udaje2
)

print(t.test.result)

    Welch Two Sample t-test

data:  exam_score by hours_group
t = 13.84, df = 197.91, p-value < 2.2e-16
alternative hypothesis: true difference in means between group High and group Low is not equal to 0
95 percent confidence interval:
  8.144613 10.851387
sample estimates:
mean in group High  mean in group Low 
            38.704             29.206 

ANOVA: Comparing Reading Scores Across Programs

# ANOVA test pre exam_score podľa skupiny hodín štúdia
anova.result <- aov(exam_score ~ hours_group, data = udaje2)
summary(anova.result)
             Df Sum Sq Mean Sq F value Pr(>F)    
hours_group   1   4511    4511   191.5 <2e-16 ***
Residuals   198   4663      24                   
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Linear Regression: Predicting Math Scores

# Lineárny model pre udaje2
model <- lm(exam_score ~ hours_studied + sleep_hours + attendance_percent, data = udaje2)
summary(model)

Call:
lm(formula = exam_score ~ hours_studied + sleep_hours + attendance_percent, 
    data = udaje2)

Residuals:
    Min      1Q  Median      3Q     Max 
-8.5534 -2.7064 -0.1704  3.1321  7.6393 

Coefficients:
                   Estimate Std. Error t value Pr(>|t|)    
(Intercept)        10.90021    1.95832   5.566 8.49e-08 ***
hours_studied       1.62964    0.08502  19.168  < 2e-16 ***
sleep_hours         0.57941    0.18318   3.163  0.00181 ** 
attendance_percent  0.11907    0.01920   6.202 3.24e-09 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 3.857 on 196 degrees of freedom
Multiple R-squared:  0.6821,    Adjusted R-squared:  0.6773 
F-statistic: 140.2 on 3 and 196 DF,  p-value: < 2.2e-16
LS0tCnRpdGxlOiAiUHLDoWNhIHMgZGF0YWLDoXpvdSIKYXV0aG9yOiAiRGlhbmEgSHJ1xaFvdnNrw6EgIDxicj4KKHMgdnl1xb5pdMOtbSB2ZXJlam5lIGRvc3R1cG7DvWNoIGvDs2RvdikiCmRhdGU6ICJTZXB0ZW1iZXIgMjAyNSIKb3V0cHV0OiAKICBodG1sX25vdGVib29rOgogICAgdG9jOiB0cnVlCiAgICB0b2NfZmxvYXQ6IHRydWUKICAgIHRoZW1lOiB1bml0ZWQKICAgIGhpZ2hsaWdodDogdGFuZ28KZWRpdG9yX29wdGlvbnM6IAogIG1hcmtkb3duOiAKICAgIHdyYXA6IDcyCi0tLQoKYGBge3J9CmtuaXRyOjpvcHRzX2NodW5rJHNldCgKICAgIGVjaG8gPSBUUlVFLAogICAgbWVzc2FnZSA9IEZBTFNFLAogICAgd2FybmluZyA9IEZBTFNFCikKYGBgCgojIFByw6FjYSBzIMO6ZGFqbWkKCiMjIFRyYWRpxI1uw6EgcHLDoWNhIHMgZGF0YWLDoXpvdQoKIyMjIFByw61rbGFkCgpNYWptZSDDumRhamUgbyDFvmlha29jaCwga3RvcsOpIHByZWRzdGF2dWrDuiB0cmkgcHJlbWVubsOpIC0gTWVubywgUHJpZXp2aXNrbwphIHpuw6Fta2E6CgpgYGB7cn0KIyBXb3JraW5nIHdpdGggZGF0YSBmcmFtZXMKCiAgTWVubyA9IGMoIkRpYW5hIiwgIlNpbW9uYSIsICJLYXRrYSIpCiAgUHJpZXp2aXNrbyA9IGMoIlNww6Fsb3bDoSIsICJIcnXFoW92c2vDoSIsICJWYW7EjW92w6EiKQogIHpuw6Fta2EgPSBjKDIsIDEsIDMpCmBgYAoKYGBge3J9CnVkYWplIDwtIGRhdGEuZnJhbWUoTWVubyxQcmllenZpc2tvLHpuw6Fta2EpCnByaW50KHVkYWplKQpgYGAKCmBgYHtyfQpwcmludCh1ZGFqZSRQcmllenZpc2tvKSAgICAgICAgICAgICAgICAgIyB0YWt0byBhZHJlc3VqZW1lIGplZG5vdGxpdsOpIHByZW1lbm7DqSB2IGRhdGEuZnJhbWUKcHJpbnQobWVhbih1ZGFqZSRQcmllenZpc2tvKSkgICAgICAgICAgICMgcHJpZW1lcm55IHZlawpwcmludCh1ZGFqZVtNZW5vPT0iU2ltb25hIixdKSAgICAgIyBhZHJlc292YW5pZSBjZWzDqWhvIHJpYWRrdQpwcmludCh1ZGFqZVszLF0pICAgICAgICAgICAgICAgICAjIGluYSBtb3pub3N0IGFkcmVzb3ZhbmlhIGNlbGVobyByaWFka3UKcHJpbnQodWRhamVbLDI6M10pICAgICAgICAgICAgICAgIyB2eXBpc2FuaWUgZHJ1aGVobyBhIHRyZXRpZWhvIHN0bHBjYSB0YWJ1bGt5CnByaW50KHVkYWplWzEsMV0pICAgICAgICAgICAgICAgICMgdnlwaXNhbmllIGplZG5laiBidW5reSB0YWJ1bGt5CnN1bW1hcnkodWRhamUpICAgICAgICAgICAgICAgICAgICMgemFrbGFkbmEgZGVza3JpcHRpdm5hIHN0YXRpc3Rpa2EgY2VsZWogdGFidWxreQpgYGAKCiMjIHByaWRhbmllIHN0xLpwY2EKCmBgYHtyfQpBYnNvbHZvdmFsIDwtIGMoVFJVRSxUUlVFLFRSVUUpCnVkYWplIDwtIGNiaW5kKHVkYWplLEFic29sdm92YWwpCnByaW50KHVkYWplKQpgYGAKCiMjIHByaWRhbmllIHJpYWRrdQoKYGBge3J9CiMgTmV3IHJlY29yZCAobXVzdCBtYXRjaCBjb2x1bW4gb3JkZXIvdHlwZXMpCm5vdnkucmlhZG9rIDwtIGRhdGEuZnJhbWUoTWVubyA9ICJBbmRyZWoiLCBQcmllenZpc2tvID0gIlZhcmdhIiwgem7DoW1rYSA9IDUsQWJzb2x2b3ZhbCA9IEZBTFNFKQoKIyBBcHBlbmQKdWRhamUgPC0gcmJpbmQodWRhamUsIG5vdnkucmlhZG9rKQpwcmludCh1ZGFqZSkKCmBgYAoKIyMjIFRhYnXEvmt5IHYgcHJvc3RyZWTDrSBrYWJsZWV4dHJhCgpgYGB7cn0KbGlicmFyeShrbml0cikKbGlicmFyeShrYWJsZUV4dHJhKQoKIyBEw6F0YQpNZW5vIDwtIGMoIkRpYW5hIiwgIlNpbW9uYSIsICJLYXRrYSIsICJBbmRyZWoiKQpQcmllenZpc2tvIDwtIGMoIlNww6Fsb3bDoSIsICJIcnXFoW92c2vDoSIsICJWYW7EjW92w6EiLCAiVmFyZ2EiKQpabmFta2EgPC0gYygyLCAxLCAzLCA1KQpBYnNvbHZvdmFsIDwtIGMoVFJVRSwgVFJVRSwgVFJVRSwgRkFMU0UpCgp1ZGFqZSA8LSBkYXRhLmZyYW1lKE1lbm8sIFByaWV6dmlza28sIFpuYW1rYSwgQWJzb2x2b3ZhbCkKCiMgVGFidcS+a2EKa2FibGUoCiAgdWRhamUsCiAgZGlnaXRzID0gMSwKICBhbGlnbiA9IGMoImwiLCAibCIsICJjIiwgImMiKSwKICBjYXB0aW9uID0gIlRvdG8gamUgdGFidcS+a2EiCikgJT4lCiAga2FibGVfc3R5bGluZygKICAgIGJvb3RzdHJhcF9vcHRpb25zID0gYygic3RyaXBlZCIsICJob3ZlciIsICJjb25kZW5zZWQiLCAicmVzcG9uc2l2ZSIpLAogICAgZnVsbF93aWR0aCA9IEZBTFNFLAogICAgcG9zaXRpb24gPSAiY2VudGVyIgogICkKCgoKYGBgCgpgYGB7cn0KbGlicmFyeShrbml0cikKbGlicmFyeShrYWJsZUV4dHJhKQpsaWJyYXJ5KGRwbHlyKQoKIyBEw6F0YQpNZW5vIDwtIGMoIkRpYW5hIiwgIlNpbW9uYSIsICJLYXRrYSIsICJBbmRyZWoiKQpQcmllenZpc2tvIDwtIGMoIlNww6Fsb3bDoSIsICJIcnXFoW92c2vDoSIsICJWYW7EjW92w6EiLCAiVmFyZ2EiKQpabmFta2EgPC0gYygyLCAxLCAzLCA1KQpBYnNvbHZvdmFsIDwtIGMoVFJVRSwgVFJVRSwgVFJVRSwgRkFMU0UpCgp1ZGFqZSA8LSBkYXRhLmZyYW1lKE1lbm8sIFByaWV6dmlza28sIFpuYW1rYSwgQWJzb2x2b3ZhbCkKCiMgVGFidcS+a2EgcyBydcW+b3bDvW0gxaF0w71sb20KdWRhamUgJT4lCiAga2FibGUoCiAgICBkaWdpdHMgPSAxLAogICAgYWxpZ24gPSBjKCJsIiwgImwiLCAiYyIsICJjIiksCiAgICBjYXB0aW9uID0gIvCfjLcgVsO9c2xlZGt5IMWhdHVkZW50b3YiCiAgKSAlPiUKICBrYWJsZV9zdHlsaW5nKAogICAgYm9vdHN0cmFwX29wdGlvbnMgPSBjKCJzdHJpcGVkIiwgImhvdmVyIiwgImNvbmRlbnNlZCIsICJyZXNwb25zaXZlIiksCiAgICBmdWxsX3dpZHRoID0gRkFMU0UsCiAgICBwb3NpdGlvbiA9ICJjZW50ZXIiLAogICAgZm9udF9zaXplID0gMTQKICApICU+JQogIHJvd19zcGVjKDAsIGJvbGQgPSBUUlVFLCBiYWNrZ3JvdW5kID0gIiNmOGQ3ZGEiLCBjb2xvciA9ICIjNmYxYTJlIikgJT4lICMgaGxhdmnEjWthCiAgcm93X3NwZWMod2hpY2goIXVkYWplJEFic29sdm92YWwpLCBiYWNrZ3JvdW5kID0gIiNmM2JjYzgiLCBjb2xvciA9ICJibGFjayIpICU+JSAjIG5lYWJzb2x2b3ZhbAogIHJvd19zcGVjKHdoaWNoKHVkYWplJEFic29sdm92YWwpLCBiYWNrZ3JvdW5kID0gIiNmZGUyZTQiLCBjb2xvciA9ICJibGFjayIpICU+JSAgIyBhYnNvbHZvdmFsCiAgY29sdW1uX3NwZWMoMywgYm9sZCA9IFRSVUUsIGNvbG9yID0gIiNiMzAwNTkiKSAlPiUgIyB6bsOhbWthCiAgY29sdW1uX3NwZWMoNCwgYm9sZCA9IFRSVUUpCgpgYGAKCiMjIFRpZHl2ZXJzZSAtIG1vZGVybsOhIHByw6FjYSBzIMO6ZGFqbWkKClRpZHl2ZXJzZSBqZSBzw7pib3Iga25pxb5uw61jLCBrdG9yw6kgbWFqw7ogemplZG5vZHXFoWnFpSBwcsOhY3UgcyDDumRham1pLiBNYWrDugpqZWRub3Ruw70ga29tdW5pa2HEjW7DvSDFoXRhbmRhcmQsIHZ6w6Fqb21uZSBzYSBkb3BsxYh1asO6LgoKYGBge3IgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KIyBMb2FkIHRpZHl2ZXJzZQpsaWJyYXJ5KHRpZHl2ZXJzZSkKYGBgCgojIyMgZHBseXIgLSBwcmUgbWFuaXB1bMOhY2l1IHMgw7pkYWptaQoKIyMjIyBWw71iZXIgYSB0cmllZGVuaWUKCmBgYHtyfQp1ZGFqZSA8LSBkYXRhLmZyYW1lKE1lbm8sIFByaWV6dmlza28sIFpuYW1rYSwgQWJzb2x2b3ZhbCkKCiMgVsO9YmVyIGEgbsOhc2xlZG7DqSB0cmllZGVuaWUKdWRhamUgJT4lCiAgZmlsdGVyKEFic29sdm92YWwgPT0gVFJVRSkgJT4lICAgICAgICMgdnliZXJpZSBsZW4gdMO9Y2gsIMSNbyBhYnNvbHZvdmFsaQogIGFycmFuZ2UoWm5hbWthKSAlPiUgICAgICAgICAgICAgICAgICAjIHpvcmFkw60gcG9kxL5hIHpuw6Fta3kgdnpvc3R1cG5lCiAga2FibGUoCiAgICBhbGlnbiA9IGMoImwiLCAibCIsICJjIiwgImMiKSwKICAgIGNhcHRpb24gPSAixaB0dWRlbnRpLCBrdG9yw60gYWJzb2x2b3ZhbGkiCiAgKSAlPiUKICBrYWJsZV9zdHlsaW5nKAogICAgYm9vdHN0cmFwX29wdGlvbnMgPSBjKCJzdHJpcGVkIiwgImhvdmVyIiwgImNvbmRlbnNlZCIsICJyZXNwb25zaXZlIiksCiAgICBmdWxsX3dpZHRoID0gRkFMU0UsCiAgICBwb3NpdGlvbiA9ICJjZW50ZXIiCiAgKQpgYGAKCiMjIyMgWm9za3VwZW5pZSBhIHN1bWFyaXrDoWNpYQoKYGBge3J9CnVkYWplIDwtIGRhdGEuZnJhbWUoTWVubywgUHJpZXp2aXNrbywgWm5hbWthLCBBYnNvbHZvdmFsKQoKIyBab3NrdXBlbmllIGEgc3VtYXJpesOhY2lhIHBvZMS+YSBhYnNvbHZvdmFuaWEKdWRhamUgJT4lCiAgZ3JvdXBfYnkoQWJzb2x2b3ZhbCkgJT4lICAgICAgICAgICAgICAgICAgICAjIHpvc2t1cMOtIHBvZMS+YSB0b2hvLCBrdG8gYWJzb2x2b3ZhbAogIHN1bW1hcmlzZSgKICAgIFByaWVtLlpuYW1rYSA9IG1lYW4oWm5hbWthKSwgICAgICAgICAgICAgICMgcHJpZW1lciB6bsOhbWt5IHYgc2t1cGluZQogICAgY291bnQgPSBuKCkgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIyBwb8SNZXQgxaF0dWRlbnRvdiB2IHNrdXBpbmUKICApICU+JQogIGthYmxlKAogICAgY2FwdGlvbiA9ICJQcmllbWVybsOhIHpuw6Fta2EgcG9kxL5hIGFic29sdm92YW5pYSIsCiAgICBjb2wubmFtZXMgPSBjKCJBYnNvbHZvdmFsIiwgIlByaWVtZXIgem7DoW1rYSIsICJQb8SNZXQiKSwKICAgIGFsaWduID0gImMiCiAgKSAlPiUKICBrYWJsZV9zdHlsaW5nKAogICAgYm9vdHN0cmFwX29wdGlvbnMgPSBjKCJzdHJpcGVkIiwgImhvdmVyIiwgImNvbmRlbnNlZCIsICJyZXNwb25zaXZlIiksCiAgICBmdWxsX3dpZHRoID0gRkFMU0UsCiAgICBwb3NpdGlvbiA9ICJjZW50ZXIiCiAgKQpgYGAKCiMjIyMgVnl0dsOhcmFuaWUgbm92ZWogcHJlbWVubmVqCgpgYGB7cn0KIyBWeXR2w6FyYW5pZSBub3ZlaiBwcmVtZW5uZWoKdWRhamUgPC0gdWRhamUgJT4lCiAgbXV0YXRlKAogICAgSG9kbm90ZW5pZSA9IGNhc2Vfd2hlbigKICAgICAgWm5hbWthID09IDEgfiAiVsO9Ym9ybsO9IiwKICAgICAgWm5hbWthID09IDIgfiAiQ2h2w6FsaXRlYm7DvSIsCiAgICAgIFpuYW1rYSA9PSAzIH4gIkRvYnLDvSIsCiAgICAgIFpuYW1rYSA9PSA0IH4gIkRvc3RhdG/EjW7DvSIsCiAgICAgIFpuYW1rYSA9PSA1IH4gIk5lZG9zdGF0b8SNbsO9IgogICAgKQogICkKCiMgWm9icmF6ZW5pZSB0YWJ1xL5reQp1ZGFqZSAlPiUKICBrYWJsZSgKICAgIGFsaWduID0gYygibCIsImwiLCJjIiwiYyIsImwiKSwKICAgIGNhcHRpb24gPSAixaB0dWRlbnRpIHMgbm92b3UgcHJlbWVubm91IEhvZG5vdGVuaWUiCiAgKSAlPiUKICBrYWJsZV9zdHlsaW5nKAogICAgYm9vdHN0cmFwX29wdGlvbnMgPSBjKCJzdHJpcGVkIiwgImhvdmVyIiwgImNvbmRlbnNlZCIsICJyZXNwb25zaXZlIiksCiAgICBmdWxsX3dpZHRoID0gRkFMU0UsCiAgICBwb3NpdGlvbiA9ICJjZW50ZXIiCiAgKQpgYGAKCiMjIEltcG9ydCDDumRham92CgojIyMgSW1wb3J0IMO6ZGFqb3YgeiAuY3N2IGFsZWJvIC54bHMKCmZpbGUuZXhpc3RzKCJDOi9Vc2Vycy9BZG1pbi9Eb2N1bWVudHMvUl9kYXRhc2V0L3N0dWRlbnRfZXhhbV9zY29yZXMuY3N2IikKCmBgYHtyfQpsaWJyYXJ5KHJlYWRyKQoKIyBOYcSNw610YW5pZSBDU1Ygc8O6Ym9ydSAobWVubyBzw7pib3J1IHByZXNuZSB0YWvDqSwgYWtvIHNpIGhvIG5haHJhbGEpCnVkYWplMiA8LSByZWFkX2Nzdigic3R1ZGVudF9leGFtX3Njb3Jlcy5jc3YiKQoKIyBQb3pyaWXFpSBwcnbDvWNoIHDDoXIgcmlhZGtvdgpoZWFkKHVkYWplMikKCmBgYAoKIyMgR3JhZnkKCiMjIyBnZ3Bsb3QyIC0ga25pxb5uaWNhIHByZSBncmFmeQoKYGBge3J9CmdncGxvdCh1ZGFqZTIsIGFlcyh4ID0gaG91cnNfc3R1ZGllZCwgeSA9IGV4YW1fc2NvcmUsIGNvbG9yID0gYXR0ZW5kYW5jZV9wZXJjZW50KSkgKwogIGdlb21fcG9pbnQoc2l6ZSA9IDQpICsKICBzY2FsZV9jb2xvcl9ncmFkaWVudChsb3cgPSAiI0ZGRDFEQyIsIGhpZ2ggPSAiI0ZGNjlCNCIpICsgICMgcGFzdGVsb3bDqSBydcW+b3bDqSBvZHRpZW5lCiAgbGFicygKICAgIHRpdGxlID0gIlZ6xaVhaCBtZWR6aSDFoXR1ZGlqbsO9bWkgaG9kaW5hbWkgYSB2w71zbGVka29tIHNrw7rFoWt5IiwKICAgIHggPSAiSG9kaW55IHN0csOhdmVuw6kgxaF0w7pkaW9tIiwKICAgIHkgPSAiVsO9c2xlZG9rIHNrw7rFoWt5IiwKICAgIGNvbG9yID0gIkRvY2jDoWR6a2EgKCUpIgogICkgKwogIHRoZW1lX21pbmltYWwoYmFzZV9zaXplID0gMTMpCgpgYGAKCiMjIyMgU2NhdHRlciBwbG90CgpgYGB7cn0KbGlicmFyeShnZ3Bsb3QyKQoKZ2dwbG90KHVkYWplMiwgYWVzKHggPSBob3Vyc19zdHVkaWVkLCB5ID0gZXhhbV9zY29yZSwgCiAgICAgICAgICAgICAgICAgICBjb2xvciA9IGF0dGVuZGFuY2VfcGVyY2VudCwgc2l6ZSA9IHNsZWVwX2hvdXJzKSkgKwogIGdlb21fcG9pbnQoYWxwaGEgPSAwLjgpICsKICBzY2FsZV9jb2xvcl9ncmFkaWVudG4oCiAgICBjb2xvcnMgPSBjKCIjRkZCM0JBIiwgIiNCQUUxRkYiLCAiI0IzRkZCQSIsICIjRkZGM0JBIikgICMgcGFzdGVsb3bDqSBmYXJieQogICkgKwogIGxhYnMoCiAgICB0aXRsZSA9ICJWesWlYWggbWVkemkgaG9kaW5hbWkgxaF0w7pkaWEsIHbDvXNsZWRrb20gc2vDusWha3kgYSBzcMOhbmtvbSIsCiAgICB4ID0gIkhvZGlueSDFoXTDumRpYSIsCiAgICB5ID0gIlbDvXNsZWRvayBza8O6xaFreSIsCiAgICBjb2xvciA9ICJEb2Now6FkemthICglKSIsCiAgICBzaXplID0gIkhvZGlueSBzcMOhbmt1IgogICkgKwogIHRoZW1lX21pbmltYWwoYmFzZV9zaXplID0gMTMpCgoKCmBgYAoKIyMjIyBCb3hwbG90CgpgYGB7cn0KbGlicmFyeShnZ3Bsb3QyKQpsaWJyYXJ5KGRwbHlyKQoKIyBSb3pkZWxlbmllIGhvdXJzX3N0dWRpZWQgZG8ga2F0ZWfDs3Jpw60KdWRhamUyIDwtIHVkYWplMiAlPiUKICBtdXRhdGUoaG91cnNfY2F0ZWdvcnkgPSBjdXQoaG91cnNfc3R1ZGllZCwgYnJlYWtzID0gMywgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxhYmVscyA9IGMoIkxvdyIsICJNZWRpdW0iLCAiSGlnaCIpKSkKCiMgQm94cGxvdCBzIHJvenByw6F2a292w71taSBtb2Ryw71taSBvZHRpZcWIbWkKZ2dwbG90KHVkYWplMiwgYWVzKHggPSBob3Vyc19jYXRlZ29yeSwgeSA9IGV4YW1fc2NvcmUsIGZpbGwgPSBob3Vyc19jYXRlZ29yeSkpICsKICBnZW9tX2JveHBsb3QoY29sb3IgPSAiIzBEMUIyQSIsIHNpemUgPSAxKSArICAjIHRtYXbDvSBrb250cmFzdG7DvSBvYnJ5cwogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IGMoCiAgICAiTG93IiA9ICIjNkNBMERDIiwgICAgICMgc3ZldGzDoSwgc8O9dGEgbW9kcsOhCiAgICAiTWVkaXVtIiA9ICIjODlDRkYwIiwgICMgcGFzdGVsb3ZvIG1vZHLDoQogICAgIkhpZ2giID0gIiNBMkQyRkYiICAgICAjIGplbW7DoSBzdmV0bG9tb2Ryw6EKICApKSArCiAgbGFicygKICAgIHRpdGxlID0gIlbDvXNsZWRreSBza8O6xaFreSBwb2TEvmEga2F0ZWfDs3JpZSBob2TDrW4gxaF0w7pkaWEiLAogICAgeCA9ICJIb2RpbnkgxaF0w7pkaWEiLAogICAgeSA9ICJWw71zbGVkb2sgc2vDusWha3kiLAogICAgZmlsbCA9ICJLYXRlZ8OzcmlhIGhvZMOtbiIKICApICsKICB0aGVtZV9taW5pbWFsKGJhc2Vfc2l6ZSA9IDEzKQoKCmBgYAoKIyBaw6FrbGFkbsOpIMWhdGF0aXN0aWt5LgoKIyMga25pdHIgLSB0YWJ1xL5rYQoKYGBge3J9CmxpYnJhcnkoZHBseXIpCmxpYnJhcnkoa25pdHIpCgojIFN1bW1hcmlzZSBiYXNpYyBzdGF0aXN0aWNzIGZvciB1ZGFqZTMKdWRhamUyLnN0YXRzIDwtIHVkYWplMiAlPiUKICBzdW1tYXJpc2UoCiAgICBuID0gbigpLAogICAgaG91cnNfbWVhbiA9IG1lYW4oaG91cnNfc3R1ZGllZCwgbmEucm0gPSBUUlVFKSwKICAgIGhvdXJzX3NkICAgPSBzZChob3Vyc19zdHVkaWVkLCBuYS5ybSA9IFRSVUUpLAogICAgaG91cnNfbWluICA9IG1pbihob3Vyc19zdHVkaWVkLCBuYS5ybSA9IFRSVUUpLAogICAgaG91cnNfcTI1ICA9IHF1YW50aWxlKGhvdXJzX3N0dWRpZWQsIDAuMjUsIG5hLnJtID0gVFJVRSksCiAgICBob3Vyc19tZWRpYW4gPSBtZWRpYW4oaG91cnNfc3R1ZGllZCwgbmEucm0gPSBUUlVFKSwKICAgIGhvdXJzX3E3NSAgPSBxdWFudGlsZShob3Vyc19zdHVkaWVkLCAwLjc1LCBuYS5ybSA9IFRSVUUpLAogICAgaG91cnNfbWF4ICA9IG1heChob3Vyc19zdHVkaWVkLCBuYS5ybSA9IFRSVUUpLAogICAgCiAgICBzbGVlcF9tZWFuID0gbWVhbihzbGVlcF9ob3VycywgbmEucm0gPSBUUlVFKSwKICAgIHNsZWVwX3NkICAgPSBzZChzbGVlcF9ob3VycywgbmEucm0gPSBUUlVFKSwKICAgIHNsZWVwX21pbiAgPSBtaW4oc2xlZXBfaG91cnMsIG5hLnJtID0gVFJVRSksCiAgICBzbGVlcF9xMjUgID0gcXVhbnRpbGUoc2xlZXBfaG91cnMsIDAuMjUsIG5hLnJtID0gVFJVRSksCiAgICBzbGVlcF9tZWRpYW4gPSBtZWRpYW4oc2xlZXBfaG91cnMsIG5hLnJtID0gVFJVRSksCiAgICBzbGVlcF9xNzUgID0gcXVhbnRpbGUoc2xlZXBfaG91cnMsIDAuNzUsIG5hLnJtID0gVFJVRSksCiAgICBzbGVlcF9tYXggID0gbWF4KHNsZWVwX2hvdXJzLCBuYS5ybSA9IFRSVUUpLAogICAgCiAgICBhdHRlbmRhbmNlX21lYW4gPSBtZWFuKGF0dGVuZGFuY2VfcGVyY2VudCwgbmEucm0gPSBUUlVFKSwKICAgIGF0dGVuZGFuY2Vfc2QgICA9IHNkKGF0dGVuZGFuY2VfcGVyY2VudCwgbmEucm0gPSBUUlVFKSwKICAgIGF0dGVuZGFuY2VfbWluICA9IG1pbihhdHRlbmRhbmNlX3BlcmNlbnQsIG5hLnJtID0gVFJVRSksCiAgICBhdHRlbmRhbmNlX3EyNSAgPSBxdWFudGlsZShhdHRlbmRhbmNlX3BlcmNlbnQsIDAuMjUsIG5hLnJtID0gVFJVRSksCiAgICBhdHRlbmRhbmNlX21lZGlhbiA9IG1lZGlhbihhdHRlbmRhbmNlX3BlcmNlbnQsIG5hLnJtID0gVFJVRSksCiAgICBhdHRlbmRhbmNlX3E3NSAgPSBxdWFudGlsZShhdHRlbmRhbmNlX3BlcmNlbnQsIDAuNzUsIG5hLnJtID0gVFJVRSksCiAgICBhdHRlbmRhbmNlX21heCAgPSBtYXgoYXR0ZW5kYW5jZV9wZXJjZW50LCBuYS5ybSA9IFRSVUUpLAogICAgCiAgICBwcmV2aW91c19tZWFuID0gbWVhbihwcmV2aW91c19zY29yZXMsIG5hLnJtID0gVFJVRSksCiAgICBwcmV2aW91c19zZCAgID0gc2QocHJldmlvdXNfc2NvcmVzLCBuYS5ybSA9IFRSVUUpLAogICAgcHJldmlvdXNfbWluICA9IG1pbihwcmV2aW91c19zY29yZXMsIG5hLnJtID0gVFJVRSksCiAgICBwcmV2aW91c19xMjUgID0gcXVhbnRpbGUocHJldmlvdXNfc2NvcmVzLCAwLjI1LCBuYS5ybSA9IFRSVUUpLAogICAgcHJldmlvdXNfbWVkaWFuID0gbWVkaWFuKHByZXZpb3VzX3Njb3JlcywgbmEucm0gPSBUUlVFKSwKICAgIHByZXZpb3VzX3E3NSAgPSBxdWFudGlsZShwcmV2aW91c19zY29yZXMsIDAuNzUsIG5hLnJtID0gVFJVRSksCiAgICBwcmV2aW91c19tYXggID0gbWF4KHByZXZpb3VzX3Njb3JlcywgbmEucm0gPSBUUlVFKSwKICAgIAogICAgZXhhbV9tZWFuID0gbWVhbihleGFtX3Njb3JlLCBuYS5ybSA9IFRSVUUpLAogICAgZXhhbV9zZCAgID0gc2QoZXhhbV9zY29yZSwgbmEucm0gPSBUUlVFKSwKICAgIGV4YW1fbWluICA9IG1pbihleGFtX3Njb3JlLCBuYS5ybSA9IFRSVUUpLAogICAgZXhhbV9xMjUgID0gcXVhbnRpbGUoZXhhbV9zY29yZSwgMC4yNSwgbmEucm0gPSBUUlVFKSwKICAgIGV4YW1fbWVkaWFuID0gbWVkaWFuKGV4YW1fc2NvcmUsIG5hLnJtID0gVFJVRSksCiAgICBleGFtX3E3NSAgPSBxdWFudGlsZShleGFtX3Njb3JlLCAwLjc1LCBuYS5ybSA9IFRSVUUpLAogICAgZXhhbV9tYXggID0gbWF4KGV4YW1fc2NvcmUsIG5hLnJtID0gVFJVRSkKICApCgojIFZ5dHZvcmVuaWUgdGFidcS+a3kKa2FibGUodWRhamUyLnN0YXRzLCBkaWdpdHMgPSAyLCBjYXB0aW9uID0gIkJhc2ljIHN0YXRpc3RpY3MgZm9yIHVkYWplMiIpCgoKYGBgCgojIyMjIHQtdGVzdDogUG9yb3ZuYW5pZSBwcmllbWVydSBFU0cgaW5kZXh1IHYgcm9rb2NoIDIwMTMgYSAyMDE1CgpgYGB7cn0KbGlicmFyeShkcGx5cikKCiMgUm96ZGVsZW5pZSBuYSBkdmUgc2t1cGlueSBwb2TEvmEgbWVkacOhbnUgaG9kw61uIMWhdMO6ZGlhCnVkYWplMiA8LSB1ZGFqZTIgJT4lCiAgbXV0YXRlKGhvdXJzX2dyb3VwID0gaWZlbHNlKGhvdXJzX3N0dWRpZWQgPD0gbWVkaWFuKGhvdXJzX3N0dWRpZWQpLCAiTG93IiwgIkhpZ2giKSkKCiMgVC10ZXN0IG1lZHppIExvdyBhIEhpZ2ggc2t1cGlub3UKdC50ZXN0LnJlc3VsdCA8LSB0LnRlc3QoCiAgZXhhbV9zY29yZSB+IGhvdXJzX2dyb3VwLAogIGRhdGEgPSB1ZGFqZTIKKQoKcHJpbnQodC50ZXN0LnJlc3VsdCkKYGBgCgojIyMjIEFOT1ZBOiBDb21wYXJpbmcgUmVhZGluZyBTY29yZXMgQWNyb3NzIFByb2dyYW1zCgpgYGB7cn0KIyBBTk9WQSB0ZXN0IHByZSBleGFtX3Njb3JlIHBvZMS+YSBza3VwaW55IGhvZMOtbiDFoXTDumRpYQphbm92YS5yZXN1bHQgPC0gYW92KGV4YW1fc2NvcmUgfiBob3Vyc19ncm91cCwgZGF0YSA9IHVkYWplMikKc3VtbWFyeShhbm92YS5yZXN1bHQpCgpgYGAKCiMjIyMgTGluZWFyIFJlZ3Jlc3Npb246IFByZWRpY3RpbmcgTWF0aCBTY29yZXMKCmBgYHtyfQojIExpbmXDoXJueSBtb2RlbCBwcmUgdWRhamUyCm1vZGVsIDwtIGxtKGV4YW1fc2NvcmUgfiBob3Vyc19zdHVkaWVkICsgc2xlZXBfaG91cnMgKyBhdHRlbmRhbmNlX3BlcmNlbnQsIGRhdGEgPSB1ZGFqZTIpCnN1bW1hcnkobW9kZWwpCgpgYGAK