[2] Study of the
variables
(I) We study the absolute and relative frequency of the
qualitative variables “city”, “year” and “month”
# Here and in the following we use the package *DT* for the better rendering of the tables.
Freq_ass_city = table(dataset["city"])
Freq_rel_city = table(dataset["city"])/N_observations
Freq_city = cbind(Freq_ass_city,Freq_rel_city)
datatable(t(Freq_city), caption = 'Absolute and Relative frequency of the cities in the dataset')
Freq_ass_year = table(dataset["year"])
Freq_rel_year = table(dataset["year"])/N_observations
Freq_year = cbind(Freq_ass_year, Freq_rel_year)
datatable(t(Freq_year), caption = 'Absolute and Relative frequency of the years in the dataset')
Freq_ass_month = table(dataset["month"])
Freq_rel_month = round(table(dataset["month"])/N_observations,2)
Freq_month = cbind(Freq_ass_month,Freq_rel_month)
datatable(t(Freq_month), options = list(pageLength = 12), caption = 'Absolute and Relative frequency of the months in the dataset')
We observe that the variables “city”, “year”, and “month” are
uniformly distributed, and thus they exhibit multimodal
distributions.
[5] In particular,
the probability that a random line of the dataset corresponds to:
- the city of “Beaumont” is P(“Beaumont”)=0.25.
- the month of “July” is P(“July”)~=0.08.
- “December 2012” is P(“December 2012”)= P(“December”) x P(“2012”) =
0.08 x 0.2 ~= 0.16.
(II) Next, we study the quantitative
variables:
- “sales”,
- “volume”,
- “median_price”,
- “listings”
- “month_inventory”
We summarize in a table a description of these variables via the main
indices of shape, position and variability. We also compare graphically
their normalized distribution against a normal distribution.
cv_funct <- function(x) {
return(sd(x) / mean(x) * 100)
}
kurtosis_index <- function(x) {
return(kurtosis(x)-3)
}
sub_data <- dataset[c("sales","volume","median_price","listings","months_inventory")]
statistics <- data.frame(
quartile_1 = round(apply(sub_data, 2, function(x) quantile(x,probs=0.25, names=FALSE)),2),
median = round(apply(sub_data, 2, median),2),
quartile_3 = round(apply(sub_data, 2, function(x) quantile(x,probs=0.75, names=FALSE)),2),
mean = round(apply(sub_data, 2, mean),2),
sd = round(apply(sub_data, 2, sd),2),
cv = round(apply(sub_data, 2, cv_funct),2),
skewness = round(apply(sub_data, 2, skewness),2),
kurtosis = round(apply(sub_data, 2, kurtosis_index),2)
)
## FOR A BETTER VISUALIZATION OF THE TABLES WE USE THE PACKAGE "DT" (https://rstudio.github.io/DT/)
datatable(statistics, caption="Indices of position, variability and form of the quantitative variables in the datset")
# the function normalize takes in input a variable in string form and returns its values normalized by its mean and standard deviation
normalize <- function(variable){
return ((dataset[[variable]]-statistics[variable, "mean"])/statistics[variable, "sd"])
}
# we generate a standard normal distribution
gaussian_distribution <- rnorm(100000,0,1)
# we plot the density of the different variables against a standard normal distribution
ggplot()+
geom_density(aes(x=gaussian_distribution, fill="N01"), color=NA, alpha=.8)+
geom_density(aes(x=normalize("sales"), color="sales"), linewidth=1.5)+
geom_density(aes(x=normalize("volume"), color="volume"), linewidth=1.5)+
geom_density(aes(x=normalize("median_price"), color= "median_price"), linewidth=1.5)+
geom_density(aes(x=normalize("listings"), color="listings"), linewidth=1.5)+
geom_density(aes(x=normalize("months_inventory"), color="months_inventory"), linewidth=1.5)+
labs(title="Distribution of the variables",
x="Normalized variable ",
y="density")+
scale_fill_manual(values = c(N01 = "grey"),
labels = c(N01 = "N(0,1)")) +
theme_classic()+
theme(plot.title.position = "panel",
plot.title=element_text(hjust=0.5))+
guides(fill = guide_legend(override.aes = list(color = NA)))+
labs(color = "Variabile",
fill = "Distribuzione normale")

[3] From the
previous analysis we can observe that the variables “volume” and
“median_price” are the ones with the highest and smallest variability
having the largest and smallest coefficient of variation, respectively.
Similarly “volume” is also the most asymmetric variable having the
highest absolute value of the Fisher skewness coefficient, differently
the least asymmetric variable is “months_inventory”.
The values of the Fisher skewness coefficients and kurtosis
demonstrate that none of the variables follow an exact normal
distribution, suggesting different distributions of the variables based
on the different cities and/or periods.
However, as we can see from the plot and the values of skewness in
the table, all the variable, except the median_price, are more densely
concentrated close to the mean on the mean left and more sparsely
distributed on the mean right.
Finally by looking at the kurtosis, we observe that all the
variables, except the volume, have tails decaying faster than the
Gaussian distribution, so the probability of observing outliers far from
the mean will be lower than the probability that we would have by
considering a normal distribution with same mean and standard
deviation.
[4] Creation of classes for
quantitative variables
In this section we divide the variable median_price in classes to
study how its distribution varies across the different cities.
First we create the classes each corresponding to a range of 10000$,
assign each data to the corresponding class and study the distribution
frequency of each class.
cat("min median_price:", min(dataset$median_price), "\n")
min median_price: 73800
cat("max median_price:", max(dataset$median_price))
max median_price: 180000
#given the minium and maximum median_price value we create classes of 10000$ each and assign each data to the corresponding class.
breaking_points <- seq(70, 180, by=10)
breaking_points_labels <- paste0("[", breaking_points[-length(breaking_points)], "K, ", breaking_points[-1], "K)")
dataset$median_price_CL <- cut(dataset$median_price,
breaks=seq(from = 70000, to = 180000, by = 10000))
levels(dataset$median_price_CL) <- breaking_points_labels
freq_ass_median_price <- table(dataset$median_price_CL)
freq_rel_median_price <- round(freq_ass_median_price/N_observations,2)
datatable(cbind(freq_ass_median_price, freq_rel_median_price))
Next, we compute the Gini heterogeneity index of the median_price
class variable over the entire dataset and separately for each city.
gini.index <- function(x){
ni = table(x)
fi = ni/length(x)
fi2 = fi^2
J = length(table(x))
gini = 1-sum(fi2)
gini.norm = gini/((J-1)/J)
return(gini.norm)
}
cat(sprintf("The Gini heterogeneity index of the classes of median price over the entrie dataset is: %f \n", gini.index(dataset$median_price_CL)))
The Gini heterogeneity index of the classes of median price over the entrie dataset is: 0.958604
for (cit in unique(dataset$city)){
city_dataset <- dataset %>%
filter(city==cit)
cat(sprintf("The Gini heterogeneity index of the classes of median price relative to the city of %s is: %f \n", cit, gini.index(city_dataset$median_price_CL)))
}
The Gini heterogeneity index of the classes of median price relative to the city of Beaumont is: 0.779778
The Gini heterogeneity index of the classes of median price relative to the city of Bryan-College Station is: 0.754722
The Gini heterogeneity index of the classes of median price relative to the city of Tyler is: 0.789556
The Gini heterogeneity index of the classes of median price relative to the city of Wichita Falls is: 0.828056
Last we visualize the frequency distribution via a barplot.
ggplot(data=dataset)+
geom_bar(aes(x=median_price_CL),
stat="count",
col="black",
fill="orange")+
labs(title="Distribution of the classes of median_price",
x="median price in classes",
y="absolute frequency")+
scale_y_continuous(breaks = seq(0,60,10))+
theme_classic()+
theme(axis.text.x = element_text(angle = 15, hjust = 1),
axis.title.x = element_text(size = 14, margin = margin(t = 10)),
axis.title.y = element_text(size = 14, margin = margin(r = 10)))

Last we visualize the frequency distribution via a barplot across the
different cities.
#for a better visualization of the frequency across the different cities we create a dataset where we count the frequency of each class for each city and we fill the dataset with observations having count=0 for each city and class of price that have no intersection
dataset_complete <- dataset %>%
count(median_price_CL, city)
for (cit in unique(dataset$city)){
for (class in unique(dataset$median_price_CL)){
filtered <- dataset_complete %>%
filter(city == cit, median_price_CL == class)
if (nrow(filtered) == 0){
dataset_complete <- rbind(dataset_complete, data.frame(city=cit, median_price_CL=class, n=0))
}
}
}
# next we visualize via a bar plot the distribution of classes of price across the different cities
ggplot(data=dataset_complete)+
geom_col(aes(x=median_price_CL,
y=n,
fill=city),
position="dodge2", #dodge, #fill, #stack
stat="identity",
col="black")+
labs(title="Distribuzione delle classi della mediana di prezzo",
x="median price in classes",
y="absolute frequency")+
scale_y_continuous(breaks = seq(0,60,10))+
theme_classic()+
theme(axis.text.x = element_text(angle = 15, hjust = 1),
axis.title.x = element_text(size = 14, margin = margin(t = 10)),
axis.title.y = element_text(size = 14, margin = margin(r = 10)),
legend.position ="bottom")

The Gini heterogeneity index close to 1 and the bar plots of the
distribution indicate that the dataset is distributed discreetly
uniformly across the different median-price classes.
The distribution of the data relative to the different cities across
the classes of price is significantly less uniform, as reflected both by
lower values of the Gini index and the bar plot relative to the
different cities.
Specifically, we observe that the prices in Wichita Falls are
generally lower than those of Beaumont which are smaller than those of
Tyler which are finally generally smaller than those of Bryan-College
Station.
We finally include a boxplot of the distribution of median_price
across the different cities to quantify the variability of the median
price for each city.
ggplot(data=dataset,
aes(x=city,
y=median_price,
fill=city))+
geom_boxplot()+
geom_hline(yintercept = statistics["median_price","quartile_3"], color = "red")+
geom_hline(yintercept = statistics["median_price","quartile_1"], color = "red")+
geom_hline(yintercept = statistics["median_price","mean"], color = "red")+
labs(title="Comparison of median_price by city",
x="city",
y="US$")+
annotate("label", x = Inf, y = statistics["median_price","quartile_1"],
label = "1°quartile median_price",
hjust = 1.1,
vjust = +.5,
fill="grey",
color = "red")+
annotate("label", x = Inf, y = statistics["median_price","median"],
label = "median median_price",
hjust = 1.1, vjust = +.5,
fill="grey",
color = "red")+
annotate("label", x = Inf, y = statistics["median_price","quartile_3"],
label = "3° quartile median_price",
hjust = 1.1,
vjust = +.5,
fill="grey",
color = "red")+
theme_classic()+
scale_x_discrete(expand = expansion(add = c(.5, 2)))+
scale_y_continuous(breaks = seq(70000, 180000, by=10000),
labels = paste0(breaking_points, "K"))+
theme(plot.title.position = "panel",
plot.title = element_text(size=16, hjust=0.5),
axis.title.x = element_text(size=14),
axis.title.y = element_text(size=14),
axis.text.x = element_text(size=10),
axis.text.y = element_text(size=10),
legend.position ="bottom")

We can observe that the median price in different cities exhibits
similar variability, measured in terms of interquartile range, and
significantly lower variability than that found by considering all the
cities together. This is due to the fact that the median price range
differs significantly from city to city.
[6] Creation of new
variables
We create three new varibales measuring the mean selling price in US
dollars, the effectiveness of the sales ads and the date measured in
moths from January 2010.
- The variable mean_price is obtained as \(10^6\)(volume/sales).
- The variable effectiveness is obtained as
(listings/months_inventory) which measures the average
monthly sales rate of the properties listed in a city in a given
month/year.
- The variable date which returns the date of each data in
months from january 2010, this is obtained as \(month+12(mod(year,2010))\).
dataset$mean_price <- (volume/sales)*10^6
dataset$effectiveness <- (listings/months_inventory)
dataset$date <- (as.numeric(as.character(month)))+12*(as.numeric(as.character(year))%%(min(as.numeric(as.character(year)))))
Next we study the trend of the quantitative variables over time.
# We use the package *patchwork* in combination with *ggplot2* to provide a cumulative significant representation of all the quantitative variables in a single multi-panel figure
# We also use the package *ggpubr* to extract the legend from a figure and print it as a unique legend for all the plots.
# The function month_convert convert a number between 1 and 12 into a string indicating the corresponding month.
month_convert <- function(x){
x_n=as.numeric(as.character(x))
months=c("Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec")
return(months[x_n])
}
# The function breaking_points takes in input a vector of dates expressed months and convert in vector of dates expressed as month+year.
# This will be used to produce the x-axis labels in the plots with the trend of the variables over time.
breaking_points <- function(x) {
return(paste(month_convert(dataset$month[x]), dataset$year[x], sep=" ") )
}
# We produce a first plot only to extract the legend.
line_sales <- ggplot(data=dataset)+
geom_line(aes(x = date,
y = sales,
group = city,
color = city),
size = 1.5)+
theme(legend.title = element_text(size = 18),
legend.text = element_text(size = 16))
# We extract the legend
legend_line <- as_ggplot(get_legend(line_sales))
# We produce the plot with the trend of the sales over time.
line_sales <- ggplot(data=dataset)+
geom_line(aes(x = date,
y = sales,
group = city,
color = city),
size = 1.5)+
geom_point(aes(x = date,
y = sales,
group = city,
color = city),
size = 3)+
labs(title="Comparison of sales by time for the different cities",
x="time",
y="sales")+
scale_x_continuous(breaks = (seq(1,60, by = 6)),
labels = breaking_points)+
theme_classic()+
theme(plot.title.position = "panel",
plot.title = element_text(size=18, hjust=0.5),
axis.title.x = element_text(size=16),
axis.title.y = element_text(size=16),
axis.text.x = element_text(size=10),
axis.text.y = element_text(size=10),
legend.position = "none")
# We produce the plot with the trend of the volume over time.
line_volume <- ggplot(data=dataset)+
geom_line(aes(x = date,
y = volume,
group = city,
color = city),
size = 1.5)+
geom_point(aes(x = date,
y = volume,
group = city,
color = city),
size = 3)+
labs(title="Comparison of volume by time for the different cities",
x="time",
y="volume")+
scale_x_continuous(breaks = (seq(1,60, by = 6)),
labels = breaking_points)+
theme_classic()+
theme(plot.title.position = "panel",
plot.title = element_text(size=18, hjust=0.5),
axis.title.x = element_text(size=16),
axis.title.y = element_text(size=16),
axis.text.x = element_text(size=10),
axis.text.y = element_text(size=10),
legend.position = "none")
# We produce the plot with the trend of the median_price over time.
line_price <- ggplot(data=dataset)+
geom_line(aes(x = date,
y = median_price,
group = city,
color = city),
size = 1.5)+
geom_point(aes(x = date,
y = median_price,
group = city,
color = city),
size = 3)+
labs(title="Comparison of median price by time for the different cities",
x="time",
y="median price")+
scale_x_continuous(breaks = (seq(1,60, by = 6)),
labels = breaking_points)+
theme_classic()+
theme(plot.title.position = "panel",
plot.title = element_text(size=18, hjust=0.5),
axis.title.x = element_text(size=16),
axis.title.y = element_text(size=16),
axis.text.x = element_text(size=10),
axis.text.y = element_text(size=10),
legend.position = "none")
# We produce the plot with the trend of the listings over time.
line_listings <- ggplot(data=dataset)+
geom_line(aes(x = date,
y = listings,
group = city,
color = city),
size = 1.5)+
geom_point(aes(x = date,
y = listings,
group = city,
color = city),
size = 3)+
labs(title="Comparison of listings by time for the different cities",
x="time",
y="listings")+
scale_x_continuous(breaks = (seq(1,60, by = 6)),
labels = breaking_points)+
theme_classic()+
theme(plot.title.position = "panel",
plot.title = element_text(size=18, hjust=0.5),
axis.title.x = element_text(size=16),
axis.title.y = element_text(size=16),
axis.text.x = element_text(size=10),
axis.text.y = element_text(size=10),
legend.position = "none")
# We produce the plot with the trend of the months_inventory over time.
line_inventory <- ggplot(data=dataset)+
geom_line(aes(x = date,
y = months_inventory,
group = city,
color = city),
size = 1.5)+
geom_point(aes(x = date,
y = months_inventory,
group = city,
color = city),
size = 3)+
labs(title="Comparison of months inventory by time for the different cities",
x="time",
y="months inventory")+
scale_x_continuous(breaks = (seq(1,60, by = 6)),
labels = breaking_points)+
theme_classic()+
theme(plot.title.position = "panel",
plot.title = element_text(size=18, hjust=0.5),
axis.title.x = element_text(size=16),
axis.title.y = element_text(size=16),
axis.text.x = element_text(size=10),
axis.text.y = element_text(size=10),
legend.position = "none")
# We combine all the above plots and the label in one figure.
comb_lines_fig = line_sales + line_volume + line_price + line_listings + line_inventory + legend_line + plot_layout(ncol=2, heights = c(5, 5, 5))
print(comb_lines_fig)

# We close all the plots created above.
rm(line_sales, line_volume, line_price, line_listings, line_inventory, legend_line, comb_lines_fig)
From the last plots we observe:
A periodic trend in almost all the variables, with the exception
of the median_price. In particular, higher sales, volume, listings and
month inventory are observed in the summer rather than in the winter.
The difference between summer and winter is well marked in the cities of
Tyler and Bryan-College Station while almost imperceptible in the city
of Wichita Falls.
It is also possible to observe that, in average, the listings and
months inventory are decreasing over the year while sales, volume and
median price are increasing. Also in this case, the city of Wichita
Falls is the one where this phenomenon is less evident.
We study deeper and quantify these phenomena, and other that can be
observed in the plots, in the following of this report.
[7] Analysis of the
variables based on cities, years and months
First we provide a statistical analysis of the quantitative
variables, computing their mean, standard deviation and variation
coefficient, based on cities and year.
We summarize the results in the tables below and represent the
results graphically by bar plots and box plots.
The 1st table studies the statistics of the variables over the
different cities
# we use the package dplyr to conduct conditioned statistical analysis by city and year.
conditional_dataset_city <-
dataset %>%
group_by(city) %>%
summarise(mean_sales = round(mean(sales),2),
sd_sales = round(sd(sales),2),
cv_sales = round(cv_funct(sales), 2),
mean_volume=round(mean(volume),2),
sd_volume=round(sd(volume),2),
cv_volume = round(cv_funct(volume), 2),
mean_med_price=round(mean(median_price),2),
sd_med_price=round(sd(median_price),2),
cv_med_price = round(cv_funct(median_price), 2),
mean_mean_price=round(mean(mean_price),2),
sd_mean_price=round(sd(mean_price),2),
cv_mean_price = round(cv_funct(mean_price), 2),
mean_listings=round(mean(listings),2),
sd_listings=round(sd(listings),2),
cv_listings = round(cv_funct(listings), 2),
mean_inventory=round(mean(months_inventory),2),
sd_inventory=round(sd(months_inventory),2),
cv_inventory = round(cv_funct(months_inventory), 2),
mean_effectivness=round(mean(effectiveness),2),
sd_effectiveness=round(sd(effectiveness),2),
cv_effectiveness = round(cv_funct(effectiveness), 2),
)
df_t <- as.data.frame(t(conditional_dataset_city[2:dim(conditional_dataset_city)[2]]))
colnames(df_t) = conditional_dataset_city$city
datatable(df_t, options = list(pageLength = 21), caption="Statistical analysis of the dataset based on city")
The 2nd table studies the statistics of the variables over the
different year
conditional_dataset_year <- dataset %>%
group_by(year) %>%
summarise(mean_sales = round(mean(sales),2),
sd_sales = round(sd(sales),2),
cv_sales = round(cv_funct(sales), 2),
mean_volume=round(mean(volume),2),
sd_volume=round(sd(volume),2),
cv_volume = round(cv_funct(volume), 2),
mean_med_price=round(mean(median_price),2),
sd_med_price=round(sd(median_price),2),
cv_med_price = round(cv_funct(median_price), 2),
mean_mean_price=round(mean(mean_price),2),
sd_mean_price=round(sd(mean_price),2),
cv_mean_price = round(cv_funct(mean_price), 2),
mean_listings=round(mean(listings),2),
sd_listings=round(sd(listings),2),
cv_listings = round(cv_funct(listings), 2),
mean_inventory=round(mean(months_inventory),2),
sd_inventory=round(sd(months_inventory),2),
cv_inventory = round(cv_funct(months_inventory), 2),
mean_effectivness=round(mean(effectiveness),2),
sd_effectiveness=round(sd(effectiveness),2),
cv_effectiveness = round(cv_funct(effectiveness), 2),
)
df_t <- as.data.frame(t(conditional_dataset_year[2:dim(conditional_dataset_year)[2]]))
colnames(df_t) = conditional_dataset_year$year
datatable(df_t, options = list(pageLength = 21), caption="Statistical analysis of the dataset based on year")
# We create a dataset where we conduct a statistical analysis conditioned both to city and year, so varying only the months, for each couple (city,year) we compute the total amount of sales volume and listings and the median months_inventory, median price and effectiveness varying the months
conditional_dataset_city_year <- dataset %>%
group_by(year, city) %>%
summarise(sales = sum(sales),
volume = sum(volume),
listings = sum(listings),
median_months_inventory=median(months_inventory),
median_median_price=median(median_price),
median_effectiveness=median(effectiveness)
)
The next plot visualizes the total sales and volume over the years
and cities
# We create barplots to visualize the total sales and volume over the years and cities
# The next plot is created only to extrapolate the legend
bar_sales_year <- ggplot(data=conditional_dataset_city_year,
aes(x=year,
y=sales,
fill=city))+
geom_col(stat="identity",
position="stack")+
theme(legend.title = element_text(size = 16),
legend.text = element_text(size = 14))
#extrapolate the legend
legend_city <- as_ggplot(get_legend(bar_sales_year))
##
##
##
#barplot with the total sales over years and cities
bar_sales_year <- ggplot(data=conditional_dataset_city_year,
aes(x=year,
y=sales,
fill=city))+
geom_col(stat="identity",
position= "dodge")+
labs(title="Comparison of total sales by year over city",
x="year",
y="Number of sales")+
theme_classic()+
theme(plot.title.position = "panel",
plot.title = element_text(size=16, hjust=0.5),
axis.title.x = element_text(size=14),
axis.title.y = element_text(size=14),
axis.text.x = element_text(size=10),
axis.text.y = element_text(size=10),
legend.position = "none")+
scale_y_continuous(breaks = seq(0, 4000, by = 250))
##
##
##
#barplot with the total volume over years and cities
bar_volume_year <- ggplot(data=conditional_dataset_city_year,
aes(x=year,
y=volume,
fill=city))+
geom_col(stat="identity",
position="dodge")+
labs(title="Comparison of total volume by year over city",
x="year",
y="US$")+
theme_classic()+
theme(plot.title.position = "panel",
plot.title = element_text(size=16, hjust=0.5),
axis.title.x = element_text(size=14),
axis.title.y = element_text(size=14),
axis.text.x = element_text(size=10),
axis.text.y = element_text(size=10),
legend.position = "none")+
scale_y_continuous(breaks = seq(0, 700, by = 50),
labels = label_number(suffix = "M"))
##
##
##
#combine the two plots in one figure and display it.
comb_fig_2 <- bar_sales_year + bar_volume_year + legend_city + plot_layout(ncol=3, widths = c(5, 5, 3), heights = c(5))
print(comb_fig_2)

The next plot visualizes how the sales and volume are distributed in
percentage with respect to the cities over the years.
# We create barplots to visualize how the sales and volume, over the years, are distributed in percentage across the cities
#barplot with the percentage sales over cities, varying the years
bar_sales_year_2 <- ggplot(data=conditional_dataset_city_year,
aes(x=year,
y=sales,
fill=city))+
geom_col(stat="identity",
position= "fill")+
labs(title="Comparison of total sales by year over city",
x="year",
y="sales")+
theme_classic()+
theme(plot.title.position = "panel",
plot.title = element_text(size=16, hjust=0.5),
axis.title.x = element_text(size=14),
axis.title.y = element_text(size=14),
axis.text.x = element_text(size=10),
axis.text.y = element_text(size=10),
legend.position = "none")+
scale_y_continuous(labels = percent_format(),
breaks = seq(0, 1, by = 0.1))
##
##
##
#barplot with the percentage volume over cities, varying the years
bar_volume_year_2 <- ggplot(data=conditional_dataset_city_year,
aes(x=year,
y=volume,
fill=city))+
geom_col(stat="identity",
position="fill")+
labs(title="Comparison of total volume by year over city",
x="year",
y="volume")+
theme_classic()+
theme(plot.title.position = "panel",
plot.title = element_text(size=16, hjust=0.5),
axis.title.x = element_text(size=14),
axis.title.y = element_text(size=14),
axis.text.x = element_text(size=10),
axis.text.y = element_text(size=10),
legend.position = "none")+
scale_y_continuous(labels = percent_format(),
breaks = seq(0, 1, by = 0.1))
#combine the two plots in one figure and display it.
comb_fig_2_5 <- bar_sales_year_2 + bar_volume_year_2 + legend_city + plot_layout(ncol=3, widths = c(5, 5, 3), heights = c(5))
print(comb_fig_2_5)

