Diagnosing Autocorrelated Errors

In Lectures 32/33 we used trend, seasonal terms and weather predictors to explain the mean response through time. A fitted curve can follow the data quite closely and still leave several consecutive observations above it, followed by several below it.

If today’s response is higher than the model predicts, does that tell us anything about tomorrow’s deviation? If it does, treating those observations as independent gives us the wrong calculation of precision.

By the end of this lecture, students should be able to:

  1. Define lagged autocorrelation and distinguish errors from residuals.
  2. Use a variance calculation to explain why dependence changes precision.
  3. Explain and use residual plots, runs tests, Durbin-Watson, ACF plots, and Ljung-Box tests.
  4. Recognise when dependence remains after a reasonable mean model has been fitted.

What Is Autocorrelation?

Write our regression model as

\[Y_t = \mu_t + \varepsilon_t, \qquad \mu_t = \mathbf{x}_t^\top\boldsymbol{\beta}.\]

The predictors in \(\mathbf{x}_t\) describe the mean. Autocorrelation describes a relationship between errors at different times, after accounting for that mean.

We cannot observe \(\varepsilon_t\), because we do not know the true mean. We work with the fitted residuals

\[e_t = y_t - \widehat{\mu}_t.\]

A high \(R^2\) describes how closely the fitted values track the responses. It does not tell us whether the remaining deviations are related through time.

What Does a Lag Mean?

Lag \(k\) means a separation of \(k\) observation intervals. For quarterly data, lag 1 is one quarter and lag 4 is one year. The observations must be equally spaced for this interpretation.

Suppose the errors have constant variance \(\sigma^2\) and their covariance depends on the time gap, rather than the calendar date. Then

\[\rho_k = \operatorname{Corr}(\varepsilon_t,\varepsilon_{t-k}) = \frac{\operatorname{Cov}(\varepsilon_t,\varepsilon_{t-k})}{\sigma^2}.\]

A Classical Example: Consumer Expenditure and Money Stock

This example studies consumer expenditure (ConsExp) and the stock of money (MoneyStk) in billions of US dollars.

Download MoneyStock.csv

MoneyStock <- read.csv("../data/MoneyStock.csv", header = TRUE)
MoneyStock |>
    head() |>
    kable()
Year Quarter ConsExp MoneyStk Year.Q
1952 1 214.6 159.3 1952.00
1952 2 217.7 161.2 1952.25
1952 3 219.6 162.8 1952.50
1952 4 227.2 164.6 1952.75
1953 1 230.9 165.9 1953.00
1953 2 233.3 167.9 1953.25
pairs(MoneyStock[3:5])

unlabelled

Fit the Regression Model

For quarter \(t\), we fit

\[\mathrm{ConsExp}_t = \beta_0 + \beta_1\mathrm{MoneyStk}_t + \varepsilon_t.\]

MoneyStock_lm1 <- lm(ConsExp ~ MoneyStk, data = MoneyStock)
summary(MoneyStock_lm1)

Call:
lm(formula = ConsExp ~ MoneyStk, data = MoneyStock)

Residuals:
   Min     1Q Median     3Q    Max 
-7.176 -3.396  1.396  2.928  6.361 

Coefficients:
             Estimate Std. Error t value Pr(>|t|)    
(Intercept) -154.7192    19.8500  -7.794 3.54e-07 ***
MoneyStk       2.3004     0.1146  20.080 8.99e-14 ***
---
Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1

Residual standard error: 3.983 on 18 degrees of freedom
Multiple R-squared:  0.9573,    Adjusted R-squared:  0.9549 
F-statistic: 403.2 on 1 and 18 DF,  p-value: 8.988e-14

MoneyStk and ConsExp have a strong linear association: \(R^2\) is about 0.96. The reported slope also looks precise. That precision calculation assumes that knowing the error in one quarter tells us nothing about another quarter’s error.

Residual Plot Over Time

Before running a test, follow the residuals from left to right. Look for stretches above or below zero, alternation, and any remaining trend or seasonal pattern.

plot(residuals(MoneyStock_lm1), type = "b", ylab = "Residuals", xlab = "Quarter")
abline(h = 0, lty = 2)

unlabelled

The residuals wander slowly above and below zero. Adjacent quarters often have deviations in the same direction. Some runs occur by chance even with independent errors; we need to judge whether this much persistence is plausible.

Why Dependence Changes Precision

Start with a simpler calculation. Suppose two observations measure the same mean \(\mu\), each with error variance \(\sigma^2\) and correlation \(\rho\). Their average has variance

\[\begin{aligned} \operatorname{Var}\left(\frac{Y_1+Y_2}{2}\right) &= \frac{1}{4}\left[\operatorname{Var}(Y_1)+\operatorname{Var}(Y_2) +2\operatorname{Cov}(Y_1,Y_2)\right] \\ &= \frac{\sigma^2}{2}(1+\rho). \end{aligned}\]

With independent errors, \(\rho=0\) and averaging halves the variance. With \(\rho=0.8\), the variance is \(0.9\sigma^2\): the second observation adds little precision because the two errors tend to move together.

The standard error is then \(\sqrt{1.8}\approx1.34\) times the value calculated under independence. Counting two observations does not give us two independent pieces of information.

What Changes in Regression?

Remember the matrix form \(\mathbf{Y}=X\boldsymbol{\beta}+\boldsymbol{\varepsilon}\). Treating \(X\) as fixed, let \(\Sigma=\operatorname{Var}(\boldsymbol{\varepsilon}\mid X)\). The OLS estimate still satisfies

\[\widehat{\boldsymbol{\beta}}=\boldsymbol{\beta}+(X^\top X)^{-1}X^\top\boldsymbol{\varepsilon}.\]

Its variance is

\[\operatorname{Var}(\widehat{\boldsymbol{\beta}}\mid X) =(X^\top X)^{-1}X^\top\Sigma X(X^\top X)^{-1}.\]

Independent errors with equal variance give \(\Sigma=\sigma^2 I\), reducing this to \(\sigma^2(X^\top X)^{-1}\). Autocorrelation introduces non-zero off-diagonal covariances into \(\Sigma\).

If \(E(\boldsymbol{\varepsilon}\mid X)=\mathbf{0}\), OLS remains unbiased. The usual standard errors can still be wrong, so the reported confidence intervals and tests become unreliable. For regression coefficients, the direction of that error depends on both the predictors and the dependence pattern.

Diagnostic Tools

We have seen a pattern that could make our precision calculation unreliable. Each diagnostic summarises a different feature of that pattern.

Diagnostic Question about the ordered residuals
Runs test Do residuals stay on the same side of their median unusually long, or switch sides unusually often?
Durbin-Watson How different is each residual from the one immediately before it?
ACF How strong is the correlation at each time gap?
Ljung-Box Is there evidence of correlation across a chosen group of lags?

Keep the time order. Rearranging observations leaves the fitted regression unchanged but changes these diagnostics. Also check the mean model: a missing trend or seasonal term can produce a residual pattern of its own.

Runs Test

A run is an uninterrupted sequence on the same side of a threshold. For example, \(+++\;--\;++\;-\) contains four runs, although it contains eight observations.

The default RunsTest() divides numerical residuals at their median. Write \(n_+\) for the number above the median and \(n_-\) for the number at or below it. Under random ordering, the expected number of runs is

\[E(R)=1+\frac{2n_+n_-}{n_++n_-}.\]

Too few runs indicate clustering on the same side; too many indicate excessive alternation. The test compares the observed count with its distribution under random ordering.

Runs in the MoneyStock Residuals

There are ten residuals on each side of the median, so under random ordering we expect

\[E(R)=1+\frac{2(10)(10)}{20}=11\text{ runs}.\]

RunsTest(residuals(MoneyStock_lm1))

    Runs Test for Randomness

data:  residuals(MoneyStock_lm1)
runs = 5, m = 10, n = 10, p-value = 0.008985
alternative hypothesis: true number of runs is not equal the expected number
sample estimates:
median(x) 
 1.395704 

We observe only five runs, with \(P\approx0.009\). This supports the impression of long stretches on the same side. The default test is two-sided, so it can detect either unusually few or unusually many runs. It does not measure the size of the residuals or identify the process producing them.

Durbin-Watson Test

Runs use only which side each residual falls on. Durbin-Watson uses the sizes of the changes between neighbouring residuals:

\[d=\frac{\sum_{t=2}^{n}(e_t-e_{t-1})^2}{\sum_{t=1}^{n}e_t^2}.\]

The denominator measures the overall residual variation. The numerator measures how much residuals change from one observation to the next.

These values guide interpretation; they are not significance cut-offs.

Durbin-Watson for MoneyStock

We test \(H_0:\rho_1=0\) against \(H_A:\rho_1>0\). The one-sided alternative targets the positive autocorrelation suggested by the time plot.

dwtest(MoneyStock_lm1, alternative = "greater")

    Durbin-Watson test

data:  MoneyStock_lm1
DW = 0.32821, p-value = 2.303e-08
alternative hypothesis: true autocorrelation is greater than 0

The statistic is \(d\approx0.33\), with a very small P-value. The residuals change much less between adjacent quarters than we would expect from their overall variation.

In dwtest(), alternative = "greater" refers to correlation greater than zero. Evidence for that alternative comes from a small value of \(d\). The test’s reference distribution accounts for the regression predictors; we do not simply declare every value below 2 significant.

Measuring Correlation at Each Lag

Durbin-Watson focuses on neighbouring observations. The autocorrelation function (ACF) lets us examine longer gaps as well. The sample autocorrelation at lag \(k\) is

\[r_k=\frac{\sum_{t=k+1}^{n}(e_t-\bar e)(e_{t-k}-\bar e)} {\sum_{t=1}^{n}(e_t-\bar e)^2}.\]

The numerator pairs residuals \(k\) observations apart. Products are positive when both deviations from \(\bar e\) have the same sign, and negative when they have opposite signs. The denominator puts the result on a correlation scale. Lag 0 is always 1.

For OLS with an intercept, \(\bar e=0\) apart from numerical rounding. Expanding the squared differences in Durbin-Watson then gives

\[d=2(1-r_1)-\frac{e_1^2+e_n^2}{\sum_{t=1}^{n}e_t^2} \approx2(1-r_1).\]

The approximation drops the two endpoint terms. It can be noticeably different in a short series, so use it to understand the direction of \(d\), rather than to replace the calculation.

ACF Plot

acf(residuals(MoneyStock_lm1), main = "ACF of MoneyStock residuals")

unlabelled

The lag-1 value is about 0.75, and positive correlation persists across several quarters. This agrees with the slow movement in the time plot. We should also check whether a missing time trend could explain part of it.

Reading the ACF Reference Lines

Under an uncorrelated white-noise reference model, the default approximate 95% reference limits at an individual non-zero lag are

\[\pm\frac{1.96}{\sqrt n}.\]

Here \(n=20\), giving limits of about \(\pm0.44\). The lag-1 correlation is well outside them. A sequence of large correlations deserves more attention than one isolated bar just beyond a line.

These are approximate, pointwise limits, not a simultaneous 95% band for the whole plot. With many lags, some bars can cross by chance. Fitting the regression also affects the behaviour of its residuals, so treat the lines as a visual reference. The acf() plotting documentation describes the white-noise assumption behind them.

Ljung-Box Test

If several ACF bars look large, we can combine them. For a chosen maximum lag \(m\), the hypotheses are

\[H_0:\rho_1=\cdots=\rho_m=0, \qquad H_A:\text{at least one of these correlations is non-zero}.\]

The Ljung-Box statistic is

