[1] Analysis of the variables

The database is composed of 240 observations each of 8 statistical variables relative to the real estate sales in different periods (month/year) and cities of Texas. The statistical variables are:
- city: nominal qualitative variable that classifies the city to which each observation refers.
- year: ordinal qualitative variable that classifies the year to which each observation refers.
- month: ordinal qualitative variable that classifies the month to which the observation refers.
- sales: a discrete quantitative variable that describes the total number of sales recorded in the city during the month of the year.
- volume: a continuous quantitative variable describing the value of sales in millions of US dollars.
- median_price: a continuous quantitative variable describing the median sales price of a property in US dollars in the city during the month of the year.
- listings: a discrete quantitative variable describing the total number of properties for sale in the city at the month of the year.
- month_inventory: a continuous quantitative variable that describes the time (in months) needed to sell all the properties available in the city at that moment (month/year).

We will analyze the quantitative variables such as sales, volume and median_price over time to identify generic or city-specific trends of the market, either monthly or annually.

The variables listings and month_inventory will be also studied over time and cities to study the speed of property sales and efficiency of advertising policies.

N_observations = dim(dataset)[1]
N_variables = dim(dataset)[2]

[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")

NA
NA

[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.

dataset$median_price_CL <- cut(dataset$median_price, 
                     breaks=seq(from = 70000, to = 180000, by = 10000))


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 and also the frequency distribution across the different cities.

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

  


#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")

NA
NA
NA
NA
NA

As we can observe from the Gini heterogeneity index close to 1 and the bar plots of the distribution in the price classes, the dataset is distributed discreetly uniformly across the different median-price classes. However, the distribution of the data relative to the different cities across the classes of price is distributed significantly less uniformly. This is reflected both by significantly lower values of the Gini index and by 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="median_price")+
       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)))+
       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)



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.

# 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")





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")
NA
NA

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



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

legend_city <- as_ggplot(get_legend(bar_sales_year))




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="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))


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="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(breaks = seq(0, 700, by = 50))







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


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














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



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


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



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")+
                    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))


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

  


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)



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)



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)


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)



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. Differently, 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. Similarly 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 also 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.

Conclusions:

All the variables are distributed not uniformly across the different cities, in particular we have observed that: - The prices are generally highest in Bryan College Station followed in decreasing order by Tyler, Beaumont and Wichita Falls.

It seems likely that the offer of real estate is decreasing in the three cities of Bryan-College Station, Tyler and Beaumont while the demand is likely increasing. This is driving up prices and business volume. In particular the ads seem to be efficient in these cities as the number of sales per month is increasing. Differently, the situation is Wichita Falls is static and the advertising policies have not produced any significant improvement to the business volume over the last years. In particular, in percentage terms, the Wichita Falls real estate market has been increasingly declining over the years. Therefore, I would recommend reviewing the advertising policy adopted in Wichita Falls, while maintaining the same policy in other cities.

