Load dataset
df_raw <- read_excel("Data Awal dan Hasil Imputasi rev.xlsx", sheet = 2) %>%
mutate(Jam=as_hms(Jam), week = rep(1:51,each=336)[1:16992],
time=seq(ymd_hm("2018-1-1 0:00"), ymd_hm("2018-12-20 23:30"), by = 30*60),
month=month(time), wday=wday(time),day=day(time),
hour=as_hms(time), yday=yday(time),
wtime=rep(seq(ymd_hm("2018-1-1 0:00"),
ymd_hm("2018-1-7 23:30"),
by = 30*60),51)[1:16992])
head(df_raw)
tail(df_raw)
dim(df_raw)
[1] 16992 23
Number of missing value for each dataset
Missing value
|
|
SUF1_CO |
1930 |
SUF7_CO |
628 |
SUF1_NO2 |
2426 |
SUF7_NO2 |
866 |
SUF1_O3 |
474 |
SUF7_O3 |
665 |
SUF1_PM10 |
7621 |
SUF7_PM10 |
2198 |
SUF1_SO2 |
1318 |
Percentage of missing value in SUF 1 dataset
|
|
SUF1_CO |
11.4% |
SUF1_NO2 |
14.3% |
SUF1_O3 |
2.8% |
SUF1_PM10 |
44.9% |
SUF1_SO2 |
7.8% |
Percentage of missing value in SUF 7 dataset
|
|
SUF7_CO |
3.70% |
SUF7_NO2 |
5.10% |
SUF7_O3 |
3.91% |
SUF7_PM10 |
12.94% |
SUF7_SO2 |
9.58% |
var_pollutant <- colnames(df_raw)[6:15]
var_pollutant
[1] "SUF1_CO" "SUF7_CO" "SUF1_NO2" "SUF7_NO2" "SUF1_O3" "SUF7_O3" "SUF1_PM10" "SUF7_PM10" "SUF1_SO2" "SUF7_SO2"
Exploratory Analysis
Time Series Plot
p <- list()
for (i in 1:10){
p[[i]] <- ggplot(df_raw, aes_(x=~time, y=as.name(var_pollutant[i]))) +
geom_line() + xlab("") +
scale_x_datetime(date_breaks = "2 month", date_labels = "%b")
}
grid.arrange(p[[1]], p[[3]], p[[5]],
p[[7]], p[[9]], ncol=2, top="Time Series Plot on SUF 1")

grid.arrange(p[[2]], p[[4]], p[[6]],
p[[8]], p[[10]], ncol=2, top="Time Series Plot on SUF 7")

Daily Time Series
p <- list()
for (i in 1:10){
p[[i]] <- ggplot(df_raw, aes_(x=~hour, y=as.name(var_pollutant[i]), group=~yday)) +
geom_line() + xlab("") +
scale_x_time(labels = label_time(format = '%H:%M'),
breaks=hms(hours = seq(0, 24, 4)))
}
grid.arrange(p[[1]], p[[3]], p[[5]],
p[[7]], p[[9]], ncol=2, top="Daily Time Series Plot on SUF 1")

grid.arrange(p[[2]], p[[4]], p[[6]],
p[[8]], p[[10]], ncol=2, top="Daily Time Series Plot on SUF 7")

Weekly Time Series
p <- list()
for (i in 1:10){
p[[i]] <- ggplot(df_raw, aes_(x=~wtime, y=as.name(var_pollutant[i]), group=~week)) +
geom_line() + xlab("") + scale_x_datetime(date_breaks = "1 day", date_labels = "%a")
}
grid.arrange(p[[1]], p[[3]], p[[5]],
p[[7]], p[[10]], ncol=2, top="Weekly Time Series Plot on SUF 1")

grid.arrange(p[[2]], p[[4]], p[[6]],
p[[8]], p[[10]], ncol=2, top="Weekly Time Series Plot on SUF 7")

Imputation
df <- list()
df[["na"]] <- data.frame(is.na(df_raw))
df[["impute_1"]] <- df_raw %>%
group_by(Hari, J) %>%
mutate_if(is.double,~replace_na(.,median(., na.rm = TRUE))) %>%
ungroup()
`mutate_if()` ignored the following grouping variables:
• Columns `Hari`, `J`
df[["impute_2"]] <- df_raw %>%
group_by(Hari, J) %>%
mutate_if(is.double,~replace_na(.,mean(., na.rm = TRUE))) %>%
ungroup()
`mutate_if()` ignored the following grouping variables:
• Columns `Hari`, `J`
df[["impute_3"]] <- df_raw %>%
group_by(Hari, J) %>%
mutate_if(is.double,~na_interpolation(., option="linear")) %>%
ungroup()
`mutate_if()` ignored the following grouping variables:
• Columns `Hari`, `J`
df[["impute_4"]] <- df_raw %>%
group_by(Hari, J) %>%
mutate_if(is.double,~na_ma(.)) %>%
ungroup()
`mutate_if()` ignored the following grouping variables:
• Columns `Hari`, `J`
CO
p1 <- ggplot(data = df[["impute_1"]] %>% mutate(missing=df[["na"]]$SUF1_CO),
aes(x=time,y=SUF1_CO, color=missing)) +
geom_line(aes(group=1)) + xlab("") + ggtitle("Median Imputation") +
scale_x_datetime(date_breaks = "1 month", date_labels = "%b")
p2 <- ggplot(data = df[["impute_2"]] %>% mutate(missing=df[["na"]]$SUF1_CO),
aes(x=time,y=SUF1_CO, color=missing)) +
geom_line(aes(group=1)) + xlab("") + ggtitle("Mean Imputation") +
scale_x_datetime(date_breaks = "1 month", date_labels = "%b")
p3 <- ggplot(data = df[["impute_3"]] %>% mutate(missing=df[["na"]]$SUF1_CO),
aes(x=time,y=SUF1_CO, color=missing)) +
geom_line(aes(group=1)) + xlab("") + ggtitle("Linear Interpolation Imputation") +
scale_x_datetime(date_breaks = "1 month", date_labels = "%b")
p4 <- ggplot(data = df[["impute_4"]] %>% mutate(missing=df[["na"]]$SUF1_CO),
aes(x=time,y=SUF1_CO, color=missing)) +
geom_line(aes(group=1)) + xlab("") + ggtitle("Moving Average Imputation") +
scale_x_datetime(date_breaks = "1 month", date_labels = "%b")
grid.arrange(p1,p2,p3,p4,ncol=1)

p1 <- ggplot(data = df[["impute_1"]] %>% mutate(missing=df[["na"]]$SUF7_CO),
aes(x=time,y=SUF7_CO, color=missing)) +
geom_line(aes(group=1)) + xlab("") + ggtitle("Median Imputation") +
scale_x_datetime(date_breaks = "1 month", date_labels = "%b")
p2 <- ggplot(data = df[["impute_2"]] %>% mutate(missing=df[["na"]]$SUF7_CO),
aes(x=time,y=SUF7_CO, color=missing)) +
geom_line(aes(group=1)) + xlab("") + ggtitle("Mean Imputation") +
scale_x_datetime(date_breaks = "1 month", date_labels = "%b")
p3 <- ggplot(data = df[["impute_3"]] %>% mutate(missing=df[["na"]]$SUF7_CO),
aes(x=time,y=SUF7_CO, color=missing)) +
geom_line(aes(group=1)) + xlab("") + ggtitle("Linear Interpolation Imputation") +
scale_x_datetime(date_breaks = "1 month", date_labels = "%b")
p4 <- ggplot(data = df[["impute_4"]] %>% mutate(missing=df[["na"]]$SUF7_CO),
aes(x=time,y=SUF7_CO, color=missing)) +
geom_line(aes(group=1)) + xlab("") + ggtitle("Moving Average Imputation") +
scale_x_datetime(date_breaks = "1 month", date_labels = "%b")
grid.arrange(p1,p2,p3,p4,ncol=1)

NO2
p1 <- ggplot(data = df[["impute_1"]] %>% mutate(missing=df[["na"]]$SUF1_NO2),
aes(x=time,y=SUF1_NO2, color=missing)) +
geom_line(aes(group=1)) + xlab("") + ggtitle("Median Imputation") +
scale_x_datetime(date_breaks = "1 month", date_labels = "%b")
p2 <- ggplot(data = df[["impute_2"]] %>% mutate(missing=df[["na"]]$SUF1_NO2),
aes(x=time,y=SUF1_NO2, color=missing)) +
geom_line(aes(group=1)) + xlab("") + ggtitle("Mean Imputation") +
scale_x_datetime(date_breaks = "1 month", date_labels = "%b")
p3 <- ggplot(data = df[["impute_3"]] %>% mutate(missing=df[["na"]]$SUF1_NO2),
aes(x=time,y=SUF1_NO2, color=missing)) +
geom_line(aes(group=1)) + xlab("") + ggtitle("Linear Interpolation Imputation") +
scale_x_datetime(date_breaks = "1 month", date_labels = "%b")
p4 <- ggplot(data = df[["impute_4"]] %>% mutate(missing=df[["na"]]$SUF1_NO2),
aes(x=time,y=SUF1_NO2, color=missing)) +
geom_line(aes(group=1)) + xlab("") + ggtitle("Moving Average Imputation") +
scale_x_datetime(date_breaks = "1 month", date_labels = "%b")
grid.arrange(p1,p2,p3,p4,ncol=1)

