The 6th Mill is the last mill in any of both tandems, meaning that
the entire bagasse mass flow must go through it (similar to the 1st
mill). When too much imbibition water is applied, chute level control is
lost as the top speed is not enough for displacing the volume
(baggase+water) that must go through the mill. This high chute level
condition increases the probability of blockages and mechanical damage
to the bagasse feeders, that can cause significant downtime.
The purpose of this analysis is to find an operational constraint
over the imbibition water applied to the 6th Mills based upon process
variables to prevent damages and downtime.
Scatter - Correlation Plot Function
mapa_dispersion <- function(label_x,label_y,dataset) {
correlacion <- round(cor(dataset[[label_x]],dataset[[label_y]]),2)
ggplot(dataset, aes(.data[[label_x]], .data[[label_y]])) +
geom_point(
color="orange",
fill="#69b3a2",
shape=21,
alpha=0.5,
size=6,
stroke = 2
) +
geom_smooth(method=lm , color="#990000", fill="#FFCF00", se=TRUE) +
ggtitle(paste(label_y,"vrs.",label_x), subtitle = paste("Correlation: ",correlacion)) +
xlab(label_x) + ylab(label_y)
}
TA & TB Dataframes
The datasets used for this analysis include operational variables
like mill speed, power, torque, chute level, etc., as well as variables
related to mass flows like imbibition water, bagasse, fiber, etc. The
variables are daily averages.
dataset <- read.csv(file = 'Dataset.csv')
# Dataset for each tandem
df_TA <- dataset[-c(4,5,8,9,12,13,16,17,20,21,24,25,31,32,33,34,35,38,39,41,43,45,47,49,51)]
df_TB <- dataset[c(1,4,5,8,9,12,13,16,17,20,21,24,25,31,32,33,34,35,38,39,41,43,45,47,49,51,52,53)]
df_TA
df_TB
Tandem “A”
Density Function: 6th Mill TA Speed (rpm)
We first take a look at the Mill Speed Distribution, to identify the
speed range where the level control of the mill is nearly lost.
# PDF
distr(df_TA,'ST55M601')
Warning: Font 'Arial Narrow' is not installed, has other name, or can't be found

# Boxplot
ggplot(df_TA, aes(y=ST55M601)) +
geom_boxplot(
# custom boxes
color="blue",
fill="blue",
alpha=0.2,
# Notch
notch=TRUE,
notchwidth = 0.8,
# custom outliers
outlier.colour="red",
outlier.fill="red",
outlier.size=3) +
scale_x_discrete() +
labs(title="Boxplot",x="", y = "ST55M601 (rpm)")

# Descriptive Statistics
data.frame(Estadistica=stat.desc(df_TA$ST55M601))
NA
Maximum Operational Speed: 1200 rpms. Maximum Average Operational
Speed: 1160 rpms.
# Quartiles:
res<-quantile(df_TA$ST55M601, probs = c(0,0.25,0.5,0.75,1))
res
0% 25% 50% 75% 100%
560.6891 868.7622 941.8143 1014.9713 1156.3707
Density Function: 6th Mill TA Power (kW)
We examine the power distribution of the mill, as a proxy variable
for identifiying an acceptable load range.
# PDF
distr(df_TA,'JT55M601')

# Boxplot
ggplot(df_TA, aes(y=JT55M601)) +
geom_boxplot(
# custom boxes
color="blue",
fill="blue",
alpha=0.2,
# Notch
notch=TRUE,
notchwidth = 0.8,
# custom outliers
outlier.colour="red",
outlier.fill="red",
outlier.size=3) +
scale_x_discrete() +
labs(title="Boxplot",x="", y = "JT55M601 (kW)")

# Descriptive Statistics
data.frame(Estadistica=stat.desc(df_TA$JT55M601))
NA
Maximum Average Operational Power: 769 kW
# Quartiles:
res<-quantile(df_TA$JT55M601, probs = c(0,0.25,0.5,0.75,1))
res
0% 25% 50% 75% 100%
347.0196 489.0803 565.8324 660.6705 769.0661
Density Function: 6th Mill TA Chute Level (%)
We examine the chute level distribution of the mill.
# PDF
distr(df_TA,'LT55M601')

# Boxplot
ggplot(df_TA, aes(y=LT55M601)) +
geom_boxplot(
# custom boxes
color="blue",
fill="blue",
alpha=0.2,
notch=TRUE,
notchwidth = 0.8,
# custom outliers
outlier.colour="red",
outlier.fill="red",
outlier.size=3) +
scale_x_discrete() +
labs(title="Boxplot",x="", y = "LT55M601 (%)")

# Descriptive Statistics
data.frame(Estadistica=stat.desc(df_TA$LT55M601))
NA
# Quartiles:
res<-quantile(df_TA$LT55M601, probs = c(0,0.25,0.5,0.75,1))
res
0% 25% 50% 75% 100%
13.59563 21.51660 26.01151 31.23077 46.33880
Dataframe Filtering
We filter observations for the following operational ranges:
- Power Range for Normal Sugar Cane Milling.
- Speed Range for High Chute Level Condition in the Mill.
# Filter Dataset by Column Values:
df_TA_filtered <- df_TA[df_TA$JT55M601>=489,] # Filter by Minimum Threshold of 1st Quartile Power
df_TA_filtered <- df_TA_filtered[df_TA_filtered$ST55M601>=1015,] # Filter by Top 25% of Maximum Operational Speed (1050)
df_TA_filtered
NA
Largest Correlation Variables with TA Imbibition Water
We inspect the largest correlated variables with Imbibition Water
corr_var(df_TA_filtered, # dataframe name
ImbTA, # target
max_pvalue = 0.05, # significance level
top = 15, # top n most correlated variables with target
plot = T
)

Scatter Plots for TA Imbibition Water
Day of Season Day of Season might be a confounder
variable, because usually it is highly correlated with bagasse / fiber
content of the sugar cane. We inspect this correlation.
label_x <- "Dia.Zafra"
label_y <- "fibra.caña.ta"
mapa_dispersion(label_x,label_y,df_TA_filtered)

6th Mill TA Speed
label_x <- "ST55M601"
label_y <- "ImbTA"
mapa_dispersion(label_x,label_y,df_TA_filtered)

Sugar Cane Bagasse Content TA
label_x <- "bagazo...caña.ta"
label_y <- "ImbTA"
mapa_dispersion(label_x,label_y,df_TA_filtered)

Fiber Content Tandem A
label_x <- "X..Fibra.Core.TA"
label_y <- "ImbTA"
mapa_dispersion(label_x,label_y,df_TA_filtered)

