Workshop 9, Financial Econometrics II

Alberto Dorantes, Ph.D. Apr 27, 2022

Consideration

Estimados estudiantes: En estos días getSymbols de la librería quantmod NO está funcionando (marca un error al bajar datos). Para arreglar el error, tienen que re-instalar la librería quantmod. Pueden hacerlo desde Packages en la ventana inferior derecha de RStudio, ó también escribir en la consola:

install.packages("quantmod")
Error in install.packages : Updating loaded packages
library(quantmod)

Abstract

In this workshop we will learn about Value at Risk (VaR) and Expected Shortfall (ES) and how to apply it to a real-world market index. We will also use a GARCH(1,1) model to forecast volatility and VaR.

Introduction to Value at Risk (VaR)

Value at Risk (VaR) is a measure of risk that focuses on potential losses of an investment in a short period of time. Investment firms and banks constantly monitor VaR of their portfolios in order to be prepared in case a bad scenario. VaR is usually estimated daily using a small probability such as 5%, 1%, or 0.1%. Very bad scenarios in the short term have a certain probability p to happen in one day. For example, if the probability of losing 10% or MORE of an investment in one single day is 5%, then we say that the 5% Value at Risk (5%VaR) is equal to 10%. We can also calculate VaR in money if we know the initial investment. For example, using the same example, if my initial investment is $1’000,000, then the 5%VaR = 10%, which is equal to $100,000.00. VaR can be reported as a positive or negative amount; this is just a matter of preference. But we have to be aware that VaR is a measure of potential loss in % or in $ with a certain probability. p%VaR is the MINIMUM % loss of an investment with a probability of p. In other words, there is a probability p that I can lose %VaR or MORE. Another way to define p%VaR is the following. p%VaR is the MAXIMUM %loss of an investment with a probatility (1-p). In other words, there is a probability (1-p) that I can have a return of %VaR or HIGHER. Then, we can say that p%VaR is the best scenario that can happen after a very bad scenario that can happen with probability p. Also, we can say that p%VaR is the worse scenario that can happen when the scenario is not the bad one, so when there is a probability of (1-p)%. Let’s illustrate VaR using real data from the US index S&P500 daily returns from January 2019 to April 26, 2022.

library(quantmod)
getSymbols("^GSPC", from="2019-01-01",
                    to="2022-04-27")
[1] "^GSPC"
# I get the adjusted column:
SPindex = Ad(GSPC)
# I calculate daily returns of the index:
SPreturn<- na.omit(diff(log(SPindex)))
names(SPreturn)<-c("return")

We plot the daily index over time:

plot(SPindex)

We see strong decline in March 2020, another important decline in early 2022.

Now we do a histogram of the return of this index

hist(SPreturn, breaks=40)

The height of each bar represents the frequency in number of days that a specific daily return range has happened.

If the daily returns behaves like a normal-distributed variable, then about 2.5% of the days the S&P500 returns would be less than the its mean minus 2 times its standard deviation. Remember that for a normal-distributed variable, in the range plus/minus 2 standard deviations from its mean, we will find about 95% of the values.

We downloaded 835 days of return, so we would expect that about 20.875 will be the # of days that the SP&500 would offer returns less than -2 times its standard deviation from its mean:

# Number of days for the S&P returns:
N=nrow(SPreturn)
N
[1] 835
# The 2.5% of these # of days is about:
n25=0.025*nrow(SPreturn)
n25
[1] 20.875

Now we can look the real data and see how many days the S&P500 has offered returns less than 2 times its standard deviation from its mean. We can calculate the mean and standard deviation (volatility) of daily returns, and then identify how many days the S&P500 has offered extreme returns less than the mean minus 2 times its volatility:

# We calculate the mean and standard deviation of returns:
mean_return=mean(SPreturn$return)
mean_return
[1] 0.0006094223
volatility = sd(SPreturn$return)
volatility
[1] 0.01417127
# We calculate the expected minimum return of the 95% confidence interval (C.I.) 
#   assuming normality (the 2.5 percentile)
min95ci_returns = mean_return-2*volatility
min95ci_returns
[1] -0.02773312
# We select the days with returns less than the minimum of the 95% C.I.
extremes<- SPreturn[SPreturn$return<min95ci_returns,]
extremes
                return
2019-08-05 -0.03023018
2019-08-14 -0.02973035
2020-02-24 -0.03408808
2020-02-25 -0.03074790
2020-02-27 -0.04516814
2020-03-03 -0.02851048
2020-03-05 -0.03451078
2020-03-09 -0.07901041
2020-03-11 -0.05010289
2020-03-12 -0.09994485
2020-03-16 -0.12765220
2020-03-18 -0.05322227
2020-03-20 -0.04432762
2020-03-23 -0.02973150
2020-03-27 -0.03426785
2020-04-01 -0.04514636
2020-04-21 -0.03115512
2020-05-01 -0.02846021
2020-06-11 -0.06075269
2020-09-03 -0.03575759
2020-09-08 -0.02814883
2020-10-28 -0.03592554
2022-03-07 -0.02996259
2022-04-22 -0.02813208
2022-04-26 -0.02855001
nextremes = nrow(extremes)
# Number of extreme returns:
nextremes
[1] 25
percextremes = nextremes / N * 100
percextremes
[1] 2.994012

In this case, we have 25 extreme days with returns less than the minimum of the 95% C.I. of daily returns. Then, it seems that we have had more extreme returns than expected. This represents about 2.994012% of the total # of days, which is greater than the expected 2.5%.

Then, 2.994012% of the time, the S&P500 has experience a loss of -2.7733123% or MORE. If we believe that in the future the S&P500 will behave in a similar manner, then we can say that there is a probability of 2.994012% that I can lose -2.7733123% or MORE in only ONE DAY.

We can also say that there is a probability of 97.005988% (100% - 2.994012%) that the MAXIMUM loss I can experience in ONE DAY is -2.7733123%. Then, the 2.994012%VaR of the daily S&P500 returns is -2.7733123%

VaR1 = min95ci_returns*100
VaR1
[1] -2.773312

For turbulence periods in financial markets it is likely that a bad scenario with probability p can happen. Once this scenario happens, then p%VaR is the best scenario, but in reality this the p%VaR is not too realistic. We need to be more conservative and estimate which might be the expected loss once the probability p of the bad scenario happens. This conservative estimate is given by the Expected Shortfall. We will review the concept of ES in the following section.

Expected Shortfall (ES)

Expected Shortfall with a probability p refers to the expected average loss of an investment in ONE period (in this case, in one day) once the probability p of a bad scenario happens. Then, the absolute value of p%ES will always be greater (more negative) than the p%VaR. Let’s calculate the ES using the previous example of the S&P500 500 daily returns.

To estimate the ES at the 2.994012% probability, we just calculate the average of the days when the S&P500 returns have been less than -2.7733123%.We can do this as follows

extremes
                return
2019-08-05 -0.03023018
2019-08-14 -0.02973035
2020-02-24 -0.03408808
2020-02-25 -0.03074790
2020-02-27 -0.04516814
2020-03-03 -0.02851048
2020-03-05 -0.03451078
2020-03-09 -0.07901041
2020-03-11 -0.05010289
2020-03-12 -0.09994485
2020-03-16 -0.12765220
2020-03-18 -0.05322227
2020-03-20 -0.04432762
2020-03-23 -0.02973150
2020-03-27 -0.03426785
2020-04-01 -0.04514636
2020-04-21 -0.03115512
2020-05-01 -0.02846021
2020-06-11 -0.06075269
2020-09-03 -0.03575759
2020-09-08 -0.02814883
2020-10-28 -0.03592554
2022-03-07 -0.02996259
2022-04-22 -0.02813208
2022-04-26 -0.02855001
ES=mean(extremes$return) * 100
ES
[1] -4.412946

The Expected Shortfall at the 2.994012% probability is the average of these extreme return, which is -4.4129462%. As expected, the 2.994012% ES is more negative than the 2.994012%VaR (-4.4129462% vs -2.7733123%).

There are more than one method to estimate VaR and ES. Read the my Note “Introduction to Value at Risk” to learn different methods to estimate VaR and Expected Shortfall.

The most popular methods are 1) Percentile method using real distribution, 2) assuming normal distribution of returns, and 3) assuming a fat-tailed distribution of returns using the t-Student probability distribution.

Another not popular method (but more accurate) is using a volatility model like an GARCH(1,1) model to estimate and forecast daily volatility, and use this volatility to estimate Value at Risk.

Kurtosis and fat-tail distribution

Skewness and Kurtosis are statistical measures of a random variable. Here is a quick summary of Skewness and Kurtosis:

Skewness is a measure for asymmetry of the distribution. A normal distribution has about the same values that are less than then mean compared with the values that are higher than the mean. A normal distribution has a skewness close to zero. A negative skewness means that the tail to the left has more values (skewed to the left). A positive skewness means that the tail to the right has more values (skewed to the right).

Kurtosis can be used to examine know whether a variable has a distribution with much more extreme values compared to the normal distribution. According to the value of Kurtosis, we can identify whether we have a significant number of extreme values in a variable:

If Kurtosis=3 then, the variable behaves close to normal distribution

If Kurtosis>3, then this means that there are extreme values in the variable that makes the distribution to be a fat-tailed distribution.

Here is a quick review of moments in statistics, which are the base to understand Variance, Skewness and Kurtosis:

Moments in Statistics:

A Moment in Statistis is a specific measure about a probability distribution of a random variable.

