library(tidyverse) library(moderndive) library(ggplot2)
library(skimr) library(gapminder) library(infer)
tinytex::install_tinytex() install.packages(“xfun”)
set.seed(4869)
#bringing in dataframe, has 4969 entries with 7 columns
movie_boxoffice.1 <-
read.csv(“C:/Users/zahir/OneDrive/Desktop/Rutgers Semester Folders/2024
Fall Semester/Inference Data Science/HW 4 Lab/movie_boxoffice-1.csv”)
View(movie_boxoffice.1)
#cleaning up dataframe of duplicates, has 4869 entries with 7 columns
movie_boxoffice_distinct <- movie_boxoffice.1 %>% distinct()
view(movie_boxoffice_distinct)
#0. How many duplicated records were removed from boxoffice data?
What is your random seed number? #Answer: 100 dublicated
records(entries) were removed, and my random seed number is set to
4869
#************************************************************************************************
#Part I: Sampling #1.Treat the box office data as population. Have a
histogram of the global box office earning. Describe shape of
distribution.
ggplot(movie_boxoffice_distinct, aes(x = Worldwide_Gross)) + geom_histogram(fill = "lightblue", color = "black") +
labs(title = "Worldwide Box Office Earnings Distribution", x = "Worldwide Gross", y = "Count")

#Answer: Seems to be an exponential distribution with mode occuring
at 0.
#2. In population, what is average global box earning? What is the
std? What is the proportion of movies who global box earning exceeds
budget?
average_globalbox_earning <- mean(movie_boxoffice_distinct$Worldwide_Gross)
print(average_globalbox_earning)
[1] 95.83149
std_globalbox_earning <- sd(movie_boxoffice_distinct$Worldwide_Gross)
print(std_globalbox_earning)
[1] 177.4594
global_earning_exceeds_budget <- movie_boxoffice_distinct %>%
filter(Worldwide_Gross > Budget)
proportion_exceed <- nrow(global_earning_exceeds_budget) / nrow(movie_boxoffice_distinct)
print(proportion_exceed)
[1] 0.6461286
#Answer:Average global box earning is $95.83 million. Standard
deviation is $177.46 million. Proportion of global box earning exceeding
budget is 64.61%
#3. Take a random sample of 200 movies from the pop. Get histogram of
global box earning, describe shape of distribution. set.seed(4869)
movies_sample <- movie_boxoffice_distinct %>% sample_n(size =
200)
ggplot(movies_sample, aes(x = Worldwide_Gross)) + geom_histogram(fill = "lightblue", color = "black") +
labs(title = "Worldwide Box Office Earnings Distribution", x = "Worldwide Gross", y = "Count")

#Answer: Seems to be an exponential distribution with mode occuring
at 0. Also seems to be similar to the overall population histogram.
#4. In sample, what {is avg global box office earning? is std? is
proportion of global box movie earning exceeding budget?} Are these
summary stats from sample close to population paramets?
average_sample_earning <- mean(movies_sample$Worldwide_Gross)
print(average_sample_earning)
[1] 119.7947
std_sample_earning <- sd(movies_sample$Worldwide_Gross)
print(std_sample_earning)
[1] 201.7954
global_sample_earning_exceeds_budget <- movies_sample %>%
filter(Worldwide_Gross > Budget)
proportion_sample_exceed <- nrow(global_sample_earning_exceeds_budget) / nrow(movie_boxoffice_distinct)
print(proportion_sample_exceed)
[1] 0.02690491
#Answer:Average global box earning is $136.55 million. Standard
deviation is $231.55 million. Proportion of global box earning exceeding
budget is 2.81%. These summary stats differ quite a bit from the
population summary stats. Specifically about $40 million in avg, $54
million in std, and about 62% difference in proportion. This sample may
contain more movies with lesser global box earnings than their budgets
unlike the overall population explaining such low proportion.
#5.Take rand sample of n movies from the pop, calculate the avg
global box office earning, and proportion of global box earning
exceeding budget.
set.seed(4869)
sample_stats <- function(n, reps = 500) {
movie_boxoffice_distinct %>%
rep_sample_n(size = n, reps = reps) %>%
group_by(replicate) %>%
summarize(
gross_avg = mean(Worldwide_Gross),
proportion_ex = mean(Worldwide_Gross > Budget),
)
}
n_val <- sample(50:500, 1)
output_ex <- sample_stats(n_val)
print(output_ex)
overall_avg <- mean(output_ex$gross_avg)
cat(
"Sample Size =", n_val,
": AVG Global Box Office Earnings =", round(overall_avg, 2),
", Proportion Exceeding Budget =", round(mean(output_ex$proportion_ex, na.rm = TRUE), 4)
)
Sample Size = 78 : AVG Global Box Office Earnings = 95.06 , Proportion Exceeding Budget = 0.6478
#6 For each n=20, 50, 100, and 200, get histrogram of the avg global
box earning using face_wrap(), also get mean and std error
set.seed(4869)
get_repetition_stats <- function(n, reps = 500) {
movie_boxoffice_distinct %>%
rep_sample_n(size = n, reps = reps) %>%
group_by(replicate) %>%
summarize(
gross_mean = mean(Worldwide_Gross),
proportion_exceed = mean(Worldwide_Gross > Budget)
)
}
n_20 <- get_repetition_stats(20)
n_50 <- get_repetition_stats(50)
n_100 <- get_repetition_stats(100)
n_200 <- get_repetition_stats(200)
n_20$Sample_Size <- 20
n_50$Sample_Size <- 50
n_100$Sample_Size <- 100
n_200$Sample_Size <- 200
allSamplesDF <- bind_rows(n_20, n_50, n_100, n_200)
allSamplesDF$Sample_Size <- rep(c(20, 50, 100, 200), each = 500)
ggplot(allSamplesDF, aes(x = gross_mean)) + geom_histogram(fill = "lightblue", color = "black") + facet_wrap(~ Sample_Size, scales = "free") + labs(title = "Average Global Box Office Earnings Distribution by n Size", x = "Worldwide Gross Mean", y ="Count")

summary_stats <- allSamplesDF %>%
group_by(Sample_Size) %>%
summarize(
mean_allgross = mean(gross_mean),
std_err_allgross = sd(gross_mean) / sqrt(n())
)
print(summary_stats)
#7. Compare distributions among the different n values, and also
compare them to the distribution from the population in Q1 #Answer: For
distrubtions among the different n values, starting at n = 20, more
closely aligned with the distribution from the population in Q1, but
mode no longer being at 0, but a value around $70 million. Going up the
scale on the n values to 50, 100, and 200, the distribtuion was
approaching normality, especially with n being 200. Although mode count
decreased, the concisesness of it went up to around the value of $90
million.
#8. For each n = {20, 50, 100, 200}, get the histogram of the
proportion of movies whose global box office earning exceeds budget,
using face_wrap, also get mean and std error
set.seed(4869)
get_repetition_prop <- function(n, reps = 500) {
movie_boxoffice_distinct %>%
rep_sample_n(size = n, reps = reps) %>%
group_by(replicate) %>%
summarize(
proportion_exceed = mean(Worldwide_Gross > Budget)
)
}
pn_20 <- get_repetition_prop(20)
pn_50 <- get_repetition_prop(50)
pn_100 <- get_repetition_prop(100)
pn_200 <- get_repetition_prop(200)
pn_20$Sample_Size <- 20
pn_50$Sample_Size <- 50
pn_100$Sample_Size <- 100
pn_200$Sample_Size <- 200
allSamDF <- bind_rows(n_20, n_50, n_100, n_200)
allSamDF$Sample_Size <- rep(c(20, 50, 100, 200), each = 500)
ggplot(allSamDF, aes(x = proportion_exceed)) + geom_histogram(fill = "lightblue", color = "black") + facet_wrap(~ Sample_Size, scales = "free") + labs(title = "Proportion of Successful Movies by n Size", x = "Proportion of Worldwide Gross Exceeding Budget", y ="Count")

prop_summary_stats <- allSamDF %>%
group_by(Sample_Size) %>%
summarize(
mean_proportion = mean(proportion_exceed),
std_err_allgross = sd(proportion_exceed) / sqrt(n())
)
print(prop_summary_stats)
#9. Compare the distributions among different n values. #Answer: For
n = 20 describles a somewhat left-skewed distribtuion with mode being at
0.7. For n = 50, distribtuion appears to be normal, while at n = 100,
repeating similarities with n = 20, but now there are two modes making
it a bimodal left-skewed distribution. For N = 200, distribution appears
to be more normal similar to n = 50.
#************************************************************************************************
#Part II: Bootstrapping
#10. Use data from Q3 as the initial sample, use bootstrapping method
to resample once with 200 movies. Are there any duplicated movies,
expected or not?
set.seed(4869)
bootstrap_samp <- movies_sample %>%
rep_sample_n(size = 200, replace = TRUE) %>%
summarize(gross_avg = mean(Worldwide_Gross))
print(bootstrap_samp)
set.seed(4869)
duplicateNum <- movies_sample %>%
rep_sample_n(size = 200, replace = TRUE) %>%
count(Movie) %>%
filter(n > 1)
print(duplicateNum)
#Answer:Yes, there were duplicated movies, was this expected? Of
course it was expected because we set replace to be TRUE allowing picked
movies to be picked again.
#11.Get the histrogram of global box office earning in the bootstrap
sample. Describe the shape of distribution and compare it to Q3
bootstrap2_samp <- movies_sample %>%
rep_sample_n(size = 200, replace = TRUE)
ggplot(bootstrap2_samp, aes(x = Worldwide_Gross)) + geom_histogram(fill = "lightblue", color = "black") + labs(title = "Boostrap Sample Histogram of Worldwide Box Earnings", x = "Worldwide Gross", y ="Count")