Bagasse Mass Flow TA
label_x <- "WT555801"
label_y <- "ImbTA"
mapa_dispersion(label_x,label_y,df_TA_filtered)

Sugar Cane Trash Content Tandem A
label_x <- "X..Trash.Ponderado"
label_y <- "ImbTA"
mapa_dispersion(label_x,label_y,df_TA_filtered)

Torque on Mill 1 TA Day of Season might be a
confounder variable, because usually it is highly correlated with
bagasse / fiber content of the sugar cane. We inspect this
correlation.
label_x <- "TQ55M101"
label_y <- "ImbTA"
mapa_dispersion(label_x,label_y,df_TA_filtered)

Imbibition Water TA Linear Model
lm_ImbTA = lm(ImbTA ~ TQ55M101 + WT555801 + X..Fibra.Core.TA + ST55M601 + bagazo...caña.ta + Trash.Total...., data = df_TA_filtered) #Create the linear regression
summary(lm_ImbTA)
Call:
lm(formula = ImbTA ~ TQ55M101 + WT555801 + X..Fibra.Core.TA +
ST55M601 + bagazo...caña.ta + Trash.Total...., data = df_TA_filtered)
Residuals:
Min 1Q Median 3Q Max -60.110 -24.433 2.742 23.406 47.965
Coefficients:
Estimate Std. Error Pr(>|t|)
(Intercept) -577.0672 221.8002 -2.602 0.014873 * 0.1227 0.0618 1.986 0.057233 .
WT555801 1.9592 0.7820 2.505 0.018569 *
X..Fibra.Core.TA -42.0349 17.0986 -2.458 0.020658
ST55M601 0.8991 0.2364 3.803 0.000744 ***
bagazo...caña.ta 18.4594 3.7877 4.874 4.28e-05 *** -10.1793 4.3757 -2.326 0.027753 *
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Residual standard error: 31.98 on 27 degrees of freedom
Multiple R-squared: 0.8399, Adjusted R-squared: 0.8043
F-statistic: 23.61 on 6 and 27 DF, p-value: 1.476e-09
Imbibition Water TA Linear Model Test
# applying fitted values to TA data frame
df_TA_filtered$fitted<- lm_ImbTA$fitted.values
# creating ggplot object for visualization
lm_ImbTA_plot <- ggplot(df_TA_filtered, aes(x= Dia.Zafra, y= ImbTA,colour="real values")) +
geom_point() +
geom_line(aes(y= fitted, colour="fitted values")) +
scale_color_manual(name = "Imbibition Water TA", values = c("fitted values" = "darkblue", "real values" = "red"))
print(lm_ImbTA_plot)

Tandem “B”
Density Function: 6th Mill TB Speed (rpm)
We first take a look at the Mill Speed Distribution, to identify the
speed range where the level control of the mill is nearly lost.
# PDF
distr(df_TB,'ST55N601')

# Boxplot
ggplot(df_TB, aes(y=ST55N601)) +
geom_boxplot(
# custom boxes
color="blue",
fill="blue",
alpha=0.2,
# Notch
notch=TRUE,
notchwidth = 0.8,
# custom outliers
outlier.colour="red",
outlier.fill="red",
outlier.size=3) +
scale_x_discrete() +
labs(title="Boxplot",x="", y = "ST55N601 (rpm)")

# Descriptive Statistics
data.frame(Estadistica=stat.desc(df_TB$ST55N601))
NA
Maximum Operational Speed: 1200 rpms. Maximum Average Operational
Speed: 1160 rpms.
# Quartiles:
res<-quantile(df_TB$ST55N601, probs = c(0,0.25,0.5,0.75,1))
res
0% 25% 75% 100%
593.0956 897.9540 965.2726 1012.9059 1165.1792
Density Function: 6th Mill TB Power (kW)
We examine the power distribution of the mill, as a proxy variable
for identifiying an acceptable load range.
# PDF
distr(df_TB,'JT55N601')

# Boxplot
ggplot(df_TB, aes(y=JT55N601)) +
geom_boxplot(
# custom boxes
color="blue",
fill="blue",
alpha=0.2,
# Notch
notch=TRUE,
notchwidth = 0.8,
# custom outliers
outlier.colour="red",
outlier.fill="red",
outlier.size=3) +
scale_x_discrete() +
labs(title="Boxplot",x="", y = "JT55N601 (kW)")

# Descriptive Statistics
data.frame(Estadistica=stat.desc(df_TB$JT55N601))
NA
Maximum Operational Power: 900 kW
# Quartiles:
res<-quantile(df_TB$JT55N601, probs = c(0,0.25,0.5,0.75,1))
res
0% 50% 75% 100%
301.3789 542.7360 642.1705 722.1480 892.5287
Density Function: 6th Mill TB Chute Level (%)
We examine the chute level distribution of the mill.
# PDF
distr(df_TB,'LT55N601')

# Boxplot
ggplot(df_TB, aes(y=LT55N601)) +
geom_boxplot(
# custom boxes
color="blue",
fill="blue",
alpha=0.2,
# Notch
notch=TRUE,
notchwidth = 0.8,
# custom outliers
outlier.colour="red",
outlier.fill="red",
outlier.size=3) +
scale_x_discrete() +
labs(title="Boxplot",x="", y = "LT55N601 (%)")

# Descriptive Statistics
data.frame(Estadistica=stat.desc(df_TB$LT55N601))
NA
# Quartiles:
res<-quantile(df_TB$LT55N601, probs = c(0,0.25,0.5,0.75,1))
res
0% 25% 50% 75% 100%
2.596137 24.073490 39.651763 48.249095 66.099806
# Filter Dataset by Column Values:
df_TB_filtered <- df_TB[df_TB$JT55N601>=542,] # Filter by Minimum Threshold of 1st Quartile Power
df_TB_filtered <- df_TB_filtered[df_TB_filtered$ST55N601>=1012,] # Filter by Top 25% of Maximum Operational Speed
df_TB_filtered
NA
Largest Correlation Variables with TB Imbibition Water
corr_var(df_TB_filtered, # dataframe name
ImbTB, # target
max_pvalue = 0.05, # significance level
top = 15, # top n most correlated variables with target
plot = T
)

Day of Season
label_x <- "Dia.Zafra"
label_y <- "ImbTB"
mapa_dispersion(label_x,label_y,df_TB_filtered)

6th TB Mill Speed
label_x <- "ST55N601"
label_y <- "ImbTB"
mapa_dispersion(label_x,label_y,df_TB_filtered)

1st TB Mill Power
label_x <- "JT55N101"
label_y <- "ImbTB"
mapa_dispersion(label_x,label_y,df_TB_filtered)

