library(tidyverse)
library(magrittr)
#library(readr)
library(googlesheets4)
library(readODS)
library(readxl)
library(jsonlite)

Listing files

list.dirs(path = mypath)
[1] "/home/cinkova/manage_files/"          
[2] "/home/cinkova/manage_files//JSONFILES"
list.files(path = mypath) 
 [1] "2021-05-07_corrected_tab01.tsv" "bezhlavy_iris.csv"             
 [3] "ChickWeight.txt"                "corrected_tab01.tsv"           
 [5] "gutenberg01.txt"                "gutenbergxml.xml"              
 [7] "iris.csv"                       "JSONFILES"                     
 [9] "managing_files_01.nb.html"      "managing_files_01.Rmd"         
[11] "mtcars.csv"                     "ockovani.json"                 
[13] "tab01"                          "tab01.alfa"                    
[15] "tab01.csv"                      "tab01.ods"                     
[17] "tab01.xlsx"                     "ToothGrowth.divnej"            
[19] "tsv_tabka.tsv"                 
znaky
 [1] "2021-05-07_corrected_tab01.tsv" "bezhlavy_iris.csv"             
 [3] "ChickWeight.txt"                "corrected_tab01.tsv"           
 [5] "gutenberg01.txt"                "gutenbergxml.xml"              
 [7] "iris.csv"                       "JSONFILES"                     
 [9] "managing_files_01.nb.html"      "managing_files_01.Rmd"         
[11] "mtcars.csv"                     "ockovani.json"                 
[13] "tab01"                          "tab01.alfa"                    
[15] "tab01.csv"                      "tab01.ods"                     
[17] "tab01.xlsx"                     "ToothGrowth.divnej"            
[19] "tsv_tabka.tsv"                 
list.files(path = mypath, full.names = TRUE)
list.files(path = mypath, recursive = TRUE, include.dirs = FALSE, full.names = TRUE ) #tady include.dirs = FALSE funguje
 [1] "/home/cinkova/manage_files//2021-05-07_corrected_tab01.tsv"       
 [2] "/home/cinkova/manage_files//bezhlavy_iris.csv"                    
 [3] "/home/cinkova/manage_files//ChickWeight.txt"                      
 [4] "/home/cinkova/manage_files//corrected_tab01.tsv"                  
 [5] "/home/cinkova/manage_files//gutenberg01.txt"                      
 [6] "/home/cinkova/manage_files//gutenbergxml.xml"                     
 [7] "/home/cinkova/manage_files//iris.csv"                             
 [8] "/home/cinkova/manage_files//JSONFILES/tabulka_pravnicky_text.json"
 [9] "/home/cinkova/manage_files//managing_files_01.nb.html"            
[10] "/home/cinkova/manage_files//managing_files_01.Rmd"                
[11] "/home/cinkova/manage_files//mtcars.csv"                           
[12] "/home/cinkova/manage_files//ockovani.json"                        
[13] "/home/cinkova/manage_files//tab01"                                
[14] "/home/cinkova/manage_files//tab01.alfa"                           
[15] "/home/cinkova/manage_files//tab01.csv"                            
[16] "/home/cinkova/manage_files//tab01.ods"                            
[17] "/home/cinkova/manage_files//tab01.xlsx"                           
[18] "/home/cinkova/manage_files//ToothGrowth.divnej"                   
[19] "/home/cinkova/manage_files//tsv_tabka.tsv"                        

Pattern as a regular expression

my_plaintables <- list.files(path = mypath, pattern = "\\.csv" )
my_plaintables
[1] "bezhlavy_iris.csv" "iris.csv"          "mtcars.csv"       
[4] "tab01.csv"        

Capture more plain text formats with one regular expression: csv, tsv, txt

my_plaintables <- list.files(path = mypath, pattern = "(\\.[ct]sv|\\.txt)" )
my_plaintables
[1] "2021-05-07_corrected_tab01.tsv" "bezhlavy_iris.csv"             
[3] "ChickWeight.txt"                "corrected_tab01.tsv"           
[5] "gutenberg01.txt"                "iris.csv"                      
[7] "mtcars.csv"                     "tab01.csv"                     
[9] "tsv_tabka.tsv"                 

