Introduction to the problem

First look at the data

library(readr)
library(TSA)
library(tseries)
library(fUnitRoots)
# Reading data
delta_ozone <- read_csv("data1.csv", col_names = FALSE)
# Renaming column
names(delta_ozone) <- c('delta')
# Converting to time series
ts_delta_ozone <- ts(delta_ozone, start = 1927, end = 2016)
# Plotting the time series
plot(ts_delta_ozone, type = 'o',
     main ="Time series plot of change in thickness of Ozone layer",
     ylab = "Change in thickness",
     xlab = "Year",
     col = c('navy'))

Figure 1: Time series plot of change in thickness of ozone layer.

Task 1: Find the best fitting model among linear, cosine, cyclical, seasonal and seasonal. Also predict yearly change for the next five years i.e. 2017 - 2021

Linear Model

Testing a simple deterministic linear model:

\[\mu = \beta_{0} + \beta_{1}t\]

# Testing a simple determininstic linear model
linear_model = lm(ts_delta_ozone~time(ts_delta_ozone))
summary(linear_model)

Call:
lm(formula = ts_delta_ozone ~ time(ts_delta_ozone))

Residuals:
    Min      1Q  Median      3Q     Max 
-4.7165 -1.6687  0.0275  1.4726  4.7940 

Coefficients:
                       Estimate Std. Error t value Pr(>|t|)    
(Intercept)          213.720155  16.257158   13.15   <2e-16 ***
time(ts_delta_ozone)  -0.110029   0.008245  -13.34   <2e-16 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 2.032 on 88 degrees of freedom
Multiple R-squared:  0.6693,    Adjusted R-squared:  0.6655 
F-statistic: 178.1 on 1 and 88 DF,  p-value: < 2.2e-16

Observations

  • \(\beta_{1} = -0.11\) has a t-value of -13.34 which means that the slope is significant and there is a clear trend in the data. This means that the slope is not constant and the time series is not stationary.
  • This simple linear model has an adjusted R-squared value of 0.6655 which means this model explains approximately 67% of variation in the change of thickness over the years.

Plot of fitted linear model

#plotting the fitted linear model
plot(ts_delta_ozone, type = 'o',
     main ="Simple Linear model for change in thickness of Ozone Layer",
     ylab = "change in thickness of Ozone Layer",
     xlab = "Year",
     col = c("navy"))
abline(linear_model, col = 'red')

Figure 2: Simple Linear model for change in thickness of Ozone Layer

  • We can clearly observe that although the linear model explains the downward trend of the change in thickness really well, but it does not do a good job of explaining the variation around this fitted line.

Analyzing the residuals of the linear model

Figure 3: Residual of linear regression model for change in ozone thickness

  • At first glance the residuals seem to be spread quite well around the mean but at the very beginning and end there is some trend of points being below the mean line. A Q-Q plot will give a clearer picture if there’s a trend and check of normality will also be done.

Q-Q plot of residuals

## Q-Q plot of the residuals for checking normality
qqnorm(y, main = "Q-Q Plot of residuals to check normality") 
qqline(y, col = 2, lwd = 2, lty = 3)

Figure 4: Q-Q Plot of residuals to check normality

  • There’s a clear drift from the the normal line in the beginning and the end just like we anticipated from the residual plot in Figure 3. Will do a Shapiro-Wilk test for the confirmation of this observation.

Conducting the Shapiro-Wilk test for checking normality

#Shapiro test for normality
shapiro.test(y)

    Shapiro-Wilk normality test

data:  y
W = 0.98733, p-value = 0.5372
  • A p-value > 0.05 confirms that the residuals are normal.

Checking residual’s ACF

Plotting Auto-correlation of the residuals of linear model

acf(y, main = "Autocorrelation plot of the residuals of linear model")

Figure 5: Autocorrelation plot of the residuals of linear model

  • It is clear from the plot that correlation at lag 1 is higher than the confidence band. This confirms that the fitted model does not give white noise as residual which indicates that there are other trends which can still be exploited for a better model.

Quadratic Model

Testing a simple deterministic quadratic model:

\[\mu_{t} = \beta_{0} + \beta_{1}t + \beta_{2}t^2\]

# Quadratic model
t = time(ts_delta_ozone)
t2 = t^2
quad_model = lm(ts_delta_ozone ~ t + t2) # creating the quadratic model
summary(quad_model) # looking at the significance of quadratic model

Call:
lm(formula = ts_delta_ozone ~ t + t2)

Residuals:
    Min      1Q  Median      3Q     Max 
-5.1062 -1.2846 -0.0055  1.3379  4.2325 

Coefficients:
              Estimate Std. Error t value Pr(>|t|)    
(Intercept) -5.733e+03  1.232e+03  -4.654 1.16e-05 ***
t            5.924e+00  1.250e+00   4.739 8.30e-06 ***
t2          -1.530e-03  3.170e-04  -4.827 5.87e-06 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 1.815 on 87 degrees of freedom
Multiple R-squared:  0.7391,    Adjusted R-squared:  0.7331 
F-statistic: 123.3 on 2 and 87 DF,  p-value: < 2.2e-16

Observations

  • All coefficients are significant and the quadratic model also has an R-squared value of 0.7331 which means the model explains approximately 73% of the variation in the change of thickness over the years.

Plot of fitted quadratic model

#plotting the quadratic curve
plot(
  ts(fitted(quad_model), start = 1927),
  ylab = 'Change in thickness of Ozone',
  main = "Quadratic model for change in thickness of Ozone Layer",
  ylim = c(-12, 3),
  col = 'red'
)
#overlay the ozone layer data
lines(ts_delta_ozone,type="o")

Figure 6: Quadratic model for change in thickness of Ozone Layer

  • The quadratic model looks a better fit than the linear model which is evident by the higher R-squared value.

Analyzing the residuals of the quadratic model

#residual analysis of quadratic model
res.quad_model = rstudent(quad_model)
plot(y = res.quad_model, x = as.vector(time(ts_delta_ozone)),
     xlab = 'Year', ylab='Standardized Residuals',type='p',
     main = "Residual of quadratic regression model for change in ozone thickness")
abline(h=mean(y), col='red')

Figure 7: Residual of quadratic regression model for change in ozone thickness

  • The variance of the model looks constant with the mean at 0

Q-Q plot of residuals

# Q-Q plot to visualize normality of residuals
y2 = res.quad_model
qqnorm(y2, main = "Q-Q Plot of residuals of quadratic model") 
qqline(y2, col = 2, lwd = 2, lty = 3)

Figure 8: Q-Q Plot of residuals of quadratic model

  • The Q-Q plot fits quite well there is still some drift around the ends but lesser than that of linear model in Figure 4. A shapiro-wilk test is needed for a final check of normality.
# Shapiro test for normality of residuals of Quadratic Model
shapiro.test(y2)

    Shapiro-Wilk normality test

data:  y2
W = 0.98889, p-value = 0.6493
  • A p-value > 0.05 means we fail to reject \(H_{0}\) that the residuals are normally distributed.

Checking residual’s ACF

Plotting Auto-correlation of the residuals of quadratic model

acf(y2, main = "Autocorrelation plot of residuals of quadratic model")

Figure 9: Autocorrelation plot of residuals of quadratic model - There is still a significant correlation at lag 1, 3 and 4, indicating there’s still some trend in the residuals.

Cyclic / Seasonal Model

  • Data is in years therefore there will be no seasonality.
  • We can check for cyclicity in the data to see if there are repeated patterns with cyclicity of 7 years.

#set the cycles frequencies
f = 7
ts_cycle =ts(ts_delta_ozone,frequency =f)

ts_plot_cycle = plot(ts_cycle, type = 'l',
                main ="Time series plot of change in thickness of Ozone layer\nin cycle of 7 years",
                ylab = "Change in Ozone thickness",
                xlab = "cycle = 7 years")
cycle = factor(rep(1:f, length.out = length(ts_cycle)), ordered = TRUE)
points(y=ts_cycle,x=time(ts_cycle), pch=as.character(cycle), col =2, cex = 1.15)

Figure 10: Time series plot of change in thickness of Ozone layer in cycle of 7 years

  • It does not look like there’s any clear pattern to cyclicity in the data.
  • The trend also does not have a constant mean, therefore the data does not follow a cosine wave pattern.

Applying a cyclic harmonic model to the data

# Simple Harmoinic model
har.<- harmonic(ts_cycle,1)
harmonic_model =lm(ts_cycle~har.)
summary(harmonic_model)

Call:
lm(formula = ts_cycle ~ har.)

Residuals:
    Min      1Q  Median      3Q     Max 
-7.8294 -1.8422  0.7481  2.4701  5.8635 

Coefficients:
                Estimate Std. Error t value Pr(>|t|)    
(Intercept)      -3.1949     0.3700  -8.636  2.5e-13 ***
har.cos(2*pi*t)   0.7386     0.5226   1.413    0.161    
har.sin(2*pi*t)  -0.2544     0.5239  -0.486    0.628    
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 3.509 on 87 degrees of freedom
Multiple R-squared:  0.02487,   Adjusted R-squared:  0.002453 
F-statistic: 1.109 on 2 and 87 DF,  p-value: 0.3344
  • The model has an R-squared value of 0.002453 which means the model only explains 0.2% of the variation in the data.
  • Also the p-values are not significant for both the harmoic terms.
  • Finally the p-value of the model is not significant enough (0.3344 > 0.05) therefore we can reject the simple cyclic model.

Applying a cyclic harmonic model with linear trend to the data

# Harmonic model with trend component
linear_harmonic_model =lm(ts_cycle~t+har.)
summary(linear_harmonic_model)

Call:
lm(formula = ts_cycle ~ t + har.)

Residuals:
    Min      1Q  Median      3Q     Max 
-4.2187 -1.6011 -0.0105  1.1970  4.2311 

Coefficients:
                  Estimate Std. Error t value Pr(>|t|)    
(Intercept)     213.141767  15.988761  13.331   <2e-16 ***
t                -0.109732   0.008109 -13.532   <2e-16 ***
har.cos(2*pi*t)   0.560458   0.297409   1.884   0.0629 .  
har.sin(2*pi*t)  -0.396451   0.298047  -1.330   0.1870    
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 1.995 on 86 degrees of freedom
Multiple R-squared:  0.6884,    Adjusted R-squared:  0.6775 
F-statistic: 63.32 on 3 and 86 DF,  p-value: < 2.2e-16
  • Even though the intercept and t have a significant p value the coefficients of harmonic terms are not significant enough to be considered.