The next plot visualizes the evolution of listings and month
inventory by years and cities
# We study the evolution of listings and month inventory over the years and varying the cities. We study the listing by means of a barplot and month inventory by means of a box plot.
# The next plot is created only to extrapolate the legend
bar_listings_city <- ggplot(data=conditional_dataset_city_year,
aes(x=city,
y=listings,
fill=year))+
geom_col(stat="identity",
position= "dodge")+
scale_fill_manual(values = c("2010" = "lightblue1",
"2011" = "lightblue2",
"2012" = "lightblue3",
"2013" = "lightblue4",
"2014" = "#374A59"
))
legend_year <- as_ggplot(get_legend(bar_listings_city))
#barplot with the total number of listings varying the years and cities
bar_listings_city <- ggplot(data=conditional_dataset_city_year,
aes(x=city,
y=listings,
fill=year))+
geom_col(stat="identity",
position= "dodge")+
labs(title="Comparison of total listings by city over year",
x="city",
y="listings")+
theme_classic()+
theme(plot.title.position = "panel",
plot.title = element_text(size=16, hjust=0.5),
axis.title.x = element_text(size=14),
axis.title.y = element_text(size=14),
axis.text.x = element_text(size=10),
axis.text.y = element_text(size=10),
legend.position = "none")+
scale_fill_manual(values = c("2010" = "lightblue1",
"2011" = "lightblue2",
"2012" = "lightblue3",
"2013" = "lightblue4",
"2014" = "#374A59"
))+
scale_y_continuous(breaks = seq(0, 35000, by = 2500),
labels = paste0(seq(0,350, by=25),"K"))
##
##
##
#boxplot to study the statistics of month_inventory varying the years and cities
box_inventory_city <- ggplot(data=dataset,
aes(x=city,
y=months_inventory,
fill=year))+
geom_boxplot()+
labs(title="Comparison of months inventory by city over year",
x="city",
y="months_inventory")+
theme_classic()+
theme(plot.title.position = "panel",
plot.title = element_text(size=16, hjust=0.5),
axis.title.x = element_text(size=14),
axis.title.y = element_text(size=14),
axis.text.x = element_text(size=10),
axis.text.y = element_text(size=10),
legend.position = "none")+
scale_fill_manual(values = c("2010" = "lightblue1",
"2011" = "lightblue2",
"2012" = "lightblue3",
"2013" = "lightblue4",
"2014" = "#374A59"
))+
scale_y_continuous(breaks = seq(4, 14, by = 2))
#combine the two plots in one figure and display it.
comb_fig_3 <- bar_listings_city + box_inventory_city + legend_year + plot_layout(ncol=3, widths = c(5, 5, 1), heights = c(5))
print(comb_fig_3)

The next plot visualizes the evolution of the selling median price
and selling efficiency over the years and cities
# We study the evolution of median prices and efficiency over the years and varying the cities by means of boxplots.
#boxplot representing the statistics of the selling median price varying the years and cities
box_price_year <- ggplot()+
geom_line(data = conditional_dataset_city_year,
aes(x = year, y = median_median_price, group = city,
color = city),
position = position_dodge(width = 0.75)) +
geom_boxplot(data=dataset,
aes(x=year,
y=median_price,
fill=city))+
labs(title="Comparison of median price by year over city",
x="year",
y="median price US$")+
theme_classic()+
theme(plot.title.position = "panel",
plot.title = element_text(size=16, hjust=0.5),
axis.title.x = element_text(size=14),
axis.title.y = element_text(size=14),
axis.text.x = element_text(size=10),
axis.text.y = element_text(size=10),
legend.position = "none")+
scale_y_continuous(breaks = seq(75000, 175000, by = 10000),
labels= paste0(seq(75, 175, by = 10),"K"))
# boxplot representing the statistics of selling efficiency varying the years and cities
box_effectiveness_year <- ggplot()+
geom_line(data = conditional_dataset_city_year,
aes(x = year, y = median_effectiveness, group = city, color = city),
position = position_dodge(width = 0.75)) +
geom_boxplot(data=dataset,
aes(x=year,
y=effectiveness,
fill=city))+
labs(title="Comparison of effectiveness by year over city",
x="year",
y="effectiveness")+
theme_classic()+
theme(plot.title.position = "panel",
plot.title = element_text(size=16, hjust=0.5),
axis.title.x = element_text(size=14),
axis.title.y = element_text(size=14),
axis.text.x = element_text(size=10),
axis.text.y = element_text(size=10),
legend.position = "none")+
scale_y_continuous(breaks = seq(0, 350, by = 25))
#combine the two plots in one figure and display it.
comb_fig_4 <- box_price_year + box_effectiveness_year + legend_city + plot_layout(ncol=3, widths = c(5, 5, 3), heights = c(5))
print(comb_fig_4)

#We close all the figures generated above
rm(bar_sales_year, bar_volume_year, legend_city, bar_listings_city, box_inventory_city, legend_year, box_price_year, box_effectiveness_year, bar_sales_year_2, bar_volume_year_2, comb_fig_2, comb_fig_2_5, comb_fig_3, comb_fig_4)
From the results above we observe that:
Tyler is the city with more sales and volume as also the city
where the sales ads are more efficient followed by Brian-College
Station, Beaumont and Wichita Falls in descending order.
The median price is higher in Brian-College Station followed by
Tyler and Beaumont and finally by Wichita Falls.
Tyler is also city with the highest number of listings and months
inventory followed by Beaumont, Bryan-College Station and Wichita
Falls.
About the variability of the variables we observe that:
The relative variability (measured in terms of the coefficient of
variation) in the volume and sales in Tyler is between 1.5 and 3 times
higher than the variability that we observe in the other
cities.
Bryan-College Station faces a variability in the listings and
month inventory that is almost twice or more the variability in the
other cities.
Finally Wichita Falls is the city with the highest variability in
the median and mean prices. However the variability in the median prices
is quite small for all the cities.
The graphs confirm a change in the trend of the variables and
so of the real estate market after 2011. On the one hand, we observe an
increase in the number of sales, volume, median price, and efficiency;
on the other hand the number of listings and monthly inventory
decreases. The only city that doesn’t seem to follow these trends is
Wichita Falls, where the situation doesn’t seem to be changing over the
years. We do not observe significant differences in the
variability of the variables over the year.
Next we conduct a statistical study about the variability and trends
of the different variables over the months.
# next we conduct a statistical analysis conditioned both to the months
conditional_dataset_month <-
dataset %>%
group_by(month) %>%
summarise(mean_sales = round(mean(sales),2),
sd_sales = round(sd(sales),2),
cv_sales = round(cv_funct(sales), 2),
mean_volume=round(mean(volume),2),
sd_volume=round(sd(volume),2),
cv_volume = round(cv_funct(volume), 2),
mean_med_price=round(mean(median_price),2),
sd_med_price=round(sd(median_price),2),
cv_med_price = round(cv_funct(median_price), 2),
mean_mean_price=round(mean(mean_price),2),
sd_mean_price=round(sd(mean_price),2),
cv_mean_price = round(cv_funct(mean_price), 2),
mean_listings=round(mean(listings),2),
sd_listings=round(sd(listings),2),
cv_listings = round(cv_funct(listings), 2),
mean_inventory=round(mean(months_inventory),2),
sd_inventory=round(sd(months_inventory),2),
cv_inventory = round(cv_funct(months_inventory), 2),
mean_effectivness=round(mean(effectiveness),2),
sd_effectiveness=round(sd(effectiveness),2),
cv_effectiveness = round(cv_funct(effectiveness), 2),
)
df_t <- as.data.frame(t(conditional_dataset_month[2:dim(conditional_dataset_month)[2]]))
colnames(df_t) <- c("Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec")
datatable(df_t, options = list(scrollX = TRUE, pageLength = 21), caption="Statistical analysis of the dataset based on month")
The table reflect a periodic trend of all the variables along
the year, having:
- More sales, volume and listings and higher month inventory
during the summer with respect to the winter.
The variables effectiveness and median/mean price are the only ones
that seem not to be affected by this periodic trend.
To capture these periodic trends we study the monthly variation (in
percentage) of the variables with respect to their mean.
# the function format_percentage writes in percentage format the values that we provide
format_percentage <- function(values) {
percent_values <- round(values * 100, 2)
sign_values <- ifelse(percent_values > 0, paste0("+", percent_values), as.character(percent_values))
paste0(sign_values, "%")
}
# next a dates is created where we report the percentage variation of the variables over the months with respect to their mean
conditional_dataset_month_percentages <- data.frame(sales = format_percentage((conditional_dataset_month$mean_sales-statistics["sales","mean"]) / statistics["sales","mean"]),
volume = format_percentage((conditional_dataset_month$mean_volume-statistics["volume","mean"]) / statistics["volume","mean"]),
median_price = format_percentage((conditional_dataset_month$mean_med_price-statistics["median_price","mean"])/ statistics["median_price","mean"]),
listings = format_percentage((conditional_dataset_month$mean_listings-statistics["listings","mean"]) / statistics["listings","mean"]),
month_inventory=format_percentage((conditional_dataset_month$mean_inventory-statistics["months_inventory","mean"])/statistics["months_inventory","mean"])
)
rownames(conditional_dataset_month_percentages) <- c("Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec")
datatable(conditional_dataset_month_percentages, options = list(scrollX = TRUE, pageLength = 21), caption="Variation of the monthly mean of the variables compared to their mean value")
Last, we study the variability of the sales, volume and listings both
over the months and across different cities. We present the results via
bar plots.
# first we create a dataset where we conduct a statistical analysis conditioned both to city and month, so varying only the year
# for each couple (city,month) we compute the total amount of sales volume and listings and the median months_inventory, median price and effectiveness varying the years
conditional_dataset_city_month <- dataset %>%
group_by(month, city) %>%
summarise(sales = sum(sales),
volume = sum(volume),
listings = sum(listings),
median_months_inventory=median(months_inventory),
median_median_price=median(median_price),
median_effectiveness=median(effectiveness)
)
#
#
# conditional_dataset_city_month$season <- sapply(conditional_dataset_city_month$month, season)
# We create barplots to visualize the periodic variations of sales, volume and listings over the months and cities
# The next plot is created only to extrapolate the legend
bar_sales_month = ggplot(data=conditional_dataset_city_month,
aes(x=month,
y=sales,
fill=city))+
geom_col(stat="identity",
position= "stack")+
labs(title="Comparison of total sales by month over city",
x="month",
y="sales")+
theme_classic()+
theme(plot.title.position = "panel",
plot.title = element_text(size=14, hjust=0.5),
axis.title.x = element_text(size=12),
axis.title.y = element_text(size=12),
axis.text.x = element_text(size=10),
axis.text.y = element_text(size=10),
legend.position = "bottom",
legend.title = element_text(size = 12),
legend.text = element_text(size = 12))
legend_month <- as_ggplot(get_legend(bar_sales_month))
# The next bar plot shows the total number of sales per month in every city
bar_sales_month = ggplot(data=conditional_dataset_city_month,
aes(x=month,
y=sales,
fill=city))+
geom_col(stat="identity",
position= "stack")+
labs(title="Comparison of total sales by month over city",
x="month",
y="sales")+
theme_classic()+
theme(plot.title.position = "panel",
plot.title = element_text(size=14, hjust=0.5),
axis.title.x = element_text(size=12),
axis.title.y = element_text(size=12),
axis.text.x = element_text(size=10),
axis.text.y = element_text(size=10),
legend.position = "none")+
scale_y_continuous(breaks = seq(0, 5000, by = 500))
# The next bar plot shows the number of sales in percentage with respect to the different cities per month
bar_sales_month_2 = ggplot(data=conditional_dataset_city_month,
aes(x=month,
y=sales,
fill=city))+
geom_col(stat="identity",
position= "fill")+
labs(title="Comparison of total sales by month over city",
x="month",
y="sales percentage")+
theme_classic()+
theme(plot.title.position = "panel",
plot.title = element_text(size=14, hjust=0.5),
axis.title.x = element_text(size=12),
axis.title.y = element_text(size=12),
axis.text.x = element_text(size=10),
axis.text.y = element_text(size=10),
legend.position = "none")+
scale_y_continuous(labels = percent_format(),
breaks = seq(0, 1, by = 0.1))
# The next bar plot shows the volume per month in every city
bar_volume_month = ggplot(data=conditional_dataset_city_month,
aes(x=month,
y=volume,
fill=city))+
geom_col(stat="identity",
position= "stack")+
labs(title="Comparison of total volume by month over city",
x="month",
y="volume US$")+
theme_classic()+
theme(plot.title.position = "panel",
plot.title = element_text(size=14, hjust=0.5),
axis.title.x = element_text(size=12),
axis.title.y = element_text(size=12),
axis.text.x = element_text(size=10),
axis.text.y = element_text(size=10),
legend.position = "none")+
scale_y_continuous(breaks = seq(0, 800, by = 50),
labels = paste0(seq(0, 800, by = 50), "M"))
# The next bar plot shows the volume in percentage with respect to the different cities per month
bar_volume_month_2 = ggplot(data=conditional_dataset_city_month,
aes(x=month,
y=volume,
fill=city))+
geom_col(stat="identity",
position= "fill")+
labs(title="Comparison of total volume by month over city",
x="month",
y="volume percentage")+
theme_classic()+
theme(plot.title.position = "panel",
plot.title = element_text(size=14, hjust=0.5),
axis.title.x = element_text(size=12),
axis.title.y = element_text(size=12),
axis.text.x = element_text(size=10),
axis.text.y = element_text(size=10),
legend.position = "none")+
scale_y_continuous(labels = percent_format(),
breaks = seq(0, 1, by = 0.1))
# The next bar plot shows the total number of listings per month in every city
bar_listings_month = ggplot(data=conditional_dataset_city_month,
aes(x=month,
y=listings,
fill=city))+
geom_col(stat="identity",
position= "stack")+
labs(title="Comparison of total listings by month over city",
x="month",
y="listings")+
theme_classic()+
theme(plot.title.position = "panel",
plot.title = element_text(size=14, hjust=0.5),
axis.title.x = element_text(size=12),
axis.title.y = element_text(size=12),
axis.text.x = element_text(size=10),
axis.text.y = element_text(size=10),
legend.position = "none")+
scale_y_continuous(breaks = seq(0, 35000, by = 5000),
labels = paste0(seq(0, 35, by = 5), "K"))
# The next bar plot shows the number of listings in percentage with respect to the different cities per month
bar_listings_month_2 = ggplot(data=conditional_dataset_city_month,
aes(x=month,
y=listings,
fill=city))+
geom_col(stat="identity",
position= "fill")+
labs(title="Comparison of total listings by month over city",
x="month",
y="listings percentage")+
theme_classic()+
theme(plot.title.position = "panel",
plot.title = element_text(size=14, hjust=0.5),
axis.title.x = element_text(size=12),
axis.title.y = element_text(size=12),
axis.text.x = element_text(size=10),
axis.text.y = element_text(size=10),
legend.position = "none")+
scale_y_continuous(labels = percent_format(),
breaks = seq(0, 1, by = 0.1))
# We combine the six plots above in 1 figure and display it
comb_fig_5 <- bar_sales_month + bar_sales_month_2 + bar_volume_month + bar_volume_month_2 + bar_listings_month + bar_listings_month_2 + legend_month + plot_spacer() + plot_layout(ncol=2, heights = c(5, 5, 5, .5))
print(comb_fig_5)

