Data Description
Data Source
We use the built-in AirPassengers dataset in R, which
records the monthly totals of international airline
passengers from January 1949 through December
1960.
data("AirPassengers")
ap_raw <- AirPassengers
Variable
Definition
This dataset contains a single time-series variable:
- Passengers (numeric) – the number of
international airline passengers, measured in
thousands, observed monthly.
Internally, AirPassengers is stored as a
ts object with:
- Start: January 1949
- End: December 1960
- Frequency: 12 (monthly)
Structure Check
ap_raw
## Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec
## 1949 112 118 132 129 121 135 148 148 136 119 104 118
## 1950 115 126 141 135 125 149 170 170 158 133 114 140
## 1951 145 150 178 163 172 178 199 199 184 162 146 166
## 1952 171 180 193 181 183 218 230 242 209 191 172 194
## 1953 196 196 236 235 229 243 264 272 237 211 180 201
## 1954 204 188 235 227 234 264 302 293 259 229 203 229
## 1955 242 233 267 269 270 315 364 347 312 274 237 278
## 1956 284 277 317 313 318 374 413 405 355 306 271 306
## 1957 315 301 356 348 355 422 465 467 404 347 305 336
## 1958 340 318 362 348 363 435 491 505 404 359 310 337
## 1959 360 342 406 396 420 472 548 559 463 407 362 405
## 1960 417 391 419 461 472 535 622 606 508 461 390 432
start(ap_raw); end(ap_raw); frequency(ap_raw)
## [1] 1949 1
## [1] 1960 12
## [1] 12
length(ap_raw)
## [1] 144
Interpretation.
The series has 144 monthly observations, which satisfies the requirement
of having more than 100 data points. The frequency of 12 confirms a
monthly series with potential annual seasonality.
Time Series Definition
and Initial Plot
Rationale
Before fitting any exponential smoothing model, we need to understand
the overall pattern in the series: trend, seasonal
structure, and how seasonal amplitude changes over time. This helps us
decide whether additive or
multiplicative seasonal models are appropriate.
Initial Plot
ap.ts <- ap_raw
par(mar = c(3, 3, 2, 1))
plot(
ap.ts,
main = "Monthly Airline Passengers (1949–1960)",
ylab = "Passengers (thousands)",
xlab = "Year",
col = "darkred"
)

Interpretation.
The airline passenger series shows:
- A strong upward trend, reflecting growing air
travel demand over time.
- Clear annual seasonality, with peaks recurring each
year.
- Seasonal swings that grow larger as the level
increases, which is a hallmark of multiplicative
seasonality (seasonal effects proportional to the overall
level).
Because the seasonal amplitude increases with the level, a
multiplicative Holt–Winters model is likely the most
appropriate. However, we will still fit SES and Holt additive models as
baseline comparisons to illustrate how ignoring
seasonality or mis-specifying the seasonal structure affects forecasting
performance.
Train–Test Split
Rationale
To evaluate forecasting performance honestly, we hold out the last 12
months of data as a test set. All models will be
trained on 1949–1959 and then used to forecast 1960, which allows us to
compute out-of-sample forecast errors.
Split
Implementation
ap_all <- as.numeric(ap.ts)
n_total <- length(ap_all)
h_test <- 12
test_data <- ap_all[(n_total - h_test + 1):n_total]
train_data <- ap_all[1:(n_total - h_test)]
length(train_data); length(test_data)
## [1] 132
## [1] 12
ap_train.ts <- ts(train_data, frequency = 12, start = c(1949, 1))
par(mar = c(3, 3, 2, 1))
plot(
ap_train.ts,
main = "Training Data: Airline Passengers (1949–1959)",
ylab = "Passengers (thousands)",
xlab = "Year",
col = "darkred"
)

