3 Plotting Our Data
Since this is monthly data, frequency = 12 will be used to define the
time series object.
price.ts <- ts(price_recent[, 2], frequency = 12, start = c(2013, 5))
par(mar = c(2, 2, 2, 2))
plot(
price.ts,
main = "US Regular Conventional Gas Prices: May 2013 to October 2025",
ylab = "Monthly Price (USD per gallon)",
xlab = "")

The time series plot of U.S. gasoline prices from May 2013 to October
2025 shows several clear shifts. Prices decline from about $3.50 in 2013
to a low near $2 in early 2016, then gradually rise through 2019. A
sharp increase begins in 2021, peaking above $4.50 in 2022. After the
peak, prices decline but remain more volatile, settling around the
mid-$3 range through 2023–2025. Overall, the graph highlights a major
upward surge after 2020 followed by partial stabilization.
4 Forecasting with Decomposition
To analyze the underlying structure of the gasoline price time
series, this project applies both classical decomposition and STL
(Seasonal-Trend Decomposition using LOESS). Using both methods provides
a more complete understanding of how the data behaves over time.
Classical decomposition separates the series into trend, seasonal, and
remainder components using fixed seasonal patterns, which helps identify
broad structural features in a straightforward way. STL decomposition,
on the other hand, offers a more flexible and robust approach that can
capture smoother trends and adapt to changes in seasonality. By
performing both methods, the analysis can compare how each technique
represents the data, highlight differences in trend and seasonal
behavior, and ensure that the decomposition used for forecasting is
based on the method that best reflects the characteristics of the
gasoline price series.
4.1 Classical
Here, I apply the classical decomposition to break the series into
its trend, seasonal, and irregular components, providing a baseline
understanding of how the data behaves over time.
cls.decomp = decompose(price.ts)
par(mar=c(2,2,2,2))
plot(cls.decomp, xlab="")

The classical decomposition separates the gasoline price series into
its observed, trend, seasonal, and remainder components. The trend
component shows a gradual decline from 2013 through 2016, followed by a
steady rise leading into the sharp peak around 2022, before leveling off
toward 2025. The seasonal component displays a consistent repeating
yearly pattern, indicating modest but regular seasonal fluctuations in
gasoline prices. The remainder component captures short-term volatility
not explained by trend or seasonality, with larger irregular movements
appearing during periods of rapid price change, particularly around
2020–2022. Overall, classical decomposition reveals a clear long-term
upward trend and stable seasonal behavior throughout the series.
4.2 STL
We will now perform the STL method.
stl.decomp=stl(price.ts, s.window = 12)
par(mar=c(2,2,2,2))
plot(stl.decomp)

The STL decomposition provides a smooth and flexible breakdown of the
gasoline price series into trend, seasonal, and remainder components.
The trend component clearly shows the long downward movement through
2016, followed by a steady rise and a pronounced peak in 2022, before
gradually declining toward 2025. The seasonal component displays a
stable, repeating yearly pattern, indicating that gasoline prices follow
consistent seasonal fluctuations over time. The remainder component
captures short-term variability that is not explained by the trend or
seasonality, with noticeable spikes during periods of rapid price
change, especially around 2020–2022. Compared with classical
decomposition, the STL trend is smoother and better highlights the
underlying long-term movements in the data.
5 Training Data
To evaluate the forecasting performance of the time series model, the
final six months of gasoline price data are reserved as a test set. This
6-month horizon provides a practical short-term evaluation window while
limiting the uncertainty associated with longer-range forecasts. The
remaining observations serve as the training data, and multiple training
window sizes are created to assess how the amount of historical
information influences forecast accuracy. By generating forecasts for
each training window and comparing them to the six held-out
observations, the analysis identifies which training size yields the
most reliable predictions for short-term gasoline price behavior.
To examine how the amount of historical data influences forecasting
performance, four different training window sizes were created using the
gasoline price time series. After holding out the final six observations
as the test set, the remaining data were used to construct training sets
of 144, 120, 96, and 72 months. These sizes were selected to represent a
range of long, medium, and shorter training periods, allowing the
analysis to evaluate whether using more or less historical information
leads to better short-term forecasts. Each training window forecasts the
same six-month test period, ensuring a fair comparison of predictive
accuracy across models. By comparing the forecasting errors associated
with these four training sizes, the analysis identifies which amount of
historical data provides the most reliable short-term predictions for
gasoline prices.
ini.data <- as.numeric(price.ts)
n0 <- length(ini.data) # should be 150
# -------------------------------
# Training data sets
# -------------------------------
train.data01 <- ini.data[1:(n0 - 6)] # 144 months
train.data02 <- ini.data[(n0 - 6 - 119):(n0 - 6)] # 120 months
train.data03 <- ini.data[(n0 - 6 - 95):(n0 - 6)] # 96 months
train.data04 <- ini.data[(n0 - 6 - 71):(n0 - 6)] # 72 months
# -------------------------------
# Test data (last 6 observations)
# -------------------------------
test.data <- ini.data[(n0 - 5):n0]
# -------------------------------
# Convert each training set to ts()
# Start = May 2013 (2013,5)
# -------------------------------
# Training 1: full 144 months starting at May 2013
train01.ts <- ts(train.data01, frequency = 12, start = c(2013, 5))
# Training 2: 120 months starting 24 months later (2015-05)
train02.ts <- ts(train.data02, frequency = 12, start = c(2015, 5))
# Training 3: 96 months starting 48 months after start (2017-05)
train03.ts <- ts(train.data03, frequency = 12, start = c(2017, 5))
# Training 4: 72 months starting 72 months after start (2019-05)
train04.ts <- ts(train.data04, frequency = 12, start = c(2019, 5))
# -------------------------------
# STL decomposition
# -------------------------------
stl01 <- stl(train01.ts, s.window = 12)
stl02 <- stl(train02.ts, s.window = 12)
stl03 <- stl(train03.ts, s.window = 12)
stl04 <- stl(train04.ts, s.window = 12)
# -------------------------------
# Forecast 6 months ahead
# -------------------------------
fcst01 <- forecast(stl01, h = 6, method = "naive")
fcst02 <- forecast(stl02, h = 6, method = "naive")
fcst03 <- forecast(stl03, h = 6, method = "naive")
fcst04 <- forecast(stl04, h = 6, method = "naive")
We next perform error analysis
# -------------------------------
# Prediction errors (MAPE without %)
# -------------------------------
PE01 <- (test.data - fcst01$mean) / fcst01$mean
PE02 <- (test.data - fcst02$mean) / fcst02$mean
PE03 <- (test.data - fcst03$mean) / fcst03$mean
PE04 <- (test.data - fcst04$mean) / fcst04$mean
MAPE1 <- mean(abs(PE01))
MAPE2 <- mean(abs(PE02))
MAPE3 <- mean(abs(PE03))
MAPE4 <- mean(abs(PE04))
# -------------------------------
# Squared errors (MSE)
# -------------------------------
E1 <- test.data - fcst01$mean
E2 <- test.data - fcst02$mean
E3 <- test.data - fcst03$mean
E4 <- test.data - fcst04$mean
MSE1 <- mean(E1^2)
MSE2 <- mean(E2^2)
MSE3 <- mean(E3^2)
MSE4 <- mean(E4^2)
# -------------------------------
# Accuracy table
# -------------------------------
MSE <- c(MSE1, MSE2, MSE3, MSE4)
MAPE <- c(MAPE1, MAPE2, MAPE3, MAPE4)
accuracy <- cbind(MSE = MSE, MAPE = MAPE)
row.names(accuracy) <- c("n=144", "n=120", "n=96", "n=72")
accuracy
MSE MAPE
n=144 0.009722946 0.02726487
n=120 0.009754861 0.02722784
n=96 0.010678115 0.02817212
n=72 0.010577313 0.02718487
# If you want it nicely formatted like the case study:
knitr::kable(
accuracy,
caption = "Error comparison between forecast results with different training sample sizes"
)
Error comparison between forecast results with different
training sample sizes
| n=144 |
0.0097229 |
0.0272649 |
| n=120 |
0.0097549 |
0.0272278 |
| n=96 |
0.0106781 |
0.0281721 |
| n=72 |
0.0105773 |
0.0271849 |
The error comparison table shows how forecast accuracy changes across
different training window sizes. The models trained with 144 and 120
months of historical data produce the lowest MSE values (0.00972 and
0.00975), indicating the most accurate forecasts in terms of squared
error. MAPE values are also very similar across these two windows, both
around 0.027, suggesting nearly identical relative accuracy. Forecast
accuracy declines slightly when using 96 and 72 months of training data,
as reflected by higher MSE and MAPE values. Overall, the results suggest
that using a longer training window—specifically 144 or 120
months—provides the most reliable short-term forecasts for gasoline
prices, while shorter windows lead to modest reductions in predictive
performance.
After computing MSE and MAPE for each training window, I visualize
the errors to compare forecasting performance across sample sizes. The
plots below show how prediction accuracy changes as the training period
becomes shorter.
par(mfrow = c(1, 2))
# -----------------------
# MSE Plot
# -----------------------
plot(1:4, MSE, type = "b", col = "darkred",
ylab = "Error", xlab = "",
main = "MSE", axes = FALSE)
labs <- c("n=144", "n=120", "n=96", "n=72")
axis(1, at = 1:4, labels = labs)
axis(2)
# Label the points with their values
text(1:4, MSE - 0.002, as.character(round(MSE, 4)),
col = "darkred", cex = 0.7)
# -----------------------
# MAPE Plot
# -----------------------
plot(1:4, MAPE, type = "b", col = "blue",
ylab = "Error", xlab = "",
main = "MAPE", axes = FALSE)
axis(1, at = 1:4, labels = labs)
axis(2)
# Label the points with their values
text(1:4, MAPE + 0.001, as.character(round(MAPE, 4)),
col = "blue", cex = 0.7)

