#Importing functions:
source("~/R/software-history/scripts/utils.R")
#Rqs Results
filenames = list.files(
  path = paste0("~/R/analysis/results_rqs"),
  full.names = TRUE,
  recursive = TRUE
)
results_frame <- do.call(rbind, lapply(filenames, function(i) {
  read.csv(i, stringsAsFactors = FALSE)
}))
#Insertions
filenames = list.files(
  path = paste0("~/R/analysis/results_insertions"),
  full.names = TRUE,
  recursive = TRUE
)
methods_insertions <- do.call(rbind, lapply(filenames, function(i) {
  read.csv(i, stringsAsFactors = FALSE)
}))
#Total Insertions
filenames = list.files(
  path = paste0("~/R/analysis/results"),
  full.names = TRUE,
  recursive = TRUE
)
methods_total <- do.call(rbind, lapply(filenames, function(i) {
  read.csv(i, stringsAsFactors = FALSE)
}))
#Final Data Frame
data_plot <- as.data.frame(
  results_frame %>%
    dplyr::group_by(Project, NoCommits) %>%
    dplyr::summarise(
      noTimeSeries = max(noTimeSeries),
      noChanges = sum(noChanges),
      noBugsIns = sum(noBugsIns),
      BugsByTs = sum(noBugsIns) / max(noTimeSeries),
      BugsByChanges = sum(noBugsIns) / sum(noChanges),
      ChangesByTs = sum(noChanges) / max(noTimeSeries)
    ) %>%
    dplyr::mutate(
      PercBugsByTs = (BugsByTs / sum(BugsByTs)) * 100,
      PercBugsByCommit = (noBugsIns / sum(noBugsIns)) * 100,
      PercBugsByChanges = (BugsByChanges / sum(BugsByChanges)) * 100,
      PercTs = (noTimeSeries / sum(noTimeSeries)) * 100,
      PercChangesByTs = (ChangesByTs / sum(ChangesByTs)) * 100,
      PercChanges = (noChanges / sum(noChanges)) * 100
    ) %>%
    dplyr::ungroup()
)
data_plot[data_plot$Project == "Elasticsearch-hadoop",c("Project")] <- "Es. Hadoop"
data_plot[data_plot$Project == "Signal-Android",c("Project")] <- "S. Android"
data_plot[data_plot$Project == "Material Drawer",c("Project")] <- "M. Drawer"
data_plot[data_plot$Project == "Material-Dialogs",c("Project")] <- "M. Dialogs"
projects <- unique(data_plot$Project)

(G1)To investigate the occurrence of commits along the history;

(Q1.1) How often are commits performed?

p1 <- ggplot(filter(data_plot, Project %in% projects[1:4], NoCommits <= 10 )) +
  geom_bar(aes(x=NoCommits,y=PercTs,group=Project), position = "dodge", stat = "identity")+
  facet_grid(.~Project,scales="free") + 
  theme(legend.position= c(0.7, 0.95), legend.direction="horizontal", legend.title = element_blank(), 
        legend.text=element_text(size=7), legend.background = element_rect(fill = "transparent", colour = NA) ) +
  ylab("Percentual") + scale_x_discrete(name ="Number of Commits", limits=seq(1,10)) +
  #theme(axis.title.x=element_blank(), axis.title.y = element_blank()) +
  theme(panel.grid.minor = element_blank(), 
        panel.grid.major = element_blank(),
        plot.background = element_rect(fill = "transparent", colour = NA),
        axis.text.x = element_text(colour="grey20",size=5,hjust=.5,vjust=.5,face="plain"))
p2 <- ggplot(filter(data_plot, Project %in% projects[5:7], NoCommits <= 10 )) +
  geom_bar(aes(x=NoCommits,y=PercTs,group=Project), position = "dodge", stat = "identity")+
  facet_grid(.~Project,scales="free") + 
  theme(legend.position= c(0.7, 0.95), legend.direction="horizontal", legend.title = element_blank(), 
        legend.text=element_text(size=7), legend.background = element_rect(fill = "transparent", colour = NA) ) +
  ylab("Percentual") + scale_x_discrete(name ="Number of Commits", limits=seq(1,10)) +
  #theme(axis.title.x=element_blank(), axis.title.y = element_blank()) +
  theme(panel.grid.minor = element_blank(), 
        panel.grid.major = element_blank(),
        plot.background = element_rect(fill = "transparent", colour = NA),
        axis.text.x = element_text(colour="grey20",size=5,hjust=.5,vjust=.5,face="plain"))
ggarrange(p1 , p2 , ncol = 1, nrow = 2)

(Q1.2) How often are changes performed among commits?

#Percentual
p1 <- ggplot(filter(data_plot, Project %in% projects[1:4], NoCommits <= 10 )) +
  geom_bar(aes(x=NoCommits,y=PercChanges,group=Project), position = "dodge", stat = "identity")+
  facet_grid(.~Project,scales="free") + 
  theme(legend.position= c(0.7, 0.95), legend.direction="horizontal", legend.title = element_blank(), 
        legend.text=element_text(size=7), legend.background = element_rect(fill = "transparent", colour = NA) ) +
  ylab("Percentual") + scale_x_discrete(name ="Number of Commits", limits=seq(1,10)) +
  #theme(axis.title.x=element_blank(), axis.title.y = element_blank()) +
  theme(panel.grid.minor = element_blank(), 
        panel.grid.major = element_blank(),
        plot.background = element_rect(fill = "transparent", colour = NA),
        axis.text.x = element_text(colour="grey20",size=5,hjust=.5,vjust=.5,face="plain"))
p2 <- ggplot(filter(data_plot, Project %in% projects[5:7], NoCommits <= 10 )) +
  geom_bar(aes(x=NoCommits,y=PercChanges,group=Project), position = "dodge", stat = "identity")+
  facet_grid(.~Project,scales="free") + 
  theme(legend.position= c(0.7, 0.95), legend.direction="horizontal", legend.title = element_blank(), 
        legend.text=element_text(size=7), legend.background = element_rect(fill = "transparent", colour = NA) ) +
  ylab("Percentual") + scale_x_discrete(name ="Number of Commits", limits=seq(1,10)) +
  #theme(axis.title.x=element_blank(), axis.title.y = element_blank()) +
  theme(panel.grid.minor = element_blank(), 
        panel.grid.major = element_blank(),
        plot.background = element_rect(fill = "transparent", colour = NA),
        axis.text.x = element_text(colour="grey20",size=5,hjust=.5,vjust=.5,face="plain"))
ggarrange(p1 , p2 , ncol = 1, nrow = 2)

(Q1.3) How often are changes performed among time series?

#Percentual:
p1 <- ggplot(filter(data_plot, Project %in% projects[1:4], NoCommits <= 10 )) +
  geom_bar(aes(x=NoCommits,y=PercChangesByTs,group=Project), position = "dodge", stat = "identity") +
  facet_grid(.~Project,scales="free") + 
  theme(legend.position= c(0.7, 0.95), legend.direction="horizontal", legend.title = element_blank(), 
        legend.text=element_text(size=7), legend.background = element_rect(fill = "transparent", colour = NA) ) +
  ylab("Percentual") + scale_x_discrete(name ="Number of Commits", limits=seq(1,10)) +
  #theme(axis.title.x=element_blank(), axis.title.y = element_blank()) +
  theme(panel.grid.minor = element_blank(), 
        panel.grid.major = element_blank(),
        plot.background = element_rect(fill = "transparent", colour = NA),
        axis.text.x = element_text(colour="grey20",size=5,hjust=.5,vjust=.5,face="plain"))
p2 <- ggplot(filter(data_plot, Project %in% projects[5:7], NoCommits <= 10 )) +
  geom_bar(aes(x=NoCommits,y=PercChangesByTs,group=Project), position = "dodge", stat = "identity")+
  facet_grid(.~Project,scales="free") + 
  theme(legend.position= c(0.7, 0.95), legend.direction="horizontal", legend.title = element_blank(), 
        legend.text=element_text(size=7), legend.background = element_rect(fill = "transparent", colour = NA) ) +
  ylab("Percentual") + scale_x_discrete(name ="Number of Commits", limits=seq(1,10)) +
  #theme(axis.title.x=element_blank(), axis.title.y = element_blank()) +
  theme(panel.grid.minor = element_blank(), 
        panel.grid.major = element_blank(),
        plot.background = element_rect(fill = "transparent", colour = NA),
        axis.text.x = element_text(colour="grey20",size=5,hjust=.5,vjust=.5,face="plain"))
ggarrange(p1 , p2 , ncol = 1, nrow = 2)

(G2)To assess the introduction of bugs along the history;

(Q2.1) How often are bugs introduced among the commits?

#Perc
p1 <- ggplot(filter(data_plot, Project %in% projects[1:4], NoCommits <= 10 )) +
  geom_bar(aes(x=NoCommits,y=PercBugsByCommit,group=Project), position = "dodge", stat = "identity")+
  facet_grid(.~Project,scales="free") + 
  theme(legend.position= c(0.7, 0.95), legend.direction="horizontal", legend.title = element_blank(), 
        legend.text=element_text(size=7), legend.background = element_rect(fill = "transparent", colour = NA) ) +
  ylab("Percentual") + scale_x_discrete(name ="Number of Commits", limits=seq(1,10)) +
  #theme(axis.title.x=element_blank(), axis.title.y = element_blank()) +
  theme(panel.grid.minor = element_blank(), 
        panel.grid.major = element_blank(),
        plot.background = element_rect(fill = "transparent", colour = NA),
        axis.text.x = element_text(colour="grey20",size=5,hjust=.5,vjust=.5,face="plain"))
p2 <- ggplot(filter(data_plot, Project %in% projects[5:7], NoCommits <= 10 )) +
  geom_bar(aes(x=NoCommits,y=PercBugsByCommit,group=Project), position = "dodge", stat = "identity")+
  facet_grid(.~Project,scales="free") + 
  theme(legend.position= c(0.7, 0.95), legend.direction="horizontal", legend.title = element_blank(), 
        legend.text=element_text(size=7), legend.background = element_rect(fill = "transparent", colour = NA) ) +
  ylab("Percentual") + scale_x_discrete(name ="Number of Commits", limits=seq(1,10)) +
  #theme(axis.title.x=element_blank(), axis.title.y = element_blank()) +
  theme(panel.grid.minor = element_blank(), 
        panel.grid.major = element_blank(),
        plot.background = element_rect(fill = "transparent", colour = NA),
        axis.text.x = element_text(colour="grey20",size=5,hjust=.5,vjust=.5,face="plain"))
ggarrange(p1 , p2 , ncol = 1, nrow = 2)

(Q2.2) How often are bugs introduced among the time series?

#Percentual:
p1 <- ggplot(filter(data_plot, Project %in% projects[1:4], NoCommits <= 10 )) +
  geom_bar(aes(x=NoCommits,y=PercBugsByTs,group=Project), position = "dodge", stat = "identity")+
  facet_grid(.~Project,scales="free") + 
  theme(legend.position= c(0.7, 0.95), legend.direction="horizontal", legend.title = element_blank(), 
        legend.text=element_text(size=7), legend.background = element_rect(fill = "transparent", colour = NA) ) +
  ylab("Percentual") + scale_x_discrete(name ="Number of Commits", limits=seq(1,10)) +
  #theme(axis.title.x=element_blank(), axis.title.y = element_blank()) +
  theme(panel.grid.minor = element_blank(), 
        panel.grid.major = element_blank(),
        plot.background = element_rect(fill = "transparent", colour = NA),
        axis.text.x = element_text(colour="grey20",size=5,hjust=.5,vjust=.5,face="plain"))
