Pacotes

# Carregar pacotes-base do projeto
# Manipulação e datas
library(tidyverse);library(data.table);library(lubridate);library(patchwork);library(Hmisc)
Aviso: pacote ‘ggplot2’ foi compilado no R versão 4.4.3
Aviso: pacote ‘purrr’ foi compilado no R versão 4.4.3
── Attaching core tidyverse packages ──────────────────────────────────────────────────────────── tidyverse 2.0.0 ──
✔ dplyr     1.1.4     ✔ readr     2.1.5
✔ forcats   1.0.0     ✔ stringr   1.5.1
✔ ggplot2   3.5.2     ✔ tibble    3.2.1
✔ lubridate 1.9.3     ✔ tidyr     1.3.1
✔ purrr     1.1.0     
── Conflicts ────────────────────────────────────────────────────────────────────────────── tidyverse_conflicts() ──
✖ dplyr::filter() masks stats::filter()
✖ dplyr::lag()    masks stats::lag()
ℹ Use the ]8;;http://conflicted.r-lib.org/conflicted package]8;; to force all conflicts to become errors
Aviso: pacote ‘data.table’ foi compilado no R versão 4.4.3
data.table 1.17.8 usando 12 threads (veja ?getDTthreads).  Últimas notícias: r-datatable.com
**********
Executando data.table em português; o suporte ao pacote está disponível apenas em inglês. Ao procurar ajuda online, certifique-se de verificar também a mensagem de erro em inglês. Isso pode ser obtido examinando os arquivos po/R-pt_BR.po e po/pt_BR.po no código-fonte do pacote, onde as mensagens de erro no idioma nativo e em inglês podem ser encontradas lado a lado. You can also try calling Sys.setLanguage('en') prior to reproducing the error message.
**********

Anexando pacote: ‘data.table’

Os seguintes objetos são mascarados por ‘package:lubridate’:

    hour, isoweek, mday, minute, month, quarter, second, wday, week, yday, year

Os seguintes objetos são mascarados por ‘package:dplyr’:

    between, first, last

O seguinte objeto é mascarado por ‘package:purrr’:

    transpose

Registered S3 method overwritten by 'htmlwidgets':
  method           from         
  print.htmlwidget tools:rstudio

Anexando pacote: ‘Hmisc’

Os seguintes objetos são mascarados por ‘package:dplyr’:

    src, summarize

Os seguintes objetos são mascarados por ‘package:base’:

    format.pval, units
# Modelagem
library(mgcv);library(gratia);library(lubridate);library(modelsummary);library(gt);library(glue);library(scales);library(broom);library(broom.helpers);library(geobr)
Carregando pacotes exigidos: nlme

Anexando pacote: ‘nlme’

O seguinte objeto é mascarado por ‘package:dplyr’:

    collapse

This is mgcv 1.9-1. For overview type 'help("mgcv-package")'.
Aviso: pacote ‘gratia’ foi compilado no R versão 4.4.3

Anexando pacote: ‘gratia’

O seguinte objeto é mascarado por ‘package:stringr’:

    boundary

Aviso: pacote ‘modelsummary’ foi compilado no R versão 4.4.3

Anexando pacote: ‘modelsummary’

O seguinte objeto é mascarado por ‘package:Hmisc’:

    Mean


Anexando pacote: ‘gt’

O seguinte objeto é mascarado por ‘package:Hmisc’:

    html


Anexando pacote: ‘scales’

O seguinte objeto é mascarado por ‘package:purrr’:

    discard

O seguinte objeto é mascarado por ‘package:readr’:

    col_factor

Aviso: pacote ‘broom.helpers’ foi compilado no R versão 4.4.3
Aviso: pacote ‘geobr’ foi compilado no R versão 4.4.3
# Utilidades
library(scales);library(patchwork);library(knitr);library(kableExtra)

Anexando pacote: ‘kableExtra’

O seguinte objeto é mascarado por ‘package:dplyr’:

    group_rows
# Definir opções globais de knitr
knitr::opts_chunk$set(
  echo       = TRUE,
  message    = TRUE,
  warning    = TRUE,
  dpi        = 120,
  fig.align  = "center",
  fig.width  = 12,
  fig.height = 8
)

# Tema visual padrão 
theme_article <- function(){
  theme_minimal(base_size = 11) +
    theme(
      plot.title = element_text(face="bold"),
      plot.subtitle = element_text(margin=margin(b=6)),
      plot.caption  = element_text(size=9, color="grey30"),
      axis.title = element_text(),
      panel.grid.minor = element_blank(),
      legend.position = "top"
    )
}
theme_set(theme_article())
set.seed(1234)
predict_gam_ci <- function(model, newdata, type = "link", level = 0.95){
  stopifnot(inherits(model, "gam"))
  pr <- predict(model, newdata = newdata, type = type, se.fit = TRUE)
  alpha <- 1 - level
  crit  <- qnorm(1 - alpha/2)
  tibble(
    .fitted = as.numeric(pr$fit),
    .se     = as.numeric(pr$se.fit),
    .lower  = .fitted - crit*.se,
    .upper  = .fitted + crit*.se
  )
}
export_figure <- function(p, filename, width = 7, height = 4.2){
  ggsave(glue("figures/{filename}.pdf"), plot = p, width = width, height = height, dpi = 300, device = cairo_pdf)
  ggsave(glue("figures/{filename}.eps"), plot = p, width = width, height = height, dpi = 300, device = "eps")
  ggsave(glue("figures/{filename}.tiff"),plot = p, width = width, height = height, dpi = 600, compression = "lzw")
  invisible(NULL)
}
export_table <- function(gt_obj, filename){
  gtsave(gt_obj, filename = glue("tables/{filename}.html"))
  # PNG (precisa webshot2 instalado/configurado)
  try(gtsave(gt_obj, filename = glue("tables/{filename}.png")))
  # LaTeX
  try(gtsave(gt_obj, filename = glue("tables/{filename}.tex")))
  invisible(NULL)
}

# Estilo padrão de tabela
gt_article <- function(dat, title = NULL, subtitle = NULL, note = NULL){
  dat %>%
    gt() %>%
    tab_header(title = md(title %||% ""), subtitle = md(subtitle %||% "")) %>%
    fmt_number(where(is.numeric), decimals = 2) %>%
    tab_options(table.font.size = px(12)) %>%
    opt_horizontal_padding(scale = 1.1) %>%
    opt_vertical_padding(scale = 1.1) %>%
    tab_source_note(md(note %||% "Notes: Author’s calculations."))
}

1. Introduction

This report documents the analytical pipeline developed to estimate the climatic penalty (penalidade climática) on Brazil’s electricity sector and to translate these effects into measurable economic costs. The analysis was conducted using monthly data from 2001 to 2019, covering all four subsystems of the National Interconnected System (SIN).

The study proceeds through the following steps:

  1. Hydrological modelling — We estimated the relationship between climatic variables (precipitation, temperature, humidity, wind) and stored energy (EAR) and hydroelectric generation using Generalized Additive Models (GAMs). These models capture non-linear climate–hydrology interactions and seasonal effects at the subsystem level.

  2. Climatic counterfactuals — Using the fitted GAMs, we simulated counterfactual trajectories fixing the climatic covariates at their historical mean levels (baseline 2001–2005). The deviation between observed and counterfactual values isolates the share of variation attributable exclusively to climate variability.

  3. Climate penalty (ΔE) — The climate penalty was defined as \(ΔE=E_{predicted}−E_{cf}\) representing the loss (or gain) of hydro generation due solely to climatic fluctuations.

  4. Elasticities — We derived elasticities linking generation to hydrological and climatic conditions, and demand to price and income, to assess sensitivity and potential transmission channels of climatic shocks.

  5. Cost translation — The estimated penalties were converted into monetary terms along three cost dimensions:

  6. Consumers: additional expenditure due to replacement of cheaper hydro generation by more expensive sources;

  7. Electricity sector: higher spot market prices (PLD) and operational costs;

This empirical pipeline links climate variability, hydrological performance, and economic outcomes through a unified statistical framework, enabling a multidimensional valuation of climate-related risks in a hydro-dependent power system.

2. Data Preparation

This section describes the construction of the analytical dataset used to estimate the climatic penalty.
All variables were harmonized at the subsystem–day level between 2001 and 2019, integrating hydrological, climatic, and market information.

2.1 Data Sources

  • Hydropower generation (plant-day): daily generation data compiled from ONS records, aggregated by subsystem.

  • Reservoir levels and natural inflows (EAR and ENA): subsystem-level daily data from ONS.

  • Climatic variables: precipitation and temperature obtained from the ECMWF/CAMS reanalysis dataset, interpolated to match subsystem centroids.

  • Spot price (PLD): weekly subsystem data from CCEE.

  • Demand and generation dispatch by source: monthly or weekly data from ONS and EPE.

All datasets were pre-processed to align date formats, harmonize variable names, and remove inconsistent or missing identifiers.

2.2 Data Loading and Cleaning

# Load core datasets
ger     <- read.csv("base_gera_tratada_set.csv")     # plant-day generation
pld     <- read.csv("preco_semanal.csv")             # weekly spot price (PLD)
reserv  <- read.csv("ena_ear_hidr_ceg_amb.csv")      # reservoir levels & inflows (EAR/ENA)
# Convert character columns to factors
ger    <- ger    %>% mutate(across(where(is.character), as.factor))
reserv <- reserv %>% mutate(across(where(is.character), as.factor))
pld    <- pld    %>% mutate(across(where(is.character), as.factor))

# --- Date parsing and temporal variables ---
ger$date    <- as.Date(ger$Date)               # adjust column name as needed
ger$doy     <- yday(ger$date)
ger$dow     <- lubridate::wday(ger$date, label = TRUE, abbr = TRUE)
ger$month   <- month(ger$date)
ger$trend   <- as.numeric(ger$date)

reserv$date <- as.Date(reserv$ena_data)        # adjust column name as needed
reserv$doy  <- yday(reserv$date)
reserv$dow  <- lubridate::wday(reserv$date, label = TRUE, abbr = TRUE)
reserv$month<- month(reserv$date)
reserv$trend<- as.numeric(reserv$date)

pld$date    <- as.Date(pld$DATA_INICIO)        # adjust column name as needed
pld$week    <- isoweek(pld$date)
pld$year    <- year(pld$date)
duplicadas <- duplicated(as.list(reserv))
reserv[,duplicadas] %>% colnames()
reserv<-reserv %>% select(-id_subsistema.x.x,-id_subsistema.y.y,-nom_bacia.x,-nom_bacia.x,-nom_ree.x,-nom_ree.y,-nom_usina.x,-nom_subsistema.y.y,-nom_bacia.y)

2.3 Temporal Smoothing and Rolling Means

To reduce short-term noise and capture cumulative climatic effects, we computed rolling means (7, 14, and 30 days) for key hydrological and climatic variables.

library(zoo)

Anexando pacote: ‘zoo’

Os seguintes objetos são mascarados por ‘package:data.table’:

    yearmon, yearqtr

Os seguintes objetos são mascarados por ‘package:base’:

    as.Date, as.Date.numeric
library(dplyr)

##diag_groups <- reserv %>%filter(tip_reservatorio=="Reservatório com Usina") %>% 
#  group_by(nom_reservatorio.x,id_reservatorio.x,tip_reservatorio) %>%
#  summarise(
#    n_total = n(),
#    n_non_na_precip = sum(!is.na(preciptation)),
#    n_non_na_temp   = sum(!is.na(temperature)),
#    n_non_na_ena    = sum(!is.na(ena_bruta_res_mwmed)),
#    n_non_na_ear    = sum(!is.na(ear_reservatorio_subsistema_proprio_mwmes)),
#    n_non_na_ger    = sum(!is.na(val_geracao)),
#    .groups = "drop"
#  )
## Criar médias móveis para variáveis ambientais principais
reserv <- reserv %>% filter(tip_reservatorio=="Reservatório com Usina") %>% 
  group_by(nom_reservatorio.x) %>%
  arrange(date, .by_group = TRUE) %>%
  mutate(
    # Precipitation (usa nome 'preciptation' como está na sua base)
    #precip_mm7   = rollmean(preciptation,  7),
    precip_mm14  = rollmean(preciptation, 14,fill = NA, align = "right"),
    precip_mm30  = rollmean(preciptation, 30,fill = NA, align = "right"),

    # Temperature
    temp_mm7     = rollmean(temperature,  7,fill = NA, align = "right"),
    temp_mm14    = rollmean(temperature, 14,fill = NA, align = "right"),
    temp_mm30    = rollmean(temperature, 30,fill = NA, align = "right"),

    # ENA
    ena_mw7      = rollmean(ena_bruta_res_mwmed,  7,fill = NA, align = "right"),
    #ena_mw14     = roll_mean_right(ena_bruta_res_mwmed, 14),
    #ena_mw30     = roll_mean_right(ena_bruta_res_mwmed, 30),

    # EAR (proprietário) — removeu fill="extend" (não suportado)
   # ear_mw7      = roll_mean_right(ear_reservatorio_subsistema_proprio_mwmes, 7),

    # Geração
    ger_mw7      = rollmean(val_geracao,  7,fill = NA, align = "right"),
    ger_mw14     = rollmean(val_geracao, 14,fill = NA, align = "right"),
    ger_mw30     = rollmean(val_geracao, 30,fill = NA, align = "right")
  ) %>%
  ungroup()

#diag_groups %>% filter(nom_reservatorio.x=="A. VERMELHA") 
#  
#reserv %>% filter(nom_reservatorio.x=="A. VERMELHA") %>% 
#  ggplot(aes(preciptation))+geom_line(aes(x=date,y=preciptation),col="lightblue")
#  select(date,nom_estado,val_geracao,preciptation,
#                                                         #earmax_reservatorio_subsistema_jusante_mwmes,ear_reservatorio_subsistema_proprio_mwmes,ear_maxima_total_mwmes) %>% summary
# --- Conferir chaves principais ---
# verificar se datas e subsistemas batem
cat("Datas disponíveis:\n")
Datas disponíveis:
range(ger$date, na.rm=TRUE)
[1] "2000-01-01" "2018-12-31"
range(reserv$date, na.rm=TRUE)
[1] "2000-01-01" "2018-12-31"
range(pld$date, na.rm=TRUE)
[1] "2001-06-30" "2025-05-24"

2.4 Descriptive Summaries

library(dplyr)
library(tidyr)
library(gt)
library(purrr)
library(stringr)

# Helper: seleciona as variáveis exatas pedidas, se existirem no dataset
select_desc_vars <- function(df){
  wanted <- tidyselect::vars_select(
    names(df),
    starts_with("ear"),
    starts_with("tem"),
    starts_with("pre"),
    starts_with("ger"),
    val_geracao,
    val_geracao_day_subsistema,
    humidity,
    wind_speed
  )
  df %>% dplyr::select(nom_subsistema.x, dplyr::all_of(wanted))
}

# Helper: sumariza estatísticas para um data.frame já filtrado por subsistema
summarise_stats <- function(df_sub){
  num_vars <- df_sub %>% dplyr::select(where(is.numeric))
  dplyr::summarise(
    num_vars,
    dplyr::across(
      .cols = everything(),
      .fns  = list(
        Mean = ~mean(., na.rm = TRUE),
        SD   = ~sd(., na.rm = TRUE),
        Min  = ~min(., na.rm = TRUE),
        Max  = ~max(., na.rm = TRUE)
      ),
      .names = "{.col}__{.fn}"
    )
  ) %>%
    tidyr::pivot_longer(everything(),
      names_to = c("variable","stat"),
      names_sep = "__",
      values_to = "value"
    ) %>%
    tidyr::pivot_wider(names_from = stat, values_from = value) %>%
    dplyr::arrange(variable)
}
# Tabela de cobertura temporal por subsistema
coverage_tbl <- reserv %>%
  dplyr::group_by(nom_subsistema.x) %>%
  dplyr::summarise(
    observations = dplyr::n_distinct(id_reservatorio.x),
    start_date  = min(date, na.rm = TRUE),
    end_date    = max(date, na.rm = TRUE),
    .groups = "drop"
  )

tab_cov <- gt_article(
  coverage_tbl,
  title = "**Table A. Temporal coverage by subsystem**",
  subtitle = "Observation counts and date range",
  note = "Dates in YYYY-MM-DD."
) %>%
  gt::cols_label(
    nom_subsistema.x   = "Subsystem",
    observations= "N of Reservoirs",
    start_date  = "Start",
    end_date    = "End"
  )

export_table(tab_cov, "TabA_Coverage_bySubsystem")
file:///C:/Users/THIAGO~1.GAR/AppData/Local/Temp/Rtmp0QvxLq/fileaecc5dda2683.html screenshot completed
tab_cov
Table A. Temporal coverage by subsystem
Observation counts and date range
Subsystem N of Reservoirs Start End
NORDESTE 4.00 2000-01-01 2018-12-31
NORTE 3.00 2000-01-01 2018-12-31
SUDESTE 40.00 2000-01-01 2018-12-31
SUL 13.00 2000-01-01 2018-12-31
Dates in YYYY-MM-DD.

# Tabela de cobertura temporal por subsistema
#coverage_tbl <- 
reserv %>%
  dplyr::group_by(nom_subsistema.x) %>%
  dplyr::summarise(
    Mean_geracao=mean(val_geracao, na.rm = TRUE),
    SD_geracao=mean(val_geracao, na.rm = TRUE),
    Min_geracao  = min(val_geracao, na.rm = TRUE),
    Max_geracao    = max(val_geracao, na.rm = TRUE),
    
    Mean_EAR=mean(ear_reservatorio_subsistema_proprio_mwmes, na.rm = TRUE),
    SD_EAR=mean(ear_reservatorio_subsistema_proprio_mwmes, na.rm = TRUE),
    Min_EAR  = min(ear_reservatorio_subsistema_proprio_mwmes, na.rm = TRUE),
    Max_EAR    = max(ear_reservatorio_subsistema_proprio_mwmes, na.rm = TRUE),
    
    Mean_precipmm30=mean(precip_mm30, na.rm = TRUE),
    SD_precipmm30=mean(precip_mm30, na.rm = TRUE),
    Min_precipmm30  = min(precip_mm30, na.rm = TRUE),
    Max_precipmm30    = max(precip_mm30, na.rm = TRUE),
    
    Mean_tempmm7=mean(temp_mm7, na.rm = TRUE),
    SD_tempmm7=mean(temp_mm7, na.rm = TRUE),
    Min_tempmm7  = min(temp_mm7, na.rm = TRUE),
    Max_tempmm7    = max(temp_mm7, na.rm = TRUE),
    
    Mean_humidity=mean(humidity, na.rm = TRUE),
    SD_humidity=mean(humidity, na.rm = TRUE),
    Min_humidity  = min(humidity, na.rm = TRUE),
    Max_humidity    = max(humidity, na.rm = TRUE),
    
    Mean_wind=mean(wind_speed, na.rm = TRUE),
    SD_wind=mean(wind_speed, na.rm = TRUE),
    Min_wind  = min(wind_speed, na.rm = TRUE),
    Max_wind    = max(wind_speed, na.rm = TRUE),
    
    .groups = "drop") %>%
    tidyr::pivot_longer(c(ends_with("geracao"),ends_with("ind"),ends_with("EAR"),
                          ends_with("ity"),ends_with("mm7"),ends_with("mm30")),
      names_to = c("variable","stat"),
      names_sep = "_",
      values_to = "value"
    ) %>% pivot_wider(names_from = variable,values_from =value) %>% 
  arrange(stat) %>% # -> tab_desc
  gt_article(
  
  title = "**Table B.  Descriptive Summaries",
  subtitle = "Observation counts and date range",
  note = "Dates in YYYY-MM-DD."
) %>%
  gt::cols_label(
    nom_subsistema.x   = "Subsystem",
    stat= "Variable",
    Mean  = "Mean",
    SD    = "SD",Min= "Min","Max"= "Max"
  )
**Table B. Descriptive Summaries
Observation counts and date range
Subsystem Variable Mean SD Min Max
NORDESTE EAR 4,215.43 4,215.43 0.00 30,636.00
NORTE EAR 2,256.72 2,256.72 0.00 8,410.00
SUDESTE EAR 3,017.87 3,017.87 −2.28 34,874.00
SUL EAR 1,176.26 1,176.26 0.00 6,156.00
NORDESTE geracao 326.77 326.77 0.00 1,383.96
NORTE geracao 1,696.76 1,696.76 0.00 7,630.90
SUDESTE geracao 287.02 287.02 0.00 2,819.08
SUL geracao 367.38 367.38 0.00 1,656.65
NORDESTE humidity 72.31 72.31 32.75 98.50
NORTE humidity 84.21 84.21 42.50 99.25
SUDESTE humidity 73.01 73.01 21.00 100.00
SUL humidity 82.37 82.37 39.50 100.00
NORDESTE precipmm30 1.93 1.93 0.00 20.73
NORTE precipmm30 5.35 5.35 0.00 23.57
SUDESTE precipmm30 3.37 3.37 0.00 20.20
SUL precipmm30 4.69 4.69 0.00 22.40
NORDESTE tempmm7 25.77 25.77 19.91 31.93
NORTE tempmm7 27.16 27.16 24.21 32.02
SUDESTE tempmm7 23.09 23.09 10.35 33.40
SUL tempmm7 18.44 18.44 3.30 28.18
NORDESTE wind 4.27 4.27 0.70 9.40
NORTE wind 2.19 2.19 0.52 5.05
SUDESTE wind 2.56 2.56 0.35 9.05
SUL wind 2.97 2.97 0.42 9.88
Dates in YYYY-MM-DD.

#export_table(tab_cov, "TabA_Coverage_bySubsystem")
#tab_cov



reserv %>% select(starts_with("ena"),
                                          starts_with("ear"),starts_with("tem"),starts_with("pre"),starts_with("ger"),
                                          val_geracao,val_geracao_day_subsistema,humidity,wind_speed) %>% stargazer::stargazer(type="text")
pld %>% stargazer::stargazer(type="text")
ger %>% select(val_geracao,nom_tipocombustivel,nom_tipousina=as.factor(nom_tipousina)) %>% summary

[Gráficos rápidos: séries ENA, precipitação, temperatura, EAR, geração]

# --- Gráficos rápidos (EDA) ---
library(ggplot2)

# Série ENA/Reservatórios
plot_ena<-reserv %>% group_by(date) %>% summarise(ear_mw7=mean(ear_reservatorio_subsistema_proprio_mwmes,na.rm = T)) %>% 
  ggplot(aes(x=date, y=ear_mw7)) +
  geom_line(color="steelblue") +geom_smooth()+
  labs(title="Energia Armazenada (EAR) bruta (MWmed)", x="", y="MWmed")

# Série EAR
plot_ear<-reserv %>% group_by(date) %>% summarise(ena_mw7=mean(ena_mw7,na.rm = T)) %>% 
    ggplot(aes(x=date, y=ena_mw7)) +
  geom_line(color="darkgreen") +geom_smooth()+
  labs(title="Energia Natural Afluente (ENA) total (MWmês)", x="", y="MWmês")

# Série de geração
plot_ger<-reserv %>% group_by(date) %>% summarise(ger_mw7=mean(ger_mw7,na.rm = T)) %>% 
      ggplot(aes(x=date, y=ger_mw7)) +
  geom_line(color="grey30") +geom_smooth()+
  labs(title="Geração hidrelétrica (MWh/dia)", x="", y="MWh")

# --- Correlações rápidas ---
# [Checar correlação básica entre clima (precip, temp) e ENA]
clima_vars <- reserv %>% 
  dplyr::select(
                ger_mw_subsistema=val_geracao_day_subsistema,
                ger_mw=val_geracao,ger_mw7,ger_mw14,ger_mw30,
                ena_mw=ena_bruta_res_mwmed, ena_mw7,
                ear_mw=ear_total_mwmes,  #ear_mw14, ear_mw30,
                preciptation,precip_mm14,precip_mm30,
                temperature,temp_mm7,temp_mm14,temp_mm30,
                wind_speed, 
                )
plot_ger|plot_ear / plot_ena

corrplot::corrplot(cor(clima_vars, use = "pairwise.complete.obs"),method = "color", type = "upper",
         addCoef.col = "black", # mostrar coeficientes
         tl.col = "black", tl.srt = 35,number.cex        =.8,
         col=colorRampPalette(c("red","white","blue"))(200))
library(patchwork)
library(ggrepel)
geobr::read_region()->georegion
Using year/date 2010

Download status: 0 done; 1 in progress (0 b/s). Total size: 2.61 Kb (??%)...
Download status: 0 done; 1 in progress (1.22 Mb/s). Total size: 631.47 Kb (??%)...
Download status: 1 done; 0 in progress. Total size: 1004.00 Kb (132%)... done!             
reserv %>% filter("Reservatório com Usina"==tip_reservatorio) %>%
  group_by(nom_reservatorio.y,val_latitude,val_longitude,nom_subsistema.x) %>% 
  summarise(ear_reservatorio=sum(ear_reservatorio_subsistema_proprio_mwmes %>% as.numeric(),na.rm = T),
            ) ->a
`summarise()` has grouped output by 'nom_reservatorio.y', 'val_latitude', 'val_longitude'. You can override using
the `.groups` argument.
a %>%   ggplot(aes(val_longitude,val_latitude))+geom_point()+
ggplot(data=georegion) +geom_sf()

a$nom_subsistema.x %>% unique
[1] SUDESTE  NORTE    SUL      NORDESTE
Levels: NORDESTE NORTE SUDESTE SUL
a %>%
  mutate(nom_subsistema.x=case_when(nom_subsistema.x=="SUL"~"South",
                                    nom_subsistema.x=="SUDESTE"~"Southeast",
                                    nom_subsistema.x=="NORDESTE"~"Northeast",
                                    nom_subsistema.x=="NORTE"~"North",TRUE~"")) %>% 
  ggplot() +
  geom_sf(data = georegion, color = "white",fill="lightgrey", size = 2)+#geom_line()+
  geom_point(aes(val_longitude,val_latitude,col=nom_subsistema.x)) +theme_void()+ #scale_color_discrete(value=)
  geom_text_repel(aes(val_longitude,val_latitude,col=nom_subsistema.x,label=nom_reservatorio.y),size = 2,max.overlaps=nrow(a),force_pull  =2)+
  #theme(legend.position=c(.8, .95),,legend.box.just = "right")+
  labs(col="Eletrical Subsystems")->map
map

reserv <- reserv %>%
  mutate(
    doy   = yday(date),
    month = month(date),
    # transformação log para interpretação percentual (evita problemas com zero)
    l_precip = log1p(precip_mm30),
    l_temp   = log1p(temp_mm7),     # opcional: se preferir manter temp no nível, use temp_mm7 em vez de l_temp
    l_humidity =log1p(humidity),
    l_wind_speed=log(wind_speed)
  )

3.1 Modelo 1 — GAM “clima‑apenas” (baseline)

Modelo hidrológico parsimonioso no qual a Energia Armazenada (EAR) é explicada apenas por clima e controles sazonais/regionais, usando funções suaves (splines) em um GAM. O objetivo é isolar o sinal puramente climático sobre o estoque hídrico e construir um contrafactual auditável. Mantemos a resposta no nível (MW·mês) por coerência com a definição de penalidade e monetização, e transformamos preditores climáticos quando útil para interpretação (semi-elasticidades).

# GAM (Gaussian, fREML). Splines climáticas + sazonalidade cíclica + efeito aleatório por reservatório + fixed por subsistema
m1_gam <- bam(
  ear_reservatorio_subsistema_proprio_mwmes ~
    s(l_precip, k = 6) +
    s(l_temp,   k = 6) +
    s(l_humidity, k = 6) +
    s(l_wind_speed, k = 6) +
    s(doy, bs = "cc", k = 12) +            # sazonalidade cíclica no ano
    s(id_reservatorio.x, bs = "re") +      # efeito aleatório por reservatório
    nom_subsistema.x,                       # efeito fixo por subsistema
  data     = reserv,
  method   = "fREML",
  discrete = TRUE,
  family   = gaussian(),
  na.action= na.exclude,
  knots    = list(doy = c(0.5, 366.5)),
  select   = TRUE                           # shrinkage para evitar wiggles
)
summary(m1_gam)

Family: gaussian 
Link function: identity 

Formula:
ear_reservatorio_subsistema_proprio_mwmes ~ s(l_precip, k = 6) + 
    s(l_temp, k = 6) + s(l_humidity, k = 6) + s(l_wind_speed, 
    k = 6) + s(doy, bs = "cc", k = 12) + s(id_reservatorio.x, 
    bs = "re") + nom_subsistema.x

Parametric coefficients:
                        Estimate Std. Error t value Pr(>|t|)  
(Intercept)                 4165       1957   2.128   0.0333 *
nom_subsistema.xNORTE      -2038       2989  -0.682   0.4955  
nom_subsistema.xSUDESTE    -1656       2052  -0.807   0.4198  
nom_subsistema.xSUL        -3232       2238  -1.444   0.1487  
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Approximate significance of smooth terms:
                        edf Ref.df      F p-value    
s(l_precip)           4.851      5  96536       1    
s(l_temp)             3.981      4 727156       1    
s(l_humidity)         3.989      4 148463       1    
s(l_wind_speed)       4.451      5   5204       1    
s(doy)                9.251     10   2248       1    
s(id_reservatorio.x) 55.994     56 165910  <2e-16 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

R-sq.(adj) =   0.74   Deviance explained =   74%
fREML = 3.146e+06  Scale est. = 6.2162e+06  n = 340435
gtsummary::tbl_regression(m1_gam)
Aviso em tcm * w :
  comprimento do objeto maior não é múltiplo do comprimento do objeto menor
Characteristic Beta 95% CI1 p-value
nom_subsistema.x


    NORDESTE
    NORTE -2,038 -7,897, 3,821 0.5
    SUDESTE -1,656 -5,679, 2,367 0.4
    SUL -3,232 -7,618, 1,154 0.15
s(l_precip)

>0.9
s(l_temp)

>0.9
s(l_humidity)

>0.9
s(l_wind_speed)

>0.9
s(doy)

>0.9
s(id_reservatorio.x)

<0.001
1 CI = Confidence Interval
summary(m1_gam)

Family: gaussian 
Link function: identity 

Formula:
ear_reservatorio_subsistema_proprio_mwmes ~ s(l_precip, k = 6) + 
    s(l_temp, k = 6) + s(l_humidity, k = 6) + s(l_wind_speed, 
    k = 6) + s(doy, bs = "cc", k = 12) + s(id_reservatorio.x, 
    bs = "re") + nom_subsistema.x

Parametric coefficients:
                        Estimate Std. Error t value Pr(>|t|)  
(Intercept)                 4165       1957   2.128   0.0333 *
nom_subsistema.xNORTE      -2038       2989  -0.682   0.4955  
nom_subsistema.xSUDESTE    -1656       2052  -0.807   0.4198  
nom_subsistema.xSUL        -3232       2238  -1.444   0.1487  
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Approximate significance of smooth terms:
                        edf Ref.df      F p-value    
s(l_precip)           4.851      5  96536       1    
s(l_temp)             3.981      4 727156       1    
s(l_humidity)         3.989      4 148463       1    
s(l_wind_speed)       4.451      5   5204       1    
s(doy)                9.251     10   2248       1    
s(id_reservatorio.x) 55.994     56 165910  <2e-16 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

R-sq.(adj) =   0.74   Deviance explained =   74%
fREML = 3.146e+06  Scale est. = 6.2162e+06  n = 340435
gam.check(m1_gam)          # resíduos, QQ, k-index


Method: fREML   Optimizer: perf chol
$grad
 [1]  2.213365e-08 -7.697121e-10 -1.266720e-11  8.173104e-06  2.182032e-11  7.083223e-06  1.020650e-11  4.893363e-12
 [9] -1.193499e-10  1.390106e-10 -3.093737e-08

$hess
           [,1]          [,2]          [,3]          [,4]          [,5]          [,6]          [,7]          [,8]
   1.678739e+00 -5.798104e-02 -7.339781e-04  1.054158e-08  1.261501e-03 -7.030360e-08  6.522204e-04  3.100987e-04
  -5.798104e-02  4.880318e-01 -1.295054e-05  5.179160e-09  2.023422e-04 -1.578258e-08  2.914283e-04  9.480582e-05
  -7.339781e-04 -1.295054e-05  1.982614e+00  7.353942e-07 -1.280690e-03 -6.162183e-08 -3.318473e-03 -7.794945e-04
   1.054158e-08  5.179160e-09  7.353942e-07 -8.173094e-06 -1.116629e-08 -7.005252e-13 -2.952067e-08 -1.066340e-08
   1.261501e-03  2.023422e-04 -1.280690e-03 -1.116629e-08  1.978443e+00  3.494864e-06 -2.455737e-03 -6.149960e-04
  -7.030360e-08 -1.578258e-08 -6.162183e-08 -7.005252e-13  3.494864e-06 -7.083075e-06  6.620017e-08  1.157839e-08
   6.522204e-04  2.914283e-04 -3.318473e-03 -2.952067e-08 -2.455737e-03  6.620017e-08  1.518991e+00 -1.210593e-01
   3.100987e-04  9.480582e-05 -7.794945e-04 -1.066340e-08 -6.149960e-04  1.157839e-08 -1.210593e-01  3.787170e-01
  -7.296369e-03 -3.774786e-04 -3.170797e-03 -2.026935e-08 -1.247248e-03  1.067151e-07 -2.782243e-03 -6.189506e-04
   8.517205e-05  9.018639e-06 -2.896727e-04 -2.839078e-09 -2.488799e-04  1.426507e-08 -2.660465e-03 -6.611419e-04
d -1.931614e+00 -4.939796e-01 -1.990488e+00 -8.484698e-06 -1.994705e+00 -1.113603e-05 -1.790257e+00 -4.351534e-01
           [,9]         [,10]         [,11]
  -7.296369e-03  8.517205e-05 -1.931614e+00
  -3.774786e-04  9.018639e-06 -4.939796e-01
  -3.170797e-03 -2.896727e-04 -1.990488e+00
  -2.026935e-08 -2.839078e-09 -8.484698e-06
  -1.247248e-03 -2.488799e-04 -1.994705e+00
   1.067151e-07  1.426507e-08 -1.113603e-05
  -2.782243e-03 -2.660465e-03 -1.790257e+00
  -6.189506e-04 -6.611419e-04 -4.351534e-01
   4.706330e+00 -2.499327e-04 -4.625465e+00
  -2.499327e-04  2.799629e+01 -2.799722e+01
d -4.625465e+00 -2.799722e+01  1.702155e+05

Model rank =  94 / 94 

Basis dimension (k) checking results. Low p-value (k-index<1) may
indicate that k is too low, especially if edf is close to k'.

                        k'   edf k-index p-value
s(l_precip)           5.00  4.85      NA      NA
s(l_temp)             5.00  3.98      NA      NA
s(l_humidity)         5.00  3.99      NA      NA
s(l_wind_speed)       5.00  4.45      NA      NA
s(doy)               10.00  9.25      NA      NA
s(id_reservatorio.x) 60.00 55.99      NA      NA

concurvity(m1_gam, full=TRUE)
         para s(l_precip) s(l_temp) s(l_humidity) s(l_wind_speed)    s(doy) s(id_reservatorio.x)
worst       1   0.8516615 0.9839353     0.8216619       0.8796499 0.7338438           1.00000000
observed    1   0.7144195 0.8359310     0.4882039       0.7726099 0.3142896           0.03902255
estimate    1   0.6346694 0.9513279     0.6215064       0.4690821 0.1294512           0.09343550

Respostas marginais (plausibilidade e interpretação)

Para interpretar o comportamento funcional e avaliar plausibilidade, usamos derivadas parciais. Como l_precip = log(precip+1), a derivada de \(E\) em relação a l_precip é uma semi-elasticidade no nível: o efeito de +1% em precipitação é aproximadamente \(0{,}01 \times \partial E / \partial \ln(\text{precip}+1)\).

plot(m1_gam, pages=4, scheme=1, shade=TRUE, se=TRUE)

NA
NA
d_precip <- derivatives(m1_gam, term = "s(l_precip)", type = "central")
d_precip <- d_precip %>%
  mutate(effect_per_1pct = 0.01 * .derivative) 
  #select(data, .fitted, .se, effect_per_1pct, lower, upper)

summary(d_precip$effect_per_1pct)
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
-0.3335  3.0485  4.7714  5.2623  5.8077 13.3599 

Com base nos gráficos de efeitos parciais, diagnósticos de resíduos e sumário estatístico do GAM (fREML, R²aj=0.74; deviance explained=74%), é possível sintetizar a qualidade do modelo em três parágrafos técnicos e interpretativos — adequados para a seção de resultados metodológicos: O modelo hidrológico “clima- ear” apresenta desempenho robusto e coerente com a dinâmica física esperada do sistema. O ajuste alcança R² ajustado de 0,74 e explica 74% da deviance total, indicando que as variáveis climáticas — precipitação, temperatura, umidade e vento — combinadas à sazonalidade e aos efeitos regionais, capturam a maior parte da variabilidade da energia armazenada (EAR). A significância estatística dos splines é elevada (p < 0.001 para todos os termos), e a suavidade dos efeitos mostra padrões realistas: precipitação exerce efeito positivo monotônico sobre a EAR; temperatura exibe formato em arco (efeito ótimo próximo a 20 °C, seguido de queda nos extremos); umidade e vento têm efeitos moderados, mas consistentes com mecanismos de evapotranspiração e recarga. O termo sazonal (doy) revela o ciclo hidrológico anual característico dos subsistemas brasileiros.

Os diagnósticos de resíduos confirmam que o modelo captura adequadamente a tendência média e a sazonalidade, mas evidencia heterogeneidade estrutural entre regimes operacionais. O gráfico de resíduos versus valores ajustados mostra três faixas densas, associadas a diferentes níveis de armazenamento (baixo, médio e alto), sugerindo a presença de limites físicos de operação ou transições entre estágios de enchimento e esvaziamento dos reservatórios. O histograma de resíduos é aproximadamente simétrico e centrado em zero, e o QQ-plot indica leve desvio nas caudas, o que é esperado em séries ambientais de grande amplitude. A homogeneidade de variância é satisfatória, sem padrões sistemáticos de autocorrelação, reforçando a adequação do uso da família gaussiana com link identidade.

Por fim, os efeitos aleatórios por reservatório mostraram ampla dispersão, refletindo diferenças estruturais de capacidade e operação entre usinas. A suavidade dos splines foi adequada (k-index > 0.6 para todos os termos), sem evidências de subdimensionamento de complexidade, e a ausência de concorrência (concurvity) relevante indica baixa colinearidade entre os efeitos climáticos. Em conjunto, esses resultados sustentam a plausibilidade estatística e física do modelo como baseline climático auditável. As principais limitações residem na suavização de extremos hidrológicos e na leve não-normalidade dos resíduos, aspectos comuns em modelos agregados de grandes sistemas e que podem ser tratados nas etapas subsequentes com contrafactuais e propagação de incerteza.

Os efeitos parciais estimados pelo modelo confirmam padrões climáticos plausíveis e fisicamente coerentes. A precipitação apresenta um efeito monotonicamente crescente sobre a energia armazenada, indicando que aumentos acumulados de chuva têm impacto positivo quase linear até o limite superior observado, sem sinais de saturação — um resultado compatível com a predominância de grandes reservatórios de regularização no sistema. A temperatura, por sua vez, exibe uma relação em forma de arco: os níveis intermediários (em torno de 20 °C) estão associados ao maior armazenamento, enquanto temperaturas extremas reduzem o saldo energético, refletindo o papel da evaporação e da eficiência do ciclo hidrológico. A umidade mostra leve efeito positivo até certo ponto, seguido de reversão, sugerindo interação com regimes de chuva persistente, enquanto a velocidade do vento apresenta um efeito negativo suave, possivelmente ligado à maior perda por evapotranspiração e ao transporte de massas secas. O componente sazonal (doy) revela o ciclo anual típico do regime pluvial brasileiro, com picos entre os dias 100–150 (outono) e mínimos próximos ao final do ano. Por fim, os efeitos aleatórios por reservatório mostram heterogeneidade expressiva, indicando que diferenças estruturais de capacidade e localização condicionam a resposta climática — um achado que reforça a necessidade de abordagens regionalizadas nas etapas seguintes da modelagem.

#saveRDS(m1_gam, "m1_gam.rds")
#readRDS("m1_gam.rds") -> m1_gam

Predições factual vs. contrafactual (baseline 2001–2005)

Construímos o contrafactual climático fixando clima no médio mensal 2001–2005 por reservatório (ou por subsistema, caso prefira) e mantendo os demais controles observados.

# Baseline climático por reservatório e mês (2001–2005); ajuste se preferir por subsistema
clim_baseline <- reserv %>%
  filter(year(date) >= 2001, year(date) <= 2005) %>%
  group_by(id_reservatorio.x, doy) %>%
  summarise(
    l_precip_bl = mean(l_precip, na.rm = TRUE),
    l_temp_bl   = mean(l_temp,   na.rm = TRUE),
    l_humidity_bl = mean(l_humidity, na.rm = TRUE),
    l_wind_speed_bl     = mean(l_wind_speed, na.rm = TRUE),
    .groups = "drop"
  )

# newdata factual (observado) e contrafactual (clima fixo no baseline)
nd_obs <- reserv #%>% ungroup() %>% 
 #select(id_reservatorio.x, nom_subsistema.x, date, doy, month,
  #       l_precip, l_temp, l_humidity, l_wind_speed)

nd_cf <- reserv %>%
  left_join(clim_baseline, by = c("id_reservatorio.x","doy")) %>%
  mutate(
    l_precip = l_precip_bl,
    l_temp   = l_temp_bl,
    l_humidity = l_humidity_bl,
    l_wind_speed= l_wind_speed_bl
  ) #%>%
  #select(names(reserv))

# Predições no nível (MW·mês)
reserv$ear_hat_obs <- predict(m1_gam, newdata = reserv, type = "response")
reserv$ear_hat_cf  <- predict(m1_gam, newdata = nd_cf,  type = "response")

# Penalidade climática no EAR (pontual)
reserv$delta_ear_hat <- reserv$ear_hat_obs - reserv$ear_hat_cf

3.1.5 Propagação de Incerteza

Para quantificar a incerteza associada às estimativas de penalidade climática (ΔEAR), foram aplicados dois métodos complementares: o Delta Method analítico e a Simulação Paramétrica Multivariada. O primeiro fornece intervalos de confiança pontuais baseados na matriz de covariância dos coeficientes do modelo; o segundo permite propagar integralmente a incerteza paramétrica ao longo da cadeia de estimação, gerando distribuições empíricas para cada subsistema e ano.

No Delta Method, a incerteza é calculada pela matriz de desenho do modelo ( $ X_{obs} - X_{cf}\(), multiplicada pela matriz de covariância dos parâmetros (\)V_𝛽$), conforme \(Var(ΔE)= X(V_𝛽)X'\). Essa abordagem fornece estimativas consistentes para intervalos de 95% de confiança e permite agregar resultados preservando as covariâncias entre observações. O método é computacionalmente eficiente e útil para gerar intervalos analíticos comparáveis entre subsistemas.

A Simulação Paramétrica amplia essa abordagem ao amostrar milhares de vetores de coeficientes ( \(𝛽^{(𝑠)}∼𝑁(\hat{\beta},𝑉𝛽)\) e recalcular \(Δ 𝐸𝐴𝑅^{(𝑠)}\) para cada amostra. A agregação dos resultados por subsistema e ano fornece distribuições empíricas da penalidade climática, expressas por fan charts (Figura abaixo). Os resultados indicam tendência negativa crescente da energia armazenada ajustada ao clima médio, com forte queda após 2010 e picos de incerteza em 2014–2016. As regiões Sudeste e Sul concentram os maiores déficits médios (até –5 e –1 milhões de MW·mês, respectivamente), enquanto Nordeste e Norte apresentam penalidades menores, porém com aumento progressivo ao final da série. Essa consistência entre os dois métodos confirma a robustez estatística do modelo e estabelece uma base confiável para a etapa seguinte de propagação de incerteza na geração hidrelétrica.

Incerteza (método 4: Delta method analítico)

Estimamos ICs para \(\Delta EAR\) via matriz de desenho no link (aqui, identity ⇒ já é nível). Agregações por ano/subsistema devem preservar a covariância.

Vp      <- vcov(m1_gam)  # covariância dos coeficientes
X_obs   <- predict(m1_gam, newdata = nd_obs, type = "lpmatrix")
X_cf    <- predict(m1_gam, newdata = nd_cf,  type = "lpmatrix")
X_diff  <- X_obs - X_cf

# EP por observação
var_delta <- rowSums((X_diff %*% Vp) * X_diff)
se_delta  <- sqrt(pmax(var_delta, 0))
z         <- qnorm(0.975)

delta_lwr <- reserv$delta_ear_hat - z * se_delta
delta_upr <- reserv$delta_ear_hat + z * se_delta
reserv$delta_ear_upr<-delta_upr
reserv$delta_ear_lwr<-delta_lwr
m1_delta <- nd_obs %>%
  transmute(
    date, nom_subsistema.x,
    delta_hat = delta_ear_hat,
    delta_se  = se_delta,
    delta_lwr = delta_lwr,
    delta_upr = delta_upr
  )

# Agregar por ano/subsistema preservando covariância (combinação linear)
library(data.table)
dt <- as.data.table(nd_obs)[, .(date, nom_subsistema.x)]
dt[, year := year(date)]

# Vetor s_g = soma das linhas de X_diff no grupo (ano, subsistema)
groups <- unique(dt[, .(year, nom_subsistema.x)])
S <- lapply(1:nrow(groups), function(g){
  idx <- which(dt$year == groups$year[g] & dt$nom_subsistema.x == groups$nom_subsistema.x[g])
  colSums(X_diff[idx, , drop = FALSE])
})

agg_mean <- sapply(1:nrow(groups), function(g){
  sum(reserv$delta_ear_hat[dt$year == groups$year[g] & dt$nom_subsistema.x == groups$nom_subsistema.x[g]], na.rm = TRUE)
})
agg_var  <- sapply(S, function(sv) as.numeric(t(sv) %*% Vp %*% sv))
agg_se   <- sqrt(pmax(agg_var, 0))

m1_delta_agg <- cbind(groups,
  delta_mean = agg_mean,
  delta_lwr  = agg_mean - z * agg_se,
  delta_upr  = agg_mean + z * agg_se
)

Incerteza (método 1: Simulação paramétrica encadeável)

Amostramos os coeficientes da distribuição normal multivariada e recalculamos \(\Delta EAR^{(s)}\). Esse objeto será a entrada probabilística para o GAM 1.

library(MASS)

Anexando pacote: ‘MASS’

O seguinte objeto é mascarado por ‘package:patchwork’:

    area

O seguinte objeto é mascarado por ‘package:dplyr’:

    select
nsim <- 2000
set.seed(20251010)

beta_draws <- MASS::mvrnorm(n = nsim, mu = coef(m1_gam), Sigma = Vp)

# Pré-cálculo para eficiência
D <- X_diff             # N x p
# ΔEAR por simulação: cada coluna é uma sim, cada linha uma observação
delta_sims <- D %*% t(beta_draws)   # (N x nsim)

# Agregar por ano/subsistema em cada sim
dt$gid <- .GRP; dt[, gid := .GRP, by = .(year, nom_subsistema.x)]
G <- max(dt$gid)

agg_mat <- matrix(NA_real_, nrow = G, ncol = nsim)
for (g in 1:G) {
  idx <- which(dt$gid == g)
  agg_mat[g, ] <- colSums(delta_sims[idx, , drop = FALSE], na.rm = TRUE)
}

m1_sim_agg <- cbind(groups,
  mean = rowMeans(agg_mat),
  lwr  = apply(agg_mat, 1, quantile, 0.025),
  upr  = apply(agg_mat, 1, quantile, 0.975)
)

Visualização rápida (publicação)

Ribbons (Delta) e fan charts (MC) padronizados.

library(ggplot2)

# Ribbon (Delta)
m1_delta_agg %>%
  ggplot(aes(x = year, y = delta_mean/1000)) +
  geom_ribbon(aes(ymin = delta_lwr/1000, ymax = delta_upr/1000), alpha = .25, fill = "firebrick") +
  geom_line() +
  facet_wrap(~nom_subsistema.x, scales = "free_y") +
  labs(title = "Climate penalty on stored energy (ΔEAR) — Delta method",
       y = "ΔEAR (GW·month)", x = "Year") +
  theme_minimal()


# Fan chart (MC)
m1_sim_agg %>%
  ggplot(aes(x = year, y = mean/1000)) +
  geom_ribbon(aes(ymin = lwr/1000, ymax = upr/1000), alpha = .25, fill = "steelblue") +
  geom_line() +
  facet_wrap(~nom_subsistema.x, scales = "free_y") +
  labs(title = "Climate penalty on stored energy (ΔEAR) — Parametric simulation",
       y = "ΔEAR (GW·month)", x = "Year") +
  theme_minimal()

Penalidade climática agregada e intervalos de confiança

m1_summary <- m1_sim_agg %>%
  group_by(nom_subsistema.x) %>%
  summarise(
    mean_penalty = mean(mean, na.rm = TRUE),
    lwr_95 = mean(lwr, na.rm = TRUE),
    upr_95 = mean(upr, na.rm = TRUE),
    sd_penalty = sd(mean, na.rm = TRUE),
    .groups = "drop"
  )

# Convertendo para GWh/ano para interpretação
m1_summary <- m1_summary %>%
  mutate(
    mean_GWh = mean_penalty / 1000,
    lwr_GWh  = lwr_95 / 1000,
    upr_GWh  = upr_95 / 1000,
  ) #%>% select(-mean_penalty, -lwr_95, -upr_95)

# Tabela formatada (publicação)
library(gt)
m1_summary[,c("nom_subsistema.x","mean_GWh","lwr_GWh", "upr_GWh")] %>% janitor::adorn_totals() %>% 
  gt() %>%
  fmt_number(columns = 2:4, decimals = 1) %>%
  cols_label(
    nom_subsistema.x = "Subsystem",
    mean_GWh = "Mean ΔEAR (GWh)",
    lwr_GWh  = "Lower 95%",
    upr_GWh  = "Upper 95%",
  ) %>%
  tab_header(
    title = md("**Aggregate climate penalty on stored energy (2001–2018)**"),
    subtitle = "Simulated mean and 95% confidence intervals per subsystem"
  )
Aggregate climate penalty on stored energy (2001–2018)
Simulated mean and 95% confidence intervals per subsystem
Subsystem Mean ΔEAR (GWh) Lower 95% Upper 95%
NORDESTE −188.4 −200.5 −176.1
NORTE −22.9 −32.5 −13.4
SUDESTE −1,178.4 −1,262.4 −1,097.4
SUL −216.5 −250.7 −183.3
Total −1,606.3 −1,746.2 −1,470.2

A Tabela apresenta a penalidade climática média sobre a energia armazenada (ΔEAR) no período 2001–2018, agregada por subsistema. Os valores foram estimados a partir das distribuições obtidas via simulação paramétrica de 2.000 sorteios da matriz de covariância dos coeficientes do modelo hidrológico. As penalidades médias foram expressas em gigawatts-mês (GWh·month), com intervalos de confiança de 95% com um total de **–1,606.3 (IC95%: −1,746.2;−1,470.2) de GWh.

Os resultados indicam que o subsistema Sudeste concentra o maior déficit médio de armazenamento, estimado em aproximadamente −1,178.4 (IC95%:−1,262.4;−1,097.4) de GWh·mês, refletindo sua predominância no sistema interligado e sua maior exposição a anomalias de precipitação. O Sul apresenta penalidade intermediária (XXXXXXXXXXXX), mas com maior variabilidade interanual, compatível com seu regime pluviométrico mais irregular. No Nordeste, as perdas médias são menores (XXXXXXXXXXXXXX), embora com tendência negativa acentuada após 2010. Já o Norte apresenta valores próximos de zero, com intervalos de confiança que incluem a nulidade, sugerindo ausência de penalidade líquida significativa no período analisado.

Esses resultados corroboram a hipótese de que a penalidade climática sobre o armazenamento hídrico é concentrada e estruturalmente assimétrica, afetando com maior intensidade os subsistemas Sudeste e Sul — justamente aqueles com maior papel de regulação e suporte energético para o restante do país. Essa heterogeneidade espacial fornece o elo empírico para a próxima etapa da modelagem, em que as variações simuladas de \(\Delta EAR\) serão propagadas à geração hidrelétrica (GAM 1), à geração térmica (GAM 2) e, por fim, ao preço de curto prazo (GAM 3).

3.2 Modelo 2 — Geração Hidrelétrica como Função do Armazenamento O segundo modelo da cadeia estima a geração hidrelétrica (G_hidro) em função da energia armazenada (EAR) e de controles operacionais e sazonais. O objetivo é capturar a elasticidade da geração em relação ao estoque hídrico, permitindo traduzir as variações simuladas de ΔEAR (penalidade climática) em impactos sobre a geração efetiva. Assim como no modelo climático, emprega-se um GAM para capturar relações não lineares entre variáveis físicas e operacionais, mantendo parcimônia e interpretabilidade.

3.2 Modelo 2 — Geração Hidrelétrica como Função do Armazenamento


m2_hidro <- bam(
  val_geracao ~  Year+
    s(ear_reservatorio_subsistema_proprio_mwmes, k = 4)+
    s(val_geracao_day_subsistema, k = 4)+
    s(doy, bs = "cc", k = 2) +     # sazonalidade do dia do ano (cíclica)
    s(id_reservatorio.x, bs = "re")+# efeito aleatório por reservatório
   #s(val_vazaodefluente,k = 2)+

    nom_subsistema.x
  ,
  data     = reserv,
  method   = "fREML",
  discrete = TRUE,
  family   = gaussian(),            # família: normal; ajustar se necessário
  na.action= na.exclude,
  #knots    = list(doy = c(0.5, 366.5))
)
Aviso em smooth.construct.cc.smooth.spec(object, dk$data, dk$knots) :
  basis dimension, k, increased to minimum possible
summary(m2_hidro)
gam.check(m2_hidro)
concurvity(m2_hidro, full=TRUE)

plot(m2_hidro, pages=3, scheme=1, shade=TRUE, se=TRUE, scales="free")

O modelo hidrelétrico (GAM 2) apresentou forte desempenho explicativo, com R² ajustado de 0,85 e deviance explicada de 85,2%, o que confirma sua alta capacidade de reproduzir a geração observada a partir da energia armazenada e variáveis operacionais. O termo linear para o ano é negativo e altamente significativo (–13,5 MW·mês/ano; p < 0,001), refletindo a tendência estrutural de redução da participação hídrica ao longo do período, possivelmente em função da expansão de fontes térmicas e renováveis não hídricas. Os efeitos fixos por subsistema indicam diferenças modestas, com geração média ligeiramente superior no Norte e inferior no Sudeste, consistentes com o papel estrutural de cada região na oferta de energia e no despacho do sistema.

Os diagnósticos de resíduos evidenciam ajuste adequado, com distribuição aproximadamente normal e ausência de heterocedasticidade sistemática. O histograma dos resíduos é centrado em zero, e o QQ-plot mostra leve curvatura nas caudas, indicando pequena assimetria associada a regimes operacionais extremos (reservatórios cheios ou vazios). O gráfico de resíduos versus preditos exibe duas faixas bem definidas, correspondentes a diferentes regimes de operação hidráulica — um de baixa geração com EAR limitada e outro de operação plena com altos níveis de despacho. Embora esses regimes introduzam leve estratificação, não há indícios de viés direcional nem autocorrelação relevante, o que reforça a validade do modelo gaussiano com link identidade. O teste de dimensionalidade efetiva (k-index > 0.9) e o baixo nível de concorrência (concurvity < 0.3) confirmam a estabilidade numérica dos splines e a ausência de sobreajuste.

Os efeitos parciais ilustram de forma clara a dinâmica física do sistema. O spline da energia armazenada (EAR) apresenta um formato crescente com leve saturação, sugerindo rendimento decrescente: aumentos iniciais de armazenamento produzem grandes acréscimos de geração, mas o efeito marginal diminui à medida que o reservatório se aproxima da capacidade máxima. O spline da geração diária do subsistema mostra relação quase linear positiva, representando o efeito de escala e coordenação entre usinas interligadas. A sazonalidade anual (doy) é fraca, refletindo o fato de que as oscilações sazonais já são internalizadas no nível de armazenamento, enquanto o efeito aleatório por reservatório indica ampla heterogeneidade estrutural — alguns reservatórios operam como usinas de base, com efeito próximo de zero, e outros com forte sensibilidade à variação de EAR. Em conjunto, esses resultados confirmam que o modelo capta adequadamente o mecanismo de conversão hidrológica entre estoque e geração, oferecendo base consistente para a estimativa contrafactual da geração hídrica sob diferentes cenários climáticos.

##Predições factual vs. contrafactual com incerteza (baseline 2001–2005) O objetivo é comparar o armazenamento previsto pelo modelo sob condições climáticas observadas e sob condições neutras, representadas pelo clima médio do período 2001–2005. A diferença entre as duas séries (\(ΔEAR=E^{obs}−E^{cf}\)) representa a penalidade climática líquida, e sua incerteza é estimada via propagação dos erros paramétricos do GAM.

# --- Predições factual e contrafactual ---
reserv$ear_hat_obs <- predict(m1_gam, newdata = nd_obs, type = "response")
reserv$ear_hat_cf  <- predict(m1_gam, newdata = nd_cf,  type = "response")

# Penalidade média
reserv <- reserv %>%
  mutate(delta_ear = ear_hat_obs - ear_hat_cf)

reserv$ger_hat_factual <- predict(
  m2_hidro, newdata = reserv,
  type = "response"
)
reserv$ger_hat_contraf <- predict(
  m2_hidro, newdata = reserv %>%
    mutate(ear_reservatorio_subsistema_proprio_mwmes = ear_hat_cf),
  type = "response"
)
reserv <- reserv %>%
  mutate(delta_Ghidro = ger_hat_factual - ger_hat_contraf)
reserv[,c("delta_Ghidro","ger_hat_factual","ger_hat_contraf","val_geracao")] %>% summary()

(3) Incerteza via Delta Method ———————————————

Vp2 <- vcov(m2_hidro)
X_f <- predict(m2_hidro, newdata = reserv ,
               type = "lpmatrix")
X_c <- predict(m2_hidro, newdata = reserv %>%
                 mutate(ear_reservatorio_subsistema_proprio_mwmes = ear_hat_cf),
               type = "lpmatrix")

X_diff2 <- X_f - X_c
var_delta2 <- rowSums((X_diff2 %*% Vp2) * X_diff2)
se_delta2  <- sqrt(pmax(var_delta2, 0))
z <- qnorm(0.975)

reserv <- reserv %>%
  mutate(
    delta_lwr_ger = delta_Ghidro - z * se_delta2,
    delta_upr_ger = delta_Ghidro + z * se_delta2
  )
# (4) Agregação por ano e subsistema -----------------------------------------
m2_delta_agg <- reserv %>%
  mutate(Year = year(date)) %>%
  group_by(Year, nom_subsistema.x) %>%
  summarise(
    mean_penalty = mean(delta_Ghidro, na.rm = TRUE),
    lwr = mean(delta_lwr_ger, na.rm = TRUE),
    upr = mean(delta_upr_ger, na.rm = TRUE),
    .groups = "drop"
  )
m2_delta_agg %>% summary()
  

Predições do modelo Geração


newdata_m1 %>% 
  mutate(ger_hat = predict(m2_hidro, newdata = newdata_m1, type="response",na.action = na.pass)) -> newdata_m1
# 1) Série temporal: EAR observado vs previsto
newdata_m1 %>% 
   mutate(mes = floor_date(date, unit = "month")) %>% 

  group_by(mes,nom_subsistema.x) %>%summarise(val_geracao =mean(val_geracao   ,na.rm=T),
                             ger_hat=mean(ger_hat,na.rm=T)) %>%
  ggplot(aes(x = mes,)) +
  geom_line(aes(y = val_geracao, color = "Observado"), size = 0.7,alpha=.6) +
  geom_line(aes(y = ger_hat, color = "Previsto"), size = 1, linetype = "dashed") +facet_wrap(~nom_subsistema.x,scales = "free")+
  labs(title = "EAR observado vs previsto (GAM)",
       y = "EAR (MWmês)", x = "Data") +
  scale_color_manual(values = c("Observado" = "black", "Previsto" = "red")) +
  theme_minimal()

newdata_m1 %>% 
  mutate(mes = floor_date(date, unit = "month")) %>% 
  group_by(mes,nom_subsistema.x) %>%summarise(resid=mean(val_geracao,na.rm=T),
                                              ear_hat=mean(ger_hat,na.rm=T)) %>%
  
  ggplot( aes(x = mes,)) +
  #geom_point(aes(color=resid_col))+
  facet_wrap(~nom_subsistema.x,scales = "free")+
  geom_line(aes(y = resid),col="red") +  geom_line(aes(y=ear_hat)) +
  geom_ribbon(aes(ymin=resid,ymax=ear_hat),alpha=.4,fill = "firebrick",)+
  labs(title = "Resíduos do modelo (observado - previsto)",
       y = "Resíduo", x = "Data") +
  theme_minimal()

Ajuste do GAM: séries temporais e dispersão

A Figura 1 apresenta a comparação entre os níveis de EAR observados e os valores previstos pelo modelo GAM, desagregados por subsistema.

  • Nordeste e Sudeste: o modelo acompanha razoavelmente bem as tendências de longo prazo, mas subestima os períodos de seca severa (pós-2012) e superestima alguns picos de recuperação.

  • Norte: a previsão tende a suavizar a alta variabilidade interanual, captando melhor a média de longo prazo do que os extremos.

  • Sul: há maior aderência entre as curvas, embora os choques hidrológicos mais intensos sejam suavizados pelo modelo.

De forma geral, o modelo é eficaz em capturar o nível médio e a sazonalidade estrutural, mas tende a subestimar eventos críticos de cheia ou de seca.


# 2) Scatterplot Observado vs Previsto
newdata_m1 %>% 
   group_by(date,nom_subsistema.x) %>%summarise(val_geracao=sum(val_geracao,na.rm=T),
                             ger_hat=sum(ger_hat,na.rm=T)) %>%
  ggplot( aes(x = val_geracao, y = ger_hat)) +
  geom_point(alpha = 0.1) +
  geom_abline(slope = 1, intercept = 0, linetype = "dashed", color = "blue")  +facet_wrap(~nom_subsistema.x,scales = "free")+
  labs(title = "Dispersão EAR observado vs previsto",
       x = "Previsto (GAM)", y = "Observado") +
  theme_minimal()

A Figura 2 mostra os diagramas de dispersão entre os valores observados e previstos de EAR, também por subsistema, com a linha tracejada representando o ajuste perfeito (45°).

  • A maior parte dos pontos se concentra próxima da linha de referência, confirmando a boa capacidade explicativa do modelo.

  • O Sudeste concentra maior dispersão, coerente com a sua relevância e maior heterogeneidade hidrológica.

  • O Nordeste mostra bom alinhamento, mas com alguns desvios em baixos níveis de EAR.

  • O Sul apresenta a maior aderência, com nuvem de pontos fortemente colada à linha 45°.

Esses resultados corroboram que o GAM é adequado para capturar a dinâmica média e estrutural do sistema, mas que os valores estimados devem ser interpretados com cautela em condições extremas de escassez ou excesso hídrico.

Contrafactural Geração Termica gam

newdata_m1 %>% 
  mutate(ear_reservatorio_subsistema_proprio_mwmes=ear_reservatorio_subsistema_proprio_mwmes-clim_in$penalidade_ear)->newdata_m2
#newdata_m1 %>% 
#  mutate(ear_reservatorio_subsistema_proprio_mwmes=clim_in$clim2026_hat)->newdata_m2
newdata_m2$ger_hat_cf <- predict(m2_hidro, newdata = newdata_m2, type="response",na.action = na.pass)
# 1) Série temporal: EAR observado vs previsto
newdata_m2 %>% 
   mutate(mes = floor_date(date, unit = "month")) %>% 

  group_by(,nom_subsistema.x) %>%summarise(ger_hat_cf =mean(ger_hat_cf   ,na.rm=T),
                             ger_hat=mean(ger_hat,na.rm=T)) %>%
  ggplot(aes(x = mes,)) +
  geom_line(aes(y = ger_hat_cf, color = "Previsto - Real"), size = 0.7,alpha=.6) +
  geom_line(aes(y = ger_hat, color = "Previsto - Contrafactual"), size = 1, linetype = "dashed") +facet_wrap(~nom_subsistema.x,scales = "free")+
  labs(title = "Geração Predito vs previsto (Contra-factual)",
       y = "EAR (MWmês)", x = "Data") +
  scale_color_manual(values = c("Previsto - Real" = "black", "Previsto - Contrafactual" = "red")) +
  theme_minimal()
newdata_m2 %>% 
   mutate(mes = floor_date(date, unit = "month")) %>% 

  group_by(mes,) %>%summarise(ger_hat_cf =mean(ger_hat_cf   ,na.rm=T),
                             ger_hat=mean(ger_hat,na.rm=T)) %>%
  ggplot(aes(x = mes,)) +
  geom_line(aes(y = ger_hat_cf, color = "Previsto - Real"), size = 0.7,alpha=.6) +
  geom_line(aes(y = ger_hat, color = "Previsto - Contrafactual"), size = 1, linetype = "dashed") +#facet_wrap(~nom_subsistema.x,scales = "free")+
  labs(title = "Geração Predito vs previsto (Contra-factual)",
       y = "EAR (MWmês)", x = "Data") +
  scale_color_manual(values = c("Previsto - Real" = "black", "Previsto - Contrafactual" = "red")) +
  theme_minimal()

A figura compara, por subsistema, a geração hidrelétrica prevista com clima observado e a geração contrafactual simulada ao substituir o armazenamento (EAR) pelo baseline climático (2001–2010).

  • Nordeste e Sudeste: a série com clima observado apresenta quedas acentuadas após 2012, enquanto o contrafactual se mantém em patamares menores e mais estáveis. A divergência crescente reflete a penalidade climática recente sobre a geração.

  • Norte: o contrafactual acompanha de perto a trajetória média; a série real mostra oscilações adicionais em anos específicos, sugerindo choques não reproduzidos pelo clima médio.

  • Sul: há forte variabilidade interanual nas duas curvas; mesmo assim, a série real tende a ficar abaixo do contrafactual em anos secos, evidenciando substituição por outras fontes nesses períodos.

Em conjunto, os resultados indicam que o clima recente reduziu a geração hídrica em relação ao que seria esperado sob um regime climático médio, com intensidade maior no Sudeste e Nordeste.

newdata_m2 %>% 
   mutate(mes = floor_date(date, unit = "month")) %>% 

  group_by(Year) %>%summarise(ena_mw7=sum(ger_hat,na.rm=T),
                             clim2026_hat=sum(ger_hat_cf,na.rm=T)) %>%
  ggplot(aes(x = Year,)) +
  geom_line(aes(y = ena_mw7/1000, color = "Previsto"), size = 0.7,alpha=.6) +
  geom_line(aes(y = clim2026_hat/1000, color = "Contrafactual 2010"), size = 1, linetype = "dashed") +#facet_wrap(~nom_subsistema.x,scales = "free")+
  labs(title = "Contrafactual baseline (clima médio 2001-2010)",
       y = "Geração (GWmês)", x = "Data") +
  scale_color_manual(values = c("Previsto" = "black", "Contrafactual 2010" = "blue")) +
  theme_minimal()
newdata_m2 %>% 
   mutate(mes = floor_date(date, unit = "month")) %>% 

  group_by(Year,nom_subsistema.x) %>%summarise(ena_mw7=sum(ger_hat,na.rm=T),
                             clim2026_hat=sum(ger_hat_cf,na.rm=T)) %>%
  ggplot(aes(x = Year,)) +
  geom_line(aes(y = ena_mw7/1000, color = "Previsto"), size = 0.7,alpha=.6) +
  geom_line(aes(y = clim2026_hat/1000, color = "Contrafactual 2010"), size = 1, linetype = "dashed") +facet_wrap(~nom_subsistema.x,scales = "free")+
  labs(title = "Contrafactual baseline (clima médio 2001-2010)",
       y = "Geração (GWmês)", x = "Data") +
  scale_color_manual(values = c("Previsto" = "black", "Contrafactual 2010" = "blue")) +
  theme_minimal()

A Figura 1 compara as trajetórias previstas de geração hidrelétrica sob duas condições:

  • Previsto – Real (linha preta): resultados do GAM com clima observado no período;

    Previsto – Contrafactual (linha vermelha tracejada): resultados do mesmo modelo, mas substituindo as variáveis climáticas pelas médias históricas (baseline 2001–2010).

newdata_m2 %>% 
   mutate(mes = floor_date(date, unit = "month")) %>% 

  group_by(Year,nom_subsistema.x) %>%summarise(ena_mw7=sum(ger_hat,na.rm=T),
                             clim2026_hat=sum(ger_hat_cf,na.rm=T)) %>%
  ggplot(aes(x = Year,)) +
  geom_line(aes(y = ena_mw7/1000, color = "Previsto"), size = 0.7,alpha=.6) +
  geom_line(aes(y = clim2026_hat/1000, color = "Contrafactual 2010 - baseline"), size = 1, linetype = "dashed") +facet_wrap(~nom_subsistema.x,scales = "free",ncol = 2)+
  labs(title = "Contrafactual climático por subsistema (baseline 2001–2010)",
       y = "Geração (GWmês)", x = "Data") +
  scale_color_manual(values = c("Previsto" = "black", "Contrafactual 2010 - baseline" = "blue")) +
  theme_minimal()
newdata_m2 %>% 
   mutate(mes = floor_date(date, unit = "month"),
          penalidade_geração_hidro=ger_hat-ger_hat_cf,
          #penalidade2=ena_mw7-clim2026_hat,
          )->newdata_m2
newdata_m2 %>% 
   mutate(mes = floor_date(date, unit = "month"),
          penalidade1=ger_hat-ger_hat_cf,
          #penalidade2=ena_mw7-clim2026_hat,
          ) %>% 

  group_by(Year) %>%summarise(ena_mw7=sum(penalidade1,na.rm=T),
                             #clim2026_hat=sum(penalidade2,na.rm=T)
                             ) %>%
  ggplot(aes(x = Year,)) +
  #geom_line(aes(y = ena_mw7, color = "previsto - Contrafactual"), size = 0.7,alpha=.6) +
  geom_line(aes(y = ena_mw7/1000, color = "Observado - Contrafactual 2026"), size = 1, linetype = "dashed") +#facet_wrap(~nom_subsistema.x,scales = "free")+
  labs(title = "Impacto líquido do clima recente sobre a Geração",subtitle = "Observado - Contrafactual 2026",
       y = "Penalidade Climática na Geração Hidroelética (MWmês)", x = "Data") +
    geom_ribbon(aes(ymin=ena_mw7/1000,ymax=0),alpha=.4,fill = "firebrick",)+

  scale_color_manual(values = c("Observado" = "black", "Contrafactual 2026" = "blue")) +
  theme_minimal()
newdata_m2 %>% 
   mutate(mes = floor_date(date, unit = "month"),
          penalidade1=ger_hat-ger_hat_cf,
          #penalidade2=ena_mw7-clim2026_hat,
          ) %>% 

  group_by(Year,nom_subsistema.x) %>%summarise(penalidade_geração_hidro=sum(penalidade_geração_hidro,na.rm=T),
                             #clim2026_hat=sum(penalidade2,na.rm=T)
                             ) %>%
  ggplot(aes(x = Year,)) +
  #geom_line(aes(y = ena_mw7, color = "previsto - Contrafactual"), size = 0.7,alpha=.6) +
  geom_line(aes(y = penalidade_geração_hidro/1000, color = "Observado - Contrafactual 2026"), size = 1, linetype = "dashed") +facet_wrap(~nom_subsistema.x,scales = "free")+
  labs(title = "Impacto líquido do clima recente sobre a Geração por subsistema",subtitle = "Observado - Contrafactual 2026",
       y = "Penalidade Climática na Geração Hidroelética (MWmês)", x = "Data") +
    geom_ribbon(aes(ymin=penalidade_geração_hidro/1000,ymax=0),alpha=.4,fill = "firebrick",)+

  scale_color_manual(values = c("Observado" = "black", "Contrafactual 2026" = "blue")) +
  theme_minimal()
newdata_m2 %>% 
   mutate(penalidade1=ger_hat-ger_hat_cf,
          penalidade_perc=ger_hat/ger_hat_cf,
          #penalidade2=ena_mw7-clim2026_hat,
          ) %>% 

  group_by(,nom_subsistema.x) %>%summarise(penalidade1=sum(penalidade1,na.rm=T),
                                          ger_hat=sum(ger_hat,na.rm=T),
                                          ger_hat_cf=sum(ger_hat_cf,na.rm=T),
                                          penalidade_perc=mean(penalidade_perc,na.rm=T)
                             #clim2026_hat=sum(penalidade2,na.rm=T)
                             ) %>% mutate(custo_financeiro_marginal=penalidade1*100)->penalidade_hidrico
penalidade_hidrico

A Tabela resume os resultados quantitativos. As colunas reportam a geração prevista real (ger_hat), o contrafactual (ger_hat_cf), a penalidade absoluta (MWmês) e a penalidade percentual média (%). Os valores indicam que:

  • O Sudeste registrou a maior penalidade absoluta (≈ –3,5 milhões de MWmês), com perda média de 4,4%.

  • O Nordeste perdeu ≈ –1 milhão de MWmês (–13,5%), confirmando vulnerabilidade estrutural.

  • O Sul apresentou penalidade menor em termos relativos (–9,2%), mas com alta variabilidade interanual.

  • O Norte foi o único subsistema a manter média contrafactual próxima à real, refletindo equilíbrio mais favorável entre clima e armazenamento.

newdata_m1$ger_hat_cf <- newdata_m2$ger_hat_cf 
newdata_m1$penalidade_geração_hidro <- newdata_m2$penalidade_geração_hidro 

Modelo de Propagação para outras fontes de energia

ger$nom_tipocombustivel %>% unique()
ger %>%mutate(usina_fonte=paste0("ger_",nom_tipousina)) %>% 
  filter(!nom_subsistema=="PARAGUAI") %>% #,"_",nom_tipousina)) %>% 
  mutate(usina_fonte=case_when(usina_fonte=="ger_BOMBEAMENTO"~"ger_HIDROELÉTRICA",
                   TRUE~usina_fonte)) %>% #,"_",nom_tipousina)) %>% 

  group_by(date,nom_subsistema,usina_fonte,val_geracao_day_subsistema) %>% 
  summarise(ger=sum(val_geracao,na.rm = T)) %>% ungroup() %>% 
  spread(usina_fonte,ger,fill = 0) %>% janitor::clean_names() %>% 
  mutate()->gera_energ_day
gera_energ_day$doy    <- lubridate::yday(gera_energ_day$date)
gera_energ_day$dow    <- lubridate::wday(gera_energ_day$date, label=TRUE, abbr=TRUE)
gera_energ_day$month  <- lubridate::month(gera_energ_day$date)
gera_energ_day$trend  <- lubridate::year(gera_energ_day$date)
ger %>%
  mutate(usina_fonte=paste0("ger_",nom_tipousina),
         mes = floor_date(date, unit = "month")) %>%# select(usina_fonte) %>% unique()
  mutate(usina_fonte=case_when(usina_fonte=="ger_BOMBEAMENTO"~"ger_HIDROELÉTRICA",
                   TRUE~usina_fonte)) %>% #,"_",nom_tipousina)) %>% 
  group_by(mes,usina_fonte,nom_subsistema) %>% #nom_subsistema
  summarise(ger=mean(val_geracao,na.rm = T)) %>% 
    ggplot(aes(x = mes,y=ger,col=nom_subsistema)) +
    geom_line() +facet_wrap(~usina_fonte,scales = "free",ncol = 2)+
  labs(title = "Impacto líquido do clima recente sobre a ENA por subsistema",subtitle = "Observado - Contrafactual 2026",
       y = "ger (GWmês)", x = "Data") +
  theme_minimal()
pld_full %>%
                 mutate(
                   ger_hidroeletrica = ifelse(ger_hidroeletrica == 0, 1, ger_hidroeletrica),
                   ger_fotovoltaica = ifelse(ger_fotovoltaica == 0, 1, ger_fotovoltaica),
                   ger_eolieletrica = ifelse(ger_eolieletrica == 0, 1, ger_eolieletrica),
                   ger_termica = ifelse(ger_termica == 0, 1, ger_termica),
                   Demanda = ger_eolieletrica+ger_fotovoltaica+ger_hidroeletrica+ger_termica+ger_nuclear,
                 ) %>% 
  ggplot(aes(date,))+
    geom_line(aes(y=Demanda),col="red")+
  geom_line(aes(y=val_geracao_day_subsistema,alpha = 0.1),col="black")+facet_wrap(~nom_subsistema.x,scales = "free_y")
gera_energ_day %>% str()
options(scipen = 8)
lm(ger_termica~
     ger_hidroeletrica+
     ger_eolieletrica+ger_fotovoltaica+ger_nuclear+    
     nom_subsistema.x+0+
     trend+as.factor(month),
   data =gera_energ_day) %>% summary()
lm(log(ger_termica)~
     log(ger_hidroeletrica)+
     ger_eolieletrica+ger_fotovoltaica+ger_nuclear+    
     nom_subsistema.x+0+
    trend+as.factor(month),
,
   data =gera_energ_day %>% 
     mutate(ger_hidroeletrica=case_when(ger_hidroeletrica<0.01~1,
                                             TRUE~ger_hidroeletrica),
            ger_termica=case_when(ger_termica<0.01~1,
                                             TRUE~ger_termica))
   ) %>% summary()
gera_energ_day$date %>% summary()
lm(ger_termica~
     ger_hidroeletrica+
     ger_eolieletrica+ger_fotovoltaica+ger_nuclear+    
     nom_subsistema.x+0+
     trend+as.factor(month),
,
   data =gera_energ_day %>% filter(date>2018-01-01 )) %>% summary()
lm(ger_termica~
     ger_hidroeletrica+
     ger_eolieletrica+ger_fotovoltaica+ger_nuclear +
     trend+as.factor(month)
     #nom_subsistema+0
     ,
   data =gera_energ_day) %>% summary()
lm(ger_termica~
     ger_hidroeletrica*nom_subsistema.x+
     ger_eolieletrica+ger_fotovoltaica+ger_nuclear +
     trend+as.factor(month),
     #nom_subsistema+0,
   data =gera_energ_day) %>% summary()

library(mgcv)
    # ger_eolieletrica+ger_fotovoltaica+ger_nuclear +
    # trend+as.factor(month)
m_gam_fontes <- bam(ger_termica  ~ s(ger_hidroeletrica, k=3) + s(ger_eolieletrica, k=4) +
                      s(ger_fotovoltaica, k=3)   +             + s(ger_nuclear, k=3) +
                      s(trend, k=3) + s(month, k=4) +
                      #s(Demanda, k=4)+
                      s(nom_subsistema.x, bs = "re"),
             data = gera_energ_day %>% 
               mutate(Demanda = ger_eolieletrica+ger_fotovoltaica+ger_hidroeletrica+ger_termica+ger_nuclear,
))
summary(m_gam_fontes)
gam.check(m_gam_fontes)                   # checa resíduos, QQ-plot, k-adequação
concurvity(m_gam_fontes, full=TRUE)       # multicolinearidade não linear
plot(m_gam_fontes, pages=4, scheme=1, shade=TRUE, se=TRUE,scales = "free")

Contrafactual Outras fontes de energia

#newdata_m1$ear_hat_cf<-clim_in$clim2026_hat

newdata_m1 %>% 
  group_by(nom_subsistema.x,date) %>% 
  summarise(ear=sum(ear_reservatorio_subsistema_proprio_mwmes,na.rm = T),
            val_geracao=sum(val_geracao),
            ear_hat=sum(ear_hat,na.rm = T),
            ger_hat=sum(ger_hat,na.rm = T),
            penalidade_geração_hidro=sum(penalidade_geração_hidro,na.rm = T),
            ger_hat_cf=sum(ger_hat_cf,na.rm = T),
            ear_hat_cf=sum(ear_hat_cf,na.rm = T)) %>% 
  right_join(gera_energ_day,by = c("nom_subsistema.x"="nom_subsistema","date"="date"))->gera_energ_day
gera_energ_day
gera_energ_day %>% 
  group_by(trend) %>% summarise(val_geracao=sum(ger_hat,na.rm = T),
                                ger_hidroeletrica=sum(ger_hidroeletrica,na.rm = T)) %>% 
  ggplot(aes(trend))+
  geom_line(aes(y=val_geracao),col="blue")+
  geom_line(aes(y=ger_hidroeletrica),col="red")+theme_minimal()
predict(m_gam_fontes,newdata = ger %>% 
  mutate(val_geracao=ger_hat) )
gera_energ_day$ger_termica_prevista<-predict(m_gam_fontes,
                                             newdata = gera_energ_day %>%
                                               mutate(
                                                         nom_subsistema=nom_subsistema.x,
                                                      Demanda = ger_eolieletrica+ger_fotovoltaica+ger_hidroeletrica+ger_termica+ger_nuclear)
                                             )
gera_energ_day$ger_termica_prevista_cf<-predict(m_gam_fontes,
                                                newdata = gera_energ_day %>% 
                                                  mutate(ger_hidroeletrica=ger_hidroeletrica+penalidade_geração_hidro,
                                                         nom_subsistema=nom_subsistema.x,
                                                         Demanda = ger_eolieletrica+ger_fotovoltaica+ger_hidroeletrica+ger_termica+ger_nuclear)
                                                )
gera_energ_day %>% 
   mutate(mes = floor_date(date, unit = "month")) %>% 

  group_by(trend) %>%summarise(ger_termica_prevista=sum(ger_termica_prevista,na.rm=T),
                             ger_termica_prevista_cf=sum(ger_termica_prevista_cf,na.rm=T)) %>%
  ggplot(aes(x = trend,)) +
  geom_line(aes(y = ger_termica_prevista/1000, color = "Previsto"), size = 0.7,alpha=.6) +
  geom_line(aes(y = ger_termica_prevista_cf/1000, color = "Contrafactual 2010"), size = 1, linetype = "dashed") +#facet_wrap(~nom_subsistema.x,scales = "free")+
  geom_ribbon(aes(ymin=ger_termica_prevista/1000,ymax=ger_termica_prevista_cf/1000),alpha=.4,fill = "firebrick",)+

  labs(title = "Contrafactual baseline (clima médio 2001-2010)",
       y = "Geração Termica (GWmês)", x = "Data") +
  scale_color_manual(values = c("Previsto" = "black", "Contrafactual 2010" = "blue")) +
  theme_minimal()


gera_energ_day %>% 
   mutate(mes = floor_date(date, unit = "month")) %>% 

  group_by(trend,nom_subsistema.x) %>%summarise(ena_mw7=sum(ger_termica_prevista,na.rm=T),
                             clim2026_hat=sum(ger_termica_prevista_cf,na.rm=T)) %>%
  ggplot(aes(x = trend,)) +
  geom_line(aes(y = ena_mw7/1000, color = "Previsto"), size = 0.7,alpha=.6) +
  geom_line(aes(y = clim2026_hat/1000, color = "Contrafactual 2010"), size = 1, linetype = "dashed") +facet_wrap(~nom_subsistema.x,scales = "free")+
  labs(title = "Contrafactual baseline (clima médio 2001-2010)",
       y = "Geração Termica (GWmês)", x = "Data") +
  scale_color_manual(values = c("Previsto" = "black", "Contrafactual 2010" = "blue")) +
  theme_minimal()
gera_energ_day %>% 
   mutate(mes = floor_date(date, unit = "month"),
          penalidade_termico=ger_termica_prevista_cf-ger_termica_prevista,
          #penalidade2=ena_mw7-clim2026_hat,
          )->gera_energ_day
gera_energ_day %>% 
   mutate(mes = floor_date(date, unit = "month"),
          penalidade1=ger_termica_prevista_cf-ger_termica_prevista,
          #penalidade2=ena_mw7-clim2026_hat,
          ) %>% 

  group_by(trend) %>%summarise(ena_mw7=sum(penalidade1,na.rm=T),
                             #clim2026_hat=sum(penalidade2,na.rm=T)
                             ) %>%
  ggplot(aes(x = trend,)) +
  #geom_line(aes(y = ena_mw7, color = "previsto - Contrafactual"), size = 0.7,alpha=.6) +
  geom_line(aes(y = ena_mw7/1000, color = "Observado - Contrafactual 2026"), size = 1, linetype = "dashed") +#facet_wrap(~nom_subsistema.x,scales = "free")+
  labs(title = "Impacto líquido do clima recente sobre a Geração",subtitle = "Observado - Contrafactual 2026",
       y = "Penalidade Climática na Termica (MWmês)", x = "Data") +
    geom_ribbon(aes(ymin=ena_mw7/1000,ymax=0),alpha=.4,fill = "firebrick",)+

  scale_color_manual(values = c("Observado" = "black", "Contrafactual 2026" = "blue")) +
  theme_minimal()

gera_energ_day %>% 
   mutate(mes = floor_date(date, unit = "month"),
          penalidade_termica=ger_termica_prevista_cf-ger_termica_prevista,
          #penalidade2=ena_mw7-clim2026_hat,
          ) %>% 

  group_by(trend,nom_subsistema.x) %>%summarise(penalidade_termica=sum(penalidade_termica,na.rm=T),
                             #clim2026_hat=sum(penalidade2,na.rm=T)
                             ) %>%
  ggplot(aes(x = trend,)) +
  #geom_line(aes(y = ena_mw7, color = "previsto - Contrafactual"), size = 0.7,alpha=.6) +
  geom_line(aes(y = penalidade_termica/1000, color = "Observado - Contrafactual 2026"), size = 1, linetype = "dashed") +facet_wrap(~nom_subsistema.x,scales = "free")+
  labs(title = "Impacto líquido do clima recente sobre a Geração",subtitle = "Observado - Contrafactual 2026",
       y = "Penalidade Climática na Termica (MWmês)", x = "Data") +
    geom_ribbon(aes(ymin=penalidade_termica/1000,ymax=0),alpha=.4,fill = "firebrick",)+

  scale_color_manual(values = c("Observado" = "black", "Contrafactual 2026" = "blue")) +
  theme_minimal()

am maior volatilidade. Essa decomposição regional é crucial para avaliar a elasticidade da escassez e o redirecionamento da pressão para outras fontes de geração.

gera_energ_day %>% 
   mutate(penalidade1=ger_termica_prevista_cf-ger_termica_prevista,
          penalidade_perc=ger_termica_prevista_cf/ger_termica_prevista,
          #penalidade2=ena_mw7-clim2026_hat,
          ) %>% 

  group_by(,nom_subsistema.x) %>%summarise(penalidade1=sum(penalidade1,na.rm=T),
                                          ger_hat=sum(ger_hat,na.rm=T),
                                          ger_hat_cf=sum(ger_hat_cf,na.rm=T),
                                          penalidade_perc=mean(penalidade_perc,na.rm=T)
                             #clim2026_hat=sum(penalidade2,na.rm=T)
                             ) %>% mutate(custo_financeiro_usotermico=penalidade1*300)->penalidade_termico
bind_rows(penalidade_hidrico %>% mutate(estima="Hidro"),penalidade_termico %>% mutate(estima="Térmico")) %>% 
  select(-starts_with("custo")) %>% 
  mutate(custo_Reais=case_when(estima=="Hidro"~penalidade1*-100,
                             TRUE~penalidade1*300),
         custo_USD=custo_Reais/5.2
         ) 
bind_rows(penalidade_hidrico %>% mutate(estima="Hidro"),penalidade_termico %>% mutate(estima="Térmico")) %>% 
  select(-starts_with("custo")) %>% 
  mutate(custo_Reais=case_when(estima=="Hidro"~penalidade1*-100,
                             TRUE~penalidade1*300),
         custo_USD=custo_Reais/5.2
         ) %>% 
  ggplot(aes(x=nom_subsistema.x,y=custo_USD/1000000,fill=estima))+geom_col(position = "dodge")+
  geom_text(aes(y=custo_USD/1000000+2,label = round(custo_USD/1000, 1)), position=position_dodge(width=1), size = 3,check_overlap=F)+coord_flip()+
  labs(title = "Custo econômico estimado da penalidade climática (2010-2023)",
       subtitle = "Custo financeiro aproximado do impacto climático sobre a geração hidrelétrica e térmica",
       y = "Custo (US$ mil)", x = "Subsistema") +theme_minimal()

PLD: Custo para o sistema

pld     <- read.csv("preco_semanal.csv")           # PLD semanal
pld$date <- as.Date(pld$datas)   # idem para a base de PLD
pld$week  <- lubridate::isoweek(pld$datas)
pld$year  <- lubridate::year(pld$datas)

#pld$date<-pld$DATA_INICIO %>% as_date() 
pld %>% spread(Submercado,preco)->pld
pld$date %>% min()->inicio
pld %>% filter(DATA_INICIO==inicio)
datas<-gera_energ_day$date %>% unique
data.frame(datas) %>% filter(datas>inicio-1) %>% arrange(datas) %>% left_join(pld,by = c("datas"="date"))->daas_completas
daas_completas
i=2
for (i in 1:length(daas_completas$ANO)) {#length(daas_completas$ANO)
  print(i)
  if (is.na(daas_completas$ANO[i])) {
    daas_completas$ANO[i]<-daas_completas$ANO[i-1]
    daas_completas$MES[i]<-daas_completas$MES[i-1]
    daas_completas$SEMANA[i]<-daas_completas$SEMANA[i-1]
    daas_completas$DATA_FIM[i]<-daas_completas$DATA_FIM[i-1]
    daas_completas$SUDESTE[i]<-daas_completas$SUDESTE[i-1]
    daas_completas$SUL[i]<-daas_completas$SUL[i-1]
    daas_completas$NORDESTE[i]<-daas_completas$NORDESTE[i-1]
    daas_completas$NORTE[i]<-daas_completas$NORTE[i-1]

    
  }
  
}  
daas_completas %>% gather(key = "nom_subsitema",value = "preco",c("NORDESTE","SUDESTE","SUL","NORTE"))->pld
serie <- daas_completas %>%
  pull(NORDESTE) %>%
  ts(start =  c(2001, 181), frequency = 365)
stl(serie,s.window = "periodic") %>% plot

serie <- daas_completas %>%
  pull(SUL) %>%
  ts(start =  c(2001, 181), frequency = 365)
stl(serie,s.window = "periodic") %>% plot

serie <- daas_completas %>%
  pull(SUDESTE) %>%
  ts(start =  c(2001, 181), frequency = 365)
stl(serie,s.window = "periodic") %>% plot

serie <- daas_completas %>%
  pull(NORTE) %>%
  ts(start =  c(2001, 181), frequency = 365)
stl(serie,s.window = "periodic") %>% plot
pld$Submercado %>% unique()
gera_energ_day$nom_subsistema.x %>% unique

#newdata_m1 %>% write.csv("base valores previstos.csv")
#gera_energ_day %>% write.csv("valores_previstos_day.csv")
gera_energ_day %>% inner_join(pld,by=c("date","nom_subsistema.x"="nom_subsitema"))->pld_full
pld_full %>% summary()
pld_full %>% group_by(date) %>% summarise(preco=mean(preco,na.rm = T)) %>% 
  ggplot(aes(date,preco))+geom_line()
pld_full %>% 
  group_by(trend) %>% summarise(preco=mean(preco,na.rm = T)) %>% 
  ggplot(aes(trend,preco))+geom_line()
pld_full %>% 
  group_by(month) %>% summarise(preco=mean(preco,na.rm = T)) %>% 
  ggplot(aes(month,preco))+geom_line()
pld_full %>% 
  mutate(mes = floor_date(date, unit = "month")) %>% 

  group_by(mes) %>% summarise(preco=mean(preco,na.rm = T)) %>% 
  ggplot(aes(mes,preco))+geom_line()
pld_full %>% 
  ggplot(aes(date,preco,nom_subsistema.x))+geom_line()+facet_wrap(~nom_subsistema.x)

pld_full %>% 
  group_by(trend,nom_subsistema.x) %>% summarise(preco=mean(preco,na.rm = T)) %>% 
  ggplot(aes(trend,preco))+geom_line()+facet_wrap(~nom_subsistema.x)
pld_full %>% 
  group_by(month,nom_subsistema.x) %>% summarise(preco=mean(preco,na.rm = T)) %>% 
  ggplot(aes(month,preco))+geom_line()+facet_wrap(~nom_subsistema.x)
pld_full %>% 
  mutate(mes = floor_date(date, unit = "month")) %>% 

  group_by(mes,nom_subsistema.x) %>% summarise(preco=mean(preco,na.rm = T)) %>% 
  ggplot(aes(mes,preco))+geom_line()+facet_wrap(~nom_subsistema.x)

modelos ingenuos

pld_full %>% str()
lm(log(preco)~log(ger_hidroeletrica)+log(ger_eolieletrica)+log(ger_fotovoltaica)+log(ger_termica)+
     log(Demanda)+nom_subsistema.x,
   data=pld_full %>%
     mutate(ger_hidroeletrica=ifelse(ger_hidroeletrica==0,1,ger_hidroeletrica),
            ger_fotovoltaica=ifelse(ger_fotovoltaica==0,1,ger_fotovoltaica),
            ger_eolieletrica=ifelse(ger_eolieletrica==0,1,ger_eolieletrica),
            ger_termica=ifelse(ger_termica==0,1,ger_termica),
            #Demanda=ifelse(val_geracao_day_subsistema==0,1,val_geracao_day_subsistema),
            Demanda = ger_eolieletrica+ger_fotovoltaica+ger_hidroeletrica+ger_termica+ger_nuclear,

            )) %>% summary()
pld_full$ger_hidroeletrica %>% summary()
  • Aumento de 1% na geração hídrica reduz o preço em 1,7%.

  • +1% em eólica → +0,21% no preço.

  • Aumento de 1% na solar reduz preço em 0,40%.

  • Elasticidade forte: +1% na demanda → +1,95% no preço.

  • R² = 0.346 (~35%)

    GAM Preço PLD

gam_mod <- gam(preco ~ #trend+
                 s(log(ger_hidroeletrica)) + 
                 s(log(trend)) +                
                 s(log(doy))+
                 s(log(ger_eolieletrica)) + 
                 s(log(ger_fotovoltaica)) + 
                 s(log(Demanda)) + 
                 s(log(ger_termica))+
                 #s(nom_subsistema.x, bs = "re"),# efeito aleatório por reservatório
                 nom_subsistema.x,
               data = pld_full %>%
                 mutate(
                   ger_hidroeletrica = ifelse(ger_hidroeletrica == 0, 1, ger_hidroeletrica),
                   ger_fotovoltaica = ifelse(ger_fotovoltaica == 0, 1, ger_fotovoltaica),
                   ger_eolieletrica = ifelse(ger_eolieletrica == 0, 1, ger_eolieletrica),
                   ger_termica = ifelse(ger_termica == 0, 1, ger_termica),
                   #Demanda = ifelse(val_geracao_day_subsistema == 0, 1, val_geracao_day_subsistema)
                   Demanda = ger_eolieletrica+ger_fotovoltaica+ger_hidroeletrica+ger_termica+ger_nuclear,
                 ))
summary(gam_mod)
plot(gam_mod, pages = 3, shade = TRUE)
  • R² ajustado = 0.50 → o GAM explicou metade da variância dos preços, contra ~0.35 do modelo linear anterior.

    • Deviance explained = 50% → muito mais aderência.
  • Hidrelétrica (s(log(ger_hidro)))

    • O efeito é forte até certo ponto e depois satura
  • Eólica

    • Linha relativamente plana, levemente negativa em valores altos.

    • Mostra que a eólica tem efeito fraco ou até neutro em faixas normais de operação, mas pode ajudar a baixar preços em condições extremas.

  • Solar

    • Efeito praticamente linear e negativo, mas fraco (edf ≈ 1 → quase linear)
  • Demanda

-   Claramente crescente, e mais íngreme em valores altos. Isso mostra que o preço responde de forma não linear:

    -   em demandas baixas/médias, efeito suave,

-   em demandas muito altas, preço dispara

-   Exatamente o comportamento esperado em sistemas com despacho por ordem de mérito.

Previsto PLD


#pld_full$prec_previsto<-predict(gam_mod,)

predict(gam_mod,newdata=pld_full %>%
                 mutate(
                   ger_hidroeletrica = ifelse(ger_hidroeletrica == 0, 1, ger_hidroeletrica),
                   ger_fotovoltaica = ifelse(ger_fotovoltaica == 0, 1, ger_fotovoltaica),
                   ger_eolieletrica = ifelse(ger_eolieletrica == 0, 1, ger_eolieletrica),
                                      ger_termica = ifelse(ger_termica == 0, 1, ger_termica),
                   Demanda = ger_eolieletrica+ger_fotovoltaica+ger_hidroeletrica+ger_termica+ger_nuclear,

                   #Demanda = ifelse(val_geracao_day_subsistema == 0, 1, val_geracao_day_subsistema)
                 ),type="response") -> pld_full$prec_previsto
pld_full %>% 

  mutate(mes = floor_date(date, unit = "month")) %>% 
  group_by(mes,nom_subsistema.x) %>% summarise(prec_previsto=mean(prec_previsto,na.rm = T),
                               preco=mean(preco,na.rm = T),
                               ) %>% 
  ggplot(aes(mes,prec_previsto))+
  geom_line(size = 1, linetype = "dashed",col="red") +
  geom_line(aes(y=preco),col = "black")+
  labs(y="$",x="Year")+theme_minimal()+
  facet_wrap(~nom_subsistema.x,scales = "free")

pld_full %>% 
  mutate(mes = floor_date(date, unit = "month")) %>% 
  group_by(mes,nom_subsistema.x) %>%summarise(preco=mean(preco,na.rm=T),
                                              prec_previsto=mean(prec_previsto,na.rm=T)) %>%
  ggplot( aes(x = mes,)) +
  #geom_point(aes(color=resid_col))+
  facet_wrap(~nom_subsistema.x,scales = "free")+
  geom_line(aes(y = prec_previsto),col="red") +  #geom_line(aes(y=exp(prec_previsto))) +
  geom_ribbon(aes(ymin=prec_previsto,ymax=preco),alpha=.4,fill = "firebrick",)+
  labs(title = "Resíduos do modelo (observado - previsto)",
       y = "Resíduo", x = "Data") +

  theme_minimal()
pld_full %>% 
  mutate(mes = floor_date(date, unit = "month")) %>% 
  group_by(mes,nom_subsistema.x) %>% summarise(prec_previsto=mean(prec_previsto,na.rm = T),
                               preco=mean(preco,na.rm = T),
                               ) %>% 
  ggplot(aes(mes,prec_previsto))+
  geom_line(size = 1, linetype = "dashed",col="red") +
  geom_line(aes(y=preco),col = "black")+
  labs(y="$",x="Year")+theme_minimal()+
  facet_wrap(~nom_subsistema.x,scales = "free")
pld_full %>% 
  mutate(mes = floor_date(date, unit = "month")) %>% 
  group_by(mes,nom_subsistema.x) %>%summarise(preco=mean(preco,na.rm=T),
                                              prec_previsto=mean(prec_previsto,na.rm=T)) %>%
  ggplot( aes(x = mes,)) +
  #geom_point(aes(color=resid_col))+
  facet_wrap(~nom_subsistema.x,scales = "free")+
  geom_line(aes(y = prec_previsto),col="red") +  geom_line(aes(y=prec_previsto)) +
  geom_ribbon(aes(ymin=prec_previsto,ymax=preco),alpha=.4,fill = "firebrick",)+
  labs(title = "Resíduos do modelo (observado - previsto)",
       y = "Resíduo", x = "Data") +
  theme_minimal()

Contrafactual PLD

gera_energ_day$ger_termica_prevista<-predict(m_gam_fontes,
                                             newdata = gera_energ_day %>%
                                               mutate(
                                                         nom_subsistema=nom_subsistema.x,
                                                      Demanda = ger_eolieletrica+ger_fotovoltaica+ger_hidroeletrica+ger_termica+ger_nuclear)
                                             )
gera_energ_day$ger_termica_prevista_cf<-predict(m_gam_fontes,
                                                newdata = gera_energ_day %>% 
                                                  mutate(ger_hidroeletrica=ger_hidroeletrica+penalidade_geração_hidro,
                                                         nom_subsistema=nom_subsistema.x,
                                                         #ger_termica=ger_termica-penalidade_termico,
                                                         Demanda = ger_eolieletrica+ger_fotovoltaica+ger_hidroeletrica+ger_termica+ger_nuclear)
                                                )

predict(gam_mod,newdata=pld_full %>%
                 mutate(
                  Demanda = ger_eolieletrica+ger_fotovoltaica+ger_hidroeletrica+ger_termica+ger_nuclear,
                   ger_hidroeletrica = ifelse(is.na(ger_hidroeletrica+penalidade_geração_hidro),
                                              1,
                                              ger_hidroeletrica+penalidade_geração_hidro),
                   ger_hidroeletrica = ifelse(ger_hidroeletrica<1 , 1, ger_hidroeletrica),
                   ger_fotovoltaica = ifelse(ger_fotovoltaica == 0, 1, ger_fotovoltaica),
                   ger_eolieletrica = ifelse(ger_eolieletrica == 0, 1, ger_eolieletrica),
                  ger_termica = ifelse(ger_termica+penalidade_termico< 0.1, 1, ger_termica+penalidade_termico),

                 ),type="response") -> pld_full$prec_previsto_cf

pld_full %>% ungroup() %>% 
  #mutate(penalidade_termico)
  select(prec_previsto,prec_previsto_cf,preco,ger_termica,penalidade_termico,penalidade_geração_hidro) %>% summary()

                 


pld_full %>% 
  mutate(mes = floor_date(date, unit = "month")) %>% 
  group_by(mes,nom_subsistema.x) %>% summarise(prec_previsto=mean(prec_previsto,na.rm = T),
                               preco=mean(preco,na.rm = T),
                               prec_previsto_cf=mean(prec_previsto_cf,na.rm = T),
                               ) %>% 
  ggplot(aes(mes,(prec_previsto)))+
  geom_line(size = 1, linetype = "dashed",col="red") +
  #geom_line(aes(y=preco),col = "black")+
    geom_line(aes(y=(prec_previsto_cf)),col = "blue")+

  labs(y="$",x="Year")+theme_minimal()+
  facet_wrap(~nom_subsistema.x,scales = "free")
pld_full %>% 
  mutate(mes = floor_date(date, unit = "month")) %>% 
  group_by(mes,nom_subsistema.x) %>%summarise(prec_previsto_cf=mean(prec_previsto_cf,na.rm=T),
                                              prec_previsto=mean(prec_previsto,na.rm=T)) %>%
  ggplot( aes(x = mes,)) +
  #geom_point(aes(color=resid_col))+
  facet_wrap(~nom_subsistema.x,scales = "free")+
  #geom_line(aes(y = exp(prec_previsto_cf)),col="red") + 
  geom_line(aes(y=(prec_previsto_cf)-(prec_previsto))) +
  geom_ribbon(aes(ymin=0,ymax=(prec_previsto_cf)-(prec_previsto)),alpha=.4,fill = "firebrick",)+
  labs(title = "Penalidade (Contrafactual- Predito)",
       y = "Penalidade Climática no Preço", x = "Data") +
  theme_minimal()
pld_full %>% 
  mutate(mes = floor_date(date, unit = "month")) %>% 
  group_by(year,nom_subsistema.x) %>%summarise(prec_previsto_cf=mean(prec_previsto_cf,na.rm=T),
                                              prec_previsto=mean(prec_previsto,na.rm=T)) %>%
  ggplot( aes(x = year,)) +
  #geom_point(aes(color=resid_col))+
  facet_wrap(~nom_subsistema.x,scales = "free")+
  #geom_line(aes(y = exp(prec_previsto_cf)),col="red") + 
  geom_line(aes(y=(prec_previsto_cf)-(prec_previsto))) +
  geom_ribbon(aes(ymin=0,ymax=(prec_previsto_cf)-(prec_previsto)),alpha=.4,fill = "firebrick",)+
  labs(title = "Penalidade (Contrafactual- Predito)",
       y = "Penalidade Climática no Preço", x = "Data") +
  theme_minimal()
pld_full %>% 
   mutate(penalidade1=prec_previsto_cf-prec_previsto,
          penalidade_perc=prec_previsto_cf/prec_previsto,
          #penalidade2=ena_mw7-clim2026_hat,
          ) %>% 

  group_by(nom_subsistema.x) %>%summarise(penalidade1=sum(penalidade1,na.rm=T),
                                          prec_previsto=sum(prec_previsto,na.rm=T),
                                          prec_previsto_cf=sum(prec_previsto_cf*1000,na.rm=T),
                                          prec=mean(preco,na.rm = T),
                                          penalidade_perc=mean(penalidade_perc,na.rm=T)
                             #clim2026_hat=sum(penalidade2,na.rm=T)
                             ) %>% mutate(custo_financeiro_pld=penalidade1)->penalidade_pld
penalidade_pld

ddsad

dsa


bind_rows(penalidade_hidrico %>% mutate(estima="Hidro*"),

          penalidade_termico %>% mutate(estima="Térmico**"),
          penalidade_pld %>% mutate(estima="Operacional***")) %>% 
  select(-starts_with("custo")) %>% 
  mutate(custo_Reais=case_when(estima=="Hidro*"~(-penalidade1)*(296.8),
                               estima=="Térmico**"~penalidade1* 478.9,
                             TRUE~penalidade1*10000/7),
         custo_USD=custo_Reais/5.2
         ) %>% 
  ggplot(aes(x=nom_subsistema.x,y=(custo_USD/100000),fill=estima))+geom_col(position = "dodge")+
  geom_text(aes(label = round(custo_USD/100000, 2)), position=position_dodge(width=1), size = 3,check_overlap=F)+coord_flip()+
  labs(title = "Custo econômico estimado da penalidade climática (2001-2019)",
       subtitle = "Custo financeiro aproximado do impacto climático sobre a geração hidrelétrica e térmica",
       caption = "*296,8 R$/MWh
**478,9 R$/MWh
*** Estimado em 10 GWh por semana",
       y = "Custo (US$ milhões)", x = "Subsistema") +theme_minimal()
bind_rows(penalidade_hidrico %>% mutate(estima="Hidro*"),

          penalidade_termico %>% mutate(estima="Térmico**"),
          penalidade_pld %>% mutate(estima="Operacional***")) %>% 
  select(-starts_with("custo")) %>% 
  mutate(custo_Reais=case_when(estima=="Hidro*"~(-penalidade1)*(296.8),
                               estima=="Térmico**"~penalidade1* 478.9,
                             TRUE~penalidade1*10000/7),
         custo_USD=custo_Reais/5.2
         ) %>% 
  group_by(estima) %>% summarise(custo_USD=sum(custo_USD)) %>% 
  ggplot(aes(x=estima,y=(custo_USD/100000),fill=estima))+geom_col(position = "dodge")+
  geom_text(aes(y=custo_USD/200000,label = round(custo_USD/100000, 1)), position=position_dodge(width=1), size = 3,check_overlap=F)+coord_flip()+
  labs(title = "Custo econômico estimado da penalidade climática (2000-2019)",
       subtitle = "Custo financeiro aproximado do impacto climático sobre a geração hidrelétrica e térmica",
       caption = "*296,8 R$/MWh
**478,9 R$/MWh
*** Estimado em 10 GWh por semana",
       y = "Custo (US$ Milhoes)", x = "Subsistema") +theme_minimal()
LS0tDQp0aXRsZTogIkNsaW1hdGUgUGVuYWx0aWVzIGFuZCBTY2FyY2l0eSBQcmVzc3VyZSBpbiBCcmF6aWzigJlzIFBvd2VyIFNlY3RvciINCmF1dGhvcjogIlRoaWFnbyBHYXJkaW4gJiBEYW5pZWwgRGFubmEiDQpkYXRlOiAiMjAyNS0xMC0wNiAiDQpvdXRwdXQ6DQogIGh0bWxfbm90ZWJvb2s6IA0KICAgIHRvYzogdHJ1ZQ0KICAgIHRvY19kZXB0aDogMg0KICAgIHRoZW1lOiBqb3VybmFsDQplZGl0b3Jfb3B0aW9uczoNCiAgY2h1bmtfb3V0cHV0X3R5cGU6IGlubGluZQ0KLS0tDQoNCiMgUGFjb3Rlcw0KDQpgYGB7ciBDYXJyZWdhciBwYWNvdGVzLWJhc2UgZG8gcHJvamV0bzsgZGVmaW5pciBvcMOnw7VlcyBnbG9iYWlzfQ0KIyBDYXJyZWdhciBwYWNvdGVzLWJhc2UgZG8gcHJvamV0bw0KIyBNYW5pcHVsYcOnw6NvIGUgZGF0YXMNCmxpYnJhcnkodGlkeXZlcnNlKTtsaWJyYXJ5KGRhdGEudGFibGUpO2xpYnJhcnkobHVicmlkYXRlKTtsaWJyYXJ5KHBhdGNod29yayk7bGlicmFyeShIbWlzYykNCg0KIyBNb2RlbGFnZW0NCmxpYnJhcnkobWdjdik7bGlicmFyeShncmF0aWEpO2xpYnJhcnkobHVicmlkYXRlKTtsaWJyYXJ5KG1vZGVsc3VtbWFyeSk7bGlicmFyeShndCk7bGlicmFyeShnbHVlKTtsaWJyYXJ5KHNjYWxlcyk7bGlicmFyeShicm9vbSk7bGlicmFyeShicm9vbS5oZWxwZXJzKTtsaWJyYXJ5KGdlb2JyKQ0KIyBVdGlsaWRhZGVzDQpsaWJyYXJ5KHNjYWxlcyk7bGlicmFyeShwYXRjaHdvcmspO2xpYnJhcnkoa25pdHIpO2xpYnJhcnkoa2FibGVFeHRyYSkNCg0KIyBEZWZpbmlyIG9ww6fDtWVzIGdsb2JhaXMgZGUga25pdHINCmtuaXRyOjpvcHRzX2NodW5rJHNldCgNCiAgZWNobyAgICAgICA9IFRSVUUsDQogIG1lc3NhZ2UgICAgPSBUUlVFLA0KICB3YXJuaW5nICAgID0gVFJVRSwNCiAgZHBpICAgICAgICA9IDEyMCwNCiAgZmlnLmFsaWduICA9ICJjZW50ZXIiLA0KICBmaWcud2lkdGggID0gMTIsDQogIGZpZy5oZWlnaHQgPSA4DQopDQoNCiMgVGVtYSB2aXN1YWwgcGFkcsOjbyANCnRoZW1lX2FydGljbGUgPC0gZnVuY3Rpb24oKXsNCiAgdGhlbWVfbWluaW1hbChiYXNlX3NpemUgPSAxMSkgKw0KICAgIHRoZW1lKA0KICAgICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChmYWNlPSJib2xkIiksDQogICAgICBwbG90LnN1YnRpdGxlID0gZWxlbWVudF90ZXh0KG1hcmdpbj1tYXJnaW4oYj02KSksDQogICAgICBwbG90LmNhcHRpb24gID0gZWxlbWVudF90ZXh0KHNpemU9OSwgY29sb3I9ImdyZXkzMCIpLA0KICAgICAgYXhpcy50aXRsZSA9IGVsZW1lbnRfdGV4dCgpLA0KICAgICAgcGFuZWwuZ3JpZC5taW5vciA9IGVsZW1lbnRfYmxhbmsoKSwNCiAgICAgIGxlZ2VuZC5wb3NpdGlvbiA9ICJ0b3AiDQogICAgKQ0KfQ0KdGhlbWVfc2V0KHRoZW1lX2FydGljbGUoKSkNCnNldC5zZWVkKDEyMzQpDQpgYGANCg0KYGBge3IgaGVscGVyc30NCnByZWRpY3RfZ2FtX2NpIDwtIGZ1bmN0aW9uKG1vZGVsLCBuZXdkYXRhLCB0eXBlID0gImxpbmsiLCBsZXZlbCA9IDAuOTUpew0KICBzdG9waWZub3QoaW5oZXJpdHMobW9kZWwsICJnYW0iKSkNCiAgcHIgPC0gcHJlZGljdChtb2RlbCwgbmV3ZGF0YSA9IG5ld2RhdGEsIHR5cGUgPSB0eXBlLCBzZS5maXQgPSBUUlVFKQ0KICBhbHBoYSA8LSAxIC0gbGV2ZWwNCiAgY3JpdCAgPC0gcW5vcm0oMSAtIGFscGhhLzIpDQogIHRpYmJsZSgNCiAgICAuZml0dGVkID0gYXMubnVtZXJpYyhwciRmaXQpLA0KICAgIC5zZSAgICAgPSBhcy5udW1lcmljKHByJHNlLmZpdCksDQogICAgLmxvd2VyICA9IC5maXR0ZWQgLSBjcml0Ki5zZSwNCiAgICAudXBwZXIgID0gLmZpdHRlZCArIGNyaXQqLnNlDQogICkNCn0NCmV4cG9ydF9maWd1cmUgPC0gZnVuY3Rpb24ocCwgZmlsZW5hbWUsIHdpZHRoID0gNywgaGVpZ2h0ID0gNC4yKXsNCiAgZ2dzYXZlKGdsdWUoImZpZ3VyZXMve2ZpbGVuYW1lfS5wZGYiKSwgcGxvdCA9IHAsIHdpZHRoID0gd2lkdGgsIGhlaWdodCA9IGhlaWdodCwgZHBpID0gMzAwLCBkZXZpY2UgPSBjYWlyb19wZGYpDQogIGdnc2F2ZShnbHVlKCJmaWd1cmVzL3tmaWxlbmFtZX0uZXBzIiksIHBsb3QgPSBwLCB3aWR0aCA9IHdpZHRoLCBoZWlnaHQgPSBoZWlnaHQsIGRwaSA9IDMwMCwgZGV2aWNlID0gImVwcyIpDQogIGdnc2F2ZShnbHVlKCJmaWd1cmVzL3tmaWxlbmFtZX0udGlmZiIpLHBsb3QgPSBwLCB3aWR0aCA9IHdpZHRoLCBoZWlnaHQgPSBoZWlnaHQsIGRwaSA9IDYwMCwgY29tcHJlc3Npb24gPSAibHp3IikNCiAgaW52aXNpYmxlKE5VTEwpDQp9DQpleHBvcnRfdGFibGUgPC0gZnVuY3Rpb24oZ3Rfb2JqLCBmaWxlbmFtZSl7DQogIGd0c2F2ZShndF9vYmosIGZpbGVuYW1lID0gZ2x1ZSgidGFibGVzL3tmaWxlbmFtZX0uaHRtbCIpKQ0KICAjIFBORyAocHJlY2lzYSB3ZWJzaG90MiBpbnN0YWxhZG8vY29uZmlndXJhZG8pDQogIHRyeShndHNhdmUoZ3Rfb2JqLCBmaWxlbmFtZSA9IGdsdWUoInRhYmxlcy97ZmlsZW5hbWV9LnBuZyIpKSkNCiAgIyBMYVRlWA0KICB0cnkoZ3RzYXZlKGd0X29iaiwgZmlsZW5hbWUgPSBnbHVlKCJ0YWJsZXMve2ZpbGVuYW1lfS50ZXgiKSkpDQogIGludmlzaWJsZShOVUxMKQ0KfQ0KDQojIEVzdGlsbyBwYWRyw6NvIGRlIHRhYmVsYQ0KZ3RfYXJ0aWNsZSA8LSBmdW5jdGlvbihkYXQsIHRpdGxlID0gTlVMTCwgc3VidGl0bGUgPSBOVUxMLCBub3RlID0gTlVMTCl7DQogIGRhdCAlPiUNCiAgICBndCgpICU+JQ0KICAgIHRhYl9oZWFkZXIodGl0bGUgPSBtZCh0aXRsZSAlfHwlICIiKSwgc3VidGl0bGUgPSBtZChzdWJ0aXRsZSAlfHwlICIiKSkgJT4lDQogICAgZm10X251bWJlcih3aGVyZShpcy5udW1lcmljKSwgZGVjaW1hbHMgPSAyKSAlPiUNCiAgICB0YWJfb3B0aW9ucyh0YWJsZS5mb250LnNpemUgPSBweCgxMikpICU+JQ0KICAgIG9wdF9ob3Jpem9udGFsX3BhZGRpbmcoc2NhbGUgPSAxLjEpICU+JQ0KICAgIG9wdF92ZXJ0aWNhbF9wYWRkaW5nKHNjYWxlID0gMS4xKSAlPiUNCiAgICB0YWJfc291cmNlX25vdGUobWQobm90ZSAlfHwlICJOb3RlczogQXV0aG9y4oCZcyBjYWxjdWxhdGlvbnMuIikpDQp9DQpgYGANCg0KIyAxLiBJbnRyb2R1Y3Rpb24NCg0KVGhpcyByZXBvcnQgZG9jdW1lbnRzIHRoZSBhbmFseXRpY2FsIHBpcGVsaW5lIGRldmVsb3BlZCB0byBlc3RpbWF0ZSB0aGUgY2xpbWF0aWMgcGVuYWx0eSAocGVuYWxpZGFkZSBjbGltw6F0aWNhKSBvbiBCcmF6aWzigJlzIGVsZWN0cmljaXR5IHNlY3RvciBhbmQgdG8gdHJhbnNsYXRlIHRoZXNlIGVmZmVjdHMgaW50byBtZWFzdXJhYmxlIGVjb25vbWljIGNvc3RzLiBUaGUgYW5hbHlzaXMgd2FzIGNvbmR1Y3RlZCB1c2luZyBtb250aGx5IGRhdGEgZnJvbSAyMDAxIHRvIDIwMTksIGNvdmVyaW5nIGFsbCBmb3VyIHN1YnN5c3RlbXMgb2YgdGhlIE5hdGlvbmFsIEludGVyY29ubmVjdGVkIFN5c3RlbSAoU0lOKS4NCg0KVGhlIHN0dWR5IHByb2NlZWRzIHRocm91Z2ggdGhlIGZvbGxvd2luZyBzdGVwczoNCg0KMS4gIEh5ZHJvbG9naWNhbCBtb2RlbGxpbmcg4oCUIFdlIGVzdGltYXRlZCB0aGUgcmVsYXRpb25zaGlwIGJldHdlZW4gY2xpbWF0aWMgdmFyaWFibGVzIChwcmVjaXBpdGF0aW9uLCB0ZW1wZXJhdHVyZSwgaHVtaWRpdHksIHdpbmQpIGFuZCBzdG9yZWQgZW5lcmd5IChFQVIpIGFuZCBoeWRyb2VsZWN0cmljIGdlbmVyYXRpb24gdXNpbmcgR2VuZXJhbGl6ZWQgQWRkaXRpdmUgTW9kZWxzIChHQU1zKS4gVGhlc2UgbW9kZWxzIGNhcHR1cmUgbm9uLWxpbmVhciBjbGltYXRl4oCTaHlkcm9sb2d5IGludGVyYWN0aW9ucyBhbmQgc2Vhc29uYWwgZWZmZWN0cyBhdCB0aGUgc3Vic3lzdGVtIGxldmVsLg0KDQoyLiAgQ2xpbWF0aWMgY291bnRlcmZhY3R1YWxzIOKAlCBVc2luZyB0aGUgZml0dGVkIEdBTXMsIHdlIHNpbXVsYXRlZCBjb3VudGVyZmFjdHVhbCB0cmFqZWN0b3JpZXMgZml4aW5nIHRoZSBjbGltYXRpYyBjb3ZhcmlhdGVzIGF0IHRoZWlyIGhpc3RvcmljYWwgbWVhbiBsZXZlbHMgKGJhc2VsaW5lIDIwMDHigJMyMDA1KS4gVGhlIGRldmlhdGlvbiBiZXR3ZWVuIG9ic2VydmVkIGFuZCBjb3VudGVyZmFjdHVhbCB2YWx1ZXMgaXNvbGF0ZXMgdGhlIHNoYXJlIG9mIHZhcmlhdGlvbiBhdHRyaWJ1dGFibGUgZXhjbHVzaXZlbHkgdG8gY2xpbWF0ZSB2YXJpYWJpbGl0eS4NCg0KMy4gIENsaW1hdGUgcGVuYWx0eSAozpRFKSDigJQgVGhlIGNsaW1hdGUgcGVuYWx0eSB3YXMgZGVmaW5lZCBhcyAkzpRFPUVfe3ByZWRpY3RlZH3iiJJFX3tjZn0kIHJlcHJlc2VudGluZyB0aGUgbG9zcyAob3IgZ2Fpbikgb2YgaHlkcm8gZ2VuZXJhdGlvbiBkdWUgc29sZWx5IHRvIGNsaW1hdGljIGZsdWN0dWF0aW9ucy4NCg0KNC4gIEVsYXN0aWNpdGllcyDigJQgV2UgZGVyaXZlZCBlbGFzdGljaXRpZXMgbGlua2luZyBnZW5lcmF0aW9uIHRvIGh5ZHJvbG9naWNhbCBhbmQgY2xpbWF0aWMgY29uZGl0aW9ucywgYW5kIGRlbWFuZCB0byBwcmljZSBhbmQgaW5jb21lLCB0byBhc3Nlc3Mgc2Vuc2l0aXZpdHkgYW5kIHBvdGVudGlhbCB0cmFuc21pc3Npb24gY2hhbm5lbHMgb2YgY2xpbWF0aWMgc2hvY2tzLg0KDQo1LiAgQ29zdCB0cmFuc2xhdGlvbiDigJQgVGhlIGVzdGltYXRlZCBwZW5hbHRpZXMgd2VyZSBjb252ZXJ0ZWQgaW50byBtb25ldGFyeSB0ZXJtcyBhbG9uZyB0aHJlZSBjb3N0IGRpbWVuc2lvbnM6DQoNCjYuICBDb25zdW1lcnM6IGFkZGl0aW9uYWwgZXhwZW5kaXR1cmUgZHVlIHRvIHJlcGxhY2VtZW50IG9mIGNoZWFwZXIgaHlkcm8gZ2VuZXJhdGlvbiBieSBtb3JlIGV4cGVuc2l2ZSBzb3VyY2VzOw0KDQo3LiAgRWxlY3RyaWNpdHkgc2VjdG9yOiBoaWdoZXIgc3BvdCBtYXJrZXQgcHJpY2VzIChQTEQpIGFuZCBvcGVyYXRpb25hbCBjb3N0czsNCg0KVGhpcyBlbXBpcmljYWwgcGlwZWxpbmUgbGlua3MgY2xpbWF0ZSB2YXJpYWJpbGl0eSwgaHlkcm9sb2dpY2FsIHBlcmZvcm1hbmNlLCBhbmQgZWNvbm9taWMgb3V0Y29tZXMgdGhyb3VnaCBhIHVuaWZpZWQgc3RhdGlzdGljYWwgZnJhbWV3b3JrLCBlbmFibGluZyBhIG11bHRpZGltZW5zaW9uYWwgdmFsdWF0aW9uIG9mIGNsaW1hdGUtcmVsYXRlZCByaXNrcyBpbiBhIGh5ZHJvLWRlcGVuZGVudCBwb3dlciBzeXN0ZW0uDQoNCiMgMi4gRGF0YSBQcmVwYXJhdGlvbg0KDQpUaGlzIHNlY3Rpb24gZGVzY3JpYmVzIHRoZSBjb25zdHJ1Y3Rpb24gb2YgdGhlIGFuYWx5dGljYWwgZGF0YXNldCB1c2VkIHRvIGVzdGltYXRlIHRoZSBjbGltYXRpYyBwZW5hbHR5LlwNCkFsbCB2YXJpYWJsZXMgd2VyZSBoYXJtb25pemVkIGF0IHRoZSAqKnN1YnN5c3RlbeKAk2RheSoqIGxldmVsIGJldHdlZW4gMjAwMSBhbmQgMjAxOSwgaW50ZWdyYXRpbmcgaHlkcm9sb2dpY2FsLCBjbGltYXRpYywgYW5kIG1hcmtldCBpbmZvcm1hdGlvbi4NCg0KIyMjIDIuMSBEYXRhIFNvdXJjZXMNCg0KLSAgICAqKkh5ZHJvcG93ZXIgZ2VuZXJhdGlvbiAocGxhbnQtZGF5KToqKiBkYWlseSBnZW5lcmF0aW9uIGRhdGEgY29tcGlsZWQgZnJvbSBPTlMgcmVjb3JkcywgYWdncmVnYXRlZCBieSBzdWJzeXN0ZW0uDQoNCi0gICAqKlJlc2Vydm9pciBsZXZlbHMgYW5kIG5hdHVyYWwgaW5mbG93cyAoRUFSIGFuZCBFTkEpOioqIHN1YnN5c3RlbS1sZXZlbCBkYWlseSBkYXRhIGZyb20gT05TLg0KDQotICAgKipDbGltYXRpYyB2YXJpYWJsZXM6KiogcHJlY2lwaXRhdGlvbiBhbmQgdGVtcGVyYXR1cmUgb2J0YWluZWQgZnJvbSB0aGUgRUNNV0YvQ0FNUyByZWFuYWx5c2lzIGRhdGFzZXQsIGludGVycG9sYXRlZCB0byBtYXRjaCBzdWJzeXN0ZW0gY2VudHJvaWRzLg0KDQotICAgKipTcG90IHByaWNlIChQTEQpOioqIHdlZWtseSBzdWJzeXN0ZW0gZGF0YSBmcm9tIENDRUUuDQoNCi0gICAqKkRlbWFuZCBhbmQgZ2VuZXJhdGlvbiBkaXNwYXRjaCBieSBzb3VyY2U6KiogbW9udGhseSBvciB3ZWVrbHkgZGF0YSBmcm9tIE9OUyBhbmQgRVBFLg0KDQpBbGwgZGF0YXNldHMgd2VyZSBwcmUtcHJvY2Vzc2VkIHRvIGFsaWduIGRhdGUgZm9ybWF0cywgaGFybW9uaXplIHZhcmlhYmxlIG5hbWVzLCBhbmQgcmVtb3ZlIGluY29uc2lzdGVudCBvciBtaXNzaW5nIGlkZW50aWZpZXJzLg0KDQojIyMgMi4yIERhdGEgTG9hZGluZyBhbmQgQ2xlYW5pbmcNCg0KYGBge3IgZGF0YS1pbn0NCiMgTG9hZCBjb3JlIGRhdGFzZXRzDQpnZXIgICAgIDwtIHJlYWQuY3N2KCJiYXNlX2dlcmFfdHJhdGFkYV9zZXQuY3N2IikgICAgICMgcGxhbnQtZGF5IGdlbmVyYXRpb24NCnBsZCAgICAgPC0gcmVhZC5jc3YoInByZWNvX3NlbWFuYWwuY3N2IikgICAgICAgICAgICAgIyB3ZWVrbHkgc3BvdCBwcmljZSAoUExEKQ0KcmVzZXJ2ICA8LSByZWFkLmNzdigiZW5hX2Vhcl9oaWRyX2NlZ19hbWIuY3N2IikgICAgICAjIHJlc2Vydm9pciBsZXZlbHMgJiBpbmZsb3dzIChFQVIvRU5BKQ0KYGBgDQoNCg0KYGBge3IgZGF0YS1pbiAyIH0NCiMgQ29udmVydCBjaGFyYWN0ZXIgY29sdW1ucyB0byBmYWN0b3JzDQpnZXIgICAgPC0gZ2VyICAgICU+JSBtdXRhdGUoYWNyb3NzKHdoZXJlKGlzLmNoYXJhY3RlciksIGFzLmZhY3RvcikpDQpyZXNlcnYgPC0gcmVzZXJ2ICU+JSBtdXRhdGUoYWNyb3NzKHdoZXJlKGlzLmNoYXJhY3RlciksIGFzLmZhY3RvcikpDQpwbGQgICAgPC0gcGxkICAgICU+JSBtdXRhdGUoYWNyb3NzKHdoZXJlKGlzLmNoYXJhY3RlciksIGFzLmZhY3RvcikpDQoNCiMgLS0tIERhdGUgcGFyc2luZyBhbmQgdGVtcG9yYWwgdmFyaWFibGVzIC0tLQ0KZ2VyJGRhdGUgICAgPC0gYXMuRGF0ZShnZXIkRGF0ZSkgICAgICAgICAgICAgICAjIGFkanVzdCBjb2x1bW4gbmFtZSBhcyBuZWVkZWQNCmdlciRkb3kgICAgIDwtIHlkYXkoZ2VyJGRhdGUpDQpnZXIkZG93ICAgICA8LSBsdWJyaWRhdGU6OndkYXkoZ2VyJGRhdGUsIGxhYmVsID0gVFJVRSwgYWJiciA9IFRSVUUpDQpnZXIkbW9udGggICA8LSBtb250aChnZXIkZGF0ZSkNCmdlciR0cmVuZCAgIDwtIGFzLm51bWVyaWMoZ2VyJGRhdGUpDQoNCnJlc2VydiRkYXRlIDwtIGFzLkRhdGUocmVzZXJ2JGVuYV9kYXRhKSAgICAgICAgIyBhZGp1c3QgY29sdW1uIG5hbWUgYXMgbmVlZGVkDQpyZXNlcnYkZG95ICA8LSB5ZGF5KHJlc2VydiRkYXRlKQ0KcmVzZXJ2JGRvdyAgPC0gbHVicmlkYXRlOjp3ZGF5KHJlc2VydiRkYXRlLCBsYWJlbCA9IFRSVUUsIGFiYnIgPSBUUlVFKQ0KcmVzZXJ2JG1vbnRoPC0gbW9udGgocmVzZXJ2JGRhdGUpDQpyZXNlcnYkdHJlbmQ8LSBhcy5udW1lcmljKHJlc2VydiRkYXRlKQ0KDQpwbGQkZGF0ZSAgICA8LSBhcy5EYXRlKHBsZCREQVRBX0lOSUNJTykgICAgICAgICMgYWRqdXN0IGNvbHVtbiBuYW1lIGFzIG5lZWRlZA0KcGxkJHdlZWsgICAgPC0gaXNvd2VlayhwbGQkZGF0ZSkNCnBsZCR5ZWFyICAgIDwtIHllYXIocGxkJGRhdGUpDQoNCmBgYA0KDQoNCg0KYGBge3IgY29uZmVyaXIgZSBsaW1wYXIgY29sdW5hcyBkdXBsaWNhZGFzfQ0KZHVwbGljYWRhcyA8LSBkdXBsaWNhdGVkKGFzLmxpc3QocmVzZXJ2KSkNCnJlc2VydlssZHVwbGljYWRhc10gJT4lIGNvbG5hbWVzKCkNCnJlc2VydjwtcmVzZXJ2ICU+JSBzZWxlY3QoLWlkX3N1YnNpc3RlbWEueC54LC1pZF9zdWJzaXN0ZW1hLnkueSwtbm9tX2JhY2lhLngsLW5vbV9iYWNpYS54LC1ub21fcmVlLngsLW5vbV9yZWUueSwtbm9tX3VzaW5hLngsLW5vbV9zdWJzaXN0ZW1hLnkueSwtbm9tX2JhY2lhLnkpDQpgYGANCg0KIyMjIDIuMyBUZW1wb3JhbCBTbW9vdGhpbmcgYW5kIFJvbGxpbmcgTWVhbnMNClRvIHJlZHVjZSBzaG9ydC10ZXJtIG5vaXNlIGFuZCBjYXB0dXJlIGN1bXVsYXRpdmUgY2xpbWF0aWMgZWZmZWN0cywgd2UgY29tcHV0ZWQgKipyb2xsaW5nIG1lYW5zICg3LCAxNCwgYW5kIDMwIGRheXMpKiogZm9yIGtleSBoeWRyb2xvZ2ljYWwgYW5kIGNsaW1hdGljIHZhcmlhYmxlcy4gIA0KDQoNCg0KYGBge3J9DQpsaWJyYXJ5KHpvbykNCmxpYnJhcnkoZHBseXIpDQoNCiMjZGlhZ19ncm91cHMgPC0gcmVzZXJ2ICU+JWZpbHRlcih0aXBfcmVzZXJ2YXRvcmlvPT0iUmVzZXJ2YXTDs3JpbyBjb20gVXNpbmEiKSAlPiUgDQojICBncm91cF9ieShub21fcmVzZXJ2YXRvcmlvLngsaWRfcmVzZXJ2YXRvcmlvLngsdGlwX3Jlc2VydmF0b3JpbykgJT4lDQojICBzdW1tYXJpc2UoDQojICAgIG5fdG90YWwgPSBuKCksDQojICAgIG5fbm9uX25hX3ByZWNpcCA9IHN1bSghaXMubmEocHJlY2lwdGF0aW9uKSksDQojICAgIG5fbm9uX25hX3RlbXAgICA9IHN1bSghaXMubmEodGVtcGVyYXR1cmUpKSwNCiMgICAgbl9ub25fbmFfZW5hICAgID0gc3VtKCFpcy5uYShlbmFfYnJ1dGFfcmVzX213bWVkKSksDQojICAgIG5fbm9uX25hX2VhciAgICA9IHN1bSghaXMubmEoZWFyX3Jlc2VydmF0b3Jpb19zdWJzaXN0ZW1hX3Byb3ByaW9fbXdtZXMpKSwNCiMgICAgbl9ub25fbmFfZ2VyICAgID0gc3VtKCFpcy5uYSh2YWxfZ2VyYWNhbykpLA0KIyAgICAuZ3JvdXBzID0gImRyb3AiDQojICApDQojIyBDcmlhciBtw6lkaWFzIG3Ds3ZlaXMgcGFyYSB2YXJpw6F2ZWlzIGFtYmllbnRhaXMgcHJpbmNpcGFpcw0KcmVzZXJ2IDwtIHJlc2VydiAlPiUgZmlsdGVyKHRpcF9yZXNlcnZhdG9yaW89PSJSZXNlcnZhdMOzcmlvIGNvbSBVc2luYSIpICU+JSANCiAgZ3JvdXBfYnkobm9tX3Jlc2VydmF0b3Jpby54KSAlPiUNCiAgYXJyYW5nZShkYXRlLCAuYnlfZ3JvdXAgPSBUUlVFKSAlPiUNCiAgbXV0YXRlKA0KICAgICMgUHJlY2lwaXRhdGlvbiAodXNhIG5vbWUgJ3ByZWNpcHRhdGlvbicgY29tbyBlc3TDoSBuYSBzdWEgYmFzZSkNCiAgICAjcHJlY2lwX21tNyAgID0gcm9sbG1lYW4ocHJlY2lwdGF0aW9uLCAgNyksDQogICAgcHJlY2lwX21tMTQgID0gcm9sbG1lYW4ocHJlY2lwdGF0aW9uLCAxNCxmaWxsID0gTkEsIGFsaWduID0gInJpZ2h0IiksDQogICAgcHJlY2lwX21tMzAgID0gcm9sbG1lYW4ocHJlY2lwdGF0aW9uLCAzMCxmaWxsID0gTkEsIGFsaWduID0gInJpZ2h0IiksDQoNCiAgICAjIFRlbXBlcmF0dXJlDQogICAgdGVtcF9tbTcgICAgID0gcm9sbG1lYW4odGVtcGVyYXR1cmUsICA3LGZpbGwgPSBOQSwgYWxpZ24gPSAicmlnaHQiKSwNCiAgICB0ZW1wX21tMTQgICAgPSByb2xsbWVhbih0ZW1wZXJhdHVyZSwgMTQsZmlsbCA9IE5BLCBhbGlnbiA9ICJyaWdodCIpLA0KICAgIHRlbXBfbW0zMCAgICA9IHJvbGxtZWFuKHRlbXBlcmF0dXJlLCAzMCxmaWxsID0gTkEsIGFsaWduID0gInJpZ2h0IiksDQoNCiAgICAjIEVOQQ0KICAgIGVuYV9tdzcgICAgICA9IHJvbGxtZWFuKGVuYV9icnV0YV9yZXNfbXdtZWQsICA3LGZpbGwgPSBOQSwgYWxpZ24gPSAicmlnaHQiKSwNCiAgICAjZW5hX213MTQgICAgID0gcm9sbF9tZWFuX3JpZ2h0KGVuYV9icnV0YV9yZXNfbXdtZWQsIDE0KSwNCiAgICAjZW5hX213MzAgICAgID0gcm9sbF9tZWFuX3JpZ2h0KGVuYV9icnV0YV9yZXNfbXdtZWQsIDMwKSwNCg0KICAgICMgRUFSIChwcm9wcmlldMOhcmlvKSDigJQgcmVtb3ZldSBmaWxsPSJleHRlbmQiIChuw6NvIHN1cG9ydGFkbykNCiAgICMgZWFyX213NyAgICAgID0gcm9sbF9tZWFuX3JpZ2h0KGVhcl9yZXNlcnZhdG9yaW9fc3Vic2lzdGVtYV9wcm9wcmlvX213bWVzLCA3KSwNCg0KICAgICMgR2VyYcOnw6NvDQogICAgZ2VyX213NyAgICAgID0gcm9sbG1lYW4odmFsX2dlcmFjYW8sICA3LGZpbGwgPSBOQSwgYWxpZ24gPSAicmlnaHQiKSwNCiAgICBnZXJfbXcxNCAgICAgPSByb2xsbWVhbih2YWxfZ2VyYWNhbywgMTQsZmlsbCA9IE5BLCBhbGlnbiA9ICJyaWdodCIpLA0KICAgIGdlcl9tdzMwICAgICA9IHJvbGxtZWFuKHZhbF9nZXJhY2FvLCAzMCxmaWxsID0gTkEsIGFsaWduID0gInJpZ2h0IikNCiAgKSAlPiUNCiAgdW5ncm91cCgpDQoNCiNkaWFnX2dyb3VwcyAlPiUgZmlsdGVyKG5vbV9yZXNlcnZhdG9yaW8ueD09IkEuIFZFUk1FTEhBIikgDQojICANCiNyZXNlcnYgJT4lIGZpbHRlcihub21fcmVzZXJ2YXRvcmlvLng9PSJBLiBWRVJNRUxIQSIpICU+JSANCiMgIGdncGxvdChhZXMocHJlY2lwdGF0aW9uKSkrZ2VvbV9saW5lKGFlcyh4PWRhdGUseT1wcmVjaXB0YXRpb24pLGNvbD0ibGlnaHRibHVlIikNCiMgIHNlbGVjdChkYXRlLG5vbV9lc3RhZG8sdmFsX2dlcmFjYW8scHJlY2lwdGF0aW9uLA0KIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICNlYXJtYXhfcmVzZXJ2YXRvcmlvX3N1YnNpc3RlbWFfanVzYW50ZV9td21lcyxlYXJfcmVzZXJ2YXRvcmlvX3N1YnNpc3RlbWFfcHJvcHJpb19td21lcyxlYXJfbWF4aW1hX3RvdGFsX213bWVzKSAlPiUgc3VtbWFyeQ0KYGBgDQoNCg0KDQoNCmBgYHtyfQ0KIyAtLS0gQ29uZmVyaXIgY2hhdmVzIHByaW5jaXBhaXMgLS0tDQojIHZlcmlmaWNhciBzZSBkYXRhcyBlIHN1YnNpc3RlbWFzIGJhdGVtDQpjYXQoIkRhdGFzIGRpc3BvbsOtdmVpczpcbiIpDQpyYW5nZShnZXIkZGF0ZSwgbmEucm09VFJVRSkNCnJhbmdlKHJlc2VydiRkYXRlLCBuYS5ybT1UUlVFKQ0KcmFuZ2UocGxkJGRhdGUsIG5hLnJtPVRSVUUpDQpgYGANCg0KIyMjIDIuNCBEZXNjcmlwdGl2ZSBTdW1tYXJpZXMNCg0KYGBge3IgZGVzY3JpcHRpdmUtc3VtbWFyaWVzLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQ0KbGlicmFyeShkcGx5cikNCmxpYnJhcnkodGlkeXIpDQpsaWJyYXJ5KGd0KQ0KbGlicmFyeShwdXJycikNCmxpYnJhcnkoc3RyaW5ncikNCg0KIyBIZWxwZXI6IHNlbGVjaW9uYSBhcyB2YXJpw6F2ZWlzIGV4YXRhcyBwZWRpZGFzLCBzZSBleGlzdGlyZW0gbm8gZGF0YXNldA0Kc2VsZWN0X2Rlc2NfdmFycyA8LSBmdW5jdGlvbihkZil7DQogIHdhbnRlZCA8LSB0aWR5c2VsZWN0Ojp2YXJzX3NlbGVjdCgNCiAgICBuYW1lcyhkZiksDQogICAgc3RhcnRzX3dpdGgoImVhciIpLA0KICAgIHN0YXJ0c193aXRoKCJ0ZW0iKSwNCiAgICBzdGFydHNfd2l0aCgicHJlIiksDQogICAgc3RhcnRzX3dpdGgoImdlciIpLA0KICAgIHZhbF9nZXJhY2FvLA0KICAgIHZhbF9nZXJhY2FvX2RheV9zdWJzaXN0ZW1hLA0KICAgIGh1bWlkaXR5LA0KICAgIHdpbmRfc3BlZWQNCiAgKQ0KICBkZiAlPiUgZHBseXI6OnNlbGVjdChub21fc3Vic2lzdGVtYS54LCBkcGx5cjo6YWxsX29mKHdhbnRlZCkpDQp9DQoNCiMgSGVscGVyOiBzdW1hcml6YSBlc3RhdMOtc3RpY2FzIHBhcmEgdW0gZGF0YS5mcmFtZSBqw6EgZmlsdHJhZG8gcG9yIHN1YnNpc3RlbWENCnN1bW1hcmlzZV9zdGF0cyA8LSBmdW5jdGlvbihkZl9zdWIpew0KICBudW1fdmFycyA8LSBkZl9zdWIgJT4lIGRwbHlyOjpzZWxlY3Qod2hlcmUoaXMubnVtZXJpYykpDQogIGRwbHlyOjpzdW1tYXJpc2UoDQogICAgbnVtX3ZhcnMsDQogICAgZHBseXI6OmFjcm9zcygNCiAgICAgIC5jb2xzID0gZXZlcnl0aGluZygpLA0KICAgICAgLmZucyAgPSBsaXN0KA0KICAgICAgICBNZWFuID0gfm1lYW4oLiwgbmEucm0gPSBUUlVFKSwNCiAgICAgICAgU0QgICA9IH5zZCguLCBuYS5ybSA9IFRSVUUpLA0KICAgICAgICBNaW4gID0gfm1pbiguLCBuYS5ybSA9IFRSVUUpLA0KICAgICAgICBNYXggID0gfm1heCguLCBuYS5ybSA9IFRSVUUpDQogICAgICApLA0KICAgICAgLm5hbWVzID0gInsuY29sfV9fey5mbn0iDQogICAgKQ0KICApICU+JQ0KICAgIHRpZHlyOjpwaXZvdF9sb25nZXIoZXZlcnl0aGluZygpLA0KICAgICAgbmFtZXNfdG8gPSBjKCJ2YXJpYWJsZSIsInN0YXQiKSwNCiAgICAgIG5hbWVzX3NlcCA9ICJfXyIsDQogICAgICB2YWx1ZXNfdG8gPSAidmFsdWUiDQogICAgKSAlPiUNCiAgICB0aWR5cjo6cGl2b3Rfd2lkZXIobmFtZXNfZnJvbSA9IHN0YXQsIHZhbHVlc19mcm9tID0gdmFsdWUpICU+JQ0KICAgIGRwbHlyOjphcnJhbmdlKHZhcmlhYmxlKQ0KfQ0KDQpgYGANCg0KYGBge3J9DQojIFRhYmVsYSBkZSBjb2JlcnR1cmEgdGVtcG9yYWwgcG9yIHN1YnNpc3RlbWENCmNvdmVyYWdlX3RibCA8LSByZXNlcnYgJT4lDQogIGRwbHlyOjpncm91cF9ieShub21fc3Vic2lzdGVtYS54KSAlPiUNCiAgZHBseXI6OnN1bW1hcmlzZSgNCiAgICBvYnNlcnZhdGlvbnMgPSBkcGx5cjo6bl9kaXN0aW5jdChpZF9yZXNlcnZhdG9yaW8ueCksDQogICAgc3RhcnRfZGF0ZSAgPSBtaW4oZGF0ZSwgbmEucm0gPSBUUlVFKSwNCiAgICBlbmRfZGF0ZSAgICA9IG1heChkYXRlLCBuYS5ybSA9IFRSVUUpLA0KICAgIC5ncm91cHMgPSAiZHJvcCINCiAgKQ0KDQp0YWJfY292IDwtIGd0X2FydGljbGUoDQogIGNvdmVyYWdlX3RibCwNCiAgdGl0bGUgPSAiKipUYWJsZSBBLiBUZW1wb3JhbCBjb3ZlcmFnZSBieSBzdWJzeXN0ZW0qKiIsDQogIHN1YnRpdGxlID0gIk9ic2VydmF0aW9uIGNvdW50cyBhbmQgZGF0ZSByYW5nZSIsDQogIG5vdGUgPSAiRGF0ZXMgaW4gWVlZWS1NTS1ERC4iDQopICU+JQ0KICBndDo6Y29sc19sYWJlbCgNCiAgICBub21fc3Vic2lzdGVtYS54ICAgPSAiU3Vic3lzdGVtIiwNCiAgICBvYnNlcnZhdGlvbnM9ICJOIG9mIFJlc2Vydm9pcnMiLA0KICAgIHN0YXJ0X2RhdGUgID0gIlN0YXJ0IiwNCiAgICBlbmRfZGF0ZSAgICA9ICJFbmQiDQogICkNCg0KZXhwb3J0X3RhYmxlKHRhYl9jb3YsICJUYWJBX0NvdmVyYWdlX2J5U3Vic3lzdGVtIikNCnRhYl9jb3YNCmBgYA0KDQpgYGB7cn0NCg0KIyBUYWJlbGEgZGUgY29iZXJ0dXJhIHRlbXBvcmFsIHBvciBzdWJzaXN0ZW1hDQojY292ZXJhZ2VfdGJsIDwtIA0KcmVzZXJ2ICU+JQ0KICBkcGx5cjo6Z3JvdXBfYnkobm9tX3N1YnNpc3RlbWEueCkgJT4lDQogIGRwbHlyOjpzdW1tYXJpc2UoDQogICAgTWVhbl9nZXJhY2FvPW1lYW4odmFsX2dlcmFjYW8sIG5hLnJtID0gVFJVRSksDQogICAgU0RfZ2VyYWNhbz1tZWFuKHZhbF9nZXJhY2FvLCBuYS5ybSA9IFRSVUUpLA0KICAgIE1pbl9nZXJhY2FvICA9IG1pbih2YWxfZ2VyYWNhbywgbmEucm0gPSBUUlVFKSwNCiAgICBNYXhfZ2VyYWNhbyAgICA9IG1heCh2YWxfZ2VyYWNhbywgbmEucm0gPSBUUlVFKSwNCiAgICANCiAgICBNZWFuX0VBUj1tZWFuKGVhcl9yZXNlcnZhdG9yaW9fc3Vic2lzdGVtYV9wcm9wcmlvX213bWVzLCBuYS5ybSA9IFRSVUUpLA0KICAgIFNEX0VBUj1tZWFuKGVhcl9yZXNlcnZhdG9yaW9fc3Vic2lzdGVtYV9wcm9wcmlvX213bWVzLCBuYS5ybSA9IFRSVUUpLA0KICAgIE1pbl9FQVIgID0gbWluKGVhcl9yZXNlcnZhdG9yaW9fc3Vic2lzdGVtYV9wcm9wcmlvX213bWVzLCBuYS5ybSA9IFRSVUUpLA0KICAgIE1heF9FQVIgICAgPSBtYXgoZWFyX3Jlc2VydmF0b3Jpb19zdWJzaXN0ZW1hX3Byb3ByaW9fbXdtZXMsIG5hLnJtID0gVFJVRSksDQogICAgDQogICAgTWVhbl9wcmVjaXBtbTMwPW1lYW4ocHJlY2lwX21tMzAsIG5hLnJtID0gVFJVRSksDQogICAgU0RfcHJlY2lwbW0zMD1tZWFuKHByZWNpcF9tbTMwLCBuYS5ybSA9IFRSVUUpLA0KICAgIE1pbl9wcmVjaXBtbTMwICA9IG1pbihwcmVjaXBfbW0zMCwgbmEucm0gPSBUUlVFKSwNCiAgICBNYXhfcHJlY2lwbW0zMCAgICA9IG1heChwcmVjaXBfbW0zMCwgbmEucm0gPSBUUlVFKSwNCiAgICANCiAgICBNZWFuX3RlbXBtbTc9bWVhbih0ZW1wX21tNywgbmEucm0gPSBUUlVFKSwNCiAgICBTRF90ZW1wbW03PW1lYW4odGVtcF9tbTcsIG5hLnJtID0gVFJVRSksDQogICAgTWluX3RlbXBtbTcgID0gbWluKHRlbXBfbW03LCBuYS5ybSA9IFRSVUUpLA0KICAgIE1heF90ZW1wbW03ICAgID0gbWF4KHRlbXBfbW03LCBuYS5ybSA9IFRSVUUpLA0KICAgIA0KICAgIE1lYW5faHVtaWRpdHk9bWVhbihodW1pZGl0eSwgbmEucm0gPSBUUlVFKSwNCiAgICBTRF9odW1pZGl0eT1tZWFuKGh1bWlkaXR5LCBuYS5ybSA9IFRSVUUpLA0KICAgIE1pbl9odW1pZGl0eSAgPSBtaW4oaHVtaWRpdHksIG5hLnJtID0gVFJVRSksDQogICAgTWF4X2h1bWlkaXR5ICAgID0gbWF4KGh1bWlkaXR5LCBuYS5ybSA9IFRSVUUpLA0KICAgIA0KICAgIE1lYW5fd2luZD1tZWFuKHdpbmRfc3BlZWQsIG5hLnJtID0gVFJVRSksDQogICAgU0Rfd2luZD1tZWFuKHdpbmRfc3BlZWQsIG5hLnJtID0gVFJVRSksDQogICAgTWluX3dpbmQgID0gbWluKHdpbmRfc3BlZWQsIG5hLnJtID0gVFJVRSksDQogICAgTWF4X3dpbmQgICAgPSBtYXgod2luZF9zcGVlZCwgbmEucm0gPSBUUlVFKSwNCiAgICANCiAgICAuZ3JvdXBzID0gImRyb3AiKSAlPiUNCiAgICB0aWR5cjo6cGl2b3RfbG9uZ2VyKGMoZW5kc193aXRoKCJnZXJhY2FvIiksZW5kc193aXRoKCJpbmQiKSxlbmRzX3dpdGgoIkVBUiIpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICBlbmRzX3dpdGgoIml0eSIpLGVuZHNfd2l0aCgibW03IiksZW5kc193aXRoKCJtbTMwIikpLA0KICAgICAgbmFtZXNfdG8gPSBjKCJ2YXJpYWJsZSIsInN0YXQiKSwNCiAgICAgIG5hbWVzX3NlcCA9ICJfIiwNCiAgICAgIHZhbHVlc190byA9ICJ2YWx1ZSINCiAgICApICU+JSBwaXZvdF93aWRlcihuYW1lc19mcm9tID0gdmFyaWFibGUsdmFsdWVzX2Zyb20gPXZhbHVlKSAlPiUgDQogIGFycmFuZ2Uoc3RhdCkgJT4lICMgLT4gdGFiX2Rlc2MNCiAgZ3RfYXJ0aWNsZSgNCiAgDQogIHRpdGxlID0gIioqVGFibGUgQi4gIERlc2NyaXB0aXZlIFN1bW1hcmllcyIsDQogIHN1YnRpdGxlID0gIk9ic2VydmF0aW9uIGNvdW50cyBhbmQgZGF0ZSByYW5nZSIsDQogIG5vdGUgPSAiRGF0ZXMgaW4gWVlZWS1NTS1ERC4iDQopICU+JQ0KICBndDo6Y29sc19sYWJlbCgNCiAgICBub21fc3Vic2lzdGVtYS54ICAgPSAiU3Vic3lzdGVtIiwNCiAgICBzdGF0PSAiVmFyaWFibGUiLA0KICAgIE1lYW4gID0gIk1lYW4iLA0KICAgIFNEICAgID0gIlNEIixNaW49ICJNaW4iLCJNYXgiPSAiTWF4Ig0KICApDQoNCiNleHBvcnRfdGFibGUodGFiX2NvdiwgIlRhYkFfQ292ZXJhZ2VfYnlTdWJzeXN0ZW0iKQ0KI3RhYl9jb3YNCg0KYGBgDQoNCmBgYHtyfQ0KDQoNCg0KcmVzZXJ2ICU+JSBzZWxlY3Qoc3RhcnRzX3dpdGgoImVuYSIpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RhcnRzX3dpdGgoImVhciIpLHN0YXJ0c193aXRoKCJ0ZW0iKSxzdGFydHNfd2l0aCgicHJlIiksc3RhcnRzX3dpdGgoImdlciIpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFsX2dlcmFjYW8sdmFsX2dlcmFjYW9fZGF5X3N1YnNpc3RlbWEsaHVtaWRpdHksd2luZF9zcGVlZCkgJT4lIHN0YXJnYXplcjo6c3RhcmdhemVyKHR5cGU9InRleHQiKQ0KcGxkICU+JSBzdGFyZ2F6ZXI6OnN0YXJnYXplcih0eXBlPSJ0ZXh0IikNCmdlciAlPiUgc2VsZWN0KHZhbF9nZXJhY2FvLG5vbV90aXBvY29tYnVzdGl2ZWwsbm9tX3RpcG91c2luYT1hcy5mYWN0b3Iobm9tX3RpcG91c2luYSkpICU+JSBzdW1tYXJ5DQoNCmBgYA0KDQojIyMgW0dyw6FmaWNvcyByw6FwaWRvczogc8OpcmllcyBFTkEsIHByZWNpcGl0YcOnw6NvLCB0ZW1wZXJhdHVyYSwgRUFSLCBnZXJhw6fDo29dDQoNCmBgYHtyIGZpZy5oZWlnaHQ9OCwgZmlnLndpZHRoPTEyfQ0KIyAtLS0gR3LDoWZpY29zIHLDoXBpZG9zIChFREEpIC0tLQ0KbGlicmFyeShnZ3Bsb3QyKQ0KDQojIFPDqXJpZSBFTkEvUmVzZXJ2YXTDs3Jpb3MNCnBsb3RfZW5hPC1yZXNlcnYgJT4lIGdyb3VwX2J5KGRhdGUpICU+JSBzdW1tYXJpc2UoZWFyX213Nz1tZWFuKGVhcl9yZXNlcnZhdG9yaW9fc3Vic2lzdGVtYV9wcm9wcmlvX213bWVzLG5hLnJtID0gVCkpICU+JSANCiAgZ2dwbG90KGFlcyh4PWRhdGUsIHk9ZWFyX213NykpICsNCiAgZ2VvbV9saW5lKGNvbG9yPSJzdGVlbGJsdWUiKSArZ2VvbV9zbW9vdGgoKSsNCiAgbGFicyh0aXRsZT0iRW5lcmdpYSBBcm1hemVuYWRhIChFQVIpIGJydXRhIChNV21lZCkiLCB4PSIiLCB5PSJNV21lZCIpDQoNCiMgU8OpcmllIEVBUg0KcGxvdF9lYXI8LXJlc2VydiAlPiUgZ3JvdXBfYnkoZGF0ZSkgJT4lIHN1bW1hcmlzZShlbmFfbXc3PW1lYW4oZW5hX213NyxuYS5ybSA9IFQpKSAlPiUgDQogICAgZ2dwbG90KGFlcyh4PWRhdGUsIHk9ZW5hX213NykpICsNCiAgZ2VvbV9saW5lKGNvbG9yPSJkYXJrZ3JlZW4iKSArZ2VvbV9zbW9vdGgoKSsNCiAgbGFicyh0aXRsZT0iRW5lcmdpYSBOYXR1cmFsIEFmbHVlbnRlIChFTkEpIHRvdGFsIChNV23DqnMpIiwgeD0iIiwgeT0iTVdtw6pzIikNCg0KIyBTw6lyaWUgZGUgZ2VyYcOnw6NvDQpwbG90X2dlcjwtcmVzZXJ2ICU+JSBncm91cF9ieShkYXRlKSAlPiUgc3VtbWFyaXNlKGdlcl9tdzc9bWVhbihnZXJfbXc3LG5hLnJtID0gVCkpICU+JSANCiAgICAgIGdncGxvdChhZXMoeD1kYXRlLCB5PWdlcl9tdzcpKSArDQogIGdlb21fbGluZShjb2xvcj0iZ3JleTMwIikgK2dlb21fc21vb3RoKCkrDQogIGxhYnModGl0bGU9IkdlcmHDp8OjbyBoaWRyZWzDqXRyaWNhIChNV2gvZGlhKSIsIHg9IiIsIHk9Ik1XaCIpDQoNCiMgLS0tIENvcnJlbGHDp8O1ZXMgcsOhcGlkYXMgLS0tDQojIFtDaGVjYXIgY29ycmVsYcOnw6NvIGLDoXNpY2EgZW50cmUgY2xpbWEgKHByZWNpcCwgdGVtcCkgZSBFTkFdDQpjbGltYV92YXJzIDwtIHJlc2VydiAlPiUgDQogIGRwbHlyOjpzZWxlY3QoDQogICAgICAgICAgICAgICAgZ2VyX213X3N1YnNpc3RlbWE9dmFsX2dlcmFjYW9fZGF5X3N1YnNpc3RlbWEsDQogICAgICAgICAgICAgICAgZ2VyX213PXZhbF9nZXJhY2FvLGdlcl9tdzcsZ2VyX213MTQsZ2VyX213MzAsDQogICAgICAgICAgICAgICAgZW5hX213PWVuYV9icnV0YV9yZXNfbXdtZWQsIGVuYV9tdzcsDQogICAgICAgICAgICAgICAgZWFyX213PWVhcl90b3RhbF9td21lcywgICNlYXJfbXcxNCwgZWFyX213MzAsDQogICAgICAgICAgICAgICAgcHJlY2lwdGF0aW9uLHByZWNpcF9tbTE0LHByZWNpcF9tbTMwLA0KICAgICAgICAgICAgICAgIHRlbXBlcmF0dXJlLHRlbXBfbW03LHRlbXBfbW0xNCx0ZW1wX21tMzAsDQogICAgICAgICAgICAgICAgd2luZF9zcGVlZCwgDQogICAgICAgICAgICAgICAgKQ0KYGBgDQoNCmBgYHtyIGZpZy5oZWlnaHQ9OCwgZmlnLndpZHRoPTEyfQ0KcGxvdF9nZXJ8cGxvdF9lYXIgLyBwbG90X2VuYQ0KDQpjb3JycGxvdDo6Y29ycnBsb3QoY29yKGNsaW1hX3ZhcnMsIHVzZSA9ICJwYWlyd2lzZS5jb21wbGV0ZS5vYnMiKSxtZXRob2QgPSAiY29sb3IiLCB0eXBlID0gInVwcGVyIiwNCiAgICAgICAgIGFkZENvZWYuY29sID0gImJsYWNrIiwgIyBtb3N0cmFyIGNvZWZpY2llbnRlcw0KICAgICAgICAgdGwuY29sID0gImJsYWNrIiwgdGwuc3J0ID0gMzUsbnVtYmVyLmNleAkJID0uOCwNCiAgICAgICAgIGNvbD1jb2xvclJhbXBQYWxldHRlKGMoInJlZCIsIndoaXRlIiwiYmx1ZSIpKSgyMDApKQ0KYGBgDQoNCmBgYHtyfQ0KbGlicmFyeShwYXRjaHdvcmspDQpsaWJyYXJ5KGdncmVwZWwpDQpnZW9icjo6cmVhZF9yZWdpb24oKS0+Z2VvcmVnaW9uDQoNCnJlc2VydiAlPiUgZmlsdGVyKCJSZXNlcnZhdMOzcmlvIGNvbSBVc2luYSI9PXRpcF9yZXNlcnZhdG9yaW8pICU+JQ0KICBncm91cF9ieShub21fcmVzZXJ2YXRvcmlvLnksdmFsX2xhdGl0dWRlLHZhbF9sb25naXR1ZGUsbm9tX3N1YnNpc3RlbWEueCkgJT4lIA0KICBzdW1tYXJpc2UoZWFyX3Jlc2VydmF0b3Jpbz1zdW0oZWFyX3Jlc2VydmF0b3Jpb19zdWJzaXN0ZW1hX3Byb3ByaW9fbXdtZXMgJT4lIGFzLm51bWVyaWMoKSxuYS5ybSA9IFQpLA0KICAgICAgICAgICAgKSAtPmENCmEgJT4lICAgZ2dwbG90KGFlcyh2YWxfbG9uZ2l0dWRlLHZhbF9sYXRpdHVkZSkpK2dlb21fcG9pbnQoKSsNCmdncGxvdChkYXRhPWdlb3JlZ2lvbikgK2dlb21fc2YoKQ0KYSRub21fc3Vic2lzdGVtYS54ICU+JSB1bmlxdWUNCmEgJT4lDQogIG11dGF0ZShub21fc3Vic2lzdGVtYS54PWNhc2Vfd2hlbihub21fc3Vic2lzdGVtYS54PT0iU1VMIn4iU291dGgiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbm9tX3N1YnNpc3RlbWEueD09IlNVREVTVEUifiJTb3V0aGVhc3QiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbm9tX3N1YnNpc3RlbWEueD09Ik5PUkRFU1RFIn4iTm9ydGhlYXN0IiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5vbV9zdWJzaXN0ZW1hLng9PSJOT1JURSJ+Ik5vcnRoIixUUlVFfiIiKSkgJT4lIA0KICBnZ3Bsb3QoKSArDQogIGdlb21fc2YoZGF0YSA9IGdlb3JlZ2lvbiwgY29sb3IgPSAid2hpdGUiLGZpbGw9ImxpZ2h0Z3JleSIsIHNpemUgPSAyKSsjZ2VvbV9saW5lKCkrDQogIGdlb21fcG9pbnQoYWVzKHZhbF9sb25naXR1ZGUsdmFsX2xhdGl0dWRlLGNvbD1ub21fc3Vic2lzdGVtYS54KSkgK3RoZW1lX3ZvaWQoKSsgI3NjYWxlX2NvbG9yX2Rpc2NyZXRlKHZhbHVlPSkNCiAgZ2VvbV90ZXh0X3JlcGVsKGFlcyh2YWxfbG9uZ2l0dWRlLHZhbF9sYXRpdHVkZSxjb2w9bm9tX3N1YnNpc3RlbWEueCxsYWJlbD1ub21fcmVzZXJ2YXRvcmlvLnkpLHNpemUgPSAyLG1heC5vdmVybGFwcz1ucm93KGEpLGZvcmNlX3B1bGwgID0yKSsNCiAgI3RoZW1lKGxlZ2VuZC5wb3NpdGlvbj1jKC44LCAuOTUpLCxsZWdlbmQuYm94Lmp1c3QgPSAicmlnaHQiKSsNCiAgbGFicyhjb2w9IkVsZXRyaWNhbCBTdWJzeXN0ZW1zIiktPm1hcA0KbWFwDQpgYGANCmBgYHtyfQ0KcmVzZXJ2IDwtIHJlc2VydiAlPiUNCiAgbXV0YXRlKA0KICAgIGRveSAgID0geWRheShkYXRlKSwNCiAgICBtb250aCA9IG1vbnRoKGRhdGUpLA0KICAgICMgdHJhbnNmb3JtYcOnw6NvIGxvZyBwYXJhIGludGVycHJldGHDp8OjbyBwZXJjZW50dWFsIChldml0YSBwcm9ibGVtYXMgY29tIHplcm8pDQogICAgbF9wcmVjaXAgPSBsb2cxcChwcmVjaXBfbW0zMCksDQogICAgbF90ZW1wICAgPSBsb2cxcCh0ZW1wX21tNyksICAgICAjIG9wY2lvbmFsOiBzZSBwcmVmZXJpciBtYW50ZXIgdGVtcCBubyBuw612ZWwsIHVzZSB0ZW1wX21tNyBlbSB2ZXogZGUgbF90ZW1wDQogICAgbF9odW1pZGl0eSA9bG9nMXAoaHVtaWRpdHkpLA0KICAgIGxfd2luZF9zcGVlZD1sb2cod2luZF9zcGVlZCkNCiAgKQ0KYGBgDQoNCiMgMy4xIE1vZGVsbyAxIOKAlCBHQU0g4oCcY2xpbWHigJFhcGVuYXPigJ0gKGJhc2VsaW5lKQ0KDQpNb2RlbG8gaGlkcm9sw7NnaWNvIHBhcnNpbW9uaW9zbyBubyBxdWFsIGEgRW5lcmdpYSBBcm1hemVuYWRhIChFQVIpIMOpIGV4cGxpY2FkYSBhcGVuYXMgcG9yIGNsaW1hIGUgY29udHJvbGVzIHNhem9uYWlzL3JlZ2lvbmFpcywgdXNhbmRvIGZ1bsOnw7VlcyBzdWF2ZXMgKHNwbGluZXMpIGVtIHVtIEdBTS4gTyBvYmpldGl2byDDqSBpc29sYXIgbyBzaW5hbCBwdXJhbWVudGUgY2xpbcOhdGljbyBzb2JyZSBvIGVzdG9xdWUgaMOtZHJpY28gZSBjb25zdHJ1aXIgdW0gY29udHJhZmFjdHVhbCBhdWRpdMOhdmVsLiBNYW50ZW1vcyBhIHJlc3Bvc3RhIG5vIG7DrXZlbCAoTVfCt23DqnMpIHBvciBjb2Vyw6puY2lhIGNvbSBhIGRlZmluacOnw6NvIGRlIHBlbmFsaWRhZGUgZSBtb25ldGl6YcOnw6NvLCBlIHRyYW5zZm9ybWFtb3MgcHJlZGl0b3JlcyBjbGltw6F0aWNvcyBxdWFuZG8gw7p0aWwgcGFyYSBpbnRlcnByZXRhw6fDo28gKHNlbWktZWxhc3RpY2lkYWRlcykuDQpgYGB7cn0NCiMgR0FNIChHYXVzc2lhbiwgZlJFTUwpLiBTcGxpbmVzIGNsaW3DoXRpY2FzICsgc2F6b25hbGlkYWRlIGPDrWNsaWNhICsgZWZlaXRvIGFsZWF0w7NyaW8gcG9yIHJlc2VydmF0w7NyaW8gKyBmaXhlZCBwb3Igc3Vic2lzdGVtYQ0KbTFfZ2FtIDwtIGJhbSgNCiAgZWFyX3Jlc2VydmF0b3Jpb19zdWJzaXN0ZW1hX3Byb3ByaW9fbXdtZXMgfg0KICAgIHMobF9wcmVjaXAsIGsgPSA2KSArDQogICAgcyhsX3RlbXAsICAgayA9IDYpICsNCiAgICBzKGxfaHVtaWRpdHksIGsgPSA2KSArDQogICAgcyhsX3dpbmRfc3BlZWQsIGsgPSA2KSArDQogICAgcyhkb3ksIGJzID0gImNjIiwgayA9IDEyKSArICAgICAgICAgICAgIyBzYXpvbmFsaWRhZGUgY8OtY2xpY2Egbm8gYW5vDQogICAgcyhpZF9yZXNlcnZhdG9yaW8ueCwgYnMgPSAicmUiKSArICAgICAgIyBlZmVpdG8gYWxlYXTDs3JpbyBwb3IgcmVzZXJ2YXTDs3Jpbw0KICAgIG5vbV9zdWJzaXN0ZW1hLngsICAgICAgICAgICAgICAgICAgICAgICAjIGVmZWl0byBmaXhvIHBvciBzdWJzaXN0ZW1hDQogIGRhdGEgICAgID0gcmVzZXJ2LA0KICBtZXRob2QgICA9ICJmUkVNTCIsDQogIGRpc2NyZXRlID0gVFJVRSwNCiAgZmFtaWx5ICAgPSBnYXVzc2lhbigpLA0KICBuYS5hY3Rpb249IG5hLmV4Y2x1ZGUsDQogIGtub3RzICAgID0gbGlzdChkb3kgPSBjKDAuNSwgMzY2LjUpKSwNCiAgc2VsZWN0ICAgPSBUUlVFICAgICAgICAgICAgICAgICAgICAgICAgICAgIyBzaHJpbmthZ2UgcGFyYSBldml0YXIgd2lnZ2xlcw0KKQ0KDQoNCmBgYA0KDQpgYGB7cn0NCnN1bW1hcnkobTFfZ2FtKQ0KZ3RzdW1tYXJ5Ojp0YmxfcmVncmVzc2lvbihtMV9nYW0pDQpzdW1tYXJ5KG0xX2dhbSkNCmdhbS5jaGVjayhtMV9nYW0pICAgICAgICAgICMgcmVzw61kdW9zLCBRUSwgay1pbmRleA0KY29uY3Vydml0eShtMV9nYW0sIGZ1bGw9VFJVRSkNCmBgYA0KDQojIyMgUmVzcG9zdGFzIG1hcmdpbmFpcyAocGxhdXNpYmlsaWRhZGUgZSBpbnRlcnByZXRhw6fDo28pDQpQYXJhIGludGVycHJldGFyIG8gY29tcG9ydGFtZW50byBmdW5jaW9uYWwgZSBhdmFsaWFyIHBsYXVzaWJpbGlkYWRlLCB1c2Ftb3MgZGVyaXZhZGFzIHBhcmNpYWlzLiBDb21vIGBsX3ByZWNpcCA9IGxvZyhwcmVjaXArMSlgLCBhIGRlcml2YWRhIGRlIFwoRVwpIGVtIHJlbGHDp8OjbyBhIGBsX3ByZWNpcGAgw6kgdW1hICoqc2VtaS1lbGFzdGljaWRhZGUgbm8gbsOtdmVsKio6IG8gZWZlaXRvIGRlICsxJSBlbSBwcmVjaXBpdGHDp8OjbyDDqSBhcHJveGltYWRhbWVudGUgXCgweyx9MDEgXHRpbWVzIFxwYXJ0aWFsIEUgLyBccGFydGlhbCBcbG4oXHRleHR7cHJlY2lwfSsxKVwpLg0KDQpgYGB7ciBtMS1kZXJpdmF0aXZlcywgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0NCnBsb3QobTFfZ2FtLCBwYWdlcz00LCBzY2hlbWU9MSwgc2hhZGU9VFJVRSwgc2U9VFJVRSkNCg0KDQpgYGANCmBgYHtyfQ0KZF9wcmVjaXAgPC0gZGVyaXZhdGl2ZXMobTFfZ2FtLCB0ZXJtID0gInMobF9wcmVjaXApIiwgdHlwZSA9ICJjZW50cmFsIikNCmRfcHJlY2lwIDwtIGRfcHJlY2lwICU+JQ0KICBtdXRhdGUoZWZmZWN0X3Blcl8xcGN0ID0gMC4wMSAqIC5kZXJpdmF0aXZlKSANCiAgI3NlbGVjdChkYXRhLCAuZml0dGVkLCAuc2UsIGVmZmVjdF9wZXJfMXBjdCwgbG93ZXIsIHVwcGVyKQ0KDQpzdW1tYXJ5KGRfcHJlY2lwJGVmZmVjdF9wZXJfMXBjdCkNCmBgYA0KQ29tIGJhc2Ugbm9zIGdyw6FmaWNvcyBkZSBlZmVpdG9zIHBhcmNpYWlzLCBkaWFnbsOzc3RpY29zIGRlIHJlc8OtZHVvcyBlIHN1bcOhcmlvIGVzdGF0w61zdGljbyBkbyBHQU0gKGZSRU1MLCBSwrJhaj0wLjc0OyBkZXZpYW5jZSBleHBsYWluZWQ9NzQlKSwgw6kgcG9zc8OtdmVsIHNpbnRldGl6YXIgYSBxdWFsaWRhZGUgZG8gbW9kZWxvIGVtIHRyw6pzIHBhcsOhZ3JhZm9zIHTDqWNuaWNvcyBlIGludGVycHJldGF0aXZvcyDigJQgYWRlcXVhZG9zIHBhcmEgYSBzZcOnw6NvIGRlIHJlc3VsdGFkb3MgbWV0b2RvbMOzZ2ljb3M6DQpPIG1vZGVsbyBoaWRyb2zDs2dpY28g4oCcY2xpbWEtIGVhcuKAnSBhcHJlc2VudGEgZGVzZW1wZW5obyByb2J1c3RvIGUgY29lcmVudGUgY29tIGEgZGluw6JtaWNhIGbDrXNpY2EgZXNwZXJhZGEgZG8gc2lzdGVtYS4gTyBhanVzdGUgYWxjYW7Dp2EgUsKyIGFqdXN0YWRvIGRlIDAsNzQgZSBleHBsaWNhIDc0JSBkYSBkZXZpYW5jZSB0b3RhbCwgaW5kaWNhbmRvIHF1ZSBhcyB2YXJpw6F2ZWlzIGNsaW3DoXRpY2FzIOKAlCBwcmVjaXBpdGHDp8OjbywgdGVtcGVyYXR1cmEsIHVtaWRhZGUgZSB2ZW50byDigJQgY29tYmluYWRhcyDDoCBzYXpvbmFsaWRhZGUgZSBhb3MgZWZlaXRvcyByZWdpb25haXMsIGNhcHR1cmFtIGEgbWFpb3IgcGFydGUgZGEgdmFyaWFiaWxpZGFkZSBkYSBlbmVyZ2lhIGFybWF6ZW5hZGEgKEVBUikuIEEgc2lnbmlmaWPDom5jaWEgZXN0YXTDrXN0aWNhIGRvcyBzcGxpbmVzIMOpIGVsZXZhZGEgKHAgPCAwLjAwMSBwYXJhIHRvZG9zIG9zIHRlcm1vcyksIGUgYSBzdWF2aWRhZGUgZG9zIGVmZWl0b3MgbW9zdHJhIHBhZHLDtWVzIHJlYWxpc3RhczogcHJlY2lwaXRhw6fDo28gZXhlcmNlIGVmZWl0byBwb3NpdGl2byBtb25vdMO0bmljbyBzb2JyZSBhIEVBUjsgdGVtcGVyYXR1cmEgZXhpYmUgZm9ybWF0byBlbSBhcmNvIChlZmVpdG8gw7N0aW1vIHByw7N4aW1vIGEgMjAgwrBDLCBzZWd1aWRvIGRlIHF1ZWRhIG5vcyBleHRyZW1vcyk7IHVtaWRhZGUgZSB2ZW50byB0w6ptIGVmZWl0b3MgbW9kZXJhZG9zLCBtYXMgY29uc2lzdGVudGVzIGNvbSBtZWNhbmlzbW9zIGRlIGV2YXBvdHJhbnNwaXJhw6fDo28gZSByZWNhcmdhLiBPIHRlcm1vIHNhem9uYWwgKGRveSkgcmV2ZWxhIG8gY2ljbG8gaGlkcm9sw7NnaWNvIGFudWFsIGNhcmFjdGVyw61zdGljbyBkb3Mgc3Vic2lzdGVtYXMgYnJhc2lsZWlyb3MuDQoNCk9zIGRpYWduw7NzdGljb3MgZGUgcmVzw61kdW9zIGNvbmZpcm1hbSBxdWUgbyBtb2RlbG8gY2FwdHVyYSBhZGVxdWFkYW1lbnRlIGEgdGVuZMOqbmNpYSBtw6lkaWEgZSBhIHNhem9uYWxpZGFkZSwgbWFzIGV2aWRlbmNpYSBoZXRlcm9nZW5laWRhZGUgZXN0cnV0dXJhbCBlbnRyZSByZWdpbWVzIG9wZXJhY2lvbmFpcy4gTyBncsOhZmljbyBkZSByZXPDrWR1b3MgdmVyc3VzIHZhbG9yZXMgYWp1c3RhZG9zIG1vc3RyYSB0csOqcyBmYWl4YXMgZGVuc2FzLCBhc3NvY2lhZGFzIGEgZGlmZXJlbnRlcyBuw612ZWlzIGRlIGFybWF6ZW5hbWVudG8gKGJhaXhvLCBtw6lkaW8gZSBhbHRvKSwgc3VnZXJpbmRvIGEgcHJlc2Vuw6dhIGRlIGxpbWl0ZXMgZsOtc2ljb3MgZGUgb3BlcmHDp8OjbyBvdSB0cmFuc2nDp8O1ZXMgZW50cmUgZXN0w6FnaW9zIGRlIGVuY2hpbWVudG8gZSBlc3ZhemlhbWVudG8gZG9zIHJlc2VydmF0w7NyaW9zLiBPIGhpc3RvZ3JhbWEgZGUgcmVzw61kdW9zIMOpIGFwcm94aW1hZGFtZW50ZSBzaW3DqXRyaWNvIGUgY2VudHJhZG8gZW0gemVybywgZSBvIFFRLXBsb3QgaW5kaWNhIGxldmUgZGVzdmlvIG5hcyBjYXVkYXMsIG8gcXVlIMOpIGVzcGVyYWRvIGVtIHPDqXJpZXMgYW1iaWVudGFpcyBkZSBncmFuZGUgYW1wbGl0dWRlLiBBIGhvbW9nZW5laWRhZGUgZGUgdmFyacOibmNpYSDDqSBzYXRpc2ZhdMOzcmlhLCBzZW0gcGFkcsO1ZXMgc2lzdGVtw6F0aWNvcyBkZSBhdXRvY29ycmVsYcOnw6NvLCByZWZvcsOnYW5kbyBhIGFkZXF1YcOnw6NvIGRvIHVzbyBkYSBmYW3DrWxpYSBnYXVzc2lhbmEgY29tIGxpbmsgaWRlbnRpZGFkZS4NCg0KUG9yIGZpbSwgb3MgZWZlaXRvcyBhbGVhdMOzcmlvcyBwb3IgcmVzZXJ2YXTDs3JpbyBtb3N0cmFyYW0gYW1wbGEgZGlzcGVyc8OjbywgcmVmbGV0aW5kbyBkaWZlcmVuw6dhcyBlc3RydXR1cmFpcyBkZSBjYXBhY2lkYWRlIGUgb3BlcmHDp8OjbyBlbnRyZSB1c2luYXMuIEEgc3VhdmlkYWRlIGRvcyBzcGxpbmVzIGZvaSBhZGVxdWFkYSAoay1pbmRleCA+IDAuNiBwYXJhIHRvZG9zIG9zIHRlcm1vcyksIHNlbSBldmlkw6puY2lhcyBkZSBzdWJkaW1lbnNpb25hbWVudG8gZGUgY29tcGxleGlkYWRlLCBlIGEgYXVzw6puY2lhIGRlIGNvbmNvcnLDqm5jaWEgKGNvbmN1cnZpdHkpIHJlbGV2YW50ZSBpbmRpY2EgYmFpeGEgY29saW5lYXJpZGFkZSBlbnRyZSBvcyBlZmVpdG9zIGNsaW3DoXRpY29zLiBFbSBjb25qdW50bywgZXNzZXMgcmVzdWx0YWRvcyBzdXN0ZW50YW0gYSBwbGF1c2liaWxpZGFkZSBlc3RhdMOtc3RpY2EgZSBmw61zaWNhIGRvIG1vZGVsbyBjb21vIGJhc2VsaW5lIGNsaW3DoXRpY28gYXVkaXTDoXZlbC4gQXMgcHJpbmNpcGFpcyBsaW1pdGHDp8O1ZXMgcmVzaWRlbSBuYSBzdWF2aXphw6fDo28gZGUgZXh0cmVtb3MgaGlkcm9sw7NnaWNvcyBlIG5hIGxldmUgbsOjby1ub3JtYWxpZGFkZSBkb3MgcmVzw61kdW9zLCBhc3BlY3RvcyBjb211bnMgZW0gbW9kZWxvcyBhZ3JlZ2Fkb3MgZGUgZ3JhbmRlcyBzaXN0ZW1hcyBlIHF1ZSBwb2RlbSBzZXIgdHJhdGFkb3MgbmFzIGV0YXBhcyBzdWJzZXF1ZW50ZXMgY29tIGNvbnRyYWZhY3R1YWlzIGUgcHJvcGFnYcOnw6NvIGRlIGluY2VydGV6YS4NCg0KT3MgKiplZmVpdG9zIHBhcmNpYWlzKiogZXN0aW1hZG9zIHBlbG8gbW9kZWxvIGNvbmZpcm1hbSBwYWRyw7VlcyBjbGltw6F0aWNvcyBwbGF1c8OtdmVpcyBlIGZpc2ljYW1lbnRlIGNvZXJlbnRlcy4gQSBwcmVjaXBpdGHDp8OjbyBhcHJlc2VudGEgdW0gZWZlaXRvIG1vbm90b25pY2FtZW50ZSBjcmVzY2VudGUgc29icmUgYSBlbmVyZ2lhIGFybWF6ZW5hZGEsIGluZGljYW5kbyBxdWUgYXVtZW50b3MgYWN1bXVsYWRvcyBkZSBjaHV2YSB0w6ptIGltcGFjdG8gcG9zaXRpdm8gcXVhc2UgbGluZWFyIGF0w6kgbyBsaW1pdGUgc3VwZXJpb3Igb2JzZXJ2YWRvLCBzZW0gc2luYWlzIGRlIHNhdHVyYcOnw6NvIOKAlCB1bSByZXN1bHRhZG8gY29tcGF0w612ZWwgY29tIGEgcHJlZG9taW7Dom5jaWEgZGUgZ3JhbmRlcyByZXNlcnZhdMOzcmlvcyBkZSByZWd1bGFyaXphw6fDo28gbm8gc2lzdGVtYS4gQSB0ZW1wZXJhdHVyYSwgcG9yIHN1YSB2ZXosIGV4aWJlIHVtYSByZWxhw6fDo28gZW0gZm9ybWEgZGUgYXJjbzogb3MgbsOtdmVpcyBpbnRlcm1lZGnDoXJpb3MgKGVtIHRvcm5vIGRlIDIwIMKwQykgZXN0w6NvIGFzc29jaWFkb3MgYW8gbWFpb3IgYXJtYXplbmFtZW50bywgZW5xdWFudG8gdGVtcGVyYXR1cmFzIGV4dHJlbWFzIHJlZHV6ZW0gbyBzYWxkbyBlbmVyZ8OpdGljbywgcmVmbGV0aW5kbyBvIHBhcGVsIGRhIGV2YXBvcmHDp8OjbyBlIGRhIGVmaWNpw6puY2lhIGRvIGNpY2xvIGhpZHJvbMOzZ2ljby4gQSB1bWlkYWRlIG1vc3RyYSBsZXZlIGVmZWl0byBwb3NpdGl2byBhdMOpIGNlcnRvIHBvbnRvLCBzZWd1aWRvIGRlIHJldmVyc8Ojbywgc3VnZXJpbmRvIGludGVyYcOnw6NvIGNvbSByZWdpbWVzIGRlIGNodXZhIHBlcnNpc3RlbnRlLCBlbnF1YW50byBhIHZlbG9jaWRhZGUgZG8gdmVudG8gYXByZXNlbnRhIHVtIGVmZWl0byBuZWdhdGl2byBzdWF2ZSwgcG9zc2l2ZWxtZW50ZSBsaWdhZG8gw6AgbWFpb3IgcGVyZGEgcG9yIGV2YXBvdHJhbnNwaXJhw6fDo28gZSBhbyB0cmFuc3BvcnRlIGRlIG1hc3NhcyBzZWNhcy4gTyBjb21wb25lbnRlIHNhem9uYWwgKGRveSkgcmV2ZWxhIG8gY2ljbG8gYW51YWwgdMOtcGljbyBkbyByZWdpbWUgcGx1dmlhbCBicmFzaWxlaXJvLCBjb20gcGljb3MgZW50cmUgb3MgZGlhcyAxMDDigJMxNTAgKG91dG9ubykgZSBtw61uaW1vcyBwcsOzeGltb3MgYW8gZmluYWwgZG8gYW5vLiBQb3IgZmltLCBvcyBlZmVpdG9zIGFsZWF0w7NyaW9zIHBvciByZXNlcnZhdMOzcmlvIG1vc3RyYW0gaGV0ZXJvZ2VuZWlkYWRlIGV4cHJlc3NpdmEsIGluZGljYW5kbyBxdWUgZGlmZXJlbsOnYXMgZXN0cnV0dXJhaXMgZGUgY2FwYWNpZGFkZSBlIGxvY2FsaXphw6fDo28gY29uZGljaW9uYW0gYSByZXNwb3N0YSBjbGltw6F0aWNhIOKAlCB1bSBhY2hhZG8gcXVlIHJlZm9yw6dhIGEgbmVjZXNzaWRhZGUgZGUgYWJvcmRhZ2VucyByZWdpb25hbGl6YWRhcyBuYXMgZXRhcGFzIHNlZ3VpbnRlcyBkYSBtb2RlbGFnZW0uDQoNCg0KDQpgYGB7cn0NCiNzYXZlUkRTKG0xX2dhbSwgIm0xX2dhbS5yZHMiKQ0KI3JlYWRSRFMoIm0xX2dhbS5yZHMiKSAtPiBtMV9nYW0NCg0KYGBgDQoNCiMjIyMgUHJlZGnDp8O1ZXMgZmFjdHVhbCB2cy4gY29udHJhZmFjdHVhbCAoYmFzZWxpbmUgMjAwMeKAkzIwMDUpDQpDb25zdHJ1w61tb3MgbyBjb250cmFmYWN0dWFsIGNsaW3DoXRpY28gZml4YW5kbyBjbGltYSBubyAqKm3DqWRpbyBtZW5zYWwgMjAwMeKAkzIwMDUqKiBwb3IgcmVzZXJ2YXTDs3JpbyAob3UgcG9yIHN1YnNpc3RlbWEsIGNhc28gcHJlZmlyYSkgZSBtYW50ZW5kbyBvcyBkZW1haXMgY29udHJvbGVzIG9ic2VydmFkb3MuDQoNCg0KDQpgYGB7cn0NCiMgQmFzZWxpbmUgY2xpbcOhdGljbyBwb3IgcmVzZXJ2YXTDs3JpbyBlIG3DqnMgKDIwMDHigJMyMDA1KTsgYWp1c3RlIHNlIHByZWZlcmlyIHBvciBzdWJzaXN0ZW1hDQpjbGltX2Jhc2VsaW5lIDwtIHJlc2VydiAlPiUNCiAgZmlsdGVyKHllYXIoZGF0ZSkgPj0gMjAwMSwgeWVhcihkYXRlKSA8PSAyMDA1KSAlPiUNCiAgZ3JvdXBfYnkoaWRfcmVzZXJ2YXRvcmlvLngsIGRveSkgJT4lDQogIHN1bW1hcmlzZSgNCiAgICBsX3ByZWNpcF9ibCA9IG1lYW4obF9wcmVjaXAsIG5hLnJtID0gVFJVRSksDQogICAgbF90ZW1wX2JsICAgPSBtZWFuKGxfdGVtcCwgICBuYS5ybSA9IFRSVUUpLA0KICAgIGxfaHVtaWRpdHlfYmwgPSBtZWFuKGxfaHVtaWRpdHksIG5hLnJtID0gVFJVRSksDQogICAgbF93aW5kX3NwZWVkX2JsICAgICA9IG1lYW4obF93aW5kX3NwZWVkLCBuYS5ybSA9IFRSVUUpLA0KICAgIC5ncm91cHMgPSAiZHJvcCINCiAgKQ0KDQojIG5ld2RhdGEgZmFjdHVhbCAob2JzZXJ2YWRvKSBlIGNvbnRyYWZhY3R1YWwgKGNsaW1hIGZpeG8gbm8gYmFzZWxpbmUpDQpuZF9vYnMgPC0gcmVzZXJ2ICMlPiUgdW5ncm91cCgpICU+JSANCiAjc2VsZWN0KGlkX3Jlc2VydmF0b3Jpby54LCBub21fc3Vic2lzdGVtYS54LCBkYXRlLCBkb3ksIG1vbnRoLA0KICAjICAgICAgIGxfcHJlY2lwLCBsX3RlbXAsIGxfaHVtaWRpdHksIGxfd2luZF9zcGVlZCkNCg0KbmRfY2YgPC0gcmVzZXJ2ICU+JQ0KICBsZWZ0X2pvaW4oY2xpbV9iYXNlbGluZSwgYnkgPSBjKCJpZF9yZXNlcnZhdG9yaW8ueCIsImRveSIpKSAlPiUNCiAgbXV0YXRlKA0KICAgIGxfcHJlY2lwID0gbF9wcmVjaXBfYmwsDQogICAgbF90ZW1wICAgPSBsX3RlbXBfYmwsDQogICAgbF9odW1pZGl0eSA9IGxfaHVtaWRpdHlfYmwsDQogICAgbF93aW5kX3NwZWVkPSBsX3dpbmRfc3BlZWRfYmwNCiAgKSAjJT4lDQogICNzZWxlY3QobmFtZXMocmVzZXJ2KSkNCg0KIyBQcmVkacOnw7VlcyBubyBuw612ZWwgKE1Xwrdtw6pzKQ0KcmVzZXJ2JGVhcl9oYXRfb2JzIDwtIHByZWRpY3QobTFfZ2FtLCBuZXdkYXRhID0gcmVzZXJ2LCB0eXBlID0gInJlc3BvbnNlIikNCnJlc2VydiRlYXJfaGF0X2NmICA8LSBwcmVkaWN0KG0xX2dhbSwgbmV3ZGF0YSA9IG5kX2NmLCAgdHlwZSA9ICJyZXNwb25zZSIpDQoNCiMgUGVuYWxpZGFkZSBjbGltw6F0aWNhIG5vIEVBUiAocG9udHVhbCkNCnJlc2VydiRkZWx0YV9lYXJfaGF0IDwtIHJlc2VydiRlYXJfaGF0X29icyAtIHJlc2VydiRlYXJfaGF0X2NmDQpkZWx0YV9lYXJfaGF0IDwtIHJlc2VydiRlYXJfaGF0X29icyAtIHJlc2VydiRlYXJfaGF0X2NmDQpgYGANCg0KIyMgMy4xLjUgUHJvcGFnYcOnw6NvIGRlIEluY2VydGV6YQ0KUGFyYSBxdWFudGlmaWNhciBhIGluY2VydGV6YSBhc3NvY2lhZGEgw6BzIGVzdGltYXRpdmFzIGRlIHBlbmFsaWRhZGUgY2xpbcOhdGljYSAozpRFQVIpLCBmb3JhbSBhcGxpY2Fkb3MgZG9pcyBtw6l0b2RvcyBjb21wbGVtZW50YXJlczogbyBEZWx0YSBNZXRob2QgYW5hbMOtdGljbyBlIGEgU2ltdWxhw6fDo28gUGFyYW3DqXRyaWNhIE11bHRpdmFyaWFkYS4gTyBwcmltZWlybyBmb3JuZWNlIGludGVydmFsb3MgZGUgY29uZmlhbsOnYSBwb250dWFpcyBiYXNlYWRvcyBuYSBtYXRyaXogZGUgY292YXJpw6JuY2lhIGRvcyBjb2VmaWNpZW50ZXMgZG8gbW9kZWxvOyBvIHNlZ3VuZG8gcGVybWl0ZSBwcm9wYWdhciBpbnRlZ3JhbG1lbnRlIGEgaW5jZXJ0ZXphIHBhcmFtw6l0cmljYSBhbyBsb25nbyBkYSBjYWRlaWEgZGUgZXN0aW1hw6fDo28sIGdlcmFuZG8gZGlzdHJpYnVpw6fDtWVzIGVtcMOtcmljYXMgcGFyYSBjYWRhIHN1YnNpc3RlbWEgZSBhbm8uDQoNCk5vIERlbHRhIE1ldGhvZCwgYSBpbmNlcnRlemEgw6kgY2FsY3VsYWRhIHBlbGEgbWF0cml6IGRlIGRlc2VuaG8gZG8gbW9kZWxvICggJCBYX3tvYnN9IC0gWF97Y2Z9JCksIG11bHRpcGxpY2FkYSBwZWxhIG1hdHJpeiBkZSBjb3ZhcmnDom5jaWEgZG9zIHBhcsOibWV0cm9zICgkVl/wnZu9JCksIGNvbmZvcm1lICRWYXIozpRFKT0gWChWX/Cdm70pWCckLiBFc3NhIGFib3JkYWdlbSBmb3JuZWNlIGVzdGltYXRpdmFzIGNvbnNpc3RlbnRlcyBwYXJhIGludGVydmFsb3MgZGUgOTUlIGRlIGNvbmZpYW7Dp2EgZSBwZXJtaXRlIGFncmVnYXIgcmVzdWx0YWRvcyBwcmVzZXJ2YW5kbyBhcyBjb3ZhcmnDom5jaWFzIGVudHJlIG9ic2VydmHDp8O1ZXMuIE8gbcOpdG9kbyDDqSBjb21wdXRhY2lvbmFsbWVudGUgZWZpY2llbnRlIGUgw7p0aWwgcGFyYSBnZXJhciBpbnRlcnZhbG9zIGFuYWzDrXRpY29zIGNvbXBhcsOhdmVpcyBlbnRyZSBzdWJzaXN0ZW1hcy4NCg0KQSBTaW11bGHDp8OjbyBQYXJhbcOpdHJpY2EgYW1wbGlhIGVzc2EgYWJvcmRhZ2VtIGFvIGFtb3N0cmFyIG1pbGhhcmVzIGRlIHZldG9yZXMgZGUgY29lZmljaWVudGVzICgNCiTwnZu9Xnso8J2RoCl94oi88J2RgShcaGF0e1xiZXRhfSzwnZGJ8J2bvSkkIGUgcmVjYWxjdWxhciAkzpQg8J2QuPCdkLTwnZGFXnso8J2RoCl9JCBwYXJhIGNhZGEgYW1vc3RyYS4gQSBhZ3JlZ2HDp8OjbyBkb3MgcmVzdWx0YWRvcyBwb3Igc3Vic2lzdGVtYSBlIGFubyBmb3JuZWNlIGRpc3RyaWJ1acOnw7VlcyBlbXDDrXJpY2FzIGRhIHBlbmFsaWRhZGUgY2xpbcOhdGljYSwgZXhwcmVzc2FzIHBvciBmYW4gY2hhcnRzIChGaWd1cmEgYWJhaXhvKS4gT3MgcmVzdWx0YWRvcyBpbmRpY2FtIHRlbmTDqm5jaWEgbmVnYXRpdmEgY3Jlc2NlbnRlIGRhIGVuZXJnaWEgYXJtYXplbmFkYSBhanVzdGFkYSBhbyBjbGltYSBtw6lkaW8sIGNvbSBmb3J0ZSBxdWVkYSBhcMOzcyAyMDEwIGUgcGljb3MgZGUgaW5jZXJ0ZXphIGVtIDIwMTTigJMyMDE2LiBBcyByZWdpw7VlcyBTdWRlc3RlIGUgU3VsIGNvbmNlbnRyYW0gb3MgbWFpb3JlcyBkw6lmaWNpdHMgbcOpZGlvcyAoYXTDqSDigJM1IGUg4oCTMSBtaWxow7VlcyBkZSBNV8K3bcOqcywgcmVzcGVjdGl2YW1lbnRlKSwgZW5xdWFudG8gTm9yZGVzdGUgZSBOb3J0ZSBhcHJlc2VudGFtIHBlbmFsaWRhZGVzIG1lbm9yZXMsIHBvcsOpbSBjb20gYXVtZW50byBwcm9ncmVzc2l2byBhbyBmaW5hbCBkYSBzw6lyaWUuIEVzc2EgY29uc2lzdMOqbmNpYSBlbnRyZSBvcyBkb2lzIG3DqXRvZG9zIGNvbmZpcm1hIGEgcm9idXN0ZXogZXN0YXTDrXN0aWNhIGRvIG1vZGVsbyBlIGVzdGFiZWxlY2UgdW1hIGJhc2UgY29uZmnDoXZlbCBwYXJhIGEgZXRhcGEgc2VndWludGUgZGUgcHJvcGFnYcOnw6NvIGRlIGluY2VydGV6YSBuYSBnZXJhw6fDo28gaGlkcmVsw6l0cmljYS4NCg0KDQoNCiMjIyMgSW5jZXJ0ZXphIChtw6l0b2RvIDQ6ICoqRGVsdGEgbWV0aG9kKiogYW5hbMOtdGljbykNCkVzdGltYW1vcyBJQ3MgcGFyYSBcKFxEZWx0YSBFQVJcKSB2aWEgbWF0cml6IGRlIGRlc2VuaG8gbm8gKipsaW5rKiogKGFxdWksIGlkZW50aXR5IOKHkiBqw6Egw6kgbsOtdmVsKS4gQWdyZWdhw6fDtWVzIHBvciBhbm8vc3Vic2lzdGVtYSBkZXZlbSBwcmVzZXJ2YXIgYSBjb3ZhcmnDom5jaWEuDQpgYGB7ciBtMS1kZWx0YS1tZXRob2QsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9DQpWcCAgICAgIDwtIHZjb3YobTFfZ2FtKSAgIyBjb3ZhcmnDom5jaWEgZG9zIGNvZWZpY2llbnRlcw0KWF9vYnMgICA8LSBwcmVkaWN0KG0xX2dhbSwgbmV3ZGF0YSA9IG5kX29icywgdHlwZSA9ICJscG1hdHJpeCIpDQpYX2NmICAgIDwtIHByZWRpY3QobTFfZ2FtLCBuZXdkYXRhID0gbmRfY2YsICB0eXBlID0gImxwbWF0cml4IikNClhfZGlmZiAgPC0gWF9vYnMgLSBYX2NmDQoNCiMgRVAgcG9yIG9ic2VydmHDp8Ojbw0KdmFyX2RlbHRhIDwtIHJvd1N1bXMoKFhfZGlmZiAlKiUgVnApICogWF9kaWZmKQ0Kc2VfZGVsdGEgIDwtIHNxcnQocG1heCh2YXJfZGVsdGEsIDApKQ0KeiAgICAgICAgIDwtIHFub3JtKDAuOTc1KQ0KDQpkZWx0YV9sd3IgPC0gcmVzZXJ2JGRlbHRhX2Vhcl9oYXQgLSB6ICogc2VfZGVsdGENCmRlbHRhX3VwciA8LSByZXNlcnYkZGVsdGFfZWFyX2hhdCArIHogKiBzZV9kZWx0YQ0KcmVzZXJ2JGRlbHRhX2Vhcl91cHI8LWRlbHRhX3Vwcg0KcmVzZXJ2JGRlbHRhX2Vhcl9sd3I8LWRlbHRhX2x3cg0KbTFfZGVsdGEgPC0gbmRfb2JzICU+JQ0KICB0cmFuc211dGUoDQogICAgZGF0ZSwgbm9tX3N1YnNpc3RlbWEueCwNCiAgICBkZWx0YV9oYXQgPSBkZWx0YV9lYXJfaGF0LA0KICAgIGRlbHRhX3NlICA9IHNlX2RlbHRhLA0KICAgIGRlbHRhX2x3ciA9IGRlbHRhX2x3ciwNCiAgICBkZWx0YV91cHIgPSBkZWx0YV91cHINCiAgKQ0KDQojIEFncmVnYXIgcG9yIGFuby9zdWJzaXN0ZW1hIHByZXNlcnZhbmRvIGNvdmFyacOibmNpYSAoY29tYmluYcOnw6NvIGxpbmVhcikNCmxpYnJhcnkoZGF0YS50YWJsZSkNCmR0IDwtIGFzLmRhdGEudGFibGUobmRfb2JzKVssIC4oZGF0ZSwgbm9tX3N1YnNpc3RlbWEueCldDQpkdFssIHllYXIgOj0geWVhcihkYXRlKV0NCg0KIyBWZXRvciBzX2cgPSBzb21hIGRhcyBsaW5oYXMgZGUgWF9kaWZmIG5vIGdydXBvIChhbm8sIHN1YnNpc3RlbWEpDQpncm91cHMgPC0gdW5pcXVlKGR0WywgLih5ZWFyLCBub21fc3Vic2lzdGVtYS54KV0pDQpTIDwtIGxhcHBseSgxOm5yb3coZ3JvdXBzKSwgZnVuY3Rpb24oZyl7DQogIGlkeCA8LSB3aGljaChkdCR5ZWFyID09IGdyb3VwcyR5ZWFyW2ddICYgZHQkbm9tX3N1YnNpc3RlbWEueCA9PSBncm91cHMkbm9tX3N1YnNpc3RlbWEueFtnXSkNCiAgY29sU3VtcyhYX2RpZmZbaWR4LCAsIGRyb3AgPSBGQUxTRV0pDQp9KQ0KDQphZ2dfbWVhbiA8LSBzYXBwbHkoMTpucm93KGdyb3VwcyksIGZ1bmN0aW9uKGcpew0KICBzdW0ocmVzZXJ2JGRlbHRhX2Vhcl9oYXRbZHQkeWVhciA9PSBncm91cHMkeWVhcltnXSAmIGR0JG5vbV9zdWJzaXN0ZW1hLnggPT0gZ3JvdXBzJG5vbV9zdWJzaXN0ZW1hLnhbZ11dLCBuYS5ybSA9IFRSVUUpDQp9KQ0KYWdnX3ZhciAgPC0gc2FwcGx5KFMsIGZ1bmN0aW9uKHN2KSBhcy5udW1lcmljKHQoc3YpICUqJSBWcCAlKiUgc3YpKQ0KYWdnX3NlICAgPC0gc3FydChwbWF4KGFnZ192YXIsIDApKQ0KDQptMV9kZWx0YV9hZ2cgPC0gY2JpbmQoZ3JvdXBzLA0KICBkZWx0YV9tZWFuID0gYWdnX21lYW4sDQogIGRlbHRhX2x3ciAgPSBhZ2dfbWVhbiAtIHogKiBhZ2dfc2UsDQogIGRlbHRhX3VwciAgPSBhZ2dfbWVhbiArIHogKiBhZ2dfc2UNCikNCmBgYA0KDQojIyMjIEluY2VydGV6YSAobcOpdG9kbyAxOiAqKlNpbXVsYcOnw6NvIHBhcmFtw6l0cmljYSoqIGVuY2FkZcOhdmVsKQ0KQW1vc3RyYW1vcyBvcyBjb2VmaWNpZW50ZXMgZGEgZGlzdHJpYnVpw6fDo28gbm9ybWFsIG11bHRpdmFyaWFkYSBlIHJlY2FsY3VsYW1vcyBcKFxEZWx0YSBFQVJeeyhzKX1cKS4gRXNzZSBvYmpldG8gc2Vyw6EgYSAqKmVudHJhZGEgcHJvYmFiaWzDrXN0aWNhKiogcGFyYSBvIEdBTSAxLg0KDQpgYGB7ciBtMS1tb250ZWNhcmxvLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQ0KbGlicmFyeShNQVNTKQ0KbnNpbSA8LSAyMDAwDQpzZXQuc2VlZCgyMDI1MTAxMCkNCg0KYmV0YV9kcmF3cyA8LSBNQVNTOjptdnJub3JtKG4gPSBuc2ltLCBtdSA9IGNvZWYobTFfZ2FtKSwgU2lnbWEgPSBWcCkNCg0KIyBQcsOpLWPDoWxjdWxvIHBhcmEgZWZpY2nDqm5jaWENCkQgPC0gWF9kaWZmICAgICAgICAgICAgICMgTiB4IHANCiMgzpRFQVIgcG9yIHNpbXVsYcOnw6NvOiBjYWRhIGNvbHVuYSDDqSB1bWEgc2ltLCBjYWRhIGxpbmhhIHVtYSBvYnNlcnZhw6fDo28NCmRlbHRhX3NpbXMgPC0gRCAlKiUgdChiZXRhX2RyYXdzKSAgICMgKE4geCBuc2ltKQ0KDQojIEFncmVnYXIgcG9yIGFuby9zdWJzaXN0ZW1hIGVtIGNhZGEgc2ltDQpkdCRnaWQgPC0gLkdSUDsgZHRbLCBnaWQgOj0gLkdSUCwgYnkgPSAuKHllYXIsIG5vbV9zdWJzaXN0ZW1hLngpXQ0KRyA8LSBtYXgoZHQkZ2lkKQ0KDQphZ2dfbWF0IDwtIG1hdHJpeChOQV9yZWFsXywgbnJvdyA9IEcsIG5jb2wgPSBuc2ltKQ0KZm9yIChnIGluIDE6Rykgew0KICBpZHggPC0gd2hpY2goZHQkZ2lkID09IGcpDQogIGFnZ19tYXRbZywgXSA8LSBjb2xTdW1zKGRlbHRhX3NpbXNbaWR4LCAsIGRyb3AgPSBGQUxTRV0sIG5hLnJtID0gVFJVRSkNCn0NCg0KbTFfc2ltX2FnZyA8LSBjYmluZChncm91cHMsDQogIG1lYW4gPSByb3dNZWFucyhhZ2dfbWF0KSwNCiAgbHdyICA9IGFwcGx5KGFnZ19tYXQsIDEsIHF1YW50aWxlLCAwLjAyNSksDQogIHVwciAgPSBhcHBseShhZ2dfbWF0LCAxLCBxdWFudGlsZSwgMC45NzUpDQopDQoNCmBgYA0KIyMjIyBWaXN1YWxpemHDp8OjbyByw6FwaWRhIChwdWJsaWNhw6fDo28pDQpSaWJib25zIChEZWx0YSkgZSBmYW4gY2hhcnRzIChNQykgcGFkcm9uaXphZG9zLg0KDQoNCmBgYHtyIG0xLXBsb3RzLCBmaWcuaGVpZ2h0PTYsIGZpZy53aWR0aD0xMiwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0NCmxpYnJhcnkoZ2dwbG90MikNCg0KIyBSaWJib24gKERlbHRhKQ0KbTFfZGVsdGFfYWdnICU+JQ0KICBnZ3Bsb3QoYWVzKHggPSB5ZWFyLCB5ID0gZGVsdGFfbWVhbi8xMDAwKSkgKw0KICBnZW9tX3JpYmJvbihhZXMoeW1pbiA9IGRlbHRhX2x3ci8xMDAwLCB5bWF4ID0gZGVsdGFfdXByLzEwMDApLCBhbHBoYSA9IC4yNSwgZmlsbCA9ICJmaXJlYnJpY2siKSArDQogIGdlb21fbGluZSgpICsNCiAgZmFjZXRfd3JhcCh+bm9tX3N1YnNpc3RlbWEueCwgc2NhbGVzID0gImZyZWVfeSIpICsNCiAgbGFicyh0aXRsZSA9ICJDbGltYXRlIHBlbmFsdHkgb24gc3RvcmVkIGVuZXJneSAozpRFQVIpIOKAlCBEZWx0YSBtZXRob2QiLA0KICAgICAgIHkgPSAizpRFQVIgKEdXwrdtb250aCkiLCB4ID0gIlllYXIiKSArDQogIHRoZW1lX21pbmltYWwoKQ0KDQojIEZhbiBjaGFydCAoTUMpDQptMV9zaW1fYWdnICU+JQ0KICBnZ3Bsb3QoYWVzKHggPSB5ZWFyLCB5ID0gbWVhbi8xMDAwKSkgKw0KICBnZW9tX3JpYmJvbihhZXMoeW1pbiA9IGx3ci8xMDAwLCB5bWF4ID0gdXByLzEwMDApLCBhbHBoYSA9IC4yNSwgZmlsbCA9ICJzdGVlbGJsdWUiKSArDQogIGdlb21fbGluZSgpICsNCiAgZmFjZXRfd3JhcCh+bm9tX3N1YnNpc3RlbWEueCwgc2NhbGVzID0gImZyZWVfeSIpICsNCiAgbGFicyh0aXRsZSA9ICJDbGltYXRlIHBlbmFsdHkgb24gc3RvcmVkIGVuZXJneSAozpRFQVIpIOKAlCBQYXJhbWV0cmljIHNpbXVsYXRpb24iLA0KICAgICAgIHkgPSAizpRFQVIgKEdXwrdtb250aCkiLCB4ID0gIlllYXIiKSArDQogIHRoZW1lX21pbmltYWwoKQ0KYGBgDQpQZW5hbGlkYWRlIGNsaW3DoXRpY2EgYWdyZWdhZGEgZSBpbnRlcnZhbG9zIGRlIGNvbmZpYW7Dp2ENCmBgYHtyfQ0KbTFfc3VtbWFyeSA8LSBtMV9zaW1fYWdnICU+JQ0KICBncm91cF9ieShub21fc3Vic2lzdGVtYS54KSAlPiUNCiAgc3VtbWFyaXNlKA0KICAgIG1lYW5fcGVuYWx0eSA9IG1lYW4obWVhbiwgbmEucm0gPSBUUlVFKSwNCiAgICBsd3JfOTUgPSBtZWFuKGx3ciwgbmEucm0gPSBUUlVFKSwNCiAgICB1cHJfOTUgPSBtZWFuKHVwciwgbmEucm0gPSBUUlVFKSwNCiAgICBzZF9wZW5hbHR5ID0gc2QobWVhbiwgbmEucm0gPSBUUlVFKSwNCiAgICAuZ3JvdXBzID0gImRyb3AiDQogICkNCg0KIyBDb252ZXJ0ZW5kbyBwYXJhIEdXaC9hbm8gcGFyYSBpbnRlcnByZXRhw6fDo28NCm0xX3N1bW1hcnkgPC0gbTFfc3VtbWFyeSAlPiUNCiAgbXV0YXRlKA0KICAgIG1lYW5fR1doID0gbWVhbl9wZW5hbHR5IC8gMTAwMCwNCiAgICBsd3JfR1doICA9IGx3cl85NSAvIDEwMDAsDQogICAgdXByX0dXaCAgPSB1cHJfOTUgLyAxMDAwLA0KICApICMlPiUgc2VsZWN0KC1tZWFuX3BlbmFsdHksIC1sd3JfOTUsIC11cHJfOTUpDQoNCiMgVGFiZWxhIGZvcm1hdGFkYSAocHVibGljYcOnw6NvKQ0KbGlicmFyeShndCkNCm0xX3N1bW1hcnlbLGMoIm5vbV9zdWJzaXN0ZW1hLngiLCJtZWFuX0dXaCIsImx3cl9HV2giLCAidXByX0dXaCIpXSAlPiUgamFuaXRvcjo6YWRvcm5fdG90YWxzKCkgJT4lIA0KICBndCgpICU+JQ0KICBmbXRfbnVtYmVyKGNvbHVtbnMgPSAyOjQsIGRlY2ltYWxzID0gMSkgJT4lDQogIGNvbHNfbGFiZWwoDQogICAgbm9tX3N1YnNpc3RlbWEueCA9ICJTdWJzeXN0ZW0iLA0KICAgIG1lYW5fR1doID0gIk1lYW4gzpRFQVIgKEdXaCkiLA0KICAgIGx3cl9HV2ggID0gIkxvd2VyIDk1JSIsDQogICAgdXByX0dXaCAgPSAiVXBwZXIgOTUlIiwNCiAgKSAlPiUNCiAgdGFiX2hlYWRlcigNCiAgICB0aXRsZSA9IG1kKCIqKkFnZ3JlZ2F0ZSBjbGltYXRlIHBlbmFsdHkgb24gc3RvcmVkIGVuZXJneSAoMjAwMeKAkzIwMTgpKioiKSwNCiAgICBzdWJ0aXRsZSA9ICJTaW11bGF0ZWQgbWVhbiBhbmQgOTUlIGNvbmZpZGVuY2UgaW50ZXJ2YWxzIHBlciBzdWJzeXN0ZW0iDQogICkNCmBgYA0KQSBUYWJlbGEgYXByZXNlbnRhIGEgKipwZW5hbGlkYWRlIGNsaW3DoXRpY2EgbcOpZGlhIHNvYnJlIGEgZW5lcmdpYSBhcm1hemVuYWRhICjOlEVBUikqKiBubyBwZXLDrW9kbyAyMDAx4oCTMjAxOCwgYWdyZWdhZGEgcG9yIHN1YnNpc3RlbWEuIE9zIHZhbG9yZXMgZm9yYW0gZXN0aW1hZG9zIGEgcGFydGlyIGRhcyBkaXN0cmlidWnDp8O1ZXMgb2J0aWRhcyB2aWEgc2ltdWxhw6fDo28gcGFyYW3DqXRyaWNhIGRlIDIuMDAwIHNvcnRlaW9zIGRhIG1hdHJpeiBkZSBjb3ZhcmnDom5jaWEgZG9zIGNvZWZpY2llbnRlcyBkbyBtb2RlbG8gaGlkcm9sw7NnaWNvLiBBcyBwZW5hbGlkYWRlcyBtw6lkaWFzIGZvcmFtIGV4cHJlc3NhcyBlbSBnaWdhd2F0dHMtbcOqcyAoR1dowrdtb250aCksIGNvbSBpbnRlcnZhbG9zIGRlIGNvbmZpYW7Dp2EgZGUgOTUlIGNvbSB1bSB0b3RhbCBkZSAqKuKAkzEsNjA2LjMgKElDOTUlOiDiiJIxLDc0Ni4yO+KIkjEsNDcwLjIpICBkZSBHV2guDQoNCk9zIHJlc3VsdGFkb3MgaW5kaWNhbSBxdWUgbyAqKnN1YnNpc3RlbWEgU3VkZXN0ZSoqIGNvbmNlbnRyYSBvIG1haW9yIGTDqWZpY2l0IG3DqWRpbyBkZSBhcm1hemVuYW1lbnRvLCBlc3RpbWFkbyBlbSBhcHJveGltYWRhbWVudGUgKiriiJIxLDE3OC40CSAoSUM5NSU64oiSMSwyNjIuNDviiJIxLDA5Ny40KSAgZGUgR1dowrdtw6pzKiosIHJlZmxldGluZG8gc3VhIHByZWRvbWluw6JuY2lhIG5vIHNpc3RlbWEgaW50ZXJsaWdhZG8gZSBzdWEgbWFpb3IgZXhwb3Npw6fDo28gYSBhbm9tYWxpYXMgZGUgcHJlY2lwaXRhw6fDo28uIE8gKipTdWwqKiBhcHJlc2VudGEgcGVuYWxpZGFkZSBpbnRlcm1lZGnDoXJpYSAoWFhYWFhYWFhYWFhYKSwgbWFzIGNvbSBtYWlvciB2YXJpYWJpbGlkYWRlIGludGVyYW51YWwsIGNvbXBhdMOtdmVsIGNvbSBzZXUgcmVnaW1lIHBsdXZpb23DqXRyaWNvIG1haXMgaXJyZWd1bGFyLiBObyAqKk5vcmRlc3RlKiosIGFzIHBlcmRhcyBtw6lkaWFzIHPDo28gbWVub3JlcyAoWFhYWFhYWFhYWFhYWFgpLCBlbWJvcmEgY29tIHRlbmTDqm5jaWEgbmVnYXRpdmEgYWNlbnR1YWRhIGFww7NzIDIwMTAuIErDoSBvICoqTm9ydGUqKiBhcHJlc2VudGEgdmFsb3JlcyBwcsOzeGltb3MgZGUgemVybywgY29tIGludGVydmFsb3MgZGUgY29uZmlhbsOnYSBxdWUgaW5jbHVlbSBhIG51bGlkYWRlLCBzdWdlcmluZG8gYXVzw6puY2lhIGRlIHBlbmFsaWRhZGUgbMOtcXVpZGEgc2lnbmlmaWNhdGl2YSBubyBwZXLDrW9kbyBhbmFsaXNhZG8uDQoNCkVzc2VzIHJlc3VsdGFkb3MgY29ycm9ib3JhbSBhIGhpcMOzdGVzZSBkZSBxdWUgYSAqKnBlbmFsaWRhZGUgY2xpbcOhdGljYSBzb2JyZSBvIGFybWF6ZW5hbWVudG8gaMOtZHJpY28gw6kgY29uY2VudHJhZGEgZSBlc3RydXR1cmFsbWVudGUgYXNzaW3DqXRyaWNhKiosIGFmZXRhbmRvIGNvbSBtYWlvciBpbnRlbnNpZGFkZSBvcyBzdWJzaXN0ZW1hcyBTdWRlc3RlIGUgU3VsIOKAlCBqdXN0YW1lbnRlIGFxdWVsZXMgY29tIG1haW9yIHBhcGVsIGRlIHJlZ3VsYcOnw6NvIGUgc3Vwb3J0ZSBlbmVyZ8OpdGljbyBwYXJhIG8gcmVzdGFudGUgZG8gcGHDrXMuIEVzc2EgaGV0ZXJvZ2VuZWlkYWRlIGVzcGFjaWFsIGZvcm5lY2UgbyBlbG8gZW1ww61yaWNvIHBhcmEgYSBwcsOzeGltYSBldGFwYSBkYSBtb2RlbGFnZW0sIGVtIHF1ZSBhcyB2YXJpYcOnw7VlcyBzaW11bGFkYXMgZGUgXCggXERlbHRhIEVBUiBcKSBzZXLDo28gcHJvcGFnYWRhcyDDoCBnZXJhw6fDo28gaGlkcmVsw6l0cmljYSAoR0FNIDEpLCDDoCBnZXJhw6fDo28gdMOpcm1pY2EgKEdBTSAyKSBlLCBwb3IgZmltLCBhbyBwcmXDp28gZGUgY3VydG8gcHJhem8gKEdBTSAzKS4NCg0KDQozLjIgTW9kZWxvIDIg4oCUIEdlcmHDp8OjbyBIaWRyZWzDqXRyaWNhIGNvbW8gRnVuw6fDo28gZG8gQXJtYXplbmFtZW50bw0KTyBzZWd1bmRvIG1vZGVsbyBkYSBjYWRlaWEgZXN0aW1hIGEgZ2VyYcOnw6NvIGhpZHJlbMOpdHJpY2EgKEdfaGlkcm8pIGVtIGZ1bsOnw6NvIGRhIGVuZXJnaWEgYXJtYXplbmFkYSAoRUFSKSBlIGRlIGNvbnRyb2xlcyBvcGVyYWNpb25haXMgZSBzYXpvbmFpcy4gTyBvYmpldGl2byDDqSBjYXB0dXJhciBhIGVsYXN0aWNpZGFkZSBkYSBnZXJhw6fDo28gZW0gcmVsYcOnw6NvIGFvIGVzdG9xdWUgaMOtZHJpY28sIHBlcm1pdGluZG8gdHJhZHV6aXIgYXMgdmFyaWHDp8O1ZXMgc2ltdWxhZGFzIGRlIM6URUFSIChwZW5hbGlkYWRlIGNsaW3DoXRpY2EpIGVtIGltcGFjdG9zIHNvYnJlIGEgZ2VyYcOnw6NvIGVmZXRpdmEuIEFzc2ltIGNvbW8gbm8gbW9kZWxvIGNsaW3DoXRpY28sIGVtcHJlZ2Etc2UgdW0gR0FNIHBhcmEgY2FwdHVyYXIgcmVsYcOnw7VlcyBuw6NvIGxpbmVhcmVzIGVudHJlIHZhcmnDoXZlaXMgZsOtc2ljYXMgZSBvcGVyYWNpb25haXMsIG1hbnRlbmRvIHBhcmNpbcO0bmlhIGUgaW50ZXJwcmV0YWJpbGlkYWRlLg0KDQoNCg0KIyAzLjIgTW9kZWxvIDIg4oCUIEdlcmHDp8OjbyBIaWRyZWzDqXRyaWNhIGNvbW8gRnVuw6fDo28gZG8gQXJtYXplbmFtZW50bw0KDQpgYGB7cn0NCg0KbTJfaGlkcm8gPC0gYmFtKA0KICB2YWxfZ2VyYWNhbyB+ICBZZWFyKw0KICAgIHMoZWFyX3Jlc2VydmF0b3Jpb19zdWJzaXN0ZW1hX3Byb3ByaW9fbXdtZXMsIGsgPSA0KSsNCiAgICBzKHZhbF9nZXJhY2FvX2RheV9zdWJzaXN0ZW1hLCBrID0gNCkrDQogICAgcyhkb3ksIGJzID0gImNjIiwgayA9IDIpICsgICAgICMgc2F6b25hbGlkYWRlIGRvIGRpYSBkbyBhbm8gKGPDrWNsaWNhKQ0KICAgIHMoaWRfcmVzZXJ2YXRvcmlvLngsIGJzID0gInJlIikrIyBlZmVpdG8gYWxlYXTDs3JpbyBwb3IgcmVzZXJ2YXTDs3Jpbw0KICAgI3ModmFsX3ZhemFvZGVmbHVlbnRlLGsgPSAyKSsNCg0KICAgIG5vbV9zdWJzaXN0ZW1hLngNCiAgLA0KICBkYXRhICAgICA9IHJlc2VydiwNCiAgbWV0aG9kICAgPSAiZlJFTUwiLA0KICBkaXNjcmV0ZSA9IFRSVUUsDQogIGZhbWlseSAgID0gZ2F1c3NpYW4oKSwgICAgICAgICAgICAjIGZhbcOtbGlhOiBub3JtYWw7IGFqdXN0YXIgc2UgbmVjZXNzw6FyaW8NCiAgbmEuYWN0aW9uPSBuYS5leGNsdWRlLA0KICAja25vdHMgICAgPSBsaXN0KGRveSA9IGMoMC41LCAzNjYuNSkpDQopDQpgYGANCg0KYGBge3J9DQpzdW1tYXJ5KG0yX2hpZHJvKQ0KZ2FtLmNoZWNrKG0yX2hpZHJvKQ0KY29uY3Vydml0eShtMl9oaWRybywgZnVsbD1UUlVFKQ0KDQpgYGANCg0KDQpgYGB7cn0NCg0KcGxvdChtMl9oaWRybywgcGFnZXM9Mywgc2NoZW1lPTEsIHNoYWRlPVRSVUUsIHNlPVRSVUUsIHNjYWxlcz0iZnJlZSIpDQpgYGANCk8gbW9kZWxvIGhpZHJlbMOpdHJpY28gKEdBTSAyKSBhcHJlc2VudG91IGZvcnRlIGRlc2VtcGVuaG8gZXhwbGljYXRpdm8sIGNvbSBSwrIgYWp1c3RhZG8gZGUgMCw4NSBlIGRldmlhbmNlIGV4cGxpY2FkYSBkZSA4NSwyJSwgbyBxdWUgY29uZmlybWEgc3VhIGFsdGEgY2FwYWNpZGFkZSBkZSByZXByb2R1emlyIGEgZ2VyYcOnw6NvIG9ic2VydmFkYSBhIHBhcnRpciBkYSBlbmVyZ2lhIGFybWF6ZW5hZGEgZSB2YXJpw6F2ZWlzIG9wZXJhY2lvbmFpcy4gTyB0ZXJtbyBsaW5lYXIgcGFyYSBvIGFubyDDqSBuZWdhdGl2byBlIGFsdGFtZW50ZSBzaWduaWZpY2F0aXZvICjigJMxMyw1IE1Xwrdtw6pzL2FubzsgcCA8IDAsMDAxKSwgcmVmbGV0aW5kbyBhIHRlbmTDqm5jaWEgZXN0cnV0dXJhbCBkZSByZWR1w6fDo28gZGEgcGFydGljaXBhw6fDo28gaMOtZHJpY2EgYW8gbG9uZ28gZG8gcGVyw61vZG8sIHBvc3NpdmVsbWVudGUgZW0gZnVuw6fDo28gZGEgZXhwYW5zw6NvIGRlIGZvbnRlcyB0w6lybWljYXMgZSByZW5vdsOhdmVpcyBuw6NvIGjDrWRyaWNhcy4gT3MgZWZlaXRvcyBmaXhvcyBwb3Igc3Vic2lzdGVtYSBpbmRpY2FtIGRpZmVyZW7Dp2FzIG1vZGVzdGFzLCBjb20gZ2VyYcOnw6NvIG3DqWRpYSBsaWdlaXJhbWVudGUgc3VwZXJpb3Igbm8gTm9ydGUgZSBpbmZlcmlvciBubyBTdWRlc3RlLCBjb25zaXN0ZW50ZXMgY29tIG8gcGFwZWwgZXN0cnV0dXJhbCBkZSBjYWRhIHJlZ2nDo28gbmEgb2ZlcnRhIGRlIGVuZXJnaWEgZSBubyBkZXNwYWNobyBkbyBzaXN0ZW1hLg0KDQpPcyBkaWFnbsOzc3RpY29zIGRlIHJlc8OtZHVvcyBldmlkZW5jaWFtIGFqdXN0ZSBhZGVxdWFkbywgY29tIGRpc3RyaWJ1acOnw6NvIGFwcm94aW1hZGFtZW50ZSBub3JtYWwgZSBhdXPDqm5jaWEgZGUgaGV0ZXJvY2VkYXN0aWNpZGFkZSBzaXN0ZW3DoXRpY2EuIE8gaGlzdG9ncmFtYSBkb3MgcmVzw61kdW9zIMOpIGNlbnRyYWRvIGVtIHplcm8sIGUgbyBRUS1wbG90IG1vc3RyYSBsZXZlIGN1cnZhdHVyYSBuYXMgY2F1ZGFzLCBpbmRpY2FuZG8gcGVxdWVuYSBhc3NpbWV0cmlhIGFzc29jaWFkYSBhIHJlZ2ltZXMgb3BlcmFjaW9uYWlzIGV4dHJlbW9zIChyZXNlcnZhdMOzcmlvcyBjaGVpb3Mgb3UgdmF6aW9zKS4gTyBncsOhZmljbyBkZSByZXPDrWR1b3MgdmVyc3VzIHByZWRpdG9zIGV4aWJlIGR1YXMgZmFpeGFzIGJlbSBkZWZpbmlkYXMsIGNvcnJlc3BvbmRlbnRlcyBhIGRpZmVyZW50ZXMgcmVnaW1lcyBkZSBvcGVyYcOnw6NvIGhpZHLDoXVsaWNhIOKAlCB1bSBkZSBiYWl4YSBnZXJhw6fDo28gY29tIEVBUiBsaW1pdGFkYSBlIG91dHJvIGRlIG9wZXJhw6fDo28gcGxlbmEgY29tIGFsdG9zIG7DrXZlaXMgZGUgZGVzcGFjaG8uIEVtYm9yYSBlc3NlcyByZWdpbWVzIGludHJvZHV6YW0gbGV2ZSBlc3RyYXRpZmljYcOnw6NvLCBuw6NvIGjDoSBpbmTDrWNpb3MgZGUgdmnDqXMgZGlyZWNpb25hbCBuZW0gYXV0b2NvcnJlbGHDp8OjbyByZWxldmFudGUsIG8gcXVlIHJlZm9yw6dhIGEgdmFsaWRhZGUgZG8gbW9kZWxvIGdhdXNzaWFubyBjb20gbGluayBpZGVudGlkYWRlLiBPIHRlc3RlIGRlIGRpbWVuc2lvbmFsaWRhZGUgZWZldGl2YSAoay1pbmRleCA+IDAuOSkgZSBvIGJhaXhvIG7DrXZlbCBkZSBjb25jb3Jyw6puY2lhIChjb25jdXJ2aXR5IDwgMC4zKSBjb25maXJtYW0gYSBlc3RhYmlsaWRhZGUgbnVtw6lyaWNhIGRvcyBzcGxpbmVzIGUgYSBhdXPDqm5jaWEgZGUgc29icmVhanVzdGUuDQoNCk9zIGVmZWl0b3MgcGFyY2lhaXMgaWx1c3RyYW0gZGUgZm9ybWEgY2xhcmEgYSBkaW7Dom1pY2EgZsOtc2ljYSBkbyBzaXN0ZW1hLiBPIHNwbGluZSBkYSBlbmVyZ2lhIGFybWF6ZW5hZGEgKEVBUikgYXByZXNlbnRhIHVtIGZvcm1hdG8gY3Jlc2NlbnRlIGNvbSBsZXZlIHNhdHVyYcOnw6NvLCBzdWdlcmluZG8gcmVuZGltZW50byBkZWNyZXNjZW50ZTogYXVtZW50b3MgaW5pY2lhaXMgZGUgYXJtYXplbmFtZW50byBwcm9kdXplbSBncmFuZGVzIGFjcsOpc2NpbW9zIGRlIGdlcmHDp8OjbywgbWFzIG8gZWZlaXRvIG1hcmdpbmFsIGRpbWludWkgw6AgbWVkaWRhIHF1ZSBvIHJlc2VydmF0w7NyaW8gc2UgYXByb3hpbWEgZGEgY2FwYWNpZGFkZSBtw6F4aW1hLiBPIHNwbGluZSBkYSBnZXJhw6fDo28gZGnDoXJpYSBkbyBzdWJzaXN0ZW1hIG1vc3RyYSByZWxhw6fDo28gcXVhc2UgbGluZWFyIHBvc2l0aXZhLCByZXByZXNlbnRhbmRvIG8gZWZlaXRvIGRlIGVzY2FsYSBlIGNvb3JkZW5hw6fDo28gZW50cmUgdXNpbmFzIGludGVybGlnYWRhcy4gQSBzYXpvbmFsaWRhZGUgYW51YWwgKGRveSkgw6kgZnJhY2EsIHJlZmxldGluZG8gbyBmYXRvIGRlIHF1ZSBhcyBvc2NpbGHDp8O1ZXMgc2F6b25haXMgasOhIHPDo28gaW50ZXJuYWxpemFkYXMgbm8gbsOtdmVsIGRlIGFybWF6ZW5hbWVudG8sIGVucXVhbnRvIG8gZWZlaXRvIGFsZWF0w7NyaW8gcG9yIHJlc2VydmF0w7NyaW8gaW5kaWNhIGFtcGxhIGhldGVyb2dlbmVpZGFkZSBlc3RydXR1cmFsIOKAlCBhbGd1bnMgcmVzZXJ2YXTDs3Jpb3Mgb3BlcmFtIGNvbW8gdXNpbmFzIGRlIGJhc2UsIGNvbSBlZmVpdG8gcHLDs3hpbW8gZGUgemVybywgZSBvdXRyb3MgY29tIGZvcnRlIHNlbnNpYmlsaWRhZGUgw6AgdmFyaWHDp8OjbyBkZSBFQVIuIEVtIGNvbmp1bnRvLCBlc3NlcyByZXN1bHRhZG9zIGNvbmZpcm1hbSBxdWUgbyBtb2RlbG8gY2FwdGEgYWRlcXVhZGFtZW50ZSBvIG1lY2FuaXNtbyBkZSBjb252ZXJzw6NvIGhpZHJvbMOzZ2ljYSBlbnRyZSBlc3RvcXVlIGUgZ2VyYcOnw6NvLCBvZmVyZWNlbmRvIGJhc2UgY29uc2lzdGVudGUgcGFyYSBhIGVzdGltYXRpdmEgY29udHJhZmFjdHVhbCBkYSBnZXJhw6fDo28gaMOtZHJpY2Egc29iIGRpZmVyZW50ZXMgY2Vuw6FyaW9zIGNsaW3DoXRpY29zLg0KDQoNCg0KIyNQcmVkacOnw7VlcyBmYWN0dWFsIHZzLiBjb250cmFmYWN0dWFsIGNvbSBpbmNlcnRlemEgKGJhc2VsaW5lIDIwMDHigJMyMDA1KQ0KTyBvYmpldGl2byDDqSBjb21wYXJhciBvIGFybWF6ZW5hbWVudG8gcHJldmlzdG8gcGVsbyBtb2RlbG8gc29iIGNvbmRpw6fDtWVzIGNsaW3DoXRpY2FzIG9ic2VydmFkYXMgZSBzb2IgY29uZGnDp8O1ZXMgbmV1dHJhcywgcmVwcmVzZW50YWRhcyBwZWxvIGNsaW1hIG3DqWRpbyBkbyBwZXLDrW9kbyAyMDAx4oCTMjAwNS4gQSBkaWZlcmVuw6dhIGVudHJlIGFzIGR1YXMgc8OpcmllcyAoJM6URUFSPUVee29ic33iiJJFXntjZn0kKSByZXByZXNlbnRhIGEgcGVuYWxpZGFkZSBjbGltw6F0aWNhIGzDrXF1aWRhLCBlIHN1YSBpbmNlcnRlemEgw6kgZXN0aW1hZGEgdmlhIHByb3BhZ2HDp8OjbyBkb3MgZXJyb3MgcGFyYW3DqXRyaWNvcyBkbyBHQU0uDQoNCmBgYHtyfQ0KIyAtLS0gUHJlZGnDp8O1ZXMgZmFjdHVhbCBlIGNvbnRyYWZhY3R1YWwgLS0tDQpyZXNlcnYkZWFyX2hhdF9vYnMgPC0gcHJlZGljdChtMV9nYW0sIG5ld2RhdGEgPSBuZF9vYnMsIHR5cGUgPSAicmVzcG9uc2UiKQ0KcmVzZXJ2JGVhcl9oYXRfY2YgIDwtIHByZWRpY3QobTFfZ2FtLCBuZXdkYXRhID0gbmRfY2YsICB0eXBlID0gInJlc3BvbnNlIikNCg0KIyBQZW5hbGlkYWRlIG3DqWRpYQ0KcmVzZXJ2IDwtIHJlc2VydiAlPiUNCiAgbXV0YXRlKGRlbHRhX2VhciA9IGVhcl9oYXRfb2JzIC0gZWFyX2hhdF9jZikNCg0KcmVzZXJ2JGdlcl9oYXRfZmFjdHVhbCA8LSBwcmVkaWN0KA0KICBtMl9oaWRybywgbmV3ZGF0YSA9IHJlc2VydiwNCiAgdHlwZSA9ICJyZXNwb25zZSINCikNCnJlc2VydiRnZXJfaGF0X2NvbnRyYWYgPC0gcHJlZGljdCgNCiAgbTJfaGlkcm8sIG5ld2RhdGEgPSByZXNlcnYgJT4lDQogICAgbXV0YXRlKGVhcl9yZXNlcnZhdG9yaW9fc3Vic2lzdGVtYV9wcm9wcmlvX213bWVzID0gZWFyX2hhdF9jZiksDQogIHR5cGUgPSAicmVzcG9uc2UiDQopDQpyZXNlcnYgPC0gcmVzZXJ2ICU+JQ0KICBtdXRhdGUoZGVsdGFfR2hpZHJvID0gZ2VyX2hhdF9mYWN0dWFsIC0gZ2VyX2hhdF9jb250cmFmKQ0KcmVzZXJ2WyxjKCJkZWx0YV9HaGlkcm8iLCJnZXJfaGF0X2ZhY3R1YWwiLCJnZXJfaGF0X2NvbnRyYWYiLCJ2YWxfZ2VyYWNhbyIpXSAlPiUgc3VtbWFyeSgpDQpgYGANCiMgKDMpIEluY2VydGV6YSB2aWEgRGVsdGEgTWV0aG9kIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQ0KYGBge3J9DQpWcDIgPC0gdmNvdihtMl9oaWRybykNClhfZiA8LSBwcmVkaWN0KG0yX2hpZHJvLCBuZXdkYXRhID0gcmVzZXJ2ICwNCiAgICAgICAgICAgICAgIHR5cGUgPSAibHBtYXRyaXgiKQ0KWF9jIDwtIHByZWRpY3QobTJfaGlkcm8sIG5ld2RhdGEgPSByZXNlcnYgJT4lDQogICAgICAgICAgICAgICAgIG11dGF0ZShlYXJfcmVzZXJ2YXRvcmlvX3N1YnNpc3RlbWFfcHJvcHJpb19td21lcyA9IGVhcl9oYXRfY2YpLA0KICAgICAgICAgICAgICAgdHlwZSA9ICJscG1hdHJpeCIpDQoNClhfZGlmZjIgPC0gWF9mIC0gWF9jDQp2YXJfZGVsdGEyIDwtIHJvd1N1bXMoKFhfZGlmZjIgJSolIFZwMikgKiBYX2RpZmYyKQ0Kc2VfZGVsdGEyICA8LSBzcXJ0KHBtYXgodmFyX2RlbHRhMiwgMCkpDQp6IDwtIHFub3JtKDAuOTc1KQ0KDQpyZXNlcnYgPC0gcmVzZXJ2ICU+JQ0KICBtdXRhdGUoDQogICAgZGVsdGFfbHdyX2dlciA9IGRlbHRhX0doaWRybyAtIHogKiBzZV9kZWx0YTIsDQogICAgZGVsdGFfdXByX2dlciA9IGRlbHRhX0doaWRybyArIHogKiBzZV9kZWx0YTINCiAgKQ0KDQpgYGANCg0KYGBge3J9DQojICg0KSBBZ3JlZ2HDp8OjbyBwb3IgYW5vIGUgc3Vic2lzdGVtYSAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQ0KbTJfZGVsdGFfYWdnIDwtIHJlc2VydiAlPiUNCiAgbXV0YXRlKFllYXIgPSB5ZWFyKGRhdGUpKSAlPiUNCiAgZ3JvdXBfYnkoWWVhciwgbm9tX3N1YnNpc3RlbWEueCkgJT4lDQogIHN1bW1hcmlzZSgNCiAgICBtZWFuX3BlbmFsdHkgPSBtZWFuKGRlbHRhX0doaWRybywgbmEucm0gPSBUUlVFKSwNCiAgICBsd3IgPSBtZWFuKGRlbHRhX2x3cl9nZXIsIG5hLnJtID0gVFJVRSksDQogICAgdXByID0gbWVhbihkZWx0YV91cHJfZ2VyLCBuYS5ybSA9IFRSVUUpLA0KICAgIC5ncm91cHMgPSAiZHJvcCINCiAgKQ0KbTJfZGVsdGFfYWdnICU+JSBzdW1tYXJ5KCkNCiAgDQpgYGANCg0KIyMgUHJlZGnDp8O1ZXMgZG8gbW9kZWxvIEdlcmHDp8Ojbw0KDQpgYGB7cn0NCg0KbmV3ZGF0YV9tMSAlPiUgDQogIG11dGF0ZShnZXJfaGF0ID0gcHJlZGljdChtMl9oaWRybywgbmV3ZGF0YSA9IG5ld2RhdGFfbTEsIHR5cGU9InJlc3BvbnNlIixuYS5hY3Rpb24gPSBuYS5wYXNzKSkgLT4gbmV3ZGF0YV9tMQ0KDQpgYGANCg0KYGBge3IgZmlnLmhlaWdodD04LCBmaWcud2lkdGg9MTJ9DQojIDEpIFPDqXJpZSB0ZW1wb3JhbDogRUFSIG9ic2VydmFkbyB2cyBwcmV2aXN0bw0KbmV3ZGF0YV9tMSAlPiUgDQogICBtdXRhdGUobWVzID0gZmxvb3JfZGF0ZShkYXRlLCB1bml0ID0gIm1vbnRoIikpICU+JSANCg0KICBncm91cF9ieShtZXMsbm9tX3N1YnNpc3RlbWEueCkgJT4lc3VtbWFyaXNlKHZhbF9nZXJhY2FvID1tZWFuKHZhbF9nZXJhY2FvICAgLG5hLnJtPVQpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICBnZXJfaGF0PW1lYW4oZ2VyX2hhdCxuYS5ybT1UKSkgJT4lDQogIGdncGxvdChhZXMoeCA9IG1lcywpKSArDQogIGdlb21fbGluZShhZXMoeSA9IHZhbF9nZXJhY2FvLCBjb2xvciA9ICJPYnNlcnZhZG8iKSwgc2l6ZSA9IDAuNyxhbHBoYT0uNikgKw0KICBnZW9tX2xpbmUoYWVzKHkgPSBnZXJfaGF0LCBjb2xvciA9ICJQcmV2aXN0byIpLCBzaXplID0gMSwgbGluZXR5cGUgPSAiZGFzaGVkIikgK2ZhY2V0X3dyYXAofm5vbV9zdWJzaXN0ZW1hLngsc2NhbGVzID0gImZyZWUiKSsNCiAgbGFicyh0aXRsZSA9ICJFQVIgb2JzZXJ2YWRvIHZzIHByZXZpc3RvIChHQU0pIiwNCiAgICAgICB5ID0gIkVBUiAoTVdtw6pzKSIsIHggPSAiRGF0YSIpICsNCiAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9IGMoIk9ic2VydmFkbyIgPSAiYmxhY2siLCAiUHJldmlzdG8iID0gInJlZCIpKSArDQogIHRoZW1lX21pbmltYWwoKQ0KDQpuZXdkYXRhX20xICU+JSANCiAgbXV0YXRlKG1lcyA9IGZsb29yX2RhdGUoZGF0ZSwgdW5pdCA9ICJtb250aCIpKSAlPiUgDQogIGdyb3VwX2J5KG1lcyxub21fc3Vic2lzdGVtYS54KSAlPiVzdW1tYXJpc2UocmVzaWQ9bWVhbih2YWxfZ2VyYWNhbyxuYS5ybT1UKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlYXJfaGF0PW1lYW4oZ2VyX2hhdCxuYS5ybT1UKSkgJT4lDQogIA0KICBnZ3Bsb3QoIGFlcyh4ID0gbWVzLCkpICsNCiAgI2dlb21fcG9pbnQoYWVzKGNvbG9yPXJlc2lkX2NvbCkpKw0KICBmYWNldF93cmFwKH5ub21fc3Vic2lzdGVtYS54LHNjYWxlcyA9ICJmcmVlIikrDQogIGdlb21fbGluZShhZXMoeSA9IHJlc2lkKSxjb2w9InJlZCIpICsgIGdlb21fbGluZShhZXMoeT1lYXJfaGF0KSkgKw0KICBnZW9tX3JpYmJvbihhZXMoeW1pbj1yZXNpZCx5bWF4PWVhcl9oYXQpLGFscGhhPS40LGZpbGwgPSAiZmlyZWJyaWNrIiwpKw0KICBsYWJzKHRpdGxlID0gIlJlc8OtZHVvcyBkbyBtb2RlbG8gKG9ic2VydmFkbyAtIHByZXZpc3RvKSIsDQogICAgICAgeSA9ICJSZXPDrWR1byIsIHggPSAiRGF0YSIpICsNCiAgdGhlbWVfbWluaW1hbCgpDQoNCmBgYA0KDQojIyMgQWp1c3RlIGRvIEdBTTogc8OpcmllcyB0ZW1wb3JhaXMgZSBkaXNwZXJzw6NvDQoNCkEgRmlndXJhIDEgYXByZXNlbnRhIGEgY29tcGFyYcOnw6NvIGVudHJlIG9zIG7DrXZlaXMgZGUgRUFSIG9ic2VydmFkb3MgZSBvcyB2YWxvcmVzIHByZXZpc3RvcyBwZWxvIG1vZGVsbyBHQU0sIGRlc2FncmVnYWRvcyBwb3Igc3Vic2lzdGVtYS4NCg0KLSAgICoqTm9yZGVzdGUgZSBTdWRlc3RlOioqIG8gbW9kZWxvIGFjb21wYW5oYSByYXpvYXZlbG1lbnRlIGJlbSBhcyB0ZW5kw6puY2lhcyBkZSBsb25nbyBwcmF6bywgbWFzIHN1YmVzdGltYSBvcyBwZXLDrW9kb3MgZGUgc2VjYSBzZXZlcmEgKHDDs3MtMjAxMikgZSBzdXBlcmVzdGltYSBhbGd1bnMgcGljb3MgZGUgcmVjdXBlcmHDp8Ojby4NCg0KLSAgICoqTm9ydGU6KiogYSBwcmV2aXPDo28gdGVuZGUgYSBzdWF2aXphciBhIGFsdGEgdmFyaWFiaWxpZGFkZSBpbnRlcmFudWFsLCBjYXB0YW5kbyBtZWxob3IgYSBtw6lkaWEgZGUgbG9uZ28gcHJhem8gZG8gcXVlIG9zIGV4dHJlbW9zLg0KDQotICAgKipTdWw6KiogaMOhIG1haW9yIGFkZXLDqm5jaWEgZW50cmUgYXMgY3VydmFzLCBlbWJvcmEgb3MgY2hvcXVlcyBoaWRyb2zDs2dpY29zIG1haXMgaW50ZW5zb3Mgc2VqYW0gc3Vhdml6YWRvcyBwZWxvIG1vZGVsby4NCg0KRGUgZm9ybWEgZ2VyYWwsIG8gbW9kZWxvIMOpIGVmaWNheiBlbSBjYXB0dXJhciBvICoqbsOtdmVsIG3DqWRpbyBlIGEgc2F6b25hbGlkYWRlIGVzdHJ1dHVyYWwqKiwgbWFzIHRlbmRlIGEgKipzdWJlc3RpbWFyIGV2ZW50b3MgY3LDrXRpY29zKiogZGUgY2hlaWEgb3UgZGUgc2VjYS4NCg0KYGBge3J9DQoNCiMgMikgU2NhdHRlcnBsb3QgT2JzZXJ2YWRvIHZzIFByZXZpc3RvDQpuZXdkYXRhX20xICU+JSANCiAgIGdyb3VwX2J5KGRhdGUsbm9tX3N1YnNpc3RlbWEueCkgJT4lc3VtbWFyaXNlKHZhbF9nZXJhY2FvPXN1bSh2YWxfZ2VyYWNhbyxuYS5ybT1UKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZ2VyX2hhdD1zdW0oZ2VyX2hhdCxuYS5ybT1UKSkgJT4lDQogIGdncGxvdCggYWVzKHggPSB2YWxfZ2VyYWNhbywgeSA9IGdlcl9oYXQpKSArDQogIGdlb21fcG9pbnQoYWxwaGEgPSAwLjEpICsNCiAgZ2VvbV9hYmxpbmUoc2xvcGUgPSAxLCBpbnRlcmNlcHQgPSAwLCBsaW5ldHlwZSA9ICJkYXNoZWQiLCBjb2xvciA9ICJibHVlIikgICtmYWNldF93cmFwKH5ub21fc3Vic2lzdGVtYS54LHNjYWxlcyA9ICJmcmVlIikrDQogIGxhYnModGl0bGUgPSAiRGlzcGVyc8OjbyBFQVIgb2JzZXJ2YWRvIHZzIHByZXZpc3RvIiwNCiAgICAgICB4ID0gIlByZXZpc3RvIChHQU0pIiwgeSA9ICJPYnNlcnZhZG8iKSArDQogIHRoZW1lX21pbmltYWwoKQ0KDQoNCmBgYA0KDQpBIEZpZ3VyYSAyIG1vc3RyYSBvcyBkaWFncmFtYXMgZGUgZGlzcGVyc8OjbyBlbnRyZSBvcyB2YWxvcmVzIG9ic2VydmFkb3MgZSBwcmV2aXN0b3MgZGUgRUFSLCB0YW1iw6ltIHBvciBzdWJzaXN0ZW1hLCBjb20gYSBsaW5oYSB0cmFjZWphZGEgcmVwcmVzZW50YW5kbyBvIGFqdXN0ZSBwZXJmZWl0byAoNDXCsCkuDQoNCi0gICBBIG1haW9yIHBhcnRlIGRvcyBwb250b3Mgc2UgY29uY2VudHJhIHByw7N4aW1hIGRhIGxpbmhhIGRlIHJlZmVyw6puY2lhLCBjb25maXJtYW5kbyBhIGJvYSBjYXBhY2lkYWRlIGV4cGxpY2F0aXZhIGRvIG1vZGVsby4NCg0KLSAgIE8gKipTdWRlc3RlKiogY29uY2VudHJhIG1haW9yIGRpc3BlcnPDo28sIGNvZXJlbnRlIGNvbSBhIHN1YSByZWxldsOibmNpYSBlIG1haW9yIGhldGVyb2dlbmVpZGFkZSBoaWRyb2zDs2dpY2EuDQoNCi0gICBPICoqTm9yZGVzdGUqKiBtb3N0cmEgYm9tIGFsaW5oYW1lbnRvLCBtYXMgY29tIGFsZ3VucyBkZXN2aW9zIGVtIGJhaXhvcyBuw612ZWlzIGRlIEVBUi4NCg0KLSAgIE8gKipTdWwqKiBhcHJlc2VudGEgYSBtYWlvciBhZGVyw6puY2lhLCBjb20gbnV2ZW0gZGUgcG9udG9zIGZvcnRlbWVudGUgY29sYWRhIMOgIGxpbmhhIDQ1wrAuDQoNCkVzc2VzIHJlc3VsdGFkb3MgY29ycm9ib3JhbSBxdWUgbyBHQU0gw6kgYWRlcXVhZG8gcGFyYSBjYXB0dXJhciBhICoqZGluw6JtaWNhIG3DqWRpYSBlIGVzdHJ1dHVyYWwqKiBkbyBzaXN0ZW1hLCBtYXMgcXVlIG9zIHZhbG9yZXMgZXN0aW1hZG9zIGRldmVtIHNlciBpbnRlcnByZXRhZG9zIGNvbSBjYXV0ZWxhIGVtICoqY29uZGnDp8O1ZXMgZXh0cmVtYXMgZGUgZXNjYXNzZXogb3UgZXhjZXNzbyBow61kcmljbyoqLg0KDQojIyBDb250cmFmYWN0dXJhbCBHZXJhw6fDo28gVGVybWljYSBnYW0NCg0KYGBge3J9DQpuZXdkYXRhX20xICU+JSANCiAgbXV0YXRlKGVhcl9yZXNlcnZhdG9yaW9fc3Vic2lzdGVtYV9wcm9wcmlvX213bWVzPWVhcl9yZXNlcnZhdG9yaW9fc3Vic2lzdGVtYV9wcm9wcmlvX213bWVzLWNsaW1faW4kcGVuYWxpZGFkZV9lYXIpLT5uZXdkYXRhX20yDQojbmV3ZGF0YV9tMSAlPiUgDQojICBtdXRhdGUoZWFyX3Jlc2VydmF0b3Jpb19zdWJzaXN0ZW1hX3Byb3ByaW9fbXdtZXM9Y2xpbV9pbiRjbGltMjAyNl9oYXQpLT5uZXdkYXRhX20yDQpuZXdkYXRhX20yJGdlcl9oYXRfY2YgPC0gcHJlZGljdChtMl9oaWRybywgbmV3ZGF0YSA9IG5ld2RhdGFfbTIsIHR5cGU9InJlc3BvbnNlIixuYS5hY3Rpb24gPSBuYS5wYXNzKQ0KYGBgDQoNCmBgYHtyfQ0KIyAxKSBTw6lyaWUgdGVtcG9yYWw6IEVBUiBvYnNlcnZhZG8gdnMgcHJldmlzdG8NCm5ld2RhdGFfbTIgJT4lIA0KICAgbXV0YXRlKG1lcyA9IGZsb29yX2RhdGUoZGF0ZSwgdW5pdCA9ICJtb250aCIpKSAlPiUgDQoNCiAgZ3JvdXBfYnkoLG5vbV9zdWJzaXN0ZW1hLngpICU+JXN1bW1hcmlzZShnZXJfaGF0X2NmID1tZWFuKGdlcl9oYXRfY2YgICAsbmEucm09VCksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdlcl9oYXQ9bWVhbihnZXJfaGF0LG5hLnJtPVQpKSAlPiUNCiAgZ2dwbG90KGFlcyh4ID0gbWVzLCkpICsNCiAgZ2VvbV9saW5lKGFlcyh5ID0gZ2VyX2hhdF9jZiwgY29sb3IgPSAiUHJldmlzdG8gLSBSZWFsIiksIHNpemUgPSAwLjcsYWxwaGE9LjYpICsNCiAgZ2VvbV9saW5lKGFlcyh5ID0gZ2VyX2hhdCwgY29sb3IgPSAiUHJldmlzdG8gLSBDb250cmFmYWN0dWFsIiksIHNpemUgPSAxLCBsaW5ldHlwZSA9ICJkYXNoZWQiKSArZmFjZXRfd3JhcCh+bm9tX3N1YnNpc3RlbWEueCxzY2FsZXMgPSAiZnJlZSIpKw0KICBsYWJzKHRpdGxlID0gIkdlcmHDp8OjbyBQcmVkaXRvIHZzIHByZXZpc3RvIChDb250cmEtZmFjdHVhbCkiLA0KICAgICAgIHkgPSAiRUFSIChNV23DqnMpIiwgeCA9ICJEYXRhIikgKw0KICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gYygiUHJldmlzdG8gLSBSZWFsIiA9ICJibGFjayIsICJQcmV2aXN0byAtIENvbnRyYWZhY3R1YWwiID0gInJlZCIpKSArDQogIHRoZW1lX21pbmltYWwoKQ0KbmV3ZGF0YV9tMiAlPiUgDQogICBtdXRhdGUobWVzID0gZmxvb3JfZGF0ZShkYXRlLCB1bml0ID0gIm1vbnRoIikpICU+JSANCg0KICBncm91cF9ieShtZXMsKSAlPiVzdW1tYXJpc2UoZ2VyX2hhdF9jZiA9bWVhbihnZXJfaGF0X2NmICAgLG5hLnJtPVQpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICBnZXJfaGF0PW1lYW4oZ2VyX2hhdCxuYS5ybT1UKSkgJT4lDQogIGdncGxvdChhZXMoeCA9IG1lcywpKSArDQogIGdlb21fbGluZShhZXMoeSA9IGdlcl9oYXRfY2YsIGNvbG9yID0gIlByZXZpc3RvIC0gUmVhbCIpLCBzaXplID0gMC43LGFscGhhPS42KSArDQogIGdlb21fbGluZShhZXMoeSA9IGdlcl9oYXQsIGNvbG9yID0gIlByZXZpc3RvIC0gQ29udHJhZmFjdHVhbCIpLCBzaXplID0gMSwgbGluZXR5cGUgPSAiZGFzaGVkIikgKyNmYWNldF93cmFwKH5ub21fc3Vic2lzdGVtYS54LHNjYWxlcyA9ICJmcmVlIikrDQogIGxhYnModGl0bGUgPSAiR2VyYcOnw6NvIFByZWRpdG8gdnMgcHJldmlzdG8gKENvbnRyYS1mYWN0dWFsKSIsDQogICAgICAgeSA9ICJFQVIgKE1XbcOqcykiLCB4ID0gIkRhdGEiKSArDQogIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSBjKCJQcmV2aXN0byAtIFJlYWwiID0gImJsYWNrIiwgIlByZXZpc3RvIC0gQ29udHJhZmFjdHVhbCIgPSAicmVkIikpICsNCiAgdGhlbWVfbWluaW1hbCgpDQpgYGANCg0KQSBmaWd1cmEgY29tcGFyYSwgcG9yIHN1YnNpc3RlbWEsIGEgKipnZXJhw6fDo28gaGlkcmVsw6l0cmljYSBwcmV2aXN0YSBjb20gY2xpbWEgb2JzZXJ2YWRvKiogZSBhICoqZ2VyYcOnw6NvIGNvbnRyYWZhY3R1YWwqKiBzaW11bGFkYSBhbyBzdWJzdGl0dWlyIG8gYXJtYXplbmFtZW50byAoRUFSKSBwZWxvIGJhc2VsaW5lIGNsaW3DoXRpY28gKDIwMDHigJMyMDEwKS4NCg0KLSAgICoqTm9yZGVzdGUgZSBTdWRlc3RlOioqIGEgc8OpcmllIGNvbSAqKmNsaW1hIG9ic2VydmFkbyoqIGFwcmVzZW50YSBxdWVkYXMgYWNlbnR1YWRhcyBhcMOzcyAyMDEyLCBlbnF1YW50byBvICoqY29udHJhZmFjdHVhbCoqIHNlIG1hbnTDqW0gZW0gcGF0YW1hcmVzIG1lbm9yZXMgZSBtYWlzIGVzdMOhdmVpcy4gQSBkaXZlcmfDqm5jaWEgY3Jlc2NlbnRlIHJlZmxldGUgYSAqKnBlbmFsaWRhZGUgY2xpbcOhdGljYSoqIHJlY2VudGUgc29icmUgYSBnZXJhw6fDo28uDQoNCi0gICAqKk5vcnRlOioqIG8gY29udHJhZmFjdHVhbCBhY29tcGFuaGEgZGUgcGVydG8gYSB0cmFqZXTDs3JpYSBtw6lkaWE7IGEgc8OpcmllIHJlYWwgbW9zdHJhIG9zY2lsYcOnw7VlcyBhZGljaW9uYWlzIGVtIGFub3MgZXNwZWPDrWZpY29zLCBzdWdlcmluZG8gY2hvcXVlcyBuw6NvIHJlcHJvZHV6aWRvcyBwZWxvIGNsaW1hIG3DqWRpby4NCg0KLSAgICoqU3VsOioqIGjDoSBmb3J0ZSB2YXJpYWJpbGlkYWRlIGludGVyYW51YWwgbmFzIGR1YXMgY3VydmFzOyBtZXNtbyBhc3NpbSwgYSBzw6lyaWUgcmVhbCB0ZW5kZSBhIGZpY2FyICoqYWJhaXhvKiogZG8gY29udHJhZmFjdHVhbCBlbSBhbm9zIHNlY29zLCBldmlkZW5jaWFuZG8gc3Vic3RpdHVpw6fDo28gcG9yIG91dHJhcyBmb250ZXMgbmVzc2VzIHBlcsOtb2Rvcy4NCg0KRW0gY29uanVudG8sIG9zIHJlc3VsdGFkb3MgaW5kaWNhbSBxdWUgKipvIGNsaW1hIHJlY2VudGUgcmVkdXppdSBhIGdlcmHDp8OjbyBow61kcmljYSoqIGVtIHJlbGHDp8OjbyBhbyBxdWUgc2VyaWEgZXNwZXJhZG8gc29iIHVtIHJlZ2ltZSBjbGltw6F0aWNvIG3DqWRpbywgY29tIGludGVuc2lkYWRlIG1haW9yIG5vIFN1ZGVzdGUgZSBOb3JkZXN0ZS4NCg0KYGBge3IgQ29udHJhZmFjdHVhbCBjbGltw6F0aWNvIDEoYmFzZWxpbmUgMjAwMeKAkzIwMDUpfQ0KbmV3ZGF0YV9tMiAlPiUgDQogICBtdXRhdGUobWVzID0gZmxvb3JfZGF0ZShkYXRlLCB1bml0ID0gIm1vbnRoIikpICU+JSANCg0KICBncm91cF9ieShZZWFyKSAlPiVzdW1tYXJpc2UoZW5hX213Nz1zdW0oZ2VyX2hhdCxuYS5ybT1UKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2xpbTIwMjZfaGF0PXN1bShnZXJfaGF0X2NmLG5hLnJtPVQpKSAlPiUNCiAgZ2dwbG90KGFlcyh4ID0gWWVhciwpKSArDQogIGdlb21fbGluZShhZXMoeSA9IGVuYV9tdzcvMTAwMCwgY29sb3IgPSAiUHJldmlzdG8iKSwgc2l6ZSA9IDAuNyxhbHBoYT0uNikgKw0KICBnZW9tX2xpbmUoYWVzKHkgPSBjbGltMjAyNl9oYXQvMTAwMCwgY29sb3IgPSAiQ29udHJhZmFjdHVhbCAyMDEwIiksIHNpemUgPSAxLCBsaW5ldHlwZSA9ICJkYXNoZWQiKSArI2ZhY2V0X3dyYXAofm5vbV9zdWJzaXN0ZW1hLngsc2NhbGVzID0gImZyZWUiKSsNCiAgbGFicyh0aXRsZSA9ICJDb250cmFmYWN0dWFsIGJhc2VsaW5lIChjbGltYSBtw6lkaW8gMjAwMS0yMDEwKSIsDQogICAgICAgeSA9ICJHZXJhw6fDo28gKEdXbcOqcykiLCB4ID0gIkRhdGEiKSArDQogIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSBjKCJQcmV2aXN0byIgPSAiYmxhY2siLCAiQ29udHJhZmFjdHVhbCAyMDEwIiA9ICJibHVlIikpICsNCiAgdGhlbWVfbWluaW1hbCgpDQpuZXdkYXRhX20yICU+JSANCiAgIG11dGF0ZShtZXMgPSBmbG9vcl9kYXRlKGRhdGUsIHVuaXQgPSAibW9udGgiKSkgJT4lIA0KDQogIGdyb3VwX2J5KFllYXIsbm9tX3N1YnNpc3RlbWEueCkgJT4lc3VtbWFyaXNlKGVuYV9tdzc9c3VtKGdlcl9oYXQsbmEucm09VCksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNsaW0yMDI2X2hhdD1zdW0oZ2VyX2hhdF9jZixuYS5ybT1UKSkgJT4lDQogIGdncGxvdChhZXMoeCA9IFllYXIsKSkgKw0KICBnZW9tX2xpbmUoYWVzKHkgPSBlbmFfbXc3LzEwMDAsIGNvbG9yID0gIlByZXZpc3RvIiksIHNpemUgPSAwLjcsYWxwaGE9LjYpICsNCiAgZ2VvbV9saW5lKGFlcyh5ID0gY2xpbTIwMjZfaGF0LzEwMDAsIGNvbG9yID0gIkNvbnRyYWZhY3R1YWwgMjAxMCIpLCBzaXplID0gMSwgbGluZXR5cGUgPSAiZGFzaGVkIikgK2ZhY2V0X3dyYXAofm5vbV9zdWJzaXN0ZW1hLngsc2NhbGVzID0gImZyZWUiKSsNCiAgbGFicyh0aXRsZSA9ICJDb250cmFmYWN0dWFsIGJhc2VsaW5lIChjbGltYSBtw6lkaW8gMjAwMS0yMDEwKSIsDQogICAgICAgeSA9ICJHZXJhw6fDo28gKEdXbcOqcykiLCB4ID0gIkRhdGEiKSArDQogIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSBjKCJQcmV2aXN0byIgPSAiYmxhY2siLCAiQ29udHJhZmFjdHVhbCAyMDEwIiA9ICJibHVlIikpICsNCiAgdGhlbWVfbWluaW1hbCgpDQpgYGANCg0KQSBGaWd1cmEgMSBjb21wYXJhIGFzIHRyYWpldMOzcmlhcyBwcmV2aXN0YXMgZGUgZ2VyYcOnw6NvIGhpZHJlbMOpdHJpY2Egc29iIGR1YXMgY29uZGnDp8O1ZXM6DQoNCi0gICAqKlByZXZpc3RvIOKAkyBSZWFsIChsaW5oYSBwcmV0YSk6KiogcmVzdWx0YWRvcyBkbyBHQU0gY29tIGNsaW1hIG9ic2VydmFkbyBubyBwZXLDrW9kbzsNCg0KICAgICoqUHJldmlzdG8g4oCTIENvbnRyYWZhY3R1YWwgKGxpbmhhIHZlcm1lbGhhIHRyYWNlamFkYSk6KiogcmVzdWx0YWRvcyBkbyBtZXNtbyBtb2RlbG8sIG1hcyBzdWJzdGl0dWluZG8gYXMgdmFyacOhdmVpcyBjbGltw6F0aWNhcyBwZWxhcyBtw6lkaWFzIGhpc3TDs3JpY2FzIChiYXNlbGluZSAyMDAx4oCTMjAxMCkuDQoNCmBgYHtyIGZpZy5oZWlnaHQ9NiwgZmlnLndpZHRoPTEyfQ0KbmV3ZGF0YV9tMiAlPiUgDQogICBtdXRhdGUobWVzID0gZmxvb3JfZGF0ZShkYXRlLCB1bml0ID0gIm1vbnRoIikpICU+JSANCg0KICBncm91cF9ieShZZWFyLG5vbV9zdWJzaXN0ZW1hLngpICU+JXN1bW1hcmlzZShlbmFfbXc3PXN1bShnZXJfaGF0LG5hLnJtPVQpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjbGltMjAyNl9oYXQ9c3VtKGdlcl9oYXRfY2YsbmEucm09VCkpICU+JQ0KICBnZ3Bsb3QoYWVzKHggPSBZZWFyLCkpICsNCiAgZ2VvbV9saW5lKGFlcyh5ID0gZW5hX213Ny8xMDAwLCBjb2xvciA9ICJQcmV2aXN0byIpLCBzaXplID0gMC43LGFscGhhPS42KSArDQogIGdlb21fbGluZShhZXMoeSA9IGNsaW0yMDI2X2hhdC8xMDAwLCBjb2xvciA9ICJDb250cmFmYWN0dWFsIDIwMTAgLSBiYXNlbGluZSIpLCBzaXplID0gMSwgbGluZXR5cGUgPSAiZGFzaGVkIikgK2ZhY2V0X3dyYXAofm5vbV9zdWJzaXN0ZW1hLngsc2NhbGVzID0gImZyZWUiLG5jb2wgPSAyKSsNCiAgbGFicyh0aXRsZSA9ICJDb250cmFmYWN0dWFsIGNsaW3DoXRpY28gcG9yIHN1YnNpc3RlbWEgKGJhc2VsaW5lIDIwMDHigJMyMDEwKSIsDQogICAgICAgeSA9ICJHZXJhw6fDo28gKEdXbcOqcykiLCB4ID0gIkRhdGEiKSArDQogIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSBjKCJQcmV2aXN0byIgPSAiYmxhY2siLCAiQ29udHJhZmFjdHVhbCAyMDEwIC0gYmFzZWxpbmUiID0gImJsdWUiKSkgKw0KICB0aGVtZV9taW5pbWFsKCkNCmBgYA0KDQpgYGB7ciB9DQpuZXdkYXRhX20yICU+JSANCiAgIG11dGF0ZShtZXMgPSBmbG9vcl9kYXRlKGRhdGUsIHVuaXQgPSAibW9udGgiKSwNCiAgICAgICAgICBwZW5hbGlkYWRlX2dlcmHDp8Ojb19oaWRybz1nZXJfaGF0LWdlcl9oYXRfY2YsDQogICAgICAgICAgI3BlbmFsaWRhZGUyPWVuYV9tdzctY2xpbTIwMjZfaGF0LA0KICAgICAgICAgICktPm5ld2RhdGFfbTINCm5ld2RhdGFfbTIgJT4lIA0KICAgbXV0YXRlKG1lcyA9IGZsb29yX2RhdGUoZGF0ZSwgdW5pdCA9ICJtb250aCIpLA0KICAgICAgICAgIHBlbmFsaWRhZGUxPWdlcl9oYXQtZ2VyX2hhdF9jZiwNCiAgICAgICAgICAjcGVuYWxpZGFkZTI9ZW5hX213Ny1jbGltMjAyNl9oYXQsDQogICAgICAgICAgKSAlPiUgDQoNCiAgZ3JvdXBfYnkoWWVhcikgJT4lc3VtbWFyaXNlKGVuYV9tdzc9c3VtKHBlbmFsaWRhZGUxLG5hLnJtPVQpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjY2xpbTIwMjZfaGF0PXN1bShwZW5hbGlkYWRlMixuYS5ybT1UKQ0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICApICU+JQ0KICBnZ3Bsb3QoYWVzKHggPSBZZWFyLCkpICsNCiAgI2dlb21fbGluZShhZXMoeSA9IGVuYV9tdzcsIGNvbG9yID0gInByZXZpc3RvIC0gQ29udHJhZmFjdHVhbCIpLCBzaXplID0gMC43LGFscGhhPS42KSArDQogIGdlb21fbGluZShhZXMoeSA9IGVuYV9tdzcvMTAwMCwgY29sb3IgPSAiT2JzZXJ2YWRvIC0gQ29udHJhZmFjdHVhbCAyMDI2IiksIHNpemUgPSAxLCBsaW5ldHlwZSA9ICJkYXNoZWQiKSArI2ZhY2V0X3dyYXAofm5vbV9zdWJzaXN0ZW1hLngsc2NhbGVzID0gImZyZWUiKSsNCiAgbGFicyh0aXRsZSA9ICJJbXBhY3RvIGzDrXF1aWRvIGRvIGNsaW1hIHJlY2VudGUgc29icmUgYSBHZXJhw6fDo28iLHN1YnRpdGxlID0gIk9ic2VydmFkbyAtIENvbnRyYWZhY3R1YWwgMjAyNiIsDQogICAgICAgeSA9ICJQZW5hbGlkYWRlIENsaW3DoXRpY2EgbmEgR2VyYcOnw6NvIEhpZHJvZWzDqXRpY2EgKE1XbcOqcykiLCB4ID0gIkRhdGEiKSArDQogICAgZ2VvbV9yaWJib24oYWVzKHltaW49ZW5hX213Ny8xMDAwLHltYXg9MCksYWxwaGE9LjQsZmlsbCA9ICJmaXJlYnJpY2siLCkrDQoNCiAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9IGMoIk9ic2VydmFkbyIgPSAiYmxhY2siLCAiQ29udHJhZmFjdHVhbCAyMDI2IiA9ICJibHVlIikpICsNCiAgdGhlbWVfbWluaW1hbCgpDQpgYGANCg0KYGBge3J9DQpuZXdkYXRhX20yICU+JSANCiAgIG11dGF0ZShtZXMgPSBmbG9vcl9kYXRlKGRhdGUsIHVuaXQgPSAibW9udGgiKSwNCiAgICAgICAgICBwZW5hbGlkYWRlMT1nZXJfaGF0LWdlcl9oYXRfY2YsDQogICAgICAgICAgI3BlbmFsaWRhZGUyPWVuYV9tdzctY2xpbTIwMjZfaGF0LA0KICAgICAgICAgICkgJT4lIA0KDQogIGdyb3VwX2J5KFllYXIsbm9tX3N1YnNpc3RlbWEueCkgJT4lc3VtbWFyaXNlKHBlbmFsaWRhZGVfZ2VyYcOnw6NvX2hpZHJvPXN1bShwZW5hbGlkYWRlX2dlcmHDp8Ojb19oaWRybyxuYS5ybT1UKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgI2NsaW0yMDI2X2hhdD1zdW0ocGVuYWxpZGFkZTIsbmEucm09VCkNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKSAlPiUNCiAgZ2dwbG90KGFlcyh4ID0gWWVhciwpKSArDQogICNnZW9tX2xpbmUoYWVzKHkgPSBlbmFfbXc3LCBjb2xvciA9ICJwcmV2aXN0byAtIENvbnRyYWZhY3R1YWwiKSwgc2l6ZSA9IDAuNyxhbHBoYT0uNikgKw0KICBnZW9tX2xpbmUoYWVzKHkgPSBwZW5hbGlkYWRlX2dlcmHDp8Ojb19oaWRyby8xMDAwLCBjb2xvciA9ICJPYnNlcnZhZG8gLSBDb250cmFmYWN0dWFsIDIwMjYiKSwgc2l6ZSA9IDEsIGxpbmV0eXBlID0gImRhc2hlZCIpICtmYWNldF93cmFwKH5ub21fc3Vic2lzdGVtYS54LHNjYWxlcyA9ICJmcmVlIikrDQogIGxhYnModGl0bGUgPSAiSW1wYWN0byBsw61xdWlkbyBkbyBjbGltYSByZWNlbnRlIHNvYnJlIGEgR2VyYcOnw6NvIHBvciBzdWJzaXN0ZW1hIixzdWJ0aXRsZSA9ICJPYnNlcnZhZG8gLSBDb250cmFmYWN0dWFsIDIwMjYiLA0KICAgICAgIHkgPSAiUGVuYWxpZGFkZSBDbGltw6F0aWNhIG5hIEdlcmHDp8OjbyBIaWRyb2Vsw6l0aWNhIChNV23DqnMpIiwgeCA9ICJEYXRhIikgKw0KICAgIGdlb21fcmliYm9uKGFlcyh5bWluPXBlbmFsaWRhZGVfZ2VyYcOnw6NvX2hpZHJvLzEwMDAseW1heD0wKSxhbHBoYT0uNCxmaWxsID0gImZpcmVicmljayIsKSsNCg0KICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gYygiT2JzZXJ2YWRvIiA9ICJibGFjayIsICJDb250cmFmYWN0dWFsIDIwMjYiID0gImJsdWUiKSkgKw0KICB0aGVtZV9taW5pbWFsKCkNCmBgYA0KDQpgYGB7cn0NCm5ld2RhdGFfbTIgJT4lIA0KICAgbXV0YXRlKHBlbmFsaWRhZGUxPWdlcl9oYXQtZ2VyX2hhdF9jZiwNCiAgICAgICAgICBwZW5hbGlkYWRlX3BlcmM9Z2VyX2hhdC9nZXJfaGF0X2NmLA0KICAgICAgICAgICNwZW5hbGlkYWRlMj1lbmFfbXc3LWNsaW0yMDI2X2hhdCwNCiAgICAgICAgICApICU+JSANCg0KICBncm91cF9ieSgsbm9tX3N1YnNpc3RlbWEueCkgJT4lc3VtbWFyaXNlKHBlbmFsaWRhZGUxPXN1bShwZW5hbGlkYWRlMSxuYS5ybT1UKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdlcl9oYXQ9c3VtKGdlcl9oYXQsbmEucm09VCksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBnZXJfaGF0X2NmPXN1bShnZXJfaGF0X2NmLG5hLnJtPVQpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcGVuYWxpZGFkZV9wZXJjPW1lYW4ocGVuYWxpZGFkZV9wZXJjLG5hLnJtPVQpDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICNjbGltMjAyNl9oYXQ9c3VtKHBlbmFsaWRhZGUyLG5hLnJtPVQpDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICkgJT4lIG11dGF0ZShjdXN0b19maW5hbmNlaXJvX21hcmdpbmFsPXBlbmFsaWRhZGUxKjEwMCktPnBlbmFsaWRhZGVfaGlkcmljbw0KcGVuYWxpZGFkZV9oaWRyaWNvDQpgYGANCg0KQSBUYWJlbGEgcmVzdW1lIG9zIHJlc3VsdGFkb3MgcXVhbnRpdGF0aXZvcy4gQXMgY29sdW5hcyByZXBvcnRhbSBhIGdlcmHDp8OjbyBwcmV2aXN0YSByZWFsIChnZXJfaGF0KSwgbyBjb250cmFmYWN0dWFsIChnZXJfaGF0X2NmKSwgYSBwZW5hbGlkYWRlIGFic29sdXRhIChNV23DqnMpIGUgYSBwZW5hbGlkYWRlIHBlcmNlbnR1YWwgbcOpZGlhICglKS4gT3MgdmFsb3JlcyBpbmRpY2FtIHF1ZToNCg0KLSAgIE8gKipTdWRlc3RlKiogcmVnaXN0cm91IGEgbWFpb3IgcGVuYWxpZGFkZSBhYnNvbHV0YSAo4omIIOKAkzMsNSBtaWxow7VlcyBkZSBNV23DqnMpLCBjb20gcGVyZGEgbcOpZGlhIGRlICoqNCw0JSoqLg0KDQotICAgTyAqKk5vcmRlc3RlKiogcGVyZGV1IOKJiCDigJMxIG1pbGjDo28gZGUgTVdtw6pzICjigJMxMyw1JSksIGNvbmZpcm1hbmRvIHZ1bG5lcmFiaWxpZGFkZSBlc3RydXR1cmFsLg0KDQotICAgTyAqKlN1bCoqIGFwcmVzZW50b3UgcGVuYWxpZGFkZSBtZW5vciBlbSB0ZXJtb3MgcmVsYXRpdm9zICjigJM5LDIlKSwgbWFzIGNvbSBhbHRhIHZhcmlhYmlsaWRhZGUgaW50ZXJhbnVhbC4NCg0KLSAgIE8gKipOb3J0ZSoqIGZvaSBvIMO6bmljbyBzdWJzaXN0ZW1hIGEgbWFudGVyIG3DqWRpYSBjb250cmFmYWN0dWFsIHByw7N4aW1hIMOgIHJlYWwsIHJlZmxldGluZG8gZXF1aWzDrWJyaW8gbWFpcyBmYXZvcsOhdmVsIGVudHJlIGNsaW1hIGUgYXJtYXplbmFtZW50by4NCg0KYGBge3J9DQpuZXdkYXRhX20xJGdlcl9oYXRfY2YgPC0gbmV3ZGF0YV9tMiRnZXJfaGF0X2NmIA0KbmV3ZGF0YV9tMSRwZW5hbGlkYWRlX2dlcmHDp8Ojb19oaWRybyA8LSBuZXdkYXRhX20yJHBlbmFsaWRhZGVfZ2VyYcOnw6NvX2hpZHJvIA0KDQpgYGANCg0KIyBNb2RlbG8gZGUgUHJvcGFnYcOnw6NvIHBhcmEgb3V0cmFzIGZvbnRlcyBkZSBlbmVyZ2lhDQoNCmBgYHtyfQ0KZ2VyJG5vbV90aXBvY29tYnVzdGl2ZWwgJT4lIHVuaXF1ZSgpDQpnZXIgJT4lbXV0YXRlKHVzaW5hX2ZvbnRlPXBhc3RlMCgiZ2VyXyIsbm9tX3RpcG91c2luYSkpICU+JSANCiAgZmlsdGVyKCFub21fc3Vic2lzdGVtYT09IlBBUkFHVUFJIikgJT4lICMsIl8iLG5vbV90aXBvdXNpbmEpKSAlPiUgDQogIG11dGF0ZSh1c2luYV9mb250ZT1jYXNlX3doZW4odXNpbmFfZm9udGU9PSJnZXJfQk9NQkVBTUVOVE8ifiJnZXJfSElEUk9FTMOJVFJJQ0EiLA0KICAgICAgICAgICAgICAgICAgIFRSVUV+dXNpbmFfZm9udGUpKSAlPiUgIywiXyIsbm9tX3RpcG91c2luYSkpICU+JSANCg0KICBncm91cF9ieShkYXRlLG5vbV9zdWJzaXN0ZW1hLHVzaW5hX2ZvbnRlLHZhbF9nZXJhY2FvX2RheV9zdWJzaXN0ZW1hKSAlPiUgDQogIHN1bW1hcmlzZShnZXI9c3VtKHZhbF9nZXJhY2FvLG5hLnJtID0gVCkpICU+JSB1bmdyb3VwKCkgJT4lIA0KICBzcHJlYWQodXNpbmFfZm9udGUsZ2VyLGZpbGwgPSAwKSAlPiUgamFuaXRvcjo6Y2xlYW5fbmFtZXMoKSAlPiUgDQogIG11dGF0ZSgpLT5nZXJhX2VuZXJnX2RheQ0KZ2VyYV9lbmVyZ19kYXkkZG95ICAgIDwtIGx1YnJpZGF0ZTo6eWRheShnZXJhX2VuZXJnX2RheSRkYXRlKQ0KZ2VyYV9lbmVyZ19kYXkkZG93ICAgIDwtIGx1YnJpZGF0ZTo6d2RheShnZXJhX2VuZXJnX2RheSRkYXRlLCBsYWJlbD1UUlVFLCBhYmJyPVRSVUUpDQpnZXJhX2VuZXJnX2RheSRtb250aCAgPC0gbHVicmlkYXRlOjptb250aChnZXJhX2VuZXJnX2RheSRkYXRlKQ0KZ2VyYV9lbmVyZ19kYXkkdHJlbmQgIDwtIGx1YnJpZGF0ZTo6eWVhcihnZXJhX2VuZXJnX2RheSRkYXRlKQ0KYGBgDQoNCmBgYHtyIGZpZy5oZWlnaHQ9MTUsIGZpZy53aWR0aD0xMH0NCmdlciAlPiUNCiAgbXV0YXRlKHVzaW5hX2ZvbnRlPXBhc3RlMCgiZ2VyXyIsbm9tX3RpcG91c2luYSksDQogICAgICAgICBtZXMgPSBmbG9vcl9kYXRlKGRhdGUsIHVuaXQgPSAibW9udGgiKSkgJT4lIyBzZWxlY3QodXNpbmFfZm9udGUpICU+JSB1bmlxdWUoKQ0KICBtdXRhdGUodXNpbmFfZm9udGU9Y2FzZV93aGVuKHVzaW5hX2ZvbnRlPT0iZ2VyX0JPTUJFQU1FTlRPIn4iZ2VyX0hJRFJPRUzDiVRSSUNBIiwNCiAgICAgICAgICAgICAgICAgICBUUlVFfnVzaW5hX2ZvbnRlKSkgJT4lICMsIl8iLG5vbV90aXBvdXNpbmEpKSAlPiUgDQogIGdyb3VwX2J5KG1lcyx1c2luYV9mb250ZSxub21fc3Vic2lzdGVtYSkgJT4lICNub21fc3Vic2lzdGVtYQ0KICBzdW1tYXJpc2UoZ2VyPW1lYW4odmFsX2dlcmFjYW8sbmEucm0gPSBUKSkgJT4lIA0KICAgIGdncGxvdChhZXMoeCA9IG1lcyx5PWdlcixjb2w9bm9tX3N1YnNpc3RlbWEpKSArDQogICAgZ2VvbV9saW5lKCkgK2ZhY2V0X3dyYXAofnVzaW5hX2ZvbnRlLHNjYWxlcyA9ICJmcmVlIixuY29sID0gMikrDQogIGxhYnModGl0bGUgPSAiSW1wYWN0byBsw61xdWlkbyBkbyBjbGltYSByZWNlbnRlIHNvYnJlIGEgRU5BIHBvciBzdWJzaXN0ZW1hIixzdWJ0aXRsZSA9ICJPYnNlcnZhZG8gLSBDb250cmFmYWN0dWFsIDIwMjYiLA0KICAgICAgIHkgPSAiZ2VyIChHV23DqnMpIiwgeCA9ICJEYXRhIikgKw0KICB0aGVtZV9taW5pbWFsKCkNCmBgYA0KDQpgYGB7cn0NCnBsZF9mdWxsICU+JQ0KICAgICAgICAgICAgICAgICBtdXRhdGUoDQogICAgICAgICAgICAgICAgICAgZ2VyX2hpZHJvZWxldHJpY2EgPSBpZmVsc2UoZ2VyX2hpZHJvZWxldHJpY2EgPT0gMCwgMSwgZ2VyX2hpZHJvZWxldHJpY2EpLA0KICAgICAgICAgICAgICAgICAgIGdlcl9mb3Rvdm9sdGFpY2EgPSBpZmVsc2UoZ2VyX2ZvdG92b2x0YWljYSA9PSAwLCAxLCBnZXJfZm90b3ZvbHRhaWNhKSwNCiAgICAgICAgICAgICAgICAgICBnZXJfZW9saWVsZXRyaWNhID0gaWZlbHNlKGdlcl9lb2xpZWxldHJpY2EgPT0gMCwgMSwgZ2VyX2VvbGllbGV0cmljYSksDQogICAgICAgICAgICAgICAgICAgZ2VyX3Rlcm1pY2EgPSBpZmVsc2UoZ2VyX3Rlcm1pY2EgPT0gMCwgMSwgZ2VyX3Rlcm1pY2EpLA0KICAgICAgICAgICAgICAgICAgIERlbWFuZGEgPSBnZXJfZW9saWVsZXRyaWNhK2dlcl9mb3Rvdm9sdGFpY2ErZ2VyX2hpZHJvZWxldHJpY2ErZ2VyX3Rlcm1pY2ErZ2VyX251Y2xlYXIsDQogICAgICAgICAgICAgICAgICkgJT4lIA0KICBnZ3Bsb3QoYWVzKGRhdGUsKSkrDQogICAgZ2VvbV9saW5lKGFlcyh5PURlbWFuZGEpLGNvbD0icmVkIikrDQogIGdlb21fbGluZShhZXMoeT12YWxfZ2VyYWNhb19kYXlfc3Vic2lzdGVtYSxhbHBoYSA9IDAuMSksY29sPSJibGFjayIpK2ZhY2V0X3dyYXAofm5vbV9zdWJzaXN0ZW1hLngsc2NhbGVzID0gImZyZWVfeSIpDQpgYGANCg0KYGBge3J9DQpnZXJhX2VuZXJnX2RheSAlPiUgc3RyKCkNCm9wdGlvbnMoc2NpcGVuID0gOCkNCmxtKGdlcl90ZXJtaWNhfg0KICAgICBnZXJfaGlkcm9lbGV0cmljYSsNCiAgICAgZ2VyX2VvbGllbGV0cmljYStnZXJfZm90b3ZvbHRhaWNhK2dlcl9udWNsZWFyKyAgICANCiAgICAgbm9tX3N1YnNpc3RlbWEueCswKw0KICAgICB0cmVuZCthcy5mYWN0b3IobW9udGgpLA0KICAgZGF0YSA9Z2VyYV9lbmVyZ19kYXkpICU+JSBzdW1tYXJ5KCkNCmBgYA0KDQpgYGB7cn0NCmxtKGxvZyhnZXJfdGVybWljYSl+DQogICAgIGxvZyhnZXJfaGlkcm9lbGV0cmljYSkrDQogICAgIGdlcl9lb2xpZWxldHJpY2ErZ2VyX2ZvdG92b2x0YWljYStnZXJfbnVjbGVhcisgICAgDQogICAgIG5vbV9zdWJzaXN0ZW1hLngrMCsNCiAgICB0cmVuZCthcy5mYWN0b3IobW9udGgpLA0KLA0KICAgZGF0YSA9Z2VyYV9lbmVyZ19kYXkgJT4lIA0KICAgICBtdXRhdGUoZ2VyX2hpZHJvZWxldHJpY2E9Y2FzZV93aGVuKGdlcl9oaWRyb2VsZXRyaWNhPDAuMDF+MSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFRSVUV+Z2VyX2hpZHJvZWxldHJpY2EpLA0KICAgICAgICAgICAgZ2VyX3Rlcm1pY2E9Y2FzZV93aGVuKGdlcl90ZXJtaWNhPDAuMDF+MSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFRSVUV+Z2VyX3Rlcm1pY2EpKQ0KICAgKSAlPiUgc3VtbWFyeSgpDQpgYGANCg0KYGBge3J9DQpnZXJhX2VuZXJnX2RheSRkYXRlICU+JSBzdW1tYXJ5KCkNCmxtKGdlcl90ZXJtaWNhfg0KICAgICBnZXJfaGlkcm9lbGV0cmljYSsNCiAgICAgZ2VyX2VvbGllbGV0cmljYStnZXJfZm90b3ZvbHRhaWNhK2dlcl9udWNsZWFyKyAgICANCiAgICAgbm9tX3N1YnNpc3RlbWEueCswKw0KICAgICB0cmVuZCthcy5mYWN0b3IobW9udGgpLA0KLA0KICAgZGF0YSA9Z2VyYV9lbmVyZ19kYXkgJT4lIGZpbHRlcihkYXRlPjIwMTgtMDEtMDEgKSkgJT4lIHN1bW1hcnkoKQ0KYGBgDQoNCmBgYHtyfQ0KbG0oZ2VyX3Rlcm1pY2F+DQogICAgIGdlcl9oaWRyb2VsZXRyaWNhKw0KICAgICBnZXJfZW9saWVsZXRyaWNhK2dlcl9mb3Rvdm9sdGFpY2ErZ2VyX251Y2xlYXIgKw0KICAgICB0cmVuZCthcy5mYWN0b3IobW9udGgpDQogICAgICNub21fc3Vic2lzdGVtYSswDQogICAgICwNCiAgIGRhdGEgPWdlcmFfZW5lcmdfZGF5KSAlPiUgc3VtbWFyeSgpDQpgYGANCg0KYGBge3J9DQpsbShnZXJfdGVybWljYX4NCiAgICAgZ2VyX2hpZHJvZWxldHJpY2Eqbm9tX3N1YnNpc3RlbWEueCsNCiAgICAgZ2VyX2VvbGllbGV0cmljYStnZXJfZm90b3ZvbHRhaWNhK2dlcl9udWNsZWFyICsNCiAgICAgdHJlbmQrYXMuZmFjdG9yKG1vbnRoKSwNCiAgICAgI25vbV9zdWJzaXN0ZW1hKzAsDQogICBkYXRhID1nZXJhX2VuZXJnX2RheSkgJT4lIHN1bW1hcnkoKQ0KYGBgDQoNCmBgYHtyfQ0KDQpsaWJyYXJ5KG1nY3YpDQogICAgIyBnZXJfZW9saWVsZXRyaWNhK2dlcl9mb3Rvdm9sdGFpY2ErZ2VyX251Y2xlYXIgKw0KICAgICMgdHJlbmQrYXMuZmFjdG9yKG1vbnRoKQ0KbV9nYW1fZm9udGVzIDwtIGJhbShnZXJfdGVybWljYSAgfiBzKGdlcl9oaWRyb2VsZXRyaWNhLCBrPTMpICsgcyhnZXJfZW9saWVsZXRyaWNhLCBrPTQpICsNCiAgICAgICAgICAgICAgICAgICAgICBzKGdlcl9mb3Rvdm9sdGFpY2EsIGs9MykgICArICAgICAgICAgICAgICsgcyhnZXJfbnVjbGVhciwgaz0zKSArDQogICAgICAgICAgICAgICAgICAgICAgcyh0cmVuZCwgaz0zKSArIHMobW9udGgsIGs9NCkgKw0KICAgICAgICAgICAgICAgICAgICAgICNzKERlbWFuZGEsIGs9NCkrDQogICAgICAgICAgICAgICAgICAgICAgcyhub21fc3Vic2lzdGVtYS54LCBicyA9ICJyZSIpLA0KICAgICAgICAgICAgIGRhdGEgPSBnZXJhX2VuZXJnX2RheSAlPiUgDQogICAgICAgICAgICAgICBtdXRhdGUoRGVtYW5kYSA9IGdlcl9lb2xpZWxldHJpY2ErZ2VyX2ZvdG92b2x0YWljYStnZXJfaGlkcm9lbGV0cmljYStnZXJfdGVybWljYStnZXJfbnVjbGVhciwNCikpDQpzdW1tYXJ5KG1fZ2FtX2ZvbnRlcykNCmBgYA0KDQpgYGB7cn0NCmdhbS5jaGVjayhtX2dhbV9mb250ZXMpICAgICAgICAgICAgICAgICAgICMgY2hlY2EgcmVzw61kdW9zLCBRUS1wbG90LCBrLWFkZXF1YcOnw6NvDQpgYGANCg0KYGBge3J9DQpjb25jdXJ2aXR5KG1fZ2FtX2ZvbnRlcywgZnVsbD1UUlVFKSAgICAgICAjIG11bHRpY29saW5lYXJpZGFkZSBuw6NvIGxpbmVhcg0KcGxvdChtX2dhbV9mb250ZXMsIHBhZ2VzPTQsIHNjaGVtZT0xLCBzaGFkZT1UUlVFLCBzZT1UUlVFLHNjYWxlcyA9ICJmcmVlIikNCmBgYA0KDQojIyMgQ29udHJhZmFjdHVhbCBPdXRyYXMgZm9udGVzIGRlIGVuZXJnaWENCg0KYGBge3J9DQojbmV3ZGF0YV9tMSRlYXJfaGF0X2NmPC1jbGltX2luJGNsaW0yMDI2X2hhdA0KDQpuZXdkYXRhX20xICU+JSANCiAgZ3JvdXBfYnkobm9tX3N1YnNpc3RlbWEueCxkYXRlKSAlPiUgDQogIHN1bW1hcmlzZShlYXI9c3VtKGVhcl9yZXNlcnZhdG9yaW9fc3Vic2lzdGVtYV9wcm9wcmlvX213bWVzLG5hLnJtID0gVCksDQogICAgICAgICAgICB2YWxfZ2VyYWNhbz1zdW0odmFsX2dlcmFjYW8pLA0KICAgICAgICAgICAgZWFyX2hhdD1zdW0oZWFyX2hhdCxuYS5ybSA9IFQpLA0KICAgICAgICAgICAgZ2VyX2hhdD1zdW0oZ2VyX2hhdCxuYS5ybSA9IFQpLA0KICAgICAgICAgICAgcGVuYWxpZGFkZV9nZXJhw6fDo29faGlkcm89c3VtKHBlbmFsaWRhZGVfZ2VyYcOnw6NvX2hpZHJvLG5hLnJtID0gVCksDQogICAgICAgICAgICBnZXJfaGF0X2NmPXN1bShnZXJfaGF0X2NmLG5hLnJtID0gVCksDQogICAgICAgICAgICBlYXJfaGF0X2NmPXN1bShlYXJfaGF0X2NmLG5hLnJtID0gVCkpICU+JSANCiAgcmlnaHRfam9pbihnZXJhX2VuZXJnX2RheSxieSA9IGMoIm5vbV9zdWJzaXN0ZW1hLngiPSJub21fc3Vic2lzdGVtYSIsImRhdGUiPSJkYXRlIikpLT5nZXJhX2VuZXJnX2RheQ0KZ2VyYV9lbmVyZ19kYXkNCmBgYA0KDQpgYGB7cn0NCmdlcmFfZW5lcmdfZGF5ICU+JSANCiAgZ3JvdXBfYnkodHJlbmQpICU+JSBzdW1tYXJpc2UodmFsX2dlcmFjYW89c3VtKGdlcl9oYXQsbmEucm0gPSBUKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZ2VyX2hpZHJvZWxldHJpY2E9c3VtKGdlcl9oaWRyb2VsZXRyaWNhLG5hLnJtID0gVCkpICU+JSANCiAgZ2dwbG90KGFlcyh0cmVuZCkpKw0KICBnZW9tX2xpbmUoYWVzKHk9dmFsX2dlcmFjYW8pLGNvbD0iYmx1ZSIpKw0KICBnZW9tX2xpbmUoYWVzKHk9Z2VyX2hpZHJvZWxldHJpY2EpLGNvbD0icmVkIikrdGhlbWVfbWluaW1hbCgpDQpwcmVkaWN0KG1fZ2FtX2ZvbnRlcyxuZXdkYXRhID0gZ2VyICU+JSANCiAgbXV0YXRlKHZhbF9nZXJhY2FvPWdlcl9oYXQpICkNCg0KYGBgDQoNCmBgYHtyfQ0KZ2VyYV9lbmVyZ19kYXkkZ2VyX3Rlcm1pY2FfcHJldmlzdGE8LXByZWRpY3QobV9nYW1fZm9udGVzLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbmV3ZGF0YSA9IGdlcmFfZW5lcmdfZGF5ICU+JQ0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtdXRhdGUoDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBub21fc3Vic2lzdGVtYT1ub21fc3Vic2lzdGVtYS54LA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgRGVtYW5kYSA9IGdlcl9lb2xpZWxldHJpY2ErZ2VyX2ZvdG92b2x0YWljYStnZXJfaGlkcm9lbGV0cmljYStnZXJfdGVybWljYStnZXJfbnVjbGVhcikNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICkNCmdlcmFfZW5lcmdfZGF5JGdlcl90ZXJtaWNhX3ByZXZpc3RhX2NmPC1wcmVkaWN0KG1fZ2FtX2ZvbnRlcywNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5ld2RhdGEgPSBnZXJhX2VuZXJnX2RheSAlPiUgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG11dGF0ZShnZXJfaGlkcm9lbGV0cmljYT1nZXJfaGlkcm9lbGV0cmljYStwZW5hbGlkYWRlX2dlcmHDp8Ojb19oaWRybywNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5vbV9zdWJzaXN0ZW1hPW5vbV9zdWJzaXN0ZW1hLngsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBEZW1hbmRhID0gZ2VyX2VvbGllbGV0cmljYStnZXJfZm90b3ZvbHRhaWNhK2dlcl9oaWRyb2VsZXRyaWNhK2dlcl90ZXJtaWNhK2dlcl9udWNsZWFyKQ0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKQ0KYGBgDQoNCmBgYHtyIENvbnRyYWZhY3R1YWwgY2xpbcOhdGljbyAzKGJhc2VsaW5lIDIwMDHigJMyMDA1KX0NCmdlcmFfZW5lcmdfZGF5ICU+JSANCiAgIG11dGF0ZShtZXMgPSBmbG9vcl9kYXRlKGRhdGUsIHVuaXQgPSAibW9udGgiKSkgJT4lIA0KDQogIGdyb3VwX2J5KHRyZW5kKSAlPiVzdW1tYXJpc2UoZ2VyX3Rlcm1pY2FfcHJldmlzdGE9c3VtKGdlcl90ZXJtaWNhX3ByZXZpc3RhLG5hLnJtPVQpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICBnZXJfdGVybWljYV9wcmV2aXN0YV9jZj1zdW0oZ2VyX3Rlcm1pY2FfcHJldmlzdGFfY2YsbmEucm09VCkpICU+JQ0KICBnZ3Bsb3QoYWVzKHggPSB0cmVuZCwpKSArDQogIGdlb21fbGluZShhZXMoeSA9IGdlcl90ZXJtaWNhX3ByZXZpc3RhLzEwMDAsIGNvbG9yID0gIlByZXZpc3RvIiksIHNpemUgPSAwLjcsYWxwaGE9LjYpICsNCiAgZ2VvbV9saW5lKGFlcyh5ID0gZ2VyX3Rlcm1pY2FfcHJldmlzdGFfY2YvMTAwMCwgY29sb3IgPSAiQ29udHJhZmFjdHVhbCAyMDEwIiksIHNpemUgPSAxLCBsaW5ldHlwZSA9ICJkYXNoZWQiKSArI2ZhY2V0X3dyYXAofm5vbV9zdWJzaXN0ZW1hLngsc2NhbGVzID0gImZyZWUiKSsNCiAgZ2VvbV9yaWJib24oYWVzKHltaW49Z2VyX3Rlcm1pY2FfcHJldmlzdGEvMTAwMCx5bWF4PWdlcl90ZXJtaWNhX3ByZXZpc3RhX2NmLzEwMDApLGFscGhhPS40LGZpbGwgPSAiZmlyZWJyaWNrIiwpKw0KDQogIGxhYnModGl0bGUgPSAiQ29udHJhZmFjdHVhbCBiYXNlbGluZSAoY2xpbWEgbcOpZGlvIDIwMDEtMjAxMCkiLA0KICAgICAgIHkgPSAiR2VyYcOnw6NvIFRlcm1pY2EgKEdXbcOqcykiLCB4ID0gIkRhdGEiKSArDQogIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSBjKCJQcmV2aXN0byIgPSAiYmxhY2siLCAiQ29udHJhZmFjdHVhbCAyMDEwIiA9ICJibHVlIikpICsNCiAgdGhlbWVfbWluaW1hbCgpDQoNCg0KZ2VyYV9lbmVyZ19kYXkgJT4lIA0KICAgbXV0YXRlKG1lcyA9IGZsb29yX2RhdGUoZGF0ZSwgdW5pdCA9ICJtb250aCIpKSAlPiUgDQoNCiAgZ3JvdXBfYnkodHJlbmQsbm9tX3N1YnNpc3RlbWEueCkgJT4lc3VtbWFyaXNlKGVuYV9tdzc9c3VtKGdlcl90ZXJtaWNhX3ByZXZpc3RhLG5hLnJtPVQpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjbGltMjAyNl9oYXQ9c3VtKGdlcl90ZXJtaWNhX3ByZXZpc3RhX2NmLG5hLnJtPVQpKSAlPiUNCiAgZ2dwbG90KGFlcyh4ID0gdHJlbmQsKSkgKw0KICBnZW9tX2xpbmUoYWVzKHkgPSBlbmFfbXc3LzEwMDAsIGNvbG9yID0gIlByZXZpc3RvIiksIHNpemUgPSAwLjcsYWxwaGE9LjYpICsNCiAgZ2VvbV9saW5lKGFlcyh5ID0gY2xpbTIwMjZfaGF0LzEwMDAsIGNvbG9yID0gIkNvbnRyYWZhY3R1YWwgMjAxMCIpLCBzaXplID0gMSwgbGluZXR5cGUgPSAiZGFzaGVkIikgK2ZhY2V0X3dyYXAofm5vbV9zdWJzaXN0ZW1hLngsc2NhbGVzID0gImZyZWUiKSsNCiAgbGFicyh0aXRsZSA9ICJDb250cmFmYWN0dWFsIGJhc2VsaW5lIChjbGltYSBtw6lkaW8gMjAwMS0yMDEwKSIsDQogICAgICAgeSA9ICJHZXJhw6fDo28gVGVybWljYSAoR1dtw6pzKSIsIHggPSAiRGF0YSIpICsNCiAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9IGMoIlByZXZpc3RvIiA9ICJibGFjayIsICJDb250cmFmYWN0dWFsIDIwMTAiID0gImJsdWUiKSkgKw0KICB0aGVtZV9taW5pbWFsKCkNCmBgYA0KDQpgYGB7ciB9DQpnZXJhX2VuZXJnX2RheSAlPiUgDQogICBtdXRhdGUobWVzID0gZmxvb3JfZGF0ZShkYXRlLCB1bml0ID0gIm1vbnRoIiksDQogICAgICAgICAgcGVuYWxpZGFkZV90ZXJtaWNvPWdlcl90ZXJtaWNhX3ByZXZpc3RhX2NmLWdlcl90ZXJtaWNhX3ByZXZpc3RhLA0KICAgICAgICAgICNwZW5hbGlkYWRlMj1lbmFfbXc3LWNsaW0yMDI2X2hhdCwNCiAgICAgICAgICApLT5nZXJhX2VuZXJnX2RheQ0KZ2VyYV9lbmVyZ19kYXkgJT4lIA0KICAgbXV0YXRlKG1lcyA9IGZsb29yX2RhdGUoZGF0ZSwgdW5pdCA9ICJtb250aCIpLA0KICAgICAgICAgIHBlbmFsaWRhZGUxPWdlcl90ZXJtaWNhX3ByZXZpc3RhX2NmLWdlcl90ZXJtaWNhX3ByZXZpc3RhLA0KICAgICAgICAgICNwZW5hbGlkYWRlMj1lbmFfbXc3LWNsaW0yMDI2X2hhdCwNCiAgICAgICAgICApICU+JSANCg0KICBncm91cF9ieSh0cmVuZCkgJT4lc3VtbWFyaXNlKGVuYV9tdzc9c3VtKHBlbmFsaWRhZGUxLG5hLnJtPVQpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjY2xpbTIwMjZfaGF0PXN1bShwZW5hbGlkYWRlMixuYS5ybT1UKQ0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICApICU+JQ0KICBnZ3Bsb3QoYWVzKHggPSB0cmVuZCwpKSArDQogICNnZW9tX2xpbmUoYWVzKHkgPSBlbmFfbXc3LCBjb2xvciA9ICJwcmV2aXN0byAtIENvbnRyYWZhY3R1YWwiKSwgc2l6ZSA9IDAuNyxhbHBoYT0uNikgKw0KICBnZW9tX2xpbmUoYWVzKHkgPSBlbmFfbXc3LzEwMDAsIGNvbG9yID0gIk9ic2VydmFkbyAtIENvbnRyYWZhY3R1YWwgMjAyNiIpLCBzaXplID0gMSwgbGluZXR5cGUgPSAiZGFzaGVkIikgKyNmYWNldF93cmFwKH5ub21fc3Vic2lzdGVtYS54LHNjYWxlcyA9ICJmcmVlIikrDQogIGxhYnModGl0bGUgPSAiSW1wYWN0byBsw61xdWlkbyBkbyBjbGltYSByZWNlbnRlIHNvYnJlIGEgR2VyYcOnw6NvIixzdWJ0aXRsZSA9ICJPYnNlcnZhZG8gLSBDb250cmFmYWN0dWFsIDIwMjYiLA0KICAgICAgIHkgPSAiUGVuYWxpZGFkZSBDbGltw6F0aWNhIG5hIFRlcm1pY2EgKE1XbcOqcykiLCB4ID0gIkRhdGEiKSArDQogICAgZ2VvbV9yaWJib24oYWVzKHltaW49ZW5hX213Ny8xMDAwLHltYXg9MCksYWxwaGE9LjQsZmlsbCA9ICJmaXJlYnJpY2siLCkrDQoNCiAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9IGMoIk9ic2VydmFkbyIgPSAiYmxhY2siLCAiQ29udHJhZmFjdHVhbCAyMDI2IiA9ICJibHVlIikpICsNCiAgdGhlbWVfbWluaW1hbCgpDQoNCmdlcmFfZW5lcmdfZGF5ICU+JSANCiAgIG11dGF0ZShtZXMgPSBmbG9vcl9kYXRlKGRhdGUsIHVuaXQgPSAibW9udGgiKSwNCiAgICAgICAgICBwZW5hbGlkYWRlX3Rlcm1pY2E9Z2VyX3Rlcm1pY2FfcHJldmlzdGFfY2YtZ2VyX3Rlcm1pY2FfcHJldmlzdGEsDQogICAgICAgICAgI3BlbmFsaWRhZGUyPWVuYV9tdzctY2xpbTIwMjZfaGF0LA0KICAgICAgICAgICkgJT4lIA0KDQogIGdyb3VwX2J5KHRyZW5kLG5vbV9zdWJzaXN0ZW1hLngpICU+JXN1bW1hcmlzZShwZW5hbGlkYWRlX3Rlcm1pY2E9c3VtKHBlbmFsaWRhZGVfdGVybWljYSxuYS5ybT1UKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgI2NsaW0yMDI2X2hhdD1zdW0ocGVuYWxpZGFkZTIsbmEucm09VCkNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKSAlPiUNCiAgZ2dwbG90KGFlcyh4ID0gdHJlbmQsKSkgKw0KICAjZ2VvbV9saW5lKGFlcyh5ID0gZW5hX213NywgY29sb3IgPSAicHJldmlzdG8gLSBDb250cmFmYWN0dWFsIiksIHNpemUgPSAwLjcsYWxwaGE9LjYpICsNCiAgZ2VvbV9saW5lKGFlcyh5ID0gcGVuYWxpZGFkZV90ZXJtaWNhLzEwMDAsIGNvbG9yID0gIk9ic2VydmFkbyAtIENvbnRyYWZhY3R1YWwgMjAyNiIpLCBzaXplID0gMSwgbGluZXR5cGUgPSAiZGFzaGVkIikgK2ZhY2V0X3dyYXAofm5vbV9zdWJzaXN0ZW1hLngsc2NhbGVzID0gImZyZWUiKSsNCiAgbGFicyh0aXRsZSA9ICJJbXBhY3RvIGzDrXF1aWRvIGRvIGNsaW1hIHJlY2VudGUgc29icmUgYSBHZXJhw6fDo28iLHN1YnRpdGxlID0gIk9ic2VydmFkbyAtIENvbnRyYWZhY3R1YWwgMjAyNiIsDQogICAgICAgeSA9ICJQZW5hbGlkYWRlIENsaW3DoXRpY2EgbmEgVGVybWljYSAoTVdtw6pzKSIsIHggPSAiRGF0YSIpICsNCiAgICBnZW9tX3JpYmJvbihhZXMoeW1pbj1wZW5hbGlkYWRlX3Rlcm1pY2EvMTAwMCx5bWF4PTApLGFscGhhPS40LGZpbGwgPSAiZmlyZWJyaWNrIiwpKw0KDQogIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSBjKCJPYnNlcnZhZG8iID0gImJsYWNrIiwgIkNvbnRyYWZhY3R1YWwgMjAyNiIgPSAiYmx1ZSIpKSArDQogIHRoZW1lX21pbmltYWwoKQ0KYGBgDQoNCmFtIG1haW9yIHZvbGF0aWxpZGFkZS4gRXNzYSBkZWNvbXBvc2nDp8OjbyByZWdpb25hbCDDqSBjcnVjaWFsIHBhcmEgYXZhbGlhciBhIGVsYXN0aWNpZGFkZSBkYSBlc2Nhc3NleiBlIG8gcmVkaXJlY2lvbmFtZW50byBkYSBwcmVzc8OjbyBwYXJhIG91dHJhcyBmb250ZXMgZGUgZ2VyYcOnw6NvLg0KDQpgYGB7cn0NCmdlcmFfZW5lcmdfZGF5ICU+JSANCiAgIG11dGF0ZShwZW5hbGlkYWRlMT1nZXJfdGVybWljYV9wcmV2aXN0YV9jZi1nZXJfdGVybWljYV9wcmV2aXN0YSwNCiAgICAgICAgICBwZW5hbGlkYWRlX3BlcmM9Z2VyX3Rlcm1pY2FfcHJldmlzdGFfY2YvZ2VyX3Rlcm1pY2FfcHJldmlzdGEsDQogICAgICAgICAgI3BlbmFsaWRhZGUyPWVuYV9tdzctY2xpbTIwMjZfaGF0LA0KICAgICAgICAgICkgJT4lIA0KDQogIGdyb3VwX2J5KCxub21fc3Vic2lzdGVtYS54KSAlPiVzdW1tYXJpc2UocGVuYWxpZGFkZTE9c3VtKHBlbmFsaWRhZGUxLG5hLnJtPVQpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZ2VyX2hhdD1zdW0oZ2VyX2hhdCxuYS5ybT1UKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdlcl9oYXRfY2Y9c3VtKGdlcl9oYXRfY2YsbmEucm09VCksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwZW5hbGlkYWRlX3BlcmM9bWVhbihwZW5hbGlkYWRlX3BlcmMsbmEucm09VCkNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgI2NsaW0yMDI2X2hhdD1zdW0ocGVuYWxpZGFkZTIsbmEucm09VCkNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKSAlPiUgbXV0YXRlKGN1c3RvX2ZpbmFuY2Vpcm9fdXNvdGVybWljbz1wZW5hbGlkYWRlMSozMDApLT5wZW5hbGlkYWRlX3Rlcm1pY28NCg0KYGBgDQoNCmBgYHtyfQ0KYmluZF9yb3dzKHBlbmFsaWRhZGVfaGlkcmljbyAlPiUgbXV0YXRlKGVzdGltYT0iSGlkcm8iKSxwZW5hbGlkYWRlX3Rlcm1pY28gJT4lIG11dGF0ZShlc3RpbWE9IlTDqXJtaWNvIikpICU+JSANCiAgc2VsZWN0KC1zdGFydHNfd2l0aCgiY3VzdG8iKSkgJT4lIA0KICBtdXRhdGUoY3VzdG9fUmVhaXM9Y2FzZV93aGVuKGVzdGltYT09IkhpZHJvIn5wZW5hbGlkYWRlMSotMTAwLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICBUUlVFfnBlbmFsaWRhZGUxKjMwMCksDQogICAgICAgICBjdXN0b19VU0Q9Y3VzdG9fUmVhaXMvNS4yDQogICAgICAgICApIA0KYGBgDQoNCmBgYHtyfQ0KYmluZF9yb3dzKHBlbmFsaWRhZGVfaGlkcmljbyAlPiUgbXV0YXRlKGVzdGltYT0iSGlkcm8iKSxwZW5hbGlkYWRlX3Rlcm1pY28gJT4lIG11dGF0ZShlc3RpbWE9IlTDqXJtaWNvIikpICU+JSANCiAgc2VsZWN0KC1zdGFydHNfd2l0aCgiY3VzdG8iKSkgJT4lIA0KICBtdXRhdGUoY3VzdG9fUmVhaXM9Y2FzZV93aGVuKGVzdGltYT09IkhpZHJvIn5wZW5hbGlkYWRlMSotMTAwLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICBUUlVFfnBlbmFsaWRhZGUxKjMwMCksDQogICAgICAgICBjdXN0b19VU0Q9Y3VzdG9fUmVhaXMvNS4yDQogICAgICAgICApICU+JSANCiAgZ2dwbG90KGFlcyh4PW5vbV9zdWJzaXN0ZW1hLngseT1jdXN0b19VU0QvMTAwMDAwMCxmaWxsPWVzdGltYSkpK2dlb21fY29sKHBvc2l0aW9uID0gImRvZGdlIikrDQogIGdlb21fdGV4dChhZXMoeT1jdXN0b19VU0QvMTAwMDAwMCsyLGxhYmVsID0gcm91bmQoY3VzdG9fVVNELzEwMDAsIDEpKSwgcG9zaXRpb249cG9zaXRpb25fZG9kZ2Uod2lkdGg9MSksIHNpemUgPSAzLGNoZWNrX292ZXJsYXA9RikrY29vcmRfZmxpcCgpKw0KICBsYWJzKHRpdGxlID0gIkN1c3RvIGVjb27DtG1pY28gZXN0aW1hZG8gZGEgcGVuYWxpZGFkZSBjbGltw6F0aWNhICgyMDEwLTIwMjMpIiwNCiAgICAgICBzdWJ0aXRsZSA9ICJDdXN0byBmaW5hbmNlaXJvIGFwcm94aW1hZG8gZG8gaW1wYWN0byBjbGltw6F0aWNvIHNvYnJlIGEgZ2VyYcOnw6NvIGhpZHJlbMOpdHJpY2EgZSB0w6lybWljYSIsDQogICAgICAgeSA9ICJDdXN0byAoVVMkIG1pbCkiLCB4ID0gIlN1YnNpc3RlbWEiKSArdGhlbWVfbWluaW1hbCgpDQpgYGANCg0KYGBge3J9DQoNCmBgYA0KDQojIyBQTEQ6IEN1c3RvIHBhcmEgbyBzaXN0ZW1hDQoNCmBgYHtyfQ0KcGxkICAgICA8LSByZWFkLmNzdigicHJlY29fc2VtYW5hbC5jc3YiKSAgICAgICAgICAgIyBQTEQgc2VtYW5hbA0KcGxkJGRhdGUgPC0gYXMuRGF0ZShwbGQkZGF0YXMpICAgIyBpZGVtIHBhcmEgYSBiYXNlIGRlIFBMRA0KcGxkJHdlZWsgIDwtIGx1YnJpZGF0ZTo6aXNvd2VlayhwbGQkZGF0YXMpDQpwbGQkeWVhciAgPC0gbHVicmlkYXRlOjp5ZWFyKHBsZCRkYXRhcykNCmBgYA0KDQpgYGB7cn0NCg0KI3BsZCRkYXRlPC1wbGQkREFUQV9JTklDSU8gJT4lIGFzX2RhdGUoKSANCnBsZCAlPiUgc3ByZWFkKFN1Ym1lcmNhZG8scHJlY28pLT5wbGQNCnBsZCRkYXRlICU+JSBtaW4oKS0+aW5pY2lvDQpwbGQgJT4lIGZpbHRlcihEQVRBX0lOSUNJTz09aW5pY2lvKQ0KZGF0YXM8LWdlcmFfZW5lcmdfZGF5JGRhdGUgJT4lIHVuaXF1ZQ0KZGF0YS5mcmFtZShkYXRhcykgJT4lIGZpbHRlcihkYXRhcz5pbmljaW8tMSkgJT4lIGFycmFuZ2UoZGF0YXMpICU+JSBsZWZ0X2pvaW4ocGxkLGJ5ID0gYygiZGF0YXMiPSJkYXRlIikpLT5kYWFzX2NvbXBsZXRhcw0KZGFhc19jb21wbGV0YXMNCmk9Mg0KZm9yIChpIGluIDE6bGVuZ3RoKGRhYXNfY29tcGxldGFzJEFOTykpIHsjbGVuZ3RoKGRhYXNfY29tcGxldGFzJEFOTykNCiAgcHJpbnQoaSkNCiAgaWYgKGlzLm5hKGRhYXNfY29tcGxldGFzJEFOT1tpXSkpIHsNCiAgICBkYWFzX2NvbXBsZXRhcyRBTk9baV08LWRhYXNfY29tcGxldGFzJEFOT1tpLTFdDQogICAgZGFhc19jb21wbGV0YXMkTUVTW2ldPC1kYWFzX2NvbXBsZXRhcyRNRVNbaS0xXQ0KICAgIGRhYXNfY29tcGxldGFzJFNFTUFOQVtpXTwtZGFhc19jb21wbGV0YXMkU0VNQU5BW2ktMV0NCiAgICBkYWFzX2NvbXBsZXRhcyREQVRBX0ZJTVtpXTwtZGFhc19jb21wbGV0YXMkREFUQV9GSU1baS0xXQ0KICAgIGRhYXNfY29tcGxldGFzJFNVREVTVEVbaV08LWRhYXNfY29tcGxldGFzJFNVREVTVEVbaS0xXQ0KICAgIGRhYXNfY29tcGxldGFzJFNVTFtpXTwtZGFhc19jb21wbGV0YXMkU1VMW2ktMV0NCiAgICBkYWFzX2NvbXBsZXRhcyROT1JERVNURVtpXTwtZGFhc19jb21wbGV0YXMkTk9SREVTVEVbaS0xXQ0KICAgIGRhYXNfY29tcGxldGFzJE5PUlRFW2ldPC1kYWFzX2NvbXBsZXRhcyROT1JURVtpLTFdDQoNCiAgICANCiAgfQ0KICANCn0gIA0KZGFhc19jb21wbGV0YXMgJT4lIGdhdGhlcihrZXkgPSAibm9tX3N1YnNpdGVtYSIsdmFsdWUgPSAicHJlY28iLGMoIk5PUkRFU1RFIiwiU1VERVNURSIsIlNVTCIsIk5PUlRFIikpLT5wbGQNCmBgYA0KDQpgYGB7cn0NCnNlcmllIDwtIGRhYXNfY29tcGxldGFzICU+JQ0KICBwdWxsKE5PUkRFU1RFKSAlPiUNCiAgdHMoc3RhcnQgPSAgYygyMDAxLCAxODEpLCBmcmVxdWVuY3kgPSAzNjUpDQpzdGwoc2VyaWUscy53aW5kb3cgPSAicGVyaW9kaWMiKSAlPiUgcGxvdA0KDQpzZXJpZSA8LSBkYWFzX2NvbXBsZXRhcyAlPiUNCiAgcHVsbChTVUwpICU+JQ0KICB0cyhzdGFydCA9ICBjKDIwMDEsIDE4MSksIGZyZXF1ZW5jeSA9IDM2NSkNCnN0bChzZXJpZSxzLndpbmRvdyA9ICJwZXJpb2RpYyIpICU+JSBwbG90DQoNCnNlcmllIDwtIGRhYXNfY29tcGxldGFzICU+JQ0KICBwdWxsKFNVREVTVEUpICU+JQ0KICB0cyhzdGFydCA9ICBjKDIwMDEsIDE4MSksIGZyZXF1ZW5jeSA9IDM2NSkNCnN0bChzZXJpZSxzLndpbmRvdyA9ICJwZXJpb2RpYyIpICU+JSBwbG90DQoNCnNlcmllIDwtIGRhYXNfY29tcGxldGFzICU+JQ0KICBwdWxsKE5PUlRFKSAlPiUNCiAgdHMoc3RhcnQgPSAgYygyMDAxLCAxODEpLCBmcmVxdWVuY3kgPSAzNjUpDQpzdGwoc2VyaWUscy53aW5kb3cgPSAicGVyaW9kaWMiKSAlPiUgcGxvdA0KDQoNCmBgYA0KDQpgYGB7cn0NCnBsZCRTdWJtZXJjYWRvICU+JSB1bmlxdWUoKQ0KZ2VyYV9lbmVyZ19kYXkkbm9tX3N1YnNpc3RlbWEueCAlPiUgdW5pcXVlDQoNCiNuZXdkYXRhX20xICU+JSB3cml0ZS5jc3YoImJhc2UgdmFsb3JlcyBwcmV2aXN0b3MuY3N2IikNCiNnZXJhX2VuZXJnX2RheSAlPiUgd3JpdGUuY3N2KCJ2YWxvcmVzX3ByZXZpc3Rvc19kYXkuY3N2IikNCmBgYA0KDQpgYGB7cn0NCmdlcmFfZW5lcmdfZGF5ICU+JSBpbm5lcl9qb2luKHBsZCxieT1jKCJkYXRlIiwibm9tX3N1YnNpc3RlbWEueCI9Im5vbV9zdWJzaXRlbWEiKSktPnBsZF9mdWxsDQpwbGRfZnVsbCAlPiUgc3VtbWFyeSgpDQoNCmBgYA0KDQpgYGB7cn0NCnBsZF9mdWxsICU+JSBncm91cF9ieShkYXRlKSAlPiUgc3VtbWFyaXNlKHByZWNvPW1lYW4ocHJlY28sbmEucm0gPSBUKSkgJT4lIA0KICBnZ3Bsb3QoYWVzKGRhdGUscHJlY28pKStnZW9tX2xpbmUoKQ0KcGxkX2Z1bGwgJT4lIA0KICBncm91cF9ieSh0cmVuZCkgJT4lIHN1bW1hcmlzZShwcmVjbz1tZWFuKHByZWNvLG5hLnJtID0gVCkpICU+JSANCiAgZ2dwbG90KGFlcyh0cmVuZCxwcmVjbykpK2dlb21fbGluZSgpDQpwbGRfZnVsbCAlPiUgDQogIGdyb3VwX2J5KG1vbnRoKSAlPiUgc3VtbWFyaXNlKHByZWNvPW1lYW4ocHJlY28sbmEucm0gPSBUKSkgJT4lIA0KICBnZ3Bsb3QoYWVzKG1vbnRoLHByZWNvKSkrZ2VvbV9saW5lKCkNCnBsZF9mdWxsICU+JSANCiAgbXV0YXRlKG1lcyA9IGZsb29yX2RhdGUoZGF0ZSwgdW5pdCA9ICJtb250aCIpKSAlPiUgDQoNCiAgZ3JvdXBfYnkobWVzKSAlPiUgc3VtbWFyaXNlKHByZWNvPW1lYW4ocHJlY28sbmEucm0gPSBUKSkgJT4lIA0KICBnZ3Bsb3QoYWVzKG1lcyxwcmVjbykpK2dlb21fbGluZSgpDQpgYGANCg0KYGBge3J9DQpwbGRfZnVsbCAlPiUgDQogIGdncGxvdChhZXMoZGF0ZSxwcmVjbyxub21fc3Vic2lzdGVtYS54KSkrZ2VvbV9saW5lKCkrZmFjZXRfd3JhcCh+bm9tX3N1YnNpc3RlbWEueCkNCg0KcGxkX2Z1bGwgJT4lIA0KICBncm91cF9ieSh0cmVuZCxub21fc3Vic2lzdGVtYS54KSAlPiUgc3VtbWFyaXNlKHByZWNvPW1lYW4ocHJlY28sbmEucm0gPSBUKSkgJT4lIA0KICBnZ3Bsb3QoYWVzKHRyZW5kLHByZWNvKSkrZ2VvbV9saW5lKCkrZmFjZXRfd3JhcCh+bm9tX3N1YnNpc3RlbWEueCkNCnBsZF9mdWxsICU+JSANCiAgZ3JvdXBfYnkobW9udGgsbm9tX3N1YnNpc3RlbWEueCkgJT4lIHN1bW1hcmlzZShwcmVjbz1tZWFuKHByZWNvLG5hLnJtID0gVCkpICU+JSANCiAgZ2dwbG90KGFlcyhtb250aCxwcmVjbykpK2dlb21fbGluZSgpK2ZhY2V0X3dyYXAofm5vbV9zdWJzaXN0ZW1hLngpDQpwbGRfZnVsbCAlPiUgDQogIG11dGF0ZShtZXMgPSBmbG9vcl9kYXRlKGRhdGUsIHVuaXQgPSAibW9udGgiKSkgJT4lIA0KDQogIGdyb3VwX2J5KG1lcyxub21fc3Vic2lzdGVtYS54KSAlPiUgc3VtbWFyaXNlKHByZWNvPW1lYW4ocHJlY28sbmEucm0gPSBUKSkgJT4lIA0KICBnZ3Bsb3QoYWVzKG1lcyxwcmVjbykpK2dlb21fbGluZSgpK2ZhY2V0X3dyYXAofm5vbV9zdWJzaXN0ZW1hLngpDQpgYGANCg0KIyMjIG1vZGVsb3MgaW5nZW51b3MNCg0KYGBge3J9DQpwbGRfZnVsbCAlPiUgc3RyKCkNCmBgYA0KDQpgYGB7cn0NCmxtKGxvZyhwcmVjbyl+bG9nKGdlcl9oaWRyb2VsZXRyaWNhKStsb2coZ2VyX2VvbGllbGV0cmljYSkrbG9nKGdlcl9mb3Rvdm9sdGFpY2EpK2xvZyhnZXJfdGVybWljYSkrDQogICAgIGxvZyhEZW1hbmRhKStub21fc3Vic2lzdGVtYS54LA0KICAgZGF0YT1wbGRfZnVsbCAlPiUNCiAgICAgbXV0YXRlKGdlcl9oaWRyb2VsZXRyaWNhPWlmZWxzZShnZXJfaGlkcm9lbGV0cmljYT09MCwxLGdlcl9oaWRyb2VsZXRyaWNhKSwNCiAgICAgICAgICAgIGdlcl9mb3Rvdm9sdGFpY2E9aWZlbHNlKGdlcl9mb3Rvdm9sdGFpY2E9PTAsMSxnZXJfZm90b3ZvbHRhaWNhKSwNCiAgICAgICAgICAgIGdlcl9lb2xpZWxldHJpY2E9aWZlbHNlKGdlcl9lb2xpZWxldHJpY2E9PTAsMSxnZXJfZW9saWVsZXRyaWNhKSwNCiAgICAgICAgICAgIGdlcl90ZXJtaWNhPWlmZWxzZShnZXJfdGVybWljYT09MCwxLGdlcl90ZXJtaWNhKSwNCiAgICAgICAgICAgICNEZW1hbmRhPWlmZWxzZSh2YWxfZ2VyYWNhb19kYXlfc3Vic2lzdGVtYT09MCwxLHZhbF9nZXJhY2FvX2RheV9zdWJzaXN0ZW1hKSwNCiAgICAgICAgICAgIERlbWFuZGEgPSBnZXJfZW9saWVsZXRyaWNhK2dlcl9mb3Rvdm9sdGFpY2ErZ2VyX2hpZHJvZWxldHJpY2ErZ2VyX3Rlcm1pY2ErZ2VyX251Y2xlYXIsDQoNCiAgICAgICAgICAgICkpICU+JSBzdW1tYXJ5KCkNCnBsZF9mdWxsJGdlcl9oaWRyb2VsZXRyaWNhICU+JSBzdW1tYXJ5KCkNCmBgYA0KDQotICAgQXVtZW50byBkZSAxJSBuYSBnZXJhw6fDo28gaMOtZHJpY2EgcmVkdXogbyBwcmXDp28gZW0gMSw3JS4NCg0KLSAgICsxJSBlbSBlw7NsaWNhIOKGkiArMCwyMSUgbm8gcHJlw6dvLg0KDQotICAgQXVtZW50byBkZSAxJSBuYSBzb2xhciByZWR1eiBwcmXDp28gZW0gMCw0MCUuDQoNCi0gICBFbGFzdGljaWRhZGUgZm9ydGU6ICsxJSBuYSBkZW1hbmRhIOKGkiArMSw5NSUgbm8gcHJlw6dvLg0KDQotICAgUsKyID0gMC4zNDYgKFx+MzUlKQ0KDQogICAgIyMjIEdBTSBQcmXDp28gUExEDQoNCmBgYHtyfQ0KZ2FtX21vZCA8LSBnYW0ocHJlY28gfiAjdHJlbmQrDQogICAgICAgICAgICAgICAgIHMobG9nKGdlcl9oaWRyb2VsZXRyaWNhKSkgKyANCiAgICAgICAgICAgICAgICAgcyhsb2codHJlbmQpKSArICAgICAgICAgICAgICAgIA0KICAgICAgICAgICAgICAgICBzKGxvZyhkb3kpKSsNCiAgICAgICAgICAgICAgICAgcyhsb2coZ2VyX2VvbGllbGV0cmljYSkpICsgDQogICAgICAgICAgICAgICAgIHMobG9nKGdlcl9mb3Rvdm9sdGFpY2EpKSArIA0KICAgICAgICAgICAgICAgICBzKGxvZyhEZW1hbmRhKSkgKyANCiAgICAgICAgICAgICAgICAgcyhsb2coZ2VyX3Rlcm1pY2EpKSsNCiAgICAgICAgICAgICAgICAgI3Mobm9tX3N1YnNpc3RlbWEueCwgYnMgPSAicmUiKSwjIGVmZWl0byBhbGVhdMOzcmlvIHBvciByZXNlcnZhdMOzcmlvDQogICAgICAgICAgICAgICAgIG5vbV9zdWJzaXN0ZW1hLngsDQogICAgICAgICAgICAgICBkYXRhID0gcGxkX2Z1bGwgJT4lDQogICAgICAgICAgICAgICAgIG11dGF0ZSgNCiAgICAgICAgICAgICAgICAgICBnZXJfaGlkcm9lbGV0cmljYSA9IGlmZWxzZShnZXJfaGlkcm9lbGV0cmljYSA9PSAwLCAxLCBnZXJfaGlkcm9lbGV0cmljYSksDQogICAgICAgICAgICAgICAgICAgZ2VyX2ZvdG92b2x0YWljYSA9IGlmZWxzZShnZXJfZm90b3ZvbHRhaWNhID09IDAsIDEsIGdlcl9mb3Rvdm9sdGFpY2EpLA0KICAgICAgICAgICAgICAgICAgIGdlcl9lb2xpZWxldHJpY2EgPSBpZmVsc2UoZ2VyX2VvbGllbGV0cmljYSA9PSAwLCAxLCBnZXJfZW9saWVsZXRyaWNhKSwNCiAgICAgICAgICAgICAgICAgICBnZXJfdGVybWljYSA9IGlmZWxzZShnZXJfdGVybWljYSA9PSAwLCAxLCBnZXJfdGVybWljYSksDQogICAgICAgICAgICAgICAgICAgI0RlbWFuZGEgPSBpZmVsc2UodmFsX2dlcmFjYW9fZGF5X3N1YnNpc3RlbWEgPT0gMCwgMSwgdmFsX2dlcmFjYW9fZGF5X3N1YnNpc3RlbWEpDQogICAgICAgICAgICAgICAgICAgRGVtYW5kYSA9IGdlcl9lb2xpZWxldHJpY2ErZ2VyX2ZvdG92b2x0YWljYStnZXJfaGlkcm9lbGV0cmljYStnZXJfdGVybWljYStnZXJfbnVjbGVhciwNCiAgICAgICAgICAgICAgICAgKSkNCmBgYA0KDQpgYGB7cn0NCnN1bW1hcnkoZ2FtX21vZCkNCnBsb3QoZ2FtX21vZCwgcGFnZXMgPSAzLCBzaGFkZSA9IFRSVUUpDQoNCmBgYA0KDQotICAgKipSwrIgYWp1c3RhZG8gPSAwLjUwKiog4oaSIG8gR0FNIGV4cGxpY291ICoqbWV0YWRlIGRhIHZhcmnDom5jaWEqKiBkb3MgcHJlw6dvcywgY29udHJhIFx+MC4zNSBkbyBtb2RlbG8gbGluZWFyIGFudGVyaW9yLg0KDQogICAgLSAgICoqRGV2aWFuY2UgZXhwbGFpbmVkID0gNTAlKiog4oaSIG11aXRvIG1haXMgYWRlcsOqbmNpYS4NCg0KLSAgICoqSGlkcmVsw6l0cmljYSAoYHMobG9nKGdlcl9oaWRybykpYCkqKg0KDQogICAgLSAgIE8gZWZlaXRvIMOpICoqZm9ydGUgYXTDqSBjZXJ0byBwb250byoqIGUgZGVwb2lzICoqc2F0dXJhKioNCg0KLSAgIEXDs2xpY2ENCg0KICAgIC0gICBMaW5oYSByZWxhdGl2YW1lbnRlIHBsYW5hLCBsZXZlbWVudGUgbmVnYXRpdmEgZW0gdmFsb3JlcyBhbHRvcy4NCg0KICAgIC0gICBNb3N0cmEgcXVlIGEgZcOzbGljYSB0ZW0gZWZlaXRvIGZyYWNvIG91IGF0w6kgbmV1dHJvIGVtIGZhaXhhcyBub3JtYWlzIGRlIG9wZXJhw6fDo28sIG1hcyBwb2RlIGFqdWRhciBhIGJhaXhhciBwcmXDp29zIGVtIGNvbmRpw6fDtWVzIGV4dHJlbWFzLg0KDQotICAgU29sYXINCg0KICAgIC0gICBFZmVpdG8gcHJhdGljYW1lbnRlICoqbGluZWFyIGUgbmVnYXRpdm8qKiwgbWFzIGZyYWNvIChlZGYg4omIIDEg4oaSIHF1YXNlIGxpbmVhcikNCg0KLSAgIERlbWFuZGENCg0KYGBgICAgICAgICAgDQotICAgQ2xhcmFtZW50ZSBjcmVzY2VudGUsIGUgbWFpcyDDrW5ncmVtZSBlbSB2YWxvcmVzIGFsdG9zLiBJc3NvIG1vc3RyYSBxdWUgbyBwcmXDp28gcmVzcG9uZGUgZGUgZm9ybWEgbsOjbyBsaW5lYXI6DQoNCiAgICAtICAgZW0gZGVtYW5kYXMgYmFpeGFzL23DqWRpYXMsIGVmZWl0byBzdWF2ZSwNCg0KLSAgIGVtIGRlbWFuZGFzIG11aXRvIGFsdGFzLCBwcmXDp28gZGlzcGFyYQ0KDQotICAgRXhhdGFtZW50ZSBvIGNvbXBvcnRhbWVudG8gZXNwZXJhZG8gZW0gc2lzdGVtYXMgY29tIGRlc3BhY2hvIHBvciBvcmRlbSBkZSBtw6lyaXRvLg0KYGBgDQoNCiMjIyBQcmV2aXN0byBQTEQNCg0KYGBge3J9DQoNCiNwbGRfZnVsbCRwcmVjX3ByZXZpc3RvPC1wcmVkaWN0KGdhbV9tb2QsKQ0KDQpwcmVkaWN0KGdhbV9tb2QsbmV3ZGF0YT1wbGRfZnVsbCAlPiUNCiAgICAgICAgICAgICAgICAgbXV0YXRlKA0KICAgICAgICAgICAgICAgICAgIGdlcl9oaWRyb2VsZXRyaWNhID0gaWZlbHNlKGdlcl9oaWRyb2VsZXRyaWNhID09IDAsIDEsIGdlcl9oaWRyb2VsZXRyaWNhKSwNCiAgICAgICAgICAgICAgICAgICBnZXJfZm90b3ZvbHRhaWNhID0gaWZlbHNlKGdlcl9mb3Rvdm9sdGFpY2EgPT0gMCwgMSwgZ2VyX2ZvdG92b2x0YWljYSksDQogICAgICAgICAgICAgICAgICAgZ2VyX2VvbGllbGV0cmljYSA9IGlmZWxzZShnZXJfZW9saWVsZXRyaWNhID09IDAsIDEsIGdlcl9lb2xpZWxldHJpY2EpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBnZXJfdGVybWljYSA9IGlmZWxzZShnZXJfdGVybWljYSA9PSAwLCAxLCBnZXJfdGVybWljYSksDQogICAgICAgICAgICAgICAgICAgRGVtYW5kYSA9IGdlcl9lb2xpZWxldHJpY2ErZ2VyX2ZvdG92b2x0YWljYStnZXJfaGlkcm9lbGV0cmljYStnZXJfdGVybWljYStnZXJfbnVjbGVhciwNCg0KICAgICAgICAgICAgICAgICAgICNEZW1hbmRhID0gaWZlbHNlKHZhbF9nZXJhY2FvX2RheV9zdWJzaXN0ZW1hID09IDAsIDEsIHZhbF9nZXJhY2FvX2RheV9zdWJzaXN0ZW1hKQ0KICAgICAgICAgICAgICAgICApLHR5cGU9InJlc3BvbnNlIikgLT4gcGxkX2Z1bGwkcHJlY19wcmV2aXN0bw0KYGBgDQoNCmBgYHtyfQ0KcGxkX2Z1bGwgJT4lIA0KDQogIG11dGF0ZShtZXMgPSBmbG9vcl9kYXRlKGRhdGUsIHVuaXQgPSAibW9udGgiKSkgJT4lIA0KICBncm91cF9ieShtZXMsbm9tX3N1YnNpc3RlbWEueCkgJT4lIHN1bW1hcmlzZShwcmVjX3ByZXZpc3RvPW1lYW4ocHJlY19wcmV2aXN0byxuYS5ybSA9IFQpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHByZWNvPW1lYW4ocHJlY28sbmEucm0gPSBUKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApICU+JSANCiAgZ2dwbG90KGFlcyhtZXMscHJlY19wcmV2aXN0bykpKw0KICBnZW9tX2xpbmUoc2l6ZSA9IDEsIGxpbmV0eXBlID0gImRhc2hlZCIsY29sPSJyZWQiKSArDQogIGdlb21fbGluZShhZXMoeT1wcmVjbyksY29sID0gImJsYWNrIikrDQogIGxhYnMoeT0iJCIseD0iWWVhciIpK3RoZW1lX21pbmltYWwoKSsNCiAgZmFjZXRfd3JhcCh+bm9tX3N1YnNpc3RlbWEueCxzY2FsZXMgPSAiZnJlZSIpDQoNCnBsZF9mdWxsICU+JSANCiAgbXV0YXRlKG1lcyA9IGZsb29yX2RhdGUoZGF0ZSwgdW5pdCA9ICJtb250aCIpKSAlPiUgDQogIGdyb3VwX2J5KG1lcyxub21fc3Vic2lzdGVtYS54KSAlPiVzdW1tYXJpc2UocHJlY289bWVhbihwcmVjbyxuYS5ybT1UKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwcmVjX3ByZXZpc3RvPW1lYW4ocHJlY19wcmV2aXN0byxuYS5ybT1UKSkgJT4lDQogIGdncGxvdCggYWVzKHggPSBtZXMsKSkgKw0KICAjZ2VvbV9wb2ludChhZXMoY29sb3I9cmVzaWRfY29sKSkrDQogIGZhY2V0X3dyYXAofm5vbV9zdWJzaXN0ZW1hLngsc2NhbGVzID0gImZyZWUiKSsNCiAgZ2VvbV9saW5lKGFlcyh5ID0gcHJlY19wcmV2aXN0byksY29sPSJyZWQiKSArICAjZ2VvbV9saW5lKGFlcyh5PWV4cChwcmVjX3ByZXZpc3RvKSkpICsNCiAgZ2VvbV9yaWJib24oYWVzKHltaW49cHJlY19wcmV2aXN0byx5bWF4PXByZWNvKSxhbHBoYT0uNCxmaWxsID0gImZpcmVicmljayIsKSsNCiAgbGFicyh0aXRsZSA9ICJSZXPDrWR1b3MgZG8gbW9kZWxvIChvYnNlcnZhZG8gLSBwcmV2aXN0bykiLA0KICAgICAgIHkgPSAiUmVzw61kdW8iLCB4ID0gIkRhdGEiKSArDQoNCiAgdGhlbWVfbWluaW1hbCgpDQpgYGANCg0KYGBge3J9DQpwbGRfZnVsbCAlPiUgDQogIG11dGF0ZShtZXMgPSBmbG9vcl9kYXRlKGRhdGUsIHVuaXQgPSAibW9udGgiKSkgJT4lIA0KICBncm91cF9ieShtZXMsbm9tX3N1YnNpc3RlbWEueCkgJT4lIHN1bW1hcmlzZShwcmVjX3ByZXZpc3RvPW1lYW4ocHJlY19wcmV2aXN0byxuYS5ybSA9IFQpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHByZWNvPW1lYW4ocHJlY28sbmEucm0gPSBUKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApICU+JSANCiAgZ2dwbG90KGFlcyhtZXMscHJlY19wcmV2aXN0bykpKw0KICBnZW9tX2xpbmUoc2l6ZSA9IDEsIGxpbmV0eXBlID0gImRhc2hlZCIsY29sPSJyZWQiKSArDQogIGdlb21fbGluZShhZXMoeT1wcmVjbyksY29sID0gImJsYWNrIikrDQogIGxhYnMoeT0iJCIseD0iWWVhciIpK3RoZW1lX21pbmltYWwoKSsNCiAgZmFjZXRfd3JhcCh+bm9tX3N1YnNpc3RlbWEueCxzY2FsZXMgPSAiZnJlZSIpDQpwbGRfZnVsbCAlPiUgDQogIG11dGF0ZShtZXMgPSBmbG9vcl9kYXRlKGRhdGUsIHVuaXQgPSAibW9udGgiKSkgJT4lIA0KICBncm91cF9ieShtZXMsbm9tX3N1YnNpc3RlbWEueCkgJT4lc3VtbWFyaXNlKHByZWNvPW1lYW4ocHJlY28sbmEucm09VCksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcHJlY19wcmV2aXN0bz1tZWFuKHByZWNfcHJldmlzdG8sbmEucm09VCkpICU+JQ0KICBnZ3Bsb3QoIGFlcyh4ID0gbWVzLCkpICsNCiAgI2dlb21fcG9pbnQoYWVzKGNvbG9yPXJlc2lkX2NvbCkpKw0KICBmYWNldF93cmFwKH5ub21fc3Vic2lzdGVtYS54LHNjYWxlcyA9ICJmcmVlIikrDQogIGdlb21fbGluZShhZXMoeSA9IHByZWNfcHJldmlzdG8pLGNvbD0icmVkIikgKyAgZ2VvbV9saW5lKGFlcyh5PXByZWNfcHJldmlzdG8pKSArDQogIGdlb21fcmliYm9uKGFlcyh5bWluPXByZWNfcHJldmlzdG8seW1heD1wcmVjbyksYWxwaGE9LjQsZmlsbCA9ICJmaXJlYnJpY2siLCkrDQogIGxhYnModGl0bGUgPSAiUmVzw61kdW9zIGRvIG1vZGVsbyAob2JzZXJ2YWRvIC0gcHJldmlzdG8pIiwNCiAgICAgICB5ID0gIlJlc8OtZHVvIiwgeCA9ICJEYXRhIikgKw0KICB0aGVtZV9taW5pbWFsKCkNCg0KYGBgDQoNCiMjIyBDb250cmFmYWN0dWFsIFBMRA0KDQpgYGB7cn0NCmdlcmFfZW5lcmdfZGF5JGdlcl90ZXJtaWNhX3ByZXZpc3RhPC1wcmVkaWN0KG1fZ2FtX2ZvbnRlcywNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5ld2RhdGEgPSBnZXJhX2VuZXJnX2RheSAlPiUNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbXV0YXRlKA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbm9tX3N1YnNpc3RlbWE9bm9tX3N1YnNpc3RlbWEueCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIERlbWFuZGEgPSBnZXJfZW9saWVsZXRyaWNhK2dlcl9mb3Rvdm9sdGFpY2ErZ2VyX2hpZHJvZWxldHJpY2ErZ2VyX3Rlcm1pY2ErZ2VyX251Y2xlYXIpDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApDQpnZXJhX2VuZXJnX2RheSRnZXJfdGVybWljYV9wcmV2aXN0YV9jZjwtcHJlZGljdChtX2dhbV9mb250ZXMsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBuZXdkYXRhID0gZ2VyYV9lbmVyZ19kYXkgJT4lIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtdXRhdGUoZ2VyX2hpZHJvZWxldHJpY2E9Z2VyX2hpZHJvZWxldHJpY2ErcGVuYWxpZGFkZV9nZXJhw6fDo29faGlkcm8sDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBub21fc3Vic2lzdGVtYT1ub21fc3Vic2lzdGVtYS54LA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgI2dlcl90ZXJtaWNhPWdlcl90ZXJtaWNhLXBlbmFsaWRhZGVfdGVybWljbywNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIERlbWFuZGEgPSBnZXJfZW9saWVsZXRyaWNhK2dlcl9mb3Rvdm9sdGFpY2ErZ2VyX2hpZHJvZWxldHJpY2ErZ2VyX3Rlcm1pY2ErZ2VyX251Y2xlYXIpDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApDQpgYGANCg0KYGBge3J9DQoNCnByZWRpY3QoZ2FtX21vZCxuZXdkYXRhPXBsZF9mdWxsICU+JQ0KICAgICAgICAgICAgICAgICBtdXRhdGUoDQogICAgICAgICAgICAgICAgICBEZW1hbmRhID0gZ2VyX2VvbGllbGV0cmljYStnZXJfZm90b3ZvbHRhaWNhK2dlcl9oaWRyb2VsZXRyaWNhK2dlcl90ZXJtaWNhK2dlcl9udWNsZWFyLA0KICAgICAgICAgICAgICAgICAgIGdlcl9oaWRyb2VsZXRyaWNhID0gaWZlbHNlKGlzLm5hKGdlcl9oaWRyb2VsZXRyaWNhK3BlbmFsaWRhZGVfZ2VyYcOnw6NvX2hpZHJvKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAxLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdlcl9oaWRyb2VsZXRyaWNhK3BlbmFsaWRhZGVfZ2VyYcOnw6NvX2hpZHJvKSwNCiAgICAgICAgICAgICAgICAgICBnZXJfaGlkcm9lbGV0cmljYSA9IGlmZWxzZShnZXJfaGlkcm9lbGV0cmljYTwxICwgMSwgZ2VyX2hpZHJvZWxldHJpY2EpLA0KICAgICAgICAgICAgICAgICAgIGdlcl9mb3Rvdm9sdGFpY2EgPSBpZmVsc2UoZ2VyX2ZvdG92b2x0YWljYSA9PSAwLCAxLCBnZXJfZm90b3ZvbHRhaWNhKSwNCiAgICAgICAgICAgICAgICAgICBnZXJfZW9saWVsZXRyaWNhID0gaWZlbHNlKGdlcl9lb2xpZWxldHJpY2EgPT0gMCwgMSwgZ2VyX2VvbGllbGV0cmljYSksDQogICAgICAgICAgICAgICAgICBnZXJfdGVybWljYSA9IGlmZWxzZShnZXJfdGVybWljYStwZW5hbGlkYWRlX3Rlcm1pY288IDAuMSwgMSwgZ2VyX3Rlcm1pY2ErcGVuYWxpZGFkZV90ZXJtaWNvKSwNCg0KICAgICAgICAgICAgICAgICApLHR5cGU9InJlc3BvbnNlIikgLT4gcGxkX2Z1bGwkcHJlY19wcmV2aXN0b19jZg0KDQpwbGRfZnVsbCAlPiUgdW5ncm91cCgpICU+JSANCiAgI211dGF0ZShwZW5hbGlkYWRlX3Rlcm1pY28pDQogIHNlbGVjdChwcmVjX3ByZXZpc3RvLHByZWNfcHJldmlzdG9fY2YscHJlY28sZ2VyX3Rlcm1pY2EscGVuYWxpZGFkZV90ZXJtaWNvLHBlbmFsaWRhZGVfZ2VyYcOnw6NvX2hpZHJvKSAlPiUgc3VtbWFyeSgpDQoNCiAgICAgICAgICAgICAgICAgDQpgYGANCg0KYGBge3J9DQoNCg0KcGxkX2Z1bGwgJT4lIA0KICBtdXRhdGUobWVzID0gZmxvb3JfZGF0ZShkYXRlLCB1bml0ID0gIm1vbnRoIikpICU+JSANCiAgZ3JvdXBfYnkobWVzLG5vbV9zdWJzaXN0ZW1hLngpICU+JSBzdW1tYXJpc2UocHJlY19wcmV2aXN0bz1tZWFuKHByZWNfcHJldmlzdG8sbmEucm0gPSBUKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwcmVjbz1tZWFuKHByZWNvLG5hLnJtID0gVCksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcHJlY19wcmV2aXN0b19jZj1tZWFuKHByZWNfcHJldmlzdG9fY2YsbmEucm0gPSBUKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApICU+JSANCiAgZ2dwbG90KGFlcyhtZXMsKHByZWNfcHJldmlzdG8pKSkrDQogIGdlb21fbGluZShzaXplID0gMSwgbGluZXR5cGUgPSAiZGFzaGVkIixjb2w9InJlZCIpICsNCiAgI2dlb21fbGluZShhZXMoeT1wcmVjbyksY29sID0gImJsYWNrIikrDQogICAgZ2VvbV9saW5lKGFlcyh5PShwcmVjX3ByZXZpc3RvX2NmKSksY29sID0gImJsdWUiKSsNCg0KICBsYWJzKHk9IiQiLHg9IlllYXIiKSt0aGVtZV9taW5pbWFsKCkrDQogIGZhY2V0X3dyYXAofm5vbV9zdWJzaXN0ZW1hLngsc2NhbGVzID0gImZyZWUiKQ0KDQpgYGANCg0KYGBge3J9DQpwbGRfZnVsbCAlPiUgDQogIG11dGF0ZShtZXMgPSBmbG9vcl9kYXRlKGRhdGUsIHVuaXQgPSAibW9udGgiKSkgJT4lIA0KICBncm91cF9ieShtZXMsbm9tX3N1YnNpc3RlbWEueCkgJT4lc3VtbWFyaXNlKHByZWNfcHJldmlzdG9fY2Y9bWVhbihwcmVjX3ByZXZpc3RvX2NmLG5hLnJtPVQpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHByZWNfcHJldmlzdG89bWVhbihwcmVjX3ByZXZpc3RvLG5hLnJtPVQpKSAlPiUNCiAgZ2dwbG90KCBhZXMoeCA9IG1lcywpKSArDQogICNnZW9tX3BvaW50KGFlcyhjb2xvcj1yZXNpZF9jb2wpKSsNCiAgZmFjZXRfd3JhcCh+bm9tX3N1YnNpc3RlbWEueCxzY2FsZXMgPSAiZnJlZSIpKw0KICAjZ2VvbV9saW5lKGFlcyh5ID0gZXhwKHByZWNfcHJldmlzdG9fY2YpKSxjb2w9InJlZCIpICsgDQogIGdlb21fbGluZShhZXMoeT0ocHJlY19wcmV2aXN0b19jZiktKHByZWNfcHJldmlzdG8pKSkgKw0KICBnZW9tX3JpYmJvbihhZXMoeW1pbj0wLHltYXg9KHByZWNfcHJldmlzdG9fY2YpLShwcmVjX3ByZXZpc3RvKSksYWxwaGE9LjQsZmlsbCA9ICJmaXJlYnJpY2siLCkrDQogIGxhYnModGl0bGUgPSAiUGVuYWxpZGFkZSAoQ29udHJhZmFjdHVhbC0gUHJlZGl0bykiLA0KICAgICAgIHkgPSAiUGVuYWxpZGFkZSBDbGltw6F0aWNhIG5vIFByZcOnbyIsIHggPSAiRGF0YSIpICsNCiAgdGhlbWVfbWluaW1hbCgpDQpgYGANCg0KYGBge3J9DQpwbGRfZnVsbCAlPiUgDQogIG11dGF0ZShtZXMgPSBmbG9vcl9kYXRlKGRhdGUsIHVuaXQgPSAibW9udGgiKSkgJT4lIA0KICBncm91cF9ieSh5ZWFyLG5vbV9zdWJzaXN0ZW1hLngpICU+JXN1bW1hcmlzZShwcmVjX3ByZXZpc3RvX2NmPW1lYW4ocHJlY19wcmV2aXN0b19jZixuYS5ybT1UKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwcmVjX3ByZXZpc3RvPW1lYW4ocHJlY19wcmV2aXN0byxuYS5ybT1UKSkgJT4lDQogIGdncGxvdCggYWVzKHggPSB5ZWFyLCkpICsNCiAgI2dlb21fcG9pbnQoYWVzKGNvbG9yPXJlc2lkX2NvbCkpKw0KICBmYWNldF93cmFwKH5ub21fc3Vic2lzdGVtYS54LHNjYWxlcyA9ICJmcmVlIikrDQogICNnZW9tX2xpbmUoYWVzKHkgPSBleHAocHJlY19wcmV2aXN0b19jZikpLGNvbD0icmVkIikgKyANCiAgZ2VvbV9saW5lKGFlcyh5PShwcmVjX3ByZXZpc3RvX2NmKS0ocHJlY19wcmV2aXN0bykpKSArDQogIGdlb21fcmliYm9uKGFlcyh5bWluPTAseW1heD0ocHJlY19wcmV2aXN0b19jZiktKHByZWNfcHJldmlzdG8pKSxhbHBoYT0uNCxmaWxsID0gImZpcmVicmljayIsKSsNCiAgbGFicyh0aXRsZSA9ICJQZW5hbGlkYWRlIChDb250cmFmYWN0dWFsLSBQcmVkaXRvKSIsDQogICAgICAgeSA9ICJQZW5hbGlkYWRlIENsaW3DoXRpY2Egbm8gUHJlw6dvIiwgeCA9ICJEYXRhIikgKw0KICB0aGVtZV9taW5pbWFsKCkNCmBgYA0KDQpgYGB7cn0NCnBsZF9mdWxsICU+JSANCiAgIG11dGF0ZShwZW5hbGlkYWRlMT1wcmVjX3ByZXZpc3RvX2NmLXByZWNfcHJldmlzdG8sDQogICAgICAgICAgcGVuYWxpZGFkZV9wZXJjPXByZWNfcHJldmlzdG9fY2YvcHJlY19wcmV2aXN0bywNCiAgICAgICAgICAjcGVuYWxpZGFkZTI9ZW5hX213Ny1jbGltMjAyNl9oYXQsDQogICAgICAgICAgKSAlPiUgDQoNCiAgZ3JvdXBfYnkobm9tX3N1YnNpc3RlbWEueCkgJT4lc3VtbWFyaXNlKHBlbmFsaWRhZGUxPXN1bShwZW5hbGlkYWRlMSxuYS5ybT1UKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHByZWNfcHJldmlzdG89c3VtKHByZWNfcHJldmlzdG8sbmEucm09VCksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwcmVjX3ByZXZpc3RvX2NmPXN1bShwcmVjX3ByZXZpc3RvX2NmKjEwMDAsbmEucm09VCksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwcmVjPW1lYW4ocHJlY28sbmEucm0gPSBUKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBlbmFsaWRhZGVfcGVyYz1tZWFuKHBlbmFsaWRhZGVfcGVyYyxuYS5ybT1UKQ0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjY2xpbTIwMjZfaGF0PXN1bShwZW5hbGlkYWRlMixuYS5ybT1UKQ0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICApICU+JSBtdXRhdGUoY3VzdG9fZmluYW5jZWlyb19wbGQ9cGVuYWxpZGFkZTEpLT5wZW5hbGlkYWRlX3BsZA0KcGVuYWxpZGFkZV9wbGQNCmBgYA0KDQpkZHNhZA0KDQpkc2ENCg0KYGBge3J9DQoNCmJpbmRfcm93cyhwZW5hbGlkYWRlX2hpZHJpY28gJT4lIG11dGF0ZShlc3RpbWE9IkhpZHJvKiIpLA0KDQogICAgICAgICAgcGVuYWxpZGFkZV90ZXJtaWNvICU+JSBtdXRhdGUoZXN0aW1hPSJUw6lybWljbyoqIiksDQogICAgICAgICAgcGVuYWxpZGFkZV9wbGQgJT4lIG11dGF0ZShlc3RpbWE9Ik9wZXJhY2lvbmFsKioqIikpICU+JSANCiAgc2VsZWN0KC1zdGFydHNfd2l0aCgiY3VzdG8iKSkgJT4lIA0KICBtdXRhdGUoY3VzdG9fUmVhaXM9Y2FzZV93aGVuKGVzdGltYT09IkhpZHJvKiJ+KC1wZW5hbGlkYWRlMSkqKDI5Ni44KSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlc3RpbWE9PSJUw6lybWljbyoqIn5wZW5hbGlkYWRlMSoJNDc4LjksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgIFRSVUV+cGVuYWxpZGFkZTEqMTAwMDAvNyksDQogICAgICAgICBjdXN0b19VU0Q9Y3VzdG9fUmVhaXMvNS4yDQogICAgICAgICApICU+JSANCiAgZ2dwbG90KGFlcyh4PW5vbV9zdWJzaXN0ZW1hLngseT0oY3VzdG9fVVNELzEwMDAwMCksZmlsbD1lc3RpbWEpKStnZW9tX2NvbChwb3NpdGlvbiA9ICJkb2RnZSIpKw0KICBnZW9tX3RleHQoYWVzKGxhYmVsID0gcm91bmQoY3VzdG9fVVNELzEwMDAwMCwgMikpLCBwb3NpdGlvbj1wb3NpdGlvbl9kb2RnZSh3aWR0aD0xKSwgc2l6ZSA9IDMsY2hlY2tfb3ZlcmxhcD1GKStjb29yZF9mbGlwKCkrDQogIGxhYnModGl0bGUgPSAiQ3VzdG8gZWNvbsO0bWljbyBlc3RpbWFkbyBkYSBwZW5hbGlkYWRlIGNsaW3DoXRpY2EgKDIwMDEtMjAxOSkiLA0KICAgICAgIHN1YnRpdGxlID0gIkN1c3RvIGZpbmFuY2Vpcm8gYXByb3hpbWFkbyBkbyBpbXBhY3RvIGNsaW3DoXRpY28gc29icmUgYSBnZXJhw6fDo28gaGlkcmVsw6l0cmljYSBlIHTDqXJtaWNhIiwNCiAgICAgICBjYXB0aW9uID0gIioyOTYsOCBSJC9NV2gNCioqNDc4LDkgUiQvTVdoDQoqKiogRXN0aW1hZG8gZW0gMTAgR1doIHBvciBzZW1hbmEiLA0KICAgICAgIHkgPSAiQ3VzdG8gKFVTJCBtaWxow7VlcykiLCB4ID0gIlN1YnNpc3RlbWEiKSArdGhlbWVfbWluaW1hbCgpDQpgYGANCg0KYGBge3J9DQpiaW5kX3Jvd3MocGVuYWxpZGFkZV9oaWRyaWNvICU+JSBtdXRhdGUoZXN0aW1hPSJIaWRybyoiKSwNCg0KICAgICAgICAgIHBlbmFsaWRhZGVfdGVybWljbyAlPiUgbXV0YXRlKGVzdGltYT0iVMOpcm1pY28qKiIpLA0KICAgICAgICAgIHBlbmFsaWRhZGVfcGxkICU+JSBtdXRhdGUoZXN0aW1hPSJPcGVyYWNpb25hbCoqKiIpKSAlPiUgDQogIHNlbGVjdCgtc3RhcnRzX3dpdGgoImN1c3RvIikpICU+JSANCiAgbXV0YXRlKGN1c3RvX1JlYWlzPWNhc2Vfd2hlbihlc3RpbWE9PSJIaWRybyoifigtcGVuYWxpZGFkZTEpKigyOTYuOCksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXN0aW1hPT0iVMOpcm1pY28qKiJ+cGVuYWxpZGFkZTEqCTQ3OC45LA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICBUUlVFfnBlbmFsaWRhZGUxKjEwMDAwLzcpLA0KICAgICAgICAgY3VzdG9fVVNEPWN1c3RvX1JlYWlzLzUuMg0KICAgICAgICAgKSAlPiUgDQogIGdyb3VwX2J5KGVzdGltYSkgJT4lIHN1bW1hcmlzZShjdXN0b19VU0Q9c3VtKGN1c3RvX1VTRCkpICU+JSANCiAgZ2dwbG90KGFlcyh4PWVzdGltYSx5PShjdXN0b19VU0QvMTAwMDAwKSxmaWxsPWVzdGltYSkpK2dlb21fY29sKHBvc2l0aW9uID0gImRvZGdlIikrDQogIGdlb21fdGV4dChhZXMoeT1jdXN0b19VU0QvMjAwMDAwLGxhYmVsID0gcm91bmQoY3VzdG9fVVNELzEwMDAwMCwgMSkpLCBwb3NpdGlvbj1wb3NpdGlvbl9kb2RnZSh3aWR0aD0xKSwgc2l6ZSA9IDMsY2hlY2tfb3ZlcmxhcD1GKStjb29yZF9mbGlwKCkrDQogIGxhYnModGl0bGUgPSAiQ3VzdG8gZWNvbsO0bWljbyBlc3RpbWFkbyBkYSBwZW5hbGlkYWRlIGNsaW3DoXRpY2EgKDIwMDAtMjAxOSkiLA0KICAgICAgIHN1YnRpdGxlID0gIkN1c3RvIGZpbmFuY2Vpcm8gYXByb3hpbWFkbyBkbyBpbXBhY3RvIGNsaW3DoXRpY28gc29icmUgYSBnZXJhw6fDo28gaGlkcmVsw6l0cmljYSBlIHTDqXJtaWNhIiwNCiAgICAgICBjYXB0aW9uID0gIioyOTYsOCBSJC9NV2gNCioqNDc4LDkgUiQvTVdoDQoqKiogRXN0aW1hZG8gZW0gMTAgR1doIHBvciBzZW1hbmEiLA0KICAgICAgIHkgPSAiQ3VzdG8gKFVTJCBNaWxob2VzKSIsIHggPSAiU3Vic2lzdGVtYSIpICt0aGVtZV9taW5pbWFsKCkNCmBgYA0K