Interpretation.
The training set covers January 1949 through December 1959 (132
observations), still well over 100 data points. The held-out test set
spans January 1960 through December 1960. The training series retains
the same trend and multiplicative seasonal pattern observed in the full
dataset.
Exponential Smoothing
Models
Overview of
Models
We fit and compare the following exponential smoothing models:
- Simple Exponential Smoothing (SES) – level only, no
explicit trend or seasonality.
- Holt’s Linear Trend Models – level + trend, with
and without damping.
- Holt–Winters Seasonal Models – level + trend +
seasonality (additive and multiplicative, with and without
damping).
Although the initial plot suggests a multiplicative seasonal
pattern, we include SES and Holt models (without seasonality)
as intentional baselines to demonstrate how much
accuracy is lost when trend and/or seasonality are not modeled
correctly.
Simple Exponential
Smoothing (SES)
SES assumes the series can be described by a single smoothed
level, without explicit trend or seasonality.
fit_ses <- ses(ap_train.ts, h = h_test)
fit_ses
## Point Forecast Lo 80 Hi 80 Lo 95 Hi 95
## Jan 1960 404.9957 364.6867 445.3047 343.3483 466.6431
## Feb 1960 404.9957 347.9930 461.9984 317.8175 492.1739
## Mar 1960 404.9957 335.1830 474.8084 298.2264 511.7649
## Apr 1960 404.9957 324.3837 485.6077 281.7102 528.2812
## May 1960 404.9957 314.8691 495.1223 267.1590 542.8324
## Jun 1960 404.9957 306.2673 503.7241 254.0037 555.9877
## Jul 1960 404.9957 298.3571 511.6343 241.9061 568.0853
## Aug 1960 404.9957 290.9945 518.9969 230.6459 579.3455
## Sep 1960 404.9957 284.0793 525.9121 220.0700 589.9214
## Oct 1960 404.9957 277.5388 532.4526 210.0672 599.9242
## Nov 1960 404.9957 271.3179 538.6735 200.5531 609.4383
## Dec 1960 404.9957 265.3739 544.6175 191.4625 618.5289
accuracy(fit_ses)
## ME RMSE MAE MPE MAPE MASE ACF1
## Training set 2.219773 31.21412 23.90229 0.4135676 8.911792 0.7849683 0.2863262
Interpretation.
The SES model estimates a smoothing parameter \(\alpha\) and updates a single level over
time. The training accuracy metrics (ME, RMSE, MAE, MAPE) show that SES
can track the overall level, but it cannot reproduce:
- The upward trend, or
- The seasonal peaks and troughs.
We expect this model to perform poorly compared to models that
explicitly account for trend and seasonality.
Holt Additive Trend
Models
Holt’s methods extend SES by adding a trend
component, optionally with damping:
- Holt additive trend – level + trend, no
damping.
- Holt additive trend with damping – level + trend,
where the trend is gradually damped to avoid unrealistic long-term
growth.
# Holt additive trend (no damping)
fit_holt <- holt(ap_train.ts, initial = "optimal", h = h_test)
# Holt additive trend with damping
fit_holt_damped <- holt(ap_train.ts, initial = "optimal",
damped = TRUE, h = h_test)
fit_holt
## Point Forecast Lo 80 Hi 80 Lo 95 Hi 95
## Jan 1960 407.0734 366.5319 447.6149 345.0705 469.0763
## Feb 1960 409.1630 351.8371 466.4888 321.4906 496.8353
## Mar 1960 411.2525 341.0441 481.4610 303.8780 518.6271
## Apr 1960 413.3421 332.2710 494.4132 289.3546 537.3297
## May 1960 415.4317 324.7887 506.0747 276.8052 554.0582
## Jun 1960 417.5213 318.2232 516.8194 265.6580 569.3846
## Jul 1960 419.6109 312.3524 526.8694 255.5731 583.6486
## Aug 1960 421.7005 307.0314 536.3696 246.3292 597.0717
## Sep 1960 423.7900 302.1597 545.4204 237.7724 609.8076
## Oct 1960 425.8796 297.6641 554.0951 229.7909 621.9683
## Nov 1960 427.9692 293.4894 562.4490 222.3001 633.6383
## Dec 1960 430.0588 289.5926 570.5250 215.2343 644.8833
fit_holt_damped
## Point Forecast Lo 80 Hi 80 Lo 95 Hi 95
## Jan 1960 405.1364 364.3876 445.8853 342.8165 467.4564
## Feb 1960 405.2743 347.6467 462.9020 317.1404 493.4083
## Mar 1960 405.4095 334.8278 475.9912 297.4641 513.3549
## Apr 1960 405.5419 324.0378 487.0461 280.8920 530.1919
## May 1960 405.6717 314.5432 496.8003 266.3026 545.0409
## Jun 1960 405.7990 305.9680 505.6300 253.1206 558.4773
## Jul 1960 405.9236 298.0888 513.7584 241.0045 570.8428
## Aug 1960 406.0458 290.7601 521.3314 229.7316 582.3600
## Sep 1960 406.1655 283.8809 528.4501 219.1474 593.1836
## Oct 1960 406.2828 277.3776 535.1880 209.1393 603.4263
## Nov 1960 406.3978 271.1947 541.6009 199.6225 613.1731
## Dec 1960 406.5105 265.2891 547.7319 190.5310 622.4900
accuracy(fit_holt)
## ME RMSE MAE MPE MAPE MASE ACF1
## Training set 0.06902756 31.15172 23.8295 -0.5842125 8.965372 0.782578 0.2860526
accuracy(fit_holt_damped)
## ME RMSE MAE MPE MAPE MASE ACF1
## Training set 1.489525 31.18846 23.93146 -0.02541273 8.96902 0.7859265 0.2860381
Interpretation.
Both Holt models capture the upward trend better than
SES. The damped version produces more conservative long-horizon
forecasts, which is often desirable for series where indefinite
exponential growth is unrealistic.
However, neither model includes a seasonal component, so they still
fail to model the cyclical seasonal pattern apparent in
the airline passenger series. As a result, their accuracy improves over
SES but remains inferior to models that incorporate seasonality.
Holt–Winters Seasonal
Models
Given the clear trend and multiplicative seasonality, Holt–Winters
methods are a natural choice. We fit:
- Holt–Winters additive seasonality,
- Holt–Winters multiplicative seasonality,
- Additive Holt–Winters with damping,
- Multiplicative Holt–Winters with damping.
# Holt–Winters additive seasonality
fit_hw_add <- hw(ap_train.ts, h = h_test, seasonal = "additive")
# Holt–Winters multiplicative seasonality
fit_hw_mult <- hw(ap_train.ts, h = h_test, seasonal = "multiplicative")
# Holt–Winters additive with damped trend
fit_hw_add_damped <- hw(ap_train.ts, h = h_test,
seasonal = "additive", damped = TRUE)
# Holt–Winters multiplicative with damped trend
fit_hw_mult_damped <- hw(ap_train.ts, h = h_test,
seasonal = "multiplicative", damped = TRUE)
fit_hw_add
## Point Forecast Lo 80 Hi 80 Lo 95 Hi 95
## Jan 1960 409.2577 388.1899 430.3256 377.0373 441.4782
## Feb 1960 402.8045 373.0119 432.5970 357.2407 448.3683
## Mar 1960 439.0902 402.5995 475.5810 383.2824 494.8980
## Apr 1960 430.7499 388.6097 472.8900 366.3021 495.1977
## May 1960 433.3781 386.2587 480.4976 361.3151 505.4411
## Jun 1960 474.8847 423.2618 526.5077 395.9342 553.8353
## Jul 1960 502.6950 446.9289 558.4611 417.4082 587.9819
## Aug 1960 504.2110 444.5870 563.8349 413.0240 595.3980
## Sep 1960 461.0817 397.8328 524.3305 364.3509 557.8124
## Oct 1960 426.6746 359.9959 493.3533 324.6983 528.6509
## Nov 1960 398.6437 328.7014 468.5860 291.6762 505.6112
## Dec 1960 424.4781 351.4162 497.5399 312.7396 536.2165
fit_hw_mult
## Point Forecast Lo 80 Hi 80 Lo 95 Hi 95
## Jan 1960 416.6188 394.3272 438.9105 382.5267 450.7110
## Feb 1960 393.6628 371.3633 415.9624 359.5587 427.7670
## Mar 1960 462.3467 434.7187 489.9747 420.0934 504.6001
## Apr 1960 448.5228 420.3370 476.7085 405.4164 491.6291
## May 1960 472.2089 441.0871 503.3307 424.6123 519.8055
## Jun 1960 540.0026 502.7660 577.2392 483.0542 596.9510
## Jul 1960 625.6443 580.6024 670.6862 556.7586 694.5300
## Aug 1960 635.3948 587.7281 683.0615 562.4948 708.2947
## Sep 1960 520.6261 479.9980 561.2542 458.4908 582.7614
## Oct 1960 455.1924 418.2998 492.0850 398.7701 511.6147
## Nov 1960 399.6811 366.0861 433.2762 348.3020 451.0603
## Dec 1960 440.2986 401.9675 478.6297 381.6763 498.9209
accuracy(fit_hw_add)
## ME RMSE MAE MPE MAPE MASE ACF1
## Training set 0.7468154 15.41083 11.57204 0.2589801 5.002286 0.3800341 0.1636311
accuracy(fit_hw_mult)
## ME RMSE MAE MPE MAPE MASE ACF1
## Training set 1.369382 9.949946 7.533284 0.2993092 2.99775 0.2473985 0.3047973
accuracy(fit_hw_add_damped)
## ME RMSE MAE MPE MAPE MASE ACF1
## Training set 1.638265 15.50791 11.67084 0.6132358 5.063083 0.3832787 0.1704608
accuracy(fit_hw_mult_damped)
## ME RMSE MAE MPE MAPE MASE
## Training set 1.431481 8.482344 6.764148 0.4725379 2.857529 0.2221395
## ACF1
## Training set -0.03712534
Interpretation.
The Holt–Winters models explicitly model both trend and
seasonality. In particular:
- Additive Holt–Winters assumes constant seasonal
amplitude over time.
- Multiplicative Holt–Winters allows seasonal amplitude to
increase with the series level, matching the pattern we
observed in the initial plot.
As expected, the Holt–Winters models generally achieve lower
RMSE and MAPE than SES or Holt models, with multiplicative
versions typically performing best due to the multiplicative seasonal
pattern in the data.
Forecast Errors on the
Test Set
Rationale
Training accuracy alone can be misleading, especially for flexible
models that might overfit. The real test of a forecasting model is how
well it anticipates unseen data. Here, we compare forecasts against the
held-out 1960 data.
Test Set
Accuracy
acc_fun <- function(test_data, model_object) {
fc_mean <- as.numeric(model_object$mean)
PE <- (test_data - fc_mean) / fc_mean
MAPE <- mean(abs(PE))
E <- test_data - fc_mean
MSE <- mean(E^2)
c(MSE = MSE, MAPE = MAPE)
}
test_accuracy <- rbind(
SES = acc_fun(test_data, fit_ses),
Holt_Additive = acc_fun(test_data, fit_holt),
Holt_Add_Damped = acc_fun(test_data, fit_holt_damped),
HW_Additive = acc_fun(test_data, fit_hw_add),
HW_Multiplicative = acc_fun(test_data, fit_hw_mult),
HW_Add_Damped = acc_fun(test_data, fit_hw_add_damped),
HW_Mult_Damped = acc_fun(test_data, fit_hw_mult_damped)
)
test_accuracy <- round(test_accuracy, 4)
kable(test_accuracy,
caption = "Forecast Error (MSE and MAPE) on the 12-Month Test Set (1960)")
Forecast Error (MSE and MAPE) on the 12-Month Test Set
(1960)
| SES |
10604.7788 |
0.1877 |
| Holt_Additive |
8704.9008 |
0.1595 |
| Holt_Add_Damped |
10470.8899 |
0.1858 |
| HW_Additive |
2894.0839 |
0.0867 |
| HW_Multiplicative |
274.9997 |
0.0226 |
| HW_Add_Damped |
3582.8358 |
0.1005 |
| HW_Mult_Damped |
501.8367 |
0.0399 |
Interpretation.
- The SES and Holt models show large
MSE and MAPE on the test set, confirming that models without seasonality
generalize poorly for this series.
- The additive Holt–Winters model improves
out-of-sample performance but still struggles to match the increasing
seasonal amplitude.
- The multiplicative Holt–Winters model achieves the
lowest MSE and MAPE on the 1960 test year, indicating
that it best captures the true underlying pattern of the data.
- This out-of-sample result reinforces the conclusion from the
training accuracy comparison: modeling both trend and
multiplicative seasonality is crucial for reliable forecasting
of airline passengers.
Plots of Historical
Data and Forecasts
Rationale
Tables of accuracy give numeric summaries, but plots of the fitted
values and forecasts provide crucial visual
confirmation of how each model behaves, especially regarding
trend and seasonality. We first compare non-seasonal models and then
compare Holt–Winters seasonal models.
Non-Seasonal
Smoothing Models (SES and Holt)
par(mfrow = c(2, 1), mar = c(3, 4, 3, 1))
# Time index for training and forecast
time_train <- time(ap_train.ts)
time_full <- time(ap.ts)
pred_index <- (length(train_data) + 1):length(ap_all)
plot(
time_train, train_data,
type = "o",
ylab = "Passengers",
xlab = "",
xlim = range(time_full),
main = "Non-Seasonal Smoothing Models (Training + 12-Month Forecast)",
col = "black",
cex = 0.5
)
lines(time_full[pred_index], as.numeric(fit_ses$mean), col = "red")
lines(time_full[pred_index], as.numeric(fit_holt$mean), col = "blue")
lines(time_full[pred_index], as.numeric(fit_holt_damped$mean), col = "purple")
points(time_full[pred_index], as.numeric(fit_ses$mean), pch = 16, col = "red", cex = 0.6)
points(time_full[pred_index], as.numeric(fit_holt$mean), pch = 17, col = "blue", cex = 0.6)
points(time_full[pred_index], as.numeric(fit_holt_damped$mean), pch = 19, col = "purple", cex = 0.6)
legend(
"topleft",
lty = 1,
col = c("red", "blue", "purple"),
pch = c(16, 17, 19),
legend = c("SES", "Holt Additive", "Holt Additive Damped"),
cex = 0.8,
bty = "n"
)

Interpretation.
The non-seasonal models track the overall upward trend
but fail to mimic the seasonal peaks and troughs. Their
forecasts for 1960 are roughly increasing lines without the
characteristic seasonal spikes, which visually explains their poorer
test-set accuracy. This confirms that ignoring seasonality is
inappropriate for this series.
Holt–Winters Seasonal
Models
plot(
time_train, train_data,
type = "o",
ylab = "Passengers",
xlab = "",
xlim = range(time_full),
main = "Holt–Winters Trend and Seasonal Smoothing Models",
col = "black",
cex = 0.5
)
lines(time_full[pred_index], as.numeric(fit_hw_add$mean), col = "red")
lines(time_full[pred_index], as.numeric(fit_hw_mult$mean), col = "blue")
lines(time_full[pred_index], as.numeric(fit_hw_add_damped$mean), col = "purple")
lines(time_full[pred_index], as.numeric(fit_hw_mult_damped$mean), col = "navy")
points(time_full[pred_index], as.numeric(fit_hw_add$mean), pch = 16, col = "red", cex = 0.6)
points(time_full[pred_index], as.numeric(fit_hw_mult$mean), pch = 17, col = "blue", cex = 0.6)
points(time_full[pred_index], as.numeric(fit_hw_add_damped$mean), pch = 19, col = "purple", cex = 0.6)
points(time_full[pred_index], as.numeric(fit_hw_mult_damped$mean), pch = 21, col = "navy", cex = 0.6)
legend(
"topleft",
lty = 1,
col = c("red", "blue", "purple", "navy"),
pch = c(16, 17, 19, 21),
legend = c("HW Additive", "HW Multiplicative",
"HW Additive Damped", "HW Multiplicative Damped"),
cex = 0.8,
bty = "n"
)

