Introduction

Code and values for Figures 4 and 5 in Section 4 of the report “Excess deaths”

Raw code can be downloaded by selecting the Download Rmd option from the Code drop down menu at the top of this page.

Software

R packages and required helper functions.

library(tidyverse)
library(curl)
library(readxl)
library(lubridate)
library(forcats)
library(patchwork)
library(ggthemes)
library(socviz)
library(here)

#Helper function
`%nin%` <- negate(`%in%`)

#Short cut for csv output with html tables
my_datatable <- function(x){
  DT::datatable(x, extensions = "Buttons", options = list(dom = "Bfrtip", 
                                                          buttons = c("csv")))
}

#Baseline plot settings
theme_set(theme_minimal(base_family = "Roboto", base_size = 20) +
            theme(panel.grid.minor = element_blank(),
                  axis.title.y = element_text(margin = margin(0, 20, 0, 0)),
                  axis.title.x = element_text(margin = margin(20, 0, 0, 0)),
                  plot.caption = element_text(colour = "#AAAAAA")))#,
                  #plot.margin = margin(3,15,3,3,"mm")))

#global options for scientific numbers and significant digits.          
options(scipen = 10,
        digits = 1)

Data

Data came from disparate sources. The tabset below identifies where and how it was wrangled in order to be combined into one UK table.

England

Data sourced from here and here and collated into .csv files by Pietro Patrignani. I have saved this file in the excess_mort_data folder available on the project GitHub repository.

england <- read_csv(here("excess_mort_data/Weekly Summary England.csv"))

england %<>% 
  slice(-1) %>% 
  select(location,
         week_number = `week number`,
         all = `all deaths`,
         non_covid, covid, 
         average = `average 2015-2019`,
         excess = `excess deaths`, 
         country) %>% 
  mutate(location = factor(location,
                           levels = c("Hospital", "Care Home", "Home", "Other"),
                           labels = c("Hospital", "Care Home", "Home", "Other"))) %>% 
  mutate_at(.vars = c("week_number", "all", "covid"), as.integer)

my_datatable(england)

Scotland

This comes from two files on the National Records of Scotland (NRS) site. One has weekly COIVD and all-cause deaths, the other the weekly numbers (including averages) for the previous 5 years. URLs are shown in the code chunk. The data is downloaded directly evertime this chunk is run.

temp_1 <- tempfile()
temp_2 <- tempfile()
source <- "https://www.nrscotland.gov.uk/files//statistics/covid19/covid-deaths-data-week-26.zip"

temp_1 <- curl_download(url = source, destfile = temp_1, quiet = FALSE)
unzip(temp_1, exdir = temp_2)

ch_death_covid <- read_csv(file.path(temp_2,"covid-deaths-data-week-26_Table 1 - COVID deaths.csv"), skip = 3)
ch_death_all <- read_csv(file.path(temp_2, "covid-deaths-data-week-26_Table 2 - All deaths.csv"), skip = 3)
#5 year average can be downladed directly from this link...
ch_death_average <- read_csv("https://www.nrscotland.gov.uk/files//statistics/covid19/weekly-deaths-by-location-2015-2019.csv", skip = 2)

#Now tidy and join together

loc_names <- c("Care Home", "Home and other non institution", "Hospital",
          "Other institution")

# Create a look-up table for week numbers to dates
week_lookup <- tibble(
  week_number = 1:52,
  week_date = seq(ymd(20191230), ymd(20201221), by = "1 week"))


#Wrangle Average deaths
ch_death_average %>% 
  slice(2:6, 9:13, 16:20, 23:27) %>% 
  mutate(location = rep(loc_names, each = 5, times = 1)) %>% 
  select(year = `Week number2`, location, everything(), -`53`) %>% 
  pivot_longer(cols = `1`:`52`, names_to = "week_number",
               values_to = "n_deaths") %>% 
  group_by(location, week_number) %>%
  mutate(min_deaths = min(n_deaths),
         max_deaths = max(n_deaths),
         mean_deaths = mean(n_deaths)) %>% 
  distinct(location, week_number, .keep_all = TRUE) %>% 
  select(-year, -n_deaths) %>% 
  ungroup %>% 
  mutate(week_number = as.integer(week_number)) -> sc

#Wrangle all deaths
ch_death_all %>% 
  select(location = X2, everything(), -`Week beginning`, -X30:-X65) %>% 
  slice(85:88) %>%  
  mutate_at(vars(`30-Dec-19`:`22-Jun-20`), as.numeric) %>% 
  pivot_longer(cols = `30-Dec-19`:`22-Jun-20`, names_to = "date",
               values_to = "deaths_all_2020") %>% 
  mutate(date = dmy(date),
         week_number = rep(1:26, each = 1, times = 4),
         location = rep(loc_names, each = 26, times = 1)) %>% 
  select(-date) %>% 
  left_join(sc, .) -> sc


#Wrangle Covid deaths and join together
ch_death_covid %>% 
  select(location = X2, everything(), -`Week beginning`,
         -`Year to Date`:-X44) %>% 
  slice(83:86) %>%  
  pivot_longer(cols = `30-Dec-19`:`22-Jun-20`, names_to = "date",
               values_to = "deaths_covid_2020") %>% 
  mutate(date = dmy(date),
         week_number = rep(1:26, each = 1, times = 4),
         location = rep(loc_names, each = 26, times = 1)) %>% 
  select(-date) %>% 
  left_join(sc, .) %>% 
  mutate(deaths_nonCovid_2020 = deaths_all_2020 - deaths_covid_2020,
         location = factor(location,
                           levels = c("Hospital", "Care Home", 
                                      "Home and other non institution", 
                                      "Other institution"),
                           labels = c("Hospital", "Care Home", "Home", "Other"))) %>% 
  left_join(., week_lookup) %>% 
  filter(week_number >=11 & week_number <= 26) %>% 
  select(-min_deaths, -max_deaths, -X29, -week_date) %>% 
  rename(all = deaths_all_2020,
         covid = deaths_covid_2020,
         non_covid = deaths_nonCovid_2020,
         average = mean_deaths) %>% 
  mutate(excess = all - average,
         country = "Scotland") -> sc

sc %>% 
  round_df(.) %>% 
  my_datatable(.)

Wales

Same source as England data. Also wrangled into a .csv by Pietro.

wales <- read_csv(here("excess_mort_data/Weekly Summary Wales.csv"))

wales %<>% 
  slice(-1) %>% 
  select(location,
         week_number = `week number`,
         all = `all deaths`,
         non_covid, covid, 
         average = `average 2015-2019`,
         excess = `excess deaths`, 
         country) %>% 
  mutate(location = factor(location,
                           levels = c("Hospital", "Care Home", "Home", "Other"),
                           labels = c("Hospital", "Care Home", "Home", "Other"))) %>% 
  mutate_at(.vars = c("week_number", "all", "covid"), as.integer)

my_datatable(wales)

Northern Ireland

Multisheet Excel file via Siobhán Murphy as requested and provided direct from the Northern Ireland Statistics and Research Agency (NISRA) who are keen to highlight these figures are provisional. Also need to point out here the figures we got from NISRA don’t break down by COVID/non-COVID deaths. Needs some wrangling….

#Start with hospital deaths on sheet 3
ni_hosp <- read_xlsx(here("excess_mort_data/NI results_revised.xlsx"), sheet = 3, 
                    range = "A2:I18") %>% 
  mutate(location = "Hospital") %>% 
  select(location,
         week_number = `...1`,
         all = `2020`,
         average = Average,
         excess)
 
#Now ingest care home data - sheet 2
ni_ch <- read_xlsx(here("excess_mort_data/NI results_revised.xlsx"), sheet = 2,
                   range = "A2:I18") %>% 
  mutate(location = "Care Home") %>% 
  select(location, 
         week_number = `...1`,
         all = `2020`,
         average = Average,
         excess)

#Home deaths - sheet 4
ni_home <- read_xlsx(here("excess_mort_data/NI results_revised.xlsx"), sheet = 4,
                     range = "A2:I18") %>% 
  mutate(location = "Home") %>% 
  select(location,
         week_number = `...1`,
         all = `2020`,
         average = Average,
         excess)

#And other place of death - sheet 5
ni_other <-  read_xlsx(here("excess_mort_data/NI results_revised.xlsx"), sheet = 5,
                     range = "A2:I18") %>% 
  mutate(location = "Other") %>% 
  select(location,
         week_number = `...1`,
         all = `2020`,
         average = Average,
         excess)

#Join these objects together
ni <- 
  bind_rows(ni_hosp, ni_ch, ni_home, ni_other) %>% 
  mutate(country = "Northern Ireland") %>% 
  separate(week_number, c("drop", "week_number"), sep = " ") %>% 
  mutate(week_number = as.integer(week_number)) %>% 
    select(-drop)


