Assessments

PHQ-9

Purpose & Evaluation :

The PHQ-9 is a “Self-administered 9-item instrument based on the nine DSM-V criteria listed under criterion A for Major Depressive Disorder. The instrument aids in guiding criteria based diagnosis of depressive symptoms, can assist in identifying treatment goals, determining severity of symptoms, as well as guiding clinical intervention (VA.gov).”

The PHQ-9 was evaluated as a patient-reported outcome measures in veterans by Katz et. al. (2021). They found that “the PHQ-9 functions more as a general measure of symptoms or distress than as a disease-specific scale. This supports its use as a PROM for patients beyond those with major depression, including those with related diagnoses and those with comorbidities, and use of related PROM-PMs in clinical settings where diagnoses may not be precise and comorbidities may be common.”

Recommendations for depression severity and questions associated with the scale can be found at: https://med.stanford.edu/fastlab/research/imapp/msrs/_jcr_content/main/accordion/accordion_content3/download_256324296/file.res/PHQ9%20id%20date%2008.03.pdf

Severity Score
Minimal Depression 0-4
Mild Depression 5-9
Moderate Depression 10-14
Moderately Severe Depression 15-19
Severe Depression 20-27
head(phq9)
#Keep only identifier columns and the PHQ-9 total score columns
phq9.change=subset(phq9, select = c(1,2,3,14))

library(tidyr)
#Change from long to wide format
phq9.change=spread(phq9.change, key = `Event Name`, value = `PHQ9.Total`)
#Sanity check: If this comes back as false, need to go back to excel sheet and correct record ID where Case ID is name for some and numeric for others
n_occur <- data.frame(table(phq9.change$`Record ID`))
n_occur[n_occur$Freq > 1,]

#Reorder columns to match order of assessments
phq9.change <- phq9.change[, c(1,2,3, 5, 4)]

library('tidyverse')
#Calculate change in score between initial and discharge
phq9.change$change=phq9.change$`Individual Discharge`-phq9.change$`Individual Baseline`
#Calculate change in score between initial and reauthorization
phq9.change$change.reauth=phq9.change$`Individual Reauthorization`-phq9.change$`Individual Baseline`

#IF discharge value is available, use it to calculate change. If not, use the reevaluation value to calculate change
#Remove columns used to calculate to only leave column with change value
phq9.change= phq9.change %>% 
    mutate(change = coalesce(change,change.reauth))
phq9.change=subset(phq9.change, select = c(1:6))


phq9.change$improvement=phq9.change$change
phq9.change$improvement[phq9.change$improvement >= 0] <- "FALSE" 
phq9.change$improvement[phq9.change$improvement < 0] <- "TRUE" 

mean_baseline=mean(phq9.change$`Individual Baseline`, na.rm=T)
mean_reauth=mean(phq9.change$`Individual Reauthorization`, na.rm = T)
mean_discharge=mean(phq9.change$`Individual Discharge`, na.rm = T)

Summary Statistics

This table shows the total sample size available at each timepoint (N) and summary statistics for the PHQ9 scores during Baseline Evaluation, Reathurization, and Discharge. Additionally, it shows the summary statistics for score changes between baseline and discharge, or reauthorization when discharge has not occurred. The breakdown of “improvement” shows the number of individuals whos PHQ9 score did and did not improve during that time.

library(vtable)
phq9.change$`Record ID`=as.character(phq9.change$`Record ID`)
#Print table statistics in R Markdown
sumtable(phq9.change, vars = c('Individual Baseline','Individual Reauthorization', 'Individual Discharge', 'change', 'improvement'))
Summary Statistics
Variable N Mean Std. Dev. Min Pctl. 25 Pctl. 75 Max
Individual Baseline 229 17.183 6.048 1 12 22 27
Individual Reauthorization 39 15.103 7.214 0 11 21.5 27
Individual Discharge 21 14.667 5.598 4 10 18 26
change 45 -2.133 8.554 -23 -7 4 18
improvement 45
… FALSE 18 40%
… TRUE 27 60%

Graphics

Change in Severity Score: When available, this frequency chart shows the distribution of score changes from baseline to discharge. When a discharge score is not yet available, it is the change from baseline to reauthorization.

### Histogram showing change in scores over time. 

ggplot(phq9.change, aes(change)) +
  geom_histogram(binwidth=5, color="black", fill= "grey") +
  xlab("Change in Depression Score")  +
  ggtitle("Change in Severity Score")

Distribution of PHQ9 scores at each timepoint (Baseline, Reauthorization, and Discharge). Color coded dotted lines indicate mean for each group, while shaded regions show density of occurance. Depression scores of minimal to severe are indicated on chart.

### Distribution of scores

den.1=ggplot() +
geom_density(aes(`Individual Baseline`, fill="Baseline"), alpha=0.2,  data=phq9.change) + 
geom_density(aes(`Individual Reauthorization`, fill="Reauthorization"), alpha=0.2, data=phq9.change) + 
  geom_density(aes(`Individual Discharge`, fill="Discharge"), alpha=0.2, data=phq9.change) + 
    labs(title="PHQ-9", 
         subtitle="Distribution of Depression Scores",
         x="Score") +
  geom_vline(xintercept=mean_baseline, size=1, color="pink", linetype="dotted") +
  geom_vline(xintercept=mean_reauth, size=1, color="blue",  linetype="dotted") +
  geom_vline(xintercept=mean_discharge, size=1, color="green",  linetype="dotted") +
   geom_vline(xintercept=4.1, size=0.5, color="black",  linetype="dotted") +
 geom_vline(xintercept=9.1, size=0.5, color="black",  linetype="dotted") +
  geom_vline(xintercept=14.1, size=0.5, color="black",  linetype="dotted") +
   geom_vline(xintercept=19.1, size=0.5, color="black",  linetype="dotted") +
  annotate(geom="text", x=2, y=0.075, label="Minimal", color="black")+
  annotate(geom="text", x=7, y=0.075, label="Mild", color="black")+
  annotate(geom="text", x=12, y=0.075, label="Moderate", color="black")+
  annotate(geom="text", x=17, y=0.075, label="Mod. Severe", color="black")+
  annotate(geom="text", x=23, y=0.075, label="Severe", color="black") +
  ylab("Density") +
  labs(fill='Timepoint') 
den.1

Flow of client scores between depression severity scores between Basleline and Discharge, or Reauthorization when Discharge scores are not yet available. The left hand coloumn shows the distribution of scores among severity categories at “Baseline”. Following the color coded sections to the “Current” column displays the proportion of clients at each starting baseline category vs their current severity rating.

#Create a column with disk level categories instead of numbers, then describe improvement based on categorical changes
phq9.change$risk.level.init=phq9.change$`Individual Baseline`

phq9.change$risk.level.init[phq9.change$risk.level.init > 19] <- "Severe" 
phq9.change$risk.level.init[phq9.change$risk.level.init == 1] <- "Minimal" 
phq9.change$risk.level.init[phq9.change$risk.level.init == 2] <- "Minimal" 
phq9.change$risk.level.init[phq9.change$risk.level.init == 3] <- "Minimal" 
phq9.change$risk.level.init[phq9.change$risk.level.init == 4] <- "Minimal" 
phq9.change$risk.level.init[phq9.change$risk.level.init == 5] <- "Mild" 
phq9.change$risk.level.init[phq9.change$risk.level.init == 6] <- "Mild" 
phq9.change$risk.level.init[phq9.change$risk.level.init == 7] <- "Mild" 
phq9.change$risk.level.init[phq9.change$risk.level.init == 8] <- "Mild" 
phq9.change$risk.level.init[phq9.change$risk.level.init == 9] <- "Mild" 
phq9.change$risk.level.init[phq9.change$risk.level.init == 10] <- "Moderate" 
phq9.change$risk.level.init[phq9.change$risk.level.init == 11] <- "Moderate" 
phq9.change$risk.level.init[phq9.change$risk.level.init == 12] <- "Moderate" 
phq9.change$risk.level.init[phq9.change$risk.level.init == 13] <- "Moderate" 
phq9.change$risk.level.init[phq9.change$risk.level.init == 14] <- "Moderate" 
phq9.change$risk.level.init[phq9.change$risk.level.init == 15] <- "Moderately Severe" 
phq9.change$risk.level.init[phq9.change$risk.level.init == 16] <- "Moderately Severe" 
phq9.change$risk.level.init[phq9.change$risk.level.init == 17] <- "Moderately Severe" 
phq9.change$risk.level.init[phq9.change$risk.level.init == 18] <- "Moderately Severe" 
phq9.change$risk.level.init[phq9.change$risk.level.init == 19] <- "Moderately Severe" 

phq9.change$risk.level.reauth=phq9.change$`Individual Reauthorization`

phq9.change$risk.level.reauth[phq9.change$risk.level.reauth > 19] <- "Severe" 
phq9.change$risk.level.reauth[phq9.change$risk.level.reauth == 1] <- "Minimal" 
phq9.change$risk.level.reauth[phq9.change$risk.level.reauth == 2] <- "Minimal" 
phq9.change$risk.level.reauth[phq9.change$risk.level.reauth == 3] <- "Minimal" 
phq9.change$risk.level.reauth[phq9.change$risk.level.reauth == 4] <- "Minimal" 
phq9.change$risk.level.reauth[phq9.change$risk.level.reauth == 5] <- "Mild" 
phq9.change$risk.level.reauth[phq9.change$risk.level.reauth == 6] <- "Mild" 
phq9.change$risk.level.reauth[phq9.change$risk.level.reauth == 7] <- "Mild" 
phq9.change$risk.level.reauth[phq9.change$risk.level.reauth == 8] <- "Mild" 
phq9.change$risk.level.reauth[phq9.change$risk.level.reauth == 9] <- "Mild" 
phq9.change$risk.level.reauth[phq9.change$risk.level.reauth == 10] <- "Moderate" 
phq9.change$risk.level.reauth[phq9.change$risk.level.reauth == 11] <- "Moderate" 
phq9.change$risk.level.reauth[phq9.change$risk.level.reauth == 12] <- "Moderate" 
phq9.change$risk.level.reauth[phq9.change$risk.level.reauth == 13] <- "Moderate" 
phq9.change$risk.level.reauth[phq9.change$risk.level.reauth == 14] <- "Moderate" 
phq9.change$risk.level.reauth[phq9.change$risk.level.reauth == 15] <- "Moderately Severe" 
phq9.change$risk.level.reauth[phq9.change$risk.level.reauth == 16] <- "Moderately Severe" 
phq9.change$risk.level.reauth[phq9.change$risk.level.reauth == 17] <- "Moderately Severe" 
phq9.change$risk.level.reauth[phq9.change$risk.level.reauth == 18] <- "Moderately Severe" 
phq9.change$risk.level.reauth[phq9.change$risk.level.reauth == 19] <- "Moderately Severe" 

phq9.change$risk.level.discharge=phq9.change$`Individual Discharge`

phq9.change$risk.level.discharge[phq9.change$risk.level.discharge > 19] <- "Severe" 
phq9.change$risk.level.discharge[phq9.change$risk.level.discharge == 1] <- "Minimal" 
phq9.change$risk.level.discharge[phq9.change$risk.level.discharge == 2] <- "Minimal" 
phq9.change$risk.level.discharge[phq9.change$risk.level.discharge == 3] <- "Minimal" 
phq9.change$risk.level.discharge[phq9.change$risk.level.discharge == 4] <- "Minimal" 
phq9.change$risk.level.discharge[phq9.change$risk.level.discharge == 5] <- "Mild" 
phq9.change$risk.level.discharge[phq9.change$risk.level.discharge == 6] <- "Mild" 
phq9.change$risk.level.discharge[phq9.change$risk.level.discharge == 7] <- "Mild" 
phq9.change$risk.level.discharge[phq9.change$risk.level.discharge == 8] <- "Mild" 
phq9.change$risk.level.discharge[phq9.change$risk.level.discharge == 9] <- "Mild" 
phq9.change$risk.level.discharge[phq9.change$risk.level.discharge == 10] <- "Moderate" 
phq9.change$risk.level.discharge[phq9.change$risk.level.discharge == 11] <- "Moderate" 
phq9.change$risk.level.discharge[phq9.change$risk.level.discharge == 12] <- "Moderate" 
phq9.change$risk.level.discharge[phq9.change$risk.level.discharge == 13] <- "Moderate" 
phq9.change$risk.level.discharge[phq9.change$risk.level.discharge == 14] <- "Moderate" 
phq9.change$risk.level.discharge[phq9.change$risk.level.discharge == 15] <- "Moderately Severe" 
phq9.change$risk.level.discharge[phq9.change$risk.level.discharge == 16] <- "Moderately Severe" 
phq9.change$risk.level.discharge[phq9.change$risk.level.discharge == 17] <- "Moderately Severe" 
phq9.change$risk.level.discharge[phq9.change$risk.level.discharge == 18] <- "Moderately Severe" 
phq9.change$risk.level.discharge[phq9.change$risk.level.discharge == 19] <- "Moderately Severe" 

#IF discharge value is available, use it to calculate change. If not, use the reevaluation value to calculate change
#Remove columns used to calculate to only leave column with change value
phq9.change$risk.level.change=phq9.change$risk.level.discharge
phq9.change= phq9.change %>% 
    mutate(risk.level.change = coalesce(risk.level.change,risk.level.reauth))

phq9.change <- phq9.change[, c(1:8,11)]
phq9.change$risk.level=paste(phq9.change$risk.level.init,phq9.change$risk.level.change,sep="-")
phq9.change$Discharged=phq9.change$`Individual Discharge`
phq9.change$Discharged[phq9.change$Discharged != "NA"] <- "TRUE" 
### Summary of number of individuals with increasing and decreasing risk factors by discharge

phq9.risk.change=phq9.change

phq9.risk.change$risk.level.change[phq9.risk.change$risk.level.change == "Minimal" ] <- 1 
phq9.risk.change$risk.level.change[phq9.risk.change$risk.level.change == "Mild"] <- 2
phq9.risk.change$risk.level.change[phq9.risk.change$risk.level.change == "Moderate"] <- 3
phq9.risk.change$risk.level.change[phq9.risk.change$risk.level.change == "Moderately Severe"] <- 4
phq9.risk.change$risk.level.change[phq9.risk.change$risk.level.change == "Severe"] <- 5 

phq9.risk.change$risk.level.init[phq9.risk.change$risk.level.init == "Minimal" ] <- 1 
phq9.risk.change$risk.level.init[phq9.risk.change$risk.level.init == "Mild"] <- 2
phq9.risk.change$risk.level.init[phq9.risk.change$risk.level.init == "Moderate"] <- 3
phq9.risk.change$risk.level.init[phq9.risk.change$risk.level.init == "Moderately Severe"] <- 4 
phq9.risk.change$risk.level.init[phq9.risk.change$risk.level.init == "Severe"] <- 5 

phq9.risk.change$risk.level.change=as.numeric(phq9.risk.change$risk.level.change)
phq9.risk.change$risk.level.init=as.numeric(phq9.risk.change$risk.level.init)
### Distribution of Severity Baseline to Current
##This needs work to add the appropriate stratum labels for each side

phq9.freq=phq9.change
phq9.freq=phq9.freq %>% drop_na(risk.level.change)

mockup_freq <- phq9.freq %>%
  dplyr::count(risk.level.init, risk.level.change) %>%
  mutate(proptot = prop.table(n))

mockup_freq <- na.omit(mockup_freq)
mockup_freq$risk.level.init <- factor(mockup_freq$risk.level.init, levels=c('Minimal', 'Mild', 'Moderate', 'Moderately Severe', 'Severe'))
levels(mockup_freq$risk.level.init)

#eventually remove rows with NA here

library(dataMaid)
library(lubridate)
library(summarytools)
library(ggstatsplot)
library(gridExtra)
library(Rmisc)
library(ggfortify)
library(ggpubr)
library(factoextra)
library(ggpubr)
library(forcats)
library(RColorBrewer)
library(ggrepel)
library(ggalluvial)


ggplot(as.data.frame(mockup_freq),
       aes(y = proptot, axis1 = risk.level.init, axis2 = risk.level.change)) +
  geom_alluvium(aes(fill = risk.level.init), width = 1/12) +
  geom_stratum(width = 1/12 , colour = "darkgrey") +
  geom_label(stat = "stratum", infer.label = TRUE, fill="white", fontface="bold", colour="darkgrey",  size=2) +
  scale_x_discrete(limits = c("risk.level.init", "risk.level.change"),
                   expand = c(.1, .1),
                   labels = c("Baseline", "Current")) +
  ggtitle("Flow of Severity between Baseline and Current Assessment") +
  scale_fill_manual(values=c("grey", "yellow", "orange", "orangered", "darkred"), 
                    name="Title",
                    breaks=c("Minimal", "Mild", "Moderate", "Moderately Severe","Severe"),
                    labels=c("Minimal", "Mild", "Moderate", "Moderately Severe.","Severe")) +
  theme_minimal() +
  theme(legend.position = "right",
        panel.grid.major = element_blank(), 
        panel.grid.minor = element_blank()) +
  labs(y = "Proportion of total") 

Interactive Data Table

library(DT)
phq9.datatable= phq9.change[, c(1:7,10:11)]
  
datatable(data = phq9.datatable, width=NULL,  filter = "top", caption= "PHQ-9 Summary Results", rownames=F, colnames = c('Record ID', 'Case ID', 'Baseline Score', 'Reauthorization Score', 'Discharge Score', 'Change in Score', "Improvement (T/F)", "Risk Level Initial:Current", "Discharged (T/F)"),
          options = list(pagelength=25,
  initComplete = JS(
    "function(settings, json) {",
    "$(this.api().table().header()).css({'background-color': 'grey', 'color': '#fff'});",
    "}")))

PCL-5

Purpose and Evaluation

Evidence for the PCL for DSM-IV suggested 5 point decrease as a minimum threshold for determining whether an individual has responded to treatment and 10 point decrease as a minimum threshold for determining whether the improvement is clinically meaningful. Change scores for PCL-5 are currently being determined. It is expected that reliable and clinically meaningful change will be in a similar range. We recommend following the DSM-IV recommendations until new information is available.

https://www.ptsd.va.gov/professional/assessment/adult-sr/ptsd-checklist.asp

The PCL-5 can be scored in different ways: A total symptom severity score (range - 0-80) can be obtained by summing the scores for each of the 20 items. DSM-5 symptom cluster severity scores can be obtained by summing the scores for the items within a given cluster, i.e., cluster B (Re-experiencing; items 1-5), cluster C (Avoidance; items 6-7), cluster D (Negative alternations in cognition and mood; items 8-14), and cluster E (Hyper-arousal; items 15-20). A provisional PTSD diagnosis can be made by treating each item rated as 2 = “Moderately” or higher as a symptom endorsed, then following the DSM-5 diagnostic rule which requires at least: 1 B item (questions 1-5), 1 C item (questions 6-7), 2 D items (questions 8-14), 2 E items (questions 15-20).

Initial research suggests that a PCL-5 cutoff score between 31-33 is indicative of probable PTSD across samples. However, additional research is needed. Further, because the population and the purpose of the screening may warrant different cutoff scores, users are encouraged to consider both of these factors when choosing a cutoff score.

Cohen, J., et al. (2015). Preliminary Evaluation of the Psychometric Properties of the PTSD Checklist for DSM – 5. (Conference Presentation). doi: 10.12140/2.1.4448.5444

pcl5 <- data.frame(lapply(pcl5, function(x) {
                  gsub("Not at All", "0", x)
              }))

pcl5 <- data.frame(lapply(pcl5, function(x) {
                  gsub("A Little Bit", "1", x)
              }))

pcl5 <- data.frame(lapply(pcl5, function(x) {
                  gsub("Moderately", "2", x)
              }))


pcl5 <- data.frame(lapply(pcl5, function(x) {
                  gsub("Quite a Bit", "3", x)
              }))

pcl5 <- data.frame(lapply(pcl5, function(x) {
                  gsub("Extremely", "4", x)
              }))

pcl5 <- pcl5 %>% 
     mutate_at(c(5:24), as.numeric)
  
pcl5$clusterA <- as.numeric(apply(pcl5[,5:9], 1, sum))
pcl5$clusterB <- as.numeric(apply(pcl5[,10:11], 1, sum))
pcl5$clusterC <- as.numeric(apply(pcl5[,12:18], 1, sum))
pcl5$clusterD <- as.numeric(apply(pcl5[,19:24], 1, sum))


#Keep only identifier columns and the total score columns
pcl5.tot=subset(pcl5, select = c(1,2,3,25))
pcl5.tot=spread(pcl5.tot, key = `Event.Name`, value = `PCL5.Total`)
pcl5.tot <- pcl5.tot[, c(1,2,3, 5, 4)]

pcl5.clusA=subset(pcl5, select = c(1,2,3,27))
pcl5.clusA=spread(pcl5.clusA, key = `Event.Name`, value = `clusterA`)
pcl5.clusA <- pcl5.clusA[, c(1,2,3, 5, 4)]

pcl5.clusB=subset(pcl5, select = c(1,2,3,28))
pcl5.clusB=spread(pcl5.clusB, key = `Event.Name`, value = `clusterB`)
pcl5.clusB <- pcl5.clusB[, c(1,2,3, 5, 4)]