#Answer: The shape of bootstrap sample histogram is closer to the
exponential distribution, with mode still occuring at 0, and more
variance with higher counts of outliers than as seen in Q3.
#12.In the bootstrap sample from Q10, what {is the avg global box
earning, is the std, is the proportion of succesful movies?} Are they
close enough to those in the intial sample?
avg_gross <- mean(bootstrap2_samp$Worldwide_Gross)
print(avg_gross)
[1] 127.9658
std_gross <- sd(bootstrap2_samp$Worldwide_Gross)
print(std_gross)
[1] 221.3411
prop_ex_bu <- mean(bootstrap2_samp$Worldwide_Gross > bootstrap2_samp$Budget)
print(prop_ex_bu)
[1] 0.69
#Answer: Average gross given is $127.97 million, Std dev is $221.34
million, and proportion of successful movies is 69%. These are pretty
close to the intial values of avg gross being $136.55 million, std dev
as $231.55 million, with the biggest defference being proportion from
2.81%. However, this is now closer to the overall population proportion
of 64.61.
#13. Get the boostrapping distr of the avg global box earning, and
proportion of movies whose global box earning exceeded budget, by
resampling 500 times with bootstrapping method. Get the mean and std
error of the average global box earning and mean and std error for
proportion.
set.seed(3223)
bootstrap_samples <- movies_sample %>%
rep_sample_n(size = nrow(movies_sample), reps = 2000, replace = TRUE)
bootstrap_stats <- bootstrap_samples %>%
summarize(
bootstrap_grossmean = mean(Worldwide_Gross),
bootstrap_prop = mean(Worldwide_Gross > Budget)
)
bootstrap_grossavg <- mean(bootstrap_stats$bootstrap_grossmean)
print(bootstrap_grossavg)
[1] 119.7433
bootstrap_std_grossavg <- sd(bootstrap_stats$bootstrap_grossmean)
print(bootstrap_std_grossavg)
[1] 14.21178
mean_prop <- mean(bootstrap_stats$bootstrap_prop)
print(mean_prop)
[1] 0.65501
se_prop <- sd(bootstrap_stats$bootstrap_prop) / sqrt(nrow(bootstrap_stats))
print(se_prop)
[1] 0.0007548658
ggplot(bootstrap_stats, aes(x = bootstrap_grossmean)) + geom_histogram(fill = "lightblue", color = "black") + labs(title = "Average Global Box Office Earnings Distribution", x = "AVG Worldwide Gross", y = "Count")

ggplot(bootstrap_stats, aes(x = bootstrap_prop)) + geom_histogram(fill = "lightblue", color = "black") + labs(title = "Proportion of Successful Movies", x = "Successful Movies", y = "Count")

#Answer: Given mean of Average global office earning is $120.30
million, with std dev being $14.59 million. Proportion of succesful
movies given is 65.44%, and the standard error for it is 0.16%. The
distribution for Average Global Box Earnings is right leaning with
occuring around $112 million, and for the poportion of succesful moves,
distribution is more normal with a slight left skew and mode occuring
around 67.5%.
#***************************************************************************************************************************************************************************
#Stat291 Homework 5 #1 The confidence interval of the average global box
office earning of all movies from 1980 to 2018
#setting up bootstrap distribution from given sample referenced in homework 4
set.seed(3333)
movie_stats <- movies_sample %>%
specify(response = Worldwide_Gross) %>%
generate(reps = 1500, type = "bootstrap") %>%
calculate(stat = "mean")
#visualization of the distribution
visualize(movie_stats)

ci_percentile <- movie_stats %>%
get_confidence_interval(level = 0.95, type = "percentile")
print(ci_percentile)
bootstrap_mean <- mean(movie_stats$stat)
bootstrap_se <- sd(movie_stats$stat)
ci_std_err <- c(
lower = bootstrap_mean - 1.96 * bootstrap_se,
upper = bootstrap_mean + 1.96 * bootstrap_se
)
print(ci_std_err)
lower upper
92.09295 146.59990
ci_theor <- c(
lower = bootstrap_mean - qnorm(0.975) * bootstrap_se,
upper = bootstrap_mean + qnorm(0.975) * bootstrap_se
)
print(ci_theor)
lower upper
92.09345 146.59940
#Answer: The lower ci and upper ci given are $93.40 million and
$148.49 million with 95% confidence, means that we can be 95% confident
that the average global box earnings for all movies released between
1980 and 2018 falls within this range. The standard error and
theoretical method were close but with values of $91 million and $146.6
million. The slight right skew observed in the bootstrap distribution
can help explain the slight difference between these two and the
percentile method.
#2 The confidence interval of the difference of average global box
earnings between movies in the summer (June, July, and August) and
movies in the rest of year
set.seed(4444)
movies_sample2 <- movies_sample %>%
mutate(summer = ifelse(Month %in% c("Jun", "Jul", "Aug"), "Summer", "Other"))
summer_stats <- movies_sample2 %>%
specify(response = Worldwide_Gross, explanatory = summer) %>%
generate(reps = 1750, type = "bootstrap") %>%
calculate(stat = "diff in means", order = c("Summer", "Other"))
visualize(summer_stats)

ci_summer <- summer_stats %>%
get_confidence_interval(level = 0.95, type = "percentile")
print(ci_summer)
summer_mean <- mean(summer_stats$stat)
summer_se <- sd(summer_stats$stat)
ci_sum_std_err <- c(
lower = summer_mean - 1.96 * summer_se,
upper = summer_mean + 1.96 * summer_se
)
print(ci_sum_std_err)
lower upper
-24.35445 140.63298
sum_ci_theor <- c(
lower = summer_mean - qnorm(0.975) * summer_se,
upper = summer_mean + qnorm(0.975) * summer_se
)
print(sum_ci_theor)
lower upper
-24.35293 140.63146
#Answer: We can be 95% confident that average global box earnings lie
between -16.47 million and 145.77 million dollars, and since the
interval includes zero, there cannot be a conclusion of a satistically
significant difference between summer and non-summer movies at this
level. From the theoretical and standard error method, the confidence
interval obtained was between -$24.35 million and $140.63 million that
can be explained by the distribution being slightly skewed right.
#3.The confidence interval of the difference of proportions of movies
whose global box office earnings exceeds budget
bootstrap_diff <- bootstrap_samples %>%
group_by(replicate) %>%
summarize(
prop_exc_budg = mean(Worldwide_Gross > Budget)
) %>%
mutate(
diff_prop = prop_exc_budg
)
mean_diff_prop <- mean(bootstrap_diff$diff_prop)
se_diff_prop <-sd(bootstrap_diff$diff_prop)
ggplot(bootstrap_diff, aes(x = diff_prop)) +
geom_histogram(binwidth = 0.01, color = "black", fill ="lightblue") +
labs(title = "Bootstrap Distribution of Difference in Proportions", x = "Difference in Proportions", y = "Count")

#c(0.025,0.975) captures center 95% while leaving 2.5% off both ends
ci_prop <- quantile(bootstrap_diff$diff_prop, probs = c(
0.025, 0.975
))
print(ci_prop)
2.5% 97.5%
0.59 0.72
ci_prop_se <- c(
lower = mean_diff_prop - 1.96 * se_diff_prop,
upper = mean_diff_prop + 1.96 * se_diff_prop
)
print(ci_prop_se)
lower upper
0.5888431 0.7211769
prop_ci_theor <- c(
lower = mean_diff_prop - qnorm(0.975) * se_diff_prop,
upper = mean_diff_prop + qnorm(0.975) * se_diff_prop
)
print(prop_ci_theor)
lower upper
0.5888443 0.7211757
#Answer: Seeing that the numbers range from about 0.59 to 0.72, means
that we can be 95% confident that the proportion for global box earnings
exceeding budget will fall within this interval. The distribution
appears to have a slight left-skew.
#4 The confidence interval, of the difference of proportions of
movies whose global box office earnings exceeds budget between movies
released from 1980 to 1999 and those released from 2000 and 2018 #using
data obtained in part 3 of this lab, I adjusted it to
prop_strap_diff <- bootstrap_samples %>%
group_by(replicate) %>%
summarize(
prop_exc_1980_1999 = mean(ifelse(Year >= 1980 & Year <= 1999 & !is.na(Worldwide_Gross), Worldwide_Gross > Budget, NA), na.rm = TRUE),
prop_exc_2000_2018 = mean(ifelse(Year >= 2000 & Year <= 2018 & !is.na(Worldwide_Gross), Worldwide_Gross > Budget, NA), na.rm = TRUE)
) %>%
mutate(
diff_prop2 = prop_exc_2000_2018 - prop_exc_1980_1999
)
mean_diff_prop2 <- mean(prop_strap_diff$diff_prop2)
se_diff_prop2 <- sd(prop_strap_diff$diff_prop2)
ggplot(prop_strap_diff, aes(x = diff_prop2)) +
geom_histogram(binwidth = 0.01, color = "black", fill = "lightblue") +
labs(title = "Bootstrap Distribution of Difference in Proportions between 1980-1999 and 2000-2018", x = "Difference in Proportions between 1980-1999 and 2000-2018", y = "Count")

