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

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

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

  1. 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")

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

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

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

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

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

Bonds Just After He Signed His San Fransico Contract

Circa 2000

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

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