Learn to write regular expressions e.g. here: (https://regexone.com/lesson/introduction_abcs)

Common tabular formats

Fig. 1

"Height","Weight","FirstName","Surname","Visit"
"165","55 ","Hana ","Nova",2010-10-10
"145","43","Anna","Kriva",2017-08-09
"173","87","Jakub","Polak",2021-01-27
"88","32","Josef","Riha","2008=12-04"

Fig. 2

"Height";"Weight";"FirstName";"Surname";"Visit"
"165";"55 ";"Hana ";"Nova";2010-10-10
"145";"43";"Anna";"Kriva";2017-08-09
"173";"87";"Jakub";"Polak";2021-01-27
"88";"32";"Josef";"Riha";"2008=12-04"

Fig. 3

[
{
    "Sepal.Length": 6.2,
    "Sepal.Width": 3.4,
    "Petal.Length": 5.4,
    "Petal.Width": 2.3,
    "Species": "virginica"
  },
  {
    "Sepal.Length": 5.9,
    "Sepal.Width": 3,
    "Petal.Length": 5.1,
    "Petal.Width": 1.8,
    "Species": "virginica"
  }
] 

Fig. 4

"Height"\t"Weight"\t"FirstName"\t"Surname"\t"Visit"
"165"\t"55 "\t"Hana "\t"Nova"\t2010-10-10
"145"\t"43"\t"Anna"\t"Kriva"\t2017-08-09
"173"\t"87"\t"Jakub"\t"Polak"\t2021-01-27
"88"\t"32"\t"Josef"\t"Riha"\t"2008=12-04"

Fig. 5

 "Height"   "Weight"    "FirstName" "Surname"   "Visit"
"165"   "55 "   "Hana " "Nova"  2010-10-10
"145"   "43"    "Anna"  "Kriva" 2017-08-09
"173"   "87"    "Jakub" "Polak" 2021-01-27
"88"    "32"    "Josef" "Riha"  "2008=12-04"

Reading rectangular data files (tables)

Local files

readr::read_csv(file = "iris.csv", n_max = 5)
Parsed with column specification:
cols(
  Sepal.Length = col_double(),
  Sepal.Width = col_double(),
  Petal.Length = col_double(),
  Petal.Width = col_double(),
  Species = col_character()
)
readr::read_csv("iris.csv", col_names = c("SL", "SW", "PL", "PW", "Spec"),skip = 1,  n_max = 5)
Parsed with column specification:
cols(
  SL = col_double(),
  SW = col_double(),
  PL = col_double(),
  PW = col_double(),
  Spec = col_character()
)
readr::read_csv("iris.csv", col_names = FALSE, skip = 1, n_max = 5)
Parsed with column specification:
cols(
  X1 = col_double(),
  X2 = col_double(),
  X3 = col_double(),
  X4 = col_double(),
  X5 = col_character()
)
readr::read_csv("iris.csv", col_names = c("SL", "SW", "PL", "PW", "Spec"), n_max = 5)
readr::read_csv2("tab01")
readr::read_csv2("tab01", quote = "\"") #play around with quoting characters
Using ',' as decimal and '.' as grouping mark. Use read_delim() for more control.
Parsed with column specification:
cols(
  Height = col_double(),
  Weight = col_double(),
  FirstName = col_character(),
  Surname = col_character(),
  Visit = col_character()
)
readr::read_lines("bezhlavy_iris.csv", n_max =  5)
[1] "5.1,3.5,1.4,0.2,setosa" "4.9,3,1.4,0.2,setosa"   "4.7,3.2,1.3,0.2,setosa"
[4] "4.6,3.1,1.5,0.2,setosa" "5,3.6,1.4,0.2,setosa"  

#how do we read in the file above? try and find out on your own

readr::read_csv("bezhlavy_iris.csv", col_names = FALSE, n_max = 3)
Parsed with column specification:
cols(
  X1 = col_double(),
  X2 = col_double(),
  X3 = col_double(),
  X4 = col_double(),
  X5 = col_character()
)
readr::read_csv("bezhlavy_iris.csv", col_names = TRUE, n_max = 3)
Parsed with column specification:
cols(
  `5.1` = col_double(),
  `3.5` = col_double(),
  `1.4` = col_double(),
  `0.2` = col_double(),
  setosa = col_character()
)

When you come across an exotic delimiter (column separator): read_delim

readr::read_lines(file = "tab01.alfa")
[1] "\"Height\"&\"Weight\"&\"FirstName\"&\"Surname\"&\"Visit\""
[2] "\"165\"&\"55 \"&\"Hana \"&\"Nova\"&2010-10-10"            
[3] "\"145\"&\"43\"&\"Anna\"&\"Kriva\"&2017-08-09"             
[4] "\"173\"&\"87\"&\"Jakub\"&\"Polak\"&2021-01-27"            
[5] "\"88\"&\"32\"&\"Josef\"&\"Riha\"&\"2008=12-04\""          
(tabka <- readr::read_delim(file = "tab01.alfa", delim = "&"))
Parsed with column specification:
cols(
  Height = col_double(),
  Weight = col_character(),
  FirstName = col_character(),
  Surname = col_character(),
  Visit = col_character()
)

Save a tabular file

Save the tabka table as a tsv

readr::write_tsv(x = tabka, path = "tsv_tabka.tsv")

read it in as a tsv again

tabka2 <- readr::read_tsv("tsv_tabka.tsv")
Parsed with column specification:
cols(
  Height = col_double(),
  Weight = col_double(),
  FirstName = col_character(),
  Surname = col_character(),
  Visit = col_character()
)
tabka2

Check consistency

Display tabka2. Can you see any strange value that is likely to be wrong? What data types you would expect for the individual columns?

tabka2
nacteno <- readr::read_tsv("tsv_tabka.tsv", #col_types = list(col_double(), 
                                                             # col_double(),  
                                                             # col_character(), 
                                                             # col_character(), 
                                                             # col_date())
                                          
                  col_types = "ddccD"

)#dopis typy sloupcu
1 parsing failure.
row   col   expected     actual            file
  4 Visit date like  2008=12-04 'tsv_tabka.tsv'
nacteno

readr::parse_date(tabka$Visit)
1 parsing failure.
row col   expected     actual
  4  -- date like  2008=12-04
[1] "2010-10-10" "2017-08-09" "2021-01-27" NA          
readr::parse_character(as.character(tabka$Visit))
[1] "2010-10-10" "2017-08-09" "2021-01-27" "2008=12-04"
#library(magrittr)
readr::parse_double(tabka$Weight)# %T>% str() # returns the value as well as prints the structure (a magrittr pipe)
[1] 55 43 87 32
weight_by_pipe <- readr::parse_double(as.character(tabka$Height)) %T>% str()
 num [1:4] 165 145 173 88
weight_by_pipe
[1] 165 145 173  88
readr::parse_double(as.character(tabka$Height)) #x musi byt znak. vektor. Kdyz to zlobi, musime ho z nej udelat
str(tabka$Height)
str(tabka)
str(nacteno)

Correct the date right in R using the base R what you learned long ago

tabka$Visit[4] <- "2008-12-04"

Save the corrected file as corrected_tab01.tsv

Save today’s file version

todays_filename
[1] "2021-05-07_corrected_tab01.tsv"

Now save today’s file version

readr::write_tsv(tabka, path = todays_filename)

This is good e.g. when you run a script daily, for instance if you want to keep track of the Czech covid-19 vaccination statistics:

vac <- readr::read_csv(file = "https://onemocneni-aktualne.mzcr.cz/api/v2/covid-19/ockovani.csv")
Parsed with column specification:
cols(
  datum = col_date(format = ""),
  vakcina = col_character(),
  kraj_nuts_kod = col_character(),
  kraj_nazev = col_character(),
  vekova_skupina = col_character(),
  prvnich_davek = col_double(),
  druhych_davek = col_double(),
  celkem_davek = col_double()
)
dplyr::glimpse(vac)
Rows: 43,941
Columns: 8
$ datum          <date> 2020-12-27, 2020-12-27, 2020-12-27, 2020-12-27, 2020-12-27, 2020-12-…
$ vakcina        <chr> "Comirnaty", "Comirnaty", "Comirnaty", "Comirnaty", "Comirnaty", "Com…
$ kraj_nuts_kod  <chr> "CZ010", "CZ010", "CZ010", "CZ010", "CZ010", "CZ010", "CZ010", "CZ010…
$ kraj_nazev     <chr> "Hlavní město Praha", "Hlavní město Praha", "Hlavní město Praha", "Hl…
$ vekova_skupina <chr> "18-24", "25-29", "30-34", "35-39", "40-44", "45-49", "50-54", "55-59…
$ prvnich_davek  <dbl> 48, 108, 102, 111, 172, 156, 128, 96, 84, 79, 48, 19, 24, 2, 3, 7, 8,…
$ druhych_davek  <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, …
$ celkem_davek   <dbl> 48, 108, 102, 111, 172, 156, 128, 96, 84, 79, 48, 19, 24, 2, 3, 7, 8,…

Kolik vyočkovaly jednotlivé kraje celkem dávek? Vytvořte agregovanou tabulku a uložte si ji do souboru pod názvem dnesnidatum_AgregOckovani.tsv. (Dnešní datum pomocí Sys.Date())

dplyr::group_by(vac, kraj_nazev) %>% dplyr::summarize(sum(celkem_davek)) %>%
  readr::write_csv(path = vaccination_filename)
`summarise()` ungrouping output (override with `.groups` argument)

Diskutujte - neprogramujte: jak byste si vyrobili tabulku s počtem dávek podle krajů za celý měsíc od zítřka? Kam byste si ukládali data? Spojovali byste soubory? Nemusíte to umět udělat, jen popřemýšlejte.

#Uložte si jakýkoli soubor z webu domů:

download.file(url = "https://onemocneni-aktualne.mzcr.cz/api/v2/covid-19/ockovani.json", 
              destfile = "ockovani.json")
trying URL 'https://onemocneni-aktualne.mzcr.cz/api/v2/covid-19/ockovani.json'
Content type 'application/json; charset=utf-8' length 13887649 bytes (13.2 MB)
==================================================
downloaded 13.2 MB
download.file(url = "https://www.gutenberg.org/files/26184/26184-8.txt", 
             destfile = "gutenberg01.txt")
trying URL 'https://www.gutenberg.org/files/26184/26184-8.txt'
Content type 'text/plain' length 75158 bytes (73 KB)
==================================================
downloaded 73 KB
readr::read_lines(file = "gutenberg01.txt", n_max = 5)
[1] "The Project Gutenberg eBook, Simple Sabotage Field Manual, by Strategic"
[2] "Services"                                                               
[3] ""                                                                       
[4] "This eBook is for the use of anyone anywhere at no cost and with"       
[5] "almost no restrictions whatsoever.  You may copy it, give it away or"   

JSON

jsonlite::fromJSON("ockovani.json")
$modified
[1] "2021-05-07T08:07:35+02:00"

$source
[1] "https://onemocneni-aktualne.mzcr.cz/"

$data
NA

Cvičení

DataCamp about

LS0tCnRpdGxlOiAiUiBOb3RlYm9vayIKb3V0cHV0OiBodG1sX25vdGVib29rCi0tLQoKYGBge3J9CmxpYnJhcnkodGlkeXZlcnNlKQpsaWJyYXJ5KG1hZ3JpdHRyKQojbGlicmFyeShyZWFkcikKbGlicmFyeShnb29nbGVzaGVldHM0KQpsaWJyYXJ5KHJlYWRPRFMpCmxpYnJhcnkocmVhZHhsKQpsaWJyYXJ5KGpzb25saXRlKQpgYGAKCiMgTGlzdGluZyBmaWxlcwoKYGBge3J9Cm15cGF0aCA8LSAifi9tYW5hZ2VfZmlsZXMvIiAjbmFzdGF2dGUgc2kgc3ZvamkgY2VzdHUKCmxpc3QuZGlycyhwYXRoID0gbXlwYXRoKQpgYGAKCmBgYHtyfQpsaXN0LmZpbGVzKHBhdGggPSBteXBhdGgpIApgYGAKCgpgYGB7cn0Kem5ha3kgPC0gbGlzdC5maWxlcyhwYXRoID0gbXlwYXRoLCBpbmNsdWRlLmRpcnMgPSBGQUxTRSkgCnpuYWt5CmBgYAoKCmBgYHtyfQpsaXN0LmZpbGVzKHBhdGggPSBteXBhdGgsIGZ1bGwubmFtZXMgPSBUUlVFKQpgYGAKCmBgYHtyfQpsaXN0LmZpbGVzKHBhdGggPSBteXBhdGgsIHJlY3Vyc2l2ZSA9IFRSVUUsIGluY2x1ZGUuZGlycyA9IEZBTFNFLCBmdWxsLm5hbWVzID0gVFJVRSApICN0YWR5IGluY2x1ZGUuZGlycyA9IEZBTFNFIGZ1bmd1amUKYGBgCgojIyBQYXR0ZXJuIGFzIGEgcmVndWxhciBleHByZXNzaW9uCgpgYGB7cn0KbXlfcGxhaW50YWJsZXMgPC0gbGlzdC5maWxlcyhwYXRoID0gbXlwYXRoLCBwYXR0ZXJuID0gIlxcLmNzdiIgKQpteV9wbGFpbnRhYmxlcwpgYGAKCkNhcHR1cmUgbW9yZSBwbGFpbiB0ZXh0IGZvcm1hdHMgd2l0aCBvbmUgcmVndWxhciBleHByZXNzaW9uOiBjc3YsIHRzdiwgdHh0CgpgYGB7cn0KbXlfcGxhaW50YWJsZXMgPC0gbGlzdC5maWxlcyhwYXRoID0gbXlwYXRoLCBwYXR0ZXJuID0gIihcXC5bY3Rdc3Z8XFwudHh0KSIgKQpteV9wbGFpbnRhYmxlcwpgYGAKCkxlYXJuIHRvIHdyaXRlIHJlZ3VsYXIgZXhwcmVzc2lvbnMgZS5nLiBoZXJlOiAoaHR0cHM6Ly9yZWdleG9uZS5jb20vbGVzc29uL2ludHJvZHVjdGlvbl9hYmNzKQoKIyMgQ29tbW9uIHRhYnVsYXIgZm9ybWF0cwoKRmlnLiAxCgpgYGAKIkhlaWdodCIsIldlaWdodCIsIkZpcnN0TmFtZSIsIlN1cm5hbWUiLCJWaXNpdCIKIjE2NSIsIjU1ICIsIkhhbmEgIiwiTm92YSIsMjAxMC0xMC0xMAoiMTQ1IiwiNDMiLCJBbm5hIiwiS3JpdmEiLDIwMTctMDgtMDkKIjE3MyIsIjg3IiwiSmFrdWIiLCJQb2xhayIsMjAyMS0wMS0yNwoiODgiLCIzMiIsIkpvc2VmIiwiUmloYSIsIjIwMDg9MTItMDQiCmBgYAoKRmlnLiAyCgpgYGAKIkhlaWdodCI7IldlaWdodCI7IkZpcnN0TmFtZSI7IlN1cm5hbWUiOyJWaXNpdCIKIjE2NSI7IjU1ICI7IkhhbmEgIjsiTm92YSI7MjAxMC0xMC0xMAoiMTQ1IjsiNDMiOyJBbm5hIjsiS3JpdmEiOzIwMTctMDgtMDkKIjE3MyI7Ijg3IjsiSmFrdWIiOyJQb2xhayI7MjAyMS0wMS0yNwoiODgiOyIzMiI7Ikpvc2VmIjsiUmloYSI7IjIwMDg9MTItMDQiCmBgYAoKRmlnLiAzIAoKYGBgClsKewogICAgIlNlcGFsLkxlbmd0aCI6IDYuMiwKICAgICJTZXBhbC5XaWR0aCI6IDMuNCwKICAgICJQZXRhbC5MZW5ndGgiOiA1LjQsCiAgICAiUGV0YWwuV2lkdGgiOiAyLjMsCiAgICAiU3BlY2llcyI6ICJ2aXJnaW5pY2EiCiAgfSwKICB7CiAgICAiU2VwYWwuTGVuZ3RoIjogNS45LAogICAgIlNlcGFsLldpZHRoIjogMywKICAgICJQZXRhbC5MZW5ndGgiOiA1LjEsCiAgICAiUGV0YWwuV2lkdGgiOiAxLjgsCiAgICAiU3BlY2llcyI6ICJ2aXJnaW5pY2EiCiAgfQpdIAoKYGBgCgpGaWcuIDQKCmBgYAoiSGVpZ2h0Ilx0IldlaWdodCJcdCJGaXJzdE5hbWUiXHQiU3VybmFtZSJcdCJWaXNpdCIKIjE2NSJcdCI1NSAiXHQiSGFuYSAiXHQiTm92YSJcdDIwMTAtMTAtMTAKIjE0NSJcdCI0MyJcdCJBbm5hIlx0IktyaXZhIlx0MjAxNy0wOC0wOQoiMTczIlx0Ijg3Ilx0Ikpha3ViIlx0IlBvbGFrIlx0MjAyMS0wMS0yNwoiODgiXHQiMzIiXHQiSm9zZWYiXHQiUmloYSJcdCIyMDA4PTEyLTA0IgpgYGAKCkZpZy4gNQoKYGBgCiAiSGVpZ2h0IgkiV2VpZ2h0IgkiRmlyc3ROYW1lIgkiU3VybmFtZSIJIlZpc2l0IgoiMTY1IgkiNTUgIgkiSGFuYSAiCSJOb3ZhIgkyMDEwLTEwLTEwCiIxNDUiCSI0MyIJIkFubmEiCSJLcml2YSIJMjAxNy0wOC0wOQoiMTczIgkiODciCSJKYWt1YiIJIlBvbGFrIgkyMDIxLTAxLTI3CiI4OCIJIjMyIgkiSm9zZWYiCSJSaWhhIgkiMjAwOD0xMi0wNCIKCmBgYAoKCiMgUmVhZGluZyByZWN0YW5ndWxhciBkYXRhIGZpbGVzICh0YWJsZXMpIAojIyBMb2NhbCBmaWxlcyAKCgpgYGB7cn0KcmVhZHI6OnJlYWRfY3N2KGZpbGUgPSAiaXJpcy5jc3YiLCBuX21heCA9IDUpCmBgYAoKYGBge3J9CnJlYWRyOjpyZWFkX2NzdigiaXJpcy5jc3YiLCBjb2xfbmFtZXMgPSBjKCJTTCIsICJTVyIsICJQTCIsICJQVyIsICJTcGVjIiksc2tpcCA9IDEsICBuX21heCA9IDUpCmBgYAoKYGBge3J9CnJlYWRyOjpyZWFkX2NzdigiaXJpcy5jc3YiLCBjb2xfbmFtZXMgPSBGQUxTRSwgc2tpcCA9IDEsIG5fbWF4ID0gNSkKYGBgCgoKCmBgYHtyfQpyZWFkcjo6cmVhZF9jc3YoImlyaXMuY3N2IiwgY29sX25hbWVzID0gYygiU0wiLCAiU1ciLCAiUEwiLCAiUFciLCAiU3BlYyIpLCBuX21heCA9IDUpCmBgYAoKYGBge3J9CnJlYWRyOjpyZWFkX2NzdjIoInRhYjAxIikKYGBgCmBgYHtyfQpyZWFkcjo6cmVhZF9jc3YyKCJ0YWIwMSIsIHF1b3RlID0gIlwiIikgI3BsYXkgYXJvdW5kIHdpdGggcXVvdGluZyBjaGFyYWN0ZXJzCmBgYAoKYGBge3J9CnJlYWRyOjpyZWFkX2xpbmVzKCJiZXpobGF2eV9pcmlzLmNzdiIsIG5fbWF4ID0gIDUpCmBgYAoKI2hvdyBkbyB3ZSByZWFkIGluIHRoZSBmaWxlIGFib3ZlPwp0cnkgYW5kIGZpbmQgb3V0IG9uIHlvdXIgb3duCmBgYHtyfQpyZWFkcjo6cmVhZF9jc3YoImJlemhsYXZ5X2lyaXMuY3N2IiwgY29sX25hbWVzID0gRkFMU0UsIG5fbWF4ID0gMykKYGBgCgoKYGBge3J9CnJlYWRyOjpyZWFkX2NzdigiYmV6aGxhdnlfaXJpcy5jc3YiLCBjb2xfbmFtZXMgPSBUUlVFLCBuX21heCA9IDMpCmBgYAoKCiMgV2hlbiB5b3UgY29tZSBhY3Jvc3MgYW4gZXhvdGljIGRlbGltaXRlciAoY29sdW1uIHNlcGFyYXRvcik6IGByZWFkX2RlbGltYApgYGB7cn0KcmVhZHI6OnJlYWRfbGluZXMoZmlsZSA9ICJ0YWIwMS5hbGZhIikKYGBgCgoKYGBge3J9Cih0YWJrYSA8LSByZWFkcjo6cmVhZF9kZWxpbShmaWxlID0gInRhYjAxLmFsZmEiLCBkZWxpbSA9ICImIikpCmBgYAoKIyBTYXZlIGEgdGFidWxhciBmaWxlCgpTYXZlIHRoZSAgdGFia2EgdGFibGUgYXMgYSB0c3YKYGBge3J9CnJlYWRyOjp3cml0ZV90c3YoeCA9IHRhYmthLCBwYXRoID0gInRzdl90YWJrYS50c3YiKQpgYGAKCnJlYWQgaXQgaW4gYXMgYSB0c3YgYWdhaW4KCmBgYHtyfQp0YWJrYTIgPC0gcmVhZHI6OnJlYWRfdHN2KCJ0c3ZfdGFia2EudHN2IikKdGFia2EyCmBgYAoKCiMjIENoZWNrIGNvbnNpc3RlbmN5IAoKRGlzcGxheSBgdGFia2EyYC4gQ2FuIHlvdSBzZWUgYW55IHN0cmFuZ2UgdmFsdWUgdGhhdCBpcyBsaWtlbHkgdG8gYmUgd3Jvbmc/CldoYXQgZGF0YSB0eXBlcyB5b3Ugd291bGQgZXhwZWN0IGZvciB0aGUgaW5kaXZpZHVhbCBjb2x1bW5zPwoKYGBge3J9CnRhYmthMgpgYGAKCgpgYGB7cn0KbmFjdGVubyA8LSByZWFkcjo6cmVhZF90c3YoInRzdl90YWJrYS50c3YiLCAjY29sX3R5cGVzID0gbGlzdChjb2xfZG91YmxlKCksIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIyBjb2xfZG91YmxlKCksICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICMgY29sX2NoYXJhY3RlcigpLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICMgY29sX2NoYXJhY3RlcigpLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICMgY29sX2RhdGUoKSkKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgIGNvbF90eXBlcyA9ICJkZGNjRCIKCikjZG9waXMgdHlweSBzbG91cGN1CmBgYAoKYGBge3J9Cm5hY3Rlbm8KYGBgCgpgYGB7cn0KCnJlYWRyOjpwYXJzZV9kYXRlKHRhYmthJFZpc2l0KQpgYGAKCmBgYHtyfQpyZWFkcjo6cGFyc2VfY2hhcmFjdGVyKGFzLmNoYXJhY3Rlcih0YWJrYSRWaXNpdCkpCmBgYAoKYGBge3J9CiNsaWJyYXJ5KG1hZ3JpdHRyKQpyZWFkcjo6cGFyc2VfZG91YmxlKHRhYmthJFdlaWdodCkgJVQ+JSBzdHIoKSAjIHJldHVybnMgdGhlIHZhbHVlIGFzIHdlbGwgYXMgcHJpbnRzIHRoZSBzdHJ1Y3R1cmUgKGEgbWFncml0dHIgcGlwZSkKYGBgCgpgYGB7cn0Kd2VpZ2h0X2J5X3BpcGUgPC0gcmVhZHI6OnBhcnNlX2RvdWJsZShhcy5jaGFyYWN0ZXIodGFia2EkSGVpZ2h0KSkgJVQ+JSBzdHIoKQpgYGAKCmBgYHtyfQp3ZWlnaHRfYnlfcGlwZQpgYGAKCmBgYHtyfQpyZWFkcjo6cGFyc2VfZG91YmxlKGFzLmNoYXJhY3Rlcih0YWJrYSRIZWlnaHQpKSAjeCBtdXNpIGJ5dCB6bmFrLiB2ZWt0b3IuIEtkeXogdG8gemxvYmksIG11c2ltZSBobyB6IG5laiB1ZGVsYXQKYGBgCgpgYGB7cn0Kc3RyKHRhYmthJEhlaWdodCkKYGBgCgoKCmBgYHtyfQpzdHIodGFia2EpCmBgYAoKYGBge3J9CnN0cihuYWN0ZW5vKQpgYGAKCgpDb3JyZWN0IHRoZSBkYXRlIHJpZ2h0IGluIFIgdXNpbmcgdGhlIGJhc2UgUiB3aGF0IHlvdSBsZWFybmVkIGxvbmcgYWdvCgpgYGB7cn0KdGFia2EkVmlzaXRbNF0gPC0gIjIwMDgtMTItMDQiCmBgYAoKU2F2ZSB0aGUgY29ycmVjdGVkIGZpbGUgYXMgYGNvcnJlY3RlZF90YWIwMS50c3ZgCgpgYGB7cn0KcmVhZHI6OndyaXRlX3Rzdih0YWJrYSwgcGF0aCA9ICJjb3JyZWN0ZWRfdGFiMDEudHN2IiApCmBgYAoKIyBTYXZlIHRvZGF5J3MgZmlsZSB2ZXJzaW9uIAoKYGBge3J9CgpTeXMuRGF0ZSgpCnRvZGF5c19maWxlbmFtZSA8LSBwYXN0ZShTeXMuRGF0ZSgpLCAiY29ycmVjdGVkX3RhYjAxLnRzdiIsIHNlcCA9ICJfIikKdG9kYXlzX2ZpbGVuYW1lCmBgYAoKTm93IHNhdmUgdG9kYXkncyBmaWxlIHZlcnNpb24KYGBge3J9CnJlYWRyOjp3cml0ZV90c3YodGFia2EsIHBhdGggPSB0b2RheXNfZmlsZW5hbWUpCmBgYAoKVGhpcyBpcyBnb29kIGUuZy4gd2hlbiB5b3UgcnVuIGEgc2NyaXB0IGRhaWx5LCBmb3IgaW5zdGFuY2UgaWYgeW91IHdhbnQgdG8gCmtlZXAgdHJhY2sgb2YgdGhlIEN6ZWNoIGNvdmlkLTE5IHZhY2NpbmF0aW9uIHN0YXRpc3RpY3M6IAoKCmBgYHtyfQp2YWNjaW5hdGlvbl9maWxlbmFtZSA8LSBwYXN0ZShTeXMuRGF0ZSgpLCAiQWdyZWdPY2tvdmFuaS5jc3YiLCBzZXAgPSAiXyIpCnZhYyA8LSByZWFkcjo6cmVhZF9jc3YoZmlsZSA9ICJodHRwczovL29uZW1vY25lbmktYWt0dWFsbmUubXpjci5jei9hcGkvdjIvY292aWQtMTkvb2Nrb3ZhbmkuY3N2IikKYGBgCgpgYGB7cn0KZHBseXI6OmdsaW1wc2UodmFjKQpgYGAKCgpLb2xpayB2eW/EjWtvdmFseSBqZWRub3RsaXbDqSBrcmFqZSBjZWxrZW0gZMOhdmVrPyBWeXR2b8WZdGUgYWdyZWdvdmFub3UgdGFidWxrdSBhCnVsb8W+dGUgc2kgamkgZG8gc291Ym9ydSBwb2QgbsOhenZlbSBgZG5lc25pZGF0dW1fQWdyZWdPY2tvdmFuaS50c3ZgLiAoRG5lxaFuw60gZGF0dW0gcG9tb2PDrSBgU3lzLkRhdGUoKWApCgoKYGBge3J9CmRwbHlyOjpncm91cF9ieSh2YWMsIGtyYWpfbmF6ZXYpICU+JSBkcGx5cjo6c3VtbWFyaXplKHN1bShjZWxrZW1fZGF2ZWspKSAlPiUKICByZWFkcjo6d3JpdGVfY3N2KHBhdGggPSB2YWNjaW5hdGlvbl9maWxlbmFtZSkKYGBgCgpEaXNrdXR1anRlIC0gbmVwcm9ncmFtdWp0ZTogamFrIGJ5c3RlIHNpIHZ5cm9iaWxpIHRhYnVsa3UgcyBwb8SNdGVtIGTDoXZlayBwb2RsZSAKa3JhasWvIHphIGNlbMO9IG3Em3PDrWMgb2QgesOtdMWZa2E/CkthbSBieXN0ZSBzaSB1a2zDoWRhbGkgZGF0YT8gU3Bvam92YWxpIGJ5c3RlIHNvdWJvcnk/IE5lbXVzw610ZSB0byB1bcSbdCB1ZMSbbGF0LCAKamVuIHBvcMWZZW3DvcWhbGVqdGUuIAoKCgojVWxvxb50ZSBzaSBqYWvDvWtvbGkgc291Ym9yIHogd2VidSBkb23FrzogCgoKYGBge3J9CmRvd25sb2FkLmZpbGUodXJsID0gImh0dHBzOi8vb25lbW9jbmVuaS1ha3R1YWxuZS5temNyLmN6L2FwaS92Mi9jb3ZpZC0xOS9vY2tvdmFuaS5qc29uIiwgCiAgICAgICAgICAgICAgZGVzdGZpbGUgPSAib2Nrb3ZhbmkuanNvbiIpCmBgYAoKCmBgYHtyfQpkb3dubG9hZC5maWxlKHVybCA9ICJodHRwczovL3d3dy5ndXRlbmJlcmcub3JnL2ZpbGVzLzI2MTg0LzI2MTg0LTgudHh0IiwgCiAgICAgICAgICAgICBkZXN0ZmlsZSA9ICJndXRlbmJlcmcwMS50eHQiKQpgYGAKCgoKCmBgYHtyfQpyZWFkcjo6cmVhZF9saW5lcyhmaWxlID0gImd1dGVuYmVyZzAxLnR4dCIsIG5fbWF4ID0gNSkKYGBgCgoKCiMgSlNPTgoKYGBge3J9Cmpzb25saXRlOjpmcm9tSlNPTigib2Nrb3ZhbmkuanNvbiIpCmBgYAoKCgojIEN2acSNZW7DrQotIE5hxI10xJt0ZSBzaSBzb3Vib3IgYFRvb3RHcm93dGguZGl2bmVqYCBqYWtvIGNvIG5lamxlcMWhw60gdGFidWxrdS4gCi0gUHJvemtvdW1lanRlIGJhbMOtxI1layBgcmVhZE9EU2AgYSBuYcSNdMSbdGUgc291Ym9yIGB0YWIwMS5vZHNgICh6IHRhYnVsa292w6lobyAKcHJvY2Vzb3J1IENhbGMgdiBPZmZpY2UgTGlicmUpCi0gUHJvemtvdW1lanRlIGJhbMOtxI1layBgcmVhZHhsYCBhIG5hxI10xJt0ZSBzb3Vib3IgYHRhYjAxLnhsc3hgCgoKIyBEYXRhQ2FtcCBhYm91dCAK