Libraries

library(tidyverse)
library(forecast)
library(gridExtra)
library(fastDummies)
library(Metrics)
library(BETS)
library(lmtest)

Dataset

df_raw <- read_csv("search.csv")
head(df_raw)
# define calendar variation variable
idul_adha_months <- c(
  "2004-02","2005-01","2006-01","2007-12","2008-12","2009-11",
  "2010-11","2011-11","2012-10","2013-10","2014-10","2015-09",
  "2016-09","2017-09","2018-08","2019-08","2020-07","2021-07",
  "2022-07","2023-06","2024-06", "2025-06"
)
df_raw$idul_adha <- as.integer(df_raw$Month %in% idul_adha_months)
df_raw
df_raw %>% filter(idul_adha==1)
df <- df_raw %>%
        mutate(ts = ym(Month), search = Search, 
               month = month(ts), year = year(ts),
               t = seq_along(ts)) %>%
        dummy_cols(select_columns = "month") %>%
        select(ts, t, idul_adha, year, month, starts_with("month_"), search) 
df
ggplot(data = df) +
  geom_line(aes(x = ts, y = search)) +
  ggtitle("Search Volume Index for keyword sapi") +
  xlab("") + ylab("") +
  scale_x_datetime(date_breaks = "2 year", date_labels = "%Y") 

train <- df %>% filter(year != 2025)
test  <- df %>% filter(year == 2025)
y_train <- ts(train$search, start = c(2004, 1), frequency = 12)
y_test  <- ts(test$search, start = c(2025, 1), frequency = 12)

Modelling

Deterministic Trend & Seasonality (Dummy)

Y_t = \underbrace{\beta_0 + \beta_1 t}_{\text{deterministic trend}} + \underbrace{\sum_{i=1}^{s-1} \delta_i S_{i,t} + \delta_{s,t}}_{\text{deterministic seasonal with dummy variable}} + \underbrace{\alpha_1 V_t}_{\text{calendar variation effect}} + \underbrace{\frac{\theta_q(B)}{\phi_p(B)} a_t}_{\text{ARIMA error}}

xreg_train <- cbind(
  trend = seq_along(y_train),
  seasonal = train %>% select(starts_with("month_")) %>% select(-month_12),                  
  idul_adha  = train$idul_adha
) %>% as.matrix()
m1 <- auto.arima(y_train, xreg = xreg_train, seasonal = FALSE)
summary(m1)
Series: y_train 
Regression with ARIMA(3,0,2) errors 

Coefficients:
         ar1     ar2     ar3      ma1      ma2  intercept   trend  seasonal.month_1  seasonal.month_2  seasonal.month_3
      0.5669  0.3314  0.0616  -0.5636  -0.2336     8.7419  0.0741           -0.7479            0.6210            3.3676
s.e.  1.8309  1.5796  0.2083   1.8370   1.5587     4.1196  0.0265            2.3072            2.2057            2.1904
      seasonal.month_4  seasonal.month_5  seasonal.month_6  seasonal.month_7  seasonal.month_8  seasonal.month_9  seasonal.month_10
                3.7441            5.2152            4.1848            6.1902            8.2195            6.7434             3.4633
s.e.            2.2121            2.2085            2.2025            2.2008            2.2021            2.1795             2.2004
      seasonal.month_11  idul_adha
                 0.5648    30.7546
s.e.             2.3110     1.7911

sigma^2 = 60.24:  log likelihood = -864.45
AIC=1768.89   AICc=1772.53   BIC=1839.48

Training set error measures:
                     ME    RMSE      MAE       MPE     MAPE     MASE        ACF1
Training set 0.02499097 7.46309 4.977715 -3.971377 21.10869 1.037024 0.001747125
predict_train <- train %>% 
  mutate(actual = search, 
         m1_predict = m1$fitted) 
predict_train

Deterministic Trend & Seasonality (Fourier)

Y_t = \underbrace{\beta_0 + \beta_1 t}_{\text{deterministic trend}} + \underbrace{\left[ \sum_{k=1}^{K} \left(a_k \sin\left(\frac{2\pi k t}{s}\right) + b_k \cos\left(\frac{2\pi k t}{s}\right)\right) \right]}_{\text{deterministic seasonal with Fourier terms}} + \underbrace{\alpha_1 V_t }_{\text{calendar variation}} + \underbrace{\frac{\theta_q(B)}{\phi_p(B)} a_t}_{\text{ARIMA error}}

xreg_train2 <- cbind(
  trend = seq_along(y_train),
  seasonal = fourier(y_train, K = 5),                  
  idul_adha  = train$idul_adha
) %>% as.matrix()
m2 <- auto.arima(y_train, xreg = xreg_train2, seasonal = FALSE)
summary(m2)
Series: y_train 
Regression with ARIMA(3,0,2) errors 

Coefficients:
         ar1     ar2     ar3      ma1      ma2  intercept   trend    S1-12    C1-12   S2-12    C2-12   S3-12   C3-12    S4-12   C4-12
      0.5702  0.3283  0.0615  -0.5671  -0.2307    12.2098  0.0741  -1.8092  -3.0268  0.1869  -1.3899  0.1815  0.6159  -0.2845  0.1101
s.e.  1.8185  1.5678  0.2081   1.8245   1.5479     3.8051  0.0265   0.5928   0.5797  0.5901   0.5903  0.6338  0.6343   0.6776  0.6770
       S5-12   C5-12  idul_adha
      0.3030  0.3186    30.7610
s.e.  0.6891  0.6890     1.7908

sigma^2 = 59.99:  log likelihood = -864.46
AIC=1766.93   AICc=1770.2   BIC=1833.99

Training set error measures:
                    ME     RMSE      MAE       MPE     MAPE     MASE        ACF1
Training set 0.0249246 7.463611 4.970092 -3.973825 21.07118 1.035436 0.001765115

Stochastic Trend & Deterministic Seasonality (Dummy)

Y_t = \beta_0 + \underbrace{\sum_{i=1}^{s-1} \delta_i S_{i,t} + \delta_{s,t}}_{\text{deterministic seasonal with dummy}} + \underbrace{\alpha_1 V_t}_{\text{calendar variation effect}} + \underbrace{\frac{\theta_q(B)}{\phi_p(B)(1-B)^d} a_t}_{\text{ARIMA error}}

xreg_train3 <- cbind(
  seasonal = train %>% select(starts_with("month_")) %>% select(-month_12),           
  idul_adha  = train$idul_adha
) %>% as.matrix()
m3 <- auto.arima(y_train, xreg = xreg_train3, seasonal = FALSE)
summary(m3)
Series: y_train 
Regression with ARIMA(2,1,2) errors 

Coefficients:
          ar1      ar2      ma1      ma2  seasonal.month_1  seasonal.month_2  seasonal.month_3  seasonal.month_4  seasonal.month_5
      -0.2974  -0.0536  -0.6848  -0.1423           -0.8380            0.5437            3.2965            3.6771            5.1538
s.e.   1.8398   0.2262   1.8444   1.5830            2.3062            2.2058            2.1877            2.2055            2.2045
      seasonal.month_6  seasonal.month_7  seasonal.month_8  seasonal.month_9  seasonal.month_10  seasonal.month_11  idul_adha
                4.1285            6.1401            8.1773            6.7114             3.4351             0.5506    30.7718
s.e.            2.1970            2.1969            2.1955            2.1772             2.2008             2.3109     1.7919

sigma^2 = 60.36:  log likelihood = -863.25
AIC=1760.51   AICc=1763.14   BIC=1820.44

Training set error measures:
                ME     RMSE      MAE       MPE     MAPE     MASE       ACF1
Training set 0.329 7.502455 5.050058 -1.862855 21.31278 1.052095 0.01021194

Stochastic Trend & Deterministic Seasonality (Fourier)

Y_t = \beta_0 + \underbrace{\left[ \sum_{k=1}^{K} \left(a_k \sin\left(\frac{2\pi k t}{s}\right) + b_k \cos\left(\frac{2\pi k t}{s}\right)\right) \right]}_{\text{deterministic seasonal with Fourier terms}} + \underbrace{\alpha_1 V_t}_{\text{calendar variation}} + \underbrace{\frac{\theta_q(B)}{\phi_p(B)(1-B)^d} a_t}_{\text{ARIMA error}}