Sugar Cane Fiber Content Tandem B
label_x <- "X..Fibra.Core.TB"
label_y <- "ImbTB"
mapa_dispersion(label_x,label_y,df_TB_filtered)

Imbibition Water TB Linear Model
lm_ImbTB = lm(ImbTB ~ Dia.Zafra + ST55N601 + TQ55N101_stdev + JT55N101_stdev + caña.molida.tb, data = df_TB_filtered) #Create the linear regression
summary(lm_ImbTB)
Call:
lm(formula = ImbTB ~ Dia.Zafra + ST55N601 + TQ55N101_stdev +
JT55N101_stdev + caña.molida.tb, data = df_TB_filtered)Residuals:
Min 1Q Median 3Q Max
-22.83 5.04 19.66 38.66
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 17.440963 145.137904 0.905079
Dia.Zafra 1.228458 0.215136 5.710 2.27e-06 ***
ST55N601 0.532491 3.752 0.000676 ***
TQ55N101_stdev -0.829769 0.293859 -2.824 **
JT55N101_stdev 1.599298 0.657877 2.431 0.020654 *
caña.molida.tb 0.008479 0.003985 2.128 0.040893 *
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Residual standard error: 29.32 on 33 degrees of freedom
Multiple R-squared: 0.7808 0.7476
F-statistic: 23.51 5 and 33 DF, p-value: 5.28e-10
Imbibition Water TB Linear Model Test
# applying fitted values to TB data frame
df_TB_filtered$fitted<- lm_ImbTB$fitted.values
# creating ggplot object for visualization
lm_ImbTB_plot <- ggplot(df_TB_filtered, aes(x= Dia.Zafra, y= ImbTB,colour="real values")) +
geom_point() +
geom_line(aes(y= fitted, colour="fitted values")) +
scale_color_manual(name = "Imbibition Water TB", values = c("fitted values" = "darkblue", "real values" = "red"))
print(lm_ImbTB_plot)

