Introduction
Our eggs dataset from 1981 to 1996 shows the number of Coregonus hoyi of age-3 egg depositions made through the years (in millions). We will analyse this dataset to capture this trend and predict the outcome for the next five years.
Methodology
- To perform this analysis we have analysed the time series plot, ACF plot, PACF plot.
- Applied transformation and done differencing to the data due to non-stationarity.
- Parameter estimation after selecting the possible models from ACF, PACF, EACF, BIC.
- Filtering the models further based on AIC and BIC score.
- Diagnostic checks on 2 models selected ARIMA(0,4,2) and ARIMA(1,4,1)
- Forecasting on ARIMA model(1,4,1) for the next five years
Setup
library(TSA)
library(dplyr)
library(readr)
library(analytics)
library(ggplot2)
library(tidyr)
library(ggfortify)
library(tidyverse)
library(broom)
library(magrittr)
library(fUnitRoots)
library(lmtest)
library(FitAR)
library(tseries)
library(forecast)
library(knitr)
Time series plot
plot(eggs_ts,ylab='Egg depositions',xlab='Year',type='o', main = "Time series plot of egg depositions (in millions)")

- Trend: there is an increasing change in the mean level
- Changing variance: There is not much of larger and smaller variation noted from the plot
- Seasonality: There are no obvious repeating patterns
- Autocorrelation structure:There are consecutive data points and some fluctuations, the behaviour of the series seems like autoregressive.
- Intervention:there is no change-point event or a sudden rise or drop in the data-points
Scatter plot of egg depositions
plot(y=eggs_ts,x=zlag(eggs_ts),ylab='Egg depositions', xlab='Previous year Egg depositions',main = "Scatter plot of Egg depositions")

- In the above scatter plot we cannot see a trend. There is no autocorrelation in its first lag of the series
ACF plot
eggs_acf <- acf(eggs_ts,plot = FALSE)
plot(eggs_acf, main = "Egg deposition Time Series ACF")

- One significant lag starting high and slowly decaying pattern, there is just one significant lag this could be because the series is small. This series is non-stationary.
PACF plot
eggs_pacf <- pacf(eggs_ts,plot = FALSE)
plot(eggs_pacf, main = "Egg deposition Time Series PACF")

- Slowly decayin pattern in ACF and very high first correlation in PACF implies the existence of trend and nonstationarity. There is no trend or any pattern observed in the PACF plot. Hence, i am assuming non-stationarity.
Differencing
- We are proceeding with differencing as the series is non-stationary.
1st differencing
diff.BC.eggs_ts = diff(BC.eggs_ts,differences=1)
plot(diff.BC.eggs_ts,type='o',ylab='Egg depositions', main='1st differencing of Egg depositions')

ADF test on 1st differencing
order = ar(diff(diff.BC.eggs_ts))$order
adfTest(diff.BC.eggs_ts, lags = order, title = NULL,description = NULL)
Title:
Augmented Dickey-Fuller Test
Test Results:
PARAMETER:
Lag Order: 4
STATISTIC:
Dickey-Fuller: -0.8222
P VALUE:
0.3469
Description:
Mon Aug 05 22:45:47 2019 by user: Mohammed
- Since the p-value is 0.3469, there is 34.69% that my process is non stationary“. Therefore, we cannot reject H0 at, 1% and therefore we conclude that the process is non stationary.
2nd differencing
diff2.BC.eggs_ts = diff(BC.eggs_ts,differences=2)
plot(diff2.BC.eggs_ts,type='o',ylab='Egg depositions',main='2nd differencing of Egg depositions')

ADF test on 2nd differencing
order = ar(diff(diff2.BC.eggs_ts))$order
adfTest(diff2.BC.eggs_ts, lags = order, title = NULL,description = NULL)
Title:
Augmented Dickey-Fuller Test
Test Results:
PARAMETER:
Lag Order: 4
STATISTIC:
Dickey-Fuller: -1.5692
P VALUE:
0.1098
Description:
Mon Aug 05 22:45:47 2019 by user: Mohammed
- The p-value 0.1098 is greater than the chosen alpha level 1%. Hence we can say that the series is still non-stationary.
3rd differencing
diff3.BC.eggs_ts = diff(BC.eggs_ts,differences=3)
plot(diff3.BC.eggs_ts,type='o',ylab='Egg depositions',main='3rd differencing of Egg depositions')

- The series still has seasonality and trend, we will check this with ADF test if series is stationary.
ADF test on 3rd differencing
order = ar(diff(diff3.BC.eggs_ts))$order # To pass the order to adfTest function
adfTest(diff3.BC.eggs_ts, lags = order, title = NULL,description = NULL)
Title:
Augmented Dickey-Fuller Test
Test Results:
PARAMETER:
Lag Order: 4
STATISTIC:
Dickey-Fuller: -1.3368
P VALUE:
0.1836
Description:
Mon Aug 05 22:45:47 2019 by user: Mohammed
- The p-value 0.1836 is greater than the chosen alpha level 1%. Hence we can say that the series is still non-stationary.
4th differencing
diff4.BC.eggs_ts = diff(BC.eggs_ts,differences=4)
plot(diff4.BC.eggs_ts,type='o',ylab='Egg depositions',main='4th differencing of Egg depositions')

- There seems to be no trend or seasonality existing, we can further verify this by ADF test for stationarity.
ADF test on 4th differencing
order = ar(diff(diff4.BC.eggs_ts))$order
adfTest(diff4.BC.eggs_ts, lags = order, title = NULL,description = NULL)
Title:
Augmented Dickey-Fuller Test
Test Results:
PARAMETER:
Lag Order: 2
STATISTIC:
Dickey-Fuller: -2.3228
P VALUE:
0.02265
Description:
Mon Aug 05 22:45:47 2019 by user: Mohammed
- We are rejecting the null hypothesis since our p-value is less than 0.1. We can conclude that the series is stationary after 4th differencing.
plot(diff4.BC.eggs_ts,ylab='Egg depositions',xlab='Year',type='o', main = "Time series plot of egg depositions after 4th differencing (in millions)")

- Trend: Trend in this series is not so obvious.
- Changing variance:There could be variation between the year 1988 and 1990 against larger variations through the series.
- Seasonality:There are no obvious repeating patterns
- Autocorrelation structure:There are very few consecutive data points and more fluctuations in the series hence it could be moving average behaviour.
- Intervention:there is no change-point event or a sudden rise or drop in the data-points
ACF plot of 4th differencing
eggs4thdiff_acf <- acf(diff4.BC.eggs_ts,plot = FALSE)
plot(eggs4thdiff_acf, main = "4th differencing of Egg deposition Time Series ACF plot")

- We can observe some trend and seasonality from the plot and there is one significant lag in ACF.
PACF plot of 4th differencing
eggs4thdiff_pacf <- pacf(diff4.BC.eggs_ts,plot = FALSE)
plot(eggs4thdiff_pacf, main = "4th differencing of Egg deposition Time Series PACF plot")

- There is one significant lag and kind of a decreasing trend observed in PACF. We can consider the model {ARIMA(1,4,1)} from ACF and PACF plot.
EACF plot of 4th differencing
eacf(diff4.BC.eggs_ts,ar.max = 2, ma.max = 2)
AR/MA
0 1 2
0 x o o
1 o o o
2 o o o
- I have considered ar.max and ma.max as “2” because projection matrix results are shown invalid if the values are increased.
- Candidate models from EACF plot are {ARIMA(0,4,1), ARIMA(0,4,2), ARIMA(1,4,1), ARIMA(1,4,2)}
BIC table of 4th differencing
BIC_eggs.ols = armasubsets(y=diff4.BC.eggs_ts,nar=4,nma=4,y.name='test',ar.method='ols')
model order: 6 singularities in the computation of the projection matrix results are only valid up to model order 55 linear dependencies foundnvmax reduced to 3
plot(BIC_eggs.ols,main="BIC table of 4th differencing")
NaNs producedNaNs producedNaNs produced