Looking at model’s residuals

res.linear_harmonic_model = rstudent(linear_harmonic_model)
shapiro.test(res.linear_harmonic_model)

    Shapiro-Wilk normality test

data:  res.linear_harmonic_model
W = 0.98238, p-value = 0.2631
  • Although the shapiro wilk test fails to reject the \(H_{0}\) that the data is not normally distributed but the model is not the best model. Therefore no need to plot the Q-Q plot and residual plot as it will not qualify as the best model anyways.

Prediction of yearly change for next five years (2017-2021) using quadratic model

  • Since quadtratic model gave the best performance among deterministic models. We will predict the change in thickness of Ozone layer using that model.

h=5 # 5 step ahead forecasting
new_data = data.frame(t = seq((min(t)), (max(t)+h), 1))
new_data$t2 = new_data$t^2
#making the predictions
pred1 = predict(quad_model, new_data, interval = "prediction") 

#getting just the predictions for year 2017 - 2021
pred1_table = data.frame(Year = seq(2017, 2021, 1),pred1[91:95,])
colnames(pred1_table) = c("Year", "Prediction", "LowerCI", "UpperCI")
pred1_table

Plotting the forecast for next five years

#graphing it out
plot(ts_delta_ozone, type = 'o',
     main ="Forecasting 5 years ahead with quadratic model",
     ylab = "Change in thickness of Ozone",
     xlab = "Year",
     xlim=c(1927,2021),
     ylim = c(-15,4))
lines(ts(as.vector(pred1[,1]), start = 1927), col="red", type="l") 
lines(ts(as.vector(pred1[,2]), start = 1927), col="green", type="l") 
lines(ts(as.vector(pred1[,3]), start = 1927), col="green", type="l")  
legend("topright", lty=1, pch=1, col=c("black","green","red"), text.width
       = 18, 
       c("Data","5% forecast limits", "Forecasts"))

Figure 11: Forecasting 5 years ahead with quadratic model

Task 2: propose a set of possible ARIMA(p,d,q) models using all suitable model specification tools

Testing stationarity

From the linear and quadratic regression in Task 1 we have already determined that there is clear downward trend in the data, and this also implies that we have non-stationarity in the data. There will be auto regressive behaviour in the data for which we’ll do further plotting to reaffirm our assumption from initial plots.

ACF Plot


#plotting the the acf

acf(ts_delta_ozone, ci.type = 'ma', main = "ACF of yearly change in Ozone thickness")

Figure 12: ACF of yearly change in Ozone thickness

PACF plot

#plotting the the pacf

pacf(ts_delta_ozone, main = "PACF of yearly change in Ozone thickness")

Figure 13: PACF of yearly change in Ozone thickness

Observation

  • Slow decay in ACF and high value at lag 1 with sharp drop after that in in PACF plot confirm our assumption of trend. The wave like pattern in the ACF plot also hints some existence of seasonality in the data.

ADF Test

# Extracting lag
ar(ts_delta_ozone)

Call:
ar(x = ts_delta_ozone)

Coefficients:
      1        2        3        4  
 0.9807  -0.1417  -0.2581   0.2985  

Order selected 4  sigma^2 estimated as  3.242
# Conducting ADF test
adfTest(ts_delta_ozone, lags = 4, type = "nc", title = 'ADF Test: No constant nor time trend')

Title:
 ADF Test: No constant nor time trend

Test Results:
  PARAMETER:
    Lag Order: 4
  STATISTIC:
    Dickey-Fuller: 0.5699
  P VALUE:
    0.7942 

Description:
 Sun Apr 18 16:41:45 2021 by user: shekh
adfTest(ts_delta_ozone, lags = 4, type = "c", title = 'ADF Test: constant no time trend')

Title:
 ADF Test: constant no time trend

Test Results:
  PARAMETER:
    Lag Order: 4
  STATISTIC:
    Dickey-Fuller: -0.4361
  P VALUE:
    0.8924 

Description:
 Sun Apr 18 16:41:45 2021 by user: shekh
adfTest(ts_delta_ozone, lags = 4, type = "ct", title = 'ADF Test: constant and with time trend')

Title:
 ADF Test: constant and with time trend

Test Results:
  PARAMETER:
    Lag Order: 4
  STATISTIC:
    Dickey-Fuller: -3.2376
  P VALUE:
    0.0867 

Description:
 Sun Apr 18 16:41:45 2021 by user: shekh

Observation

  • The AIC of the time series gives us \(k=4\) as the best value to be used in the ADF test.
  • The p values of ADF for both No constant nor time trend and constant no time trend is greater than 0.1 if considering a 10% significance level for the test. Therefore, we fail to reject the \(H_{0}\) that data is non-stationary.
  • In the case of constant and with time trend a p-value of 0.0867 implies that we can reject the \(H_{0}\) that data is non-stationary at 10% significance but an importatnt thing to note here is that if a significance of 5% is used (the standard) we fail to reject the null hypothesis.
  • Since the results are not conclusive enough we can still assume that the data is non-stationary.

Analyzing change in variance

From the initial plots of the time series (Figure 2) we can see that the variance in the data does not change significantly. But it is worthwhile to do a check whether this inference we made just by looking at the time series is true.

#checking for Box_Cox transformation best lambda
ts_transf <-  BoxCox.ar(ts_delta_ozone+13)
title(main = "Log-likelihood versus the values of lambda")

Figure 14: Log-likelihood versus the values of lambda after BoxCox transformation

Observation

Since the confidence interval of \(\lambda\) includes the value 1 this suggests that power or log transformation is not required.

Applying Difference

We have established that there is trend in the data as well as the fact that the variance is not changing at a significant amount to apply power or log transformation, therefore we take first difference of the data.

Figure 15: First Difference of yearly changes in thickess of Ozone Layer

Observation

  • We can see that first difference has removed the trend from the data.
  • To test if the trend factor has truely been removed, we’ll perform ADF test again

ADF test on differenced data


Call:
ar(x = ts_diff)

Coefficients:
      1        2        3        4        5        6  
-0.1976  -0.2628  -0.6019  -0.3064  -0.2253  -0.3045  

Order selected 6  sigma^2 estimated as  2.232

Title:
 ADF Test with No constant nor time trend

Test Results:
  PARAMETER:
    Lag Order: 6
  STATISTIC:
    Dickey-Fuller: -5.0757
  P VALUE:
    0.01 

Description:
 Sun Apr 18 16:59:05 2021 by user: shekh


Title:
 ADF Test with constant no time trend

Test Results:
  PARAMETER:
    Lag Order: 6
  STATISTIC:
    Dickey-Fuller: -5.5901
  P VALUE:
    0.01 

Description:
 Sun Apr 18 16:59:05 2021 by user: shekh


Title:
 ADF Test with constant and with time trend

Test Results:
  PARAMETER:
    Lag Order: 6
  STATISTIC:
    Dickey-Fuller: -5.7327
  P VALUE:
    0.01 

Description:
 Sun Apr 18 16:59:05 2021 by user: shekh

Observation

  • Using \(K=6\) for the ADF test on the differenced data
  • A significant p-value of (less than 0.05) for all three cases of ADF test imply that we can reject \(H_{0}\) and confirm that the time series is stationary after applying first difference.

ACF and PACF of differenced data

# Plotting ACF and PACF of differenced data
acf(ts_diff, main = 'ACF of differenced data')

Figure 16: ACF of differenced data

Observation

  • There a diminishing oscillating pattern in the ACF plot with significat values at lag 3, 7 and 10
pacf(ts_diff, main = 'PACF of differenced data')

Figure 17: PACF of differenced data

Observation

  • Three values less than the lower bound of the significant PACF are present at lags 3, 4 and 6. But PACF at lag 3 is clearly very significant and can be used to model the data.

Possible Models

  • Since a dampened sine wave is present, there is a possibility of AR in the differenced data therefore an ARI(3,1) model can be picked because of significant values at lag 3 in PACF.
  • If we only pick significant lags from ACF and PACF then ARIMA(3,1,3) is a candidate model.
  • And finally, since all smaller models than the identified model can b picked, we can also include ARIMA(1,1,1), ARIMA(2,1,1), ARIMA(3,1,1), ARIMA(1,1,2), ARIMA(1,1,3), ARIMA(2,1,2), ARIMA(2,1,3), ARIMA(3,1,2) ARI(3,1), IMA(1,3) among the candidate models.

Using EACF to identify candidate models

#calculating the eacf
eacf(ts_diff, ar.max = 10, ma.max = 6)
AR/MA
   0 1 2 3 4 5 6
0  o o x o o o x
1  x o x o o o o
2  x o x o o o x
3  x o x o o x o
4  x o o x o x o
5  x x x x o x o
6  o o o x x o o
7  o o o x o o o
8  x x o x o o o
9  o x o x o o o
10 x o x o x o o

Observation

  • The top left vertex starts at \(p = 0\) and \(q = 3\) from there we can get an MA(1) model. Further surrounding models can also be cosidered as candidate models which are MA(4), ARMA(1,3), ARMA(1,4).

Using BIC to identfy potential models

#creating the BIC plot
There were 18 warnings (use warnings() to see them)
res = armasubsets(ts_diff, nar = 9, nma = 9, y.name='ar', ar.method = 'ols')
Reordering variables and trying again:
plot(res)
title(main = "BIC table of differenced data", line = 6)

Figure 18: BIC table of differenced data #### Observation - The BIC table’s shaded columns correspond to AR(7) and MA(6) therefore a model ARIMA(7,1,6) can also be included as potential model.

Conclusion

Bibliography

Ritchie, Hannah, and Max Roser. 2020. “Ozone Layer.” Our World in Data.