xreg_train4 <- cbind(
  seasonal = fourier(y_train, K = 5),           
  idul_adha  = train$idul_adha
) %>% as.matrix()
m4 <- auto.arima(y_train, xreg = xreg_train4, seasonal = FALSE)
summary(m4)
Series: y_train 
Regression with ARIMA(2,1,2) errors 

Coefficients:
          ar1      ar2      ma1      ma2    S1-12    C1-12   S2-12    C2-12   S3-12   C3-12    S4-12   C4-12   S5-12   C5-12
      -0.4307  -0.0687  -0.5511  -0.2571  -1.8347  -3.0158  0.1746  -1.3822  0.1734  0.6235  -0.2890  0.1189  0.3009  0.3278
s.e.   1.9877   0.2219   1.9945   1.7161   0.5886   0.5755  0.5886   0.5890  0.6339  0.6345   0.6792  0.6787  0.6894  0.6892
      idul_adha
        30.7572
s.e.     1.7970

sigma^2 = 60.11:  log likelihood = -863.27
AIC=1758.55   AICc=1760.87   BIC=1814.95

Training set error measures:
                  ME     RMSE      MAE       MPE     MAPE     MASE       ACF1
Training set 0.32892 7.503059 5.044598 -1.868757 21.28611 1.050958 0.01014251

Deterministic Trend & Stochastic Seasonality

Y_t = \underbrace{\beta_0 + \beta_1 t}_{\text{deterministic trend}} + \underbrace{\alpha_1 V_t}_{\text{calendar variation effect}} + \underbrace{\frac{\theta_q(B)\Theta_Q(B^s)}{\phi_p(B)\Phi_P(B^s)(1-B)^d(1-B^s)^D} a_t}_{\text{Seasonal ARIMA}}

xreg_train5 <- cbind(
  trend = seq_along(y_train),           
  idul_adha  = train$idul_adha
) %>% as.matrix()
m5 <- auto.arima(y_train, xreg = xreg_train5)
summary(m5)
Series: y_train 
Regression with ARIMA(1,0,2)(2,0,0)[12] errors 

Coefficients:
         ar1      ma1     ma2    sar1     sar2  intercept   trend  idul_adha
      0.8435  -0.8533  0.1479  0.9431  -0.3234    13.5693  0.0743    18.3191
s.e.  0.1268   0.1547  0.0735  0.0708   0.0759     3.3776  0.0231     1.8880

sigma^2 = 36.69:  log likelihood = -813.21
AIC=1644.43   AICc=1645.17   BIC=1676.19

Training set error measures:
                      ME     RMSE      MAE       MPE     MAPE      MASE         ACF1
Training set -0.01452727 5.960219 3.593978 -3.338806 14.54093 0.7487454 -0.006946276

Stochastic Trend & Seasonality

Y_t = \beta_0 + \underbrace{\alpha_1 V_t}_{\text{calendar variation effect}} + \underbrace{\frac{\theta_q(B)\Theta_Q(B^s)}{\phi_p(B)\Phi_P(B^s)(1-B)^d(1-B^s)^D} a_t}_{\text{Seasonal ARIMA}}

xreg_train6 <- cbind(
  idul_adha  = train$idul_adha
) %>% as.matrix()
m6 <- auto.arima(y_train, xreg = xreg_train6)
summary(m6)
Series: y_train 
Regression with ARIMA(1,1,1)(1,0,2)[12] errors 

Coefficients:
          ar1      ma1    sar1    sma1    sma2  idul_adha
      -0.1260  -0.8738  0.3328  0.5422  0.2995    18.9039
s.e.   0.0872   0.0442  0.1322  0.1337  0.1077     1.9471

sigma^2 = 37.12:  log likelihood = -812.64
AIC=1639.28   AICc=1639.74   BIC=1663.96

Training set error measures:
                     ME     RMSE      MAE      MPE     MAPE      MASE      ACF1
Training set 0.08039586 6.007218 3.694197 -2.04907 14.90472 0.7696244 0.0087753

Forecasting

Train Set

predict_train <- train %>% 
  mutate(actual = search, 
         m1_predict = m1$fitted,
         m2_predict = m2$fitted,
         m3_predict = m3$fitted,
         m4_predict = m4$fitted,
         m5_predict = m5$fitted,
         m6_predict = m6$fitted) %>%
  select(ts, actual, m1_predict, m2_predict, m3_predict, m4_predict, m5_predict, m6_predict) 
predict_train
my_theme <- theme(
  legend.position  = c(0.2, 0.75),
  legend.text      = element_text(size = 5),
  legend.title     = element_text(size = 10),
  legend.key.size   = unit(0.3, "lines"),
  legend.box.margin = margin(0, 0, 0, 0),
  legend.background= element_rect(fill = "white", colour = "grey80"),
  plot.title       = element_text(size = 8, face = "bold")
)

p1 <- ggplot(data = predict_train) +
  geom_line(aes(x = ts, y = actual,  color = "Actual")) +
  geom_line(aes(x = ts, y = m1_predict, color = "Predicted")) +
  scale_color_manual(
    name = NULL,
    values = c("Actual" = "grey",
               "Predicted" = "red")
  ) +
  ggtitle("Deterministic Trend & Seasonality (Dummy)") +
  xlab("") + ylab("") +
  scale_x_datetime(date_breaks = "3 year", date_labels = "%Y") +
  my_theme

p2 <- ggplot(data = predict_train) +
  geom_line(aes(x = ts, y = actual,  color = "Actual")) +
  geom_line(aes(x = ts, y = m2_predict, color = "Predicted")) +
  scale_color_manual(
    name = NULL,
    values = c("Actual" = "grey",
               "Predicted" = "blue")
  ) +
  ggtitle("Deterministic Trend & Seasonality (Fourier)") +
  xlab("") + ylab("") +
  scale_x_datetime(date_breaks = "3 year", date_labels = "%Y") +
  my_theme

p3 <- ggplot(data = predict_train) +
  geom_line(aes(x = ts, y = actual,  color = "Actual")) +
  geom_line(aes(x = ts, y = m3_predict, color = "Predicted")) +
  scale_color_manual(
    name = NULL,
    values = c("Actual" = "grey",
               "Predicted" = "brown")
  ) +
  ggtitle("Stochastic Trend & Deterministic Seasonality (Dummy)") +
  xlab("") + ylab("") +
  scale_x_datetime(date_breaks = "3 year", date_labels = "%Y") +
  my_theme

p4 <- ggplot(data = predict_train) +
  geom_line(aes(x = ts, y = actual,  color = "Actual")) +
  geom_line(aes(x = ts, y = m4_predict, color = "Predicted")) +
  scale_color_manual(
    name = NULL,
    values = c("Actual" = "grey",
               "Predicted" = "purple")
  ) +
  ggtitle("Stochastic Trend & Deterministic Seasonality (Fourier)") +
  xlab("") + ylab("") +
  scale_x_datetime(date_breaks = "3 year", date_labels = "%Y") +
  my_theme

p5 <- ggplot(data = predict_train) +
  geom_line(aes(x = ts, y = actual,  color = "Actual")) +
  geom_line(aes(x = ts, y = m5_predict, color = "Predicted")) +
  scale_color_manual(
    name = NULL,
    values = c("Actual" = "grey",
               "Predicted" = "green4")
  ) +
  ggtitle("Deterministic Trend & Stochastic Seasonality") +
  xlab("") + ylab("") +
  scale_x_datetime(date_breaks = "3 year", date_labels = "%Y") +
  my_theme

p6 <- ggplot(data = predict_train) +
  geom_line(aes(x = ts, y = actual,  color = "Actual")) +
  geom_line(aes(x = ts, y = m6_predict, color = "Predicted")) +
  scale_color_manual(
    name = NULL,
    values = c("Actual" = "grey",
               "Predicted" = "orange")
  ) +
  ggtitle("Stochastic Trend & Seasonality") +
  xlab("") + ylab("") +
  scale_x_datetime(date_breaks = "3 year", date_labels = "%Y") +
  my_theme

grid.arrange(p1,p2, p3, p4, p5, p6, ncol=2)

Test Set

xreg_future <- cbind(
  trend = test$t,
  seasonal = test %>% select(starts_with("month_")) %>% select(-month_12),                  
  idul_adha  = test$idul_adha
) %>% as.matrix()

