Load Packages

library(jsonlite)
library(tidyverse)
library(httr)
library(ggplot2)
library(patchwork)

Make an API call to the Department of Labor for the CPI and Unemployment rate for 2000-2020

url <- "https://api.bls.gov/publicAPI/v2/timeseries/data/"

payload <- toJSON(list(
  seriesid = list("CUSR0000SA0", "LNS14000000"),
  startyear = "2000",
  endyear = "2026",
  registrationkey = Sys.getenv("BLS_KEY")
), auto_unbox = TRUE)

response <- POST(
  url,
  body = payload,
  add_headers("Content-Type" = "application/json")
)

parsed <- content(response, as = "text", encoding = "UTF-8") |> fromJSON(simplifyVector = FALSE)

cpi1 <- parsed$Results$series[[1]]$data
ue1 <- parsed$Results$series[[2]]$data                              

Make an API call to the Department of Labor for the CPI and Unemployment rate for 2020-2026

url <- "https://api.bls.gov/publicAPI/v2/timeseries/data/"

payload1 <- toJSON(list(
  seriesid = list("CUSR0000SA0", "LNS14000000"),
  startyear = "2020",
  endyear = "2026",
  registrationkey = Sys.getenv("BLS_KEY")
), auto_unbox = TRUE)

response1 <- POST(
  url,
  body = payload1,
  add_headers("Content-Type" = "application/json")
)

parsed1 <- content(response1, as = "text", encoding = "UTF-8") |> fromJSON(simplifyVector = FALSE)

cpi2 <- parsed1$Results$series[[1]]$data
ue2 <- parsed1$Results$series[[2]]$data

Build dataframes of the API calls

cpi <- bind_rows(cpi1, cpi2) |> arrange(year, period) |> mutate(
  year = as.integer(year),
  cpi = as.numeric(value)
) |> select(-footnotes,-latest, -value)

ue <- bind_rows(ue1, ue2) |> arrange(year, period) |> mutate(
  year = as.integer(year),
  unemployment_rate = as.numeric(value)
) |> select(-footnotes,-latest, -value)

cpi_ue <- left_join(cpi, ue, by = c("year","period","periodName"))

Make an API call to the Fed for the Funds Rate

fed_url <- "https://api.stlouisfed.org/fred/series/observations"

payload2 <- GET(
  fed_url,
  query = list(
    series_id = "FEDFUNDS",
    api_key = Sys.getenv("FED_KEY"),
    file_type = "json",
    observation_start = "2000-01-01",
    observation_end = "2026-02-01"
  )
)

fed_data <- content(payload2, as="text") |> fromJSON()

fed_funds <- fed_data$observations |> select(date:value) |> mutate(
  date = as.Date(date),
  fed_rate = value) |> 
  select(-value) |> 
  mutate(
    year = year(date),
    period = sprintf("M%02d", month(date))
  ) |> 
  select(-date) |> 
  relocate(c(year, period, fed_rate))

Inspect the dataframe

fed_funds

Join the dataframes from the API calls

df_all <- left_join(cpi_ue,fed_funds, by=c("year", "period"))

Clean and adjust the data to create references

df_all <- df_all |> mutate(
  month_no = as.numeric((str_extract_all(period,"\\d+")))) |> 
  mutate(
    year_month = ymd(as.Date(str_glue("{year}-{month_no}-01"))),
    fed_rate = as.numeric(fed_rate),
    inflation_mom = 100 * (log(cpi) - log(lag(cpi))),
    inflation_yoy = 100 * (log(cpi) - log(lag(cpi, 12))),
    unemp_change = unemployment_rate - lag(unemployment_rate),
    fed_lag = lag(fed_rate)
  )

Inspect the dataframe

head(df_all)

Explore some graphs

g1 <- ggplot(data=df_all, aes(x=year_month)) +
  geom_line(aes(y=cpi), color = "green")

g2 <- ggplot(data=df_all, aes(x=year_month)) +
  geom_line(aes(y=unemployment_rate), color = "red") +
  geom_line(aes(y=fed_rate), color = "purple")

g1 / g2

Continue to explore visualization

Prepare a Linear model of the fed rate, inflation rate, and unemployment correlation

summary(model)

Call:
lm(formula = fed_rate ~ fed_lag + inflation_yoy + unemployment_rate, 
    data = df_all)

Residuals:
     Min       1Q   Median       3Q      Max 
-0.94621 -0.02496  0.01711  0.07434  0.58370 

Coefficients:
                   Estimate Std. Error t value Pr(>|t|)    
(Intercept)        0.073951   0.052747   1.402  0.16197    
fed_lag            0.969513   0.006447 150.371  < 2e-16 ***
inflation_yoy      0.028852   0.006500   4.439 1.28e-05 ***
unemployment_rate -0.017295   0.006618  -2.613  0.00942 ** 
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 0.172 on 296 degrees of freedom
  (13 observations deleted due to missingness)
Multiple R-squared:  0.9917,    Adjusted R-squared:  0.9916 
F-statistic: 1.181e+04 on 3 and 296 DF,  p-value: < 2.2e-16
cor(df_all$inflation_yoy, lag(df_all$fed_rate, 12), use="complete.obs")
[1] 0.02374964

Prepare a chart of the main data

df_long <- df_all |>
  select(year_month, cpi, unemployment_rate, fed_rate) |>
  pivot_longer(
    cols = -year_month,
    names_to = "series",
    values_to = "value"
  )

df_long$series <- factor(
  df_long$series,
  levels = c("cpi", "unemployment_rate", "fed_rate")
)

ggplot(df_long, aes(x = year_month, y = value, color = series)) +
  geom_line(size = 1) +
  facet_wrap(
    ~series,
    ncol = 1,
    scales = "free_y",
    labeller = labeller(
      series = c(
        cpi     = "Consumer Price Index ($)",
        unemployment_rate = "Unemployment Rate (%)",
        fed_rate          = "Federal Funds Rate (%)"
      )
    )
  ) +
  scale_color_manual(
    values = c(
      cpi     = "#2CA02C",
      unemployment_rate = "#D62728",
      fed_rate          = "purple"
    )
  ) +
  theme_minimal() +
  theme(
    legend.position = "none",
    strip.text = element_text(size = 14, face = "bold")
  ) +
  labs(
    x = "Year",
    y = ""
  )

Calculate the average inflation rate

inflation_avg <- df_all |> summarise(avg_inflation_yoy = mean(inflation_yoy, na.rm = TRUE))

inflation_avg_yoy <- df_all |> group_by(year) |> summarise(avg_inflation_yoy = mean(inflation_yoy, na.rm =TRUE))

inflation_avg

Create an average inflation chart by year

inflation_avg_yoy <- inflation_avg_yoy |> mutate(
  target_inflation_yoy = 2.00
)

inflation_avg_yoy

Explore a possible plot

ggplot(inflation_avg_yoy, aes(x=year)) +
  geom_line(aes(y=avg_inflation_yoy)) +
  geom_line(aes(y=target_inflation_yoy))

Prepare a dataframe for analysis

constant2pct_rate <- list(1.00)
year <- list("2000-01-01")

rate_mult <- 1.02^25

for (n in 1:25) {
  rate <- 1.02^n
  constant2pct_rate[[length(constant2pct_rate)+1]] <- rate
  thisyear <- paste0((2000+n),"-","01","-","01")
  year[[length(year)+1]] <- thisyear
}


df <- data_frame(year_month = unlist(year), rate_change = unlist(constant2pct_rate)) |> mutate(
  year_month = as.Date(year_month)
)

df <- left_join(df, df_all, by = "year_month")

df <- df |>  mutate(
  cpiplus_2pct = cpi[1] * rate_change,
  overprevyr2pct = lag(cpi) * 1.02,
  pct_yoy = (lead(cpi)/cpi-1)*100
)

Calculate the average inflation rate

avg_inflation <- df |> summarise(mean(inflation_yoy, na.rm = TRUE))

Calculate the inflation count

inflation_count <- df |>  summarise(above_target = sum(inflation_yoy >2, na.rm = TRUE))

Inspect the dataframe

df

Explore the plot with a linechart

ggplot(df, aes(x=year_month)) +
  geom_line(aes(y=cpi, color = "red")) +
  geom_line(aes(y=cpiplus_2pct, color = "green")) +
  geom_line(aes(y=overprevyr2pct, color = "blue"))

Prepare the dataframe for more analysis

df <- df |> mutate(
  deviation = pct_yoy - 2,
  cum_dev = cumsum(deviation),
  unemployment_change = unemployment_rate - lag(unemployment_rate, default = 0),
  cum_unempl_change = cumsum(unemployment_change)
)

Calculate average unemployment

avg_unemployment <- df |> summarise(mean(unemployment_rate, na.rm = TRUE))