LS0tDQp0aXRsZTogIlRpbWUgU2VyaWVzIEFuYWx5c2lzOiBBc3NpZ25tZW50IDEiDQphdXRob3I6ICJTaGVraGFyIEhhemFyaSINCm91dHB1dDoNCiAgaHRtbF9ub3RlYm9vazoNCiAgICB0b2M6IFRSVUUNCi0tLQ0KDQojIEludHJvZHVjdGlvbiB0byB0aGUgcHJvYmxlbQ0KLSBXZSBoYXZlIGJlZW4gZ2l2ZW4gYSBjc3YgZmlsZSBjb250YWluaW5nIHllYXJseSBjaGFuZ2UgaW4gdGhpY2tuZXNzIG9mIE96b25lIGxheWVyIHNpbmNlIDE5MjcgdG8gMjAxNi4NCi0gQXMgVGFzayAxIG9mIHRoZSBhc3NpZ25tZW50LCB3ZSBhcmUgcmVxdWlyZWQgdG8gZmluZCB0aGUgYmVzdCBtb2RlbCBhbW9uZyBsaW5lYXIsIHF1YWRyYXRpYywgY3ljbGljYWwgYW5kIHNlYXNvbmFsIHRyZW5kIG1vZGVsIGFuZCBwcmVkaWN0IHllYXJseSBjaGFuZ2VzIGZvciB0aGUgbmV4dCA1IHllYXJzIGZyb20gMjAxNyB0byAyMDIxLg0KLSBBcyBUYXNrIDIgb2YgdGhlIGFzc2lnbWVudCwgd2UgYXJlIHJlcXVpcmVkIHRvIHByb3Bvc2UgYSBzZXQgb2YgcG9zc2libGUgQVJJTUEocCxkLHEpIG1vZGVscyB1c2luZyBhbGwgc3VpdGFibGUgbW9kZWwgc3BlY2lmaWNhdGlvbiB0b29scy4gVGhlIG1haW4gbW90aXZhdGlvbiBiZWhpbmQgdGhpcyB0YXNrIGlzIHRvIHVzZSBhbGwgbW9kZWwgc3BlY2lmaWNhdGlvbnMgc3VjaCBhcyBBQ0YtUEFDRiwgRUFDRiwgQklDIGFuZCBjbGVhcmx5IGV4cGxhaW4gdGhlIHJhdGlvbmFsZSBiZWhpbmQgdGhlIGNob2ljZXMgYmVpbmcgbWFkZSBmb3IgbW9kZWwgc2VsZWN0aW9uLg0KDQojIEZpcnN0IGxvb2sgYXQgdGhlIGRhdGENCi0gSW4gdGhlIHBsb3QgYmVsb3csIHlvdSBjYW4gc2VlIHRoZSBkYXRhLiBEYXRhIGlzIHllYXJseSBjaGFuZ2UgaW4gdGhpY2tuZXNzIG9mIE96b25lIGxheWVyIGFuZCB0aGVyZWZvcmUgYSBuZWdhdGl2ZSB2YWx1ZSByZXByZXNlbnRzIGRlY3JlYXNlIGluIHRoaWNrbmVzcyBvZiBPem9uZSBsYXllciBmcm9tIHByZXZpb3VzIHllYXIgd2hlcmVhcyBhIHBvc2l0aXZlIHZhbHVlIHJlcHJlc2VudHMgaW5jcmVhc2UgaW4gdGhpY2tuZXNzIG9mIE96b25lIGxheWVyIGZyb20gcHJldmlvdXMgeWVhci4NCg0KYGBge3Igc2V0dXAsIGluY2x1ZGU9RkFMU0V9DQprbml0cjo6b3B0c19jaHVuayRzZXQoDQoJZWNobyA9IFRSVUUsDQoJbWVzc2FnZSA9IEZBTFNFLA0KCXdhcm5pbmcgPSBGQUxTRSwNCglwYWdlZC5wcmludCA9IFRSVUUNCikNCmBgYA0KDQpgYGB7ciByZWFkX2RhdGEsIGVjaG89VFJVRSwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRSwgcGFnZWQucHJpbnQ9VFJVRX0NCmxpYnJhcnkocmVhZHIpDQpsaWJyYXJ5KFRTQSkNCmxpYnJhcnkodHNlcmllcykNCmxpYnJhcnkoZlVuaXRSb290cykNCiMgUmVhZGluZyBkYXRhDQpkZWx0YV9vem9uZSA8LSByZWFkX2NzdigiZGF0YTEuY3N2IiwgY29sX25hbWVzID0gRkFMU0UpDQojIFJlbmFtaW5nIGNvbHVtbg0KbmFtZXMoZGVsdGFfb3pvbmUpIDwtIGMoJ2RlbHRhJykNCiMgQ29udmVydGluZyB0byB0aW1lIHNlcmllcw0KdHNfZGVsdGFfb3pvbmUgPC0gdHMoZGVsdGFfb3pvbmUsIHN0YXJ0ID0gMTkyNywgZW5kID0gMjAxNikNCiMgUGxvdHRpbmcgdGhlIHRpbWUgc2VyaWVzDQpwbG90KHRzX2RlbHRhX296b25lLCB0eXBlID0gJ28nLA0KICAgICBtYWluID0iVGltZSBzZXJpZXMgcGxvdCBvZiBjaGFuZ2UgaW4gdGhpY2tuZXNzIG9mIE96b25lIGxheWVyIiwNCiAgICAgeWxhYiA9ICJDaGFuZ2UgaW4gdGhpY2tuZXNzIiwNCiAgICAgeGxhYiA9ICJZZWFyIiwNCiAgICAgY29sID0gYygnbmF2eScpKQ0KYGBgDQpGaWd1cmUgMTogVGltZSBzZXJpZXMgcGxvdCBvZiBjaGFuZ2UgaW4gdGhpY2tuZXNzIG9mIG96b25lIGxheWVyLg0KDQotIExvb2tpbmcgYXQgdGhlIGZpZ3VyZSAxIHdlIGNhbiB0ZWxsIHRoYXQgdGhlIG1lYW4gaXMgbm90IGNvbnN0YW50IGFuZCB0aGVyZSBpcyBhIGNsZWFyIGRvd253YXJkIHRyZW5kIGluIHRoZSBkYXRhLCB3aGljaCBtZWFucyB0aGUgT3pvbmUgbGF5ZXIncyB0aGlja25lc3MgaXMgZGVwbGV0aW5nIGF0IGEgZmFzdGVyIHJhdGUuDQpJbiB0aGUgZm9sbG93aW5nIHNlY3Rpb25zIHdlIHdpbGwgZGV0ZXJtaW5lIGEgbW9kZWwgdGhhdCBmaXRzIHRoZSBkYXRhIGJlc3QuDQoNCiMgVGFzayAxOiBGaW5kIHRoZSBiZXN0IGZpdHRpbmcgbW9kZWwgYW1vbmcgbGluZWFyLCBjb3NpbmUsIGN5Y2xpY2FsLCBzZWFzb25hbCBhbmQgc2Vhc29uYWwuIEFsc28gcHJlZGljdCB5ZWFybHkgY2hhbmdlIGZvciB0aGUgbmV4dCBmaXZlIHllYXJzIGkuZS4gMjAxNyAtIDIwMjENCg0KIyMgTGluZWFyIE1vZGVsDQojIyMgVGVzdGluZyBhIHNpbXBsZSBkZXRlcm1pbmlzdGljIGxpbmVhciBtb2RlbDoNCiQkXG11ID0gXGJldGFfezB9ICsgXGJldGFfezF9dCQkDQoNCmBgYHtyIFRhc2tfMS1UZXN0aW5nX2Ffc2ltcGxlX2RldGVybWluaXN0aWNfbGluZWFyX21vZGVsLCBlY2hvPVRSVUUsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0UsIHBhZ2VkLnByaW50PVRSVUV9DQojIFRlc3RpbmcgYSBzaW1wbGUgZGV0ZXJtaW5pbnN0aWMgbGluZWFyIG1vZGVsDQpsaW5lYXJfbW9kZWwgPSBsbSh0c19kZWx0YV9vem9uZX50aW1lKHRzX2RlbHRhX296b25lKSkNCnN1bW1hcnkobGluZWFyX21vZGVsKQ0KYGBgDQoNCiMjIyMgT2JzZXJ2YXRpb25zDQotICRcYmV0YV97MX0gPSAtMC4xMSQgaGFzIGEgdC12YWx1ZSBvZiAtMTMuMzQgd2hpY2ggbWVhbnMgdGhhdCB0aGUgc2xvcGUgaXMgc2lnbmlmaWNhbnQgYW5kIHRoZXJlIGlzIGEgY2xlYXIgdHJlbmQgaW4gdGhlIGRhdGEuIFRoaXMgbWVhbnMgdGhhdCB0aGUgc2xvcGUgaXMgbm90IGNvbnN0YW50IGFuZCB0aGUgdGltZSBzZXJpZXMgaXMgKm5vdCBzdGF0aW9uYXJ5Ki4NCi0gVGhpcyBzaW1wbGUgbGluZWFyIG1vZGVsIGhhcyBhbiBhZGp1c3RlZCAqUi1zcXVhcmVkKiB2YWx1ZSBvZiAwLjY2NTUgd2hpY2ggbWVhbnMgKnRoaXMgbW9kZWwgZXhwbGFpbnMgYXBwcm94aW1hdGVseSA2NyUgb2YgdmFyaWF0aW9uIGluIHRoZSBjaGFuZ2Ugb2YgdGhpY2tuZXNzIG92ZXIgdGhlIHllYXJzKi4NCg0KIyMjIyBQbG90IG9mIGZpdHRlZCBsaW5lYXIgbW9kZWwNCg0KYGBge3IgUGxvdHRpbmdfdGhlX2xpbmVhcl9tb2RlbCwgZWNobz1UUlVFLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFLCBwYWdlZC5wcmludD1UUlVFfQ0KI3Bsb3R0aW5nIHRoZSBmaXR0ZWQgbGluZWFyIG1vZGVsDQpwbG90KHRzX2RlbHRhX296b25lLCB0eXBlID0gJ28nLA0KICAgICBtYWluID0iU2ltcGxlIExpbmVhciBtb2RlbCBmb3IgY2hhbmdlIGluIHRoaWNrbmVzcyBvZiBPem9uZSBMYXllciIsDQogICAgIHlsYWIgPSAiY2hhbmdlIGluIHRoaWNrbmVzcyBvZiBPem9uZSBMYXllciIsDQogICAgIHhsYWIgPSAiWWVhciIsDQogICAgIGNvbCA9IGMoIm5hdnkiKSkNCmFibGluZShsaW5lYXJfbW9kZWwsIGNvbCA9ICdyZWQnKQ0KYGBgDQpGaWd1cmUgMjogU2ltcGxlIExpbmVhciBtb2RlbCBmb3IgY2hhbmdlIGluIHRoaWNrbmVzcyBvZiBPem9uZSBMYXllcg0KDQotIFdlIGNhbiBjbGVhcmx5IG9ic2VydmUgdGhhdCBhbHRob3VnaCB0aGUgbGluZWFyIG1vZGVsIGV4cGxhaW5zIHRoZSBkb3dud2FyZCB0cmVuZCBvZiB0aGUgY2hhbmdlIGluIHRoaWNrbmVzcyByZWFsbHkgd2VsbCwgYnV0IGl0IGRvZXMgbm90IGRvIGEgZ29vZCBqb2Igb2YgZXhwbGFpbmluZyB0aGUgdmFyaWF0aW9uIGFyb3VuZCB0aGlzIGZpdHRlZCBsaW5lLg0KDQojIyMjIEFuYWx5emluZyB0aGUgcmVzaWR1YWxzIG9mIHRoZSBsaW5lYXIgbW9kZWwNCg0KYGBge3IgQW5hbHl6aW5nX3RoZV9yZXNpZHVhbHNfb2ZfdGhlX2xpbmVhcl9tb2RlbH0NCiMgRGlzdHJpYnV0aW9uIG9mIHJlc2lkdWFscyBvZiBsaW5lYXJfbW9kZWwNCnJlcy5saW5lYXJfbW9kZWwgPSByc3R1ZGVudChsaW5lYXJfbW9kZWwpDQp5ID0gcmVzLmxpbmVhcl9tb2RlbA0KcGxvdCh5ID0geSwgeCA9IGFzLnZlY3Rvcih0aW1lKHRzX2RlbHRhX296b25lKSksDQogICAgIHhsYWIgPSAnWWVhcicsIHlsYWI9J1N0YW5kYXJkaXplZCBSZXNpZHVhbHMnLHR5cGU9J3AnLA0KICAgICBtYWluID0gIlJlc2lkdWFsIG9mIGxpbmVhciByZWdyZXNzaW9uIG1vZGVsIGZvciBjaGFuZ2UgaW4gb3pvbmUgdGhpY2tuZXNzIikNCmFibGluZShoPW1lYW4oeSksIGNvbD0ncmVkJykNCmBgYA0KRmlndXJlIDM6IFJlc2lkdWFsIG9mIGxpbmVhciByZWdyZXNzaW9uIG1vZGVsIGZvciBjaGFuZ2UgaW4gb3pvbmUgdGhpY2tuZXNzDQoNCi0gQXQgZmlyc3QgZ2xhbmNlIHRoZSByZXNpZHVhbHMgc2VlbSB0byBiZSBzcHJlYWQgcXVpdGUgd2VsbCBhcm91bmQgdGhlIG1lYW4gYnV0IGF0IHRoZSB2ZXJ5IGJlZ2lubmluZyBhbmQgZW5kIHRoZXJlIGlzIHNvbWUgdHJlbmQgb2YgcG9pbnRzIGJlaW5nIGJlbG93IHRoZSBtZWFuIGxpbmUuIEEgUS1RIHBsb3Qgd2lsbCBnaXZlIGEgY2xlYXJlciBwaWN0dXJlIGlmIHRoZXJlJ3MgYSB0cmVuZCBhbmQgY2hlY2sgb2Ygbm9ybWFsaXR5IHdpbGwgYWxzbyBiZSBkb25lLg0KDQojIyMjIFEtUSBwbG90IG9mIHJlc2lkdWFscw0KDQpgYGB7ciBDaGVja19vZl9ub3JtYWxpdHlfb2ZfdGhlIHJlc2lkdWFscywgZWNobz1UUlVFLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFLCBwYWdlZC5wcmludD1UUlVFfQ0KIyMgUS1RIHBsb3Qgb2YgdGhlIHJlc2lkdWFscyBmb3IgY2hlY2tpbmcgbm9ybWFsaXR5DQpxcW5vcm0oeSwgbWFpbiA9ICJRLVEgUGxvdCBvZiByZXNpZHVhbHMgdG8gY2hlY2sgbm9ybWFsaXR5IikgDQpxcWxpbmUoeSwgY29sID0gMiwgbHdkID0gMiwgbHR5ID0gMykNCmBgYA0KRmlndXJlIDQ6IFEtUSBQbG90IG9mIHJlc2lkdWFscyB0byBjaGVjayBub3JtYWxpdHkNCg0KLSBUaGVyZSdzIGEgY2xlYXIgZHJpZnQgZnJvbSB0aGUgdGhlIG5vcm1hbCBsaW5lIGluIHRoZSBiZWdpbm5pbmcgYW5kIHRoZSBlbmQganVzdCBsaWtlIHdlIGFudGljaXBhdGVkIGZyb20gdGhlIHJlc2lkdWFsIHBsb3QgaW4gRmlndXJlIDMuIFdpbGwgZG8gYSBTaGFwaXJvLVdpbGsgdGVzdCBmb3IgdGhlIGNvbmZpcm1hdGlvbiBvZiB0aGlzIG9ic2VydmF0aW9uLg0KDQojIyMjIENvbmR1Y3RpbmcgdGhlIFNoYXBpcm8tV2lsayB0ZXN0IGZvciBjaGVja2luZyBub3JtYWxpdHkNCg0KYGBge3Igc2hhcGlyb190ZXN0X2xpbmVhcl9tb2RlbCwgZWNobz1UUlVFLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFLCBwYWdlZC5wcmludD1UUlVFfQ0KI1NoYXBpcm8gdGVzdCBmb3Igbm9ybWFsaXR5DQpzaGFwaXJvLnRlc3QoeSkNCmBgYA0KDQotIEEgKnAtdmFsdWUgPiAwLjA1KiBjb25maXJtcyB0aGF0IHRoZSByZXNpZHVhbHMgYXJlIG5vcm1hbC4NCg0KIyMjIyBDaGVja2luZyByZXNpZHVhbCdzIEFDRg0KDQpQbG90dGluZyBBdXRvLWNvcnJlbGF0aW9uIG9mIHRoZSByZXNpZHVhbHMgb2YgbGluZWFyIG1vZGVsDQoNCmBgYHtyIGFjZl9saW5lYXJfbW9kZWxfcmVzaWR1YWxzLCBlY2hvPVRSVUUsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0UsIHBhZ2VkLnByaW50PVRSVUV9DQphY2YoeSwgbWFpbiA9ICJBdXRvY29ycmVsYXRpb24gcGxvdCBvZiB0aGUgcmVzaWR1YWxzIG9mIGxpbmVhciBtb2RlbCIpDQpgYGANCkZpZ3VyZSA1OiBBdXRvY29ycmVsYXRpb24gcGxvdCBvZiB0aGUgcmVzaWR1YWxzIG9mIGxpbmVhciBtb2RlbA0KDQotIEl0IGlzIGNsZWFyIGZyb20gdGhlIHBsb3QgdGhhdCBjb3JyZWxhdGlvbiBhdCBsYWcgMSBpcyBoaWdoZXIgdGhhbiB0aGUgY29uZmlkZW5jZSBiYW5kLiBUaGlzIGNvbmZpcm1zIHRoYXQgdGhlIGZpdHRlZCBtb2RlbCBkb2VzIG5vdCBnaXZlIHdoaXRlIG5vaXNlIGFzIHJlc2lkdWFsIHdoaWNoIGluZGljYXRlcyB0aGF0IHRoZXJlIGFyZSBvdGhlciB0cmVuZHMgd2hpY2ggY2FuIHN0aWxsIGJlIGV4cGxvaXRlZCBmb3IgYSBiZXR0ZXIgbW9kZWwuDQoNCiMjIFF1YWRyYXRpYyBNb2RlbA0KDQojIyMgVGVzdGluZyBhIHNpbXBsZSBkZXRlcm1pbmlzdGljIHF1YWRyYXRpYyBtb2RlbDoNCiQkXG11X3t0fSA9IFxiZXRhX3swfSArIFxiZXRhX3sxfXQgKyBcYmV0YV97Mn10XjIkJA0KDQpgYGB7ciBmaXR0aW5nX3F1YWRyYXRpY19tb2RlbCwgZWNobz1UUlVFLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFLCBwYWdlZC5wcmludD1UUlVFfQ0KIyBRdWFkcmF0aWMgbW9kZWwNCnQgPSB0aW1lKHRzX2RlbHRhX296b25lKQ0KdDIgPSB0XjINCnF1YWRfbW9kZWwgPSBsbSh0c19kZWx0YV9vem9uZSB+IHQgKyB0MikgIyBjcmVhdGluZyB0aGUgcXVhZHJhdGljIG1vZGVsDQpzdW1tYXJ5KHF1YWRfbW9kZWwpICMgbG9va2luZyBhdCB0aGUgc2lnbmlmaWNhbmNlIG9mIHF1YWRyYXRpYyBtb2RlbA0KYGBgDQoNCiMjIyMgT2JzZXJ2YXRpb25zDQoNCi0gQWxsIGNvZWZmaWNpZW50cyBhcmUgc2lnbmlmaWNhbnQgYW5kIHRoZSBxdWFkcmF0aWMgbW9kZWwgYWxzbyBoYXMgYW4gUi1zcXVhcmVkIHZhbHVlIG9mIDAuNzMzMSB3aGljaCBtZWFucyB0aGUgKm1vZGVsIGV4cGxhaW5zIGFwcHJveGltYXRlbHkgNzMlIG9mIHRoZSB2YXJpYXRpb24gaW4gdGhlIGNoYW5nZSBvZiB0aGlja25lc3Mgb3ZlciB0aGUgeWVhcnMqLg0KDQojIyMjIFBsb3Qgb2YgZml0dGVkIHF1YWRyYXRpYyBtb2RlbA0KDQpgYGB7ciBxdWFkcmF0aWNfY3VydmVfcGxvdCwgZWNobz1UUlVFLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFLCBwYWdlZC5wcmludD1UUlVFfQ0KI3Bsb3R0aW5nIHRoZSBxdWFkcmF0aWMgY3VydmUNCnBsb3QoDQogIHRzKGZpdHRlZChxdWFkX21vZGVsKSwgc3RhcnQgPSAxOTI3KSwNCiAgeWxhYiA9ICdDaGFuZ2UgaW4gdGhpY2tuZXNzIG9mIE96b25lJywNCiAgbWFpbiA9ICJRdWFkcmF0aWMgbW9kZWwgZm9yIGNoYW5nZSBpbiB0aGlja25lc3Mgb2YgT3pvbmUgTGF5ZXIiLA0KICB5bGltID0gYygtMTIsIDMpLA0KICBjb2wgPSAncmVkJw0KKQ0KI292ZXJsYXkgdGhlIG96b25lIGxheWVyIGRhdGENCmxpbmVzKHRzX2RlbHRhX296b25lLHR5cGU9Im8iKQ0KYGBgDQoNCkZpZ3VyZSA2OiBRdWFkcmF0aWMgbW9kZWwgZm9yIGNoYW5nZSBpbiB0aGlja25lc3Mgb2YgT3pvbmUgTGF5ZXINCg0KLSBUaGUgcXVhZHJhdGljIG1vZGVsIGxvb2tzIGEgYmV0dGVyIGZpdCB0aGFuIHRoZSBsaW5lYXIgbW9kZWwgd2hpY2ggaXMgZXZpZGVudCBieSB0aGUgaGlnaGVyIFItc3F1YXJlZCB2YWx1ZS4NCg0KIyMjIyBBbmFseXppbmcgdGhlIHJlc2lkdWFscyBvZiB0aGUgcXVhZHJhdGljIG1vZGVsDQoNCmBgYHtyIHJlc2lkdWFsc19xdWFkcmF0aWNfbW9kZWwsIGVjaG89VFJVRSwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRSwgcGFnZWQucHJpbnQ9VFJVRX0NCiNyZXNpZHVhbCBhbmFseXNpcyBvZiBxdWFkcmF0aWMgbW9kZWwNCnJlcy5xdWFkX21vZGVsID0gcnN0dWRlbnQocXVhZF9tb2RlbCkNCnBsb3QoeSA9IHJlcy5xdWFkX21vZGVsLCB4ID0gYXMudmVjdG9yKHRpbWUodHNfZGVsdGFfb3pvbmUpKSwNCiAgICAgeGxhYiA9ICdZZWFyJywgeWxhYj0nU3RhbmRhcmRpemVkIFJlc2lkdWFscycsdHlwZT0ncCcsDQogICAgIG1haW4gPSAiUmVzaWR1YWwgb2YgcXVhZHJhdGljIHJlZ3Jlc3Npb24gbW9kZWwgZm9yIGNoYW5nZSBpbiBvem9uZSB0aGlja25lc3MiKQ0KYWJsaW5lKGg9bWVhbih5KSwgY29sPSdyZWQnKQ0KYGBgDQoNCkZpZ3VyZSA3OiBSZXNpZHVhbCBvZiBxdWFkcmF0aWMgcmVncmVzc2lvbiBtb2RlbCBmb3IgY2hhbmdlIGluIG96b25lIHRoaWNrbmVzcw0KDQotIFRoZSB2YXJpYW5jZSBvZiB0aGUgbW9kZWwgbG9va3MgY29uc3RhbnQgd2l0aCB0aGUgbWVhbiBhdCAwDQoNCiMjIyMgUS1RIHBsb3Qgb2YgcmVzaWR1YWxzDQoNCmBgYHtyIHFxX3Bsb3RfcXVhZHJhdGljX21vZGVsLCBlY2hvPVRSVUUsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0UsIHBhZ2VkLnByaW50PVRSVUV9DQojIFEtUSBwbG90IHRvIHZpc3VhbGl6ZSBub3JtYWxpdHkgb2YgcmVzaWR1YWxzDQp5MiA9IHJlcy5xdWFkX21vZGVsDQpxcW5vcm0oeTIsIG1haW4gPSAiUS1RIFBsb3Qgb2YgcmVzaWR1YWxzIG9mIHF1YWRyYXRpYyBtb2RlbCIpIA0KcXFsaW5lKHkyLCBjb2wgPSAyLCBsd2QgPSAyLCBsdHkgPSAzKQ0KYGBgDQoNCkZpZ3VyZSA4OiBRLVEgUGxvdCBvZiByZXNpZHVhbHMgb2YgcXVhZHJhdGljIG1vZGVsDQoNCi0gVGhlIFEtUSBwbG90IGZpdHMgcXVpdGUgd2VsbCB0aGVyZSBpcyBzdGlsbCBzb21lIGRyaWZ0IGFyb3VuZCB0aGUgZW5kcyBidXQgbGVzc2VyIHRoYW4gdGhhdCBvZiBsaW5lYXIgbW9kZWwgaW4gRmlndXJlIDQuIEEgc2hhcGlyby13aWxrIHRlc3QgaXMgbmVlZGVkIGZvciBhIGZpbmFsIGNoZWNrIG9mIG5vcm1hbGl0eS4NCg0KYGBge3Igc2hhcGlyby13aWxrX3F1YWRyYXRpY19tb2RlbCwgZWNobz1UUlVFLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFLCBwYWdlZC5wcmludD1UUlVFfQ0KIyBTaGFwaXJvIHRlc3QgZm9yIG5vcm1hbGl0eSBvZiByZXNpZHVhbHMgb2YgUXVhZHJhdGljIE1vZGVsDQpzaGFwaXJvLnRlc3QoeTIpDQpgYGANCg0KLSBBIHAtdmFsdWUgPiAwLjA1IG1lYW5zIHdlIGZhaWwgdG8gcmVqZWN0ICRIX3swfSQgdGhhdCB0aGUgcmVzaWR1YWxzIGFyZSBub3JtYWxseSBkaXN0cmlidXRlZC4NCg0KIyMjIyBDaGVja2luZyByZXNpZHVhbCdzIEFDRg0KDQpQbG90dGluZyBBdXRvLWNvcnJlbGF0aW9uIG9mIHRoZSByZXNpZHVhbHMgb2YgcXVhZHJhdGljIG1vZGVsDQoNCmBgYHtyIGFjZl9xdWFkcmF0aWNfbW9kZWwsIGVjaG89VFJVRSwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRSwgcGFnZWQucHJpbnQ9VFJVRX0NCmFjZih5MiwgbWFpbiA9ICJBdXRvY29ycmVsYXRpb24gcGxvdCBvZiByZXNpZHVhbHMgb2YgcXVhZHJhdGljIG1vZGVsIikNCmBgYA0KDQpGaWd1cmUgOTogQXV0b2NvcnJlbGF0aW9uIHBsb3Qgb2YgcmVzaWR1YWxzIG9mIHF1YWRyYXRpYyBtb2RlbA0KLSBUaGVyZSBpcyBzdGlsbCBhIHNpZ25pZmljYW50IGNvcnJlbGF0aW9uIGF0IGxhZyAxLCAzIGFuZCA0LCBpbmRpY2F0aW5nIHRoZXJlJ3Mgc3RpbGwgc29tZSB0cmVuZCBpbiB0aGUgcmVzaWR1YWxzLg0KDQojIyBDeWNsaWMgLyBTZWFzb25hbCBNb2RlbA0KLSBEYXRhIGlzIGluIHllYXJzIHRoZXJlZm9yZSB0aGVyZSB3aWxsIGJlIG5vIHNlYXNvbmFsaXR5Lg0KLSBXZSBjYW4gY2hlY2sgZm9yIGN5Y2xpY2l0eSBpbiB0aGUgZGF0YSB0byBzZWUgaWYgdGhlcmUgYXJlIHJlcGVhdGVkIHBhdHRlcm5zIHdpdGggY3ljbGljaXR5IG9mIDcgeWVhcnMuDQoNCmBgYHtyIGN5Y2xpY2l0eV9pbl90aGVfZGF0YSwgZWNobz1UUlVFLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFLCBwYWdlZC5wcmludD1UUlVFfQ0KDQojc2V0IHRoZSBjeWNsZXMgZnJlcXVlbmNpZXMNCmYgPSA3DQp0c19jeWNsZSA9dHModHNfZGVsdGFfb3pvbmUsZnJlcXVlbmN5ID1mKQ0KDQp0c19wbG90X2N5Y2xlID0gcGxvdCh0c19jeWNsZSwgdHlwZSA9ICdsJywNCiAgICAgICAgICAgICAgICBtYWluID0iVGltZSBzZXJpZXMgcGxvdCBvZiBjaGFuZ2UgaW4gdGhpY2tuZXNzIG9mIE96b25lIGxheWVyXG5pbiBjeWNsZSBvZiA3IHllYXJzIiwNCiAgICAgICAgICAgICAgICB5bGFiID0gIkNoYW5nZSBpbiBPem9uZSB0aGlja25lc3MiLA0KICAgICAgICAgICAgICAgIHhsYWIgPSAiY3ljbGUgPSA3IHllYXJzIikNCmN5Y2xlID0gZmFjdG9yKHJlcCgxOmYsIGxlbmd0aC5vdXQgPSBsZW5ndGgodHNfY3ljbGUpKSwgb3JkZXJlZCA9IFRSVUUpDQpwb2ludHMoeT10c19jeWNsZSx4PXRpbWUodHNfY3ljbGUpLCBwY2g9YXMuY2hhcmFjdGVyKGN5Y2xlKSwgY29sID0yLCBjZXggPSAxLjE1KQ0KYGBgDQoNCkZpZ3VyZSAxMDogVGltZSBzZXJpZXMgcGxvdCBvZiBjaGFuZ2UgaW4gdGhpY2tuZXNzIG9mIE96b25lIGxheWVyIGluIGN5Y2xlIG9mIDcgeWVhcnMNCg0KLSBJdCBkb2VzIG5vdCBsb29rIGxpa2UgdGhlcmUncyBhbnkgY2xlYXIgcGF0dGVybiB0byBjeWNsaWNpdHkgaW4gdGhlIGRhdGEuDQotIFRoZSB0cmVuZCBhbHNvIGRvZXMgbm90IGhhdmUgYSBjb25zdGFudCBtZWFuLCB0aGVyZWZvcmUgdGhlIGRhdGEgZG9lcyBub3QgZm9sbG93IGEgY29zaW5lIHdhdmUgcGF0dGVybi4NCg0KIyMjIEFwcGx5aW5nIGEgY3ljbGljIGhhcm1vbmljIG1vZGVsIHRvIHRoZSBkYXRhDQoNCmBgYHtyIGhhcm1vbmljX21vZGVsLCBlY2hvPVRSVUUsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0UsIHBhZ2VkLnByaW50PVRSVUV9DQojIFNpbXBsZSBIYXJtb2luaWMgbW9kZWwNCmhhci48LSBoYXJtb25pYyh0c19jeWNsZSwxKQ0KaGFybW9uaWNfbW9kZWwgPWxtKHRzX2N5Y2xlfmhhci4pDQpzdW1tYXJ5KGhhcm1vbmljX21vZGVsKQ0KYGBgDQoNCi0gVGhlIG1vZGVsIGhhcyBhbiBSLXNxdWFyZWQgdmFsdWUgb2YgMC4wMDI0NTMgd2hpY2ggbWVhbnMgdGhlIG1vZGVsIG9ubHkgZXhwbGFpbnMgMC4yJSBvZiB0aGUgdmFyaWF0aW9uIGluIHRoZSBkYXRhLg0KLSBBbHNvIHRoZSBwLXZhbHVlcyBhcmUgbm90IHNpZ25pZmljYW50IGZvciBib3RoIHRoZSBoYXJtb2ljIHRlcm1zLg0KLSBGaW5hbGx5IHRoZSBwLXZhbHVlIG9mIHRoZSBtb2RlbCBpcyBub3Qgc2lnbmlmaWNhbnQgZW5vdWdoICgwLjMzNDQgPiAwLjA1KSB0aGVyZWZvcmUgd2UgY2FuIHJlamVjdCB0aGUgc2ltcGxlIGN5Y2xpYyBtb2RlbC4NCg0KIyMjIEFwcGx5aW5nIGEgY3ljbGljIGhhcm1vbmljIG1vZGVsIHdpdGggbGluZWFyIHRyZW5kIHRvIHRoZSBkYXRhDQoNCmBgYHtyIGxpbmVhcl9oYXJtb25pY19tb2RlbCwgZWNobz1UUlVFLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFLCBwYWdlZC5wcmludD1UUlVFfQ0KIyBIYXJtb25pYyBtb2RlbCB3aXRoIHRyZW5kIGNvbXBvbmVudA0KbGluZWFyX2hhcm1vbmljX21vZGVsID1sbSh0c19jeWNsZX50K2hhci4pDQpzdW1tYXJ5KGxpbmVhcl9oYXJtb25pY19tb2RlbCkNCmBgYA0KDQotIEV2ZW4gdGhvdWdoIHRoZSBpbnRlcmNlcHQgYW5kICp0KiBoYXZlIGEgc2lnbmlmaWNhbnQgcCB2YWx1ZSB0aGUgY29lZmZpY2llbnRzIG9mIGhhcm1vbmljIHRlcm1zIGFyZSBub3Qgc2lnbmlmaWNhbnQgZW5vdWdoIHRvIGJlIGNvbnNpZGVyZWQuDQoNCiMjIyMgTG9va2luZyBhdCBtb2RlbCdzIHJlc2lkdWFscw0KYGBge3IgbGluZWFyX2hhcm1vaW5jX21vZGVsX3Jlc2lkdWFscywgZWNobz1UUlVFLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFLCBwYWdlZC5wcmludD1UUlVFfQ0KcmVzLmxpbmVhcl9oYXJtb25pY19tb2RlbCA9IHJzdHVkZW50KGxpbmVhcl9oYXJtb25pY19tb2RlbCkNCnNoYXBpcm8udGVzdChyZXMubGluZWFyX2hhcm1vbmljX21vZGVsKQ0KYGBgDQoNCi0gQWx0aG91Z2ggdGhlIHNoYXBpcm8gd2lsayB0ZXN0IGZhaWxzIHRvIHJlamVjdCB0aGUgJEhfezB9JCB0aGF0IHRoZSBkYXRhIGlzIG5vdCBub3JtYWxseSBkaXN0cmlidXRlZCBidXQgdGhlIG1vZGVsIGlzIG5vdCB0aGUgYmVzdCBtb2RlbC4gVGhlcmVmb3JlIG5vIG5lZWQgdG8gcGxvdCB0aGUgUS1RIHBsb3QgYW5kIHJlc2lkdWFsIHBsb3QgYXMgaXQgd2lsbCBub3QgcXVhbGlmeSBhcyB0aGUgYmVzdCBtb2RlbCBhbnl3YXlzLg0KDQojIyBQcmVkaWN0aW9uIG9mIHllYXJseSBjaGFuZ2UgZm9yIG5leHQgZml2ZSB5ZWFycyAoMjAxNy0yMDIxKSB1c2luZyBxdWFkcmF0aWMgbW9kZWwNCg0KLSBTaW5jZSBxdWFkdHJhdGljIG1vZGVsIGdhdmUgdGhlIGJlc3QgcGVyZm9ybWFuY2UgYW1vbmcgZGV0ZXJtaW5pc3RpYyBtb2RlbHMuIFdlIHdpbGwgcHJlZGljdCB0aGUgY2hhbmdlIGluIHRoaWNrbmVzcyBvZiBPem9uZSBsYXllciB1c2luZyB0aGF0IG1vZGVsLg0KDQpgYGB7ciBwcmVkaWN0aW9uLCBlY2hvPVRSVUUsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0UsIHBhZ2VkLnByaW50PVRSVUV9DQoNCmg9NSAjIDUgc3RlcCBhaGVhZCBmb3JlY2FzdGluZw0KbmV3X2RhdGEgPSBkYXRhLmZyYW1lKHQgPSBzZXEoKG1pbih0KSksIChtYXgodCkraCksIDEpKQ0KbmV3X2RhdGEkdDIgPSBuZXdfZGF0YSR0XjINCiNtYWtpbmcgdGhlIHByZWRpY3Rpb25zDQpwcmVkMSA9IHByZWRpY3QocXVhZF9tb2RlbCwgbmV3X2RhdGEsIGludGVydmFsID0gInByZWRpY3Rpb24iKSANCg0KI2dldHRpbmcganVzdCB0aGUgcHJlZGljdGlvbnMgZm9yIHllYXIgMjAxNyAtIDIwMjENCnByZWQxX3RhYmxlID0gZGF0YS5mcmFtZShZZWFyID0gc2VxKDIwMTcsIDIwMjEsIDEpLHByZWQxWzkxOjk1LF0pDQpjb2xuYW1lcyhwcmVkMV90YWJsZSkgPSBjKCJZZWFyIiwgIlByZWRpY3Rpb24iLCAiTG93ZXJDSSIsICJVcHBlckNJIikNCnByZWQxX3RhYmxlDQpgYGANCg0KIyMjIyBQbG90dGluZyB0aGUgZm9yZWNhc3QgZm9yIG5leHQgZml2ZSB5ZWFycw0KYGBge3IgcGxvdF9mb3JlY2FzdCwgZWNobz1UUlVFLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFLCBwYWdlZC5wcmludD1UUlVFfQ0KI2dyYXBoaW5nIGl0IG91dA0KcGxvdCh0c19kZWx0YV9vem9uZSwgdHlwZSA9ICdvJywNCiAgICAgbWFpbiA9IkZvcmVjYXN0aW5nIDUgeWVhcnMgYWhlYWQgd2l0aCBxdWFkcmF0aWMgbW9kZWwiLA0KICAgICB5bGFiID0gIkNoYW5nZSBpbiB0aGlja25lc3Mgb2YgT3pvbmUiLA0KICAgICB4bGFiID0gIlllYXIiLA0KICAgICB4bGltPWMoMTkyNywyMDIxKSwNCiAgICAgeWxpbSA9IGMoLTE1LDQpKQ0KbGluZXModHMoYXMudmVjdG9yKHByZWQxWywxXSksIHN0YXJ0ID0gMTkyNyksIGNvbD0icmVkIiwgdHlwZT0ibCIpIA0KbGluZXModHMoYXMudmVjdG9yKHByZWQxWywyXSksIHN0YXJ0ID0gMTkyNyksIGNvbD0iZ3JlZW4iLCB0eXBlPSJsIikgDQpsaW5lcyh0cyhhcy52ZWN0b3IocHJlZDFbLDNdKSwgc3RhcnQgPSAxOTI3KSwgY29sPSJncmVlbiIsIHR5cGU9ImwiKSAgDQpsZWdlbmQoInRvcHJpZ2h0IiwgbHR5PTEsIHBjaD0xLCBjb2w9YygiYmxhY2siLCJncmVlbiIsInJlZCIpLCB0ZXh0LndpZHRoDQogICAgICAgPSAxOCwgDQogICAgICAgYygiRGF0YSIsIjUlIGZvcmVjYXN0IGxpbWl0cyIsICJGb3JlY2FzdHMiKSkNCg0KYGBgDQoNCkZpZ3VyZSAxMTogRm9yZWNhc3RpbmcgNSB5ZWFycyBhaGVhZCB3aXRoIHF1YWRyYXRpYyBtb2RlbA0KDQojIFRhc2sgMjogcHJvcG9zZSBhIHNldCBvZiBwb3NzaWJsZSBBUklNQShwLGQscSkgbW9kZWxzIHVzaW5nIGFsbCBzdWl0YWJsZSBtb2RlbCBzcGVjaWZpY2F0aW9uIHRvb2xzDQoNCiMjIFRlc3Rpbmcgc3RhdGlvbmFyaXR5DQpGcm9tIHRoZSBsaW5lYXIgYW5kIHF1YWRyYXRpYyByZWdyZXNzaW9uIGluIFRhc2sgMSB3ZSBoYXZlIGFscmVhZHkgZGV0ZXJtaW5lZCB0aGF0IHRoZXJlIGlzIGNsZWFyIGRvd253YXJkIHRyZW5kIGluIHRoZSBkYXRhLCBhbmQgdGhpcyBhbHNvIGltcGxpZXMgdGhhdCB3ZSBoYXZlIG5vbi1zdGF0aW9uYXJpdHkgaW4gdGhlIGRhdGEuIFRoZXJlIHdpbGwgYmUgYXV0byByZWdyZXNzaXZlIGJlaGF2aW91ciBpbiB0aGUgZGF0YSBmb3Igd2hpY2ggd2UnbGwgZG8gZnVydGhlciBwbG90dGluZyB0byByZWFmZmlybSBvdXIgYXNzdW1wdGlvbiBmcm9tIGluaXRpYWwgcGxvdHMuDQoNCiMjIyBBQ0YgUGxvdA0KDQpgYGB7ciBBQ0ZfcGxvdCwgZWNobz1UUlVFLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFLCBwYWdlZC5wcmludD1UUlVFfQ0KDQojcGxvdHRpbmcgdGhlIHRoZSBhY2YNCg0KYWNmKHRzX2RlbHRhX296b25lLCBjaS50eXBlID0gJ21hJywgbWFpbiA9ICJBQ0Ygb2YgeWVhcmx5IGNoYW5nZSBpbiBPem9uZSB0aGlja25lc3MiKQ0KDQpgYGANCkZpZ3VyZSAxMjogQUNGIG9mIHllYXJseSBjaGFuZ2UgaW4gT3pvbmUgdGhpY2tuZXNzDQoNCiMjIyBQQUNGIHBsb3QNCg0KYGBge3IgcGFjZl9wbG90LCBlY2hvPVRSVUUsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0UsIHBhZ2VkLnByaW50PVRSVUV9DQojcGxvdHRpbmcgdGhlIHRoZSBwYWNmDQoNCnBhY2YodHNfZGVsdGFfb3pvbmUsIG1haW4gPSAiUEFDRiBvZiB5ZWFybHkgY2hhbmdlIGluIE96b25lIHRoaWNrbmVzcyIpDQoNCmBgYA0KDQpGaWd1cmUgMTM6IFBBQ0Ygb2YgeWVhcmx5IGNoYW5nZSBpbiBPem9uZSB0aGlja25lc3MNCg0KIyMjIyBPYnNlcnZhdGlvbg0KLSBTbG93IGRlY2F5IGluIEFDRiBhbmQgaGlnaCB2YWx1ZSBhdCBsYWcgMSB3aXRoIHNoYXJwIGRyb3AgYWZ0ZXIgdGhhdCBpbiBpbiBQQUNGIHBsb3QgY29uZmlybSBvdXIgYXNzdW1wdGlvbiBvZiB0cmVuZC4gVGhlIHdhdmUgbGlrZSBwYXR0ZXJuIGluIHRoZSBBQ0YgcGxvdCBhbHNvIGhpbnRzIHNvbWUgZXhpc3RlbmNlIG9mIHNlYXNvbmFsaXR5IGluIHRoZSBkYXRhLg0KDQojIyMgQURGIFRlc3QNCg0KYGBge3IgQURGX3Rlc3QsIGVjaG89VFJVRSwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRSwgcGFnZWQucHJpbnQ9VFJVRX0NCiMgRXh0cmFjdGluZyBsYWcNCmFyKHRzX2RlbHRhX296b25lKQ0KDQojIENvbmR1Y3RpbmcgQURGIHRlc3QNCmFkZlRlc3QodHNfZGVsdGFfb3pvbmUsIGxhZ3MgPSA0LCB0eXBlID0gIm5jIiwgdGl0bGUgPSAnQURGIFRlc3Q6IE5vIGNvbnN0YW50IG5vciB0aW1lIHRyZW5kJykNCmFkZlRlc3QodHNfZGVsdGFfb3pvbmUsIGxhZ3MgPSA0LCB0eXBlID0gImMiLCB0aXRsZSA9ICdBREYgVGVzdDogY29uc3RhbnQgbm8gdGltZSB0cmVuZCcpDQphZGZUZXN0KHRzX2RlbHRhX296b25lLCBsYWdzID0gNCwgdHlwZSA9ICJjdCIsIHRpdGxlID0gJ0FERiBUZXN0OiBjb25zdGFudCBhbmQgd2l0aCB0aW1lIHRyZW5kJykNCmBgYA0KDQojIyMjIE9ic2VydmF0aW9uDQotIFRoZSBBSUMgb2YgdGhlIHRpbWUgc2VyaWVzIGdpdmVzIHVzICRrPTQkIGFzIHRoZSBiZXN0IHZhbHVlIHRvIGJlIHVzZWQgaW4gdGhlIEFERiB0ZXN0Lg0KLSBUaGUgcCB2YWx1ZXMgb2YgQURGIGZvciBib3RoICpObyBjb25zdGFudCBub3IgdGltZSB0cmVuZCogYW5kICpjb25zdGFudCBubyB0aW1lIHRyZW5kKiBpcyBncmVhdGVyIHRoYW4gMC4xIGlmIGNvbnNpZGVyaW5nIGEgMTAlIHNpZ25pZmljYW5jZSBsZXZlbCBmb3IgdGhlIHRlc3QuIFRoZXJlZm9yZSwgd2UgZmFpbCB0byByZWplY3QgdGhlICRIX3swfSQgdGhhdCBkYXRhIGlzIG5vbi1zdGF0aW9uYXJ5Lg0KLSBJbiB0aGUgY2FzZSBvZiAqY29uc3RhbnQgYW5kIHdpdGggdGltZSB0cmVuZCogYSBwLXZhbHVlIG9mIDAuMDg2NyBpbXBsaWVzIHRoYXQgd2UgY2FuIHJlamVjdCB0aGUgJEhfezB9JCB0aGF0IGRhdGEgaXMgbm9uLXN0YXRpb25hcnkgYXQgMTAlIHNpZ25pZmljYW5jZSBidXQgYW4gaW1wb3J0YXRudCB0aGluZyB0byBub3RlIGhlcmUgaXMgdGhhdCBpZiBhIHNpZ25pZmljYW5jZSBvZiA1JSBpcyB1c2VkICh0aGUgc3RhbmRhcmQpIHdlIGZhaWwgdG8gcmVqZWN0IHRoZSBudWxsIGh5cG90aGVzaXMuDQotIFNpbmNlIHRoZSByZXN1bHRzIGFyZSBub3QgY29uY2x1c2l2ZSBlbm91Z2ggd2UgY2FuIHN0aWxsIGFzc3VtZSB0aGF0IHRoZSBkYXRhIGlzIG5vbi1zdGF0aW9uYXJ5Lg0KDQojIyBBbmFseXppbmcgY2hhbmdlIGluIHZhcmlhbmNlDQoNCkZyb20gdGhlIGluaXRpYWwgcGxvdHMgb2YgdGhlIHRpbWUgc2VyaWVzIChGaWd1cmUgMikgd2UgY2FuIHNlZSB0aGF0IHRoZSB2YXJpYW5jZSBpbiB0aGUgZGF0YSBkb2VzIG5vdCBjaGFuZ2Ugc2lnbmlmaWNhbnRseS4gQnV0IGl0IGlzIHdvcnRod2hpbGUgdG8gZG8gYSBjaGVjayB3aGV0aGVyIHRoaXMgaW5mZXJlbmNlIHdlIG1hZGUganVzdCBieSBsb29raW5nIGF0IHRoZSB0aW1lIHNlcmllcyBpcyB0cnVlLg0KDQpgYGB7ciB0cmFuc2Zvcm1hdGlvbiwgZWNobz1UUlVFLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFLCBwYWdlZC5wcmludD1UUlVFfQ0KIyBjaGVja2luZyBiZXN0IGxhbWJkYSB1c2luZyBCb3hfQ294IHRyYW5zZm9ybWF0aW9uDQp0c190cmFuc2YgPC0gIEJveENveC5hcih0c19kZWx0YV9vem9uZSsxMykNCnRpdGxlKG1haW4gPSAiTG9nLWxpa2VsaWhvb2QgdmVyc3VzIHRoZSB2YWx1ZXMgb2YgbGFtYmRhIGFmdGVyIEJveENveCB0cmFuc2Zvcm1hdGlvbiIpDQpgYGANCg0KRmlndXJlIDE0OiBMb2ctbGlrZWxpaG9vZCB2ZXJzdXMgdGhlIHZhbHVlcyBvZiBsYW1iZGEgYWZ0ZXIgQm94Q294IHRyYW5zZm9ybWF0aW9uDQoNCiMjIyMgT2JzZXJ2YXRpb24NClNpbmNlIHRoZSBjb25maWRlbmNlIGludGVydmFsIG9mICRcbGFtYmRhJCBpbmNsdWRlcyB0aGUgdmFsdWUgMSB0aGlzIHN1Z2dlc3RzIHRoYXQgcG93ZXIgb3IgbG9nIHRyYW5zZm9ybWF0aW9uIGlzIG5vdCByZXF1aXJlZC4NCg0KIyMgQXBwbHlpbmcgRGlmZmVyZW5jZQ0KV2UgaGF2ZSBlc3RhYmxpc2hlZCB0aGF0IHRoZXJlIGlzIHRyZW5kIGluIHRoZSBkYXRhIGFzIHdlbGwgYXMgdGhlIGZhY3QgdGhhdCB0aGUgdmFyaWFuY2UgaXMgbm90IGNoYW5naW5nIGF0IGEgc2lnbmlmaWNhbnQgYW1vdW50IHRvIGFwcGx5IHBvd2VyIG9yIGxvZyB0cmFuc2Zvcm1hdGlvbiwgdGhlcmVmb3JlIHdlIHRha2UgZmlyc3QgZGlmZmVyZW5jZSBvZiB0aGUgZGF0YS4NCg0KYGBge3IgZGlmZmVyZW5jZWRfZGF0YSwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRSwgcGFnZWQucHJpbnQ9VFJVRX0NCiMgUGxvdHRpbmcgZmlyc3QgZGlmZmVyZW5jZQ0KdHNfZGlmZiA9IGRpZmYodHNfZGVsdGFfb3pvbmUpDQpwbG90KHRzX2RpZmYsIHR5cGUgPSAnbycsDQogICAgIG1haW4gPSJGaXJzdCBEaWZmZXJlbmNlIG9mIHllYXJseSBjaGFuZ2VzIGluIHRoaWNrZXNzIG9mIE96b25lIExheWVyIiwNCiAgICAgeWxhYiA9ICJDaGFuZ2UgaW4gdGhpY2tlc3Mgb2YgT3pvbmUgTGF5ZXIiLA0KICAgICB4bGFiID0gIlllYXIiKQ0KYGBgDQpGaWd1cmUgMTU6IEZpcnN0IERpZmZlcmVuY2Ugb2YgeWVhcmx5IGNoYW5nZXMgaW4gdGhpY2tlc3Mgb2YgT3pvbmUgTGF5ZXINCg0KIyMjIyBPYnNlcnZhdGlvbg0KLSBXZSBjYW4gc2VlIHRoYXQgZmlyc3QgZGlmZmVyZW5jZSBoYXMgcmVtb3ZlZCB0aGUgdHJlbmQgZnJvbSB0aGUgZGF0YS4NCi0gVG8gdGVzdCBpZiB0aGUgdHJlbmQgZmFjdG9yIGhhcyB0cnVlbHkgYmVlbiByZW1vdmVkLCB3ZSdsbCBwZXJmb3JtIEFERiB0ZXN0IGFnYWluDQoNCiMjIyBBREYgdGVzdCBvbiBkaWZmZXJlbmNlZCBkYXRhDQoNCmBgYHtyIEFERl9kaWZmZXJlbmNlZF9kYXRhLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFLCBwYWdlZC5wcmludD1UUlVFfQ0KI2dldHRpbmcgdGhlIGxhZyB0byB1c2UgaW4gdGhlIEFERiB0ZXN0DQphcih0c19kaWZmKQ0KDQojY29uZHVjdGluZyB0aGUgYWRmIHRlc3QNCmFkZlRlc3QodHNfZGlmZiwgbGFncyA9IDYsIHR5cGUgPSAibmMiLCB0aXRsZSA9ICdBREYgVGVzdCB3aXRoIE5vIGNvbnN0YW50IG5vciB0aW1lIHRyZW5kJykNCmFkZlRlc3QodHNfZGlmZiwgbGFncyA9IDYsIHR5cGUgPSAiYyIsIHRpdGxlID0gJ0FERiBUZXN0IHdpdGggY29uc3RhbnQgbm8gdGltZSB0cmVuZCcpDQphZGZUZXN0KHRzX2RpZmYsIGxhZ3MgPSA2LCB0eXBlID0gImN0IiwgdGl0bGUgPSAnQURGIFRlc3Qgd2l0aCBjb25zdGFudCBhbmQgd2l0aCB0aW1lIHRyZW5kJykNCmBgYA0KDQojIyMjIE9ic2VydmF0aW9uDQotIFVzaW5nICRLPTYkIGZvciB0aGUgQURGIHRlc3Qgb24gdGhlIGRpZmZlcmVuY2VkIGRhdGENCi0gQSBzaWduaWZpY2FudCBwLXZhbHVlIG9mIChsZXNzIHRoYW4gMC4wNSkgZm9yIGFsbCB0aHJlZSBjYXNlcyBvZiBBREYgdGVzdCBpbXBseSB0aGF0IHdlIGNhbiByZWplY3QgJEhfezB9JCBhbmQgY29uZmlybSB0aGF0IHRoZSB0aW1lIHNlcmllcyBpcyBzdGF0aW9uYXJ5IGFmdGVyIGFwcGx5aW5nIGZpcnN0IGRpZmZlcmVuY2UuDQoNCiMjIyBBQ0YgYW5kIFBBQ0Ygb2YgZGlmZmVyZW5jZWQgZGF0YQ0KDQpgYGB7ciBBQ0ZfZGlmZmVyZW5jZWRfZGF0YSwgZWNobz1UUlVFLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFLCBwYWdlZC5wcmludD1UUlVFfQ0KIyBQbG90dGluZyBBQ0YgYW5kIFBBQ0Ygb2YgZGlmZmVyZW5jZWQgZGF0YQ0KYWNmKHRzX2RpZmYsIG1haW4gPSAnQUNGIG9mIGRpZmZlcmVuY2VkIGRhdGEnKQ0KYGBgDQpGaWd1cmUgMTY6IEFDRiBvZiBkaWZmZXJlbmNlZCBkYXRhDQoNCiMjIyMgT2JzZXJ2YXRpb24NCi0gVGhlcmUgYSBkaW1pbmlzaGluZyBvc2NpbGxhdGluZyBwYXR0ZXJuIGluIHRoZSBBQ0YgcGxvdCB3aXRoIHNpZ25pZmljYXQgdmFsdWVzIGF0IGxhZyAzLCA3IGFuZCAxMA0KDQpgYGB7ciBQQUNGX2RpZmZlcmVuY2VkX2RhdGEsIGVjaG89VFJVRSwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRSwgcGFnZWQucHJpbnQ9VFJVRX0NCnBhY2YodHNfZGlmZiwgbWFpbiA9ICdQQUNGIG9mIGRpZmZlcmVuY2VkIGRhdGEnKQ0KYGBgDQoNCkZpZ3VyZSAxNzogUEFDRiBvZiBkaWZmZXJlbmNlZCBkYXRhDQoNCiMjIyMgT2JzZXJ2YXRpb24NCi0gVGhyZWUgdmFsdWVzIGxlc3MgdGhhbiB0aGUgbG93ZXIgYm91bmQgb2YgdGhlIHNpZ25pZmljYW50IFBBQ0YgYXJlIHByZXNlbnQgYXQgbGFncyAzLCA0IGFuZCA2LiBCdXQgUEFDRiBhdCBsYWcgMyBpcyBjbGVhcmx5IHZlcnkgc2lnbmlmaWNhbnQgYW5kIGNhbiBiZSB1c2VkIHRvIG1vZGVsIHRoZSBkYXRhLg0KDQojIyBQb3NzaWJsZSBNb2RlbHMNCg0KLSBTaW5jZSBhIGRhbXBlbmVkIHNpbmUgd2F2ZSBpcyBwcmVzZW50LCB0aGVyZSBpcyBhIHBvc3NpYmlsaXR5IG9mIEFSIGluIHRoZSBkaWZmZXJlbmNlZCBkYXRhIHRoZXJlZm9yZSBhbiBBUkkoMywxKSBtb2RlbCBjYW4gYmUgcGlja2VkIGJlY2F1c2Ugb2Ygc2lnbmlmaWNhbnQgdmFsdWVzIGF0IGxhZyAzIGluIFBBQ0YuDQotIElmIHdlIG9ubHkgcGljayBzaWduaWZpY2FudCBsYWdzIGZyb20gQUNGIGFuZCBQQUNGIHRoZW4gQVJJTUEoMywxLDMpIGlzIGEgY2FuZGlkYXRlIG1vZGVsLg0KLSBBbmQgZmluYWxseSwgc2luY2UgYWxsIHNtYWxsZXIgbW9kZWxzIHRoYW4gdGhlIGlkZW50aWZpZWQgbW9kZWwgY2FuIGIgcGlja2VkLCB3ZSBjYW4gYWxzbyBpbmNsdWRlIEFSSU1BKDEsMSwxKSwgQVJJTUEoMiwxLDEpLCBBUklNQSgzLDEsMSksIEFSSU1BKDEsMSwyKSwgQVJJTUEoMSwxLDMpLCBBUklNQSgyLDEsMiksIEFSSU1BKDIsMSwzKSwgQVJJTUEoMywxLDIpIEFSSSgzLDEpLCBJTUEoMSwzKSBhbW9uZyB0aGUgY2FuZGlkYXRlIG1vZGVscy4NCg0KIyMgVXNpbmcgRUFDRiB0byBpZGVudGlmeSBjYW5kaWRhdGUgbW9kZWxzDQpgYGB7ciBFQUNGX2Zvcl9jYW5kaWRhdGVfbW9kZWxzLCBlY2hvPVRSVUUsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0UsIHBhZ2VkLnByaW50PVRSVUV9DQojY2FsY3VsYXRpbmcgdGhlIGVhY2YNCmVhY2YodHNfZGlmZiwgYXIubWF4ID0gMTAsIG1hLm1heCA9IDYpDQpgYGANCg0KIyMjIyBPYnNlcnZhdGlvbg0KLSBUaGUgdG9wIGxlZnQgdmVydGV4IHN0YXJ0cyBhdCAkcCA9IDAkIGFuZCAkcSA9IDMkIGZyb20gdGhlcmUgd2UgY2FuIGdldCBhbiBNQSgxKSBtb2RlbC4gRnVydGhlciBzdXJyb3VuZGluZyBtb2RlbHMgY2FuIGFsc28gYmUgY29zaWRlcmVkIGFzIGNhbmRpZGF0ZSBtb2RlbHMgd2hpY2ggYXJlIE1BKDQpLCBBUk1BKDEsMyksIEFSTUEoMSw0KS4NCg0KIyMgVXNpbmcgQklDIHRvIGlkZW50ZnkgcG90ZW50aWFsIG1vZGVscw0KYGBge3IgQklDX2Zvcl9pZGVudGlmeWluZ19jYW5kaWRhdGVfbW9kZWxzLCBlY2hvPVRSVUUsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0UsIHBhZ2VkLnByaW50PVRSVUV9DQojY3JlYXRpbmcgdGhlIEJJQyBwbG90DQpyZXMgPSBhcm1hc3Vic2V0cyh0c19kaWZmLCBuYXIgPSA5LCBubWEgPSA5LCB5Lm5hbWU9J2FyJywgYXIubWV0aG9kID0gJ29scycpDQpwbG90KHJlcykNCnRpdGxlKG1haW4gPSAiQklDIHRhYmxlIG9mIGRpZmZlcmVuY2VkIGRhdGEiLCBsaW5lID0gNikNCmBgYA0KDQpGaWd1cmUgMTg6IEJJQyB0YWJsZSBvZiBkaWZmZXJlbmNlZCBkYXRhDQojIyMjIE9ic2VydmF0aW9uDQotIFRoZSBCSUMgdGFibGUncyBzaGFkZWQgY29sdW1ucyBjb3JyZXNwb25kIHRvIEFSKDcpIGFuZCBNQSg2KSB0aGVyZWZvcmUgYSBtb2RlbCBBUklNQSg3LDEsNikgY2FuIGFsc28gYmUgaW5jbHVkZWQgYXMgcG90ZW50aWFsIG1vZGVsLg0KDQojIENvbmNsdXNpb24NCi0gVGhlIGJlc3QgZGV0ZXJtaW5pc3RpYyBtb2RlbCBmcm9tIFRhc2sgb25lIHdhcyBxdWFkcmF0aWMgbW9kZWwgZm9yIHByZWRpY3Rpb24gb2YgY2hhbmdlIGluIE96b25lIGxheWVyJ3MgdGhpY2tuZXNzIGluIHllYXJzIDIwMTctMjAyMQ0KLSBBbW9uZyBzdG9jaGFzdGljIG1vZGVscyB0aGUgZm9sbG93aW5nIG1vZGVscyBoYXZlIGJlZW4gaWRlbnRpZmllZCBhcyBwb3RlbnRpYWwgY2FuZGlkYXRlIG1vZGVsczogQVJJTUEoMywxLDMpLCBBUklNQSgxLDEsMSksIEFSSU1BKDIsMSwxKSwgQVJJTUEoMywxLDEpLCBBUklNQSgxLDEsMiksIEFSSU1BKDEsMSwzKSwgQVJJTUEoMiwxLDIpLCBBUklNQSgyLDEsMyksIEFSSU1BKDMsMSwyKSwgQVJJKDMsMSksIElNQSgxLDMpLCBNQSg0KSwgQVJNQSgxLDMpLCBBUk1BKDEsNCkgYW5kIEFSSU1BKDcsMSw2KQ0KLSBXZSBjYW4gcGVyZm9ybSBmdXJ0aGVyIHRlc3RzIHRvIGRldGVybWluZSB0aGUgYmVzdCBtb2RlbCBvdXQgb2YgY2FuZGlkYXRlIG1vZGVscywgYnV0IHRoYXQgaXMgYmV5b25kIHRoZSBzY29wZSBvZiB0aGlzIGFzc2lnbm1lbnQuDQoNCiMgQmlibGlvZ3JhcGh5DQpSaXRjaGllLCBIYW5uYWgsIGFuZCBNYXggUm9zZXIuIDIwMjAuIOKAnE96b25lIExheWVyLuKAnSBPdXIgV29ybGQgaW4gRGF0YS4=