pcl5.clusC=subset(pcl5, select = c(1,2,3,29))
pcl5.clusC=spread(pcl5.clusC, key = `Event.Name`, value = `clusterC`)
pcl5.clusC <- pcl5.clusC[, c(1,2,3, 5, 4)]

pcl5.clusD=subset(pcl5, select = c(1,2,3,30))
pcl5.clusD=spread(pcl5.clusD, key = `Event.Name`, value = `clusterD`)
pcl5.clusD <- pcl5.clusD[, c(1,2,3, 5, 4)]
pcl5.tot$`Individual Baseline`=as.numeric(pcl5.tot$`Individual Baseline`)
pcl5.tot$`Individual Reauthorization`=as.numeric(pcl5.tot$`Individual Reauthorization`)
pcl5.tot$`Individual Discharge`=as.numeric(pcl5.tot$`Individual Discharge`)

#Calculate change in score between initial and discharge
pcl5.tot$change=pcl5.tot$`Individual Discharge`-pcl5.tot$`Individual Baseline`
#Calculate change in score between initial and reauthorization
pcl5.tot$change.reauth=pcl5.tot$`Individual Reauthorization`-pcl5.tot$`Individual Baseline`

#IF discharge value is available, use it to calculate change. If not, use the reevaluation value to calculate change
#Remove columns used to calculate to only leave column with change value
pcl5.tot= pcl5.tot %>% 
    mutate(change = coalesce(change,change.reauth))
pcl5.tot=subset(pcl5.tot, select = c(1:6))

Summary Statistics

Table including the sample size (N) and summary statistics for PCL-5 scores. “Change” varaible is the difference between the baseline and discharge score, or baseline and reauthorization score when no discharge score is available.

Table also includes “Improvement”, which categorizes changes in scores into those described by the VA for clinical improvement, responding to treatment, no response, or increased PTSD symptoms.

library(vtable)
sumtable(pcl5.tot)
Summary Statistics
Variable N Mean Std. Dev. Min Pctl. 25 Pctl. 75 Max
Individual Baseline 222 50.577 17.356 4 40 64 80
Individual Reauthorization 38 44.868 19.837 1 36.25 56.75 76
Individual Discharge 20 46.55 18.389 11 34.5 57.5 80
change 44 -7.25 20.356 -69 -16.5 5 23

Graphics

Change in PTSD Severity: Graph shows frequency of score changes between baseline and discharge assessments, or baseline and reauthorization assessments when discharge data is not available. Vertical lines seperate changes in scores into meaninful categories of “Responding to Treatment” (>5 point decrease), Clinical improvement” (>10 point decrease), or “Increased PTSD Symptoms”.

ggplot(pcl5.tot, aes(change)) +
  geom_histogram(binwidth=1, color="black", fill= "grey") +
  xlab("Change in PTSD Score")  +
  ggtitle("Change in Severity Score") +
geom_vline(xintercept=-10, size=1, color="grey",  linetype="dotted") +
  annotate(geom="text", x=-20, y=5.5, size=2, label="Clinical Improvement", color="black") +
geom_vline(xintercept=-4, size=1, color="grey",  linetype="dotted") +
  annotate(geom="text", x=-6.5, y=5.5, size=2, label="Responding", color="black") +
    annotate(geom="text", x=-6.5, y=5.35, size=2, label="to", color="black") +
    annotate(geom="text", x=-6.5, y=5.2, size=2, label="Treatment", color="black") +
  geom_vline(xintercept=-1, size=1, color="grey",  linetype="dotted") +
    annotate(geom="text", x=16.5, y=5.5, size=2, label="Increased PTSD Symptoms", color="black") 

Proportion of Clinets reporting clinically improved PTSD symptoms, response to treatment, no response to treatment, or increased PTSD symptoms. The graph on the left includes all changes in scores between baseline and discharge, and using reathorization scores when discharge scores are not available. The chart on the right includes only individuals who have completed the discharge assessment. Sample sizes for each category and indicated within pie wedges.

library(gridExtra)
library(ggpubr)
### Table summary of change in score. 
pcl5.tot$improvement=pcl5.tot$change

pcl5.tot$improvement[pcl5.tot$improvement < -9] <- "Clinical Improvement" 
pcl5.tot$improvement[pcl5.tot$improvement == -5] <- "Responding to Treatment" 
pcl5.tot$improvement[pcl5.tot$improvement == -6] <- "Responding to Treatment" 
pcl5.tot$improvement[pcl5.tot$improvement == -7] <- "Responding to Treatment" 
pcl5.tot$improvement[pcl5.tot$improvement == -8] <- "Responding to Treatment" 
pcl5.tot$improvement[pcl5.tot$improvement == -9] <- "Responding to Treatment" 
pcl5.tot$improvement[pcl5.tot$improvement >0 & pcl5.tot$improvement <= 80] <- "Increased PTSD Symptoms"    # Replace values in range
pcl5.tot$improvement[pcl5.tot$improvement == -4] <- "No Response" 
pcl5.tot$improvement[pcl5.tot$improvement == -3] <- "No Response" 
pcl5.tot$improvement[pcl5.tot$improvement == -2] <- "No Response" 
pcl5.tot$improvement[pcl5.tot$improvement == -1] <- "No Response" 
pcl5.tot$improvement[pcl5.tot$improvement == -0] <- "No Response" 

pcl5.tot1=pcl5.tot %>% drop_na(`improvement`)

pcl5.tot1$improvement <- factor(pcl5.tot1$improvement, levels = c("Clinical Improvement", "Responding to Treatment", "No Response", "Increased PTSD Symptoms"))

tab1=as.data.frame(table(pcl5.tot1$improvement))
tab1$perc=tab1$Freq/nrow(pcl5.tot1)

tab1.p=ggplot(tab1, aes(x="", y=perc, fill=Var1)) +
  geom_bar(stat="identity", width=1) +
  coord_polar("y", start=0) +
  xlab("") +
  ggtitle("All Reauth & Discharges") +
  geom_text(aes(label = Freq),
            position = position_stack(vjust = 0.5)) +
  ylab("Proportion") 


pcl5.tot2=pcl5.tot %>% drop_na(`Individual Discharge`)
pcl5.tot2$improvement <- factor(pcl5.tot2$improvement, levels = c("Clinical Improvement", "Responding to Treatment", "No Response", "Increased PTSD Symptoms"))


tab2=as.data.frame(table(pcl5.tot2$improvement))
tab2$perc=tab2$Freq/nrow(pcl5.tot2)

tab2.p=ggplot(tab2, aes(x="", y=perc, fill=Var1)) +
  geom_bar(stat="identity", width=1) +
  coord_polar("y", start=0) +
    xlab("") +
  ggtitle("Discharged Only") +
  geom_text(aes(label = Freq),
            position = position_stack(vjust = 0.5)) +
  ylab("Proportion")
  

ggarrange(tab1.p , tab2.p, 
          ncol=2, nrow=1, common.legend = TRUE, legend="bottom") 

Distribution of PCL-5 scores at each timepoint (Baseline, Reauthorization, and Discharge). Color coded dotted lines indicate mean for each group, while shaded regions show density of occurance. The shaded region indicates field accepted scores indicating “probable PTSD”.

### Distribution of scores

mean_baseline2=mean(pcl5.tot$`Individual Baseline`, na.rm=T)
mean_reauth2=mean(pcl5.tot$`Individual Reauthorization`, na.rm = T)
mean_discharge2=mean(pcl5.tot$`Individual Discharge`, na.rm = T)


den.2=ggplot() +
geom_density(aes(`Individual Baseline`, fill="Baseline"), alpha=0.2,  data=pcl5.tot) + 
geom_density(aes(`Individual Reauthorization`, fill="Reauthorization"), alpha=0.2, data=pcl5.tot) + 
  geom_density(aes(`Individual Discharge`, fill="Discharge"), alpha=0.2, data=pcl5.tot) + 
    labs(title="PCL-5", 
         subtitle="Distribution of PTSD Scores",
         x="Score") +
  ylab("Density") +
  annotate('rect', xmin=31, xmax=33, ymin=0, ymax=Inf, alpha=.2, fill='black') +
  geom_vline(xintercept=mean_baseline2, size=1, color="pink", linetype="dotted") +
  geom_vline(xintercept=mean_reauth2, size=1, color="blue",  linetype="dotted") +
  geom_vline(xintercept=mean_discharge2, size=1, color="green",  linetype="dotted")  +
  labs(fill='Timepoint') 

den.2

Interactive Data Table

library(DT)
pcl5.datatable= pcl5.tot
  
datatable(data = pcl5.datatable, width=NULL,  filter = "top", caption= "PHQ-9 Summary Results", rownames=F, colnames = c('Record ID', 'Case ID', 'Baseline Score', 'Reauthorization Score', 'Discharge Score', 'Change in Score', "Improvement Type"),
          options = list(pagelength=25,
  initComplete = JS(
    "function(settings, json) {",
    "$(this.api().table().header()).css({'background-color': 'grey', 'color': '#fff'});",
    "}")))

CD Risc

Purpose and Evaluation

The Connor-Davidson Resillience Scale

Measure of psychological resillience. These ratings result in a number between 0–40, and higher scores indicate higher resilience. The 10 item version comprises items 1, 4, 6, 7, 8, 11, 14, 16, 17, 19 from the original scale, and was developed by Drs. Campbell-Sills and Stein, at the University of California, San Diego, on the basis of factor analysis. In a community survey of 764 US adults, a mean score of 31.8 (SD = 5.4) was obtained for the CD-RISC 10 (Campbell-Sills L, Forde DR, Stein MB. J Psychiatric Research (2009), doi:10.1016/j.jpsychires.2009.01.013). The population quartile scores for the CD-RISC-10 are as follows: 25th % = 29; 50th % = 32; 75th % = 36. An almost identical mean score was obtained by Davidson in the US general population sample studied in the 2003 report above.

Wingo et al (2017) found mean of 23.6 (7.9 SD) in veterans with PTSD and depression

Summary Statistics

cd.risc[cd.risc == "Not at all"] <- "0"
cd.risc[cd.risc == "Rarely True"] <- "1" 
cd.risc[cd.risc == "Sometimes True"] <- "2" 
cd.risc[cd.risc == "Often True"] <- "3" 
cd.risc[cd.risc == "True Nearly all of the Time"] <- "4" 

cd.risc <- cd.risc %>% 
     mutate_at(c(5:14), as.numeric)

cd.risc$total <- as.numeric(apply(cd.risc[,5:14], 1, sum))

cd.risc.tot=subset(cd.risc, select = c(1,2,3,16))
cd.risc.tot=spread(cd.risc.tot, key = `Event Name`, value = total)

cd.risc.tot$`Individual Baseline`=as.numeric(cd.risc.tot$`Individual Baseline`)
cd.risc.tot$`Individual Reauthorization`=as.numeric(cd.risc.tot$`Individual Reauthorization`)
cd.risc.tot$`Individual Discharge`=as.numeric(cd.risc.tot$`Individual Discharge`)

#Calculate change in score between initial and discharge
cd.risc.tot$change=cd.risc.tot$`Individual Discharge`-cd.risc.tot$`Individual Baseline`
#Calculate change in score between initial and reauthorization
cd.risc.tot$change.reauth=cd.risc.tot$`Individual Reauthorization`-cd.risc.tot$`Individual Baseline`

#IF discharge value is available, use it to calculate change. If not, use the reevaluation value to calculate change
#Remove columns used to calculate to only leave column with change value
cd.risc.tot= cd.risc.tot %>% 
    mutate(change = coalesce(change,change.reauth))
cd.risc.tot=subset(cd.risc.tot, select = c(1:6))

This table shows the total sample size available at each timepoint (N) and summary statistics for the CD-RISC scores during Baseline Evaluation, Reathurization, and Discharge.

cd.risc.tot$`Record ID`=as.character(cd.risc.tot$`Record ID`)
sumtable(cd.risc.tot)
Summary Statistics
Variable N Mean Std. Dev. Min Pctl. 25 Pctl. 75 Max
Case ID 216 23911.681 2887.611 2310 22815.25 25374.5 29069
Individual Baseline 214 21.005 7.286 1 17 25.75 40
Individual Reauthorization 37 22.703 9.792 4 16 31 40
Individual Discharge 18 19.444 7.965 8 13.25 23.75 35
change 40 1.55 7.507 -10 -3 5 27

Graphics

Change in Severity Score: When available, this frequency chart shows the distribution of score changes from baseline to discharge. When a discharge score is not yet available, it is the change from baseline to reauthorization.

ggplot(cd.risc.tot, aes(change)) +
  geom_histogram(binwidth=5, color="black", fill= "grey") +
  xlab("Change in Resiliency Score")  +
  ggtitle("Change in Severity Score")

Distribution of CD-RISC scores at each timepoint (Baseline, Reauthorization, and Discharge). Color coded dotted lines indicate mean for each group, while shaded regions show density of occurance. Depression scores of minimal to severe are indicated on chart. The dotted grey line indicates the average CD-RISC score previously found for veterans with PTSD and depression (Wingo et. al, 2017), and the shaded gray box indicates a SD of 7.9 for the same population.

Note: Mean scores for the general public are higher, and the quartiles are as follows: 25th % = 29; 50th % = 32; 75th % = 36.

mean_baseline3=mean(cd.risc.tot$`Individual Baseline`, na.rm = T)
mean_reauth3=mean(cd.risc.tot$`Individual Reauthorization`, na.rm = T)
mean_discharge3=mean(cd.risc.tot$`Individual Discharge`, na.rm = T)

#shaded grey box indicates previous findings of mean +/- SD for veterans with PTSD and Depression
den.3=ggplot() +
geom_density(aes(`Individual Baseline`, fill="Baseline"), alpha=0.2,  data=cd.risc.tot) + 
geom_density(aes(`Individual Reauthorization`, fill="Reauthorization"), alpha=0.2, data=cd.risc.tot) + 
  geom_density(aes(`Individual Discharge`, fill="Discharge"), alpha=0.2, data=cd.risc.tot) + 
    labs(title="CD-RISC", 
         subtitle="Distribution of Resiliency Scores",
         x="Score") +
  ylab("Density") +
     annotate("rect", xmin=15.7, xmax=31.5, ymin=0, ymax=Inf, alpha = .1) +
  geom_vline(xintercept=mean_baseline3, size=1, color="pink", linetype="dotted") +
  geom_vline(xintercept=mean_reauth3, size=1, color="blue",  linetype="dotted") +
  geom_vline(xintercept=mean_discharge3, size=1, color="green",  linetype="dotted") +
  geom_vline(xintercept=23.6, size=1, color="grey",  linetype="dotted") +
  annotate(geom="text", x=26.5, y=0.075, size=3, label="Veterans with PTSD", color="black") +
    annotate(geom="text", x=26.5, y=0.072, size=3, label="and Depression", color="black")+
  annotate(geom="text", x=26.5, y=0.069, size=2, label="(Wingo et. al., 2017)", color="black")  +
  labs(fill='Timepoint') 

den.3

Interactive Data Table

library(DT)
cd.risc.datatable= cd.risc.tot
  
datatable(data = cd.risc.datatable, width=NULL,  filter = "top", caption= "PHQ-9 Summary Results", rownames=F, colnames = c('Record ID', 'Case ID', 'Baseline Score', 'Reauthorization Score', 'Discharge Score', 'Change in Score'),
          options = list(pagelength=25,
  initComplete = JS(
    "function(settings, json) {",
    "$(this.api().table().header()).css({'background-color': 'grey', 'color': '#fff'});",
    "}")))

Summary View

Key Takeaways

  1. As of August 31th 2023, at the aggregate level, none of the three measures are showing signs of clinical improvement, however the PCL-5 PTSD screener is showing response to treatment.
  2. Cumulative data shows non-clinically significant improvements in Depression and Resilience scales.
  3. While sample size is still limited, which is leading to extreme changes in data patterns from month to month, all three measures are now improving over time as we gain additional discharge data (see figure below). However, this should be interpreted carfully, as sample size only increased by 1 individual from July to August, and led to an extermem percent improvement of outcome.

Per Assessment Summary

  • PHQ-9 indicates a decrease in Depression from baseline to both reauthorization and discharge. The mean values at each timepoint remain within the “Moderately Severe” categorization. However, by baseline the score is 14.67, and 14 is considered “Moderate”. Greater than a 1SD change in score (6.05 as of August) is the SSS determination of clinical improvement. The current improvement is at a score of 2.13.
  • PCL-5 improvement of 6.25% or 12.5% would indicate response to treatment or clinical improvement respectively. Centerstone currently reports 9.06% improvement on average between baseline and current levels (discharge when available, reauthorization when discharge as not occurred). While there is a “response to treatment” in PTSD score from baseline to reathorization and discharge, at this time, 16 clients show clinical improvement, 3 are responding to treatment, 8 have no response, and 17 have reported increased PTSD symptoms.
  • CD-Risc indicates that our clients fall within the previously reported range of Resiliency for veterans with PTSD and Depression. Resilience scores decrease from baseline slightly at discharge, while the are improved at measures of reauthorization. Greater than a 1SD change in score (7.29 as of August) is the SSS determination of clinical improvement. The current average score has decreased by 1.55.

Summary Table

Summary data is presented showing how cumulative improvement scores have changed over time. Please note that all data presented is analyzed through the month listed, not within that 30 day period (ex. May data includes all data prior to may, including April).

Changes displayed in negative values for the PHQ-9 and PCL-5 indicate improvement, while a positive value for the CD-Risc indicates improvement.

sumtab= data.frame(
  Month = c("April", "May", "June", "July", "August"),
  N.Anaylzed=c (37, 39, 40, 44, 45),
  N.Discharged=c(10,16, 18, 21, 21),
  PHQ9= c(-1.216, -0.769, -0.85, -1.82, -2.13),
  PCL5=c(-2.833, -2.921, -3.154, -6.116, -7.25),
  CDRisc=c(0.059,-0.086, -0.171, 1.385, 1.55)
)

sumtab$Month=
sumtab$Month <- factor(sumtab$Month, levels=c('April', 'May', 'June', 'July', 'August'))


datatable(data = sumtab, width=NULL,  filter = "top", caption= "Cumulative Results by Month", rownames=F, colnames = c('Month', 'N Analysed', "N Discharged", 'Cumulative PHQ-9', 'Cumulative PCL-5', 'Cumulative CD-Risc'),
          options = list(pagelength=25,
  initComplete = JS(
    "function(settings, json) {",
    "$(this.api().table().header()).css({'background-color': 'grey', 'color': '#fff'});",
    "}")))

Summary Graphics

Graphic depicting the change in improvement over time in percentages.

PHQ-9 and CD-Risc: Clinical improvment is indicated by a greater than 1 standard deviation improvment in scores for the baseline assessment.See “Per Assessment Summary” above for specific values.

PCL-5: Clinical improvement on a per-client basis is considered a minimum of 12.5% improvment in score. Responding to treatment is considered a minimum of 6.25% improvment.

sumtab.perc=sumtab
sumtab.perc$PHQ9.p=sumtab.perc$PHQ9/27*(-100)
sumtab.perc$PCL5.p=sumtab.perc$PCL5/80*(-100)
sumtab.perc$CDRisc.p=sumtab.perc$CDRisc/40*100

percents.long <- gather(sumtab.perc, Assessment, PercImprov, PHQ9.p:CDRisc.p, factor_key=TRUE)

facet_titles <- c(
                    `PHQ9.p` = "PHQ-9: Despression Scale",
                    `PCL5.p` = "PCL-5: PTSD Scale",
                    `CDRisc.p` = "CD-Risc: Resilience Scale"
                    )

perc.pl=ggplot(percents.long, aes(Month, PercImprov), group=Assessment) +                      
  geom_line(aes(group=1), color="green") +
  geom_point(color = "green") +
  ylab("Percent Improvement") +  
  facet_wrap( ~ Assessment, ncol=1, scales = "free", labeller = as_labeller(facet_titles))

ggplotly(perc.pl, tooltip=c("Month", "Assessment", "PercImprov"))
#Graphic depicting the change in improvment over time in raw scores. 

sumtab.long <- gather(sumtab, Assessment, Score, PHQ9:CDRisc, factor_key=TRUE)

facet_titles <- c(
                    `PHQ9` = "PHQ-9 (Improvment indicated by decrease)",
                    `PCL5` = "PCL-5 (Improvment indicated by decrease)",
                    `CDRisc` = "CD-Risc (Improvment indicated by increase)"
                    )

sum.pl1=ggplot(sumtab.long, aes(Month, Score), group=Assessment) +                      
  geom_line(aes(group=1), color="grey") +
  geom_point(color = "grey") +
  facet_wrap( ~ Assessment, ncol=1, scales = "free", labeller = as_labeller(facet_titles))