xreg_future2 <- cbind(
  trend = test$t,
  seasonal = fourier(y_test, K = 5),                   
  idul_adha  = test$idul_adha
) %>% as.matrix()

xreg_future3 <- cbind(
  seasonal = test %>% select(starts_with("month_")) %>% select(-month_12),            
  idul_adha  = test$idul_adha
) %>% as.matrix()

xreg_future4 <- cbind(
  seasonal = fourier(y_test, K = 5),           
  idul_adha  = test$idul_adha
) %>% as.matrix()

xreg_future5 <- cbind(
  trend = test$t,
  idul_adha  = test$idul_adha
) %>% as.matrix()

xreg_future6 <- cbind(
  idul_adha  = test$idul_adha
) %>% as.matrix()

predict_test <- test %>% 
  mutate(actual = search, 
         m1_predict = forecast(m1, xreg = xreg_future)$mean,
         m2_predict = forecast(m2, xreg = xreg_future2)$mean,
         m3_predict = forecast(m3, xreg = xreg_future3)$mean,
         m4_predict = forecast(m4, xreg = xreg_future4)$mean,
         m5_predict = forecast(m5, xreg = xreg_future5)$mean,
         m6_predict = forecast(m6, xreg = xreg_future6)$mean) %>%
  select(ts, actual, m1_predict, m2_predict, m3_predict, m4_predict, m5_predict, m6_predict) 
predict_test
p1 <- ggplot(data = predict_test) +
  geom_line(aes(x = ts, y = actual,  color = "Actual")) +
  geom_line(aes(x = ts, y = m1_predict, color = "Predicted")) +
  scale_color_manual(
    name = NULL,
    values = c("Actual" = "grey",
               "Predicted" = "red")
  ) +
  ggtitle("Deterministic Trend & Seasonality (Dummy)") +
  xlab("") + ylab("") +
  scale_x_datetime(date_breaks = "3 year", date_labels = "%Y") +
  my_theme

p2 <- ggplot(data = predict_test) +
  geom_line(aes(x = ts, y = actual,  color = "Actual")) +
  geom_line(aes(x = ts, y = m2_predict, color = "Predicted")) +
  scale_color_manual(
    name = NULL,
    values = c("Actual" = "grey",
               "Predicted" = "blue")
  ) +
  ggtitle("Deterministic Trend & Seasonality (Fourier)") +
  xlab("") + ylab("") +
  scale_x_datetime(date_breaks = "3 year", date_labels = "%Y") +
  my_theme

p3 <- ggplot(data = predict_test) +
  geom_line(aes(x = ts, y = actual,  color = "Actual")) +
  geom_line(aes(x = ts, y = m3_predict, color = "Predicted")) +
  scale_color_manual(
    name = NULL,
    values = c("Actual" = "grey",
               "Predicted" = "brown")
  ) +
  ggtitle("Stochastic Trend & Deterministic Seasonality (Dummy)") +
  xlab("") + ylab("") +
  scale_x_datetime(date_breaks = "3 year", date_labels = "%Y") +
  my_theme

p4 <- ggplot(data = predict_test) +
  geom_line(aes(x = ts, y = actual,  color = "Actual")) +
  geom_line(aes(x = ts, y = m4_predict, color = "Predicted")) +
  scale_color_manual(
    name = NULL,
    values = c("Actual" = "grey",
               "Predicted" = "purple")
  ) +
  ggtitle("Stochastic Trend & Deterministic Seasonality (Fourier)") +
  xlab("") + ylab("") +
  scale_x_datetime(date_breaks = "3 year", date_labels = "%Y") +
  my_theme

p5 <- ggplot(data = predict_test) +
  geom_line(aes(x = ts, y = actual,  color = "Actual")) +
  geom_line(aes(x = ts, y = m5_predict, color = "Predicted")) +
  scale_color_manual(
    name = NULL,
    values = c("Actual" = "grey",
               "Predicted" = "green4")
  ) +
  ggtitle("Deterministic Trend & Stochastic Seasonality") +
  xlab("") + ylab("") +
  scale_x_datetime(date_breaks = "3 year", date_labels = "%Y") +
  my_theme

p6 <- ggplot(data = predict_test) +
  geom_line(aes(x = ts, y = actual,  color = "Actual")) +
  geom_line(aes(x = ts, y = m6_predict, color = "Predicted")) +
  scale_color_manual(
    name = NULL,
    values = c("Actual" = "grey",
               "Predicted" = "orange")
  ) +
  ggtitle("Stochastic Trend & Seasonality") +
  xlab("") + ylab("") +
  scale_x_datetime(date_breaks = "3 year", date_labels = "%Y") +
  my_theme

grid.arrange(p1,p2, p3, p4, p5, p6, ncol=2)

Model Evaluation

Train Set

predict_train %>%
  select(ends_with("_predict")) %>%          
  imap_dfr(~ tibble(
    Model = .y,                               
    RMSE  = rmse (predict_train$actual, .x),
    MAPE  = mape (predict_train$actual, .x),
    sMAPE = smape(predict_train$actual, .x)
  )) %>%
  mutate(Model = recode(Model,
    m1_predict = "Deterministic Trend & Seasonality (Dummy)",
    m2_predict = "Deterministic Trend & Seasonality (Fourier)",
    m3_predict = "Stochastic Trend & Deterministic Seasonality (Dummy)",
    m4_predict = "Stochastic Trend & Deterministic Seasonality (Fourier)",
    m5_predict = "Deterministic Trend & Stochastic Seasonality",
    m6_predict = "Stochastic Trend & Seasonality",
  ))

Test Set

predict_test %>%
  select(ends_with("_predict")) %>%          
  imap_dfr(~ tibble(
    Model = .y,                               
    RMSE  = rmse (predict_test$actual, .x),
    MAPE  = mape (predict_test$actual, .x),
    sMAPE = smape(predict_test$actual, .x)
  )) %>%
  mutate(Model = recode(Model,
    m1_predict = "Deterministic Trend & Seasonality (Dummy)",
    m2_predict = "Deterministic Trend & Seasonality (Fourier)",
    m3_predict = "Stochastic Trend & Deterministic Seasonality (Dummy)",
    m4_predict = "Stochastic Trend & Deterministic Seasonality (Fourier)",
    m5_predict = "Deterministic Trend & Stochastic Seasonality",
    m6_predict = "Stochastic Trend & Seasonality",
  ))