- From the BIC table we can consider the models {ARIMA(0,4,2), ARIMA(0,4,4)}
- I’m not including ARIMA(0,4,4) considering the length of the series
- The final set of possible models are {ARIMA(0,4,1), ARIMA(0,4,2), ARIMA(1,4,1), ARIMA(1,4,2)}
Parameter estimation
- We will be doing parameter estimation using two methods to see the consistency i.e. CSS (conditional sum of squares) and ML (maximum likelihood).
ARIMA(0,4,1) - CSS
model_041_css = arima(diff4.BC.eggs_ts,order=c(0,4,1),method='CSS')
coeftest(model_041_css)
z test of coefficients:
Estimate Std. Error z value Pr(>|z|)
ma1 -0.71507 0.19460 -3.6746 0.0002382 ***
---
Signif. codes: 0 *** 0.001 ** 0.01 * 0.05 . 0.1 1
ARIMA(0,4,1) - ML
model_041_ml = arima(diff4.BC.eggs_ts,order=c(0,4,1),method='ML')
coeftest(model_041_ml)
z test of coefficients:
Estimate Std. Error z value Pr(>|z|)
ma1 -0.93603 0.34371 -2.7233 0.006463 **
---
Signif. codes: 0 *** 0.001 ** 0.01 * 0.05 . 0.1 1
- Both conditional sum of squares and maximum likelihood methods show us that this model is significant
ARIMA(0,4,2) - CSS
model_042_css = arima(diff4.BC.eggs_ts,order=c(0,4,2),method='CSS')
coeftest(model_042_css)
z test of coefficients:
Estimate Std. Error z value Pr(>|z|)
ma1 -0.96402 0.32660 -2.9517 0.00316 **
ma2 0.44644 0.26991 1.6540 0.09812 .
---
Signif. codes: 0 *** 0.001 ** 0.01 * 0.05 . 0.1 1
- only MA(1) is significant using conditional sum of squares method
ARIMA(0,4,2) - ML
model_042_ml = arima(diff4.BC.eggs_ts,order=c(0,4,2),method='ML')
coeftest(model_042_ml)
z test of coefficients:
Estimate Std. Error z value Pr(>|z|)
ma1 -1.70750 0.41520 -4.1124 3.915e-05 ***
ma2 0.90912 0.39415 2.3066 0.02108 *
---
Signif. codes: 0 *** 0.001 ** 0.01 * 0.05 . 0.1 1
- using the maximum likelihood method, both MA(1) and MA(2) are significant.
ARIMA(1,4,1) - CSS
model_141_css = arima(diff4.BC.eggs_ts,order=c(1,4,1),method='CSS')
possible convergence problem: optim gave code = 1
coeftest(model_141_css)
z test of coefficients:
Estimate Std. Error z value Pr(>|z|)
ar1 -0.728797 0.001113 -654.812 < 2.2e-16 ***
ma1 -2.570176 0.044918 -57.219 < 2.2e-16 ***
---
Signif. codes: 0 *** 0.001 ** 0.01 * 0.05 . 0.1 1
- using the conditional sum of squares method, AR(1) and MA(1) is significant
ARIMA(1,4,1) - ML
model_141_ml = arima(diff4.BC.eggs_ts,order=c(1,4,1),method='ML')
coeftest(model_141_ml)
z test of coefficients:
Estimate Std. Error z value Pr(>|z|)
ar1 -0.935358 0.089804 -10.4156 < 2.2e-16 ***
ma1 -0.937656 0.342549 -2.7373 0.006195 **
---
Signif. codes: 0 *** 0.001 ** 0.01 * 0.05 . 0.1 1
- using the maximum likelihood method, AR(1) and MA(1) is significant
ARIMA(1,4,2) - CSS
model_142_css = arima(diff4.BC.eggs_ts,order=c(1,4,2),method='CSS')
possible convergence problem: optim gave code = 1
coeftest(model_142_css)
z test of coefficients:
Estimate Std. Error z value Pr(>|z|)
ar1 -0.7353679 0.0012092 -608.1692 < 2.2e-16 ***
ma1 -2.9788233 0.4007513 -7.4331 1.061e-13 ***
ma2 1.6470485 0.8974066 1.8353 0.06645 .
---
Signif. codes: 0 *** 0.001 ** 0.01 * 0.05 . 0.1 1
- MA(2) is insignificant using conditional sum of squares method and AR(1), MA(1) is significant
ARIMA(1,4,2) - ML
model_142_ml = arima(diff4.BC.eggs_ts,order=c(1,4,2),method='ML')
coeftest(model_142_ml)
z test of coefficients:
Estimate Std. Error z value Pr(>|z|)
ar1 -0.90516 0.11712 -7.7288 1.086e-14 ***
ma1 -1.64557 0.50634 -3.2499 0.001154 **
ma2 0.82574 0.48150 1.7149 0.086356 .
---
Signif. codes: 0 *** 0.001 ** 0.01 * 0.05 . 0.1 1
- Again, both AR(1), MA(1) are significant using maximum likelihood method and MA(2) is insignificant
- The models with all coefficients significant are {ARIMA(0,4,1), ARIMA(0,4,2), ARIMA(1,4,1)} and ARIMA(1,4,2) was shown insignificant using CSS and ML method.
Sort score function for AIC and BIC score
sort.score <- function(x, score = c("bic", "aic")){
if (score == "aic"){
x[with(x, order(AIC)),]
} else if (score == "bic") {
x[with(x, order(BIC)),]
} else {
warning('score = "x" only accepts valid arguments ("aic","bic")')
}
}
AIC and BIC score
sort.score(AIC(model_041_ml,model_042_ml,model_141_ml), score = "aic")
sort.score(BIC(model_041_ml,model_042_ml,model_141_ml), score = "bic" )
- The order of scoring in both AIC, BIC is the same. model_141_ml has the lowest AIC and BIC score which is better. I am also considering model_042_ml as it has the second lowest AIC & BIC score.
Residual analysis function
residual.analysis <- function(model, std = TRUE,start = 2){
library(TSA)
library(FitAR)
if (std == TRUE){
res.model = rstandard(model)
}else{
res.model = residuals(model)
}
par(mfrow=c(3,2))
plot(res.model,type='o',ylab='Standardised residuals', main="Time series plot of standardised residuals")
abline(h=0)
hist(res.model,main="Histogram of standardised residuals")
acf(res.model,main="ACF of standardised residuals")
pacf(res.model,main="PACF of standardised residuals")
qqnorm(res.model,main="QQ plot of standardised residuals")
qqline(res.model, col = 2)
print(shapiro.test(res.model))
k=0
LBQPlot(res.model, lag.max = length(model$residuals)-1, StartLag = k + 1, k = 0, SquaredQ = FALSE)
par(mfrow=c(1,1))
}
Diagnostic checks
- Performing diagnostic checks for both the models model_042_ml and model_141_ml
Diagnostic check for model_042_ml
residual.analysis(model = model_042_ml)
Shapiro-Wilk normality test
data: res.model
W = 0.94842, p-value = 0.614

- Time series plot: There are at least three or four residuals mid-ending of the series with magnitudes larger than 1 and -1 which is unusual in a standard normal distribution. Ideally, we should go back to those years and try to learn what outside factors may have influenced unusually large drops or unusually large increases in the egg depositions.
- Histogram: The histogram is slightly left skewed which doesn’t seem normally distributed.
- ACF plot: There is one slightly significant lag. We conclude that the graph shows statistically significant evidence of nonzero autocorrelation in the residuals.
- PACF plot: There is one slightly significant lag which shouldn’t be the case, we will confirm this in Ljung-box test
- QQ plot: Very few data-points are falling on the qqline and the data-points at the beginning and end of the line are tailing off.
- Ljung-box test: The estimated ARIMA(0,4,2) model doesn’t seem to be capturing the dependence structure of the egg depositions time series quite well. There is one data-point below the 0.05 significance level.
- Shapiro-Wilk test: The p-value is greater than our chosen alpha level of 0.05, hence we are not able to reject the null hypothesis that the data is normally distributed. This could be because we just have 16 datapoints in our dataset.
Diagnostic check for model_141_ml
residual.analysis(model = model_141_ml)
Shapiro-Wilk normality test
data: res.model
W = 0.95083, p-value = 0.6492