#We close all the figures and plots generated above
rm(bar_sales_month, bar_sales_month_2, bar_volume_month, bar_volume_month_2, bar_listings_month, bar_listings_month_2, legend_month, comb_fig_5)
The last studies highlight a trend in many variables over the
months:
We observe significantly higher sales and volumes in the spring
and summer months (in average +20/+30% of the annual mean) with respect
to the autumn and winter ones (-20/-30% of the annual mean).
A similar trend is observed also for the number of listings and
months inventory, however the gap over the year of these variables is
significantly less pronounced (\(\pm\)
5/10% of the annual mean).
This phenomenon is highly pronounced in the cities of Tyler and
Bryan-College Station, mildly pronounced in Beaumont, and not noticeable
in Wichita Falls.
The per-month variability of all the variables, measured in terms of
the coefficient of variation, is comparable across months.
Finally, we highlight that the sales, volume and listings of Wichita
Falls represent about 10-15% of the total during all the year, the ones
of Beaumont about 20-25% of the total and the ones in Bryan-College
Station plus Tyler stably over 60% of the total.
LS0tDQp0aXRsZTogIlRleGFzIFJlYWwgRXN0YXRlIE1hcmtldCBBbmFseXNpcyINCm91dHB1dDogaHRtbF9ub3RlYm9vaw0KLS0tDQoNCjwhLS0gVGhpcyBpcyBhbiBbUiBNYXJrZG93bl0oaHR0cDovL3JtYXJrZG93bi5yc3R1ZGlvLmNvbSkgTm90ZWJvb2suIFdoZW4geW91IGV4ZWN1dGUgY29kZSB3aXRoaW4gdGhlIG5vdGVib29rLCB0aGUgcmVzdWx0cyBhcHBlYXIgYmVuZWF0aCB0aGUgY29kZS4gIC0tPg0KDQo8IS0tIFRyeSBleGVjdXRpbmcgdGhpcyBjaHVuayBieSBjbGlja2luZyB0aGUgKlJ1biogYnV0dG9uIHdpdGhpbiB0aGUgY2h1bmsgb3IgYnkgcGxhY2luZyB5b3VyIGN1cnNvciBpbnNpZGUgaXQgYW5kIHByZXNzaW5nICpDdHJsK1NoaWZ0K0VudGVyKi4gIC0tPg0KDQoNCjwhLS0gQWRkIGEgbmV3IGNodW5rIGJ5IGNsaWNraW5nIHRoZSAqSW5zZXJ0IENodW5rKiBidXR0b24gb24gdGhlIHRvb2xiYXIgb3IgYnkgcHJlc3NpbmcgKkN0cmwrQWx0K0kqLiAtLT4NCg0KPCEtLSBXaGVuIHlvdSBzYXZlIHRoZSBub3RlYm9vaywgYW4gSFRNTCBmaWxlIGNvbnRhaW5pbmcgdGhlIGNvZGUgYW5kIG91dHB1dCB3aWxsIGJlIHNhdmVkIGFsb25nc2lkZSBpdCAoY2xpY2sgdGhlICpQcmV2aWV3KiBidXR0b24gb3IgcHJlc3MgKkN0cmwrU2hpZnQrSyogdG8gcHJldmlldyB0aGUgSFRNTCBmaWxlKS4gLS0+DQoNCjwhLS0gVGhlIHByZXZpZXcgc2hvd3MgeW91IGEgcmVuZGVyZWQgSFRNTCBjb3B5IG9mIHRoZSBjb250ZW50cyBvZiB0aGUgZWRpdG9yLiBDb25zZXF1ZW50bHksIHVubGlrZSAqS25pdCosICpQcmV2aWV3KiBkb2VzIG5vdCBydW4gYW55IFIgY29kZSBjaHVua3MuIEluc3RlYWQsIHRoZSBvdXRwdXQgb2YgdGhlIGNodW5rIHdoZW4gaXQgd2FzIGxhc3QgcnVuIGluIHRoZSBlZGl0b3IgaXMgZGlzcGxheWVkLiAtLT4NCg0KYGBge3IsIGVjaG89RkFMU0V9DQpsaWJyYXJ5KGRwbHlyKQ0KbGlicmFyeShtb21lbnRzKQ0KbGlicmFyeShnZ3Bsb3QyKQ0KbGlicmFyeShwYXRjaHdvcmspDQpsaWJyYXJ5KHNjYWxlcykNCmxpYnJhcnkoZ2dwdWJyKQ0KbGlicmFyeShEVCkNCm9wdGlvbnMod2lkdGggPSAxMDApDQpgYGANCg0KDQpgYGB7ciwgZWNobz1GQUxTRX0NCiMgSU1QT1JUIFRIRSBEQVRBU0VUDQpkYXRhc2V0IDwtIHJlYWQuY3N2KCJyZWFsZXN0YXRlX3RleGFzLmNzdiIpDQoNCmRhdGFzZXQkbW9udGggPC0gZmFjdG9yKGRhdGFzZXQkbW9udGgpDQpkYXRhc2V0JHllYXIgPC0gZmFjdG9yKGRhdGFzZXQkeWVhcikNCg0KYXR0YWNoKGRhdGFzZXQpDQpgYGANCg0KDQojIyAqKjxzcGFuIHN0eWxlPSJjb2xvcjpyZWQiPiBbMV0gPC9zcGFuPiBBbmFseXNpcyBvZiB0aGUgdmFyaWFibGVzKioNCg0KDQpUaGUgZGF0YWJhc2UgaXMgY29tcG9zZWQgb2YgMjQwIG9ic2VydmF0aW9ucyBlYWNoIG9mIDggc3RhdGlzdGljYWwgdmFyaWFibGVzIHJlbGF0aXZlIHRvIHRoZSByZWFsIGVzdGF0ZSBzYWxlcyBpbiBkaWZmZXJlbnQgcGVyaW9kcyAobW9udGgveWVhcikgYW5kIGNpdGllcyBvZiBUZXhhcy4gVGhlIHN0YXRpc3RpY2FsIHZhcmlhYmxlcyBhcmU6ICANCi0gKmNpdHkqOiBub21pbmFsIHF1YWxpdGF0aXZlIHZhcmlhYmxlIHRoYXQgY2xhc3NpZmllcyB0aGUgY2l0eSB0byB3aGljaCBlYWNoIG9ic2VydmF0aW9uIHJlZmVycy4gIA0KDQotICp5ZWFyKjogcXVhbnRpdGF0aXZlIGNvbnRpbnVlIHZhcmlhYmxlIHRvIHRyZWF0IGFzIG9yZGluYWwgcXVhbGl0YXRpdmUgdmFyaWFibGUgdGhhdCBjbGFzc2lmaWVzIHRoZSB5ZWFyIHRvIHdoaWNoIGVhY2ggb2JzZXJ2YXRpb24gcmVmZXJzLiAgDQoNCi0gKm1vbnRoKjogb3JkaW5hbCBxdWFsaXRhdGl2ZSB2YXJpYWJsZSAoY29kZWQgaW4gbnVtYmVycykgdGhhdCBjbGFzc2lmaWVzIHRoZSBtb250aCB0byB3aGljaCB0aGUgb2JzZXJ2YXRpb24gcmVmZXJzLiAgDQoNCi0gKnNhbGVzKjogYSBkaXNjcmV0ZSBxdWFudGl0YXRpdmUgdmFyaWFibGUgdGhhdCBkZXNjcmliZXMgdGhlIHRvdGFsIG51bWJlciBvZiBzYWxlcyByZWNvcmRlZCBpbiB0aGUgY2l0eSBkdXJpbmcgdGhlIG1vbnRoIG9mIHRoZSB5ZWFyLiAgDQoNCi0gKnZvbHVtZSo6IGEgY29udGludW91cyBxdWFudGl0YXRpdmUgdmFyaWFibGUgZGVzY3JpYmluZyB0aGUgdmFsdWUgb2Ygc2FsZXMgaW4gbWlsbGlvbnMgb2YgVVMgZG9sbGFycy4gIA0KDQotICptZWRpYW5fcHJpY2UqOiBhIGNvbnRpbnVvdXMgcXVhbnRpdGF0aXZlIHZhcmlhYmxlIGRlc2NyaWJpbmcgdGhlIG1lZGlhbiBzYWxlcyBwcmljZSBvZiBhIHByb3BlcnR5IGluIFVTIGRvbGxhcnMgaW4gdGhlIGNpdHkgZHVyaW5nIHRoZSBtb250aCBvZiB0aGUgeWVhci4gIA0KDQotICpsaXN0aW5ncyo6IGEgZGlzY3JldGUgcXVhbnRpdGF0aXZlIHZhcmlhYmxlIGRlc2NyaWJpbmcgdGhlIHRvdGFsIG51bWJlciBvZiBwcm9wZXJ0aWVzIGZvciBzYWxlIGluIHRoZSBjaXR5IGF0IHRoZSBtb250aCBvZiB0aGUgeWVhci4gIA0KDQotICptb250aF9pbnZlbnRvcnkqOiBhIGNvbnRpbnVvdXMgcXVhbnRpdGF0aXZlIHZhcmlhYmxlIHRoYXQgZGVzY3JpYmVzIHRoZSB0aW1lIChpbiBtb250aHMpIG5lZWRlZCB0byBzZWxsIGFsbCB0aGUgcHJvcGVydGllcyBhdmFpbGFibGUgaW4gdGhlIGNpdHkgYXQgdGhhdCBtb21lbnQgKG1vbnRoL3llYXIpLg0KDQpXZSB3aWxsIGFuYWx5emUgdGhlIHF1YW50aXRhdGl2ZSB2YXJpYWJsZXMgc3VjaCBhcyBzYWxlcywgdm9sdW1lIGFuZCBtZWRpYW5fcHJpY2Ugb3ZlciB0aW1lIHRvIGlkZW50aWZ5IGdlbmVyaWMgb3IgY2l0eS1zcGVjaWZpYyB0cmVuZHMgb2YgdGhlIG1hcmtldCwgZWl0aGVyIG1vbnRobHkgb3IgYW5udWFsbHkuDQoNClRoZSB2YXJpYWJsZXMgbGlzdGluZ3MgYW5kIG1vbnRoX2ludmVudG9yeSB3aWxsIGJlIGFsc28gc3R1ZGllZCBvdmVyIHRpbWUgYW5kIGNpdGllcyB0byBzdHVkeSB0aGUgc3BlZWQgb2YgcHJvcGVydHkgc2FsZXMgYW5kIGVmZmljaWVuY3kgb2YgYWR2ZXJ0aXNpbmcgcG9saWNpZXMuDQoNCmBgYHtyfQ0KTl9vYnNlcnZhdGlvbnMgPSBkaW0oZGF0YXNldClbMV0NCk5fdmFyaWFibGVzID0gZGltKGRhdGFzZXQpWzJdDQpgYGANCg0KIyMgKio8c3BhbiBzdHlsZT0iY29sb3I6cmVkIj4gWzJdIDwvc3Bhbj4gU3R1ZHkgb2YgdGhlIHZhcmlhYmxlcyoqDQoNCiMjIyAqKihJKSBXZSBzdHVkeSB0aGUgYWJzb2x1dGUgYW5kIHJlbGF0aXZlIGZyZXF1ZW5jeSBvZiB0aGUgcXVhbGl0YXRpdmUgdmFyaWFibGVzICJjaXR5IiwgInllYXIiIGFuZCAibW9udGgiKioNCg0KDQoNCmBgYHtyfQ0KIyBIZXJlIGFuZCBpbiB0aGUgZm9sbG93aW5nIHdlIHVzZSB0aGUgcGFja2FnZSAqRFQqIGZvciB0aGUgYmV0dGVyIHJlbmRlcmluZyBvZiB0aGUgdGFibGVzLg0KDQpGcmVxX2Fzc19jaXR5ID0gdGFibGUoZGF0YXNldFsiY2l0eSJdKQ0KRnJlcV9yZWxfY2l0eSA9IHRhYmxlKGRhdGFzZXRbImNpdHkiXSkvTl9vYnNlcnZhdGlvbnMNCkZyZXFfY2l0eSA9IGNiaW5kKEZyZXFfYXNzX2NpdHksRnJlcV9yZWxfY2l0eSkNCmRhdGF0YWJsZSh0KEZyZXFfY2l0eSksIGNhcHRpb24gPSAnQWJzb2x1dGUgYW5kIFJlbGF0aXZlIGZyZXF1ZW5jeSBvZiB0aGUgY2l0aWVzIGluIHRoZSBkYXRhc2V0JykNCg0KRnJlcV9hc3NfeWVhciA9IHRhYmxlKGRhdGFzZXRbInllYXIiXSkNCkZyZXFfcmVsX3llYXIgPSB0YWJsZShkYXRhc2V0WyJ5ZWFyIl0pL05fb2JzZXJ2YXRpb25zDQpGcmVxX3llYXIgPSBjYmluZChGcmVxX2Fzc195ZWFyLCBGcmVxX3JlbF95ZWFyKQ0KZGF0YXRhYmxlKHQoRnJlcV95ZWFyKSwgY2FwdGlvbiA9ICdBYnNvbHV0ZSBhbmQgUmVsYXRpdmUgZnJlcXVlbmN5IG9mIHRoZSB5ZWFycyBpbiB0aGUgZGF0YXNldCcpDQoNCkZyZXFfYXNzX21vbnRoID0gdGFibGUoZGF0YXNldFsibW9udGgiXSkNCkZyZXFfcmVsX21vbnRoID0gcm91bmQodGFibGUoZGF0YXNldFsibW9udGgiXSkvTl9vYnNlcnZhdGlvbnMsMikNCkZyZXFfbW9udGggPSBjYmluZChGcmVxX2Fzc19tb250aCxGcmVxX3JlbF9tb250aCkNCmRhdGF0YWJsZSh0KEZyZXFfbW9udGgpLCBvcHRpb25zID0gbGlzdChwYWdlTGVuZ3RoID0gMTIpLCBjYXB0aW9uID0gJ0Fic29sdXRlIGFuZCBSZWxhdGl2ZSBmcmVxdWVuY3kgb2YgdGhlIG1vbnRocyBpbiB0aGUgZGF0YXNldCcpDQpgYGANCg0KV2Ugb2JzZXJ2ZSB0aGF0IHRoZSB2YXJpYWJsZXMgImNpdHkiLCAieWVhciIsIGFuZCAibW9udGgiIGFyZSB1bmlmb3JtbHkgZGlzdHJpYnV0ZWQsIGFuZCB0aHVzIHRoZXkgZXhoaWJpdCAqKm11bHRpbW9kYWwqKiBkaXN0cmlidXRpb25zLg0KDQoqKjxzcGFuIHN0eWxlPSJjb2xvcjpyZWQiPiBbNV0gPC9zcGFuPioqIEluIHBhcnRpY3VsYXIsIHRoZSBwcm9iYWJpbGl0eSB0aGF0IGEgcmFuZG9tIGxpbmUgb2YgdGhlIGRhdGFzZXQgY29ycmVzcG9uZHMgdG86ICANCi0gdGhlIGNpdHkgb2Yg4oCcQmVhdW1vbnTigJ0gaXMgKlAo4oCcQmVhdW1vbnTigJ0pPTAuMjUqLiAgDQotIHRoZSBtb250aCBvZiAiSnVseSIgaXMgKlAoIkp1bHkiKX49MC4wOCouICAgICANCi0gIkRlY2VtYmVyIDIwMTIiIGlzICpQKCJEZWNlbWJlciAyMDEyIik9IFAoIkRlY2VtYmVyIikgeCBQKCIyMDEyIikgPSAwLjA4IHggMC4yIH49IDAuMTYuKiAgDQoNCiMjIyAqKihJSSkgTmV4dCwgd2Ugc3R1ZHkgdGhlIHF1YW50aXRhdGl2ZSB2YXJpYWJsZXM6KiogIA0KLSAqKiJzYWxlcyIsKiogICANCi0gKioidm9sdW1lIiwqKiAgDQotICoqIm1lZGlhbl9wcmljZSIsKiogIA0KLSAqKiJsaXN0aW5ncyIqKiAgDQotICoqIm1vbnRoX2ludmVudG9yeSIgKiogIA0KDQpXZSBzdW1tYXJpemUgaW4gYSB0YWJsZSBhIGRlc2NyaXB0aW9uIG9mIHRoZXNlIHZhcmlhYmxlcyB2aWEgdGhlIG1haW4gaW5kaWNlcyBvZiBzaGFwZSwgcG9zaXRpb24gYW5kIHZhcmlhYmlsaXR5LiBXZSBhbHNvIGNvbXBhcmUgZ3JhcGhpY2FsbHkgdGhlaXIgbm9ybWFsaXplZCBkaXN0cmlidXRpb24gYWdhaW5zdCBhIG5vcm1hbCBkaXN0cmlidXRpb24uDQoNCg0KYGBge3J9DQpjdl9mdW5jdCA8LSBmdW5jdGlvbih4KSB7DQogIHJldHVybihzZCh4KSAvIG1lYW4oeCkgKiAxMDApDQp9DQoNCg0Ka3VydG9zaXNfaW5kZXggPC0gZnVuY3Rpb24oeCkgew0KICByZXR1cm4oa3VydG9zaXMoeCktMykNCn0NCg0KDQpzdWJfZGF0YSA8LSBkYXRhc2V0W2MoInNhbGVzIiwidm9sdW1lIiwibWVkaWFuX3ByaWNlIiwibGlzdGluZ3MiLCJtb250aHNfaW52ZW50b3J5IildDQoNCnN0YXRpc3RpY3MgPC0gZGF0YS5mcmFtZSgNCiAgICAgICAgDQogIHF1YXJ0aWxlXzEgPSByb3VuZChhcHBseShzdWJfZGF0YSwgMiwgZnVuY3Rpb24oeCkgcXVhbnRpbGUoeCxwcm9icz0wLjI1LCBuYW1lcz1GQUxTRSkpLDIpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICANCiAgbWVkaWFuID0gcm91bmQoYXBwbHkoc3ViX2RhdGEsIDIsIG1lZGlhbiksMiksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgDQogIHF1YXJ0aWxlXzMgPSByb3VuZChhcHBseShzdWJfZGF0YSwgMiwgZnVuY3Rpb24oeCkgcXVhbnRpbGUoeCxwcm9icz0wLjc1LCBuYW1lcz1GQUxTRSkpLDIpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICANCiAgbWVhbiA9IHJvdW5kKGFwcGx5KHN1Yl9kYXRhLCAyLCBtZWFuKSwyKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgDQogIHNkID0gcm91bmQoYXBwbHkoc3ViX2RhdGEsIDIsIHNkKSwyKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgDQogIGN2ID0gcm91bmQoYXBwbHkoc3ViX2RhdGEsIDIsIGN2X2Z1bmN0KSwyKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgDQogIHNrZXduZXNzID0gcm91bmQoYXBwbHkoc3ViX2RhdGEsIDIsIHNrZXduZXNzKSwyKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgDQogIGt1cnRvc2lzID0gcm91bmQoYXBwbHkoc3ViX2RhdGEsIDIsIGt1cnRvc2lzX2luZGV4KSwyKQ0KKQ0KDQojIyBGT1IgQSBCRVRURVIgVklTVUFMSVpBVElPTiBPRiBUSEUgVEFCTEVTIFdFIFVTRSBUSEUgUEFDS0FHRSAiRFQiIChodHRwczovL3JzdHVkaW8uZ2l0aHViLmlvL0RULykNCg0KZGF0YXRhYmxlKHN0YXRpc3RpY3MsIGNhcHRpb249IkluZGljZXMgb2YgcG9zaXRpb24sIHZhcmlhYmlsaXR5IGFuZCBmb3JtIG9mIHRoZSBxdWFudGl0YXRpdmUgdmFyaWFibGVzIGluIHRoZSBkYXRzZXQiKQ0KYGBgDQoNCmBgYHtyfQ0KDQojIHRoZSBmdW5jdGlvbiBub3JtYWxpemUgdGFrZXMgaW4gaW5wdXQgYSB2YXJpYWJsZSBpbiBzdHJpbmcgZm9ybSBhbmQgcmV0dXJucyBpdHMgdmFsdWVzIG5vcm1hbGl6ZWQgYnkgaXRzIG1lYW4gYW5kIHN0YW5kYXJkIGRldmlhdGlvbg0Kbm9ybWFsaXplIDwtIGZ1bmN0aW9uKHZhcmlhYmxlKXsNCiAgcmV0dXJuICgoZGF0YXNldFtbdmFyaWFibGVdXS1zdGF0aXN0aWNzW3ZhcmlhYmxlLCAibWVhbiJdKS9zdGF0aXN0aWNzW3ZhcmlhYmxlLCAic2QiXSkNCn0NCg0KIyB3ZSBnZW5lcmF0ZSBhIHN0YW5kYXJkIG5vcm1hbCBkaXN0cmlidXRpb24NCmdhdXNzaWFuX2Rpc3RyaWJ1dGlvbiA8LSBybm9ybSgxMDAwMDAsMCwxKQ0KDQoNCiMgd2UgcGxvdCB0aGUgZGVuc2l0eSBvZiB0aGUgZGlmZmVyZW50IHZhcmlhYmxlcyBhZ2FpbnN0IGEgc3RhbmRhcmQgbm9ybWFsIGRpc3RyaWJ1dGlvbg0KZ2dwbG90KCkrDQogIGdlb21fZGVuc2l0eShhZXMoeD1nYXVzc2lhbl9kaXN0cmlidXRpb24sIGZpbGw9Ik4wMSIpLCBjb2xvcj1OQSwgIGFscGhhPS44KSsNCiAgZ2VvbV9kZW5zaXR5KGFlcyh4PW5vcm1hbGl6ZSgic2FsZXMiKSwgY29sb3I9InNhbGVzIiksIGxpbmV3aWR0aD0xLjUpKw0KICBnZW9tX2RlbnNpdHkoYWVzKHg9bm9ybWFsaXplKCJ2b2x1bWUiKSwgY29sb3I9InZvbHVtZSIpLCBsaW5ld2lkdGg9MS41KSsNCiAgZ2VvbV9kZW5zaXR5KGFlcyh4PW5vcm1hbGl6ZSgibWVkaWFuX3ByaWNlIiksIGNvbG9yPSAibWVkaWFuX3ByaWNlIiksIGxpbmV3aWR0aD0xLjUpKw0KICBnZW9tX2RlbnNpdHkoYWVzKHg9bm9ybWFsaXplKCJsaXN0aW5ncyIpLCBjb2xvcj0ibGlzdGluZ3MiKSwgbGluZXdpZHRoPTEuNSkrDQogIGdlb21fZGVuc2l0eShhZXMoeD1ub3JtYWxpemUoIm1vbnRoc19pbnZlbnRvcnkiKSwgY29sb3I9Im1vbnRoc19pbnZlbnRvcnkiKSwgbGluZXdpZHRoPTEuNSkrDQogIGxhYnModGl0bGU9IkRpc3RyaWJ1dGlvbiBvZiB0aGUgdmFyaWFibGVzIiwNCiAgICAgICB4PSJOb3JtYWxpemVkIHZhcmlhYmxlICIsDQogICAgICAgeT0iZGVuc2l0eSIpKw0KICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBjKE4wMSA9ICJncmV5IiksICAgDQogICAgICAgICAgICAgICAgICAgIGxhYmVscyA9IGMoTjAxID0gIk4oMCwxKSIpKSArDQogIHRoZW1lX2NsYXNzaWMoKSsNCiAgdGhlbWUocGxvdC50aXRsZS5wb3NpdGlvbiA9ICJwYW5lbCIsDQogICAgICAgIHBsb3QudGl0bGU9ZWxlbWVudF90ZXh0KGhqdXN0PTAuNSkpKw0KICBndWlkZXMoZmlsbCA9IGd1aWRlX2xlZ2VuZChvdmVycmlkZS5hZXMgPSBsaXN0KGNvbG9yID0gTkEpKSkrDQogIGxhYnMoY29sb3IgPSAiVmFyaWFiaWxlIiwNCiAgICAgIGZpbGwgPSAiRGlzdHJpYnV6aW9uZSBub3JtYWxlIikNCmBgYA0KDQoNCg0KDQoNCioqPHNwYW4gc3R5bGU9ImNvbG9yOnJlZCI+IFszXSA8L3NwYW4+KiogRnJvbSB0aGUgcHJldmlvdXMgYW5hbHlzaXMgd2UgY2FuIG9ic2VydmUgdGhhdCB0aGUgdmFyaWFibGVzICJ2b2x1bWUiIGFuZCAibWVkaWFuX3ByaWNlIiBhcmUgdGhlIG9uZXMgd2l0aCB0aGUgaGlnaGVzdCBhbmQgc21hbGxlc3QgdmFyaWFiaWxpdHkgaGF2aW5nIHRoZSBsYXJnZXN0IGFuZCBzbWFsbGVzdCBjb2VmZmljaWVudCBvZiB2YXJpYXRpb24sIHJlc3BlY3RpdmVseS4gU2ltaWxhcmx5ICJ2b2x1bWUiIGlzIGFsc28gdGhlIG1vc3QgYXN5bW1ldHJpYyB2YXJpYWJsZSBoYXZpbmcgdGhlIGhpZ2hlc3QgYWJzb2x1dGUgdmFsdWUgb2YgdGhlIEZpc2hlciBza2V3bmVzcyBjb2VmZmljaWVudCwgZGlmZmVyZW50bHkgdGhlIGxlYXN0IGFzeW1tZXRyaWMgdmFyaWFibGUgaXMgIm1vbnRoc19pbnZlbnRvcnkiLiAgDQoNClRoZSB2YWx1ZXMgb2YgdGhlIEZpc2hlciBza2V3bmVzcyBjb2VmZmljaWVudHMgYW5kIGt1cnRvc2lzIGRlbW9uc3RyYXRlIHRoYXQgbm9uZSBvZiB0aGUgdmFyaWFibGVzIGZvbGxvdyBhbiBleGFjdCBub3JtYWwgZGlzdHJpYnV0aW9uLCBzdWdnZXN0aW5nIGRpZmZlcmVudCBkaXN0cmlidXRpb25zIG9mIHRoZSB2YXJpYWJsZXMgYmFzZWQgb24gdGhlIGRpZmZlcmVudCBjaXRpZXMgYW5kL29yIHBlcmlvZHMuIA0KDQpIb3dldmVyLCBhcyB3ZSBjYW4gc2VlIGZyb20gdGhlIHBsb3QgYW5kIHRoZSB2YWx1ZXMgb2Ygc2tld25lc3MgaW4gdGhlIHRhYmxlLCBhbGwgdGhlIHZhcmlhYmxlLCBleGNlcHQgdGhlIG1lZGlhbl9wcmljZSwgYXJlIG1vcmUgZGVuc2VseSBjb25jZW50cmF0ZWQgY2xvc2UgdG8gdGhlIG1lYW4gb24gdGhlIG1lYW4gbGVmdCBhbmQgbW9yZSBzcGFyc2VseSBkaXN0cmlidXRlZCBvbiB0aGUgbWVhbiByaWdodC4NCg0KRmluYWxseSBieSBsb29raW5nIGF0IHRoZSBrdXJ0b3Npcywgd2Ugb2JzZXJ2ZSB0aGF0IGFsbCB0aGUgdmFyaWFibGVzLCBleGNlcHQgdGhlIHZvbHVtZSwgaGF2ZSB0YWlscyBkZWNheWluZyBmYXN0ZXIgdGhhbiB0aGUgR2F1c3NpYW4gZGlzdHJpYnV0aW9uLCBzbyB0aGUgcHJvYmFiaWxpdHkgb2Ygb2JzZXJ2aW5nIG91dGxpZXJzIGZhciBmcm9tIHRoZSBtZWFuIHdpbGwgYmUgbG93ZXIgdGhhbiB0aGUgcHJvYmFiaWxpdHkgdGhhdCB3ZSB3b3VsZCBoYXZlIGJ5IGNvbnNpZGVyaW5nIGEgbm9ybWFsIGRpc3RyaWJ1dGlvbiB3aXRoIHNhbWUgbWVhbiBhbmQgc3RhbmRhcmQgZGV2aWF0aW9uLg0KDQoNCiMjICoqPHNwYW4gc3R5bGU9ImNvbG9yOnJlZCI+IFs0XSA8L3NwYW4+IENyZWF0aW9uIG9mIGNsYXNzZXMgZm9yIHF1YW50aXRhdGl2ZSB2YXJpYWJsZXMqKg0KIyMjIEluIHRoaXMgc2VjdGlvbiB3ZSBkaXZpZGUgdGhlIHZhcmlhYmxlIG1lZGlhbl9wcmljZSBpbiBjbGFzc2VzIHRvIHN0dWR5IGhvdyBpdHMgZGlzdHJpYnV0aW9uIHZhcmllcyBhY3Jvc3MgdGhlIGRpZmZlcmVudCBjaXRpZXMuDQpGaXJzdCB3ZSBjcmVhdGUgdGhlIGNsYXNzZXMgZWFjaCBjb3JyZXNwb25kaW5nIHRvIGEgcmFuZ2Ugb2YgMTAwMDAkLCBhc3NpZ24gZWFjaCBkYXRhIHRvIHRoZSBjb3JyZXNwb25kaW5nIGNsYXNzIGFuZCBzdHVkeSB0aGUgZGlzdHJpYnV0aW9uIGZyZXF1ZW5jeSBvZiBlYWNoIGNsYXNzLg0KDQpgYGB7cn0NCmNhdCgibWluIG1lZGlhbl9wcmljZToiLCBtaW4oZGF0YXNldCRtZWRpYW5fcHJpY2UpLCAiXG4iKQ0KY2F0KCJtYXggbWVkaWFuX3ByaWNlOiIsIG1heChkYXRhc2V0JG1lZGlhbl9wcmljZSkpDQoNCg0KDQojZ2l2ZW4gdGhlIG1pbml1bSBhbmQgbWF4aW11bSBtZWRpYW5fcHJpY2UgdmFsdWUgd2UgY3JlYXRlIGNsYXNzZXMgb2YgMTAwMDAkIGVhY2ggYW5kIGFzc2lnbiBlYWNoIGRhdGEgdG8gdGhlIGNvcnJlc3BvbmRpbmcgY2xhc3MuDQoNCmJyZWFraW5nX3BvaW50cyA8LSBzZXEoNzAsIDE4MCwgYnk9MTApICAgIA0KYnJlYWtpbmdfcG9pbnRzX2xhYmVscyA8LSBwYXN0ZTAoIlsiLCBicmVha2luZ19wb2ludHNbLWxlbmd0aChicmVha2luZ19wb2ludHMpXSwgIkssICIsIGJyZWFraW5nX3BvaW50c1stMV0sICJLKSIpDQoNCmRhdGFzZXQkbWVkaWFuX3ByaWNlX0NMIDwtIGN1dChkYXRhc2V0JG1lZGlhbl9wcmljZSwgDQogICAgICAgICAgICAgICAgICAgICBicmVha3M9c2VxKGZyb20gPSA3MDAwMCwgdG8gPSAxODAwMDAsIGJ5ID0gMTAwMDApKQ0KDQoNCg0KbGV2ZWxzKGRhdGFzZXQkbWVkaWFuX3ByaWNlX0NMKSA8LSBicmVha2luZ19wb2ludHNfbGFiZWxzDQoNCmZyZXFfYXNzX21lZGlhbl9wcmljZSA8LSB0YWJsZShkYXRhc2V0JG1lZGlhbl9wcmljZV9DTCkNCmZyZXFfcmVsX21lZGlhbl9wcmljZSA8LSByb3VuZChmcmVxX2Fzc19tZWRpYW5fcHJpY2UvTl9vYnNlcnZhdGlvbnMsMikNCg0KZGF0YXRhYmxlKGNiaW5kKGZyZXFfYXNzX21lZGlhbl9wcmljZSwgZnJlcV9yZWxfbWVkaWFuX3ByaWNlKSkNCmBgYA0KTmV4dCwgd2UgY29tcHV0ZSB0aGUgR2luaSBoZXRlcm9nZW5laXR5IGluZGV4IG9mIHRoZSBtZWRpYW5fcHJpY2UgY2xhc3MgdmFyaWFibGUgb3ZlciB0aGUgZW50aXJlIGRhdGFzZXQgYW5kIHNlcGFyYXRlbHkgZm9yIGVhY2ggY2l0eS4gDQoNCmBgYHtyfQ0KZ2luaS5pbmRleCA8LSBmdW5jdGlvbih4KXsNCiAgbmkgPSB0YWJsZSh4KQ0KICBmaSA9IG5pL2xlbmd0aCh4KQ0KICBmaTIgPSBmaV4yDQogIEogPSBsZW5ndGgodGFibGUoeCkpDQogIA0KICBnaW5pID0gMS1zdW0oZmkyKQ0KICBnaW5pLm5vcm0gPSBnaW5pLygoSi0xKS9KKQ0KICANCiAgcmV0dXJuKGdpbmkubm9ybSkNCn0NCg0KDQpjYXQoc3ByaW50ZigiVGhlIEdpbmkgaGV0ZXJvZ2VuZWl0eSBpbmRleCBvZiB0aGUgY2xhc3NlcyBvZiBtZWRpYW4gcHJpY2Ugb3ZlciB0aGUgZW50cmllIGRhdGFzZXQgaXM6ICVmIFxuIiwgZ2luaS5pbmRleChkYXRhc2V0JG1lZGlhbl9wcmljZV9DTCkpKQ0KDQpmb3IgKGNpdCBpbiB1bmlxdWUoZGF0YXNldCRjaXR5KSl7DQogIGNpdHlfZGF0YXNldCA8LSBkYXRhc2V0ICU+JQ0KICAgIGZpbHRlcihjaXR5PT1jaXQpDQoNCiAgY2F0KHNwcmludGYoIlRoZSBHaW5pIGhldGVyb2dlbmVpdHkgaW5kZXggb2YgdGhlIGNsYXNzZXMgb2YgbWVkaWFuIHByaWNlIHJlbGF0aXZlIHRvIHRoZSBjaXR5IG9mICVzIGlzOiAlZiBcbiIsIGNpdCwgZ2luaS5pbmRleChjaXR5X2RhdGFzZXQkbWVkaWFuX3ByaWNlX0NMKSkpDQogIH0NCg0KYGBgDQpMYXN0IHdlIHZpc3VhbGl6ZSB0aGUgZnJlcXVlbmN5IGRpc3RyaWJ1dGlvbiB2aWEgYSBiYXJwbG90LiAgDQoNCmBgYHtyfQ0KZ2dwbG90KGRhdGE9ZGF0YXNldCkrDQogIGdlb21fYmFyKGFlcyh4PW1lZGlhbl9wcmljZV9DTCksDQogICAgICAgICAgIHN0YXQ9ImNvdW50IiwNCiAgICAgICAgICAgY29sPSJibGFjayIsDQogICAgICAgICAgIGZpbGw9Im9yYW5nZSIpKw0KICBsYWJzKHRpdGxlPSJEaXN0cmlidXRpb24gb2YgdGhlIGNsYXNzZXMgb2YgbWVkaWFuX3ByaWNlIiwNCiAgICAgICB4PSJtZWRpYW4gcHJpY2UgaW4gY2xhc3NlcyIsDQogICAgICAgeT0iYWJzb2x1dGUgZnJlcXVlbmN5IikrDQogIHNjYWxlX3lfY29udGludW91cyhicmVha3MgPSBzZXEoMCw2MCwxMCkpKw0KICB0aGVtZV9jbGFzc2ljKCkrDQogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gMTUsIGhqdXN0ID0gMSksDQogICAgICAgIGF4aXMudGl0bGUueCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTQsIG1hcmdpbiA9IG1hcmdpbih0ID0gMTApKSwNCiAgICAgICAgYXhpcy50aXRsZS55ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNCwgbWFyZ2luID0gbWFyZ2luKHIgPSAxMCkpKQ0KYGBgICANCg0KDQpMYXN0IHdlIHZpc3VhbGl6ZSB0aGUgZnJlcXVlbmN5IGRpc3RyaWJ1dGlvbiB2aWEgYSBiYXJwbG90IGFjcm9zcyB0aGUgZGlmZmVyZW50IGNpdGllcy4gIA0KDQpgYGB7cn0NCiNmb3IgYSBiZXR0ZXIgdmlzdWFsaXphdGlvbiBvZiB0aGUgZnJlcXVlbmN5IGFjcm9zcyB0aGUgZGlmZmVyZW50IGNpdGllcyB3ZSBjcmVhdGUgYSBkYXRhc2V0IHdoZXJlIHdlIGNvdW50IHRoZSBmcmVxdWVuY3kgb2YgZWFjaCBjbGFzcyBmb3IgZWFjaCBjaXR5IGFuZCB3ZSBmaWxsIHRoZSBkYXRhc2V0IHdpdGggb2JzZXJ2YXRpb25zIGhhdmluZyBjb3VudD0wIGZvciBlYWNoIGNpdHkgYW5kIGNsYXNzIG9mIHByaWNlIHRoYXQgaGF2ZSBubyBpbnRlcnNlY3Rpb24gICANCmRhdGFzZXRfY29tcGxldGUgPC0gZGF0YXNldCAlPiUNCiAgY291bnQobWVkaWFuX3ByaWNlX0NMLCBjaXR5KQ0KDQpmb3IgKGNpdCBpbiB1bmlxdWUoZGF0YXNldCRjaXR5KSl7DQogIGZvciAoY2xhc3MgaW4gdW5pcXVlKGRhdGFzZXQkbWVkaWFuX3ByaWNlX0NMKSl7DQogICAgZmlsdGVyZWQgPC0gZGF0YXNldF9jb21wbGV0ZSAlPiUNCiAgICAgIGZpbHRlcihjaXR5ID09IGNpdCwgbWVkaWFuX3ByaWNlX0NMID09IGNsYXNzKQ0KICAgIGlmIChucm93KGZpbHRlcmVkKSA9PSAwKXsNCiAgICAgIGRhdGFzZXRfY29tcGxldGUgPC0gcmJpbmQoZGF0YXNldF9jb21wbGV0ZSwgZGF0YS5mcmFtZShjaXR5PWNpdCwgbWVkaWFuX3ByaWNlX0NMPWNsYXNzLCBuPTApKQ0KICAgIH0NCiAgfQ0KfQ0KYGBgDQoNCg0KYGBge3J9DQojIG5leHQgd2UgdmlzdWFsaXplIHZpYSBhIGJhciBwbG90IHRoZSBkaXN0cmlidXRpb24gb2YgY2xhc3NlcyBvZiBwcmljZSBhY3Jvc3MgdGhlIGRpZmZlcmVudCBjaXRpZXMNCmdncGxvdChkYXRhPWRhdGFzZXRfY29tcGxldGUpKw0KICBnZW9tX2NvbChhZXMoeD1tZWRpYW5fcHJpY2VfQ0wsDQogICAgICAgICAgICAgICB5PW4sDQogICAgICAgICAgICAgICBmaWxsPWNpdHkpLA0KICAgICAgICAgICBwb3NpdGlvbj0iZG9kZ2UyIiwgICNkb2RnZSwgI2ZpbGwsICNzdGFjaw0KICAgICAgICAgICBzdGF0PSJpZGVudGl0eSIsDQogICAgICAgICAgIGNvbD0iYmxhY2siKSsNCiAgbGFicyh0aXRsZT0iRGlzdHJpYnV6aW9uZSBkZWxsZSBjbGFzc2kgZGVsbGEgbWVkaWFuYSBkaSBwcmV6em8iLA0KICAgICAgIHg9Im1lZGlhbiBwcmljZSBpbiBjbGFzc2VzIiwNCiAgICAgICB5PSJhYnNvbHV0ZSBmcmVxdWVuY3kiKSsNCiAgc2NhbGVfeV9jb250aW51b3VzKGJyZWFrcyA9IHNlcSgwLDYwLDEwKSkrDQogIHRoZW1lX2NsYXNzaWMoKSsNCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSAxNSwgaGp1c3QgPSAxKSwNCiAgICAgICAgYXhpcy50aXRsZS54ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNCwgbWFyZ2luID0gbWFyZ2luKHQgPSAxMCkpLA0KICAgICAgICBheGlzLnRpdGxlLnkgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE0LCBtYXJnaW4gPSBtYXJnaW4ociA9IDEwKSksDQogICAgICAgIGxlZ2VuZC5wb3NpdGlvbiA9ImJvdHRvbSIpDQpgYGANClRoZSBHaW5pIGhldGVyb2dlbmVpdHkgaW5kZXggY2xvc2UgdG8gMSBhbmQgdGhlIGJhciBwbG90cyBvZiB0aGUgZGlzdHJpYnV0aW9uIGluZGljYXRlIHRoYXQgdGhlIGRhdGFzZXQgaXMgZGlzdHJpYnV0ZWQgZGlzY3JlZXRseSB1bmlmb3JtbHkgYWNyb3NzIHRoZSBkaWZmZXJlbnQgbWVkaWFuLXByaWNlIGNsYXNzZXMuICANCg0KVGhlIGRpc3RyaWJ1dGlvbiBvZiB0aGUgZGF0YSByZWxhdGl2ZSB0byB0aGUgZGlmZmVyZW50IGNpdGllcyBhY3Jvc3MgdGhlIGNsYXNzZXMgb2YgcHJpY2UgaXMgc2lnbmlmaWNhbnRseSBsZXNzIHVuaWZvcm0sIGFzIHJlZmxlY3RlZCBib3RoIGJ5IGxvd2VyIHZhbHVlcyBvZiB0aGUgR2luaSBpbmRleCBhbmQgdGhlIGJhciBwbG90IHJlbGF0aXZlIHRvIHRoZSBkaWZmZXJlbnQgY2l0aWVzLiAgIA0KDQpTcGVjaWZpY2FsbHksIHdlIG9ic2VydmUgdGhhdCB0aGUgcHJpY2VzIGluIFdpY2hpdGEgRmFsbHMgYXJlIGdlbmVyYWxseSBsb3dlciB0aGFuIHRob3NlIG9mIEJlYXVtb250IHdoaWNoIGFyZSBzbWFsbGVyIHRoYW4gdGhvc2Ugb2YgVHlsZXIgd2hpY2ggYXJlIGZpbmFsbHkgZ2VuZXJhbGx5IHNtYWxsZXIgdGhhbiB0aG9zZSBvZiBCcnlhbi1Db2xsZWdlIFN0YXRpb24uDQoNCldlIGZpbmFsbHkgaW5jbHVkZSBhIGJveHBsb3Qgb2YgdGhlIGRpc3RyaWJ1dGlvbiBvZiBtZWRpYW5fcHJpY2UgYWNyb3NzIHRoZSBkaWZmZXJlbnQgY2l0aWVzIHRvIHF1YW50aWZ5IHRoZSB2YXJpYWJpbGl0eSBvZiB0aGUgbWVkaWFuIHByaWNlIGZvciBlYWNoIGNpdHkuDQpgYGB7cn0NCmdncGxvdChkYXRhPWRhdGFzZXQsDQogICAgICAgYWVzKHg9Y2l0eSwNCiAgICAgICAgICAgeT1tZWRpYW5fcHJpY2UsDQogICAgICAgICAgIGZpbGw9Y2l0eSkpKw0KICAgICAgIGdlb21fYm94cGxvdCgpKw0KICAgICAgIGdlb21faGxpbmUoeWludGVyY2VwdCA9IHN0YXRpc3RpY3NbIm1lZGlhbl9wcmljZSIsInF1YXJ0aWxlXzMiXSwgY29sb3IgPSAicmVkIikrDQogICAgICAgZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0gc3RhdGlzdGljc1sibWVkaWFuX3ByaWNlIiwicXVhcnRpbGVfMSJdLCBjb2xvciA9ICJyZWQiKSsNCiAgICAgICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQgPSBzdGF0aXN0aWNzWyJtZWRpYW5fcHJpY2UiLCJtZWFuIl0sIGNvbG9yID0gInJlZCIpKw0KICAgICAgIGxhYnModGl0bGU9IkNvbXBhcmlzb24gb2YgbWVkaWFuX3ByaWNlIGJ5IGNpdHkiLA0KICAgICAgICAgICAgeD0iY2l0eSIsDQogICAgICAgICAgICB5PSJVUyQiKSsNCiAgICAgICBhbm5vdGF0ZSgibGFiZWwiLCB4ID0gSW5mLCB5ID0gc3RhdGlzdGljc1sibWVkaWFuX3ByaWNlIiwicXVhcnRpbGVfMSJdLCANCiAgICAgICAgICAgICAgICBsYWJlbCA9ICIxwrBxdWFydGlsZSBtZWRpYW5fcHJpY2UiLCANCiAgICAgICAgICAgICAgICBoanVzdCA9IDEuMSwgDQogICAgICAgICAgICAgICAgdmp1c3QgPSArLjUsIA0KICAgICAgICAgICAgICAgIGZpbGw9ImdyZXkiLCANCiAgICAgICAgICAgICAgICBjb2xvciA9ICJyZWQiKSsNCiAgICAgICBhbm5vdGF0ZSgibGFiZWwiLCB4ID0gSW5mLCB5ID0gc3RhdGlzdGljc1sibWVkaWFuX3ByaWNlIiwibWVkaWFuIl0sDQogICAgICAgICAgICAgICAgbGFiZWwgPSAibWVkaWFuIG1lZGlhbl9wcmljZSIsDQogICAgICAgICAgICAgICAgaGp1c3QgPSAxLjEsIHZqdXN0ID0gKy41LA0KICAgICAgICAgICAgICAgIGZpbGw9ImdyZXkiLA0KICAgICAgICAgICAgICAgIGNvbG9yID0gInJlZCIpKw0KICAgICAgIGFubm90YXRlKCJsYWJlbCIsIHggPSBJbmYsIHkgPSBzdGF0aXN0aWNzWyJtZWRpYW5fcHJpY2UiLCJxdWFydGlsZV8zIl0sDQogICAgICAgICAgICAgICAgbGFiZWwgPSAiM8KwIHF1YXJ0aWxlIG1lZGlhbl9wcmljZSIsDQogICAgICAgICAgICAgICAgaGp1c3QgPSAxLjEsDQogICAgICAgICAgICAgICAgdmp1c3QgPSArLjUsDQogICAgICAgICAgICAgICAgZmlsbD0iZ3JleSIsDQogICAgICAgICAgICAgICAgY29sb3IgPSAicmVkIikrDQogICAgICAgdGhlbWVfY2xhc3NpYygpKw0KICAgICAgIHNjYWxlX3hfZGlzY3JldGUoZXhwYW5kID0gZXhwYW5zaW9uKGFkZCA9IGMoLjUsIDIpKSkrDQogICAgICAgc2NhbGVfeV9jb250aW51b3VzKGJyZWFrcyA9IHNlcSg3MDAwMCwgMTgwMDAwLCBieT0xMDAwMCksIA0KICAgICAgICAgICAgICAgICAgICAgICAgICBsYWJlbHMgPSBwYXN0ZTAoYnJlYWtpbmdfcG9pbnRzLCAiSyIpKSsNCiAgICAgICB0aGVtZShwbG90LnRpdGxlLnBvc2l0aW9uID0gInBhbmVsIiwNCiAgICAgICAgICAgICBwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemU9MTYsIGhqdXN0PTAuNSksDQogICAgICAgICAgICAgYXhpcy50aXRsZS54ID0gZWxlbWVudF90ZXh0KHNpemU9MTQpLA0KICAgICAgICAgICAgIGF4aXMudGl0bGUueSA9IGVsZW1lbnRfdGV4dChzaXplPTE0KSwNCiAgICAgICAgICAgICBheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChzaXplPTEwKSwNCiAgICAgICAgICAgICBheGlzLnRleHQueSA9IGVsZW1lbnRfdGV4dChzaXplPTEwKSwNCiAgICAgICAgICAgICBsZWdlbmQucG9zaXRpb24gPSJib3R0b20iKQ0KYGBgDQpXZSBjYW4gb2JzZXJ2ZSB0aGF0IHRoZSBtZWRpYW4gcHJpY2UgaW4gZGlmZmVyZW50IGNpdGllcyBleGhpYml0cyBzaW1pbGFyIHZhcmlhYmlsaXR5LCBtZWFzdXJlZCBpbiB0ZXJtcyBvZiBpbnRlcnF1YXJ0aWxlIHJhbmdlLCBhbmQgc2lnbmlmaWNhbnRseSBsb3dlciB2YXJpYWJpbGl0eSB0aGFuIHRoYXQgZm91bmQgYnkgY29uc2lkZXJpbmcgYWxsIHRoZSBjaXRpZXMgdG9nZXRoZXIuIFRoaXMgaXMgZHVlIHRvIHRoZSBmYWN0IHRoYXQgdGhlIG1lZGlhbiBwcmljZSByYW5nZSBkaWZmZXJzIHNpZ25pZmljYW50bHkgZnJvbSBjaXR5IHRvIGNpdHkuDQoNCg0KDQojIyAqKjxzcGFuIHN0eWxlPSJjb2xvcjpyZWQiPiBbNl0gPC9zcGFuPiBDcmVhdGlvbiBvZiBuZXcgdmFyaWFibGVzKioNCiMjIyBXZSBjcmVhdGUgdGhyZWUgbmV3IHZhcmliYWxlcyBtZWFzdXJpbmcgdGhlIG1lYW4gc2VsbGluZyBwcmljZSBpbiBVUyBkb2xsYXJzLCB0aGUgZWZmZWN0aXZlbmVzcyBvZiB0aGUgc2FsZXMgYWRzIGFuZCB0aGUgZGF0ZSBtZWFzdXJlZCBpbiBtb3RocyBmcm9tIEphbnVhcnkgMjAxMC4gIA0KLSBUaGUgdmFyaWFibGUgKm1lYW5fcHJpY2UqIGlzIG9idGFpbmVkIGFzICQxMF42JCgqdm9sdW1lKi8qc2FsZXMqKS4NCi0gVGhlIHZhcmlhYmxlICplZmZlY3RpdmVuZXNzKiBpcyBvYnRhaW5lZCBhcyAoKmxpc3RpbmdzKi8qbW9udGhzX2ludmVudG9yeSopIHdoaWNoIG1lYXN1cmVzIHRoZSBhdmVyYWdlIG1vbnRobHkgc2FsZXMgcmF0ZSBvZiB0aGUgcHJvcGVydGllcyBsaXN0ZWQgaW4gYSBjaXR5IGluIGEgZ2l2ZW4gbW9udGgveWVhci4NCi0gVGhlIHZhcmlhYmxlICpkYXRlKiB3aGljaCByZXR1cm5zIHRoZSBkYXRlIG9mIGVhY2ggZGF0YSBpbiBtb250aHMgZnJvbSBqYW51YXJ5IDIwMTAsIHRoaXMgaXMgb2J0YWluZWQgYXMgJG1vbnRoKzEyKG1vZCh5ZWFyLDIwMTApKSQuDQoNCmBgYHtyfQ0KZGF0YXNldCRtZWFuX3ByaWNlIDwtICh2b2x1bWUvc2FsZXMpKjEwXjYNCg0KZGF0YXNldCRlZmZlY3RpdmVuZXNzIDwtIChsaXN0aW5ncy9tb250aHNfaW52ZW50b3J5KQ0KDQpkYXRhc2V0JGRhdGUgPC0gKGFzLm51bWVyaWMoYXMuY2hhcmFjdGVyKG1vbnRoKSkpKzEyKihhcy5udW1lcmljKGFzLmNoYXJhY3Rlcih5ZWFyKSklJShtaW4oYXMubnVtZXJpYyhhcy5jaGFyYWN0ZXIoeWVhcikpKSkpDQpgYGANCg0KDQpOZXh0IHdlIHN0dWR5IHRoZSB0cmVuZCBvZiB0aGUgcXVhbnRpdGF0aXZlIHZhcmlhYmxlcyBvdmVyIHRpbWUuIA0KDQoNCmBgYHtyLCBmaWcud2lkdGg9MTQsIGZpZy5oZWlnaHQ9MTV9DQojIFdlIHVzZSB0aGUgcGFja2FnZSAqcGF0Y2h3b3JrKiBpbiBjb21iaW5hdGlvbiB3aXRoICpnZ3Bsb3QyKiB0byBwcm92aWRlIGEgY3VtdWxhdGl2ZSBzaWduaWZpY2FudCByZXByZXNlbnRhdGlvbiBvZiBhbGwgdGhlIHF1YW50aXRhdGl2ZSB2YXJpYWJsZXMgaW4gYSBzaW5nbGUgbXVsdGktcGFuZWwgZmlndXJlDQojIFdlIGFsc28gdXNlIHRoZSBwYWNrYWdlICpnZ3B1YnIqIHRvIGV4dHJhY3QgdGhlIGxlZ2VuZCBmcm9tIGEgZmlndXJlIGFuZCBwcmludCBpdCBhcyBhIHVuaXF1ZSBsZWdlbmQgZm9yIGFsbCB0aGUgcGxvdHMuDQoNCg0KIyBUaGUgZnVuY3Rpb24gbW9udGhfY29udmVydCBjb252ZXJ0IGEgbnVtYmVyIGJldHdlZW4gMSBhbmQgMTIgaW50byBhIHN0cmluZyBpbmRpY2F0aW5nIHRoZSBjb3JyZXNwb25kaW5nIG1vbnRoLg0KbW9udGhfY29udmVydCA8LSBmdW5jdGlvbih4KXsNCiAgeF9uPWFzLm51bWVyaWMoYXMuY2hhcmFjdGVyKHgpKQ0KICBtb250aHM9YygiSmFuIiwgIkZlYiIsICJNYXIiLCAiQXByIiwgIk1heSIsICJKdW4iLCAiSnVsIiwgIkF1ZyIsICJTZXAiLCAiT2N0IiwgIk5vdiIsICJEZWMiKQ0KICByZXR1cm4obW9udGhzW3hfbl0pDQp9DQoNCg0KIyBUaGUgZnVuY3Rpb24gYnJlYWtpbmdfcG9pbnRzIHRha2VzIGluIGlucHV0IGEgdmVjdG9yIG9mIGRhdGVzIGV4cHJlc3NlZCBtb250aHMgYW5kIGNvbnZlcnQgaW4gdmVjdG9yIG9mIGRhdGVzIGV4cHJlc3NlZCBhcyBtb250aCt5ZWFyLg0KIyBUaGlzIHdpbGwgYmUgdXNlZCB0byBwcm9kdWNlIHRoZSB4LWF4aXMgbGFiZWxzIGluIHRoZSBwbG90cyB3aXRoIHRoZSB0cmVuZCBvZiB0aGUgdmFyaWFibGVzIG92ZXIgdGltZS4gDQpicmVha2luZ19wb2ludHMgPC0gZnVuY3Rpb24oeCkgew0KICByZXR1cm4ocGFzdGUobW9udGhfY29udmVydChkYXRhc2V0JG1vbnRoW3hdKSwgZGF0YXNldCR5ZWFyW3hdLCBzZXA9IiAiKSApDQp9DQoNCg0KIyBXZSBwcm9kdWNlIGEgZmlyc3QgcGxvdCBvbmx5IHRvIGV4dHJhY3QgdGhlIGxlZ2VuZC4NCmxpbmVfc2FsZXMgPC0gZ2dwbG90KGRhdGE9ZGF0YXNldCkrDQogIGdlb21fbGluZShhZXMoeCA9IGRhdGUsDQogICAgICAgICAgICAgICAgeSA9IHNhbGVzLA0KICAgICAgICAgICAgICAgIGdyb3VwID0gY2l0eSwNCiAgICAgICAgICAgICAgICBjb2xvciA9IGNpdHkpLCANCiAgICAgICAgICAgIHNpemUgPSAxLjUpKw0KICAgIHRoZW1lKGxlZ2VuZC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTgpLA0KICAgICAgICAgIGxlZ2VuZC50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNikpDQoNCiMgV2UgZXh0cmFjdCB0aGUgbGVnZW5kDQpsZWdlbmRfbGluZSA8LSBhc19nZ3Bsb3QoZ2V0X2xlZ2VuZChsaW5lX3NhbGVzKSkNCg0KDQojIFdlIHByb2R1Y2UgdGhlIHBsb3Qgd2l0aCB0aGUgdHJlbmQgb2YgdGhlIHNhbGVzIG92ZXIgdGltZS4NCmxpbmVfc2FsZXMgPC0gZ2dwbG90KGRhdGE9ZGF0YXNldCkrDQogIGdlb21fbGluZShhZXMoeCA9IGRhdGUsDQogICAgICAgICAgICAgICAgeSA9IHNhbGVzLA0KICAgICAgICAgICAgICAgIGdyb3VwID0gY2l0eSwNCiAgICAgICAgICAgICAgICBjb2xvciA9IGNpdHkpLCANCiAgICAgICAgICAgIHNpemUgPSAxLjUpKw0KICBnZW9tX3BvaW50KGFlcyh4ID0gZGF0ZSwNCiAgICAgICAgICAgICAgICB5ID0gc2FsZXMsDQogICAgICAgICAgICAgICAgZ3JvdXAgPSBjaXR5LA0KICAgICAgICAgICAgICAgIGNvbG9yID0gY2l0eSksIA0KICAgICAgICAgICAgIHNpemUgPSAzKSsNCiAgbGFicyh0aXRsZT0iQ29tcGFyaXNvbiBvZiBzYWxlcyBieSB0aW1lIGZvciB0aGUgZGlmZmVyZW50IGNpdGllcyIsDQogICAgICAgeD0idGltZSIsDQogICAgICAgeT0ic2FsZXMiKSsNCiAgIHNjYWxlX3hfY29udGludW91cyhicmVha3MgPSAoc2VxKDEsNjAsIGJ5ID0gNikpLA0KICAgICAgICAgICAgICAgICAgICAgIGxhYmVscyA9IGJyZWFraW5nX3BvaW50cykrDQogIHRoZW1lX2NsYXNzaWMoKSsNCiAgdGhlbWUocGxvdC50aXRsZS5wb3NpdGlvbiA9ICJwYW5lbCIsDQogICAgICAgIHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZT0xOCwgaGp1c3Q9MC41KSwNCiAgICAgICAgYXhpcy50aXRsZS54ID0gZWxlbWVudF90ZXh0KHNpemU9MTYpLA0KICAgICAgICBheGlzLnRpdGxlLnkgPSBlbGVtZW50X3RleHQoc2l6ZT0xNiksDQogICAgICAgIGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KHNpemU9MTApLA0KICAgICAgICBheGlzLnRleHQueSA9IGVsZW1lbnRfdGV4dChzaXplPTEwKSwNCiAgICAgICAgbGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKQ0KDQoNCiMgV2UgcHJvZHVjZSB0aGUgcGxvdCB3aXRoIHRoZSB0cmVuZCBvZiB0aGUgdm9sdW1lIG92ZXIgdGltZS4NCmxpbmVfdm9sdW1lIDwtIGdncGxvdChkYXRhPWRhdGFzZXQpKw0KICBnZW9tX2xpbmUoYWVzKHggPSBkYXRlLA0KICAgICAgICAgICAgICAgIHkgPSB2b2x1bWUsDQogICAgICAgICAgICAgICAgZ3JvdXAgPSBjaXR5LA0KICAgICAgICAgICAgICAgIGNvbG9yID0gY2l0eSksIA0KICAgICAgICAgICAgc2l6ZSA9IDEuNSkrDQogIGdlb21fcG9pbnQoYWVzKHggPSBkYXRlLA0KICAgICAgICAgICAgICAgIHkgPSB2b2x1bWUsDQogICAgICAgICAgICAgICAgZ3JvdXAgPSBjaXR5LA0KICAgICAgICAgICAgICAgIGNvbG9yID0gY2l0eSksIA0KICAgICAgICAgICAgIHNpemUgPSAzKSsNCiAgbGFicyh0aXRsZT0iQ29tcGFyaXNvbiBvZiB2b2x1bWUgYnkgdGltZSBmb3IgdGhlIGRpZmZlcmVudCBjaXRpZXMiLA0KICAgICAgIHg9InRpbWUiLA0KICAgICAgIHk9InZvbHVtZSIpKw0KICAgc2NhbGVfeF9jb250aW51b3VzKGJyZWFrcyA9IChzZXEoMSw2MCwgYnkgPSA2KSksDQogICAgICAgICAgICAgICAgICAgICAgbGFiZWxzID0gYnJlYWtpbmdfcG9pbnRzKSsNCiAgdGhlbWVfY2xhc3NpYygpKw0KICB0aGVtZShwbG90LnRpdGxlLnBvc2l0aW9uID0gInBhbmVsIiwNCiAgICAgICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplPTE4LCBoanVzdD0wLjUpLA0KICAgICAgICBheGlzLnRpdGxlLnggPSBlbGVtZW50X3RleHQoc2l6ZT0xNiksDQogICAgICAgIGF4aXMudGl0bGUueSA9IGVsZW1lbnRfdGV4dChzaXplPTE2KSwNCiAgICAgICAgYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoc2l6ZT0xMCksDQogICAgICAgIGF4aXMudGV4dC55ID0gZWxlbWVudF90ZXh0KHNpemU9MTApLA0KICAgICAgICBsZWdlbmQucG9zaXRpb24gPSAibm9uZSIpDQoNCg0KIyBXZSBwcm9kdWNlIHRoZSBwbG90IHdpdGggdGhlIHRyZW5kIG9mIHRoZSBtZWRpYW5fcHJpY2Ugb3ZlciB0aW1lLg0KbGluZV9wcmljZSA8LSBnZ3Bsb3QoZGF0YT1kYXRhc2V0KSsNCiAgZ2VvbV9saW5lKGFlcyh4ID0gZGF0ZSwNCiAgICAgICAgICAgICAgICB5ID0gbWVkaWFuX3ByaWNlLA0KICAgICAgICAgICAgICAgIGdyb3VwID0gY2l0eSwNCiAgICAgICAgICAgICAgICBjb2xvciA9IGNpdHkpLCANCiAgICAgICAgICAgIHNpemUgPSAxLjUpKw0KICBnZW9tX3BvaW50KGFlcyh4ID0gZGF0ZSwNCiAgICAgICAgICAgICAgICB5ID0gbWVkaWFuX3ByaWNlLA0KICAgICAgICAgICAgICAgIGdyb3VwID0gY2l0eSwNCiAgICAgICAgICAgICAgICBjb2xvciA9IGNpdHkpLCANCiAgICAgICAgICAgICBzaXplID0gMykrDQogIGxhYnModGl0bGU9IkNvbXBhcmlzb24gb2YgbWVkaWFuIHByaWNlIGJ5IHRpbWUgZm9yIHRoZSBkaWZmZXJlbnQgY2l0aWVzIiwNCiAgICAgICB4PSJ0aW1lIiwNCiAgICAgICB5PSJtZWRpYW4gcHJpY2UiKSsNCiAgIHNjYWxlX3hfY29udGludW91cyhicmVha3MgPSAoc2VxKDEsNjAsIGJ5ID0gNikpLA0KICAgICAgICAgICAgICAgICAgICAgIGxhYmVscyA9IGJyZWFraW5nX3BvaW50cykrDQogIHRoZW1lX2NsYXNzaWMoKSsNCiAgdGhlbWUocGxvdC50aXRsZS5wb3NpdGlvbiA9ICJwYW5lbCIsDQogICAgICAgIHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZT0xOCwgaGp1c3Q9MC41KSwNCiAgICAgICAgYXhpcy50aXRsZS54ID0gZWxlbWVudF90ZXh0KHNpemU9MTYpLA0KICAgICAgICBheGlzLnRpdGxlLnkgPSBlbGVtZW50X3RleHQoc2l6ZT0xNiksDQogICAgICAgIGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KHNpemU9MTApLA0KICAgICAgICBheGlzLnRleHQueSA9IGVsZW1lbnRfdGV4dChzaXplPTEwKSwNCiAgICAgICAgbGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKQ0KDQoNCg0KIyBXZSBwcm9kdWNlIHRoZSBwbG90IHdpdGggdGhlIHRyZW5kIG9mIHRoZSBsaXN0aW5ncyBvdmVyIHRpbWUuDQpsaW5lX2xpc3RpbmdzIDwtIGdncGxvdChkYXRhPWRhdGFzZXQpKw0KICBnZW9tX2xpbmUoYWVzKHggPSBkYXRlLA0KICAgICAgICAgICAgICAgIHkgPSBsaXN0aW5ncywNCiAgICAgICAgICAgICAgICBncm91cCA9IGNpdHksDQogICAgICAgICAgICAgICAgY29sb3IgPSBjaXR5KSwgDQogICAgICAgICAgICBzaXplID0gMS41KSsNCiAgZ2VvbV9wb2ludChhZXMoeCA9IGRhdGUsDQogICAgICAgICAgICAgICAgeSA9IGxpc3RpbmdzLA0KICAgICAgICAgICAgICAgIGdyb3VwID0gY2l0eSwNCiAgICAgICAgICAgICAgICBjb2xvciA9IGNpdHkpLCANCiAgICAgICAgICAgICBzaXplID0gMykrDQogIGxhYnModGl0bGU9IkNvbXBhcmlzb24gb2YgbGlzdGluZ3MgYnkgdGltZSBmb3IgdGhlIGRpZmZlcmVudCBjaXRpZXMiLA0KICAgICAgIHg9InRpbWUiLA0KICAgICAgIHk9Imxpc3RpbmdzIikrDQogICBzY2FsZV94X2NvbnRpbnVvdXMoYnJlYWtzID0gKHNlcSgxLDYwLCBieSA9IDYpKSwNCiAgICAgICAgICAgICAgICAgICAgICBsYWJlbHMgPSBicmVha2luZ19wb2ludHMpKw0KICB0aGVtZV9jbGFzc2ljKCkrDQogIHRoZW1lKHBsb3QudGl0bGUucG9zaXRpb24gPSAicGFuZWwiLA0KICAgICAgICBwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemU9MTgsIGhqdXN0PTAuNSksDQogICAgICAgIGF4aXMudGl0bGUueCA9IGVsZW1lbnRfdGV4dChzaXplPTE2KSwNCiAgICAgICAgYXhpcy50aXRsZS55ID0gZWxlbWVudF90ZXh0KHNpemU9MTYpLA0KICAgICAgICBheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChzaXplPTEwKSwNCiAgICAgICAgYXhpcy50ZXh0LnkgPSBlbGVtZW50X3RleHQoc2l6ZT0xMCksDQogICAgICAgIGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikNCg0KDQojIFdlIHByb2R1Y2UgdGhlIHBsb3Qgd2l0aCB0aGUgdHJlbmQgb2YgdGhlIG1vbnRoc19pbnZlbnRvcnkgb3ZlciB0aW1lLg0KbGluZV9pbnZlbnRvcnkgPC0gZ2dwbG90KGRhdGE9ZGF0YXNldCkrDQogIGdlb21fbGluZShhZXMoeCA9IGRhdGUsDQogICAgICAgICAgICAgICAgeSA9IG1vbnRoc19pbnZlbnRvcnksDQogICAgICAgICAgICAgICAgZ3JvdXAgPSBjaXR5LA0KICAgICAgICAgICAgICAgIGNvbG9yID0gY2l0eSksIA0KICAgICAgICAgICAgc2l6ZSA9IDEuNSkrDQogIGdlb21fcG9pbnQoYWVzKHggPSBkYXRlLA0KICAgICAgICAgICAgICAgIHkgPSBtb250aHNfaW52ZW50b3J5LA0KICAgICAgICAgICAgICAgIGdyb3VwID0gY2l0eSwNCiAgICAgICAgICAgICAgICBjb2xvciA9IGNpdHkpLCANCiAgICAgICAgICAgICBzaXplID0gMykrDQogIGxhYnModGl0bGU9IkNvbXBhcmlzb24gb2YgbW9udGhzIGludmVudG9yeSBieSB0aW1lIGZvciB0aGUgZGlmZmVyZW50IGNpdGllcyIsDQogICAgICAgeD0idGltZSIsDQogICAgICAgeT0ibW9udGhzIGludmVudG9yeSIpKw0KICAgc2NhbGVfeF9jb250aW51b3VzKGJyZWFrcyA9IChzZXEoMSw2MCwgYnkgPSA2KSksDQogICAgICAgICAgICAgICAgICAgICAgbGFiZWxzID0gYnJlYWtpbmdfcG9pbnRzKSsNCiAgdGhlbWVfY2xhc3NpYygpKw0KICB0aGVtZShwbG90LnRpdGxlLnBvc2l0aW9uID0gInBhbmVsIiwNCiAgICAgICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplPTE4LCBoanVzdD0wLjUpLA0KICAgICAgICBheGlzLnRpdGxlLnggPSBlbGVtZW50X3RleHQoc2l6ZT0xNiksDQogICAgICAgIGF4aXMudGl0bGUueSA9IGVsZW1lbnRfdGV4dChzaXplPTE2KSwNCiAgICAgICAgYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoc2l6ZT0xMCksDQogICAgICAgIGF4aXMudGV4dC55ID0gZWxlbWVudF90ZXh0KHNpemU9MTApLA0KICAgICAgICBsZWdlbmQucG9zaXRpb24gPSAibm9uZSIpDQoNCg0KIyBXZSBjb21iaW5lIGFsbCB0aGUgYWJvdmUgcGxvdHMgYW5kIHRoZSBsYWJlbCBpbiBvbmUgZmlndXJlLg0KY29tYl9saW5lc19maWcgPSBsaW5lX3NhbGVzICsgbGluZV92b2x1bWUgKyBsaW5lX3ByaWNlICsgbGluZV9saXN0aW5ncyArIGxpbmVfaW52ZW50b3J5ICsgbGVnZW5kX2xpbmUgICsgcGxvdF9sYXlvdXQobmNvbD0yLCBoZWlnaHRzID0gYyg1LCA1LCA1KSkNCnByaW50KGNvbWJfbGluZXNfZmlnKQ0KDQojIFdlIGNsb3NlIGFsbCB0aGUgcGxvdHMgY3JlYXRlZCBhYm92ZS4NCnJtKGxpbmVfc2FsZXMsIGxpbmVfdm9sdW1lLCBsaW5lX3ByaWNlLCBsaW5lX2xpc3RpbmdzLCBsaW5lX2ludmVudG9yeSwgbGVnZW5kX2xpbmUsIGNvbWJfbGluZXNfZmlnKQ0KYGBgDQoNCkZyb20gdGhlIGxhc3QgcGxvdHMgd2Ugb2JzZXJ2ZToNCg0KLSBBIHBlcmlvZGljIHRyZW5kIGluIGFsbW9zdCBhbGwgdGhlIHZhcmlhYmxlcywgd2l0aCB0aGUgZXhjZXB0aW9uIG9mIHRoZSBtZWRpYW5fcHJpY2UuIEluIHBhcnRpY3VsYXIsIGhpZ2hlciBzYWxlcywgdm9sdW1lLCBsaXN0aW5ncyBhbmQgbW9udGggaW52ZW50b3J5IGFyZSBvYnNlcnZlZCBpbiB0aGUgc3VtbWVyIHJhdGhlciB0aGFuIGluIHRoZSB3aW50ZXIuDQpUaGUgZGlmZmVyZW5jZSBiZXR3ZWVuIHN1bW1lciBhbmQgd2ludGVyIGlzIHdlbGwgbWFya2VkIGluIHRoZSBjaXRpZXMgb2YgVHlsZXIgYW5kIEJyeWFuLUNvbGxlZ2UgU3RhdGlvbiB3aGlsZSBhbG1vc3QgaW1wZXJjZXB0aWJsZSBpbiB0aGUgY2l0eSBvZiBXaWNoaXRhIEZhbGxzLg0KDQotIEl0IGlzIGFsc28gcG9zc2libGUgdG8gb2JzZXJ2ZSB0aGF0LCBpbiBhdmVyYWdlLCB0aGUgbGlzdGluZ3MgYW5kIG1vbnRocyBpbnZlbnRvcnkgYXJlIGRlY3JlYXNpbmcgb3ZlciB0aGUgeWVhciB3aGlsZSBzYWxlcywgdm9sdW1lIGFuZCBtZWRpYW4gcHJpY2UgYXJlIGluY3JlYXNpbmcuIEFsc28gaW4gdGhpcyBjYXNlLCB0aGUgY2l0eSBvZiBXaWNoaXRhIEZhbGxzIGlzIHRoZSBvbmUgd2hlcmUgdGhpcyBwaGVub21lbm9uIGlzIGxlc3MgZXZpZGVudC4NCg0KV2Ugc3R1ZHkgZGVlcGVyIGFuZCBxdWFudGlmeSB0aGVzZSBwaGVub21lbmEsIGFuZCBvdGhlciB0aGF0IGNhbiBiZSBvYnNlcnZlZCBpbiB0aGUgcGxvdHMsIGluIHRoZSBmb2xsb3dpbmcgb2YgdGhpcyByZXBvcnQuIA0KDQoNCg0KIyMgKio8c3BhbiBzdHlsZT0iY29sb3I6cmVkIj4gWzddIDwvc3Bhbj4gQW5hbHlzaXMgb2YgdGhlIHZhcmlhYmxlcyBiYXNlZCBvbiBjaXRpZXMsIHllYXJzIGFuZCBtb250aHMqKg0KDQojIyMgRmlyc3Qgd2UgcHJvdmlkZSBhIHN0YXRpc3RpY2FsIGFuYWx5c2lzIG9mIHRoZSBxdWFudGl0YXRpdmUgdmFyaWFibGVzLCBjb21wdXRpbmcgdGhlaXIgbWVhbiwgc3RhbmRhcmQgZGV2aWF0aW9uIGFuZCB2YXJpYXRpb24gY29lZmZpY2llbnQsIGJhc2VkIG9uIGNpdGllcyBhbmQgeWVhci4NCldlIHN1bW1hcml6ZSB0aGUgcmVzdWx0cyBpbiB0aGUgdGFibGVzIGJlbG93IGFuZCByZXByZXNlbnQgdGhlIHJlc3VsdHMgZ3JhcGhpY2FsbHkgYnkgYmFyIHBsb3RzIGFuZCBib3ggcGxvdHMuDQoNCg0KIyMjIFRoZSAxc3QgdGFibGUgc3R1ZGllcyB0aGUgc3RhdGlzdGljcyBvZiB0aGUgdmFyaWFibGVzIG92ZXIgdGhlIGRpZmZlcmVudCBjaXRpZXMNCg0KYGBge3J9DQojIHdlIHVzZSB0aGUgcGFja2FnZSBkcGx5ciB0byBjb25kdWN0IGNvbmRpdGlvbmVkIHN0YXRpc3RpY2FsIGFuYWx5c2lzIGJ5IGNpdHkgYW5kIHllYXIuDQoNCmNvbmRpdGlvbmFsX2RhdGFzZXRfY2l0eSA8LQ0KICBkYXRhc2V0ICU+JSANCiAgZ3JvdXBfYnkoY2l0eSkgJT4lDQogIHN1bW1hcmlzZShtZWFuX3NhbGVzID0gcm91bmQobWVhbihzYWxlcyksMiksDQogICAgICAgICAgICBzZF9zYWxlcyA9IHJvdW5kKHNkKHNhbGVzKSwyKSwNCiAgICAgICAgICAgIGN2X3NhbGVzID0gcm91bmQoY3ZfZnVuY3Qoc2FsZXMpLCAyKSwNCiAgDQogICAgICAgICAgICBtZWFuX3ZvbHVtZT1yb3VuZChtZWFuKHZvbHVtZSksMiksDQogICAgICAgICAgICBzZF92b2x1bWU9cm91bmQoc2Qodm9sdW1lKSwyKSwNCiAgICAgICAgICAgIGN2X3ZvbHVtZSA9IHJvdW5kKGN2X2Z1bmN0KHZvbHVtZSksIDIpLA0KICAgICAgICAgICAgDQogICAgICAgICAgICBtZWFuX21lZF9wcmljZT1yb3VuZChtZWFuKG1lZGlhbl9wcmljZSksMiksDQogICAgICAgICAgICBzZF9tZWRfcHJpY2U9cm91bmQoc2QobWVkaWFuX3ByaWNlKSwyKSwNCiAgICAgICAgICAgIGN2X21lZF9wcmljZSA9IHJvdW5kKGN2X2Z1bmN0KG1lZGlhbl9wcmljZSksIDIpLA0KICAgICAgICAgICAgDQogICAgICAgICAgICBtZWFuX21lYW5fcHJpY2U9cm91bmQobWVhbihtZWFuX3ByaWNlKSwyKSwNCiAgICAgICAgICAgIHNkX21lYW5fcHJpY2U9cm91bmQoc2QobWVhbl9wcmljZSksMiksDQogICAgICAgICAgICBjdl9tZWFuX3ByaWNlID0gcm91bmQoY3ZfZnVuY3QobWVhbl9wcmljZSksIDIpLA0KICAgICAgICAgICAgDQogICAgICAgICAgICBtZWFuX2xpc3RpbmdzPXJvdW5kKG1lYW4obGlzdGluZ3MpLDIpLA0KICAgICAgICAgICAgc2RfbGlzdGluZ3M9cm91bmQoc2QobGlzdGluZ3MpLDIpLA0KICAgICAgICAgICAgY3ZfbGlzdGluZ3MgPSByb3VuZChjdl9mdW5jdChsaXN0aW5ncyksIDIpLA0KICANCiAgICAgICAgICAgIG1lYW5faW52ZW50b3J5PXJvdW5kKG1lYW4obW9udGhzX2ludmVudG9yeSksMiksDQogICAgICAgICAgICBzZF9pbnZlbnRvcnk9cm91bmQoc2QobW9udGhzX2ludmVudG9yeSksMiksDQogICAgICAgICAgICBjdl9pbnZlbnRvcnkgPSByb3VuZChjdl9mdW5jdChtb250aHNfaW52ZW50b3J5KSwgMiksDQogICAgICAgICAgICANCiAgICAgICAgICAgIG1lYW5fZWZmZWN0aXZuZXNzPXJvdW5kKG1lYW4oZWZmZWN0aXZlbmVzcyksMiksDQogICAgICAgICAgICBzZF9lZmZlY3RpdmVuZXNzPXJvdW5kKHNkKGVmZmVjdGl2ZW5lc3MpLDIpLA0KICAgICAgICAgICAgY3ZfZWZmZWN0aXZlbmVzcyA9IHJvdW5kKGN2X2Z1bmN0KGVmZmVjdGl2ZW5lc3MpLCAyKSwNCiAgICAgICAgICAgICkNCg0KZGZfdCA8LSBhcy5kYXRhLmZyYW1lKHQoY29uZGl0aW9uYWxfZGF0YXNldF9jaXR5WzI6ZGltKGNvbmRpdGlvbmFsX2RhdGFzZXRfY2l0eSlbMl1dKSkNCmNvbG5hbWVzKGRmX3QpID0gY29uZGl0aW9uYWxfZGF0YXNldF9jaXR5JGNpdHkNCmRhdGF0YWJsZShkZl90LCBvcHRpb25zID0gbGlzdChwYWdlTGVuZ3RoID0gMjEpLCBjYXB0aW9uPSJTdGF0aXN0aWNhbCBhbmFseXNpcyBvZiB0aGUgZGF0YXNldCBiYXNlZCBvbiBjaXR5IikNCmBgYA0KDQoNCiMjIyBUaGUgMm5kIHRhYmxlIHN0dWRpZXMgdGhlIHN0YXRpc3RpY3Mgb2YgdGhlIHZhcmlhYmxlcyBvdmVyIHRoZSBkaWZmZXJlbnQgeWVhcg0KYGBge3J9DQpjb25kaXRpb25hbF9kYXRhc2V0X3llYXIgPC0gZGF0YXNldCAlPiUgDQogIGdyb3VwX2J5KHllYXIpICU+JSANCiAgc3VtbWFyaXNlKG1lYW5fc2FsZXMgPSByb3VuZChtZWFuKHNhbGVzKSwyKSwNCiAgICAgICAgICAgIHNkX3NhbGVzID0gcm91bmQoc2Qoc2FsZXMpLDIpLA0KICAgICAgICAgICAgY3Zfc2FsZXMgPSByb3VuZChjdl9mdW5jdChzYWxlcyksIDIpLA0KICANCiAgICAgICAgICAgIG1lYW5fdm9sdW1lPXJvdW5kKG1lYW4odm9sdW1lKSwyKSwNCiAgICAgICAgICAgIHNkX3ZvbHVtZT1yb3VuZChzZCh2b2x1bWUpLDIpLA0KICAgICAgICAgICAgY3Zfdm9sdW1lID0gcm91bmQoY3ZfZnVuY3Qodm9sdW1lKSwgMiksDQogICAgICAgICAgICANCiAgICAgICAgICAgIG1lYW5fbWVkX3ByaWNlPXJvdW5kKG1lYW4obWVkaWFuX3ByaWNlKSwyKSwNCiAgICAgICAgICAgIHNkX21lZF9wcmljZT1yb3VuZChzZChtZWRpYW5fcHJpY2UpLDIpLA0KICAgICAgICAgICAgY3ZfbWVkX3ByaWNlID0gcm91bmQoY3ZfZnVuY3QobWVkaWFuX3ByaWNlKSwgMiksDQogICAgICAgICAgICANCiAgICAgICAgICAgIG1lYW5fbWVhbl9wcmljZT1yb3VuZChtZWFuKG1lYW5fcHJpY2UpLDIpLA0KICAgICAgICAgICAgc2RfbWVhbl9wcmljZT1yb3VuZChzZChtZWFuX3ByaWNlKSwyKSwNCiAgICAgICAgICAgIGN2X21lYW5fcHJpY2UgPSByb3VuZChjdl9mdW5jdChtZWFuX3ByaWNlKSwgMiksDQogICAgICAgICAgICANCiAgICAgICAgICAgIG1lYW5fbGlzdGluZ3M9cm91bmQobWVhbihsaXN0aW5ncyksMiksDQogICAgICAgICAgICBzZF9saXN0aW5ncz1yb3VuZChzZChsaXN0aW5ncyksMiksDQogICAgICAgICAgICBjdl9saXN0aW5ncyA9IHJvdW5kKGN2X2Z1bmN0KGxpc3RpbmdzKSwgMiksDQogIA0KICAgICAgICAgICAgbWVhbl9pbnZlbnRvcnk9cm91bmQobWVhbihtb250aHNfaW52ZW50b3J5KSwyKSwNCiAgICAgICAgICAgIHNkX2ludmVudG9yeT1yb3VuZChzZChtb250aHNfaW52ZW50b3J5KSwyKSwNCiAgICAgICAgICAgIGN2X2ludmVudG9yeSA9IHJvdW5kKGN2X2Z1bmN0KG1vbnRoc19pbnZlbnRvcnkpLCAyKSwNCiAgICAgICAgICAgIA0KICAgICAgICAgICAgbWVhbl9lZmZlY3Rpdm5lc3M9cm91bmQobWVhbihlZmZlY3RpdmVuZXNzKSwyKSwNCiAgICAgICAgICAgIHNkX2VmZmVjdGl2ZW5lc3M9cm91bmQoc2QoZWZmZWN0aXZlbmVzcyksMiksDQogICAgICAgICAgICBjdl9lZmZlY3RpdmVuZXNzID0gcm91bmQoY3ZfZnVuY3QoZWZmZWN0aXZlbmVzcyksIDIpLA0KICAgICAgICAgICAgKQ0KDQoNCmRmX3QgPC0gYXMuZGF0YS5mcmFtZSh0KGNvbmRpdGlvbmFsX2RhdGFzZXRfeWVhclsyOmRpbShjb25kaXRpb25hbF9kYXRhc2V0X3llYXIpWzJdXSkpDQpjb2xuYW1lcyhkZl90KSA9IGNvbmRpdGlvbmFsX2RhdGFzZXRfeWVhciR5ZWFyDQpkYXRhdGFibGUoZGZfdCwgb3B0aW9ucyA9IGxpc3QocGFnZUxlbmd0aCA9IDIxKSwgY2FwdGlvbj0iU3RhdGlzdGljYWwgYW5hbHlzaXMgb2YgdGhlIGRhdGFzZXQgYmFzZWQgb24geWVhciIpDQpgYGANCg0KDQoNCg0KYGBge3J9DQoNCiMgV2UgY3JlYXRlIGEgZGF0YXNldCB3aGVyZSB3ZSBjb25kdWN0IGEgc3RhdGlzdGljYWwgYW5hbHlzaXMgY29uZGl0aW9uZWQgYm90aCB0byBjaXR5IGFuZCB5ZWFyLCBzbyB2YXJ5aW5nIG9ubHkgdGhlIG1vbnRocywgZm9yIGVhY2ggY291cGxlIChjaXR5LHllYXIpIHdlIGNvbXB1dGUgdGhlIHRvdGFsIGFtb3VudCBvZiBzYWxlcyB2b2x1bWUgYW5kIGxpc3RpbmdzIGFuZCB0aGUgbWVkaWFuIG1vbnRoc19pbnZlbnRvcnksIG1lZGlhbiBwcmljZSBhbmQgZWZmZWN0aXZlbmVzcyB2YXJ5aW5nIHRoZSBtb250aHMNCg0KY29uZGl0aW9uYWxfZGF0YXNldF9jaXR5X3llYXIgPC0gZGF0YXNldCAlPiUgDQogIGdyb3VwX2J5KHllYXIsIGNpdHkpICU+JSANCiAgc3VtbWFyaXNlKHNhbGVzID0gc3VtKHNhbGVzKSwNCiAgICAgICAgICAgIHZvbHVtZSA9IHN1bSh2b2x1bWUpLA0KICAgICAgICAgICAgbGlzdGluZ3MgPSBzdW0obGlzdGluZ3MpLA0KICAgICAgICAgICAgbWVkaWFuX21vbnRoc19pbnZlbnRvcnk9bWVkaWFuKG1vbnRoc19pbnZlbnRvcnkpLA0KICAgICAgICAgICAgbWVkaWFuX21lZGlhbl9wcmljZT1tZWRpYW4obWVkaWFuX3ByaWNlKSwNCiAgICAgICAgICAgIG1lZGlhbl9lZmZlY3RpdmVuZXNzPW1lZGlhbihlZmZlY3RpdmVuZXNzKQ0KICAgICAgICAgICAgKQ0KYGBgDQoNCg0KDQojIyMgVGhlIG5leHQgcGxvdCB2aXN1YWxpemVzIHRoZSB0b3RhbCBzYWxlcyBhbmQgdm9sdW1lIG92ZXIgdGhlIHllYXJzIGFuZCBjaXRpZXMNCg0KYGBge3IsIGZpZy53aWR0aD0xMywgZmlnLmhlaWdodD01fQ0KIyBXZSBjcmVhdGUgYmFycGxvdHMgdG8gdmlzdWFsaXplIHRoZSB0b3RhbCBzYWxlcyBhbmQgdm9sdW1lIG92ZXIgdGhlIHllYXJzIGFuZCBjaXRpZXMNCg0KIyBUaGUgbmV4dCBwbG90IGlzIGNyZWF0ZWQgb25seSB0byBleHRyYXBvbGF0ZSB0aGUgbGVnZW5kDQpiYXJfc2FsZXNfeWVhciA8LSAgZ2dwbG90KGRhdGE9Y29uZGl0aW9uYWxfZGF0YXNldF9jaXR5X3llYXIsIA0KICAgICAgICAgICAgICAgICAgICAgICAgYWVzKHg9eWVhciwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICB5PXNhbGVzLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZpbGw9Y2l0eSkpKw0KICAgICAgICAgICAgICAgICAgZ2VvbV9jb2woc3RhdD0iaWRlbnRpdHkiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgcG9zaXRpb249InN0YWNrIikrDQogICAgICAgICAgICAgICAgICB0aGVtZShsZWdlbmQudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE2KSwNCiAgICAgICAgICAgICAgICAgICAgICAgIGxlZ2VuZC50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNCkpDQoNCiNleHRyYXBvbGF0ZSB0aGUgbGVnZW5kDQpsZWdlbmRfY2l0eSA8LSBhc19nZ3Bsb3QoZ2V0X2xlZ2VuZChiYXJfc2FsZXNfeWVhcikpDQoNCiMjDQojIw0KIyMNCg0KI2JhcnBsb3Qgd2l0aCB0aGUgdG90YWwgc2FsZXMgb3ZlciB5ZWFycyBhbmQgY2l0aWVzDQpiYXJfc2FsZXNfeWVhciA8LSAgZ2dwbG90KGRhdGE9Y29uZGl0aW9uYWxfZGF0YXNldF9jaXR5X3llYXIsDQogICAgICAgICAgICAgICAgICAgICAgICBhZXMoeD15ZWFyLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIHk9c2FsZXMsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgZmlsbD1jaXR5KSkrDQogICAgICAgICAgICAgICAgICBnZW9tX2NvbChzdGF0PSJpZGVudGl0eSIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICBwb3NpdGlvbj0gImRvZGdlIikrDQogICAgICAgICAgICAgICAgICBsYWJzKHRpdGxlPSJDb21wYXJpc29uIG9mIHRvdGFsIHNhbGVzIGJ5IHllYXIgb3ZlciBjaXR5IiwNCiAgICAgICAgICAgICAgICAgICAgICAgeD0ieWVhciIsDQogICAgICAgICAgICAgICAgICAgICAgIHk9Ik51bWJlciBvZiBzYWxlcyIpKw0KICAgICAgICAgICAgICAgICAgdGhlbWVfY2xhc3NpYygpKw0KICAgICAgICAgICAgICAgICAgdGhlbWUocGxvdC50aXRsZS5wb3NpdGlvbiA9ICJwYW5lbCIsDQogICAgICAgICAgICAgICAgICAgICAgICBwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemU9MTYsIGhqdXN0PTAuNSksDQogICAgICAgICAgICAgICAgICAgICAgICBheGlzLnRpdGxlLnggPSBlbGVtZW50X3RleHQoc2l6ZT0xNCksDQogICAgICAgICAgICAgICAgICAgICAgICBheGlzLnRpdGxlLnkgPSBlbGVtZW50X3RleHQoc2l6ZT0xNCksDQogICAgICAgICAgICAgICAgICAgICAgICBheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChzaXplPTEwKSwNCiAgICAgICAgICAgICAgICAgICAgICAgIGF4aXMudGV4dC55ID0gZWxlbWVudF90ZXh0KHNpemU9MTApLA0KICAgICAgICAgICAgICAgICAgICAgICAgbGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKSsNCiAgICAgICAgICAgICAgICAgICAgICAgIHNjYWxlX3lfY29udGludW91cyhicmVha3MgPSBzZXEoMCwgNDAwMCwgYnkgPSAyNTApKQ0KDQojIw0KIyMNCiMjDQoNCiNiYXJwbG90IHdpdGggdGhlIHRvdGFsIHZvbHVtZSBvdmVyIHllYXJzIGFuZCBjaXRpZXMNCmJhcl92b2x1bWVfeWVhciA8LSBnZ3Bsb3QoZGF0YT1jb25kaXRpb25hbF9kYXRhc2V0X2NpdHlfeWVhciwNCiAgICAgICAgICAgICAgICAgICAgICAgICBhZXMoeD15ZWFyLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICB5PXZvbHVtZSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmlsbD1jaXR5KSkrDQogICAgICAgICAgICAgICAgICBnZW9tX2NvbChzdGF0PSJpZGVudGl0eSIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICBwb3NpdGlvbj0iZG9kZ2UiKSsNCiAgICAgICAgICAgICAgICAgIGxhYnModGl0bGU9IkNvbXBhcmlzb24gb2YgdG90YWwgdm9sdW1lIGJ5IHllYXIgb3ZlciBjaXR5IiwNCiAgICAgICAgICAgICAgICAgICAgICAgeD0ieWVhciIsDQogICAgICAgICAgICAgICAgICAgICAgIHk9IlVTJCIpKw0KICAgICAgICAgICAgICAgICAgdGhlbWVfY2xhc3NpYygpKw0KICAgICAgICAgICAgICAgICAgdGhlbWUocGxvdC50aXRsZS5wb3NpdGlvbiA9ICJwYW5lbCIsDQogICAgICAgICAgICAgICAgICAgICAgICBwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemU9MTYsIGhqdXN0PTAuNSksDQogICAgICAgICAgICAgICAgICAgICAgICBheGlzLnRpdGxlLnggPSBlbGVtZW50X3RleHQoc2l6ZT0xNCksDQogICAgICAgICAgICAgICAgICAgICAgICBheGlzLnRpdGxlLnkgPSBlbGVtZW50X3RleHQoc2l6ZT0xNCksDQogICAgICAgICAgICAgICAgICAgICAgICBheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChzaXplPTEwKSwNCiAgICAgICAgICAgICAgICAgICAgICAgIGF4aXMudGV4dC55ID0gZWxlbWVudF90ZXh0KHNpemU9MTApLA0KICAgICAgICAgICAgICAgICAgICAgICAgbGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKSsNCiAgICAgICAgICAgICAgICAgICAgICAgIHNjYWxlX3lfY29udGludW91cyhicmVha3MgPSBzZXEoMCwgNzAwLCBieSA9IDUwKSwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGFiZWxzID0gbGFiZWxfbnVtYmVyKHN1ZmZpeCA9ICJNIikpDQoNCiMjDQojIw0KIyMNCg0KI2NvbWJpbmUgdGhlIHR3byBwbG90cyBpbiBvbmUgZmlndXJlIGFuZCBkaXNwbGF5IGl0Lg0KY29tYl9maWdfMiA8LSBiYXJfc2FsZXNfeWVhciArIGJhcl92b2x1bWVfeWVhciArIGxlZ2VuZF9jaXR5ICsgcGxvdF9sYXlvdXQobmNvbD0zLCB3aWR0aHMgPSBjKDUsIDUsIDMpLCBoZWlnaHRzID0gYyg1KSkNCnByaW50KGNvbWJfZmlnXzIpDQpgYGANCg0KDQoNCg0KIyMjIFRoZSBuZXh0IHBsb3QgdmlzdWFsaXplcyBob3cgdGhlIHNhbGVzIGFuZCB2b2x1bWUgYXJlIGRpc3RyaWJ1dGVkIGluIHBlcmNlbnRhZ2Ugd2l0aCByZXNwZWN0IHRvIHRoZSBjaXRpZXMgb3ZlciB0aGUgeWVhcnMuDQpgYGB7ciwgZmlnLndpZHRoPTEzLCBmaWcuaGVpZ2h0PTV9DQojIFdlIGNyZWF0ZSBiYXJwbG90cyB0byB2aXN1YWxpemUgaG93IHRoZSBzYWxlcyBhbmQgdm9sdW1lLCBvdmVyIHRoZSB5ZWFycywgYXJlIGRpc3RyaWJ1dGVkIGluIHBlcmNlbnRhZ2UgYWNyb3NzIHRoZSBjaXRpZXMNCg0KI2JhcnBsb3Qgd2l0aCB0aGUgcGVyY2VudGFnZSBzYWxlcyBvdmVyIGNpdGllcywgdmFyeWluZyB0aGUgeWVhcnMNCmJhcl9zYWxlc195ZWFyXzIgPC0gIGdncGxvdChkYXRhPWNvbmRpdGlvbmFsX2RhdGFzZXRfY2l0eV95ZWFyLA0KICAgICAgICAgICAgICAgICAgICAgICAgYWVzKHg9eWVhciwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICB5PXNhbGVzLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZpbGw9Y2l0eSkpKw0KICAgICAgICAgICAgICAgICAgZ2VvbV9jb2woc3RhdD0iaWRlbnRpdHkiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgcG9zaXRpb249ICJmaWxsIikrDQogICAgICAgICAgICAgICAgICBsYWJzKHRpdGxlPSJDb21wYXJpc29uIG9mIHRvdGFsIHNhbGVzIGJ5IHllYXIgb3ZlciBjaXR5IiwNCiAgICAgICAgICAgICAgICAgICAgICAgeD0ieWVhciIsDQogICAgICAgICAgICAgICAgICAgICAgIHk9InNhbGVzIikrDQogICAgICAgICAgICAgICAgICB0aGVtZV9jbGFzc2ljKCkrDQogICAgICAgICAgICAgICAgICB0aGVtZShwbG90LnRpdGxlLnBvc2l0aW9uID0gInBhbmVsIiwNCiAgICAgICAgICAgICAgICAgICAgICAgIHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZT0xNiwgaGp1c3Q9MC41KSwNCiAgICAgICAgICAgICAgICAgICAgICAgIGF4aXMudGl0bGUueCA9IGVsZW1lbnRfdGV4dChzaXplPTE0KSwNCiAgICAgICAgICAgICAgICAgICAgICAgIGF4aXMudGl0bGUueSA9IGVsZW1lbnRfdGV4dChzaXplPTE0KSwNCiAgICAgICAgICAgICAgICAgICAgICAgIGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KHNpemU9MTApLA0KICAgICAgICAgICAgICAgICAgICAgICAgYXhpcy50ZXh0LnkgPSBlbGVtZW50X3RleHQoc2l6ZT0xMCksDQogICAgICAgICAgICAgICAgICAgICAgICBsZWdlbmQucG9zaXRpb24gPSAibm9uZSIpKw0KICAgICAgICAgICAgICAgICAgICAgICAgc2NhbGVfeV9jb250aW51b3VzKGxhYmVscyA9IHBlcmNlbnRfZm9ybWF0KCksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWtzID0gc2VxKDAsIDEsIGJ5ID0gMC4xKSkgDQoNCiMjDQojIw0KIyMNCg0KI2JhcnBsb3Qgd2l0aCB0aGUgcGVyY2VudGFnZSB2b2x1bWUgb3ZlciBjaXRpZXMsIHZhcnlpbmcgdGhlIHllYXJzDQpiYXJfdm9sdW1lX3llYXJfMiA8LSBnZ3Bsb3QoZGF0YT1jb25kaXRpb25hbF9kYXRhc2V0X2NpdHlfeWVhciwNCiAgICAgICAgICAgICAgICAgICAgICAgICBhZXMoeD15ZWFyLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICB5PXZvbHVtZSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmlsbD1jaXR5KSkrDQogICAgICAgICAgICAgICAgICBnZW9tX2NvbChzdGF0PSJpZGVudGl0eSIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICBwb3NpdGlvbj0iZmlsbCIpKw0KICAgICAgICAgICAgICAgICAgbGFicyh0aXRsZT0iQ29tcGFyaXNvbiBvZiB0b3RhbCB2b2x1bWUgYnkgeWVhciBvdmVyIGNpdHkiLA0KICAgICAgICAgICAgICAgICAgICAgICB4PSJ5ZWFyIiwNCiAgICAgICAgICAgICAgICAgICAgICAgeT0idm9sdW1lIikrDQogICAgICAgICAgICAgICAgICB0aGVtZV9jbGFzc2ljKCkrDQogICAgICAgICAgICAgICAgICB0aGVtZShwbG90LnRpdGxlLnBvc2l0aW9uID0gInBhbmVsIiwNCiAgICAgICAgICAgICAgICAgICAgICAgIHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZT0xNiwgaGp1c3Q9MC41KSwNCiAgICAgICAgICAgICAgICAgICAgICAgIGF4aXMudGl0bGUueCA9IGVsZW1lbnRfdGV4dChzaXplPTE0KSwNCiAgICAgICAgICAgICAgICAgICAgICAgIGF4aXMudGl0bGUueSA9IGVsZW1lbnRfdGV4dChzaXplPTE0KSwNCiAgICAgICAgICAgICAgICAgICAgICAgIGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KHNpemU9MTApLA0KICAgICAgICAgICAgICAgICAgICAgICAgYXhpcy50ZXh0LnkgPSBlbGVtZW50X3RleHQoc2l6ZT0xMCksDQogICAgICAgICAgICAgICAgICAgICAgICBsZWdlbmQucG9zaXRpb24gPSAibm9uZSIpKw0KICAgICAgICAgICAgICAgICAgICAgICAgc2NhbGVfeV9jb250aW51b3VzKGxhYmVscyA9IHBlcmNlbnRfZm9ybWF0KCksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWtzID0gc2VxKDAsIDEsIGJ5ID0gMC4xKSkgDQoNCg0KDQojY29tYmluZSB0aGUgdHdvIHBsb3RzIGluIG9uZSBmaWd1cmUgYW5kIGRpc3BsYXkgaXQuDQpjb21iX2ZpZ18yXzUgPC0gYmFyX3NhbGVzX3llYXJfMiArIGJhcl92b2x1bWVfeWVhcl8yICsgbGVnZW5kX2NpdHkgKyBwbG90X2xheW91dChuY29sPTMsIHdpZHRocyA9IGMoNSwgNSwgMyksIGhlaWdodHMgPSBjKDUpKQ0KcHJpbnQoY29tYl9maWdfMl81KQ0KYGBgDQoNCg0KDQoNCg0KIyMjIFRoZSBuZXh0IHBsb3QgdmlzdWFsaXplcyB0aGUgZXZvbHV0aW9uIG9mIGxpc3RpbmdzIGFuZCBtb250aCBpbnZlbnRvcnkgYnkgeWVhcnMgYW5kIGNpdGllcw0KYGBge3IsIGZpZy53aWR0aD0xMywgZmlnLmhlaWdodD01fQ0KIyBXZSBzdHVkeSB0aGUgZXZvbHV0aW9uIG9mIGxpc3RpbmdzIGFuZCBtb250aCBpbnZlbnRvcnkgb3ZlciB0aGUgeWVhcnMgYW5kIHZhcnlpbmcgdGhlIGNpdGllcy4gV2Ugc3R1ZHkgdGhlIGxpc3RpbmcgYnkgbWVhbnMgb2YgYSBiYXJwbG90IGFuZCBtb250aCBpbnZlbnRvcnkgYnkgbWVhbnMgb2YgYSBib3ggcGxvdC4NCg0KDQoNCiMgVGhlIG5leHQgcGxvdCBpcyBjcmVhdGVkIG9ubHkgdG8gZXh0cmFwb2xhdGUgdGhlIGxlZ2VuZA0KYmFyX2xpc3RpbmdzX2NpdHkgPC0gZ2dwbG90KGRhdGE9Y29uZGl0aW9uYWxfZGF0YXNldF9jaXR5X3llYXIsIA0KICAgICAgICAgICAgICAgICAgICAgIGFlcyh4PWNpdHksDQogICAgICAgICAgICAgICAgICAgICAgICAgIHk9bGlzdGluZ3MsDQogICAgICAgICAgICAgICAgICAgICAgICAgIGZpbGw9eWVhcikpKw0KICAgICAgICAgICAgICAgICAgICBnZW9tX2NvbChzdGF0PSJpZGVudGl0eSIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBvc2l0aW9uPSAiZG9kZ2UiKSsNCiAgICAgICAgICAgICAgICAgICAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gYygiMjAxMCIgPSAibGlnaHRibHVlMSIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIjIwMTEiID0gImxpZ2h0Ymx1ZTIiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICIyMDEyIiA9ICJsaWdodGJsdWUzIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiMjAxMyIgPSAibGlnaHRibHVlNCIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIjIwMTQiID0gIiMzNzRBNTkiDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKSkNCg0KbGVnZW5kX3llYXIgPC0gYXNfZ2dwbG90KGdldF9sZWdlbmQoYmFyX2xpc3RpbmdzX2NpdHkpKQ0KDQoNCiNiYXJwbG90IHdpdGggdGhlIHRvdGFsIG51bWJlciBvZiBsaXN0aW5ncyB2YXJ5aW5nIHRoZSB5ZWFycyBhbmQgY2l0aWVzDQpiYXJfbGlzdGluZ3NfY2l0eSA8LSBnZ3Bsb3QoZGF0YT1jb25kaXRpb25hbF9kYXRhc2V0X2NpdHlfeWVhciwgDQogICAgICAgICAgICAgICAgICAgICAgYWVzKHg9Y2l0eSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgeT1saXN0aW5ncywNCiAgICAgICAgICAgICAgICAgICAgICAgICAgZmlsbD15ZWFyKSkrDQogICAgICAgICAgICAgICAgICAgIGdlb21fY29sKHN0YXQ9ImlkZW50aXR5IiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcG9zaXRpb249ICJkb2RnZSIpKw0KICAgICAgICAgICAgICAgICAgICBsYWJzKHRpdGxlPSJDb21wYXJpc29uIG9mIHRvdGFsIGxpc3RpbmdzIGJ5IGNpdHkgb3ZlciB5ZWFyIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICB4PSJjaXR5IiwNCiAgICAgICAgICAgICAgICAgICAgICAgICB5PSJsaXN0aW5ncyIpKw0KICAgICAgICAgICAgICAgICAgICB0aGVtZV9jbGFzc2ljKCkrDQogICAgICAgICAgICAgICAgICAgIHRoZW1lKHBsb3QudGl0bGUucG9zaXRpb24gPSAicGFuZWwiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICBwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemU9MTYsIGhqdXN0PTAuNSksDQogICAgICAgICAgICAgICAgICAgICAgICAgIGF4aXMudGl0bGUueCA9IGVsZW1lbnRfdGV4dChzaXplPTE0KSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgYXhpcy50aXRsZS55ID0gZWxlbWVudF90ZXh0KHNpemU9MTQpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICBheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChzaXplPTEwKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgYXhpcy50ZXh0LnkgPSBlbGVtZW50X3RleHQoc2l6ZT0xMCksDQogICAgICAgICAgICAgICAgICAgICAgICAgIGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikrDQogICAgICAgICAgICAgICAgICAgICAgICAgIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IGMoIjIwMTAiID0gImxpZ2h0Ymx1ZTEiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICIyMDExIiA9ICJsaWdodGJsdWUyIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiMjAxMiIgPSAibGlnaHRibHVlMyIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIjIwMTMiID0gImxpZ2h0Ymx1ZTQiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICIyMDE0IiA9ICIjMzc0QTU5Ig0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICkpKw0KICAgICAgICAgICAgICAgICAgICAgICAgICBzY2FsZV95X2NvbnRpbnVvdXMoYnJlYWtzID0gc2VxKDAsIDM1MDAwLCBieSA9IDI1MDApLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGFiZWxzID0gcGFzdGUwKHNlcSgwLDM1MCwgYnk9MjUpLCJLIikpDQoNCiMjDQojIw0KIyMNCg0KI2JveHBsb3QgdG8gc3R1ZHkgdGhlIHN0YXRpc3RpY3Mgb2YgbW9udGhfaW52ZW50b3J5IHZhcnlpbmcgdGhlIHllYXJzIGFuZCBjaXRpZXMNCmJveF9pbnZlbnRvcnlfY2l0eSA8LSBnZ3Bsb3QoZGF0YT1kYXRhc2V0LA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFlcyh4PWNpdHksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHk9bW9udGhzX2ludmVudG9yeSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmlsbD15ZWFyKSkrDQogICAgICAgICAgICAgICAgICAgICBnZW9tX2JveHBsb3QoKSsNCiAgICAgICAgICAgICAgICAgICAgIGxhYnModGl0bGU9IkNvbXBhcmlzb24gb2YgbW9udGhzIGludmVudG9yeSBieSBjaXR5IG92ZXIgeWVhciIsDQogICAgICAgICAgICAgICAgICAgICAgICAgIHg9ImNpdHkiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICB5PSJtb250aHNfaW52ZW50b3J5IikrDQogICAgICAgICAgICAgICAgICAgICB0aGVtZV9jbGFzc2ljKCkrDQogICAgICAgICAgICAgICAgICAgICB0aGVtZShwbG90LnRpdGxlLnBvc2l0aW9uID0gInBhbmVsIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgIHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZT0xNiwgaGp1c3Q9MC41KSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgIGF4aXMudGl0bGUueCA9IGVsZW1lbnRfdGV4dChzaXplPTE0KSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgIGF4aXMudGl0bGUueSA9IGVsZW1lbnRfdGV4dChzaXplPTE0KSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgIGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KHNpemU9MTApLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgYXhpcy50ZXh0LnkgPSBlbGVtZW50X3RleHQoc2l6ZT0xMCksDQogICAgICAgICAgICAgICAgICAgICAgICAgICBsZWdlbmQucG9zaXRpb24gPSAibm9uZSIpKw0KICAgICAgICAgICAgICAgICAgICAgICAgICAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gYygiMjAxMCIgPSAibGlnaHRibHVlMSIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICIyMDExIiA9ICJsaWdodGJsdWUyIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIjIwMTIiID0gImxpZ2h0Ymx1ZTMiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiMjAxMyIgPSAibGlnaHRibHVlNCIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICIyMDE0IiA9ICIjMzc0QTU5Ig0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApKSsNCiAgICAgICAgICAgICAgICAgICAgICAgICAgc2NhbGVfeV9jb250aW51b3VzKGJyZWFrcyA9IHNlcSg0LCAxNCwgYnkgPSAyKSkNCg0KDQoNCiNjb21iaW5lIHRoZSB0d28gcGxvdHMgaW4gb25lIGZpZ3VyZSBhbmQgZGlzcGxheSBpdC4NCmNvbWJfZmlnXzMgPC0gYmFyX2xpc3RpbmdzX2NpdHkgKyBib3hfaW52ZW50b3J5X2NpdHkgKyBsZWdlbmRfeWVhciArIHBsb3RfbGF5b3V0KG5jb2w9Mywgd2lkdGhzID0gYyg1LCA1LCAxKSwgaGVpZ2h0cyA9IGMoNSkpDQpwcmludChjb21iX2ZpZ18zKQ0KYGBgDQoNCg0KDQoNCiMjIyBUaGUgbmV4dCBwbG90IHZpc3VhbGl6ZXMgdGhlIGV2b2x1dGlvbiBvZiB0aGUgc2VsbGluZyBtZWRpYW4gcHJpY2UgYW5kIHNlbGxpbmcgZWZmaWNpZW5jeSBvdmVyIHRoZSB5ZWFycyBhbmQgY2l0aWVzDQpgYGB7ciwgZmlnLndpZHRoPTEzLCBmaWcuaGVpZ2h0PTV9DQojIFdlIHN0dWR5IHRoZSBldm9sdXRpb24gb2YgbWVkaWFuIHByaWNlcyBhbmQgZWZmaWNpZW5jeSBvdmVyIHRoZSB5ZWFycyBhbmQgdmFyeWluZyB0aGUgY2l0aWVzIGJ5IG1lYW5zIG9mIGJveHBsb3RzLiANCg0KI2JveHBsb3QgcmVwcmVzZW50aW5nIHRoZSBzdGF0aXN0aWNzIG9mIHRoZSBzZWxsaW5nIG1lZGlhbiBwcmljZSB2YXJ5aW5nIHRoZSB5ZWFycyBhbmQgY2l0aWVzDQpib3hfcHJpY2VfeWVhciA8LSBnZ3Bsb3QoKSsNCiAgICAgICAgICAgICAgICAgICAgZ2VvbV9saW5lKGRhdGEgPSBjb25kaXRpb25hbF9kYXRhc2V0X2NpdHlfeWVhciwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFlcyh4ID0geWVhciwgeSA9IG1lZGlhbl9tZWRpYW5fcHJpY2UsIGdyb3VwID0gY2l0eSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb2xvciA9IGNpdHkpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcG9zaXRpb24gPSBwb3NpdGlvbl9kb2RnZSh3aWR0aCA9IDAuNzUpKSArDQogICAgICAgICAgICAgICAgICAgIGdlb21fYm94cGxvdChkYXRhPWRhdGFzZXQsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYWVzKHg9eWVhciwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB5PW1lZGlhbl9wcmljZSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmaWxsPWNpdHkpKSsNCiAgICAgICAgICAgICAgICAgICAgbGFicyh0aXRsZT0iQ29tcGFyaXNvbiBvZiBtZWRpYW4gcHJpY2UgYnkgeWVhciBvdmVyIGNpdHkiLA0KICAgICAgICAgICAgICAgICAgICAgICAgIHg9InllYXIiLA0KICAgICAgICAgICAgICAgICAgICAgICAgIHk9Im1lZGlhbiBwcmljZSBVUyQiKSsNCiAgICAgICAgICAgICAgICAgICAgdGhlbWVfY2xhc3NpYygpKw0KICAgICAgICAgICAgICAgICAgICB0aGVtZShwbG90LnRpdGxlLnBvc2l0aW9uID0gInBhbmVsIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplPTE2LCBoanVzdD0wLjUpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICBheGlzLnRpdGxlLnggPSBlbGVtZW50X3RleHQoc2l6ZT0xNCksDQogICAgICAgICAgICAgICAgICAgICAgICAgIGF4aXMudGl0bGUueSA9IGVsZW1lbnRfdGV4dChzaXplPTE0KSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoc2l6ZT0xMCksDQogICAgICAgICAgICAgICAgICAgICAgICAgIGF4aXMudGV4dC55ID0gZWxlbWVudF90ZXh0KHNpemU9MTApLA0KICAgICAgICAgICAgICAgICAgICAgICAgICBsZWdlbmQucG9zaXRpb24gPSAibm9uZSIpKw0KICAgICAgICAgICAgICAgICAgICAgICAgICBzY2FsZV95X2NvbnRpbnVvdXMoYnJlYWtzID0gc2VxKDc1MDAwLCAxNzUwMDAsIGJ5ID0gMTAwMDApLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGFiZWxzPSBwYXN0ZTAoc2VxKDc1LCAxNzUsIGJ5ID0gMTApLCJLIikpDQoNCiAgICAgICAgICAgICAgICAgICAgICAgICANCiMgYm94cGxvdCByZXByZXNlbnRpbmcgdGhlIHN0YXRpc3RpY3Mgb2Ygc2VsbGluZyBlZmZpY2llbmN5IHZhcnlpbmcgdGhlIHllYXJzIGFuZCBjaXRpZXMNCg0KYm94X2VmZmVjdGl2ZW5lc3NfeWVhciA8LSBnZ3Bsb3QoKSsNCiAgICAgICAgICAgICAgICAgICAgZ2VvbV9saW5lKGRhdGEgPSBjb25kaXRpb25hbF9kYXRhc2V0X2NpdHlfeWVhciwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFlcyh4ID0geWVhciwgeSA9IG1lZGlhbl9lZmZlY3RpdmVuZXNzLCBncm91cCA9IGNpdHksIGNvbG9yID0gY2l0eSksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwb3NpdGlvbiA9IHBvc2l0aW9uX2RvZGdlKHdpZHRoID0gMC43NSkpICsNCiAgICAgICAgICAgICAgICAgICAgZ2VvbV9ib3hwbG90KGRhdGE9ZGF0YXNldCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFlcyh4PXllYXIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgeT1lZmZlY3RpdmVuZXNzLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZpbGw9Y2l0eSkpKw0KICAgICAgICAgICAgICAgICAgICBsYWJzKHRpdGxlPSJDb21wYXJpc29uIG9mIGVmZmVjdGl2ZW5lc3MgYnkgeWVhciBvdmVyIGNpdHkiLA0KICAgICAgICAgICAgICAgICAgICAgICAgIHg9InllYXIiLA0KICAgICAgICAgICAgICAgICAgICAgICAgIHk9ImVmZmVjdGl2ZW5lc3MiKSsNCiAgICAgICAgICAgICAgICAgICAgdGhlbWVfY2xhc3NpYygpKw0KICAgICAgICAgICAgICAgICAgICB0aGVtZShwbG90LnRpdGxlLnBvc2l0aW9uID0gInBhbmVsIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplPTE2LCBoanVzdD0wLjUpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICBheGlzLnRpdGxlLnggPSBlbGVtZW50X3RleHQoc2l6ZT0xNCksDQogICAgICAgICAgICAgICAgICAgICAgICAgIGF4aXMudGl0bGUueSA9IGVsZW1lbnRfdGV4dChzaXplPTE0KSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoc2l6ZT0xMCksDQogICAgICAgICAgICAgICAgICAgICAgICAgIGF4aXMudGV4dC55ID0gZWxlbWVudF90ZXh0KHNpemU9MTApLA0KICAgICAgICAgICAgICAgICAgICAgICAgICBsZWdlbmQucG9zaXRpb24gPSAibm9uZSIpKw0KICAgICAgICAgICAgICAgICAgICAgICAgICBzY2FsZV95X2NvbnRpbnVvdXMoYnJlYWtzID0gc2VxKDAsIDM1MCwgYnkgPSAyNSkpIA0KDQogIA0KDQojY29tYmluZSB0aGUgdHdvIHBsb3RzIGluIG9uZSBmaWd1cmUgYW5kIGRpc3BsYXkgaXQuDQpjb21iX2ZpZ180IDwtIGJveF9wcmljZV95ZWFyICsgYm94X2VmZmVjdGl2ZW5lc3NfeWVhciArIGxlZ2VuZF9jaXR5ICsgcGxvdF9sYXlvdXQobmNvbD0zLCB3aWR0aHMgPSBjKDUsIDUsIDMpLCBoZWlnaHRzID0gYyg1KSkNCnByaW50KGNvbWJfZmlnXzQpDQpgYGANCg0KDQpgYGB7cn0NCiNXZSBjbG9zZSBhbGwgdGhlIGZpZ3VyZXMgZ2VuZXJhdGVkIGFib3ZlDQpybShiYXJfc2FsZXNfeWVhciwgYmFyX3ZvbHVtZV95ZWFyLCBsZWdlbmRfY2l0eSwgYmFyX2xpc3RpbmdzX2NpdHksIGJveF9pbnZlbnRvcnlfY2l0eSwgbGVnZW5kX3llYXIsIGJveF9wcmljZV95ZWFyLCBib3hfZWZmZWN0aXZlbmVzc195ZWFyLCBiYXJfc2FsZXNfeWVhcl8yLCBiYXJfdm9sdW1lX3llYXJfMiwgY29tYl9maWdfMiwgY29tYl9maWdfMl81LCBjb21iX2ZpZ18zLCBjb21iX2ZpZ180KQ0KYGBgDQoNCg0KDQpGcm9tIHRoZSByZXN1bHRzIGFib3ZlIHdlIG9ic2VydmUgdGhhdDogDQoNCi0gVHlsZXIgaXMgdGhlIGNpdHkgd2l0aCBtb3JlIHNhbGVzIGFuZCB2b2x1bWUgYXMgYWxzbyB0aGUgY2l0eSB3aGVyZSB0aGUgc2FsZXMgYWRzIGFyZSBtb3JlIGVmZmljaWVudCBmb2xsb3dlZCBieSBCcmlhbi1Db2xsZWdlIFN0YXRpb24sIEJlYXVtb250IGFuZCBXaWNoaXRhIEZhbGxzIGluIGRlc2NlbmRpbmcgb3JkZXIuDQoNCi0gVGhlIG1lZGlhbiBwcmljZSBpcyBoaWdoZXIgaW4gQnJpYW4tQ29sbGVnZSBTdGF0aW9uIGZvbGxvd2VkIGJ5IFR5bGVyIGFuZCBCZWF1bW9udCBhbmQgZmluYWxseSBieSBXaWNoaXRhIEZhbGxzLg0KDQotIFR5bGVyIGlzIGFsc28gY2l0eSB3aXRoIHRoZSBoaWdoZXN0IG51bWJlciBvZiBsaXN0aW5ncyBhbmQgbW9udGhzIGludmVudG9yeSBmb2xsb3dlZCBieSBCZWF1bW9udCwgQnJ5YW4tQ29sbGVnZSBTdGF0aW9uIGFuZCBXaWNoaXRhIEZhbGxzLiANCg0KQWJvdXQgdGhlIHZhcmlhYmlsaXR5IG9mIHRoZSB2YXJpYWJsZXMgd2Ugb2JzZXJ2ZSB0aGF0OiAgDQoNCi0gVGhlIHJlbGF0aXZlIHZhcmlhYmlsaXR5IChtZWFzdXJlZCBpbiB0ZXJtcyBvZiB0aGUgY29lZmZpY2llbnQgb2YgdmFyaWF0aW9uKSBpbiB0aGUgdm9sdW1lIGFuZCBzYWxlcyBpbiBUeWxlciBpcyBiZXR3ZWVuIDEuNSBhbmQgMyB0aW1lcyBoaWdoZXIgdGhhbiB0aGUgdmFyaWFiaWxpdHkgdGhhdCB3ZSBvYnNlcnZlIGluIHRoZSBvdGhlciBjaXRpZXMuICAgDQoNCi0gQnJ5YW4tQ29sbGVnZSBTdGF0aW9uIGZhY2VzIGEgdmFyaWFiaWxpdHkgaW4gdGhlIGxpc3RpbmdzIGFuZCBtb250aCBpbnZlbnRvcnkgdGhhdCBpcyBhbG1vc3QgdHdpY2Ugb3IgbW9yZSB0aGUgdmFyaWFiaWxpdHkgaW4gdGhlIG90aGVyIGNpdGllcy4gDQoNCi0gRmluYWxseSBXaWNoaXRhIEZhbGxzIGlzIHRoZSBjaXR5IHdpdGggdGhlIGhpZ2hlc3QgdmFyaWFiaWxpdHkgaW4gdGhlIG1lZGlhbiBhbmQgbWVhbiBwcmljZXMuIEhvd2V2ZXIgdGhlIHZhcmlhYmlsaXR5IGluIHRoZSBtZWRpYW4gcHJpY2VzIGlzIHF1aXRlIHNtYWxsIGZvciBhbGwgdGhlIGNpdGllcy4gDQoNCioqVGhlIGdyYXBocyBjb25maXJtIGEgY2hhbmdlIGluIHRoZSB0cmVuZCBvZiB0aGUgdmFyaWFibGVzIGFuZCBzbyBvZiB0aGUgcmVhbCBlc3RhdGUgbWFya2V0IGFmdGVyIDIwMTEuIE9uIHRoZSBvbmUgaGFuZCwgd2Ugb2JzZXJ2ZSBhbiBpbmNyZWFzZSBpbiB0aGUgbnVtYmVyIG9mIHNhbGVzLCB2b2x1bWUsIG1lZGlhbiBwcmljZSwgYW5kIGVmZmljaWVuY3k7IG9uIHRoZSBvdGhlciBoYW5kIHRoZSBudW1iZXIgb2YgbGlzdGluZ3MgYW5kIG1vbnRobHkgaW52ZW50b3J5IGRlY3JlYXNlcy4gVGhlIG9ubHkgY2l0eSB0aGF0IGRvZXNuJ3Qgc2VlbSB0byBmb2xsb3cgdGhlc2UgdHJlbmRzIGlzIFdpY2hpdGEgRmFsbHMsIHdoZXJlIHRoZSBzaXR1YXRpb24gZG9lc24ndCBzZWVtIHRvIGJlIGNoYW5naW5nIG92ZXIgdGhlIHllYXJzLioqIFdlIGRvIG5vdCBvYnNlcnZlIHNpZ25pZmljYW50IGRpZmZlcmVuY2VzIGluIHRoZSB2YXJpYWJpbGl0eSBvZiB0aGUgdmFyaWFibGVzIG92ZXIgdGhlIHllYXIuDQoNCg0KDQojIyMgTmV4dCB3ZSBjb25kdWN0IGEgc3RhdGlzdGljYWwgc3R1ZHkgYWJvdXQgdGhlIHZhcmlhYmlsaXR5IGFuZCB0cmVuZHMgb2YgdGhlIGRpZmZlcmVudCB2YXJpYWJsZXMgb3ZlciB0aGUgbW9udGhzLg0KDQoNCmBgYHtyfQ0KIyBuZXh0IHdlIGNvbmR1Y3QgYSBzdGF0aXN0aWNhbCBhbmFseXNpcyBjb25kaXRpb25lZCBib3RoIHRvIHRoZSBtb250aHMNCmNvbmRpdGlvbmFsX2RhdGFzZXRfbW9udGggPC0gDQogIGRhdGFzZXQgJT4lIA0KICBncm91cF9ieShtb250aCkgJT4lICAgDQogICBzdW1tYXJpc2UobWVhbl9zYWxlcyA9IHJvdW5kKG1lYW4oc2FsZXMpLDIpLA0KICAgICAgICAgICAgc2Rfc2FsZXMgPSByb3VuZChzZChzYWxlcyksMiksDQogICAgICAgICAgICBjdl9zYWxlcyA9IHJvdW5kKGN2X2Z1bmN0KHNhbGVzKSwgMiksDQogIA0KICAgICAgICAgICAgbWVhbl92b2x1bWU9cm91bmQobWVhbih2b2x1bWUpLDIpLA0KICAgICAgICAgICAgc2Rfdm9sdW1lPXJvdW5kKHNkKHZvbHVtZSksMiksDQogICAgICAgICAgICBjdl92b2x1bWUgPSByb3VuZChjdl9mdW5jdCh2b2x1bWUpLCAyKSwNCiAgICAgICAgICAgIA0KICAgICAgICAgICAgbWVhbl9tZWRfcHJpY2U9cm91bmQobWVhbihtZWRpYW5fcHJpY2UpLDIpLA0KICAgICAgICAgICAgc2RfbWVkX3ByaWNlPXJvdW5kKHNkKG1lZGlhbl9wcmljZSksMiksDQogICAgICAgICAgICBjdl9tZWRfcHJpY2UgPSByb3VuZChjdl9mdW5jdChtZWRpYW5fcHJpY2UpLCAyKSwNCiAgICAgICAgICAgIA0KICAgICAgICAgICAgbWVhbl9tZWFuX3ByaWNlPXJvdW5kKG1lYW4obWVhbl9wcmljZSksMiksDQogICAgICAgICAgICBzZF9tZWFuX3ByaWNlPXJvdW5kKHNkKG1lYW5fcHJpY2UpLDIpLA0KICAgICAgICAgICAgY3ZfbWVhbl9wcmljZSA9IHJvdW5kKGN2X2Z1bmN0KG1lYW5fcHJpY2UpLCAyKSwNCiAgICAgICAgICAgIA0KICAgICAgICAgICAgbWVhbl9saXN0aW5ncz1yb3VuZChtZWFuKGxpc3RpbmdzKSwyKSwNCiAgICAgICAgICAgIHNkX2xpc3RpbmdzPXJvdW5kKHNkKGxpc3RpbmdzKSwyKSwNCiAgICAgICAgICAgIGN2X2xpc3RpbmdzID0gcm91bmQoY3ZfZnVuY3QobGlzdGluZ3MpLCAyKSwNCiAgDQogICAgICAgICAgICBtZWFuX2ludmVudG9yeT1yb3VuZChtZWFuKG1vbnRoc19pbnZlbnRvcnkpLDIpLA0KICAgICAgICAgICAgc2RfaW52ZW50b3J5PXJvdW5kKHNkKG1vbnRoc19pbnZlbnRvcnkpLDIpLA0KICAgICAgICAgICAgY3ZfaW52ZW50b3J5ID0gcm91bmQoY3ZfZnVuY3QobW9udGhzX2ludmVudG9yeSksIDIpLA0KICAgICAgICAgICAgDQogICAgICAgICAgICBtZWFuX2VmZmVjdGl2bmVzcz1yb3VuZChtZWFuKGVmZmVjdGl2ZW5lc3MpLDIpLA0KICAgICAgICAgICAgc2RfZWZmZWN0aXZlbmVzcz1yb3VuZChzZChlZmZlY3RpdmVuZXNzKSwyKSwNCiAgICAgICAgICAgIGN2X2VmZmVjdGl2ZW5lc3MgPSByb3VuZChjdl9mdW5jdChlZmZlY3RpdmVuZXNzKSwgMiksDQogICAgICAgICAgICApIA0KDQoNCg0KDQpkZl90IDwtIGFzLmRhdGEuZnJhbWUodChjb25kaXRpb25hbF9kYXRhc2V0X21vbnRoWzI6ZGltKGNvbmRpdGlvbmFsX2RhdGFzZXRfbW9udGgpWzJdXSkpDQpjb2xuYW1lcyhkZl90KSA8LSBjKCJKYW4iLCAiRmViIiwgIk1hciIsICJBcHIiLCAiTWF5IiwgIkp1biIsICJKdWwiLCAiQXVnIiwgIlNlcCIsICJPY3QiLCAiTm92IiwgIkRlYyIpDQpkYXRhdGFibGUoZGZfdCwgb3B0aW9ucyA9IGxpc3Qoc2Nyb2xsWCA9IFRSVUUsIHBhZ2VMZW5ndGggPSAyMSksIGNhcHRpb249IlN0YXRpc3RpY2FsIGFuYWx5c2lzIG9mIHRoZSBkYXRhc2V0IGJhc2VkIG9uIG1vbnRoIikNCmBgYA0KDQpUaGUgdGFibGUgcmVmbGVjdCBhICoqcGVyaW9kaWMgdHJlbmQgb2YgYWxsIHRoZSB2YXJpYWJsZXMgYWxvbmcgdGhlIHllYXIsIGhhdmluZzoqKiAgDQoNCi0gKipNb3JlIHNhbGVzLCB2b2x1bWUgYW5kIGxpc3RpbmdzIGFuZCBoaWdoZXIgbW9udGggaW52ZW50b3J5IGR1cmluZyB0aGUgc3VtbWVyIHdpdGggcmVzcGVjdCB0byB0aGUgd2ludGVyLioqDQoNClRoZSB2YXJpYWJsZXMgZWZmZWN0aXZlbmVzcyBhbmQgbWVkaWFuL21lYW4gcHJpY2UgYXJlIHRoZSBvbmx5IG9uZXMgdGhhdCBzZWVtIG5vdCB0byBiZSBhZmZlY3RlZCBieSB0aGlzIHBlcmlvZGljIHRyZW5kLg0KDQojIyMgVG8gY2FwdHVyZSB0aGVzZSBwZXJpb2RpYyB0cmVuZHMgd2Ugc3R1ZHkgdGhlIG1vbnRobHkgdmFyaWF0aW9uIChpbiBwZXJjZW50YWdlKSBvZiB0aGUgdmFyaWFibGVzIHdpdGggcmVzcGVjdCB0byB0aGVpciBtZWFuLg0KDQpgYGB7cn0NCiMgdGhlIGZ1bmN0aW9uIGZvcm1hdF9wZXJjZW50YWdlIHdyaXRlcyBpbiBwZXJjZW50YWdlIGZvcm1hdCB0aGUgdmFsdWVzIHRoYXQgd2UgcHJvdmlkZQ0KZm9ybWF0X3BlcmNlbnRhZ2UgPC0gZnVuY3Rpb24odmFsdWVzKSB7DQogIHBlcmNlbnRfdmFsdWVzIDwtIHJvdW5kKHZhbHVlcyAqIDEwMCwgMikNCiAgc2lnbl92YWx1ZXMgPC0gaWZlbHNlKHBlcmNlbnRfdmFsdWVzID4gMCwgcGFzdGUwKCIrIiwgcGVyY2VudF92YWx1ZXMpLCBhcy5jaGFyYWN0ZXIocGVyY2VudF92YWx1ZXMpKQ0KICBwYXN0ZTAoc2lnbl92YWx1ZXMsICIlIikNCn0NCg0KDQoNCiMgbmV4dCBhIGRhdGVzIGlzIGNyZWF0ZWQgd2hlcmUgd2UgcmVwb3J0IHRoZSBwZXJjZW50YWdlIHZhcmlhdGlvbiBvZiB0aGUgdmFyaWFibGVzIG92ZXIgdGhlIG1vbnRocyB3aXRoIHJlc3BlY3QgdG8gdGhlaXIgbWVhbg0KY29uZGl0aW9uYWxfZGF0YXNldF9tb250aF9wZXJjZW50YWdlcyA8LSBkYXRhLmZyYW1lKHNhbGVzID0gZm9ybWF0X3BlcmNlbnRhZ2UoKGNvbmRpdGlvbmFsX2RhdGFzZXRfbW9udGgkbWVhbl9zYWxlcy1zdGF0aXN0aWNzWyJzYWxlcyIsIm1lYW4iXSkgLyBzdGF0aXN0aWNzWyJzYWxlcyIsIm1lYW4iXSksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdm9sdW1lID0gZm9ybWF0X3BlcmNlbnRhZ2UoKGNvbmRpdGlvbmFsX2RhdGFzZXRfbW9udGgkbWVhbl92b2x1bWUtc3RhdGlzdGljc1sidm9sdW1lIiwibWVhbiJdKSAvIHN0YXRpc3RpY3NbInZvbHVtZSIsIm1lYW4iXSksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWVkaWFuX3ByaWNlID0gZm9ybWF0X3BlcmNlbnRhZ2UoKGNvbmRpdGlvbmFsX2RhdGFzZXRfbW9udGgkbWVhbl9tZWRfcHJpY2Utc3RhdGlzdGljc1sibWVkaWFuX3ByaWNlIiwibWVhbiJdKS8gc3RhdGlzdGljc1sibWVkaWFuX3ByaWNlIiwibWVhbiJdKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsaXN0aW5ncyA9IGZvcm1hdF9wZXJjZW50YWdlKChjb25kaXRpb25hbF9kYXRhc2V0X21vbnRoJG1lYW5fbGlzdGluZ3Mtc3RhdGlzdGljc1sibGlzdGluZ3MiLCJtZWFuIl0pIC8gc3RhdGlzdGljc1sibGlzdGluZ3MiLCJtZWFuIl0pLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1vbnRoX2ludmVudG9yeT1mb3JtYXRfcGVyY2VudGFnZSgoY29uZGl0aW9uYWxfZGF0YXNldF9tb250aCRtZWFuX2ludmVudG9yeS1zdGF0aXN0aWNzWyJtb250aHNfaW52ZW50b3J5IiwibWVhbiJdKS9zdGF0aXN0aWNzWyJtb250aHNfaW52ZW50b3J5IiwibWVhbiJdKQ0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICkgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIA0KDQpyb3duYW1lcyhjb25kaXRpb25hbF9kYXRhc2V0X21vbnRoX3BlcmNlbnRhZ2VzKSA8LSBjKCJKYW4iLCAiRmViIiwgIk1hciIsICJBcHIiLCAiTWF5IiwgIkp1biIsICJKdWwiLCAiQXVnIiwgIlNlcCIsICJPY3QiLCAiTm92IiwgIkRlYyIpDQpkYXRhdGFibGUoY29uZGl0aW9uYWxfZGF0YXNldF9tb250aF9wZXJjZW50YWdlcywgb3B0aW9ucyA9IGxpc3Qoc2Nyb2xsWCA9IFRSVUUsIHBhZ2VMZW5ndGggPSAyMSksIGNhcHRpb249IlZhcmlhdGlvbiBvZiB0aGUgbW9udGhseSBtZWFuIG9mIHRoZSB2YXJpYWJsZXMgY29tcGFyZWQgdG8gdGhlaXIgbWVhbiB2YWx1ZSIpDQpgYGANCg0KTGFzdCwgd2Ugc3R1ZHkgdGhlIHZhcmlhYmlsaXR5IG9mIHRoZSBzYWxlcywgdm9sdW1lIGFuZCBsaXN0aW5ncyBib3RoIG92ZXIgdGhlIG1vbnRocyBhbmQgYWNyb3NzIGRpZmZlcmVudCBjaXRpZXMuIFdlIHByZXNlbnQgdGhlIHJlc3VsdHMgdmlhIGJhciBwbG90cy4gDQoNCmBgYHtyfQ0KIyBmaXJzdCB3ZSBjcmVhdGUgYSBkYXRhc2V0IHdoZXJlIHdlIGNvbmR1Y3QgYSBzdGF0aXN0aWNhbCBhbmFseXNpcyBjb25kaXRpb25lZCBib3RoIHRvIGNpdHkgYW5kIG1vbnRoLCBzbyB2YXJ5aW5nIG9ubHkgdGhlIHllYXINCiMgZm9yIGVhY2ggY291cGxlIChjaXR5LG1vbnRoKSB3ZSBjb21wdXRlIHRoZSB0b3RhbCBhbW91bnQgb2Ygc2FsZXMgdm9sdW1lIGFuZCBsaXN0aW5ncyBhbmQgdGhlIG1lZGlhbiBtb250aHNfaW52ZW50b3J5LCBtZWRpYW4gcHJpY2UgYW5kIGVmZmVjdGl2ZW5lc3MgdmFyeWluZyB0aGUgeWVhcnMNCmNvbmRpdGlvbmFsX2RhdGFzZXRfY2l0eV9tb250aCA8LSBkYXRhc2V0ICU+JQ0KICBncm91cF9ieShtb250aCwgY2l0eSkgJT4lDQogIHN1bW1hcmlzZShzYWxlcyA9IHN1bShzYWxlcyksDQogICAgICAgICAgICB2b2x1bWUgPSBzdW0odm9sdW1lKSwNCiAgICAgICAgICAgIGxpc3RpbmdzID0gc3VtKGxpc3RpbmdzKSwNCiAgICAgICAgICAgIG1lZGlhbl9tb250aHNfaW52ZW50b3J5PW1lZGlhbihtb250aHNfaW52ZW50b3J5KSwNCiAgICAgICAgICAgIG1lZGlhbl9tZWRpYW5fcHJpY2U9bWVkaWFuKG1lZGlhbl9wcmljZSksDQogICAgICAgICAgICBtZWRpYW5fZWZmZWN0aXZlbmVzcz1tZWRpYW4oZWZmZWN0aXZlbmVzcykNCiAgICAgICAgICAgICkNCiMgDQojIA0KIyBjb25kaXRpb25hbF9kYXRhc2V0X2NpdHlfbW9udGgkc2Vhc29uIDwtIHNhcHBseShjb25kaXRpb25hbF9kYXRhc2V0X2NpdHlfbW9udGgkbW9udGgsIHNlYXNvbikNCmBgYA0KDQoNCmBgYHtyLCBmaWcud2lkdGg9MTAsIGZpZy5oZWlnaHQ9MTZ9DQojIFdlIGNyZWF0ZSBiYXJwbG90cyB0byB2aXN1YWxpemUgdGhlIHBlcmlvZGljIHZhcmlhdGlvbnMgb2Ygc2FsZXMsIHZvbHVtZSBhbmQgbGlzdGluZ3Mgb3ZlciB0aGUgbW9udGhzIGFuZCBjaXRpZXMNCg0KIyBUaGUgbmV4dCBwbG90IGlzIGNyZWF0ZWQgb25seSB0byBleHRyYXBvbGF0ZSB0aGUgbGVnZW5kDQpiYXJfc2FsZXNfbW9udGggPSAgZ2dwbG90KGRhdGE9Y29uZGl0aW9uYWxfZGF0YXNldF9jaXR5X21vbnRoLA0KICAgICAgICAgICAgICAgICAgICAgICAgYWVzKHg9bW9udGgsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgeT1zYWxlcywNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBmaWxsPWNpdHkpKSsNCiAgICAgICAgICAgICAgICAgIGdlb21fY29sKHN0YXQ9ImlkZW50aXR5IiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgIHBvc2l0aW9uPSAic3RhY2siKSsNCiAgICAgICAgICAgICAgICAgIGxhYnModGl0bGU9IkNvbXBhcmlzb24gb2YgdG90YWwgc2FsZXMgYnkgbW9udGggb3ZlciBjaXR5IiwNCiAgICAgICAgICAgICAgICAgICAgICAgeD0ibW9udGgiLA0KICAgICAgICAgICAgICAgICAgICAgICB5PSJzYWxlcyIpKw0KICAgICAgICAgICAgICAgICAgdGhlbWVfY2xhc3NpYygpKw0KICAgICAgICAgICAgICAgICAgdGhlbWUocGxvdC50aXRsZS5wb3NpdGlvbiA9ICJwYW5lbCIsDQogICAgICAgICAgICAgICAgICAgICAgICBwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemU9MTQsIGhqdXN0PTAuNSksDQogICAgICAgICAgICAgICAgICAgICAgICBheGlzLnRpdGxlLnggPSBlbGVtZW50X3RleHQoc2l6ZT0xMiksDQogICAgICAgICAgICAgICAgICAgICAgICBheGlzLnRpdGxlLnkgPSBlbGVtZW50X3RleHQoc2l6ZT0xMiksDQogICAgICAgICAgICAgICAgICAgICAgICBheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChzaXplPTEwKSwNCiAgICAgICAgICAgICAgICAgICAgICAgIGF4aXMudGV4dC55ID0gZWxlbWVudF90ZXh0KHNpemU9MTApLA0KICAgICAgICAgICAgICAgICAgICAgICAgbGVnZW5kLnBvc2l0aW9uID0gImJvdHRvbSIsDQogICAgICAgICAgICAgICAgICAgICAgICBsZWdlbmQudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEyKSwNCiAgICAgICAgICAgICAgICAgICAgICAgIGxlZ2VuZC50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMikpDQoNCmxlZ2VuZF9tb250aCA8LSBhc19nZ3Bsb3QoZ2V0X2xlZ2VuZChiYXJfc2FsZXNfbW9udGgpKQ0KDQoNCiMgVGhlIG5leHQgYmFyIHBsb3Qgc2hvd3MgdGhlIHRvdGFsIG51bWJlciBvZiBzYWxlcyBwZXIgbW9udGggaW4gZXZlcnkgY2l0eQ0KYmFyX3NhbGVzX21vbnRoID0gIGdncGxvdChkYXRhPWNvbmRpdGlvbmFsX2RhdGFzZXRfY2l0eV9tb250aCwNCiAgICAgICAgICAgICAgICAgICAgICAgIGFlcyh4PW1vbnRoLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIHk9c2FsZXMsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgZmlsbD1jaXR5KSkrDQogICAgICAgICAgICAgICAgICBnZW9tX2NvbChzdGF0PSJpZGVudGl0eSIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICBwb3NpdGlvbj0gInN0YWNrIikrDQogICAgICAgICAgICAgICAgICBsYWJzKHRpdGxlPSJDb21wYXJpc29uIG9mIHRvdGFsIHNhbGVzIGJ5IG1vbnRoIG92ZXIgY2l0eSIsDQogICAgICAgICAgICAgICAgICAgICAgIHg9Im1vbnRoIiwNCiAgICAgICAgICAgICAgICAgICAgICAgeT0ic2FsZXMiKSsNCiAgICAgICAgICAgICAgICAgIHRoZW1lX2NsYXNzaWMoKSsNCiAgICAgICAgICAgICAgICAgIHRoZW1lKHBsb3QudGl0bGUucG9zaXRpb24gPSAicGFuZWwiLA0KICAgICAgICAgICAgICAgICAgICAgICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplPTE0LCBoanVzdD0wLjUpLA0KICAgICAgICAgICAgICAgICAgICAgICAgYXhpcy50aXRsZS54ID0gZWxlbWVudF90ZXh0KHNpemU9MTIpLA0KICAgICAgICAgICAgICAgICAgICAgICAgYXhpcy50aXRsZS55ID0gZWxlbWVudF90ZXh0KHNpemU9MTIpLA0KICAgICAgICAgICAgICAgICAgICAgICAgYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoc2l6ZT0xMCksDQogICAgICAgICAgICAgICAgICAgICAgICBheGlzLnRleHQueSA9IGVsZW1lbnRfdGV4dChzaXplPTEwKSwNCiAgICAgICAgICAgICAgICAgICAgICAgIGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikrDQogICAgICAgICAgICAgICAgICAgICAgICBzY2FsZV95X2NvbnRpbnVvdXMoYnJlYWtzID0gc2VxKDAsIDUwMDAsIGJ5ID0gNTAwKSkNCg0KDQoNCiMgVGhlIG5leHQgYmFyIHBsb3Qgc2hvd3MgdGhlIG51bWJlciBvZiBzYWxlcyBpbiBwZXJjZW50YWdlIHdpdGggcmVzcGVjdCB0byB0aGUgZGlmZmVyZW50IGNpdGllcyBwZXIgbW9udGggDQpiYXJfc2FsZXNfbW9udGhfMiA9ICBnZ3Bsb3QoZGF0YT1jb25kaXRpb25hbF9kYXRhc2V0X2NpdHlfbW9udGgsDQogICAgICAgICAgICAgICAgICAgICAgICBhZXMoeD1tb250aCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICB5PXNhbGVzLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZpbGw9Y2l0eSkpKw0KICAgICAgICAgICAgICAgICAgZ2VvbV9jb2woc3RhdD0iaWRlbnRpdHkiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgcG9zaXRpb249ICJmaWxsIikrDQogICAgICAgICAgICAgICAgICBsYWJzKHRpdGxlPSJDb21wYXJpc29uIG9mIHRvdGFsIHNhbGVzIGJ5IG1vbnRoIG92ZXIgY2l0eSIsDQogICAgICAgICAgICAgICAgICAgICAgIHg9Im1vbnRoIiwNCiAgICAgICAgICAgICAgICAgICAgICAgeT0ic2FsZXMgcGVyY2VudGFnZSIpKw0KICAgICAgICAgICAgICAgICAgdGhlbWVfY2xhc3NpYygpKw0KICAgICAgICAgICAgICAgICAgdGhlbWUocGxvdC50aXRsZS5wb3NpdGlvbiA9ICJwYW5lbCIsDQogICAgICAgICAgICAgICAgICAgICAgICBwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemU9MTQsIGhqdXN0PTAuNSksDQogICAgICAgICAgICAgICAgICAgICAgICBheGlzLnRpdGxlLnggPSBlbGVtZW50X3RleHQoc2l6ZT0xMiksDQogICAgICAgICAgICAgICAgICAgICAgICBheGlzLnRpdGxlLnkgPSBlbGVtZW50X3RleHQoc2l6ZT0xMiksDQogICAgICAgICAgICAgICAgICAgICAgICBheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChzaXplPTEwKSwNCiAgICAgICAgICAgICAgICAgICAgICAgIGF4aXMudGV4dC55ID0gZWxlbWVudF90ZXh0KHNpemU9MTApLA0KICAgICAgICAgICAgICAgICAgICAgICAgbGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKSsNCiAgICAgICAgICAgICAgICAgICAgICAgIHNjYWxlX3lfY29udGludW91cyhsYWJlbHMgPSBwZXJjZW50X2Zvcm1hdCgpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrcyA9IHNlcSgwLCAxLCBieSA9IDAuMSkpIA0KDQoNCiMgVGhlIG5leHQgYmFyIHBsb3Qgc2hvd3MgdGhlIHZvbHVtZSBwZXIgbW9udGggaW4gZXZlcnkgY2l0eQ0KYmFyX3ZvbHVtZV9tb250aCA9ICBnZ3Bsb3QoZGF0YT1jb25kaXRpb25hbF9kYXRhc2V0X2NpdHlfbW9udGgsDQogICAgICAgICAgICAgICAgICAgICAgICBhZXMoeD1tb250aCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICB5PXZvbHVtZSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBmaWxsPWNpdHkpKSsNCiAgICAgICAgICAgICAgICAgIGdlb21fY29sKHN0YXQ9ImlkZW50aXR5IiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgIHBvc2l0aW9uPSAic3RhY2siKSsNCiAgICAgICAgICAgICAgICAgIGxhYnModGl0bGU9IkNvbXBhcmlzb24gb2YgdG90YWwgdm9sdW1lIGJ5IG1vbnRoIG92ZXIgY2l0eSIsDQogICAgICAgICAgICAgICAgICAgICAgIHg9Im1vbnRoIiwNCiAgICAgICAgICAgICAgICAgICAgICAgeT0idm9sdW1lIFVTJCIpKw0KICAgICAgICAgICAgICAgICAgdGhlbWVfY2xhc3NpYygpKw0KICAgICAgICAgICAgICAgICAgdGhlbWUocGxvdC50aXRsZS5wb3NpdGlvbiA9ICJwYW5lbCIsDQogICAgICAgICAgICAgICAgICAgICAgICBwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemU9MTQsIGhqdXN0PTAuNSksDQogICAgICAgICAgICAgICAgICAgICAgICBheGlzLnRpdGxlLnggPSBlbGVtZW50X3RleHQoc2l6ZT0xMiksDQogICAgICAgICAgICAgICAgICAgICAgICBheGlzLnRpdGxlLnkgPSBlbGVtZW50X3RleHQoc2l6ZT0xMiksDQogICAgICAgICAgICAgICAgICAgICAgICBheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChzaXplPTEwKSwNCiAgICAgICAgICAgICAgICAgICAgICAgIGF4aXMudGV4dC55ID0gZWxlbWVudF90ZXh0KHNpemU9MTApLA0KICAgICAgICAgICAgICAgICAgICAgICAgbGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKSsNCiAgICAgICAgICAgICAgICAgICAgICAgIHNjYWxlX3lfY29udGludW91cyhicmVha3MgPSBzZXEoMCwgODAwLCBieSA9IDUwKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsYWJlbHMgPSBwYXN0ZTAoc2VxKDAsIDgwMCwgYnkgPSA1MCksICJNIikpDQogIA0KDQojIFRoZSBuZXh0IGJhciBwbG90IHNob3dzIHRoZSB2b2x1bWUgaW4gcGVyY2VudGFnZSB3aXRoIHJlc3BlY3QgdG8gdGhlIGRpZmZlcmVudCBjaXRpZXMgcGVyIG1vbnRoIA0KYmFyX3ZvbHVtZV9tb250aF8yID0gIGdncGxvdChkYXRhPWNvbmRpdGlvbmFsX2RhdGFzZXRfY2l0eV9tb250aCwNCiAgICAgICAgICAgICAgICAgICAgICAgIGFlcyh4PW1vbnRoLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIHk9dm9sdW1lLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZpbGw9Y2l0eSkpKw0KICAgICAgICAgICAgICAgICAgZ2VvbV9jb2woc3RhdD0iaWRlbnRpdHkiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgcG9zaXRpb249ICJmaWxsIikrDQogICAgICAgICAgICAgICAgICBsYWJzKHRpdGxlPSJDb21wYXJpc29uIG9mIHRvdGFsIHZvbHVtZSBieSBtb250aCBvdmVyIGNpdHkiLA0KICAgICAgICAgICAgICAgICAgICAgICB4PSJtb250aCIsDQogICAgICAgICAgICAgICAgICAgICAgIHk9InZvbHVtZSBwZXJjZW50YWdlIikrDQogICAgICAgICAgICAgICAgICB0aGVtZV9jbGFzc2ljKCkrDQogICAgICAgICAgICAgICAgICB0aGVtZShwbG90LnRpdGxlLnBvc2l0aW9uID0gInBhbmVsIiwNCiAgICAgICAgICAgICAgICAgICAgICAgIHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZT0xNCwgaGp1c3Q9MC41KSwNCiAgICAgICAgICAgICAgICAgICAgICAgIGF4aXMudGl0bGUueCA9IGVsZW1lbnRfdGV4dChzaXplPTEyKSwNCiAgICAgICAgICAgICAgICAgICAgICAgIGF4aXMudGl0bGUueSA9IGVsZW1lbnRfdGV4dChzaXplPTEyKSwNCiAgICAgICAgICAgICAgICAgICAgICAgIGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KHNpemU9MTApLA0KICAgICAgICAgICAgICAgICAgICAgICAgYXhpcy50ZXh0LnkgPSBlbGVtZW50X3RleHQoc2l6ZT0xMCksDQogICAgICAgICAgICAgICAgICAgICAgICBsZWdlbmQucG9zaXRpb24gPSAibm9uZSIpKw0KICAgICAgICAgICAgICAgICAgICAgICAgc2NhbGVfeV9jb250aW51b3VzKGxhYmVscyA9IHBlcmNlbnRfZm9ybWF0KCksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWtzID0gc2VxKDAsIDEsIGJ5ID0gMC4xKSkgDQoNCiMgVGhlIG5leHQgYmFyIHBsb3Qgc2hvd3MgdGhlIHRvdGFsIG51bWJlciBvZiBsaXN0aW5ncyBwZXIgbW9udGggaW4gZXZlcnkgY2l0eQ0KYmFyX2xpc3RpbmdzX21vbnRoID0gIGdncGxvdChkYXRhPWNvbmRpdGlvbmFsX2RhdGFzZXRfY2l0eV9tb250aCwNCiAgICAgICAgICAgICAgICAgICAgICAgIGFlcyh4PW1vbnRoLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIHk9bGlzdGluZ3MsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgZmlsbD1jaXR5KSkrDQogICAgICAgICAgICAgICAgICBnZW9tX2NvbChzdGF0PSJpZGVudGl0eSIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICBwb3NpdGlvbj0gInN0YWNrIikrDQogICAgICAgICAgICAgICAgICBsYWJzKHRpdGxlPSJDb21wYXJpc29uIG9mIHRvdGFsIGxpc3RpbmdzIGJ5IG1vbnRoIG92ZXIgY2l0eSIsDQogICAgICAgICAgICAgICAgICAgICAgIHg9Im1vbnRoIiwNCiAgICAgICAgICAgICAgICAgICAgICAgeT0ibGlzdGluZ3MiKSsNCiAgICAgICAgICAgICAgICAgIHRoZW1lX2NsYXNzaWMoKSsNCiAgICAgICAgICAgICAgICAgIHRoZW1lKHBsb3QudGl0bGUucG9zaXRpb24gPSAicGFuZWwiLA0KICAgICAgICAgICAgICAgICAgICAgICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplPTE0LCBoanVzdD0wLjUpLA0KICAgICAgICAgICAgICAgICAgICAgICAgYXhpcy50aXRsZS54ID0gZWxlbWVudF90ZXh0KHNpemU9MTIpLA0KICAgICAgICAgICAgICAgICAgICAgICAgYXhpcy50aXRsZS55ID0gZWxlbWVudF90ZXh0KHNpemU9MTIpLA0KICAgICAgICAgICAgICAgICAgICAgICAgYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoc2l6ZT0xMCksDQogICAgICAgICAgICAgICAgICAgICAgICBheGlzLnRleHQueSA9IGVsZW1lbnRfdGV4dChzaXplPTEwKSwNCiAgICAgICAgICAgICAgICAgICAgICAgIGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikrDQogICAgICAgICAgICAgICAgICAgICAgICBzY2FsZV95X2NvbnRpbnVvdXMoYnJlYWtzID0gc2VxKDAsIDM1MDAwLCBieSA9IDUwMDApLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsYWJlbHMgPSBwYXN0ZTAoc2VxKDAsIDM1LCBieSA9IDUpLCAiSyIpKQ0KDQoNCiMgVGhlIG5leHQgYmFyIHBsb3Qgc2hvd3MgdGhlIG51bWJlciBvZiBsaXN0aW5ncyBpbiBwZXJjZW50YWdlIHdpdGggcmVzcGVjdCB0byB0aGUgZGlmZmVyZW50IGNpdGllcyBwZXIgbW9udGggDQpiYXJfbGlzdGluZ3NfbW9udGhfMiA9ICBnZ3Bsb3QoZGF0YT1jb25kaXRpb25hbF9kYXRhc2V0X2NpdHlfbW9udGgsDQogICAgICAgICAgICAgICAgICAgICAgICBhZXMoeD1tb250aCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICB5PWxpc3RpbmdzLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZpbGw9Y2l0eSkpKw0KICAgICAgICAgICAgICAgICAgZ2VvbV9jb2woc3RhdD0iaWRlbnRpdHkiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgcG9zaXRpb249ICJmaWxsIikrDQogICAgICAgICAgICAgICAgICBsYWJzKHRpdGxlPSJDb21wYXJpc29uIG9mIHRvdGFsIGxpc3RpbmdzIGJ5IG1vbnRoIG92ZXIgY2l0eSIsDQogICAgICAgICAgICAgICAgICAgICAgIHg9Im1vbnRoIiwNCiAgICAgICAgICAgICAgICAgICAgICAgeT0ibGlzdGluZ3MgcGVyY2VudGFnZSIpKw0KICAgICAgICAgICAgICAgICAgdGhlbWVfY2xhc3NpYygpKw0KICAgICAgICAgICAgICAgICAgdGhlbWUocGxvdC50aXRsZS5wb3NpdGlvbiA9ICJwYW5lbCIsDQogICAgICAgICAgICAgICAgICAgICAgICBwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemU9MTQsIGhqdXN0PTAuNSksDQogICAgICAgICAgICAgICAgICAgICAgICBheGlzLnRpdGxlLnggPSBlbGVtZW50X3RleHQoc2l6ZT0xMiksDQogICAgICAgICAgICAgICAgICAgICAgICBheGlzLnRpdGxlLnkgPSBlbGVtZW50X3RleHQoc2l6ZT0xMiksDQogICAgICAgICAgICAgICAgICAgICAgICBheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChzaXplPTEwKSwNCiAgICAgICAgICAgICAgICAgICAgICAgIGF4aXMudGV4dC55ID0gZWxlbWVudF90ZXh0KHNpemU9MTApLA0KICAgICAgICAgICAgICAgICAgICAgICAgbGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKSsNCiAgICAgICAgICAgICAgICAgICAgICAgIHNjYWxlX3lfY29udGludW91cyhsYWJlbHMgPSBwZXJjZW50X2Zvcm1hdCgpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrcyA9IHNlcSgwLCAxLCBieSA9IDAuMSkpIA0KDQoNCiMgV2UgY29tYmluZSB0aGUgc2l4IHBsb3RzIGFib3ZlIGluIDEgZmlndXJlIGFuZCBkaXNwbGF5IGl0DQpjb21iX2ZpZ181IDwtIGJhcl9zYWxlc19tb250aCArIGJhcl9zYWxlc19tb250aF8yICsgYmFyX3ZvbHVtZV9tb250aCArIGJhcl92b2x1bWVfbW9udGhfMiArIGJhcl9saXN0aW5nc19tb250aCArIGJhcl9saXN0aW5nc19tb250aF8yICsgIGxlZ2VuZF9tb250aCArIHBsb3Rfc3BhY2VyKCkgKyBwbG90X2xheW91dChuY29sPTIsIGhlaWdodHMgPSBjKDUsIDUsIDUsIC41KSkNCnByaW50KGNvbWJfZmlnXzUpDQoNCiNXZSBjbG9zZSBhbGwgdGhlIGZpZ3VyZXMgYW5kIHBsb3RzIGdlbmVyYXRlZCBhYm92ZQ0Kcm0oYmFyX3NhbGVzX21vbnRoLCBiYXJfc2FsZXNfbW9udGhfMiwgYmFyX3ZvbHVtZV9tb250aCwgYmFyX3ZvbHVtZV9tb250aF8yLCBiYXJfbGlzdGluZ3NfbW9udGgsIGJhcl9saXN0aW5nc19tb250aF8yLCAgbGVnZW5kX21vbnRoLCBjb21iX2ZpZ181KQ0KYGBgDQoNClRoZSBsYXN0IHN0dWRpZXMgaGlnaGxpZ2h0IGEgdHJlbmQgaW4gbWFueSB2YXJpYWJsZXMgb3ZlciB0aGUgbW9udGhzOiAgDQoNCi0gV2Ugb2JzZXJ2ZSBzaWduaWZpY2FudGx5IGhpZ2hlciBzYWxlcyBhbmQgdm9sdW1lcyBpbiB0aGUgc3ByaW5nIGFuZCBzdW1tZXIgbW9udGhzIChpbiBhdmVyYWdlICsyMC8rMzAlIG9mIHRoZSBhbm51YWwgbWVhbikgd2l0aCByZXNwZWN0IHRvIHRoZSBhdXR1bW4gYW5kIHdpbnRlciBvbmVzICgtMjAvLTMwJSBvZiB0aGUgYW5udWFsIG1lYW4pLiAgDQoNCi0gQSBzaW1pbGFyIHRyZW5kIGlzIG9ic2VydmVkIGFsc28gZm9yIHRoZSBudW1iZXIgb2YgbGlzdGluZ3MgYW5kIG1vbnRocyBpbnZlbnRvcnksIGhvd2V2ZXIgdGhlIGdhcCBvdmVyIHRoZSB5ZWFyIG9mIHRoZXNlIHZhcmlhYmxlcyBpcyBzaWduaWZpY2FudGx5IGxlc3MgcHJvbm91bmNlZCAoJFxwbSQgNS8xMCUgb2YgdGhlIGFubnVhbCBtZWFuKS4gIA0KDQpUaGlzIHBoZW5vbWVub24gaXMgaGlnaGx5IHByb25vdW5jZWQgaW4gdGhlIGNpdGllcyBvZiBUeWxlciBhbmQgQnJ5YW4tQ29sbGVnZSBTdGF0aW9uLCBtaWxkbHkgcHJvbm91bmNlZCBpbiBCZWF1bW9udCwgYW5kIG5vdCBub3RpY2VhYmxlIGluIFdpY2hpdGEgRmFsbHMuICANCg0KVGhlIHBlci1tb250aCB2YXJpYWJpbGl0eSBvZiBhbGwgdGhlIHZhcmlhYmxlcywgbWVhc3VyZWQgaW4gdGVybXMgb2YgdGhlIGNvZWZmaWNpZW50IG9mIHZhcmlhdGlvbiwgaXMgY29tcGFyYWJsZSBhY3Jvc3MgbW9udGhzLg0KDQpGaW5hbGx5LCB3ZSBoaWdobGlnaHQgdGhhdCB0aGUgc2FsZXMsIHZvbHVtZSBhbmQgbGlzdGluZ3Mgb2YgV2ljaGl0YSBGYWxscyByZXByZXNlbnQgYWJvdXQgMTAtMTUlIG9mIHRoZSB0b3RhbCBkdXJpbmcgYWxsIHRoZSB5ZWFyLCB0aGUgb25lcyBvZiBCZWF1bW9udCBhYm91dCAyMC0yNSUgb2YgdGhlIHRvdGFsIGFuZCB0aGUgb25lcyBpbiBCcnlhbi1Db2xsZWdlIFN0YXRpb24gcGx1cyBUeWxlciBzdGFibHkgb3ZlciA2MCUgb2YgdGhlIHRvdGFsLg0KDQoNCiMjICoqQ29uY2x1c2lvbnM6KioNCkFsbCB0aGUgdmFyaWFibGVzIGFyZSBkaXN0cmlidXRlZCBub3QgdW5pZm9ybWx5IGFjcm9zcyB0aGUgZGlmZmVyZW50IGNpdGllcywgaW4gcGFydGljdWxhciB3ZSBoYXZlIG9ic2VydmVkIHRoYXQ6ICANCg0KLSBUaGUgcHJpY2VzIGFyZSBnZW5lcmFsbHkgaGlnaGVzdCBpbiBCcnlhbiBDb2xsZWdlIFN0YXRpb24gZm9sbG93ZWQgaW4gZGVjcmVhc2luZyBvcmRlciBieSBUeWxlciwgQmVhdW1vbnQgYW5kIFdpY2hpdGEgRmFsbHMuICANCg0KLSBUaGUgbnVtYmVyIG9mIHNhbGVzIGFuZCB2b2x1bWUgZm9sbG93IGEgc2ltaWxhciBkaXN0cmlidXRpb24gYW5kIGFyZSBoaWdoZXN0IGluIFR5bGVyIGZvbGxvd2VkIGluIGRlY3JlYXNpbmcgb3JkZXIgYnkgQnJ5YW4gQ29sbGVnZSBTdGF0aW9uLCBCZWF1bW9udCBhbmQgV2ljaGl0YSBGYWxscy4gICANCg0KLSBUaGUgbnVtYmVyIG9mIGxpc3RpbmdzIGluIFR5bGVyIGlzIHNpZ25pZmljYW50bHkgaGlnaGVyIChhbG1vc3QgdHdpY2UpIHRoYW4gaW4gYWxsIHRoZSBvdGhlciBjaXRpZXMuICAgDQoNCi0gVGhlIHZhcmlhYmlsaXR5IChtZWFzdXJlZCBpbiB0ZXJtcyBvZiB0aGUgY29lZmZpY2llbnQgb2YgdmFyaWF0aW9uKSBpbiB0aGUgdm9sdW1lIGFuZCBzYWxlcyBpbiBUeWxlciBpcyBiZXR3ZWVuIDEuNSBhbmQgMyB0aW1lcyBoaWdoZXIgdGhhbiB0aGUgdmFyaWFiaWxpdHkgb2JzZXJ2ZWQgaW4gdGhlIG90aGVyIGNpdGllcy4gV2hpbGUgdGhlIGhpZ2hlc3QgdmFyaWFiaWxpdHkgaW4gdGhlIGxpc3RpbmdzIGFuZCBtb250aCBpbnZlbnRvcnkgaXMgb2JzZXJ2ZWQgaW4gQnJ5YW4tQ29sbGVnZSBTdGF0aW9uIHdoZXJlIGl0IGlzIGFsbW9zdCB0d2ljZSBvciBtb3JlIHRoZSB2YXJpYWJpbGl0eSBpbiB0aGUgb3RoZXIgY2l0aWVzLiAgDQoNCi0gQWxsIHRoZSBjaXRpZXMgZXhjZXB0IFdpY2hpdGEgRmFsbHMgYXJlIGV4cGVyaWVuY2luZyBhIHNhbWUgdHJlbmQgb3ZlciB0aGUgbGFzdCB5ZWFycy4gVGhlIG51bWJlciBvZiBzYWxlcyB2b2x1bWUgYW5kIHByaWNlcyBhcmUgaW5jcmVhc2luZyB3aGlsZSB0aGUgbnVtYmVyIG9mIGxpc3RpbmdzIGFuZCBtb250aCBpbnZlbnRvcnkgaXMgZGVjcmVhc2luZy4gSG93ZXZlciB0aGUgYWRzIGxvb2tzIHRvIGJlIGVmZmljaWVudCBhcyB0aGUgZWZmaWNpZW5jeSBpLmUuIHF1b3RpZW50IGJldHdlZW4gbW9udGhzIGludmVudG9yeSBhbmQgbGlzdGluZ3MgaXMgaW5jcmVhc2luZy4gIA0KDQotIFRoZXNlIHRocmVlIGNpdGllcyBhbHNvIGV4cGVyaWVuY2UgYSB0cmVuZCBvdmVyIHRoZSBtb250aHMgd2l0aCBtb3JlIHNhbGVzIGFuZCB2b2x1bWUgZHVyaW5nIHRoZSBzcHJpbmcgYW5kIHN1bW1lciByYXRoZXIgdGhlbiBkdXJpbmcgdGhlIGF1dHVtbiB3aW50ZXIuIFBoZW5vbWVub24gdGhhdCBpcyBwYXJ0aWN1bGFybHkgcHJvbm91bmNlZCBpbiBUeWxlciBhbmQgQnJ5YW4tQ29sbGVnZSBTdGF0aW9uLiAgIA0KDQotIE92ZXJhbGwgdGhlIHRocmVlIGNpdGllcyBvZiBCZWF1bW9udCwgQnJ5YW4tQ29sbGVnZSBTdGF0aW9uIGFuZCBUeWxlciBhcmUgaW5jcmVhc2luZ2x5IA0Kb2NjdXB5aW5nIGEgbGFyZ2VyIG1hcmtldCBzaGFyZSBldmVyeSB5ZWFyIHVwIHRvIGFsbW9zdCA5MCUgb2Ygc2FsZXMgYW5kIHZvbHVtZSBpbiAyMDE0LiAgDQoNCi0gVGhlIHRocmVlIGNpdGllcyBvZiBCZWF1bW9udCwgQnJ5YW4tQ29sbGVnZSBTdGF0aW9uIGFuZCBUeWxlciBhbHNvIGV4cGVyaWVuY2Ugc2Vhc29uYWwgdmFyaWF0aW9ucyBpbiB0aGUgbWFya2V0LCB3aGljaCBpcyBtb3JlIGFjdGl2ZSBkdXJpbmcgdGhlIHNwcmluZyBhbmQgc3VtbWVyIHRoYW4gZHVyaW5nIHRoZSBhdXR1bW4gYW5kIHdpbnRlci4gVGhlIHNlYXNvbmFsIGRpZmZlcmVuY2UgaXMgcGFydGljdWxhcmx5IHByb25vdW5jZWQgaW4gQnJ5YW4tQ29sbGVnZSBTdGF0aW9uIGFuZCBUeWxlciwgd2hpbGUgaXQgaXMgbGVzcyBwcm9ub3VuY2VkIGluIEJlYXVtb250Lg0KDQotIFRoZSBjaXR5IG9mIFdpY2hpdGEgRmFsbHMgaXMgdGhlIG9ubHkgb25lIHdoZXJlIHRoZXJlIGFyZSBubyBzaWduaWZpY2FudCBjaGFuZ2VzIGluIHNhbGVzLCB2b2x1bWUsIGxpc3RpbmdzLCBtb250aCByZWNvdmVyeSBhbmQgcHJpY2VzIG92ZXIgdGhlIHllYXJzLiBBbHNvIGR1cmluZyB0aGUgc2Vhc29ucyBubyBzaWduaWZpY2FudCBjaGFuZ2VzIHZhcmlhdGlvbnMgYXJlIGV4cGVyaWVuY2VzLiAgDQoNCg0KSXQgc2VlbXMgbGlrZWx5IHRoYXQgdGhlIG9mZmVyIG9mIHJlYWwgZXN0YXRlIGlzIGRlY3JlYXNpbmcgaW4gdGhlIHRocmVlIGNpdGllcyBvZiBCcnlhbi1Db2xsZWdlIFN0YXRpb24sIFR5bGVyIGFuZCBCZWF1bW9udCB3aGlsZSB0aGUgZGVtYW5kIGlzIGxpa2VseSBpbmNyZWFzaW5nLg0KVGhpcyBpcyBkcml2aW5nIHVwIHByaWNlcyBhbmQgYnVzaW5lc3Mgdm9sdW1lLiBJbiBwYXJ0aWN1bGFyIHRoZSBhZHMgc2VlbSB0byBiZSBlZmZpY2llbnQgaW4gdGhlc2UgY2l0aWVzIGFzIHRoZSBudW1iZXIgb2Ygc2FsZXMgcGVyIG1vbnRoIGlzIGluY3JlYXNpbmcuIERpZmZlcmVudGx5LCB0aGUgc2l0dWF0aW9uIGlzIFdpY2hpdGEgRmFsbHMgaXMgc3RhdGljIGFuZCB0aGUgYWR2ZXJ0aXNpbmcgcG9saWNpZXMgaGF2ZSBub3QgcHJvZHVjZWQgYW55IHNpZ25pZmljYW50IGltcHJvdmVtZW50IHRvIHRoZSBidXNpbmVzcyB2b2x1bWUgb3ZlciB0aGUgbGFzdCB5ZWFycy4gSW4gcGFydGljdWxhciwgaW4gcGVyY2VudGFnZSB0ZXJtcywgdGhlIFdpY2hpdGEgRmFsbHMgcmVhbCBlc3RhdGUgbWFya2V0IGhhcyBiZWVuIGluY3JlYXNpbmdseSBkZWNsaW5pbmcgb3ZlciB0aGUgeWVhcnMuIFRoZXJlZm9yZSwgSSB3b3VsZCByZWNvbW1lbmQgcmV2aWV3aW5nIHRoZSBhZHZlcnRpc2luZyBwb2xpY3kgYWRvcHRlZCBpbiBXaWNoaXRhIEZhbGxzLCB3aGlsZSBtYWludGFpbmluZyB0aGUgc2FtZSBwb2xpY3kgaW4gb3RoZXIgY2l0aWVzLg0KDQoNCg0K