\[Q=n(n+2)\sum_{k=1}^{m}\frac{r_k^2}{n-k}.\]

Squaring prevents positive and negative correlations from cancelling. Larger correlations give a larger \(Q\) and more evidence against the null hypothesis. Choose \(m\) using the time scale and the available sample size, before inspecting a collection of P-values.

Ljung-Box for MoneyStock

Here we use \(m=10\), combining correlations over gaps from one to ten quarters.

Box.test(residuals(MoneyStock_lm1), lag = 10, type = "Ljung-Box")

    Box-Ljung test

data:  residuals(MoneyStock_lm1)
X-squared = 64.397, df = 10, p-value = 5.286e-10

We obtain \(Q\approx64.4\) and a very small P-value. With the default fitdf = 0, Box.test() compares this with an approximate \(\chi^2_{10}\) distribution.

There are only 20 observations here, and the residuals come from an estimated regression, so treat that P-value as an approximate diagnostic summary. The time plot, runs test and Durbin-Watson already give substantial evidence of persistence. This result does not establish that every lag is correlated or tell us which change to the model will address it.

Work Through the Diagnostics

1. If \(d=0.6\), what lag-1 correlation does \(d\approx2(1-r_1)\) suggest?

. . .

Rearranging gives \(r_1\approx1-d/2=0.7\), suggesting strong positive correlation between neighbours. This is an approximation, not a P-value.

. . .

2. If \(r_1=0\) but \(r_4\) is large, which diagnostic displays that pattern, and which can test a group of lags containing it?

. . .

The ACF displays the lag-4 correlation. Ljung-Box with \(m\geq4\) includes it in a joint test; a lag-1 diagnostic alone can miss it.

. . .

3. Why would shuffling complete rows of MoneyStock leave the coefficients and \(R^2\) unchanged but alter the residual diagnostics?

. . .

OLS minimises the same sum of squares after reordering. Runs, neighbouring differences and lagged products depend on which observations follow one another, so the diagnostics need the actual time order.

A Modern Comparison: Seoul Bike Residuals

The same diagnostic logic applies to the richer daily bike model from Lectures 32/33, which combined two Fourier pairs with the time trend and weather predictors.

Download seoul_bike_daily.csv

seoul_daily <- read_csv("../data/seoul_bike_daily.csv", show_col_types = FALSE) |>
    mutate(date = as.Date(date)) |>
    arrange(date) |>
    filter(functioning_day_all == "yes") |>
    mutate(S1 = sin(2 * pi * day_index/365), C1 = cos(2 * pi * day_index/365), S2 = sin(4 *
        pi * day_index/365), C2 = cos(4 * pi * day_index/365))

seoul_mean <- lm(rented_bike_count ~ day_index + S1 + C1 + S2 + C2 + mean_temperature +
    total_rainfall + total_solar_radiation, data = seoul_daily)

seoul_diagnostics <- seoul_daily |>
    mutate(residual = residuals(seoul_mean))

unlabelled

We fitted the mean model to all 352 functioning days. The dates remain visible here, including the gaps left by 13 outage days.

Seoul: One Uninterrupted Period

For the daily diagnostics, select the longest uninterrupted period: 1 December 2017 through 10 April 2018. Otherwise, an ordinary ACF would treat consecutive retained rows as though they were always one day apart.

Refit the same mean formula on these 131 consecutive days. All four diagnostics below use residuals from this refitted model, so the Durbin-Watson test and the other summaries refer to the same observations and fit.

seoul_run_data <- seoul_daily |>
    filter(date >= as.Date("2017-12-01"), date <= as.Date("2018-04-10"))

seoul_run_model <- update(seoul_mean, data = seoul_run_data)
seoul_run_residuals <- residuals(seoul_run_model)

Seoul: Runs Above and Below the Median

Divide the residuals at their median, 126.6 bikes. Each uninterrupted colour block is one run.

Sequence of Seoul residuals above and at or below their median, with each colour block marking one run

There are 65 residuals above the median and 66 at or below it. Compare the actual run count with \(E(R)=1+2n_+n_-/n\).

seoul_runs <- RunsTest(seoul_run_residuals)
Observed runs Expected runs Test statistic z P-value
55 66.5 -1.93 0.0537

The count is 55 runs; \(z\) standardises its departure from the expected count, with a continuity correction. The two-sided P-value is just above 0.05. This test uses only the median-side sequence, so it can miss dependence visible in the residual magnitudes.

Seoul: Durbin-Watson

Use the sizes of the changes between consecutive daily residuals:

\[d=\frac{\sum_{t=2}^{n}(e_t-e_{t-1})^2}{\sum_{t=1}^{n}e_t^2} =\frac{609135793}{453162261} \approx 1.34.\]

seoul_dw <- dwtest(seoul_run_model, alternative = "greater")
seoul_dw

    Durbin-Watson test

data:  seoul_run_model
DW = 1.3442, p-value = 7.693e-06
alternative hypothesis: true autocorrelation is greater than 0

The statistic is below 2, with strong evidence against \(H_0:\rho_1=0\) in favour of positive autocorrelation. Unlike the runs test, Durbin-Watson uses how far neighbouring residuals move, as well as their direction.

Seoul: ACF of the Daily Residuals

acf(seoul_run_residuals, main = "ACF of Seoul residuals: refitted on consecutive days")

unlabelled

The lag-1 correlation is \(r_1\approx 0.327\). The approximate pointwise reference limits are

\[\pm\frac{1.96}{\sqrt{131}}\approx\pm 0.171.\]

Neighbouring daily residuals remain positively correlated after refitting the mean. Read the other lags from the plot as well; the reference lines are approximate and do not form a simultaneous band.

Seoul: Ljung-Box Across Two Weeks

Combine the correlations at lags 1 through 14, rather than testing only neighbouring days:

\[Q=n(n+2)\sum_{k=1}^{14}\frac{r_k^2}{n-k}.\]

seoul_ljung_box <- Box.test(seoul_run_residuals, lag = 14, type = "Ljung-Box")
Statistic Q Reference df P-value
45.19 14 3.79e-05

The small P-value gives evidence of remaining autocorrelation across these lags. It does not imply that every lag is correlated. This is an approximate diagnostic on fitted regression residuals, using the default fitdf = 0.

The runs test gave weaker evidence because it discarded residual magnitudes. Taken together, the time plot, Durbin-Watson, ACF and Ljung-Box suggest that refitting the mean has not removed the dependence. These results concern the 131-day fit, rather than establishing adequacy over the entire gappy year.

Diagnostic Summary

The time plot comes first, then the ACF. The runs test, Durbin-Watson and Ljung-Box each summarise a different feature of the ordered residuals, so a collection of small P-values supports what we can already see in the plots. None of them identifies the error process that produced the pattern.

Before changing the error model, check the mean: a missing trend, seasonal term or outage can leave a residual pattern of its own. For both MoneyStock and Seoul we fitted reasonable mean models and the dependence remained, so we treat it as part of the errors and model it directly.

Looking Ahead

Every model we have fitted this semester assumed independent errors. Flexible curves, factors and weights changed the mean or the variance; the correlation between errors never entered the model. After this lecture we know how to detect that correlation, and in MoneyStock and Seoul it is clearly there.

Next lecture we model it. An AR(1) error model, fitted by generalised least squares (GLS), keeps the mean formula and adds a correlation structure to the errors instead. We will fit the tourism model with gls() and corAR1(), compare the standard errors with the ordinary fit, and check whether the normalised residuals look closer to white noise.

