1. Refer to Question 11 from Assignment 1:
  1. Compute the probability that another random sample of the same size will produce a sample mean that is at least the same value as the value of X¯¯¯¯ you observed in Question 11 of Assignment 1.

R./ since we know it is a normal distribution and we know the mean of the sample of 12 is 5.6875, the population mean is 5.0 and the sample sd we can use pnorm to calculate the probability of getting another sample of 12 with the same mean. We need to subtract the probability we found from 1 and that is the probability of sampling another 12 deliveries that will have the same mean of 5.6875 –> 0.0562

p5.68 = pnorm(5.6875, 5.0, (1.5/sqrt(12)))
patleast5.68 = 1 - p5.68
patleast5.68
[1] 0.0561756
  1. Refer to the value of the sample standard deviation S (which you computed in Exercise 11 of Assignment 1): Compute the probability that another random sample (again, of the same size) will yield a sample standard deviation that is between 0.5 hour and 1 hour. R./ P(0.5 < SD < 1) = P (sd = 1) - P(SD=0.5) Using Chi-square P(SD=0.5) = P(110.5 / (1.5/sqrt(12))) = P(12.701) = pchisq(12.701, 11) = 0.6867 P(SD=1) = P(111 / (1/sqrt(12))) = P(38.105) = pchisq(38.105) = 0.9999 P(0.5 < SD < 1) = 0.9999 - 0.6867 = 0.3132
Xsq0.5 = (11*0.5 / (1.5/sqrt(12)))
P0.5 = pchisq(Xsq0.5, 11)
P0.5
[1] 0.686732
Xsq1 = (11*1 / (1/sqrt(12)))
P1 = pchisq(Xsq1, 11)
P1
[1] 0.9999249
P = P1 - P0.5
P
[1] 0.3131929
  1. A 2012 poll carried out by Ipsos Reid in found that “42% of Canadians, who live outside of Quebec, believe Quebec will separate from Canada at some point in the future.” A pollster wishes to see if this sentiment is still present for Canadians who live outside of the province of Quebec.
  1. The pollster has determined that they are going to randomly sample n=1426 Canadian residents who are not residents of Quebec in an attempt to estimate p - the proportion of all Canadians who live outside of Quebec (“Rest of Canada”) - who believe that Quebec will separate from Canada within the next 10 years. Describe the distribution of pˆ, the proportion of n=1426 randomly chosen Canadians who live outside of Quebec who believe Quebec will separate from Canada within the next 10 years. (Ensure that your description provides a (i) distribution shape (ii) a balancing point and (iii) a measure of spread.)

R./ The distribution is bell shaped The balancing point correspond to the population mean (0.42) The standard deviation is 0.01307

x = seq(300, 800, 0.1)
phat = (x/1426)
sdphat = sqrt(0.42*(1-0.42) / 1426)
sdphat
[1] 0.0130701
plot(phat, dnorm(phat, 0.42, sdphat), yaxt = 'n', xlab="Values of the Sample Proportion", ylab = "Density", main="Distribution of Sample Proportion from n = 1426", type="h", col='blue') + abline(v=0.42, col="blue")
integer(0)

  1. A recent poll of n=1426 Canadians who are not residents of Quebec was taken. Of these, 541 thought that Quebec will separate from Canada in the next 10 years (356 indicated “might happen”; 128 responded “likely to happen”; 57 indicated “definitely will happen”). The sample proportion is computed to be pˆ=5411426=0.3794. Under the condition of the 2012 poll result, how likely is it for another random sample of n=1426 Canadians (who reside outside of Quebec) to produce a sample proportion that is at most as 0.3794?

R./ I calculated the sd for the sample proportion, I used pnorm() to find the probability of getting another sample with a sample proportion of at most 0.3794 is 0.0009471

sdphat = sqrt(0.42*(1-0.42) / 1426) #calculate phat for this sample
sdphat
[1] 0.0130701
pless037 = pnorm(0.3794, mean=0.42, sd=sdphat)
pless037
[1] 0.000947136
  1. Consider the steps and associated R Code required to generate a distribution of the sample proportion, pˆ, when sampling n=1426 Canadians who live outside of Quebec, then determining the proportion who believe Quebec will separate from Canada within the next 10 years. Carry out a simulation where you simulate 1000 random samples of n=1426. Create, then run your code to determine the proportion of your pˆs that are less than or equal to 0.3794. Provide this proportion.

R./ After running the simulation, I found that the proportion of phats is 0.001. This proportion changes every time the simulation is run, I have gotten values from 0 to 0,004

nsamples = 1000  #no. of simulations
sample.phat = numeric(nsamples) #data vector to hold 1000 sample standard deviations of n = 5
size = 1426
s1426data = rbinom(1,size,0.42) #As described https://www.programmingr.com/examples/neat-tricks/sample-r-function/r-rbinom/
counter = 0

for(i in 1:nsamples){
  s1426data = rbinom(1,size,0.42) #simulates a binary sample with p = 0.42
  sample.phat[i] = s1426data/size #compute the phat of the sample of 1426
  if (sample.phat[i] < 0.3794){
      counter = counter + 1
  }
}

sample.phat[1:5]
[1] 0.4460028 0.4354839 0.3997195 0.4137447 0.4039271
sample.phat[995:999]
[1] 0.4235624 0.4004208 0.4417952 0.4130435 0.3920056
pphatless037 = counter/nsamples
pphatless037
[1] 0.001
  1. Billy purchases one 6-49 lottery ticket every week and keeps track of the number of “matches” he has on each of his tickets. To be clear, a “match” will occur when a number on his ticket matches a number that appears in the winning combination. A random variable X that keeps track of the number of matching numbers Billy experiences per week has the probability distribution function with a mean and standard deviation of P(X=x) = choose (6, x) * choose(43, 6−x) / choose(49, 6) x=0,1,2,3,4,5,6. E(X) = μX = 36 / 49 = 0.7347 SD(X) = σX = 0.75998 ≈ 0.76 Billy claims that in a year (52 weeks), on average, he manages to have at least one matching number on his 6-49 ticket. What do you think about Billy’s claim? Provide a brief commentary about Billy’s claim using your current knowledge of statistics and probability theory.

R./ The probability of getting at least one matching number is equal to 1 minus the probability of no getting any number or P(x=0)

P(x >= 1) = 1 - P(x = 0) we obtain P(0) by replacing x with 0 in the probability function P(X=0) = choose (6, 0) * choose(43, 6−0) / choose(49, 6) P(X=0) = 0.4360

replacing this value P(X >= 1) = 1 - 0.4360 P(X >= 1) = 0.5640

R./ The probability of getting at least one matching number in 52 draws ( one draw / week) is 0.564 which is greater that the probability of getting no matching numbers which is 0.436. It is possible that Billy does get at least one matching number every week for a year.

P0 = choose (6, 0) * choose(43, 6) / choose(49, 6) 
P0
[1] 0.435965
Pmore1 = 1 - P0
Pmore1
[1] 0.564035
  1. A common measure of toxicity for any pollutant is the concentration of the pollutant that will kill half of the test species in a given amount of time (usually about 96 hours for the fish species). This measurement is called the LC50, which refers to the lethal concentration killing 50% of the test species).

The Environmental Protection Agency has collected data on LC50 measurements for certain chemicals likely to be found in freshwater and lakes. For a certain species of fish, the LC50 measurements (in parts per million) for DDT in 12 experiments to determine the LC50 “dose” are 16,5,21,19,10,5,8,2,7,2,4,9

  1. Use R studio to create the bootstrap distribution of the sample mean X¯¯¯¯Boot,LC50. Use 2000 “bootstraps” in your work, and display the distribution.

R./ As follows

# library(mosaic)
library(ggplot2)
library(lattice)
lc50 = c(16,5,21,19,10,5,8,2,7,2,4,9)  #create a vector with the values of LC50
lc50.df = data.frame(lc50)  # convert the above vector into a dataframe
lc50.df
ntimes = 100
bootdata = numeric(length(lc50.df$lc50)*ntimes)
for(i in 1:ntimes)
{  if (i == 1) bootdata = lc50.df$lc50
   else bootdata = c(lc50.df$lc50, bootdata)
}

N = 2000
n.size = length(lc50.df$lc50)
boot.mean = numeric(N)
boot.data = numeric(n.size)
#
for(i in 1:N){
  
  boot.data = sample(lc50.df$lc50, n.size, replace=TRUE) #sample with replacement 
  boot.mean[i] = mean(boot.data)
}
bootstrap.mean = data.frame(boot.mean) #data frame holding 2000 different bootstrap sample means
head(bootstrap.mean, 4)
NA
tail(bootstrap.mean, 4)
ggplot(bootstrap.mean, aes(x = boot.mean)) + geom_histogram(col="red", fill="blue", binwidth = 0.5) + xlab("Values of Bootstrap Mean") + ylab("Count") + ggtitle("Distribution of Bootstrap Statistic: Sample Mean")
favstats(~boot.mean, data=bootstrap.mean)
  1. From your result in (a), compute the 95% bootstrap (percentile) confidence interval for \(\mu_{LC50}\), the mean LC50 measurement for DDT.

R./ using qdata() on the list of means and then displaying the distribution with the values for p25 ans p97.5 which are 5.75 and 12.5

p25.lc50 = qdata(~boot.mean, c(0.025, 0.975), data=bootstrap.mean)[1]
p25.lc50[1]
2.5% 
5.75 
p975.lc50 = qdata(~boot.mean, c(0.025, 0.975), data=bootstrap.mean)[2]
p975.lc50
97.5% 
 12.5 
ggplot(bootstrap.mean, aes(x = boot.mean)) + geom_histogram(col="red", fill="blue", binwidth = 0.5) + xlab("Values of Bootstrap Mean") + ylab("Count") + ggtitle("Distribution of Bootstrap Statistic: Sample Mean with 95% confidence Interval ") + geom_vline(xintercept = p25.lc50, color="red") + geom_vline(xintercept = p975.lc50, color="red")

  1. Repeat your estimation of \(\mu_{LC50}\), using the “other” confidence interval covered in Data 602. In the context of these data, interpret the meaning of the confidence interval. State any conditions/assumptions that are required in the computation of this confidence interval.

R./Using Student’s T we found P2.5 = 4.9181 and P97.5 = 13.0819

Ttest.lc50 = t.test(~lc50, data=lc50.df)$conf #using default value of 0.95 confidence interval 
Ttest.lc50[1]
[1] 4.91814
Ttest.lc50[2]
[1] 13.08186
  1. Compare your results in parts (b) and (c). If you were to report one of these confidence intervals, which would you report? Explain your answer.

R./ Bootstrap for CI95 = (5.75, 12.58) (red in the graph) Student’s T for CI95 = (4.9181, 13.0817) (blue in the graph) To be on the safer side, I want to report a tighter interval so I prefer the interval from Bootstrap

ggplot(bootstrap.mean, aes(x = boot.mean)) + geom_histogram(col="red", fill="blue", binwidth = 0.5) + xlab("Values of Bootstrap Mean") + ylab("Count") + ggtitle("Distribution of Bootstrap Statistic: Sample Mean with 95% confidence Interval ") + geom_vline(xintercept = p25.lc50, color="red") + geom_vline(xintercept = p975.lc50, color="red") + geom_vline(xintercept = Ttest.lc50[1], color="blue") + geom_vline(xintercept = Ttest.lc50[2], color="blue")

  1. Does one’s educational level influence their opinion about vaccinations? A recent Angus Reid2 survey was taken. Each person sampled was asked to respond to the statement “The science around vaccinations isn’t clear.”

Respondents either “strongly agree”, “moderately agree”, “moderately disagree”, or “strongly disagree”. The sample was partitioned by level of education.

There were n=670 respondents who’s highest level of education was high school or less, of which 348 “disagreed” (moderately disagree or stongly disagree). There were also n=376 who’s highest level of education was at least an undergraduate university education. Of these, 274 disagreed.

  1. Consider the population consisting of all persons, who’s highest level of education was high school or less and the bootstrap statistic pˆBoot,HS . Using 1000 iterations/replications, create a bootstrap distribution of pˆHS . Display your distribution.

R./ From the information given we can calculate pHS = 348 / 670 = 0.52. I use this proportion to create a random list of zeros(agreed) and ones (disagree). I then use this list to create a table that allows me to see the amount of zeros and ones in the list. Next I loop 1000 times to create a sample from the list I created with the size of 670 and replacement = true. The mean of the sample is then calculated and stored in an array called phats.hs; then I create a data frame from the phats.hs list and displayed its histogram

library(binom)
hs = rbinom(n=670,size=1,prob=0.52)
table(hs)
hs
  0   1 
343 327 
phats.hs = numeric(1000) #create a vector to store each of the 1000 bootstrap values of the sample proportion
for(i in 1:1000){
      temp.data = sample(hs, length(hs), replace=TRUE) #could have used resample(userofmari) here
      phats.hs[i] = mean(temp.data)
}
boot_phat_hs.df = data.frame(phats.hs)
head(boot_phat_hs.df, 4)
tail(boot_phat_hs.df, 4)
tail(boot_phat_hs.df, 4)
ggplot(boot_phat_hs.df, aes(x = phats.hs)) + geom_histogram(col="green", fill="blue", binwidth=0.01) + xlab("Values of the Sample Proportion") + ylab("Count") + ggtitle("Histogram: Distribution of Bootstrap Sample Proportion")

  1. Now consider a different population that consist of all persons who’s highest level of education was at least an undergraduate degree. Repeat part (a), creating a bootstrap distribution for pˆBoot,Uni. (Again, display your distribution).

R./ From the information given we can calculate pUni= 274 / 376 = 0.73. I use this proportion to create a random list of zeros(agreed) and ones (disagree). I then use this list to create a table that allows me to see the amount of zeros and ones in the list. Next I loop 1000 times to create a sample from the list I created with the size of 376 and replacement = true. The mean of the sample is then calculated and stored in an array called phats.uni; then I create a data frame from the phats.uni list and displayed its histogram

uni = rbinom(n=376,size=1,prob=0.73)
table(uni)
uni
  0   1 
108 268 
phats.uni = numeric(1000) 
for(i in 1:1000){
      temp.data = sample(uni, length(uni), replace=TRUE) 
      phats.uni[i] = mean(temp.data)
}
boot_phat_uni.df = data.frame(phats.uni)
head(boot_phat_uni.df, 4)
tail(boot_phat_uni.df, 4)
tail(boot_phat_uni.df, 4)
ggplot(boot_phat_uni.df, aes(x = phats.uni)) + geom_histogram(col="green", fill="blue", binwidth=0.01) + xlab("Values of the Sample Proportion") + ylab("Proportion") + ggtitle("Histogram: Distribution of Bootstrap Sample Proportion") 

  1. You wish to estimate pUni−pHS, the difference between the proportion of all university-educated Canadians who disagree that the science of vaccinations isn’t clear and the proportion of all Canadians who’s highest level of completed education is high school who believe the same. You wish to have 95% confidence in your result. Think about the code you created to generate the bootstrap distributions on parts (a) and (b). Modify the code to you created in parts (a) and (b) to create a distribution of the bootstrap statistic pˆUni−pˆHS.

R./ As follows