my_datatable(ni)

Combined

With each nations data now wrangled into the same format we can join them all together into one object - uk.

uk <- bind_rows(england, sc, wales, ni)

uk %>%
  mutate(country = factor(country, 
                          levels = c("England", "Scotland", 
                                     "Wales", "Northern Ireland"))) %>% 
  select(country, everything()) -> uk
my_datatable(uk)

Weekly P-score by Nation

No we have all the information combined in the uk object we can start plotting. Firstly the weekly excess by nation for Figure 5.

Plot

fig_5 <- 
  uk %>% 
  group_by(country, week_number) %>%  
  summarise(all = sum(all),
            average = sum(average), 
            excess = all - average) %>% 
  mutate(pct_change = (excess / average * 100)) %>% 
  ggplot(aes(week_number, pct_change, colour = country)) +
  geom_point(size = 1.5) +
  geom_line(size = 1.5) +
  scale_colour_wsj(guide = guide_legend(keywidth = 2)) +
  scale_y_continuous(limits = c(-15, 120),
                     breaks = scales::pretty_breaks(n = 6),
                     labels = scales::percent_format(scale = 1)) +
  scale_x_continuous(breaks = scales::pretty_breaks(n = 12)) +
  theme(legend.position = "top") +
  labs(title = "Weeekly excess mortality in the UK.",
       subtitle = "Weeks 11-26 2020",
       x = "Week number",
       y = "% change from 5-yr average",
       colour = "",
       caption = "Source: ONS, NRS & NISRA\nFigures are provisional\nCode:https://github.com/davidhen/ltc_covid_uk") 

fig_5

Table

uk %>% 
  group_by(country, week_number) %>%  
  summarise(all = sum(all),
            average = sum(average), 
            excess = all - average) %>% 
  mutate(pct_change = (excess / average * 100)) %>% 
  round_df(.) %>% 
  my_datatable(.)

P Score Breakdown plot

Figure 6 is a combination of 3 plots. First we show the individual plots and underlying tables

Overall

Summarising the excess across all weeks 11-26 by nation

Plot

uk %>% 
  group_by(country) %>% 
  summarise(all = sum(all), 
            average = sum(average),
            excess = all - average,
            pct_change = excess / average * 100) %>% 
  ggplot(aes(country, pct_change, fill = country)) +
  geom_col() +
  scale_fill_wsj() +
  scale_y_continuous(limits = c(0,40),
                     labels = scales::percent_format(scale = 1)) +
  #scale_x_discrete(position = "top") +
  theme(legend.position = "none",
        axis.title.y = element_text(size = 16)) +
  labs(title = "Overall",
       x = "",
       y = "% difference from 5 year average",
       caption = "") -> uk_excess
uk_excess

Table

uk %>% 
  group_by(country) %>%  
  summarise(all = sum(all),
            average = sum(average), 
            excess = all - average) %>% 
  mutate(pct_change = (excess / average * 100)) %>% 
  round_df(.) %>% 
  my_datatable(.)

by Location only

Again a summary across all weeks 11-26 but split by location of death.

Plot

fig_excess_uk_2 <-
  uk %>% 
  group_by(country, location) %>% 
  summarise(all = sum(all), 
            average = sum(average),
            excess = all - average,
            pct_change = excess / average * 100) %>% 
  ggplot(aes(country, pct_change, fill = country)) +
  geom_col() +
  facet_grid(~location, switch = "x") +
  scale_fill_wsj() +
  scale_y_continuous(limits = c(-20,80),
                     labels = scales::percent_format(scale = 1),
                     breaks = scales::pretty_breaks()) +
  theme(legend.position = "top",
        axis.text.x = element_blank(),
        strip.placement = "outside",
        axis.title.y = element_text(size = 16)) +
  labs(title = "by Location",
       x = "",
       y = "% difference from 5 year average",
       fill = "")
fig_excess_uk_2

Table

uk %>% 
  group_by(country, location) %>%  
  summarise(all = sum(all),
            covid = sum(covid),
            non_covid = sum(non_covid),
            average = sum(average), 
            excess = all - average) %>% 
  mutate(pct_change = (excess / average * 100)) %>% 
  arrange(location) %>% 
  round_df(.) %>% 
  my_datatable(.)

By location and week

Finally, weekly change by location and country.

Plot

fig_uk_excess_1 <- 
  uk %>% 
  mutate(pct_change = (excess / average * 100)) %>% 
  ggplot(aes(week_number, pct_change, fill = country)) +
  geom_col() +
  facet_grid(location~country) +
  scale_fill_wsj() +
  scale_y_continuous(limits = c(-100, 300),
                     labels = scales::percent_format(scale = 1)) +
  theme(legend.position = "none",
        axis.title.y = element_text(size = 16),
        panel.spacing.y = unit(2, "lines")) +
  labs(title = "by Location and Week",
       x = "Week Number",
       y = "% difference from 5 year average")#,
       #caption = "Source: ONS & NRS\nCode:https://github.com/davidhen/ltc_covid_uk/blob/master/excess_mort_plot.Rmd")
fig_uk_excess_1

Table

uk %>% 
  mutate(pct_change = (excess / average * 100)) %>% 
  arrange(country, location, week_number) %>% 
  round_df(.) %>% 
  my_datatable(.)

Combination plot Figure 6

Using the patchwork package to combine together.

(uk_excess + fig_excess_uk_2) / fig_uk_excess_1 +
  plot_annotation(title = "Excess mortality in the UK. Weeks 11-26 2020",
                  subtitle = "Breakdown",
                  caption = "Source: ONS, NRS & NISRA\nFigures are provisional\nCode:https://github.com/davidhen/ltc_covid_uk") +
  plot_layout(heights = c(1, 1.2))  -> fig_6
fig_6

HOME PAGE