LS0tCnRpdGxlOiAiQ2FsZW5kYXIgVmFyaWF0aW9uIE1vZGVscyIKb3V0cHV0OgogIGh0bWxfbm90ZWJvb2s6CiAgICB0b2M6IHRydWUKICAgIHRvY19mbG9hdDoKICAgICAgdG9jX2NvbGxhcHNlZDogdHJ1ZQogICAgbWF0aF9tZXRob2Q6IGthdGV4Ci0tLQoKIyMgTGlicmFyaWVzCgpgYGB7cn0KbGlicmFyeSh0aWR5dmVyc2UpCmxpYnJhcnkoZm9yZWNhc3QpCmxpYnJhcnkoZ3JpZEV4dHJhKQpsaWJyYXJ5KGZhc3REdW1taWVzKQpsaWJyYXJ5KE1ldHJpY3MpCmxpYnJhcnkoQkVUUykKbGlicmFyeShsbXRlc3QpCmBgYAoKIyMgRGF0YXNldAoKYGBge3J9CmRmX3JhdyA8LSByZWFkX2Nzdigic2VhcmNoLmNzdiIpCmBgYAoKYGBge3J9CmhlYWQoZGZfcmF3KQpgYGAKCmBgYHtyfQojIGRlZmluZSBjYWxlbmRhciB2YXJpYXRpb24gdmFyaWFibGUKaWR1bF9hZGhhX21vbnRocyA8LSBjKAogICIyMDA0LTAyIiwiMjAwNS0wMSIsIjIwMDYtMDEiLCIyMDA3LTEyIiwiMjAwOC0xMiIsIjIwMDktMTEiLAogICIyMDEwLTExIiwiMjAxMS0xMSIsIjIwMTItMTAiLCIyMDEzLTEwIiwiMjAxNC0xMCIsIjIwMTUtMDkiLAogICIyMDE2LTA5IiwiMjAxNy0wOSIsIjIwMTgtMDgiLCIyMDE5LTA4IiwiMjAyMC0wNyIsIjIwMjEtMDciLAogICIyMDIyLTA3IiwiMjAyMy0wNiIsIjIwMjQtMDYiLCAiMjAyNS0wNiIKKQpkZl9yYXckaWR1bF9hZGhhIDwtIGFzLmludGVnZXIoZGZfcmF3JE1vbnRoICVpbiUgaWR1bF9hZGhhX21vbnRocykKZGZfcmF3CmBgYAoKYGBge3J9CmRmX3JhdyAlPiUgZmlsdGVyKGlkdWxfYWRoYT09MSkKYGBgCgoKYGBge3J9CmRmIDwtIGRmX3JhdyAlPiUKICAgICAgICBtdXRhdGUodHMgPSB5bShNb250aCksIHNlYXJjaCA9IFNlYXJjaCwgCiAgICAgICAgICAgICAgIG1vbnRoID0gbW9udGgodHMpLCB5ZWFyID0geWVhcih0cyksCiAgICAgICAgICAgICAgIHQgPSBzZXFfYWxvbmcodHMpKSAlPiUKICAgICAgICBkdW1teV9jb2xzKHNlbGVjdF9jb2x1bW5zID0gIm1vbnRoIikgJT4lCiAgICAgICAgc2VsZWN0KHRzLCB0LCBpZHVsX2FkaGEsIHllYXIsIG1vbnRoLCBzdGFydHNfd2l0aCgibW9udGhfIiksIHNlYXJjaCkgCmRmCmBgYAoKCmBgYHtyfQpnZ3Bsb3QoZGF0YSA9IGRmKSArCiAgZ2VvbV9saW5lKGFlcyh4ID0gdHMsIHkgPSBzZWFyY2gpKSArCiAgZ2d0aXRsZSgiU2VhcmNoIFZvbHVtZSBJbmRleCBmb3Iga2V5d29yZCBzYXBpIikgKwogIHhsYWIoIiIpICsgeWxhYigiIikgKwogIHNjYWxlX3hfZGF0ZXRpbWUoZGF0ZV9icmVha3MgPSAiMiB5ZWFyIiwgZGF0ZV9sYWJlbHMgPSAiJVkiKSAKYGBgCgoKYGBge3J9CnRyYWluIDwtIGRmICU+JSBmaWx0ZXIoeWVhciAhPSAyMDI1KQp0ZXN0ICA8LSBkZiAlPiUgZmlsdGVyKHllYXIgPT0gMjAyNSkKeV90cmFpbiA8LSB0cyh0cmFpbiRzZWFyY2gsIHN0YXJ0ID0gYygyMDA0LCAxKSwgZnJlcXVlbmN5ID0gMTIpCnlfdGVzdCAgPC0gdHModGVzdCRzZWFyY2gsIHN0YXJ0ID0gYygyMDI1LCAxKSwgZnJlcXVlbmN5ID0gMTIpCmBgYAoKIyMgTW9kZWxsaW5nCgojIyMgRGV0ZXJtaW5pc3RpYyBUcmVuZCAmIFNlYXNvbmFsaXR5IChEdW1teSkKCgokJApZX3QgPSBcdW5kZXJicmFjZXtcYmV0YV8wICsgXGJldGFfMSB0fV97XHRleHR7ZGV0ZXJtaW5pc3RpYyB0cmVuZH19ICsgXHVuZGVyYnJhY2V7XHN1bV97aT0xfV57cy0xfSBcZGVsdGFfaSBTX3tpLHR9ICsgXGRlbHRhX3tzLHR9fV97XHRleHR7ZGV0ZXJtaW5pc3RpYyBzZWFzb25hbCB3aXRoIGR1bW15IHZhcmlhYmxlfX0gKyBcdW5kZXJicmFjZXtcYWxwaGFfMSBWX3R9X3tcdGV4dHtjYWxlbmRhciB2YXJpYXRpb24gZWZmZWN0fX0gKyBcdW5kZXJicmFjZXtcZnJhY3tcdGhldGFfcShCKX17XHBoaV9wKEIpfSBhX3R9X3tcdGV4dHtBUklNQSBlcnJvcn19CiQkCgpgYGB7cn0KeHJlZ190cmFpbiA8LSBjYmluZCgKICB0cmVuZCA9IHNlcV9hbG9uZyh5X3RyYWluKSwKICBzZWFzb25hbCA9IHRyYWluICU+JSBzZWxlY3Qoc3RhcnRzX3dpdGgoIm1vbnRoXyIpKSAlPiUgc2VsZWN0KC1tb250aF8xMiksICAgICAgICAgICAgICAgICAgCiAgaWR1bF9hZGhhICA9IHRyYWluJGlkdWxfYWRoYQopICU+JSBhcy5tYXRyaXgoKQpgYGAKCgoKYGBge3J9Cm0xIDwtIGF1dG8uYXJpbWEoeV90cmFpbiwgeHJlZyA9IHhyZWdfdHJhaW4sIHNlYXNvbmFsID0gRkFMU0UpCnN1bW1hcnkobTEpCmBgYAoKCgpgYGB7cn0KcHJlZGljdF90cmFpbiA8LSB0cmFpbiAlPiUgCiAgbXV0YXRlKGFjdHVhbCA9IHNlYXJjaCwgCiAgICAgICAgIG0xX3ByZWRpY3QgPSBtMSRmaXR0ZWQpIApwcmVkaWN0X3RyYWluCmBgYAoKCgojIyMgRGV0ZXJtaW5pc3RpYyBUcmVuZCAmIFNlYXNvbmFsaXR5IChGb3VyaWVyKQoKJCQKICAgICAgICBZX3QgPSBcdW5kZXJicmFjZXtcYmV0YV8wICsgXGJldGFfMSB0fV97XHRleHR7ZGV0ZXJtaW5pc3RpYyB0cmVuZH19ICsgXHVuZGVyYnJhY2V7XGxlZnRbIFxzdW1fe2s9MX1ee0t9IFxsZWZ0KGFfayBcc2luXGxlZnQoXGZyYWN7MlxwaSBrIHR9e3N9XHJpZ2h0KSArIGJfayBcY29zXGxlZnQoXGZyYWN7MlxwaSBrIHR9e3N9XHJpZ2h0KVxyaWdodCkgXHJpZ2h0XX1fe1x0ZXh0e2RldGVybWluaXN0aWMgc2Vhc29uYWwgd2l0aCBGb3VyaWVyIHRlcm1zfX0gKyBcdW5kZXJicmFjZXtcYWxwaGFfMSBWX3QgfV97XHRleHR7Y2FsZW5kYXIgdmFyaWF0aW9ufX0gKyBcdW5kZXJicmFjZXtcZnJhY3tcdGhldGFfcShCKX17XHBoaV9wKEIpfSBhX3R9X3tcdGV4dHtBUklNQSBlcnJvcn19CiQkCgoKCmBgYHtyfQp4cmVnX3RyYWluMiA8LSBjYmluZCgKICB0cmVuZCA9IHNlcV9hbG9uZyh5X3RyYWluKSwKICBzZWFzb25hbCA9IGZvdXJpZXIoeV90cmFpbiwgSyA9IDUpLCAgICAgICAgICAgICAgICAgIAogIGlkdWxfYWRoYSAgPSB0cmFpbiRpZHVsX2FkaGEKKSAlPiUgYXMubWF0cml4KCkKYGBgCgpgYGB7cn0KbTIgPC0gYXV0by5hcmltYSh5X3RyYWluLCB4cmVnID0geHJlZ190cmFpbjIsIHNlYXNvbmFsID0gRkFMU0UpCnN1bW1hcnkobTIpCmBgYAoKCiMjIyAgU3RvY2hhc3RpYyBUcmVuZCAmIERldGVybWluaXN0aWMgU2Vhc29uYWxpdHkgKER1bW15KQoKJCQKWV90ID0gXGJldGFfMCArIFx1bmRlcmJyYWNle1xzdW1fe2k9MX1ee3MtMX0gXGRlbHRhX2kgU197aSx0fSArIFxkZWx0YV97cyx0fX1fe1x0ZXh0e2RldGVybWluaXN0aWMgc2Vhc29uYWwgd2l0aCBkdW1teX19ICsgXHVuZGVyYnJhY2V7XGFscGhhXzEgVl90fV97XHRleHR7Y2FsZW5kYXIgdmFyaWF0aW9uIGVmZmVjdH19ICsgXHVuZGVyYnJhY2V7XGZyYWN7XHRoZXRhX3EoQil9e1xwaGlfcChCKSgxLUIpXmR9IGFfdH1fe1x0ZXh0e0FSSU1BIGVycm9yfX0KJCQKCmBgYHtyfQp4cmVnX3RyYWluMyA8LSBjYmluZCgKICBzZWFzb25hbCA9IHRyYWluICU+JSBzZWxlY3Qoc3RhcnRzX3dpdGgoIm1vbnRoXyIpKSAlPiUgc2VsZWN0KC1tb250aF8xMiksICAgICAgICAgICAKICBpZHVsX2FkaGEgID0gdHJhaW4kaWR1bF9hZGhhCikgJT4lIGFzLm1hdHJpeCgpCmBgYAoKCmBgYHtyfQptMyA8LSBhdXRvLmFyaW1hKHlfdHJhaW4sIHhyZWcgPSB4cmVnX3RyYWluMywgc2Vhc29uYWwgPSBGQUxTRSkKc3VtbWFyeShtMykKYGBgCgoKCiMjIyAgU3RvY2hhc3RpYyBUcmVuZCAmIERldGVybWluaXN0aWMgU2Vhc29uYWxpdHkgKEZvdXJpZXIpCgokJAogICAgICAgIFlfdCA9IFxiZXRhXzAgKyBcdW5kZXJicmFjZXtcbGVmdFsgXHN1bV97az0xfV57S30gXGxlZnQoYV9rIFxzaW5cbGVmdChcZnJhY3syXHBpIGsgdH17c31ccmlnaHQpICsgYl9rIFxjb3NcbGVmdChcZnJhY3syXHBpIGsgdH17c31ccmlnaHQpXHJpZ2h0KSBccmlnaHRdfV97XHRleHR7ZGV0ZXJtaW5pc3RpYyBzZWFzb25hbCB3aXRoIEZvdXJpZXIgdGVybXN9fSArIFx1bmRlcmJyYWNle1xhbHBoYV8xIFZfdH1fe1x0ZXh0e2NhbGVuZGFyIHZhcmlhdGlvbn19ICsgXHVuZGVyYnJhY2V7XGZyYWN7XHRoZXRhX3EoQil9e1xwaGlfcChCKSgxLUIpXmR9IGFfdH1fe1x0ZXh0e0FSSU1BIGVycm9yfX0KJCQKCgpgYGB7cn0KeHJlZ190cmFpbjQgPC0gY2JpbmQoCiAgc2Vhc29uYWwgPSBmb3VyaWVyKHlfdHJhaW4sIEsgPSA1KSwgICAgICAgICAgIAogIGlkdWxfYWRoYSAgPSB0cmFpbiRpZHVsX2FkaGEKKSAlPiUgYXMubWF0cml4KCkKYGBgCgpgYGB7cn0KbTQgPC0gYXV0by5hcmltYSh5X3RyYWluLCB4cmVnID0geHJlZ190cmFpbjQsIHNlYXNvbmFsID0gRkFMU0UpCnN1bW1hcnkobTQpCmBgYAoKCgojIyMgIERldGVybWluaXN0aWMgVHJlbmQgJiBTdG9jaGFzdGljIFNlYXNvbmFsaXR5CgokJAogICAgWV90ID0gXHVuZGVyYnJhY2V7XGJldGFfMCArIFxiZXRhXzEgdH1fe1x0ZXh0e2RldGVybWluaXN0aWMgdHJlbmR9fSArIFx1bmRlcmJyYWNle1xhbHBoYV8xIFZfdH1fe1x0ZXh0e2NhbGVuZGFyIHZhcmlhdGlvbiBlZmZlY3R9fSArIFx1bmRlcmJyYWNle1xmcmFje1x0aGV0YV9xKEIpXFRoZXRhX1EoQl5zKX17XHBoaV9wKEIpXFBoaV9QKEJecykoMS1CKV5kKDEtQl5zKV5EfSBhX3R9X3tcdGV4dHtTZWFzb25hbCBBUklNQX19CiQkCgoKYGBge3J9CnhyZWdfdHJhaW41IDwtIGNiaW5kKAogIHRyZW5kID0gc2VxX2Fsb25nKHlfdHJhaW4pLCAgICAgICAgICAgCiAgaWR1bF9hZGhhICA9IHRyYWluJGlkdWxfYWRoYQopICU+JSBhcy5tYXRyaXgoKQpgYGAKCgpgYGB7cn0KbTUgPC0gYXV0by5hcmltYSh5X3RyYWluLCB4cmVnID0geHJlZ190cmFpbjUpCnN1bW1hcnkobTUpCmBgYAoKCgojIyMgIFN0b2NoYXN0aWMgVHJlbmQgJiBTZWFzb25hbGl0eQoKJCQKICAgIFlfdCA9IFxiZXRhXzAgKyBcdW5kZXJicmFjZXtcYWxwaGFfMSBWX3R9X3tcdGV4dHtjYWxlbmRhciB2YXJpYXRpb24gZWZmZWN0fX0gKyBcdW5kZXJicmFjZXtcZnJhY3tcdGhldGFfcShCKVxUaGV0YV9RKEJecyl9e1xwaGlfcChCKVxQaGlfUChCXnMpKDEtQileZCgxLUJecyleRH0gYV90fV97XHRleHR7U2Vhc29uYWwgQVJJTUF9fQokJAoKCmBgYHtyfQp4cmVnX3RyYWluNiA8LSBjYmluZCgKICBpZHVsX2FkaGEgID0gdHJhaW4kaWR1bF9hZGhhCikgJT4lIGFzLm1hdHJpeCgpCmBgYAoKCmBgYHtyfQptNiA8LSBhdXRvLmFyaW1hKHlfdHJhaW4sIHhyZWcgPSB4cmVnX3RyYWluNikKc3VtbWFyeShtNikKYGBgCgoKIyMgRm9yZWNhc3RpbmcKCiMjIyBUcmFpbiBTZXQKCmBgYHtyfQpwcmVkaWN0X3RyYWluIDwtIHRyYWluICU+JSAKICBtdXRhdGUoYWN0dWFsID0gc2VhcmNoLCAKICAgICAgICAgbTFfcHJlZGljdCA9IG0xJGZpdHRlZCwKICAgICAgICAgbTJfcHJlZGljdCA9IG0yJGZpdHRlZCwKICAgICAgICAgbTNfcHJlZGljdCA9IG0zJGZpdHRlZCwKICAgICAgICAgbTRfcHJlZGljdCA9IG00JGZpdHRlZCwKICAgICAgICAgbTVfcHJlZGljdCA9IG01JGZpdHRlZCwKICAgICAgICAgbTZfcHJlZGljdCA9IG02JGZpdHRlZCkgJT4lCiAgc2VsZWN0KHRzLCBhY3R1YWwsIG0xX3ByZWRpY3QsIG0yX3ByZWRpY3QsIG0zX3ByZWRpY3QsIG00X3ByZWRpY3QsIG01X3ByZWRpY3QsIG02X3ByZWRpY3QpIApwcmVkaWN0X3RyYWluCmBgYAoKYGBge3J9Cm15X3RoZW1lIDwtIHRoZW1lKAogIGxlZ2VuZC5wb3NpdGlvbiAgPSBjKDAuMiwgMC43NSksCiAgbGVnZW5kLnRleHQgICAgICA9IGVsZW1lbnRfdGV4dChzaXplID0gNSksCiAgbGVnZW5kLnRpdGxlICAgICA9IGVsZW1lbnRfdGV4dChzaXplID0gMTApLAogIGxlZ2VuZC5rZXkuc2l6ZSAgID0gdW5pdCgwLjMsICJsaW5lcyIpLAogIGxlZ2VuZC5ib3gubWFyZ2luID0gbWFyZ2luKDAsIDAsIDAsIDApLAogIGxlZ2VuZC5iYWNrZ3JvdW5kPSBlbGVtZW50X3JlY3QoZmlsbCA9ICJ3aGl0ZSIsIGNvbG91ciA9ICJncmV5ODAiKSwKICBwbG90LnRpdGxlICAgICAgID0gZWxlbWVudF90ZXh0KHNpemUgPSA4LCBmYWNlID0gImJvbGQiKQopCgpwMSA8LSBnZ3Bsb3QoZGF0YSA9IHByZWRpY3RfdHJhaW4pICsKICBnZW9tX2xpbmUoYWVzKHggPSB0cywgeSA9IGFjdHVhbCwgIGNvbG9yID0gIkFjdHVhbCIpKSArCiAgZ2VvbV9saW5lKGFlcyh4ID0gdHMsIHkgPSBtMV9wcmVkaWN0LCBjb2xvciA9ICJQcmVkaWN0ZWQiKSkgKwogIHNjYWxlX2NvbG9yX21hbnVhbCgKICAgIG5hbWUgPSBOVUxMLAogICAgdmFsdWVzID0gYygiQWN0dWFsIiA9ICJncmV5IiwKICAgICAgICAgICAgICAgIlByZWRpY3RlZCIgPSAicmVkIikKICApICsKICBnZ3RpdGxlKCJEZXRlcm1pbmlzdGljIFRyZW5kICYgU2Vhc29uYWxpdHkgKER1bW15KSIpICsKICB4bGFiKCIiKSArIHlsYWIoIiIpICsKICBzY2FsZV94X2RhdGV0aW1lKGRhdGVfYnJlYWtzID0gIjMgeWVhciIsIGRhdGVfbGFiZWxzID0gIiVZIikgKwogIG15X3RoZW1lCgpwMiA8LSBnZ3Bsb3QoZGF0YSA9IHByZWRpY3RfdHJhaW4pICsKICBnZW9tX2xpbmUoYWVzKHggPSB0cywgeSA9IGFjdHVhbCwgIGNvbG9yID0gIkFjdHVhbCIpKSArCiAgZ2VvbV9saW5lKGFlcyh4ID0gdHMsIHkgPSBtMl9wcmVkaWN0LCBjb2xvciA9ICJQcmVkaWN0ZWQiKSkgKwogIHNjYWxlX2NvbG9yX21hbnVhbCgKICAgIG5hbWUgPSBOVUxMLAogICAgdmFsdWVzID0gYygiQWN0dWFsIiA9ICJncmV5IiwKICAgICAgICAgICAgICAgIlByZWRpY3RlZCIgPSAiYmx1ZSIpCiAgKSArCiAgZ2d0aXRsZSgiRGV0ZXJtaW5pc3RpYyBUcmVuZCAmIFNlYXNvbmFsaXR5IChGb3VyaWVyKSIpICsKICB4bGFiKCIiKSArIHlsYWIoIiIpICsKICBzY2FsZV94X2RhdGV0aW1lKGRhdGVfYnJlYWtzID0gIjMgeWVhciIsIGRhdGVfbGFiZWxzID0gIiVZIikgKwogIG15X3RoZW1lCgpwMyA8LSBnZ3Bsb3QoZGF0YSA9IHByZWRpY3RfdHJhaW4pICsKICBnZW9tX2xpbmUoYWVzKHggPSB0cywgeSA9IGFjdHVhbCwgIGNvbG9yID0gIkFjdHVhbCIpKSArCiAgZ2VvbV9saW5lKGFlcyh4ID0gdHMsIHkgPSBtM19wcmVkaWN0LCBjb2xvciA9ICJQcmVkaWN0ZWQiKSkgKwogIHNjYWxlX2NvbG9yX21hbnVhbCgKICAgIG5hbWUgPSBOVUxMLAogICAgdmFsdWVzID0gYygiQWN0dWFsIiA9ICJncmV5IiwKICAgICAgICAgICAgICAgIlByZWRpY3RlZCIgPSAiYnJvd24iKQogICkgKwogIGdndGl0bGUoIlN0b2NoYXN0aWMgVHJlbmQgJiBEZXRlcm1pbmlzdGljIFNlYXNvbmFsaXR5IChEdW1teSkiKSArCiAgeGxhYigiIikgKyB5bGFiKCIiKSArCiAgc2NhbGVfeF9kYXRldGltZShkYXRlX2JyZWFrcyA9ICIzIHllYXIiLCBkYXRlX2xhYmVscyA9ICIlWSIpICsKICBteV90aGVtZQoKcDQgPC0gZ2dwbG90KGRhdGEgPSBwcmVkaWN0X3RyYWluKSArCiAgZ2VvbV9saW5lKGFlcyh4ID0gdHMsIHkgPSBhY3R1YWwsICBjb2xvciA9ICJBY3R1YWwiKSkgKwogIGdlb21fbGluZShhZXMoeCA9IHRzLCB5ID0gbTRfcHJlZGljdCwgY29sb3IgPSAiUHJlZGljdGVkIikpICsKICBzY2FsZV9jb2xvcl9tYW51YWwoCiAgICBuYW1lID0gTlVMTCwKICAgIHZhbHVlcyA9IGMoIkFjdHVhbCIgPSAiZ3JleSIsCiAgICAgICAgICAgICAgICJQcmVkaWN0ZWQiID0gInB1cnBsZSIpCiAgKSArCiAgZ2d0aXRsZSgiU3RvY2hhc3RpYyBUcmVuZCAmIERldGVybWluaXN0aWMgU2Vhc29uYWxpdHkgKEZvdXJpZXIpIikgKwogIHhsYWIoIiIpICsgeWxhYigiIikgKwogIHNjYWxlX3hfZGF0ZXRpbWUoZGF0ZV9icmVha3MgPSAiMyB5ZWFyIiwgZGF0ZV9sYWJlbHMgPSAiJVkiKSArCiAgbXlfdGhlbWUKCnA1IDwtIGdncGxvdChkYXRhID0gcHJlZGljdF90cmFpbikgKwogIGdlb21fbGluZShhZXMoeCA9IHRzLCB5ID0gYWN0dWFsLCAgY29sb3IgPSAiQWN0dWFsIikpICsKICBnZW9tX2xpbmUoYWVzKHggPSB0cywgeSA9IG01X3ByZWRpY3QsIGNvbG9yID0gIlByZWRpY3RlZCIpKSArCiAgc2NhbGVfY29sb3JfbWFudWFsKAogICAgbmFtZSA9IE5VTEwsCiAgICB2YWx1ZXMgPSBjKCJBY3R1YWwiID0gImdyZXkiLAogICAgICAgICAgICAgICAiUHJlZGljdGVkIiA9ICJncmVlbjQiKQogICkgKwogIGdndGl0bGUoIkRldGVybWluaXN0aWMgVHJlbmQgJiBTdG9jaGFzdGljIFNlYXNvbmFsaXR5IikgKwogIHhsYWIoIiIpICsgeWxhYigiIikgKwogIHNjYWxlX3hfZGF0ZXRpbWUoZGF0ZV9icmVha3MgPSAiMyB5ZWFyIiwgZGF0ZV9sYWJlbHMgPSAiJVkiKSArCiAgbXlfdGhlbWUKCnA2IDwtIGdncGxvdChkYXRhID0gcHJlZGljdF90cmFpbikgKwogIGdlb21fbGluZShhZXMoeCA9IHRzLCB5ID0gYWN0dWFsLCAgY29sb3IgPSAiQWN0dWFsIikpICsKICBnZW9tX2xpbmUoYWVzKHggPSB0cywgeSA9IG02X3ByZWRpY3QsIGNvbG9yID0gIlByZWRpY3RlZCIpKSArCiAgc2NhbGVfY29sb3JfbWFudWFsKAogICAgbmFtZSA9IE5VTEwsCiAgICB2YWx1ZXMgPSBjKCJBY3R1YWwiID0gImdyZXkiLAogICAgICAgICAgICAgICAiUHJlZGljdGVkIiA9ICJvcmFuZ2UiKQogICkgKwogIGdndGl0bGUoIlN0b2NoYXN0aWMgVHJlbmQgJiBTZWFzb25hbGl0eSIpICsKICB4bGFiKCIiKSArIHlsYWIoIiIpICsKICBzY2FsZV94X2RhdGV0aW1lKGRhdGVfYnJlYWtzID0gIjMgeWVhciIsIGRhdGVfbGFiZWxzID0gIiVZIikgKwogIG15X3RoZW1lCgpncmlkLmFycmFuZ2UocDEscDIsIHAzLCBwNCwgcDUsIHA2LCBuY29sPTIpCmBgYAoKCgojIyMgVGVzdCBTZXQKCmBgYHtyfQp4cmVnX2Z1dHVyZSA8LSBjYmluZCgKICB0cmVuZCA9IHRlc3QkdCwKICBzZWFzb25hbCA9IHRlc3QgJT4lIHNlbGVjdChzdGFydHNfd2l0aCgibW9udGhfIikpICU+JSBzZWxlY3QoLW1vbnRoXzEyKSwgICAgICAgICAgICAgICAgICAKICBpZHVsX2FkaGEgID0gdGVzdCRpZHVsX2FkaGEKKSAlPiUgYXMubWF0cml4KCkKCnhyZWdfZnV0dXJlMiA8LSBjYmluZCgKICB0cmVuZCA9IHRlc3QkdCwKICBzZWFzb25hbCA9IGZvdXJpZXIoeV90ZXN0LCBLID0gNSksICAgICAgICAgICAgICAgICAgIAogIGlkdWxfYWRoYSAgPSB0ZXN0JGlkdWxfYWRoYQopICU+JSBhcy5tYXRyaXgoKQoKeHJlZ19mdXR1cmUzIDwtIGNiaW5kKAogIHNlYXNvbmFsID0gdGVzdCAlPiUgc2VsZWN0KHN0YXJ0c193aXRoKCJtb250aF8iKSkgJT4lIHNlbGVjdCgtbW9udGhfMTIpLCAgICAgICAgICAgIAogIGlkdWxfYWRoYSAgPSB0ZXN0JGlkdWxfYWRoYQopICU+JSBhcy5tYXRyaXgoKQoKeHJlZ19mdXR1cmU0IDwtIGNiaW5kKAogIHNlYXNvbmFsID0gZm91cmllcih5X3Rlc3QsIEsgPSA1KSwgICAgICAgICAgIAogIGlkdWxfYWRoYSAgPSB0ZXN0JGlkdWxfYWRoYQopICU+JSBhcy5tYXRyaXgoKQoKeHJlZ19mdXR1cmU1IDwtIGNiaW5kKAogIHRyZW5kID0gdGVzdCR0LAogIGlkdWxfYWRoYSAgPSB0ZXN0JGlkdWxfYWRoYQopICU+JSBhcy5tYXRyaXgoKQoKeHJlZ19mdXR1cmU2IDwtIGNiaW5kKAogIGlkdWxfYWRoYSAgPSB0ZXN0JGlkdWxfYWRoYQopICU+JSBhcy5tYXRyaXgoKQpgYGAKCmBgYHtyfQoKcHJlZGljdF90ZXN0IDwtIHRlc3QgJT4lIAogIG11dGF0ZShhY3R1YWwgPSBzZWFyY2gsIAogICAgICAgICBtMV9wcmVkaWN0ID0gZm9yZWNhc3QobTEsIHhyZWcgPSB4cmVnX2Z1dHVyZSkkbWVhbiwKICAgICAgICAgbTJfcHJlZGljdCA9IGZvcmVjYXN0KG0yLCB4cmVnID0geHJlZ19mdXR1cmUyKSRtZWFuLAogICAgICAgICBtM19wcmVkaWN0ID0gZm9yZWNhc3QobTMsIHhyZWcgPSB4cmVnX2Z1dHVyZTMpJG1lYW4sCiAgICAgICAgIG00X3ByZWRpY3QgPSBmb3JlY2FzdChtNCwgeHJlZyA9IHhyZWdfZnV0dXJlNCkkbWVhbiwKICAgICAgICAgbTVfcHJlZGljdCA9IGZvcmVjYXN0KG01LCB4cmVnID0geHJlZ19mdXR1cmU1KSRtZWFuLAogICAgICAgICBtNl9wcmVkaWN0ID0gZm9yZWNhc3QobTYsIHhyZWcgPSB4cmVnX2Z1dHVyZTYpJG1lYW4pICU+JQogIHNlbGVjdCh0cywgYWN0dWFsLCBtMV9wcmVkaWN0LCBtMl9wcmVkaWN0LCBtM19wcmVkaWN0LCBtNF9wcmVkaWN0LCBtNV9wcmVkaWN0LCBtNl9wcmVkaWN0KSAKcHJlZGljdF90ZXN0CmBgYAoKYGBge3J9CnAxIDwtIGdncGxvdChkYXRhID0gcHJlZGljdF90ZXN0KSArCiAgZ2VvbV9saW5lKGFlcyh4ID0gdHMsIHkgPSBhY3R1YWwsICBjb2xvciA9ICJBY3R1YWwiKSkgKwogIGdlb21fbGluZShhZXMoeCA9IHRzLCB5ID0gbTFfcHJlZGljdCwgY29sb3IgPSAiUHJlZGljdGVkIikpICsKICBzY2FsZV9jb2xvcl9tYW51YWwoCiAgICBuYW1lID0gTlVMTCwKICAgIHZhbHVlcyA9IGMoIkFjdHVhbCIgPSAiZ3JleSIsCiAgICAgICAgICAgICAgICJQcmVkaWN0ZWQiID0gInJlZCIpCiAgKSArCiAgZ2d0aXRsZSgiRGV0ZXJtaW5pc3RpYyBUcmVuZCAmIFNlYXNvbmFsaXR5IChEdW1teSkiKSArCiAgeGxhYigiIikgKyB5bGFiKCIiKSArCiAgc2NhbGVfeF9kYXRldGltZShkYXRlX2JyZWFrcyA9ICIzIHllYXIiLCBkYXRlX2xhYmVscyA9ICIlWSIpICsKICBteV90aGVtZQoKcDIgPC0gZ2dwbG90KGRhdGEgPSBwcmVkaWN0X3Rlc3QpICsKICBnZW9tX2xpbmUoYWVzKHggPSB0cywgeSA9IGFjdHVhbCwgIGNvbG9yID0gIkFjdHVhbCIpKSArCiAgZ2VvbV9saW5lKGFlcyh4ID0gdHMsIHkgPSBtMl9wcmVkaWN0LCBjb2xvciA9ICJQcmVkaWN0ZWQiKSkgKwogIHNjYWxlX2NvbG9yX21hbnVhbCgKICAgIG5hbWUgPSBOVUxMLAogICAgdmFsdWVzID0gYygiQWN0dWFsIiA9ICJncmV5IiwKICAgICAgICAgICAgICAgIlByZWRpY3RlZCIgPSAiYmx1ZSIpCiAgKSArCiAgZ2d0aXRsZSgiRGV0ZXJtaW5pc3RpYyBUcmVuZCAmIFNlYXNvbmFsaXR5IChGb3VyaWVyKSIpICsKICB4bGFiKCIiKSArIHlsYWIoIiIpICsKICBzY2FsZV94X2RhdGV0aW1lKGRhdGVfYnJlYWtzID0gIjMgeWVhciIsIGRhdGVfbGFiZWxzID0gIiVZIikgKwogIG15X3RoZW1lCgpwMyA8LSBnZ3Bsb3QoZGF0YSA9IHByZWRpY3RfdGVzdCkgKwogIGdlb21fbGluZShhZXMoeCA9IHRzLCB5ID0gYWN0dWFsLCAgY29sb3IgPSAiQWN0dWFsIikpICsKICBnZW9tX2xpbmUoYWVzKHggPSB0cywgeSA9IG0zX3ByZWRpY3QsIGNvbG9yID0gIlByZWRpY3RlZCIpKSArCiAgc2NhbGVfY29sb3JfbWFudWFsKAogICAgbmFtZSA9IE5VTEwsCiAgICB2YWx1ZXMgPSBjKCJBY3R1YWwiID0gImdyZXkiLAogICAgICAgICAgICAgICAiUHJlZGljdGVkIiA9ICJicm93biIpCiAgKSArCiAgZ2d0aXRsZSgiU3RvY2hhc3RpYyBUcmVuZCAmIERldGVybWluaXN0aWMgU2Vhc29uYWxpdHkgKER1bW15KSIpICsKICB4bGFiKCIiKSArIHlsYWIoIiIpICsKICBzY2FsZV94X2RhdGV0aW1lKGRhdGVfYnJlYWtzID0gIjMgeWVhciIsIGRhdGVfbGFiZWxzID0gIiVZIikgKwogIG15X3RoZW1lCgpwNCA8LSBnZ3Bsb3QoZGF0YSA9IHByZWRpY3RfdGVzdCkgKwogIGdlb21fbGluZShhZXMoeCA9IHRzLCB5ID0gYWN0dWFsLCAgY29sb3IgPSAiQWN0dWFsIikpICsKICBnZW9tX2xpbmUoYWVzKHggPSB0cywgeSA9IG00X3ByZWRpY3QsIGNvbG9yID0gIlByZWRpY3RlZCIpKSArCiAgc2NhbGVfY29sb3JfbWFudWFsKAogICAgbmFtZSA9IE5VTEwsCiAgICB2YWx1ZXMgPSBjKCJBY3R1YWwiID0gImdyZXkiLAogICAgICAgICAgICAgICAiUHJlZGljdGVkIiA9ICJwdXJwbGUiKQogICkgKwogIGdndGl0bGUoIlN0b2NoYXN0aWMgVHJlbmQgJiBEZXRlcm1pbmlzdGljIFNlYXNvbmFsaXR5IChGb3VyaWVyKSIpICsKICB4bGFiKCIiKSArIHlsYWIoIiIpICsKICBzY2FsZV94X2RhdGV0aW1lKGRhdGVfYnJlYWtzID0gIjMgeWVhciIsIGRhdGVfbGFiZWxzID0gIiVZIikgKwogIG15X3RoZW1lCgpwNSA8LSBnZ3Bsb3QoZGF0YSA9IHByZWRpY3RfdGVzdCkgKwogIGdlb21fbGluZShhZXMoeCA9IHRzLCB5ID0gYWN0dWFsLCAgY29sb3IgPSAiQWN0dWFsIikpICsKICBnZW9tX2xpbmUoYWVzKHggPSB0cywgeSA9IG01X3ByZWRpY3QsIGNvbG9yID0gIlByZWRpY3RlZCIpKSArCiAgc2NhbGVfY29sb3JfbWFudWFsKAogICAgbmFtZSA9IE5VTEwsCiAgICB2YWx1ZXMgPSBjKCJBY3R1YWwiID0gImdyZXkiLAogICAgICAgICAgICAgICAiUHJlZGljdGVkIiA9ICJncmVlbjQiKQogICkgKwogIGdndGl0bGUoIkRldGVybWluaXN0aWMgVHJlbmQgJiBTdG9jaGFzdGljIFNlYXNvbmFsaXR5IikgKwogIHhsYWIoIiIpICsgeWxhYigiIikgKwogIHNjYWxlX3hfZGF0ZXRpbWUoZGF0ZV9icmVha3MgPSAiMyB5ZWFyIiwgZGF0ZV9sYWJlbHMgPSAiJVkiKSArCiAgbXlfdGhlbWUKCnA2IDwtIGdncGxvdChkYXRhID0gcHJlZGljdF90ZXN0KSArCiAgZ2VvbV9saW5lKGFlcyh4ID0gdHMsIHkgPSBhY3R1YWwsICBjb2xvciA9ICJBY3R1YWwiKSkgKwogIGdlb21fbGluZShhZXMoeCA9IHRzLCB5ID0gbTZfcHJlZGljdCwgY29sb3IgPSAiUHJlZGljdGVkIikpICsKICBzY2FsZV9jb2xvcl9tYW51YWwoCiAgICBuYW1lID0gTlVMTCwKICAgIHZhbHVlcyA9IGMoIkFjdHVhbCIgPSAiZ3JleSIsCiAgICAgICAgICAgICAgICJQcmVkaWN0ZWQiID0gIm9yYW5nZSIpCiAgKSArCiAgZ2d0aXRsZSgiU3RvY2hhc3RpYyBUcmVuZCAmIFNlYXNvbmFsaXR5IikgKwogIHhsYWIoIiIpICsgeWxhYigiIikgKwogIHNjYWxlX3hfZGF0ZXRpbWUoZGF0ZV9icmVha3MgPSAiMyB5ZWFyIiwgZGF0ZV9sYWJlbHMgPSAiJVkiKSArCiAgbXlfdGhlbWUKCmdyaWQuYXJyYW5nZShwMSxwMiwgcDMsIHA0LCBwNSwgcDYsIG5jb2w9MikKYGBgCgoKIyMgTW9kZWwgRXZhbHVhdGlvbgoKIyMjIFRyYWluIFNldAoKYGBge3J9CnByZWRpY3RfdHJhaW4gJT4lCiAgc2VsZWN0KGVuZHNfd2l0aCgiX3ByZWRpY3QiKSkgJT4lICAgICAgICAgIAogIGltYXBfZGZyKH4gdGliYmxlKAogICAgTW9kZWwgPSAueSwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICBSTVNFICA9IHJtc2UgKHByZWRpY3RfdHJhaW4kYWN0dWFsLCAueCksCiAgICBNQVBFICA9IG1hcGUgKHByZWRpY3RfdHJhaW4kYWN0dWFsLCAueCksCiAgICBzTUFQRSA9IHNtYXBlKHByZWRpY3RfdHJhaW4kYWN0dWFsLCAueCkKICApKSAlPiUKICBtdXRhdGUoTW9kZWwgPSByZWNvZGUoTW9kZWwsCiAgICBtMV9wcmVkaWN0ID0gIkRldGVybWluaXN0aWMgVHJlbmQgJiBTZWFzb25hbGl0eSAoRHVtbXkpIiwKICAgIG0yX3ByZWRpY3QgPSAiRGV0ZXJtaW5pc3RpYyBUcmVuZCAmIFNlYXNvbmFsaXR5IChGb3VyaWVyKSIsCiAgICBtM19wcmVkaWN0ID0gIlN0b2NoYXN0aWMgVHJlbmQgJiBEZXRlcm1pbmlzdGljIFNlYXNvbmFsaXR5IChEdW1teSkiLAogICAgbTRfcHJlZGljdCA9ICJTdG9jaGFzdGljIFRyZW5kICYgRGV0ZXJtaW5pc3RpYyBTZWFzb25hbGl0eSAoRm91cmllcikiLAogICAgbTVfcHJlZGljdCA9ICJEZXRlcm1pbmlzdGljIFRyZW5kICYgU3RvY2hhc3RpYyBTZWFzb25hbGl0eSIsCiAgICBtNl9wcmVkaWN0ID0gIlN0b2NoYXN0aWMgVHJlbmQgJiBTZWFzb25hbGl0eSIsCiAgKSkKYGBgCgoKIyMjIFRlc3QgU2V0CgpgYGB7cn0KcHJlZGljdF90ZXN0ICU+JQogIHNlbGVjdChlbmRzX3dpdGgoIl9wcmVkaWN0IikpICU+JSAgICAgICAgICAKICBpbWFwX2Rmcih+IHRpYmJsZSgKICAgIE1vZGVsID0gLnksICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgUk1TRSAgPSBybXNlIChwcmVkaWN0X3Rlc3QkYWN0dWFsLCAueCksCiAgICBNQVBFICA9IG1hcGUgKHByZWRpY3RfdGVzdCRhY3R1YWwsIC54KSwKICAgIHNNQVBFID0gc21hcGUocHJlZGljdF90ZXN0JGFjdHVhbCwgLngpCiAgKSkgJT4lCiAgbXV0YXRlKE1vZGVsID0gcmVjb2RlKE1vZGVsLAogICAgbTFfcHJlZGljdCA9ICJEZXRlcm1pbmlzdGljIFRyZW5kICYgU2Vhc29uYWxpdHkgKER1bW15KSIsCiAgICBtMl9wcmVkaWN0ID0gIkRldGVybWluaXN0aWMgVHJlbmQgJiBTZWFzb25hbGl0eSAoRm91cmllcikiLAogICAgbTNfcHJlZGljdCA9ICJTdG9jaGFzdGljIFRyZW5kICYgRGV0ZXJtaW5pc3RpYyBTZWFzb25hbGl0eSAoRHVtbXkpIiwKICAgIG00X3ByZWRpY3QgPSAiU3RvY2hhc3RpYyBUcmVuZCAmIERldGVybWluaXN0aWMgU2Vhc29uYWxpdHkgKEZvdXJpZXIpIiwKICAgIG01X3ByZWRpY3QgPSAiRGV0ZXJtaW5pc3RpYyBUcmVuZCAmIFN0b2NoYXN0aWMgU2Vhc29uYWxpdHkiLAogICAgbTZfcHJlZGljdCA9ICJTdG9jaGFzdGljIFRyZW5kICYgU2Vhc29uYWxpdHkiLAogICkpCmBgYAoKCgoK