(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)

(G3) To analyse the kind of changes are mostly related to the bugs insertion;
(Q3.1) Which are the types (Add/Del) of changes more frequent in the bugs insertion?
#Changes Chart
methods_changes <- filter(methods_insertions, changeType != 'All', groupMetric == 'All', Metric == 'All')
methods_changes[methods_changes$changeType == "changeMetricsAddition", c("changeType")] <- "Addition"
methods_changes[methods_changes$changeType == "changeMetricsDeletion", c("changeType")] <- "Deletion"
methods_changes[methods_changes$Project == "Elasticsearch-hadoop",c("Project")] <- "Es. Hadoop"
methods_changes[methods_changes$Project == "Signal-Android",c("Project")] <- "S. Android"
methods_changes[methods_changes$Project == "Material Drawer",c("Project")] <- "M. Drawer"
methods_changes[methods_changes$Project == "Material-Dialogs",c("Project")] <- "M. Dialogs"
cbPalette <- c("#009E73", "#F15854")
methods_changes <- as.data.frame(
methods_changes %>%
dplyr::group_by(Project, changeType) %>%
dplyr::summarise(totalChanges = sum(Count)) %>%
mutate(Percentual = totalChanges / sum(totalChanges) * 100) %>%
ungroup()
)
ggplot(methods_changes) +
geom_bar(aes(x = Project, y = Percentual, fill = changeType, group = changeType), position = "dodge", stat = "identity") +
geom_text( aes(x = Project, y = Percentual, label = round(Percentual), group = changeType),
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.position= c(0.82, 0.95), legend.direction="horizontal", legend.title = element_blank(),
axis.title.x=element_blank(), legend.text=element_text(size=7), 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)) +
scale_fill_manual(values=cbPalette)

(Q3.2) Which are the metrics groups more frequent in the bugs insertion?
methods_groups<- filter(methods_insertions, groupMetric != "RM", changeType == 'All', groupMetric != 'All', Metric == 'All')
#reorder(methods_groups$Changes, methods_groups$groupMetric, function(x)-length(x))
methods_groups[methods_groups$Project == "Elasticsearch-hadoop",c("Project")] <- "Es. Hadoop"
methods_groups[methods_groups$Project == "Signal-Android",c("Project")] <- "S. Android"
methods_groups[methods_groups$Project == "Material Drawer",c("Project")] <- "M. Drawer"
methods_groups[methods_groups$Project == "Material-Dialogs",c("Project")] <- "M. Dialogs"
cbPalette <- c("#4D4D4D", "#5DA5DA", "#FAA43A", "#B276B2", "#F15854", "#009E73", "#F0E442", "#0072B2", "#999999", "#993300")
methods_groups <- as.data.frame(
methods_groups %>%
dplyr::group_by(Project, groupMetric) %>%
dplyr::summarise(totalTs = sum(Count)) %>%
mutate(Percentual = totalTs / sum(totalTs) * 100) %>%
ungroup()
)
methods_groups$rank <- ave(methods_groups$totalTs, methods_groups$Project, FUN = function(x) rank(-x))
barplot1 <- ggplot(filter(methods_groups, Project %in% projects[1:5], rank <=5)) +
geom_bar(aes(x = Project, y = totalTs, fill = groupMetric, group = groupMetric), position = "dodge", stat = "identity") +
geom_text( aes(x = Project, y = totalTs, label = round(totalTs), group = groupMetric),
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.position= c(0.40, 0.95), legend.direction="horizontal", legend.title = element_blank(),
axis.title.x=element_blank(), legend.text=element_text(size=6), 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)
barplot2 <- ggplot(filter(methods_groups, Project %in% projects[6:10], rank <=5)) +
geom_bar(aes(x = Project, y = totalTs, fill = groupMetric, group = groupMetric), position = "dodge", stat = "identity") +
geom_text( aes(x = Project, y = totalTs, label = round(totalTs), group = groupMetric),
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.position= c(0.40, 0.95), legend.direction="horizontal", legend.title = element_blank(),
axis.title.x=element_blank(), legend.text=element_text(size=6), 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)
ggarrange(barplot1, barplot2, ncol = 1, nrow = 2, common.legend = TRUE)


(Q3.3) Which are the change metrics more frequent in the bugs insertion?
#Filter:D
methods_ind <- filter(methods_insertions, groupMetric != "RM", changeType == 'All', groupMetric != 'All', Metric != 'All')
#reorder(methods_groups$Changes, methods_groups$groupMetric, function(x)-length(x))
methods_ind[methods_ind$Project == "Elasticsearch-hadoop",c("Project")] <- "Es. Hadoop"
methods_ind[methods_ind$Project == "Signal-Android",c("Project")] <- "S. Android"
methods_ind[methods_ind$Project == "Material Drawer",c("Project")] <- "M. Drawer"
methods_ind[methods_ind$Project == "Material-Dialogs",c("Project")] <- "M. Dialogs"
cbPalette <- c("#4D4D4D", "#5DA5DA", "#FAA43A", "#B276B2", "#F15854", "#009E73", "#F0E442", "#0072B2", "#999999", "#993300")
methods_ind <- as.data.frame(
methods_ind %>%
dplyr::group_by(Project, Metric) %>%
dplyr::summarise(totalTs = sum(Count)) %>%
mutate(Percentual = totalTs / sum(totalTs) * 100) %>%
ungroup()
)
methods_ind$rank <- ave(methods_ind$totalTs, methods_ind$Project, FUN = function(x) rank(-x))
barplot1 <- ggplot(filter(methods_ind, Project %in% projects[1:5], rank <=5)) +
geom_bar(aes(x = Project, y = totalTs, fill = Metric, group = Metric), position = "dodge", stat = "identity") +
#geom_text( aes(x = Project, y = totalTs, label = round(totalTs), group = Metric),
# 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.position= c(0.40, 0.95), legend.direction="horizontal", legend.title = element_blank(),
axis.title.x=element_blank(), legend.text=element_text(size=4), 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)
barplot2 <- ggplot(filter(methods_ind, Project %in% projects[6:10], rank <=5)) +
geom_bar(aes(x = Project, y = totalTs, fill = Metric, group = Metric), position = "dodge", stat = "identity") +
#geom_text( aes(x = Project, y = totalTs, label = round(totalTs), group = Metric),
# 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.position= c(0.40, 0.95), legend.direction="horizontal", legend.title = element_blank(),
axis.title.x=element_blank(), legend.text=element_text(size=6), 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)
ggarrange(barplot1, barplot2, ncol = 1, nrow = 2, common.legend = TRUE)


(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)

(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=