phats.uni_hs = numeric(1000) 
for(i in 1:1000){
    temp.data.hs = sample(hs, length(hs), replace=TRUE) #could have used resample(userofmari) here
    temp.data.uni = sample(uni, length(uni), replace=TRUE)  
    phats.uni_hs[i] = mean(temp.data.uni) - mean(temp.data.hs)
}
boot_phat_uni_hs.df = data.frame(phats.uni_hs)
head(boot_phat_uni_hs.df, 4)
tail(boot_phat_uni_hs.df, 4)
tail(boot_phat_uni_hs.df, 4)
  1. Consider your finding in part (c). Compute the 95% bootstrap percentile confidence interval for pUni−pHs. From your result, does the proportion of persons with at most a high school education who disagree the science around vaccinations isn’t clear greater than the similar proportion of persons with at least an undergraduate university degree? Write a paragraph that supports your answer.

R./ The proportion of people with a level of education higher than high school who disagree the science around vaccination isn’t clear is greater than the proportion of people with a level of education equal or less than high school. This is evident by the fact that the distribution of the simulation of pUni−pHs yields values that are greater than 0. The 95% confidence interval shows that most of the values for this difference falls between 16.68% and 28.32% in favor of people with higher education than high school.

p25.uni_hs = qdata(~phats.uni_hs, c(0.025, 0.975), data=boot_phat_uni_hs.df)[1]
p25.uni_hs
     2.5% 
0.1667625 
p975.uni_hs = qdata(~phats.uni_hs, c(0.025, 0.975), data=boot_phat_uni_hs.df)[2]
p975.uni_hs
    97.5% 
0.2831919 
ggplot(boot_phat_uni_hs.df, aes(x = phats.uni_hs)) + geom_histogram(col="green", fill="blue", binwidth=0.01) + xlab("Values of the Sample Proportion") + ylab("Count") + ggtitle("Histogram: Distribution of Bootstrap Sample Proportion") + geom_vline(xintercept = p25.uni_hs, color="red") + geom_vline(xintercept = p975.uni_hs, color="red")

  1. Nanos research3 recently completed a survey of n=1000 Canadians aged 18 years of age or older, asking each “what is your most important national issue of concern?” 163 responded “Inflation”, 149 responded “Environment”, 131 responded “Jobs/Economy”. Those were the Top Three.
  1. Compute a 95% confidence interval for pInflation, the proportion of all Canadians aged 18 years or older for whom “Inflation” is the most important national concern.

R./I can calculate the 95% confidence interval using the plus-2/plus-4 which gives us 0.1427(p2.5) - 0.1885(p97.5)

prop.test(163 + 2, 1000 + 4, correct=FALSE)$conf
[1] 0.142707 0.188537
attr(,"conf.level")
[1] 0.95
  1. Similar to your work in Question 4(b), create the distribution of the bootstrap statistic pˆBoot,Inflation and a 95% bootstrap percentile confidence interval for pInflation.

R./ Confidence interval 95% = 0.144 - 0.188

infl = rbinom(n=1000,size=1,prob=0.163)
infl.df = data.frame(infl)
head(infl.df, 4)
tail(infl.df)
N = 1000
n.size = length(infl.df$infl)
boot.proportion_infl = numeric(N)
boot.data_infl = numeric(n.size)


for(i in 1:N){
  
  boot.data_infl = sample(infl.df$infl, n.size, replace=TRUE) #sample with replacement 
  boot.proportion_infl[i] = mean(boot.data_infl)
}
bootstrap.proportion_infl = data.frame(boot.proportion_infl) #data frame holding 2000 different bootstrap sample means
head(bootstrap.proportion_infl, 4)
NA
tail(bootstrap.proportion_infl, 4)
p2.5Infl = qdata(~boot.proportion_infl, c(0.025, 0.975), data = bootstrap.proportion_infl)[1]
p2.5Infl
 2.5% 
0.143 
p97.5Infl = qdata(~boot.proportion_infl, c(0.025, 0.975), data = bootstrap.proportion_infl)[2]
p97.5Infl
97.5% 
0.191 
ggplot(bootstrap.proportion_infl, aes(x = boot.proportion_infl)) + geom_histogram(col="green", fill="blue", binwidth=0.005) + xlab("Values of the Sample Proportion") + ylab("Count") + ggtitle("Histogram: Distribution of Bootstrap Sample Proportion") + geom_vline(xintercept = p2.5Infl, color="red") + geom_vline(xintercept = p97.5Infl, color="red")

  1. A similar survey of Canadians in August 2023 - a little over a month ago - suggested that the proportion of all Canadians who identified “Inflation” as the most important national concern was pInflation,Aug_23=0.13 From your results in (a) and (b), can you infer that the proportion of all Canadians who believe “Inflation” is the most important national issue has increased since August of this year? Why or why not? Ensure you invoke a statistical justification.

R./ I can infer that the proportion of Canadians who believe inflation is the most important issue has increased based on the fact that the Confidence Interval for the most recent survey goes from 14.4 to 18.8; there is no overlap with the previous value of 0.13 found in the previous survey, showing us that the proportion has increased

  1. Refer to the data encountered in Question 4 of this assignment. Prior to completing parts (a) and (b), carefully read through both parts (a) and (b).
  1. Use the Bootstrap method to compute a 98% confidence interval for μ˜LC50, the median LC50 level. Interpret the meaning of this interval in the context of these data.

R./ I will proceed to simulate the median with N=2000,and then calculate the 98% confidence Interval using qdata for the 1% and 99%. Finally I will graph these results. Confidence Interval 99% = (4, 16) We can say that there is a 98% probability that the median value for DDT LC50 is between 4 and 16 ppm

N = 2000
n.size = length(lc50.df$lc50)
boot.median = numeric(N)
boot.data = numeric(n.size)


for(i in 1:N){
  
  boot.data = sample(lc50.df$lc50, n.size, replace=TRUE) #sample with replacement 
  boot.median[i] = median(boot.data)
}

bootstrap.median = data.frame(boot.median) #data frame holding 2000 different bootstrap sample medians
head(bootstrap.median, 4)
tail(bootstrap.median, 4)
lc50.median_99 = qdata(boot.median, c(0.01, 0.99), data=bootstrap.median)
lc50.median_99
 1% 99% 
  4  16 
ggplot(bootstrap.median, aes(x = boot.median)) + geom_histogram(col="red", fill="blue", binwidth=0.8) + xlab("Values of the Sample Median") + ylab("Count") + ggtitle("Histogram: Distribution of Bootstrap Sample Median") + geom_vline(xintercept = lc50.median_99[1], color="green") + geom_vline(xintercept = lc50.median_99[2], color="green")

  1. Compute the 95% bootstrap percentile confidence interval for the population standard deviation, σ. In addition, interpret the meaning of your interval in the context of these data.

R./ For this question, I will find the confidence interval for the variance first and then take the sq root of these results are thw data for the 95% confidence interval for the sd: (3.1712, 7.8607)

We can say that there is a 95% probability that the standard deviation value for DDT LC50 is between 3.1281 and 7.9183 ppm

N = 2000
n.size = length(lc50.df$lc50)
boot.var = numeric(N)
boot.data = numeric(n.size)


for(i in 1:N){
  
  boot.data = sample(lc50.df$lc50, n.size, replace=TRUE) #sample with replacement 
  boot.var[i] = var(boot.data)
}

bootstrap.var = data.frame(boot.var) #data frame holding 2000 different bootstrap sample variance
head(bootstrap.var, 4)
tail(bootstrap.var, 4)
lc50.var_95 = qdata(boot.var, c(0.025, 0.975), data=bootstrap.var)
lc50.var_95
    2.5%    97.5% 
10.05682 61.79072 
ggplot(bootstrap.var, aes(x = boot.var)) + geom_histogram(col="red", fill="blue", binwidth=1) + xlab("Values of the Sample Variance") + ylab("Count") + ggtitle("Histogram: Distribution of Bootstrap Sample Variance") + geom_vline(xintercept = lc50.var_95[1], color="green") + geom_vline(xintercept = lc50.var_95[2], color="green")

lc50.sd_95 = sqrt(lc50.var_95)
lc50.sd_95
    2.5%    97.5% 
3.171249 7.860707 
  1. A national survey 4 of n=399 “Gen Z”-ers - someone who is born in the years 1996 - 2010 (inclusive) was taken. Each was then asked the following question: “If a federal election were held tomorrow, which one of the following parties would you vote for in your constituency?” The results?

128 responded “Conservative” (Conservative Party of Canada) 96 responded “Liberal” (Liberal Party of Canada) 104 responded “NDP” (New Democratic Party of Canada) Respondents were provided with a few more “closed options”, including the Bloc Quebecois, People’s Party, and Green Party.

  1. Compute the 95% confidence interval for pCon, the proportion of all Gen Z-ers in Canada that will vote for their respective Conservative Member of Parliament candidate/constituency, in an election were “held tomorrow”.

R./ Since we know n and nconservative, we cam use prop.test() to determine the confidence interval using its default 95% and the plus-2/plus-4 to make the interval tighter. Pcons 95% CI = (0.2788,0.3697 ) According to these results we can say with a 95% confidence that between 27.88 and 36.97 % of Gen Z-ers will vote conservative.

ci95con.prop = prop.test(128+2, 399+4, correct=FALSE)$conf
ci95con.prop
[1] 0.2788012 0.3697105
attr(,"conf.level")
[1] 0.95
  1. Consider the bootstrap statistic p˜Con=XCon+2399+4 . Write the R code that will generate a bootstrap distribution for p˜Con . Use 1000 as the number of replications/iterations.
nsamples = 1000  #no. of simulations
sample.phat_con = numeric(nsamples) #data vector to hold 1000 samples representing the gen z-ers that choose conservative
size = 399

for(i in 1:nsamples){
  boot.data = rbinom(1,size,0.32) #simulates a binary sample representing the genz-ers that choose conservative knowing Pcon = 128/399 = 0.33
  sample.phat_con[i] = (boot.data + 2)/(size +4) #compute the phat using plus2/plus4 and stores it in the sample.phat_con list
}

bootstrap.con = data.frame(sample.phat_con)
head(bootstrap.con, 4)
tail(bootstrap.con, 4)
  1. From your result in part (b), compute a 95% bootstrap confidence interval for pCon.
ci95con.boot = qdata(~sample.phat_con, c(0.025, 0.975), data=bootstrap.con)
ci95con.boot
     2.5%     97.5% 
0.2779156 0.3622829 
ggplot(bootstrap.con, aes(x = sample.phat_con)) + geom_histogram(col="green", fill="blue", binwidth=0.05) + xlab("Values of the Sample Proportion") + ylab("Count") + ggtitle("Histogram: Distribution of Bootstrap Sample Proportion") + geom_vline(xintercept = ci95con.prop[1], color="red") + geom_vline(xintercept = ci95con.prop[2], color="red") + geom_vline(xintercept = ci95con.boot[1], color="purple") + geom_vline(xintercept = ci95con.boot[2], color="purple")

  1. Consider your results in parts (a) and (c). Compare the two results. If you had to pick one as the “best” estimate for the unknown value of pCon, which one would you select? Provide a justification for your choice.

R./ from a) CI95.prop = (0.2788, 0.3647) –> 0.3647 - 0.2788 = 0.0909 (red) b) CI95.boot = (0.2779, 0.3628) –> 0.3697 - 0.2754 = 0.0849 (purple)

     These intervals are very close, if I have to choose one, I choose the one with the smaller interval which in this case is the interval found by running boostrap
  1. In this question you will use the albertacountiessampled2019.csv. The data appearing in this file are the results of a random sample of n=100 counties in Alberta. For each county, the median household income was computed. This feature appears in the OriginalValue column.

Read this data into a R data frame. To read this into R, you will have to select the Raw tab appearing on the top right-hand side.

The bootstrap t statistic is defined as TBootstrap=X¯¯¯¯Boot−X¯¯¯¯(Sn√) where X¯¯¯¯ and S are the mean and standard deviation of the sample.

  1. From these data, generate the distribution of TBootstrap. Display this distribution. Use 1000 for the number of bootstraps.
alberta.counties = read.csv("albertacountiessampled2019.csv")
income.median = data.frame(alberta.counties$OriginalValue)
head(income.median, 4)
tail(income.median, 4)
stats = favstats(income.median$alberta.counties.OriginalValue)
stats
sample.mean = stats[6]
sample.mean
sample.sd = stats[7]
sample.sd
N = 1000
sample.size = length(income.median$alberta.counties.OriginalValue)
boot.data = numeric(sample.size)
boot.mean = numeric(N)
boot.t = numeric(N)

for (i in 1:N){
  boot.data = sample(alberta.counties$OriginalValue, sample.size, replace = TRUE)
  boot.mean[i] = mean(boot.data)
  t = (boot.mean[i] - sample.mean) / (sample.sd / sqrt(sample.size))
  t
  boot.t[i] = t
}

boot.meandf = data.frame(boot.mean)
head(boot.meandf)
tail(boot.meandf)
boot.tval = c(N)
for(i in 1:N){
  boot.tval[i] = boot.t[[i]][1]
}

boot.tdf = data.frame(boot.tval)
head(boot.tdf)
NA
tail(boot.tdf)
ggplot(boot.tdf, aes(x = boot.tval)) + geom_histogram(col="red", fill="blue", binwidth=0.4) + xlab("Values of Bootstrat T") + ylab("Count") + ggtitle("Histogram: Distribution of Bootstrap T")

  1. Refer to part (a): A Bootstrap t.Confidence Interval for μ is defined as: [X¯¯¯¯−t∗α2(Sn−−√),X¯¯¯¯+t∗1−α2(Sn−−√)] where t∗α2 and t∗1−α2 is are α2 and 1−α2 percentiles from the TBootstrap distribution.

Compute the 95% bootstrap t confidence interval for μMedian_Family_Income for all the counties in Alberta.

Note: −tα2 will be a negative value due to the nature of the Student’s t distribution. Hence the “-” sign in front.

percentileT = quantile(boot.tdf$boot.tval, c(0.025, 0.975))
percentileT
     2.5%     97.5% 
-2.058206  1.842106 
meanCI2.5 = sample.mean - (percentileT[1] * (sample.sd/sqrt(sample.size)))
meanCI2.5$mean
[1] 92128.91
meanCI97.5 = sample.mean - (percentileT[2] * (sample.sd/sqrt(sample.size)))
meanCI97.5$mean
[1] 83239.22
  1. Compute the (i) 95% bootstrap percentile confidence interval estimate of μMedian_Family_Income and (ii) the 95% Student’s t confidence interval for μMedian_Family_Income.
medianIncome.ci95 = qdata(~alberta.counties.OriginalValue, c(0.025, 0.975), data=income.median)
medianIncome.ci95
    2.5%    97.5% 
 34747.5 131119.5 
BootTci95 = qdata(boot.tval, c(0.025, 0.975), data=boot.tdf)
BootTci95
     2.5%     97.5% 
-2.058206  1.842106 

D. Consider your results in parts (b) and (c): If you were to report one of these confidence intervals to a client, what would be your consultation? Provide a short paragraph explaining what the value of μMedian_Family_Income Could possibly be, and why you chose the method of confidence interval estimation to report from.

I would use the 95% Confidence Interval found in part b as it reports a tighter interval for than the one reported in C

  1. 83029.28 - 91911.28
  2. 34747.50 - 131119.50
