Data description
For our analysis, we are only interested in the monthly residential
gas consumption in GWh. Note that the raw data has two other types of
gas consumption (industrial consumption and
production/co-generation).
We use tsibble objects as they are specifically designed
for time series analysis. A tsibble is a special kind of
tibble.
After downloading, importing, and tidying the data, the resulting
tsibble, named df is shown below.
We observe that:
- There are 93 rows and 3 columns
- The interval (time step) is 1 month (
month column)
- There are two time series:
- Monthly residential gas consumption in GWh
(
consumption_gwh column)
- Monthly average temperature in degrees Celcius
(
temp_celcius column)
Although the first 10 rows are displayed, the month
column contains 8 years.
unique(year(df$month))
## [1] 2017 2018 2019 2020 2021 2022 2023 2024
Furthermore, we observe that the time series:
- starts at Jan-2017
- ends at Sep-2024
- has 0 gaps
Next, we perform an exploratory data analysis to understand the
patterns in the data.
Exploratory data
analysis
Desriptive
statistics
The following descriptive statistics are computed for the monthly
temperature in Celcius.
|
Statistic
|
Value
|
|
n
|
93.0
|
|
min
|
-1.6
|
|
q1
|
4.9
|
|
mean
|
10.8
|
|
median
|
10.0
|
|
q3
|
16.7
|
|
max
|
22.1
|
For the residential gas consumption in GWh, we compute a more
comprehensive list of statistics.
consumption_gwh_stats <- df |>
as_tibble() |>
summarise(
n = n(),
sum = sum(consumption_gwh),
min = min(consumption_gwh),
q1 = quantile(consumption_gwh, 0.25),
mean = mean(consumption_gwh),
median = median(consumption_gwh),
q3 = quantile(consumption_gwh, 0.75),
max = max(consumption_gwh),
var = var(consumption_gwh),
sd = sd(consumption_gwh),
skewness = skewness(consumption_gwh),
kurtosis = kurtosis(consumption_gwh),
IQR = IQR(consumption_gwh),
MAD = mad(consumption_gwh, center = mean(consumption_gwh)),
MSD = mean((consumption_gwh - mean(consumption_gwh))^2)
) |>
pivot_longer(everything(),
names_to = "Statistic",
values_to = "Value"
) |>
mutate(Value = round(Value, 2))
kbl(consumption_gwh_stats) |>
kable_styling(bootstrap_options = "striped",
full_width = FALSE,
position = "center")
|
Statistic
|
Value
|
|
n
|
93.00
|
|
sum
|
21212.76
|
|
min
|
32.47
|
|
q1
|
172.14
|
|
mean
|
228.09
|
|
median
|
225.09
|
|
q3
|
309.17
|
|
max
|
416.42
|
|
var
|
10287.68
|
|
sd
|
101.43
|
|
skewness
|
-0.16
|
|
kurtosis
|
2.17
|
|
IQR
|
137.03
|
|
MAD
|
102.52
|
|
MSD
|
10177.06
|
We observe that:
- The total residential gas consumption was 21,212.76 GWh.
- The average monthly residential gas consumption is 228.09 GWh.
Histograms
Let us examine the distribution of the data.

Density plots

We observe that both distributions are bimodal. The temperature
distribution has a more pronounced bimodal feature.
Boxplots
One simple yet effective method to detect outliers graphically is the
boxplot. These are the boxplots for our two variables.

The lower and upper hinges correspond to the first and third
quartiles (the 25th and 75th percentiles). The line between the hinges
corresponds to the median. The upper whisker extends from the hinge to
the largest value no further than 1.5 * IQR from the hinge. IQR is the
distance between the first and third quartiles. The lower whisker
extends from the hinge to the smallest value at most 1.5 * IQR of the
hinge. Data beyond the end of the whiskers are called “outliers” and are
plotted individually.
We observe that both distributions do not contain any outliers.
Time plots
Perhaps the most useful data visualization when it comes to time
series is the time plot. Here is the time plot for our data.

The time plot of the gas consumption (upper plot) immediately reveals
some interesting features.
- Peaks happen in the winter.
- Low points happen in the summer.
- There is a decreasing trend.
- The seasonal pattern increases in size as the level of the series
increases. This causes the variance to increase over time and it is also
known as heteroskedasticity.
The spikes during the winter months are probably caused due to
household gas heating. Similarly, the low points in the summer could be
due to the reduced need for household gas heating.
The time plot of the mean monthly temperature (lower plot) exhibits
the opposite pattern.
- Peaks happen in the summer
- Low points happen in the winter.
- There is a flat trend.
- The data appears to be homoskedastic.
Both time series have a strong seasonal pattern.
Seasonal plots
A seasonal plot is similar to a time plot except that the data are
plotted against the individual month in which the data were
observed.

In addition to the observations made by the time plot, we observe
that:
- February and March 2018 have a higher gas consumption than the same
months in other years.
- February 2024 has a lower gas consumption than the same month in
other years.
- There are two “clusters” of curves. The first cluster has 2017 to
2021 curves and the second cluster has 2022 to 2024 curves. The curves
of the second cluster are below than the curves of the first cluster,
from April to November. This could be explained by the higher-than-usual
residential gas prices observed from 2022 until
The higher-than-usual gas consumption in February and March 2018 is
most likely explained by the low mean temperature during these months,
as observed in the graph below.

Seasonal subseries
plot
An alternative plot that emphasizes the seasonal patterns is where
the data for each season are collected together in separate mini time
plots. The blue horizontal lines indicate the means for each month. The
x-axis indicates the year.

We observe that the pattern is similar between months, except from
January.

We do not detect any clear pattern in this seasonal subseries
graph.
Up until now, we have observed each time series individually. This is
also called a univariate analysis. Next, we will look at how these time
series behave together. This is also called a multivariate analysis.
Scatterplot
Let us visualize the data points of gas consumption and mean
temperature together. The most common plot for this task is the
scatterplot, as shown below. A linear fit is also plotted.

As expected, we observe a negative correlation between mean
temperature and gas consumption. We also observe that the upper left
corner (low temperature, high consumption) has data points closer to the
linear regression line. In contrast, the lower right corner (high
temperature, low consumption) has data points scattered away from the
linear regression line.
The correlation coefficient measures the strength of the
linear relationship between mean temperature and gas
consumption. For this data, the correlation coefficient is -0.85.
As shown below, the correlation test indicates that the correlation
coefficient is significantly different than zero.
cor.test(df$consumption_gwh, df$temp_celcius, method = "pearson",
alternative = "two.sided", conf.level = 0.95)
##
## Pearson's product-moment correlation
##
## data: df$consumption_gwh and df$temp_celcius
## t = -15.48, df = 91, p-value < 2.2e-16
## alternative hypothesis: true correlation is not equal to 0
## 95 percent confidence interval:
## -0.8991106 -0.7834962
## sample estimates:
## cor
## -0.8513285
Lag plots
The figure below displays scatterplots where the horizontal axis
shows lagged values (k) of the time series. Each graph shows
monthly gas consumption data points plotted against themselves at
different lags.
df |>
gg_lag(consumption_gwh, geom = "point", lags = 1:12) +
labs(
x = "lag(gas consumption in GWh, k)",
y = "Gas consumption in GWh",
color = "Month"
) +
theme_minimal()

The colors indicate the month of the variable on the vertical axis.
The relationship is strongly positive at lags 1 and 12, reflecting the
strong seasonality in the data. The negative relationship seen for lag 6
occurs because peaks of gas consumption (in the winther) are plotted
against troughs (in the summer).
Autocorrelation
Just as correlation measures the extent of a linear relationship
between two variables, autocorrelation measures the linear relationship
between lagged values of a time series.
There are several autocorrelation coefficients, corresponding to each
panel in the lag plot above.
The autocorrelation coefficients make up the autocorrelation
function or ACF.
df |>
ACF(consumption_gwh, lag_max = 48) |>
autoplot() +
labs(
title = "ACF plot: Monthly gas consumption in GWh",
x = "Lag in months",
y = "ACF"
) +
theme_minimal()

In this graph:
- The autocorrelation coefficients at lag 1, 12, 24, etc. (denoted
\(r_1\), \(r_{12}\), and \(r_{24}\) respectively) are high. This is
due to the seasonal pattern in the data: the peaks tend to be 12 months
apart and the low points tend to also be 12 months apart.
- The dashed blue lines indicate whether the correlations are
significantly different from zero. If an autocorrelation coefficient
lies outside the blue bound, it is significantly different from
zero.
Time series
decomposition
dcmp <- df |>
model(stl = STL(consumption_gwh)) |>
components()
dcmp