The expected value of a random variable X can be calculated as the mean of X using historical values:

Mean(X)=X⎯⎯⎯⎯=E[X]=1N∑(Xi)=X1+X2+…XNN

The 4 Moments in Statistics are:

1st moment: E[X−X⎯⎯⎯⎯]=0

2nd moment: E[X−X⎯⎯⎯⎯]2=1N∑(Xi−X⎯⎯⎯⎯)2=VAR(X) = Variance(X);

The Standard Deviation of X is the square root of the Variance(X): SD(X)=VAR(X)‾‾‾‾‾‾‾‾√

3rd moment: E[X−X⎯⎯⎯⎯]3=1N∑(Xi−X⎯⎯⎯⎯)3 The 3rd moment is used to estimate Skewness(X) as:

Skewness(X)=E[X−X⎯⎯⎯⎯]3SD(X)3

4rd moment: E[X−X⎯⎯⎯⎯]4=1N∑(Xi−X⎯⎯⎯⎯)4 The 4rd moment is used to estimate Kurtosis(X) as:

Kurtosis(X)=E[X−X⎯⎯⎯⎯]4SD(X)4

Calculate Kurtosis of S&P500 daily returns. Do you see a sign of fat-tail distribution of returns

The moments library has functions for Kurtosis and Skewness. Install this library

library(moments)
kurtosis = as.numeric(kurtosis(SPreturn))
kurtosis
[1] 20.0883

Since kurtosis is much higher than 3, this is a sign of fat-tailed distribution.

Estimating VaR assuming fat-tail distribution

Considering that the distribution of real returns is more a fat-tail distribution (more-than-normal extreme values), it is better to use the t distribution rather than the normal distribution. Research indicates that there is a relationship between the kurtosis and the degrees of freedom of the t distribution to model fat-tail distributions. A t-distribution with low degrees of freedom shows fatter tails compared with a t distribution with higher degrees of freedom (or compared to a normal distribution). The way to estimate the degrees of freedom of a t distribution to model a fat-tail distribution, we use the kurtosis of the distribution as follows: Degrees of freedom (df)= 6/Kurtosis + 4 You have to estimate the degrees of freedom and then use the t distribution to estimate the 1% VaR of $1million for the next future day of the sample. Compare both estimations of VaR, the one calculated assuming normal distribution and this one. Briefly reports this comparison. Hint: the function qt(0.01,df) gives you the t value, which represents the # of standard deviations you need to go from the mean to the left to arrive to the 1% percentile. I calculate the degrees of freedom I use to simulate a fat-tailed distribution using the t-Student distribution:

# I calculate the degrees of freedom for the t distribution:
df = 6/kurtosis + 4
df
[1] 4.298681
# I calculate the t critical value according to the probability of 1% and the df:
t1 = qt(0.01,df)
t1
[1] -3.607109

Now I get the 1%VaR assuming fat-tail distribution:

meansp = mean(SPreturn)
volatilitysp = sd(SPreturn)
VaR2 = meansp + t1 * volatilitysp
VaR2
[1] -0.05050791

Interpretation of this 1%VaR:

Assuming fat-tail distribution of daily returns of the S&P500, I can lose in one day -5.0507905% or more with a probability of 1%.

Compared to the first 1%VaR=-277.331227% (assuming normal distribution), this 1%VaR=-5.0507905% assuming fat-tail distribution is more conservative, and more realistic.

To calculate the Expected Shortfall assuming fat-tail distribution, we can calculate the average return of the bad days that have had returns less than the 1%VaR assuming fat-tail distribution:

baddays2 <- SPreturn[SPreturn$return<=VaR2,]
baddays2
                return
2020-03-09 -0.07901041
2020-03-12 -0.09994485
2020-03-16 -0.12765220
2020-03-18 -0.05322227
2020-06-11 -0.06075269

Now we can get the average of these very bad days:

ES3 = mean(baddays2$return)
ES3
[1] -0.08411649

This would be the more conservative estimation of 1% Expected Shortfall of the S&P500. Then, assuming fat-tail distribution of daily returns of the S&P500, and using real historical daily returns, ON AVERAGE, I can lose in one day -8.4116486% with a probability of 1%.

Forecasting VaR with GARCH(1,1) Model

Work with the same dataset (daily S&P500 returns).

1.- Run a GARCH(1,1) model. INTERPRET the model and briefly explain your results.

library(rugarch)
Especgarch1=ugarchspec(variance.model= list(model= "sGARCH", garchOrder= c(1, 1), 
submodel= NULL,  variance.targeting= FALSE), 
mean.model= list(armaOrder= c(0, 0), include.mean= TRUE, archm= FALSE, 
archpow= 0, arfima= FALSE,  external.regressors= NULL, archex= FALSE), 
distribution.model= "norm", start.pars= list(), fixed.pars= list())

#Estimación del GARCH(1,1)

garch1<- ugarchfit(spec=Especgarch1, data=SPreturn$return)
garch1

*---------------------------------*
*          GARCH Model Fit        *
*---------------------------------*

Conditional Variance Dynamics   
-----------------------------------
GARCH Model : sGARCH(1,1)
Mean Model  : ARFIMA(0,0,0)
Distribution    : norm 

Optimal Parameters
------------------------------------
        Estimate  Std. Error  t value Pr(>|t|)
mu      0.001047    0.000270   3.8804 0.000104
omega   0.000006    0.000003   2.3265 0.019993
alpha1  0.253622    0.036941   6.8656 0.000000
beta1   0.721067    0.011207  64.3398 0.000000

Robust Standard Errors:
        Estimate  Std. Error  t value Pr(>|t|)
mu      0.001047    0.000260  4.02889 0.000056
omega   0.000006    0.000007  0.84433 0.398487
alpha1  0.253622    0.051157  4.95770 0.000001
beta1   0.721067    0.094270  7.64894 0.000000

LogLikelihood : 2677.884 

Information Criteria
------------------------------------
                    
Akaike       -6.4045
Bayes        -6.3819
Shibata      -6.4046
Hannan-Quinn -6.3958

Weighted Ljung-Box Test on Standardized Residuals
------------------------------------
                        statistic p-value
Lag[1]                     0.7817  0.3766
Lag[2*(p+q)+(p+q)-1][2]    0.9404  0.5180
Lag[4*(p+q)+(p+q)-1][5]    1.3737  0.7709
d.o.f=0
H0 : No serial correlation

Weighted Ljung-Box Test on Standardized Squared Residuals
------------------------------------
                        statistic p-value
Lag[1]                     0.4232  0.5153
Lag[2*(p+q)+(p+q)-1][5]    1.1354  0.8283
Lag[4*(p+q)+(p+q)-1][9]    1.7665  0.9310
d.o.f=2

Weighted ARCH LM Tests
------------------------------------
            Statistic Shape Scale P-Value
ARCH Lag[3]   0.01123 0.500 2.000  0.9156
ARCH Lag[5]   0.92434 1.440 1.667  0.7555
ARCH Lag[7]   1.06257 2.315 1.543  0.9032

Nyblom stability test
------------------------------------
Joint Statistic:  2.5098
Individual Statistics:             
mu     0.2157
omega  0.2498
alpha1 0.1074
beta1  0.2079

Asymptotic Critical Values (10% 5% 1%)
Joint Statistic:         1.07 1.24 1.6
Individual Statistic:    0.35 0.47 0.75

Sign Bias Test
------------------------------------


Adjusted Pearson Goodness-of-Fit Test:
------------------------------------
  group statistic p-value(g-1)
1    20     43.06    0.0012721
2    30     60.44    0.0005448
3    40     80.40    0.0001071
4    50     77.28    0.0061301


Elapsed time : 0.07194638 

*INTERPRETATION the model output**

What does each coefficient mean?

THE beta1 COEFFICIENT IS 0.7210678, AND IT IS SIGNIFICANTLY DIFFERENT THAN ZERO. THIS MEANS THAT ABOUT 72.1067762% OF THE RETURN VARIANCE OF YESTERDAY IS PASSED TO THE RETURN VARIANCE OF TODAY, BESIDES THE IMPACT OF THE YESTERDAY’S SQUARED ERROR. SINCE THIS COEFFICIENT IS GREATER THAN 0.7, THIS IS A SIGN OF CLUSTERING OF VOLATILITY.

CONSIDERING THE VARIANCE OF YESTERDAY, THE SQUARED ERROR OF YESTERDAY IMPACTS THE RETURN VARIANCE OF TODAY IN A POSITIVE AND SIGNIFICANT WAY, BUT ONLY ABOUT 25.3621103% OF THE SQUARED ERROR OF YESTERDAY IS PASSED TO THE VARIANCE OF TODAY.

2.- With this GARCH(1,1) model, forecast both volatility and 1% VaR of $1 million for 1 future day (tomorrow).

garch1.prediction <- ugarchforecast(garch1,n.ahead= 1)

garch1.prediction will be a very special R class: an uGARCHforecast class. This is special R class object that stores information about the GARCH prediction.

For this type of R class objects, we use the @ character to get access to the content of each element stored in this object.

The forecast for the daily return is stored in

garch1.prediction@forecast$seriesFor
     2022-04-26
T+1 0.001047319

The forecast for the standard deviation of returns (volatility) is stored in:

garch1.prediction@forecast$sigmaFor
    2022-04-26
T+1 0.02016522

Now using this predicted volatility, I calculate a new 1%VaR for tomorrow. I will assume fat-tail distribution, so I will use the t-Student distribution with the degrees of freedom I calculated above:

VaR1_G = meansp + t1 * garch1.prediction@forecast$sigmaFor[1]
VaR1_G
[1] -0.07212872

*The 1%VaR using the predicted volatility from the GARCH(1,1) model is -7.2128673%.

Extend the dataset 10 days in the future. Do a within-sample forecast and an out-of-sample forecast for all days of the year (before and after TODAY) for daily volatility and 1%VaR for 1 day.

we do a forecast for 10 days

garch1.prediction <- ugarchforecast(garch1,n.ahead= 10)

We can plot the historic and future volatility:

plot(garch1.prediction,which = 3)

Now I calculate the daily 1%VaR for these 10 future days:

VaR1_G = meansp + t1 * garch1.prediction@forecast$sigmaFor
VaR1_G
      2022-04-26
T+1  -0.07212872
T+2  -0.07174397
T+3  -0.07136698
T+4  -0.07099762
T+5  -0.07063577
T+6  -0.07028130
T+7  -0.06993409
T+8  -0.06959401
T+9  -0.06926094
T+10 -0.06893478
# Now I calculate 1%VaR for a $1 million per day:
VaR1_G_1mill = VaR1_G * 1000000
VaR1_G_1mill
     2022-04-26
T+1   -72128.72
T+2   -71743.97
T+3   -71366.98
T+4   -70997.62
T+5   -70635.77
T+6   -70281.30
T+7   -69934.09
T+8   -69594.01
T+9   -69260.94
T+10  -68934.78

4.- Do a plot of volatility and VaR for the whole year *The GARCH(1,1) fit estimation for volatility (sigma) and for stock return in the history is stored in the garch1 R object at:

$sigma

We can look at the last values of the volatility fitted values:

tail(garch1@fit$sigma)
[1] 0.01017608 0.01169814 0.01026554 0.01209087 0.01809301 0.01573200

We can use these fit sigma values and attach them in the SPreturn xts dataset along with the daily returns:

SPreturn$gvol = garch1@fit$sigma

Now we add a column for the 1%VaR using these historical GARCH volatilities. I will use the t-Student distribution assuming fat-tails ( I will use the t1 I estimated above):

SPreturn$gVaR = meansp + t1 * SPreturn$gvol
SPreturn$gVaR1mill = SPreturn$gVaR * 1000000

Now I plot daily historical returns, and historial GARCH(1,1) fitted values for daily volatilities and 1%Value at Risk:

plot(SPreturn$gVaR1mill)

plot(SPreturn[,c(2,3)])

The green line is the GARCH(1,1) 1% Value at Risk; the red line is the GARCH(1,1) fitted volatility, and the black line is the daily return series.