Create a chart for inflation deviation

ggplot(df, aes(x = year_month)) +
  geom_col(aes(y = deviation, fill = deviation > 0)) +
  geom_line(aes(y = cum_dev), color = "#D62728", size = 1.2) +
  geom_hline(yintercept = 0, linetype = "dashed", size = 1) +
  scale_fill_manual(
    values = c("TRUE" = "#D62728",
               "FALSE" = "blue"),
    guide = "none"
  ) +
  theme_minimal() +
  labs(
    x = "Year",
    y = "Inflation deviation from 2% target",
    caption = "Inflation deviation\nBars: annual deviation | Line: cumulative deviation",
    title = NULL
  ) +
  theme(
    text = element_text(color = "gray30"),
    panel.grid.major = element_blank(),
    panel.grid.minor = element_blank(),
    plot.caption = element_text(
      size = 12,
      hjust = 0
    ),
    plot.caption.position = "plot"
  ) +
  scale_x_date(expand = expansion(mult = c(0.01, 0.08)))

Create a chart for unempployment deviation

ggplot(df, aes(x = year_month)) +
  geom_col(aes(y = unemployment_change, fill = unemployment_change > 0)) +
  geom_line(aes(y = cum_unempl_change), color = "#D62728", size = 1.2) +
  geom_hline(yintercept = 0, linetype = "dashed", size = 1) +
  scale_fill_manual(
    values = c("TRUE" = "#D62728",
               "FALSE" = "blue"),
    guide = "none"
  ) +
  theme_minimal() +
  labs(
    x = "Year",
    y = "Unemployment deviation",
    caption = "Unemployment deviation\nBars: annual deviation | Line: cumulative deviation",
    title = NULL
  ) +
  theme(
    text = element_text(color = "gray30"),
    panel.grid.major = element_blank(),
    panel.grid.minor = element_blank(),
    plot.caption = element_text(
      size = 12,
      hjust = 0
    ),
    plot.caption.position = "plot"
  ) +
  scale_x_date(expand = expansion(mult = c(0.01, 0.08)))

Chart the main data

df_long <- df_all |>
  select(year_month, inflation_yoy, unemployment_rate, fed_rate) |>
  pivot_longer(
    cols = -year_month,
    names_to = "series",
    values_to = "value"
  )

df_long$series <- factor(
  df_long$series,
  levels = c("inflation_yoy", "unemployment_rate", "fed_rate")
)

ggplot(df_long, aes(x = year_month, y = value, color = series)) +
  geom_line(size = 1) +
  facet_wrap(
    ~series,
    ncol = 1,
    scales = "free_y",
    labeller = labeller(
      series = c(
        inflation_yoy = "Annual Inflation Rate (%)",
        unemployment_rate = "Unemployment Rate (%)",
        fed_rate          = "Federal Funds Rate (%)"
      )
    )
  ) +
  scale_color_manual(
    values = c(
      inflation_yoy     = "#2CA02C",
      unemployment_rate = "#D62728",
      fed_rate          = "purple"
    )
  ) +
  theme_minimal() +
  theme(
    legend.position = "none",
    strip.text = element_text(size = 14, face = "bold")
  ) +
  labs(
    x = "Year",
    y = ""
  )

Prepare subsets of data

df_2008 <- df_all |> filter(year >= 2007 & year <= 2012) |> select(year_month, inflation_yoy, unemployment_rate, fed_rate) |>
  pivot_longer(
    cols = -year_month,
    names_to = "series",
    values_to = "value"
  )

df_2020 <- df_all |> filter(year >= 2019 & year <= 2025) |> select(year_month, inflation_yoy, unemployment_rate, fed_rate) |>
  pivot_longer(
    cols = -year_month,
    names_to = "series",
    values_to = "value"
  )

Prepare a chart to highlight 2008 and 2020

df_long <- df_all |> 
  select(year_month, inflation_yoy, unemployment_rate, fed_rate) |>
  pivot_longer(
    cols = -year_month,
    names_to = "series",
    values_to = "value"
  )

df_long$series <- factor(
  df_long$series,
  levels = c("inflation_yoy", "unemployment_rate", "fed_rate")
)


ggplot(df_long, aes(x = year_month, y = value)) +

  geom_line(aes(group = series), color = "gray70", size = 0.8, alpha = 0.5) +

  
  geom_line(
    data = df_2008,
    aes(x = year_month, y = value, color = series),
    size = 1.3
  ) +


  geom_line(
    data = df_2020,
    aes(x = year_month, y = value, color = series),
    size = 1.3
  ) +

  
  facet_wrap(
    ~series,
    ncol = 1,
    scales = "free_y",
    labeller = labeller(
      series = c(
        inflation_yoy = "Annual Inflation Rate (%)",
        unemployment_rate = "Unemployment Rate (%)",
        fed_rate = "Federal Funds Rate (%)"
      )
    )
  ) +

  # Colors for highlights
  scale_color_manual(
    values = c(
      inflation_yoy     = "#2CA02C",
      unemployment_rate = "#D62728",
      fed_rate          = "purple"
    )
  ) +

  theme_minimal(base_size = 14) +
  theme(
    legend.position = "none", # or "none" if you prefer no legend
    strip.text = element_text(size = 14, color = "gray70"),
    axis.title = element_text(color = "gray70", size = 14),
    axis.text = element_text(color = "gray70", size = 12),
    panel.grid = element_blank()
  ) +

  labs(
    x = "Year",
    y = "Percentage",
    color = "gray70"
  )

Explore a possible chart

df <- df %>%
  arrange(year_month) %>%
  mutate(fed_rate_lag12 = lag(fed_rate, 1))  # 12-month lag

ggplot(df, aes(x = year_month)) +

  # Bars: annual inflation deviation
  geom_col(aes(y = deviation, fill = deviation > 0), alpha = 0.7) +

  # Cumulative deviation line
  geom_line(aes(y = cum_dev), color = "black", size = 1.2) +

  # Lagged Fed rate line (scaled if necessary)
  geom_line(aes(y = fed_rate_lag12), color = "#1F77B4", size = 1, linetype = "dashed") +

  # Zero line
  geom_hline(yintercept = 0, linetype = "dashed", size = 0.8) +

  # Color scale for bars
  scale_fill_manual(values = c("TRUE" = "#D62728", "FALSE" = "blue"), guide = "none") +

  # Minimal theme
  theme_minimal(base_size = 14) +
  theme(
    plot.caption = element_text(size = 16, face = "bold", hjust = 0.5),
    plot.caption.position = "plot"
  ) +

  # Labels
  labs(
    x = "Year",
    y = "Inflation Deviation / Fed Rate",
    caption = "Bars = deviation from 2% target | Solid line = cumulative deviation | Dashed blue line = Fed rate (12-month lag)"
  )

Subset the subset

df_2008_slice <- df_2008 |> filter(year_month >= "2008-01-01" & year_month <= "2010-01-01")

Prepare a highlighted graph of 2008