Trend and seasonal
strength
|
Feature
|
Monthly gas consumption in GWh
|
Monthly mean temperature in Celcius
|
|
trend_strength
|
0.8324117
|
0.1722841
|
|
seasonal_strength_year
|
0.9463735
|
0.9527928
|
|
seasonal_peak_year
|
1
|
7
|
|
seasonal_trough_year
|
8
|
1
|
|
spikiness
|
51.265714290
|
0.001106719
|
|
linearity
|
-394.9711522
|
0.3238554
|
|
curvature
|
-100.9533782
|
-0.1425342
|
|
stl_e_acf1
|
0.3120111
|
-0.1448544
|
|
stl_e_acf10
|
0.6141027
|
0.2663283
|

LS0tCnRpdGxlOiAiQW5hbHlzaXMgb2YgcmVzaWRlbnRpYWwgZ2FzIGNvbnN1bXB0aW9uIGRhdGEgaW4gTHV4ZW1ib3VyZyIKYXV0aG9yOiAiQ2hyaXN0b3MgQXZyaWxpb25pcyIKZGF0ZTogIjIwMjUtMTEtMjQiCm91dHB1dDoKICBodG1sX2RvY3VtZW50OiAKICAgIGFuY2hvcl9zZWN0aW9uczogZmFsc2UKICAgIHRvYzogdHJ1ZQogICAgdG9jX2Zsb2F0OgogICAgICBjb2xsYXBzZWQ6IGZhbHNlCiAgICAgIHNtb290aF9zY3JvbGw6IHRydWUKICAgIGNvZGVfZG93bmxvYWQ6IHRydWUKICAgIGNvZGVfZm9sZGluZzogbm9uZQogICAgY3NzOiBzdHlsZS5jc3MKICAgIG51bWJlcl9zZWN0aW9uczogdHJ1ZQogICAgZmlnX3dpZHRoOiA5CiAgICBmaWdfY2FwdGlvbjogZmFsc2UKICAgIGRmX3ByaW50OiBwYWdlZApiaWJsaW9ncmFwaHk6IHJlZmVyZW5jZXMuYmliCmNzbDogYXBhLmNzbAplZGl0b3Jfb3B0aW9uczogCiAgbWFya2Rvd246IAogICAgd3JhcDogNzIKLS0tCgpgYGB7ciBzZXR1cCwgaW5jbHVkZSA9IEZBTFNFfQprbml0cjo6b3B0c19jaHVuayRzZXQoZWNobyA9IFRSVUUpCgpzdXBwcmVzc1BhY2thZ2VTdGFydHVwTWVzc2FnZXMoewogIGxpYnJhcnkodGlkeXZlcnNlKQogIGxpYnJhcnkoZ3JpZEV4dHJhKQogIGxpYnJhcnkobW9tZW50cykKICBsaWJyYXJ5KGZhYmxlKQogIGxpYnJhcnkoZmFibGV0b29scykKICBsaWJyYXJ5KGZlYXN0cykKICBsaWJyYXJ5KGdncmVwZWwpCiAgbGlicmFyeShsYXRleDJleHApCiAgbGlicmFyeShrYWJsZUV4dHJhKQp9KQpgYGAKCiFbXSguLy4uL3d3dy90aGVybW9zdGF0LmpwZyl7LmNlbnRlci1pbWFnZX0KCioqTGlzdCBvZiBhYmJyZXZpYXRpb25zKioKCmBgYHtyIGFiYnJldmlhdGlvbnMsIGVjaG89RkFMU0V9CgphYmJyIDwtIHJlYWRfZGVsaW0oIi4vLi4vZGF0YS9hYmJyZXZpYXRpb25zLmNzdiIsCiAgICAgICAgICAgICAgICAgICBkZWxpbSA9ICJ8IiwKICAgICAgICAgICAgICAgICAgIGNvbF9uYW1lcyA9IFRSVUUsCiAgICAgICAgICAgICAgICAgICBzaG93X2NvbF90eXBlcyA9IEZBTFNFKSB8PgogIGFycmFuZ2UoQWJicmV2aWF0aW9uKQoKa2JsKGFiYnIpIHw+CiAga2FibGVfc3R5bGluZyhib290c3RyYXBfb3B0aW9ucyA9ICJzdHJpcGVkIiwKICAgICAgICAgICAgICAgIGZ1bGxfd2lkdGggPSBGQUxTRSwKICAgICAgICAgICAgICAgIHBvc2l0aW9uID0gImNlbnRlciIpCmBgYAoKIyMgSW50cm9kdWN0aW9uCgpUaGlzIGRvY3VtZW50IHByZXNlbnRzIHRoZSBhbmFseXNpcyBvZiByZXNpZGVudGlhbCBnYXMgY29uc3VtcHRpb24gZGF0YQppbiBMdXhlbWJvdXJnLgoKIyMgRGF0YSBzb3VyY2VzCgpUaGUgYW5hbHlzaXMgaGVyZWFmdGVyIGlzIGJhc2VkIG9uIHR3byBkYXRhIHNvdXJjZXMgd2l0aCB0aGUgZm9sbG93aW5nCmNoYXJhY3RlcmlzdGljcy4KCnwgRGF0YSBzb3VyY2UgfCBQcm9kdWNlciB8IFVSTCB8IEZvcm1hdCB8CnwtLS0tLS0tLS0tLS18LS0tLS0tLS0tLS0tfC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS18LS0tLS0tLS0tLS0tfAp8IE1vbnRobHkgcmVzaWRlbnRpYWwgZ2FzIGNvbnN1bXB0aW9uIGluIEx1eGVtYm91cmcgfCAqSW5zdGl0dXQgTHV4ZW1ib3VyZ2VvaXMgZGUgUsOpZ3VsYXRpb24gKElMUikqIHwgPGh0dHBzOi8vZGF0YS5wdWJsaWMubHUvZW4vZGF0YXNldHMvZG9ubmVlcy1zdGF0aXN0aXF1ZXMtZHUtc2VjdGV1ci1kZS1nYXotbmF0dXJlbC1pbHIvPiB8IC54bHN4IHwKfCBNb250aGx5IG1lYW4gYWlyIHRlbXBlcmF0dXJlIGluIEx1eGVtYm91cmcgfCBNZXRlb0x1eCB8IDxodHRwczovL2RhdGEucHVibGljLmx1L2VuL2RhdGFzZXRzL2luc3BpcmUtYW5uZXgtaWlpLW1ldGVvcm9sb2dpY2FsLWdlb2dyYXBoaWNhbC1mZWF0dXJlcy1wb2ludHRpbWVzZXJpZXNvYnNlcnZhdGlvbi1tb250aGx5LXdlYXRoZXItbWVhc3VyZW1lbnRzLWF0LWx1eGVtYm91cmctZmluZGVsLWFpcnBvcnQtMS8+IHwgLmdtbCB8CgpGb3IgY29uY2lzZW5lc3MsIHRoZSBkZXRhaWxzIG9mIGRhdGEgZG93bmxvYWQsIGltcG9ydCBhbmQgdGlkeWluZyBhcmUKbm90IGRpc2N1c3NlZCBoZXJlLiBJZiB5b3UgYXJlIGludGVyZXN0ZWQsIHlvdSBjYW4gdXNlIHRoZSBSIGNvZGUgZnJvbQpbR2l0SHViXShodHRwczovL2dpdGh1Yi5jb20vY2F2cmlsaW9uaXMvbHUtZ2FzLWFuYWx5c2lzL2Jsb2IvbWFpbi9SKSB0bwpkb3dubG9hZCwgaW1wb3J0LCBhbmQgdGlkeSB0aGUgZGF0YS4KCmBgYHtyIGRvd25sb2FkX2RhdGEsIGluY2x1ZGUgPSBGQUxTRX0Kc291cmNlKCIwMS1kb3dubG9hZF9kYXRhLlIiKQpgYGAKCmBgYHtyIGltcG9ydF9kYXRhLCBpbmNsdWRlID0gRkFMU0V9CnNvdXJjZSgiMDItaW1wb3J0LWRhdGEuUiIpCmBgYAoKIyMgRGF0YSBkZXNjcmlwdGlvbgoKRm9yIG91ciBhbmFseXNpcywgd2UgYXJlIG9ubHkgaW50ZXJlc3RlZCBpbiB0aGUgbW9udGhseSByZXNpZGVudGlhbCBnYXMKY29uc3VtcHRpb24gaW4gR1doLiBOb3RlIHRoYXQgdGhlIHJhdyBkYXRhIGhhcyB0d28gb3RoZXIgdHlwZXMgb2YgZ2FzCmNvbnN1bXB0aW9uIChpbmR1c3RyaWFsIGNvbnN1bXB0aW9uIGFuZCBwcm9kdWN0aW9uL2NvLWdlbmVyYXRpb24pLgoKV2UgdXNlIGB0c2liYmxlYCBvYmplY3RzIGFzIHRoZXkgYXJlIHNwZWNpZmljYWxseSBkZXNpZ25lZCBmb3IgdGltZQpzZXJpZXMgYW5hbHlzaXMuIEEgYHRzaWJibGVgIGlzIGEgc3BlY2lhbCBraW5kIG9mIGB0aWJibGVgLgoKQWZ0ZXIgZG93bmxvYWRpbmcsIGltcG9ydGluZywgYW5kIHRpZHlpbmcgdGhlIGRhdGEsIHRoZSByZXN1bHRpbmcKYHRzaWJibGVgLCBuYW1lZCBgZGZgIGlzIHNob3duIGJlbG93LgoKYGBge3IgcHJpbnRfZGYsIGVjaG8gPSBGQUxTRX0KZGYKYGBgCgpXZSBvYnNlcnZlIHRoYXQ6CgotICAgVGhlcmUgYXJlIGByIG5yb3coZGYpYCByb3dzIGFuZCBgciBuY29sKGRmKWAgY29sdW1ucwotICAgVGhlIGludGVydmFsICh0aW1lIHN0ZXApIGlzIDEgbW9udGggKGBtb250aGAgY29sdW1uKQotICAgVGhlcmUgYXJlIHR3byB0aW1lIHNlcmllczoKICAgIC0gICBNb250aGx5IHJlc2lkZW50aWFsIGdhcyBjb25zdW1wdGlvbiBpbiBHV2ggKGBjb25zdW1wdGlvbl9nd2hgCiAgICAgICAgY29sdW1uKQogICAgLSAgIE1vbnRobHkgYXZlcmFnZSB0ZW1wZXJhdHVyZSBpbiBkZWdyZWVzIENlbGNpdXMgKGB0ZW1wX2NlbGNpdXNgCiAgICAgICAgY29sdW1uKQoKQWx0aG91Z2ggdGhlIGZpcnN0IDEwIHJvd3MgYXJlIGRpc3BsYXllZCwgdGhlIGBtb250aGAgY29sdW1uIGNvbnRhaW5zCmByIGxlbmd0aCh1bmlxdWUoeWVhcihkZiRtb250aCkpKWAgeWVhcnMuCgpgYGB7ciB1bmlxdWVfbW9udGhzfQp1bmlxdWUoeWVhcihkZiRtb250aCkpCmBgYAoKRnVydGhlcm1vcmUsIHdlIG9ic2VydmUgdGhhdCB0aGUgdGltZSBzZXJpZXM6CgotICAgc3RhcnRzIGF0IGByIGZvcm1hdChtaW4oZGYkbW9udGgpLCAiJWItJVkiKWAKLSAgIGVuZHMgYXQgYHIgZm9ybWF0KG1heChkZiRtb250aCksICIlYi0lWSIpYAotICAgaGFzIGByIG5yb3coY291bnRfZ2FwcyhkZikpYCBnYXBzCgpOZXh0LCB3ZSBwZXJmb3JtIGFuIGV4cGxvcmF0b3J5IGRhdGEgYW5hbHlzaXMgdG8gdW5kZXJzdGFuZCB0aGUgcGF0dGVybnMKaW4gdGhlIGRhdGEuCgojIyBFeHBsb3JhdG9yeSBkYXRhIGFuYWx5c2lzCgojIyMgRGVzcmlwdGl2ZSBzdGF0aXN0aWNzCgpUaGUgZm9sbG93aW5nIGRlc2NyaXB0aXZlIHN0YXRpc3RpY3MgYXJlIGNvbXB1dGVkIGZvciB0aGUgbW9udGhseQp0ZW1wZXJhdHVyZSBpbiBDZWxjaXVzLgoKYGBge3Igc3RhdHNfdGVtcF9jZWxjaXVzLCBlY2hvID0gRkFMU0V9CnRlbXBfY2VsY2l1c19zdGF0cyA8LSBkZiB8PgogIGFzX3RpYmJsZSgpIHw+CiAgc3VtbWFyaXNlKAogICAgbiA9IG4oKSwKICAgIG1pbiA9IG1pbih0ZW1wX2NlbGNpdXMpLAogICAgcTEgPSBxdWFudGlsZSh0ZW1wX2NlbGNpdXMsIDAuMjUpLAogICAgbWVhbiA9IG1lYW4odGVtcF9jZWxjaXVzKSwKICAgIG1lZGlhbiA9IG1lZGlhbih0ZW1wX2NlbGNpdXMpLAogICAgcTMgPSBxdWFudGlsZSh0ZW1wX2NlbGNpdXMsIDAuNzUpLAogICAgbWF4ID0gbWF4KHRlbXBfY2VsY2l1cykKICApIHw+CiAgcGl2b3RfbG9uZ2VyKGV2ZXJ5dGhpbmcoKSwKICAgIG5hbWVzX3RvID0gIlN0YXRpc3RpYyIsCiAgICB2YWx1ZXNfdG8gPSAiVmFsdWUiCiAgKSB8PgogIG11dGF0ZShWYWx1ZSA9IHJvdW5kKFZhbHVlLCAxKSkKCmtibCh0ZW1wX2NlbGNpdXNfc3RhdHMpIHw+CiAga2FibGVfc3R5bGluZyhib290c3RyYXBfb3B0aW9ucyA9ICJzdHJpcGVkIiwKICAgICAgICAgICAgICAgIGZ1bGxfd2lkdGggPSBGQUxTRSwKICAgICAgICAgICAgICAgIHBvc2l0aW9uID0gImNlbnRlciIpCmBgYAoKRm9yIHRoZSByZXNpZGVudGlhbCBnYXMgY29uc3VtcHRpb24gaW4gR1doLCB3ZSBjb21wdXRlIGEgbW9yZQpjb21wcmVoZW5zaXZlIGxpc3Qgb2Ygc3RhdGlzdGljcy4KCmBgYHtyIHN0YXRzX2NvbnN1bXB0aW9uX2d3aH0KY29uc3VtcHRpb25fZ3doX3N0YXRzIDwtIGRmIHw+CiAgYXNfdGliYmxlKCkgfD4KICBzdW1tYXJpc2UoCiAgICBuID0gbigpLAogICAgc3VtID0gc3VtKGNvbnN1bXB0aW9uX2d3aCksCiAgICBtaW4gPSBtaW4oY29uc3VtcHRpb25fZ3doKSwKICAgIHExID0gcXVhbnRpbGUoY29uc3VtcHRpb25fZ3doLCAwLjI1KSwKICAgIG1lYW4gPSBtZWFuKGNvbnN1bXB0aW9uX2d3aCksCiAgICBtZWRpYW4gPSBtZWRpYW4oY29uc3VtcHRpb25fZ3doKSwKICAgIHEzID0gcXVhbnRpbGUoY29uc3VtcHRpb25fZ3doLCAwLjc1KSwKICAgIG1heCA9IG1heChjb25zdW1wdGlvbl9nd2gpLAogICAgdmFyID0gdmFyKGNvbnN1bXB0aW9uX2d3aCksCiAgICBzZCA9IHNkKGNvbnN1bXB0aW9uX2d3aCksCiAgICBza2V3bmVzcyA9IHNrZXduZXNzKGNvbnN1bXB0aW9uX2d3aCksCiAgICBrdXJ0b3NpcyA9IGt1cnRvc2lzKGNvbnN1bXB0aW9uX2d3aCksCiAgICBJUVIgPSBJUVIoY29uc3VtcHRpb25fZ3doKSwKICAgIE1BRCA9IG1hZChjb25zdW1wdGlvbl9nd2gsIGNlbnRlciA9IG1lYW4oY29uc3VtcHRpb25fZ3doKSksCiAgICBNU0QgPSBtZWFuKChjb25zdW1wdGlvbl9nd2ggLSBtZWFuKGNvbnN1bXB0aW9uX2d3aCkpXjIpCiAgKSB8PgogIHBpdm90X2xvbmdlcihldmVyeXRoaW5nKCksCiAgICBuYW1lc190byA9ICJTdGF0aXN0aWMiLAogICAgdmFsdWVzX3RvID0gIlZhbHVlIgogICkgfD4KICBtdXRhdGUoVmFsdWUgPSByb3VuZChWYWx1ZSwgMikpCgoKa2JsKGNvbnN1bXB0aW9uX2d3aF9zdGF0cykgfD4KICBrYWJsZV9zdHlsaW5nKGJvb3RzdHJhcF9vcHRpb25zID0gInN0cmlwZWQiLAogICAgICAgICAgICAgICAgZnVsbF93aWR0aCA9IEZBTFNFLAogICAgICAgICAgICAgICAgcG9zaXRpb24gPSAiY2VudGVyIikKYGBgCgpXZSBvYnNlcnZlIHRoYXQ6CgotICAgVGhlIHRvdGFsIHJlc2lkZW50aWFsIGdhcyBjb25zdW1wdGlvbiB3YXMKICAgIGByIGNvbnN1bXB0aW9uX2d3aF9zdGF0cyB8PiBmaWx0ZXIoU3RhdGlzdGljID09ICJzdW0iKSB8PiBwdWxsKFZhbHVlKSB8PiBmb3JtYXQoYmlnLm1hcmsgPSAiLCIsIHNjaWVudGlmaWMgPSBGQUxTRSlgCiAgICBHV2guCi0gICBUaGUgYXZlcmFnZSBtb250aGx5IHJlc2lkZW50aWFsIGdhcyBjb25zdW1wdGlvbiBpcwogICAgYHIgY29uc3VtcHRpb25fZ3doX3N0YXRzIHw+IGZpbHRlcihTdGF0aXN0aWMgPT0gIm1lYW4iKSB8PiBwdWxsKFZhbHVlKSB8PiByb3VuZCgyKWAKICAgIEdXaC4KCiMjIyBIaXN0b2dyYW1zCgpMZXQgdXMgZXhhbWluZSB0aGUgZGlzdHJpYnV0aW9uIG9mIHRoZSBkYXRhLgoKYGBge3IgaGlzdG9ncmFtcywgZWNobyA9IEZBTFNFfQpid19jb25zIDwtIDIgKiBJUVIoZGYkY29uc3VtcHRpb25fZ3doKSAvIGxlbmd0aChkZiRjb25zdW1wdGlvbl9nd2gpXigxIC8gMykKCnAxIDwtIGdncGxvdChkZiwgYWVzKHggPSBjb25zdW1wdGlvbl9nd2gpKSArCiAgZ2VvbV9oaXN0b2dyYW0oYmlud2lkdGggPSBid19jb25zLCBmaWxsID0gImxpZ2h0Z3JleSIsIGNvbG9yID0gImdyZXkzNSIpICsKICB0aGVtZV9taW5pbWFsKCkgKwogIGxhYnMoCiAgICB4ID0gIk1vbnRobHkgZ2FzIGNvbnN1bXB0aW9uIGluIEdXaCIsCiAgICB5ID0gIkZyZXF1ZW5jeSIKICApCgpid190ZW1wIDwtIDIgKiBJUVIoZGYkdGVtcF9jZWxjaXVzKSAvIGxlbmd0aChkZiR0ZW1wX2NlbGNpdXMpXigxIC8gMykKCnAyIDwtIGdncGxvdChkZiwgYWVzKHggPSB0ZW1wX2NlbGNpdXMpKSArCiAgZ2VvbV9oaXN0b2dyYW0oYmlud2lkdGggPSBid190ZW1wLCBmaWxsID0gImxpZ2h0Z3JleSIsIGNvbG9yID0gImdyZXkzNSIpICsKICB0aGVtZV9taW5pbWFsKCkgKwogIGxhYnMoCiAgICB4ID0gIk1lYW4gbW9udGhseSB0ZW1wZXJhdHVyZSBpbiBkZWdyZWVzIENlbGNpdXMiLAogICAgeSA9ICJGcmVxdWVuY3kiCiAgKQoKZ3JpZC5hcnJhbmdlKHAxLCBwMiwgbmNvbCA9IDIpCmBgYAoKIyMjIERlbnNpdHkgcGxvdHMKCmBgYHtyLCBkZW5zaXR5X3Bsb3RzLCBlY2hvID0gRkFMU0V9CnAxIDwtIGdncGxvdChkZiwgYWVzKHggPSBjb25zdW1wdGlvbl9nd2gpKSArCiAgZ2VvbV9kZW5zaXR5KGZpbGwgPSAibGlnaHRncmV5IiwgY29sb3IgPSAibGlnaHRncmV5IikgKwogIHRoZW1lX21pbmltYWwoKSArCiAgbGFicygKICAgIHggPSAiTW9udGhseSBnYXMgY29uc3VtcHRpb24gaW4gR1doIiwKICAgIHkgPSBOVUxMCiAgKSArCiAgdGhlbWUoCiAgICBheGlzLnRleHQueSA9IGVsZW1lbnRfYmxhbmsoKSwKICAgIGF4aXMudGlja3MueSA9IGVsZW1lbnRfYmxhbmsoKSwKICAgIHBhbmVsLmdyaWQubWFqb3IueSA9IGVsZW1lbnRfYmxhbmsoKSwKICAgIHBhbmVsLmdyaWQubWlub3IueSA9IGVsZW1lbnRfYmxhbmsoKQogICkKCnAyIDwtIGdncGxvdChkZiwgYWVzKHggPSB0ZW1wX2NlbGNpdXMpKSArCiAgZ2VvbV9kZW5zaXR5KGZpbGwgPSAibGlnaHRncmV5IiwgY29sb3IgPSAibGlnaHRncmV5IikgKwogIHRoZW1lX21pbmltYWwoKSArCiAgbGFicygKICAgIHggPSAiTWVhbiBtb250aGx5IHRlbXBlcmF0dXJlIGluIGRlZ3JlZXMgQ2VsY2l1cyIsCiAgICB5ID0gTlVMTAogICkgKwogIHRoZW1lKAogICAgYXhpcy50ZXh0LnkgPSBlbGVtZW50X2JsYW5rKCksCiAgICBheGlzLnRpY2tzLnkgPSBlbGVtZW50X2JsYW5rKCksCiAgICBwYW5lbC5ncmlkLm1ham9yLnkgPSBlbGVtZW50X2JsYW5rKCksCiAgICBwYW5lbC5ncmlkLm1pbm9yLnkgPSBlbGVtZW50X2JsYW5rKCkKICApCgpncmlkLmFycmFuZ2UocDEsIHAyLCBuY29sID0gMikKYGBgCgpXZSBvYnNlcnZlIHRoYXQgYm90aCBkaXN0cmlidXRpb25zIGFyZSBiaW1vZGFsLiBUaGUgdGVtcGVyYXR1cmUKZGlzdHJpYnV0aW9uIGhhcyBhIG1vcmUgcHJvbm91bmNlZCBiaW1vZGFsIGZlYXR1cmUuCgojIyMgQm94cGxvdHMKCk9uZSBzaW1wbGUgeWV0IGVmZmVjdGl2ZSBtZXRob2QgdG8gZGV0ZWN0IG91dGxpZXJzIGdyYXBoaWNhbGx5IGlzIHRoZQpib3hwbG90LiBUaGVzZSBhcmUgdGhlIGJveHBsb3RzIGZvciBvdXIgdHdvIHZhcmlhYmxlcy4KCmBgYHtyIGJveHBsb3RzLCBlY2hvID0gRkFMU0UsIGZpZy5oZWlnaHQ9Mn0KcDEgPC0gZ2dwbG90KGRmLCBhZXMoeCA9IGNvbnN1bXB0aW9uX2d3aCkpICsKICBnZW9tX2JveHBsb3Qob3V0bGllcnMgPSBUUlVFKSArCiAgdGhlbWVfbWluaW1hbCgpICsKICB0aGVtZSgKICAgIGF4aXMudGl0bGUueSA9IGVsZW1lbnRfYmxhbmsoKSwKICAgIGF4aXMudGV4dC55ID0gZWxlbWVudF9ibGFuaygpLAogICAgYXhpcy50aWNrcy55ID0gZWxlbWVudF9ibGFuaygpLAogICAgcGFuZWwuZ3JpZC5tYWpvci55ID0gZWxlbWVudF9ibGFuaygpLAogICAgcGFuZWwuZ3JpZC5taW5vci55ID0gZWxlbWVudF9ibGFuaygpCiAgKSArCiAgbGFicyh4ID0gIk1vbnRobHkgZ2FzIGNvbnN1bXB0aW9uIGluIEdXaCIsIHRpdGxlID0gTlVMTCkKCnAyIDwtIGdncGxvdChkZiwgYWVzKHggPSB0ZW1wX2NlbGNpdXMpKSArCiAgZ2VvbV9ib3hwbG90KG91dGxpZXJzID0gVFJVRSkgKwogIHRoZW1lX21pbmltYWwoKSArCiAgdGhlbWUoCiAgICBheGlzLnRpdGxlLnkgPSBlbGVtZW50X2JsYW5rKCksCiAgICBheGlzLnRleHQueSA9IGVsZW1lbnRfYmxhbmsoKSwKICAgIGF4aXMudGlja3MueSA9IGVsZW1lbnRfYmxhbmsoKSwKICAgIHBhbmVsLmdyaWQubWFqb3IueSA9IGVsZW1lbnRfYmxhbmsoKSwKICAgIHBhbmVsLmdyaWQubWlub3IueSA9IGVsZW1lbnRfYmxhbmsoKQogICkgKwogIGxhYnMoeCA9ICJNZWFuIG1vbnRobHkgdGVtcGVyYXR1cmUgaW4gZGVncmVlcyBDZWxjaXVzIiwgdGl0bGUgPSBOVUxMKQoKZ3JpZC5hcnJhbmdlKHAxLCBwMiwgbmNvbCA9IDIpCmBgYAoKVGhlIGxvd2VyIGFuZCB1cHBlciBoaW5nZXMgY29ycmVzcG9uZCB0byB0aGUgZmlyc3QgYW5kIHRoaXJkIHF1YXJ0aWxlcwoodGhlIDI1dGggYW5kIDc1dGggcGVyY2VudGlsZXMpLiBUaGUgbGluZSBiZXR3ZWVuIHRoZSBoaW5nZXMgY29ycmVzcG9uZHMKdG8gdGhlIG1lZGlhbi4gVGhlIHVwcGVyIHdoaXNrZXIgZXh0ZW5kcyBmcm9tIHRoZSBoaW5nZSB0byB0aGUgbGFyZ2VzdAp2YWx1ZSBubyBmdXJ0aGVyIHRoYW4gMS41IFwqIElRUiBmcm9tIHRoZSBoaW5nZS4gSVFSIGlzIHRoZSBkaXN0YW5jZQpiZXR3ZWVuIHRoZSBmaXJzdCBhbmQgdGhpcmQgcXVhcnRpbGVzLiBUaGUgbG93ZXIgd2hpc2tlciBleHRlbmRzIGZyb20KdGhlIGhpbmdlIHRvIHRoZSBzbWFsbGVzdCB2YWx1ZSBhdCBtb3N0IDEuNSBcKiBJUVIgb2YgdGhlIGhpbmdlLiBEYXRhCmJleW9uZCB0aGUgZW5kIG9mIHRoZSB3aGlza2VycyBhcmUgY2FsbGVkICJvdXRsaWVycyIgYW5kIGFyZSBwbG90dGVkCmluZGl2aWR1YWxseS4KCldlIG9ic2VydmUgdGhhdCBib3RoIGRpc3RyaWJ1dGlvbnMgZG8gbm90IGNvbnRhaW4gYW55IG91dGxpZXJzLgoKIyMjIFRpbWUgcGxvdHMKClBlcmhhcHMgdGhlIG1vc3QgdXNlZnVsIGRhdGEgdmlzdWFsaXphdGlvbiB3aGVuIGl0IGNvbWVzIHRvIHRpbWUgc2VyaWVzCmlzIHRoZSB0aW1lIHBsb3QuIEhlcmUgaXMgdGhlIHRpbWUgcGxvdCBmb3Igb3VyIGRhdGEuCgpgYGB7ciB0aW1lX3Bsb3RzLCBlY2hvID0gRkFMU0UsIGZpZy5oZWlnaHQgPSA3fQpwMSA8LSBkZiB8PgogIGF1dG9wbG90KGNvbnN1bXB0aW9uX2d3aCkgKwogIGxhYnMoCiAgICB4ID0gIk1vbnRoIiwKICAgIHkgPSBOVUxMLAogICAgdGl0bGUgPSAiTW9udGhseSBnYXMgY29uc3VtcHRpb24gaW4gR1doIgogICkgKwogIHlsaW0oMCwgTkEpICsKICB0aGVtZV9taW5pbWFsKCkKCnAyIDwtIGRmIHw+CiAgYXV0b3Bsb3QodGVtcF9jZWxjaXVzKSArCiAgbGFicygKICAgIHggPSAiTW9udGgiLAogICAgeSA9IE5VTEwsCiAgICB0aXRsZSA9ICJNZWFuIG1vbnRobHkgdGVtcGVyYXR1cmUgaW4gZGVncmVlcyBDZWxjaXVzIgogICkgKwogIHRoZW1lX21pbmltYWwoKQoKZ3JpZC5hcnJhbmdlKHAxLCBwMiwgbnJvdyA9IDIsIG5jb2wgPSAxKQpgYGAKClRoZSB0aW1lIHBsb3Qgb2YgdGhlIGdhcyBjb25zdW1wdGlvbiAodXBwZXIgcGxvdCkgaW1tZWRpYXRlbHkgcmV2ZWFscwpzb21lIGludGVyZXN0aW5nIGZlYXR1cmVzLgoKLSAgIFBlYWtzIGhhcHBlbiBpbiB0aGUgd2ludGVyLgotICAgTG93IHBvaW50cyBoYXBwZW4gaW4gdGhlIHN1bW1lci4KLSAgIFRoZXJlIGlzIGEgZGVjcmVhc2luZyB0cmVuZC4KLSAgIFRoZSBzZWFzb25hbCBwYXR0ZXJuIGluY3JlYXNlcyBpbiBzaXplIGFzIHRoZSBsZXZlbCBvZiB0aGUgc2VyaWVzCiAgICBpbmNyZWFzZXMuIFRoaXMgY2F1c2VzIHRoZSB2YXJpYW5jZSB0byBpbmNyZWFzZSBvdmVyIHRpbWUgYW5kIGl0IGlzCiAgICBhbHNvIGtub3duIGFzCiAgICBbaGV0ZXJvc2tlZGFzdGljaXR5XShodHRwczovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9Ib21vc2NlZGFzdGljaXR5X2FuZF9oZXRlcm9zY2VkYXN0aWNpdHkpLgoKVGhlIHNwaWtlcyBkdXJpbmcgdGhlIHdpbnRlciBtb250aHMgYXJlIHByb2JhYmx5IGNhdXNlZCBkdWUgdG8gaG91c2Vob2xkCmdhcyBoZWF0aW5nLiBTaW1pbGFybHksIHRoZSBsb3cgcG9pbnRzIGluIHRoZSBzdW1tZXIgY291bGQgYmUgZHVlIHRvIHRoZQpyZWR1Y2VkIG5lZWQgZm9yIGhvdXNlaG9sZCBnYXMgaGVhdGluZy4KClRoZSB0aW1lIHBsb3Qgb2YgdGhlIG1lYW4gbW9udGhseSB0ZW1wZXJhdHVyZSAobG93ZXIgcGxvdCkgZXhoaWJpdHMgdGhlCm9wcG9zaXRlIHBhdHRlcm4uCgotICAgUGVha3MgaGFwcGVuIGluIHRoZSBzdW1tZXIKLSAgIExvdyBwb2ludHMgaGFwcGVuIGluIHRoZSB3aW50ZXIuCi0gICBUaGVyZSBpcyBhIGZsYXQgdHJlbmQuCi0gICBUaGUgZGF0YSBhcHBlYXJzIHRvIGJlIGhvbW9za2VkYXN0aWMuCgpCb3RoIHRpbWUgc2VyaWVzIGhhdmUgYSBzdHJvbmcgc2Vhc29uYWwgcGF0dGVybi4KCiMjIyBTZWFzb25hbCBwbG90cwoKQSBzZWFzb25hbCBwbG90IGlzIHNpbWlsYXIgdG8gYSB0aW1lIHBsb3QgZXhjZXB0IHRoYXQgdGhlIGRhdGEgYXJlCnBsb3R0ZWQgYWdhaW5zdCB0aGUgaW5kaXZpZHVhbCBtb250aCBpbiB3aGljaCB0aGUgZGF0YSB3ZXJlIG9ic2VydmVkLgoKYGBge3Igc2Vhc29uYWxfcGxvdF9jb25zdW1wdGlvbiwgZWNobyA9IEZBTFNFfQpkZiB8PgogIGdnX3NlYXNvbihjb25zdW1wdGlvbl9nd2gsIGxhYmVscyA9ICJib3RoIiwgbGFiZWxzX3JlcGVsID0gVFJVRSkgKwogIGxhYnMoCiAgICB4ID0gIk1vbnRoIiwKICAgIHkgPSBOVUxMLAogICAgdGl0bGUgPSAiU2Vhc29uYWwgcGxvdDogTW9udGhseSByZXNpZGVudGlhbCBnYXMgY29uc3VtcHRpb24gaW4gR1doIgogICkgKwogIHlsaW0oMCwgTkEpICsKICB0aGVtZV9taW5pbWFsKCkKYGBgCgpJbiBhZGRpdGlvbiB0byB0aGUgb2JzZXJ2YXRpb25zIG1hZGUgYnkgdGhlIHRpbWUgcGxvdCwgd2Ugb2JzZXJ2ZSB0aGF0OgoKLSAgIEZlYnJ1YXJ5IGFuZCBNYXJjaCAyMDE4IGhhdmUgYSBoaWdoZXIgZ2FzIGNvbnN1bXB0aW9uIHRoYW4gdGhlIHNhbWUKICAgIG1vbnRocyBpbiBvdGhlciB5ZWFycy4KLSAgIEZlYnJ1YXJ5IDIwMjQgaGFzIGEgbG93ZXIgZ2FzIGNvbnN1bXB0aW9uIHRoYW4gdGhlIHNhbWUgbW9udGggaW4KICAgIG90aGVyIHllYXJzLgotICAgVGhlcmUgYXJlIHR3byAiY2x1c3RlcnMiIG9mIGN1cnZlcy4gVGhlIGZpcnN0IGNsdXN0ZXIgaGFzIDIwMTcgdG8KICAgIDIwMjEgY3VydmVzIGFuZCB0aGUgc2Vjb25kIGNsdXN0ZXIgaGFzIDIwMjIgdG8gMjAyNCBjdXJ2ZXMuIFRoZQogICAgY3VydmVzIG9mIHRoZSBzZWNvbmQgY2x1c3RlciBhcmUgYmVsb3cgdGhhbiB0aGUgY3VydmVzIG9mIHRoZSBmaXJzdAogICAgY2x1c3RlciwgZnJvbSBBcHJpbCB0byBOb3ZlbWJlci4gVGhpcyBjb3VsZCBiZSBleHBsYWluZWQgYnkgdGhlCiAgICBoaWdoZXItdGhhbi11c3VhbCByZXNpZGVudGlhbCBnYXMgcHJpY2VzIG9ic2VydmVkIGZyb20gMjAyMiB1bnRpbAogICAgMjAyNC4KClRoZSBoaWdoZXItdGhhbi11c3VhbCBnYXMgY29uc3VtcHRpb24gaW4gRmVicnVhcnkgYW5kIE1hcmNoIDIwMTggaXMgbW9zdApsaWtlbHkgZXhwbGFpbmVkIGJ5IHRoZSBsb3cgbWVhbiB0ZW1wZXJhdHVyZSBkdXJpbmcgdGhlc2UgbW9udGhzLCBhcwpvYnNlcnZlZCBpbiB0aGUgZ3JhcGggYmVsb3cuCgpgYGB7ciBzZWFzb25hbF9wbG90X3RlbXBlcmF0dXJlLCBlY2hvID0gRkFMU0UsIHdhcm5pbmcgPSBGQUxTRX0KZGYgfD4KICBnZ19zZWFzb24odGVtcF9jZWxjaXVzLCBsYWJlbHMgPSAiYm90aCIsIGxhYmVsc19yZXBlbCA9IFRSVUUpICsKICBsYWJzKAogICAgeCA9ICJNb250aCIsCiAgICB5ID0gTlVMTCwKICAgIHRpdGxlID0gIlNlYXNvbmFsIHBsb3Q6IE1lYW4gbW9udGhseSB0ZW1wZXJhdHVyZSBpbiBkZWdyZWVzIENlbGNpdXMiCiAgKSArCiAgdGhlbWVfbWluaW1hbCgpCmBgYAoKIyMjIFNlYXNvbmFsIHN1YnNlcmllcyBwbG90CgpBbiBhbHRlcm5hdGl2ZSBwbG90IHRoYXQgZW1waGFzaXplcyB0aGUgc2Vhc29uYWwgcGF0dGVybnMgaXMgd2hlcmUgdGhlCmRhdGEgZm9yIGVhY2ggc2Vhc29uIGFyZSBjb2xsZWN0ZWQgdG9nZXRoZXIgaW4gc2VwYXJhdGUgbWluaSB0aW1lIHBsb3RzLgpUaGUgYmx1ZSBob3Jpem9udGFsIGxpbmVzIGluZGljYXRlIHRoZSBtZWFucyBmb3IgZWFjaCBtb250aC4gVGhlIHgtYXhpcwppbmRpY2F0ZXMgdGhlIHllYXIuCgpgYGB7ciBzZWFzb25hbF9zdWJzZXJpZXNfcGxvdF9jb25zdW1wdGlvbiwgZWNobyA9IEZBTFNFfQpkZiB8PgogIGdnX3N1YnNlcmllcyhjb25zdW1wdGlvbl9nd2gpICsKICBsYWJzKAogICAgeCA9ICJZZWFyIiwKICAgIHkgPSBOVUxMLAogICAgdGl0bGUgPSAiU2Vhc29uYWwgc3Vic2VyaWVzIHBsb3Q6IE1vbnRobHkgZ2FzIGNvbnN1bXB0aW9uIGluIEdXaCIKICApICsKICB5bGltKDAsIE5BKSArCiAgdGhlbWVfbWluaW1hbCgpICsKICB0aGVtZSgKICAgIGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gOTAsIGhqdXN0ID0gMSwgdmp1c3QgPSAwLjUpLAogICAgcGFuZWwuZ3JpZC5taW5vci54ID0gZWxlbWVudF9ibGFuaygpCiAgKQpgYGAKCldlIG9ic2VydmUgdGhhdCB0aGUgcGF0dGVybiBpcyBzaW1pbGFyIGJldHdlZW4gbW9udGhzLCBleGNlcHQgZnJvbQpKYW51YXJ5LgoKYGBge3Igc2Vhc29uYWxfc3Vic2VyaWVzX3Bsb3RfdGVtcGVyYXR1cmUsIGVjaG8gPSBGQUxTRX0KZGYgfD4KICBnZ19zdWJzZXJpZXModGVtcF9jZWxjaXVzKSArCiAgbGFicygKICAgIHggPSAiWWVhciIsCiAgICB5ID0gTlVMTCwKICAgIHRpdGxlID0gIlNlYXNvbmFsIHN1YnNlcmllcyBwbG90OiBNb250aGx5IHRlbXBlcmF0dXJlIGluIGRlZ3JlZXMgQ2VsY2l1cyIKICApICsKICB0aGVtZV9taW5pbWFsKCkgKwogIHRoZW1lKAogICAgYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA5MCwgaGp1c3QgPSAxLCB2anVzdCA9IDAuNSksCiAgICBwYW5lbC5ncmlkLm1pbm9yLnggPSBlbGVtZW50X2JsYW5rKCkKICApCmBgYAoKV2UgZG8gbm90IGRldGVjdCBhbnkgY2xlYXIgcGF0dGVybiBpbiB0aGlzIHNlYXNvbmFsIHN1YnNlcmllcyBncmFwaC4KClVwIHVudGlsIG5vdywgd2UgaGF2ZSBvYnNlcnZlZCBlYWNoIHRpbWUgc2VyaWVzIGluZGl2aWR1YWxseS4gVGhpcyBpcwphbHNvIGNhbGxlZCBhIHVuaXZhcmlhdGUgYW5hbHlzaXMuIE5leHQsIHdlIHdpbGwgbG9vayBhdCBob3cgdGhlc2UgdGltZQpzZXJpZXMgYmVoYXZlIHRvZ2V0aGVyLiBUaGlzIGlzIGFsc28gY2FsbGVkIGEgbXVsdGl2YXJpYXRlIGFuYWx5c2lzLgoKIyMjIFNjYXR0ZXJwbG90CgpMZXQgdXMgdmlzdWFsaXplIHRoZSBkYXRhIHBvaW50cyBvZiBnYXMgY29uc3VtcHRpb24gYW5kIG1lYW4gdGVtcGVyYXR1cmUKdG9nZXRoZXIuIFRoZSBtb3N0IGNvbW1vbiBwbG90IGZvciB0aGlzIHRhc2sgaXMgdGhlIHNjYXR0ZXJwbG90LCBhcwpzaG93biBiZWxvdy4gQSBsaW5lYXIgZml0IGlzIGFsc28gcGxvdHRlZC4KCmBgYHtyIHNjYXR0ZXJwbG90LCBlY2hvID0gRkFMU0V9CmdncGxvdChkZiwgYWVzKHggPSB0ZW1wX2NlbGNpdXMsIHkgPSBjb25zdW1wdGlvbl9nd2gpKSArCiAgZ2VvbV9wb2ludChzaXplID0gMywgc2hhcGUgPSAxKSArCiAgZ2VvbV9zbW9vdGgobWV0aG9kID0gImxtIiwgZm9ybXVsYSA9ICJ5IH4geCIpICsKICBsYWJzKAogICAgeCA9ICJNZWFuIHRlbXBlcmF0dXJlIGluIENlbGNpdXMiLAogICAgeSA9ICJDb25zdW1wdGlvbiBpbiBHV2giLAogICAgdGl0bGUgPSBOVUxMCiAgKSArCiAgdGhlbWVfbWluaW1hbCgpCmBgYAoKQXMgZXhwZWN0ZWQsIHdlIG9ic2VydmUgYSBuZWdhdGl2ZSBjb3JyZWxhdGlvbiBiZXR3ZWVuIG1lYW4gdGVtcGVyYXR1cmUKYW5kIGdhcyBjb25zdW1wdGlvbi4gV2UgYWxzbyBvYnNlcnZlIHRoYXQgdGhlIHVwcGVyIGxlZnQgY29ybmVyIChsb3cKdGVtcGVyYXR1cmUsIGhpZ2ggY29uc3VtcHRpb24pIGhhcyBkYXRhIHBvaW50cyBjbG9zZXIgdG8gdGhlIGxpbmVhcgpyZWdyZXNzaW9uIGxpbmUuIEluIGNvbnRyYXN0LCB0aGUgbG93ZXIgcmlnaHQgY29ybmVyIChoaWdoIHRlbXBlcmF0dXJlLApsb3cgY29uc3VtcHRpb24pIGhhcyBkYXRhIHBvaW50cyBzY2F0dGVyZWQgYXdheSBmcm9tIHRoZSBsaW5lYXIKcmVncmVzc2lvbiBsaW5lLgoKVGhlIGNvcnJlbGF0aW9uIGNvZWZmaWNpZW50IG1lYXN1cmVzIHRoZSBzdHJlbmd0aCBvZiB0aGUgKipsaW5lYXIqKgpyZWxhdGlvbnNoaXAgYmV0d2VlbiBtZWFuIHRlbXBlcmF0dXJlIGFuZCBnYXMgY29uc3VtcHRpb24uIEZvciB0aGlzCmRhdGEsIHRoZSBjb3JyZWxhdGlvbiBjb2VmZmljaWVudCBpcwpgciByb3VuZChjb3IoZGYkY29uc3VtcHRpb25fZ3doLCBkZiR0ZW1wX2NlbGNpdXMpLCAyKWAuCgpBcyBzaG93biBiZWxvdywgdGhlIGNvcnJlbGF0aW9uIHRlc3QgaW5kaWNhdGVzIHRoYXQgdGhlIGNvcnJlbGF0aW9uCmNvZWZmaWNpZW50IGlzIHNpZ25pZmljYW50bHkgZGlmZmVyZW50IHRoYW4gemVyby4KCmBgYHtyIGNvcnJlbGF0aW9uX3Rlc3R9CmNvci50ZXN0KGRmJGNvbnN1bXB0aW9uX2d3aCwgZGYkdGVtcF9jZWxjaXVzLCBtZXRob2QgPSAicGVhcnNvbiIsCiAgICAgICAgIGFsdGVybmF0aXZlID0gInR3by5zaWRlZCIsIGNvbmYubGV2ZWwgPSAwLjk1KQpgYGAKCiMjIyBMYWcgcGxvdHMKClRoZSBmaWd1cmUgYmVsb3cgZGlzcGxheXMgc2NhdHRlcnBsb3RzIHdoZXJlIHRoZSBob3Jpem9udGFsIGF4aXMgc2hvd3MKbGFnZ2VkIHZhbHVlcyAoaykgb2YgdGhlIHRpbWUgc2VyaWVzLiBFYWNoIGdyYXBoIHNob3dzXAptb250aGx5IGdhcyBjb25zdW1wdGlvbiBkYXRhIHBvaW50cyBwbG90dGVkIGFnYWluc3QgdGhlbXNlbHZlcyBhdApkaWZmZXJlbnQgbGFncy4KCmBgYHtyIGxhZ19wbG90fQpkZiB8PgogIGdnX2xhZyhjb25zdW1wdGlvbl9nd2gsIGdlb20gPSAicG9pbnQiLCBsYWdzID0gMToxMikgKwogIGxhYnMoCiAgICB4ID0gImxhZyhnYXMgY29uc3VtcHRpb24gaW4gR1doLCBrKSIsCiAgICB5ID0gIkdhcyBjb25zdW1wdGlvbiBpbiBHV2giLAogICAgY29sb3IgPSAiTW9udGgiCiAgKSArCiAgdGhlbWVfbWluaW1hbCgpCmBgYAoKVGhlIGNvbG9ycyBpbmRpY2F0ZSB0aGUgbW9udGggb2YgdGhlIHZhcmlhYmxlIG9uIHRoZSB2ZXJ0aWNhbCBheGlzLiBUaGUKcmVsYXRpb25zaGlwIGlzIHN0cm9uZ2x5IHBvc2l0aXZlIGF0IGxhZ3MgMSBhbmQgMTIsIHJlZmxlY3RpbmcgdGhlCnN0cm9uZyBzZWFzb25hbGl0eSBpbiB0aGUgZGF0YS4gVGhlIG5lZ2F0aXZlIHJlbGF0aW9uc2hpcCBzZWVuIGZvciBsYWcgNgpvY2N1cnMgYmVjYXVzZSBwZWFrcyBvZiBnYXMgY29uc3VtcHRpb24gKGluIHRoZSB3aW50aGVyKSBhcmUgcGxvdHRlZAphZ2FpbnN0IHRyb3VnaHMgKGluIHRoZSBzdW1tZXIpLgoKIyMjIEF1dG9jb3JyZWxhdGlvbgoKSnVzdCBhcyBjb3JyZWxhdGlvbiBtZWFzdXJlcyB0aGUgZXh0ZW50IG9mIGEgbGluZWFyIHJlbGF0aW9uc2hpcCBiZXR3ZWVuCnR3byB2YXJpYWJsZXMsIGF1dG9jb3JyZWxhdGlvbiBtZWFzdXJlcyB0aGUgbGluZWFyIHJlbGF0aW9uc2hpcCBiZXR3ZWVuCmxhZ2dlZCB2YWx1ZXMgb2YgYSB0aW1lIHNlcmllcy4KClRoZXJlIGFyZSBzZXZlcmFsIGF1dG9jb3JyZWxhdGlvbiBjb2VmZmljaWVudHMsIGNvcnJlc3BvbmRpbmcgdG8gZWFjaApwYW5lbCBpbiB0aGUgbGFnIHBsb3QgYWJvdmUuCgpUaGUgYXV0b2NvcnJlbGF0aW9uIGNvZWZmaWNpZW50cyBtYWtlIHVwIHRoZSAqYXV0b2NvcnJlbGF0aW9uIGZ1bmN0aW9uKgpvciBBQ0YuCgpgYGB7ciBhY2Z9CmRmIHw+CiAgQUNGKGNvbnN1bXB0aW9uX2d3aCwgbGFnX21heCA9IDQ4KSB8PgogIGF1dG9wbG90KCkgKwogIGxhYnMoCiAgICB0aXRsZSA9ICJBQ0YgcGxvdDogTW9udGhseSBnYXMgY29uc3VtcHRpb24gaW4gR1doIiwKICAgIHggPSAiTGFnIGluIG1vbnRocyIsCiAgICB5ID0gIkFDRiIKICApICsKICB0aGVtZV9taW5pbWFsKCkKYGBgCgpJbiB0aGlzIGdyYXBoOgoKLSAgIFRoZSBhdXRvY29ycmVsYXRpb24gY29lZmZpY2llbnRzIGF0IGxhZyAxLCAxMiwgMjQsIGV0Yy4gKGRlbm90ZWQKICAgICRyXzEkLCAkcl97MTJ9JCwgYW5kICRyX3syNH0kIHJlc3BlY3RpdmVseSkgYXJlIGhpZ2guIFRoaXMgaXMgZHVlIHRvCiAgICB0aGUgc2Vhc29uYWwgcGF0dGVybiBpbiB0aGUgZGF0YTogdGhlIHBlYWtzIHRlbmQgdG8gYmUgMTIgbW9udGhzCiAgICBhcGFydCBhbmQgdGhlIGxvdyBwb2ludHMgdGVuZCB0byBhbHNvIGJlIDEyIG1vbnRocyBhcGFydC4KLSAgIFRoZSBkYXNoZWQgYmx1ZSBsaW5lcyBpbmRpY2F0ZSB3aGV0aGVyIHRoZSBjb3JyZWxhdGlvbnMgYXJlCiAgICBzaWduaWZpY2FudGx5IGRpZmZlcmVudCBmcm9tIHplcm8uIElmIGFuIGF1dG9jb3JyZWxhdGlvbiBjb2VmZmljaWVudAogICAgbGllcyBvdXRzaWRlIHRoZSBibHVlIGJvdW5kLCBpdCBpcyBzaWduaWZpY2FudGx5IGRpZmZlcmVudCBmcm9tCiAgICB6ZXJvLgoKIyMjIEJveC1Db3ggdHJhbnNmb3JtYXRpb24KCkZvciBtb3JlIGRldGFpbHMsIHBsZWFzZSByZWZlciB0byBbQGZwcDNdLgoKYGBge3IgYm94X2NveH0KbGFtYmRhIDwtIGRmIHw+CiAgZmVhdHVyZXMoY29uc3VtcHRpb25fZ3doLCBmZWF0dXJlcyA9IGd1ZXJyZXJvKSB8PgogIHB1bGwobGFtYmRhX2d1ZXJyZXJvKQpgYGAKClRoZSBvcHRpbWFsIGxhbWJkYSBmb3IgdmFyaWFuY2Ugc3RhYmlsaXphdGlvbiBpcyBgciByb3VuZChsYW1iZGEsIDIpYC4KCmBgYHtyIHRyYW5zZm9ybWVkX3NlcmllcywgZWNobz1GQUxTRX0KZGYgfD4KICBhdXRvcGxvdChib3hfY294KGNvbnN1bXB0aW9uX2d3aCwgbGFtYmRhKSkgKwogIGxhYnMoCiAgICB4ID0gIk1vbnRoIiwKICAgIHkgPSAiVHJhbnNmb3JtZWQgZ2FzIGNvbnN1bXB0aW9uIiwKICAgIHRpdGxlID0gVGVYKHBhc3RlMCgKICAgICAgIkJveC1Db3ggdHJhbnNmb3JtYXRpb24gd2l0aCAkXFxsYW1iZGEkID0gIiwKICAgICAgcm91bmQobGFtYmRhLCAyKQogICAgKSkKICApICsKICB5bGltKDAsIE5BKSArCiAgdGhlbWVfbWluaW1hbCgpCmBgYAoKIyMjIFRpbWUgc2VyaWVzIGRlY29tcG9zaXRpb24KCmBgYHtyIGRlY29tcG9zaXRpb25fdGFibGV9CmRjbXAgPC0gZGYgfD4KICBtb2RlbChzdGwgPSBTVEwoY29uc3VtcHRpb25fZ3doKSkgfD4KICBjb21wb25lbnRzKCkKCmRjbXAKYGBgCgpgYGB7ciBkZWNvbXBvc2l0aW9uX3Bsb3RzLCBlY2hvID0gRkFMU0UsIGZpZy5oZWlnaHQgPSAxMH0KZGNtcCB8PgogIGF1dG9wbG90KCkgKwogIHRoZW1lX21pbmltYWwoKSArCiAgbGFicyh4ID0gIk1vbnRoIikKYGBgCgojIyMgVHJlbmQgYW5kIHNlYXNvbmFsIHN0cmVuZ3RoCgpgYGB7ciBzdHJlbmd0aF9kYXRhLCBlY2hvID0gRkFMU0V9CmZlYXRfc3RsX2NvbnN1bXB0aW9uX2d3aCA8LSBkZiB8PgogIGZlYXR1cmVzKGNvbnN1bXB0aW9uX2d3aCwgZmVhdF9zdGwpIHw+CiAgYXNfdGliYmxlKCkgfD4KICBtdXRhdGUodHMgPSAiTW9udGhseSBnYXMgY29uc3VtcHRpb24gaW4gR1doIiwgLmJlZm9yZSA9IGV2ZXJ5dGhpbmcoKSkKCmZlYXRfc3RsX3RlbXBfY2VsY2l1cyA8LSBkZiB8PgogIGZlYXR1cmVzKHRlbXBfY2VsY2l1cywgZmVhdF9zdGwpIHw+CiAgYXNfdGliYmxlKCkgfD4KICBtdXRhdGUodHMgPSAiTW9udGhseSBtZWFuIHRlbXBlcmF0dXJlIGluIENlbGNpdXMiLCAuYmVmb3JlID0gZXZlcnl0aGluZygpKQoKZmVhdF9zdGwgPC0gcmJpbmQoZmVhdF9zdGxfY29uc3VtcHRpb25fZ3doLCBmZWF0X3N0bF90ZW1wX2NlbGNpdXMpCgpmZWF0X3N0bF90IDwtIGZlYXRfc3RsIHw+CiAgdCgpIHw+CiAgYXMuZGF0YS5mcmFtZSgpIHw+CiAgcm93bmFtZXNfdG9fY29sdW1uKCJGZWF0dXJlIikKICAKY29sbmFtZXMoZmVhdF9zdGxfdCkgPC0gYygiRmVhdHVyZSIsIGZlYXRfc3RsX3RbMSwgMl0sIGZlYXRfc3RsX3RbMSwgM10pCgpmZWF0X3N0bF90IHw+CiAgc2xpY2UoLTEpIHw+IAogIGtibCgpIHw+IAogIGthYmxlX3N0eWxpbmcoYm9vdHN0cmFwX29wdGlvbnMgPSAic3RyaXBlZCIsCiAgICAgICAgICAgICAgICBmdWxsX3dpZHRoID0gRkFMU0UsCiAgICAgICAgICAgICAgICBwb3NpdGlvbiA9ICJjZW50ZXIiKQpgYGAKCmBgYHtyIHN0cmVuZ3RoX3Bsb3QsIGVjaG8gPSBGQUxTRX0KZmVhdF9zdGwgfD4KICBnZ3Bsb3QoYWVzKHggPSB0cmVuZF9zdHJlbmd0aCwgeSA9IHNlYXNvbmFsX3N0cmVuZ3RoX3llYXIpKSArCiAgZ2VvbV9wb2ludChzaXplID0gMykgKwogIGdlb21fdGV4dF9yZXBlbChhZXMobGFiZWwgPSB0cyksCiAgICBib3gucGFkZGluZyA9IDAuNSwKICAgIHBvaW50LnBhZGRpbmcgPSAwLjMsCiAgICBmb3JjZSA9IDEsCiAgICBtYXgub3ZlcmxhcHMgPSAxNQogICkgKwogIHRoZW1lX21pbmltYWwoKSArCiAgeWxpbSgwLCAxKSArCiAgeGxpbSgwLCAxKSArCiAgbGFicyh4ID0gIlRyZW5kIHN0cmVuZ3RoIiwgeSA9ICJTZWFzb25hbCBzdHJlbmd0aCIpCmBgYAoKIyMgUmVmZXJlbmNlcwo=