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

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)

Importing and converting dataset to “ts” format

eggs <- read.csv("C:/Users/Mohammed/Documents/eggs.csv", header=TRUE)
view(eggs)
class(eggs)
[1] "data.frame"
eggs_ts <- ts(eggs$eggs, start = 1981, end = 1996)
class(eggs_ts)
[1] "ts"
hist(eggs$eggs,xlab = "Egg deposition",main = "Histogram of Egg deposition")

Time series plot

plot(eggs_ts,ylab='Egg depositions',xlab='Year',type='o', main = "Time series plot of egg depositions (in millions)")

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.

Applying transformation

eggs_ts.transform = BoxCox.ar(eggs_ts, method = "yule-walker")
possible convergence problem: optim gave code = 1possible convergence problem: optim gave code = 1

eggs_ts.transform$ci
[1] 0.1 0.8
lambda = 0.45
BC.eggs_ts = (eggs_ts^lambda-1)/lambda

Differencing

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

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

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

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

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



LS0tDQp0aXRsZTogIk1BVEgxMzE4IFNlbWVzdGVyIDEsIDIwMTkiDQphdXRob3I6ICJNVUpFRVIgTU9IQU1NRUQgUzM3NDA1ODciDQpzdWJ0aXRsZTogQXNzaWdubWVudCAyDQpvdXRwdXQ6DQogIGh0bWxfbm90ZWJvb2s6IGRlZmF1bHQNCiAgcGRmX2RvY3VtZW50OiBkZWZhdWx0DQogIGh0bWxfZG9jdW1lbnQ6DQogICAgZmlnX3dpZHRoOiA2DQogICAgZmlnX2hlaWdodDogNA0KICAgIGRmX3ByaW50OiBwYWdlZA0KLS0tDQoNCiMjSW50cm9kdWN0aW9uDQpPdXIgZWdncyBkYXRhc2V0IGZyb20gMTk4MSB0byAxOTk2IHNob3dzIHRoZSBudW1iZXIgb2YgQ29yZWdvbnVzIGhveWkgb2YgYWdlLTMgZWdnIGRlcG9zaXRpb25zIG1hZGUgdGhyb3VnaCB0aGUgeWVhcnMgKGluIG1pbGxpb25zKS4gV2Ugd2lsbCBhbmFseXNlIHRoaXMgZGF0YXNldCB0byBjYXB0dXJlIHRoaXMgdHJlbmQgYW5kIHByZWRpY3QgdGhlIG91dGNvbWUgZm9yIHRoZSBuZXh0IGZpdmUgeWVhcnMuDQoNCiMjTWV0aG9kb2xvZ3kNCiogVG8gcGVyZm9ybSB0aGlzIGFuYWx5c2lzIHdlIGhhdmUgYW5hbHlzZWQgdGhlIHRpbWUgc2VyaWVzIHBsb3QsIEFDRiBwbG90LCBQQUNGIHBsb3QuIA0KKiBBcHBsaWVkIHRyYW5zZm9ybWF0aW9uIGFuZCBkb25lIGRpZmZlcmVuY2luZyB0byB0aGUgZGF0YSBkdWUgdG8gbm9uLXN0YXRpb25hcml0eS4NCiogUGFyYW1ldGVyIGVzdGltYXRpb24gYWZ0ZXIgc2VsZWN0aW5nIHRoZSBwb3NzaWJsZSBtb2RlbHMgZnJvbSBBQ0YsIFBBQ0YsIEVBQ0YsIEJJQy4NCiogRmlsdGVyaW5nIHRoZSBtb2RlbHMgZnVydGhlciBiYXNlZCBvbiBBSUMgYW5kIEJJQyBzY29yZS4NCiogRGlhZ25vc3RpYyBjaGVja3Mgb24gMiBtb2RlbHMgc2VsZWN0ZWQgQVJJTUEoMCw0LDIpIGFuZCBBUklNQSgxLDQsMSkNCiogRm9yZWNhc3Rpbmcgb24gQVJJTUEgbW9kZWwoMSw0LDEpIGZvciB0aGUgbmV4dCBmaXZlIHllYXJzDQoNCiMjIFNldHVwDQoNCmBgYHtyLCBlY2hvID0gVFJVRSwgd2FybmluZ3MgPSBGQUxTRX0NCg0KbGlicmFyeShUU0EpDQpsaWJyYXJ5KGRwbHlyKQ0KbGlicmFyeShyZWFkcikNCmxpYnJhcnkoYW5hbHl0aWNzKQ0KbGlicmFyeShnZ3Bsb3QyKQ0KbGlicmFyeSh0aWR5cikNCmxpYnJhcnkoZ2dmb3J0aWZ5KQ0KbGlicmFyeSh0aWR5dmVyc2UpDQpsaWJyYXJ5KGJyb29tKQ0KbGlicmFyeShtYWdyaXR0cikNCmxpYnJhcnkoZlVuaXRSb290cykNCmxpYnJhcnkobG10ZXN0KQ0KbGlicmFyeShGaXRBUikNCmxpYnJhcnkodHNlcmllcykNCmxpYnJhcnkoZm9yZWNhc3QpDQpsaWJyYXJ5KGtuaXRyKQ0KDQpgYGANCg0KIyNJbXBvcnRpbmcgYW5kIGNvbnZlcnRpbmcgZGF0YXNldCB0byAidHMiIGZvcm1hdA0KYGBge3J9DQplZ2dzIDwtIHJlYWQuY3N2KCJDOi9Vc2Vycy9Nb2hhbW1lZC9Eb2N1bWVudHMvZWdncy5jc3YiLCBoZWFkZXI9VFJVRSkNCnZpZXcoZWdncykNCmNsYXNzKGVnZ3MpDQplZ2dzX3RzIDwtIHRzKGVnZ3MkZWdncywgc3RhcnQgPSAxOTgxLCBlbmQgPSAxOTk2KQ0KY2xhc3MoZWdnc190cykNCg0KYGBgDQpgYGB7cn0NCg0KaGlzdChlZ2dzJGVnZ3MseGxhYiA9ICJFZ2cgZGVwb3NpdGlvbiIsbWFpbiA9ICJIaXN0b2dyYW0gb2YgRWdnIGRlcG9zaXRpb24iKQ0KDQpgYGANCiogVGhlIGRpc3RyaWJ1dGlvbiBpcyByaWdodCBza2V3ZWQgYXMgZWdnIGRlcG9zaXRpb24gY2Fubm90IGJlIG5lZ2F0aXZlDQoNCiMjVGltZSBzZXJpZXMgcGxvdA0KYGBge3J9DQpwbG90KGVnZ3NfdHMseWxhYj0nRWdnIGRlcG9zaXRpb25zJyx4bGFiPSdZZWFyJyx0eXBlPSdvJywgbWFpbiA9ICJUaW1lIHNlcmllcyBwbG90IG9mIGVnZyBkZXBvc2l0aW9ucyAoaW4gbWlsbGlvbnMpIikNCg0KYGBgDQoNCiogVHJlbmQ6IHRoZXJlIGlzIGFuIGluY3JlYXNpbmcgY2hhbmdlIGluIHRoZSBtZWFuIGxldmVsDQoqIENoYW5naW5nIHZhcmlhbmNlOiBUaGVyZSBpcyBub3QgbXVjaCBvZiBsYXJnZXIgYW5kIHNtYWxsZXIgdmFyaWF0aW9uIG5vdGVkIGZyb20gdGhlIHBsb3QNCiogU2Vhc29uYWxpdHk6IFRoZXJlIGFyZSBubyBvYnZpb3VzIHJlcGVhdGluZyBwYXR0ZXJucw0KKiBBdXRvY29ycmVsYXRpb24gc3RydWN0dXJlOlRoZXJlIGFyZSBjb25zZWN1dGl2ZSBkYXRhIHBvaW50cyBhbmQgc29tZSBmbHVjdHVhdGlvbnMsIHRoZSBiZWhhdmlvdXIgb2YgdGhlIHNlcmllcyBzZWVtcyBsaWtlIGF1dG9yZWdyZXNzaXZlLiAgDQoqIEludGVydmVudGlvbjp0aGVyZSBpcyBubyBjaGFuZ2UtcG9pbnQgZXZlbnQgb3IgYSBzdWRkZW4gcmlzZSBvciBkcm9wIGluIHRoZSBkYXRhLXBvaW50cw0KDQoNCiMjI1NjYXR0ZXIgcGxvdCBvZiBlZ2cgZGVwb3NpdGlvbnMNCmBgYHtyfQ0KDQpwbG90KHk9ZWdnc190cyx4PXpsYWcoZWdnc190cykseWxhYj0nRWdnIGRlcG9zaXRpb25zJywgeGxhYj0nUHJldmlvdXMgeWVhciBFZ2cgZGVwb3NpdGlvbnMnLG1haW4gPSAiU2NhdHRlciBwbG90IG9mIEVnZyBkZXBvc2l0aW9ucyIpDQoNCmBgYA0KKiBJbiB0aGUgYWJvdmUgc2NhdHRlciBwbG90IHdlIGNhbm5vdCBzZWUgYSB0cmVuZC4gVGhlcmUgaXMgbm8gYXV0b2NvcnJlbGF0aW9uIGluIGl0cyBmaXJzdCBsYWcgb2YgdGhlIHNlcmllcw0KDQojIyNBQ0YgcGxvdA0KYGBge3J9DQplZ2dzX2FjZiA8LSBhY2YoZWdnc190cyxwbG90ID0gRkFMU0UpDQpwbG90KGVnZ3NfYWNmLCBtYWluID0gIkVnZyBkZXBvc2l0aW9uIFRpbWUgU2VyaWVzIEFDRiIpDQpgYGANCiogT25lIHNpZ25pZmljYW50IGxhZyBzdGFydGluZyBoaWdoIGFuZCBzbG93bHkgZGVjYXlpbmcgcGF0dGVybiwgdGhlcmUgaXMganVzdCBvbmUgc2lnbmlmaWNhbnQgbGFnIHRoaXMgY291bGQgYmUgYmVjYXVzZSB0aGUgc2VyaWVzIGlzIHNtYWxsLiBUaGlzIHNlcmllcyBpcyBub24tc3RhdGlvbmFyeS4NCg0KIyMjUEFDRiBwbG90DQpgYGB7cn0NCmVnZ3NfcGFjZiA8LSBwYWNmKGVnZ3NfdHMscGxvdCA9IEZBTFNFKQ0KcGxvdChlZ2dzX3BhY2YsIG1haW4gPSAiRWdnIGRlcG9zaXRpb24gVGltZSBTZXJpZXMgUEFDRiIpDQoNCmBgYA0KKiBTbG93bHkgZGVjYXlpbiBwYXR0ZXJuIGluIEFDRiBhbmQgdmVyeSBoaWdoIGZpcnN0IGNvcnJlbGF0aW9uIGluIFBBQ0YgaW1wbGllcyB0aGUgZXhpc3RlbmNlIG9mIHRyZW5kIGFuZCBub25zdGF0aW9uYXJpdHkuIFRoZXJlIGlzIG5vIHRyZW5kIG9yIGFueSBwYXR0ZXJuIG9ic2VydmVkIGluIHRoZSBQQUNGIHBsb3QuIEhlbmNlLCBpIGFtIGFzc3VtaW5nIG5vbi1zdGF0aW9uYXJpdHkuDQoNCiMjQXBwbHlpbmcgdHJhbnNmb3JtYXRpb24NCmBgYHtyfQ0KZWdnc190cy50cmFuc2Zvcm0gPSBCb3hDb3guYXIoZWdnc190cywgbWV0aG9kID0gInl1bGUtd2Fsa2VyIikNCmVnZ3NfdHMudHJhbnNmb3JtJGNpDQpsYW1iZGEgPSAwLjQ1DQpCQy5lZ2dzX3RzID0gKGVnZ3NfdHNebGFtYmRhLTEpL2xhbWJkYQ0KDQpgYGANCiogQXBwbGllZCBib3gtY294IHRyYW5zZm9ybWF0aW9uIGFuZCBnb3QgdGhlIGxhbWJkYSB2YWx1ZSBmcm9tIGNvbmZpZGVuY2UgaW50ZXJ2YWwgKDAuMSAwLjgpIGFzIDAuNDUNCg0KIyNEaWZmZXJlbmNpbmcNCiogV2UgYXJlIHByb2NlZWRpbmcgd2l0aCBkaWZmZXJlbmNpbmcgYXMgdGhlIHNlcmllcyBpcyBub24tc3RhdGlvbmFyeS4NCg0KIyMjMXN0IGRpZmZlcmVuY2luZw0KYGBge3J9DQoNCmRpZmYuQkMuZWdnc190cyA9IGRpZmYoQkMuZWdnc190cyxkaWZmZXJlbmNlcz0xKQ0KcGxvdChkaWZmLkJDLmVnZ3NfdHMsdHlwZT0nbycseWxhYj0nRWdnIGRlcG9zaXRpb25zJywgbWFpbj0nMXN0IGRpZmZlcmVuY2luZyBvZiBFZ2cgZGVwb3NpdGlvbnMnKQ0KDQoNCmBgYCAgIA0KDQojIyNBREYgdGVzdCBvbiAxc3QgZGlmZmVyZW5jaW5nDQpgYGB7cn0NCg0Kb3JkZXIgID0gYXIoZGlmZihkaWZmLkJDLmVnZ3NfdHMpKSRvcmRlcg0KYWRmVGVzdChkaWZmLkJDLmVnZ3NfdHMsIGxhZ3MgPSBvcmRlciwgIHRpdGxlID0gTlVMTCxkZXNjcmlwdGlvbiA9IE5VTEwpDQoNCg0KYGBgICAgDQoqIFNpbmNlIHRoZSBwLXZhbHVlIGlzIDAuMzQ2OSwgdGhlcmUgaXMgMzQuNjklIHRoYXQgbXkgcHJvY2VzcyBpcyBub24gc3RhdGlvbmFyeSIuIFRoZXJlZm9yZSwgd2UgY2Fubm90IHJlamVjdCBIMCBhdCwgMSUgYW5kIHRoZXJlZm9yZSB3ZSBjb25jbHVkZSB0aGF0IHRoZSBwcm9jZXNzIGlzIG5vbiBzdGF0aW9uYXJ5Lg0KDQoNCiMjIzJuZCBkaWZmZXJlbmNpbmcNCmBgYHtyfQ0KZGlmZjIuQkMuZWdnc190cyA9IGRpZmYoQkMuZWdnc190cyxkaWZmZXJlbmNlcz0yKQ0KcGxvdChkaWZmMi5CQy5lZ2dzX3RzLHR5cGU9J28nLHlsYWI9J0VnZyBkZXBvc2l0aW9ucycsbWFpbj0nMm5kIGRpZmZlcmVuY2luZyBvZiBFZ2cgZGVwb3NpdGlvbnMnKQ0KYGBgDQoNCg0KIyMjQURGIHRlc3Qgb24gMm5kIGRpZmZlcmVuY2luZw0KYGBge3J9DQoNCm9yZGVyICA9IGFyKGRpZmYoZGlmZjIuQkMuZWdnc190cykpJG9yZGVyDQphZGZUZXN0KGRpZmYyLkJDLmVnZ3NfdHMsIGxhZ3MgPSBvcmRlciwgIHRpdGxlID0gTlVMTCxkZXNjcmlwdGlvbiA9IE5VTEwpDQoNCmBgYA0KKiBUaGUgcC12YWx1ZSAwLjEwOTggaXMgZ3JlYXRlciB0aGFuIHRoZSBjaG9zZW4gYWxwaGEgbGV2ZWwgMSUuIEhlbmNlIHdlIGNhbiBzYXkgdGhhdCB0aGUgc2VyaWVzIGlzIHN0aWxsIG5vbi1zdGF0aW9uYXJ5Lg0KDQoNCiMjIzNyZCBkaWZmZXJlbmNpbmcNCmBgYHtyfQ0KZGlmZjMuQkMuZWdnc190cyA9IGRpZmYoQkMuZWdnc190cyxkaWZmZXJlbmNlcz0zKQ0KcGxvdChkaWZmMy5CQy5lZ2dzX3RzLHR5cGU9J28nLHlsYWI9J0VnZyBkZXBvc2l0aW9ucycsbWFpbj0nM3JkIGRpZmZlcmVuY2luZyBvZiBFZ2cgZGVwb3NpdGlvbnMnKQ0KDQoNCmBgYA0KKiBUaGUgc2VyaWVzIHN0aWxsIGhhcyBzZWFzb25hbGl0eSBhbmQgdHJlbmQsIHdlIHdpbGwgY2hlY2sgdGhpcyB3aXRoIEFERiB0ZXN0IGlmIHNlcmllcyBpcyBzdGF0aW9uYXJ5Lg0KDQojIyNBREYgdGVzdCBvbiAzcmQgZGlmZmVyZW5jaW5nDQpgYGB7cn0NCm9yZGVyICA9IGFyKGRpZmYoZGlmZjMuQkMuZWdnc190cykpJG9yZGVyICMgVG8gcGFzcyB0aGUgb3JkZXIgdG8gYWRmVGVzdCBmdW5jdGlvbg0KYWRmVGVzdChkaWZmMy5CQy5lZ2dzX3RzLCBsYWdzID0gb3JkZXIsICB0aXRsZSA9IE5VTEwsZGVzY3JpcHRpb24gPSBOVUxMKQ0KDQoNCmBgYA0KDQoqIFRoZSBwLXZhbHVlIDAuMTgzNiBpcyBncmVhdGVyIHRoYW4gdGhlIGNob3NlbiBhbHBoYSBsZXZlbCAxJS4gSGVuY2Ugd2UgY2FuIHNheSB0aGF0IHRoZSBzZXJpZXMgaXMgc3RpbGwgbm9uLXN0YXRpb25hcnkuDQoNCiMjIzR0aCBkaWZmZXJlbmNpbmcNCmBgYHtyfQ0KDQpkaWZmNC5CQy5lZ2dzX3RzID0gZGlmZihCQy5lZ2dzX3RzLGRpZmZlcmVuY2VzPTQpDQpwbG90KGRpZmY0LkJDLmVnZ3NfdHMsdHlwZT0nbycseWxhYj0nRWdnIGRlcG9zaXRpb25zJyxtYWluPSc0dGggZGlmZmVyZW5jaW5nIG9mIEVnZyBkZXBvc2l0aW9ucycpDQoNCmBgYA0KKiBUaGVyZSBzZWVtcyB0byBiZSBubyB0cmVuZCBvciBzZWFzb25hbGl0eSBleGlzdGluZywgd2UgY2FuIGZ1cnRoZXIgdmVyaWZ5IHRoaXMgYnkgQURGIHRlc3QgZm9yIHN0YXRpb25hcml0eS4NCg0KIyMjQURGIHRlc3Qgb24gNHRoIGRpZmZlcmVuY2luZw0KYGBge3J9DQoNCm9yZGVyICA9IGFyKGRpZmYoZGlmZjQuQkMuZWdnc190cykpJG9yZGVyDQphZGZUZXN0KGRpZmY0LkJDLmVnZ3NfdHMsIGxhZ3MgPSBvcmRlciwgIHRpdGxlID0gTlVMTCxkZXNjcmlwdGlvbiA9IE5VTEwpDQoNCmBgYA0KKiBXZSBhcmUgcmVqZWN0aW5nIHRoZSBudWxsIGh5cG90aGVzaXMgc2luY2Ugb3VyIHAtdmFsdWUgaXMgbGVzcyB0aGFuIDAuMS4gV2UgY2FuIGNvbmNsdWRlIHRoYXQgdGhlIHNlcmllcyBpcyBzdGF0aW9uYXJ5IGFmdGVyIDR0aCBkaWZmZXJlbmNpbmcuDQoNCg0KYGBge3J9DQpwbG90KGRpZmY0LkJDLmVnZ3NfdHMseWxhYj0nRWdnIGRlcG9zaXRpb25zJyx4bGFiPSdZZWFyJyx0eXBlPSdvJywgbWFpbiA9ICJUaW1lIHNlcmllcyBwbG90IG9mIGVnZyBkZXBvc2l0aW9ucyBhZnRlciA0dGggZGlmZmVyZW5jaW5nIChpbiBtaWxsaW9ucykiKQ0KYGBgDQoqIFRyZW5kOiBUcmVuZCBpbiB0aGlzIHNlcmllcyBpcyBub3Qgc28gb2J2aW91cy4NCiogQ2hhbmdpbmcgdmFyaWFuY2U6VGhlcmUgY291bGQgYmUgdmFyaWF0aW9uIGJldHdlZW4gdGhlIHllYXIgMTk4OCBhbmQgMTk5MCBhZ2FpbnN0IGxhcmdlciB2YXJpYXRpb25zIHRocm91Z2ggdGhlIHNlcmllcy4NCiogU2Vhc29uYWxpdHk6VGhlcmUgYXJlIG5vIG9idmlvdXMgcmVwZWF0aW5nIHBhdHRlcm5zDQoqIEF1dG9jb3JyZWxhdGlvbiBzdHJ1Y3R1cmU6VGhlcmUgYXJlIHZlcnkgZmV3IGNvbnNlY3V0aXZlIGRhdGEgcG9pbnRzIGFuZCBtb3JlIGZsdWN0dWF0aW9ucyBpbiB0aGUgc2VyaWVzIGhlbmNlIGl0IGNvdWxkIGJlIG1vdmluZyBhdmVyYWdlIGJlaGF2aW91ci4gICANCiogSW50ZXJ2ZW50aW9uOnRoZXJlIGlzIG5vIGNoYW5nZS1wb2ludCBldmVudCBvciBhIHN1ZGRlbiByaXNlIG9yIGRyb3AgaW4gdGhlIGRhdGEtcG9pbnRzDQoNCiMjI0FDRiBwbG90IG9mIDR0aCBkaWZmZXJlbmNpbmcNCmBgYHtyfQ0KDQplZ2dzNHRoZGlmZl9hY2YgPC0gYWNmKGRpZmY0LkJDLmVnZ3NfdHMscGxvdCA9IEZBTFNFKQ0KcGxvdChlZ2dzNHRoZGlmZl9hY2YsIG1haW4gPSAiNHRoIGRpZmZlcmVuY2luZyBvZiBFZ2cgZGVwb3NpdGlvbiBUaW1lIFNlcmllcyBBQ0YgcGxvdCIpDQoNCmBgYA0KKiBXZSBjYW4gb2JzZXJ2ZSBzb21lIHRyZW5kIGFuZCBzZWFzb25hbGl0eSBmcm9tIHRoZSBwbG90IGFuZCB0aGVyZSBpcyBvbmUgc2lnbmlmaWNhbnQgbGFnIGluIEFDRi4NCg0KIyMjUEFDRiBwbG90IG9mIDR0aCBkaWZmZXJlbmNpbmcNCmBgYHtyfQ0KZWdnczR0aGRpZmZfcGFjZiA8LSBwYWNmKGRpZmY0LkJDLmVnZ3NfdHMscGxvdCA9IEZBTFNFKQ0KcGxvdChlZ2dzNHRoZGlmZl9wYWNmLCBtYWluID0gIjR0aCBkaWZmZXJlbmNpbmcgb2YgRWdnIGRlcG9zaXRpb24gVGltZSBTZXJpZXMgUEFDRiBwbG90IikNCmBgYA0KKiBUaGVyZSBpcyBvbmUgc2lnbmlmaWNhbnQgbGFnIGFuZCBraW5kIG9mIGEgZGVjcmVhc2luZyB0cmVuZCBvYnNlcnZlZCBpbiBQQUNGLiBXZSBjYW4gY29uc2lkZXIgdGhlIG1vZGVsIHtBUklNQSgxLDQsMSl9IGZyb20gQUNGIGFuZCBQQUNGIHBsb3QuDQoNCiMjI0VBQ0YgcGxvdCBvZiA0dGggZGlmZmVyZW5jaW5nDQpgYGB7cn0NCmVhY2YoZGlmZjQuQkMuZWdnc190cyxhci5tYXggPSAyLCBtYS5tYXggPSAyKQ0KYGBgDQoqIEkgaGF2ZSBjb25zaWRlcmVkIGFyLm1heCBhbmQgbWEubWF4IGFzICIyIiBiZWNhdXNlIHByb2plY3Rpb24gbWF0cml4IHJlc3VsdHMgYXJlIHNob3duIGludmFsaWQgaWYgdGhlIHZhbHVlcyBhcmUgaW5jcmVhc2VkLg0KKiBDYW5kaWRhdGUgbW9kZWxzIGZyb20gRUFDRiBwbG90IGFyZSB7QVJJTUEoMCw0LDEpLCBBUklNQSgwLDQsMiksIEFSSU1BKDEsNCwxKSwgQVJJTUEoMSw0LDIpfQ0KDQoNCiMjI0JJQyB0YWJsZSBvZiA0dGggZGlmZmVyZW5jaW5nDQpgYGB7cn0NCkJJQ19lZ2dzLm9scyA9IGFybWFzdWJzZXRzKHk9ZGlmZjQuQkMuZWdnc190cyxuYXI9NCxubWE9NCx5Lm5hbWU9J3Rlc3QnLGFyLm1ldGhvZD0nb2xzJykNCnBsb3QoQklDX2VnZ3Mub2xzLG1haW49IkJJQyB0YWJsZSBvZiA0dGggZGlmZmVyZW5jaW5nIikNCmBgYA0KKiBGcm9tIHRoZSBCSUMgdGFibGUgd2UgY2FuIGNvbnNpZGVyIHRoZSBtb2RlbHMge0FSSU1BKDAsNCwyKSwgQVJJTUEoMCw0LDQpfQ0KKiBJJ20gbm90IGluY2x1ZGluZyBBUklNQSgwLDQsNCkgY29uc2lkZXJpbmcgdGhlIGxlbmd0aCBvZiB0aGUgc2VyaWVzDQoqIFRoZSBmaW5hbCBzZXQgb2YgcG9zc2libGUgbW9kZWxzIGFyZSB7QVJJTUEoMCw0LDEpLCBBUklNQSgwLDQsMiksIEFSSU1BKDEsNCwxKSwgQVJJTUEoMSw0LDIpfQ0KDQoNCiMjUGFyYW1ldGVyIGVzdGltYXRpb24NCiogV2Ugd2lsbCBiZSBkb2luZyBwYXJhbWV0ZXIgZXN0aW1hdGlvbiB1c2luZyB0d28gbWV0aG9kcyB0byBzZWUgdGhlIGNvbnNpc3RlbmN5IGkuZS4gQ1NTIChjb25kaXRpb25hbCBzdW0gb2Ygc3F1YXJlcykgYW5kIE1MIChtYXhpbXVtIGxpa2VsaWhvb2QpLg0KDQojIyNBUklNQSgwLDQsMSkgLSBDU1MNCmBgYHtyfQ0KbW9kZWxfMDQxX2NzcyA9IGFyaW1hKGRpZmY0LkJDLmVnZ3NfdHMsb3JkZXI9YygwLDQsMSksbWV0aG9kPSdDU1MnKQ0KY29lZnRlc3QobW9kZWxfMDQxX2NzcykNCmBgYA0KDQojIyNBUklNQSgwLDQsMSkgLSBNTA0KYGBge3J9DQptb2RlbF8wNDFfbWwgPSBhcmltYShkaWZmNC5CQy5lZ2dzX3RzLG9yZGVyPWMoMCw0LDEpLG1ldGhvZD0nTUwnKQ0KY29lZnRlc3QobW9kZWxfMDQxX21sKQ0KYGBgDQoqIEJvdGggY29uZGl0aW9uYWwgc3VtIG9mIHNxdWFyZXMgYW5kIG1heGltdW0gbGlrZWxpaG9vZCBtZXRob2RzIHNob3cgdXMgdGhhdCB0aGlzIG1vZGVsIGlzIHNpZ25pZmljYW50DQoNCiMjIyBBUklNQSgwLDQsMikgLSBDU1MNCmBgYHtyfQ0KbW9kZWxfMDQyX2NzcyA9IGFyaW1hKGRpZmY0LkJDLmVnZ3NfdHMsb3JkZXI9YygwLDQsMiksbWV0aG9kPSdDU1MnKQ0KY29lZnRlc3QobW9kZWxfMDQyX2NzcykNCmBgYA0KKiBvbmx5IE1BKDEpIGlzIHNpZ25pZmljYW50IHVzaW5nIGNvbmRpdGlvbmFsIHN1bSBvZiBzcXVhcmVzIG1ldGhvZA0KDQojIyMgQVJJTUEoMCw0LDIpIC0gTUwNCmBgYHtyfQ0KbW9kZWxfMDQyX21sID0gYXJpbWEoZGlmZjQuQkMuZWdnc190cyxvcmRlcj1jKDAsNCwyKSxtZXRob2Q9J01MJykNCmNvZWZ0ZXN0KG1vZGVsXzA0Ml9tbCkNCmBgYA0KKiB1c2luZyB0aGUgbWF4aW11bSBsaWtlbGlob29kIG1ldGhvZCwgYm90aCBNQSgxKSBhbmQgTUEoMikgYXJlIHNpZ25pZmljYW50Lg0KDQojIyMgQVJJTUEoMSw0LDEpIC0gQ1NTDQpgYGB7cn0NCm1vZGVsXzE0MV9jc3MgPSBhcmltYShkaWZmNC5CQy5lZ2dzX3RzLG9yZGVyPWMoMSw0LDEpLG1ldGhvZD0nQ1NTJykNCmNvZWZ0ZXN0KG1vZGVsXzE0MV9jc3MpDQpgYGANCiogdXNpbmcgdGhlIGNvbmRpdGlvbmFsIHN1bSBvZiBzcXVhcmVzIG1ldGhvZCwgQVIoMSkgYW5kIE1BKDEpIGlzIHNpZ25pZmljYW50DQoNCiMjIyBBUklNQSgxLDQsMSkgLSBNTA0KYGBge3J9DQptb2RlbF8xNDFfbWwgPSBhcmltYShkaWZmNC5CQy5lZ2dzX3RzLG9yZGVyPWMoMSw0LDEpLG1ldGhvZD0nTUwnKQ0KY29lZnRlc3QobW9kZWxfMTQxX21sKQ0KYGBgDQoqIHVzaW5nIHRoZSBtYXhpbXVtIGxpa2VsaWhvb2QgbWV0aG9kLCBBUigxKSBhbmQgTUEoMSkgaXMgc2lnbmlmaWNhbnQNCg0KIyMjIEFSSU1BKDEsNCwyKSAtIENTUw0KYGBge3J9DQptb2RlbF8xNDJfY3NzID0gYXJpbWEoZGlmZjQuQkMuZWdnc190cyxvcmRlcj1jKDEsNCwyKSxtZXRob2Q9J0NTUycpDQpjb2VmdGVzdChtb2RlbF8xNDJfY3NzKQ0KYGBgDQoqIE1BKDIpIGlzIGluc2lnbmlmaWNhbnQgdXNpbmcgY29uZGl0aW9uYWwgc3VtIG9mIHNxdWFyZXMgbWV0aG9kIGFuZCBBUigxKSwgTUEoMSkgaXMgc2lnbmlmaWNhbnQNCg0KIyMjIEFSSU1BKDEsNCwyKSAtIE1MDQpgYGB7cn0NCm1vZGVsXzE0Ml9tbCA9IGFyaW1hKGRpZmY0LkJDLmVnZ3NfdHMsb3JkZXI9YygxLDQsMiksbWV0aG9kPSdNTCcpDQpjb2VmdGVzdChtb2RlbF8xNDJfbWwpDQpgYGANCiogQWdhaW4sIGJvdGggQVIoMSksIE1BKDEpIGFyZSBzaWduaWZpY2FudCB1c2luZyBtYXhpbXVtIGxpa2VsaWhvb2QgbWV0aG9kIGFuZCBNQSgyKSBpcyBpbnNpZ25pZmljYW50DQoqIFRoZSBtb2RlbHMgd2l0aCBhbGwgY29lZmZpY2llbnRzIHNpZ25pZmljYW50IGFyZSB7QVJJTUEoMCw0LDEpLCBBUklNQSgwLDQsMiksIEFSSU1BKDEsNCwxKX0gYW5kIEFSSU1BKDEsNCwyKSB3YXMgc2hvd24gaW5zaWduaWZpY2FudCB1c2luZyBDU1MgYW5kIE1MIG1ldGhvZC4NCg0KIyMjU29ydCBzY29yZSBmdW5jdGlvbiBmb3IgQUlDIGFuZCBCSUMgc2NvcmUNCmBgYHtyfQ0Kc29ydC5zY29yZSA8LSBmdW5jdGlvbih4LCBzY29yZSA9IGMoImJpYyIsICJhaWMiKSl7DQogIGlmIChzY29yZSA9PSAiYWljIil7DQogICAgeFt3aXRoKHgsIG9yZGVyKEFJQykpLF0NCiAgfSBlbHNlIGlmIChzY29yZSA9PSAiYmljIikgew0KICAgIHhbd2l0aCh4LCBvcmRlcihCSUMpKSxdDQogIH0gZWxzZSB7DQogICAgd2FybmluZygnc2NvcmUgPSAieCIgb25seSBhY2NlcHRzIHZhbGlkIGFyZ3VtZW50cyAoImFpYyIsImJpYyIpJykNCiAgfQ0KfQ0KYGBgDQoNCiMjQUlDIGFuZCBCSUMgc2NvcmUNCmBgYHtyfQ0Kc29ydC5zY29yZShBSUMobW9kZWxfMDQxX21sLG1vZGVsXzA0Ml9tbCxtb2RlbF8xNDFfbWwpLCBzY29yZSA9ICJhaWMiKQ0Kc29ydC5zY29yZShCSUMobW9kZWxfMDQxX21sLG1vZGVsXzA0Ml9tbCxtb2RlbF8xNDFfbWwpLCBzY29yZSA9ICJiaWMiICkNCmBgYA0KKiBUaGUgb3JkZXIgb2Ygc2NvcmluZyBpbiBib3RoIEFJQywgQklDIGlzIHRoZSBzYW1lLiBtb2RlbF8xNDFfbWwgaGFzIHRoZSBsb3dlc3QgQUlDIGFuZCBCSUMgc2NvcmUgd2hpY2ggaXMgYmV0dGVyLiBJIGFtIGFsc28gY29uc2lkZXJpbmcgbW9kZWxfMDQyX21sIGFzIGl0IGhhcyB0aGUgc2Vjb25kIGxvd2VzdCBBSUMgJiBCSUMgc2NvcmUuDQoNCiMjI1Jlc2lkdWFsIGFuYWx5c2lzIGZ1bmN0aW9uDQpgYGB7cn0NCnJlc2lkdWFsLmFuYWx5c2lzIDwtIGZ1bmN0aW9uKG1vZGVsLCBzdGQgPSBUUlVFLHN0YXJ0ID0gMil7DQogIGxpYnJhcnkoVFNBKQ0KICBsaWJyYXJ5KEZpdEFSKQ0KICAgIGlmIChzdGQgPT0gVFJVRSl7DQogICAgICByZXMubW9kZWwgPSByc3RhbmRhcmQobW9kZWwpDQogICAgfWVsc2V7DQogICAgICByZXMubW9kZWwgPSByZXNpZHVhbHMobW9kZWwpDQogICAgfQ0KICBwYXIobWZyb3c9YygzLDIpKQ0KICBwbG90KHJlcy5tb2RlbCx0eXBlPSdvJyx5bGFiPSdTdGFuZGFyZGlzZWQgcmVzaWR1YWxzJywgbWFpbj0iVGltZSBzZXJpZXMgcGxvdCBvZiBzdGFuZGFyZGlzZWQgcmVzaWR1YWxzIikNCiAgYWJsaW5lKGg9MCkNCiAgaGlzdChyZXMubW9kZWwsbWFpbj0iSGlzdG9ncmFtIG9mIHN0YW5kYXJkaXNlZCByZXNpZHVhbHMiKQ0KICBhY2YocmVzLm1vZGVsLG1haW49IkFDRiBvZiBzdGFuZGFyZGlzZWQgcmVzaWR1YWxzIikNCiAgcGFjZihyZXMubW9kZWwsbWFpbj0iUEFDRiBvZiBzdGFuZGFyZGlzZWQgcmVzaWR1YWxzIikNCiAgcXFub3JtKHJlcy5tb2RlbCxtYWluPSJRUSBwbG90IG9mIHN0YW5kYXJkaXNlZCByZXNpZHVhbHMiKQ0KICBxcWxpbmUocmVzLm1vZGVsLCBjb2wgPSAyKQ0KICBwcmludChzaGFwaXJvLnRlc3QocmVzLm1vZGVsKSkNCiAgaz0wDQogIExCUVBsb3QocmVzLm1vZGVsLCBsYWcubWF4ID0gbGVuZ3RoKG1vZGVsJHJlc2lkdWFscyktMSwgU3RhcnRMYWcgPSBrICsgMSwgayA9IDAsIFNxdWFyZWRRID0gRkFMU0UpDQogIHBhcihtZnJvdz1jKDEsMSkpDQp9DQoNCmBgYA0KDQojI0RpYWdub3N0aWMgY2hlY2tzDQoqIFBlcmZvcm1pbmcgZGlhZ25vc3RpYyBjaGVja3MgZm9yIGJvdGggdGhlIG1vZGVscyBtb2RlbF8wNDJfbWwgYW5kIG1vZGVsXzE0MV9tbA0KDQojIyNEaWFnbm9zdGljIGNoZWNrIGZvciBtb2RlbF8wNDJfbWwNCmBgYHtyfQ0KcmVzaWR1YWwuYW5hbHlzaXMobW9kZWwgPSBtb2RlbF8wNDJfbWwpDQpgYGANCiogVGltZSBzZXJpZXMgcGxvdDogVGhlcmUgYXJlIGF0IGxlYXN0IHRocmVlIG9yIGZvdXIgcmVzaWR1YWxzIG1pZC1lbmRpbmcgb2YgdGhlIHNlcmllcyB3aXRoIG1hZ25pdHVkZXMgbGFyZ2VyIHRoYW4gMSBhbmQgLTEgd2hpY2ggaXMgdW51c3VhbCBpbiBhIHN0YW5kYXJkIG5vcm1hbCBkaXN0cmlidXRpb24uIElkZWFsbHksIHdlIHNob3VsZCBnbyBiYWNrIHRvIHRob3NlIHllYXJzIGFuZCB0cnkgdG8gbGVhcm4gd2hhdCBvdXRzaWRlIGZhY3RvcnMgbWF5IGhhdmUgaW5mbHVlbmNlZCB1bnVzdWFsbHkgbGFyZ2UgZHJvcHMgb3IgdW51c3VhbGx5IGxhcmdlIGluY3JlYXNlcyBpbiB0aGUgZWdnIGRlcG9zaXRpb25zLg0KKiBIaXN0b2dyYW06IFRoZSBoaXN0b2dyYW0gaXMgc2xpZ2h0bHkgbGVmdCBza2V3ZWQgd2hpY2ggZG9lc24ndCBzZWVtIG5vcm1hbGx5IGRpc3RyaWJ1dGVkLg0KKiBBQ0YgcGxvdDogVGhlcmUgaXMgb25lIHNsaWdodGx5IHNpZ25pZmljYW50IGxhZy4gV2UgY29uY2x1ZGUgdGhhdCB0aGUgZ3JhcGggc2hvd3Mgc3RhdGlzdGljYWxseSBzaWduaWZpY2FudCBldmlkZW5jZSBvZiBub256ZXJvIGF1dG9jb3JyZWxhdGlvbiBpbiB0aGUgcmVzaWR1YWxzLg0KKiBQQUNGIHBsb3Q6IFRoZXJlIGlzIG9uZSBzbGlnaHRseSBzaWduaWZpY2FudCBsYWcgd2hpY2ggc2hvdWxkbid0IGJlIHRoZSBjYXNlLCB3ZSB3aWxsIGNvbmZpcm0gdGhpcyBpbiBManVuZy1ib3ggdGVzdA0KKiBRUSBwbG90OiBWZXJ5IGZldyBkYXRhLXBvaW50cyBhcmUgZmFsbGluZyBvbiB0aGUgcXFsaW5lIGFuZCB0aGUgZGF0YS1wb2ludHMgYXQgdGhlIGJlZ2lubmluZyBhbmQgZW5kIG9mIHRoZSBsaW5lIGFyZSB0YWlsaW5nIG9mZi4NCiogTGp1bmctYm94IHRlc3Q6IFRoZSBlc3RpbWF0ZWQgQVJJTUEoMCw0LDIpIG1vZGVsIGRvZXNuJ3Qgc2VlbSB0byBiZSBjYXB0dXJpbmcgdGhlIGRlcGVuZGVuY2Ugc3RydWN0dXJlIG9mIHRoZSBlZ2cgZGVwb3NpdGlvbnMgdGltZSBzZXJpZXMgcXVpdGUgd2VsbC4gVGhlcmUgaXMgb25lIGRhdGEtcG9pbnQgYmVsb3cgdGhlIDAuMDUgc2lnbmlmaWNhbmNlIGxldmVsLg0KKiBTaGFwaXJvLVdpbGsgdGVzdDogVGhlIHAtdmFsdWUgaXMgZ3JlYXRlciB0aGFuIG91ciBjaG9zZW4gYWxwaGEgbGV2ZWwgb2YgMC4wNSwgaGVuY2Ugd2UgYXJlIG5vdCBhYmxlIHRvIHJlamVjdCB0aGUgbnVsbCBoeXBvdGhlc2lzIHRoYXQgdGhlIGRhdGEgaXMgbm9ybWFsbHkgZGlzdHJpYnV0ZWQuIFRoaXMgY291bGQgYmUgYmVjYXVzZSB3ZSBqdXN0IGhhdmUgMTYgZGF0YXBvaW50cyBpbiBvdXIgZGF0YXNldC4NCg0KDQojIyNEaWFnbm9zdGljIGNoZWNrIGZvciBtb2RlbF8xNDFfbWwNCmBgYHtyfQ0KcmVzaWR1YWwuYW5hbHlzaXMobW9kZWwgPSBtb2RlbF8xNDFfbWwpDQpgYGANCiogVGltZSBzZXJpZXMgcGxvdDogVGhlcmUgYXJlIGF0IGxlYXN0IHR3byBvciB0aHJlZSByZXNpZHVhbHMgdG93YXJkcyB0aGUgZW5kIG9mIHRoZSBzZXJpZXMgd2l0aCBtYWduaXR1ZGVzIGxhcmdlciB0aGFuIDEgYW5kIC0xLiBJZGVhbGx5LCB3ZSBzaG91bGQgZ28gYmFjayB0byB0aG9zZSB5ZWFycyBhbmQgdHJ5IHRvIGxlYXJuIHdoYXQgb3V0c2lkZSBmYWN0b3JzIG1heSBoYXZlIGluZmx1ZW5jZWQgdW51c3VhbGx5IGxhcmdlIGRyb3BzIG9yIHVudXN1YWxseSBsYXJnZSBpbmNyZWFzZXMgaW4gdGhlIGVnZyBkZXBvc2l0aW9ucy4NCiogSGlzdG9ncmFtOiBUaGUgaGlzdG9ncmFtIGlzIHNsaWdodGx5IGxlZnQgc2tld2VkIHdoaWNoIGRvZXNuJ3Qgc2VlbSBub3JtYWxseSBkaXN0cmlidXRlZC4NCiogQUNGIHBsb3Q6IFRoZXJlIGlzIG5vIHRyZW5kIG5vciBhbnkgc2lnbmlmaWNhbnQgbGFncyBpbiB0aGUgcGxvdC4gV2UgY29uY2x1ZGUgdGhhdCB0aGUgZ3JhcGggZG9lcyBub3Qgc2hvdyBzdGF0aXN0aWNhbGx5IHNpZ25pZmljYW50IGV2aWRlbmNlIG9mIG5vbnplcm8gYXV0b2NvcnJlbGF0aW9uIGluIHRoZSByZXNpZHVhbHMuDQoqIFBBQ0YgcGxvdDogVGhlcmUgaXMgbm8gdHJlbmQgbm9yIGFueSBzaWduaWZpY2FudCBsYWdzIGluIHRoZSBwbG90LiBUaGVyZSBjb3VsZCBqdXN0IGJlIHdoaXRlLW5vaXNlLg0KKiBRUSBwbG90OiBNb3N0IG9mIHRoZSBkYXRhLXBvaW50cyBhcmUgZmFsbGluZyBvbiB0aGUgcXFsaW5lIGFuZCB0aGVyZSBpcyBqdXN0IG9uZSByZXNpZHVhbCB3aGljaCBpcyB0YWlsZWQgb2ZmIGluIHRoZSBiZWdpbm5pbmcuDQoqIExqdW5nLWJveCB0ZXN0OiBUaGUgZXN0aW1hdGVkIEFSSU1BKDEsNCwxKSBtb2RlbCBzZWVtcyB0byBiZSBjYXB0dXJpbmcgdGhlIGRlcGVuZGVuY2Ugc3RydWN0dXJlIG9mIHRoZSBlZ2cgZGVwb3NpdGlvbnMgdGltZSBzZXJpZXMgcXVpdGUgd2VsbC4NCiogU2hhcGlyby1XaWxrIHRlc3Q6IFRoZSBwLXZhbHVlIGlzIGdyZWF0ZXIgdGhhbiBvdXIgY2hvc2VuIGFscGhhIGxldmVsIG9mIDAuMDUsIGhlbmNlIHdlIGFyZSBhY2NlcHRpbmcgdGhlIG51bGwgaHlwb3RoZXNpcyB0aGF0IHRoZSBkYXRhIGlzIG5vcm1hbGx5IGRpc3RyaWJ1dGVkLg0KKiBUaGVyZSBpcyBubyBwcm9ibGVtIGluIHRoZSByZXNpZHVhbHMgb2YgQVJJTUEoMSw0LDEpIG1vZGVsLg0KDQoNCiMjRm9yZWNhc3RpbmcNCiogU2luY2UgdGhlcmUgaXMgbm8gcHJvYmxlbSBpbiB0aGUgcmVzaWR1YWxzIG9mIEFSSU1BKDEsNCwxKSBtb2RlbCwgaSBhbSBjb25zaWRlcmluZyB0aGlzIGFzIG15IGZpbmFsIG1vZGVsIGZvciBmb3JlY2FzdGluZy4gVGhlIGxhbWJkYSB2YWx1ZSBpcyBtZW50aW9uZWQgaW4gdGhlIGJlbG93IGZ1bmN0aW9uIGNvbnNpZGVyaW5nIGJveC1jb3ggdHJhbnNmb3JtYXRpb24gYXBwbGllZC4NCmBgYHtyfQ0KbW9kZWwxNDFmaXQ9QXJpbWEoZWdnc190cyxjKDEsNCwxKSxsYW1iZGE9LjQ1KQ0KcGxvdChmb3JlY2FzdChtb2RlbDE0MWZpdCxoPTUpLHlsaW09YygzLC0xKSx4bGFiPSdZZWFyJyx5bGFiPSdFZ2cgZGVwb3NpdGlvbnMgKGluIG1pbGxpb25zKScsbWFpbj0nRm9yZWNhc3Rpbmcgb2YgRWdnIGRlcG9zaXRpb25zIGZvciB0aGUgbmV4dCBmaXZlIHllYXJzJykNCmBgYA0KDQojI0NvbmNsdXNpb24NCiogQmFzZWQgb24gdGhlIEFDRiwgUEFDRiwgRUFDRiwgQklDIHRhYmxlIGFuZCBkaWFnbm9zdGljIGNoZWNrcywgd2UgaGF2ZSBjb25zaWRlcmVkIEFSSU1BIG1vZGVsICgxLDQsMSkuIEV2ZW4sIG1vZGVsIEFSSU1BKDAsNCwyKSBjb3VsZCBoYXZlIGJlZW4gdXNlZCBmb3IgZm9yZWNhc3RpbmcgYXMgYXBhcnQgZnJvbSBmZXcgZGlhZ25vc3RpYyBjaGVja3BvaW50cyBpdCB3YXMgYSByZWFsbHkgZ29vZCBtb2RlbC4gSG93ZXZlciwgdGhlcmUgc2VlbXMgdG8gYmUgYW4gaW5jcmVhc2luZyB0cmVuZCBpbiB0aGUgZWdnIGRlcG9zaXRpb25zIGJhc2VkIG9uIG91ciBmb3JlY2FzdGluZyBvZiBBUklNQSBtb2RlbCAoMSw0LDEpIGZvciB0aGUgbmV4dCA1IHllYXJzICgxOTk3LTIwMDEpLiANCg0KDQo8YnI+DQo8YnI+DQo=