LS0tDQp0aXRsZTogIkxlY3R1cmUgMzQ6IERpYWdub3NpbmcgQXV0b2NvcnJlbGF0ZWQgRXJyb3JzIg0Kc3VidGl0bGU6IDE2MS4yNTEgUmVncmVzc2lvbiBNb2RlbGxpbmcNCmF1dGhvcjogIlByZXNlbnRlZCBieSBOaWNrIEtub3dsdG9uIDxOLktub3dsdG9uQG1hc3NleS5hYy5uej4iICANCmRhdGU6ICJXZWVrIDEyIG9mIFNlbWVzdGVyIDIsIGByIGx1YnJpZGF0ZTo6eWVhcihsdWJyaWRhdGU6Om5vdygpKWAiDQpvdXRwdXQ6DQogIGh0bWxfZG9jdW1lbnQ6DQogICAgY29kZV9kb3dubG9hZDogdHJ1ZQ0KICAgIHRoZW1lOiB5ZXRpDQogICAgaGlnaGxpZ2h0X3N0eWxlOiBweWdtZW50cw0KICBodG1sX25vdGVib29rOg0KICAgIGNvZGVfZG93bmxvYWQ6IHRydWUNCiAgICB0aGVtZTogeWV0aQ0KICAgIGhpZ2hsaWdodF9zdHlsZTogcHlnbWVudHMNCiAgaW9zbGlkZXNfcHJlc2VudGF0aW9uOg0KICAgIHdpZGVzY3JlZW46IHRydWUNCiAgICBzbWFsbGVyOiB0cnVlDQogIHdvcmRfZG9jdW1lbnQ6IGRlZmF1bHQNCiAgc2xpZHlfcHJlc2VudGF0aW9uOiANCiAgICB0aGVtZTogeWV0aQ0KICAgIGhpZ2hsaWdodF9zdHlsZTogcHlnbWVudHMNCiAgcGRmX2RvY3VtZW50OiBkZWZhdWx0DQotLS0NCg0KDQoNCg0KPCEtLS0gRGF0YSBpcyBvbg0KaHR0cHM6Ly9yLXJlc291cmNlcy5tYXNzZXkuYWMubnovZGF0YS8xNjEyNTEvDQotLS0+DQoNCmBgYHtyIHNldHVwLCBwdXJsPUZBTFNFLCBpbmNsdWRlPUZBTFNFfQ0KbGlicmFyeShrbml0cikNCm9wdHNfY2h1bmskc2V0KGRldj1jKCJwbmciLCAicGRmIikpDQpvcHRzX2NodW5rJHNldChmaWcuaGVpZ2h0PTYsIGZpZy53aWR0aD03LCBmaWcucGF0aD0iRmlndXJlcy8iLCBmaWcuYWx0PSJ1bmxhYmVsbGVkIikNCm9wdHNfY2h1bmskc2V0KGNvbW1lbnQ9IiIsIGZpZy5hbGlnbj0iY2VudGVyIiwgdGlkeT1UUlVFKQ0Kb3B0aW9ucyhrbml0ci5rYWJsZS5OQSA9ICcnKQ0KbGlicmFyeSh0aWR5dmVyc2UpDQpsaWJyYXJ5KGJyb29tKQ0KYGBgDQoNCg0KPCEtLS0gRG8gbm90IGVkaXQgYW55dGhpbmcgYWJvdmUgdGhpcyBsaW5lLiAtLS0+DQoNCmBgYHtyIGRpYWdub3NpbmctYXV0b2NvcnJlbGF0aW9uLXNldHVwLCBpbmNsdWRlPUZBTFNFfQ0KbGlicmFyeShEZXNjVG9vbHMpDQpsaWJyYXJ5KGxtdGVzdCkNCmBgYA0KDQojIyBEaWFnbm9zaW5nIEF1dG9jb3JyZWxhdGVkIEVycm9ycw0KDQpJbiBMZWN0dXJlcyAzMi8zMyB3ZSB1c2VkIHRyZW5kLCBzZWFzb25hbCB0ZXJtcyBhbmQgd2VhdGhlciBwcmVkaWN0b3JzIHRvIGV4cGxhaW4gdGhlIG1lYW4gcmVzcG9uc2UgdGhyb3VnaCB0aW1lLiBBIGZpdHRlZCBjdXJ2ZSBjYW4gZm9sbG93IHRoZSBkYXRhIHF1aXRlIGNsb3NlbHkgYW5kIHN0aWxsIGxlYXZlIHNldmVyYWwgY29uc2VjdXRpdmUgb2JzZXJ2YXRpb25zIGFib3ZlIGl0LCBmb2xsb3dlZCBieSBzZXZlcmFsIGJlbG93IGl0Lg0KDQpJZiB0b2RheSdzIHJlc3BvbnNlIGlzIGhpZ2hlciB0aGFuIHRoZSBtb2RlbCBwcmVkaWN0cywgZG9lcyB0aGF0IHRlbGwgdXMgYW55dGhpbmcgYWJvdXQgdG9tb3Jyb3cncyBkZXZpYXRpb24/IElmIGl0IGRvZXMsIHRyZWF0aW5nIHRob3NlIG9ic2VydmF0aW9ucyBhcyBpbmRlcGVuZGVudCBnaXZlcyB1cyB0aGUgd3JvbmcgY2FsY3VsYXRpb24gb2YgcHJlY2lzaW9uLg0KDQpCeSB0aGUgZW5kIG9mIHRoaXMgbGVjdHVyZSwgc3R1ZGVudHMgc2hvdWxkIGJlIGFibGUgdG86DQoNCjEuIERlZmluZSBsYWdnZWQgYXV0b2NvcnJlbGF0aW9uIGFuZCBkaXN0aW5ndWlzaCBlcnJvcnMgZnJvbSByZXNpZHVhbHMuDQoyLiBVc2UgYSB2YXJpYW5jZSBjYWxjdWxhdGlvbiB0byBleHBsYWluIHdoeSBkZXBlbmRlbmNlIGNoYW5nZXMgcHJlY2lzaW9uLg0KMy4gRXhwbGFpbiBhbmQgdXNlIHJlc2lkdWFsIHBsb3RzLCBydW5zIHRlc3RzLCBEdXJiaW4tV2F0c29uLCBBQ0YgcGxvdHMsIGFuZCBManVuZy1Cb3ggdGVzdHMuDQo0LiBSZWNvZ25pc2Ugd2hlbiBkZXBlbmRlbmNlIHJlbWFpbnMgYWZ0ZXIgYSByZWFzb25hYmxlIG1lYW4gbW9kZWwgaGFzIGJlZW4gZml0dGVkLg0KDQojIyBXaGF0IElzIEF1dG9jb3JyZWxhdGlvbj8NCg0KV3JpdGUgb3VyIHJlZ3Jlc3Npb24gbW9kZWwgYXMNCg0KJCRZX3QgPSBcbXVfdCArIFx2YXJlcHNpbG9uX3QsIFxxcXVhZCBcbXVfdCA9IFxtYXRoYmZ7eH1fdF5cdG9wXGJvbGRzeW1ib2x7XGJldGF9LiQkDQoNClRoZSBwcmVkaWN0b3JzIGluICRcbWF0aGJme3h9X3QkIGRlc2NyaWJlIHRoZSBtZWFuLiBBdXRvY29ycmVsYXRpb24gZGVzY3JpYmVzIGEgcmVsYXRpb25zaGlwIGJldHdlZW4gZXJyb3JzIGF0IGRpZmZlcmVudCB0aW1lcywgYWZ0ZXIgYWNjb3VudGluZyBmb3IgdGhhdCBtZWFuLg0KDQpXZSBjYW5ub3Qgb2JzZXJ2ZSAkXHZhcmVwc2lsb25fdCQsIGJlY2F1c2Ugd2UgZG8gbm90IGtub3cgdGhlIHRydWUgbWVhbi4gV2Ugd29yayB3aXRoIHRoZSBmaXR0ZWQgcmVzaWR1YWxzDQoNCiQkZV90ID0geV90IC0gXHdpZGVoYXR7XG11fV90LiQkDQoNCkEgaGlnaCAkUl4yJCBkZXNjcmliZXMgaG93IGNsb3NlbHkgdGhlIGZpdHRlZCB2YWx1ZXMgdHJhY2sgdGhlIHJlc3BvbnNlcy4gSXQgZG9lcyBub3QgdGVsbCB1cyB3aGV0aGVyIHRoZSByZW1haW5pbmcgZGV2aWF0aW9ucyBhcmUgcmVsYXRlZCB0aHJvdWdoIHRpbWUuDQoNCiMjIFdoYXQgRG9lcyBhIExhZyBNZWFuPw0KDQoqKkxhZyAkayQqKiBtZWFucyBhIHNlcGFyYXRpb24gb2YgJGskIG9ic2VydmF0aW9uIGludGVydmFscy4gRm9yIHF1YXJ0ZXJseSBkYXRhLCBsYWcgMSBpcyBvbmUgcXVhcnRlciBhbmQgbGFnIDQgaXMgb25lIHllYXIuIFRoZSBvYnNlcnZhdGlvbnMgbXVzdCBiZSBlcXVhbGx5IHNwYWNlZCBmb3IgdGhpcyBpbnRlcnByZXRhdGlvbi4NCg0KU3VwcG9zZSB0aGUgZXJyb3JzIGhhdmUgY29uc3RhbnQgdmFyaWFuY2UgJFxzaWdtYV4yJCBhbmQgdGhlaXIgY292YXJpYW5jZSBkZXBlbmRzIG9uIHRoZSB0aW1lIGdhcCwgcmF0aGVyIHRoYW4gdGhlIGNhbGVuZGFyIGRhdGUuIFRoZW4NCg0KJCRccmhvX2sgPSBcb3BlcmF0b3JuYW1le0NvcnJ9KFx2YXJlcHNpbG9uX3QsXHZhcmVwc2lsb25fe3Qta30pDQo9IFxmcmFje1xvcGVyYXRvcm5hbWV7Q292fShcdmFyZXBzaWxvbl90LFx2YXJlcHNpbG9uX3t0LWt9KX17XHNpZ21hXjJ9LiQkDQoNCi0gJFxyaG9fMSA+IDAkOiBuZWFyYnkgZXJyb3JzIHRlbmQgdG8gaGF2ZSB0aGUgc2FtZSBzaWduLCBwcm9kdWNpbmcgcGVyc2lzdGVudCBydW5zLg0KLSAkXHJob18xIDwgMCQ6IG5lYXJieSBlcnJvcnMgdGVuZCB0byBhbHRlcm5hdGUgaW4gc2lnbi4NCi0gSW5kZXBlbmRlbnQgZXJyb3JzIGhhdmUgJFxyaG9fayA9IDAkIGZvciBldmVyeSAkayA+IDAkLiBaZXJvIGNvcnJlbGF0aW9uIGFsb25lIGRvZXMgbm90IGVzdGFibGlzaCBpbmRlcGVuZGVuY2UuDQoNCiMjIEEgQ2xhc3NpY2FsIEV4YW1wbGU6IENvbnN1bWVyIEV4cGVuZGl0dXJlIGFuZCBNb25leSBTdG9jaw0KDQpUaGlzIGV4YW1wbGUgc3R1ZGllcyBjb25zdW1lciBleHBlbmRpdHVyZSAoYENvbnNFeHBgKSBhbmQgdGhlIHN0b2NrIG9mIG1vbmV5IChgTW9uZXlTdGtgKSBpbiBiaWxsaW9ucyBvZiBVUyBkb2xsYXJzLg0KDQpgciB4ZnVuOjplbWJlZF9maWxlKCIuLi9kYXRhL01vbmV5U3RvY2suY3N2IilgDQoNCjo6Ojogey5jb2x1bW5zIC5tb25leS1zdG9jay1sYXlvdXR9DQo6Ojogey5jb2x1bW4gc3R5bGU9IndpZHRoOiAxMDAlOyJ9DQoNCmBgYHtyIHJlYWQtbW9uZXktc3RvY2t9DQpNb25leVN0b2NrIDwtIHJlYWQuY3N2KCIuLi9kYXRhL01vbmV5U3RvY2suY3N2IiwgaGVhZGVyID0gVFJVRSkNCk1vbmV5U3RvY2sgfD4gaGVhZCgpIHw+IGthYmxlKCkNCmBgYA0KDQo6OjoNCg0KOjo6IHsuY29sdW1uIHN0eWxlPSJ3aWR0aDogMTAwJTsifQ0KDQpgYGB7ciBtb25leS1zdG9jay1wYWlyc30NCnBhaXJzKE1vbmV5U3RvY2tbMzo1XSkNCmBgYA0KDQo6OjoNCjo6OjoNCg0KIyMgRml0IHRoZSBSZWdyZXNzaW9uIE1vZGVsDQoNCkZvciBxdWFydGVyICR0JCwgd2UgZml0DQoNCiQkXG1hdGhybXtDb25zRXhwfV90ID0gXGJldGFfMCArIFxiZXRhXzFcbWF0aHJte01vbmV5U3RrfV90ICsgXHZhcmVwc2lsb25fdC4kJA0KDQpgYGB7ciBtb25leS1zdG9jay1yZWdyZXNzaW9ufQ0KTW9uZXlTdG9ja19sbTEgPC0gbG0oQ29uc0V4cCB+IE1vbmV5U3RrLCBkYXRhID0gTW9uZXlTdG9jaykNCnN1bW1hcnkoTW9uZXlTdG9ja19sbTEpDQpgYGANCg0KYE1vbmV5U3RrYCBhbmQgYENvbnNFeHBgIGhhdmUgYSBzdHJvbmcgbGluZWFyIGFzc29jaWF0aW9uOiAkUl4yJCBpcyBhYm91dCAwLjk2LiBUaGUgcmVwb3J0ZWQgc2xvcGUgYWxzbyBsb29rcyBwcmVjaXNlLiBUaGF0IHByZWNpc2lvbiBjYWxjdWxhdGlvbiBhc3N1bWVzIHRoYXQga25vd2luZyB0aGUgZXJyb3IgaW4gb25lIHF1YXJ0ZXIgdGVsbHMgdXMgbm90aGluZyBhYm91dCBhbm90aGVyIHF1YXJ0ZXIncyBlcnJvci4NCg0KIyMgUmVzaWR1YWwgUGxvdCBPdmVyIFRpbWUNCg0KQmVmb3JlIHJ1bm5pbmcgYSB0ZXN0LCBmb2xsb3cgdGhlIHJlc2lkdWFscyBmcm9tIGxlZnQgdG8gcmlnaHQuIExvb2sgZm9yIHN0cmV0Y2hlcyBhYm92ZSBvciBiZWxvdyB6ZXJvLCBhbHRlcm5hdGlvbiwgYW5kIGFueSByZW1haW5pbmcgdHJlbmQgb3Igc2Vhc29uYWwgcGF0dGVybi4NCg0KYGBge3IgbW9uZXktc3RvY2stcmVzaWR1YWwtcGxvdH0NCnBsb3QocmVzaWR1YWxzKE1vbmV5U3RvY2tfbG0xKSwgdHlwZSA9ICJiIiwgeWxhYiA9ICJSZXNpZHVhbHMiLCB4bGFiID0gIlF1YXJ0ZXIiKQ0KYWJsaW5lKGggPSAwLCBsdHkgPSAyKQ0KYGBgDQoNClRoZSByZXNpZHVhbHMgd2FuZGVyIHNsb3dseSBhYm92ZSBhbmQgYmVsb3cgemVyby4gQWRqYWNlbnQgcXVhcnRlcnMgb2Z0ZW4gaGF2ZSBkZXZpYXRpb25zIGluIHRoZSBzYW1lIGRpcmVjdGlvbi4gU29tZSBydW5zIG9jY3VyIGJ5IGNoYW5jZSBldmVuIHdpdGggaW5kZXBlbmRlbnQgZXJyb3JzOyB3ZSBuZWVkIHRvIGp1ZGdlIHdoZXRoZXIgdGhpcyBtdWNoIHBlcnNpc3RlbmNlIGlzIHBsYXVzaWJsZS4NCg0KIyMgV2h5IERlcGVuZGVuY2UgQ2hhbmdlcyBQcmVjaXNpb24NCg0KU3RhcnQgd2l0aCBhIHNpbXBsZXIgY2FsY3VsYXRpb24uIFN1cHBvc2UgdHdvIG9ic2VydmF0aW9ucyBtZWFzdXJlIHRoZSBzYW1lIG1lYW4gJFxtdSQsIGVhY2ggd2l0aCBlcnJvciB2YXJpYW5jZSAkXHNpZ21hXjIkIGFuZCBjb3JyZWxhdGlvbiAkXHJobyQuIFRoZWlyIGF2ZXJhZ2UgaGFzIHZhcmlhbmNlDQoNCiQkXGJlZ2lue2FsaWduZWR9DQpcb3BlcmF0b3JuYW1le1Zhcn1cbGVmdChcZnJhY3tZXzErWV8yfXsyfVxyaWdodCkNCiY9IFxmcmFjezF9ezR9XGxlZnRbXG9wZXJhdG9ybmFtZXtWYXJ9KFlfMSkrXG9wZXJhdG9ybmFtZXtWYXJ9KFlfMikNCiAgKzJcb3BlcmF0b3JuYW1le0Nvdn0oWV8xLFlfMilccmlnaHRdIFxcDQomPSBcZnJhY3tcc2lnbWFeMn17Mn0oMStccmhvKS4NClxlbmR7YWxpZ25lZH0kJA0KDQpXaXRoIGluZGVwZW5kZW50IGVycm9ycywgJFxyaG89MCQgYW5kIGF2ZXJhZ2luZyBoYWx2ZXMgdGhlIHZhcmlhbmNlLiBXaXRoICRccmhvPTAuOCQsIHRoZSB2YXJpYW5jZSBpcyAkMC45XHNpZ21hXjIkOiB0aGUgc2Vjb25kIG9ic2VydmF0aW9uIGFkZHMgbGl0dGxlIHByZWNpc2lvbiBiZWNhdXNlIHRoZSB0d28gZXJyb3JzIHRlbmQgdG8gbW92ZSB0b2dldGhlci4NCg0KVGhlIHN0YW5kYXJkIGVycm9yIGlzIHRoZW4gJFxzcXJ0ezEuOH1cYXBwcm94MS4zNCQgdGltZXMgdGhlIHZhbHVlIGNhbGN1bGF0ZWQgdW5kZXIgaW5kZXBlbmRlbmNlLiBDb3VudGluZyB0d28gb2JzZXJ2YXRpb25zIGRvZXMgbm90IGdpdmUgdXMgdHdvIGluZGVwZW5kZW50IHBpZWNlcyBvZiBpbmZvcm1hdGlvbi4NCg0KIyMgV2hhdCBDaGFuZ2VzIGluIFJlZ3Jlc3Npb24/DQoNClJlbWVtYmVyIHRoZSBtYXRyaXggZm9ybSAkXG1hdGhiZntZfT1YXGJvbGRzeW1ib2x7XGJldGF9K1xib2xkc3ltYm9se1x2YXJlcHNpbG9ufSQuIFRyZWF0aW5nICRYJCBhcyBmaXhlZCwgbGV0ICRcU2lnbWE9XG9wZXJhdG9ybmFtZXtWYXJ9KFxib2xkc3ltYm9se1x2YXJlcHNpbG9ufVxtaWQgWCkkLiBUaGUgT0xTIGVzdGltYXRlIHN0aWxsIHNhdGlzZmllcw0KDQokJFx3aWRlaGF0e1xib2xkc3ltYm9se1xiZXRhfX09XGJvbGRzeW1ib2x7XGJldGF9KyhYXlx0b3AgWCleey0xfVheXHRvcFxib2xkc3ltYm9se1x2YXJlcHNpbG9ufS4kJA0KDQpJdHMgdmFyaWFuY2UgaXMNCg0KJCRcb3BlcmF0b3JuYW1le1Zhcn0oXHdpZGVoYXR7XGJvbGRzeW1ib2x7XGJldGF9fVxtaWQgWCkNCj0oWF5cdG9wIFgpXnstMX1YXlx0b3BcU2lnbWEgWChYXlx0b3AgWCleey0xfS4kJA0KDQpJbmRlcGVuZGVudCBlcnJvcnMgd2l0aCBlcXVhbCB2YXJpYW5jZSBnaXZlICRcU2lnbWE9XHNpZ21hXjIgSSQsIHJlZHVjaW5nIHRoaXMgdG8gJFxzaWdtYV4yKFheXHRvcCBYKV57LTF9JC4gQXV0b2NvcnJlbGF0aW9uIGludHJvZHVjZXMgbm9uLXplcm8gb2ZmLWRpYWdvbmFsIGNvdmFyaWFuY2VzIGludG8gJFxTaWdtYSQuDQoNCklmICRFKFxib2xkc3ltYm9se1x2YXJlcHNpbG9ufVxtaWQgWCk9XG1hdGhiZnswfSQsIE9MUyByZW1haW5zIHVuYmlhc2VkLiBUaGUgdXN1YWwgc3RhbmRhcmQgZXJyb3JzIGNhbiBzdGlsbCBiZSB3cm9uZywgc28gdGhlIHJlcG9ydGVkIGNvbmZpZGVuY2UgaW50ZXJ2YWxzIGFuZCB0ZXN0cyBiZWNvbWUgdW5yZWxpYWJsZS4gRm9yIHJlZ3Jlc3Npb24gY29lZmZpY2llbnRzLCB0aGUgZGlyZWN0aW9uIG9mIHRoYXQgZXJyb3IgZGVwZW5kcyBvbiBib3RoIHRoZSBwcmVkaWN0b3JzIGFuZCB0aGUgZGVwZW5kZW5jZSBwYXR0ZXJuLg0KDQojIyBEaWFnbm9zdGljIFRvb2xzDQoNCldlIGhhdmUgc2VlbiBhIHBhdHRlcm4gdGhhdCBjb3VsZCBtYWtlIG91ciBwcmVjaXNpb24gY2FsY3VsYXRpb24gdW5yZWxpYWJsZS4gRWFjaCBkaWFnbm9zdGljIHN1bW1hcmlzZXMgYSBkaWZmZXJlbnQgZmVhdHVyZSBvZiB0aGF0IHBhdHRlcm4uDQoNCnwgRGlhZ25vc3RpYyB8IFF1ZXN0aW9uIGFib3V0IHRoZSBvcmRlcmVkIHJlc2lkdWFscyB8DQp8Oi0tfDotLXwNCnwgUnVucyB0ZXN0IHwgRG8gcmVzaWR1YWxzIHN0YXkgb24gdGhlIHNhbWUgc2lkZSBvZiB0aGVpciBtZWRpYW4gdW51c3VhbGx5IGxvbmcsIG9yIHN3aXRjaCBzaWRlcyB1bnVzdWFsbHkgb2Z0ZW4/IHwNCnwgRHVyYmluLVdhdHNvbiB8IEhvdyBkaWZmZXJlbnQgaXMgZWFjaCByZXNpZHVhbCBmcm9tIHRoZSBvbmUgaW1tZWRpYXRlbHkgYmVmb3JlIGl0PyB8DQp8IEFDRiB8IEhvdyBzdHJvbmcgaXMgdGhlIGNvcnJlbGF0aW9uIGF0IGVhY2ggdGltZSBnYXA/IHwNCnwgTGp1bmctQm94IHwgSXMgdGhlcmUgZXZpZGVuY2Ugb2YgY29ycmVsYXRpb24gYWNyb3NzIGEgY2hvc2VuIGdyb3VwIG9mIGxhZ3M/IHwNCg0KS2VlcCB0aGUgdGltZSBvcmRlci4gUmVhcnJhbmdpbmcgb2JzZXJ2YXRpb25zIGxlYXZlcyB0aGUgZml0dGVkIHJlZ3Jlc3Npb24gdW5jaGFuZ2VkIGJ1dCBjaGFuZ2VzIHRoZXNlIGRpYWdub3N0aWNzLiBBbHNvIGNoZWNrIHRoZSBtZWFuIG1vZGVsOiBhIG1pc3NpbmcgdHJlbmQgb3Igc2Vhc29uYWwgdGVybSBjYW4gcHJvZHVjZSBhIHJlc2lkdWFsIHBhdHRlcm4gb2YgaXRzIG93bi4NCg0KIyMgUnVucyBUZXN0DQoNCkEgKipydW4qKiBpcyBhbiB1bmludGVycnVwdGVkIHNlcXVlbmNlIG9uIHRoZSBzYW1lIHNpZGUgb2YgYSB0aHJlc2hvbGQuIEZvciBleGFtcGxlLCAkKysrXDstLVw7KytcOy0kIGNvbnRhaW5zIGZvdXIgcnVucywgYWx0aG91Z2ggaXQgY29udGFpbnMgZWlnaHQgb2JzZXJ2YXRpb25zLg0KDQpUaGUgZGVmYXVsdCBbYFJ1bnNUZXN0KClgXShodHRwczovL2FuZHJpc2lnbm9yZWxsLmdpdGh1Yi5pby9EZXNjVG9vbHMvcmVmZXJlbmNlL1J1bnNUZXN0Lmh0bWwpIGRpdmlkZXMgbnVtZXJpY2FsIHJlc2lkdWFscyBhdCB0aGVpciBtZWRpYW4uIFdyaXRlICRuXyskIGZvciB0aGUgbnVtYmVyIGFib3ZlIHRoZSBtZWRpYW4gYW5kICRuXy0kIGZvciB0aGUgbnVtYmVyIGF0IG9yIGJlbG93IGl0LiBVbmRlciByYW5kb20gb3JkZXJpbmcsIHRoZSBleHBlY3RlZCBudW1iZXIgb2YgcnVucyBpcw0KDQokJEUoUik9MStcZnJhY3sybl8rbl8tfXtuXysrbl8tfS4kJA0KDQpUb28gZmV3IHJ1bnMgaW5kaWNhdGUgY2x1c3RlcmluZyBvbiB0aGUgc2FtZSBzaWRlOyB0b28gbWFueSBpbmRpY2F0ZSBleGNlc3NpdmUgYWx0ZXJuYXRpb24uIFRoZSB0ZXN0IGNvbXBhcmVzIHRoZSBvYnNlcnZlZCBjb3VudCB3aXRoIGl0cyBkaXN0cmlidXRpb24gdW5kZXIgcmFuZG9tIG9yZGVyaW5nLg0KDQojIyBSdW5zIGluIHRoZSBNb25leVN0b2NrIFJlc2lkdWFscw0KDQpUaGVyZSBhcmUgdGVuIHJlc2lkdWFscyBvbiBlYWNoIHNpZGUgb2YgdGhlIG1lZGlhbiwgc28gdW5kZXIgcmFuZG9tIG9yZGVyaW5nIHdlIGV4cGVjdA0KDQokJEUoUik9MStcZnJhY3syKDEwKSgxMCl9ezIwfT0xMVx0ZXh0eyBydW5zfS4kJA0KDQpgYGB7ciBtb25leS1zdG9jay1ydW5zLXRlc3R9DQpSdW5zVGVzdChyZXNpZHVhbHMoTW9uZXlTdG9ja19sbTEpKQ0KYGBgDQoNCldlIG9ic2VydmUgb25seSBmaXZlIHJ1bnMsIHdpdGggJFBcYXBwcm94MC4wMDkkLiBUaGlzIHN1cHBvcnRzIHRoZSBpbXByZXNzaW9uIG9mIGxvbmcgc3RyZXRjaGVzIG9uIHRoZSBzYW1lIHNpZGUuIFRoZSBkZWZhdWx0IHRlc3QgaXMgdHdvLXNpZGVkLCBzbyBpdCBjYW4gZGV0ZWN0IGVpdGhlciB1bnVzdWFsbHkgZmV3IG9yIHVudXN1YWxseSBtYW55IHJ1bnMuIEl0IGRvZXMgbm90IG1lYXN1cmUgdGhlIHNpemUgb2YgdGhlIHJlc2lkdWFscyBvciBpZGVudGlmeSB0aGUgcHJvY2VzcyBwcm9kdWNpbmcgdGhlbS4NCg0KIyMgRHVyYmluLVdhdHNvbiBUZXN0DQoNClJ1bnMgdXNlIG9ubHkgd2hpY2ggc2lkZSBlYWNoIHJlc2lkdWFsIGZhbGxzIG9uLiBEdXJiaW4tV2F0c29uIHVzZXMgdGhlIHNpemVzIG9mIHRoZSBjaGFuZ2VzIGJldHdlZW4gbmVpZ2hib3VyaW5nIHJlc2lkdWFsczoNCg0KJCRkPVxmcmFje1xzdW1fe3Q9Mn1ee259KGVfdC1lX3t0LTF9KV4yfXtcc3VtX3t0PTF9XntufWVfdF4yfS4kJA0KDQpUaGUgZGVub21pbmF0b3IgbWVhc3VyZXMgdGhlIG92ZXJhbGwgcmVzaWR1YWwgdmFyaWF0aW9uLiBUaGUgbnVtZXJhdG9yIG1lYXN1cmVzIGhvdyBtdWNoIHJlc2lkdWFscyBjaGFuZ2UgZnJvbSBvbmUgb2JzZXJ2YXRpb24gdG8gdGhlIG5leHQuDQoNCi0gUG9zaXRpdmUgYXV0b2NvcnJlbGF0aW9uIGdpdmVzIHNtYWxsIG5laWdoYm91cmluZyBkaWZmZXJlbmNlcywgc28gJGQkIHRlbmRzIHRvd2FyZHMgMC4NCi0gV2l0aCBubyBsYWctMSBhdXRvY29ycmVsYXRpb24sICRkJCBpcyB0eXBpY2FsbHkgbmVhciAyLg0KLSBOZWdhdGl2ZSBhdXRvY29ycmVsYXRpb24gZ2l2ZXMgbGFyZ2VyIG5laWdoYm91cmluZyBkaWZmZXJlbmNlcywgc28gJGQkIHRlbmRzIHRvd2FyZHMgNC4NCg0KVGhlc2UgdmFsdWVzIGd1aWRlIGludGVycHJldGF0aW9uOyB0aGV5IGFyZSBub3Qgc2lnbmlmaWNhbmNlIGN1dC1vZmZzLg0KDQojIyBEdXJiaW4tV2F0c29uIGZvciBNb25leVN0b2NrDQoNCldlIHRlc3QgJEhfMDpccmhvXzE9MCQgYWdhaW5zdCAkSF9BOlxyaG9fMT4wJC4gVGhlIG9uZS1zaWRlZCBhbHRlcm5hdGl2ZSB0YXJnZXRzIHRoZSBwb3NpdGl2ZSBhdXRvY29ycmVsYXRpb24gc3VnZ2VzdGVkIGJ5IHRoZSB0aW1lIHBsb3QuDQoNCmBgYHtyIG1vbmV5LXN0b2NrLWR1cmJpbi13YXRzb259DQpkd3Rlc3QoTW9uZXlTdG9ja19sbTEsIGFsdGVybmF0aXZlID0gImdyZWF0ZXIiKQ0KYGBgDQoNClRoZSBzdGF0aXN0aWMgaXMgJGRcYXBwcm94MC4zMyQsIHdpdGggYSB2ZXJ5IHNtYWxsIFAtdmFsdWUuIFRoZSByZXNpZHVhbHMgY2hhbmdlIG11Y2ggbGVzcyBiZXR3ZWVuIGFkamFjZW50IHF1YXJ0ZXJzIHRoYW4gd2Ugd291bGQgZXhwZWN0IGZyb20gdGhlaXIgb3ZlcmFsbCB2YXJpYXRpb24uDQoNCkluIFtgZHd0ZXN0KClgXShodHRwczovL3N0YXQuZXRoei5jaC9DUkFOL3dlYi9wYWNrYWdlcy9sbXRlc3QvbG10ZXN0LnBkZiksIGBhbHRlcm5hdGl2ZSA9ICJncmVhdGVyImAgcmVmZXJzIHRvIGNvcnJlbGF0aW9uIGdyZWF0ZXIgdGhhbiB6ZXJvLiBFdmlkZW5jZSBmb3IgdGhhdCBhbHRlcm5hdGl2ZSBjb21lcyBmcm9tIGEgKipzbWFsbCoqIHZhbHVlIG9mICRkJC4gVGhlIHRlc3QncyByZWZlcmVuY2UgZGlzdHJpYnV0aW9uIGFjY291bnRzIGZvciB0aGUgcmVncmVzc2lvbiBwcmVkaWN0b3JzOyB3ZSBkbyBub3Qgc2ltcGx5IGRlY2xhcmUgZXZlcnkgdmFsdWUgYmVsb3cgMiBzaWduaWZpY2FudC4NCg0KIyMgTWVhc3VyaW5nIENvcnJlbGF0aW9uIGF0IEVhY2ggTGFnDQoNCkR1cmJpbi1XYXRzb24gZm9jdXNlcyBvbiBuZWlnaGJvdXJpbmcgb2JzZXJ2YXRpb25zLiBUaGUgYXV0b2NvcnJlbGF0aW9uIGZ1bmN0aW9uIChBQ0YpIGxldHMgdXMgZXhhbWluZSBsb25nZXIgZ2FwcyBhcyB3ZWxsLiBUaGUgW3NhbXBsZSBhdXRvY29ycmVsYXRpb25dKGh0dHBzOi8vd3d3Lml0bC5uaXN0Lmdvdi9kaXY4OTgvaGFuZGJvb2svZWRhL3NlY3Rpb24zL2VkYTM1Yy5odG0pIGF0IGxhZyAkayQgaXMNCg0KJCRyX2s9XGZyYWN7XHN1bV97dD1rKzF9XntufShlX3QtXGJhciBlKShlX3t0LWt9LVxiYXIgZSl9DQp7XHN1bV97dD0xfV57bn0oZV90LVxiYXIgZSleMn0uJCQNCg0KVGhlIG51bWVyYXRvciBwYWlycyByZXNpZHVhbHMgJGskIG9ic2VydmF0aW9ucyBhcGFydC4gUHJvZHVjdHMgYXJlIHBvc2l0aXZlIHdoZW4gYm90aCBkZXZpYXRpb25zIGZyb20gJFxiYXIgZSQgaGF2ZSB0aGUgc2FtZSBzaWduLCBhbmQgbmVnYXRpdmUgd2hlbiB0aGV5IGhhdmUgb3Bwb3NpdGUgc2lnbnMuIFRoZSBkZW5vbWluYXRvciBwdXRzIHRoZSByZXN1bHQgb24gYSBjb3JyZWxhdGlvbiBzY2FsZS4gTGFnIDAgaXMgYWx3YXlzIDEuDQoNCkZvciBPTFMgd2l0aCBhbiBpbnRlcmNlcHQsICRcYmFyIGU9MCQgYXBhcnQgZnJvbSBudW1lcmljYWwgcm91bmRpbmcuIEV4cGFuZGluZyB0aGUgc3F1YXJlZCBkaWZmZXJlbmNlcyBpbiBEdXJiaW4tV2F0c29uIHRoZW4gZ2l2ZXMNCg0KJCRkPTIoMS1yXzEpLVxmcmFje2VfMV4yK2Vfbl4yfXtcc3VtX3t0PTF9XntufWVfdF4yfQ0KXGFwcHJveDIoMS1yXzEpLiQkDQoNClRoZSBhcHByb3hpbWF0aW9uIGRyb3BzIHRoZSB0d28gZW5kcG9pbnQgdGVybXMuIEl0IGNhbiBiZSBub3RpY2VhYmx5IGRpZmZlcmVudCBpbiBhIHNob3J0IHNlcmllcywgc28gdXNlIGl0IHRvIHVuZGVyc3RhbmQgdGhlIGRpcmVjdGlvbiBvZiAkZCQsIHJhdGhlciB0aGFuIHRvIHJlcGxhY2UgdGhlIGNhbGN1bGF0aW9uLg0KDQojIyBBQ0YgUGxvdA0KDQpgYGB7ciBtb25leS1zdG9jay1hY2YsIGZpZy53aWR0aD04LCBmaWcuaGVpZ2h0PTR9DQphY2YocmVzaWR1YWxzKE1vbmV5U3RvY2tfbG0xKSwgbWFpbiA9ICJBQ0Ygb2YgTW9uZXlTdG9jayByZXNpZHVhbHMiKQ0KYGBgDQoNClRoZSBsYWctMSB2YWx1ZSBpcyBhYm91dCAwLjc1LCBhbmQgcG9zaXRpdmUgY29ycmVsYXRpb24gcGVyc2lzdHMgYWNyb3NzIHNldmVyYWwgcXVhcnRlcnMuIFRoaXMgYWdyZWVzIHdpdGggdGhlIHNsb3cgbW92ZW1lbnQgaW4gdGhlIHRpbWUgcGxvdC4gV2Ugc2hvdWxkIGFsc28gY2hlY2sgd2hldGhlciBhIG1pc3NpbmcgdGltZSB0cmVuZCBjb3VsZCBleHBsYWluIHBhcnQgb2YgaXQuDQoNCiMjIFJlYWRpbmcgdGhlIEFDRiBSZWZlcmVuY2UgTGluZXMNCg0KVW5kZXIgYW4gdW5jb3JyZWxhdGVkIHdoaXRlLW5vaXNlIHJlZmVyZW5jZSBtb2RlbCwgdGhlIGRlZmF1bHQgYXBwcm94aW1hdGUgOTUlIHJlZmVyZW5jZSBsaW1pdHMgYXQgYW4gaW5kaXZpZHVhbCBub24temVybyBsYWcgYXJlDQoNCiQkXHBtXGZyYWN7MS45Nn17XHNxcnQgbn0uJCQNCg0KSGVyZSAkbj0yMCQsIGdpdmluZyBsaW1pdHMgb2YgYWJvdXQgJFxwbTAuNDQkLiBUaGUgbGFnLTEgY29ycmVsYXRpb24gaXMgd2VsbCBvdXRzaWRlIHRoZW0uIEEgc2VxdWVuY2Ugb2YgbGFyZ2UgY29ycmVsYXRpb25zIGRlc2VydmVzIG1vcmUgYXR0ZW50aW9uIHRoYW4gb25lIGlzb2xhdGVkIGJhciBqdXN0IGJleW9uZCBhIGxpbmUuDQoNClRoZXNlIGFyZSBhcHByb3hpbWF0ZSwgcG9pbnR3aXNlIGxpbWl0cywgbm90IGEgc2ltdWx0YW5lb3VzIDk1JSBiYW5kIGZvciB0aGUgd2hvbGUgcGxvdC4gV2l0aCBtYW55IGxhZ3MsIHNvbWUgYmFycyBjYW4gY3Jvc3MgYnkgY2hhbmNlLiBGaXR0aW5nIHRoZSByZWdyZXNzaW9uIGFsc28gYWZmZWN0cyB0aGUgYmVoYXZpb3VyIG9mIGl0cyByZXNpZHVhbHMsIHNvIHRyZWF0IHRoZSBsaW5lcyBhcyBhIHZpc3VhbCByZWZlcmVuY2UuIFRoZSBbYGFjZigpYCBwbG90dGluZyBkb2N1bWVudGF0aW9uXShodHRwczovL3N0YXQuZXRoei5jaC9SLW1hbnVhbC9SLWRldmVsL2xpYnJhcnkvc3RhdHMvaHRtbC9wbG90LmFjZi5odG1sKSBkZXNjcmliZXMgdGhlIHdoaXRlLW5vaXNlIGFzc3VtcHRpb24gYmVoaW5kIHRoZW0uDQoNCiMjIExqdW5nLUJveCBUZXN0DQoNCklmIHNldmVyYWwgQUNGIGJhcnMgbG9vayBsYXJnZSwgd2UgY2FuIGNvbWJpbmUgdGhlbS4gRm9yIGEgY2hvc2VuIG1heGltdW0gbGFnICRtJCwgdGhlIGh5cG90aGVzZXMgYXJlDQoNCiQkSF8wOlxyaG9fMT1cY2RvdHM9XHJob19tPTAsIFxxcXVhZA0KSF9BOlx0ZXh0e2F0IGxlYXN0IG9uZSBvZiB0aGVzZSBjb3JyZWxhdGlvbnMgaXMgbm9uLXplcm99LiQkDQoNClRoZSBbTGp1bmctQm94IHN0YXRpc3RpY10oaHR0cHM6Ly93d3cuaXRsLm5pc3QuZ292L2Rpdjg5OC9oYW5kYm9vay9wbWMvc2VjdGlvbjQvcG1jNDQ4MS5odG0pIGlzDQoNCiQkUT1uKG4rMilcc3VtX3trPTF9XnttfVxmcmFje3Jfa14yfXtuLWt9LiQkDQoNClNxdWFyaW5nIHByZXZlbnRzIHBvc2l0aXZlIGFuZCBuZWdhdGl2ZSBjb3JyZWxhdGlvbnMgZnJvbSBjYW5jZWxsaW5nLiBMYXJnZXIgY29ycmVsYXRpb25zIGdpdmUgYSBsYXJnZXIgJFEkIGFuZCBtb3JlIGV2aWRlbmNlIGFnYWluc3QgdGhlIG51bGwgaHlwb3RoZXNpcy4gQ2hvb3NlICRtJCB1c2luZyB0aGUgdGltZSBzY2FsZSBhbmQgdGhlIGF2YWlsYWJsZSBzYW1wbGUgc2l6ZSwgYmVmb3JlIGluc3BlY3RpbmcgYSBjb2xsZWN0aW9uIG9mIFAtdmFsdWVzLg0KDQojIyBManVuZy1Cb3ggZm9yIE1vbmV5U3RvY2sNCg0KSGVyZSB3ZSB1c2UgJG09MTAkLCBjb21iaW5pbmcgY29ycmVsYXRpb25zIG92ZXIgZ2FwcyBmcm9tIG9uZSB0byB0ZW4gcXVhcnRlcnMuDQoNCmBgYHtyIG1vbmV5LXN0b2NrLWxqdW5nLWJveH0NCkJveC50ZXN0KHJlc2lkdWFscyhNb25leVN0b2NrX2xtMSksIGxhZyA9IDEwLCB0eXBlID0gIkxqdW5nLUJveCIpDQpgYGANCg0KV2Ugb2J0YWluICRRXGFwcHJveDY0LjQkIGFuZCBhIHZlcnkgc21hbGwgUC12YWx1ZS4gV2l0aCB0aGUgZGVmYXVsdCBgZml0ZGYgPSAwYCwgW2BCb3gudGVzdCgpYF0oaHR0cHM6Ly9zdGF0LmV0aHouY2gvUi1tYW51YWwvUi1kZXZlbC9saWJyYXJ5L3N0YXRzL2h0bWwvYm94LnRlc3QuaHRtbCkgY29tcGFyZXMgdGhpcyB3aXRoIGFuIGFwcHJveGltYXRlICRcY2hpXjJfezEwfSQgZGlzdHJpYnV0aW9uLg0KDQpUaGVyZSBhcmUgb25seSAyMCBvYnNlcnZhdGlvbnMgaGVyZSwgYW5kIHRoZSByZXNpZHVhbHMgY29tZSBmcm9tIGFuIGVzdGltYXRlZCByZWdyZXNzaW9uLCBzbyB0cmVhdCB0aGF0IFAtdmFsdWUgYXMgYW4gYXBwcm94aW1hdGUgZGlhZ25vc3RpYyBzdW1tYXJ5LiBUaGUgdGltZSBwbG90LCBydW5zIHRlc3QgYW5kIER1cmJpbi1XYXRzb24gYWxyZWFkeSBnaXZlIHN1YnN0YW50aWFsIGV2aWRlbmNlIG9mIHBlcnNpc3RlbmNlLiBUaGlzIHJlc3VsdCBkb2VzIG5vdCBlc3RhYmxpc2ggdGhhdCBldmVyeSBsYWcgaXMgY29ycmVsYXRlZCBvciB0ZWxsIHVzIHdoaWNoIGNoYW5nZSB0byB0aGUgbW9kZWwgd2lsbCBhZGRyZXNzIGl0Lg0KDQojIyBXb3JrIFRocm91Z2ggdGhlIERpYWdub3N0aWNzDQoNCioqMS4qKiBJZiAkZD0wLjYkLCB3aGF0IGxhZy0xIGNvcnJlbGF0aW9uIGRvZXMgJGRcYXBwcm94MigxLXJfMSkkIHN1Z2dlc3Q/DQoNCi4gLiAuDQoNClJlYXJyYW5naW5nIGdpdmVzICRyXzFcYXBwcm94MS1kLzI9MC43JCwgc3VnZ2VzdGluZyBzdHJvbmcgcG9zaXRpdmUgY29ycmVsYXRpb24gYmV0d2VlbiBuZWlnaGJvdXJzLiBUaGlzIGlzIGFuIGFwcHJveGltYXRpb24sIG5vdCBhIFAtdmFsdWUuDQoNCi4gLiAuDQoNCioqMi4qKiBJZiAkcl8xPTAkIGJ1dCAkcl80JCBpcyBsYXJnZSwgd2hpY2ggZGlhZ25vc3RpYyBkaXNwbGF5cyB0aGF0IHBhdHRlcm4sIGFuZCB3aGljaCBjYW4gdGVzdCBhIGdyb3VwIG9mIGxhZ3MgY29udGFpbmluZyBpdD8NCg0KLiAuIC4NCg0KVGhlIEFDRiBkaXNwbGF5cyB0aGUgbGFnLTQgY29ycmVsYXRpb24uIExqdW5nLUJveCB3aXRoICRtXGdlcTQkIGluY2x1ZGVzIGl0IGluIGEgam9pbnQgdGVzdDsgYSBsYWctMSBkaWFnbm9zdGljIGFsb25lIGNhbiBtaXNzIGl0Lg0KDQouIC4gLg0KDQoqKjMuKiogV2h5IHdvdWxkIHNodWZmbGluZyBjb21wbGV0ZSByb3dzIG9mIE1vbmV5U3RvY2sgbGVhdmUgdGhlIGNvZWZmaWNpZW50cyBhbmQgJFJeMiQgdW5jaGFuZ2VkIGJ1dCBhbHRlciB0aGUgcmVzaWR1YWwgZGlhZ25vc3RpY3M/DQoNCi4gLiAuDQoNCk9MUyBtaW5pbWlzZXMgdGhlIHNhbWUgc3VtIG9mIHNxdWFyZXMgYWZ0ZXIgcmVvcmRlcmluZy4gUnVucywgbmVpZ2hib3VyaW5nIGRpZmZlcmVuY2VzIGFuZCBsYWdnZWQgcHJvZHVjdHMgZGVwZW5kIG9uIHdoaWNoIG9ic2VydmF0aW9ucyBmb2xsb3cgb25lIGFub3RoZXIsIHNvIHRoZSBkaWFnbm9zdGljcyBuZWVkIHRoZSBhY3R1YWwgdGltZSBvcmRlci4NCg0KIyMgQSBNb2Rlcm4gQ29tcGFyaXNvbjogU2VvdWwgQmlrZSBSZXNpZHVhbHMNCg0KVGhlIHNhbWUgZGlhZ25vc3RpYyBsb2dpYyBhcHBsaWVzIHRvIHRoZSByaWNoZXIgZGFpbHkgYmlrZSBtb2RlbCBmcm9tIExlY3R1cmVzIDMyLzMzLCB3aGljaCBjb21iaW5lZCB0d28gRm91cmllciBwYWlycyB3aXRoIHRoZSB0aW1lIHRyZW5kIGFuZCB3ZWF0aGVyIHByZWRpY3RvcnMuDQoNCmByIHhmdW46OmVtYmVkX2ZpbGUoIi4uL2RhdGEvc2VvdWxfYmlrZV9kYWlseS5jc3YiKWANCg0KOjo6OiB7LmNvbHVtbnMgLnNlb3VsLXJlc2lkdWFsLWxheW91dH0NCjo6OiB7LmNvbHVtbiBzdHlsZT0id2lkdGg6IDEwMCU7In0NCg0KYGBge3IgcmVhZC1zZW91bC1kYWlseS1kaWFnbm9zdGljcywgbWVzc2FnZT1GQUxTRX0NCnNlb3VsX2RhaWx5IDwtIHJlYWRfY3N2KCIuLi9kYXRhL3Nlb3VsX2Jpa2VfZGFpbHkuY3N2Iiwgc2hvd19jb2xfdHlwZXMgPSBGQUxTRSkgfD4NCiAgbXV0YXRlKGRhdGUgPSBhcy5EYXRlKGRhdGUpKSB8Pg0KICBhcnJhbmdlKGRhdGUpIHw+DQogIGZpbHRlcihmdW5jdGlvbmluZ19kYXlfYWxsID09ICJ5ZXMiKSB8Pg0KICBtdXRhdGUoDQogICAgUzEgPSBzaW4oMiAqIHBpICogZGF5X2luZGV4IC8gMzY1KSwNCiAgICBDMSA9IGNvcygyICogcGkgKiBkYXlfaW5kZXggLyAzNjUpLA0KICAgIFMyID0gc2luKDQgKiBwaSAqIGRheV9pbmRleCAvIDM2NSksDQogICAgQzIgPSBjb3MoNCAqIHBpICogZGF5X2luZGV4IC8gMzY1KQ0KICApDQoNCnNlb3VsX21lYW4gPC0gbG0oDQogIHJlbnRlZF9iaWtlX2NvdW50IH4gZGF5X2luZGV4ICsgUzEgKyBDMSArIFMyICsgQzIgKw0KICAgIG1lYW5fdGVtcGVyYXR1cmUgKyB0b3RhbF9yYWluZmFsbCArIHRvdGFsX3NvbGFyX3JhZGlhdGlvbiwNCiAgZGF0YSA9IHNlb3VsX2RhaWx5DQopDQoNCnNlb3VsX2RpYWdub3N0aWNzIDwtIHNlb3VsX2RhaWx5IHw+DQogIG11dGF0ZShyZXNpZHVhbCA9IHJlc2lkdWFscyhzZW91bF9tZWFuKSkNCmBgYA0KDQo6OjoNCg0KOjo6IHsuY29sdW1uIHN0eWxlPSJ3aWR0aDogMTAwJTsifQ0KDQpgYGB7ciBzZW91bC1yZXNpZHVhbC1wbG90LCBlY2hvPUZBTFNFLCBvdXQud2lkdGg9IjEwMCUifQ0KZ2dwbG90KHNlb3VsX2RpYWdub3N0aWNzLCBhZXMoeCA9IGRhdGUsIHkgPSByZXNpZHVhbCkpICsNCiAgZ2VvbV9saW5lKCkgKw0KICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQgPSAwLCBsaW5ldHlwZSA9IDIpICsNCiAgbGFicyh4ID0gIkFjdHVhbCBkYXRlIiwgeSA9ICJSZXNpZHVhbCIsIHRpdGxlID0gIlNlb3VsIGJpa2UgcmVzaWR1YWxzIG9uIGZ1bmN0aW9uaW5nIGRheXMiKQ0KYGBgDQoNCjo6Og0KOjo6Og0KDQpXZSBmaXR0ZWQgdGhlIG1lYW4gbW9kZWwgdG8gYWxsIDM1MiBmdW5jdGlvbmluZyBkYXlzLiBUaGUgZGF0ZXMgcmVtYWluIHZpc2libGUgaGVyZSwgaW5jbHVkaW5nIHRoZSBnYXBzIGxlZnQgYnkgMTMgb3V0YWdlIGRheXMuDQoNCiMjIFNlb3VsOiBPbmUgVW5pbnRlcnJ1cHRlZCBQZXJpb2QNCg0KRm9yIHRoZSBkYWlseSBkaWFnbm9zdGljcywgc2VsZWN0IHRoZSBsb25nZXN0IHVuaW50ZXJydXB0ZWQgcGVyaW9kOiAxIERlY2VtYmVyIDIwMTcgdGhyb3VnaCAxMCBBcHJpbCAyMDE4LiBPdGhlcndpc2UsIGFuIG9yZGluYXJ5IEFDRiB3b3VsZCB0cmVhdCBjb25zZWN1dGl2ZSByZXRhaW5lZCByb3dzIGFzIHRob3VnaCB0aGV5IHdlcmUgYWx3YXlzIG9uZSBkYXkgYXBhcnQuDQoNClJlZml0IHRoZSAqKnNhbWUgbWVhbiBmb3JtdWxhKiogb24gdGhlc2UgMTMxIGNvbnNlY3V0aXZlIGRheXMuIEFsbCBmb3VyIGRpYWdub3N0aWNzIGJlbG93IHVzZSByZXNpZHVhbHMgZnJvbSB0aGlzIHJlZml0dGVkIG1vZGVsLCBzbyB0aGUgRHVyYmluLVdhdHNvbiB0ZXN0IGFuZCB0aGUgb3RoZXIgc3VtbWFyaWVzIHJlZmVyIHRvIHRoZSBzYW1lIG9ic2VydmF0aW9ucyBhbmQgZml0Lg0KDQpgYGB7ciBzZW91bC1kaWFnbm9zdGljLXRlc3RzfQ0Kc2VvdWxfcnVuX2RhdGEgPC0gc2VvdWxfZGFpbHkgfD4NCiAgZmlsdGVyKGRhdGUgPj0gYXMuRGF0ZSgiMjAxNy0xMi0wMSIpLCBkYXRlIDw9IGFzLkRhdGUoIjIwMTgtMDQtMTAiKSkNCg0Kc2VvdWxfcnVuX21vZGVsIDwtIHVwZGF0ZShzZW91bF9tZWFuLCBkYXRhID0gc2VvdWxfcnVuX2RhdGEpDQpzZW91bF9ydW5fcmVzaWR1YWxzIDwtIHJlc2lkdWFscyhzZW91bF9ydW5fbW9kZWwpDQpgYGANCg0KYGBge3Igc2VvdWwtZGlhZ25vc3RpYy1jYWxjdWxhdGlvbnMsIGluY2x1ZGU9RkFMU0V9DQpzZW91bF9uIDwtIGxlbmd0aChzZW91bF9ydW5fcmVzaWR1YWxzKQ0Kc2VvdWxfbWVkaWFuIDwtIG1lZGlhbihzZW91bF9ydW5fcmVzaWR1YWxzKQ0Kc2VvdWxfYWJvdmUgPC0gc2VvdWxfcnVuX3Jlc2lkdWFscyA+IHNlb3VsX21lZGlhbg0Kc2VvdWxfcnVuc19vYnNlcnZlZCA8LSBsZW5ndGgocmxlKHNlb3VsX2Fib3ZlKSRsZW5ndGhzKQ0Kc2VvdWxfbl9hYm92ZSA8LSBzdW0oc2VvdWxfYWJvdmUpDQpzZW91bF9uX2JlbG93IDwtIHN1bSghc2VvdWxfYWJvdmUpDQpzZW91bF9ydW5zX2V4cGVjdGVkIDwtIDEgKyAyICogc2VvdWxfbl9hYm92ZSAqIHNlb3VsX25fYmVsb3cgLyBzZW91bF9uDQoNCnNlb3VsX2R3X251bWVyYXRvciA8LSBzdW0oZGlmZihzZW91bF9ydW5fcmVzaWR1YWxzKV4yKQ0Kc2VvdWxfZHdfZGVub21pbmF0b3IgPC0gc3VtKHNlb3VsX3J1bl9yZXNpZHVhbHNeMikNCnNlb3VsX2FjZl92YWx1ZXMgPC0gYWNmKHNlb3VsX3J1bl9yZXNpZHVhbHMsIGxhZy5tYXggPSAxNCwgcGxvdCA9IEZBTFNFKQ0Kc2VvdWxfYWNmX2xpbWl0IDwtIHFub3JtKDAuOTc1KSAvIHNxcnQoc2VvdWxfbikNCmBgYA0KDQojIyBTZW91bDogUnVucyBBYm92ZSBhbmQgQmVsb3cgdGhlIE1lZGlhbg0KDQpEaXZpZGUgdGhlIHJlc2lkdWFscyBhdCB0aGVpciBtZWRpYW4sIGByIHJvdW5kKHNlb3VsX21lZGlhbiwgMSlgIGJpa2VzLiBFYWNoIHVuaW50ZXJydXB0ZWQgY29sb3VyIGJsb2NrIGlzIG9uZSBydW4uDQoNCmBgYHtyIHNlb3VsLXJ1bnMtc3RyaXAsIGVjaG89RkFMU0UsIGZpZy53aWR0aD04LCBmaWcuaGVpZ2h0PTEuMywgb3V0LndpZHRoPSI4NSUiLCBmaWcuYWx0PSJTZXF1ZW5jZSBvZiBTZW91bCByZXNpZHVhbHMgYWJvdmUgYW5kIGF0IG9yIGJlbG93IHRoZWlyIG1lZGlhbiwgd2l0aCBlYWNoIGNvbG91ciBibG9jayBtYXJraW5nIG9uZSBydW4ifQ0Kc2VvdWxfcnVuX2RhdGEgfD4NCiAgbXV0YXRlKHNpZGUgPSBpZl9lbHNlKHNlb3VsX2Fib3ZlLCAiQWJvdmUgbWVkaWFuIiwgIkF0IG9yIGJlbG93IG1lZGlhbiIpKSB8Pg0KICBnZ3Bsb3QoYWVzKHggPSBkYXRlLCB5ID0gMSwgZmlsbCA9IHNpZGUpKSArDQogIGdlb21fdGlsZSh3aWR0aCA9IDEsIGhlaWdodCA9IDAuNikgKw0KICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBjKCJBYm92ZSBtZWRpYW4iID0gIiMxNzNmNWYiLCAiQXQgb3IgYmVsb3cgbWVkaWFuIiA9ICIjZDQ4NjNiIikpICsNCiAgbGFicyh4ID0gTlVMTCwgeSA9IE5VTEwsIGZpbGwgPSBOVUxMKSArDQogIHRoZW1lX21pbmltYWwoYmFzZV9zaXplID0gMTEpICsNCiAgdGhlbWUoDQogICAgcGFuZWwuZ3JpZCA9IGVsZW1lbnRfYmxhbmsoKSwNCiAgICBheGlzLnRleHQueSA9IGVsZW1lbnRfYmxhbmsoKSwNCiAgICBheGlzLnRpY2tzLnkgPSBlbGVtZW50X2JsYW5rKCksDQogICAgbGVnZW5kLnBvc2l0aW9uID0gImJvdHRvbSINCiAgKQ0KYGBgDQoNClRoZXJlIGFyZSBgciBzZW91bF9uX2Fib3ZlYCByZXNpZHVhbHMgYWJvdmUgdGhlIG1lZGlhbiBhbmQgYHIgc2VvdWxfbl9iZWxvd2AgYXQgb3IgYmVsb3cgaXQuIENvbXBhcmUgdGhlIGFjdHVhbCBydW4gY291bnQgd2l0aCAkRShSKT0xKzJuXytuXy0vbiQuDQoNCmBgYHtyIHNlb3VsLXJ1bnMtdGVzdH0NCnNlb3VsX3J1bnMgPC0gUnVuc1Rlc3Qoc2VvdWxfcnVuX3Jlc2lkdWFscykNCmBgYA0KDQpgYGB7ciBzZW91bC1ydW5zLXN1bW1hcnksIGVjaG89RkFMU0V9DQp0aWJibGUoDQogIGBPYnNlcnZlZCBydW5zYCA9IHNlb3VsX3J1bnNfb2JzZXJ2ZWQsDQogIGBFeHBlY3RlZCBydW5zYCA9IHJvdW5kKHNlb3VsX3J1bnNfZXhwZWN0ZWQsIDEpLA0KICBgVGVzdCBzdGF0aXN0aWMgemAgPSByb3VuZCh1bm5hbWUoc2VvdWxfcnVucyRzdGF0aXN0aWMpLCAyKSwNCiAgYFAtdmFsdWVgID0gZm9ybWF0LnB2YWwoc2VvdWxfcnVucyRwLnZhbHVlLCBkaWdpdHMgPSAzKQ0KKSB8PiBrYWJsZSgpDQpgYGANCg0KVGhlIGNvdW50IGlzICoqYHIgc2VvdWxfcnVuc19vYnNlcnZlZGAgcnVucyoqOyAkeiQgc3RhbmRhcmRpc2VzIGl0cyBkZXBhcnR1cmUgZnJvbSB0aGUgZXhwZWN0ZWQgY291bnQsIHdpdGggYSBjb250aW51aXR5IGNvcnJlY3Rpb24uIFRoZSB0d28tc2lkZWQgUC12YWx1ZSBpcyBqdXN0IGFib3ZlIDAuMDUuIFRoaXMgdGVzdCB1c2VzIG9ubHkgdGhlIG1lZGlhbi1zaWRlIHNlcXVlbmNlLCBzbyBpdCBjYW4gbWlzcyBkZXBlbmRlbmNlIHZpc2libGUgaW4gdGhlIHJlc2lkdWFsIG1hZ25pdHVkZXMuDQoNCiMjIFNlb3VsOiBEdXJiaW4tV2F0c29uDQoNClVzZSB0aGUgc2l6ZXMgb2YgdGhlIGNoYW5nZXMgYmV0d2VlbiBjb25zZWN1dGl2ZSBkYWlseSByZXNpZHVhbHM6DQoNCiQkZD1cZnJhY3tcc3VtX3t0PTJ9XntufShlX3QtZV97dC0xfSleMn17XHN1bV97dD0xfV57bn1lX3ReMn0NCj1cZnJhY3tgciBzcHJpbnRmKCIlLjBmIiwgc2VvdWxfZHdfbnVtZXJhdG9yKWB9e2ByIHNwcmludGYoIiUuMGYiLCBzZW91bF9kd19kZW5vbWluYXRvcilgfQ0KXGFwcHJveCBgciByb3VuZChzZW91bF9kd19udW1lcmF0b3IgLyBzZW91bF9kd19kZW5vbWluYXRvciwgMilgLiQkDQoNCmBgYHtyIHNlb3VsLWR1cmJpbi13YXRzb259DQpzZW91bF9kdyA8LSBkd3Rlc3Qoc2VvdWxfcnVuX21vZGVsLCBhbHRlcm5hdGl2ZSA9ICJncmVhdGVyIikNCnNlb3VsX2R3DQpgYGANCg0KVGhlIHN0YXRpc3RpYyBpcyBiZWxvdyAyLCB3aXRoIHN0cm9uZyBldmlkZW5jZSBhZ2FpbnN0ICRIXzA6XHJob18xPTAkIGluIGZhdm91ciBvZiBwb3NpdGl2ZSBhdXRvY29ycmVsYXRpb24uIFVubGlrZSB0aGUgcnVucyB0ZXN0LCBEdXJiaW4tV2F0c29uIHVzZXMgaG93IGZhciBuZWlnaGJvdXJpbmcgcmVzaWR1YWxzIG1vdmUsIGFzIHdlbGwgYXMgdGhlaXIgZGlyZWN0aW9uLg0KDQojIyBTZW91bDogQUNGIG9mIHRoZSBEYWlseSBSZXNpZHVhbHMNCg0KYGBge3Igc2VvdWwtYWNmLCBmaWcud2lkdGg9OCwgZmlnLmhlaWdodD0zLCBvdXQud2lkdGg9Ijg1JSJ9DQphY2Yoc2VvdWxfcnVuX3Jlc2lkdWFscywgbWFpbiA9ICJBQ0Ygb2YgU2VvdWwgcmVzaWR1YWxzOiByZWZpdHRlZCBvbiBjb25zZWN1dGl2ZSBkYXlzIikNCmBgYA0KDQpUaGUgbGFnLTEgY29ycmVsYXRpb24gaXMgJHJfMVxhcHByb3ggYHIgcm91bmQoc2VvdWxfYWNmX3ZhbHVlcyRhY2ZbMl0sIDMpYCQuIFRoZSBhcHByb3hpbWF0ZSBwb2ludHdpc2UgcmVmZXJlbmNlIGxpbWl0cyBhcmUNCg0KJCRccG1cZnJhY3sxLjk2fXtcc3FydHtgciBzZW91bF9uYH19XGFwcHJveFxwbSBgciByb3VuZChzZW91bF9hY2ZfbGltaXQsIDMpYC4kJA0KDQpOZWlnaGJvdXJpbmcgZGFpbHkgcmVzaWR1YWxzIHJlbWFpbiBwb3NpdGl2ZWx5IGNvcnJlbGF0ZWQgYWZ0ZXIgcmVmaXR0aW5nIHRoZSBtZWFuLiBSZWFkIHRoZSBvdGhlciBsYWdzIGZyb20gdGhlIHBsb3QgYXMgd2VsbDsgdGhlIHJlZmVyZW5jZSBsaW5lcyBhcmUgYXBwcm94aW1hdGUgYW5kIGRvIG5vdCBmb3JtIGEgc2ltdWx0YW5lb3VzIGJhbmQuDQoNCiMjIFNlb3VsOiBManVuZy1Cb3ggQWNyb3NzIFR3byBXZWVrcw0KDQpDb21iaW5lIHRoZSBjb3JyZWxhdGlvbnMgYXQgbGFncyAxIHRocm91Z2ggMTQsIHJhdGhlciB0aGFuIHRlc3Rpbmcgb25seSBuZWlnaGJvdXJpbmcgZGF5czoNCg0KJCRRPW4obisyKVxzdW1fe2s9MX1eezE0fVxmcmFje3Jfa14yfXtuLWt9LiQkDQoNCmBgYHtyIHNlb3VsLWxqdW5nLWJveH0NCnNlb3VsX2xqdW5nX2JveCA8LSBCb3gudGVzdChzZW91bF9ydW5fcmVzaWR1YWxzLCBsYWcgPSAxNCwgdHlwZSA9ICJManVuZy1Cb3giKQ0KYGBgDQoNCmBgYHtyIHNlb3VsLWxqdW5nLWJveC1zdW1tYXJ5LCBlY2hvPUZBTFNFfQ0KdGliYmxlKA0KICBgU3RhdGlzdGljIFFgID0gcm91bmQodW5uYW1lKHNlb3VsX2xqdW5nX2JveCRzdGF0aXN0aWMpLCAyKSwNCiAgYFJlZmVyZW5jZSBkZmAgPSB1bm5hbWUoc2VvdWxfbGp1bmdfYm94JHBhcmFtZXRlciksDQogIGBQLXZhbHVlYCA9IGZvcm1hdC5wdmFsKHNlb3VsX2xqdW5nX2JveCRwLnZhbHVlLCBkaWdpdHMgPSAzKQ0KKSB8PiBrYWJsZSgpDQpgYGANCg0KVGhlIHNtYWxsIFAtdmFsdWUgZ2l2ZXMgZXZpZGVuY2Ugb2YgcmVtYWluaW5nIGF1dG9jb3JyZWxhdGlvbiBhY3Jvc3MgdGhlc2UgbGFncy4gSXQgZG9lcyBub3QgaW1wbHkgdGhhdCBldmVyeSBsYWcgaXMgY29ycmVsYXRlZC4gVGhpcyBpcyBhbiBhcHByb3hpbWF0ZSBkaWFnbm9zdGljIG9uIGZpdHRlZCByZWdyZXNzaW9uIHJlc2lkdWFscywgdXNpbmcgdGhlIGRlZmF1bHQgYGZpdGRmID0gMGAuDQoNClRoZSBydW5zIHRlc3QgZ2F2ZSB3ZWFrZXIgZXZpZGVuY2UgYmVjYXVzZSBpdCBkaXNjYXJkZWQgcmVzaWR1YWwgbWFnbml0dWRlcy4gVGFrZW4gdG9nZXRoZXIsIHRoZSB0aW1lIHBsb3QsIER1cmJpbi1XYXRzb24sIEFDRiBhbmQgTGp1bmctQm94IHN1Z2dlc3QgdGhhdCByZWZpdHRpbmcgdGhlIG1lYW4gaGFzIG5vdCByZW1vdmVkIHRoZSBkZXBlbmRlbmNlLiBUaGVzZSByZXN1bHRzIGNvbmNlcm4gdGhlIDEzMS1kYXkgZml0LCByYXRoZXIgdGhhbiBlc3RhYmxpc2hpbmcgYWRlcXVhY3kgb3ZlciB0aGUgZW50aXJlIGdhcHB5IHllYXIuDQoNCiMjIERpYWdub3N0aWMgU3VtbWFyeQ0KDQpUaGUgdGltZSBwbG90IGNvbWVzIGZpcnN0LCB0aGVuIHRoZSBBQ0YuIFRoZSBydW5zIHRlc3QsIER1cmJpbi1XYXRzb24gYW5kIExqdW5nLUJveCBlYWNoIHN1bW1hcmlzZSBhIGRpZmZlcmVudCBmZWF0dXJlIG9mIHRoZSBvcmRlcmVkIHJlc2lkdWFscywgc28gYSBjb2xsZWN0aW9uIG9mIHNtYWxsIFAtdmFsdWVzIHN1cHBvcnRzIHdoYXQgd2UgY2FuIGFscmVhZHkgc2VlIGluIHRoZSBwbG90cy4gTm9uZSBvZiB0aGVtIGlkZW50aWZpZXMgdGhlIGVycm9yIHByb2Nlc3MgdGhhdCBwcm9kdWNlZCB0aGUgcGF0dGVybi4NCg0KQmVmb3JlIGNoYW5naW5nIHRoZSBlcnJvciBtb2RlbCwgY2hlY2sgdGhlIG1lYW46IGEgbWlzc2luZyB0cmVuZCwgc2Vhc29uYWwgdGVybSBvciBvdXRhZ2UgY2FuIGxlYXZlIGEgcmVzaWR1YWwgcGF0dGVybiBvZiBpdHMgb3duLiBGb3IgYm90aCBNb25leVN0b2NrIGFuZCBTZW91bCB3ZSBmaXR0ZWQgcmVhc29uYWJsZSBtZWFuIG1vZGVscyBhbmQgdGhlIGRlcGVuZGVuY2UgcmVtYWluZWQsIHNvIHdlIHRyZWF0IGl0IGFzIHBhcnQgb2YgdGhlIGVycm9ycyBhbmQgbW9kZWwgaXQgZGlyZWN0bHkuDQoNCiMjIExvb2tpbmcgQWhlYWQNCg0KRXZlcnkgbW9kZWwgd2UgaGF2ZSBmaXR0ZWQgdGhpcyBzZW1lc3RlciBhc3N1bWVkIGluZGVwZW5kZW50IGVycm9ycy4gRmxleGlibGUgY3VydmVzLCBmYWN0b3JzIGFuZCB3ZWlnaHRzIGNoYW5nZWQgdGhlIG1lYW4gb3IgdGhlIHZhcmlhbmNlOyB0aGUgY29ycmVsYXRpb24gYmV0d2VlbiBlcnJvcnMgbmV2ZXIgZW50ZXJlZCB0aGUgbW9kZWwuIEFmdGVyIHRoaXMgbGVjdHVyZSB3ZSBrbm93IGhvdyB0byBkZXRlY3QgdGhhdCBjb3JyZWxhdGlvbiwgYW5kIGluIE1vbmV5U3RvY2sgYW5kIFNlb3VsIGl0IGlzIGNsZWFybHkgdGhlcmUuDQoNCk5leHQgbGVjdHVyZSB3ZSBtb2RlbCBpdC4gQW4gQVIoMSkgZXJyb3IgbW9kZWwsIGZpdHRlZCBieSBnZW5lcmFsaXNlZCBsZWFzdCBzcXVhcmVzIChHTFMpLCBrZWVwcyB0aGUgbWVhbiBmb3JtdWxhIGFuZCBhZGRzIGEgY29ycmVsYXRpb24gc3RydWN0dXJlIHRvIHRoZSBlcnJvcnMgaW5zdGVhZC4gV2Ugd2lsbCBmaXQgdGhlIHRvdXJpc20gbW9kZWwgd2l0aCBgZ2xzKClgIGFuZCBgY29yQVIxKClgLCBjb21wYXJlIHRoZSBzdGFuZGFyZCBlcnJvcnMgd2l0aCB0aGUgb3JkaW5hcnkgZml0LCBhbmQgY2hlY2sgd2hldGhlciB0aGUgbm9ybWFsaXNlZCByZXNpZHVhbHMgbG9vayBjbG9zZXIgdG8gd2hpdGUgbm9pc2UuDQo=