devtools::session_info()
## ─ Session info ────────────────────────────────────────
##  setting  value                       
##  version  R version 4.1.0 (2021-05-18)
##  os       macOS Big Sur 11.4          
##  system   aarch64, darwin20           
##  ui       RStudio                     
##  language (EN)                        
##  collate  en_GB.UTF-8                 
##  ctype    en_GB.UTF-8                 
##  tz       Europe/London               
##  date     2021-06-14                  
## 
## ─ Packages ────────────────────────────────────────────
##  package     * version date       lib source        
##  assertthat    0.2.1   2019-03-21 [1] CRAN (R 4.1.0)
##  backports     1.2.1   2020-12-09 [1] CRAN (R 4.1.0)
##  broom         0.7.7   2021-06-13 [1] CRAN (R 4.1.0)
##  bslib         0.2.5.1 2021-05-18 [1] CRAN (R 4.1.0)
##  cachem        1.0.5   2021-05-15 [1] CRAN (R 4.1.0)
##  callr         3.7.0   2021-04-20 [1] CRAN (R 4.1.0)
##  cellranger    1.1.0   2016-07-27 [1] CRAN (R 4.1.0)
##  cli           2.5.0   2021-04-26 [1] CRAN (R 4.1.0)
##  colorspace    2.0-1   2021-05-04 [1] CRAN (R 4.1.0)
##  crayon        1.4.1   2021-02-08 [1] CRAN (R 4.1.0)
##  crosstalk     1.1.1   2021-01-12 [1] CRAN (R 4.1.0)
##  curl        * 4.3.1   2021-04-30 [1] CRAN (R 4.1.0)
##  DBI           1.1.1   2021-01-15 [1] CRAN (R 4.1.0)
##  dbplyr        2.1.1   2021-04-06 [1] CRAN (R 4.1.0)
##  desc          1.3.0   2021-03-05 [1] CRAN (R 4.1.0)
##  devtools      2.4.2   2021-06-07 [1] CRAN (R 4.1.0)
##  digest        0.6.27  2020-10-24 [1] CRAN (R 4.1.0)
##  dplyr       * 1.0.6   2021-05-05 [1] CRAN (R 4.1.0)
##  DT            0.18    2021-04-14 [1] CRAN (R 4.1.0)
##  ellipsis      0.3.2   2021-04-29 [1] CRAN (R 4.1.0)
##  evaluate      0.14    2019-05-28 [1] CRAN (R 4.1.0)
##  fansi         0.5.0   2021-05-25 [1] CRAN (R 4.1.0)
##  farver        2.1.0   2021-02-28 [1] CRAN (R 4.1.0)
##  fastmap       1.1.0   2021-01-25 [1] CRAN (R 4.1.0)
##  feather       0.3.5   2019-09-15 [1] CRAN (R 4.1.0)
##  forcats     * 0.5.1   2021-01-27 [1] CRAN (R 4.1.0)
##  fs            1.5.0   2020-07-31 [1] CRAN (R 4.1.0)
##  generics      0.1.0   2020-10-31 [1] CRAN (R 4.1.0)
##  ggplot2     * 3.3.3   2020-12-30 [1] CRAN (R 4.1.0)
##  ggthemes    * 4.2.4   2021-01-20 [1] CRAN (R 4.1.0)
##  glue          1.4.2   2020-08-27 [1] CRAN (R 4.1.0)
##  gtable        0.3.0   2019-03-25 [1] CRAN (R 4.1.0)
##  haven         2.4.1   2021-04-23 [1] CRAN (R 4.1.0)
##  here        * 1.0.1   2020-12-13 [1] CRAN (R 4.1.0)
##  highr         0.9     2021-04-16 [1] CRAN (R 4.1.0)
##  hms           1.1.0   2021-05-17 [1] CRAN (R 4.1.0)
##  htmltools     0.5.1.1 2021-01-22 [1] CRAN (R 4.1.0)
##  htmlwidgets   1.5.3   2020-12-10 [1] CRAN (R 4.1.0)
##  httr          1.4.2   2020-07-20 [1] CRAN (R 4.1.0)
##  jquerylib     0.1.4   2021-04-26 [1] CRAN (R 4.1.0)
##  jsonlite      1.7.2   2020-12-09 [1] CRAN (R 4.1.0)
##  knitr         1.33    2021-04-24 [1] CRAN (R 4.1.0)
##  labeling      0.4.2   2020-10-20 [1] CRAN (R 4.1.0)
##  lifecycle     1.0.0   2021-02-15 [1] CRAN (R 4.1.0)
##  lubridate   * 1.7.10  2021-02-26 [1] CRAN (R 4.1.0)
##  magrittr      2.0.1   2020-11-17 [1] CRAN (R 4.1.0)
##  memoise       2.0.0   2021-01-26 [1] CRAN (R 4.1.0)
##  modelr        0.1.8   2020-05-19 [1] CRAN (R 4.1.0)
##  munsell       0.5.0   2018-06-12 [1] CRAN (R 4.1.0)
##  patchwork   * 1.1.1   2020-12-17 [1] CRAN (R 4.1.0)
##  pillar        1.6.1   2021-05-16 [1] CRAN (R 4.1.0)
##  pkgbuild      1.2.0   2020-12-15 [1] CRAN (R 4.1.0)
##  pkgconfig     2.0.3   2019-09-22 [1] CRAN (R 4.1.0)
##  pkgload       1.2.1   2021-04-06 [1] CRAN (R 4.1.0)
##  prettyunits   1.1.1   2020-01-24 [1] CRAN (R 4.1.0)
##  processx      3.5.2   2021-04-30 [1] CRAN (R 4.1.0)
##  ps            1.6.0   2021-02-28 [1] CRAN (R 4.1.0)
##  purrr       * 0.3.4   2020-04-17 [1] CRAN (R 4.1.0)
##  R6            2.5.0   2020-10-28 [1] CRAN (R 4.1.0)
##  Rcpp          1.0.6   2021-01-15 [1] CRAN (R 4.1.0)
##  readr       * 1.4.0   2020-10-05 [1] CRAN (R 4.1.0)
##  readxl      * 1.3.1   2019-03-13 [1] CRAN (R 4.1.0)
##  rematch       1.0.1   2016-04-21 [1] CRAN (R 4.1.0)
##  remotes       2.4.0   2021-06-02 [1] CRAN (R 4.1.0)
##  reprex        2.0.0   2021-04-02 [1] CRAN (R 4.1.0)
##  rlang         0.4.11  2021-04-30 [1] CRAN (R 4.1.0)
##  rmarkdown   * 2.8     2021-05-07 [1] CRAN (R 4.1.0)
##  rprojroot     2.0.2   2020-11-15 [1] CRAN (R 4.1.0)
##  rstudioapi    0.13    2020-11-12 [1] CRAN (R 4.1.0)
##  rvest         1.0.0   2021-03-09 [1] CRAN (R 4.1.0)
##  sass          0.4.0   2021-05-12 [1] CRAN (R 4.1.0)
##  scales        1.1.1   2020-05-11 [1] CRAN (R 4.1.0)
##  sessioninfo   1.1.1   2018-11-05 [1] CRAN (R 4.1.0)
##  socviz      * 1.2     2020-06-10 [1] CRAN (R 4.1.0)
##  stringi       1.6.2   2021-05-17 [1] CRAN (R 4.1.0)
##  stringr     * 1.4.0   2019-02-10 [1] CRAN (R 4.1.0)
##  testthat      3.0.2   2021-02-14 [1] CRAN (R 4.1.0)
##  tibble      * 3.1.2   2021-05-16 [1] CRAN (R 4.1.0)
##  tidyr       * 1.1.3   2021-03-03 [1] CRAN (R 4.1.0)
##  tidyselect    1.1.1   2021-04-30 [1] CRAN (R 4.1.0)
##  tidyverse   * 1.3.1   2021-04-15 [1] CRAN (R 4.1.0)
##  usethis       2.0.1   2021-02-10 [1] CRAN (R 4.1.0)
##  utf8          1.2.1   2021-03-12 [1] CRAN (R 4.1.0)
##  vctrs         0.3.8   2021-04-29 [1] CRAN (R 4.1.0)
##  withr         2.4.2   2021-04-18 [1] CRAN (R 4.1.0)
##  xfun          0.23    2021-05-15 [1] CRAN (R 4.1.0)
##  xml2          1.3.2   2020-04-23 [1] CRAN (R 4.1.0)
##  yaml          2.2.1   2020-02-01 [1] CRAN (R 4.1.0)
## 
## [1] /Library/Frameworks/R.framework/Versions/4.1-arm64/Resources/library
LS0tCnRpdGxlOiAiRmlsZSAzIgphdXRob3I6ICJEYXZpZCBIZW5kZXJzb24iCmRhdGU6ICdgciBmb3JtYXQoU3lzLkRhdGUoKSwgIiVCICVkLCAlWSIpYCcKLS0tCgpgYGB7ciBzZXR1cCwgZWNobz1GQUxTRX0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KGVjaG8gPSBUUlVFLAogICAgICAgICAgICAgICAgICAgICAgZmlnLndpZHRoID0gMTIsIGZpZy5oZWlnaHQgPSA5LAogICAgICAgICAgICAgICAgICAgICAgd2FybmluZyA9IEZBTFNFLCBtZXNzYWdlID0gRkFMU0UsCiAgICAgICAgICAgICAgICAgICAgICBjbGFzcy5zb3VyY2U9ImJnLXN1Y2Nlc3MiKQpgYGAKCgojIEludHJvZHVjdGlvbgoKQ29kZSBhbmQgdmFsdWVzIGZvciBGaWd1cmVzIDQgYW5kIDUgaW4gU2VjdGlvbiA0IG9mIHRoZSByZXBvcnQgIkV4Y2VzcyBkZWF0aHMiCgpSYXcgY29kZSBjYW4gYmUgZG93bmxvYWRlZCBieSBzZWxlY3RpbmcgdGhlIGBEb3dubG9hZCBSbWRgIG9wdGlvbiBmcm9tIHRoZSBgQ29kZWAgZHJvcCBkb3duIG1lbnUgYXQgdGhlIHRvcCBvZiB0aGlzIHBhZ2UuCgojIyBTb2Z0d2FyZQoKUiBwYWNrYWdlcyBhbmQgcmVxdWlyZWQgaGVscGVyIGZ1bmN0aW9ucy4KCmBgYHtyLCB3YXJuaW5nPUZBTFNFLCBtZXNzYWdlPUZBTFNFfQpsaWJyYXJ5KHRpZHl2ZXJzZSkKbGlicmFyeShjdXJsKQpsaWJyYXJ5KHJlYWR4bCkKbGlicmFyeShsdWJyaWRhdGUpCmxpYnJhcnkoZm9yY2F0cykKbGlicmFyeShwYXRjaHdvcmspCmxpYnJhcnkoZ2d0aGVtZXMpCmxpYnJhcnkoc29jdml6KQpsaWJyYXJ5KGhlcmUpCgojSGVscGVyIGZ1bmN0aW9uCmAlbmluJWAgPC0gbmVnYXRlKGAlaW4lYCkKCiNTaG9ydCBjdXQgZm9yIGNzdiBvdXRwdXQgd2l0aCBodG1sIHRhYmxlcwpteV9kYXRhdGFibGUgPC0gZnVuY3Rpb24oeCl7CiAgRFQ6OmRhdGF0YWJsZSh4LCBleHRlbnNpb25zID0gIkJ1dHRvbnMiLCBvcHRpb25zID0gbGlzdChkb20gPSAiQmZydGlwIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBidXR0b25zID0gYygiY3N2IikpKQp9CgojQmFzZWxpbmUgcGxvdCBzZXR0aW5ncwp0aGVtZV9zZXQodGhlbWVfbWluaW1hbChiYXNlX2ZhbWlseSA9ICJSb2JvdG8iLCBiYXNlX3NpemUgPSAyMCkgKwogICAgICAgICAgICB0aGVtZShwYW5lbC5ncmlkLm1pbm9yID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgICAgICAgICAgICBheGlzLnRpdGxlLnkgPSBlbGVtZW50X3RleHQobWFyZ2luID0gbWFyZ2luKDAsIDIwLCAwLCAwKSksCiAgICAgICAgICAgICAgICAgIGF4aXMudGl0bGUueCA9IGVsZW1lbnRfdGV4dChtYXJnaW4gPSBtYXJnaW4oMjAsIDAsIDAsIDApKSwKICAgICAgICAgICAgICAgICAgcGxvdC5jYXB0aW9uID0gZWxlbWVudF90ZXh0KGNvbG91ciA9ICIjQUFBQUFBIikpKSMsCiAgICAgICAgICAgICAgICAgICNwbG90Lm1hcmdpbiA9IG1hcmdpbigzLDE1LDMsMywibW0iKSkpCgojZ2xvYmFsIG9wdGlvbnMgZm9yIHNjaWVudGlmaWMgbnVtYmVycyBhbmQgc2lnbmlmaWNhbnQgZGlnaXRzLiAgICAgICAgICAKb3B0aW9ucyhzY2lwZW4gPSAxMCwKICAgICAgICBkaWdpdHMgPSAxKQpgYGAKCgojIERhdGEgey50YWJzZXR9CgpEYXRhIGNhbWUgZnJvbSBkaXNwYXJhdGUgc291cmNlcy4gVGhlIHRhYnNldCBiZWxvdyBpZGVudGlmaWVzIHdoZXJlIGFuZCBob3cgaXQgd2FzIHdyYW5nbGVkIGluIG9yZGVyIHRvIGJlIGNvbWJpbmVkIGludG8gb25lIFVLIHRhYmxlLgoKIyMgRW5nbGFuZAoKRGF0YSBzb3VyY2VkIGZyb20gW2hlcmVdKGh0dHBzOi8vd3d3Lm9ucy5nb3YudWsvcGVvcGxlcG9wdWxhdGlvbmFuZGNvbW11bml0eS9oZWFsdGhhbmRzb2NpYWxjYXJlL2NhdXNlc29mZGVhdGgvZGF0YXNldHMvZGVhdGhyZWdpc3RyYXRpb25zYW5kb2NjdXJyZW5jZXNieWxvY2FsYXV0aG9yaXR5YW5kaGVhbHRoYm9hcmQpIGFuZCBbaGVyZV0oaHR0cHM6Ly93d3cub25zLmdvdi51ay9wZW9wbGVwb3B1bGF0aW9uYW5kY29tbXVuaXR5L2JpcnRoc2RlYXRoc2FuZG1hcnJpYWdlcy9kZWF0aHMvYWRob2NzLzExODI2Zml2ZXllYXJhdmVyYWdld2Vla2x5ZGVhdGhzYnlsb2NhbGF1dGhvcml0eWFuZHBsYWNlb2ZvY2N1cnJlbmNlZW5nbGFuZGFuZHdhbGVzZGVhdGhzcmVnaXN0ZXJlZDIwMTV0bzIwMTkpIGFuZCBjb2xsYXRlZCBpbnRvIGAuY3N2YCBmaWxlcyBieSBQaWV0cm8gUGF0cmlnbmFuaS4gSSBoYXZlIHNhdmVkIHRoaXMgZmlsZSBpbiB0aGUgYGV4Y2Vzc19tb3J0X2RhdGFgIGZvbGRlciBhdmFpbGFibGUgb24gdGhlIFtwcm9qZWN0IEdpdEh1YiByZXBvc2l0b3J5XShodHRwczovL2dpdGh1Yi5jb20vZGF2aWRoZW4vbHRjX2NvdmlkX3VrKS4KCmBgYHtyfQplbmdsYW5kIDwtIHJlYWRfY3N2KGhlcmUoImV4Y2Vzc19tb3J0X2RhdGEvV2Vla2x5IFN1bW1hcnkgRW5nbGFuZC5jc3YiKSkKCmVuZ2xhbmQgJTw+JSAKICBzbGljZSgtMSkgJT4lIAogIHNlbGVjdChsb2NhdGlvbiwKICAgICAgICAgd2Vla19udW1iZXIgPSBgd2VlayBudW1iZXJgLAogICAgICAgICBhbGwgPSBgYWxsIGRlYXRoc2AsCiAgICAgICAgIG5vbl9jb3ZpZCwgY292aWQsIAogICAgICAgICBhdmVyYWdlID0gYGF2ZXJhZ2UgMjAxNS0yMDE5YCwKICAgICAgICAgZXhjZXNzID0gYGV4Y2VzcyBkZWF0aHNgLCAKICAgICAgICAgY291bnRyeSkgJT4lIAogIG11dGF0ZShsb2NhdGlvbiA9IGZhY3Rvcihsb2NhdGlvbiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgbGV2ZWxzID0gYygiSG9zcGl0YWwiLCAiQ2FyZSBIb21lIiwgIkhvbWUiLCAiT3RoZXIiKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgbGFiZWxzID0gYygiSG9zcGl0YWwiLCAiQ2FyZSBIb21lIiwgIkhvbWUiLCAiT3RoZXIiKSkpICU+JSAKICBtdXRhdGVfYXQoLnZhcnMgPSBjKCJ3ZWVrX251bWJlciIsICJhbGwiLCAiY292aWQiKSwgYXMuaW50ZWdlcikKCm15X2RhdGF0YWJsZShlbmdsYW5kKQpgYGAKCiMjIFNjb3RsYW5kCgpUaGlzIGNvbWVzIGZyb20gdHdvIGZpbGVzIG9uIHRoZSBOYXRpb25hbCBSZWNvcmRzIG9mIFNjb3RsYW5kIChOUlMpIHNpdGUuIE9uZSBoYXMgd2Vla2x5IENPSVZEIGFuZCBhbGwtY2F1c2UgZGVhdGhzLCB0aGUgb3RoZXIgdGhlIHdlZWtseSBudW1iZXJzIChpbmNsdWRpbmcgYXZlcmFnZXMpIGZvciB0aGUgcHJldmlvdXMgNSB5ZWFycy4gVVJMcyBhcmUgc2hvd24gaW4gdGhlIGNvZGUgY2h1bmsuIFRoZSBkYXRhIGlzIGRvd25sb2FkZWQgZGlyZWN0bHkgZXZlcnRpbWUgdGhpcyBjaHVuayBpcyBydW4uCgpgYGB7ciwgd2FybmluZz1GQUxTRSwgbWVzc2FnZT1GQUxTRX0KdGVtcF8xIDwtIHRlbXBmaWxlKCkKdGVtcF8yIDwtIHRlbXBmaWxlKCkKc291cmNlIDwtICJodHRwczovL3d3dy5ucnNjb3RsYW5kLmdvdi51ay9maWxlcy8vc3RhdGlzdGljcy9jb3ZpZDE5L2NvdmlkLWRlYXRocy1kYXRhLXdlZWstMjYuemlwIgoKdGVtcF8xIDwtIGN1cmxfZG93bmxvYWQodXJsID0gc291cmNlLCBkZXN0ZmlsZSA9IHRlbXBfMSwgcXVpZXQgPSBGQUxTRSkKdW56aXAodGVtcF8xLCBleGRpciA9IHRlbXBfMikKCmNoX2RlYXRoX2NvdmlkIDwtIHJlYWRfY3N2KGZpbGUucGF0aCh0ZW1wXzIsImNvdmlkLWRlYXRocy1kYXRhLXdlZWstMjZfVGFibGUgMSAtIENPVklEIGRlYXRocy5jc3YiKSwgc2tpcCA9IDMpCmNoX2RlYXRoX2FsbCA8LSByZWFkX2NzdihmaWxlLnBhdGgodGVtcF8yLCAiY292aWQtZGVhdGhzLWRhdGEtd2Vlay0yNl9UYWJsZSAyIC0gQWxsIGRlYXRocy5jc3YiKSwgc2tpcCA9IDMpCiM1IHllYXIgYXZlcmFnZSBjYW4gYmUgZG93bmxhZGVkIGRpcmVjdGx5IGZyb20gdGhpcyBsaW5rLi4uCmNoX2RlYXRoX2F2ZXJhZ2UgPC0gcmVhZF9jc3YoImh0dHBzOi8vd3d3Lm5yc2NvdGxhbmQuZ292LnVrL2ZpbGVzLy9zdGF0aXN0aWNzL2NvdmlkMTkvd2Vla2x5LWRlYXRocy1ieS1sb2NhdGlvbi0yMDE1LTIwMTkuY3N2Iiwgc2tpcCA9IDIpCgojTm93IHRpZHkgYW5kIGpvaW4gdG9nZXRoZXIKCmxvY19uYW1lcyA8LSBjKCJDYXJlIEhvbWUiLCAiSG9tZSBhbmQgb3RoZXIgbm9uIGluc3RpdHV0aW9uIiwgIkhvc3BpdGFsIiwKICAgICAgICAgICJPdGhlciBpbnN0aXR1dGlvbiIpCgojIENyZWF0ZSBhIGxvb2stdXAgdGFibGUgZm9yIHdlZWsgbnVtYmVycyB0byBkYXRlcwp3ZWVrX2xvb2t1cCA8LSB0aWJibGUoCiAgd2Vla19udW1iZXIgPSAxOjUyLAogIHdlZWtfZGF0ZSA9IHNlcSh5bWQoMjAxOTEyMzApLCB5bWQoMjAyMDEyMjEpLCBieSA9ICIxIHdlZWsiKSkKCgojV3JhbmdsZSBBdmVyYWdlIGRlYXRocwpjaF9kZWF0aF9hdmVyYWdlICU+JSAKICBzbGljZSgyOjYsIDk6MTMsIDE2OjIwLCAyMzoyNykgJT4lIAogIG11dGF0ZShsb2NhdGlvbiA9IHJlcChsb2NfbmFtZXMsIGVhY2ggPSA1LCB0aW1lcyA9IDEpKSAlPiUgCiAgc2VsZWN0KHllYXIgPSBgV2VlayBudW1iZXIyYCwgbG9jYXRpb24sIGV2ZXJ5dGhpbmcoKSwgLWA1M2ApICU+JSAKICBwaXZvdF9sb25nZXIoY29scyA9IGAxYDpgNTJgLCBuYW1lc190byA9ICJ3ZWVrX251bWJlciIsCiAgICAgICAgICAgICAgIHZhbHVlc190byA9ICJuX2RlYXRocyIpICU+JSAKICBncm91cF9ieShsb2NhdGlvbiwgd2Vla19udW1iZXIpICU+JQogIG11dGF0ZShtaW5fZGVhdGhzID0gbWluKG5fZGVhdGhzKSwKICAgICAgICAgbWF4X2RlYXRocyA9IG1heChuX2RlYXRocyksCiAgICAgICAgIG1lYW5fZGVhdGhzID0gbWVhbihuX2RlYXRocykpICU+JSAKICBkaXN0aW5jdChsb2NhdGlvbiwgd2Vla19udW1iZXIsIC5rZWVwX2FsbCA9IFRSVUUpICU+JSAKICBzZWxlY3QoLXllYXIsIC1uX2RlYXRocykgJT4lIAogIHVuZ3JvdXAgJT4lIAogIG11dGF0ZSh3ZWVrX251bWJlciA9IGFzLmludGVnZXIod2Vla19udW1iZXIpKSAtPiBzYwoKI1dyYW5nbGUgYWxsIGRlYXRocwpjaF9kZWF0aF9hbGwgJT4lIAogIHNlbGVjdChsb2NhdGlvbiA9IFgyLCBldmVyeXRoaW5nKCksIC1gV2VlayBiZWdpbm5pbmdgLCAtWDMwOi1YNjUpICU+JSAKICBzbGljZSg4NTo4OCkgJT4lICAKICBtdXRhdGVfYXQodmFycyhgMzAtRGVjLTE5YDpgMjItSnVuLTIwYCksIGFzLm51bWVyaWMpICU+JSAKICBwaXZvdF9sb25nZXIoY29scyA9IGAzMC1EZWMtMTlgOmAyMi1KdW4tMjBgLCBuYW1lc190byA9ICJkYXRlIiwKICAgICAgICAgICAgICAgdmFsdWVzX3RvID0gImRlYXRoc19hbGxfMjAyMCIpICU+JSAKICBtdXRhdGUoZGF0ZSA9IGRteShkYXRlKSwKICAgICAgICAgd2Vla19udW1iZXIgPSByZXAoMToyNiwgZWFjaCA9IDEsIHRpbWVzID0gNCksCiAgICAgICAgIGxvY2F0aW9uID0gcmVwKGxvY19uYW1lcywgZWFjaCA9IDI2LCB0aW1lcyA9IDEpKSAlPiUgCiAgc2VsZWN0KC1kYXRlKSAlPiUgCiAgbGVmdF9qb2luKHNjLCAuKSAtPiBzYwoKCiNXcmFuZ2xlIENvdmlkIGRlYXRocyBhbmQgam9pbiB0b2dldGhlcgpjaF9kZWF0aF9jb3ZpZCAlPiUgCiAgc2VsZWN0KGxvY2F0aW9uID0gWDIsIGV2ZXJ5dGhpbmcoKSwgLWBXZWVrIGJlZ2lubmluZ2AsCiAgICAgICAgIC1gWWVhciB0byBEYXRlYDotWDQ0KSAlPiUgCiAgc2xpY2UoODM6ODYpICU+JSAgCiAgcGl2b3RfbG9uZ2VyKGNvbHMgPSBgMzAtRGVjLTE5YDpgMjItSnVuLTIwYCwgbmFtZXNfdG8gPSAiZGF0ZSIsCiAgICAgICAgICAgICAgIHZhbHVlc190byA9ICJkZWF0aHNfY292aWRfMjAyMCIpICU+JSAKICBtdXRhdGUoZGF0ZSA9IGRteShkYXRlKSwKICAgICAgICAgd2Vla19udW1iZXIgPSByZXAoMToyNiwgZWFjaCA9IDEsIHRpbWVzID0gNCksCiAgICAgICAgIGxvY2F0aW9uID0gcmVwKGxvY19uYW1lcywgZWFjaCA9IDI2LCB0aW1lcyA9IDEpKSAlPiUgCiAgc2VsZWN0KC1kYXRlKSAlPiUgCiAgbGVmdF9qb2luKHNjLCAuKSAlPiUgCiAgbXV0YXRlKGRlYXRoc19ub25Db3ZpZF8yMDIwID0gZGVhdGhzX2FsbF8yMDIwIC0gZGVhdGhzX2NvdmlkXzIwMjAsCiAgICAgICAgIGxvY2F0aW9uID0gZmFjdG9yKGxvY2F0aW9uLAogICAgICAgICAgICAgICAgICAgICAgICAgICBsZXZlbHMgPSBjKCJIb3NwaXRhbCIsICJDYXJlIEhvbWUiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiSG9tZSBhbmQgb3RoZXIgbm9uIGluc3RpdHV0aW9uIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIk90aGVyIGluc3RpdHV0aW9uIiksCiAgICAgICAgICAgICAgICAgICAgICAgICAgIGxhYmVscyA9IGMoIkhvc3BpdGFsIiwgIkNhcmUgSG9tZSIsICJIb21lIiwgIk90aGVyIikpKSAlPiUgCiAgbGVmdF9qb2luKC4sIHdlZWtfbG9va3VwKSAlPiUgCiAgZmlsdGVyKHdlZWtfbnVtYmVyID49MTEgJiB3ZWVrX251bWJlciA8PSAyNikgJT4lIAogIHNlbGVjdCgtbWluX2RlYXRocywgLW1heF9kZWF0aHMsIC1YMjksIC13ZWVrX2RhdGUpICU+JSAKICByZW5hbWUoYWxsID0gZGVhdGhzX2FsbF8yMDIwLAogICAgICAgICBjb3ZpZCA9IGRlYXRoc19jb3ZpZF8yMDIwLAogICAgICAgICBub25fY292aWQgPSBkZWF0aHNfbm9uQ292aWRfMjAyMCwKICAgICAgICAgYXZlcmFnZSA9IG1lYW5fZGVhdGhzKSAlPiUgCiAgbXV0YXRlKGV4Y2VzcyA9IGFsbCAtIGF2ZXJhZ2UsCiAgICAgICAgIGNvdW50cnkgPSAiU2NvdGxhbmQiKSAtPiBzYwoKc2MgJT4lIAogIHJvdW5kX2RmKC4pICU+JSAKICBteV9kYXRhdGFibGUoLikKYGBgCgojIyBXYWxlcwoKU2FtZSBzb3VyY2UgYXMgRW5nbGFuZCBkYXRhLiBBbHNvIHdyYW5nbGVkIGludG8gYSBgLmNzdmAgYnkgUGlldHJvLgoKYGBge3J9CndhbGVzIDwtIHJlYWRfY3N2KGhlcmUoImV4Y2Vzc19tb3J0X2RhdGEvV2Vla2x5IFN1bW1hcnkgV2FsZXMuY3N2IikpCgp3YWxlcyAlPD4lIAogIHNsaWNlKC0xKSAlPiUgCiAgc2VsZWN0KGxvY2F0aW9uLAogICAgICAgICB3ZWVrX251bWJlciA9IGB3ZWVrIG51bWJlcmAsCiAgICAgICAgIGFsbCA9IGBhbGwgZGVhdGhzYCwKICAgICAgICAgbm9uX2NvdmlkLCBjb3ZpZCwgCiAgICAgICAgIGF2ZXJhZ2UgPSBgYXZlcmFnZSAyMDE1LTIwMTlgLAogICAgICAgICBleGNlc3MgPSBgZXhjZXNzIGRlYXRoc2AsIAogICAgICAgICBjb3VudHJ5KSAlPiUgCiAgbXV0YXRlKGxvY2F0aW9uID0gZmFjdG9yKGxvY2F0aW9uLAogICAgICAgICAgICAgICAgICAgICAgICAgICBsZXZlbHMgPSBjKCJIb3NwaXRhbCIsICJDYXJlIEhvbWUiLCAiSG9tZSIsICJPdGhlciIpLAogICAgICAgICAgICAgICAgICAgICAgICAgICBsYWJlbHMgPSBjKCJIb3NwaXRhbCIsICJDYXJlIEhvbWUiLCAiSG9tZSIsICJPdGhlciIpKSkgJT4lIAogIG11dGF0ZV9hdCgudmFycyA9IGMoIndlZWtfbnVtYmVyIiwgImFsbCIsICJjb3ZpZCIpLCBhcy5pbnRlZ2VyKQoKbXlfZGF0YXRhYmxlKHdhbGVzKQpgYGAKCiMjIE5vcnRoZXJuIElyZWxhbmQKCk11bHRpc2hlZXQgRXhjZWwgZmlsZSB2aWEgU2lvYmjDoW4gTXVycGh5IGFzIHJlcXVlc3RlZCBhbmQgcHJvdmlkZWQgZGlyZWN0IGZyb20gdGhlIE5vcnRoZXJuIElyZWxhbmQgU3RhdGlzdGljcyBhbmQgUmVzZWFyY2ggQWdlbmN5IChOSVNSQSkgd2hvIGFyZSBrZWVuIHRvIGhpZ2hsaWdodCB0aGVzZSBmaWd1cmVzIGFyZSBwcm92aXNpb25hbC4gQWxzbyBuZWVkIHRvIHBvaW50IG91dCBoZXJlIHRoZSBmaWd1cmVzIHdlIGdvdCBmcm9tIE5JU1JBIGRvbid0IGJyZWFrIGRvd24gYnkgQ09WSUQvbm9uLUNPVklEIGRlYXRocy4gTmVlZHMgc29tZSB3cmFuZ2xpbmcuLi4uCgpgYGB7cn0KI1N0YXJ0IHdpdGggaG9zcGl0YWwgZGVhdGhzIG9uIHNoZWV0IDMKbmlfaG9zcCA8LSByZWFkX3hsc3goaGVyZSgiZXhjZXNzX21vcnRfZGF0YS9OSSByZXN1bHRzX3JldmlzZWQueGxzeCIpLCBzaGVldCA9IDMsIAogICAgICAgICAgICAgICAgICAgIHJhbmdlID0gIkEyOkkxOCIpICU+JSAKICBtdXRhdGUobG9jYXRpb24gPSAiSG9zcGl0YWwiKSAlPiUgCiAgc2VsZWN0KGxvY2F0aW9uLAogICAgICAgICB3ZWVrX251bWJlciA9IGAuLi4xYCwKICAgICAgICAgYWxsID0gYDIwMjBgLAogICAgICAgICBhdmVyYWdlID0gQXZlcmFnZSwKICAgICAgICAgZXhjZXNzKQogCiNOb3cgaW5nZXN0IGNhcmUgaG9tZSBkYXRhIC0gc2hlZXQgMgpuaV9jaCA8LSByZWFkX3hsc3goaGVyZSgiZXhjZXNzX21vcnRfZGF0YS9OSSByZXN1bHRzX3JldmlzZWQueGxzeCIpLCBzaGVldCA9IDIsCiAgICAgICAgICAgICAgICAgICByYW5nZSA9ICJBMjpJMTgiKSAlPiUgCiAgbXV0YXRlKGxvY2F0aW9uID0gIkNhcmUgSG9tZSIpICU+JSAKICBzZWxlY3QobG9jYXRpb24sIAogICAgICAgICB3ZWVrX251bWJlciA9IGAuLi4xYCwKICAgICAgICAgYWxsID0gYDIwMjBgLAogICAgICAgICBhdmVyYWdlID0gQXZlcmFnZSwKICAgICAgICAgZXhjZXNzKQoKI0hvbWUgZGVhdGhzIC0gc2hlZXQgNApuaV9ob21lIDwtIHJlYWRfeGxzeChoZXJlKCJleGNlc3NfbW9ydF9kYXRhL05JIHJlc3VsdHNfcmV2aXNlZC54bHN4IiksIHNoZWV0ID0gNCwKICAgICAgICAgICAgICAgICAgICAgcmFuZ2UgPSAiQTI6STE4IikgJT4lIAogIG11dGF0ZShsb2NhdGlvbiA9ICJIb21lIikgJT4lIAogIHNlbGVjdChsb2NhdGlvbiwKICAgICAgICAgd2Vla19udW1iZXIgPSBgLi4uMWAsCiAgICAgICAgIGFsbCA9IGAyMDIwYCwKICAgICAgICAgYXZlcmFnZSA9IEF2ZXJhZ2UsCiAgICAgICAgIGV4Y2VzcykKCiNBbmQgb3RoZXIgcGxhY2Ugb2YgZGVhdGggLSBzaGVldCA1Cm5pX290aGVyIDwtICByZWFkX3hsc3goaGVyZSgiZXhjZXNzX21vcnRfZGF0YS9OSSByZXN1bHRzX3JldmlzZWQueGxzeCIpLCBzaGVldCA9IDUsCiAgICAgICAgICAgICAgICAgICAgIHJhbmdlID0gIkEyOkkxOCIpICU+JSAKICBtdXRhdGUobG9jYXRpb24gPSAiT3RoZXIiKSAlPiUgCiAgc2VsZWN0KGxvY2F0aW9uLAogICAgICAgICB3ZWVrX251bWJlciA9IGAuLi4xYCwKICAgICAgICAgYWxsID0gYDIwMjBgLAogICAgICAgICBhdmVyYWdlID0gQXZlcmFnZSwKICAgICAgICAgZXhjZXNzKQoKI0pvaW4gdGhlc2Ugb2JqZWN0cyB0b2dldGhlcgpuaSA8LSAKICBiaW5kX3Jvd3MobmlfaG9zcCwgbmlfY2gsIG5pX2hvbWUsIG5pX290aGVyKSAlPiUgCiAgbXV0YXRlKGNvdW50cnkgPSAiTm9ydGhlcm4gSXJlbGFuZCIpICU+JSAKICBzZXBhcmF0ZSh3ZWVrX251bWJlciwgYygiZHJvcCIsICJ3ZWVrX251bWJlciIpLCBzZXAgPSAiICIpICU+JSAKICBtdXRhdGUod2Vla19udW1iZXIgPSBhcy5pbnRlZ2VyKHdlZWtfbnVtYmVyKSkgJT4lIAogICAgc2VsZWN0KC1kcm9wKQoKCm15X2RhdGF0YWJsZShuaSkKYGBgCgoKIyMgQ29tYmluZWQKCldpdGggZWFjaCBuYXRpb25zIGRhdGEgbm93IHdyYW5nbGVkIGludG8gdGhlIHNhbWUgZm9ybWF0IHdlIGNhbiBqb2luIHRoZW0gYWxsIHRvZ2V0aGVyIGludG8gb25lIG9iamVjdCAtIGB1a2AuCgpgYGB7cn0KdWsgPC0gYmluZF9yb3dzKGVuZ2xhbmQsIHNjLCB3YWxlcywgbmkpCgp1ayAlPiUKICBtdXRhdGUoY291bnRyeSA9IGZhY3Rvcihjb3VudHJ5LCAKICAgICAgICAgICAgICAgICAgICAgICAgICBsZXZlbHMgPSBjKCJFbmdsYW5kIiwgIlNjb3RsYW5kIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiV2FsZXMiLCAiTm9ydGhlcm4gSXJlbGFuZCIpKSkgJT4lIAogIHNlbGVjdChjb3VudHJ5LCBldmVyeXRoaW5nKCkpIC0+IHVrCm15X2RhdGF0YWJsZSh1aykKYGBgCgojIFdlZWtseSBQLXNjb3JlIGJ5IE5hdGlvbiB7LnRhYnNldH0KCk5vIHdlIGhhdmUgYWxsIHRoZSBpbmZvcm1hdGlvbiBjb21iaW5lZCBpbiB0aGUgYHVrYCBvYmplY3Qgd2UgY2FuIHN0YXJ0IHBsb3R0aW5nLiBGaXJzdGx5IHRoZSB3ZWVrbHkgZXhjZXNzIGJ5IG5hdGlvbiBmb3IgRmlndXJlIDUuCgojIyBQbG90CgpgYGB7cn0KZmlnXzUgPC0gCiAgdWsgJT4lIAogIGdyb3VwX2J5KGNvdW50cnksIHdlZWtfbnVtYmVyKSAlPiUgIAogIHN1bW1hcmlzZShhbGwgPSBzdW0oYWxsKSwKICAgICAgICAgICAgYXZlcmFnZSA9IHN1bShhdmVyYWdlKSwgCiAgICAgICAgICAgIGV4Y2VzcyA9IGFsbCAtIGF2ZXJhZ2UpICU+JSAKICBtdXRhdGUocGN0X2NoYW5nZSA9IChleGNlc3MgLyBhdmVyYWdlICogMTAwKSkgJT4lIAogIGdncGxvdChhZXMod2Vla19udW1iZXIsIHBjdF9jaGFuZ2UsIGNvbG91ciA9IGNvdW50cnkpKSArCiAgZ2VvbV9wb2ludChzaXplID0gMS41KSArCiAgZ2VvbV9saW5lKHNpemUgPSAxLjUpICsKICBzY2FsZV9jb2xvdXJfd3NqKGd1aWRlID0gZ3VpZGVfbGVnZW5kKGtleXdpZHRoID0gMikpICsKICBzY2FsZV95X2NvbnRpbnVvdXMobGltaXRzID0gYygtMTUsIDEyMCksCiAgICAgICAgICAgICAgICAgICAgIGJyZWFrcyA9IHNjYWxlczo6cHJldHR5X2JyZWFrcyhuID0gNiksCiAgICAgICAgICAgICAgICAgICAgIGxhYmVscyA9IHNjYWxlczo6cGVyY2VudF9mb3JtYXQoc2NhbGUgPSAxKSkgKwogIHNjYWxlX3hfY29udGludW91cyhicmVha3MgPSBzY2FsZXM6OnByZXR0eV9icmVha3MobiA9IDEyKSkgKwogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJ0b3AiKSArCiAgbGFicyh0aXRsZSA9ICJXZWVla2x5IGV4Y2VzcyBtb3J0YWxpdHkgaW4gdGhlIFVLLiIsCiAgICAgICBzdWJ0aXRsZSA9ICJXZWVrcyAxMS0yNiAyMDIwIiwKICAgICAgIHggPSAiV2VlayBudW1iZXIiLAogICAgICAgeSA9ICIlIGNoYW5nZSBmcm9tIDUteXIgYXZlcmFnZSIsCiAgICAgICBjb2xvdXIgPSAiIiwKICAgICAgIGNhcHRpb24gPSAiU291cmNlOiBPTlMsIE5SUyAmIE5JU1JBXG5GaWd1cmVzIGFyZSBwcm92aXNpb25hbFxuQ29kZTpodHRwczovL2dpdGh1Yi5jb20vZGF2aWRoZW4vbHRjX2NvdmlkX3VrIikgCgpmaWdfNQpgYGAKCmBgYHtyLCBldmFsPUZBTFNFLCBlY2hvPUZBTFNFfQpnZ3NhdmUoaGVyZSgicGxvdHMvZmlnXzUucG5nIiksIGZpZ181LCB3aWR0aCA9IDEyLCBoZWlnaHQgPSA5LCBkcGkgPSAzMDApCmBgYAoKIyMgVGFibGUKCmBgYHtyfQp1ayAlPiUgCiAgZ3JvdXBfYnkoY291bnRyeSwgd2Vla19udW1iZXIpICU+JSAgCiAgc3VtbWFyaXNlKGFsbCA9IHN1bShhbGwpLAogICAgICAgICAgICBhdmVyYWdlID0gc3VtKGF2ZXJhZ2UpLCAKICAgICAgICAgICAgZXhjZXNzID0gYWxsIC0gYXZlcmFnZSkgJT4lIAogIG11dGF0ZShwY3RfY2hhbmdlID0gKGV4Y2VzcyAvIGF2ZXJhZ2UgKiAxMDApKSAlPiUgCiAgcm91bmRfZGYoLikgJT4lIAogIG15X2RhdGF0YWJsZSguKQpgYGAKCgoKIyBQIFNjb3JlIEJyZWFrZG93biBwbG90CgpGaWd1cmUgNiBpcyBhIGNvbWJpbmF0aW9uIG9mIDMgcGxvdHMuIEZpcnN0IHdlIHNob3cgdGhlIGluZGl2aWR1YWwgcGxvdHMgYW5kIHVuZGVybHlpbmcgdGFibGVzCgojIyBPdmVyYWxsIHsudGFic2V0fQoKU3VtbWFyaXNpbmcgdGhlIGV4Y2VzcyBhY3Jvc3MgYWxsIHdlZWtzIDExLTI2IGJ5IG5hdGlvbgoKIyMjIFBsb3QKCmBgYHtyfQp1ayAlPiUgCiAgZ3JvdXBfYnkoY291bnRyeSkgJT4lIAogIHN1bW1hcmlzZShhbGwgPSBzdW0oYWxsKSwgCiAgICAgICAgICAgIGF2ZXJhZ2UgPSBzdW0oYXZlcmFnZSksCiAgICAgICAgICAgIGV4Y2VzcyA9IGFsbCAtIGF2ZXJhZ2UsCiAgICAgICAgICAgIHBjdF9jaGFuZ2UgPSBleGNlc3MgLyBhdmVyYWdlICogMTAwKSAlPiUgCiAgZ2dwbG90KGFlcyhjb3VudHJ5LCBwY3RfY2hhbmdlLCBmaWxsID0gY291bnRyeSkpICsKICBnZW9tX2NvbCgpICsKICBzY2FsZV9maWxsX3dzaigpICsKICBzY2FsZV95X2NvbnRpbnVvdXMobGltaXRzID0gYygwLDQwKSwKICAgICAgICAgICAgICAgICAgICAgbGFiZWxzID0gc2NhbGVzOjpwZXJjZW50X2Zvcm1hdChzY2FsZSA9IDEpKSArCiAgI3NjYWxlX3hfZGlzY3JldGUocG9zaXRpb24gPSAidG9wIikgKwogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIiwKICAgICAgICBheGlzLnRpdGxlLnkgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE2KSkgKwogIGxhYnModGl0bGUgPSAiT3ZlcmFsbCIsCiAgICAgICB4ID0gIiIsCiAgICAgICB5ID0gIiUgZGlmZmVyZW5jZSBmcm9tIDUgeWVhciBhdmVyYWdlIiwKICAgICAgIGNhcHRpb24gPSAiIikgLT4gdWtfZXhjZXNzCnVrX2V4Y2VzcwpgYGAKCiMjIyBUYWJsZQoKYGBge3J9CnVrICU+JSAKICBncm91cF9ieShjb3VudHJ5KSAlPiUgIAogIHN1bW1hcmlzZShhbGwgPSBzdW0oYWxsKSwKICAgICAgICAgICAgYXZlcmFnZSA9IHN1bShhdmVyYWdlKSwgCiAgICAgICAgICAgIGV4Y2VzcyA9IGFsbCAtIGF2ZXJhZ2UpICU+JSAKICBtdXRhdGUocGN0X2NoYW5nZSA9IChleGNlc3MgLyBhdmVyYWdlICogMTAwKSkgJT4lIAogIHJvdW5kX2RmKC4pICU+JSAKICBteV9kYXRhdGFibGUoLikKYGBgCgojIyBieSBMb2NhdGlvbiBvbmx5IHsudGFic2V0fQoKQWdhaW4gYSBzdW1tYXJ5IGFjcm9zcyBhbGwgd2Vla3MgMTEtMjYgYnV0IHNwbGl0IGJ5IGxvY2F0aW9uIG9mIGRlYXRoLgoKIyMjIFBsb3QKCgpgYGB7ciwgZmlnLndpZHRoPTEyLCBmaWcuaGVpZ2h0PTZ9CmZpZ19leGNlc3NfdWtfMiA8LQogIHVrICU+JSAKICBncm91cF9ieShjb3VudHJ5LCBsb2NhdGlvbikgJT4lIAogIHN1bW1hcmlzZShhbGwgPSBzdW0oYWxsKSwgCiAgICAgICAgICAgIGF2ZXJhZ2UgPSBzdW0oYXZlcmFnZSksCiAgICAgICAgICAgIGV4Y2VzcyA9IGFsbCAtIGF2ZXJhZ2UsCiAgICAgICAgICAgIHBjdF9jaGFuZ2UgPSBleGNlc3MgLyBhdmVyYWdlICogMTAwKSAlPiUgCiAgZ2dwbG90KGFlcyhjb3VudHJ5LCBwY3RfY2hhbmdlLCBmaWxsID0gY291bnRyeSkpICsKICBnZW9tX2NvbCgpICsKICBmYWNldF9ncmlkKH5sb2NhdGlvbiwgc3dpdGNoID0gIngiKSArCiAgc2NhbGVfZmlsbF93c2ooKSArCiAgc2NhbGVfeV9jb250aW51b3VzKGxpbWl0cyA9IGMoLTIwLDgwKSwKICAgICAgICAgICAgICAgICAgICAgbGFiZWxzID0gc2NhbGVzOjpwZXJjZW50X2Zvcm1hdChzY2FsZSA9IDEpLAogICAgICAgICAgICAgICAgICAgICBicmVha3MgPSBzY2FsZXM6OnByZXR0eV9icmVha3MoKSkgKwogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJ0b3AiLAogICAgICAgIGF4aXMudGV4dC54ID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgIHN0cmlwLnBsYWNlbWVudCA9ICJvdXRzaWRlIiwKICAgICAgICBheGlzLnRpdGxlLnkgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE2KSkgKwogIGxhYnModGl0bGUgPSAiYnkgTG9jYXRpb24iLAogICAgICAgeCA9ICIiLAogICAgICAgeSA9ICIlIGRpZmZlcmVuY2UgZnJvbSA1IHllYXIgYXZlcmFnZSIsCiAgICAgICBmaWxsID0gIiIpCmZpZ19leGNlc3NfdWtfMgpgYGAKCiMjIyBUYWJsZQoKYGBge3J9CnVrICU+JSAKICBncm91cF9ieShjb3VudHJ5LCBsb2NhdGlvbikgJT4lICAKICBzdW1tYXJpc2UoYWxsID0gc3VtKGFsbCksCiAgICAgICAgICAgIGNvdmlkID0gc3VtKGNvdmlkKSwKICAgICAgICAgICAgbm9uX2NvdmlkID0gc3VtKG5vbl9jb3ZpZCksCiAgICAgICAgICAgIGF2ZXJhZ2UgPSBzdW0oYXZlcmFnZSksIAogICAgICAgICAgICBleGNlc3MgPSBhbGwgLSBhdmVyYWdlKSAlPiUgCiAgbXV0YXRlKHBjdF9jaGFuZ2UgPSAoZXhjZXNzIC8gYXZlcmFnZSAqIDEwMCkpICU+JSAKICBhcnJhbmdlKGxvY2F0aW9uKSAlPiUgCiAgcm91bmRfZGYoLikgJT4lIAogIG15X2RhdGF0YWJsZSguKQpgYGAKCgoKIyMgQnkgbG9jYXRpb24gYW5kIHdlZWsgey50YWJzZXR9CgpGaW5hbGx5LCB3ZWVrbHkgY2hhbmdlIGJ5IGxvY2F0aW9uIGFuZCBjb3VudHJ5LgoKIyMjIFBsb3QKCmBgYHtyfQpmaWdfdWtfZXhjZXNzXzEgPC0gCiAgdWsgJT4lIAogIG11dGF0ZShwY3RfY2hhbmdlID0gKGV4Y2VzcyAvIGF2ZXJhZ2UgKiAxMDApKSAlPiUgCiAgZ2dwbG90KGFlcyh3ZWVrX251bWJlciwgcGN0X2NoYW5nZSwgZmlsbCA9IGNvdW50cnkpKSArCiAgZ2VvbV9jb2woKSArCiAgZmFjZXRfZ3JpZChsb2NhdGlvbn5jb3VudHJ5KSArCiAgc2NhbGVfZmlsbF93c2ooKSArCiAgc2NhbGVfeV9jb250aW51b3VzKGxpbWl0cyA9IGMoLTEwMCwgMzAwKSwKICAgICAgICAgICAgICAgICAgICAgbGFiZWxzID0gc2NhbGVzOjpwZXJjZW50X2Zvcm1hdChzY2FsZSA9IDEpKSArCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiLAogICAgICAgIGF4aXMudGl0bGUueSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTYpLAogICAgICAgIHBhbmVsLnNwYWNpbmcueSA9IHVuaXQoMiwgImxpbmVzIikpICsKICBsYWJzKHRpdGxlID0gImJ5IExvY2F0aW9uIGFuZCBXZWVrIiwKICAgICAgIHggPSAiV2VlayBOdW1iZXIiLAogICAgICAgeSA9ICIlIGRpZmZlcmVuY2UgZnJvbSA1IHllYXIgYXZlcmFnZSIpIywKICAgICAgICNjYXB0aW9uID0gIlNvdXJjZTogT05TICYgTlJTXG5Db2RlOmh0dHBzOi8vZ2l0aHViLmNvbS9kYXZpZGhlbi9sdGNfY292aWRfdWsvYmxvYi9tYXN0ZXIvZXhjZXNzX21vcnRfcGxvdC5SbWQiKQpmaWdfdWtfZXhjZXNzXzEKYGBgCgoKCiMjIyBUYWJsZQoKCmBgYHtyfQp1ayAlPiUgCiAgbXV0YXRlKHBjdF9jaGFuZ2UgPSAoZXhjZXNzIC8gYXZlcmFnZSAqIDEwMCkpICU+JSAKICBhcnJhbmdlKGNvdW50cnksIGxvY2F0aW9uLCB3ZWVrX251bWJlcikgJT4lIAogIHJvdW5kX2RmKC4pICU+JSAKICBteV9kYXRhdGFibGUoLikKYGBgCgoKIyBDb21iaW5hdGlvbiBwbG90IEZpZ3VyZSA2CgpVc2luZyB0aGUgYHBhdGNod29ya2AgcGFja2FnZSB0byBjb21iaW5lIHRvZ2V0aGVyLgoKYGBge3IsIGZpZy53aWR0aD0xOCwgZmlnLmhlaWdodD0xOH0KKHVrX2V4Y2VzcyArIGZpZ19leGNlc3NfdWtfMikgLyBmaWdfdWtfZXhjZXNzXzEgKwogIHBsb3RfYW5ub3RhdGlvbih0aXRsZSA9ICJFeGNlc3MgbW9ydGFsaXR5IGluIHRoZSBVSy4gV2Vla3MgMTEtMjYgMjAyMCIsCiAgICAgICAgICAgICAgICAgIHN1YnRpdGxlID0gIkJyZWFrZG93biIsCiAgICAgICAgICAgICAgICAgIGNhcHRpb24gPSAiU291cmNlOiBPTlMsIE5SUyAmIE5JU1JBXG5GaWd1cmVzIGFyZSBwcm92aXNpb25hbFxuQ29kZTpodHRwczovL2dpdGh1Yi5jb20vZGF2aWRoZW4vbHRjX2NvdmlkX3VrIikgKwogIHBsb3RfbGF5b3V0KGhlaWdodHMgPSBjKDEsIDEuMikpICAtPiBmaWdfNgpmaWdfNgpgYGAKCmBgYHtyLCBlY2hvPUZBTFNFLCBldmFsPUZBTFNFfQpnZ3NhdmUoaGVyZSgicGxvdHMvZmlnXzYucG5nIiksIGZpZ182LCB3aWR0aCA9IDE4LCBoZWlnaHQgPSAxOCwgZHBpID0gMzAwKQpgYGAKCgoKIyBbSE9NRSBQQUdFXShodHRwczovL2RhdmlkaGVuLmdpdGh1Yi5pby9sdGNfY292aWRfdWsvaW5kZXguaHRtbCkKCmBgYHtyfQpkZXZ0b29sczo6c2Vzc2lvbl9pbmZvKCkKYGBgCgoKCgoKCgo=