ggplotly(sum.pl1)
LS0tCnRpdGxlOiAiQ2VudGVyU3RvbmUgQ2xpZW50IEV2YWx1YXRpb24iCmF1dGhvcjogIkFiYnkgQmVhdHR5IgpkYXRlOiAiUmVjdXJyaW5nIEFzc2Vzc21lbnQtIFNlcHRlbWJlciAyMDIzIgpvdXRwdXQ6CiAgaHRtbF9kb2N1bWVudDoKICAgIHRoZW1lOiBzYW5kc3RvbmUKICAgIGNvZGVfZm9sZGluZzogaGlkZQogICAgY29kZV9kb3dubG9hZDogdHJ1ZQotLS0KIyBBc3Nlc3NtZW50cyB7LnRhYnNldH0KYGBge3IgbG9hZCBkYXRhLCBwcmludD1GQUxTRSwgcmVzdWx0cz1GQUxTRSwgZWNobz1GLCB3YXJuaW5nPUZBTFNFLCBtZXNzYWdlPUZBTFNFfQoKbGlicmFyeShnb29nbGVkcml2ZSkgCmxpYnJhcnkocHVycnIpIApsaWJyYXJ5KHJlYWR4bCkKbGlicmFyeShwbG90bHkpCgoKI2RyaXZlX2ZpbmQoKQpmb2xkZXJfdXJsIDwtICJodHRwczovL2RyaXZlLmdvb2dsZS5jb20vZHJpdmUvZm9sZGVycy8xQ2kwZ1hqa2NGa2F2enY1bnZFQ3RmaXFWdXZUVkNmbV8iIAoKI2RyaXZlX2Rvd25sb2FkKCJodHRwczovL2RvY3MuZ29vZ2xlLmNvbS9zcHJlYWRzaGVldHMvZC8xRlpha2pyT09QM1g3RVlzSWJ4aFhXbGRkY3JNU0tBZTkvZWRpdCNnaWQ9MTM3Mzg0OTU5OSIsIG92ZXJ3cml0ZSA9IFQpCgpkYXQ9cmVhZF9leGNlbCgnQ3VtdWxhdGl2ZSBfQXNzZXNzbWVudF9DZW50ZXJzdG9uZS54bHN4JykKCmBgYAoKYGBge3IgcmVuYW1lIHZhcmlhYmxlcywgcHJpbnQ9RkFMU0UsIHJlc3VsdHM9RkFMU0UsIHdhcm5pbmc9RkFMU0UsIG1lc3NhZ2U9RkFMU0UsIGVjaG89Rn0KI1JlbmFtZSBDb21wbGV0ZSBjb2x1bW5zIHRvIGluY2x1ZGUgc3VydmV5IG5hbWUKbGlicmFyeShkcGx5cikKCmRhdD1kYXQgJT4lIAogICAgcmVuYW1lKCJWZXRzLjEyLkNvbXBsZXRlIiA9ICJDb21wbGV0ZT8uLi4xOSIsCiAgICAgICAgICAgIlBIUTkuQ29tcGxldGUiPSJDb21wbGV0ZT8uLi4zMiIsCiAgICAgICAgICAgIlBDTDUuQ29tcGxldGUiID0gIkNvbXBsZXRlPy4uLjU1IiwKICAgICAgICAgICAiQ0QuUklTQy5Db21wbGV0ZSI9IkNvbXBsZXRlPy4uLjY3IiwKICAgICAgICAgICAiVmV0cy4xMi5UaW1lc3RhbXAiPSJWZXRlcmFucyBSYW5kIDEyIEl0ZW0gSGVhbHRoIFN1cnZleS1TdXJ2ZXkgVGltZXN0YW1wIiwKICAgICAgICAgICAiUEhROS5UaW1lc3RhbXAiID0gIlBIUS0gOSBTdXJ2ZXkgVGltZXN0YW1wIiwKICAgICAgICAgICAiUENMNS5UaW1lc3RhbXAiID0gIlBDTCA1LSBTdXJ2ZXkgVGltZXN0YW1wIiwKICAgICAgICAgICAiQ0QuUklTQy5UaW1lc3RhbXAiPSJDRC0gUklTQyBTdXJ2ZXkgVGltZXN0YW1wIiwKICAgICAgICAgICAiUEhROS5Ub3RhbCIgPSAiVG90YWwgU2NvcmUgb2YgUXVlc3Rpb25zIDEtOToiLAogICAgICAgICAgICJQQ0w1LlRvdGFsIiA9ICJUb3RhbCBTY29yZTombmJzcDsiKQoKZGF0JGBFdmVudCBOYW1lYCA8LSBmYWN0b3IoZGF0JGBFdmVudCBOYW1lYCwgbGV2ZWxzPWMoJ0luZGl2aWR1YWwgQmFzZWxpbmUnLCAnSW5kaXZpZHVhbCBSZWF1dGhvcml6YXRpb24nLCAnSW5kaXZpZHVhbCBEaXNjaGFyZ2UnKSkKCmBgYAoKCmBgYHtyIHNlcGVyYXRlIGFzc2Vzc21lbnRzLCBwcmludD1GQUxTRSwgcmVzdWx0cz1GQUxTRSwgd2FybmluZz1GQUxTRSwgZWNobz1GQUxTRSwgbWVzc2FnZT1GQUxTRX0KCiNTZXBhcmF0ZSBvdXQgYWxsIGFzc2Vzc21lbnRzCiNSZW1vdmUgYWxsIGluc3RhbmNlcyBpbiB3aGljaCAiQ29tcGxldGUiIGlzIG5vdCB0cnVlCgojVmV0ZXJhbnMgMTIgUmFuZG9tIAp2ZXRzLjEyPXN1YnNldChkYXQsIHNlbGVjdCA9IGMoMSwgMiwgMywgNDoxOSkpCnZldHMuMTI9c3Vic2V0KHZldHMuMTIsIFZldHMuMTIuQ29tcGxldGUgPT0gIkNvbXBsZXRlIikKI1BIUTkKcGhxOT1zdWJzZXQoZGF0LCBzZWxlY3QgPSBjKDEsIDIsIDMsIDIwOjMyKSkKcGhxOT1zdWJzZXQocGhxOSwgUEhROS5Db21wbGV0ZSA9PSAiQ29tcGxldGUiKQojUENMNQpwY2w1PXN1YnNldChkYXQsIHNlbGVjdCA9IGMoMSwgMiwgMywgMzM6NTUpKQpwY2w1PXN1YnNldChwY2w1LCBQQ0w1LkNvbXBsZXRlID09ICJDb21wbGV0ZSIpCiNDRCBSSVNDCmNkLnJpc2M9c3Vic2V0KGRhdCwgc2VsZWN0ID0gYygxLCAyLCAzLCA1Njo2NiwgNjcpKQpjZC5yaXNjPXN1YnNldChjZC5yaXNjLCBDRC5SSVNDLkNvbXBsZXRlID09ICJDb21wbGV0ZSIpCgoKYGBgCgojIyBQSFEtOSB7LnRhYnNldH0KCiMjIyBQdXJwb3NlICYgRXZhbHVhdGlvbiA6IAoKPlRoZSBQSFEtOSBpcyBhICJTZWxmLWFkbWluaXN0ZXJlZCA5LWl0ZW0gaW5zdHJ1bWVudCBiYXNlZCBvbiB0aGUgbmluZSBEU00tViBjcml0ZXJpYSBsaXN0ZWQgdW5kZXIgY3JpdGVyaW9uIEEgZm9yIE1ham9yIERlcHJlc3NpdmUgRGlzb3JkZXIuICBUaGUgaW5zdHJ1bWVudCBhaWRzIGluIGd1aWRpbmcgY3JpdGVyaWEgYmFzZWQgZGlhZ25vc2lzIG9mIGRlcHJlc3NpdmUgc3ltcHRvbXMsIGNhbiBhc3Npc3QgaW4gaWRlbnRpZnlpbmcgdHJlYXRtZW50IGdvYWxzLCBkZXRlcm1pbmluZyBzZXZlcml0eSBvZiBzeW1wdG9tcywgYXMgd2VsbCBhcyBndWlkaW5nIGNsaW5pY2FsIGludGVydmVudGlvbiAoW1ZBLmdvdl0oaHR0cHM6Ly93d3cubWlyZWNjLnZhLmdvdi9jaWgtdmlzbjIvRG9jdW1lbnRzL0NsaW5pY2FsL1BIUTlfd2l0aF9JbmZvX1NoZWV0LnBkZikpLiIKCj5UaGUgUEhRLTkgd2FzIGV2YWx1YXRlZCBhcyBhIHBhdGllbnQtcmVwb3J0ZWQgb3V0Y29tZSBtZWFzdXJlcyBpbiB2ZXRlcmFucyBieSBbS2F0eiBldC4gYWwuICgyMDIxKV0oaHR0cHM6Ly9wdWJtZWQubmNiaS5ubG0ubmloLmdvdi8zNDM3ODUzOC8pLiBUaGV5IGZvdW5kIHRoYXQgInRoZSBQSFEtOSBmdW5jdGlvbnMgbW9yZSBhcyBhIGdlbmVyYWwgbWVhc3VyZSBvZiBzeW1wdG9tcyBvciBkaXN0cmVzcyB0aGFuIGFzIGEgZGlzZWFzZS1zcGVjaWZpYyBzY2FsZS4gVGhpcyBzdXBwb3J0cyBpdHMgdXNlIGFzIGEgUFJPTSBmb3IgcGF0aWVudHMgYmV5b25kIHRob3NlIHdpdGggbWFqb3IgZGVwcmVzc2lvbiwgaW5jbHVkaW5nIHRob3NlIHdpdGggcmVsYXRlZCBkaWFnbm9zZXMgYW5kIHRob3NlIHdpdGggY29tb3JiaWRpdGllcywgYW5kIHVzZSBvZiByZWxhdGVkIFBST00tUE1zIGluIGNsaW5pY2FsIHNldHRpbmdzIHdoZXJlIGRpYWdub3NlcyBtYXkgbm90IGJlIHByZWNpc2UgYW5kIGNvbW9yYmlkaXRpZXMgbWF5IGJlIGNvbW1vbi4iCgo+IFJlY29tbWVuZGF0aW9ucyBmb3IgZGVwcmVzc2lvbiBzZXZlcml0eSBhbmQgcXVlc3Rpb25zIGFzc29jaWF0ZWQgd2l0aCB0aGUgc2NhbGUgY2FuIGJlIGZvdW5kIGF0OiBodHRwczovL21lZC5zdGFuZm9yZC5lZHUvZmFzdGxhYi9yZXNlYXJjaC9pbWFwcC9tc3JzL19qY3JfY29udGVudC9tYWluL2FjY29yZGlvbi9hY2NvcmRpb25fY29udGVudDMvZG93bmxvYWRfMjU2MzI0Mjk2L2ZpbGUucmVzL1BIUTklMjBpZCUyMGRhdGUlMjAwOC4wMy5wZGYKCnxTZXZlcml0eSB8IFNjb3JlIHwKfC0tLS0tLS0tLXwtLS0tLS0tfAp8IE1pbmltYWwgRGVwcmVzc2lvbiB8IDAtNCB8CnwgTWlsZCBEZXByZXNzaW9uIHwgNS05IHwKfCBNb2RlcmF0ZSBEZXByZXNzaW9uIHwgMTAtMTQgfAp8IE1vZGVyYXRlbHkgU2V2ZXJlIERlcHJlc3Npb24gfCAxNS0xOSB8CnwgU2V2ZXJlIERlcHJlc3Npb24gfCAyMC0yNyB8CgpgYGB7ciwgcHJpbnQ9RkFMU0UsIHJlc3VsdHM9RkFMU0UsIHdhcm5pbmc9RkFMU0UsIG1lc3NhZ2U9RkFMU0V9CmhlYWQocGhxOSkKI0tlZXAgb25seSBpZGVudGlmaWVyIGNvbHVtbnMgYW5kIHRoZSBQSFEtOSB0b3RhbCBzY29yZSBjb2x1bW5zCnBocTkuY2hhbmdlPXN1YnNldChwaHE5LCBzZWxlY3QgPSBjKDEsMiwzLDE0KSkKCmxpYnJhcnkodGlkeXIpCiNDaGFuZ2UgZnJvbSBsb25nIHRvIHdpZGUgZm9ybWF0CnBocTkuY2hhbmdlPXNwcmVhZChwaHE5LmNoYW5nZSwga2V5ID0gYEV2ZW50IE5hbWVgLCB2YWx1ZSA9IGBQSFE5LlRvdGFsYCkKI1Nhbml0eSBjaGVjazogSWYgdGhpcyBjb21lcyBiYWNrIGFzIGZhbHNlLCBuZWVkIHRvIGdvIGJhY2sgdG8gZXhjZWwgc2hlZXQgYW5kIGNvcnJlY3QgcmVjb3JkIElEIHdoZXJlIENhc2UgSUQgaXMgbmFtZSBmb3Igc29tZSBhbmQgbnVtZXJpYyBmb3Igb3RoZXJzCm5fb2NjdXIgPC0gZGF0YS5mcmFtZSh0YWJsZShwaHE5LmNoYW5nZSRgUmVjb3JkIElEYCkpCm5fb2NjdXJbbl9vY2N1ciRGcmVxID4gMSxdCgojUmVvcmRlciBjb2x1bW5zIHRvIG1hdGNoIG9yZGVyIG9mIGFzc2Vzc21lbnRzCnBocTkuY2hhbmdlIDwtIHBocTkuY2hhbmdlWywgYygxLDIsMywgNSwgNCldCgpsaWJyYXJ5KCd0aWR5dmVyc2UnKQojQ2FsY3VsYXRlIGNoYW5nZSBpbiBzY29yZSBiZXR3ZWVuIGluaXRpYWwgYW5kIGRpc2NoYXJnZQpwaHE5LmNoYW5nZSRjaGFuZ2U9cGhxOS5jaGFuZ2UkYEluZGl2aWR1YWwgRGlzY2hhcmdlYC1waHE5LmNoYW5nZSRgSW5kaXZpZHVhbCBCYXNlbGluZWAKI0NhbGN1bGF0ZSBjaGFuZ2UgaW4gc2NvcmUgYmV0d2VlbiBpbml0aWFsIGFuZCByZWF1dGhvcml6YXRpb24KcGhxOS5jaGFuZ2UkY2hhbmdlLnJlYXV0aD1waHE5LmNoYW5nZSRgSW5kaXZpZHVhbCBSZWF1dGhvcml6YXRpb25gLXBocTkuY2hhbmdlJGBJbmRpdmlkdWFsIEJhc2VsaW5lYAoKI0lGIGRpc2NoYXJnZSB2YWx1ZSBpcyBhdmFpbGFibGUsIHVzZSBpdCB0byBjYWxjdWxhdGUgY2hhbmdlLiBJZiBub3QsIHVzZSB0aGUgcmVldmFsdWF0aW9uIHZhbHVlIHRvIGNhbGN1bGF0ZSBjaGFuZ2UKI1JlbW92ZSBjb2x1bW5zIHVzZWQgdG8gY2FsY3VsYXRlIHRvIG9ubHkgbGVhdmUgY29sdW1uIHdpdGggY2hhbmdlIHZhbHVlCnBocTkuY2hhbmdlPSBwaHE5LmNoYW5nZSAlPiUgCiAgICBtdXRhdGUoY2hhbmdlID0gY29hbGVzY2UoY2hhbmdlLGNoYW5nZS5yZWF1dGgpKQpwaHE5LmNoYW5nZT1zdWJzZXQocGhxOS5jaGFuZ2UsIHNlbGVjdCA9IGMoMTo2KSkKCgpwaHE5LmNoYW5nZSRpbXByb3ZlbWVudD1waHE5LmNoYW5nZSRjaGFuZ2UKcGhxOS5jaGFuZ2UkaW1wcm92ZW1lbnRbcGhxOS5jaGFuZ2UkaW1wcm92ZW1lbnQgPj0gMF0gPC0gIkZBTFNFIiAKcGhxOS5jaGFuZ2UkaW1wcm92ZW1lbnRbcGhxOS5jaGFuZ2UkaW1wcm92ZW1lbnQgPCAwXSA8LSAiVFJVRSIgCgptZWFuX2Jhc2VsaW5lPW1lYW4ocGhxOS5jaGFuZ2UkYEluZGl2aWR1YWwgQmFzZWxpbmVgLCBuYS5ybT1UKQptZWFuX3JlYXV0aD1tZWFuKHBocTkuY2hhbmdlJGBJbmRpdmlkdWFsIFJlYXV0aG9yaXphdGlvbmAsIG5hLnJtID0gVCkKbWVhbl9kaXNjaGFyZ2U9bWVhbihwaHE5LmNoYW5nZSRgSW5kaXZpZHVhbCBEaXNjaGFyZ2VgLCBuYS5ybSA9IFQpCgpgYGAKIyMjIFN1bW1hcnkgU3RhdGlzdGljcyAKCj5UaGlzIHRhYmxlIHNob3dzIHRoZSB0b3RhbCBzYW1wbGUgc2l6ZSBhdmFpbGFibGUgYXQgZWFjaCB0aW1lcG9pbnQgKE4pIGFuZCBzdW1tYXJ5IHN0YXRpc3RpY3MgZm9yIHRoZSBQSFE5IHNjb3JlcyBkdXJpbmcgQmFzZWxpbmUgRXZhbHVhdGlvbiwgUmVhdGh1cml6YXRpb24sIGFuZCBEaXNjaGFyZ2UuIEFkZGl0aW9uYWxseSwgaXQgc2hvd3MgdGhlIHN1bW1hcnkgc3RhdGlzdGljcyBmb3Igc2NvcmUgY2hhbmdlcyBiZXR3ZWVuIGJhc2VsaW5lIGFuZCBkaXNjaGFyZ2UsIG9yIHJlYXV0aG9yaXphdGlvbiB3aGVuIGRpc2NoYXJnZSBoYXMgbm90IG9jY3VycmVkLiBUaGUgYnJlYWtkb3duIG9mICJpbXByb3ZlbWVudCIgc2hvd3MgdGhlIG51bWJlciBvZiBpbmRpdmlkdWFscyB3aG9zIFBIUTkgc2NvcmUgZGlkIGFuZCBkaWQgbm90IGltcHJvdmUgZHVyaW5nIHRoYXQgdGltZS4gCgpgYGB7ciwgcHJpbnQ9RkFMU0UsIHJlc3VsdHM9RkFMU0UsIHdhcm5pbmc9RkFMU0UsIG1lc3NhZ2U9RkFMU0V9CmxpYnJhcnkodnRhYmxlKQpwaHE5LmNoYW5nZSRgUmVjb3JkIElEYD1hcy5jaGFyYWN0ZXIocGhxOS5jaGFuZ2UkYFJlY29yZCBJRGApCiNQcmludCB0YWJsZSBzdGF0aXN0aWNzIGluIFIgTWFya2Rvd24KCgpgYGAKCmBgYHtyfQpzdW10YWJsZShwaHE5LmNoYW5nZSwgdmFycyA9IGMoJ0luZGl2aWR1YWwgQmFzZWxpbmUnLCdJbmRpdmlkdWFsIFJlYXV0aG9yaXphdGlvbicsICdJbmRpdmlkdWFsIERpc2NoYXJnZScsICdjaGFuZ2UnLCAnaW1wcm92ZW1lbnQnKSkKYGBgCgojIyMgR3JhcGhpY3MgCj5DaGFuZ2UgaW4gU2V2ZXJpdHkgU2NvcmU6IFdoZW4gYXZhaWxhYmxlLCB0aGlzIGZyZXF1ZW5jeSBjaGFydCBzaG93cyB0aGUgZGlzdHJpYnV0aW9uIG9mIHNjb3JlIGNoYW5nZXMgZnJvbSBiYXNlbGluZSB0byBkaXNjaGFyZ2UuIFdoZW4gYSBkaXNjaGFyZ2Ugc2NvcmUgaXMgbm90IHlldCBhdmFpbGFibGUsIGl0IGlzIHRoZSBjaGFuZ2UgZnJvbSBiYXNlbGluZSB0byByZWF1dGhvcml6YXRpb24uIAoKYGBge3IsIHByaW50PUZBTFNFLCByZXN1bHRzPUZBTFNFLCB3YXJuaW5nPUZBTFNFLCBtZXNzYWdlPUZBTFNFfQojIyMgSGlzdG9ncmFtIHNob3dpbmcgY2hhbmdlIGluIHNjb3JlcyBvdmVyIHRpbWUuIAoKZ2dwbG90KHBocTkuY2hhbmdlLCBhZXMoY2hhbmdlKSkgKwogIGdlb21faGlzdG9ncmFtKGJpbndpZHRoPTUsIGNvbG9yPSJibGFjayIsIGZpbGw9ICJncmV5IikgKwogIHhsYWIoIkNoYW5nZSBpbiBEZXByZXNzaW9uIFNjb3JlIikgICsKICBnZ3RpdGxlKCJDaGFuZ2UgaW4gU2V2ZXJpdHkgU2NvcmUiKQpgYGAKCj5EaXN0cmlidXRpb24gb2YgUEhROSBzY29yZXMgYXQgZWFjaCB0aW1lcG9pbnQgKEJhc2VsaW5lLCBSZWF1dGhvcml6YXRpb24sIGFuZCBEaXNjaGFyZ2UpLiBDb2xvciBjb2RlZCBkb3R0ZWQgbGluZXMgaW5kaWNhdGUgbWVhbiBmb3IgZWFjaCBncm91cCwgd2hpbGUgc2hhZGVkIHJlZ2lvbnMgc2hvdyBkZW5zaXR5IG9mIG9jY3VyYW5jZS4gRGVwcmVzc2lvbiBzY29yZXMgb2YgbWluaW1hbCB0byBzZXZlcmUgYXJlIGluZGljYXRlZCBvbiBjaGFydC4gIAoKYGBge3IsIHByaW50PUZBTFNFLCByZXN1bHRzPUZBTFNFLCB3YXJuaW5nPUZBTFNFLCBtZXNzYWdlPUZBTFNFfQojIyMgRGlzdHJpYnV0aW9uIG9mIHNjb3JlcwoKZGVuLjE9Z2dwbG90KCkgKwpnZW9tX2RlbnNpdHkoYWVzKGBJbmRpdmlkdWFsIEJhc2VsaW5lYCwgZmlsbD0iQmFzZWxpbmUiKSwgYWxwaGE9MC4yLCAgZGF0YT1waHE5LmNoYW5nZSkgKyAKZ2VvbV9kZW5zaXR5KGFlcyhgSW5kaXZpZHVhbCBSZWF1dGhvcml6YXRpb25gLCBmaWxsPSJSZWF1dGhvcml6YXRpb24iKSwgYWxwaGE9MC4yLCBkYXRhPXBocTkuY2hhbmdlKSArIAogIGdlb21fZGVuc2l0eShhZXMoYEluZGl2aWR1YWwgRGlzY2hhcmdlYCwgZmlsbD0iRGlzY2hhcmdlIiksIGFscGhhPTAuMiwgZGF0YT1waHE5LmNoYW5nZSkgKyAKICAgIGxhYnModGl0bGU9IlBIUS05IiwgCiAgICAgICAgIHN1YnRpdGxlPSJEaXN0cmlidXRpb24gb2YgRGVwcmVzc2lvbiBTY29yZXMiLAogICAgICAgICB4PSJTY29yZSIpICsKICBnZW9tX3ZsaW5lKHhpbnRlcmNlcHQ9bWVhbl9iYXNlbGluZSwgc2l6ZT0xLCBjb2xvcj0icGluayIsIGxpbmV0eXBlPSJkb3R0ZWQiKSArCiAgZ2VvbV92bGluZSh4aW50ZXJjZXB0PW1lYW5fcmVhdXRoLCBzaXplPTEsIGNvbG9yPSJibHVlIiwgIGxpbmV0eXBlPSJkb3R0ZWQiKSArCiAgZ2VvbV92bGluZSh4aW50ZXJjZXB0PW1lYW5fZGlzY2hhcmdlLCBzaXplPTEsIGNvbG9yPSJncmVlbiIsICBsaW5ldHlwZT0iZG90dGVkIikgKwogICBnZW9tX3ZsaW5lKHhpbnRlcmNlcHQ9NC4xLCBzaXplPTAuNSwgY29sb3I9ImJsYWNrIiwgIGxpbmV0eXBlPSJkb3R0ZWQiKSArCiBnZW9tX3ZsaW5lKHhpbnRlcmNlcHQ9OS4xLCBzaXplPTAuNSwgY29sb3I9ImJsYWNrIiwgIGxpbmV0eXBlPSJkb3R0ZWQiKSArCiAgZ2VvbV92bGluZSh4aW50ZXJjZXB0PTE0LjEsIHNpemU9MC41LCBjb2xvcj0iYmxhY2siLCAgbGluZXR5cGU9ImRvdHRlZCIpICsKICAgZ2VvbV92bGluZSh4aW50ZXJjZXB0PTE5LjEsIHNpemU9MC41LCBjb2xvcj0iYmxhY2siLCAgbGluZXR5cGU9ImRvdHRlZCIpICsKICBhbm5vdGF0ZShnZW9tPSJ0ZXh0IiwgeD0yLCB5PTAuMDc1LCBsYWJlbD0iTWluaW1hbCIsIGNvbG9yPSJibGFjayIpKwogIGFubm90YXRlKGdlb209InRleHQiLCB4PTcsIHk9MC4wNzUsIGxhYmVsPSJNaWxkIiwgY29sb3I9ImJsYWNrIikrCiAgYW5ub3RhdGUoZ2VvbT0idGV4dCIsIHg9MTIsIHk9MC4wNzUsIGxhYmVsPSJNb2RlcmF0ZSIsIGNvbG9yPSJibGFjayIpKwogIGFubm90YXRlKGdlb209InRleHQiLCB4PTE3LCB5PTAuMDc1LCBsYWJlbD0iTW9kLiBTZXZlcmUiLCBjb2xvcj0iYmxhY2siKSsKICBhbm5vdGF0ZShnZW9tPSJ0ZXh0IiwgeD0yMywgeT0wLjA3NSwgbGFiZWw9IlNldmVyZSIsIGNvbG9yPSJibGFjayIpICsKICB5bGFiKCJEZW5zaXR5IikgKwogIGxhYnMoZmlsbD0nVGltZXBvaW50JykgCmBgYAoKCmBgYHtyLCB3YXJuaW5nPUZ9CmRlbi4xCmBgYAoKPiBGbG93IG9mIGNsaWVudCBzY29yZXMgYmV0d2VlbiBkZXByZXNzaW9uIHNldmVyaXR5IHNjb3JlcyBiZXR3ZWVuIEJhc2xlbGluZSBhbmQgRGlzY2hhcmdlLCBvciBSZWF1dGhvcml6YXRpb24gd2hlbiBEaXNjaGFyZ2Ugc2NvcmVzIGFyZSBub3QgeWV0IGF2YWlsYWJsZS4gVGhlIGxlZnQgaGFuZCBjb2xvdW1uIHNob3dzIHRoZSBkaXN0cmlidXRpb24gb2Ygc2NvcmVzIGFtb25nIHNldmVyaXR5IGNhdGVnb3JpZXMgYXQgIkJhc2VsaW5lIi4gRm9sbG93aW5nIHRoZSBjb2xvciBjb2RlZCBzZWN0aW9ucyB0byB0aGUgIkN1cnJlbnQiIGNvbHVtbiBkaXNwbGF5cyB0aGUgcHJvcG9ydGlvbiBvZiBjbGllbnRzIGF0IGVhY2ggc3RhcnRpbmcgYmFzZWxpbmUgY2F0ZWdvcnkgdnMgdGhlaXIgY3VycmVudCBzZXZlcml0eSByYXRpbmcuICAKCmBgYHtyLCBwcmludD1GQUxTRSwgcmVzdWx0cz1GQUxTRSwgd2FybmluZz1GQUxTRSwgbWVzc2FnZT1GQUxTRX0KI0NyZWF0ZSBhIGNvbHVtbiB3aXRoIGRpc2sgbGV2ZWwgY2F0ZWdvcmllcyBpbnN0ZWFkIG9mIG51bWJlcnMsIHRoZW4gZGVzY3JpYmUgaW1wcm92ZW1lbnQgYmFzZWQgb24gY2F0ZWdvcmljYWwgY2hhbmdlcwpwaHE5LmNoYW5nZSRyaXNrLmxldmVsLmluaXQ9cGhxOS5jaGFuZ2UkYEluZGl2aWR1YWwgQmFzZWxpbmVgCgpwaHE5LmNoYW5nZSRyaXNrLmxldmVsLmluaXRbcGhxOS5jaGFuZ2Ukcmlzay5sZXZlbC5pbml0ID4gMTldIDwtICJTZXZlcmUiIApwaHE5LmNoYW5nZSRyaXNrLmxldmVsLmluaXRbcGhxOS5jaGFuZ2Ukcmlzay5sZXZlbC5pbml0ID09IDFdIDwtICJNaW5pbWFsIiAKcGhxOS5jaGFuZ2Ukcmlzay5sZXZlbC5pbml0W3BocTkuY2hhbmdlJHJpc2subGV2ZWwuaW5pdCA9PSAyXSA8LSAiTWluaW1hbCIgCnBocTkuY2hhbmdlJHJpc2subGV2ZWwuaW5pdFtwaHE5LmNoYW5nZSRyaXNrLmxldmVsLmluaXQgPT0gM10gPC0gIk1pbmltYWwiIApwaHE5LmNoYW5nZSRyaXNrLmxldmVsLmluaXRbcGhxOS5jaGFuZ2Ukcmlzay5sZXZlbC5pbml0ID09IDRdIDwtICJNaW5pbWFsIiAKcGhxOS5jaGFuZ2Ukcmlzay5sZXZlbC5pbml0W3BocTkuY2hhbmdlJHJpc2subGV2ZWwuaW5pdCA9PSA1XSA8LSAiTWlsZCIgCnBocTkuY2hhbmdlJHJpc2subGV2ZWwuaW5pdFtwaHE5LmNoYW5nZSRyaXNrLmxldmVsLmluaXQgPT0gNl0gPC0gIk1pbGQiIApwaHE5LmNoYW5nZSRyaXNrLmxldmVsLmluaXRbcGhxOS5jaGFuZ2Ukcmlzay5sZXZlbC5pbml0ID09IDddIDwtICJNaWxkIiAKcGhxOS5jaGFuZ2Ukcmlzay5sZXZlbC5pbml0W3BocTkuY2hhbmdlJHJpc2subGV2ZWwuaW5pdCA9PSA4XSA8LSAiTWlsZCIgCnBocTkuY2hhbmdlJHJpc2subGV2ZWwuaW5pdFtwaHE5LmNoYW5nZSRyaXNrLmxldmVsLmluaXQgPT0gOV0gPC0gIk1pbGQiIApwaHE5LmNoYW5nZSRyaXNrLmxldmVsLmluaXRbcGhxOS5jaGFuZ2Ukcmlzay5sZXZlbC5pbml0ID09IDEwXSA8LSAiTW9kZXJhdGUiIApwaHE5LmNoYW5nZSRyaXNrLmxldmVsLmluaXRbcGhxOS5jaGFuZ2Ukcmlzay5sZXZlbC5pbml0ID09IDExXSA8LSAiTW9kZXJhdGUiIApwaHE5LmNoYW5nZSRyaXNrLmxldmVsLmluaXRbcGhxOS5jaGFuZ2Ukcmlzay5sZXZlbC5pbml0ID09IDEyXSA8LSAiTW9kZXJhdGUiIApwaHE5LmNoYW5nZSRyaXNrLmxldmVsLmluaXRbcGhxOS5jaGFuZ2Ukcmlzay5sZXZlbC5pbml0ID09IDEzXSA8LSAiTW9kZXJhdGUiIApwaHE5LmNoYW5nZSRyaXNrLmxldmVsLmluaXRbcGhxOS5jaGFuZ2Ukcmlzay5sZXZlbC5pbml0ID09IDE0XSA8LSAiTW9kZXJhdGUiIApwaHE5LmNoYW5nZSRyaXNrLmxldmVsLmluaXRbcGhxOS5jaGFuZ2Ukcmlzay5sZXZlbC5pbml0ID09IDE1XSA8LSAiTW9kZXJhdGVseSBTZXZlcmUiIApwaHE5LmNoYW5nZSRyaXNrLmxldmVsLmluaXRbcGhxOS5jaGFuZ2Ukcmlzay5sZXZlbC5pbml0ID09IDE2XSA8LSAiTW9kZXJhdGVseSBTZXZlcmUiIApwaHE5LmNoYW5nZSRyaXNrLmxldmVsLmluaXRbcGhxOS5jaGFuZ2Ukcmlzay5sZXZlbC5pbml0ID09IDE3XSA8LSAiTW9kZXJhdGVseSBTZXZlcmUiIApwaHE5LmNoYW5nZSRyaXNrLmxldmVsLmluaXRbcGhxOS5jaGFuZ2Ukcmlzay5sZXZlbC5pbml0ID09IDE4XSA8LSAiTW9kZXJhdGVseSBTZXZlcmUiIApwaHE5LmNoYW5nZSRyaXNrLmxldmVsLmluaXRbcGhxOS5jaGFuZ2Ukcmlzay5sZXZlbC5pbml0ID09IDE5XSA8LSAiTW9kZXJhdGVseSBTZXZlcmUiIAoKcGhxOS5jaGFuZ2Ukcmlzay5sZXZlbC5yZWF1dGg9cGhxOS5jaGFuZ2UkYEluZGl2aWR1YWwgUmVhdXRob3JpemF0aW9uYAoKcGhxOS5jaGFuZ2Ukcmlzay5sZXZlbC5yZWF1dGhbcGhxOS5jaGFuZ2Ukcmlzay5sZXZlbC5yZWF1dGggPiAxOV0gPC0gIlNldmVyZSIgCnBocTkuY2hhbmdlJHJpc2subGV2ZWwucmVhdXRoW3BocTkuY2hhbmdlJHJpc2subGV2ZWwucmVhdXRoID09IDFdIDwtICJNaW5pbWFsIiAKcGhxOS5jaGFuZ2Ukcmlzay5sZXZlbC5yZWF1dGhbcGhxOS5jaGFuZ2Ukcmlzay5sZXZlbC5yZWF1dGggPT0gMl0gPC0gIk1pbmltYWwiIApwaHE5LmNoYW5nZSRyaXNrLmxldmVsLnJlYXV0aFtwaHE5LmNoYW5nZSRyaXNrLmxldmVsLnJlYXV0aCA9PSAzXSA8LSAiTWluaW1hbCIgCnBocTkuY2hhbmdlJHJpc2subGV2ZWwucmVhdXRoW3BocTkuY2hhbmdlJHJpc2subGV2ZWwucmVhdXRoID09IDRdIDwtICJNaW5pbWFsIiAKcGhxOS5jaGFuZ2Ukcmlzay5sZXZlbC5yZWF1dGhbcGhxOS5jaGFuZ2Ukcmlzay5sZXZlbC5yZWF1dGggPT0gNV0gPC0gIk1pbGQiIApwaHE5LmNoYW5nZSRyaXNrLmxldmVsLnJlYXV0aFtwaHE5LmNoYW5nZSRyaXNrLmxldmVsLnJlYXV0aCA9PSA2XSA8LSAiTWlsZCIgCnBocTkuY2hhbmdlJHJpc2subGV2ZWwucmVhdXRoW3BocTkuY2hhbmdlJHJpc2subGV2ZWwucmVhdXRoID09IDddIDwtICJNaWxkIiAKcGhxOS5jaGFuZ2Ukcmlzay5sZXZlbC5yZWF1dGhbcGhxOS5jaGFuZ2Ukcmlzay5sZXZlbC5yZWF1dGggPT0gOF0gPC0gIk1pbGQiIApwaHE5LmNoYW5nZSRyaXNrLmxldmVsLnJlYXV0aFtwaHE5LmNoYW5nZSRyaXNrLmxldmVsLnJlYXV0aCA9PSA5XSA8LSAiTWlsZCIgCnBocTkuY2hhbmdlJHJpc2subGV2ZWwucmVhdXRoW3BocTkuY2hhbmdlJHJpc2subGV2ZWwucmVhdXRoID09IDEwXSA8LSAiTW9kZXJhdGUiIApwaHE5LmNoYW5nZSRyaXNrLmxldmVsLnJlYXV0aFtwaHE5LmNoYW5nZSRyaXNrLmxldmVsLnJlYXV0aCA9PSAxMV0gPC0gIk1vZGVyYXRlIiAKcGhxOS5jaGFuZ2Ukcmlzay5sZXZlbC5yZWF1dGhbcGhxOS5jaGFuZ2Ukcmlzay5sZXZlbC5yZWF1dGggPT0gMTJdIDwtICJNb2RlcmF0ZSIgCnBocTkuY2hhbmdlJHJpc2subGV2ZWwucmVhdXRoW3BocTkuY2hhbmdlJHJpc2subGV2ZWwucmVhdXRoID09IDEzXSA8LSAiTW9kZXJhdGUiIApwaHE5LmNoYW5nZSRyaXNrLmxldmVsLnJlYXV0aFtwaHE5LmNoYW5nZSRyaXNrLmxldmVsLnJlYXV0aCA9PSAxNF0gPC0gIk1vZGVyYXRlIiAKcGhxOS5jaGFuZ2Ukcmlzay5sZXZlbC5yZWF1dGhbcGhxOS5jaGFuZ2Ukcmlzay5sZXZlbC5yZWF1dGggPT0gMTVdIDwtICJNb2RlcmF0ZWx5IFNldmVyZSIgCnBocTkuY2hhbmdlJHJpc2subGV2ZWwucmVhdXRoW3BocTkuY2hhbmdlJHJpc2subGV2ZWwucmVhdXRoID09IDE2XSA8LSAiTW9kZXJhdGVseSBTZXZlcmUiIApwaHE5LmNoYW5nZSRyaXNrLmxldmVsLnJlYXV0aFtwaHE5LmNoYW5nZSRyaXNrLmxldmVsLnJlYXV0aCA9PSAxN10gPC0gIk1vZGVyYXRlbHkgU2V2ZXJlIiAKcGhxOS5jaGFuZ2Ukcmlzay5sZXZlbC5yZWF1dGhbcGhxOS5jaGFuZ2Ukcmlzay5sZXZlbC5yZWF1dGggPT0gMThdIDwtICJNb2RlcmF0ZWx5IFNldmVyZSIgCnBocTkuY2hhbmdlJHJpc2subGV2ZWwucmVhdXRoW3BocTkuY2hhbmdlJHJpc2subGV2ZWwucmVhdXRoID09IDE5XSA8LSAiTW9kZXJhdGVseSBTZXZlcmUiIAoKcGhxOS5jaGFuZ2Ukcmlzay5sZXZlbC5kaXNjaGFyZ2U9cGhxOS5jaGFuZ2UkYEluZGl2aWR1YWwgRGlzY2hhcmdlYAoKcGhxOS5jaGFuZ2Ukcmlzay5sZXZlbC5kaXNjaGFyZ2VbcGhxOS5jaGFuZ2Ukcmlzay5sZXZlbC5kaXNjaGFyZ2UgPiAxOV0gPC0gIlNldmVyZSIgCnBocTkuY2hhbmdlJHJpc2subGV2ZWwuZGlzY2hhcmdlW3BocTkuY2hhbmdlJHJpc2subGV2ZWwuZGlzY2hhcmdlID09IDFdIDwtICJNaW5pbWFsIiAKcGhxOS5jaGFuZ2Ukcmlzay5sZXZlbC5kaXNjaGFyZ2VbcGhxOS5jaGFuZ2Ukcmlzay5sZXZlbC5kaXNjaGFyZ2UgPT0gMl0gPC0gIk1pbmltYWwiIApwaHE5LmNoYW5nZSRyaXNrLmxldmVsLmRpc2NoYXJnZVtwaHE5LmNoYW5nZSRyaXNrLmxldmVsLmRpc2NoYXJnZSA9PSAzXSA8LSAiTWluaW1hbCIgCnBocTkuY2hhbmdlJHJpc2subGV2ZWwuZGlzY2hhcmdlW3BocTkuY2hhbmdlJHJpc2subGV2ZWwuZGlzY2hhcmdlID09IDRdIDwtICJNaW5pbWFsIiAKcGhxOS5jaGFuZ2Ukcmlzay5sZXZlbC5kaXNjaGFyZ2VbcGhxOS5jaGFuZ2Ukcmlzay5sZXZlbC5kaXNjaGFyZ2UgPT0gNV0gPC0gIk1pbGQiIApwaHE5LmNoYW5nZSRyaXNrLmxldmVsLmRpc2NoYXJnZVtwaHE5LmNoYW5nZSRyaXNrLmxldmVsLmRpc2NoYXJnZSA9PSA2XSA8LSAiTWlsZCIgCnBocTkuY2hhbmdlJHJpc2subGV2ZWwuZGlzY2hhcmdlW3BocTkuY2hhbmdlJHJpc2subGV2ZWwuZGlzY2hhcmdlID09IDddIDwtICJNaWxkIiAKcGhxOS5jaGFuZ2Ukcmlzay5sZXZlbC5kaXNjaGFyZ2VbcGhxOS5jaGFuZ2Ukcmlzay5sZXZlbC5kaXNjaGFyZ2UgPT0gOF0gPC0gIk1pbGQiIApwaHE5LmNoYW5nZSRyaXNrLmxldmVsLmRpc2NoYXJnZVtwaHE5LmNoYW5nZSRyaXNrLmxldmVsLmRpc2NoYXJnZSA9PSA5XSA8LSAiTWlsZCIgCnBocTkuY2hhbmdlJHJpc2subGV2ZWwuZGlzY2hhcmdlW3BocTkuY2hhbmdlJHJpc2subGV2ZWwuZGlzY2hhcmdlID09IDEwXSA8LSAiTW9kZXJhdGUiIApwaHE5LmNoYW5nZSRyaXNrLmxldmVsLmRpc2NoYXJnZVtwaHE5LmNoYW5nZSRyaXNrLmxldmVsLmRpc2NoYXJnZSA9PSAxMV0gPC0gIk1vZGVyYXRlIiAKcGhxOS5jaGFuZ2Ukcmlzay5sZXZlbC5kaXNjaGFyZ2VbcGhxOS5jaGFuZ2Ukcmlzay5sZXZlbC5kaXNjaGFyZ2UgPT0gMTJdIDwtICJNb2RlcmF0ZSIgCnBocTkuY2hhbmdlJHJpc2subGV2ZWwuZGlzY2hhcmdlW3BocTkuY2hhbmdlJHJpc2subGV2ZWwuZGlzY2hhcmdlID09IDEzXSA8LSAiTW9kZXJhdGUiIApwaHE5LmNoYW5nZSRyaXNrLmxldmVsLmRpc2NoYXJnZVtwaHE5LmNoYW5nZSRyaXNrLmxldmVsLmRpc2NoYXJnZSA9PSAxNF0gPC0gIk1vZGVyYXRlIiAKcGhxOS5jaGFuZ2Ukcmlzay5sZXZlbC5kaXNjaGFyZ2VbcGhxOS5jaGFuZ2Ukcmlzay5sZXZlbC5kaXNjaGFyZ2UgPT0gMTVdIDwtICJNb2RlcmF0ZWx5IFNldmVyZSIgCnBocTkuY2hhbmdlJHJpc2subGV2ZWwuZGlzY2hhcmdlW3BocTkuY2hhbmdlJHJpc2subGV2ZWwuZGlzY2hhcmdlID09IDE2XSA8LSAiTW9kZXJhdGVseSBTZXZlcmUiIApwaHE5LmNoYW5nZSRyaXNrLmxldmVsLmRpc2NoYXJnZVtwaHE5LmNoYW5nZSRyaXNrLmxldmVsLmRpc2NoYXJnZSA9PSAxN10gPC0gIk1vZGVyYXRlbHkgU2V2ZXJlIiAKcGhxOS5jaGFuZ2Ukcmlzay5sZXZlbC5kaXNjaGFyZ2VbcGhxOS5jaGFuZ2Ukcmlzay5sZXZlbC5kaXNjaGFyZ2UgPT0gMThdIDwtICJNb2RlcmF0ZWx5IFNldmVyZSIgCnBocTkuY2hhbmdlJHJpc2subGV2ZWwuZGlzY2hhcmdlW3BocTkuY2hhbmdlJHJpc2subGV2ZWwuZGlzY2hhcmdlID09IDE5XSA8LSAiTW9kZXJhdGVseSBTZXZlcmUiIAoKI0lGIGRpc2NoYXJnZSB2YWx1ZSBpcyBhdmFpbGFibGUsIHVzZSBpdCB0byBjYWxjdWxhdGUgY2hhbmdlLiBJZiBub3QsIHVzZSB0aGUgcmVldmFsdWF0aW9uIHZhbHVlIHRvIGNhbGN1bGF0ZSBjaGFuZ2UKI1JlbW92ZSBjb2x1bW5zIHVzZWQgdG8gY2FsY3VsYXRlIHRvIG9ubHkgbGVhdmUgY29sdW1uIHdpdGggY2hhbmdlIHZhbHVlCnBocTkuY2hhbmdlJHJpc2subGV2ZWwuY2hhbmdlPXBocTkuY2hhbmdlJHJpc2subGV2ZWwuZGlzY2hhcmdlCnBocTkuY2hhbmdlPSBwaHE5LmNoYW5nZSAlPiUgCiAgICBtdXRhdGUocmlzay5sZXZlbC5jaGFuZ2UgPSBjb2FsZXNjZShyaXNrLmxldmVsLmNoYW5nZSxyaXNrLmxldmVsLnJlYXV0aCkpCgpwaHE5LmNoYW5nZSA8LSBwaHE5LmNoYW5nZVssIGMoMTo4LDExKV0KcGhxOS5jaGFuZ2Ukcmlzay5sZXZlbD1wYXN0ZShwaHE5LmNoYW5nZSRyaXNrLmxldmVsLmluaXQscGhxOS5jaGFuZ2Ukcmlzay5sZXZlbC5jaGFuZ2Usc2VwPSItIikKcGhxOS5jaGFuZ2UkRGlzY2hhcmdlZD1waHE5LmNoYW5nZSRgSW5kaXZpZHVhbCBEaXNjaGFyZ2VgCnBocTkuY2hhbmdlJERpc2NoYXJnZWRbcGhxOS5jaGFuZ2UkRGlzY2hhcmdlZCAhPSAiTkEiXSA8LSAiVFJVRSIgCmBgYAoKYGBge3IsIHByaW50PUZBTFNFLCByZXN1bHRzPUZBTFNFLCB3YXJuaW5nPUZBTFNFLCBtZXNzYWdlPUZBTFNFfQoKIyMjIFN1bW1hcnkgb2YgbnVtYmVyIG9mIGluZGl2aWR1YWxzIHdpdGggaW5jcmVhc2luZyBhbmQgZGVjcmVhc2luZyByaXNrIGZhY3RvcnMgYnkgZGlzY2hhcmdlCgpwaHE5LnJpc2suY2hhbmdlPXBocTkuY2hhbmdlCgpwaHE5LnJpc2suY2hhbmdlJHJpc2subGV2ZWwuY2hhbmdlW3BocTkucmlzay5jaGFuZ2Ukcmlzay5sZXZlbC5jaGFuZ2UgPT0gIk1pbmltYWwiIF0gPC0gMSAKcGhxOS5yaXNrLmNoYW5nZSRyaXNrLmxldmVsLmNoYW5nZVtwaHE5LnJpc2suY2hhbmdlJHJpc2subGV2ZWwuY2hhbmdlID09ICJNaWxkIl0gPC0gMgpwaHE5LnJpc2suY2hhbmdlJHJpc2subGV2ZWwuY2hhbmdlW3BocTkucmlzay5jaGFuZ2Ukcmlzay5sZXZlbC5jaGFuZ2UgPT0gIk1vZGVyYXRlIl0gPC0gMwpwaHE5LnJpc2suY2hhbmdlJHJpc2subGV2ZWwuY2hhbmdlW3BocTkucmlzay5jaGFuZ2Ukcmlzay5sZXZlbC5jaGFuZ2UgPT0gIk1vZGVyYXRlbHkgU2V2ZXJlIl0gPC0gNApwaHE5LnJpc2suY2hhbmdlJHJpc2subGV2ZWwuY2hhbmdlW3BocTkucmlzay5jaGFuZ2Ukcmlzay5sZXZlbC5jaGFuZ2UgPT0gIlNldmVyZSJdIDwtIDUgCgpwaHE5LnJpc2suY2hhbmdlJHJpc2subGV2ZWwuaW5pdFtwaHE5LnJpc2suY2hhbmdlJHJpc2subGV2ZWwuaW5pdCA9PSAiTWluaW1hbCIgXSA8LSAxIApwaHE5LnJpc2suY2hhbmdlJHJpc2subGV2ZWwuaW5pdFtwaHE5LnJpc2suY2hhbmdlJHJpc2subGV2ZWwuaW5pdCA9PSAiTWlsZCJdIDwtIDIKcGhxOS5yaXNrLmNoYW5nZSRyaXNrLmxldmVsLmluaXRbcGhxOS5yaXNrLmNoYW5nZSRyaXNrLmxldmVsLmluaXQgPT0gIk1vZGVyYXRlIl0gPC0gMwpwaHE5LnJpc2suY2hhbmdlJHJpc2subGV2ZWwuaW5pdFtwaHE5LnJpc2suY2hhbmdlJHJpc2subGV2ZWwuaW5pdCA9PSAiTW9kZXJhdGVseSBTZXZlcmUiXSA8LSA0IApwaHE5LnJpc2suY2hhbmdlJHJpc2subGV2ZWwuaW5pdFtwaHE5LnJpc2suY2hhbmdlJHJpc2subGV2ZWwuaW5pdCA9PSAiU2V2ZXJlIl0gPC0gNSAKCnBocTkucmlzay5jaGFuZ2Ukcmlzay5sZXZlbC5jaGFuZ2U9YXMubnVtZXJpYyhwaHE5LnJpc2suY2hhbmdlJHJpc2subGV2ZWwuY2hhbmdlKQpwaHE5LnJpc2suY2hhbmdlJHJpc2subGV2ZWwuaW5pdD1hcy5udW1lcmljKHBocTkucmlzay5jaGFuZ2Ukcmlzay5sZXZlbC5pbml0KQpgYGAKCgpgYGB7ciwgcHJpbnQ9RkFMU0UsIHJlc3VsdHM9RkFMU0UsIHdhcm5pbmc9RkFMU0UsIG1lc3NhZ2U9RkFMU0V9CiMjIyBEaXN0cmlidXRpb24gb2YgU2V2ZXJpdHkgQmFzZWxpbmUgdG8gQ3VycmVudAojI1RoaXMgbmVlZHMgd29yayB0byBhZGQgdGhlIGFwcHJvcHJpYXRlIHN0cmF0dW0gbGFiZWxzIGZvciBlYWNoIHNpZGUKCnBocTkuZnJlcT1waHE5LmNoYW5nZQpwaHE5LmZyZXE9cGhxOS5mcmVxICU+JSBkcm9wX25hKHJpc2subGV2ZWwuY2hhbmdlKQoKbW9ja3VwX2ZyZXEgPC0gcGhxOS5mcmVxICU+JQogIGRwbHlyOjpjb3VudChyaXNrLmxldmVsLmluaXQsIHJpc2subGV2ZWwuY2hhbmdlKSAlPiUKICBtdXRhdGUocHJvcHRvdCA9IHByb3AudGFibGUobikpCgptb2NrdXBfZnJlcSA8LSBuYS5vbWl0KG1vY2t1cF9mcmVxKQptb2NrdXBfZnJlcSRyaXNrLmxldmVsLmluaXQgPC0gZmFjdG9yKG1vY2t1cF9mcmVxJHJpc2subGV2ZWwuaW5pdCwgbGV2ZWxzPWMoJ01pbmltYWwnLCAnTWlsZCcsICdNb2RlcmF0ZScsICdNb2RlcmF0ZWx5IFNldmVyZScsICdTZXZlcmUnKSkKbGV2ZWxzKG1vY2t1cF9mcmVxJHJpc2subGV2ZWwuaW5pdCkKCiNldmVudHVhbGx5IHJlbW92ZSByb3dzIHdpdGggTkEgaGVyZQoKbGlicmFyeShkYXRhTWFpZCkKbGlicmFyeShsdWJyaWRhdGUpCmxpYnJhcnkoc3VtbWFyeXRvb2xzKQpsaWJyYXJ5KGdnc3RhdHNwbG90KQpsaWJyYXJ5KGdyaWRFeHRyYSkKbGlicmFyeShSbWlzYykKbGlicmFyeShnZ2ZvcnRpZnkpCmxpYnJhcnkoZ2dwdWJyKQpsaWJyYXJ5KGZhY3RvZXh0cmEpCmxpYnJhcnkoZ2dwdWJyKQpsaWJyYXJ5KGZvcmNhdHMpCmxpYnJhcnkoUkNvbG9yQnJld2VyKQpsaWJyYXJ5KGdncmVwZWwpCmxpYnJhcnkoZ2dhbGx1dmlhbCkKCgpnZ3Bsb3QoYXMuZGF0YS5mcmFtZShtb2NrdXBfZnJlcSksCiAgICAgICBhZXMoeSA9IHByb3B0b3QsIGF4aXMxID0gcmlzay5sZXZlbC5pbml0LCBheGlzMiA9IHJpc2subGV2ZWwuY2hhbmdlKSkgKwogIGdlb21fYWxsdXZpdW0oYWVzKGZpbGwgPSByaXNrLmxldmVsLmluaXQpLCB3aWR0aCA9IDEvMTIpICsKICBnZW9tX3N0cmF0dW0od2lkdGggPSAxLzEyICwgY29sb3VyID0gImRhcmtncmV5IikgKwogIGdlb21fbGFiZWwoc3RhdCA9ICJzdHJhdHVtIiwgaW5mZXIubGFiZWwgPSBUUlVFLCBmaWxsPSJ3aGl0ZSIsIGZvbnRmYWNlPSJib2xkIiwgY29sb3VyPSJkYXJrZ3JleSIsICBzaXplPTIpICsKICBzY2FsZV94X2Rpc2NyZXRlKGxpbWl0cyA9IGMoInJpc2subGV2ZWwuaW5pdCIsICJyaXNrLmxldmVsLmNoYW5nZSIpLAogICAgICAgICAgICAgICAgICAgZXhwYW5kID0gYyguMSwgLjEpLAogICAgICAgICAgICAgICAgICAgbGFiZWxzID0gYygiQmFzZWxpbmUiLCAiQ3VycmVudCIpKSArCiAgZ2d0aXRsZSgiRmxvdyBvZiBTZXZlcml0eSBiZXR3ZWVuIEJhc2VsaW5lIGFuZCBDdXJyZW50IEFzc2Vzc21lbnQiKSArCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzPWMoImdyZXkiLCAieWVsbG93IiwgIm9yYW5nZSIsICJvcmFuZ2VyZWQiLCAiZGFya3JlZCIpLCAKICAgICAgICAgICAgICAgICAgICBuYW1lPSJUaXRsZSIsCiAgICAgICAgICAgICAgICAgICAgYnJlYWtzPWMoIk1pbmltYWwiLCAiTWlsZCIsICJNb2RlcmF0ZSIsICJNb2RlcmF0ZWx5IFNldmVyZSIsIlNldmVyZSIpLAogICAgICAgICAgICAgICAgICAgIGxhYmVscz1jKCJNaW5pbWFsIiwgIk1pbGQiLCAiTW9kZXJhdGUiLCAiTW9kZXJhdGVseSBTZXZlcmUuIiwiU2V2ZXJlIikpICsKICB0aGVtZV9taW5pbWFsKCkgKwogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJyaWdodCIsCiAgICAgICAgcGFuZWwuZ3JpZC5tYWpvciA9IGVsZW1lbnRfYmxhbmsoKSwgCiAgICAgICAgcGFuZWwuZ3JpZC5taW5vciA9IGVsZW1lbnRfYmxhbmsoKSkgKwogIGxhYnMoeSA9ICJQcm9wb3J0aW9uIG9mIHRvdGFsIikgCgpgYGAKCiMjIyBJbnRlcmFjdGl2ZSBEYXRhIFRhYmxlCmBgYHtyfQpsaWJyYXJ5KERUKQpwaHE5LmRhdGF0YWJsZT0gcGhxOS5jaGFuZ2VbLCBjKDE6NywxMDoxMSldCiAgCmRhdGF0YWJsZShkYXRhID0gcGhxOS5kYXRhdGFibGUsIHdpZHRoPU5VTEwsICBmaWx0ZXIgPSAidG9wIiwgY2FwdGlvbj0gIlBIUS05IFN1bW1hcnkgUmVzdWx0cyIsIHJvd25hbWVzPUYsIGNvbG5hbWVzID0gYygnUmVjb3JkIElEJywgJ0Nhc2UgSUQnLCAnQmFzZWxpbmUgU2NvcmUnLCAnUmVhdXRob3JpemF0aW9uIFNjb3JlJywgJ0Rpc2NoYXJnZSBTY29yZScsICdDaGFuZ2UgaW4gU2NvcmUnLCAiSW1wcm92ZW1lbnQgKFQvRikiLCAiUmlzayBMZXZlbCBJbml0aWFsOkN1cnJlbnQiLCAiRGlzY2hhcmdlZCAoVC9GKSIpLAogICAgICAgICAgb3B0aW9ucyA9IGxpc3QocGFnZWxlbmd0aD0yNSwKICBpbml0Q29tcGxldGUgPSBKUygKICAgICJmdW5jdGlvbihzZXR0aW5ncywganNvbikgeyIsCiAgICAiJCh0aGlzLmFwaSgpLnRhYmxlKCkuaGVhZGVyKCkpLmNzcyh7J2JhY2tncm91bmQtY29sb3InOiAnZ3JleScsICdjb2xvcic6ICcjZmZmJ30pOyIsCiAgICAifSIpKSkKCgpgYGAKCgojIyBQQ0wtNSB7LnRhYnNldH0KCiMjIyBQdXJwb3NlIGFuZCBFdmFsdWF0aW9uCj4gRXZpZGVuY2UgZm9yIHRoZSBQQ0wgZm9yIERTTS1JViBzdWdnZXN0ZWQgNSBwb2ludCBkZWNyZWFzZSBhcyBhIG1pbmltdW0gdGhyZXNob2xkIGZvciBkZXRlcm1pbmluZyB3aGV0aGVyIGFuIGluZGl2aWR1YWwgaGFzIHJlc3BvbmRlZCB0byB0cmVhdG1lbnQgYW5kIDEwIHBvaW50IGRlY3JlYXNlIGFzIGEgbWluaW11bSB0aHJlc2hvbGQgZm9yIGRldGVybWluaW5nIHdoZXRoZXIgdGhlIGltcHJvdmVtZW50IGlzIGNsaW5pY2FsbHkgbWVhbmluZ2Z1bC4gQ2hhbmdlIHNjb3JlcyBmb3IgUENMLTUgYXJlIGN1cnJlbnRseSBiZWluZyBkZXRlcm1pbmVkLiBJdCBpcyBleHBlY3RlZCB0aGF0IHJlbGlhYmxlIGFuZCBjbGluaWNhbGx5IG1lYW5pbmdmdWwgY2hhbmdlIHdpbGwgYmUgaW4gYSBzaW1pbGFyIHJhbmdlLiBXZSByZWNvbW1lbmQgZm9sbG93aW5nIHRoZSBEU00tSVYgcmVjb21tZW5kYXRpb25zIHVudGlsIG5ldyBpbmZvcm1hdGlvbiBpcyBhdmFpbGFibGUuCgpodHRwczovL3d3dy5wdHNkLnZhLmdvdi9wcm9mZXNzaW9uYWwvYXNzZXNzbWVudC9hZHVsdC1zci9wdHNkLWNoZWNrbGlzdC5hc3AKCj4gVGhlIFBDTC01IGNhbiBiZSBzY29yZWQgaW4gZGlmZmVyZW50IHdheXM6Cj4gQSB0b3RhbCBzeW1wdG9tIHNldmVyaXR5IHNjb3JlIChyYW5nZSAtIDAtODApIGNhbiBiZSBvYnRhaW5lZCBieSBzdW1taW5nIHRoZSBzY29yZXMgZm9yIGVhY2ggb2YgdGhlIDIwIGl0ZW1zLgo+IERTTS01IHN5bXB0b20gY2x1c3RlciBzZXZlcml0eSBzY29yZXMgY2FuIGJlIG9idGFpbmVkIGJ5IHN1bW1pbmcgdGhlIHNjb3JlcyBmb3IgdGhlIGl0ZW1zIHdpdGhpbiBhIGdpdmVuIGNsdXN0ZXIsIGkuZS4sIGNsdXN0ZXIgQiAoKipSZS1leHBlcmllbmNpbmcqKjsgaXRlbXMgMS01KSwgY2x1c3RlciBDICgqKkF2b2lkYW5jZSoqOyBpdGVtcyA2LTcpLCBjbHVzdGVyIEQgKCoqTmVnYXRpdmUgYWx0ZXJuYXRpb25zIGluIGNvZ25pdGlvbiBhbmQgbW9vZCoqOyBpdGVtcyA4LTE0KSwgYW5kIGNsdXN0ZXIgRSAoKipIeXBlci1hcm91c2FsKio7IGl0ZW1zIDE1LTIwKS4KPkEgcHJvdmlzaW9uYWwgUFRTRCBkaWFnbm9zaXMgY2FuIGJlIG1hZGUgYnkgdHJlYXRpbmcgZWFjaCBpdGVtIHJhdGVkIGFzIDIgPSAiTW9kZXJhdGVseSIgb3IgaGlnaGVyIGFzIGEgc3ltcHRvbSBlbmRvcnNlZCwgdGhlbiBmb2xsb3dpbmcgdGhlIERTTS01IGRpYWdub3N0aWMgcnVsZSB3aGljaCByZXF1aXJlcyBhdCBsZWFzdDogMSBCIGl0ZW0gKHF1ZXN0aW9ucyAxLTUpLCAxIEMgaXRlbSAocXVlc3Rpb25zIDYtNyksIDIgRCBpdGVtcyAocXVlc3Rpb25zIDgtMTQpLCAyIEUgaXRlbXMgKHF1ZXN0aW9ucyAxNS0yMCkuCgo+SW5pdGlhbCByZXNlYXJjaCBzdWdnZXN0cyB0aGF0IGEgUENMLTUgY3V0b2ZmIHNjb3JlIGJldHdlZW4gMzEtMzMgaXMgaW5kaWNhdGl2ZSBvZiBwcm9iYWJsZSBQVFNEIGFjcm9zcyBzYW1wbGVzLiBIb3dldmVyLCBhZGRpdGlvbmFsIHJlc2VhcmNoIGlzIG5lZWRlZC4gRnVydGhlciwgYmVjYXVzZSB0aGUgcG9wdWxhdGlvbiBhbmQgdGhlIHB1cnBvc2Ugb2YgdGhlIHNjcmVlbmluZyBtYXkgd2FycmFudCBkaWZmZXJlbnQgY3V0b2ZmIHNjb3JlcywgdXNlcnMgYXJlIGVuY291cmFnZWQgdG8gY29uc2lkZXIgYm90aCBvZiB0aGVzZSBmYWN0b3JzIHdoZW4gY2hvb3NpbmcgYSBjdXRvZmYgc2NvcmUuCgpDb2hlbiwgSi4sIGV0IGFsLiAoMjAxNSkuIFByZWxpbWluYXJ5IEV2YWx1YXRpb24gb2YgdGhlIFBzeWNob21ldHJpYyBQcm9wZXJ0aWVzIG9mIHRoZSBQVFNEIENoZWNrbGlzdCBmb3IgRFNNIOKAkyA1LiAoQ29uZmVyZW5jZSBQcmVzZW50YXRpb24pLiBkb2k6IDEwLjEyMTQwLzIuMS40NDQ4LjU0NDQKCmBgYHtyLCBwcmludD1GLCB3YXJuaW5nPUZ9CnBjbDUgPC0gZGF0YS5mcmFtZShsYXBwbHkocGNsNSwgZnVuY3Rpb24oeCkgewogICAgICAgICAgICAgICAgICBnc3ViKCJOb3QgYXQgQWxsIiwgIjAiLCB4KQogICAgICAgICAgICAgIH0pKQoKcGNsNSA8LSBkYXRhLmZyYW1lKGxhcHBseShwY2w1LCBmdW5jdGlvbih4KSB7CiAgICAgICAgICAgICAgICAgIGdzdWIoIkEgTGl0dGxlIEJpdCIsICIxIiwgeCkKICAgICAgICAgICAgICB9KSkKCnBjbDUgPC0gZGF0YS5mcmFtZShsYXBwbHkocGNsNSwgZnVuY3Rpb24oeCkgewogICAgICAgICAgICAgICAgICBnc3ViKCJNb2RlcmF0ZWx5IiwgIjIiLCB4KQogICAgICAgICAgICAgIH0pKQoKCnBjbDUgPC0gZGF0YS5mcmFtZShsYXBwbHkocGNsNSwgZnVuY3Rpb24oeCkgewogICAgICAgICAgICAgICAgICBnc3ViKCJRdWl0ZSBhIEJpdCIsICIzIiwgeCkKICAgICAgICAgICAgICB9KSkKCnBjbDUgPC0gZGF0YS5mcmFtZShsYXBwbHkocGNsNSwgZnVuY3Rpb24oeCkgewogICAgICAgICAgICAgICAgICBnc3ViKCJFeHRyZW1lbHkiLCAiNCIsIHgpCiAgICAgICAgICAgICAgfSkpCgpwY2w1IDwtIHBjbDUgJT4lIAogICAgIG11dGF0ZV9hdChjKDU6MjQpLCBhcy5udW1lcmljKQogIApwY2w1JGNsdXN0ZXJBIDwtIGFzLm51bWVyaWMoYXBwbHkocGNsNVssNTo5XSwgMSwgc3VtKSkKcGNsNSRjbHVzdGVyQiA8LSBhcy5udW1lcmljKGFwcGx5KHBjbDVbLDEwOjExXSwgMSwgc3VtKSkKcGNsNSRjbHVzdGVyQyA8LSBhcy5udW1lcmljKGFwcGx5KHBjbDVbLDEyOjE4XSwgMSwgc3VtKSkKcGNsNSRjbHVzdGVyRCA8LSBhcy5udW1lcmljKGFwcGx5KHBjbDVbLDE5OjI0XSwgMSwgc3VtKSkKCgojS2VlcCBvbmx5IGlkZW50aWZpZXIgY29sdW1ucyBhbmQgdGhlIHRvdGFsIHNjb3JlIGNvbHVtbnMKcGNsNS50b3Q9c3Vic2V0KHBjbDUsIHNlbGVjdCA9IGMoMSwyLDMsMjUpKQpwY2w1LnRvdD1zcHJlYWQocGNsNS50b3QsIGtleSA9IGBFdmVudC5OYW1lYCwgdmFsdWUgPSBgUENMNS5Ub3RhbGApCnBjbDUudG90IDwtIHBjbDUudG90WywgYygxLDIsMywgNSwgNCldCgpwY2w1LmNsdXNBPXN1YnNldChwY2w1LCBzZWxlY3QgPSBjKDEsMiwzLDI3KSkKcGNsNS5jbHVzQT1zcHJlYWQocGNsNS5jbHVzQSwga2V5ID0gYEV2ZW50Lk5hbWVgLCB2YWx1ZSA9IGBjbHVzdGVyQWApCnBjbDUuY2x1c0EgPC0gcGNsNS5jbHVzQVssIGMoMSwyLDMsIDUsIDQpXQoKcGNsNS5jbHVzQj1zdWJzZXQocGNsNSwgc2VsZWN0ID0gYygxLDIsMywyOCkpCnBjbDUuY2x1c0I9c3ByZWFkKHBjbDUuY2x1c0IsIGtleSA9IGBFdmVudC5OYW1lYCwgdmFsdWUgPSBgY2x1c3RlckJgKQpwY2w1LmNsdXNCIDwtIHBjbDUuY2x1c0JbLCBjKDEsMiwzLCA1LCA0KV0KCnBjbDUuY2x1c0M9c3Vic2V0KHBjbDUsIHNlbGVjdCA9IGMoMSwyLDMsMjkpKQpwY2w1LmNsdXNDPXNwcmVhZChwY2w1LmNsdXNDLCBrZXkgPSBgRXZlbnQuTmFtZWAsIHZhbHVlID0gYGNsdXN0ZXJDYCkKcGNsNS5jbHVzQyA8LSBwY2w1LmNsdXNDWywgYygxLDIsMywgNSwgNCldCgpwY2w1LmNsdXNEPXN1YnNldChwY2w1LCBzZWxlY3QgPSBjKDEsMiwzLDMwKSkKcGNsNS5jbHVzRD1zcHJlYWQocGNsNS5jbHVzRCwga2V5ID0gYEV2ZW50Lk5hbWVgLCB2YWx1ZSA9IGBjbHVzdGVyRGApCnBjbDUuY2x1c0QgPC0gcGNsNS5jbHVzRFssIGMoMSwyLDMsIDUsIDQpXQoKYGBgCgpgYGB7ciwgcHJpbnQ9Riwgd2FybmluZz1GfQpwY2w1LnRvdCRgSW5kaXZpZHVhbCBCYXNlbGluZWA9YXMubnVtZXJpYyhwY2w1LnRvdCRgSW5kaXZpZHVhbCBCYXNlbGluZWApCnBjbDUudG90JGBJbmRpdmlkdWFsIFJlYXV0aG9yaXphdGlvbmA9YXMubnVtZXJpYyhwY2w1LnRvdCRgSW5kaXZpZHVhbCBSZWF1dGhvcml6YXRpb25gKQpwY2w1LnRvdCRgSW5kaXZpZHVhbCBEaXNjaGFyZ2VgPWFzLm51bWVyaWMocGNsNS50b3QkYEluZGl2aWR1YWwgRGlzY2hhcmdlYCkKCiNDYWxjdWxhdGUgY2hhbmdlIGluIHNjb3JlIGJldHdlZW4gaW5pdGlhbCBhbmQgZGlzY2hhcmdlCnBjbDUudG90JGNoYW5nZT1wY2w1LnRvdCRgSW5kaXZpZHVhbCBEaXNjaGFyZ2VgLXBjbDUudG90JGBJbmRpdmlkdWFsIEJhc2VsaW5lYAojQ2FsY3VsYXRlIGNoYW5nZSBpbiBzY29yZSBiZXR3ZWVuIGluaXRpYWwgYW5kIHJlYXV0aG9yaXphdGlvbgpwY2w1LnRvdCRjaGFuZ2UucmVhdXRoPXBjbDUudG90JGBJbmRpdmlkdWFsIFJlYXV0aG9yaXphdGlvbmAtcGNsNS50b3QkYEluZGl2aWR1YWwgQmFzZWxpbmVgCgojSUYgZGlzY2hhcmdlIHZhbHVlIGlzIGF2YWlsYWJsZSwgdXNlIGl0IHRvIGNhbGN1bGF0ZSBjaGFuZ2UuIElmIG5vdCwgdXNlIHRoZSByZWV2YWx1YXRpb24gdmFsdWUgdG8gY2FsY3VsYXRlIGNoYW5nZQojUmVtb3ZlIGNvbHVtbnMgdXNlZCB0byBjYWxjdWxhdGUgdG8gb25seSBsZWF2ZSBjb2x1bW4gd2l0aCBjaGFuZ2UgdmFsdWUKcGNsNS50b3Q9IHBjbDUudG90ICU+JSAKICAgIG11dGF0ZShjaGFuZ2UgPSBjb2FsZXNjZShjaGFuZ2UsY2hhbmdlLnJlYXV0aCkpCnBjbDUudG90PXN1YnNldChwY2w1LnRvdCwgc2VsZWN0ID0gYygxOjYpKQpgYGAKCiMjIyBTdW1tYXJ5IFN0YXRpc3RpY3MgCgo+IFRhYmxlIGluY2x1ZGluZyB0aGUgc2FtcGxlIHNpemUgKE4pIGFuZCBzdW1tYXJ5IHN0YXRpc3RpY3MgZm9yIFBDTC01IHNjb3Jlcy4gIkNoYW5nZSIgdmFyYWlibGUgaXMgdGhlIGRpZmZlcmVuY2UgYmV0d2VlbiB0aGUgYmFzZWxpbmUgYW5kIGRpc2NoYXJnZSBzY29yZSwgb3IgYmFzZWxpbmUgYW5kIHJlYXV0aG9yaXphdGlvbiBzY29yZSB3aGVuIG5vIGRpc2NoYXJnZSBzY29yZSBpcyBhdmFpbGFibGUuIAoKPlRhYmxlIGFsc28gaW5jbHVkZXMgIkltcHJvdmVtZW50Iiwgd2hpY2ggY2F0ZWdvcml6ZXMgY2hhbmdlcyBpbiBzY29yZXMgaW50byB0aG9zZSBkZXNjcmliZWQgYnkgdGhlIFZBIGZvciBjbGluaWNhbCBpbXByb3ZlbWVudCwgcmVzcG9uZGluZyB0byB0cmVhdG1lbnQsIG5vIHJlc3BvbnNlLCBvciBpbmNyZWFzZWQgUFRTRCBzeW1wdG9tcy4gIAoKYGBge3IsIHByaW50PUZBTFNFLCByZXN1bHRzPUZBTFNFLCB3YXJuaW5nPUZBTFNFLCBtZXNzYWdlPUZBTFNFfQpsaWJyYXJ5KHZ0YWJsZSkKYGBgCgpgYGB7cn0Kc3VtdGFibGUocGNsNS50b3QpCmBgYAoKIyMjIEdyYXBoaWNzCgo+IENoYW5nZSBpbiBQVFNEIFNldmVyaXR5OiBHcmFwaCBzaG93cyBmcmVxdWVuY3kgb2Ygc2NvcmUgY2hhbmdlcyBiZXR3ZWVuIGJhc2VsaW5lIGFuZCBkaXNjaGFyZ2UgYXNzZXNzbWVudHMsIG9yIGJhc2VsaW5lIGFuZCByZWF1dGhvcml6YXRpb24gYXNzZXNzbWVudHMgd2hlbiBkaXNjaGFyZ2UgZGF0YSBpcyBub3QgYXZhaWxhYmxlLiAgVmVydGljYWwgbGluZXMgc2VwZXJhdGUgY2hhbmdlcyBpbiBzY29yZXMgaW50byBtZWFuaW5mdWwgY2F0ZWdvcmllcyBvZiAiUmVzcG9uZGluZyB0byBUcmVhdG1lbnQiICg+NSBwb2ludCBkZWNyZWFzZSksIENsaW5pY2FsIGltcHJvdmVtZW50IiAoPjEwIHBvaW50IGRlY3JlYXNlKSwgb3IgIkluY3JlYXNlZCBQVFNEIFN5bXB0b21zIi4gCgpgYGB7ciwgd2FybmluZz1GfQpnZ3Bsb3QocGNsNS50b3QsIGFlcyhjaGFuZ2UpKSArCiAgZ2VvbV9oaXN0b2dyYW0oYmlud2lkdGg9MSwgY29sb3I9ImJsYWNrIiwgZmlsbD0gImdyZXkiKSArCiAgeGxhYigiQ2hhbmdlIGluIFBUU0QgU2NvcmUiKSAgKwogIGdndGl0bGUoIkNoYW5nZSBpbiBTZXZlcml0eSBTY29yZSIpICsKZ2VvbV92bGluZSh4aW50ZXJjZXB0PS0xMCwgc2l6ZT0xLCBjb2xvcj0iZ3JleSIsICBsaW5ldHlwZT0iZG90dGVkIikgKwogIGFubm90YXRlKGdlb209InRleHQiLCB4PS0yMCwgeT01LjUsIHNpemU9MiwgbGFiZWw9IkNsaW5pY2FsIEltcHJvdmVtZW50IiwgY29sb3I9ImJsYWNrIikgKwpnZW9tX3ZsaW5lKHhpbnRlcmNlcHQ9LTQsIHNpemU9MSwgY29sb3I9ImdyZXkiLCAgbGluZXR5cGU9ImRvdHRlZCIpICsKICBhbm5vdGF0ZShnZW9tPSJ0ZXh0IiwgeD0tNi41LCB5PTUuNSwgc2l6ZT0yLCBsYWJlbD0iUmVzcG9uZGluZyIsIGNvbG9yPSJibGFjayIpICsKICAgIGFubm90YXRlKGdlb209InRleHQiLCB4PS02LjUsIHk9NS4zNSwgc2l6ZT0yLCBsYWJlbD0idG8iLCBjb2xvcj0iYmxhY2siKSArCiAgICBhbm5vdGF0ZShnZW9tPSJ0ZXh0IiwgeD0tNi41LCB5PTUuMiwgc2l6ZT0yLCBsYWJlbD0iVHJlYXRtZW50IiwgY29sb3I9ImJsYWNrIikgKwogIGdlb21fdmxpbmUoeGludGVyY2VwdD0tMSwgc2l6ZT0xLCBjb2xvcj0iZ3JleSIsICBsaW5ldHlwZT0iZG90dGVkIikgKwogICAgYW5ub3RhdGUoZ2VvbT0idGV4dCIsIHg9MTYuNSwgeT01LjUsIHNpemU9MiwgbGFiZWw9IkluY3JlYXNlZCBQVFNEIFN5bXB0b21zIiwgY29sb3I9ImJsYWNrIikgCgoKYGBgCgo+IFByb3BvcnRpb24gb2YgQ2xpbmV0cyByZXBvcnRpbmcgY2xpbmljYWxseSBpbXByb3ZlZCBQVFNEIHN5bXB0b21zLCByZXNwb25zZSB0byB0cmVhdG1lbnQsIG5vIHJlc3BvbnNlIHRvIHRyZWF0bWVudCwgb3IgaW5jcmVhc2VkIFBUU0Qgc3ltcHRvbXMuIFRoZSBncmFwaCBvbiB0aGUgbGVmdCBpbmNsdWRlcyBhbGwgY2hhbmdlcyBpbiBzY29yZXMgYmV0d2VlbiBiYXNlbGluZSBhbmQgZGlzY2hhcmdlLCBhbmQgdXNpbmcgcmVhdGhvcml6YXRpb24gc2NvcmVzIHdoZW4gZGlzY2hhcmdlIHNjb3JlcyBhcmUgbm90IGF2YWlsYWJsZS4gVGhlIGNoYXJ0IG9uIHRoZSByaWdodCBpbmNsdWRlcyBvbmx5IGluZGl2aWR1YWxzIHdobyBoYXZlIGNvbXBsZXRlZCB0aGUgZGlzY2hhcmdlIGFzc2Vzc21lbnQuIFNhbXBsZSBzaXplcyBmb3IgZWFjaCBjYXRlZ29yeSBhbmQgaW5kaWNhdGVkIHdpdGhpbiBwaWUgd2VkZ2VzLiAKCmBgYHtyLCB3YXJuaW5nPUZ9CmxpYnJhcnkoZ3JpZEV4dHJhKQpsaWJyYXJ5KGdncHVicikKIyMjIFRhYmxlIHN1bW1hcnkgb2YgY2hhbmdlIGluIHNjb3JlLiAKcGNsNS50b3QkaW1wcm92ZW1lbnQ9cGNsNS50b3QkY2hhbmdlCgpwY2w1LnRvdCRpbXByb3ZlbWVudFtwY2w1LnRvdCRpbXByb3ZlbWVudCA8IC05XSA8LSAiQ2xpbmljYWwgSW1wcm92ZW1lbnQiIApwY2w1LnRvdCRpbXByb3ZlbWVudFtwY2w1LnRvdCRpbXByb3ZlbWVudCA9PSAtNV0gPC0gIlJlc3BvbmRpbmcgdG8gVHJlYXRtZW50IiAKcGNsNS50b3QkaW1wcm92ZW1lbnRbcGNsNS50b3QkaW1wcm92ZW1lbnQgPT0gLTZdIDwtICJSZXNwb25kaW5nIHRvIFRyZWF0bWVudCIgCnBjbDUudG90JGltcHJvdmVtZW50W3BjbDUudG90JGltcHJvdmVtZW50ID09IC03XSA8LSAiUmVzcG9uZGluZyB0byBUcmVhdG1lbnQiIApwY2w1LnRvdCRpbXByb3ZlbWVudFtwY2w1LnRvdCRpbXByb3ZlbWVudCA9PSAtOF0gPC0gIlJlc3BvbmRpbmcgdG8gVHJlYXRtZW50IiAKcGNsNS50b3QkaW1wcm92ZW1lbnRbcGNsNS50b3QkaW1wcm92ZW1lbnQgPT0gLTldIDwtICJSZXNwb25kaW5nIHRvIFRyZWF0bWVudCIgCnBjbDUudG90JGltcHJvdmVtZW50W3BjbDUudG90JGltcHJvdmVtZW50ID4wICYgcGNsNS50b3QkaW1wcm92ZW1lbnQgPD0gODBdIDwtICJJbmNyZWFzZWQgUFRTRCBTeW1wdG9tcyIgICAgIyBSZXBsYWNlIHZhbHVlcyBpbiByYW5nZQpwY2w1LnRvdCRpbXByb3ZlbWVudFtwY2w1LnRvdCRpbXByb3ZlbWVudCA9PSAtNF0gPC0gIk5vIFJlc3BvbnNlIiAKcGNsNS50b3QkaW1wcm92ZW1lbnRbcGNsNS50b3QkaW1wcm92ZW1lbnQgPT0gLTNdIDwtICJObyBSZXNwb25zZSIgCnBjbDUudG90JGltcHJvdmVtZW50W3BjbDUudG90JGltcHJvdmVtZW50ID09IC0yXSA8LSAiTm8gUmVzcG9uc2UiIApwY2w1LnRvdCRpbXByb3ZlbWVudFtwY2w1LnRvdCRpbXByb3ZlbWVudCA9PSAtMV0gPC0gIk5vIFJlc3BvbnNlIiAKcGNsNS50b3QkaW1wcm92ZW1lbnRbcGNsNS50b3QkaW1wcm92ZW1lbnQgPT0gLTBdIDwtICJObyBSZXNwb25zZSIgCgpwY2w1LnRvdDE9cGNsNS50b3QgJT4lIGRyb3BfbmEoYGltcHJvdmVtZW50YCkKCnBjbDUudG90MSRpbXByb3ZlbWVudCA8LSBmYWN0b3IocGNsNS50b3QxJGltcHJvdmVtZW50LCBsZXZlbHMgPSBjKCJDbGluaWNhbCBJbXByb3ZlbWVudCIsICJSZXNwb25kaW5nIHRvIFRyZWF0bWVudCIsICJObyBSZXNwb25zZSIsICJJbmNyZWFzZWQgUFRTRCBTeW1wdG9tcyIpKQoKdGFiMT1hcy5kYXRhLmZyYW1lKHRhYmxlKHBjbDUudG90MSRpbXByb3ZlbWVudCkpCnRhYjEkcGVyYz10YWIxJEZyZXEvbnJvdyhwY2w1LnRvdDEpCgp0YWIxLnA9Z2dwbG90KHRhYjEsIGFlcyh4PSIiLCB5PXBlcmMsIGZpbGw9VmFyMSkpICsKICBnZW9tX2JhcihzdGF0PSJpZGVudGl0eSIsIHdpZHRoPTEpICsKICBjb29yZF9wb2xhcigieSIsIHN0YXJ0PTApICsKICB4bGFiKCIiKSArCiAgZ2d0aXRsZSgiQWxsIFJlYXV0aCAmIERpc2NoYXJnZXMiKSArCiAgZ2VvbV90ZXh0KGFlcyhsYWJlbCA9IEZyZXEpLAogICAgICAgICAgICBwb3NpdGlvbiA9IHBvc2l0aW9uX3N0YWNrKHZqdXN0ID0gMC41KSkgKwogIHlsYWIoIlByb3BvcnRpb24iKSAKCgpwY2w1LnRvdDI9cGNsNS50b3QgJT4lIGRyb3BfbmEoYEluZGl2aWR1YWwgRGlzY2hhcmdlYCkKcGNsNS50b3QyJGltcHJvdmVtZW50IDwtIGZhY3RvcihwY2w1LnRvdDIkaW1wcm92ZW1lbnQsIGxldmVscyA9IGMoIkNsaW5pY2FsIEltcHJvdmVtZW50IiwgIlJlc3BvbmRpbmcgdG8gVHJlYXRtZW50IiwgIk5vIFJlc3BvbnNlIiwgIkluY3JlYXNlZCBQVFNEIFN5bXB0b21zIikpCgoKdGFiMj1hcy5kYXRhLmZyYW1lKHRhYmxlKHBjbDUudG90MiRpbXByb3ZlbWVudCkpCnRhYjIkcGVyYz10YWIyJEZyZXEvbnJvdyhwY2w1LnRvdDIpCgp0YWIyLnA9Z2dwbG90KHRhYjIsIGFlcyh4PSIiLCB5PXBlcmMsIGZpbGw9VmFyMSkpICsKICBnZW9tX2JhcihzdGF0PSJpZGVudGl0eSIsIHdpZHRoPTEpICsKICBjb29yZF9wb2xhcigieSIsIHN0YXJ0PTApICsKICAgIHhsYWIoIiIpICsKICBnZ3RpdGxlKCJEaXNjaGFyZ2VkIE9ubHkiKSArCiAgZ2VvbV90ZXh0KGFlcyhsYWJlbCA9IEZyZXEpLAogICAgICAgICAgICBwb3NpdGlvbiA9IHBvc2l0aW9uX3N0YWNrKHZqdXN0ID0gMC41KSkgKwogIHlsYWIoIlByb3BvcnRpb24iKQogIAoKZ2dhcnJhbmdlKHRhYjEucCAsIHRhYjIucCwgCiAgICAgICAgICBuY29sPTIsIG5yb3c9MSwgY29tbW9uLmxlZ2VuZCA9IFRSVUUsIGxlZ2VuZD0iYm90dG9tIikgCmBgYAoKPiBEaXN0cmlidXRpb24gb2YgUENMLTUgc2NvcmVzIGF0IGVhY2ggdGltZXBvaW50IChCYXNlbGluZSwgUmVhdXRob3JpemF0aW9uLCBhbmQgRGlzY2hhcmdlKS4gQ29sb3IgY29kZWQgZG90dGVkIGxpbmVzIGluZGljYXRlIG1lYW4gZm9yIGVhY2ggZ3JvdXAsIHdoaWxlIHNoYWRlZCByZWdpb25zIHNob3cgZGVuc2l0eSBvZiBvY2N1cmFuY2UuIFRoZSBzaGFkZWQgcmVnaW9uIGluZGljYXRlcyBmaWVsZCBhY2NlcHRlZCBzY29yZXMgaW5kaWNhdGluZyAicHJvYmFibGUgUFRTRCIuCgpgYGB7ciwgd2FybmluZz1GfQoKIyMjIERpc3RyaWJ1dGlvbiBvZiBzY29yZXMKCm1lYW5fYmFzZWxpbmUyPW1lYW4ocGNsNS50b3QkYEluZGl2aWR1YWwgQmFzZWxpbmVgLCBuYS5ybT1UKQptZWFuX3JlYXV0aDI9bWVhbihwY2w1LnRvdCRgSW5kaXZpZHVhbCBSZWF1dGhvcml6YXRpb25gLCBuYS5ybSA9IFQpCm1lYW5fZGlzY2hhcmdlMj1tZWFuKHBjbDUudG90JGBJbmRpdmlkdWFsIERpc2NoYXJnZWAsIG5hLnJtID0gVCkKCgpkZW4uMj1nZ3Bsb3QoKSArCmdlb21fZGVuc2l0eShhZXMoYEluZGl2aWR1YWwgQmFzZWxpbmVgLCBmaWxsPSJCYXNlbGluZSIpLCBhbHBoYT0wLjIsICBkYXRhPXBjbDUudG90KSArIApnZW9tX2RlbnNpdHkoYWVzKGBJbmRpdmlkdWFsIFJlYXV0aG9yaXphdGlvbmAsIGZpbGw9IlJlYXV0aG9yaXphdGlvbiIpLCBhbHBoYT0wLjIsIGRhdGE9cGNsNS50b3QpICsgCiAgZ2VvbV9kZW5zaXR5KGFlcyhgSW5kaXZpZHVhbCBEaXNjaGFyZ2VgLCBmaWxsPSJEaXNjaGFyZ2UiKSwgYWxwaGE9MC4yLCBkYXRhPXBjbDUudG90KSArIAogICAgbGFicyh0aXRsZT0iUENMLTUiLCAKICAgICAgICAgc3VidGl0bGU9IkRpc3RyaWJ1dGlvbiBvZiBQVFNEIFNjb3JlcyIsCiAgICAgICAgIHg9IlNjb3JlIikgKwogIHlsYWIoIkRlbnNpdHkiKSArCiAgYW5ub3RhdGUoJ3JlY3QnLCB4bWluPTMxLCB4bWF4PTMzLCB5bWluPTAsIHltYXg9SW5mLCBhbHBoYT0uMiwgZmlsbD0nYmxhY2snKSArCiAgZ2VvbV92bGluZSh4aW50ZXJjZXB0PW1lYW5fYmFzZWxpbmUyLCBzaXplPTEsIGNvbG9yPSJwaW5rIiwgbGluZXR5cGU9ImRvdHRlZCIpICsKICBnZW9tX3ZsaW5lKHhpbnRlcmNlcHQ9bWVhbl9yZWF1dGgyLCBzaXplPTEsIGNvbG9yPSJibHVlIiwgIGxpbmV0eXBlPSJkb3R0ZWQiKSArCiAgZ2VvbV92bGluZSh4aW50ZXJjZXB0PW1lYW5fZGlzY2hhcmdlMiwgc2l6ZT0xLCBjb2xvcj0iZ3JlZW4iLCAgbGluZXR5cGU9ImRvdHRlZCIpICArCiAgbGFicyhmaWxsPSdUaW1lcG9pbnQnKSAKCmRlbi4yCmBgYAoKIyMjIEludGVyYWN0aXZlIERhdGEgVGFibGUKCmBgYHtyfQpsaWJyYXJ5KERUKQpwY2w1LmRhdGF0YWJsZT0gcGNsNS50b3QKICAKZGF0YXRhYmxlKGRhdGEgPSBwY2w1LmRhdGF0YWJsZSwgd2lkdGg9TlVMTCwgIGZpbHRlciA9ICJ0b3AiLCBjYXB0aW9uPSAiUEhRLTkgU3VtbWFyeSBSZXN1bHRzIiwgcm93bmFtZXM9RiwgY29sbmFtZXMgPSBjKCdSZWNvcmQgSUQnLCAnQ2FzZSBJRCcsICdCYXNlbGluZSBTY29yZScsICdSZWF1dGhvcml6YXRpb24gU2NvcmUnLCAnRGlzY2hhcmdlIFNjb3JlJywgJ0NoYW5nZSBpbiBTY29yZScsICJJbXByb3ZlbWVudCBUeXBlIiksCiAgICAgICAgICBvcHRpb25zID0gbGlzdChwYWdlbGVuZ3RoPTI1LAogIGluaXRDb21wbGV0ZSA9IEpTKAogICAgImZ1bmN0aW9uKHNldHRpbmdzLCBqc29uKSB7IiwKICAgICIkKHRoaXMuYXBpKCkudGFibGUoKS5oZWFkZXIoKSkuY3NzKHsnYmFja2dyb3VuZC1jb2xvcic6ICdncmV5JywgJ2NvbG9yJzogJyNmZmYnfSk7IiwKICAgICJ9IikpKQoKCmBgYAoKIyMgQ0QgUmlzYyB7LnRhYnNldH0KIyMjIFB1cnBvc2UgYW5kIEV2YWx1YXRpb24KCj4gVGhlIENvbm5vci1EYXZpZHNvbiBSZXNpbGxpZW5jZSBTY2FsZQoKPiBNZWFzdXJlIG9mIHBzeWNob2xvZ2ljYWwgcmVzaWxsaWVuY2UuIFRoZXNlIHJhdGluZ3MgcmVzdWx0IGluIGEgbnVtYmVyIGJldHdlZW4gMOKAkzQwLCBhbmQgaGlnaGVyIHNjb3JlcyBpbmRpY2F0ZSBoaWdoZXIgcmVzaWxpZW5jZS4gVGhlIDEwIGl0ZW0gdmVyc2lvbiBjb21wcmlzZXMgaXRlbXMgMSwgNCwgNiwgNywgOCwgMTEsIDE0LCAxNiwgMTcsIDE5IGZyb20gdGhlIG9yaWdpbmFsIHNjYWxlLCBhbmQgd2FzIGRldmVsb3BlZCBieSBEcnMuIENhbXBiZWxsLVNpbGxzIGFuZCBTdGVpbiwgYXQgdGhlIFVuaXZlcnNpdHkgb2YgQ2FsaWZvcm5pYSwgU2FuIERpZWdvLCBvbiB0aGUgYmFzaXMgb2YgZmFjdG9yIGFuYWx5c2lzLiBJbiBhIGNvbW11bml0eSBzdXJ2ZXkgb2YgNzY0IFVTIGFkdWx0cywgYSBtZWFuIHNjb3JlIG9mIDMxLjggKFNEID0gNS40KSB3YXMgb2J0YWluZWQgZm9yIHRoZSBDRC1SSVNDIDEwIChDYW1wYmVsbC1TaWxscyBMLCBGb3JkZSBEUiwgU3RlaW4gTUIuIEogUHN5Y2hpYXRyaWMgUmVzZWFyY2ggKDIwMDkpLCBkb2k6MTAuMTAxNi9qLmpwc3ljaGlyZXMuMjAwOS4wMS4wMTMpLiBUaGUgcG9wdWxhdGlvbiBxdWFydGlsZSBzY29yZXMgZm9yIHRoZSBDRC1SSVNDLTEwIGFyZSBhcyBmb2xsb3dzOiAyNXRoICUgPSAyOTsgNTB0aCAlID0gMzI7IDc1dGggJSA9IDM2LiBBbiBhbG1vc3QgaWRlbnRpY2FsIG1lYW4gc2NvcmUgd2FzIG9idGFpbmVkIGJ5IERhdmlkc29uIGluIHRoZSBVUyBnZW5lcmFsIHBvcHVsYXRpb24gc2FtcGxlIHN0dWRpZWQgaW4gdGhlIDIwMDMgcmVwb3J0IGFib3ZlLgoKPldpbmdvIGV0IGFsICgyMDE3KSBmb3VuZCBtZWFuIG9mIDIzLjYgKDcuOSBTRCkgaW4gdmV0ZXJhbnMgd2l0aCBQVFNEIGFuZCBkZXByZXNzaW9uCgojIyMgU3VtbWFyeSBTdGF0aXN0aWNzCgpgYGB7ciwgd2FybmluZz1GLCBwcmludD1GfQpjZC5yaXNjW2NkLnJpc2MgPT0gIk5vdCBhdCBhbGwiXSA8LSAiMCIKY2QucmlzY1tjZC5yaXNjID09ICJSYXJlbHkgVHJ1ZSJdIDwtICIxIiAKY2QucmlzY1tjZC5yaXNjID09ICJTb21ldGltZXMgVHJ1ZSJdIDwtICIyIiAKY2QucmlzY1tjZC5yaXNjID09ICJPZnRlbiBUcnVlIl0gPC0gIjMiIApjZC5yaXNjW2NkLnJpc2MgPT0gIlRydWUgTmVhcmx5IGFsbCBvZiB0aGUgVGltZSJdIDwtICI0IiAKCmNkLnJpc2MgPC0gY2QucmlzYyAlPiUgCiAgICAgbXV0YXRlX2F0KGMoNToxNCksIGFzLm51bWVyaWMpCgpjZC5yaXNjJHRvdGFsIDwtIGFzLm51bWVyaWMoYXBwbHkoY2QucmlzY1ssNToxNF0sIDEsIHN1bSkpCgpjZC5yaXNjLnRvdD1zdWJzZXQoY2QucmlzYywgc2VsZWN0ID0gYygxLDIsMywxNikpCmNkLnJpc2MudG90PXNwcmVhZChjZC5yaXNjLnRvdCwga2V5ID0gYEV2ZW50IE5hbWVgLCB2YWx1ZSA9IHRvdGFsKQoKY2QucmlzYy50b3QkYEluZGl2aWR1YWwgQmFzZWxpbmVgPWFzLm51bWVyaWMoY2QucmlzYy50b3QkYEluZGl2aWR1YWwgQmFzZWxpbmVgKQpjZC5yaXNjLnRvdCRgSW5kaXZpZHVhbCBSZWF1dGhvcml6YXRpb25gPWFzLm51bWVyaWMoY2QucmlzYy50b3QkYEluZGl2aWR1YWwgUmVhdXRob3JpemF0aW9uYCkKY2QucmlzYy50b3QkYEluZGl2aWR1YWwgRGlzY2hhcmdlYD1hcy5udW1lcmljKGNkLnJpc2MudG90JGBJbmRpdmlkdWFsIERpc2NoYXJnZWApCgojQ2FsY3VsYXRlIGNoYW5nZSBpbiBzY29yZSBiZXR3ZWVuIGluaXRpYWwgYW5kIGRpc2NoYXJnZQpjZC5yaXNjLnRvdCRjaGFuZ2U9Y2QucmlzYy50b3QkYEluZGl2aWR1YWwgRGlzY2hhcmdlYC1jZC5yaXNjLnRvdCRgSW5kaXZpZHVhbCBCYXNlbGluZWAKI0NhbGN1bGF0ZSBjaGFuZ2UgaW4gc2NvcmUgYmV0d2VlbiBpbml0aWFsIGFuZCByZWF1dGhvcml6YXRpb24KY2QucmlzYy50b3QkY2hhbmdlLnJlYXV0aD1jZC5yaXNjLnRvdCRgSW5kaXZpZHVhbCBSZWF1dGhvcml6YXRpb25gLWNkLnJpc2MudG90JGBJbmRpdmlkdWFsIEJhc2VsaW5lYAoKI0lGIGRpc2NoYXJnZSB2YWx1ZSBpcyBhdmFpbGFibGUsIHVzZSBpdCB0byBjYWxjdWxhdGUgY2hhbmdlLiBJZiBub3QsIHVzZSB0aGUgcmVldmFsdWF0aW9uIHZhbHVlIHRvIGNhbGN1bGF0ZSBjaGFuZ2UKI1JlbW92ZSBjb2x1bW5zIHVzZWQgdG8gY2FsY3VsYXRlIHRvIG9ubHkgbGVhdmUgY29sdW1uIHdpdGggY2hhbmdlIHZhbHVlCmNkLnJpc2MudG90PSBjZC5yaXNjLnRvdCAlPiUgCiAgICBtdXRhdGUoY2hhbmdlID0gY29hbGVzY2UoY2hhbmdlLGNoYW5nZS5yZWF1dGgpKQpjZC5yaXNjLnRvdD1zdWJzZXQoY2QucmlzYy50b3QsIHNlbGVjdCA9IGMoMTo2KSkKCmBgYAoKPlRoaXMgdGFibGUgc2hvd3MgdGhlIHRvdGFsIHNhbXBsZSBzaXplIGF2YWlsYWJsZSBhdCBlYWNoIHRpbWVwb2ludCAoTikgYW5kIHN1bW1hcnkgc3RhdGlzdGljcyBmb3IgdGhlIENELVJJU0Mgc2NvcmVzIGR1cmluZyBCYXNlbGluZSBFdmFsdWF0aW9uLCBSZWF0aHVyaXphdGlvbiwgYW5kIERpc2NoYXJnZS4gCgpgYGB7ciwgcHJpbnQ9RkFMU0UsIHJlc3VsdHM9RkFMU0UsIHdhcm5pbmc9RkFMU0UsIG1lc3NhZ2U9RkFMU0V9CmNkLnJpc2MudG90JGBSZWNvcmQgSURgPWFzLmNoYXJhY3RlcihjZC5yaXNjLnRvdCRgUmVjb3JkIElEYCkKYGBgCgpgYGB7cn0Kc3VtdGFibGUoY2QucmlzYy50b3QpCmBgYAoKCgojIyMgR3JhcGhpY3MKCj5DaGFuZ2UgaW4gU2V2ZXJpdHkgU2NvcmU6IFdoZW4gYXZhaWxhYmxlLCB0aGlzIGZyZXF1ZW5jeSBjaGFydCBzaG93cyB0aGUgZGlzdHJpYnV0aW9uIG9mIHNjb3JlIGNoYW5nZXMgZnJvbSBiYXNlbGluZSB0byBkaXNjaGFyZ2UuIFdoZW4gYSBkaXNjaGFyZ2Ugc2NvcmUgaXMgbm90IHlldCBhdmFpbGFibGUsIGl0IGlzIHRoZSBjaGFuZ2UgZnJvbSBiYXNlbGluZSB0byByZWF1dGhvcml6YXRpb24uIAoKYGBge3IsIHdhcm5pbmc9Rn0KZ2dwbG90KGNkLnJpc2MudG90LCBhZXMoY2hhbmdlKSkgKwogIGdlb21faGlzdG9ncmFtKGJpbndpZHRoPTUsIGNvbG9yPSJibGFjayIsIGZpbGw9ICJncmV5IikgKwogIHhsYWIoIkNoYW5nZSBpbiBSZXNpbGllbmN5IFNjb3JlIikgICsKICBnZ3RpdGxlKCJDaGFuZ2UgaW4gU2V2ZXJpdHkgU2NvcmUiKQpgYGAKCj4gRGlzdHJpYnV0aW9uIG9mIENELVJJU0Mgc2NvcmVzIGF0IGVhY2ggdGltZXBvaW50IChCYXNlbGluZSwgUmVhdXRob3JpemF0aW9uLCBhbmQgRGlzY2hhcmdlKS4gQ29sb3IgY29kZWQgZG90dGVkIGxpbmVzIGluZGljYXRlIG1lYW4gZm9yIGVhY2ggZ3JvdXAsIHdoaWxlIHNoYWRlZCByZWdpb25zIHNob3cgZGVuc2l0eSBvZiBvY2N1cmFuY2UuIERlcHJlc3Npb24gc2NvcmVzIG9mIG1pbmltYWwgdG8gc2V2ZXJlIGFyZSBpbmRpY2F0ZWQgb24gY2hhcnQuIFRoZSBkb3R0ZWQgZ3JleSBsaW5lIGluZGljYXRlcyB0aGUgYXZlcmFnZSBDRC1SSVNDIHNjb3JlIHByZXZpb3VzbHkgZm91bmQgZm9yIHZldGVyYW5zIHdpdGggUFRTRCBhbmQgZGVwcmVzc2lvbiAoV2luZ28gZXQuIGFsLCAyMDE3KSwgYW5kIHRoZSBzaGFkZWQgZ3JheSBib3ggaW5kaWNhdGVzIGEgU0Qgb2YgNy45IGZvciB0aGUgc2FtZSBwb3B1bGF0aW9uLgoKCj4gTm90ZTogTWVhbiBzY29yZXMgZm9yIHRoZSBnZW5lcmFsIHB1YmxpYyBhcmUgaGlnaGVyLCBhbmQgdGhlIHF1YXJ0aWxlcyBhcmUgYXMgZm9sbG93czogMjV0aCAlID0gMjk7IDUwdGggJSA9IDMyOyA3NXRoICUgPSAzNi4KCmBgYHtyLCB3YXJuaW5nPUZ9Cm1lYW5fYmFzZWxpbmUzPW1lYW4oY2QucmlzYy50b3QkYEluZGl2aWR1YWwgQmFzZWxpbmVgLCBuYS5ybSA9IFQpCm1lYW5fcmVhdXRoMz1tZWFuKGNkLnJpc2MudG90JGBJbmRpdmlkdWFsIFJlYXV0aG9yaXphdGlvbmAsIG5hLnJtID0gVCkKbWVhbl9kaXNjaGFyZ2UzPW1lYW4oY2QucmlzYy50b3QkYEluZGl2aWR1YWwgRGlzY2hhcmdlYCwgbmEucm0gPSBUKQoKI3NoYWRlZCBncmV5IGJveCBpbmRpY2F0ZXMgcHJldmlvdXMgZmluZGluZ3Mgb2YgbWVhbiArLy0gU0QgZm9yIHZldGVyYW5zIHdpdGggUFRTRCBhbmQgRGVwcmVzc2lvbgpkZW4uMz1nZ3Bsb3QoKSArCmdlb21fZGVuc2l0eShhZXMoYEluZGl2aWR1YWwgQmFzZWxpbmVgLCBmaWxsPSJCYXNlbGluZSIpLCBhbHBoYT0wLjIsICBkYXRhPWNkLnJpc2MudG90KSArIApnZW9tX2RlbnNpdHkoYWVzKGBJbmRpdmlkdWFsIFJlYXV0aG9yaXphdGlvbmAsIGZpbGw9IlJlYXV0aG9yaXphdGlvbiIpLCBhbHBoYT0wLjIsIGRhdGE9Y2QucmlzYy50b3QpICsgCiAgZ2VvbV9kZW5zaXR5KGFlcyhgSW5kaXZpZHVhbCBEaXNjaGFyZ2VgLCBmaWxsPSJEaXNjaGFyZ2UiKSwgYWxwaGE9MC4yLCBkYXRhPWNkLnJpc2MudG90KSArIAogICAgbGFicyh0aXRsZT0iQ0QtUklTQyIsIAogICAgICAgICBzdWJ0aXRsZT0iRGlzdHJpYnV0aW9uIG9mIFJlc2lsaWVuY3kgU2NvcmVzIiwKICAgICAgICAgeD0iU2NvcmUiKSArCiAgeWxhYigiRGVuc2l0eSIpICsKICAgICBhbm5vdGF0ZSgicmVjdCIsIHhtaW49MTUuNywgeG1heD0zMS41LCB5bWluPTAsIHltYXg9SW5mLCBhbHBoYSA9IC4xKSArCiAgZ2VvbV92bGluZSh4aW50ZXJjZXB0PW1lYW5fYmFzZWxpbmUzLCBzaXplPTEsIGNvbG9yPSJwaW5rIiwgbGluZXR5cGU9ImRvdHRlZCIpICsKICBnZW9tX3ZsaW5lKHhpbnRlcmNlcHQ9bWVhbl9yZWF1dGgzLCBzaXplPTEsIGNvbG9yPSJibHVlIiwgIGxpbmV0eXBlPSJkb3R0ZWQiKSArCiAgZ2VvbV92bGluZSh4aW50ZXJjZXB0PW1lYW5fZGlzY2hhcmdlMywgc2l6ZT0xLCBjb2xvcj0iZ3JlZW4iLCAgbGluZXR5cGU9ImRvdHRlZCIpICsKICBnZW9tX3ZsaW5lKHhpbnRlcmNlcHQ9MjMuNiwgc2l6ZT0xLCBjb2xvcj0iZ3JleSIsICBsaW5ldHlwZT0iZG90dGVkIikgKwogIGFubm90YXRlKGdlb209InRleHQiLCB4PTI2LjUsIHk9MC4wNzUsIHNpemU9MywgbGFiZWw9IlZldGVyYW5zIHdpdGggUFRTRCIsIGNvbG9yPSJibGFjayIpICsKICAgIGFubm90YXRlKGdlb209InRleHQiLCB4PTI2LjUsIHk9MC4wNzIsIHNpemU9MywgbGFiZWw9ImFuZCBEZXByZXNzaW9uIiwgY29sb3I9ImJsYWNrIikrCiAgYW5ub3RhdGUoZ2VvbT0idGV4dCIsIHg9MjYuNSwgeT0wLjA2OSwgc2l6ZT0yLCBsYWJlbD0iKFdpbmdvIGV0LiBhbC4sIDIwMTcpIiwgY29sb3I9ImJsYWNrIikgICsKICBsYWJzKGZpbGw9J1RpbWVwb2ludCcpIAoKZGVuLjMKYGBgCgojIyMgSW50ZXJhY3RpdmUgRGF0YSBUYWJsZQpgYGB7cn0KbGlicmFyeShEVCkKY2QucmlzYy5kYXRhdGFibGU9IGNkLnJpc2MudG90CiAgCmRhdGF0YWJsZShkYXRhID0gY2QucmlzYy5kYXRhdGFibGUsIHdpZHRoPU5VTEwsICBmaWx0ZXIgPSAidG9wIiwgY2FwdGlvbj0gIlBIUS05IFN1bW1hcnkgUmVzdWx0cyIsIHJvd25hbWVzPUYsIGNvbG5hbWVzID0gYygnUmVjb3JkIElEJywgJ0Nhc2UgSUQnLCAnQmFzZWxpbmUgU2NvcmUnLCAnUmVhdXRob3JpemF0aW9uIFNjb3JlJywgJ0Rpc2NoYXJnZSBTY29yZScsICdDaGFuZ2UgaW4gU2NvcmUnKSwKICAgICAgICAgIG9wdGlvbnMgPSBsaXN0KHBhZ2VsZW5ndGg9MjUsCiAgaW5pdENvbXBsZXRlID0gSlMoCiAgICAiZnVuY3Rpb24oc2V0dGluZ3MsIGpzb24pIHsiLAogICAgIiQodGhpcy5hcGkoKS50YWJsZSgpLmhlYWRlcigpKS5jc3MoeydiYWNrZ3JvdW5kLWNvbG9yJzogJ2dyZXknLCAnY29sb3InOiAnI2ZmZid9KTsiLAogICAgIn0iKSkpCgoKYGBgCgojIyBTdW1tYXJ5IFZpZXcgey50YWJzZXR9Cgo+IEtleSBUYWtlYXdheXMKCjEuIEFzIG9mIEF1Z3VzdCAzMXRoIDIwMjMsIGF0IHRoZSBhZ2dyZWdhdGUgbGV2ZWwsIG5vbmUgb2YgdGhlIHRocmVlIG1lYXN1cmVzIGFyZSBzaG93aW5nIHNpZ25zIG9mIGNsaW5pY2FsIGltcHJvdmVtZW50LCBob3dldmVyIHRoZSBQQ0wtNSBQVFNEIHNjcmVlbmVyIGlzIHNob3dpbmcgcmVzcG9uc2UgdG8gdHJlYXRtZW50LgoyLiBDdW11bGF0aXZlIGRhdGEgc2hvd3Mgbm9uLWNsaW5pY2FsbHkgc2lnbmlmaWNhbnQgaW1wcm92ZW1lbnRzIGluIERlcHJlc3Npb24gYW5kIFJlc2lsaWVuY2Ugc2NhbGVzLiAKMy4gV2hpbGUgc2FtcGxlIHNpemUgaXMgc3RpbGwgbGltaXRlZCwgd2hpY2ggaXMgbGVhZGluZyB0byBleHRyZW1lIGNoYW5nZXMgaW4gZGF0YSBwYXR0ZXJucyBmcm9tIG1vbnRoIHRvIG1vbnRoLCBhbGwgdGhyZWUgbWVhc3VyZXMgYXJlIG5vdyBpbXByb3Zpbmcgb3ZlciB0aW1lIGFzIHdlIGdhaW4gYWRkaXRpb25hbCBkaXNjaGFyZ2UgZGF0YSAoc2VlIGZpZ3VyZSBiZWxvdykuIEhvd2V2ZXIsIHRoaXMgc2hvdWxkIGJlIGludGVycHJldGVkIGNhcmZ1bGx5LCBhcyBzYW1wbGUgc2l6ZSBvbmx5IGluY3JlYXNlZCBieSAxIGluZGl2aWR1YWwgZnJvbSBKdWx5IHRvIEF1Z3VzdCwgYW5kIGxlZCB0byBhbiBleHRlcm1lbSBwZXJjZW50IGltcHJvdmVtZW50IG9mIG91dGNvbWUuCgo+IFBlciBBc3Nlc3NtZW50IFN1bW1hcnkKCi0gUEhRLTkgaW5kaWNhdGVzIGEgZGVjcmVhc2UgaW4gRGVwcmVzc2lvbiBmcm9tIGJhc2VsaW5lIHRvIGJvdGggcmVhdXRob3JpemF0aW9uIGFuZCBkaXNjaGFyZ2UuIFRoZSBtZWFuIHZhbHVlcyBhdCBlYWNoIHRpbWVwb2ludCByZW1haW4gd2l0aGluIHRoZSAiTW9kZXJhdGVseSBTZXZlcmUiIGNhdGVnb3JpemF0aW9uLiBIb3dldmVyLCBieSBiYXNlbGluZSB0aGUgc2NvcmUgaXMgMTQuNjcsIGFuZCAxNCBpcyBjb25zaWRlcmVkICJNb2RlcmF0ZSIuICBHcmVhdGVyIHRoYW4gYSAxU0QgY2hhbmdlIGluIHNjb3JlICg2LjA1IGFzIG9mIEF1Z3VzdCkgaXMgdGhlIFNTUyBkZXRlcm1pbmF0aW9uIG9mIGNsaW5pY2FsIGltcHJvdmVtZW50LiBUaGUgY3VycmVudCBpbXByb3ZlbWVudCBpcyBhdCBhIHNjb3JlIG9mIDIuMTMuIAotIFBDTC01IGltcHJvdmVtZW50IG9mIDYuMjUlIG9yIDEyLjUlIHdvdWxkIGluZGljYXRlIHJlc3BvbnNlIHRvIHRyZWF0bWVudCBvciBjbGluaWNhbCBpbXByb3ZlbWVudCByZXNwZWN0aXZlbHkuIENlbnRlcnN0b25lIGN1cnJlbnRseSByZXBvcnRzIDkuMDYlIGltcHJvdmVtZW50IG9uIGF2ZXJhZ2UgYmV0d2VlbiBiYXNlbGluZSBhbmQgY3VycmVudCBsZXZlbHMgKGRpc2NoYXJnZSB3aGVuIGF2YWlsYWJsZSwgcmVhdXRob3JpemF0aW9uIHdoZW4gZGlzY2hhcmdlIGFzIG5vdCBvY2N1cnJlZCkuIFdoaWxlIHRoZXJlIGlzIGEgInJlc3BvbnNlIHRvIHRyZWF0bWVudCIgaW4gUFRTRCBzY29yZSBmcm9tIGJhc2VsaW5lIHRvIHJlYXRob3JpemF0aW9uIGFuZCBkaXNjaGFyZ2UsIGF0IHRoaXMgdGltZSwgMTYgY2xpZW50cyBzaG93IGNsaW5pY2FsIGltcHJvdmVtZW50LCAzIGFyZSByZXNwb25kaW5nIHRvIHRyZWF0bWVudCwgOCBoYXZlIG5vIHJlc3BvbnNlLCBhbmQgMTcgaGF2ZSByZXBvcnRlZCBpbmNyZWFzZWQgUFRTRCBzeW1wdG9tcy4gCi0gQ0QtUmlzYyBpbmRpY2F0ZXMgdGhhdCBvdXIgY2xpZW50cyBmYWxsIHdpdGhpbiB0aGUgcHJldmlvdXNseSByZXBvcnRlZCByYW5nZSBvZiBSZXNpbGllbmN5IGZvciB2ZXRlcmFucyB3aXRoIFBUU0QgYW5kIERlcHJlc3Npb24uIFJlc2lsaWVuY2Ugc2NvcmVzIGRlY3JlYXNlIGZyb20gYmFzZWxpbmUgc2xpZ2h0bHkgYXQgZGlzY2hhcmdlLCB3aGlsZSB0aGUgYXJlIGltcHJvdmVkIGF0IG1lYXN1cmVzIG9mIHJlYXV0aG9yaXphdGlvbi4gR3JlYXRlciB0aGFuIGEgMVNEIGNoYW5nZSBpbiBzY29yZSAoNy4yOSBhcyBvZiBBdWd1c3QpIGlzIHRoZSBTU1MgZGV0ZXJtaW5hdGlvbiBvZiBjbGluaWNhbCBpbXByb3ZlbWVudC4gVGhlIGN1cnJlbnQgYXZlcmFnZSBzY29yZSBoYXMgZGVjcmVhc2VkIGJ5IDEuNTUuIAoKPiBTdW1tYXJ5IFRhYmxlCgpTdW1tYXJ5IGRhdGEgaXMgcHJlc2VudGVkIHNob3dpbmcgaG93IGN1bXVsYXRpdmUgaW1wcm92ZW1lbnQgc2NvcmVzIGhhdmUgY2hhbmdlZCBvdmVyIHRpbWUuIFBsZWFzZSBub3RlIHRoYXQgYWxsIGRhdGEgcHJlc2VudGVkIGlzIGFuYWx5emVkIHRocm91Z2ggdGhlIG1vbnRoIGxpc3RlZCwgbm90IHdpdGhpbiB0aGF0IDMwIGRheSBwZXJpb2QgKGV4LiBNYXkgZGF0YSBpbmNsdWRlcyBhbGwgZGF0YSBwcmlvciB0byBtYXksIGluY2x1ZGluZyBBcHJpbCkuIAoKQ2hhbmdlcyBkaXNwbGF5ZWQgaW4gbmVnYXRpdmUgdmFsdWVzIGZvciB0aGUgUEhRLTkgYW5kIFBDTC01IGluZGljYXRlIGltcHJvdmVtZW50LCB3aGlsZSBhIHBvc2l0aXZlIHZhbHVlIGZvciB0aGUgQ0QtUmlzYyBpbmRpY2F0ZXMgaW1wcm92ZW1lbnQuIAoKYGBge3IsIHByaW50PUYsIHdhcm5pbmc9Rn0KCnN1bXRhYj0gZGF0YS5mcmFtZSgKICBNb250aCA9IGMoIkFwcmlsIiwgIk1heSIsICJKdW5lIiwgIkp1bHkiLCAiQXVndXN0IiksCiAgTi5BbmF5bHplZD1jICgzNywgMzksIDQwLCA0NCwgNDUpLAogIE4uRGlzY2hhcmdlZD1jKDEwLDE2LCAxOCwgMjEsIDIxKSwKICBQSFE5PSBjKC0xLjIxNiwgLTAuNzY5LCAtMC44NSwgLTEuODIsIC0yLjEzKSwKICBQQ0w1PWMoLTIuODMzLCAtMi45MjEsIC0zLjE1NCwgLTYuMTE2LCAtNy4yNSksCiAgQ0RSaXNjPWMoMC4wNTksLTAuMDg2LCAtMC4xNzEsIDEuMzg1LCAxLjU1KQopCgpzdW10YWIkTW9udGg9CnN1bXRhYiRNb250aCA8LSBmYWN0b3Ioc3VtdGFiJE1vbnRoLCBsZXZlbHM9YygnQXByaWwnLCAnTWF5JywgJ0p1bmUnLCAnSnVseScsICdBdWd1c3QnKSkKCgpkYXRhdGFibGUoZGF0YSA9IHN1bXRhYiwgd2lkdGg9TlVMTCwgIGZpbHRlciA9ICJ0b3AiLCBjYXB0aW9uPSAiQ3VtdWxhdGl2ZSBSZXN1bHRzIGJ5IE1vbnRoIiwgcm93bmFtZXM9RiwgY29sbmFtZXMgPSBjKCdNb250aCcsICdOIEFuYWx5c2VkJywgIk4gRGlzY2hhcmdlZCIsICdDdW11bGF0aXZlIFBIUS05JywgJ0N1bXVsYXRpdmUgUENMLTUnLCAnQ3VtdWxhdGl2ZSBDRC1SaXNjJyksCiAgICAgICAgICBvcHRpb25zID0gbGlzdChwYWdlbGVuZ3RoPTI1LAogIGluaXRDb21wbGV0ZSA9IEpTKAogICAgImZ1bmN0aW9uKHNldHRpbmdzLCBqc29uKSB7IiwKICAgICIkKHRoaXMuYXBpKCkudGFibGUoKS5oZWFkZXIoKSkuY3NzKHsnYmFja2dyb3VuZC1jb2xvcic6ICdncmV5JywgJ2NvbG9yJzogJyNmZmYnfSk7IiwKICAgICJ9IikpKQoKCgpgYGAKCj4gU3VtbWFyeSBHcmFwaGljcwoKR3JhcGhpYyBkZXBpY3RpbmcgdGhlIGNoYW5nZSBpbiBpbXByb3ZlbWVudCBvdmVyIHRpbWUgaW4gcGVyY2VudGFnZXMuIAoKKipQSFEtOSBhbmQgQ0QtUmlzYyoqOiBDbGluaWNhbCBpbXByb3ZtZW50IGlzIGluZGljYXRlZCBieSBhIGdyZWF0ZXIgdGhhbiAxIHN0YW5kYXJkIGRldmlhdGlvbiBpbXByb3ZtZW50IGluIHNjb3JlcyBmb3IgdGhlIGJhc2VsaW5lIGFzc2Vzc21lbnQuU2VlICJQZXIgQXNzZXNzbWVudCBTdW1tYXJ5IiBhYm92ZSBmb3Igc3BlY2lmaWMgdmFsdWVzLiAKCioqUENMLTUqKjogQ2xpbmljYWwgaW1wcm92ZW1lbnQgb24gYSBwZXItY2xpZW50IGJhc2lzIGlzIGNvbnNpZGVyZWQgYSBtaW5pbXVtIG9mIDEyLjUlIGltcHJvdm1lbnQgaW4gc2NvcmUuIFJlc3BvbmRpbmcgdG8gdHJlYXRtZW50IGlzIGNvbnNpZGVyZWQgYSBtaW5pbXVtIG9mIDYuMjUlIGltcHJvdm1lbnQuIAoKCmBgYHtyLCBwcmludD1GLCB3YXJuaW5nPUZ9CgpzdW10YWIucGVyYz1zdW10YWIKc3VtdGFiLnBlcmMkUEhROS5wPXN1bXRhYi5wZXJjJFBIUTkvMjcqKC0xMDApCnN1bXRhYi5wZXJjJFBDTDUucD1zdW10YWIucGVyYyRQQ0w1LzgwKigtMTAwKQpzdW10YWIucGVyYyRDRFJpc2MucD1zdW10YWIucGVyYyRDRFJpc2MvNDAqMTAwCgpwZXJjZW50cy5sb25nIDwtIGdhdGhlcihzdW10YWIucGVyYywgQXNzZXNzbWVudCwgUGVyY0ltcHJvdiwgUEhROS5wOkNEUmlzYy5wLCBmYWN0b3Jfa2V5PVRSVUUpCgpmYWNldF90aXRsZXMgPC0gYygKICAgICAgICAgICAgICAgICAgICBgUEhROS5wYCA9ICJQSFEtOTogRGVzcHJlc3Npb24gU2NhbGUiLAogICAgICAgICAgICAgICAgICAgIGBQQ0w1LnBgID0gIlBDTC01OiBQVFNEIFNjYWxlIiwKICAgICAgICAgICAgICAgICAgICBgQ0RSaXNjLnBgID0gIkNELVJpc2M6IFJlc2lsaWVuY2UgU2NhbGUiCiAgICAgICAgICAgICAgICAgICAgKQoKcGVyYy5wbD1nZ3Bsb3QocGVyY2VudHMubG9uZywgYWVzKE1vbnRoLCBQZXJjSW1wcm92KSwgZ3JvdXA9QXNzZXNzbWVudCkgKyAgICAgICAgICAgICAgICAgICAgICAKICBnZW9tX2xpbmUoYWVzKGdyb3VwPTEpLCBjb2xvcj0iZ3JlZW4iKSArCiAgZ2VvbV9wb2ludChjb2xvciA9ICJncmVlbiIpICsKICB5bGFiKCJQZXJjZW50IEltcHJvdmVtZW50IikgKyAgCiAgZmFjZXRfd3JhcCggfiBBc3Nlc3NtZW50LCBuY29sPTEsIHNjYWxlcyA9ICJmcmVlIiwgbGFiZWxsZXIgPSBhc19sYWJlbGxlcihmYWNldF90aXRsZXMpKQoKZ2dwbG90bHkocGVyYy5wbCwgdG9vbHRpcD1jKCJNb250aCIsICJBc3Nlc3NtZW50IiwgIlBlcmNJbXByb3YiKSkKCmBgYAoKCmBgYHtyLCBwcmludD1GLCB3YXJuaW5nPUYsIGV2YWw9Rn0KI0dyYXBoaWMgZGVwaWN0aW5nIHRoZSBjaGFuZ2UgaW4gaW1wcm92bWVudCBvdmVyIHRpbWUgaW4gcmF3IHNjb3Jlcy4gCgpzdW10YWIubG9uZyA8LSBnYXRoZXIoc3VtdGFiLCBBc3Nlc3NtZW50LCBTY29yZSwgUEhROTpDRFJpc2MsIGZhY3Rvcl9rZXk9VFJVRSkKCmZhY2V0X3RpdGxlcyA8LSBjKAogICAgICAgICAgICAgICAgICAgIGBQSFE5YCA9ICJQSFEtOSAoSW1wcm92bWVudCBpbmRpY2F0ZWQgYnkgZGVjcmVhc2UpIiwKICAgICAgICAgICAgICAgICAgICBgUENMNWAgPSAiUENMLTUgKEltcHJvdm1lbnQgaW5kaWNhdGVkIGJ5IGRlY3JlYXNlKSIsCiAgICAgICAgICAgICAgICAgICAgYENEUmlzY2AgPSAiQ0QtUmlzYyAoSW1wcm92bWVudCBpbmRpY2F0ZWQgYnkgaW5jcmVhc2UpIgogICAgICAgICAgICAgICAgICAgICkKCnN1bS5wbDE9Z2dwbG90KHN1bXRhYi5sb25nLCBhZXMoTW9udGgsIFNjb3JlKSwgZ3JvdXA9QXNzZXNzbWVudCkgKyAgICAgICAgICAgICAgICAgICAgICAKICBnZW9tX2xpbmUoYWVzKGdyb3VwPTEpLCBjb2xvcj0iZ3JleSIpICsKICBnZW9tX3BvaW50KGNvbG9yID0gImdyZXkiKSArCiAgZmFjZXRfd3JhcCggfiBBc3Nlc3NtZW50LCBuY29sPTEsIHNjYWxlcyA9ICJmcmVlIiwgbGFiZWxsZXIgPSBhc19sYWJlbGxlcihmYWNldF90aXRsZXMpKQoKCmdncGxvdGx5KHN1bS5wbDEpCgpgYGAKCg==