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