p2 <- ggplot(filter(data_plot, Project %in% projects[5:7], NoCommits <= 10 )) +
  geom_bar(aes(x=NoCommits,y=PercBugsByTs,group=Project), position = "dodge", stat = "identity")+
  facet_grid(.~Project,scales="free") + 
  theme(legend.position= c(0.7, 0.95), legend.direction="horizontal", legend.title = element_blank(), 
        legend.text=element_text(size=7), legend.background = element_rect(fill = "transparent", colour = NA) ) +
  ylab("Percentual") + scale_x_discrete(name ="Number of Commits", limits=seq(1,10)) +
  #theme(axis.title.x=element_blank(), axis.title.y = element_blank()) +
  theme(panel.grid.minor = element_blank(), 
        panel.grid.major = element_blank(),
        plot.background = element_rect(fill = "transparent", colour = NA),
        axis.text.x = element_text(colour="grey20",size=5,hjust=.5,vjust=.5,face="plain"))
ggarrange(p1 , p2 , ncol = 1, nrow = 2)

(Q2.3) How often are bugs introduced among the changes?

#Perc:
p1 <- ggplot(filter(data_plot, Project %in% projects[1:4], NoCommits <= 10 )) +
  geom_bar(aes(x=NoCommits,y=PercBugsByChanges,group=Project), position = "dodge", stat = "identity")+
  facet_grid(.~Project,scales="free") + 
  theme(legend.position= c(0.7, 0.95), legend.direction="horizontal", legend.title = element_blank(), 
        legend.text=element_text(size=7), legend.background = element_rect(fill = "transparent", colour = NA) ) +
  ylab("Percentual") + scale_x_discrete(name ="Number of Commits", limits=seq(1,10)) +
  #theme(axis.title.x=element_blank(), axis.title.y = element_blank()) +
  theme(panel.grid.minor = element_blank(), 
        panel.grid.major = element_blank(),
        plot.background = element_rect(fill = "transparent", colour = NA),
        axis.text.x = element_text(colour="grey20",size=5,hjust=.5,vjust=.5,face="plain"))
p2 <- ggplot(filter(data_plot, Project %in% projects[5:7], NoCommits <= 10 )) +
  geom_bar(aes(x=NoCommits,y=PercBugsByChanges,group=Project), position = "dodge", stat = "identity")+
  facet_grid(.~Project,scales="free") + 
  theme(legend.position= c(0.7, 0.95), legend.direction="horizontal", legend.title = element_blank(), 
        legend.text=element_text(size=7), legend.background = element_rect(fill = "transparent", colour = NA) ) +
  ylab("Percentual") + scale_x_discrete(name ="Number of Commits", limits=seq(1,10)) +
  #theme(axis.title.x=element_blank(), axis.title.y = element_blank()) +
  theme(panel.grid.minor = element_blank(), 
        panel.grid.major = element_blank(),
        plot.background = element_rect(fill = "transparent", colour = NA),
        axis.text.x = element_text(colour="grey20",size=5,hjust=.5,vjust=.5,face="plain"))
ggarrange(p1 , p2 , ncol = 1, nrow = 2)

(G4) To analyse the relation between the history of changes and bugs;

(Q4.1) Is a high number of changes an indicative of bugs introduction?

#Changes Chart
methods_changes <- filter(methods_total, changeType == 'All', groupMetric == 'All', Metric == 'All')
#Calculing peaks
methods_changes[,"totalofBugsIns"] <- maply(methods_changes$bugsInsertion, getTotalBugsIns)
#Filtering only ts with bugs and more with one commit
methods_changes <- filter(methods_changes, totalofBugsIns > 0, NtimeofCommits > 1)
#Generating id of data frame
methods_changes <- genId(methods_changes)
#List of changes and bugs insertions
listofPeaks <<- methods_changes$elementsValue
listofBugsIns <<- methods_changes$bugsInsertion
#Creating columns
methods_changes[,c("peaks", "tp", "fp", "fn", "tn", "Precision", "Recall", "Fmeasure")] <- 0 
#calculating confusion matrix
methods_changes[,c("peaks", "tp", "fp", "fn", "tn", "Precision", "Recall", "Fmeasure")]  <-  plyr::ldply(methods_changes$id, getStatsProcess)
#Grouping data
confusion_matrix <- as.data.frame(
  methods_changes %>%
    dplyr::group_by(Project) %>%
    dplyr::summarise(
      Precision = median(Precision, na.rm = TRUE),
      Recall = median(Recall, na.rm = TRUE),
      Fmeasure = median(Fmeasure, na.rm = TRUE)
    )
)
#Pivot data
data_plot <- melt(confusion_matrix, id = (c("Project")))
colnames(data_plot) <- c("Project", "Measure", "Values")
#Ploting results
ggplot(data_plot) +
  geom_bar(aes(x = Project, y = Values, fill = Measure, group = Measure), position = "dodge", stat = "identity") +
  geom_text(aes(x = Project, y = Values, label = round(Values), group = Measure),  
             check_overlap = TRUE, position = position_dodge(width = 1), vjust = -0.5, size = 3) + #scale_fill_grey() + 
  theme(axis.text.x = element_text(angle = 45, hjust = 1)) +
  theme(legend.direction="vertical", legend.title = element_blank(),
        axis.title.x=element_blank(), legend.text=element_text(size=5), legend.background = element_rect(fill = "transparent", colour = NA)) +
  theme(panel.grid.minor = element_blank(), 
        panel.grid.major = element_blank(),
        plot.background = element_rect(fill = "transparent", colour = NA)) +
  #ylab("Frequency") +
  #coord_cartesian(xlim=c(1,5), ylim=c(0, 50)) +
  scale_fill_manual(values=cbPalette)

Results

confusion_matrix

(Q4.1) Is a high number of changes an indicative of bugs introduction in Granger positives cases?