```{r}
Error: attempt to use zero-length variable name

Prepare a highlight of 2020 crisis

LS0tCnRpdGxlOiAiVGhlIEZlZDogSW5mbGF0aW9uIGFuZCBFbXBsb3ltZW50IgpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sKLS0tCgpMb2FkIFBhY2thZ2VzCgpgYGB7ciBsb2FkIHBhY2thZ2VzfQpsaWJyYXJ5KGpzb25saXRlKQpsaWJyYXJ5KHRpZHl2ZXJzZSkKbGlicmFyeShodHRyKQpsaWJyYXJ5KGdncGxvdDIpCmxpYnJhcnkocGF0Y2h3b3JrKQpgYGAKCk1ha2UgYW4gQVBJIGNhbGwgdG8gdGhlIERlcGFydG1lbnQgb2YgTGFib3IgZm9yIHRoZSBDUEkgYW5kIFVuZW1wbG95bWVudCByYXRlIGZvciAyMDAwLTIwMjAKCmBgYHtyfQp1cmwgPC0gImh0dHBzOi8vYXBpLmJscy5nb3YvcHVibGljQVBJL3YyL3RpbWVzZXJpZXMvZGF0YS8iCgpwYXlsb2FkIDwtIHRvSlNPTihsaXN0KAogIHNlcmllc2lkID0gbGlzdCgiQ1VTUjAwMDBTQTAiLCAiTE5TMTQwMDAwMDAiKSwKICBzdGFydHllYXIgPSAiMjAwMCIsCiAgZW5keWVhciA9ICIyMDI2IiwKICByZWdpc3RyYXRpb25rZXkgPSBTeXMuZ2V0ZW52KCJCTFNfS0VZIikKKSwgYXV0b191bmJveCA9IFRSVUUpCgpyZXNwb25zZSA8LSBQT1NUKAogIHVybCwKICBib2R5ID0gcGF5bG9hZCwKICBhZGRfaGVhZGVycygiQ29udGVudC1UeXBlIiA9ICJhcHBsaWNhdGlvbi9qc29uIikKKQoKcGFyc2VkIDwtIGNvbnRlbnQocmVzcG9uc2UsIGFzID0gInRleHQiLCBlbmNvZGluZyA9ICJVVEYtOCIpIHw+IGZyb21KU09OKHNpbXBsaWZ5VmVjdG9yID0gRkFMU0UpCgpjcGkxIDwtIHBhcnNlZCRSZXN1bHRzJHNlcmllc1tbMV1dJGRhdGEKdWUxIDwtIHBhcnNlZCRSZXN1bHRzJHNlcmllc1tbMl1dJGRhdGEgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKYGBgCgpNYWtlIGFuIEFQSSBjYWxsIHRvIHRoZSBEZXBhcnRtZW50IG9mIExhYm9yIGZvciB0aGUgQ1BJIGFuZCBVbmVtcGxveW1lbnQgcmF0ZSBmb3IgMjAyMC0yMDI2CgpgYGB7cn0KdXJsIDwtICJodHRwczovL2FwaS5ibHMuZ292L3B1YmxpY0FQSS92Mi90aW1lc2VyaWVzL2RhdGEvIgoKcGF5bG9hZDEgPC0gdG9KU09OKGxpc3QoCiAgc2VyaWVzaWQgPSBsaXN0KCJDVVNSMDAwMFNBMCIsICJMTlMxNDAwMDAwMCIpLAogIHN0YXJ0eWVhciA9ICIyMDIwIiwKICBlbmR5ZWFyID0gIjIwMjYiLAogIHJlZ2lzdHJhdGlvbmtleSA9IFN5cy5nZXRlbnYoIkJMU19LRVkiKQopLCBhdXRvX3VuYm94ID0gVFJVRSkKCnJlc3BvbnNlMSA8LSBQT1NUKAogIHVybCwKICBib2R5ID0gcGF5bG9hZDEsCiAgYWRkX2hlYWRlcnMoIkNvbnRlbnQtVHlwZSIgPSAiYXBwbGljYXRpb24vanNvbiIpCikKCnBhcnNlZDEgPC0gY29udGVudChyZXNwb25zZTEsIGFzID0gInRleHQiLCBlbmNvZGluZyA9ICJVVEYtOCIpIHw+IGZyb21KU09OKHNpbXBsaWZ5VmVjdG9yID0gRkFMU0UpCgpjcGkyIDwtIHBhcnNlZDEkUmVzdWx0cyRzZXJpZXNbWzFdXSRkYXRhCnVlMiA8LSBwYXJzZWQxJFJlc3VsdHMkc2VyaWVzW1syXV0kZGF0YQpgYGAKCkJ1aWxkIGRhdGFmcmFtZXMgb2YgdGhlIEFQSSBjYWxscwoKYGBge3J9CmNwaSA8LSBiaW5kX3Jvd3MoY3BpMSwgY3BpMikgfD4gYXJyYW5nZSh5ZWFyLCBwZXJpb2QpIHw+IG11dGF0ZSgKICB5ZWFyID0gYXMuaW50ZWdlcih5ZWFyKSwKICBjcGkgPSBhcy5udW1lcmljKHZhbHVlKQopIHw+IHNlbGVjdCgtZm9vdG5vdGVzLC1sYXRlc3QsIC12YWx1ZSkKCnVlIDwtIGJpbmRfcm93cyh1ZTEsIHVlMikgfD4gYXJyYW5nZSh5ZWFyLCBwZXJpb2QpIHw+IG11dGF0ZSgKICB5ZWFyID0gYXMuaW50ZWdlcih5ZWFyKSwKICB1bmVtcGxveW1lbnRfcmF0ZSA9IGFzLm51bWVyaWModmFsdWUpCikgfD4gc2VsZWN0KC1mb290bm90ZXMsLWxhdGVzdCwgLXZhbHVlKQoKY3BpX3VlIDwtIGxlZnRfam9pbihjcGksIHVlLCBieSA9IGMoInllYXIiLCJwZXJpb2QiLCJwZXJpb2ROYW1lIikpCmBgYAoKTWFrZSBhbiBBUEkgY2FsbCB0byB0aGUgRmVkIGZvciB0aGUgRnVuZHMgUmF0ZQoKYGBge3J9CmZlZF91cmwgPC0gImh0dHBzOi8vYXBpLnN0bG91aXNmZWQub3JnL2ZyZWQvc2VyaWVzL29ic2VydmF0aW9ucyIKCnBheWxvYWQyIDwtIEdFVCgKICBmZWRfdXJsLAogIHF1ZXJ5ID0gbGlzdCgKICAgIHNlcmllc19pZCA9ICJGRURGVU5EUyIsCiAgICBhcGlfa2V5ID0gU3lzLmdldGVudigiRkVEX0tFWSIpLAogICAgZmlsZV90eXBlID0gImpzb24iLAogICAgb2JzZXJ2YXRpb25fc3RhcnQgPSAiMjAwMC0wMS0wMSIsCiAgICBvYnNlcnZhdGlvbl9lbmQgPSAiMjAyNi0wMi0wMSIKICApCikKCmZlZF9kYXRhIDwtIGNvbnRlbnQocGF5bG9hZDIsIGFzPSJ0ZXh0IikgfD4gZnJvbUpTT04oKQoKZmVkX2Z1bmRzIDwtIGZlZF9kYXRhJG9ic2VydmF0aW9ucyB8PiBzZWxlY3QoZGF0ZTp2YWx1ZSkgfD4gbXV0YXRlKAogIGRhdGUgPSBhcy5EYXRlKGRhdGUpLAogIGZlZF9yYXRlID0gdmFsdWUpIHw+IAogIHNlbGVjdCgtdmFsdWUpIHw+IAogIG11dGF0ZSgKICAgIHllYXIgPSB5ZWFyKGRhdGUpLAogICAgcGVyaW9kID0gc3ByaW50ZigiTSUwMmQiLCBtb250aChkYXRlKSkKICApIHw+IAogIHNlbGVjdCgtZGF0ZSkgfD4gCiAgcmVsb2NhdGUoYyh5ZWFyLCBwZXJpb2QsIGZlZF9yYXRlKSkKYGBgCgpJbnNwZWN0IHRoZSBkYXRhZnJhbWUKCmBgYHtyfQpmZWRfZnVuZHMKYGBgCgpKb2luIHRoZSBkYXRhZnJhbWVzIGZyb20gdGhlIEFQSSBjYWxscwoKYGBge3J9CmRmX2FsbCA8LSBsZWZ0X2pvaW4oY3BpX3VlLGZlZF9mdW5kcywgYnk9YygieWVhciIsICJwZXJpb2QiKSkKYGBgCgpDbGVhbiBhbmQgYWRqdXN0IHRoZSBkYXRhIHRvIGNyZWF0ZSByZWZlcmVuY2VzCgpgYGB7cn0gCmRmX2FsbCA8LSBkZl9hbGwgfD4gbXV0YXRlKAogIG1vbnRoX25vID0gYXMubnVtZXJpYygoc3RyX2V4dHJhY3RfYWxsKHBlcmlvZCwiXFxkKyIpKSkpIHw+IAogIG11dGF0ZSgKICAgIHllYXJfbW9udGggPSB5bWQoYXMuRGF0ZShzdHJfZ2x1ZSgie3llYXJ9LXttb250aF9ub30tMDEiKSkpLAogICAgZmVkX3JhdGUgPSBhcy5udW1lcmljKGZlZF9yYXRlKSwKICAgIGluZmxhdGlvbl9tb20gPSAxMDAgKiAobG9nKGNwaSkgLSBsb2cobGFnKGNwaSkpKSwKICAgIGluZmxhdGlvbl95b3kgPSAxMDAgKiAobG9nKGNwaSkgLSBsb2cobGFnKGNwaSwgMTIpKSksCiAgICB1bmVtcF9jaGFuZ2UgPSB1bmVtcGxveW1lbnRfcmF0ZSAtIGxhZyh1bmVtcGxveW1lbnRfcmF0ZSksCiAgICBmZWRfbGFnID0gbGFnKGZlZF9yYXRlKQogICkKYGBgCgpJbnNwZWN0IHRoZSBkYXRhZnJhbWUKCmBgYHtyfQpoZWFkKGRmX2FsbCkKYGBgCgpFeHBsb3JlIHNvbWUgZ3JhcGhzCgpgYGB7cn0KZzEgPC0gZ2dwbG90KGRhdGE9ZGZfYWxsLCBhZXMoeD15ZWFyX21vbnRoKSkgKwogIGdlb21fbGluZShhZXMoeT1jcGkpLCBjb2xvciA9ICJncmVlbiIpCgpnMiA8LSBnZ3Bsb3QoZGF0YT1kZl9hbGwsIGFlcyh4PXllYXJfbW9udGgpKSArCiAgZ2VvbV9saW5lKGFlcyh5PXVuZW1wbG95bWVudF9yYXRlKSwgY29sb3IgPSAicmVkIikgKwogIGdlb21fbGluZShhZXMoeT1mZWRfcmF0ZSksIGNvbG9yID0gInB1cnBsZSIpCgpnMSAvIGcyCmBgYAoKQ29udGludWUgdG8gZXhwbG9yZSB2aXN1YWxpemF0aW9uCgpgYGB7cn0KZzEgPC0gZ2dwbG90KGRhdGE9ZGZfYWxsLCBhZXMoeD15ZWFyX21vbnRoKSkgKwogIGdlb21fbGluZShhZXMoeT1jcGkpLCBjb2xvciA9ICJncmVlbiIpIAoKZzIgPC0gZ2dwbG90KGRhdGE9ZGZfYWxsLCBhZXMoeD15ZWFyX21vbnRoKSkgKwogIGdlb21fbGluZShhZXMoeT1pbmZsYXRpb25feW95KSwgY29sb3IgPSAicmVkIikgKwogIGdlb21fbGluZShhZXMoeT11bmVtcGxveW1lbnRfcmF0ZSksIGNvbG9yID0gInB1cnBsZSIpICsKICBnZW9tX2xpbmUoYWVzKHk9ZmVkX3JhdGUpLCBjb2xvciA9ICJibHVlIikKCmczIDwtIGdncGxvdChkYXRhPWRmX2FsbCwgYWVzKHg9eWVhcl9tb250aCkpICsKICBnZW9tX2xpbmUoYWVzKHk9aW5mbGF0aW9uX3lveSksIGNvbG9yID0gInJlZCIpICsKICBnZW9tX2xpbmUoYWVzKHk9dW5lbXBsb3ltZW50X3JhdGUpLCBjb2xvciA9ICJwdXJwbGUiKSArCiAgZ2VvbV9saW5lKGFlcyh5PWZlZF9yYXRlKSwgY29sb3IgPSAiYmx1ZSIpCgpnMiA8LSBnZ3Bsb3QoZGF0YT1kZl9hbGwsIGFlcyh4PXllYXJfbW9udGgpKSArCiAgZ2VvbV9saW5lKGFlcyh5PWluZmxhdGlvbl95b3kpLCBjb2xvciA9ICJyZWQiKSArCiAgZ2VvbV9saW5lKGFlcyh5PXVuZW1wbG95bWVudF9yYXRlKSwgY29sb3IgPSAicHVycGxlIikgKwogIGdlb21fbGluZShhZXMoeT1mZWRfcmF0ZSksIGNvbG9yID0gImJsdWUiKQogICAgICAKCmcxIC8gZzIgL2czCmBgYAoKUHJlcGFyZSBhIExpbmVhciBtb2RlbCBvZiB0aGUgZmVkIHJhdGUsIGluZmxhdGlvbiByYXRlLCBhbmQgdW5lbXBsb3ltZW50IGNvcnJlbGF0aW9uCgpgYGB7cn0KbW9kZWwgPC0gbG0oZmVkX3JhdGUgfiBmZWRfbGFnICsgaW5mbGF0aW9uX3lveSArIHVuZW1wbG95bWVudF9yYXRlLCBkZl9hbGwpCgpzdW1tYXJ5KG1vZGVsKQpgYGAKCmBgYHtyfQpjb3IoZGZfYWxsJGluZmxhdGlvbl95b3ksIGxhZyhkZl9hbGwkZmVkX3JhdGUsIDEyKSwgdXNlPSJjb21wbGV0ZS5vYnMiKQpgYGAKClByZXBhcmUgYSBjaGFydCBvZiB0aGUgbWFpbiBkYXRhCgpgYGB7cn0KZGZfbG9uZyA8LSBkZl9hbGwgfD4KICBzZWxlY3QoeWVhcl9tb250aCwgY3BpLCB1bmVtcGxveW1lbnRfcmF0ZSwgZmVkX3JhdGUpIHw+CiAgcGl2b3RfbG9uZ2VyKAogICAgY29scyA9IC15ZWFyX21vbnRoLAogICAgbmFtZXNfdG8gPSAic2VyaWVzIiwKICAgIHZhbHVlc190byA9ICJ2YWx1ZSIKICApCgpkZl9sb25nJHNlcmllcyA8LSBmYWN0b3IoCiAgZGZfbG9uZyRzZXJpZXMsCiAgbGV2ZWxzID0gYygiY3BpIiwgInVuZW1wbG95bWVudF9yYXRlIiwgImZlZF9yYXRlIikKKQoKZ2dwbG90KGRmX2xvbmcsIGFlcyh4ID0geWVhcl9tb250aCwgeSA9IHZhbHVlLCBjb2xvciA9IHNlcmllcykpICsKICBnZW9tX2xpbmUoc2l6ZSA9IDEpICsKICBmYWNldF93cmFwKAogICAgfnNlcmllcywKICAgIG5jb2wgPSAxLAogICAgc2NhbGVzID0gImZyZWVfeSIsCiAgICBsYWJlbGxlciA9IGxhYmVsbGVyKAogICAgICBzZXJpZXMgPSBjKAogICAgICAgIGNwaSAgICAgPSAiQ29uc3VtZXIgUHJpY2UgSW5kZXggKCQpIiwKICAgICAgICB1bmVtcGxveW1lbnRfcmF0ZSA9ICJVbmVtcGxveW1lbnQgUmF0ZSAoJSkiLAogICAgICAgIGZlZF9yYXRlICAgICAgICAgID0gIkZlZGVyYWwgRnVuZHMgUmF0ZSAoJSkiCiAgICAgICkKICAgICkKICApICsKICBzY2FsZV9jb2xvcl9tYW51YWwoCiAgICB2YWx1ZXMgPSBjKAogICAgICBjcGkgICAgID0gIiMyQ0EwMkMiLAogICAgICB1bmVtcGxveW1lbnRfcmF0ZSA9ICIjRDYyNzI4IiwKICAgICAgZmVkX3JhdGUgICAgICAgICAgPSAicHVycGxlIgogICAgKQogICkgKwogIHRoZW1lX21pbmltYWwoKSArCiAgdGhlbWUoCiAgICBsZWdlbmQucG9zaXRpb24gPSAibm9uZSIsCiAgICBzdHJpcC50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNCwgZmFjZSA9ICJib2xkIikKICApICsKICBsYWJzKAogICAgeCA9ICJZZWFyIiwKICAgIHkgPSAiIgogICkKYGBgCkNhbGN1bGF0ZSB0aGUgYXZlcmFnZSBpbmZsYXRpb24gcmF0ZQoKYGBge3J9CmluZmxhdGlvbl9hdmcgPC0gZGZfYWxsIHw+IHN1bW1hcmlzZShhdmdfaW5mbGF0aW9uX3lveSA9IG1lYW4oaW5mbGF0aW9uX3lveSwgbmEucm0gPSBUUlVFKSkKCmluZmxhdGlvbl9hdmdfeW95IDwtIGRmX2FsbCB8PiBncm91cF9ieSh5ZWFyKSB8PiBzdW1tYXJpc2UoYXZnX2luZmxhdGlvbl95b3kgPSBtZWFuKGluZmxhdGlvbl95b3ksIG5hLnJtID1UUlVFKSkKCmluZmxhdGlvbl9hdmcKYGBgCgpDcmVhdGUgYW4gYXZlcmFnZSBpbmZsYXRpb24gY2hhcnQgYnkgeWVhcgoKYGBge3J9CmluZmxhdGlvbl9hdmdfeW95IDwtIGluZmxhdGlvbl9hdmdfeW95IHw+IG11dGF0ZSgKICB0YXJnZXRfaW5mbGF0aW9uX3lveSA9IDIuMDAKKQoKaW5mbGF0aW9uX2F2Z195b3kKYGBgCgpFeHBsb3JlIGEgcG9zc2libGUgcGxvdAoKYGBge3J9CmdncGxvdChpbmZsYXRpb25fYXZnX3lveSwgYWVzKHg9eWVhcikpICsKICBnZW9tX2xpbmUoYWVzKHk9YXZnX2luZmxhdGlvbl95b3kpKSArCiAgZ2VvbV9saW5lKGFlcyh5PXRhcmdldF9pbmZsYXRpb25feW95KSkKYGBgCgpQcmVwYXJlIGEgZGF0YWZyYW1lIGZvciBhbmFseXNpcwoKYGBge3J9CmNvbnN0YW50MnBjdF9yYXRlIDwtIGxpc3QoMS4wMCkKeWVhciA8LSBsaXN0KCIyMDAwLTAxLTAxIikKCnJhdGVfbXVsdCA8LSAxLjAyXjI1Cgpmb3IgKG4gaW4gMToyNSkgewogIHJhdGUgPC0gMS4wMl5uCiAgY29uc3RhbnQycGN0X3JhdGVbW2xlbmd0aChjb25zdGFudDJwY3RfcmF0ZSkrMV1dIDwtIHJhdGUKICB0aGlzeWVhciA8LSBwYXN0ZTAoKDIwMDArbiksIi0iLCIwMSIsIi0iLCIwMSIpCiAgeWVhcltbbGVuZ3RoKHllYXIpKzFdXSA8LSB0aGlzeWVhcgp9CgoKZGYgPC0gZGF0YV9mcmFtZSh5ZWFyX21vbnRoID0gdW5saXN0KHllYXIpLCByYXRlX2NoYW5nZSA9IHVubGlzdChjb25zdGFudDJwY3RfcmF0ZSkpIHw+IG11dGF0ZSgKICB5ZWFyX21vbnRoID0gYXMuRGF0ZSh5ZWFyX21vbnRoKQopCgpkZiA8LSBsZWZ0X2pvaW4oZGYsIGRmX2FsbCwgYnkgPSAieWVhcl9tb250aCIpCgpkZiA8LSBkZiB8PiAgbXV0YXRlKAogIGNwaXBsdXNfMnBjdCA9IGNwaVsxXSAqIHJhdGVfY2hhbmdlLAogIG92ZXJwcmV2eXIycGN0ID0gbGFnKGNwaSkgKiAxLjAyLAogIHBjdF95b3kgPSAobGVhZChjcGkpL2NwaS0xKSoxMDAKKQpgYGAKCkNhbGN1bGF0ZSB0aGUgYXZlcmFnZSBpbmZsYXRpb24gcmF0ZQoKYGBge3J9CmF2Z19pbmZsYXRpb24gPC0gZGYgfD4gc3VtbWFyaXNlKG1lYW4oaW5mbGF0aW9uX3lveSwgbmEucm0gPSBUUlVFKSkKYGBgCgpDYWxjdWxhdGUgdGhlIGluZmxhdGlvbiBjb3VudAoKYGBge3J9CmluZmxhdGlvbl9jb3VudCA8LSBkZiB8PiAgc3VtbWFyaXNlKGFib3ZlX3RhcmdldCA9IHN1bShpbmZsYXRpb25feW95ID4yLCBuYS5ybSA9IFRSVUUpKQpgYGAKCkluc3BlY3QgdGhlIGRhdGFmcmFtZQoKYGBge3J9CmRmCmBgYAoKRXhwbG9yZSB0aGUgcGxvdCB3aXRoIGEgbGluZWNoYXJ0CgpgYGB7cn0KZ2dwbG90KGRmLCBhZXMoeD15ZWFyX21vbnRoKSkgKwogIGdlb21fbGluZShhZXMoeT1jcGksIGNvbG9yID0gInJlZCIpKSArCiAgZ2VvbV9saW5lKGFlcyh5PWNwaXBsdXNfMnBjdCwgY29sb3IgPSAiZ3JlZW4iKSkgKwogIGdlb21fbGluZShhZXMoeT1vdmVycHJldnlyMnBjdCwgY29sb3IgPSAiYmx1ZSIpKQoKYGBgCgpQcmVwYXJlIHRoZSBkYXRhZnJhbWUgZm9yIG1vcmUgYW5hbHlzaXMKCmBgYHtyfQpkZiA8LSBkZiB8PiBtdXRhdGUoCiAgZGV2aWF0aW9uID0gcGN0X3lveSAtIDIsCiAgY3VtX2RldiA9IGN1bXN1bShkZXZpYXRpb24pLAogIHVuZW1wbG95bWVudF9jaGFuZ2UgPSB1bmVtcGxveW1lbnRfcmF0ZSAtIGxhZyh1bmVtcGxveW1lbnRfcmF0ZSwgZGVmYXVsdCA9IDApLAogIGN1bV91bmVtcGxfY2hhbmdlID0gY3Vtc3VtKHVuZW1wbG95bWVudF9jaGFuZ2UpCikKYGBgCgpDYWxjdWxhdGUgYXZlcmFnZSB1bmVtcGxveW1lbnQKCmBgYHtyfQphdmdfdW5lbXBsb3ltZW50IDwtIGRmIHw+IHN1bW1hcmlzZShtZWFuKHVuZW1wbG95bWVudF9yYXRlLCBuYS5ybSA9IFRSVUUpKQpgYGAKCkNyZWF0ZSBhIGNoYXJ0IGZvciBpbmZsYXRpb24gZGV2aWF0aW9uCgpgYGB7cn0KZ2dwbG90KGRmLCBhZXMoeCA9IHllYXJfbW9udGgpKSArCiAgZ2VvbV9jb2woYWVzKHkgPSBkZXZpYXRpb24sIGZpbGwgPSBkZXZpYXRpb24gPiAwKSkgKwogIGdlb21fbGluZShhZXMoeSA9IGN1bV9kZXYpLCBjb2xvciA9ICIjRDYyNzI4Iiwgc2l6ZSA9IDEuMikgKwogIGdlb21faGxpbmUoeWludGVyY2VwdCA9IDAsIGxpbmV0eXBlID0gImRhc2hlZCIsIHNpemUgPSAxKSArCiAgc2NhbGVfZmlsbF9tYW51YWwoCiAgICB2YWx1ZXMgPSBjKCJUUlVFIiA9ICIjRDYyNzI4IiwKICAgICAgICAgICAgICAgIkZBTFNFIiA9ICJibHVlIiksCiAgICBndWlkZSA9ICJub25lIgogICkgKwogIHRoZW1lX21pbmltYWwoKSArCiAgbGFicygKICAgIHggPSAiWWVhciIsCiAgICB5ID0gIkluZmxhdGlvbiBkZXZpYXRpb24gZnJvbSAyJSB0YXJnZXQiLAogICAgY2FwdGlvbiA9ICJJbmZsYXRpb24gZGV2aWF0aW9uXG5CYXJzOiBhbm51YWwgZGV2aWF0aW9uIHwgTGluZTogY3VtdWxhdGl2ZSBkZXZpYXRpb24iLAogICAgdGl0bGUgPSBOVUxMCiAgKSArCiAgdGhlbWUoCiAgICB0ZXh0ID0gZWxlbWVudF90ZXh0KGNvbG9yID0gImdyYXkzMCIpLAogICAgcGFuZWwuZ3JpZC5tYWpvciA9IGVsZW1lbnRfYmxhbmsoKSwKICAgIHBhbmVsLmdyaWQubWlub3IgPSBlbGVtZW50X2JsYW5rKCksCiAgICBwbG90LmNhcHRpb24gPSBlbGVtZW50X3RleHQoCiAgICAgIHNpemUgPSAxMiwKICAgICAgaGp1c3QgPSAwCiAgICApLAogICAgcGxvdC5jYXB0aW9uLnBvc2l0aW9uID0gInBsb3QiCiAgKSArCiAgc2NhbGVfeF9kYXRlKGV4cGFuZCA9IGV4cGFuc2lvbihtdWx0ID0gYygwLjAxLCAwLjA4KSkpCmBgYApDcmVhdGUgYSBjaGFydCBmb3IgdW5lbXBwbG95bWVudCBkZXZpYXRpb24KCmBgYHtyfQpnZ3Bsb3QoZGYsIGFlcyh4ID0geWVhcl9tb250aCkpICsKICBnZW9tX2NvbChhZXMoeSA9IHVuZW1wbG95bWVudF9jaGFuZ2UsIGZpbGwgPSB1bmVtcGxveW1lbnRfY2hhbmdlID4gMCkpICsKICBnZW9tX2xpbmUoYWVzKHkgPSBjdW1fdW5lbXBsX2NoYW5nZSksIGNvbG9yID0gIiNENjI3MjgiLCBzaXplID0gMS4yKSArCiAgZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0gMCwgbGluZXR5cGUgPSAiZGFzaGVkIiwgc2l6ZSA9IDEpICsKICBzY2FsZV9maWxsX21hbnVhbCgKICAgIHZhbHVlcyA9IGMoIlRSVUUiID0gIiNENjI3MjgiLAogICAgICAgICAgICAgICAiRkFMU0UiID0gImJsdWUiKSwKICAgIGd1aWRlID0gIm5vbmUiCiAgKSArCiAgdGhlbWVfbWluaW1hbCgpICsKICBsYWJzKAogICAgeCA9ICJZZWFyIiwKICAgIHkgPSAiVW5lbXBsb3ltZW50IGRldmlhdGlvbiIsCiAgICBjYXB0aW9uID0gIlVuZW1wbG95bWVudCBkZXZpYXRpb25cbkJhcnM6IGFubnVhbCBkZXZpYXRpb24gfCBMaW5lOiBjdW11bGF0aXZlIGRldmlhdGlvbiIsCiAgICB0aXRsZSA9IE5VTEwKICApICsKICB0aGVtZSgKICAgIHRleHQgPSBlbGVtZW50X3RleHQoY29sb3IgPSAiZ3JheTMwIiksCiAgICBwYW5lbC5ncmlkLm1ham9yID0gZWxlbWVudF9ibGFuaygpLAogICAgcGFuZWwuZ3JpZC5taW5vciA9IGVsZW1lbnRfYmxhbmsoKSwKICAgIHBsb3QuY2FwdGlvbiA9IGVsZW1lbnRfdGV4dCgKICAgICAgc2l6ZSA9IDEyLAogICAgICBoanVzdCA9IDAKICAgICksCiAgICBwbG90LmNhcHRpb24ucG9zaXRpb24gPSAicGxvdCIKICApICsKICBzY2FsZV94X2RhdGUoZXhwYW5kID0gZXhwYW5zaW9uKG11bHQgPSBjKDAuMDEsIDAuMDgpKSkKYGBgCgpDaGFydCB0aGUgbWFpbiBkYXRhCgpgYGB7cn0KZGZfbG9uZyA8LSBkZl9hbGwgfD4KICBzZWxlY3QoeWVhcl9tb250aCwgaW5mbGF0aW9uX3lveSwgdW5lbXBsb3ltZW50X3JhdGUsIGZlZF9yYXRlKSB8PgogIHBpdm90X2xvbmdlcigKICAgIGNvbHMgPSAteWVhcl9tb250aCwKICAgIG5hbWVzX3RvID0gInNlcmllcyIsCiAgICB2YWx1ZXNfdG8gPSAidmFsdWUiCiAgKQoKZGZfbG9uZyRzZXJpZXMgPC0gZmFjdG9yKAogIGRmX2xvbmckc2VyaWVzLAogIGxldmVscyA9IGMoImluZmxhdGlvbl95b3kiLCAidW5lbXBsb3ltZW50X3JhdGUiLCAiZmVkX3JhdGUiKQopCgpnZ3Bsb3QoZGZfbG9uZywgYWVzKHggPSB5ZWFyX21vbnRoLCB5ID0gdmFsdWUsIGNvbG9yID0gc2VyaWVzKSkgKwogIGdlb21fbGluZShzaXplID0gMSkgKwogIGZhY2V0X3dyYXAoCiAgICB+c2VyaWVzLAogICAgbmNvbCA9IDEsCiAgICBzY2FsZXMgPSAiZnJlZV95IiwKICAgIGxhYmVsbGVyID0gbGFiZWxsZXIoCiAgICAgIHNlcmllcyA9IGMoCiAgICAgICAgaW5mbGF0aW9uX3lveSA9ICJBbm51YWwgSW5mbGF0aW9uIFJhdGUgKCUpIiwKICAgICAgICB1bmVtcGxveW1lbnRfcmF0ZSA9ICJVbmVtcGxveW1lbnQgUmF0ZSAoJSkiLAogICAgICAgIGZlZF9yYXRlICAgICAgICAgID0gIkZlZGVyYWwgRnVuZHMgUmF0ZSAoJSkiCiAgICAgICkKICAgICkKICApICsKICBzY2FsZV9jb2xvcl9tYW51YWwoCiAgICB2YWx1ZXMgPSBjKAogICAgICBpbmZsYXRpb25feW95ICAgICA9ICIjMkNBMDJDIiwKICAgICAgdW5lbXBsb3ltZW50X3JhdGUgPSAiI0Q2MjcyOCIsCiAgICAgIGZlZF9yYXRlICAgICAgICAgID0gInB1cnBsZSIKICAgICkKICApICsKICB0aGVtZV9taW5pbWFsKCkgKwogIHRoZW1lKAogICAgbGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiLAogICAgc3RyaXAudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTQsIGZhY2UgPSAiYm9sZCIpCiAgKSArCiAgbGFicygKICAgIHggPSAiWWVhciIsCiAgICB5ID0gIiIKICApCmBgYApQcmVwYXJlIHN1YnNldHMgb2YgZGF0YQoKYGBge3J9CmRmXzIwMDggPC0gZGZfYWxsIHw+IGZpbHRlcih5ZWFyID49IDIwMDcgJiB5ZWFyIDw9IDIwMTIpIHw+IHNlbGVjdCh5ZWFyX21vbnRoLCBpbmZsYXRpb25feW95LCB1bmVtcGxveW1lbnRfcmF0ZSwgZmVkX3JhdGUpIHw+CiAgcGl2b3RfbG9uZ2VyKAogICAgY29scyA9IC15ZWFyX21vbnRoLAogICAgbmFtZXNfdG8gPSAic2VyaWVzIiwKICAgIHZhbHVlc190byA9ICJ2YWx1ZSIKICApCgpkZl8yMDIwIDwtIGRmX2FsbCB8PiBmaWx0ZXIoeWVhciA+PSAyMDE5ICYgeWVhciA8PSAyMDI1KSB8PiBzZWxlY3QoeWVhcl9tb250aCwgaW5mbGF0aW9uX3lveSwgdW5lbXBsb3ltZW50X3JhdGUsIGZlZF9yYXRlKSB8PgogIHBpdm90X2xvbmdlcigKICAgIGNvbHMgPSAteWVhcl9tb250aCwKICAgIG5hbWVzX3RvID0gInNlcmllcyIsCiAgICB2YWx1ZXNfdG8gPSAidmFsdWUiCiAgKQpgYGAKClByZXBhcmUgYSBjaGFydCB0byBoaWdobGlnaHQgMjAwOCBhbmQgMjAyMAoKYGBge3J9CmRmX2xvbmcgPC0gZGZfYWxsIHw+IAogIHNlbGVjdCh5ZWFyX21vbnRoLCBpbmZsYXRpb25feW95LCB1bmVtcGxveW1lbnRfcmF0ZSwgZmVkX3JhdGUpIHw+CiAgcGl2b3RfbG9uZ2VyKAogICAgY29scyA9IC15ZWFyX21vbnRoLAogICAgbmFtZXNfdG8gPSAic2VyaWVzIiwKICAgIHZhbHVlc190byA9ICJ2YWx1ZSIKICApCgpkZl9sb25nJHNlcmllcyA8LSBmYWN0b3IoCiAgZGZfbG9uZyRzZXJpZXMsCiAgbGV2ZWxzID0gYygiaW5mbGF0aW9uX3lveSIsICJ1bmVtcGxveW1lbnRfcmF0ZSIsICJmZWRfcmF0ZSIpCikKCgpnZ3Bsb3QoZGZfbG9uZywgYWVzKHggPSB5ZWFyX21vbnRoLCB5ID0gdmFsdWUpKSArCgogIGdlb21fbGluZShhZXMoZ3JvdXAgPSBzZXJpZXMpLCBjb2xvciA9ICJncmF5NzAiLCBzaXplID0gMC44LCBhbHBoYSA9IDAuNSkgKwoKICAKICBnZW9tX2xpbmUoCiAgICBkYXRhID0gZGZfMjAwOCwKICAgIGFlcyh4ID0geWVhcl9tb250aCwgeSA9IHZhbHVlLCBjb2xvciA9IHNlcmllcyksCiAgICBzaXplID0gMS4zCiAgKSArCgoKICBnZW9tX2xpbmUoCiAgICBkYXRhID0gZGZfMjAyMCwKICAgIGFlcyh4ID0geWVhcl9tb250aCwgeSA9IHZhbHVlLCBjb2xvciA9IHNlcmllcyksCiAgICBzaXplID0gMS4zCiAgKSArCgogIAogIGZhY2V0X3dyYXAoCiAgICB+c2VyaWVzLAogICAgbmNvbCA9IDEsCiAgICBzY2FsZXMgPSAiZnJlZV95IiwKICAgIGxhYmVsbGVyID0gbGFiZWxsZXIoCiAgICAgIHNlcmllcyA9IGMoCiAgICAgICAgaW5mbGF0aW9uX3lveSA9ICJBbm51YWwgSW5mbGF0aW9uIFJhdGUgKCUpIiwKICAgICAgICB1bmVtcGxveW1lbnRfcmF0ZSA9ICJVbmVtcGxveW1lbnQgUmF0ZSAoJSkiLAogICAgICAgIGZlZF9yYXRlID0gIkZlZGVyYWwgRnVuZHMgUmF0ZSAoJSkiCiAgICAgICkKICAgICkKICApICsKCiAgIyBDb2xvcnMgZm9yIGhpZ2hsaWdodHMKICBzY2FsZV9jb2xvcl9tYW51YWwoCiAgICB2YWx1ZXMgPSBjKAogICAgICBpbmZsYXRpb25feW95ICAgICA9ICIjMkNBMDJDIiwKICAgICAgdW5lbXBsb3ltZW50X3JhdGUgPSAiI0Q2MjcyOCIsCiAgICAgIGZlZF9yYXRlICAgICAgICAgID0gInB1cnBsZSIKICAgICkKICApICsKCiAgdGhlbWVfbWluaW1hbChiYXNlX3NpemUgPSAxNCkgKwogIHRoZW1lKAogICAgbGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiLCAjIG9yICJub25lIiBpZiB5b3UgcHJlZmVyIG5vIGxlZ2VuZAogICAgc3RyaXAudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTQsIGNvbG9yID0gImdyYXk3MCIpLAogICAgYXhpcy50aXRsZSA9IGVsZW1lbnRfdGV4dChjb2xvciA9ICJncmF5NzAiLCBzaXplID0gMTQpLAogICAgYXhpcy50ZXh0ID0gZWxlbWVudF90ZXh0KGNvbG9yID0gImdyYXk3MCIsIHNpemUgPSAxMiksCiAgICBwYW5lbC5ncmlkID0gZWxlbWVudF9ibGFuaygpCiAgKSArCgogIGxhYnMoCiAgICB4ID0gIlllYXIiLAogICAgeSA9ICJQZXJjZW50YWdlIiwKICAgIGNvbG9yID0gImdyYXk3MCIKICApCmBgYAoKRXhwbG9yZSBhIHBvc3NpYmxlIGNoYXJ0CgpgYGB7cn0KZGYgPC0gZGYgJT4lCiAgYXJyYW5nZSh5ZWFyX21vbnRoKSAlPiUKICBtdXRhdGUoZmVkX3JhdGVfbGFnMTIgPSBsYWcoZmVkX3JhdGUsIDEpKSAgIyAxMi1tb250aCBsYWcKCmdncGxvdChkZiwgYWVzKHggPSB5ZWFyX21vbnRoKSkgKwoKICAjIEJhcnM6IGFubnVhbCBpbmZsYXRpb24gZGV2aWF0aW9uCiAgZ2VvbV9jb2woYWVzKHkgPSBkZXZpYXRpb24sIGZpbGwgPSBkZXZpYXRpb24gPiAwKSwgYWxwaGEgPSAwLjcpICsKCiAgIyBDdW11bGF0aXZlIGRldmlhdGlvbiBsaW5lCiAgZ2VvbV9saW5lKGFlcyh5ID0gY3VtX2RldiksIGNvbG9yID0gImJsYWNrIiwgc2l6ZSA9IDEuMikgKwoKICAjIExhZ2dlZCBGZWQgcmF0ZSBsaW5lIChzY2FsZWQgaWYgbmVjZXNzYXJ5KQogIGdlb21fbGluZShhZXMoeSA9IGZlZF9yYXRlX2xhZzEyKSwgY29sb3IgPSAiIzFGNzdCNCIsIHNpemUgPSAxLCBsaW5ldHlwZSA9ICJkYXNoZWQiKSArCgogICMgWmVybyBsaW5lCiAgZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0gMCwgbGluZXR5cGUgPSAiZGFzaGVkIiwgc2l6ZSA9IDAuOCkgKwoKICAjIENvbG9yIHNjYWxlIGZvciBiYXJzCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gYygiVFJVRSIgPSAiI0Q2MjcyOCIsICJGQUxTRSIgPSAiYmx1ZSIpLCBndWlkZSA9ICJub25lIikgKwoKICAjIE1pbmltYWwgdGhlbWUKICB0aGVtZV9taW5pbWFsKGJhc2Vfc2l6ZSA9IDE0KSArCiAgdGhlbWUoCiAgICBwbG90LmNhcHRpb24gPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE2LCBmYWNlID0gImJvbGQiLCBoanVzdCA9IDAuNSksCiAgICBwbG90LmNhcHRpb24ucG9zaXRpb24gPSAicGxvdCIKICApICsKCiAgIyBMYWJlbHMKICBsYWJzKAogICAgeCA9ICJZZWFyIiwKICAgIHkgPSAiSW5mbGF0aW9uIERldmlhdGlvbiAvIEZlZCBSYXRlIiwKICAgIGNhcHRpb24gPSAiQmFycyA9IGRldmlhdGlvbiBmcm9tIDIlIHRhcmdldCB8IFNvbGlkIGxpbmUgPSBjdW11bGF0aXZlIGRldmlhdGlvbiB8IERhc2hlZCBibHVlIGxpbmUgPSBGZWQgcmF0ZSAoMTItbW9udGggbGFnKSIKICApCmBgYAoKU3Vic2V0IHRoZSBzdWJzZXQKCmBgYHtyfQpkZl8yMDA4X3NsaWNlIDwtIGRmXzIwMDggfD4gZmlsdGVyKHllYXJfbW9udGggPj0gIjIwMDgtMDEtMDEiICYgeWVhcl9tb250aCA8PSAiMjAxMC0wMS0wMSIpCmBgYAoKUHJlcGFyZSBhIGhpZ2hsaWdodGVkIGdyYXBoIG9mIDIwMDgKCmBgYHtyfQpnZ3Bsb3QoZGZfMjAwOCwgYWVzKHggPSB5ZWFyX21vbnRoLCB5ID0gdmFsdWUpKSArCgogICMgR3JheSBiYWNrZ3JvdW5kIGxpbmVzCiAgZ2VvbV9saW5lKGFlcyhncm91cCA9IHNlcmllcyksIGNvbG9yID0gImdyYXk3MCIsIHNpemUgPSAwLjgsIGFscGhhID0gMC41LCBzaG93LmxlZ2VuZCA9IEZBTFNFKSArCgogICMgSGlnaGxpZ2h0ZWQgc2xpY2UKICBnZW9tX2xpbmUoCiAgICBkYXRhID0gZGZfMjAwOF9zbGljZSwKICAgIGFlcyh4ID0geWVhcl9tb250aCwgeSA9IHZhbHVlLCBjb2xvciA9IHNlcmllcyksCiAgICBzaXplID0gMS4zCiAgKSArCgogICMgRmFjZXRzCiAjIGZhY2V0X3dyYXAoCiAjICAgfnNlcmllcywKIyAgICBuY29sID0gMSwKIyAgICBzY2FsZXMgPSAiZnJlZV95IiwKIyAgICBsYWJlbGxlciA9IGxhYmVsbGVyKAojICAgICAgc2VyaWVzID0gYygKIyAgICAgICAgaW5mbGF0aW9uX3lveSA9ICJBbm51YWwgSW5mbGF0aW9uIFJhdGUgKCUpIiwKIyAgICAgICAgdW5lbXBsb3ltZW50X3JhdGUgPSAiVW5lbXBsb3ltZW50IFJhdGUgKCUpIiwKIyAgICAgICAgZmVkX3JhdGUgPSAiRmVkZXJhbCBGdW5kcyBSYXRlICglKSIKIyAgICAgICkKIyAgICApCiMgICkgKwoKICAjIENvbG9ycyBhbmQgY3VzdG9tIGxlZ2VuZCBsYWJlbHMKICBzY2FsZV9jb2xvcl9tYW51YWwoCiAgICB2YWx1ZXMgPSBjKAogICAgICBpbmZsYXRpb25feW95ICAgICA9ICIjMkNBMDJDIiwKICAgICAgdW5lbXBsb3ltZW50X3JhdGUgPSAiI0Q2MjcyOCIsCiAgICAgIGZlZF9yYXRlICAgICAgICAgID0gInB1cnBsZSIKICAgICksCiAgICBsYWJlbHMgPSBjKAogICAgICBpbmZsYXRpb25feW95ICAgICA9ICJJbmZsYXRpb24gKFlvWSAlKSIsCiAgICAgIHVuZW1wbG95bWVudF9yYXRlID0gIlVuZW1wbG95bWVudCAoJSkiLAogICAgICBmZWRfcmF0ZSAgICAgICAgICA9ICJGZWQgUmF0ZSAoJSkiCiAgICApCiAgKSArCgogICMgVGhlbWUKICB0aGVtZV9taW5pbWFsKGJhc2Vfc2l6ZSA9IDE0KSArCiAgdGhlbWUoCiAgICBsZWdlbmQucG9zaXRpb24gPSAidG9wIiwgICAjIHNob3cgdGhlIGxlZ2VuZAogICAgbGVnZW5kLnRleHQgPSBlbGVtZW50X3RleHQoY29sb3IgPSAiZ3JheTcwIiksCiAgICBzdHJpcC50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNCwgY29sb3IgPSAiZ3JheTcwIiksCiAgICBheGlzLnRpdGxlID0gZWxlbWVudF90ZXh0KGNvbG9yID0gImdyYXk3MCIsIHNpemUgPSAxNCksCiAgICBheGlzLnRleHQgPSBlbGVtZW50X3RleHQoY29sb3IgPSAiZ3JheTcwIiwgc2l6ZSA9IDEyKSwKICAgIHBhbmVsLmdyaWQgPSBlbGVtZW50X2JsYW5rKCkKICApICsKCiAgbGFicygKICAgIHggPSAiWWVhciIsCiAgICB5ID0gIlBlcmNlbnRhZ2UiLAogICAgY29sb3IgPSBOVUxMICAjIHJlbW92ZXMgZGVmYXVsdCAiU2VyaWVzIiB0aXRsZQogICkKYGBgCgpgYGB7cn0KZGZfMjAyMF9zbGljZSA8LSBkZl8yMDIwIHw+IGZpbHRlcih5ZWFyX21vbnRoID49ICIyMDIwLTAxLTAxIiAmIHllYXJfbW9udGggPD0gIjIwMjUtMDEtMDEiKQpgYGAKClByZXBhcmUgYSBoaWdobGlnaHQgb2YgMjAyMCBjcmlzaXMKYGBge3J9CmdncGxvdChkZl8yMDIwLCBhZXMoeCA9IHllYXJfbW9udGgsIHkgPSB2YWx1ZSkpICsKCiAgIyBHcmF5IGJhY2tncm91bmQgbGluZXMKICBnZW9tX2xpbmUoYWVzKGdyb3VwID0gc2VyaWVzKSwgY29sb3IgPSAiZ3JheTcwIiwgc2l6ZSA9IDAuOCwgYWxwaGEgPSAwLjUsIHNob3cubGVnZW5kID0gRkFMU0UpICsKCiAgIyBIaWdobGlnaHRlZCBzbGljZQogIGdlb21fbGluZSgKICAgIGRhdGEgPSBkZl8yMDIwX3NsaWNlLAogICAgYWVzKHggPSB5ZWFyX21vbnRoLCB5ID0gdmFsdWUsIGNvbG9yID0gc2VyaWVzKSwKICAgIHNpemUgPSAxLjMKICApICsKCiAgIyBGYWNldHMKICMgZmFjZXRfd3JhcCgKICMgICB+c2VyaWVzLAojICAgIG5jb2wgPSAxLAojICAgIHNjYWxlcyA9ICJmcmVlX3kiLAojICAgIGxhYmVsbGVyID0gbGFiZWxsZXIoCiMgICAgICBzZXJpZXMgPSBjKAojICAgICAgICBpbmZsYXRpb25feW95ID0gIkFubnVhbCBJbmZsYXRpb24gUmF0ZSAoJSkiLAojICAgICAgICB1bmVtcGxveW1lbnRfcmF0ZSA9ICJVbmVtcGxveW1lbnQgUmF0ZSAoJSkiLAojICAgICAgICBmZWRfcmF0ZSA9ICJGZWRlcmFsIEZ1bmRzIFJhdGUgKCUpIgojICAgICAgKQojICAgICkKIyAgKSArCgogICMgQ29sb3JzIGFuZCBjdXN0b20gbGVnZW5kIGxhYmVscwogIHNjYWxlX2NvbG9yX21hbnVhbCgKICAgIHZhbHVlcyA9IGMoCiAgICAgIGluZmxhdGlvbl95b3kgICAgID0gIiMyQ0EwMkMiLAogICAgICB1bmVtcGxveW1lbnRfcmF0ZSA9ICIjRDYyNzI4IiwKICAgICAgZmVkX3JhdGUgICAgICAgICAgPSAicHVycGxlIgogICAgKSwKICAgIGxhYmVscyA9IGMoCiAgICAgIGluZmxhdGlvbl95b3kgICAgID0gIkluZmxhdGlvbiAoWW9ZICUpIiwKICAgICAgdW5lbXBsb3ltZW50X3JhdGUgPSAiVW5lbXBsb3ltZW50ICglKSIsCiAgICAgIGZlZF9yYXRlICAgICAgICAgID0gIkZlZCBSYXRlICglKSIKICAgICkKICApICsKCiAgIyBUaGVtZQogIHRoZW1lX21pbmltYWwoYmFzZV9zaXplID0gMTQpICsKICB0aGVtZSgKICAgIGxlZ2VuZC5wb3NpdGlvbiA9ICJ0b3AiLCAgICMgc2hvdyB0aGUgbGVnZW5kCiAgICBsZWdlbmQudGV4dCA9IGVsZW1lbnRfdGV4dChjb2xvciA9ICJncmF5NzAiKSwKICAgIHN0cmlwLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE0LCBjb2xvciA9ICJncmF5NzAiKSwKICAgIGF4aXMudGl0bGUgPSBlbGVtZW50X3RleHQoY29sb3IgPSAiZ3JheTcwIiwgc2l6ZSA9IDE0KSwKICAgIGF4aXMudGV4dCA9IGVsZW1lbnRfdGV4dChjb2xvciA9ICJncmF5NzAiLCBzaXplID0gMTIpLAogICAgcGFuZWwuZ3JpZCA9IGVsZW1lbnRfYmxhbmsoKQogICkgKwoKICBsYWJzKAogICAgeCA9ICJZZWFyIiwKICAgIHkgPSAiUGVyY2VudGFnZSIsCiAgICBjb2xvciA9IE5VTEwgICMgcmVtb3ZlcyBkZWZhdWx0ICJTZXJpZXMiIHRpdGxlCiAgKQpgYGAKCgoKYGBge3J9CmdncGxvdChkZl8yMDA4LCBhZXMoeCA9IHllYXJfbW9udGgsIHkgPSB2YWx1ZSkpICsKCiAgZ2VvbV9saW5lKGFlcyhncm91cCA9IHNlcmllcywgY29sb3IgPSBzZXJpZXMpLCBzaXplID0gMC44LCBhbHBoYSA9IDAuNSkgKwoKICAKICBnZW9tX2xpbmUoCiAgICBkYXRhID0gZGZfMjAwOCwKICAgIGFlcyh4ID0geWVhcl9tb250aCwgeSA9IHZhbHVlLCBjb2xvciA9IHNlcmllcyksCiAgICBzaXplID0gMS4zCiAgKSArCiAgc2NhbGVfY29sb3JfbWFudWFsKAogICAgdmFsdWVzID0gYygKICAgICAgaW5mbGF0aW9uX3lveSAgICAgPSAiIzJDQTAyQyIsCiAgICAgIHVuZW1wbG95bWVudF9yYXRlID0gIiNENjI3MjgiLAogICAgICBmZWRfcmF0ZSAgICAgICAgICA9ICJwdXJwbGUiCiAgICApLAogICAgbGFiZWxzID0gYygKICAgICAgaW5mbGF0aW9uX3lveSAgICAgPSAiSW5mbGF0aW9uIChZb1kgJSkiLAogICAgICB1bmVtcGxveW1lbnRfcmF0ZSA9ICJVbmVtcGxveW1lbnQgKCUpIiwKICAgICAgZmVkX3JhdGUgICAgICAgICAgPSAiRmVkZXJhbCBGdW5kcyBSYXRlICglKSIKICAgICkKICApICsKCiAgdGhlbWVfbWluaW1hbChiYXNlX3NpemUgPSAxNCkgKwogIHRoZW1lKAogICAgbGVnZW5kLnBvc2l0aW9uID0gImJvdHRvbSIsCiAgICBsZWdlbmQudGV4dCA9IGVsZW1lbnRfdGV4dChjb2xvciA9ICJncmF5NzAiKSwKICAgIHN0cmlwLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE0LCBjb2xvciA9ICJncmF5NzAiKSwKICAgIGF4aXMudGl0bGUgPSBlbGVtZW50X3RleHQoY29sb3IgPSAiZ3JheTcwIiwgc2l6ZSA9IDE0KSwKICAgIGF4aXMudGV4dCA9IGVsZW1lbnRfdGV4dChjb2xvciA9ICJncmF5NzAiLCBzaXplID0gMTIpLAogICAgcGFuZWwuZ3JpZCA9IGVsZW1lbnRfYmxhbmsoKQogICkgKwoKICBsYWJzKAogICAgeCA9ICJZZWFyIiwKICAgIHkgPSAiUGVyY2VudGFnZSIsCiAgICBjb2xvciA9IE5VTEwKICApCmBgYAoK