diff --git a/src/r/make_manuscript_figures.Rmd b/src/r/make_manuscript_figures.Rmd index 4a247a6..faf6b22 100644 --- a/src/r/make_manuscript_figures.Rmd +++ b/src/r/make_manuscript_figures.Rmd @@ -185,7 +185,7 @@ final_figure dev.off() ``` #### vii. Create the accessory function -This accessory function `pathway_heatmap` will create a heatmap for specific metabolic pathways using the `data` variable constructed in the previous code blocks. You can also subset a data frame manually and visualize it that way. +This accessory function `flux_heatmap` will create a heatmap for specific metabolic pathways using the `data` variable constructed in the previous code blocks. You can also subset a data frame manually and visualize it that way. ```{r, fig.width=20, fig.height=12.5, fig.align='right', dpi=100} flux_heatmap = function(df, pathway){ @@ -210,6 +210,7 @@ flux_heatmap = function(df, pathway){ mid2_data = abs(data[, c("GSE17708_24hrs", "Garcia_24hrs", "GSE147405_24hrs")]) late_data = abs(data[, c("GSE17708_72hrs", "GSE17518_72hrs", "Garcia_48hrs", "Keshamouni_72hrs", "GSE147405_72hrs")]) + tmp = cbind(early_data, mid1_data, mid2_data, late_data) # Create column annotation bars h1_col = HeatmapAnnotation(h1=anno_block(gp=gpar(fill="#CAC4CE"), @@ -246,7 +247,10 @@ flux_heatmap = function(df, pathway){ ) # Construct the heatmaps - col_fun = colorRamp2(c(0, median(data), max(data)), + col_fun = colorRamp2(c(0, + median(as.matrix(tmp), + na.rm=TRUE), + max(as.matrix(tmp), na.rm=TRUE)), c("Gray", "#FD7470", "#DC1C13")) h1 = Heatmap(row_labels=data$name, row_names_side="left", @@ -388,7 +392,7 @@ ko_heatmap = function(df, pathway){ mid2_data = data[, c("GSE17708_24hrs", "Garcia_24hrs", "GSE147405_24hrs")] - 1 late_data = data[, c("GSE17708_72hrs", "GSE17518_72hrs", "Garcia_48hrs", "Keshamouni_72hrs", "GSE147405_72hrs")] - 1 - tmp = cbind(early_data, mid1_data, mid2_data, late_data) - 1 + tmp = cbind(early_data, mid1_data, mid2_data, late_data) # Create column annotation bars h1_col = HeatmapAnnotation(h1=anno_block(gp=gpar(fill="#CAC4CE"), @@ -411,7 +415,7 @@ ko_heatmap = function(df, pathway){ # Construct experiment heatmap annotation hm = Heatmap(as.matrix(expt_data), col = colorRamp2(c(1, 5), - c("Gray", "#95C623")), + c("#FFFFFF", "#5BC0BE", "#3A506B", "#1C2541", "#0B132B")), heatmap_legend_param=list(title="Experiments", color_bar="discrete"), rect_gp = gpar(col="black", @@ -427,7 +431,7 @@ ko_heatmap = function(df, pathway){ ) # Construct the heatmaps - col_fun = colorRamp2(c(min(tmp), 0, max(tmp)), + col_fun = colorRamp2(c(min(as.matrix(tmp)), 0, max(as.matrix(tmp))), c("#073B4C", "#FFFFFF", "#EF476F")) h1 = Heatmap(row_labels=data$name, row_names_side="left", @@ -472,7 +476,7 @@ ko_heatmap = function(df, pathway){ width = ncol(late_data)*unit(5, "mm"), height = nrow(late_data)*unit(5, "mm"), heatmap_legend_param=list(title="Normalized KO Growth Score", - at = c(min(tmp), 0, max(tmp)), + at = c(min(as.matrix(tmp)), 0, max(as.matrix(tmp))), labels = c("Decr. Fitness", "No change", "Incr. fitness"))) # Return the final figure @@ -482,7 +486,7 @@ ko_heatmap = function(df, pathway){ } ``` -### B. Plot the top 50 reactions based on priority score. +### C. Plot the top 50 reactions based on priority score. ```{r, fig.width=20, fig.height=12.5, fig.align='right', dpi=100} # Sort data by priority score data = data[order(data$`Absolute Effect * N expts`, decreasing=TRUE), ] @@ -504,7 +508,7 @@ dev.off top50_figures ``` -### C. Grab high confidence reactions (2 or more in same sample) +### D. Grab high confidence reactions (2 or more in same sample) There's not that much for high confidence reactions. ```{r, fig.width=20, fig.height=12.5, fig.align='right', dpi=100} @@ -530,7 +534,7 @@ specific_figures ``` -### D. Grab low confidence reactions (1 in same sample) +### E. Grab low confidence reactions (1 in same sample) The list of low confidence reactions I'd like to visualize is high. ```{r} @@ -634,6 +638,9 @@ hm = Heatmap(as.matrix(data[, "Std_All"]), ### D. Create the Heatmap with additional figures ```{r, fig.width=20, fig.height=12.5, fig.align='right', dpi=100} final_data = as.matrix(tmp) +col_fun = colorRamp2(c(min(as.matrix(tmp)), 0, max(as.matrix(tmp))), + c("#073B4C", "#FFFFFF", "#EF476F")) + ht = Heatmap(row_labels=data$name, final_data, row_names_side="left", @@ -641,10 +648,9 @@ ht = Heatmap(row_labels=data$name, lwd = 1), cluster_columns=FALSE, cluster_rows=FALSE, - col = colorRamp2(c(-0.5, 0, 0.1), - c("blue", "white", "red")), + col = col_fun, heatmap_legend_param=list(title="Normalized KO Growth Score", - at = c(-0.6, 0, 0.2), + at = c(min(as.matrix(tmp)), 0, max(as.matrix(tmp))), labels = c("Decr. Fitness", "No change", "Incr. fitness")), width = ncol(final_data)*unit(5, "mm"), height = nrow(final_data)*unit(5, "mm")) + @@ -652,11 +658,11 @@ ht = Heatmap(row_labels=data$name, ht ``` - +Save figures ```{r} png(filename="D:/Analysis/EMT/figures/scRNASeq_avg_rxn_ko.png", - width=7.5, - height=10, + width=20, + height=12.5, units='in', res=1200) ht diff --git a/src/r/make_manuscript_figures.nb.html b/src/r/make_manuscript_figures.nb.html index c73ff69..8b79383 100644 --- a/src/r/make_manuscript_figures.nb.html +++ b/src/r/make_manuscript_figures.nb.html @@ -1755,14 +1755,80 @@

Load Libraries

Let’s load some plotting libraries.

- -
library(tidyverse)
-library(ggplot2)
-library(reshape2)
-library(extrafont)
-library(ComplexHeatmap)
-library(circlize)
-#font_import()
+
+
library(tidyverse)
+ + +
Registered S3 methods overwritten by 'dbplyr':
+  method         from
+  print.tbl_lazy     
+  print.tbl_sql      
+-- Attaching packages ----------------------------------------------------------------------------------------------- tidyverse 1.3.1 --
+v ggplot2 3.3.3     v purrr   0.3.4
+v tibble  3.1.1     v dplyr   1.0.5
+v tidyr   1.1.3     v stringr 1.4.0
+v readr   1.4.0     v forcats 0.5.1
+-- Conflicts -------------------------------------------------------------------------------------------------- tidyverse_conflicts() --
+x dplyr::filter() masks stats::filter()
+x dplyr::lag()    masks stats::lag()
+ + +
library(ggplot2)
+library(reshape2)
+ + +

+Attaching package: 㤼㸱reshape2㤼㸲
+
+The following object is masked from 㤼㸱package:tidyr㤼㸲:
+
+    smiths
+ + +
library(extrafont)
+ + +
Registering fonts with R
+ + +
library(ComplexHeatmap)
+ + +
Loading required package: grid
+========================================
+ComplexHeatmap version 2.6.2
+Bioconductor page: http://bioconductor.org/packages/ComplexHeatmap/
+Github page: https://github.com/jokergoo/ComplexHeatmap
+Documentation: http://jokergoo.github.io/ComplexHeatmap-reference
+
+If you use it in published research, please cite:
+Gu, Z. Complex heatmaps reveal patterns and correlations in multidimensional 
+  genomic data. Bioinformatics 2016.
+
+This message can be suppressed by:
+  suppressPackageStartupMessages(library(ComplexHeatmap))
+========================================
+ + +
library(circlize)
+ + +
========================================
+circlize version 0.4.12
+CRAN page: https://cran.r-project.org/package=circlize
+Github page: https://github.com/jokergoo/circlize
+Documentation: https://jokergoo.github.io/circlize_book/book/
+
+If you use it in published research, please cite:
+Gu, Z. circlize implements and enhances circular visualization
+  in R. Bioinformatics 2014.
+
+This message can be suppressed by:
+  suppressPackageStartupMessages(library(circlize))
+========================================
+ + +
#font_import()
 #loadfonts(device = "win")
@@ -1996,11 +2062,11 @@

vi. Save the figure

vii. Create the accessory function

-

This accessory function pathway_heatmap will create a heatmap for specific metabolic pathways using the data variable constructed in the previous code blocks. You can also subset a data frame manually and visualize it that way.

+

This accessory function flux_heatmap will create a heatmap for specific metabolic pathways using the data variable constructed in the previous code blocks. You can also subset a data frame manually and visualize it that way.

- -
pathway_heatmap = function(df, pathway){
+
+
flux_heatmap = function(df, pathway){
   
   # If pathway variable is missing, just visualize everything
   if(missing(pathway)){
@@ -2022,6 +2088,7 @@ 

vii. Create the accessory function

mid2_data = abs(data[, c("GSE17708_24hrs", "Garcia_24hrs", "GSE147405_24hrs")]) late_data = abs(data[, c("GSE17708_72hrs", "GSE17518_72hrs", "Garcia_48hrs", "Keshamouni_72hrs", "GSE147405_72hrs")]) + tmp = cbind(early_data, mid1_data, mid2_data, late_data) # Create column annotation bars h1_col = HeatmapAnnotation(h1=anno_block(gp=gpar(fill="#CAC4CE"), @@ -2058,7 +2125,10 @@

vii. Create the accessory function

) # Construct the heatmaps - col_fun = colorRamp2(c(0, 5, 20), + col_fun = colorRamp2(c(0, + median(as.matrix(tmp), + na.rm=TRUE), + max(as.matrix(tmp), na.rm=TRUE)), c("Gray", "#FD7470", "#DC1C13")) h1 = Heatmap(row_labels=data$name, row_names_side="left", @@ -2102,7 +2172,7 @@

vii. Create the accessory function

bottom_annotation=h4_col, width = ncol(late_data)*unit(5, "mm"), height = nrow(late_data)*unit(5, "mm"), - heatmap_legend_param=list(title="Absolute Flux")) + heatmap_legend_param=list(title="Absolute flux (gDW/mmol*hr)")) # Return the final figure final_figure = h1+h2+h3+h4+hm+bp @@ -2119,8 +2189,8 @@

C. Visualize Glycolytic Reactions

Now let’s specifically get reactions related to Glycolysis.

- -
glycolysis_figures = pathway_heatmap(data, pathway="Glycolysis/Gluconeogenesis")
+ +
glycolysis_figures = flux_heatmap(data, pathway="Glycolysis/Gluconeogenesis")
The input is a data frame, convert it to the matrix.The input is a data frame, convert it to the matrix.The input is a data frame, convert it to the matrix.The input is a data frame, convert it to the matrix.
@@ -2145,8 +2215,8 @@

C. Visualize Glycolytic Reactions

D. Visualize Pentose Phosphate Pathway Reactions

- -
ppp_figures = pathway_heatmap(data, pathway="Pentose Phosphate Pathway")
+ +
ppp_figures = flux_heatmap(data, pathway="Pentose Phosphate Pathway")
The input is a data frame, convert it to the matrix.The input is a data frame, convert it to the matrix.The input is a data frame, convert it to the matrix.The input is a data frame, convert it to the matrix.
@@ -2172,7 +2242,7 @@

E. Visualize Specific Reactions

Now let’s specifically get reactions that are unique to each state.

- +
# Manually subset reactions
 reactions_of_interest = c("ribulose 5-phosphate 3-epimerase",
                           "Biotin transport via sodium symport",
@@ -2183,7 +2253,7 @@ 

E. Visualize Specific Reactions

specific_data = data[idx, ] # Create figures -specific_figures = pathway_heatmap(specific_data)
+specific_figures = flux_heatmap(specific_data)
The input is a data frame, convert it to the matrix.The input is a data frame, convert it to the matrix.The input is a data frame, convert it to the matrix.The input is a data frame, convert it to the matrix.
@@ -2246,7 +2316,7 @@

A. Load Data

B. Create accessory function

- +
ko_heatmap = function(df, pathway){
   
   # If pathway variable is missing, just visualize everything
@@ -2269,7 +2339,7 @@ 

B. Create accessory function

mid2_data = data[, c("GSE17708_24hrs", "Garcia_24hrs", "GSE147405_24hrs")] - 1 late_data = data[, c("GSE17708_72hrs", "GSE17518_72hrs", "Garcia_48hrs", "Keshamouni_72hrs", "GSE147405_72hrs")] - 1 - tmp = cbind(early_data, mid1_data, mid2_data, late_data) - 1 + tmp = cbind(early_data, mid1_data, mid2_data, late_data) # Create column annotation bars h1_col = HeatmapAnnotation(h1=anno_block(gp=gpar(fill="#CAC4CE"), @@ -2308,7 +2378,7 @@

B. Create accessory function

) # Construct the heatmaps - col_fun = colorRamp2(c(min(tmp), 0, max(tmp)), + col_fun = colorRamp2(c(min(as.matrix(tmp)), 0, max(as.matrix(tmp))), c("#073B4C", "#FFFFFF", "#EF476F")) h1 = Heatmap(row_labels=data$name, row_names_side="left", @@ -2353,7 +2423,7 @@

B. Create accessory function

width = ncol(late_data)*unit(5, "mm"), height = nrow(late_data)*unit(5, "mm"), heatmap_legend_param=list(title="Normalized KO Growth Score", - at = c(min(tmp), 0, max(tmp)), + at = c(min(as.matrix(tmp)), 0, max(as.matrix(tmp))), labels = c("Decr. Fitness", "No change", "Incr. fitness"))) # Return the final figure @@ -2365,18 +2435,18 @@

B. Create accessory function

-
-

B. Plot the top 50 reactions based on priority score.

+
+

C. Plot the top 50 reactions based on priority score.

-

+

-
-

C. Grab high confidence reactions (2 or more in same sample)

+
+

D. Grab high confidence reactions (2 or more in same sample)

There’s not that much for high confidence reactions.

@@ -2406,11 +2476,22 @@

C. Grab high confidence reactions (2 or more in same sample)

null device 
           1 
+ +
# Show
+specific_figures
+ + +

+ + +
NA
+NA
+
-
-

D. Grab low confidence reactions (1 in same sample)

+
+

E. Grab low confidence reactions (1 in same sample)

The list of low confidence reactions I’d like to visualize is high.

@@ -2459,20 +2540,9 @@

D. Grab low confidence reactions (1 in same sample)

Subset and create the plot.

- -
idx = data$`BiGG Reaction ID` %in% reactions_of_interest
-specific_data = data[idx, ]
-
-# Create figures
-specific_figures = ko_heatmap(specific_data)
-png(filename="D:/Analysis/EMT/figures/RECON1_rxnko_low_priority_heatmap.png",
-       width=20,
-       height=12.5,
-       units='in',
-    res=1200)
-specific_figures
-dev.off()
- + +

+
@@ -2491,11 +2561,33 @@

3. Single-Cell Reaction KOs

A. Load Data

- +
filename = "D:/Analysis/EMT/data/scRNASeq Reaction KO.csv"
-data = read_csv(filename)
-
-# Create new variable for row names
+data = read_csv(filename)
+ + +

+-- Column specification ----------------------------------------------------------------------------------------------------------------
+cols(
+  `Reaction Name` = col_character(),
+  `BiGG Reaction ID` = col_character(),
+  `KEGG Subsystem` = col_character(),
+  Average_All = col_double(),
+  Average_Day0 = col_double(),
+  Average_Hour8 = col_double(),
+  Average_Day1 = col_double(),
+  Average_Day3 = col_double(),
+  Average_Day7 = col_double(),
+  Std_All = col_double(),
+  Std_Day0 = col_double(),
+  Std_Hour8 = col_double(),
+  Std_Day1 = col_double(),
+  Std_Day3 = col_double(),
+  Std_Day7 = col_double()
+)
+ + +
# Create new variable for row names
 data$name = paste0(data$`BiGG Reaction ID`, 
                     ', ',
                     data$`KEGG Subsystem`)
@@ -2521,12 +2613,14 @@

B. Subset the average data columns

C. Create an annotation heatmap showing the average standard deviation for each reaction across all cells

- +
hm = Heatmap(as.matrix(data[, "Std_All"]),
              rect_gp = gpar(col = "black", 
                             lwd = 1),
              col = colorRamp2(c(0, 0.3), 
                               c("#FFFFFF", "orange")),
+             cluster_columns=FALSE,
+             cluster_rows=FALSE,
              heatmap_legend_param=list(title="Average Std",
                                        color_bar="continuous"),
              width = ncol(data[, "Std_All"])*unit(5, "mm"), 
@@ -2539,8 +2633,11 @@ 

C. Create an annotation heatmap showing the average standard deviation for e

D. Create the Heatmap with additional figures

- +
final_data = as.matrix(tmp)
+col_fun = colorRamp2(c(min(as.matrix(tmp)), 0, max(as.matrix(tmp))), 
+                       c("#073B4C", "#FFFFFF", "#EF476F"))
+
 ht = Heatmap(row_labels=data$name,
              final_data, 
              row_names_side="left",
@@ -2548,10 +2645,9 @@ 

D. Create the Heatmap with additional figures

lwd = 1), cluster_columns=FALSE, cluster_rows=FALSE, - col = colorRamp2(c(-0.5, 0, 0.1), - c("blue", "white", "red")), + col = col_fun, heatmap_legend_param=list(title="Normalized KO Growth Score", - at = c(-0.6, 0, 0.2), + at = c(min(as.matrix(tmp)), 0, max(as.matrix(tmp))), labels = c("Decr. Fitness", "No change", "Incr. fitness")), width = ncol(final_data)*unit(5, "mm"), height = nrow(final_data)*unit(5, "mm")) + @@ -2560,21 +2656,16 @@

D. Create the Heatmap with additional figures

ht
-

+

+

Save figures

- -
png(filename="D:/Analysis/EMT/figures/scRNASeq_avg_rxn_ko.png",
-       width=7.5,
-       height=10,
-       units='in',
-    res=1200)
-ht
-dev.off()
- + +

+
@@ -2584,7 +2675,7 @@

Conclusion

-
LS0tDQp0aXRsZTogIkVNVCBNYW51c2NyaXB0IEZpZ3VyZXMiDQpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sNCmF1dGhvcjogIlNjb3R0Ig0KLS0tDQoNCiMjIFN1bW1hcnkNClRoaXMgbm90ZWJvb2sgbWFrZXMgc2V2ZXJhbCBmaWd1cmVzIGZvciB0aGUgQ09CUkEgRU1UIHB1YmxpY2F0aW9uLg0KDQpgYGB7cn0NCnJtKGxpc3Q9bHMoKSkNCmBgYA0KDQojIyBMb2FkIExpYnJhcmllcw0KTGV0J3MgbG9hZCBzb21lIHBsb3R0aW5nIGxpYnJhcmllcy4NCg0KYGBge3J9DQpsaWJyYXJ5KHRpZHl2ZXJzZSkNCmxpYnJhcnkoZ2dwbG90MikNCmxpYnJhcnkocmVzaGFwZTIpDQpsaWJyYXJ5KGV4dHJhZm9udCkNCmxpYnJhcnkoQ29tcGxleEhlYXRtYXApDQpsaWJyYXJ5KGNpcmNsaXplKQ0KI2ZvbnRfaW1wb3J0KCkNCiNsb2FkZm9udHMoZGV2aWNlID0gIndpbiIpDQpgYGANCg0KIyMgMS4gVmlzdWFsaXplIEJ1bGsgRmx1eGVzDQoNCiMjIyBBLiBMb2FkIERhdGENCkZpcnN0LCBsZXQncyBsb2FkIHRoZSBkYXRhDQpgYGB7cn0NCmZpbGVuYW1lID0gIkQ6L0FuYWx5c2lzL0VNVC9kYXRhL0J1bGsgRmx1eCBJbnRlcnNlY3Rpb24uY3N2Ig0KZGF0YSA9IHJlYWRfY3N2KGZpbGVuYW1lKQ0KYGBgDQoNCiMjIyBCLiBWaXN1YWxpemUgdGhlIHRvcCA1MCByZWFjdGlvbiBrbm9ja291dHMgZnJvbSBidWxrL2FnZ3JlZ2dhdGVkIHN0dWRpZXMNCkhlcmUncyBhIGRlc2NyaXB0aW9uIG9mIGVhY2ggdmFyaWFibGUgY3JlYXRlZDoNCiAgKiBgdG9wNTBgOiBUb3AgNTAgcmVhY3Rpb25zIHJhbmtlZCBieSBwcmlvcml0eSBzY29yZQ0KICAqIGBiYXJkYXRhYDogZGF0YSB1c2VkIGluIEJhciBQbG90DQogICogYGV4cHRfZGF0YWA6IGRhdGEgdXNlZCBpbiBkaXNjcmV0ZSBoZWF0bWFwDQogIA0KYGBge3J9DQojIFNvcnQgZGF0YSBieSBwcmlvcml0eSBzY29yZQ0KZGF0YSA9IGRhdGFbb3JkZXIoZGF0YSRgQWJzb2x1dGUgRWZmZWN0ICogTiBleHB0c2AsIGRlY3JlYXNpbmc9VFJVRSksIF0NCg0KIyBDcmVhdGUgbmV3IHZhcmlhYmxlIGZvciByb3cgbmFtZXMNCmRhdGEkbmFtZSA9IHBhc3RlMChkYXRhJGBCaUdHIFJlYWN0aW9uIElEYCwgDQogICAgICAgICAgICAgICAgICAgICcsICcsDQogICAgICAgICAgICAgICAgICAgIGRhdGEkYEtFR0cgU3Vic3lzdGVtYCkNCg0KIyBHcmFiIHRvcCA1MA0KdG9wNTAgPSBkYXRhWzE6NTAsIF0NCg0KIyBDcmVhdGUgbmV3IGRhdGEgZm9yIGJhcnBsb3RzIGFuZCBkaXNjcmV0ZSBoZWF0bWFwDQpiYXJkYXRhID0gdG9wNTBbLCA0XQ0KZXhwdF9kYXRhID0gdG9wNTBbLCA1XQ0KYGBgDQoNCiMjIyMgaS4gUmVmb3JtYXQgdGhlIGRhdGENCldlJ3JlIGdvaW5nIHRvIGdyYWIgc2VsZWN0ZWQgdGltZSBwb2ludHMgdGhhdCBoYXZlIHJlcGxpY2F0ZSB2YWx1ZXMgYWNyb3NzIG11bHRpcGxlIHN0dWRpZXMgYW5kIHRlbGwgdGhlIEVNVCBzdG9yeS4gVGhlIHNlbGVjdGVkIHRpbWUgcG9pbnRzIHdpbGwgYmUgc3RvcmVkIDQgc2VwYXJhdGUgZGF0YWZyYW1lcyBjb3JyZXNwb25kaW5nIHRvIGVhY2ggdGltZSBwb2ludC4NCg0KYGBge3J9DQojIFNwbGl0IGJ5IGhvdXJzDQplYXJseV9kYXRhID0gYWJzKHRvcDUwWywgYygiR1NFMTc3MDhfMWhycyIsICJHYXJjaWFfMWhycyIpXSkNCm1pZDFfZGF0YSAgPSBhYnModG9wNTBbLCBjKCJHU0UxNzcwOF84aHJzIiwgIkdTRTE0NzQwNV84aHJzIildKQ0KbWlkMl9kYXRhICA9IGFicyh0b3A1MFssIGMoIkdTRTE3NzA4XzI0aHJzIiwgIkdhcmNpYV8yNGhycyIsICJHU0UxNDc0MDVfMjRocnMiKV0pDQpsYXRlX2RhdGEgID0gYWJzKHRvcDUwWywgYygiR1NFMTc3MDhfNzJocnMiLCAiR1NFMTc1MThfNzJocnMiLCAiR2FyY2lhXzQ4aHJzIiwgDQogICAgICAgICAgICAgICAgICAgICAgICJLZXNoYW1vdW5pXzcyaHJzIiwgIkdTRTE0NzQwNV83MmhycyIpXSkNCmBgYA0KDQojIyMjIGlpLiBDcmVhdGUgdGhlIGNvbHVtbiBhbm5vdGF0aW9uIGhlYXRtYXAgZm9yIGVhY2ggdGltZS1wb2ludA0KVGhpcyBjcmVhdGVzIGluZGl2aWR1YWwgYW5ub3RhdGlvbiBiYXJzIGZvciBlYWNoIG9mIHRoZSBjb3JyZXNwb25kaW5nIHRpbWUgcG9pbnRzLg0KDQpgYGB7cn0NCmgxX2NvbCA9IEhlYXRtYXBBbm5vdGF0aW9uKGgxPWFubm9fYmxvY2soZ3A9Z3BhcihmaWxsPSIjQ0FDNENFIiksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxhYmVscz1jKCJFYXJseSIpLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGFiZWxzX2dwPWdwYXIoY29sPSJibGFjayIsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmb250c2l6ZT0xMCkpKQ0KaDJfY29sID0gSGVhdG1hcEFubm90YXRpb24oaDI9YW5ub19ibG9jayhncD1ncGFyKGZpbGw9IiM4RDg2QzkiKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGFiZWxzPWMoIkludC4gMSIpLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGFiZWxzX2dwPWdwYXIoY29sPSJ3aGl0ZSIsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmb250c2l6ZT0xMCkpKQ0KaDNfY29sID0gSGVhdG1hcEFubm90YXRpb24oaDM9YW5ub19ibG9jayhncD1ncGFyKGZpbGw9IiM3MjVBQzEiKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGFiZWxzPWMoIkludC4gMiIpLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGFiZWxzX2dwPWdwYXIoY29sPSJ3aGl0ZSIsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmb250c2l6ZT0xMCkpKQ0KaDRfY29sID0gSGVhdG1hcEFubm90YXRpb24oaDQ9YW5ub19ibG9jayhncD1ncGFyKGZpbGw9IiMyNDIwMzgiKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGFiZWxzPWMoIkxhdGUiKSwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxhYmVsc19ncD1ncGFyKGNvbD0id2hpdGUiLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9udHNpemU9MTApKSkNCmBgYA0KDQojIyMjIGlpaS4gQ3JlYXRlIHRoZSBiYXJwbG90IHRoYXQgc2hvd3MgdGhlIHByaW9yaXR5IHNjb3JlDQpUaGUgYW5ub3RhdGlvbiBiYXJwbG90IHdpbGwgc2hvdyB0aGUgcHJpb3JpdHkgc2NvcmVzIG9uIHRoZSByaWdodGhhbmQgc2lkZS4NCg0KYGBge3J9DQpicCA9IHJvd0Fubm90YXRpb24oDQogIFByaW9yaXR5PWFubm9fYmFycGxvdCgNCiAgICBiYXJkYXRhDQogICkNCikNCmBgYA0KDQojIyMjIGl2LiBDcmVhdGUgYSBoZWF0bWFwIHNob3dpbmcgdGhlIG51bWJlciBvZiBleHBlcmltZW50cyBmb3IgZWFjaCByZWFjdGlvbg0KV2UnbGwgYWxzbyBjcmVhdGUgYW4gYW5ub3RhdGlvbiBoZWF0bWFwIGNvcnJlc3BvbmRpbmcgdG8gdGhlIG51bWJlciBvZiBleHBlcmltZW50cyBmb3IgZWFjaCByZWFjdGlvbi4NCg0KYGBge3IsIGZpZy53aWR0aD0xMCwgZmlnLmhlaWdodD03LjV9DQpobSA9IEhlYXRtYXAoYXMubWF0cml4KGV4cHRfZGF0YSksDQogICAgICAgICAgICAgY29sID0gY29sb3JSYW1wMihjKDEsNSksIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYygiR3JheSIsICIjOTVDNjIzIikpLA0KICAgICAgICAgICAgIGhlYXRtYXBfbGVnZW5kX3BhcmFtPWxpc3QodGl0bGU9IkV4cGVyaW1lbnRzIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbG9yX2Jhcj0iZGlzY3JldGUiKSwNCiAgICAgICAgICAgICByZWN0X2dwID0gZ3Bhcihjb2w9ImJsYWNrIiwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsd2Q9MSksDQogICAgICAgICAgICAgd2lkdGggPSBuY29sKGV4cHRfZGF0YSkqdW5pdCg1LCAibW0iKSwgDQogICAgICAgICAgICAgaGVpZ2h0ID0gbnJvdyhleHB0X2RhdGEpKnVuaXQoNSwgIm1tIikpDQpgYGANCg0KIyMjIyB2LiBDcmVhdGUgdGhlIGZpZ3VyZQ0KRmluYWxseSwgd2UnbGwgY3JlYXRlIHRoZSBlbnRpcmUgZmlndXJlLg0KDQpgYGB7ciwgZmlnLndpZHRoPTIwLCBmaWcuaGVpZ2h0PTEyLjUsIGZpZy5hbGlnbj0ncmlnaHQnLCBkcGk9MTAwfQ0KY29sX2Z1biA9IGNvbG9yUmFtcDIoYygwLCA1LCAyMCksIA0KICAgICAgICAgICAgICAgICAgICAgYygiR3JheSIsICIjRkQ3NDcwIiwgIiNEQzFDMTMiKSkNCmgxID0gSGVhdG1hcChyb3dfbGFiZWxzPXRvcDUwJG5hbWUsDQogICAgICAgICAgICAgcm93X25hbWVzX3NpZGU9ImxlZnQiLA0KICAgICAgICAgICAgIGVhcmx5X2RhdGEsIA0KICAgICAgICAgICAgIGNvbD1jb2xfZnVuLCANCiAgICAgICAgICAgICBjbHVzdGVyX2NvbHVtbnM9RkFMU0UsIA0KICAgICAgICAgICAgICAgcmVjdF9ncCA9IGdwYXIoY29sPSJibGFjayIsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbHdkPTEpLA0KICAgICAgICAgICAgIGNsdXN0ZXJfcm93cz1GQUxTRSwNCiAgICAgICAgICAgICBzaG93X2hlYXRtYXBfbGVnZW5kPUZBTFNFLA0KICAgICAgICAgICAgIGJvdHRvbV9hbm5vdGF0aW9uPWgxX2NvbCwgDQogICAgICAgICAgICAgd2lkdGggPSBuY29sKGVhcmx5X2RhdGEpKnVuaXQoNSwgIm1tIiksIA0KICAgICAgICAgICAgIGhlaWdodCA9IG5yb3coZWFybHlfZGF0YSkqdW5pdCg1LCAibW0iKSkNCmgyID0gSGVhdG1hcChtaWQxX2RhdGEsIA0KICAgICAgICAgICAgIGNvbD1jb2xfZnVuLCANCiAgICAgICAgICAgICBjbHVzdGVyX2NvbHVtbnM9RkFMU0UsIA0KICAgICAgICAgICAgICAgcmVjdF9ncCA9IGdwYXIoY29sPSJibGFjayIsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbHdkPTEpLA0KICAgICAgICAgICAgIGNsdXN0ZXJfcm93cz1GQUxTRSwNCiAgICAgICAgICAgICBzaG93X2hlYXRtYXBfbGVnZW5kPUZBTFNFLA0KICAgICAgICAgICAgIGJvdHRvbV9hbm5vdGF0aW9uPWgyX2NvbCwgDQogICAgICAgICAgICAgd2lkdGggPSBuY29sKG1pZDFfZGF0YSkqdW5pdCg1LCAibW0iKSwgDQogICAgICAgICAgICAgaGVpZ2h0ID0gbnJvdyhtaWQxX2RhdGEpKnVuaXQoNSwgIm1tIikpDQpoMyA9IEhlYXRtYXAobWlkMl9kYXRhLCANCiAgICAgICAgICAgICBjb2w9Y29sX2Z1biwgDQogICAgICAgICAgICAgY2x1c3Rlcl9jb2x1bW5zPUZBTFNFLCANCiAgICAgICAgICAgICAgIHJlY3RfZ3AgPSBncGFyKGNvbD0iYmxhY2siLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGx3ZD0xKSwNCiAgICAgICAgICAgICANCiAgICAgICAgICAgICBjbHVzdGVyX3Jvd3M9RkFMU0UsDQogICAgICAgICAgICAgc2hvd19oZWF0bWFwX2xlZ2VuZD1GQUxTRSwNCiAgICAgICAgICAgICBib3R0b21fYW5ub3RhdGlvbj1oM19jb2wsIA0KICAgICAgICAgICAgIHdpZHRoID0gbmNvbChtaWQyX2RhdGEpKnVuaXQoNSwgIm1tIiksIA0KICAgICAgICAgICAgIGhlaWdodCA9IG5yb3cobWlkMl9kYXRhKSp1bml0KDUsICJtbSIpKQ0KaDQgPSBIZWF0bWFwKGxhdGVfZGF0YSwgDQogICAgICAgICAgICAgY29sPWNvbF9mdW4sIA0KICAgICAgICAgICAgIGNsdXN0ZXJfY29sdW1ucz1GQUxTRSwgDQogICAgICAgICAgICAgICByZWN0X2dwID0gZ3Bhcihjb2w9ImJsYWNrIiwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsd2Q9MSksDQogICAgICAgICAgICAgY2x1c3Rlcl9yb3dzPUZBTFNFLA0KICAgICAgICAgICAgIHNob3dfaGVhdG1hcF9sZWdlbmQ9VFJVRSwNCiAgICAgICAgICAgICBib3R0b21fYW5ub3RhdGlvbj1oNF9jb2wsDQogICAgICAgICAgICAgd2lkdGggPSBuY29sKGxhdGVfZGF0YSkqdW5pdCg1LCAibW0iKSwgDQogICAgICAgICAgICAgaGVpZ2h0ID0gbnJvdyhsYXRlX2RhdGEpKnVuaXQoNSwgIm1tIiksDQogICAgICAgICAgICAgaGVhdG1hcF9sZWdlbmRfcGFyYW09bGlzdCh0aXRsZT0iQWJzb2x1dGUgRmx1eCIpKQ0KDQpmaW5hbF9maWd1cmUgPSBoMStoMitoMytoNCtobSticA0KZmluYWxfZmlndXJlDQpgYGANCg0KIyMjIyB2aS4gU2F2ZSB0aGUgZmlndXJlDQpGaW5hbGx5LCB3ZSdsbCBzYXZlIHRoZSBlbnRpcmUgZmlndXJlIHdpdGggaGlnaCByZXNvbHV0aW9uLg0KDQpgYGB7ciwgZmlnLndpZHRoPTIwLCBmaWcuaGVpZ2h0PTEyLjUsIGZpZy5hbGlnbj0ncmlnaHQnLCBkcGk9MTAwfQ0KcG5nKGZpbGVuYW1lPSJEOi9BbmFseXNpcy9FTVQvZmlndXJlcy9SRUNPTjFfZmx1eF9oZWF0bWFwLnBuZyIsDQogICAgICAgd2lkdGg9MjAsDQogICAgICAgaGVpZ2h0PTEyLjUsDQogICAgICAgdW5pdHM9J2luJywNCiAgICByZXM9MTIwMCkNCmZpbmFsX2ZpZ3VyZQ0KZGV2Lm9mZigpDQpgYGANCiMjIyMgdmlpLiBDcmVhdGUgdGhlIGFjY2Vzc29yeSBmdW5jdGlvbg0KVGhpcyBhY2Nlc3NvcnkgZnVuY3Rpb24gYHBhdGh3YXlfaGVhdG1hcGAgd2lsbCBjcmVhdGUgYSBoZWF0bWFwIGZvciBzcGVjaWZpYyBtZXRhYm9saWMgcGF0aHdheXMgdXNpbmcgdGhlIGBkYXRhYCB2YXJpYWJsZSBjb25zdHJ1Y3RlZCBpbiB0aGUgcHJldmlvdXMgY29kZSBibG9ja3MuIFlvdSBjYW4gYWxzbyBzdWJzZXQgYSBkYXRhIGZyYW1lIG1hbnVhbGx5IGFuZCB2aXN1YWxpemUgaXQgdGhhdCB3YXkuDQoNCmBgYHtyLCBmaWcud2lkdGg9MjAsIGZpZy5oZWlnaHQ9MTIuNSwgZmlnLmFsaWduPSdyaWdodCcsIGRwaT0xMDB9DQpmbHV4X2hlYXRtYXAgPSBmdW5jdGlvbihkZiwgcGF0aHdheSl7DQogIA0KICAjIElmIHBhdGh3YXkgdmFyaWFibGUgaXMgbWlzc2luZywganVzdCB2aXN1YWxpemUgZXZlcnl0aGluZw0KICBpZihtaXNzaW5nKHBhdGh3YXkpKXsNCiAgICBkYXRhID0gZGYNCiAgfWVsc2V7DQogICAgaWR4ID0gKGRmJGBLRUdHIFN1YnN5c3RlbWAgPT0gcGF0aHdheSkNCiAgICBpZHhbaXMubmEoaWR4KV0gPSBGQUxTRQ0KICAgIGRhdGEgPSBkZltpZHgsIF0NCiAgfQ0KDQogICMgQ3JlYXRlIG5ldyBkYXRhIGZvciBiYXJwbG90cyBhbmQgZGlzY3JldGUgaGVhdG1hcA0KICBiYXJkYXRhID0gZGF0YVssIDRdDQogIGJhcmRhdGFbaXMubmEoYmFyZGF0YSldID0gMA0KICBleHB0X2RhdGEgPSBkYXRhWywgNV0NCiAgDQogICMgU3BsaXQgYnkgaG91cnMNCiAgZWFybHlfZGF0YSA9IGFicyhkYXRhWywgYygiR1NFMTc3MDhfMWhycyIsICJHYXJjaWFfMWhycyIpXSkNCiAgbWlkMV9kYXRhICA9IGFicyhkYXRhWywgYygiR1NFMTc3MDhfOGhycyIsICJHU0UxNDc0MDVfOGhycyIpXSkNCiAgbWlkMl9kYXRhICA9IGFicyhkYXRhWywgYygiR1NFMTc3MDhfMjRocnMiLCAiR2FyY2lhXzI0aHJzIiwgIkdTRTE0NzQwNV8yNGhycyIpXSkNCiAgbGF0ZV9kYXRhICA9IGFicyhkYXRhWywgYygiR1NFMTc3MDhfNzJocnMiLCAiR1NFMTc1MThfNzJocnMiLCAiR2FyY2lhXzQ4aHJzIiwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIktlc2hhbW91bmlfNzJocnMiLCAiR1NFMTQ3NDA1XzcyaHJzIildKQ0KICANCiAgIyBDcmVhdGUgY29sdW1uIGFubm90YXRpb24gYmFycw0KICBoMV9jb2wgPSBIZWF0bWFwQW5ub3RhdGlvbihoMT1hbm5vX2Jsb2NrKGdwPWdwYXIoZmlsbD0iI0NBQzRDRSIpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxhYmVscz1jKCJFYXJseSIpLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsYWJlbHNfZ3A9Z3Bhcihjb2w9ImJsYWNrIiwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9udHNpemU9MTApKSkNCiAgaDJfY29sID0gSGVhdG1hcEFubm90YXRpb24oaDI9YW5ub19ibG9jayhncD1ncGFyKGZpbGw9IiM4RDg2QzkiKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsYWJlbHM9YygiSW50LiAxIiksIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxhYmVsc19ncD1ncGFyKGNvbD0id2hpdGUiLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmb250c2l6ZT0xMCkpKQ0KICBoM19jb2wgPSBIZWF0bWFwQW5ub3RhdGlvbihoMz1hbm5vX2Jsb2NrKGdwPWdwYXIoZmlsbD0iIzcyNUFDMSIpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxhYmVscz1jKCJJbnQuIDIiKSwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGFiZWxzX2dwPWdwYXIoY29sPSJ3aGl0ZSIsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZvbnRzaXplPTEwKSkpDQogIGg0X2NvbCA9IEhlYXRtYXBBbm5vdGF0aW9uKGg0PWFubm9fYmxvY2soZ3A9Z3BhcihmaWxsPSIjMjQyMDM4IiksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGFiZWxzPWMoIkxhdGUiKSwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGFiZWxzX2dwPWdwYXIoY29sPSJ3aGl0ZSIsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmb250c2l6ZT0xMCkpKQ0KICANCiAgIyBDb25zdHJ1Y3QgZXhwZXJpbWVudCBoZWF0bWFwIGFubm90YXRpb24NCiAgaG0gPSBIZWF0bWFwKGFzLm1hdHJpeChleHB0X2RhdGEpLA0KICAgICAgICAgICAgIGNvbCA9IGNvbG9yUmFtcDIoYygxLDUpLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGMoIkdyYXkiLCAiIzk1QzYyMyIpKSwNCiAgICAgICAgICAgICBoZWF0bWFwX2xlZ2VuZF9wYXJhbT1saXN0KHRpdGxlPSJFeHBlcmltZW50cyIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb2xvcl9iYXI9ImRpc2NyZXRlIiksIA0KICAgICAgICAgICAgIHdpZHRoID0gbmNvbChleHB0X2RhdGEpKnVuaXQoNSwgIm1tIiksIA0KICAgICAgICAgICAgIGhlaWdodCA9IG5yb3coZXhwdF9kYXRhKSp1bml0KDUsICJtbSIpKQ0KICANCiAgIyBDb25zdHJ1Y3QgcHJpb3JpdHkgc2NvcmUgYmFycGxvdCBhbm5vdGF0aW9uDQogIGJwID0gcm93QW5ub3RhdGlvbigNCiAgICBQcmlvcml0eT1hbm5vX2JhcnBsb3QoDQogICAgICBiYXJkYXRhDQogICAgKQ0KICApDQogIA0KICAjIENvbnN0cnVjdCB0aGUgaGVhdG1hcHMNCiAgY29sX2Z1biA9IGNvbG9yUmFtcDIoYygwLCBtZWRpYW4oZGF0YSksIG1heChkYXRhKSksIA0KICAgICAgICAgICAgICAgICAgICAgICBjKCJHcmF5IiwgIiNGRDc0NzAiLCAiI0RDMUMxMyIpKQ0KICBoMSA9IEhlYXRtYXAocm93X2xhYmVscz1kYXRhJG5hbWUsDQogICAgICAgICAgICAgICByb3dfbmFtZXNfc2lkZT0ibGVmdCIsDQogICAgICAgICAgICAgICBlYXJseV9kYXRhLCANCiAgICAgICAgICAgICAgIGNvbD1jb2xfZnVuLCANCiAgICAgICAgICAgICAgIGNsdXN0ZXJfY29sdW1ucz1GQUxTRSwgDQogICAgICAgICAgICAgICByZWN0X2dwID0gZ3Bhcihjb2w9ImJsYWNrIiwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsd2Q9MSksDQogICAgICAgICAgICAgICBjbHVzdGVyX3Jvd3M9RkFMU0UsDQogICAgICAgICAgICAgICBzaG93X2hlYXRtYXBfbGVnZW5kPUZBTFNFLA0KICAgICAgICAgICAgICAgYm90dG9tX2Fubm90YXRpb249aDFfY29sLCANCiAgICAgICAgICAgICAgIHdpZHRoID0gbmNvbChlYXJseV9kYXRhKSp1bml0KDUsICJtbSIpLCANCiAgICAgICAgICAgICAgIGhlaWdodCA9IG5yb3coZWFybHlfZGF0YSkqdW5pdCg1LCAibW0iKSkNCiAgaDIgPSBIZWF0bWFwKG1pZDFfZGF0YSwgDQogICAgICAgICAgICAgICBjb2w9Y29sX2Z1biwgDQogICAgICAgICAgICAgICBjbHVzdGVyX2NvbHVtbnM9RkFMU0UsIA0KICAgICAgICAgICAgICAgcmVjdF9ncCA9IGdwYXIoY29sPSJibGFjayIsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbHdkPTEpLA0KICAgICAgICAgICAgICAgY2x1c3Rlcl9yb3dzPUZBTFNFLA0KICAgICAgICAgICAgICAgc2hvd19oZWF0bWFwX2xlZ2VuZD1GQUxTRSwNCiAgICAgICAgICAgICAgIGJvdHRvbV9hbm5vdGF0aW9uPWgyX2NvbCwgDQogICAgICAgICAgICAgICB3aWR0aCA9IG5jb2wobWlkMV9kYXRhKSp1bml0KDUsICJtbSIpLCANCiAgICAgICAgICAgICAgIGhlaWdodCA9IG5yb3cobWlkMV9kYXRhKSp1bml0KDUsICJtbSIpKQ0KICBoMyA9IEhlYXRtYXAobWlkMl9kYXRhLCANCiAgICAgICAgICAgICAgIGNvbD1jb2xfZnVuLCANCiAgICAgICAgICAgICAgIGNsdXN0ZXJfY29sdW1ucz1GQUxTRSwgDQogICAgICAgICAgICAgICByZWN0X2dwID0gZ3Bhcihjb2w9ImJsYWNrIiwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsd2Q9MSksDQogICAgICAgICAgICAgICBjbHVzdGVyX3Jvd3M9RkFMU0UsDQogICAgICAgICAgICAgICBzaG93X2hlYXRtYXBfbGVnZW5kPUZBTFNFLA0KICAgICAgICAgICAgICAgYm90dG9tX2Fubm90YXRpb249aDNfY29sLCANCiAgICAgICAgICAgICAgIHdpZHRoID0gbmNvbChtaWQyX2RhdGEpKnVuaXQoNSwgIm1tIiksIA0KICAgICAgICAgICAgICAgaGVpZ2h0ID0gbnJvdyhtaWQyX2RhdGEpKnVuaXQoNSwgIm1tIikpDQogIGg0ID0gSGVhdG1hcChsYXRlX2RhdGEsIA0KICAgICAgICAgICAgICAgY29sPWNvbF9mdW4sIA0KICAgICAgICAgICAgICAgY2x1c3Rlcl9jb2x1bW5zPUZBTFNFLCANCiAgICAgICAgICAgICAgIHJlY3RfZ3AgPSBncGFyKGNvbD0iYmxhY2siLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGx3ZD0xKSwNCiAgICAgICAgICAgICAgIGNsdXN0ZXJfcm93cz1GQUxTRSwNCiAgICAgICAgICAgICAgIHNob3dfaGVhdG1hcF9sZWdlbmQ9VFJVRSwNCiAgICAgICAgICAgICAgIGJvdHRvbV9hbm5vdGF0aW9uPWg0X2NvbCwNCiAgICAgICAgICAgICAgIHdpZHRoID0gbmNvbChsYXRlX2RhdGEpKnVuaXQoNSwgIm1tIiksIA0KICAgICAgICAgICAgICAgaGVpZ2h0ID0gbnJvdyhsYXRlX2RhdGEpKnVuaXQoNSwgIm1tIiksDQogICAgICAgICAgICAgICBoZWF0bWFwX2xlZ2VuZF9wYXJhbT1saXN0KHRpdGxlPSJBYnNvbHV0ZSBmbHV4IChnRFcvbW1vbCpocikiKSkNCiAgDQogICMgUmV0dXJuIHRoZSBmaW5hbCBmaWd1cmUNCiAgZmluYWxfZmlndXJlID0gaDEraDIraDMraDQraG0rYnANCiAgcmV0dXJuKGZpbmFsX2ZpZ3VyZSkNCiAgICANCn0NCmBgYA0KDQojIyMgQy4gVmlzdWFsaXplIEdseWNvbHl0aWMgUmVhY3Rpb25zDQpOb3cgbGV0J3Mgc3BlY2lmaWNhbGx5IGdldCByZWFjdGlvbnMgcmVsYXRlZCB0byBHbHljb2x5c2lzLg0KYGBge3IsIGZpZy53aWR0aD0yMCwgZmlnLmhlaWdodD0xMi41LCBmaWcuYWxpZ249J3JpZ2h0JywgZHBpPTEwMH0NCmdseWNvbHlzaXNfZmlndXJlcyA9IGZsdXhfaGVhdG1hcChkYXRhLCBwYXRod2F5PSJHbHljb2x5c2lzL0dsdWNvbmVvZ2VuZXNpcyIpDQpwbmcoZmlsZW5hbWU9IkQ6L0FuYWx5c2lzL0VNVC9maWd1cmVzL2dseWNvbHlzaXNfZmx1eF9oZWF0bWFwLnBuZyIsDQogICAgICAgd2lkdGg9MjAsDQogICAgICAgaGVpZ2h0PTEyLjUsDQogICAgICAgdW5pdHM9J2luJywNCiAgICByZXM9MTIwMCkNCmdseWNvbHlzaXNfZmlndXJlcw0KZGV2Lm9mZigpDQpgYGANCg0KIyMjIEQuIFZpc3VhbGl6ZSBQZW50b3NlIFBob3NwaGF0ZSBQYXRod2F5IFJlYWN0aW9ucw0KYGBge3IsIGZpZy53aWR0aD0yMCwgZmlnLmhlaWdodD0xMi41LCBmaWcuYWxpZ249J3JpZ2h0JywgZHBpPTEwMH0NCnBwcF9maWd1cmVzID0gZmx1eF9oZWF0bWFwKGRhdGEsIHBhdGh3YXk9IlBlbnRvc2UgUGhvc3BoYXRlIFBhdGh3YXkiKQ0KcG5nKGZpbGVuYW1lPSJEOi9BbmFseXNpcy9FTVQvZmlndXJlcy9wcHBfZmx1eF9oZWF0bWFwLnBuZyIsDQogICAgICAgd2lkdGg9MjAsDQogICAgICAgaGVpZ2h0PTEyLjUsDQogICAgICAgdW5pdHM9J2luJywNCiAgICByZXM9MTIwMCkNCnBwcF9maWd1cmVzDQpkZXYub2ZmKCkNCmBgYA0KDQoNCiMjIyBFLiBWaXN1YWxpemUgU3BlY2lmaWMgUmVhY3Rpb25zDQpOb3cgbGV0J3Mgc3BlY2lmaWNhbGx5IGdldCByZWFjdGlvbnMgdGhhdCBhcmUgdW5pcXVlIHRvIGVhY2ggc3RhdGUuDQpgYGB7ciwgZmlnLndpZHRoPTIwLCBmaWcuaGVpZ2h0PTEyLjUsIGZpZy5hbGlnbj0ncmlnaHQnLCBkcGk9MTAwfQ0KIyBNYW51YWxseSBzdWJzZXQgcmVhY3Rpb25zDQpyZWFjdGlvbnNfb2ZfaW50ZXJlc3QgPSBjKCJyaWJ1bG9zZSA1LXBob3NwaGF0ZSAzLWVwaW1lcmFzZSIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICJCaW90aW4gdHJhbnNwb3J0IHZpYSBzb2RpdW0gc3ltcG9ydCIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICJCaW90aW4gcmV2ZXJzaWJsZSB0cmFuc3BvcnQgdmlhIHByb3RvbiBzeW1wb3J0IiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgIk5BREggZGVoeWRyb2dlbmFzZSwgbWl0b2Nob25kcmlhbCIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICJMLWxhY3RhdGUgZGVoeWRyb2dlbmFzZSIpDQppZHggPSBkYXRhJGBCaUdHIFJlYWN0aW9uIElEYCAlaW4lIHJlYWN0aW9uc19vZl9pbnRlcmVzdA0Kc3BlY2lmaWNfZGF0YSA9IGRhdGFbaWR4LCBdDQoNCiMgQ3JlYXRlIGZpZ3VyZXMNCnNwZWNpZmljX2ZpZ3VyZXMgPSBmbHV4X2hlYXRtYXAoc3BlY2lmaWNfZGF0YSkNCnBuZyhmaWxlbmFtZT0iRDovQW5hbHlzaXMvRU1UL2ZpZ3VyZXMvc3BlY2lmaWNfZmx1eF9oZWF0bWFwLnBuZyIsDQogICAgICAgd2lkdGg9MjAsDQogICAgICAgaGVpZ2h0PTEyLjUsDQogICAgICAgdW5pdHM9J2luJywNCiAgICByZXM9MTIwMCkNCnNwZWNpZmljX2ZpZ3VyZXMNCmRldi5vZmYoKQ0KYGBgDQoNCiMjIDIuIFZpc3VhbGl6ZSB0aGUgQnVsayBSZWFjdGlvbiBLT3MNCmBgYHtyfQ0Kcm0obGlzdD1zZXRkaWZmKGxzKCksICJmbHV4X2hlYXRtYXAiKSkNCmBgYA0KDQojIyMgQS4gTG9hZCBEYXRhDQpgYGB7cn0NCmZpbGVuYW1lID0gIkQ6L0FuYWx5c2lzL0VNVC9kYXRhL0J1bGsgUmVhY3Rpb24gS08gSW50ZXJzZWN0aW9uLmNzdiINCmRhdGEgPSByZWFkX2NzdihmaWxlbmFtZSkNCg0KIyBDcmVhdGUgbmV3IHZhcmlhYmxlIGZvciByb3cgbmFtZXMNCmRhdGEkbmFtZSA9IHBhc3RlMChkYXRhJGBCaUdHIFJlYWN0aW9uIElEYCwgDQogICAgICAgICAgICAgICAgICAgICcsICcsDQogICAgICAgICAgICAgICAgICAgIGRhdGEkYEtFR0cgU3Vic3lzdGVtYCkNCmBgYA0KDQojIyMgQi4gQ3JlYXRlIGFjY2Vzc29yeSBmdW5jdGlvbg0KYGBge3IsIGZpZy53aWR0aD0yMCwgZmlnLmhlaWdodD0xMi41LCBmaWcuYWxpZ249J3JpZ2h0JywgZHBpPTEwMH0NCmtvX2hlYXRtYXAgPSBmdW5jdGlvbihkZiwgcGF0aHdheSl7DQogIA0KICAjIElmIHBhdGh3YXkgdmFyaWFibGUgaXMgbWlzc2luZywganVzdCB2aXN1YWxpemUgZXZlcnl0aGluZw0KICBpZihtaXNzaW5nKHBhdGh3YXkpKXsNCiAgICBkYXRhID0gZGYNCiAgfWVsc2V7DQogICAgaWR4ID0gKGRmJGBLRUdHIFN1YnN5c3RlbWAgPT0gcGF0aHdheSkNCiAgICBpZHhbaXMubmEoaWR4KV0gPSBGQUxTRQ0KICAgIGRhdGEgPSBkZltpZHgsIF0NCiAgfQ0KDQogICMgQ3JlYXRlIG5ldyBkYXRhIGZvciBiYXJwbG90cyBhbmQgZGlzY3JldGUgaGVhdG1hcA0KICBiYXJkYXRhID0gZGF0YVssIDRdDQogIGJhcmRhdGFbaXMubmEoYmFyZGF0YSldID0gMA0KICBleHB0X2RhdGEgPSBkYXRhWywgNV0NCiAgDQogICMgU3BsaXQgYnkgaG91cnMNCiAgZWFybHlfZGF0YSA9IGRhdGFbLCBjKCJHU0UxNzcwOF8xaHJzIiwgIkdhcmNpYV8xaHJzIildIC0gMQ0KICBtaWQxX2RhdGEgID0gZGF0YVssIGMoIkdTRTE3NzA4XzhocnMiLCAiR1NFMTQ3NDA1XzhocnMiKV0gLSAxDQogIG1pZDJfZGF0YSAgPSBkYXRhWywgYygiR1NFMTc3MDhfMjRocnMiLCAiR2FyY2lhXzI0aHJzIiwgIkdTRTE0NzQwNV8yNGhycyIpXSAtIDENCiAgbGF0ZV9kYXRhICA9IGRhdGFbLCBjKCJHU0UxNzcwOF83MmhycyIsICJHU0UxNzUxOF83MmhycyIsICJHYXJjaWFfNDhocnMiLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiS2VzaGFtb3VuaV83MmhycyIsICJHU0UxNDc0MDVfNzJocnMiKV0gLSAxDQogIHRtcCA9IGNiaW5kKGVhcmx5X2RhdGEsIG1pZDFfZGF0YSwgbWlkMl9kYXRhLCBsYXRlX2RhdGEpIC0gMQ0KICANCiAgIyBDcmVhdGUgY29sdW1uIGFubm90YXRpb24gYmFycw0KICBoMV9jb2wgPSBIZWF0bWFwQW5ub3RhdGlvbihoMT1hbm5vX2Jsb2NrKGdwPWdwYXIoZmlsbD0iI0NBQzRDRSIpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxhYmVscz1jKCJFYXJseSIpLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsYWJlbHNfZ3A9Z3Bhcihjb2w9ImJsYWNrIiwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9udHNpemU9MTApKSkNCiAgaDJfY29sID0gSGVhdG1hcEFubm90YXRpb24oaDI9YW5ub19ibG9jayhncD1ncGFyKGZpbGw9IiM4RDg2QzkiKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsYWJlbHM9YygiSW50LiAxIiksIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxhYmVsc19ncD1ncGFyKGNvbD0id2hpdGUiLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmb250c2l6ZT0xMCkpKQ0KICBoM19jb2wgPSBIZWF0bWFwQW5ub3RhdGlvbihoMz1hbm5vX2Jsb2NrKGdwPWdwYXIoZmlsbD0iIzcyNUFDMSIpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxhYmVscz1jKCJJbnQuIDIiKSwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGFiZWxzX2dwPWdwYXIoY29sPSJ3aGl0ZSIsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZvbnRzaXplPTEwKSkpDQogIGg0X2NvbCA9IEhlYXRtYXBBbm5vdGF0aW9uKGg0PWFubm9fYmxvY2soZ3A9Z3BhcihmaWxsPSIjMjQyMDM4IiksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGFiZWxzPWMoIkxhdGUiKSwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGFiZWxzX2dwPWdwYXIoY29sPSJ3aGl0ZSIsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmb250c2l6ZT0xMCkpKQ0KICANCiAgIyBDb25zdHJ1Y3QgZXhwZXJpbWVudCBoZWF0bWFwIGFubm90YXRpb24NCiAgaG0gPSBIZWF0bWFwKGFzLm1hdHJpeChleHB0X2RhdGEpLA0KICAgICAgICAgICAgIGNvbCA9IGNvbG9yUmFtcDIoYygxLCA1KSwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjKCJHcmF5IiwgIiM5NUM2MjMiKSksDQogICAgICAgICAgICAgaGVhdG1hcF9sZWdlbmRfcGFyYW09bGlzdCh0aXRsZT0iRXhwZXJpbWVudHMiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29sb3JfYmFyPSJkaXNjcmV0ZSIpLCANCiAgICAgICAgICAgICByZWN0X2dwID0gZ3Bhcihjb2w9ImJsYWNrIiwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsd2Q9MSksDQogICAgICAgICAgICAgd2lkdGggPSBuY29sKGV4cHRfZGF0YSkqdW5pdCg1LCAibW0iKSwgDQogICAgICAgICAgICAgaGVpZ2h0ID0gbnJvdyhleHB0X2RhdGEpKnVuaXQoNSwgIm1tIikpDQogIA0KICAjIENvbnN0cnVjdCBwcmlvcml0eSBzY29yZSBiYXJwbG90IGFubm90YXRpb24NCiAgYnAgPSByb3dBbm5vdGF0aW9uKA0KICAgIFByaW9yaXR5PWFubm9fYmFycGxvdCgNCiAgICAgIGJhcmRhdGENCiAgICApDQogICkNCiAgDQogICMgQ29uc3RydWN0IHRoZSBoZWF0bWFwcw0KICBjb2xfZnVuID0gY29sb3JSYW1wMihjKG1pbih0bXApLCAwLCBtYXgodG1wKSksIA0KICAgICAgICAgICAgICAgICAgICAgICBjKCIjMDczQjRDIiwgIiNGRkZGRkYiLCAiI0VGNDc2RiIpKQ0KICBoMSA9IEhlYXRtYXAocm93X2xhYmVscz1kYXRhJG5hbWUsDQogICAgICAgICAgICAgICByb3dfbmFtZXNfc2lkZT0ibGVmdCIsDQogICAgICAgICAgICAgICBlYXJseV9kYXRhLCANCiAgICAgICAgICAgICAgIGNvbD1jb2xfZnVuLCANCiAgICAgICAgICAgICAgIGNsdXN0ZXJfY29sdW1ucz1GQUxTRSwgDQogICAgICAgICAgICAgICByZWN0X2dwID0gZ3Bhcihjb2w9ImJsYWNrIiwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsd2Q9MSksDQogICAgICAgICAgICAgICBjbHVzdGVyX3Jvd3M9RkFMU0UsDQogICAgICAgICAgICAgICBzaG93X2hlYXRtYXBfbGVnZW5kPUZBTFNFLA0KICAgICAgICAgICAgICAgYm90dG9tX2Fubm90YXRpb249aDFfY29sLCANCiAgICAgICAgICAgICAgIHdpZHRoID0gbmNvbChlYXJseV9kYXRhKSp1bml0KDUsICJtbSIpLCANCiAgICAgICAgICAgICAgIGhlaWdodCA9IG5yb3coZWFybHlfZGF0YSkqdW5pdCg1LCAibW0iKSkNCiAgaDIgPSBIZWF0bWFwKG1pZDFfZGF0YSwgDQogICAgICAgICAgICAgICBjb2w9Y29sX2Z1biwgDQogICAgICAgICAgICAgICBjbHVzdGVyX2NvbHVtbnM9RkFMU0UsIA0KICAgICAgICAgICAgICAgcmVjdF9ncCA9IGdwYXIoY29sPSJibGFjayIsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbHdkPTEpLA0KICAgICAgICAgICAgICAgY2x1c3Rlcl9yb3dzPUZBTFNFLA0KICAgICAgICAgICAgICAgc2hvd19oZWF0bWFwX2xlZ2VuZD1GQUxTRSwNCiAgICAgICAgICAgICAgIGJvdHRvbV9hbm5vdGF0aW9uPWgyX2NvbCwgDQogICAgICAgICAgICAgICB3aWR0aCA9IG5jb2wobWlkMV9kYXRhKSp1bml0KDUsICJtbSIpLCANCiAgICAgICAgICAgICAgIGhlaWdodCA9IG5yb3cobWlkMV9kYXRhKSp1bml0KDUsICJtbSIpKQ0KICBoMyA9IEhlYXRtYXAobWlkMl9kYXRhLCANCiAgICAgICAgICAgICAgIGNvbD1jb2xfZnVuLCANCiAgICAgICAgICAgICAgIGNsdXN0ZXJfY29sdW1ucz1GQUxTRSwgDQogICAgICAgICAgICAgICByZWN0X2dwID0gZ3Bhcihjb2w9ImJsYWNrIiwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsd2Q9MSksDQogICAgICAgICAgICAgICBjbHVzdGVyX3Jvd3M9RkFMU0UsDQogICAgICAgICAgICAgICBzaG93X2hlYXRtYXBfbGVnZW5kPUZBTFNFLA0KICAgICAgICAgICAgICAgYm90dG9tX2Fubm90YXRpb249aDNfY29sLCANCiAgICAgICAgICAgICAgIHdpZHRoID0gbmNvbChtaWQyX2RhdGEpKnVuaXQoNSwgIm1tIiksIA0KICAgICAgICAgICAgICAgaGVpZ2h0ID0gbnJvdyhtaWQyX2RhdGEpKnVuaXQoNSwgIm1tIikpDQogIGg0ID0gSGVhdG1hcChsYXRlX2RhdGEsIA0KICAgICAgICAgICAgICAgY29sPWNvbF9mdW4sIA0KICAgICAgICAgICAgICAgY2x1c3Rlcl9jb2x1bW5zPUZBTFNFLCANCiAgICAgICAgICAgICAgIHJlY3RfZ3AgPSBncGFyKGNvbD0iYmxhY2siLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGx3ZD0xKSwNCiAgICAgICAgICAgICAgIGNsdXN0ZXJfcm93cz1GQUxTRSwNCiAgICAgICAgICAgICAgIHNob3dfaGVhdG1hcF9sZWdlbmQ9VFJVRSwNCiAgICAgICAgICAgICAgIGJvdHRvbV9hbm5vdGF0aW9uPWg0X2NvbCwNCiAgICAgICAgICAgICAgIHdpZHRoID0gbmNvbChsYXRlX2RhdGEpKnVuaXQoNSwgIm1tIiksIA0KICAgICAgICAgICAgICAgaGVpZ2h0ID0gbnJvdyhsYXRlX2RhdGEpKnVuaXQoNSwgIm1tIiksDQogICAgICAgICAgICAgICBoZWF0bWFwX2xlZ2VuZF9wYXJhbT1saXN0KHRpdGxlPSJOb3JtYWxpemVkIEtPIEdyb3d0aCBTY29yZSIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhdCA9IGMobWluKHRtcCksIDAsIG1heCh0bXApKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxhYmVscyA9IGMoIkRlY3IuIEZpdG5lc3MiLCAiTm8gY2hhbmdlIiwgIkluY3IuIGZpdG5lc3MiKSkpDQogIA0KICAjIFJldHVybiB0aGUgZmluYWwgZmlndXJlDQogIGZpbmFsX2ZpZ3VyZSA9IGgxK2gyK2gzK2g0K2htK2JwDQogIHJldHVybihmaW5hbF9maWd1cmUpDQogICAgDQp9DQpgYGANCg0KIyMjIEIuIFBsb3QgdGhlIHRvcCA1MCByZWFjdGlvbnMgYmFzZWQgb24gcHJpb3JpdHkgc2NvcmUuDQpgYGB7ciwgZmlnLndpZHRoPTIwLCBmaWcuaGVpZ2h0PTEyLjUsIGZpZy5hbGlnbj0ncmlnaHQnLCBkcGk9MTAwfQ0KIyBTb3J0IGRhdGEgYnkgcHJpb3JpdHkgc2NvcmUNCmRhdGEgPSBkYXRhW29yZGVyKGRhdGEkYEFic29sdXRlIEVmZmVjdCAqIE4gZXhwdHNgLCBkZWNyZWFzaW5nPVRSVUUpLCBdDQoNCiMgR3JhYiB0b3AgNTANCnRvcDUwID0gZGF0YVsxOjUwLCBdDQoNCiMgQ3JlYXRlIGZpZ3VyZXMNCnRvcDUwX2ZpZ3VyZXMgPSBrb19oZWF0bWFwKHRvcDUwKQ0KcG5nKGZpbGVuYW1lPSJEOi9BbmFseXNpcy9FTVQvZmlndXJlcy9SRUNPTjFfcnhua29faGVhdG1hcC5wbmciLA0KICAgICAgIHdpZHRoPTIwLA0KICAgICAgIGhlaWdodD0xMi41LA0KICAgICAgIHVuaXRzPSdpbicsDQogICAgcmVzPTEyMDApDQp0b3A1MF9maWd1cmVzDQpkZXYub2ZmDQoNCiMgU2hvdw0KdG9wNTBfZmlndXJlcw0KYGBgDQoNCiMjIyBDLiBHcmFiIGhpZ2ggY29uZmlkZW5jZSByZWFjdGlvbnMgKDIgb3IgbW9yZSBpbiBzYW1lIHNhbXBsZSkNClRoZXJlJ3Mgbm90IHRoYXQgbXVjaCBmb3IgaGlnaCBjb25maWRlbmNlIHJlYWN0aW9ucy4NCg0KYGBge3IsIGZpZy53aWR0aD0yMCwgZmlnLmhlaWdodD0xMi41LCBmaWcuYWxpZ249J3JpZ2h0JywgZHBpPTEwMH0NCiMgU3Vic2V0IFJlYWN0aW9ucw0KcmVhY3Rpb25zX29mX2ludGVyZXN0ID0gYygiYWxwaGEta2V0b2dsdXRhcmF0ZS9tYWxhdGUgdHJhbnNwb3J0ZXIiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAiY2Fybml0aW5lIE8tYWNldHlsdHJhbnNmZXJhc2UiKQ0KaWR4ID0gZGF0YSRgQmlHRyBSZWFjdGlvbiBJRGAgJWluJSByZWFjdGlvbnNfb2ZfaW50ZXJlc3QNCnNwZWNpZmljX2RhdGEgPSBkYXRhW2lkeCwgXQ0KDQojIENyZWF0ZSBmaWd1cmVzDQpzcGVjaWZpY19maWd1cmVzID0ga29faGVhdG1hcChzcGVjaWZpY19kYXRhKQ0KcG5nKGZpbGVuYW1lPSJEOi9BbmFseXNpcy9FTVQvZmlndXJlcy9SRUNPTjFfcnhua29faGlnaF9wcmlvcml0eV9oZWF0bWFwLnBuZyIsDQogICAgICAgd2lkdGg9MjAsDQogICAgICAgaGVpZ2h0PTEyLjUsDQogICAgICAgdW5pdHM9J2luJywNCiAgICByZXM9MTIwMCkNCnNwZWNpZmljX2ZpZ3VyZXMNCmRldi5vZmYoKQ0KDQojIFNob3cNCnNwZWNpZmljX2ZpZ3VyZXMNCg0KDQpgYGANCg0KIyMjIEQuIEdyYWIgbG93IGNvbmZpZGVuY2UgcmVhY3Rpb25zICgxIGluIHNhbWUgc2FtcGxlKQ0KVGhlIGxpc3Qgb2YgbG93IGNvbmZpZGVuY2UgcmVhY3Rpb25zIEknZCBsaWtlIHRvIHZpc3VhbGl6ZSBpcyBoaWdoLg0KDQpgYGB7cn0NCnJlYWN0aW9uc19vZl9pbnRlcmVzdCA9IGMoImVub2xhc2UiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAiZmF0dHktYWN5bC1Db0EgZWxvbmdhdGlvbiAobi1DMjA6NENvQSkiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAiZmF0dHkgYWN5bC1Db0Egc3ludGhhc2UgKG4tQzEwOjBDb0EpIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgImZhdHR5LWFjeWwtQ29BIHN5bnRoYXNlIChuLUMxMjowQ29BKSIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICJmYXR0eS1hY3lsLUNvQSBzeW50aGFzZSAobi1DMTQ6MENvQSkiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAiaHlkcm94eW1ldGh5bGdsdXRhcnlsLUNvQSBseWFzZSIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICJkR1RQIHRyYW5zcG9ydCB2aWEgQVRQIGFudGlwb3J0IiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgIlVEUGdsdWNvc2UgNC1lcGltZXJhc2UiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAiYWRlbm9zaW5lIGtpbmFzZSIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICJwYW50ZXRoZWluZS1waG9zcGhhdGUgYWRlbnlseWx0cmFuc2ZlcmFzZSIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICIgNC1IeWRyb3h5cGhlbnlscHlydXZhdGU6b3h5Z2VuIG94aWRvcmVkdWN0YXNlIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgImZ1bWFyeWxhY2V0b2FjZXRhc2UiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAiSG9tb2dlbnRpc2F0ZTpveHlnZW4gMSwyLW94aWRvcmVkdWN0YXNlIChkZWN5Y2xpemluZykiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAibWFsZXlsYWNldG9hY2V0YXRlIGlzb21lcmFzZSIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICJNYWxhdGU6c3VsZml0ZSBhbnRpcG9ydCwgbWl0b2Nob25kcmlhbCIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICJjaG9uZHJvaXRpbiA2LXN1bGZvdHJhbnNmZXJhc2UsIEdvbGdpIGFwcGFyYXR1cyIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICJuaWNvdGluYXRlLW51Y2xlb3RpZGUgYWRlbnlseWx0cmFuc2ZlcmFzZSIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICJtYWxhdGUgZGVoeWRyb2dlbmFzZSIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICJOb3JlcGluZXBocmluZSB1bmlwb3J0IiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgIkh5ZHJveHltZXRoeWxnbHV0YXJ5bC1Db0EgcmV2ZXJzaWJsZSBtaXRvY2hvbmRyaWFsIHRyYW5zcG9ydCIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICJjYXJuaXRpbmUtYWNldHlsY2Fybml0aW5lIGNhcnJpZXIsIHBlcm94aXNvbWFsIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgImNhcm5pdGluZSBPLWFjZXR5bHRyYW5zZmVyYXNlLCByZXZlcnNlIGRpcmVjdGlvbiwgcGVyb3hpc29tYWwiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAiVURQLUdsY05BYzpiZXRhR2FsIGJldGEtMSwzLU4tYWNldHlsZ2x1Y29zYW1pbnlsdHJhbnNmZXJhc2UgMSIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICJVRFAtR2xjTkFjOmJldGFHYWwgYmV0YS0xLDMtTi1hY2V0eWxnbHVjb3NhbWlueWx0cmFuc2ZlcmFzZSAzLCBHb2xnaSBhcHBhcmF0dXMiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAiSHlkcm94eW1ldGh5bGdsdXRhcnlsIENvQSBzeW50aGFzZSAoaXIpIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgImNpdHJhdGUgdHJhbnNwb3J0LCBtaXRvY2hvbmRyaWFsIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgIkFjb25pdGF0ZSBoeWRyYXRhc2UiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAiQVRQLUNpdHJhdGUgbHlhc2UiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAiZnVtYXJhc2UsIG1pdG9jaG9uZHJpYWwiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAidHJpb3NlLXBob3NwaGF0ZSBpc29tZXJhc2UiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAiYWNldG9uZSBtb25vb3h5Z2VuYXNlIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgImZydWN0b3NlLWJpc3Bob3NwaGF0YXNlIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgIm9ybml0aGluZSB0cmFuc2FtaW5hc2UgcmV2ZXJzaWJsZSAobSkiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAic3VjY2luYXRlIGRlaHlkcm9nZW5hc2UiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAiY2Fybml0aW5lIE8tYWNleWx0cmFuc2ZlcmFzZSwgbWl0b2Nob25kcmlhbCIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICJjaXRyYXRlIHN5bnRoYXNlIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgIklzb2NpdHJhdGUgZGVoeWRyb2dlbmFzZSAoTkFEUCspIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgIkwtbGFjdGF0ZSBkZWh5ZHJvZ2VuYXNlIikNCmBgYA0KDQpTdWJzZXQgYW5kIGNyZWF0ZSB0aGUgcGxvdC4NCmBgYHtyLCBmaWcud2lkdGg9MjAsIGZpZy5oZWlnaHQ9MTIuNSwgZmlnLmFsaWduPSdyaWdodCcsIGRwaT0xMDB9DQppZHggPSBkYXRhJGBCaUdHIFJlYWN0aW9uIElEYCAlaW4lIHJlYWN0aW9uc19vZl9pbnRlcmVzdA0Kc3BlY2lmaWNfZGF0YSA9IGRhdGFbaWR4LCBdDQoNCiMgQ3JlYXRlIGZpZ3VyZXMNCnNwZWNpZmljX2ZpZ3VyZXMgPSBrb19oZWF0bWFwKHNwZWNpZmljX2RhdGEpDQpwbmcoZmlsZW5hbWU9IkQ6L0FuYWx5c2lzL0VNVC9maWd1cmVzL1JFQ09OMV9yeG5rb19sb3dfcHJpb3JpdHlfaGVhdG1hcC5wbmciLA0KICAgICAgIHdpZHRoPTIwLA0KICAgICAgIGhlaWdodD0xMi41LA0KICAgICAgIHVuaXRzPSdpbicsDQogICAgcmVzPTEyMDApDQpzcGVjaWZpY19maWd1cmVzDQpkZXYub2ZmKCkNCmBgYA0KDQojIyAzLiBTaW5nbGUtQ2VsbCBSZWFjdGlvbiBLT3MNCkZpbmFsbHksIGxldCdzIGNyZWF0ZSBhIHZpc3VhbGl6YXRpb24gZm9yIHRoZSBzaW5nbGUtY2VsbCByZWFjdGlvbiBrbm9ja291dHMuDQoNCmBgYHtyfQ0Kcm0obGlzdD1scygpKQ0KYGBgDQoNCiMjIyBBLiBMb2FkIERhdGENCmBgYHtyfQ0KZmlsZW5hbWUgPSAiRDovQW5hbHlzaXMvRU1UL2RhdGEvc2NSTkFTZXEgUmVhY3Rpb24gS08uY3N2Ig0KZGF0YSA9IHJlYWRfY3N2KGZpbGVuYW1lKQ0KDQojIENyZWF0ZSBuZXcgdmFyaWFibGUgZm9yIHJvdyBuYW1lcw0KZGF0YSRuYW1lID0gcGFzdGUwKGRhdGEkYEJpR0cgUmVhY3Rpb24gSURgLCANCiAgICAgICAgICAgICAgICAgICAgJywgJywNCiAgICAgICAgICAgICAgICAgICAgZGF0YSRgS0VHRyBTdWJzeXN0ZW1gKQ0KYGBgDQojIyMgQi4gU3Vic2V0IHRoZSBhdmVyYWdlIGRhdGEgY29sdW1ucw0KVGhlIGRhdGEgaGFzIGFscmVhZHkgYmVlbiBhdmVyYWdlZCBhY3Jvc3MgYWxsIGNlbGxzLg0KYGBge3J9DQp0bXAgPSBkYXRhWywgYygiQXZlcmFnZV9BbGwiLAkiQXZlcmFnZV9EYXkwIiwNCiAgICAgICAgICAgICAgICJBdmVyYWdlX0hvdXI4IiwJIkF2ZXJhZ2VfRGF5MSIsDQogICAgICAgICAgICAgICAiQXZlcmFnZV9EYXkzIiwJIkF2ZXJhZ2VfRGF5NyIpXQ0KdG1wID0gdG1wLTENCmBgYA0KDQojIyMgQy4gQ3JlYXRlIGFuIGFubm90YXRpb24gaGVhdG1hcCBzaG93aW5nIHRoZSBhdmVyYWdlIHN0YW5kYXJkIGRldmlhdGlvbiBmb3IgZWFjaCByZWFjdGlvbiBhY3Jvc3MgYWxsIGNlbGxzDQpgYGB7ciwgZmlnLndpZHRoPTIwLCBmaWcuaGVpZ2h0PTEyLjUsIGZpZy5hbGlnbj0ncmlnaHQnLCBkcGk9MTAwfQ0KaG0gPSBIZWF0bWFwKGFzLm1hdHJpeChkYXRhWywgIlN0ZF9BbGwiXSksDQogICAgICAgICAgICAgcmVjdF9ncCA9IGdwYXIoY29sID0gImJsYWNrIiwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgbHdkID0gMSksDQogICAgICAgICAgICAgY29sID0gY29sb3JSYW1wMihjKDAsIDAuMyksIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYygiI0ZGRkZGRiIsICJvcmFuZ2UiKSksDQogICAgICAgICAgICAgY2x1c3Rlcl9jb2x1bW5zPUZBTFNFLA0KICAgICAgICAgICAgIGNsdXN0ZXJfcm93cz1GQUxTRSwNCiAgICAgICAgICAgICBoZWF0bWFwX2xlZ2VuZF9wYXJhbT1saXN0KHRpdGxlPSJBdmVyYWdlIFN0ZCIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb2xvcl9iYXI9ImNvbnRpbnVvdXMiKSwNCiAgICAgICAgICAgICB3aWR0aCA9IG5jb2woZGF0YVssICJTdGRfQWxsIl0pKnVuaXQoNSwgIm1tIiksIA0KICAgICAgICAgICAgIGhlaWdodCA9IG5yb3coZGF0YVssICJTdGRfQWxsIl0pKnVuaXQoNSwgIm1tIikpDQpgYGANCg0KIyMjIEQuIENyZWF0ZSB0aGUgSGVhdG1hcCB3aXRoIGFkZGl0aW9uYWwgZmlndXJlcw0KYGBge3IsIGZpZy53aWR0aD0yMCwgZmlnLmhlaWdodD0xMi41LCBmaWcuYWxpZ249J3JpZ2h0JywgZHBpPTEwMH0NCmZpbmFsX2RhdGEgPSBhcy5tYXRyaXgodG1wKQ0KaHQgPSBIZWF0bWFwKHJvd19sYWJlbHM9ZGF0YSRuYW1lLA0KICAgICAgICAgICAgIGZpbmFsX2RhdGEsIA0KICAgICAgICAgICAgIHJvd19uYW1lc19zaWRlPSJsZWZ0IiwNCiAgICAgICAgICAgICByZWN0X2dwID0gZ3Bhcihjb2wgPSAiYmxhY2siLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBsd2QgPSAxKSwNCiAgICAgICAgICAgICBjbHVzdGVyX2NvbHVtbnM9RkFMU0UsDQogICAgICAgICAgICAgY2x1c3Rlcl9yb3dzPUZBTFNFLA0KICAgICAgICAgICAgIGNvbCA9IGNvbG9yUmFtcDIoYygtMC41LCAwLCAwLjEpLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGMoImJsdWUiLCAid2hpdGUiLCAicmVkIikpLA0KICAgICAgICAgICAgIGhlYXRtYXBfbGVnZW5kX3BhcmFtPWxpc3QodGl0bGU9Ik5vcm1hbGl6ZWQgS08gR3Jvd3RoIFNjb3JlIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGF0ID0gYygtMC42LCAwLCAwLjIpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGFiZWxzID0gYygiRGVjci4gRml0bmVzcyIsICJObyBjaGFuZ2UiLCAiSW5jci4gZml0bmVzcyIpKSwNCiAgICAgICAgICAgICB3aWR0aCA9IG5jb2woZmluYWxfZGF0YSkqdW5pdCg1LCAibW0iKSwgDQogICAgICAgICAgICAgaGVpZ2h0ID0gbnJvdyhmaW5hbF9kYXRhKSp1bml0KDUsICJtbSIpKSArDQogICAgIGhtIA0KDQpodA0KYGBgDQoNCmBgYHtyfQ0KcG5nKGZpbGVuYW1lPSJEOi9BbmFseXNpcy9FTVQvZmlndXJlcy9zY1JOQVNlcV9hdmdfcnhuX2tvLnBuZyIsDQogICAgICAgd2lkdGg9Ny41LA0KICAgICAgIGhlaWdodD0xMCwNCiAgICAgICB1bml0cz0naW4nLA0KICAgIHJlcz0xMjAwKQ0KaHQNCmRldi5vZmYoKQ0KYGBgDQoNCiMjIENvbmNsdXNpb24=
+
LS0tDQp0aXRsZTogIkVNVCBNYW51c2NyaXB0IEZpZ3VyZXMiDQpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sNCmF1dGhvcjogIlNjb3R0Ig0KLS0tDQoNCiMjIFN1bW1hcnkNClRoaXMgbm90ZWJvb2sgbWFrZXMgc2V2ZXJhbCBmaWd1cmVzIGZvciB0aGUgQ09CUkEgRU1UIHB1YmxpY2F0aW9uLg0KDQpgYGB7cn0NCnJtKGxpc3Q9bHMoKSkNCmBgYA0KDQojIyBMb2FkIExpYnJhcmllcw0KTGV0J3MgbG9hZCBzb21lIHBsb3R0aW5nIGxpYnJhcmllcy4NCg0KYGBge3J9DQpsaWJyYXJ5KHRpZHl2ZXJzZSkNCmxpYnJhcnkoZ2dwbG90MikNCmxpYnJhcnkocmVzaGFwZTIpDQpsaWJyYXJ5KGV4dHJhZm9udCkNCmxpYnJhcnkoQ29tcGxleEhlYXRtYXApDQpsaWJyYXJ5KGNpcmNsaXplKQ0KI2ZvbnRfaW1wb3J0KCkNCiNsb2FkZm9udHMoZGV2aWNlID0gIndpbiIpDQpgYGANCg0KIyMgMS4gVmlzdWFsaXplIEJ1bGsgRmx1eGVzDQoNCiMjIyBBLiBMb2FkIERhdGENCkZpcnN0LCBsZXQncyBsb2FkIHRoZSBkYXRhDQpgYGB7cn0NCmZpbGVuYW1lID0gIkQ6L0FuYWx5c2lzL0VNVC9kYXRhL0J1bGsgRmx1eCBJbnRlcnNlY3Rpb24uY3N2Ig0KZGF0YSA9IHJlYWRfY3N2KGZpbGVuYW1lKQ0KYGBgDQoNCiMjIyBCLiBWaXN1YWxpemUgdGhlIHRvcCA1MCByZWFjdGlvbiBrbm9ja291dHMgZnJvbSBidWxrL2FnZ3JlZ2dhdGVkIHN0dWRpZXMNCkhlcmUncyBhIGRlc2NyaXB0aW9uIG9mIGVhY2ggdmFyaWFibGUgY3JlYXRlZDoNCiAgKiBgdG9wNTBgOiBUb3AgNTAgcmVhY3Rpb25zIHJhbmtlZCBieSBwcmlvcml0eSBzY29yZQ0KICAqIGBiYXJkYXRhYDogZGF0YSB1c2VkIGluIEJhciBQbG90DQogICogYGV4cHRfZGF0YWA6IGRhdGEgdXNlZCBpbiBkaXNjcmV0ZSBoZWF0bWFwDQogIA0KYGBge3J9DQojIFNvcnQgZGF0YSBieSBwcmlvcml0eSBzY29yZQ0KZGF0YSA9IGRhdGFbb3JkZXIoZGF0YSRgQWJzb2x1dGUgRWZmZWN0ICogTiBleHB0c2AsIGRlY3JlYXNpbmc9VFJVRSksIF0NCg0KIyBDcmVhdGUgbmV3IHZhcmlhYmxlIGZvciByb3cgbmFtZXMNCmRhdGEkbmFtZSA9IHBhc3RlMChkYXRhJGBCaUdHIFJlYWN0aW9uIElEYCwgDQogICAgICAgICAgICAgICAgICAgICcsICcsDQogICAgICAgICAgICAgICAgICAgIGRhdGEkYEtFR0cgU3Vic3lzdGVtYCkNCg0KIyBHcmFiIHRvcCA1MA0KdG9wNTAgPSBkYXRhWzE6NTAsIF0NCg0KIyBDcmVhdGUgbmV3IGRhdGEgZm9yIGJhcnBsb3RzIGFuZCBkaXNjcmV0ZSBoZWF0bWFwDQpiYXJkYXRhID0gdG9wNTBbLCA0XQ0KZXhwdF9kYXRhID0gdG9wNTBbLCA1XQ0KYGBgDQoNCiMjIyMgaS4gUmVmb3JtYXQgdGhlIGRhdGENCldlJ3JlIGdvaW5nIHRvIGdyYWIgc2VsZWN0ZWQgdGltZSBwb2ludHMgdGhhdCBoYXZlIHJlcGxpY2F0ZSB2YWx1ZXMgYWNyb3NzIG11bHRpcGxlIHN0dWRpZXMgYW5kIHRlbGwgdGhlIEVNVCBzdG9yeS4gVGhlIHNlbGVjdGVkIHRpbWUgcG9pbnRzIHdpbGwgYmUgc3RvcmVkIDQgc2VwYXJhdGUgZGF0YWZyYW1lcyBjb3JyZXNwb25kaW5nIHRvIGVhY2ggdGltZSBwb2ludC4NCg0KYGBge3J9DQojIFNwbGl0IGJ5IGhvdXJzDQplYXJseV9kYXRhID0gYWJzKHRvcDUwWywgYygiR1NFMTc3MDhfMWhycyIsICJHYXJjaWFfMWhycyIpXSkNCm1pZDFfZGF0YSAgPSBhYnModG9wNTBbLCBjKCJHU0UxNzcwOF84aHJzIiwgIkdTRTE0NzQwNV84aHJzIildKQ0KbWlkMl9kYXRhICA9IGFicyh0b3A1MFssIGMoIkdTRTE3NzA4XzI0aHJzIiwgIkdhcmNpYV8yNGhycyIsICJHU0UxNDc0MDVfMjRocnMiKV0pDQpsYXRlX2RhdGEgID0gYWJzKHRvcDUwWywgYygiR1NFMTc3MDhfNzJocnMiLCAiR1NFMTc1MThfNzJocnMiLCAiR2FyY2lhXzQ4aHJzIiwgDQogICAgICAgICAgICAgICAgICAgICAgICJLZXNoYW1vdW5pXzcyaHJzIiwgIkdTRTE0NzQwNV83MmhycyIpXSkNCmBgYA0KDQojIyMjIGlpLiBDcmVhdGUgdGhlIGNvbHVtbiBhbm5vdGF0aW9uIGhlYXRtYXAgZm9yIGVhY2ggdGltZS1wb2ludA0KVGhpcyBjcmVhdGVzIGluZGl2aWR1YWwgYW5ub3RhdGlvbiBiYXJzIGZvciBlYWNoIG9mIHRoZSBjb3JyZXNwb25kaW5nIHRpbWUgcG9pbnRzLg0KDQpgYGB7cn0NCmgxX2NvbCA9IEhlYXRtYXBBbm5vdGF0aW9uKGgxPWFubm9fYmxvY2soZ3A9Z3BhcihmaWxsPSIjQ0FDNENFIiksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxhYmVscz1jKCJFYXJseSIpLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGFiZWxzX2dwPWdwYXIoY29sPSJibGFjayIsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmb250c2l6ZT0xMCkpKQ0KaDJfY29sID0gSGVhdG1hcEFubm90YXRpb24oaDI9YW5ub19ibG9jayhncD1ncGFyKGZpbGw9IiM4RDg2QzkiKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGFiZWxzPWMoIkludC4gMSIpLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGFiZWxzX2dwPWdwYXIoY29sPSJ3aGl0ZSIsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmb250c2l6ZT0xMCkpKQ0KaDNfY29sID0gSGVhdG1hcEFubm90YXRpb24oaDM9YW5ub19ibG9jayhncD1ncGFyKGZpbGw9IiM3MjVBQzEiKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGFiZWxzPWMoIkludC4gMiIpLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGFiZWxzX2dwPWdwYXIoY29sPSJ3aGl0ZSIsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmb250c2l6ZT0xMCkpKQ0KaDRfY29sID0gSGVhdG1hcEFubm90YXRpb24oaDQ9YW5ub19ibG9jayhncD1ncGFyKGZpbGw9IiMyNDIwMzgiKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGFiZWxzPWMoIkxhdGUiKSwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxhYmVsc19ncD1ncGFyKGNvbD0id2hpdGUiLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9udHNpemU9MTApKSkNCmBgYA0KDQojIyMjIGlpaS4gQ3JlYXRlIHRoZSBiYXJwbG90IHRoYXQgc2hvd3MgdGhlIHByaW9yaXR5IHNjb3JlDQpUaGUgYW5ub3RhdGlvbiBiYXJwbG90IHdpbGwgc2hvdyB0aGUgcHJpb3JpdHkgc2NvcmVzIG9uIHRoZSByaWdodGhhbmQgc2lkZS4NCg0KYGBge3J9DQpicCA9IHJvd0Fubm90YXRpb24oDQogIFByaW9yaXR5PWFubm9fYmFycGxvdCgNCiAgICBiYXJkYXRhDQogICkNCikNCmBgYA0KDQojIyMjIGl2LiBDcmVhdGUgYSBoZWF0bWFwIHNob3dpbmcgdGhlIG51bWJlciBvZiBleHBlcmltZW50cyBmb3IgZWFjaCByZWFjdGlvbg0KV2UnbGwgYWxzbyBjcmVhdGUgYW4gYW5ub3RhdGlvbiBoZWF0bWFwIGNvcnJlc3BvbmRpbmcgdG8gdGhlIG51bWJlciBvZiBleHBlcmltZW50cyBmb3IgZWFjaCByZWFjdGlvbi4NCg0KYGBge3IsIGZpZy53aWR0aD0xMCwgZmlnLmhlaWdodD03LjV9DQpobSA9IEhlYXRtYXAoYXMubWF0cml4KGV4cHRfZGF0YSksDQogICAgICAgICAgICAgY29sID0gY29sb3JSYW1wMihjKDEsNSksIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYygiR3JheSIsICIjOTVDNjIzIikpLA0KICAgICAgICAgICAgIGhlYXRtYXBfbGVnZW5kX3BhcmFtPWxpc3QodGl0bGU9IkV4cGVyaW1lbnRzIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbG9yX2Jhcj0iZGlzY3JldGUiKSwNCiAgICAgICAgICAgICByZWN0X2dwID0gZ3Bhcihjb2w9ImJsYWNrIiwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsd2Q9MSksDQogICAgICAgICAgICAgd2lkdGggPSBuY29sKGV4cHRfZGF0YSkqdW5pdCg1LCAibW0iKSwgDQogICAgICAgICAgICAgaGVpZ2h0ID0gbnJvdyhleHB0X2RhdGEpKnVuaXQoNSwgIm1tIikpDQpgYGANCg0KIyMjIyB2LiBDcmVhdGUgdGhlIGZpZ3VyZQ0KRmluYWxseSwgd2UnbGwgY3JlYXRlIHRoZSBlbnRpcmUgZmlndXJlLg0KDQpgYGB7ciwgZmlnLndpZHRoPTIwLCBmaWcuaGVpZ2h0PTEyLjUsIGZpZy5hbGlnbj0ncmlnaHQnLCBkcGk9MTAwfQ0KY29sX2Z1biA9IGNvbG9yUmFtcDIoYygwLCA1LCAyMCksIA0KICAgICAgICAgICAgICAgICAgICAgYygiR3JheSIsICIjRkQ3NDcwIiwgIiNEQzFDMTMiKSkNCmgxID0gSGVhdG1hcChyb3dfbGFiZWxzPXRvcDUwJG5hbWUsDQogICAgICAgICAgICAgcm93X25hbWVzX3NpZGU9ImxlZnQiLA0KICAgICAgICAgICAgIGVhcmx5X2RhdGEsIA0KICAgICAgICAgICAgIGNvbD1jb2xfZnVuLCANCiAgICAgICAgICAgICBjbHVzdGVyX2NvbHVtbnM9RkFMU0UsIA0KICAgICAgICAgICAgICAgcmVjdF9ncCA9IGdwYXIoY29sPSJibGFjayIsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbHdkPTEpLA0KICAgICAgICAgICAgIGNsdXN0ZXJfcm93cz1GQUxTRSwNCiAgICAgICAgICAgICBzaG93X2hlYXRtYXBfbGVnZW5kPUZBTFNFLA0KICAgICAgICAgICAgIGJvdHRvbV9hbm5vdGF0aW9uPWgxX2NvbCwgDQogICAgICAgICAgICAgd2lkdGggPSBuY29sKGVhcmx5X2RhdGEpKnVuaXQoNSwgIm1tIiksIA0KICAgICAgICAgICAgIGhlaWdodCA9IG5yb3coZWFybHlfZGF0YSkqdW5pdCg1LCAibW0iKSkNCmgyID0gSGVhdG1hcChtaWQxX2RhdGEsIA0KICAgICAgICAgICAgIGNvbD1jb2xfZnVuLCANCiAgICAgICAgICAgICBjbHVzdGVyX2NvbHVtbnM9RkFMU0UsIA0KICAgICAgICAgICAgICAgcmVjdF9ncCA9IGdwYXIoY29sPSJibGFjayIsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbHdkPTEpLA0KICAgICAgICAgICAgIGNsdXN0ZXJfcm93cz1GQUxTRSwNCiAgICAgICAgICAgICBzaG93X2hlYXRtYXBfbGVnZW5kPUZBTFNFLA0KICAgICAgICAgICAgIGJvdHRvbV9hbm5vdGF0aW9uPWgyX2NvbCwgDQogICAgICAgICAgICAgd2lkdGggPSBuY29sKG1pZDFfZGF0YSkqdW5pdCg1LCAibW0iKSwgDQogICAgICAgICAgICAgaGVpZ2h0ID0gbnJvdyhtaWQxX2RhdGEpKnVuaXQoNSwgIm1tIikpDQpoMyA9IEhlYXRtYXAobWlkMl9kYXRhLCANCiAgICAgICAgICAgICBjb2w9Y29sX2Z1biwgDQogICAgICAgICAgICAgY2x1c3Rlcl9jb2x1bW5zPUZBTFNFLCANCiAgICAgICAgICAgICAgIHJlY3RfZ3AgPSBncGFyKGNvbD0iYmxhY2siLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGx3ZD0xKSwNCiAgICAgICAgICAgICANCiAgICAgICAgICAgICBjbHVzdGVyX3Jvd3M9RkFMU0UsDQogICAgICAgICAgICAgc2hvd19oZWF0bWFwX2xlZ2VuZD1GQUxTRSwNCiAgICAgICAgICAgICBib3R0b21fYW5ub3RhdGlvbj1oM19jb2wsIA0KICAgICAgICAgICAgIHdpZHRoID0gbmNvbChtaWQyX2RhdGEpKnVuaXQoNSwgIm1tIiksIA0KICAgICAgICAgICAgIGhlaWdodCA9IG5yb3cobWlkMl9kYXRhKSp1bml0KDUsICJtbSIpKQ0KaDQgPSBIZWF0bWFwKGxhdGVfZGF0YSwgDQogICAgICAgICAgICAgY29sPWNvbF9mdW4sIA0KICAgICAgICAgICAgIGNsdXN0ZXJfY29sdW1ucz1GQUxTRSwgDQogICAgICAgICAgICAgICByZWN0X2dwID0gZ3Bhcihjb2w9ImJsYWNrIiwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsd2Q9MSksDQogICAgICAgICAgICAgY2x1c3Rlcl9yb3dzPUZBTFNFLA0KICAgICAgICAgICAgIHNob3dfaGVhdG1hcF9sZWdlbmQ9VFJVRSwNCiAgICAgICAgICAgICBib3R0b21fYW5ub3RhdGlvbj1oNF9jb2wsDQogICAgICAgICAgICAgd2lkdGggPSBuY29sKGxhdGVfZGF0YSkqdW5pdCg1LCAibW0iKSwgDQogICAgICAgICAgICAgaGVpZ2h0ID0gbnJvdyhsYXRlX2RhdGEpKnVuaXQoNSwgIm1tIiksDQogICAgICAgICAgICAgaGVhdG1hcF9sZWdlbmRfcGFyYW09bGlzdCh0aXRsZT0iQWJzb2x1dGUgRmx1eCIpKQ0KDQpmaW5hbF9maWd1cmUgPSBoMStoMitoMytoNCtobSticA0KZmluYWxfZmlndXJlDQpgYGANCg0KIyMjIyB2aS4gU2F2ZSB0aGUgZmlndXJlDQpGaW5hbGx5LCB3ZSdsbCBzYXZlIHRoZSBlbnRpcmUgZmlndXJlIHdpdGggaGlnaCByZXNvbHV0aW9uLg0KDQpgYGB7ciwgZmlnLndpZHRoPTIwLCBmaWcuaGVpZ2h0PTEyLjUsIGZpZy5hbGlnbj0ncmlnaHQnLCBkcGk9MTAwfQ0KcG5nKGZpbGVuYW1lPSJEOi9BbmFseXNpcy9FTVQvZmlndXJlcy9SRUNPTjFfZmx1eF9oZWF0bWFwLnBuZyIsDQogICAgICAgd2lkdGg9MjAsDQogICAgICAgaGVpZ2h0PTEyLjUsDQogICAgICAgdW5pdHM9J2luJywNCiAgICByZXM9MTIwMCkNCmZpbmFsX2ZpZ3VyZQ0KZGV2Lm9mZigpDQpgYGANCiMjIyMgdmlpLiBDcmVhdGUgdGhlIGFjY2Vzc29yeSBmdW5jdGlvbg0KVGhpcyBhY2Nlc3NvcnkgZnVuY3Rpb24gYGZsdXhfaGVhdG1hcGAgd2lsbCBjcmVhdGUgYSBoZWF0bWFwIGZvciBzcGVjaWZpYyBtZXRhYm9saWMgcGF0aHdheXMgdXNpbmcgdGhlIGBkYXRhYCB2YXJpYWJsZSBjb25zdHJ1Y3RlZCBpbiB0aGUgcHJldmlvdXMgY29kZSBibG9ja3MuIFlvdSBjYW4gYWxzbyBzdWJzZXQgYSBkYXRhIGZyYW1lIG1hbnVhbGx5IGFuZCB2aXN1YWxpemUgaXQgdGhhdCB3YXkuDQoNCmBgYHtyLCBmaWcud2lkdGg9MjAsIGZpZy5oZWlnaHQ9MTIuNSwgZmlnLmFsaWduPSdyaWdodCcsIGRwaT0xMDB9DQpmbHV4X2hlYXRtYXAgPSBmdW5jdGlvbihkZiwgcGF0aHdheSl7DQogIA0KICAjIElmIHBhdGh3YXkgdmFyaWFibGUgaXMgbWlzc2luZywganVzdCB2aXN1YWxpemUgZXZlcnl0aGluZw0KICBpZihtaXNzaW5nKHBhdGh3YXkpKXsNCiAgICBkYXRhID0gZGYNCiAgfWVsc2V7DQogICAgaWR4ID0gKGRmJGBLRUdHIFN1YnN5c3RlbWAgPT0gcGF0aHdheSkNCiAgICBpZHhbaXMubmEoaWR4KV0gPSBGQUxTRQ0KICAgIGRhdGEgPSBkZltpZHgsIF0NCiAgfQ0KDQogICMgQ3JlYXRlIG5ldyBkYXRhIGZvciBiYXJwbG90cyBhbmQgZGlzY3JldGUgaGVhdG1hcA0KICBiYXJkYXRhID0gZGF0YVssIDRdDQogIGJhcmRhdGFbaXMubmEoYmFyZGF0YSldID0gMA0KICBleHB0X2RhdGEgPSBkYXRhWywgNV0NCiAgDQogICMgU3BsaXQgYnkgaG91cnMNCiAgZWFybHlfZGF0YSA9IGFicyhkYXRhWywgYygiR1NFMTc3MDhfMWhycyIsICJHYXJjaWFfMWhycyIpXSkNCiAgbWlkMV9kYXRhICA9IGFicyhkYXRhWywgYygiR1NFMTc3MDhfOGhycyIsICJHU0UxNDc0MDVfOGhycyIpXSkNCiAgbWlkMl9kYXRhICA9IGFicyhkYXRhWywgYygiR1NFMTc3MDhfMjRocnMiLCAiR2FyY2lhXzI0aHJzIiwgIkdTRTE0NzQwNV8yNGhycyIpXSkNCiAgbGF0ZV9kYXRhICA9IGFicyhkYXRhWywgYygiR1NFMTc3MDhfNzJocnMiLCAiR1NFMTc1MThfNzJocnMiLCAiR2FyY2lhXzQ4aHJzIiwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIktlc2hhbW91bmlfNzJocnMiLCAiR1NFMTQ3NDA1XzcyaHJzIildKQ0KICB0bXAgPSBjYmluZChlYXJseV9kYXRhLCBtaWQxX2RhdGEsIG1pZDJfZGF0YSwgbGF0ZV9kYXRhKQ0KICANCiAgIyBDcmVhdGUgY29sdW1uIGFubm90YXRpb24gYmFycw0KICBoMV9jb2wgPSBIZWF0bWFwQW5ub3RhdGlvbihoMT1hbm5vX2Jsb2NrKGdwPWdwYXIoZmlsbD0iI0NBQzRDRSIpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxhYmVscz1jKCJFYXJseSIpLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsYWJlbHNfZ3A9Z3Bhcihjb2w9ImJsYWNrIiwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9udHNpemU9MTApKSkNCiAgaDJfY29sID0gSGVhdG1hcEFubm90YXRpb24oaDI9YW5ub19ibG9jayhncD1ncGFyKGZpbGw9IiM4RDg2QzkiKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsYWJlbHM9YygiSW50LiAxIiksIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxhYmVsc19ncD1ncGFyKGNvbD0id2hpdGUiLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmb250c2l6ZT0xMCkpKQ0KICBoM19jb2wgPSBIZWF0bWFwQW5ub3RhdGlvbihoMz1hbm5vX2Jsb2NrKGdwPWdwYXIoZmlsbD0iIzcyNUFDMSIpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxhYmVscz1jKCJJbnQuIDIiKSwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGFiZWxzX2dwPWdwYXIoY29sPSJ3aGl0ZSIsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZvbnRzaXplPTEwKSkpDQogIGg0X2NvbCA9IEhlYXRtYXBBbm5vdGF0aW9uKGg0PWFubm9fYmxvY2soZ3A9Z3BhcihmaWxsPSIjMjQyMDM4IiksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGFiZWxzPWMoIkxhdGUiKSwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGFiZWxzX2dwPWdwYXIoY29sPSJ3aGl0ZSIsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmb250c2l6ZT0xMCkpKQ0KICANCiAgIyBDb25zdHJ1Y3QgZXhwZXJpbWVudCBoZWF0bWFwIGFubm90YXRpb24NCiAgaG0gPSBIZWF0bWFwKGFzLm1hdHJpeChleHB0X2RhdGEpLA0KICAgICAgICAgICAgIGNvbCA9IGNvbG9yUmFtcDIoYygxLDUpLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGMoIkdyYXkiLCAiIzk1QzYyMyIpKSwNCiAgICAgICAgICAgICBoZWF0bWFwX2xlZ2VuZF9wYXJhbT1saXN0KHRpdGxlPSJFeHBlcmltZW50cyIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb2xvcl9iYXI9ImRpc2NyZXRlIiksIA0KICAgICAgICAgICAgIHdpZHRoID0gbmNvbChleHB0X2RhdGEpKnVuaXQoNSwgIm1tIiksIA0KICAgICAgICAgICAgIGhlaWdodCA9IG5yb3coZXhwdF9kYXRhKSp1bml0KDUsICJtbSIpKQ0KICANCiAgIyBDb25zdHJ1Y3QgcHJpb3JpdHkgc2NvcmUgYmFycGxvdCBhbm5vdGF0aW9uDQogIGJwID0gcm93QW5ub3RhdGlvbigNCiAgICBQcmlvcml0eT1hbm5vX2JhcnBsb3QoDQogICAgICBiYXJkYXRhDQogICAgKQ0KICApDQogIA0KICAjIENvbnN0cnVjdCB0aGUgaGVhdG1hcHMNCiAgY29sX2Z1biA9IGNvbG9yUmFtcDIoYygwLCANCiAgICAgICAgICAgICAgICAgICAgICAgICBtZWRpYW4oYXMubWF0cml4KHRtcCksIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBuYS5ybT1UUlVFKSwgDQogICAgICAgICAgICAgICAgICAgICAgICAgbWF4KGFzLm1hdHJpeCh0bXApLCBuYS5ybT1UUlVFKSksIA0KICAgICAgICAgICAgICAgICAgICAgICBjKCJHcmF5IiwgIiNGRDc0NzAiLCAiI0RDMUMxMyIpKQ0KICBoMSA9IEhlYXRtYXAocm93X2xhYmVscz1kYXRhJG5hbWUsDQogICAgICAgICAgICAgICByb3dfbmFtZXNfc2lkZT0ibGVmdCIsDQogICAgICAgICAgICAgICBlYXJseV9kYXRhLCANCiAgICAgICAgICAgICAgIGNvbD1jb2xfZnVuLCANCiAgICAgICAgICAgICAgIGNsdXN0ZXJfY29sdW1ucz1GQUxTRSwgDQogICAgICAgICAgICAgICByZWN0X2dwID0gZ3Bhcihjb2w9ImJsYWNrIiwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsd2Q9MSksDQogICAgICAgICAgICAgICBjbHVzdGVyX3Jvd3M9RkFMU0UsDQogICAgICAgICAgICAgICBzaG93X2hlYXRtYXBfbGVnZW5kPUZBTFNFLA0KICAgICAgICAgICAgICAgYm90dG9tX2Fubm90YXRpb249aDFfY29sLCANCiAgICAgICAgICAgICAgIHdpZHRoID0gbmNvbChlYXJseV9kYXRhKSp1bml0KDUsICJtbSIpLCANCiAgICAgICAgICAgICAgIGhlaWdodCA9IG5yb3coZWFybHlfZGF0YSkqdW5pdCg1LCAibW0iKSkNCiAgaDIgPSBIZWF0bWFwKG1pZDFfZGF0YSwgDQogICAgICAgICAgICAgICBjb2w9Y29sX2Z1biwgDQogICAgICAgICAgICAgICBjbHVzdGVyX2NvbHVtbnM9RkFMU0UsIA0KICAgICAgICAgICAgICAgcmVjdF9ncCA9IGdwYXIoY29sPSJibGFjayIsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbHdkPTEpLA0KICAgICAgICAgICAgICAgY2x1c3Rlcl9yb3dzPUZBTFNFLA0KICAgICAgICAgICAgICAgc2hvd19oZWF0bWFwX2xlZ2VuZD1GQUxTRSwNCiAgICAgICAgICAgICAgIGJvdHRvbV9hbm5vdGF0aW9uPWgyX2NvbCwgDQogICAgICAgICAgICAgICB3aWR0aCA9IG5jb2wobWlkMV9kYXRhKSp1bml0KDUsICJtbSIpLCANCiAgICAgICAgICAgICAgIGhlaWdodCA9IG5yb3cobWlkMV9kYXRhKSp1bml0KDUsICJtbSIpKQ0KICBoMyA9IEhlYXRtYXAobWlkMl9kYXRhLCANCiAgICAgICAgICAgICAgIGNvbD1jb2xfZnVuLCANCiAgICAgICAgICAgICAgIGNsdXN0ZXJfY29sdW1ucz1GQUxTRSwgDQogICAgICAgICAgICAgICByZWN0X2dwID0gZ3Bhcihjb2w9ImJsYWNrIiwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsd2Q9MSksDQogICAgICAgICAgICAgICBjbHVzdGVyX3Jvd3M9RkFMU0UsDQogICAgICAgICAgICAgICBzaG93X2hlYXRtYXBfbGVnZW5kPUZBTFNFLA0KICAgICAgICAgICAgICAgYm90dG9tX2Fubm90YXRpb249aDNfY29sLCANCiAgICAgICAgICAgICAgIHdpZHRoID0gbmNvbChtaWQyX2RhdGEpKnVuaXQoNSwgIm1tIiksIA0KICAgICAgICAgICAgICAgaGVpZ2h0ID0gbnJvdyhtaWQyX2RhdGEpKnVuaXQoNSwgIm1tIikpDQogIGg0ID0gSGVhdG1hcChsYXRlX2RhdGEsIA0KICAgICAgICAgICAgICAgY29sPWNvbF9mdW4sIA0KICAgICAgICAgICAgICAgY2x1c3Rlcl9jb2x1bW5zPUZBTFNFLCANCiAgICAgICAgICAgICAgIHJlY3RfZ3AgPSBncGFyKGNvbD0iYmxhY2siLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGx3ZD0xKSwNCiAgICAgICAgICAgICAgIGNsdXN0ZXJfcm93cz1GQUxTRSwNCiAgICAgICAgICAgICAgIHNob3dfaGVhdG1hcF9sZWdlbmQ9VFJVRSwNCiAgICAgICAgICAgICAgIGJvdHRvbV9hbm5vdGF0aW9uPWg0X2NvbCwNCiAgICAgICAgICAgICAgIHdpZHRoID0gbmNvbChsYXRlX2RhdGEpKnVuaXQoNSwgIm1tIiksIA0KICAgICAgICAgICAgICAgaGVpZ2h0ID0gbnJvdyhsYXRlX2RhdGEpKnVuaXQoNSwgIm1tIiksDQogICAgICAgICAgICAgICBoZWF0bWFwX2xlZ2VuZF9wYXJhbT1saXN0KHRpdGxlPSJBYnNvbHV0ZSBmbHV4IChnRFcvbW1vbCpocikiKSkNCiAgDQogICMgUmV0dXJuIHRoZSBmaW5hbCBmaWd1cmUNCiAgZmluYWxfZmlndXJlID0gaDEraDIraDMraDQraG0rYnANCiAgcmV0dXJuKGZpbmFsX2ZpZ3VyZSkNCiAgICANCn0NCmBgYA0KDQojIyMgQy4gVmlzdWFsaXplIEdseWNvbHl0aWMgUmVhY3Rpb25zDQpOb3cgbGV0J3Mgc3BlY2lmaWNhbGx5IGdldCByZWFjdGlvbnMgcmVsYXRlZCB0byBHbHljb2x5c2lzLg0KYGBge3IsIGZpZy53aWR0aD0yMCwgZmlnLmhlaWdodD0xMi41LCBmaWcuYWxpZ249J3JpZ2h0JywgZHBpPTEwMH0NCmdseWNvbHlzaXNfZmlndXJlcyA9IGZsdXhfaGVhdG1hcChkYXRhLCBwYXRod2F5PSJHbHljb2x5c2lzL0dsdWNvbmVvZ2VuZXNpcyIpDQpwbmcoZmlsZW5hbWU9IkQ6L0FuYWx5c2lzL0VNVC9maWd1cmVzL2dseWNvbHlzaXNfZmx1eF9oZWF0bWFwLnBuZyIsDQogICAgICAgd2lkdGg9MjAsDQogICAgICAgaGVpZ2h0PTEyLjUsDQogICAgICAgdW5pdHM9J2luJywNCiAgICByZXM9MTIwMCkNCmdseWNvbHlzaXNfZmlndXJlcw0KZGV2Lm9mZigpDQpgYGANCg0KIyMjIEQuIFZpc3VhbGl6ZSBQZW50b3NlIFBob3NwaGF0ZSBQYXRod2F5IFJlYWN0aW9ucw0KYGBge3IsIGZpZy53aWR0aD0yMCwgZmlnLmhlaWdodD0xMi41LCBmaWcuYWxpZ249J3JpZ2h0JywgZHBpPTEwMH0NCnBwcF9maWd1cmVzID0gZmx1eF9oZWF0bWFwKGRhdGEsIHBhdGh3YXk9IlBlbnRvc2UgUGhvc3BoYXRlIFBhdGh3YXkiKQ0KcG5nKGZpbGVuYW1lPSJEOi9BbmFseXNpcy9FTVQvZmlndXJlcy9wcHBfZmx1eF9oZWF0bWFwLnBuZyIsDQogICAgICAgd2lkdGg9MjAsDQogICAgICAgaGVpZ2h0PTEyLjUsDQogICAgICAgdW5pdHM9J2luJywNCiAgICByZXM9MTIwMCkNCnBwcF9maWd1cmVzDQpkZXYub2ZmKCkNCmBgYA0KDQoNCiMjIyBFLiBWaXN1YWxpemUgU3BlY2lmaWMgUmVhY3Rpb25zDQpOb3cgbGV0J3Mgc3BlY2lmaWNhbGx5IGdldCByZWFjdGlvbnMgdGhhdCBhcmUgdW5pcXVlIHRvIGVhY2ggc3RhdGUuDQpgYGB7ciwgZmlnLndpZHRoPTIwLCBmaWcuaGVpZ2h0PTEyLjUsIGZpZy5hbGlnbj0ncmlnaHQnLCBkcGk9MTAwfQ0KIyBNYW51YWxseSBzdWJzZXQgcmVhY3Rpb25zDQpyZWFjdGlvbnNfb2ZfaW50ZXJlc3QgPSBjKCJyaWJ1bG9zZSA1LXBob3NwaGF0ZSAzLWVwaW1lcmFzZSIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICJCaW90aW4gdHJhbnNwb3J0IHZpYSBzb2RpdW0gc3ltcG9ydCIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICJCaW90aW4gcmV2ZXJzaWJsZSB0cmFuc3BvcnQgdmlhIHByb3RvbiBzeW1wb3J0IiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgIk5BREggZGVoeWRyb2dlbmFzZSwgbWl0b2Nob25kcmlhbCIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICJMLWxhY3RhdGUgZGVoeWRyb2dlbmFzZSIpDQppZHggPSBkYXRhJGBCaUdHIFJlYWN0aW9uIElEYCAlaW4lIHJlYWN0aW9uc19vZl9pbnRlcmVzdA0Kc3BlY2lmaWNfZGF0YSA9IGRhdGFbaWR4LCBdDQoNCiMgQ3JlYXRlIGZpZ3VyZXMNCnNwZWNpZmljX2ZpZ3VyZXMgPSBmbHV4X2hlYXRtYXAoc3BlY2lmaWNfZGF0YSkNCnBuZyhmaWxlbmFtZT0iRDovQW5hbHlzaXMvRU1UL2ZpZ3VyZXMvc3BlY2lmaWNfZmx1eF9oZWF0bWFwLnBuZyIsDQogICAgICAgd2lkdGg9MjAsDQogICAgICAgaGVpZ2h0PTEyLjUsDQogICAgICAgdW5pdHM9J2luJywNCiAgICByZXM9MTIwMCkNCnNwZWNpZmljX2ZpZ3VyZXMNCmRldi5vZmYoKQ0KYGBgDQoNCiMjIDIuIFZpc3VhbGl6ZSB0aGUgQnVsayBSZWFjdGlvbiBLT3MNCmBgYHtyfQ0Kcm0obGlzdD1zZXRkaWZmKGxzKCksICJmbHV4X2hlYXRtYXAiKSkNCmBgYA0KDQojIyMgQS4gTG9hZCBEYXRhDQpgYGB7cn0NCmZpbGVuYW1lID0gIkQ6L0FuYWx5c2lzL0VNVC9kYXRhL0J1bGsgUmVhY3Rpb24gS08gSW50ZXJzZWN0aW9uLmNzdiINCmRhdGEgPSByZWFkX2NzdihmaWxlbmFtZSkNCg0KIyBDcmVhdGUgbmV3IHZhcmlhYmxlIGZvciByb3cgbmFtZXMNCmRhdGEkbmFtZSA9IHBhc3RlMChkYXRhJGBCaUdHIFJlYWN0aW9uIElEYCwgDQogICAgICAgICAgICAgICAgICAgICcsICcsDQogICAgICAgICAgICAgICAgICAgIGRhdGEkYEtFR0cgU3Vic3lzdGVtYCkNCmBgYA0KDQojIyMgQi4gQ3JlYXRlIGFjY2Vzc29yeSBmdW5jdGlvbg0KYGBge3IsIGZpZy53aWR0aD0yMCwgZmlnLmhlaWdodD0xMi41LCBmaWcuYWxpZ249J3JpZ2h0JywgZHBpPTEwMH0NCmtvX2hlYXRtYXAgPSBmdW5jdGlvbihkZiwgcGF0aHdheSl7DQogIA0KICAjIElmIHBhdGh3YXkgdmFyaWFibGUgaXMgbWlzc2luZywganVzdCB2aXN1YWxpemUgZXZlcnl0aGluZw0KICBpZihtaXNzaW5nKHBhdGh3YXkpKXsNCiAgICBkYXRhID0gZGYNCiAgfWVsc2V7DQogICAgaWR4ID0gKGRmJGBLRUdHIFN1YnN5c3RlbWAgPT0gcGF0aHdheSkNCiAgICBpZHhbaXMubmEoaWR4KV0gPSBGQUxTRQ0KICAgIGRhdGEgPSBkZltpZHgsIF0NCiAgfQ0KDQogICMgQ3JlYXRlIG5ldyBkYXRhIGZvciBiYXJwbG90cyBhbmQgZGlzY3JldGUgaGVhdG1hcA0KICBiYXJkYXRhID0gZGF0YVssIDRdDQogIGJhcmRhdGFbaXMubmEoYmFyZGF0YSldID0gMA0KICBleHB0X2RhdGEgPSBkYXRhWywgNV0NCiAgDQogICMgU3BsaXQgYnkgaG91cnMNCiAgZWFybHlfZGF0YSA9IGRhdGFbLCBjKCJHU0UxNzcwOF8xaHJzIiwgIkdhcmNpYV8xaHJzIildIC0gMQ0KICBtaWQxX2RhdGEgID0gZGF0YVssIGMoIkdTRTE3NzA4XzhocnMiLCAiR1NFMTQ3NDA1XzhocnMiKV0gLSAxDQogIG1pZDJfZGF0YSAgPSBkYXRhWywgYygiR1NFMTc3MDhfMjRocnMiLCAiR2FyY2lhXzI0aHJzIiwgIkdTRTE0NzQwNV8yNGhycyIpXSAtIDENCiAgbGF0ZV9kYXRhICA9IGRhdGFbLCBjKCJHU0UxNzcwOF83MmhycyIsICJHU0UxNzUxOF83MmhycyIsICJHYXJjaWFfNDhocnMiLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiS2VzaGFtb3VuaV83MmhycyIsICJHU0UxNDc0MDVfNzJocnMiKV0gLSAxDQogIHRtcCA9IGNiaW5kKGVhcmx5X2RhdGEsIG1pZDFfZGF0YSwgbWlkMl9kYXRhLCBsYXRlX2RhdGEpDQogIA0KICAjIENyZWF0ZSBjb2x1bW4gYW5ub3RhdGlvbiBiYXJzDQogIGgxX2NvbCA9IEhlYXRtYXBBbm5vdGF0aW9uKGgxPWFubm9fYmxvY2soZ3A9Z3BhcihmaWxsPSIjQ0FDNENFIiksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGFiZWxzPWMoIkVhcmx5IiksIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxhYmVsc19ncD1ncGFyKGNvbD0iYmxhY2siLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmb250c2l6ZT0xMCkpKQ0KICBoMl9jb2wgPSBIZWF0bWFwQW5ub3RhdGlvbihoMj1hbm5vX2Jsb2NrKGdwPWdwYXIoZmlsbD0iIzhEODZDOSIpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxhYmVscz1jKCJJbnQuIDEiKSwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGFiZWxzX2dwPWdwYXIoY29sPSJ3aGl0ZSIsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZvbnRzaXplPTEwKSkpDQogIGgzX2NvbCA9IEhlYXRtYXBBbm5vdGF0aW9uKGgzPWFubm9fYmxvY2soZ3A9Z3BhcihmaWxsPSIjNzI1QUMxIiksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGFiZWxzPWMoIkludC4gMiIpLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsYWJlbHNfZ3A9Z3Bhcihjb2w9IndoaXRlIiwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9udHNpemU9MTApKSkNCiAgaDRfY29sID0gSGVhdG1hcEFubm90YXRpb24oaDQ9YW5ub19ibG9jayhncD1ncGFyKGZpbGw9IiMyNDIwMzgiKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsYWJlbHM9YygiTGF0ZSIpLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsYWJlbHNfZ3A9Z3Bhcihjb2w9IndoaXRlIiwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZvbnRzaXplPTEwKSkpDQogIA0KICAjIENvbnN0cnVjdCBleHBlcmltZW50IGhlYXRtYXAgYW5ub3RhdGlvbg0KICBobSA9IEhlYXRtYXAoYXMubWF0cml4KGV4cHRfZGF0YSksDQogICAgICAgICAgICAgY29sID0gY29sb3JSYW1wMihjKDEsIDUpLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGMoIiNGRkZGRkYiLCAiIzVCQzBCRSIsICIjM0E1MDZCIiwgIiMxQzI1NDEiLCAiIzBCMTMyQiIpKSwNCiAgICAgICAgICAgICBoZWF0bWFwX2xlZ2VuZF9wYXJhbT1saXN0KHRpdGxlPSJFeHBlcmltZW50cyIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb2xvcl9iYXI9ImRpc2NyZXRlIiksIA0KICAgICAgICAgICAgIHJlY3RfZ3AgPSBncGFyKGNvbD0iYmxhY2siLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGx3ZD0xKSwNCiAgICAgICAgICAgICB3aWR0aCA9IG5jb2woZXhwdF9kYXRhKSp1bml0KDUsICJtbSIpLCANCiAgICAgICAgICAgICBoZWlnaHQgPSBucm93KGV4cHRfZGF0YSkqdW5pdCg1LCAibW0iKSkNCiAgDQogICMgQ29uc3RydWN0IHByaW9yaXR5IHNjb3JlIGJhcnBsb3QgYW5ub3RhdGlvbg0KICBicCA9IHJvd0Fubm90YXRpb24oDQogICAgUHJpb3JpdHk9YW5ub19iYXJwbG90KA0KICAgICAgYmFyZGF0YQ0KICAgICkNCiAgKQ0KICANCiAgIyBDb25zdHJ1Y3QgdGhlIGhlYXRtYXBzDQogIGNvbF9mdW4gPSBjb2xvclJhbXAyKGMobWluKGFzLm1hdHJpeCh0bXApKSwgMCwgbWF4KGFzLm1hdHJpeCh0bXApKSksIA0KICAgICAgICAgICAgICAgICAgICAgICBjKCIjMDczQjRDIiwgIiNGRkZGRkYiLCAiI0VGNDc2RiIpKQ0KICBoMSA9IEhlYXRtYXAocm93X2xhYmVscz1kYXRhJG5hbWUsDQogICAgICAgICAgICAgICByb3dfbmFtZXNfc2lkZT0ibGVmdCIsDQogICAgICAgICAgICAgICBlYXJseV9kYXRhLCANCiAgICAgICAgICAgICAgIGNvbD1jb2xfZnVuLCANCiAgICAgICAgICAgICAgIGNsdXN0ZXJfY29sdW1ucz1GQUxTRSwgDQogICAgICAgICAgICAgICByZWN0X2dwID0gZ3Bhcihjb2w9ImJsYWNrIiwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsd2Q9MSksDQogICAgICAgICAgICAgICBjbHVzdGVyX3Jvd3M9RkFMU0UsDQogICAgICAgICAgICAgICBzaG93X2hlYXRtYXBfbGVnZW5kPUZBTFNFLA0KICAgICAgICAgICAgICAgYm90dG9tX2Fubm90YXRpb249aDFfY29sLCANCiAgICAgICAgICAgICAgIHdpZHRoID0gbmNvbChlYXJseV9kYXRhKSp1bml0KDUsICJtbSIpLCANCiAgICAgICAgICAgICAgIGhlaWdodCA9IG5yb3coZWFybHlfZGF0YSkqdW5pdCg1LCAibW0iKSkNCiAgaDIgPSBIZWF0bWFwKG1pZDFfZGF0YSwgDQogICAgICAgICAgICAgICBjb2w9Y29sX2Z1biwgDQogICAgICAgICAgICAgICBjbHVzdGVyX2NvbHVtbnM9RkFMU0UsIA0KICAgICAgICAgICAgICAgcmVjdF9ncCA9IGdwYXIoY29sPSJibGFjayIsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbHdkPTEpLA0KICAgICAgICAgICAgICAgY2x1c3Rlcl9yb3dzPUZBTFNFLA0KICAgICAgICAgICAgICAgc2hvd19oZWF0bWFwX2xlZ2VuZD1GQUxTRSwNCiAgICAgICAgICAgICAgIGJvdHRvbV9hbm5vdGF0aW9uPWgyX2NvbCwgDQogICAgICAgICAgICAgICB3aWR0aCA9IG5jb2wobWlkMV9kYXRhKSp1bml0KDUsICJtbSIpLCANCiAgICAgICAgICAgICAgIGhlaWdodCA9IG5yb3cobWlkMV9kYXRhKSp1bml0KDUsICJtbSIpKQ0KICBoMyA9IEhlYXRtYXAobWlkMl9kYXRhLCANCiAgICAgICAgICAgICAgIGNvbD1jb2xfZnVuLCANCiAgICAgICAgICAgICAgIGNsdXN0ZXJfY29sdW1ucz1GQUxTRSwgDQogICAgICAgICAgICAgICByZWN0X2dwID0gZ3Bhcihjb2w9ImJsYWNrIiwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsd2Q9MSksDQogICAgICAgICAgICAgICBjbHVzdGVyX3Jvd3M9RkFMU0UsDQogICAgICAgICAgICAgICBzaG93X2hlYXRtYXBfbGVnZW5kPUZBTFNFLA0KICAgICAgICAgICAgICAgYm90dG9tX2Fubm90YXRpb249aDNfY29sLCANCiAgICAgICAgICAgICAgIHdpZHRoID0gbmNvbChtaWQyX2RhdGEpKnVuaXQoNSwgIm1tIiksIA0KICAgICAgICAgICAgICAgaGVpZ2h0ID0gbnJvdyhtaWQyX2RhdGEpKnVuaXQoNSwgIm1tIikpDQogIGg0ID0gSGVhdG1hcChsYXRlX2RhdGEsIA0KICAgICAgICAgICAgICAgY29sPWNvbF9mdW4sIA0KICAgICAgICAgICAgICAgY2x1c3Rlcl9jb2x1bW5zPUZBTFNFLCANCiAgICAgICAgICAgICAgIHJlY3RfZ3AgPSBncGFyKGNvbD0iYmxhY2siLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGx3ZD0xKSwNCiAgICAgICAgICAgICAgIGNsdXN0ZXJfcm93cz1GQUxTRSwNCiAgICAgICAgICAgICAgIHNob3dfaGVhdG1hcF9sZWdlbmQ9VFJVRSwNCiAgICAgICAgICAgICAgIGJvdHRvbV9hbm5vdGF0aW9uPWg0X2NvbCwNCiAgICAgICAgICAgICAgIHdpZHRoID0gbmNvbChsYXRlX2RhdGEpKnVuaXQoNSwgIm1tIiksIA0KICAgICAgICAgICAgICAgaGVpZ2h0ID0gbnJvdyhsYXRlX2RhdGEpKnVuaXQoNSwgIm1tIiksDQogICAgICAgICAgICAgICBoZWF0bWFwX2xlZ2VuZF9wYXJhbT1saXN0KHRpdGxlPSJOb3JtYWxpemVkIEtPIEdyb3d0aCBTY29yZSIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhdCA9IGMobWluKGFzLm1hdHJpeCh0bXApKSwgMCwgbWF4KGFzLm1hdHJpeCh0bXApKSksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsYWJlbHMgPSBjKCJEZWNyLiBGaXRuZXNzIiwgIk5vIGNoYW5nZSIsICJJbmNyLiBmaXRuZXNzIikpKQ0KICANCiAgIyBSZXR1cm4gdGhlIGZpbmFsIGZpZ3VyZQ0KICBmaW5hbF9maWd1cmUgPSBoMStoMitoMytoNCtobSticA0KICByZXR1cm4oZmluYWxfZmlndXJlKQ0KICAgIA0KfQ0KYGBgDQoNCiMjIyBDLiBQbG90IHRoZSB0b3AgNTAgcmVhY3Rpb25zIGJhc2VkIG9uIHByaW9yaXR5IHNjb3JlLg0KYGBge3IsIGZpZy53aWR0aD0yMCwgZmlnLmhlaWdodD0xMi41LCBmaWcuYWxpZ249J3JpZ2h0JywgZHBpPTEwMH0NCiMgU29ydCBkYXRhIGJ5IHByaW9yaXR5IHNjb3JlDQpkYXRhID0gZGF0YVtvcmRlcihkYXRhJGBBYnNvbHV0ZSBFZmZlY3QgKiBOIGV4cHRzYCwgZGVjcmVhc2luZz1UUlVFKSwgXQ0KDQojIEdyYWIgdG9wIDUwDQp0b3A1MCA9IGRhdGFbMTo1MCwgXQ0KDQojIENyZWF0ZSBmaWd1cmVzDQp0b3A1MF9maWd1cmVzID0ga29faGVhdG1hcCh0b3A1MCkNCnBuZyhmaWxlbmFtZT0iRDovQW5hbHlzaXMvRU1UL2ZpZ3VyZXMvUkVDT04xX3J4bmtvX2hlYXRtYXAucG5nIiwNCiAgICAgICB3aWR0aD0yMCwNCiAgICAgICBoZWlnaHQ9MTIuNSwNCiAgICAgICB1bml0cz0naW4nLA0KICAgIHJlcz0xMjAwKQ0KdG9wNTBfZmlndXJlcw0KZGV2Lm9mZg0KDQojIFNob3cNCnRvcDUwX2ZpZ3VyZXMNCmBgYA0KDQojIyMgRC4gR3JhYiBoaWdoIGNvbmZpZGVuY2UgcmVhY3Rpb25zICgyIG9yIG1vcmUgaW4gc2FtZSBzYW1wbGUpDQpUaGVyZSdzIG5vdCB0aGF0IG11Y2ggZm9yIGhpZ2ggY29uZmlkZW5jZSByZWFjdGlvbnMuDQoNCmBgYHtyLCBmaWcud2lkdGg9MjAsIGZpZy5oZWlnaHQ9MTIuNSwgZmlnLmFsaWduPSdyaWdodCcsIGRwaT0xMDB9DQojIFN1YnNldCBSZWFjdGlvbnMNCnJlYWN0aW9uc19vZl9pbnRlcmVzdCA9IGMoImFscGhhLWtldG9nbHV0YXJhdGUvbWFsYXRlIHRyYW5zcG9ydGVyIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgImNhcm5pdGluZSBPLWFjZXR5bHRyYW5zZmVyYXNlIikNCmlkeCA9IGRhdGEkYEJpR0cgUmVhY3Rpb24gSURgICVpbiUgcmVhY3Rpb25zX29mX2ludGVyZXN0DQpzcGVjaWZpY19kYXRhID0gZGF0YVtpZHgsIF0NCg0KIyBDcmVhdGUgZmlndXJlcw0Kc3BlY2lmaWNfZmlndXJlcyA9IGtvX2hlYXRtYXAoc3BlY2lmaWNfZGF0YSkNCnBuZyhmaWxlbmFtZT0iRDovQW5hbHlzaXMvRU1UL2ZpZ3VyZXMvUkVDT04xX3J4bmtvX2hpZ2hfcHJpb3JpdHlfaGVhdG1hcC5wbmciLA0KICAgICAgIHdpZHRoPTIwLA0KICAgICAgIGhlaWdodD0xMi41LA0KICAgICAgIHVuaXRzPSdpbicsDQogICAgcmVzPTEyMDApDQpzcGVjaWZpY19maWd1cmVzDQpkZXYub2ZmKCkNCg0KIyBTaG93DQpzcGVjaWZpY19maWd1cmVzDQoNCg0KYGBgDQoNCiMjIyBFLiBHcmFiIGxvdyBjb25maWRlbmNlIHJlYWN0aW9ucyAoMSBpbiBzYW1lIHNhbXBsZSkNClRoZSBsaXN0IG9mIGxvdyBjb25maWRlbmNlIHJlYWN0aW9ucyBJJ2QgbGlrZSB0byB2aXN1YWxpemUgaXMgaGlnaC4NCg0KYGBge3J9DQpyZWFjdGlvbnNfb2ZfaW50ZXJlc3QgPSBjKCJlbm9sYXNlIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgImZhdHR5LWFjeWwtQ29BIGVsb25nYXRpb24gKG4tQzIwOjRDb0EpIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgImZhdHR5IGFjeWwtQ29BIHN5bnRoYXNlIChuLUMxMDowQ29BKSIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICJmYXR0eS1hY3lsLUNvQSBzeW50aGFzZSAobi1DMTI6MENvQSkiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAiZmF0dHktYWN5bC1Db0Egc3ludGhhc2UgKG4tQzE0OjBDb0EpIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgImh5ZHJveHltZXRoeWxnbHV0YXJ5bC1Db0EgbHlhc2UiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAiZEdUUCB0cmFuc3BvcnQgdmlhIEFUUCBhbnRpcG9ydCIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICJVRFBnbHVjb3NlIDQtZXBpbWVyYXNlIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgImFkZW5vc2luZSBraW5hc2UiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAicGFudGV0aGVpbmUtcGhvc3BoYXRlIGFkZW55bHlsdHJhbnNmZXJhc2UiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAiIDQtSHlkcm94eXBoZW55bHB5cnV2YXRlOm94eWdlbiBveGlkb3JlZHVjdGFzZSIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICJmdW1hcnlsYWNldG9hY2V0YXNlIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgIkhvbW9nZW50aXNhdGU6b3h5Z2VuIDEsMi1veGlkb3JlZHVjdGFzZSAoZGVjeWNsaXppbmcpIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgIm1hbGV5bGFjZXRvYWNldGF0ZSBpc29tZXJhc2UiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAiTWFsYXRlOnN1bGZpdGUgYW50aXBvcnQsIG1pdG9jaG9uZHJpYWwiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAiY2hvbmRyb2l0aW4gNi1zdWxmb3RyYW5zZmVyYXNlLCBHb2xnaSBhcHBhcmF0dXMiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAibmljb3RpbmF0ZS1udWNsZW90aWRlIGFkZW55bHlsdHJhbnNmZXJhc2UiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAibWFsYXRlIGRlaHlkcm9nZW5hc2UiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAiTm9yZXBpbmVwaHJpbmUgdW5pcG9ydCIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICJIeWRyb3h5bWV0aHlsZ2x1dGFyeWwtQ29BIHJldmVyc2libGUgbWl0b2Nob25kcmlhbCB0cmFuc3BvcnQiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAiY2Fybml0aW5lLWFjZXR5bGNhcm5pdGluZSBjYXJyaWVyLCBwZXJveGlzb21hbCIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICJjYXJuaXRpbmUgTy1hY2V0eWx0cmFuc2ZlcmFzZSwgcmV2ZXJzZSBkaXJlY3Rpb24sIHBlcm94aXNvbWFsIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgIlVEUC1HbGNOQWM6YmV0YUdhbCBiZXRhLTEsMy1OLWFjZXR5bGdsdWNvc2FtaW55bHRyYW5zZmVyYXNlIDEiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAiVURQLUdsY05BYzpiZXRhR2FsIGJldGEtMSwzLU4tYWNldHlsZ2x1Y29zYW1pbnlsdHJhbnNmZXJhc2UgMywgR29sZ2kgYXBwYXJhdHVzIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgIkh5ZHJveHltZXRoeWxnbHV0YXJ5bCBDb0Egc3ludGhhc2UgKGlyKSIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICJjaXRyYXRlIHRyYW5zcG9ydCwgbWl0b2Nob25kcmlhbCIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICJBY29uaXRhdGUgaHlkcmF0YXNlIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgIkFUUC1DaXRyYXRlIGx5YXNlIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgImZ1bWFyYXNlLCBtaXRvY2hvbmRyaWFsIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgInRyaW9zZS1waG9zcGhhdGUgaXNvbWVyYXNlIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgImFjZXRvbmUgbW9ub294eWdlbmFzZSIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICJmcnVjdG9zZS1iaXNwaG9zcGhhdGFzZSIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICJvcm5pdGhpbmUgdHJhbnNhbWluYXNlIHJldmVyc2libGUgKG0pIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgInN1Y2NpbmF0ZSBkZWh5ZHJvZ2VuYXNlIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgImNhcm5pdGluZSBPLWFjZXlsdHJhbnNmZXJhc2UsIG1pdG9jaG9uZHJpYWwiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAiY2l0cmF0ZSBzeW50aGFzZSIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICJJc29jaXRyYXRlIGRlaHlkcm9nZW5hc2UgKE5BRFArKSIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICJMLWxhY3RhdGUgZGVoeWRyb2dlbmFzZSIpDQpgYGANCg0KU3Vic2V0IGFuZCBjcmVhdGUgdGhlIHBsb3QuDQpgYGB7ciwgZmlnLndpZHRoPTIwLCBmaWcuaGVpZ2h0PTEyLjUsIGZpZy5hbGlnbj0ncmlnaHQnLCBkcGk9MTAwfQ0KaWR4ID0gZGF0YSRgQmlHRyBSZWFjdGlvbiBJRGAgJWluJSByZWFjdGlvbnNfb2ZfaW50ZXJlc3QNCnNwZWNpZmljX2RhdGEgPSBkYXRhW2lkeCwgXQ0KDQojIENyZWF0ZSBmaWd1cmVzDQpzcGVjaWZpY19maWd1cmVzID0ga29faGVhdG1hcChzcGVjaWZpY19kYXRhKQ0KcG5nKGZpbGVuYW1lPSJEOi9BbmFseXNpcy9FTVQvZmlndXJlcy9SRUNPTjFfcnhua29fbG93X3ByaW9yaXR5X2hlYXRtYXAucG5nIiwNCiAgICAgICB3aWR0aD0yMCwNCiAgICAgICBoZWlnaHQ9MTIuNSwNCiAgICAgICB1bml0cz0naW4nLA0KICAgIHJlcz0xMjAwKQ0Kc3BlY2lmaWNfZmlndXJlcw0KZGV2Lm9mZigpDQpgYGANCg0KIyMgMy4gU2luZ2xlLUNlbGwgUmVhY3Rpb24gS09zDQpGaW5hbGx5LCBsZXQncyBjcmVhdGUgYSB2aXN1YWxpemF0aW9uIGZvciB0aGUgc2luZ2xlLWNlbGwgcmVhY3Rpb24ga25vY2tvdXRzLg0KDQpgYGB7cn0NCnJtKGxpc3Q9bHMoKSkNCmBgYA0KDQojIyMgQS4gTG9hZCBEYXRhDQpgYGB7cn0NCmZpbGVuYW1lID0gIkQ6L0FuYWx5c2lzL0VNVC9kYXRhL3NjUk5BU2VxIFJlYWN0aW9uIEtPLmNzdiINCmRhdGEgPSByZWFkX2NzdihmaWxlbmFtZSkNCg0KIyBDcmVhdGUgbmV3IHZhcmlhYmxlIGZvciByb3cgbmFtZXMNCmRhdGEkbmFtZSA9IHBhc3RlMChkYXRhJGBCaUdHIFJlYWN0aW9uIElEYCwgDQogICAgICAgICAgICAgICAgICAgICcsICcsDQogICAgICAgICAgICAgICAgICAgIGRhdGEkYEtFR0cgU3Vic3lzdGVtYCkNCmBgYA0KIyMjIEIuIFN1YnNldCB0aGUgYXZlcmFnZSBkYXRhIGNvbHVtbnMNClRoZSBkYXRhIGhhcyBhbHJlYWR5IGJlZW4gYXZlcmFnZWQgYWNyb3NzIGFsbCBjZWxscy4NCmBgYHtyfQ0KdG1wID0gZGF0YVssIGMoIkF2ZXJhZ2VfQWxsIiwJIkF2ZXJhZ2VfRGF5MCIsDQogICAgICAgICAgICAgICAiQXZlcmFnZV9Ib3VyOCIsCSJBdmVyYWdlX0RheTEiLA0KICAgICAgICAgICAgICAgIkF2ZXJhZ2VfRGF5MyIsCSJBdmVyYWdlX0RheTciKV0NCnRtcCA9IHRtcC0xDQpgYGANCg0KIyMjIEMuIENyZWF0ZSBhbiBhbm5vdGF0aW9uIGhlYXRtYXAgc2hvd2luZyB0aGUgYXZlcmFnZSBzdGFuZGFyZCBkZXZpYXRpb24gZm9yIGVhY2ggcmVhY3Rpb24gYWNyb3NzIGFsbCBjZWxscw0KYGBge3IsIGZpZy53aWR0aD0yMCwgZmlnLmhlaWdodD0xMi41LCBmaWcuYWxpZ249J3JpZ2h0JywgZHBpPTEwMH0NCmhtID0gSGVhdG1hcChhcy5tYXRyaXgoZGF0YVssICJTdGRfQWxsIl0pLA0KICAgICAgICAgICAgIHJlY3RfZ3AgPSBncGFyKGNvbCA9ICJibGFjayIsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIGx3ZCA9IDEpLA0KICAgICAgICAgICAgIGNvbCA9IGNvbG9yUmFtcDIoYygwLCAwLjMpLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGMoIiNGRkZGRkYiLCAib3JhbmdlIikpLA0KICAgICAgICAgICAgIGNsdXN0ZXJfY29sdW1ucz1GQUxTRSwNCiAgICAgICAgICAgICBjbHVzdGVyX3Jvd3M9RkFMU0UsDQogICAgICAgICAgICAgaGVhdG1hcF9sZWdlbmRfcGFyYW09bGlzdCh0aXRsZT0iQXZlcmFnZSBTdGQiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29sb3JfYmFyPSJjb250aW51b3VzIiksDQogICAgICAgICAgICAgd2lkdGggPSBuY29sKGRhdGFbLCAiU3RkX0FsbCJdKSp1bml0KDUsICJtbSIpLCANCiAgICAgICAgICAgICBoZWlnaHQgPSBucm93KGRhdGFbLCAiU3RkX0FsbCJdKSp1bml0KDUsICJtbSIpKQ0KYGBgDQoNCiMjIyBELiBDcmVhdGUgdGhlIEhlYXRtYXAgd2l0aCBhZGRpdGlvbmFsIGZpZ3VyZXMNCmBgYHtyLCBmaWcud2lkdGg9MjAsIGZpZy5oZWlnaHQ9MTIuNSwgZmlnLmFsaWduPSdyaWdodCcsIGRwaT0xMDB9DQpmaW5hbF9kYXRhID0gYXMubWF0cml4KHRtcCkNCmNvbF9mdW4gPSBjb2xvclJhbXAyKGMobWluKGFzLm1hdHJpeCh0bXApKSwgMCwgbWF4KGFzLm1hdHJpeCh0bXApKSksIA0KICAgICAgICAgICAgICAgICAgICAgICBjKCIjMDczQjRDIiwgIiNGRkZGRkYiLCAiI0VGNDc2RiIpKQ0KDQpodCA9IEhlYXRtYXAocm93X2xhYmVscz1kYXRhJG5hbWUsDQogICAgICAgICAgICAgZmluYWxfZGF0YSwgDQogICAgICAgICAgICAgcm93X25hbWVzX3NpZGU9ImxlZnQiLA0KICAgICAgICAgICAgIHJlY3RfZ3AgPSBncGFyKGNvbCA9ICJibGFjayIsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIGx3ZCA9IDEpLA0KICAgICAgICAgICAgIGNsdXN0ZXJfY29sdW1ucz1GQUxTRSwNCiAgICAgICAgICAgICBjbHVzdGVyX3Jvd3M9RkFMU0UsDQogICAgICAgICAgICAgY29sID0gY29sX2Z1biwNCiAgICAgICAgICAgICBoZWF0bWFwX2xlZ2VuZF9wYXJhbT1saXN0KHRpdGxlPSJOb3JtYWxpemVkIEtPIEdyb3d0aCBTY29yZSIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhdCA9IGMobWluKGFzLm1hdHJpeCh0bXApKSwgMCwgbWF4KGFzLm1hdHJpeCh0bXApKSksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsYWJlbHMgPSBjKCJEZWNyLiBGaXRuZXNzIiwgIk5vIGNoYW5nZSIsICJJbmNyLiBmaXRuZXNzIikpLA0KICAgICAgICAgICAgIHdpZHRoID0gbmNvbChmaW5hbF9kYXRhKSp1bml0KDUsICJtbSIpLCANCiAgICAgICAgICAgICBoZWlnaHQgPSBucm93KGZpbmFsX2RhdGEpKnVuaXQoNSwgIm1tIikpICsNCiAgICAgaG0gDQoNCmh0DQpgYGANClNhdmUgZmlndXJlcw0KYGBge3J9DQpwbmcoZmlsZW5hbWU9IkQ6L0FuYWx5c2lzL0VNVC9maWd1cmVzL3NjUk5BU2VxX2F2Z19yeG5fa28ucG5nIiwNCiAgICAgICB3aWR0aD0yMCwNCiAgICAgICBoZWlnaHQ9MTIuNSwNCiAgICAgICB1bml0cz0naW4nLA0KICAgIHJlcz0xMjAwKQ0KaHQNCmRldi5vZmYoKQ0KYGBgDQoNCiMjIENvbmNsdXNpb24=