#Granger
data_granger <- filter(methods_changes, P1 == 1, P2 == 1, P3 == 1, P4 == 1, P5 == 1, GrangerPos == 1)
#Grouping data
confusion_matrix <- as.data.frame(
  data_granger %>%
    dplyr::group_by(Project) %>%
    dplyr::summarise(
      Precision = median(Precision, na.rm = TRUE),
      Recall = median(Recall, na.rm = TRUE),
      Fmeasure = median(Fmeasure, na.rm = TRUE)
    )
)
confusion_matrix
LS0tCnRpdGxlOiAiUiBOb3RlYm9vayIKb3V0cHV0OiBodG1sX25vdGVib29rCi0tLQoKCmBgYHtyfQojSW1wb3J0aW5nIGZ1bmN0aW9uczoKc291cmNlKCJ+L1Ivc29mdHdhcmUtaGlzdG9yeS9zY3JpcHRzL3V0aWxzLlIiKQoKI1JxcyBSZXN1bHRzCmZpbGVuYW1lcyA9IGxpc3QuZmlsZXMoCiAgcGF0aCA9IHBhc3RlMCgifi9SL2FuYWx5c2lzL3Jlc3VsdHNfcnFzIiksCiAgZnVsbC5uYW1lcyA9IFRSVUUsCiAgcmVjdXJzaXZlID0gVFJVRQopCgpyZXN1bHRzX2ZyYW1lIDwtIGRvLmNhbGwocmJpbmQsIGxhcHBseShmaWxlbmFtZXMsIGZ1bmN0aW9uKGkpIHsKICByZWFkLmNzdihpLCBzdHJpbmdzQXNGYWN0b3JzID0gRkFMU0UpCn0pKQoKCiNJbnNlcnRpb25zCmZpbGVuYW1lcyA9IGxpc3QuZmlsZXMoCiAgcGF0aCA9IHBhc3RlMCgifi9SL2FuYWx5c2lzL3Jlc3VsdHNfaW5zZXJ0aW9ucyIpLAogIGZ1bGwubmFtZXMgPSBUUlVFLAogIHJlY3Vyc2l2ZSA9IFRSVUUKKQoKCm1ldGhvZHNfaW5zZXJ0aW9ucyA8LSBkby5jYWxsKHJiaW5kLCBsYXBwbHkoZmlsZW5hbWVzLCBmdW5jdGlvbihpKSB7CiAgcmVhZC5jc3YoaSwgc3RyaW5nc0FzRmFjdG9ycyA9IEZBTFNFKQp9KSkKCgojVG90YWwgSW5zZXJ0aW9ucwpmaWxlbmFtZXMgPSBsaXN0LmZpbGVzKAogIHBhdGggPSBwYXN0ZTAoIn4vUi9hbmFseXNpcy9yZXN1bHRzIiksCiAgZnVsbC5uYW1lcyA9IFRSVUUsCiAgcmVjdXJzaXZlID0gVFJVRQopCgptZXRob2RzX3RvdGFsIDwtIGRvLmNhbGwocmJpbmQsIGxhcHBseShmaWxlbmFtZXMsIGZ1bmN0aW9uKGkpIHsKICByZWFkLmNzdihpLCBzdHJpbmdzQXNGYWN0b3JzID0gRkFMU0UpCn0pKQoKI0ZpbmFsIERhdGEgRnJhbWUKZGF0YV9wbG90IDwtIGFzLmRhdGEuZnJhbWUoCiAgcmVzdWx0c19mcmFtZSAlPiUKICAgIGRwbHlyOjpncm91cF9ieShQcm9qZWN0LCBOb0NvbW1pdHMpICU+JQogICAgZHBseXI6OnN1bW1hcmlzZSgKICAgICAgbm9UaW1lU2VyaWVzID0gbWF4KG5vVGltZVNlcmllcyksCiAgICAgIG5vQ2hhbmdlcyA9IHN1bShub0NoYW5nZXMpLAogICAgICBub0J1Z3NJbnMgPSBzdW0obm9CdWdzSW5zKSwKICAgICAgQnVnc0J5VHMgPSBzdW0obm9CdWdzSW5zKSAvIG1heChub1RpbWVTZXJpZXMpLAogICAgICBCdWdzQnlDaGFuZ2VzID0gc3VtKG5vQnVnc0lucykgLyBzdW0obm9DaGFuZ2VzKSwKICAgICAgQ2hhbmdlc0J5VHMgPSBzdW0obm9DaGFuZ2VzKSAvIG1heChub1RpbWVTZXJpZXMpCiAgICApICU+JQogICAgZHBseXI6Om11dGF0ZSgKICAgICAgUGVyY0J1Z3NCeVRzID0gKEJ1Z3NCeVRzIC8gc3VtKEJ1Z3NCeVRzKSkgKiAxMDAsCiAgICAgIFBlcmNCdWdzQnlDb21taXQgPSAobm9CdWdzSW5zIC8gc3VtKG5vQnVnc0lucykpICogMTAwLAogICAgICBQZXJjQnVnc0J5Q2hhbmdlcyA9IChCdWdzQnlDaGFuZ2VzIC8gc3VtKEJ1Z3NCeUNoYW5nZXMpKSAqIDEwMCwKICAgICAgUGVyY1RzID0gKG5vVGltZVNlcmllcyAvIHN1bShub1RpbWVTZXJpZXMpKSAqIDEwMCwKICAgICAgUGVyY0NoYW5nZXNCeVRzID0gKENoYW5nZXNCeVRzIC8gc3VtKENoYW5nZXNCeVRzKSkgKiAxMDAsCiAgICAgIFBlcmNDaGFuZ2VzID0gKG5vQ2hhbmdlcyAvIHN1bShub0NoYW5nZXMpKSAqIDEwMAogICAgKSAlPiUKICAgIGRwbHlyOjp1bmdyb3VwKCkKKQoKZGF0YV9wbG90W2RhdGFfcGxvdCRQcm9qZWN0ID09ICJFbGFzdGljc2VhcmNoLWhhZG9vcCIsYygiUHJvamVjdCIpXSA8LSAiRXMuIEhhZG9vcCIKZGF0YV9wbG90W2RhdGFfcGxvdCRQcm9qZWN0ID09ICJTaWduYWwtQW5kcm9pZCIsYygiUHJvamVjdCIpXSA8LSAiUy4gQW5kcm9pZCIKZGF0YV9wbG90W2RhdGFfcGxvdCRQcm9qZWN0ID09ICJNYXRlcmlhbCBEcmF3ZXIiLGMoIlByb2plY3QiKV0gPC0gIk0uIERyYXdlciIKZGF0YV9wbG90W2RhdGFfcGxvdCRQcm9qZWN0ID09ICJNYXRlcmlhbC1EaWFsb2dzIixjKCJQcm9qZWN0IildIDwtICJNLiBEaWFsb2dzIgoKcHJvamVjdHMgPC0gdW5pcXVlKGRhdGFfcGxvdCRQcm9qZWN0KQpgYGAKCgoKIyMjIChHMSlUbyBpbnZlc3RpZ2F0ZSB0aGUgb2NjdXJyZW5jZSBvZiBjb21taXRzIGFsb25nIHRoZSBoaXN0b3J5OyAKIyMjIyhRMS4xKSBIb3cgb2Z0ZW4gYXJlIGNvbW1pdHMgcGVyZm9ybWVkPyAKCmBgYHtyfQoKcDEgPC0gZ2dwbG90KGZpbHRlcihkYXRhX3Bsb3QsIFByb2plY3QgJWluJSBwcm9qZWN0c1sxOjRdLCBOb0NvbW1pdHMgPD0gMTAgKSkgKwogIGdlb21fYmFyKGFlcyh4PU5vQ29tbWl0cyx5PVBlcmNUcyxncm91cD1Qcm9qZWN0KSwgcG9zaXRpb24gPSAiZG9kZ2UiLCBzdGF0ID0gImlkZW50aXR5IikrCiAgZmFjZXRfZ3JpZCguflByb2plY3Qsc2NhbGVzPSJmcmVlIikgKyAKICB0aGVtZShsZWdlbmQucG9zaXRpb249IGMoMC43LCAwLjk1KSwgbGVnZW5kLmRpcmVjdGlvbj0iaG9yaXpvbnRhbCIsIGxlZ2VuZC50aXRsZSA9IGVsZW1lbnRfYmxhbmsoKSwgCiAgICAgICAgbGVnZW5kLnRleHQ9ZWxlbWVudF90ZXh0KHNpemU9NyksIGxlZ2VuZC5iYWNrZ3JvdW5kID0gZWxlbWVudF9yZWN0KGZpbGwgPSAidHJhbnNwYXJlbnQiLCBjb2xvdXIgPSBOQSkgKSArCiAgeWxhYigiUGVyY2VudHVhbCIpICsgc2NhbGVfeF9kaXNjcmV0ZShuYW1lID0iTnVtYmVyIG9mIENvbW1pdHMiLCBsaW1pdHM9c2VxKDEsMTApKSArCiAgI3RoZW1lKGF4aXMudGl0bGUueD1lbGVtZW50X2JsYW5rKCksIGF4aXMudGl0bGUueSA9IGVsZW1lbnRfYmxhbmsoKSkgKwogIHRoZW1lKHBhbmVsLmdyaWQubWlub3IgPSBlbGVtZW50X2JsYW5rKCksIAogICAgICAgIHBhbmVsLmdyaWQubWFqb3IgPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgcGxvdC5iYWNrZ3JvdW5kID0gZWxlbWVudF9yZWN0KGZpbGwgPSAidHJhbnNwYXJlbnQiLCBjb2xvdXIgPSBOQSksCiAgICAgICAgYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoY29sb3VyPSJncmV5MjAiLHNpemU9NSxoanVzdD0uNSx2anVzdD0uNSxmYWNlPSJwbGFpbiIpKQoKCnAyIDwtIGdncGxvdChmaWx0ZXIoZGF0YV9wbG90LCBQcm9qZWN0ICVpbiUgcHJvamVjdHNbNTo3XSwgTm9Db21taXRzIDw9IDEwICkpICsKICBnZW9tX2JhcihhZXMoeD1Ob0NvbW1pdHMseT1QZXJjVHMsZ3JvdXA9UHJvamVjdCksIHBvc2l0aW9uID0gImRvZGdlIiwgc3RhdCA9ICJpZGVudGl0eSIpKwogIGZhY2V0X2dyaWQoLn5Qcm9qZWN0LHNjYWxlcz0iZnJlZSIpICsgCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uPSBjKDAuNywgMC45NSksIGxlZ2VuZC5kaXJlY3Rpb249Imhvcml6b250YWwiLCBsZWdlbmQudGl0bGUgPSBlbGVtZW50X2JsYW5rKCksIAogICAgICAgIGxlZ2VuZC50ZXh0PWVsZW1lbnRfdGV4dChzaXplPTcpLCBsZWdlbmQuYmFja2dyb3VuZCA9IGVsZW1lbnRfcmVjdChmaWxsID0gInRyYW5zcGFyZW50IiwgY29sb3VyID0gTkEpICkgKwogIHlsYWIoIlBlcmNlbnR1YWwiKSArIHNjYWxlX3hfZGlzY3JldGUobmFtZSA9Ik51bWJlciBvZiBDb21taXRzIiwgbGltaXRzPXNlcSgxLDEwKSkgKwogICN0aGVtZShheGlzLnRpdGxlLng9ZWxlbWVudF9ibGFuaygpLCBheGlzLnRpdGxlLnkgPSBlbGVtZW50X2JsYW5rKCkpICsKICB0aGVtZShwYW5lbC5ncmlkLm1pbm9yID0gZWxlbWVudF9ibGFuaygpLCAKICAgICAgICBwYW5lbC5ncmlkLm1ham9yID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgIHBsb3QuYmFja2dyb3VuZCA9IGVsZW1lbnRfcmVjdChmaWxsID0gInRyYW5zcGFyZW50IiwgY29sb3VyID0gTkEpLAogICAgICAgIGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGNvbG91cj0iZ3JleTIwIixzaXplPTUsaGp1c3Q9LjUsdmp1c3Q9LjUsZmFjZT0icGxhaW4iKSkKCgpnZ2FycmFuZ2UocDEgLCBwMiAsIG5jb2wgPSAxLCBucm93ID0gMikKYGBgCgoKIyMjIyhRMS4yKSBIb3cgb2Z0ZW4gYXJlIGNoYW5nZXMgcGVyZm9ybWVkIGFtb25nIGNvbW1pdHM/CgpgYGB7cn0KCiNQZXJjZW50dWFsCnAxIDwtIGdncGxvdChmaWx0ZXIoZGF0YV9wbG90LCBQcm9qZWN0ICVpbiUgcHJvamVjdHNbMTo0XSwgTm9Db21taXRzIDw9IDEwICkpICsKICBnZW9tX2JhcihhZXMoeD1Ob0NvbW1pdHMseT1QZXJjQ2hhbmdlcyxncm91cD1Qcm9qZWN0KSwgcG9zaXRpb24gPSAiZG9kZ2UiLCBzdGF0ID0gImlkZW50aXR5IikrCiAgZmFjZXRfZ3JpZCguflByb2plY3Qsc2NhbGVzPSJmcmVlIikgKyAKICB0aGVtZShsZWdlbmQucG9zaXRpb249IGMoMC43LCAwLjk1KSwgbGVnZW5kLmRpcmVjdGlvbj0iaG9yaXpvbnRhbCIsIGxlZ2VuZC50aXRsZSA9IGVsZW1lbnRfYmxhbmsoKSwgCiAgICAgICAgbGVnZW5kLnRleHQ9ZWxlbWVudF90ZXh0KHNpemU9NyksIGxlZ2VuZC5iYWNrZ3JvdW5kID0gZWxlbWVudF9yZWN0KGZpbGwgPSAidHJhbnNwYXJlbnQiLCBjb2xvdXIgPSBOQSkgKSArCiAgeWxhYigiUGVyY2VudHVhbCIpICsgc2NhbGVfeF9kaXNjcmV0ZShuYW1lID0iTnVtYmVyIG9mIENvbW1pdHMiLCBsaW1pdHM9c2VxKDEsMTApKSArCiAgI3RoZW1lKGF4aXMudGl0bGUueD1lbGVtZW50X2JsYW5rKCksIGF4aXMudGl0bGUueSA9IGVsZW1lbnRfYmxhbmsoKSkgKwogIHRoZW1lKHBhbmVsLmdyaWQubWlub3IgPSBlbGVtZW50X2JsYW5rKCksIAogICAgICAgIHBhbmVsLmdyaWQubWFqb3IgPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgcGxvdC5iYWNrZ3JvdW5kID0gZWxlbWVudF9yZWN0KGZpbGwgPSAidHJhbnNwYXJlbnQiLCBjb2xvdXIgPSBOQSksCiAgICAgICAgYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoY29sb3VyPSJncmV5MjAiLHNpemU9NSxoanVzdD0uNSx2anVzdD0uNSxmYWNlPSJwbGFpbiIpKQoKCnAyIDwtIGdncGxvdChmaWx0ZXIoZGF0YV9wbG90LCBQcm9qZWN0ICVpbiUgcHJvamVjdHNbNTo3XSwgTm9Db21taXRzIDw9IDEwICkpICsKICBnZW9tX2JhcihhZXMoeD1Ob0NvbW1pdHMseT1QZXJjQ2hhbmdlcyxncm91cD1Qcm9qZWN0KSwgcG9zaXRpb24gPSAiZG9kZ2UiLCBzdGF0ID0gImlkZW50aXR5IikrCiAgZmFjZXRfZ3JpZCguflByb2plY3Qsc2NhbGVzPSJmcmVlIikgKyAKICB0aGVtZShsZWdlbmQucG9zaXRpb249IGMoMC43LCAwLjk1KSwgbGVnZW5kLmRpcmVjdGlvbj0iaG9yaXpvbnRhbCIsIGxlZ2VuZC50aXRsZSA9IGVsZW1lbnRfYmxhbmsoKSwgCiAgICAgICAgbGVnZW5kLnRleHQ9ZWxlbWVudF90ZXh0KHNpemU9NyksIGxlZ2VuZC5iYWNrZ3JvdW5kID0gZWxlbWVudF9yZWN0KGZpbGwgPSAidHJhbnNwYXJlbnQiLCBjb2xvdXIgPSBOQSkgKSArCiAgeWxhYigiUGVyY2VudHVhbCIpICsgc2NhbGVfeF9kaXNjcmV0ZShuYW1lID0iTnVtYmVyIG9mIENvbW1pdHMiLCBsaW1pdHM9c2VxKDEsMTApKSArCiAgI3RoZW1lKGF4aXMudGl0bGUueD1lbGVtZW50X2JsYW5rKCksIGF4aXMudGl0bGUueSA9IGVsZW1lbnRfYmxhbmsoKSkgKwogIHRoZW1lKHBhbmVsLmdyaWQubWlub3IgPSBlbGVtZW50X2JsYW5rKCksIAogICAgICAgIHBhbmVsLmdyaWQubWFqb3IgPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgcGxvdC5iYWNrZ3JvdW5kID0gZWxlbWVudF9yZWN0KGZpbGwgPSAidHJhbnNwYXJlbnQiLCBjb2xvdXIgPSBOQSksCiAgICAgICAgYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoY29sb3VyPSJncmV5MjAiLHNpemU9NSxoanVzdD0uNSx2anVzdD0uNSxmYWNlPSJwbGFpbiIpKQoKCmdnYXJyYW5nZShwMSAsIHAyICwgbmNvbCA9IDEsIG5yb3cgPSAyKQpgYGAKCgojIyMjKFExLjMpIEhvdyBvZnRlbiBhcmUgY2hhbmdlcyBwZXJmb3JtZWQgYW1vbmcgdGltZSBzZXJpZXM/CgpgYGB7cn0KCiNQZXJjZW50dWFsOgpwMSA8LSBnZ3Bsb3QoZmlsdGVyKGRhdGFfcGxvdCwgUHJvamVjdCAlaW4lIHByb2plY3RzWzE6NF0sIE5vQ29tbWl0cyA8PSAxMCApKSArCiAgZ2VvbV9iYXIoYWVzKHg9Tm9Db21taXRzLHk9UGVyY0NoYW5nZXNCeVRzLGdyb3VwPVByb2plY3QpLCBwb3NpdGlvbiA9ICJkb2RnZSIsIHN0YXQgPSAiaWRlbnRpdHkiKSArCiAgZmFjZXRfZ3JpZCguflByb2plY3Qsc2NhbGVzPSJmcmVlIikgKyAKICB0aGVtZShsZWdlbmQucG9zaXRpb249IGMoMC43LCAwLjk1KSwgbGVnZW5kLmRpcmVjdGlvbj0iaG9yaXpvbnRhbCIsIGxlZ2VuZC50aXRsZSA9IGVsZW1lbnRfYmxhbmsoKSwgCiAgICAgICAgbGVnZW5kLnRleHQ9ZWxlbWVudF90ZXh0KHNpemU9NyksIGxlZ2VuZC5iYWNrZ3JvdW5kID0gZWxlbWVudF9yZWN0KGZpbGwgPSAidHJhbnNwYXJlbnQiLCBjb2xvdXIgPSBOQSkgKSArCiAgeWxhYigiUGVyY2VudHVhbCIpICsgc2NhbGVfeF9kaXNjcmV0ZShuYW1lID0iTnVtYmVyIG9mIENvbW1pdHMiLCBsaW1pdHM9c2VxKDEsMTApKSArCiAgI3RoZW1lKGF4aXMudGl0bGUueD1lbGVtZW50X2JsYW5rKCksIGF4aXMudGl0bGUueSA9IGVsZW1lbnRfYmxhbmsoKSkgKwogIHRoZW1lKHBhbmVsLmdyaWQubWlub3IgPSBlbGVtZW50X2JsYW5rKCksIAogICAgICAgIHBhbmVsLmdyaWQubWFqb3IgPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgcGxvdC5iYWNrZ3JvdW5kID0gZWxlbWVudF9yZWN0KGZpbGwgPSAidHJhbnNwYXJlbnQiLCBjb2xvdXIgPSBOQSksCiAgICAgICAgYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoY29sb3VyPSJncmV5MjAiLHNpemU9NSxoanVzdD0uNSx2anVzdD0uNSxmYWNlPSJwbGFpbiIpKQoKCnAyIDwtIGdncGxvdChmaWx0ZXIoZGF0YV9wbG90LCBQcm9qZWN0ICVpbiUgcHJvamVjdHNbNTo3XSwgTm9Db21taXRzIDw9IDEwICkpICsKICBnZW9tX2JhcihhZXMoeD1Ob0NvbW1pdHMseT1QZXJjQ2hhbmdlc0J5VHMsZ3JvdXA9UHJvamVjdCksIHBvc2l0aW9uID0gImRvZGdlIiwgc3RhdCA9ICJpZGVudGl0eSIpKwogIGZhY2V0X2dyaWQoLn5Qcm9qZWN0LHNjYWxlcz0iZnJlZSIpICsgCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uPSBjKDAuNywgMC45NSksIGxlZ2VuZC5kaXJlY3Rpb249Imhvcml6b250YWwiLCBsZWdlbmQudGl0bGUgPSBlbGVtZW50X2JsYW5rKCksIAogICAgICAgIGxlZ2VuZC50ZXh0PWVsZW1lbnRfdGV4dChzaXplPTcpLCBsZWdlbmQuYmFja2dyb3VuZCA9IGVsZW1lbnRfcmVjdChmaWxsID0gInRyYW5zcGFyZW50IiwgY29sb3VyID0gTkEpICkgKwogIHlsYWIoIlBlcmNlbnR1YWwiKSArIHNjYWxlX3hfZGlzY3JldGUobmFtZSA9Ik51bWJlciBvZiBDb21taXRzIiwgbGltaXRzPXNlcSgxLDEwKSkgKwogICN0aGVtZShheGlzLnRpdGxlLng9ZWxlbWVudF9ibGFuaygpLCBheGlzLnRpdGxlLnkgPSBlbGVtZW50X2JsYW5rKCkpICsKICB0aGVtZShwYW5lbC5ncmlkLm1pbm9yID0gZWxlbWVudF9ibGFuaygpLCAKICAgICAgICBwYW5lbC5ncmlkLm1ham9yID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgIHBsb3QuYmFja2dyb3VuZCA9IGVsZW1lbnRfcmVjdChmaWxsID0gInRyYW5zcGFyZW50IiwgY29sb3VyID0gTkEpLAogICAgICAgIGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGNvbG91cj0iZ3JleTIwIixzaXplPTUsaGp1c3Q9LjUsdmp1c3Q9LjUsZmFjZT0icGxhaW4iKSkKCmdnYXJyYW5nZShwMSAsIHAyICwgbmNvbCA9IDEsIG5yb3cgPSAyKQpgYGAKCgojIyMgKEcyKVRvIGFzc2VzcyB0aGUgaW50cm9kdWN0aW9uIG9mIGJ1Z3MgYWxvbmcgdGhlIGhpc3Rvcnk7IAoKIyMjIyAoUTIuMSkgSG93IG9mdGVuIGFyZSBidWdzIGludHJvZHVjZWQgYW1vbmcgdGhlIGNvbW1pdHM/CgpgYGB7cn0KI1BlcmMKcDEgPC0gZ2dwbG90KGZpbHRlcihkYXRhX3Bsb3QsIFByb2plY3QgJWluJSBwcm9qZWN0c1sxOjRdLCBOb0NvbW1pdHMgPD0gMTAgKSkgKwogIGdlb21fYmFyKGFlcyh4PU5vQ29tbWl0cyx5PVBlcmNCdWdzQnlDb21taXQsZ3JvdXA9UHJvamVjdCksIHBvc2l0aW9uID0gImRvZGdlIiwgc3RhdCA9ICJpZGVudGl0eSIpKwogIGZhY2V0X2dyaWQoLn5Qcm9qZWN0LHNjYWxlcz0iZnJlZSIpICsgCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uPSBjKDAuNywgMC45NSksIGxlZ2VuZC5kaXJlY3Rpb249Imhvcml6b250YWwiLCBsZWdlbmQudGl0bGUgPSBlbGVtZW50X2JsYW5rKCksIAogICAgICAgIGxlZ2VuZC50ZXh0PWVsZW1lbnRfdGV4dChzaXplPTcpLCBsZWdlbmQuYmFja2dyb3VuZCA9IGVsZW1lbnRfcmVjdChmaWxsID0gInRyYW5zcGFyZW50IiwgY29sb3VyID0gTkEpICkgKwogIHlsYWIoIlBlcmNlbnR1YWwiKSArIHNjYWxlX3hfZGlzY3JldGUobmFtZSA9Ik51bWJlciBvZiBDb21taXRzIiwgbGltaXRzPXNlcSgxLDEwKSkgKwogICN0aGVtZShheGlzLnRpdGxlLng9ZWxlbWVudF9ibGFuaygpLCBheGlzLnRpdGxlLnkgPSBlbGVtZW50X2JsYW5rKCkpICsKICB0aGVtZShwYW5lbC5ncmlkLm1pbm9yID0gZWxlbWVudF9ibGFuaygpLCAKICAgICAgICBwYW5lbC5ncmlkLm1ham9yID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgIHBsb3QuYmFja2dyb3VuZCA9IGVsZW1lbnRfcmVjdChmaWxsID0gInRyYW5zcGFyZW50IiwgY29sb3VyID0gTkEpLAogICAgICAgIGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGNvbG91cj0iZ3JleTIwIixzaXplPTUsaGp1c3Q9LjUsdmp1c3Q9LjUsZmFjZT0icGxhaW4iKSkKCgpwMiA8LSBnZ3Bsb3QoZmlsdGVyKGRhdGFfcGxvdCwgUHJvamVjdCAlaW4lIHByb2plY3RzWzU6N10sIE5vQ29tbWl0cyA8PSAxMCApKSArCiAgZ2VvbV9iYXIoYWVzKHg9Tm9Db21taXRzLHk9UGVyY0J1Z3NCeUNvbW1pdCxncm91cD1Qcm9qZWN0KSwgcG9zaXRpb24gPSAiZG9kZ2UiLCBzdGF0ID0gImlkZW50aXR5IikrCiAgZmFjZXRfZ3JpZCguflByb2plY3Qsc2NhbGVzPSJmcmVlIikgKyAKICB0aGVtZShsZWdlbmQucG9zaXRpb249IGMoMC43LCAwLjk1KSwgbGVnZW5kLmRpcmVjdGlvbj0iaG9yaXpvbnRhbCIsIGxlZ2VuZC50aXRsZSA9IGVsZW1lbnRfYmxhbmsoKSwgCiAgICAgICAgbGVnZW5kLnRleHQ9ZWxlbWVudF90ZXh0KHNpemU9NyksIGxlZ2VuZC5iYWNrZ3JvdW5kID0gZWxlbWVudF9yZWN0KGZpbGwgPSAidHJhbnNwYXJlbnQiLCBjb2xvdXIgPSBOQSkgKSArCiAgeWxhYigiUGVyY2VudHVhbCIpICsgc2NhbGVfeF9kaXNjcmV0ZShuYW1lID0iTnVtYmVyIG9mIENvbW1pdHMiLCBsaW1pdHM9c2VxKDEsMTApKSArCiAgI3RoZW1lKGF4aXMudGl0bGUueD1lbGVtZW50X2JsYW5rKCksIGF4aXMudGl0bGUueSA9IGVsZW1lbnRfYmxhbmsoKSkgKwogIHRoZW1lKHBhbmVsLmdyaWQubWlub3IgPSBlbGVtZW50X2JsYW5rKCksIAogICAgICAgIHBhbmVsLmdyaWQubWFqb3IgPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgcGxvdC5iYWNrZ3JvdW5kID0gZWxlbWVudF9yZWN0KGZpbGwgPSAidHJhbnNwYXJlbnQiLCBjb2xvdXIgPSBOQSksCiAgICAgICAgYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoY29sb3VyPSJncmV5MjAiLHNpemU9NSxoanVzdD0uNSx2anVzdD0uNSxmYWNlPSJwbGFpbiIpKQoKZ2dhcnJhbmdlKHAxICwgcDIgLCBuY29sID0gMSwgbnJvdyA9IDIpCmBgYAoKCgojIyMjIChRMi4yKSBIb3cgb2Z0ZW4gYXJlIGJ1Z3MgaW50cm9kdWNlZCBhbW9uZyB0aGUgdGltZSBzZXJpZXM/CgpgYGB7cn0KCiNQZXJjZW50dWFsOgpwMSA8LSBnZ3Bsb3QoZmlsdGVyKGRhdGFfcGxvdCwgUHJvamVjdCAlaW4lIHByb2plY3RzWzE6NF0sIE5vQ29tbWl0cyA8PSAxMCApKSArCiAgZ2VvbV9iYXIoYWVzKHg9Tm9Db21taXRzLHk9UGVyY0J1Z3NCeVRzLGdyb3VwPVByb2plY3QpLCBwb3NpdGlvbiA9ICJkb2RnZSIsIHN0YXQgPSAiaWRlbnRpdHkiKSsKICBmYWNldF9ncmlkKC5+UHJvamVjdCxzY2FsZXM9ImZyZWUiKSArIAogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbj0gYygwLjcsIDAuOTUpLCBsZWdlbmQuZGlyZWN0aW9uPSJob3Jpem9udGFsIiwgbGVnZW5kLnRpdGxlID0gZWxlbWVudF9ibGFuaygpLCAKICAgICAgICBsZWdlbmQudGV4dD1lbGVtZW50X3RleHQoc2l6ZT03KSwgbGVnZW5kLmJhY2tncm91bmQgPSBlbGVtZW50X3JlY3QoZmlsbCA9ICJ0cmFuc3BhcmVudCIsIGNvbG91ciA9IE5BKSApICsKICB5bGFiKCJQZXJjZW50dWFsIikgKyBzY2FsZV94X2Rpc2NyZXRlKG5hbWUgPSJOdW1iZXIgb2YgQ29tbWl0cyIsIGxpbWl0cz1zZXEoMSwxMCkpICsKICAjdGhlbWUoYXhpcy50aXRsZS54PWVsZW1lbnRfYmxhbmsoKSwgYXhpcy50aXRsZS55ID0gZWxlbWVudF9ibGFuaygpKSArCiAgdGhlbWUocGFuZWwuZ3JpZC5taW5vciA9IGVsZW1lbnRfYmxhbmsoKSwgCiAgICAgICAgcGFuZWwuZ3JpZC5tYWpvciA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBwbG90LmJhY2tncm91bmQgPSBlbGVtZW50X3JlY3QoZmlsbCA9ICJ0cmFuc3BhcmVudCIsIGNvbG91ciA9IE5BKSwKICAgICAgICBheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChjb2xvdXI9ImdyZXkyMCIsc2l6ZT01LGhqdXN0PS41LHZqdXN0PS41LGZhY2U9InBsYWluIikpCgoKcDIgPC0gZ2dwbG90KGZpbHRlcihkYXRhX3Bsb3QsIFByb2plY3QgJWluJSBwcm9qZWN0c1s1OjddLCBOb0NvbW1pdHMgPD0gMTAgKSkgKwogIGdlb21fYmFyKGFlcyh4PU5vQ29tbWl0cyx5PVBlcmNCdWdzQnlUcyxncm91cD1Qcm9qZWN0KSwgcG9zaXRpb24gPSAiZG9kZ2UiLCBzdGF0ID0gImlkZW50aXR5IikrCiAgZmFjZXRfZ3JpZCguflByb2plY3Qsc2NhbGVzPSJmcmVlIikgKyAKICB0aGVtZShsZWdlbmQucG9zaXRpb249IGMoMC43LCAwLjk1KSwgbGVnZW5kLmRpcmVjdGlvbj0iaG9yaXpvbnRhbCIsIGxlZ2VuZC50aXRsZSA9IGVsZW1lbnRfYmxhbmsoKSwgCiAgICAgICAgbGVnZW5kLnRleHQ9ZWxlbWVudF90ZXh0KHNpemU9NyksIGxlZ2VuZC5iYWNrZ3JvdW5kID0gZWxlbWVudF9yZWN0KGZpbGwgPSAidHJhbnNwYXJlbnQiLCBjb2xvdXIgPSBOQSkgKSArCiAgeWxhYigiUGVyY2VudHVhbCIpICsgc2NhbGVfeF9kaXNjcmV0ZShuYW1lID0iTnVtYmVyIG9mIENvbW1pdHMiLCBsaW1pdHM9c2VxKDEsMTApKSArCiAgI3RoZW1lKGF4aXMudGl0bGUueD1lbGVtZW50X2JsYW5rKCksIGF4aXMudGl0bGUueSA9IGVsZW1lbnRfYmxhbmsoKSkgKwogIHRoZW1lKHBhbmVsLmdyaWQubWlub3IgPSBlbGVtZW50X2JsYW5rKCksIAogICAgICAgIHBhbmVsLmdyaWQubWFqb3IgPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgcGxvdC5iYWNrZ3JvdW5kID0gZWxlbWVudF9yZWN0KGZpbGwgPSAidHJhbnNwYXJlbnQiLCBjb2xvdXIgPSBOQSksCiAgICAgICAgYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoY29sb3VyPSJncmV5MjAiLHNpemU9NSxoanVzdD0uNSx2anVzdD0uNSxmYWNlPSJwbGFpbiIpKQoKZ2dhcnJhbmdlKHAxICwgcDIgLCBuY29sID0gMSwgbnJvdyA9IDIpCmBgYAoKCiMjIyMgKFEyLjMpIEhvdyBvZnRlbiBhcmUgYnVncyBpbnRyb2R1Y2VkIGFtb25nIHRoZSBjaGFuZ2VzPwoKYGBge3J9CiNQZXJjOgpwMSA8LSBnZ3Bsb3QoZmlsdGVyKGRhdGFfcGxvdCwgUHJvamVjdCAlaW4lIHByb2plY3RzWzE6NF0sIE5vQ29tbWl0cyA8PSAxMCApKSArCiAgZ2VvbV9iYXIoYWVzKHg9Tm9Db21taXRzLHk9UGVyY0J1Z3NCeUNoYW5nZXMsZ3JvdXA9UHJvamVjdCksIHBvc2l0aW9uID0gImRvZGdlIiwgc3RhdCA9ICJpZGVudGl0eSIpKwogIGZhY2V0X2dyaWQoLn5Qcm9qZWN0LHNjYWxlcz0iZnJlZSIpICsgCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uPSBjKDAuNywgMC45NSksIGxlZ2VuZC5kaXJlY3Rpb249Imhvcml6b250YWwiLCBsZWdlbmQudGl0bGUgPSBlbGVtZW50X2JsYW5rKCksIAogICAgICAgIGxlZ2VuZC50ZXh0PWVsZW1lbnRfdGV4dChzaXplPTcpLCBsZWdlbmQuYmFja2dyb3VuZCA9IGVsZW1lbnRfcmVjdChmaWxsID0gInRyYW5zcGFyZW50IiwgY29sb3VyID0gTkEpICkgKwogIHlsYWIoIlBlcmNlbnR1YWwiKSArIHNjYWxlX3hfZGlzY3JldGUobmFtZSA9Ik51bWJlciBvZiBDb21taXRzIiwgbGltaXRzPXNlcSgxLDEwKSkgKwogICN0aGVtZShheGlzLnRpdGxlLng9ZWxlbWVudF9ibGFuaygpLCBheGlzLnRpdGxlLnkgPSBlbGVtZW50X2JsYW5rKCkpICsKICB0aGVtZShwYW5lbC5ncmlkLm1pbm9yID0gZWxlbWVudF9ibGFuaygpLCAKICAgICAgICBwYW5lbC5ncmlkLm1ham9yID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgIHBsb3QuYmFja2dyb3VuZCA9IGVsZW1lbnRfcmVjdChmaWxsID0gInRyYW5zcGFyZW50IiwgY29sb3VyID0gTkEpLAogICAgICAgIGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGNvbG91cj0iZ3JleTIwIixzaXplPTUsaGp1c3Q9LjUsdmp1c3Q9LjUsZmFjZT0icGxhaW4iKSkKCnAyIDwtIGdncGxvdChmaWx0ZXIoZGF0YV9wbG90LCBQcm9qZWN0ICVpbiUgcHJvamVjdHNbNTo3XSwgTm9Db21taXRzIDw9IDEwICkpICsKICBnZW9tX2JhcihhZXMoeD1Ob0NvbW1pdHMseT1QZXJjQnVnc0J5Q2hhbmdlcyxncm91cD1Qcm9qZWN0KSwgcG9zaXRpb24gPSAiZG9kZ2UiLCBzdGF0ID0gImlkZW50aXR5IikrCiAgZmFjZXRfZ3JpZCguflByb2plY3Qsc2NhbGVzPSJmcmVlIikgKyAKICB0aGVtZShsZWdlbmQucG9zaXRpb249IGMoMC43LCAwLjk1KSwgbGVnZW5kLmRpcmVjdGlvbj0iaG9yaXpvbnRhbCIsIGxlZ2VuZC50aXRsZSA9IGVsZW1lbnRfYmxhbmsoKSwgCiAgICAgICAgbGVnZW5kLnRleHQ9ZWxlbWVudF90ZXh0KHNpemU9NyksIGxlZ2VuZC5iYWNrZ3JvdW5kID0gZWxlbWVudF9yZWN0KGZpbGwgPSAidHJhbnNwYXJlbnQiLCBjb2xvdXIgPSBOQSkgKSArCiAgeWxhYigiUGVyY2VudHVhbCIpICsgc2NhbGVfeF9kaXNjcmV0ZShuYW1lID0iTnVtYmVyIG9mIENvbW1pdHMiLCBsaW1pdHM9c2VxKDEsMTApKSArCiAgI3RoZW1lKGF4aXMudGl0bGUueD1lbGVtZW50X2JsYW5rKCksIGF4aXMudGl0bGUueSA9IGVsZW1lbnRfYmxhbmsoKSkgKwogIHRoZW1lKHBhbmVsLmdyaWQubWlub3IgPSBlbGVtZW50X2JsYW5rKCksIAogICAgICAgIHBhbmVsLmdyaWQubWFqb3IgPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgcGxvdC5iYWNrZ3JvdW5kID0gZWxlbWVudF9yZWN0KGZpbGwgPSAidHJhbnNwYXJlbnQiLCBjb2xvdXIgPSBOQSksCiAgICAgICAgYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoY29sb3VyPSJncmV5MjAiLHNpemU9NSxoanVzdD0uNSx2anVzdD0uNSxmYWNlPSJwbGFpbiIpKQoKZ2dhcnJhbmdlKHAxICwgcDIgLCBuY29sID0gMSwgbnJvdyA9IDIpCmBgYAoKCiMjIyhHMykgVG8gYW5hbHlzZSB0aGUga2luZCBvZiBjaGFuZ2VzIGFyZSBtb3N0bHkgcmVsYXRlZCB0byB0aGUgYnVncyBpbnNlcnRpb247CgojIyMjKFEzLjEpIFdoaWNoIGFyZSB0aGUgdHlwZXMgKEFkZC9EZWwpIG9mIGNoYW5nZXMgbW9yZSBmcmVxdWVudCBpbiB0aGUgYnVncyBpbnNlcnRpb24/IAoKYGBge3J9CiNDaGFuZ2VzIENoYXJ0Cm1ldGhvZHNfY2hhbmdlcyA8LSBmaWx0ZXIobWV0aG9kc19pbnNlcnRpb25zLCBjaGFuZ2VUeXBlICE9ICdBbGwnLCBncm91cE1ldHJpYyA9PSAnQWxsJywgTWV0cmljID09ICdBbGwnKQoKbWV0aG9kc19jaGFuZ2VzW21ldGhvZHNfY2hhbmdlcyRjaGFuZ2VUeXBlID09ICJjaGFuZ2VNZXRyaWNzQWRkaXRpb24iLCBjKCJjaGFuZ2VUeXBlIildIDwtICJBZGRpdGlvbiIKbWV0aG9kc19jaGFuZ2VzW21ldGhvZHNfY2hhbmdlcyRjaGFuZ2VUeXBlID09ICJjaGFuZ2VNZXRyaWNzRGVsZXRpb24iLCBjKCJjaGFuZ2VUeXBlIildIDwtICJEZWxldGlvbiIKCm1ldGhvZHNfY2hhbmdlc1ttZXRob2RzX2NoYW5nZXMkUHJvamVjdCA9PSAiRWxhc3RpY3NlYXJjaC1oYWRvb3AiLGMoIlByb2plY3QiKV0gPC0gIkVzLiBIYWRvb3AiCm1ldGhvZHNfY2hhbmdlc1ttZXRob2RzX2NoYW5nZXMkUHJvamVjdCA9PSAiU2lnbmFsLUFuZHJvaWQiLGMoIlByb2plY3QiKV0gPC0gIlMuIEFuZHJvaWQiCm1ldGhvZHNfY2hhbmdlc1ttZXRob2RzX2NoYW5nZXMkUHJvamVjdCA9PSAiTWF0ZXJpYWwgRHJhd2VyIixjKCJQcm9qZWN0IildIDwtICJNLiBEcmF3ZXIiCm1ldGhvZHNfY2hhbmdlc1ttZXRob2RzX2NoYW5nZXMkUHJvamVjdCA9PSAiTWF0ZXJpYWwtRGlhbG9ncyIsYygiUHJvamVjdCIpXSA8LSAiTS4gRGlhbG9ncyIKCmNiUGFsZXR0ZSA8LSBjKCIjMDA5RTczIiwgIiNGMTU4NTQiKQoKbWV0aG9kc19jaGFuZ2VzIDwtICBhcy5kYXRhLmZyYW1lKAogIG1ldGhvZHNfY2hhbmdlcyAlPiUKICAgIGRwbHlyOjpncm91cF9ieShQcm9qZWN0LCBjaGFuZ2VUeXBlKSAlPiUKICAgIGRwbHlyOjpzdW1tYXJpc2UodG90YWxDaGFuZ2VzID0gc3VtKENvdW50KSkgJT4lCiAgICBtdXRhdGUoUGVyY2VudHVhbCA9IHRvdGFsQ2hhbmdlcyAvIHN1bSh0b3RhbENoYW5nZXMpICogMTAwKSAlPiUKICAgIHVuZ3JvdXAoKQopCgpnZ3Bsb3QobWV0aG9kc19jaGFuZ2VzKSArCiAgZ2VvbV9iYXIoYWVzKHggPSBQcm9qZWN0LCB5ID0gUGVyY2VudHVhbCwgZmlsbCA9IGNoYW5nZVR5cGUsIGdyb3VwID0gY2hhbmdlVHlwZSksIHBvc2l0aW9uID0gImRvZGdlIiwgc3RhdCA9ICJpZGVudGl0eSIpICsKICBnZW9tX3RleHQoIGFlcyh4ID0gUHJvamVjdCwgeSA9IFBlcmNlbnR1YWwsIGxhYmVsID0gcm91bmQoUGVyY2VudHVhbCksIGdyb3VwID0gY2hhbmdlVHlwZSksICAKICAgICAgICAgICAgIGNoZWNrX292ZXJsYXAgPSBUUlVFLCBwb3NpdGlvbiA9IHBvc2l0aW9uX2RvZGdlKHdpZHRoID0gMSksIHZqdXN0ID0gLTAuNSwgc2l6ZSA9IDMpICsgI3NjYWxlX2ZpbGxfZ3JleSgpICsgCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA0NSwgaGp1c3QgPSAxKSkgKwogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbj0gYygwLjgyLCAwLjk1KSwgbGVnZW5kLmRpcmVjdGlvbj0iaG9yaXpvbnRhbCIsIGxlZ2VuZC50aXRsZSA9IGVsZW1lbnRfYmxhbmsoKSwgCiAgICAgICAgYXhpcy50aXRsZS54PWVsZW1lbnRfYmxhbmsoKSwgbGVnZW5kLnRleHQ9ZWxlbWVudF90ZXh0KHNpemU9NyksIGxlZ2VuZC5iYWNrZ3JvdW5kID0gZWxlbWVudF9yZWN0KGZpbGwgPSAidHJhbnNwYXJlbnQiLCBjb2xvdXIgPSBOQSkgKSArCiAgdGhlbWUocGFuZWwuZ3JpZC5taW5vciA9IGVsZW1lbnRfYmxhbmsoKSwgCiAgICAgICAgcGFuZWwuZ3JpZC5tYWpvciA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBwbG90LmJhY2tncm91bmQgPSBlbGVtZW50X3JlY3QoZmlsbCA9ICJ0cmFuc3BhcmVudCIsIGNvbG91ciA9IE5BKSkgKwogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcz1jYlBhbGV0dGUpCmBgYAoKCiMjIyMoUTMuMikgV2hpY2ggYXJlIHRoZSBtZXRyaWNzIGdyb3VwcyBtb3JlIGZyZXF1ZW50IGluIHRoZSBidWdzIGluc2VydGlvbj8gCgpgYGB7cn0KCm1ldGhvZHNfZ3JvdXBzPC0gZmlsdGVyKG1ldGhvZHNfaW5zZXJ0aW9ucywgZ3JvdXBNZXRyaWMgIT0gIlJNIiwgY2hhbmdlVHlwZSA9PSAnQWxsJywgZ3JvdXBNZXRyaWMgIT0gJ0FsbCcsIE1ldHJpYyA9PSAnQWxsJykKCiNyZW9yZGVyKG1ldGhvZHNfZ3JvdXBzJENoYW5nZXMsIG1ldGhvZHNfZ3JvdXBzJGdyb3VwTWV0cmljLCBmdW5jdGlvbih4KS1sZW5ndGgoeCkpCgptZXRob2RzX2dyb3Vwc1ttZXRob2RzX2dyb3VwcyRQcm9qZWN0ID09ICJFbGFzdGljc2VhcmNoLWhhZG9vcCIsYygiUHJvamVjdCIpXSA8LSAiRXMuIEhhZG9vcCIKbWV0aG9kc19ncm91cHNbbWV0aG9kc19ncm91cHMkUHJvamVjdCA9PSAiU2lnbmFsLUFuZHJvaWQiLGMoIlByb2plY3QiKV0gPC0gIlMuIEFuZHJvaWQiCm1ldGhvZHNfZ3JvdXBzW21ldGhvZHNfZ3JvdXBzJFByb2plY3QgPT0gIk1hdGVyaWFsIERyYXdlciIsYygiUHJvamVjdCIpXSA8LSAiTS4gRHJhd2VyIgptZXRob2RzX2dyb3Vwc1ttZXRob2RzX2dyb3VwcyRQcm9qZWN0ID09ICJNYXRlcmlhbC1EaWFsb2dzIixjKCJQcm9qZWN0IildIDwtICJNLiBEaWFsb2dzIgoKY2JQYWxldHRlIDwtIGMoIiM0RDRENEQiLCAiIzVEQTVEQSIsICIjRkFBNDNBIiwgIiNCMjc2QjIiLCAiI0YxNTg1NCIsICIjMDA5RTczIiwgIiNGMEU0NDIiLCAiIzAwNzJCMiIsICIjOTk5OTk5IiwgIiM5OTMzMDAiKQoKCm1ldGhvZHNfZ3JvdXBzIDwtICBhcy5kYXRhLmZyYW1lKAogIG1ldGhvZHNfZ3JvdXBzICU+JQogICAgZHBseXI6Omdyb3VwX2J5KFByb2plY3QsIGdyb3VwTWV0cmljKSAlPiUKICAgIGRwbHlyOjpzdW1tYXJpc2UodG90YWxUcyA9IHN1bShDb3VudCkpICU+JQogICAgbXV0YXRlKFBlcmNlbnR1YWwgPSB0b3RhbFRzIC8gc3VtKHRvdGFsVHMpICogMTAwKSAlPiUKICAgIHVuZ3JvdXAoKQopCgptZXRob2RzX2dyb3VwcyRyYW5rIDwtIGF2ZShtZXRob2RzX2dyb3VwcyR0b3RhbFRzLCBtZXRob2RzX2dyb3VwcyRQcm9qZWN0LCBGVU4gPSBmdW5jdGlvbih4KSByYW5rKC14KSkKCmJhcnBsb3QxIDwtIGdncGxvdChmaWx0ZXIobWV0aG9kc19ncm91cHMsIFByb2plY3QgJWluJSBwcm9qZWN0c1sxOjVdLCByYW5rIDw9NSkpICsKICBnZW9tX2JhcihhZXMoeCA9IFByb2plY3QsIHkgPSB0b3RhbFRzLCBmaWxsID0gZ3JvdXBNZXRyaWMsIGdyb3VwID0gZ3JvdXBNZXRyaWMpLCBwb3NpdGlvbiA9ICJkb2RnZSIsIHN0YXQgPSAiaWRlbnRpdHkiKSArCiAgZ2VvbV90ZXh0KCBhZXMoeCA9IFByb2plY3QsIHkgPSB0b3RhbFRzLCBsYWJlbCA9IHJvdW5kKHRvdGFsVHMpLCBncm91cCA9IGdyb3VwTWV0cmljKSwgIAogICAgICAgICAgICAgY2hlY2tfb3ZlcmxhcCA9IFRSVUUsIHBvc2l0aW9uID0gcG9zaXRpb25fZG9kZ2Uod2lkdGggPSAxKSwgdmp1c3QgPSAtMC41LCBzaXplID0gMykgKyAjc2NhbGVfZmlsbF9ncmV5KCkgKyAKICAjdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA0NSwgaGp1c3QgPSAxKSkgKwogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbj0gYygwLjQwLCAwLjk1KSwgbGVnZW5kLmRpcmVjdGlvbj0iaG9yaXpvbnRhbCIsIGxlZ2VuZC50aXRsZSA9IGVsZW1lbnRfYmxhbmsoKSwgCiAgICAgICAgYXhpcy50aXRsZS54PWVsZW1lbnRfYmxhbmsoKSwgbGVnZW5kLnRleHQ9ZWxlbWVudF90ZXh0KHNpemU9NiksIGxlZ2VuZC5iYWNrZ3JvdW5kID0gZWxlbWVudF9yZWN0KGZpbGwgPSAidHJhbnNwYXJlbnQiLCBjb2xvdXIgPSBOQSkpICsKICB0aGVtZShwYW5lbC5ncmlkLm1pbm9yID0gZWxlbWVudF9ibGFuaygpLCAKICAgICAgICBwYW5lbC5ncmlkLm1ham9yID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgIHBsb3QuYmFja2dyb3VuZCA9IGVsZW1lbnRfcmVjdChmaWxsID0gInRyYW5zcGFyZW50IiwgY29sb3VyID0gTkEpKSArCiAgeWxhYigiRnJlcXVlbmN5IikgKwogICNjb29yZF9jYXJ0ZXNpYW4oeGxpbT1jKDEsNSksIHlsaW09YygwLCA1MCkpICsKICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXM9Y2JQYWxldHRlKQoKYmFycGxvdDIgPC0gZ2dwbG90KGZpbHRlcihtZXRob2RzX2dyb3VwcywgUHJvamVjdCAlaW4lIHByb2plY3RzWzY6MTBdLCByYW5rIDw9NSkpICsKICBnZW9tX2JhcihhZXMoeCA9IFByb2plY3QsIHkgPSB0b3RhbFRzLCBmaWxsID0gZ3JvdXBNZXRyaWMsIGdyb3VwID0gZ3JvdXBNZXRyaWMpLCBwb3NpdGlvbiA9ICJkb2RnZSIsIHN0YXQgPSAiaWRlbnRpdHkiKSArCiAgZ2VvbV90ZXh0KCBhZXMoeCA9IFByb2plY3QsIHkgPSB0b3RhbFRzLCBsYWJlbCA9IHJvdW5kKHRvdGFsVHMpLCBncm91cCA9IGdyb3VwTWV0cmljKSwgIAogICAgICAgICAgICAgY2hlY2tfb3ZlcmxhcCA9IFRSVUUsIHBvc2l0aW9uID0gcG9zaXRpb25fZG9kZ2Uod2lkdGggPSAxKSwgdmp1c3QgPSAtMC41LCBzaXplID0gMykgKyAjc2NhbGVfZmlsbF9ncmV5KCkgKyAKICAjdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA0NSwgaGp1c3QgPSAxKSkgKwogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbj0gYygwLjQwLCAwLjk1KSwgbGVnZW5kLmRpcmVjdGlvbj0iaG9yaXpvbnRhbCIsIGxlZ2VuZC50aXRsZSA9IGVsZW1lbnRfYmxhbmsoKSwgCiAgICAgICAgYXhpcy50aXRsZS54PWVsZW1lbnRfYmxhbmsoKSwgbGVnZW5kLnRleHQ9ZWxlbWVudF90ZXh0KHNpemU9NiksIGxlZ2VuZC5iYWNrZ3JvdW5kID0gZWxlbWVudF9yZWN0KGZpbGwgPSAidHJhbnNwYXJlbnQiLCBjb2xvdXIgPSBOQSkpICsKICB0aGVtZShwYW5lbC5ncmlkLm1pbm9yID0gZWxlbWVudF9ibGFuaygpLCAKICAgICAgICBwYW5lbC5ncmlkLm1ham9yID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgIHBsb3QuYmFja2dyb3VuZCA9IGVsZW1lbnRfcmVjdChmaWxsID0gInRyYW5zcGFyZW50IiwgY29sb3VyID0gTkEpKSArCiAgeWxhYigiRnJlcXVlbmN5IikgKwogICNjb29yZF9jYXJ0ZXNpYW4oeGxpbT1jKDEsNSksIHlsaW09YygwLCA1MCkpICsKICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXM9Y2JQYWxldHRlKQoKZ2dhcnJhbmdlKGJhcnBsb3QxLCBiYXJwbG90MiwgbmNvbCA9IDEsIG5yb3cgPSAyLCBjb21tb24ubGVnZW5kID0gVFJVRSkKCmBgYAoKCiMjIyMoUTMuMykgV2hpY2ggYXJlIHRoZSBjaGFuZ2UgbWV0cmljcyBtb3JlIGZyZXF1ZW50IGluIHRoZSBidWdzIGluc2VydGlvbj8gCgpgYGB7cn0KCiNGaWx0ZXI6RAptZXRob2RzX2luZCA8LSBmaWx0ZXIobWV0aG9kc19pbnNlcnRpb25zLCBncm91cE1ldHJpYyAhPSAiUk0iLCBjaGFuZ2VUeXBlID09ICdBbGwnLCBncm91cE1ldHJpYyAhPSAnQWxsJywgTWV0cmljICE9ICdBbGwnKQoKI3Jlb3JkZXIobWV0aG9kc19ncm91cHMkQ2hhbmdlcywgbWV0aG9kc19ncm91cHMkZ3JvdXBNZXRyaWMsIGZ1bmN0aW9uKHgpLWxlbmd0aCh4KSkKCm1ldGhvZHNfaW5kW21ldGhvZHNfaW5kJFByb2plY3QgPT0gIkVsYXN0aWNzZWFyY2gtaGFkb29wIixjKCJQcm9qZWN0IildIDwtICJFcy4gSGFkb29wIgptZXRob2RzX2luZFttZXRob2RzX2luZCRQcm9qZWN0ID09ICJTaWduYWwtQW5kcm9pZCIsYygiUHJvamVjdCIpXSA8LSAiUy4gQW5kcm9pZCIKbWV0aG9kc19pbmRbbWV0aG9kc19pbmQkUHJvamVjdCA9PSAiTWF0ZXJpYWwgRHJhd2VyIixjKCJQcm9qZWN0IildIDwtICJNLiBEcmF3ZXIiCm1ldGhvZHNfaW5kW21ldGhvZHNfaW5kJFByb2plY3QgPT0gIk1hdGVyaWFsLURpYWxvZ3MiLGMoIlByb2plY3QiKV0gPC0gIk0uIERpYWxvZ3MiCgpjYlBhbGV0dGUgPC0gYygiIzRENEQ0RCIsICIjNURBNURBIiwgIiNGQUE0M0EiLCAiI0IyNzZCMiIsICIjRjE1ODU0IiwgIiMwMDlFNzMiLCAiI0YwRTQ0MiIsICIjMDA3MkIyIiwgIiM5OTk5OTkiLCAiIzk5MzMwMCIpCgoKbWV0aG9kc19pbmQgPC0gIGFzLmRhdGEuZnJhbWUoCiAgbWV0aG9kc19pbmQgJT4lCiAgICBkcGx5cjo6Z3JvdXBfYnkoUHJvamVjdCwgTWV0cmljKSAlPiUKICAgIGRwbHlyOjpzdW1tYXJpc2UodG90YWxUcyA9IHN1bShDb3VudCkpICU+JQogICAgbXV0YXRlKFBlcmNlbnR1YWwgPSB0b3RhbFRzIC8gc3VtKHRvdGFsVHMpICogMTAwKSAlPiUKICAgIHVuZ3JvdXAoKQopCgptZXRob2RzX2luZCRyYW5rIDwtIGF2ZShtZXRob2RzX2luZCR0b3RhbFRzLCBtZXRob2RzX2luZCRQcm9qZWN0LCBGVU4gPSBmdW5jdGlvbih4KSByYW5rKC14KSkKCmJhcnBsb3QxIDwtIGdncGxvdChmaWx0ZXIobWV0aG9kc19pbmQsIFByb2plY3QgJWluJSBwcm9qZWN0c1sxOjVdLCByYW5rIDw9NSkpICsKICBnZW9tX2JhcihhZXMoeCA9IFByb2plY3QsIHkgPSB0b3RhbFRzLCBmaWxsID0gTWV0cmljLCBncm91cCA9IE1ldHJpYyksIHBvc2l0aW9uID0gImRvZGdlIiwgc3RhdCA9ICJpZGVudGl0eSIpICsKICAjZ2VvbV90ZXh0KCBhZXMoeCA9IFByb2plY3QsIHkgPSB0b3RhbFRzLCBsYWJlbCA9IHJvdW5kKHRvdGFsVHMpLCBncm91cCA9IE1ldHJpYyksICAKICAjICAgICAgICAgICBjaGVja19vdmVybGFwID0gVFJVRSwgcG9zaXRpb24gPSBwb3NpdGlvbl9kb2RnZSh3aWR0aCA9IDEpLCB2anVzdCA9IC0wLjUsIHNpemUgPSAzKSArICNzY2FsZV9maWxsX2dyZXkoKSArIAogICN0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDQ1LCBoanVzdCA9IDEpKSArCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uPSBjKDAuNDAsIDAuOTUpLCBsZWdlbmQuZGlyZWN0aW9uPSJob3Jpem9udGFsIiwgbGVnZW5kLnRpdGxlID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgIGF4aXMudGl0bGUueD1lbGVtZW50X2JsYW5rKCksIGxlZ2VuZC50ZXh0PWVsZW1lbnRfdGV4dChzaXplPTQpLCBsZWdlbmQuYmFja2dyb3VuZCA9IGVsZW1lbnRfcmVjdChmaWxsID0gInRyYW5zcGFyZW50IiwgY29sb3VyID0gTkEpKSArCiAgdGhlbWUocGFuZWwuZ3JpZC5taW5vciA9IGVsZW1lbnRfYmxhbmsoKSwgCiAgICAgICAgcGFuZWwuZ3JpZC5tYWpvciA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBwbG90LmJhY2tncm91bmQgPSBlbGVtZW50X3JlY3QoZmlsbCA9ICJ0cmFuc3BhcmVudCIsIGNvbG91ciA9IE5BKSkgKwogIHlsYWIoIkZyZXF1ZW5jeSIpICsKICAjY29vcmRfY2FydGVzaWFuKHhsaW09YygxLDUpLCB5bGltPWMoMCwgNTApKSArCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzPWNiUGFsZXR0ZSkKCmJhcnBsb3QyIDwtIGdncGxvdChmaWx0ZXIobWV0aG9kc19pbmQsIFByb2plY3QgJWluJSBwcm9qZWN0c1s2OjEwXSwgcmFuayA8PTUpKSArCiAgZ2VvbV9iYXIoYWVzKHggPSBQcm9qZWN0LCB5ID0gdG90YWxUcywgZmlsbCA9IE1ldHJpYywgZ3JvdXAgPSBNZXRyaWMpLCBwb3NpdGlvbiA9ICJkb2RnZSIsIHN0YXQgPSAiaWRlbnRpdHkiKSArCiAgI2dlb21fdGV4dCggYWVzKHggPSBQcm9qZWN0LCB5ID0gdG90YWxUcywgbGFiZWwgPSByb3VuZCh0b3RhbFRzKSwgZ3JvdXAgPSBNZXRyaWMpLCAgCiAgIyAgICAgICAgICAgY2hlY2tfb3ZlcmxhcCA9IFRSVUUsIHBvc2l0aW9uID0gcG9zaXRpb25fZG9kZ2Uod2lkdGggPSAxKSwgdmp1c3QgPSAtMC41LCBzaXplID0gMykgKyAjc2NhbGVfZmlsbF9ncmV5KCkgKyAKICAjdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA0NSwgaGp1c3QgPSAxKSkgKwogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbj0gYygwLjQwLCAwLjk1KSwgbGVnZW5kLmRpcmVjdGlvbj0iaG9yaXpvbnRhbCIsIGxlZ2VuZC50aXRsZSA9IGVsZW1lbnRfYmxhbmsoKSwgCiAgICAgICAgYXhpcy50aXRsZS54PWVsZW1lbnRfYmxhbmsoKSwgbGVnZW5kLnRleHQ9ZWxlbWVudF90ZXh0KHNpemU9NiksIGxlZ2VuZC5iYWNrZ3JvdW5kID0gZWxlbWVudF9yZWN0KGZpbGwgPSAidHJhbnNwYXJlbnQiLCBjb2xvdXIgPSBOQSkpICsKICB0aGVtZShwYW5lbC5ncmlkLm1pbm9yID0gZWxlbWVudF9ibGFuaygpLCAKICAgICAgICBwYW5lbC5ncmlkLm1ham9yID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgIHBsb3QuYmFja2dyb3VuZCA9IGVsZW1lbnRfcmVjdChmaWxsID0gInRyYW5zcGFyZW50IiwgY29sb3VyID0gTkEpKSArCiAgeWxhYigiRnJlcXVlbmN5IikgKwogICNjb29yZF9jYXJ0ZXNpYW4oeGxpbT1jKDEsNSksIHlsaW09YygwLCA1MCkpICsKICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXM9Y2JQYWxldHRlKQoKZ2dhcnJhbmdlKGJhcnBsb3QxLCBiYXJwbG90MiwgbmNvbCA9IDEsIG5yb3cgPSAyLCBjb21tb24ubGVnZW5kID0gVFJVRSkKYGBgCgojIyMgKEc0KSBUbyBhbmFseXNlIHRoZSByZWxhdGlvbiBiZXR3ZWVuIHRoZSBoaXN0b3J5IG9mIGNoYW5nZXMgYW5kIGJ1Z3M7CgojIyMjIChRNC4xKSBJcyBhIGhpZ2ggbnVtYmVyIG9mIGNoYW5nZXMgYW4gaW5kaWNhdGl2ZSBvZiBidWdzIGludHJvZHVjdGlvbj8KCmBgYHtyfQoKI0NoYW5nZXMgQ2hhcnQKbWV0aG9kc19jaGFuZ2VzIDwtIGZpbHRlcihtZXRob2RzX3RvdGFsLCBjaGFuZ2VUeXBlID09ICdBbGwnLCBncm91cE1ldHJpYyA9PSAnQWxsJywgTWV0cmljID09ICdBbGwnKQoKI0NhbGN1bGluZyBwZWFrcwptZXRob2RzX2NoYW5nZXNbLCJ0b3RhbG9mQnVnc0lucyJdIDwtIG1hcGx5KG1ldGhvZHNfY2hhbmdlcyRidWdzSW5zZXJ0aW9uLCBnZXRUb3RhbEJ1Z3NJbnMpCgojRmlsdGVyaW5nIG9ubHkgdHMgd2l0aCBidWdzIGFuZCBtb3JlIHdpdGggb25lIGNvbW1pdAptZXRob2RzX2NoYW5nZXMgPC0gZmlsdGVyKG1ldGhvZHNfY2hhbmdlcywgdG90YWxvZkJ1Z3NJbnMgPiAwLCBOdGltZW9mQ29tbWl0cyA+IDEpCgojR2VuZXJhdGluZyBpZCBvZiBkYXRhIGZyYW1lCm1ldGhvZHNfY2hhbmdlcyA8LSBnZW5JZChtZXRob2RzX2NoYW5nZXMpCgojTGlzdCBvZiBjaGFuZ2VzIGFuZCBidWdzIGluc2VydGlvbnMKbGlzdG9mUGVha3MgPDwtIG1ldGhvZHNfY2hhbmdlcyRlbGVtZW50c1ZhbHVlCmxpc3RvZkJ1Z3NJbnMgPDwtIG1ldGhvZHNfY2hhbmdlcyRidWdzSW5zZXJ0aW9uCgojQ3JlYXRpbmcgY29sdW1ucwptZXRob2RzX2NoYW5nZXNbLGMoInBlYWtzIiwgInRwIiwgImZwIiwgImZuIiwgInRuIiwgIlByZWNpc2lvbiIsICJSZWNhbGwiLCAiRm1lYXN1cmUiKV0gPC0gMCAKCiNjYWxjdWxhdGluZyBjb25mdXNpb24gbWF0cml4Cm1ldGhvZHNfY2hhbmdlc1ssYygicGVha3MiLCAidHAiLCAiZnAiLCAiZm4iLCAidG4iLCAiUHJlY2lzaW9uIiwgIlJlY2FsbCIsICJGbWVhc3VyZSIpXSAgPC0gIHBseXI6OmxkcGx5KG1ldGhvZHNfY2hhbmdlcyRpZCwgZ2V0U3RhdHNQcm9jZXNzKQoKI0dyb3VwaW5nIGRhdGEKY29uZnVzaW9uX21hdHJpeCA8LSBhcy5kYXRhLmZyYW1lKAogIG1ldGhvZHNfY2hhbmdlcyAlPiUKICAgIGRwbHlyOjpncm91cF9ieShQcm9qZWN0KSAlPiUKICAgIGRwbHlyOjpzdW1tYXJpc2UoCiAgICAgIFByZWNpc2lvbiA9IG1lZGlhbihQcmVjaXNpb24sIG5hLnJtID0gVFJVRSksCiAgICAgIFJlY2FsbCA9IG1lZGlhbihSZWNhbGwsIG5hLnJtID0gVFJVRSksCiAgICAgIEZtZWFzdXJlID0gbWVkaWFuKEZtZWFzdXJlLCBuYS5ybSA9IFRSVUUpCiAgICApCikKCiNQaXZvdCBkYXRhCmRhdGFfcGxvdCA8LSBtZWx0KGNvbmZ1c2lvbl9tYXRyaXgsIGlkID0gKGMoIlByb2plY3QiKSkpCmNvbG5hbWVzKGRhdGFfcGxvdCkgPC0gYygiUHJvamVjdCIsICJNZWFzdXJlIiwgIlZhbHVlcyIpCgojUGxvdGluZyByZXN1bHRzCmdncGxvdChkYXRhX3Bsb3QpICsKICBnZW9tX2JhcihhZXMoeCA9IFByb2plY3QsIHkgPSBWYWx1ZXMsIGZpbGwgPSBNZWFzdXJlLCBncm91cCA9IE1lYXN1cmUpLCBwb3NpdGlvbiA9ICJkb2RnZSIsIHN0YXQgPSAiaWRlbnRpdHkiKSArCiAgZ2VvbV90ZXh0KGFlcyh4ID0gUHJvamVjdCwgeSA9IFZhbHVlcywgbGFiZWwgPSByb3VuZChWYWx1ZXMpLCBncm91cCA9IE1lYXN1cmUpLCAgCiAgICAgICAgICAgICBjaGVja19vdmVybGFwID0gVFJVRSwgcG9zaXRpb24gPSBwb3NpdGlvbl9kb2RnZSh3aWR0aCA9IDEpLCB2anVzdCA9IC0wLjUsIHNpemUgPSAzKSArICNzY2FsZV9maWxsX2dyZXkoKSArIAogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gNDUsIGhqdXN0ID0gMSkpICsKICB0aGVtZShsZWdlbmQuZGlyZWN0aW9uPSJ2ZXJ0aWNhbCIsIGxlZ2VuZC50aXRsZSA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBheGlzLnRpdGxlLng9ZWxlbWVudF9ibGFuaygpLCBsZWdlbmQudGV4dD1lbGVtZW50X3RleHQoc2l6ZT01KSwgbGVnZW5kLmJhY2tncm91bmQgPSBlbGVtZW50X3JlY3QoZmlsbCA9ICJ0cmFuc3BhcmVudCIsIGNvbG91ciA9IE5BKSkgKwogIHRoZW1lKHBhbmVsLmdyaWQubWlub3IgPSBlbGVtZW50X2JsYW5rKCksIAogICAgICAgIHBhbmVsLmdyaWQubWFqb3IgPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgcGxvdC5iYWNrZ3JvdW5kID0gZWxlbWVudF9yZWN0KGZpbGwgPSAidHJhbnNwYXJlbnQiLCBjb2xvdXIgPSBOQSkpICsKICAjeWxhYigiRnJlcXVlbmN5IikgKwogICNjb29yZF9jYXJ0ZXNpYW4oeGxpbT1jKDEsNSksIHlsaW09YygwLCA1MCkpICsKICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXM9Y2JQYWxldHRlKQoKYGBgCgojIyMjIFJlc3VsdHMgCmBgYHtyfQpjb25mdXNpb25fbWF0cml4CmBgYAoKCiMjIyMgKFE0LjEpIElzIGEgaGlnaCBudW1iZXIgb2YgY2hhbmdlcyBhbiBpbmRpY2F0aXZlIG9mIGJ1Z3MgaW50cm9kdWN0aW9uIGluIEdyYW5nZXIgcG9zaXRpdmVzIGNhc2VzPwoKYGBge3J9CiNHcmFuZ2VyCmRhdGFfZ3JhbmdlciA8LSBmaWx0ZXIobWV0aG9kc19jaGFuZ2VzLCBQMSA9PSAxLCBQMiA9PSAxLCBQMyA9PSAxLCBQNCA9PSAxLCBQNSA9PSAxLCBHcmFuZ2VyUG9zID09IDEpCgojR3JvdXBpbmcgZGF0YQpjb25mdXNpb25fbWF0cml4IDwtIGFzLmRhdGEuZnJhbWUoCiAgZGF0YV9ncmFuZ2VyICU+JQogICAgZHBseXI6Omdyb3VwX2J5KFByb2plY3QpICU+JQogICAgZHBseXI6OnN1bW1hcmlzZSgKICAgICAgUHJlY2lzaW9uID0gbWVkaWFuKFByZWNpc2lvbiwgbmEucm0gPSBUUlVFKSwKICAgICAgUmVjYWxsID0gbWVkaWFuKFJlY2FsbCwgbmEucm0gPSBUUlVFKSwKICAgICAgRm1lYXN1cmUgPSBtZWRpYW4oRm1lYXN1cmUsIG5hLnJtID0gVFJVRSkKICAgICkKKQoKY29uZnVzaW9uX21hdHJpeAoKYGBgCgo=