library(flexdashboard)
knitr::opts_chunk$set(
echo = TRUE,
message = FALSE,
warning = FALSE,
include = TRUE
)
##
r = getOption("repos")
r["CRAN"] = "http://cran.us.r-project.org"
options(repos = r)
###
if(!require(tidyverse)){install.packages("tidyverse")}
if(!require(googlesheets4)){install.packages("googlesheets4")}
if(!require(googledrive)){install.packages("googledrive")}
if(!require(dplyr)){install.packages("dplyr")}
if(!require(httr2)){install.packages("httr2")}
if(!require(jsonlite)){install.packages("jsonlite")}
if(!require(Rselenium)){install.packages("Rselenium")}
WARNING: Rtools is required to build R packages but is not currently installed. Please download and install the appropriate version of Rtools before proceeding:
https://cran.rstudio.com/bin/windows/Rtools/
if(!require(chromote)){install.packages("chromote")}
if(!require(purrr)){install.packages("purrr")}
if(!require(wdman)){install.packages("wdman")}
if(!require(pdftools)){install.packages("pdftools")}
##
library(pdftools)
library(chromote)
library(purrr)
library(wdman)
library(tidyverse)
library(rvest)
library(dplyr)
library(jsonlite)
library(RSelenium)
library(googlesheets4)
library(googledrive)
Men Chamonix July
##################################################
# scraping active page using chromote #
#############################################
# URL of the webpage to scrape
url <- "https://www.ifsc-climbing.org/events/ifsc-world-cup-chamonix-2024/result/index?discipline=lead&category=men"
############ chromote:: OPTION ######
# Create a new Chromote session
b <- ChromoteSession$new()
# Navigate to the webpage
b$Page$navigate(url)
$frameId
[1] "CE0D642469B8541986F2430F7276291C"
$loaderId
[1] "FC79A989BD3828D3944714880352BB38"
# Extract the rendered HTML
# html <- b$Runtime$evaluate('document.querySelector(".appearence-none)') # Replace with your CSS selector
Quali
html <- b$Runtime$evaluate('document.querySelector(".appearence-none:nth-child(1)").click();') # Replace with your CSS selector
Sys.sleep(10)
### WAIT for "backstage" page loading ####
html <- b$Runtime$evaluate("document.documentElement.outerHTML")$result$value
##
page <- read_html(html)
###
compe <- page %>%
html_elements('h2.d3-ty-heading-2') %>%
html_text()
###
competitor_divs <- page %>%
html_elements("tr.px-6") #
# Extract and clean data
scrap <- competitor_divs %>%
map_df(~{
rank <- .x %>% html_element("td.py-2:nth-child(1)") %>% html_text(trim = TRUE) %>% tail(1) # rank
name <- .x %>% html_element("td.py-2:nth-child(2)") %>% html_text(trim = TRUE) %>% tail(1) # name
country <- .x %>% html_element("td.py-2:nth-child(3)") %>% html_text(trim = TRUE) %>% tail(1) # country
score <- .x %>% html_element("td.py-2:nth-child(4)") %>% html_text(trim = TRUE) %>% tail(1) # score
# Return as a tibble
tibble(Name = name,
Rank = rank,
Country = country,
Score = score)
})
###
#scrap <- scrap %>%
# separate(Score, into = c(NA, "score", "Ts", "Zs","Score.rank", NA), sep = " ")
#scrap <- scrap %>%
# separate(score.rank, into = c(NA,NA,"score.rank"), sep = "()")
scrap <- scrap %>%
mutate(Rank = as.numeric(Rank),
Competition = rep(compe, length(scrap$Name) ),
Stage = rep("Quali", length(scrap$Name ) ) )
##
compe
[1] "IFSC World Cup Chamonix 2024"
n.competitors <- max(scrap$Rank, na.rm = TRUE); n.competitors
[1] 68
##
# scrap %>% print(n=length(scrap$Name))
#scrap[,c(1:9)] %>%
# filter(!is.na(score)) %>%
# print(n = 17)
############### ##################
Men_Chamonix_Quali <- scrap
SemiFs
###
b$Runtime$evaluate("
let dropdown = document.querySelector('select.d3-ty-select'); // Find the dropdown by class
if (dropdown) {
dropdown.value = 'Semi-final'; // Set the value to 'Semi-final'
dropdown.dispatchEvent(new Event('change', { bubbles: true })); // Trigger update
}
")
$result
$result$type
[1] "boolean"
$result$value
[1] TRUE
###
stage <- b$Runtime$evaluate("
document.querySelector('select.d3-ty-select').value;
")$result$value
###
#html <- b$Runtime$evaluate('document.querySelector(".dropdown-Semim-final").click();') # Replace with your CSS selector
Sys.sleep(10)
### WAIT for "backstage" page loading ####
html <- b$Runtime$evaluate("document.documentElement.outerHTML")$result$value
##
page <- read_html(html)
###
compe <- page %>%
html_elements('h2.d3-ty-heading-2') %>%
html_text()
###
competitor_divs <- page %>%
html_elements("tr.px-6") #
# Extract and clean data
scrap <- competitor_divs %>%
map_df(~{
rank <- .x %>% html_element("td.py-2:nth-child(1)") %>% html_text(trim = TRUE) %>% tail(1) # rank
name <- .x %>% html_element("td.py-2:nth-child(2)") %>% html_text(trim = TRUE) %>% tail(1) # name
country <- .x %>% html_element("td.py-2:nth-child(3)") %>% html_text(trim = TRUE) %>% tail(1) # country
score <- .x %>% html_element("td.py-2:nth-child(4)") %>% html_text(trim = TRUE) %>% tail(1) # score
# Return as a tibble
tibble(Name = name,
Rank = rank,
Country = country,
Score = score)
})
###
#scrap <- scrap %>%
# separate(Score, into = c(NA, "score", "Ts", "Zs","Score.rank", NA), sep = " ")
#scrap <- scrap %>%
# separate(score.rank, into = c(NA,NA,"score.rank"), sep = "()")
scrap <- scrap %>%
mutate(Rank = as.numeric(Rank),
Competition = rep(compe, length(scrap$Name) ),
Stage = rep(stage, length(scrap$Name)))
##
compe
[1] "IFSC World Cup Chamonix 2024"
n.competitors <- max(scrap$Rank, na.rm = TRUE); n.competitors
[1] 26
##
# scrap %>% print(n=length(scrap$Name))
#scrap[,c(1:9)] %>%
# filter(!is.na(score)) %>%
# print(n = 17)
############### ##################
Men_Chamonix_Semifs <- scrap
Finals
b <- ChromoteSession$new()
# Navigate to the webpage
b$Page$navigate(url)
$frameId
[1] "703CD5C788061E938202AF06BEAA792E"
$loaderId
[1] "80B0F5A93F6BC0862BCC8505D9EAE44B"
# Extract the rendered HTML
# html <- b$Runtime$evaluate('document.querySelector(".appearence-none)') # Replace with your CSS selector
html <- b$Runtime$evaluate('document.querySelector(".appearence-none:nth-child(1)").click();') # Replace with your CSS selector
Sys.sleep(10)
###
b$Runtime$evaluate("
let dropdown = document.querySelector('select.d3-ty-select'); // Find the dropdown by class
if (dropdown) {
dropdown.value = 'Final'; // Set the value to 'Final'
dropdown.dispatchEvent(new Event('change', { bubbles: true })); // Trigger update
}
")
$result
$result$type
[1] "boolean"
$result$value
[1] TRUE
###
stage <- b$Runtime$evaluate("
document.querySelector('select.d3-ty-select').value;
")$result$value
###
#html <- b$Runtime$evaluate('document.querySelector(".dropdown-Semim-final").click();') # Replace with your CSS selector
Sys.sleep(10)
### WAIT for "backstage" page loading ####
html <- b$Runtime$evaluate("document.documentElement.outerHTML")$result$value
##
page <- read_html(html)
###
compe <- page %>%
html_elements('h2.d3-ty-heading-2') %>%
html_text()
###
competitor_divs <- page %>%
html_elements("tr.px-6") #
# Extract and clean data
scrap <- competitor_divs %>%
map_df(~{
rank <- .x %>% html_element("td.py-2:nth-child(1)") %>% html_text(trim = TRUE) %>% tail(1) # rank
name <- .x %>% html_element("td.py-2:nth-child(2)") %>% html_text(trim = TRUE) %>% tail(1) # name
country <- .x %>% html_element("td.py-2:nth-child(3)") %>% html_text(trim = TRUE) %>% tail(1) # country
score <- .x %>% html_element("td.py-2:nth-child(4)") %>% html_text(trim = TRUE) %>% tail(1) # score
# Return as a tibble
tibble(Name = name,
Rank = rank,
Country = country,
Score = score)
})
###
#scrap <- scrap %>%
# separate(Score, into = c(NA, "score", "Ts", "Zs","Score.rank", NA), sep = " ")
#scrap <- scrap %>%
# separate(score.rank, into = c(NA,NA,"score.rank"), sep = "()")
scrap <- scrap %>%
mutate(Rank = as.numeric(Rank),
Competition = rep(compe, length(scrap$Name) ),
Stage = rep(stage, length(scrap$Name)))
##
compe
[1] "IFSC World Cup Chamonix 2024"
n.competitors <- max(scrap$Rank, na.rm = TRUE); n.competitors
[1] 8
##
# scrap %>% print(n=length(scrap$Name))
#scrap[,c(1:9)] %>%
# filter(!is.na(score)) %>%
# print(n = 17)
############### ##################
Men_Chamonix_Finals <- scrap
WRITE
### Write google sheet ###
Men.July_Chamonix.24 <- rbind(Men_Chamonix_Quali,
Men_Chamonix_Semifs,
Men_Chamonix_Finals)
Men.July_Chamonix.24 %>% print(n=length(Men.July_Chamonix.24$Name))
options(gargle_oauth_email = "villatoropazfj@dataanalysislab.com")
gs4_deauth()
gs4_auth()
sheet_write(data = Men.July_Chamonix.24,
ss= "https://docs.google.com/spreadsheets/d/1JhBs7yceEXUrnncYDWkWT16nKY1MCx_ZTpxgOOURJ6M/edit?usp=sharing",
sheet=paste("Men.July_Chamonix.24", "_", Sys.Date()))
LS0tDQp0aXRsZTogIklGU0NfcmVzdWx0c19sZWFkXzIwMjQiDQphdXRob3I6ICJGZWRlcmljbyBKLiBWaWxsYXRvcm8iDQpvdXRwdXQ6IA0KICBodG1sX25vdGVib29rOg0KICAgIHRvYzogdHJ1ZQ0KICAgIHRvY19kZXB0aDogMw0KICAgIHRvY19mbG9hdDogdHJ1ZQ0KZGF0ZTogImByIFN5cy5EYXRlKClgIg0KLS0tDQoNCiMjIyMjIEZ1ZW50ZTogW2h0dHBzOi8vd3d3Lmlmc2MtY2xpbWJpbmcub3JnL2NhbGVuZGFyL2luZGV4XShodHRwczovL3d3dy5pZnNjLWNsaW1iaW5nLm9yZy9jYWxlbmRhci9pbmRleCkNCg0KYGBge3Igc2V0dXAsIGluY2x1ZGU9VFJVRX0NCmxpYnJhcnkoZmxleGRhc2hib2FyZCkNCmtuaXRyOjpvcHRzX2NodW5rJHNldCgNCiAgZWNobyA9IFRSVUUsDQoJbWVzc2FnZSA9IEZBTFNFLA0KICB3YXJuaW5nID0gRkFMU0UsDQoJaW5jbHVkZSA9IFRSVUUNCikNCmBgYCAgDQoNCmBgYHtyIHBhY2thZ2VzLCBtZXNzYWdlPUZBTFNFLCBpbmNsdWRlPVRSVUV9DQojIw0KciA9IGdldE9wdGlvbigicmVwb3MiKQ0KclsiQ1JBTiJdID0gImh0dHA6Ly9jcmFuLnVzLnItcHJvamVjdC5vcmciDQpvcHRpb25zKHJlcG9zID0gcikNCiMjIw0KaWYoIXJlcXVpcmUodGlkeXZlcnNlKSl7aW5zdGFsbC5wYWNrYWdlcygidGlkeXZlcnNlIil9DQppZighcmVxdWlyZShnb29nbGVzaGVldHM0KSl7aW5zdGFsbC5wYWNrYWdlcygiZ29vZ2xlc2hlZXRzNCIpfQ0KaWYoIXJlcXVpcmUoZ29vZ2xlZHJpdmUpKXtpbnN0YWxsLnBhY2thZ2VzKCJnb29nbGVkcml2ZSIpfQ0KaWYoIXJlcXVpcmUoZHBseXIpKXtpbnN0YWxsLnBhY2thZ2VzKCJkcGx5ciIpfQ0KaWYoIXJlcXVpcmUoaHR0cjIpKXtpbnN0YWxsLnBhY2thZ2VzKCJodHRyMiIpfQ0KaWYoIXJlcXVpcmUoanNvbmxpdGUpKXtpbnN0YWxsLnBhY2thZ2VzKCJqc29ubGl0ZSIpfQ0KaWYoIXJlcXVpcmUoUnNlbGVuaXVtKSl7aW5zdGFsbC5wYWNrYWdlcygiUnNlbGVuaXVtIil9DQppZighcmVxdWlyZShjaHJvbW90ZSkpe2luc3RhbGwucGFja2FnZXMoImNocm9tb3RlIil9DQppZighcmVxdWlyZShwdXJycikpe2luc3RhbGwucGFja2FnZXMoInB1cnJyIil9DQppZighcmVxdWlyZSh3ZG1hbikpe2luc3RhbGwucGFja2FnZXMoIndkbWFuIil9DQppZighcmVxdWlyZShwZGZ0b29scykpe2luc3RhbGwucGFja2FnZXMoInBkZnRvb2xzIil9DQojIw0KbGlicmFyeShwZGZ0b29scykNCmxpYnJhcnkoY2hyb21vdGUpDQpsaWJyYXJ5KHB1cnJyKQ0KbGlicmFyeSh3ZG1hbikNCg0KbGlicmFyeSh0aWR5dmVyc2UpDQpsaWJyYXJ5KHJ2ZXN0KQ0KbGlicmFyeShkcGx5cikNCmxpYnJhcnkoanNvbmxpdGUpDQpsaWJyYXJ5KFJTZWxlbml1bSkNCg0KbGlicmFyeShnb29nbGVzaGVldHM0KQ0KbGlicmFyeShnb29nbGVkcml2ZSkNCg0KYGBgICANCg0KIyMgTWVuIENoYW1vbml4IEp1bHkNCg0KYGBge3IgaW5jbHVkZT1UUlVFfQ0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgc2NyYXBpbmcgYWN0aXZlIHBhZ2UgdXNpbmcgY2hyb21vdGUgIw0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQoNCiMgVVJMIG9mIHRoZSB3ZWJwYWdlIHRvIHNjcmFwZQ0KdXJsIDwtICJodHRwczovL3d3dy5pZnNjLWNsaW1iaW5nLm9yZy9ldmVudHMvaWZzYy13b3JsZC1jdXAtY2hhbW9uaXgtMjAyNC9yZXN1bHQvaW5kZXg/ZGlzY2lwbGluZT1sZWFkJmNhdGVnb3J5PW1lbiINCiMjIyMjIyMjIyMjIyAgIGNocm9tb3RlOjogT1BUSU9OICMjIyMjIw0KIyBDcmVhdGUgYSBuZXcgQ2hyb21vdGUgc2Vzc2lvbg0KYiA8LSBDaHJvbW90ZVNlc3Npb24kbmV3KCkNCiMgTmF2aWdhdGUgdG8gdGhlIHdlYnBhZ2UNCmIkUGFnZSRuYXZpZ2F0ZSh1cmwpDQojIEV4dHJhY3QgdGhlIHJlbmRlcmVkIEhUTUwNCiMgICBodG1sIDwtIGIkUnVudGltZSRldmFsdWF0ZSgnZG9jdW1lbnQucXVlcnlTZWxlY3RvcigiLmFwcGVhcmVuY2Utbm9uZSknKSAgIyBSZXBsYWNlIHdpdGggeW91ciBDU1Mgc2VsZWN0b3INCmBgYCAgDQoNCiMjIyBRdWFsaQ0KYGBge3J9DQpodG1sIDwtIGIkUnVudGltZSRldmFsdWF0ZSgnZG9jdW1lbnQucXVlcnlTZWxlY3RvcigiLmFwcGVhcmVuY2Utbm9uZTpudGgtY2hpbGQoMSkiKS5jbGljaygpOycpICAjIFJlcGxhY2Ugd2l0aCB5b3VyIENTUyBzZWxlY3Rvcg0KU3lzLnNsZWVwKDEwKSANCg0KIyMjIFdBSVQgZm9yICJiYWNrc3RhZ2UiIHBhZ2UgbG9hZGluZyAjIyMjDQpodG1sIDwtIGIkUnVudGltZSRldmFsdWF0ZSgiZG9jdW1lbnQuZG9jdW1lbnRFbGVtZW50Lm91dGVySFRNTCIpJHJlc3VsdCR2YWx1ZQ0KIyMgDQpwYWdlIDwtIHJlYWRfaHRtbChodG1sKQ0KIyMjIA0KY29tcGUgPC0gcGFnZSAlPiUNCiAgaHRtbF9lbGVtZW50cygnaDIuZDMtdHktaGVhZGluZy0yJykgJT4lDQogIGh0bWxfdGV4dCgpDQojIyMNCmNvbXBldGl0b3JfZGl2cyA8LSBwYWdlICU+JSANCiAgaHRtbF9lbGVtZW50cygidHIucHgtNiIpICMgDQoNCiMgRXh0cmFjdCBhbmQgY2xlYW4gZGF0YQ0Kc2NyYXAgPC0gY29tcGV0aXRvcl9kaXZzICU+JQ0KICBtYXBfZGYofnsNCiAgICByYW5rIDwtIC54ICU+JSBodG1sX2VsZW1lbnQoInRkLnB5LTI6bnRoLWNoaWxkKDEpIikgJT4lIGh0bWxfdGV4dCh0cmltID0gVFJVRSkgJT4lIHRhaWwoMSkgIyByYW5rDQogICAgbmFtZSA8LSAueCAlPiUgaHRtbF9lbGVtZW50KCJ0ZC5weS0yOm50aC1jaGlsZCgyKSIpICU+JSBodG1sX3RleHQodHJpbSA9IFRSVUUpICU+JSB0YWlsKDEpICMgbmFtZQ0KICAgIGNvdW50cnkgPC0gLnggJT4lIGh0bWxfZWxlbWVudCgidGQucHktMjpudGgtY2hpbGQoMykiKSAlPiUgaHRtbF90ZXh0KHRyaW0gPSBUUlVFKSAlPiUgdGFpbCgxKSAjIGNvdW50cnkgDQogICAgc2NvcmUgPC0gLnggJT4lIGh0bWxfZWxlbWVudCgidGQucHktMjpudGgtY2hpbGQoNCkiKSAlPiUgaHRtbF90ZXh0KHRyaW0gPSBUUlVFKSAlPiUgdGFpbCgxKSAgIyBzY29yZQ0KICAgICMgUmV0dXJuIGFzIGEgdGliYmxlDQogICAgdGliYmxlKE5hbWUgPSBuYW1lLCANCiAgICAgICAgICAgUmFuayA9IHJhbmssDQogICAgICAgICAgIENvdW50cnkgPSBjb3VudHJ5LA0KICAgICAgICAgICBTY29yZSA9IHNjb3JlKQ0KICB9KQ0KIyMjDQojc2NyYXAgPC0gc2NyYXAgJT4lIA0KICMgc2VwYXJhdGUoU2NvcmUsIGludG8gPSBjKE5BLCAic2NvcmUiLCAiVHMiLCAiWnMiLCJTY29yZS5yYW5rIiwgTkEpLCBzZXAgPSAiICIpDQojc2NyYXAgPC0gc2NyYXAgJT4lIA0KICMgc2VwYXJhdGUoc2NvcmUucmFuaywgaW50byA9IGMoTkEsTkEsInNjb3JlLnJhbmsiKSwgc2VwID0gIigpIikNCnNjcmFwIDwtIHNjcmFwICU+JSANCiAgbXV0YXRlKFJhbmsgPSBhcy5udW1lcmljKFJhbmspLCANCiAgICAgICAgIENvbXBldGl0aW9uID0gcmVwKGNvbXBlLCBsZW5ndGgoc2NyYXAkTmFtZSkgKSwNCiAgICAgICAgIFN0YWdlID0gcmVwKCJRdWFsaSIsIGxlbmd0aChzY3JhcCROYW1lICkgKSApDQojIw0KY29tcGUNCm4uY29tcGV0aXRvcnMgPC0gbWF4KHNjcmFwJFJhbmssIG5hLnJtID0gVFJVRSk7IG4uY29tcGV0aXRvcnMNCiMjDQojIHNjcmFwICU+JSBwcmludChuPWxlbmd0aChzY3JhcCROYW1lKSkNCiNzY3JhcFssYygxOjkpXSAlPiUgDQogIyBmaWx0ZXIoIWlzLm5hKHNjb3JlKSkgJT4lDQojICBwcmludChuID0gMTcpDQojIyMjIyMjIyMjIyMjIyMgIyMjIyMjIyMjIyMjIyMjIyMjDQpNZW5fQ2hhbW9uaXhfUXVhbGkgPC0gc2NyYXANCmBgYCAgDQoNCiMjIyBTZW1pRnMNCg0KYGBge3J9DQoNCiMjIw0KYiRSdW50aW1lJGV2YWx1YXRlKCINCiAgbGV0IGRyb3Bkb3duID0gZG9jdW1lbnQucXVlcnlTZWxlY3Rvcignc2VsZWN0LmQzLXR5LXNlbGVjdCcpOyAvLyBGaW5kIHRoZSBkcm9wZG93biBieSBjbGFzcw0KICBpZiAoZHJvcGRvd24pIHsNCiAgICBkcm9wZG93bi52YWx1ZSA9ICdTZW1pLWZpbmFsJzsgIC8vIFNldCB0aGUgdmFsdWUgdG8gJ1NlbWktZmluYWwnDQogICAgZHJvcGRvd24uZGlzcGF0Y2hFdmVudChuZXcgRXZlbnQoJ2NoYW5nZScsIHsgYnViYmxlczogdHJ1ZSB9KSk7IC8vIFRyaWdnZXIgdXBkYXRlDQogIH0NCiIpDQojIyMNCnN0YWdlIDwtIGIkUnVudGltZSRldmFsdWF0ZSgiDQogIGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IoJ3NlbGVjdC5kMy10eS1zZWxlY3QnKS52YWx1ZTsNCiIpJHJlc3VsdCR2YWx1ZQ0KIyMjDQoNCg0KI2h0bWwgPC0gYiRSdW50aW1lJGV2YWx1YXRlKCdkb2N1bWVudC5xdWVyeVNlbGVjdG9yKCIuZHJvcGRvd24tU2VtaW0tZmluYWwiKS5jbGljaygpOycpICAjIFJlcGxhY2Ugd2l0aCB5b3VyIENTUyBzZWxlY3Rvcg0KU3lzLnNsZWVwKDEwKSANCg0KIyMjIFdBSVQgZm9yICJiYWNrc3RhZ2UiIHBhZ2UgbG9hZGluZyAjIyMjDQpodG1sIDwtIGIkUnVudGltZSRldmFsdWF0ZSgiZG9jdW1lbnQuZG9jdW1lbnRFbGVtZW50Lm91dGVySFRNTCIpJHJlc3VsdCR2YWx1ZQ0KIyMgDQpwYWdlIDwtIHJlYWRfaHRtbChodG1sKQ0KIyMjIA0KY29tcGUgPC0gcGFnZSAlPiUNCiAgaHRtbF9lbGVtZW50cygnaDIuZDMtdHktaGVhZGluZy0yJykgJT4lDQogIGh0bWxfdGV4dCgpDQojIyMNCmNvbXBldGl0b3JfZGl2cyA8LSBwYWdlICU+JSANCiAgaHRtbF9lbGVtZW50cygidHIucHgtNiIpICMgDQoNCiMgRXh0cmFjdCBhbmQgY2xlYW4gZGF0YQ0Kc2NyYXAgPC0gY29tcGV0aXRvcl9kaXZzICU+JQ0KICBtYXBfZGYofnsNCiAgICByYW5rIDwtIC54ICU+JSBodG1sX2VsZW1lbnQoInRkLnB5LTI6bnRoLWNoaWxkKDEpIikgJT4lIGh0bWxfdGV4dCh0cmltID0gVFJVRSkgJT4lIHRhaWwoMSkgIyByYW5rDQogICAgbmFtZSA8LSAueCAlPiUgaHRtbF9lbGVtZW50KCJ0ZC5weS0yOm50aC1jaGlsZCgyKSIpICU+JSBodG1sX3RleHQodHJpbSA9IFRSVUUpICU+JSB0YWlsKDEpICMgbmFtZQ0KICAgIGNvdW50cnkgPC0gLnggJT4lIGh0bWxfZWxlbWVudCgidGQucHktMjpudGgtY2hpbGQoMykiKSAlPiUgaHRtbF90ZXh0KHRyaW0gPSBUUlVFKSAlPiUgdGFpbCgxKSAjIGNvdW50cnkgDQogICAgc2NvcmUgPC0gLnggJT4lIGh0bWxfZWxlbWVudCgidGQucHktMjpudGgtY2hpbGQoNCkiKSAlPiUgaHRtbF90ZXh0KHRyaW0gPSBUUlVFKSAlPiUgdGFpbCgxKSAgIyBzY29yZQ0KICAgICMgUmV0dXJuIGFzIGEgdGliYmxlDQogICAgdGliYmxlKE5hbWUgPSBuYW1lLCANCiAgICAgICAgICAgUmFuayA9IHJhbmssDQogICAgICAgICAgIENvdW50cnkgPSBjb3VudHJ5LA0KICAgICAgICAgICBTY29yZSA9IHNjb3JlKQ0KICB9KQ0KIyMjDQojc2NyYXAgPC0gc2NyYXAgJT4lIA0KICMgc2VwYXJhdGUoU2NvcmUsIGludG8gPSBjKE5BLCAic2NvcmUiLCAiVHMiLCAiWnMiLCJTY29yZS5yYW5rIiwgTkEpLCBzZXAgPSAiICIpDQojc2NyYXAgPC0gc2NyYXAgJT4lIA0KICMgc2VwYXJhdGUoc2NvcmUucmFuaywgaW50byA9IGMoTkEsTkEsInNjb3JlLnJhbmsiKSwgc2VwID0gIigpIikNCnNjcmFwIDwtIHNjcmFwICU+JSANCiAgbXV0YXRlKFJhbmsgPSBhcy5udW1lcmljKFJhbmspLCANCiAgICAgICAgIENvbXBldGl0aW9uID0gcmVwKGNvbXBlLCBsZW5ndGgoc2NyYXAkTmFtZSkgKSwNCiAgICAgICAgIFN0YWdlID0gcmVwKHN0YWdlLCBsZW5ndGgoc2NyYXAkTmFtZSkpKQ0KIyMNCmNvbXBlDQpuLmNvbXBldGl0b3JzIDwtIG1heChzY3JhcCRSYW5rLCBuYS5ybSA9IFRSVUUpOyBuLmNvbXBldGl0b3JzDQojIw0KIyBzY3JhcCAlPiUgcHJpbnQobj1sZW5ndGgoc2NyYXAkTmFtZSkpDQojc2NyYXBbLGMoMTo5KV0gJT4lIA0KICMgZmlsdGVyKCFpcy5uYShzY29yZSkpICU+JQ0KIyAgcHJpbnQobiA9IDE3KQ0KIyMjIyMjIyMjIyMjIyMjICMjIyMjIyMjIyMjIyMjIyMjIw0KTWVuX0NoYW1vbml4X1NlbWlmcyA8LSBzY3JhcA0KYGBgICANCiMjIyBGaW5hbHMNCg0KYGBge3J9DQpiIDwtIENocm9tb3RlU2Vzc2lvbiRuZXcoKQ0KIyBOYXZpZ2F0ZSB0byB0aGUgd2VicGFnZQ0KYiRQYWdlJG5hdmlnYXRlKHVybCkNCiMgRXh0cmFjdCB0aGUgcmVuZGVyZWQgSFRNTA0KIyAgIGh0bWwgPC0gYiRSdW50aW1lJGV2YWx1YXRlKCdkb2N1bWVudC5xdWVyeVNlbGVjdG9yKCIuYXBwZWFyZW5jZS1ub25lKScpICAjIFJlcGxhY2Ugd2l0aCB5b3VyIENTUyBzZWxlY3Rvcg0KaHRtbCA8LSBiJFJ1bnRpbWUkZXZhbHVhdGUoJ2RvY3VtZW50LnF1ZXJ5U2VsZWN0b3IoIi5hcHBlYXJlbmNlLW5vbmU6bnRoLWNoaWxkKDEpIikuY2xpY2soKTsnKSAgIyBSZXBsYWNlIHdpdGggeW91ciBDU1Mgc2VsZWN0b3INClN5cy5zbGVlcCgxMCkgDQojIyMNCmIkUnVudGltZSRldmFsdWF0ZSgiDQogIGxldCBkcm9wZG93biA9IGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IoJ3NlbGVjdC5kMy10eS1zZWxlY3QnKTsgLy8gRmluZCB0aGUgZHJvcGRvd24gYnkgY2xhc3MNCiAgaWYgKGRyb3Bkb3duKSB7DQogICAgZHJvcGRvd24udmFsdWUgPSAnRmluYWwnOyAgLy8gU2V0IHRoZSB2YWx1ZSB0byAnRmluYWwnDQogICAgZHJvcGRvd24uZGlzcGF0Y2hFdmVudChuZXcgRXZlbnQoJ2NoYW5nZScsIHsgYnViYmxlczogdHJ1ZSB9KSk7IC8vIFRyaWdnZXIgdXBkYXRlDQogIH0NCiIpDQojIyMNCnN0YWdlIDwtIGIkUnVudGltZSRldmFsdWF0ZSgiDQogIGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IoJ3NlbGVjdC5kMy10eS1zZWxlY3QnKS52YWx1ZTsNCiIpJHJlc3VsdCR2YWx1ZQ0KIyMjDQoNCg0KI2h0bWwgPC0gYiRSdW50aW1lJGV2YWx1YXRlKCdkb2N1bWVudC5xdWVyeVNlbGVjdG9yKCIuZHJvcGRvd24tU2VtaW0tZmluYWwiKS5jbGljaygpOycpICAjIFJlcGxhY2Ugd2l0aCB5b3VyIENTUyBzZWxlY3Rvcg0KU3lzLnNsZWVwKDEwKSANCg0KIyMjIFdBSVQgZm9yICJiYWNrc3RhZ2UiIHBhZ2UgbG9hZGluZyAjIyMjDQpodG1sIDwtIGIkUnVudGltZSRldmFsdWF0ZSgiZG9jdW1lbnQuZG9jdW1lbnRFbGVtZW50Lm91dGVySFRNTCIpJHJlc3VsdCR2YWx1ZQ0KIyMgDQpwYWdlIDwtIHJlYWRfaHRtbChodG1sKQ0KIyMjIA0KY29tcGUgPC0gcGFnZSAlPiUNCiAgaHRtbF9lbGVtZW50cygnaDIuZDMtdHktaGVhZGluZy0yJykgJT4lDQogIGh0bWxfdGV4dCgpDQojIyMNCmNvbXBldGl0b3JfZGl2cyA8LSBwYWdlICU+JSANCiAgaHRtbF9lbGVtZW50cygidHIucHgtNiIpICMgDQoNCiMgRXh0cmFjdCBhbmQgY2xlYW4gZGF0YQ0Kc2NyYXAgPC0gY29tcGV0aXRvcl9kaXZzICU+JQ0KICBtYXBfZGYofnsNCiAgICByYW5rIDwtIC54ICU+JSBodG1sX2VsZW1lbnQoInRkLnB5LTI6bnRoLWNoaWxkKDEpIikgJT4lIGh0bWxfdGV4dCh0cmltID0gVFJVRSkgJT4lIHRhaWwoMSkgIyByYW5rDQogICAgbmFtZSA8LSAueCAlPiUgaHRtbF9lbGVtZW50KCJ0ZC5weS0yOm50aC1jaGlsZCgyKSIpICU+JSBodG1sX3RleHQodHJpbSA9IFRSVUUpICU+JSB0YWlsKDEpICMgbmFtZQ0KICAgIGNvdW50cnkgPC0gLnggJT4lIGh0bWxfZWxlbWVudCgidGQucHktMjpudGgtY2hpbGQoMykiKSAlPiUgaHRtbF90ZXh0KHRyaW0gPSBUUlVFKSAlPiUgdGFpbCgxKSAjIGNvdW50cnkgDQogICAgc2NvcmUgPC0gLnggJT4lIGh0bWxfZWxlbWVudCgidGQucHktMjpudGgtY2hpbGQoNCkiKSAlPiUgaHRtbF90ZXh0KHRyaW0gPSBUUlVFKSAlPiUgdGFpbCgxKSAgIyBzY29yZQ0KICAgICMgUmV0dXJuIGFzIGEgdGliYmxlDQogICAgdGliYmxlKE5hbWUgPSBuYW1lLCANCiAgICAgICAgICAgUmFuayA9IHJhbmssDQogICAgICAgICAgIENvdW50cnkgPSBjb3VudHJ5LA0KICAgICAgICAgICBTY29yZSA9IHNjb3JlKQ0KICB9KQ0KIyMjDQojc2NyYXAgPC0gc2NyYXAgJT4lIA0KICMgc2VwYXJhdGUoU2NvcmUsIGludG8gPSBjKE5BLCAic2NvcmUiLCAiVHMiLCAiWnMiLCJTY29yZS5yYW5rIiwgTkEpLCBzZXAgPSAiICIpDQojc2NyYXAgPC0gc2NyYXAgJT4lIA0KICMgc2VwYXJhdGUoc2NvcmUucmFuaywgaW50byA9IGMoTkEsTkEsInNjb3JlLnJhbmsiKSwgc2VwID0gIigpIikNCnNjcmFwIDwtIHNjcmFwICU+JSANCiAgbXV0YXRlKFJhbmsgPSBhcy5udW1lcmljKFJhbmspLCANCiAgICAgICAgIENvbXBldGl0aW9uID0gcmVwKGNvbXBlLCBsZW5ndGgoc2NyYXAkTmFtZSkgKSwNCiAgICAgICAgIFN0YWdlID0gcmVwKHN0YWdlLCBsZW5ndGgoc2NyYXAkTmFtZSkpKQ0KIyMNCmNvbXBlDQpuLmNvbXBldGl0b3JzIDwtIG1heChzY3JhcCRSYW5rLCBuYS5ybSA9IFRSVUUpOyBuLmNvbXBldGl0b3JzDQojIw0KIyBzY3JhcCAlPiUgcHJpbnQobj1sZW5ndGgoc2NyYXAkTmFtZSkpDQojc2NyYXBbLGMoMTo5KV0gJT4lIA0KICMgZmlsdGVyKCFpcy5uYShzY29yZSkpICU+JQ0KIyAgcHJpbnQobiA9IDE3KQ0KIyMjIyMjIyMjIyMjIyMjICMjIyMjIyMjIyMjIyMjIyMjIw0KTWVuX0NoYW1vbml4X0ZpbmFscyA8LSBzY3JhcA0KYGBgICANCg0KIyMjIFdSSVRFDQoNCmBgYHtyIGluY2x1ZGU9VFJVRSwgZXZhbD1GQUxTRX0NCiMjIyBXcml0ZSBnb29nbGUgc2hlZXQgIyMjDQpNZW4uSnVseV9DaGFtb25peC4yNCA8LSByYmluZChNZW5fQ2hhbW9uaXhfUXVhbGksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBNZW5fQ2hhbW9uaXhfU2VtaWZzLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgTWVuX0NoYW1vbml4X0ZpbmFscykNCk1lbi5KdWx5X0NoYW1vbml4LjI0ICU+JSBwcmludChuPWxlbmd0aChNZW4uSnVseV9DaGFtb25peC4yNCROYW1lKSkNCg0Kb3B0aW9ucyhnYXJnbGVfb2F1dGhfZW1haWwgPSAidmlsbGF0b3JvcGF6ZmpAZGF0YWFuYWx5c2lzbGFiLmNvbSIpDQpnczRfZGVhdXRoKCkNCmdzNF9hdXRoKCkNCnNoZWV0X3dyaXRlKGRhdGEgPSBNZW4uSnVseV9DaGFtb25peC4yNCwNCiAgICAgICAgICAgIHNzPSAiaHR0cHM6Ly9kb2NzLmdvb2dsZS5jb20vc3ByZWFkc2hlZXRzL2QvMUpoQnM3eWNlRVhVcm5uY1lEV2tXVDE2bktZMU1DeF9aVHB4Z09PVVJKNk0vZWRpdD91c3A9c2hhcmluZyIsIA0KICAgICAgICAgICAgc2hlZXQ9cGFzdGUoIk1lbi5KdWx5X0NoYW1vbml4LjI0IiwgIl8iLCBTeXMuRGF0ZSgpKSkNCg0KDQpgYGANCg0KIyMjIENvbnNvbGlkYWRvIGVuIGxhIFtIb2phIEdvb2dsZV0oaHR0cHM6Ly9kb2NzLmdvb2dsZS5jb20vc3ByZWFkc2hlZXRzL2QvMUpoQnM3eWNlRVhVcm5uY1lEV2tXVDE2bktZMU1DeF9aVHB4Z09PVVJKNk0vZWRpdD91c3A9c2hhcmluZykNCg0KDQoNCg0K