- Time series plot: There are at least two or three residuals towards the end of the series with magnitudes larger than 1 and -1. Ideally, we should go back to those years and try to learn what outside factors may have influenced unusually large drops or unusually large increases in the egg depositions.
- Histogram: The histogram is slightly left skewed which doesn’t seem normally distributed.
- ACF plot: There is no trend nor any significant lags in the plot. We conclude that the graph does not show statistically significant evidence of nonzero autocorrelation in the residuals.
- PACF plot: There is no trend nor any significant lags in the plot. There could just be white-noise.
- QQ plot: Most of the data-points are falling on the qqline and there is just one residual which is tailed off in the beginning.
- Ljung-box test: The estimated ARIMA(1,4,1) model seems to be capturing the dependence structure of the egg depositions time series quite well.
- Shapiro-Wilk test: The p-value is greater than our chosen alpha level of 0.05, hence we are accepting the null hypothesis that the data is normally distributed.
- There is no problem in the residuals of ARIMA(1,4,1) model.
Forecasting
- Since there is no problem in the residuals of ARIMA(1,4,1) model, i am considering this as my final model for forecasting. The lambda value is mentioned in the below function considering box-cox transformation applied.
model141fit=Arima(eggs_ts,c(1,4,1),lambda=.45)
plot(forecast(model141fit,h=5),ylim=c(3,-1),xlab='Year',ylab='Egg depositions (in millions)',main='Forecasting of Egg depositions for the next five years')