LS0tDQp0aXRsZTogIk1pbGwgNiBJbWJpYml0aW9uIFdhdGVyIE9wZXJhdGlvbmFsIENvbnN0cmFpbnQiDQpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sNCi0tLQ0KDQpUaGUgNnRoIE1pbGwgaXMgdGhlIGxhc3QgbWlsbCBpbiBhbnkgb2YgYm90aCB0YW5kZW1zLCBtZWFuaW5nIHRoYXQgdGhlIGVudGlyZSBiYWdhc3NlIG1hc3MgZmxvdyBtdXN0IGdvIHRocm91Z2ggaXQgKHNpbWlsYXIgdG8gdGhlIDFzdCBtaWxsKS4gV2hlbiB0b28gbXVjaCBpbWJpYml0aW9uIHdhdGVyIGlzIGFwcGxpZWQsIGNodXRlIGxldmVsIGNvbnRyb2wgaXMgbG9zdCBhcyB0aGUgdG9wIHNwZWVkIGlzIG5vdCBlbm91Z2ggZm9yIGRpc3BsYWNpbmcgdGhlIHZvbHVtZSAoYmFnZ2FzZSt3YXRlcikgdGhhdCBtdXN0IGdvIHRocm91Z2ggdGhlIG1pbGwuIFRoaXMgaGlnaCBjaHV0ZSBsZXZlbCBjb25kaXRpb24gaW5jcmVhc2VzIHRoZSBwcm9iYWJpbGl0eSBvZiBibG9ja2FnZXMgYW5kIG1lY2hhbmljYWwgZGFtYWdlIHRvIHRoZSBiYWdhc3NlIGZlZWRlcnMsIHRoYXQgY2FuIGNhdXNlIHNpZ25pZmljYW50IGRvd250aW1lLg0KDQpUaGUgcHVycG9zZSBvZiB0aGlzIGFuYWx5c2lzIGlzIHRvIGZpbmQgYW4gb3BlcmF0aW9uYWwgY29uc3RyYWludCBvdmVyIHRoZSBpbWJpYml0aW9uIHdhdGVyIGFwcGxpZWQgdG8gdGhlIDZ0aCBNaWxscyBiYXNlZCB1cG9uIHByb2Nlc3MgdmFyaWFibGVzIHRvIHByZXZlbnQgZGFtYWdlcyBhbmQgZG93bnRpbWUuIA0KDQpGb3IgdGhhdCBhIENvcnJlbGF0aW9uIEFuYWx5c2lzIGZvciBNaWxsIDYgb24gVEEgJiBUQiBmb3IgdGhlICoqMjAyMy0yMDI0IEhhcnZlc3QgU2Vhc29uKiogaXMgY29uZHVjdGVkLg0KDQoNCiMjIyBMaWJyYXJpZXMNCmBgYHtyfQ0KbGlicmFyeShkcGx5cikNCmxpYnJhcnkocGFzdGVjcykNCmxpYnJhcnkoZ2dwbG90MikNCmxpYnJhcnkobGFyZXMpDQpgYGANCg0KIyMjIFNjYXR0ZXIgLSBDb3JyZWxhdGlvbiBQbG90IEZ1bmN0aW9uDQpgYGB7cn0NCm1hcGFfZGlzcGVyc2lvbiA8LSBmdW5jdGlvbihsYWJlbF94LGxhYmVsX3ksZGF0YXNldCkgew0KICBjb3JyZWxhY2lvbiA8LSByb3VuZChjb3IoZGF0YXNldFtbbGFiZWxfeF1dLGRhdGFzZXRbW2xhYmVsX3ldXSksMikNCiAgZ2dwbG90KGRhdGFzZXQsIGFlcyguZGF0YVtbbGFiZWxfeF1dLCAuZGF0YVtbbGFiZWxfeV1dKSkgKyANCiAgICBnZW9tX3BvaW50KA0KICAgICAgICBjb2xvcj0ib3JhbmdlIiwNCiAgICAgICAgZmlsbD0iIzY5YjNhMiIsDQogICAgICAgIHNoYXBlPTIxLA0KICAgICAgICBhbHBoYT0wLjUsDQogICAgICAgIHNpemU9NiwNCiAgICAgICAgc3Ryb2tlID0gMg0KICAgICAgICApICsNCiAgICBnZW9tX3Ntb290aChtZXRob2Q9bG0gLCBjb2xvcj0iIzk5MDAwMCIsIGZpbGw9IiNGRkNGMDAiLCBzZT1UUlVFKSArDQogICAgZ2d0aXRsZShwYXN0ZShsYWJlbF95LCJ2cnMuIixsYWJlbF94KSwgc3VidGl0bGUgPSBwYXN0ZSgiQ29ycmVsYXRpb246ICIsY29ycmVsYWNpb24pKSArDQogIHhsYWIobGFiZWxfeCkgKyB5bGFiKGxhYmVsX3kpDQp9DQpgYGANCg0KIyMjIFRBICYgVEIgRGF0YWZyYW1lcw0KDQpUaGUgZGF0YXNldHMgdXNlZCBmb3IgdGhpcyBhbmFseXNpcyBpbmNsdWRlIG9wZXJhdGlvbmFsIHZhcmlhYmxlcyBsaWtlIG1pbGwgc3BlZWQsIHBvd2VyLCB0b3JxdWUsIGNodXRlIGxldmVsLCBldGMuLCBhcyB3ZWxsIGFzIHZhcmlhYmxlcyByZWxhdGVkIHRvIG1hc3MgZmxvd3MgbGlrZSBpbWJpYml0aW9uIHdhdGVyLCBiYWdhc3NlLCBmaWJlciwgZXRjLiBUaGUgdmFyaWFibGVzIGFyZSAqKmRhaWx5IGF2ZXJhZ2VzKiouDQpgYGB7cn0NCmRhdGFzZXQgPC0gcmVhZC5jc3YoZmlsZSA9ICdEYXRhc2V0LmNzdicpDQoNCiMgRGF0YXNldCBmb3IgZWFjaCB0YW5kZW0NCmRmX1RBIDwtIGRhdGFzZXRbLWMoNCw1LDgsOSwxMiwxMywxNiwxNywyMCwyMSwyNCwyNSwzMSwzMiwzMywzNCwzNSwzOCwzOSw0MSw0Myw0NSw0Nyw0OSw1MSldDQpkZl9UQiA8LSBkYXRhc2V0W2MoMSw0LDUsOCw5LDEyLDEzLDE2LDE3LDIwLDIxLDI0LDI1LDMxLDMyLDMzLDM0LDM1LDM4LDM5LDQxLDQzLDQ1LDQ3LDQ5LDUxLDUyLDUzKV0NCmRmX1RBDQpkZl9UQg0KYGBgDQojIyBUYW5kZW0gIkEiDQoNCiMjIyBEZW5zaXR5IEZ1bmN0aW9uOiA2dGggTWlsbCBUQSBTcGVlZCAocnBtKQ0KDQpXZSBmaXJzdCB0YWtlIGEgbG9vayBhdCB0aGUgTWlsbCBTcGVlZCBEaXN0cmlidXRpb24sIHRvIGlkZW50aWZ5IHRoZSBzcGVlZCByYW5nZSB3aGVyZSB0aGUgbGV2ZWwgY29udHJvbCBvZiB0aGUgbWlsbCBpcyBuZWFybHkgbG9zdC4NCmBgYHtyfQ0KDQojIFBERg0KZGlzdHIoZGZfVEEsJ1NUNTVNNjAxJykNCg0KIyBCb3hwbG90DQpnZ3Bsb3QoZGZfVEEsIGFlcyh5PVNUNTVNNjAxKSkgKyANCiAgICBnZW9tX2JveHBsb3QoIA0KICAgICAgICAjIGN1c3RvbSBib3hlcw0KICAgICAgICBjb2xvcj0iYmx1ZSIsDQogICAgICAgIGZpbGw9ImJsdWUiLA0KICAgICAgICBhbHBoYT0wLjIsDQogICAgICAgIA0KICAgICAgICAjIE5vdGNoDQogICAgICAgIG5vdGNoPVRSVUUsDQogICAgICAgIG5vdGNod2lkdGggPSAwLjgsDQogICAgICAgIA0KICAgICAgICAjIGN1c3RvbSBvdXRsaWVycw0KICAgICAgICBvdXRsaWVyLmNvbG91cj0icmVkIiwNCiAgICAgICAgb3V0bGllci5maWxsPSJyZWQiLA0KICAgICAgICBvdXRsaWVyLnNpemU9MykgKw0KICBzY2FsZV94X2Rpc2NyZXRlKCkgKw0KICBsYWJzKHRpdGxlPSJCb3hwbG90Iix4PSIiLCB5ID0gIlNUNTVNNjAxIChycG0pIikNCg0KIyBEZXNjcmlwdGl2ZSBTdGF0aXN0aWNzDQpkYXRhLmZyYW1lKEVzdGFkaXN0aWNhPXN0YXQuZGVzYyhkZl9UQSRTVDU1TTYwMSkpDQoNCmBgYA0KTWF4aW11bSBPcGVyYXRpb25hbCBTcGVlZDogMTIwMCBycG1zLiBNYXhpbXVtIEF2ZXJhZ2UgT3BlcmF0aW9uYWwgU3BlZWQ6IDExNjAgcnBtcy4NCg0KYGBge3J9DQojIFF1YXJ0aWxlczoNCnJlczwtcXVhbnRpbGUoZGZfVEEkU1Q1NU02MDEsIHByb2JzID0gYygwLDAuMjUsMC41LDAuNzUsMSkpIA0KcmVzDQoNCmBgYA0KDQojIyMgRGVuc2l0eSBGdW5jdGlvbjogNnRoIE1pbGwgVEEgUG93ZXIgKGtXKQ0KDQpXZSBleGFtaW5lIHRoZSBwb3dlciBkaXN0cmlidXRpb24gb2YgdGhlIG1pbGwsIGFzIGEgcHJveHkgdmFyaWFibGUgZm9yIGlkZW50aWZpeWluZyBhbiBhY2NlcHRhYmxlIGxvYWQgcmFuZ2UuDQpgYGB7cn0NCg0KIyBQREYNCmRpc3RyKGRmX1RBLCdKVDU1TTYwMScpDQoNCiMgQm94cGxvdA0KZ2dwbG90KGRmX1RBLCBhZXMoeT1KVDU1TTYwMSkpICsgDQogICAgZ2VvbV9ib3hwbG90KCANCiAgICAgICAgIyBjdXN0b20gYm94ZXMNCiAgICAgICAgY29sb3I9ImJsdWUiLA0KICAgICAgICBmaWxsPSJibHVlIiwNCiAgICAgICAgYWxwaGE9MC4yLA0KICAgICAgICANCiAgICAgICAgIyBOb3RjaA0KICAgICAgICBub3RjaD1UUlVFLA0KICAgICAgICBub3RjaHdpZHRoID0gMC44LA0KICAgICAgICANCiAgICAgICAgIyBjdXN0b20gb3V0bGllcnMNCiAgICAgICAgb3V0bGllci5jb2xvdXI9InJlZCIsDQogICAgICAgIG91dGxpZXIuZmlsbD0icmVkIiwNCiAgICAgICAgb3V0bGllci5zaXplPTMpICsNCiAgc2NhbGVfeF9kaXNjcmV0ZSgpICsNCiAgbGFicyh0aXRsZT0iQm94cGxvdCIseD0iIiwgeSA9ICJKVDU1TTYwMSAoa1cpIikNCg0KIyBEZXNjcmlwdGl2ZSBTdGF0aXN0aWNzDQpkYXRhLmZyYW1lKEVzdGFkaXN0aWNhPXN0YXQuZGVzYyhkZl9UQSRKVDU1TTYwMSkpDQoNCmBgYA0KTWF4aW11bSBBdmVyYWdlIE9wZXJhdGlvbmFsIFBvd2VyOiA3Njkga1cNCg0KYGBge3J9DQojIFF1YXJ0aWxlczoNCnJlczwtcXVhbnRpbGUoZGZfVEEkSlQ1NU02MDEsIHByb2JzID0gYygwLDAuMjUsMC41LDAuNzUsMSkpIA0KcmVzDQoNCmBgYA0KDQoNCiMjIyBEZW5zaXR5IEZ1bmN0aW9uOiA2dGggTWlsbCBUQSBDaHV0ZSBMZXZlbCAoJSkNCg0KV2UgZXhhbWluZSB0aGUgY2h1dGUgbGV2ZWwgZGlzdHJpYnV0aW9uIG9mIHRoZSBtaWxsLg0KYGBge3J9DQoNCiMgUERGDQpkaXN0cihkZl9UQSwnTFQ1NU02MDEnKQ0KDQojIEJveHBsb3QNCmdncGxvdChkZl9UQSwgYWVzKHk9TFQ1NU02MDEpKSArIA0KICAgIGdlb21fYm94cGxvdCggDQogICAgICAgICMgY3VzdG9tIGJveGVzDQogICAgICAgIGNvbG9yPSJibHVlIiwNCiAgICAgICAgZmlsbD0iYmx1ZSIsDQogICAgICAgIGFscGhhPTAuMiwNCiAgICAgICAgDQogICAgICAgICMgTm90Y2gNCiAgICAgICAgbm90Y2g9VFJVRSwNCiAgICAgICAgbm90Y2h3aWR0aCA9IDAuOCwNCiAgICAgICAgDQogICAgICAgICMgY3VzdG9tIG91dGxpZXJzDQogICAgICAgIG91dGxpZXIuY29sb3VyPSJyZWQiLA0KICAgICAgICBvdXRsaWVyLmZpbGw9InJlZCIsDQogICAgICAgIG91dGxpZXIuc2l6ZT0zKSArDQogIHNjYWxlX3hfZGlzY3JldGUoKSArDQogIGxhYnModGl0bGU9IkJveHBsb3QiLHg9IiIsIHkgPSAiTFQ1NU02MDEgKCUpIikNCg0KIyBEZXNjcmlwdGl2ZSBTdGF0aXN0aWNzDQpkYXRhLmZyYW1lKEVzdGFkaXN0aWNhPXN0YXQuZGVzYyhkZl9UQSRMVDU1TTYwMSkpDQoNCmBgYA0KYGBge3J9DQojIFF1YXJ0aWxlczoNCnJlczwtcXVhbnRpbGUoZGZfVEEkTFQ1NU02MDEsIHByb2JzID0gYygwLDAuMjUsMC41LDAuNzUsMSkpIA0KcmVzDQoNCmBgYA0KDQojIyMgRGF0YWZyYW1lIEZpbHRlcmluZw0KDQpXZSBmaWx0ZXIgb2JzZXJ2YXRpb25zIGZvciB0aGUgZm9sbG93aW5nIG9wZXJhdGlvbmFsIHJhbmdlczoNCg0KLSBQb3dlciBSYW5nZSBmb3IgTm9ybWFsIFN1Z2FyIENhbmUgTWlsbGluZy4NCi0gU3BlZWQgUmFuZ2UgZm9yIEhpZ2ggQ2h1dGUgTGV2ZWwgQ29uZGl0aW9uIGluIHRoZSBNaWxsLg0KDQpgYGB7cn0NCg0KIyBGaWx0ZXIgRGF0YXNldCBieSBDb2x1bW4gVmFsdWVzOg0KZGZfVEFfZmlsdGVyZWQgPC0gZGZfVEFbZGZfVEEkSlQ1NU02MDE+PTQ4OSxdICMgRmlsdGVyIGJ5IE1pbmltdW0gVGhyZXNob2xkIG9mIDFzdCBRdWFydGlsZSBQb3dlcg0KZGZfVEFfZmlsdGVyZWQgPC0gZGZfVEFfZmlsdGVyZWRbZGZfVEFfZmlsdGVyZWQkU1Q1NU02MDE+PTEwMTUsXSAjIEZpbHRlciBieSBUb3AgMjUlIG9mIE1heGltdW0gT3BlcmF0aW9uYWwgU3BlZWQgKDEwNTApDQpkZl9UQV9maWx0ZXJlZA0KDQpgYGANCiMjIyBMYXJnZXN0IENvcnJlbGF0aW9uIFZhcmlhYmxlcyB3aXRoIFRBIEltYmliaXRpb24gV2F0ZXINCg0KV2UgaW5zcGVjdCB0aGUgbGFyZ2VzdCBjb3JyZWxhdGVkIHZhcmlhYmxlcyB3aXRoIEltYmliaXRpb24gV2F0ZXINCmBgYHtyfQ0KY29ycl92YXIoZGZfVEFfZmlsdGVyZWQsICMgZGF0YWZyYW1lIG5hbWUNCiAgSW1iVEEsICMgdGFyZ2V0DQogIG1heF9wdmFsdWUgPSAwLjA1LCAjIHNpZ25pZmljYW5jZSBsZXZlbA0KICB0b3AgPSAxNSwgIyB0b3AgbiBtb3N0IGNvcnJlbGF0ZWQgdmFyaWFibGVzIHdpdGggdGFyZ2V0DQogIHBsb3QgPSBUDQopDQoNCmBgYA0KDQojIyMgU2NhdHRlciBQbG90cyBmb3IgVEEgSW1iaWJpdGlvbiBXYXRlcg0KDQoqKkRheSBvZiBTZWFzb24qKg0KRGF5IG9mIFNlYXNvbiBtaWdodCBiZSBhIGNvbmZvdW5kZXIgdmFyaWFibGUsIGJlY2F1c2UgdXN1YWxseSBpdCBpcyBoaWdobHkgY29ycmVsYXRlZCB3aXRoIGJhZ2Fzc2UgLyBmaWJlciBjb250ZW50IG9mIHRoZSBzdWdhciBjYW5lLiBXZSBpbnNwZWN0IHRoaXMgY29ycmVsYXRpb24uDQoNCmBgYHtyfQ0KbGFiZWxfeCA8LSAiRGlhLlphZnJhIg0KbGFiZWxfeSA8LSAiZmlicmEuY2HDsWEudGEiDQoNCm1hcGFfZGlzcGVyc2lvbihsYWJlbF94LGxhYmVsX3ksZGZfVEFfZmlsdGVyZWQpDQpgYGANCg0KKio2dGggTWlsbCBUQSBTcGVlZCoqDQpgYGB7cn0NCmxhYmVsX3ggPC0gIlNUNTVNNjAxIg0KbGFiZWxfeSA8LSAiSW1iVEEiDQoNCm1hcGFfZGlzcGVyc2lvbihsYWJlbF94LGxhYmVsX3ksZGZfVEFfZmlsdGVyZWQpDQpgYGANCg0KKipTdWdhciBDYW5lIEJhZ2Fzc2UgQ29udGVudCBUQSAqKg0KYGBge3J9DQpsYWJlbF94IDwtICJiYWdhem8uLi5jYcOxYS50YSINCmxhYmVsX3kgPC0gIkltYlRBIg0KDQptYXBhX2Rpc3BlcnNpb24obGFiZWxfeCxsYWJlbF95LGRmX1RBX2ZpbHRlcmVkKQ0KYGBgDQoNCioqRmliZXIgQ29udGVudCBUYW5kZW0gQSoqDQpgYGB7cn0NCmxhYmVsX3ggPC0gIlguLkZpYnJhLkNvcmUuVEEiDQpsYWJlbF95IDwtICJJbWJUQSINCg0KbWFwYV9kaXNwZXJzaW9uKGxhYmVsX3gsbGFiZWxfeSxkZl9UQV9maWx0ZXJlZCkNCmBgYA0KDQoqKkJhZ2Fzc2UgTWFzcyBGbG93IFRBICoqDQpgYGB7cn0NCmxhYmVsX3ggPC0gIldUNTU1ODAxIg0KbGFiZWxfeSA8LSAiSW1iVEEiDQoNCm1hcGFfZGlzcGVyc2lvbihsYWJlbF94LGxhYmVsX3ksZGZfVEFfZmlsdGVyZWQpDQpgYGANCg0KDQoqKlN1Z2FyIENhbmUgVHJhc2ggQ29udGVudCBUYW5kZW0gQSoqDQpgYGB7cn0NCmxhYmVsX3ggPC0gIlguLlRyYXNoLlBvbmRlcmFkbyINCmxhYmVsX3kgPC0gIkltYlRBIg0KDQptYXBhX2Rpc3BlcnNpb24obGFiZWxfeCxsYWJlbF95LGRmX1RBX2ZpbHRlcmVkKQ0KYGBgDQoNCioqVG9ycXVlIG9uIE1pbGwgMSBUQSoqDQpEYXkgb2YgU2Vhc29uIG1pZ2h0IGJlIGEgY29uZm91bmRlciB2YXJpYWJsZSwgYmVjYXVzZSB1c3VhbGx5IGl0IGlzIGhpZ2hseSBjb3JyZWxhdGVkIHdpdGggYmFnYXNzZSAvIGZpYmVyIGNvbnRlbnQgb2YgdGhlIHN1Z2FyIGNhbmUuIFdlIGluc3BlY3QgdGhpcyBjb3JyZWxhdGlvbi4NCg0KYGBge3J9DQpsYWJlbF94IDwtICJUUTU1TTEwMSINCmxhYmVsX3kgPC0gIkltYlRBIg0KDQptYXBhX2Rpc3BlcnNpb24obGFiZWxfeCxsYWJlbF95LGRmX1RBX2ZpbHRlcmVkKQ0KYGBgDQoNCg0KIyMjIEltYmliaXRpb24gV2F0ZXIgVEEgTGluZWFyIE1vZGVsDQpgYGB7cn0NCmxtX0ltYlRBID0gbG0oSW1iVEEgfiBUUTU1TTEwMSArIFdUNTU1ODAxICsgWC4uRmlicmEuQ29yZS5UQSArIFNUNTVNNjAxICsgYmFnYXpvLi4uY2HDsWEudGEgKyBUcmFzaC5Ub3RhbC4uLi4sIGRhdGEgPSBkZl9UQV9maWx0ZXJlZCkgI0NyZWF0ZSB0aGUgbGluZWFyIHJlZ3Jlc3Npb24NCnN1bW1hcnkobG1fSW1iVEEpDQpgYGANCg0KIyMjIEltYmliaXRpb24gV2F0ZXIgVEEgTGluZWFyIE1vZGVsIFRlc3QNCg0KYGBge3J9DQojIGFwcGx5aW5nIGZpdHRlZCB2YWx1ZXMgdG8gVEEgZGF0YSBmcmFtZQ0KZGZfVEFfZmlsdGVyZWQkZml0dGVkPC0gbG1fSW1iVEEkZml0dGVkLnZhbHVlcw0KDQojIGNyZWF0aW5nIGdncGxvdCBvYmplY3QgZm9yIHZpc3VhbGl6YXRpb24NCmxtX0ltYlRBX3Bsb3QgPC0gZ2dwbG90KGRmX1RBX2ZpbHRlcmVkLCBhZXMoeD0gRGlhLlphZnJhLCB5PSBJbWJUQSxjb2xvdXI9InJlYWwgdmFsdWVzIikpICsNCiAgZ2VvbV9wb2ludCgpICsNCiAgZ2VvbV9saW5lKGFlcyh5PSBmaXR0ZWQsIGNvbG91cj0iZml0dGVkIHZhbHVlcyIpKSArDQogIHNjYWxlX2NvbG9yX21hbnVhbChuYW1lID0gIkltYmliaXRpb24gV2F0ZXIgVEEiLCB2YWx1ZXMgPSBjKCJmaXR0ZWQgdmFsdWVzIiA9ICJkYXJrYmx1ZSIsICJyZWFsIHZhbHVlcyIgPSAicmVkIikpDQoNCnByaW50KGxtX0ltYlRBX3Bsb3QpDQoNCmBgYA0KIyMgVGFuZGVtICJCIg0KDQojIyMgRGVuc2l0eSBGdW5jdGlvbjogNnRoIE1pbGwgVEIgU3BlZWQgKHJwbSkNCldlIGZpcnN0IHRha2UgYSBsb29rIGF0IHRoZSBNaWxsIFNwZWVkIERpc3RyaWJ1dGlvbiwgdG8gaWRlbnRpZnkgdGhlIHNwZWVkIHJhbmdlIHdoZXJlIHRoZSBsZXZlbCBjb250cm9sIG9mIHRoZSBtaWxsIGlzIG5lYXJseSBsb3N0Lg0KYGBge3J9DQoNCiMgUERGDQpkaXN0cihkZl9UQiwnU1Q1NU42MDEnKQ0KDQojIEJveHBsb3QNCmdncGxvdChkZl9UQiwgYWVzKHk9U1Q1NU42MDEpKSArIA0KICAgIGdlb21fYm94cGxvdCggDQogICAgICAgICMgY3VzdG9tIGJveGVzDQogICAgICAgIGNvbG9yPSJibHVlIiwNCiAgICAgICAgZmlsbD0iYmx1ZSIsDQogICAgICAgIGFscGhhPTAuMiwNCiAgICAgICAgDQogICAgICAgICMgTm90Y2gNCiAgICAgICAgbm90Y2g9VFJVRSwNCiAgICAgICAgbm90Y2h3aWR0aCA9IDAuOCwNCiAgICAgICAgDQogICAgICAgICMgY3VzdG9tIG91dGxpZXJzDQogICAgICAgIG91dGxpZXIuY29sb3VyPSJyZWQiLA0KICAgICAgICBvdXRsaWVyLmZpbGw9InJlZCIsDQogICAgICAgIG91dGxpZXIuc2l6ZT0zKSArDQogIHNjYWxlX3hfZGlzY3JldGUoKSArDQogIGxhYnModGl0bGU9IkJveHBsb3QiLHg9IiIsIHkgPSAiU1Q1NU42MDEgKHJwbSkiKQ0KDQojIERlc2NyaXB0aXZlIFN0YXRpc3RpY3MNCmRhdGEuZnJhbWUoRXN0YWRpc3RpY2E9c3RhdC5kZXNjKGRmX1RCJFNUNTVONjAxKSkNCg0KYGBgDQoNCk1heGltdW0gT3BlcmF0aW9uYWwgU3BlZWQ6IDEyMDAgcnBtcy4gTWF4aW11bSBBdmVyYWdlIE9wZXJhdGlvbmFsIFNwZWVkOiAxMTYwIHJwbXMuDQoNCmBgYHtyfQ0KIyBRdWFydGlsZXM6DQpyZXM8LXF1YW50aWxlKGRmX1RCJFNUNTVONjAxLCBwcm9icyA9IGMoMCwwLjI1LDAuNSwwLjc1LDEpKSANCnJlcw0KDQpgYGANCg0KIyMjIERlbnNpdHkgRnVuY3Rpb246IDZ0aCBNaWxsIFRCIFBvd2VyIChrVykNCldlIGV4YW1pbmUgdGhlIHBvd2VyIGRpc3RyaWJ1dGlvbiBvZiB0aGUgbWlsbCwgYXMgYSBwcm94eSB2YXJpYWJsZSBmb3IgaWRlbnRpZml5aW5nIGFuIGFjY2VwdGFibGUgbG9hZCByYW5nZS4NCmBgYHtyfQ0KDQojIFBERg0KZGlzdHIoZGZfVEIsJ0pUNTVONjAxJykNCg0KIyBCb3hwbG90DQpnZ3Bsb3QoZGZfVEIsIGFlcyh5PUpUNTVONjAxKSkgKyANCiAgICBnZW9tX2JveHBsb3QoIA0KICAgICAgICAjIGN1c3RvbSBib3hlcw0KICAgICAgICBjb2xvcj0iYmx1ZSIsDQogICAgICAgIGZpbGw9ImJsdWUiLA0KICAgICAgICBhbHBoYT0wLjIsDQogICAgICAgIA0KICAgICAgICAjIE5vdGNoDQogICAgICAgIG5vdGNoPVRSVUUsDQogICAgICAgIG5vdGNod2lkdGggPSAwLjgsDQogICAgICAgIA0KICAgICAgICAjIGN1c3RvbSBvdXRsaWVycw0KICAgICAgICBvdXRsaWVyLmNvbG91cj0icmVkIiwNCiAgICAgICAgb3V0bGllci5maWxsPSJyZWQiLA0KICAgICAgICBvdXRsaWVyLnNpemU9MykgKw0KICBzY2FsZV94X2Rpc2NyZXRlKCkgKw0KICBsYWJzKHRpdGxlPSJCb3hwbG90Iix4PSIiLCB5ID0gIkpUNTVONjAxIChrVykiKQ0KDQojIERlc2NyaXB0aXZlIFN0YXRpc3RpY3MNCmRhdGEuZnJhbWUoRXN0YWRpc3RpY2E9c3RhdC5kZXNjKGRmX1RCJEpUNTVONjAxKSkNCg0KYGBgDQpNYXhpbXVtIE9wZXJhdGlvbmFsIFBvd2VyOiA5MDAga1cNCg0KYGBge3J9DQojIFF1YXJ0aWxlczoNCnJlczwtcXVhbnRpbGUoZGZfVEIkSlQ1NU42MDEsIHByb2JzID0gYygwLDAuMjUsMC41LDAuNzUsMSkpIA0KcmVzDQoNCmBgYA0KDQoNCiMjIyBEZW5zaXR5IEZ1bmN0aW9uOiA2dGggTWlsbCBUQiBDaHV0ZSBMZXZlbCAoJSkNCg0KV2UgZXhhbWluZSB0aGUgY2h1dGUgbGV2ZWwgZGlzdHJpYnV0aW9uIG9mIHRoZSBtaWxsLg0KYGBge3J9DQoNCiMgUERGDQpkaXN0cihkZl9UQiwnTFQ1NU42MDEnKQ0KDQojIEJveHBsb3QNCmdncGxvdChkZl9UQiwgYWVzKHk9TFQ1NU42MDEpKSArIA0KICAgIGdlb21fYm94cGxvdCggDQogICAgICAgICMgY3VzdG9tIGJveGVzDQogICAgICAgIGNvbG9yPSJibHVlIiwNCiAgICAgICAgZmlsbD0iYmx1ZSIsDQogICAgICAgIGFscGhhPTAuMiwNCiAgICAgICAgDQogICAgICAgICMgTm90Y2gNCiAgICAgICAgbm90Y2g9VFJVRSwNCiAgICAgICAgbm90Y2h3aWR0aCA9IDAuOCwNCiAgICAgICAgDQogICAgICAgICMgY3VzdG9tIG91dGxpZXJzDQogICAgICAgIG91dGxpZXIuY29sb3VyPSJyZWQiLA0KICAgICAgICBvdXRsaWVyLmZpbGw9InJlZCIsDQogICAgICAgIG91dGxpZXIuc2l6ZT0zKSArDQogIHNjYWxlX3hfZGlzY3JldGUoKSArDQogIGxhYnModGl0bGU9IkJveHBsb3QiLHg9IiIsIHkgPSAiTFQ1NU42MDEgKCUpIikNCg0KIyBEZXNjcmlwdGl2ZSBTdGF0aXN0aWNzDQpkYXRhLmZyYW1lKEVzdGFkaXN0aWNhPXN0YXQuZGVzYyhkZl9UQiRMVDU1TjYwMSkpDQoNCmBgYA0KYGBge3J9DQojIFF1YXJ0aWxlczoNCnJlczwtcXVhbnRpbGUoZGZfVEIkTFQ1NU42MDEsIHByb2JzID0gYygwLDAuMjUsMC41LDAuNzUsMSkpIA0KcmVzDQoNCmBgYA0KDQoNCmBgYHtyfQ0KDQojIEZpbHRlciBEYXRhc2V0IGJ5IENvbHVtbiBWYWx1ZXM6DQpkZl9UQl9maWx0ZXJlZCA8LSBkZl9UQltkZl9UQiRKVDU1TjYwMT49NTQyLF0gIyBGaWx0ZXIgYnkgTWluaW11bSBUaHJlc2hvbGQgb2YgMXN0IFF1YXJ0aWxlIFBvd2VyDQpkZl9UQl9maWx0ZXJlZCA8LSBkZl9UQl9maWx0ZXJlZFtkZl9UQl9maWx0ZXJlZCRTVDU1TjYwMT49MTAxMixdICMgRmlsdGVyIGJ5IFRvcCAyNSUgb2YgTWF4aW11bSBPcGVyYXRpb25hbCBTcGVlZA0KZGZfVEJfZmlsdGVyZWQNCg0KYGBgDQoNCiMjIyBMYXJnZXN0IENvcnJlbGF0aW9uIFZhcmlhYmxlcyB3aXRoIFRCIEltYmliaXRpb24gV2F0ZXINCmBgYHtyfQ0KY29ycl92YXIoZGZfVEJfZmlsdGVyZWQsICMgZGF0YWZyYW1lIG5hbWUNCiAgSW1iVEIsICMgdGFyZ2V0DQogIG1heF9wdmFsdWUgPSAwLjA1LCAjIHNpZ25pZmljYW5jZSBsZXZlbA0KICB0b3AgPSAxNSwgIyB0b3AgbiBtb3N0IGNvcnJlbGF0ZWQgdmFyaWFibGVzIHdpdGggdGFyZ2V0DQogIHBsb3QgPSBUDQopDQoNCmBgYA0KDQoNCioqRGF5IG9mIFNlYXNvbioqDQpgYGB7cn0NCmxhYmVsX3ggPC0gIkRpYS5aYWZyYSINCmxhYmVsX3kgPC0gIkltYlRCIg0KDQptYXBhX2Rpc3BlcnNpb24obGFiZWxfeCxsYWJlbF95LGRmX1RCX2ZpbHRlcmVkKQ0KYGBgDQoNCioqNnRoIFRCIE1pbGwgU3BlZWQqKg0KYGBge3J9DQpsYWJlbF94IDwtICJTVDU1TjYwMSINCmxhYmVsX3kgPC0gIkltYlRCIg0KDQptYXBhX2Rpc3BlcnNpb24obGFiZWxfeCxsYWJlbF95LGRmX1RCX2ZpbHRlcmVkKQ0KYGBgDQoNCioqMXN0IFRCIE1pbGwgUG93ZXIqKg0KYGBge3J9DQpsYWJlbF94IDwtICJKVDU1TjEwMSINCmxhYmVsX3kgPC0gIkltYlRCIg0KDQptYXBhX2Rpc3BlcnNpb24obGFiZWxfeCxsYWJlbF95LGRmX1RCX2ZpbHRlcmVkKQ0KYGBgDQoNCioqU3VnYXIgQ2FuZSBGaWJlciBDb250ZW50IFRhbmRlbSBCKioNCmBgYHtyfQ0KbGFiZWxfeCA8LSAiWC4uRmlicmEuQ29yZS5UQiINCmxhYmVsX3kgPC0gIkltYlRCIg0KDQptYXBhX2Rpc3BlcnNpb24obGFiZWxfeCxsYWJlbF95LGRmX1RCX2ZpbHRlcmVkKQ0KYGBgDQoNCiMjIyBJbWJpYml0aW9uIFdhdGVyIFRCIExpbmVhciBNb2RlbA0KYGBge3J9DQpsbV9JbWJUQiA9IGxtKEltYlRCIH4gRGlhLlphZnJhICsgU1Q1NU42MDEgKyBUUTU1TjEwMV9zdGRldiArIEpUNTVOMTAxX3N0ZGV2ICsgY2HDsWEubW9saWRhLnRiLCBkYXRhID0gZGZfVEJfZmlsdGVyZWQpICNDcmVhdGUgdGhlIGxpbmVhciByZWdyZXNzaW9uDQpzdW1tYXJ5KGxtX0ltYlRCKQ0KYGBgDQoNCiMjIyBJbWJpYml0aW9uIFdhdGVyIFRCIExpbmVhciBNb2RlbCBUZXN0DQoNCmBgYHtyfQ0KIyBhcHBseWluZyBmaXR0ZWQgdmFsdWVzIHRvIFRCIGRhdGEgZnJhbWUNCmRmX1RCX2ZpbHRlcmVkJGZpdHRlZDwtIGxtX0ltYlRCJGZpdHRlZC52YWx1ZXMNCg0KIyBjcmVhdGluZyBnZ3Bsb3Qgb2JqZWN0IGZvciB2aXN1YWxpemF0aW9uDQpsbV9JbWJUQl9wbG90IDwtIGdncGxvdChkZl9UQl9maWx0ZXJlZCwgYWVzKHg9IERpYS5aYWZyYSwgeT0gSW1iVEIsY29sb3VyPSJyZWFsIHZhbHVlcyIpKSArDQogIGdlb21fcG9pbnQoKSArDQogIGdlb21fbGluZShhZXMoeT0gZml0dGVkLCBjb2xvdXI9ImZpdHRlZCB2YWx1ZXMiKSkgKw0KICBzY2FsZV9jb2xvcl9tYW51YWwobmFtZSA9ICJJbWJpYml0aW9uIFdhdGVyIFRCIiwgdmFsdWVzID0gYygiZml0dGVkIHZhbHVlcyIgPSAiZGFya2JsdWUiLCAicmVhbCB2YWx1ZXMiID0gInJlZCIpKQ0KDQpwcmludChsbV9JbWJUQl9wbG90KQ0KDQpgYGANCg0K