I recommend you to read the article GARCH 101: The use of [http://www.cmat.edu.uy/~mordecki/hk/engle.pdf||ARCH/GARCH Models in Applied Econometrics] written by Robert Engle to better understand how you can apply ARCH model to forecast volatility and VaR

LS0tCnRpdGxlOiAiV29ya3Nob3AgOSwgRmluYW5jaWFsIEVjb25vbWV0cmljcyBJSSIKYXV0aG9yOiBTdGVmYW4gU2Nod2VpdHplcgpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sKLS0tCiMjIFdvcmtzaG9wIDksIEZpbmFuY2lhbCBFY29ub21ldHJpY3MgSUkKIyBBbGJlcnRvIERvcmFudGVzLCBQaC5ELiBBcHIgMjcsIDIwMjIKICAKIyBDb25zaWRlcmF0aW9uCkVzdGltYWRvcyBlc3R1ZGlhbnRlczoKRW4gZXN0b3MgZMOtYXMgZ2V0U3ltYm9scyBkZSBsYSBsaWJyZXLDrWEgcXVhbnRtb2QgTk8gZXN0w6EgZnVuY2lvbmFuZG8gKG1hcmNhIHVuIGVycm9yIGFsIGJhamFyIGRhdG9zKS4KUGFyYSBhcnJlZ2xhciBlbCBlcnJvciwgdGllbmVuIHF1ZSByZS1pbnN0YWxhciBsYSBsaWJyZXLDrWEgcXVhbnRtb2QuIFB1ZWRlbiBoYWNlcmxvIGRlc2RlIFBhY2thZ2VzIGVuIGxhIHZlbnRhbmEgaW5mZXJpb3IgZGVyZWNoYSBkZSBSU3R1ZGlvLCDDsyB0YW1iacOpbiBlc2NyaWJpciBlbiBsYSBjb25zb2xhOgoKYGBge3J9Cmluc3RhbGwucGFja2FnZXMoInF1YW50bW9kIikKYGBgCmBgYHtyfQpsaWJyYXJ5KHF1YW50bW9kKQpgYGAKCiMgQWJzdHJhY3QKSW4gdGhpcyB3b3Jrc2hvcCB3ZSB3aWxsIGxlYXJuIGFib3V0IFZhbHVlIGF0IFJpc2sgKFZhUikgYW5kIEV4cGVjdGVkIFNob3J0ZmFsbCAoRVMpIGFuZCBob3cgdG8gYXBwbHkgaXQgdG8gYSByZWFsLXdvcmxkIG1hcmtldCBpbmRleC4gV2Ugd2lsbCBhbHNvIHVzZSBhIEdBUkNIKDEsMSkgbW9kZWwgdG8gZm9yZWNhc3Qgdm9sYXRpbGl0eSBhbmQgVmFSLgoKIyBJbnRyb2R1Y3Rpb24gdG8gVmFsdWUgYXQgUmlzayAoVmFSKQpWYWx1ZSBhdCBSaXNrIChWYVIpIGlzIGEgbWVhc3VyZSBvZiByaXNrIHRoYXQgZm9jdXNlcyBvbiBwb3RlbnRpYWwgbG9zc2VzIG9mIGFuIGludmVzdG1lbnQgaW4gYSBzaG9ydCBwZXJpb2Qgb2YgdGltZS4KSW52ZXN0bWVudCBmaXJtcyBhbmQgYmFua3MgY29uc3RhbnRseSBtb25pdG9yIFZhUiBvZiB0aGVpciBwb3J0Zm9saW9zIGluIG9yZGVyIHRvIGJlIHByZXBhcmVkIGluIGNhc2UgYSBiYWQgc2NlbmFyaW8uIFZhUiBpcyB1c3VhbGx5IGVzdGltYXRlZCBkYWlseSB1c2luZyBhIHNtYWxsIHByb2JhYmlsaXR5IHN1Y2ggYXMgNSUsIDElLCBvciAwLjElLgpWZXJ5IGJhZCBzY2VuYXJpb3MgaW4gdGhlIHNob3J0IHRlcm0gaGF2ZSBhIGNlcnRhaW4gcHJvYmFiaWxpdHkgcCB0byBoYXBwZW4gaW4gb25lIGRheS4gRm9yIGV4YW1wbGUsIGlmIHRoZSBwcm9iYWJpbGl0eSBvZiBsb3NpbmcgMTAlIG9yIE1PUkUgb2YgYW4gaW52ZXN0bWVudCBpbiBvbmUgc2luZ2xlIGRheSBpcyA1JSwgdGhlbiB3ZSBzYXkgdGhhdCB0aGUgNSUgVmFsdWUgYXQgUmlzayAoNSVWYVIpIGlzIGVxdWFsIHRvIDEwJS4KV2UgY2FuIGFsc28gY2FsY3VsYXRlIFZhUiBpbiBtb25leSBpZiB3ZSBrbm93IHRoZSBpbml0aWFsIGludmVzdG1lbnQuIEZvciBleGFtcGxlLCB1c2luZyB0aGUgc2FtZSBleGFtcGxlLCBpZiBteSBpbml0aWFsIGludmVzdG1lbnQgaXMgJDHigJkwMDAsMDAwLCB0aGVuIHRoZSA1JVZhUiA9IDEwJSwgd2hpY2ggaXMgZXF1YWwgdG8gJDEwMCwwMDAuMDAuIFZhUiBjYW4gYmUgcmVwb3J0ZWQgYXMgYSBwb3NpdGl2ZSBvciBuZWdhdGl2ZSBhbW91bnQ7IHRoaXMgaXMganVzdCBhIG1hdHRlciBvZiBwcmVmZXJlbmNlLiBCdXQgd2UgaGF2ZSB0byBiZSBhd2FyZSB0aGF0IFZhUiBpcyBhIG1lYXN1cmUgb2YgcG90ZW50aWFsIGxvc3MgaW4gJSBvciBpbiAkIHdpdGggYSBjZXJ0YWluIHByb2JhYmlsaXR5LgpwJVZhUiBpcyB0aGUgTUlOSU1VTSAlIGxvc3Mgb2YgYW4gaW52ZXN0bWVudCB3aXRoIGEgcHJvYmFiaWxpdHkgb2YgcC4gSW4gb3RoZXIgd29yZHMsIHRoZXJlIGlzIGEgcHJvYmFiaWxpdHkgcCB0aGF0IEkgY2FuIGxvc2UgJVZhUiBvciBNT1JFLiBBbm90aGVyIHdheSB0byBkZWZpbmUgcCVWYVIgaXMgdGhlIGZvbGxvd2luZy4gcCVWYVIgaXMgdGhlIE1BWElNVU0gJWxvc3Mgb2YgYW4gaW52ZXN0bWVudCB3aXRoIGEgcHJvYmF0aWxpdHkgKDEtcCkuIEluIG90aGVyIHdvcmRzLCB0aGVyZSBpcyBhIHByb2JhYmlsaXR5ICgxLXApIHRoYXQgSSBjYW4gaGF2ZSBhIHJldHVybiBvZiAlVmFSIG9yIEhJR0hFUi4KVGhlbiwgd2UgY2FuIHNheSB0aGF0IHAlVmFSIGlzIHRoZSBiZXN0IHNjZW5hcmlvIHRoYXQgY2FuIGhhcHBlbiBhZnRlciBhIHZlcnkgYmFkIHNjZW5hcmlvIHRoYXQgY2FuIGhhcHBlbiB3aXRoIHByb2JhYmlsaXR5IHAuIEFsc28sIHdlIGNhbiBzYXkgdGhhdCBwJVZhUiBpcyB0aGUgd29yc2Ugc2NlbmFyaW8gdGhhdCBjYW4gaGFwcGVuIHdoZW4gdGhlIHNjZW5hcmlvIGlzIG5vdCB0aGUgYmFkIG9uZSwgc28gd2hlbiB0aGVyZSBpcyBhIHByb2JhYmlsaXR5IG9mICgxLXApJS4KTGV04oCZcyBpbGx1c3RyYXRlIFZhUiB1c2luZyByZWFsIGRhdGEgZnJvbSB0aGUgVVMgaW5kZXggUyZQNTAwIGRhaWx5IHJldHVybnMgZnJvbSBKYW51YXJ5IDIwMTkgdG8gQXByaWwgMjYsIDIwMjIuCgpgYGB7cn0KbGlicmFyeShxdWFudG1vZCkKZ2V0U3ltYm9scygiXkdTUEMiLCBmcm9tPSIyMDE5LTAxLTAxIiwKICAgICAgICAgICAgICAgICAgICB0bz0iMjAyMi0wNC0yNyIpCmBgYAoKYGBge3J9CiMgSSBnZXQgdGhlIGFkanVzdGVkIGNvbHVtbjoKU1BpbmRleCA9IEFkKEdTUEMpCiMgSSBjYWxjdWxhdGUgZGFpbHkgcmV0dXJucyBvZiB0aGUgaW5kZXg6ClNQcmV0dXJuPC0gbmEub21pdChkaWZmKGxvZyhTUGluZGV4KSkpCm5hbWVzKFNQcmV0dXJuKTwtYygicmV0dXJuIikKYGBgCgpXZSBwbG90IHRoZSBkYWlseSBpbmRleCBvdmVyIHRpbWU6CmBgYHtyfQpwbG90KFNQaW5kZXgpCmBgYApXZSBzZWUgc3Ryb25nIGRlY2xpbmUgaW4gTWFyY2ggMjAyMCwgYW5vdGhlciBpbXBvcnRhbnQgZGVjbGluZSBpbiBlYXJseSAyMDIyLgoKTm93IHdlIGRvIGEgaGlzdG9ncmFtIG9mIHRoZSByZXR1cm4gb2YgdGhpcyBpbmRleAoKYGBge3J9Cmhpc3QoU1ByZXR1cm4sIGJyZWFrcz00MCkKYGBgClRoZSBoZWlnaHQgb2YgZWFjaCBiYXIgcmVwcmVzZW50cyB0aGUgZnJlcXVlbmN5IGluIG51bWJlciBvZiBkYXlzIHRoYXQgYSBzcGVjaWZpYyBkYWlseSByZXR1cm4gcmFuZ2UgaGFzIGhhcHBlbmVkLgoKSWYgdGhlIGRhaWx5IHJldHVybnMgYmVoYXZlcyBsaWtlIGEgbm9ybWFsLWRpc3RyaWJ1dGVkIHZhcmlhYmxlLCB0aGVuIGFib3V0IDIuNSUgb2YgdGhlIGRheXMgdGhlIFMmUDUwMCByZXR1cm5zIHdvdWxkIGJlIGxlc3MgdGhhbiB0aGUgaXRzIG1lYW4gbWludXMgMiB0aW1lcyBpdHMgc3RhbmRhcmQgZGV2aWF0aW9uLiBSZW1lbWJlciB0aGF0IGZvciBhIG5vcm1hbC1kaXN0cmlidXRlZCB2YXJpYWJsZSwgaW4gdGhlIHJhbmdlIHBsdXMvbWludXMgMiBzdGFuZGFyZCBkZXZpYXRpb25zIGZyb20gaXRzIG1lYW4sIHdlIHdpbGwgZmluZCBhYm91dCA5NSUgb2YgdGhlIHZhbHVlcy4KCldlIGRvd25sb2FkZWQgODM1IGRheXMgb2YgcmV0dXJuLCBzbyB3ZSB3b3VsZCBleHBlY3QgdGhhdCBhYm91dCAyMC44NzUgd2lsbCBiZSB0aGUgIyBvZiBkYXlzIHRoYXQgdGhlIFNQJjUwMCB3b3VsZCBvZmZlciByZXR1cm5zIGxlc3MgdGhhbiAtMiB0aW1lcyBpdHMgc3RhbmRhcmQgZGV2aWF0aW9uIGZyb20gaXRzIG1lYW46CgpgYGB7cn0KIyBOdW1iZXIgb2YgZGF5cyBmb3IgdGhlIFMmUCByZXR1cm5zOgpOPW5yb3coU1ByZXR1cm4pCk4KYGBgCgpgYGB7cn0KIyBUaGUgMi41JSBvZiB0aGVzZSAjIG9mIGRheXMgaXMgYWJvdXQ6Cm4yNT0wLjAyNSpucm93KFNQcmV0dXJuKQpuMjUKYGBgCgpOb3cgd2UgY2FuIGxvb2sgdGhlIHJlYWwgZGF0YSBhbmQgc2VlIGhvdyBtYW55IGRheXMgdGhlIFMmUDUwMCBoYXMgb2ZmZXJlZCByZXR1cm5zIGxlc3MgdGhhbiAyIHRpbWVzIGl0cyBzdGFuZGFyZCBkZXZpYXRpb24gZnJvbSBpdHMgbWVhbi4gV2UgY2FuIGNhbGN1bGF0ZSB0aGUgbWVhbiBhbmQgc3RhbmRhcmQgZGV2aWF0aW9uICh2b2xhdGlsaXR5KSBvZiBkYWlseSByZXR1cm5zLCBhbmQgdGhlbiBpZGVudGlmeSBob3cgbWFueSBkYXlzIHRoZSBTJlA1MDAgaGFzIG9mZmVyZWQgZXh0cmVtZSByZXR1cm5zIGxlc3MgdGhhbiB0aGUgbWVhbiBtaW51cyAyIHRpbWVzIGl0cyB2b2xhdGlsaXR5OgoKYGBge3J9CiMgV2UgY2FsY3VsYXRlIHRoZSBtZWFuIGFuZCBzdGFuZGFyZCBkZXZpYXRpb24gb2YgcmV0dXJuczoKbWVhbl9yZXR1cm49bWVhbihTUHJldHVybiRyZXR1cm4pCm1lYW5fcmV0dXJuCmBgYAoKYGBge3J9CnZvbGF0aWxpdHkgPSBzZChTUHJldHVybiRyZXR1cm4pCnZvbGF0aWxpdHkKYGBgCgpgYGB7cn0KIyBXZSBjYWxjdWxhdGUgdGhlIGV4cGVjdGVkIG1pbmltdW0gcmV0dXJuIG9mIHRoZSA5NSUgY29uZmlkZW5jZSBpbnRlcnZhbCAoQy5JLikgCiMgICBhc3N1bWluZyBub3JtYWxpdHkgKHRoZSAyLjUgcGVyY2VudGlsZSkKbWluOTVjaV9yZXR1cm5zID0gbWVhbl9yZXR1cm4tMip2b2xhdGlsaXR5Cm1pbjk1Y2lfcmV0dXJucwpgYGAKCmBgYHtyfQojIFdlIHNlbGVjdCB0aGUgZGF5cyB3aXRoIHJldHVybnMgbGVzcyB0aGFuIHRoZSBtaW5pbXVtIG9mIHRoZSA5NSUgQy5JLgpleHRyZW1lczwtIFNQcmV0dXJuW1NQcmV0dXJuJHJldHVybjxtaW45NWNpX3JldHVybnMsXQpleHRyZW1lcwpgYGAKCmBgYHtyfQpuZXh0cmVtZXMgPSBucm93KGV4dHJlbWVzKQojIE51bWJlciBvZiBleHRyZW1lIHJldHVybnM6Cm5leHRyZW1lcwpgYGAKCmBgYHtyfQpwZXJjZXh0cmVtZXMgPSBuZXh0cmVtZXMgLyBOICogMTAwCnBlcmNleHRyZW1lcwpgYGAKCkluIHRoaXMgY2FzZSwgd2UgaGF2ZSAyNSBleHRyZW1lIGRheXMgd2l0aCByZXR1cm5zIGxlc3MgdGhhbiB0aGUgbWluaW11bSBvZiB0aGUgOTUlIEMuSS4gb2YgZGFpbHkgcmV0dXJucy4gVGhlbiwgaXQgc2VlbXMgdGhhdCB3ZSBoYXZlIGhhZCBtb3JlIGV4dHJlbWUgcmV0dXJucyB0aGFuIGV4cGVjdGVkLiBUaGlzIHJlcHJlc2VudHMgYWJvdXQgMi45OTQwMTIlIG9mIHRoZSB0b3RhbCAjIG9mIGRheXMsIHdoaWNoIGlzIGdyZWF0ZXIgdGhhbiB0aGUgZXhwZWN0ZWQgMi41JS4KClRoZW4sIDIuOTk0MDEyJSBvZiB0aGUgdGltZSwgdGhlIFMmUDUwMCBoYXMgZXhwZXJpZW5jZSBhIGxvc3Mgb2YgLTIuNzczMzEyMyUgb3IgTU9SRS4gSWYgd2UgYmVsaWV2ZSB0aGF0IGluIHRoZSBmdXR1cmUgdGhlIFMmUDUwMCB3aWxsIGJlaGF2ZSBpbiBhIHNpbWlsYXIgbWFubmVyLCB0aGVuIHdlIGNhbiBzYXkgdGhhdCB0aGVyZSBpcyBhIHByb2JhYmlsaXR5IG9mIDIuOTk0MDEyJSB0aGF0IEkgY2FuIGxvc2UgLTIuNzczMzEyMyUgb3IgTU9SRSBpbiBvbmx5IE9ORSBEQVkuCgpXZSBjYW4gYWxzbyBzYXkgdGhhdCB0aGVyZSBpcyBhIHByb2JhYmlsaXR5IG9mIDk3LjAwNTk4OCUgKDEwMCUgLSAyLjk5NDAxMiUpIHRoYXQgdGhlIE1BWElNVU0gbG9zcyBJIGNhbiBleHBlcmllbmNlIGluIE9ORSBEQVkgaXMgLTIuNzczMzEyMyUuIFRoZW4sIHRoZSAyLjk5NDAxMiVWYVIgb2YgdGhlIGRhaWx5IFMmUDUwMCByZXR1cm5zIGlzIC0yLjc3MzMxMjMlCgpgYGB7cn0KVmFSMSA9IG1pbjk1Y2lfcmV0dXJucyoxMDAKVmFSMQpgYGAKRm9yIHR1cmJ1bGVuY2UgcGVyaW9kcyBpbiBmaW5hbmNpYWwgbWFya2V0cyBpdCBpcyBsaWtlbHkgdGhhdCBhIGJhZCBzY2VuYXJpbyB3aXRoIHByb2JhYmlsaXR5IHAgY2FuIGhhcHBlbi4gT25jZSB0aGlzIHNjZW5hcmlvIGhhcHBlbnMsIHRoZW4gcCVWYVIgaXMgdGhlIGJlc3Qgc2NlbmFyaW8sIGJ1dCBpbiByZWFsaXR5IHRoaXMgdGhlIHAlVmFSIGlzIG5vdCB0b28gcmVhbGlzdGljLiBXZSBuZWVkIHRvIGJlIG1vcmUgY29uc2VydmF0aXZlIGFuZCBlc3RpbWF0ZSB3aGljaCBtaWdodCBiZSB0aGUgZXhwZWN0ZWQgbG9zcyBvbmNlIHRoZSBwcm9iYWJpbGl0eSBwIG9mIHRoZSBiYWQgc2NlbmFyaW8gaGFwcGVucy4gVGhpcyBjb25zZXJ2YXRpdmUgZXN0aW1hdGUgaXMgZ2l2ZW4gYnkgdGhlIEV4cGVjdGVkIFNob3J0ZmFsbC4gV2Ugd2lsbCByZXZpZXcgdGhlIGNvbmNlcHQgb2YgRVMgaW4gdGhlIGZvbGxvd2luZyBzZWN0aW9uLgoKIyBFeHBlY3RlZCBTaG9ydGZhbGwgKEVTKQoKRXhwZWN0ZWQgU2hvcnRmYWxsIHdpdGggYSBwcm9iYWJpbGl0eSBwIHJlZmVycyB0byB0aGUgZXhwZWN0ZWQgYXZlcmFnZSBsb3NzIG9mIGFuIGludmVzdG1lbnQgaW4gT05FIHBlcmlvZCAoaW4gdGhpcyBjYXNlLCBpbiBvbmUgZGF5KSBvbmNlIHRoZSBwcm9iYWJpbGl0eSBwIG9mIGEgYmFkIHNjZW5hcmlvIGhhcHBlbnMuIFRoZW4sIHRoZSBhYnNvbHV0ZSB2YWx1ZSBvZiBwJUVTIHdpbGwgYWx3YXlzIGJlIGdyZWF0ZXIgKG1vcmUgbmVnYXRpdmUpIHRoYW4gdGhlIHAlVmFSLiBMZXTigJlzIGNhbGN1bGF0ZSB0aGUgRVMgdXNpbmcgdGhlIHByZXZpb3VzIGV4YW1wbGUgb2YgdGhlIFMmUDUwMCA1MDAgZGFpbHkgcmV0dXJucy4KClRvIGVzdGltYXRlIHRoZSBFUyBhdCB0aGUgMi45OTQwMTIlIHByb2JhYmlsaXR5LCB3ZSBqdXN0IGNhbGN1bGF0ZSB0aGUgYXZlcmFnZSBvZiB0aGUgZGF5cyB3aGVuIHRoZSBTJlA1MDAgcmV0dXJucyBoYXZlIGJlZW4gbGVzcyB0aGFuIC0yLjc3MzMxMjMlLldlIGNhbiBkbyB0aGlzIGFzIGZvbGxvd3MKCmBgYHtyfQpleHRyZW1lcwpgYGAKYGBge3J9CkVTPW1lYW4oZXh0cmVtZXMkcmV0dXJuKSAqIDEwMApFUwpgYGAKVGhlIEV4cGVjdGVkIFNob3J0ZmFsbCBhdCB0aGUgMi45OTQwMTIlIHByb2JhYmlsaXR5IGlzIHRoZSBhdmVyYWdlIG9mIHRoZXNlIGV4dHJlbWUgcmV0dXJuLCB3aGljaCBpcyAtNC40MTI5NDYyJS4gQXMgZXhwZWN0ZWQsIHRoZSAyLjk5NDAxMiUgRVMgaXMgbW9yZSBuZWdhdGl2ZSB0aGFuIHRoZSAyLjk5NDAxMiVWYVIgKC00LjQxMjk0NjIlIHZzIC0yLjc3MzMxMjMlKS4KClRoZXJlIGFyZSBtb3JlIHRoYW4gb25lIG1ldGhvZCB0byBlc3RpbWF0ZSBWYVIgYW5kIEVTLiBSZWFkIHRoZSBteSBOb3RlIOKAnEludHJvZHVjdGlvbiB0byBWYWx1ZSBhdCBSaXNr4oCdIHRvIGxlYXJuIGRpZmZlcmVudCBtZXRob2RzIHRvIGVzdGltYXRlIFZhUiBhbmQgRXhwZWN0ZWQgU2hvcnRmYWxsLgoKVGhlIG1vc3QgcG9wdWxhciBtZXRob2RzIGFyZSAxKSBQZXJjZW50aWxlIG1ldGhvZCB1c2luZyByZWFsIGRpc3RyaWJ1dGlvbiwgMikgYXNzdW1pbmcgbm9ybWFsIGRpc3RyaWJ1dGlvbiBvZiByZXR1cm5zLCBhbmQgMykgYXNzdW1pbmcgYSBmYXQtdGFpbGVkIGRpc3RyaWJ1dGlvbiBvZiByZXR1cm5zIHVzaW5nIHRoZSB0LVN0dWRlbnQgcHJvYmFiaWxpdHkgZGlzdHJpYnV0aW9uLgoKQW5vdGhlciBub3QgcG9wdWxhciBtZXRob2QgKGJ1dCBtb3JlIGFjY3VyYXRlKSBpcyB1c2luZyBhIHZvbGF0aWxpdHkgbW9kZWwgbGlrZSBhbiBHQVJDSCgxLDEpIG1vZGVsIHRvIGVzdGltYXRlIGFuZCBmb3JlY2FzdCBkYWlseSB2b2xhdGlsaXR5LCBhbmQgdXNlIHRoaXMgdm9sYXRpbGl0eSB0byBlc3RpbWF0ZSBWYWx1ZSBhdCBSaXNrLgoKIyBLdXJ0b3NpcyBhbmQgZmF0LXRhaWwgZGlzdHJpYnV0aW9uCgpTa2V3bmVzcyBhbmQgS3VydG9zaXMgYXJlIHN0YXRpc3RpY2FsIG1lYXN1cmVzIG9mIGEgcmFuZG9tIHZhcmlhYmxlLiBIZXJlIGlzIGEgcXVpY2sgc3VtbWFyeSBvZiBTa2V3bmVzcyBhbmQgS3VydG9zaXM6CgpTa2V3bmVzcyBpcyBhIG1lYXN1cmUgZm9yIGFzeW1tZXRyeSBvZiB0aGUgZGlzdHJpYnV0aW9uLiBBIG5vcm1hbCBkaXN0cmlidXRpb24gaGFzIGFib3V0IHRoZSBzYW1lIHZhbHVlcyB0aGF0IGFyZSBsZXNzIHRoYW4gdGhlbiBtZWFuIGNvbXBhcmVkIHdpdGggdGhlIHZhbHVlcyB0aGF0IGFyZSBoaWdoZXIgdGhhbiB0aGUgbWVhbi4gQSBub3JtYWwgZGlzdHJpYnV0aW9uIGhhcyBhIHNrZXduZXNzIGNsb3NlIHRvIHplcm8uIEEgbmVnYXRpdmUgc2tld25lc3MgbWVhbnMgdGhhdCB0aGUgdGFpbCB0byB0aGUgbGVmdCBoYXMgbW9yZSB2YWx1ZXMgKHNrZXdlZCB0byB0aGUgbGVmdCkuIEEgcG9zaXRpdmUgc2tld25lc3MgbWVhbnMgdGhhdCB0aGUgdGFpbCB0byB0aGUgcmlnaHQgaGFzIG1vcmUgdmFsdWVzIChza2V3ZWQgdG8gdGhlIHJpZ2h0KS4KCkt1cnRvc2lzIGNhbiBiZSB1c2VkIHRvIGV4YW1pbmUga25vdyB3aGV0aGVyIGEgdmFyaWFibGUgaGFzIGEgZGlzdHJpYnV0aW9uIHdpdGggbXVjaCBtb3JlIGV4dHJlbWUgdmFsdWVzIGNvbXBhcmVkIHRvIHRoZSBub3JtYWwgZGlzdHJpYnV0aW9uLiBBY2NvcmRpbmcgdG8gdGhlIHZhbHVlIG9mIEt1cnRvc2lzLCB3ZSBjYW4gaWRlbnRpZnkgd2hldGhlciB3ZSBoYXZlIGEgc2lnbmlmaWNhbnQgbnVtYmVyIG9mIGV4dHJlbWUgdmFsdWVzIGluIGEgdmFyaWFibGU6CgpJZiBLdXJ0b3Npcz0zIHRoZW4sIHRoZSB2YXJpYWJsZSBiZWhhdmVzIGNsb3NlIHRvIG5vcm1hbCBkaXN0cmlidXRpb24KCklmIEt1cnRvc2lzPjMsIHRoZW4gdGhpcyBtZWFucyB0aGF0IHRoZXJlIGFyZSBleHRyZW1lIHZhbHVlcyBpbiB0aGUgdmFyaWFibGUgdGhhdCBtYWtlcyB0aGUgZGlzdHJpYnV0aW9uIHRvIGJlIGEgZmF0LXRhaWxlZCBkaXN0cmlidXRpb24uCgpIZXJlIGlzIGEgcXVpY2sgcmV2aWV3IG9mIG1vbWVudHMgaW4gc3RhdGlzdGljcywgd2hpY2ggYXJlIHRoZSBiYXNlIHRvIHVuZGVyc3RhbmQgVmFyaWFuY2UsIFNrZXduZXNzIGFuZCBLdXJ0b3NpczoKCk1vbWVudHMgaW4gU3RhdGlzdGljczoKCkEgTW9tZW50IGluIFN0YXRpc3RpcyBpcyBhIHNwZWNpZmljIG1lYXN1cmUgYWJvdXQgYSBwcm9iYWJpbGl0eSBkaXN0cmlidXRpb24gb2YgYSByYW5kb20gdmFyaWFibGUuCgpUaGUgZXhwZWN0ZWQgdmFsdWUgb2YgYSByYW5kb20gdmFyaWFibGUgWCBjYW4gYmUgY2FsY3VsYXRlZCBhcyB0aGUgbWVhbiBvZiBYIHVzaW5nIGhpc3RvcmljYWwgdmFsdWVzOgoKTWVhbihYKT1Y4o6v4o6v4o6v4o6vPUVbWF09MU7iiJEoWGkpPVgxK1gyKy4uLlhOTgoKVGhlIDQgTW9tZW50cyBpbiBTdGF0aXN0aWNzIGFyZToKCjFzdCBtb21lbnQ6IEVbWOKIkljijq/ijq/ijq/ijq9dPTAKCjJuZCBtb21lbnQ6IEVbWOKIkljijq/ijq/ijq/ijq9dMj0xTuKIkShYaeKIkljijq/ijq/ijq/ijq8pMj1WQVIoWCkKID0gVmFyaWFuY2UoWCk7CgpUaGUgU3RhbmRhcmQgRGV2aWF0aW9uIG9mIFggaXMgdGhlIHNxdWFyZSByb290IG9mIHRoZSBWYXJpYW5jZShYKToKU0QoWCk9VkFSKFgp4oC+4oC+4oC+4oC+4oC+4oC+4oC+4oC+4oiaCgozcmQgbW9tZW50OiBFW1jiiJJY4o6v4o6v4o6v4o6vXTM9MU7iiJEoWGniiJJY4o6v4o6v4o6v4o6vKTMKVGhlIDNyZCBtb21lbnQgaXMgdXNlZCB0byBlc3RpbWF0ZSBTa2V3bmVzcyhYKSBhczoKClNrZXduZXNzKFgpPUVbWOKIkljijq/ijq/ijq/ijq9dM1NEKFgpMwoKNHJkIG1vbWVudDogRVtY4oiSWOKOr+KOr+KOr+KOr100PTFO4oiRKFhp4oiSWOKOr+KOr+KOr+KOryk0ClRoZSA0cmQgbW9tZW50IGlzIHVzZWQgdG8gZXN0aW1hdGUgS3VydG9zaXMoWCkgYXM6CgpLdXJ0b3NpcyhYKT1FW1jiiJJY4o6v4o6v4o6v4o6vXTRTRChYKTQKCkNhbGN1bGF0ZSBLdXJ0b3NpcyBvZiBTJlA1MDAgZGFpbHkgcmV0dXJucy4gRG8geW91IHNlZSBhIHNpZ24gb2YgZmF0LXRhaWwgZGlzdHJpYnV0aW9uIG9mIHJldHVybnMKClRoZSBtb21lbnRzIGxpYnJhcnkgaGFzIGZ1bmN0aW9ucyBmb3IgS3VydG9zaXMgYW5kIFNrZXduZXNzLiBJbnN0YWxsIHRoaXMgbGlicmFyeQoKYGBge3J9CmxpYnJhcnkobW9tZW50cykKa3VydG9zaXMgPSBhcy5udW1lcmljKGt1cnRvc2lzKFNQcmV0dXJuKSkKa3VydG9zaXMKYGBgCgpTaW5jZSBrdXJ0b3NpcyBpcyBtdWNoIGhpZ2hlciB0aGFuIDMsIHRoaXMgaXMgYSBzaWduIG9mIGZhdC10YWlsZWQgZGlzdHJpYnV0aW9uLgoKIyBFc3RpbWF0aW5nIFZhUiBhc3N1bWluZyBmYXQtdGFpbCBkaXN0cmlidXRpb24KQ29uc2lkZXJpbmcgdGhhdCB0aGUgZGlzdHJpYnV0aW9uIG9mIHJlYWwgcmV0dXJucyBpcyBtb3JlIGEgZmF0LXRhaWwgZGlzdHJpYnV0aW9uIChtb3JlLXRoYW4tbm9ybWFsIGV4dHJlbWUgdmFsdWVzKSwgaXQgaXMgYmV0dGVyIHRvIHVzZSB0aGUgdCBkaXN0cmlidXRpb24gcmF0aGVyIHRoYW4gdGhlIG5vcm1hbCBkaXN0cmlidXRpb24uIFJlc2VhcmNoIGluZGljYXRlcyB0aGF0IHRoZXJlIGlzIGEgcmVsYXRpb25zaGlwIGJldHdlZW4gdGhlIGt1cnRvc2lzIGFuZCB0aGUgZGVncmVlcyBvZiBmcmVlZG9tIG9mIHRoZSB0IGRpc3RyaWJ1dGlvbiB0byBtb2RlbCBmYXQtdGFpbCBkaXN0cmlidXRpb25zLgpBIHQtZGlzdHJpYnV0aW9uIHdpdGggbG93IGRlZ3JlZXMgb2YgZnJlZWRvbSBzaG93cyBmYXR0ZXIgdGFpbHMgY29tcGFyZWQgd2l0aCBhIHQgZGlzdHJpYnV0aW9uIHdpdGggaGlnaGVyIGRlZ3JlZXMgb2YgZnJlZWRvbSAob3IgY29tcGFyZWQgdG8gYSBub3JtYWwgZGlzdHJpYnV0aW9uKS4KVGhlIHdheSB0byBlc3RpbWF0ZSB0aGUgZGVncmVlcyBvZiBmcmVlZG9tIG9mIGEgdCBkaXN0cmlidXRpb24gdG8gbW9kZWwgYSBmYXQtdGFpbCBkaXN0cmlidXRpb24sIHdlIHVzZSB0aGUga3VydG9zaXMgb2YgdGhlIGRpc3RyaWJ1dGlvbiBhcyBmb2xsb3dzOgpEZWdyZWVzIG9mIGZyZWVkb20gKGRmKT0gNi9LdXJ0b3NpcyArIDQKWW91IGhhdmUgdG8gZXN0aW1hdGUgdGhlIGRlZ3JlZXMgb2YgZnJlZWRvbSBhbmQgdGhlbiB1c2UgdGhlIHQgZGlzdHJpYnV0aW9uIHRvIGVzdGltYXRlIHRoZSAxJSBWYVIgb2YgJDFtaWxsaW9uIGZvciB0aGUgbmV4dCBmdXR1cmUgZGF5IG9mIHRoZSBzYW1wbGUuIENvbXBhcmUgYm90aCBlc3RpbWF0aW9ucyBvZiBWYVIsIHRoZSBvbmUgY2FsY3VsYXRlZCBhc3N1bWluZyBub3JtYWwgZGlzdHJpYnV0aW9uIGFuZCB0aGlzIG9uZS4gQnJpZWZseSByZXBvcnRzIHRoaXMgY29tcGFyaXNvbi4KSGludDogdGhlIGZ1bmN0aW9uIHF0KDAuMDEsZGYpIGdpdmVzIHlvdSB0aGUgdCB2YWx1ZSwgd2hpY2ggcmVwcmVzZW50cyB0aGUgIyBvZiBzdGFuZGFyZCBkZXZpYXRpb25zIHlvdSBuZWVkIHRvIGdvIGZyb20gdGhlIG1lYW4gdG8gdGhlIGxlZnQgdG8gYXJyaXZlIHRvIHRoZSAxJSBwZXJjZW50aWxlLgpJIGNhbGN1bGF0ZSB0aGUgZGVncmVlcyBvZiBmcmVlZG9tIEkgdXNlIHRvIHNpbXVsYXRlIGEgZmF0LXRhaWxlZCBkaXN0cmlidXRpb24gdXNpbmcgdGhlIHQtU3R1ZGVudCBkaXN0cmlidXRpb246CgpgYGB7cn0KIyBJIGNhbGN1bGF0ZSB0aGUgZGVncmVlcyBvZiBmcmVlZG9tIGZvciB0aGUgdCBkaXN0cmlidXRpb246CmRmID0gNi9rdXJ0b3NpcyArIDQKZGYKYGBgCgpgYGB7cn0KIyBJIGNhbGN1bGF0ZSB0aGUgdCBjcml0aWNhbCB2YWx1ZSBhY2NvcmRpbmcgdG8gdGhlIHByb2JhYmlsaXR5IG9mIDElIGFuZCB0aGUgZGY6CnQxID0gcXQoMC4wMSxkZikKdDEKYGBgCgpOb3cgSSBnZXQgdGhlIDElVmFSIGFzc3VtaW5nIGZhdC10YWlsIGRpc3RyaWJ1dGlvbjoKCmBgYHtyfQptZWFuc3AgPSBtZWFuKFNQcmV0dXJuKQp2b2xhdGlsaXR5c3AgPSBzZChTUHJldHVybikKVmFSMiA9IG1lYW5zcCArIHQxICogdm9sYXRpbGl0eXNwClZhUjIKYGBgCkludGVycHJldGF0aW9uIG9mIHRoaXMgMSVWYVI6CgpBc3N1bWluZyBmYXQtdGFpbCBkaXN0cmlidXRpb24gb2YgZGFpbHkgcmV0dXJucyBvZiB0aGUgUyZQNTAwLCBJIGNhbiBsb3NlIGluIG9uZSBkYXkgLTUuMDUwNzkwNSUgb3IgbW9yZSB3aXRoIGEgcHJvYmFiaWxpdHkgb2YgMSUuCgpDb21wYXJlZCB0byB0aGUgZmlyc3QgMSVWYVI9LTI3Ny4zMzEyMjclIChhc3N1bWluZyBub3JtYWwgZGlzdHJpYnV0aW9uKSwgdGhpcyAxJVZhUj0tNS4wNTA3OTA1JSBhc3N1bWluZyBmYXQtdGFpbCBkaXN0cmlidXRpb24gaXMgbW9yZSBjb25zZXJ2YXRpdmUsIGFuZCBtb3JlIHJlYWxpc3RpYy4KClRvIGNhbGN1bGF0ZSB0aGUgRXhwZWN0ZWQgU2hvcnRmYWxsIGFzc3VtaW5nIGZhdC10YWlsIGRpc3RyaWJ1dGlvbiwgd2UgY2FuIGNhbGN1bGF0ZSB0aGUgYXZlcmFnZSByZXR1cm4gb2YgdGhlIGJhZCBkYXlzIHRoYXQgaGF2ZSBoYWQgcmV0dXJucyBsZXNzIHRoYW4gdGhlIDElVmFSIGFzc3VtaW5nIGZhdC10YWlsIGRpc3RyaWJ1dGlvbjoKCmBgYHtyfQpiYWRkYXlzMiA8LSBTUHJldHVybltTUHJldHVybiRyZXR1cm48PVZhUjIsXQpiYWRkYXlzMgpgYGAKCk5vdyB3ZSBjYW4gZ2V0IHRoZSBhdmVyYWdlIG9mIHRoZXNlIHZlcnkgYmFkIGRheXM6CgpgYGB7cn0KRVMzID0gbWVhbihiYWRkYXlzMiRyZXR1cm4pCkVTMwpgYGAKClRoaXMgd291bGQgYmUgdGhlIG1vcmUgY29uc2VydmF0aXZlIGVzdGltYXRpb24gb2YgMSUgRXhwZWN0ZWQgU2hvcnRmYWxsIG9mIHRoZSBTJlA1MDAuIFRoZW4sIGFzc3VtaW5nIGZhdC10YWlsIGRpc3RyaWJ1dGlvbiBvZiBkYWlseSByZXR1cm5zIG9mIHRoZSBTJlA1MDAsIGFuZCB1c2luZyByZWFsIGhpc3RvcmljYWwgZGFpbHkgcmV0dXJucywgT04gQVZFUkFHRSwgSSBjYW4gbG9zZSBpbiBvbmUgZGF5IC04LjQxMTY0ODYlIHdpdGggYSBwcm9iYWJpbGl0eSBvZiAxJS4KCiMgRm9yZWNhc3RpbmcgVmFSIHdpdGggR0FSQ0goMSwxKSBNb2RlbAoKV29yayB3aXRoIHRoZSBzYW1lIGRhdGFzZXQgKGRhaWx5IFMmUDUwMCByZXR1cm5zKS4KCjEuLSBSdW4gYSBHQVJDSCgxLDEpIG1vZGVsLiBJTlRFUlBSRVQgdGhlIG1vZGVsIGFuZCBicmllZmx5IGV4cGxhaW4geW91ciByZXN1bHRzLgoKYGBge3J9CmxpYnJhcnkocnVnYXJjaCkKRXNwZWNnYXJjaDE9dWdhcmNoc3BlYyh2YXJpYW5jZS5tb2RlbD0gbGlzdChtb2RlbD0gInNHQVJDSCIsIGdhcmNoT3JkZXI9IGMoMSwgMSksIApzdWJtb2RlbD0gTlVMTCwgIHZhcmlhbmNlLnRhcmdldGluZz0gRkFMU0UpLCAKbWVhbi5tb2RlbD0gbGlzdChhcm1hT3JkZXI9IGMoMCwgMCksIGluY2x1ZGUubWVhbj0gVFJVRSwgYXJjaG09IEZBTFNFLCAKYXJjaHBvdz0gMCwgYXJmaW1hPSBGQUxTRSwgIGV4dGVybmFsLnJlZ3Jlc3NvcnM9IE5VTEwsIGFyY2hleD0gRkFMU0UpLCAKZGlzdHJpYnV0aW9uLm1vZGVsPSAibm9ybSIsIHN0YXJ0LnBhcnM9IGxpc3QoKSwgZml4ZWQucGFycz0gbGlzdCgpKQoKI0VzdGltYWNpw7NuIGRlbCBHQVJDSCgxLDEpCgpnYXJjaDE8LSB1Z2FyY2hmaXQoc3BlYz1Fc3BlY2dhcmNoMSwgZGF0YT1TUHJldHVybiRyZXR1cm4pCmdhcmNoMQpgYGAKKklOVEVSUFJFVEFUSU9OIHRoZSBtb2RlbCBvdXRwdXQqKgoKV2hhdCBkb2VzIGVhY2ggY29lZmZpY2llbnQgbWVhbj8KClRIRSBiZXRhMSBDT0VGRklDSUVOVCBJUyAwLjcyMTA2NzgsIEFORCBJVCBJUyBTSUdOSUZJQ0FOVExZIERJRkZFUkVOVCBUSEFOIFpFUk8uIFRISVMgTUVBTlMgVEhBVCBBQk9VVCA3Mi4xMDY3NzYyJSBPRiBUSEUgUkVUVVJOIFZBUklBTkNFIE9GIFlFU1RFUkRBWSBJUyBQQVNTRUQgVE8gVEhFIFJFVFVSTiBWQVJJQU5DRSBPRiBUT0RBWSwgQkVTSURFUyBUSEUgSU1QQUNUIE9GIFRIRSBZRVNURVJEQVnigJlTIFNRVUFSRUQgRVJST1IuIFNJTkNFIFRISVMgQ09FRkZJQ0lFTlQgSVMgR1JFQVRFUiBUSEFOIDAuNywgVEhJUyBJUyBBIFNJR04gT0YgQ0xVU1RFUklORyBPRiBWT0xBVElMSVRZLgoKQ09OU0lERVJJTkcgVEhFIFZBUklBTkNFIE9GIFlFU1RFUkRBWSwgVEhFIFNRVUFSRUQgRVJST1IgT0YgWUVTVEVSREFZIElNUEFDVFMgVEhFIFJFVFVSTiBWQVJJQU5DRSBPRiBUT0RBWSBJTiBBIFBPU0lUSVZFIEFORCBTSUdOSUZJQ0FOVCBXQVksIEJVVCBPTkxZIEFCT1VUIDI1LjM2MjExMDMlIE9GIFRIRSBTUVVBUkVEIEVSUk9SIE9GIFlFU1RFUkRBWSBJUyBQQVNTRUQgVE8gVEhFIFZBUklBTkNFIE9GIFRPREFZLgoKMi4tIFdpdGggdGhpcyBHQVJDSCgxLDEpIG1vZGVsLCBmb3JlY2FzdCBib3RoIHZvbGF0aWxpdHkgYW5kIDElIFZhUiBvZiAkMSBtaWxsaW9uIGZvciAxIGZ1dHVyZSBkYXkgKHRvbW9ycm93KS4KCmBgYHtyfQpnYXJjaDEucHJlZGljdGlvbiA8LSB1Z2FyY2hmb3JlY2FzdChnYXJjaDEsbi5haGVhZD0gMSkKYGBgCmdhcmNoMS5wcmVkaWN0aW9uIHdpbGwgYmUgYSB2ZXJ5IHNwZWNpYWwgUiBjbGFzczogYW4gdUdBUkNIZm9yZWNhc3QgY2xhc3MuIFRoaXMgaXMgc3BlY2lhbCBSIGNsYXNzIG9iamVjdCB0aGF0IHN0b3JlcyBpbmZvcm1hdGlvbiBhYm91dCB0aGUgR0FSQ0ggcHJlZGljdGlvbi4KCkZvciB0aGlzIHR5cGUgb2YgUiBjbGFzcyBvYmplY3RzLCB3ZSB1c2UgdGhlIEAgY2hhcmFjdGVyIHRvIGdldCBhY2Nlc3MgdG8gdGhlIGNvbnRlbnQgb2YgZWFjaCBlbGVtZW50IHN0b3JlZCBpbiB0aGlzIG9iamVjdC4KClRoZSBmb3JlY2FzdCBmb3IgdGhlIGRhaWx5IHJldHVybiBpcyBzdG9yZWQgaW4KYGBge3J9CmdhcmNoMS5wcmVkaWN0aW9uQGZvcmVjYXN0JHNlcmllc0ZvcgpgYGAKClRoZSBmb3JlY2FzdCBmb3IgdGhlIHN0YW5kYXJkIGRldmlhdGlvbiBvZiByZXR1cm5zICh2b2xhdGlsaXR5KSBpcyBzdG9yZWQgaW46CgpgYGB7cn0KZ2FyY2gxLnByZWRpY3Rpb25AZm9yZWNhc3Qkc2lnbWFGb3IKYGBgCgpOb3cgdXNpbmcgdGhpcyBwcmVkaWN0ZWQgdm9sYXRpbGl0eSwgSSBjYWxjdWxhdGUgYSBuZXcgMSVWYVIgZm9yIHRvbW9ycm93LiBJIHdpbGwgYXNzdW1lIGZhdC10YWlsIGRpc3RyaWJ1dGlvbiwgc28gSSB3aWxsIHVzZSB0aGUgdC1TdHVkZW50IGRpc3RyaWJ1dGlvbiB3aXRoIHRoZSBkZWdyZWVzIG9mIGZyZWVkb20gSSBjYWxjdWxhdGVkIGFib3ZlOgoKYGBge3J9ClZhUjFfRyA9IG1lYW5zcCArIHQxICogZ2FyY2gxLnByZWRpY3Rpb25AZm9yZWNhc3Qkc2lnbWFGb3JbMV0KVmFSMV9HCmBgYAoKKlRoZSAxJVZhUiB1c2luZyB0aGUgcHJlZGljdGVkIHZvbGF0aWxpdHkgZnJvbSB0aGUgR0FSQ0goMSwxKSBtb2RlbCBpcyAtNy4yMTI4NjczJS4KCkV4dGVuZCB0aGUgZGF0YXNldCAxMCBkYXlzIGluIHRoZSBmdXR1cmUuIERvIGEgd2l0aGluLXNhbXBsZSBmb3JlY2FzdCBhbmQgYW4gb3V0LW9mLXNhbXBsZSBmb3JlY2FzdCBmb3IgYWxsIGRheXMgb2YgdGhlIHllYXIgKGJlZm9yZSBhbmQgYWZ0ZXIgVE9EQVkpIGZvciBkYWlseSB2b2xhdGlsaXR5IGFuZCAxJVZhUiBmb3IgMSBkYXkuCgp3ZSBkbyBhIGZvcmVjYXN0IGZvciAxMCBkYXlzCmBgYHtyfQpnYXJjaDEucHJlZGljdGlvbiA8LSB1Z2FyY2hmb3JlY2FzdChnYXJjaDEsbi5haGVhZD0gMTApCmBgYApXZSBjYW4gcGxvdCB0aGUgaGlzdG9yaWMgYW5kIGZ1dHVyZSB2b2xhdGlsaXR5OgpgYGB7cn0KcGxvdChnYXJjaDEucHJlZGljdGlvbix3aGljaCA9IDMpCmBgYApOb3cgSSBjYWxjdWxhdGUgdGhlIGRhaWx5IDElVmFSIGZvciB0aGVzZSAxMCBmdXR1cmUgZGF5czoKYGBge3J9ClZhUjFfRyA9IG1lYW5zcCArIHQxICogZ2FyY2gxLnByZWRpY3Rpb25AZm9yZWNhc3Qkc2lnbWFGb3IKVmFSMV9HCmBgYApgYGB7cn0KIyBOb3cgSSBjYWxjdWxhdGUgMSVWYVIgZm9yIGEgJDEgbWlsbGlvbiBwZXIgZGF5OgpWYVIxX0dfMW1pbGwgPSBWYVIxX0cgKiAxMDAwMDAwClZhUjFfR18xbWlsbApgYGAKCjQuLSBEbyBhIHBsb3Qgb2Ygdm9sYXRpbGl0eSBhbmQgVmFSIGZvciB0aGUgd2hvbGUgeWVhcgoqVGhlIEdBUkNIKDEsMSkgZml0IGVzdGltYXRpb24gZm9yIHZvbGF0aWxpdHkgKHNpZ21hKSBhbmQgZm9yIHN0b2NrIHJldHVybiBpbiB0aGUgaGlzdG9yeSBpcyBzdG9yZWQgaW4gdGhlIGdhcmNoMSBSIG9iamVjdCBhdDoKCmdhcmNoMUBmaXQkc2lnbWEKCldlIGNhbiBsb29rIGF0IHRoZSBsYXN0IHZhbHVlcyBvZiB0aGUgdm9sYXRpbGl0eSBmaXR0ZWQgdmFsdWVzOgoKYGBge3J9CnRhaWwoZ2FyY2gxQGZpdCRzaWdtYSkKYGBgCgpXZSBjYW4gdXNlIHRoZXNlIGZpdCBzaWdtYSB2YWx1ZXMgYW5kIGF0dGFjaCB0aGVtIGluIHRoZSBTUHJldHVybiB4dHMgZGF0YXNldCBhbG9uZyB3aXRoIHRoZSBkYWlseSByZXR1cm5zOgoKYGBge3J9ClNQcmV0dXJuJGd2b2wgPSBnYXJjaDFAZml0JHNpZ21hCmBgYAoKTm93IHdlIGFkZCBhIGNvbHVtbiBmb3IgdGhlIDElVmFSIHVzaW5nIHRoZXNlIGhpc3RvcmljYWwgR0FSQ0ggdm9sYXRpbGl0aWVzLiBJIHdpbGwgdXNlIHRoZSB0LVN0dWRlbnQgZGlzdHJpYnV0aW9uIGFzc3VtaW5nIGZhdC10YWlscyAoIEkgd2lsbCB1c2UgdGhlIHQxIEkgZXN0aW1hdGVkIGFib3ZlKToKCmBgYHtyfQpTUHJldHVybiRnVmFSID0gbWVhbnNwICsgdDEgKiBTUHJldHVybiRndm9sClNQcmV0dXJuJGdWYVIxbWlsbCA9IFNQcmV0dXJuJGdWYVIgKiAxMDAwMDAwCmBgYApOb3cgSSBwbG90IGRhaWx5IGhpc3RvcmljYWwgcmV0dXJucywgYW5kIGhpc3RvcmlhbCBHQVJDSCgxLDEpIGZpdHRlZCB2YWx1ZXMgZm9yIGRhaWx5IHZvbGF0aWxpdGllcyBhbmQgMSVWYWx1ZSBhdCBSaXNrOgpgYGB7cn0KcGxvdChTUHJldHVybiRnVmFSMW1pbGwpCmBgYApgYGB7cn0KcGxvdChTUHJldHVyblssYygyLDMpXSkKYGBgClRoZSBncmVlbiBsaW5lIGlzIHRoZSBHQVJDSCgxLDEpIDElIFZhbHVlIGF0IFJpc2s7IHRoZSByZWQgbGluZSBpcyB0aGUgR0FSQ0goMSwxKSBmaXR0ZWQgdm9sYXRpbGl0eSwgYW5kIHRoZSBibGFjayBsaW5lIGlzIHRoZSBkYWlseSByZXR1cm4gc2VyaWVzLgoKSSByZWNvbW1lbmQgeW91IHRvIHJlYWQgdGhlIGFydGljbGUgR0FSQ0ggMTAxOiBUaGUgdXNlIG9mIFtodHRwOi8vd3d3LmNtYXQuZWR1LnV5L35tb3JkZWNraS9oay9lbmdsZS5wZGZ8fEFSQ0gvR0FSQ0ggTW9kZWxzIGluIEFwcGxpZWQgRWNvbm9tZXRyaWNzXSB3cml0dGVuIGJ5IFJvYmVydCBFbmdsZSB0byBiZXR0ZXIgdW5kZXJzdGFuZCBob3cgeW91IGNhbiBhcHBseSBBUkNIIG1vZGVsIHRvIGZvcmVjYXN0IHZvbGF0aWxpdHkgYW5kIFZhUgoK