1 Introduction

The goal of this project is to use exponential smoothing methods to forecast the monthly totals of international airline passengers using the classic AirPassengers time series. The series spans more than 100 observations and exhibits both strong trend and clear seasonality, making it an ideal example for comparing different exponential smoothing models.

We address three main questions:

  1. How should we model the trend and seasonality in the airline passenger series?
  2. Among simple exponential smoothing (SES), Holt’s trend methods, and Holt–Winters seasonal methods, which model best fits the training data?
  3. Which model produces the most accurate forecasts on a 12-month hold-out test set?

Our approach is to:

  • Split the series into training (1949–1959) and test (1960) portions,
  • Fit SES, Holt, and Holt–Winters models (with and without damping, additive vs multiplicative seasonality),
  • Compare in-sample accuracy and out-of-sample forecast errors, and
  • Select a final model that respects the clearly multiplicative seasonal pattern seen in the data.

2 Data Description

2.1 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

2.2 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)

2.3 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.

3 Time Series Definition and Initial Plot

3.1 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.

3.2 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.

4 Train–Test Split

4.1 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.

4.2 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.

5 Exponential Smoothing Models

5.1 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.

5.2 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.

5.3 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.

5.4 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.

6 Training Accuracy Comparison

6.1 Training Accuracy Table

accuracy_table_train <- round(rbind(
  SES                = accuracy(fit_ses),
  Holt_Additive      = accuracy(fit_holt),
  Holt_Add_Damped    = accuracy(fit_holt_damped),
  HW_Additive        = accuracy(fit_hw_add),
  HW_Multiplicative  = accuracy(fit_hw_mult),
  HW_Add_Damped      = accuracy(fit_hw_add_damped),
  HW_Mult_Damped     = accuracy(fit_hw_mult_damped)
), 4)

kable(accuracy_table_train,
      caption = "Training Accuracy Measures for Exponential Smoothing Models (Airline Passengers)")
Training Accuracy Measures for Exponential Smoothing Models (Airline Passengers)
ME RMSE MAE MPE MAPE MASE ACF1
Training set 2.2198 31.2141 23.9023 0.4136 8.9118 0.7850 0.2863
Training set 0.0690 31.1517 23.8295 -0.5842 8.9654 0.7826 0.2861
Training set 1.4895 31.1885 23.9315 -0.0254 8.9690 0.7859 0.2860
Training set 0.7468 15.4108 11.5720 0.2590 5.0023 0.3800 0.1636
Training set 1.3694 9.9499 7.5333 0.2993 2.9978 0.2474 0.3048
Training set 1.6383 15.5079 11.6708 0.6132 5.0631 0.3833 0.1705
Training set 1.4315 8.4823 6.7641 0.4725 2.8575 0.2221 -0.0371

Interpretation.

  • SES has the largest RMSE and MAPE, confirming that ignoring trend and seasonality leads to poor fit.
  • Holt additive and damped models improve accuracy by capturing the upward trend, but still miss the seasonal structure.
  • Holt–Winters models (especially the multiplicative versions) provide the smallest training errors, reflecting their ability to capture both trend and multiplicative seasonality.
  • Among all models, the multiplicative Holt–Winters (often with damping) emerges as the best fitting model on the training data.

7 Forecast Errors on the Test Set

7.1 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.

7.2 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)
MSE MAPE
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.

8 Plots of Historical Data and Forecasts

8.1 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.

8.2 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.

8.3 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.

9 Discussion and Conclusions

9.1 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.

9.2 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.

9.3 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.

9.4 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.

9.5 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=