#c(0.025,0.975) captures center 95% while leaving 2.5% off both ends
ci_prop2 <- quantile(prop_strap_diff$diff_prop2, probs = c(
0.025, 0.975
))
print(ci_prop2)
2.5% 97.5%
-0.04787311 0.31644719
ci_prop_se2 <- c(
lower = mean_diff_prop2 - 1.96 * se_diff_prop2,
upper = mean_diff_prop2 + 1.96 * se_diff_prop2
)
print(ci_prop_se2)
lower upper
-0.04577925 0.31359360
prop_ci_theor2 <- c(
lower = mean_diff_prop2 - qnorm(0.975) * se_diff_prop2,
upper = mean_diff_prop2 + qnorm(0.975) * se_diff_prop2
)
print(prop_ci_theor2)
lower upper
-0.04577595 0.31359030
#Answer: Observing the different confident interval values, ranging
from approx -0.046 to 0.314 or as in the percentile method: -0.048 to
0.316. Since zero is included within all intervals, at the 95%
confidence level, it can be stated that there is no statistically
significant difference between both time periods from (1980-1999 to
2000-2018).
LS0tDQp0aXRsZTogIlIgTm90ZWJvb2siDQpvdXRwdXQ6DQogIGh0bWxfbm90ZWJvb2s6IGRlZmF1bHQNCiAgaHRtbF9kb2N1bWVudDoNCiAgICBkZl9wcmludDogcGFnZWQNCiAgcGRmX2RvY3VtZW50OiBkZWZhdWx0DQotLS0NCmxpYnJhcnkodGlkeXZlcnNlKQ0KbGlicmFyeShtb2Rlcm5kaXZlKQ0KbGlicmFyeShnZ3Bsb3QyKQ0KbGlicmFyeShza2ltcikNCmxpYnJhcnkoZ2FwbWluZGVyKQ0KbGlicmFyeShpbmZlcikNCnRpbnl0ZXg6Omluc3RhbGxfdGlueXRleCgpDQppbnN0YWxsLnBhY2thZ2VzKCJ4ZnVuIikNCg0KDQpzZXQuc2VlZCg0ODY5KQ0KDQojYnJpbmdpbmcgaW4gZGF0YWZyYW1lLCBoYXMgNDk2OSBlbnRyaWVzIHdpdGggNyBjb2x1bW5zDQptb3ZpZV9ib3hvZmZpY2UuMSA8LSByZWFkLmNzdigiQzovVXNlcnMvemFoaXIvT25lRHJpdmUvRGVza3RvcC9SdXRnZXJzIFNlbWVzdGVyIEZvbGRlcnMvMjAyNCBGYWxsIFNlbWVzdGVyL0luZmVyZW5jZSBEYXRhIFNjaWVuY2UvSFcgNCBMYWIvbW92aWVfYm94b2ZmaWNlLTEuY3N2IikNCiAgVmlldyhtb3ZpZV9ib3hvZmZpY2UuMSkNCg0KI2NsZWFuaW5nIHVwIGRhdGFmcmFtZSBvZiBkdXBsaWNhdGVzLCBoYXMgNDg2OSBlbnRyaWVzIHdpdGggNyBjb2x1bW5zDQptb3ZpZV9ib3hvZmZpY2VfZGlzdGluY3QgPC0gbW92aWVfYm94b2ZmaWNlLjEgJT4lDQogIGRpc3RpbmN0KCkNCiAgdmlldyhtb3ZpZV9ib3hvZmZpY2VfZGlzdGluY3QpDQogIA0KIzAuIEhvdyBtYW55IGR1cGxpY2F0ZWQgcmVjb3JkcyB3ZXJlIHJlbW92ZWQgZnJvbSBib3hvZmZpY2UgZGF0YT8gV2hhdCBpcyB5b3VyIHJhbmRvbSBzZWVkIG51bWJlcj8NCiNBbnN3ZXI6IDEwMCBkdWJsaWNhdGVkIHJlY29yZHMoZW50cmllcykgd2VyZSByZW1vdmVkLCBhbmQgbXkgcmFuZG9tIHNlZWQgbnVtYmVyIGlzIHNldCB0byA0ODY5DQoNCiMqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioNCiNQYXJ0IEk6IFNhbXBsaW5nDQojMS5UcmVhdCB0aGUgYm94IG9mZmljZSBkYXRhIGFzIHBvcHVsYXRpb24uIEhhdmUgYSBoaXN0b2dyYW0gb2YgdGhlIGdsb2JhbCBib3ggb2ZmaWNlIGVhcm5pbmcuIERlc2NyaWJlIHNoYXBlIG9mIGRpc3RyaWJ1dGlvbi4NCmBgYHtyIEhpc3RvZ3JhbSBvZiB0aGUgR2xvYmFsIEJveCBFYXJuaW5nfQ0KZ2dwbG90KG1vdmllX2JveG9mZmljZV9kaXN0aW5jdCwgYWVzKHggPSBXb3JsZHdpZGVfR3Jvc3MpKSArIGdlb21faGlzdG9ncmFtKGZpbGwgPSAibGlnaHRibHVlIiwgY29sb3IgPSAiYmxhY2siKSArIA0KbGFicyh0aXRsZSA9ICJXb3JsZHdpZGUgQm94IE9mZmljZSBFYXJuaW5ncyBEaXN0cmlidXRpb24iLCB4ID0gIldvcmxkd2lkZSBHcm9zcyIsIHkgPSAiQ291bnQiKQ0KYGBgDQojQW5zd2VyOiBTZWVtcyB0byBiZSBhbiBleHBvbmVudGlhbCBkaXN0cmlidXRpb24gd2l0aCBtb2RlIG9jY3VyaW5nIGF0IDAuDQoNCiMyLiBJbiBwb3B1bGF0aW9uLCB3aGF0IGlzIGF2ZXJhZ2UgZ2xvYmFsIGJveCBlYXJuaW5nPyBXaGF0IGlzIHRoZSBzdGQ/IFdoYXQgaXMgdGhlIHByb3BvcnRpb24gb2YgbW92aWVzIHdobyBnbG9iYWwgYm94IGVhcm5pbmcgZXhjZWVkcyBidWRnZXQ/DQpgYGB7ciBQYXJ0IDEgU3RlcCAyIENvZGV9DQphdmVyYWdlX2dsb2JhbGJveF9lYXJuaW5nIDwtIG1lYW4obW92aWVfYm94b2ZmaWNlX2Rpc3RpbmN0JFdvcmxkd2lkZV9Hcm9zcykNCnByaW50KGF2ZXJhZ2VfZ2xvYmFsYm94X2Vhcm5pbmcpDQoNCnN0ZF9nbG9iYWxib3hfZWFybmluZyA8LSBzZChtb3ZpZV9ib3hvZmZpY2VfZGlzdGluY3QkV29ybGR3aWRlX0dyb3NzKQ0KcHJpbnQoc3RkX2dsb2JhbGJveF9lYXJuaW5nKQ0KDQpnbG9iYWxfZWFybmluZ19leGNlZWRzX2J1ZGdldCA8LSBtb3ZpZV9ib3hvZmZpY2VfZGlzdGluY3QgJT4lDQogIGZpbHRlcihXb3JsZHdpZGVfR3Jvc3MgPiBCdWRnZXQpDQpwcm9wb3J0aW9uX2V4Y2VlZCA8LSBucm93KGdsb2JhbF9lYXJuaW5nX2V4Y2VlZHNfYnVkZ2V0KSAvIG5yb3cobW92aWVfYm94b2ZmaWNlX2Rpc3RpbmN0KQ0KcHJpbnQocHJvcG9ydGlvbl9leGNlZWQpDQpgYGANCiNBbnN3ZXI6QXZlcmFnZSBnbG9iYWwgYm94IGVhcm5pbmcgaXMgJDk1LjgzIG1pbGxpb24uIFN0YW5kYXJkIGRldmlhdGlvbiBpcyAkMTc3LjQ2IG1pbGxpb24uIFByb3BvcnRpb24gb2YgZ2xvYmFsIGJveCBlYXJuaW5nIGV4Y2VlZGluZyBidWRnZXQgaXMgNjQuNjElDQoNCiMzLiBUYWtlIGEgcmFuZG9tIHNhbXBsZSBvZiAyMDAgbW92aWVzIGZyb20gdGhlIHBvcC4gR2V0IGhpc3RvZ3JhbSBvZiBnbG9iYWwgYm94IGVhcm5pbmcsIGRlc2NyaWJlIHNoYXBlIG9mIGRpc3RyaWJ1dGlvbi4NCnNldC5zZWVkKDQ4NjkpDQptb3ZpZXNfc2FtcGxlIDwtIG1vdmllX2JveG9mZmljZV9kaXN0aW5jdCAlPiUNCiAgc2FtcGxlX24oc2l6ZSA9IDIwMCkNCmBgYHtyIFBhcnQgMSBTdGVwIDMgSGlzdG9ncmFtfQ0KZ2dwbG90KG1vdmllc19zYW1wbGUsIGFlcyh4ID0gV29ybGR3aWRlX0dyb3NzKSkgKyBnZW9tX2hpc3RvZ3JhbShmaWxsID0gImxpZ2h0Ymx1ZSIsIGNvbG9yID0gImJsYWNrIikgKyANCmxhYnModGl0bGUgPSAiV29ybGR3aWRlIEJveCBPZmZpY2UgRWFybmluZ3MgRGlzdHJpYnV0aW9uIiwgeCA9ICJXb3JsZHdpZGUgR3Jvc3MiLCB5ID0gIkNvdW50IikNCmBgYA0KI0Fuc3dlcjogU2VlbXMgdG8gYmUgYW4gZXhwb25lbnRpYWwgZGlzdHJpYnV0aW9uIHdpdGggbW9kZSBvY2N1cmluZyBhdCAwLiBBbHNvIHNlZW1zIHRvIGJlIHNpbWlsYXIgdG8gdGhlIG92ZXJhbGwgcG9wdWxhdGlvbiBoaXN0b2dyYW0uDQoNCiM0LiBJbiBzYW1wbGUsIHdoYXQge2lzIGF2ZyBnbG9iYWwgYm94IG9mZmljZSBlYXJuaW5nPyBpcyBzdGQ/IGlzIHByb3BvcnRpb24gb2YgZ2xvYmFsIGJveCBtb3ZpZSBlYXJuaW5nIGV4Y2VlZGluZyBidWRnZXQ/fSBBcmUgdGhlc2Ugc3VtbWFyeSBzdGF0cyBmcm9tIHNhbXBsZSBjbG9zZSB0byBwb3B1bGF0aW9uIHBhcmFtZXRzPw0KYGBge3IgUGFydCAxIFN0ZXAgNCBDb2RlfQ0KYXZlcmFnZV9zYW1wbGVfZWFybmluZyA8LSBtZWFuKG1vdmllc19zYW1wbGUkV29ybGR3aWRlX0dyb3NzKQ0KcHJpbnQoYXZlcmFnZV9zYW1wbGVfZWFybmluZykNCg0Kc3RkX3NhbXBsZV9lYXJuaW5nIDwtIHNkKG1vdmllc19zYW1wbGUkV29ybGR3aWRlX0dyb3NzKQ0KcHJpbnQoc3RkX3NhbXBsZV9lYXJuaW5nKQ0KDQpnbG9iYWxfc2FtcGxlX2Vhcm5pbmdfZXhjZWVkc19idWRnZXQgPC0gbW92aWVzX3NhbXBsZSAlPiUNCiAgZmlsdGVyKFdvcmxkd2lkZV9Hcm9zcyA+IEJ1ZGdldCkNCnByb3BvcnRpb25fc2FtcGxlX2V4Y2VlZCA8LSBucm93KGdsb2JhbF9zYW1wbGVfZWFybmluZ19leGNlZWRzX2J1ZGdldCkgLyBucm93KG1vdmllX2JveG9mZmljZV9kaXN0aW5jdCkNCnByaW50KHByb3BvcnRpb25fc2FtcGxlX2V4Y2VlZCkNCmBgYA0KI0Fuc3dlcjpBdmVyYWdlIGdsb2JhbCBib3ggZWFybmluZyBpcyAkMTM2LjU1IG1pbGxpb24uIFN0YW5kYXJkIGRldmlhdGlvbiBpcyAkMjMxLjU1IG1pbGxpb24uIFByb3BvcnRpb24gb2YgZ2xvYmFsIGJveCBlYXJuaW5nIGV4Y2VlZGluZyBidWRnZXQgaXMgMi44MSUuIFRoZXNlIHN1bW1hcnkgc3RhdHMgZGlmZmVyIHF1aXRlIGEgYml0IGZyb20gdGhlIHBvcHVsYXRpb24gc3VtbWFyeSBzdGF0cy4gU3BlY2lmaWNhbGx5IGFib3V0ICQ0MCBtaWxsaW9uIGluIGF2ZywgJDU0IG1pbGxpb24gaW4gc3RkLCBhbmQgYWJvdXQgNjIlIGRpZmZlcmVuY2UgaW4gcHJvcG9ydGlvbi4gVGhpcyBzYW1wbGUgbWF5IGNvbnRhaW4gbW9yZSBtb3ZpZXMgd2l0aCBsZXNzZXIgZ2xvYmFsIGJveCBlYXJuaW5ncyB0aGFuIHRoZWlyIGJ1ZGdldHMgdW5saWtlIHRoZSBvdmVyYWxsIHBvcHVsYXRpb24gZXhwbGFpbmluZyBzdWNoIGxvdyBwcm9wb3J0aW9uLg0KDQojNS5UYWtlIHJhbmQgc2FtcGxlIG9mIG4gbW92aWVzIGZyb20gdGhlIHBvcCwgY2FsY3VsYXRlIHRoZSBhdmcgZ2xvYmFsIGJveCBvZmZpY2UgZWFybmluZywgYW5kIHByb3BvcnRpb24gb2YgZ2xvYmFsIGJveCBlYXJuaW5nIGV4Y2VlZGluZyBidWRnZXQuDQpgYGB7ciA1MDAgSXRlcmF0aW9uc30NCnNldC5zZWVkKDQ4NjkpDQpzYW1wbGVfc3RhdHMgPC0gZnVuY3Rpb24obiwgcmVwcyA9IDUwMCkgew0KICBtb3ZpZV9ib3hvZmZpY2VfZGlzdGluY3QgJT4lDQogICAgcmVwX3NhbXBsZV9uKHNpemUgPSBuLCByZXBzID0gcmVwcykgJT4lDQogICAgZ3JvdXBfYnkocmVwbGljYXRlKSAlPiUNCiAgICBzdW1tYXJpemUoDQogICAgICBncm9zc19hdmcgPSBtZWFuKFdvcmxkd2lkZV9Hcm9zcyksDQogICAgICBwcm9wb3J0aW9uX2V4ID0gbWVhbihXb3JsZHdpZGVfR3Jvc3MgPiBCdWRnZXQpLA0KICAgICkNCn0NCg0Kbl92YWwgPC0gc2FtcGxlKDUwOjUwMCwgMSkNCg0Kb3V0cHV0X2V4IDwtIHNhbXBsZV9zdGF0cyhuX3ZhbCkNCnByaW50KG91dHB1dF9leCkNCg0Kb3ZlcmFsbF9hdmcgPC0gbWVhbihvdXRwdXRfZXgkZ3Jvc3NfYXZnKQ0KY2F0KA0KICAiU2FtcGxlIFNpemUgPSIsIG5fdmFsLCANCiAgIjogQVZHIEdsb2JhbCBCb3ggT2ZmaWNlIEVhcm5pbmdzID0iLCByb3VuZChvdmVyYWxsX2F2ZywgMiksDQogICIsIFByb3BvcnRpb24gRXhjZWVkaW5nIEJ1ZGdldCA9Iiwgcm91bmQobWVhbihvdXRwdXRfZXgkcHJvcG9ydGlvbl9leCwgbmEucm0gPSBUUlVFKSwgNCkNCiAgKQ0KYGBgDQoNCiM2IEZvciBlYWNoIG49MjAsIDUwLCAxMDAsIGFuZCAyMDAsIGdldCBoaXN0cm9ncmFtIG9mIHRoZSBhdmcgZ2xvYmFsIGJveCBlYXJuaW5nIHVzaW5nIGZhY2Vfd3JhcCgpLCBhbHNvIGdldCBtZWFuIGFuZCBzdGQgZXJyb3INCg0KYGBge3IgSGlzdG9ncmFtIGJ5IG4gU2l6ZX0NCnNldC5zZWVkKDQ4NjkpDQpnZXRfcmVwZXRpdGlvbl9zdGF0cyA8LSBmdW5jdGlvbihuLCByZXBzID0gNTAwKSB7DQogIG1vdmllX2JveG9mZmljZV9kaXN0aW5jdCAlPiUNCiAgICByZXBfc2FtcGxlX24oc2l6ZSA9IG4sIHJlcHMgPSByZXBzKSAlPiUNCiAgICBncm91cF9ieShyZXBsaWNhdGUpICU+JQ0KICAgICAgc3VtbWFyaXplKA0KICAgICAgICBncm9zc19tZWFuID0gbWVhbihXb3JsZHdpZGVfR3Jvc3MpLA0KICAgICAgICBwcm9wb3J0aW9uX2V4Y2VlZCA9IG1lYW4oV29ybGR3aWRlX0dyb3NzID4gQnVkZ2V0KQ0KICAgICAgKQ0KfQ0KDQpuXzIwIDwtIGdldF9yZXBldGl0aW9uX3N0YXRzKDIwKQ0Kbl81MCA8LSBnZXRfcmVwZXRpdGlvbl9zdGF0cyg1MCkNCm5fMTAwIDwtIGdldF9yZXBldGl0aW9uX3N0YXRzKDEwMCkNCm5fMjAwIDwtIGdldF9yZXBldGl0aW9uX3N0YXRzKDIwMCkNCg0Kbl8yMCRTYW1wbGVfU2l6ZSA8LSAyMA0Kbl81MCRTYW1wbGVfU2l6ZSA8LSA1MA0Kbl8xMDAkU2FtcGxlX1NpemUgPC0gMTAwDQpuXzIwMCRTYW1wbGVfU2l6ZSA8LSAyMDANCiAgDQphbGxTYW1wbGVzREYgPC0gYmluZF9yb3dzKG5fMjAsIG5fNTAsIG5fMTAwLCBuXzIwMCkNCg0KYWxsU2FtcGxlc0RGJFNhbXBsZV9TaXplIDwtIHJlcChjKDIwLCA1MCwgMTAwLCAyMDApLCBlYWNoID0gNTAwKQ0KDQpnZ3Bsb3QoYWxsU2FtcGxlc0RGLCBhZXMoeCA9IGdyb3NzX21lYW4pKSArIGdlb21faGlzdG9ncmFtKGZpbGwgPSAibGlnaHRibHVlIiwgY29sb3IgPSAiYmxhY2siKSArIGZhY2V0X3dyYXAofiBTYW1wbGVfU2l6ZSwgc2NhbGVzID0gImZyZWUiKSArIGxhYnModGl0bGUgPSAiQXZlcmFnZSBHbG9iYWwgQm94IE9mZmljZSBFYXJuaW5ncyBEaXN0cmlidXRpb24gYnkgbiBTaXplIiwgeCA9ICJXb3JsZHdpZGUgR3Jvc3MgTWVhbiIsIHkgPSJDb3VudCIpDQpgYGANCmBgYHtyIE1lYW4gYW5kIHN0ZCBlcnJvciBvZiBhdmVyYWdlIGdsb2JhbCBib3ggZWFybmluZ30NCnN1bW1hcnlfc3RhdHMgPC0gYWxsU2FtcGxlc0RGICU+JQ0KICBncm91cF9ieShTYW1wbGVfU2l6ZSkgJT4lDQogIHN1bW1hcml6ZSgNCiAgICBtZWFuX2FsbGdyb3NzID0gbWVhbihncm9zc19tZWFuKSwNCiAgICBzdGRfZXJyX2FsbGdyb3NzID0gc2QoZ3Jvc3NfbWVhbikgLyBzcXJ0KG4oKSkNCiAgKQ0KcHJpbnQoc3VtbWFyeV9zdGF0cykNCmBgYA0KDQojNy4gQ29tcGFyZSBkaXN0cmlidXRpb25zIGFtb25nIHRoZSBkaWZmZXJlbnQgbiB2YWx1ZXMsIGFuZCBhbHNvIGNvbXBhcmUgdGhlbSB0byB0aGUgZGlzdHJpYnV0aW9uIGZyb20gdGhlIHBvcHVsYXRpb24gaW4gUTENCiNBbnN3ZXI6IEZvciBkaXN0cnVidGlvbnMgYW1vbmcgdGhlIGRpZmZlcmVudCBuIHZhbHVlcywgc3RhcnRpbmcgYXQgbiA9IDIwLCBtb3JlIGNsb3NlbHkgYWxpZ25lZCB3aXRoIHRoZSBkaXN0cmlidXRpb24gZnJvbSB0aGUgcG9wdWxhdGlvbiBpbiBRMSwgYnV0IG1vZGUgbm8gbG9uZ2VyIGJlaW5nIGF0IDAsIGJ1dCBhIHZhbHVlIGFyb3VuZCAkNzAgbWlsbGlvbi4gR29pbmcgdXAgdGhlIHNjYWxlIG9uIHRoZSBuIHZhbHVlcyB0byA1MCwgMTAwLCBhbmQgMjAwLCB0aGUgZGlzdHJpYnR1aW9uIHdhcyBhcHByb2FjaGluZyBub3JtYWxpdHksIGVzcGVjaWFsbHkgd2l0aCBuIGJlaW5nIDIwMC4gQWx0aG91Z2ggbW9kZSBjb3VudCBkZWNyZWFzZWQsIHRoZSBjb25jaXNlc25lc3Mgb2YgaXQgd2VudCB1cCB0byBhcm91bmQgdGhlIHZhbHVlIG9mICQ5MCBtaWxsaW9uLg0KDQojOC4gRm9yIGVhY2ggbiA9IHsyMCwgNTAsIDEwMCwgMjAwfSwgZ2V0IHRoZSBoaXN0b2dyYW0gb2YgdGhlIHByb3BvcnRpb24gb2YgbW92aWVzIHdob3NlIGdsb2JhbCBib3ggb2ZmaWNlIGVhcm5pbmcgZXhjZWVkcyBidWRnZXQsIHVzaW5nIGZhY2Vfd3JhcCwgYWxzbyBnZXQgbWVhbiBhbmQgc3RkIGVycm9yDQpgYGB7ciBIaXN0b2dyYW1zIG9mIFByb3BvcnRpb24gb2YgU3VjY2Vzc2Z1bCBNb3ZpZXMgYnkgbiBTaXplfQ0Kc2V0LnNlZWQoNDg2OSkNCmdldF9yZXBldGl0aW9uX3Byb3AgPC0gZnVuY3Rpb24obiwgcmVwcyA9IDUwMCkgew0KICBtb3ZpZV9ib3hvZmZpY2VfZGlzdGluY3QgJT4lDQogICAgcmVwX3NhbXBsZV9uKHNpemUgPSBuLCByZXBzID0gcmVwcykgJT4lDQogICAgZ3JvdXBfYnkocmVwbGljYXRlKSAlPiUNCiAgICAgIHN1bW1hcml6ZSgNCiAgICAgICAgcHJvcG9ydGlvbl9leGNlZWQgPSBtZWFuKFdvcmxkd2lkZV9Hcm9zcyA+IEJ1ZGdldCkNCiAgICAgICkNCn0NCg0KcG5fMjAgPC0gZ2V0X3JlcGV0aXRpb25fcHJvcCgyMCkNCnBuXzUwIDwtIGdldF9yZXBldGl0aW9uX3Byb3AoNTApDQpwbl8xMDAgPC0gZ2V0X3JlcGV0aXRpb25fcHJvcCgxMDApDQpwbl8yMDAgPC0gZ2V0X3JlcGV0aXRpb25fcHJvcCgyMDApDQoNCnBuXzIwJFNhbXBsZV9TaXplIDwtIDIwDQpwbl81MCRTYW1wbGVfU2l6ZSA8LSA1MA0KcG5fMTAwJFNhbXBsZV9TaXplIDwtIDEwMA0KcG5fMjAwJFNhbXBsZV9TaXplIDwtIDIwMA0KICANCmFsbFNhbURGIDwtIGJpbmRfcm93cyhuXzIwLCBuXzUwLCBuXzEwMCwgbl8yMDApDQoNCmFsbFNhbURGJFNhbXBsZV9TaXplIDwtIHJlcChjKDIwLCA1MCwgMTAwLCAyMDApLCBlYWNoID0gNTAwKQ0KDQpnZ3Bsb3QoYWxsU2FtREYsIGFlcyh4ID0gcHJvcG9ydGlvbl9leGNlZWQpKSArIGdlb21faGlzdG9ncmFtKGZpbGwgPSAibGlnaHRibHVlIiwgY29sb3IgPSAiYmxhY2siKSArIGZhY2V0X3dyYXAofiBTYW1wbGVfU2l6ZSwgc2NhbGVzID0gImZyZWUiKSArIGxhYnModGl0bGUgPSAiUHJvcG9ydGlvbiBvZiBTdWNjZXNzZnVsIE1vdmllcyBieSBuIFNpemUiLCB4ID0gIlByb3BvcnRpb24gb2YgV29ybGR3aWRlIEdyb3NzIEV4Y2VlZGluZyBCdWRnZXQiLCB5ID0iQ291bnQiKQ0KYGBgDQpgYGB7cn0NCnByb3Bfc3VtbWFyeV9zdGF0cyA8LSBhbGxTYW1ERiAlPiUNCiAgZ3JvdXBfYnkoU2FtcGxlX1NpemUpICU+JQ0KICBzdW1tYXJpemUoDQogICAgbWVhbl9wcm9wb3J0aW9uID0gbWVhbihwcm9wb3J0aW9uX2V4Y2VlZCksDQogICAgc3RkX2Vycl9hbGxncm9zcyA9IHNkKHByb3BvcnRpb25fZXhjZWVkKSAvIHNxcnQobigpKQ0KICApDQpwcmludChwcm9wX3N1bW1hcnlfc3RhdHMpDQpgYGANCg0KIzkuIENvbXBhcmUgdGhlIGRpc3RyaWJ1dGlvbnMgYW1vbmcgZGlmZmVyZW50IG4gdmFsdWVzLiANCiNBbnN3ZXI6IEZvciBuID0gMjAgZGVzY3JpYmxlcyBhIHNvbWV3aGF0IGxlZnQtc2tld2VkIGRpc3RyaWJ0dWlvbiB3aXRoIG1vZGUgYmVpbmcgYXQgMC43LiBGb3IgbiA9IDUwLCBkaXN0cmlidHVpb24gYXBwZWFycyB0byBiZSBub3JtYWwsIHdoaWxlIGF0IG4gPSAxMDAsIHJlcGVhdGluZyBzaW1pbGFyaXRpZXMgd2l0aCBuID0gMjAsIGJ1dCBub3cgdGhlcmUgYXJlIHR3byBtb2RlcyBtYWtpbmcgaXQgYSBiaW1vZGFsIGxlZnQtc2tld2VkIGRpc3RyaWJ1dGlvbi4gRm9yIE4gPSAyMDAsIGRpc3RyaWJ1dGlvbiBhcHBlYXJzIHRvIGJlIG1vcmUgbm9ybWFsIHNpbWlsYXIgdG8gbiA9IDUwLg0KDQojKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqDQojUGFydCBJSTogQm9vdHN0cmFwcGluZw0KDQojMTAuIFVzZSBkYXRhIGZyb20gUTMgYXMgdGhlIGluaXRpYWwgc2FtcGxlLCB1c2UgYm9vdHN0cmFwcGluZyBtZXRob2QgdG8gcmVzYW1wbGUgb25jZSB3aXRoIDIwMCBtb3ZpZXMuIEFyZSB0aGVyZSBhbnkgZHVwbGljYXRlZCBtb3ZpZXMsIGV4cGVjdGVkIG9yIG5vdD8NCmBgYHtyfQ0Kc2V0LnNlZWQoNDg2OSkNCg0KYm9vdHN0cmFwX3NhbXAgPC0gbW92aWVzX3NhbXBsZSAlPiUNCiAgcmVwX3NhbXBsZV9uKHNpemUgPSAyMDAsIHJlcGxhY2UgPSBUUlVFKSAlPiUNCiAgc3VtbWFyaXplKGdyb3NzX2F2ZyA9IG1lYW4oV29ybGR3aWRlX0dyb3NzKSkNCnByaW50KGJvb3RzdHJhcF9zYW1wKQ0KYGBgDQpgYGB7cn0NCnNldC5zZWVkKDQ4NjkpDQpkdXBsaWNhdGVOdW0gPC0gbW92aWVzX3NhbXBsZSAlPiUNCiAgcmVwX3NhbXBsZV9uKHNpemUgPSAyMDAsIHJlcGxhY2UgPSBUUlVFKSAlPiUNCiAgY291bnQoTW92aWUpICU+JQ0KICBmaWx0ZXIobiA+IDEpDQpwcmludChkdXBsaWNhdGVOdW0pDQpgYGANCg0KI0Fuc3dlcjpZZXMsIHRoZXJlIHdlcmUgZHVwbGljYXRlZCBtb3ZpZXMsIHdhcyB0aGlzIGV4cGVjdGVkPyBPZiBjb3Vyc2UgaXQgd2FzIGV4cGVjdGVkIGJlY2F1c2Ugd2Ugc2V0IHJlcGxhY2UgdG8gYmUgVFJVRSBhbGxvd2luZyBwaWNrZWQgbW92aWVzIHRvIGJlIHBpY2tlZCBhZ2Fpbi4NCg0KIzExLkdldCB0aGUgaGlzdHJvZ3JhbSBvZiBnbG9iYWwgYm94IG9mZmljZSBlYXJuaW5nIGluIHRoZSBib290c3RyYXAgc2FtcGxlLiBEZXNjcmliZSB0aGUgc2hhcGUgb2YgZGlzdHJpYnV0aW9uIGFuZCBjb21wYXJlIGl0IHRvIFEzDQpgYGB7cn0NCmJvb3RzdHJhcDJfc2FtcCA8LSBtb3ZpZXNfc2FtcGxlICU+JQ0KICByZXBfc2FtcGxlX24oc2l6ZSA9IDIwMCwgcmVwbGFjZSA9IFRSVUUpDQoNCmdncGxvdChib290c3RyYXAyX3NhbXAsIGFlcyh4ID0gV29ybGR3aWRlX0dyb3NzKSkgKyBnZW9tX2hpc3RvZ3JhbShmaWxsID0gImxpZ2h0Ymx1ZSIsIGNvbG9yID0gImJsYWNrIikgKyBsYWJzKHRpdGxlID0gIkJvb3N0cmFwIFNhbXBsZSBIaXN0b2dyYW0gb2YgV29ybGR3aWRlIEJveCBFYXJuaW5ncyIsIHggPSAiV29ybGR3aWRlIEdyb3NzIiwgeSA9IkNvdW50IikNCmBgYA0KI0Fuc3dlcjogVGhlIHNoYXBlIG9mIGJvb3RzdHJhcCBzYW1wbGUgaGlzdG9ncmFtIGlzIGNsb3NlciB0byB0aGUgZXhwb25lbnRpYWwgZGlzdHJpYnV0aW9uLCB3aXRoIG1vZGUgc3RpbGwgb2NjdXJpbmcgYXQgMCwgYW5kIG1vcmUgdmFyaWFuY2Ugd2l0aCBoaWdoZXIgY291bnRzIG9mIG91dGxpZXJzIHRoYW4gYXMgc2VlbiBpbiBRMy4NCg0KIzEyLkluIHRoZSBib290c3RyYXAgc2FtcGxlIGZyb20gUTEwLCB3aGF0IHtpcyB0aGUgYXZnIGdsb2JhbCBib3ggZWFybmluZywgaXMgdGhlIHN0ZCwgaXMgdGhlIHByb3BvcnRpb24gb2Ygc3VjY2VzZnVsIG1vdmllcz99IEFyZSB0aGV5IGNsb3NlIGVub3VnaCB0byB0aG9zZSBpbiB0aGUgaW50aWFsIHNhbXBsZT8NCmBgYHtyfQ0KYXZnX2dyb3NzIDwtIG1lYW4oYm9vdHN0cmFwMl9zYW1wJFdvcmxkd2lkZV9Hcm9zcykNCnByaW50KGF2Z19ncm9zcykNCg0Kc3RkX2dyb3NzIDwtIHNkKGJvb3RzdHJhcDJfc2FtcCRXb3JsZHdpZGVfR3Jvc3MpDQpwcmludChzdGRfZ3Jvc3MpDQoNCnByb3BfZXhfYnUgPC0gbWVhbihib290c3RyYXAyX3NhbXAkV29ybGR3aWRlX0dyb3NzID4gYm9vdHN0cmFwMl9zYW1wJEJ1ZGdldCkNCnByaW50KHByb3BfZXhfYnUpDQpgYGANCiNBbnN3ZXI6IEF2ZXJhZ2UgZ3Jvc3MgZ2l2ZW4gaXMgJDEyNy45NyBtaWxsaW9uLCBTdGQgZGV2IGlzICQyMjEuMzQgbWlsbGlvbiwgYW5kIHByb3BvcnRpb24gb2Ygc3VjY2Vzc2Z1bCBtb3ZpZXMgaXMgNjklLiBUaGVzZSBhcmUgcHJldHR5IGNsb3NlIHRvIHRoZSBpbnRpYWwgdmFsdWVzIG9mIGF2ZyBncm9zcyBiZWluZyAkMTM2LjU1IG1pbGxpb24sIHN0ZCBkZXYgYXMgJDIzMS41NSBtaWxsaW9uLCB3aXRoIHRoZSBiaWdnZXN0IGRlZmZlcmVuY2UgYmVpbmcgcHJvcG9ydGlvbiBmcm9tIDIuODElLiBIb3dldmVyLCB0aGlzIGlzIG5vdyBjbG9zZXIgdG8gdGhlIG92ZXJhbGwgcG9wdWxhdGlvbiBwcm9wb3J0aW9uIG9mIDY0LjYxLg0KDQojMTMuIEdldCB0aGUgYm9vc3RyYXBwaW5nIGRpc3RyIG9mIHRoZSBhdmcgZ2xvYmFsIGJveCBlYXJuaW5nLCBhbmQgcHJvcG9ydGlvbiBvZiBtb3ZpZXMgd2hvc2UgZ2xvYmFsIGJveCBlYXJuaW5nIGV4Y2VlZGVkIGJ1ZGdldCwgYnkgcmVzYW1wbGluZyA1MDAgdGltZXMgd2l0aCBib290c3RyYXBwaW5nIG1ldGhvZC4gR2V0IHRoZSBtZWFuIGFuZCBzdGQgZXJyb3Igb2YgdGhlIGF2ZXJhZ2UgZ2xvYmFsIGJveCBlYXJuaW5nIGFuZCBtZWFuIGFuZCBzdGQgZXJyb3IgZm9yIHByb3BvcnRpb24uDQpgYGB7cn0NCnNldC5zZWVkKDMyMjMpDQpib290c3RyYXBfc2FtcGxlcyA8LSBtb3ZpZXNfc2FtcGxlICU+JQ0KICByZXBfc2FtcGxlX24oc2l6ZSA9IG5yb3cobW92aWVzX3NhbXBsZSksIHJlcHMgPSAyMDAwLCByZXBsYWNlID0gVFJVRSkNCg0KYm9vdHN0cmFwX3N0YXRzIDwtIGJvb3RzdHJhcF9zYW1wbGVzICU+JQ0KICBzdW1tYXJpemUoDQogICAgYm9vdHN0cmFwX2dyb3NzbWVhbiA9IG1lYW4oV29ybGR3aWRlX0dyb3NzKSwNCiAgICBib290c3RyYXBfcHJvcCA9IG1lYW4oV29ybGR3aWRlX0dyb3NzID4gQnVkZ2V0KQ0KICApDQpib290c3RyYXBfZ3Jvc3NhdmcgPC0gbWVhbihib290c3RyYXBfc3RhdHMkYm9vdHN0cmFwX2dyb3NzbWVhbikNCnByaW50KGJvb3RzdHJhcF9ncm9zc2F2ZykNCg0KYm9vdHN0cmFwX3N0ZF9ncm9zc2F2ZyA8LSBzZChib290c3RyYXBfc3RhdHMkYm9vdHN0cmFwX2dyb3NzbWVhbikNCnByaW50KGJvb3RzdHJhcF9zdGRfZ3Jvc3NhdmcpDQoNCm1lYW5fcHJvcCA8LSBtZWFuKGJvb3RzdHJhcF9zdGF0cyRib290c3RyYXBfcHJvcCkNCnByaW50KG1lYW5fcHJvcCkNCg0Kc2VfcHJvcCA8LSBzZChib290c3RyYXBfc3RhdHMkYm9vdHN0cmFwX3Byb3ApIC8gc3FydChucm93KGJvb3RzdHJhcF9zdGF0cykpDQpwcmludChzZV9wcm9wKQ0KYGBgDQpgYGB7ciBFYXJuaW5ncyBEaXN0cmlidXRpb24gfQ0KZ2dwbG90KGJvb3RzdHJhcF9zdGF0cywgYWVzKHggPSBib290c3RyYXBfZ3Jvc3NtZWFuKSkgKyBnZW9tX2hpc3RvZ3JhbShmaWxsID0gImxpZ2h0Ymx1ZSIsIGNvbG9yID0gImJsYWNrIikgKyBsYWJzKHRpdGxlID0gIkF2ZXJhZ2UgR2xvYmFsIEJveCBPZmZpY2UgRWFybmluZ3MgRGlzdHJpYnV0aW9uIiwgeCA9ICJBVkcgV29ybGR3aWRlIEdyb3NzIiwgeSA9ICJDb3VudCIpDQpgYGANCmBgYHtyfQ0KZ2dwbG90KGJvb3RzdHJhcF9zdGF0cywgYWVzKHggPSBib290c3RyYXBfcHJvcCkpICsgZ2VvbV9oaXN0b2dyYW0oZmlsbCA9ICJsaWdodGJsdWUiLCBjb2xvciA9ICJibGFjayIpICsgbGFicyh0aXRsZSA9ICJQcm9wb3J0aW9uIG9mIFN1Y2Nlc3NmdWwgTW92aWVzIiwgeCA9ICJTdWNjZXNzZnVsIE1vdmllcyIsIHkgPSAiQ291bnQiKQ0KDQpgYGANCg0KI0Fuc3dlcjogR2l2ZW4gbWVhbiBvZiBBdmVyYWdlIGdsb2JhbCBvZmZpY2UgZWFybmluZyBpcyAkMTIwLjMwIG1pbGxpb24sIHdpdGggc3RkIGRldiBiZWluZyAkMTQuNTkgbWlsbGlvbi4gUHJvcG9ydGlvbiBvZiBzdWNjZXNmdWwgbW92aWVzIGdpdmVuIGlzIDY1LjQ0JSwgYW5kIHRoZSBzdGFuZGFyZCBlcnJvciBmb3IgaXQgaXMgMC4xNiUuIFRoZSBkaXN0cmlidXRpb24gZm9yIEF2ZXJhZ2UgR2xvYmFsIEJveCBFYXJuaW5ncyBpcyByaWdodCBsZWFuaW5nIHdpdGggb2NjdXJpbmcgYXJvdW5kICQxMTIgbWlsbGlvbiwgYW5kIGZvciB0aGUgcG9wb3J0aW9uIG9mIHN1Y2Nlc2Z1bCBtb3ZlcywgZGlzdHJpYnV0aW9uIGlzIG1vcmUgbm9ybWFsIHdpdGggYSBzbGlnaHQgbGVmdCBza2V3IGFuZCBtb2RlIG9jY3VyaW5nIGFyb3VuZCA2Ny41JS4NCg0KIyoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKg0KI1N0YXQyOTEgSG9tZXdvcmsgNQ0KIzEgVGhlIGNvbmZpZGVuY2UgaW50ZXJ2YWwgb2YgdGhlIGF2ZXJhZ2UgZ2xvYmFsIGJveCBvZmZpY2UgZWFybmluZyBvZiBhbGwgbW92aWVzIGZyb20gMTk4MCB0byAyMDE4DQpgYGB7ciBDb25maWRlbmNlIEludGVydmFsIEJvb3RzdHJhcCBEaXN0cmlidXRpb24gMX0NCiNzZXR0aW5nIHVwIGJvb3RzdHJhcCBkaXN0cmlidXRpb24gZnJvbSBnaXZlbiBzYW1wbGUgcmVmZXJlbmNlZCBpbiBob21ld29yayA0DQpzZXQuc2VlZCgzMzMzKQ0KDQptb3ZpZV9zdGF0cyA8LSBtb3ZpZXNfc2FtcGxlICU+JQ0KICBzcGVjaWZ5KHJlc3BvbnNlID0gV29ybGR3aWRlX0dyb3NzKSAlPiUNCiAgZ2VuZXJhdGUocmVwcyA9IDE1MDAsIHR5cGUgPSAiYm9vdHN0cmFwIikgJT4lDQogIGNhbGN1bGF0ZShzdGF0ID0gIm1lYW4iKQ0KDQojdmlzdWFsaXphdGlvbiBvZiB0aGUgZGlzdHJpYnV0aW9uDQp2aXN1YWxpemUobW92aWVfc3RhdHMpDQpgYGANCmBgYHtyIFBlcmNlbnRpbGUgbWV0aG9kIDF9DQpjaV9wZXJjZW50aWxlIDwtIG1vdmllX3N0YXRzICU+JQ0KICBnZXRfY29uZmlkZW5jZV9pbnRlcnZhbChsZXZlbCA9IDAuOTUsIHR5cGUgPSAicGVyY2VudGlsZSIpDQoNCnByaW50KGNpX3BlcmNlbnRpbGUpDQpgYGANCmBgYHtyIFN0YW5kYXJkIEVycm9yIE1ldGhvZCAxfQ0KYm9vdHN0cmFwX21lYW4gPC0gbWVhbihtb3ZpZV9zdGF0cyRzdGF0KQ0KYm9vdHN0cmFwX3NlIDwtIHNkKG1vdmllX3N0YXRzJHN0YXQpDQoNCmNpX3N0ZF9lcnIgPC0gYygNCiAgbG93ZXIgPSBib290c3RyYXBfbWVhbiAtIDEuOTYgKiBib290c3RyYXBfc2UsDQogIHVwcGVyID0gYm9vdHN0cmFwX21lYW4gKyAxLjk2ICogYm9vdHN0cmFwX3NlDQopDQoNCnByaW50KGNpX3N0ZF9lcnIpDQpgYGANCmBgYHtyIFRoZW9yZXRpY2FsIE1ldGhvZCAxfQ0KY2lfdGhlb3IgPC0gYygNCiAgbG93ZXIgPSBib290c3RyYXBfbWVhbiAtIHFub3JtKDAuOTc1KSAqIGJvb3RzdHJhcF9zZSwNCiAgdXBwZXIgPSBib290c3RyYXBfbWVhbiArIHFub3JtKDAuOTc1KSAqIGJvb3RzdHJhcF9zZQ0KKQ0KDQpwcmludChjaV90aGVvcikNCmBgYA0KDQojQW5zd2VyOiBUaGUgbG93ZXIgY2kgYW5kIHVwcGVyIGNpIGdpdmVuIGFyZSAkOTMuNDAgbWlsbGlvbiBhbmQgJDE0OC40OSBtaWxsaW9uIHdpdGggOTUlIGNvbmZpZGVuY2UsIG1lYW5zIHRoYXQgd2UgY2FuIGJlIDk1JSBjb25maWRlbnQgdGhhdCB0aGUgYXZlcmFnZSBnbG9iYWwgYm94IGVhcm5pbmdzIGZvciBhbGwgbW92aWVzIHJlbGVhc2VkIGJldHdlZW4gMTk4MCBhbmQgMjAxOCBmYWxscyB3aXRoaW4gdGhpcyByYW5nZS4gVGhlIHN0YW5kYXJkIGVycm9yIGFuZCB0aGVvcmV0aWNhbCBtZXRob2Qgd2VyZSBjbG9zZSBidXQgd2l0aCB2YWx1ZXMgb2YgJDkxIG1pbGxpb24gYW5kICQxNDYuNiBtaWxsaW9uLiBUaGUgc2xpZ2h0IHJpZ2h0IHNrZXcgb2JzZXJ2ZWQgaW4gdGhlIGJvb3RzdHJhcCBkaXN0cmlidXRpb24gY2FuIGhlbHAgZXhwbGFpbiB0aGUgc2xpZ2h0IGRpZmZlcmVuY2UgYmV0d2VlbiB0aGVzZSB0d28gYW5kIHRoZSBwZXJjZW50aWxlIG1ldGhvZC4NCg0KIzIgVGhlIGNvbmZpZGVuY2UgaW50ZXJ2YWwgb2YgdGhlIGRpZmZlcmVuY2Ugb2YgYXZlcmFnZSBnbG9iYWwgYm94IGVhcm5pbmdzIGJldHdlZW4gbW92aWVzIGluIHRoZSBzdW1tZXIgKEp1bmUsIEp1bHksIGFuZCBBdWd1c3QpIGFuZCBtb3ZpZXMgaW4gdGhlIHJlc3Qgb2YgeWVhcg0KYGBge3IgQ29uZmlkZW5jZSBJbnRlcnZhbCBCb290c3RyYXAgRGlzdHJpYnV0aW9uIDJ9DQpzZXQuc2VlZCg0NDQ0KQ0KDQptb3ZpZXNfc2FtcGxlMiA8LSBtb3ZpZXNfc2FtcGxlICU+JQ0KICBtdXRhdGUoc3VtbWVyID0gaWZlbHNlKE1vbnRoICVpbiUgYygiSnVuIiwgIkp1bCIsICJBdWciKSwgIlN1bW1lciIsICJPdGhlciIpKQ0KDQpzdW1tZXJfc3RhdHMgPC0gbW92aWVzX3NhbXBsZTIgJT4lDQogIHNwZWNpZnkocmVzcG9uc2UgPSBXb3JsZHdpZGVfR3Jvc3MsIGV4cGxhbmF0b3J5ID0gc3VtbWVyKSAlPiUNCiAgZ2VuZXJhdGUocmVwcyA9IDE3NTAsIHR5cGUgPSAiYm9vdHN0cmFwIikgJT4lDQogIGNhbGN1bGF0ZShzdGF0ID0gImRpZmYgaW4gbWVhbnMiLCBvcmRlciA9IGMoIlN1bW1lciIsICJPdGhlciIpKQ0KDQoNCnZpc3VhbGl6ZShzdW1tZXJfc3RhdHMpDQpgYGANCmBgYHtyIFBlcmNlbnRpbGUgTWV0aG9kIDJ9DQpjaV9zdW1tZXIgPC0gc3VtbWVyX3N0YXRzICU+JQ0KICBnZXRfY29uZmlkZW5jZV9pbnRlcnZhbChsZXZlbCA9IDAuOTUsIHR5cGUgPSAicGVyY2VudGlsZSIpDQoNCnByaW50KGNpX3N1bW1lcikNCmBgYA0KYGBge3Igc3RhbmRhcmQgZXJyb3IgbWV0aG9kIDJ9DQpzdW1tZXJfbWVhbiA8LSBtZWFuKHN1bW1lcl9zdGF0cyRzdGF0KQ0Kc3VtbWVyX3NlIDwtIHNkKHN1bW1lcl9zdGF0cyRzdGF0KQ0KDQpjaV9zdW1fc3RkX2VyciA8LSBjKA0KICBsb3dlciA9IHN1bW1lcl9tZWFuIC0gMS45NiAqIHN1bW1lcl9zZSwNCiAgdXBwZXIgPSBzdW1tZXJfbWVhbiArIDEuOTYgKiBzdW1tZXJfc2UNCikNCg0KcHJpbnQoY2lfc3VtX3N0ZF9lcnIpDQpgYGANCmBgYHtyIFRoZW9yZXRpY2FsIE1ldGhvZCAyfQ0Kc3VtX2NpX3RoZW9yIDwtIGMoDQogIGxvd2VyID0gc3VtbWVyX21lYW4gLSBxbm9ybSgwLjk3NSkgKiBzdW1tZXJfc2UsDQogIHVwcGVyID0gc3VtbWVyX21lYW4gKyBxbm9ybSgwLjk3NSkgKiBzdW1tZXJfc2UNCikNCg0KcHJpbnQoc3VtX2NpX3RoZW9yKQ0KYGBgDQojQW5zd2VyOiBXZSBjYW4gYmUgOTUlIGNvbmZpZGVudCB0aGF0IGF2ZXJhZ2UgZ2xvYmFsIGJveCBlYXJuaW5ncyBsaWUgYmV0d2VlbiAtMTYuNDcgbWlsbGlvbiBhbmQgMTQ1Ljc3IG1pbGxpb24gZG9sbGFycywgYW5kIHNpbmNlIHRoZSBpbnRlcnZhbCBpbmNsdWRlcyB6ZXJvLCB0aGVyZSBjYW5ub3QgYmUgYSBjb25jbHVzaW9uIG9mIGEgc2F0aXN0aWNhbGx5IHNpZ25pZmljYW50IGRpZmZlcmVuY2UgYmV0d2VlbiBzdW1tZXIgYW5kIG5vbi1zdW1tZXIgbW92aWVzIGF0IHRoaXMgbGV2ZWwuIEZyb20gdGhlIHRoZW9yZXRpY2FsIGFuZCBzdGFuZGFyZCBlcnJvciBtZXRob2QsIHRoZSBjb25maWRlbmNlIGludGVydmFsIG9idGFpbmVkIHdhcyBiZXR3ZWVuIC0kMjQuMzUgbWlsbGlvbiBhbmQgJDE0MC42MyBtaWxsaW9uIHRoYXQgY2FuIGJlIGV4cGxhaW5lZCBieSB0aGUgZGlzdHJpYnV0aW9uIGJlaW5nIHNsaWdodGx5IHNrZXdlZCByaWdodC4NCg0KIzMuVGhlIGNvbmZpZGVuY2UgaW50ZXJ2YWwgb2YgdGhlIGRpZmZlcmVuY2Ugb2YgcHJvcG9ydGlvbnMgb2YgbW92aWVzIHdob3NlIGdsb2JhbCBib3ggb2ZmaWNlIGVhcm5pbmdzIGV4Y2VlZHMgYnVkZ2V0DQpgYGB7ciBDb25maWRlbmNlIEludGVydmFsIEJvb3RzdHJhcCBEaXN0cmlidXRpb24gM30NCmJvb3RzdHJhcF9kaWZmIDwtIGJvb3RzdHJhcF9zYW1wbGVzICU+JQ0KICBncm91cF9ieShyZXBsaWNhdGUpICU+JQ0KICBzdW1tYXJpemUoDQogICAgcHJvcF9leGNfYnVkZyA9IG1lYW4oV29ybGR3aWRlX0dyb3NzID4gQnVkZ2V0KQ0KICApICU+JQ0KICBtdXRhdGUoDQogICAgZGlmZl9wcm9wID0gcHJvcF9leGNfYnVkZw0KICApDQoNCm1lYW5fZGlmZl9wcm9wIDwtIG1lYW4oYm9vdHN0cmFwX2RpZmYkZGlmZl9wcm9wKQ0KDQpzZV9kaWZmX3Byb3AgPC1zZChib290c3RyYXBfZGlmZiRkaWZmX3Byb3ApDQoNCmdncGxvdChib290c3RyYXBfZGlmZiwgYWVzKHggPSBkaWZmX3Byb3ApKSArDQogIGdlb21faGlzdG9ncmFtKGJpbndpZHRoID0gMC4wMSwgY29sb3IgPSAiYmxhY2siLCBmaWxsID0ibGlnaHRibHVlIikgKw0KICBsYWJzKHRpdGxlID0gIkJvb3RzdHJhcCBEaXN0cmlidXRpb24gb2YgRGlmZmVyZW5jZSBpbiBQcm9wb3J0aW9ucyIsIHggPSAiRGlmZmVyZW5jZSBpbiBQcm9wb3J0aW9ucyIsIHkgPSAiQ291bnQiKQ0KYGBgDQpgYGB7ciBQZXJjZW50aWxlIG1ldGhvZCAzfQ0KI2MoMC4wMjUsMC45NzUpIGNhcHR1cmVzIGNlbnRlciA5NSUgd2hpbGUgbGVhdmluZyAyLjUlIG9mZiBib3RoIGVuZHMNCmNpX3Byb3AgPC0gcXVhbnRpbGUoYm9vdHN0cmFwX2RpZmYkZGlmZl9wcm9wLCBwcm9icyA9IGMoDQogIDAuMDI1LCAwLjk3NQ0KICApKQ0KDQpwcmludChjaV9wcm9wKQ0KYGBgDQpgYGB7ciBzdGFuZGFyZCBlcnJvciBtZXRob2QgM30NCmNpX3Byb3Bfc2UgPC0gYygNCiAgbG93ZXIgPSBtZWFuX2RpZmZfcHJvcCAtIDEuOTYgKiBzZV9kaWZmX3Byb3AsDQogIHVwcGVyID0gbWVhbl9kaWZmX3Byb3AgKyAxLjk2ICogc2VfZGlmZl9wcm9wDQogICkNCg0KcHJpbnQoY2lfcHJvcF9zZSkNCmBgYA0KYGBge3IgVGhlb3JldGljYWwgTWV0aG9kIDN9DQpwcm9wX2NpX3RoZW9yIDwtIGMoDQogIGxvd2VyID0gbWVhbl9kaWZmX3Byb3AgLSBxbm9ybSgwLjk3NSkgKiBzZV9kaWZmX3Byb3AsDQogIHVwcGVyID0gbWVhbl9kaWZmX3Byb3AgKyBxbm9ybSgwLjk3NSkgKiBzZV9kaWZmX3Byb3ANCikNCg0KcHJpbnQocHJvcF9jaV90aGVvcikNCmBgYA0KI0Fuc3dlcjogU2VlaW5nIHRoYXQgdGhlIG51bWJlcnMgcmFuZ2UgZnJvbSBhYm91dCAwLjU5IHRvIDAuNzIsIG1lYW5zIHRoYXQgd2UgY2FuIGJlIDk1JSBjb25maWRlbnQgdGhhdCB0aGUgcHJvcG9ydGlvbiBmb3IgZ2xvYmFsIGJveCBlYXJuaW5ncyBleGNlZWRpbmcgYnVkZ2V0IHdpbGwgZmFsbCB3aXRoaW4gdGhpcyBpbnRlcnZhbC4gVGhlIGRpc3RyaWJ1dGlvbiBhcHBlYXJzIHRvIGhhdmUgYSBzbGlnaHQgbGVmdC1za2V3Lg0KDQojNCBUaGUgY29uZmlkZW5jZSBpbnRlcnZhbCwgb2YgdGhlIGRpZmZlcmVuY2Ugb2YgcHJvcG9ydGlvbnMgb2YgbW92aWVzIHdob3NlIGdsb2JhbCBib3ggb2ZmaWNlIGVhcm5pbmdzIGV4Y2VlZHMgYnVkZ2V0IGJldHdlZW4gbW92aWVzIHJlbGVhc2VkIGZyb20gMTk4MCB0byAxOTk5IGFuZCB0aG9zZSByZWxlYXNlZCBmcm9tIDIwMDAgYW5kIDIwMTgNCiN1c2luZyBkYXRhIG9idGFpbmVkIGluIHBhcnQgMyBvZiB0aGlzIGxhYiwgSSBhZGp1c3RlZCBpdCB0byANCmBgYHtyIENvbmZpZGVuY2UgSW50ZXJ2YWwgQm9vdHN0cmFwIERpc3RyaWJ1dGlvbiA0fQ0KcHJvcF9zdHJhcF9kaWZmIDwtIGJvb3RzdHJhcF9zYW1wbGVzICU+JQ0KICBncm91cF9ieShyZXBsaWNhdGUpICU+JQ0KICBzdW1tYXJpemUoDQogICAgcHJvcF9leGNfMTk4MF8xOTk5ID0gbWVhbihpZmVsc2UoWWVhciA+PSAxOTgwICYgWWVhciA8PSAxOTk5ICYgIWlzLm5hKFdvcmxkd2lkZV9Hcm9zcyksIFdvcmxkd2lkZV9Hcm9zcyA+IEJ1ZGdldCwgTkEpLCBuYS5ybSA9IFRSVUUpLA0KICAgIHByb3BfZXhjXzIwMDBfMjAxOCA9IG1lYW4oaWZlbHNlKFllYXIgPj0gMjAwMCAmIFllYXIgPD0gMjAxOCAmICFpcy5uYShXb3JsZHdpZGVfR3Jvc3MpLCBXb3JsZHdpZGVfR3Jvc3MgPiBCdWRnZXQsIE5BKSwgbmEucm0gPSBUUlVFKQ0KICApICU+JQ0KICBtdXRhdGUoDQogICAgZGlmZl9wcm9wMiA9IHByb3BfZXhjXzIwMDBfMjAxOCAtIHByb3BfZXhjXzE5ODBfMTk5OQ0KICApDQoNCm1lYW5fZGlmZl9wcm9wMiA8LSBtZWFuKHByb3Bfc3RyYXBfZGlmZiRkaWZmX3Byb3AyKQ0Kc2VfZGlmZl9wcm9wMiA8LSBzZChwcm9wX3N0cmFwX2RpZmYkZGlmZl9wcm9wMikNCg0KZ2dwbG90KHByb3Bfc3RyYXBfZGlmZiwgYWVzKHggPSBkaWZmX3Byb3AyKSkgKw0KICBnZW9tX2hpc3RvZ3JhbShiaW53aWR0aCA9IDAuMDEsIGNvbG9yID0gImJsYWNrIiwgZmlsbCA9ICJsaWdodGJsdWUiKSArDQogIGxhYnModGl0bGUgPSAiQm9vdHN0cmFwIERpc3RyaWJ1dGlvbiBvZiBEaWZmZXJlbmNlIGluIFByb3BvcnRpb25zIGJldHdlZW4gMTk4MC0xOTk5IGFuZCAyMDAwLTIwMTgiLCB4ID0gIkRpZmZlcmVuY2UgaW4gUHJvcG9ydGlvbnMgYmV0d2VlbiAxOTgwLTE5OTkgYW5kIDIwMDAtMjAxOCIsIHkgPSAiQ291bnQiKQ0KYGBgDQpgYGB7ciBQZXJjZW50aWxlIG1ldGhvZCA0fQ0KI2MoMC4wMjUsMC45NzUpIGNhcHR1cmVzIGNlbnRlciA5NSUgd2hpbGUgbGVhdmluZyAyLjUlIG9mZiBib3RoIGVuZHMNCmNpX3Byb3AyIDwtIHF1YW50aWxlKHByb3Bfc3RyYXBfZGlmZiRkaWZmX3Byb3AyLCBwcm9icyA9IGMoDQogIDAuMDI1LCAwLjk3NQ0KICApKQ0KDQpwcmludChjaV9wcm9wMikNCg0KYGBgDQpgYGB7ciBzdGFuZGFyZCBlcnJvciBtZXRob2QgNH0NCmNpX3Byb3Bfc2UyIDwtIGMoDQogIGxvd2VyID0gbWVhbl9kaWZmX3Byb3AyIC0gMS45NiAqIHNlX2RpZmZfcHJvcDIsDQogIHVwcGVyID0gbWVhbl9kaWZmX3Byb3AyICsgMS45NiAqIHNlX2RpZmZfcHJvcDINCiAgKQ0KDQpwcmludChjaV9wcm9wX3NlMikNCmBgYA0KYGBge3IgVGhlb3JldGljYWwgTWV0aG9kIDR9DQpwcm9wX2NpX3RoZW9yMiA8LSBjKA0KICBsb3dlciA9IG1lYW5fZGlmZl9wcm9wMiAtIHFub3JtKDAuOTc1KSAqIHNlX2RpZmZfcHJvcDIsDQogIHVwcGVyID0gbWVhbl9kaWZmX3Byb3AyICsgcW5vcm0oMC45NzUpICogc2VfZGlmZl9wcm9wMg0KKQ0KDQpwcmludChwcm9wX2NpX3RoZW9yMikNCmBgYA0KI0Fuc3dlcjogT2JzZXJ2aW5nIHRoZSBkaWZmZXJlbnQgY29uZmlkZW50IGludGVydmFsIHZhbHVlcywgcmFuZ2luZyBmcm9tIGFwcHJveCAtMC4wNDYgdG8gMC4zMTQgb3IgYXMgaW4gdGhlIHBlcmNlbnRpbGUgbWV0aG9kOiAtMC4wNDggdG8gMC4zMTYuIFNpbmNlIHplcm8gaXMgaW5jbHVkZWQgd2l0aGluIGFsbCBpbnRlcnZhbHMsIGF0IHRoZSA5NSUgY29uZmlkZW5jZSBsZXZlbCwgaXQgY2FuIGJlIHN0YXRlZCB0aGF0IHRoZXJlIGlzIG5vIHN0YXRpc3RpY2FsbHkgc2lnbmlmaWNhbnQgZGlmZmVyZW5jZSBiZXR3ZWVuIGJvdGggdGltZSBwZXJpb2RzIGZyb20gKDE5ODAtMTk5OSB0byAyMDAwLTIwMTgpLg0KDQoNCg==