Conclusion
- Based on the ACF, PACF, EACF, BIC table and diagnostic checks, we have considered ARIMA model (1,4,1). Even, model ARIMA(0,4,2) could have been used for forecasting as apart from few diagnostic checkpoints it was a really good model. However, there seems to be an increasing trend in the egg depositions based on our forecasting of ARIMA model (1,4,1) for the next 5 years (1997-2001).
LS0tDQp0aXRsZTogIk1BVEgxMzE4IFNlbWVzdGVyIDEsIDIwMTkiDQphdXRob3I6ICJNVUpFRVIgTU9IQU1NRUQgUzM3NDA1ODciDQpzdWJ0aXRsZTogQXNzaWdubWVudCAyDQpvdXRwdXQ6DQogIGh0bWxfbm90ZWJvb2s6IGRlZmF1bHQNCiAgcGRmX2RvY3VtZW50OiBkZWZhdWx0DQogIGh0bWxfZG9jdW1lbnQ6DQogICAgZmlnX3dpZHRoOiA2DQogICAgZmlnX2hlaWdodDogNA0KICAgIGRmX3ByaW50OiBwYWdlZA0KLS0tDQoNCiMjSW50cm9kdWN0aW9uDQpPdXIgZWdncyBkYXRhc2V0IGZyb20gMTk4MSB0byAxOTk2IHNob3dzIHRoZSBudW1iZXIgb2YgQ29yZWdvbnVzIGhveWkgb2YgYWdlLTMgZWdnIGRlcG9zaXRpb25zIG1hZGUgdGhyb3VnaCB0aGUgeWVhcnMgKGluIG1pbGxpb25zKS4gV2Ugd2lsbCBhbmFseXNlIHRoaXMgZGF0YXNldCB0byBjYXB0dXJlIHRoaXMgdHJlbmQgYW5kIHByZWRpY3QgdGhlIG91dGNvbWUgZm9yIHRoZSBuZXh0IGZpdmUgeWVhcnMuDQoNCiMjTWV0aG9kb2xvZ3kNCiogVG8gcGVyZm9ybSB0aGlzIGFuYWx5c2lzIHdlIGhhdmUgYW5hbHlzZWQgdGhlIHRpbWUgc2VyaWVzIHBsb3QsIEFDRiBwbG90LCBQQUNGIHBsb3QuIA0KKiBBcHBsaWVkIHRyYW5zZm9ybWF0aW9uIGFuZCBkb25lIGRpZmZlcmVuY2luZyB0byB0aGUgZGF0YSBkdWUgdG8gbm9uLXN0YXRpb25hcml0eS4NCiogUGFyYW1ldGVyIGVzdGltYXRpb24gYWZ0ZXIgc2VsZWN0aW5nIHRoZSBwb3NzaWJsZSBtb2RlbHMgZnJvbSBBQ0YsIFBBQ0YsIEVBQ0YsIEJJQy4NCiogRmlsdGVyaW5nIHRoZSBtb2RlbHMgZnVydGhlciBiYXNlZCBvbiBBSUMgYW5kIEJJQyBzY29yZS4NCiogRGlhZ25vc3RpYyBjaGVja3Mgb24gMiBtb2RlbHMgc2VsZWN0ZWQgQVJJTUEoMCw0LDIpIGFuZCBBUklNQSgxLDQsMSkNCiogRm9yZWNhc3Rpbmcgb24gQVJJTUEgbW9kZWwoMSw0LDEpIGZvciB0aGUgbmV4dCBmaXZlIHllYXJzDQoNCiMjIFNldHVwDQoNCmBgYHtyLCBlY2hvID0gVFJVRSwgd2FybmluZ3MgPSBGQUxTRX0NCg0KbGlicmFyeShUU0EpDQpsaWJyYXJ5KGRwbHlyKQ0KbGlicmFyeShyZWFkcikNCmxpYnJhcnkoYW5hbHl0aWNzKQ0KbGlicmFyeShnZ3Bsb3QyKQ0KbGlicmFyeSh0aWR5cikNCmxpYnJhcnkoZ2dmb3J0aWZ5KQ0KbGlicmFyeSh0aWR5dmVyc2UpDQpsaWJyYXJ5KGJyb29tKQ0KbGlicmFyeShtYWdyaXR0cikNCmxpYnJhcnkoZlVuaXRSb290cykNCmxpYnJhcnkobG10ZXN0KQ0KbGlicmFyeShGaXRBUikNCmxpYnJhcnkodHNlcmllcykNCmxpYnJhcnkoZm9yZWNhc3QpDQpsaWJyYXJ5KGtuaXRyKQ0KDQpgYGANCg0KIyNJbXBvcnRpbmcgYW5kIGNvbnZlcnRpbmcgZGF0YXNldCB0byAidHMiIGZvcm1hdA0KYGBge3J9DQplZ2dzIDwtIHJlYWQuY3N2KCJDOi9Vc2Vycy9Nb2hhbW1lZC9Eb2N1bWVudHMvZWdncy5jc3YiLCBoZWFkZXI9VFJVRSkNCnZpZXcoZWdncykNCmNsYXNzKGVnZ3MpDQplZ2dzX3RzIDwtIHRzKGVnZ3MkZWdncywgc3RhcnQgPSAxOTgxLCBlbmQgPSAxOTk2KQ0KY2xhc3MoZWdnc190cykNCg0KYGBgDQpgYGB7cn0NCg0KaGlzdChlZ2dzJGVnZ3MseGxhYiA9ICJFZ2cgZGVwb3NpdGlvbiIsbWFpbiA9ICJIaXN0b2dyYW0gb2YgRWdnIGRlcG9zaXRpb24iKQ0KDQpgYGANCiogVGhlIGRpc3RyaWJ1dGlvbiBpcyByaWdodCBza2V3ZWQgYXMgZWdnIGRlcG9zaXRpb24gY2Fubm90IGJlIG5lZ2F0aXZlDQoNCiMjVGltZSBzZXJpZXMgcGxvdA0KYGBge3J9DQpwbG90KGVnZ3NfdHMseWxhYj0nRWdnIGRlcG9zaXRpb25zJyx4bGFiPSdZZWFyJyx0eXBlPSdvJywgbWFpbiA9ICJUaW1lIHNlcmllcyBwbG90IG9mIGVnZyBkZXBvc2l0aW9ucyAoaW4gbWlsbGlvbnMpIikNCg0KYGBgDQoNCiogVHJlbmQ6IHRoZXJlIGlzIGFuIGluY3JlYXNpbmcgY2hhbmdlIGluIHRoZSBtZWFuIGxldmVsDQoqIENoYW5naW5nIHZhcmlhbmNlOiBUaGVyZSBpcyBub3QgbXVjaCBvZiBsYXJnZXIgYW5kIHNtYWxsZXIgdmFyaWF0aW9uIG5vdGVkIGZyb20gdGhlIHBsb3QNCiogU2Vhc29uYWxpdHk6IFRoZXJlIGFyZSBubyBvYnZpb3VzIHJlcGVhdGluZyBwYXR0ZXJucw0KKiBBdXRvY29ycmVsYXRpb24gc3RydWN0dXJlOlRoZXJlIGFyZSBjb25zZWN1dGl2ZSBkYXRhIHBvaW50cyBhbmQgc29tZSBmbHVjdHVhdGlvbnMsIHRoZSBiZWhhdmlvdXIgb2YgdGhlIHNlcmllcyBzZWVtcyBsaWtlIGF1dG9yZWdyZXNzaXZlLiAgDQoqIEludGVydmVudGlvbjp0aGVyZSBpcyBubyBjaGFuZ2UtcG9pbnQgZXZlbnQgb3IgYSBzdWRkZW4gcmlzZSBvciBkcm9wIGluIHRoZSBkYXRhLXBvaW50cw0KDQoNCiMjI1NjYXR0ZXIgcGxvdCBvZiBlZ2cgZGVwb3NpdGlvbnMNCmBgYHtyfQ0KDQpwbG90KHk9ZWdnc190cyx4PXpsYWcoZWdnc190cykseWxhYj0nRWdnIGRlcG9zaXRpb25zJywgeGxhYj0nUHJldmlvdXMgeWVhciBFZ2cgZGVwb3NpdGlvbnMnLG1haW4gPSAiU2NhdHRlciBwbG90IG9mIEVnZyBkZXBvc2l0aW9ucyIpDQoNCmBgYA0KKiBJbiB0aGUgYWJvdmUgc2NhdHRlciBwbG90IHdlIGNhbm5vdCBzZWUgYSB0cmVuZC4gVGhlcmUgaXMgbm8gYXV0b2NvcnJlbGF0aW9uIGluIGl0cyBmaXJzdCBsYWcgb2YgdGhlIHNlcmllcw0KDQojIyNBQ0YgcGxvdA0KYGBge3J9DQplZ2dzX2FjZiA8LSBhY2YoZWdnc190cyxwbG90ID0gRkFMU0UpDQpwbG90KGVnZ3NfYWNmLCBtYWluID0gIkVnZyBkZXBvc2l0aW9uIFRpbWUgU2VyaWVzIEFDRiIpDQpgYGANCiogT25lIHNpZ25pZmljYW50IGxhZyBzdGFydGluZyBoaWdoIGFuZCBzbG93bHkgZGVjYXlpbmcgcGF0dGVybiwgdGhlcmUgaXMganVzdCBvbmUgc2lnbmlmaWNhbnQgbGFnIHRoaXMgY291bGQgYmUgYmVjYXVzZSB0aGUgc2VyaWVzIGlzIHNtYWxsLiBUaGlzIHNlcmllcyBpcyBub24tc3RhdGlvbmFyeS4NCg0KIyMjUEFDRiBwbG90DQpgYGB7cn0NCmVnZ3NfcGFjZiA8LSBwYWNmKGVnZ3NfdHMscGxvdCA9IEZBTFNFKQ0KcGxvdChlZ2dzX3BhY2YsIG1haW4gPSAiRWdnIGRlcG9zaXRpb24gVGltZSBTZXJpZXMgUEFDRiIpDQoNCmBgYA0KKiBTbG93bHkgZGVjYXlpbiBwYXR0ZXJuIGluIEFDRiBhbmQgdmVyeSBoaWdoIGZpcnN0IGNvcnJlbGF0aW9uIGluIFBBQ0YgaW1wbGllcyB0aGUgZXhpc3RlbmNlIG9mIHRyZW5kIGFuZCBub25zdGF0aW9uYXJpdHkuIFRoZXJlIGlzIG5vIHRyZW5kIG9yIGFueSBwYXR0ZXJuIG9ic2VydmVkIGluIHRoZSBQQUNGIHBsb3QuIEhlbmNlLCBpIGFtIGFzc3VtaW5nIG5vbi1zdGF0aW9uYXJpdHkuDQoNCiMjQXBwbHlpbmcgdHJhbnNmb3JtYXRpb24NCmBgYHtyfQ0KZWdnc190cy50cmFuc2Zvcm0gPSBCb3hDb3guYXIoZWdnc190cywgbWV0aG9kID0gInl1bGUtd2Fsa2VyIikNCmVnZ3NfdHMudHJhbnNmb3JtJGNpDQpsYW1iZGEgPSAwLjQ1DQpCQy5lZ2dzX3RzID0gKGVnZ3NfdHNebGFtYmRhLTEpL2xhbWJkYQ0KDQpgYGANCiogQXBwbGllZCBib3gtY294IHRyYW5zZm9ybWF0aW9uIGFuZCBnb3QgdGhlIGxhbWJkYSB2YWx1ZSBmcm9tIGNvbmZpZGVuY2UgaW50ZXJ2YWwgKDAuMSAwLjgpIGFzIDAuNDUNCg0KIyNEaWZmZXJlbmNpbmcNCiogV2UgYXJlIHByb2NlZWRpbmcgd2l0aCBkaWZmZXJlbmNpbmcgYXMgdGhlIHNlcmllcyBpcyBub24tc3RhdGlvbmFyeS4NCg0KIyMjMXN0IGRpZmZlcmVuY2luZw0KYGBge3J9DQoNCmRpZmYuQkMuZWdnc190cyA9IGRpZmYoQkMuZWdnc190cyxkaWZmZXJlbmNlcz0xKQ0KcGxvdChkaWZmLkJDLmVnZ3NfdHMsdHlwZT0nbycseWxhYj0nRWdnIGRlcG9zaXRpb25zJywgbWFpbj0nMXN0IGRpZmZlcmVuY2luZyBvZiBFZ2cgZGVwb3NpdGlvbnMnKQ0KDQoNCmBgYCAgIA0KDQojIyNBREYgdGVzdCBvbiAxc3QgZGlmZmVyZW5jaW5nDQpgYGB7cn0NCg0Kb3JkZXIgID0gYXIoZGlmZihkaWZmLkJDLmVnZ3NfdHMpKSRvcmRlcg0KYWRmVGVzdChkaWZmLkJDLmVnZ3NfdHMsIGxhZ3MgPSBvcmRlciwgIHRpdGxlID0gTlVMTCxkZXNjcmlwdGlvbiA9IE5VTEwpDQoNCg0KYGBgICAgDQoqIFNpbmNlIHRoZSBwLXZhbHVlIGlzIDAuMzQ2OSwgdGhlcmUgaXMgMzQuNjklIHRoYXQgbXkgcHJvY2VzcyBpcyBub24gc3RhdGlvbmFyeSIuIFRoZXJlZm9yZSwgd2UgY2Fubm90IHJlamVjdCBIMCBhdCwgMSUgYW5kIHRoZXJlZm9yZSB3ZSBjb25jbHVkZSB0aGF0IHRoZSBwcm9jZXNzIGlzIG5vbiBzdGF0aW9uYXJ5Lg0KDQoNCiMjIzJuZCBkaWZmZXJlbmNpbmcNCmBgYHtyfQ0KZGlmZjIuQkMuZWdnc190cyA9IGRpZmYoQkMuZWdnc190cyxkaWZmZXJlbmNlcz0yKQ0KcGxvdChkaWZmMi5CQy5lZ2dzX3RzLHR5cGU9J28nLHlsYWI9J0VnZyBkZXBvc2l0aW9ucycsbWFpbj0nMm5kIGRpZmZlcmVuY2luZyBvZiBFZ2cgZGVwb3NpdGlvbnMnKQ0KYGBgDQoNCg0KIyMjQURGIHRlc3Qgb24gMm5kIGRpZmZlcmVuY2luZw0KYGBge3J9DQoNCm9yZGVyICA9IGFyKGRpZmYoZGlmZjIuQkMuZWdnc190cykpJG9yZGVyDQphZGZUZXN0KGRpZmYyLkJDLmVnZ3NfdHMsIGxhZ3MgPSBvcmRlciwgIHRpdGxlID0gTlVMTCxkZXNjcmlwdGlvbiA9IE5VTEwpDQoNCmBgYA0KKiBUaGUgcC12YWx1ZSAwLjEwOTggaXMgZ3JlYXRlciB0aGFuIHRoZSBjaG9zZW4gYWxwaGEgbGV2ZWwgMSUuIEhlbmNlIHdlIGNhbiBzYXkgdGhhdCB0aGUgc2VyaWVzIGlzIHN0aWxsIG5vbi1zdGF0aW9uYXJ5Lg0KDQoNCiMjIzNyZCBkaWZmZXJlbmNpbmcNCmBgYHtyfQ0KZGlmZjMuQkMuZWdnc190cyA9IGRpZmYoQkMuZWdnc190cyxkaWZmZXJlbmNlcz0zKQ0KcGxvdChkaWZmMy5CQy5lZ2dzX3RzLHR5cGU9J28nLHlsYWI9J0VnZyBkZXBvc2l0aW9ucycsbWFpbj0nM3JkIGRpZmZlcmVuY2luZyBvZiBFZ2cgZGVwb3NpdGlvbnMnKQ0KDQoNCmBgYA0KKiBUaGUgc2VyaWVzIHN0aWxsIGhhcyBzZWFzb25hbGl0eSBhbmQgdHJlbmQsIHdlIHdpbGwgY2hlY2sgdGhpcyB3aXRoIEFERiB0ZXN0IGlmIHNlcmllcyBpcyBzdGF0aW9uYXJ5Lg0KDQojIyNBREYgdGVzdCBvbiAzcmQgZGlmZmVyZW5jaW5nDQpgYGB7cn0NCm9yZGVyICA9IGFyKGRpZmYoZGlmZjMuQkMuZWdnc190cykpJG9yZGVyICMgVG8gcGFzcyB0aGUgb3JkZXIgdG8gYWRmVGVzdCBmdW5jdGlvbg0KYWRmVGVzdChkaWZmMy5CQy5lZ2dzX3RzLCBsYWdzID0gb3JkZXIsICB0aXRsZSA9IE5VTEwsZGVzY3JpcHRpb24gPSBOVUxMKQ0KDQoNCmBgYA0KDQoqIFRoZSBwLXZhbHVlIDAuMTgzNiBpcyBncmVhdGVyIHRoYW4gdGhlIGNob3NlbiBhbHBoYSBsZXZlbCAxJS4gSGVuY2Ugd2UgY2FuIHNheSB0aGF0IHRoZSBzZXJpZXMgaXMgc3RpbGwgbm9uLXN0YXRpb25hcnkuDQoNCiMjIzR0aCBkaWZmZXJlbmNpbmcNCmBgYHtyfQ0KDQpkaWZmNC5CQy5lZ2dzX3RzID0gZGlmZihCQy5lZ2dzX3RzLGRpZmZlcmVuY2VzPTQpDQpwbG90KGRpZmY0LkJDLmVnZ3NfdHMsdHlwZT0nbycseWxhYj0nRWdnIGRlcG9zaXRpb25zJyxtYWluPSc0dGggZGlmZmVyZW5jaW5nIG9mIEVnZyBkZXBvc2l0aW9ucycpDQoNCmBgYA0KKiBUaGVyZSBzZWVtcyB0byBiZSBubyB0cmVuZCBvciBzZWFzb25hbGl0eSBleGlzdGluZywgd2UgY2FuIGZ1cnRoZXIgdmVyaWZ5IHRoaXMgYnkgQURGIHRlc3QgZm9yIHN0YXRpb25hcml0eS4NCg0KIyMjQURGIHRlc3Qgb24gNHRoIGRpZmZlcmVuY2luZw0KYGBge3J9DQoNCm9yZGVyICA9IGFyKGRpZmYoZGlmZjQuQkMuZWdnc190cykpJG9yZGVyDQphZGZUZXN0KGRpZmY0LkJDLmVnZ3NfdHMsIGxhZ3MgPSBvcmRlciwgIHRpdGxlID0gTlVMTCxkZXNjcmlwdGlvbiA9IE5VTEwpDQoNCmBgYA0KKiBXZSBhcmUgcmVqZWN0aW5nIHRoZSBudWxsIGh5cG90aGVzaXMgc2luY2Ugb3VyIHAtdmFsdWUgaXMgbGVzcyB0aGFuIDAuMS4gV2UgY2FuIGNvbmNsdWRlIHRoYXQgdGhlIHNlcmllcyBpcyBzdGF0aW9uYXJ5IGFmdGVyIDR0aCBkaWZmZXJlbmNpbmcuDQoNCg0KYGBge3J9DQpwbG90KGRpZmY0LkJDLmVnZ3NfdHMseWxhYj0nRWdnIGRlcG9zaXRpb25zJyx4bGFiPSdZZWFyJyx0eXBlPSdvJywgbWFpbiA9ICJUaW1lIHNlcmllcyBwbG90IG9mIGVnZyBkZXBvc2l0aW9ucyBhZnRlciA0dGggZGlmZmVyZW5jaW5nIChpbiBtaWxsaW9ucykiKQ0KYGBgDQoqIFRyZW5kOiBUcmVuZCBpbiB0aGlzIHNlcmllcyBpcyBub3Qgc28gb2J2aW91cy4NCiogQ2hhbmdpbmcgdmFyaWFuY2U6VGhlcmUgY291bGQgYmUgdmFyaWF0aW9uIGJldHdlZW4gdGhlIHllYXIgMTk4OCBhbmQgMTk5MCBhZ2FpbnN0IGxhcmdlciB2YXJpYXRpb25zIHRocm91Z2ggdGhlIHNlcmllcy4NCiogU2Vhc29uYWxpdHk6VGhlcmUgYXJlIG5vIG9idmlvdXMgcmVwZWF0aW5nIHBhdHRlcm5zDQoqIEF1dG9jb3JyZWxhdGlvbiBzdHJ1Y3R1cmU6VGhlcmUgYXJlIHZlcnkgZmV3IGNvbnNlY3V0aXZlIGRhdGEgcG9pbnRzIGFuZCBtb3JlIGZsdWN0dWF0aW9ucyBpbiB0aGUgc2VyaWVzIGhlbmNlIGl0IGNvdWxkIGJlIG1vdmluZyBhdmVyYWdlIGJlaGF2aW91ci4gICANCiogSW50ZXJ2ZW50aW9uOnRoZXJlIGlzIG5vIGNoYW5nZS1wb2ludCBldmVudCBvciBhIHN1ZGRlbiByaXNlIG9yIGRyb3AgaW4gdGhlIGRhdGEtcG9pbnRzDQoNCiMjI0FDRiBwbG90IG9mIDR0aCBkaWZmZXJlbmNpbmcNCmBgYHtyfQ0KDQplZ2dzNHRoZGlmZl9hY2YgPC0gYWNmKGRpZmY0LkJDLmVnZ3NfdHMscGxvdCA9IEZBTFNFKQ0KcGxvdChlZ2dzNHRoZGlmZl9hY2YsIG1haW4gPSAiNHRoIGRpZmZlcmVuY2luZyBvZiBFZ2cgZGVwb3NpdGlvbiBUaW1lIFNlcmllcyBBQ0YgcGxvdCIpDQoNCmBgYA0KKiBXZSBjYW4gb2JzZXJ2ZSBzb21lIHRyZW5kIGFuZCBzZWFzb25hbGl0eSBmcm9tIHRoZSBwbG90IGFuZCB0aGVyZSBpcyBvbmUgc2lnbmlmaWNhbnQgbGFnIGluIEFDRi4NCg0KIyMjUEFDRiBwbG90IG9mIDR0aCBkaWZmZXJlbmNpbmcNCmBgYHtyfQ0KZWdnczR0aGRpZmZfcGFjZiA8LSBwYWNmKGRpZmY0LkJDLmVnZ3NfdHMscGxvdCA9IEZBTFNFKQ0KcGxvdChlZ2dzNHRoZGlmZl9wYWNmLCBtYWluID0gIjR0aCBkaWZmZXJlbmNpbmcgb2YgRWdnIGRlcG9zaXRpb24gVGltZSBTZXJpZXMgUEFDRiBwbG90IikNCmBgYA0KKiBUaGVyZSBpcyBvbmUgc2lnbmlmaWNhbnQgbGFnIGFuZCBraW5kIG9mIGEgZGVjcmVhc2luZyB0cmVuZCBvYnNlcnZlZCBpbiBQQUNGLiBXZSBjYW4gY29uc2lkZXIgdGhlIG1vZGVsIHtBUklNQSgxLDQsMSl9IGZyb20gQUNGIGFuZCBQQUNGIHBsb3QuDQoNCiMjI0VBQ0YgcGxvdCBvZiA0dGggZGlmZmVyZW5jaW5nDQpgYGB7cn0NCmVhY2YoZGlmZjQuQkMuZWdnc190cyxhci5tYXggPSAyLCBtYS5tYXggPSAyKQ0KYGBgDQoqIEkgaGF2ZSBjb25zaWRlcmVkIGFyLm1heCBhbmQgbWEubWF4IGFzICIyIiBiZWNhdXNlIHByb2plY3Rpb24gbWF0cml4IHJlc3VsdHMgYXJlIHNob3duIGludmFsaWQgaWYgdGhlIHZhbHVlcyBhcmUgaW5jcmVhc2VkLg0KKiBDYW5kaWRhdGUgbW9kZWxzIGZyb20gRUFDRiBwbG90IGFyZSB7QVJJTUEoMCw0LDEpLCBBUklNQSgwLDQsMiksIEFSSU1BKDEsNCwxKSwgQVJJTUEoMSw0LDIpfQ0KDQoNCiMjI0JJQyB0YWJsZSBvZiA0dGggZGlmZmVyZW5jaW5nDQpgYGB7cn0NCkJJQ19lZ2dzLm9scyA9IGFybWFzdWJzZXRzKHk9ZGlmZjQuQkMuZWdnc190cyxuYXI9NCxubWE9NCx5Lm5hbWU9J3Rlc3QnLGFyLm1ldGhvZD0nb2xzJykNCnBsb3QoQklDX2VnZ3Mub2xzLG1haW49IkJJQyB0YWJsZSBvZiA0dGggZGlmZmVyZW5jaW5nIikNCmBgYA0KKiBGcm9tIHRoZSBCSUMgdGFibGUgd2UgY2FuIGNvbnNpZGVyIHRoZSBtb2RlbHMge0FSSU1BKDAsNCwyKSwgQVJJTUEoMCw0LDQpfQ0KKiBJJ20gbm90IGluY2x1ZGluZyBBUklNQSgwLDQsNCkgY29uc2lkZXJpbmcgdGhlIGxlbmd0aCBvZiB0aGUgc2VyaWVzDQoqIFRoZSBmaW5hbCBzZXQgb2YgcG9zc2libGUgbW9kZWxzIGFyZSB7QVJJTUEoMCw0LDEpLCBBUklNQSgwLDQsMiksIEFSSU1BKDEsNCwxKSwgQVJJTUEoMSw0LDIpfQ0KDQoNCiMjUGFyYW1ldGVyIGVzdGltYXRpb24NCiogV2Ugd2lsbCBiZSBkb2luZyBwYXJhbWV0ZXIgZXN0aW1hdGlvbiB1c2luZyB0d28gbWV0aG9kcyB0byBzZWUgdGhlIGNvbnNpc3RlbmN5IGkuZS4gQ1NTIChjb25kaXRpb25hbCBzdW0gb2Ygc3F1YXJlcykgYW5kIE1MIChtYXhpbXVtIGxpa2VsaWhvb2QpLg0KDQojIyNBUklNQSgwLDQsMSkgLSBDU1MNCmBgYHtyfQ0KbW9kZWxfMDQxX2NzcyA9IGFyaW1hKGRpZmY0LkJDLmVnZ3NfdHMsb3JkZXI9YygwLDQsMSksbWV0aG9kPSdDU1MnKQ0KY29lZnRlc3QobW9kZWxfMDQxX2NzcykNCmBgYA0KDQojIyNBUklNQSgwLDQsMSkgLSBNTA0KYGBge3J9DQptb2RlbF8wNDFfbWwgPSBhcmltYShkaWZmNC5CQy5lZ2dzX3RzLG9yZGVyPWMoMCw0LDEpLG1ldGhvZD0nTUwnKQ0KY29lZnRlc3QobW9kZWxfMDQxX21sKQ0KYGBgDQoqIEJvdGggY29uZGl0aW9uYWwgc3VtIG9mIHNxdWFyZXMgYW5kIG1heGltdW0gbGlrZWxpaG9vZCBtZXRob2RzIHNob3cgdXMgdGhhdCB0aGlzIG1vZGVsIGlzIHNpZ25pZmljYW50DQoNCiMjIyBBUklNQSgwLDQsMikgLSBDU1MNCmBgYHtyfQ0KbW9kZWxfMDQyX2NzcyA9IGFyaW1hKGRpZmY0LkJDLmVnZ3NfdHMsb3JkZXI9YygwLDQsMiksbWV0aG9kPSdDU1MnKQ0KY29lZnRlc3QobW9kZWxfMDQyX2NzcykNCmBgYA0KKiBvbmx5IE1BKDEpIGlzIHNpZ25pZmljYW50IHVzaW5nIGNvbmRpdGlvbmFsIHN1bSBvZiBzcXVhcmVzIG1ldGhvZA0KDQojIyMgQVJJTUEoMCw0LDIpIC0gTUwNCmBgYHtyfQ0KbW9kZWxfMDQyX21sID0gYXJpbWEoZGlmZjQuQkMuZWdnc190cyxvcmRlcj1jKDAsNCwyKSxtZXRob2Q9J01MJykNCmNvZWZ0ZXN0KG1vZGVsXzA0Ml9tbCkNCmBgYA0KKiB1c2luZyB0aGUgbWF4aW11bSBsaWtlbGlob29kIG1ldGhvZCwgYm90aCBNQSgxKSBhbmQgTUEoMikgYXJlIHNpZ25pZmljYW50Lg0KDQojIyMgQVJJTUEoMSw0LDEpIC0gQ1NTDQpgYGB7cn0NCm1vZGVsXzE0MV9jc3MgPSBhcmltYShkaWZmNC5CQy5lZ2dzX3RzLG9yZGVyPWMoMSw0LDEpLG1ldGhvZD0nQ1NTJykNCmNvZWZ0ZXN0KG1vZGVsXzE0MV9jc3MpDQpgYGANCiogdXNpbmcgdGhlIGNvbmRpdGlvbmFsIHN1bSBvZiBzcXVhcmVzIG1ldGhvZCwgQVIoMSkgYW5kIE1BKDEpIGlzIHNpZ25pZmljYW50DQoNCiMjIyBBUklNQSgxLDQsMSkgLSBNTA0KYGBge3J9DQptb2RlbF8xNDFfbWwgPSBhcmltYShkaWZmNC5CQy5lZ2dzX3RzLG9yZGVyPWMoMSw0LDEpLG1ldGhvZD0nTUwnKQ0KY29lZnRlc3QobW9kZWxfMTQxX21sKQ0KYGBgDQoqIHVzaW5nIHRoZSBtYXhpbXVtIGxpa2VsaWhvb2QgbWV0aG9kLCBBUigxKSBhbmQgTUEoMSkgaXMgc2lnbmlmaWNhbnQNCg0KIyMjIEFSSU1BKDEsNCwyKSAtIENTUw0KYGBge3J9DQptb2RlbF8xNDJfY3NzID0gYXJpbWEoZGlmZjQuQkMuZWdnc190cyxvcmRlcj1jKDEsNCwyKSxtZXRob2Q9J0NTUycpDQpjb2VmdGVzdChtb2RlbF8xNDJfY3NzKQ0KYGBgDQoqIE1BKDIpIGlzIGluc2lnbmlmaWNhbnQgdXNpbmcgY29uZGl0aW9uYWwgc3VtIG9mIHNxdWFyZXMgbWV0aG9kIGFuZCBBUigxKSwgTUEoMSkgaXMgc2lnbmlmaWNhbnQNCg0KIyMjIEFSSU1BKDEsNCwyKSAtIE1MDQpgYGB7cn0NCm1vZGVsXzE0Ml9tbCA9IGFyaW1hKGRpZmY0LkJDLmVnZ3NfdHMsb3JkZXI9YygxLDQsMiksbWV0aG9kPSdNTCcpDQpjb2VmdGVzdChtb2RlbF8xNDJfbWwpDQpgYGANCiogQWdhaW4sIGJvdGggQVIoMSksIE1BKDEpIGFyZSBzaWduaWZpY2FudCB1c2luZyBtYXhpbXVtIGxpa2VsaWhvb2QgbWV0aG9kIGFuZCBNQSgyKSBpcyBpbnNpZ25pZmljYW50DQoqIFRoZSBtb2RlbHMgd2l0aCBhbGwgY29lZmZpY2llbnRzIHNpZ25pZmljYW50IGFyZSB7QVJJTUEoMCw0LDEpLCBBUklNQSgwLDQsMiksIEFSSU1BKDEsNCwxKX0gYW5kIEFSSU1BKDEsNCwyKSB3YXMgc2hvd24gaW5zaWduaWZpY2FudCB1c2luZyBDU1MgYW5kIE1MIG1ldGhvZC4NCg0KIyMjU29ydCBzY29yZSBmdW5jdGlvbiBmb3IgQUlDIGFuZCBCSUMgc2NvcmUNCmBgYHtyfQ0Kc29ydC5zY29yZSA8LSBmdW5jdGlvbih4LCBzY29yZSA9IGMoImJpYyIsICJhaWMiKSl7DQogIGlmIChzY29yZSA9PSAiYWljIil7DQogICAgeFt3aXRoKHgsIG9yZGVyKEFJQykpLF0NCiAgfSBlbHNlIGlmIChzY29yZSA9PSAiYmljIikgew0KICAgIHhbd2l0aCh4LCBvcmRlcihCSUMpKSxdDQogIH0gZWxzZSB7DQogICAgd2FybmluZygnc2NvcmUgPSAieCIgb25seSBhY2NlcHRzIHZhbGlkIGFyZ3VtZW50cyAoImFpYyIsImJpYyIpJykNCiAgfQ0KfQ0KYGBgDQoNCiMjQUlDIGFuZCBCSUMgc2NvcmUNCmBgYHtyfQ0Kc29ydC5zY29yZShBSUMobW9kZWxfMDQxX21sLG1vZGVsXzA0Ml9tbCxtb2RlbF8xNDFfbWwpLCBzY29yZSA9ICJhaWMiKQ0Kc29ydC5zY29yZShCSUMobW9kZWxfMDQxX21sLG1vZGVsXzA0Ml9tbCxtb2RlbF8xNDFfbWwpLCBzY29yZSA9ICJiaWMiICkNCmBgYA0KKiBUaGUgb3JkZXIgb2Ygc2NvcmluZyBpbiBib3RoIEFJQywgQklDIGlzIHRoZSBzYW1lLiBtb2RlbF8xNDFfbWwgaGFzIHRoZSBsb3dlc3QgQUlDIGFuZCBCSUMgc2NvcmUgd2hpY2ggaXMgYmV0dGVyLiBJIGFtIGFsc28gY29uc2lkZXJpbmcgbW9kZWxfMDQyX21sIGFzIGl0IGhhcyB0aGUgc2Vjb25kIGxvd2VzdCBBSUMgJiBCSUMgc2NvcmUuDQoNCiMjI1Jlc2lkdWFsIGFuYWx5c2lzIGZ1bmN0aW9uDQpgYGB7cn0NCnJlc2lkdWFsLmFuYWx5c2lzIDwtIGZ1bmN0aW9uKG1vZGVsLCBzdGQgPSBUUlVFLHN0YXJ0ID0gMil7DQogIGxpYnJhcnkoVFNBKQ0KICBsaWJyYXJ5KEZpdEFSKQ0KICAgIGlmIChzdGQgPT0gVFJVRSl7DQogICAgICByZXMubW9kZWwgPSByc3RhbmRhcmQobW9kZWwpDQogICAgfWVsc2V7DQogICAgICByZXMubW9kZWwgPSByZXNpZHVhbHMobW9kZWwpDQogICAgfQ0KICBwYXIobWZyb3c9YygzLDIpKQ0KICBwbG90KHJlcy5tb2RlbCx0eXBlPSdvJyx5bGFiPSdTdGFuZGFyZGlzZWQgcmVzaWR1YWxzJywgbWFpbj0iVGltZSBzZXJpZXMgcGxvdCBvZiBzdGFuZGFyZGlzZWQgcmVzaWR1YWxzIikNCiAgYWJsaW5lKGg9MCkNCiAgaGlzdChyZXMubW9kZWwsbWFpbj0iSGlzdG9ncmFtIG9mIHN0YW5kYXJkaXNlZCByZXNpZHVhbHMiKQ0KICBhY2YocmVzLm1vZGVsLG1haW49IkFDRiBvZiBzdGFuZGFyZGlzZWQgcmVzaWR1YWxzIikNCiAgcGFjZihyZXMubW9kZWwsbWFpbj0iUEFDRiBvZiBzdGFuZGFyZGlzZWQgcmVzaWR1YWxzIikNCiAgcXFub3JtKHJlcy5tb2RlbCxtYWluPSJRUSBwbG90IG9mIHN0YW5kYXJkaXNlZCByZXNpZHVhbHMiKQ0KICBxcWxpbmUocmVzLm1vZGVsLCBjb2wgPSAyKQ0KICBwcmludChzaGFwaXJvLnRlc3QocmVzLm1vZGVsKSkNCiAgaz0wDQogIExCUVBsb3QocmVzLm1vZGVsLCBsYWcubWF4ID0gbGVuZ3RoKG1vZGVsJHJlc2lkdWFscyktMSwgU3RhcnRMYWcgPSBrICsgMSwgayA9IDAsIFNxdWFyZWRRID0gRkFMU0UpDQogIHBhcihtZnJvdz1jKDEsMSkpDQp9DQoNCmBgYA0KDQojI0RpYWdub3N0aWMgY2hlY2tzDQoqIFBlcmZvcm1pbmcgZGlhZ25vc3RpYyBjaGVja3MgZm9yIGJvdGggdGhlIG1vZGVscyBtb2RlbF8wNDJfbWwgYW5kIG1vZGVsXzE0MV9tbA0KDQojIyNEaWFnbm9zdGljIGNoZWNrIGZvciBtb2RlbF8wNDJfbWwNCmBgYHtyfQ0KcmVzaWR1YWwuYW5hbHlzaXMobW9kZWwgPSBtb2RlbF8wNDJfbWwpDQpgYGANCiogVGltZSBzZXJpZXMgcGxvdDogVGhlcmUgYXJlIGF0IGxlYXN0IHRocmVlIG9yIGZvdXIgcmVzaWR1YWxzIG1pZC1lbmRpbmcgb2YgdGhlIHNlcmllcyB3aXRoIG1hZ25pdHVkZXMgbGFyZ2VyIHRoYW4gMSBhbmQgLTEgd2hpY2ggaXMgdW51c3VhbCBpbiBhIHN0YW5kYXJkIG5vcm1hbCBkaXN0cmlidXRpb24uIElkZWFsbHksIHdlIHNob3VsZCBnbyBiYWNrIHRvIHRob3NlIHllYXJzIGFuZCB0cnkgdG8gbGVhcm4gd2hhdCBvdXRzaWRlIGZhY3RvcnMgbWF5IGhhdmUgaW5mbHVlbmNlZCB1bnVzdWFsbHkgbGFyZ2UgZHJvcHMgb3IgdW51c3VhbGx5IGxhcmdlIGluY3JlYXNlcyBpbiB0aGUgZWdnIGRlcG9zaXRpb25zLg0KKiBIaXN0b2dyYW06IFRoZSBoaXN0b2dyYW0gaXMgc2xpZ2h0bHkgbGVmdCBza2V3ZWQgd2hpY2ggZG9lc24ndCBzZWVtIG5vcm1hbGx5IGRpc3RyaWJ1dGVkLg0KKiBBQ0YgcGxvdDogVGhlcmUgaXMgb25lIHNsaWdodGx5IHNpZ25pZmljYW50IGxhZy4gV2UgY29uY2x1ZGUgdGhhdCB0aGUgZ3JhcGggc2hvd3Mgc3RhdGlzdGljYWxseSBzaWduaWZpY2FudCBldmlkZW5jZSBvZiBub256ZXJvIGF1dG9jb3JyZWxhdGlvbiBpbiB0aGUgcmVzaWR1YWxzLg0KKiBQQUNGIHBsb3Q6IFRoZXJlIGlzIG9uZSBzbGlnaHRseSBzaWduaWZpY2FudCBsYWcgd2hpY2ggc2hvdWxkbid0IGJlIHRoZSBjYXNlLCB3ZSB3aWxsIGNvbmZpcm0gdGhpcyBpbiBManVuZy1ib3ggdGVzdA0KKiBRUSBwbG90OiBWZXJ5IGZldyBkYXRhLXBvaW50cyBhcmUgZmFsbGluZyBvbiB0aGUgcXFsaW5lIGFuZCB0aGUgZGF0YS1wb2ludHMgYXQgdGhlIGJlZ2lubmluZyBhbmQgZW5kIG9mIHRoZSBsaW5lIGFyZSB0YWlsaW5nIG9mZi4NCiogTGp1bmctYm94IHRlc3Q6IFRoZSBlc3RpbWF0ZWQgQVJJTUEoMCw0LDIpIG1vZGVsIGRvZXNuJ3Qgc2VlbSB0byBiZSBjYXB0dXJpbmcgdGhlIGRlcGVuZGVuY2Ugc3RydWN0dXJlIG9mIHRoZSBlZ2cgZGVwb3NpdGlvbnMgdGltZSBzZXJpZXMgcXVpdGUgd2VsbC4gVGhlcmUgaXMgb25lIGRhdGEtcG9pbnQgYmVsb3cgdGhlIDAuMDUgc2lnbmlmaWNhbmNlIGxldmVsLg0KKiBTaGFwaXJvLVdpbGsgdGVzdDogVGhlIHAtdmFsdWUgaXMgZ3JlYXRlciB0aGFuIG91ciBjaG9zZW4gYWxwaGEgbGV2ZWwgb2YgMC4wNSwgaGVuY2Ugd2UgYXJlIG5vdCBhYmxlIHRvIHJlamVjdCB0aGUgbnVsbCBoeXBvdGhlc2lzIHRoYXQgdGhlIGRhdGEgaXMgbm9ybWFsbHkgZGlzdHJpYnV0ZWQuIFRoaXMgY291bGQgYmUgYmVjYXVzZSB3ZSBqdXN0IGhhdmUgMTYgZGF0YXBvaW50cyBpbiBvdXIgZGF0YXNldC4NCg0KDQojIyNEaWFnbm9zdGljIGNoZWNrIGZvciBtb2RlbF8xNDFfbWwNCmBgYHtyfQ0KcmVzaWR1YWwuYW5hbHlzaXMobW9kZWwgPSBtb2RlbF8xNDFfbWwpDQpgYGANCiogVGltZSBzZXJpZXMgcGxvdDogVGhlcmUgYXJlIGF0IGxlYXN0IHR3byBvciB0aHJlZSByZXNpZHVhbHMgdG93YXJkcyB0aGUgZW5kIG9mIHRoZSBzZXJpZXMgd2l0aCBtYWduaXR1ZGVzIGxhcmdlciB0aGFuIDEgYW5kIC0xLiBJZGVhbGx5LCB3ZSBzaG91bGQgZ28gYmFjayB0byB0aG9zZSB5ZWFycyBhbmQgdHJ5IHRvIGxlYXJuIHdoYXQgb3V0c2lkZSBmYWN0b3JzIG1heSBoYXZlIGluZmx1ZW5jZWQgdW51c3VhbGx5IGxhcmdlIGRyb3BzIG9yIHVudXN1YWxseSBsYXJnZSBpbmNyZWFzZXMgaW4gdGhlIGVnZyBkZXBvc2l0aW9ucy4NCiogSGlzdG9ncmFtOiBUaGUgaGlzdG9ncmFtIGlzIHNsaWdodGx5IGxlZnQgc2tld2VkIHdoaWNoIGRvZXNuJ3Qgc2VlbSBub3JtYWxseSBkaXN0cmlidXRlZC4NCiogQUNGIHBsb3Q6IFRoZXJlIGlzIG5vIHRyZW5kIG5vciBhbnkgc2lnbmlmaWNhbnQgbGFncyBpbiB0aGUgcGxvdC4gV2UgY29uY2x1ZGUgdGhhdCB0aGUgZ3JhcGggZG9lcyBub3Qgc2hvdyBzdGF0aXN0aWNhbGx5IHNpZ25pZmljYW50IGV2aWRlbmNlIG9mIG5vbnplcm8gYXV0b2NvcnJlbGF0aW9uIGluIHRoZSByZXNpZHVhbHMuDQoqIFBBQ0YgcGxvdDogVGhlcmUgaXMgbm8gdHJlbmQgbm9yIGFueSBzaWduaWZpY2FudCBsYWdzIGluIHRoZSBwbG90LiBUaGVyZSBjb3VsZCBqdXN0IGJlIHdoaXRlLW5vaXNlLg0KKiBRUSBwbG90OiBNb3N0IG9mIHRoZSBkYXRhLXBvaW50cyBhcmUgZmFsbGluZyBvbiB0aGUgcXFsaW5lIGFuZCB0aGVyZSBpcyBqdXN0IG9uZSByZXNpZHVhbCB3aGljaCBpcyB0YWlsZWQgb2ZmIGluIHRoZSBiZWdpbm5pbmcuDQoqIExqdW5nLWJveCB0ZXN0OiBUaGUgZXN0aW1hdGVkIEFSSU1BKDEsNCwxKSBtb2RlbCBzZWVtcyB0byBiZSBjYXB0dXJpbmcgdGhlIGRlcGVuZGVuY2Ugc3RydWN0dXJlIG9mIHRoZSBlZ2cgZGVwb3NpdGlvbnMgdGltZSBzZXJpZXMgcXVpdGUgd2VsbC4NCiogU2hhcGlyby1XaWxrIHRlc3Q6IFRoZSBwLXZhbHVlIGlzIGdyZWF0ZXIgdGhhbiBvdXIgY2hvc2VuIGFscGhhIGxldmVsIG9mIDAuMDUsIGhlbmNlIHdlIGFyZSBhY2NlcHRpbmcgdGhlIG51bGwgaHlwb3RoZXNpcyB0aGF0IHRoZSBkYXRhIGlzIG5vcm1hbGx5IGRpc3RyaWJ1dGVkLg0KKiBUaGVyZSBpcyBubyBwcm9ibGVtIGluIHRoZSByZXNpZHVhbHMgb2YgQVJJTUEoMSw0LDEpIG1vZGVsLg0KDQoNCiMjRm9yZWNhc3RpbmcNCiogU2luY2UgdGhlcmUgaXMgbm8gcHJvYmxlbSBpbiB0aGUgcmVzaWR1YWxzIG9mIEFSSU1BKDEsNCwxKSBtb2RlbCwgaSBhbSBjb25zaWRlcmluZyB0aGlzIGFzIG15IGZpbmFsIG1vZGVsIGZvciBmb3JlY2FzdGluZy4gVGhlIGxhbWJkYSB2YWx1ZSBpcyBtZW50aW9uZWQgaW4gdGhlIGJlbG93IGZ1bmN0aW9uIGNvbnNpZGVyaW5nIGJveC1jb3ggdHJhbnNmb3JtYXRpb24gYXBwbGllZC4NCmBgYHtyfQ0KbW9kZWwxNDFmaXQ9QXJpbWEoZWdnc190cyxjKDEsNCwxKSxsYW1iZGE9LjQ1KQ0KcGxvdChmb3JlY2FzdChtb2RlbDE0MWZpdCxoPTUpLHlsaW09YygzLC0xKSx4bGFiPSdZZWFyJyx5bGFiPSdFZ2cgZGVwb3NpdGlvbnMgKGluIG1pbGxpb25zKScsbWFpbj0nRm9yZWNhc3Rpbmcgb2YgRWdnIGRlcG9zaXRpb25zIGZvciB0aGUgbmV4dCBmaXZlIHllYXJzJykNCmBgYA0KDQojI0NvbmNsdXNpb24NCiogQmFzZWQgb24gdGhlIEFDRiwgUEFDRiwgRUFDRiwgQklDIHRhYmxlIGFuZCBkaWFnbm9zdGljIGNoZWNrcywgd2UgaGF2ZSBjb25zaWRlcmVkIEFSSU1BIG1vZGVsICgxLDQsMSkuIEV2ZW4sIG1vZGVsIEFSSU1BKDAsNCwyKSBjb3VsZCBoYXZlIGJlZW4gdXNlZCBmb3IgZm9yZWNhc3RpbmcgYXMgYXBhcnQgZnJvbSBmZXcgZGlhZ25vc3RpYyBjaGVja3BvaW50cyBpdCB3YXMgYSByZWFsbHkgZ29vZCBtb2RlbC4gSG93ZXZlciwgdGhlcmUgc2VlbXMgdG8gYmUgYW4gaW5jcmVhc2luZyB0cmVuZCBpbiB0aGUgZWdnIGRlcG9zaXRpb25zIGJhc2VkIG9uIG91ciBmb3JlY2FzdGluZyBvZiBBUklNQSBtb2RlbCAoMSw0LDEpIGZvciB0aGUgbmV4dCA1IHllYXJzICgxOTk3LTIwMDEpLiANCg0KDQo8YnI+DQo8YnI+DQo=