Aims and content

The present document includes the pre-processing steps to read the intensive longitudinal data collected with the Qualtrics platform (Qualtrics, Seattle, WA, USA) and prepare them from the analyses. The data were collected from a sample of full-time workers (mainly office workers) that responded to a preliminary questionnaire prelqs followed by a one- or two-week daily diary protocol diary.

Here, we remove all objects from the R global environment, and we set the system time zone.

# removing all objets from the workspace
rm(list=ls())

# setting system time zone to GMT (for consistent temporal synchronization)
Sys.setenv(tz="GMT")

The following R packages are used in this document (see References section):

# required packages
packages <- c("lubridate","ggplot2","gridExtra","plyr","labourR","data.table","magrittr")

# generate packages references
knitr::write_bib(c(.packages(), packages),"packagesProc.bib")

# # run to install missing packages
# xfun::pkg_attach2(packages, message = FALSE); rm(list=ls())


1. Data reading

First, we read preliminary questionnaire prelqs data exported from Qualtrics (available upon request to the main author).

# loading preliminary questionnaire dataset (skipping first two lines including unuseful information))
prelqs <- read.csv("DATI/WHLSM2021 - prelQS.csv", 
                   na.strings="")[3:nrow(read.csv("DATI/WHLSM2021 - prelQS.csv")),]

# removing 1 case with missing values to all items
prelqs <- prelqs[!is.na(prelqs$gender),]

# removing 1 case with no e-mail address (i.e., no identification code)
prelqs <- prelqs[!is.na(prelqs$RecipientEmail),]


Second, we read the diary datasets exported from Qualtrics as CSV files with numeric values (available upon request to the main author). A separate diary survey (resulting in a separate dataset) was used for afternoon _a, evening _e, and morning _m diaries, respectively. Moreover, a separate survey was used for Saturday morning (_m_sat), and surveys sometimes (i.e., in case of techical problems with the smartphones), they administered by sending anonymized links including an e-mail field: _mail.

# loading diary datasets
diary_a <- read.csv("DATI/WEEK40/WHLSM2021_DiaryAfternoon.csv",
                    na.strings="")[3:nrow(read.csv("DATI/WEEK40/WHLSM2021_DiaryAfternoon.csv")),] # diary_a = Afternoon (after work)
diary_e <- read.csv("DATI/WEEK40/WHLSM2021_DiaryEvening.csv",
                    na.strings="")[3:nrow(read.csv("DATI/WEEK40/WHLSM2021_DiaryEvening.csv")),] # diary_e = Evening (bedtime)
diary_m <- read.csv("DATI/WEEK40/WHLSM2021_DiaryMorning.csv", 
                    na.strings="")[3:nrow(read.csv("DATI/WEEK40/WHLSM2021_DiaryMorning.csv")),] # diary_m = Morning (before work)
diary_m_sat <- read.csv("DATI/WEEK40/WHLSM2021_DiaryMorning_sat.csv",
                    na.strings="")[3:nrow(read.csv("DATI/WEEK40/WHLSM2021_DiaryMorning_sat.csv")),] # diary_m_sat = Saturday Morning

# loading diary datasets with e-mail field (used in cases of technical problems)
diary_m_mail <- read.csv("DATI/WEEK40/WHLSM2021_DiaryMorning_mail.csv",
                         na.strings="")[3:nrow(read.csv("DATI/WEEK40/WHLSM2021_DiaryMorning_mail.csv")),]
diary_a_mail <- read.csv("DATI/WEEK40/WHLSM2021_DiaryAfternoon_mail.csv",
                         na.strings="")[3:nrow(read.csv("DATI/WEEK40/WHLSM2021_DiaryAfternoon_mail.csv")),]
diary_e_mail <- read.csv("DATI/WEEK40/WHLSM2021_DiaryEvening_mail.csv",
                         na.strings="")[3:nrow(read.csv("DATI/WEEK40/WHLSM2021_DiaryEvening_mail.csv")),]
diary_m_sat_mail <- read.csv("DATI/WEEK40/WHLSM2021_DiaryMorning_sat_mail.csv",
                             na.strings="")[3:nrow(read.csv("DATI/WEEK40/WHLSM2021_DiaryMorning_sat_mail.csv")),]


2. Data recoding

Second, we recode the two datasets by removing unuseful columns, by re-setting variable labels and classes, by renaming relevant columns, and by merging the diary datasets.

2.1. Preliminary questionnaire

Here, we remove the unuseful columns, and we rename and sort the relevant columns of the prelqs dataset.

# removing unuseful columns
prelqs[,c("Status","IPAddress","Progress","Duration..in.seconds.","Finished","RecordedDate","ResponseId",
          "RecipientLastName","RecipientFirstName","LocationLatitude","LocationLongitude",
          "DistributionChannel","UserLanguage","consent")] <- NULL

# renaming variables
colnames(prelqs)[1:4] <- c("start","end","ID","recruiter.ID") # participant's identifier (e-mail)
colnames(prelqs)[1:which(colnames(prelqs)=="children_1")] <- # removing question numbers from column names
  gsub("_4","",gsub("_1","",colnames(prelqs)[1:which(colnames(prelqs)=="children_1")]))
colnames(prelqs)[which(substr(colnames(prelqs),1,2)=="EX")] <- paste("EX",1:7,sep="_") # recoding question numbers for EX scale


Then, we change the classes of the relevant variables by converting dates as POSIXct (the R format for dates and times), categorical variables as factor, and quantitative variables as integer or numeric.

# time (POSIXct variables): start, end
prelqs$start <- as.POSIXct(prelqs$start)
prelqs$end <- as.POSIXct(prelqs$end)

# integer: age, WHLSM, WA, OC, WE, EX, WL, WFC, OWC, TS, NA
prelqs[,c(which(colnames(prelqs)=="age"),which(colnames(prelqs)=="WHLSM_1"):which(colnames(prelqs)=="NA_4"))] <-
  lapply(prelqs[,c(which(colnames(prelqs)=="age"),which(colnames(prelqs)=="WHLSM_1"):which(colnames(prelqs)=="NA_4"))],as.integer)

# numeric: weekHours, weekHours_remote
colnames(prelqs)[which(substr(colnames(prelqs),1,4)=="week")] <- c("weekHours","weekHours_remote")
prelqs[,c("weight","height","weekHours","weekHours_remote")] <-
  lapply(prelqs[,c("weight","height","weekHours","weekHours_remote")],as.numeric)

# factors: all other variables
prelqs[,c("recruiter.ID","gender","edu","mStatus","home","children","smoker","drugs_1","drugs_2","drugs_3",
          "disfunctions_1","disfunctions_2","position","sector")] <-
  lapply(prelqs[,c("recruiter.ID","gender","edu","mStatus","home","children","smoker","drugs_1","drugs_2","drugs_3",
                   "disfunctions_1","disfunctions_2","position","sector")],as.factor)


We also recode the levels and values of sociodemographic variables as we preregistered (see preregistration here).

# gender: F, M, (Other)
prelqs$gender <- as.factor(gsub("1","M",gsub("2","F",gsub("3","Other",prelqs$gender))))
if(nlevels(prelqs$gender)==2){ cat("Recoding as M/F since nobody chose gender='Other'") 
  prelqs$gender <- factor(prelqs$gender,levels=c("F","M")) }
## Recoding as M/F since nobody chose gender='Other'
# education: highschool or lower vs. university or higher
prelqs$edu <- as.factor(gsub("1","highschool-",gsub("2","highschool-",gsub("3","university+",prelqs$edu))))

# children: yes/no
prelqs[prelqs$children!=0,"children"] <- 1
prelqs$children <- as.factor(gsub("0","No",gsub("1","Yes",prelqs$children))) # having a children

# home situation: alone, partner, children, parents, others
prelqs$home <- gsub("1","partner",gsub("2","parents",gsub("3","children",gsub("4","alone",gsub("5","others",prelqs$home)))))
prelqs$home <- factor(gsub("partner,alone","partner", # partner and alone = partner
                           gsub("partner,others","partner", # partner and others = partner
                                gsub("partner,children","children", # if children = children
                                     gsub("alone,others","others", # alone and others = others
                                          gsub("partner,parents","partner",prelqs$home))))), # partner and parents = partner
                      levels=c("alone","partner","children","parents","others")) 

# children in the household: yes/no
prelqs$home_child <- as.factor(gsub("alone","No", # 
                                   gsub("partner","No",
                                        gsub("children","Yes",
                                             gsub("parents","No",
                                                  gsub("others","No",prelqs$home))))))

# marital status: single, partner, divorced, widowed
prelqs$mStatus <- factor(gsub("1","single",gsub("2","partner",gsub("3","divorced",gsub("4","widowed",prelqs$mStatus)))),
                         levels=c("single","partner","divorced","widowed"))

# having a partner
prelqs$partner <- as.factor(gsub("single","No",
                                gsub("partner","Yes",
                                     gsub("divorced","No",
                                          gsub("widowed","No",prelqs$mStatus))))) 

# living with partner
prelqs$home_partner <- as.factor(gsub("alone","No", # living with partner
                                     gsub("partner","Yes",
                                          gsub("children","No",
                                               gsub("parents","No",
                                                    gsub("others","No",prelqs$home))))))

# smoking status: Yes/No
prelqs$smoker <- factor(gsub("1","Yes",gsub("2","Quit_less",gsub("3","Quit_more",gsub("4","No",prelqs$smoker)))),
                        levels=c("No","Yes","Quit_less","Quit_more"))
prelqs$smoker <- as.factor(gsub("Quit_less","Yes",gsub("Quit_more","No",prelqs$smoker)))

# drugs/medications
colnames(prelqs)[which(substr(colnames(prelqs),1,5)=="drugs")] <- c("bp_drugs","horm_drugs","psy_drugs") # drugs/medications
prelqs$bp_drugs <- as.factor(gsub("1","Yes",gsub("2","No",prelqs$bp_drugs)))
prelqs$horm_drugs <- as.factor(gsub("1","Yes",gsub("2","No",prelqs$horm_drugs)))
prelqs$psy_drugs <- as.factor(gsub("1","Yes",gsub("2","No",prelqs$psy_drugs)))

# cardiovascular and sleep dysfunctions
colnames(prelqs)[which(substr(colnames(prelqs),1,5)=="disfu")] <- c("cv_dysf","sleep_dysf")
prelqs$cv_dysf <- as.factor(gsub("1","Yes",gsub("2","No",prelqs$cv_dysf)))
prelqs$sleep_dysf <- as.factor(gsub("1","Yes",gsub("2","No",prelqs$sleep_dysf)))

# job position: employee or project vs. manager or self-employed/employer
prelqs$position <- factor(gsub("1","Manager/Employers",
                               gsub("2","Employee",
                                    gsub("3","Manager/Employers",
                                         gsub("4","Project",
                                              prelqs$position)))),
                          levels=c("Employee","Manager/Employers","Project"))

# job sector: public vs. private
prelqs$sector <- as.factor(gsub("1","Public",gsub("2","Private",prelqs$sector)))

# remotePlace (open-ended question -> making it categorical)
prelqs$remotePlace <- factor(gsub("casa","home",
                                  gsub("acasa","casa",
                                       gsub("dacasa","casa",
                                            gsub("acasa/inco-wo","casa",
                                                 gsub("studioausl","studio",
                                                      gsub("ufficio","studio",
                                                           gsub("ospedale","studio",
                                                                gsub("officina","studio",
                                                                     gsub("instudioinvideocall","studio",
                                                                          gsub("nessuno","0",
                                                                               gsub("nessuni","0",
                                            gsub("\\.","",gsub(" ","",tolower(prelqs$remotePlace)))))))))))))),
                             levels=c("0","home","studio"))

# from height and weight to BMI
prelqs[prelqs$height<3,"height"] <- prelqs[prelqs$height<3,"height"]*100 # correcting heights reported in meters
prelqs$BMI <- prelqs$weight/(prelqs$height/100)^2 # BMI = kg/m^2
prelqs <- prelqs[,c(1:which(colnames(prelqs)=="age"), # removing height and weight
                    ncol(prelqs),which(colnames(prelqs)=="edu"):(ncol(prelqs)-1))]


2.1.1. Recoding jobs

Here, the job.recode() function is used to recode the open-ended job item responses by using the ISCO-08 classification of occupations (level 2) (Ganzeboom, 2010). The function is based on the labouR package integrated with some manual recoding. The open-ended responses are then removed for privacy reasons.

job.recode()

job.recode <- function(data){ require(labourR); require(data.table); require(magrittr)

  # creating corpus data
  corpus <- data.table(ID=data$ID,text=data$job,edu=data$edu,pos=data$position,lang="it")
  languages <- unique(corpus$language) # language classes
  
  # first screening based on the labourR::classify_occupation() function
  suggestions <- classify_occupation(corpus=corpus,id_col="ID",text_col="text",lang="it",isco_level=2,num_leaves=10)
  corpus <- plyr::join(corpus,suggestions,by="ID",type="left")
  
  # adjusting automatic classification based on manual screening
  corpus[corpus$text%in%c("Responsabile sistemi informativi",
                          "Responsabile di un piccolo museo e operatrice museale e teatrale nelle scuole"),
         "preferredLabel"] <- 
    "Legal, social and cultural professionals"
  corpus[corpus$text%in%c("Funzionario Tecnico pubblica amministrazione "),
         "preferredLabel"] <- 
    "Legal, social and cultural professionals"
  corpus[corpus$text%in%c("Banca - Responsabile Organizzazione",
                          "addetta amministrazione e amministratore di azienda in proprio",
                          "Commercialista"),
         "preferredLabel"] <- 
    "Business and administration professionals"
  corpus[corpus$text%in%c("Lavoro nella segreteria di una Scuola Secondaria di Primo Grado come amministrativa. Mi occupo di questioni burocratiche e organizzative, gestisco soprattutto circolari e domande di iscrizione, nulla osta, ecc. Al momento gestisco anche il controllo dei Green Pass e le varie procedure da seguire.",
                          "Attività amministrativa di ufficio e front Office ",
                          "impiegata commerciale",
                          "impiegata nel settore amministrativo",
                          "Addetta back office presso agenzia di somministrazione"),
         "preferredLabel"] <- 
    "Business and administration associate professionals"
  corpus[corpus$text%in%c("direzione piccola azienda",
                          "Dirigente d'azienda ",
                          "Dirigente multinazionale digital marketing",
                          "Founder brand moda ",
                          "Imprenditore nel settore degli alberghi, gestione di un hotel di 45 camere più sala ristorante. Gestione di 9 dipendenti, rapporti con fornitori e piattaforme online. Gestione della contabilità. Occasionalmente docente presso Cescot Rimini, corsi di formazione.",
                          "Imprenditore di carpenteria metallica ",
                          "Imprenditrice"),
         "preferredLabel"] <- 
    "Chief executives, senior officials and legislators"
  corpus[corpus$text%in%c("attività di ricerca presso università",
                          "Dottorando di Ricerca",
                          "Dottorato di ricerca",
                          "Sono un geometra contabile. Il mio lavoro consiste nel tenere traccia di tutte le lavorazioni che svolgono gli operai sui vari cantieri, dopodiché realizzo dei report fotografici e contabili per il mio datore di lavoro. \nGli operai mi inviano giornalmente le foto per realizzare i report, dalle foto ne ricavo le misure delle lavorazioni eseguite. In base alle misurazioni effettuate eseguo dei disegni contabili e realizzo un computo metrico dove controllo i costi delle lavorazioni eseguite e verifico che non superiamo il budget prefissato.",
                          "Artigiano idraulico elettricista",
                          "Geometra libero professionista"),
         "preferredLabel"] <- 
    "Science and engineering associate professionals"
  corpus[corpus$text%in%c("radiologo, analisi immagini alla workstation (computer) alternato a periodi di studio al computer e esecuzione di ecografie ",
                          "riabilitazione della voce e della deglutizione per adulti operati delle corde vocali",
                          "Psicoterapeuta presso il mio studio privato. L'attività che svolgo si rivolge ad adulti e adolescenti, quasi esclusivamente in presenza, in sedute di circa 1 h ciascuna. A ciò si aggiunge il lavoro di fatturazione, formazione e aggiornamento, gestione pratica dello studio (Back office)",
                          "infermiere coordinatore",
                          "Psichiatra psicoterapeuta "),
         "preferredLabel"] <- 
    "Health professionals"
  corpus[corpus$text%in%c("Odontotecnico da libero professionista, ",
                          "operatore socio sanitario",
                          "Tutor ABA: mi occupo dell'applicazione di procedure e strategie comportamentali per bambini con Disturbo dello spettro autistico, all'interno di un rapporto 1:1.\nDurante la sessione di lavoro è necessario costruire una buona relazione con il bambino con spettro autistico e la sua famiglia; prendere a mano note per ciascuna sessione, inserire i dati in un database; osservare il comportamento del bambino e quindi applicare una strategia idonea; monitorare gli esiti dell’intervento da condividere successivamente con il supervisore ABA, nell'ottica di una riformulazione della programmazione da implementare per quel bambino.\n"),
         "preferredLabel"] <- 
    "Health associate professionals"
  corpus[corpus$text%in%c("Coordinatore unità operativa in un servizio di  integrazione socio sanitaria in salute mentale. Coordinatore unità operativa per soggetti svantaggiati e disabili nel cooperativismo. Consigliere CDA in Cooperativa. Cultore della materia in facoltà universitaria.",
                          "Psicologa infantile, Progettista sociale, Coordinatrice Centro Famiglie",
                          "Traduttrice, addetta stampa, content creator",
                          "project manager e consulente aziendale rispetto alla psicologia clinica, psicologia organizzazioni e psicologia emergeza"),
         "preferredLabel"] <- 
    "Legal, social and cultural professionals"
  corpus[corpus$text%in%c("Energy Back Office Specialist (Addetto al Billing Gas)",
                          "Solgo 2 lavori:\nLibera professione, svolgo attività di impresa nelle società con mio fratello nel campo architettura, immobiliare e turistico \nResponsabile ricerca e sviluppo (con orari flessibili) x un quartiere fieristico"),
         "preferredLabel"] <- 
    "Science and engineering professionals"
  corpus[corpus$text%in%c("Doposcuola ",
                          "Educatrice all'interno di una scuora superiore."),
         "preferredLabel"] <- 
    "Teaching professionals"
  corpus[corpus$text%in%c("TITOLARE DI IMPRESA DI PULIZIE"),
         "preferredLabel"] <- 
    "Personal service workers"
  corpus[corpus$text%in%c("Programmatore",
                          "Coach di E-Sports, alleno dei giocatori di videogiochi attraverso dei campioni professionistici"),
         "preferredLabel"] <- 
    "Information and communications technology professionals"
  
  # merging corpus with data
  corpus$ID <- as.factor(corpus$ID)
  data <- plyr::join(data,corpus[,c("ID","preferredLabel")],by="ID",type="left")
  
  # replacing original job with recoded job categories
  data$job <- as.factor(data$preferredLabel)
  data$preferredLabel <- NULL # removing preferredLabel
  data$ID <- as.factor(data$ID)
  
  # summarizing info
  cat("Recoded job variable into",nlevels(data$job),"categories:\n")
  print(summary(data[!is.na(data$job),"job"]))
  return(data) }

prelqs <- job.recode(prelqs)
## Recoded job variable into 22 categories:
##                      Administrative and commercial managers 
##                                                           2 
##                                                  Assemblers 
##                                                           1 
##         Business and administration associate professionals 
##                                                          21 
##                   Business and administration professionals 
##                                                          17 
##          Chief executives, senior officials and legislators 
##                                                           6 
##                                    Customer services clerks 
##                                                           2 
##                    Electrical and electronic trades workers 
##                                                           1 
##                             Handicraft and printing workers 
##                                                           1 
##                              Health associate professionals 
##                                                           3 
##                                        Health professionals 
##                                                           9 
##             Hospitality, retail and other services managers 
##                                                           4 
##     Information and communications technology professionals 
##                                                           5 
##                    Legal, social and cultural professionals 
##                                                          17 
## Legal, social, cultural and related associate professionals 
##                                                           1 
##                 Metal, machinery and related trades workers 
##                                                           2 
##                                    Personal service workers 
##                                                           3 
##                Production and specialised services managers 
##                                                           6 
##                                               Sales workers 
##                                                           2 
##             Science and engineering associate professionals 
##                                                          13 
##                       Science and engineering professionals 
##                                                          14 
##                      Stationary plant and machine operators 
##                                                           2 
##                                      Teaching professionals 
##                                                          17


2.1.2. recoding workTime

Then, we recode the workTime variable, which was measured with an open-ended question as well.

# all lower case letters
workTimes <- wt.min <- wt.max <- tolower(prelqs$workTime)

# categorizing work start time
wt.min[grep("6:",wt.min)] <- # ............. # 6/7 = starting between 6:00 AM and 7:59 AM
  wt.min[grep("6.",wt.min)] <-  
  wt.min[grep("7:",wt.min)] <- 
  wt.min[grep("7.",wt.min)] <- "6/7"
wt.min[grep("8:",wt.min)] <- # ............... # 8 = starting between 8:00 AM and 8:59 AM
  wt.min[grep("8.",wt.min)] <-  "8"
wt.min[grep("9:",wt.min)] <- # ............ # 9/10 = starting between 9:00 AM and 9:59 AM
  wt.min[grep("9.",wt.min)] <- 
  wt.min[grep("10:",wt.min)] <- 
  wt.min[grep("10.",wt.min)] <- "9/10"
wt.min[grep("15-",wt.min)] <- # ............. # PM = starting in the afternoon
  wt.min[grep("15.",wt.min)] <- 
  wt.min[grep("14.",wt.min)] <- "PM"

# categorizing work end time
wt.max[grep("19:",wt.max)] <- # ............. # 19/21 = ending between 7:00 PM and 6:59 PM
  wt.max[grep("19.",wt.max)] <- 
  wt.max[grep("-19",wt.max)] <- 
  wt.max[grep("- 19",wt.max)] <- 
  wt.max[grep("- 20",wt.max)] <- 
  wt.max[grep("- 21",wt.max)] <- "19/21" 
wt.max[grep("17:",wt.max)] <- # ............. # 17/18 = ending between 5:00 PM and 6:59 PM
  wt.max[grep("17.",wt.max)] <- 
  wt.max[grep("-17",wt.max)] <- 
  wt.max[grep("- 17",wt.max)] <- 
  wt.max[grep("18:",wt.max)] <- 
  wt.max[grep("18.",wt.max)] <- 
  wt.max[grep("-18",wt.max)] <- 
  wt.max[grep("- 18",wt.max)] <- "17/18" 
wt.max[grep("15.",wt.max)] <-  #............. # 15/16 = ending between 3:00 PM and 4:59 PM
  wt.max[grep("15:",wt.max)] <- 
  wt.max[grep("-15",wt.max)] <- 
  wt.max[grep("16.",wt.max)] <- 
  wt.max[grep("16:",wt.max)] <- "15/16"
wt.max[grep("12:",wt.max)] <- # ............. # 12/14 = ending between noon and 2:59 PM
  wt.max[grep("12.",wt.max)] <- 
  wt.max[grep("13:",wt.max)] <- 
  wt.max[grep("13.",wt.max)] <- 
  wt.max[grep("_13",wt.max)] <-
  wt.max[grep("/13",wt.max)] <- 
  wt.max[grep("-13",wt.max)] <- 
  wt.max[grep("14:",wt.max)] <- 
  wt.max[grep("14.",wt.max)] <- 
  wt.max[grep("/14",wt.max)] <- 
  wt.max[grep("-2.",wt.max)] <- 
  wt.max[grep("- 02",wt.max)] <- "12/14" 

# joining start and end time
wt <- paste(wt.min,wt.max,sep="_")
wt[grep("PM_",wt)] <- "PM only" # correcting some cases and merging categories with few cases

# replacing workTime variable with recoded work times
prelqs$workTime <- as.factor(wt)
summary(prelqs$workTime)
##  6/7_12/14  6/7_15/16  6/7_17/18  6/7_19/21    8_12/14    8_15/16    8_17/18 
##          2         11         29          4         13          3         38 
##    8_19/21 9/10_12/14 9/10_15/16 9/10_17/18 9/10_19/21    PM only 
##         15          5          3          5         18          3


2.2. Daily diaries

Here, we merge and recode the daily diary datasets.

2.2.1. Data cleaning

Here, we filter trial responses, we remove unuseful columns, and we rename and sort the relevant columns of the diary datasets.

# filtering trial/preview responses
diary_m <- diary_m[diary_m$DistributionChannel=="email",]
diary_m_sat <- diary_m_sat[diary_m_sat$DistributionChannel=="email",]
diary_a <- diary_a[diary_a$DistributionChannel=="email",]
diary_e <- diary_e[diary_e$DistributionChannel=="email",]

# removing unuseful variables
toRemove <- c("Duration..in.seconds.","Status","IPAddress","Progress","Finished","RecordedDate","ResponseId",
              "RecipientLastName","RecipientFirstName","LocationLatitude","LocationLongitude","DistributionChannel","UserLanguage")
diary_m[,toRemove] <- diary_a[,toRemove] <- diary_e[,toRemove] <- diary_m_mail[,toRemove] <-
  diary_a_mail[,toRemove] <- diary_m_sat[,toRemove] <- diary_m_sat_mail[,toRemove] <- diary_e_mail[,toRemove] <- NULL


2.2.2. Direct e-mails

Then, we merge each diary dataset with the corresponding data obtained by directly e-mailing participants (i.e., in case of technical/schedule problems).

# joining 'ordinary' datasets with datasets e-mailed datasets
diary_a_mail$RecipientEmail <- diary_a_mail$Q22_1 # afternoon
diary_a_mail$Q22_1 <- NULL
diary_a <- rbind(diary_a,diary_a_mail)
diary_e_mail$RecipientEmail <- diary_e_mail$e.mail_1 # evening
diary_e_mail$e.mail_1 <- NULL
diary_e <- rbind(diary_e,diary_e_mail)
diary_m_mail$RecipientEmail <- diary_m_mail$Q30_1 # morning
diary_m_mail$Q30_1 <- NULL
colnames(diary_m) <- gsub("\\.","",colnames(diary_m))
diary_m <- rbind(diary_m,diary_m_mail)
diary_m_sat_mail$RecipientEmail <- diary_m_sat_mail$Q11_1 # Saturday morning
diary_m_sat_mail$Q11_1 <- NULL
diary_m_sat_mail <- diary_m_sat_mail[!is.na(diary_m_sat_mail$RecipientEmail),] # removing trial entries
diary_m_sat <- rbind(diary_m_sat,diary_m_sat_mail)
diary_m_sat$dayOff_today <- diary_m_sat$AWL_1 <- diary_m_sat$AWL_2 <- diary_m_sat$AWL_3 <- NA # no AWL values on Saturday
diary_m <- rbind(diary_m,diary_m_sat)

# sorting and renaming columns
diary_m <- diary_m[,c(1:which(colnames(diary_m)=="ExternalReference"),which(colnames(diary_m)=="dayOff_today"),
                      which(colnames(diary_m)=="BP1_1"):which(colnames(diary_m)=="dayOff_yesterday"),
                      which(colnames(diary_m)=="AWL_1"):ncol(diary_m))]
colnames(diary_m)[1:9] <- colnames(diary_a)[1:9] <- colnames(diary_e)[1:9] <- c("start","end","ID","recruiter.ID","dayOff_today",
                                                                                "SBP1","DBP1","SBP2","DBP2")
colnames(diary_a)[5] <- colnames(diary_e)[5] <- "dayOff" # differentiating afternoon/evening from morning dayOff values 
colnames(diary_a) <- gsub("WHLSM1","WHLSM",gsub("WHLSM2","WHLSM",colnames(diary_a)))


2.2.3. Merging diary data

Here, we merge the four datasets into a single long-form diary dataset. The diaryType variable is created for discriminating among Morning, Afternoon, and Evening diaries.

# adding diaryType column
diary_m$diaryType <- "M" # Morning diary
diary_a$diaryType <- "A" # Afternoon diary
diary_e$diaryType <- "E" # Evening diary

# Merging diary data (LONG dataset)
diary <- plyr::join(plyr::join(diary_m,diary_a,type="full"),diary_e,type="full")
cat("sanity check:",nrow(diary) == nrow(diary_m) + nrow(diary_a) + nrow(diary_e))
## sanity check: TRUE


2.2.4. Data recoding

Then, we rename diary variables, we change the classes of the relevant variables, and we recode the levels of categorical (factor) variables consistently what we preregistered (see preregistration here).

# renaming columns
colnames(diary)[which(colnames(diary)=="lateWorkHours_1")] <- "lateWorkHours" # renaming column
colnames(diary)[which(colnames(diary)=="workHours_1")] <- "workHours" # renaming column
colnames(diary)[which(colnames(diary)=="waketime_16")] <- "wakeTime" # renaming column
colnames(diary) <- gsub("_","",colnames(diary))
colnames(diary)[grepl("SQ",colnames(diary))] <- paste("SQ",1:4,sep="")
colnames(diary)[which(colnames(diary)=="WL4")] <- "WL3"
colnames(diary)[grepl("WHLSM",colnames(diary))] <- paste("WHLSM",1:6,sep="")
colnames(diary)[which(colnames(diary)=="EE5")] <- "EE4"
colnames(diary)[grepl("R.det",colnames(diary))] <- paste("R.det",1:3,sep="")
colnames(diary)[grepl("R.rel",colnames(diary))] <- paste("R.rel",1:3,sep="")
colnames(diary)[grepl("R.mas",colnames(diary))] <- paste("R.mas",1:3,sep="")

# time (POSIXct variables)
diary$start <- as.POSIXct(diary$start)
diary$end <- as.POSIXct(diary$end)

# numeric
nums <- c(which(colnames(diary)=="SBP1"):which(colnames(diary)=="DBP2"),
          which(colnames(diary)=="AWL1"):which(colnames(diary)=="AWL3"),
          which(colnames(diary)=="OC1"):which(colnames(diary)=="SQ4"),
          which(colnames(diary)=="WL1"):which(colnames(diary)=="R.mas3"),
          which(colnames(diary)=="workHours"))
diary[,nums] <- lapply(diary[,nums],as.numeric)

# recording location
diary$where <- factor(gsub("1","workplace",
                           gsub("2","home",
                                gsub("4","other",diary$where))),levels=c("home","workplace","other"))
# dailyHassles
diary$dailyHassles <- as.factor(gsub("2","No",gsub("1","Yes",diary$dailyHassles)))

# diary type
diary$diaryType <- factor(diary$diaryType,levels=c("M","A","E"))

# dayOff_today & dayOff_yesterday as factor (recoding levels as FALSE = no, TRUE = yes)
diary$dayOff <- as.logical(as.numeric(diary$dayOff)-1)
diary$dayOfftoday <- as.logical(as.numeric(diary$dayOfftoday)-1)
diary$dayOffyesterday <- as.logical(as.numeric(diary$dayOffyesterday)-1)

# teleWork
diary$teleWork <- factor(gsub("1","teleWork",
                              gsub("2","office",
                                   gsub("3","both",
                                        gsub("4","dayOff",diary$teleWork)))),levels=c("office","teleWork","both","dayOff"))
# confounders
diary$confounders <- gsub("1","coffee",
                          gsub("2","smoke",
                               gsub("4","sport",
                                    gsub("5","meal",
                                         gsub("6","0",diary$confounders)))))


2.2.5. Recoding confounders

The confounders variable is processed by using the checklist_sep function in order to separate the different confounding factors.

checklist_sep()

checklist_sep <- function(data=NULL,varName=NULL,sep=",",nOptions=4,
                          labels=c("coffee","smoke","sport","meal"),return.data=FALSE){
  
  checklist <- data.frame(checklist_var=data[,varName])
  checklist$checklist_var <- as.character(checklist$checklist_var)
  for(i in 1:nOptions){ checklist$new.col <- NA
    if(!is.null(labels)){ colnames(checklist)[i+1] <- labels[i] } else { colnames(checklist)[i+1] <- paste("item",i,sep="") }}
  
  for(i in 1:nrow(checklist)){
    if(!is.na(checklist[i,1])){ checklist[i,2:ncol(checklist)] <- 0
      if(checklist[i,1]!="0"){ selected <- unlist(strsplit(checklist[i,1],sep))
        for(k in 1:length(selected)){ checklist[i,selected[k]] <- 1 }}}}
  checklist[,2:(nOptions+1)] <- lapply(checklist[,2:(nOptions+1)],as.factor)
  
  # adding new variables to data (excluding the category without confounders)
  data <- cbind(data[,1:which(colnames(data)==varName)],checklist[,2:(ncol(checklist)-1)],
                data[,(which(colnames(data)==varName)+1):ncol(data)])
  
  # recoding the original variable as logical (TRUE=any confounder category, FALSE=none)
  data$originalVar <- data[,varName]
  data[,varName] <- NA
  data[!is.na(data$originalVar),varName] <- TRUE
  data[!is.na(data$originalVar) & data$originalVar=="0",varName] <- FALSE
  data$originalVar <- NULL
  
  # printing summary
  print(summary(na.omit(checklist[,1:5])))
  
  # printing percentages
  out <- paste("\n\nPercentage of",varName,"over total number of occasions with non-missing values:\n")
  for(SC in labels){ colnames(checklist)[which(colnames(checklist)==SC)] <- "Var"
    out <- paste(out,"- ",SC,": ",
                 round(100*nrow(checklist[!is.na(checklist$checklist_var) & checklist$Var == "1",])
                       /nrow(checklist[!is.na(checklist$checklist_var),]),2),
                                  "%\n",sep="")
    colnames(checklist)[which(colnames(checklist)=="Var")] <- SC }
  cat(out)
  if(return.data==TRUE){return(data)}}

# number and percentages for each confounder
diary <- checklist_sep(data=diary,varName="confounders",return.data = TRUE)
##  checklist_var      coffee   smoke    sport    meal    
##  Length:2940        0:2700   0:2748   0:2843   0:2740  
##  Class :character   1: 240   1: 192   1:  97   1: 200  
##  Mode  :character                                      
## 
## 
## Percentage of confounders over total number of occasions with non-missing values:
## - coffee: 8.16%
## - smoke: 6.53%
## - sport: 3.3%
## - meal: 6.8%
# overall No. of cases with one or more confounders (604 TRUE, 2336 FALSE, 153 NA)
summary(diary$confounders)
##    Mode   FALSE    TRUE    NA's 
## logical    2336     604     153


2.2.6. wakeTime recoding

Then, we recode the wakeTime variable, which was measured with an open-ended question.

# recoding wakeTime
wakeTimes <- diary$wakeTime
wakeTimes <- gsub("\\;",":",gsub("\\.","\\:",gsub("\\,","\\.",gsub("e",":",gsub(" ","",wakeTimes)))))
wakeTimes[!is.na(wakeTimes) & nchar(wakeTimes)==1] <- paste("0",wakeTimes[!is.na(wakeTimes) & nchar(wakeTimes)==1],":00",sep="")
wakeTimes[!is.na(wakeTimes) & nchar(wakeTimes)==2] <- paste(wakeTimes[!is.na(wakeTimes) & nchar(wakeTimes)==2],":00",sep="")
wakeTimes[!is.na(diary$wakeTime) & wakeTimes=="0615"] <- "05:15"
wakeTimes[!is.na(diary$wakeTime) & wakeTimes=="0800"] <- "08:00"
wakeTimes[!is.na(diary$wakeTime) & wakeTimes=="0830"] <- "08:30"
wakeTimes[!is.na(diary$wakeTime) & wakeTimes=="0700"] <- "07:00"
wakeTimes[!is.na(wakeTimes) & nchar(wakeTimes)==4] <- paste("0",wakeTimes[!is.na(wakeTimes) & nchar(wakeTimes)==4],sep="")
wakeTimes[!is.na(wakeTimes) & wakeTimes=="630"] <- "06:30"

# wakeTime as POSIXct & hhFromAwake
library(lubridate)
## 
## Attaching package: 'lubridate'
## The following objects are masked from 'package:data.table':
## 
##     hour, isoweek, mday, minute, month, quarter, second, wday, week,
##     yday, year
## The following objects are masked from 'package:base':
## 
##     date, intersect, setdiff, union
diary$wakeTime <- as.POSIXct(paste(substr(Sys.time(),1,10),wakeTimes),format="%Y-%m-%d %H:%M",tz="GMT")
diary$hhFromAwake <- as.numeric(difftime(as.POSIXct(paste(substr(Sys.time(),1,10),substr(diary$start,12,16)),
                                                    format="%Y-%m-%d %H:%M",tz="GMT"),diary$wakeTime,units="hours"))

# showing some example
head(diary[!is.na(diary$wakeTime),c("wakeTime","start","hhFromAwake")])


2.3. Data anonymization

Third, participants’ ID (currently their e-mail addresses) are anonymized (i.e., replaced with alphanumeric code from S001 to Snnn).

Before anonymizing ID values, we filter cases only included in one but not in the other dataset.

# preparing prelqs data
prelqs$ID <- tolower(prelqs$ID) # all e-mails in lower capital
prelqs.IDs <- levels(as.factor(prelqs$ID)) # saving original IDs

# excluding pre-pilot diary data with the main author
diary <- diary[!(grepl("ini.job",diary$ID)|grepl("varo@st",diary$ID)|grepl("tti@stu",diary$ID)|grepl("tti@un",diary$ID)),]
diary$ID <- tolower(diary$ID) # all e-mails in lower capital

# correcting wrongly reported e-mail addresses in diary data
diary$ID <- gsub("tierno@studio.unibo.it","tierno@libero.it",diary$ID) 
diary$ID <- gsub("uzziell2","uzziello",diary$ID)
diary$ID <- gsub("uzziello@hotmail","uzziello@unibo",diary$ID)
diary$ID <- gsub("riarosa.m","rosa.m",gsub("o@auslromagna.it","o@gmail.com",diary$ID))
diary$ID <- gsub("o@auslcesena.it","o@gmail.com",diary$ID)
diary$ID <- gsub("gmsil","gmail",diary$ID)
diary$ID <- gsub("gmail.con","gmail.com",diary$ID)
diary$ID <- gsub("lli.robo@","lli.robi@",diary$ID)
diary$ID <- gsub("officia","officina",diary$ID)
diary$ID <- gsub("@liberi","@libero",gsub("@lidero","@libero",gsub("@llibro","@libero",diary$ID)))
diary$ID <- gsub("fcibien","f.cibien",gsub("klarco.com","klarco.it",diary$ID))
IDs <- levels(as.factor(diary$ID))

# sanity checks
cat(length(IDs),"participants in diary data,",length(prelqs.IDs),"in prelqs data\n",
    length(IDs[!(IDs%in%prelqs.IDs)]),"cases in diary but not in prelqs\n",
    length(prelqs.IDs[!(prelqs.IDs%in%IDs)]),"cases in prelqs but not in diary")
## 151 participants in diary data, 149 in prelqs data
##  4 cases in diary but not in prelqs
##  2 cases in prelqs but not in diary
# removing cases only included prelqs but not in diary
memory <- prelqs
prelqs <- prelqs[prelqs$ID %in% IDs,]
prelqs.IDs <- levels(as.factor(prelqs$ID))
cat("Removed",nrow(memory)-nrow(prelqs),"participants only included in prelqs data")
## Removed 2 participants only included in prelqs data
# removing cases only included in diary but not in prelqs
memory <- diary
diary <- diary[diary$ID %in% prelqs.IDs,]
IDs <- levels(as.factor(diary$ID))
cat("Removed",nlevels(as.factor(memory$ID))-length(IDs),"participants,",nrow(memory)-nrow(diary),
    "observations only included in diary data")
## Removed 4 participants, 4 observations only included in diary data
# sanity checks
cat(length(IDs),"participants in diary data,",length(prelqs.IDs),"in prelqs data\n",
    length(IDs[!(IDs%in%prelqs.IDs)]),"cases in diary but not in prelqs\n",
    length(prelqs.IDs[!(prelqs.IDs%in%IDs)]),"cases in prelqs but not in diary")
## 147 participants in diary data, 147 in prelqs data
##  0 cases in diary but not in prelqs
##  0 cases in prelqs but not in diary


We also correct a number of issues with diary time points due to participants answering to the wrong link.

# correcting surveys taken at wrong time points
diary[substr(diary$ID,15,27)=="rno@gmail.com" & 
        as.character(diary$start) %in% c("2021-10-26 21:26:43","2021-11-02 21:21:51"),
      "diaryType"] <- "E" # participant who responded twice to Afternoon diary in Evening time (keeping only BP values)
diary[substr(diary$ID,15,27)=="rno@gmail.com" & 
        as.character(diary$start) %in% c("2021-10-26 21:26:43","2021-11-02 21:21:51"),
      which(colnames(diary)=="WL1"):which(colnames(diary)=="WE3")] <- NA
diary[substr(diary$ID,8,13)=="isa.ma" & # participants that responded to a link open on the previous day
        !is.na(diary$WHLSM3) & as.character(diary$start)=="2022-01-25 10:45:00",
      "start"] <- as.character(as.POSIXct(diary[substr(diary$ID,8,13)=="isa.ma" & !is.na(diary$WHLSM3) & 
                                     as.character(diary$start)=="2022-01-25 10:45:00","end"]) -
  mean(as.numeric(difftime(diary[substr(diary$ID,8,13)=="isa.ma" & diary$start!="2022-01-25 10:45:00","end"],
                           diary[substr(diary$ID,8,13)=="isa.ma" & diary$start!="2022-01-25 10:45:00","start"],units="secs"))))
diary <- diary[!(substr(diary$ID,8,13)=="mo@mda" & diary$start%in%c("2022-01-25 16:39:22","2022-01-26 20:00:21")),] # double resp
diary[grepl("aia79",diary$ID) & as.character(diary$start)=="2022-03-10 07:25:32","diaryType"] <- 
  "M" # participant that responded to the Evening diary in Morning time (keeping only BP values and changing as Morning)
diary[grepl("aia79",diary$ID) & as.character(diary$start)=="2022-03-10 07:25:32",
      which(colnames(diary)=="EE1"):which(colnames(diary)=="workHours")] <- NA
diary <- # participant that responded twice to the Morning diary 
  diary[!(grepl("basso87",diary$ID) & as.character(diary$start)=="2022-03-07 19:53:47"),]

# correcting wrongly reported BP values
diary[substr(diary$ID,18,32)=="na.isasi.cnr.it" & as.character(diary$start)=="2021-11-25 19:17:27","SBP2"] <- 
  133 # reported as 88133


2.3.1. Preliminary questionnaire

Here, we anonymize prelqs ID values.

# replacing participants' e-mail with alphanumeric code (e.g., S001)
prelqs <- prelqs[order(prelqs$ID),] # sorting by ID
for(ID in prelqs.IDs){ id <- paste("S",which(prelqs.IDs==ID),sep="") 
  if(nchar(id)>2){ if(nchar(id)>3){ prelqs[prelqs$ID==ID,"ID"] <- id
  } else { prelqs[prelqs$ID==ID,"ID"] <- gsub("S","S0",id) }
    } else { prelqs[prelqs$ID==ID,"ID"] <- gsub("S","S00",id) }
  prelqs[prelqs$ID==ID,"ID"] <- ifelse(nchar(id)==3,id,paste("S0",which(prelqs.IDs==ID),sep=""))}
prelqs$ID <- as.factor(prelqs$ID)

# sanity check
head(levels(prelqs$ID))
## [1] "S001" "S002" "S003" "S004" "S005" "S006"
cat(nlevels(prelqs$ID),"participants,",nrow(prelqs),"observations") # 147, 147
## 147 participants, 147 observations


2.3.2. Daily diaries

Here, we anonymize diary ID values.

# replacing participants' e-mail with alphanumeric code (e.g., S001)
diary <- diary[order(diary$ID,diary$start),] # sorting by ID and start time
for(ID in IDs){ id <- paste("S",which(IDs==ID),sep="") # replacing participants' e-mail with alphanumeric code (e.g., S001)
  if(nchar(id)>2){ if(nchar(id)>3){ diary[diary$ID==ID,"ID"] <- id
  } else { diary[diary$ID==ID,"ID"] <- gsub("S","S0",id) }
    } else { diary[diary$ID==ID,"ID"] <- gsub("S","S00",id) }
  diary[diary$ID==ID,"ID"] <- ifelse(nchar(id)==3,id,paste("S0",which(IDs==ID),sep=""))}
diary$ID <- as.factor(diary$ID)

# sanity check
head(levels(diary$ID))
## [1] "S001" "S002" "S003" "S004" "S005" "S006"
cat(nlevels(diary$ID),"participants,",nrow(diary),"observations") # 147,3077
## 147 participants, 3075 observations


3. Data processing

As a final pre-processing step, we process diary data by including a day variable, by inspecting and recoding BP (blood pressure) and BMI (body mass index) data, by switching from the current long form to a wide form with one row per day, by merging the diary and the prelqs datasets, and by inspecting cases of incoherent/inconsistent responses in the considered variables.

3.1. Assessment day

First, we create the variable day indicating the day for participation (i.e., 1 = Monday, 2 = Tuesday, 3 = Wednesday, 4 = Thursday, 5 = Friday, 7 = Monday week II, 8 = Tuesday week II, 9 = Wednesday week II, 10 = Thursday week II, 11 = Friday week II). Note that this variable is recoded to be referred to the previous day in cases of Evening diaries filled after 00:00, and in all Morning diaries. We also remove 5 unexpected responses on day 6 and 12 (Saturday afternoon or Sunday).

# creating day
diary$day <- as.POSIXlt(diary$start)$wday

# adding 6 days to the second week
for(i in 2:nrow(diary)){
  if(diary[i,"ID"]==diary[i-1,"ID"] & diary[i,"day"] < diary[i-1,"day"]){ diary[i,"day"] <- diary[i,"day"] + 6 }}

# correcting evening days when start is after midnight
for(i in 1:nrow(diary)){
  if(diary[i,"diaryType"]=="E" & diary[i,"start"] < as.POSIXct(paste(substr(diary[i,"start"],1,10),"07:00:00"))){
    diary[i,"day"] <- diary[i,"day"] - 1 }}

# subtracting one day to all Morning diaries
diary[diary$diaryType=="M","day"] <- diary[diary$diaryType=="M","day"] - 1

# checking cases with unexpected values (6 or 12 = Morning on Mon, Evening/Afternoon on Sat)
table(diary$day)
## 
##   1   2   3   4   5   6   7   8   9  10  11  12 
## 387 410 398 378 371   4 232 232 230 221 211   1


# inspecting cases with unexpected values (6 or 12 = Morning on Mon, Evening/Afternoon on Sat)
cbind(wday=as.POSIXlt(diary[diary$day%in%c(6,12),"start"])$wday,
      diary[diary$day%in%c(6,12),c("ID","day","start","SBP1","WL1","EE1","SQ1","dayOff","dayOffyesterday")])


diary <- diary[!diary$day%in%c(6,12),] # removing 5 unexpected responses 

# sanity check
diary[,c("ID","start","diaryType","day")]


3.2. Blood pressure

Here, we visually inspect the distributions and temporal trends of blood pressure BP values against normative values and separately by the period of the day. Then, we process the signal, and we compute the aggregate BP values.

First, we prepare the data for the inspection and processing, by creading a long form dataset with one row for each BP recording.

# preparing dataset
diary_long <- data.frame(ID=rep(diary$ID,4),measure=c(rep("SBP1",nrow(diary)),rep("SBP2",nrow(diary)),
                                                      rep("DBP1",nrow(diary)),rep("DBP2",nrow(diary))),
                         BP=c(diary$SBP1,diary$SBP2,diary$DBP1,diary$DBP2),diaryType=rep(diary$diaryType,4))
diary_long$gender=plyr::join(diary_long,prelqs[,c("ID","gender")],type="left",by="ID")$gender
diary_long$cv_d=paste(plyr::join(diary_long,prelqs[,c("ID","cv_dysf")],type="left",by="ID")$cv_dysf,
                      plyr::join(diary_long,prelqs[,c("ID","bp_drugs")],type="left",by="ID")$bp_drugs,sep="_")


3.2.1. BP distributions

Here, we visualize BP distributions by plotting them against normative values.

vs. ESH/ESC Guidelines (2018)

First, we inspect the distribution of the observed BP measurements, accounting for the cut-off values recommended by the ESH/ESC Guidelines (2018). We can see that BP values are quite normally distributed (although with some cases showing bimodal distribution) and centered below the cut-offs for hypertension, with a small proportion of measurements (~ 9-11%) above the cut-offs. Higher SBP and DBP is showed in participants reporting suffering from cardiovascular dysfunctions and/or taking BP medications. Slightly higher systolic BP is reported by men compared to women, and during afternoon compared to morning and evening. Overall, the data look realistic, although diastolic BP looks bounded at 40 mmHg.

library(ggplot2); library(gridExtra)

# preparing dataset
diary_long <- data.frame(ID=rep(diary$ID,4),measure=c(rep("SBP1",nrow(diary)),rep("SBP2",nrow(diary)),
                                                      rep("DBP1",nrow(diary)),rep("DBP2",nrow(diary))),
                         BP=c(diary$SBP1,diary$SBP2,diary$DBP1,diary$DBP2),diaryType=rep(diary$diaryType,4))
diary_long$gender=plyr::join(diary_long,prelqs[,c("ID","gender")],type="left",by="ID")$gender
diary_long$cv_d=paste(plyr::join(diary_long,prelqs[,c("ID","cv_dysf")],type="left",by="ID")$cv_dysf,
                      plyr::join(diary_long,prelqs[,c("ID","bp_drugs")],type="left",by="ID")$bp_drugs,sep="_")

grid.arrange( # plotting sistolic and diastolic BP measurements
  ggplot(na.omit(diary_long),aes(x=measure,y=BP,group=measure)) + geom_point(color="gray",position=position_jitter()) + 
    geom_violin(alpha=0.4) + geom_boxplot(alpha=0.4,outlier.alpha=0) + ylab("Blood pressure (mmHg)") +
    geom_hline(yintercept = c(135,85),color="red",lty=2), # adding 2013 ESH/ESC Guidelines cut-offs for hypertension
  ggplot(na.omit(diary_long),aes(x=measure,y=BP,fill=gender)) + geom_point(color="gray",position=position_jitter()) + # by gender
    geom_violin(alpha=0.4) + geom_boxplot(alpha=0.4,outlier.alpha=0) + ylab("Blood pressure (mmHg)"),
  ggplot(na.omit(diary_long),aes(x=measure,y=BP,fill=cv_d)) + geom_point(color="gray",position=position_jitter()) + 
    geom_violin(alpha=0.4) + geom_boxplot(alpha=0.4,outlier.alpha=0) + ylab("Blood pressure (mmHg)"), # by cv_dysf & bp_drugs
  ggplot(na.omit(diary_long),aes(x=measure,y=BP,fill=diaryType)) + geom_point(color="gray",position=position_jitter()) + 
    geom_violin(alpha=0.4) + geom_boxplot(alpha=0.4,outlier.alpha=0) + ylab("Blood pressure (mmHg)"),nrow=2) # by time of day

# No. and % of SBP > 130 mmHG
ns <- nrow(diary_long[!is.na(diary_long$BP)&diary_long$measure%in%c("SBP1","SBP2")&diary_long$BP>135,])
nd <- nrow(diary_long[!is.na(diary_long$BP)&diary_long$measure%in%c("DBP1","DBP2")&diary_long$BP>85,])
cat(ns,"(",round(100*ns/nrow(diary_long[!is.na(diary_long$BP),]),1),"% ) SBP values above 130 mmHg\n",
    nd,"(",round(100*nd/nrow(diary_long[!is.na(diary_long$BP),]),1),"% ) DBP values above 85 mmHg\n")
## 1030 ( 8.7 % ) SBP values above 130 mmHg
##  1343 ( 11.4 % ) DBP values above 85 mmHg
# minumum diastolic BP
min(diary_long[diary_long$measure%in%c("DBP1","DBP2"),"BP"],na.rm=TRUE)
## [1] 40


vs. Weisser et al (2000)

Here, we compare the observed BP values with normative values from Weisser et al (2000), based on self-measured and office BP from 503 healthy Swiss adults. Red lines indicate the 35°, 58° and 76° percentile for office (solid) and self-measured (dotted) systolic BP, and the 50°, 67° and 78° percentile for diastolic BP, respectively. White dotted lines indicate the corresponding percentiles in the current sample. We can see that the observed values are quite similar to the normative ones, with greater similarities with home (~3-5 mmHg) compared to office normative values (~9 mmHg). It is confirmed that DBP is bounded at 40 mmHg, with a peak of cases corresponding to the lower limit.

par(mfrow=c(2,2))
for(BP in c("SBP1","DBP1","SBP2","DBP2")){ hist(diary[,BP],main=BP,xlab="BP (mmHg)",breaks=50,col="black")
  abline(v=quantile(diary[,BP],na.rm=TRUE,probs=c(.35,.58,.76)),col="gray",lwd=2,lty=2) # observed quantiles
  if(substr(BP,1,1)=="S"){ abline(v=c(114.3,124.1,132.6),col="red",lwd=2,lty=2) # normative quantiles (systolic, home)
    abline(v=c(120,130,140),col="red",lwd=3) # normative quantiles (systolic, office)
  } else {  abline(v=c(75.1,79.9,85.8),col="red",lwd=2,lty=2) # normative quantiles (diastolic, home)
    abline(v=c(80,85,90),col="red",lwd=3) }} # normative quantiles (diastolic, office)ì

vs. Asayama et al (2019)

Then, we compare BP values obtained from Morning and Evening measures with those reported by Asayama et al (2019) for morning and evening BP self-measured by 308 hypertensive patients. Red lines indicate normative mean ± 2 SD, whereas gray dotted lines indicate the observed mean +/- 2 SD from the current sample. Again, data look ‘realistic’.

par(mfrow=c(2,2))
for(BP in c("SBP1","SBP2","DBP1","DBP2")){ hist(diary[,BP],main=BP,xlab="BP (mmHg)",breaks=50,col="black")
  abline(v=c(mean(diary[,BP],na.rm=TRUE),mean(diary[,BP],na.rm=TRUE)-2*sd(diary[,BP],na.rm=TRUE),
             mean(diary[,BP],na.rm=TRUE)+2*sd(diary[,BP],na.rm=TRUE)),col="gray",lwd=2,lty=2)
  if(substr(BP,1,1)=="S"){ abline(v=c(128.0,128.0+9.4*2,128.0-9.4*2),col="red",lwd=2) 
  } else {  abline(v=c(70.5,70.5+9.7*2,70.5-9.7*2),col="red",lwd=2) }} # normative mean +/- sd (diastolic)


3.2.2. BP by day time

Here, we visualize the distribution of Systolic BP values in Morning (M), Afternoon (A) and Evening (E) recordings, while also showing individual patterns of change. It is hard to determinate the prevalence of an increasing or decreasing pattern for both variables, although most cases seem to increase from Morning to Afternoon and decrease from Afternoon to Evening.

# plotting SBP
diary$IDday <- as.factor(paste(diary$ID,diary$day,sep="_")) # adding ID x day factor
grid.arrange(ggplot(data=diary,aes(x=diaryType,y=SBP1)) + geom_line(aes(group=IDday,col=IDday)) + geom_violin(alpha=.4) +
               geom_boxplot(alpha=0.5,width=0.3,outlier.alpha=0) + theme(legend.position="none"),
             ggplot(data=diary,aes(x=diaryType,y=SBP2)) + geom_line(aes(group=IDday,col=IDday)) + geom_violin(alpha=.4) +
               geom_boxplot(fill=rgb(1,1,1,alpha=.4),width=0.3,outlier.alpha=0) + theme(legend.position="none"),nrow=1)

# plotting DBP
grid.arrange(ggplot(data=diary,aes(x=diaryType,y=DBP1)) + geom_line(aes(group=IDday,col=IDday)) + geom_violin(alpha=.4) +
               geom_boxplot(fill=rgb(1,1,1,alpha=.4),width=0.3) + ggtitle("Diastolic BP 1") + theme(legend.position="none"),
             ggplot(data=diary,aes(x=diaryType,y=DBP2)) + geom_line(aes(group=IDday,col=IDday)) + geom_violin(alpha=.4) +
               geom_boxplot(fill=rgb(1,1,1,alpha=.4),width=0.3) + ggtitle("Diastolic BP 2") + theme(legend.position="none"),nrow=1)


3.2.3. BP trajectories

Then, we use the plotBP function to visualize daily fluctuations in BP values. For each recording, the first and second entered value are showed in light and dark blue, respectively. The red triangles show cases in which the second measurement was 10 mmHg higher or lower than the second one, whereas the blue dotted line indicates the ESH/ESC Guidelines (2018) cut-off for hypertension. For both systolic and diastolic BP time series, we flag problematic cases based on the visual inspection of steep BP increases/decreases compared to the others values from that participant.

plotBP()

plotBP <- function(data=NULL,BP="S",ncol=3,flagged=NA,what=NA,meanVal=NA){ require(ggplot2)
  
  # creating TIME by joining day and diaryType
  data$TIMElab <- paste(data$day,data$diaryType,sep="")
  data$TIME <- as.numeric(gsub("M",".0",gsub("A",".33",gsub("E",".66",data$TIMElab))))
  
  # setting graphic parameters
  cols <- colnames(data)[substr(colnames(data),1,3)==paste(BP,"BP",sep="")] # columns to be plotted
  maxScore <- max(data[,cols],na.rm=TRUE)
  data$disc <- abs(data[,cols[1]]-data[,cols[2]])
  data$disc10 <- FALSE
  data[!is.na(data$disc) & data$disc>=10,"disc10"] <- TRUE
  
  # plotting 
  p <- ggplot(data,aes_string(x="TIME",y=cols[1])) + 
    geom_line(colour="lightblue") + geom_point(colour="lightblue") + 
    scale_x_continuous(breaks=seq(1.33,12.66,length.out=11),labels=paste(1:11,"A",sep=""),position="top") +
    geom_line(aes_string(y=cols[2]),colour="blue") + 
    geom_point(aes_string(y=cols[2],shape="disc10"),size=2,color="blue") +
    geom_point(data=data[!is.na(data$disc) & data$disc>=10,],aes_string(y=cols[2],shape="disc10"),size=2,color="red") +
    facet_wrap("ID",strip.position = "right",ncol=ncol) +
    ggtitle(paste("Daily fluctuations in",ifelse(BP=="S","Systolic","Diastolic"),
                  "blood pressure (light blue = 1st recording, dark blue = 2nd recording, red triangles = discrep. > 10 mmHg)")) + 
    xlab("Day of week") + ylab(paste(BP,"BP (mmHg)",sep=""))+
    geom_hline(yintercept=ifelse(BP=="S",130,85),color="blue",lty=2)+
    theme(axis.text.x = element_text(size=9,angle = 45),legend.position="none")
  
  # marking flagged cases
  if(!is.na(flagged)){ data$flag <- data[,flagged]
    p <- p + geom_point(data=data[!is.na(data$flag) & data$flag==TRUE,],aes_string(y=cols[2]),size=4,shape=1) +
      geom_text(data=data[!is.na(data$flag) & data$flag==TRUE,],aes_string(y=paste(cols[2],"+10"),label=what)) }
  
  # showing average value
  if(!is.na(meanVal)){ data$meanVal <- data[,meanVal]
    p <- p + geom_line(data=data[!is.na(data$meanVal),],aes(y=meanVal),lwd=1.1,color="green") +
      geom_point(data=data[!is.na(data$meanVal),],aes(y=meanVal),color="green") }
  p}


SBP

plotBP(diary,BP="S",ncol=4)


DBP

plotBP(diary,BP="D",ncol=4)


SBP (flagged)

Here, we manually flag the cases showing extreme values in the second measurement or both, since we will remove the first measurement when it is more than 10 mmHg lower or higher than the first one (see below). Only these cases are plotted below.

# flagged cases (only second = "2" or "both" measurement)
flagS <- data.frame(ID   = c("S006","S007","S011","S011","S030","S030","S033","S058","S061","S065","S077","S077"),
                   day   =     c(3,     2,     1,     8,    1,     2,    6,      8,     9,     10,   1,    1),
                   diaryType= c("A",   "E",   "A",   "A",  "A",   "A",  "M",    "A",   "E",   "M",   "A",  "E"),
                   whatS =     c("both","both","both","2",  "2",   "2",  "2",    "2",   "2",   "2",   "2",  "2"))
# further flagged cases
flagS <- rbind(flagS,
               data.frame(ID   = c("s080","s080","s080","S082","S100","S110","S110","S144"),
                   day   =     c(     1,    1,     2,     1,     1,     2,     3,      8),
                   diaryType= c(     "E",  "M",    "E",  "A",   "A",   "M",   "M",   "A"),
                   whatS =     c(   "both","both","both","both","both", "2",   "2",   "both")))

# adding information on flagged cases
flagS$SBPflag <- TRUE
diary <- plyr::join(diary,flagS,by=c("ID","day","diaryType"),type="left")
diary[is.na(diary$SBPflag) & !is.na(diary$SBP1),"SBPflag"] <- FALSE

# plotting
plotBP(diary[diary$ID%in%levels(as.factor(as.character(flagS$ID))),],BP="S",ncol=4,flagged="SBPflag",what="whatS")


DBP (flagged)

Here, we manually flag the cases showing extreme values in the second measurement or both, since we will remove the first measurement when it is more than 10 mmHg lower or higher than the first one (see below). Only these cases are plotted below.

# flagged cases (only systolic = "S" or "both", but not diastolic - see below)
flagD <- data.frame(ID  = c(rep("S006",4),           "S007","S034","S057","S058","S058","S070","S070",rep("S080",3),"S082"),
                   day  = c(     1,  2,    2,  3,         5,     2,     9,    8,     8,       6,    8,       1,2,2,     1),
                   diaryType=c( "A","M",  "E","M",       "E",   "M",   "E",  "A",   "E",     "M",  "M",    "E","M","E","A"),
                   whatD =    c("2","inv","2","2",      "both", "2",  "2",   "2",   "2",     "2",  "2",  rep("both",3),"both"))

# further flagged cases
flagD <- rbind(flagD,
               data.frame(ID=c("S092","S093","S093","S093","S117","S117","S130","S144","S144","S145"),
                   day  =     c(  9,    2,      3,     7,    6,      9,     2,     8,     11,     1),
                   diaryType = c("E",  "A",    "A",   "E",  "M",    "A",   "E",   "A",    "E",   "A"),
                   whatD =    c(  "2", "inv",  "inv", "inv", "2",    "2",   "2",  "both","both", "2")))

# adding information on flagged cases
flagD$DBPflag <- TRUE
diary <- plyr::join(diary,flagD,by=c("ID","day","diaryType"),type="left")
diary[is.na(diary$DBPflag) & !is.na(diary$SBP1),"DBPflag"] <- FALSE

# plotting
plotBP(diary[diary$ID%in%levels(as.factor(as.character(flagD$ID))),],BP="D",ncol=4,flagged="DBPflag",what="whatD")


3.2.4. BP Aggregated values

Here, we aggregate the first and second measurement of systolic and diastolic BP. As pre-registered here, SBP and DBP aggregated values are computed as the average between the first and the second (immediately consecutive) BP recording. In all cases showing discrepancies (i.e., absolute differences) between the first and the second recording equal to or higher than 10 mmHg, only the second recorded value is considered (i.e., the first recording is excluded).

However, we also account for the flagged cases marked as “2” (when the second measurement should be removed), “both” (when both measurements have extreme values in the same direction), and “inv” (when the both have extreme values in opposite directions):

  • in cases flagged as "2", we only keep the first measurement

  • in cases flagged as "inv", we compute the average (as in any non-flagged case)

  • in cases flagged as "both", we interpolate the measurement as the maximum value (or the minimum, based on the direction of extreme values) recorded for that participant.

This is done independently for systolic and diastolic BP


3.2.4.1. Aggregating values

First, we aggregate SBP values.

# SBP - printing info
cat("- Averaging",nrow(diary[!is.na(diary$SBPflag) & (diary$SBPflag==FALSE | diary$SBPflag=="inv") & 
                               abs(diary$SBP1-diary$SBP2)<10,]),"cases\n- Excluding",
    nrow(diary[!is.na(diary$SBPflag) & abs(diary$SBP1-diary$SBP2)>=10 & diary$SBPflag==FALSE,]),
    "first measurments\n- Excluding",nrow(diary[!is.na(diary$whatS) & diary$whatS=="2",]),
    "second mesurements\n- Interpolating",nrow(diary[!is.na(diary$whatS) & diary$whatS=="both",]),"measurements")
## - Averaging 2366 cases
## - Excluding 562 first measurments
## - Excluding 10 second mesurements
## - Interpolating 6 measurements
# (1) averaged cases (no flagged, or flagged = "inv", and discrepancies < 10mmHg)
diary[(!is.na(diary$SBPflag) & diary$SBPflag==FALSE & abs(diary$SBP1-diary$SBP2) < 10) |
        (!is.na(diary$whatS) & diary$whatS=="inv"),"SBP"] <- 
  apply(diary[(!is.na(diary$SBPflag) & diary$SBPflag==FALSE & abs(diary$SBP1-diary$SBP2) < 10) |
        (!is.na(diary$whatS) & diary$whatS=="inv"),c("SBP1","SBP2")],1,mean)
# (2) cases only based on the second measuremnt (discrepancies >= 10mmHg AND no flags)
diary[!is.na(diary$SBPflag) & diary$SBPflag==FALSE & abs(diary$SBP1-diary$SBP2) >= 10,"SBP"] <- 
  diary[!is.na(diary$SBPflag) & diary$SBPflag==FALSE & abs(diary$SBP1-diary$SBP2) >= 10,"SBP2"]
# (3) cases only based on the first measuremnt (flagged=TRUE and what = "2")
diary[!is.na(diary$SBPflag) & diary$SBPflag==TRUE & diary$whatS=="2",
      "SBP"] <- diary[!is.na(diary$SBPflag) & diary$SBPflag==TRUE & diary$whatS=="2","SBP1"]
# (4) cases interpolated as the maximum value
for(i in which(!is.na(diary$whatS) & diary$whatS=="both")){ 
  if(diary[i,"SBP2"]>mean(diary[diary$ID==diary[i,"ID"],"SBP"],na.rm=TRUE)){
    diary[i,"SBP"] <- max(diary[diary$ID==diary[i,"ID"],"SBP"],na.rm=TRUE)
  } else { diary[i,"SBP"] <- min(diary[diary$ID==diary[i,"ID"],"SBP"],na.rm=TRUE) }}

# sanity check
nrow(diary[(!is.na(diary$SBPflag) & is.na(diary$SBP))|(is.na(diary$SBPflag) & !is.na(diary$SBP)),]) == 0 
## [1] TRUE


Then, we aggregate DBP values.

# DBP - printing info
cat("- Averaging",nrow(diary[((!is.na(diary$DBPflag) & diary$DBPflag==FALSE) | 
                               (!is.na(diary$whatD) & diary$whatD=="inv")) & 
                               abs(diary$DBP1-diary$DBP2)<10,]),"cases\n- Excluding",
    nrow(diary[!is.na(diary$DBPflag) & abs(diary$DBP1-diary$DBP2)>=10 & diary$DBPflag==FALSE,]),
    "first measurments\n- Excluding",nrow(diary[!is.na(diary$whatD) & diary$whatD=="2",]),
    "second mesurements\n- Interpolating",nrow(diary[!is.na(diary$whatD) & diary$whatD=="both",]),"measurements")
## - Averaging 2292 cases
## - Excluding 629 first measurments
## - Excluding 12 second mesurements
## - Interpolating 7 measurements
# (1) averaged cases (no flagged and discrepancies < 10mmHg, or flagged = "inv")
diary[((!is.na(diary$DBPflag) & diary$DBPflag==FALSE & abs(diary$DBP1-diary$DBP2) < 10) | 
         (!is.na(diary$whatD) & diary$whatD=="inv")),"DBP"] <- 
  apply(diary[((!is.na(diary$DBPflag) & diary$DBPflag==FALSE & abs(diary$DBP1-diary$DBP2) < 10) | 
         (!is.na(diary$whatD) & diary$whatD=="inv")),c("DBP1","DBP2")],1,mean)
# (2) cases only based on the second measurement (discrepancies >= 10mmHg AND no flags)
diary[!is.na(diary$DBPflag) & diary$DBPflag==FALSE & abs(diary$DBP1-diary$DBP2) >= 10,"DBP"] <- 
  diary[!is.na(diary$DBPflag) & diary$DBPflag==FALSE & abs(diary$DBP1-diary$DBP2) >= 10,"DBP2"]
# (3) cases only based on the first measurement (flagged=TRUE and what = "2")
diary[!is.na(diary$DBPflag) & !is.na(diary$whatD) & diary$DBPflag==TRUE & diary$whatD=="2",
      "DBP"] <- diary[!is.na(diary$DBPflag) & diary$DBPflag==TRUE & diary$whatD=="2","DBP1"]
# (4) cases interpolated as the maximum value
for(i in which(!is.na(diary$whatD) & diary$whatD=="both")){ 
  if(diary[i,"DBP2"]>mean(diary[diary$ID==diary[i,"ID"],"DBP"],na.rm=TRUE)){
    diary[i,"DBP"] <- max(diary[diary$ID==diary[i,"ID"],"DBP"],na.rm=TRUE)
  } else { diary[i,"DBP"] <- min(diary[diary$ID==diary[i,"ID"],"DBP"],na.rm=TRUE) }}

# sanity check
nrow(diary[(!is.na(diary$DBPflag) & is.na(diary$DBP))|(is.na(diary$DBPflag) & !is.na(diary$DBP)),]) == 0 
## [1] TRUE


3.2.4.2. Visual inspection

Then, we replicate the plots generated above by showing the aggregated BP values in green.

SBP
plotBP(diary,BP="S",ncol=4,flagged="SBPflag",what="whatS",meanVal="SBP")


DBP
plotBP(diary,BP="D",ncol=4,flagged="DBPflag",what="whatD",meanVal="DBP")
## Warning: Removed 126 rows containing missing values (`geom_point()`).
## Removed 126 rows containing missing values (`geom_point()`).


3.2.4.3. Data integration

Finally, we replace the raw BP data with the processed (i.e., aggregate) values in the diary dataset and we remove the variables identifying flagged cases.

# replacing raw BP with aggregate BP
diary <- diary[,c(1:which(colnames(diary)=="dayOfftoday"),which(colnames(diary)%in%c("SBP","DBP")),
                  which(colnames(diary)=="dayOffyesterday"):(ncol(diary)-2))]

# creating new variable summarizing flagged cases
diary$flagBP <- FALSE
diary[(!is.na(diary$SBPflag) & diary$SBPflag==TRUE)|(!is.na(diary$DBPflag) & diary$DBPflag==TRUE),"flagBP"] <- TRUE
diary$SBPflag <- diary$whatS <- diary$DBPflag <- diary$whatD <- NULL # removing variables identifying flagged cases


3.3. BMI

Here, we inspect the distribution of BMI values, and we compare it with the cut-offs proposed by the World Health Organization (2010). We observe no extreme BMI values despite a few participants in the underweight (N = 3), and obesity - class II category (N = 8), and one participant in the obese - class III category. We have no reasons to exclude participants based on BMI values.

hist(prelqs$BMI,xlab="BMI (kg/m^2)",breaks=30,xlim=c(15,40),ylim=c(0,14))
abline(v=c(18.5,25,30,35,40),col="red",lty=2)
text(x=c(16,21.5,27.5,32.5,37.5),y = 13,
     labels=c("Underweight","Normal weight","Pre-obesity","Obesity I","Obesity II"))


3.4. Daily wide dataset

Here, we use the day variable created above to transform the diary dataset from the current long form (i.e., one row per measurement occasion within day and participant) to a daily wide form (i.e., one row per day within participant, with measurements collected on the same day being presented in the same line of the dataset).

First, we split the diary dataset back to the three datasets based on the measurement occasion (i.e., morning, afternoon, and evening).

# sorting columns
diary <- diary[,c("ID","day","start","end","diaryType","dayOff","dayOfftoday","dayOffyesterday",
                  "SBP","DBP","flagBP","where","confounders","coffee","smoke","sport","meal","dailyHassles",
                  colnames(diary)[which(colnames(diary)=="OC1"):which(colnames(diary)=="wakeTime")],"hhFromAwake",
                  paste("AWL",1:3,sep=""),
                  colnames(diary)[which(colnames(diary)=="WL1"):which(colnames(diary)=="workHours")],"IDday")]

# splitting dataset
diary_m <- diary[diary$diaryType=="M",c(1:which(colnames(diary)=="end"),
                                        which(colnames(diary)=="dayOfftoday"):which(colnames(diary)=="AWL3"),ncol(diary))]
diary_a <- diary[diary$diaryType=="A",c(1:which(colnames(diary)=="end"),which(colnames(diary)=="dayOff"),
                                        which(colnames(diary)=="SBP"):which(colnames(diary)=="meal"),
                                        which(colnames(diary)=="WL1"):which(colnames(diary)=="WE3"),ncol(diary))]
diary_e <- diary[diary$diaryType=="E",c(1:which(colnames(diary)=="end"),which(colnames(diary)=="dayOff"),
                                        which(colnames(diary)=="SBP"):which(colnames(diary)=="flagBP"),
                                        which(colnames(diary)=="confounders"):which(colnames(diary)=="dailyHassles"),
                                        which(colnames(diary)=="EE1"):which(colnames(diary)=="workHours"),ncol(diary))]

# renaming columns sharing the same name in the three datasets
cm <- colnames(diary_m)
ca <- colnames(diary_a)
ce <- colnames(diary_e)
colnames(diary_m)[3:ncol(diary_m)][which(colnames(diary_m)[3:ncol(diary_m)]%in%ca | colnames(diary_m)[3:ncol(diary_m)]%in%ce)] <-
  paste(colnames(diary_m)[3:ncol(diary_m)][which(colnames(diary_m)[3:ncol(diary_m)]%in%ca |
                                                   colnames(diary_m)[3:ncol(diary_m)]%in%ce)],"mor",sep="_")
colnames(diary_a)[3:ncol(diary_a)][which(colnames(diary_a)[3:ncol(diary_a)]%in%cm | colnames(diary_a)[3:ncol(diary_a)]%in%ce)] <-
  paste(colnames(diary_a)[3:ncol(diary_a)][which(colnames(diary_a)[3:ncol(diary_a)]%in%cm |
                                                   colnames(diary_a)[3:ncol(diary_a)]%in%ce)],"aft",sep="_")
colnames(diary_e)[3:ncol(diary_e)][which(colnames(diary_e)[3:ncol(diary_e)]%in%cm | colnames(diary_e)[3:ncol(diary_e)]%in%ca)] <-
  paste(colnames(diary_e)[3:ncol(diary_e)][which(colnames(diary_e)[3:ncol(diary_e)]%in%cm |
                                                   colnames(diary_e)[3:ncol(diary_e)]%in%ca)],"eve",sep="_")

# adding IDday column to join datasets based on ID and day
colnames(diary_m)[ncol(diary_m)] <- colnames(diary_a)[ncol(diary_a)] <- colnames(diary_e)[ncol(diary_e)] <- "IDday"


Second, we look for cases of double responses within each dataset by using the ID x day identifier created above. A total of six double responses are detected.

# diary_m: 1 double response -> taking 1st one
diary_m[diary_m$IDday%in%diary_m$IDday[duplicated(diary_m$IDday)],] 
diary_m <- diary_m[!(diary_m$ID=="S025" & as.character(diary_m$end_mor)=="2022-05-03 13:53:34"),]

# diary_a: 2 double responses -> taking 1st or 2d based on submission time
diary_a[diary_a$IDday%in%diary_a$IDday[duplicated(diary_a$IDday)],] 
diary_a <- diary_a[!((diary_a$ID=="S040" & as.character(diary_a$end_aft)=="2022-03-08 20:01:01") |
                       (diary_a$ID=="S060" & as.character(diary_a$end_aft)=="2022-01-25 18:58:10") |
                       (diary_a$ID=="S113" & as.character(diary_a$end_aft)=="2022-02-28 20:33:41") |
                       (diary_a$ID=="S113" & as.character(diary_a$end_aft)=="2022-03-01 21:41:58")),]

# diary_e: 3 double responses -> taking 2nd or 1st based on submission time
diary_e[diary_e$IDday%in%diary_e$IDday[duplicated(diary_e$IDday)],] 


diary_e <- diary_e[!((diary_e$ID=="S060" & as.character(diary_e$end_eve)=="2022-01-26 19:57:02") |
                       (diary_e$ID=="S108" & diary_e$dayOff_eve==TRUE)),]
# sanity check
nrow(diary_m[duplicated(diary_m$IDday),]) == 0 & nrow(diary_a[duplicated(diary_a$IDday),]) == 0 &
  nrow(diary_e[duplicated(diary_e$IDday),]) == 0
## [1] TRUE


Now we can merge the tree dataset into a daily wide form dataset.

# joining datasets
diary_wide <- plyr::join(diary_a,plyr::join(diary_e,diary_m,by="IDday",type="full"),by="IDday",type="full")
diary_wide <- diary_wide[order(diary_wide$ID,diary_wide$day),] # sorting by ID and day

# sanity check
nrow(diary_wide[!is.na(diary_wide$start_aft),]) == nrow(diary_a) &
  nrow(diary_wide[!is.na(diary_wide$start_eve),]) == nrow(diary_e) & 
  nrow(diary_wide[!is.na(diary_wide$start_mor),]) == nrow(diary_m)
## [1] TRUE
# checking for duplicates
nrow(diary_wide[duplicated(diary_wide$IDday),])
## [1] 0
diary_wide$IDday <- NULL # removing IDday (no longer necessary)

# adding variables to filter missing data
diary_wide[,c("aft","eve","mor")] <- 0
diary_wide[!is.na(diary_wide$start_aft) & !is.na(diary_wide$dayOff_aft) & diary_wide$dayOff_aft==FALSE,"aft"] <- 1
diary_wide[!is.na(diary_wide$start_eve) & !is.na(diary_wide$dayOff_eve) & diary_wide$dayOff_eve==FALSE,"eve"] <- 1
diary_wide[!is.na(diary_wide$start_mor) & !is.na(diary_wide$dayOffyesterday) & diary_wide$dayOffyesterday==FALSE,"mor"] <- 1 
diary_wide[,c("aft","eve","mor")] <- lapply(diary_wide[,c("aft","eve","mor")],as.factor)
diary_wide <- diary_wide[,c(1:2,(ncol(diary_wide)-2):ncol(diary_wide),3:(ncol(diary_wide)-3))]

# sorting by ID and day
diary_wide <- diary_wide[order(diary_wide$ID,diary_wide$day),]
rownames(diary_wide) <- 1:nrow(diary_wide)

# showing dataset
diary_wide[,c(colnames(diary_wide)[1:6],"start_eve","start_mor")]


3.5. Joining prelqs

Here, we join the demographic and occupational information from the prelqs dataset with the time-varying data included in the diary_wide dataset. The resulting diary_wide dataset has multiple rows reporting the same demographic and occupational values (level-2) repeated over multiple rows associated with the same participant. Moreover, we also join the responses to the raw retrospective workaholism items.

# renaming retrospective workaholism items
colnames(prelqs)[grep("WHLSM",colnames(prelqs))] <- paste0("duwas",1:10)

# joining prelqs variables to diary_wide
diary_wide <- plyr::join(diary_wide,
                         prelqs[,c("ID",
                                   colnames(prelqs)[which(colnames(prelqs)=="gender"):which(colnames(prelqs)=="children")],
                                   "home_child","partner","home_partner",
                                   colnames(prelqs)[which(colnames(prelqs)=="smoker"):which(colnames(prelqs)=="workTime")],
                                   paste0("duwas",1:10))],
                         by="ID",type="left") # merging datasets by ID

# showing examples
head(diary_wide[,c(colnames(diary_wide)[1:6],"SBP_aft","age","sector")])


3.6. Response processing

Here, we look for cases of incoherent/inconsistent responses in several considered variables.


3.6.1. Days off

First, we check the cases of incoherent responses to the dayOff variable across the three daily diaries (e.g., participants reporting “today, I did not work” to the afternoon but not to the evening questionnaire). We can see a few incoherent cases (2%), mainly between afternoon and morning, in which participants reported a day-off at the end of the workday but an incoherent response on the following day. Since we have no criteria for establishing which was the ‘true’ answer, we assume that (un)voluntary mistakes were made for dayOff=TRUE responses, treating them as missing responses. Note that none of the cases with dayOff_eve=FALSE have workHours=0.

# 1) inconsistencies within Evening: dayOff_eve = FALSE but teleWork = "dayOff" (N = 4)
diary_wide[!is.na(diary_wide$teleWork) & diary_wide$teleWork=="dayOff",c("ID","day","teleWork","workHours")]
diary_wide[!is.na(diary_wide$teleWork) & diary_wide$teleWork=="dayOff","teleWork"] <- "office" # recoding as teleWork="office"

# 2) inconsistencies between Afternoon & Evening: dayOff_aft != dayOff_eve (N = 10)
diary_wide[!is.na(diary_wide$dayOff_aft) & !is.na(diary_wide$dayOff_eve) & diary_wide$dayOff_aft != diary_wide$dayOff_eve,
           c("ID","day","teleWork","workHours","aft","WL1","eve","EE1","dayOff_eve","dayOff_aft")]
diary_wide[!is.na(diary_wide$dayOff_aft) & !is.na(diary_wide$dayOff_eve) & 
             diary_wide$dayOff_aft==TRUE & diary_wide$dayOff_eve == FALSE,"dayOff_aft"] <- NA # replacing incorrect dayOff as NA
diary_wide[!is.na(diary_wide$dayOff_aft) & !is.na(diary_wide$dayOff_eve) & 
             diary_wide$dayOff_aft==FALSE & diary_wide$dayOff_eve == TRUE,"dayOff_eve"] <- NA

# 3) inconsistencies between Afternoon & Evening: dayOff_aft = FALSE but teleWork = "dayOff" (N = 0)
diary_wide[!is.na(diary_wide$dayOff_aft) & !is.na(diary_wide$teleWork) & 
             diary_wide$dayOff_aft==FALSE & diary_wide$teleWork=="dayOff",
           c("ID","day","teleWork","workHours","aft","WL1","eve","EE1","dayOff_eve","dayOff_aft")]
# 4) inconsistencies between Afternoon & Morning: dayOff_aft != dayOffyesterday (N = 4)
diary_wide[!is.na(diary_wide$dayOff_aft) & !is.na(diary_wide$dayOffyesterday) & diary_wide$dayOff_aft!=diary_wide$dayOffyesterday,
           c("ID","day","workHours","aft","WL1","mor","SQ1","dayOffyesterday","dayOff_aft")]
diary_wide[!is.na(diary_wide$dayOff_aft) & !is.na(diary_wide$dayOffyesterday) & 
             diary_wide$dayOff_aft==TRUE & diary_wide$dayOffyesterday == FALSE,"dayOff_aft"] <- NA # replacing with NA
diary_wide[!is.na(diary_wide$dayOff_aft) & !is.na(diary_wide$dayOffyesterday) & 
             diary_wide$dayOff_aft==FALSE & diary_wide$dayOffyesterday == TRUE,"dayOffyesterday"] <- NA

# 5) inconsistencies between Evening & Morning: dayOff_eve != dayOffyesterday (N = 2)
diary_wide[!is.na(diary_wide$dayOff_eve) & !is.na(diary_wide$dayOffyesterday) & diary_wide$dayOff_eve!=diary_wide$dayOffyesterday,
           c("ID","day","workHours","eve","EE1","mor","SQ1","dayOffyesterday","dayOff_eve")]
diary_wide[!is.na(diary_wide$dayOff_eve) & !is.na(diary_wide$dayOffyesterday) & diary_wide$dayOff_eve!=diary_wide$dayOffyesterday,
           "dayOff_eve"] <- NA # replacing unexpected value with NA

# 6) inconsistencies between Evening & Morning: teleWork = "dayOff" but dayOffyesterday=FALSE (N = 0)
diary_wide[!is.na(diary_wide$dayOffyesterday) & !is.na(diary_wide$teleWork) & 
             diary_wide$dayOffyesterday==FALSE & diary_wide$teleWork=="dayOff",
           c("ID","day","teleWork","workHours","eve","EE1","mor","SQ1","dayOff_eve","dayOffyesterday")]


Similarly, we inspect cases of participants reporting working days but answering “Today I did not work” to the teleWork item in the evening questionnaire, and vice versa. We can note that there are no cases of incoherent responses related to these variables.

# evening dayOff incoherent to evening telework (N = 0)
diary_wide[!is.na(diary_wide$dayOff_eve) & !is.na(diary_wide$telework) &
             ((diary_wide$dayOff_eve==FALSE & diary_wide$teleWork=="dayOff") |
                (diary_wide$dayOff_eve==TRUE & diary_wide$teleWork!="dayOff")),
           c("ID","dayOff_eve","teleWork","workHours")]
# afternoon dayOff incoherent to evening telework (N = 0)
diary_wide[!is.na(diary_wide$dayOff_aft) & !is.na(diary_wide$telework) &
             ((diary_wide$dayOff_aft==FALSE & diary_wide$teleWork=="dayOff") |
                (diary_wide$dayOff_aft==TRUE & diary_wide$teleWork!="dayOff")),
           c("ID","dayOff_aft","teleWork","workHours")]
# morning dayOffyesterday incoherent to evening telework (N = 0)
diary_wide[!is.na(diary_wide$dayOffyesterday) & !is.na(diary_wide$telework) &
             ((diary_wide$dayOffyesterday==FALSE & diary_wide$teleWork=="dayOff") |
                (diary_wide$dayOffyesterday==TRUE & diary_wide$teleWork!="dayOff")),
           c("ID","dayOffyesterday","teleWork","workHours")]


Finally, we inspect all cases with workHours = 0. We can see only a few of such cases (2%), all of which show dayOff_eve=FALSE (also because it was a necessary condition for responding to the workHours question) as well as dayOff_aft=FALSE and dayOffyesterday=FALSE. Due to this incoherence, we ‘trust’ the responses to dayOff items and we assume that these workHours responses were careless responses. Thus, we interpolate them by assigning the mean No.of workHours reported by the same participant in the other occasions. We also note one participant (S137) that reported workHours=0 in all occasions. Thus, responses are interpolated based on the weekHours question from the prelqs data of the same participant, and we flag this participant as a potential careless respondent.

# inspecting cases of workHours = 0
cat(nrow(diary_wide[!is.na(diary_wide$workHours) & diary_wide$workHours==0,]),"cases of workHours = 0")
## 21 cases of workHours = 0
# inspecting responses to critical variables for such cases
diary_wide[!is.na(diary_wide$workHours) & diary_wide$workHours==0,
           c("ID","dayOff_aft","dayOff_eve","dayOffyesterday","workHours","lateWorkHours")]
# interpolating responses (i.e., assigning the mean No. of workHours for each participant)
IDs <- levels(as.factor(as.character(diary_wide[!is.na(diary_wide$workHours) & diary_wide$workHours==0,"ID"])))
for(ID in IDs[1:(length(IDs)-1)]){
  diary_wide[diary_wide$ID==ID & !is.na(diary_wide$workHours) & diary_wide$workHours==0,"workHours"] <-
    mean(diary_wide[diary_wide$ID==ID & !is.na(diary_wide$workHours) & diary_wide$workHours!=0,"workHours"])}

# interpolating responses of one participant that always reported workHours=0 based on prelqs weekHours
prelqs[prelqs$ID=="S137",c("ID","start","job","position","sector","weekHours","weekHours_remote","workTime")]
diary_wide[diary_wide$ID=="S137" & !is.na(diary_wide$dayOff_eve) & diary_wide$dayOff_eve==FALSE,"workHours"] <-
  prelqs[prelqs$ID=="S137","weekHours"]/5

# flagging S137 as a potential careless respondent
prelqs$careless <- FALSE
prelqs[prelqs$ID=="S137","careless"] <- TRUE
diary_wide <- plyr::join(diary_wide,prelqs[,c("ID","careless")],by="ID",type="left") # joining careless to diary_wide


3.6.2. Start time

Here, we inspect the distribution of start times looking for filtering responses out of time (e.g., morning diary filled in the evening).

# plotting
par(mfrow=c(1,3))
hist(as.POSIXct(substr(diary_wide$start_aft,12,19),format="%H:%M:%S"),breaks="hours",main="Afternoon",xlab="")
hist(as.POSIXct(substr(diary_wide$start_eve,12,19),format="%H:%M:%S"),breaks="hours",main="Evening",xlab="")
hist(as.POSIXct(substr(diary_wide$start_mor,12,19),format="%H:%M:%S"),breaks="hours",main="Morning",xlab="")


3.6.2.1. Filtering Afternoon

With flagged Afternoon responses given after 22:00 (N = 11) :

  • we keep all responses that were submitted up to one hour before starting the Evening diary (N = 3)

  • we only consider retrospective items (i.e., dayOff_aft, WL, WHLSM, WE) and not momentary items (i.e., confounders and BP are removed) for responses submitted less than one hour before starting the Evening diary (N = 6)

  • we recode momentary items (i.e., BP, confounders) as they were responded in the Evening for all responses submitted later than 22:00 with no subsequent Evening response (i.e., BP values) but with nonmissing afternoon BP (N = 2)

# selecting flagged cases - afternoon (N = 11)
diary_wide$IDday <- paste(diary_wide$ID,diary_wide$day,sep="_") # re-creating IDday
flagA <- diary_wide[!is.na(diary_wide$start_aft) & (as.POSIXct(substr(diary_wide$start_aft,12,16),format="%H:%M") < # A after 22:00
                                                      as.POSIXct("15:00",format="%H:%M",tz="GMT") |
                                                      as.POSIXct(substr(diary_wide$start_aft,12,16),format="%H:%M") >
                                                      as.POSIXct("22:00",format="%H:%M",tz="GMT")),] 
flagA[,c("IDday","start_aft","end_aft","start_eve","workHours","lateWorkHours","workTime")] # showing flagged cases
# marking responses
flagA$flag <- NA
flagA[!is.na(flagA$start_eve) & difftime(flagA$start_eve,flagA$end_aft,units="hours")>1,"flag"] <- "ok"
flagA[!is.na(flagA$start_eve) & difftime(flagA$start_eve,flagA$end_aft,units="hours")<=1,"flag"] <- "momentary.OUT"
flagA[is.na(flagA$SBP_eve) & !is.na(flagA$SBP_aft),"flag"] <- "toEvening"
table(flagA$flag) # showing No. of cases
## 
## momentary.OUT            ok     toEvening 
##             6             3             2
# filtering responses
diary_wide$flagA <- NA # flagging all flagA cases in the diary_wide dataset
diary_wide[diary_wide$IDday%in%levels(as.factor(flagA$IDday)),"flagA"] <- flagA[,"flag"]
aft_cols <- which(colnames(diary_wide)=="SBP_aft"):which(colnames(diary_wide)=="meal_aft") # afternoon momentary columns
eve_cols <- which(colnames(diary_wide)=="SBP_eve"):which(colnames(diary_wide)=="meal_eve") # evening momentary columns
diary_wide[!is.na(diary_wide$flagA) & diary_wide$flagA=="momentary.OUT",aft_cols] <- NA # removing momentary (N = 6)
diary_wide[!is.na(diary_wide$flagA) & diary_wide$flagA=="toEvening",eve_cols] <- # momentary values to Evening (N = 2)
  diary_wide[!is.na(diary_wide$flagA) & diary_wide$flagA=="toEvening",aft_cols[aft_cols!=which(colnames(diary_wide)=="where_aft")]]
diary_wide[!is.na(diary_wide$flagA) & diary_wide$flagA=="toEvening",
           aft_cols[aft_cols!=which(colnames(diary_wide)=="where_aft")]] <- NA # removing mom. from those cases

# sanity check
diary_wide[!is.na(diary_wide$flagA),c("flagA","end_aft","start_eve","SBP_aft","SBP_eve","WL1","EE1")]


3.6.2.2. Filtering Evening

With flagged Evening responses (N = 16) given after 05:00:

  • we keep all responses that were submitted between 21:00 and 5:00 and up to one hour after submitting the Afternoon diary (N = 8), by assuming that (a) in a few cases participant went to sleep around 21:30 (N = 7), and (b) responses that took 1+ hours (N = 1) were open early by mistake but responded at the right time (i.e., bedtime)

  • we remove all momentary responses (i.e., BP, confounders) that were submitted less than one hour after submitting the Afternoon diary (N = 2)

  • we keep all responses submitted between 21:00 and 5:00 with missing Afternoon responses (N = 3)

  • we remove all responses submitted after 05:00 when followed by the morning surveys with nonmissing BP measurements (N = 2)

  • we recode momentary items (i.e., BP, confounders) as they were responded in the Morning, while removing retrospective items for responses submitted later than 05:00 with no subsequent Morning response (N = 1)

# selecting flagged cases - evening (N = 16)
flagE <- diary_wide[!is.na(diary_wide$start_eve) & (as.POSIXct(substr(diary_wide$start_eve,12,16),format="%H:%M") < # E after 5:00
                                                      as.POSIXct("21:30",format="%H:%M",tz="GMT") &
                                                      as.POSIXct(substr(diary_wide$start_eve,12,16),format="%H:%M") >
                                                      as.POSIXct("05:00",format="%H:%M",tz="GMT")),] 
flagE$wakeTime <- substr(flagE$wakeTime,12,16)
flagE[,c("ID","end_aft","start_eve","end_eve","start_mor","wakeTime","workTime")] # showing flagged cases
# marking responses
flagE$flag <- NA
flagE[!is.na(flagE$start_aft) & difftime(flagE$end_eve,flagE$end_aft,units="hours")>=1 & # >21:00 & >1h from Aft (N = 8)
        as.POSIXct(substr(flagE$end_eve,12,16),format="%H:%M") > as.POSIXct("21:00",format="%H:%M",tz="GMT")  |
        as.POSIXct(substr(flagE$end_eve,12,16),format="%H:%M") < as.POSIXct("05:00",format="%H:%M",tz="GMT"),"flag"] <- "ok1"
flagE[!is.na(flagE$start_aft) & difftime(flagE$end_eve,flagE$end_aft,units="hours")<1,"flag"] <- "momentary.OUT" # >1h from Aft (2)
flagE[is.na(flagE$start_aft) & # >21:00 & without Aft (N = 3)
        as.POSIXct(substr(flagE$end_eve,12,16),format="%H:%M") > as.POSIXct("21:00",format="%H:%M",tz="GMT")  |
        as.POSIXct(substr(flagE$end_eve,12,16),format="%H:%M") < as.POSIXct("05:00",format="%H:%M",tz="GMT"),"flag"] <-"ok2"
flagE[!is.na(flagE$SBP_mor) & is.na(flagE$flag) & # >5:00 & nonmissing Morning BP (N = 2)
        as.POSIXct(substr(flagE$end_eve,12,16),format="%H:%M") > as.POSIXct("05:00",format="%H:%M",tz="GMT") &
        as.POSIXct(substr(flagE$end_eve,12,16),format="%H:%M") < as.POSIXct("21:00",format="%H:%M",tz="GMT"),"flag"] <-"OUT"
flagE[is.na(flagE$SBP_mor) & # >5:00 & missing Morning BP (N = 1)
        as.POSIXct(substr(flagE$end_eve,12,16),format="%H:%M") > as.POSIXct("05:00",format="%H:%M",tz="GMT") &
        as.POSIXct(substr(flagE$end_eve,12,16),format="%H:%M") < as.POSIXct("21:00",format="%H:%M",tz="GMT"),"flag"] <-"toMorning"
table(flagE$flag) # showing No. of cases
## 
## momentary.OUT           ok1           ok2           OUT     toMorning 
##             2             8             3             2             1
# filtering responses
diary_wide$flagE <- NA # flagging all flagM cases in the diary_wide dataset
eve_cols.full <- which(colnames(diary_wide)=="start_eve"):which(colnames(diary_wide)=="workHours") # evening full columns
mor_cols <- which(colnames(diary_wide)=="SBP_mor"):which(colnames(diary_wide)=="meal_mor") # morning momentary columns
diary_wide[diary_wide$IDday%in%levels(as.factor(flagE$IDday)),"flagE"] <- flagE[,"flag"]
diary_wide[!is.na(diary_wide$flagE) & diary_wide$flagE=="momentary.OUT",eve_cols] <- NA # removing momentary Evening (N = 2)
diary_wide[!is.na(diary_wide$flagE) & diary_wide$flagE=="OUT",eve_cols.full] <- NA # removing all Evening (N = 2)
diary_wide[!is.na(diary_wide$flagE) & diary_wide$flagE=="OUT","eve"] <- 0 
diary_wide[!is.na(diary_wide$flagE) & diary_wide$flagE=="toMorning",
           mor_cols[mor_cols!=which(colnames(diary_wide)=="where_mor")]] <- # momentary values to Morning (N = 1)
  diary_wide[!is.na(diary_wide$flagE) & diary_wide$flagE=="toMorning",eve_cols]
diary_wide[!is.na(diary_wide$flagE) & diary_wide$flagE=="toMorning",eve_cols] <- NA # removing mom. from those cases

# sanity check
diary_wide[!is.na(diary_wide$flagE),c("flagE","end_aft","end_eve","end_mor","SBP_eve","SBP_mor","EE1","OC1")]


3.6.2.3. Filtering Morning

With flagged Morning responses (N = 23) given after 05:00:

  • we keep all responses started on Saturdays before 15:00 (N = 6)

  • we keep all responses submitted on Tuesday-Friday before 15:00 and up to three hours before submitting the Afternoon diary (N = 11)

  • we remove all responses submitted after 15:00 (N = 4)

  • we remove momentary items from responses submitted less than three hours before submitting the Afternoon diary with nonmissing BP values (N = 1)

# selecting flagged cases - morning (N = 22)
flagM <- diary_wide[!is.na(diary_wide$start_mor) & (as.POSIXct(substr(diary_wide$start_mor,12,16),format="%H:%M") < # M after 12:00
                                                      as.POSIXct("23:59",format="%H:%M",tz="GMT") & 
                                                      as.POSIXct(substr(diary_wide$start_mor,12,16),format="%H:%M") >
                                                      as.POSIXct("12:00",format="%H:%M",tz="GMT")),]

# adding next day start_aft (start_aft.nd) when nonmissing
flagM$start_aft.nd <- as.POSIXct(NA)
flagM1 <- as.data.frame(matrix(nrow=0,ncol=ncol(flagM)))
for(i in 1:nrow(flagM)){ flagM1 <- rbind(flagM1,flagM[i,])
  if(nrow(diary_wide[diary_wide$ID==flagM[i,"ID"] & diary_wide$day==flagM[i,"day"]+1,])>0){ 
    flagM1[nrow(flagM1),"start_aft.nd"]<-diary_wide[diary_wide$ID==flagM[i,"ID"]&diary_wide$day==flagM[i,"day"]+1,"start_aft"]}}

# showing cases
flagM1[,c("ID","day","wakeTime","start_mor","end_mor","start_aft.nd")]


# marking responses
flagM1$flag <- NA
flagM1[flagM1$day%in%c(5,11) & # Saturdays with start <15:00 (N = 6)
       as.POSIXct(substr(flagM1$start_mor,12,16),format="%H:%M") < as.POSIXct("15:00",format="%H:%M",tz="GMT"),"flag"] <- "ok1"
flagM1[!flagM1$day%in%c(5,11) & difftime(flagM1$start_aft.nd,flagM1$end_mor,units="hours")>3 & # Tue-Fry <15:00 & >3h from Aft (11)
       as.POSIXct(substr(flagM1$start_mor,12,16),format="%H:%M") < as.POSIXct("15:00",format="%H:%M",tz="GMT"),"flag"] <- "ok2"
flagM1[as.POSIXct(substr(flagM1$start_mor,12,16),format="%H:%M") > # submitted >15:00 (N = 4)
         as.POSIXct("15:00",format="%H:%M",tz="GMT"),"flag"] <- "OUT"
flagM1[is.na(flagM1$flag),"flag"] <- "momentary.OUT" # submitted <3h before following Afternoon (N = 1)
table(flagM1$flag) # showing No. of cases
## 
## momentary.OUT           ok1           ok2           OUT 
##             1             6            11             4


# filtering responses
diary_wide$flagM <- NA # flagging all flagM cases in the diary_wide dataset
mor_cols.full <- which(colnames(diary_wide)=="start_mor"):which(colnames(diary_wide)=="AWL3") # morning full columns
diary_wide[diary_wide$IDday%in%levels(as.factor(flagM1$IDday)),"flagM"] <- flagM1[,"flag"]
diary_wide[!is.na(diary_wide$flagM) & diary_wide$flagM=="momentary.OUT",mor_cols] <- NA # removing momentary Morning (N = 1)
diary_wide[!is.na(diary_wide$flagM) & diary_wide$flagM=="OUT",mor_cols.full] <- NA # removing all Morning (N = 4)
diary_wide[!is.na(diary_wide$flagM) & diary_wide$flagM=="OUT","mor"] <- 0

# sanity check
diary_wide[!is.na(diary_wide$flagM),c("flagM","start_mor","end_mor","SBP_mor","OC1")]


3.6.2.4. Summary

In summary, we processed diary_wide responses by removing those obtained out of the scheduled times and by recoding time points based on the hour of the day. Specifically, we removed 6 cases (2 Morning, 4 Evening) with response times extremely out of bounds, we removed momentary item responses from 9 cases (6 Afternoon, 2 Evening, 1 Morning) with BP measurements too close to the preceding or the following ones, and we recoded 3 cases (2 Afternoon, 1 Evening) by assigning momentary item responses to the following diary. Here, we re-inspect the distribution of response times in the processed data.

# creating new variable summarizing flagged cases
diary_wide$flagTime <- FALSE
diary_wide[(!is.na(diary_wide$flagA) & diary_wide$flagA!="ok") |
             (!is.na(diary_wide$flagE) & diary_wide$flagE!="ok1" & diary_wide$flagE!="ok2") |
             (!is.na(diary_wide$flagM) & diary_wide$flagM!="ok1" & diary_wide$flagM!="ok2"),"flagTime"] <- TRUE
diary_wide$flagA <- diary_wide$flagE <- diary_wide$flagM <- NULL # removing individual flag variables

# plotting
par(mfrow=c(1,3))
hist(as.POSIXct(substr(diary_wide[!is.na(diary_wide$SBP_aft),
                                  "start_aft"],12,19),format="%H:%M:%S"),breaks="hours",main="Aft",xlab="")
hist(as.POSIXct(substr(diary_wide[!is.na(diary_wide$SBP_eve),
                                  "start_eve"],12,19),format="%H:%M:%S"),breaks="hours",main="Eve",xlab="")
hist(as.POSIXct(substr(diary_wide[!is.na(diary_wide$SBP_mor),
                                  "start_mor"],12,19),format="%H:%M:%S"),breaks="hours",main="Mor",xlab="")


3.6.3. Work hours

Here, we inspect the distribution of workHours and lateWorkHours from the diary_wide dataset, and that of weekHours from the prelqs dataset, looking for cases of unrealistic numbers of working hours. We also compute the workHours_total variable as the sum of workhours and lateWorkHours.

However, we can see that the latter variable would be inaccurate as it might have value > 24h in some cases, implying that a number of participants did not consider workhours and lateWorkhours as mutually exclusive. Thus, we remove it from the dataset.

Moreover, whereas workhours seems quite realistic (ranging from 1h to 15h), lateWorkHours looks inaccurately responded by a number of participants that reported up to 10-20 hours of work after the ‘ordinary’ work schedule. Thus, we dychotomize lateWorkHours as FALSE (lateWorkHours = 0) or TRUE (lateWorkHours > 0)

# computing workHours_total
diary_wide$workHours_total <- diary_wide$workHours + diary_wide$lateWorkHours

# plotting
par(mfrow=c(1,4)); hist(diary_wide$workHours,breaks=30); hist(diary_wide$lateWorkHours,breaks=30)
hist(diary_wide$workHours_total,breaks=30); hist(prelqs$weekHours,breaks=30)

# removing workHours_total
diary_wide$workHours_total <- NULL

# cases of lateWorkHours > 10
diary_wide[!is.na(diary_wide$lateWorkHours) & diary_wide$lateWorkHours>10,c("ID","day","workHours","lateWorkHours",
                                                                            "SQ1","wakeTime","workTime","weekHours",
                                                                            "weekHours_remote","job")]


# dychotomizing lateWorkHours
diary_wide$lateWorkHours1 <- NA
diary_wide[!is.na(diary_wide$lateWorkHours) & diary_wide$lateWorkHours==0,"lateWorkHours1"] <- FALSE
diary_wide[!is.na(diary_wide$lateWorkHours) & diary_wide$lateWorkHours>0,"lateWorkHours1"] <- TRUE
diary_wide$lateWorkHours <- diary_wide$lateWorkHours1
diary_wide$lateWorkHours1 <- NULL
summary(diary_wide$lateWorkHours) # summarizing cases  FALSE=702, TRUE=245, NA=197
##    Mode   FALSE    TRUE    NA's 
## logical     702     245     197


3.6.4. BP confounders

Finally, we observe a number of cases (N = 2-7) with nonmissing response to the core diary items (e.g., workaholism, exhaustion, and sleep items) but missing response to the blood pressure confounders. Here, we set the confounders = FALSE for all of these cases.

# afternoon
cat(nrow(diary_wide[!is.na(diary_wide$WHLSM1) & is.na(diary_wide$confounders_aft),]),
    "cases with missing confounders_aft but nonmissing WHLSM1 item score")
## 7 cases with missing confounders_aft but nonmissing WHLSM1 item score
diary_wide[!is.na(diary_wide$WHLSM1) & is.na(diary_wide$confounders_aft),"confounders_aft"] <- FALSE

# evening
cat(nrow(diary_wide[!is.na(diary_wide$EE1) & is.na(diary_wide$confounders_eve),]),
    "cases with missing confounders_eve but nonmissing EVE1 item score")
## 2 cases with missing confounders_eve but nonmissing EVE1 item score
diary_wide[!is.na(diary_wide$EE1) & is.na(diary_wide$confounders_eve),"confounders_eve"] <- FALSE

# same thing for flagBP variables
diary_wide[!is.na(diary_wide$WHLSM_1) & is.na(diary$flagBP_aft),"flagBP_aft"] <- FALSE
diary_wide[!is.na(diary_wide$EE_1) & is.na(diary$flagBP_eve),"flagBP_eve"] <- FALSE


4. Data selection

Here, we select the observations, participants, and variables to be considered for the subsequent analyses. That is, we discard pilot participants and all related observations, and we remove the variables not considered in the present work.

4.1. Variable selection

Here, we subset the data by selecting and sorting the variables to be considered in the following analyses, whereas unused variables are not included.

# diary data                # case identification
diary_wide <- diary_wide[,c("ID","day",

                            # compliance
                            "aft","eve","mor",

                            # data quality
                            "flagTime","flagBP_aft","flagBP_eve","careless",

                            # afternoon diary
                            "start_aft","end_aft", # starting & ending date & time
                            "dayOff_aft", # took a day off (missing responses)
                            "SBP_aft","DBP_aft", # blood pressure
                            "where_aft","confounders_aft","coffee_aft","smoke_aft","sport_aft","meal_aft", # confounders
                            paste("WHLSM",1:6,sep=""), # state workaholism

                            # evening diary
                            "start_eve","end_eve", # starting & ending date & time
                            "dayOff_eve", # took a day off (missing responses)
                            "SBP_eve","DBP_eve", # blood pressure
                            "confounders_eve","coffee_eve","smoke_eve","sport_eve","meal_eve", # confounders
                            "teleWork","workHours","dailyHassles_eve", # further confounders/covariates
                            paste("EE",1:4,sep=""), # emotional exhaustion
                            paste0("R.det",1:3), # psychological detachment

                            # morning diary
                            "start_mor","end_mor", # starting & ending date & time
                            "dayOffyesterday", # took a day off yesterday or today (missing responses)
                            "lateWorkHours","wakeTime","hhFromAwake", # confounders/covariates
                            paste("SQ",1:4,sep=""), # sleep quality

                            # demographics from the preqls dataset
                            colnames(diary_wide)[which(colnames(diary_wide)=="gender"):which(colnames(diary_wide)=="weekHours")],
                            
                            # Retrospective workaholism items from the prelqs dataset
                            paste0("duwas",1:10))]


4.2. Case selection

Here, we subset the data by selecting the cases to be considered in the following analyses. That is, we filter 12 pilot participants that took part in the pilot trial of the study (i.e., before 2021-04-05).

# selecting pilot participants (12)
(pilots <- levels(as.factor(as.character(prelqs[prelqs$start<as.POSIXct("2021-04-05"),"ID"]))))
##  [1] "S005" "S013" "S067" "S074" "S089" "S094" "S112" "S121" "S133" "S134"
## [11] "S139" "S141"
# filtering 12 pilot participants from diary data
memory <- diary
memory2 <- diary_wide
diary <- diary[!(diary$ID%in%pilots),]
diary_wide <- diary_wide[!(diary_wide$ID%in%pilots),]
diary$ID <- as.factor(as.character(diary$ID))
diary_wide$ID <- as.factor(as.character(diary_wide$ID))
cat("Removed",nlevels(memory$ID)-nlevels(diary$ID),"participants,",
    nrow(memory2)-nrow(diary_wide),"days,",nrow(memory)-nrow(diary),"observations")
## Removed 12 participants, 60 days, 149 observations
cat("diary_wide: total No. of responses =",nrow(diary_wide),"from",nlevels(diary_wide$ID),"participants")
## diary_wide: total No. of responses = 1084 from 135 participants


5. Data dictionary

Here, we provide a definition for each variable in the processed diary_wide datasets.

str(diary_wide)
## 'data.frame':    1084 obs. of  86 variables:
##  $ ID              : Factor w/ 135 levels "S001","S002",..: 1 1 1 1 1 1 1 1 1 1 ...
##  $ day             : num  1 2 3 4 5 7 8 9 10 11 ...
##  $ aft             : Factor w/ 2 levels "0","1": 2 2 2 2 2 2 2 2 2 2 ...
##  $ eve             : Factor w/ 2 levels "0","1": 2 2 2 2 2 2 2 2 2 2 ...
##  $ mor             : Factor w/ 2 levels "0","1": 2 2 2 2 2 2 2 2 2 2 ...
##  $ flagTime        : logi  FALSE FALSE FALSE FALSE FALSE FALSE ...
##  $ flagBP_aft      : logi  FALSE FALSE FALSE FALSE FALSE FALSE ...
##  $ flagBP_eve      : logi  FALSE FALSE FALSE FALSE FALSE FALSE ...
##  $ careless        : logi  FALSE FALSE FALSE FALSE FALSE FALSE ...
##  $ start_aft       : POSIXct, format: "2022-01-24 15:42:17" "2022-01-25 15:50:20" ...
##  $ end_aft         : POSIXct, format: "2022-01-24 15:45:52" "2022-01-25 15:52:14" ...
##  $ dayOff_aft      : logi  FALSE FALSE FALSE FALSE FALSE FALSE ...
##  $ SBP_aft         : num  130 114 114 120 112 ...
##  $ DBP_aft         : num  73 75 75.5 78.5 75.5 82 76 83.5 75.5 80 ...
##  $ where_aft       : Factor w/ 3 levels "home","workplace",..: 1 1 1 1 1 1 1 1 2 1 ...
##  $ confounders_aft : logi  FALSE FALSE FALSE FALSE FALSE FALSE ...
##  $ coffee_aft      : Factor w/ 2 levels "0","1": 1 1 1 1 1 1 1 1 1 1 ...
##  $ smoke_aft       : Factor w/ 2 levels "0","1": 1 1 1 1 1 1 1 1 1 1 ...
##  $ sport_aft       : Factor w/ 2 levels "0","1": 1 1 1 1 1 1 1 1 1 1 ...
##  $ meal_aft        : Factor w/ 2 levels "0","1": 1 1 1 1 1 1 1 1 1 1 ...
##  $ WHLSM1          : num  3 6 5 3 3 3 2 3 2 3 ...
##  $ WHLSM2          : num  2 6 6 3 2 3 2 3 2 4 ...
##  $ WHLSM3          : num  1 6 1 2 1 1 1 1 3 1 ...
##  $ WHLSM4          : num  2 4 2 1 3 3 2 3 2 3 ...
##  $ WHLSM5          : num  1 2 1 1 1 1 1 1 2 1 ...
##  $ WHLSM6          : num  1 3 5 2 3 4 2 5 2 5 ...
##  $ start_eve       : POSIXct, format: "2022-01-24 21:50:17" "2022-01-25 22:17:12" ...
##  $ end_eve         : POSIXct, format: "2022-01-24 21:53:33" "2022-01-25 22:20:13" ...
##  $ dayOff_eve      : logi  FALSE FALSE FALSE FALSE FALSE FALSE ...
##  $ SBP_eve         : num  122 108 106 113 112 ...
##  $ DBP_eve         : num  77 76 66.5 75 74 75.5 80 76 86.5 84 ...
##  $ confounders_eve : logi  FALSE FALSE FALSE FALSE FALSE FALSE ...
##  $ coffee_eve      : Factor w/ 2 levels "0","1": 1 1 1 1 1 1 1 1 1 1 ...
##  $ smoke_eve       : Factor w/ 2 levels "0","1": 1 1 1 1 1 1 1 1 1 1 ...
##  $ sport_eve       : Factor w/ 2 levels "0","1": 1 1 1 1 1 1 1 1 1 1 ...
##  $ meal_eve        : Factor w/ 2 levels "0","1": 1 1 1 1 1 1 1 1 1 1 ...
##  $ teleWork        : Factor w/ 4 levels "office","teleWork",..: 1 1 1 1 1 1 1 1 1 1 ...
##  $ workHours       : num  6 6 6 6 6 6 6 6 9 6 ...
##  $ dailyHassles_eve: Factor w/ 2 levels "No","Yes": 1 1 1 1 1 1 1 1 1 1 ...
##  $ EE1             : num  5 6 7 4 3 5 5 5 5 5 ...
##  $ EE2             : num  5 4 5 3 2 5 4 5 5 4 ...
##  $ EE3             : num  4 1 2 2 2 5 3 1 3 1 ...
##  $ EE4             : num  2 1 1 2 2 5 1 1 4 1 ...
##  $ R.det1          : num  3 2 2 1 1 2 2 4 3 4 ...
##  $ R.det2          : num  2 1 3 1 1 2 3 4 3 3 ...
##  $ R.det3          : num  6 4 5 1 1 2 4 5 5 6 ...
##  $ start_mor       : POSIXct, format: "2022-01-25 08:03:06" "2022-01-26 08:01:20" ...
##  $ end_mor         : POSIXct, format: "2022-01-25 08:05:29" "2022-01-26 08:03:11" ...
##  $ dayOffyesterday : logi  FALSE FALSE FALSE FALSE FALSE FALSE ...
##  $ lateWorkHours   : logi  FALSE FALSE FALSE FALSE FALSE FALSE ...
##  $ wakeTime        : POSIXct, format: "2024-05-17 06:45:00" "2024-05-17 06:45:00" ...
##  $ hhFromAwake     : num  1.3 1.27 1.27 1.68 1.37 ...
##  $ SQ1             : num  2 1 1 3 2 2 2 1 2 2 ...
##  $ SQ2             : num  3 1 1 3 1 1 2 1 2 1 ...
##  $ SQ3             : num  1 1 1 3 1 1 1 1 2 2 ...
##  $ SQ4             : num  1 1 1 2 1 1 1 1 2 1 ...
##  $ gender          : Factor w/ 2 levels "F","M": 1 1 1 1 1 1 1 1 1 1 ...
##  $ age             : int  59 59 59 59 59 59 59 59 59 59 ...
##  $ BMI             : num  18.8 18.8 18.8 18.8 18.8 ...
##  $ edu             : Factor w/ 2 levels "highschool-",..: 1 1 1 1 1 1 1 1 1 1 ...
##  $ mStatus         : Factor w/ 4 levels "single","partner",..: 2 2 2 2 2 2 2 2 2 2 ...
##  $ home            : Factor w/ 5 levels "alone","partner",..: 3 3 3 3 3 3 3 3 3 3 ...
##  $ children        : Factor w/ 2 levels "No","Yes": 2 2 2 2 2 2 2 2 2 2 ...
##  $ home_child      : Factor w/ 2 levels "No","Yes": 2 2 2 2 2 2 2 2 2 2 ...
##  $ partner         : Factor w/ 2 levels "No","Yes": 2 2 2 2 2 2 2 2 2 2 ...
##  $ home_partner    : Factor w/ 2 levels "No","Yes": 1 1 1 1 1 1 1 1 1 1 ...
##  $ smoker          : Factor w/ 2 levels "No","Yes": 2 2 2 2 2 2 2 2 2 2 ...
##  $ bp_drugs        : Factor w/ 2 levels "No","Yes": 1 1 1 1 1 1 1 1 1 1 ...
##  $ horm_drugs      : Factor w/ 2 levels "No","Yes": 1 1 1 1 1 1 1 1 1 1 ...
##  $ psy_drugs       : Factor w/ 2 levels "No","Yes": 1 1 1 1 1 1 1 1 1 1 ...
##  $ cv_dysf         : Factor w/ 2 levels "No","Yes": 1 1 1 1 1 1 1 1 1 1 ...
##  $ sleep_dysf      : Factor w/ 2 levels "No","Yes": 1 1 1 1 1 1 1 1 1 1 ...
##  $ job             : Factor w/ 22 levels "Administrative and commercial managers",..: 3 3 3 3 3 3 3 3 3 3 ...
##  $ position        : Factor w/ 3 levels "Employee","Manager/Employers",..: 1 1 1 1 1 1 1 1 1 1 ...
##  $ sector          : Factor w/ 2 levels "Private","Public": 1 1 1 1 1 1 1 1 1 1 ...
##  $ weekHours       : num  35 35 35 35 35 35 35 35 35 35 ...
##  $ duwas1          : int  2 2 2 2 2 2 2 2 2 2 ...
##  $ duwas2          : int  4 4 4 4 4 4 4 4 4 4 ...
##  $ duwas3          : int  2 2 2 2 2 2 2 2 2 2 ...
##  $ duwas4          : int  4 4 4 4 4 4 4 4 4 4 ...
##  $ duwas5          : int  2 2 2 2 2 2 2 2 2 2 ...
##  $ duwas6          : int  2 2 2 2 2 2 2 2 2 2 ...
##  $ duwas7          : int  1 1 1 1 1 1 1 1 1 1 ...
##  $ duwas8          : int  2 2 2 2 2 2 2 2 2 2 ...
##  $ duwas9          : int  1 1 1 1 1 1 1 1 1 1 ...
##  $ duwas10         : int  3 3 3 3 3 3 3 3 3 3 ...


Identification

  • ID = participant’s identification code

  • day = day of participation (from 1 to 11)


Compliance

  • aft = day including the response to the Afternoon questionnaire (1) or not (0)

  • eve = day including the response to the Evening questionnaire (1) or not (0)

  • mor = day including the response to the Morning questionnaire (1) or not (0)


Data quality

  • flagTime = responses recoded due to wrong response timing (i.e., responses given outside the scheduled intervals) (see section 3.6.2)

  • flagBP_aft - flagBP_eve = flagged cases that were reprocessed due to extreme BP values (see section 3.2)

  • careless = participant flagged as a careless respondent (careless = TRUE) due to inconsistent responses in the DayOff variables (see section 3.4.1) - the same variable is included in the prelqs dataset


Afternoon questionnaire

  • start_aft = starting time of the Afternoon questionnaire (yyyy-mm-dd hh:mm:ss)

  • end_aft = submission time of the Afternoon questionnaire (yyyy-mm-dd hh:mm:ss)

  • dayOff_aft = logical variable indicating whether the participant reported working on that day (FALSE) or not (TRUE)

  • SBP_aft - DBP_aft = systolic and diastolic aggregate blood pressure value (mmHg) measured in the Afternoon

  • where_aft = place where the Afternoon blood pressure recording was done (“home”, “workplace”, “other”)

  • confounders_aft = logical variable indicating the presence (TRUE) or absence (FALSE) of any confounder before the Afternoon recording

  • coffee_aft - meal_aft = variables indicating the presence (1) or absence (0) of each confounder (i.e., cofee, smoke, sport, and meal)

  • WHLSM1 - WHLSM_6 = item scores at the diary version of the DUWAS (workaholism) (1-7)


Evening questionnaire

  • start_eve = starting time of the Evening questionnaire (yyyy-mm-dd hh:mm:ss)

  • end_eve = submission time of the Evening questionnaire (yyyy-mm-dd hh:mm:ss)

  • dayOff_eve = logical variable indicating whether the participant reported working on that day (FALSE) or not (TRUE)

  • SBP_eve - DBP_eve = systolic and diastolic aggregate blood pressure value (mmHg) measured in the Evening

  • confounders_eve = logical variable indicating the presence (TRUE) or absence (FALSE) of any confounder before the Evening recording

  • coffee_eve - meal_eve = variables indicating the presence (1) or absence (0) of each confounder (i.e., cofee, smoke, sport, and meal)

  • teleWork = factor indicating whether on that day the participant worked in the “office”, did “teleWork”, or “both”

  • workHours = number of working hours for that day (No.)

  • dailyHassless_eve = factor indicating whether the participant reported some daily hassles outside the working time on that day (“Yes”) or not (“No”)

  • EE1 - EE4 = item scores at the diary version of the Copenhagen Burnout Inventory (emotional exhaustion) (1-7)

  • R.det1 - R.det3 = item scores at the diary version of the Recovery Experiences Questionnaire (psychological detachment) (1-7)


Morning questionnaire

  • start_mor = starting time of the Morning questionnaire (yyyy-mm-dd hh:mm:ss)

  • end_mor = submission time of the Morning questionnaire (yyyy-mm-dd hh:mm:ss)

  • dayOffyesterday = logical variable indicating whether the participant reported working on the previous day day (FALSE) or not (TRUE)

  • lateWorkHours = logical variable indicating whether the participant reported working in the previous evening (TRUE) or not (FALSE)

  • wakeTime = self-reported waking time (yyyy-mm-dd hh:mm:ss)

  • hhFromAwake = number of hours between waketime and the response to the Morning questionnaire

  • SQ - SQ4 = item scores at the diary version of the Mini Sleep Questionnaire (sleep disturbances) (1-7)


Retrospective time-invariant variables (measured with the preliminary questionnaire)

Demographics

  • gender = participant’s gender (“F” or “M”)

  • age = participant’s age (years)

  • BMI = participant’s body mass index (kg/m^2)

  • edu = participant’s education level (“middle”, “highschool”, “university+”)

  • mStatus = participant’s marital status (“single”, “partner”, “divorced”, “widowed”)

  • home = family situation (living “alone” or with “partner”, “children”, “parents”, “others”)

  • children = number of children (No.)

  • home_child = living with children (Yes/No)

  • partner = having a partner (Yes/No)

  • home_partner = living with partner (Yes/No)

Confounders and inclusion criteria

  • smoker = smoking status (“No”, “Yes”, “Quit_less”, “Quit_more”)

  • bp_drugs = participant reporting taking blood pressure medications (e.g., diuretics, beta-blokkants, anti-hypertension)

  • horm_drugs = participant reporting taking hormonal medications (e.g., birth control)

  • psy_drugs = participant reporting taking psychiatric drugs (e.g., antidepressants, anxiety)

  • cv_dysf = participant reporting suffering from a cardiovascular disease (e.g., hypertension, ischemia, strokes)

  • sleep_dysf = participant reporting suffering from a sleep-related disease (e.g., insomnia, parasomnia, sleep apnea)

Occupational variables

  • job = participant’s job recoded using the ISCO-08 classification of occupations (level 2) (Ganzeboom, 2010

  • position = participant’s job position (“Employee”, “Project”, “Manager”, “(Self-)Employer”)

  • sector = participant’s job sector (“Private” or “Public”)

  • weekHours = participant’s self-reported mean number of working hours per week (No.)


6. Data export

Here, we export the recoded and pre-processed diary_wide dataset (renamed as diary) to be used for further analyses. The datasets is exported in both CSV and RData format.

# exporting diary data
diary <- diary_wide # renamed as 'diary'
save(diary,file="DATI/diary_processed.RData") # RData
write.csv2(diary,file="DATI/diary_processed.csv", row.names=FALSE) # csv with ";"


References

  • Ganzeboom, H. B. (2010). International standard classification of occupations ISCO-08 with ISEI-08 scores. Version of July, 27, 2010. Available from this link.

R packages

Auguie, Baptiste. 2017. gridExtra: Miscellaneous Functions for "Grid" Graphics. https://CRAN.R-project.org/package=gridExtra.
Bache, Stefan Milton, and Hadley Wickham. 2022. Magrittr: A Forward-Pipe Operator for r. https://CRAN.R-project.org/package=magrittr.
Dowle, Matt, and Arun Srinivasan. 2023. Data.table: Extension of ‘Data.frame‘. https://CRAN.R-project.org/package=data.table.
Grolemund, Garrett, and Hadley Wickham. 2011. “Dates and Times Made Easy with lubridate.” Journal of Statistical Software 40 (3): 1–25. https://www.jstatsoft.org/v40/i03/.
Kouretsis, Alexandros, Andreas Bampouris, Petros Morfiris, and Konstantinos Papageorgiou. 2020. labourR: Classify Multilingual Labour Market Free-Text to Standardized Hierarchical Occupations. https://github.com/AleKoure/labourR.
R Core Team. 2023. R: A Language and Environment for Statistical Computing. Vienna, Austria: R Foundation for Statistical Computing. https://www.R-project.org/.
Spinu, Vitalie, Garrett Grolemund, and Hadley Wickham. 2023. Lubridate: Make Dealing with Dates a Little Easier. https://CRAN.R-project.org/package=lubridate.
Wickham, Hadley. 2011. “The Split-Apply-Combine Strategy for Data Analysis.” Journal of Statistical Software 40 (1): 1–29. https://www.jstatsoft.org/v40/i01/.
———. 2016. Ggplot2: Elegant Graphics for Data Analysis. Springer-Verlag New York. https://ggplot2.tidyverse.org.
———. 2022. Plyr: Tools for Splitting, Applying and Combining Data. https://CRAN.R-project.org/package=plyr.
Wickham, Hadley, Winston Chang, Lionel Henry, Thomas Lin Pedersen, Kohske Takahashi, Claus Wilke, Kara Woo, Hiroaki Yutani, and Dewey Dunnington. 2023. Ggplot2: Create Elegant Data Visualisations Using the Grammar of Graphics. https://CRAN.R-project.org/package=ggplot2.
LS0tDQp0aXRsZTogIlRoZSBkYWlseSBjb3N0cyBvZiB3b3JrYWhvbGlzbSINCnN1YnRpdGxlOiAiU3VwcGxlbWVudGFyeSBtYXRlcmlhbCBTMzogRGF0YSBwcmUtcHJvY2Vzc2luZyINCmF1dGhvcjogICJMdWNhIE1lbmdoaW5pLCBQaC5ELiwgQ3Jpc3RpYW4gQmFsZHVjY2ksIFBoLkQuIg0KZGF0ZTogImByIFN5cy5EYXRlKClgIg0KYmlibGlvZ3JhcGh5OiBbcGFja2FnZXNQcm9jLmJpYl0NCm5vY2l0ZTogJ0AqJw0Kb3V0cHV0Og0KICBodG1sX2RvY3VtZW50Og0KICAgIGRmX3ByaW50OiBwYWdlZA0KICAgIHRvYzogdHJ1ZQ0KICAgIHRvY19mbG9hdDogdHJ1ZQ0KICAgIHRvY19kZXB0aDogNA0KICAgIGNzczogc3R5bGVzLmNzcw0KICAgIGNvZGVfZG93bmxvYWQ6IHRydWUNCiAgcGRmX2RvY3VtZW50OiBkZWZhdWx0DQogIHdvcmRfZG9jdW1lbnQ6IGRlZmF1bHQNCiAgdGhlbWU6IHVuaXRlZA0KLS0tDQoNCmBgYHtyIHNldHVwLCBpbmNsdWRlPUZBTFNFfQ0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KGVjaG8gPSBUUlVFKQ0KYGBgDQoNCjxicj4NCg0KIyBBaW1zIGFuZCBjb250ZW50DQoNClRoZSBwcmVzZW50IGRvY3VtZW50IGluY2x1ZGVzIHRoZSBwcmUtcHJvY2Vzc2luZyBzdGVwcyB0byByZWFkIHRoZSBpbnRlbnNpdmUgbG9uZ2l0dWRpbmFsIGRhdGEgY29sbGVjdGVkIHdpdGggdGhlIFF1YWx0cmljcyBwbGF0Zm9ybSAoUXVhbHRyaWNzLCBTZWF0dGxlLCBXQSwgVVNBKSBhbmQgcHJlcGFyZSB0aGVtIGZyb20gdGhlIGFuYWx5c2VzLiBUaGUgZGF0YSB3ZXJlIGNvbGxlY3RlZCBmcm9tIGEgc2FtcGxlIG9mIGZ1bGwtdGltZSB3b3JrZXJzIChtYWlubHkgb2ZmaWNlDQp3b3JrZXJzKSB0aGF0IHJlc3BvbmRlZCB0byBhIHByZWxpbWluYXJ5IHF1ZXN0aW9ubmFpcmUgYHByZWxxc2AgZm9sbG93ZWQgYnkgYSBvbmUtIG9yIHR3by13ZWVrIGRhaWx5IGRpYXJ5IHByb3RvY29sIGBkaWFyeWAuDQoNCkhlcmUsIHdlIHJlbW92ZSBhbGwgb2JqZWN0cyBmcm9tIHRoZSBSIGdsb2JhbCBlbnZpcm9ubWVudCwgYW5kIHdlIHNldCB0aGUgc3lzdGVtIHRpbWUgem9uZS4NCg0KYGBgIHtyfQ0KIyByZW1vdmluZyBhbGwgb2JqZXRzIGZyb20gdGhlIHdvcmtzcGFjZQ0Kcm0obGlzdD1scygpKQ0KDQojIHNldHRpbmcgc3lzdGVtIHRpbWUgem9uZSB0byBHTVQgKGZvciBjb25zaXN0ZW50IHRlbXBvcmFsIHN5bmNocm9uaXphdGlvbikNClN5cy5zZXRlbnYodHo9IkdNVCIpDQpgYGANCg0KVGhlIGZvbGxvd2luZyBSIHBhY2thZ2VzIGFyZSB1c2VkIGluIHRoaXMgZG9jdW1lbnQgKHNlZSBbUmVmZXJlbmNlc10oI3JlZikgc2VjdGlvbik6DQoNCmBgYCB7cn0NCiMgcmVxdWlyZWQgcGFja2FnZXMNCnBhY2thZ2VzIDwtIGMoImx1YnJpZGF0ZSIsImdncGxvdDIiLCJncmlkRXh0cmEiLCJwbHlyIiwibGFib3VyUiIsImRhdGEudGFibGUiLCJtYWdyaXR0ciIpDQoNCiMgZ2VuZXJhdGUgcGFja2FnZXMgcmVmZXJlbmNlcw0Ka25pdHI6OndyaXRlX2JpYihjKC5wYWNrYWdlcygpLCBwYWNrYWdlcyksInBhY2thZ2VzUHJvYy5iaWIiKQ0KDQojICMgcnVuIHRvIGluc3RhbGwgbWlzc2luZyBwYWNrYWdlcw0KIyB4ZnVuOjpwa2dfYXR0YWNoMihwYWNrYWdlcywgbWVzc2FnZSA9IEZBTFNFKTsgcm0obGlzdD1scygpKQ0KYGBgDQoNCjxicj4NCg0KIyAxLiBEYXRhIHJlYWRpbmcNCg0KRmlyc3QsIHdlIHJlYWQgKipwcmVsaW1pbmFyeSBxdWVzdGlvbm5haXJlKiogYHByZWxxc2AgZGF0YSBleHBvcnRlZCBmcm9tIFF1YWx0cmljcyAoYXZhaWxhYmxlIHVwb24gcmVxdWVzdCB0byB0aGUgbWFpbiBhdXRob3IpLg0KDQpgYGAge3J9DQojIGxvYWRpbmcgcHJlbGltaW5hcnkgcXVlc3Rpb25uYWlyZSBkYXRhc2V0IChza2lwcGluZyBmaXJzdCB0d28gbGluZXMgaW5jbHVkaW5nIHVudXNlZnVsIGluZm9ybWF0aW9uKSkNCnByZWxxcyA8LSByZWFkLmNzdigiREFUSS9XSExTTTIwMjEgLSBwcmVsUVMuY3N2IiwgDQogICAgICAgICAgICAgICAgICAgbmEuc3RyaW5ncz0iIilbMzpucm93KHJlYWQuY3N2KCJEQVRJL1dITFNNMjAyMSAtIHByZWxRUy5jc3YiKSksXQ0KDQojIHJlbW92aW5nIDEgY2FzZSB3aXRoIG1pc3NpbmcgdmFsdWVzIHRvIGFsbCBpdGVtcw0KcHJlbHFzIDwtIHByZWxxc1shaXMubmEocHJlbHFzJGdlbmRlciksXQ0KDQojIHJlbW92aW5nIDEgY2FzZSB3aXRoIG5vIGUtbWFpbCBhZGRyZXNzIChpLmUuLCBubyBpZGVudGlmaWNhdGlvbiBjb2RlKQ0KcHJlbHFzIDwtIHByZWxxc1shaXMubmEocHJlbHFzJFJlY2lwaWVudEVtYWlsKSxdDQpgYGANCg0KPGJyPg0KDQpTZWNvbmQsIHdlIHJlYWQgdGhlIGBkaWFyeWAgZGF0YXNldHMgZXhwb3J0ZWQgZnJvbSBRdWFsdHJpY3MgYXMgQ1NWIGZpbGVzIHdpdGggbnVtZXJpYyB2YWx1ZXMgKGF2YWlsYWJsZSB1cG9uIHJlcXVlc3QgdG8gdGhlIG1haW4gYXV0aG9yKS4gQSBzZXBhcmF0ZSBkaWFyeSBzdXJ2ZXkgKHJlc3VsdGluZyBpbiBhIHNlcGFyYXRlIGRhdGFzZXQpIHdhcyB1c2VkIGZvciBhZnRlcm5vb24gYF9hYCwgZXZlbmluZyBgX2VgLCBhbmQgbW9ybmluZyBgX21gIGRpYXJpZXMsIHJlc3BlY3RpdmVseS4gTW9yZW92ZXIsIGEgc2VwYXJhdGUgc3VydmV5IHdhcyB1c2VkIGZvciBTYXR1cmRheSBtb3JuaW5nIChgX21fc2F0YCksIGFuZCBzdXJ2ZXlzIHNvbWV0aW1lcyAoaS5lLiwgaW4gY2FzZSBvZiB0ZWNoaWNhbCBwcm9ibGVtcyB3aXRoIHRoZSBzbWFydHBob25lcyksIHRoZXkgYWRtaW5pc3RlcmVkIGJ5IHNlbmRpbmcgYW5vbnltaXplZCBsaW5rcyBpbmNsdWRpbmcgYW4gZS1tYWlsIGZpZWxkOiBgX21haWxgLg0KDQpgYGAge3J9DQojIGxvYWRpbmcgZGlhcnkgZGF0YXNldHMNCmRpYXJ5X2EgPC0gcmVhZC5jc3YoIkRBVEkvV0VFSzQwL1dITFNNMjAyMV9EaWFyeUFmdGVybm9vbi5jc3YiLA0KICAgICAgICAgICAgICAgICAgICBuYS5zdHJpbmdzPSIiKVszOm5yb3cocmVhZC5jc3YoIkRBVEkvV0VFSzQwL1dITFNNMjAyMV9EaWFyeUFmdGVybm9vbi5jc3YiKSksXSAjIGRpYXJ5X2EgPSBBZnRlcm5vb24gKGFmdGVyIHdvcmspDQpkaWFyeV9lIDwtIHJlYWQuY3N2KCJEQVRJL1dFRUs0MC9XSExTTTIwMjFfRGlhcnlFdmVuaW5nLmNzdiIsDQogICAgICAgICAgICAgICAgICAgIG5hLnN0cmluZ3M9IiIpWzM6bnJvdyhyZWFkLmNzdigiREFUSS9XRUVLNDAvV0hMU00yMDIxX0RpYXJ5RXZlbmluZy5jc3YiKSksXSAjIGRpYXJ5X2UgPSBFdmVuaW5nIChiZWR0aW1lKQ0KZGlhcnlfbSA8LSByZWFkLmNzdigiREFUSS9XRUVLNDAvV0hMU00yMDIxX0RpYXJ5TW9ybmluZy5jc3YiLCANCiAgICAgICAgICAgICAgICAgICAgbmEuc3RyaW5ncz0iIilbMzpucm93KHJlYWQuY3N2KCJEQVRJL1dFRUs0MC9XSExTTTIwMjFfRGlhcnlNb3JuaW5nLmNzdiIpKSxdICMgZGlhcnlfbSA9IE1vcm5pbmcgKGJlZm9yZSB3b3JrKQ0KZGlhcnlfbV9zYXQgPC0gcmVhZC5jc3YoIkRBVEkvV0VFSzQwL1dITFNNMjAyMV9EaWFyeU1vcm5pbmdfc2F0LmNzdiIsDQogICAgICAgICAgICAgICAgICAgIG5hLnN0cmluZ3M9IiIpWzM6bnJvdyhyZWFkLmNzdigiREFUSS9XRUVLNDAvV0hMU00yMDIxX0RpYXJ5TW9ybmluZ19zYXQuY3N2IikpLF0gIyBkaWFyeV9tX3NhdCA9IFNhdHVyZGF5IE1vcm5pbmcNCg0KIyBsb2FkaW5nIGRpYXJ5IGRhdGFzZXRzIHdpdGggZS1tYWlsIGZpZWxkICh1c2VkIGluIGNhc2VzIG9mIHRlY2huaWNhbCBwcm9ibGVtcykNCmRpYXJ5X21fbWFpbCA8LSByZWFkLmNzdigiREFUSS9XRUVLNDAvV0hMU00yMDIxX0RpYXJ5TW9ybmluZ19tYWlsLmNzdiIsDQogICAgICAgICAgICAgICAgICAgICAgICAgbmEuc3RyaW5ncz0iIilbMzpucm93KHJlYWQuY3N2KCJEQVRJL1dFRUs0MC9XSExTTTIwMjFfRGlhcnlNb3JuaW5nX21haWwuY3N2IikpLF0NCmRpYXJ5X2FfbWFpbCA8LSByZWFkLmNzdigiREFUSS9XRUVLNDAvV0hMU00yMDIxX0RpYXJ5QWZ0ZXJub29uX21haWwuY3N2IiwNCiAgICAgICAgICAgICAgICAgICAgICAgICBuYS5zdHJpbmdzPSIiKVszOm5yb3cocmVhZC5jc3YoIkRBVEkvV0VFSzQwL1dITFNNMjAyMV9EaWFyeUFmdGVybm9vbl9tYWlsLmNzdiIpKSxdDQpkaWFyeV9lX21haWwgPC0gcmVhZC5jc3YoIkRBVEkvV0VFSzQwL1dITFNNMjAyMV9EaWFyeUV2ZW5pbmdfbWFpbC5jc3YiLA0KICAgICAgICAgICAgICAgICAgICAgICAgIG5hLnN0cmluZ3M9IiIpWzM6bnJvdyhyZWFkLmNzdigiREFUSS9XRUVLNDAvV0hMU00yMDIxX0RpYXJ5RXZlbmluZ19tYWlsLmNzdiIpKSxdDQpkaWFyeV9tX3NhdF9tYWlsIDwtIHJlYWQuY3N2KCJEQVRJL1dFRUs0MC9XSExTTTIwMjFfRGlhcnlNb3JuaW5nX3NhdF9tYWlsLmNzdiIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5hLnN0cmluZ3M9IiIpWzM6bnJvdyhyZWFkLmNzdigiREFUSS9XRUVLNDAvV0hMU00yMDIxX0RpYXJ5TW9ybmluZ19zYXRfbWFpbC5jc3YiKSksXQ0KYGBgDQoNCjxicj4NCg0KIyAyLiBEYXRhIHJlY29kaW5nDQoNClNlY29uZCwgd2UgcmVjb2RlIHRoZSB0d28gZGF0YXNldHMgYnkgcmVtb3ZpbmcgdW51c2VmdWwgY29sdW1ucywgYnkgcmUtc2V0dGluZyB2YXJpYWJsZSBsYWJlbHMgYW5kIGNsYXNzZXMsIGJ5IHJlbmFtaW5nIHJlbGV2YW50IGNvbHVtbnMsIGFuZCBieSBtZXJnaW5nIHRoZSBgZGlhcnlgIGRhdGFzZXRzLg0KDQojIyAyLjEuIFByZWxpbWluYXJ5IHF1ZXN0aW9ubmFpcmUNCg0KSGVyZSwgd2UgcmVtb3ZlIHRoZSB1bnVzZWZ1bCBjb2x1bW5zLCBhbmQgd2UgcmVuYW1lIGFuZCBzb3J0IHRoZSByZWxldmFudCBjb2x1bW5zIG9mIHRoZSBgcHJlbHFzYCBkYXRhc2V0Lg0KYGBgIHtyfQ0KIyByZW1vdmluZyB1bnVzZWZ1bCBjb2x1bW5zDQpwcmVscXNbLGMoIlN0YXR1cyIsIklQQWRkcmVzcyIsIlByb2dyZXNzIiwiRHVyYXRpb24uLmluLnNlY29uZHMuIiwiRmluaXNoZWQiLCJSZWNvcmRlZERhdGUiLCJSZXNwb25zZUlkIiwNCiAgICAgICAgICAiUmVjaXBpZW50TGFzdE5hbWUiLCJSZWNpcGllbnRGaXJzdE5hbWUiLCJMb2NhdGlvbkxhdGl0dWRlIiwiTG9jYXRpb25Mb25naXR1ZGUiLA0KICAgICAgICAgICJEaXN0cmlidXRpb25DaGFubmVsIiwiVXNlckxhbmd1YWdlIiwiY29uc2VudCIpXSA8LSBOVUxMDQoNCiMgcmVuYW1pbmcgdmFyaWFibGVzDQpjb2xuYW1lcyhwcmVscXMpWzE6NF0gPC0gYygic3RhcnQiLCJlbmQiLCJJRCIsInJlY3J1aXRlci5JRCIpICMgcGFydGljaXBhbnQncyBpZGVudGlmaWVyIChlLW1haWwpDQpjb2xuYW1lcyhwcmVscXMpWzE6d2hpY2goY29sbmFtZXMocHJlbHFzKT09ImNoaWxkcmVuXzEiKV0gPC0gIyByZW1vdmluZyBxdWVzdGlvbiBudW1iZXJzIGZyb20gY29sdW1uIG5hbWVzDQogIGdzdWIoIl80IiwiIixnc3ViKCJfMSIsIiIsY29sbmFtZXMocHJlbHFzKVsxOndoaWNoKGNvbG5hbWVzKHByZWxxcyk9PSJjaGlsZHJlbl8xIildKSkNCmNvbG5hbWVzKHByZWxxcylbd2hpY2goc3Vic3RyKGNvbG5hbWVzKHByZWxxcyksMSwyKT09IkVYIildIDwtIHBhc3RlKCJFWCIsMTo3LHNlcD0iXyIpICMgcmVjb2RpbmcgcXVlc3Rpb24gbnVtYmVycyBmb3IgRVggc2NhbGUNCmBgYA0KDQo8YnI+DQoNClRoZW4sIHdlIGNoYW5nZSB0aGUgY2xhc3NlcyBvZiB0aGUgcmVsZXZhbnQgdmFyaWFibGVzIGJ5IGNvbnZlcnRpbmcgZGF0ZXMgYXMgYFBPU0lYY3RgICh0aGUgUiBmb3JtYXQgZm9yIGRhdGVzIGFuZCB0aW1lcyksIGNhdGVnb3JpY2FsIHZhcmlhYmxlcyBhcyBgZmFjdG9yYCwgYW5kIHF1YW50aXRhdGl2ZSB2YXJpYWJsZXMgYXMgYGludGVnZXJgIG9yIGBudW1lcmljYC4NCmBgYCB7cn0NCiMgdGltZSAoUE9TSVhjdCB2YXJpYWJsZXMpOiBzdGFydCwgZW5kDQpwcmVscXMkc3RhcnQgPC0gYXMuUE9TSVhjdChwcmVscXMkc3RhcnQpDQpwcmVscXMkZW5kIDwtIGFzLlBPU0lYY3QocHJlbHFzJGVuZCkNCg0KIyBpbnRlZ2VyOiBhZ2UsIFdITFNNLCBXQSwgT0MsIFdFLCBFWCwgV0wsIFdGQywgT1dDLCBUUywgTkENCnByZWxxc1ssYyh3aGljaChjb2xuYW1lcyhwcmVscXMpPT0iYWdlIiksd2hpY2goY29sbmFtZXMocHJlbHFzKT09IldITFNNXzEiKTp3aGljaChjb2xuYW1lcyhwcmVscXMpPT0iTkFfNCIpKV0gPC0NCiAgbGFwcGx5KHByZWxxc1ssYyh3aGljaChjb2xuYW1lcyhwcmVscXMpPT0iYWdlIiksd2hpY2goY29sbmFtZXMocHJlbHFzKT09IldITFNNXzEiKTp3aGljaChjb2xuYW1lcyhwcmVscXMpPT0iTkFfNCIpKV0sYXMuaW50ZWdlcikNCg0KIyBudW1lcmljOiB3ZWVrSG91cnMsIHdlZWtIb3Vyc19yZW1vdGUNCmNvbG5hbWVzKHByZWxxcylbd2hpY2goc3Vic3RyKGNvbG5hbWVzKHByZWxxcyksMSw0KT09IndlZWsiKV0gPC0gYygid2Vla0hvdXJzIiwid2Vla0hvdXJzX3JlbW90ZSIpDQpwcmVscXNbLGMoIndlaWdodCIsImhlaWdodCIsIndlZWtIb3VycyIsIndlZWtIb3Vyc19yZW1vdGUiKV0gPC0NCiAgbGFwcGx5KHByZWxxc1ssYygid2VpZ2h0IiwiaGVpZ2h0Iiwid2Vla0hvdXJzIiwid2Vla0hvdXJzX3JlbW90ZSIpXSxhcy5udW1lcmljKQ0KDQojIGZhY3RvcnM6IGFsbCBvdGhlciB2YXJpYWJsZXMNCnByZWxxc1ssYygicmVjcnVpdGVyLklEIiwiZ2VuZGVyIiwiZWR1IiwibVN0YXR1cyIsImhvbWUiLCJjaGlsZHJlbiIsInNtb2tlciIsImRydWdzXzEiLCJkcnVnc18yIiwiZHJ1Z3NfMyIsDQogICAgICAgICAgImRpc2Z1bmN0aW9uc18xIiwiZGlzZnVuY3Rpb25zXzIiLCJwb3NpdGlvbiIsInNlY3RvciIpXSA8LQ0KICBsYXBwbHkocHJlbHFzWyxjKCJyZWNydWl0ZXIuSUQiLCJnZW5kZXIiLCJlZHUiLCJtU3RhdHVzIiwiaG9tZSIsImNoaWxkcmVuIiwic21va2VyIiwiZHJ1Z3NfMSIsImRydWdzXzIiLCJkcnVnc18zIiwNCiAgICAgICAgICAgICAgICAgICAiZGlzZnVuY3Rpb25zXzEiLCJkaXNmdW5jdGlvbnNfMiIsInBvc2l0aW9uIiwic2VjdG9yIildLGFzLmZhY3RvcikNCmBgYA0KDQo8YnI+DQoNCldlIGFsc28gcmVjb2RlIHRoZSBsZXZlbHMgYW5kIHZhbHVlcyBvZiBzb2Npb2RlbW9ncmFwaGljIHZhcmlhYmxlcyBhcyB3ZSBwcmVyZWdpc3RlcmVkIChzZWUgW3ByZXJlZ2lzdHJhdGlvbiBoZXJlXShodHRwczovL29zZi5pby9oOXp2cSkpLg0KYGBgIHtyfQ0KIyBnZW5kZXI6IEYsIE0sIChPdGhlcikNCnByZWxxcyRnZW5kZXIgPC0gYXMuZmFjdG9yKGdzdWIoIjEiLCJNIixnc3ViKCIyIiwiRiIsZ3N1YigiMyIsIk90aGVyIixwcmVscXMkZ2VuZGVyKSkpKQ0KaWYobmxldmVscyhwcmVscXMkZ2VuZGVyKT09Mil7IGNhdCgiUmVjb2RpbmcgYXMgTS9GIHNpbmNlIG5vYm9keSBjaG9zZSBnZW5kZXI9J090aGVyJyIpIA0KICBwcmVscXMkZ2VuZGVyIDwtIGZhY3RvcihwcmVscXMkZ2VuZGVyLGxldmVscz1jKCJGIiwiTSIpKSB9DQoNCiMgZWR1Y2F0aW9uOiBoaWdoc2Nob29sIG9yIGxvd2VyIHZzLiB1bml2ZXJzaXR5IG9yIGhpZ2hlcg0KcHJlbHFzJGVkdSA8LSBhcy5mYWN0b3IoZ3N1YigiMSIsImhpZ2hzY2hvb2wtIixnc3ViKCIyIiwiaGlnaHNjaG9vbC0iLGdzdWIoIjMiLCJ1bml2ZXJzaXR5KyIscHJlbHFzJGVkdSkpKSkNCg0KIyBjaGlsZHJlbjogeWVzL25vDQpwcmVscXNbcHJlbHFzJGNoaWxkcmVuIT0wLCJjaGlsZHJlbiJdIDwtIDENCnByZWxxcyRjaGlsZHJlbiA8LSBhcy5mYWN0b3IoZ3N1YigiMCIsIk5vIixnc3ViKCIxIiwiWWVzIixwcmVscXMkY2hpbGRyZW4pKSkgIyBoYXZpbmcgYSBjaGlsZHJlbg0KDQojIGhvbWUgc2l0dWF0aW9uOiBhbG9uZSwgcGFydG5lciwgY2hpbGRyZW4sIHBhcmVudHMsIG90aGVycw0KcHJlbHFzJGhvbWUgPC0gZ3N1YigiMSIsInBhcnRuZXIiLGdzdWIoIjIiLCJwYXJlbnRzIixnc3ViKCIzIiwiY2hpbGRyZW4iLGdzdWIoIjQiLCJhbG9uZSIsZ3N1YigiNSIsIm90aGVycyIscHJlbHFzJGhvbWUpKSkpKQ0KcHJlbHFzJGhvbWUgPC0gZmFjdG9yKGdzdWIoInBhcnRuZXIsYWxvbmUiLCJwYXJ0bmVyIiwgIyBwYXJ0bmVyIGFuZCBhbG9uZSA9IHBhcnRuZXINCiAgICAgICAgICAgICAgICAgICAgICAgICAgIGdzdWIoInBhcnRuZXIsb3RoZXJzIiwicGFydG5lciIsICMgcGFydG5lciBhbmQgb3RoZXJzID0gcGFydG5lcg0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBnc3ViKCJwYXJ0bmVyLGNoaWxkcmVuIiwiY2hpbGRyZW4iLCAjIGlmIGNoaWxkcmVuID0gY2hpbGRyZW4NCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBnc3ViKCJhbG9uZSxvdGhlcnMiLCJvdGhlcnMiLCAjIGFsb25lIGFuZCBvdGhlcnMgPSBvdGhlcnMNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdzdWIoInBhcnRuZXIscGFyZW50cyIsInBhcnRuZXIiLHByZWxxcyRob21lKSkpKSksICMgcGFydG5lciBhbmQgcGFyZW50cyA9IHBhcnRuZXINCiAgICAgICAgICAgICAgICAgICAgICBsZXZlbHM9YygiYWxvbmUiLCJwYXJ0bmVyIiwiY2hpbGRyZW4iLCJwYXJlbnRzIiwib3RoZXJzIikpIA0KDQojIGNoaWxkcmVuIGluIHRoZSBob3VzZWhvbGQ6IHllcy9ubw0KcHJlbHFzJGhvbWVfY2hpbGQgPC0gYXMuZmFjdG9yKGdzdWIoImFsb25lIiwiTm8iLCAjIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBnc3ViKCJwYXJ0bmVyIiwiTm8iLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdzdWIoImNoaWxkcmVuIiwiWWVzIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdzdWIoInBhcmVudHMiLCJObyIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdzdWIoIm90aGVycyIsIk5vIixwcmVscXMkaG9tZSkpKSkpKQ0KDQojIG1hcml0YWwgc3RhdHVzOiBzaW5nbGUsIHBhcnRuZXIsIGRpdm9yY2VkLCB3aWRvd2VkDQpwcmVscXMkbVN0YXR1cyA8LSBmYWN0b3IoZ3N1YigiMSIsInNpbmdsZSIsZ3N1YigiMiIsInBhcnRuZXIiLGdzdWIoIjMiLCJkaXZvcmNlZCIsZ3N1YigiNCIsIndpZG93ZWQiLHByZWxxcyRtU3RhdHVzKSkpKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICBsZXZlbHM9Yygic2luZ2xlIiwicGFydG5lciIsImRpdm9yY2VkIiwid2lkb3dlZCIpKQ0KDQojIGhhdmluZyBhIHBhcnRuZXINCnByZWxxcyRwYXJ0bmVyIDwtIGFzLmZhY3Rvcihnc3ViKCJzaW5nbGUiLCJObyIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdzdWIoInBhcnRuZXIiLCJZZXMiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdzdWIoImRpdm9yY2VkIiwiTm8iLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZ3N1Yigid2lkb3dlZCIsIk5vIixwcmVscXMkbVN0YXR1cykpKSkpIA0KDQojIGxpdmluZyB3aXRoIHBhcnRuZXINCnByZWxxcyRob21lX3BhcnRuZXIgPC0gYXMuZmFjdG9yKGdzdWIoImFsb25lIiwiTm8iLCAjIGxpdmluZyB3aXRoIHBhcnRuZXINCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBnc3ViKCJwYXJ0bmVyIiwiWWVzIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdzdWIoImNoaWxkcmVuIiwiTm8iLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBnc3ViKCJwYXJlbnRzIiwiTm8iLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdzdWIoIm90aGVycyIsIk5vIixwcmVscXMkaG9tZSkpKSkpKQ0KDQojIHNtb2tpbmcgc3RhdHVzOiBZZXMvTm8NCnByZWxxcyRzbW9rZXIgPC0gZmFjdG9yKGdzdWIoIjEiLCJZZXMiLGdzdWIoIjIiLCJRdWl0X2xlc3MiLGdzdWIoIjMiLCJRdWl0X21vcmUiLGdzdWIoIjQiLCJObyIscHJlbHFzJHNtb2tlcikpKSksDQogICAgICAgICAgICAgICAgICAgICAgICBsZXZlbHM9YygiTm8iLCJZZXMiLCJRdWl0X2xlc3MiLCJRdWl0X21vcmUiKSkNCnByZWxxcyRzbW9rZXIgPC0gYXMuZmFjdG9yKGdzdWIoIlF1aXRfbGVzcyIsIlllcyIsZ3N1YigiUXVpdF9tb3JlIiwiTm8iLHByZWxxcyRzbW9rZXIpKSkNCg0KIyBkcnVncy9tZWRpY2F0aW9ucw0KY29sbmFtZXMocHJlbHFzKVt3aGljaChzdWJzdHIoY29sbmFtZXMocHJlbHFzKSwxLDUpPT0iZHJ1Z3MiKV0gPC0gYygiYnBfZHJ1Z3MiLCJob3JtX2RydWdzIiwicHN5X2RydWdzIikgIyBkcnVncy9tZWRpY2F0aW9ucw0KcHJlbHFzJGJwX2RydWdzIDwtIGFzLmZhY3Rvcihnc3ViKCIxIiwiWWVzIixnc3ViKCIyIiwiTm8iLHByZWxxcyRicF9kcnVncykpKQ0KcHJlbHFzJGhvcm1fZHJ1Z3MgPC0gYXMuZmFjdG9yKGdzdWIoIjEiLCJZZXMiLGdzdWIoIjIiLCJObyIscHJlbHFzJGhvcm1fZHJ1Z3MpKSkNCnByZWxxcyRwc3lfZHJ1Z3MgPC0gYXMuZmFjdG9yKGdzdWIoIjEiLCJZZXMiLGdzdWIoIjIiLCJObyIscHJlbHFzJHBzeV9kcnVncykpKQ0KDQojIGNhcmRpb3Zhc2N1bGFyIGFuZCBzbGVlcCBkeXNmdW5jdGlvbnMNCmNvbG5hbWVzKHByZWxxcylbd2hpY2goc3Vic3RyKGNvbG5hbWVzKHByZWxxcyksMSw1KT09ImRpc2Z1IildIDwtIGMoImN2X2R5c2YiLCJzbGVlcF9keXNmIikNCnByZWxxcyRjdl9keXNmIDwtIGFzLmZhY3Rvcihnc3ViKCIxIiwiWWVzIixnc3ViKCIyIiwiTm8iLHByZWxxcyRjdl9keXNmKSkpDQpwcmVscXMkc2xlZXBfZHlzZiA8LSBhcy5mYWN0b3IoZ3N1YigiMSIsIlllcyIsZ3N1YigiMiIsIk5vIixwcmVscXMkc2xlZXBfZHlzZikpKQ0KDQojIGpvYiBwb3NpdGlvbjogZW1wbG95ZWUgb3IgcHJvamVjdCB2cy4gbWFuYWdlciBvciBzZWxmLWVtcGxveWVkL2VtcGxveWVyDQpwcmVscXMkcG9zaXRpb24gPC0gZmFjdG9yKGdzdWIoIjEiLCJNYW5hZ2VyL0VtcGxveWVycyIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZ3N1YigiMiIsIkVtcGxveWVlIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdzdWIoIjMiLCJNYW5hZ2VyL0VtcGxveWVycyIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdzdWIoIjQiLCJQcm9qZWN0IiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwcmVscXMkcG9zaXRpb24pKSkpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICBsZXZlbHM9YygiRW1wbG95ZWUiLCJNYW5hZ2VyL0VtcGxveWVycyIsIlByb2plY3QiKSkNCg0KIyBqb2Igc2VjdG9yOiBwdWJsaWMgdnMuIHByaXZhdGUNCnByZWxxcyRzZWN0b3IgPC0gYXMuZmFjdG9yKGdzdWIoIjEiLCJQdWJsaWMiLGdzdWIoIjIiLCJQcml2YXRlIixwcmVscXMkc2VjdG9yKSkpDQoNCiMgcmVtb3RlUGxhY2UgKG9wZW4tZW5kZWQgcXVlc3Rpb24gLT4gbWFraW5nIGl0IGNhdGVnb3JpY2FsKQ0KcHJlbHFzJHJlbW90ZVBsYWNlIDwtIGZhY3Rvcihnc3ViKCJjYXNhIiwiaG9tZSIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZ3N1YigiYWNhc2EiLCJjYXNhIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdzdWIoImRhY2FzYSIsImNhc2EiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBnc3ViKCJhY2FzYS9pbmNvLXdvIiwiY2FzYSIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZ3N1Yigic3R1ZGlvYXVzbCIsInN0dWRpbyIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBnc3ViKCJ1ZmZpY2lvIiwic3R1ZGlvIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZ3N1Yigib3NwZWRhbGUiLCJzdHVkaW8iLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdzdWIoIm9mZmljaW5hIiwic3R1ZGlvIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdzdWIoImluc3R1ZGlvaW52aWRlb2NhbGwiLCJzdHVkaW8iLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBnc3ViKCJuZXNzdW5vIiwiMCIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZ3N1YigibmVzc3VuaSIsIjAiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBnc3ViKCJcXC4iLCIiLGdzdWIoIiAiLCIiLHRvbG93ZXIocHJlbHFzJHJlbW90ZVBsYWNlKSkpKSkpKSkpKSkpKSksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxldmVscz1jKCIwIiwiaG9tZSIsInN0dWRpbyIpKQ0KDQojIGZyb20gaGVpZ2h0IGFuZCB3ZWlnaHQgdG8gQk1JDQpwcmVscXNbcHJlbHFzJGhlaWdodDwzLCJoZWlnaHQiXSA8LSBwcmVscXNbcHJlbHFzJGhlaWdodDwzLCJoZWlnaHQiXSoxMDAgIyBjb3JyZWN0aW5nIGhlaWdodHMgcmVwb3J0ZWQgaW4gbWV0ZXJzDQpwcmVscXMkQk1JIDwtIHByZWxxcyR3ZWlnaHQvKHByZWxxcyRoZWlnaHQvMTAwKV4yICMgQk1JID0ga2cvbV4yDQpwcmVscXMgPC0gcHJlbHFzWyxjKDE6d2hpY2goY29sbmFtZXMocHJlbHFzKT09ImFnZSIpLCAjIHJlbW92aW5nIGhlaWdodCBhbmQgd2VpZ2h0DQogICAgICAgICAgICAgICAgICAgIG5jb2wocHJlbHFzKSx3aGljaChjb2xuYW1lcyhwcmVscXMpPT0iZWR1Iik6KG5jb2wocHJlbHFzKS0xKSldDQpgYGANCg0KPGJyPg0KDQojIyMgMi4xLjEuIFJlY29kaW5nIGpvYnMNCg0KSGVyZSwgdGhlIGBqb2IucmVjb2RlKClgIGZ1bmN0aW9uIGlzIHVzZWQgdG8gcmVjb2RlIHRoZSBvcGVuLWVuZGVkIGBqb2JgIGl0ZW0gcmVzcG9uc2VzIGJ5IHVzaW5nIHRoZSAqKklTQ08tMDggY2xhc3NpZmljYXRpb24gb2Ygb2NjdXBhdGlvbnMgKGxldmVsIDIpKiogKFtHYW56ZWJvb20sIDIwMTBdKCNyZWYpKS4gVGhlIGZ1bmN0aW9uIGlzIGJhc2VkIG9uIHRoZSBgbGFib3VSYCBwYWNrYWdlIGludGVncmF0ZWQgd2l0aCBzb21lIG1hbnVhbCByZWNvZGluZy4gVGhlIG9wZW4tZW5kZWQgcmVzcG9uc2VzIGFyZSB0aGVuIHJlbW92ZWQgZm9yIHByaXZhY3kgcmVhc29ucy4NCg0KPGRldGFpbHM+PHN1bW1hcnk+YGpvYi5yZWNvZGUoKWA8L3N1bW1hcnk+DQo8cD4NCmBgYCB7cn0NCmpvYi5yZWNvZGUgPC0gZnVuY3Rpb24oZGF0YSl7IHJlcXVpcmUobGFib3VyUik7IHJlcXVpcmUoZGF0YS50YWJsZSk7IHJlcXVpcmUobWFncml0dHIpDQoNCiAgIyBjcmVhdGluZyBjb3JwdXMgZGF0YQ0KICBjb3JwdXMgPC0gZGF0YS50YWJsZShJRD1kYXRhJElELHRleHQ9ZGF0YSRqb2IsZWR1PWRhdGEkZWR1LHBvcz1kYXRhJHBvc2l0aW9uLGxhbmc9Iml0IikNCiAgbGFuZ3VhZ2VzIDwtIHVuaXF1ZShjb3JwdXMkbGFuZ3VhZ2UpICMgbGFuZ3VhZ2UgY2xhc3Nlcw0KICANCiAgIyBmaXJzdCBzY3JlZW5pbmcgYmFzZWQgb24gdGhlIGxhYm91clI6OmNsYXNzaWZ5X29jY3VwYXRpb24oKSBmdW5jdGlvbg0KICBzdWdnZXN0aW9ucyA8LSBjbGFzc2lmeV9vY2N1cGF0aW9uKGNvcnB1cz1jb3JwdXMsaWRfY29sPSJJRCIsdGV4dF9jb2w9InRleHQiLGxhbmc9Iml0Iixpc2NvX2xldmVsPTIsbnVtX2xlYXZlcz0xMCkNCiAgY29ycHVzIDwtIHBseXI6OmpvaW4oY29ycHVzLHN1Z2dlc3Rpb25zLGJ5PSJJRCIsdHlwZT0ibGVmdCIpDQogIA0KICAjIGFkanVzdGluZyBhdXRvbWF0aWMgY2xhc3NpZmljYXRpb24gYmFzZWQgb24gbWFudWFsIHNjcmVlbmluZw0KICBjb3JwdXNbY29ycHVzJHRleHQlaW4lYygiUmVzcG9uc2FiaWxlIHNpc3RlbWkgaW5mb3JtYXRpdmkiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAiUmVzcG9uc2FiaWxlIGRpIHVuIHBpY2NvbG8gbXVzZW8gZSBvcGVyYXRyaWNlIG11c2VhbGUgZSB0ZWF0cmFsZSBuZWxsZSBzY3VvbGUiKSwNCiAgICAgICAgICJwcmVmZXJyZWRMYWJlbCJdIDwtIA0KICAgICJMZWdhbCwgc29jaWFsIGFuZCBjdWx0dXJhbCBwcm9mZXNzaW9uYWxzIg0KICBjb3JwdXNbY29ycHVzJHRleHQlaW4lYygiRnVuemlvbmFyaW8gVGVjbmljbyBwdWJibGljYSBhbW1pbmlzdHJhemlvbmUgIiksDQogICAgICAgICAicHJlZmVycmVkTGFiZWwiXSA8LSANCiAgICAiTGVnYWwsIHNvY2lhbCBhbmQgY3VsdHVyYWwgcHJvZmVzc2lvbmFscyINCiAgY29ycHVzW2NvcnB1cyR0ZXh0JWluJWMoIkJhbmNhIC0gUmVzcG9uc2FiaWxlIE9yZ2FuaXp6YXppb25lIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgImFkZGV0dGEgYW1taW5pc3RyYXppb25lIGUgYW1taW5pc3RyYXRvcmUgZGkgYXppZW5kYSBpbiBwcm9wcmlvIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgIkNvbW1lcmNpYWxpc3RhIiksDQogICAgICAgICAicHJlZmVycmVkTGFiZWwiXSA8LSANCiAgICAiQnVzaW5lc3MgYW5kIGFkbWluaXN0cmF0aW9uIHByb2Zlc3Npb25hbHMiDQogIGNvcnB1c1tjb3JwdXMkdGV4dCVpbiVjKCJMYXZvcm8gbmVsbGEgc2VncmV0ZXJpYSBkaSB1bmEgU2N1b2xhIFNlY29uZGFyaWEgZGkgUHJpbW8gR3JhZG8gY29tZSBhbW1pbmlzdHJhdGl2YS4gTWkgb2NjdXBvIGRpIHF1ZXN0aW9uaSBidXJvY3JhdGljaGUgZSBvcmdhbml6emF0aXZlLCBnZXN0aXNjbyBzb3ByYXR0dXR0byBjaXJjb2xhcmkgZSBkb21hbmRlIGRpIGlzY3JpemlvbmUsIG51bGxhIG9zdGEsIGVjYy4gQWwgbW9tZW50byBnZXN0aXNjbyBhbmNoZSBpbCBjb250cm9sbG8gZGVpIEdyZWVuIFBhc3MgZSBsZSB2YXJpZSBwcm9jZWR1cmUgZGEgc2VndWlyZS4iLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAiQXR0aXZpdMOgIGFtbWluaXN0cmF0aXZhIGRpIHVmZmljaW8gZSBmcm9udCBPZmZpY2UgIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgImltcGllZ2F0YSBjb21tZXJjaWFsZSIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICJpbXBpZWdhdGEgbmVsIHNldHRvcmUgYW1taW5pc3RyYXRpdm8iLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAiQWRkZXR0YSBiYWNrIG9mZmljZSBwcmVzc28gYWdlbnppYSBkaSBzb21taW5pc3RyYXppb25lIiksDQogICAgICAgICAicHJlZmVycmVkTGFiZWwiXSA8LSANCiAgICAiQnVzaW5lc3MgYW5kIGFkbWluaXN0cmF0aW9uIGFzc29jaWF0ZSBwcm9mZXNzaW9uYWxzIg0KICBjb3JwdXNbY29ycHVzJHRleHQlaW4lYygiZGlyZXppb25lIHBpY2NvbGEgYXppZW5kYSIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICJEaXJpZ2VudGUgZCdhemllbmRhICIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICJEaXJpZ2VudGUgbXVsdGluYXppb25hbGUgZGlnaXRhbCBtYXJrZXRpbmciLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAiRm91bmRlciBicmFuZCBtb2RhICIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICJJbXByZW5kaXRvcmUgbmVsIHNldHRvcmUgZGVnbGkgYWxiZXJnaGksIGdlc3Rpb25lIGRpIHVuIGhvdGVsIGRpIDQ1IGNhbWVyZSBwacO5IHNhbGEgcmlzdG9yYW50ZS4gR2VzdGlvbmUgZGkgOSBkaXBlbmRlbnRpLCByYXBwb3J0aSBjb24gZm9ybml0b3JpIGUgcGlhdHRhZm9ybWUgb25saW5lLiBHZXN0aW9uZSBkZWxsYSBjb250YWJpbGl0w6AuIE9jY2FzaW9uYWxtZW50ZSBkb2NlbnRlIHByZXNzbyBDZXNjb3QgUmltaW5pLCBjb3JzaSBkaSBmb3JtYXppb25lLiIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICJJbXByZW5kaXRvcmUgZGkgY2FycGVudGVyaWEgbWV0YWxsaWNhICIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICJJbXByZW5kaXRyaWNlIiksDQogICAgICAgICAicHJlZmVycmVkTGFiZWwiXSA8LSANCiAgICAiQ2hpZWYgZXhlY3V0aXZlcywgc2VuaW9yIG9mZmljaWFscyBhbmQgbGVnaXNsYXRvcnMiDQogIGNvcnB1c1tjb3JwdXMkdGV4dCVpbiVjKCJhdHRpdml0w6AgZGkgcmljZXJjYSBwcmVzc28gdW5pdmVyc2l0w6AiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAiRG90dG9yYW5kbyBkaSBSaWNlcmNhIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgIkRvdHRvcmF0byBkaSByaWNlcmNhIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgIlNvbm8gdW4gZ2VvbWV0cmEgY29udGFiaWxlLiBJbCBtaW8gbGF2b3JvIGNvbnNpc3RlIG5lbCB0ZW5lcmUgdHJhY2NpYSBkaSB0dXR0ZSBsZSBsYXZvcmF6aW9uaSBjaGUgc3ZvbGdvbm8gZ2xpIG9wZXJhaSBzdWkgdmFyaSBjYW50aWVyaSwgZG9wb2RpY2jDqSByZWFsaXp6byBkZWkgcmVwb3J0IGZvdG9ncmFmaWNpIGUgY29udGFiaWxpIHBlciBpbCBtaW8gZGF0b3JlIGRpIGxhdm9yby4gXG5HbGkgb3BlcmFpIG1pIGludmlhbm8gZ2lvcm5hbG1lbnRlIGxlIGZvdG8gcGVyIHJlYWxpenphcmUgaSByZXBvcnQsIGRhbGxlIGZvdG8gbmUgcmljYXZvIGxlIG1pc3VyZSBkZWxsZSBsYXZvcmF6aW9uaSBlc2VndWl0ZS4gSW4gYmFzZSBhbGxlIG1pc3VyYXppb25pIGVmZmV0dHVhdGUgZXNlZ3VvIGRlaSBkaXNlZ25pIGNvbnRhYmlsaSBlIHJlYWxpenpvIHVuIGNvbXB1dG8gbWV0cmljbyBkb3ZlIGNvbnRyb2xsbyBpIGNvc3RpIGRlbGxlIGxhdm9yYXppb25pIGVzZWd1aXRlIGUgdmVyaWZpY28gY2hlIG5vbiBzdXBlcmlhbW8gaWwgYnVkZ2V0IHByZWZpc3NhdG8uIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgIkFydGlnaWFubyBpZHJhdWxpY28gZWxldHRyaWNpc3RhIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgIkdlb21ldHJhIGxpYmVybyBwcm9mZXNzaW9uaXN0YSIpLA0KICAgICAgICAgInByZWZlcnJlZExhYmVsIl0gPC0gDQogICAgIlNjaWVuY2UgYW5kIGVuZ2luZWVyaW5nIGFzc29jaWF0ZSBwcm9mZXNzaW9uYWxzIg0KICBjb3JwdXNbY29ycHVzJHRleHQlaW4lYygicmFkaW9sb2dvLCBhbmFsaXNpIGltbWFnaW5pIGFsbGEgd29ya3N0YXRpb24gKGNvbXB1dGVyKSBhbHRlcm5hdG8gYSBwZXJpb2RpIGRpIHN0dWRpbyBhbCBjb21wdXRlciBlIGVzZWN1emlvbmUgZGkgZWNvZ3JhZmllICIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICJyaWFiaWxpdGF6aW9uZSBkZWxsYSB2b2NlIGUgZGVsbGEgZGVnbHV0aXppb25lIHBlciBhZHVsdGkgb3BlcmF0aSBkZWxsZSBjb3JkZSB2b2NhbGkiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAiUHNpY290ZXJhcGV1dGEgcHJlc3NvIGlsIG1pbyBzdHVkaW8gcHJpdmF0by4gTCdhdHRpdml0w6AgY2hlIHN2b2xnbyBzaSByaXZvbGdlIGFkIGFkdWx0aSBlIGFkb2xlc2NlbnRpLCBxdWFzaSBlc2NsdXNpdmFtZW50ZSBpbiBwcmVzZW56YSwgaW4gc2VkdXRlIGRpIGNpcmNhIDEgaCBjaWFzY3VuYS4gQSBjacOyIHNpIGFnZ2l1bmdlIGlsIGxhdm9ybyBkaSBmYXR0dXJhemlvbmUsIGZvcm1hemlvbmUgZSBhZ2dpb3JuYW1lbnRvLCBnZXN0aW9uZSBwcmF0aWNhIGRlbGxvIHN0dWRpbyAoQmFjayBvZmZpY2UpIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgImluZmVybWllcmUgY29vcmRpbmF0b3JlIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgIlBzaWNoaWF0cmEgcHNpY290ZXJhcGV1dGEgIiksDQogICAgICAgICAicHJlZmVycmVkTGFiZWwiXSA8LSANCiAgICAiSGVhbHRoIHByb2Zlc3Npb25hbHMiDQogIGNvcnB1c1tjb3JwdXMkdGV4dCVpbiVjKCJPZG9udG90ZWNuaWNvIGRhIGxpYmVybyBwcm9mZXNzaW9uaXN0YSwgIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgIm9wZXJhdG9yZSBzb2NpbyBzYW5pdGFyaW8iLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAiVHV0b3IgQUJBOiBtaSBvY2N1cG8gZGVsbCdhcHBsaWNhemlvbmUgZGkgcHJvY2VkdXJlIGUgc3RyYXRlZ2llIGNvbXBvcnRhbWVudGFsaSBwZXIgYmFtYmluaSBjb24gRGlzdHVyYm8gZGVsbG8gc3BldHRybyBhdXRpc3RpY28sIGFsbCdpbnRlcm5vIGRpIHVuIHJhcHBvcnRvIDE6MS5cbkR1cmFudGUgbGEgc2Vzc2lvbmUgZGkgbGF2b3JvIMOoIG5lY2Vzc2FyaW8gY29zdHJ1aXJlIHVuYSBidW9uYSByZWxhemlvbmUgY29uIGlsIGJhbWJpbm8gY29uIHNwZXR0cm8gYXV0aXN0aWNvIGUgbGEgc3VhIGZhbWlnbGlhOyBwcmVuZGVyZSBhIG1hbm8gbm90ZSBwZXIgY2lhc2N1bmEgc2Vzc2lvbmUsIGluc2VyaXJlIGkgZGF0aSBpbiB1biBkYXRhYmFzZTsgb3NzZXJ2YXJlIGlsIGNvbXBvcnRhbWVudG8gZGVsIGJhbWJpbm8gZSBxdWluZGkgYXBwbGljYXJlIHVuYSBzdHJhdGVnaWEgaWRvbmVhOyBtb25pdG9yYXJlIGdsaSBlc2l0aSBkZWxs4oCZaW50ZXJ2ZW50byBkYSBjb25kaXZpZGVyZSBzdWNjZXNzaXZhbWVudGUgY29uIGlsIHN1cGVydmlzb3JlIEFCQSwgbmVsbCdvdHRpY2EgZGkgdW5hIHJpZm9ybXVsYXppb25lIGRlbGxhIHByb2dyYW1tYXppb25lIGRhIGltcGxlbWVudGFyZSBwZXIgcXVlbCBiYW1iaW5vLlxuIiksDQogICAgICAgICAicHJlZmVycmVkTGFiZWwiXSA8LSANCiAgICAiSGVhbHRoIGFzc29jaWF0ZSBwcm9mZXNzaW9uYWxzIg0KICBjb3JwdXNbY29ycHVzJHRleHQlaW4lYygiQ29vcmRpbmF0b3JlIHVuaXTDoCBvcGVyYXRpdmEgaW4gdW4gc2Vydml6aW8gZGkgIGludGVncmF6aW9uZSBzb2NpbyBzYW5pdGFyaWEgaW4gc2FsdXRlIG1lbnRhbGUuIENvb3JkaW5hdG9yZSB1bml0w6Agb3BlcmF0aXZhIHBlciBzb2dnZXR0aSBzdmFudGFnZ2lhdGkgZSBkaXNhYmlsaSBuZWwgY29vcGVyYXRpdmlzbW8uIENvbnNpZ2xpZXJlIENEQSBpbiBDb29wZXJhdGl2YS4gQ3VsdG9yZSBkZWxsYSBtYXRlcmlhIGluIGZhY29sdMOgIHVuaXZlcnNpdGFyaWEuIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgIlBzaWNvbG9nYSBpbmZhbnRpbGUsIFByb2dldHRpc3RhIHNvY2lhbGUsIENvb3JkaW5hdHJpY2UgQ2VudHJvIEZhbWlnbGllIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgIlRyYWR1dHRyaWNlLCBhZGRldHRhIHN0YW1wYSwgY29udGVudCBjcmVhdG9yIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgInByb2plY3QgbWFuYWdlciBlIGNvbnN1bGVudGUgYXppZW5kYWxlIHJpc3BldHRvIGFsbGEgcHNpY29sb2dpYSBjbGluaWNhLCBwc2ljb2xvZ2lhIG9yZ2FuaXp6YXppb25pIGUgcHNpY29sb2dpYSBlbWVyZ2V6YSIpLA0KICAgICAgICAgInByZWZlcnJlZExhYmVsIl0gPC0gDQogICAgIkxlZ2FsLCBzb2NpYWwgYW5kIGN1bHR1cmFsIHByb2Zlc3Npb25hbHMiDQogIGNvcnB1c1tjb3JwdXMkdGV4dCVpbiVjKCJFbmVyZ3kgQmFjayBPZmZpY2UgU3BlY2lhbGlzdCAoQWRkZXR0byBhbCBCaWxsaW5nIEdhcykiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAiU29sZ28gMiBsYXZvcmk6XG5MaWJlcmEgcHJvZmVzc2lvbmUsIHN2b2xnbyBhdHRpdml0w6AgZGkgaW1wcmVzYSBuZWxsZSBzb2NpZXTDoCBjb24gbWlvIGZyYXRlbGxvIG5lbCBjYW1wbyBhcmNoaXRldHR1cmEsIGltbW9iaWxpYXJlIGUgdHVyaXN0aWNvIFxuUmVzcG9uc2FiaWxlIHJpY2VyY2EgZSBzdmlsdXBwbyAoY29uIG9yYXJpIGZsZXNzaWJpbGkpIHggdW4gcXVhcnRpZXJlIGZpZXJpc3RpY28iKSwNCiAgICAgICAgICJwcmVmZXJyZWRMYWJlbCJdIDwtIA0KICAgICJTY2llbmNlIGFuZCBlbmdpbmVlcmluZyBwcm9mZXNzaW9uYWxzIg0KICBjb3JwdXNbY29ycHVzJHRleHQlaW4lYygiRG9wb3NjdW9sYSAiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAiRWR1Y2F0cmljZSBhbGwnaW50ZXJubyBkaSB1bmEgc2N1b3JhIHN1cGVyaW9yZS4iKSwNCiAgICAgICAgICJwcmVmZXJyZWRMYWJlbCJdIDwtIA0KICAgICJUZWFjaGluZyBwcm9mZXNzaW9uYWxzIg0KICBjb3JwdXNbY29ycHVzJHRleHQlaW4lYygiVElUT0xBUkUgREkgSU1QUkVTQSBESSBQVUxJWklFIiksDQogICAgICAgICAicHJlZmVycmVkTGFiZWwiXSA8LSANCiAgICAiUGVyc29uYWwgc2VydmljZSB3b3JrZXJzIg0KICBjb3JwdXNbY29ycHVzJHRleHQlaW4lYygiUHJvZ3JhbW1hdG9yZSIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICJDb2FjaCBkaSBFLVNwb3J0cywgYWxsZW5vIGRlaSBnaW9jYXRvcmkgZGkgdmlkZW9naW9jaGkgYXR0cmF2ZXJzbyBkZWkgY2FtcGlvbmkgcHJvZmVzc2lvbmlzdGljaSIpLA0KICAgICAgICAgInByZWZlcnJlZExhYmVsIl0gPC0gDQogICAgIkluZm9ybWF0aW9uIGFuZCBjb21tdW5pY2F0aW9ucyB0ZWNobm9sb2d5IHByb2Zlc3Npb25hbHMiDQogIA0KICAjIG1lcmdpbmcgY29ycHVzIHdpdGggZGF0YQ0KICBjb3JwdXMkSUQgPC0gYXMuZmFjdG9yKGNvcnB1cyRJRCkNCiAgZGF0YSA8LSBwbHlyOjpqb2luKGRhdGEsY29ycHVzWyxjKCJJRCIsInByZWZlcnJlZExhYmVsIildLGJ5PSJJRCIsdHlwZT0ibGVmdCIpDQogIA0KICAjIHJlcGxhY2luZyBvcmlnaW5hbCBqb2Igd2l0aCByZWNvZGVkIGpvYiBjYXRlZ29yaWVzDQogIGRhdGEkam9iIDwtIGFzLmZhY3RvcihkYXRhJHByZWZlcnJlZExhYmVsKQ0KICBkYXRhJHByZWZlcnJlZExhYmVsIDwtIE5VTEwgIyByZW1vdmluZyBwcmVmZXJyZWRMYWJlbA0KICBkYXRhJElEIDwtIGFzLmZhY3RvcihkYXRhJElEKQ0KICANCiAgIyBzdW1tYXJpemluZyBpbmZvDQogIGNhdCgiUmVjb2RlZCBqb2IgdmFyaWFibGUgaW50byIsbmxldmVscyhkYXRhJGpvYiksImNhdGVnb3JpZXM6XG4iKQ0KICBwcmludChzdW1tYXJ5KGRhdGFbIWlzLm5hKGRhdGEkam9iKSwiam9iIl0pKQ0KICByZXR1cm4oZGF0YSkgfQ0KYGBgDQo8L3A+DQo8L2RldGFpbHM+DQoNCmBgYCB7ciBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQ0KcHJlbHFzIDwtIGpvYi5yZWNvZGUocHJlbHFzKQ0KYGBgDQoNCjxicj4NCg0KIyMjIDIuMS4yLiByZWNvZGluZyB3b3JrVGltZQ0KDQpUaGVuLCB3ZSByZWNvZGUgdGhlIGB3b3JrVGltZWAgdmFyaWFibGUsIHdoaWNoIHdhcyBtZWFzdXJlZCB3aXRoIGFuIG9wZW4tZW5kZWQgcXVlc3Rpb24gYXMgd2VsbC4NCmBgYCB7cn0NCiMgYWxsIGxvd2VyIGNhc2UgbGV0dGVycw0Kd29ya1RpbWVzIDwtIHd0Lm1pbiA8LSB3dC5tYXggPC0gdG9sb3dlcihwcmVscXMkd29ya1RpbWUpDQoNCiMgY2F0ZWdvcml6aW5nIHdvcmsgc3RhcnQgdGltZQ0Kd3QubWluW2dyZXAoIjY6Iix3dC5taW4pXSA8LSAjIC4uLi4uLi4uLi4uLi4gIyA2LzcgPSBzdGFydGluZyBiZXR3ZWVuIDY6MDAgQU0gYW5kIDc6NTkgQU0NCiAgd3QubWluW2dyZXAoIjYuIix3dC5taW4pXSA8LSAgDQogIHd0Lm1pbltncmVwKCI3OiIsd3QubWluKV0gPC0gDQogIHd0Lm1pbltncmVwKCI3LiIsd3QubWluKV0gPC0gIjYvNyINCnd0Lm1pbltncmVwKCI4OiIsd3QubWluKV0gPC0gIyAuLi4uLi4uLi4uLi4uLi4gIyA4ID0gc3RhcnRpbmcgYmV0d2VlbiA4OjAwIEFNIGFuZCA4OjU5IEFNDQogIHd0Lm1pbltncmVwKCI4LiIsd3QubWluKV0gPC0gICI4Ig0Kd3QubWluW2dyZXAoIjk6Iix3dC5taW4pXSA8LSAjIC4uLi4uLi4uLi4uLiAjIDkvMTAgPSBzdGFydGluZyBiZXR3ZWVuIDk6MDAgQU0gYW5kIDk6NTkgQU0NCiAgd3QubWluW2dyZXAoIjkuIix3dC5taW4pXSA8LSANCiAgd3QubWluW2dyZXAoIjEwOiIsd3QubWluKV0gPC0gDQogIHd0Lm1pbltncmVwKCIxMC4iLHd0Lm1pbildIDwtICI5LzEwIg0Kd3QubWluW2dyZXAoIjE1LSIsd3QubWluKV0gPC0gIyAuLi4uLi4uLi4uLi4uICMgUE0gPSBzdGFydGluZyBpbiB0aGUgYWZ0ZXJub29uDQogIHd0Lm1pbltncmVwKCIxNS4iLHd0Lm1pbildIDwtIA0KICB3dC5taW5bZ3JlcCgiMTQuIix3dC5taW4pXSA8LSAiUE0iDQoNCiMgY2F0ZWdvcml6aW5nIHdvcmsgZW5kIHRpbWUNCnd0Lm1heFtncmVwKCIxOToiLHd0Lm1heCldIDwtICMgLi4uLi4uLi4uLi4uLiAjIDE5LzIxID0gZW5kaW5nIGJldHdlZW4gNzowMCBQTSBhbmQgNjo1OSBQTQ0KICB3dC5tYXhbZ3JlcCgiMTkuIix3dC5tYXgpXSA8LSANCiAgd3QubWF4W2dyZXAoIi0xOSIsd3QubWF4KV0gPC0gDQogIHd0Lm1heFtncmVwKCItIDE5Iix3dC5tYXgpXSA8LSANCiAgd3QubWF4W2dyZXAoIi0gMjAiLHd0Lm1heCldIDwtIA0KICB3dC5tYXhbZ3JlcCgiLSAyMSIsd3QubWF4KV0gPC0gIjE5LzIxIiANCnd0Lm1heFtncmVwKCIxNzoiLHd0Lm1heCldIDwtICMgLi4uLi4uLi4uLi4uLiAjIDE3LzE4ID0gZW5kaW5nIGJldHdlZW4gNTowMCBQTSBhbmQgNjo1OSBQTQ0KICB3dC5tYXhbZ3JlcCgiMTcuIix3dC5tYXgpXSA8LSANCiAgd3QubWF4W2dyZXAoIi0xNyIsd3QubWF4KV0gPC0gDQogIHd0Lm1heFtncmVwKCItIDE3Iix3dC5tYXgpXSA8LSANCiAgd3QubWF4W2dyZXAoIjE4OiIsd3QubWF4KV0gPC0gDQogIHd0Lm1heFtncmVwKCIxOC4iLHd0Lm1heCldIDwtIA0KICB3dC5tYXhbZ3JlcCgiLTE4Iix3dC5tYXgpXSA8LSANCiAgd3QubWF4W2dyZXAoIi0gMTgiLHd0Lm1heCldIDwtICIxNy8xOCIgDQp3dC5tYXhbZ3JlcCgiMTUuIix3dC5tYXgpXSA8LSAgIy4uLi4uLi4uLi4uLi4gIyAxNS8xNiA9IGVuZGluZyBiZXR3ZWVuIDM6MDAgUE0gYW5kIDQ6NTkgUE0NCiAgd3QubWF4W2dyZXAoIjE1OiIsd3QubWF4KV0gPC0gDQogIHd0Lm1heFtncmVwKCItMTUiLHd0Lm1heCldIDwtIA0KICB3dC5tYXhbZ3JlcCgiMTYuIix3dC5tYXgpXSA8LSANCiAgd3QubWF4W2dyZXAoIjE2OiIsd3QubWF4KV0gPC0gIjE1LzE2Ig0Kd3QubWF4W2dyZXAoIjEyOiIsd3QubWF4KV0gPC0gIyAuLi4uLi4uLi4uLi4uICMgMTIvMTQgPSBlbmRpbmcgYmV0d2VlbiBub29uIGFuZCAyOjU5IFBNDQogIHd0Lm1heFtncmVwKCIxMi4iLHd0Lm1heCldIDwtIA0KICB3dC5tYXhbZ3JlcCgiMTM6Iix3dC5tYXgpXSA8LSANCiAgd3QubWF4W2dyZXAoIjEzLiIsd3QubWF4KV0gPC0gDQogIHd0Lm1heFtncmVwKCJfMTMiLHd0Lm1heCldIDwtDQogIHd0Lm1heFtncmVwKCIvMTMiLHd0Lm1heCldIDwtIA0KICB3dC5tYXhbZ3JlcCgiLTEzIix3dC5tYXgpXSA8LSANCiAgd3QubWF4W2dyZXAoIjE0OiIsd3QubWF4KV0gPC0gDQogIHd0Lm1heFtncmVwKCIxNC4iLHd0Lm1heCldIDwtIA0KICB3dC5tYXhbZ3JlcCgiLzE0Iix3dC5tYXgpXSA8LSANCiAgd3QubWF4W2dyZXAoIi0yLiIsd3QubWF4KV0gPC0gDQogIHd0Lm1heFtncmVwKCItIDAyIix3dC5tYXgpXSA8LSAiMTIvMTQiIA0KDQojIGpvaW5pbmcgc3RhcnQgYW5kIGVuZCB0aW1lDQp3dCA8LSBwYXN0ZSh3dC5taW4sd3QubWF4LHNlcD0iXyIpDQp3dFtncmVwKCJQTV8iLHd0KV0gPC0gIlBNIG9ubHkiICMgY29ycmVjdGluZyBzb21lIGNhc2VzIGFuZCBtZXJnaW5nIGNhdGVnb3JpZXMgd2l0aCBmZXcgY2FzZXMNCg0KIyByZXBsYWNpbmcgd29ya1RpbWUgdmFyaWFibGUgd2l0aCByZWNvZGVkIHdvcmsgdGltZXMNCnByZWxxcyR3b3JrVGltZSA8LSBhcy5mYWN0b3Iod3QpDQpzdW1tYXJ5KHByZWxxcyR3b3JrVGltZSkNCmBgYA0KDQo8YnI+DQoNCiMjIDIuMi4gRGFpbHkgZGlhcmllcw0KDQpIZXJlLCB3ZSBtZXJnZSBhbmQgcmVjb2RlIHRoZSBkYWlseSBgZGlhcnlgIGRhdGFzZXRzLg0KDQojIyMgMi4yLjEuIERhdGEgY2xlYW5pbmcNCg0KSGVyZSwgd2UgZmlsdGVyIHRyaWFsIHJlc3BvbnNlcywgd2UgcmVtb3ZlIHVudXNlZnVsIGNvbHVtbnMsIGFuZCB3ZSByZW5hbWUgYW5kIHNvcnQgdGhlIHJlbGV2YW50IGNvbHVtbnMgb2YgdGhlIGBkaWFyeWAgZGF0YXNldHMuDQpgYGAge3J9DQojIGZpbHRlcmluZyB0cmlhbC9wcmV2aWV3IHJlc3BvbnNlcw0KZGlhcnlfbSA8LSBkaWFyeV9tW2RpYXJ5X20kRGlzdHJpYnV0aW9uQ2hhbm5lbD09ImVtYWlsIixdDQpkaWFyeV9tX3NhdCA8LSBkaWFyeV9tX3NhdFtkaWFyeV9tX3NhdCREaXN0cmlidXRpb25DaGFubmVsPT0iZW1haWwiLF0NCmRpYXJ5X2EgPC0gZGlhcnlfYVtkaWFyeV9hJERpc3RyaWJ1dGlvbkNoYW5uZWw9PSJlbWFpbCIsXQ0KZGlhcnlfZSA8LSBkaWFyeV9lW2RpYXJ5X2UkRGlzdHJpYnV0aW9uQ2hhbm5lbD09ImVtYWlsIixdDQoNCiMgcmVtb3ZpbmcgdW51c2VmdWwgdmFyaWFibGVzDQp0b1JlbW92ZSA8LSBjKCJEdXJhdGlvbi4uaW4uc2Vjb25kcy4iLCJTdGF0dXMiLCJJUEFkZHJlc3MiLCJQcm9ncmVzcyIsIkZpbmlzaGVkIiwiUmVjb3JkZWREYXRlIiwiUmVzcG9uc2VJZCIsDQogICAgICAgICAgICAgICJSZWNpcGllbnRMYXN0TmFtZSIsIlJlY2lwaWVudEZpcnN0TmFtZSIsIkxvY2F0aW9uTGF0aXR1ZGUiLCJMb2NhdGlvbkxvbmdpdHVkZSIsIkRpc3RyaWJ1dGlvbkNoYW5uZWwiLCJVc2VyTGFuZ3VhZ2UiKQ0KZGlhcnlfbVssdG9SZW1vdmVdIDwtIGRpYXJ5X2FbLHRvUmVtb3ZlXSA8LSBkaWFyeV9lWyx0b1JlbW92ZV0gPC0gZGlhcnlfbV9tYWlsWyx0b1JlbW92ZV0gPC0NCiAgZGlhcnlfYV9tYWlsWyx0b1JlbW92ZV0gPC0gZGlhcnlfbV9zYXRbLHRvUmVtb3ZlXSA8LSBkaWFyeV9tX3NhdF9tYWlsWyx0b1JlbW92ZV0gPC0gZGlhcnlfZV9tYWlsWyx0b1JlbW92ZV0gPC0gTlVMTA0KYGBgDQoNCg0KPGJyPg0KDQojIyMgMi4yLjIuIERpcmVjdCBlLW1haWxzDQoNClRoZW4sIHdlIG1lcmdlIGVhY2ggYGRpYXJ5YCBkYXRhc2V0IHdpdGggdGhlIGNvcnJlc3BvbmRpbmcgZGF0YSBvYnRhaW5lZCBieSBkaXJlY3RseSBlLW1haWxpbmcgcGFydGljaXBhbnRzIChpLmUuLCBpbiBjYXNlIG9mIHRlY2huaWNhbC9zY2hlZHVsZSBwcm9ibGVtcykuDQoNCmBgYCB7cn0NCiMgam9pbmluZyAnb3JkaW5hcnknIGRhdGFzZXRzIHdpdGggZGF0YXNldHMgZS1tYWlsZWQgZGF0YXNldHMNCmRpYXJ5X2FfbWFpbCRSZWNpcGllbnRFbWFpbCA8LSBkaWFyeV9hX21haWwkUTIyXzEgIyBhZnRlcm5vb24NCmRpYXJ5X2FfbWFpbCRRMjJfMSA8LSBOVUxMDQpkaWFyeV9hIDwtIHJiaW5kKGRpYXJ5X2EsZGlhcnlfYV9tYWlsKQ0KZGlhcnlfZV9tYWlsJFJlY2lwaWVudEVtYWlsIDwtIGRpYXJ5X2VfbWFpbCRlLm1haWxfMSAjIGV2ZW5pbmcNCmRpYXJ5X2VfbWFpbCRlLm1haWxfMSA8LSBOVUxMDQpkaWFyeV9lIDwtIHJiaW5kKGRpYXJ5X2UsZGlhcnlfZV9tYWlsKQ0KZGlhcnlfbV9tYWlsJFJlY2lwaWVudEVtYWlsIDwtIGRpYXJ5X21fbWFpbCRRMzBfMSAjIG1vcm5pbmcNCmRpYXJ5X21fbWFpbCRRMzBfMSA8LSBOVUxMDQpjb2xuYW1lcyhkaWFyeV9tKSA8LSBnc3ViKCJcXC4iLCIiLGNvbG5hbWVzKGRpYXJ5X20pKQ0KZGlhcnlfbSA8LSByYmluZChkaWFyeV9tLGRpYXJ5X21fbWFpbCkNCmRpYXJ5X21fc2F0X21haWwkUmVjaXBpZW50RW1haWwgPC0gZGlhcnlfbV9zYXRfbWFpbCRRMTFfMSAjIFNhdHVyZGF5IG1vcm5pbmcNCmRpYXJ5X21fc2F0X21haWwkUTExXzEgPC0gTlVMTA0KZGlhcnlfbV9zYXRfbWFpbCA8LSBkaWFyeV9tX3NhdF9tYWlsWyFpcy5uYShkaWFyeV9tX3NhdF9tYWlsJFJlY2lwaWVudEVtYWlsKSxdICMgcmVtb3ZpbmcgdHJpYWwgZW50cmllcw0KZGlhcnlfbV9zYXQgPC0gcmJpbmQoZGlhcnlfbV9zYXQsZGlhcnlfbV9zYXRfbWFpbCkNCmRpYXJ5X21fc2F0JGRheU9mZl90b2RheSA8LSBkaWFyeV9tX3NhdCRBV0xfMSA8LSBkaWFyeV9tX3NhdCRBV0xfMiA8LSBkaWFyeV9tX3NhdCRBV0xfMyA8LSBOQSAjIG5vIEFXTCB2YWx1ZXMgb24gU2F0dXJkYXkNCmRpYXJ5X20gPC0gcmJpbmQoZGlhcnlfbSxkaWFyeV9tX3NhdCkNCg0KIyBzb3J0aW5nIGFuZCByZW5hbWluZyBjb2x1bW5zDQpkaWFyeV9tIDwtIGRpYXJ5X21bLGMoMTp3aGljaChjb2xuYW1lcyhkaWFyeV9tKT09IkV4dGVybmFsUmVmZXJlbmNlIiksd2hpY2goY29sbmFtZXMoZGlhcnlfbSk9PSJkYXlPZmZfdG9kYXkiKSwNCiAgICAgICAgICAgICAgICAgICAgICB3aGljaChjb2xuYW1lcyhkaWFyeV9tKT09IkJQMV8xIik6d2hpY2goY29sbmFtZXMoZGlhcnlfbSk9PSJkYXlPZmZfeWVzdGVyZGF5IiksDQogICAgICAgICAgICAgICAgICAgICAgd2hpY2goY29sbmFtZXMoZGlhcnlfbSk9PSJBV0xfMSIpOm5jb2woZGlhcnlfbSkpXQ0KY29sbmFtZXMoZGlhcnlfbSlbMTo5XSA8LSBjb2xuYW1lcyhkaWFyeV9hKVsxOjldIDwtIGNvbG5hbWVzKGRpYXJ5X2UpWzE6OV0gPC0gYygic3RhcnQiLCJlbmQiLCJJRCIsInJlY3J1aXRlci5JRCIsImRheU9mZl90b2RheSIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJTQlAxIiwiREJQMSIsIlNCUDIiLCJEQlAyIikNCmNvbG5hbWVzKGRpYXJ5X2EpWzVdIDwtIGNvbG5hbWVzKGRpYXJ5X2UpWzVdIDwtICJkYXlPZmYiICMgZGlmZmVyZW50aWF0aW5nIGFmdGVybm9vbi9ldmVuaW5nIGZyb20gbW9ybmluZyBkYXlPZmYgdmFsdWVzIA0KY29sbmFtZXMoZGlhcnlfYSkgPC0gZ3N1YigiV0hMU00xIiwiV0hMU00iLGdzdWIoIldITFNNMiIsIldITFNNIixjb2xuYW1lcyhkaWFyeV9hKSkpDQpgYGANCg0KPGJyPg0KDQojIyMgMi4yLjMuIE1lcmdpbmcgZGlhcnkgZGF0YQ0KDQpIZXJlLCB3ZSBtZXJnZSB0aGUgZm91ciBkYXRhc2V0cyBpbnRvIGEgc2luZ2xlIGxvbmctZm9ybSBgZGlhcnlgIGRhdGFzZXQuIFRoZSBgZGlhcnlUeXBlYCB2YXJpYWJsZSBpcyBjcmVhdGVkIGZvciBkaXNjcmltaW5hdGluZyBhbW9uZyBgTWBvcm5pbmcsIGBBYGZ0ZXJub29uLCBhbmQgYEVgdmVuaW5nIGRpYXJpZXMuIA0KYGBgIHtyIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9DQojIGFkZGluZyBkaWFyeVR5cGUgY29sdW1uDQpkaWFyeV9tJGRpYXJ5VHlwZSA8LSAiTSIgIyBNb3JuaW5nIGRpYXJ5DQpkaWFyeV9hJGRpYXJ5VHlwZSA8LSAiQSIgIyBBZnRlcm5vb24gZGlhcnkNCmRpYXJ5X2UkZGlhcnlUeXBlIDwtICJFIiAjIEV2ZW5pbmcgZGlhcnkNCg0KIyBNZXJnaW5nIGRpYXJ5IGRhdGEgKExPTkcgZGF0YXNldCkNCmRpYXJ5IDwtIHBseXI6OmpvaW4ocGx5cjo6am9pbihkaWFyeV9tLGRpYXJ5X2EsdHlwZT0iZnVsbCIpLGRpYXJ5X2UsdHlwZT0iZnVsbCIpDQpjYXQoInNhbml0eSBjaGVjazoiLG5yb3coZGlhcnkpID09IG5yb3coZGlhcnlfbSkgKyBucm93KGRpYXJ5X2EpICsgbnJvdyhkaWFyeV9lKSkNCmBgYA0KPGJyPg0KDQojIyMgMi4yLjQuIERhdGEgcmVjb2RpbmcNCg0KVGhlbiwgd2UgcmVuYW1lIGBkaWFyeWAgdmFyaWFibGVzLCB3ZSBjaGFuZ2UgdGhlIGNsYXNzZXMgb2YgdGhlIHJlbGV2YW50IHZhcmlhYmxlcywgYW5kIHdlIHJlY29kZSB0aGUgbGV2ZWxzIG9mIGNhdGVnb3JpY2FsIChmYWN0b3IpIHZhcmlhYmxlcyBjb25zaXN0ZW50bHkgd2hhdCB3ZSBwcmVyZWdpc3RlcmVkIChzZWUgW3ByZXJlZ2lzdHJhdGlvbiBoZXJlXShodHRwczovL29zZi5pby9oOXp2cSkpLg0KYGBge3J9DQojIHJlbmFtaW5nIGNvbHVtbnMNCmNvbG5hbWVzKGRpYXJ5KVt3aGljaChjb2xuYW1lcyhkaWFyeSk9PSJsYXRlV29ya0hvdXJzXzEiKV0gPC0gImxhdGVXb3JrSG91cnMiICMgcmVuYW1pbmcgY29sdW1uDQpjb2xuYW1lcyhkaWFyeSlbd2hpY2goY29sbmFtZXMoZGlhcnkpPT0id29ya0hvdXJzXzEiKV0gPC0gIndvcmtIb3VycyIgIyByZW5hbWluZyBjb2x1bW4NCmNvbG5hbWVzKGRpYXJ5KVt3aGljaChjb2xuYW1lcyhkaWFyeSk9PSJ3YWtldGltZV8xNiIpXSA8LSAid2FrZVRpbWUiICMgcmVuYW1pbmcgY29sdW1uDQpjb2xuYW1lcyhkaWFyeSkgPC0gZ3N1YigiXyIsIiIsY29sbmFtZXMoZGlhcnkpKQ0KY29sbmFtZXMoZGlhcnkpW2dyZXBsKCJTUSIsY29sbmFtZXMoZGlhcnkpKV0gPC0gcGFzdGUoIlNRIiwxOjQsc2VwPSIiKQ0KY29sbmFtZXMoZGlhcnkpW3doaWNoKGNvbG5hbWVzKGRpYXJ5KT09IldMNCIpXSA8LSAiV0wzIg0KY29sbmFtZXMoZGlhcnkpW2dyZXBsKCJXSExTTSIsY29sbmFtZXMoZGlhcnkpKV0gPC0gcGFzdGUoIldITFNNIiwxOjYsc2VwPSIiKQ0KY29sbmFtZXMoZGlhcnkpW3doaWNoKGNvbG5hbWVzKGRpYXJ5KT09IkVFNSIpXSA8LSAiRUU0Ig0KY29sbmFtZXMoZGlhcnkpW2dyZXBsKCJSLmRldCIsY29sbmFtZXMoZGlhcnkpKV0gPC0gcGFzdGUoIlIuZGV0IiwxOjMsc2VwPSIiKQ0KY29sbmFtZXMoZGlhcnkpW2dyZXBsKCJSLnJlbCIsY29sbmFtZXMoZGlhcnkpKV0gPC0gcGFzdGUoIlIucmVsIiwxOjMsc2VwPSIiKQ0KY29sbmFtZXMoZGlhcnkpW2dyZXBsKCJSLm1hcyIsY29sbmFtZXMoZGlhcnkpKV0gPC0gcGFzdGUoIlIubWFzIiwxOjMsc2VwPSIiKQ0KDQojIHRpbWUgKFBPU0lYY3QgdmFyaWFibGVzKQ0KZGlhcnkkc3RhcnQgPC0gYXMuUE9TSVhjdChkaWFyeSRzdGFydCkNCmRpYXJ5JGVuZCA8LSBhcy5QT1NJWGN0KGRpYXJ5JGVuZCkNCg0KIyBudW1lcmljDQpudW1zIDwtIGMod2hpY2goY29sbmFtZXMoZGlhcnkpPT0iU0JQMSIpOndoaWNoKGNvbG5hbWVzKGRpYXJ5KT09IkRCUDIiKSwNCiAgICAgICAgICB3aGljaChjb2xuYW1lcyhkaWFyeSk9PSJBV0wxIik6d2hpY2goY29sbmFtZXMoZGlhcnkpPT0iQVdMMyIpLA0KICAgICAgICAgIHdoaWNoKGNvbG5hbWVzKGRpYXJ5KT09Ik9DMSIpOndoaWNoKGNvbG5hbWVzKGRpYXJ5KT09IlNRNCIpLA0KICAgICAgICAgIHdoaWNoKGNvbG5hbWVzKGRpYXJ5KT09IldMMSIpOndoaWNoKGNvbG5hbWVzKGRpYXJ5KT09IlIubWFzMyIpLA0KICAgICAgICAgIHdoaWNoKGNvbG5hbWVzKGRpYXJ5KT09IndvcmtIb3VycyIpKQ0KZGlhcnlbLG51bXNdIDwtIGxhcHBseShkaWFyeVssbnVtc10sYXMubnVtZXJpYykNCg0KIyByZWNvcmRpbmcgbG9jYXRpb24NCmRpYXJ5JHdoZXJlIDwtIGZhY3Rvcihnc3ViKCIxIiwid29ya3BsYWNlIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgIGdzdWIoIjIiLCJob21lIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZ3N1YigiNCIsIm90aGVyIixkaWFyeSR3aGVyZSkpKSxsZXZlbHM9YygiaG9tZSIsIndvcmtwbGFjZSIsIm90aGVyIikpDQojIGRhaWx5SGFzc2xlcw0KZGlhcnkkZGFpbHlIYXNzbGVzIDwtIGFzLmZhY3Rvcihnc3ViKCIyIiwiTm8iLGdzdWIoIjEiLCJZZXMiLGRpYXJ5JGRhaWx5SGFzc2xlcykpKQ0KDQojIGRpYXJ5IHR5cGUNCmRpYXJ5JGRpYXJ5VHlwZSA8LSBmYWN0b3IoZGlhcnkkZGlhcnlUeXBlLGxldmVscz1jKCJNIiwiQSIsIkUiKSkNCg0KIyBkYXlPZmZfdG9kYXkgJiBkYXlPZmZfeWVzdGVyZGF5IGFzIGZhY3RvciAocmVjb2RpbmcgbGV2ZWxzIGFzIEZBTFNFID0gbm8sIFRSVUUgPSB5ZXMpDQpkaWFyeSRkYXlPZmYgPC0gYXMubG9naWNhbChhcy5udW1lcmljKGRpYXJ5JGRheU9mZiktMSkNCmRpYXJ5JGRheU9mZnRvZGF5IDwtIGFzLmxvZ2ljYWwoYXMubnVtZXJpYyhkaWFyeSRkYXlPZmZ0b2RheSktMSkNCmRpYXJ5JGRheU9mZnllc3RlcmRheSA8LSBhcy5sb2dpY2FsKGFzLm51bWVyaWMoZGlhcnkkZGF5T2ZmeWVzdGVyZGF5KS0xKQ0KDQojIHRlbGVXb3JrDQpkaWFyeSR0ZWxlV29yayA8LSBmYWN0b3IoZ3N1YigiMSIsInRlbGVXb3JrIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdzdWIoIjIiLCJvZmZpY2UiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBnc3ViKCIzIiwiYm90aCIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZ3N1YigiNCIsImRheU9mZiIsZGlhcnkkdGVsZVdvcmspKSkpLGxldmVscz1jKCJvZmZpY2UiLCJ0ZWxlV29yayIsImJvdGgiLCJkYXlPZmYiKSkNCiMgY29uZm91bmRlcnMNCmRpYXJ5JGNvbmZvdW5kZXJzIDwtIGdzdWIoIjEiLCJjb2ZmZWUiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICBnc3ViKCIyIiwic21va2UiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdzdWIoIjQiLCJzcG9ydCIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBnc3ViKCI1IiwibWVhbCIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdzdWIoIjYiLCIwIixkaWFyeSRjb25mb3VuZGVycykpKSkpDQpgYGANCg0KPGJyPg0KDQojIyMgMi4yLjUuIFJlY29kaW5nIGNvbmZvdW5kZXJzDQoNClRoZSBgY29uZm91bmRlcnNgIHZhcmlhYmxlIGlzIHByb2Nlc3NlZCBieSB1c2luZyB0aGUgYGNoZWNrbGlzdF9zZXBgIGZ1bmN0aW9uIGluIG9yZGVyIHRvIHNlcGFyYXRlIHRoZSBkaWZmZXJlbnQgY29uZm91bmRpbmcgZmFjdG9ycy4NCg0KPGRldGFpbHM+PHN1bW1hcnk+YGNoZWNrbGlzdF9zZXAoKWA8L3N1bW1hcnk+DQo8cD4NCmBgYCB7cn0NCmNoZWNrbGlzdF9zZXAgPC0gZnVuY3Rpb24oZGF0YT1OVUxMLHZhck5hbWU9TlVMTCxzZXA9IiwiLG5PcHRpb25zPTQsDQogICAgICAgICAgICAgICAgICAgICAgICAgIGxhYmVscz1jKCJjb2ZmZWUiLCJzbW9rZSIsInNwb3J0IiwibWVhbCIpLHJldHVybi5kYXRhPUZBTFNFKXsNCiAgDQogIGNoZWNrbGlzdCA8LSBkYXRhLmZyYW1lKGNoZWNrbGlzdF92YXI9ZGF0YVssdmFyTmFtZV0pDQogIGNoZWNrbGlzdCRjaGVja2xpc3RfdmFyIDwtIGFzLmNoYXJhY3RlcihjaGVja2xpc3QkY2hlY2tsaXN0X3ZhcikNCiAgZm9yKGkgaW4gMTpuT3B0aW9ucyl7IGNoZWNrbGlzdCRuZXcuY29sIDwtIE5BDQogICAgaWYoIWlzLm51bGwobGFiZWxzKSl7IGNvbG5hbWVzKGNoZWNrbGlzdClbaSsxXSA8LSBsYWJlbHNbaV0gfSBlbHNlIHsgY29sbmFtZXMoY2hlY2tsaXN0KVtpKzFdIDwtIHBhc3RlKCJpdGVtIixpLHNlcD0iIikgfX0NCiAgDQogIGZvcihpIGluIDE6bnJvdyhjaGVja2xpc3QpKXsNCiAgICBpZighaXMubmEoY2hlY2tsaXN0W2ksMV0pKXsgY2hlY2tsaXN0W2ksMjpuY29sKGNoZWNrbGlzdCldIDwtIDANCiAgICAgIGlmKGNoZWNrbGlzdFtpLDFdIT0iMCIpeyBzZWxlY3RlZCA8LSB1bmxpc3Qoc3Ryc3BsaXQoY2hlY2tsaXN0W2ksMV0sc2VwKSkNCiAgICAgICAgZm9yKGsgaW4gMTpsZW5ndGgoc2VsZWN0ZWQpKXsgY2hlY2tsaXN0W2ksc2VsZWN0ZWRba11dIDwtIDEgfX19fQ0KICBjaGVja2xpc3RbLDI6KG5PcHRpb25zKzEpXSA8LSBsYXBwbHkoY2hlY2tsaXN0WywyOihuT3B0aW9ucysxKV0sYXMuZmFjdG9yKQ0KICANCiAgIyBhZGRpbmcgbmV3IHZhcmlhYmxlcyB0byBkYXRhIChleGNsdWRpbmcgdGhlIGNhdGVnb3J5IHdpdGhvdXQgY29uZm91bmRlcnMpDQogIGRhdGEgPC0gY2JpbmQoZGF0YVssMTp3aGljaChjb2xuYW1lcyhkYXRhKT09dmFyTmFtZSldLGNoZWNrbGlzdFssMjoobmNvbChjaGVja2xpc3QpLTEpXSwNCiAgICAgICAgICAgICAgICBkYXRhWywod2hpY2goY29sbmFtZXMoZGF0YSk9PXZhck5hbWUpKzEpOm5jb2woZGF0YSldKQ0KICANCiAgIyByZWNvZGluZyB0aGUgb3JpZ2luYWwgdmFyaWFibGUgYXMgbG9naWNhbCAoVFJVRT1hbnkgY29uZm91bmRlciBjYXRlZ29yeSwgRkFMU0U9bm9uZSkNCiAgZGF0YSRvcmlnaW5hbFZhciA8LSBkYXRhWyx2YXJOYW1lXQ0KICBkYXRhWyx2YXJOYW1lXSA8LSBOQQ0KICBkYXRhWyFpcy5uYShkYXRhJG9yaWdpbmFsVmFyKSx2YXJOYW1lXSA8LSBUUlVFDQogIGRhdGFbIWlzLm5hKGRhdGEkb3JpZ2luYWxWYXIpICYgZGF0YSRvcmlnaW5hbFZhcj09IjAiLHZhck5hbWVdIDwtIEZBTFNFDQogIGRhdGEkb3JpZ2luYWxWYXIgPC0gTlVMTA0KICANCiAgIyBwcmludGluZyBzdW1tYXJ5DQogIHByaW50KHN1bW1hcnkobmEub21pdChjaGVja2xpc3RbLDE6NV0pKSkNCiAgDQogICMgcHJpbnRpbmcgcGVyY2VudGFnZXMNCiAgb3V0IDwtIHBhc3RlKCJcblxuUGVyY2VudGFnZSBvZiIsdmFyTmFtZSwib3ZlciB0b3RhbCBudW1iZXIgb2Ygb2NjYXNpb25zIHdpdGggbm9uLW1pc3NpbmcgdmFsdWVzOlxuIikNCiAgZm9yKFNDIGluIGxhYmVscyl7IGNvbG5hbWVzKGNoZWNrbGlzdClbd2hpY2goY29sbmFtZXMoY2hlY2tsaXN0KT09U0MpXSA8LSAiVmFyIg0KICAgIG91dCA8LSBwYXN0ZShvdXQsIi0gIixTQywiOiAiLA0KICAgICAgICAgICAgICAgICByb3VuZCgxMDAqbnJvdyhjaGVja2xpc3RbIWlzLm5hKGNoZWNrbGlzdCRjaGVja2xpc3RfdmFyKSAmIGNoZWNrbGlzdCRWYXIgPT0gIjEiLF0pDQogICAgICAgICAgICAgICAgICAgICAgIC9ucm93KGNoZWNrbGlzdFshaXMubmEoY2hlY2tsaXN0JGNoZWNrbGlzdF92YXIpLF0pLDIpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICIlXG4iLHNlcD0iIikNCiAgICBjb2xuYW1lcyhjaGVja2xpc3QpW3doaWNoKGNvbG5hbWVzKGNoZWNrbGlzdCk9PSJWYXIiKV0gPC0gU0MgfQ0KICBjYXQob3V0KQ0KICBpZihyZXR1cm4uZGF0YT09VFJVRSl7cmV0dXJuKGRhdGEpfX0NCmBgYA0KPC9wPg0KPC9kZXRhaWxzPg0KDQpgYGAge3J9DQojIG51bWJlciBhbmQgcGVyY2VudGFnZXMgZm9yIGVhY2ggY29uZm91bmRlcg0KZGlhcnkgPC0gY2hlY2tsaXN0X3NlcChkYXRhPWRpYXJ5LHZhck5hbWU9ImNvbmZvdW5kZXJzIixyZXR1cm4uZGF0YSA9IFRSVUUpDQpgYGANCg0KYGBgIHtyfQ0KIyBvdmVyYWxsIE5vLiBvZiBjYXNlcyB3aXRoIG9uZSBvciBtb3JlIGNvbmZvdW5kZXJzICg2MDQgVFJVRSwgMjMzNiBGQUxTRSwgMTUzIE5BKQ0Kc3VtbWFyeShkaWFyeSRjb25mb3VuZGVycykNCmBgYA0KDQoNCg0KPGJyPg0KDQojIyMgMi4yLjYuIHdha2VUaW1lIHJlY29kaW5nDQoNClRoZW4sIHdlIHJlY29kZSB0aGUgYHdha2VUaW1lYCB2YXJpYWJsZSwgd2hpY2ggd2FzIG1lYXN1cmVkIHdpdGggYW4NCm9wZW4tZW5kZWQgcXVlc3Rpb24uDQoNCmBgYCB7cn0NCiMgcmVjb2Rpbmcgd2FrZVRpbWUNCndha2VUaW1lcyA8LSBkaWFyeSR3YWtlVGltZQ0Kd2FrZVRpbWVzIDwtIGdzdWIoIlxcOyIsIjoiLGdzdWIoIlxcLiIsIlxcOiIsZ3N1YigiXFwsIiwiXFwuIixnc3ViKCJlIiwiOiIsZ3N1YigiICIsIiIsd2FrZVRpbWVzKSkpKSkNCndha2VUaW1lc1shaXMubmEod2FrZVRpbWVzKSAmIG5jaGFyKHdha2VUaW1lcyk9PTFdIDwtIHBhc3RlKCIwIix3YWtlVGltZXNbIWlzLm5hKHdha2VUaW1lcykgJiBuY2hhcih3YWtlVGltZXMpPT0xXSwiOjAwIixzZXA9IiIpDQp3YWtlVGltZXNbIWlzLm5hKHdha2VUaW1lcykgJiBuY2hhcih3YWtlVGltZXMpPT0yXSA8LSBwYXN0ZSh3YWtlVGltZXNbIWlzLm5hKHdha2VUaW1lcykgJiBuY2hhcih3YWtlVGltZXMpPT0yXSwiOjAwIixzZXA9IiIpDQp3YWtlVGltZXNbIWlzLm5hKGRpYXJ5JHdha2VUaW1lKSAmIHdha2VUaW1lcz09IjA2MTUiXSA8LSAiMDU6MTUiDQp3YWtlVGltZXNbIWlzLm5hKGRpYXJ5JHdha2VUaW1lKSAmIHdha2VUaW1lcz09IjA4MDAiXSA8LSAiMDg6MDAiDQp3YWtlVGltZXNbIWlzLm5hKGRpYXJ5JHdha2VUaW1lKSAmIHdha2VUaW1lcz09IjA4MzAiXSA8LSAiMDg6MzAiDQp3YWtlVGltZXNbIWlzLm5hKGRpYXJ5JHdha2VUaW1lKSAmIHdha2VUaW1lcz09IjA3MDAiXSA8LSAiMDc6MDAiDQp3YWtlVGltZXNbIWlzLm5hKHdha2VUaW1lcykgJiBuY2hhcih3YWtlVGltZXMpPT00XSA8LSBwYXN0ZSgiMCIsd2FrZVRpbWVzWyFpcy5uYSh3YWtlVGltZXMpICYgbmNoYXIod2FrZVRpbWVzKT09NF0sc2VwPSIiKQ0Kd2FrZVRpbWVzWyFpcy5uYSh3YWtlVGltZXMpICYgd2FrZVRpbWVzPT0iNjMwIl0gPC0gIjA2OjMwIg0KDQojIHdha2VUaW1lIGFzIFBPU0lYY3QgJiBoaEZyb21Bd2FrZQ0KbGlicmFyeShsdWJyaWRhdGUpDQpkaWFyeSR3YWtlVGltZSA8LSBhcy5QT1NJWGN0KHBhc3RlKHN1YnN0cihTeXMudGltZSgpLDEsMTApLHdha2VUaW1lcyksZm9ybWF0PSIlWS0lbS0lZCAlSDolTSIsdHo9IkdNVCIpDQpkaWFyeSRoaEZyb21Bd2FrZSA8LSBhcy5udW1lcmljKGRpZmZ0aW1lKGFzLlBPU0lYY3QocGFzdGUoc3Vic3RyKFN5cy50aW1lKCksMSwxMCksc3Vic3RyKGRpYXJ5JHN0YXJ0LDEyLDE2KSksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9ybWF0PSIlWS0lbS0lZCAlSDolTSIsdHo9IkdNVCIpLGRpYXJ5JHdha2VUaW1lLHVuaXRzPSJob3VycyIpKQ0KDQojIHNob3dpbmcgc29tZSBleGFtcGxlDQpoZWFkKGRpYXJ5WyFpcy5uYShkaWFyeSR3YWtlVGltZSksYygid2FrZVRpbWUiLCJzdGFydCIsImhoRnJvbUF3YWtlIildKQ0KYGBgDQoNCjxicj4NCg0KIyMgMi4zLiBEYXRhIGFub255bWl6YXRpb24NCg0KVGhpcmQsIHBhcnRpY2lwYW50cycgYElEYCAoY3VycmVudGx5IHRoZWlyIGUtbWFpbCBhZGRyZXNzZXMpIGFyZSAqKmFub255bWl6ZWQqKiAoaS5lLiwgcmVwbGFjZWQgd2l0aCBhbHBoYW51bWVyaWMgY29kZSBmcm9tIGBTMDAxYCB0bw0KYFNubm5gKS4NCg0KQmVmb3JlIGFub255bWl6aW5nIGBJRGAgdmFsdWVzLCB3ZSBmaWx0ZXIgY2FzZXMgb25seSBpbmNsdWRlZCBpbiBvbmUgYnV0IG5vdCBpbiB0aGUgb3RoZXIgZGF0YXNldC4NCmBgYCB7cn0NCiMgcHJlcGFyaW5nIHByZWxxcyBkYXRhDQpwcmVscXMkSUQgPC0gdG9sb3dlcihwcmVscXMkSUQpICMgYWxsIGUtbWFpbHMgaW4gbG93ZXIgY2FwaXRhbA0KcHJlbHFzLklEcyA8LSBsZXZlbHMoYXMuZmFjdG9yKHByZWxxcyRJRCkpICMgc2F2aW5nIG9yaWdpbmFsIElEcw0KDQojIGV4Y2x1ZGluZyBwcmUtcGlsb3QgZGlhcnkgZGF0YSB3aXRoIHRoZSBtYWluIGF1dGhvcg0KZGlhcnkgPC0gZGlhcnlbIShncmVwbCgiaW5pLmpvYiIsZGlhcnkkSUQpfGdyZXBsKCJ2YXJvQHN0IixkaWFyeSRJRCl8Z3JlcGwoInR0aUBzdHUiLGRpYXJ5JElEKXxncmVwbCgidHRpQHVuIixkaWFyeSRJRCkpLF0NCmRpYXJ5JElEIDwtIHRvbG93ZXIoZGlhcnkkSUQpICMgYWxsIGUtbWFpbHMgaW4gbG93ZXIgY2FwaXRhbA0KDQojIGNvcnJlY3Rpbmcgd3JvbmdseSByZXBvcnRlZCBlLW1haWwgYWRkcmVzc2VzIGluIGRpYXJ5IGRhdGENCmRpYXJ5JElEIDwtIGdzdWIoInRpZXJub0BzdHVkaW8udW5pYm8uaXQiLCJ0aWVybm9AbGliZXJvLml0IixkaWFyeSRJRCkgDQpkaWFyeSRJRCA8LSBnc3ViKCJ1enppZWxsMiIsInV6emllbGxvIixkaWFyeSRJRCkNCmRpYXJ5JElEIDwtIGdzdWIoInV6emllbGxvQGhvdG1haWwiLCJ1enppZWxsb0B1bmlibyIsZGlhcnkkSUQpDQpkaWFyeSRJRCA8LSBnc3ViKCJyaWFyb3NhLm0iLCJyb3NhLm0iLGdzdWIoIm9AYXVzbHJvbWFnbmEuaXQiLCJvQGdtYWlsLmNvbSIsZGlhcnkkSUQpKQ0KZGlhcnkkSUQgPC0gZ3N1Yigib0BhdXNsY2VzZW5hLml0Iiwib0BnbWFpbC5jb20iLGRpYXJ5JElEKQ0KZGlhcnkkSUQgPC0gZ3N1YigiZ21zaWwiLCJnbWFpbCIsZGlhcnkkSUQpDQpkaWFyeSRJRCA8LSBnc3ViKCJnbWFpbC5jb24iLCJnbWFpbC5jb20iLGRpYXJ5JElEKQ0KZGlhcnkkSUQgPC0gZ3N1YigibGxpLnJvYm9AIiwibGxpLnJvYmlAIixkaWFyeSRJRCkNCmRpYXJ5JElEIDwtIGdzdWIoIm9mZmljaWEiLCJvZmZpY2luYSIsZGlhcnkkSUQpDQpkaWFyeSRJRCA8LSBnc3ViKCJAbGliZXJpIiwiQGxpYmVybyIsZ3N1YigiQGxpZGVybyIsIkBsaWJlcm8iLGdzdWIoIkBsbGlicm8iLCJAbGliZXJvIixkaWFyeSRJRCkpKQ0KZGlhcnkkSUQgPC0gZ3N1YigiZmNpYmllbiIsImYuY2liaWVuIixnc3ViKCJrbGFyY28uY29tIiwia2xhcmNvLml0IixkaWFyeSRJRCkpDQpJRHMgPC0gbGV2ZWxzKGFzLmZhY3RvcihkaWFyeSRJRCkpDQoNCiMgc2FuaXR5IGNoZWNrcw0KY2F0KGxlbmd0aChJRHMpLCJwYXJ0aWNpcGFudHMgaW4gZGlhcnkgZGF0YSwiLGxlbmd0aChwcmVscXMuSURzKSwiaW4gcHJlbHFzIGRhdGFcbiIsDQogICAgbGVuZ3RoKElEc1shKElEcyVpbiVwcmVscXMuSURzKV0pLCJjYXNlcyBpbiBkaWFyeSBidXQgbm90IGluIHByZWxxc1xuIiwNCiAgICBsZW5ndGgocHJlbHFzLklEc1shKHByZWxxcy5JRHMlaW4lSURzKV0pLCJjYXNlcyBpbiBwcmVscXMgYnV0IG5vdCBpbiBkaWFyeSIpDQpgYGANCg0KYGBgIHtyfQ0KIyByZW1vdmluZyBjYXNlcyBvbmx5IGluY2x1ZGVkIHByZWxxcyBidXQgbm90IGluIGRpYXJ5DQptZW1vcnkgPC0gcHJlbHFzDQpwcmVscXMgPC0gcHJlbHFzW3ByZWxxcyRJRCAlaW4lIElEcyxdDQpwcmVscXMuSURzIDwtIGxldmVscyhhcy5mYWN0b3IocHJlbHFzJElEKSkNCmNhdCgiUmVtb3ZlZCIsbnJvdyhtZW1vcnkpLW5yb3cocHJlbHFzKSwicGFydGljaXBhbnRzIG9ubHkgaW5jbHVkZWQgaW4gcHJlbHFzIGRhdGEiKQ0KDQojIHJlbW92aW5nIGNhc2VzIG9ubHkgaW5jbHVkZWQgaW4gZGlhcnkgYnV0IG5vdCBpbiBwcmVscXMNCm1lbW9yeSA8LSBkaWFyeQ0KZGlhcnkgPC0gZGlhcnlbZGlhcnkkSUQgJWluJSBwcmVscXMuSURzLF0NCklEcyA8LSBsZXZlbHMoYXMuZmFjdG9yKGRpYXJ5JElEKSkNCmNhdCgiUmVtb3ZlZCIsbmxldmVscyhhcy5mYWN0b3IobWVtb3J5JElEKSktbGVuZ3RoKElEcyksInBhcnRpY2lwYW50cywiLG5yb3cobWVtb3J5KS1ucm93KGRpYXJ5KSwNCiAgICAib2JzZXJ2YXRpb25zIG9ubHkgaW5jbHVkZWQgaW4gZGlhcnkgZGF0YSIpDQoNCiMgc2FuaXR5IGNoZWNrcw0KY2F0KGxlbmd0aChJRHMpLCJwYXJ0aWNpcGFudHMgaW4gZGlhcnkgZGF0YSwiLGxlbmd0aChwcmVscXMuSURzKSwiaW4gcHJlbHFzIGRhdGFcbiIsDQogICAgbGVuZ3RoKElEc1shKElEcyVpbiVwcmVscXMuSURzKV0pLCJjYXNlcyBpbiBkaWFyeSBidXQgbm90IGluIHByZWxxc1xuIiwNCiAgICBsZW5ndGgocHJlbHFzLklEc1shKHByZWxxcy5JRHMlaW4lSURzKV0pLCJjYXNlcyBpbiBwcmVscXMgYnV0IG5vdCBpbiBkaWFyeSIpDQpgYGANCg0KPGJyPg0KDQpXZSBhbHNvIGNvcnJlY3QgYSBudW1iZXIgb2YgaXNzdWVzIHdpdGggYGRpYXJ5YCB0aW1lIHBvaW50cyBkdWUgdG8gcGFydGljaXBhbnRzIGFuc3dlcmluZyB0byB0aGUgd3JvbmcgbGluay4NCg0KYGBgIHtyfQ0KIyBjb3JyZWN0aW5nIHN1cnZleXMgdGFrZW4gYXQgd3JvbmcgdGltZSBwb2ludHMNCmRpYXJ5W3N1YnN0cihkaWFyeSRJRCwxNSwyNyk9PSJybm9AZ21haWwuY29tIiAmIA0KICAgICAgICBhcy5jaGFyYWN0ZXIoZGlhcnkkc3RhcnQpICVpbiUgYygiMjAyMS0xMC0yNiAyMToyNjo0MyIsIjIwMjEtMTEtMDIgMjE6MjE6NTEiKSwNCiAgICAgICJkaWFyeVR5cGUiXSA8LSAiRSIgIyBwYXJ0aWNpcGFudCB3aG8gcmVzcG9uZGVkIHR3aWNlIHRvIEFmdGVybm9vbiBkaWFyeSBpbiBFdmVuaW5nIHRpbWUgKGtlZXBpbmcgb25seSBCUCB2YWx1ZXMpDQpkaWFyeVtzdWJzdHIoZGlhcnkkSUQsMTUsMjcpPT0icm5vQGdtYWlsLmNvbSIgJiANCiAgICAgICAgYXMuY2hhcmFjdGVyKGRpYXJ5JHN0YXJ0KSAlaW4lIGMoIjIwMjEtMTAtMjYgMjE6MjY6NDMiLCIyMDIxLTExLTAyIDIxOjIxOjUxIiksDQogICAgICB3aGljaChjb2xuYW1lcyhkaWFyeSk9PSJXTDEiKTp3aGljaChjb2xuYW1lcyhkaWFyeSk9PSJXRTMiKV0gPC0gTkENCmRpYXJ5W3N1YnN0cihkaWFyeSRJRCw4LDEzKT09ImlzYS5tYSIgJiAjIHBhcnRpY2lwYW50cyB0aGF0IHJlc3BvbmRlZCB0byBhIGxpbmsgb3BlbiBvbiB0aGUgcHJldmlvdXMgZGF5DQogICAgICAgICFpcy5uYShkaWFyeSRXSExTTTMpICYgYXMuY2hhcmFjdGVyKGRpYXJ5JHN0YXJ0KT09IjIwMjItMDEtMjUgMTA6NDU6MDAiLA0KICAgICAgInN0YXJ0Il0gPC0gYXMuY2hhcmFjdGVyKGFzLlBPU0lYY3QoZGlhcnlbc3Vic3RyKGRpYXJ5JElELDgsMTMpPT0iaXNhLm1hIiAmICFpcy5uYShkaWFyeSRXSExTTTMpICYgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYXMuY2hhcmFjdGVyKGRpYXJ5JHN0YXJ0KT09IjIwMjItMDEtMjUgMTA6NDU6MDAiLCJlbmQiXSkgLQ0KICBtZWFuKGFzLm51bWVyaWMoZGlmZnRpbWUoZGlhcnlbc3Vic3RyKGRpYXJ5JElELDgsMTMpPT0iaXNhLm1hIiAmIGRpYXJ5JHN0YXJ0IT0iMjAyMi0wMS0yNSAxMDo0NTowMCIsImVuZCJdLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgZGlhcnlbc3Vic3RyKGRpYXJ5JElELDgsMTMpPT0iaXNhLm1hIiAmIGRpYXJ5JHN0YXJ0IT0iMjAyMi0wMS0yNSAxMDo0NTowMCIsInN0YXJ0Il0sdW5pdHM9InNlY3MiKSkpKQ0KZGlhcnkgPC0gZGlhcnlbIShzdWJzdHIoZGlhcnkkSUQsOCwxMyk9PSJtb0BtZGEiICYgZGlhcnkkc3RhcnQlaW4lYygiMjAyMi0wMS0yNSAxNjozOToyMiIsIjIwMjItMDEtMjYgMjA6MDA6MjEiKSksXSAjIGRvdWJsZSByZXNwDQpkaWFyeVtncmVwbCgiYWlhNzkiLGRpYXJ5JElEKSAmIGFzLmNoYXJhY3RlcihkaWFyeSRzdGFydCk9PSIyMDIyLTAzLTEwIDA3OjI1OjMyIiwiZGlhcnlUeXBlIl0gPC0gDQogICJNIiAjIHBhcnRpY2lwYW50IHRoYXQgcmVzcG9uZGVkIHRvIHRoZSBFdmVuaW5nIGRpYXJ5IGluIE1vcm5pbmcgdGltZSAoa2VlcGluZyBvbmx5IEJQIHZhbHVlcyBhbmQgY2hhbmdpbmcgYXMgTW9ybmluZykNCmRpYXJ5W2dyZXBsKCJhaWE3OSIsZGlhcnkkSUQpICYgYXMuY2hhcmFjdGVyKGRpYXJ5JHN0YXJ0KT09IjIwMjItMDMtMTAgMDc6MjU6MzIiLA0KICAgICAgd2hpY2goY29sbmFtZXMoZGlhcnkpPT0iRUUxIik6d2hpY2goY29sbmFtZXMoZGlhcnkpPT0id29ya0hvdXJzIildIDwtIE5BDQpkaWFyeSA8LSAjIHBhcnRpY2lwYW50IHRoYXQgcmVzcG9uZGVkIHR3aWNlIHRvIHRoZSBNb3JuaW5nIGRpYXJ5IA0KICBkaWFyeVshKGdyZXBsKCJiYXNzbzg3IixkaWFyeSRJRCkgJiBhcy5jaGFyYWN0ZXIoZGlhcnkkc3RhcnQpPT0iMjAyMi0wMy0wNyAxOTo1Mzo0NyIpLF0NCg0KIyBjb3JyZWN0aW5nIHdyb25nbHkgcmVwb3J0ZWQgQlAgdmFsdWVzDQpkaWFyeVtzdWJzdHIoZGlhcnkkSUQsMTgsMzIpPT0ibmEuaXNhc2kuY25yLml0IiAmIGFzLmNoYXJhY3RlcihkaWFyeSRzdGFydCk9PSIyMDIxLTExLTI1IDE5OjE3OjI3IiwiU0JQMiJdIDwtIA0KICAxMzMgIyByZXBvcnRlZCBhcyA4ODEzMw0KYGBgDQoNCjxicj4NCg0KIyMjIDIuMy4xLiBQcmVsaW1pbmFyeSBxdWVzdGlvbm5haXJlDQoNCkhlcmUsIHdlIGFub255bWl6ZSBgcHJlbHFzYCBgSURgIHZhbHVlcy4NCmBgYCB7cn0NCiMgcmVwbGFjaW5nIHBhcnRpY2lwYW50cycgZS1tYWlsIHdpdGggYWxwaGFudW1lcmljIGNvZGUgKGUuZy4sIFMwMDEpDQpwcmVscXMgPC0gcHJlbHFzW29yZGVyKHByZWxxcyRJRCksXSAjIHNvcnRpbmcgYnkgSUQNCmZvcihJRCBpbiBwcmVscXMuSURzKXsgaWQgPC0gcGFzdGUoIlMiLHdoaWNoKHByZWxxcy5JRHM9PUlEKSxzZXA9IiIpIA0KICBpZihuY2hhcihpZCk+Mil7IGlmKG5jaGFyKGlkKT4zKXsgcHJlbHFzW3ByZWxxcyRJRD09SUQsIklEIl0gPC0gaWQNCiAgfSBlbHNlIHsgcHJlbHFzW3ByZWxxcyRJRD09SUQsIklEIl0gPC0gZ3N1YigiUyIsIlMwIixpZCkgfQ0KICAgIH0gZWxzZSB7IHByZWxxc1twcmVscXMkSUQ9PUlELCJJRCJdIDwtIGdzdWIoIlMiLCJTMDAiLGlkKSB9DQogIHByZWxxc1twcmVscXMkSUQ9PUlELCJJRCJdIDwtIGlmZWxzZShuY2hhcihpZCk9PTMsaWQscGFzdGUoIlMwIix3aGljaChwcmVscXMuSURzPT1JRCksc2VwPSIiKSl9DQpwcmVscXMkSUQgPC0gYXMuZmFjdG9yKHByZWxxcyRJRCkNCg0KIyBzYW5pdHkgY2hlY2sNCmhlYWQobGV2ZWxzKHByZWxxcyRJRCkpDQpjYXQobmxldmVscyhwcmVscXMkSUQpLCJwYXJ0aWNpcGFudHMsIixucm93KHByZWxxcyksIm9ic2VydmF0aW9ucyIpICMgMTQ3LCAxNDcNCmBgYA0KDQo8YnI+DQoNCiMjIyAyLjMuMi4gRGFpbHkgZGlhcmllcw0KDQpIZXJlLCB3ZSBhbm9ueW1pemUgYGRpYXJ5YCBgSURgIHZhbHVlcy4NCmBgYHtyfQ0KIyByZXBsYWNpbmcgcGFydGljaXBhbnRzJyBlLW1haWwgd2l0aCBhbHBoYW51bWVyaWMgY29kZSAoZS5nLiwgUzAwMSkNCmRpYXJ5IDwtIGRpYXJ5W29yZGVyKGRpYXJ5JElELGRpYXJ5JHN0YXJ0KSxdICMgc29ydGluZyBieSBJRCBhbmQgc3RhcnQgdGltZQ0KZm9yKElEIGluIElEcyl7IGlkIDwtIHBhc3RlKCJTIix3aGljaChJRHM9PUlEKSxzZXA9IiIpICMgcmVwbGFjaW5nIHBhcnRpY2lwYW50cycgZS1tYWlsIHdpdGggYWxwaGFudW1lcmljIGNvZGUgKGUuZy4sIFMwMDEpDQogIGlmKG5jaGFyKGlkKT4yKXsgaWYobmNoYXIoaWQpPjMpeyBkaWFyeVtkaWFyeSRJRD09SUQsIklEIl0gPC0gaWQNCiAgfSBlbHNlIHsgZGlhcnlbZGlhcnkkSUQ9PUlELCJJRCJdIDwtIGdzdWIoIlMiLCJTMCIsaWQpIH0NCiAgICB9IGVsc2UgeyBkaWFyeVtkaWFyeSRJRD09SUQsIklEIl0gPC0gZ3N1YigiUyIsIlMwMCIsaWQpIH0NCiAgZGlhcnlbZGlhcnkkSUQ9PUlELCJJRCJdIDwtIGlmZWxzZShuY2hhcihpZCk9PTMsaWQscGFzdGUoIlMwIix3aGljaChJRHM9PUlEKSxzZXA9IiIpKX0NCmRpYXJ5JElEIDwtIGFzLmZhY3RvcihkaWFyeSRJRCkNCg0KIyBzYW5pdHkgY2hlY2sNCmhlYWQobGV2ZWxzKGRpYXJ5JElEKSkNCmBgYA0KDQpgYGAge3J9DQpjYXQobmxldmVscyhkaWFyeSRJRCksInBhcnRpY2lwYW50cywiLG5yb3coZGlhcnkpLCJvYnNlcnZhdGlvbnMiKSAjIDE0NywzMDc3DQpgYGANCg0KPGJyPg0KDQojIDMuIERhdGEgcHJvY2Vzc2luZw0KDQpBcyBhIGZpbmFsIHByZS1wcm9jZXNzaW5nIHN0ZXAsIHdlIHByb2Nlc3MgYGRpYXJ5YCBkYXRhIGJ5IGluY2x1ZGluZyBhIGBkYXlgIHZhcmlhYmxlLCBieSBpbnNwZWN0aW5nIGFuZCByZWNvZGluZyBgQlBgIChibG9vZCBwcmVzc3VyZSkgYW5kIGBCTUlgIChib2R5IG1hc3MgaW5kZXgpIGRhdGEsIGJ5IHN3aXRjaGluZyBmcm9tIHRoZSBjdXJyZW50IGxvbmcgZm9ybSB0byBhICoqd2lkZSBmb3JtKiogd2l0aCBvbmUgcm93IHBlciBkYXksIGJ5IG1lcmdpbmcgdGhlIGBkaWFyeWAgYW5kIHRoZSBgcHJlbHFzYCBkYXRhc2V0cywgYW5kIGJ5IGluc3BlY3RpbmcgY2FzZXMgb2YgaW5jb2hlcmVudC9pbmNvbnNpc3RlbnQgcmVzcG9uc2VzIGluIHRoZSBjb25zaWRlcmVkIHZhcmlhYmxlcy4NCg0KIyMgMy4xLiBBc3Nlc3NtZW50IGRheQ0KDQpGaXJzdCwgd2UgY3JlYXRlIHRoZSB2YXJpYWJsZSAqZGF5KiBpbmRpY2F0aW5nIHRoZSBkYXkgZm9yIHBhcnRpY2lwYXRpb24gKGkuZS4sIDEgPSBNb25kYXksIDIgPSBUdWVzZGF5LCAzID0gV2VkbmVzZGF5LCA0ID0gVGh1cnNkYXksIDUgPSBGcmlkYXksIDcgPSBNb25kYXkgd2VlayBJSSwgOCA9IFR1ZXNkYXkgd2VlayBJSSwgOSA9IFdlZG5lc2RheSB3ZWVrIElJLCAxMCA9IFRodXJzZGF5IHdlZWsgSUksIDExID0gRnJpZGF5IHdlZWsgSUkpLiBOb3RlIHRoYXQgdGhpcyB2YXJpYWJsZSBpcyByZWNvZGVkIHRvIGJlICoqcmVmZXJyZWQgdG8gdGhlIHByZXZpb3VzIGRheSoqIGluIGNhc2VzIG9mICoqRXZlbmluZyBkaWFyaWVzIGZpbGxlZCBhZnRlciAwMDowMCoqLCBhbmQgaW4gKiphbGwgTW9ybmluZyBkaWFyaWVzKiouIFdlIGFsc28gcmVtb3ZlIDUgdW5leHBlY3RlZCByZXNwb25zZXMgb24gZGF5IDYgYW5kIDEyIChTYXR1cmRheSBhZnRlcm5vb24gb3IgU3VuZGF5KS4NCmBgYCB7cn0NCiMgY3JlYXRpbmcgZGF5DQpkaWFyeSRkYXkgPC0gYXMuUE9TSVhsdChkaWFyeSRzdGFydCkkd2RheQ0KDQojIGFkZGluZyA2IGRheXMgdG8gdGhlIHNlY29uZCB3ZWVrDQpmb3IoaSBpbiAyOm5yb3coZGlhcnkpKXsNCiAgaWYoZGlhcnlbaSwiSUQiXT09ZGlhcnlbaS0xLCJJRCJdICYgZGlhcnlbaSwiZGF5Il0gPCBkaWFyeVtpLTEsImRheSJdKXsgZGlhcnlbaSwiZGF5Il0gPC0gZGlhcnlbaSwiZGF5Il0gKyA2IH19DQoNCiMgY29ycmVjdGluZyBldmVuaW5nIGRheXMgd2hlbiBzdGFydCBpcyBhZnRlciBtaWRuaWdodA0KZm9yKGkgaW4gMTpucm93KGRpYXJ5KSl7DQogIGlmKGRpYXJ5W2ksImRpYXJ5VHlwZSJdPT0iRSIgJiBkaWFyeVtpLCJzdGFydCJdIDwgYXMuUE9TSVhjdChwYXN0ZShzdWJzdHIoZGlhcnlbaSwic3RhcnQiXSwxLDEwKSwiMDc6MDA6MDAiKSkpew0KICAgIGRpYXJ5W2ksImRheSJdIDwtIGRpYXJ5W2ksImRheSJdIC0gMSB9fQ0KDQojIHN1YnRyYWN0aW5nIG9uZSBkYXkgdG8gYWxsIE1vcm5pbmcgZGlhcmllcw0KZGlhcnlbZGlhcnkkZGlhcnlUeXBlPT0iTSIsImRheSJdIDwtIGRpYXJ5W2RpYXJ5JGRpYXJ5VHlwZT09Ik0iLCJkYXkiXSAtIDENCg0KIyBjaGVja2luZyBjYXNlcyB3aXRoIHVuZXhwZWN0ZWQgdmFsdWVzICg2IG9yIDEyID0gTW9ybmluZyBvbiBNb24sIEV2ZW5pbmcvQWZ0ZXJub29uIG9uIFNhdCkNCnRhYmxlKGRpYXJ5JGRheSkNCmBgYA0KDQo8YnI+DQoNCmBgYCB7cn0NCiMgaW5zcGVjdGluZyBjYXNlcyB3aXRoIHVuZXhwZWN0ZWQgdmFsdWVzICg2IG9yIDEyID0gTW9ybmluZyBvbiBNb24sIEV2ZW5pbmcvQWZ0ZXJub29uIG9uIFNhdCkNCmNiaW5kKHdkYXk9YXMuUE9TSVhsdChkaWFyeVtkaWFyeSRkYXklaW4lYyg2LDEyKSwic3RhcnQiXSkkd2RheSwNCiAgICAgIGRpYXJ5W2RpYXJ5JGRheSVpbiVjKDYsMTIpLGMoIklEIiwiZGF5Iiwic3RhcnQiLCJTQlAxIiwiV0wxIiwiRUUxIiwiU1ExIiwiZGF5T2ZmIiwiZGF5T2ZmeWVzdGVyZGF5IildKQ0KYGBgDQoNCjxicj4NCg0KYGBgIHtyfQ0KZGlhcnkgPC0gZGlhcnlbIWRpYXJ5JGRheSVpbiVjKDYsMTIpLF0gIyByZW1vdmluZyA1IHVuZXhwZWN0ZWQgcmVzcG9uc2VzIA0KDQojIHNhbml0eSBjaGVjaw0KZGlhcnlbLGMoIklEIiwic3RhcnQiLCJkaWFyeVR5cGUiLCJkYXkiKV0NCmBgYA0KDQo8YnI+DQoNCiMjIDMuMi4gQmxvb2QgcHJlc3N1cmUNCg0KSGVyZSwgd2UgdmlzdWFsbHkgaW5zcGVjdCB0aGUgZGlzdHJpYnV0aW9ucyBhbmQgdGVtcG9yYWwgdHJlbmRzIG9mICoqYmxvb2QgcHJlc3N1cmUqKiBgQlBgIHZhbHVlcyBhZ2FpbnN0ICoqbm9ybWF0aXZlIHZhbHVlcyoqIGFuZA0Kc2VwYXJhdGVseSBieSB0aGUgKipwZXJpb2Qgb2YgdGhlIGRheSoqLiBUaGVuLCB3ZSBwcm9jZXNzIHRoZSBzaWduYWwsIGFuZCB3ZSBjb21wdXRlIHRoZSBhZ2dyZWdhdGUgYEJQYCB2YWx1ZXMuDQoNCkZpcnN0LCB3ZSBwcmVwYXJlIHRoZSBkYXRhIGZvciB0aGUgaW5zcGVjdGlvbiBhbmQgcHJvY2Vzc2luZywgYnkgY3JlYWRpbmcgYSAqKmxvbmcgZm9ybSoqIGRhdGFzZXQgd2l0aCBvbmUgcm93IGZvciBlYWNoIGBCUGAgcmVjb3JkaW5nLg0KDQpgYGAge3J9DQojIHByZXBhcmluZyBkYXRhc2V0DQpkaWFyeV9sb25nIDwtIGRhdGEuZnJhbWUoSUQ9cmVwKGRpYXJ5JElELDQpLG1lYXN1cmU9YyhyZXAoIlNCUDEiLG5yb3coZGlhcnkpKSxyZXAoIlNCUDIiLG5yb3coZGlhcnkpKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlcCgiREJQMSIsbnJvdyhkaWFyeSkpLHJlcCgiREJQMiIsbnJvdyhkaWFyeSkpKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICBCUD1jKGRpYXJ5JFNCUDEsZGlhcnkkU0JQMixkaWFyeSREQlAxLGRpYXJ5JERCUDIpLGRpYXJ5VHlwZT1yZXAoZGlhcnkkZGlhcnlUeXBlLDQpKQ0KZGlhcnlfbG9uZyRnZW5kZXI9cGx5cjo6am9pbihkaWFyeV9sb25nLHByZWxxc1ssYygiSUQiLCJnZW5kZXIiKV0sdHlwZT0ibGVmdCIsYnk9IklEIikkZ2VuZGVyDQpkaWFyeV9sb25nJGN2X2Q9cGFzdGUocGx5cjo6am9pbihkaWFyeV9sb25nLHByZWxxc1ssYygiSUQiLCJjdl9keXNmIildLHR5cGU9ImxlZnQiLGJ5PSJJRCIpJGN2X2R5c2YsDQogICAgICAgICAgICAgICAgICAgICAgcGx5cjo6am9pbihkaWFyeV9sb25nLHByZWxxc1ssYygiSUQiLCJicF9kcnVncyIpXSx0eXBlPSJsZWZ0IixieT0iSUQiKSRicF9kcnVncyxzZXA9Il8iKQ0KYGBgDQoNCjxicj4NCg0KIyMjIDMuMi4xLiBCUCBkaXN0cmlidXRpb25zIHsjYnAtZGlzdHJpYnV0aW9ucyAudGFic2V0IC50YWJzZXQtZmFkZSAudGFic2V0LXBpbGxzfQ0KDQpIZXJlLCB3ZSB2aXN1YWxpemUgYEJQYCBkaXN0cmlidXRpb25zIGJ5IHBsb3R0aW5nIHRoZW0gYWdhaW5zdCAqKm5vcm1hdGl2ZSB2YWx1ZXMqKi4NCg0KIyMjIyB2cy4gRVNIL0VTQyBHdWlkZWxpbmVzICgyMDE4KQ0KDQpGaXJzdCwgd2UgaW5zcGVjdCB0aGUgZGlzdHJpYnV0aW9uIG9mIHRoZSBvYnNlcnZlZCBgQlBgIG1lYXN1cmVtZW50cywgYWNjb3VudGluZyBmb3IgdGhlIGN1dC1vZmYgdmFsdWVzIHJlY29tbWVuZGVkIGJ5IHRoZSBbRVNIL0VTQyBHdWlkZWxpbmVzICgyMDE4KV0oI3JlZikuIFdlIGNhbiBzZWUgdGhhdCBgQlBgIHZhbHVlcyBhcmUgcXVpdGUgbm9ybWFsbHkgZGlzdHJpYnV0ZWQgKGFsdGhvdWdoIHdpdGggc29tZSBjYXNlcyBzaG93aW5nIGJpbW9kYWwgZGlzdHJpYnV0aW9uKSBhbmQgY2VudGVyZWQgYmVsb3cgdGhlIGN1dC1vZmZzIGZvciBoeXBlcnRlbnNpb24sIHdpdGggYSAqKnNtYWxsIHByb3BvcnRpb24gb2YgbWVhc3VyZW1lbnRzIChcfiA5LTExJSkgYWJvdmUgdGhlIGN1dC1vZmZzKiouIEhpZ2hlciBgU0JQYCBhbmQgYERCUGAgaXMgc2hvd2VkIGluIHBhcnRpY2lwYW50cyByZXBvcnRpbmcgc3VmZmVyaW5nIGZyb20gY2FyZGlvdmFzY3VsYXIgZHlzZnVuY3Rpb25zIGFuZC9vciB0YWtpbmcgQlAgbWVkaWNhdGlvbnMuIFNsaWdodGx5IGhpZ2hlciBzeXN0b2xpYyBgQlBgIGlzIHJlcG9ydGVkIGJ5IG1lbiBjb21wYXJlZCB0byB3b21lbiwgYW5kIGR1cmluZyBhZnRlcm5vb24gY29tcGFyZWQgdG8gbW9ybmluZyBhbmQgZXZlbmluZy4gT3ZlcmFsbCwgdGhlIGRhdGEgbG9vayByZWFsaXN0aWMsIGFsdGhvdWdoICoqZGlhc3RvbGljIEJQIGxvb2tzIGJvdW5kZWQgYXQgNDAgbW1IZyoqLg0KDQpgYGAge3IgZmlnLndpZHRoPTEyLGZpZy5oZWlnaHQ9OCx3YXJuaW5nPUZBTFNFfQ0KbGlicmFyeShnZ3Bsb3QyKTsgbGlicmFyeShncmlkRXh0cmEpDQoNCiMgcHJlcGFyaW5nIGRhdGFzZXQNCmRpYXJ5X2xvbmcgPC0gZGF0YS5mcmFtZShJRD1yZXAoZGlhcnkkSUQsNCksbWVhc3VyZT1jKHJlcCgiU0JQMSIsbnJvdyhkaWFyeSkpLHJlcCgiU0JQMiIsbnJvdyhkaWFyeSkpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVwKCJEQlAxIixucm93KGRpYXJ5KSkscmVwKCJEQlAyIixucm93KGRpYXJ5KSkpLA0KICAgICAgICAgICAgICAgICAgICAgICAgIEJQPWMoZGlhcnkkU0JQMSxkaWFyeSRTQlAyLGRpYXJ5JERCUDEsZGlhcnkkREJQMiksZGlhcnlUeXBlPXJlcChkaWFyeSRkaWFyeVR5cGUsNCkpDQpkaWFyeV9sb25nJGdlbmRlcj1wbHlyOjpqb2luKGRpYXJ5X2xvbmcscHJlbHFzWyxjKCJJRCIsImdlbmRlciIpXSx0eXBlPSJsZWZ0IixieT0iSUQiKSRnZW5kZXINCmRpYXJ5X2xvbmckY3ZfZD1wYXN0ZShwbHlyOjpqb2luKGRpYXJ5X2xvbmcscHJlbHFzWyxjKCJJRCIsImN2X2R5c2YiKV0sdHlwZT0ibGVmdCIsYnk9IklEIikkY3ZfZHlzZiwNCiAgICAgICAgICAgICAgICAgICAgICBwbHlyOjpqb2luKGRpYXJ5X2xvbmcscHJlbHFzWyxjKCJJRCIsImJwX2RydWdzIildLHR5cGU9ImxlZnQiLGJ5PSJJRCIpJGJwX2RydWdzLHNlcD0iXyIpDQoNCmdyaWQuYXJyYW5nZSggIyBwbG90dGluZyBzaXN0b2xpYyBhbmQgZGlhc3RvbGljIEJQIG1lYXN1cmVtZW50cw0KICBnZ3Bsb3QobmEub21pdChkaWFyeV9sb25nKSxhZXMoeD1tZWFzdXJlLHk9QlAsZ3JvdXA9bWVhc3VyZSkpICsgZ2VvbV9wb2ludChjb2xvcj0iZ3JheSIscG9zaXRpb249cG9zaXRpb25faml0dGVyKCkpICsgDQogICAgZ2VvbV92aW9saW4oYWxwaGE9MC40KSArIGdlb21fYm94cGxvdChhbHBoYT0wLjQsb3V0bGllci5hbHBoYT0wKSArIHlsYWIoIkJsb29kIHByZXNzdXJlIChtbUhnKSIpICsNCiAgICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQgPSBjKDEzNSw4NSksY29sb3I9InJlZCIsbHR5PTIpLCAjIGFkZGluZyAyMDEzIEVTSC9FU0MgR3VpZGVsaW5lcyBjdXQtb2ZmcyBmb3IgaHlwZXJ0ZW5zaW9uDQogIGdncGxvdChuYS5vbWl0KGRpYXJ5X2xvbmcpLGFlcyh4PW1lYXN1cmUseT1CUCxmaWxsPWdlbmRlcikpICsgZ2VvbV9wb2ludChjb2xvcj0iZ3JheSIscG9zaXRpb249cG9zaXRpb25faml0dGVyKCkpICsgIyBieSBnZW5kZXINCiAgICBnZW9tX3Zpb2xpbihhbHBoYT0wLjQpICsgZ2VvbV9ib3hwbG90KGFscGhhPTAuNCxvdXRsaWVyLmFscGhhPTApICsgeWxhYigiQmxvb2QgcHJlc3N1cmUgKG1tSGcpIiksDQogIGdncGxvdChuYS5vbWl0KGRpYXJ5X2xvbmcpLGFlcyh4PW1lYXN1cmUseT1CUCxmaWxsPWN2X2QpKSArIGdlb21fcG9pbnQoY29sb3I9ImdyYXkiLHBvc2l0aW9uPXBvc2l0aW9uX2ppdHRlcigpKSArIA0KICAgIGdlb21fdmlvbGluKGFscGhhPTAuNCkgKyBnZW9tX2JveHBsb3QoYWxwaGE9MC40LG91dGxpZXIuYWxwaGE9MCkgKyB5bGFiKCJCbG9vZCBwcmVzc3VyZSAobW1IZykiKSwgIyBieSBjdl9keXNmICYgYnBfZHJ1Z3MNCiAgZ2dwbG90KG5hLm9taXQoZGlhcnlfbG9uZyksYWVzKHg9bWVhc3VyZSx5PUJQLGZpbGw9ZGlhcnlUeXBlKSkgKyBnZW9tX3BvaW50KGNvbG9yPSJncmF5Iixwb3NpdGlvbj1wb3NpdGlvbl9qaXR0ZXIoKSkgKyANCiAgICBnZW9tX3Zpb2xpbihhbHBoYT0wLjQpICsgZ2VvbV9ib3hwbG90KGFscGhhPTAuNCxvdXRsaWVyLmFscGhhPTApICsgeWxhYigiQmxvb2QgcHJlc3N1cmUgKG1tSGcpIiksbnJvdz0yKSAjIGJ5IHRpbWUgb2YgZGF5DQoNCiMgTm8uIGFuZCAlIG9mIFNCUCA+IDEzMCBtbUhHDQpucyA8LSBucm93KGRpYXJ5X2xvbmdbIWlzLm5hKGRpYXJ5X2xvbmckQlApJmRpYXJ5X2xvbmckbWVhc3VyZSVpbiVjKCJTQlAxIiwiU0JQMiIpJmRpYXJ5X2xvbmckQlA+MTM1LF0pDQpuZCA8LSBucm93KGRpYXJ5X2xvbmdbIWlzLm5hKGRpYXJ5X2xvbmckQlApJmRpYXJ5X2xvbmckbWVhc3VyZSVpbiVjKCJEQlAxIiwiREJQMiIpJmRpYXJ5X2xvbmckQlA+ODUsXSkNCmNhdChucywiKCIscm91bmQoMTAwKm5zL25yb3coZGlhcnlfbG9uZ1shaXMubmEoZGlhcnlfbG9uZyRCUCksXSksMSksIiUgKSBTQlAgdmFsdWVzIGFib3ZlIDEzMCBtbUhnXG4iLA0KICAgIG5kLCIoIixyb3VuZCgxMDAqbmQvbnJvdyhkaWFyeV9sb25nWyFpcy5uYShkaWFyeV9sb25nJEJQKSxdKSwxKSwiJSApIERCUCB2YWx1ZXMgYWJvdmUgODUgbW1IZ1xuIikNCg0KIyBtaW51bXVtIGRpYXN0b2xpYyBCUA0KbWluKGRpYXJ5X2xvbmdbZGlhcnlfbG9uZyRtZWFzdXJlJWluJWMoIkRCUDEiLCJEQlAyIiksIkJQIl0sbmEucm09VFJVRSkNCmBgYA0KDQo8YnI+DQoNCiMjIyMgdnMuIFdlaXNzZXIgZXQgYWwgKDIwMDApDQoNCkhlcmUsIHdlIGNvbXBhcmUgdGhlIG9ic2VydmVkIEJQIHZhbHVlcyB3aXRoICoqbm9ybWF0aXZlIHZhbHVlcyoqIGZyb20gW1dlaXNzZXIgZXQgYWwgKDIwMDApXSgjcmVmKSwgYmFzZWQgb24gc2VsZi1tZWFzdXJlZCBhbmQgb2ZmaWNlIEJQIGZyb20gKio1MDMgaGVhbHRoeSBTd2lzcyBhZHVsdHMqKi4gUmVkIGxpbmVzIGluZGljYXRlIHRoZSAzNcKwLCA1OMKwIGFuZCA3NsKwIHBlcmNlbnRpbGUgZm9yIG9mZmljZSAoc29saWQpIGFuZCBzZWxmLW1lYXN1cmVkIChkb3R0ZWQpIHN5c3RvbGljIEJQLCBhbmQgdGhlIDUwwrAsIDY3wrAgYW5kIDc4wrAgcGVyY2VudGlsZSBmb3IgZGlhc3RvbGljIEJQLCByZXNwZWN0aXZlbHkuIFdoaXRlIGRvdHRlZCBsaW5lcyBpbmRpY2F0ZSB0aGUgY29ycmVzcG9uZGluZyBwZXJjZW50aWxlcyBpbiB0aGUgY3VycmVudCBzYW1wbGUuIFdlIGNhbiBzZWUgdGhhdCB0aGUgb2JzZXJ2ZWQgdmFsdWVzIGFyZSAqKnF1aXRlIHNpbWlsYXIqKiB0byB0aGUgbm9ybWF0aXZlIG9uZXMsIHdpdGggZ3JlYXRlciBzaW1pbGFyaXRpZXMgd2l0aCBob21lIChcfjMtNSBtbUhnKSBjb21wYXJlZCB0byBvZmZpY2Ugbm9ybWF0aXZlIHZhbHVlcyAoXH45IG1tSGcpLiBJdCBpcyBjb25maXJtZWQgdGhhdCAqKkRCUCBpcyBib3VuZGVkIGF0IDQwIG1tSGcqKiwgd2l0aCBhIHBlYWsgb2YgY2FzZXMgY29ycmVzcG9uZGluZyB0byB0aGUgbG93ZXIgbGltaXQuDQoNCmBgYCB7ciBmaWcud2lkdGg9MTIsZmlnLmhlaWdodD01fQ0KcGFyKG1mcm93PWMoMiwyKSkNCmZvcihCUCBpbiBjKCJTQlAxIiwiREJQMSIsIlNCUDIiLCJEQlAyIikpeyBoaXN0KGRpYXJ5WyxCUF0sbWFpbj1CUCx4bGFiPSJCUCAobW1IZykiLGJyZWFrcz01MCxjb2w9ImJsYWNrIikNCiAgYWJsaW5lKHY9cXVhbnRpbGUoZGlhcnlbLEJQXSxuYS5ybT1UUlVFLHByb2JzPWMoLjM1LC41OCwuNzYpKSxjb2w9ImdyYXkiLGx3ZD0yLGx0eT0yKSAjIG9ic2VydmVkIHF1YW50aWxlcw0KICBpZihzdWJzdHIoQlAsMSwxKT09IlMiKXsgYWJsaW5lKHY9YygxMTQuMywxMjQuMSwxMzIuNiksY29sPSJyZWQiLGx3ZD0yLGx0eT0yKSAjIG5vcm1hdGl2ZSBxdWFudGlsZXMgKHN5c3RvbGljLCBob21lKQ0KICAgIGFibGluZSh2PWMoMTIwLDEzMCwxNDApLGNvbD0icmVkIixsd2Q9MykgIyBub3JtYXRpdmUgcXVhbnRpbGVzIChzeXN0b2xpYywgb2ZmaWNlKQ0KICB9IGVsc2UgeyAgYWJsaW5lKHY9Yyg3NS4xLDc5LjksODUuOCksY29sPSJyZWQiLGx3ZD0yLGx0eT0yKSAjIG5vcm1hdGl2ZSBxdWFudGlsZXMgKGRpYXN0b2xpYywgaG9tZSkNCiAgICBhYmxpbmUodj1jKDgwLDg1LDkwKSxjb2w9InJlZCIsbHdkPTMpIH19ICMgbm9ybWF0aXZlIHF1YW50aWxlcyAoZGlhc3RvbGljLCBvZmZpY2Upw6wNCmBgYA0KDQojIyMjIHZzLiBBc2F5YW1hIGV0IGFsICgyMDE5KQ0KDQpUaGVuLCB3ZSBjb21wYXJlIEJQIHZhbHVlcyBvYnRhaW5lZCBmcm9tIE1vcm5pbmcgYW5kIEV2ZW5pbmcgbWVhc3VyZXMgd2l0aCB0aG9zZSByZXBvcnRlZCBieSBbQXNheWFtYSBldCBhbCAoMjAxOSldKCNyZWYpIGZvciBtb3JuaW5nIGFuZA0KZXZlbmluZyBCUCBzZWxmLW1lYXN1cmVkIGJ5IDMwOCAqKmh5cGVydGVuc2l2ZSBwYXRpZW50cyoqLiBSZWQgbGluZXMgaW5kaWNhdGUgbm9ybWF0aXZlIG1lYW4gwrEgMiBTRCwgd2hlcmVhcyBncmF5IGRvdHRlZCBsaW5lcyBpbmRpY2F0ZSB0aGUNCm9ic2VydmVkIG1lYW4gKy8tIDIgU0QgZnJvbSB0aGUgY3VycmVudCBzYW1wbGUuIEFnYWluLCBkYXRhIGxvb2sgJ3JlYWxpc3RpYycuDQoNCmBgYCB7ciBmaWcud2lkdGg9MTIsZmlnLmhlaWdodD01fQ0KcGFyKG1mcm93PWMoMiwyKSkNCmZvcihCUCBpbiBjKCJTQlAxIiwiU0JQMiIsIkRCUDEiLCJEQlAyIikpeyBoaXN0KGRpYXJ5WyxCUF0sbWFpbj1CUCx4bGFiPSJCUCAobW1IZykiLGJyZWFrcz01MCxjb2w9ImJsYWNrIikNCiAgYWJsaW5lKHY9YyhtZWFuKGRpYXJ5WyxCUF0sbmEucm09VFJVRSksbWVhbihkaWFyeVssQlBdLG5hLnJtPVRSVUUpLTIqc2QoZGlhcnlbLEJQXSxuYS5ybT1UUlVFKSwNCiAgICAgICAgICAgICBtZWFuKGRpYXJ5WyxCUF0sbmEucm09VFJVRSkrMipzZChkaWFyeVssQlBdLG5hLnJtPVRSVUUpKSxjb2w9ImdyYXkiLGx3ZD0yLGx0eT0yKQ0KICBpZihzdWJzdHIoQlAsMSwxKT09IlMiKXsgYWJsaW5lKHY9YygxMjguMCwxMjguMCs5LjQqMiwxMjguMC05LjQqMiksY29sPSJyZWQiLGx3ZD0yKSANCiAgfSBlbHNlIHsgIGFibGluZSh2PWMoNzAuNSw3MC41KzkuNyoyLDcwLjUtOS43KjIpLGNvbD0icmVkIixsd2Q9MikgfX0gIyBub3JtYXRpdmUgbWVhbiArLy0gc2QgKGRpYXN0b2xpYykNCmBgYA0KDQo8YnI+DQoNCiMjIyAzLjIuMi4gQlAgYnkgZGF5IHRpbWUNCg0KSGVyZSwgd2UgdmlzdWFsaXplIHRoZSBkaXN0cmlidXRpb24gb2YgKipTeXN0b2xpYyBCUCB2YWx1ZXMqKiBpbiBNb3JuaW5nIChNKSwgQWZ0ZXJub29uIChBKSBhbmQgRXZlbmluZyAoRSkgcmVjb3JkaW5ncywgd2hpbGUgYWxzbyBzaG93aW5nIGluZGl2aWR1YWwgcGF0dGVybnMgb2YgY2hhbmdlLiBJdCBpcyBoYXJkIHRvIGRldGVybWluYXRlIHRoZSBwcmV2YWxlbmNlIG9mIGFuIGluY3JlYXNpbmcgb3IgZGVjcmVhc2luZyBwYXR0ZXJuIGZvciBib3RoIHZhcmlhYmxlcywgYWx0aG91Z2ggbW9zdCBjYXNlcyBzZWVtIHRvIGluY3JlYXNlIGZyb20gTW9ybmluZyB0byBBZnRlcm5vb24gYW5kIGRlY3JlYXNlIGZyb20gQWZ0ZXJub29uIHRvIEV2ZW5pbmcuDQoNCmBgYCB7ciBmaWcud2lkdGg9MTIsZmlnLmhlaWdodD00LHdhcm5pbmc9RkFMU0V9DQojIHBsb3R0aW5nIFNCUA0KZGlhcnkkSURkYXkgPC0gYXMuZmFjdG9yKHBhc3RlKGRpYXJ5JElELGRpYXJ5JGRheSxzZXA9Il8iKSkgIyBhZGRpbmcgSUQgeCBkYXkgZmFjdG9yDQpncmlkLmFycmFuZ2UoZ2dwbG90KGRhdGE9ZGlhcnksYWVzKHg9ZGlhcnlUeXBlLHk9U0JQMSkpICsgZ2VvbV9saW5lKGFlcyhncm91cD1JRGRheSxjb2w9SURkYXkpKSArIGdlb21fdmlvbGluKGFscGhhPS40KSArDQogICAgICAgICAgICAgICBnZW9tX2JveHBsb3QoYWxwaGE9MC41LHdpZHRoPTAuMyxvdXRsaWVyLmFscGhhPTApICsgdGhlbWUobGVnZW5kLnBvc2l0aW9uPSJub25lIiksDQogICAgICAgICAgICAgZ2dwbG90KGRhdGE9ZGlhcnksYWVzKHg9ZGlhcnlUeXBlLHk9U0JQMikpICsgZ2VvbV9saW5lKGFlcyhncm91cD1JRGRheSxjb2w9SURkYXkpKSArIGdlb21fdmlvbGluKGFscGhhPS40KSArDQogICAgICAgICAgICAgICBnZW9tX2JveHBsb3QoZmlsbD1yZ2IoMSwxLDEsYWxwaGE9LjQpLHdpZHRoPTAuMyxvdXRsaWVyLmFscGhhPTApICsgdGhlbWUobGVnZW5kLnBvc2l0aW9uPSJub25lIiksbnJvdz0xKQ0KDQojIHBsb3R0aW5nIERCUA0KZ3JpZC5hcnJhbmdlKGdncGxvdChkYXRhPWRpYXJ5LGFlcyh4PWRpYXJ5VHlwZSx5PURCUDEpKSArIGdlb21fbGluZShhZXMoZ3JvdXA9SURkYXksY29sPUlEZGF5KSkgKyBnZW9tX3Zpb2xpbihhbHBoYT0uNCkgKw0KICAgICAgICAgICAgICAgZ2VvbV9ib3hwbG90KGZpbGw9cmdiKDEsMSwxLGFscGhhPS40KSx3aWR0aD0wLjMpICsgZ2d0aXRsZSgiRGlhc3RvbGljIEJQIDEiKSArIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbj0ibm9uZSIpLA0KICAgICAgICAgICAgIGdncGxvdChkYXRhPWRpYXJ5LGFlcyh4PWRpYXJ5VHlwZSx5PURCUDIpKSArIGdlb21fbGluZShhZXMoZ3JvdXA9SURkYXksY29sPUlEZGF5KSkgKyBnZW9tX3Zpb2xpbihhbHBoYT0uNCkgKw0KICAgICAgICAgICAgICAgZ2VvbV9ib3hwbG90KGZpbGw9cmdiKDEsMSwxLGFscGhhPS40KSx3aWR0aD0wLjMpICsgZ2d0aXRsZSgiRGlhc3RvbGljIEJQIDIiKSArIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbj0ibm9uZSIpLG5yb3c9MSkNCmBgYA0KDQo8YnI+DQoNCiMjIyAzLjIuMy4gQlAgdHJhamVjdG9yaWVzIHsjYnAtdHJhamVjdG9yaWVzIC50YWJzZXQgLnRhYnNldC1mYWRlIC50YWJzZXQtcGlsbHN9DQoNClRoZW4sIHdlIHVzZSB0aGUgYHBsb3RCUGAgZnVuY3Rpb24gdG8gdmlzdWFsaXplIGRhaWx5IGZsdWN0dWF0aW9ucyBpbiBCUCB2YWx1ZXMuIEZvciBlYWNoIHJlY29yZGluZywgdGhlIGZpcnN0IGFuZCBzZWNvbmQgZW50ZXJlZCB2YWx1ZSBhcmUNCnNob3dlZCBpbiBsaWdodCBhbmQgZGFyayBibHVlLCByZXNwZWN0aXZlbHkuIFRoZSByZWQgdHJpYW5nbGVzIHNob3cgY2FzZXMgaW4gd2hpY2ggdGhlIHNlY29uZCBtZWFzdXJlbWVudCB3YXMgMTAgbW1IZyBoaWdoZXIgb3IgbG93ZXIgdGhhbg0KdGhlIHNlY29uZCBvbmUsIHdoZXJlYXMgdGhlIGJsdWUgZG90dGVkIGxpbmUgaW5kaWNhdGVzIHRoZSBbRVNIL0VTQyBHdWlkZWxpbmVzICgyMDE4KV0oI3JlZikgY3V0LW9mZiBmb3IgaHlwZXJ0ZW5zaW9uLiBGb3IgYm90aCBzeXN0b2xpYyBhbmQNCmRpYXN0b2xpYyBCUCB0aW1lIHNlcmllcywgd2UgKipmbGFnIHByb2JsZW1hdGljIGNhc2VzKiogYmFzZWQgb24gdGhlIHZpc3VhbCBpbnNwZWN0aW9uIG9mIHN0ZWVwIEJQIGluY3JlYXNlcy9kZWNyZWFzZXMgY29tcGFyZWQgdG8gdGhlIG90aGVycyB2YWx1ZXMgZnJvbSB0aGF0IHBhcnRpY2lwYW50Lg0KDQo8ZGV0YWlscz48c3VtbWFyeT5gcGxvdEJQKClgPC9zdW1tYXJ5Pg0KPHA+DQpgYGAge3J9DQpwbG90QlAgPC0gZnVuY3Rpb24oZGF0YT1OVUxMLEJQPSJTIixuY29sPTMsZmxhZ2dlZD1OQSx3aGF0PU5BLG1lYW5WYWw9TkEpeyByZXF1aXJlKGdncGxvdDIpDQogIA0KICAjIGNyZWF0aW5nIFRJTUUgYnkgam9pbmluZyBkYXkgYW5kIGRpYXJ5VHlwZQ0KICBkYXRhJFRJTUVsYWIgPC0gcGFzdGUoZGF0YSRkYXksZGF0YSRkaWFyeVR5cGUsc2VwPSIiKQ0KICBkYXRhJFRJTUUgPC0gYXMubnVtZXJpYyhnc3ViKCJNIiwiLjAiLGdzdWIoIkEiLCIuMzMiLGdzdWIoIkUiLCIuNjYiLGRhdGEkVElNRWxhYikpKSkNCiAgDQogICMgc2V0dGluZyBncmFwaGljIHBhcmFtZXRlcnMNCiAgY29scyA8LSBjb2xuYW1lcyhkYXRhKVtzdWJzdHIoY29sbmFtZXMoZGF0YSksMSwzKT09cGFzdGUoQlAsIkJQIixzZXA9IiIpXSAjIGNvbHVtbnMgdG8gYmUgcGxvdHRlZA0KICBtYXhTY29yZSA8LSBtYXgoZGF0YVssY29sc10sbmEucm09VFJVRSkNCiAgZGF0YSRkaXNjIDwtIGFicyhkYXRhWyxjb2xzWzFdXS1kYXRhWyxjb2xzWzJdXSkNCiAgZGF0YSRkaXNjMTAgPC0gRkFMU0UNCiAgZGF0YVshaXMubmEoZGF0YSRkaXNjKSAmIGRhdGEkZGlzYz49MTAsImRpc2MxMCJdIDwtIFRSVUUNCiAgDQogICMgcGxvdHRpbmcgDQogIHAgPC0gZ2dwbG90KGRhdGEsYWVzX3N0cmluZyh4PSJUSU1FIix5PWNvbHNbMV0pKSArIA0KICAgIGdlb21fbGluZShjb2xvdXI9ImxpZ2h0Ymx1ZSIpICsgZ2VvbV9wb2ludChjb2xvdXI9ImxpZ2h0Ymx1ZSIpICsgDQogICAgc2NhbGVfeF9jb250aW51b3VzKGJyZWFrcz1zZXEoMS4zMywxMi42NixsZW5ndGgub3V0PTExKSxsYWJlbHM9cGFzdGUoMToxMSwiQSIsc2VwPSIiKSxwb3NpdGlvbj0idG9wIikgKw0KICAgIGdlb21fbGluZShhZXNfc3RyaW5nKHk9Y29sc1syXSksY29sb3VyPSJibHVlIikgKyANCiAgICBnZW9tX3BvaW50KGFlc19zdHJpbmcoeT1jb2xzWzJdLHNoYXBlPSJkaXNjMTAiKSxzaXplPTIsY29sb3I9ImJsdWUiKSArDQogICAgZ2VvbV9wb2ludChkYXRhPWRhdGFbIWlzLm5hKGRhdGEkZGlzYykgJiBkYXRhJGRpc2M+PTEwLF0sYWVzX3N0cmluZyh5PWNvbHNbMl0sc2hhcGU9ImRpc2MxMCIpLHNpemU9Mixjb2xvcj0icmVkIikgKw0KICAgIGZhY2V0X3dyYXAoIklEIixzdHJpcC5wb3NpdGlvbiA9ICJyaWdodCIsbmNvbD1uY29sKSArDQogICAgZ2d0aXRsZShwYXN0ZSgiRGFpbHkgZmx1Y3R1YXRpb25zIGluIixpZmVsc2UoQlA9PSJTIiwiU3lzdG9saWMiLCJEaWFzdG9saWMiKSwNCiAgICAgICAgICAgICAgICAgICJibG9vZCBwcmVzc3VyZSAobGlnaHQgYmx1ZSA9IDFzdCByZWNvcmRpbmcsIGRhcmsgYmx1ZSA9IDJuZCByZWNvcmRpbmcsIHJlZCB0cmlhbmdsZXMgPSBkaXNjcmVwLiA+IDEwIG1tSGcpIikpICsgDQogICAgeGxhYigiRGF5IG9mIHdlZWsiKSArIHlsYWIocGFzdGUoQlAsIkJQIChtbUhnKSIsc2VwPSIiKSkrDQogICAgZ2VvbV9obGluZSh5aW50ZXJjZXB0PWlmZWxzZShCUD09IlMiLDEzMCw4NSksY29sb3I9ImJsdWUiLGx0eT0yKSsNCiAgICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChzaXplPTksYW5nbGUgPSA0NSksbGVnZW5kLnBvc2l0aW9uPSJub25lIikNCiAgDQogICMgbWFya2luZyBmbGFnZ2VkIGNhc2VzDQogIGlmKCFpcy5uYShmbGFnZ2VkKSl7IGRhdGEkZmxhZyA8LSBkYXRhWyxmbGFnZ2VkXQ0KICAgIHAgPC0gcCArIGdlb21fcG9pbnQoZGF0YT1kYXRhWyFpcy5uYShkYXRhJGZsYWcpICYgZGF0YSRmbGFnPT1UUlVFLF0sYWVzX3N0cmluZyh5PWNvbHNbMl0pLHNpemU9NCxzaGFwZT0xKSArDQogICAgICBnZW9tX3RleHQoZGF0YT1kYXRhWyFpcy5uYShkYXRhJGZsYWcpICYgZGF0YSRmbGFnPT1UUlVFLF0sYWVzX3N0cmluZyh5PXBhc3RlKGNvbHNbMl0sIisxMCIpLGxhYmVsPXdoYXQpKSB9DQogIA0KICAjIHNob3dpbmcgYXZlcmFnZSB2YWx1ZQ0KICBpZighaXMubmEobWVhblZhbCkpeyBkYXRhJG1lYW5WYWwgPC0gZGF0YVssbWVhblZhbF0NCiAgICBwIDwtIHAgKyBnZW9tX2xpbmUoZGF0YT1kYXRhWyFpcy5uYShkYXRhJG1lYW5WYWwpLF0sYWVzKHk9bWVhblZhbCksbHdkPTEuMSxjb2xvcj0iZ3JlZW4iKSArDQogICAgICBnZW9tX3BvaW50KGRhdGE9ZGF0YVshaXMubmEoZGF0YSRtZWFuVmFsKSxdLGFlcyh5PW1lYW5WYWwpLGNvbG9yPSJncmVlbiIpIH0NCiAgcH0NCmBgYA0KPC9wPg0KPC9kZXRhaWxzPg0KDQo8YnI+DQoNCiMjIyMgU0JQDQoNCmBgYCB7ciBmaWcud2lkdGg9MTIsZmlnLmhlaWdodD04MCx3YXJuaW5nPUZBTFNFfQ0KcGxvdEJQKGRpYXJ5LEJQPSJTIixuY29sPTQpDQpgYGANCg0KPGJyPg0KDQojIyMjIERCUA0KDQpgYGAge3IgZmlnLndpZHRoPTEyLGZpZy5oZWlnaHQ9NCx3YXJuaW5nPUZBTFNFfQ0KcGxvdEJQKGRpYXJ5LEJQPSJEIixuY29sPTQpDQpgYGANCg0KPGJyPg0KDQojIyMjIFNCUCAoZmxhZ2dlZCkNCg0KSGVyZSwgd2UgbWFudWFsbHkgZmxhZyB0aGUgY2FzZXMgc2hvd2luZyBleHRyZW1lIHZhbHVlcyBpbiB0aGUgKipzZWNvbmQgbWVhc3VyZW1lbnQgb3IgYm90aCoqLCBzaW5jZSB3ZSB3aWxsIHJlbW92ZSB0aGUgZmlyc3QgbWVhc3VyZW1lbnQgd2hlbiBpdCBpcyBtb3JlIHRoYW4gMTAgbW1IZyBsb3dlciBvciBoaWdoZXIgdGhhbiB0aGUgZmlyc3Qgb25lIChzZWUgYmVsb3cpLiBPbmx5IHRoZXNlIGNhc2VzIGFyZSBwbG90dGVkIGJlbG93Lg0KDQpgYGAge3IgZmlnLndpZHRoPTEyLGZpZy5oZWlnaHQ9OCx3YXJuaW5nPUZBTFNFfQ0KIyBmbGFnZ2VkIGNhc2VzIChvbmx5IHNlY29uZCA9ICIyIiBvciAiYm90aCIgbWVhc3VyZW1lbnQpDQpmbGFnUyA8LSBkYXRhLmZyYW1lKElEICAgPSBjKCJTMDA2IiwiUzAwNyIsIlMwMTEiLCJTMDExIiwiUzAzMCIsIlMwMzAiLCJTMDMzIiwiUzA1OCIsIlMwNjEiLCJTMDY1IiwiUzA3NyIsIlMwNzciKSwNCiAgICAgICAgICAgICAgICAgICBkYXkgICA9ICAgICBjKDMsICAgICAyLCAgICAgMSwgICAgIDgsICAgIDEsICAgICAyLCAgICA2LCAgICAgIDgsICAgICA5LCAgICAgMTAsICAgMSwgICAgMSksDQogICAgICAgICAgICAgICAgICAgZGlhcnlUeXBlPSBjKCJBIiwgICAiRSIsICAgIkEiLCAgICJBIiwgICJBIiwgICAiQSIsICAiTSIsICAgICJBIiwgICAiRSIsICAgIk0iLCAgICJBIiwgICJFIiksDQogICAgICAgICAgICAgICAgICAgd2hhdFMgPSAgICAgYygiYm90aCIsImJvdGgiLCJib3RoIiwiMiIsICAiMiIsICAgIjIiLCAgIjIiLCAgICAiMiIsICAgIjIiLCAgICIyIiwgICAiMiIsICAiMiIpKQ0KIyBmdXJ0aGVyIGZsYWdnZWQgY2FzZXMNCmZsYWdTIDwtIHJiaW5kKGZsYWdTLA0KICAgICAgICAgICAgICAgZGF0YS5mcmFtZShJRCAgID0gYygiczA4MCIsInMwODAiLCJzMDgwIiwiUzA4MiIsIlMxMDAiLCJTMTEwIiwiUzExMCIsIlMxNDQiKSwNCiAgICAgICAgICAgICAgICAgICBkYXkgICA9ICAgICBjKCAgICAgMSwgICAgMSwgICAgIDIsICAgICAxLCAgICAgMSwgICAgIDIsICAgICAzLCAgICAgIDgpLA0KICAgICAgICAgICAgICAgICAgIGRpYXJ5VHlwZT0gYyggICAgICJFIiwgICJNIiwgICAgIkUiLCAgIkEiLCAgICJBIiwgICAiTSIsICAgIk0iLCAgICJBIiksDQogICAgICAgICAgICAgICAgICAgd2hhdFMgPSAgICAgYyggICAiYm90aCIsImJvdGgiLCJib3RoIiwiYm90aCIsImJvdGgiLCAiMiIsICAgIjIiLCAgICJib3RoIikpKQ0KDQojIGFkZGluZyBpbmZvcm1hdGlvbiBvbiBmbGFnZ2VkIGNhc2VzDQpmbGFnUyRTQlBmbGFnIDwtIFRSVUUNCmRpYXJ5IDwtIHBseXI6OmpvaW4oZGlhcnksZmxhZ1MsYnk9YygiSUQiLCJkYXkiLCJkaWFyeVR5cGUiKSx0eXBlPSJsZWZ0IikNCmRpYXJ5W2lzLm5hKGRpYXJ5JFNCUGZsYWcpICYgIWlzLm5hKGRpYXJ5JFNCUDEpLCJTQlBmbGFnIl0gPC0gRkFMU0UNCg0KIyBwbG90dGluZw0KcGxvdEJQKGRpYXJ5W2RpYXJ5JElEJWluJWxldmVscyhhcy5mYWN0b3IoYXMuY2hhcmFjdGVyKGZsYWdTJElEKSkpLF0sQlA9IlMiLG5jb2w9NCxmbGFnZ2VkPSJTQlBmbGFnIix3aGF0PSJ3aGF0UyIpDQpgYGANCg0KPGJyPg0KDQojIyMjIERCUCAoZmxhZ2dlZCkNCg0KSGVyZSwgd2UgbWFudWFsbHkgZmxhZyB0aGUgY2FzZXMgc2hvd2luZyBleHRyZW1lIHZhbHVlcyBpbiB0aGUgKipzZWNvbmQgbWVhc3VyZW1lbnQgb3IgYm90aCoqLCBzaW5jZSB3ZSB3aWxsIHJlbW92ZSB0aGUgZmlyc3QgbWVhc3VyZW1lbnQgd2hlbiBpdCBpcyBtb3JlIHRoYW4gMTAgbW1IZyBsb3dlciBvciBoaWdoZXIgdGhhbiB0aGUgZmlyc3Qgb25lIChzZWUgYmVsb3cpLiBPbmx5IHRoZXNlIGNhc2VzIGFyZSBwbG90dGVkIGJlbG93Lg0KDQpgYGAge3IgZmlnLndpZHRoPTEyLGZpZy5oZWlnaHQ9OCx3YXJuaW5nPUZBTFNFfQ0KIyBmbGFnZ2VkIGNhc2VzIChvbmx5IHN5c3RvbGljID0gIlMiIG9yICJib3RoIiwgYnV0IG5vdCBkaWFzdG9saWMgLSBzZWUgYmVsb3cpDQpmbGFnRCA8LSBkYXRhLmZyYW1lKElEICA9IGMocmVwKCJTMDA2Iiw0KSwgICAgICAgICAgICJTMDA3IiwiUzAzNCIsIlMwNTciLCJTMDU4IiwiUzA1OCIsIlMwNzAiLCJTMDcwIixyZXAoIlMwODAiLDMpLCJTMDgyIiksDQogICAgICAgICAgICAgICAgICAgZGF5ICA9IGMoICAgICAxLCAgMiwgICAgMiwgIDMsICAgICAgICAgNSwgICAgIDIsICAgICA5LCAgICA4LCAgICAgOCwgICAgICAgNiwgICAgOCwgICAgICAgMSwyLDIsICAgICAxKSwNCiAgICAgICAgICAgICAgICAgICBkaWFyeVR5cGU9YyggIkEiLCJNIiwgICJFIiwiTSIsICAgICAgICJFIiwgICAiTSIsICAgIkUiLCAgIkEiLCAgICJFIiwgICAgICJNIiwgICJNIiwgICAgIkUiLCJNIiwiRSIsIkEiKSwNCiAgICAgICAgICAgICAgICAgICB3aGF0RCA9ICAgIGMoIjIiLCJpbnYiLCIyIiwiMiIsICAgICAgImJvdGgiLCAiMiIsICAiMiIsICAgIjIiLCAgICIyIiwgICAgICIyIiwgICIyIiwgIHJlcCgiYm90aCIsMyksImJvdGgiKSkNCg0KIyBmdXJ0aGVyIGZsYWdnZWQgY2FzZXMNCmZsYWdEIDwtIHJiaW5kKGZsYWdELA0KICAgICAgICAgICAgICAgZGF0YS5mcmFtZShJRD1jKCJTMDkyIiwiUzA5MyIsIlMwOTMiLCJTMDkzIiwiUzExNyIsIlMxMTciLCJTMTMwIiwiUzE0NCIsIlMxNDQiLCJTMTQ1IiksDQogICAgICAgICAgICAgICAgICAgZGF5ICA9ICAgICBjKCAgOSwgICAgMiwgICAgICAzLCAgICAgNywgICAgNiwgICAgICA5LCAgICAgMiwgICAgIDgsICAgICAxMSwgICAgIDEpLA0KICAgICAgICAgICAgICAgICAgIGRpYXJ5VHlwZSA9IGMoIkUiLCAgIkEiLCAgICAiQSIsICAgIkUiLCAgIk0iLCAgICAiQSIsICAgIkUiLCAgICJBIiwgICAgIkUiLCAgICJBIiksDQogICAgICAgICAgICAgICAgICAgd2hhdEQgPSAgICBjKCAgIjIiLCAiaW52IiwgICJpbnYiLCAiaW52IiwgIjIiLCAgICAiMiIsICAgIjIiLCAgImJvdGgiLCJib3RoIiwgIjIiKSkpDQoNCiMgYWRkaW5nIGluZm9ybWF0aW9uIG9uIGZsYWdnZWQgY2FzZXMNCmZsYWdEJERCUGZsYWcgPC0gVFJVRQ0KZGlhcnkgPC0gcGx5cjo6am9pbihkaWFyeSxmbGFnRCxieT1jKCJJRCIsImRheSIsImRpYXJ5VHlwZSIpLHR5cGU9ImxlZnQiKQ0KZGlhcnlbaXMubmEoZGlhcnkkREJQZmxhZykgJiAhaXMubmEoZGlhcnkkU0JQMSksIkRCUGZsYWciXSA8LSBGQUxTRQ0KDQojIHBsb3R0aW5nDQpwbG90QlAoZGlhcnlbZGlhcnkkSUQlaW4lbGV2ZWxzKGFzLmZhY3Rvcihhcy5jaGFyYWN0ZXIoZmxhZ0QkSUQpKSksXSxCUD0iRCIsbmNvbD00LGZsYWdnZWQ9IkRCUGZsYWciLHdoYXQ9IndoYXREIikNCmBgYA0KDQo8YnI+DQoNCiMjIyAzLjIuNC4gQlAgQWdncmVnYXRlZCB2YWx1ZXMNCg0KSGVyZSwgd2UgYWdncmVnYXRlIHRoZSBmaXJzdCBhbmQgc2Vjb25kIG1lYXN1cmVtZW50IG9mIHN5c3RvbGljIGFuZCBkaWFzdG9saWMgYEJQLmAgQXMgW3ByZS1yZWdpc3RlcmVkIGhlcmVdKGh0dHBzOi8vb3NmLmlvL2g5enZxKSwgU0JQIGFuZCBEQlAgYWdncmVnYXRlZCB2YWx1ZXMgYXJlIGNvbXB1dGVkIGFzIHRoZSAqKmF2ZXJhZ2UgYmV0d2VlbiB0aGUgZmlyc3QgYW5kIHRoZSBzZWNvbmQqKiAoaW1tZWRpYXRlbHkgY29uc2VjdXRpdmUpIGBCUGAgcmVjb3JkaW5nLiBJbiBhbGwgY2FzZXMgc2hvd2luZyAqKmRpc2NyZXBhbmNpZXMqKiAoaS5lLiwgYWJzb2x1dGUgZGlmZmVyZW5jZXMpIGJldHdlZW4gdGhlIGZpcnN0IGFuZCB0aGUgc2Vjb25kIHJlY29yZGluZyAqKmVxdWFsIHRvIG9yIGhpZ2hlciB0aGFuIDEwIG1tSGcsIG9ubHkgdGhlIHNlY29uZCByZWNvcmRlZCB2YWx1ZSoqIGlzIGNvbnNpZGVyZWQgKGkuZS4sIHRoZSBmaXJzdCByZWNvcmRpbmcgaXMgZXhjbHVkZWQpLg0KDQpIb3dldmVyLCB3ZSBhbHNvIGFjY291bnQgZm9yIHRoZSAqKmZsYWdnZWQgY2FzZXMqKiBtYXJrZWQgYXMgIjIiICh3aGVuIHRoZSBzZWNvbmQgbWVhc3VyZW1lbnQgc2hvdWxkIGJlIHJlbW92ZWQpLCAiYm90aCIgKHdoZW4gYm90aCBtZWFzdXJlbWVudHMgaGF2ZSBleHRyZW1lIHZhbHVlcyBpbiB0aGUgc2FtZSBkaXJlY3Rpb24pLCBhbmQgImludiIgKHdoZW4gdGhlIGJvdGggaGF2ZSBleHRyZW1lIHZhbHVlcyBpbiBvcHBvc2l0ZSBkaXJlY3Rpb25zKToNCg0KLSBpbiBjYXNlcyBmbGFnZ2VkIGFzIGAiMiJgLCB3ZSBvbmx5IGtlZXAgdGhlIGZpcnN0IG1lYXN1cmVtZW50DQoNCi0gaW4gY2FzZXMgZmxhZ2dlZCBhcyBgImludiJgLCB3ZSBjb21wdXRlIHRoZSBhdmVyYWdlIChhcyBpbiBhbnkgbm9uLWZsYWdnZWQgY2FzZSkNCg0KLSBpbiBjYXNlcyBmbGFnZ2VkIGFzIGAiYm90aCJgLCB3ZSBpbnRlcnBvbGF0ZSB0aGUgbWVhc3VyZW1lbnQgYXMgdGhlIG1heGltdW0gdmFsdWUgKG9yIHRoZSBtaW5pbXVtLCBiYXNlZCBvbiB0aGUgZGlyZWN0aW9uIG9mIGV4dHJlbWUgdmFsdWVzKSByZWNvcmRlZCBmb3IgdGhhdCBwYXJ0aWNpcGFudC4NCg0KVGhpcyBpcyBkb25lIGluZGVwZW5kZW50bHkgZm9yIHN5c3RvbGljIGFuZCBkaWFzdG9saWMgYEJQYA0KDQo8YnI+DQoNCiMjIyMgMy4yLjQuMS4gQWdncmVnYXRpbmcgdmFsdWVzDQoNCkZpcnN0LCB3ZSBhZ2dyZWdhdGUgYFNCUGAgdmFsdWVzLg0KYGBgIHtyfQ0KIyBTQlAgLSBwcmludGluZyBpbmZvDQpjYXQoIi0gQXZlcmFnaW5nIixucm93KGRpYXJ5WyFpcy5uYShkaWFyeSRTQlBmbGFnKSAmIChkaWFyeSRTQlBmbGFnPT1GQUxTRSB8IGRpYXJ5JFNCUGZsYWc9PSJpbnYiKSAmIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFicyhkaWFyeSRTQlAxLWRpYXJ5JFNCUDIpPDEwLF0pLCJjYXNlc1xuLSBFeGNsdWRpbmciLA0KICAgIG5yb3coZGlhcnlbIWlzLm5hKGRpYXJ5JFNCUGZsYWcpICYgYWJzKGRpYXJ5JFNCUDEtZGlhcnkkU0JQMik+PTEwICYgZGlhcnkkU0JQZmxhZz09RkFMU0UsXSksDQogICAgImZpcnN0IG1lYXN1cm1lbnRzXG4tIEV4Y2x1ZGluZyIsbnJvdyhkaWFyeVshaXMubmEoZGlhcnkkd2hhdFMpICYgZGlhcnkkd2hhdFM9PSIyIixdKSwNCiAgICAic2Vjb25kIG1lc3VyZW1lbnRzXG4tIEludGVycG9sYXRpbmciLG5yb3coZGlhcnlbIWlzLm5hKGRpYXJ5JHdoYXRTKSAmIGRpYXJ5JHdoYXRTPT0iYm90aCIsXSksIm1lYXN1cmVtZW50cyIpDQoNCg0KIyAoMSkgYXZlcmFnZWQgY2FzZXMgKG5vIGZsYWdnZWQsIG9yIGZsYWdnZWQgPSAiaW52IiwgYW5kIGRpc2NyZXBhbmNpZXMgPCAxMG1tSGcpDQpkaWFyeVsoIWlzLm5hKGRpYXJ5JFNCUGZsYWcpICYgZGlhcnkkU0JQZmxhZz09RkFMU0UgJiBhYnMoZGlhcnkkU0JQMS1kaWFyeSRTQlAyKSA8IDEwKSB8DQogICAgICAgICghaXMubmEoZGlhcnkkd2hhdFMpICYgZGlhcnkkd2hhdFM9PSJpbnYiKSwiU0JQIl0gPC0gDQogIGFwcGx5KGRpYXJ5WyghaXMubmEoZGlhcnkkU0JQZmxhZykgJiBkaWFyeSRTQlBmbGFnPT1GQUxTRSAmIGFicyhkaWFyeSRTQlAxLWRpYXJ5JFNCUDIpIDwgMTApIHwNCiAgICAgICAgKCFpcy5uYShkaWFyeSR3aGF0UykgJiBkaWFyeSR3aGF0Uz09ImludiIpLGMoIlNCUDEiLCJTQlAyIildLDEsbWVhbikNCiMgKDIpIGNhc2VzIG9ubHkgYmFzZWQgb24gdGhlIHNlY29uZCBtZWFzdXJlbW50IChkaXNjcmVwYW5jaWVzID49IDEwbW1IZyBBTkQgbm8gZmxhZ3MpDQpkaWFyeVshaXMubmEoZGlhcnkkU0JQZmxhZykgJiBkaWFyeSRTQlBmbGFnPT1GQUxTRSAmIGFicyhkaWFyeSRTQlAxLWRpYXJ5JFNCUDIpID49IDEwLCJTQlAiXSA8LSANCiAgZGlhcnlbIWlzLm5hKGRpYXJ5JFNCUGZsYWcpICYgZGlhcnkkU0JQZmxhZz09RkFMU0UgJiBhYnMoZGlhcnkkU0JQMS1kaWFyeSRTQlAyKSA+PSAxMCwiU0JQMiJdDQojICgzKSBjYXNlcyBvbmx5IGJhc2VkIG9uIHRoZSBmaXJzdCBtZWFzdXJlbW50IChmbGFnZ2VkPVRSVUUgYW5kIHdoYXQgPSAiMiIpDQpkaWFyeVshaXMubmEoZGlhcnkkU0JQZmxhZykgJiBkaWFyeSRTQlBmbGFnPT1UUlVFICYgZGlhcnkkd2hhdFM9PSIyIiwNCiAgICAgICJTQlAiXSA8LSBkaWFyeVshaXMubmEoZGlhcnkkU0JQZmxhZykgJiBkaWFyeSRTQlBmbGFnPT1UUlVFICYgZGlhcnkkd2hhdFM9PSIyIiwiU0JQMSJdDQojICg0KSBjYXNlcyBpbnRlcnBvbGF0ZWQgYXMgdGhlIG1heGltdW0gdmFsdWUNCmZvcihpIGluIHdoaWNoKCFpcy5uYShkaWFyeSR3aGF0UykgJiBkaWFyeSR3aGF0Uz09ImJvdGgiKSl7IA0KICBpZihkaWFyeVtpLCJTQlAyIl0+bWVhbihkaWFyeVtkaWFyeSRJRD09ZGlhcnlbaSwiSUQiXSwiU0JQIl0sbmEucm09VFJVRSkpew0KICAgIGRpYXJ5W2ksIlNCUCJdIDwtIG1heChkaWFyeVtkaWFyeSRJRD09ZGlhcnlbaSwiSUQiXSwiU0JQIl0sbmEucm09VFJVRSkNCiAgfSBlbHNlIHsgZGlhcnlbaSwiU0JQIl0gPC0gbWluKGRpYXJ5W2RpYXJ5JElEPT1kaWFyeVtpLCJJRCJdLCJTQlAiXSxuYS5ybT1UUlVFKSB9fQ0KDQojIHNhbml0eSBjaGVjaw0KbnJvdyhkaWFyeVsoIWlzLm5hKGRpYXJ5JFNCUGZsYWcpICYgaXMubmEoZGlhcnkkU0JQKSl8KGlzLm5hKGRpYXJ5JFNCUGZsYWcpICYgIWlzLm5hKGRpYXJ5JFNCUCkpLF0pID09IDAgDQpgYGANCg0KPGJyPg0KDQpUaGVuLCB3ZSBhZ2dyZWdhdGUgREJQIHZhbHVlcy4NCg0KYGBgIHtyfQ0KIyBEQlAgLSBwcmludGluZyBpbmZvDQpjYXQoIi0gQXZlcmFnaW5nIixucm93KGRpYXJ5WygoIWlzLm5hKGRpYXJ5JERCUGZsYWcpICYgZGlhcnkkREJQZmxhZz09RkFMU0UpIHwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKCFpcy5uYShkaWFyeSR3aGF0RCkgJiBkaWFyeSR3aGF0RD09ImludiIpKSAmIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFicyhkaWFyeSREQlAxLWRpYXJ5JERCUDIpPDEwLF0pLCJjYXNlc1xuLSBFeGNsdWRpbmciLA0KICAgIG5yb3coZGlhcnlbIWlzLm5hKGRpYXJ5JERCUGZsYWcpICYgYWJzKGRpYXJ5JERCUDEtZGlhcnkkREJQMik+PTEwICYgZGlhcnkkREJQZmxhZz09RkFMU0UsXSksDQogICAgImZpcnN0IG1lYXN1cm1lbnRzXG4tIEV4Y2x1ZGluZyIsbnJvdyhkaWFyeVshaXMubmEoZGlhcnkkd2hhdEQpICYgZGlhcnkkd2hhdEQ9PSIyIixdKSwNCiAgICAic2Vjb25kIG1lc3VyZW1lbnRzXG4tIEludGVycG9sYXRpbmciLG5yb3coZGlhcnlbIWlzLm5hKGRpYXJ5JHdoYXREKSAmIGRpYXJ5JHdoYXREPT0iYm90aCIsXSksIm1lYXN1cmVtZW50cyIpDQpgYGANCg0KYGBgIHtyfQ0KIyAoMSkgYXZlcmFnZWQgY2FzZXMgKG5vIGZsYWdnZWQgYW5kIGRpc2NyZXBhbmNpZXMgPCAxMG1tSGcsIG9yIGZsYWdnZWQgPSAiaW52IikNCmRpYXJ5WygoIWlzLm5hKGRpYXJ5JERCUGZsYWcpICYgZGlhcnkkREJQZmxhZz09RkFMU0UgJiBhYnMoZGlhcnkkREJQMS1kaWFyeSREQlAyKSA8IDEwKSB8IA0KICAgICAgICAgKCFpcy5uYShkaWFyeSR3aGF0RCkgJiBkaWFyeSR3aGF0RD09ImludiIpKSwiREJQIl0gPC0gDQogIGFwcGx5KGRpYXJ5WygoIWlzLm5hKGRpYXJ5JERCUGZsYWcpICYgZGlhcnkkREJQZmxhZz09RkFMU0UgJiBhYnMoZGlhcnkkREJQMS1kaWFyeSREQlAyKSA8IDEwKSB8IA0KICAgICAgICAgKCFpcy5uYShkaWFyeSR3aGF0RCkgJiBkaWFyeSR3aGF0RD09ImludiIpKSxjKCJEQlAxIiwiREJQMiIpXSwxLG1lYW4pDQojICgyKSBjYXNlcyBvbmx5IGJhc2VkIG9uIHRoZSBzZWNvbmQgbWVhc3VyZW1lbnQgKGRpc2NyZXBhbmNpZXMgPj0gMTBtbUhnIEFORCBubyBmbGFncykNCmRpYXJ5WyFpcy5uYShkaWFyeSREQlBmbGFnKSAmIGRpYXJ5JERCUGZsYWc9PUZBTFNFICYgYWJzKGRpYXJ5JERCUDEtZGlhcnkkREJQMikgPj0gMTAsIkRCUCJdIDwtIA0KICBkaWFyeVshaXMubmEoZGlhcnkkREJQZmxhZykgJiBkaWFyeSREQlBmbGFnPT1GQUxTRSAmIGFicyhkaWFyeSREQlAxLWRpYXJ5JERCUDIpID49IDEwLCJEQlAyIl0NCiMgKDMpIGNhc2VzIG9ubHkgYmFzZWQgb24gdGhlIGZpcnN0IG1lYXN1cmVtZW50IChmbGFnZ2VkPVRSVUUgYW5kIHdoYXQgPSAiMiIpDQpkaWFyeVshaXMubmEoZGlhcnkkREJQZmxhZykgJiAhaXMubmEoZGlhcnkkd2hhdEQpICYgZGlhcnkkREJQZmxhZz09VFJVRSAmIGRpYXJ5JHdoYXREPT0iMiIsDQogICAgICAiREJQIl0gPC0gZGlhcnlbIWlzLm5hKGRpYXJ5JERCUGZsYWcpICYgZGlhcnkkREJQZmxhZz09VFJVRSAmIGRpYXJ5JHdoYXREPT0iMiIsIkRCUDEiXQ0KIyAoNCkgY2FzZXMgaW50ZXJwb2xhdGVkIGFzIHRoZSBtYXhpbXVtIHZhbHVlDQpmb3IoaSBpbiB3aGljaCghaXMubmEoZGlhcnkkd2hhdEQpICYgZGlhcnkkd2hhdEQ9PSJib3RoIikpeyANCiAgaWYoZGlhcnlbaSwiREJQMiJdPm1lYW4oZGlhcnlbZGlhcnkkSUQ9PWRpYXJ5W2ksIklEIl0sIkRCUCJdLG5hLnJtPVRSVUUpKXsNCiAgICBkaWFyeVtpLCJEQlAiXSA8LSBtYXgoZGlhcnlbZGlhcnkkSUQ9PWRpYXJ5W2ksIklEIl0sIkRCUCJdLG5hLnJtPVRSVUUpDQogIH0gZWxzZSB7IGRpYXJ5W2ksIkRCUCJdIDwtIG1pbihkaWFyeVtkaWFyeSRJRD09ZGlhcnlbaSwiSUQiXSwiREJQIl0sbmEucm09VFJVRSkgfX0NCg0KIyBzYW5pdHkgY2hlY2sNCm5yb3coZGlhcnlbKCFpcy5uYShkaWFyeSREQlBmbGFnKSAmIGlzLm5hKGRpYXJ5JERCUCkpfChpcy5uYShkaWFyeSREQlBmbGFnKSAmICFpcy5uYShkaWFyeSREQlApKSxdKSA9PSAwIA0KYGBgDQoNCjxicj4NCg0KIyMjIyAzLjIuNC4yLiBWaXN1YWwgaW5zcGVjdGlvbiB7I3Zpc3VhbC1pbnNwZWN0aW9uIC50YWJzZXQgLnRhYnNldC1mYWRlIC50YWJzZXQtcGlsbHN9DQoNClRoZW4sIHdlIHJlcGxpY2F0ZSB0aGUgcGxvdHMgZ2VuZXJhdGVkIGFib3ZlIGJ5IHNob3dpbmcgdGhlIGFnZ3JlZ2F0ZWQgQlAgdmFsdWVzIGluIGdyZWVuLg0KDQojIyMjIyBTQlANCg0KYGBgIHtyIGZpZy53aWR0aD0xMixmaWcuaGVpZ2h0PTgwLHdhcm5pbmc9RkFMU0V9DQpwbG90QlAoZGlhcnksQlA9IlMiLG5jb2w9NCxmbGFnZ2VkPSJTQlBmbGFnIix3aGF0PSJ3aGF0UyIsbWVhblZhbD0iU0JQIikNCmBgYA0KDQo8YnI+DQoNCiMjIyMjIERCUA0KDQpgYGAge3J9DQpwbG90QlAoZGlhcnksQlA9IkQiLG5jb2w9NCxmbGFnZ2VkPSJEQlBmbGFnIix3aGF0PSJ3aGF0RCIsbWVhblZhbD0iREJQIikNCmBgYA0KDQo8YnI+DQoNCiMjIyMgMy4yLjQuMy4gRGF0YSBpbnRlZ3JhdGlvbg0KDQpGaW5hbGx5LCB3ZSByZXBsYWNlIHRoZSByYXcgQlAgZGF0YSB3aXRoIHRoZSBwcm9jZXNzZWQgKGkuZS4sIGFnZ3JlZ2F0ZSkgdmFsdWVzIGluIHRoZSBgZGlhcnlgIGRhdGFzZXQgYW5kIHdlIHJlbW92ZSB0aGUgdmFyaWFibGVzIGlkZW50aWZ5aW5nIGZsYWdnZWQgY2FzZXMuDQoNCmBgYCB7cn0NCiMgcmVwbGFjaW5nIHJhdyBCUCB3aXRoIGFnZ3JlZ2F0ZSBCUA0KZGlhcnkgPC0gZGlhcnlbLGMoMTp3aGljaChjb2xuYW1lcyhkaWFyeSk9PSJkYXlPZmZ0b2RheSIpLHdoaWNoKGNvbG5hbWVzKGRpYXJ5KSVpbiVjKCJTQlAiLCJEQlAiKSksDQogICAgICAgICAgICAgICAgICB3aGljaChjb2xuYW1lcyhkaWFyeSk9PSJkYXlPZmZ5ZXN0ZXJkYXkiKToobmNvbChkaWFyeSktMikpXQ0KDQojIGNyZWF0aW5nIG5ldyB2YXJpYWJsZSBzdW1tYXJpemluZyBmbGFnZ2VkIGNhc2VzDQpkaWFyeSRmbGFnQlAgPC0gRkFMU0UNCmRpYXJ5WyghaXMubmEoZGlhcnkkU0JQZmxhZykgJiBkaWFyeSRTQlBmbGFnPT1UUlVFKXwoIWlzLm5hKGRpYXJ5JERCUGZsYWcpICYgZGlhcnkkREJQZmxhZz09VFJVRSksImZsYWdCUCJdIDwtIFRSVUUNCmRpYXJ5JFNCUGZsYWcgPC0gZGlhcnkkd2hhdFMgPC0gZGlhcnkkREJQZmxhZyA8LSBkaWFyeSR3aGF0RCA8LSBOVUxMICMgcmVtb3ZpbmcgdmFyaWFibGVzIGlkZW50aWZ5aW5nIGZsYWdnZWQgY2FzZXMNCmBgYA0KDQo8YnI+DQoNCiMjIDMuMy4gQk1JDQoNCkhlcmUsIHdlIGluc3BlY3QgdGhlIGRpc3RyaWJ1dGlvbiBvZiBgQk1JYCB2YWx1ZXMsIGFuZCB3ZSBjb21wYXJlIGl0IHdpdGggdGhlIGN1dC1vZmZzIHByb3Bvc2VkIGJ5IHRoZSBbV29ybGQgSGVhbHRoIE9yZ2FuaXphdGlvbiAoMjAxMCldKCNyZWYpLiBXZSBvYnNlcnZlICoqbm8gZXh0cmVtZSBCTUkgdmFsdWVzKiogZGVzcGl0ZSBhIGZldyBwYXJ0aWNpcGFudHMgaW4gdGhlIHVuZGVyd2VpZ2h0IChOID0gMyksIGFuZCBvYmVzaXR5IC0gY2xhc3MgSUkgY2F0ZWdvcnkgKE4gPSA4KSwgYW5kIG9uZSBwYXJ0aWNpcGFudCBpbiB0aGUgb2Jlc2UgLSBjbGFzcyBJSUkgY2F0ZWdvcnkuIFdlIGhhdmUgKipubyByZWFzb25zIHRvIGV4Y2x1ZGUqKiBwYXJ0aWNpcGFudHMgYmFzZWQgb24gYEJNSWAgdmFsdWVzLg0KDQpgYGAge3IgZmlnLndpZHRoPTEyLGZpZy5oZWlnaHQ9NCx3YXJuaW5nPUZBTFNFfQ0KaGlzdChwcmVscXMkQk1JLHhsYWI9IkJNSSAoa2cvbV4yKSIsYnJlYWtzPTMwLHhsaW09YygxNSw0MCkseWxpbT1jKDAsMTQpKQ0KYWJsaW5lKHY9YygxOC41LDI1LDMwLDM1LDQwKSxjb2w9InJlZCIsbHR5PTIpDQp0ZXh0KHg9YygxNiwyMS41LDI3LjUsMzIuNSwzNy41KSx5ID0gMTMsDQogICAgIGxhYmVscz1jKCJVbmRlcndlaWdodCIsIk5vcm1hbCB3ZWlnaHQiLCJQcmUtb2Jlc2l0eSIsIk9iZXNpdHkgSSIsIk9iZXNpdHkgSUkiKSkNCmBgYA0KDQo8YnI+DQoNCiMjIDMuNC4gRGFpbHkgd2lkZSBkYXRhc2V0DQoNCkhlcmUsIHdlIHVzZSB0aGUgYGRheWAgdmFyaWFibGUgY3JlYXRlZCBhYm92ZSB0byB0cmFuc2Zvcm0gdGhlIGBkaWFyeWAgZGF0YXNldCBmcm9tIHRoZSBjdXJyZW50IGxvbmcgZm9ybSAoaS5lLiwgb25lIHJvdyBwZXIgbWVhc3VyZW1lbnQNCm9jY2FzaW9uIHdpdGhpbiBkYXkgYW5kIHBhcnRpY2lwYW50KSB0byBhIGRhaWx5IHdpZGUgZm9ybSAoaS5lLiwgb25lIHJvdyBwZXIgZGF5IHdpdGhpbiBwYXJ0aWNpcGFudCwgd2l0aCBtZWFzdXJlbWVudHMgY29sbGVjdGVkIG9uIHRoZSBzYW1lIGRheSBiZWluZyBwcmVzZW50ZWQgaW4gdGhlIHNhbWUgbGluZSBvZiB0aGUgZGF0YXNldCkuDQoNCkZpcnN0LCB3ZSBzcGxpdCB0aGUgYGRpYXJ5YCBkYXRhc2V0IGJhY2sgdG8gdGhlIHRocmVlIGRhdGFzZXRzIGJhc2VkIG9uIHRoZSBtZWFzdXJlbWVudCBvY2Nhc2lvbiAoaS5lLiwgbW9ybmluZywgYWZ0ZXJub29uLCBhbmQgZXZlbmluZykuDQpgYGAge3J9DQojIHNvcnRpbmcgY29sdW1ucw0KZGlhcnkgPC0gZGlhcnlbLGMoIklEIiwiZGF5Iiwic3RhcnQiLCJlbmQiLCJkaWFyeVR5cGUiLCJkYXlPZmYiLCJkYXlPZmZ0b2RheSIsImRheU9mZnllc3RlcmRheSIsDQogICAgICAgICAgICAgICAgICAiU0JQIiwiREJQIiwiZmxhZ0JQIiwid2hlcmUiLCJjb25mb3VuZGVycyIsImNvZmZlZSIsInNtb2tlIiwic3BvcnQiLCJtZWFsIiwiZGFpbHlIYXNzbGVzIiwNCiAgICAgICAgICAgICAgICAgIGNvbG5hbWVzKGRpYXJ5KVt3aGljaChjb2xuYW1lcyhkaWFyeSk9PSJPQzEiKTp3aGljaChjb2xuYW1lcyhkaWFyeSk9PSJ3YWtlVGltZSIpXSwiaGhGcm9tQXdha2UiLA0KICAgICAgICAgICAgICAgICAgcGFzdGUoIkFXTCIsMTozLHNlcD0iIiksDQogICAgICAgICAgICAgICAgICBjb2xuYW1lcyhkaWFyeSlbd2hpY2goY29sbmFtZXMoZGlhcnkpPT0iV0wxIik6d2hpY2goY29sbmFtZXMoZGlhcnkpPT0id29ya0hvdXJzIildLCJJRGRheSIpXQ0KDQojIHNwbGl0dGluZyBkYXRhc2V0DQpkaWFyeV9tIDwtIGRpYXJ5W2RpYXJ5JGRpYXJ5VHlwZT09Ik0iLGMoMTp3aGljaChjb2xuYW1lcyhkaWFyeSk9PSJlbmQiKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB3aGljaChjb2xuYW1lcyhkaWFyeSk9PSJkYXlPZmZ0b2RheSIpOndoaWNoKGNvbG5hbWVzKGRpYXJ5KT09IkFXTDMiKSxuY29sKGRpYXJ5KSldDQpkaWFyeV9hIDwtIGRpYXJ5W2RpYXJ5JGRpYXJ5VHlwZT09IkEiLGMoMTp3aGljaChjb2xuYW1lcyhkaWFyeSk9PSJlbmQiKSx3aGljaChjb2xuYW1lcyhkaWFyeSk9PSJkYXlPZmYiKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB3aGljaChjb2xuYW1lcyhkaWFyeSk9PSJTQlAiKTp3aGljaChjb2xuYW1lcyhkaWFyeSk9PSJtZWFsIiksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgd2hpY2goY29sbmFtZXMoZGlhcnkpPT0iV0wxIik6d2hpY2goY29sbmFtZXMoZGlhcnkpPT0iV0UzIiksbmNvbChkaWFyeSkpXQ0KZGlhcnlfZSA8LSBkaWFyeVtkaWFyeSRkaWFyeVR5cGU9PSJFIixjKDE6d2hpY2goY29sbmFtZXMoZGlhcnkpPT0iZW5kIiksd2hpY2goY29sbmFtZXMoZGlhcnkpPT0iZGF5T2ZmIiksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgd2hpY2goY29sbmFtZXMoZGlhcnkpPT0iU0JQIik6d2hpY2goY29sbmFtZXMoZGlhcnkpPT0iZmxhZ0JQIiksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgd2hpY2goY29sbmFtZXMoZGlhcnkpPT0iY29uZm91bmRlcnMiKTp3aGljaChjb2xuYW1lcyhkaWFyeSk9PSJkYWlseUhhc3NsZXMiKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB3aGljaChjb2xuYW1lcyhkaWFyeSk9PSJFRTEiKTp3aGljaChjb2xuYW1lcyhkaWFyeSk9PSJ3b3JrSG91cnMiKSxuY29sKGRpYXJ5KSldDQoNCiMgcmVuYW1pbmcgY29sdW1ucyBzaGFyaW5nIHRoZSBzYW1lIG5hbWUgaW4gdGhlIHRocmVlIGRhdGFzZXRzDQpjbSA8LSBjb2xuYW1lcyhkaWFyeV9tKQ0KY2EgPC0gY29sbmFtZXMoZGlhcnlfYSkNCmNlIDwtIGNvbG5hbWVzKGRpYXJ5X2UpDQpjb2xuYW1lcyhkaWFyeV9tKVszOm5jb2woZGlhcnlfbSldW3doaWNoKGNvbG5hbWVzKGRpYXJ5X20pWzM6bmNvbChkaWFyeV9tKV0laW4lY2EgfCBjb2xuYW1lcyhkaWFyeV9tKVszOm5jb2woZGlhcnlfbSldJWluJWNlKV0gPC0NCiAgcGFzdGUoY29sbmFtZXMoZGlhcnlfbSlbMzpuY29sKGRpYXJ5X20pXVt3aGljaChjb2xuYW1lcyhkaWFyeV9tKVszOm5jb2woZGlhcnlfbSldJWluJWNhIHwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbG5hbWVzKGRpYXJ5X20pWzM6bmNvbChkaWFyeV9tKV0laW4lY2UpXSwibW9yIixzZXA9Il8iKQ0KY29sbmFtZXMoZGlhcnlfYSlbMzpuY29sKGRpYXJ5X2EpXVt3aGljaChjb2xuYW1lcyhkaWFyeV9hKVszOm5jb2woZGlhcnlfYSldJWluJWNtIHwgY29sbmFtZXMoZGlhcnlfYSlbMzpuY29sKGRpYXJ5X2EpXSVpbiVjZSldIDwtDQogIHBhc3RlKGNvbG5hbWVzKGRpYXJ5X2EpWzM6bmNvbChkaWFyeV9hKV1bd2hpY2goY29sbmFtZXMoZGlhcnlfYSlbMzpuY29sKGRpYXJ5X2EpXSVpbiVjbSB8DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb2xuYW1lcyhkaWFyeV9hKVszOm5jb2woZGlhcnlfYSldJWluJWNlKV0sImFmdCIsc2VwPSJfIikNCmNvbG5hbWVzKGRpYXJ5X2UpWzM6bmNvbChkaWFyeV9lKV1bd2hpY2goY29sbmFtZXMoZGlhcnlfZSlbMzpuY29sKGRpYXJ5X2UpXSVpbiVjbSB8IGNvbG5hbWVzKGRpYXJ5X2UpWzM6bmNvbChkaWFyeV9lKV0laW4lY2EpXSA8LQ0KICBwYXN0ZShjb2xuYW1lcyhkaWFyeV9lKVszOm5jb2woZGlhcnlfZSldW3doaWNoKGNvbG5hbWVzKGRpYXJ5X2UpWzM6bmNvbChkaWFyeV9lKV0laW4lY20gfA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29sbmFtZXMoZGlhcnlfZSlbMzpuY29sKGRpYXJ5X2UpXSVpbiVjYSldLCJldmUiLHNlcD0iXyIpDQoNCiMgYWRkaW5nIElEZGF5IGNvbHVtbiB0byBqb2luIGRhdGFzZXRzIGJhc2VkIG9uIElEIGFuZCBkYXkNCmNvbG5hbWVzKGRpYXJ5X20pW25jb2woZGlhcnlfbSldIDwtIGNvbG5hbWVzKGRpYXJ5X2EpW25jb2woZGlhcnlfYSldIDwtIGNvbG5hbWVzKGRpYXJ5X2UpW25jb2woZGlhcnlfZSldIDwtICJJRGRheSINCmBgYA0KDQo8YnI+DQoNClNlY29uZCwgd2UgbG9vayBmb3IgY2FzZXMgb2YgKipkb3VibGUgcmVzcG9uc2VzKiogd2l0aGluIGVhY2ggZGF0YXNldCBieSB1c2luZyB0aGUgYElEYCB4IGBkYXlgIGlkZW50aWZpZXIgY3JlYXRlZCBhYm92ZS4gQSB0b3RhbCBvZiBzaXggZG91YmxlIHJlc3BvbnNlcyBhcmUgZGV0ZWN0ZWQuDQpgYGAge3J9DQojIGRpYXJ5X206IDEgZG91YmxlIHJlc3BvbnNlIC0+IHRha2luZyAxc3Qgb25lDQpkaWFyeV9tW2RpYXJ5X20kSURkYXklaW4lZGlhcnlfbSRJRGRheVtkdXBsaWNhdGVkKGRpYXJ5X20kSURkYXkpXSxdIA0KZGlhcnlfbSA8LSBkaWFyeV9tWyEoZGlhcnlfbSRJRD09IlMwMjUiICYgYXMuY2hhcmFjdGVyKGRpYXJ5X20kZW5kX21vcik9PSIyMDIyLTA1LTAzIDEzOjUzOjM0IiksXQ0KDQojIGRpYXJ5X2E6IDIgZG91YmxlIHJlc3BvbnNlcyAtPiB0YWtpbmcgMXN0IG9yIDJkIGJhc2VkIG9uIHN1Ym1pc3Npb24gdGltZQ0KZGlhcnlfYVtkaWFyeV9hJElEZGF5JWluJWRpYXJ5X2EkSURkYXlbZHVwbGljYXRlZChkaWFyeV9hJElEZGF5KV0sXSANCmRpYXJ5X2EgPC0gZGlhcnlfYVshKChkaWFyeV9hJElEPT0iUzA0MCIgJiBhcy5jaGFyYWN0ZXIoZGlhcnlfYSRlbmRfYWZ0KT09IjIwMjItMDMtMDggMjA6MDE6MDEiKSB8DQogICAgICAgICAgICAgICAgICAgICAgIChkaWFyeV9hJElEPT0iUzA2MCIgJiBhcy5jaGFyYWN0ZXIoZGlhcnlfYSRlbmRfYWZ0KT09IjIwMjItMDEtMjUgMTg6NTg6MTAiKSB8DQogICAgICAgICAgICAgICAgICAgICAgIChkaWFyeV9hJElEPT0iUzExMyIgJiBhcy5jaGFyYWN0ZXIoZGlhcnlfYSRlbmRfYWZ0KT09IjIwMjItMDItMjggMjA6MzM6NDEiKSB8DQogICAgICAgICAgICAgICAgICAgICAgIChkaWFyeV9hJElEPT0iUzExMyIgJiBhcy5jaGFyYWN0ZXIoZGlhcnlfYSRlbmRfYWZ0KT09IjIwMjItMDMtMDEgMjE6NDE6NTgiKSksXQ0KDQojIGRpYXJ5X2U6IDMgZG91YmxlIHJlc3BvbnNlcyAtPiB0YWtpbmcgMm5kIG9yIDFzdCBiYXNlZCBvbiBzdWJtaXNzaW9uIHRpbWUNCmRpYXJ5X2VbZGlhcnlfZSRJRGRheSVpbiVkaWFyeV9lJElEZGF5W2R1cGxpY2F0ZWQoZGlhcnlfZSRJRGRheSldLF0gDQpgYGANCg0KPGJyPg0KDQpgYGAge3J9DQpkaWFyeV9lIDwtIGRpYXJ5X2VbISgoZGlhcnlfZSRJRD09IlMwNjAiICYgYXMuY2hhcmFjdGVyKGRpYXJ5X2UkZW5kX2V2ZSk9PSIyMDIyLTAxLTI2IDE5OjU3OjAyIikgfA0KICAgICAgICAgICAgICAgICAgICAgICAoZGlhcnlfZSRJRD09IlMxMDgiICYgZGlhcnlfZSRkYXlPZmZfZXZlPT1UUlVFKSksXQ0KIyBzYW5pdHkgY2hlY2sNCm5yb3coZGlhcnlfbVtkdXBsaWNhdGVkKGRpYXJ5X20kSURkYXkpLF0pID09IDAgJiBucm93KGRpYXJ5X2FbZHVwbGljYXRlZChkaWFyeV9hJElEZGF5KSxdKSA9PSAwICYNCiAgbnJvdyhkaWFyeV9lW2R1cGxpY2F0ZWQoZGlhcnlfZSRJRGRheSksXSkgPT0gMA0KYGBgDQoNCjxicj4NCg0KTm93IHdlIGNhbiBtZXJnZSB0aGUgdHJlZSBkYXRhc2V0IGludG8gYSAqKmRhaWx5IHdpZGUgZm9ybSBkYXRhc2V0KiouDQoNCmBgYCB7cn0NCiMgam9pbmluZyBkYXRhc2V0cw0KZGlhcnlfd2lkZSA8LSBwbHlyOjpqb2luKGRpYXJ5X2EscGx5cjo6am9pbihkaWFyeV9lLGRpYXJ5X20sYnk9IklEZGF5Iix0eXBlPSJmdWxsIiksYnk9IklEZGF5Iix0eXBlPSJmdWxsIikNCmRpYXJ5X3dpZGUgPC0gZGlhcnlfd2lkZVtvcmRlcihkaWFyeV93aWRlJElELGRpYXJ5X3dpZGUkZGF5KSxdICMgc29ydGluZyBieSBJRCBhbmQgZGF5DQoNCiMgc2FuaXR5IGNoZWNrDQpucm93KGRpYXJ5X3dpZGVbIWlzLm5hKGRpYXJ5X3dpZGUkc3RhcnRfYWZ0KSxdKSA9PSBucm93KGRpYXJ5X2EpICYNCiAgbnJvdyhkaWFyeV93aWRlWyFpcy5uYShkaWFyeV93aWRlJHN0YXJ0X2V2ZSksXSkgPT0gbnJvdyhkaWFyeV9lKSAmIA0KICBucm93KGRpYXJ5X3dpZGVbIWlzLm5hKGRpYXJ5X3dpZGUkc3RhcnRfbW9yKSxdKSA9PSBucm93KGRpYXJ5X20pDQoNCg0KIyBjaGVja2luZyBmb3IgZHVwbGljYXRlcw0KbnJvdyhkaWFyeV93aWRlW2R1cGxpY2F0ZWQoZGlhcnlfd2lkZSRJRGRheSksXSkNCmRpYXJ5X3dpZGUkSURkYXkgPC0gTlVMTCAjIHJlbW92aW5nIElEZGF5IChubyBsb25nZXIgbmVjZXNzYXJ5KQ0KDQojIGFkZGluZyB2YXJpYWJsZXMgdG8gZmlsdGVyIG1pc3NpbmcgZGF0YQ0KZGlhcnlfd2lkZVssYygiYWZ0IiwiZXZlIiwibW9yIildIDwtIDANCmRpYXJ5X3dpZGVbIWlzLm5hKGRpYXJ5X3dpZGUkc3RhcnRfYWZ0KSAmICFpcy5uYShkaWFyeV93aWRlJGRheU9mZl9hZnQpICYgZGlhcnlfd2lkZSRkYXlPZmZfYWZ0PT1GQUxTRSwiYWZ0Il0gPC0gMQ0KZGlhcnlfd2lkZVshaXMubmEoZGlhcnlfd2lkZSRzdGFydF9ldmUpICYgIWlzLm5hKGRpYXJ5X3dpZGUkZGF5T2ZmX2V2ZSkgJiBkaWFyeV93aWRlJGRheU9mZl9ldmU9PUZBTFNFLCJldmUiXSA8LSAxDQpkaWFyeV93aWRlWyFpcy5uYShkaWFyeV93aWRlJHN0YXJ0X21vcikgJiAhaXMubmEoZGlhcnlfd2lkZSRkYXlPZmZ5ZXN0ZXJkYXkpICYgZGlhcnlfd2lkZSRkYXlPZmZ5ZXN0ZXJkYXk9PUZBTFNFLCJtb3IiXSA8LSAxIA0KZGlhcnlfd2lkZVssYygiYWZ0IiwiZXZlIiwibW9yIildIDwtIGxhcHBseShkaWFyeV93aWRlWyxjKCJhZnQiLCJldmUiLCJtb3IiKV0sYXMuZmFjdG9yKQ0KZGlhcnlfd2lkZSA8LSBkaWFyeV93aWRlWyxjKDE6MiwobmNvbChkaWFyeV93aWRlKS0yKTpuY29sKGRpYXJ5X3dpZGUpLDM6KG5jb2woZGlhcnlfd2lkZSktMykpXQ0KDQojIHNvcnRpbmcgYnkgSUQgYW5kIGRheQ0KZGlhcnlfd2lkZSA8LSBkaWFyeV93aWRlW29yZGVyKGRpYXJ5X3dpZGUkSUQsZGlhcnlfd2lkZSRkYXkpLF0NCnJvd25hbWVzKGRpYXJ5X3dpZGUpIDwtIDE6bnJvdyhkaWFyeV93aWRlKQ0KDQojIHNob3dpbmcgZGF0YXNldA0KZGlhcnlfd2lkZVssYyhjb2xuYW1lcyhkaWFyeV93aWRlKVsxOjZdLCJzdGFydF9ldmUiLCJzdGFydF9tb3IiKV0NCmBgYA0KDQoNCjxicj4NCg0KIyMgMy41LiBKb2luaW5nIHByZWxxcw0KDQpIZXJlLCB3ZSBqb2luIHRoZSBkZW1vZ3JhcGhpYyBhbmQgb2NjdXBhdGlvbmFsIGluZm9ybWF0aW9uIGZyb20gdGhlIGBwcmVscXNgIGRhdGFzZXQgd2l0aCB0aGUgdGltZS12YXJ5aW5nIGRhdGEgaW5jbHVkZWQgaW4gdGhlIGBkaWFyeV93aWRlYCBkYXRhc2V0LiBUaGUgcmVzdWx0aW5nIGBkaWFyeV93aWRlYCBkYXRhc2V0IGhhcyBtdWx0aXBsZSByb3dzIHJlcG9ydGluZyB0aGUgc2FtZSBkZW1vZ3JhcGhpYyBhbmQgb2NjdXBhdGlvbmFsIHZhbHVlcyAobGV2ZWwtMikgcmVwZWF0ZWQgb3ZlciBtdWx0aXBsZSByb3dzIGFzc29jaWF0ZWQgd2l0aCB0aGUgc2FtZSBwYXJ0aWNpcGFudC4gTW9yZW92ZXIsIHdlIGFsc28gam9pbiB0aGUgcmVzcG9uc2VzIHRvIHRoZSByYXcgcmV0cm9zcGVjdGl2ZSB3b3JrYWhvbGlzbSBpdGVtcy4NCmBgYCB7cn0NCiMgcmVuYW1pbmcgcmV0cm9zcGVjdGl2ZSB3b3JrYWhvbGlzbSBpdGVtcw0KY29sbmFtZXMocHJlbHFzKVtncmVwKCJXSExTTSIsY29sbmFtZXMocHJlbHFzKSldIDwtIHBhc3RlMCgiZHV3YXMiLDE6MTApDQoNCiMgam9pbmluZyBwcmVscXMgdmFyaWFibGVzIHRvIGRpYXJ5X3dpZGUNCmRpYXJ5X3dpZGUgPC0gcGx5cjo6am9pbihkaWFyeV93aWRlLA0KICAgICAgICAgICAgICAgICAgICAgICAgIHByZWxxc1ssYygiSUQiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb2xuYW1lcyhwcmVscXMpW3doaWNoKGNvbG5hbWVzKHByZWxxcyk9PSJnZW5kZXIiKTp3aGljaChjb2xuYW1lcyhwcmVscXMpPT0iY2hpbGRyZW4iKV0sDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJob21lX2NoaWxkIiwicGFydG5lciIsImhvbWVfcGFydG5lciIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbG5hbWVzKHByZWxxcylbd2hpY2goY29sbmFtZXMocHJlbHFzKT09InNtb2tlciIpOndoaWNoKGNvbG5hbWVzKHByZWxxcyk9PSJ3b3JrVGltZSIpXSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcGFzdGUwKCJkdXdhcyIsMToxMCkpXSwNCiAgICAgICAgICAgICAgICAgICAgICAgICBieT0iSUQiLHR5cGU9ImxlZnQiKSAjIG1lcmdpbmcgZGF0YXNldHMgYnkgSUQNCg0KIyBzaG93aW5nIGV4YW1wbGVzDQpoZWFkKGRpYXJ5X3dpZGVbLGMoY29sbmFtZXMoZGlhcnlfd2lkZSlbMTo2XSwiU0JQX2FmdCIsImFnZSIsInNlY3RvciIpXSkNCmBgYA0KDQo8YnI+DQoNCiMjIDMuNi4gUmVzcG9uc2UgcHJvY2Vzc2luZw0KDQpIZXJlLCB3ZSBsb29rIGZvciBjYXNlcyBvZiAqKmluY29oZXJlbnQvaW5jb25zaXN0ZW50IHJlc3BvbnNlcyoqIGluIHNldmVyYWwgY29uc2lkZXJlZCB2YXJpYWJsZXMuDQoNCjxicj4NCg0KIyMjIDMuNi4xLiBEYXlzIG9mZg0KDQpGaXJzdCwgd2UgY2hlY2sgdGhlIGNhc2VzIG9mIGluY29oZXJlbnQgcmVzcG9uc2VzIHRvIHRoZSBgZGF5T2ZmYCB2YXJpYWJsZSBhY3Jvc3MgdGhlIHRocmVlIGRhaWx5IGRpYXJpZXMgKGUuZy4sIHBhcnRpY2lwYW50cyByZXBvcnRpbmcgIip0b2RheSwgSSBkaWQgbm90IHdvcmsqIiB0byB0aGUgYWZ0ZXJub29uIGJ1dCBub3QgdG8gdGhlIGV2ZW5pbmcgcXVlc3Rpb25uYWlyZSkuIFdlIGNhbiBzZWUgYSBmZXcgaW5jb2hlcmVudCBjYXNlcyAoKioyJSoqKSwgbWFpbmx5IGJldHdlZW4gYWZ0ZXJub29uIGFuZCBtb3JuaW5nLCBpbiB3aGljaCBwYXJ0aWNpcGFudHMgcmVwb3J0ZWQgYSBkYXktb2ZmIGF0IHRoZSBlbmQgb2YgdGhlIHdvcmtkYXkgYnV0IGFuIGluY29oZXJlbnQgcmVzcG9uc2Ugb24gdGhlIGZvbGxvd2luZyBkYXkuIFNpbmNlIHdlIGhhdmUgbm8gY3JpdGVyaWEgZm9yIGVzdGFibGlzaGluZyB3aGljaCB3YXMgdGhlICd0cnVlJyBhbnN3ZXIsIHdlIGFzc3VtZSB0aGF0ICh1bil2b2x1bnRhcnkgbWlzdGFrZXMgd2VyZSBtYWRlIGZvciBgZGF5T2ZmPVRSVUVgIHJlc3BvbnNlcywgKip0cmVhdGluZyB0aGVtIGFzIG1pc3NpbmcgcmVzcG9uc2VzKiouIE5vdGUgdGhhdCBub25lIG9mIHRoZSBjYXNlcyB3aXRoIGBkYXlPZmZfZXZlPUZBTFNFYCBoYXZlIGB3b3JrSG91cnM9MGAuDQpgYGAge3J9DQojIDEpIGluY29uc2lzdGVuY2llcyB3aXRoaW4gRXZlbmluZzogZGF5T2ZmX2V2ZSA9IEZBTFNFIGJ1dCB0ZWxlV29yayA9ICJkYXlPZmYiIChOID0gNCkNCmRpYXJ5X3dpZGVbIWlzLm5hKGRpYXJ5X3dpZGUkdGVsZVdvcmspICYgZGlhcnlfd2lkZSR0ZWxlV29yaz09ImRheU9mZiIsYygiSUQiLCJkYXkiLCJ0ZWxlV29yayIsIndvcmtIb3VycyIpXQ0KZGlhcnlfd2lkZVshaXMubmEoZGlhcnlfd2lkZSR0ZWxlV29yaykgJiBkaWFyeV93aWRlJHRlbGVXb3JrPT0iZGF5T2ZmIiwidGVsZVdvcmsiXSA8LSAib2ZmaWNlIiAjIHJlY29kaW5nIGFzIHRlbGVXb3JrPSJvZmZpY2UiDQoNCiMgMikgaW5jb25zaXN0ZW5jaWVzIGJldHdlZW4gQWZ0ZXJub29uICYgRXZlbmluZzogZGF5T2ZmX2FmdCAhPSBkYXlPZmZfZXZlIChOID0gMTApDQpkaWFyeV93aWRlWyFpcy5uYShkaWFyeV93aWRlJGRheU9mZl9hZnQpICYgIWlzLm5hKGRpYXJ5X3dpZGUkZGF5T2ZmX2V2ZSkgJiBkaWFyeV93aWRlJGRheU9mZl9hZnQgIT0gZGlhcnlfd2lkZSRkYXlPZmZfZXZlLA0KICAgICAgICAgICBjKCJJRCIsImRheSIsInRlbGVXb3JrIiwid29ya0hvdXJzIiwiYWZ0IiwiV0wxIiwiZXZlIiwiRUUxIiwiZGF5T2ZmX2V2ZSIsImRheU9mZl9hZnQiKV0NCmRpYXJ5X3dpZGVbIWlzLm5hKGRpYXJ5X3dpZGUkZGF5T2ZmX2FmdCkgJiAhaXMubmEoZGlhcnlfd2lkZSRkYXlPZmZfZXZlKSAmIA0KICAgICAgICAgICAgIGRpYXJ5X3dpZGUkZGF5T2ZmX2FmdD09VFJVRSAmIGRpYXJ5X3dpZGUkZGF5T2ZmX2V2ZSA9PSBGQUxTRSwiZGF5T2ZmX2FmdCJdIDwtIE5BICMgcmVwbGFjaW5nIGluY29ycmVjdCBkYXlPZmYgYXMgTkENCmRpYXJ5X3dpZGVbIWlzLm5hKGRpYXJ5X3dpZGUkZGF5T2ZmX2FmdCkgJiAhaXMubmEoZGlhcnlfd2lkZSRkYXlPZmZfZXZlKSAmIA0KICAgICAgICAgICAgIGRpYXJ5X3dpZGUkZGF5T2ZmX2FmdD09RkFMU0UgJiBkaWFyeV93aWRlJGRheU9mZl9ldmUgPT0gVFJVRSwiZGF5T2ZmX2V2ZSJdIDwtIE5BDQoNCiMgMykgaW5jb25zaXN0ZW5jaWVzIGJldHdlZW4gQWZ0ZXJub29uICYgRXZlbmluZzogZGF5T2ZmX2FmdCA9IEZBTFNFIGJ1dCB0ZWxlV29yayA9ICJkYXlPZmYiIChOID0gMCkNCmRpYXJ5X3dpZGVbIWlzLm5hKGRpYXJ5X3dpZGUkZGF5T2ZmX2FmdCkgJiAhaXMubmEoZGlhcnlfd2lkZSR0ZWxlV29yaykgJiANCiAgICAgICAgICAgICBkaWFyeV93aWRlJGRheU9mZl9hZnQ9PUZBTFNFICYgZGlhcnlfd2lkZSR0ZWxlV29yaz09ImRheU9mZiIsDQogICAgICAgICAgIGMoIklEIiwiZGF5IiwidGVsZVdvcmsiLCJ3b3JrSG91cnMiLCJhZnQiLCJXTDEiLCJldmUiLCJFRTEiLCJkYXlPZmZfZXZlIiwiZGF5T2ZmX2FmdCIpXQ0KDQojIDQpIGluY29uc2lzdGVuY2llcyBiZXR3ZWVuIEFmdGVybm9vbiAmIE1vcm5pbmc6IGRheU9mZl9hZnQgIT0gZGF5T2ZmeWVzdGVyZGF5IChOID0gNCkNCmRpYXJ5X3dpZGVbIWlzLm5hKGRpYXJ5X3dpZGUkZGF5T2ZmX2FmdCkgJiAhaXMubmEoZGlhcnlfd2lkZSRkYXlPZmZ5ZXN0ZXJkYXkpICYgZGlhcnlfd2lkZSRkYXlPZmZfYWZ0IT1kaWFyeV93aWRlJGRheU9mZnllc3RlcmRheSwNCiAgICAgICAgICAgYygiSUQiLCJkYXkiLCJ3b3JrSG91cnMiLCJhZnQiLCJXTDEiLCJtb3IiLCJTUTEiLCJkYXlPZmZ5ZXN0ZXJkYXkiLCJkYXlPZmZfYWZ0IildDQpkaWFyeV93aWRlWyFpcy5uYShkaWFyeV93aWRlJGRheU9mZl9hZnQpICYgIWlzLm5hKGRpYXJ5X3dpZGUkZGF5T2ZmeWVzdGVyZGF5KSAmIA0KICAgICAgICAgICAgIGRpYXJ5X3dpZGUkZGF5T2ZmX2FmdD09VFJVRSAmIGRpYXJ5X3dpZGUkZGF5T2ZmeWVzdGVyZGF5ID09IEZBTFNFLCJkYXlPZmZfYWZ0Il0gPC0gTkEgIyByZXBsYWNpbmcgd2l0aCBOQQ0KZGlhcnlfd2lkZVshaXMubmEoZGlhcnlfd2lkZSRkYXlPZmZfYWZ0KSAmICFpcy5uYShkaWFyeV93aWRlJGRheU9mZnllc3RlcmRheSkgJiANCiAgICAgICAgICAgICBkaWFyeV93aWRlJGRheU9mZl9hZnQ9PUZBTFNFICYgZGlhcnlfd2lkZSRkYXlPZmZ5ZXN0ZXJkYXkgPT0gVFJVRSwiZGF5T2ZmeWVzdGVyZGF5Il0gPC0gTkENCg0KIyA1KSBpbmNvbnNpc3RlbmNpZXMgYmV0d2VlbiBFdmVuaW5nICYgTW9ybmluZzogZGF5T2ZmX2V2ZSAhPSBkYXlPZmZ5ZXN0ZXJkYXkgKE4gPSAyKQ0KZGlhcnlfd2lkZVshaXMubmEoZGlhcnlfd2lkZSRkYXlPZmZfZXZlKSAmICFpcy5uYShkaWFyeV93aWRlJGRheU9mZnllc3RlcmRheSkgJiBkaWFyeV93aWRlJGRheU9mZl9ldmUhPWRpYXJ5X3dpZGUkZGF5T2ZmeWVzdGVyZGF5LA0KICAgICAgICAgICBjKCJJRCIsImRheSIsIndvcmtIb3VycyIsImV2ZSIsIkVFMSIsIm1vciIsIlNRMSIsImRheU9mZnllc3RlcmRheSIsImRheU9mZl9ldmUiKV0NCmRpYXJ5X3dpZGVbIWlzLm5hKGRpYXJ5X3dpZGUkZGF5T2ZmX2V2ZSkgJiAhaXMubmEoZGlhcnlfd2lkZSRkYXlPZmZ5ZXN0ZXJkYXkpICYgZGlhcnlfd2lkZSRkYXlPZmZfZXZlIT1kaWFyeV93aWRlJGRheU9mZnllc3RlcmRheSwNCiAgICAgICAgICAgImRheU9mZl9ldmUiXSA8LSBOQSAjIHJlcGxhY2luZyB1bmV4cGVjdGVkIHZhbHVlIHdpdGggTkENCg0KIyA2KSBpbmNvbnNpc3RlbmNpZXMgYmV0d2VlbiBFdmVuaW5nICYgTW9ybmluZzogdGVsZVdvcmsgPSAiZGF5T2ZmIiBidXQgZGF5T2ZmeWVzdGVyZGF5PUZBTFNFIChOID0gMCkNCmRpYXJ5X3dpZGVbIWlzLm5hKGRpYXJ5X3dpZGUkZGF5T2ZmeWVzdGVyZGF5KSAmICFpcy5uYShkaWFyeV93aWRlJHRlbGVXb3JrKSAmIA0KICAgICAgICAgICAgIGRpYXJ5X3dpZGUkZGF5T2ZmeWVzdGVyZGF5PT1GQUxTRSAmIGRpYXJ5X3dpZGUkdGVsZVdvcms9PSJkYXlPZmYiLA0KICAgICAgICAgICBjKCJJRCIsImRheSIsInRlbGVXb3JrIiwid29ya0hvdXJzIiwiZXZlIiwiRUUxIiwibW9yIiwiU1ExIiwiZGF5T2ZmX2V2ZSIsImRheU9mZnllc3RlcmRheSIpXQ0KYGBgDQoNCjxicj4NCg0KU2ltaWxhcmx5LCB3ZSBpbnNwZWN0IGNhc2VzIG9mIHBhcnRpY2lwYW50cyByZXBvcnRpbmcgd29ya2luZyBkYXlzIGJ1dCBhbnN3ZXJpbmcgIlRvZGF5IEkgZGlkIG5vdCB3b3JrIiB0byB0aGUgYHRlbGVXb3JrYCBpdGVtIGluIHRoZSBldmVuaW5nIHF1ZXN0aW9ubmFpcmUsIGFuZCB2aWNlIHZlcnNhLiBXZSBjYW4gbm90ZSB0aGF0IHRoZXJlIGFyZSAqKm5vIGNhc2VzKiogb2YgaW5jb2hlcmVudCByZXNwb25zZXMgcmVsYXRlZCB0byB0aGVzZSB2YXJpYWJsZXMuDQoNCmBgYCB7cn0NCiMgZXZlbmluZyBkYXlPZmYgaW5jb2hlcmVudCB0byBldmVuaW5nIHRlbGV3b3JrIChOID0gMCkNCmRpYXJ5X3dpZGVbIWlzLm5hKGRpYXJ5X3dpZGUkZGF5T2ZmX2V2ZSkgJiAhaXMubmEoZGlhcnlfd2lkZSR0ZWxld29yaykgJg0KICAgICAgICAgICAgICgoZGlhcnlfd2lkZSRkYXlPZmZfZXZlPT1GQUxTRSAmIGRpYXJ5X3dpZGUkdGVsZVdvcms9PSJkYXlPZmYiKSB8DQogICAgICAgICAgICAgICAgKGRpYXJ5X3dpZGUkZGF5T2ZmX2V2ZT09VFJVRSAmIGRpYXJ5X3dpZGUkdGVsZVdvcmshPSJkYXlPZmYiKSksDQogICAgICAgICAgIGMoIklEIiwiZGF5T2ZmX2V2ZSIsInRlbGVXb3JrIiwid29ya0hvdXJzIildDQoNCiMgYWZ0ZXJub29uIGRheU9mZiBpbmNvaGVyZW50IHRvIGV2ZW5pbmcgdGVsZXdvcmsgKE4gPSAwKQ0KZGlhcnlfd2lkZVshaXMubmEoZGlhcnlfd2lkZSRkYXlPZmZfYWZ0KSAmICFpcy5uYShkaWFyeV93aWRlJHRlbGV3b3JrKSAmDQogICAgICAgICAgICAgKChkaWFyeV93aWRlJGRheU9mZl9hZnQ9PUZBTFNFICYgZGlhcnlfd2lkZSR0ZWxlV29yaz09ImRheU9mZiIpIHwNCiAgICAgICAgICAgICAgICAoZGlhcnlfd2lkZSRkYXlPZmZfYWZ0PT1UUlVFICYgZGlhcnlfd2lkZSR0ZWxlV29yayE9ImRheU9mZiIpKSwNCiAgICAgICAgICAgYygiSUQiLCJkYXlPZmZfYWZ0IiwidGVsZVdvcmsiLCJ3b3JrSG91cnMiKV0NCg0KIyBtb3JuaW5nIGRheU9mZnllc3RlcmRheSBpbmNvaGVyZW50IHRvIGV2ZW5pbmcgdGVsZXdvcmsgKE4gPSAwKQ0KZGlhcnlfd2lkZVshaXMubmEoZGlhcnlfd2lkZSRkYXlPZmZ5ZXN0ZXJkYXkpICYgIWlzLm5hKGRpYXJ5X3dpZGUkdGVsZXdvcmspICYNCiAgICAgICAgICAgICAoKGRpYXJ5X3dpZGUkZGF5T2ZmeWVzdGVyZGF5PT1GQUxTRSAmIGRpYXJ5X3dpZGUkdGVsZVdvcms9PSJkYXlPZmYiKSB8DQogICAgICAgICAgICAgICAgKGRpYXJ5X3dpZGUkZGF5T2ZmeWVzdGVyZGF5PT1UUlVFICYgZGlhcnlfd2lkZSR0ZWxlV29yayE9ImRheU9mZiIpKSwNCiAgICAgICAgICAgYygiSUQiLCJkYXlPZmZ5ZXN0ZXJkYXkiLCJ0ZWxlV29yayIsIndvcmtIb3VycyIpXQ0KYGBgDQoNCjxicj4NCg0KRmluYWxseSwgd2UgaW5zcGVjdCBhbGwgY2FzZXMgd2l0aCBgd29ya0hvdXJzID0gMGAuIFdlIGNhbiBzZWUgb25seSBhIGZldyBvZiBzdWNoIGNhc2VzICgqKjIlKiopLCBhbGwgb2Ygd2hpY2ggc2hvdyBgZGF5T2ZmX2V2ZT1GQUxTRWAgKGFsc28gYmVjYXVzZSBpdCB3YXMgYSBuZWNlc3NhcnkgY29uZGl0aW9uIGZvciByZXNwb25kaW5nIHRvIHRoZSBgd29ya0hvdXJzYCBxdWVzdGlvbikgYXMgd2VsbCBhcyBgZGF5T2ZmX2FmdD1GQUxTRWAgYW5kIGBkYXlPZmZ5ZXN0ZXJkYXk9RkFMU0VgLiBEdWUgdG8gdGhpcyBpbmNvaGVyZW5jZSwgd2UgJ3RydXN0JyB0aGUgcmVzcG9uc2VzIHRvIGBkYXlPZmZgIGl0ZW1zIGFuZCB3ZSBhc3N1bWUgdGhhdCB0aGVzZSBgd29ya0hvdXJzYCByZXNwb25zZXMgd2VyZSAqKmNhcmVsZXNzIHJlc3BvbnNlcyoqLiBUaHVzLCB3ZSAqKmludGVycG9sYXRlKiogdGhlbSBieSBhc3NpZ25pbmcgdGhlIG1lYW4gTm8ub2YgYHdvcmtIb3Vyc2AgcmVwb3J0ZWQgYnkgdGhlIHNhbWUgcGFydGljaXBhbnQgaW4gdGhlIG90aGVyIG9jY2FzaW9ucy4gV2UgYWxzbyBub3RlIG9uZSBwYXJ0aWNpcGFudCAoYFMxMzdgKSB0aGF0IHJlcG9ydGVkIGB3b3JrSG91cnM9MGAgaW4gYWxsIG9jY2FzaW9ucy4gVGh1cywgcmVzcG9uc2VzIGFyZSBpbnRlcnBvbGF0ZWQgYmFzZWQgb24gdGhlIGB3ZWVrSG91cnNgIHF1ZXN0aW9uIGZyb20gdGhlIGBwcmVscXNgIGRhdGEgb2YgdGhlIHNhbWUgcGFydGljaXBhbnQsIGFuZCB3ZSBmbGFnIHRoaXMgcGFydGljaXBhbnQgYXMgYSBwb3RlbnRpYWwgYGNhcmVsZXNzYCByZXNwb25kZW50Lg0KDQpgYGAge3J9DQojIGluc3BlY3RpbmcgY2FzZXMgb2Ygd29ya0hvdXJzID0gMA0KY2F0KG5yb3coZGlhcnlfd2lkZVshaXMubmEoZGlhcnlfd2lkZSR3b3JrSG91cnMpICYgZGlhcnlfd2lkZSR3b3JrSG91cnM9PTAsXSksImNhc2VzIG9mIHdvcmtIb3VycyA9IDAiKQ0KDQojIGluc3BlY3RpbmcgcmVzcG9uc2VzIHRvIGNyaXRpY2FsIHZhcmlhYmxlcyBmb3Igc3VjaCBjYXNlcw0KZGlhcnlfd2lkZVshaXMubmEoZGlhcnlfd2lkZSR3b3JrSG91cnMpICYgZGlhcnlfd2lkZSR3b3JrSG91cnM9PTAsDQogICAgICAgICAgIGMoIklEIiwiZGF5T2ZmX2FmdCIsImRheU9mZl9ldmUiLCJkYXlPZmZ5ZXN0ZXJkYXkiLCJ3b3JrSG91cnMiLCJsYXRlV29ya0hvdXJzIildDQoNCiMgaW50ZXJwb2xhdGluZyByZXNwb25zZXMgKGkuZS4sIGFzc2lnbmluZyB0aGUgbWVhbiBOby4gb2Ygd29ya0hvdXJzIGZvciBlYWNoIHBhcnRpY2lwYW50KQ0KSURzIDwtIGxldmVscyhhcy5mYWN0b3IoYXMuY2hhcmFjdGVyKGRpYXJ5X3dpZGVbIWlzLm5hKGRpYXJ5X3dpZGUkd29ya0hvdXJzKSAmIGRpYXJ5X3dpZGUkd29ya0hvdXJzPT0wLCJJRCJdKSkpDQpmb3IoSUQgaW4gSURzWzE6KGxlbmd0aChJRHMpLTEpXSl7DQogIGRpYXJ5X3dpZGVbZGlhcnlfd2lkZSRJRD09SUQgJiAhaXMubmEoZGlhcnlfd2lkZSR3b3JrSG91cnMpICYgZGlhcnlfd2lkZSR3b3JrSG91cnM9PTAsIndvcmtIb3VycyJdIDwtDQogICAgbWVhbihkaWFyeV93aWRlW2RpYXJ5X3dpZGUkSUQ9PUlEICYgIWlzLm5hKGRpYXJ5X3dpZGUkd29ya0hvdXJzKSAmIGRpYXJ5X3dpZGUkd29ya0hvdXJzIT0wLCJ3b3JrSG91cnMiXSl9DQoNCiMgaW50ZXJwb2xhdGluZyByZXNwb25zZXMgb2Ygb25lIHBhcnRpY2lwYW50IHRoYXQgYWx3YXlzIHJlcG9ydGVkIHdvcmtIb3Vycz0wIGJhc2VkIG9uIHByZWxxcyB3ZWVrSG91cnMNCnByZWxxc1twcmVscXMkSUQ9PSJTMTM3IixjKCJJRCIsInN0YXJ0Iiwiam9iIiwicG9zaXRpb24iLCJzZWN0b3IiLCJ3ZWVrSG91cnMiLCJ3ZWVrSG91cnNfcmVtb3RlIiwid29ya1RpbWUiKV0NCmRpYXJ5X3dpZGVbZGlhcnlfd2lkZSRJRD09IlMxMzciICYgIWlzLm5hKGRpYXJ5X3dpZGUkZGF5T2ZmX2V2ZSkgJiBkaWFyeV93aWRlJGRheU9mZl9ldmU9PUZBTFNFLCJ3b3JrSG91cnMiXSA8LQ0KICBwcmVscXNbcHJlbHFzJElEPT0iUzEzNyIsIndlZWtIb3VycyJdLzUNCg0KIyBmbGFnZ2luZyBTMTM3IGFzIGEgcG90ZW50aWFsIGNhcmVsZXNzIHJlc3BvbmRlbnQNCnByZWxxcyRjYXJlbGVzcyA8LSBGQUxTRQ0KcHJlbHFzW3ByZWxxcyRJRD09IlMxMzciLCJjYXJlbGVzcyJdIDwtIFRSVUUNCmRpYXJ5X3dpZGUgPC0gcGx5cjo6am9pbihkaWFyeV93aWRlLHByZWxxc1ssYygiSUQiLCJjYXJlbGVzcyIpXSxieT0iSUQiLHR5cGU9ImxlZnQiKSAjIGpvaW5pbmcgY2FyZWxlc3MgdG8gZGlhcnlfd2lkZQ0KYGBgDQoNCjxicj4NCg0KIyMjIDMuNi4yLiBTdGFydCB0aW1lDQoNCkhlcmUsIHdlIGluc3BlY3QgdGhlIGRpc3RyaWJ1dGlvbiBvZiBgc3RhcnRgIHRpbWVzIGxvb2tpbmcgZm9yICoqZmlsdGVyaW5nIHJlc3BvbnNlcyBvdXQgb2YgdGltZSoqIChlLmcuLCBtb3JuaW5nIGRpYXJ5IGZpbGxlZCBpbiB0aGUgZXZlbmluZykuDQoNCmBgYCB7ciBmaWcud2lkdGg9MTIsZmlnLmhlaWdodD0zfQ0KIyBwbG90dGluZw0KcGFyKG1mcm93PWMoMSwzKSkNCmhpc3QoYXMuUE9TSVhjdChzdWJzdHIoZGlhcnlfd2lkZSRzdGFydF9hZnQsMTIsMTkpLGZvcm1hdD0iJUg6JU06JVMiKSxicmVha3M9ImhvdXJzIixtYWluPSJBZnRlcm5vb24iLHhsYWI9IiIpDQpoaXN0KGFzLlBPU0lYY3Qoc3Vic3RyKGRpYXJ5X3dpZGUkc3RhcnRfZXZlLDEyLDE5KSxmb3JtYXQ9IiVIOiVNOiVTIiksYnJlYWtzPSJob3VycyIsbWFpbj0iRXZlbmluZyIseGxhYj0iIikNCmhpc3QoYXMuUE9TSVhjdChzdWJzdHIoZGlhcnlfd2lkZSRzdGFydF9tb3IsMTIsMTkpLGZvcm1hdD0iJUg6JU06JVMiKSxicmVha3M9ImhvdXJzIixtYWluPSJNb3JuaW5nIix4bGFiPSIiKQ0KYGBgDQoNCjxicj4NCg0KIyMjIyAzLjYuMi4xLiBGaWx0ZXJpbmcgQWZ0ZXJub29uDQoNCldpdGggZmxhZ2dlZCAqKkFmdGVybm9vbioqIHJlc3BvbnNlcyBnaXZlbiAqKmFmdGVyIDIyOjAwKiogKE4gPSAxMSkgOg0KDQotICAgd2UgKiprZWVwKiogYWxsIHJlc3BvbnNlcyB0aGF0IHdlcmUgc3VibWl0dGVkICoqdXAgdG8gb25lIGhvdXIgYmVmb3JlKiogc3RhcnRpbmcgdGhlIEV2ZW5pbmcgZGlhcnkgKE4gPSAzKQ0KDQotICAgd2UgKipvbmx5IGNvbnNpZGVyIHJldHJvc3BlY3RpdmUgaXRlbXMqKiAoaS5lLiwgYGRheU9mZl9hZnRgLCBgV0xgLCBgV0hMU01gLCBgV0VgKSBhbmQgbm90IG1vbWVudGFyeSBpdGVtcyAoaS5lLiwgY29uZm91bmRlcnMgYW5kIEJQIGFyZSByZW1vdmVkKSBmb3IgcmVzcG9uc2VzIHN1Ym1pdHRlZCAqKmxlc3MgdGhhbiBvbmUgaG91ciBiZWZvcmUqKiBzdGFydGluZyB0aGUgRXZlbmluZyBkaWFyeSAoTiA9IDYpDQoNCi0gICB3ZSAqKnJlY29kZSBtb21lbnRhcnkgaXRlbXMqKiAoaS5lLiwgQlAsIGNvbmZvdW5kZXJzKSBhcyB0aGV5IHdlcmUgcmVzcG9uZGVkICoqaW4gdGhlIEV2ZW5pbmcqKiBmb3IgYWxsIHJlc3BvbnNlcyBzdWJtaXR0ZWQgbGF0ZXIgdGhhbiAyMjowMCB3aXRoICoqbm8gc3Vic2VxdWVudCBFdmVuaW5nIHJlc3BvbnNlKiogKGkuZS4sIEJQIHZhbHVlcykgYnV0IHdpdGggbm9ubWlzc2luZyBhZnRlcm5vb24gQlAgKE4gPSAyKQ0KDQpgYGAge3J9DQojIHNlbGVjdGluZyBmbGFnZ2VkIGNhc2VzIC0gYWZ0ZXJub29uIChOID0gMTEpDQpkaWFyeV93aWRlJElEZGF5IDwtIHBhc3RlKGRpYXJ5X3dpZGUkSUQsZGlhcnlfd2lkZSRkYXksc2VwPSJfIikgIyByZS1jcmVhdGluZyBJRGRheQ0KZmxhZ0EgPC0gZGlhcnlfd2lkZVshaXMubmEoZGlhcnlfd2lkZSRzdGFydF9hZnQpICYgKGFzLlBPU0lYY3Qoc3Vic3RyKGRpYXJ5X3dpZGUkc3RhcnRfYWZ0LDEyLDE2KSxmb3JtYXQ9IiVIOiVNIikgPCAjIEEgYWZ0ZXIgMjI6MDANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFzLlBPU0lYY3QoIjE1OjAwIixmb3JtYXQ9IiVIOiVNIix0ej0iR01UIikgfA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYXMuUE9TSVhjdChzdWJzdHIoZGlhcnlfd2lkZSRzdGFydF9hZnQsMTIsMTYpLGZvcm1hdD0iJUg6JU0iKSA+DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhcy5QT1NJWGN0KCIyMjowMCIsZm9ybWF0PSIlSDolTSIsdHo9IkdNVCIpKSxdIA0KZmxhZ0FbLGMoIklEZGF5Iiwic3RhcnRfYWZ0IiwiZW5kX2FmdCIsInN0YXJ0X2V2ZSIsIndvcmtIb3VycyIsImxhdGVXb3JrSG91cnMiLCJ3b3JrVGltZSIpXSAjIHNob3dpbmcgZmxhZ2dlZCBjYXNlcw0KDQojIG1hcmtpbmcgcmVzcG9uc2VzDQpmbGFnQSRmbGFnIDwtIE5BDQpmbGFnQVshaXMubmEoZmxhZ0Ekc3RhcnRfZXZlKSAmIGRpZmZ0aW1lKGZsYWdBJHN0YXJ0X2V2ZSxmbGFnQSRlbmRfYWZ0LHVuaXRzPSJob3VycyIpPjEsImZsYWciXSA8LSAib2siDQpmbGFnQVshaXMubmEoZmxhZ0Ekc3RhcnRfZXZlKSAmIGRpZmZ0aW1lKGZsYWdBJHN0YXJ0X2V2ZSxmbGFnQSRlbmRfYWZ0LHVuaXRzPSJob3VycyIpPD0xLCJmbGFnIl0gPC0gIm1vbWVudGFyeS5PVVQiDQpmbGFnQVtpcy5uYShmbGFnQSRTQlBfZXZlKSAmICFpcy5uYShmbGFnQSRTQlBfYWZ0KSwiZmxhZyJdIDwtICJ0b0V2ZW5pbmciDQp0YWJsZShmbGFnQSRmbGFnKSAjIHNob3dpbmcgTm8uIG9mIGNhc2VzDQoNCiMgZmlsdGVyaW5nIHJlc3BvbnNlcw0KZGlhcnlfd2lkZSRmbGFnQSA8LSBOQSAjIGZsYWdnaW5nIGFsbCBmbGFnQSBjYXNlcyBpbiB0aGUgZGlhcnlfd2lkZSBkYXRhc2V0DQpkaWFyeV93aWRlW2RpYXJ5X3dpZGUkSURkYXklaW4lbGV2ZWxzKGFzLmZhY3RvcihmbGFnQSRJRGRheSkpLCJmbGFnQSJdIDwtIGZsYWdBWywiZmxhZyJdDQphZnRfY29scyA8LSB3aGljaChjb2xuYW1lcyhkaWFyeV93aWRlKT09IlNCUF9hZnQiKTp3aGljaChjb2xuYW1lcyhkaWFyeV93aWRlKT09Im1lYWxfYWZ0IikgIyBhZnRlcm5vb24gbW9tZW50YXJ5IGNvbHVtbnMNCmV2ZV9jb2xzIDwtIHdoaWNoKGNvbG5hbWVzKGRpYXJ5X3dpZGUpPT0iU0JQX2V2ZSIpOndoaWNoKGNvbG5hbWVzKGRpYXJ5X3dpZGUpPT0ibWVhbF9ldmUiKSAjIGV2ZW5pbmcgbW9tZW50YXJ5IGNvbHVtbnMNCmRpYXJ5X3dpZGVbIWlzLm5hKGRpYXJ5X3dpZGUkZmxhZ0EpICYgZGlhcnlfd2lkZSRmbGFnQT09Im1vbWVudGFyeS5PVVQiLGFmdF9jb2xzXSA8LSBOQSAjIHJlbW92aW5nIG1vbWVudGFyeSAoTiA9IDYpDQpkaWFyeV93aWRlWyFpcy5uYShkaWFyeV93aWRlJGZsYWdBKSAmIGRpYXJ5X3dpZGUkZmxhZ0E9PSJ0b0V2ZW5pbmciLGV2ZV9jb2xzXSA8LSAjIG1vbWVudGFyeSB2YWx1ZXMgdG8gRXZlbmluZyAoTiA9IDIpDQogIGRpYXJ5X3dpZGVbIWlzLm5hKGRpYXJ5X3dpZGUkZmxhZ0EpICYgZGlhcnlfd2lkZSRmbGFnQT09InRvRXZlbmluZyIsYWZ0X2NvbHNbYWZ0X2NvbHMhPXdoaWNoKGNvbG5hbWVzKGRpYXJ5X3dpZGUpPT0id2hlcmVfYWZ0IildXQ0KZGlhcnlfd2lkZVshaXMubmEoZGlhcnlfd2lkZSRmbGFnQSkgJiBkaWFyeV93aWRlJGZsYWdBPT0idG9FdmVuaW5nIiwNCiAgICAgICAgICAgYWZ0X2NvbHNbYWZ0X2NvbHMhPXdoaWNoKGNvbG5hbWVzKGRpYXJ5X3dpZGUpPT0id2hlcmVfYWZ0IildXSA8LSBOQSAjIHJlbW92aW5nIG1vbS4gZnJvbSB0aG9zZSBjYXNlcw0KDQojIHNhbml0eSBjaGVjaw0KZGlhcnlfd2lkZVshaXMubmEoZGlhcnlfd2lkZSRmbGFnQSksYygiZmxhZ0EiLCJlbmRfYWZ0Iiwic3RhcnRfZXZlIiwiU0JQX2FmdCIsIlNCUF9ldmUiLCJXTDEiLCJFRTEiKV0NCmBgYA0KDQo8YnI+DQoNCiMjIyMgMy42LjIuMi4gRmlsdGVyaW5nIEV2ZW5pbmcNCg0KV2l0aCBmbGFnZ2VkICoqRXZlbmluZyoqIHJlc3BvbnNlcyAoTiA9IDE2KSBnaXZlbiBhZnRlciAwNTowMDoNCg0KLSAgIHdlICoqa2VlcCoqIGFsbCByZXNwb25zZXMgdGhhdCB3ZXJlIHN1Ym1pdHRlZCAqKmJldHdlZW4gMjE6MDAgYW5kIDU6MDAqKiBhbmQgKip1cCB0byBvbmUgaG91ciBhZnRlcioqIHN1Ym1pdHRpbmcgdGhlIEFmdGVybm9vbiBkaWFyeSAoTiA9IDgpLCBieSBhc3N1bWluZyB0aGF0IChhKSBpbiBhIGZldyBjYXNlcyBwYXJ0aWNpcGFudCB3ZW50IHRvIHNsZWVwIGFyb3VuZCAyMTozMCAoTiA9IDcpLCBhbmQgKGIpIHJlc3BvbnNlcyB0aGF0IHRvb2sgMSsgaG91cnMgKE4gPSAxKSB3ZXJlIG9wZW4gZWFybHkgYnkgbWlzdGFrZSBidXQgcmVzcG9uZGVkIGF0IHRoZSByaWdodCB0aW1lIChpLmUuLCBiZWR0aW1lKQ0KDQotICAgd2UgKipyZW1vdmUqKiBhbGwgKiptb21lbnRhcnkgcmVzcG9uc2VzKiogKGkuZS4sIEJQLCBjb25mb3VuZGVycykgdGhhdCB3ZXJlICoqc3VibWl0dGVkIGxlc3MgdGhhbiBvbmUgaG91ciBhZnRlcioqIHN1Ym1pdHRpbmcgdGhlIEFmdGVybm9vbiBkaWFyeSAoTiA9IDIpDQoNCi0gICB3ZSAqKmtlZXAqKiBhbGwgcmVzcG9uc2VzIHN1Ym1pdHRlZCAqKmJldHdlZW4gMjE6MDAgYW5kIDU6MDAqKiB3aXRoICoqbWlzc2luZyBBZnRlcm5vb24qKiByZXNwb25zZXMgKE4gPSAzKQ0KDQotICAgd2UgKipyZW1vdmUqKiBhbGwgcmVzcG9uc2VzIHN1Ym1pdHRlZCAqKmFmdGVyIDA1OjAwKiogd2hlbiBmb2xsb3dlZCBieSB0aGUgKiptb3JuaW5nIHN1cnZleXMqKiB3aXRoIG5vbm1pc3NpbmcgQlAgbWVhc3VyZW1lbnRzIChOID0gMikNCg0KLSAgIHdlICoqcmVjb2RlIG1vbWVudGFyeSBpdGVtcyoqIChpLmUuLCBCUCwgY29uZm91bmRlcnMpIGFzIHRoZXkgd2VyZSByZXNwb25kZWQgKippbiB0aGUgTW9ybmluZyoqLCB3aGlsZSAqKnJlbW92aW5nKiogcmV0cm9zcGVjdGl2ZSBpdGVtcyBmb3IgcmVzcG9uc2VzIHN1Ym1pdHRlZCBsYXRlciB0aGFuIDA1OjAwIHdpdGggKipubyBzdWJzZXF1ZW50IE1vcm5pbmcgcmVzcG9uc2UqKiAoTiA9IDEpDQoNCmBgYCB7cn0NCiMgc2VsZWN0aW5nIGZsYWdnZWQgY2FzZXMgLSBldmVuaW5nIChOID0gMTYpDQpmbGFnRSA8LSBkaWFyeV93aWRlWyFpcy5uYShkaWFyeV93aWRlJHN0YXJ0X2V2ZSkgJiAoYXMuUE9TSVhjdChzdWJzdHIoZGlhcnlfd2lkZSRzdGFydF9ldmUsMTIsMTYpLGZvcm1hdD0iJUg6JU0iKSA8ICMgRSBhZnRlciA1OjAwDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhcy5QT1NJWGN0KCIyMTozMCIsZm9ybWF0PSIlSDolTSIsdHo9IkdNVCIpICYNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFzLlBPU0lYY3Qoc3Vic3RyKGRpYXJ5X3dpZGUkc3RhcnRfZXZlLDEyLDE2KSxmb3JtYXQ9IiVIOiVNIikgPg0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYXMuUE9TSVhjdCgiMDU6MDAiLGZvcm1hdD0iJUg6JU0iLHR6PSJHTVQiKSksXSANCmZsYWdFJHdha2VUaW1lIDwtIHN1YnN0cihmbGFnRSR3YWtlVGltZSwxMiwxNikNCmZsYWdFWyxjKCJJRCIsImVuZF9hZnQiLCJzdGFydF9ldmUiLCJlbmRfZXZlIiwic3RhcnRfbW9yIiwid2FrZVRpbWUiLCJ3b3JrVGltZSIpXSAjIHNob3dpbmcgZmxhZ2dlZCBjYXNlcw0KDQojIG1hcmtpbmcgcmVzcG9uc2VzDQpmbGFnRSRmbGFnIDwtIE5BDQpmbGFnRVshaXMubmEoZmxhZ0Ukc3RhcnRfYWZ0KSAmIGRpZmZ0aW1lKGZsYWdFJGVuZF9ldmUsZmxhZ0UkZW5kX2FmdCx1bml0cz0iaG91cnMiKT49MSAmICMgPjIxOjAwICYgPjFoIGZyb20gQWZ0IChOID0gOCkNCiAgICAgICAgYXMuUE9TSVhjdChzdWJzdHIoZmxhZ0UkZW5kX2V2ZSwxMiwxNiksZm9ybWF0PSIlSDolTSIpID4gYXMuUE9TSVhjdCgiMjE6MDAiLGZvcm1hdD0iJUg6JU0iLHR6PSJHTVQiKSAgfA0KICAgICAgICBhcy5QT1NJWGN0KHN1YnN0cihmbGFnRSRlbmRfZXZlLDEyLDE2KSxmb3JtYXQ9IiVIOiVNIikgPCBhcy5QT1NJWGN0KCIwNTowMCIsZm9ybWF0PSIlSDolTSIsdHo9IkdNVCIpLCJmbGFnIl0gPC0gIm9rMSINCmZsYWdFWyFpcy5uYShmbGFnRSRzdGFydF9hZnQpICYgZGlmZnRpbWUoZmxhZ0UkZW5kX2V2ZSxmbGFnRSRlbmRfYWZ0LHVuaXRzPSJob3VycyIpPDEsImZsYWciXSA8LSAibW9tZW50YXJ5Lk9VVCIgIyA+MWggZnJvbSBBZnQgKDIpDQpmbGFnRVtpcy5uYShmbGFnRSRzdGFydF9hZnQpICYgIyA+MjE6MDAgJiB3aXRob3V0IEFmdCAoTiA9IDMpDQogICAgICAgIGFzLlBPU0lYY3Qoc3Vic3RyKGZsYWdFJGVuZF9ldmUsMTIsMTYpLGZvcm1hdD0iJUg6JU0iKSA+IGFzLlBPU0lYY3QoIjIxOjAwIixmb3JtYXQ9IiVIOiVNIix0ej0iR01UIikgIHwNCiAgICAgICAgYXMuUE9TSVhjdChzdWJzdHIoZmxhZ0UkZW5kX2V2ZSwxMiwxNiksZm9ybWF0PSIlSDolTSIpIDwgYXMuUE9TSVhjdCgiMDU6MDAiLGZvcm1hdD0iJUg6JU0iLHR6PSJHTVQiKSwiZmxhZyJdIDwtIm9rMiINCmZsYWdFWyFpcy5uYShmbGFnRSRTQlBfbW9yKSAmIGlzLm5hKGZsYWdFJGZsYWcpICYgIyA+NTowMCAmIG5vbm1pc3NpbmcgTW9ybmluZyBCUCAoTiA9IDIpDQogICAgICAgIGFzLlBPU0lYY3Qoc3Vic3RyKGZsYWdFJGVuZF9ldmUsMTIsMTYpLGZvcm1hdD0iJUg6JU0iKSA+IGFzLlBPU0lYY3QoIjA1OjAwIixmb3JtYXQ9IiVIOiVNIix0ej0iR01UIikgJg0KICAgICAgICBhcy5QT1NJWGN0KHN1YnN0cihmbGFnRSRlbmRfZXZlLDEyLDE2KSxmb3JtYXQ9IiVIOiVNIikgPCBhcy5QT1NJWGN0KCIyMTowMCIsZm9ybWF0PSIlSDolTSIsdHo9IkdNVCIpLCJmbGFnIl0gPC0iT1VUIg0KZmxhZ0VbaXMubmEoZmxhZ0UkU0JQX21vcikgJiAjID41OjAwICYgbWlzc2luZyBNb3JuaW5nIEJQIChOID0gMSkNCiAgICAgICAgYXMuUE9TSVhjdChzdWJzdHIoZmxhZ0UkZW5kX2V2ZSwxMiwxNiksZm9ybWF0PSIlSDolTSIpID4gYXMuUE9TSVhjdCgiMDU6MDAiLGZvcm1hdD0iJUg6JU0iLHR6PSJHTVQiKSAmDQogICAgICAgIGFzLlBPU0lYY3Qoc3Vic3RyKGZsYWdFJGVuZF9ldmUsMTIsMTYpLGZvcm1hdD0iJUg6JU0iKSA8IGFzLlBPU0lYY3QoIjIxOjAwIixmb3JtYXQ9IiVIOiVNIix0ej0iR01UIiksImZsYWciXSA8LSJ0b01vcm5pbmciDQp0YWJsZShmbGFnRSRmbGFnKSAjIHNob3dpbmcgTm8uIG9mIGNhc2VzDQoNCiMgZmlsdGVyaW5nIHJlc3BvbnNlcw0KZGlhcnlfd2lkZSRmbGFnRSA8LSBOQSAjIGZsYWdnaW5nIGFsbCBmbGFnTSBjYXNlcyBpbiB0aGUgZGlhcnlfd2lkZSBkYXRhc2V0DQpldmVfY29scy5mdWxsIDwtIHdoaWNoKGNvbG5hbWVzKGRpYXJ5X3dpZGUpPT0ic3RhcnRfZXZlIik6d2hpY2goY29sbmFtZXMoZGlhcnlfd2lkZSk9PSJ3b3JrSG91cnMiKSAjIGV2ZW5pbmcgZnVsbCBjb2x1bW5zDQptb3JfY29scyA8LSB3aGljaChjb2xuYW1lcyhkaWFyeV93aWRlKT09IlNCUF9tb3IiKTp3aGljaChjb2xuYW1lcyhkaWFyeV93aWRlKT09Im1lYWxfbW9yIikgIyBtb3JuaW5nIG1vbWVudGFyeSBjb2x1bW5zDQpkaWFyeV93aWRlW2RpYXJ5X3dpZGUkSURkYXklaW4lbGV2ZWxzKGFzLmZhY3RvcihmbGFnRSRJRGRheSkpLCJmbGFnRSJdIDwtIGZsYWdFWywiZmxhZyJdDQpkaWFyeV93aWRlWyFpcy5uYShkaWFyeV93aWRlJGZsYWdFKSAmIGRpYXJ5X3dpZGUkZmxhZ0U9PSJtb21lbnRhcnkuT1VUIixldmVfY29sc10gPC0gTkEgIyByZW1vdmluZyBtb21lbnRhcnkgRXZlbmluZyAoTiA9IDIpDQpkaWFyeV93aWRlWyFpcy5uYShkaWFyeV93aWRlJGZsYWdFKSAmIGRpYXJ5X3dpZGUkZmxhZ0U9PSJPVVQiLGV2ZV9jb2xzLmZ1bGxdIDwtIE5BICMgcmVtb3ZpbmcgYWxsIEV2ZW5pbmcgKE4gPSAyKQ0KZGlhcnlfd2lkZVshaXMubmEoZGlhcnlfd2lkZSRmbGFnRSkgJiBkaWFyeV93aWRlJGZsYWdFPT0iT1VUIiwiZXZlIl0gPC0gMCANCmRpYXJ5X3dpZGVbIWlzLm5hKGRpYXJ5X3dpZGUkZmxhZ0UpICYgZGlhcnlfd2lkZSRmbGFnRT09InRvTW9ybmluZyIsDQogICAgICAgICAgIG1vcl9jb2xzW21vcl9jb2xzIT13aGljaChjb2xuYW1lcyhkaWFyeV93aWRlKT09IndoZXJlX21vciIpXV0gPC0gIyBtb21lbnRhcnkgdmFsdWVzIHRvIE1vcm5pbmcgKE4gPSAxKQ0KICBkaWFyeV93aWRlWyFpcy5uYShkaWFyeV93aWRlJGZsYWdFKSAmIGRpYXJ5X3dpZGUkZmxhZ0U9PSJ0b01vcm5pbmciLGV2ZV9jb2xzXQ0KZGlhcnlfd2lkZVshaXMubmEoZGlhcnlfd2lkZSRmbGFnRSkgJiBkaWFyeV93aWRlJGZsYWdFPT0idG9Nb3JuaW5nIixldmVfY29sc10gPC0gTkEgIyByZW1vdmluZyBtb20uIGZyb20gdGhvc2UgY2FzZXMNCg0KIyBzYW5pdHkgY2hlY2sNCmRpYXJ5X3dpZGVbIWlzLm5hKGRpYXJ5X3dpZGUkZmxhZ0UpLGMoImZsYWdFIiwiZW5kX2FmdCIsImVuZF9ldmUiLCJlbmRfbW9yIiwiU0JQX2V2ZSIsIlNCUF9tb3IiLCJFRTEiLCJPQzEiKV0NCmBgYA0KDQo8YnI+DQoNCiMjIyMgMy42LjIuMy4gRmlsdGVyaW5nIE1vcm5pbmcNCg0KV2l0aCBmbGFnZ2VkICoqTW9ybmluZyoqIHJlc3BvbnNlcyAoTiA9IDIzKSBnaXZlbiBhZnRlciAwNTowMDoNCg0KLSAgIHdlICoqa2VlcCoqIGFsbCByZXNwb25zZXMgc3RhcnRlZCBvbiAqKlNhdHVyZGF5cyBiZWZvcmUgMTU6MDAqKiAoTiA9IDYpDQoNCi0gICB3ZSAqKmtlZXAqKiBhbGwgcmVzcG9uc2VzIHN1Ym1pdHRlZCBvbiBUdWVzZGF5LUZyaWRheSAqKmJlZm9yZSAxNTowMCoqIGFuZCAqKnVwIHRvIHRocmVlIGhvdXJzIGJlZm9yZSoqIHN1Ym1pdHRpbmcgdGhlIEFmdGVybm9vbiBkaWFyeSAoTiA9IDExKQ0KDQotICAgd2UgKipyZW1vdmUqKiBhbGwgcmVzcG9uc2VzIHN1Ym1pdHRlZCAqKmFmdGVyIDE1OjAwKiogKE4gPSA0KQ0KDQotICAgd2UgKipyZW1vdmUgbW9tZW50YXJ5IGl0ZW1zKiogZnJvbSByZXNwb25zZXMgc3VibWl0dGVkICoqbGVzcyB0aGFuIHRocmVlIGhvdXJzIGJlZm9yZSoqIHN1Ym1pdHRpbmcgdGhlIEFmdGVybm9vbiBkaWFyeSB3aXRoIG5vbm1pc3NpbmcgQlAgdmFsdWVzIChOID0gMSkNCg0KYGBgIHtyfQ0KIyBzZWxlY3RpbmcgZmxhZ2dlZCBjYXNlcyAtIG1vcm5pbmcgKE4gPSAyMikNCmZsYWdNIDwtIGRpYXJ5X3dpZGVbIWlzLm5hKGRpYXJ5X3dpZGUkc3RhcnRfbW9yKSAmIChhcy5QT1NJWGN0KHN1YnN0cihkaWFyeV93aWRlJHN0YXJ0X21vciwxMiwxNiksZm9ybWF0PSIlSDolTSIpIDwgIyBNIGFmdGVyIDEyOjAwDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhcy5QT1NJWGN0KCIyMzo1OSIsZm9ybWF0PSIlSDolTSIsdHo9IkdNVCIpICYgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhcy5QT1NJWGN0KHN1YnN0cihkaWFyeV93aWRlJHN0YXJ0X21vciwxMiwxNiksZm9ybWF0PSIlSDolTSIpID4NCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFzLlBPU0lYY3QoIjEyOjAwIixmb3JtYXQ9IiVIOiVNIix0ej0iR01UIikpLF0NCg0KIyBhZGRpbmcgbmV4dCBkYXkgc3RhcnRfYWZ0IChzdGFydF9hZnQubmQpIHdoZW4gbm9ubWlzc2luZw0KZmxhZ00kc3RhcnRfYWZ0Lm5kIDwtIGFzLlBPU0lYY3QoTkEpDQpmbGFnTTEgPC0gYXMuZGF0YS5mcmFtZShtYXRyaXgobnJvdz0wLG5jb2w9bmNvbChmbGFnTSkpKQ0KZm9yKGkgaW4gMTpucm93KGZsYWdNKSl7IGZsYWdNMSA8LSByYmluZChmbGFnTTEsZmxhZ01baSxdKQ0KICBpZihucm93KGRpYXJ5X3dpZGVbZGlhcnlfd2lkZSRJRD09ZmxhZ01baSwiSUQiXSAmIGRpYXJ5X3dpZGUkZGF5PT1mbGFnTVtpLCJkYXkiXSsxLF0pPjApeyANCiAgICBmbGFnTTFbbnJvdyhmbGFnTTEpLCJzdGFydF9hZnQubmQiXTwtZGlhcnlfd2lkZVtkaWFyeV93aWRlJElEPT1mbGFnTVtpLCJJRCJdJmRpYXJ5X3dpZGUkZGF5PT1mbGFnTVtpLCJkYXkiXSsxLCJzdGFydF9hZnQiXX19DQoNCiMgc2hvd2luZyBjYXNlcw0KZmxhZ00xWyxjKCJJRCIsImRheSIsIndha2VUaW1lIiwic3RhcnRfbW9yIiwiZW5kX21vciIsInN0YXJ0X2FmdC5uZCIpXQ0KYGBgDQoNCjxicj4NCg0KYGBgIHtyfQ0KIyBtYXJraW5nIHJlc3BvbnNlcw0KZmxhZ00xJGZsYWcgPC0gTkENCmZsYWdNMVtmbGFnTTEkZGF5JWluJWMoNSwxMSkgJiAjIFNhdHVyZGF5cyB3aXRoIHN0YXJ0IDwxNTowMCAoTiA9IDYpDQogICAgICAgYXMuUE9TSVhjdChzdWJzdHIoZmxhZ00xJHN0YXJ0X21vciwxMiwxNiksZm9ybWF0PSIlSDolTSIpIDwgYXMuUE9TSVhjdCgiMTU6MDAiLGZvcm1hdD0iJUg6JU0iLHR6PSJHTVQiKSwiZmxhZyJdIDwtICJvazEiDQpmbGFnTTFbIWZsYWdNMSRkYXklaW4lYyg1LDExKSAmIGRpZmZ0aW1lKGZsYWdNMSRzdGFydF9hZnQubmQsZmxhZ00xJGVuZF9tb3IsdW5pdHM9ImhvdXJzIik+MyAmICMgVHVlLUZyeSA8MTU6MDAgJiA+M2ggZnJvbSBBZnQgKDExKQ0KICAgICAgIGFzLlBPU0lYY3Qoc3Vic3RyKGZsYWdNMSRzdGFydF9tb3IsMTIsMTYpLGZvcm1hdD0iJUg6JU0iKSA8IGFzLlBPU0lYY3QoIjE1OjAwIixmb3JtYXQ9IiVIOiVNIix0ej0iR01UIiksImZsYWciXSA8LSAib2syIg0KZmxhZ00xW2FzLlBPU0lYY3Qoc3Vic3RyKGZsYWdNMSRzdGFydF9tb3IsMTIsMTYpLGZvcm1hdD0iJUg6JU0iKSA+ICMgc3VibWl0dGVkID4xNTowMCAoTiA9IDQpDQogICAgICAgICBhcy5QT1NJWGN0KCIxNTowMCIsZm9ybWF0PSIlSDolTSIsdHo9IkdNVCIpLCJmbGFnIl0gPC0gIk9VVCINCmZsYWdNMVtpcy5uYShmbGFnTTEkZmxhZyksImZsYWciXSA8LSAibW9tZW50YXJ5Lk9VVCIgIyBzdWJtaXR0ZWQgPDNoIGJlZm9yZSBmb2xsb3dpbmcgQWZ0ZXJub29uIChOID0gMSkNCnRhYmxlKGZsYWdNMSRmbGFnKSAjIHNob3dpbmcgTm8uIG9mIGNhc2VzDQpgYGANCjxicj4NCg0KYGBgIHtyfQ0KIyBmaWx0ZXJpbmcgcmVzcG9uc2VzDQpkaWFyeV93aWRlJGZsYWdNIDwtIE5BICMgZmxhZ2dpbmcgYWxsIGZsYWdNIGNhc2VzIGluIHRoZSBkaWFyeV93aWRlIGRhdGFzZXQNCm1vcl9jb2xzLmZ1bGwgPC0gd2hpY2goY29sbmFtZXMoZGlhcnlfd2lkZSk9PSJzdGFydF9tb3IiKTp3aGljaChjb2xuYW1lcyhkaWFyeV93aWRlKT09IkFXTDMiKSAjIG1vcm5pbmcgZnVsbCBjb2x1bW5zDQpkaWFyeV93aWRlW2RpYXJ5X3dpZGUkSURkYXklaW4lbGV2ZWxzKGFzLmZhY3RvcihmbGFnTTEkSURkYXkpKSwiZmxhZ00iXSA8LSBmbGFnTTFbLCJmbGFnIl0NCmRpYXJ5X3dpZGVbIWlzLm5hKGRpYXJ5X3dpZGUkZmxhZ00pICYgZGlhcnlfd2lkZSRmbGFnTT09Im1vbWVudGFyeS5PVVQiLG1vcl9jb2xzXSA8LSBOQSAjIHJlbW92aW5nIG1vbWVudGFyeSBNb3JuaW5nIChOID0gMSkNCmRpYXJ5X3dpZGVbIWlzLm5hKGRpYXJ5X3dpZGUkZmxhZ00pICYgZGlhcnlfd2lkZSRmbGFnTT09Ik9VVCIsbW9yX2NvbHMuZnVsbF0gPC0gTkEgIyByZW1vdmluZyBhbGwgTW9ybmluZyAoTiA9IDQpDQpkaWFyeV93aWRlWyFpcy5uYShkaWFyeV93aWRlJGZsYWdNKSAmIGRpYXJ5X3dpZGUkZmxhZ009PSJPVVQiLCJtb3IiXSA8LSAwDQoNCiMgc2FuaXR5IGNoZWNrDQpkaWFyeV93aWRlWyFpcy5uYShkaWFyeV93aWRlJGZsYWdNKSxjKCJmbGFnTSIsInN0YXJ0X21vciIsImVuZF9tb3IiLCJTQlBfbW9yIiwiT0MxIildDQpgYGANCg0KPGJyPg0KDQojIyMjIDMuNi4yLjQuIFN1bW1hcnkNCg0KSW4gc3VtbWFyeSwgd2UgcHJvY2Vzc2VkIGBkaWFyeV93aWRlYCByZXNwb25zZXMgYnkgcmVtb3ZpbmcgdGhvc2Ugb2J0YWluZWQgb3V0IG9mIHRoZSBzY2hlZHVsZWQgdGltZXMgYW5kIGJ5IHJlY29kaW5nIHRpbWUgcG9pbnRzIGJhc2VkIG9uIHRoZSBob3VyIG9mIHRoZSBkYXkuIFNwZWNpZmljYWxseSwgd2UgKipyZW1vdmVkIDYgY2FzZXMqKiAoMiBNb3JuaW5nLCA0IEV2ZW5pbmcpIHdpdGggcmVzcG9uc2UgdGltZXMgZXh0cmVtZWx5IG91dCBvZiBib3VuZHMsIHdlICoqcmVtb3ZlZCBtb21lbnRhcnkgaXRlbSByZXNwb25zZXMgZnJvbSA5IGNhc2VzKiogKDYgQWZ0ZXJub29uLCAyIEV2ZW5pbmcsIDEgTW9ybmluZykgd2l0aCBCUCBtZWFzdXJlbWVudHMgdG9vIGNsb3NlIHRvIHRoZSBwcmVjZWRpbmcgb3IgdGhlIGZvbGxvd2luZyBvbmVzLCBhbmQgd2UgKipyZWNvZGVkIDMgY2FzZXMqKiAoMiBBZnRlcm5vb24sIDEgRXZlbmluZykgYnkgYXNzaWduaW5nIG1vbWVudGFyeSBpdGVtIHJlc3BvbnNlcyB0byB0aGUgZm9sbG93aW5nIGRpYXJ5LiBIZXJlLCB3ZSByZS1pbnNwZWN0IHRoZSBkaXN0cmlidXRpb24gb2YgcmVzcG9uc2UgdGltZXMgaW4gdGhlIHByb2Nlc3NlZCBkYXRhLg0KDQpgYGAge3IgZmlnLndpZHRoPTEyLGZpZy5oZWlnaHQ9M30NCiMgY3JlYXRpbmcgbmV3IHZhcmlhYmxlIHN1bW1hcml6aW5nIGZsYWdnZWQgY2FzZXMNCmRpYXJ5X3dpZGUkZmxhZ1RpbWUgPC0gRkFMU0UNCmRpYXJ5X3dpZGVbKCFpcy5uYShkaWFyeV93aWRlJGZsYWdBKSAmIGRpYXJ5X3dpZGUkZmxhZ0EhPSJvayIpIHwNCiAgICAgICAgICAgICAoIWlzLm5hKGRpYXJ5X3dpZGUkZmxhZ0UpICYgZGlhcnlfd2lkZSRmbGFnRSE9Im9rMSIgJiBkaWFyeV93aWRlJGZsYWdFIT0ib2syIikgfA0KICAgICAgICAgICAgICghaXMubmEoZGlhcnlfd2lkZSRmbGFnTSkgJiBkaWFyeV93aWRlJGZsYWdNIT0ib2sxIiAmIGRpYXJ5X3dpZGUkZmxhZ00hPSJvazIiKSwiZmxhZ1RpbWUiXSA8LSBUUlVFDQpkaWFyeV93aWRlJGZsYWdBIDwtIGRpYXJ5X3dpZGUkZmxhZ0UgPC0gZGlhcnlfd2lkZSRmbGFnTSA8LSBOVUxMICMgcmVtb3ZpbmcgaW5kaXZpZHVhbCBmbGFnIHZhcmlhYmxlcw0KDQojIHBsb3R0aW5nDQpwYXIobWZyb3c9YygxLDMpKQ0KaGlzdChhcy5QT1NJWGN0KHN1YnN0cihkaWFyeV93aWRlWyFpcy5uYShkaWFyeV93aWRlJFNCUF9hZnQpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJzdGFydF9hZnQiXSwxMiwxOSksZm9ybWF0PSIlSDolTTolUyIpLGJyZWFrcz0iaG91cnMiLG1haW49IkFmdCIseGxhYj0iIikNCmhpc3QoYXMuUE9TSVhjdChzdWJzdHIoZGlhcnlfd2lkZVshaXMubmEoZGlhcnlfd2lkZSRTQlBfZXZlKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAic3RhcnRfZXZlIl0sMTIsMTkpLGZvcm1hdD0iJUg6JU06JVMiKSxicmVha3M9ImhvdXJzIixtYWluPSJFdmUiLHhsYWI9IiIpDQpoaXN0KGFzLlBPU0lYY3Qoc3Vic3RyKGRpYXJ5X3dpZGVbIWlzLm5hKGRpYXJ5X3dpZGUkU0JQX21vciksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgInN0YXJ0X21vciJdLDEyLDE5KSxmb3JtYXQ9IiVIOiVNOiVTIiksYnJlYWtzPSJob3VycyIsbWFpbj0iTW9yIix4bGFiPSIiKQ0KYGBgDQoNCjxicj4NCg0KIyMjIDMuNi4zLiBXb3JrIGhvdXJzDQoNCkhlcmUsIHdlIGluc3BlY3QgdGhlIGRpc3RyaWJ1dGlvbiBvZiBgd29ya0hvdXJzYCBhbmQgYGxhdGVXb3JrSG91cnNgIGZyb20gdGhlIGBkaWFyeV93aWRlYCBkYXRhc2V0LCBhbmQgdGhhdCBvZiBgd2Vla0hvdXJzYCBmcm9tIHRoZSBgcHJlbHFzYCBkYXRhc2V0LCBsb29raW5nIGZvciBjYXNlcyBvZiB1bnJlYWxpc3RpYyBudW1iZXJzIG9mIHdvcmtpbmcgaG91cnMuIFdlIGFsc28gY29tcHV0ZSB0aGUgYHdvcmtIb3Vyc190b3RhbGAgdmFyaWFibGUgYXMgdGhlIHN1bSBvZiBgd29ya2hvdXJzYCBhbmQgYGxhdGVXb3JrSG91cnNgLg0KDQpIb3dldmVyLCB3ZSBjYW4gc2VlIHRoYXQgdGhlIGxhdHRlciB2YXJpYWJsZSB3b3VsZCBiZSBpbmFjY3VyYXRlIGFzIGl0IG1pZ2h0IGhhdmUgdmFsdWUgPiAyNGggaW4gc29tZSBjYXNlcywgaW1wbHlpbmcgdGhhdCBhIG51bWJlciBvZiBwYXJ0aWNpcGFudHMgZGlkIG5vdCBjb25zaWRlciBgd29ya2hvdXJzYCBhbmQgYGxhdGVXb3JraG91cnNgIGFzIG11dHVhbGx5IGV4Y2x1c2l2ZS4gVGh1cywgd2UgcmVtb3ZlIGl0IGZyb20gdGhlIGRhdGFzZXQuDQoNCk1vcmVvdmVyLCB3aGVyZWFzIGB3b3JraG91cnNgIHNlZW1zIHF1aXRlIHJlYWxpc3RpYyAocmFuZ2luZyBmcm9tIDFoIHRvIDE1aCksICoqYGxhdGVXb3JrSG91cnNgIGxvb2tzIGluYWNjdXJhdGVseSByZXNwb25kZWQqKiBieSBhIG51bWJlciBvZiBwYXJ0aWNpcGFudHMgdGhhdCByZXBvcnRlZCB1cCB0byAxMC0yMCBob3VycyBvZiB3b3JrIGFmdGVyIHRoZSAnb3JkaW5hcnknIHdvcmsgc2NoZWR1bGUuIFRodXMsIHdlICoqZHljaG90b21pemUqKiBgbGF0ZVdvcmtIb3Vyc2AgYXMgYEZBTFNFYCAoYGxhdGVXb3JrSG91cnMgPSAwYCkgb3IgYFRSVUVgIChgbGF0ZVdvcmtIb3VycyA+IDBgKQ0KYGBgIHtyIGZpZy53aWR0aD0xMixmaWcuaGVpZ2h0PTN9DQojIGNvbXB1dGluZyB3b3JrSG91cnNfdG90YWwNCmRpYXJ5X3dpZGUkd29ya0hvdXJzX3RvdGFsIDwtIGRpYXJ5X3dpZGUkd29ya0hvdXJzICsgZGlhcnlfd2lkZSRsYXRlV29ya0hvdXJzDQoNCiMgcGxvdHRpbmcNCnBhcihtZnJvdz1jKDEsNCkpOyBoaXN0KGRpYXJ5X3dpZGUkd29ya0hvdXJzLGJyZWFrcz0zMCk7IGhpc3QoZGlhcnlfd2lkZSRsYXRlV29ya0hvdXJzLGJyZWFrcz0zMCkNCmhpc3QoZGlhcnlfd2lkZSR3b3JrSG91cnNfdG90YWwsYnJlYWtzPTMwKTsgaGlzdChwcmVscXMkd2Vla0hvdXJzLGJyZWFrcz0zMCkNCg0KIyByZW1vdmluZyB3b3JrSG91cnNfdG90YWwNCmRpYXJ5X3dpZGUkd29ya0hvdXJzX3RvdGFsIDwtIE5VTEwNCg0KIyBjYXNlcyBvZiBsYXRlV29ya0hvdXJzID4gMTANCmRpYXJ5X3dpZGVbIWlzLm5hKGRpYXJ5X3dpZGUkbGF0ZVdvcmtIb3VycykgJiBkaWFyeV93aWRlJGxhdGVXb3JrSG91cnM+MTAsYygiSUQiLCJkYXkiLCJ3b3JrSG91cnMiLCJsYXRlV29ya0hvdXJzIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiU1ExIiwid2FrZVRpbWUiLCJ3b3JrVGltZSIsIndlZWtIb3VycyIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIndlZWtIb3Vyc19yZW1vdGUiLCJqb2IiKV0NCmBgYA0KDQo8YnI+DQoNCmBgYCB7cn0NCiMgZHljaG90b21pemluZyBsYXRlV29ya0hvdXJzDQpkaWFyeV93aWRlJGxhdGVXb3JrSG91cnMxIDwtIE5BDQpkaWFyeV93aWRlWyFpcy5uYShkaWFyeV93aWRlJGxhdGVXb3JrSG91cnMpICYgZGlhcnlfd2lkZSRsYXRlV29ya0hvdXJzPT0wLCJsYXRlV29ya0hvdXJzMSJdIDwtIEZBTFNFDQpkaWFyeV93aWRlWyFpcy5uYShkaWFyeV93aWRlJGxhdGVXb3JrSG91cnMpICYgZGlhcnlfd2lkZSRsYXRlV29ya0hvdXJzPjAsImxhdGVXb3JrSG91cnMxIl0gPC0gVFJVRQ0KZGlhcnlfd2lkZSRsYXRlV29ya0hvdXJzIDwtIGRpYXJ5X3dpZGUkbGF0ZVdvcmtIb3VyczENCmRpYXJ5X3dpZGUkbGF0ZVdvcmtIb3VyczEgPC0gTlVMTA0Kc3VtbWFyeShkaWFyeV93aWRlJGxhdGVXb3JrSG91cnMpICMgc3VtbWFyaXppbmcgY2FzZXMgIEZBTFNFPTcwMiwgVFJVRT0yNDUsIE5BPTE5Nw0KYGBgDQoNCjxicj4NCg0KIyMjIDMuNi40LiBCUCBjb25mb3VuZGVycw0KDQpGaW5hbGx5LCB3ZSBvYnNlcnZlIGEgbnVtYmVyIG9mIGNhc2VzIChOID0gMi03KSB3aXRoIG5vbm1pc3NpbmcgcmVzcG9uc2UgdG8gdGhlIGNvcmUgYGRpYXJ5YCBpdGVtcyAoZS5nLiwgd29ya2Fob2xpc20sIGV4aGF1c3Rpb24sIGFuZCBzbGVlcCBpdGVtcykgYnV0IG1pc3NpbmcgcmVzcG9uc2UgdG8gdGhlIGJsb29kIHByZXNzdXJlIGNvbmZvdW5kZXJzLiBIZXJlLCB3ZSBzZXQgdGhlIGNvbmZvdW5kZXJzID0gYEZBTFNFYCBmb3IgYWxsIG9mIHRoZXNlIGNhc2VzLg0KYGBgIHtyfQ0KIyBhZnRlcm5vb24NCmNhdChucm93KGRpYXJ5X3dpZGVbIWlzLm5hKGRpYXJ5X3dpZGUkV0hMU00xKSAmIGlzLm5hKGRpYXJ5X3dpZGUkY29uZm91bmRlcnNfYWZ0KSxdKSwNCiAgICAiY2FzZXMgd2l0aCBtaXNzaW5nIGNvbmZvdW5kZXJzX2FmdCBidXQgbm9ubWlzc2luZyBXSExTTTEgaXRlbSBzY29yZSIpDQpkaWFyeV93aWRlWyFpcy5uYShkaWFyeV93aWRlJFdITFNNMSkgJiBpcy5uYShkaWFyeV93aWRlJGNvbmZvdW5kZXJzX2FmdCksImNvbmZvdW5kZXJzX2FmdCJdIDwtIEZBTFNFDQoNCiMgZXZlbmluZw0KY2F0KG5yb3coZGlhcnlfd2lkZVshaXMubmEoZGlhcnlfd2lkZSRFRTEpICYgaXMubmEoZGlhcnlfd2lkZSRjb25mb3VuZGVyc19ldmUpLF0pLA0KICAgICJjYXNlcyB3aXRoIG1pc3NpbmcgY29uZm91bmRlcnNfZXZlIGJ1dCBub25taXNzaW5nIEVWRTEgaXRlbSBzY29yZSIpDQpkaWFyeV93aWRlWyFpcy5uYShkaWFyeV93aWRlJEVFMSkgJiBpcy5uYShkaWFyeV93aWRlJGNvbmZvdW5kZXJzX2V2ZSksImNvbmZvdW5kZXJzX2V2ZSJdIDwtIEZBTFNFDQoNCiMgc2FtZSB0aGluZyBmb3IgZmxhZ0JQIHZhcmlhYmxlcw0KZGlhcnlfd2lkZVshaXMubmEoZGlhcnlfd2lkZSRXSExTTV8xKSAmIGlzLm5hKGRpYXJ5JGZsYWdCUF9hZnQpLCJmbGFnQlBfYWZ0Il0gPC0gRkFMU0UNCmRpYXJ5X3dpZGVbIWlzLm5hKGRpYXJ5X3dpZGUkRUVfMSkgJiBpcy5uYShkaWFyeSRmbGFnQlBfZXZlKSwiZmxhZ0JQX2V2ZSJdIDwtIEZBTFNFDQpgYGANCg0KPGJyPg0KDQojIDQuIERhdGEgc2VsZWN0aW9uDQoNCkhlcmUsIHdlIHNlbGVjdCB0aGUgb2JzZXJ2YXRpb25zLCBwYXJ0aWNpcGFudHMsIGFuZCB2YXJpYWJsZXMgdG8gYmUgY29uc2lkZXJlZCBmb3IgdGhlIHN1YnNlcXVlbnQgYW5hbHlzZXMuIFRoYXQgaXMsIHdlIGRpc2NhcmQgcGlsb3QgcGFydGljaXBhbnRzIGFuZCBhbGwgcmVsYXRlZCBvYnNlcnZhdGlvbnMsIGFuZCB3ZSByZW1vdmUgdGhlIHZhcmlhYmxlcyBub3QgY29uc2lkZXJlZCBpbiB0aGUgcHJlc2VudCB3b3JrLg0KDQojIyA0LjEuIFZhcmlhYmxlIHNlbGVjdGlvbg0KDQpIZXJlLCB3ZSBzdWJzZXQgdGhlIGRhdGEgYnkgc2VsZWN0aW5nIGFuZCBzb3J0aW5nIHRoZSB2YXJpYWJsZXMgdG8gYmUgY29uc2lkZXJlZCBpbiB0aGUgZm9sbG93aW5nIGFuYWx5c2VzLCB3aGVyZWFzIHVudXNlZCB2YXJpYWJsZXMgYXJlIG5vdCBpbmNsdWRlZC4NCmBgYCB7cn0NCiMgZGlhcnkgZGF0YSAgICAgICAgICAgICAgICAjIGNhc2UgaWRlbnRpZmljYXRpb24NCmRpYXJ5X3dpZGUgPC0gZGlhcnlfd2lkZVssYygiSUQiLCJkYXkiLA0KDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgIyBjb21wbGlhbmNlDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgImFmdCIsImV2ZSIsIm1vciIsDQoNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAjIGRhdGEgcXVhbGl0eQ0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICJmbGFnVGltZSIsImZsYWdCUF9hZnQiLCJmbGFnQlBfZXZlIiwiY2FyZWxlc3MiLA0KDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgIyBhZnRlcm5vb24gZGlhcnkNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAic3RhcnRfYWZ0IiwiZW5kX2FmdCIsICMgc3RhcnRpbmcgJiBlbmRpbmcgZGF0ZSAmIHRpbWUNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAiZGF5T2ZmX2FmdCIsICMgdG9vayBhIGRheSBvZmYgKG1pc3NpbmcgcmVzcG9uc2VzKQ0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICJTQlBfYWZ0IiwiREJQX2FmdCIsICMgYmxvb2QgcHJlc3N1cmUNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAid2hlcmVfYWZ0IiwiY29uZm91bmRlcnNfYWZ0IiwiY29mZmVlX2FmdCIsInNtb2tlX2FmdCIsInNwb3J0X2FmdCIsIm1lYWxfYWZ0IiwgIyBjb25mb3VuZGVycw0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBhc3RlKCJXSExTTSIsMTo2LHNlcD0iIiksICMgc3RhdGUgd29ya2Fob2xpc20NCg0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICMgZXZlbmluZyBkaWFyeQ0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICJzdGFydF9ldmUiLCJlbmRfZXZlIiwgIyBzdGFydGluZyAmIGVuZGluZyBkYXRlICYgdGltZQ0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICJkYXlPZmZfZXZlIiwgIyB0b29rIGEgZGF5IG9mZiAobWlzc2luZyByZXNwb25zZXMpDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgIlNCUF9ldmUiLCJEQlBfZXZlIiwgIyBibG9vZCBwcmVzc3VyZQ0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICJjb25mb3VuZGVyc19ldmUiLCJjb2ZmZWVfZXZlIiwic21va2VfZXZlIiwic3BvcnRfZXZlIiwibWVhbF9ldmUiLCAjIGNvbmZvdW5kZXJzDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgInRlbGVXb3JrIiwid29ya0hvdXJzIiwiZGFpbHlIYXNzbGVzX2V2ZSIsICMgZnVydGhlciBjb25mb3VuZGVycy9jb3ZhcmlhdGVzDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgcGFzdGUoIkVFIiwxOjQsc2VwPSIiKSwgIyBlbW90aW9uYWwgZXhoYXVzdGlvbg0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBhc3RlMCgiUi5kZXQiLDE6MyksICMgcHN5Y2hvbG9naWNhbCBkZXRhY2htZW50DQoNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAjIG1vcm5pbmcgZGlhcnkNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAic3RhcnRfbW9yIiwiZW5kX21vciIsICMgc3RhcnRpbmcgJiBlbmRpbmcgZGF0ZSAmIHRpbWUNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAiZGF5T2ZmeWVzdGVyZGF5IiwgIyB0b29rIGEgZGF5IG9mZiB5ZXN0ZXJkYXkgb3IgdG9kYXkgKG1pc3NpbmcgcmVzcG9uc2VzKQ0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICJsYXRlV29ya0hvdXJzIiwid2FrZVRpbWUiLCJoaEZyb21Bd2FrZSIsICMgY29uZm91bmRlcnMvY292YXJpYXRlcw0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBhc3RlKCJTUSIsMTo0LHNlcD0iIiksICMgc2xlZXAgcXVhbGl0eQ0KDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgIyBkZW1vZ3JhcGhpY3MgZnJvbSB0aGUgcHJlcWxzIGRhdGFzZXQNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb2xuYW1lcyhkaWFyeV93aWRlKVt3aGljaChjb2xuYW1lcyhkaWFyeV93aWRlKT09ImdlbmRlciIpOndoaWNoKGNvbG5hbWVzKGRpYXJ5X3dpZGUpPT0id2Vla0hvdXJzIildLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICMgUmV0cm9zcGVjdGl2ZSB3b3JrYWhvbGlzbSBpdGVtcyBmcm9tIHRoZSBwcmVscXMgZGF0YXNldA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBhc3RlMCgiZHV3YXMiLDE6MTApKV0NCmBgYA0KDQo8YnI+DQoNCiMjIDQuMi4gQ2FzZSBzZWxlY3Rpb24NCg0KSGVyZSwgd2Ugc3Vic2V0IHRoZSBkYXRhIGJ5IHNlbGVjdGluZyB0aGUgY2FzZXMgdG8gYmUgY29uc2lkZXJlZCBpbiB0aGUgZm9sbG93aW5nIGFuYWx5c2VzLiBUaGF0IGlzLCB3ZSAqKmZpbHRlciAxMiBwaWxvdCBwYXJ0aWNpcGFudHMqKiB0aGF0IHRvb2sgcGFydCBpbiB0aGUgcGlsb3QgdHJpYWwgb2YgdGhlIHN0dWR5IChpLmUuLCBiZWZvcmUgMjAyMS0wNC0wNSkuDQpgYGAge3J9DQojIHNlbGVjdGluZyBwaWxvdCBwYXJ0aWNpcGFudHMgKDEyKQ0KKHBpbG90cyA8LSBsZXZlbHMoYXMuZmFjdG9yKGFzLmNoYXJhY3RlcihwcmVscXNbcHJlbHFzJHN0YXJ0PGFzLlBPU0lYY3QoIjIwMjEtMDQtMDUiKSwiSUQiXSkpKSkNCg0KIyBmaWx0ZXJpbmcgMTIgcGlsb3QgcGFydGljaXBhbnRzIGZyb20gZGlhcnkgZGF0YQ0KbWVtb3J5IDwtIGRpYXJ5DQptZW1vcnkyIDwtIGRpYXJ5X3dpZGUNCmRpYXJ5IDwtIGRpYXJ5WyEoZGlhcnkkSUQlaW4lcGlsb3RzKSxdDQpkaWFyeV93aWRlIDwtIGRpYXJ5X3dpZGVbIShkaWFyeV93aWRlJElEJWluJXBpbG90cyksXQ0KZGlhcnkkSUQgPC0gYXMuZmFjdG9yKGFzLmNoYXJhY3RlcihkaWFyeSRJRCkpDQpkaWFyeV93aWRlJElEIDwtIGFzLmZhY3Rvcihhcy5jaGFyYWN0ZXIoZGlhcnlfd2lkZSRJRCkpDQpjYXQoIlJlbW92ZWQiLG5sZXZlbHMobWVtb3J5JElEKS1ubGV2ZWxzKGRpYXJ5JElEKSwicGFydGljaXBhbnRzLCIsDQogICAgbnJvdyhtZW1vcnkyKS1ucm93KGRpYXJ5X3dpZGUpLCJkYXlzLCIsbnJvdyhtZW1vcnkpLW5yb3coZGlhcnkpLCJvYnNlcnZhdGlvbnMiKQ0KY2F0KCJkaWFyeV93aWRlOiB0b3RhbCBOby4gb2YgcmVzcG9uc2VzID0iLG5yb3coZGlhcnlfd2lkZSksImZyb20iLG5sZXZlbHMoZGlhcnlfd2lkZSRJRCksInBhcnRpY2lwYW50cyIpDQpgYGANCg0KPGJyPg0KDQojIDUuIERhdGEgZGljdGlvbmFyeQ0KDQpIZXJlLCB3ZSBwcm92aWRlIGEgZGVmaW5pdGlvbiBmb3IgZWFjaCB2YXJpYWJsZSBpbiB0aGUgcHJvY2Vzc2VkIGBkaWFyeV93aWRlYCBkYXRhc2V0cy4NCg0KYGBgIHtyfQ0Kc3RyKGRpYXJ5X3dpZGUpDQpgYGANCg0KPGJyPg0KDQoqKklkZW50aWZpY2F0aW9uKioNCg0KLSAgIGBJRGAgPSBwYXJ0aWNpcGFudCdzIGlkZW50aWZpY2F0aW9uIGNvZGUNCg0KLSAgIGBkYXlgID0gZGF5IG9mIHBhcnRpY2lwYXRpb24gKGZyb20gMSB0byAxMSkNCg0KPGJyPg0KDQoqKkNvbXBsaWFuY2UqKg0KDQotICAgYGFmdGAgPSBkYXkgaW5jbHVkaW5nIHRoZSByZXNwb25zZSB0byB0aGUgQWZ0ZXJub29uDQogICAgcXVlc3Rpb25uYWlyZSAoMSkgb3Igbm90ICgwKQ0KDQotICAgYGV2ZWAgPSBkYXkgaW5jbHVkaW5nIHRoZSByZXNwb25zZSB0byB0aGUgRXZlbmluZyBxdWVzdGlvbm5haXJlICgxKQ0KICAgIG9yIG5vdCAoMCkNCg0KLSAgIGBtb3JgID0gZGF5IGluY2x1ZGluZyB0aGUgcmVzcG9uc2UgdG8gdGhlIE1vcm5pbmcgcXVlc3Rpb25uYWlyZSAoMSkNCiAgICBvciBub3QgKDApDQoNCjxicj4NCg0KKipEYXRhIHF1YWxpdHkqKg0KDQotICAgYGZsYWdUaW1lYCA9IHJlc3BvbnNlcyByZWNvZGVkIGR1ZSB0byB3cm9uZyByZXNwb25zZSB0aW1pbmcgKGkuZS4sDQogICAgcmVzcG9uc2VzIGdpdmVuIG91dHNpZGUgdGhlIHNjaGVkdWxlZCBpbnRlcnZhbHMpIChzZWUgc2VjdGlvbiAzLjYuMikNCg0KLSAgIGBmbGFnQlBfYWZ0YCAtIGBmbGFnQlBfZXZlYCA9IGZsYWdnZWQgY2FzZXMgdGhhdCB3ZXJlIHJlcHJvY2Vzc2VkDQogICAgZHVlIHRvIGV4dHJlbWUgQlAgdmFsdWVzIChzZWUgc2VjdGlvbiAzLjIpDQoNCi0gICBgY2FyZWxlc3NgID0gcGFydGljaXBhbnQgZmxhZ2dlZCBhcyBhIGNhcmVsZXNzIHJlc3BvbmRlbnQNCiAgICAoYGNhcmVsZXNzID0gVFJVRWApIGR1ZSB0byBpbmNvbnNpc3RlbnQgcmVzcG9uc2VzIGluIHRoZSBgRGF5T2ZmYA0KICAgIHZhcmlhYmxlcyAoc2VlIHNlY3Rpb24gMy40LjEpIC0gdGhlIHNhbWUgdmFyaWFibGUgaXMgaW5jbHVkZWQgaW4gdGhlDQogICAgYHByZWxxc2AgZGF0YXNldA0KDQo8YnI+DQoNCioqQWZ0ZXJub29uIHF1ZXN0aW9ubmFpcmUqKg0KDQotICAgYHN0YXJ0X2FmdGAgPSBzdGFydGluZyB0aW1lIG9mIHRoZSBBZnRlcm5vb24gcXVlc3Rpb25uYWlyZQ0KICAgICh5eXl5LW1tLWRkIGhoOm1tOnNzKQ0KDQotICAgYGVuZF9hZnRgID0gc3VibWlzc2lvbiB0aW1lIG9mIHRoZSBBZnRlcm5vb24gcXVlc3Rpb25uYWlyZQ0KICAgICh5eXl5LW1tLWRkIGhoOm1tOnNzKQ0KDQotICAgYGRheU9mZl9hZnRgID0gbG9naWNhbCB2YXJpYWJsZSBpbmRpY2F0aW5nIHdoZXRoZXIgdGhlIHBhcnRpY2lwYW50DQogICAgcmVwb3J0ZWQgd29ya2luZyBvbiB0aGF0IGRheSAoRkFMU0UpIG9yIG5vdCAoVFJVRSkNCg0KLSAgIGBTQlBfYWZ0YCAtIGBEQlBfYWZ0YCA9IHN5c3RvbGljIGFuZCBkaWFzdG9saWMgYWdncmVnYXRlIGJsb29kDQogICAgcHJlc3N1cmUgdmFsdWUgKG1tSGcpIG1lYXN1cmVkIGluIHRoZSBBZnRlcm5vb24NCg0KLSAgIGB3aGVyZV9hZnRgID0gcGxhY2Ugd2hlcmUgdGhlIEFmdGVybm9vbiBibG9vZCBwcmVzc3VyZSByZWNvcmRpbmcgd2FzDQogICAgZG9uZSAoImhvbWUiLCAid29ya3BsYWNlIiwgIm90aGVyIikNCg0KLSAgIGBjb25mb3VuZGVyc19hZnRgID0gbG9naWNhbCB2YXJpYWJsZSBpbmRpY2F0aW5nIHRoZSBwcmVzZW5jZSAoVFJVRSkNCiAgICBvciBhYnNlbmNlIChGQUxTRSkgb2YgYW55IGNvbmZvdW5kZXIgYmVmb3JlIHRoZSBBZnRlcm5vb24gcmVjb3JkaW5nDQoNCi0gICBgY29mZmVlX2FmdGAgLSBgbWVhbF9hZnRgID0gdmFyaWFibGVzIGluZGljYXRpbmcgdGhlIHByZXNlbmNlICgxKSBvcg0KICAgIGFic2VuY2UgKDApIG9mIGVhY2ggY29uZm91bmRlciAoaS5lLiwgY29mZWUsIHNtb2tlLCBzcG9ydCwgYW5kIG1lYWwpDQoNCi0gICBgV0hMU00xYCAtIGBXSExTTV82YCA9IGl0ZW0gc2NvcmVzIGF0IHRoZSBkaWFyeSB2ZXJzaW9uIG9mIHRoZSBEVVdBUw0KICAgICh3b3JrYWhvbGlzbSkgKDEtNykNCg0KPGJyPg0KDQoqKkV2ZW5pbmcgcXVlc3Rpb25uYWlyZSoqDQoNCi0gICBgc3RhcnRfZXZlYCA9IHN0YXJ0aW5nIHRpbWUgb2YgdGhlIEV2ZW5pbmcgcXVlc3Rpb25uYWlyZSAoeXl5eS1tbS1kZA0KICAgIGhoOm1tOnNzKQ0KDQotICAgYGVuZF9ldmVgID0gc3VibWlzc2lvbiB0aW1lIG9mIHRoZSBFdmVuaW5nIHF1ZXN0aW9ubmFpcmUgKHl5eXktbW0tZGQNCiAgICBoaDptbTpzcykNCg0KLSAgIGBkYXlPZmZfZXZlYCA9IGxvZ2ljYWwgdmFyaWFibGUgaW5kaWNhdGluZyB3aGV0aGVyIHRoZSBwYXJ0aWNpcGFudA0KICAgIHJlcG9ydGVkIHdvcmtpbmcgb24gdGhhdCBkYXkgKEZBTFNFKSBvciBub3QgKFRSVUUpDQoNCi0gICBgU0JQX2V2ZWAgLSBgREJQX2V2ZWAgPSBzeXN0b2xpYyBhbmQgZGlhc3RvbGljIGFnZ3JlZ2F0ZSBibG9vZA0KICAgIHByZXNzdXJlIHZhbHVlIChtbUhnKSBtZWFzdXJlZCBpbiB0aGUgRXZlbmluZw0KDQotICAgYGNvbmZvdW5kZXJzX2V2ZWAgPSBsb2dpY2FsIHZhcmlhYmxlIGluZGljYXRpbmcgdGhlIHByZXNlbmNlIChUUlVFKQ0KICAgIG9yIGFic2VuY2UgKEZBTFNFKSBvZiBhbnkgY29uZm91bmRlciBiZWZvcmUgdGhlIEV2ZW5pbmcgcmVjb3JkaW5nDQoNCi0gICBgY29mZmVlX2V2ZWAgLSBgbWVhbF9ldmVgID0gdmFyaWFibGVzIGluZGljYXRpbmcgdGhlIHByZXNlbmNlICgxKSBvcg0KICAgIGFic2VuY2UgKDApIG9mIGVhY2ggY29uZm91bmRlciAoaS5lLiwgY29mZWUsIHNtb2tlLCBzcG9ydCwgYW5kIG1lYWwpDQoNCi0gICBgdGVsZVdvcmtgID0gZmFjdG9yIGluZGljYXRpbmcgd2hldGhlciBvbiB0aGF0IGRheSB0aGUgcGFydGljaXBhbnQNCiAgICB3b3JrZWQgaW4gdGhlICJvZmZpY2UiLCBkaWQgInRlbGVXb3JrIiwgb3IgImJvdGgiDQoNCi0gICBgd29ya0hvdXJzYCA9IG51bWJlciBvZiB3b3JraW5nIGhvdXJzIGZvciB0aGF0IGRheSAoTm8uKQ0KDQotICAgYGRhaWx5SGFzc2xlc3NfZXZlYCA9IGZhY3RvciBpbmRpY2F0aW5nIHdoZXRoZXIgdGhlIHBhcnRpY2lwYW50DQogICAgcmVwb3J0ZWQgc29tZSBkYWlseSBoYXNzbGVzIG91dHNpZGUgdGhlIHdvcmtpbmcgdGltZSBvbiB0aGF0IGRheQ0KICAgICgiWWVzIikgb3Igbm90ICgiTm8iKQ0KDQotICAgYEVFMWAgLSBgRUU0YCA9IGl0ZW0gc2NvcmVzIGF0IHRoZSBkaWFyeSB2ZXJzaW9uIG9mIHRoZSBDb3BlbmhhZ2VuDQogICAgQnVybm91dCBJbnZlbnRvcnkgKGVtb3Rpb25hbCBleGhhdXN0aW9uKSAoMS03KQ0KDQotICAgYFIuZGV0MWAgLSBgUi5kZXQzYCA9IGl0ZW0gc2NvcmVzIGF0IHRoZSBkaWFyeSB2ZXJzaW9uIG9mIHRoZSBSZWNvdmVyeSBFeHBlcmllbmNlcyBRdWVzdGlvbm5haXJlIChwc3ljaG9sb2dpY2FsIGRldGFjaG1lbnQpICgxLTcpDQoNCjxicj4NCg0KKipNb3JuaW5nIHF1ZXN0aW9ubmFpcmUqKg0KDQotICAgYHN0YXJ0X21vcmAgPSBzdGFydGluZyB0aW1lIG9mIHRoZSBNb3JuaW5nIHF1ZXN0aW9ubmFpcmUgKHl5eXktbW0tZGQNCiAgICBoaDptbTpzcykNCg0KLSAgIGBlbmRfbW9yYCA9IHN1Ym1pc3Npb24gdGltZSBvZiB0aGUgTW9ybmluZyBxdWVzdGlvbm5haXJlICh5eXl5LW1tLWRkDQogICAgaGg6bW06c3MpDQoNCi0gICBgZGF5T2ZmeWVzdGVyZGF5YCA9IGxvZ2ljYWwgdmFyaWFibGUgaW5kaWNhdGluZyB3aGV0aGVyIHRoZQ0KICAgIHBhcnRpY2lwYW50IHJlcG9ydGVkIHdvcmtpbmcgb24gdGhlIHByZXZpb3VzIGRheSBkYXkgKEZBTFNFKSBvciBub3QNCiAgICAoVFJVRSkNCg0KLSAgIGBsYXRlV29ya0hvdXJzYCA9IGxvZ2ljYWwgdmFyaWFibGUgaW5kaWNhdGluZyB3aGV0aGVyIHRoZQ0KICAgIHBhcnRpY2lwYW50IHJlcG9ydGVkIHdvcmtpbmcgaW4gdGhlIHByZXZpb3VzIGV2ZW5pbmcgKFRSVUUpIG9yIG5vdA0KICAgIChGQUxTRSkNCg0KLSAgIGB3YWtlVGltZWAgPSBzZWxmLXJlcG9ydGVkIHdha2luZyB0aW1lICh5eXl5LW1tLWRkIGhoOm1tOnNzKQ0KDQotICAgYGhoRnJvbUF3YWtlYCA9IG51bWJlciBvZiBob3VycyBiZXR3ZWVuIHdha2V0aW1lIGFuZCB0aGUgcmVzcG9uc2UgdG8NCiAgICB0aGUgTW9ybmluZyBxdWVzdGlvbm5haXJlDQoNCi0gICBgU1FgIC0gYFNRNGAgPSBpdGVtIHNjb3JlcyBhdCB0aGUgZGlhcnkgdmVyc2lvbiBvZiB0aGUNCiAgICBNaW5pIFNsZWVwIFF1ZXN0aW9ubmFpcmUgKHNsZWVwIGRpc3R1cmJhbmNlcykgKDEtNykNCg0KPGJyPg0KDQoqKlJldHJvc3BlY3RpdmUgdGltZS1pbnZhcmlhbnQgdmFyaWFibGVzKiogKG1lYXN1cmVkIHdpdGggdGhlIHByZWxpbWluYXJ5IHF1ZXN0aW9ubmFpcmUpDQoNCipEZW1vZ3JhcGhpY3MqDQoNCi0gICBgZ2VuZGVyYCA9IHBhcnRpY2lwYW504oCZcyBnZW5kZXIgKOKAnEbigJ0gb3Ig4oCcTeKAnSkNCg0KLSAgIGBhZ2VgID0gcGFydGljaXBhbnTigJlzIGFnZSAoeWVhcnMpDQoNCi0gICBgQk1JYCA9IHBhcnRpY2lwYW504oCZcyBib2R5IG1hc3MgaW5kZXggKGtnL21eMikNCg0KLSAgIGBlZHVgID0gcGFydGljaXBhbnTigJlzIGVkdWNhdGlvbiBsZXZlbCAo4oCcbWlkZGxl4oCdLCDigJxoaWdoc2Nob29s4oCdLCDigJx1bml2ZXJzaXR5K+KAnSkNCg0KLSAgIGBtU3RhdHVzYCA9IHBhcnRpY2lwYW504oCZcyBtYXJpdGFsIHN0YXR1cyAo4oCcc2luZ2xl4oCdLCDigJxwYXJ0bmVy4oCdLCDigJxkaXZvcmNlZOKAnSwg4oCcd2lkb3dlZOKAnSkNCg0KLSAgIGBob21lYCA9IGZhbWlseSBzaXR1YXRpb24gKGxpdmluZyDigJxhbG9uZeKAnSBvciB3aXRoIOKAnHBhcnRuZXLigJ0sIOKAnGNoaWxkcmVu4oCdLCDigJxwYXJlbnRz4oCdLCDigJxvdGhlcnPigJ0pDQoNCi0gICBgY2hpbGRyZW5gID0gbnVtYmVyIG9mIGNoaWxkcmVuIChOby4pDQoNCi0gICBgaG9tZV9jaGlsZGAgPSBsaXZpbmcgd2l0aCBjaGlsZHJlbiAoWWVzL05vKQ0KDQotICAgYHBhcnRuZXJgID0gaGF2aW5nIGEgcGFydG5lciAoWWVzL05vKQ0KDQotICAgYGhvbWVfcGFydG5lcmAgPSBsaXZpbmcgd2l0aCBwYXJ0bmVyIChZZXMvTm8pDQoNCipDb25mb3VuZGVycyBhbmQgaW5jbHVzaW9uIGNyaXRlcmlhKg0KDQotICAgYHNtb2tlcmAgPSBzbW9raW5nIHN0YXR1cyAo4oCcTm/igJ0sIOKAnFllc+KAnSwg4oCcUXVpdF9sZXNz4oCdLCDigJxRdWl0X21vcmXigJ0pDQoNCi0gICBgYnBfZHJ1Z3NgID0gcGFydGljaXBhbnQgcmVwb3J0aW5nIHRha2luZyBibG9vZCBwcmVzc3VyZSBtZWRpY2F0aW9ucyAoZS5nLiwgZGl1cmV0aWNzLCBiZXRhLWJsb2trYW50cywgYW50aS1oeXBlcnRlbnNpb24pDQoNCi0gICBgaG9ybV9kcnVnc2AgPSBwYXJ0aWNpcGFudCByZXBvcnRpbmcgdGFraW5nIGhvcm1vbmFsIG1lZGljYXRpb25zIChlLmcuLCBiaXJ0aCBjb250cm9sKQ0KDQotICAgYHBzeV9kcnVnc2AgPSBwYXJ0aWNpcGFudCByZXBvcnRpbmcgdGFraW5nIHBzeWNoaWF0cmljIGRydWdzIChlLmcuLCBhbnRpZGVwcmVzc2FudHMsIGFueGlldHkpDQoNCi0gICBgY3ZfZHlzZmAgPSBwYXJ0aWNpcGFudCByZXBvcnRpbmcgc3VmZmVyaW5nIGZyb20gYSBjYXJkaW92YXNjdWxhciBkaXNlYXNlIChlLmcuLCBoeXBlcnRlbnNpb24sIGlzY2hlbWlhLCBzdHJva2VzKQ0KDQotICAgYHNsZWVwX2R5c2ZgID0gcGFydGljaXBhbnQgcmVwb3J0aW5nIHN1ZmZlcmluZyBmcm9tIGEgc2xlZXAtcmVsYXRlZCBkaXNlYXNlIChlLmcuLCBpbnNvbW5pYSwgcGFyYXNvbW5pYSwgc2xlZXAgYXBuZWEpDQoNCipPY2N1cGF0aW9uYWwgdmFyaWFibGVzKg0KDQotICAgYGpvYmAgPSBwYXJ0aWNpcGFudOKAmXMgam9iIHJlY29kZWQgdXNpbmcgdGhlIElTQ08tMDggY2xhc3NpZmljYXRpb24gb2Ygb2NjdXBhdGlvbnMgKGxldmVsIDIpIChHYW56ZWJvb20sIDIwMTANCg0KLSAgIGBwb3NpdGlvbmAgPSBwYXJ0aWNpcGFudOKAmXMgam9iIHBvc2l0aW9uICjigJxFbXBsb3llZeKAnSwg4oCcUHJvamVjdOKAnSwg4oCcTWFuYWdlcuKAnSwg4oCcKFNlbGYtKUVtcGxveWVy4oCdKQ0KDQotICAgYHNlY3RvcmAgPSBwYXJ0aWNpcGFudOKAmXMgam9iIHNlY3RvciAo4oCcUHJpdmF0ZeKAnSBvciDigJxQdWJsaWPigJ0pDQoNCi0gICBgd2Vla0hvdXJzYCA9IHBhcnRpY2lwYW504oCZcyBzZWxmLXJlcG9ydGVkIG1lYW4gbnVtYmVyIG9mIHdvcmtpbmcgaG91cnMgcGVyIHdlZWsgKE5vLikNCg0KPGJyPg0KDQojIDYuIERhdGEgZXhwb3J0DQoNCkhlcmUsIHdlIGV4cG9ydCB0aGUgcmVjb2RlZCBhbmQgcHJlLXByb2Nlc3NlZCBgZGlhcnlfd2lkZWAgZGF0YXNldCAocmVuYW1lZCBhcyBgZGlhcnlgKSB0byBiZSB1c2VkIGZvciBmdXJ0aGVyIGFuYWx5c2VzLiBUaGUgZGF0YXNldHMgaXMgZXhwb3J0ZWQgaW4gYm90aCBDU1YgYW5kIFJEYXRhIGZvcm1hdC4NCmBgYCB7cn0NCiMgZXhwb3J0aW5nIGRpYXJ5IGRhdGENCmRpYXJ5IDwtIGRpYXJ5X3dpZGUgIyByZW5hbWVkIGFzICdkaWFyeScNCnNhdmUoZGlhcnksZmlsZT0iREFUSS9kaWFyeV9wcm9jZXNzZWQuUkRhdGEiKSAjIFJEYXRhDQp3cml0ZS5jc3YyKGRpYXJ5LGZpbGU9IkRBVEkvZGlhcnlfcHJvY2Vzc2VkLmNzdiIsIHJvdy5uYW1lcz1GQUxTRSkgIyBjc3Ygd2l0aCAiOyINCmBgYA0KDQo8YnI+DQoNCiMgUmVmZXJlbmNlcyB7I3JlZn0NCg0KLSBHYW56ZWJvb20sIEguIEIuICgyMDEwKS4gSW50ZXJuYXRpb25hbCBzdGFuZGFyZCBjbGFzc2lmaWNhdGlvbiBvZiBvY2N1cGF0aW9ucyBJU0NPLTA4IHdpdGggSVNFSS0wOCBzY29yZXMuIFZlcnNpb24gb2YgSnVseSwgMjcsIDIwMTAuIEF2YWlsYWJsZSBmcm9tIFt0aGlzIGxpbmtdKGh0dHA6Ly93d3cuaGFycnlnYW56ZWJvb20ubmwvUGRmLzIwMTAlMjAtJTIwR2FuemVib29tJTIwLSUyMEElMjBOZXclMjBJbnRlcm5hdGlvbmFsJTIwU29jaW8tRWNvbm9taWMlMjBJbmRleCUyMElTRUklMjBvZiUyMG9jY3VwYXRpb25hbCUyMHN0YXR1cyUyMGZvciUyMHRoZSUyMEludGVybmF0aW9uYWwlMjBTdGFuZGFyZCUyMENsYXNzaWZpY2F0aW9uJTIwb2YlMjBPY2N1cGF0aW9uLnBkZikuDQoNCiMjIFIgcGFja2FnZXM=