LS0tDQp0aXRsZTogIlRleGFzIFJlYWwgRXN0YXRlIE1hcmtldCBBbmFseXNpcyINCm91dHB1dDogaHRtbF9ub3RlYm9vaw0KLS0tDQoNCjwhLS0gVGhpcyBpcyBhbiBbUiBNYXJrZG93bl0oaHR0cDovL3JtYXJrZG93bi5yc3R1ZGlvLmNvbSkgTm90ZWJvb2suIFdoZW4geW91IGV4ZWN1dGUgY29kZSB3aXRoaW4gdGhlIG5vdGVib29rLCB0aGUgcmVzdWx0cyBhcHBlYXIgYmVuZWF0aCB0aGUgY29kZS4gIC0tPg0KDQo8IS0tIFRyeSBleGVjdXRpbmcgdGhpcyBjaHVuayBieSBjbGlja2luZyB0aGUgKlJ1biogYnV0dG9uIHdpdGhpbiB0aGUgY2h1bmsgb3IgYnkgcGxhY2luZyB5b3VyIGN1cnNvciBpbnNpZGUgaXQgYW5kIHByZXNzaW5nICpDdHJsK1NoaWZ0K0VudGVyKi4gIC0tPg0KDQoNCjwhLS0gQWRkIGEgbmV3IGNodW5rIGJ5IGNsaWNraW5nIHRoZSAqSW5zZXJ0IENodW5rKiBidXR0b24gb24gdGhlIHRvb2xiYXIgb3IgYnkgcHJlc3NpbmcgKkN0cmwrQWx0K0kqLiAtLT4NCg0KPCEtLSBXaGVuIHlvdSBzYXZlIHRoZSBub3RlYm9vaywgYW4gSFRNTCBmaWxlIGNvbnRhaW5pbmcgdGhlIGNvZGUgYW5kIG91dHB1dCB3aWxsIGJlIHNhdmVkIGFsb25nc2lkZSBpdCAoY2xpY2sgdGhlICpQcmV2aWV3KiBidXR0b24gb3IgcHJlc3MgKkN0cmwrU2hpZnQrSyogdG8gcHJldmlldyB0aGUgSFRNTCBmaWxlKS4gLS0+DQoNCjwhLS0gVGhlIHByZXZpZXcgc2hvd3MgeW91IGEgcmVuZGVyZWQgSFRNTCBjb3B5IG9mIHRoZSBjb250ZW50cyBvZiB0aGUgZWRpdG9yLiBDb25zZXF1ZW50bHksIHVubGlrZSAqS25pdCosICpQcmV2aWV3KiBkb2VzIG5vdCBydW4gYW55IFIgY29kZSBjaHVua3MuIEluc3RlYWQsIHRoZSBvdXRwdXQgb2YgdGhlIGNodW5rIHdoZW4gaXQgd2FzIGxhc3QgcnVuIGluIHRoZSBlZGl0b3IgaXMgZGlzcGxheWVkLiAtLT4NCg0KYGBge3IsIGVjaG89RkFMU0V9DQpsaWJyYXJ5KGRwbHlyKQ0KbGlicmFyeShtb21lbnRzKQ0KbGlicmFyeShnZ3Bsb3QyKQ0KbGlicmFyeShwYXRjaHdvcmspDQpsaWJyYXJ5KHNjYWxlcykNCmxpYnJhcnkoZ2dwdWJyKQ0KbGlicmFyeShEVCkNCm9wdGlvbnMod2lkdGggPSAxMDApDQpgYGANCg0KDQpgYGB7ciwgZWNobz1GQUxTRX0NCiMgSU1QT1JUIFRIRSBEQVRBU0VUDQpkYXRhc2V0IDwtIHJlYWQuY3N2KCJyZWFsZXN0YXRlX3RleGFzLmNzdiIpDQoNCmRhdGFzZXQkbW9udGggPC0gZmFjdG9yKGRhdGFzZXQkbW9udGgpDQpkYXRhc2V0JHllYXIgPC0gZmFjdG9yKGRhdGFzZXQkeWVhcikNCg0KYXR0YWNoKGRhdGFzZXQpDQpgYGANCg0KDQojIyAqKjxzcGFuIHN0eWxlPSJjb2xvcjpyZWQiPiBbMV0gPC9zcGFuPiBBbmFseXNpcyBvZiB0aGUgdmFyaWFibGVzKioNCg0KDQpUaGUgZGF0YWJhc2UgaXMgY29tcG9zZWQgb2YgMjQwIG9ic2VydmF0aW9ucyBlYWNoIG9mIDggc3RhdGlzdGljYWwgdmFyaWFibGVzIHJlbGF0aXZlIHRvIHRoZSByZWFsIGVzdGF0ZSBzYWxlcyBpbiBkaWZmZXJlbnQgcGVyaW9kcyAobW9udGgveWVhcikgYW5kIGNpdGllcyBvZiBUZXhhcy4gVGhlIHN0YXRpc3RpY2FsIHZhcmlhYmxlcyBhcmU6ICANCi0gKmNpdHkqOiBub21pbmFsIHF1YWxpdGF0aXZlIHZhcmlhYmxlIHRoYXQgY2xhc3NpZmllcyB0aGUgY2l0eSB0byB3aGljaCBlYWNoIG9ic2VydmF0aW9uIHJlZmVycy4gIA0KLSAqeWVhcio6IG9yZGluYWwgcXVhbGl0YXRpdmUgdmFyaWFibGUgdGhhdCBjbGFzc2lmaWVzIHRoZSB5ZWFyIHRvIHdoaWNoIGVhY2ggb2JzZXJ2YXRpb24gcmVmZXJzLiAgDQotICptb250aCo6IG9yZGluYWwgcXVhbGl0YXRpdmUgdmFyaWFibGUgdGhhdCBjbGFzc2lmaWVzIHRoZSBtb250aCB0byB3aGljaCB0aGUgb2JzZXJ2YXRpb24gcmVmZXJzLiAgDQotICpzYWxlcyo6IGEgZGlzY3JldGUgcXVhbnRpdGF0aXZlIHZhcmlhYmxlIHRoYXQgZGVzY3JpYmVzIHRoZSB0b3RhbCBudW1iZXIgb2Ygc2FsZXMgcmVjb3JkZWQgaW4gdGhlIGNpdHkgZHVyaW5nIHRoZSBtb250aCBvZiB0aGUgeWVhci4gIA0KLSAqdm9sdW1lKjogYSBjb250aW51b3VzIHF1YW50aXRhdGl2ZSB2YXJpYWJsZSBkZXNjcmliaW5nIHRoZSB2YWx1ZSBvZiBzYWxlcyBpbiBtaWxsaW9ucyBvZiBVUyBkb2xsYXJzLiAgDQotICptZWRpYW5fcHJpY2UqOiBhIGNvbnRpbnVvdXMgcXVhbnRpdGF0aXZlIHZhcmlhYmxlIGRlc2NyaWJpbmcgdGhlIG1lZGlhbiBzYWxlcyBwcmljZSBvZiBhIHByb3BlcnR5IGluIFVTIGRvbGxhcnMgaW4gdGhlIGNpdHkgZHVyaW5nIHRoZSBtb250aCBvZiB0aGUgeWVhci4gIA0KLSAqbGlzdGluZ3MqOiBhIGRpc2NyZXRlIHF1YW50aXRhdGl2ZSB2YXJpYWJsZSBkZXNjcmliaW5nIHRoZSB0b3RhbCBudW1iZXIgb2YgcHJvcGVydGllcyBmb3Igc2FsZSBpbiB0aGUgY2l0eSBhdCB0aGUgbW9udGggb2YgdGhlIHllYXIuICANCi0gKm1vbnRoX2ludmVudG9yeSo6IGEgY29udGludW91cyBxdWFudGl0YXRpdmUgdmFyaWFibGUgdGhhdCBkZXNjcmliZXMgdGhlIHRpbWUgKGluIG1vbnRocykgbmVlZGVkIHRvIHNlbGwgYWxsIHRoZSBwcm9wZXJ0aWVzIGF2YWlsYWJsZSBpbiB0aGUgY2l0eSBhdCB0aGF0IG1vbWVudCAobW9udGgveWVhcikuDQoNCldlIHdpbGwgYW5hbHl6ZSB0aGUgcXVhbnRpdGF0aXZlIHZhcmlhYmxlcyBzdWNoIGFzIHNhbGVzLCB2b2x1bWUgYW5kIG1lZGlhbl9wcmljZSBvdmVyIHRpbWUgdG8gaWRlbnRpZnkgZ2VuZXJpYyBvciBjaXR5LXNwZWNpZmljIHRyZW5kcyBvZiB0aGUgbWFya2V0LCBlaXRoZXIgbW9udGhseSBvciBhbm51YWxseS4NCg0KVGhlIHZhcmlhYmxlcyBsaXN0aW5ncyBhbmQgbW9udGhfaW52ZW50b3J5IHdpbGwgYmUgYWxzbyBzdHVkaWVkIG92ZXIgdGltZSBhbmQgY2l0aWVzIHRvIHN0dWR5IHRoZSBzcGVlZCBvZiBwcm9wZXJ0eSBzYWxlcyBhbmQgZWZmaWNpZW5jeSBvZiBhZHZlcnRpc2luZyBwb2xpY2llcy4NCg0KYGBge3J9DQpOX29ic2VydmF0aW9ucyA9IGRpbShkYXRhc2V0KVsxXQ0KTl92YXJpYWJsZXMgPSBkaW0oZGF0YXNldClbMl0NCmBgYA0KDQojIyAqKjxzcGFuIHN0eWxlPSJjb2xvcjpyZWQiPiBbMl0gPC9zcGFuPiBTdHVkeSBvZiB0aGUgdmFyaWFibGVzKioNCg0KIyMjICoqKEkpIFdlIHN0dWR5IHRoZSBhYnNvbHV0ZSBhbmQgcmVsYXRpdmUgZnJlcXVlbmN5IG9mIHRoZSBxdWFsaXRhdGl2ZSB2YXJpYWJsZXMgImNpdHkiLCAieWVhciIgYW5kICJtb250aCIqKg0KDQoNCg0KYGBge3J9DQojIEhlcmUgYW5kIGluIHRoZSBmb2xsb3dpbmcgd2UgdXNlIHRoZSBwYWNrYWdlICpEVCogZm9yIHRoZSBiZXR0ZXIgcmVuZGVyaW5nIG9mIHRoZSB0YWJsZXMuDQoNCkZyZXFfYXNzX2NpdHkgPSB0YWJsZShkYXRhc2V0WyJjaXR5Il0pDQpGcmVxX3JlbF9jaXR5ID0gdGFibGUoZGF0YXNldFsiY2l0eSJdKS9OX29ic2VydmF0aW9ucw0KRnJlcV9jaXR5ID0gY2JpbmQoRnJlcV9hc3NfY2l0eSxGcmVxX3JlbF9jaXR5KQ0KZGF0YXRhYmxlKHQoRnJlcV9jaXR5KSwgY2FwdGlvbiA9ICdBYnNvbHV0ZSBhbmQgUmVsYXRpdmUgZnJlcXVlbmN5IG9mIHRoZSBjaXRpZXMgaW4gdGhlIGRhdGFzZXQnKQ0KDQpGcmVxX2Fzc195ZWFyID0gdGFibGUoZGF0YXNldFsieWVhciJdKQ0KRnJlcV9yZWxfeWVhciA9IHRhYmxlKGRhdGFzZXRbInllYXIiXSkvTl9vYnNlcnZhdGlvbnMNCkZyZXFfeWVhciA9IGNiaW5kKEZyZXFfYXNzX3llYXIsIEZyZXFfcmVsX3llYXIpDQpkYXRhdGFibGUodChGcmVxX3llYXIpLCBjYXB0aW9uID0gJ0Fic29sdXRlIGFuZCBSZWxhdGl2ZSBmcmVxdWVuY3kgb2YgdGhlIHllYXJzIGluIHRoZSBkYXRhc2V0JykNCg0KRnJlcV9hc3NfbW9udGggPSB0YWJsZShkYXRhc2V0WyJtb250aCJdKQ0KRnJlcV9yZWxfbW9udGggPSByb3VuZCh0YWJsZShkYXRhc2V0WyJtb250aCJdKS9OX29ic2VydmF0aW9ucywyKQ0KRnJlcV9tb250aCA9IGNiaW5kKEZyZXFfYXNzX21vbnRoLEZyZXFfcmVsX21vbnRoKQ0KZGF0YXRhYmxlKHQoRnJlcV9tb250aCksIG9wdGlvbnMgPSBsaXN0KHBhZ2VMZW5ndGggPSAxMiksIGNhcHRpb24gPSAnQWJzb2x1dGUgYW5kIFJlbGF0aXZlIGZyZXF1ZW5jeSBvZiB0aGUgbW9udGhzIGluIHRoZSBkYXRhc2V0JykNCmBgYA0KDQpXZSBvYnNlcnZlIHRoYXQgdGhlIHZhcmlhYmxlcyAiY2l0eSIsICJ5ZWFyIiwgYW5kICJtb250aCIgYXJlIHVuaWZvcm1seSBkaXN0cmlidXRlZCwgYW5kIHRodXMgdGhleSBleGhpYml0ICoqbXVsdGltb2RhbCoqIGRpc3RyaWJ1dGlvbnMuDQoNCioqPHNwYW4gc3R5bGU9ImNvbG9yOnJlZCI+IFs1XSA8L3NwYW4+KiogSW4gcGFydGljdWxhciwgdGhlIHByb2JhYmlsaXR5IHRoYXQgYSByYW5kb20gbGluZSBvZiB0aGUgZGF0YXNldCBjb3JyZXNwb25kcyB0bzogIA0KLSB0aGUgY2l0eSBvZiDigJxCZWF1bW9udOKAnSBpcyAqUCjigJxCZWF1bW9udOKAnSk9MC4yNSouICANCi0gdGhlIG1vbnRoIG9mICJKdWx5IiBpcyAqUCgiSnVseSIpfj0wLjA4Ki4gICAgIA0KLSAiRGVjZW1iZXIgMjAxMiIgaXMgKlAoIkRlY2VtYmVyIDIwMTIiKT0gUCgiRGVjZW1iZXIiKSB4IFAoIjIwMTIiKSA9IDAuMDggeCAwLjIgfj0gMC4xNi4qICANCg0KIyMjICoqKElJKSBOZXh0LCB3ZSBzdHVkeSB0aGUgcXVhbnRpdGF0aXZlIHZhcmlhYmxlczoqKiAgDQotICoqInNhbGVzIiwqKiAgIA0KLSAqKiJ2b2x1bWUiLCoqICANCi0gKioibWVkaWFuX3ByaWNlIiwqKiAgDQotICoqImxpc3RpbmdzIioqICANCi0gKioibW9udGhfaW52ZW50b3J5IiAqKiAgDQoNCldlIHN1bW1hcml6ZSBpbiBhIHRhYmxlIGEgZGVzY3JpcHRpb24gb2YgdGhlc2UgdmFyaWFibGVzIHZpYSB0aGUgbWFpbiBpbmRpY2VzIG9mIHNoYXBlLCBwb3NpdGlvbiBhbmQgdmFyaWFiaWxpdHkuIFdlIGFsc28gY29tcGFyZSBncmFwaGljYWxseSB0aGVpciBub3JtYWxpemVkIGRpc3RyaWJ1dGlvbiBhZ2FpbnN0IGEgbm9ybWFsIGRpc3RyaWJ1dGlvbi4NCg0KDQpgYGB7cn0NCmN2X2Z1bmN0IDwtIGZ1bmN0aW9uKHgpIHsNCiAgcmV0dXJuKHNkKHgpIC8gbWVhbih4KSAqIDEwMCkNCn0NCg0KDQprdXJ0b3Npc19pbmRleCA8LSBmdW5jdGlvbih4KSB7DQogIHJldHVybihrdXJ0b3Npcyh4KS0zKQ0KfQ0KDQoNCnN1Yl9kYXRhIDwtIGRhdGFzZXRbYygic2FsZXMiLCJ2b2x1bWUiLCJtZWRpYW5fcHJpY2UiLCJsaXN0aW5ncyIsIm1vbnRoc19pbnZlbnRvcnkiKV0NCg0Kc3RhdGlzdGljcyA8LSBkYXRhLmZyYW1lKA0KICAgICAgICANCiAgcXVhcnRpbGVfMSA9IHJvdW5kKGFwcGx5KHN1Yl9kYXRhLCAyLCBmdW5jdGlvbih4KSBxdWFudGlsZSh4LHByb2JzPTAuMjUsIG5hbWVzPUZBTFNFKSksMiksDQogICAgICAgICAgICAgICAgICAgICAgICAgIA0KICBtZWRpYW4gPSByb3VuZChhcHBseShzdWJfZGF0YSwgMiwgbWVkaWFuKSwyKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICANCiAgcXVhcnRpbGVfMyA9IHJvdW5kKGFwcGx5KHN1Yl9kYXRhLCAyLCBmdW5jdGlvbih4KSBxdWFudGlsZSh4LHByb2JzPTAuNzUsIG5hbWVzPUZBTFNFKSksMiksDQogICAgICAgICAgICAgICAgICAgICAgICAgIA0KICBtZWFuID0gcm91bmQoYXBwbHkoc3ViX2RhdGEsIDIsIG1lYW4pLDIpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICANCiAgc2QgPSByb3VuZChhcHBseShzdWJfZGF0YSwgMiwgc2QpLDIpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICANCiAgY3YgPSByb3VuZChhcHBseShzdWJfZGF0YSwgMiwgY3ZfZnVuY3QpLDIpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICANCiAgc2tld25lc3MgPSByb3VuZChhcHBseShzdWJfZGF0YSwgMiwgc2tld25lc3MpLDIpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICANCiAga3VydG9zaXMgPSByb3VuZChhcHBseShzdWJfZGF0YSwgMiwga3VydG9zaXNfaW5kZXgpLDIpDQopDQoNCiMjIEZPUiBBIEJFVFRFUiBWSVNVQUxJWkFUSU9OIE9GIFRIRSBUQUJMRVMgV0UgVVNFIFRIRSBQQUNLQUdFICJEVCIgKGh0dHBzOi8vcnN0dWRpby5naXRodWIuaW8vRFQvKQ0KDQpkYXRhdGFibGUoc3RhdGlzdGljcywgY2FwdGlvbj0iSW5kaWNlcyBvZiBwb3NpdGlvbiwgdmFyaWFiaWxpdHkgYW5kIGZvcm0gb2YgdGhlIHF1YW50aXRhdGl2ZSB2YXJpYWJsZXMgaW4gdGhlIGRhdHNldCIpDQpgYGANCg0KYGBge3J9DQoNCiMgdGhlIGZ1bmN0aW9uIG5vcm1hbGl6ZSB0YWtlcyBpbiBpbnB1dCBhIHZhcmlhYmxlIGluIHN0cmluZyBmb3JtIGFuZCByZXR1cm5zIGl0cyB2YWx1ZXMgbm9ybWFsaXplZCBieSBpdHMgbWVhbiBhbmQgc3RhbmRhcmQgZGV2aWF0aW9uDQpub3JtYWxpemUgPC0gZnVuY3Rpb24odmFyaWFibGUpew0KICByZXR1cm4gKChkYXRhc2V0W1t2YXJpYWJsZV1dLXN0YXRpc3RpY3NbdmFyaWFibGUsICJtZWFuIl0pL3N0YXRpc3RpY3NbdmFyaWFibGUsICJzZCJdKQ0KfQ0KDQojIHdlIGdlbmVyYXRlIGEgc3RhbmRhcmQgbm9ybWFsIGRpc3RyaWJ1dGlvbg0KZ2F1c3NpYW5fZGlzdHJpYnV0aW9uIDwtIHJub3JtKDEwMDAwMCwwLDEpDQoNCg0KIyB3ZSBwbG90IHRoZSBkZW5zaXR5IG9mIHRoZSBkaWZmZXJlbnQgdmFyaWFibGVzIGFnYWluc3QgYSBzdGFuZGFyZCBub3JtYWwgZGlzdHJpYnV0aW9uDQpnZ3Bsb3QoKSsNCiAgZ2VvbV9kZW5zaXR5KGFlcyh4PWdhdXNzaWFuX2Rpc3RyaWJ1dGlvbiwgZmlsbD0iTjAxIiksIGNvbG9yPU5BLCAgYWxwaGE9LjgpKw0KICBnZW9tX2RlbnNpdHkoYWVzKHg9bm9ybWFsaXplKCJzYWxlcyIpLCBjb2xvcj0ic2FsZXMiKSwgbGluZXdpZHRoPTEuNSkrDQogIGdlb21fZGVuc2l0eShhZXMoeD1ub3JtYWxpemUoInZvbHVtZSIpLCBjb2xvcj0idm9sdW1lIiksIGxpbmV3aWR0aD0xLjUpKw0KICBnZW9tX2RlbnNpdHkoYWVzKHg9bm9ybWFsaXplKCJtZWRpYW5fcHJpY2UiKSwgY29sb3I9ICJtZWRpYW5fcHJpY2UiKSwgbGluZXdpZHRoPTEuNSkrDQogIGdlb21fZGVuc2l0eShhZXMoeD1ub3JtYWxpemUoImxpc3RpbmdzIiksIGNvbG9yPSJsaXN0aW5ncyIpLCBsaW5ld2lkdGg9MS41KSsNCiAgZ2VvbV9kZW5zaXR5KGFlcyh4PW5vcm1hbGl6ZSgibW9udGhzX2ludmVudG9yeSIpLCBjb2xvcj0ibW9udGhzX2ludmVudG9yeSIpLCBsaW5ld2lkdGg9MS41KSsNCiAgbGFicyh0aXRsZT0iRGlzdHJpYnV0aW9uIG9mIHRoZSB2YXJpYWJsZXMiLA0KICAgICAgIHg9Ik5vcm1hbGl6ZWQgdmFyaWFibGUgIiwNCiAgICAgICB5PSJkZW5zaXR5IikrDQogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IGMoTjAxID0gImdyZXkiKSwgICANCiAgICAgICAgICAgICAgICAgICAgbGFiZWxzID0gYyhOMDEgPSAiTigwLDEpIikpICsNCiAgdGhlbWVfY2xhc3NpYygpKw0KICB0aGVtZShwbG90LnRpdGxlLnBvc2l0aW9uID0gInBhbmVsIiwNCiAgICAgICAgcGxvdC50aXRsZT1lbGVtZW50X3RleHQoaGp1c3Q9MC41KSkrDQogIGd1aWRlcyhmaWxsID0gZ3VpZGVfbGVnZW5kKG92ZXJyaWRlLmFlcyA9IGxpc3QoY29sb3IgPSBOQSkpKSsNCiAgbGFicyhjb2xvciA9ICJWYXJpYWJpbGUiLA0KICAgICAgZmlsbCA9ICJEaXN0cmlidXppb25lIG5vcm1hbGUiKQ0KDQoNCmBgYA0KDQoNCg0KDQoNCioqPHNwYW4gc3R5bGU9ImNvbG9yOnJlZCI+IFszXSA8L3NwYW4+KiogRnJvbSB0aGUgcHJldmlvdXMgYW5hbHlzaXMgd2UgY2FuIG9ic2VydmUgdGhhdCB0aGUgdmFyaWFibGVzICJ2b2x1bWUiIGFuZCAibWVkaWFuX3ByaWNlIiBhcmUgdGhlIG9uZXMgd2l0aCB0aGUgaGlnaGVzdCBhbmQgc21hbGxlc3QgdmFyaWFiaWxpdHkgaGF2aW5nIHRoZSBsYXJnZXN0IGFuZCBzbWFsbGVzdCBjb2VmZmljaWVudCBvZiB2YXJpYXRpb24sIHJlc3BlY3RpdmVseS4gU2ltaWxhcmx5ICJ2b2x1bWUiIGlzIGFsc28gdGhlIG1vc3QgYXN5bW1ldHJpYyB2YXJpYWJsZSBoYXZpbmcgdGhlIGhpZ2hlc3QgYWJzb2x1dGUgdmFsdWUgb2YgdGhlIEZpc2hlciBza2V3bmVzcyBjb2VmZmljaWVudCwgZGlmZmVyZW50bHkgdGhlIGxlYXN0IGFzeW1tZXRyaWMgdmFyaWFibGUgaXMgIm1vbnRoc19pbnZlbnRvcnkiLiAgDQoNClRoZSB2YWx1ZXMgb2YgdGhlIEZpc2hlciBza2V3bmVzcyBjb2VmZmljaWVudHMgYW5kIGt1cnRvc2lzIGRlbW9uc3RyYXRlIHRoYXQgbm9uZSBvZiB0aGUgdmFyaWFibGVzIGZvbGxvdyBhbiBleGFjdCBub3JtYWwgZGlzdHJpYnV0aW9uLCBzdWdnZXN0aW5nIGRpZmZlcmVudCBkaXN0cmlidXRpb25zIG9mIHRoZSB2YXJpYWJsZXMgYmFzZWQgb24gdGhlIGRpZmZlcmVudCBjaXRpZXMgYW5kL29yIHBlcmlvZHMuIA0KDQpIb3dldmVyLCBhcyB3ZSBjYW4gc2VlIGZyb20gdGhlIHBsb3QgYW5kIHRoZSB2YWx1ZXMgb2Ygc2tld25lc3MgaW4gdGhlIHRhYmxlLCBhbGwgdGhlIHZhcmlhYmxlLCBleGNlcHQgdGhlIG1lZGlhbl9wcmljZSwgYXJlIG1vcmUgZGVuc2VseSBjb25jZW50cmF0ZWQgY2xvc2UgdG8gdGhlIG1lYW4gb24gdGhlIG1lYW4gbGVmdCBhbmQgbW9yZSBzcGFyc2VseSBkaXN0cmlidXRlZCBvbiB0aGUgbWVhbiByaWdodC4NCg0KRmluYWxseSBieSBsb29raW5nIGF0IHRoZSBrdXJ0b3Npcywgd2Ugb2JzZXJ2ZSB0aGF0IGFsbCB0aGUgdmFyaWFibGVzLCBleGNlcHQgdGhlIHZvbHVtZSwgaGF2ZSB0YWlscyBkZWNheWluZyBmYXN0ZXIgdGhhbiB0aGUgR2F1c3NpYW4gZGlzdHJpYnV0aW9uLCBzbyB0aGUgcHJvYmFiaWxpdHkgb2Ygb2JzZXJ2aW5nIG91dGxpZXJzIGZhciBmcm9tIHRoZSBtZWFuIHdpbGwgYmUgbG93ZXIgdGhhbiB0aGUgcHJvYmFiaWxpdHkgdGhhdCB3ZSB3b3VsZCBoYXZlIGJ5IGNvbnNpZGVyaW5nIGEgbm9ybWFsIGRpc3RyaWJ1dGlvbiB3aXRoIHNhbWUgbWVhbiBhbmQgc3RhbmRhcmQgZGV2aWF0aW9uLg0KDQoNCiMjICoqPHNwYW4gc3R5bGU9ImNvbG9yOnJlZCI+IFs0XSA8L3NwYW4+IENyZWF0aW9uIG9mIGNsYXNzZXMgZm9yIHF1YW50aXRhdGl2ZSB2YXJpYWJsZXMqKg0KIyMjIEluIHRoaXMgc2VjdGlvbiB3ZSBkaXZpZGUgdGhlIHZhcmlhYmxlIG1lZGlhbl9wcmljZSBpbiBjbGFzc2VzIHRvIHN0dWR5IGhvdyBpdHMgZGlzdHJpYnV0aW9uIHZhcmllcyBhY3Jvc3MgdGhlIGRpZmZlcmVudCBjaXRpZXMuDQpGaXJzdCB3ZSBjcmVhdGUgdGhlIGNsYXNzZXMgZWFjaCBjb3JyZXNwb25kaW5nIHRvIGEgcmFuZ2Ugb2YgMTAwMDAkLCBhc3NpZ24gZWFjaCBkYXRhIHRvIHRoZSBjb3JyZXNwb25kaW5nIGNsYXNzIGFuZCBzdHVkeSB0aGUgZGlzdHJpYnV0aW9uIGZyZXF1ZW5jeSBvZiBlYWNoIGNsYXNzLg0KDQpgYGB7cn0NCmNhdCgibWluIG1lZGlhbl9wcmljZToiLCBtaW4oZGF0YXNldCRtZWRpYW5fcHJpY2UpLCAiXG4iKQ0KY2F0KCJtYXggbWVkaWFuX3ByaWNlOiIsIG1heChkYXRhc2V0JG1lZGlhbl9wcmljZSkpDQoNCiNnaXZlbiB0aGUgbWluaXVtIGFuZCBtYXhpbXVtIG1lZGlhbl9wcmljZSB2YWx1ZSB3ZSBjcmVhdGUgY2xhc3NlcyBvZiAxMDAwMCAkIGVhY2ggYW5kIGFzc2lnbiBlYWNoIGRhdGEgdG8gdGhlIGNvcnJlc3BvbmRpbmcgY2xhc3MuDQoNCmRhdGFzZXQkbWVkaWFuX3ByaWNlX0NMIDwtIGN1dChkYXRhc2V0JG1lZGlhbl9wcmljZSwgDQogICAgICAgICAgICAgICAgICAgICBicmVha3M9c2VxKGZyb20gPSA3MDAwMCwgdG8gPSAxODAwMDAsIGJ5ID0gMTAwMDApKQ0KDQoNCmZyZXFfYXNzX21lZGlhbl9wcmljZSA8LSB0YWJsZShkYXRhc2V0JG1lZGlhbl9wcmljZV9DTCkNCmZyZXFfcmVsX21lZGlhbl9wcmljZSA8LSByb3VuZChmcmVxX2Fzc19tZWRpYW5fcHJpY2UvTl9vYnNlcnZhdGlvbnMsMikNCg0KZGF0YXRhYmxlKGNiaW5kKGZyZXFfYXNzX21lZGlhbl9wcmljZSwgZnJlcV9yZWxfbWVkaWFuX3ByaWNlKSkNCmBgYA0KTmV4dCwgd2UgY29tcHV0ZSB0aGUgR2luaSBoZXRlcm9nZW5laXR5IGluZGV4IG9mIHRoZSBtZWRpYW5fcHJpY2UgY2xhc3MgdmFyaWFibGUgb3ZlciB0aGUgZW50aXJlIGRhdGFzZXQgYW5kIHNlcGFyYXRlbHkgZm9yIGVhY2ggY2l0eS4gDQoNCmBgYHtyfQ0KZ2luaS5pbmRleCA8LSBmdW5jdGlvbih4KXsNCiAgbmkgPSB0YWJsZSh4KQ0KICBmaSA9IG5pL2xlbmd0aCh4KQ0KICBmaTIgPSBmaV4yDQogIEogPSBsZW5ndGgodGFibGUoeCkpDQogIA0KICBnaW5pID0gMS1zdW0oZmkyKQ0KICBnaW5pLm5vcm0gPSBnaW5pLygoSi0xKS9KKQ0KICANCiAgcmV0dXJuKGdpbmkubm9ybSkNCn0NCg0KDQpjYXQoc3ByaW50ZigiVGhlIEdpbmkgaGV0ZXJvZ2VuZWl0eSBpbmRleCBvZiB0aGUgY2xhc3NlcyBvZiBtZWRpYW4gcHJpY2Ugb3ZlciB0aGUgZW50cmllIGRhdGFzZXQgaXM6ICVmIFxuIiwgZ2luaS5pbmRleChkYXRhc2V0JG1lZGlhbl9wcmljZV9DTCkpKQ0KDQpmb3IgKGNpdCBpbiB1bmlxdWUoZGF0YXNldCRjaXR5KSl7DQogIGNpdHlfZGF0YXNldCA8LSBkYXRhc2V0ICU+JQ0KICAgIGZpbHRlcihjaXR5PT1jaXQpDQoNCiAgY2F0KHNwcmludGYoIlRoZSBHaW5pIGhldGVyb2dlbmVpdHkgaW5kZXggb2YgdGhlIGNsYXNzZXMgb2YgbWVkaWFuIHByaWNlIHJlbGF0aXZlIHRvIHRoZSBjaXR5IG9mICVzIGlzOiAlZiBcbiIsIGNpdCwgZ2luaS5pbmRleChjaXR5X2RhdGFzZXQkbWVkaWFuX3ByaWNlX0NMKSkpDQogIH0NCg0KYGBgDQoNCkxhc3Qgd2UgdmlzdWFsaXplIHRoZSBmcmVxdWVuY3kgZGlzdHJpYnV0aW9uIHZpYSBhIGJhcnBsb3QgYW5kIGFsc28gdGhlIGZyZXF1ZW5jeSBkaXN0cmlidXRpb24gYWNyb3NzIHRoZSBkaWZmZXJlbnQgY2l0aWVzLiAgDQoNCmBgYHtyfQ0KZ2dwbG90KGRhdGE9ZGF0YXNldCkrDQogIGdlb21fYmFyKGFlcyh4PW1lZGlhbl9wcmljZV9DTCksDQogICAgICAgICAgIHN0YXQ9ImNvdW50IiwNCiAgICAgICAgICAgY29sPSJibGFjayIsDQogICAgICAgICAgIGZpbGw9Im9yYW5nZSIpKw0KICBsYWJzKHRpdGxlPSJEaXN0cmlidXRpb24gb2YgdGhlIGNsYXNzZXMgb2YgbWVkaWFuX3ByaWNlIiwNCiAgICAgICB4PSJtZWRpYW4gcHJpY2UgaW4gY2xhc3NlcyIsDQogICAgICAgeT0iYWJzb2x1dGUgZnJlcXVlbmN5IikrDQogIHNjYWxlX3lfY29udGludW91cyhicmVha3MgPSBzZXEoMCw2MCwxMCkpKw0KICB0aGVtZV9jbGFzc2ljKCkrDQogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gMTUsIGhqdXN0ID0gMSksDQogICAgICAgIGF4aXMudGl0bGUueCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTQsIG1hcmdpbiA9IG1hcmdpbih0ID0gMTApKSwNCiAgICAgICAgYXhpcy50aXRsZS55ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNCwgbWFyZ2luID0gbWFyZ2luKHIgPSAxMCkpKQ0KICANCg0KDQojZm9yIGEgYmV0dGVyIHZpc3VhbGl6YXRpb24gb2YgdGhlIGZyZXF1ZW5jeSBhY3Jvc3MgdGhlIGRpZmZlcmVudCBjaXRpZXMgd2UgY3JlYXRlIGEgZGF0YXNldCB3aGVyZSB3ZSBjb3VudCB0aGUgZnJlcXVlbmN5IG9mIGVhY2ggY2xhc3MgZm9yIGVhY2ggY2l0eSBhbmQgd2UgZmlsbCB0aGUgZGF0YXNldCB3aXRoIG9ic2VydmF0aW9ucyBoYXZpbmcgY291bnQ9MCBmb3IgZWFjaCBjaXR5IGFuZCBjbGFzcyBvZiBwcmljZSB0aGF0IGhhdmUgbm8gaW50ZXJzZWN0aW9uICAgDQoNCmRhdGFzZXRfY29tcGxldGUgPC0gZGF0YXNldCAlPiUNCiAgY291bnQobWVkaWFuX3ByaWNlX0NMLCBjaXR5KQ0KDQpmb3IgKGNpdCBpbiB1bmlxdWUoZGF0YXNldCRjaXR5KSl7DQogIGZvciAoY2xhc3MgaW4gdW5pcXVlKGRhdGFzZXQkbWVkaWFuX3ByaWNlX0NMKSl7DQogICAgZmlsdGVyZWQgPC0gZGF0YXNldF9jb21wbGV0ZSAlPiUNCiAgICAgIGZpbHRlcihjaXR5ID09IGNpdCwgbWVkaWFuX3ByaWNlX0NMID09IGNsYXNzKQ0KICAgIGlmIChucm93KGZpbHRlcmVkKSA9PSAwKXsNCiAgICAgIGRhdGFzZXRfY29tcGxldGUgPC0gcmJpbmQoZGF0YXNldF9jb21wbGV0ZSwgZGF0YS5mcmFtZShjaXR5PWNpdCwgbWVkaWFuX3ByaWNlX0NMPWNsYXNzLCBuPTApKQ0KICAgIH0NCiAgfQ0KfQ0KDQoNCg0KIyBuZXh0IHdlIHZpc3VhbGl6ZSB2aWEgYSBiYXIgcGxvdCB0aGUgZGlzdHJpYnV0aW9uIG9mIGNsYXNzZXMgb2YgcHJpY2UgYWNyb3NzIHRoZSBkaWZmZXJlbnQgY2l0aWVzDQpnZ3Bsb3QoZGF0YT1kYXRhc2V0X2NvbXBsZXRlKSsNCiAgZ2VvbV9jb2woYWVzKHg9bWVkaWFuX3ByaWNlX0NMLA0KICAgICAgICAgICAgICAgeT1uLA0KICAgICAgICAgICAgICAgZmlsbD1jaXR5KSwNCiAgICAgICAgICAgcG9zaXRpb249ImRvZGdlMiIsICAjZG9kZ2UsICNmaWxsLCAjc3RhY2sNCiAgICAgICAgICAgc3RhdD0iaWRlbnRpdHkiLA0KICAgICAgICAgICBjb2w9ImJsYWNrIikrDQogIGxhYnModGl0bGU9IkRpc3RyaWJ1emlvbmUgZGVsbGUgY2xhc3NpIGRlbGxhIG1lZGlhbmEgZGkgcHJlenpvIiwNCiAgICAgICB4PSJtZWRpYW4gcHJpY2UgaW4gY2xhc3NlcyIsDQogICAgICAgeT0iYWJzb2x1dGUgZnJlcXVlbmN5IikrDQogIHNjYWxlX3lfY29udGludW91cyhicmVha3MgPSBzZXEoMCw2MCwxMCkpKw0KICB0aGVtZV9jbGFzc2ljKCkrDQogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gMTUsIGhqdXN0ID0gMSksDQogICAgICAgIGF4aXMudGl0bGUueCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTQsIG1hcmdpbiA9IG1hcmdpbih0ID0gMTApKSwNCiAgICAgICAgYXhpcy50aXRsZS55ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNCwgbWFyZ2luID0gbWFyZ2luKHIgPSAxMCkpLA0KICAgICAgICBsZWdlbmQucG9zaXRpb24gPSJib3R0b20iKQ0KDQoNCg0KDQoNCmBgYA0KDQpBcyB3ZSBjYW4gb2JzZXJ2ZSBmcm9tIHRoZSBHaW5pIGhldGVyb2dlbmVpdHkgaW5kZXggY2xvc2UgdG8gMSBhbmQgdGhlIGJhciBwbG90cyBvZiB0aGUgZGlzdHJpYnV0aW9uIGluIHRoZSBwcmljZSBjbGFzc2VzLCB0aGUgZGF0YXNldCBpcyBkaXN0cmlidXRlZCBkaXNjcmVldGx5IHVuaWZvcm1seSBhY3Jvc3MgdGhlIGRpZmZlcmVudCBtZWRpYW4tcHJpY2UgY2xhc3Nlcy4NCkhvd2V2ZXIsIHRoZSBkaXN0cmlidXRpb24gb2YgdGhlIGRhdGEgcmVsYXRpdmUgdG8gdGhlIGRpZmZlcmVudCBjaXRpZXMgYWNyb3NzIHRoZSBjbGFzc2VzIG9mIHByaWNlIGlzIGRpc3RyaWJ1dGVkIHNpZ25pZmljYW50bHkgbGVzcyB1bmlmb3JtbHkuIFRoaXMgaXMgcmVmbGVjdGVkIGJvdGggYnkgc2lnbmlmaWNhbnRseSBsb3dlciB2YWx1ZXMgb2YgdGhlIEdpbmkgaW5kZXggYW5kIGJ5IHRoZSBiYXIgcGxvdCByZWxhdGl2ZSB0byB0aGUgZGlmZmVyZW50IGNpdGllcy4gU3BlY2lmaWNhbGx5LCB3ZSBvYnNlcnZlIHRoYXQgdGhlIHByaWNlcyBpbiBXaWNoaXRhIEZhbGxzIGFyZSBnZW5lcmFsbHkgbG93ZXIgdGhhbiB0aG9zZSBvZiBCZWF1bW9udCB3aGljaCBhcmUgc21hbGxlciB0aGFuIHRob3NlIG9mIFR5bGVyIHdoaWNoIGFyZSBmaW5hbGx5IGdlbmVyYWxseSBzbWFsbGVyIHRoYW4gdGhvc2Ugb2YgQnJ5YW4tQ29sbGVnZSBTdGF0aW9uLg0KDQoNCldlIGZpbmFsbHkgaW5jbHVkZSBhIGJveHBsb3Qgb2YgdGhlIGRpc3RyaWJ1dGlvbiBvZiBtZWRpYW5fcHJpY2UgYWNyb3NzIHRoZSBkaWZmZXJlbnQgY2l0aWVzIHRvIHF1YW50aWZ5IHRoZSB2YXJpYWJpbGl0eSBvZiB0aGUgbWVkaWFuIHByaWNlIGZvciBlYWNoIGNpdHkuDQoNCg0KYGBge3J9DQoNCmdncGxvdChkYXRhPWRhdGFzZXQsDQogICAgICAgYWVzKHg9Y2l0eSwNCiAgICAgICAgICAgeT1tZWRpYW5fcHJpY2UsDQogICAgICAgICAgIGZpbGw9Y2l0eSkpKw0KICAgICAgIGdlb21fYm94cGxvdCgpKw0KICAgICAgIGdlb21faGxpbmUoeWludGVyY2VwdCA9IHN0YXRpc3RpY3NbIm1lZGlhbl9wcmljZSIsInF1YXJ0aWxlXzMiXSwgY29sb3IgPSAicmVkIikrDQogICAgICAgZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0gc3RhdGlzdGljc1sibWVkaWFuX3ByaWNlIiwicXVhcnRpbGVfMSJdLCBjb2xvciA9ICJyZWQiKSsNCiAgICAgICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQgPSBzdGF0aXN0aWNzWyJtZWRpYW5fcHJpY2UiLCJtZWFuIl0sIGNvbG9yID0gInJlZCIpKw0KICAgICAgIGxhYnModGl0bGU9IkNvbXBhcmlzb24gb2YgbWVkaWFuX3ByaWNlIGJ5IGNpdHkiLA0KICAgICAgICAgICAgeD0iY2l0eSIsDQogICAgICAgICAgICB5PSJtZWRpYW5fcHJpY2UiKSsNCiAgICAgICBhbm5vdGF0ZSgibGFiZWwiLCB4ID0gSW5mLCB5ID0gc3RhdGlzdGljc1sibWVkaWFuX3ByaWNlIiwicXVhcnRpbGVfMSJdLCBsYWJlbCA9ICIxwrAgcXVhcnRpbGUgbWVkaWFuX3ByaWNlIiwgaGp1c3QgPSAxLjEsIHZqdXN0ID0gKy41LCBmaWxsPSJncmV5IiwgY29sb3IgPSAicmVkIikrDQogICAgICAgYW5ub3RhdGUoImxhYmVsIiwgeCA9IEluZiwgeSA9IHN0YXRpc3RpY3NbIm1lZGlhbl9wcmljZSIsIm1lZGlhbiJdLCBsYWJlbCA9ICJtZWRpYW4gbWVkaWFuX3ByaWNlIiwgaGp1c3QgPSAxLjEsIHZqdXN0ID0gKy41LCBmaWxsPSJncmV5IiwgY29sb3IgPSAicmVkIikrDQogICAgICAgYW5ub3RhdGUoImxhYmVsIiwgeCA9IEluZiwgeSA9IHN0YXRpc3RpY3NbIm1lZGlhbl9wcmljZSIsInF1YXJ0aWxlXzMiXSwgbGFiZWwgPSAiM8KwIHF1YXJ0aWxlIG1lZGlhbl9wcmljZSIsIGhqdXN0ID0gMS4xLCB2anVzdCA9ICsuNSwgZmlsbD0iZ3JleSIsIGNvbG9yID0gInJlZCIpKw0KICAgICAgIHRoZW1lX2NsYXNzaWMoKSsNCiAgICAgICBzY2FsZV94X2Rpc2NyZXRlKGV4cGFuZCA9IGV4cGFuc2lvbihhZGQgPSBjKC41LCAyKSkpKw0KICAgICAgIHRoZW1lKHBsb3QudGl0bGUucG9zaXRpb24gPSAicGFuZWwiLA0KICAgICAgICAgICAgIHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZT0xNiwgaGp1c3Q9MC41KSwNCiAgICAgICAgICAgICBheGlzLnRpdGxlLnggPSBlbGVtZW50X3RleHQoc2l6ZT0xNCksDQogICAgICAgICAgICAgYXhpcy50aXRsZS55ID0gZWxlbWVudF90ZXh0KHNpemU9MTQpLA0KICAgICAgICAgICAgIGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KHNpemU9MTApLA0KICAgICAgICAgICAgIGF4aXMudGV4dC55ID0gZWxlbWVudF90ZXh0KHNpemU9MTApLA0KICAgICAgICAgICAgIGxlZ2VuZC5wb3NpdGlvbiA9ImJvdHRvbSIpDQoNCmBgYA0KV2UgY2FuIG9ic2VydmUgdGhhdCB0aGUgbWVkaWFuIHByaWNlIGluIGRpZmZlcmVudCBjaXRpZXMgZXhoaWJpdHMgc2ltaWxhciB2YXJpYWJpbGl0eSwgbWVhc3VyZWQgaW4gdGVybXMgb2YgaW50ZXJxdWFydGlsZSByYW5nZSwgYW5kIHNpZ25pZmljYW50bHkgbG93ZXIgdmFyaWFiaWxpdHkgdGhhbiB0aGF0IGZvdW5kIGJ5IGNvbnNpZGVyaW5nIGFsbCB0aGUgY2l0aWVzIHRvZ2V0aGVyLiBUaGlzIGlzIGR1ZSB0byB0aGUgZmFjdCB0aGF0IHRoZSBtZWRpYW4gcHJpY2UgcmFuZ2UgZGlmZmVycyBzaWduaWZpY2FudGx5IGZyb20gY2l0eSB0byBjaXR5Lg0KDQoNCg0KIyMgKio8c3BhbiBzdHlsZT0iY29sb3I6cmVkIj4gWzZdIDwvc3Bhbj4gQ3JlYXRpb24gb2YgbmV3IHZhcmlhYmxlcyoqDQojIyMgV2UgY3JlYXRlIHRocmVlIG5ldyB2YXJpYmFsZXMgbWVhc3VyaW5nIHRoZSBtZWFuIHNlbGxpbmcgcHJpY2UgaW4gVVMgZG9sbGFycywgdGhlIGVmZmVjdGl2ZW5lc3Mgb2YgdGhlIHNhbGVzIGFkcyBhbmQgdGhlIGRhdGUgbWVhc3VyZWQgaW4gbW90aHMgZnJvbSBKYW51YXJ5IDIwMTAuICANCi0gVGhlIHZhcmlhYmxlICptZWFuX3ByaWNlKiBpcyBvYnRhaW5lZCBhcyAkMTBeNiQoKnZvbHVtZSovKnNhbGVzKikuDQotIFRoZSB2YXJpYWJsZSAqZWZmZWN0aXZlbmVzcyogaXMgb2J0YWluZWQgYXMgKCpsaXN0aW5ncyovKm1vbnRoc19pbnZlbnRvcnkqKSB3aGljaCBtZWFzdXJlcyB0aGUgYXZlcmFnZSBtb250aGx5IHNhbGVzIHJhdGUgb2YgdGhlIHByb3BlcnRpZXMgbGlzdGVkIGluIGEgY2l0eSBpbiBhIGdpdmVuIG1vbnRoL3llYXIuDQotIFRoZSB2YXJpYWJsZSAqZGF0ZSogd2hpY2ggcmV0dXJucyB0aGUgZGF0ZSBvZiBlYWNoIGRhdGEgaW4gbW9udGhzIGZyb20gamFudWFyeSAyMDEwLCB0aGlzIGlzIG9idGFpbmVkIGFzICRtb250aCsxMihtb2QoeWVhciwyMDEwKSkkLg0KDQpgYGB7cn0NCmRhdGFzZXQkbWVhbl9wcmljZSA8LSAodm9sdW1lL3NhbGVzKSoxMF42DQoNCmRhdGFzZXQkZWZmZWN0aXZlbmVzcyA8LSAobGlzdGluZ3MvbW9udGhzX2ludmVudG9yeSkNCg0KZGF0YXNldCRkYXRlIDwtIChhcy5udW1lcmljKGFzLmNoYXJhY3Rlcihtb250aCkpKSsxMiooYXMubnVtZXJpYyhhcy5jaGFyYWN0ZXIoeWVhcikpJSUobWluKGFzLm51bWVyaWMoYXMuY2hhcmFjdGVyKHllYXIpKSkpKQ0KYGBgDQoNCg0KTmV4dCB3ZSBzdHVkeSB0aGUgdHJlbmQgb2YgdGhlIHF1YW50aXRhdGl2ZSB2YXJpYWJsZXMgb3ZlciB0aW1lLiANCg0KDQpgYGB7ciwgZmlnLndpZHRoPTE0LCBmaWcuaGVpZ2h0PTE1fQ0KDQojIFdlIHVzZSB0aGUgcGFja2FnZSAqcGF0Y2h3b3JrKiBpbiBjb21iaW5hdGlvbiB3aXRoICpnZ3Bsb3QyKiB0byBwcm92aWRlIGEgY3VtdWxhdGl2ZSBzaWduaWZpY2FudCByZXByZXNlbnRhdGlvbiBvZiBhbGwgdGhlIHF1YW50aXRhdGl2ZSB2YXJpYWJsZXMgaW4gYSBzaW5nbGUgbXVsdGktcGFuZWwgZmlndXJlDQojIFdlIGFsc28gdXNlIHRoZSBwYWNrYWdlICpnZ3B1YnIqIHRvIGV4dHJhY3QgdGhlIGxlZ2VuZCBmcm9tIGEgZmlndXJlIGFuZCBwcmludCBpdCBhcyBhIHVuaXF1ZSBsZWdlbmQgZm9yIGFsbCB0aGUgcGxvdHMuDQoNCg0KIyBUaGUgZnVuY3Rpb24gbW9udGhfY29udmVydCBjb252ZXJ0IGEgbnVtYmVyIGJldHdlZW4gMSBhbmQgMTIgaW50byBhIHN0cmluZyBpbmRpY2F0aW5nIHRoZSBjb3JyZXNwb25kaW5nIG1vbnRoLg0KbW9udGhfY29udmVydCA8LSBmdW5jdGlvbih4KXsNCiAgeF9uPWFzLm51bWVyaWMoYXMuY2hhcmFjdGVyKHgpKQ0KICBtb250aHM9YygiSmFuIiwgIkZlYiIsICJNYXIiLCAiQXByIiwgIk1heSIsICJKdW4iLCAiSnVsIiwgIkF1ZyIsICJTZXAiLCAiT2N0IiwgIk5vdiIsICJEZWMiKQ0KICByZXR1cm4obW9udGhzW3hfbl0pDQp9DQoNCg0KIyBUaGUgZnVuY3Rpb24gYnJlYWtpbmdfcG9pbnRzIHRha2VzIGluIGlucHV0IGEgdmVjdG9yIG9mIGRhdGVzIGV4cHJlc3NlZCBtb250aHMgYW5kIGNvbnZlcnQgaW4gdmVjdG9yIG9mIGRhdGVzIGV4cHJlc3NlZCBhcyBtb250aCt5ZWFyLg0KIyBUaGlzIHdpbGwgYmUgdXNlZCB0byBwcm9kdWNlIHRoZSB4LWF4aXMgbGFiZWxzIGluIHRoZSBwbG90cyB3aXRoIHRoZSB0cmVuZCBvZiB0aGUgdmFyaWFibGVzIG92ZXIgdGltZS4gDQpicmVha2luZ19wb2ludHMgPC0gZnVuY3Rpb24oeCkgew0KICByZXR1cm4ocGFzdGUobW9udGhfY29udmVydChkYXRhc2V0JG1vbnRoW3hdKSwgZGF0YXNldCR5ZWFyW3hdLCBzZXA9IiAiKSApDQp9DQoNCg0KIyBXZSBwcm9kdWNlIGEgZmlyc3QgcGxvdCBvbmx5IHRvIGV4dHJhY3QgdGhlIGxlZ2VuZC4NCmxpbmVfc2FsZXMgPC0gZ2dwbG90KGRhdGE9ZGF0YXNldCkrDQogIGdlb21fbGluZShhZXMoeCA9IGRhdGUsDQogICAgICAgICAgICAgICAgeSA9IHNhbGVzLA0KICAgICAgICAgICAgICAgIGdyb3VwID0gY2l0eSwNCiAgICAgICAgICAgICAgICBjb2xvciA9IGNpdHkpLCANCiAgICAgICAgICAgIHNpemUgPSAxLjUpKw0KICAgIHRoZW1lKGxlZ2VuZC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTgpLA0KICAgICAgICAgIGxlZ2VuZC50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNikpDQoNCiMgV2UgZXh0cmFjdCB0aGUgbGVnZW5kDQpsZWdlbmRfbGluZSA8LSBhc19nZ3Bsb3QoZ2V0X2xlZ2VuZChsaW5lX3NhbGVzKSkNCg0KDQojIFdlIHByb2R1Y2UgdGhlIHBsb3Qgd2l0aCB0aGUgdHJlbmQgb2YgdGhlIHNhbGVzIG92ZXIgdGltZS4NCmxpbmVfc2FsZXMgPC0gZ2dwbG90KGRhdGE9ZGF0YXNldCkrDQogIGdlb21fbGluZShhZXMoeCA9IGRhdGUsDQogICAgICAgICAgICAgICAgeSA9IHNhbGVzLA0KICAgICAgICAgICAgICAgIGdyb3VwID0gY2l0eSwNCiAgICAgICAgICAgICAgICBjb2xvciA9IGNpdHkpLCANCiAgICAgICAgICAgIHNpemUgPSAxLjUpKw0KICBnZW9tX3BvaW50KGFlcyh4ID0gZGF0ZSwNCiAgICAgICAgICAgICAgICB5ID0gc2FsZXMsDQogICAgICAgICAgICAgICAgZ3JvdXAgPSBjaXR5LA0KICAgICAgICAgICAgICAgIGNvbG9yID0gY2l0eSksIA0KICAgICAgICAgICAgIHNpemUgPSAzKSsNCiAgbGFicyh0aXRsZT0iQ29tcGFyaXNvbiBvZiBzYWxlcyBieSB0aW1lIGZvciB0aGUgZGlmZmVyZW50IGNpdGllcyIsDQogICAgICAgeD0idGltZSIsDQogICAgICAgeT0ic2FsZXMiKSsNCiAgIHNjYWxlX3hfY29udGludW91cyhicmVha3MgPSAoc2VxKDEsNjAsIGJ5ID0gNikpLA0KICAgICAgICAgICAgICAgICAgICAgIGxhYmVscyA9IGJyZWFraW5nX3BvaW50cykrDQogIHRoZW1lX2NsYXNzaWMoKSsNCiAgdGhlbWUocGxvdC50aXRsZS5wb3NpdGlvbiA9ICJwYW5lbCIsDQogICAgICAgIHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZT0xOCwgaGp1c3Q9MC41KSwNCiAgICAgICAgYXhpcy50aXRsZS54ID0gZWxlbWVudF90ZXh0KHNpemU9MTYpLA0KICAgICAgICBheGlzLnRpdGxlLnkgPSBlbGVtZW50X3RleHQoc2l6ZT0xNiksDQogICAgICAgIGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KHNpemU9MTApLA0KICAgICAgICBheGlzLnRleHQueSA9IGVsZW1lbnRfdGV4dChzaXplPTEwKSwNCiAgICAgICAgbGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKQ0KDQoNCiMgV2UgcHJvZHVjZSB0aGUgcGxvdCB3aXRoIHRoZSB0cmVuZCBvZiB0aGUgdm9sdW1lIG92ZXIgdGltZS4NCmxpbmVfdm9sdW1lIDwtIGdncGxvdChkYXRhPWRhdGFzZXQpKw0KICBnZW9tX2xpbmUoYWVzKHggPSBkYXRlLA0KICAgICAgICAgICAgICAgIHkgPSB2b2x1bWUsDQogICAgICAgICAgICAgICAgZ3JvdXAgPSBjaXR5LA0KICAgICAgICAgICAgICAgIGNvbG9yID0gY2l0eSksIA0KICAgICAgICAgICAgc2l6ZSA9IDEuNSkrDQogIGdlb21fcG9pbnQoYWVzKHggPSBkYXRlLA0KICAgICAgICAgICAgICAgIHkgPSB2b2x1bWUsDQogICAgICAgICAgICAgICAgZ3JvdXAgPSBjaXR5LA0KICAgICAgICAgICAgICAgIGNvbG9yID0gY2l0eSksIA0KICAgICAgICAgICAgIHNpemUgPSAzKSsNCiAgbGFicyh0aXRsZT0iQ29tcGFyaXNvbiBvZiB2b2x1bWUgYnkgdGltZSBmb3IgdGhlIGRpZmZlcmVudCBjaXRpZXMiLA0KICAgICAgIHg9InRpbWUiLA0KICAgICAgIHk9InZvbHVtZSIpKw0KICAgc2NhbGVfeF9jb250aW51b3VzKGJyZWFrcyA9IChzZXEoMSw2MCwgYnkgPSA2KSksDQogICAgICAgICAgICAgICAgICAgICAgbGFiZWxzID0gYnJlYWtpbmdfcG9pbnRzKSsNCiAgdGhlbWVfY2xhc3NpYygpKw0KICB0aGVtZShwbG90LnRpdGxlLnBvc2l0aW9uID0gInBhbmVsIiwNCiAgICAgICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplPTE4LCBoanVzdD0wLjUpLA0KICAgICAgICBheGlzLnRpdGxlLnggPSBlbGVtZW50X3RleHQoc2l6ZT0xNiksDQogICAgICAgIGF4aXMudGl0bGUueSA9IGVsZW1lbnRfdGV4dChzaXplPTE2KSwNCiAgICAgICAgYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoc2l6ZT0xMCksDQogICAgICAgIGF4aXMudGV4dC55ID0gZWxlbWVudF90ZXh0KHNpemU9MTApLA0KICAgICAgICBsZWdlbmQucG9zaXRpb24gPSAibm9uZSIpDQoNCg0KIyBXZSBwcm9kdWNlIHRoZSBwbG90IHdpdGggdGhlIHRyZW5kIG9mIHRoZSBtZWRpYW5fcHJpY2Ugb3ZlciB0aW1lLg0KbGluZV9wcmljZSA8LSBnZ3Bsb3QoZGF0YT1kYXRhc2V0KSsNCiAgZ2VvbV9saW5lKGFlcyh4ID0gZGF0ZSwNCiAgICAgICAgICAgICAgICB5ID0gbWVkaWFuX3ByaWNlLA0KICAgICAgICAgICAgICAgIGdyb3VwID0gY2l0eSwNCiAgICAgICAgICAgICAgICBjb2xvciA9IGNpdHkpLCANCiAgICAgICAgICAgIHNpemUgPSAxLjUpKw0KICBnZW9tX3BvaW50KGFlcyh4ID0gZGF0ZSwNCiAgICAgICAgICAgICAgICB5ID0gbWVkaWFuX3ByaWNlLA0KICAgICAgICAgICAgICAgIGdyb3VwID0gY2l0eSwNCiAgICAgICAgICAgICAgICBjb2xvciA9IGNpdHkpLCANCiAgICAgICAgICAgICBzaXplID0gMykrDQogIGxhYnModGl0bGU9IkNvbXBhcmlzb24gb2YgbWVkaWFuIHByaWNlIGJ5IHRpbWUgZm9yIHRoZSBkaWZmZXJlbnQgY2l0aWVzIiwNCiAgICAgICB4PSJ0aW1lIiwNCiAgICAgICB5PSJtZWRpYW4gcHJpY2UiKSsNCiAgIHNjYWxlX3hfY29udGludW91cyhicmVha3MgPSAoc2VxKDEsNjAsIGJ5ID0gNikpLA0KICAgICAgICAgICAgICAgICAgICAgIGxhYmVscyA9IGJyZWFraW5nX3BvaW50cykrDQogIHRoZW1lX2NsYXNzaWMoKSsNCiAgdGhlbWUocGxvdC50aXRsZS5wb3NpdGlvbiA9ICJwYW5lbCIsDQogICAgICAgIHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZT0xOCwgaGp1c3Q9MC41KSwNCiAgICAgICAgYXhpcy50aXRsZS54ID0gZWxlbWVudF90ZXh0KHNpemU9MTYpLA0KICAgICAgICBheGlzLnRpdGxlLnkgPSBlbGVtZW50X3RleHQoc2l6ZT0xNiksDQogICAgICAgIGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KHNpemU9MTApLA0KICAgICAgICBheGlzLnRleHQueSA9IGVsZW1lbnRfdGV4dChzaXplPTEwKSwNCiAgICAgICAgbGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKQ0KDQoNCg0KIyBXZSBwcm9kdWNlIHRoZSBwbG90IHdpdGggdGhlIHRyZW5kIG9mIHRoZSBsaXN0aW5ncyBvdmVyIHRpbWUuDQpsaW5lX2xpc3RpbmdzIDwtIGdncGxvdChkYXRhPWRhdGFzZXQpKw0KICBnZW9tX2xpbmUoYWVzKHggPSBkYXRlLA0KICAgICAgICAgICAgICAgIHkgPSBsaXN0aW5ncywNCiAgICAgICAgICAgICAgICBncm91cCA9IGNpdHksDQogICAgICAgICAgICAgICAgY29sb3IgPSBjaXR5KSwgDQogICAgICAgICAgICBzaXplID0gMS41KSsNCiAgZ2VvbV9wb2ludChhZXMoeCA9IGRhdGUsDQogICAgICAgICAgICAgICAgeSA9IGxpc3RpbmdzLA0KICAgICAgICAgICAgICAgIGdyb3VwID0gY2l0eSwNCiAgICAgICAgICAgICAgICBjb2xvciA9IGNpdHkpLCANCiAgICAgICAgICAgICBzaXplID0gMykrDQogIGxhYnModGl0bGU9IkNvbXBhcmlzb24gb2YgbGlzdGluZ3MgYnkgdGltZSBmb3IgdGhlIGRpZmZlcmVudCBjaXRpZXMiLA0KICAgICAgIHg9InRpbWUiLA0KICAgICAgIHk9Imxpc3RpbmdzIikrDQogICBzY2FsZV94X2NvbnRpbnVvdXMoYnJlYWtzID0gKHNlcSgxLDYwLCBieSA9IDYpKSwNCiAgICAgICAgICAgICAgICAgICAgICBsYWJlbHMgPSBicmVha2luZ19wb2ludHMpKw0KICB0aGVtZV9jbGFzc2ljKCkrDQogIHRoZW1lKHBsb3QudGl0bGUucG9zaXRpb24gPSAicGFuZWwiLA0KICAgICAgICBwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemU9MTgsIGhqdXN0PTAuNSksDQogICAgICAgIGF4aXMudGl0bGUueCA9IGVsZW1lbnRfdGV4dChzaXplPTE2KSwNCiAgICAgICAgYXhpcy50aXRsZS55ID0gZWxlbWVudF90ZXh0KHNpemU9MTYpLA0KICAgICAgICBheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChzaXplPTEwKSwNCiAgICAgICAgYXhpcy50ZXh0LnkgPSBlbGVtZW50X3RleHQoc2l6ZT0xMCksDQogICAgICAgIGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikNCg0KDQojIFdlIHByb2R1Y2UgdGhlIHBsb3Qgd2l0aCB0aGUgdHJlbmQgb2YgdGhlIG1vbnRoc19pbnZlbnRvcnkgb3ZlciB0aW1lLg0KbGluZV9pbnZlbnRvcnkgPC0gZ2dwbG90KGRhdGE9ZGF0YXNldCkrDQogIGdlb21fbGluZShhZXMoeCA9IGRhdGUsDQogICAgICAgICAgICAgICAgeSA9IG1vbnRoc19pbnZlbnRvcnksDQogICAgICAgICAgICAgICAgZ3JvdXAgPSBjaXR5LA0KICAgICAgICAgICAgICAgIGNvbG9yID0gY2l0eSksIA0KICAgICAgICAgICAgc2l6ZSA9IDEuNSkrDQogIGdlb21fcG9pbnQoYWVzKHggPSBkYXRlLA0KICAgICAgICAgICAgICAgIHkgPSBtb250aHNfaW52ZW50b3J5LA0KICAgICAgICAgICAgICAgIGdyb3VwID0gY2l0eSwNCiAgICAgICAgICAgICAgICBjb2xvciA9IGNpdHkpLCANCiAgICAgICAgICAgICBzaXplID0gMykrDQogIGxhYnModGl0bGU9IkNvbXBhcmlzb24gb2YgbW9udGhzIGludmVudG9yeSBieSB0aW1lIGZvciB0aGUgZGlmZmVyZW50IGNpdGllcyIsDQogICAgICAgeD0idGltZSIsDQogICAgICAgeT0ibW9udGhzIGludmVudG9yeSIpKw0KICAgc2NhbGVfeF9jb250aW51b3VzKGJyZWFrcyA9IChzZXEoMSw2MCwgYnkgPSA2KSksDQogICAgICAgICAgICAgICAgICAgICAgbGFiZWxzID0gYnJlYWtpbmdfcG9pbnRzKSsNCiAgdGhlbWVfY2xhc3NpYygpKw0KICB0aGVtZShwbG90LnRpdGxlLnBvc2l0aW9uID0gInBhbmVsIiwNCiAgICAgICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplPTE4LCBoanVzdD0wLjUpLA0KICAgICAgICBheGlzLnRpdGxlLnggPSBlbGVtZW50X3RleHQoc2l6ZT0xNiksDQogICAgICAgIGF4aXMudGl0bGUueSA9IGVsZW1lbnRfdGV4dChzaXplPTE2KSwNCiAgICAgICAgYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoc2l6ZT0xMCksDQogICAgICAgIGF4aXMudGV4dC55ID0gZWxlbWVudF90ZXh0KHNpemU9MTApLA0KICAgICAgICBsZWdlbmQucG9zaXRpb24gPSAibm9uZSIpDQoNCg0KIyBXZSBjb21iaW5lIGFsbCB0aGUgYWJvdmUgcGxvdHMgYW5kIHRoZSBsYWJlbCBpbiBvbmUgZmlndXJlLg0KY29tYl9saW5lc19maWcgPSBsaW5lX3NhbGVzICsgbGluZV92b2x1bWUgKyBsaW5lX3ByaWNlICsgbGluZV9saXN0aW5ncyArIGxpbmVfaW52ZW50b3J5ICsgbGVnZW5kX2xpbmUgICsgcGxvdF9sYXlvdXQobmNvbD0yLCBoZWlnaHRzID0gYyg1LCA1LCA1KSkNCnByaW50KGNvbWJfbGluZXNfZmlnKQ0KDQoNCnJtKGxpbmVfc2FsZXMsIGxpbmVfdm9sdW1lLCBsaW5lX3ByaWNlLCBsaW5lX2xpc3RpbmdzLCBsaW5lX2ludmVudG9yeSwgbGVnZW5kX2xpbmUsIGNvbWJfbGluZXNfZmlnKQ0KYGBgDQoNCkZyb20gdGhlIGxhc3QgcGxvdHMgd2Ugb2JzZXJ2ZToNCg0KLSBBIHBlcmlvZGljIHRyZW5kIGluIGFsbW9zdCBhbGwgdGhlIHZhcmlhYmxlcywgd2l0aCB0aGUgZXhjZXB0aW9uIG9mIHRoZSBtZWRpYW5fcHJpY2UuIEluIHBhcnRpY3VsYXIsIGhpZ2hlciBzYWxlcywgdm9sdW1lLCBsaXN0aW5ncyBhbmQgbW9udGggaW52ZW50b3J5IGFyZSBvYnNlcnZlZCBpbiB0aGUgc3VtbWVyIHJhdGhlciB0aGFuIGluIHRoZSB3aW50ZXIuDQpUaGUgZGlmZmVyZW5jZSBiZXR3ZWVuIHN1bW1lciBhbmQgd2ludGVyIGlzIHdlbGwgbWFya2VkIGluIHRoZSBjaXRpZXMgb2YgVHlsZXIgYW5kIEJyeWFuLUNvbGxlZ2UgU3RhdGlvbiB3aGlsZSBhbG1vc3QgaW1wZXJjZXB0aWJsZSBpbiB0aGUgY2l0eSBvZiBXaWNoaXRhIEZhbGxzLg0KDQotIEl0IGlzIGFsc28gcG9zc2libGUgdG8gb2JzZXJ2ZSB0aGF0LCBpbiBhdmVyYWdlLCB0aGUgbGlzdGluZ3MgYW5kIG1vbnRocyBpbnZlbnRvcnkgYXJlIGRlY3JlYXNpbmcgb3ZlciB0aGUgeWVhciB3aGlsZSBzYWxlcywgdm9sdW1lIGFuZCBtZWRpYW4gcHJpY2UgYXJlIGluY3JlYXNpbmcuIEFsc28gaW4gdGhpcyBjYXNlLCB0aGUgY2l0eSBvZiBXaWNoaXRhIEZhbGxzIGlzIHRoZSBvbmUgd2hlcmUgdGhpcyBwaGVub21lbm9uIGlzIGxlc3MgZXZpZGVudC4NCg0KV2Ugc3R1ZHkgZGVlcGVyIGFuZCBxdWFudGlmeSB0aGVzZSBwaGVub21lbmEsIGFuZCBvdGhlciB0aGF0IGNhbiBiZSBvYnNlcnZlZCBpbiB0aGUgcGxvdHMsIGluIHRoZSBmb2xsb3dpbmcgb2YgdGhpcyByZXBvcnQuIA0KDQoNCg0KIyMgKio8c3BhbiBzdHlsZT0iY29sb3I6cmVkIj4gWzddIDwvc3Bhbj4gQW5hbHlzaXMgb2YgdGhlIHZhcmlhYmxlcyBiYXNlZCBvbiBjaXRpZXMsIHllYXJzIGFuZCBtb250aHMqKg0KDQojIyMgRmlyc3Qgd2UgcHJvdmlkZSBhIHN0YXRpc3RpY2FsIGFuYWx5c2lzIG9mIHRoZSBxdWFudGl0YXRpdmUgdmFyaWFibGVzLCBjb21wdXRpbmcgdGhlaXIgbWVhbiwgc3RhbmRhcmQgZGV2aWF0aW9uIGFuZCB2YXJpYXRpb24gY29lZmZpY2llbnQsIGJhc2VkIG9uIGNpdGllcyBhbmQgeWVhci4NCldlIHN1bW1hcml6ZSB0aGUgcmVzdWx0cyBpbiB0aGUgdGFibGVzIGJlbG93IGFuZCByZXByZXNlbnQgdGhlIHJlc3VsdHMgZ3JhcGhpY2FsbHkgYnkgYmFyIHBsb3RzIGFuZCBib3ggcGxvdHMuDQoNCg0KYGBge3J9DQojIHdlIHVzZSB0aGUgcGFja2FnZSBkcGx5ciB0byBjb25kdWN0IGNvbmRpdGlvbmVkIHN0YXRpc3RpY2FsIGFuYWx5c2lzIGJ5IGNpdHkgYW5kIHllYXIuDQoNCmNvbmRpdGlvbmFsX2RhdGFzZXRfY2l0eSA8LQ0KICBkYXRhc2V0ICU+JSANCiAgZ3JvdXBfYnkoY2l0eSkgJT4lDQogIHN1bW1hcmlzZShtZWFuX3NhbGVzID0gcm91bmQobWVhbihzYWxlcyksMiksDQogICAgICAgICAgICBzZF9zYWxlcyA9IHJvdW5kKHNkKHNhbGVzKSwyKSwNCiAgICAgICAgICAgIGN2X3NhbGVzID0gcm91bmQoY3ZfZnVuY3Qoc2FsZXMpLCAyKSwNCiAgDQogICAgICAgICAgICBtZWFuX3ZvbHVtZT1yb3VuZChtZWFuKHZvbHVtZSksMiksDQogICAgICAgICAgICBzZF92b2x1bWU9cm91bmQoc2Qodm9sdW1lKSwyKSwNCiAgICAgICAgICAgIGN2X3ZvbHVtZSA9IHJvdW5kKGN2X2Z1bmN0KHZvbHVtZSksIDIpLA0KICAgICAgICAgICAgDQogICAgICAgICAgICBtZWFuX21lZF9wcmljZT1yb3VuZChtZWFuKG1lZGlhbl9wcmljZSksMiksDQogICAgICAgICAgICBzZF9tZWRfcHJpY2U9cm91bmQoc2QobWVkaWFuX3ByaWNlKSwyKSwNCiAgICAgICAgICAgIGN2X21lZF9wcmljZSA9IHJvdW5kKGN2X2Z1bmN0KG1lZGlhbl9wcmljZSksIDIpLA0KICAgICAgICAgICAgDQogICAgICAgICAgICBtZWFuX21lYW5fcHJpY2U9cm91bmQobWVhbihtZWFuX3ByaWNlKSwyKSwNCiAgICAgICAgICAgIHNkX21lYW5fcHJpY2U9cm91bmQoc2QobWVhbl9wcmljZSksMiksDQogICAgICAgICAgICBjdl9tZWFuX3ByaWNlID0gcm91bmQoY3ZfZnVuY3QobWVhbl9wcmljZSksIDIpLA0KICAgICAgICAgICAgDQogICAgICAgICAgICBtZWFuX2xpc3RpbmdzPXJvdW5kKG1lYW4obGlzdGluZ3MpLDIpLA0KICAgICAgICAgICAgc2RfbGlzdGluZ3M9cm91bmQoc2QobGlzdGluZ3MpLDIpLA0KICAgICAgICAgICAgY3ZfbGlzdGluZ3MgPSByb3VuZChjdl9mdW5jdChsaXN0aW5ncyksIDIpLA0KICANCiAgICAgICAgICAgIG1lYW5faW52ZW50b3J5PXJvdW5kKG1lYW4obW9udGhzX2ludmVudG9yeSksMiksDQogICAgICAgICAgICBzZF9pbnZlbnRvcnk9cm91bmQoc2QobW9udGhzX2ludmVudG9yeSksMiksDQogICAgICAgICAgICBjdl9pbnZlbnRvcnkgPSByb3VuZChjdl9mdW5jdChtb250aHNfaW52ZW50b3J5KSwgMiksDQogICAgICAgICAgICANCiAgICAgICAgICAgIG1lYW5fZWZmZWN0aXZuZXNzPXJvdW5kKG1lYW4oZWZmZWN0aXZlbmVzcyksMiksDQogICAgICAgICAgICBzZF9lZmZlY3RpdmVuZXNzPXJvdW5kKHNkKGVmZmVjdGl2ZW5lc3MpLDIpLA0KICAgICAgICAgICAgY3ZfZWZmZWN0aXZlbmVzcyA9IHJvdW5kKGN2X2Z1bmN0KGVmZmVjdGl2ZW5lc3MpLCAyKSwNCiAgICAgICAgICAgICkNCg0KZGZfdCA8LSBhcy5kYXRhLmZyYW1lKHQoY29uZGl0aW9uYWxfZGF0YXNldF9jaXR5WzI6ZGltKGNvbmRpdGlvbmFsX2RhdGFzZXRfY2l0eSlbMl1dKSkNCmNvbG5hbWVzKGRmX3QpID0gY29uZGl0aW9uYWxfZGF0YXNldF9jaXR5JGNpdHkNCmRhdGF0YWJsZShkZl90LCBvcHRpb25zID0gbGlzdChwYWdlTGVuZ3RoID0gMjEpLCBjYXB0aW9uPSJTdGF0aXN0aWNhbCBhbmFseXNpcyBvZiB0aGUgZGF0YXNldCBiYXNlZCBvbiBjaXR5IikNCg0KDQoNCg0KDQpjb25kaXRpb25hbF9kYXRhc2V0X3llYXIgPC0gZGF0YXNldCAlPiUgDQogIGdyb3VwX2J5KHllYXIpICU+JSANCiAgc3VtbWFyaXNlKG1lYW5fc2FsZXMgPSByb3VuZChtZWFuKHNhbGVzKSwyKSwNCiAgICAgICAgICAgIHNkX3NhbGVzID0gcm91bmQoc2Qoc2FsZXMpLDIpLA0KICAgICAgICAgICAgY3Zfc2FsZXMgPSByb3VuZChjdl9mdW5jdChzYWxlcyksIDIpLA0KICANCiAgICAgICAgICAgIG1lYW5fdm9sdW1lPXJvdW5kKG1lYW4odm9sdW1lKSwyKSwNCiAgICAgICAgICAgIHNkX3ZvbHVtZT1yb3VuZChzZCh2b2x1bWUpLDIpLA0KICAgICAgICAgICAgY3Zfdm9sdW1lID0gcm91bmQoY3ZfZnVuY3Qodm9sdW1lKSwgMiksDQogICAgICAgICAgICANCiAgICAgICAgICAgIG1lYW5fbWVkX3ByaWNlPXJvdW5kKG1lYW4obWVkaWFuX3ByaWNlKSwyKSwNCiAgICAgICAgICAgIHNkX21lZF9wcmljZT1yb3VuZChzZChtZWRpYW5fcHJpY2UpLDIpLA0KICAgICAgICAgICAgY3ZfbWVkX3ByaWNlID0gcm91bmQoY3ZfZnVuY3QobWVkaWFuX3ByaWNlKSwgMiksDQogICAgICAgICAgICANCiAgICAgICAgICAgIG1lYW5fbWVhbl9wcmljZT1yb3VuZChtZWFuKG1lYW5fcHJpY2UpLDIpLA0KICAgICAgICAgICAgc2RfbWVhbl9wcmljZT1yb3VuZChzZChtZWFuX3ByaWNlKSwyKSwNCiAgICAgICAgICAgIGN2X21lYW5fcHJpY2UgPSByb3VuZChjdl9mdW5jdChtZWFuX3ByaWNlKSwgMiksDQogICAgICAgICAgICANCiAgICAgICAgICAgIG1lYW5fbGlzdGluZ3M9cm91bmQobWVhbihsaXN0aW5ncyksMiksDQogICAgICAgICAgICBzZF9saXN0aW5ncz1yb3VuZChzZChsaXN0aW5ncyksMiksDQogICAgICAgICAgICBjdl9saXN0aW5ncyA9IHJvdW5kKGN2X2Z1bmN0KGxpc3RpbmdzKSwgMiksDQogIA0KICAgICAgICAgICAgbWVhbl9pbnZlbnRvcnk9cm91bmQobWVhbihtb250aHNfaW52ZW50b3J5KSwyKSwNCiAgICAgICAgICAgIHNkX2ludmVudG9yeT1yb3VuZChzZChtb250aHNfaW52ZW50b3J5KSwyKSwNCiAgICAgICAgICAgIGN2X2ludmVudG9yeSA9IHJvdW5kKGN2X2Z1bmN0KG1vbnRoc19pbnZlbnRvcnkpLCAyKSwNCiAgICAgICAgICAgIA0KICAgICAgICAgICAgbWVhbl9lZmZlY3Rpdm5lc3M9cm91bmQobWVhbihlZmZlY3RpdmVuZXNzKSwyKSwNCiAgICAgICAgICAgIHNkX2VmZmVjdGl2ZW5lc3M9cm91bmQoc2QoZWZmZWN0aXZlbmVzcyksMiksDQogICAgICAgICAgICBjdl9lZmZlY3RpdmVuZXNzID0gcm91bmQoY3ZfZnVuY3QoZWZmZWN0aXZlbmVzcyksIDIpLA0KICAgICAgICAgICAgKQ0KDQoNCmRmX3QgPC0gYXMuZGF0YS5mcmFtZSh0KGNvbmRpdGlvbmFsX2RhdGFzZXRfeWVhclsyOmRpbShjb25kaXRpb25hbF9kYXRhc2V0X3llYXIpWzJdXSkpDQpjb2xuYW1lcyhkZl90KSA9IGNvbmRpdGlvbmFsX2RhdGFzZXRfeWVhciR5ZWFyDQpkYXRhdGFibGUoZGZfdCwgb3B0aW9ucyA9IGxpc3QocGFnZUxlbmd0aCA9IDIxKSwgY2FwdGlvbj0iU3RhdGlzdGljYWwgYW5hbHlzaXMgb2YgdGhlIGRhdGFzZXQgYmFzZWQgb24geWVhciIpDQoNCg0KYGBgDQoNCg0KDQoNCmBgYHtyLCBmaWcud2lkdGg9MTMsIGZpZy5oZWlnaHQ9NX0NCg0KIyBXZSBjcmVhdGUgYSBkYXRhc2V0IHdoZXJlIHdlIGNvbmR1Y3QgYSBzdGF0aXN0aWNhbCBhbmFseXNpcyBjb25kaXRpb25lZCBib3RoIHRvIGNpdHkgYW5kIHllYXIsIHNvIHZhcnlpbmcgb25seSB0aGUgbW9udGhzLCBmb3IgZWFjaCBjb3VwbGUgKGNpdHkseWVhcikgd2UgY29tcHV0ZSB0aGUgdG90YWwgYW1vdW50IG9mIHNhbGVzIHZvbHVtZSBhbmQgbGlzdGluZ3MgYW5kIHRoZSBtZWRpYW4gbW9udGhzX2ludmVudG9yeSwgbWVkaWFuIHByaWNlIGFuZCBlZmZlY3RpdmVuZXNzIHZhcnlpbmcgdGhlIG1vbnRocw0KDQpjb25kaXRpb25hbF9kYXRhc2V0X2NpdHlfeWVhciA8LSBkYXRhc2V0ICU+JSANCiAgZ3JvdXBfYnkoeWVhciwgY2l0eSkgJT4lIA0KICBzdW1tYXJpc2Uoc2FsZXMgPSBzdW0oc2FsZXMpLA0KICAgICAgICAgICAgdm9sdW1lID0gc3VtKHZvbHVtZSksDQogICAgICAgICAgICBsaXN0aW5ncyA9IHN1bShsaXN0aW5ncyksDQogICAgICAgICAgICBtZWRpYW5fbW9udGhzX2ludmVudG9yeT1tZWRpYW4obW9udGhzX2ludmVudG9yeSksDQogICAgICAgICAgICBtZWRpYW5fbWVkaWFuX3ByaWNlPW1lZGlhbihtZWRpYW5fcHJpY2UpLA0KICAgICAgICAgICAgbWVkaWFuX2VmZmVjdGl2ZW5lc3M9bWVkaWFuKGVmZmVjdGl2ZW5lc3MpDQogICAgICAgICAgICApDQoNCg0KDQpiYXJfc2FsZXNfeWVhciA8LSAgZ2dwbG90KGRhdGE9Y29uZGl0aW9uYWxfZGF0YXNldF9jaXR5X3llYXIsIA0KICAgICAgICAgICAgICAgICAgICAgICAgYWVzKHg9eWVhciwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICB5PXNhbGVzLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZpbGw9Y2l0eSkpKw0KICAgICAgICAgICAgICAgICAgZ2VvbV9jb2woc3RhdD0iaWRlbnRpdHkiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgcG9zaXRpb249InN0YWNrIikrDQogICAgICAgICAgICAgICAgICB0aGVtZShsZWdlbmQudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE2KSwNCiAgICAgICAgICAgICAgICAgICAgICAgIGxlZ2VuZC50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNCkpDQoNCmxlZ2VuZF9jaXR5IDwtIGFzX2dncGxvdChnZXRfbGVnZW5kKGJhcl9zYWxlc195ZWFyKSkNCg0KDQoNCg0KYmFyX3NhbGVzX3llYXIgPC0gIGdncGxvdChkYXRhPWNvbmRpdGlvbmFsX2RhdGFzZXRfY2l0eV95ZWFyLA0KICAgICAgICAgICAgICAgICAgICAgICAgYWVzKHg9eWVhciwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICB5PXNhbGVzLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZpbGw9Y2l0eSkpKw0KICAgICAgICAgICAgICAgICAgZ2VvbV9jb2woc3RhdD0iaWRlbnRpdHkiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgcG9zaXRpb249ICJkb2RnZSIpKw0KICAgICAgICAgICAgICAgICAgbGFicyh0aXRsZT0iQ29tcGFyaXNvbiBvZiB0b3RhbCBzYWxlcyBieSB5ZWFyIG92ZXIgY2l0eSIsDQogICAgICAgICAgICAgICAgICAgICAgIHg9InllYXIiLA0KICAgICAgICAgICAgICAgICAgICAgICB5PSJzYWxlcyIpKw0KICAgICAgICAgICAgICAgICAgdGhlbWVfY2xhc3NpYygpKw0KICAgICAgICAgICAgICAgICAgdGhlbWUocGxvdC50aXRsZS5wb3NpdGlvbiA9ICJwYW5lbCIsDQogICAgICAgICAgICAgICAgICAgICAgICBwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemU9MTYsIGhqdXN0PTAuNSksDQogICAgICAgICAgICAgICAgICAgICAgICBheGlzLnRpdGxlLnggPSBlbGVtZW50X3RleHQoc2l6ZT0xNCksDQogICAgICAgICAgICAgICAgICAgICAgICBheGlzLnRpdGxlLnkgPSBlbGVtZW50X3RleHQoc2l6ZT0xNCksDQogICAgICAgICAgICAgICAgICAgICAgICBheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChzaXplPTEwKSwNCiAgICAgICAgICAgICAgICAgICAgICAgIGF4aXMudGV4dC55ID0gZWxlbWVudF90ZXh0KHNpemU9MTApLA0KICAgICAgICAgICAgICAgICAgICAgICAgbGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKSsNCiAgICAgICAgICAgICAgICAgICAgICAgIHNjYWxlX3lfY29udGludW91cyhicmVha3MgPSBzZXEoMCwgNDAwMCwgYnkgPSAyNTApKQ0KDQoNCmJhcl92b2x1bWVfeWVhciA8LSBnZ3Bsb3QoZGF0YT1jb25kaXRpb25hbF9kYXRhc2V0X2NpdHlfeWVhciwNCiAgICAgICAgICAgICAgICAgICAgICAgICBhZXMoeD15ZWFyLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICB5PXZvbHVtZSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmlsbD1jaXR5KSkrDQogICAgICAgICAgICAgICAgICBnZW9tX2NvbChzdGF0PSJpZGVudGl0eSIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICBwb3NpdGlvbj0iZG9kZ2UiKSsNCiAgICAgICAgICAgICAgICAgIGxhYnModGl0bGU9IkNvbXBhcmlzb24gb2YgdG90YWwgdm9sdW1lIGJ5IHllYXIgb3ZlciBjaXR5IiwNCiAgICAgICAgICAgICAgICAgICAgICAgeD0ieWVhciIsDQogICAgICAgICAgICAgICAgICAgICAgIHk9InZvbHVtZSIpKw0KICAgICAgICAgICAgICAgICAgdGhlbWVfY2xhc3NpYygpKw0KICAgICAgICAgICAgICAgICAgdGhlbWUocGxvdC50aXRsZS5wb3NpdGlvbiA9ICJwYW5lbCIsDQogICAgICAgICAgICAgICAgICAgICAgICBwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemU9MTYsIGhqdXN0PTAuNSksDQogICAgICAgICAgICAgICAgICAgICAgICBheGlzLnRpdGxlLnggPSBlbGVtZW50X3RleHQoc2l6ZT0xNCksDQogICAgICAgICAgICAgICAgICAgICAgICBheGlzLnRpdGxlLnkgPSBlbGVtZW50X3RleHQoc2l6ZT0xNCksDQogICAgICAgICAgICAgICAgICAgICAgICBheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChzaXplPTEwKSwNCiAgICAgICAgICAgICAgICAgICAgICAgIGF4aXMudGV4dC55ID0gZWxlbWVudF90ZXh0KHNpemU9MTApLA0KICAgICAgICAgICAgICAgICAgICAgICAgbGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKSsNCiAgICAgICAgICAgICAgICAgICAgICAgIHNjYWxlX3lfY29udGludW91cyhicmVha3MgPSBzZXEoMCwgNzAwLCBieSA9IDUwKSkNCg0KDQoNCg0KDQoNCg0KYmFyX3NhbGVzX3llYXJfMiA8LSAgZ2dwbG90KGRhdGE9Y29uZGl0aW9uYWxfZGF0YXNldF9jaXR5X3llYXIsDQogICAgICAgICAgICAgICAgICAgICAgICBhZXMoeD15ZWFyLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIHk9c2FsZXMsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgZmlsbD1jaXR5KSkrDQogICAgICAgICAgICAgICAgICBnZW9tX2NvbChzdGF0PSJpZGVudGl0eSIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICBwb3NpdGlvbj0gImZpbGwiKSsNCiAgICAgICAgICAgICAgICAgIGxhYnModGl0bGU9IkNvbXBhcmlzb24gb2YgdG90YWwgc2FsZXMgYnkgeWVhciBvdmVyIGNpdHkiLA0KICAgICAgICAgICAgICAgICAgICAgICB4PSJ5ZWFyIiwNCiAgICAgICAgICAgICAgICAgICAgICAgeT0ic2FsZXMiKSsNCiAgICAgICAgICAgICAgICAgIHRoZW1lX2NsYXNzaWMoKSsNCiAgICAgICAgICAgICAgICAgIHRoZW1lKHBsb3QudGl0bGUucG9zaXRpb24gPSAicGFuZWwiLA0KICAgICAgICAgICAgICAgICAgICAgICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplPTE2LCBoanVzdD0wLjUpLA0KICAgICAgICAgICAgICAgICAgICAgICAgYXhpcy50aXRsZS54ID0gZWxlbWVudF90ZXh0KHNpemU9MTQpLA0KICAgICAgICAgICAgICAgICAgICAgICAgYXhpcy50aXRsZS55ID0gZWxlbWVudF90ZXh0KHNpemU9MTQpLA0KICAgICAgICAgICAgICAgICAgICAgICAgYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoc2l6ZT0xMCksDQogICAgICAgICAgICAgICAgICAgICAgICBheGlzLnRleHQueSA9IGVsZW1lbnRfdGV4dChzaXplPTEwKSwNCiAgICAgICAgICAgICAgICAgICAgICAgIGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikrDQogICAgICAgICAgICAgICAgICAgICAgICBzY2FsZV95X2NvbnRpbnVvdXMobGFiZWxzID0gcGVyY2VudF9mb3JtYXQoKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVha3MgPSBzZXEoMCwgMSwgYnkgPSAwLjEpKSANCg0KDQpiYXJfdm9sdW1lX3llYXJfMiA8LSBnZ3Bsb3QoZGF0YT1jb25kaXRpb25hbF9kYXRhc2V0X2NpdHlfeWVhciwNCiAgICAgICAgICAgICAgICAgICAgICAgICBhZXMoeD15ZWFyLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICB5PXZvbHVtZSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmlsbD1jaXR5KSkrDQogICAgICAgICAgICAgICAgICBnZW9tX2NvbChzdGF0PSJpZGVudGl0eSIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICBwb3NpdGlvbj0iZmlsbCIpKw0KICAgICAgICAgICAgICAgICAgbGFicyh0aXRsZT0iQ29tcGFyaXNvbiBvZiB0b3RhbCB2b2x1bWUgYnkgeWVhciBvdmVyIGNpdHkiLA0KICAgICAgICAgICAgICAgICAgICAgICB4PSJ5ZWFyIiwNCiAgICAgICAgICAgICAgICAgICAgICAgeT0idm9sdW1lIikrDQogICAgICAgICAgICAgICAgICB0aGVtZV9jbGFzc2ljKCkrDQogICAgICAgICAgICAgICAgICB0aGVtZShwbG90LnRpdGxlLnBvc2l0aW9uID0gInBhbmVsIiwNCiAgICAgICAgICAgICAgICAgICAgICAgIHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZT0xNiwgaGp1c3Q9MC41KSwNCiAgICAgICAgICAgICAgICAgICAgICAgIGF4aXMudGl0bGUueCA9IGVsZW1lbnRfdGV4dChzaXplPTE0KSwNCiAgICAgICAgICAgICAgICAgICAgICAgIGF4aXMudGl0bGUueSA9IGVsZW1lbnRfdGV4dChzaXplPTE0KSwNCiAgICAgICAgICAgICAgICAgICAgICAgIGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KHNpemU9MTApLA0KICAgICAgICAgICAgICAgICAgICAgICAgYXhpcy50ZXh0LnkgPSBlbGVtZW50X3RleHQoc2l6ZT0xMCksDQogICAgICAgICAgICAgICAgICAgICAgICBsZWdlbmQucG9zaXRpb24gPSAibm9uZSIpKw0KICAgICAgICAgICAgICAgICAgICAgICAgc2NhbGVfeV9jb250aW51b3VzKGxhYmVscyA9IHBlcmNlbnRfZm9ybWF0KCksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWtzID0gc2VxKDAsIDEsIGJ5ID0gMC4xKSkgDQoNCg0KDQoNCg0KDQoNCg0KDQoNCg0KDQoNCg0KYmFyX2xpc3RpbmdzX2NpdHkgPC0gZ2dwbG90KGRhdGE9Y29uZGl0aW9uYWxfZGF0YXNldF9jaXR5X3llYXIsIA0KICAgICAgICAgICAgICAgICAgICAgIGFlcyh4PWNpdHksDQogICAgICAgICAgICAgICAgICAgICAgICAgIHk9bGlzdGluZ3MsDQogICAgICAgICAgICAgICAgICAgICAgICAgIGZpbGw9eWVhcikpKw0KICAgICAgICAgICAgICAgICAgICBnZW9tX2NvbChzdGF0PSJpZGVudGl0eSIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBvc2l0aW9uPSAiZG9kZ2UiKSsNCiAgICAgICAgICAgICAgICAgICAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gYygiMjAxMCIgPSAibGlnaHRibHVlMSIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIjIwMTEiID0gImxpZ2h0Ymx1ZTIiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICIyMDEyIiA9ICJsaWdodGJsdWUzIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiMjAxMyIgPSAibGlnaHRibHVlNCIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIjIwMTQiID0gIiMzNzRBNTkiDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKSkNCg0KbGVnZW5kX3llYXIgPC0gYXNfZ2dwbG90KGdldF9sZWdlbmQoYmFyX2xpc3RpbmdzX2NpdHkpKQ0KDQoNCg0KYmFyX2xpc3RpbmdzX2NpdHkgPC0gZ2dwbG90KGRhdGE9Y29uZGl0aW9uYWxfZGF0YXNldF9jaXR5X3llYXIsIA0KICAgICAgICAgICAgICAgICAgICAgIGFlcyh4PWNpdHksDQogICAgICAgICAgICAgICAgICAgICAgICAgIHk9bGlzdGluZ3MsDQogICAgICAgICAgICAgICAgICAgICAgICAgIGZpbGw9eWVhcikpKw0KICAgICAgICAgICAgICAgICAgICBnZW9tX2NvbChzdGF0PSJpZGVudGl0eSIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBvc2l0aW9uPSAiZG9kZ2UiKSsNCiAgICAgICAgICAgICAgICAgICAgbGFicyh0aXRsZT0iQ29tcGFyaXNvbiBvZiB0b3RhbCBsaXN0aW5ncyBieSBjaXR5IG92ZXIgeWVhciIsDQogICAgICAgICAgICAgICAgICAgICAgICAgeD0iY2l0eSIsDQogICAgICAgICAgICAgICAgICAgICAgICAgeT0ibGlzdGluZ3MiKSsNCiAgICAgICAgICAgICAgICAgICAgdGhlbWVfY2xhc3NpYygpKw0KICAgICAgICAgICAgICAgICAgICB0aGVtZShwbG90LnRpdGxlLnBvc2l0aW9uID0gInBhbmVsIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplPTE2LCBoanVzdD0wLjUpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICBheGlzLnRpdGxlLnggPSBlbGVtZW50X3RleHQoc2l6ZT0xNCksDQogICAgICAgICAgICAgICAgICAgICAgICAgIGF4aXMudGl0bGUueSA9IGVsZW1lbnRfdGV4dChzaXplPTE0KSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoc2l6ZT0xMCksDQogICAgICAgICAgICAgICAgICAgICAgICAgIGF4aXMudGV4dC55ID0gZWxlbWVudF90ZXh0KHNpemU9MTApLA0KICAgICAgICAgICAgICAgICAgICAgICAgICBsZWdlbmQucG9zaXRpb24gPSAibm9uZSIpKw0KICAgICAgICAgICAgICAgICAgICAgICAgICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBjKCIyMDEwIiA9ICJsaWdodGJsdWUxIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiMjAxMSIgPSAibGlnaHRibHVlMiIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIjIwMTIiID0gImxpZ2h0Ymx1ZTMiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICIyMDEzIiA9ICJsaWdodGJsdWU0IiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiMjAxNCIgPSAiIzM3NEE1OSINCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApKSsNCiAgICAgICAgICAgICAgICAgICAgICAgICAgc2NhbGVfeV9jb250aW51b3VzKGJyZWFrcyA9IHNlcSgwLCAzNTAwMCwgYnkgPSAyNTAwKSkNCg0KDQpib3hfaW52ZW50b3J5X2NpdHkgPC0gZ2dwbG90KGRhdGE9ZGF0YXNldCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBhZXMoeD1jaXR5LA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB5PW1vbnRoc19pbnZlbnRvcnksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZpbGw9eWVhcikpKw0KICAgICAgICAgICAgICAgICAgICAgZ2VvbV9ib3hwbG90KCkrDQogICAgICAgICAgICAgICAgICAgICBsYWJzKHRpdGxlPSJDb21wYXJpc29uIG9mIG1vbnRocyBpbnZlbnRvcnkgYnkgY2l0eSBvdmVyIHllYXIiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICB4PSJjaXR5IiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgeT0ibW9udGhzX2ludmVudG9yeSIpKw0KICAgICAgICAgICAgICAgICAgICAgdGhlbWVfY2xhc3NpYygpKw0KICAgICAgICAgICAgICAgICAgICAgdGhlbWUocGxvdC50aXRsZS5wb3NpdGlvbiA9ICJwYW5lbCIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICBwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemU9MTYsIGhqdXN0PTAuNSksDQogICAgICAgICAgICAgICAgICAgICAgICAgICBheGlzLnRpdGxlLnggPSBlbGVtZW50X3RleHQoc2l6ZT0xNCksDQogICAgICAgICAgICAgICAgICAgICAgICAgICBheGlzLnRpdGxlLnkgPSBlbGVtZW50X3RleHQoc2l6ZT0xNCksDQogICAgICAgICAgICAgICAgICAgICAgICAgICBheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChzaXplPTEwKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgIGF4aXMudGV4dC55ID0gZWxlbWVudF90ZXh0KHNpemU9MTApLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgbGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKSsNCiAgICAgICAgICAgICAgICAgICAgICAgICAgIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IGMoIjIwMTAiID0gImxpZ2h0Ymx1ZTEiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiMjAxMSIgPSAibGlnaHRibHVlMiIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICIyMDEyIiA9ICJsaWdodGJsdWUzIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIjIwMTMiID0gImxpZ2h0Ymx1ZTQiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiMjAxNCIgPSAiIzM3NEE1OSINCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKSkrDQogICAgICAgICAgICAgICAgICAgICAgICAgIHNjYWxlX3lfY29udGludW91cyhicmVha3MgPSBzZXEoNCwgMTQsIGJ5ID0gMikpDQoNCg0KDQpib3hfcHJpY2VfeWVhciA8LSBnZ3Bsb3QoKSsNCiAgICAgICAgICAgICAgICAgICAgZ2VvbV9saW5lKGRhdGEgPSBjb25kaXRpb25hbF9kYXRhc2V0X2NpdHlfeWVhciwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFlcyh4ID0geWVhciwgeSA9IG1lZGlhbl9tZWRpYW5fcHJpY2UsIGdyb3VwID0gY2l0eSwgY29sb3IgPSBjaXR5KSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBvc2l0aW9uID0gcG9zaXRpb25fZG9kZ2Uod2lkdGggPSAwLjc1KSkgKw0KICAgICAgICAgICAgICAgICAgICBnZW9tX2JveHBsb3QoZGF0YT1kYXRhc2V0LCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFlcyh4PXllYXIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgeT1tZWRpYW5fcHJpY2UsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmlsbD1jaXR5KSkrDQogICAgICAgICAgICAgICAgICAgIGxhYnModGl0bGU9IkNvbXBhcmlzb24gb2YgbWVkaWFuIHByaWNlIGJ5IHllYXIgb3ZlciBjaXR5IiwNCiAgICAgICAgICAgICAgICAgICAgICAgICB4PSJ5ZWFyIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICB5PSJtZWRpYW4gcHJpY2UiKSsNCiAgICAgICAgICAgICAgICAgICAgdGhlbWVfY2xhc3NpYygpKw0KICAgICAgICAgICAgICAgICAgICB0aGVtZShwbG90LnRpdGxlLnBvc2l0aW9uID0gInBhbmVsIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplPTE2LCBoanVzdD0wLjUpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICBheGlzLnRpdGxlLnggPSBlbGVtZW50X3RleHQoc2l6ZT0xNCksDQogICAgICAgICAgICAgICAgICAgICAgICAgIGF4aXMudGl0bGUueSA9IGVsZW1lbnRfdGV4dChzaXplPTE0KSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoc2l6ZT0xMCksDQogICAgICAgICAgICAgICAgICAgICAgICAgIGF4aXMudGV4dC55ID0gZWxlbWVudF90ZXh0KHNpemU9MTApLA0KICAgICAgICAgICAgICAgICAgICAgICAgICBsZWdlbmQucG9zaXRpb24gPSAibm9uZSIpKw0KICAgICAgICAgICAgICAgICAgICAgICAgICBzY2FsZV95X2NvbnRpbnVvdXMoYnJlYWtzID0gc2VxKDc1MDAwLCAxNzUwMDAsIGJ5ID0gMTAwMDApKQ0KDQoNCmJveF9lZmZlY3RpdmVuZXNzX3llYXIgPC0gZ2dwbG90KCkrDQogICAgICAgICAgICAgICAgICAgIGdlb21fbGluZShkYXRhID0gY29uZGl0aW9uYWxfZGF0YXNldF9jaXR5X3llYXIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhZXMoeCA9IHllYXIsIHkgPSBtZWRpYW5fZWZmZWN0aXZlbmVzcywgZ3JvdXAgPSBjaXR5LCBjb2xvciA9IGNpdHkpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcG9zaXRpb24gPSBwb3NpdGlvbl9kb2RnZSh3aWR0aCA9IDAuNzUpKSArDQogICAgICAgICAgICAgICAgICAgIGdlb21fYm94cGxvdChkYXRhPWRhdGFzZXQsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhZXMoeD15ZWFyLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHk9ZWZmZWN0aXZlbmVzcywNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmaWxsPWNpdHkpKSsNCiAgICAgICAgICAgICAgICAgICAgbGFicyh0aXRsZT0iQ29tcGFyaXNvbiBvZiBlZmZlY3RpdmVuZXNzIGJ5IHllYXIgb3ZlciBjaXR5IiwNCiAgICAgICAgICAgICAgICAgICAgICAgICB4PSJ5ZWFyIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICB5PSJlZmZlY3RpdmVuZXNzIikrDQogICAgICAgICAgICAgICAgICAgIHRoZW1lX2NsYXNzaWMoKSsNCiAgICAgICAgICAgICAgICAgICAgdGhlbWUocGxvdC50aXRsZS5wb3NpdGlvbiA9ICJwYW5lbCIsDQogICAgICAgICAgICAgICAgICAgICAgICAgIHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZT0xNiwgaGp1c3Q9MC41KSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgYXhpcy50aXRsZS54ID0gZWxlbWVudF90ZXh0KHNpemU9MTQpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICBheGlzLnRpdGxlLnkgPSBlbGVtZW50X3RleHQoc2l6ZT0xNCksDQogICAgICAgICAgICAgICAgICAgICAgICAgIGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KHNpemU9MTApLA0KICAgICAgICAgICAgICAgICAgICAgICAgICBheGlzLnRleHQueSA9IGVsZW1lbnRfdGV4dChzaXplPTEwKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgbGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKSsNCiAgICAgICAgICAgICAgICAgICAgICAgICAgc2NhbGVfeV9jb250aW51b3VzKGJyZWFrcyA9IHNlcSgwLCAzNTAsIGJ5ID0gMjUpKSANCg0KICANCg0KDQpjb21iX2ZpZ18yIDwtIGJhcl9zYWxlc195ZWFyICsgYmFyX3ZvbHVtZV95ZWFyICsgbGVnZW5kX2NpdHkgKyBwbG90X2xheW91dChuY29sPTMsIHdpZHRocyA9IGMoNSwgNSwgMyksIGhlaWdodHMgPSBjKDUpKQ0KcHJpbnQoY29tYl9maWdfMikNCg0KDQpjb21iX2ZpZ18yXzUgPC0gYmFyX3NhbGVzX3llYXJfMiArIGJhcl92b2x1bWVfeWVhcl8yICsgbGVnZW5kX2NpdHkgKyBwbG90X2xheW91dChuY29sPTMsIHdpZHRocyA9IGMoNSwgNSwgMyksIGhlaWdodHMgPSBjKDUpKQ0KcHJpbnQoY29tYl9maWdfMl81KQ0KDQoNCmNvbWJfZmlnXzMgPC0gYmFyX2xpc3RpbmdzX2NpdHkgKyBib3hfaW52ZW50b3J5X2NpdHkgKyBsZWdlbmRfeWVhciArIHBsb3RfbGF5b3V0KG5jb2w9Mywgd2lkdGhzID0gYyg1LCA1LCAxKSwgaGVpZ2h0cyA9IGMoNSkpDQpwcmludChjb21iX2ZpZ18zKQ0KDQpjb21iX2ZpZ180IDwtIGJveF9wcmljZV95ZWFyICsgYm94X2VmZmVjdGl2ZW5lc3NfeWVhciArIGxlZ2VuZF9jaXR5ICsgcGxvdF9sYXlvdXQobmNvbD0zLCB3aWR0aHMgPSBjKDUsIDUsIDMpLCBoZWlnaHRzID0gYyg1KSkNCnByaW50KGNvbWJfZmlnXzQpDQoNCg0Kcm0oYmFyX3NhbGVzX3llYXIsIGJhcl92b2x1bWVfeWVhciwgbGVnZW5kX2NpdHksIGJhcl9saXN0aW5nc19jaXR5LCBib3hfaW52ZW50b3J5X2NpdHksIGxlZ2VuZF95ZWFyLCBib3hfcHJpY2VfeWVhciwgYm94X2VmZmVjdGl2ZW5lc3NfeWVhciwgYmFyX3NhbGVzX3llYXJfMiwgYmFyX3ZvbHVtZV95ZWFyXzIsIGNvbWJfZmlnXzIsIGNvbWJfZmlnXzJfNSwgY29tYl9maWdfMywgY29tYl9maWdfNCkNCmBgYA0KDQoNCg0KRnJvbSB0aGUgcmVzdWx0cyBhYm92ZSB3ZSBvYnNlcnZlIHRoYXQgVHlsZXIgaXMgdGhlIGNpdHkgd2l0aCBtb3JlIHNhbGVzIGFuZCB2b2x1bWUgYXMgYWxzbyB0aGUgY2l0eSB3aGVyZSB0aGUgc2FsZXMgYWRzIGFyZSBtb3JlIGVmZmljaWVudCBmb2xsb3dlZCBieSBCcmlhbi1Db2xsZWdlIFN0YXRpb24sIEJlYXVtb250IGFuZCBXaWNoaXRhIEZhbGxzIGluIGRlc2NlbmRpbmcgb3JkZXIuIERpZmZlcmVudGx5LCB0aGUgbWVkaWFuIHByaWNlIGlzIGhpZ2hlciBpbiBCcmlhbi1Db2xsZWdlIFN0YXRpb24gZm9sbG93ZWQgYnkgVHlsZXIgYW5kIEJlYXVtb250IGFuZCBmaW5hbGx5IGJ5IFdpY2hpdGEgRmFsbHMuIFR5bGVyIGlzIGFsc28gY2l0eSB3aXRoIHRoZSBoaWdoZXN0IG51bWJlciBvZiBsaXN0aW5ncyBhbmQgbW9udGhzIGludmVudG9yeSBmb2xsb3dlZCBieSBCZWF1bW9udCwgQnJ5YW4tQ29sbGVnZSBTdGF0aW9uIGFuZCBXaWNoaXRhIEZhbGxzLiANCg0KQWJvdXQgdGhlIHZhcmlhYmlsaXR5IG9mIHRoZSB2YXJpYWJsZXMgd2Ugb2JzZXJ2ZSB0aGF0IHRoZSByZWxhdGl2ZSB2YXJpYWJpbGl0eSAobWVhc3VyZWQgaW4gdGVybXMgb2YgdGhlIGNvZWZmaWNpZW50IG9mIHZhcmlhdGlvbikgaW4gdGhlIHZvbHVtZSBhbmQgc2FsZXMgaW4gVHlsZXIgaXMgYmV0d2VlbiAxLjUgYW5kIDMgdGltZXMgaGlnaGVyIHRoYW4gdGhlIHZhcmlhYmlsaXR5IHRoYXQgd2Ugb2JzZXJ2ZSBpbiB0aGUgb3RoZXIgY2l0aWVzLiBTaW1pbGFybHkgQnJ5YW4tQ29sbGVnZSBTdGF0aW9uIGZhY2VzIGEgdmFyaWFiaWxpdHkgaW4gdGhlIGxpc3RpbmdzIGFuZCBtb250aCBpbnZlbnRvcnkgdGhhdCBpcyBhbG1vc3QgdHdpY2Ugb3IgbW9yZSB0aGUgdmFyaWFiaWxpdHkgaW4gdGhlIG90aGVyIGNpdGllcy4gRmluYWxseSBXaWNoaXRhIEZhbGxzIGlzIHRoZSBjaXR5IHdpdGggdGhlIGhpZ2hlc3QgdmFyaWFiaWxpdHkgaW4gdGhlIG1lZGlhbiBhbmQgbWVhbiBwcmljZXMuIEhvd2V2ZXIgdGhlIHZhcmlhYmlsaXR5IGluIHRoZSBtZWRpYW4gcHJpY2VzIGlzIHF1aXRlIHNtYWxsIGZvciBhbGwgdGhlIGNpdGllcy4gDQoNClRoZSBncmFwaHMgYWxzbyBjb25maXJtIGEgY2hhbmdlIGluIHRoZSB0cmVuZCBvZiB0aGUgdmFyaWFibGVzIGFuZCBzbyBvZiB0aGUgcmVhbCBlc3RhdGUgbWFya2V0IGFmdGVyIDIwMTEuIE9uIHRoZSBvbmUgaGFuZCwgd2Ugb2JzZXJ2ZSBhbiBpbmNyZWFzZSBpbiB0aGUgbnVtYmVyIG9mIHNhbGVzLCB2b2x1bWUsIG1lZGlhbiBwcmljZSwgYW5kIGVmZmljaWVuY3k7IG9uIHRoZSBvdGhlciBoYW5kIHRoZSBudW1iZXIgb2YgbGlzdGluZ3MgYW5kIG1vbnRobHkgaW52ZW50b3J5IGRlY3JlYXNlcy4gVGhlIG9ubHkgY2l0eSB0aGF0IGRvZXNuJ3Qgc2VlbSB0byBmb2xsb3cgdGhlc2UgdHJlbmRzIGlzIFdpY2hpdGEgRmFsbHMsIHdoZXJlIHRoZSBzaXR1YXRpb24gZG9lc24ndCBzZWVtIHRvIGJlIGNoYW5naW5nIG92ZXIgdGhlIHllYXJzLiBXZSBkbyBub3Qgb2JzZXJ2ZSBzaWduaWZpY2FudCBkaWZmZXJlbmNlcyBpbiB0aGUgdmFyaWFiaWxpdHkgb2YgdGhlIHZhcmlhYmxlcyBvdmVyIHRoZSB5ZWFyLg0KDQoNCg0KIyMjIE5leHQgd2UgY29uZHVjdCBhIHN0YXRpc3RpY2FsIHN0dWR5IGFib3V0IHRoZSB2YXJpYWJpbGl0eSBhbmQgdHJlbmRzIG9mIHRoZSBkaWZmZXJlbnQgdmFyaWFibGVzIG92ZXIgdGhlIG1vbnRocy4NCg0KDQpgYGB7cn0NCiMgbmV4dCB3ZSBjb25kdWN0IGEgc3RhdGlzdGljYWwgYW5hbHlzaXMgY29uZGl0aW9uZWQgYm90aCB0byB0aGUgbW9udGhzDQpjb25kaXRpb25hbF9kYXRhc2V0X21vbnRoIDwtIA0KICBkYXRhc2V0ICU+JSANCiAgZ3JvdXBfYnkobW9udGgpICU+JSAgIA0KICAgc3VtbWFyaXNlKG1lYW5fc2FsZXMgPSByb3VuZChtZWFuKHNhbGVzKSwyKSwNCiAgICAgICAgICAgIHNkX3NhbGVzID0gcm91bmQoc2Qoc2FsZXMpLDIpLA0KICAgICAgICAgICAgY3Zfc2FsZXMgPSByb3VuZChjdl9mdW5jdChzYWxlcyksIDIpLA0KICANCiAgICAgICAgICAgIG1lYW5fdm9sdW1lPXJvdW5kKG1lYW4odm9sdW1lKSwyKSwNCiAgICAgICAgICAgIHNkX3ZvbHVtZT1yb3VuZChzZCh2b2x1bWUpLDIpLA0KICAgICAgICAgICAgY3Zfdm9sdW1lID0gcm91bmQoY3ZfZnVuY3Qodm9sdW1lKSwgMiksDQogICAgICAgICAgICANCiAgICAgICAgICAgIG1lYW5fbWVkX3ByaWNlPXJvdW5kKG1lYW4obWVkaWFuX3ByaWNlKSwyKSwNCiAgICAgICAgICAgIHNkX21lZF9wcmljZT1yb3VuZChzZChtZWRpYW5fcHJpY2UpLDIpLA0KICAgICAgICAgICAgY3ZfbWVkX3ByaWNlID0gcm91bmQoY3ZfZnVuY3QobWVkaWFuX3ByaWNlKSwgMiksDQogICAgICAgICAgICANCiAgICAgICAgICAgIG1lYW5fbWVhbl9wcmljZT1yb3VuZChtZWFuKG1lYW5fcHJpY2UpLDIpLA0KICAgICAgICAgICAgc2RfbWVhbl9wcmljZT1yb3VuZChzZChtZWFuX3ByaWNlKSwyKSwNCiAgICAgICAgICAgIGN2X21lYW5fcHJpY2UgPSByb3VuZChjdl9mdW5jdChtZWFuX3ByaWNlKSwgMiksDQogICAgICAgICAgICANCiAgICAgICAgICAgIG1lYW5fbGlzdGluZ3M9cm91bmQobWVhbihsaXN0aW5ncyksMiksDQogICAgICAgICAgICBzZF9saXN0aW5ncz1yb3VuZChzZChsaXN0aW5ncyksMiksDQogICAgICAgICAgICBjdl9saXN0aW5ncyA9IHJvdW5kKGN2X2Z1bmN0KGxpc3RpbmdzKSwgMiksDQogIA0KICAgICAgICAgICAgbWVhbl9pbnZlbnRvcnk9cm91bmQobWVhbihtb250aHNfaW52ZW50b3J5KSwyKSwNCiAgICAgICAgICAgIHNkX2ludmVudG9yeT1yb3VuZChzZChtb250aHNfaW52ZW50b3J5KSwyKSwNCiAgICAgICAgICAgIGN2X2ludmVudG9yeSA9IHJvdW5kKGN2X2Z1bmN0KG1vbnRoc19pbnZlbnRvcnkpLCAyKSwNCiAgICAgICAgICAgIA0KICAgICAgICAgICAgbWVhbl9lZmZlY3Rpdm5lc3M9cm91bmQobWVhbihlZmZlY3RpdmVuZXNzKSwyKSwNCiAgICAgICAgICAgIHNkX2VmZmVjdGl2ZW5lc3M9cm91bmQoc2QoZWZmZWN0aXZlbmVzcyksMiksDQogICAgICAgICAgICBjdl9lZmZlY3RpdmVuZXNzID0gcm91bmQoY3ZfZnVuY3QoZWZmZWN0aXZlbmVzcyksIDIpLA0KICAgICAgICAgICAgKSANCg0KDQoNCg0KZGZfdCA8LSBhcy5kYXRhLmZyYW1lKHQoY29uZGl0aW9uYWxfZGF0YXNldF9tb250aFsyOmRpbShjb25kaXRpb25hbF9kYXRhc2V0X21vbnRoKVsyXV0pKQ0KY29sbmFtZXMoZGZfdCkgPC0gYygiSmFuIiwgIkZlYiIsICJNYXIiLCAiQXByIiwgIk1heSIsICJKdW4iLCAiSnVsIiwgIkF1ZyIsICJTZXAiLCAiT2N0IiwgIk5vdiIsICJEZWMiKQ0KZGF0YXRhYmxlKGRmX3QsIG9wdGlvbnMgPSBsaXN0KHNjcm9sbFggPSBUUlVFLCBwYWdlTGVuZ3RoID0gMjEpLCBjYXB0aW9uPSJTdGF0aXN0aWNhbCBhbmFseXNpcyBvZiB0aGUgZGF0YXNldCBiYXNlZCBvbiBtb250aCIpDQoNCmBgYA0KDQpUaGUgdGFibGUgcmVmbGVjdCBhIHBlcmlvZGljIHRyZW5kIG9mIGFsbCB0aGUgdmFyaWFibGVzIGFsb25nIHRoZSB5ZWFyLCBoYXZpbmcgbW9yZSBzYWxlcywgdm9sdW1lIGFuZCBsaXN0aW5ncyBhbmQgaGlnaGVyIG1vbnRoIGludmVudG9yeSBkdXJpbmcgdGhlIHN1bW1lciB3aXRoIHJlc3BlY3QgdG8gdGhlIHdpbnRlci4gVGhlIHZhcmlhYmxlcyBlZmZlY3RpdmVuZXNzIGFuZCBtZWRpYW4vbWVhbiBwcmljZSBhcmUgdGhlIG9ubHkgb25lcyB0aGF0IHNlZW0gbm90IHRvIGJlIGFmZmVjdGVkIGJ5IHRoaXMgcGVyaW9kaWMgdHJlbmQuDQoNClRvIGJldHRlciBjYXB0dXJlIHRoZSB2YXJpYWJpbGl0eSBvZiB0aGUgdmFyaWFibGVzIG92ZXIgdGhlIG1vbnRocyB3ZSBzdHVkeSBob3cgZG8gdGhleSB2YXJ5IGluIHBlcmNlbnRhZ2Ugd2l0aCByZXNwZWN0IHRvIHRoZWlyIG1lYW4uDQoNCmBgYHtyfQ0KDQoNCiMgdGhlIGZ1bmN0aW9uIGZvcm1hdF9wZXJjZW50YWdlIHdyaXRlcyBpbiBwZXJjZW50YWdlIGZvcm1hdCB0aGUgdmFsdWVzIHRoYXQgd2UgcHJvdmlkZQ0KZm9ybWF0X3BlcmNlbnRhZ2UgPC0gZnVuY3Rpb24odmFsdWVzKSB7DQogIHBlcmNlbnRfdmFsdWVzIDwtIHJvdW5kKHZhbHVlcyAqIDEwMCwgMikNCiAgc2lnbl92YWx1ZXMgPC0gaWZlbHNlKHBlcmNlbnRfdmFsdWVzID4gMCwgcGFzdGUwKCIrIiwgcGVyY2VudF92YWx1ZXMpLCBhcy5jaGFyYWN0ZXIocGVyY2VudF92YWx1ZXMpKQ0KICBwYXN0ZTAoc2lnbl92YWx1ZXMsICIlIikNCn0NCg0KDQoNCiMgbmV4dCBhIGRhdGVzIGlzIGNyZWF0ZWQgd2hlcmUgd2UgcmVwb3J0IHRoZSBwZXJjZW50YWdlIHZhcmlhdGlvbiBvZiB0aGUgdmFyaWFibGVzIG92ZXIgdGhlIG1vbnRocyB3aXRoIHJlc3BlY3QgdG8gdGhlaXIgbWVhbg0KY29uZGl0aW9uYWxfZGF0YXNldF9tb250aF9wZXJjZW50YWdlcyA8LSBkYXRhLmZyYW1lKHNhbGVzID0gZm9ybWF0X3BlcmNlbnRhZ2UoKGNvbmRpdGlvbmFsX2RhdGFzZXRfbW9udGgkbWVhbl9zYWxlcy1zdGF0aXN0aWNzWyJzYWxlcyIsIm1lYW4iXSkgLyBzdGF0aXN0aWNzWyJzYWxlcyIsIm1lYW4iXSksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdm9sdW1lID0gZm9ybWF0X3BlcmNlbnRhZ2UoKGNvbmRpdGlvbmFsX2RhdGFzZXRfbW9udGgkbWVhbl92b2x1bWUtc3RhdGlzdGljc1sidm9sdW1lIiwibWVhbiJdKSAvIHN0YXRpc3RpY3NbInZvbHVtZSIsIm1lYW4iXSksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWVkaWFuX3ByaWNlID0gZm9ybWF0X3BlcmNlbnRhZ2UoKGNvbmRpdGlvbmFsX2RhdGFzZXRfbW9udGgkbWVhbl9tZWRfcHJpY2Utc3RhdGlzdGljc1sibWVkaWFuX3ByaWNlIiwibWVhbiJdKS8gc3RhdGlzdGljc1sibWVkaWFuX3ByaWNlIiwibWVhbiJdKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsaXN0aW5ncyA9IGZvcm1hdF9wZXJjZW50YWdlKChjb25kaXRpb25hbF9kYXRhc2V0X21vbnRoJG1lYW5fbGlzdGluZ3Mtc3RhdGlzdGljc1sibGlzdGluZ3MiLCJtZWFuIl0pIC8gc3RhdGlzdGljc1sibGlzdGluZ3MiLCJtZWFuIl0pLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1vbnRoX2ludmVudG9yeT1mb3JtYXRfcGVyY2VudGFnZSgoY29uZGl0aW9uYWxfZGF0YXNldF9tb250aCRtZWFuX2ludmVudG9yeS1zdGF0aXN0aWNzWyJtb250aHNfaW52ZW50b3J5IiwibWVhbiJdKS9zdGF0aXN0aWNzWyJtb250aHNfaW52ZW50b3J5IiwibWVhbiJdKQ0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICkgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgDQoNCg0Kcm93bmFtZXMoY29uZGl0aW9uYWxfZGF0YXNldF9tb250aF9wZXJjZW50YWdlcykgPC0gYygiSmFuIiwgIkZlYiIsICJNYXIiLCAiQXByIiwgIk1heSIsICJKdW4iLCAiSnVsIiwgIkF1ZyIsICJTZXAiLCAiT2N0IiwgIk5vdiIsICJEZWMiKQ0KZGF0YXRhYmxlKGNvbmRpdGlvbmFsX2RhdGFzZXRfbW9udGhfcGVyY2VudGFnZXMsIG9wdGlvbnMgPSBsaXN0KHNjcm9sbFggPSBUUlVFLCBwYWdlTGVuZ3RoID0gMjEpLCBjYXB0aW9uPSJWYXJpYXRpb24gb2YgdGhlIG1vbnRobHkgbWVhbiBvZiB0aGUgdmFyaWFibGVzIGNvbXBhcmVkIHRvIHRoZWlyIG1lYW4gdmFsdWUiKQ0KDQpgYGANCg0KPCEtLQ0KI2BgYHtyfQ0KDQojIA0KIyBzZWFzb24gPC0gIGZ1bmN0aW9uKHgpew0KIyAgIHg9YXMubnVtZXJpYyhhcy5jaGFyYWN0ZXIoeCkpDQojICAgaWYgKHggJWluJSBjKDEsMiwzKSl7DQojICAgICByZXR1cm4oIndpbnRlciIpfQ0KIyAgIGlmICh4ICVpbiUgYyg0LDUsNikpew0KIyAgICAgcmV0dXJuKCJzcHJpbmciKX0NCiMgICBpZiAoeCAlaW4lIGMoNyw4LDkpKXsNCiMgICAgIHJldHVybigic3VtbWVyIil9DQojICAgaWYgKHggJWluJSBjKDEwLDExLDEyKSl7DQojICAgICByZXR1cm4oImF1dHVtbiIpfQ0KIyB9DQojIA0KIyANCiMgZGF0YXNldCRzZWFzb24gPC0gc2FwcGx5KG1vbnRoLCBzZWFzb24pDQojIA0KDQotLT4NCg0KDQpGaW5hbGx5LCB3ZSBzdHVkeSB0aGUgdmFyaWFiaWxpdHkgb2YgdGhlIHNhbGVzLCB2b2x1bWUgYW5kIGxpc3RpbmdzIGJvdGggb3ZlciB0aGUgbW9udGhzIGFuZCBhY3Jvc3MgZGlmZmVyZW50IGNpdGllcy4gV2UgcHJlc2VudCB0aGUgcmVzdWx0cyB2aWEgYmFyIHBsb3RzLiANCg0KYGBge3J9DQojIGZpcnN0IHdlIGNyZWF0ZSBhIGRhdGFzZXQgd2hlcmUgd2UgY29uZHVjdCBhIHN0YXRpc3RpY2FsIGFuYWx5c2lzIGNvbmRpdGlvbmVkIGJvdGggdG8gY2l0eSBhbmQgbW9udGgsIHNvIHZhcnlpbmcgb25seSB0aGUgeWVhcg0KIyBmb3IgZWFjaCBjb3VwbGUgKGNpdHksbW9udGgpIHdlIGNvbXB1dGUgdGhlIHRvdGFsIGFtb3VudCBvZiBzYWxlcyB2b2x1bWUgYW5kIGxpc3RpbmdzIGFuZCB0aGUgbWVkaWFuIG1vbnRoc19pbnZlbnRvcnksIG1lZGlhbiBwcmljZSBhbmQgZWZmZWN0aXZlbmVzcyB2YXJ5aW5nIHRoZSB5ZWFycw0KY29uZGl0aW9uYWxfZGF0YXNldF9jaXR5X21vbnRoIDwtIGRhdGFzZXQgJT4lDQogIGdyb3VwX2J5KG1vbnRoLCBjaXR5KSAlPiUNCiAgc3VtbWFyaXNlKHNhbGVzID0gc3VtKHNhbGVzKSwNCiAgICAgICAgICAgIHZvbHVtZSA9IHN1bSh2b2x1bWUpLA0KICAgICAgICAgICAgbGlzdGluZ3MgPSBzdW0obGlzdGluZ3MpLA0KICAgICAgICAgICAgbWVkaWFuX21vbnRoc19pbnZlbnRvcnk9bWVkaWFuKG1vbnRoc19pbnZlbnRvcnkpLA0KICAgICAgICAgICAgbWVkaWFuX21lZGlhbl9wcmljZT1tZWRpYW4obWVkaWFuX3ByaWNlKSwNCiAgICAgICAgICAgIG1lZGlhbl9lZmZlY3RpdmVuZXNzPW1lZGlhbihlZmZlY3RpdmVuZXNzKQ0KICAgICAgICAgICAgKQ0KIyANCiMgDQojIGNvbmRpdGlvbmFsX2RhdGFzZXRfY2l0eV9tb250aCRzZWFzb24gPC0gc2FwcGx5KGNvbmRpdGlvbmFsX2RhdGFzZXRfY2l0eV9tb250aCRtb250aCwgc2Vhc29uKQ0KYGBgDQoNCg0KYGBge3IsIGZpZy53aWR0aD0xMCwgZmlnLmhlaWdodD0xNn0NCmJhcl9zYWxlc19tb250aCA9ICBnZ3Bsb3QoZGF0YT1jb25kaXRpb25hbF9kYXRhc2V0X2NpdHlfbW9udGgsDQogICAgICAgICAgICAgICAgICAgICAgICBhZXMoeD1tb250aCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICB5PXNhbGVzLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZpbGw9Y2l0eSkpKw0KICAgICAgICAgICAgICAgICAgZ2VvbV9jb2woc3RhdD0iaWRlbnRpdHkiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgcG9zaXRpb249ICJzdGFjayIpKw0KICAgICAgICAgICAgICAgICAgbGFicyh0aXRsZT0iQ29tcGFyaXNvbiBvZiB0b3RhbCBzYWxlcyBieSBtb250aCBvdmVyIGNpdHkiLA0KICAgICAgICAgICAgICAgICAgICAgICB4PSJtb250aCIsDQogICAgICAgICAgICAgICAgICAgICAgIHk9InNhbGVzIikrDQogICAgICAgICAgICAgICAgICB0aGVtZV9jbGFzc2ljKCkrDQogICAgICAgICAgICAgICAgICB0aGVtZShwbG90LnRpdGxlLnBvc2l0aW9uID0gInBhbmVsIiwNCiAgICAgICAgICAgICAgICAgICAgICAgIHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZT0xNCwgaGp1c3Q9MC41KSwNCiAgICAgICAgICAgICAgICAgICAgICAgIGF4aXMudGl0bGUueCA9IGVsZW1lbnRfdGV4dChzaXplPTEyKSwNCiAgICAgICAgICAgICAgICAgICAgICAgIGF4aXMudGl0bGUueSA9IGVsZW1lbnRfdGV4dChzaXplPTEyKSwNCiAgICAgICAgICAgICAgICAgICAgICAgIGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KHNpemU9MTApLA0KICAgICAgICAgICAgICAgICAgICAgICAgYXhpcy50ZXh0LnkgPSBlbGVtZW50X3RleHQoc2l6ZT0xMCksDQogICAgICAgICAgICAgICAgICAgICAgICBsZWdlbmQucG9zaXRpb24gPSAiYm90dG9tIiwNCiAgICAgICAgICAgICAgICAgICAgICAgIGxlZ2VuZC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTIpLA0KICAgICAgICAgICAgICAgICAgICAgICAgbGVnZW5kLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEyKSkNCg0KbGVnZW5kX21vbnRoIDwtIGFzX2dncGxvdChnZXRfbGVnZW5kKGJhcl9zYWxlc19tb250aCkpDQoNCg0KDQpiYXJfc2FsZXNfbW9udGggPSAgZ2dwbG90KGRhdGE9Y29uZGl0aW9uYWxfZGF0YXNldF9jaXR5X21vbnRoLA0KICAgICAgICAgICAgICAgICAgICAgICAgYWVzKHg9bW9udGgsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgeT1zYWxlcywNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBmaWxsPWNpdHkpKSsNCiAgICAgICAgICAgICAgICAgIGdlb21fY29sKHN0YXQ9ImlkZW50aXR5IiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgIHBvc2l0aW9uPSAic3RhY2siKSsNCiAgICAgICAgICAgICAgICAgIGxhYnModGl0bGU9IkNvbXBhcmlzb24gb2YgdG90YWwgc2FsZXMgYnkgbW9udGggb3ZlciBjaXR5IiwNCiAgICAgICAgICAgICAgICAgICAgICAgeD0ibW9udGgiLA0KICAgICAgICAgICAgICAgICAgICAgICB5PSJzYWxlcyIpKw0KICAgICAgICAgICAgICAgICAgdGhlbWVfY2xhc3NpYygpKw0KICAgICAgICAgICAgICAgICAgdGhlbWUocGxvdC50aXRsZS5wb3NpdGlvbiA9ICJwYW5lbCIsDQogICAgICAgICAgICAgICAgICAgICAgICBwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemU9MTQsIGhqdXN0PTAuNSksDQogICAgICAgICAgICAgICAgICAgICAgICBheGlzLnRpdGxlLnggPSBlbGVtZW50X3RleHQoc2l6ZT0xMiksDQogICAgICAgICAgICAgICAgICAgICAgICBheGlzLnRpdGxlLnkgPSBlbGVtZW50X3RleHQoc2l6ZT0xMiksDQogICAgICAgICAgICAgICAgICAgICAgICBheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChzaXplPTEwKSwNCiAgICAgICAgICAgICAgICAgICAgICAgIGF4aXMudGV4dC55ID0gZWxlbWVudF90ZXh0KHNpemU9MTApLA0KICAgICAgICAgICAgICAgICAgICAgICAgbGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKSsNCiAgICAgICAgICAgICAgICAgICAgICAgIHNjYWxlX3lfY29udGludW91cyhicmVha3MgPSBzZXEoMCwgNTAwMCwgYnkgPSA1MDApKSANCg0KDQoNCg0KYmFyX3NhbGVzX21vbnRoXzIgPSAgZ2dwbG90KGRhdGE9Y29uZGl0aW9uYWxfZGF0YXNldF9jaXR5X21vbnRoLA0KICAgICAgICAgICAgICAgICAgICAgICAgYWVzKHg9bW9udGgsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgeT1zYWxlcywNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBmaWxsPWNpdHkpKSsNCiAgICAgICAgICAgICAgICAgIGdlb21fY29sKHN0YXQ9ImlkZW50aXR5IiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgIHBvc2l0aW9uPSAiZmlsbCIpKw0KICAgICAgICAgICAgICAgICAgbGFicyh0aXRsZT0iQ29tcGFyaXNvbiBvZiB0b3RhbCBzYWxlcyBieSBtb250aCBvdmVyIGNpdHkiLA0KICAgICAgICAgICAgICAgICAgICAgICB4PSJtb250aCIsDQogICAgICAgICAgICAgICAgICAgICAgIHk9InNhbGVzIHBlcmNlbnRhZ2UiKSsNCiAgICAgICAgICAgICAgICAgIHRoZW1lX2NsYXNzaWMoKSsNCiAgICAgICAgICAgICAgICAgIHRoZW1lKHBsb3QudGl0bGUucG9zaXRpb24gPSAicGFuZWwiLA0KICAgICAgICAgICAgICAgICAgICAgICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplPTE0LCBoanVzdD0wLjUpLA0KICAgICAgICAgICAgICAgICAgICAgICAgYXhpcy50aXRsZS54ID0gZWxlbWVudF90ZXh0KHNpemU9MTIpLA0KICAgICAgICAgICAgICAgICAgICAgICAgYXhpcy50aXRsZS55ID0gZWxlbWVudF90ZXh0KHNpemU9MTIpLA0KICAgICAgICAgICAgICAgICAgICAgICAgYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoc2l6ZT0xMCksDQogICAgICAgICAgICAgICAgICAgICAgICBheGlzLnRleHQueSA9IGVsZW1lbnRfdGV4dChzaXplPTEwKSwNCiAgICAgICAgICAgICAgICAgICAgICAgIGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikrDQogICAgICAgICAgICAgICAgICAgICAgICBzY2FsZV95X2NvbnRpbnVvdXMobGFiZWxzID0gcGVyY2VudF9mb3JtYXQoKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVha3MgPSBzZXEoMCwgMSwgYnkgPSAwLjEpKSANCg0KDQoNCmJhcl92b2x1bWVfbW9udGggPSAgZ2dwbG90KGRhdGE9Y29uZGl0aW9uYWxfZGF0YXNldF9jaXR5X21vbnRoLA0KICAgICAgICAgICAgICAgICAgICAgICAgYWVzKHg9bW9udGgsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgeT12b2x1bWUsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgZmlsbD1jaXR5KSkrDQogICAgICAgICAgICAgICAgICBnZW9tX2NvbChzdGF0PSJpZGVudGl0eSIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICBwb3NpdGlvbj0gInN0YWNrIikrDQogICAgICAgICAgICAgICAgICBsYWJzKHRpdGxlPSJDb21wYXJpc29uIG9mIHRvdGFsIHZvbHVtZSBieSBtb250aCBvdmVyIGNpdHkiLA0KICAgICAgICAgICAgICAgICAgICAgICB4PSJtb250aCIsDQogICAgICAgICAgICAgICAgICAgICAgIHk9InZvbHVtZSIpKw0KICAgICAgICAgICAgICAgICAgdGhlbWVfY2xhc3NpYygpKw0KICAgICAgICAgICAgICAgICAgdGhlbWUocGxvdC50aXRsZS5wb3NpdGlvbiA9ICJwYW5lbCIsDQogICAgICAgICAgICAgICAgICAgICAgICBwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemU9MTQsIGhqdXN0PTAuNSksDQogICAgICAgICAgICAgICAgICAgICAgICBheGlzLnRpdGxlLnggPSBlbGVtZW50X3RleHQoc2l6ZT0xMiksDQogICAgICAgICAgICAgICAgICAgICAgICBheGlzLnRpdGxlLnkgPSBlbGVtZW50X3RleHQoc2l6ZT0xMiksDQogICAgICAgICAgICAgICAgICAgICAgICBheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChzaXplPTEwKSwNCiAgICAgICAgICAgICAgICAgICAgICAgIGF4aXMudGV4dC55ID0gZWxlbWVudF90ZXh0KHNpemU9MTApLA0KICAgICAgICAgICAgICAgICAgICAgICAgbGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKSsNCiAgICAgICAgICAgICAgICAgICAgICAgIHNjYWxlX3lfY29udGludW91cyhicmVha3MgPSBzZXEoMCwgODAwLCBieSA9IDUwKSkNCiAgDQoNCg0KYmFyX3ZvbHVtZV9tb250aF8yID0gIGdncGxvdChkYXRhPWNvbmRpdGlvbmFsX2RhdGFzZXRfY2l0eV9tb250aCwNCiAgICAgICAgICAgICAgICAgICAgICAgIGFlcyh4PW1vbnRoLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIHk9dm9sdW1lLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZpbGw9Y2l0eSkpKw0KICAgICAgICAgICAgICAgICAgZ2VvbV9jb2woc3RhdD0iaWRlbnRpdHkiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgcG9zaXRpb249ICJmaWxsIikrDQogICAgICAgICAgICAgICAgICBsYWJzKHRpdGxlPSJDb21wYXJpc29uIG9mIHRvdGFsIHZvbHVtZSBieSBtb250aCBvdmVyIGNpdHkiLA0KICAgICAgICAgICAgICAgICAgICAgICB4PSJtb250aCIsDQogICAgICAgICAgICAgICAgICAgICAgIHk9InZvbHVtZSBwZXJjZW50YWdlIikrDQogICAgICAgICAgICAgICAgICB0aGVtZV9jbGFzc2ljKCkrDQogICAgICAgICAgICAgICAgICB0aGVtZShwbG90LnRpdGxlLnBvc2l0aW9uID0gInBhbmVsIiwNCiAgICAgICAgICAgICAgICAgICAgICAgIHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZT0xNCwgaGp1c3Q9MC41KSwNCiAgICAgICAgICAgICAgICAgICAgICAgIGF4aXMudGl0bGUueCA9IGVsZW1lbnRfdGV4dChzaXplPTEyKSwNCiAgICAgICAgICAgICAgICAgICAgICAgIGF4aXMudGl0bGUueSA9IGVsZW1lbnRfdGV4dChzaXplPTEyKSwNCiAgICAgICAgICAgICAgICAgICAgICAgIGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KHNpemU9MTApLA0KICAgICAgICAgICAgICAgICAgICAgICAgYXhpcy50ZXh0LnkgPSBlbGVtZW50X3RleHQoc2l6ZT0xMCksDQogICAgICAgICAgICAgICAgICAgICAgICBsZWdlbmQucG9zaXRpb24gPSAibm9uZSIpKw0KICAgICAgICAgICAgICAgICAgICAgICAgc2NhbGVfeV9jb250aW51b3VzKGxhYmVscyA9IHBlcmNlbnRfZm9ybWF0KCksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWtzID0gc2VxKDAsIDEsIGJ5ID0gMC4xKSkgDQoNCg0KYmFyX2xpc3RpbmdzX21vbnRoID0gIGdncGxvdChkYXRhPWNvbmRpdGlvbmFsX2RhdGFzZXRfY2l0eV9tb250aCwNCiAgICAgICAgICAgICAgICAgICAgICAgIGFlcyh4PW1vbnRoLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIHk9bGlzdGluZ3MsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgZmlsbD1jaXR5KSkrDQogICAgICAgICAgICAgICAgICBnZW9tX2NvbChzdGF0PSJpZGVudGl0eSIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICBwb3NpdGlvbj0gInN0YWNrIikrDQogICAgICAgICAgICAgICAgICBsYWJzKHRpdGxlPSJDb21wYXJpc29uIG9mIHRvdGFsIGxpc3RpbmdzIGJ5IG1vbnRoIG92ZXIgY2l0eSIsDQogICAgICAgICAgICAgICAgICAgICAgIHg9Im1vbnRoIiwNCiAgICAgICAgICAgICAgICAgICAgICAgeT0ibGlzdGluZ3MiKSsNCiAgICAgICAgICAgICAgICAgIHRoZW1lX2NsYXNzaWMoKSsNCiAgICAgICAgICAgICAgICAgIHRoZW1lKHBsb3QudGl0bGUucG9zaXRpb24gPSAicGFuZWwiLA0KICAgICAgICAgICAgICAgICAgICAgICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplPTE0LCBoanVzdD0wLjUpLA0KICAgICAgICAgICAgICAgICAgICAgICAgYXhpcy50aXRsZS54ID0gZWxlbWVudF90ZXh0KHNpemU9MTIpLA0KICAgICAgICAgICAgICAgICAgICAgICAgYXhpcy50aXRsZS55ID0gZWxlbWVudF90ZXh0KHNpemU9MTIpLA0KICAgICAgICAgICAgICAgICAgICAgICAgYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoc2l6ZT0xMCksDQogICAgICAgICAgICAgICAgICAgICAgICBheGlzLnRleHQueSA9IGVsZW1lbnRfdGV4dChzaXplPTEwKSwNCiAgICAgICAgICAgICAgICAgICAgICAgIGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikrDQogICAgICAgICAgICAgICAgICAgICAgICBzY2FsZV95X2NvbnRpbnVvdXMoYnJlYWtzID0gc2VxKDAsIDM1MDAwLCBieSA9IDUwMDApKQ0KDQoNCg0KYmFyX2xpc3RpbmdzX21vbnRoXzIgPSAgZ2dwbG90KGRhdGE9Y29uZGl0aW9uYWxfZGF0YXNldF9jaXR5X21vbnRoLA0KICAgICAgICAgICAgICAgICAgICAgICAgYWVzKHg9bW9udGgsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgeT1saXN0aW5ncywNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBmaWxsPWNpdHkpKSsNCiAgICAgICAgICAgICAgICAgIGdlb21fY29sKHN0YXQ9ImlkZW50aXR5IiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgIHBvc2l0aW9uPSAiZmlsbCIpKw0KICAgICAgICAgICAgICAgICAgbGFicyh0aXRsZT0iQ29tcGFyaXNvbiBvZiB0b3RhbCBsaXN0aW5ncyBieSBtb250aCBvdmVyIGNpdHkiLA0KICAgICAgICAgICAgICAgICAgICAgICB4PSJtb250aCIsDQogICAgICAgICAgICAgICAgICAgICAgIHk9Imxpc3RpbmdzIHBlcmNlbnRhZ2UiKSsNCiAgICAgICAgICAgICAgICAgIHRoZW1lX2NsYXNzaWMoKSsNCiAgICAgICAgICAgICAgICAgIHRoZW1lKHBsb3QudGl0bGUucG9zaXRpb24gPSAicGFuZWwiLA0KICAgICAgICAgICAgICAgICAgICAgICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplPTE0LCBoanVzdD0wLjUpLA0KICAgICAgICAgICAgICAgICAgICAgICAgYXhpcy50aXRsZS54ID0gZWxlbWVudF90ZXh0KHNpemU9MTIpLA0KICAgICAgICAgICAgICAgICAgICAgICAgYXhpcy50aXRsZS55ID0gZWxlbWVudF90ZXh0KHNpemU9MTIpLA0KICAgICAgICAgICAgICAgICAgICAgICAgYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoc2l6ZT0xMCksDQogICAgICAgICAgICAgICAgICAgICAgICBheGlzLnRleHQueSA9IGVsZW1lbnRfdGV4dChzaXplPTEwKSwNCiAgICAgICAgICAgICAgICAgICAgICAgIGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikrDQogICAgICAgICAgICAgICAgICAgICAgICBzY2FsZV95X2NvbnRpbnVvdXMobGFiZWxzID0gcGVyY2VudF9mb3JtYXQoKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVha3MgPSBzZXEoMCwgMSwgYnkgPSAwLjEpKSANCg0KDQoNCmNvbWJfZmlnXzUgPC0gYmFyX3NhbGVzX21vbnRoICsgYmFyX3NhbGVzX21vbnRoXzIgKyBiYXJfdm9sdW1lX21vbnRoICsgYmFyX3ZvbHVtZV9tb250aF8yICsgYmFyX2xpc3RpbmdzX21vbnRoICsgYmFyX2xpc3RpbmdzX21vbnRoXzIgKyAgbGVnZW5kX21vbnRoICsgcGxvdF9zcGFjZXIoKSArIHBsb3RfbGF5b3V0KG5jb2w9MiwgaGVpZ2h0cyA9IGMoNSwgNSwgNSwgLjUpKQ0KcHJpbnQoY29tYl9maWdfNSkNCg0KDQpybShiYXJfc2FsZXNfbW9udGgsIGJhcl9zYWxlc19tb250aF8yLCBiYXJfdm9sdW1lX21vbnRoLCBiYXJfdm9sdW1lX21vbnRoXzIsIGJhcl9saXN0aW5nc19tb250aCwgYmFyX2xpc3RpbmdzX21vbnRoXzIsICBsZWdlbmRfbW9udGgsIGNvbWJfZmlnXzUpDQpgYGANCg0KVGhlIGxhc3Qgc3R1ZGllcyBoaWdobGlnaHQgYSB0cmVuZCBpbiBtYW55IHZhcmlhYmxlcyBvdmVyIHRoZSBtb250aHMuIFdlIG9ic2VydmUgc2lnbmlmaWNhbnRseSBoaWdoZXIgc2FsZXMgYW5kIHZvbHVtZXMgaW4gdGhlIHNwcmluZyBhbmQgc3VtbWVyIG1vbnRocyAoaW4gYXZlcmFnZSArMjAvKzMwJSBvZiB0aGUgYW5udWFsIG1lYW4pIHdpdGggcmVzcGVjdCB0byB0aGUgYXV0dW1uIGFuZCB3aW50ZXIgb25lcyAoLTIwLy0zMCUgb2YgdGhlIGFubnVhbCBtZWFuKS4gQSBzaW1pbGFyIHRyZW5kIGlzIG9ic2VydmVkIGFsc28gZm9yIHRoZSBudW1iZXIgb2YgbGlzdGluZ3MgYW5kIG1vbnRocyBpbnZlbnRvcnksIGhvd2V2ZXIgdGhlIGdhcCBvdmVyIHRoZSB5ZWFyIG9mIHRoZXNlIHZhcmlhYmxlcyBpcyBzaWduaWZpY2FudGx5IGxlc3MgcHJvbm91bmNlZCAoJFxwbSQgNS8xMCUgb2YgdGhlIGFubnVhbCBtZWFuKS4gIA0KDQpXZSBhbHNvIG9ic2VydmUgdGhhdCB0aGlzIHBoZW5vbWVub24gaXMgaGlnaGx5IHByb25vdW5jZWQgaW4gdGhlIGNpdGllcyBvZiBUeWxlciBhbmQgQnJ5YW4tQ29sbGVnZSBTdGF0aW9uLCBtaWxkbHkgcHJvbm91bmNlZCBpbiBCZWF1bW9udCwgYW5kIG5vdCBub3RpY2VhYmxlIGluIFdpY2hpdGEgRmFsbHMuIA0KVGhlIHBlci1tb250aCB2YXJpYWJpbGl0eSBvZiBhbGwgdGhlIHZhcmlhYmxlcywgbWVhc3VyZWQgaW4gdGVybXMgb2YgdGhlIGNvZWZmaWNpZW50IG9mIHZhcmlhdGlvbiwgaXMgY29tcGFyYWJsZSBhY3Jvc3MgbW9udGhzLg0KDQpGaW5hbGx5LCB3ZSBoaWdobGlnaHQgdGhhdCB0aGUgc2FsZXMsIHZvbHVtZSBhbmQgbGlzdGluZ3Mgb2YgV2ljaGl0YSBGYWxscyByZXByZXNlbnQgYWJvdXQgMTAtMTUlIG9mIHRoZSB0b3RhbCBkdXJpbmcgYWxsIHRoZSB5ZWFyLCB0aGUgb25lcyBvZiBCZWF1bW9udCBhYm91dCAyMC0yNSUgb2YgdGhlIHRvdGFsIGFuZCB0aGUgb25lcyBpbiBCcnlhbi1Db2xsZWdlIFN0YXRpb24gcGx1cyBUeWxlciBzdGFibHkgb3ZlciA2MCUgb2YgdGhlIHRvdGFsLg0KDQoNCiMjICoqQ29uY2x1c2lvbnM6KioNCkFsbCB0aGUgdmFyaWFibGVzIGFyZSBkaXN0cmlidXRlZCBub3QgdW5pZm9ybWx5IGFjcm9zcyB0aGUgZGlmZmVyZW50IGNpdGllcywgaW4gcGFydGljdWxhciB3ZSBoYXZlIG9ic2VydmVkIHRoYXQ6IA0KLSBUaGUgcHJpY2VzIGFyZSBnZW5lcmFsbHkgaGlnaGVzdCBpbiBCcnlhbiBDb2xsZWdlIFN0YXRpb24gZm9sbG93ZWQgaW4gZGVjcmVhc2luZyBvcmRlciBieSBUeWxlciwgQmVhdW1vbnQgYW5kIFdpY2hpdGEgRmFsbHMuICANCg0KLSBUaGUgbnVtYmVyIG9mIHNhbGVzIGFuZCB2b2x1bWUgZm9sbG93IGEgc2ltaWxhciBkaXN0cmlidXRpb24gYW5kIGFyZSBoaWdoZXN0IGluIFR5bGVyIGZvbGxvd2VkIGluIGRlY3JlYXNpbmcgb3JkZXIgYnkgQnJ5YW4gQ29sbGVnZSBTdGF0aW9uLCBCZWF1bW9udCBhbmQgV2ljaGl0YSBGYWxscy4gICANCg0KLSBUaGUgbnVtYmVyIG9mIGxpc3RpbmdzIGluIFR5bGVyIGlzIHNpZ25pZmljYW50bHkgaGlnaGVyIChhbG1vc3QgdHdpY2UpIHRoYW4gaW4gYWxsIHRoZSBvdGhlciBjaXRpZXMuICAgDQoNCi0gVGhlIHZhcmlhYmlsaXR5IChtZWFzdXJlZCBpbiB0ZXJtcyBvZiB0aGUgY29lZmZpY2llbnQgb2YgdmFyaWF0aW9uKSBpbiB0aGUgdm9sdW1lIGFuZCBzYWxlcyBpbiBUeWxlciBpcyBiZXR3ZWVuIDEuNSBhbmQgMyB0aW1lcyBoaWdoZXIgdGhhbiB0aGUgdmFyaWFiaWxpdHkgb2JzZXJ2ZWQgaW4gdGhlIG90aGVyIGNpdGllcy4gV2hpbGUgdGhlIGhpZ2hlc3QgdmFyaWFiaWxpdHkgaW4gdGhlIGxpc3RpbmdzIGFuZCBtb250aCBpbnZlbnRvcnkgaXMgb2JzZXJ2ZWQgaW4gQnJ5YW4tQ29sbGVnZSBTdGF0aW9uIHdoZXJlIGl0IGlzIGFsbW9zdCB0d2ljZSBvciBtb3JlIHRoZSB2YXJpYWJpbGl0eSBpbiB0aGUgb3RoZXIgY2l0aWVzLiAgDQoNCi0gQWxsIHRoZSBjaXRpZXMgZXhjZXB0IFdpY2hpdGEgRmFsbHMgYXJlIGV4cGVyaWVuY2luZyBhIHNhbWUgdHJlbmQgb3ZlciB0aGUgbGFzdCB5ZWFycy4gVGhlIG51bWJlciBvZiBzYWxlcyB2b2x1bWUgYW5kIHByaWNlcyBhcmUgaW5jcmVhc2luZyB3aGlsZSB0aGUgbnVtYmVyIG9mIGxpc3RpbmdzIGFuZCBtb250aCBpbnZlbnRvcnkgaXMgZGVjcmVhc2luZy4gSG93ZXZlciB0aGUgYWRzIGxvb2tzIHRvIGJlIGVmZmljaWVudCBhcyB0aGUgZWZmaWNpZW5jeSBpLmUuIHF1b3RpZW50IGJldHdlZW4gbW9udGhzIGludmVudG9yeSBhbmQgbGlzdGluZ3MgaXMgaW5jcmVhc2luZy4gIA0KDQotIFRoZXNlIHRocmVlIGNpdGllcyBhbHNvIGV4cGVyaWVuY2UgYSB0cmVuZCBvdmVyIHRoZSBtb250aHMgd2l0aCBtb3JlIHNhbGVzIGFuZCB2b2x1bWUgZHVyaW5nIHRoZSBzcHJpbmcgYW5kIHN1bW1lciByYXRoZXIgdGhlbiBkdXJpbmcgdGhlIGF1dHVtbiB3aW50ZXIuIFBoZW5vbWVub24gdGhhdCBpcyBwYXJ0aWN1bGFybHkgcHJvbm91bmNlZCBpbiBUeWxlciBhbmQgQnJ5YW4tQ29sbGVnZSBTdGF0aW9uLiAgIA0KDQotIE92ZXJhbGwgdGhlIHRocmVlIGNpdGllcyBvZiBCZWF1bW9udCwgQnJ5YW4tQ29sbGVnZSBTdGF0aW9uIGFuZCBUeWxlciBhcmUgaW5jcmVhc2luZ2x5IA0Kb2NjdXB5aW5nIGEgbGFyZ2VyIG1hcmtldCBzaGFyZSBldmVyeSB5ZWFyIHVwIHRvIGFsbW9zdCA5MCUgb2Ygc2FsZXMgYW5kIHZvbHVtZSBpbiAyMDE0LiAgDQoNCi0gVGhlIHRocmVlIGNpdGllcyBvZiBCZWF1bW9udCwgQnJ5YW4tQ29sbGVnZSBTdGF0aW9uIGFuZCBUeWxlciBhbHNvIGV4cGVyaWVuY2Ugc2Vhc29uYWwgdmFyaWF0aW9ucyBpbiB0aGUgbWFya2V0LCB3aGljaCBpcyBtb3JlIGFjdGl2ZSBkdXJpbmcgdGhlIHNwcmluZyBhbmQgc3VtbWVyIHRoYW4gZHVyaW5nIHRoZSBhdXR1bW4gYW5kIHdpbnRlci4gVGhlIHNlYXNvbmFsIGRpZmZlcmVuY2UgaXMgcGFydGljdWxhcmx5IHByb25vdW5jZWQgaW4gQnJ5YW4tQ29sbGVnZSBTdGF0aW9uIGFuZCBUeWxlciwgd2hpbGUgaXQgaXMgbGVzcyBwcm9ub3VuY2VkIGluIEJlYXVtb250Lg0KDQotIFRoZSBjaXR5IG9mIFdpY2hpdGEgRmFsbHMgaXMgdGhlIG9ubHkgb25lIHdoZXJlIHRoZXJlIGFyZSBubyBzaWduaWZpY2FudCBjaGFuZ2VzIGluIHNhbGVzLCB2b2x1bWUsIGxpc3RpbmdzLCBtb250aCByZWNvdmVyeSBhbmQgcHJpY2VzIG92ZXIgdGhlIHllYXJzLiBBbHNvIGR1cmluZyB0aGUgc2Vhc29ucyBubyBzaWduaWZpY2FudCBjaGFuZ2VzIHZhcmlhdGlvbnMgYXJlIGV4cGVyaWVuY2VzLiAgDQoNCg0KSXQgc2VlbXMgbGlrZWx5IHRoYXQgdGhlIG9mZmVyIG9mIHJlYWwgZXN0YXRlIGlzIGRlY3JlYXNpbmcgaW4gdGhlIHRocmVlIGNpdGllcyBvZiBCcnlhbi1Db2xsZWdlIFN0YXRpb24sIFR5bGVyIGFuZCBCZWF1bW9udCB3aGlsZSB0aGUgZGVtYW5kIGlzIGxpa2VseSBpbmNyZWFzaW5nLg0KVGhpcyBpcyBkcml2aW5nIHVwIHByaWNlcyBhbmQgYnVzaW5lc3Mgdm9sdW1lLiBJbiBwYXJ0aWN1bGFyIHRoZSBhZHMgc2VlbSB0byBiZSBlZmZpY2llbnQgaW4gdGhlc2UgY2l0aWVzIGFzIHRoZSBudW1iZXIgb2Ygc2FsZXMgcGVyIG1vbnRoIGlzIGluY3JlYXNpbmcuIERpZmZlcmVudGx5LCB0aGUgc2l0dWF0aW9uIGlzIFdpY2hpdGEgRmFsbHMgaXMgc3RhdGljIGFuZCB0aGUgYWR2ZXJ0aXNpbmcgcG9saWNpZXMgaGF2ZSBub3QgcHJvZHVjZWQgYW55IHNpZ25pZmljYW50IGltcHJvdmVtZW50IHRvIHRoZSBidXNpbmVzcyB2b2x1bWUgb3ZlciB0aGUgbGFzdCB5ZWFycy4gSW4gcGFydGljdWxhciwgaW4gcGVyY2VudGFnZSB0ZXJtcywgdGhlIFdpY2hpdGEgRmFsbHMgcmVhbCBlc3RhdGUgbWFya2V0IGhhcyBiZWVuIGluY3JlYXNpbmdseSBkZWNsaW5pbmcgb3ZlciB0aGUgeWVhcnMuIFRoZXJlZm9yZSwgSSB3b3VsZCByZWNvbW1lbmQgcmV2aWV3aW5nIHRoZSBhZHZlcnRpc2luZyBwb2xpY3kgYWRvcHRlZCBpbiBXaWNoaXRhIEZhbGxzLCB3aGlsZSBtYWludGFpbmluZyB0aGUgc2FtZSBwb2xpY3kgaW4gb3RoZXIgY2l0aWVzLg0KDQoNCg0K