p1 <- ggplot(data = df[["impute_1"]] %>% mutate(missing=df[["na"]]$SUF7_NO2),
aes(x=time,y=SUF7_NO2, color=missing)) +
geom_line(aes(group=1)) + xlab("") + ggtitle("Median Imputation") +
scale_x_datetime(date_breaks = "1 month", date_labels = "%b")
p2 <- ggplot(data = df[["impute_2"]] %>% mutate(missing=df[["na"]]$SUF7_NO2),
aes(x=time,y=SUF7_NO2, color=missing)) +
geom_line(aes(group=1)) + xlab("") + ggtitle("Mean Imputation") +
scale_x_datetime(date_breaks = "1 month", date_labels = "%b")
p3 <- ggplot(data = df[["impute_3"]] %>% mutate(missing=df[["na"]]$SUF7_NO2),
aes(x=time,y=SUF7_NO2, color=missing)) +
geom_line(aes(group=1)) + xlab("") + ggtitle("Linear Interpolation Imputation") +
scale_x_datetime(date_breaks = "1 month", date_labels = "%b")
p4 <- ggplot(data = df[["impute_4"]] %>% mutate(missing=df[["na"]]$SUF7_NO2),
aes(x=time,y=SUF7_NO2, color=missing)) +
geom_line(aes(group=1)) + xlab("") + ggtitle("Moving Average Imputation") +
scale_x_datetime(date_breaks = "1 month", date_labels = "%b")
grid.arrange(p1,p2,p3,p4,ncol=1)

O3
p1 <- ggplot(data = df[["impute_1"]] %>% mutate(missing=df[["na"]]$SUF1_O3),
aes(x=time,y=SUF1_O3, color=missing)) +
geom_line(aes(group=1)) + xlab("") + ggtitle("Median Imputation") +
scale_x_datetime(date_breaks = "1 month", date_labels = "%b")
p2 <- ggplot(data = df[["impute_2"]] %>% mutate(missing=df[["na"]]$SUF1_O3),
aes(x=time,y=SUF1_O3, color=missing)) +
geom_line(aes(group=1)) + xlab("") + ggtitle("Mean Imputation") +
scale_x_datetime(date_breaks = "1 month", date_labels = "%b")
p3 <- ggplot(data = df[["impute_3"]] %>% mutate(missing=df[["na"]]$SUF1_O3),
aes(x=time,y=SUF1_O3, color=missing)) +
geom_line(aes(group=1)) + xlab("") + ggtitle("Linear Interpolation Imputation") +
scale_x_datetime(date_breaks = "1 month", date_labels = "%b")
p4 <- ggplot(data = df[["impute_4"]] %>% mutate(missing=df[["na"]]$SUF1_O3),
aes(x=time,y=SUF1_O3, color=missing)) +
geom_line(aes(group=1)) + xlab("") + ggtitle("Moving Average Imputation") +
scale_x_datetime(date_breaks = "1 month", date_labels = "%b")
grid.arrange(p1,p2,p3,p4,ncol=1)

p1 <- ggplot(data = df[["impute_1"]] %>% mutate(missing=df[["na"]]$SUF7_O3),
aes(x=time,y=SUF7_O3, color=missing)) +
geom_line(aes(group=1)) + xlab("") + ggtitle("Median Imputation") +
scale_x_datetime(date_breaks = "1 month", date_labels = "%b")
p2 <- ggplot(data = df[["impute_2"]] %>% mutate(missing=df[["na"]]$SUF7_O3),
aes(x=time,y=SUF7_O3, color=missing)) +
geom_line(aes(group=1)) + xlab("") + ggtitle("Mean Imputation") +
scale_x_datetime(date_breaks = "1 month", date_labels = "%b")
p3 <- ggplot(data = df[["impute_3"]] %>% mutate(missing=df[["na"]]$SUF7_O3),
aes(x=time,y=SUF7_O3, color=missing)) +
geom_line(aes(group=1)) + xlab("") + ggtitle("Linear Interpolation Imputation") +
scale_x_datetime(date_breaks = "1 month", date_labels = "%b")
p4 <- ggplot(data = df[["impute_4"]] %>% mutate(missing=df[["na"]]$SUF7_O3),
aes(x=time,y=SUF7_O3, color=missing)) +
geom_line(aes(group=1)) + xlab("") + ggtitle("Moving Average Imputation") +
scale_x_datetime(date_breaks = "1 month", date_labels = "%b")
grid.arrange(p1,p2,p3,p4,ncol=1)

PM10
p1 <- ggplot(data = df[["impute_1"]] %>% mutate(missing=df[["na"]]$SUF1_PM10),
aes(x=time,y=SUF1_PM10, color=missing)) +
geom_line(aes(group=1)) + xlab("") + ggtitle("Median Imputation") +
scale_x_datetime(date_breaks = "1 month", date_labels = "%b")
p2 <- ggplot(data = df[["impute_2"]] %>% mutate(missing=df[["na"]]$SUF1_PM10),
aes(x=time,y=SUF1_PM10, color=missing)) +
geom_line(aes(group=1)) + xlab("") + ggtitle("Mean Imputation") +
scale_x_datetime(date_breaks = "1 month", date_labels = "%b")
p3 <- ggplot(data = df[["impute_3"]] %>% mutate(missing=df[["na"]]$SUF1_PM10),
aes(x=time,y=SUF1_PM10, color=missing)) +
geom_line(aes(group=1)) + xlab("") + ggtitle("Linear Interpolation Imputation") +
scale_x_datetime(date_breaks = "1 month", date_labels = "%b")
p4 <- ggplot(data = df[["impute_4"]] %>% mutate(missing=df[["na"]]$SUF1_PM10),
aes(x=time,y=SUF1_PM10, color=missing)) +
geom_line(aes(group=1)) + xlab("") + ggtitle("Moving Average Imputation") +
scale_x_datetime(date_breaks = "1 month", date_labels = "%b")
grid.arrange(p1,p2,p3,p4,ncol=1)

p1 <- ggplot(data = df[["impute_1"]] %>% mutate(missing=df[["na"]]$SUF7_PM10),
aes(x=time,y=SUF7_PM10, color=missing)) +
geom_line(aes(group=1)) + xlab("") + ggtitle("Median Imputation") +
scale_x_datetime(date_breaks = "1 month", date_labels = "%b")
p2 <- ggplot(data = df[["impute_2"]] %>% mutate(missing=df[["na"]]$SUF7_PM10),
aes(x=time,y=SUF7_PM10, color=missing)) +
geom_line(aes(group=1)) + xlab("") + ggtitle("Mean Imputation") +
scale_x_datetime(date_breaks = "1 month", date_labels = "%b")
p3 <- ggplot(data = df[["impute_3"]] %>% mutate(missing=df[["na"]]$SUF7_PM10),
aes(x=time,y=SUF7_PM10, color=missing)) +
geom_line(aes(group=1)) + xlab("") + ggtitle("Linear Interpolation Imputation") +
scale_x_datetime(date_breaks = "1 month", date_labels = "%b")
p4 <- ggplot(data = df[["impute_4"]] %>% mutate(missing=df[["na"]]$SUF7_PM10),
aes(x=time,y=SUF7_PM10, color=missing)) +
geom_line(aes(group=1)) + xlab("") + ggtitle("Moving Average Imputation") +
scale_x_datetime(date_breaks = "1 month", date_labels = "%b")
grid.arrange(p1,p2,p3,p4,ncol=1)

SO2
p1 <- ggplot(data = df[["impute_1"]] %>% mutate(missing=df[["na"]]$SUF1_SO2),
aes(x=time,y=SUF1_SO2, color=missing)) +
geom_line(aes(group=1)) + xlab("") + ggtitle("Median Imputation") +
scale_x_datetime(date_breaks = "1 month", date_labels = "%b")
p2 <- ggplot(data = df[["impute_2"]] %>% mutate(missing=df[["na"]]$SUF1_SO2),
aes(x=time,y=SUF1_SO2, color=missing)) +
geom_line(aes(group=1)) + xlab("") + ggtitle("Mean Imputation") +
scale_x_datetime(date_breaks = "1 month", date_labels = "%b")
p3 <- ggplot(data = df[["impute_3"]] %>% mutate(missing=df[["na"]]$SUF1_SO2),
aes(x=time,y=SUF1_SO2, color=missing)) +
geom_line(aes(group=1)) + xlab("") + ggtitle("Linear Interpolation Imputation") +
scale_x_datetime(date_breaks = "1 month", date_labels = "%b")
p4 <- ggplot(data = df[["impute_4"]] %>% mutate(missing=df[["na"]]$SUF1_SO2),
aes(x=time,y=SUF1_SO2, color=missing)) +
geom_line(aes(group=1)) + xlab("") + ggtitle("Moving Average Imputation") +
scale_x_datetime(date_breaks = "1 month", date_labels = "%b")
grid.arrange(p1,p2,p3,p4,ncol=1)

p1 <- ggplot(data = df[["impute_1"]] %>% mutate(missing=df[["na"]]$SUF7_SO2),
aes(x=time,y=SUF7_SO2, color=missing)) +
geom_line(aes(group=1)) + xlab("") + ggtitle("Median Imputation") +
scale_x_datetime(date_breaks = "1 month", date_labels = "%b")
p2 <- ggplot(data = df[["impute_2"]] %>% mutate(missing=df[["na"]]$SUF7_SO2),
aes(x=time,y=SUF7_SO2, color=missing)) +
geom_line(aes(group=1)) + xlab("") + ggtitle("Mean Imputation") +
scale_x_datetime(date_breaks = "1 month", date_labels = "%b")
p3 <- ggplot(data = df[["impute_3"]] %>% mutate(missing=df[["na"]]$SUF7_SO2),
aes(x=time,y=SUF7_SO2, color=missing)) +
geom_line(aes(group=1)) + xlab("") + ggtitle("Linear Interpolation Imputation") +
scale_x_datetime(date_breaks = "1 month", date_labels = "%b")
p4 <- ggplot(data = df[["impute_4"]] %>% mutate(missing=df[["na"]]$SUF7_SO2),
aes(x=time,y=SUF7_SO2, color=missing)) +
geom_line(aes(group=1)) + xlab("") + ggtitle("Moving Average Imputation") +
scale_x_datetime(date_breaks = "1 month", date_labels = "%b")
grid.arrange(p1,p2,p3,p4,ncol=1)