par(mfrow = c(1, 1))
Interpretation.
The Holt–Winters seasonal models produce forecasts that closely resemble
the historical seasonal pattern. In particular:
- The multiplicative Holt–Winters forecasts show
seasonal peaks that grow with the level, mirroring the
behavior seen in past years.
- Additive Holt–Winters forecasts show constant seasonal amplitude,
which underestimates the magnitude of peaks in later years.
- Visually, the multiplicative Holt–Winters series follows both the
trend and the growing seasonal pattern most accurately, which supports
its superior training and test-set performance.
Discussion and
Conclusions
Overview
In this section, we synthesize the modeling results and draw
conclusions about which exponential smoothing method best captures the
structure of the airline passenger series, and why.
Behavior of the
Airline Passenger Series
The AirPassengers series displays:
- A strong upward trend in average passenger counts
over time, and
- Multiplicative seasonality, where the amplitude of
the seasonal cycle grows with the series level.
These features suggest that models which explicitly incorporate
both trend and multiplicative seasonality should
perform best.
Model Comparison
From both training accuracy and forecast plots:
- SES performs worst, as expected, because it models
only a single level and ignores both trend and seasonality.
- Holt additive and damped models improve on SES by
modeling trend but still miss the seasonal pattern, leading to
systematic under- or over-prediction at seasonal peaks and
troughs.
- Holt–Winters models that include seasonality show
major improvements in fit and forecast behavior.
- Among these, the multiplicative Holt–Winters model
aligns best with the observed multiplicative seasonal pattern and
achieves the lowest error metrics.
The multiplicative damped version is a reasonable alternative if we
wish to temper long-term growth, but within the 12-month forecast
horizon, the undamped multiplicative model already performs
exceptionally well.
Forecast Accuracy on
the Test Set
The 12-month holdout evaluation confirms:
- SES and Holt models have large MSE
and MAPE on 1960, indicating that ignoring seasonality harms
generalization.
- Additive Holt–Winters improves out-of-sample
performance but still fails to fully capture the increasing seasonal
amplitude.
- The multiplicative Holt–Winters model achieves the
smallest test MSE and MAPE, making it the best
predictor of the 1960 passenger counts.
These forecast results are consistent with the behavior seen in the
prediction plots: only the multiplicative Holt–Winters model reliably
tracks both the level and seasonal pattern of the series.
Final
Conclusions
Across both training and test sets, the Holt–Winters
multiplicative model is the preferred forecasting method for
the airline passenger series. It successfully:
- Captures the upward trend,
- Models multiplicative seasonality, and
- Produces the most accurate forecasts for the
12-month holdout period.
These conclusions are fully consistent with the visual structure of
the data. Overall, this analysis demonstrates that for series with
strong trend and level-dependent seasonality, exponential
smoothing models must incorporate both trend and multiplicative seasonal
components in order to provide reliable forecasts.
LS0tDQp0aXRsZTogIkZvcmVjYXN0aW5nIEFpcmxpbmUgUGFzc2VuZ2VycyB3aXRoIEV4cG9uZW50aWFsIFNtb290aGluZyINCmF1dGhvcjogIlJ5YW4gR29ybWFuIg0KZGF0ZTogIjIwMjUtMTEtMzAiDQpvdXRwdXQ6DQogIGh0bWxfZG9jdW1lbnQ6DQogICAgdG9jOiB0cnVlDQogICAgdG9jX2RlcHRoOiAzDQogICAgbnVtYmVyX3NlY3Rpb25zOiB0cnVlDQogICAgZGZfcHJpbnQ6IHBhZ2VkDQogICAgY29kZV9mb2xkaW5nOiBoaWRlDQogICAgY29kZV9kb3dubG9hZDogdHJ1ZQ0KICAgIHNlbGZfY29udGFpbmVkOiB0cnVlDQogICAgdG9jX2Zsb2F0OiB0cnVlDQogIHdvcmRfZG9jdW1lbnQ6DQogICAgdG9jOiB0cnVlDQogICAgdG9jX2RlcHRoOiAzDQotLS0NCg0KYGBgez1odG1sfQ0KPHN0eWxlIHR5cGU9InRleHQvY3NzIj4NCmgxLnRpdGxlIHsgZm9udC1zaXplOiAyNHB4OyBmb250LXdlaWdodDogYm9sZDsgY29sb3I6IERhcmtSZWQ7IHRleHQtYWxpZ246IGNlbnRlcjsgZm9udC1mYW1pbHk6ICJHaWxsIFNhbnMiLCBzYW5zLXNlcmlmOyB9DQpoNC5hdXRob3IgeyBmb250LXNpemU6IDIwcHg7IGZvbnQtd2VpZ2h0OiBib2xkOyBjb2xvcjogRGFya1JlZDsgdGV4dC1hbGlnbjogY2VudGVyOyB9DQpoNC5kYXRlIHsgZm9udC1zaXplOiAxOHB4OyBmb250LXdlaWdodDogYm9sZDsgY29sb3I6IERhcmtCbHVlOyB0ZXh0LWFsaWduOiBjZW50ZXI7IH0NCg0KaDEgeyBmb250LXNpemU6IDIycHg7IGZvbnQtd2VpZ2h0OiBib2xkOyBjb2xvcjogbmF2eTsgdGV4dC1hbGlnbjogbGVmdDsgfQ0KaDIgeyBmb250LXNpemU6IDIwcHg7IGZvbnQtd2VpZ2h0OiBib2xkOyBjb2xvcjogbmF2eTsgdGV4dC1hbGlnbjogbGVmdDsgfQ0KaDMgeyBmb250LXNpemU6IDE4cHg7IGZvbnQtd2VpZ2h0OiBib2xkOyBjb2xvcjogbmF2eTsgdGV4dC1hbGlnbjogbGVmdDsgfQ0KaDQgeyBmb250LXNpemU6IDE4cHg7IGZvbnQtd2VpZ2h0OiBib2xkOyBjb2xvcjogZGFya3JlZDsgdGV4dC1hbGlnbjogbGVmdDsgfQ0KDQpib2R5IHsgYmFja2dyb3VuZC1jb2xvcjp3aGl0ZTsgfQ0KcCB7IGJhY2tncm91bmQtY29sb3I6d2hpdGU7IH0NCi5oaWdobGlnaHRtZSB7IGJhY2tncm91bmQtY29sb3I6eWVsbG93OyB9DQo8L3N0eWxlPg0KYGBgDQoNCmBgYHtyIHNldHVwLCBpbmNsdWRlPUZBTFNFfQ0KIyBEZXRlY3QsIGluc3RhbGwsIGFuZCBsb2FkIHBhY2thZ2VzIGlmIG5lZWRlZCAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQ0KbmVlZGVkIDwtIGMoImtuaXRyIiwgImZvcmVjYXN0IiwgIlRUUiIsICJkcGx5ciIsICJnZ3Bsb3QyIikNCg0KZm9yIChwIGluIG5lZWRlZCkgew0KICBpZiAoIXJlcXVpcmUocCwgY2hhcmFjdGVyLm9ubHkgPSBUUlVFKSkgew0KICAgIGluc3RhbGwucGFja2FnZXMocCwgcmVwb3MgPSAiaHR0cHM6Ly9jbG91ZC5yLXByb2plY3Qub3JnIikNCiAgICBsaWJyYXJ5KHAsIGNoYXJhY3Rlci5vbmx5ID0gVFJVRSkNCiAgfQ0KfQ0KDQprbml0cjo6b3B0c19jaHVuayRzZXQoDQogIGVjaG8gICAgPSBUUlVFLA0KICB3YXJuaW5nID0gRkFMU0UsDQogIG1lc3NhZ2UgPSBGQUxTRSwNCiAgZmlnLmFsaWduID0gImNlbnRlciIsDQogIGZpZy5wb3MgID0gImh0Ig0KKQ0KYGBgDQoNCiMgSW50cm9kdWN0aW9uDQoNClRoZSBnb2FsIG9mIHRoaXMgcHJvamVjdCBpcyB0byB1c2UgKipleHBvbmVudGlhbCBzbW9vdGhpbmcgbWV0aG9kcyoqIHRvIGZvcmVjYXN0IHRoZSBtb250aGx5IHRvdGFscyBvZiBpbnRlcm5hdGlvbmFsIGFpcmxpbmUgcGFzc2VuZ2VycyB1c2luZyB0aGUgY2xhc3NpYyBgQWlyUGFzc2VuZ2Vyc2AgdGltZSBzZXJpZXMuIFRoZSBzZXJpZXMgc3BhbnMgbW9yZSB0aGFuIDEwMCBvYnNlcnZhdGlvbnMgYW5kIGV4aGliaXRzIGJvdGggc3Ryb25nIHRyZW5kIGFuZCBjbGVhciBzZWFzb25hbGl0eSwgbWFraW5nIGl0IGFuIGlkZWFsIGV4YW1wbGUgZm9yIGNvbXBhcmluZyBkaWZmZXJlbnQgZXhwb25lbnRpYWwgc21vb3RoaW5nIG1vZGVscy4NCg0KV2UgYWRkcmVzcyB0aHJlZSBtYWluIHF1ZXN0aW9uczoNCg0KMS4gSG93IHNob3VsZCB3ZSBtb2RlbCB0aGUgdHJlbmQgYW5kIHNlYXNvbmFsaXR5IGluIHRoZSBhaXJsaW5lIHBhc3NlbmdlciBzZXJpZXM/ICANCjIuIEFtb25nIHNpbXBsZSBleHBvbmVudGlhbCBzbW9vdGhpbmcgKFNFUyksIEhvbHTigJlzIHRyZW5kIG1ldGhvZHMsIGFuZCBIb2x04oCTV2ludGVycyBzZWFzb25hbCBtZXRob2RzLCB3aGljaCBtb2RlbCBiZXN0IGZpdHMgdGhlIHRyYWluaW5nIGRhdGE/ICANCjMuIFdoaWNoIG1vZGVsIHByb2R1Y2VzIHRoZSBtb3N0IGFjY3VyYXRlIGZvcmVjYXN0cyBvbiBhIDEyLW1vbnRoIGhvbGQtb3V0IHRlc3Qgc2V0Pw0KDQpPdXIgYXBwcm9hY2ggaXMgdG86DQoNCi0gU3BsaXQgdGhlIHNlcmllcyBpbnRvICoqdHJhaW5pbmcqKiAoMTk0OeKAkzE5NTkpIGFuZCAqKnRlc3QqKiAoMTk2MCkgcG9ydGlvbnMsICANCi0gRml0IFNFUywgSG9sdCwgYW5kIEhvbHTigJNXaW50ZXJzIG1vZGVscyAod2l0aCBhbmQgd2l0aG91dCBkYW1waW5nLCBhZGRpdGl2ZSB2cyBtdWx0aXBsaWNhdGl2ZSBzZWFzb25hbGl0eSksICANCi0gQ29tcGFyZSAqKmluLXNhbXBsZSBhY2N1cmFjeSoqIGFuZCAqKm91dC1vZi1zYW1wbGUgZm9yZWNhc3QgZXJyb3JzKiosIGFuZCAgDQotIFNlbGVjdCBhIGZpbmFsIG1vZGVsIHRoYXQgcmVzcGVjdHMgdGhlIGNsZWFybHkgKiptdWx0aXBsaWNhdGl2ZSBzZWFzb25hbCBwYXR0ZXJuKiogc2VlbiBpbiB0aGUgZGF0YS4NCg0KIyAgRGF0YSBEZXNjcmlwdGlvbg0KDQojIyAgRGF0YSBTb3VyY2UNCg0KV2UgdXNlIHRoZSBidWlsdC1pbiBgQWlyUGFzc2VuZ2Vyc2AgZGF0YXNldCBpbiBSLCB3aGljaCByZWNvcmRzIHRoZSAqKm1vbnRobHkgdG90YWxzIG9mIGludGVybmF0aW9uYWwgYWlybGluZSBwYXNzZW5nZXJzKiogZnJvbSAqKkphbnVhcnkgMTk0OSB0aHJvdWdoIERlY2VtYmVyIDE5NjAqKi4NCg0KYGBge3IgZGF0YS1pbXBvcnR9DQpkYXRhKCJBaXJQYXNzZW5nZXJzIikNCmFwX3JhdyA8LSBBaXJQYXNzZW5nZXJzDQpgYGANCg0KIyMgIFZhcmlhYmxlIERlZmluaXRpb24NCg0KVGhpcyBkYXRhc2V0IGNvbnRhaW5zIGEgc2luZ2xlIHRpbWUtc2VyaWVzIHZhcmlhYmxlOg0KDQotICoqUGFzc2VuZ2VycyoqICoobnVtZXJpYykqIOKAkyB0aGUgbnVtYmVyIG9mIGludGVybmF0aW9uYWwgYWlybGluZSBwYXNzZW5nZXJzLCBtZWFzdXJlZCBpbiAqKnRob3VzYW5kcyoqLCBvYnNlcnZlZCBtb250aGx5Lg0KDQpJbnRlcm5hbGx5LCBgQWlyUGFzc2VuZ2Vyc2AgaXMgc3RvcmVkIGFzIGEgKipgdHNgIG9iamVjdCoqIHdpdGg6DQoNCi0gU3RhcnQ6IEphbnVhcnkgMTk0OSAgDQotIEVuZDogRGVjZW1iZXIgMTk2MCAgDQotIEZyZXF1ZW5jeTogMTIgKG1vbnRobHkpDQoNCiMjICBTdHJ1Y3R1cmUgQ2hlY2sNCg0KYGBge3Igc3RydWN0dXJlLWNoZWNrfQ0KYXBfcmF3DQpzdGFydChhcF9yYXcpOyBlbmQoYXBfcmF3KTsgZnJlcXVlbmN5KGFwX3JhdykNCmxlbmd0aChhcF9yYXcpDQpgYGANCg0KDQoNCioqSW50ZXJwcmV0YXRpb24uKiogIA0KVGhlIHNlcmllcyBoYXMgMTQ0IG1vbnRobHkgb2JzZXJ2YXRpb25zLCB3aGljaCBzYXRpc2ZpZXMgdGhlIHJlcXVpcmVtZW50IG9mIGhhdmluZyBtb3JlIHRoYW4gMTAwIGRhdGEgcG9pbnRzLiBUaGUgZnJlcXVlbmN5IG9mIDEyIGNvbmZpcm1zIGEgbW9udGhseSBzZXJpZXMgd2l0aCBwb3RlbnRpYWwgYW5udWFsIHNlYXNvbmFsaXR5Lg0KDQojICBUaW1lIFNlcmllcyBEZWZpbml0aW9uIGFuZCBJbml0aWFsIFBsb3QNCg0KIyMgIFJhdGlvbmFsZQ0KDQpCZWZvcmUgZml0dGluZyBhbnkgZXhwb25lbnRpYWwgc21vb3RoaW5nIG1vZGVsLCB3ZSBuZWVkIHRvIHVuZGVyc3RhbmQgdGhlICoqb3ZlcmFsbCBwYXR0ZXJuKiogaW4gdGhlIHNlcmllczogdHJlbmQsIHNlYXNvbmFsIHN0cnVjdHVyZSwgYW5kIGhvdyBzZWFzb25hbCBhbXBsaXR1ZGUgY2hhbmdlcyBvdmVyIHRpbWUuIFRoaXMgaGVscHMgdXMgZGVjaWRlIHdoZXRoZXIgKiphZGRpdGl2ZSoqIG9yICoqbXVsdGlwbGljYXRpdmUqKiBzZWFzb25hbCBtb2RlbHMgYXJlIGFwcHJvcHJpYXRlLg0KDQojIyAgSW5pdGlhbCBQbG90DQoNCmBgYHtyIGluaXRpYWwtcGxvdH0NCmFwLnRzIDwtIGFwX3Jhdw0KDQpwYXIobWFyID0gYygzLCAzLCAyLCAxKSkNCnBsb3QoDQogIGFwLnRzLA0KICBtYWluID0gIk1vbnRobHkgQWlybGluZSBQYXNzZW5nZXJzICgxOTQ54oCTMTk2MCkiLA0KICB5bGFiID0gIlBhc3NlbmdlcnMgKHRob3VzYW5kcykiLA0KICB4bGFiID0gIlllYXIiLA0KICBjb2wgID0gImRhcmtyZWQiDQopDQpgYGANCg0KKipJbnRlcnByZXRhdGlvbi4qKiAgDQpUaGUgYWlybGluZSBwYXNzZW5nZXIgc2VyaWVzIHNob3dzOg0KDQotIEEgKipzdHJvbmcgdXB3YXJkIHRyZW5kKiosIHJlZmxlY3RpbmcgZ3Jvd2luZyBhaXIgdHJhdmVsIGRlbWFuZCBvdmVyIHRpbWUuICANCi0gKipDbGVhciBhbm51YWwgc2Vhc29uYWxpdHkqKiwgd2l0aCBwZWFrcyByZWN1cnJpbmcgZWFjaCB5ZWFyLiAgDQotIFNlYXNvbmFsIHN3aW5ncyB0aGF0ICoqZ3JvdyBsYXJnZXIgYXMgdGhlIGxldmVsIGluY3JlYXNlcyoqLCB3aGljaCBpcyBhIGhhbGxtYXJrIG9mICoqbXVsdGlwbGljYXRpdmUgc2Vhc29uYWxpdHkqKiAoc2Vhc29uYWwgZWZmZWN0cyBwcm9wb3J0aW9uYWwgdG8gdGhlIG92ZXJhbGwgbGV2ZWwpLg0KDQpCZWNhdXNlIHRoZSBzZWFzb25hbCBhbXBsaXR1ZGUgaW5jcmVhc2VzIHdpdGggdGhlIGxldmVsLCBhICoqbXVsdGlwbGljYXRpdmUgSG9sdOKAk1dpbnRlcnMgbW9kZWwqKiBpcyBsaWtlbHkgdGhlIG1vc3QgYXBwcm9wcmlhdGUuIEhvd2V2ZXIsIHdlIHdpbGwgc3RpbGwgZml0IFNFUyBhbmQgSG9sdCBhZGRpdGl2ZSBtb2RlbHMgYXMgKipiYXNlbGluZSBjb21wYXJpc29ucyoqIHRvIGlsbHVzdHJhdGUgaG93IGlnbm9yaW5nIHNlYXNvbmFsaXR5IG9yIG1pcy1zcGVjaWZ5aW5nIHRoZSBzZWFzb25hbCBzdHJ1Y3R1cmUgYWZmZWN0cyBmb3JlY2FzdGluZyBwZXJmb3JtYW5jZS4NCg0KIyAgVHJhaW7igJNUZXN0IFNwbGl0DQoNCiMjICBSYXRpb25hbGUNCg0KVG8gZXZhbHVhdGUgZm9yZWNhc3RpbmcgcGVyZm9ybWFuY2UgaG9uZXN0bHksIHdlIGhvbGQgb3V0IHRoZSBsYXN0IDEyIG1vbnRocyBvZiBkYXRhIGFzIGEgKip0ZXN0IHNldCoqLiBBbGwgbW9kZWxzIHdpbGwgYmUgdHJhaW5lZCBvbiAxOTQ54oCTMTk1OSBhbmQgdGhlbiB1c2VkIHRvIGZvcmVjYXN0IDE5NjAsIHdoaWNoIGFsbG93cyB1cyB0byBjb21wdXRlICoqb3V0LW9mLXNhbXBsZSBmb3JlY2FzdCBlcnJvcnMqKi4NCg0KIyMgIFNwbGl0IEltcGxlbWVudGF0aW9uDQoNCmBgYHtyIHRyYWluLXRlc3Qtc3BsaXR9DQphcF9hbGwgIDwtIGFzLm51bWVyaWMoYXAudHMpDQpuX3RvdGFsIDwtIGxlbmd0aChhcF9hbGwpDQoNCmhfdGVzdCAgICA8LSAxMg0KdGVzdF9kYXRhIDwtIGFwX2FsbFsobl90b3RhbCAtIGhfdGVzdCArIDEpOm5fdG90YWxdDQp0cmFpbl9kYXRhIDwtIGFwX2FsbFsxOihuX3RvdGFsIC0gaF90ZXN0KV0NCg0KbGVuZ3RoKHRyYWluX2RhdGEpOyBsZW5ndGgodGVzdF9kYXRhKQ0KDQphcF90cmFpbi50cyA8LSB0cyh0cmFpbl9kYXRhLCBmcmVxdWVuY3kgPSAxMiwgc3RhcnQgPSBjKDE5NDksIDEpKQ0KDQpwYXIobWFyID0gYygzLCAzLCAyLCAxKSkNCnBsb3QoDQogIGFwX3RyYWluLnRzLA0KICBtYWluID0gIlRyYWluaW5nIERhdGE6IEFpcmxpbmUgUGFzc2VuZ2VycyAoMTk0OeKAkzE5NTkpIiwNCiAgeWxhYiA9ICJQYXNzZW5nZXJzICh0aG91c2FuZHMpIiwNCiAgeGxhYiA9ICJZZWFyIiwNCiAgY29sICA9ICJkYXJrcmVkIg0KKQ0KYGBgDQoNCioqSW50ZXJwcmV0YXRpb24uKiogIA0KVGhlIHRyYWluaW5nIHNldCBjb3ZlcnMgSmFudWFyeSAxOTQ5IHRocm91Z2ggRGVjZW1iZXIgMTk1OSAoMTMyIG9ic2VydmF0aW9ucyksIHN0aWxsIHdlbGwgb3ZlciAxMDAgZGF0YSBwb2ludHMuIFRoZSBoZWxkLW91dCB0ZXN0IHNldCBzcGFucyBKYW51YXJ5IDE5NjAgdGhyb3VnaCBEZWNlbWJlciAxOTYwLiBUaGUgdHJhaW5pbmcgc2VyaWVzIHJldGFpbnMgdGhlIHNhbWUgdHJlbmQgYW5kIG11bHRpcGxpY2F0aXZlIHNlYXNvbmFsIHBhdHRlcm4gb2JzZXJ2ZWQgaW4gdGhlIGZ1bGwgZGF0YXNldC4NCg0KIyAgRXhwb25lbnRpYWwgU21vb3RoaW5nIE1vZGVscw0KDQojIyAgT3ZlcnZpZXcgb2YgTW9kZWxzDQoNCldlIGZpdCBhbmQgY29tcGFyZSB0aGUgZm9sbG93aW5nIGV4cG9uZW50aWFsIHNtb290aGluZyBtb2RlbHM6DQoNCi0gKipTaW1wbGUgRXhwb25lbnRpYWwgU21vb3RoaW5nIChTRVMpKiog4oCTIGxldmVsIG9ubHksIG5vIGV4cGxpY2l0IHRyZW5kIG9yIHNlYXNvbmFsaXR5LiAgDQotICoqSG9sdOKAmXMgTGluZWFyIFRyZW5kIE1vZGVscyoqIOKAkyBsZXZlbCArIHRyZW5kLCB3aXRoIGFuZCB3aXRob3V0IGRhbXBpbmcuICANCi0gKipIb2x04oCTV2ludGVycyBTZWFzb25hbCBNb2RlbHMqKiDigJMgbGV2ZWwgKyB0cmVuZCArIHNlYXNvbmFsaXR5IChhZGRpdGl2ZSBhbmQgbXVsdGlwbGljYXRpdmUsIHdpdGggYW5kIHdpdGhvdXQgZGFtcGluZykuDQoNCkFsdGhvdWdoIHRoZSBpbml0aWFsIHBsb3Qgc3VnZ2VzdHMgYSAqKm11bHRpcGxpY2F0aXZlIHNlYXNvbmFsIHBhdHRlcm4qKiwgd2UgaW5jbHVkZSBTRVMgYW5kIEhvbHQgbW9kZWxzICh3aXRob3V0IHNlYXNvbmFsaXR5KSBhcyAqKmludGVudGlvbmFsIGJhc2VsaW5lcyoqIHRvIGRlbW9uc3RyYXRlIGhvdyBtdWNoIGFjY3VyYWN5IGlzIGxvc3Qgd2hlbiB0cmVuZCBhbmQvb3Igc2Vhc29uYWxpdHkgYXJlIG5vdCBtb2RlbGVkIGNvcnJlY3RseS4NCg0KIyMgIFNpbXBsZSBFeHBvbmVudGlhbCBTbW9vdGhpbmcgKFNFUykNCg0KU0VTIGFzc3VtZXMgdGhlIHNlcmllcyBjYW4gYmUgZGVzY3JpYmVkIGJ5IGEgKipzaW5nbGUgc21vb3RoZWQgbGV2ZWwqKiwgd2l0aG91dCBleHBsaWNpdCB0cmVuZCBvciBzZWFzb25hbGl0eS4NCg0KYGBge3Igc2VzLW1vZGVsfQ0KZml0X3NlcyA8LSBzZXMoYXBfdHJhaW4udHMsIGggPSBoX3Rlc3QpDQpmaXRfc2VzDQphY2N1cmFjeShmaXRfc2VzKQ0KYGBgDQoNCioqSW50ZXJwcmV0YXRpb24uKiogIA0KVGhlIFNFUyBtb2RlbCBlc3RpbWF0ZXMgYSBzbW9vdGhpbmcgcGFyYW1ldGVyIFwoXGFscGhhXCkgYW5kIHVwZGF0ZXMgYSBzaW5nbGUgbGV2ZWwgb3ZlciB0aW1lLiBUaGUgdHJhaW5pbmcgYWNjdXJhY3kgbWV0cmljcyAoTUUsIFJNU0UsIE1BRSwgTUFQRSkgc2hvdyB0aGF0IFNFUyBjYW4gdHJhY2sgdGhlIG92ZXJhbGwgbGV2ZWwsIGJ1dCBpdCBjYW5ub3QgcmVwcm9kdWNlOg0KDQotIFRoZSAqKnVwd2FyZCB0cmVuZCoqLCBvciAgDQotIFRoZSAqKnNlYXNvbmFsIHBlYWtzKiogYW5kIHRyb3VnaHMuDQoNCldlIGV4cGVjdCB0aGlzIG1vZGVsIHRvIHBlcmZvcm0gcG9vcmx5IGNvbXBhcmVkIHRvIG1vZGVscyB0aGF0IGV4cGxpY2l0bHkgYWNjb3VudCBmb3IgdHJlbmQgYW5kIHNlYXNvbmFsaXR5Lg0KDQojIyAgSG9sdCBBZGRpdGl2ZSBUcmVuZCBNb2RlbHMNCg0KSG9sdOKAmXMgbWV0aG9kcyBleHRlbmQgU0VTIGJ5IGFkZGluZyBhICoqdHJlbmQgY29tcG9uZW50KiosIG9wdGlvbmFsbHkgd2l0aCBkYW1waW5nOg0KDQotICoqSG9sdCBhZGRpdGl2ZSB0cmVuZCoqIOKAkyBsZXZlbCArIHRyZW5kLCBubyBkYW1waW5nLiAgDQotICoqSG9sdCBhZGRpdGl2ZSB0cmVuZCB3aXRoIGRhbXBpbmcqKiDigJMgbGV2ZWwgKyB0cmVuZCwgd2hlcmUgdGhlIHRyZW5kIGlzIGdyYWR1YWxseSBkYW1wZWQgdG8gYXZvaWQgdW5yZWFsaXN0aWMgbG9uZy10ZXJtIGdyb3d0aC4NCg0KYGBge3IgaG9sdC1tb2RlbHN9DQojIEhvbHQgYWRkaXRpdmUgdHJlbmQgKG5vIGRhbXBpbmcpDQpmaXRfaG9sdCA8LSBob2x0KGFwX3RyYWluLnRzLCBpbml0aWFsID0gIm9wdGltYWwiLCBoID0gaF90ZXN0KQ0KDQojIEhvbHQgYWRkaXRpdmUgdHJlbmQgd2l0aCBkYW1waW5nDQpmaXRfaG9sdF9kYW1wZWQgPC0gaG9sdChhcF90cmFpbi50cywgaW5pdGlhbCA9ICJvcHRpbWFsIiwNCiAgICAgICAgICAgICAgICAgICAgICAgIGRhbXBlZCA9IFRSVUUsIGggPSBoX3Rlc3QpDQoNCmZpdF9ob2x0DQpmaXRfaG9sdF9kYW1wZWQNCg0KYWNjdXJhY3koZml0X2hvbHQpDQphY2N1cmFjeShmaXRfaG9sdF9kYW1wZWQpDQpgYGANCg0KKipJbnRlcnByZXRhdGlvbi4qKiAgDQpCb3RoIEhvbHQgbW9kZWxzIGNhcHR1cmUgdGhlICoqdXB3YXJkIHRyZW5kKiogYmV0dGVyIHRoYW4gU0VTLiBUaGUgZGFtcGVkIHZlcnNpb24gcHJvZHVjZXMgbW9yZSBjb25zZXJ2YXRpdmUgbG9uZy1ob3Jpem9uIGZvcmVjYXN0cywgd2hpY2ggaXMgb2Z0ZW4gZGVzaXJhYmxlIGZvciBzZXJpZXMgd2hlcmUgaW5kZWZpbml0ZSBleHBvbmVudGlhbCBncm93dGggaXMgdW5yZWFsaXN0aWMuDQoNCkhvd2V2ZXIsIG5laXRoZXIgbW9kZWwgaW5jbHVkZXMgYSBzZWFzb25hbCBjb21wb25lbnQsIHNvIHRoZXkgc3RpbGwgKipmYWlsIHRvIG1vZGVsIHRoZSBjeWNsaWNhbCBzZWFzb25hbCBwYXR0ZXJuKiogYXBwYXJlbnQgaW4gdGhlIGFpcmxpbmUgcGFzc2VuZ2VyIHNlcmllcy4gQXMgYSByZXN1bHQsIHRoZWlyIGFjY3VyYWN5IGltcHJvdmVzIG92ZXIgU0VTIGJ1dCByZW1haW5zIGluZmVyaW9yIHRvIG1vZGVscyB0aGF0IGluY29ycG9yYXRlIHNlYXNvbmFsaXR5Lg0KDQojIyAgSG9sdOKAk1dpbnRlcnMgU2Vhc29uYWwgTW9kZWxzDQoNCkdpdmVuIHRoZSBjbGVhciB0cmVuZCBhbmQgbXVsdGlwbGljYXRpdmUgc2Vhc29uYWxpdHksIEhvbHTigJNXaW50ZXJzIG1ldGhvZHMgYXJlIGEgbmF0dXJhbCBjaG9pY2UuIFdlIGZpdDoNCg0KLSAqKkhvbHTigJNXaW50ZXJzIGFkZGl0aXZlIHNlYXNvbmFsaXR5KiosICANCi0gKipIb2x04oCTV2ludGVycyBtdWx0aXBsaWNhdGl2ZSBzZWFzb25hbGl0eSoqLCAgDQotICoqQWRkaXRpdmUgSG9sdOKAk1dpbnRlcnMgd2l0aCBkYW1waW5nKiosICANCi0gKipNdWx0aXBsaWNhdGl2ZSBIb2x04oCTV2ludGVycyB3aXRoIGRhbXBpbmcqKi4NCg0KYGBge3IgaHctbW9kZWxzfQ0KIyBIb2x04oCTV2ludGVycyBhZGRpdGl2ZSBzZWFzb25hbGl0eQ0KZml0X2h3X2FkZCA8LSBodyhhcF90cmFpbi50cywgaCA9IGhfdGVzdCwgc2Vhc29uYWwgPSAiYWRkaXRpdmUiKQ0KDQojIEhvbHTigJNXaW50ZXJzIG11bHRpcGxpY2F0aXZlIHNlYXNvbmFsaXR5DQpmaXRfaHdfbXVsdCA8LSBodyhhcF90cmFpbi50cywgaCA9IGhfdGVzdCwgc2Vhc29uYWwgPSAibXVsdGlwbGljYXRpdmUiKQ0KDQojIEhvbHTigJNXaW50ZXJzIGFkZGl0aXZlIHdpdGggZGFtcGVkIHRyZW5kDQpmaXRfaHdfYWRkX2RhbXBlZCA8LSBodyhhcF90cmFpbi50cywgaCA9IGhfdGVzdCwNCiAgICAgICAgICAgICAgICAgICAgICAgIHNlYXNvbmFsID0gImFkZGl0aXZlIiwgZGFtcGVkID0gVFJVRSkNCg0KIyBIb2x04oCTV2ludGVycyBtdWx0aXBsaWNhdGl2ZSB3aXRoIGRhbXBlZCB0cmVuZA0KZml0X2h3X211bHRfZGFtcGVkIDwtIGh3KGFwX3RyYWluLnRzLCBoID0gaF90ZXN0LA0KICAgICAgICAgICAgICAgICAgICAgICAgIHNlYXNvbmFsID0gIm11bHRpcGxpY2F0aXZlIiwgZGFtcGVkID0gVFJVRSkNCg0KZml0X2h3X2FkZA0KZml0X2h3X211bHQNCg0KYWNjdXJhY3koZml0X2h3X2FkZCkNCmFjY3VyYWN5KGZpdF9od19tdWx0KQ0KYWNjdXJhY3koZml0X2h3X2FkZF9kYW1wZWQpDQphY2N1cmFjeShmaXRfaHdfbXVsdF9kYW1wZWQpDQpgYGANCg0KKipJbnRlcnByZXRhdGlvbi4qKiAgDQpUaGUgSG9sdOKAk1dpbnRlcnMgbW9kZWxzIGV4cGxpY2l0bHkgbW9kZWwgYm90aCAqKnRyZW5kIGFuZCBzZWFzb25hbGl0eSoqLiBJbiBwYXJ0aWN1bGFyOg0KDQotIEFkZGl0aXZlIEhvbHTigJNXaW50ZXJzIGFzc3VtZXMgKipjb25zdGFudCBzZWFzb25hbCBhbXBsaXR1ZGUqKiBvdmVyIHRpbWUuICANCi0gTXVsdGlwbGljYXRpdmUgSG9sdOKAk1dpbnRlcnMgYWxsb3dzICoqc2Vhc29uYWwgYW1wbGl0dWRlIHRvIGluY3JlYXNlIHdpdGggdGhlIHNlcmllcyBsZXZlbCoqLCBtYXRjaGluZyB0aGUgcGF0dGVybiB3ZSBvYnNlcnZlZCBpbiB0aGUgaW5pdGlhbCBwbG90Lg0KDQpBcyBleHBlY3RlZCwgdGhlIEhvbHTigJNXaW50ZXJzIG1vZGVscyBnZW5lcmFsbHkgYWNoaWV2ZSAqKmxvd2VyIFJNU0UgYW5kIE1BUEUqKiB0aGFuIFNFUyBvciBIb2x0IG1vZGVscywgd2l0aCBtdWx0aXBsaWNhdGl2ZSB2ZXJzaW9ucyB0eXBpY2FsbHkgcGVyZm9ybWluZyBiZXN0IGR1ZSB0byB0aGUgbXVsdGlwbGljYXRpdmUgc2Vhc29uYWwgcGF0dGVybiBpbiB0aGUgZGF0YS4NCg0KIyAgVHJhaW5pbmcgQWNjdXJhY3kgQ29tcGFyaXNvbg0KDQojIyAgVHJhaW5pbmcgQWNjdXJhY3kgVGFibGUNCg0KYGBge3IgdHJhaW4tYWNjdXJhY3l9DQphY2N1cmFjeV90YWJsZV90cmFpbiA8LSByb3VuZChyYmluZCgNCiAgU0VTICAgICAgICAgICAgICAgID0gYWNjdXJhY3koZml0X3NlcyksDQogIEhvbHRfQWRkaXRpdmUgICAgICA9IGFjY3VyYWN5KGZpdF9ob2x0KSwNCiAgSG9sdF9BZGRfRGFtcGVkICAgID0gYWNjdXJhY3koZml0X2hvbHRfZGFtcGVkKSwNCiAgSFdfQWRkaXRpdmUgICAgICAgID0gYWNjdXJhY3koZml0X2h3X2FkZCksDQogIEhXX011bHRpcGxpY2F0aXZlICA9IGFjY3VyYWN5KGZpdF9od19tdWx0KSwNCiAgSFdfQWRkX0RhbXBlZCAgICAgID0gYWNjdXJhY3koZml0X2h3X2FkZF9kYW1wZWQpLA0KICBIV19NdWx0X0RhbXBlZCAgICAgPSBhY2N1cmFjeShmaXRfaHdfbXVsdF9kYW1wZWQpDQopLCA0KQ0KDQprYWJsZShhY2N1cmFjeV90YWJsZV90cmFpbiwNCiAgICAgIGNhcHRpb24gPSAiVHJhaW5pbmcgQWNjdXJhY3kgTWVhc3VyZXMgZm9yIEV4cG9uZW50aWFsIFNtb290aGluZyBNb2RlbHMgKEFpcmxpbmUgUGFzc2VuZ2VycykiKQ0KYGBgDQoNCioqSW50ZXJwcmV0YXRpb24uKiogIA0KDQotICoqU0VTKiogaGFzIHRoZSBsYXJnZXN0IFJNU0UgYW5kIE1BUEUsIGNvbmZpcm1pbmcgdGhhdCBpZ25vcmluZyB0cmVuZCBhbmQgc2Vhc29uYWxpdHkgbGVhZHMgdG8gcG9vciBmaXQuICANCi0gKipIb2x0IGFkZGl0aXZlIGFuZCBkYW1wZWQqKiBtb2RlbHMgaW1wcm92ZSBhY2N1cmFjeSBieSBjYXB0dXJpbmcgdGhlICoqdXB3YXJkIHRyZW5kKiosIGJ1dCBzdGlsbCBtaXNzIHRoZSBzZWFzb25hbCBzdHJ1Y3R1cmUuICANCi0gKipIb2x04oCTV2ludGVycyBtb2RlbHMqKiAoZXNwZWNpYWxseSB0aGUgbXVsdGlwbGljYXRpdmUgdmVyc2lvbnMpIHByb3ZpZGUgdGhlICoqc21hbGxlc3QgdHJhaW5pbmcgZXJyb3JzKiosIHJlZmxlY3RpbmcgdGhlaXIgYWJpbGl0eSB0byBjYXB0dXJlIGJvdGggdHJlbmQgYW5kIG11bHRpcGxpY2F0aXZlIHNlYXNvbmFsaXR5LiAgDQotIEFtb25nIGFsbCBtb2RlbHMsIHRoZSAqKm11bHRpcGxpY2F0aXZlIEhvbHTigJNXaW50ZXJzIChvZnRlbiB3aXRoIGRhbXBpbmcpKiogZW1lcmdlcyBhcyB0aGUgYmVzdCBmaXR0aW5nIG1vZGVsIG9uIHRoZSB0cmFpbmluZyBkYXRhLg0KDQojICBGb3JlY2FzdCBFcnJvcnMgb24gdGhlIFRlc3QgU2V0DQoNCiMjICBSYXRpb25hbGUNCg0KVHJhaW5pbmcgYWNjdXJhY3kgYWxvbmUgY2FuIGJlIG1pc2xlYWRpbmcsIGVzcGVjaWFsbHkgZm9yIGZsZXhpYmxlIG1vZGVscyB0aGF0IG1pZ2h0IG92ZXJmaXQuIFRoZSByZWFsIHRlc3Qgb2YgYSBmb3JlY2FzdGluZyBtb2RlbCBpcyBob3cgd2VsbCBpdCBhbnRpY2lwYXRlcyB1bnNlZW4gZGF0YS4gSGVyZSwgd2UgY29tcGFyZSBmb3JlY2FzdHMgYWdhaW5zdCB0aGUgKipoZWxkLW91dCAxOTYwIGRhdGEqKi4NCg0KIyMgIFRlc3QgU2V0IEFjY3VyYWN5DQoNCmBgYHtyIHRlc3QtYWNjdXJhY3l9DQphY2NfZnVuIDwtIGZ1bmN0aW9uKHRlc3RfZGF0YSwgbW9kZWxfb2JqZWN0KSB7DQogIGZjX21lYW4gPC0gYXMubnVtZXJpYyhtb2RlbF9vYmplY3QkbWVhbikNCiAgUEUgICAgICA8LSAodGVzdF9kYXRhIC0gZmNfbWVhbikgLyBmY19tZWFuDQogIE1BUEUgICAgPC0gbWVhbihhYnMoUEUpKQ0KICBFICAgICAgIDwtIHRlc3RfZGF0YSAtIGZjX21lYW4NCiAgTVNFICAgICA8LSBtZWFuKEVeMikNCiAgYyhNU0UgPSBNU0UsIE1BUEUgPSBNQVBFKQ0KfQ0KDQp0ZXN0X2FjY3VyYWN5IDwtIHJiaW5kKA0KICBTRVMgICAgICAgICAgICAgICA9IGFjY19mdW4odGVzdF9kYXRhLCBmaXRfc2VzKSwNCiAgSG9sdF9BZGRpdGl2ZSAgICAgPSBhY2NfZnVuKHRlc3RfZGF0YSwgZml0X2hvbHQpLA0KICBIb2x0X0FkZF9EYW1wZWQgICA9IGFjY19mdW4odGVzdF9kYXRhLCBmaXRfaG9sdF9kYW1wZWQpLA0KICBIV19BZGRpdGl2ZSAgICAgICA9IGFjY19mdW4odGVzdF9kYXRhLCBmaXRfaHdfYWRkKSwNCiAgSFdfTXVsdGlwbGljYXRpdmUgPSBhY2NfZnVuKHRlc3RfZGF0YSwgZml0X2h3X211bHQpLA0KICBIV19BZGRfRGFtcGVkICAgICA9IGFjY19mdW4odGVzdF9kYXRhLCBmaXRfaHdfYWRkX2RhbXBlZCksDQogIEhXX011bHRfRGFtcGVkICAgID0gYWNjX2Z1bih0ZXN0X2RhdGEsIGZpdF9od19tdWx0X2RhbXBlZCkNCikNCg0KdGVzdF9hY2N1cmFjeSA8LSByb3VuZCh0ZXN0X2FjY3VyYWN5LCA0KQ0KDQprYWJsZSh0ZXN0X2FjY3VyYWN5LA0KICAgICAgY2FwdGlvbiA9ICJGb3JlY2FzdCBFcnJvciAoTVNFIGFuZCBNQVBFKSBvbiB0aGUgMTItTW9udGggVGVzdCBTZXQgKDE5NjApIikNCmBgYA0KDQoqKkludGVycHJldGF0aW9uLioqICANCg0KLSBUaGUgKipTRVMqKiBhbmQgKipIb2x0KiogbW9kZWxzIHNob3cgbGFyZ2UgTVNFIGFuZCBNQVBFIG9uIHRoZSB0ZXN0IHNldCwgY29uZmlybWluZyB0aGF0IG1vZGVscyB3aXRob3V0IHNlYXNvbmFsaXR5IGdlbmVyYWxpemUgcG9vcmx5IGZvciB0aGlzIHNlcmllcy4gIA0KLSBUaGUgKiphZGRpdGl2ZSBIb2x04oCTV2ludGVycyoqIG1vZGVsIGltcHJvdmVzIG91dC1vZi1zYW1wbGUgcGVyZm9ybWFuY2UgYnV0IHN0aWxsIHN0cnVnZ2xlcyB0byBtYXRjaCB0aGUgaW5jcmVhc2luZyBzZWFzb25hbCBhbXBsaXR1ZGUuICANCi0gVGhlICoqbXVsdGlwbGljYXRpdmUgSG9sdOKAk1dpbnRlcnMgbW9kZWwqKiBhY2hpZXZlcyB0aGUgKipsb3dlc3QgTVNFIGFuZCBNQVBFKiogb24gdGhlIDE5NjAgdGVzdCB5ZWFyLCBpbmRpY2F0aW5nIHRoYXQgaXQgYmVzdCBjYXB0dXJlcyB0aGUgdHJ1ZSB1bmRlcmx5aW5nIHBhdHRlcm4gb2YgdGhlIGRhdGEuICANCi0gVGhpcyBvdXQtb2Ytc2FtcGxlIHJlc3VsdCByZWluZm9yY2VzIHRoZSBjb25jbHVzaW9uIGZyb20gdGhlIHRyYWluaW5nIGFjY3VyYWN5IGNvbXBhcmlzb246ICoqbW9kZWxpbmcgYm90aCB0cmVuZCBhbmQgbXVsdGlwbGljYXRpdmUgc2Vhc29uYWxpdHkgaXMgY3J1Y2lhbCoqIGZvciByZWxpYWJsZSBmb3JlY2FzdGluZyBvZiBhaXJsaW5lIHBhc3NlbmdlcnMuDQoNCiMgIFBsb3RzIG9mIEhpc3RvcmljYWwgRGF0YSBhbmQgRm9yZWNhc3RzDQoNCiMjICBSYXRpb25hbGUNCg0KVGFibGVzIG9mIGFjY3VyYWN5IGdpdmUgbnVtZXJpYyBzdW1tYXJpZXMsIGJ1dCBwbG90cyBvZiB0aGUgZml0dGVkIHZhbHVlcyBhbmQgZm9yZWNhc3RzIHByb3ZpZGUgY3J1Y2lhbCAqKnZpc3VhbCBjb25maXJtYXRpb24qKiBvZiBob3cgZWFjaCBtb2RlbCBiZWhhdmVzLCBlc3BlY2lhbGx5IHJlZ2FyZGluZyB0cmVuZCBhbmQgc2Vhc29uYWxpdHkuIFdlIGZpcnN0IGNvbXBhcmUgbm9uLXNlYXNvbmFsIG1vZGVscyBhbmQgdGhlbiBjb21wYXJlIEhvbHTigJNXaW50ZXJzIHNlYXNvbmFsIG1vZGVscy4NCg0KIyMgIE5vbi1TZWFzb25hbCBTbW9vdGhpbmcgTW9kZWxzIChTRVMgYW5kIEhvbHQpDQoNCmBgYHtyIG5vbnNlYXNvbmFsLXBsb3RzfQ0KcGFyKG1mcm93ID0gYygyLCAxKSwgbWFyID0gYygzLCA0LCAzLCAxKSkNCg0KIyBUaW1lIGluZGV4IGZvciB0cmFpbmluZyBhbmQgZm9yZWNhc3QNCnRpbWVfdHJhaW4gPC0gdGltZShhcF90cmFpbi50cykNCnRpbWVfZnVsbCAgPC0gdGltZShhcC50cykNCnByZWRfaW5kZXggPC0gKGxlbmd0aCh0cmFpbl9kYXRhKSArIDEpOmxlbmd0aChhcF9hbGwpDQoNCnBsb3QoDQogIHRpbWVfdHJhaW4sIHRyYWluX2RhdGEsDQogIHR5cGUgPSAibyIsDQogIHlsYWIgPSAiUGFzc2VuZ2VycyIsDQogIHhsYWIgPSAiIiwNCiAgeGxpbSA9IHJhbmdlKHRpbWVfZnVsbCksDQogIG1haW4gPSAiTm9uLVNlYXNvbmFsIFNtb290aGluZyBNb2RlbHMgKFRyYWluaW5nICsgMTItTW9udGggRm9yZWNhc3QpIiwNCiAgY29sICA9ICJibGFjayIsDQogIGNleCAgPSAwLjUNCikNCg0KbGluZXModGltZV9mdWxsW3ByZWRfaW5kZXhdLCBhcy5udW1lcmljKGZpdF9zZXMkbWVhbiksIGNvbCA9ICJyZWQiKQ0KbGluZXModGltZV9mdWxsW3ByZWRfaW5kZXhdLCBhcy5udW1lcmljKGZpdF9ob2x0JG1lYW4pLCBjb2wgPSAiYmx1ZSIpDQpsaW5lcyh0aW1lX2Z1bGxbcHJlZF9pbmRleF0sIGFzLm51bWVyaWMoZml0X2hvbHRfZGFtcGVkJG1lYW4pLCBjb2wgPSAicHVycGxlIikNCg0KcG9pbnRzKHRpbWVfZnVsbFtwcmVkX2luZGV4XSwgYXMubnVtZXJpYyhmaXRfc2VzJG1lYW4pLCBwY2ggPSAxNiwgY29sID0gInJlZCIsIGNleCA9IDAuNikNCnBvaW50cyh0aW1lX2Z1bGxbcHJlZF9pbmRleF0sIGFzLm51bWVyaWMoZml0X2hvbHQkbWVhbiksIHBjaCA9IDE3LCBjb2wgPSAiYmx1ZSIsIGNleCA9IDAuNikNCnBvaW50cyh0aW1lX2Z1bGxbcHJlZF9pbmRleF0sIGFzLm51bWVyaWMoZml0X2hvbHRfZGFtcGVkJG1lYW4pLCBwY2ggPSAxOSwgY29sID0gInB1cnBsZSIsIGNleCA9IDAuNikNCg0KbGVnZW5kKA0KICAidG9wbGVmdCIsDQogIGx0eSA9IDEsDQogIGNvbCA9IGMoInJlZCIsICJibHVlIiwgInB1cnBsZSIpLA0KICBwY2ggPSBjKDE2LCAxNywgMTkpLA0KICBsZWdlbmQgPSBjKCJTRVMiLCAiSG9sdCBBZGRpdGl2ZSIsICJIb2x0IEFkZGl0aXZlIERhbXBlZCIpLA0KICBjZXggPSAwLjgsDQogIGJ0eSA9ICJuIg0KKQ0KYGBgDQoNCioqSW50ZXJwcmV0YXRpb24uKiogIA0KVGhlIG5vbi1zZWFzb25hbCBtb2RlbHMgdHJhY2sgdGhlICoqb3ZlcmFsbCB1cHdhcmQgdHJlbmQqKiBidXQgZmFpbCB0byBtaW1pYyB0aGUgKipzZWFzb25hbCBwZWFrcyBhbmQgdHJvdWdocyoqLiBUaGVpciBmb3JlY2FzdHMgZm9yIDE5NjAgYXJlIHJvdWdobHkgaW5jcmVhc2luZyBsaW5lcyB3aXRob3V0IHRoZSBjaGFyYWN0ZXJpc3RpYyBzZWFzb25hbCBzcGlrZXMsIHdoaWNoIHZpc3VhbGx5IGV4cGxhaW5zIHRoZWlyIHBvb3JlciB0ZXN0LXNldCBhY2N1cmFjeS4gVGhpcyBjb25maXJtcyB0aGF0ICoqaWdub3Jpbmcgc2Vhc29uYWxpdHkgaXMgaW5hcHByb3ByaWF0ZSoqIGZvciB0aGlzIHNlcmllcy4NCg0KIyMgIEhvbHTigJNXaW50ZXJzIFNlYXNvbmFsIE1vZGVscw0KDQpgYGB7ciBzZWFzb25hbC1wbG90c30NCnBsb3QoDQogIHRpbWVfdHJhaW4sIHRyYWluX2RhdGEsDQogIHR5cGUgPSAibyIsDQogIHlsYWIgPSAiUGFzc2VuZ2VycyIsDQogIHhsYWIgPSAiIiwNCiAgeGxpbSA9IHJhbmdlKHRpbWVfZnVsbCksDQogIG1haW4gPSAiSG9sdOKAk1dpbnRlcnMgVHJlbmQgYW5kIFNlYXNvbmFsIFNtb290aGluZyBNb2RlbHMiLA0KICBjb2wgID0gImJsYWNrIiwNCiAgY2V4ICA9IDAuNQ0KKQ0KDQpsaW5lcyh0aW1lX2Z1bGxbcHJlZF9pbmRleF0sIGFzLm51bWVyaWMoZml0X2h3X2FkZCRtZWFuKSwgY29sID0gInJlZCIpDQpsaW5lcyh0aW1lX2Z1bGxbcHJlZF9pbmRleF0sIGFzLm51bWVyaWMoZml0X2h3X211bHQkbWVhbiksIGNvbCA9ICJibHVlIikNCmxpbmVzKHRpbWVfZnVsbFtwcmVkX2luZGV4XSwgYXMubnVtZXJpYyhmaXRfaHdfYWRkX2RhbXBlZCRtZWFuKSwgY29sID0gInB1cnBsZSIpDQpsaW5lcyh0aW1lX2Z1bGxbcHJlZF9pbmRleF0sIGFzLm51bWVyaWMoZml0X2h3X211bHRfZGFtcGVkJG1lYW4pLCBjb2wgPSAibmF2eSIpDQoNCnBvaW50cyh0aW1lX2Z1bGxbcHJlZF9pbmRleF0sIGFzLm51bWVyaWMoZml0X2h3X2FkZCRtZWFuKSwgcGNoID0gMTYsIGNvbCA9ICJyZWQiLCBjZXggPSAwLjYpDQpwb2ludHModGltZV9mdWxsW3ByZWRfaW5kZXhdLCBhcy5udW1lcmljKGZpdF9od19tdWx0JG1lYW4pLCBwY2ggPSAxNywgY29sID0gImJsdWUiLCBjZXggPSAwLjYpDQpwb2ludHModGltZV9mdWxsW3ByZWRfaW5kZXhdLCBhcy5udW1lcmljKGZpdF9od19hZGRfZGFtcGVkJG1lYW4pLCBwY2ggPSAxOSwgY29sID0gInB1cnBsZSIsIGNleCA9IDAuNikNCnBvaW50cyh0aW1lX2Z1bGxbcHJlZF9pbmRleF0sIGFzLm51bWVyaWMoZml0X2h3X211bHRfZGFtcGVkJG1lYW4pLCBwY2ggPSAyMSwgY29sID0gIm5hdnkiLCBjZXggPSAwLjYpDQoNCmxlZ2VuZCgNCiAgInRvcGxlZnQiLA0KICBsdHkgPSAxLA0KICBjb2wgPSBjKCJyZWQiLCAiYmx1ZSIsICJwdXJwbGUiLCAibmF2eSIpLA0KICBwY2ggPSBjKDE2LCAxNywgMTksIDIxKSwNCiAgbGVnZW5kID0gYygiSFcgQWRkaXRpdmUiLCAiSFcgTXVsdGlwbGljYXRpdmUiLA0KICAgICAgICAgICAgICJIVyBBZGRpdGl2ZSBEYW1wZWQiLCAiSFcgTXVsdGlwbGljYXRpdmUgRGFtcGVkIiksDQogIGNleCA9IDAuOCwNCiAgYnR5ID0gIm4iDQopDQoNCnBhcihtZnJvdyA9IGMoMSwgMSkpDQpgYGANCg0KKipJbnRlcnByZXRhdGlvbi4qKiAgDQpUaGUgSG9sdOKAk1dpbnRlcnMgc2Vhc29uYWwgbW9kZWxzIHByb2R1Y2UgZm9yZWNhc3RzIHRoYXQgY2xvc2VseSByZXNlbWJsZSB0aGUgKipoaXN0b3JpY2FsIHNlYXNvbmFsIHBhdHRlcm4qKi4gSW4gcGFydGljdWxhcjoNCg0KLSBUaGUgKiptdWx0aXBsaWNhdGl2ZSBIb2x04oCTV2ludGVycyoqIGZvcmVjYXN0cyBzaG93IHNlYXNvbmFsIHBlYWtzIHRoYXQgKipncm93IHdpdGggdGhlIGxldmVsKiosIG1pcnJvcmluZyB0aGUgYmVoYXZpb3Igc2VlbiBpbiBwYXN0IHllYXJzLiAgDQotIEFkZGl0aXZlIEhvbHTigJNXaW50ZXJzIGZvcmVjYXN0cyBzaG93IGNvbnN0YW50IHNlYXNvbmFsIGFtcGxpdHVkZSwgd2hpY2ggdW5kZXJlc3RpbWF0ZXMgdGhlIG1hZ25pdHVkZSBvZiBwZWFrcyBpbiBsYXRlciB5ZWFycy4gIA0KLSBWaXN1YWxseSwgdGhlIG11bHRpcGxpY2F0aXZlIEhvbHTigJNXaW50ZXJzIHNlcmllcyBmb2xsb3dzIGJvdGggdGhlIHRyZW5kIGFuZCB0aGUgZ3Jvd2luZyBzZWFzb25hbCBwYXR0ZXJuIG1vc3QgYWNjdXJhdGVseSwgd2hpY2ggc3VwcG9ydHMgaXRzIHN1cGVyaW9yIHRyYWluaW5nIGFuZCB0ZXN0LXNldCBwZXJmb3JtYW5jZS4NCg0KIyAgRGlzY3Vzc2lvbiBhbmQgQ29uY2x1c2lvbnMNCg0KIyMgIE92ZXJ2aWV3DQoNCkluIHRoaXMgc2VjdGlvbiwgd2Ugc3ludGhlc2l6ZSB0aGUgbW9kZWxpbmcgcmVzdWx0cyBhbmQgZHJhdyBjb25jbHVzaW9ucyBhYm91dCB3aGljaCBleHBvbmVudGlhbCBzbW9vdGhpbmcgbWV0aG9kIGJlc3QgY2FwdHVyZXMgdGhlIHN0cnVjdHVyZSBvZiB0aGUgYWlybGluZSBwYXNzZW5nZXIgc2VyaWVzLCBhbmQgd2h5Lg0KDQojIyAgQmVoYXZpb3Igb2YgdGhlIEFpcmxpbmUgUGFzc2VuZ2VyIFNlcmllcw0KDQpUaGUgYEFpclBhc3NlbmdlcnNgIHNlcmllcyBkaXNwbGF5czoNCg0KLSBBICoqc3Ryb25nIHVwd2FyZCB0cmVuZCoqIGluIGF2ZXJhZ2UgcGFzc2VuZ2VyIGNvdW50cyBvdmVyIHRpbWUsIGFuZCAgDQotICoqTXVsdGlwbGljYXRpdmUgc2Vhc29uYWxpdHkqKiwgd2hlcmUgdGhlIGFtcGxpdHVkZSBvZiB0aGUgc2Vhc29uYWwgY3ljbGUgZ3Jvd3Mgd2l0aCB0aGUgc2VyaWVzIGxldmVsLg0KDQpUaGVzZSBmZWF0dXJlcyBzdWdnZXN0IHRoYXQgbW9kZWxzIHdoaWNoIGV4cGxpY2l0bHkgaW5jb3Jwb3JhdGUgKipib3RoIHRyZW5kIGFuZCBtdWx0aXBsaWNhdGl2ZSBzZWFzb25hbGl0eSoqIHNob3VsZCBwZXJmb3JtIGJlc3QuDQoNCiMjICBNb2RlbCBDb21wYXJpc29uDQoNCkZyb20gYm90aCB0cmFpbmluZyBhY2N1cmFjeSBhbmQgZm9yZWNhc3QgcGxvdHM6DQoNCi0gKipTRVMqKiBwZXJmb3JtcyB3b3JzdCwgYXMgZXhwZWN0ZWQsIGJlY2F1c2UgaXQgbW9kZWxzIG9ubHkgYSBzaW5nbGUgbGV2ZWwgYW5kIGlnbm9yZXMgYm90aCB0cmVuZCBhbmQgc2Vhc29uYWxpdHkuICANCi0gKipIb2x0IGFkZGl0aXZlIGFuZCBkYW1wZWQgbW9kZWxzKiogaW1wcm92ZSBvbiBTRVMgYnkgbW9kZWxpbmcgdHJlbmQgYnV0IHN0aWxsIG1pc3MgdGhlIHNlYXNvbmFsIHBhdHRlcm4sIGxlYWRpbmcgdG8gc3lzdGVtYXRpYyB1bmRlci0gb3Igb3Zlci1wcmVkaWN0aW9uIGF0IHNlYXNvbmFsIHBlYWtzIGFuZCB0cm91Z2hzLiAgDQotICoqSG9sdOKAk1dpbnRlcnMgbW9kZWxzKiogdGhhdCBpbmNsdWRlIHNlYXNvbmFsaXR5IHNob3cgbWFqb3IgaW1wcm92ZW1lbnRzIGluIGZpdCBhbmQgZm9yZWNhc3QgYmVoYXZpb3IuICANCi0gQW1vbmcgdGhlc2UsIHRoZSAqKm11bHRpcGxpY2F0aXZlIEhvbHTigJNXaW50ZXJzIG1vZGVsKiogYWxpZ25zIGJlc3Qgd2l0aCB0aGUgb2JzZXJ2ZWQgbXVsdGlwbGljYXRpdmUgc2Vhc29uYWwgcGF0dGVybiBhbmQgYWNoaWV2ZXMgdGhlIGxvd2VzdCBlcnJvciBtZXRyaWNzLg0KDQpUaGUgbXVsdGlwbGljYXRpdmUgZGFtcGVkIHZlcnNpb24gaXMgYSByZWFzb25hYmxlIGFsdGVybmF0aXZlIGlmIHdlIHdpc2ggdG8gdGVtcGVyIGxvbmctdGVybSBncm93dGgsIGJ1dCB3aXRoaW4gdGhlIDEyLW1vbnRoIGZvcmVjYXN0IGhvcml6b24sIHRoZSB1bmRhbXBlZCBtdWx0aXBsaWNhdGl2ZSBtb2RlbCBhbHJlYWR5IHBlcmZvcm1zIGV4Y2VwdGlvbmFsbHkgd2VsbC4NCg0KIyMgIEZvcmVjYXN0IEFjY3VyYWN5IG9uIHRoZSBUZXN0IFNldA0KDQpUaGUgMTItbW9udGggaG9sZG91dCBldmFsdWF0aW9uIGNvbmZpcm1zOg0KDQotICoqU0VTKiogYW5kICoqSG9sdCoqIG1vZGVscyBoYXZlIGxhcmdlIE1TRSBhbmQgTUFQRSBvbiAxOTYwLCBpbmRpY2F0aW5nIHRoYXQgaWdub3Jpbmcgc2Vhc29uYWxpdHkgaGFybXMgZ2VuZXJhbGl6YXRpb24uICANCi0gKipBZGRpdGl2ZSBIb2x04oCTV2ludGVycyoqIGltcHJvdmVzIG91dC1vZi1zYW1wbGUgcGVyZm9ybWFuY2UgYnV0IHN0aWxsIGZhaWxzIHRvIGZ1bGx5IGNhcHR1cmUgdGhlIGluY3JlYXNpbmcgc2Vhc29uYWwgYW1wbGl0dWRlLiAgDQotIFRoZSAqKm11bHRpcGxpY2F0aXZlIEhvbHTigJNXaW50ZXJzIG1vZGVsKiogYWNoaWV2ZXMgdGhlICoqc21hbGxlc3QgdGVzdCBNU0UgYW5kIE1BUEUqKiwgbWFraW5nIGl0IHRoZSBiZXN0IHByZWRpY3RvciBvZiB0aGUgMTk2MCBwYXNzZW5nZXIgY291bnRzLg0KDQpUaGVzZSBmb3JlY2FzdCByZXN1bHRzIGFyZSBjb25zaXN0ZW50IHdpdGggdGhlIGJlaGF2aW9yIHNlZW4gaW4gdGhlIHByZWRpY3Rpb24gcGxvdHM6IG9ubHkgdGhlIG11bHRpcGxpY2F0aXZlIEhvbHTigJNXaW50ZXJzIG1vZGVsIHJlbGlhYmx5IHRyYWNrcyBib3RoIHRoZSBsZXZlbCBhbmQgc2Vhc29uYWwgcGF0dGVybiBvZiB0aGUgc2VyaWVzLg0KDQojIyAgRmluYWwgQ29uY2x1c2lvbnMNCg0KQWNyb3NzIGJvdGggdHJhaW5pbmcgYW5kIHRlc3Qgc2V0cywgdGhlICoqSG9sdOKAk1dpbnRlcnMgbXVsdGlwbGljYXRpdmUgbW9kZWwqKiBpcyB0aGUgcHJlZmVycmVkIGZvcmVjYXN0aW5nIG1ldGhvZCBmb3IgdGhlIGFpcmxpbmUgcGFzc2VuZ2VyIHNlcmllcy4gSXQgc3VjY2Vzc2Z1bGx5Og0KDQotIENhcHR1cmVzIHRoZSAqKnVwd2FyZCB0cmVuZCoqLCAgDQotIE1vZGVscyAqKm11bHRpcGxpY2F0aXZlIHNlYXNvbmFsaXR5KiosIGFuZCAgDQotIFByb2R1Y2VzIHRoZSAqKm1vc3QgYWNjdXJhdGUgZm9yZWNhc3RzKiogZm9yIHRoZSAxMi1tb250aCBob2xkb3V0IHBlcmlvZC4NCg0KVGhlc2UgY29uY2x1c2lvbnMgYXJlIGZ1bGx5IGNvbnNpc3RlbnQgd2l0aCB0aGUgdmlzdWFsIHN0cnVjdHVyZSBvZiB0aGUgZGF0YS4gT3ZlcmFsbCwgdGhpcyBhbmFseXNpcyBkZW1vbnN0cmF0ZXMgdGhhdCBmb3Igc2VyaWVzIHdpdGggc3Ryb25nIHRyZW5kIGFuZCBsZXZlbC1kZXBlbmRlbnQgc2Vhc29uYWxpdHksICoqZXhwb25lbnRpYWwgc21vb3RoaW5nIG1vZGVscyBtdXN0IGluY29ycG9yYXRlIGJvdGggdHJlbmQgYW5kIG11bHRpcGxpY2F0aXZlIHNlYXNvbmFsIGNvbXBvbmVudHMqKiBpbiBvcmRlciB0byBwcm92aWRlIHJlbGlhYmxlIGZvcmVjYXN0cy4NCg0KDQo=