library(plyr)
library(binom)
library(car)
library(collapsibleTree)
library(dbplyr)
library(dplyr)
library(EnvStats)
library(ggformula)
library(ggplot2)
library(gmodels)
library(htmltools)
library(ISLR)
library(knitr)
library(lawstat)
library(markdown)
library(mosaic)
library(mdsr)
library(mosaicData)
library(nycflights13)
library(olsrr)
library(purrr)
library(plotly)
library(resampledata)
library(rmarkdown)
library(rpart)
library(rpart.plot)
library(rvest)
library(SDaA)
library(shiny)
library(stringi)
library(tibble)
library(tidyr)
library(tidyselect)
library(tinytex)
library(yaml)
library(shiny)
Attempt all problems below. You will be required to complete this
assignment in R Notebook or R Markdown. Convert your work to a .pdf file
and submit to Gradescope.ca.
Ensure you justify all computation and data visualizations with
accompanying code.
1. The Capital Asset Price Model (CAPM) is a
financial model that attempts to predict the rate of return on a
financial instrument, such as a common stock, in such a way that it is
linearly related to the rate of return on the overal market.
Specifically
\[
R_{StockA,i} = \beta_{0} + \beta_{1}R_{Market, i} + e_{i}
\]
(Note: To align the notation with a stock’s ``beta’’, \(\beta_{0} = A\) and \(\beta_{1} = B\))
You are to study the relationship between the two variables and
estimate the above model:
\(R_{SUNCOR, i}\) - rate of return
on Stock A for month \(i\), \(i = 1, 2, \cdots, 59\).
\(R_{Market, i}\) - market rate of
return for month \(i\), \(i = 1, 2, \cdots, 59\).
\(\beta_{1}\) represent’s the stocks
`beta’ value, or its systematic risk. It measure’s the stocks
volatility related to the market volatility. \(\beta_{0}\) represents the risk-free
interest rate.
The data appeaing in the file
contains the data on Suncor’s rate of return and the Toronto Composite
Index rate of return for 59 randomly selected months.
Therefore \(R_{SUNCOR, i}\)
represents the monthly rate of return for a common share of Suncor
stock; \(R_{TSE, i}\) represents the
monthly rate of return (increase or decrease) of the TSE Index for the
same month, month \(i\). The first
column in this data file contains the monthly rate of return on Suncor
stock; the second column contains the monthly rate of return on the TSE
index for the same month.
Read this data into R Studio and answer the questions posed
below.
capmdata.df = read.csv("https://raw.githubusercontent.com/Statman44/Data602/main/capm.csv")
head(capmdata.df, 3) #to get a sense of what the data look like
- Appropriately visualize these data. What can you infer from this
visualization? Provide a brief commentary.
ggplot(capmdata.df, aes(x = TSE.Index, y = Suncor)) + geom_point(col="blue", size = 2) + xlab("TSE Index") + ylab("Suncor") + ggtitle("Plot:TSE Index to Suncor")

The graph shows a positive relation between the variables TSE.Index
and Suncor
- Estimate the model above.
predict.suncorRate = lm(Suncor ~ TSE.Index, data = capmdata.df)
predict.suncorRate$coef
(Intercept) TSE.Index
0.01664794 0.53869099
\[
\widehat{Suncor}_{i} = 0.01664794 + (0.53869099*TSE.Index_{i})
\hspace{0.5in} \text{(Note: There is no}\:\: e_{i} \:\:\text{term on the
estimate of the model)}
\] (c) In the context of these data, interpret the meaning of
your estimates of the estimates \(\widehat{\beta}_{0}\) and \(\widehat{\beta}_{1}\), in the context of
these data.
The rate of return of Suncor will increase by an average/mean of
0.53869099 per every unit the TSE Index increases
- Refer to your answer in (b) In a certain month, the rate of return
on the TSE Index was 4%. Predict the rate of return on Suncor stock for
the same month.
0.01664794 + (0.53869099*0.04)
[1] 0.03819558
predict(predict.suncorRate, data.frame(TSE.Index=0.04))
1
0.03819558
- Think about the conditions of this model in the context of
these data. Create the visualizations that inspect each of the two
conditions and provide commentary that addresses the validity (or
invalidity) of each.
We need to check for the 2 conditions: Normality of Residuals and
Homoscedasticity 1. Normalcy of Residuals
tseindex = capmdata.df$TSE.Index #read tse.index
suncorvalues = capmdata.df$Suncor #read Suncor rate
predicted.SuncorRate = predict.suncorRate$fitted.values #get fitted values from the predict.suncor
eisSuncor = predict.suncorRate$residuals #gget residual from predict.suncor
standardized.eis=rstandard(predict.suncorRate) #applies rstandard to predeict.suncor and place them in standardized.eis variable
diagnosticdf = data.frame(tseindex, suncorvalues, predicted.SuncorRate, eisSuncor, standardized.eis) #create a data frame with all variables above
head(diagnosticdf,4)
ggplot(diagnosticdf, aes(sample = standardized.eis)) + stat_qq(col='blue') + stat_qqline(col='red') + ggtitle("Normal Probability Plot of Standardized Residuals")

This graph proves the normalcy of residuals.
- Homoscedasticity
ggplot(diagnosticdf, aes(x = tseindex, y = standardized.eis)) + geom_point(size=2, col='blue', position="jitter") + xlab("TSE Index") + ylab("Standardized Residuals") + ggtitle("Scatterplot of Residuals vs predicted values") + geom_hline(yintercept=0, color="red", linetype="dashed")

- From these data, can you infer that the monthly rate of return of
Suncor stock can be expressed as a positive linear function of the
monthly rate of return of the TSE Index? State your statistical
hypotheses, compute (and report) both the test statistic and the \(P\)-value and provide your decision.
Hypotheses H0: B1<=0
HA:B1>0
summary(predict.suncorRate)
Call:
lm(formula = Suncor ~ TSE.Index, data = capmdata.df)
Residuals:
Min 1Q Median 3Q Max
-0.187377 -0.068498 -0.003155 0.072103 0.252016
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 0.01665 0.01177 1.414 0.1628
TSE.Index 0.53869 0.19178 2.809 0.0068 **
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Residual standard error: 0.08995 on 57 degrees of freedom
Multiple R-squared: 0.1216, Adjusted R-squared: 0.1062
F-statistic: 7.89 on 1 and 57 DF, p-value: 0.006797
Tobs=(0.53869099-0)/0.19177963
Tobs
[1] 2.808906
Tobs=2.8089 with df=57 same as the result obtained with the
predict.suncorRate and a Pvalue = 0.0068/2 = 0.00034 (We are looking at
the probability of T > Tobs so we divide Pvalue by 2)
1-pt(2.8089, 57-2)
[1] 0.003434463
As per Pvalue = 0.00343, (less than 0.05) we reject H0. We can say
that the monthly rate of return of Suncor stock can be expressed as a
positive linear function of the monthly rate of return of the TSE
Index
- Compute a 95% confidence interval for \(\beta_{1}\), then interpret its meaning in
the context of these data.
confint(predict.suncorRate, conf.int=0.95)
2.5 % 97.5 %
(Intercept) -0.006928949 0.04022482
TSE.Index 0.154658904 0.92272309
the regression coefficient will have a vale between 0.1546 and 0.9227
in 95% of the cases.
- Compute a 95% confidence interval for the mean monthly rate of
return of Suncor stock when the TSE has a monthly rate of return of
3%.
predict(predict.suncorRate, newdata=data.frame(TSE.Index=0.03), interval='conf')
fit lwr upr
1 0.03280867 0.007660256 0.05795708
when the TSE.Index value is 0.03, Suncor monthly rate will be 95% of
the time between 0.00766 and 0.0579
- In a month of September, the TSE Index had a rate of return of
1.16%. With 95% confidence, compute the September rate of return for
Suncor stock.
predict(predict.suncorRate, newdata=data.frame(TSE.Index=0.0116), interval='conf')
fit lwr upr
1 0.02289675 -0.0006404417 0.04643395
We can say with 95% confidence that the rate of return of the Suncor
stock for that month of September was between -0.00064 and 0.04643
- Recall the Bootstrap Method. From these data, use the bootstrap
method to create a 95% confidence interval for mean monthly rate of
return of Suncor stock when the TSE has a monthly rate of return of 3%.
Compare your result to your result in part (h). Use 1000 iterations for
your bootstrap. Carefully consider how you would resample
bivariate data points \((x_{TSE, i},
y_{Suncor, i})\).
Nsims = 1000
TSEval = 0.03
boot_predict = numeric(1000)
pair_x_y = dim(capmdata.df)[1]
for(i in 1:Nsims)
{
index = sample(pair_x_y,replace=TRUE)
dsample = capmdata.df[index, ]
temp = lm(Suncor~TSE.Index, data = dsample)
boot_predict[i] = (coef(temp)[1]) + ((coef(temp)[2])*TSEval)
}
reg_bootstrap = data.frame(boot_predict)
head(reg_bootstrap,4)
ggplot(reg_bootstrap, aes(x = boot_predict)) + geom_histogram(col='red', fill='blue', binwidth=0.006) + xlab("Predicted Values of Suncor Rate when TSE.Index = 0.03") + ylab("Count") +
ggtitle("Distribution of Bootstrap Statistic: Predicted Suncor Rate")

qdata(~boot_predict, c(0.025,0.975), data=reg_bootstrap)
2.5% 97.5%
0.008810805 0.056672167
This confidence interval is close to the interval found in h.
2. Was Barry Bonds using Steroids? During the 2001
Season, Bary Bonds hit a major leauge record of 73 home runs.
The following bivariate data set gives the year and the number of
home runs divided by the number of at bats - attempts to hit the ball -
for each season. The number of homeruns is not used as later in his
career he was given intentional walks, which do not count as an at
bat.
In this exercise, you will build on your learning of model building
and attempt to predict the number of home runs Barry Bonds would
have hit in the 2001 season. These data are stored in the data
file.
Remove the data point that corresponds to the season ==
2001. After which, you are attempting to build a statistical
model of the following form: \[
HRAT_{i} = A + B*Year_{i} + e_{i} \hspace{0.5in} i = 1987, 1988, \cdots,
2000.
\] Carry out the appropriate statistical analysis to justify your
answer. Communicate your answer in the form of a few paragraphs. In
writing your response and statistical justification, ensure that any
conditions/assumptions of the model stated above are mentioned and
checked.
bbonds.df = read.csv("https://raw.githubusercontent.com/Statman44/Data602/main/bondsdata.csv")
head(bbonds.df)
tail(bbonds.df)
Create a new dataframe without 2001
bbonds1.df = bbonds.df %>% filter(season!=2001)
tail(bbonds1.df)
ggplot(bbonds1.df, aes(x = season, y = hrat)) + geom_point(col="blue", size = 2) + xlab("Season") + ylab("hrat") + ggtitle("Scatter plot for Barry Bonds' (hrat) Homeruns 1987-2000")

The scatterplot pattern does not show a cone like pattern, seems to
follow linearity
predict.homerun = lm(hrat~season, data=bbonds1.df)
predict.homerun$coefficients
(Intercept) season
-7.992499290 0.004044169
summary(predict.homerun)
Call:
lm(formula = hrat ~ season, data = bbonds1.df)
Residuals:
Min 1Q Median 3Q Max
-0.020722 -0.009931 0.001841 0.007701 0.023055
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) -7.9924993 1.7566775 -4.550 0.000666 ***
season 0.0040442 0.0008812 4.589 0.000622 ***
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Residual standard error: 0.01329 on 12 degrees of freedom
Multiple R-squared: 0.6371, Adjusted R-squared: 0.6068
F-statistic: 21.06 on 1 and 12 DF, p-value: 0.0006222
Se = 0.01329 r^2 = 0.6371 t value = 4.589 b = 0.00404 a = -7.9925
CONDITIONS OF THE MODEL
actual.hrat = bbonds1.df$hrat
actual.season= bbonds1.df$season
eis.bbonds=predict.homerun$residuals
se.bbonds = summary(predict.homerun)$sigma
standardized.eis = rstandard(predict.homerun)
predicted.values.hrat = predict.homerun$fitted.values
diagnostic.df = data.frame(actual.season, actual.hrat, predicted.values.hrat,eis.bbonds, standardized.eis)
head(diagnostic.df)
- Normality
ggplot(diagnostic.df, aes(sample = standardized.eis)) + stat_qq(col='blue') + stat_qq_line(col='red') + ggtitle("Normal Probability Plot of Standardized Residuals")

The line fits through the pattern. This can be considered linear and
proves Normality
- Homoscedasticity
ggplot(diagnostic.df, aes(x = actual.season, y = standardized.eis)) + geom_point(size=2, col='blue', position="jitter") + xlab("Season") + ylab("Residuals") +
ggtitle("Season to Standardized Residuals") + geom_hline(yintercept=0, color="red", linetype="dashed")

The spread does not show any cone like patterns on the spread of
residuals. We can consider it homoscedastic
Hypotheses H0: beta1 = 0 HA: Beta1 != 0
F-TEST
summary(aov(predict.homerun))
Df Sum Sq Mean Sq F value Pr(>F)
season 1 0.003721 0.003721 21.06 0.000622 ***
Residuals 12 0.002120 0.000177
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
summary(aov(predict.homerun))[[1]][["Pr(>F)"]][1]
[1] 0.0006222474
Pvalue is 0.000622 so we reject H0
PREDICTING HOMERUNS 2001 SEASON
nh = data.frame(season=2021)
predict(predict.homerun, newdata=nh, interval='prediction')
fit lwr upr
1 0.1807667 0.1200519 0.2414816
Extract Hrat for 2001
bbonds.df[15,2]
[1] 0.1534
use Hrat 2001 and number of homeruns to calculate atbat
atbat = 73/0.1534
atbat
[1] 475.8801
use Hrat 2001 and number of homeruns to calculate atbat
atbat = 73/0.1534
atbat
[1] 475.8801
Use fit value of the model and atbat to do the prediction
predict.2001 = atbat*0.1808
predict.2001
[1] 86.03911
predict.2001_upper = atbat * 0.1331382
predict.2001_lower = atbat * 0.0666284
predict.2001_upper
[1] 63.35781
predict.2001_lower
[1] 31.70713
LS0tCnRpdGxlOiAiRGF0YSA2MDIgLSBBc3NpZ25tZW50IEZvdXIsIFBhcnQgSUkiCm91dHB1dDoKICBodG1sX25vdGVib29rOiBkZWZhdWx0CiAgcGRmX2RvY3VtZW50OiBkZWZhdWx0CiAgaHRtbF9kb2N1bWVudDoKICAgIGRmX3ByaW50OiBwYWdlZApkYXRlOiAiRHVlIE9jdG9iZXIgMTUsIDIwMjMgQCAxMTo1OXBtIgotLS0KCmBgYHtyfQpsaWJyYXJ5KHBseXIpCmxpYnJhcnkoYmlub20pCmxpYnJhcnkoY2FyKQpsaWJyYXJ5KGNvbGxhcHNpYmxlVHJlZSkKbGlicmFyeShkYnBseXIpCmxpYnJhcnkoZHBseXIpCmxpYnJhcnkoRW52U3RhdHMpCmxpYnJhcnkoZ2dmb3JtdWxhKQpsaWJyYXJ5KGdncGxvdDIpCmxpYnJhcnkoZ21vZGVscykKbGlicmFyeShodG1sdG9vbHMpCmxpYnJhcnkoSVNMUikKbGlicmFyeShrbml0cikKbGlicmFyeShsYXdzdGF0KQpsaWJyYXJ5KG1hcmtkb3duKQpsaWJyYXJ5KG1vc2FpYykKbGlicmFyeShtZHNyKQpsaWJyYXJ5KG1vc2FpY0RhdGEpCmxpYnJhcnkobnljZmxpZ2h0czEzKQpsaWJyYXJ5KG9sc3JyKQpsaWJyYXJ5KHB1cnJyKQpsaWJyYXJ5KHBsb3RseSkKbGlicmFyeShyZXNhbXBsZWRhdGEpCmxpYnJhcnkocm1hcmtkb3duKQpsaWJyYXJ5KHJwYXJ0KQpsaWJyYXJ5KHJwYXJ0LnBsb3QpCmxpYnJhcnkocnZlc3QpCmxpYnJhcnkoU0RhQSkKbGlicmFyeShzaGlueSkKbGlicmFyeShzdHJpbmdpKQpsaWJyYXJ5KHRpYmJsZSkKbGlicmFyeSh0aWR5cikKbGlicmFyeSh0aWR5c2VsZWN0KQpsaWJyYXJ5KHRpbnl0ZXgpCmxpYnJhcnkoeWFtbCkKbGlicmFyeShzaGlueSkKYGBgCgpBdHRlbXB0IGFsbCBwcm9ibGVtcyBiZWxvdy4gWW91IHdpbGwgYmUgcmVxdWlyZWQgdG8gY29tcGxldGUgdGhpcyBhc3NpZ25tZW50IGluIFIgTm90ZWJvb2sgb3IgUiBNYXJrZG93bi4gQ29udmVydCB5b3VyIHdvcmsgdG8gYSAucGRmIGZpbGUgYW5kIHN1Ym1pdCB0byBbR3JhZGVzY29wZS5jYV0oaHR0cHM6Ly93d3cuZ3JhZGVzY29wZS5jYS8pLiAKCkVuc3VyZSB5b3UganVzdGlmeSBhbGwgY29tcHV0YXRpb24gYW5kIGRhdGEgdmlzdWFsaXphdGlvbnMgd2l0aCBhY2NvbXBhbnlpbmcgY29kZS4gCgoKKioxLioqIFRoZSBDYXBpdGFsIEFzc2V0IFByaWNlIE1vZGVsIChDQVBNKSBpcyBhIGZpbmFuY2lhbCBtb2RlbCB0aGF0IGF0dGVtcHRzIHRvIHByZWRpY3QgdGhlIApyYXRlIG9mIHJldHVybiBvbiBhIGZpbmFuY2lhbCBpbnN0cnVtZW50LCBzdWNoIGFzIGEgY29tbW9uIHN0b2NrLCBpbiBzdWNoIGEgd2F5IHRoYXQgaXQgaXMKbGluZWFybHkgcmVsYXRlZCB0byB0aGUgcmF0ZSBvZiByZXR1cm4gb24gdGhlIG92ZXJhbCBtYXJrZXQuIFNwZWNpZmljYWxseQoKJCQKUl97U3RvY2tBLGl9ID0gXGJldGFfezB9ICsgXGJldGFfezF9Ul97TWFya2V0LCBpfSArIGVfe2l9ICAgCiQkCgooTm90ZTogVG8gYWxpZ24gdGhlIG5vdGF0aW9uIHdpdGggYSBzdG9jaydzIGBgYmV0YScnLCAkXGJldGFfezB9ID0gQSQgYW5kICRcYmV0YV97MX0gPSBCJCkKCgpZb3UgYXJlIHRvIHN0dWR5IHRoZSByZWxhdGlvbnNoaXAgYmV0d2VlbiB0aGUgdHdvIHZhcmlhYmxlcyBhbmQgZXN0aW1hdGUgdGhlIGFib3ZlIG1vZGVsOgoKJFJfe1NVTkNPUiwgaX0kIC0gcmF0ZSBvZiByZXR1cm4gb24gU3RvY2sgQSBmb3IgbW9udGggJGkkLCAkaSA9IDEsIDIsIFxjZG90cywgNTkkLgoKJFJfe01hcmtldCwgaX0kIC0gbWFya2V0IHJhdGUgb2YgcmV0dXJuIGZvciBtb250aCAkaSQsICRpID0gMSwgMiwgXGNkb3RzLCA1OSQuCgoKJFxiZXRhX3sxfSQgcmVwcmVzZW50J3MgdGhlIHN0b2NrcyBgYmV0YScgdmFsdWUsIG9yIGl0cyAqc3lzdGVtYXRpYyByaXNrKi4gSXQgbWVhc3VyZSdzIHRoZSBzdG9ja3Mgdm9sYXRpbGl0eSByZWxhdGVkCnRvIHRoZSBtYXJrZXQgdm9sYXRpbGl0eS4gICRcYmV0YV97MH0kIHJlcHJlc2VudHMgdGhlIHJpc2stZnJlZSBpbnRlcmVzdCByYXRlLgoKVGhlIGRhdGEgYXBwZWFpbmcgaW4gdGhlIFtmaWxlXShodHRwczovL2dpdGh1Yi5jb20vU3RhdG1hbjQ0L0RhdGE2MDIvYmxvYi9tYWluL2JvbmRzZGF0YS5jc3YpIGNvbnRhaW5zIHRoZSBkYXRhIG9uIFN1bmNvcidzIHJhdGUgb2YgcmV0dXJuIGFuZCB0aGUgVG9yb250byBDb21wb3NpdGUgSW5kZXggcmF0ZSBvZiByZXR1cm4gZm9yIDU5IHJhbmRvbWx5IHNlbGVjdGVkIG1vbnRocy4gIAoKVGhlcmVmb3JlICRSX3tTVU5DT1IsIGl9JCByZXByZXNlbnRzIHRoZSBtb250aGx5IHJhdGUgb2YgcmV0dXJuIGZvciBhIGNvbW1vbiBzaGFyZSBvZiBTdW5jb3Igc3RvY2s7IAokUl97VFNFLCBpfSQgcmVwcmVzZW50cyB0aGUgbW9udGhseSByYXRlIG9mIHJldHVybiAoaW5jcmVhc2Ugb3IgZGVjcmVhc2UpIG9mIHRoZSBUU0UgSW5kZXggZm9yIHRoZSBzYW1lIG1vbnRoLCBtb250aCAkaSQuClRoZSBmaXJzdCBjb2x1bW4gaW4gdGhpcyBkYXRhIGZpbGUgY29udGFpbnMgdGhlIG1vbnRobHkgcmF0ZSBvZiByZXR1cm4gb24gU3VuY29yIHN0b2NrOyB0aGUgc2Vjb25kIGNvbHVtbiBjb250YWlucyB0aGUgbW9udGhseSByYXRlIG9mIHJldHVybiBvbiB0aGUgVFNFIGluZGV4IGZvciB0aGUgKnNhbWUgbW9udGgqLiAKClJlYWQgdGhpcyBkYXRhIGludG8gUiBTdHVkaW8gYW5kIGFuc3dlciB0aGUgcXVlc3Rpb25zIHBvc2VkIGJlbG93LiAKYGBge3J9CmNhcG1kYXRhLmRmID0gcmVhZC5jc3YoImh0dHBzOi8vcmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbS9TdGF0bWFuNDQvRGF0YTYwMi9tYWluL2NhcG0uY3N2IikKaGVhZChjYXBtZGF0YS5kZiwgMykgICN0byBnZXQgYSBzZW5zZSBvZiB3aGF0IHRoZSBkYXRhIGxvb2sgbGlrZQpgYGAKCgooYSkgQXBwcm9wcmlhdGVseSB2aXN1YWxpemUgdGhlc2UgZGF0YS4gV2hhdCBjYW4geW91IGluZmVyIGZyb20gdGhpcyB2aXN1YWxpemF0aW9uPyBQcm92aWRlIGEgYnJpZWYgY29tbWVudGFyeS4KCmBgYHtyfQpnZ3Bsb3QoY2FwbWRhdGEuZGYsIGFlcyh4ID0gVFNFLkluZGV4LCB5ID0gU3VuY29yKSkgKyBnZW9tX3BvaW50KGNvbD0iYmx1ZSIsIHNpemUgPSAyKSArIHhsYWIoIlRTRSBJbmRleCIpICsgeWxhYigiU3VuY29yIikgKyBnZ3RpdGxlKCJQbG90OlRTRSBJbmRleCB0byBTdW5jb3IiKSAKCmBgYApUaGUgZ3JhcGggc2hvd3MgYSBwb3NpdGl2ZSByZWxhdGlvbiBiZXR3ZWVuIHRoZSB2YXJpYWJsZXMgVFNFLkluZGV4IGFuZCBTdW5jb3IKCihiKSBFc3RpbWF0ZSB0aGUgbW9kZWwgYWJvdmUuICAKYGBge3J9CnByZWRpY3Quc3VuY29yUmF0ZSA9IGxtKFN1bmNvciB+IFRTRS5JbmRleCwgZGF0YSA9IGNhcG1kYXRhLmRmKQpwcmVkaWN0LnN1bmNvclJhdGUkY29lZgoKYGBgCiQkClx3aWRlaGF0e1N1bmNvcn1fe2l9ID0gMC4wMTY2NDc5NCArICgwLjUzODY5MDk5KlRTRS5JbmRleF97aX0pIFxoc3BhY2V7MC41aW59IFx0ZXh0eyhOb3RlOiBUaGVyZSBpcyBub31cOlw6IGVfe2l9IFw6XDpcdGV4dHt0ZXJtIG9uIHRoZSBlc3RpbWF0ZSBvZiB0aGUgbW9kZWwpfQokJAooYykgSW4gdGhlIGNvbnRleHQgb2YgdGhlc2UgZGF0YSwgaW50ZXJwcmV0IHRoZSBtZWFuaW5nIG9mIHlvdXIgZXN0aW1hdGVzIG9mIHRoZSBlc3RpbWF0ZXMgJFx3aWRlaGF0e1xiZXRhfV97MH0kIGFuZCAkXHdpZGVoYXR7XGJldGF9X3sxfSQsIGluIHRoZSBjb250ZXh0IG9mIHRoZXNlIGRhdGEuCgpUaGUgcmF0ZSBvZiByZXR1cm4gb2YgU3VuY29yIHdpbGwgaW5jcmVhc2UgYnkgYW4gYXZlcmFnZS9tZWFuIG9mIDAuNTM4NjkwOTkgcGVyIGV2ZXJ5IHVuaXQgdGhlIFRTRSBJbmRleCBpbmNyZWFzZXMKCgooZCkgUmVmZXIgdG8geW91ciBhbnN3ZXIgaW4gKGIpIEluIGEgY2VydGFpbiBtb250aCwgdGhlIHJhdGUgb2YgcmV0dXJuIG9uIHRoZSBUU0UgSW5kZXggd2FzIDQlLiBQcmVkaWN0IHRoZSByYXRlIG9mIHJldHVybiBvbiBTdW5jb3Igc3RvY2sgZm9yIHRoZSBzYW1lIG1vbnRoLiAKYGBge3J9CjAuMDE2NjQ3OTQgKyAoMC41Mzg2OTA5OSowLjA0KQpgYGAKYGBge3J9CnByZWRpY3QocHJlZGljdC5zdW5jb3JSYXRlLCBkYXRhLmZyYW1lKFRTRS5JbmRleD0wLjA0KSkKYGBgCgoKCihlKSBUaGluayBhYm91dCB0aGUgY29uZGl0aW9ucyBvZiB0aGlzIG1vZGVsICppbiB0aGUgY29udGV4dCogb2YgdGhlc2UgZGF0YS4gQ3JlYXRlIHRoZSB2aXN1YWxpemF0aW9ucyB0aGF0IGluc3BlY3QgZWFjaCBvZiB0aGUgdHdvIGNvbmRpdGlvbnMgYW5kIHByb3ZpZGUgY29tbWVudGFyeSB0aGF0IGFkZHJlc3NlcyB0aGUgdmFsaWRpdHkgKG9yIGludmFsaWRpdHkpIG9mIGVhY2guIAoKV2UgbmVlZCB0byBjaGVjayBmb3IgdGhlIDIgY29uZGl0aW9uczogTm9ybWFsaXR5IG9mIFJlc2lkdWFscyBhbmQgSG9tb3NjZWRhc3RpY2l0eQoxLiBOb3JtYWxjeSBvZiBSZXNpZHVhbHMKCmBgYHtyfQp0c2VpbmRleCA9IGNhcG1kYXRhLmRmJFRTRS5JbmRleCAgI3JlYWQgdHNlLmluZGV4CnN1bmNvcnZhbHVlcyA9IGNhcG1kYXRhLmRmJFN1bmNvciAgICNyZWFkIFN1bmNvciByYXRlCnByZWRpY3RlZC5TdW5jb3JSYXRlID0gcHJlZGljdC5zdW5jb3JSYXRlJGZpdHRlZC52YWx1ZXMgI2dldCBmaXR0ZWQgdmFsdWVzIGZyb20gdGhlIHByZWRpY3Quc3VuY29yIAplaXNTdW5jb3IgPSBwcmVkaWN0LnN1bmNvclJhdGUkcmVzaWR1YWxzICAgICAgI2dnZXQgcmVzaWR1YWwgZnJvbSBwcmVkaWN0LnN1bmNvcgpzdGFuZGFyZGl6ZWQuZWlzPXJzdGFuZGFyZChwcmVkaWN0LnN1bmNvclJhdGUpICAjYXBwbGllcyByc3RhbmRhcmQgdG8gcHJlZGVpY3Quc3VuY29yIGFuZCBwbGFjZSB0aGVtIGluIHN0YW5kYXJkaXplZC5laXMgdmFyaWFibGUKZGlhZ25vc3RpY2RmID0gZGF0YS5mcmFtZSh0c2VpbmRleCwgc3VuY29ydmFsdWVzLCBwcmVkaWN0ZWQuU3VuY29yUmF0ZSwgZWlzU3VuY29yLCBzdGFuZGFyZGl6ZWQuZWlzKSAjY3JlYXRlIGEgZGF0YSBmcmFtZSB3aXRoIGFsbCB2YXJpYWJsZXMgYWJvdmUKaGVhZChkaWFnbm9zdGljZGYsNCkKYGBgCmBgYHtyfQpnZ3Bsb3QoZGlhZ25vc3RpY2RmLCBhZXMoc2FtcGxlID0gc3RhbmRhcmRpemVkLmVpcykpICsgIHN0YXRfcXEoY29sPSdibHVlJykgKyBzdGF0X3FxbGluZShjb2w9J3JlZCcpICsgZ2d0aXRsZSgiTm9ybWFsIFByb2JhYmlsaXR5IFBsb3Qgb2YgU3RhbmRhcmRpemVkIFJlc2lkdWFscyIpCmBgYApUaGlzIGdyYXBoIHByb3ZlcyB0aGUgbm9ybWFsY3kgb2YgcmVzaWR1YWxzLiAKCjIuIEhvbW9zY2VkYXN0aWNpdHkKCmBgYHtyfQpnZ3Bsb3QoZGlhZ25vc3RpY2RmLCBhZXMoeCA9IHRzZWluZGV4LCB5ID0gc3RhbmRhcmRpemVkLmVpcykpICsgIGdlb21fcG9pbnQoc2l6ZT0yLCBjb2w9J2JsdWUnLCBwb3NpdGlvbj0iaml0dGVyIikgKyB4bGFiKCJUU0UgSW5kZXgiKSArIHlsYWIoIlN0YW5kYXJkaXplZCBSZXNpZHVhbHMiKSArIGdndGl0bGUoIlNjYXR0ZXJwbG90IG9mICBSZXNpZHVhbHMgdnMgcHJlZGljdGVkIHZhbHVlcyIpICsgZ2VvbV9obGluZSh5aW50ZXJjZXB0PTAsIGNvbG9yPSJyZWQiLCBsaW5ldHlwZT0iZGFzaGVkIikKYGBgCgooZikgRnJvbSB0aGVzZSBkYXRhLCBjYW4geW91IGluZmVyIHRoYXQgdGhlIG1vbnRobHkgcmF0ZSBvZiByZXR1cm4gb2YgU3VuY29yIHN0b2NrIGNhbiBiZSBleHByZXNzZWQgYXMgYSBwb3NpdGl2ZSBsaW5lYXIgZnVuY3Rpb24gb2YgdGhlIG1vbnRobHkgcmF0ZSBvZiByZXR1cm4gb2YgdGhlIFRTRSBJbmRleD8gU3RhdGUgeW91ciBzdGF0aXN0aWNhbCBoeXBvdGhlc2VzLCBjb21wdXRlIChhbmQgcmVwb3J0KSBib3RoIHRoZSB0ZXN0IHN0YXRpc3RpYyBhbmQgdGhlICRQJC12YWx1ZSBhbmQgcHJvdmlkZSB5b3VyIGRlY2lzaW9uLiAKCkh5cG90aGVzZXMKICAgICAgICBIMDogQjE8PTAgICAgICAgICAgIAogICAgICAgIEhBOkIxPjAKCmBgYHtyfQpzdW1tYXJ5KHByZWRpY3Quc3VuY29yUmF0ZSkKYGBgCgpgYGB7cn0KVG9icz0oMC41Mzg2OTA5OS0wKS8wLjE5MTc3OTYzIApUb2JzCmBgYApUb2JzPTIuODA4OSB3aXRoIGRmPTU3IHNhbWUgYXMgdGhlIHJlc3VsdCBvYnRhaW5lZCB3aXRoIHRoZSBwcmVkaWN0LnN1bmNvclJhdGUgIGFuZCBhIFB2YWx1ZSA9IDAuMDA2OC8yID0gMC4wMDAzNCAoV2UgYXJlIGxvb2tpbmcgYXQgdGhlIHByb2JhYmlsaXR5IG9mIFQgPiBUb2JzIHNvIHdlIGRpdmlkZSBQdmFsdWUgYnkgMikKCmBgYHtyfQoxLXB0KDIuODA4OSwgNTctMikKYGBgCgpBcyBwZXIgUHZhbHVlID0gMC4wMDM0MywgKGxlc3MgdGhhbiAwLjA1KSB3ZSByZWplY3QgSDAuIFdlIGNhbiBzYXkgdGhhdCB0aGUgbW9udGhseSByYXRlIG9mIHJldHVybiBvZiBTdW5jb3Igc3RvY2sgY2FuIGJlIGV4cHJlc3NlZCBhcyBhIHBvc2l0aXZlIGxpbmVhciBmdW5jdGlvbiBvZiB0aGUgbW9udGhseSByYXRlIG9mIHJldHVybiBvZiB0aGUgVFNFIEluZGV4CgooZykgQ29tcHV0ZSBhIDk1JSBjb25maWRlbmNlIGludGVydmFsIGZvciAkXGJldGFfezF9JCwgdGhlbiBpbnRlcnByZXQgaXRzIG1lYW5pbmcgaW4gdGhlIGNvbnRleHQgb2YgdGhlc2UgZGF0YS4gCgpgYGB7cn0KY29uZmludChwcmVkaWN0LnN1bmNvclJhdGUsIGNvbmYuaW50PTAuOTUpCmBgYAp0aGUgcmVncmVzc2lvbiBjb2VmZmljaWVudCB3aWxsIGhhdmUgYSB2YWxlIGJldHdlZW4gMC4xNTQ2IGFuZCAwLjkyMjcgaW4gOTUlIG9mIHRoZSBjYXNlcy4KCgooaCkgQ29tcHV0ZSBhIDk1JSBjb25maWRlbmNlIGludGVydmFsIGZvciB0aGUgbWVhbiBtb250aGx5IHJhdGUgb2YgcmV0dXJuIG9mIFN1bmNvciBzdG9jayB3aGVuIHRoZSBUU0UgaGFzIGEgbW9udGhseSByYXRlIG9mIHJldHVybiBvZiAzJS4gCgpgYGB7cn0KcHJlZGljdChwcmVkaWN0LnN1bmNvclJhdGUsIG5ld2RhdGE9ZGF0YS5mcmFtZShUU0UuSW5kZXg9MC4wMyksIGludGVydmFsPSdjb25mJykKYGBgCndoZW4gdGhlIFRTRS5JbmRleCB2YWx1ZSBpcyAwLjAzLCBTdW5jb3IgbW9udGhseSByYXRlIHdpbGwgYmUgOTUlIG9mIHRoZSB0aW1lIGJldHdlZW4gMC4wMDc2NiBhbmQgMC4wNTc5CgoKKGkpIEluIGEgbW9udGggb2YgU2VwdGVtYmVyLCB0aGUgVFNFIEluZGV4IGhhZCBhIHJhdGUgb2YgcmV0dXJuIG9mIDEuMTYlLiBXaXRoIDk1JSBjb25maWRlbmNlLCBjb21wdXRlIHRoZSBTZXB0ZW1iZXIgcmF0ZSBvZiByZXR1cm4gZm9yIFN1bmNvciBzdG9jay4gCgpgYGB7cn0KcHJlZGljdChwcmVkaWN0LnN1bmNvclJhdGUsIG5ld2RhdGE9ZGF0YS5mcmFtZShUU0UuSW5kZXg9MC4wMTE2KSwgaW50ZXJ2YWw9J2NvbmYnKQpgYGAKV2UgY2FuIHNheSB3aXRoIDk1JSBjb25maWRlbmNlIHRoYXQgdGhlIHJhdGUgb2YgcmV0dXJuIG9mIHRoZSBTdW5jb3Igc3RvY2sgZm9yIHRoYXQgbW9udGggb2YgU2VwdGVtYmVyIHdhcyBiZXR3ZWVuIC0wLjAwMDY0IGFuZCAwLjA0NjQzCgooaikgUmVjYWxsIHRoZSBCb290c3RyYXAgTWV0aG9kLiBGcm9tIHRoZXNlIGRhdGEsIHVzZSB0aGUgYm9vdHN0cmFwIG1ldGhvZCB0byBjcmVhdGUgYSA5NSUgY29uZmlkZW5jZSBpbnRlcnZhbCBmb3IgbWVhbiBtb250aGx5IHJhdGUgb2YgcmV0dXJuIG9mIFN1bmNvciBzdG9jayB3aGVuIHRoZSBUU0UgaGFzIGEgbW9udGhseSByYXRlIG9mIHJldHVybiBvZiAzJS4gQ29tcGFyZSB5b3VyIHJlc3VsdCB0byB5b3VyIHJlc3VsdCBpbiBwYXJ0IChoKS4gVXNlIDEwMDAgaXRlcmF0aW9ucyBmb3IgeW91ciBib290c3RyYXAuICpDYXJlZnVsbHkqIGNvbnNpZGVyIGhvdyB5b3Ugd291bGQgcmVzYW1wbGUgYml2YXJpYXRlIGRhdGEgcG9pbnRzICQoeF97VFNFLCBpfSwgeV97U3VuY29yLCBpfSkkLiAKCmBgYHtyfQpOc2ltcyA9IDEwMDAKVFNFdmFsID0gMC4wMwpib290X3ByZWRpY3QgPSBudW1lcmljKDEwMDApCnBhaXJfeF95ID0gZGltKGNhcG1kYXRhLmRmKVsxXQoKZm9yKGkgaW4gMTpOc2ltcykKewogIGluZGV4ID0gc2FtcGxlKHBhaXJfeF95LHJlcGxhY2U9VFJVRSkKICBkc2FtcGxlID0gY2FwbWRhdGEuZGZbaW5kZXgsIF0KICB0ZW1wID0gbG0oU3VuY29yflRTRS5JbmRleCwgZGF0YSA9IGRzYW1wbGUpCiAgYm9vdF9wcmVkaWN0W2ldID0gKGNvZWYodGVtcClbMV0pICsgKChjb2VmKHRlbXApWzJdKSpUU0V2YWwpCn0KCnJlZ19ib290c3RyYXAgPSBkYXRhLmZyYW1lKGJvb3RfcHJlZGljdCkKaGVhZChyZWdfYm9vdHN0cmFwLDQpCmBgYAoKYGBge3J9CmdncGxvdChyZWdfYm9vdHN0cmFwLCBhZXMoeCA9IGJvb3RfcHJlZGljdCkpICsgZ2VvbV9oaXN0b2dyYW0oY29sPSdyZWQnLCBmaWxsPSdibHVlJywgYmlud2lkdGg9MC4wMDYpICsgeGxhYigiUHJlZGljdGVkIFZhbHVlcyBvZiBTdW5jb3IgUmF0ZSB3aGVuIFRTRS5JbmRleCA9IDAuMDMiKSArIHlsYWIoIkNvdW50IikgKyAKZ2d0aXRsZSgiRGlzdHJpYnV0aW9uIG9mIEJvb3RzdHJhcCBTdGF0aXN0aWM6IFByZWRpY3RlZCBTdW5jb3IgUmF0ZSIpCmBgYAoKYGBge3J9CnFkYXRhKH5ib290X3ByZWRpY3QsIGMoMC4wMjUsMC45NzUpLCBkYXRhPXJlZ19ib290c3RyYXApCmBgYApUaGlzIGNvbmZpZGVuY2UgaW50ZXJ2YWwgaXMgY2xvc2UgdG8gdGhlIGludGVydmFsIGZvdW5kIGluIGguIAoKCioqMi4qKiBXYXMgQmFycnkgQm9uZHMgdXNpbmcgU3Rlcm9pZHM/IER1cmluZyB0aGUgMjAwMSBTZWFzb24sIEJhcnkgQm9uZHMgaGl0IGEgbWFqb3IgbGVhdWdlIHJlY29yZCBvZiA3MyBob21lIHJ1bnMuCgpUaGUgZm9sbG93aW5nIGJpdmFyaWF0ZSBkYXRhIHNldCBnaXZlcyB0aGUgeWVhciBhbmQgdGhlIG51bWJlciBvZiBob21lIHJ1bnMgZGl2aWRlZCBieSB0aGUgbnVtYmVyIG9mIGF0IGJhdHMgLSBhdHRlbXB0cyB0byBoaXQgdGhlIGJhbGwgLSBmb3IgZWFjaCBzZWFzb24uIFRoZSBudW1iZXIgb2YgaG9tZXJ1bnMgaXMgbm90IHVzZWQgYXMgbGF0ZXIgaW4gaGlzIGNhcmVlciBoZSB3YXMgZ2l2ZW4gaW50ZW50aW9uYWwgd2Fsa3MsIHdoaWNoIGRvIG5vdCBjb3VudCBhcyBhbiBhdCBiYXQuIAoKSW4gdGhpcyBleGVyY2lzZSwgeW91IHdpbGwgYnVpbGQgb24geW91ciBsZWFybmluZyBvZiBtb2RlbCBidWlsZGluZyBhbmQgYXR0ZW1wdCB0byAqKnByZWRpY3QgdGhlIG51bWJlciBvZiBob21lIHJ1bnMgQmFycnkgQm9uZHMgd291bGQgaGF2ZSBoaXQgaW4gdGhlIDIwMDEqKiBzZWFzb24uIFRoZXNlIGRhdGEgYXJlIHN0b3JlZCBpbiB0aGUgW2RhdGEgZmlsZV0oaHR0cHM6Ly9naXRodWIuY29tL1N0YXRtYW40NC9EYXRhNjAyL2Jsb2IvbWFpbi9ib25kc2RhdGEuY3N2KS4gCgoKPGNlbnRlcj4KIVtCb25kcyBKdXN0IEFmdGVyIEhlIFNpZ25lZCBIaXMgU2FuIEZyYW5zaWNvIENvbnRyYWN0XShCb25kc1ByZS5qcGcpCgohW0NpcmNhIDIwMDBdKEJvbmRzUG9zdC5qcGcpCgoKUmVtb3ZlIHRoZSBkYXRhIHBvaW50IHRoYXQgY29ycmVzcG9uZHMgdG8gdGhlICoqc2Vhc29uID09IDIwMDEqKi4gQWZ0ZXIgd2hpY2gsIHlvdSBhcmUgYXR0ZW1wdGluZyB0byBidWlsZCBhIHN0YXRpc3RpY2FsIG1vZGVsIG9mIHRoZSBmb2xsb3dpbmcgZm9ybToKJCQKSFJBVF97aX0gPSBBICsgQipZZWFyX3tpfSArIGVfe2l9IFxoc3BhY2V7MC41aW59IGkgPSAxOTg3LCAxOTg4LCBcY2RvdHMsIDIwMDAuCiQkCkNhcnJ5IG91dCB0aGUgYXBwcm9wcmlhdGUgc3RhdGlzdGljYWwgYW5hbHlzaXMgdG8ganVzdGlmeSB5b3VyIGFuc3dlci4gQ29tbXVuaWNhdGUgeW91ciBhbnN3ZXIgaW4gdGhlIGZvcm0gb2YgYSBmZXcgcGFyYWdyYXBocy4gSW4gd3JpdGluZyB5b3VyIHJlc3BvbnNlIGFuZCBzdGF0aXN0aWNhbCBqdXN0aWZpY2F0aW9uLCBlbnN1cmUgdGhhdCBhbnkgY29uZGl0aW9ucy9hc3N1bXB0aW9ucyBvZiB0aGUgbW9kZWwgc3RhdGVkIGFib3ZlIGFyZSBtZW50aW9uZWQgYW5kIGNoZWNrZWQuIAoKYGBge3J9CmJib25kcy5kZiA9IHJlYWQuY3N2KCJodHRwczovL3Jhdy5naXRodWJ1c2VyY29udGVudC5jb20vU3RhdG1hbjQ0L0RhdGE2MDIvbWFpbi9ib25kc2RhdGEuY3N2IikKaGVhZChiYm9uZHMuZGYpCmBgYAoKYGBge3J9CnRhaWwoYmJvbmRzLmRmKQpgYGAKCkNyZWF0ZSBhIG5ldyBkYXRhZnJhbWUgd2l0aG91dCAyMDAxCgpgYGB7cn0KYmJvbmRzMS5kZiA9IGJib25kcy5kZiAlPiUgZmlsdGVyKHNlYXNvbiE9MjAwMSkKdGFpbChiYm9uZHMxLmRmKQpgYGAKCgpgYGB7cn0KZ2dwbG90KGJib25kczEuZGYsIGFlcyh4ID0gc2Vhc29uLCB5ID0gaHJhdCkpICsgZ2VvbV9wb2ludChjb2w9ImJsdWUiLCBzaXplID0gMikgKyB4bGFiKCJTZWFzb24iKSArIHlsYWIoImhyYXQiKSArIGdndGl0bGUoIlNjYXR0ZXIgcGxvdCBmb3IgQmFycnkgQm9uZHMnIChocmF0KSBIb21lcnVucyAxOTg3LTIwMDAiKQpgYGAKVGhlIHNjYXR0ZXJwbG90IHBhdHRlcm4gZG9lcyBub3Qgc2hvdyBhIGNvbmUgbGlrZSBwYXR0ZXJuLCBzZWVtcyB0byBmb2xsb3cgbGluZWFyaXR5CgpgYGB7cn0KcHJlZGljdC5ob21lcnVuID0gbG0oaHJhdH5zZWFzb24sIGRhdGE9YmJvbmRzMS5kZikKcHJlZGljdC5ob21lcnVuJGNvZWZmaWNpZW50cwoKYGBgCgpgYGB7cn0Kc3VtbWFyeShwcmVkaWN0LmhvbWVydW4pCmBgYAoKU2UgPSAwLjAxMzI5CnJeMiA9IDAuNjM3MQp0IHZhbHVlID0gNC41ODkKYiA9IDAuMDA0MDQKYSA9IC03Ljk5MjUKCgpDT05ESVRJT05TIE9GIFRIRSBNT0RFTAoKYGBge3J9CmFjdHVhbC5ocmF0ID0gYmJvbmRzMS5kZiRocmF0CmFjdHVhbC5zZWFzb249IGJib25kczEuZGYkc2Vhc29uCmVpcy5iYm9uZHM9cHJlZGljdC5ob21lcnVuJHJlc2lkdWFscwpzZS5iYm9uZHMgPSBzdW1tYXJ5KHByZWRpY3QuaG9tZXJ1bikkc2lnbWEKc3RhbmRhcmRpemVkLmVpcyA9IHJzdGFuZGFyZChwcmVkaWN0LmhvbWVydW4pCnByZWRpY3RlZC52YWx1ZXMuaHJhdCA9IHByZWRpY3QuaG9tZXJ1biRmaXR0ZWQudmFsdWVzCmRpYWdub3N0aWMuZGYgPSBkYXRhLmZyYW1lKGFjdHVhbC5zZWFzb24sIGFjdHVhbC5ocmF0LCBwcmVkaWN0ZWQudmFsdWVzLmhyYXQsZWlzLmJib25kcywgc3RhbmRhcmRpemVkLmVpcykKaGVhZChkaWFnbm9zdGljLmRmKQpgYGAKCjEuIE5vcm1hbGl0eQoKYGBge3J9CmdncGxvdChkaWFnbm9zdGljLmRmLCBhZXMoc2FtcGxlID0gc3RhbmRhcmRpemVkLmVpcykpICsgIHN0YXRfcXEoY29sPSdibHVlJykgKyBzdGF0X3FxX2xpbmUoY29sPSdyZWQnKSArIGdndGl0bGUoIk5vcm1hbCBQcm9iYWJpbGl0eSBQbG90IG9mIFN0YW5kYXJkaXplZCBSZXNpZHVhbHMiKQpgYGAKVGhlIGxpbmUgZml0cyB0aHJvdWdoIHRoZSBwYXR0ZXJuLiBUaGlzIGNhbiBiZSBjb25zaWRlcmVkIGxpbmVhciBhbmQgcHJvdmVzIE5vcm1hbGl0eQoKCjIuIEhvbW9zY2VkYXN0aWNpdHkKCmBgYHtyfQpnZ3Bsb3QoZGlhZ25vc3RpYy5kZiwgYWVzKHggPSBhY3R1YWwuc2Vhc29uLCB5ID0gc3RhbmRhcmRpemVkLmVpcykpICsgZ2VvbV9wb2ludChzaXplPTIsIGNvbD0nYmx1ZScsIHBvc2l0aW9uPSJqaXR0ZXIiKSArIHhsYWIoIlNlYXNvbiIpICsgeWxhYigiUmVzaWR1YWxzIikgKwpnZ3RpdGxlKCJTZWFzb24gdG8gU3RhbmRhcmRpemVkIFJlc2lkdWFscyIpICsgZ2VvbV9obGluZSh5aW50ZXJjZXB0PTAsIGNvbG9yPSJyZWQiLCBsaW5ldHlwZT0iZGFzaGVkIikKYGBgClRoZSBzcHJlYWQgZG9lcyBub3Qgc2hvdyBhbnkgY29uZSBsaWtlIHBhdHRlcm5zIG9uIHRoZSBzcHJlYWQgb2YgcmVzaWR1YWxzLiBXZSBjYW4gY29uc2lkZXIgaXQgaG9tb3NjZWRhc3RpYwoKSHlwb3RoZXNlcwogICAgICAgIEgwOiBiZXRhMSA9IDAKICAgICAgICBIQTogQmV0YTEgIT0gMAogICAgICAgIApGLVRFU1QKYGBge3J9CnN1bW1hcnkoYW92KHByZWRpY3QuaG9tZXJ1bikpCmBgYAoKYGBge3J9CnN1bW1hcnkoYW92KHByZWRpY3QuaG9tZXJ1bikpW1sxXV1bWyJQcig+RikiXV1bMV0KYGBgClB2YWx1ZSBpcyAwLjAwMDYyMiBzbyB3ZSByZWplY3QgSDAKCgpQUkVESUNUSU5HIEhPTUVSVU5TIDIwMDEgU0VBU09OCgoKYGBge3J9Cm5oID0gZGF0YS5mcmFtZShzZWFzb249MjAyMSkKcHJlZGljdChwcmVkaWN0LmhvbWVydW4sIG5ld2RhdGE9bmgsIGludGVydmFsPSdwcmVkaWN0aW9uJykKYGBgCkV4dHJhY3QgSHJhdCBmb3IgMjAwMQoKYGBge3J9CmJib25kcy5kZlsxNSwyXQpgYGAKdXNlIEhyYXQgMjAwMSBhbmQgbnVtYmVyIG9mIGhvbWVydW5zIHRvIGNhbGN1bGF0ZSBhdGJhdAoKYGBge3J9CmF0YmF0ID0gNzMvMC4xNTM0CmF0YmF0CmBgYAp1c2UgSHJhdCAyMDAxIGFuZCBudW1iZXIgb2YgaG9tZXJ1bnMgdG8gY2FsY3VsYXRlIGF0YmF0CgpgYGB7cn0KYXRiYXQgPSA3My8wLjE1MzQKYXRiYXQKCmBgYApVc2UgZml0IHZhbHVlIG9mIHRoZSBtb2RlbCBhbmQgYXRiYXQgdG8gZG8gdGhlIHByZWRpY3Rpb24KYGBge3J9CnByZWRpY3QuMjAwMSA9IGF0YmF0KjAuMTgwOApwcmVkaWN0LjIwMDEKYGBgCmBgYHtyfQpwcmVkaWN0LjIwMDFfdXBwZXIgPSBhdGJhdCAqIDAuMTMzMTM4MgpwcmVkaWN0LjIwMDFfbG93ZXIgPSBhdGJhdCAqIDAuMDY2NjI4NApwcmVkaWN0LjIwMDFfdXBwZXIKYGBgCgoKYGBge3J9CnByZWRpY3QuMjAwMV9sb3dlcgoKYGBgCgo=