Modelling
Dummy variables
df[["dummy"]] <- dummy_cols(df_raw, select_columns = c("J","Hari")) %>%
mutate(t=seq_along(time)) %>%
select(starts_with("J_"), starts_with("Hari_"),t)
for (k in var_pollutant){
name <- paste0(k,"_imp_1")
df[[name]] <- bind_cols(df[["impute_1"]], df[["dummy"]]) %>%
select(time,starts_with(k), starts_with("J_"), starts_with("Hari_"),t)
name <- paste0(k,"_imp_2")
df[[name]] <- bind_cols(df[["impute_2"]], df[["dummy"]]) %>%
select(time,starts_with(k), starts_with("J_"), starts_with("Hari_"),t)
name <- paste0(k,"_imp_3")
df[[name]] <- bind_cols(df[["impute_3"]], df[["dummy"]]) %>%
select(time,starts_with(k), starts_with("J_"), starts_with("Hari_"),t)
name <- paste0(k,"_imp_4")
df[[name]] <- bind_cols(df[["impute_4"]], df[["dummy"]]) %>%
select(time,starts_with(k), starts_with("J_"), starts_with("Hari_"),t)
}
ind <- df_raw %>% make_ts_splits(.length_test = 48)
ind
split [16944|48|16992]
Model Fitting and Forecasting
applyForecast <- function(data){
ind <- data %>% make_ts_splits(.length_test = 48)
train <- data[ind$idx_train,]
test <- data[ind$idx_test,]
yy <- colnames(data)[2]
f <- paste0(yy,"~.-1-time-Hari_1")
m <- lm(f, data = train)
r.squared <- summary(m)$r.squared
pred <- m %>% predict(test)
RMSE <- rmse(test[yy] %>% pull(),pred)
MAPE <- mape(test[yy] %>% pull(),pred)
sMAPE <- smape(test[yy] %>% pull(),pred)
p_train <- ggplot(train %>% mutate(predicted=m$fitted.values)) +
geom_line(aes_(x=~time,y=as.name(yy))) +
geom_line(aes(x=time,y=predicted), color="red")
p_test <- ggplot(test %>% mutate(predicted=pred)) +
geom_line(aes_(x=~time,y=as.name(yy))) +
geom_line(aes(x=time,y=predicted), color="red")
results <- list(prediction=pred,
r.squared=r.squared,
RMSE=RMSE,
MAPE=MAPE,
sMAPE=sMAPE,
plot_train=p_train,
plot_test=p_test)
}
df_pollutant <- names(df)[grepl("imp_",names(df))]
res <- list()
for (name in df_pollutant){res[[name]] <- applyForecast(df[[name]])}
LS0tCnRpdGxlOiAiVGltZSBTZXJpZXMgSW1wdXRhdGlvbiIKb3V0cHV0OgogIGh0bWxfbm90ZWJvb2s6IAogICAgdG9jOiB5ZXMKICAgIHRvY19mbG9hdDoKICAgICAgdG9jX2NvbGxhcHNlZDogeWVzCmVkaXRvcl9vcHRpb25zOiAKICBjaHVua19vdXRwdXRfdHlwZTogaW5saW5lCi0tLQoKIyMgSW1wb3J0IGxpYnJhcnkKYGBge3IgZWNobz1UUlVFLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQpsaWJyYXJ5KHRpZHl2ZXJzZSkKbGlicmFyeShncmlkRXh0cmEpCmxpYnJhcnkocmVhZHhsKQpsaWJyYXJ5KGx1YnJpZGF0ZSkKbGlicmFyeShobXMpCmxpYnJhcnkoZm9yZWNhc3QpCmxpYnJhcnkoZmFzdER1bW1pZXMpCmxpYnJhcnkoaW1wdXRlVFMpCmxpYnJhcnkoc2NhbGVzKQpsaWJyYXJ5KGthYmxlRXh0cmEpCmxpYnJhcnkobW9kZWx0aW1lKQpsaWJyYXJ5KE1ldHJpY3MpCmBgYAoKIyMgTG9hZCBkYXRhc2V0CgpgYGB7cn0KZGZfcmF3IDwtIHJlYWRfZXhjZWwoIkRhdGEgQXdhbCBkYW4gSGFzaWwgSW1wdXRhc2kgcmV2Lnhsc3giLCBzaGVldCA9IDIpICU+JSAKICAgICAgICAgIG11dGF0ZShKYW09YXNfaG1zKEphbSksIHdlZWsgPSByZXAoMTo1MSxlYWNoPTMzNilbMToxNjk5Ml0sCiAgICAgICAgICAgICAgICAgdGltZT1zZXEoeW1kX2htKCIyMDE4LTEtMSAwOjAwIiksIHltZF9obSgiMjAxOC0xMi0yMCAyMzozMCIpLCBieSA9IDMwKjYwKSwKICAgICAgICAgICAgICAgICBtb250aD1tb250aCh0aW1lKSwgd2RheT13ZGF5KHRpbWUpLGRheT1kYXkodGltZSksIAogICAgICAgICAgICAgICAgIGhvdXI9YXNfaG1zKHRpbWUpLCB5ZGF5PXlkYXkodGltZSksCiAgICAgICAgICAgICAgICAgd3RpbWU9cmVwKHNlcSh5bWRfaG0oIjIwMTgtMS0xIDA6MDAiKSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB5bWRfaG0oIjIwMTgtMS03IDIzOjMwIiksIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnkgPSAzMCo2MCksNTEpWzE6MTY5OTJdKSAKaGVhZChkZl9yYXcpCmBgYAoKYGBge3J9CnRhaWwoZGZfcmF3KQpgYGAKCgpgYGB7cn0KZGltKGRmX3JhdykKYGBgCgpOdW1iZXIgb2YgbWlzc2luZyB2YWx1ZSBmb3IgZWFjaCBkYXRhc2V0CmBgYHtyIGVjaG89RkFMU0V9CmNvbFN1bXMoaXMubmEoZGZfcmF3KSlbNjoxNF0gJT4lCiAga2JsKGNhcHRpb24gPSAiTWlzc2luZyB2YWx1ZSIsIGNvbC5uYW1lcyA9ICIiKSAlPiUKICAga2FibGVfc3R5bGluZyhib290c3RyYXBfb3B0aW9ucyA9IGMoInN0cmlwZWQiLCAiaG92ZXIiLCAiY29uZGVuc2VkIiwgInJlc3BvbnNpdmUiKSwgCiAgICAgICAgICAgICAgICAgZnVsbF93aWR0aCA9IEYsIHBvc2l0aW9uID0gImxlZnQiKQpgYGAKCgpQZXJjZW50YWdlIG9mIG1pc3NpbmcgdmFsdWUgaW4gU1VGIDEgZGF0YXNldApgYGB7ciBlY2hvPUZBTFNFfQpsYWJlbF9wZXJjZW50KCkgKGNvbFN1bXMoaXMubmEoZGZfcmF3KSlbYyg2LDgsMTAsMTIsMTQpXS9kaW0oZGZfcmF3KVsxXSkgJT4lCiAga2JsKGNvbC5uYW1lcyA9ICIiKSAlPiUKICBrYWJsZV9zdHlsaW5nKGJvb3RzdHJhcF9vcHRpb25zID0gYygic3RyaXBlZCIsICJob3ZlciIsICJjb25kZW5zZWQiLCAicmVzcG9uc2l2ZSIpLCAKICAgICAgICAgICAgICAgIGZ1bGxfd2lkdGggPSBGLCBwb3NpdGlvbiA9ICJsZWZ0IikKYGBgCgpQZXJjZW50YWdlIG9mIG1pc3NpbmcgdmFsdWUgaW4gU1VGIDcgZGF0YXNldApgYGB7ciBlY2hvPUZBTFNFfQpsYWJlbF9wZXJjZW50KCkgKGNvbFN1bXMoaXMubmEoZGZfcmF3KSlbYyg3LDksMTEsMTMsMTUpXS9kaW0oZGZfcmF3KVsxXSkgJT4lCiAga2JsKGNvbC5uYW1lcyA9ICIiKSAlPiUKICBrYWJsZV9zdHlsaW5nKGJvb3RzdHJhcF9vcHRpb25zID0gYygic3RyaXBlZCIsICJob3ZlciIsICJjb25kZW5zZWQiLCAicmVzcG9uc2l2ZSIpLCAKICAgICAgICAgICAgICAgIGZ1bGxfd2lkdGggPSBGLCBwb3NpdGlvbiA9ICJsZWZ0IikKYGBgCgoKYGBge3J9CnZhcl9wb2xsdXRhbnQgPC0gY29sbmFtZXMoZGZfcmF3KVs2OjE1XQp2YXJfcG9sbHV0YW50CmBgYAoKIyMgRXhwbG9yYXRvcnkgQW5hbHlzaXMKCiMjIyBUaW1lIFNlcmllcyBQbG90CmBgYHtyfQpwIDwtIGxpc3QoKQpmb3IgKGkgaW4gMToxMCl7CiAgcFtbaV1dIDwtIGdncGxvdChkZl9yYXcsIGFlc18oeD1+dGltZSwgeT1hcy5uYW1lKHZhcl9wb2xsdXRhbnRbaV0pKSkgKwogICAgICAgICAgICAgIGdlb21fbGluZSgpICsgeGxhYigiIikgKwogICAgICAgICAgICAgIHNjYWxlX3hfZGF0ZXRpbWUoZGF0ZV9icmVha3MgPSAiMiBtb250aCIsIGRhdGVfbGFiZWxzID0gIiViIikKfQpgYGAKCgpgYGB7ciB3YXJuaW5nPUZBTFNFfQpncmlkLmFycmFuZ2UocFtbMV1dLCBwW1szXV0sIHBbWzVdXSwKICAgICAgICAgICAgIHBbWzddXSwgcFtbOV1dLCBuY29sPTIsIHRvcD0iVGltZSBTZXJpZXMgUGxvdCBvbiBTVUYgMSIpCmBgYAoKYGBge3Igd2FybmluZz1GQUxTRX0KZ3JpZC5hcnJhbmdlKHBbWzJdXSwgcFtbNF1dLCBwW1s2XV0sCiAgICAgICAgICAgICBwW1s4XV0sIHBbWzEwXV0sIG5jb2w9MiwgdG9wPSJUaW1lIFNlcmllcyBQbG90IG9uIFNVRiA3IikKYGBgCgojIyMgRGFpbHkgVGltZSBTZXJpZXMKYGBge3J9CnAgPC0gbGlzdCgpCmZvciAoaSBpbiAxOjEwKXsKICBwW1tpXV0gPC0gZ2dwbG90KGRmX3JhdywgYWVzXyh4PX5ob3VyLCB5PWFzLm5hbWUodmFyX3BvbGx1dGFudFtpXSksIGdyb3VwPX55ZGF5KSkgKwogICAgICAgICAgICAgIGdlb21fbGluZSgpICsgeGxhYigiIikgKyAKICAgICAgICAgICAgICBzY2FsZV94X3RpbWUobGFiZWxzID0gbGFiZWxfdGltZShmb3JtYXQgPSAnJUg6JU0nKSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrcz1obXMoaG91cnMgPSBzZXEoMCwgMjQsIDQpKSkKfQpgYGAKCgpgYGB7ciB3YXJuaW5nPUZBTFNFfQpncmlkLmFycmFuZ2UocFtbMV1dLCBwW1szXV0sIHBbWzVdXSwKICAgICAgICAgICAgIHBbWzddXSwgcFtbOV1dLCBuY29sPTIsIHRvcD0iRGFpbHkgVGltZSBTZXJpZXMgUGxvdCBvbiBTVUYgMSIpCmBgYAoKYGBge3Igd2FybmluZz1GQUxTRX0KZ3JpZC5hcnJhbmdlKHBbWzJdXSwgcFtbNF1dLCBwW1s2XV0sCiAgICAgICAgICAgICBwW1s4XV0sIHBbWzEwXV0sIG5jb2w9MiwgdG9wPSJEYWlseSBUaW1lIFNlcmllcyBQbG90IG9uIFNVRiA3IikKYGBgCgoKIyMjIFdlZWtseSBUaW1lIFNlcmllcwpgYGB7cn0KcCA8LSBsaXN0KCkKZm9yIChpIGluIDE6MTApewogIHBbW2ldXSA8LSBnZ3Bsb3QoZGZfcmF3LCBhZXNfKHg9fnd0aW1lLCB5PWFzLm5hbWUodmFyX3BvbGx1dGFudFtpXSksIGdyb3VwPX53ZWVrKSkgKwogICAgICAgICAgICAgIGdlb21fbGluZSgpICsgeGxhYigiIikgKyBzY2FsZV94X2RhdGV0aW1lKGRhdGVfYnJlYWtzID0gIjEgZGF5IiwgZGF0ZV9sYWJlbHMgPSAiJWEiKQp9CmBgYAoKCmBgYHtyIHdhcm5pbmc9RkFMU0V9CmdyaWQuYXJyYW5nZShwW1sxXV0sIHBbWzNdXSwgcFtbNV1dLAogICAgICAgICAgICAgcFtbN11dLCBwW1sxMF1dLCBuY29sPTIsIHRvcD0iV2Vla2x5IFRpbWUgU2VyaWVzIFBsb3Qgb24gU1VGIDEiKQpgYGAKCgoKYGBge3Igd2FybmluZz1GQUxTRX0KZ3JpZC5hcnJhbmdlKHBbWzJdXSwgcFtbNF1dLCBwW1s2XV0sCiAgICAgICAgICAgICBwW1s4XV0sIHBbWzEwXV0sIG5jb2w9MiwgdG9wPSJXZWVrbHkgVGltZSBTZXJpZXMgUGxvdCBvbiBTVUYgNyIpCmBgYAoKCiMjIEltcHV0YXRpb24KCgpgYGB7cn0KZGYgPC0gbGlzdCgpCmRmW1sibmEiXV0gPC0gZGF0YS5mcmFtZShpcy5uYShkZl9yYXcpKQpkZltbImltcHV0ZV8xIl1dIDwtIGRmX3JhdyAlPiUgCiAgICAgICAgICAgICAgICAgICAgZ3JvdXBfYnkoSGFyaSwgSikgJT4lIAogICAgICAgICAgICAgICAgICAgIG11dGF0ZV9pZihpcy5kb3VibGUsfnJlcGxhY2VfbmEoLixtZWRpYW4oLiwgbmEucm0gPSBUUlVFKSkpICU+JSAKICAgICAgICAgICAgICAgICAgICB1bmdyb3VwKCkKZGZbWyJpbXB1dGVfMiJdXSA8LSBkZl9yYXcgJT4lIAogICAgICAgICAgICAgICAgICAgIGdyb3VwX2J5KEhhcmksIEopICU+JSAKICAgICAgICAgICAgICAgICAgICBtdXRhdGVfaWYoaXMuZG91YmxlLH5yZXBsYWNlX25hKC4sbWVhbiguLCBuYS5ybSA9IFRSVUUpKSkgJT4lIAogICAgICAgICAgICAgICAgICAgIHVuZ3JvdXAoKQpkZltbImltcHV0ZV8zIl1dIDwtIGRmX3JhdyAlPiUgCiAgICAgICAgICAgICAgICAgICAgZ3JvdXBfYnkoSGFyaSwgSikgJT4lIAogICAgICAgICAgICAgICAgICAgIG11dGF0ZV9pZihpcy5kb3VibGUsfm5hX2ludGVycG9sYXRpb24oLiwgb3B0aW9uPSJsaW5lYXIiKSkgJT4lIAogICAgICAgICAgICAgICAgICAgIHVuZ3JvdXAoKQpkZltbImltcHV0ZV80Il1dIDwtIGRmX3JhdyAlPiUgCiAgICAgICAgICAgICAgICAgICAgZ3JvdXBfYnkoSGFyaSwgSikgJT4lIAogICAgICAgICAgICAgICAgICAgIG11dGF0ZV9pZihpcy5kb3VibGUsfm5hX21hKC4pKSAlPiUgCiAgICAgICAgICAgICAgICAgICAgdW5ncm91cCgpCmBgYAoKIyMjIENPCgpgYGB7ciwgZmlnLndpZHRoPTV9CnAxIDwtIGdncGxvdChkYXRhID0gZGZbWyJpbXB1dGVfMSJdXSAlPiUgbXV0YXRlKG1pc3Npbmc9ZGZbWyJuYSJdXSRTVUYxX0NPKSwgCiAgICAgICAgICAgICBhZXMoeD10aW1lLHk9U1VGMV9DTywgY29sb3I9bWlzc2luZykpICsgCiAgICAgIGdlb21fbGluZShhZXMoZ3JvdXA9MSkpICsgeGxhYigiIikgKyBnZ3RpdGxlKCJNZWRpYW4gSW1wdXRhdGlvbiIpICsKICAgICAgc2NhbGVfeF9kYXRldGltZShkYXRlX2JyZWFrcyA9ICIxIG1vbnRoIiwgZGF0ZV9sYWJlbHMgPSAiJWIiKQpwMiA8LSBnZ3Bsb3QoZGF0YSA9IGRmW1siaW1wdXRlXzIiXV0gJT4lIG11dGF0ZShtaXNzaW5nPWRmW1sibmEiXV0kU1VGMV9DTyksIAogICAgICAgICAgICAgYWVzKHg9dGltZSx5PVNVRjFfQ08sIGNvbG9yPW1pc3NpbmcpKSArIAogICAgICBnZW9tX2xpbmUoYWVzKGdyb3VwPTEpKSArIHhsYWIoIiIpICsgZ2d0aXRsZSgiTWVhbiBJbXB1dGF0aW9uIikgKwogICAgICBzY2FsZV94X2RhdGV0aW1lKGRhdGVfYnJlYWtzID0gIjEgbW9udGgiLCBkYXRlX2xhYmVscyA9ICIlYiIpCnAzIDwtIGdncGxvdChkYXRhID0gZGZbWyJpbXB1dGVfMyJdXSAlPiUgbXV0YXRlKG1pc3Npbmc9ZGZbWyJuYSJdXSRTVUYxX0NPKSwgCiAgICAgICAgICAgICBhZXMoeD10aW1lLHk9U1VGMV9DTywgY29sb3I9bWlzc2luZykpICsgCiAgICAgIGdlb21fbGluZShhZXMoZ3JvdXA9MSkpICsgeGxhYigiIikgKyBnZ3RpdGxlKCJMaW5lYXIgSW50ZXJwb2xhdGlvbiBJbXB1dGF0aW9uIikgKwogICAgICBzY2FsZV94X2RhdGV0aW1lKGRhdGVfYnJlYWtzID0gIjEgbW9udGgiLCBkYXRlX2xhYmVscyA9ICIlYiIpCnA0IDwtIGdncGxvdChkYXRhID0gZGZbWyJpbXB1dGVfNCJdXSAlPiUgbXV0YXRlKG1pc3Npbmc9ZGZbWyJuYSJdXSRTVUYxX0NPKSwgCiAgICAgICAgICAgICBhZXMoeD10aW1lLHk9U1VGMV9DTywgY29sb3I9bWlzc2luZykpICsgCiAgICAgIGdlb21fbGluZShhZXMoZ3JvdXA9MSkpICsgeGxhYigiIikgKyBnZ3RpdGxlKCJNb3ZpbmcgQXZlcmFnZSBJbXB1dGF0aW9uIikgKwogICAgICBzY2FsZV94X2RhdGV0aW1lKGRhdGVfYnJlYWtzID0gIjEgbW9udGgiLCBkYXRlX2xhYmVscyA9ICIlYiIpCmdyaWQuYXJyYW5nZShwMSxwMixwMyxwNCxuY29sPTEpCmBgYAoKCmBgYHtyLCBmaWcud2lkdGg9NX0KcDEgPC0gZ2dwbG90KGRhdGEgPSBkZltbImltcHV0ZV8xIl1dICU+JSBtdXRhdGUobWlzc2luZz1kZltbIm5hIl1dJFNVRjdfQ08pLCAKICAgICAgICAgICAgIGFlcyh4PXRpbWUseT1TVUY3X0NPLCBjb2xvcj1taXNzaW5nKSkgKyAKICAgICAgZ2VvbV9saW5lKGFlcyhncm91cD0xKSkgKyB4bGFiKCIiKSArIGdndGl0bGUoIk1lZGlhbiBJbXB1dGF0aW9uIikgKwogICAgICBzY2FsZV94X2RhdGV0aW1lKGRhdGVfYnJlYWtzID0gIjEgbW9udGgiLCBkYXRlX2xhYmVscyA9ICIlYiIpCnAyIDwtIGdncGxvdChkYXRhID0gZGZbWyJpbXB1dGVfMiJdXSAlPiUgbXV0YXRlKG1pc3Npbmc9ZGZbWyJuYSJdXSRTVUY3X0NPKSwgCiAgICAgICAgICAgICBhZXMoeD10aW1lLHk9U1VGN19DTywgY29sb3I9bWlzc2luZykpICsgCiAgICAgIGdlb21fbGluZShhZXMoZ3JvdXA9MSkpICsgeGxhYigiIikgKyBnZ3RpdGxlKCJNZWFuIEltcHV0YXRpb24iKSArCiAgICAgIHNjYWxlX3hfZGF0ZXRpbWUoZGF0ZV9icmVha3MgPSAiMSBtb250aCIsIGRhdGVfbGFiZWxzID0gIiViIikKcDMgPC0gZ2dwbG90KGRhdGEgPSBkZltbImltcHV0ZV8zIl1dICU+JSBtdXRhdGUobWlzc2luZz1kZltbIm5hIl1dJFNVRjdfQ08pLCAKICAgICAgICAgICAgIGFlcyh4PXRpbWUseT1TVUY3X0NPLCBjb2xvcj1taXNzaW5nKSkgKyAKICAgICAgZ2VvbV9saW5lKGFlcyhncm91cD0xKSkgKyB4bGFiKCIiKSArIGdndGl0bGUoIkxpbmVhciBJbnRlcnBvbGF0aW9uIEltcHV0YXRpb24iKSArCiAgICAgIHNjYWxlX3hfZGF0ZXRpbWUoZGF0ZV9icmVha3MgPSAiMSBtb250aCIsIGRhdGVfbGFiZWxzID0gIiViIikKcDQgPC0gZ2dwbG90KGRhdGEgPSBkZltbImltcHV0ZV80Il1dICU+JSBtdXRhdGUobWlzc2luZz1kZltbIm5hIl1dJFNVRjdfQ08pLCAKICAgICAgICAgICAgIGFlcyh4PXRpbWUseT1TVUY3X0NPLCBjb2xvcj1taXNzaW5nKSkgKyAKICAgICAgZ2VvbV9saW5lKGFlcyhncm91cD0xKSkgKyB4bGFiKCIiKSArIGdndGl0bGUoIk1vdmluZyBBdmVyYWdlIEltcHV0YXRpb24iKSArCiAgICAgIHNjYWxlX3hfZGF0ZXRpbWUoZGF0ZV9icmVha3MgPSAiMSBtb250aCIsIGRhdGVfbGFiZWxzID0gIiViIikKZ3JpZC5hcnJhbmdlKHAxLHAyLHAzLHA0LG5jb2w9MSkKYGBgCgoKCiMjIyBOTzIKCmBgYHtyLCBmaWcud2lkdGg9NX0KcDEgPC0gZ2dwbG90KGRhdGEgPSBkZltbImltcHV0ZV8xIl1dICU+JSBtdXRhdGUobWlzc2luZz1kZltbIm5hIl1dJFNVRjFfTk8yKSwgCiAgICAgICAgICAgICBhZXMoeD10aW1lLHk9U1VGMV9OTzIsIGNvbG9yPW1pc3NpbmcpKSArIAogICAgICBnZW9tX2xpbmUoYWVzKGdyb3VwPTEpKSArIHhsYWIoIiIpICsgZ2d0aXRsZSgiTWVkaWFuIEltcHV0YXRpb24iKSArCiAgICAgIHNjYWxlX3hfZGF0ZXRpbWUoZGF0ZV9icmVha3MgPSAiMSBtb250aCIsIGRhdGVfbGFiZWxzID0gIiViIikKcDIgPC0gZ2dwbG90KGRhdGEgPSBkZltbImltcHV0ZV8yIl1dICU+JSBtdXRhdGUobWlzc2luZz1kZltbIm5hIl1dJFNVRjFfTk8yKSwgCiAgICAgICAgICAgICBhZXMoeD10aW1lLHk9U1VGMV9OTzIsIGNvbG9yPW1pc3NpbmcpKSArIAogICAgICBnZW9tX2xpbmUoYWVzKGdyb3VwPTEpKSArIHhsYWIoIiIpICsgZ2d0aXRsZSgiTWVhbiBJbXB1dGF0aW9uIikgKwogICAgICBzY2FsZV94X2RhdGV0aW1lKGRhdGVfYnJlYWtzID0gIjEgbW9udGgiLCBkYXRlX2xhYmVscyA9ICIlYiIpCnAzIDwtIGdncGxvdChkYXRhID0gZGZbWyJpbXB1dGVfMyJdXSAlPiUgbXV0YXRlKG1pc3Npbmc9ZGZbWyJuYSJdXSRTVUYxX05PMiksIAogICAgICAgICAgICAgYWVzKHg9dGltZSx5PVNVRjFfTk8yLCBjb2xvcj1taXNzaW5nKSkgKyAKICAgICAgZ2VvbV9saW5lKGFlcyhncm91cD0xKSkgKyB4bGFiKCIiKSArIGdndGl0bGUoIkxpbmVhciBJbnRlcnBvbGF0aW9uIEltcHV0YXRpb24iKSArCiAgICAgIHNjYWxlX3hfZGF0ZXRpbWUoZGF0ZV9icmVha3MgPSAiMSBtb250aCIsIGRhdGVfbGFiZWxzID0gIiViIikKcDQgPC0gZ2dwbG90KGRhdGEgPSBkZltbImltcHV0ZV80Il1dICU+JSBtdXRhdGUobWlzc2luZz1kZltbIm5hIl1dJFNVRjFfTk8yKSwgCiAgICAgICAgICAgICBhZXMoeD10aW1lLHk9U1VGMV9OTzIsIGNvbG9yPW1pc3NpbmcpKSArIAogICAgICBnZW9tX2xpbmUoYWVzKGdyb3VwPTEpKSArIHhsYWIoIiIpICsgZ2d0aXRsZSgiTW92aW5nIEF2ZXJhZ2UgSW1wdXRhdGlvbiIpICsKICAgICAgc2NhbGVfeF9kYXRldGltZShkYXRlX2JyZWFrcyA9ICIxIG1vbnRoIiwgZGF0ZV9sYWJlbHMgPSAiJWIiKQpncmlkLmFycmFuZ2UocDEscDIscDMscDQsbmNvbD0xKQpgYGAKCgpgYGB7ciwgZmlnLndpZHRoPTV9CnAxIDwtIGdncGxvdChkYXRhID0gZGZbWyJpbXB1dGVfMSJdXSAlPiUgbXV0YXRlKG1pc3Npbmc9ZGZbWyJuYSJdXSRTVUY3X05PMiksIAogICAgICAgICAgICAgYWVzKHg9dGltZSx5PVNVRjdfTk8yLCBjb2xvcj1taXNzaW5nKSkgKyAKICAgICAgZ2VvbV9saW5lKGFlcyhncm91cD0xKSkgKyB4bGFiKCIiKSArIGdndGl0bGUoIk1lZGlhbiBJbXB1dGF0aW9uIikgKwogICAgICBzY2FsZV94X2RhdGV0aW1lKGRhdGVfYnJlYWtzID0gIjEgbW9udGgiLCBkYXRlX2xhYmVscyA9ICIlYiIpCnAyIDwtIGdncGxvdChkYXRhID0gZGZbWyJpbXB1dGVfMiJdXSAlPiUgbXV0YXRlKG1pc3Npbmc9ZGZbWyJuYSJdXSRTVUY3X05PMiksIAogICAgICAgICAgICAgYWVzKHg9dGltZSx5PVNVRjdfTk8yLCBjb2xvcj1taXNzaW5nKSkgKyAKICAgICAgZ2VvbV9saW5lKGFlcyhncm91cD0xKSkgKyB4bGFiKCIiKSArIGdndGl0bGUoIk1lYW4gSW1wdXRhdGlvbiIpICsKICAgICAgc2NhbGVfeF9kYXRldGltZShkYXRlX2JyZWFrcyA9ICIxIG1vbnRoIiwgZGF0ZV9sYWJlbHMgPSAiJWIiKQpwMyA8LSBnZ3Bsb3QoZGF0YSA9IGRmW1siaW1wdXRlXzMiXV0gJT4lIG11dGF0ZShtaXNzaW5nPWRmW1sibmEiXV0kU1VGN19OTzIpLCAKICAgICAgICAgICAgIGFlcyh4PXRpbWUseT1TVUY3X05PMiwgY29sb3I9bWlzc2luZykpICsgCiAgICAgIGdlb21fbGluZShhZXMoZ3JvdXA9MSkpICsgeGxhYigiIikgKyBnZ3RpdGxlKCJMaW5lYXIgSW50ZXJwb2xhdGlvbiBJbXB1dGF0aW9uIikgKwogICAgICBzY2FsZV94X2RhdGV0aW1lKGRhdGVfYnJlYWtzID0gIjEgbW9udGgiLCBkYXRlX2xhYmVscyA9ICIlYiIpCnA0IDwtIGdncGxvdChkYXRhID0gZGZbWyJpbXB1dGVfNCJdXSAlPiUgbXV0YXRlKG1pc3Npbmc9ZGZbWyJuYSJdXSRTVUY3X05PMiksIAogICAgICAgICAgICAgYWVzKHg9dGltZSx5PVNVRjdfTk8yLCBjb2xvcj1taXNzaW5nKSkgKyAKICAgICAgZ2VvbV9saW5lKGFlcyhncm91cD0xKSkgKyB4bGFiKCIiKSArIGdndGl0bGUoIk1vdmluZyBBdmVyYWdlIEltcHV0YXRpb24iKSArCiAgICAgIHNjYWxlX3hfZGF0ZXRpbWUoZGF0ZV9icmVha3MgPSAiMSBtb250aCIsIGRhdGVfbGFiZWxzID0gIiViIikKZ3JpZC5hcnJhbmdlKHAxLHAyLHAzLHA0LG5jb2w9MSkKYGBgCgojIyMgTzMKCmBgYHtyLCBmaWcud2lkdGg9NX0KcDEgPC0gZ2dwbG90KGRhdGEgPSBkZltbImltcHV0ZV8xIl1dICU+JSBtdXRhdGUobWlzc2luZz1kZltbIm5hIl1dJFNVRjFfTzMpLCAKICAgICAgICAgICAgIGFlcyh4PXRpbWUseT1TVUYxX08zLCBjb2xvcj1taXNzaW5nKSkgKyAKICAgICAgZ2VvbV9saW5lKGFlcyhncm91cD0xKSkgKyB4bGFiKCIiKSArIGdndGl0bGUoIk1lZGlhbiBJbXB1dGF0aW9uIikgKwogICAgICBzY2FsZV94X2RhdGV0aW1lKGRhdGVfYnJlYWtzID0gIjEgbW9udGgiLCBkYXRlX2xhYmVscyA9ICIlYiIpCnAyIDwtIGdncGxvdChkYXRhID0gZGZbWyJpbXB1dGVfMiJdXSAlPiUgbXV0YXRlKG1pc3Npbmc9ZGZbWyJuYSJdXSRTVUYxX08zKSwgCiAgICAgICAgICAgICBhZXMoeD10aW1lLHk9U1VGMV9PMywgY29sb3I9bWlzc2luZykpICsgCiAgICAgIGdlb21fbGluZShhZXMoZ3JvdXA9MSkpICsgeGxhYigiIikgKyBnZ3RpdGxlKCJNZWFuIEltcHV0YXRpb24iKSArCiAgICAgIHNjYWxlX3hfZGF0ZXRpbWUoZGF0ZV9icmVha3MgPSAiMSBtb250aCIsIGRhdGVfbGFiZWxzID0gIiViIikKcDMgPC0gZ2dwbG90KGRhdGEgPSBkZltbImltcHV0ZV8zIl1dICU+JSBtdXRhdGUobWlzc2luZz1kZltbIm5hIl1dJFNVRjFfTzMpLCAKICAgICAgICAgICAgIGFlcyh4PXRpbWUseT1TVUYxX08zLCBjb2xvcj1taXNzaW5nKSkgKyAKICAgICAgZ2VvbV9saW5lKGFlcyhncm91cD0xKSkgKyB4bGFiKCIiKSArIGdndGl0bGUoIkxpbmVhciBJbnRlcnBvbGF0aW9uIEltcHV0YXRpb24iKSArCiAgICAgIHNjYWxlX3hfZGF0ZXRpbWUoZGF0ZV9icmVha3MgPSAiMSBtb250aCIsIGRhdGVfbGFiZWxzID0gIiViIikKcDQgPC0gZ2dwbG90KGRhdGEgPSBkZltbImltcHV0ZV80Il1dICU+JSBtdXRhdGUobWlzc2luZz1kZltbIm5hIl1dJFNVRjFfTzMpLCAKICAgICAgICAgICAgIGFlcyh4PXRpbWUseT1TVUYxX08zLCBjb2xvcj1taXNzaW5nKSkgKyAKICAgICAgZ2VvbV9saW5lKGFlcyhncm91cD0xKSkgKyB4bGFiKCIiKSArIGdndGl0bGUoIk1vdmluZyBBdmVyYWdlIEltcHV0YXRpb24iKSArCiAgICAgIHNjYWxlX3hfZGF0ZXRpbWUoZGF0ZV9icmVha3MgPSAiMSBtb250aCIsIGRhdGVfbGFiZWxzID0gIiViIikKZ3JpZC5hcnJhbmdlKHAxLHAyLHAzLHA0LG5jb2w9MSkKYGBgCgoKYGBge3IsIGZpZy53aWR0aD01fQpwMSA8LSBnZ3Bsb3QoZGF0YSA9IGRmW1siaW1wdXRlXzEiXV0gJT4lIG11dGF0ZShtaXNzaW5nPWRmW1sibmEiXV0kU1VGN19PMyksIAogICAgICAgICAgICAgYWVzKHg9dGltZSx5PVNVRjdfTzMsIGNvbG9yPW1pc3NpbmcpKSArIAogICAgICBnZW9tX2xpbmUoYWVzKGdyb3VwPTEpKSArIHhsYWIoIiIpICsgZ2d0aXRsZSgiTWVkaWFuIEltcHV0YXRpb24iKSArCiAgICAgIHNjYWxlX3hfZGF0ZXRpbWUoZGF0ZV9icmVha3MgPSAiMSBtb250aCIsIGRhdGVfbGFiZWxzID0gIiViIikKcDIgPC0gZ2dwbG90KGRhdGEgPSBkZltbImltcHV0ZV8yIl1dICU+JSBtdXRhdGUobWlzc2luZz1kZltbIm5hIl1dJFNVRjdfTzMpLCAKICAgICAgICAgICAgIGFlcyh4PXRpbWUseT1TVUY3X08zLCBjb2xvcj1taXNzaW5nKSkgKyAKICAgICAgZ2VvbV9saW5lKGFlcyhncm91cD0xKSkgKyB4bGFiKCIiKSArIGdndGl0bGUoIk1lYW4gSW1wdXRhdGlvbiIpICsKICAgICAgc2NhbGVfeF9kYXRldGltZShkYXRlX2JyZWFrcyA9ICIxIG1vbnRoIiwgZGF0ZV9sYWJlbHMgPSAiJWIiKQpwMyA8LSBnZ3Bsb3QoZGF0YSA9IGRmW1siaW1wdXRlXzMiXV0gJT4lIG11dGF0ZShtaXNzaW5nPWRmW1sibmEiXV0kU1VGN19PMyksIAogICAgICAgICAgICAgYWVzKHg9dGltZSx5PVNVRjdfTzMsIGNvbG9yPW1pc3NpbmcpKSArIAogICAgICBnZW9tX2xpbmUoYWVzKGdyb3VwPTEpKSArIHhsYWIoIiIpICsgZ2d0aXRsZSgiTGluZWFyIEludGVycG9sYXRpb24gSW1wdXRhdGlvbiIpICsKICAgICAgc2NhbGVfeF9kYXRldGltZShkYXRlX2JyZWFrcyA9ICIxIG1vbnRoIiwgZGF0ZV9sYWJlbHMgPSAiJWIiKQpwNCA8LSBnZ3Bsb3QoZGF0YSA9IGRmW1siaW1wdXRlXzQiXV0gJT4lIG11dGF0ZShtaXNzaW5nPWRmW1sibmEiXV0kU1VGN19PMyksIAogICAgICAgICAgICAgYWVzKHg9dGltZSx5PVNVRjdfTzMsIGNvbG9yPW1pc3NpbmcpKSArIAogICAgICBnZW9tX2xpbmUoYWVzKGdyb3VwPTEpKSArIHhsYWIoIiIpICsgZ2d0aXRsZSgiTW92aW5nIEF2ZXJhZ2UgSW1wdXRhdGlvbiIpICsKICAgICAgc2NhbGVfeF9kYXRldGltZShkYXRlX2JyZWFrcyA9ICIxIG1vbnRoIiwgZGF0ZV9sYWJlbHMgPSAiJWIiKQpncmlkLmFycmFuZ2UocDEscDIscDMscDQsbmNvbD0xKQpgYGAKCiMjIyBQTTEwCmBgYHtyLCBmaWcud2lkdGg9NX0KcDEgPC0gZ2dwbG90KGRhdGEgPSBkZltbImltcHV0ZV8xIl1dICU+JSBtdXRhdGUobWlzc2luZz1kZltbIm5hIl1dJFNVRjFfUE0xMCksIAogICAgICAgICAgICAgYWVzKHg9dGltZSx5PVNVRjFfUE0xMCwgY29sb3I9bWlzc2luZykpICsgCiAgICAgIGdlb21fbGluZShhZXMoZ3JvdXA9MSkpICsgeGxhYigiIikgKyBnZ3RpdGxlKCJNZWRpYW4gSW1wdXRhdGlvbiIpICsKICAgICAgc2NhbGVfeF9kYXRldGltZShkYXRlX2JyZWFrcyA9ICIxIG1vbnRoIiwgZGF0ZV9sYWJlbHMgPSAiJWIiKQpwMiA8LSBnZ3Bsb3QoZGF0YSA9IGRmW1siaW1wdXRlXzIiXV0gJT4lIG11dGF0ZShtaXNzaW5nPWRmW1sibmEiXV0kU1VGMV9QTTEwKSwgCiAgICAgICAgICAgICBhZXMoeD10aW1lLHk9U1VGMV9QTTEwLCBjb2xvcj1taXNzaW5nKSkgKyAKICAgICAgZ2VvbV9saW5lKGFlcyhncm91cD0xKSkgKyB4bGFiKCIiKSArIGdndGl0bGUoIk1lYW4gSW1wdXRhdGlvbiIpICsKICAgICAgc2NhbGVfeF9kYXRldGltZShkYXRlX2JyZWFrcyA9ICIxIG1vbnRoIiwgZGF0ZV9sYWJlbHMgPSAiJWIiKQpwMyA8LSBnZ3Bsb3QoZGF0YSA9IGRmW1siaW1wdXRlXzMiXV0gJT4lIG11dGF0ZShtaXNzaW5nPWRmW1sibmEiXV0kU1VGMV9QTTEwKSwgCiAgICAgICAgICAgICBhZXMoeD10aW1lLHk9U1VGMV9QTTEwLCBjb2xvcj1taXNzaW5nKSkgKyAKICAgICAgZ2VvbV9saW5lKGFlcyhncm91cD0xKSkgKyB4bGFiKCIiKSArIGdndGl0bGUoIkxpbmVhciBJbnRlcnBvbGF0aW9uIEltcHV0YXRpb24iKSArCiAgICAgIHNjYWxlX3hfZGF0ZXRpbWUoZGF0ZV9icmVha3MgPSAiMSBtb250aCIsIGRhdGVfbGFiZWxzID0gIiViIikKcDQgPC0gZ2dwbG90KGRhdGEgPSBkZltbImltcHV0ZV80Il1dICU+JSBtdXRhdGUobWlzc2luZz1kZltbIm5hIl1dJFNVRjFfUE0xMCksIAogICAgICAgICAgICAgYWVzKHg9dGltZSx5PVNVRjFfUE0xMCwgY29sb3I9bWlzc2luZykpICsgCiAgICAgIGdlb21fbGluZShhZXMoZ3JvdXA9MSkpICsgeGxhYigiIikgKyBnZ3RpdGxlKCJNb3ZpbmcgQXZlcmFnZSBJbXB1dGF0aW9uIikgKwogICAgICBzY2FsZV94X2RhdGV0aW1lKGRhdGVfYnJlYWtzID0gIjEgbW9udGgiLCBkYXRlX2xhYmVscyA9ICIlYiIpCmdyaWQuYXJyYW5nZShwMSxwMixwMyxwNCxuY29sPTEpCmBgYAoKCmBgYHtyLCBmaWcud2lkdGg9NX0KcDEgPC0gZ2dwbG90KGRhdGEgPSBkZltbImltcHV0ZV8xIl1dICU+JSBtdXRhdGUobWlzc2luZz1kZltbIm5hIl1dJFNVRjdfUE0xMCksIAogICAgICAgICAgICAgYWVzKHg9dGltZSx5PVNVRjdfUE0xMCwgY29sb3I9bWlzc2luZykpICsgCiAgICAgIGdlb21fbGluZShhZXMoZ3JvdXA9MSkpICsgeGxhYigiIikgKyBnZ3RpdGxlKCJNZWRpYW4gSW1wdXRhdGlvbiIpICsKICAgICAgc2NhbGVfeF9kYXRldGltZShkYXRlX2JyZWFrcyA9ICIxIG1vbnRoIiwgZGF0ZV9sYWJlbHMgPSAiJWIiKQpwMiA8LSBnZ3Bsb3QoZGF0YSA9IGRmW1siaW1wdXRlXzIiXV0gJT4lIG11dGF0ZShtaXNzaW5nPWRmW1sibmEiXV0kU1VGN19QTTEwKSwgCiAgICAgICAgICAgICBhZXMoeD10aW1lLHk9U1VGN19QTTEwLCBjb2xvcj1taXNzaW5nKSkgKyAKICAgICAgZ2VvbV9saW5lKGFlcyhncm91cD0xKSkgKyB4bGFiKCIiKSArIGdndGl0bGUoIk1lYW4gSW1wdXRhdGlvbiIpICsKICAgICAgc2NhbGVfeF9kYXRldGltZShkYXRlX2JyZWFrcyA9ICIxIG1vbnRoIiwgZGF0ZV9sYWJlbHMgPSAiJWIiKQpwMyA8LSBnZ3Bsb3QoZGF0YSA9IGRmW1siaW1wdXRlXzMiXV0gJT4lIG11dGF0ZShtaXNzaW5nPWRmW1sibmEiXV0kU1VGN19QTTEwKSwgCiAgICAgICAgICAgICBhZXMoeD10aW1lLHk9U1VGN19QTTEwLCBjb2xvcj1taXNzaW5nKSkgKyAKICAgICAgZ2VvbV9saW5lKGFlcyhncm91cD0xKSkgKyB4bGFiKCIiKSArIGdndGl0bGUoIkxpbmVhciBJbnRlcnBvbGF0aW9uIEltcHV0YXRpb24iKSArCiAgICAgIHNjYWxlX3hfZGF0ZXRpbWUoZGF0ZV9icmVha3MgPSAiMSBtb250aCIsIGRhdGVfbGFiZWxzID0gIiViIikKcDQgPC0gZ2dwbG90KGRhdGEgPSBkZltbImltcHV0ZV80Il1dICU+JSBtdXRhdGUobWlzc2luZz1kZltbIm5hIl1dJFNVRjdfUE0xMCksIAogICAgICAgICAgICAgYWVzKHg9dGltZSx5PVNVRjdfUE0xMCwgY29sb3I9bWlzc2luZykpICsgCiAgICAgIGdlb21fbGluZShhZXMoZ3JvdXA9MSkpICsgeGxhYigiIikgKyBnZ3RpdGxlKCJNb3ZpbmcgQXZlcmFnZSBJbXB1dGF0aW9uIikgKwogICAgICBzY2FsZV94X2RhdGV0aW1lKGRhdGVfYnJlYWtzID0gIjEgbW9udGgiLCBkYXRlX2xhYmVscyA9ICIlYiIpCmdyaWQuYXJyYW5nZShwMSxwMixwMyxwNCxuY29sPTEpCmBgYAoKIyMjIFNPMgoKYGBge3IsIGZpZy53aWR0aD01fQpwMSA8LSBnZ3Bsb3QoZGF0YSA9IGRmW1siaW1wdXRlXzEiXV0gJT4lIG11dGF0ZShtaXNzaW5nPWRmW1sibmEiXV0kU1VGMV9TTzIpLCAKICAgICAgICAgICAgIGFlcyh4PXRpbWUseT1TVUYxX1NPMiwgY29sb3I9bWlzc2luZykpICsgCiAgICAgIGdlb21fbGluZShhZXMoZ3JvdXA9MSkpICsgeGxhYigiIikgKyBnZ3RpdGxlKCJNZWRpYW4gSW1wdXRhdGlvbiIpICsKICAgICAgc2NhbGVfeF9kYXRldGltZShkYXRlX2JyZWFrcyA9ICIxIG1vbnRoIiwgZGF0ZV9sYWJlbHMgPSAiJWIiKQpwMiA8LSBnZ3Bsb3QoZGF0YSA9IGRmW1siaW1wdXRlXzIiXV0gJT4lIG11dGF0ZShtaXNzaW5nPWRmW1sibmEiXV0kU1VGMV9TTzIpLCAKICAgICAgICAgICAgIGFlcyh4PXRpbWUseT1TVUYxX1NPMiwgY29sb3I9bWlzc2luZykpICsgCiAgICAgIGdlb21fbGluZShhZXMoZ3JvdXA9MSkpICsgeGxhYigiIikgKyBnZ3RpdGxlKCJNZWFuIEltcHV0YXRpb24iKSArCiAgICAgIHNjYWxlX3hfZGF0ZXRpbWUoZGF0ZV9icmVha3MgPSAiMSBtb250aCIsIGRhdGVfbGFiZWxzID0gIiViIikKcDMgPC0gZ2dwbG90KGRhdGEgPSBkZltbImltcHV0ZV8zIl1dICU+JSBtdXRhdGUobWlzc2luZz1kZltbIm5hIl1dJFNVRjFfU08yKSwgCiAgICAgICAgICAgICBhZXMoeD10aW1lLHk9U1VGMV9TTzIsIGNvbG9yPW1pc3NpbmcpKSArIAogICAgICBnZW9tX2xpbmUoYWVzKGdyb3VwPTEpKSArIHhsYWIoIiIpICsgZ2d0aXRsZSgiTGluZWFyIEludGVycG9sYXRpb24gSW1wdXRhdGlvbiIpICsKICAgICAgc2NhbGVfeF9kYXRldGltZShkYXRlX2JyZWFrcyA9ICIxIG1vbnRoIiwgZGF0ZV9sYWJlbHMgPSAiJWIiKQpwNCA8LSBnZ3Bsb3QoZGF0YSA9IGRmW1siaW1wdXRlXzQiXV0gJT4lIG11dGF0ZShtaXNzaW5nPWRmW1sibmEiXV0kU1VGMV9TTzIpLCAKICAgICAgICAgICAgIGFlcyh4PXRpbWUseT1TVUYxX1NPMiwgY29sb3I9bWlzc2luZykpICsgCiAgICAgIGdlb21fbGluZShhZXMoZ3JvdXA9MSkpICsgeGxhYigiIikgKyBnZ3RpdGxlKCJNb3ZpbmcgQXZlcmFnZSBJbXB1dGF0aW9uIikgKwogICAgICBzY2FsZV94X2RhdGV0aW1lKGRhdGVfYnJlYWtzID0gIjEgbW9udGgiLCBkYXRlX2xhYmVscyA9ICIlYiIpCmdyaWQuYXJyYW5nZShwMSxwMixwMyxwNCxuY29sPTEpCmBgYAoKCmBgYHtyLCBmaWcud2lkdGg9NX0KcDEgPC0gZ2dwbG90KGRhdGEgPSBkZltbImltcHV0ZV8xIl1dICU+JSBtdXRhdGUobWlzc2luZz1kZltbIm5hIl1dJFNVRjdfU08yKSwgCiAgICAgICAgICAgICBhZXMoeD10aW1lLHk9U1VGN19TTzIsIGNvbG9yPW1pc3NpbmcpKSArIAogICAgICBnZW9tX2xpbmUoYWVzKGdyb3VwPTEpKSArIHhsYWIoIiIpICsgZ2d0aXRsZSgiTWVkaWFuIEltcHV0YXRpb24iKSArCiAgICAgIHNjYWxlX3hfZGF0ZXRpbWUoZGF0ZV9icmVha3MgPSAiMSBtb250aCIsIGRhdGVfbGFiZWxzID0gIiViIikKcDIgPC0gZ2dwbG90KGRhdGEgPSBkZltbImltcHV0ZV8yIl1dICU+JSBtdXRhdGUobWlzc2luZz1kZltbIm5hIl1dJFNVRjdfU08yKSwgCiAgICAgICAgICAgICBhZXMoeD10aW1lLHk9U1VGN19TTzIsIGNvbG9yPW1pc3NpbmcpKSArIAogICAgICBnZW9tX2xpbmUoYWVzKGdyb3VwPTEpKSArIHhsYWIoIiIpICsgZ2d0aXRsZSgiTWVhbiBJbXB1dGF0aW9uIikgKwogICAgICBzY2FsZV94X2RhdGV0aW1lKGRhdGVfYnJlYWtzID0gIjEgbW9udGgiLCBkYXRlX2xhYmVscyA9ICIlYiIpCnAzIDwtIGdncGxvdChkYXRhID0gZGZbWyJpbXB1dGVfMyJdXSAlPiUgbXV0YXRlKG1pc3Npbmc9ZGZbWyJuYSJdXSRTVUY3X1NPMiksIAogICAgICAgICAgICAgYWVzKHg9dGltZSx5PVNVRjdfU08yLCBjb2xvcj1taXNzaW5nKSkgKyAKICAgICAgZ2VvbV9saW5lKGFlcyhncm91cD0xKSkgKyB4bGFiKCIiKSArIGdndGl0bGUoIkxpbmVhciBJbnRlcnBvbGF0aW9uIEltcHV0YXRpb24iKSArCiAgICAgIHNjYWxlX3hfZGF0ZXRpbWUoZGF0ZV9icmVha3MgPSAiMSBtb250aCIsIGRhdGVfbGFiZWxzID0gIiViIikKcDQgPC0gZ2dwbG90KGRhdGEgPSBkZltbImltcHV0ZV80Il1dICU+JSBtdXRhdGUobWlzc2luZz1kZltbIm5hIl1dJFNVRjdfU08yKSwgCiAgICAgICAgICAgICBhZXMoeD10aW1lLHk9U1VGN19TTzIsIGNvbG9yPW1pc3NpbmcpKSArIAogICAgICBnZW9tX2xpbmUoYWVzKGdyb3VwPTEpKSArIHhsYWIoIiIpICsgZ2d0aXRsZSgiTW92aW5nIEF2ZXJhZ2UgSW1wdXRhdGlvbiIpICsKICAgICAgc2NhbGVfeF9kYXRldGltZShkYXRlX2JyZWFrcyA9ICIxIG1vbnRoIiwgZGF0ZV9sYWJlbHMgPSAiJWIiKQpncmlkLmFycmFuZ2UocDEscDIscDMscDQsbmNvbD0xKQpgYGAKCiMjIE1vZGVsbGluZwoKIyMjIER1bW15IHZhcmlhYmxlcwpgYGB7ciB3YXJuaW5nPUZBTFNFfQpkZltbImR1bW15Il1dIDwtIGR1bW15X2NvbHMoZGZfcmF3LCBzZWxlY3RfY29sdW1ucyA9IGMoIkoiLCJIYXJpIikpICU+JSAKICAgICAgICAgICAgICAgICBtdXRhdGUodD1zZXFfYWxvbmcodGltZSkpICU+JSAKICAgICAgICAgICAgICAgICBzZWxlY3Qoc3RhcnRzX3dpdGgoIkpfIiksIHN0YXJ0c193aXRoKCJIYXJpXyIpLHQpCmBgYAoKCgpgYGB7cn0KZm9yIChrIGluIHZhcl9wb2xsdXRhbnQpewogIG5hbWUgPC0gcGFzdGUwKGssIl9pbXBfMSIpCiAgZGZbW25hbWVdXSA8LSBiaW5kX2NvbHMoZGZbWyJpbXB1dGVfMSJdXSwgZGZbWyJkdW1teSJdXSkgJT4lIAogICAgICAgICAgICAgICAgc2VsZWN0KHRpbWUsc3RhcnRzX3dpdGgoayksIHN0YXJ0c193aXRoKCJKXyIpLCBzdGFydHNfd2l0aCgiSGFyaV8iKSx0KQogIG5hbWUgPC0gcGFzdGUwKGssIl9pbXBfMiIpCiAgZGZbW25hbWVdXSA8LSBiaW5kX2NvbHMoZGZbWyJpbXB1dGVfMiJdXSwgZGZbWyJkdW1teSJdXSkgJT4lIAogICAgICAgICAgICAgICAgc2VsZWN0KHRpbWUsc3RhcnRzX3dpdGgoayksIHN0YXJ0c193aXRoKCJKXyIpLCBzdGFydHNfd2l0aCgiSGFyaV8iKSx0KQogIG5hbWUgPC0gcGFzdGUwKGssIl9pbXBfMyIpCiAgZGZbW25hbWVdXSA8LSBiaW5kX2NvbHMoZGZbWyJpbXB1dGVfMyJdXSwgZGZbWyJkdW1teSJdXSkgJT4lIAogICAgICAgICAgICAgICAgc2VsZWN0KHRpbWUsc3RhcnRzX3dpdGgoayksIHN0YXJ0c193aXRoKCJKXyIpLCBzdGFydHNfd2l0aCgiSGFyaV8iKSx0KQogIG5hbWUgPC0gcGFzdGUwKGssIl9pbXBfNCIpCiAgZGZbW25hbWVdXSA8LSBiaW5kX2NvbHMoZGZbWyJpbXB1dGVfNCJdXSwgZGZbWyJkdW1teSJdXSkgJT4lIAogICAgICAgICAgICAgICAgc2VsZWN0KHRpbWUsc3RhcnRzX3dpdGgoayksIHN0YXJ0c193aXRoKCJKXyIpLCBzdGFydHNfd2l0aCgiSGFyaV8iKSx0KQp9CmBgYAoKCmBgYHtyfQppbmQgPC0gZGZfcmF3ICU+JSBtYWtlX3RzX3NwbGl0cygubGVuZ3RoX3Rlc3QgPSA0OCkKaW5kCmBgYAoKCiMjIyBNb2RlbCBGaXR0aW5nIGFuZCBGb3JlY2FzdGluZwpgYGB7cn0KYXBwbHlGb3JlY2FzdCA8LSBmdW5jdGlvbihkYXRhKXsKICBpbmQgPC0gZGF0YSAlPiUgbWFrZV90c19zcGxpdHMoLmxlbmd0aF90ZXN0ID0gNDgpCiAgdHJhaW4gPC0gZGF0YVtpbmQkaWR4X3RyYWluLF0KICB0ZXN0ICA8LSBkYXRhW2luZCRpZHhfdGVzdCxdCiAgeXkgPC0gY29sbmFtZXMoZGF0YSlbMl0KICBmIDwtIHBhc3RlMCh5eSwifi4tMS10aW1lLUhhcmlfMSIpCiAgbSA8LSBsbShmLCBkYXRhID0gdHJhaW4pCiAgci5zcXVhcmVkIDwtIHN1bW1hcnkobSkkci5zcXVhcmVkCiAgcHJlZCA8LSBtICU+JSBwcmVkaWN0KHRlc3QpCiAgUk1TRSA8LSBybXNlKHRlc3RbeXldICU+JSBwdWxsKCkscHJlZCkKICBNQVBFIDwtIG1hcGUodGVzdFt5eV0gJT4lIHB1bGwoKSxwcmVkKQogIHNNQVBFIDwtIHNtYXBlKHRlc3RbeXldICU+JSBwdWxsKCkscHJlZCkKICBwX3RyYWluIDwtIGdncGxvdCh0cmFpbiAlPiUgbXV0YXRlKHByZWRpY3RlZD1tJGZpdHRlZC52YWx1ZXMpKSArIAogICAgICAgICAgICAgZ2VvbV9saW5lKGFlc18oeD1+dGltZSx5PWFzLm5hbWUoeXkpKSkgKyAgCiAgICAgICAgICAgICBnZW9tX2xpbmUoYWVzKHg9dGltZSx5PXByZWRpY3RlZCksIGNvbG9yPSJyZWQiKQogIHBfdGVzdCAgPC0gZ2dwbG90KHRlc3QgJT4lIG11dGF0ZShwcmVkaWN0ZWQ9cHJlZCkpICsgCiAgICAgICAgICAgICBnZW9tX2xpbmUoYWVzXyh4PX50aW1lLHk9YXMubmFtZSh5eSkpKSArICAKICAgICAgICAgICAgIGdlb21fbGluZShhZXMoeD10aW1lLHk9cHJlZGljdGVkKSwgY29sb3I9InJlZCIpCiAgcmVzdWx0cyA8LSBsaXN0KHByZWRpY3Rpb249cHJlZCwgCiAgICAgICAgICAgICAgICAgIHIuc3F1YXJlZD1yLnNxdWFyZWQsCiAgICAgICAgICAgICAgICAgIFJNU0U9Uk1TRSwKICAgICAgICAgICAgICAgICAgTUFQRT1NQVBFLAogICAgICAgICAgICAgICAgICBzTUFQRT1zTUFQRSwKICAgICAgICAgICAgICAgICAgcGxvdF90cmFpbj1wX3RyYWluLAogICAgICAgICAgICAgICAgICBwbG90X3Rlc3Q9cF90ZXN0KQp9CmBgYAoKCgoKYGBge3J9CmRmX3BvbGx1dGFudCA8LSBuYW1lcyhkZilbZ3JlcGwoImltcF8iLG5hbWVzKGRmKSldCnJlcyA8LSBsaXN0KCkKZm9yIChuYW1lIGluIGRmX3BvbGx1dGFudCl7cmVzW1tuYW1lXV0gPC0gYXBwbHlGb3JlY2FzdChkZltbbmFtZV1dKX0KYGBgCgoKIyMgRm9yZWNhc3QgQ29tcGFyaXNvbgpgYGB7cn0KZGQgPC0gYXNfdGliYmxlKHJlc1tbMV1dWzI6NV0pCmZvciAobmFtZSBpbiBkZl9wb2xsdXRhbnRbLTFdKXsKICBkZCA8LSBkZCAlPiUgYWRkX3Jvdyhhc190aWJibGUocmVzW1tuYW1lXV1bMjo1XSkpCn0KcmVzdWx0cyA8LSBkZCAlPiUgbXV0YXRlKG1vZGVsPWRmX3BvbGx1dGFudCkKYGBgCgoKIyMjIENPCmBgYHtyfQpyZXN1bHRzWzE6OCxdCmBgYAoKIyMjIE5PMgpgYGB7cn0KcmVzdWx0c1s5OjE2LF0KYGBgCgoKIyMjIE8zCmBgYHtyfQpyZXN1bHRzWzE3OjI0LF0KYGBgCgoKIyMjIFBNMTAKYGBge3J9CnJlc3VsdHNbMjU6MzIsXQpgYGAKCgojIyMgU08yCmBgYHtyfQpyZXN1bHRzWzMzOjQwLF0KYGBgCgoKCgoKCgoKCgoK