The error plots show how forecast accuracy changes with different
training window sizes. Both MSE and MAPE are lowest when using the
largest training windows (n = 144 and n = 120), indicating that models
with more historical data produce more accurate six-month forecasts.
Error values increase for the shorter training windows (n = 96 and n =
72), especially for MSE, suggesting that reducing the amount of
available history weakens predictive performance. Overall, the visual
patterns confirm that longer training periods lead to more reliable
short-term gasoline price forecasts, while shorter windows introduce
more variability and higher forecasting errors.
6 Conclusion
This analysis examined monthly U.S. gasoline prices from May 2013 to
October 2025 to evaluate how recent price movements compare with
long-term historical trends. Both classical and STL decomposition
revealed clear structural patterns, including a gradual decline through
2016, a steady rise heading into 2020, and a sharp peak in 2022 followed
by partial stabilization. STL produced a smoother and more reliable
trend estimate, making it more suitable for forecasting. Using the last
six months as a test set and training windows of 144, 120, 96, and 72
months, the results showed that the longest training windows produced
the lowest MSE and MAPE values, indicating that incorporating more
historical information leads to better short-term predictions. While
these findings provide useful insight into how gasoline prices in early
2025 align with long-term trends, the analysis is subject to several
limitations. The dataset contains only 150 observations, restricting how
many meaningful training windows could be used, and gasoline prices are
influenced by external economic and geopolitical factors that are not
captured in a univariate time series. Potential user errors—such as
indexing mistakes or assumptions about start dates—could also affect the
results, and classical decomposition’s additive structure may
oversimplify a series with periods of heightened volatility. Future
analyses could be strengthened by using a larger dataset, experimenting
with additional forecasting models such as ARIMA or exponential
smoothing, incorporating external predictors like crude oil prices, or
applying rolling-origin validation to better assess forecasting
performance. Despite these limitations, the analysis provides a
structured and data-driven assessment of short-term gasoline price
behavior relative to long-term historical patterns.
LS0tDQp0aXRsZTogIkZvcmVjYXN0aW5nIFUuUy4gR2Fzb2xpbmUgUHJpY2VzIFVzaW5nIFRpbWUgU2VyaWVzIERlY29tcG9zaXRpb24iDQphdXRob3I6ICJMdWtlIFZvbG0iDQpkYXRlOiAiMjAyNS0xMS0yMCINCm91dHB1dDoNCiAgaHRtbF9kb2N1bWVudDogICAgICAgICAgICMgb3V0cHV0IGRvY3VtZW50IGZvcm1hdA0KICAgIHRvYzogeWVzICAgICAgICAgICAgICAgIyBhZGQgdGFibGUgY29udGVudHMNCiAgICB0b2NfZmxvYXQ6IHllcyAgICAgICAgICMgdG9jX3Byb3BlcnR5OiBmbG9hdGluZw0KICAgIHRvY19kZXB0aDogNCAgICAgICAgICAgIyBkZXB0aCBvZiBUT0MgaGVhZGluZ3MNCiAgICBmaWdfd2lkdGg6IDYgICAgICAgICAgICMgZ2xvYmFsIGZpZ3VyZSB3aWR0aA0KICAgIGZpZ19oZWlnaHQ6IDQgICAgICAgICAgIyBnbG9iYWwgZmlndXJlIGhlaWdodA0KICAgIGZpZ19jYXB0aW9uOiB5ZXMgICAgICAgIyBhZGQgZmlndXJlIGNhcHRpb24NCiAgICBudW1iZXJfc2VjdGlvbnM6IG5vICAgIyBudW1iZXJpbmcgc2VjdGlvbiBoZWFkaW5ncw0KICAgIHRvY19jb2xsYXBzZWQ6IHllcyAgICAgIyBUT0Mgc3ViaGVhZGluZyBjb2xsYXBzaW5nDQogICAgY29kZV9mb2xkaW5nOiBoaWRlICAgICAjIGZvbGRpbmcvc2hvd2luZyBjb2RlIA0KICAgIGNvZGVfZG93bmxvYWQ6IHllcyAgICAgIyBhbGxvdyB0byBkb3dubG9hZCBjb21wbGV0ZSBSTWFya2Rvd24gc291cmNlIGNvZGUNCiAgICBzbW9vdGhfc2Nyb2xsOiB5ZXMgICAgICMgc2Nyb2xsaW5nIHRleHQgb2YgdGhlIGRvY3VtZW50DQogICAgdGhlbWU6IGx1bWVuICAgICAgICAgICAjIHZpc3VhbCB0aGVtZSBmb3IgSFRNTCBkb2N1bWVudCBvbmx5DQogICAgaGlnaGxpZ2h0OiB0YW5nbyAgICAgICAjIGNvZGUgc3ludGF4IGhpZ2hsaWdodGluZyBzdHlsZXMNCiAgcGRmX2RvY3VtZW50OiANCiAgICB0b2M6IHllcw0KICAgIHRvY19kZXB0aDogNA0KICAgIGZpZ19jYXB0aW9uOiB5ZXMNCiAgICBudW1iZXJfc2VjdGlvbnM6IHllcw0KICB3b3JkX2RvY3VtZW50Og0KICAgIHRvYzogeWVzDQogICAgdG9jX2RlcHRoOiAnNCcNCi0tLQ0KDQpgYGB7Y3NzLCBlY2hvID0gRkFMU0V9DQpkaXYjVE9DIGx3ZXsgICAgIC8qIHRhYmxlIG9mIGNvbnRlbnQgICovDQogICAgbGlzdC1zdHlsZTp1cHBlci1yb21hbjsNCiAgICBiYWNrZ3JvdW5kLWltYWdlOm5vbmU7DQogICAgYmFja2dyb3VuZC1yZXBlYXQ6bm9uZTsNCiAgICBiYWNrZ3JvdW5kLXBvc2l0aW9uOjA7DQp9DQoNCmgxLnRpdGxlIHsgICAgLyogbGV2ZWwgMSBoZWFkZXIgb2YgdGl0bGUgICovDQogIGZvbnQtc2l6ZTogMjRweDsNCiAgZm9udC13ZWlnaHQ6IGJvbGQ7DQogIGNvbG9yOiBEYXJrUmVkOw0KICB0ZXh0LWFsaWduOiBjZW50ZXI7DQp9DQoNCmg0LmF1dGhvciB7IC8qIEhlYWRlciA0IC0gYW5kIHRoZSBhdXRob3IgYW5kIGRhdGEgaGVhZGVycyB1c2UgdGhpcyB0b28gICovDQogIGZvbnQtc2l6ZTogMThweDsNCiAgZm9udC13ZWlnaHQ6IGJvbGQ7DQogIGZvbnQtZmFtaWx5OiAiVGltZXMgTmV3IFJvbWFuIiwgVGltZXMsIHNlcmlmOw0KICBjb2xvcjogRGFya1JlZDsNCiAgdGV4dC1hbGlnbjogY2VudGVyOw0KfQ0KDQpoNC5kYXRlIHsgLyogSGVhZGVyIDQgLSBhbmQgdGhlIGF1dGhvciBhbmQgZGF0YSBoZWFkZXJzIHVzZSB0aGlzIHRvbyAgKi8NCiAgZm9udC1zaXplOiAxOHB4Ow0KICBmb250LXdlaWdodDogYm9sZDsNCiAgZm9udC1mYW1pbHk6ICJUaW1lcyBOZXcgUm9tYW4iLCBUaW1lcywgc2VyaWY7DQogIGNvbG9yOiBEYXJrQmx1ZTsNCiAgdGV4dC1hbGlnbjogY2VudGVyOw0KfQ0KDQpoMSB7IC8qIEhlYWRlciAxIC0gYW5kIHRoZSBhdXRob3IgYW5kIGRhdGEgaGVhZGVycyB1c2UgdGhpcyB0b28gICovDQogICAgZm9udC1zaXplOiAyMHB4Ow0KICAgIGZvbnQtd2VpZ2h0OiBib2xkOw0KICAgIGZvbnQtZmFtaWx5OiAiVGltZXMgTmV3IFJvbWFuIiwgVGltZXMsIHNlcmlmOw0KICAgIGNvbG9yOiBkYXJrcmVkOw0KICAgIHRleHQtYWxpZ246IGNlbnRlcjsNCn0NCg0KaDIgeyAvKiBIZWFkZXIgMiAtIGFuZCB0aGUgYXV0aG9yIGFuZCBkYXRhIGhlYWRlcnMgdXNlIHRoaXMgdG9vICAqLw0KICAgIGZvbnQtc2l6ZTogMThweDsNCiAgICBmb250LXdlaWdodDogYm9sZDsNCiAgICBmb250LWZhbWlseTogIlRpbWVzIE5ldyBSb21hbiIsIFRpbWVzLCBzZXJpZjsNCiAgICBjb2xvcjogbmF2eTsNCiAgICB0ZXh0LWFsaWduOiBsZWZ0Ow0KfQ0KDQpoMyB7IC8qIEhlYWRlciAzIC0gYW5kIHRoZSBhdXRob3IgYW5kIGRhdGEgaGVhZGVycyB1c2UgdGhpcyB0b28gICovDQogICAgZm9udC1zaXplOiAxNnB4Ow0KICAgIGZvbnQtd2VpZ2h0OiBib2xkOw0KICAgIGZvbnQtZmFtaWx5OiAiVGltZXMgTmV3IFJvbWFuIiwgVGltZXMsIHNlcmlmOw0KICAgIGNvbG9yOiBuYXZ5Ow0KICAgIHRleHQtYWxpZ246IGxlZnQ7DQp9DQoNCmg0IHsgLyogSGVhZGVyIDQgLSBhbmQgdGhlIGF1dGhvciBhbmQgZGF0YSBoZWFkZXJzIHVzZSB0aGlzIHRvbyAgKi8NCiAgICBmb250LXNpemU6IDE0cHg7DQogIGZvbnQtd2VpZ2h0OiBib2xkOw0KICAgIGZvbnQtZmFtaWx5OiAiVGltZXMgTmV3IFJvbWFuIiwgVGltZXMsIHNlcmlmOw0KICAgIGNvbG9yOiBkYXJrcmVkOw0KICAgIHRleHQtYWxpZ246IGxlZnQ7DQp9DQoNCi8qIEFkZCBkb3RzIGFmdGVyIG51bWJlcmVkIGhlYWRlcnMgKi8NCi5oZWFkZXItc2VjdGlvbi1udW1iZXI6OmFmdGVyIHsNCiAgY29udGVudDogIi4iOw0KfQ0KYGBgDQoNCmBgYHtyIHNldHVwLCBpbmNsdWRlPUZBTFNFfQ0KbGlicmFyeShyZWFkeGwpDQpsaWJyYXJ5KGJvb3QpDQpsaWJyYXJ5KGRwbHlyKQ0KbGlicmFyeShrbml0cikNCmxpYnJhcnkocHN5Y2gpDQpsaWJyYXJ5KE1BU1MpDQpsaWJyYXJ5KHRpZHlyKQ0KbGlicmFyeShnZ3Bsb3QyKQ0KbGlicmFyeShjYXIpDQpsaWJyYXJ5KHBhbmRlcikNCmxpYnJhcnkoZm9yZWNhc3QpDQoNCiMgU2V0IHNlZWQgZm9yIHJlcHJvZHVjaWJpbGl0eQ0Kc2V0LnNlZWQoMTIzKQ0KDQojIFJlYWQgaW4gZGF0YSAoZHJvcCBmaXJzdCBjb2x1bW4gaWYgaXQncyBqdXN0IGFuIGluZGV4L0lEKQ0Kc2V0d2QoIkM6L1VzZXJzL3ZvbG0xL09uZURyaXZlL0Rlc2t0b3AvU1RBMzIxIG5ldyIpDQpwcmljZSA8LSByZWFkLmNzdigiR0FTUkVHQ09WTS5jc3YiKQ0KIyBHbG9iYWwgY2h1bmsgb3B0aW9ucw0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KA0KICBlY2hvID0gVFJVRSwgICAgICAjIHNob3cgY29kZQ0KICB3YXJuaW5nID0gRkFMU0UsICAjIHN1cHByZXNzIHdhcm5pbmdzDQogIG1lc3NhZ2UgPSBGQUxTRSwgICMgc3VwcHJlc3MgbWVzc2FnZXMNCiAgcmVzdWx0cyA9IFRSVUUsICAgIyBzaG93IHJlc3VsdHMNCiAgY29tbWVudCA9IE5BICAgICAgIyBjbGVhbmVyIG91dHB1dCAobm8gIiMjIiBwcmVmaXgpDQopDQpgYGANCg0KIyAxIEludHJvZHVjdGlvbg0KDQpUaGlzIHByb2plY3QgYW5hbHl6ZXMgbW9udGhseSBVLlMuIGdhc29saW5lIHByaWNlcyB1c2luZyBwdWJsaWNseSBhdmFpbGFibGUgZGF0YSBmcm9tIHRoZSBGZWRlcmFsIFJlc2VydmUgQmFuayBvZiBTdC4gTG91aXMgKEZSRUQpLiBUaGUgZ29hbCBvZiB0aGUgYW5hbHlzaXMgaXMgdG8gZXZhbHVhdGUgaG93IHJlY2VudCBwcmljZSBsZXZlbHMgY29tcGFyZSB3aXRoIGxvbmctdGVybSBwYXR0ZXJucyBieSBhZGRyZXNzaW5nIHRoZSByZXNlYXJjaCBxdWVzdGlvbjogSG93IGRvIFUuUy4gZ2Fzb2xpbmUgcHJpY2VzIGluIGVhcmx5IDIwMjUgY29tcGFyZSB0byB0aGVpciBsb25nLXRlcm0gaGlzdG9yaWNhbCB0cmVuZD8gVG8gaW52ZXN0aWdhdGUgdGhpcywgdGhlIG1vc3QgcmVjZW50IDE1MCBtb250aHMgb2YgZGF0YSBhcmUgZXh0cmFjdGVkIGFuZCBjb252ZXJ0ZWQgaW50byBhIHRpbWUgc2VyaWVzIG9iamVjdCBmb3Igc3RydWN0dXJlZCBhbmFseXNpcy4gQ2xhc3NpY2FsIGFuZCBTVEwgZGVjb21wb3NpdGlvbiBtZXRob2RzIGFyZSBhcHBsaWVkIHRvIHNlcGFyYXRlIHRoZSBzZXJpZXMgaW50byB0cmVuZCwgc2Vhc29uYWwsIGFuZCByZW1haW5kZXIgY29tcG9uZW50cywgYWxsb3dpbmcgZm9yIGFuIGV4YW1pbmF0aW9uIG9mIHVuZGVybHlpbmcgbW92ZW1lbnRzIG92ZXIgdGltZS4gU2V2ZXJhbCB0cmFpbmluZyB3aW5kb3dzIGFyZSB0aGVuIGNvbnN0cnVjdGVkLCB3aXRoIHRoZSBmaW5hbCBzaXggbW9udGhzIGhlbGQgb3V0IGFzIGEgdGVzdCBzZXQsIGFuZCBTVEwtYmFzZWQgbmFpdmUgZm9yZWNhc3RzIGFyZSBnZW5lcmF0ZWQuIEZvcmVjYXN0IGFjY3VyYWN5IGlzIGFzc2Vzc2VkIHVzaW5nIE1TRSBhbmQgTUFQRSBhY3Jvc3MgdGhlIGRpZmZlcmVudCB0cmFpbmluZyBzaXplcywgcHJvdmlkaW5nIGluc2lnaHQgaW50byBob3cgd2VsbCByZWNlbnQgZ2Fzb2xpbmUgcHJpY2VzIGFsaWduIHdpdGggZXhwZWN0YXRpb25zIGJhc2VkIG9uIGxvbmctdGVybSBoaXN0b3JpY2FsIGJlaGF2aW9yLg0KDQojIDIgRGVzY3JpcHRpb24gb2YgRGF0YSBTZXQNCg0KVGhlIHRpbWUgc2VyaWVzIGRhdGEgdXNlZCBpbiB0aGlzIHN0dWR5IGlzIGZyb20gdGhlIEZlZGVyYWwgUmVzZXJ2ZSBCYW5rIG9mIFN0LiBMb3Vpcy4gVGhlIGRhdGEgY29udGFpbnMgdGhlIGdhcyBwcmljZSBmb3IgdGhlIGZpcnN0IG9mIGV2ZXJ5IG1vbnRoIHNpbmNlIFNlcHRlbWJlciAxLCAxOTkwLiBXZSB3aWxsIGJlIG9ic2VydnNpbmcgb25seSB0aGUgbW9zdCByZWNlbnQgMTUwIG9ic2VydmF0aW9ucywgd2hpY2ggcmFuZ2VzIGZyb20gTWF5IDIwMTMgdG8gT2N0b2JlciAyMDI1LiBPdXIgb2JzZXJ2YXRpb24gSUQgYW5kIGV4cGxhbmF0b3J5IHZhcmlhYmxlIHdpbGwgYmUgdGhlIE9ic2VydmF0aW9uIERhdGUuIE91ciByZXNwb25zZSB2YXJpYWJsZSBpcyBEb2xsYXJzIHBlciBHYWxsb24gKEdBU1JFR0NPVk0pLg0KDQpgYGB7cn0NCg0KcHJpY2VfcmVjZW50IDwtIHRhaWwocHJpY2UsIDE1MCkNCg0KYGBgDQoNCkluIHRoZSBhYm92ZSBjb2RlIGNodW5rLCB3ZSB0YWtlIHRoZSAxNTAgbW9zdCByZWNlbnQgZGF0ZXMsIG9yIG9ic2VydmF0aW9ucywgaW4gdGhlIGRhdGEgc2V0Lg0KDQojIDMgUGxvdHRpbmcgT3VyIERhdGENCg0KU2luY2UgdGhpcyBpcyBtb250aGx5IGRhdGEsIGZyZXF1ZW5jeSA9IDEyIHdpbGwgYmUgdXNlZCB0byBkZWZpbmUgdGhlIHRpbWUgc2VyaWVzIG9iamVjdC4gDQoNCmBgYHtyfQ0KDQpwcmljZS50cyA8LSB0cyhwcmljZV9yZWNlbnRbLCAyXSwgZnJlcXVlbmN5ID0gMTIsIHN0YXJ0ID0gYygyMDEzLCA1KSkNCg0KcGFyKG1hciA9IGMoMiwgMiwgMiwgMikpDQpwbG90KA0KICBwcmljZS50cywNCiAgbWFpbiA9ICJVUyBSZWd1bGFyIENvbnZlbnRpb25hbCBHYXMgUHJpY2VzOiBNYXkgMjAxMyB0byBPY3RvYmVyIDIwMjUiLA0KICB5bGFiID0gIk1vbnRobHkgUHJpY2UgKFVTRCBwZXIgZ2FsbG9uKSIsDQogIHhsYWIgPSAiIikNCmBgYA0KDQpUaGUgdGltZSBzZXJpZXMgcGxvdCBvZiBVLlMuIGdhc29saW5lIHByaWNlcyBmcm9tIE1heSAyMDEzIHRvIE9jdG9iZXIgMjAyNSBzaG93cyBzZXZlcmFsIGNsZWFyIHNoaWZ0cy4gUHJpY2VzIGRlY2xpbmUgZnJvbSBhYm91dCAkMy41MCBpbiAyMDEzIHRvIGEgbG93IG5lYXIgJDIgaW4gZWFybHkgMjAxNiwgdGhlbiBncmFkdWFsbHkgcmlzZSB0aHJvdWdoIDIwMTkuIEEgc2hhcnAgaW5jcmVhc2UgYmVnaW5zIGluIDIwMjEsIHBlYWtpbmcgYWJvdmUgJDQuNTAgaW4gMjAyMi4gQWZ0ZXIgdGhlIHBlYWssIHByaWNlcyBkZWNsaW5lIGJ1dCByZW1haW4gbW9yZSB2b2xhdGlsZSwgc2V0dGxpbmcgYXJvdW5kIHRoZSBtaWQtJDMgcmFuZ2UgdGhyb3VnaCAyMDIz4oCTMjAyNS4gT3ZlcmFsbCwgdGhlIGdyYXBoIGhpZ2hsaWdodHMgYSBtYWpvciB1cHdhcmQgc3VyZ2UgYWZ0ZXIgMjAyMCBmb2xsb3dlZCBieSBwYXJ0aWFsIHN0YWJpbGl6YXRpb24uDQoNCiMgNCBGb3JlY2FzdGluZyB3aXRoIERlY29tcG9zaXRpb24NCg0KVG8gYW5hbHl6ZSB0aGUgdW5kZXJseWluZyBzdHJ1Y3R1cmUgb2YgdGhlIGdhc29saW5lIHByaWNlIHRpbWUgc2VyaWVzLCB0aGlzIHByb2plY3QgYXBwbGllcyBib3RoIGNsYXNzaWNhbCBkZWNvbXBvc2l0aW9uIGFuZCBTVEwgKFNlYXNvbmFsLVRyZW5kIERlY29tcG9zaXRpb24gdXNpbmcgTE9FU1MpLiBVc2luZyBib3RoIG1ldGhvZHMgcHJvdmlkZXMgYSBtb3JlIGNvbXBsZXRlIHVuZGVyc3RhbmRpbmcgb2YgaG93IHRoZSBkYXRhIGJlaGF2ZXMgb3ZlciB0aW1lLiBDbGFzc2ljYWwgZGVjb21wb3NpdGlvbiBzZXBhcmF0ZXMgdGhlIHNlcmllcyBpbnRvIHRyZW5kLCBzZWFzb25hbCwgYW5kIHJlbWFpbmRlciBjb21wb25lbnRzIHVzaW5nIGZpeGVkIHNlYXNvbmFsIHBhdHRlcm5zLCB3aGljaCBoZWxwcyBpZGVudGlmeSBicm9hZCBzdHJ1Y3R1cmFsIGZlYXR1cmVzIGluIGEgc3RyYWlnaHRmb3J3YXJkIHdheS4gU1RMIGRlY29tcG9zaXRpb24sIG9uIHRoZSBvdGhlciBoYW5kLCBvZmZlcnMgYSBtb3JlIGZsZXhpYmxlIGFuZCByb2J1c3QgYXBwcm9hY2ggdGhhdCBjYW4gY2FwdHVyZSBzbW9vdGhlciB0cmVuZHMgYW5kIGFkYXB0IHRvIGNoYW5nZXMgaW4gc2Vhc29uYWxpdHkuIEJ5IHBlcmZvcm1pbmcgYm90aCBtZXRob2RzLCB0aGUgYW5hbHlzaXMgY2FuIGNvbXBhcmUgaG93IGVhY2ggdGVjaG5pcXVlIHJlcHJlc2VudHMgdGhlIGRhdGEsIGhpZ2hsaWdodCBkaWZmZXJlbmNlcyBpbiB0cmVuZCBhbmQgc2Vhc29uYWwgYmVoYXZpb3IsIGFuZCBlbnN1cmUgdGhhdCB0aGUgZGVjb21wb3NpdGlvbiB1c2VkIGZvciBmb3JlY2FzdGluZyBpcyBiYXNlZCBvbiB0aGUgbWV0aG9kIHRoYXQgYmVzdCByZWZsZWN0cyB0aGUgY2hhcmFjdGVyaXN0aWNzIG9mIHRoZSBnYXNvbGluZSBwcmljZSBzZXJpZXMuDQoNCiMjIDQuMSBDbGFzc2ljYWwNCg0KSGVyZSwgSSBhcHBseSB0aGUgY2xhc3NpY2FsIGRlY29tcG9zaXRpb24gdG8gYnJlYWsgdGhlIHNlcmllcyBpbnRvIGl0cyB0cmVuZCwgc2Vhc29uYWwsIGFuZCBpcnJlZ3VsYXIgY29tcG9uZW50cywgcHJvdmlkaW5nIGEgYmFzZWxpbmUgdW5kZXJzdGFuZGluZyBvZiBob3cgdGhlIGRhdGEgYmVoYXZlcyBvdmVyIHRpbWUuDQoNCmBgYHtyfQ0KDQpjbHMuZGVjb21wID0gZGVjb21wb3NlKHByaWNlLnRzKQ0KcGFyKG1hcj1jKDIsMiwyLDIpKQ0KcGxvdChjbHMuZGVjb21wLCB4bGFiPSIiKQ0KDQpgYGANCg0KVGhlIGNsYXNzaWNhbCBkZWNvbXBvc2l0aW9uIHNlcGFyYXRlcyB0aGUgZ2Fzb2xpbmUgcHJpY2Ugc2VyaWVzIGludG8gaXRzIG9ic2VydmVkLCB0cmVuZCwgc2Vhc29uYWwsIGFuZCByZW1haW5kZXIgY29tcG9uZW50cy4gVGhlIHRyZW5kIGNvbXBvbmVudCBzaG93cyBhIGdyYWR1YWwgZGVjbGluZSBmcm9tIDIwMTMgdGhyb3VnaCAyMDE2LCBmb2xsb3dlZCBieSBhIHN0ZWFkeSByaXNlIGxlYWRpbmcgaW50byB0aGUgc2hhcnAgcGVhayBhcm91bmQgMjAyMiwgYmVmb3JlIGxldmVsaW5nIG9mZiB0b3dhcmQgMjAyNS4gVGhlIHNlYXNvbmFsIGNvbXBvbmVudCBkaXNwbGF5cyBhIGNvbnNpc3RlbnQgcmVwZWF0aW5nIHllYXJseSBwYXR0ZXJuLCBpbmRpY2F0aW5nIG1vZGVzdCBidXQgcmVndWxhciBzZWFzb25hbCBmbHVjdHVhdGlvbnMgaW4gZ2Fzb2xpbmUgcHJpY2VzLiBUaGUgcmVtYWluZGVyIGNvbXBvbmVudCBjYXB0dXJlcyBzaG9ydC10ZXJtIHZvbGF0aWxpdHkgbm90IGV4cGxhaW5lZCBieSB0cmVuZCBvciBzZWFzb25hbGl0eSwgd2l0aCBsYXJnZXIgaXJyZWd1bGFyIG1vdmVtZW50cyBhcHBlYXJpbmcgZHVyaW5nIHBlcmlvZHMgb2YgcmFwaWQgcHJpY2UgY2hhbmdlLCBwYXJ0aWN1bGFybHkgYXJvdW5kIDIwMjDigJMyMDIyLiBPdmVyYWxsLCBjbGFzc2ljYWwgZGVjb21wb3NpdGlvbiByZXZlYWxzIGEgY2xlYXIgbG9uZy10ZXJtIHVwd2FyZCB0cmVuZCBhbmQgc3RhYmxlIHNlYXNvbmFsIGJlaGF2aW9yIHRocm91Z2hvdXQgdGhlIHNlcmllcy4NCg0KIyMgNC4yIFNUTA0KDQpXZSB3aWxsIG5vdyBwZXJmb3JtIHRoZSBTVEwgbWV0aG9kLg0KDQpgYGB7cn0NCg0Kc3RsLmRlY29tcD1zdGwocHJpY2UudHMsIHMud2luZG93ID0gMTIpDQpwYXIobWFyPWMoMiwyLDIsMikpDQpwbG90KHN0bC5kZWNvbXApDQoNCmBgYA0KDQpUaGUgU1RMIGRlY29tcG9zaXRpb24gcHJvdmlkZXMgYSBzbW9vdGggYW5kIGZsZXhpYmxlIGJyZWFrZG93biBvZiB0aGUgZ2Fzb2xpbmUgcHJpY2Ugc2VyaWVzIGludG8gdHJlbmQsIHNlYXNvbmFsLCBhbmQgcmVtYWluZGVyIGNvbXBvbmVudHMuIFRoZSB0cmVuZCBjb21wb25lbnQgY2xlYXJseSBzaG93cyB0aGUgbG9uZyBkb3dud2FyZCBtb3ZlbWVudCB0aHJvdWdoIDIwMTYsIGZvbGxvd2VkIGJ5IGEgc3RlYWR5IHJpc2UgYW5kIGEgcHJvbm91bmNlZCBwZWFrIGluIDIwMjIsIGJlZm9yZSBncmFkdWFsbHkgZGVjbGluaW5nIHRvd2FyZCAyMDI1LiBUaGUgc2Vhc29uYWwgY29tcG9uZW50IGRpc3BsYXlzIGEgc3RhYmxlLCByZXBlYXRpbmcgeWVhcmx5IHBhdHRlcm4sIGluZGljYXRpbmcgdGhhdCBnYXNvbGluZSBwcmljZXMgZm9sbG93IGNvbnNpc3RlbnQgc2Vhc29uYWwgZmx1Y3R1YXRpb25zIG92ZXIgdGltZS4gVGhlIHJlbWFpbmRlciBjb21wb25lbnQgY2FwdHVyZXMgc2hvcnQtdGVybSB2YXJpYWJpbGl0eSB0aGF0IGlzIG5vdCBleHBsYWluZWQgYnkgdGhlIHRyZW5kIG9yIHNlYXNvbmFsaXR5LCB3aXRoIG5vdGljZWFibGUgc3Bpa2VzIGR1cmluZyBwZXJpb2RzIG9mIHJhcGlkIHByaWNlIGNoYW5nZSwgZXNwZWNpYWxseSBhcm91bmQgMjAyMOKAkzIwMjIuIENvbXBhcmVkIHdpdGggY2xhc3NpY2FsIGRlY29tcG9zaXRpb24sIHRoZSBTVEwgdHJlbmQgaXMgc21vb3RoZXIgYW5kIGJldHRlciBoaWdobGlnaHRzIHRoZSB1bmRlcmx5aW5nIGxvbmctdGVybSBtb3ZlbWVudHMgaW4gdGhlIGRhdGEuDQoNCiMgNSBUcmFpbmluZyBEYXRhDQoNClRvIGV2YWx1YXRlIHRoZSBmb3JlY2FzdGluZyBwZXJmb3JtYW5jZSBvZiB0aGUgdGltZSBzZXJpZXMgbW9kZWwsIHRoZSBmaW5hbCBzaXggbW9udGhzIG9mIGdhc29saW5lIHByaWNlIGRhdGEgYXJlIHJlc2VydmVkIGFzIGEgdGVzdCBzZXQuIFRoaXMgNi1tb250aCBob3Jpem9uIHByb3ZpZGVzIGEgcHJhY3RpY2FsIHNob3J0LXRlcm0gZXZhbHVhdGlvbiB3aW5kb3cgd2hpbGUgbGltaXRpbmcgdGhlIHVuY2VydGFpbnR5IGFzc29jaWF0ZWQgd2l0aCBsb25nZXItcmFuZ2UgZm9yZWNhc3RzLiBUaGUgcmVtYWluaW5nIG9ic2VydmF0aW9ucyBzZXJ2ZSBhcyB0aGUgdHJhaW5pbmcgZGF0YSwgYW5kIG11bHRpcGxlIHRyYWluaW5nIHdpbmRvdyBzaXplcyBhcmUgY3JlYXRlZCB0byBhc3Nlc3MgaG93IHRoZSBhbW91bnQgb2YgaGlzdG9yaWNhbCBpbmZvcm1hdGlvbiBpbmZsdWVuY2VzIGZvcmVjYXN0IGFjY3VyYWN5LiBCeSBnZW5lcmF0aW5nIGZvcmVjYXN0cyBmb3IgZWFjaCB0cmFpbmluZyB3aW5kb3cgYW5kIGNvbXBhcmluZyB0aGVtIHRvIHRoZSBzaXggaGVsZC1vdXQgb2JzZXJ2YXRpb25zLCB0aGUgYW5hbHlzaXMgaWRlbnRpZmllcyB3aGljaCB0cmFpbmluZyBzaXplIHlpZWxkcyB0aGUgbW9zdCByZWxpYWJsZSBwcmVkaWN0aW9ucyBmb3Igc2hvcnQtdGVybSBnYXNvbGluZSBwcmljZSBiZWhhdmlvci4NCg0KVG8gZXhhbWluZSBob3cgdGhlIGFtb3VudCBvZiBoaXN0b3JpY2FsIGRhdGEgaW5mbHVlbmNlcyBmb3JlY2FzdGluZyBwZXJmb3JtYW5jZSwgZm91ciBkaWZmZXJlbnQgdHJhaW5pbmcgd2luZG93IHNpemVzIHdlcmUgY3JlYXRlZCB1c2luZyB0aGUgZ2Fzb2xpbmUgcHJpY2UgdGltZSBzZXJpZXMuIEFmdGVyIGhvbGRpbmcgb3V0IHRoZSBmaW5hbCBzaXggb2JzZXJ2YXRpb25zIGFzIHRoZSB0ZXN0IHNldCwgdGhlIHJlbWFpbmluZyBkYXRhIHdlcmUgdXNlZCB0byBjb25zdHJ1Y3QgdHJhaW5pbmcgc2V0cyBvZiAxNDQsIDEyMCwgOTYsIGFuZCA3MiBtb250aHMuIFRoZXNlIHNpemVzIHdlcmUgc2VsZWN0ZWQgdG8gcmVwcmVzZW50IGEgcmFuZ2Ugb2YgbG9uZywgbWVkaXVtLCBhbmQgc2hvcnRlciB0cmFpbmluZyBwZXJpb2RzLCBhbGxvd2luZyB0aGUgYW5hbHlzaXMgdG8gZXZhbHVhdGUgd2hldGhlciB1c2luZyBtb3JlIG9yIGxlc3MgaGlzdG9yaWNhbCBpbmZvcm1hdGlvbiBsZWFkcyB0byBiZXR0ZXIgc2hvcnQtdGVybSBmb3JlY2FzdHMuIEVhY2ggdHJhaW5pbmcgd2luZG93IGZvcmVjYXN0cyB0aGUgc2FtZSBzaXgtbW9udGggdGVzdCBwZXJpb2QsIGVuc3VyaW5nIGEgZmFpciBjb21wYXJpc29uIG9mIHByZWRpY3RpdmUgYWNjdXJhY3kgYWNyb3NzIG1vZGVscy4gQnkgY29tcGFyaW5nIHRoZSBmb3JlY2FzdGluZyBlcnJvcnMgYXNzb2NpYXRlZCB3aXRoIHRoZXNlIGZvdXIgdHJhaW5pbmcgc2l6ZXMsIHRoZSBhbmFseXNpcyBpZGVudGlmaWVzIHdoaWNoIGFtb3VudCBvZiBoaXN0b3JpY2FsIGRhdGEgcHJvdmlkZXMgdGhlIG1vc3QgcmVsaWFibGUgc2hvcnQtdGVybSBwcmVkaWN0aW9ucyBmb3IgZ2Fzb2xpbmUgcHJpY2VzLg0KDQpgYGB7cn0NCg0KaW5pLmRhdGEgPC0gYXMubnVtZXJpYyhwcmljZS50cykNCm4wIDwtIGxlbmd0aChpbmkuZGF0YSkgICAjIHNob3VsZCBiZSAxNTANCg0KIyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tDQojIFRyYWluaW5nIGRhdGEgc2V0cw0KIyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tDQp0cmFpbi5kYXRhMDEgPC0gaW5pLmRhdGFbMToobjAgLSA2KV0gICAgICAgICAgICAgICAgICMgMTQ0IG1vbnRocw0KdHJhaW4uZGF0YTAyIDwtIGluaS5kYXRhWyhuMCAtIDYgLSAxMTkpOihuMCAtIDYpXSAgICAjIDEyMCBtb250aHMNCnRyYWluLmRhdGEwMyA8LSBpbmkuZGF0YVsobjAgLSA2IC0gOTUpOihuMCAtIDYpXSAgICAgIyA5NiBtb250aHMNCnRyYWluLmRhdGEwNCA8LSBpbmkuZGF0YVsobjAgLSA2IC0gNzEpOihuMCAtIDYpXSAgICAgIyA3MiBtb250aHMNCg0KIyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tDQojIFRlc3QgZGF0YSAobGFzdCA2IG9ic2VydmF0aW9ucykNCiMgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQ0KdGVzdC5kYXRhIDwtIGluaS5kYXRhWyhuMCAtIDUpOm4wXQ0KDQojIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0NCiMgQ29udmVydCBlYWNoIHRyYWluaW5nIHNldCB0byB0cygpDQojIFN0YXJ0ID0gTWF5IDIwMTMgKDIwMTMsNSkNCiMgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQ0KDQojIFRyYWluaW5nIDE6IGZ1bGwgMTQ0IG1vbnRocyBzdGFydGluZyBhdCBNYXkgMjAxMw0KdHJhaW4wMS50cyA8LSB0cyh0cmFpbi5kYXRhMDEsIGZyZXF1ZW5jeSA9IDEyLCBzdGFydCA9IGMoMjAxMywgNSkpDQoNCiMgVHJhaW5pbmcgMjogMTIwIG1vbnRocyBzdGFydGluZyAyNCBtb250aHMgbGF0ZXIgKDIwMTUtMDUpDQp0cmFpbjAyLnRzIDwtIHRzKHRyYWluLmRhdGEwMiwgZnJlcXVlbmN5ID0gMTIsIHN0YXJ0ID0gYygyMDE1LCA1KSkNCg0KIyBUcmFpbmluZyAzOiA5NiBtb250aHMgc3RhcnRpbmcgNDggbW9udGhzIGFmdGVyIHN0YXJ0ICgyMDE3LTA1KQ0KdHJhaW4wMy50cyA8LSB0cyh0cmFpbi5kYXRhMDMsIGZyZXF1ZW5jeSA9IDEyLCBzdGFydCA9IGMoMjAxNywgNSkpDQoNCiMgVHJhaW5pbmcgNDogNzIgbW9udGhzIHN0YXJ0aW5nIDcyIG1vbnRocyBhZnRlciBzdGFydCAoMjAxOS0wNSkNCnRyYWluMDQudHMgPC0gdHModHJhaW4uZGF0YTA0LCBmcmVxdWVuY3kgPSAxMiwgc3RhcnQgPSBjKDIwMTksIDUpKQ0KDQojIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0NCiMgU1RMIGRlY29tcG9zaXRpb24NCiMgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQ0Kc3RsMDEgPC0gc3RsKHRyYWluMDEudHMsIHMud2luZG93ID0gMTIpDQpzdGwwMiA8LSBzdGwodHJhaW4wMi50cywgcy53aW5kb3cgPSAxMikNCnN0bDAzIDwtIHN0bCh0cmFpbjAzLnRzLCBzLndpbmRvdyA9IDEyKQ0Kc3RsMDQgPC0gc3RsKHRyYWluMDQudHMsIHMud2luZG93ID0gMTIpDQoNCiMgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQ0KIyBGb3JlY2FzdCA2IG1vbnRocyBhaGVhZA0KIyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tDQoNCmZjc3QwMSA8LSBmb3JlY2FzdChzdGwwMSwgaCA9IDYsIG1ldGhvZCA9ICJuYWl2ZSIpDQpmY3N0MDIgPC0gZm9yZWNhc3Qoc3RsMDIsIGggPSA2LCBtZXRob2QgPSAibmFpdmUiKQ0KZmNzdDAzIDwtIGZvcmVjYXN0KHN0bDAzLCBoID0gNiwgbWV0aG9kID0gIm5haXZlIikNCmZjc3QwNCA8LSBmb3JlY2FzdChzdGwwNCwgaCA9IDYsIG1ldGhvZCA9ICJuYWl2ZSIpDQoNCmBgYA0KDQpXZSBuZXh0IHBlcmZvcm0gZXJyb3IgYW5hbHlzaXMNCg0KYGBge3J9DQoNCiMgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQ0KIyBQcmVkaWN0aW9uIGVycm9ycyAoTUFQRSB3aXRob3V0ICUpIA0KIyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tDQpQRTAxIDwtICh0ZXN0LmRhdGEgLSBmY3N0MDEkbWVhbikgLyBmY3N0MDEkbWVhbg0KUEUwMiA8LSAodGVzdC5kYXRhIC0gZmNzdDAyJG1lYW4pIC8gZmNzdDAyJG1lYW4NClBFMDMgPC0gKHRlc3QuZGF0YSAtIGZjc3QwMyRtZWFuKSAvIGZjc3QwMyRtZWFuDQpQRTA0IDwtICh0ZXN0LmRhdGEgLSBmY3N0MDQkbWVhbikgLyBmY3N0MDQkbWVhbg0KDQpNQVBFMSA8LSBtZWFuKGFicyhQRTAxKSkNCk1BUEUyIDwtIG1lYW4oYWJzKFBFMDIpKQ0KTUFQRTMgPC0gbWVhbihhYnMoUEUwMykpDQpNQVBFNCA8LSBtZWFuKGFicyhQRTA0KSkNCg0KIyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tDQojIFNxdWFyZWQgZXJyb3JzIChNU0UpDQojIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0NCkUxIDwtIHRlc3QuZGF0YSAtIGZjc3QwMSRtZWFuDQpFMiA8LSB0ZXN0LmRhdGEgLSBmY3N0MDIkbWVhbg0KRTMgPC0gdGVzdC5kYXRhIC0gZmNzdDAzJG1lYW4NCkU0IDwtIHRlc3QuZGF0YSAtIGZjc3QwNCRtZWFuDQoNCk1TRTEgPC0gbWVhbihFMV4yKQ0KTVNFMiA8LSBtZWFuKEUyXjIpDQpNU0UzIDwtIG1lYW4oRTNeMikNCk1TRTQgPC0gbWVhbihFNF4yKQ0KDQojIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0NCiMgQWNjdXJhY3kgdGFibGUNCiMgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQ0KTVNFICA8LSBjKE1TRTEsIE1TRTIsIE1TRTMsIE1TRTQpDQpNQVBFIDwtIGMoTUFQRTEsIE1BUEUyLCBNQVBFMywgTUFQRTQpDQoNCmFjY3VyYWN5IDwtIGNiaW5kKE1TRSA9IE1TRSwgTUFQRSA9IE1BUEUpDQpyb3cubmFtZXMoYWNjdXJhY3kpIDwtIGMoIm49MTQ0IiwgIm49MTIwIiwgIm49OTYiLCAibj03MiIpDQoNCmFjY3VyYWN5DQoNCiMgSWYgeW91IHdhbnQgaXQgbmljZWx5IGZvcm1hdHRlZCBsaWtlIHRoZSBjYXNlIHN0dWR5Og0Ka25pdHI6OmthYmxlKA0KICBhY2N1cmFjeSwgDQogIGNhcHRpb24gPSAiRXJyb3IgY29tcGFyaXNvbiBiZXR3ZWVuIGZvcmVjYXN0IHJlc3VsdHMgd2l0aCBkaWZmZXJlbnQgdHJhaW5pbmcgc2FtcGxlIHNpemVzIg0KKQ0KYGBgDQoNClRoZSBlcnJvciBjb21wYXJpc29uIHRhYmxlIHNob3dzIGhvdyBmb3JlY2FzdCBhY2N1cmFjeSBjaGFuZ2VzIGFjcm9zcyBkaWZmZXJlbnQgdHJhaW5pbmcgd2luZG93IHNpemVzLiBUaGUgbW9kZWxzIHRyYWluZWQgd2l0aCAxNDQgYW5kIDEyMCBtb250aHMgb2YgaGlzdG9yaWNhbCBkYXRhIHByb2R1Y2UgdGhlIGxvd2VzdCBNU0UgdmFsdWVzICgwLjAwOTcyIGFuZCAwLjAwOTc1KSwgaW5kaWNhdGluZyB0aGUgbW9zdCBhY2N1cmF0ZSBmb3JlY2FzdHMgaW4gdGVybXMgb2Ygc3F1YXJlZCBlcnJvci4gTUFQRSB2YWx1ZXMgYXJlIGFsc28gdmVyeSBzaW1pbGFyIGFjcm9zcyB0aGVzZSB0d28gd2luZG93cywgYm90aCBhcm91bmQgMC4wMjcsIHN1Z2dlc3RpbmcgbmVhcmx5IGlkZW50aWNhbCByZWxhdGl2ZSBhY2N1cmFjeS4gRm9yZWNhc3QgYWNjdXJhY3kgZGVjbGluZXMgc2xpZ2h0bHkgd2hlbiB1c2luZyA5NiBhbmQgNzIgbW9udGhzIG9mIHRyYWluaW5nIGRhdGEsIGFzIHJlZmxlY3RlZCBieSBoaWdoZXIgTVNFIGFuZCBNQVBFIHZhbHVlcy4gT3ZlcmFsbCwgdGhlIHJlc3VsdHMgc3VnZ2VzdCB0aGF0IHVzaW5nIGEgbG9uZ2VyIHRyYWluaW5nIHdpbmRvd+KAlHNwZWNpZmljYWxseSAxNDQgb3IgMTIwIG1vbnRoc+KAlHByb3ZpZGVzIHRoZSBtb3N0IHJlbGlhYmxlIHNob3J0LXRlcm0gZm9yZWNhc3RzIGZvciBnYXNvbGluZSBwcmljZXMsIHdoaWxlIHNob3J0ZXIgd2luZG93cyBsZWFkIHRvIG1vZGVzdCByZWR1Y3Rpb25zIGluIHByZWRpY3RpdmUgcGVyZm9ybWFuY2UuDQoNCkFmdGVyIGNvbXB1dGluZyBNU0UgYW5kIE1BUEUgZm9yIGVhY2ggdHJhaW5pbmcgd2luZG93LCBJIHZpc3VhbGl6ZSB0aGUgZXJyb3JzIHRvIGNvbXBhcmUgZm9yZWNhc3RpbmcgcGVyZm9ybWFuY2UgYWNyb3NzIHNhbXBsZSBzaXplcy4gVGhlIHBsb3RzIGJlbG93IHNob3cgaG93IHByZWRpY3Rpb24gYWNjdXJhY3kgY2hhbmdlcyBhcyB0aGUgdHJhaW5pbmcgcGVyaW9kIGJlY29tZXMgc2hvcnRlci4NCg0KYGBge3J9DQoNCnBhcihtZnJvdyA9IGMoMSwgMikpDQoNCiMgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0NCiMgTVNFIFBsb3QNCiMgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0NCnBsb3QoMTo0LCBNU0UsIHR5cGUgPSAiYiIsIGNvbCA9ICJkYXJrcmVkIiwNCiAgICAgeWxhYiA9ICJFcnJvciIsIHhsYWIgPSAiIiwNCiAgICAgbWFpbiA9ICJNU0UiLCBheGVzID0gRkFMU0UpDQoNCmxhYnMgPC0gYygibj0xNDQiLCAibj0xMjAiLCAibj05NiIsICJuPTcyIikNCmF4aXMoMSwgYXQgPSAxOjQsIGxhYmVscyA9IGxhYnMpDQpheGlzKDIpDQoNCiMgTGFiZWwgdGhlIHBvaW50cyB3aXRoIHRoZWlyIHZhbHVlcw0KdGV4dCgxOjQsIE1TRSAtIDAuMDAyLCBhcy5jaGFyYWN0ZXIocm91bmQoTVNFLCA0KSksDQogICAgIGNvbCA9ICJkYXJrcmVkIiwgY2V4ID0gMC43KQ0KDQoNCiMgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0NCiMgTUFQRSBQbG90DQojIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tDQpwbG90KDE6NCwgTUFQRSwgdHlwZSA9ICJiIiwgY29sID0gImJsdWUiLA0KICAgICB5bGFiID0gIkVycm9yIiwgeGxhYiA9ICIiLA0KICAgICBtYWluID0gIk1BUEUiLCBheGVzID0gRkFMU0UpDQoNCmF4aXMoMSwgYXQgPSAxOjQsIGxhYmVscyA9IGxhYnMpDQpheGlzKDIpDQoNCiMgTGFiZWwgdGhlIHBvaW50cyB3aXRoIHRoZWlyIHZhbHVlcw0KdGV4dCgxOjQsIE1BUEUgKyAwLjAwMSwgYXMuY2hhcmFjdGVyKHJvdW5kKE1BUEUsIDQpKSwNCiAgICAgY29sID0gImJsdWUiLCBjZXggPSAwLjcpDQoNCnBhcihtZnJvdyA9IGMoMSwxKSkNCmBgYA0KDQpUaGUgZXJyb3IgcGxvdHMgc2hvdyBob3cgZm9yZWNhc3QgYWNjdXJhY3kgY2hhbmdlcyB3aXRoIGRpZmZlcmVudCB0cmFpbmluZyB3aW5kb3cgc2l6ZXMuIEJvdGggTVNFIGFuZCBNQVBFIGFyZSBsb3dlc3Qgd2hlbiB1c2luZyB0aGUgbGFyZ2VzdCB0cmFpbmluZyB3aW5kb3dzIChuID0gMTQ0IGFuZCBuID0gMTIwKSwgaW5kaWNhdGluZyB0aGF0IG1vZGVscyB3aXRoIG1vcmUgaGlzdG9yaWNhbCBkYXRhIHByb2R1Y2UgbW9yZSBhY2N1cmF0ZSBzaXgtbW9udGggZm9yZWNhc3RzLiBFcnJvciB2YWx1ZXMgaW5jcmVhc2UgZm9yIHRoZSBzaG9ydGVyIHRyYWluaW5nIHdpbmRvd3MgKG4gPSA5NiBhbmQgbiA9IDcyKSwgZXNwZWNpYWxseSBmb3IgTVNFLCBzdWdnZXN0aW5nIHRoYXQgcmVkdWNpbmcgdGhlIGFtb3VudCBvZiBhdmFpbGFibGUgaGlzdG9yeSB3ZWFrZW5zIHByZWRpY3RpdmUgcGVyZm9ybWFuY2UuIE92ZXJhbGwsIHRoZSB2aXN1YWwgcGF0dGVybnMgY29uZmlybSB0aGF0IGxvbmdlciB0cmFpbmluZyBwZXJpb2RzIGxlYWQgdG8gbW9yZSByZWxpYWJsZSBzaG9ydC10ZXJtIGdhc29saW5lIHByaWNlIGZvcmVjYXN0cywgd2hpbGUgc2hvcnRlciB3aW5kb3dzIGludHJvZHVjZSBtb3JlIHZhcmlhYmlsaXR5IGFuZCBoaWdoZXIgZm9yZWNhc3RpbmcgZXJyb3JzLg0KDQojIDYgQ29uY2x1c2lvbg0KDQpUaGlzIGFuYWx5c2lzIGV4YW1pbmVkIG1vbnRobHkgVS5TLiBnYXNvbGluZSBwcmljZXMgZnJvbSBNYXkgMjAxMyB0byBPY3RvYmVyIDIwMjUgdG8gZXZhbHVhdGUgaG93IHJlY2VudCBwcmljZSBtb3ZlbWVudHMgY29tcGFyZSB3aXRoIGxvbmctdGVybSBoaXN0b3JpY2FsIHRyZW5kcy4gQm90aCBjbGFzc2ljYWwgYW5kIFNUTCBkZWNvbXBvc2l0aW9uIHJldmVhbGVkIGNsZWFyIHN0cnVjdHVyYWwgcGF0dGVybnMsIGluY2x1ZGluZyBhIGdyYWR1YWwgZGVjbGluZSB0aHJvdWdoIDIwMTYsIGEgc3RlYWR5IHJpc2UgaGVhZGluZyBpbnRvIDIwMjAsIGFuZCBhIHNoYXJwIHBlYWsgaW4gMjAyMiBmb2xsb3dlZCBieSBwYXJ0aWFsIHN0YWJpbGl6YXRpb24uIFNUTCBwcm9kdWNlZCBhIHNtb290aGVyIGFuZCBtb3JlIHJlbGlhYmxlIHRyZW5kIGVzdGltYXRlLCBtYWtpbmcgaXQgbW9yZSBzdWl0YWJsZSBmb3IgZm9yZWNhc3RpbmcuIFVzaW5nIHRoZSBsYXN0IHNpeCBtb250aHMgYXMgYSB0ZXN0IHNldCBhbmQgdHJhaW5pbmcgd2luZG93cyBvZiAxNDQsIDEyMCwgOTYsIGFuZCA3MiBtb250aHMsIHRoZSByZXN1bHRzIHNob3dlZCB0aGF0IHRoZSBsb25nZXN0IHRyYWluaW5nIHdpbmRvd3MgcHJvZHVjZWQgdGhlIGxvd2VzdCBNU0UgYW5kIE1BUEUgdmFsdWVzLCBpbmRpY2F0aW5nIHRoYXQgaW5jb3Jwb3JhdGluZyBtb3JlIGhpc3RvcmljYWwgaW5mb3JtYXRpb24gbGVhZHMgdG8gYmV0dGVyIHNob3J0LXRlcm0gcHJlZGljdGlvbnMuIFdoaWxlIHRoZXNlIGZpbmRpbmdzIHByb3ZpZGUgdXNlZnVsIGluc2lnaHQgaW50byBob3cgZ2Fzb2xpbmUgcHJpY2VzIGluIGVhcmx5IDIwMjUgYWxpZ24gd2l0aCBsb25nLXRlcm0gdHJlbmRzLCB0aGUgYW5hbHlzaXMgaXMgc3ViamVjdCB0byBzZXZlcmFsIGxpbWl0YXRpb25zLiBUaGUgZGF0YXNldCBjb250YWlucyBvbmx5IDE1MCBvYnNlcnZhdGlvbnMsIHJlc3RyaWN0aW5nIGhvdyBtYW55IG1lYW5pbmdmdWwgdHJhaW5pbmcgd2luZG93cyBjb3VsZCBiZSB1c2VkLCBhbmQgZ2Fzb2xpbmUgcHJpY2VzIGFyZSBpbmZsdWVuY2VkIGJ5IGV4dGVybmFsIGVjb25vbWljIGFuZCBnZW9wb2xpdGljYWwgZmFjdG9ycyB0aGF0IGFyZSBub3QgY2FwdHVyZWQgaW4gYSB1bml2YXJpYXRlIHRpbWUgc2VyaWVzLiBQb3RlbnRpYWwgdXNlciBlcnJvcnPigJRzdWNoIGFzIGluZGV4aW5nIG1pc3Rha2VzIG9yIGFzc3VtcHRpb25zIGFib3V0IHN0YXJ0IGRhdGVz4oCUY291bGQgYWxzbyBhZmZlY3QgdGhlIHJlc3VsdHMsIGFuZCBjbGFzc2ljYWwgZGVjb21wb3NpdGlvbuKAmXMgYWRkaXRpdmUgc3RydWN0dXJlIG1heSBvdmVyc2ltcGxpZnkgYSBzZXJpZXMgd2l0aCBwZXJpb2RzIG9mIGhlaWdodGVuZWQgdm9sYXRpbGl0eS4gRnV0dXJlIGFuYWx5c2VzIGNvdWxkIGJlIHN0cmVuZ3RoZW5lZCBieSB1c2luZyBhIGxhcmdlciBkYXRhc2V0LCBleHBlcmltZW50aW5nIHdpdGggYWRkaXRpb25hbCBmb3JlY2FzdGluZyBtb2RlbHMgc3VjaCBhcyBBUklNQSBvciBleHBvbmVudGlhbCBzbW9vdGhpbmcsIGluY29ycG9yYXRpbmcgZXh0ZXJuYWwgcHJlZGljdG9ycyBsaWtlIGNydWRlIG9pbCBwcmljZXMsIG9yIGFwcGx5aW5nIHJvbGxpbmctb3JpZ2luIHZhbGlkYXRpb24gdG8gYmV0dGVyIGFzc2VzcyBmb3JlY2FzdGluZyBwZXJmb3JtYW5jZS4gRGVzcGl0ZSB0aGVzZSBsaW1pdGF0aW9ucywgdGhlIGFuYWx5c2lzIHByb3ZpZGVzIGEgc3RydWN0dXJlZCBhbmQgZGF0YS1kcml2ZW4gYXNzZXNzbWVudCBvZiBzaG9ydC10ZXJtIGdhc29saW5lIHByaWNlIGJlaGF2aW9yIHJlbGF0aXZlIHRvIGxvbmctdGVybSBoaXN0b3JpY2FsIHBhdHRlcm5zLg==