Ci0tLQp0aXRsZTogIkRBVEE2MDJfQVNTSUdOTUVOVDIiCm91dHB1dDogaHRtbF9ub3RlYm9vawotLS0KMS4gUmVmZXIgdG8gUXVlc3Rpb24gMTEgZnJvbSBBc3NpZ25tZW50IDE6CgphLiBDb21wdXRlIHRoZSBwcm9iYWJpbGl0eSB0aGF0IGFub3RoZXIgcmFuZG9tIHNhbXBsZSBvZiB0aGUgc2FtZSBzaXplIHdpbGwgcHJvZHVjZSBhIHNhbXBsZSBtZWFuIHRoYXQgaXMgYXQgbGVhc3QgdGhlIHNhbWUgdmFsdWUgYXMgdGhlIHZhbHVlIG9mIFjCr8Kvwq/CryB5b3Ugb2JzZXJ2ZWQgaW4gUXVlc3Rpb24gMTEgb2YgQXNzaWdubWVudCAxLgoKUi4vIHNpbmNlIHdlIGtub3cgaXQgaXMgYSBub3JtYWwgZGlzdHJpYnV0aW9uIGFuZCB3ZSBrbm93IHRoZSBtZWFuIG9mIHRoZSBzYW1wbGUgb2YgMTIgaXMgNS42ODc1LCB0aGUgcG9wdWxhdGlvbiBtZWFuIGlzIDUuMCBhbmQgdGhlIHNhbXBsZSBzZCB3ZSBjYW4gdXNlIHBub3JtIHRvIGNhbGN1bGF0ZSB0aGUgcHJvYmFiaWxpdHkgb2YgZ2V0dGluZyBhbm90aGVyIHNhbXBsZSBvZiAxMiB3aXRoIHRoZSBzYW1lIG1lYW4uIFdlIG5lZWQgdG8gc3VidHJhY3QgdGhlIHByb2JhYmlsaXR5IHdlIGZvdW5kIGZyb20gMSBhbmQgdGhhdCBpcyB0aGUgcHJvYmFiaWxpdHkgb2Ygc2FtcGxpbmcgYW5vdGhlciAxMiBkZWxpdmVyaWVzIHRoYXQgd2lsbCBoYXZlIHRoZSBzYW1lIG1lYW4gb2YgNS42ODc1IC0tPiAwLjA1NjIKCmBgYHtyfQpwNS42OCA9IHBub3JtKDUuNjg3NSwgNS4wLCAoMS41L3NxcnQoMTIpKSkKcGF0bGVhc3Q1LjY4ID0gMSAtIHA1LjY4CnBhdGxlYXN0NS42OApgYGAKYi4gUmVmZXIgdG8gdGhlIHZhbHVlIG9mIHRoZSBzYW1wbGUgc3RhbmRhcmQgZGV2aWF0aW9uIFMgKHdoaWNoIHlvdSBjb21wdXRlZCBpbiBFeGVyY2lzZSAxMSBvZiBBc3NpZ25tZW50IDEpOiBDb21wdXRlIHRoZSBwcm9iYWJpbGl0eSB0aGF0IGFub3RoZXIgcmFuZG9tIHNhbXBsZSAoYWdhaW4sIG9mIHRoZSBzYW1lIHNpemUpIHdpbGwgeWllbGQgYSBzYW1wbGUgc3RhbmRhcmQgZGV2aWF0aW9uIHRoYXQgaXMgYmV0d2VlbiAwLjUgaG91ciBhbmQgMSBob3VyLgpSLi8gUCgwLjUgPCBTRCA8IDEpID0gUCAoc2QgPSAxKSAtIFAoU0Q9MC41KQpVc2luZyBDaGktc3F1YXJlClAoU0Q9MC41KSA9IFAoMTEqMC41IC8gKDEuNS9zcXJ0KDEyKSkpID0gUCgxMi43MDEpID0gcGNoaXNxKDEyLjcwMSwgMTEpID0gMC42ODY3ClAoU0Q9MSkgPSBQKDExKjEgLyAoMS9zcXJ0KDEyKSkpID0gUCgzOC4xMDUpID0gcGNoaXNxKDM4LjEwNSkgPSAwLjk5OTkKUCgwLjUgPCBTRCA8IDEpID0gMC45OTk5IC0gMC42ODY3ID0gMC4zMTMyCgpgYGB7cn0KWHNxMC41ID0gKDExKjAuNSAvICgxLjUvc3FydCgxMikpKQpQMC41ID0gcGNoaXNxKFhzcTAuNSwgMTEpClAwLjUKWHNxMSA9ICgxMSoxIC8gKDEvc3FydCgxMikpKQpQMSA9IHBjaGlzcShYc3ExLCAxMSkKUDEKUCA9IFAxIC0gUDAuNQpQCmBgYAoyLiBBIDIwMTIgcG9sbCBjYXJyaWVkIG91dCBieSBJcHNvcyBSZWlkIGluIGZvdW5kIHRoYXQg4oCcNDIlIG9mIENhbmFkaWFucywgd2hvIGxpdmUgb3V0c2lkZSBvZiBRdWViZWMsIGJlbGlldmUgUXVlYmVjIHdpbGwgc2VwYXJhdGUgZnJvbSBDYW5hZGEgYXQgc29tZSBwb2ludCBpbiB0aGUgZnV0dXJlLuKAnSBBIHBvbGxzdGVyIHdpc2hlcyB0byBzZWUgaWYgdGhpcyBzZW50aW1lbnQgaXMgc3RpbGwgcHJlc2VudCBmb3IgQ2FuYWRpYW5zIHdobyBsaXZlIG91dHNpZGUgb2YgdGhlIHByb3ZpbmNlIG9mIFF1ZWJlYy4KCmEuIFRoZSBwb2xsc3RlciBoYXMgZGV0ZXJtaW5lZCB0aGF0IHRoZXkgYXJlIGdvaW5nIHRvIHJhbmRvbWx5IHNhbXBsZSBuPTE0MjYgQ2FuYWRpYW4gcmVzaWRlbnRzIHdobyBhcmUgbm90IHJlc2lkZW50cyBvZiBRdWViZWMgaW4gYW4gYXR0ZW1wdCB0byBlc3RpbWF0ZSBwIC0gdGhlIHByb3BvcnRpb24gb2YgYWxsIENhbmFkaWFucyB3aG8gbGl2ZSBvdXRzaWRlIG9mIFF1ZWJlYyAo4oCcUmVzdCBvZiBDYW5hZGHigJ0pIC0gd2hvIGJlbGlldmUgdGhhdCBRdWViZWMgd2lsbCBzZXBhcmF0ZSBmcm9tIENhbmFkYSB3aXRoaW4gdGhlIG5leHQgMTAgeWVhcnMuIERlc2NyaWJlIHRoZSBkaXN0cmlidXRpb24gb2YgcMuGLCB0aGUgcHJvcG9ydGlvbiBvZiBuPTE0MjYgcmFuZG9tbHkgY2hvc2VuIENhbmFkaWFucyB3aG8gbGl2ZSBvdXRzaWRlIG9mIFF1ZWJlYyB3aG8gYmVsaWV2ZSBRdWViZWMgd2lsbCBzZXBhcmF0ZSBmcm9tIENhbmFkYSB3aXRoaW4gdGhlIG5leHQgMTAgeWVhcnMuIChFbnN1cmUgdGhhdCB5b3VyIGRlc2NyaXB0aW9uIHByb3ZpZGVzIGEgKGkpIGRpc3RyaWJ1dGlvbiBzaGFwZSAoaWkpIGEgYmFsYW5jaW5nIHBvaW50IGFuZCAoaWlpKSBhIG1lYXN1cmUgb2Ygc3ByZWFkLikKIAogUi4vIFRoZSBkaXN0cmlidXRpb24gaXMgYmVsbCBzaGFwZWQKIFRoZSBiYWxhbmNpbmcgcG9pbnQgY29ycmVzcG9uZCB0byB0aGUgcG9wdWxhdGlvbiBtZWFuICgwLjQyKQogVGhlIHN0YW5kYXJkIGRldmlhdGlvbiBpcyAwLjAxMzA3CmBgYHtyfQp4ID0gc2VxKDMwMCwgODAwLCAwLjEpCnBoYXQgPSAoeC8xNDI2KQpzZHBoYXQgPSBzcXJ0KDAuNDIqKDEtMC40MikgLyAxNDI2KQpzZHBoYXQKYGBgCgoKYGBge3J9CnBsb3QocGhhdCwgZG5vcm0ocGhhdCwgMC40Miwgc2RwaGF0KSwgeWF4dCA9ICduJywgeGxhYj0iVmFsdWVzIG9mIHRoZSBTYW1wbGUgUHJvcG9ydGlvbiIsIHlsYWIgPSAiRGVuc2l0eSIsIG1haW49IkRpc3RyaWJ1dGlvbiBvZiBTYW1wbGUgUHJvcG9ydGlvbiBmcm9tIG4gPSAxNDI2IiwgdHlwZT0iaCIsIGNvbD0nYmx1ZScpICsgYWJsaW5lKHY9MC40MiwgY29sPSJibHVlIikKYGBgCiBiLiBBIHJlY2VudCBwb2xsIG9mIG49MTQyNiBDYW5hZGlhbnMgd2hvIGFyZSBub3QgcmVzaWRlbnRzIG9mIFF1ZWJlYyB3YXMgdGFrZW4uIE9mIHRoZXNlLCA1NDEgdGhvdWdodCB0aGF0IFF1ZWJlYyB3aWxsIHNlcGFyYXRlIGZyb20gQ2FuYWRhIGluIHRoZSBuZXh0IDEwIHllYXJzICgzNTYgaW5kaWNhdGVkIOKAnG1pZ2h0IGhhcHBlbuKAnTsgMTI4IHJlc3BvbmRlZCDigJxsaWtlbHkgdG8gaGFwcGVu4oCdOyA1NyBpbmRpY2F0ZWQg4oCcZGVmaW5pdGVseSB3aWxsIGhhcHBlbuKAnSkuIFRoZSBzYW1wbGUgcHJvcG9ydGlvbiBpcyBjb21wdXRlZCB0byBiZSBwy4Y9NTQxMTQyNj0wLjM3OTQuIFVuZGVyIHRoZSBjb25kaXRpb24gb2YgdGhlIDIwMTIgcG9sbCByZXN1bHQsIGhvdyBsaWtlbHkgaXMgaXQgZm9yIGFub3RoZXIgcmFuZG9tIHNhbXBsZSBvZiBuPTE0MjYgQ2FuYWRpYW5zICh3aG8gcmVzaWRlIG91dHNpZGUgb2YgUXVlYmVjKSB0byBwcm9kdWNlIGEgc2FtcGxlIHByb3BvcnRpb24gdGhhdCBpcyBhdCBtb3N0IGFzIDAuMzc5ND8KIApSLi8gSSBjYWxjdWxhdGVkIHRoZSBzZCBmb3IgdGhlIHNhbXBsZSBwcm9wb3J0aW9uLCBJIHVzZWQgcG5vcm0oKSB0byBmaW5kIHRoZSBwcm9iYWJpbGl0eSBvZiBnZXR0aW5nIGFub3RoZXIgc2FtcGxlIHdpdGggYSBzYW1wbGUgcHJvcG9ydGlvbiBvZiBhdCBtb3N0IDAuMzc5NCBpcyAwLjAwMDk0NzEKYGBge3J9CnNkcGhhdCA9IHNxcnQoMC40MiooMS0wLjQyKSAvIDE0MjYpICNjYWxjdWxhdGUgcGhhdCBmb3IgdGhpcyBzYW1wbGUKc2RwaGF0CnBsZXNzMDM3ID0gcG5vcm0oMC4zNzk0LCBtZWFuPTAuNDIsIHNkPXNkcGhhdCkKcGxlc3MwMzcKYGBgCmMuIENvbnNpZGVyIHRoZSBzdGVwcyBhbmQgYXNzb2NpYXRlZCBSIENvZGUgcmVxdWlyZWQgdG8gZ2VuZXJhdGUgYSBkaXN0cmlidXRpb24gb2YgdGhlIHNhbXBsZSBwcm9wb3J0aW9uLCBwy4YsIHdoZW4gc2FtcGxpbmcgbj0xNDI2IENhbmFkaWFucyB3aG8gbGl2ZSBvdXRzaWRlIG9mIFF1ZWJlYywgdGhlbiBkZXRlcm1pbmluZyB0aGUgcHJvcG9ydGlvbiB3aG8gYmVsaWV2ZSBRdWViZWMgd2lsbCBzZXBhcmF0ZSBmcm9tIENhbmFkYSB3aXRoaW4gdGhlIG5leHQgMTAgeWVhcnMuIENhcnJ5IG91dCBhIHNpbXVsYXRpb24gd2hlcmUgeW91IHNpbXVsYXRlIDEwMDAgcmFuZG9tIHNhbXBsZXMgb2Ygbj0xNDI2LiBDcmVhdGUsIHRoZW4gcnVuIHlvdXIgY29kZSB0byBkZXRlcm1pbmUgdGhlIHByb3BvcnRpb24gb2YgeW91ciBwy4ZzIHRoYXQgYXJlIGxlc3MgdGhhbiBvciBlcXVhbCB0byAwLjM3OTQuIFByb3ZpZGUgdGhpcyBwcm9wb3J0aW9uLgoKUi4vIEFmdGVyIHJ1bm5pbmcgdGhlIHNpbXVsYXRpb24sIEkgZm91bmQgdGhhdCB0aGUgcHJvcG9ydGlvbiBvZiBwaGF0cyBpcyAwLjAwMS4gClRoaXMgcHJvcG9ydGlvbiBjaGFuZ2VzIGV2ZXJ5IHRpbWUgdGhlIHNpbXVsYXRpb24gaXMgcnVuLCBJIGhhdmUgZ290dGVuIHZhbHVlcyBmcm9tIDAgdG8gMCwwMDQKCmBgYHtyfQpuc2FtcGxlcyA9IDEwMDAgICNuby4gb2Ygc2ltdWxhdGlvbnMKc2FtcGxlLnBoYXQgPSBudW1lcmljKG5zYW1wbGVzKSAjZGF0YSB2ZWN0b3IgdG8gaG9sZCAxMDAwIHNhbXBsZSBzdGFuZGFyZCBkZXZpYXRpb25zIG9mIG4gPSA1CnNpemUgPSAxNDI2CnMxNDI2ZGF0YSA9IHJiaW5vbSgxLHNpemUsMC40MikgI0FzIGRlc2NyaWJlZCBodHRwczovL3d3dy5wcm9ncmFtbWluZ3IuY29tL2V4YW1wbGVzL25lYXQtdHJpY2tzL3NhbXBsZS1yLWZ1bmN0aW9uL3ItcmJpbm9tLwpjb3VudGVyID0gMAoKZm9yKGkgaW4gMTpuc2FtcGxlcyl7CiAgczE0MjZkYXRhID0gcmJpbm9tKDEsc2l6ZSwwLjQyKSAjc2ltdWxhdGVzIGEgYmluYXJ5IHNhbXBsZSB3aXRoIHAgPSAwLjQyCiAgc2FtcGxlLnBoYXRbaV0gPSBzMTQyNmRhdGEvc2l6ZSAjY29tcHV0ZSB0aGUgcGhhdCBvZiB0aGUgc2FtcGxlIG9mIDE0MjYKICBpZiAoc2FtcGxlLnBoYXRbaV0gPCAwLjM3OTQpewogICAgICBjb3VudGVyID0gY291bnRlciArIDEKICB9Cn0KCnNhbXBsZS5waGF0WzE6NV0Kc2FtcGxlLnBoYXRbOTk1Ojk5OV0KCnBwaGF0bGVzczAzNyA9IGNvdW50ZXIvbnNhbXBsZXMKcHBoYXRsZXNzMDM3CmBgYAozLiBCaWxseSBwdXJjaGFzZXMgb25lIDYtNDkgbG90dGVyeSB0aWNrZXQgZXZlcnkgd2VlayBhbmQga2VlcHMgdHJhY2sgb2YgdGhlIG51bWJlciBvZiDigJxtYXRjaGVz4oCdIGhlIGhhcyBvbiBlYWNoIG9mIGhpcyB0aWNrZXRzLiBUbyBiZSBjbGVhciwgYSDigJxtYXRjaOKAnSB3aWxsIG9jY3VyIHdoZW4gYSBudW1iZXIgb24gaGlzIHRpY2tldCBtYXRjaGVzIGEgbnVtYmVyIHRoYXQgYXBwZWFycyBpbiB0aGUgd2lubmluZyBjb21iaW5hdGlvbi4gQSByYW5kb20gdmFyaWFibGUgWCAgdGhhdCBrZWVwcyB0cmFjayBvZiB0aGUgbnVtYmVyIG9mIG1hdGNoaW5nIG51bWJlcnMgQmlsbHkgZXhwZXJpZW5jZXMgcGVyIHdlZWsgaGFzIHRoZSBwcm9iYWJpbGl0eSBkaXN0cmlidXRpb24gZnVuY3Rpb24gd2l0aCBhIG1lYW4gYW5kIHN0YW5kYXJkIGRldmlhdGlvbiBvZgpQKFg9eCkgPSBjaG9vc2UgKDYsIHgpICogY2hvb3NlKDQzLCA24oiSeCkgLyBjaG9vc2UoNDksIDYpICAgICAgeD0wLDEsMiwzLDQsNSw2LgpFKFgpID0gzrxYID0gMzYgLyA0OSA9IDAuNzM0NwpTRChYKSA9IM+DWCA9IDAuNzU5OTgg4omIIDAuNzYKQmlsbHkgY2xhaW1zIHRoYXQgaW4gYSB5ZWFyICg1MiB3ZWVrcyksIG9uIGF2ZXJhZ2UsIGhlIG1hbmFnZXMgdG8gaGF2ZSBhdCBsZWFzdCBvbmUgbWF0Y2hpbmcgbnVtYmVyIG9uIGhpcyA2LTQ5IHRpY2tldC4gV2hhdCBkbyB5b3UgdGhpbmsgCmFib3V0IEJpbGx54oCZcyBjbGFpbT8gUHJvdmlkZSBhIGJyaWVmIGNvbW1lbnRhcnkgYWJvdXQgQmlsbHnigJlzIGNsYWltIHVzaW5nIHlvdXIgY3VycmVudCBrbm93bGVkZ2Ugb2Ygc3RhdGlzdGljcyBhbmQgcHJvYmFiaWxpdHkgdGhlb3J5LiAKClIuLyBUaGUgcHJvYmFiaWxpdHkgb2YgZ2V0dGluZyBhdCBsZWFzdCBvbmUgbWF0Y2hpbmcgbnVtYmVyIGlzIGVxdWFsIHRvIDEgbWludXMgdGhlIHByb2JhYmlsaXR5IG9mIG5vIGdldHRpbmcgYW55IG51bWJlciBvciBQKHg9MCkgCgpQKHggPj0gMSkgPSAxIC0gUCh4ID0gMCkgCndlIG9idGFpbiBQKDApIGJ5IHJlcGxhY2luZyB4IHdpdGggMCBpbiB0aGUgcHJvYmFiaWxpdHkgZnVuY3Rpb24KUChYPTApID0gY2hvb3NlICg2LCAwKSAqIGNob29zZSg0MywgNuKIkjApIC8gY2hvb3NlKDQ5LCA2KSAKUChYPTApID0gMC40MzYwCgpyZXBsYWNpbmcgdGhpcyB2YWx1ZSAKUChYID49IDEpID0gMSAtIDAuNDM2MApQKFggPj0gMSkgPSAwLjU2NDAKClIuLyBUaGUgcHJvYmFiaWxpdHkgb2YgZ2V0dGluZyBhdCBsZWFzdCBvbmUgbWF0Y2hpbmcgbnVtYmVyIGluIDUyIGRyYXdzICggb25lIGRyYXcgLyB3ZWVrKSBpcyAwLjU2NCB3aGljaCBpcyBncmVhdGVyIHRoYXQgdGhlIHByb2JhYmlsaXR5IG9mIGdldHRpbmcgbm8gbWF0Y2hpbmcgbnVtYmVycyB3aGljaCBpcyAwLjQzNi4gCkl0IGlzIHBvc3NpYmxlIHRoYXQgQmlsbHkgZG9lcyBnZXQgYXQgbGVhc3Qgb25lIG1hdGNoaW5nIG51bWJlciBldmVyeSB3ZWVrIGZvciBhIHllYXIuCgpgYGB7cn0KUDAgPSBjaG9vc2UgKDYsIDApICogY2hvb3NlKDQzLCA2KSAvIGNob29zZSg0OSwgNikgClAwCgpQbW9yZTEgPSAxIC0gUDAKUG1vcmUxCmBgYAo0LiBBIGNvbW1vbiBtZWFzdXJlIG9mIHRveGljaXR5IGZvciBhbnkgcG9sbHV0YW50IGlzIHRoZSBjb25jZW50cmF0aW9uIG9mIHRoZSBwb2xsdXRhbnQgdGhhdCB3aWxsIGtpbGwgaGFsZiBvZiB0aGUgdGVzdCBzcGVjaWVzIGluIGEgZ2l2ZW4gYW1vdW50IG9mIHRpbWUgKHVzdWFsbHkgYWJvdXQgOTYgaG91cnMgZm9yIHRoZSBmaXNoIHNwZWNpZXMpLiBUaGlzIG1lYXN1cmVtZW50IGlzIGNhbGxlZCB0aGUgTEM1MCwgd2hpY2ggcmVmZXJzIHRvIHRoZSBsZXRoYWwgY29uY2VudHJhdGlvbiBraWxsaW5nIDUwJSBvZiB0aGUgdGVzdCBzcGVjaWVzKS4KClRoZSBFbnZpcm9ubWVudGFsIFByb3RlY3Rpb24gQWdlbmN5IGhhcyBjb2xsZWN0ZWQgZGF0YSBvbiBMQzUwIG1lYXN1cmVtZW50cyBmb3IgY2VydGFpbiBjaGVtaWNhbHMgbGlrZWx5IHRvIGJlIGZvdW5kIGluIGZyZXNod2F0ZXIgYW5kIGxha2VzLiBGb3IgYSBjZXJ0YWluIHNwZWNpZXMgb2YgZmlzaCwgdGhlIExDNTAgbWVhc3VyZW1lbnRzIChpbiBwYXJ0cyBwZXIgbWlsbGlvbikgZm9yIEREVCBpbiAxMiBleHBlcmltZW50cyB0byBkZXRlcm1pbmUgdGhlIExDNTAg4oCcZG9zZeKAnSBhcmUKMTYsNSwyMSwxOSwxMCw1LDgsMiw3LDIsNCw5CgphLiBVc2UgUiBzdHVkaW8gdG8gY3JlYXRlIHRoZSBib290c3RyYXAgZGlzdHJpYnV0aW9uIG9mIHRoZSBzYW1wbGUgbWVhbiBYwq/Cr8Kvwq9Cb290LExDNTAuIFVzZSAyMDAwIOKAnGJvb3RzdHJhcHPigJ0gaW4geW91ciB3b3JrLCBhbmQgZGlzcGxheSB0aGUgZGlzdHJpYnV0aW9uLgoKUi4vIEFzIGZvbGxvd3MKCmBgYHtyfQojIGxpYnJhcnkobW9zYWljKQpsaWJyYXJ5KGdncGxvdDIpCmxpYnJhcnkobGF0dGljZSkKbGM1MCA9IGMoMTYsNSwyMSwxOSwxMCw1LDgsMiw3LDIsNCw5KSAgI2NyZWF0ZSBhIHZlY3RvciB3aXRoIHRoZSB2YWx1ZXMgb2YgTEM1MApsYzUwLmRmID0gZGF0YS5mcmFtZShsYzUwKSAgIyBjb252ZXJ0IHRoZSBhYm92ZSB2ZWN0b3IgaW50byBhIGRhdGFmcmFtZQpsYzUwLmRmCmBgYAoKCmBgYHtyfQpudGltZXMgPSAxMDAKYm9vdGRhdGEgPSBudW1lcmljKGxlbmd0aChsYzUwLmRmJGxjNTApKm50aW1lcykKZm9yKGkgaW4gMTpudGltZXMpCnsgIGlmIChpID09IDEpIGJvb3RkYXRhID0gbGM1MC5kZiRsYzUwCiAgIGVsc2UgYm9vdGRhdGEgPSBjKGxjNTAuZGYkbGM1MCwgYm9vdGRhdGEpCn0KCk4gPSAyMDAwCm4uc2l6ZSA9IGxlbmd0aChsYzUwLmRmJGxjNTApCmJvb3QubWVhbiA9IG51bWVyaWMoTikKYm9vdC5kYXRhID0gbnVtZXJpYyhuLnNpemUpCiMKZm9yKGkgaW4gMTpOKXsKICAKICBib290LmRhdGEgPSBzYW1wbGUobGM1MC5kZiRsYzUwLCBuLnNpemUsIHJlcGxhY2U9VFJVRSkgI3NhbXBsZSB3aXRoIHJlcGxhY2VtZW50IAogIGJvb3QubWVhbltpXSA9IG1lYW4oYm9vdC5kYXRhKQp9CmJvb3RzdHJhcC5tZWFuID0gZGF0YS5mcmFtZShib290Lm1lYW4pICNkYXRhIGZyYW1lIGhvbGRpbmcgMjAwMCBkaWZmZXJlbnQgYm9vdHN0cmFwIHNhbXBsZSBtZWFucwpoZWFkKGJvb3RzdHJhcC5tZWFuLCA0KQoKYGBgCmBgYHtyfQp0YWlsKGJvb3RzdHJhcC5tZWFuLCA0KQpgYGAKCgpgYGB7cn0KZ2dwbG90KGJvb3RzdHJhcC5tZWFuLCBhZXMoeCA9IGJvb3QubWVhbikpICsgZ2VvbV9oaXN0b2dyYW0oY29sPSJyZWQiLCBmaWxsPSJibHVlIiwgYmlud2lkdGggPSAwLjUpICsgeGxhYigiVmFsdWVzIG9mIEJvb3RzdHJhcCBNZWFuIikgKyB5bGFiKCJDb3VudCIpICsgZ2d0aXRsZSgiRGlzdHJpYnV0aW9uIG9mIEJvb3RzdHJhcCBTdGF0aXN0aWM6IFNhbXBsZSBNZWFuIikKYGBgCmBgYHtyfQpmYXZzdGF0cyh+Ym9vdC5tZWFuLCBkYXRhPWJvb3RzdHJhcC5tZWFuKQpgYGAKYi4gRnJvbSB5b3VyIHJlc3VsdCBpbiAoYSksIGNvbXB1dGUgdGhlIDk1JSBib290c3RyYXAgKHBlcmNlbnRpbGUpIGNvbmZpZGVuY2UgaW50ZXJ2YWwgZm9yIFwoXG11X3tMQzUwfVwpLCB0aGUgbWVhbiBMQzUwIG1lYXN1cmVtZW50IGZvciBERFQuCgpSLi8gdXNpbmcgcWRhdGEoKSBvbiB0aGUgbGlzdCBvZiBtZWFucyBhbmQgdGhlbiBkaXNwbGF5aW5nIHRoZSBkaXN0cmlidXRpb24gd2l0aCB0aGUgdmFsdWVzIGZvciBwMjUgYW5zIHA5Ny41IHdoaWNoIGFyZSA1Ljc1IGFuZCAxMi41IAoKYGBge3J9CnAyNS5sYzUwID0gcWRhdGEofmJvb3QubWVhbiwgYygwLjAyNSwgMC45NzUpLCBkYXRhPWJvb3RzdHJhcC5tZWFuKVsxXQpwMjUubGM1MFsxXQoKcDk3NS5sYzUwID0gcWRhdGEofmJvb3QubWVhbiwgYygwLjAyNSwgMC45NzUpLCBkYXRhPWJvb3RzdHJhcC5tZWFuKVsyXQpwOTc1LmxjNTAKYGBgCmBgYHtyfQpnZ3Bsb3QoYm9vdHN0cmFwLm1lYW4sIGFlcyh4ID0gYm9vdC5tZWFuKSkgKyBnZW9tX2hpc3RvZ3JhbShjb2w9InJlZCIsIGZpbGw9ImJsdWUiLCBiaW53aWR0aCA9IDAuNSkgKyB4bGFiKCJWYWx1ZXMgb2YgQm9vdHN0cmFwIE1lYW4iKSArIHlsYWIoIkNvdW50IikgKyBnZ3RpdGxlKCJEaXN0cmlidXRpb24gb2YgQm9vdHN0cmFwIFN0YXRpc3RpYzogU2FtcGxlIE1lYW4gd2l0aCA5NSUgY29uZmlkZW5jZSBJbnRlcnZhbCAiKSArIGdlb21fdmxpbmUoeGludGVyY2VwdCA9IHAyNS5sYzUwLCBjb2xvcj0icmVkIikgKyBnZW9tX3ZsaW5lKHhpbnRlcmNlcHQgPSBwOTc1LmxjNTAsIGNvbG9yPSJyZWQiKQpgYGAKYy4gUmVwZWF0IHlvdXIgZXN0aW1hdGlvbiBvZiBcKFxtdV97TEM1MH1cKSwgdXNpbmcgdGhlIOKAnG90aGVy4oCdIGNvbmZpZGVuY2UgaW50ZXJ2YWwgY292ZXJlZCBpbiBEYXRhIDYwMi4gSW4gdGhlIGNvbnRleHQgb2YgdGhlc2UgZGF0YSwgaW50ZXJwcmV0IHRoZSBtZWFuaW5nIG9mIHRoZSBjb25maWRlbmNlIGludGVydmFsLiBTdGF0ZSBhbnkgY29uZGl0aW9ucy9hc3N1bXB0aW9ucyB0aGF0IGFyZSByZXF1aXJlZCBpbiB0aGUgY29tcHV0YXRpb24gb2YgdGhpcyBjb25maWRlbmNlIGludGVydmFsLgoKUi4vVXNpbmcgU3R1ZGVudCdzIFQgd2UgZm91bmQgUDIuNSA9IDQuOTE4MSBhbmQgUDk3LjUgPSAxMy4wODE5CgoKYGBge3J9ClR0ZXN0LmxjNTAgPSB0LnRlc3QofmxjNTAsIGRhdGE9bGM1MC5kZikkY29uZiAjdXNpbmcgZGVmYXVsdCB2YWx1ZSBvZiAwLjk1IGNvbmZpZGVuY2UgaW50ZXJ2YWwgClR0ZXN0LmxjNTBbMV0KVHRlc3QubGM1MFsyXQpgYGAKZC4gQ29tcGFyZSB5b3VyIHJlc3VsdHMgaW4gcGFydHMgKGIpIGFuZCAoYykuIElmIHlvdSB3ZXJlIHRvIHJlcG9ydCBvbmUgb2YgdGhlc2UgY29uZmlkZW5jZSBpbnRlcnZhbHMsIHdoaWNoIHdvdWxkIHlvdSByZXBvcnQ/IEV4cGxhaW4geW91ciBhbnN3ZXIuCgpSLi8gQm9vdHN0cmFwIGZvciBDSTk1ID0gKDUuNzUsIDEyLjU4KSAocmVkIGluIHRoZSBncmFwaCkKU3R1ZGVudCdzIFQgZm9yIENJOTUgPSAoNC45MTgxLCAxMy4wODE3KSAoYmx1ZSBpbiB0aGUgZ3JhcGgpClRvIGJlIG9uIHRoZSBzYWZlciBzaWRlLCBJIHdhbnQgdG8gcmVwb3J0IGEgdGlnaHRlciBpbnRlcnZhbCBzbyBJIHByZWZlciB0aGUgaW50ZXJ2YWwgZnJvbSBCb290c3RyYXAKCmBgYHtyfQpnZ3Bsb3QoYm9vdHN0cmFwLm1lYW4sIGFlcyh4ID0gYm9vdC5tZWFuKSkgKyBnZW9tX2hpc3RvZ3JhbShjb2w9InJlZCIsIGZpbGw9ImJsdWUiLCBiaW53aWR0aCA9IDAuNSkgKyB4bGFiKCJWYWx1ZXMgb2YgQm9vdHN0cmFwIE1lYW4iKSArIHlsYWIoIkNvdW50IikgKyBnZ3RpdGxlKCJEaXN0cmlidXRpb24gb2YgQm9vdHN0cmFwIFN0YXRpc3RpYzogU2FtcGxlIE1lYW4gd2l0aCA5NSUgY29uZmlkZW5jZSBJbnRlcnZhbCAiKSArIGdlb21fdmxpbmUoeGludGVyY2VwdCA9IHAyNS5sYzUwLCBjb2xvcj0icmVkIikgKyBnZW9tX3ZsaW5lKHhpbnRlcmNlcHQgPSBwOTc1LmxjNTAsIGNvbG9yPSJyZWQiKSArIGdlb21fdmxpbmUoeGludGVyY2VwdCA9IFR0ZXN0LmxjNTBbMV0sIGNvbG9yPSJibHVlIikgKyBnZW9tX3ZsaW5lKHhpbnRlcmNlcHQgPSBUdGVzdC5sYzUwWzJdLCBjb2xvcj0iYmx1ZSIpCmBgYAo1LiBEb2VzIG9uZeKAmXMgZWR1Y2F0aW9uYWwgbGV2ZWwgaW5mbHVlbmNlIHRoZWlyIG9waW5pb24gYWJvdXQgdmFjY2luYXRpb25zPyBBIHJlY2VudCBBbmd1cyBSZWlkMiBzdXJ2ZXkgd2FzIHRha2VuLiBFYWNoIHBlcnNvbiBzYW1wbGVkIHdhcyBhc2tlZCB0byByZXNwb25kIHRvIHRoZSBzdGF0ZW1lbnQg4oCcVGhlIHNjaWVuY2UgYXJvdW5kIHZhY2NpbmF0aW9ucyBpc27igJl0IGNsZWFyLuKAnQoKUmVzcG9uZGVudHMgZWl0aGVyIOKAnHN0cm9uZ2x5IGFncmVl4oCdLCDigJxtb2RlcmF0ZWx5IGFncmVl4oCdLCDigJxtb2RlcmF0ZWx5IGRpc2FncmVl4oCdLCBvciDigJxzdHJvbmdseSBkaXNhZ3JlZeKAnS4gVGhlIHNhbXBsZSB3YXMgcGFydGl0aW9uZWQgYnkgbGV2ZWwgb2YgZWR1Y2F0aW9uLgoKVGhlcmUgd2VyZSBuPTY3MCByZXNwb25kZW50cyB3aG/igJlzIGhpZ2hlc3QgbGV2ZWwgb2YgZWR1Y2F0aW9uIHdhcyBoaWdoIHNjaG9vbCBvciBsZXNzLCBvZiB3aGljaCAzNDgg4oCcZGlzYWdyZWVk4oCdIChtb2RlcmF0ZWx5IGRpc2FncmVlIG9yIHN0b25nbHkgZGlzYWdyZWUpLiBUaGVyZSB3ZXJlIGFsc28gbj0zNzYKIHdob+KAmXMgaGlnaGVzdCBsZXZlbCBvZiBlZHVjYXRpb24gd2FzIGF0IGxlYXN0IGFuIHVuZGVyZ3JhZHVhdGUgdW5pdmVyc2l0eSBlZHVjYXRpb24uIE9mIHRoZXNlLCAyNzQgZGlzYWdyZWVkLgoKCmEuIENvbnNpZGVyIHRoZSBwb3B1bGF0aW9uIGNvbnNpc3Rpbmcgb2YgYWxsIHBlcnNvbnMsIHdob+KAmXMgaGlnaGVzdCBsZXZlbCBvZiBlZHVjYXRpb24gd2FzIGhpZ2ggc2Nob29sIG9yIGxlc3MgYW5kIHRoZSBib290c3RyYXAgc3RhdGlzdGljIHDLhkJvb3QsSFMgLiBVc2luZyAxMDAwIGl0ZXJhdGlvbnMvcmVwbGljYXRpb25zLCBjcmVhdGUgYSBib290c3RyYXAgZGlzdHJpYnV0aW9uIG9mIHDLhkhTCi4gRGlzcGxheSB5b3VyIGRpc3RyaWJ1dGlvbi4KClIuLyBGcm9tIHRoZSBpbmZvcm1hdGlvbiBnaXZlbiB3ZSBjYW4gY2FsY3VsYXRlIHBIUyA9IDM0OCAvIDY3MCA9IDAuNTIuIEkgdXNlIHRoaXMgcHJvcG9ydGlvbiB0byBjcmVhdGUgYSByYW5kb20gbGlzdCBvZiB6ZXJvcyhhZ3JlZWQpIGFuZCBvbmVzIChkaXNhZ3JlZSkuCkkgdGhlbiB1c2UgdGhpcyBsaXN0IHRvIGNyZWF0ZSBhIHRhYmxlIHRoYXQgYWxsb3dzIG1lIHRvIHNlZSB0aGUgYW1vdW50IG9mIHplcm9zIGFuZCBvbmVzIGluIHRoZSBsaXN0LgpOZXh0IEkgbG9vcCAxMDAwIHRpbWVzIHRvIGNyZWF0ZSBhIHNhbXBsZSBmcm9tIHRoZSBsaXN0IEkgY3JlYXRlZCB3aXRoIHRoZSBzaXplIG9mIDY3MCBhbmQgcmVwbGFjZW1lbnQgPSB0cnVlLiBUaGUgbWVhbiBvZiB0aGUgc2FtcGxlIGlzIHRoZW4gY2FsY3VsYXRlZCBhbmQgc3RvcmVkIGluIGFuIGFycmF5IGNhbGxlZCBwaGF0cy5oczsgdGhlbiBJIGNyZWF0ZSBhIGRhdGEgZnJhbWUgZnJvbSB0aGUgcGhhdHMuaHMgbGlzdCBhbmQgZGlzcGxheWVkIGl0cyBoaXN0b2dyYW0KCmBgYHtyfQpsaWJyYXJ5KGJpbm9tKQpocyA9IHJiaW5vbShuPTY3MCxzaXplPTEscHJvYj0wLjUyKQp0YWJsZShocykKYGBgCmBgYHtyfQpwaGF0cy5ocyA9IG51bWVyaWMoMTAwMCkgI2NyZWF0ZSBhIHZlY3RvciB0byBzdG9yZSBlYWNoIG9mIHRoZSAxMDAwIGJvb3RzdHJhcCB2YWx1ZXMgb2YgdGhlIHNhbXBsZSBwcm9wb3J0aW9uCmZvcihpIGluIDE6MTAwMCl7CiAgICAgIHRlbXAuZGF0YSA9IHNhbXBsZShocywgbGVuZ3RoKGhzKSwgcmVwbGFjZT1UUlVFKSAjY291bGQgaGF2ZSB1c2VkIHJlc2FtcGxlKHVzZXJvZm1hcmkpIGhlcmUKICAgICAgcGhhdHMuaHNbaV0gPSBtZWFuKHRlbXAuZGF0YSkKfQpib290X3BoYXRfaHMuZGYgPSBkYXRhLmZyYW1lKHBoYXRzLmhzKQpoZWFkKGJvb3RfcGhhdF9ocy5kZiwgNCkKCmBgYApgYGB7cn0KdGFpbChib290X3BoYXRfaHMuZGYsIDQpCmBgYAoKCmBgYHtyfQpnZ3Bsb3QoYm9vdF9waGF0X2hzLmRmLCBhZXMoeCA9IHBoYXRzLmhzKSkgKyBnZW9tX2hpc3RvZ3JhbShjb2w9ImdyZWVuIiwgZmlsbD0iYmx1ZSIsIGJpbndpZHRoPTAuMDEpICsgeGxhYigiVmFsdWVzIG9mIHRoZSBTYW1wbGUgUHJvcG9ydGlvbiIpICsgeWxhYigiQ291bnQiKSArIGdndGl0bGUoIkhpc3RvZ3JhbTogRGlzdHJpYnV0aW9uIG9mIEJvb3RzdHJhcCBTYW1wbGUgUHJvcG9ydGlvbiIpCmBgYApiLiBOb3cgY29uc2lkZXIgYSBkaWZmZXJlbnQgcG9wdWxhdGlvbiB0aGF0IGNvbnNpc3Qgb2YgYWxsIHBlcnNvbnMgd2hv4oCZcyBoaWdoZXN0IGxldmVsIG9mIGVkdWNhdGlvbiB3YXMgYXQgbGVhc3QgYW4gdW5kZXJncmFkdWF0ZSBkZWdyZWUuIFJlcGVhdCBwYXJ0IChhKSwgY3JlYXRpbmcgYSBib290c3RyYXAgZGlzdHJpYnV0aW9uIGZvciBwy4ZCb290LFVuaS4gKEFnYWluLCBkaXNwbGF5IHlvdXIgZGlzdHJpYnV0aW9uKS4KClIuLyBGcm9tIHRoZSBpbmZvcm1hdGlvbiBnaXZlbiB3ZSBjYW4gY2FsY3VsYXRlIHBVbmk9IDI3NCAvIDM3NiA9IDAuNzMuIEkgdXNlIHRoaXMgcHJvcG9ydGlvbiB0byBjcmVhdGUgYSByYW5kb20gbGlzdCBvZiB6ZXJvcyhhZ3JlZWQpIGFuZCBvbmVzIChkaXNhZ3JlZSkuIEkgdGhlbiB1c2UgdGhpcyBsaXN0IHRvIGNyZWF0ZSBhIHRhYmxlIHRoYXQgYWxsb3dzIG1lIHRvIHNlZSB0aGUgYW1vdW50IG9mIHplcm9zIGFuZCBvbmVzIGluIHRoZSBsaXN0LgpOZXh0IEkgbG9vcCAxMDAwIHRpbWVzIHRvIGNyZWF0ZSBhIHNhbXBsZSBmcm9tIHRoZSBsaXN0IEkgY3JlYXRlZCB3aXRoIHRoZSBzaXplIG9mIDM3NiBhbmQgcmVwbGFjZW1lbnQgPSB0cnVlLiBUaGUgbWVhbiBvZiB0aGUgc2FtcGxlIGlzIHRoZW4gY2FsY3VsYXRlZCBhbmQgc3RvcmVkIGluIGFuIGFycmF5IGNhbGxlZCBwaGF0cy51bmk7IHRoZW4gSSBjcmVhdGUgYSBkYXRhIGZyYW1lIGZyb20gdGhlIHBoYXRzLnVuaSBsaXN0IGFuZCBkaXNwbGF5ZWQgaXRzIGhpc3RvZ3JhbQoKYGBge3J9CnVuaSA9IHJiaW5vbShuPTM3NixzaXplPTEscHJvYj0wLjczKQp0YWJsZSh1bmkpCmBgYApgYGB7cn0KcGhhdHMudW5pID0gbnVtZXJpYygxMDAwKSAKZm9yKGkgaW4gMToxMDAwKXsKICAgICAgdGVtcC5kYXRhID0gc2FtcGxlKHVuaSwgbGVuZ3RoKHVuaSksIHJlcGxhY2U9VFJVRSkgCiAgICAgIHBoYXRzLnVuaVtpXSA9IG1lYW4odGVtcC5kYXRhKQp9CmJvb3RfcGhhdF91bmkuZGYgPSBkYXRhLmZyYW1lKHBoYXRzLnVuaSkKaGVhZChib290X3BoYXRfdW5pLmRmLCA0KQpgYGAKYGBge3J9CnRhaWwoYm9vdF9waGF0X3VuaS5kZiwgNCkKYGBgCgoKYGBge3J9CmdncGxvdChib290X3BoYXRfdW5pLmRmLCBhZXMoeCA9IHBoYXRzLnVuaSkpICsgZ2VvbV9oaXN0b2dyYW0oY29sPSJncmVlbiIsIGZpbGw9ImJsdWUiLCBiaW53aWR0aD0wLjAxKSArIHhsYWIoIlZhbHVlcyBvZiB0aGUgU2FtcGxlIFByb3BvcnRpb24iKSArIHlsYWIoIlByb3BvcnRpb24iKSArIGdndGl0bGUoIkhpc3RvZ3JhbTogRGlzdHJpYnV0aW9uIG9mIEJvb3RzdHJhcCBTYW1wbGUgUHJvcG9ydGlvbiIpIApgYGAKYy4gWW91IHdpc2ggdG8gZXN0aW1hdGUgcFVuaeKIknBIUywgdGhlIGRpZmZlcmVuY2UgYmV0d2VlbiB0aGUgcHJvcG9ydGlvbiBvZiBhbGwgdW5pdmVyc2l0eS1lZHVjYXRlZCBDYW5hZGlhbnMgd2hvIGRpc2FncmVlIHRoYXQgdGhlIHNjaWVuY2Ugb2YgdmFjY2luYXRpb25zIGlzbuKAmXQgY2xlYXIgYW5kIHRoZSBwcm9wb3J0aW9uIG9mIGFsbCBDYW5hZGlhbnMgd2hv4oCZcyBoaWdoZXN0IGxldmVsIG9mIGNvbXBsZXRlZCBlZHVjYXRpb24gaXMgaGlnaCBzY2hvb2wgd2hvIGJlbGlldmUgdGhlIHNhbWUuIFlvdSB3aXNoIHRvIGhhdmUgOTUlIGNvbmZpZGVuY2UgaW4geW91ciByZXN1bHQuIFRoaW5rIGFib3V0IHRoZSBjb2RlIHlvdSBjcmVhdGVkIHRvIGdlbmVyYXRlIHRoZSBib290c3RyYXAgZGlzdHJpYnV0aW9ucyBvbiBwYXJ0cyAoYSkgYW5kIChiKS4gTW9kaWZ5IHRoZSBjb2RlIHRvIHlvdSBjcmVhdGVkIGluIHBhcnRzIChhKSBhbmQgKGIpIHRvIGNyZWF0ZSBhIGRpc3RyaWJ1dGlvbiBvZiB0aGUgYm9vdHN0cmFwIHN0YXRpc3RpYyBwy4ZVbmniiJJwy4ZIUy4KClIuLyBBcyBmb2xsb3dzCgpgYGB7cn0KcGhhdHMudW5pX2hzID0gbnVtZXJpYygxMDAwKSAKZm9yKGkgaW4gMToxMDAwKXsKICAgIHRlbXAuZGF0YS5ocyA9IHNhbXBsZShocywgbGVuZ3RoKGhzKSwgcmVwbGFjZT1UUlVFKSAjY291bGQgaGF2ZSB1c2VkIHJlc2FtcGxlKHVzZXJvZm1hcmkpIGhlcmUKICAgIHRlbXAuZGF0YS51bmkgPSBzYW1wbGUodW5pLCBsZW5ndGgodW5pKSwgcmVwbGFjZT1UUlVFKSAgCiAgICBwaGF0cy51bmlfaHNbaV0gPSBtZWFuKHRlbXAuZGF0YS51bmkpIC0gbWVhbih0ZW1wLmRhdGEuaHMpCn0KYm9vdF9waGF0X3VuaV9ocy5kZiA9IGRhdGEuZnJhbWUocGhhdHMudW5pX2hzKQpoZWFkKGJvb3RfcGhhdF91bmlfaHMuZGYsIDQpCgpgYGAKYGBge3J9CnRhaWwoYm9vdF9waGF0X3VuaV9ocy5kZiwgNCkKYGBgCgoKZC4gQ29uc2lkZXIgeW91ciBmaW5kaW5nIGluIHBhcnQgKGMpLiBDb21wdXRlIHRoZSA5NSUgYm9vdHN0cmFwIHBlcmNlbnRpbGUgY29uZmlkZW5jZSBpbnRlcnZhbCBmb3IgcFVuaeKIknBIcy4gRnJvbSB5b3VyIHJlc3VsdCwgZG9lcyB0aGUgcHJvcG9ydGlvbiBvZiBwZXJzb25zIHdpdGggYXQgbW9zdCBhIGhpZ2ggc2Nob29sIGVkdWNhdGlvbiB3aG8gZGlzYWdyZWUgdGhlIHNjaWVuY2UgYXJvdW5kIHZhY2NpbmF0aW9ucyBpc27igJl0IGNsZWFyIGdyZWF0ZXIgdGhhbiB0aGUgc2ltaWxhciBwcm9wb3J0aW9uIG9mIHBlcnNvbnMgd2l0aCBhdCBsZWFzdCBhbiB1bmRlcmdyYWR1YXRlIHVuaXZlcnNpdHkgZGVncmVlPyBXcml0ZSBhIHBhcmFncmFwaCB0aGF0IHN1cHBvcnRzIHlvdXIgYW5zd2VyLgoKUi4vIFRoZSBwcm9wb3J0aW9uIG9mIHBlb3BsZSB3aXRoIGEgbGV2ZWwgb2YgZWR1Y2F0aW9uIGhpZ2hlciB0aGFuIGhpZ2ggc2Nob29sIHdobyBkaXNhZ3JlZSB0aGUgc2NpZW5jZSBhcm91bmQgdmFjY2luYXRpb24gaXNuJ3QgY2xlYXIgaXMgZ3JlYXRlciB0aGFuIHRoZSBwcm9wb3J0aW9uIG9mIHBlb3BsZSB3aXRoIGEgbGV2ZWwgb2YgZWR1Y2F0aW9uIGVxdWFsIG9yIGxlc3MgdGhhbiBoaWdoIHNjaG9vbC4gVGhpcyBpcyBldmlkZW50IGJ5IHRoZSBmYWN0IHRoYXQgdGhlIGRpc3RyaWJ1dGlvbiBvZiB0aGUgc2ltdWxhdGlvbiBvZiBwVW5p4oiScEhzIHlpZWxkcyB2YWx1ZXMgdGhhdCBhcmUgZ3JlYXRlciB0aGFuIDAuIFRoZSA5NSUgY29uZmlkZW5jZSBpbnRlcnZhbCBzaG93cyB0aGF0IG1vc3Qgb2YgdGhlIHZhbHVlcyBmb3IgdGhpcyBkaWZmZXJlbmNlIGZhbGxzIGJldHdlZW4gMTYuNjglIGFuZCAyOC4zMiUgaW4gZmF2b3Igb2YgcGVvcGxlIHdpdGggaGlnaGVyIGVkdWNhdGlvbiB0aGFuIGhpZ2ggc2Nob29sLgoKYGBge3J9CnAyNS51bmlfaHMgPSBxZGF0YSh+cGhhdHMudW5pX2hzLCBjKDAuMDI1LCAwLjk3NSksIGRhdGE9Ym9vdF9waGF0X3VuaV9ocy5kZilbMV0KcDI1LnVuaV9ocwpwOTc1LnVuaV9ocyA9IHFkYXRhKH5waGF0cy51bmlfaHMsIGMoMC4wMjUsIDAuOTc1KSwgZGF0YT1ib290X3BoYXRfdW5pX2hzLmRmKVsyXQpwOTc1LnVuaV9ocwoKYGBgCmBgYHtyfQpnZ3Bsb3QoYm9vdF9waGF0X3VuaV9ocy5kZiwgYWVzKHggPSBwaGF0cy51bmlfaHMpKSArIGdlb21faGlzdG9ncmFtKGNvbD0iZ3JlZW4iLCBmaWxsPSJibHVlIiwgYmlud2lkdGg9MC4wMSkgKyB4bGFiKCJWYWx1ZXMgb2YgdGhlIFNhbXBsZSBQcm9wb3J0aW9uIikgKyB5bGFiKCJDb3VudCIpICsgZ2d0aXRsZSgiSGlzdG9ncmFtOiBEaXN0cmlidXRpb24gb2YgQm9vdHN0cmFwIFNhbXBsZSBQcm9wb3J0aW9uIikgKyBnZW9tX3ZsaW5lKHhpbnRlcmNlcHQgPSBwMjUudW5pX2hzLCBjb2xvcj0icmVkIikgKyBnZW9tX3ZsaW5lKHhpbnRlcmNlcHQgPSBwOTc1LnVuaV9ocywgY29sb3I9InJlZCIpCmBgYAoKCjYuIE5hbm9zIHJlc2VhcmNoMyByZWNlbnRseSBjb21wbGV0ZWQgYSBzdXJ2ZXkgb2Ygbj0xMDAwICBDYW5hZGlhbnMgYWdlZCAxOCB5ZWFycyBvZiBhZ2Ugb3Igb2xkZXIsIGFza2luZyBlYWNoIOKAnHdoYXQgaXMgeW91ciBtb3N0IGltcG9ydGFudCBuYXRpb25hbCBpc3N1ZSBvZiBjb25jZXJuP+KAnSAxNjMgcmVzcG9uZGVkIOKAnEluZmxhdGlvbuKAnSwgMTQ5IHJlc3BvbmRlZCDigJxFbnZpcm9ubWVudOKAnSwgMTMxIHJlc3BvbmRlZCDigJxKb2JzL0Vjb25vbXnigJ0uIFRob3NlIHdlcmUgdGhlIFRvcCBUaHJlZS4KCmEuIENvbXB1dGUgYSA5NSUgY29uZmlkZW5jZSBpbnRlcnZhbCBmb3IgcEluZmxhdGlvbiwgdGhlIHByb3BvcnRpb24gb2YgYWxsIENhbmFkaWFucyBhZ2VkIDE4IHllYXJzIG9yIG9sZGVyIGZvciB3aG9tIOKAnEluZmxhdGlvbuKAnSBpcyB0aGUgbW9zdCBpbXBvcnRhbnQgbmF0aW9uYWwgY29uY2Vybi4KClIuL0kgY2FuIGNhbGN1bGF0ZSB0aGUgOTUlIGNvbmZpZGVuY2UgaW50ZXJ2YWwgdXNpbmcgdGhlIHBsdXMtMi9wbHVzLTQgd2hpY2ggZ2l2ZXMgdXMgMC4xNDI3KHAyLjUpIC0gMC4xODg1KHA5Ny41KQpgYGB7cn0KcHJvcC50ZXN0KDE2MyArIDIsIDEwMDAgKyA0LCBjb3JyZWN0PUZBTFNFKSRjb25mCmBgYApiLiBTaW1pbGFyIHRvIHlvdXIgd29yayBpbiBRdWVzdGlvbiA0KGIpLCBjcmVhdGUgdGhlIGRpc3RyaWJ1dGlvbiBvZiB0aGUgYm9vdHN0cmFwIHN0YXRpc3RpYyBwy4ZCb290LEluZmxhdGlvbgogYW5kIGEgOTUlIGJvb3RzdHJhcCBwZXJjZW50aWxlIGNvbmZpZGVuY2UgaW50ZXJ2YWwgZm9yIHBJbmZsYXRpb24uCiAKIFIuLyBDb25maWRlbmNlIGludGVydmFsIDk1JSA9IDAuMTQ0IC0gMC4xODgKIApgYGB7cn0KaW5mbCA9IHJiaW5vbShuPTEwMDAsc2l6ZT0xLHByb2I9MC4xNjMpCmluZmwuZGYgPSBkYXRhLmZyYW1lKGluZmwpCmhlYWQoaW5mbC5kZiwgNCkKYGBgCmBgYHtyfQp0YWlsKGluZmwuZGYpCmBgYAoKCmBgYHtyfQpOID0gMTAwMApuLnNpemUgPSBsZW5ndGgoaW5mbC5kZiRpbmZsKQpib290LnByb3BvcnRpb25faW5mbCA9IG51bWVyaWMoTikKYm9vdC5kYXRhX2luZmwgPSBudW1lcmljKG4uc2l6ZSkKCgpmb3IoaSBpbiAxOk4pewogIAogIGJvb3QuZGF0YV9pbmZsID0gc2FtcGxlKGluZmwuZGYkaW5mbCwgbi5zaXplLCByZXBsYWNlPVRSVUUpICNzYW1wbGUgd2l0aCByZXBsYWNlbWVudCAKICBib290LnByb3BvcnRpb25faW5mbFtpXSA9IG1lYW4oYm9vdC5kYXRhX2luZmwpCn0KYm9vdHN0cmFwLnByb3BvcnRpb25faW5mbCA9IGRhdGEuZnJhbWUoYm9vdC5wcm9wb3J0aW9uX2luZmwpICNkYXRhIGZyYW1lIGhvbGRpbmcgMjAwMCBkaWZmZXJlbnQgYm9vdHN0cmFwIHNhbXBsZSBtZWFucwpoZWFkKGJvb3RzdHJhcC5wcm9wb3J0aW9uX2luZmwsIDQpCgpgYGAKYGBge3J9CnRhaWwoYm9vdHN0cmFwLnByb3BvcnRpb25faW5mbCwgNCkKYGBgCgoKYGBge3J9CnAyLjVJbmZsID0gcWRhdGEofmJvb3QucHJvcG9ydGlvbl9pbmZsLCBjKDAuMDI1LCAwLjk3NSksIGRhdGEgPSBib290c3RyYXAucHJvcG9ydGlvbl9pbmZsKVsxXQpwMi41SW5mbApwOTcuNUluZmwgPSBxZGF0YSh+Ym9vdC5wcm9wb3J0aW9uX2luZmwsIGMoMC4wMjUsIDAuOTc1KSwgZGF0YSA9IGJvb3RzdHJhcC5wcm9wb3J0aW9uX2luZmwpWzJdCnA5Ny41SW5mbApgYGAKYGBge3J9CmdncGxvdChib290c3RyYXAucHJvcG9ydGlvbl9pbmZsLCBhZXMoeCA9IGJvb3QucHJvcG9ydGlvbl9pbmZsKSkgKyBnZW9tX2hpc3RvZ3JhbShjb2w9ImdyZWVuIiwgZmlsbD0iYmx1ZSIsIGJpbndpZHRoPTAuMDA1KSArIHhsYWIoIlZhbHVlcyBvZiB0aGUgU2FtcGxlIFByb3BvcnRpb24iKSArIHlsYWIoIkNvdW50IikgKyBnZ3RpdGxlKCJIaXN0b2dyYW06IERpc3RyaWJ1dGlvbiBvZiBCb290c3RyYXAgU2FtcGxlIFByb3BvcnRpb24iKSArIGdlb21fdmxpbmUoeGludGVyY2VwdCA9IHAyLjVJbmZsLCBjb2xvcj0icmVkIikgKyBnZW9tX3ZsaW5lKHhpbnRlcmNlcHQgPSBwOTcuNUluZmwsIGNvbG9yPSJyZWQiKQpgYGAKYy4gQSBzaW1pbGFyIHN1cnZleSBvZiBDYW5hZGlhbnMgaW4gQXVndXN0IDIwMjMgLSBhIGxpdHRsZSBvdmVyIGEgbW9udGggYWdvIC0gc3VnZ2VzdGVkIHRoYXQgdGhlIHByb3BvcnRpb24gb2YgYWxsIENhbmFkaWFucyB3aG8gaWRlbnRpZmllZCDigJxJbmZsYXRpb27igJ0gYXMgdGhlIG1vc3QgaW1wb3J0YW50IG5hdGlvbmFsIGNvbmNlcm4gd2FzIHBJbmZsYXRpb24sQXVnXzIzPTAuMTMKRnJvbSB5b3VyIHJlc3VsdHMgaW4gKGEpIGFuZCAoYiksIGNhbiB5b3UgaW5mZXIgdGhhdCB0aGUgcHJvcG9ydGlvbiBvZiBhbGwgQ2FuYWRpYW5zIHdobyBiZWxpZXZlIOKAnEluZmxhdGlvbuKAnSBpcyB0aGUgbW9zdCBpbXBvcnRhbnQgbmF0aW9uYWwgaXNzdWUgaGFzIGluY3JlYXNlZCBzaW5jZSBBdWd1c3Qgb2YgdGhpcyB5ZWFyPyBXaHkgb3Igd2h5IG5vdD8gRW5zdXJlIHlvdSBpbnZva2UgYSBzdGF0aXN0aWNhbCBqdXN0aWZpY2F0aW9uLgoKUi4vIEkgY2FuIGluZmVyIHRoYXQgdGhlIHByb3BvcnRpb24gb2YgQ2FuYWRpYW5zIHdobyBiZWxpZXZlIGluZmxhdGlvbiBpcyB0aGUgbW9zdCBpbXBvcnRhbnQgaXNzdWUgaGFzIGluY3JlYXNlZCBiYXNlZCBvbiB0aGUgZmFjdCB0aGF0IHRoZSBDb25maWRlbmNlIEludGVydmFsIGZvciB0aGUgbW9zdCByZWNlbnQgc3VydmV5IGdvZXMgZnJvbSAxNC40IHRvIDE4Ljg7IHRoZXJlIGlzIG5vIG92ZXJsYXAgd2l0aCB0aGUgcHJldmlvdXMgdmFsdWUgb2YgMC4xMyBmb3VuZCBpbiB0aGUgcHJldmlvdXMgc3VydmV5LCBzaG93aW5nIHVzIHRoYXQgdGhlIHByb3BvcnRpb24gaGFzIGluY3JlYXNlZAoKCjcuIFJlZmVyIHRvIHRoZSBkYXRhIGVuY291bnRlcmVkIGluIFF1ZXN0aW9uIDQgb2YgdGhpcyBhc3NpZ25tZW50LiBQcmlvciB0byBjb21wbGV0aW5nIHBhcnRzIChhKSBhbmQgKGIpLCBjYXJlZnVsbHkgcmVhZCB0aHJvdWdoIGJvdGggcGFydHMgKGEpIGFuZCAoYikuCgphLiBVc2UgdGhlIEJvb3RzdHJhcCBtZXRob2QgdG8gY29tcHV0ZSBhIDk4JSBjb25maWRlbmNlIGludGVydmFsIGZvciDOvMucTEM1MCwgdGhlIG1lZGlhbiBMQzUwIGxldmVsLiBJbnRlcnByZXQgdGhlIG1lYW5pbmcgb2YgdGhpcyBpbnRlcnZhbCBpbiB0aGUgY29udGV4dCBvZiB0aGVzZSBkYXRhLgoKUi4vIEkgd2lsbCBwcm9jZWVkIHRvIHNpbXVsYXRlIHRoZSBtZWRpYW4gd2l0aCBOPTIwMDAsYW5kIHRoZW4gY2FsY3VsYXRlIHRoZSA5OCUgY29uZmlkZW5jZSBJbnRlcnZhbCB1c2luZyBxZGF0YSBmb3IgdGhlIDElIGFuZCA5OSUuIEZpbmFsbHkgSSB3aWxsIGdyYXBoIHRoZXNlIHJlc3VsdHMuIApDb25maWRlbmNlIEludGVydmFsIDk5JSA9ICg0LCAxNikKV2UgY2FuIHNheSB0aGF0IHRoZXJlIGlzIGEgOTglIHByb2JhYmlsaXR5IHRoYXQgdGhlIG1lZGlhbiB2YWx1ZSBmb3IgRERUIExDNTAgaXMgYmV0d2VlbiA0IGFuZCAxNiBwcG0KYGBge3J9Ck4gPSAyMDAwCm4uc2l6ZSA9IGxlbmd0aChsYzUwLmRmJGxjNTApCmJvb3QubWVkaWFuID0gbnVtZXJpYyhOKQpib290LmRhdGEgPSBudW1lcmljKG4uc2l6ZSkKCgpmb3IoaSBpbiAxOk4pewogIAogIGJvb3QuZGF0YSA9IHNhbXBsZShsYzUwLmRmJGxjNTAsIG4uc2l6ZSwgcmVwbGFjZT1UUlVFKSAjc2FtcGxlIHdpdGggcmVwbGFjZW1lbnQgCiAgYm9vdC5tZWRpYW5baV0gPSBtZWRpYW4oYm9vdC5kYXRhKQp9Cgpib290c3RyYXAubWVkaWFuID0gZGF0YS5mcmFtZShib290Lm1lZGlhbikgI2RhdGEgZnJhbWUgaG9sZGluZyAyMDAwIGRpZmZlcmVudCBib290c3RyYXAgc2FtcGxlIG1lZGlhbnMKaGVhZChib290c3RyYXAubWVkaWFuLCA0KQpgYGAKCgpgYGB7cn0KdGFpbChib290c3RyYXAubWVkaWFuLCA0KQpgYGAKCgpgYGB7cn0KbGM1MC5tZWRpYW5fOTkgPSBxZGF0YShib290Lm1lZGlhbiwgYygwLjAxLCAwLjk5KSwgZGF0YT1ib290c3RyYXAubWVkaWFuKQpsYzUwLm1lZGlhbl85OQpgYGAKCgpgYGB7cn0KZ2dwbG90KGJvb3RzdHJhcC5tZWRpYW4sIGFlcyh4ID0gYm9vdC5tZWRpYW4pKSArIGdlb21faGlzdG9ncmFtKGNvbD0icmVkIiwgZmlsbD0iYmx1ZSIsIGJpbndpZHRoPTAuOCkgKyB4bGFiKCJWYWx1ZXMgb2YgdGhlIFNhbXBsZSBNZWRpYW4iKSArIHlsYWIoIkNvdW50IikgKyBnZ3RpdGxlKCJIaXN0b2dyYW06IERpc3RyaWJ1dGlvbiBvZiBCb290c3RyYXAgU2FtcGxlIE1lZGlhbiIpICsgZ2VvbV92bGluZSh4aW50ZXJjZXB0ID0gbGM1MC5tZWRpYW5fOTlbMV0sIGNvbG9yPSJncmVlbiIpICsgZ2VvbV92bGluZSh4aW50ZXJjZXB0ID0gbGM1MC5tZWRpYW5fOTlbMl0sIGNvbG9yPSJncmVlbiIpCmBgYApiLiBDb21wdXRlIHRoZSA5NSUgYm9vdHN0cmFwIHBlcmNlbnRpbGUgY29uZmlkZW5jZSBpbnRlcnZhbCBmb3IgdGhlIHBvcHVsYXRpb24gc3RhbmRhcmQgZGV2aWF0aW9uLCDPgy4gSW4gYWRkaXRpb24sIGludGVycHJldCB0aGUgbWVhbmluZyBvZiB5b3VyIGludGVydmFsIGluIHRoZSBjb250ZXh0IG9mIHRoZXNlIGRhdGEuCgpSLi8gRm9yIHRoaXMgcXVlc3Rpb24sIEkgd2lsbCBmaW5kIHRoZSBjb25maWRlbmNlIGludGVydmFsIGZvciB0aGUgdmFyaWFuY2UgZmlyc3QgYW5kIHRoZW4gdGFrZSB0aGUgc3Egcm9vdCBvZiB0aGVzZSByZXN1bHRzIGFyZSB0aHcgZGF0YSBmb3IgdGhlIDk1JSBjb25maWRlbmNlIGludGVydmFsIGZvciB0aGUgc2Q6ICgzLjE3MTIsIDcuODYwNykKCldlIGNhbiBzYXkgdGhhdCB0aGVyZSBpcyBhIDk1JSBwcm9iYWJpbGl0eSB0aGF0IHRoZSBzdGFuZGFyZCBkZXZpYXRpb24gdmFsdWUgZm9yIEREVCBMQzUwIGlzIGJldHdlZW4gMy4xMjgxIGFuZCA3LjkxODMgcHBtCmBgYHtyfQpOID0gMjAwMApuLnNpemUgPSBsZW5ndGgobGM1MC5kZiRsYzUwKQpib290LnZhciA9IG51bWVyaWMoTikKYm9vdC5kYXRhID0gbnVtZXJpYyhuLnNpemUpCgoKZm9yKGkgaW4gMTpOKXsKICAKICBib290LmRhdGEgPSBzYW1wbGUobGM1MC5kZiRsYzUwLCBuLnNpemUsIHJlcGxhY2U9VFJVRSkgI3NhbXBsZSB3aXRoIHJlcGxhY2VtZW50IAogIGJvb3QudmFyW2ldID0gdmFyKGJvb3QuZGF0YSkKfQoKYm9vdHN0cmFwLnZhciA9IGRhdGEuZnJhbWUoYm9vdC52YXIpICNkYXRhIGZyYW1lIGhvbGRpbmcgMjAwMCBkaWZmZXJlbnQgYm9vdHN0cmFwIHNhbXBsZSB2YXJpYW5jZQpoZWFkKGJvb3RzdHJhcC52YXIsIDQpCmBgYAoKYGBge3J9CnRhaWwoYm9vdHN0cmFwLnZhciwgNCkKYGBgCmBgYHtyfQpsYzUwLnZhcl85NSA9IHFkYXRhKGJvb3QudmFyLCBjKDAuMDI1LCAwLjk3NSksIGRhdGE9Ym9vdHN0cmFwLnZhcikKbGM1MC52YXJfOTUKYGBgCgoKYGBge3J9CmdncGxvdChib290c3RyYXAudmFyLCBhZXMoeCA9IGJvb3QudmFyKSkgKyBnZW9tX2hpc3RvZ3JhbShjb2w9InJlZCIsIGZpbGw9ImJsdWUiLCBiaW53aWR0aD0xKSArIHhsYWIoIlZhbHVlcyBvZiB0aGUgU2FtcGxlIFZhcmlhbmNlIikgKyB5bGFiKCJDb3VudCIpICsgZ2d0aXRsZSgiSGlzdG9ncmFtOiBEaXN0cmlidXRpb24gb2YgQm9vdHN0cmFwIFNhbXBsZSBWYXJpYW5jZSIpICsgZ2VvbV92bGluZSh4aW50ZXJjZXB0ID0gbGM1MC52YXJfOTVbMV0sIGNvbG9yPSJncmVlbiIpICsgZ2VvbV92bGluZSh4aW50ZXJjZXB0ID0gbGM1MC52YXJfOTVbMl0sIGNvbG9yPSJncmVlbiIpCmBgYAoKYGBge3J9CmxjNTAuc2RfOTUgPSBzcXJ0KGxjNTAudmFyXzk1KQpsYzUwLnNkXzk1CmBgYAo4LiBBIG5hdGlvbmFsIHN1cnZleSA0IG9mIG49Mzk5ICDigJxHZW4gWuKAnS1lcnMgLSBzb21lb25lIHdobyBpcyBib3JuIGluIHRoZSB5ZWFycyAxOTk2IC0gMjAxMCAoaW5jbHVzaXZlKSB3YXMgdGFrZW4uIEVhY2ggd2FzIHRoZW4gYXNrZWQgdGhlIGZvbGxvd2luZyBxdWVzdGlvbjoK4oCcSWYgYSBmZWRlcmFsIGVsZWN0aW9uIHdlcmUgaGVsZCB0b21vcnJvdywgd2hpY2ggb25lIG9mIHRoZSBmb2xsb3dpbmcgcGFydGllcyB3b3VsZCB5b3Ugdm90ZSBmb3IgaW4geW91ciBjb25zdGl0dWVuY3k/4oCdClRoZSByZXN1bHRzPwoKMTI4IHJlc3BvbmRlZCDigJxDb25zZXJ2YXRpdmXigJ0gKENvbnNlcnZhdGl2ZSBQYXJ0eSBvZiBDYW5hZGEpCjk2IHJlc3BvbmRlZCDigJxMaWJlcmFs4oCdIChMaWJlcmFsIFBhcnR5IG9mIENhbmFkYSkKMTA0IHJlc3BvbmRlZCDigJxORFDigJ0gKE5ldyBEZW1vY3JhdGljIFBhcnR5IG9mIENhbmFkYSkKUmVzcG9uZGVudHMgd2VyZSBwcm92aWRlZCB3aXRoIGEgZmV3IG1vcmUg4oCcY2xvc2VkIG9wdGlvbnPigJ0sIGluY2x1ZGluZyB0aGUgQmxvYyBRdWViZWNvaXMsIFBlb3BsZeKAmXMgUGFydHksIGFuZCBHcmVlbiBQYXJ0eS4KCmEuIENvbXB1dGUgdGhlIDk1JSBjb25maWRlbmNlIGludGVydmFsIGZvciBwQ29uLCB0aGUgcHJvcG9ydGlvbiBvZiBhbGwgR2VuIFotZXJzIGluIENhbmFkYSB0aGF0IHdpbGwgdm90ZSBmb3IgdGhlaXIgcmVzcGVjdGl2ZSBDb25zZXJ2YXRpdmUgTWVtYmVyIG9mIFBhcmxpYW1lbnQgY2FuZGlkYXRlL2NvbnN0aXR1ZW5jeSwgaW4gYW4gZWxlY3Rpb24gd2VyZSDigJxoZWxkIHRvbW9ycm934oCdLgoKUi4vIFNpbmNlIHdlIGtub3cgbiBhbmQgbmNvbnNlcnZhdGl2ZSwgd2UgY2FtIHVzZSBwcm9wLnRlc3QoKSB0byBkZXRlcm1pbmUgdGhlIGNvbmZpZGVuY2UgaW50ZXJ2YWwgdXNpbmcgaXRzIGRlZmF1bHQgOTUlIGFuZCB0aGUgcGx1cy0yL3BsdXMtNCB0byBtYWtlIHRoZSBpbnRlcnZhbCB0aWdodGVyLgpQY29ucyA5NSUgQ0kgPSAoMC4yNzg4LDAuMzY5NyApCkFjY29yZGluZyB0byB0aGVzZSByZXN1bHRzIHdlIGNhbiBzYXkgd2l0aCBhIDk1JSBjb25maWRlbmNlIHRoYXQgYmV0d2VlbiAyNy44OCBhbmQgMzYuOTcgJSBvZiBHZW4gWi1lcnMgd2lsbCB2b3RlIGNvbnNlcnZhdGl2ZS4KCmBgYHtyfQpjaTk1Y29uLnByb3AgPSBwcm9wLnRlc3QoMTI4KzIsIDM5OSs0LCBjb3JyZWN0PUZBTFNFKSRjb25mCmNpOTVjb24ucHJvcApgYGAKYi4gQ29uc2lkZXIgdGhlIGJvb3RzdHJhcCBzdGF0aXN0aWMgcMucQ29uPVhDb24rMjM5OSs0Ci4gV3JpdGUgdGhlIFIgY29kZSB0aGF0IHdpbGwgZ2VuZXJhdGUgYSBib290c3RyYXAgZGlzdHJpYnV0aW9uIGZvciBwy5xDb24KLiBVc2UgMTAwMCBhcyB0aGUgbnVtYmVyIG9mIHJlcGxpY2F0aW9ucy9pdGVyYXRpb25zLgoKYGBge3J9Cm5zYW1wbGVzID0gMTAwMCAgI25vLiBvZiBzaW11bGF0aW9ucwpzYW1wbGUucGhhdF9jb24gPSBudW1lcmljKG5zYW1wbGVzKSAjZGF0YSB2ZWN0b3IgdG8gaG9sZCAxMDAwIHNhbXBsZXMgcmVwcmVzZW50aW5nIHRoZSBnZW4gei1lcnMgdGhhdCBjaG9vc2UgY29uc2VydmF0aXZlCnNpemUgPSAzOTkKCmZvcihpIGluIDE6bnNhbXBsZXMpewogIGJvb3QuZGF0YSA9IHJiaW5vbSgxLHNpemUsMC4zMikgI3NpbXVsYXRlcyBhIGJpbmFyeSBzYW1wbGUgcmVwcmVzZW50aW5nIHRoZSBnZW56LWVycyB0aGF0IGNob29zZSBjb25zZXJ2YXRpdmUga25vd2luZyBQY29uID0gMTI4LzM5OSA9IDAuMzMKICBzYW1wbGUucGhhdF9jb25baV0gPSAoYm9vdC5kYXRhICsgMikvKHNpemUgKzQpICNjb21wdXRlIHRoZSBwaGF0IHVzaW5nIHBsdXMyL3BsdXM0IGFuZCBzdG9yZXMgaXQgaW4gdGhlIHNhbXBsZS5waGF0X2NvbiBsaXN0Cn0KCmJvb3RzdHJhcC5jb24gPSBkYXRhLmZyYW1lKHNhbXBsZS5waGF0X2NvbikKaGVhZChib290c3RyYXAuY29uLCA0KQpgYGAKYGBge3J9CnRhaWwoYm9vdHN0cmFwLmNvbiwgNCkKYGBgCgoKYy4gRnJvbSB5b3VyIHJlc3VsdCBpbiBwYXJ0IChiKSwgY29tcHV0ZSBhIDk1JSBib290c3RyYXAgY29uZmlkZW5jZSBpbnRlcnZhbCBmb3IgcENvbi4KCmBgYHtyfQpjaTk1Y29uLmJvb3QgPSBxZGF0YSh+c2FtcGxlLnBoYXRfY29uLCBjKDAuMDI1LCAwLjk3NSksIGRhdGE9Ym9vdHN0cmFwLmNvbikKY2k5NWNvbi5ib290CmBgYApgYGB7cn0KZ2dwbG90KGJvb3RzdHJhcC5jb24sIGFlcyh4ID0gc2FtcGxlLnBoYXRfY29uKSkgKyBnZW9tX2hpc3RvZ3JhbShjb2w9ImdyZWVuIiwgZmlsbD0iYmx1ZSIsIGJpbndpZHRoPTAuMDUpICsgeGxhYigiVmFsdWVzIG9mIHRoZSBTYW1wbGUgUHJvcG9ydGlvbiIpICsgeWxhYigiQ291bnQiKSArIGdndGl0bGUoIkhpc3RvZ3JhbTogRGlzdHJpYnV0aW9uIG9mIEJvb3RzdHJhcCBTYW1wbGUgUHJvcG9ydGlvbiIpICsgZ2VvbV92bGluZSh4aW50ZXJjZXB0ID0gY2k5NWNvbi5wcm9wWzFdLCBjb2xvcj0icmVkIikgKyBnZW9tX3ZsaW5lKHhpbnRlcmNlcHQgPSBjaTk1Y29uLnByb3BbMl0sIGNvbG9yPSJyZWQiKSArIGdlb21fdmxpbmUoeGludGVyY2VwdCA9IGNpOTVjb24uYm9vdFsxXSwgY29sb3I9InB1cnBsZSIpICsgZ2VvbV92bGluZSh4aW50ZXJjZXB0ID0gY2k5NWNvbi5ib290WzJdLCBjb2xvcj0icHVycGxlIikKYGBgCgpkLiBDb25zaWRlciB5b3VyIHJlc3VsdHMgaW4gcGFydHMgKGEpIGFuZCAoYykuIENvbXBhcmUgdGhlIHR3byByZXN1bHRzLiBJZiB5b3UgaGFkIHRvIHBpY2sgb25lIGFzIHRoZSDigJxiZXN04oCdIGVzdGltYXRlIGZvciB0aGUgdW5rbm93biB2YWx1ZSBvZiBwQ29uLCB3aGljaCBvbmUgd291bGQgeW91IHNlbGVjdD8gUHJvdmlkZSBhIGp1c3RpZmljYXRpb24gZm9yIHlvdXIgY2hvaWNlLgoKUi4vIGZyb20gYSkgQ0k5NS5wcm9wID0gKDAuMjc4OCwgMC4zNjQ3KSAtLT4gMC4zNjQ3IC0gMC4yNzg4ID0gMC4wOTA5IChyZWQpCiAgICAgICAgIGIpIENJOTUuYm9vdCA9ICgwLjI3NzksIDAuMzYyOCkgLS0+IDAuMzY5NyAtIDAuMjc1NCA9IDAuMDg0OSAocHVycGxlKQogICAgICAgICAKICAgICAgICAgVGhlc2UgaW50ZXJ2YWxzIGFyZSB2ZXJ5IGNsb3NlLCBpZiBJIGhhdmUgdG8gY2hvb3NlIG9uZSwgSSBjaG9vc2UgdGhlIG9uZSB3aXRoIHRoZSBzbWFsbGVyIGludGVydmFsIHdoaWNoIGluIHRoaXMgY2FzZSBpcyB0aGUgaW50ZXJ2YWwgZm91bmQgYnkgcnVubmluZyBib29zdHJhcAoKOS4gSW4gdGhpcyBxdWVzdGlvbiB5b3Ugd2lsbCB1c2UgdGhlIGFsYmVydGFjb3VudGllc3NhbXBsZWQyMDE5LmNzdi4gVGhlIGRhdGEgYXBwZWFyaW5nIGluIHRoaXMgZmlsZSBhcmUgdGhlIHJlc3VsdHMgb2YgYSByYW5kb20gc2FtcGxlIG9mIG49MTAwIGNvdW50aWVzIGluIEFsYmVydGEuIEZvciBlYWNoIGNvdW50eSwgdGhlIG1lZGlhbiBob3VzZWhvbGQgaW5jb21lIHdhcyBjb21wdXRlZC4gVGhpcyBmZWF0dXJlIGFwcGVhcnMgaW4gdGhlIE9yaWdpbmFsVmFsdWUgY29sdW1uLgoKUmVhZCB0aGlzIGRhdGEgaW50byBhIFIgZGF0YSBmcmFtZS4gVG8gcmVhZCB0aGlzIGludG8gUiwgeW91IHdpbGwgaGF2ZSB0byBzZWxlY3QgdGhlIFJhdyB0YWIgYXBwZWFyaW5nIG9uIHRoZSB0b3AgcmlnaHQtaGFuZCBzaWRlLgoKVGhlIGJvb3RzdHJhcCB0IHN0YXRpc3RpYyBpcyBkZWZpbmVkIGFzClRCb290c3RyYXA9WMKvwq/Cr8KvQm9vdOKIkljCr8Kvwq/CryhTbuKImikKd2hlcmUgWMKvwq/Cr8KvCiBhbmQgUwogYXJlIHRoZSBtZWFuIGFuZCBzdGFuZGFyZCBkZXZpYXRpb24gb2YgdGhlIHNhbXBsZS4KCmEuIEZyb20gdGhlc2UgZGF0YSwgZ2VuZXJhdGUgdGhlIGRpc3RyaWJ1dGlvbiBvZiBUQm9vdHN0cmFwLiBEaXNwbGF5IHRoaXMgZGlzdHJpYnV0aW9uLiBVc2UgMTAwMCBmb3IgdGhlIG51bWJlciBvZiBib290c3RyYXBzLgoKYGBge3J9CmFsYmVydGEuY291bnRpZXMgPSByZWFkLmNzdigiYWxiZXJ0YWNvdW50aWVzc2FtcGxlZDIwMTkuY3N2IikKaW5jb21lLm1lZGlhbiA9IGRhdGEuZnJhbWUoYWxiZXJ0YS5jb3VudGllcyRPcmlnaW5hbFZhbHVlKQpoZWFkKGluY29tZS5tZWRpYW4sIDQpCmBgYApgYGB7cn0KdGFpbChpbmNvbWUubWVkaWFuLCA0KQpgYGAKYGBge3J9CnN0YXRzID0gZmF2c3RhdHMoaW5jb21lLm1lZGlhbiRhbGJlcnRhLmNvdW50aWVzLk9yaWdpbmFsVmFsdWUpCnN0YXRzCmBgYApgYGB7cn0Kc2FtcGxlLm1lYW4gPSBzdGF0c1s2XQpzYW1wbGUubWVhbgpgYGAKCmBgYHtyfQpzYW1wbGUuc2QgPSBzdGF0c1s3XQpzYW1wbGUuc2QKYGBgCmBgYHtyfQpOID0gMTAwMApzYW1wbGUuc2l6ZSA9IGxlbmd0aChpbmNvbWUubWVkaWFuJGFsYmVydGEuY291bnRpZXMuT3JpZ2luYWxWYWx1ZSkKYm9vdC5kYXRhID0gbnVtZXJpYyhzYW1wbGUuc2l6ZSkKYm9vdC5tZWFuID0gbnVtZXJpYyhOKQpib290LnQgPSBudW1lcmljKE4pCgpmb3IgKGkgaW4gMTpOKXsKICBib290LmRhdGEgPSBzYW1wbGUoYWxiZXJ0YS5jb3VudGllcyRPcmlnaW5hbFZhbHVlLCBzYW1wbGUuc2l6ZSwgcmVwbGFjZSA9IFRSVUUpCiAgYm9vdC5tZWFuW2ldID0gbWVhbihib290LmRhdGEpCiAgdCA9IChib290Lm1lYW5baV0gLSBzYW1wbGUubWVhbikgLyAoc2FtcGxlLnNkIC8gc3FydChzYW1wbGUuc2l6ZSkpCiAgdAogIGJvb3QudFtpXSA9IHQKfQoKYm9vdC5tZWFuZGYgPSBkYXRhLmZyYW1lKGJvb3QubWVhbikKaGVhZChib290Lm1lYW5kZikKYGBgCgpgYGB7cn0KdGFpbChib290Lm1lYW5kZikKYGBgCgpgYGB7cn0KYm9vdC50dmFsID0gYyhOKQpmb3IoaSBpbiAxOk4pewogIGJvb3QudHZhbFtpXSA9IGJvb3QudFtbaV1dWzFdCn0KCmJvb3QudGRmID0gZGF0YS5mcmFtZShib290LnR2YWwpCmhlYWQoYm9vdC50ZGYpCgpgYGAKYGBge3J9CnRhaWwoYm9vdC50ZGYpCmBgYAoKYGBge3J9CmdncGxvdChib290LnRkZiwgYWVzKHggPSBib290LnR2YWwpKSArIGdlb21faGlzdG9ncmFtKGNvbD0icmVkIiwgZmlsbD0iYmx1ZSIsIGJpbndpZHRoPTAuNCkgKyB4bGFiKCJWYWx1ZXMgb2YgQm9vdHN0cmF0IFQiKSArIHlsYWIoIkNvdW50IikgKyBnZ3RpdGxlKCJIaXN0b2dyYW06IERpc3RyaWJ1dGlvbiBvZiBCb290c3RyYXAgVCIpCgpgYGAKYi4gUmVmZXIgdG8gcGFydCAoYSk6IEEgQm9vdHN0cmFwIHQuQ29uZmlkZW5jZSBJbnRlcnZhbCBmb3IgzrwgIGlzIGRlZmluZWQgYXM6CltYwq/Cr8Kvwq/iiJJ04oiXzrEyKFNu4oiS4oiS4oiaKSxYwq/Cr8Kvwq8rdOKIlzHiiJLOsTIoU27iiJLiiJLiiJopXQp3aGVyZSB04oiXzrEyCiBhbmQgdOKIlzHiiJLOsTIKIGlzIGFyZSDOsTIKIGFuZCAx4oiSzrEyCiBwZXJjZW50aWxlcyBmcm9tIHRoZSBUQm9vdHN0cmFwIGRpc3RyaWJ1dGlvbi4KCkNvbXB1dGUgdGhlIDk1JSBib290c3RyYXAgdCBjb25maWRlbmNlIGludGVydmFsIGZvciDOvE1lZGlhbl9GYW1pbHlfSW5jb21lIGZvciBhbGwgdGhlIGNvdW50aWVzIGluIEFsYmVydGEuCgpOb3RlOiDiiJJ0zrEyICB3aWxsIGJlIGEgbmVnYXRpdmUgdmFsdWUgZHVlIHRvIHRoZSBuYXR1cmUgb2YgdGhlIFN0dWRlbnTigJlzIHQgIGRpc3RyaWJ1dGlvbi4gSGVuY2UgdGhlIOKAnC3igJ0gc2lnbiBpbiBmcm9udC4KCmBgYHtyfQpwZXJjZW50aWxlVCA9IHF1YW50aWxlKGJvb3QudGRmJGJvb3QudHZhbCwgYygwLjAyNSwgMC45NzUpKQpwZXJjZW50aWxlVApgYGAKYGBge3J9Cm1lYW5DSTIuNSA9IHNhbXBsZS5tZWFuIC0gKHBlcmNlbnRpbGVUWzFdICogKHNhbXBsZS5zZC9zcXJ0KHNhbXBsZS5zaXplKSkpCm1lYW5DSTIuNSRtZWFuCmBgYAogCmBgYHtyfQptZWFuQ0k5Ny41ID0gc2FtcGxlLm1lYW4gLSAocGVyY2VudGlsZVRbMl0gKiAoc2FtcGxlLnNkL3NxcnQoc2FtcGxlLnNpemUpKSkKbWVhbkNJOTcuNSRtZWFuCmBgYApjLiBDb21wdXRlIHRoZSAoaSkgOTUlIGJvb3RzdHJhcCBwZXJjZW50aWxlIGNvbmZpZGVuY2UgaW50ZXJ2YWwgZXN0aW1hdGUgb2YgzrxNZWRpYW5fRmFtaWx5X0luY29tZSAgYW5kIChpaSkgdGhlIDk1JSBTdHVkZW504oCZcyB0IGNvbmZpZGVuY2UgaW50ZXJ2YWwgZm9yIM68TWVkaWFuX0ZhbWlseV9JbmNvbWUuCmBgYHtyfQptZWRpYW5JbmNvbWUuY2k5NSA9IHFkYXRhKH5hbGJlcnRhLmNvdW50aWVzLk9yaWdpbmFsVmFsdWUsIGMoMC4wMjUsIDAuOTc1KSwgZGF0YT1pbmNvbWUubWVkaWFuKQptZWRpYW5JbmNvbWUuY2k5NQoKYGBgCgoKYGBge3J9CkJvb3RUY2k5NSA9IHFkYXRhKGJvb3QudHZhbCwgYygwLjAyNSwgMC45NzUpLCBkYXRhPWJvb3QudGRmKQpCb290VGNpOTUKCmBgYApELiBDb25zaWRlciB5b3VyIHJlc3VsdHMgaW4gcGFydHMgKGIpIGFuZCAoYyk6IElmIHlvdSB3ZXJlIHRvIHJlcG9ydCBvbmUgb2YgdGhlc2UgY29uZmlkZW5jZSBpbnRlcnZhbHMgdG8gYSBjbGllbnQsIHdoYXQgd291bGQgYmUgeW91ciBjb25zdWx0YXRpb24/IFByb3ZpZGUgYSBzaG9ydCBwYXJhZ3JhcGggZXhwbGFpbmluZyB3aGF0IHRoZSB2YWx1ZSBvZiDOvE1lZGlhbl9GYW1pbHlfSW5jb21lIENvdWxkIHBvc3NpYmx5IGJlLCBhbmQgd2h5IHlvdSBjaG9zZSB0aGUgbWV0aG9kIG9mIGNvbmZpZGVuY2UgaW50ZXJ2YWwgZXN0aW1hdGlvbiB0byByZXBvcnQgZnJvbS4KCkkgd291bGQgdXNlIHRoZSA5NSUgQ29uZmlkZW5jZSBJbnRlcnZhbCBmb3VuZCBpbiBwYXJ0IGIgYXMgaXQgcmVwb3J0cyBhIHRpZ2h0ZXIgaW50ZXJ2YWwgZm9yIHRoYW4gdGhlIG9uZSByZXBvcnRlZCBpbiBDCgpiKSA4MzAyOS4yOCAtIDkxOTExLjI4CmMpIDM0NzQ3LjUwIC0gMTMxMTE5LjUwCgo=