Pacotes

# Carregar pacotes-base do projeto
# Manipulação e datas
library(tidyverse);library(data.table);library(lubridate);library(patchwork);library(Hmisc)

# Modelagem
library(mgcv);library(gratia);library(lubridate);library(modelsummary);library(gt);library(glue);library(scales);library(broom);library(broom.helpers);library(geobr)
# Utilidades
library(scales);library(patchwork);library(knitr);library(kableExtra)

# 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

pld     <- read.csv("pld_diario_completo.csv")             # weekly spot price (PLD)
Aviso em file(file, "rt") :
  não foi possível abrir o arquivo 'pld_diario_completo.csv': No such file or directory
Error in file(file, "rt") : não é possível abrir a conexão
# 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)
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")
range(ger$date, na.rm=TRUE)
range(reserv$date, na.rm=TRUE)
range(pld$date, na.rm=TRUE)

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")
tab_cov

# 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"
  )

#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

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
a %>%   ggplot(aes(val_longitude,val_latitude))+geom_point()+
ggplot(data=georegion) +geom_sf()
a$nom_subsistema.x %>% unique
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)
gtsummary::tbl_regression(m1_gam)
summary(m1_gam)
gam.check(m1_gam)          # resíduos, QQ, k-index
concurvity(m1_gam, full=TRUE)

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)
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)

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
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)
nsim <- 500
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 <- as.data.table(nd_obs)[, .(date, year = year(date), nom_subsistema.x)]

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),
  sd  = apply(agg_mat, 1, sd)

)
m1_sim_agg %>% mutate(sd_up=mean+z*sd, sd_lwr=mean-z*sd)->m1_sim_agg

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_ribbon(aes(ymin = 0, ymax = upr/1000), fill = "red3", alpha = 0.1) +

  geom_line() +
  facet_wrap(~nom_subsistema.x, scales = "free_y") +
  labs(title = "Climate penalty on stored energy (ΔEAR) — Parametric simulation quartile",
       y = "ΔEAR (GW·month)", x = "Year") +
  theme_minimal()

m1_sim_agg %>%
  ggplot(aes(x = year, y = mean/1000)) +
  geom_ribbon(aes(ymin = sd_lwr/1000, ymax = sd_up/1000), alpha = .25, fill = "steelblue") +
  geom_ribbon(aes(ymin = 0, ymax = sd_up/1000), fill = "red3", alpha = 0.1) +

  geom_line() +
  facet_wrap(~nom_subsistema.x, scales = "free_y") +
  labs(title = "Climate penalty on stored energy (ΔEAR) — Parametric simulation sd",
       y = "ΔEAR (GW·month)", x = "Year") +
  theme_minimal()
Error in `geom_ribbon()`:
! Problem while computing aesthetics.
ℹ Error occurred in the 1st layer.
Caused by error:
! objeto 'sd_lwr' não encontrado
Run `]8;;x-r-run:rlang::last_trace()rlang::last_trace()]8;;` to see where the error occurred.

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  = mean_penalty-z*sd_penalty / 1000,
    upr_GWh  = mean_penalty+z*sd_penalty / 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"
  )

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))
)
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)

C <- reserv %>%
  mutate(
    delta_lwr_ger = delta_Ghidro - z * se_delta2,
    delta_upr_ger = delta_Ghidro + z * se_delta2
  )
C[,c("delta_Ghidro","delta_lwr_ger","delta_upr_ger","val_geracao")] %>% summary()
# (4) Agregação por ano e subsistema -----------------------------------------
m2_delta_agg <- C %>%
  mutate(Year = year(date)) %>%
  group_by(Year, nom_subsistema.x) %>%
  summarise(
    mean_penalty = sum(delta_Ghidro, na.rm = TRUE),
    lwr = sum(delta_lwr_ger, na.rm = TRUE),
    upr = sum(delta_upr_ger, na.rm = TRUE),
    .groups = "drop"
  )
m2_delta_agg
library(ggplot2)
m2_delta_agg %>%
  ggplot(aes(x = Year, y = mean_penalty/1000)) +
  geom_ribbon(aes(ymin = lwr/1000, ymax = upr/1000), fill = "steelblue", alpha = 0.8) +
  geom_ribbon(aes(ymin = 0, ymax = upr/1000), fill = "red3", alpha = 0.1) +

  geom_line(color = "black") +
  facet_wrap(~nom_subsistema.x, scales = "free_y") +
  labs(title = "Propagated climate penalty on hydropower generation (ΔG_hidro)",
       subtitle = "Baseline climate: mean 2001–2005",
       y = "ΔG_hidro (GW·month)", x = "Year") +
  theme_minimal()

 
m2_summary  <- C %>%
  mutate(Year = year(date)) %>% ungroup() %>% 
  group_by( nom_subsistema.x) %>%
  summarise(
    mean_penalty = sum(delta_Ghidro, na.rm = TRUE),
    lwr = sum(delta_lwr_ger, na.rm = TRUE),
    upr = sum(delta_upr_ger, na.rm = TRUE),
    .groups = "drop"
  )

library(gt)
m2_summary[,c("nom_subsistema.x","mean_penalty","lwr", "upr")] %>% janitor::adorn_totals() %>% 
  gt() %>%
  fmt_number(columns = 2:4, decimals = 1) %>%
  cols_label(
    nom_subsistema.x = "Subsystem",
    mean_penalty = "Sum Δger (MWh)",
    lwr  = "Lower 95%",
    upr  = "Upper 95%",
  ) %>%
  tab_header(
    title = md("**Aggregate climate penalty on hidropower energy (2001–2018)**"),
    subtitle = "Simulated mean and 95% confidence intervals per subsystem"
  )

A Figura apresenta o resultado da propagação da penalidade climática sobre a geração hidrelétrica (ΔG_hidro), obtida pela substituição do clima observado pelo clima médio histórico (2001–2005) no modelo de armazenamento e pela aplicação desses valores contrafactuais no modelo de geração. O gráfico mostra a diferença entre a geração prevista sob clima efetivo e o cenário contrafactual neutro, com intervalos de confiança calculados por duas abordagens: o método analítico (Delta) e a simulação paramétrica.

Os resultados indicam que a penalidade climática média sobre a geração hidrelétrica segue o mesmo padrão espacial observado na energia armazenada, mas com magnitude amplificada devido à resposta elástica do despacho hídrico. O Sudeste apresenta o maior déficit médio, com reduções acumuladas superiores a –4 milhões de MW·mês em anos secos, refletindo a forte dependência da geração ao nível de reservatórios. O Sul mostra penalidades intermediárias (entre –1 e –2 milhões de MW·mês), com alta variabilidade interanual. O Nordeste e o Norte apresentam oscilações menores, mas com tendência negativa acentuada após 2012, compatível com períodos de estiagem prolongada.

Os intervalos de confiança revelam aumento expressivo da incerteza após 2010, quando as condições climáticas se tornaram mais voláteis e os reservatórios passaram a operar próximos de limites críticos. Esse padrão reforça a interpretação de que a penalidade climática propagada à geração representa não apenas a perda de estoque hídrico, mas também a diminuição da flexibilidade operativa do sistema, um dos principais canais de transmissão dos efeitos climáticos para os custos do setor elétrico.

3.2.5 Propagação conjunta de incerteza (ΔEAR → ΔG_hidro) Este bloco realiza uma simulação Monte Carlo encadeada: cada sorteio inclui simultaneamente os coeficientes do modelo climático (m1_gam) e do modelo hidrelétrico (m2_hidro). Assim, as incertezas da previsão do armazenamento (EAR) são transmitidas integralmente para as previsões de geração, produzindo uma distribuição conjunta para \(Δ𝐺_{ℎ𝑖𝑑𝑟𝑜}\).

3.2.6 Resultados — Propagação integral de incerteza (ΔG_hidro conjunto) partindo do m2——————–

library(MASS)
library(dplyr)
library(lubridate)

set.seed(20251011)
nsim <- 500  # pode aumentar depois para 1000, mas teste com 500 primeiro


# --- 1. Covariâncias e sorteios dos coeficientes ----------------------------
Vp1 <- vcov(m1_gam)
Vp2 <- vcov(m2_hidro)
beta_draws_1 <- MASS::mvrnorm(n = nsim, mu = coef(m1_gam), Sigma = Vp1)
beta_draws_2 <- MASS::mvrnorm(n = nsim, mu = coef(m2_hidro), Sigma = Vp2)

# --- 2. Matrizes do modelo 1 (EAR ~ clima) ----------------------------------
X_obs_ear <- predict(m1_gam, newdata = nd_obs, type = "lpmatrix")
X_cf_ear  <- predict(m1_gam, newdata = nd_cf,  type = "lpmatrix")

# --- 3. Propagação Monte Carlo encadeada -----------------------------------
delta_G_joint <- matrix(NA_real_, nrow = nrow(nd_obs), ncol = nsim)

for (s in seq_len(nsim)) {
  # 1. EAR factual e contrafactual simulados
  ear_f <- as.numeric(X_obs_ear %*% beta_draws_1[s, ])
  ear_c <- as.numeric(X_cf_ear  %*% beta_draws_1[s, ])
  
  # 2. Atualizar inputs do modelo de geração
  nd_f <- nd_obs %>%
    mutate(ear_reservatorio_subsistema_proprio_mwmes = ear_f)
  nd_c <- nd_obs %>%
    mutate(ear_reservatorio_subsistema_proprio_mwmes = ear_c)
  
  # 3. Predições completas do modelo de geração (não linear)
  g_f <- predict(m2_hidro, newdata = nd_f, type = "response")
  g_c <- predict(m2_hidro, newdata = nd_c, type = "response")
  
  # 4. Penalidade propagada
  delta_G_joint[, s] <- g_f - g_c
  print(s)
}


write_rds(delta_G_joint, "delta_G_joint.rds")
delta_G_joint<-read_rds("data/delta_G_joint.rds")
Error in readRDS(con, refhook = refhook) : não é possível abrir a conexão
# --- 4. Agregar por subsistema e ano ----------------------------------------
nd_obs$Year
dt <- nd_obs %>% select(Year, nom_subsistema.x)
dt$Year<-nd_obs$Year


library(data.table)
dt <- as.data.table(dt)
groups <- unique(dt[, .(Year, nom_subsistema.x)])

agg_joint <- lapply(seq_len(nrow(groups)), function(g){
  idx <- which(dt$Year == groups$Year[g] & dt$nom_subsistema.x == groups$nom_subsistema.x[g])
  colSums(delta_G_joint[idx, , drop = FALSE], na.rm = TRUE)
})
agg_joint <- do.call(rbind, agg_joint)
colnames(agg_joint) <- paste0("sim_", 1:nsim)
  agg_df <- cbind(groups, agg_joint)
# --- 5. Estatísticas resumo -------------------------------------------------
m2_joint_summary <- agg_df %>%
  tidyr::pivot_longer(cols = starts_with("sim_"), values_to = "delta_G") %>%
  group_by(Year, nom_subsistema.x) %>%
  summarise(
    mean = mean(delta_G, na.rm = TRUE),
    lwr  = quantile(delta_G, 0.025, na.rm = TRUE),
    upr  = quantile(delta_G, 0.975, na.rm = TRUE),
    .groups = "drop"
  )
library(ggplot2)
m2_joint_summary %>%
  ggplot(aes(x = Year, y = mean)) +
  geom_ribbon(aes(ymin = lwr, ymax = upr), fill = "firebrick", alpha = 0.3) +
  geom_line(color = "black") +
  facet_wrap(~nom_subsistema.x, scales = "free_y") +
  labs(title = "Joint propagated climate penalty on hydropower generation (ΔG_hidro)",
       subtitle = "Uncertainty fully propagated from climate → storage → generation",
       y = "ΔG_hidro (MW·month)", x = "Year") +
  theme_minimal()
library(ggplot2)
m2_joint_summary %>%
  ggplot(aes(x = Year, y = mean/1000)) +
  geom_ribbon(aes(ymin = lwr/1000, ymax = upr/1000), fill = "steelblue", alpha = 1) +
    geom_ribbon(aes(ymin = 0, ymax = upr/1000), fill = "firebrick", alpha = 0.1) +

  geom_line(color = "black") +
  facet_wrap(~nom_subsistema.x, scales = "free_y") +
  labs(title = "Joint propagated climate penalty on hydropower generation (ΔG_hidro)",
       subtitle = "Uncertainty fully propagated from climate → storage → generation",
       y = "ΔG_hidro (GW·month)", x = "Year") +
  theme_minimal()

A Figura apresenta a penalidade climática sobre a geração hidrelétrica (ΔG_hidro) estimada com propagação conjunta de incerteza ao longo de toda a cadeia climato-hidrológica. Diferentemente das abordagens que tratam os modelos de forma independente, esta simulação incorpora simultaneamente a incerteza dos coeficientes do modelo climático (EAR ~ clima) e do modelo hidrelétrico (geração ~ EAR), gerando uma distribuição conjunta de resultados. Cada trajetória Monte Carlo representa uma combinação plausível de parâmetros e condições climáticas, permitindo capturar a variabilidade estrutural e climática do sistema.

Os resultados mostram que a incerteza propagada amplia os intervalos de confiança das estimativas anuais de ΔG_hidro, principalmente após 2010, quando a variabilidade climática e operacional aumenta significativamente. O subsistema Sudeste concentra as maiores perdas médias (até –4,5 × 10⁶ MW·mês) e a maior dispersão interanual, refletindo tanto a magnitude de sua capacidade de armazenamento quanto sua exposição a secas prolongadas. O Sul apresenta penalidades menores, mas com amplitudes de incerteza elevadas, coerentes com sua instabilidade hidrológica. Nordeste e Norte mostram menores déficits absolutos, mas com tendência negativa contínua.
Esses resultados representam a estimativa mais completa de impacto climático propagado no sistema elétrico, pois integram incertezas climáticas, hidrológicas e operacionais dentro de uma mesma estrutura probabilística.

m2_summary <- m2_joint_summary %>%
  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
m2_summary <- m2_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)
m2_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 ΔG_hidro (GWh)",
    lwr_GWh  = "Lower 95%",
    upr_GWh  = "Upper 95%",
  ) %>%
  tab_header(
    title = md("**Aggregate climate penalty on Hidric Generation (2001–2018)**"),
    subtitle = "Simulated mean and 95% confidence intervals per subsystem"
  )
Aggregate climate penalty on Hidric Generation (2001–2018)
Simulated mean and 95% confidence intervals per subsystem
Subsystem Mean ΔG_hidro (GWh) Lower 95% Upper 95%
NORDESTE −6.8 −7.0 −6.6
NORTE −1.9 −2.1 −1.6
SUDESTE −79.0 −82.5 −76.0
SUL −16.7 −17.8 −15.9
Total −104.4 −109.4 −100.1

3.3 Modelo 3 — Geração Termica como Função da Geração Hidrelétrica

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)

O Modelo 3 estima a resposta da geração térmica às variações na geração hidrelétrica, incorporando a competição com outras fontes e o ciclo sazonal de demanda. O modelo aditivo generalizado (GAM) foi ajustado para o período 2000–2019, com estrutura semiparamétrica que permite capturar relações não lineares entre as fontes de geração e seus determinantes temporais. Os resultados indicam uma relação negativa e estatisticamente significativa entre geração hidrelétrica e térmica, evidenciando o papel da térmica como mecanismo de compensação durante períodos de escassez hídrica. O efeito marginal de ger_hidroeletrica é fortemente não linear, com respostas mais intensas em faixas intermediárias de redução, o que sugere que o despacho térmico atinge limites estruturais de expansão em anos de seca severa.

library(mgcv)
library(dplyr)

# --- Preparação dos dados ---------------------------------------------------
gera_energ_day <- gera_energ_day %>%
  mutate(
    Demanda = ger_eolieletrica + ger_fotovoltaica + ger_hidroeletrica + ger_termica + ger_nuclear,
    month = as.numeric(format(date, "%m")),
    trend = as.numeric(date - min(date)) / 30  # tendência linear em meses
  )

# --- Modelo GAM 3: Geração Térmica como função da Hidro + outras fontes -----
m3_gam_termica <- bam(
  ger_termica ~ 
    s(ger_hidroeletrica, k = 4) +    # principal efeito substitutivo
    s(ger_eolieletrica, k = 4) +
    s(ger_fotovoltaica, k = 4) +
    s(ger_nuclear, k = 3) +
    s(trend, k = 3) +
    s(month, bs = "cc", k = 4) +     # padrão sazonal
    s(nom_subsistema, bs = "re"),  # efeito aleatório por subsistema
  data = gera_energ_day,
  method = "fREML",
  discrete = TRUE,
  family = gaussian(),
  na.action = na.exclude
)

summary(m3_gam_termica)
summary(m3_gam_termica)
gtsummary::tbl_regression(m3_gam_termica)
summary(m3_gam_termica)
gam.check(m3_gam_termica)          # resíduos, QQ, k-index
concurvity(m3_gam_termica, full=TRUE)
plot(m3_gam_termica, pages=4, scheme=1, shade=TRUE, se=TRUE)

\(𝑔𝑒𝑟 𝑡𝑒𝑟𝑚𝑖𝑐𝑎_𝑡=𝑓_1(𝑔𝑒_h𝑖𝑑𝑟𝑜_𝑡)+𝑓_2(𝑔𝑒𝑟_𝑒𝑜𝑙𝑖𝑐𝑎_𝑡)+𝑓_3(𝑔𝑒𝑟_𝑠𝑜𝑙𝑎𝑟_𝑡)+_𝑓_4(𝑔𝑒𝑟_𝑛𝑢𝑐𝑙𝑒𝑎𝑟𝑡)+𝑓_5(𝑡𝑟𝑒𝑛𝑑_𝑡)+𝑓_6(𝑚𝑜𝑛𝑡ℎ_𝑡)+𝑢𝑠𝑢𝑏𝑠𝑖𝑠𝑡𝑒𝑚𝑎+𝜀\) Qualidade do ajuste

O modelo apresenta R² ajustado de 0,64 e deviance explicada de 64,1%, indicando boa capacidade preditiva diante da alta variabilidade interdiária. Todos os efeitos suaves são altamente significativos (p < 0.001), com exceção do intercepto. O histograma e o QQ-plot dos resíduos mostram distribuição aproximadamente normal, com leve assimetria nas caudas — reflexo de picos de despacho térmico em períodos de seca severa.

O gráfico “Resíduos vs. Valores Ajustados” revela dispersão crescente com o aumento da geração prevista, sugerindo heterocedasticidade moderada associada a regimes distintos de operação (base × pico). Ainda assim, os resíduos são centrados e sem padrão sistemático, confirmando a adequação geral da especificação.

Efeitos parciais

Os efeitos marginais estimados exibem comportamentos coerentes com a lógica física do sistema:

-s(ger_eolieletrica) e s(ger_fotovoltaica) → ambas apresentam efeitos substitutivos negativos, evidenciando o papel das renováveis na mitigação do uso térmico.

Síntese O modelo confirma o papel contracíclico da geração térmica no sistema elétrico brasileiro: quando o clima reduz a geração hídrica, a resposta térmica compensa parte do déficit, com sensibilidade não linear e limites operacionais definidos.

A estrutura suavizada dos efeitos permite quantificar a elasticidade marginal entre fontes, que será usada na próxima etapa para estimar a penalidade térmica propagada (ΔG_term) resultante da penalidade hídrica (ΔG_hidro) obtida no Modelo

Predições factual vs. contrafactual (propagação de incerteza)

# --- 5. Loop principal de propagação Monte Carlo -----------------------------
for (s in seq_len(nsim)) {
  # ===== (1) EAR factual e contrafactual (M1) no nível de reservatório×dia
  ear_f <- as.numeric(X1_obs %*% b1[s, ])
  ear_c <- as.numeric(X1_cf  %*% b1[s, ])

  # ===== (2) Predição de G_hidro factual e cf (M2) no nível de reservatório×dia
  nd2_f <- reserv %>% mutate(ear_reservatorio_subsistema_proprio_mwmes = ear_f)
  nd2_c <- reserv %>% mutate(ear_reservatorio_subsistema_proprio_mwmes = ear_c)

  X2_f <- predict(m2_hidro, newdata = nd2_f, type = "lpmatrix")
  X2_c <- predict(m2_hidro, newdata = nd2_c, type = "lpmatrix")

  g_h_f_res <- as.numeric(X2_f %*% b2[s, ])  # por reservatório×dia
  g_h_c_res <- as.numeric(X2_c %*% b2[s, ])

  # ===== (3) Agregar G_hidro por subsistema×dia (para alimentar M3)
  df_h <- data.frame(date = keys_m2$date,
                     subs = keys_m2$nom_subsistema.x,
                     g_h_f = g_h_f_res,
                     g_h_c = g_h_c_res)

  g_h_agg <- df_h |>
    group_by(date, subs) |>
    summarise(g_h_f = sum(g_h_f, na.rm = TRUE),
              g_h_c = sum(g_h_c, na.rm = TRUE), .groups = "drop")

  # ΔG_hidro_clima (subsistema×dia)
  g_h_agg <- g_h_agg |>
    mutate(delta_g_hidro_clima = g_h_f - g_h_c)

  # ===== (4) Construir input do M3
  # factual: usa a hidrelétrica observada (gera_energ_day$ger_hidroeletrica)
  # contrafactual: obs − ΔG_hidro_clima
  nd3 <- gera_energ_day |>
    left_join(g_h_agg,
              by = c("date" = "date", "nom_subsistema" = "subs"))

  # se faltar subsistema em algum dia, trata NA como 0 delta
  nd3$delta_g_hidro_clima[is.na(nd3$delta_g_hidro_clima)] <- 0

  g_h_obs <- nd3$ger_hidroeletrica
  g_h_cfM3 <- g_h_obs - nd3$delta_g_hidro_clima# clipping em 0

  nd3_f <- nd3 %>% mutate(ger_hidroeletrica = g_h_obs)   # factual (observado)
  nd3_c <- nd3 %>% mutate(ger_hidroeletrica = g_h_cfM3)  # contrafactual (obs − Δclima)

  # ===== (5) Predição térmica factual e cf (M3) no nível subsistema×dia
  X3_f <- predict(m3_gam_termica, newdata = nd3_f, type = "lpmatrix")
  X3_c <- predict(m3_gam_termica, newdata = nd3_c, type = "lpmatrix")

  g_t_f <- as.numeric(X3_f %*% b3[s, ])
  g_t_c <- as.numeric(X3_c %*% b3[s, ])

  delta_Gterm_mat[, s] <- g_t_f - g_t_c
  print(s)
}

Aggregate climate penalty on stored energy (2001–2018)
Simulated mean and 95% confidence intervals per subsystem
Subsystem Sum Δger Term (MWh) Lower 95% Upper 95%
NORDESTE −35,567.9 −37,124.3 −34,109.4
NORTE 7,159.6 −172.2 11,126.5
SUDESTE 195,864.3 171,174.0 213,723.0
SUL 567,160.8 539,040.6 587,110.0
Total 734,616.8 672,918.1 777,850.2

#3.4 Modelo 3 PLD: Custo para o sistema

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

#pld$date<-pld$DATA_INICIO %>% as_date() 
pld %>% spread(Submercado,preco)->pld
Error in `spread()`:
Caused by error:
! objeto 'Submercado' não encontrado
Run `]8;;x-r-run:rlang::last_trace()rlang::last_trace()]8;;` to see where the error occurred.
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

NA
NA
pld$Submercado %>% unique()
NULL
gera_energ_day$nom_subsistema.x %>% unique
Aviso: Unknown or uninitialised column: `nom_subsistema.x`.
NULL
#newdata_m1 %>% write.csv("base valores previstos.csv")
#gera_energ_day %>% write.csv("valores_previstos_day.csv")
pld_full %>% summary()
      date            nom_subsistema     val_geracao_day_subsistema ger_eolieletrica  ger_fotovoltaica  ger_hidroeletrica
 Min.   :2001-06-30   Length:25536       Min.   :    0              Min.   :   0.00   Min.   :  0.000   Min.   :    0    
 1st Qu.:2005-11-12   Class :character   1st Qu.: 5109              1st Qu.:   0.00   1st Qu.:  0.000   1st Qu.: 3736    
 Median :2010-03-27   Mode  :character   Median : 7269              Median :   0.00   Median :  0.000   Median : 6233    
 Mean   :2010-03-29                      Mean   :10564              Mean   : 257.88   Mean   :  5.367   Mean   :10019    
 3rd Qu.:2014-08-11                      3rd Qu.:11367              3rd Qu.:  69.93   3rd Qu.:  0.000   3rd Qu.:13023    
 Max.   :2018-12-31                      Max.   :40055              Max.   :7863.72   Max.   :375.152   Max.   :35712    
                                         NA's   :2078                                                                    
  ger_nuclear      ger_termica          doy         dow           month            trend           Demanda           ANO      
 Min.   :   0.0   Min.   :   0.0   Min.   :  1.0   dom:3650   Min.   : 1.000   Min.   : 18.20   Min.   :    0   Min.   :2001  
 1st Qu.:   0.0   1st Qu.: 235.0   1st Qu.: 94.0   seg:3649   1st Qu.: 4.000   1st Qu.: 71.42   1st Qu.: 5308   1st Qu.:2005  
 Median :   0.0   Median : 974.5   Median :188.0   ter:3646   Median : 7.000   Median :124.62   Median : 7653   Median :2010  
 Mean   : 403.9   Mean   :1428.6   Mean   :185.8   qua:3646   Mean   : 6.612   Mean   :124.67   Mean   :12115   Mean   :2010  
 3rd Qu.:   0.0   3rd Qu.:1933.6   3rd Qu.:277.0   qui:3646   3rd Qu.:10.000   3rd Qu.:177.87   3rd Qu.:14941   3rd Qu.:2014  
 Max.   :2026.2   Max.   :8117.4   Max.   :366.0   sex:3649   Max.   :12.000   Max.   :231.30   Max.   :40688   Max.   :2018  
                                                   sáb:3650                                                                   
      MES             SEMANA      DATA_INICIO          DATA_FIM              week            year           preco       
 Min.   : 1.000   Min.   :  1.0   Length:25536       Length:25536       Min.   : 1      Min.   :2001    Min.   :  4.00  
 1st Qu.: 4.000   1st Qu.:232.0   Class :character   Class :character   1st Qu.:14      1st Qu.:2005    1st Qu.: 18.59  
 Median : 7.000   Median :460.0   Mode  :character   Mode  :character   Median :27      Median :2010    Median : 79.16  
 Mean   : 6.612   Mean   :459.9                                         Mean   :27      Mean   :2010    Mean   :159.29  
 3rd Qu.:10.000   3rd Qu.:688.0                                         3rd Qu.:40      3rd Qu.:2014    3rd Qu.:213.52  
 Max.   :12.000   Max.   :919.0                                         Max.   :53      Max.   :2018    Max.   :822.83  
                                                                        NA's   :21866   NA's   :21866                   

Modelo 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,
                 ))
Error in eval(predvars, data, env) : 
  objeto 'nom_subsistema.x' não encontrado
summary(gam_3_pld)

Family: gaussian 
Link function: identity 

Formula:
preco ~ 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)) + nom_subsistema

Parametric coefficients:
                      Estimate Std. Error t value Pr(>|t|)    
(Intercept)            123.845      5.255  23.565   <2e-16 ***
nom_subsistemaNORTE     56.400      6.080   9.276   <2e-16 ***
nom_subsistemaSUDESTE   42.572     17.231   2.471   0.0135 *  
nom_subsistemaSUL       42.793      3.838  11.149   <2e-16 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Approximate significance of smooth terms:
                            edf Ref.df      F p-value    
s(log(ger_hidroeletrica)) 9.000  9.000 171.44  <2e-16 ***
s(log(trend))             8.985  9.000 680.45  <2e-16 ***
s(log(doy))               8.881  8.996  13.21  <2e-16 ***
s(log(ger_eolieletrica))  8.479  8.922  66.83  <2e-16 ***
s(log(ger_fotovoltaica))  8.627  8.956  60.52  <2e-16 ***
s(log(Demanda))           8.952  8.999 204.85  <2e-16 ***
s(log(ger_termica))       8.963  9.000 158.85  <2e-16 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

R-sq.(adj) =  0.614   Deviance explained = 61.5%
GCV =  14797  Scale est. = 14759     n = 25536
summary(gam_3_pld)

Family: gaussian 
Link function: identity 

Formula:
preco ~ 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)) + nom_subsistema

Parametric coefficients:
                      Estimate Std. Error t value Pr(>|t|)    
(Intercept)            123.845      5.255  23.565   <2e-16 ***
nom_subsistemaNORTE     56.400      6.080   9.276   <2e-16 ***
nom_subsistemaSUDESTE   42.572     17.231   2.471   0.0135 *  
nom_subsistemaSUL       42.793      3.838  11.149   <2e-16 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Approximate significance of smooth terms:
                            edf Ref.df      F p-value    
s(log(ger_hidroeletrica)) 9.000  9.000 171.44  <2e-16 ***
s(log(trend))             8.985  9.000 680.45  <2e-16 ***
s(log(doy))               8.881  8.996  13.21  <2e-16 ***
s(log(ger_eolieletrica))  8.479  8.922  66.83  <2e-16 ***
s(log(ger_fotovoltaica))  8.627  8.956  60.52  <2e-16 ***
s(log(Demanda))           8.952  8.999 204.85  <2e-16 ***
s(log(ger_termica))       8.963  9.000 158.85  <2e-16 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

R-sq.(adj) =  0.614   Deviance explained = 61.5%
GCV =  14797  Scale est. = 14759     n = 25536
gtsummary::tbl_regression(gam_3_pld)
Characteristic Beta 95% CI1 p-value
nom_subsistema


    NORDESTE
    NORTE 56 44, 68 <0.001
    SUDESTE 43 8.8, 76 0.013
    SUL 43 35, 50 <0.001
s(log(ger_hidroeletrica))

<0.001
s(log(trend))

<0.001
s(log(doy))

<0.001
s(log(ger_eolieletrica))

<0.001
s(log(ger_fotovoltaica))

<0.001
s(log(Demanda))

<0.001
s(log(ger_termica))

<0.001
1 CI = Confidence Interval
summary(gam_3_pld)

Family: gaussian 
Link function: identity 

Formula:
preco ~ 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)) + nom_subsistema

Parametric coefficients:
                      Estimate Std. Error t value Pr(>|t|)    
(Intercept)            123.845      5.255  23.565   <2e-16 ***
nom_subsistemaNORTE     56.400      6.080   9.276   <2e-16 ***
nom_subsistemaSUDESTE   42.572     17.231   2.471   0.0135 *  
nom_subsistemaSUL       42.793      3.838  11.149   <2e-16 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Approximate significance of smooth terms:
                            edf Ref.df      F p-value    
s(log(ger_hidroeletrica)) 9.000  9.000 171.44  <2e-16 ***
s(log(trend))             8.985  9.000 680.45  <2e-16 ***
s(log(doy))               8.881  8.996  13.21  <2e-16 ***
s(log(ger_eolieletrica))  8.479  8.922  66.83  <2e-16 ***
s(log(ger_fotovoltaica))  8.627  8.956  60.52  <2e-16 ***
s(log(Demanda))           8.952  8.999 204.85  <2e-16 ***
s(log(ger_termica))       8.963  9.000 158.85  <2e-16 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

R-sq.(adj) =  0.614   Deviance explained = 61.5%
GCV =  14797  Scale est. = 14759     n = 25536
gam.check(gam_3_pld)          # resíduos, QQ, k-index


Method: GCV   Optimizer: magic
Smoothing parameter selection converged after 23 iterations.
The RMS GCV score gradient at convergence was 0.001482978 .
The Hessian was positive definite.
Model rank =  67 / 67 

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(log(ger_hidroeletrica)) 9.00 9.00    1.00    0.34    
s(log(trend))             9.00 8.99    0.34  <2e-16 ***
s(log(doy))               9.00 8.88    0.99    0.32    
s(log(ger_eolieletrica))  9.00 8.48    0.98    0.07 .  
s(log(ger_fotovoltaica))  9.00 8.63    0.98    0.11    
s(log(Demanda))           9.00 8.95    1.01    0.66    
s(log(ger_termica))       9.00 8.96    0.98    0.12    
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

concurvity(gam_3_pld, full=TRUE)
              para s(log(ger_hidroeletrica)) s(log(trend)) s(log(doy)) s(log(ger_eolieletrica)) s(log(ger_fotovoltaica))
worst    0.9792992                 0.9994989     0.8701883  0.16445905                0.9702436                0.7582099
observed 0.9792992                 0.9973993     0.4043606  0.03943132                0.9065618                0.4626105
estimate 0.9792992                 0.9742579     0.6596454  0.03892563                0.8213786                0.4134559
         s(log(Demanda)) s(log(ger_termica))
worst          0.9996432           0.9847597
observed       0.9966872           0.7688939
estimate       0.9727015           0.8624509
plot(gam_3_pld, pages=4, scheme=1, shade=TRUE, se=TRUE)

# --- 2. Matrizes de design do M1 (clima → EAR) -------------------------------
X1_obs <- predict(m1_gam, newdata = nd_obs, type = "lpmatrix")
X1_cf  <- predict(m1_gam, newdata = nd_cf,  type = "lpmatrix")
# --- 3. Preparação de bases e matrizes de saída ------------------------------
delta_PLD_mat <- matrix(NA_real_, nrow = nrow(preco_day), ncol = nsim)
Erro: objeto 'preco_day' não encontrado
# ==========================================================
# --- 4. Loop principal de propagação Monte Carlo ----------
# ==========================================================
for (s in seq_len(nsim)) {

  # ===== (1) EAR factual e contrafactual (M1) por reservatório×dia ===========
  ear_f <- as.numeric(X1_obs %*% b1[s, ])
  ear_c <- as.numeric(X1_cf  %*% b1[s, ])

  # ===== (2) Predição de G_hidro factual e cf (M2) ===========================
  nd2_f <- reserv %>% mutate(ear_reservatorio_subsistema_proprio_mwmes = ear_f)
  nd2_c <- reserv %>% mutate(ear_reservatorio_subsistema_proprio_mwmes = ear_c)

  X2_f <- predict(m2_hidro, newdata = nd2_f, type = "lpmatrix")
  X2_c <- predict(m2_hidro, newdata = nd2_c, type = "lpmatrix")

  g_h_f_res <- as.numeric(X2_f %*% b2[s, ])  # geração hídrica por reservatório×dia
  g_h_c_res <- as.numeric(X2_c %*% b2[s, ])

  # ===== (3) Agregar G_hidro para subsistema×dia =============================
  df_h <- data.frame(date = keys_m2$date,
                     subs = keys_m2$nom_subsistema.x,
                     g_h_f = g_h_f_res,
                     g_h_c = g_h_c_res)

  g_h_agg <- df_h |>
    group_by(date, subs) |>
    summarise(g_h_f = sum(g_h_f, na.rm = TRUE),
              g_h_c = sum(g_h_c, na.rm = TRUE), .groups = "drop") |>
    mutate(delta_g_hidro_clima = g_h_f - g_h_c)

# ===== (4) Construir input do M3 (subsistema×dia) ==========================
  nd3 <- gera_energ_day |>
    left_join(g_h_agg, by = c("date" = "date", "nom_subsistema" = "subs"))

  nd3$delta_g_hidro_clima[is.na(nd3$delta_g_hidro_clima)] <- 0

  g_h_obs <- nd3$ger_hidroeletrica
  g_h_cfM3 <- g_h_obs - nd3$delta_g_hidro_clima   # sem truncagem

  nd3_f <- nd3 %>% mutate(ger_hidroeletrica = g_h_obs)%>%
                 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,
                 )
  nd3_c <- nd3 %>% mutate(ger_hidroeletrica = g_h_cfM3)%>%
                 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,
                 )

  # ===== (5) Predição térmica factual e cf (M3) ==============================
  X3_f <- predict(m3_gam_termica, newdata = nd3_f, type = "lpmatrix")
  X3_c <- predict(m3_gam_termica, newdata = nd3_c, type = "lpmatrix")

  g_t_f <- as.numeric(X3_f %*% b3[s, ])
  g_t_c <- as.numeric(X3_c %*% b3[s, ])

  delta_g_term_clima <- g_t_f - g_t_c

# ===== (6) Preparar input para M4 (preço) ==================================
  nd4 <- pld_full2 |>
    left_join(
      nd3 %>% select(date, nom_subsistema, ger_hidroeletrica) %>% 
        mutate(g_t_f=g_t_f,g_h_cfM3=g_h_cfM3,
               g_t_c=g_t_c,g_h_obs=g_h_obs,
               ),
      by = c("date", "nom_subsistema")
    ) |>
    mutate(ger_termica_f = g_t_f,
           ger_termica_c = g_t_c,
           ger_hidroeletrica_c = g_h_cfM3,
           ger_hidroeletrica_f = g_h_obs)

  # factual
  nd4_f <- nd4 %>% mutate(
    ger_termica = ger_termica_f,
    ger_hidroeletrica = ger_hidroeletrica_f
  )%>%
                 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,
                 )
  # contrafactual (com penalidade climática propagada)
  nd4_c <- nd4 %>% mutate(
    ger_termica = ger_termica_c,
    ger_hidroeletrica = ger_hidroeletrica_c
  )%>%
                 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,
                 )
# ===== (7) Predição de preço factual e cf (M4) =============================
  X4_f <- predict(gam_4_pld, newdata = nd4_f, type = "lpmatrix")
  X4_c <- predict(gam_4_pld, newdata = nd4_c, type = "lpmatrix")

  pld_f <- as.numeric(X4_f %*% b4[s, ])
  pld_c <- as.numeric(X4_c %*% b4[s, ])

  delta_PLD_mat[, s] <- pld_f - pld_c   # penalidade climática em preço (R$/MWh)
  print(s)
}
[1] 1
[1] 2
[1] 3
[1] 4
[1] 5
[1] 6
[1] 7
[1] 8
[1] 9
[1] 10
[1] 11
[1] 12
[1] 13
[1] 14
[1] 15
[1] 16
[1] 17
[1] 18
[1] 19
[1] 20
[1] 21
[1] 22
[1] 23
[1] 24
[1] 25
[1] 26
[1] 27
[1] 28
[1] 29
[1] 30
[1] 31
[1] 32
[1] 33
[1] 34
[1] 35
[1] 36
[1] 37
[1] 38
[1] 39
[1] 40
[1] 41
[1] 42
[1] 43
[1] 44
[1] 45
[1] 46
[1] 47
[1] 48
[1] 49
[1] 50

— 6. Visualização: Fan Chart do impacto no PLD ———-

Aggregate climate penalty on stored energy (2001–2018)
Simulated mean and 95% confidence intervals per subsystem
Subsystem mean Δpld Term (MWh) Lower 95% Upper 95%
NORDESTE 0.7 0.6 0.9
NORTE 1.1 0.9 1.2
SUDESTE 3.0 2.5 3.6
SUL 13.5 12.4 14.7
Total 18.4 16.5 20.3
LS0tDQp0aXRsZTogIkNsaW1hdGUgUGVuYWx0aWVzIGFuZCBTY2FyY2l0eSBQcmVzc3VyZSBpbiBCcmF6aWzigJlzIFBvd2VyIFNlY3RvciINCmF1dGhvcjogIlRoaWFnbyBHYXJkaW4gJiBEYW5pZWwgRGFubmEiDQpkYXRlOiAiMjAyNS0xMC0wNiAiDQpvdXRwdXQ6DQogIGh0bWxfbm90ZWJvb2s6IA0KICAgIHRvYzogdHJ1ZQ0KICAgIHRvY19kZXB0aDogMg0KICAgIHRoZW1lOiBqb3VybmFsDQplZGl0b3Jfb3B0aW9uczoNCiAgY2h1bmtfb3V0cHV0X3R5cGU6IGlubGluZQ0KLS0tDQoNCiMgUGFjb3Rlcw0KDQpgYGB7ciBDYXJyZWdhciBwYWNvdGVzLWJhc2UgZG8gcHJvamV0bzsgZGVmaW5pciBvcMOnw7VlcyBnbG9iYWlzfQ0KIyBDYXJyZWdhciBwYWNvdGVzLWJhc2UgZG8gcHJvamV0bw0KIyBNYW5pcHVsYcOnw6NvIGUgZGF0YXMNCmxpYnJhcnkodGlkeXZlcnNlKTtsaWJyYXJ5KGRhdGEudGFibGUpO2xpYnJhcnkobHVicmlkYXRlKTtsaWJyYXJ5KHBhdGNod29yayk7bGlicmFyeShIbWlzYykNCg0KIyBNb2RlbGFnZW0NCmxpYnJhcnkobWdjdik7bGlicmFyeShncmF0aWEpO2xpYnJhcnkobHVicmlkYXRlKTtsaWJyYXJ5KG1vZGVsc3VtbWFyeSk7bGlicmFyeShndCk7bGlicmFyeShnbHVlKTtsaWJyYXJ5KHNjYWxlcyk7bGlicmFyeShicm9vbSk7bGlicmFyeShicm9vbS5oZWxwZXJzKTtsaWJyYXJ5KGdlb2JyKQ0KIyBVdGlsaWRhZGVzDQpsaWJyYXJ5KHNjYWxlcyk7bGlicmFyeShwYXRjaHdvcmspO2xpYnJhcnkoa25pdHIpO2xpYnJhcnkoa2FibGVFeHRyYSkNCg0KIyBEZWZpbmlyIG9ww6fDtWVzIGdsb2JhaXMgZGUga25pdHINCmtuaXRyOjpvcHRzX2NodW5rJHNldCgNCiAgZWNobyAgICAgICA9IFRSVUUsDQogIG1lc3NhZ2UgICAgPSBUUlVFLA0KICB3YXJuaW5nICAgID0gVFJVRSwNCiAgZHBpICAgICAgICA9IDEyMCwNCiAgZmlnLmFsaWduICA9ICJjZW50ZXIiLA0KICBmaWcud2lkdGggID0gMTIsDQogIGZpZy5oZWlnaHQgPSA4DQopDQoNCiMgVGVtYSB2aXN1YWwgcGFkcsOjbyANCnRoZW1lX2FydGljbGUgPC0gZnVuY3Rpb24oKXsNCiAgdGhlbWVfbWluaW1hbChiYXNlX3NpemUgPSAxMSkgKw0KICAgIHRoZW1lKA0KICAgICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChmYWNlPSJib2xkIiksDQogICAgICBwbG90LnN1YnRpdGxlID0gZWxlbWVudF90ZXh0KG1hcmdpbj1tYXJnaW4oYj02KSksDQogICAgICBwbG90LmNhcHRpb24gID0gZWxlbWVudF90ZXh0KHNpemU9OSwgY29sb3I9ImdyZXkzMCIpLA0KICAgICAgYXhpcy50aXRsZSA9IGVsZW1lbnRfdGV4dCgpLA0KICAgICAgcGFuZWwuZ3JpZC5taW5vciA9IGVsZW1lbnRfYmxhbmsoKSwNCiAgICAgIGxlZ2VuZC5wb3NpdGlvbiA9ICJ0b3AiDQogICAgKQ0KfQ0KdGhlbWVfc2V0KHRoZW1lX2FydGljbGUoKSkNCnNldC5zZWVkKDEyMzQpDQpgYGANCg0KYGBge3IgaGVscGVyc30NCnByZWRpY3RfZ2FtX2NpIDwtIGZ1bmN0aW9uKG1vZGVsLCBuZXdkYXRhLCB0eXBlID0gImxpbmsiLCBsZXZlbCA9IDAuOTUpew0KICBzdG9waWZub3QoaW5oZXJpdHMobW9kZWwsICJnYW0iKSkNCiAgcHIgPC0gcHJlZGljdChtb2RlbCwgbmV3ZGF0YSA9IG5ld2RhdGEsIHR5cGUgPSB0eXBlLCBzZS5maXQgPSBUUlVFKQ0KICBhbHBoYSA8LSAxIC0gbGV2ZWwNCiAgY3JpdCAgPC0gcW5vcm0oMSAtIGFscGhhLzIpDQogIHRpYmJsZSgNCiAgICAuZml0dGVkID0gYXMubnVtZXJpYyhwciRmaXQpLA0KICAgIC5zZSAgICAgPSBhcy5udW1lcmljKHByJHNlLmZpdCksDQogICAgLmxvd2VyICA9IC5maXR0ZWQgLSBjcml0Ki5zZSwNCiAgICAudXBwZXIgID0gLmZpdHRlZCArIGNyaXQqLnNlDQogICkNCn0NCmV4cG9ydF9maWd1cmUgPC0gZnVuY3Rpb24ocCwgZmlsZW5hbWUsIHdpZHRoID0gNywgaGVpZ2h0ID0gNC4yKXsNCiAgZ2dzYXZlKGdsdWUoImZpZ3VyZXMve2ZpbGVuYW1lfS5wZGYiKSwgcGxvdCA9IHAsIHdpZHRoID0gd2lkdGgsIGhlaWdodCA9IGhlaWdodCwgZHBpID0gMzAwLCBkZXZpY2UgPSBjYWlyb19wZGYpDQogIGdnc2F2ZShnbHVlKCJmaWd1cmVzL3tmaWxlbmFtZX0uZXBzIiksIHBsb3QgPSBwLCB3aWR0aCA9IHdpZHRoLCBoZWlnaHQgPSBoZWlnaHQsIGRwaSA9IDMwMCwgZGV2aWNlID0gImVwcyIpDQogIGdnc2F2ZShnbHVlKCJmaWd1cmVzL3tmaWxlbmFtZX0udGlmZiIpLHBsb3QgPSBwLCB3aWR0aCA9IHdpZHRoLCBoZWlnaHQgPSBoZWlnaHQsIGRwaSA9IDYwMCwgY29tcHJlc3Npb24gPSAibHp3IikNCiAgaW52aXNpYmxlKE5VTEwpDQp9DQpleHBvcnRfdGFibGUgPC0gZnVuY3Rpb24oZ3Rfb2JqLCBmaWxlbmFtZSl7DQogIGd0c2F2ZShndF9vYmosIGZpbGVuYW1lID0gZ2x1ZSgidGFibGVzL3tmaWxlbmFtZX0uaHRtbCIpKQ0KICAjIFBORyAocHJlY2lzYSB3ZWJzaG90MiBpbnN0YWxhZG8vY29uZmlndXJhZG8pDQogIHRyeShndHNhdmUoZ3Rfb2JqLCBmaWxlbmFtZSA9IGdsdWUoInRhYmxlcy97ZmlsZW5hbWV9LnBuZyIpKSkNCiAgIyBMYVRlWA0KICB0cnkoZ3RzYXZlKGd0X29iaiwgZmlsZW5hbWUgPSBnbHVlKCJ0YWJsZXMve2ZpbGVuYW1lfS50ZXgiKSkpDQogIGludmlzaWJsZShOVUxMKQ0KfQ0KDQojIEVzdGlsbyBwYWRyw6NvIGRlIHRhYmVsYQ0KZ3RfYXJ0aWNsZSA8LSBmdW5jdGlvbihkYXQsIHRpdGxlID0gTlVMTCwgc3VidGl0bGUgPSBOVUxMLCBub3RlID0gTlVMTCl7DQogIGRhdCAlPiUNCiAgICBndCgpICU+JQ0KICAgIHRhYl9oZWFkZXIodGl0bGUgPSBtZCh0aXRsZSAlfHwlICIiKSwgc3VidGl0bGUgPSBtZChzdWJ0aXRsZSAlfHwlICIiKSkgJT4lDQogICAgZm10X251bWJlcih3aGVyZShpcy5udW1lcmljKSwgZGVjaW1hbHMgPSAyKSAlPiUNCiAgICB0YWJfb3B0aW9ucyh0YWJsZS5mb250LnNpemUgPSBweCgxMikpICU+JQ0KICAgIG9wdF9ob3Jpem9udGFsX3BhZGRpbmcoc2NhbGUgPSAxLjEpICU+JQ0KICAgIG9wdF92ZXJ0aWNhbF9wYWRkaW5nKHNjYWxlID0gMS4xKSAlPiUNCiAgICB0YWJfc291cmNlX25vdGUobWQobm90ZSAlfHwlICJOb3RlczogQXV0aG9y4oCZcyBjYWxjdWxhdGlvbnMuIikpDQp9DQpgYGANCg0KIyAxLiBJbnRyb2R1Y3Rpb24NCg0KVGhpcyByZXBvcnQgZG9jdW1lbnRzIHRoZSBhbmFseXRpY2FsIHBpcGVsaW5lIGRldmVsb3BlZCB0byBlc3RpbWF0ZSB0aGUgY2xpbWF0aWMgcGVuYWx0eSAocGVuYWxpZGFkZSBjbGltw6F0aWNhKSBvbiBCcmF6aWzigJlzIGVsZWN0cmljaXR5IHNlY3RvciBhbmQgdG8gdHJhbnNsYXRlIHRoZXNlIGVmZmVjdHMgaW50byBtZWFzdXJhYmxlIGVjb25vbWljIGNvc3RzLiBUaGUgYW5hbHlzaXMgd2FzIGNvbmR1Y3RlZCB1c2luZyBtb250aGx5IGRhdGEgZnJvbSAyMDAxIHRvIDIwMTksIGNvdmVyaW5nIGFsbCBmb3VyIHN1YnN5c3RlbXMgb2YgdGhlIE5hdGlvbmFsIEludGVyY29ubmVjdGVkIFN5c3RlbSAoU0lOKS4NCg0KVGhlIHN0dWR5IHByb2NlZWRzIHRocm91Z2ggdGhlIGZvbGxvd2luZyBzdGVwczoNCg0KMS4gIEh5ZHJvbG9naWNhbCBtb2RlbGxpbmcg4oCUIFdlIGVzdGltYXRlZCB0aGUgcmVsYXRpb25zaGlwIGJldHdlZW4gY2xpbWF0aWMgdmFyaWFibGVzIChwcmVjaXBpdGF0aW9uLCB0ZW1wZXJhdHVyZSwgaHVtaWRpdHksIHdpbmQpIGFuZCBzdG9yZWQgZW5lcmd5IChFQVIpIGFuZCBoeWRyb2VsZWN0cmljIGdlbmVyYXRpb24gdXNpbmcgR2VuZXJhbGl6ZWQgQWRkaXRpdmUgTW9kZWxzIChHQU1zKS4gVGhlc2UgbW9kZWxzIGNhcHR1cmUgbm9uLWxpbmVhciBjbGltYXRl4oCTaHlkcm9sb2d5IGludGVyYWN0aW9ucyBhbmQgc2Vhc29uYWwgZWZmZWN0cyBhdCB0aGUgc3Vic3lzdGVtIGxldmVsLg0KDQoyLiAgQ2xpbWF0aWMgY291bnRlcmZhY3R1YWxzIOKAlCBVc2luZyB0aGUgZml0dGVkIEdBTXMsIHdlIHNpbXVsYXRlZCBjb3VudGVyZmFjdHVhbCB0cmFqZWN0b3JpZXMgZml4aW5nIHRoZSBjbGltYXRpYyBjb3ZhcmlhdGVzIGF0IHRoZWlyIGhpc3RvcmljYWwgbWVhbiBsZXZlbHMgKGJhc2VsaW5lIDIwMDHigJMyMDA1KS4gVGhlIGRldmlhdGlvbiBiZXR3ZWVuIG9ic2VydmVkIGFuZCBjb3VudGVyZmFjdHVhbCB2YWx1ZXMgaXNvbGF0ZXMgdGhlIHNoYXJlIG9mIHZhcmlhdGlvbiBhdHRyaWJ1dGFibGUgZXhjbHVzaXZlbHkgdG8gY2xpbWF0ZSB2YXJpYWJpbGl0eS4NCg0KMy4gIENsaW1hdGUgcGVuYWx0eSAozpRFKSDigJQgVGhlIGNsaW1hdGUgcGVuYWx0eSB3YXMgZGVmaW5lZCBhcyAkzpRFPUVfe3ByZWRpY3RlZH3iiJJFX3tjZn0kIHJlcHJlc2VudGluZyB0aGUgbG9zcyAob3IgZ2Fpbikgb2YgaHlkcm8gZ2VuZXJhdGlvbiBkdWUgc29sZWx5IHRvIGNsaW1hdGljIGZsdWN0dWF0aW9ucy4NCg0KNC4gIEVsYXN0aWNpdGllcyDigJQgV2UgZGVyaXZlZCBlbGFzdGljaXRpZXMgbGlua2luZyBnZW5lcmF0aW9uIHRvIGh5ZHJvbG9naWNhbCBhbmQgY2xpbWF0aWMgY29uZGl0aW9ucywgYW5kIGRlbWFuZCB0byBwcmljZSBhbmQgaW5jb21lLCB0byBhc3Nlc3Mgc2Vuc2l0aXZpdHkgYW5kIHBvdGVudGlhbCB0cmFuc21pc3Npb24gY2hhbm5lbHMgb2YgY2xpbWF0aWMgc2hvY2tzLg0KDQo1LiAgQ29zdCB0cmFuc2xhdGlvbiDigJQgVGhlIGVzdGltYXRlZCBwZW5hbHRpZXMgd2VyZSBjb252ZXJ0ZWQgaW50byBtb25ldGFyeSB0ZXJtcyBhbG9uZyB0aHJlZSBjb3N0IGRpbWVuc2lvbnM6DQoNCjYuICBDb25zdW1lcnM6IGFkZGl0aW9uYWwgZXhwZW5kaXR1cmUgZHVlIHRvIHJlcGxhY2VtZW50IG9mIGNoZWFwZXIgaHlkcm8gZ2VuZXJhdGlvbiBieSBtb3JlIGV4cGVuc2l2ZSBzb3VyY2VzOw0KDQo3LiAgRWxlY3RyaWNpdHkgc2VjdG9yOiBoaWdoZXIgc3BvdCBtYXJrZXQgcHJpY2VzIChQTEQpIGFuZCBvcGVyYXRpb25hbCBjb3N0czsNCg0KVGhpcyBlbXBpcmljYWwgcGlwZWxpbmUgbGlua3MgY2xpbWF0ZSB2YXJpYWJpbGl0eSwgaHlkcm9sb2dpY2FsIHBlcmZvcm1hbmNlLCBhbmQgZWNvbm9taWMgb3V0Y29tZXMgdGhyb3VnaCBhIHVuaWZpZWQgc3RhdGlzdGljYWwgZnJhbWV3b3JrLCBlbmFibGluZyBhIG11bHRpZGltZW5zaW9uYWwgdmFsdWF0aW9uIG9mIGNsaW1hdGUtcmVsYXRlZCByaXNrcyBpbiBhIGh5ZHJvLWRlcGVuZGVudCBwb3dlciBzeXN0ZW0uDQoNCiMgMi4gRGF0YSBQcmVwYXJhdGlvbg0KDQpUaGlzIHNlY3Rpb24gZGVzY3JpYmVzIHRoZSBjb25zdHJ1Y3Rpb24gb2YgdGhlIGFuYWx5dGljYWwgZGF0YXNldCB1c2VkIHRvIGVzdGltYXRlIHRoZSBjbGltYXRpYyBwZW5hbHR5LlwNCkFsbCB2YXJpYWJsZXMgd2VyZSBoYXJtb25pemVkIGF0IHRoZSAqKnN1YnN5c3RlbeKAk2RheSoqIGxldmVsIGJldHdlZW4gMjAwMSBhbmQgMjAxOSwgaW50ZWdyYXRpbmcgaHlkcm9sb2dpY2FsLCBjbGltYXRpYywgYW5kIG1hcmtldCBpbmZvcm1hdGlvbi4NCg0KIyMjIDIuMSBEYXRhIFNvdXJjZXMNCg0KLSAgICAqKkh5ZHJvcG93ZXIgZ2VuZXJhdGlvbiAocGxhbnQtZGF5KToqKiBkYWlseSBnZW5lcmF0aW9uIGRhdGEgY29tcGlsZWQgZnJvbSBPTlMgcmVjb3JkcywgYWdncmVnYXRlZCBieSBzdWJzeXN0ZW0uDQoNCi0gICAqKlJlc2Vydm9pciBsZXZlbHMgYW5kIG5hdHVyYWwgaW5mbG93cyAoRUFSIGFuZCBFTkEpOioqIHN1YnN5c3RlbS1sZXZlbCBkYWlseSBkYXRhIGZyb20gT05TLg0KDQotICAgKipDbGltYXRpYyB2YXJpYWJsZXM6KiogcHJlY2lwaXRhdGlvbiBhbmQgdGVtcGVyYXR1cmUgb2J0YWluZWQgZnJvbSB0aGUgRUNNV0YvQ0FNUyByZWFuYWx5c2lzIGRhdGFzZXQsIGludGVycG9sYXRlZCB0byBtYXRjaCBzdWJzeXN0ZW0gY2VudHJvaWRzLg0KDQotICAgKipTcG90IHByaWNlIChQTEQpOioqIHdlZWtseSBzdWJzeXN0ZW0gZGF0YSBmcm9tIENDRUUuDQoNCi0gICAqKkRlbWFuZCBhbmQgZ2VuZXJhdGlvbiBkaXNwYXRjaCBieSBzb3VyY2U6KiogbW9udGhseSBvciB3ZWVrbHkgZGF0YSBmcm9tIE9OUyBhbmQgRVBFLg0KDQpBbGwgZGF0YXNldHMgd2VyZSBwcmUtcHJvY2Vzc2VkIHRvIGFsaWduIGRhdGUgZm9ybWF0cywgaGFybW9uaXplIHZhcmlhYmxlIG5hbWVzLCBhbmQgcmVtb3ZlIGluY29uc2lzdGVudCBvciBtaXNzaW5nIGlkZW50aWZpZXJzLg0KDQojIyMgMi4yIERhdGEgTG9hZGluZyBhbmQgQ2xlYW5pbmcNCg0KYGBge3IgZGF0YS1pbn0NCiMgTG9hZCBjb3JlIGRhdGFzZXRzDQpnZXIgICAgIDwtIHJlYWQuY3N2KCJiYXNlX2dlcmFfdHJhdGFkYV9zZXQuY3N2IikgICAgICMgcGxhbnQtZGF5IGdlbmVyYXRpb24NCnBsZCAgICAgPC0gcmVhZC5jc3YoInBsZF9kaWFyaW9fY29tcGxldG8uY3N2IikgICAgICAgICAgICAgIyB3ZWVrbHkgc3BvdCBwcmljZSAoUExEKQ0KcmVzZXJ2ICA8LSByZWFkLmNzdigiZW5hX2Vhcl9oaWRyX2NlZ19hbWIuY3N2IikgICAgICAjIHJlc2Vydm9pciBsZXZlbHMgJiBpbmZsb3dzIChFQVIvRU5BKQ0KYGBgDQoNCg0KYGBge3IgZGF0YS1pbiAyIH0NCiMgQ29udmVydCBjaGFyYWN0ZXIgY29sdW1ucyB0byBmYWN0b3JzDQpnZXIgICAgPC0gZ2VyICAgICU+JSBtdXRhdGUoYWNyb3NzKHdoZXJlKGlzLmNoYXJhY3RlciksIGFzLmZhY3RvcikpDQpyZXNlcnYgPC0gcmVzZXJ2ICU+JSBtdXRhdGUoYWNyb3NzKHdoZXJlKGlzLmNoYXJhY3RlciksIGFzLmZhY3RvcikpDQpwbGQgICAgPC0gcGxkICAgICU+JSBtdXRhdGUoYWNyb3NzKHdoZXJlKGlzLmNoYXJhY3RlciksIGFzLmZhY3RvcikpDQoNCiMgLS0tIERhdGUgcGFyc2luZyBhbmQgdGVtcG9yYWwgdmFyaWFibGVzIC0tLQ0KZ2VyJGRhdGUgICAgPC0gYXMuRGF0ZShnZXIkRGF0ZSkgICAgICAgICAgICAgICAjIGFkanVzdCBjb2x1bW4gbmFtZSBhcyBuZWVkZWQNCmdlciRkb3kgICAgIDwtIHlkYXkoZ2VyJGRhdGUpDQpnZXIkZG93ICAgICA8LSBsdWJyaWRhdGU6OndkYXkoZ2VyJGRhdGUsIGxhYmVsID0gVFJVRSwgYWJiciA9IFRSVUUpDQpnZXIkbW9udGggICA8LSBtb250aChnZXIkZGF0ZSkNCmdlciR0cmVuZCAgIDwtIGFzLm51bWVyaWMoZ2VyJGRhdGUpDQoNCnJlc2VydiRkYXRlIDwtIGFzLkRhdGUocmVzZXJ2JGVuYV9kYXRhKSAgICAgICAgIyBhZGp1c3QgY29sdW1uIG5hbWUgYXMgbmVlZGVkDQpyZXNlcnYkZG95ICA8LSB5ZGF5KHJlc2VydiRkYXRlKQ0KcmVzZXJ2JGRvdyAgPC0gbHVicmlkYXRlOjp3ZGF5KHJlc2VydiRkYXRlLCBsYWJlbCA9IFRSVUUsIGFiYnIgPSBUUlVFKQ0KcmVzZXJ2JG1vbnRoPC0gbW9udGgocmVzZXJ2JGRhdGUpDQpyZXNlcnYkdHJlbmQ8LSBhcy5udW1lcmljKHJlc2VydiRkYXRlKQ0KDQpwbGQkZGF0ZSAgICA8LSBhcy5EYXRlKHBsZCREQVRBX0lOSUNJTykgICAgICAgICMgYWRqdXN0IGNvbHVtbiBuYW1lIGFzIG5lZWRlZA0KcGxkJHdlZWsgICAgPC0gaXNvd2VlayhwbGQkZGF0ZSkNCnBsZCR5ZWFyICAgIDwtIHllYXIocGxkJGRhdGUpDQoNCmBgYA0KDQoNCg0KYGBge3IgY29uZmVyaXIgZSBsaW1wYXIgY29sdW5hcyBkdXBsaWNhZGFzfQ0KZHVwbGljYWRhcyA8LSBkdXBsaWNhdGVkKGFzLmxpc3QocmVzZXJ2KSkNCnJlc2VydlssZHVwbGljYWRhc10gJT4lIGNvbG5hbWVzKCkNCnJlc2VydjwtcmVzZXJ2ICU+JSBzZWxlY3QoLWlkX3N1YnNpc3RlbWEueC54LC1pZF9zdWJzaXN0ZW1hLnkueSwtbm9tX2JhY2lhLngsLW5vbV9iYWNpYS54LC1ub21fcmVlLngsLW5vbV9yZWUueSwtbm9tX3VzaW5hLngsLW5vbV9zdWJzaXN0ZW1hLnkueSwtbm9tX2JhY2lhLnkpDQpgYGANCg0KIyMjIDIuMyBUZW1wb3JhbCBTbW9vdGhpbmcgYW5kIFJvbGxpbmcgTWVhbnMNClRvIHJlZHVjZSBzaG9ydC10ZXJtIG5vaXNlIGFuZCBjYXB0dXJlIGN1bXVsYXRpdmUgY2xpbWF0aWMgZWZmZWN0cywgd2UgY29tcHV0ZWQgKipyb2xsaW5nIG1lYW5zICg3LCAxNCwgYW5kIDMwIGRheXMpKiogZm9yIGtleSBoeWRyb2xvZ2ljYWwgYW5kIGNsaW1hdGljIHZhcmlhYmxlcy4gIA0KDQoNCg0KYGBge3J9DQpsaWJyYXJ5KHpvbykNCmxpYnJhcnkoZHBseXIpDQoNCiMjZGlhZ19ncm91cHMgPC0gcmVzZXJ2ICU+JWZpbHRlcih0aXBfcmVzZXJ2YXRvcmlvPT0iUmVzZXJ2YXTDs3JpbyBjb20gVXNpbmEiKSAlPiUgDQojICBncm91cF9ieShub21fcmVzZXJ2YXRvcmlvLngsaWRfcmVzZXJ2YXRvcmlvLngsdGlwX3Jlc2VydmF0b3JpbykgJT4lDQojICBzdW1tYXJpc2UoDQojICAgIG5fdG90YWwgPSBuKCksDQojICAgIG5fbm9uX25hX3ByZWNpcCA9IHN1bSghaXMubmEocHJlY2lwdGF0aW9uKSksDQojICAgIG5fbm9uX25hX3RlbXAgICA9IHN1bSghaXMubmEodGVtcGVyYXR1cmUpKSwNCiMgICAgbl9ub25fbmFfZW5hICAgID0gc3VtKCFpcy5uYShlbmFfYnJ1dGFfcmVzX213bWVkKSksDQojICAgIG5fbm9uX25hX2VhciAgICA9IHN1bSghaXMubmEoZWFyX3Jlc2VydmF0b3Jpb19zdWJzaXN0ZW1hX3Byb3ByaW9fbXdtZXMpKSwNCiMgICAgbl9ub25fbmFfZ2VyICAgID0gc3VtKCFpcy5uYSh2YWxfZ2VyYWNhbykpLA0KIyAgICAuZ3JvdXBzID0gImRyb3AiDQojICApDQojIyBDcmlhciBtw6lkaWFzIG3Ds3ZlaXMgcGFyYSB2YXJpw6F2ZWlzIGFtYmllbnRhaXMgcHJpbmNpcGFpcw0KcmVzZXJ2IDwtIHJlc2VydiAlPiUgZmlsdGVyKHRpcF9yZXNlcnZhdG9yaW89PSJSZXNlcnZhdMOzcmlvIGNvbSBVc2luYSIpICU+JSANCiAgZ3JvdXBfYnkobm9tX3Jlc2VydmF0b3Jpby54KSAlPiUNCiAgYXJyYW5nZShkYXRlLCAuYnlfZ3JvdXAgPSBUUlVFKSAlPiUNCiAgbXV0YXRlKA0KICAgICMgUHJlY2lwaXRhdGlvbiAodXNhIG5vbWUgJ3ByZWNpcHRhdGlvbicgY29tbyBlc3TDoSBuYSBzdWEgYmFzZSkNCiAgICAjcHJlY2lwX21tNyAgID0gcm9sbG1lYW4ocHJlY2lwdGF0aW9uLCAgNyksDQogICAgcHJlY2lwX21tMTQgID0gcm9sbG1lYW4ocHJlY2lwdGF0aW9uLCAxNCxmaWxsID0gTkEsIGFsaWduID0gInJpZ2h0IiksDQogICAgcHJlY2lwX21tMzAgID0gcm9sbG1lYW4ocHJlY2lwdGF0aW9uLCAzMCxmaWxsID0gTkEsIGFsaWduID0gInJpZ2h0IiksDQoNCiAgICAjIFRlbXBlcmF0dXJlDQogICAgdGVtcF9tbTcgICAgID0gcm9sbG1lYW4odGVtcGVyYXR1cmUsICA3LGZpbGwgPSBOQSwgYWxpZ24gPSAicmlnaHQiKSwNCiAgICB0ZW1wX21tMTQgICAgPSByb2xsbWVhbih0ZW1wZXJhdHVyZSwgMTQsZmlsbCA9IE5BLCBhbGlnbiA9ICJyaWdodCIpLA0KICAgIHRlbXBfbW0zMCAgICA9IHJvbGxtZWFuKHRlbXBlcmF0dXJlLCAzMCxmaWxsID0gTkEsIGFsaWduID0gInJpZ2h0IiksDQoNCiAgICAjIEVOQQ0KICAgIGVuYV9tdzcgICAgICA9IHJvbGxtZWFuKGVuYV9icnV0YV9yZXNfbXdtZWQsICA3LGZpbGwgPSBOQSwgYWxpZ24gPSAicmlnaHQiKSwNCiAgICAjZW5hX213MTQgICAgID0gcm9sbF9tZWFuX3JpZ2h0KGVuYV9icnV0YV9yZXNfbXdtZWQsIDE0KSwNCiAgICAjZW5hX213MzAgICAgID0gcm9sbF9tZWFuX3JpZ2h0KGVuYV9icnV0YV9yZXNfbXdtZWQsIDMwKSwNCg0KICAgICMgRUFSIChwcm9wcmlldMOhcmlvKSDigJQgcmVtb3ZldSBmaWxsPSJleHRlbmQiIChuw6NvIHN1cG9ydGFkbykNCiAgICMgZWFyX213NyAgICAgID0gcm9sbF9tZWFuX3JpZ2h0KGVhcl9yZXNlcnZhdG9yaW9fc3Vic2lzdGVtYV9wcm9wcmlvX213bWVzLCA3KSwNCg0KICAgICMgR2VyYcOnw6NvDQogICAgZ2VyX213NyAgICAgID0gcm9sbG1lYW4odmFsX2dlcmFjYW8sICA3LGZpbGwgPSBOQSwgYWxpZ24gPSAicmlnaHQiKSwNCiAgICBnZXJfbXcxNCAgICAgPSByb2xsbWVhbih2YWxfZ2VyYWNhbywgMTQsZmlsbCA9IE5BLCBhbGlnbiA9ICJyaWdodCIpLA0KICAgIGdlcl9tdzMwICAgICA9IHJvbGxtZWFuKHZhbF9nZXJhY2FvLCAzMCxmaWxsID0gTkEsIGFsaWduID0gInJpZ2h0IikNCiAgKSAlPiUNCiAgdW5ncm91cCgpDQoNCiNkaWFnX2dyb3VwcyAlPiUgZmlsdGVyKG5vbV9yZXNlcnZhdG9yaW8ueD09IkEuIFZFUk1FTEhBIikgDQojICANCiNyZXNlcnYgJT4lIGZpbHRlcihub21fcmVzZXJ2YXRvcmlvLng9PSJBLiBWRVJNRUxIQSIpICU+JSANCiMgIGdncGxvdChhZXMocHJlY2lwdGF0aW9uKSkrZ2VvbV9saW5lKGFlcyh4PWRhdGUseT1wcmVjaXB0YXRpb24pLGNvbD0ibGlnaHRibHVlIikNCiMgIHNlbGVjdChkYXRlLG5vbV9lc3RhZG8sdmFsX2dlcmFjYW8scHJlY2lwdGF0aW9uLA0KIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICNlYXJtYXhfcmVzZXJ2YXRvcmlvX3N1YnNpc3RlbWFfanVzYW50ZV9td21lcyxlYXJfcmVzZXJ2YXRvcmlvX3N1YnNpc3RlbWFfcHJvcHJpb19td21lcyxlYXJfbWF4aW1hX3RvdGFsX213bWVzKSAlPiUgc3VtbWFyeQ0KYGBgDQoNCg0KDQoNCmBgYHtyfQ0KIyAtLS0gQ29uZmVyaXIgY2hhdmVzIHByaW5jaXBhaXMgLS0tDQojIHZlcmlmaWNhciBzZSBkYXRhcyBlIHN1YnNpc3RlbWFzIGJhdGVtDQpjYXQoIkRhdGFzIGRpc3BvbsOtdmVpczpcbiIpDQpyYW5nZShnZXIkZGF0ZSwgbmEucm09VFJVRSkNCnJhbmdlKHJlc2VydiRkYXRlLCBuYS5ybT1UUlVFKQ0KcmFuZ2UocGxkJGRhdGUsIG5hLnJtPVRSVUUpDQpgYGANCg0KIyMjIDIuNCBEZXNjcmlwdGl2ZSBTdW1tYXJpZXMNCg0KYGBge3IgZGVzY3JpcHRpdmUtc3VtbWFyaWVzLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQ0KbGlicmFyeShkcGx5cikNCmxpYnJhcnkodGlkeXIpDQpsaWJyYXJ5KGd0KQ0KbGlicmFyeShwdXJycikNCmxpYnJhcnkoc3RyaW5ncikNCg0KIyBIZWxwZXI6IHNlbGVjaW9uYSBhcyB2YXJpw6F2ZWlzIGV4YXRhcyBwZWRpZGFzLCBzZSBleGlzdGlyZW0gbm8gZGF0YXNldA0Kc2VsZWN0X2Rlc2NfdmFycyA8LSBmdW5jdGlvbihkZil7DQogIHdhbnRlZCA8LSB0aWR5c2VsZWN0Ojp2YXJzX3NlbGVjdCgNCiAgICBuYW1lcyhkZiksDQogICAgc3RhcnRzX3dpdGgoImVhciIpLA0KICAgIHN0YXJ0c193aXRoKCJ0ZW0iKSwNCiAgICBzdGFydHNfd2l0aCgicHJlIiksDQogICAgc3RhcnRzX3dpdGgoImdlciIpLA0KICAgIHZhbF9nZXJhY2FvLA0KICAgIHZhbF9nZXJhY2FvX2RheV9zdWJzaXN0ZW1hLA0KICAgIGh1bWlkaXR5LA0KICAgIHdpbmRfc3BlZWQNCiAgKQ0KICBkZiAlPiUgZHBseXI6OnNlbGVjdChub21fc3Vic2lzdGVtYS54LCBkcGx5cjo6YWxsX29mKHdhbnRlZCkpDQp9DQoNCiMgSGVscGVyOiBzdW1hcml6YSBlc3RhdMOtc3RpY2FzIHBhcmEgdW0gZGF0YS5mcmFtZSBqw6EgZmlsdHJhZG8gcG9yIHN1YnNpc3RlbWENCnN1bW1hcmlzZV9zdGF0cyA8LSBmdW5jdGlvbihkZl9zdWIpew0KICBudW1fdmFycyA8LSBkZl9zdWIgJT4lIGRwbHlyOjpzZWxlY3Qod2hlcmUoaXMubnVtZXJpYykpDQogIGRwbHlyOjpzdW1tYXJpc2UoDQogICAgbnVtX3ZhcnMsDQogICAgZHBseXI6OmFjcm9zcygNCiAgICAgIC5jb2xzID0gZXZlcnl0aGluZygpLA0KICAgICAgLmZucyAgPSBsaXN0KA0KICAgICAgICBNZWFuID0gfm1lYW4oLiwgbmEucm0gPSBUUlVFKSwNCiAgICAgICAgU0QgICA9IH5zZCguLCBuYS5ybSA9IFRSVUUpLA0KICAgICAgICBNaW4gID0gfm1pbiguLCBuYS5ybSA9IFRSVUUpLA0KICAgICAgICBNYXggID0gfm1heCguLCBuYS5ybSA9IFRSVUUpDQogICAgICApLA0KICAgICAgLm5hbWVzID0gInsuY29sfV9fey5mbn0iDQogICAgKQ0KICApICU+JQ0KICAgIHRpZHlyOjpwaXZvdF9sb25nZXIoZXZlcnl0aGluZygpLA0KICAgICAgbmFtZXNfdG8gPSBjKCJ2YXJpYWJsZSIsInN0YXQiKSwNCiAgICAgIG5hbWVzX3NlcCA9ICJfXyIsDQogICAgICB2YWx1ZXNfdG8gPSAidmFsdWUiDQogICAgKSAlPiUNCiAgICB0aWR5cjo6cGl2b3Rfd2lkZXIobmFtZXNfZnJvbSA9IHN0YXQsIHZhbHVlc19mcm9tID0gdmFsdWUpICU+JQ0KICAgIGRwbHlyOjphcnJhbmdlKHZhcmlhYmxlKQ0KfQ0KDQpgYGANCg0KYGBge3J9DQojIFRhYmVsYSBkZSBjb2JlcnR1cmEgdGVtcG9yYWwgcG9yIHN1YnNpc3RlbWENCmNvdmVyYWdlX3RibCA8LSByZXNlcnYgJT4lDQogIGRwbHlyOjpncm91cF9ieShub21fc3Vic2lzdGVtYS54KSAlPiUNCiAgZHBseXI6OnN1bW1hcmlzZSgNCiAgICBvYnNlcnZhdGlvbnMgPSBkcGx5cjo6bl9kaXN0aW5jdChpZF9yZXNlcnZhdG9yaW8ueCksDQogICAgc3RhcnRfZGF0ZSAgPSBtaW4oZGF0ZSwgbmEucm0gPSBUUlVFKSwNCiAgICBlbmRfZGF0ZSAgICA9IG1heChkYXRlLCBuYS5ybSA9IFRSVUUpLA0KICAgIC5ncm91cHMgPSAiZHJvcCINCiAgKQ0KDQp0YWJfY292IDwtIGd0X2FydGljbGUoDQogIGNvdmVyYWdlX3RibCwNCiAgdGl0bGUgPSAiKipUYWJsZSBBLiBUZW1wb3JhbCBjb3ZlcmFnZSBieSBzdWJzeXN0ZW0qKiIsDQogIHN1YnRpdGxlID0gIk9ic2VydmF0aW9uIGNvdW50cyBhbmQgZGF0ZSByYW5nZSIsDQogIG5vdGUgPSAiRGF0ZXMgaW4gWVlZWS1NTS1ERC4iDQopICU+JQ0KICBndDo6Y29sc19sYWJlbCgNCiAgICBub21fc3Vic2lzdGVtYS54ICAgPSAiU3Vic3lzdGVtIiwNCiAgICBvYnNlcnZhdGlvbnM9ICJOIG9mIFJlc2Vydm9pcnMiLA0KICAgIHN0YXJ0X2RhdGUgID0gIlN0YXJ0IiwNCiAgICBlbmRfZGF0ZSAgICA9ICJFbmQiDQogICkNCg0KZXhwb3J0X3RhYmxlKHRhYl9jb3YsICJUYWJBX0NvdmVyYWdlX2J5U3Vic3lzdGVtIikNCnRhYl9jb3YNCmBgYA0KDQpgYGB7cn0NCg0KIyBUYWJlbGEgZGUgY29iZXJ0dXJhIHRlbXBvcmFsIHBvciBzdWJzaXN0ZW1hDQojY292ZXJhZ2VfdGJsIDwtIA0KcmVzZXJ2ICU+JQ0KICBkcGx5cjo6Z3JvdXBfYnkobm9tX3N1YnNpc3RlbWEueCkgJT4lDQogIGRwbHlyOjpzdW1tYXJpc2UoDQogICAgTWVhbl9nZXJhY2FvPW1lYW4odmFsX2dlcmFjYW8sIG5hLnJtID0gVFJVRSksDQogICAgU0RfZ2VyYWNhbz1tZWFuKHZhbF9nZXJhY2FvLCBuYS5ybSA9IFRSVUUpLA0KICAgIE1pbl9nZXJhY2FvICA9IG1pbih2YWxfZ2VyYWNhbywgbmEucm0gPSBUUlVFKSwNCiAgICBNYXhfZ2VyYWNhbyAgICA9IG1heCh2YWxfZ2VyYWNhbywgbmEucm0gPSBUUlVFKSwNCiAgICANCiAgICBNZWFuX0VBUj1tZWFuKGVhcl9yZXNlcnZhdG9yaW9fc3Vic2lzdGVtYV9wcm9wcmlvX213bWVzLCBuYS5ybSA9IFRSVUUpLA0KICAgIFNEX0VBUj1tZWFuKGVhcl9yZXNlcnZhdG9yaW9fc3Vic2lzdGVtYV9wcm9wcmlvX213bWVzLCBuYS5ybSA9IFRSVUUpLA0KICAgIE1pbl9FQVIgID0gbWluKGVhcl9yZXNlcnZhdG9yaW9fc3Vic2lzdGVtYV9wcm9wcmlvX213bWVzLCBuYS5ybSA9IFRSVUUpLA0KICAgIE1heF9FQVIgICAgPSBtYXgoZWFyX3Jlc2VydmF0b3Jpb19zdWJzaXN0ZW1hX3Byb3ByaW9fbXdtZXMsIG5hLnJtID0gVFJVRSksDQogICAgDQogICAgTWVhbl9wcmVjaXBtbTMwPW1lYW4ocHJlY2lwX21tMzAsIG5hLnJtID0gVFJVRSksDQogICAgU0RfcHJlY2lwbW0zMD1tZWFuKHByZWNpcF9tbTMwLCBuYS5ybSA9IFRSVUUpLA0KICAgIE1pbl9wcmVjaXBtbTMwICA9IG1pbihwcmVjaXBfbW0zMCwgbmEucm0gPSBUUlVFKSwNCiAgICBNYXhfcHJlY2lwbW0zMCAgICA9IG1heChwcmVjaXBfbW0zMCwgbmEucm0gPSBUUlVFKSwNCiAgICANCiAgICBNZWFuX3RlbXBtbTc9bWVhbih0ZW1wX21tNywgbmEucm0gPSBUUlVFKSwNCiAgICBTRF90ZW1wbW03PW1lYW4odGVtcF9tbTcsIG5hLnJtID0gVFJVRSksDQogICAgTWluX3RlbXBtbTcgID0gbWluKHRlbXBfbW03LCBuYS5ybSA9IFRSVUUpLA0KICAgIE1heF90ZW1wbW03ICAgID0gbWF4KHRlbXBfbW03LCBuYS5ybSA9IFRSVUUpLA0KICAgIA0KICAgIE1lYW5faHVtaWRpdHk9bWVhbihodW1pZGl0eSwgbmEucm0gPSBUUlVFKSwNCiAgICBTRF9odW1pZGl0eT1tZWFuKGh1bWlkaXR5LCBuYS5ybSA9IFRSVUUpLA0KICAgIE1pbl9odW1pZGl0eSAgPSBtaW4oaHVtaWRpdHksIG5hLnJtID0gVFJVRSksDQogICAgTWF4X2h1bWlkaXR5ICAgID0gbWF4KGh1bWlkaXR5LCBuYS5ybSA9IFRSVUUpLA0KICAgIA0KICAgIE1lYW5fd2luZD1tZWFuKHdpbmRfc3BlZWQsIG5hLnJtID0gVFJVRSksDQogICAgU0Rfd2luZD1tZWFuKHdpbmRfc3BlZWQsIG5hLnJtID0gVFJVRSksDQogICAgTWluX3dpbmQgID0gbWluKHdpbmRfc3BlZWQsIG5hLnJtID0gVFJVRSksDQogICAgTWF4X3dpbmQgICAgPSBtYXgod2luZF9zcGVlZCwgbmEucm0gPSBUUlVFKSwNCiAgICANCiAgICAuZ3JvdXBzID0gImRyb3AiKSAlPiUNCiAgICB0aWR5cjo6cGl2b3RfbG9uZ2VyKGMoZW5kc193aXRoKCJnZXJhY2FvIiksZW5kc193aXRoKCJpbmQiKSxlbmRzX3dpdGgoIkVBUiIpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICBlbmRzX3dpdGgoIml0eSIpLGVuZHNfd2l0aCgibW03IiksZW5kc193aXRoKCJtbTMwIikpLA0KICAgICAgbmFtZXNfdG8gPSBjKCJ2YXJpYWJsZSIsInN0YXQiKSwNCiAgICAgIG5hbWVzX3NlcCA9ICJfIiwNCiAgICAgIHZhbHVlc190byA9ICJ2YWx1ZSINCiAgICApICU+JSBwaXZvdF93aWRlcihuYW1lc19mcm9tID0gdmFyaWFibGUsdmFsdWVzX2Zyb20gPXZhbHVlKSAlPiUgDQogIGFycmFuZ2Uoc3RhdCkgJT4lICMgLT4gdGFiX2Rlc2MNCiAgZ3RfYXJ0aWNsZSgNCiAgDQogIHRpdGxlID0gIioqVGFibGUgQi4gIERlc2NyaXB0aXZlIFN1bW1hcmllcyIsDQogIHN1YnRpdGxlID0gIk9ic2VydmF0aW9uIGNvdW50cyBhbmQgZGF0ZSByYW5nZSIsDQogIG5vdGUgPSAiRGF0ZXMgaW4gWVlZWS1NTS1ERC4iDQopICU+JQ0KICBndDo6Y29sc19sYWJlbCgNCiAgICBub21fc3Vic2lzdGVtYS54ICAgPSAiU3Vic3lzdGVtIiwNCiAgICBzdGF0PSAiVmFyaWFibGUiLA0KICAgIE1lYW4gID0gIk1lYW4iLA0KICAgIFNEICAgID0gIlNEIixNaW49ICJNaW4iLCJNYXgiPSAiTWF4Ig0KICApDQoNCiNleHBvcnRfdGFibGUodGFiX2NvdiwgIlRhYkFfQ292ZXJhZ2VfYnlTdWJzeXN0ZW0iKQ0KI3RhYl9jb3YNCg0KYGBgDQoNCmBgYHtyfQ0KDQoNCg0KcmVzZXJ2ICU+JSBzZWxlY3Qoc3RhcnRzX3dpdGgoImVuYSIpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RhcnRzX3dpdGgoImVhciIpLHN0YXJ0c193aXRoKCJ0ZW0iKSxzdGFydHNfd2l0aCgicHJlIiksc3RhcnRzX3dpdGgoImdlciIpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFsX2dlcmFjYW8sdmFsX2dlcmFjYW9fZGF5X3N1YnNpc3RlbWEsaHVtaWRpdHksd2luZF9zcGVlZCkgJT4lIHN0YXJnYXplcjo6c3RhcmdhemVyKHR5cGU9InRleHQiKQ0KcGxkICU+JSBzdGFyZ2F6ZXI6OnN0YXJnYXplcih0eXBlPSJ0ZXh0IikNCmdlciAlPiUgc2VsZWN0KHZhbF9nZXJhY2FvLG5vbV90aXBvY29tYnVzdGl2ZWwsbm9tX3RpcG91c2luYT1hcy5mYWN0b3Iobm9tX3RpcG91c2luYSkpICU+JSBzdW1tYXJ5DQoNCmBgYA0KDQojIyMgW0dyw6FmaWNvcyByw6FwaWRvczogc8OpcmllcyBFTkEsIHByZWNpcGl0YcOnw6NvLCB0ZW1wZXJhdHVyYSwgRUFSLCBnZXJhw6fDo29dDQoNCmBgYHtyIGZpZy5oZWlnaHQ9OCwgZmlnLndpZHRoPTEyfQ0KIyAtLS0gR3LDoWZpY29zIHLDoXBpZG9zIChFREEpIC0tLQ0KbGlicmFyeShnZ3Bsb3QyKQ0KDQojIFPDqXJpZSBFTkEvUmVzZXJ2YXTDs3Jpb3MNCnBsb3RfZW5hPC1yZXNlcnYgJT4lIGdyb3VwX2J5KGRhdGUpICU+JSBzdW1tYXJpc2UoZWFyX213Nz1tZWFuKGVhcl9yZXNlcnZhdG9yaW9fc3Vic2lzdGVtYV9wcm9wcmlvX213bWVzLG5hLnJtID0gVCkpICU+JSANCiAgZ2dwbG90KGFlcyh4PWRhdGUsIHk9ZWFyX213NykpICsNCiAgZ2VvbV9saW5lKGNvbG9yPSJzdGVlbGJsdWUiKSArZ2VvbV9zbW9vdGgoKSsNCiAgbGFicyh0aXRsZT0iRW5lcmdpYSBBcm1hemVuYWRhIChFQVIpIGJydXRhIChNV21lZCkiLCB4PSIiLCB5PSJNV21lZCIpDQoNCiMgU8OpcmllIEVBUg0KcGxvdF9lYXI8LXJlc2VydiAlPiUgZ3JvdXBfYnkoZGF0ZSkgJT4lIHN1bW1hcmlzZShlbmFfbXc3PW1lYW4oZW5hX213NyxuYS5ybSA9IFQpKSAlPiUgDQogICAgZ2dwbG90KGFlcyh4PWRhdGUsIHk9ZW5hX213NykpICsNCiAgZ2VvbV9saW5lKGNvbG9yPSJkYXJrZ3JlZW4iKSArZ2VvbV9zbW9vdGgoKSsNCiAgbGFicyh0aXRsZT0iRW5lcmdpYSBOYXR1cmFsIEFmbHVlbnRlIChFTkEpIHRvdGFsIChNV23DqnMpIiwgeD0iIiwgeT0iTVdtw6pzIikNCg0KIyBTw6lyaWUgZGUgZ2VyYcOnw6NvDQpwbG90X2dlcjwtcmVzZXJ2ICU+JSBncm91cF9ieShkYXRlKSAlPiUgc3VtbWFyaXNlKGdlcl9tdzc9bWVhbihnZXJfbXc3LG5hLnJtID0gVCkpICU+JSANCiAgICAgIGdncGxvdChhZXMoeD1kYXRlLCB5PWdlcl9tdzcpKSArDQogIGdlb21fbGluZShjb2xvcj0iZ3JleTMwIikgK2dlb21fc21vb3RoKCkrDQogIGxhYnModGl0bGU9IkdlcmHDp8OjbyBoaWRyZWzDqXRyaWNhIChNV2gvZGlhKSIsIHg9IiIsIHk9Ik1XaCIpDQoNCiMgLS0tIENvcnJlbGHDp8O1ZXMgcsOhcGlkYXMgLS0tDQojIFtDaGVjYXIgY29ycmVsYcOnw6NvIGLDoXNpY2EgZW50cmUgY2xpbWEgKHByZWNpcCwgdGVtcCkgZSBFTkFdDQpjbGltYV92YXJzIDwtIHJlc2VydiAlPiUgDQogIGRwbHlyOjpzZWxlY3QoDQogICAgICAgICAgICAgICAgZ2VyX213X3N1YnNpc3RlbWE9dmFsX2dlcmFjYW9fZGF5X3N1YnNpc3RlbWEsDQogICAgICAgICAgICAgICAgZ2VyX213PXZhbF9nZXJhY2FvLGdlcl9tdzcsZ2VyX213MTQsZ2VyX213MzAsDQogICAgICAgICAgICAgICAgZW5hX213PWVuYV9icnV0YV9yZXNfbXdtZWQsIGVuYV9tdzcsDQogICAgICAgICAgICAgICAgZWFyX213PWVhcl90b3RhbF9td21lcywgICNlYXJfbXcxNCwgZWFyX213MzAsDQogICAgICAgICAgICAgICAgcHJlY2lwdGF0aW9uLHByZWNpcF9tbTE0LHByZWNpcF9tbTMwLA0KICAgICAgICAgICAgICAgIHRlbXBlcmF0dXJlLHRlbXBfbW03LHRlbXBfbW0xNCx0ZW1wX21tMzAsDQogICAgICAgICAgICAgICAgd2luZF9zcGVlZCwgDQogICAgICAgICAgICAgICAgKQ0KYGBgDQoNCmBgYHtyIGZpZy5oZWlnaHQ9OCwgZmlnLndpZHRoPTEyfQ0KcGxvdF9nZXJ8cGxvdF9lYXIgLyBwbG90X2VuYQ0KDQpjb3JycGxvdDo6Y29ycnBsb3QoY29yKGNsaW1hX3ZhcnMsIHVzZSA9ICJwYWlyd2lzZS5jb21wbGV0ZS5vYnMiKSxtZXRob2QgPSAiY29sb3IiLCB0eXBlID0gInVwcGVyIiwNCiAgICAgICAgIGFkZENvZWYuY29sID0gImJsYWNrIiwgIyBtb3N0cmFyIGNvZWZpY2llbnRlcw0KICAgICAgICAgdGwuY29sID0gImJsYWNrIiwgdGwuc3J0ID0gMzUsbnVtYmVyLmNleAkJID0uOCwNCiAgICAgICAgIGNvbD1jb2xvclJhbXBQYWxldHRlKGMoInJlZCIsIndoaXRlIiwiYmx1ZSIpKSgyMDApKQ0KYGBgDQoNCmBgYHtyfQ0KbGlicmFyeShwYXRjaHdvcmspDQpsaWJyYXJ5KGdncmVwZWwpDQpnZW9icjo6cmVhZF9yZWdpb24oKS0+Z2VvcmVnaW9uDQoNCnJlc2VydiAlPiUgZmlsdGVyKCJSZXNlcnZhdMOzcmlvIGNvbSBVc2luYSI9PXRpcF9yZXNlcnZhdG9yaW8pICU+JQ0KICBncm91cF9ieShub21fcmVzZXJ2YXRvcmlvLnksdmFsX2xhdGl0dWRlLHZhbF9sb25naXR1ZGUsbm9tX3N1YnNpc3RlbWEueCkgJT4lIA0KICBzdW1tYXJpc2UoZWFyX3Jlc2VydmF0b3Jpbz1zdW0oZWFyX3Jlc2VydmF0b3Jpb19zdWJzaXN0ZW1hX3Byb3ByaW9fbXdtZXMgJT4lIGFzLm51bWVyaWMoKSxuYS5ybSA9IFQpLA0KICAgICAgICAgICAgKSAtPmENCmEgJT4lICAgZ2dwbG90KGFlcyh2YWxfbG9uZ2l0dWRlLHZhbF9sYXRpdHVkZSkpK2dlb21fcG9pbnQoKSsNCmdncGxvdChkYXRhPWdlb3JlZ2lvbikgK2dlb21fc2YoKQ0KYSRub21fc3Vic2lzdGVtYS54ICU+JSB1bmlxdWUNCmEgJT4lDQogIG11dGF0ZShub21fc3Vic2lzdGVtYS54PWNhc2Vfd2hlbihub21fc3Vic2lzdGVtYS54PT0iU1VMIn4iU291dGgiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbm9tX3N1YnNpc3RlbWEueD09IlNVREVTVEUifiJTb3V0aGVhc3QiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbm9tX3N1YnNpc3RlbWEueD09Ik5PUkRFU1RFIn4iTm9ydGhlYXN0IiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5vbV9zdWJzaXN0ZW1hLng9PSJOT1JURSJ+Ik5vcnRoIixUUlVFfiIiKSkgJT4lIA0KICBnZ3Bsb3QoKSArDQogIGdlb21fc2YoZGF0YSA9IGdlb3JlZ2lvbiwgY29sb3IgPSAid2hpdGUiLGZpbGw9ImxpZ2h0Z3JleSIsIHNpemUgPSAyKSsjZ2VvbV9saW5lKCkrDQogIGdlb21fcG9pbnQoYWVzKHZhbF9sb25naXR1ZGUsdmFsX2xhdGl0dWRlLGNvbD1ub21fc3Vic2lzdGVtYS54KSkgK3RoZW1lX3ZvaWQoKSsgI3NjYWxlX2NvbG9yX2Rpc2NyZXRlKHZhbHVlPSkNCiAgZ2VvbV90ZXh0X3JlcGVsKGFlcyh2YWxfbG9uZ2l0dWRlLHZhbF9sYXRpdHVkZSxjb2w9bm9tX3N1YnNpc3RlbWEueCxsYWJlbD1ub21fcmVzZXJ2YXRvcmlvLnkpLHNpemUgPSAyLG1heC5vdmVybGFwcz1ucm93KGEpLGZvcmNlX3B1bGwgID0yKSsNCiAgI3RoZW1lKGxlZ2VuZC5wb3NpdGlvbj1jKC44LCAuOTUpLCxsZWdlbmQuYm94Lmp1c3QgPSAicmlnaHQiKSsNCiAgbGFicyhjb2w9IkVsZXRyaWNhbCBTdWJzeXN0ZW1zIiktPm1hcA0KbWFwDQpgYGANCmBgYHtyfQ0KcmVzZXJ2IDwtIHJlc2VydiAlPiUNCiAgbXV0YXRlKA0KICAgIGRveSAgID0geWRheShkYXRlKSwNCiAgICBtb250aCA9IG1vbnRoKGRhdGUpLA0KICAgICMgdHJhbnNmb3JtYcOnw6NvIGxvZyBwYXJhIGludGVycHJldGHDp8OjbyBwZXJjZW50dWFsIChldml0YSBwcm9ibGVtYXMgY29tIHplcm8pDQogICAgbF9wcmVjaXAgPSBsb2cxcChwcmVjaXBfbW0zMCksDQogICAgbF90ZW1wICAgPSBsb2cxcCh0ZW1wX21tNyksICAgICAjIG9wY2lvbmFsOiBzZSBwcmVmZXJpciBtYW50ZXIgdGVtcCBubyBuw612ZWwsIHVzZSB0ZW1wX21tNyBlbSB2ZXogZGUgbF90ZW1wDQogICAgbF9odW1pZGl0eSA9bG9nMXAoaHVtaWRpdHkpLA0KICAgIGxfd2luZF9zcGVlZD1sb2cod2luZF9zcGVlZCkNCiAgKQ0KYGBgDQoNCiMgMy4xIE1vZGVsbyAxIOKAlCBHQU0g4oCcY2xpbWHigJFhcGVuYXPigJ0gKGJhc2VsaW5lKQ0KDQpNb2RlbG8gaGlkcm9sw7NnaWNvIHBhcnNpbW9uaW9zbyBubyBxdWFsIGEgRW5lcmdpYSBBcm1hemVuYWRhIChFQVIpIMOpIGV4cGxpY2FkYSBhcGVuYXMgcG9yIGNsaW1hIGUgY29udHJvbGVzIHNhem9uYWlzL3JlZ2lvbmFpcywgdXNhbmRvIGZ1bsOnw7VlcyBzdWF2ZXMgKHNwbGluZXMpIGVtIHVtIEdBTS4gTyBvYmpldGl2byDDqSBpc29sYXIgbyBzaW5hbCBwdXJhbWVudGUgY2xpbcOhdGljbyBzb2JyZSBvIGVzdG9xdWUgaMOtZHJpY28gZSBjb25zdHJ1aXIgdW0gY29udHJhZmFjdHVhbCBhdWRpdMOhdmVsLiBNYW50ZW1vcyBhIHJlc3Bvc3RhIG5vIG7DrXZlbCAoTVfCt23DqnMpIHBvciBjb2Vyw6puY2lhIGNvbSBhIGRlZmluacOnw6NvIGRlIHBlbmFsaWRhZGUgZSBtb25ldGl6YcOnw6NvLCBlIHRyYW5zZm9ybWFtb3MgcHJlZGl0b3JlcyBjbGltw6F0aWNvcyBxdWFuZG8gw7p0aWwgcGFyYSBpbnRlcnByZXRhw6fDo28gKHNlbWktZWxhc3RpY2lkYWRlcykuDQpgYGB7cn0NCiMgR0FNIChHYXVzc2lhbiwgZlJFTUwpLiBTcGxpbmVzIGNsaW3DoXRpY2FzICsgc2F6b25hbGlkYWRlIGPDrWNsaWNhICsgZWZlaXRvIGFsZWF0w7NyaW8gcG9yIHJlc2VydmF0w7NyaW8gKyBmaXhlZCBwb3Igc3Vic2lzdGVtYQ0KbTFfZ2FtIDwtIGJhbSgNCiAgZWFyX3Jlc2VydmF0b3Jpb19zdWJzaXN0ZW1hX3Byb3ByaW9fbXdtZXMgfg0KICAgIHMobF9wcmVjaXAsIGsgPSA2KSArDQogICAgcyhsX3RlbXAsICAgayA9IDYpICsNCiAgICBzKGxfaHVtaWRpdHksIGsgPSA2KSArDQogICAgcyhsX3dpbmRfc3BlZWQsIGsgPSA2KSArDQogICAgcyhkb3ksIGJzID0gImNjIiwgayA9IDEyKSArICAgICAgICAgICAgIyBzYXpvbmFsaWRhZGUgY8OtY2xpY2Egbm8gYW5vDQogICAgcyhpZF9yZXNlcnZhdG9yaW8ueCwgYnMgPSAicmUiKSArICAgICAgIyBlZmVpdG8gYWxlYXTDs3JpbyBwb3IgcmVzZXJ2YXTDs3Jpbw0KICAgIG5vbV9zdWJzaXN0ZW1hLngsICAgICAgICAgICAgICAgICAgICAgICAjIGVmZWl0byBmaXhvIHBvciBzdWJzaXN0ZW1hDQogIGRhdGEgICAgID0gcmVzZXJ2LA0KICBtZXRob2QgICA9ICJmUkVNTCIsDQogIGRpc2NyZXRlID0gVFJVRSwNCiAgZmFtaWx5ICAgPSBnYXVzc2lhbigpLA0KICBuYS5hY3Rpb249IG5hLmV4Y2x1ZGUsDQogIGtub3RzICAgID0gbGlzdChkb3kgPSBjKDAuNSwgMzY2LjUpKSwNCiAgc2VsZWN0ICAgPSBUUlVFICAgICAgICAgICAgICAgICAgICAgICAgICAgIyBzaHJpbmthZ2UgcGFyYSBldml0YXIgd2lnZ2xlcw0KKQ0KDQoNCmBgYA0KDQpgYGB7cn0NCnN1bW1hcnkobTFfZ2FtKQ0KZ3RzdW1tYXJ5Ojp0YmxfcmVncmVzc2lvbihtMV9nYW0pDQpzdW1tYXJ5KG0xX2dhbSkNCmdhbS5jaGVjayhtMV9nYW0pICAgICAgICAgICMgcmVzw61kdW9zLCBRUSwgay1pbmRleA0KY29uY3Vydml0eShtMV9nYW0sIGZ1bGw9VFJVRSkNCmBgYA0KDQojIyMgUmVzcG9zdGFzIG1hcmdpbmFpcyAocGxhdXNpYmlsaWRhZGUgZSBpbnRlcnByZXRhw6fDo28pDQpQYXJhIGludGVycHJldGFyIG8gY29tcG9ydGFtZW50byBmdW5jaW9uYWwgZSBhdmFsaWFyIHBsYXVzaWJpbGlkYWRlLCB1c2Ftb3MgZGVyaXZhZGFzIHBhcmNpYWlzLiBDb21vIGBsX3ByZWNpcCA9IGxvZyhwcmVjaXArMSlgLCBhIGRlcml2YWRhIGRlIFwoRVwpIGVtIHJlbGHDp8OjbyBhIGBsX3ByZWNpcGAgw6kgdW1hICoqc2VtaS1lbGFzdGljaWRhZGUgbm8gbsOtdmVsKio6IG8gZWZlaXRvIGRlICsxJSBlbSBwcmVjaXBpdGHDp8OjbyDDqSBhcHJveGltYWRhbWVudGUgXCgweyx9MDEgXHRpbWVzIFxwYXJ0aWFsIEUgLyBccGFydGlhbCBcbG4oXHRleHR7cHJlY2lwfSsxKVwpLg0KDQpgYGB7ciBtMS1kZXJpdmF0aXZlcywgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0NCg0KcGxvdChtMV9nYW0sIHBhZ2VzPTQsIHNjaGVtZT0xLCBzaGFkZT1UUlVFLCBzZT1UUlVFKQ0KDQoNCmBgYA0KYGBge3J9DQpkX3ByZWNpcCA8LSBkZXJpdmF0aXZlcyhtMV9nYW0sIHRlcm0gPSAicyhsX3ByZWNpcCkiLCB0eXBlID0gImNlbnRyYWwiKQ0KZF9wcmVjaXAgPC0gZF9wcmVjaXAgJT4lDQogIG11dGF0ZShlZmZlY3RfcGVyXzFwY3QgPSAwLjAxICogLmRlcml2YXRpdmUpIA0KICAjc2VsZWN0KGRhdGEsIC5maXR0ZWQsIC5zZSwgZWZmZWN0X3Blcl8xcGN0LCBsb3dlciwgdXBwZXIpDQoNCnN1bW1hcnkoZF9wcmVjaXAkZWZmZWN0X3Blcl8xcGN0KQ0KYGBgDQpDb20gYmFzZSBub3MgZ3LDoWZpY29zIGRlIGVmZWl0b3MgcGFyY2lhaXMsIGRpYWduw7NzdGljb3MgZGUgcmVzw61kdW9zIGUgc3Vtw6FyaW8gZXN0YXTDrXN0aWNvIGRvIEdBTSAoZlJFTUwsIFLCsmFqPTAuNzQ7IGRldmlhbmNlIGV4cGxhaW5lZD03NCUpLCDDqSBwb3Nzw612ZWwgc2ludGV0aXphciBhIHF1YWxpZGFkZSBkbyBtb2RlbG8gZW0gdHLDqnMgcGFyw6FncmFmb3MgdMOpY25pY29zIGUgaW50ZXJwcmV0YXRpdm9zIOKAlCBhZGVxdWFkb3MgcGFyYSBhIHNlw6fDo28gZGUgcmVzdWx0YWRvcyBtZXRvZG9sw7NnaWNvczoNCk8gbW9kZWxvIGhpZHJvbMOzZ2ljbyDigJxjbGltYS0gZWFy4oCdIGFwcmVzZW50YSBkZXNlbXBlbmhvIHJvYnVzdG8gZSBjb2VyZW50ZSBjb20gYSBkaW7Dom1pY2EgZsOtc2ljYSBlc3BlcmFkYSBkbyBzaXN0ZW1hLiBPIGFqdXN0ZSBhbGNhbsOnYSBSwrIgYWp1c3RhZG8gZGUgMCw3NCBlIGV4cGxpY2EgNzQlIGRhIGRldmlhbmNlIHRvdGFsLCBpbmRpY2FuZG8gcXVlIGFzIHZhcmnDoXZlaXMgY2xpbcOhdGljYXMg4oCUIHByZWNpcGl0YcOnw6NvLCB0ZW1wZXJhdHVyYSwgdW1pZGFkZSBlIHZlbnRvIOKAlCBjb21iaW5hZGFzIMOgIHNhem9uYWxpZGFkZSBlIGFvcyBlZmVpdG9zIHJlZ2lvbmFpcywgY2FwdHVyYW0gYSBtYWlvciBwYXJ0ZSBkYSB2YXJpYWJpbGlkYWRlIGRhIGVuZXJnaWEgYXJtYXplbmFkYSAoRUFSKS4gQSBzaWduaWZpY8OibmNpYSBlc3RhdMOtc3RpY2EgZG9zIHNwbGluZXMgw6kgZWxldmFkYSAocCA8IDAuMDAxIHBhcmEgdG9kb3Mgb3MgdGVybW9zKSwgZSBhIHN1YXZpZGFkZSBkb3MgZWZlaXRvcyBtb3N0cmEgcGFkcsO1ZXMgcmVhbGlzdGFzOiBwcmVjaXBpdGHDp8OjbyBleGVyY2UgZWZlaXRvIHBvc2l0aXZvIG1vbm90w7RuaWNvIHNvYnJlIGEgRUFSOyB0ZW1wZXJhdHVyYSBleGliZSBmb3JtYXRvIGVtIGFyY28gKGVmZWl0byDDs3RpbW8gcHLDs3hpbW8gYSAyMCDCsEMsIHNlZ3VpZG8gZGUgcXVlZGEgbm9zIGV4dHJlbW9zKTsgdW1pZGFkZSBlIHZlbnRvIHTDqm0gZWZlaXRvcyBtb2RlcmFkb3MsIG1hcyBjb25zaXN0ZW50ZXMgY29tIG1lY2FuaXNtb3MgZGUgZXZhcG90cmFuc3BpcmHDp8OjbyBlIHJlY2FyZ2EuIE8gdGVybW8gc2F6b25hbCAoZG95KSByZXZlbGEgbyBjaWNsbyBoaWRyb2zDs2dpY28gYW51YWwgY2FyYWN0ZXLDrXN0aWNvIGRvcyBzdWJzaXN0ZW1hcyBicmFzaWxlaXJvcy4NCg0KT3MgZGlhZ27Ds3N0aWNvcyBkZSByZXPDrWR1b3MgY29uZmlybWFtIHF1ZSBvIG1vZGVsbyBjYXB0dXJhIGFkZXF1YWRhbWVudGUgYSB0ZW5kw6puY2lhIG3DqWRpYSBlIGEgc2F6b25hbGlkYWRlLCBtYXMgZXZpZGVuY2lhIGhldGVyb2dlbmVpZGFkZSBlc3RydXR1cmFsIGVudHJlIHJlZ2ltZXMgb3BlcmFjaW9uYWlzLiBPIGdyw6FmaWNvIGRlIHJlc8OtZHVvcyB2ZXJzdXMgdmFsb3JlcyBhanVzdGFkb3MgbW9zdHJhIHRyw6pzIGZhaXhhcyBkZW5zYXMsIGFzc29jaWFkYXMgYSBkaWZlcmVudGVzIG7DrXZlaXMgZGUgYXJtYXplbmFtZW50byAoYmFpeG8sIG3DqWRpbyBlIGFsdG8pLCBzdWdlcmluZG8gYSBwcmVzZW7Dp2EgZGUgbGltaXRlcyBmw61zaWNvcyBkZSBvcGVyYcOnw6NvIG91IHRyYW5zacOnw7VlcyBlbnRyZSBlc3TDoWdpb3MgZGUgZW5jaGltZW50byBlIGVzdmF6aWFtZW50byBkb3MgcmVzZXJ2YXTDs3Jpb3MuIE8gaGlzdG9ncmFtYSBkZSByZXPDrWR1b3Mgw6kgYXByb3hpbWFkYW1lbnRlIHNpbcOpdHJpY28gZSBjZW50cmFkbyBlbSB6ZXJvLCBlIG8gUVEtcGxvdCBpbmRpY2EgbGV2ZSBkZXN2aW8gbmFzIGNhdWRhcywgbyBxdWUgw6kgZXNwZXJhZG8gZW0gc8OpcmllcyBhbWJpZW50YWlzIGRlIGdyYW5kZSBhbXBsaXR1ZGUuIEEgaG9tb2dlbmVpZGFkZSBkZSB2YXJpw6JuY2lhIMOpIHNhdGlzZmF0w7NyaWEsIHNlbSBwYWRyw7VlcyBzaXN0ZW3DoXRpY29zIGRlIGF1dG9jb3JyZWxhw6fDo28sIHJlZm9yw6dhbmRvIGEgYWRlcXVhw6fDo28gZG8gdXNvIGRhIGZhbcOtbGlhIGdhdXNzaWFuYSBjb20gbGluayBpZGVudGlkYWRlLg0KDQpQb3IgZmltLCBvcyBlZmVpdG9zIGFsZWF0w7NyaW9zIHBvciByZXNlcnZhdMOzcmlvIG1vc3RyYXJhbSBhbXBsYSBkaXNwZXJzw6NvLCByZWZsZXRpbmRvIGRpZmVyZW7Dp2FzIGVzdHJ1dHVyYWlzIGRlIGNhcGFjaWRhZGUgZSBvcGVyYcOnw6NvIGVudHJlIHVzaW5hcy4gQSBzdWF2aWRhZGUgZG9zIHNwbGluZXMgZm9pIGFkZXF1YWRhIChrLWluZGV4ID4gMC42IHBhcmEgdG9kb3Mgb3MgdGVybW9zKSwgc2VtIGV2aWTDqm5jaWFzIGRlIHN1YmRpbWVuc2lvbmFtZW50byBkZSBjb21wbGV4aWRhZGUsIGUgYSBhdXPDqm5jaWEgZGUgY29uY29ycsOqbmNpYSAoY29uY3Vydml0eSkgcmVsZXZhbnRlIGluZGljYSBiYWl4YSBjb2xpbmVhcmlkYWRlIGVudHJlIG9zIGVmZWl0b3MgY2xpbcOhdGljb3MuIEVtIGNvbmp1bnRvLCBlc3NlcyByZXN1bHRhZG9zIHN1c3RlbnRhbSBhIHBsYXVzaWJpbGlkYWRlIGVzdGF0w61zdGljYSBlIGbDrXNpY2EgZG8gbW9kZWxvIGNvbW8gYmFzZWxpbmUgY2xpbcOhdGljbyBhdWRpdMOhdmVsLiBBcyBwcmluY2lwYWlzIGxpbWl0YcOnw7VlcyByZXNpZGVtIG5hIHN1YXZpemHDp8OjbyBkZSBleHRyZW1vcyBoaWRyb2zDs2dpY29zIGUgbmEgbGV2ZSBuw6NvLW5vcm1hbGlkYWRlIGRvcyByZXPDrWR1b3MsIGFzcGVjdG9zIGNvbXVucyBlbSBtb2RlbG9zIGFncmVnYWRvcyBkZSBncmFuZGVzIHNpc3RlbWFzIGUgcXVlIHBvZGVtIHNlciB0cmF0YWRvcyBuYXMgZXRhcGFzIHN1YnNlcXVlbnRlcyBjb20gY29udHJhZmFjdHVhaXMgZSBwcm9wYWdhw6fDo28gZGUgaW5jZXJ0ZXphLg0KDQpPcyAqKmVmZWl0b3MgcGFyY2lhaXMqKiBlc3RpbWFkb3MgcGVsbyBtb2RlbG8gY29uZmlybWFtIHBhZHLDtWVzIGNsaW3DoXRpY29zIHBsYXVzw612ZWlzIGUgZmlzaWNhbWVudGUgY29lcmVudGVzLiBBIHByZWNpcGl0YcOnw6NvIGFwcmVzZW50YSB1bSBlZmVpdG8gbW9ub3RvbmljYW1lbnRlIGNyZXNjZW50ZSBzb2JyZSBhIGVuZXJnaWEgYXJtYXplbmFkYSwgaW5kaWNhbmRvIHF1ZSBhdW1lbnRvcyBhY3VtdWxhZG9zIGRlIGNodXZhIHTDqm0gaW1wYWN0byBwb3NpdGl2byBxdWFzZSBsaW5lYXIgYXTDqSBvIGxpbWl0ZSBzdXBlcmlvciBvYnNlcnZhZG8sIHNlbSBzaW5haXMgZGUgc2F0dXJhw6fDo28g4oCUIHVtIHJlc3VsdGFkbyBjb21wYXTDrXZlbCBjb20gYSBwcmVkb21pbsOibmNpYSBkZSBncmFuZGVzIHJlc2VydmF0w7NyaW9zIGRlIHJlZ3VsYXJpemHDp8OjbyBubyBzaXN0ZW1hLiBBIHRlbXBlcmF0dXJhLCBwb3Igc3VhIHZleiwgZXhpYmUgdW1hIHJlbGHDp8OjbyBlbSBmb3JtYSBkZSBhcmNvOiBvcyBuw612ZWlzIGludGVybWVkacOhcmlvcyAoZW0gdG9ybm8gZGUgMjAgwrBDKSBlc3TDo28gYXNzb2NpYWRvcyBhbyBtYWlvciBhcm1hemVuYW1lbnRvLCBlbnF1YW50byB0ZW1wZXJhdHVyYXMgZXh0cmVtYXMgcmVkdXplbSBvIHNhbGRvIGVuZXJnw6l0aWNvLCByZWZsZXRpbmRvIG8gcGFwZWwgZGEgZXZhcG9yYcOnw6NvIGUgZGEgZWZpY2nDqm5jaWEgZG8gY2ljbG8gaGlkcm9sw7NnaWNvLiBBIHVtaWRhZGUgbW9zdHJhIGxldmUgZWZlaXRvIHBvc2l0aXZvIGF0w6kgY2VydG8gcG9udG8sIHNlZ3VpZG8gZGUgcmV2ZXJzw6NvLCBzdWdlcmluZG8gaW50ZXJhw6fDo28gY29tIHJlZ2ltZXMgZGUgY2h1dmEgcGVyc2lzdGVudGUsIGVucXVhbnRvIGEgdmVsb2NpZGFkZSBkbyB2ZW50byBhcHJlc2VudGEgdW0gZWZlaXRvIG5lZ2F0aXZvIHN1YXZlLCBwb3NzaXZlbG1lbnRlIGxpZ2FkbyDDoCBtYWlvciBwZXJkYSBwb3IgZXZhcG90cmFuc3BpcmHDp8OjbyBlIGFvIHRyYW5zcG9ydGUgZGUgbWFzc2FzIHNlY2FzLiBPIGNvbXBvbmVudGUgc2F6b25hbCAoZG95KSByZXZlbGEgbyBjaWNsbyBhbnVhbCB0w61waWNvIGRvIHJlZ2ltZSBwbHV2aWFsIGJyYXNpbGVpcm8sIGNvbSBwaWNvcyBlbnRyZSBvcyBkaWFzIDEwMOKAkzE1MCAob3V0b25vKSBlIG3DrW5pbW9zIHByw7N4aW1vcyBhbyBmaW5hbCBkbyBhbm8uIFBvciBmaW0sIG9zIGVmZWl0b3MgYWxlYXTDs3Jpb3MgcG9yIHJlc2VydmF0w7NyaW8gbW9zdHJhbSBoZXRlcm9nZW5laWRhZGUgZXhwcmVzc2l2YSwgaW5kaWNhbmRvIHF1ZSBkaWZlcmVuw6dhcyBlc3RydXR1cmFpcyBkZSBjYXBhY2lkYWRlIGUgbG9jYWxpemHDp8OjbyBjb25kaWNpb25hbSBhIHJlc3Bvc3RhIGNsaW3DoXRpY2Eg4oCUIHVtIGFjaGFkbyBxdWUgcmVmb3LDp2EgYSBuZWNlc3NpZGFkZSBkZSBhYm9yZGFnZW5zIHJlZ2lvbmFsaXphZGFzIG5hcyBldGFwYXMgc2VndWludGVzIGRhIG1vZGVsYWdlbS4NCg0KDQoNCmBgYHtyfQ0KI3NhdmVSRFMobTFfZ2FtLCAibTFfZ2FtLnJkcyIpDQojcmVhZFJEUygibTFfZ2FtLnJkcyIpIC0+IG0xX2dhbQ0KDQpgYGANCg0KIyMjIyBQcmVkacOnw7VlcyBmYWN0dWFsIHZzLiBjb250cmFmYWN0dWFsIChiYXNlbGluZSAyMDAx4oCTMjAwNSkNCkNvbnN0cnXDrW1vcyBvIGNvbnRyYWZhY3R1YWwgY2xpbcOhdGljbyBmaXhhbmRvIGNsaW1hIG5vICoqbcOpZGlvIG1lbnNhbCAyMDAx4oCTMjAwNSoqIHBvciByZXNlcnZhdMOzcmlvIChvdSBwb3Igc3Vic2lzdGVtYSwgY2FzbyBwcmVmaXJhKSBlIG1hbnRlbmRvIG9zIGRlbWFpcyBjb250cm9sZXMgb2JzZXJ2YWRvcy4NCg0KDQoNCmBgYHtyfQ0KIyBCYXNlbGluZSBjbGltw6F0aWNvIHBvciByZXNlcnZhdMOzcmlvIGUgbcOqcyAoMjAwMeKAkzIwMDUpOyBhanVzdGUgc2UgcHJlZmVyaXIgcG9yIHN1YnNpc3RlbWENCmNsaW1fYmFzZWxpbmUgPC0gcmVzZXJ2ICU+JQ0KICBmaWx0ZXIoeWVhcihkYXRlKSA+PSAyMDAxLCB5ZWFyKGRhdGUpIDw9IDIwMDUpICU+JQ0KICBncm91cF9ieShpZF9yZXNlcnZhdG9yaW8ueCwgZG95KSAlPiUNCiAgc3VtbWFyaXNlKA0KICAgIGxfcHJlY2lwX2JsID0gbWVhbihsX3ByZWNpcCwgbmEucm0gPSBUUlVFKSwNCiAgICBsX3RlbXBfYmwgICA9IG1lYW4obF90ZW1wLCAgIG5hLnJtID0gVFJVRSksDQogICAgbF9odW1pZGl0eV9ibCA9IG1lYW4obF9odW1pZGl0eSwgbmEucm0gPSBUUlVFKSwNCiAgICBsX3dpbmRfc3BlZWRfYmwgICAgID0gbWVhbihsX3dpbmRfc3BlZWQsIG5hLnJtID0gVFJVRSksDQogICAgLmdyb3VwcyA9ICJkcm9wIg0KICApDQoNCiMgbmV3ZGF0YSBmYWN0dWFsIChvYnNlcnZhZG8pIGUgY29udHJhZmFjdHVhbCAoY2xpbWEgZml4byBubyBiYXNlbGluZSkNCm5kX29icyA8LSByZXNlcnYgIyU+JSB1bmdyb3VwKCkgJT4lIA0KICNzZWxlY3QoaWRfcmVzZXJ2YXRvcmlvLngsIG5vbV9zdWJzaXN0ZW1hLngsIGRhdGUsIGRveSwgbW9udGgsDQogICMgICAgICAgbF9wcmVjaXAsIGxfdGVtcCwgbF9odW1pZGl0eSwgbF93aW5kX3NwZWVkKQ0KDQpuZF9jZiA8LSByZXNlcnYgJT4lDQogIGxlZnRfam9pbihjbGltX2Jhc2VsaW5lLCBieSA9IGMoImlkX3Jlc2VydmF0b3Jpby54IiwiZG95IikpICU+JQ0KICBtdXRhdGUoDQogICAgbF9wcmVjaXAgPSBsX3ByZWNpcF9ibCwNCiAgICBsX3RlbXAgICA9IGxfdGVtcF9ibCwNCiAgICBsX2h1bWlkaXR5ID0gbF9odW1pZGl0eV9ibCwNCiAgICBsX3dpbmRfc3BlZWQ9IGxfd2luZF9zcGVlZF9ibA0KICApICMlPiUNCiAgI3NlbGVjdChuYW1lcyhyZXNlcnYpKQ0KDQojIFByZWRpw6fDtWVzIG5vIG7DrXZlbCAoTVfCt23DqnMpDQpyZXNlcnYkZWFyX2hhdF9vYnMgPC0gcHJlZGljdChtMV9nYW0sIG5ld2RhdGEgPSByZXNlcnYsIHR5cGUgPSAicmVzcG9uc2UiKQ0KcmVzZXJ2JGVhcl9oYXRfY2YgIDwtIHByZWRpY3QobTFfZ2FtLCBuZXdkYXRhID0gbmRfY2YsICB0eXBlID0gInJlc3BvbnNlIikNCg0KIyBQZW5hbGlkYWRlIGNsaW3DoXRpY2Egbm8gRUFSIChwb250dWFsKQ0KcmVzZXJ2JGRlbHRhX2Vhcl9oYXQgPC0gcmVzZXJ2JGVhcl9oYXRfb2JzIC0gcmVzZXJ2JGVhcl9oYXRfY2YNCmRlbHRhX2Vhcl9oYXQgPC0gcmVzZXJ2JGVhcl9oYXRfb2JzIC0gcmVzZXJ2JGVhcl9oYXRfY2YNCmBgYA0KDQojIyAzLjEuNSBQcm9wYWdhw6fDo28gZGUgSW5jZXJ0ZXphDQpQYXJhIHF1YW50aWZpY2FyIGEgaW5jZXJ0ZXphIGFzc29jaWFkYSDDoHMgZXN0aW1hdGl2YXMgZGUgcGVuYWxpZGFkZSBjbGltw6F0aWNhICjOlEVBUiksIGZvcmFtIGFwbGljYWRvcyBkb2lzIG3DqXRvZG9zIGNvbXBsZW1lbnRhcmVzOiBvIERlbHRhIE1ldGhvZCBhbmFsw610aWNvIGUgYSBTaW11bGHDp8OjbyBQYXJhbcOpdHJpY2EgTXVsdGl2YXJpYWRhLiBPIHByaW1laXJvIGZvcm5lY2UgaW50ZXJ2YWxvcyBkZSBjb25maWFuw6dhIHBvbnR1YWlzIGJhc2VhZG9zIG5hIG1hdHJpeiBkZSBjb3ZhcmnDom5jaWEgZG9zIGNvZWZpY2llbnRlcyBkbyBtb2RlbG87IG8gc2VndW5kbyBwZXJtaXRlIHByb3BhZ2FyIGludGVncmFsbWVudGUgYSBpbmNlcnRlemEgcGFyYW3DqXRyaWNhIGFvIGxvbmdvIGRhIGNhZGVpYSBkZSBlc3RpbWHDp8OjbywgZ2VyYW5kbyBkaXN0cmlidWnDp8O1ZXMgZW1ww61yaWNhcyBwYXJhIGNhZGEgc3Vic2lzdGVtYSBlIGFuby4NCg0KTm8gRGVsdGEgTWV0aG9kLCBhIGluY2VydGV6YSDDqSBjYWxjdWxhZGEgcGVsYSBtYXRyaXogZGUgZGVzZW5obyBkbyBtb2RlbG8gKCAkIFhfe29ic30gLSBYX3tjZn0kKSwgbXVsdGlwbGljYWRhIHBlbGEgbWF0cml6IGRlIGNvdmFyacOibmNpYSBkb3MgcGFyw6JtZXRyb3MgKCRWX/Cdm70kKSwgY29uZm9ybWUgJFZhcijOlEUpPSBYKFZf8J2bvSlYJyQuIEVzc2EgYWJvcmRhZ2VtIGZvcm5lY2UgZXN0aW1hdGl2YXMgY29uc2lzdGVudGVzIHBhcmEgaW50ZXJ2YWxvcyBkZSA5NSUgZGUgY29uZmlhbsOnYSBlIHBlcm1pdGUgYWdyZWdhciByZXN1bHRhZG9zIHByZXNlcnZhbmRvIGFzIGNvdmFyacOibmNpYXMgZW50cmUgb2JzZXJ2YcOnw7Vlcy4gTyBtw6l0b2RvIMOpIGNvbXB1dGFjaW9uYWxtZW50ZSBlZmljaWVudGUgZSDDunRpbCBwYXJhIGdlcmFyIGludGVydmFsb3MgYW5hbMOtdGljb3MgY29tcGFyw6F2ZWlzIGVudHJlIHN1YnNpc3RlbWFzLg0KDQpBIFNpbXVsYcOnw6NvIFBhcmFtw6l0cmljYSBhbXBsaWEgZXNzYSBhYm9yZGFnZW0gYW8gYW1vc3RyYXIgbWlsaGFyZXMgZGUgdmV0b3JlcyBkZSBjb2VmaWNpZW50ZXMgKA0KJPCdm71eeyjwnZGgKX3iiLzwnZGBKFxoYXR7XGJldGF9LPCdkYnwnZu9KSQgZSByZWNhbGN1bGFyICTOlCDwnZC48J2QtPCdkYVeeyjwnZGgKX0kIHBhcmEgY2FkYSBhbW9zdHJhLiBBIGFncmVnYcOnw6NvIGRvcyByZXN1bHRhZG9zIHBvciBzdWJzaXN0ZW1hIGUgYW5vIGZvcm5lY2UgZGlzdHJpYnVpw6fDtWVzIGVtcMOtcmljYXMgZGEgcGVuYWxpZGFkZSBjbGltw6F0aWNhLCBleHByZXNzYXMgcG9yIGZhbiBjaGFydHMgKEZpZ3VyYSBhYmFpeG8pLiBPcyByZXN1bHRhZG9zIGluZGljYW0gdGVuZMOqbmNpYSBuZWdhdGl2YSBjcmVzY2VudGUgZGEgZW5lcmdpYSBhcm1hemVuYWRhIGFqdXN0YWRhIGFvIGNsaW1hIG3DqWRpbywgY29tIGZvcnRlIHF1ZWRhIGFww7NzIDIwMTAgZSBwaWNvcyBkZSBpbmNlcnRlemEgZW0gMjAxNOKAkzIwMTYuIEFzIHJlZ2nDtWVzIFN1ZGVzdGUgZSBTdWwgY29uY2VudHJhbSBvcyBtYWlvcmVzIGTDqWZpY2l0cyBtw6lkaW9zIChhdMOpIOKAkzUgZSDigJMxIG1pbGjDtWVzIGRlIE1Xwrdtw6pzLCByZXNwZWN0aXZhbWVudGUpLCBlbnF1YW50byBOb3JkZXN0ZSBlIE5vcnRlIGFwcmVzZW50YW0gcGVuYWxpZGFkZXMgbWVub3JlcywgcG9yw6ltIGNvbSBhdW1lbnRvIHByb2dyZXNzaXZvIGFvIGZpbmFsIGRhIHPDqXJpZS4gRXNzYSBjb25zaXN0w6puY2lhIGVudHJlIG9zIGRvaXMgbcOpdG9kb3MgY29uZmlybWEgYSByb2J1c3RleiBlc3RhdMOtc3RpY2EgZG8gbW9kZWxvIGUgZXN0YWJlbGVjZSB1bWEgYmFzZSBjb25macOhdmVsIHBhcmEgYSBldGFwYSBzZWd1aW50ZSBkZSBwcm9wYWdhw6fDo28gZGUgaW5jZXJ0ZXphIG5hIGdlcmHDp8OjbyBoaWRyZWzDqXRyaWNhLg0KDQoNCg0KIyMjIyBJbmNlcnRlemEgKG3DqXRvZG8gNDogKipEZWx0YSBtZXRob2QqKiBhbmFsw610aWNvKQ0KRXN0aW1hbW9zIElDcyBwYXJhIFwoXERlbHRhIEVBUlwpIHZpYSBtYXRyaXogZGUgZGVzZW5obyBubyAqKmxpbmsqKiAoYXF1aSwgaWRlbnRpdHkg4oeSIGrDoSDDqSBuw612ZWwpLiBBZ3JlZ2HDp8O1ZXMgcG9yIGFuby9zdWJzaXN0ZW1hIGRldmVtIHByZXNlcnZhciBhIGNvdmFyacOibmNpYS4NCmBgYHtyIG0xLWRlbHRhLW1ldGhvZCwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0NClZwICAgICAgPC0gdmNvdihtMV9nYW0pICAjIGNvdmFyacOibmNpYSBkb3MgY29lZmljaWVudGVzDQpYX29icyAgIDwtIHByZWRpY3QobTFfZ2FtLCBuZXdkYXRhID0gbmRfb2JzLCB0eXBlID0gImxwbWF0cml4IikNClhfY2YgICAgPC0gcHJlZGljdChtMV9nYW0sIG5ld2RhdGEgPSBuZF9jZiwgIHR5cGUgPSAibHBtYXRyaXgiKQ0KWF9kaWZmICA8LSBYX29icyAtIFhfY2YNCg0KIyBFUCBwb3Igb2JzZXJ2YcOnw6NvDQp2YXJfZGVsdGEgPC0gcm93U3VtcygoWF9kaWZmICUqJSBWcCkgKiBYX2RpZmYpDQpzZV9kZWx0YSAgPC0gc3FydChwbWF4KHZhcl9kZWx0YSwgMCkpDQp6ICAgICAgICAgPC0gcW5vcm0oMC45NzUpDQoNCmRlbHRhX2x3ciA8LSByZXNlcnYkZGVsdGFfZWFyX2hhdCAtIHogKiBzZV9kZWx0YQ0KZGVsdGFfdXByIDwtIHJlc2VydiRkZWx0YV9lYXJfaGF0ICsgeiAqIHNlX2RlbHRhDQpyZXNlcnYkZGVsdGFfZWFyX3VwcjwtZGVsdGFfdXByDQpyZXNlcnYkZGVsdGFfZWFyX2x3cjwtZGVsdGFfbHdyDQptMV9kZWx0YSA8LSBuZF9vYnMgJT4lDQogIHRyYW5zbXV0ZSgNCiAgICBkYXRlLCBub21fc3Vic2lzdGVtYS54LA0KICAgIGRlbHRhX2hhdCA9IGRlbHRhX2Vhcl9oYXQsDQogICAgZGVsdGFfc2UgID0gc2VfZGVsdGEsDQogICAgZGVsdGFfbHdyID0gZGVsdGFfbHdyLA0KICAgIGRlbHRhX3VwciA9IGRlbHRhX3Vwcg0KICApDQoNCiMgQWdyZWdhciBwb3IgYW5vL3N1YnNpc3RlbWEgcHJlc2VydmFuZG8gY292YXJpw6JuY2lhIChjb21iaW5hw6fDo28gbGluZWFyKQ0KbGlicmFyeShkYXRhLnRhYmxlKQ0KZHQgPC0gYXMuZGF0YS50YWJsZShuZF9vYnMpWywgLihkYXRlLCBub21fc3Vic2lzdGVtYS54KV0NCmR0WywgeWVhciA6PSB5ZWFyKGRhdGUpXQ0KDQojIFZldG9yIHNfZyA9IHNvbWEgZGFzIGxpbmhhcyBkZSBYX2RpZmYgbm8gZ3J1cG8gKGFubywgc3Vic2lzdGVtYSkNCmdyb3VwcyA8LSB1bmlxdWUoZHRbLCAuKHllYXIsIG5vbV9zdWJzaXN0ZW1hLngpXSkNClMgPC0gbGFwcGx5KDE6bnJvdyhncm91cHMpLCBmdW5jdGlvbihnKXsNCiAgaWR4IDwtIHdoaWNoKGR0JHllYXIgPT0gZ3JvdXBzJHllYXJbZ10gJiBkdCRub21fc3Vic2lzdGVtYS54ID09IGdyb3VwcyRub21fc3Vic2lzdGVtYS54W2ddKQ0KICBjb2xTdW1zKFhfZGlmZltpZHgsICwgZHJvcCA9IEZBTFNFXSkNCn0pDQoNCmFnZ19tZWFuIDwtIHNhcHBseSgxOm5yb3coZ3JvdXBzKSwgZnVuY3Rpb24oZyl7DQogIHN1bShyZXNlcnYkZGVsdGFfZWFyX2hhdFtkdCR5ZWFyID09IGdyb3VwcyR5ZWFyW2ddICYgZHQkbm9tX3N1YnNpc3RlbWEueCA9PSBncm91cHMkbm9tX3N1YnNpc3RlbWEueFtnXV0sIG5hLnJtID0gVFJVRSkNCn0pDQphZ2dfdmFyICA8LSBzYXBwbHkoUywgZnVuY3Rpb24oc3YpIGFzLm51bWVyaWModChzdikgJSolIFZwICUqJSBzdikpDQphZ2dfc2UgICA8LSBzcXJ0KHBtYXgoYWdnX3ZhciwgMCkpDQoNCm0xX2RlbHRhX2FnZyA8LSBjYmluZChncm91cHMsDQogIGRlbHRhX21lYW4gPSBhZ2dfbWVhbiwNCiAgZGVsdGFfbHdyICA9IGFnZ19tZWFuIC0geiAqIGFnZ19zZSwNCiAgZGVsdGFfdXByICA9IGFnZ19tZWFuICsgeiAqIGFnZ19zZQ0KKQ0KYGBgDQoNCiMjIyMgSW5jZXJ0ZXphIChtw6l0b2RvIDE6ICoqU2ltdWxhw6fDo28gcGFyYW3DqXRyaWNhKiogZW5jYWRlw6F2ZWwpDQpBbW9zdHJhbW9zIG9zIGNvZWZpY2llbnRlcyBkYSBkaXN0cmlidWnDp8OjbyBub3JtYWwgbXVsdGl2YXJpYWRhIGUgcmVjYWxjdWxhbW9zIFwoXERlbHRhIEVBUl57KHMpfVwpLiBFc3NlIG9iamV0byBzZXLDoSBhICoqZW50cmFkYSBwcm9iYWJpbMOtc3RpY2EqKiBwYXJhIG8gR0FNIDEuDQoNCmBgYHtyIG0xLW1vbnRlY2FybG8sIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9DQpsaWJyYXJ5KE1BU1MpDQpuc2ltIDwtIDUwMA0Kc2V0LnNlZWQoMjAyNTEwMTApDQoNCmJldGFfZHJhd3MgPC0gTUFTUzo6bXZybm9ybShuID0gbnNpbSwgbXUgPSBjb2VmKG0xX2dhbSksIFNpZ21hID0gVnApDQoNCiMgUHLDqS1jw6FsY3VsbyBwYXJhIGVmaWNpw6puY2lhDQpEIDwtIFhfZGlmZiAgICAgICAgICAgICAjIE4geCBwDQojIM6URUFSIHBvciBzaW11bGHDp8OjbzogY2FkYSBjb2x1bmEgw6kgdW1hIHNpbSwgY2FkYSBsaW5oYSB1bWEgb2JzZXJ2YcOnw6NvDQpkZWx0YV9zaW1zIDwtIEQgJSolIHQoYmV0YV9kcmF3cykgICAjIChOIHggbnNpbSkNCg0KIyBBZ3JlZ2FyIHBvciBhbm8vc3Vic2lzdGVtYSBlbSBjYWRhIHNpbQ0KZHQgPC0gYXMuZGF0YS50YWJsZShuZF9vYnMpWywgLihkYXRlLCB5ZWFyID0geWVhcihkYXRlKSwgbm9tX3N1YnNpc3RlbWEueCldDQoNCmR0JGdpZCA8LSAuR1JQOyBkdFssIGdpZCA6PSAuR1JQLCBieSA9IC4oeWVhciwgbm9tX3N1YnNpc3RlbWEueCldDQpHIDwtIG1heChkdCRnaWQpDQoNCmFnZ19tYXQgPC0gbWF0cml4KE5BX3JlYWxfLCBucm93ID0gRywgbmNvbCA9IG5zaW0pDQpmb3IgKGcgaW4gMTpHKSB7DQogIGlkeCA8LSB3aGljaChkdCRnaWQgPT0gZykNCiAgYWdnX21hdFtnLCBdIDwtIGNvbFN1bXMoZGVsdGFfc2ltc1tpZHgsICwgZHJvcCA9IEZBTFNFXSwgbmEucm0gPSBUUlVFKQ0KfQ0KDQptMV9zaW1fYWdnIDwtIGNiaW5kKGdyb3VwcywNCiAgbWVhbiA9IHJvd01lYW5zKGFnZ19tYXQpLA0KICBsd3IgID0gYXBwbHkoYWdnX21hdCwgMSwgcXVhbnRpbGUsIDAuMDI1KSwNCiAgdXByICA9IGFwcGx5KGFnZ19tYXQsIDEsIHF1YW50aWxlLCAwLjk3NSksDQogIHNkICA9IGFwcGx5KGFnZ19tYXQsIDEsIHNkKQ0KDQopDQoNCmBgYA0KYGBge3J9DQptMV9zaW1fYWdnICU+JSBtdXRhdGUoc2RfdXA9bWVhbit6KnNkLCBzZF9sd3I9bWVhbi16KnNkKS0+bTFfc2ltX2FnZw0KYGBgDQoNCiMjIyMgVmlzdWFsaXphw6fDo28gcsOhcGlkYSAocHVibGljYcOnw6NvKQ0KUmliYm9ucyAoRGVsdGEpIGUgZmFuIGNoYXJ0cyAoTUMpIHBhZHJvbml6YWRvcy4NCg0KDQpgYGB7ciBtMS1wbG90cywgZmlnLmhlaWdodD02LCBmaWcud2lkdGg9MTIsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9DQpsaWJyYXJ5KGdncGxvdDIpDQoNCiMgUmliYm9uIChEZWx0YSkNCm0xX2RlbHRhX2FnZyAlPiUNCiAgZ2dwbG90KGFlcyh4ID0geWVhciwgeSA9IGRlbHRhX21lYW4vMTAwMCkpICsNCiAgZ2VvbV9yaWJib24oYWVzKHltaW4gPSBkZWx0YV9sd3IvMTAwMCwgeW1heCA9IGRlbHRhX3Vwci8xMDAwKSwgYWxwaGEgPSAuMjUsIGZpbGwgPSAiZmlyZWJyaWNrIikgKw0KICBnZW9tX2xpbmUoKSArDQogIGZhY2V0X3dyYXAofm5vbV9zdWJzaXN0ZW1hLngsIHNjYWxlcyA9ICJmcmVlX3kiKSArDQogIGxhYnModGl0bGUgPSAiQ2xpbWF0ZSBwZW5hbHR5IG9uIHN0b3JlZCBlbmVyZ3kgKM6URUFSKSDigJQgRGVsdGEgbWV0aG9kIiwNCiAgICAgICB5ID0gIs6URUFSIChHV8K3bW9udGgpIiwgeCA9ICJZZWFyIikgKw0KICB0aGVtZV9taW5pbWFsKCkNCg0KIyBGYW4gY2hhcnQgKE1DKQ0KbTFfc2ltX2FnZyAlPiUNCiAgZ2dwbG90KGFlcyh4ID0geWVhciwgeSA9IG1lYW4vMTAwMCkpICsNCiAgZ2VvbV9yaWJib24oYWVzKHltaW4gPSBsd3IvMTAwMCwgeW1heCA9IHVwci8xMDAwKSwgYWxwaGEgPSAuMjUsIGZpbGwgPSAic3RlZWxibHVlIikgKw0KICBnZW9tX3JpYmJvbihhZXMoeW1pbiA9IDAsIHltYXggPSB1cHIvMTAwMCksIGZpbGwgPSAicmVkMyIsIGFscGhhID0gMC4xKSArDQoNCiAgZ2VvbV9saW5lKCkgKw0KICBmYWNldF93cmFwKH5ub21fc3Vic2lzdGVtYS54LCBzY2FsZXMgPSAiZnJlZV95IikgKw0KICBsYWJzKHRpdGxlID0gIkNsaW1hdGUgcGVuYWx0eSBvbiBzdG9yZWQgZW5lcmd5ICjOlEVBUikg4oCUIFBhcmFtZXRyaWMgc2ltdWxhdGlvbiBxdWFydGlsZSIsDQogICAgICAgeSA9ICLOlEVBUiAoR1fCt21vbnRoKSIsIHggPSAiWWVhciIpICsNCiAgdGhlbWVfbWluaW1hbCgpDQptMV9zaW1fYWdnICU+JQ0KICBnZ3Bsb3QoYWVzKHggPSB5ZWFyLCB5ID0gbWVhbi8xMDAwKSkgKw0KICBnZW9tX3JpYmJvbihhZXMoeW1pbiA9IHNkX2x3ci8xMDAwLCB5bWF4ID0gc2RfdXAvMTAwMCksIGFscGhhID0gLjI1LCBmaWxsID0gInN0ZWVsYmx1ZSIpICsNCiAgZ2VvbV9yaWJib24oYWVzKHltaW4gPSAwLCB5bWF4ID0gc2RfdXAvMTAwMCksIGZpbGwgPSAicmVkMyIsIGFscGhhID0gMC4xKSArDQoNCiAgZ2VvbV9saW5lKCkgKw0KICBmYWNldF93cmFwKH5ub21fc3Vic2lzdGVtYS54LCBzY2FsZXMgPSAiZnJlZV95IikgKw0KICBsYWJzKHRpdGxlID0gIkNsaW1hdGUgcGVuYWx0eSBvbiBzdG9yZWQgZW5lcmd5ICjOlEVBUikg4oCUIFBhcmFtZXRyaWMgc2ltdWxhdGlvbiBzZCIsDQogICAgICAgeSA9ICLOlEVBUiAoR1fCt21vbnRoKSIsIHggPSAiWWVhciIpICsNCiAgdGhlbWVfbWluaW1hbCgpDQpgYGANCg0KUGVuYWxpZGFkZSBjbGltw6F0aWNhIGFncmVnYWRhIGUgaW50ZXJ2YWxvcyBkZSBjb25maWFuw6dhDQoNCmBgYHtyfQ0KbTFfc3VtbWFyeSA8LSBtMV9zaW1fYWdnICU+JQ0KICBncm91cF9ieShub21fc3Vic2lzdGVtYS54KSAlPiUNCiAgc3VtbWFyaXNlKA0KICAgIG1lYW5fcGVuYWx0eSA9IG1lYW4obWVhbiwgbmEucm0gPSBUUlVFKSwNCiAgICBsd3JfOTUgPSBtZWFuKGx3ciwgbmEucm0gPSBUUlVFKSwNCiAgICB1cHJfOTUgPSBtZWFuKHVwciwgbmEucm0gPSBUUlVFKSwNCiAgICBzZF9wZW5hbHR5ID0gc2QobWVhbiwgbmEucm0gPSBUUlVFKSwNCiAgICAuZ3JvdXBzID0gImRyb3AiDQogICkNCg0KIyBDb252ZXJ0ZW5kbyBwYXJhIEdXaC9hbm8gcGFyYSBpbnRlcnByZXRhw6fDo28NCm0xX3N1bW1hcnkgPC0gbTFfc3VtbWFyeSAlPiUNCiAgbXV0YXRlKA0KICAgIG1lYW5fR1doID0gbWVhbl9wZW5hbHR5IC8gMTAwMCwNCiAgICBsd3JfR1doICA9IG1lYW5fcGVuYWx0eS16KnNkX3BlbmFsdHkgLyAxMDAwLA0KICAgIHVwcl9HV2ggID0gbWVhbl9wZW5hbHR5K3oqc2RfcGVuYWx0eSAvIDEwMDAsDQogICkgIyU+JSBzZWxlY3QoLW1lYW5fcGVuYWx0eSwgLWx3cl85NSwgLXVwcl85NSkNCg0KIyBUYWJlbGEgZm9ybWF0YWRhIChwdWJsaWNhw6fDo28pDQpsaWJyYXJ5KGd0KQ0KbTFfc3VtbWFyeVssYygibm9tX3N1YnNpc3RlbWEueCIsIm1lYW5fR1doIiwibHdyX0dXaCIsICJ1cHJfR1doIildICU+JSBqYW5pdG9yOjphZG9ybl90b3RhbHMoKSAlPiUgDQogIGd0KCkgJT4lDQogIGZtdF9udW1iZXIoY29sdW1ucyA9IDI6NCwgZGVjaW1hbHMgPSAxKSAlPiUNCiAgY29sc19sYWJlbCgNCiAgICBub21fc3Vic2lzdGVtYS54ID0gIlN1YnN5c3RlbSIsDQogICAgbWVhbl9HV2ggPSAiTWVhbiDOlEVBUiAoR1doKSIsDQogICAgbHdyX0dXaCAgPSAiTG93ZXIgOTUlIiwNCiAgICB1cHJfR1doICA9ICJVcHBlciA5NSUiLA0KICApICU+JQ0KICB0YWJfaGVhZGVyKA0KICAgIHRpdGxlID0gbWQoIioqQWdncmVnYXRlIGNsaW1hdGUgcGVuYWx0eSBvbiBzdG9yZWQgZW5lcmd5ICgyMDAx4oCTMjAxOCkqKiIpLA0KICAgIHN1YnRpdGxlID0gIlNpbXVsYXRlZCBtZWFuIGFuZCA5NSUgY29uZmlkZW5jZSBpbnRlcnZhbHMgcGVyIHN1YnN5c3RlbSINCiAgKQ0KYGBgDQpBIFRhYmVsYSBhcHJlc2VudGEgYSAqKnBlbmFsaWRhZGUgY2xpbcOhdGljYSBtw6lkaWEgc29icmUgYSBlbmVyZ2lhIGFybWF6ZW5hZGEgKM6URUFSKSoqIG5vIHBlcsOtb2RvIDIwMDHigJMyMDE4LCBhZ3JlZ2FkYSBwb3Igc3Vic2lzdGVtYS4gT3MgdmFsb3JlcyBmb3JhbSBlc3RpbWFkb3MgYSBwYXJ0aXIgZGFzIGRpc3RyaWJ1acOnw7VlcyBvYnRpZGFzIHZpYSBzaW11bGHDp8OjbyBwYXJhbcOpdHJpY2EgZGUgMi4wMDAgc29ydGVpb3MgZGEgbWF0cml6IGRlIGNvdmFyacOibmNpYSBkb3MgY29lZmljaWVudGVzIGRvIG1vZGVsbyBoaWRyb2zDs2dpY28uIEFzIHBlbmFsaWRhZGVzIG3DqWRpYXMgZm9yYW0gZXhwcmVzc2FzIGVtIGdpZ2F3YXR0cy1tw6pzIChHV2jCt21vbnRoKSwgY29tIGludGVydmFsb3MgZGUgY29uZmlhbsOnYSBkZSA5NSUgY29tIHVtIHRvdGFsIGRlICoq4oCTMSw2MDYuMyAoSUM5NSU6IOKIkjEsNzQ2LjI74oiSMSw0NzAuMikgIGRlIEdXaC4NCg0KT3MgcmVzdWx0YWRvcyBpbmRpY2FtIHF1ZSBvICoqc3Vic2lzdGVtYSBTdWRlc3RlKiogY29uY2VudHJhIG8gbWFpb3IgZMOpZmljaXQgbcOpZGlvIGRlIGFybWF6ZW5hbWVudG8sIGVzdGltYWRvIGVtIGFwcm94aW1hZGFtZW50ZSAqKuKIkjEsMTc4LjQJIChJQzk1JTriiJIxLDI2Mi40O+KIkjEsMDk3LjQpICBkZSBHV2jCt23DqnMqKiwgcmVmbGV0aW5kbyBzdWEgcHJlZG9taW7Dom5jaWEgbm8gc2lzdGVtYSBpbnRlcmxpZ2FkbyBlIHN1YSBtYWlvciBleHBvc2nDp8OjbyBhIGFub21hbGlhcyBkZSBwcmVjaXBpdGHDp8Ojby4gTyAqKlN1bCoqIGFwcmVzZW50YSBwZW5hbGlkYWRlIGludGVybWVkacOhcmlhIChYWFhYWFhYWFhYWFgpLCBtYXMgY29tIG1haW9yIHZhcmlhYmlsaWRhZGUgaW50ZXJhbnVhbCwgY29tcGF0w612ZWwgY29tIHNldSByZWdpbWUgcGx1dmlvbcOpdHJpY28gbWFpcyBpcnJlZ3VsYXIuIE5vICoqTm9yZGVzdGUqKiwgYXMgcGVyZGFzIG3DqWRpYXMgc8OjbyBtZW5vcmVzIChYWFhYWFhYWFhYWFhYWCksIGVtYm9yYSBjb20gdGVuZMOqbmNpYSBuZWdhdGl2YSBhY2VudHVhZGEgYXDDs3MgMjAxMC4gSsOhIG8gKipOb3J0ZSoqIGFwcmVzZW50YSB2YWxvcmVzIHByw7N4aW1vcyBkZSB6ZXJvLCBjb20gaW50ZXJ2YWxvcyBkZSBjb25maWFuw6dhIHF1ZSBpbmNsdWVtIGEgbnVsaWRhZGUsIHN1Z2VyaW5kbyBhdXPDqm5jaWEgZGUgcGVuYWxpZGFkZSBsw61xdWlkYSBzaWduaWZpY2F0aXZhIG5vIHBlcsOtb2RvIGFuYWxpc2Fkby4NCg0KRXNzZXMgcmVzdWx0YWRvcyBjb3Jyb2JvcmFtIGEgaGlww7N0ZXNlIGRlIHF1ZSBhICoqcGVuYWxpZGFkZSBjbGltw6F0aWNhIHNvYnJlIG8gYXJtYXplbmFtZW50byBow61kcmljbyDDqSBjb25jZW50cmFkYSBlIGVzdHJ1dHVyYWxtZW50ZSBhc3NpbcOpdHJpY2EqKiwgYWZldGFuZG8gY29tIG1haW9yIGludGVuc2lkYWRlIG9zIHN1YnNpc3RlbWFzIFN1ZGVzdGUgZSBTdWwg4oCUIGp1c3RhbWVudGUgYXF1ZWxlcyBjb20gbWFpb3IgcGFwZWwgZGUgcmVndWxhw6fDo28gZSBzdXBvcnRlIGVuZXJnw6l0aWNvIHBhcmEgbyByZXN0YW50ZSBkbyBwYcOtcy4gRXNzYSBoZXRlcm9nZW5laWRhZGUgZXNwYWNpYWwgZm9ybmVjZSBvIGVsbyBlbXDDrXJpY28gcGFyYSBhIHByw7N4aW1hIGV0YXBhIGRhIG1vZGVsYWdlbSwgZW0gcXVlIGFzIHZhcmlhw6fDtWVzIHNpbXVsYWRhcyBkZSBcKCBcRGVsdGEgRUFSIFwpIHNlcsOjbyBwcm9wYWdhZGFzIMOgIGdlcmHDp8OjbyBoaWRyZWzDqXRyaWNhIChHQU0gMSksIMOgIGdlcmHDp8OjbyB0w6lybWljYSAoR0FNIDIpIGUsIHBvciBmaW0sIGFvIHByZcOnbyBkZSBjdXJ0byBwcmF6byAoR0FNIDMpLg0KDQoNCjMuMiBNb2RlbG8gMiDigJQgR2VyYcOnw6NvIEhpZHJlbMOpdHJpY2EgY29tbyBGdW7Dp8OjbyBkbyBBcm1hemVuYW1lbnRvDQpPIHNlZ3VuZG8gbW9kZWxvIGRhIGNhZGVpYSBlc3RpbWEgYSBnZXJhw6fDo28gaGlkcmVsw6l0cmljYSAoR19oaWRybykgZW0gZnVuw6fDo28gZGEgZW5lcmdpYSBhcm1hemVuYWRhIChFQVIpIGUgZGUgY29udHJvbGVzIG9wZXJhY2lvbmFpcyBlIHNhem9uYWlzLiBPIG9iamV0aXZvIMOpIGNhcHR1cmFyIGEgZWxhc3RpY2lkYWRlIGRhIGdlcmHDp8OjbyBlbSByZWxhw6fDo28gYW8gZXN0b3F1ZSBow61kcmljbywgcGVybWl0aW5kbyB0cmFkdXppciBhcyB2YXJpYcOnw7VlcyBzaW11bGFkYXMgZGUgzpRFQVIgKHBlbmFsaWRhZGUgY2xpbcOhdGljYSkgZW0gaW1wYWN0b3Mgc29icmUgYSBnZXJhw6fDo28gZWZldGl2YS4gQXNzaW0gY29tbyBubyBtb2RlbG8gY2xpbcOhdGljbywgZW1wcmVnYS1zZSB1bSBHQU0gcGFyYSBjYXB0dXJhciByZWxhw6fDtWVzIG7Do28gbGluZWFyZXMgZW50cmUgdmFyacOhdmVpcyBmw61zaWNhcyBlIG9wZXJhY2lvbmFpcywgbWFudGVuZG8gcGFyY2ltw7RuaWEgZSBpbnRlcnByZXRhYmlsaWRhZGUuDQoNCg0KDQojIDMuMiBNb2RlbG8gMiDigJQgR2VyYcOnw6NvIEhpZHJlbMOpdHJpY2EgY29tbyBGdW7Dp8OjbyBkbyBBcm1hemVuYW1lbnRvLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0NCg0KYGBge3J9DQoNCm0yX2hpZHJvIDwtIGJhbSgNCiAgdmFsX2dlcmFjYW8gfiAgWWVhcisNCiAgICBzKGVhcl9yZXNlcnZhdG9yaW9fc3Vic2lzdGVtYV9wcm9wcmlvX213bWVzLCBrID0gNCkrDQogICAgcyh2YWxfZ2VyYWNhb19kYXlfc3Vic2lzdGVtYSwgayA9IDQpKw0KICAgIHMoZG95LCBicyA9ICJjYyIsIGsgPSAyKSArICAgICAjIHNhem9uYWxpZGFkZSBkbyBkaWEgZG8gYW5vIChjw61jbGljYSkNCiAgICBzKGlkX3Jlc2VydmF0b3Jpby54LCBicyA9ICJyZSIpKyMgZWZlaXRvIGFsZWF0w7NyaW8gcG9yIHJlc2VydmF0w7NyaW8NCiAgICNzKHZhbF92YXphb2RlZmx1ZW50ZSxrID0gMikrDQoNCiAgICBub21fc3Vic2lzdGVtYS54DQogICwNCiAgZGF0YSAgICAgPSByZXNlcnYsDQogIG1ldGhvZCAgID0gImZSRU1MIiwNCiAgZGlzY3JldGUgPSBUUlVFLA0KICBmYW1pbHkgICA9IGdhdXNzaWFuKCksICAgICAgICAgICAgIyBmYW3DrWxpYTogbm9ybWFsOyBhanVzdGFyIHNlIG5lY2Vzc8OhcmlvDQogIG5hLmFjdGlvbj0gbmEuZXhjbHVkZSwNCiAgI2tub3RzICAgID0gbGlzdChkb3kgPSBjKDAuNSwgMzY2LjUpKQ0KKQ0KYGBgDQoNCmBgYHtyfQ0Kc3VtbWFyeShtMl9oaWRybykNCmdhbS5jaGVjayhtMl9oaWRybykNCmNvbmN1cnZpdHkobTJfaGlkcm8sIGZ1bGw9VFJVRSkNCg0KYGBgDQoNCg0KYGBge3J9DQoNCnBsb3QobTJfaGlkcm8sIHBhZ2VzPTMsIHNjaGVtZT0xLCBzaGFkZT1UUlVFLCBzZT1UUlVFLCBzY2FsZXM9ImZyZWUiKQ0KYGBgDQpPIG1vZGVsbyBoaWRyZWzDqXRyaWNvIChHQU0gMikgYXByZXNlbnRvdSBmb3J0ZSBkZXNlbXBlbmhvIGV4cGxpY2F0aXZvLCBjb20gUsKyIGFqdXN0YWRvIGRlIDAsODUgZSBkZXZpYW5jZSBleHBsaWNhZGEgZGUgODUsMiUsIG8gcXVlIGNvbmZpcm1hIHN1YSBhbHRhIGNhcGFjaWRhZGUgZGUgcmVwcm9kdXppciBhIGdlcmHDp8OjbyBvYnNlcnZhZGEgYSBwYXJ0aXIgZGEgZW5lcmdpYSBhcm1hemVuYWRhIGUgdmFyacOhdmVpcyBvcGVyYWNpb25haXMuIE8gdGVybW8gbGluZWFyIHBhcmEgbyBhbm8gw6kgbmVnYXRpdm8gZSBhbHRhbWVudGUgc2lnbmlmaWNhdGl2byAo4oCTMTMsNSBNV8K3bcOqcy9hbm87IHAgPCAwLDAwMSksIHJlZmxldGluZG8gYSB0ZW5kw6puY2lhIGVzdHJ1dHVyYWwgZGUgcmVkdcOnw6NvIGRhIHBhcnRpY2lwYcOnw6NvIGjDrWRyaWNhIGFvIGxvbmdvIGRvIHBlcsOtb2RvLCBwb3NzaXZlbG1lbnRlIGVtIGZ1bsOnw6NvIGRhIGV4cGFuc8OjbyBkZSBmb250ZXMgdMOpcm1pY2FzIGUgcmVub3bDoXZlaXMgbsOjbyBow61kcmljYXMuIE9zIGVmZWl0b3MgZml4b3MgcG9yIHN1YnNpc3RlbWEgaW5kaWNhbSBkaWZlcmVuw6dhcyBtb2Rlc3RhcywgY29tIGdlcmHDp8OjbyBtw6lkaWEgbGlnZWlyYW1lbnRlIHN1cGVyaW9yIG5vIE5vcnRlIGUgaW5mZXJpb3Igbm8gU3VkZXN0ZSwgY29uc2lzdGVudGVzIGNvbSBvIHBhcGVsIGVzdHJ1dHVyYWwgZGUgY2FkYSByZWdpw6NvIG5hIG9mZXJ0YSBkZSBlbmVyZ2lhIGUgbm8gZGVzcGFjaG8gZG8gc2lzdGVtYS4NCg0KT3MgZGlhZ27Ds3N0aWNvcyBkZSByZXPDrWR1b3MgZXZpZGVuY2lhbSBhanVzdGUgYWRlcXVhZG8sIGNvbSBkaXN0cmlidWnDp8OjbyBhcHJveGltYWRhbWVudGUgbm9ybWFsIGUgYXVzw6puY2lhIGRlIGhldGVyb2NlZGFzdGljaWRhZGUgc2lzdGVtw6F0aWNhLiBPIGhpc3RvZ3JhbWEgZG9zIHJlc8OtZHVvcyDDqSBjZW50cmFkbyBlbSB6ZXJvLCBlIG8gUVEtcGxvdCBtb3N0cmEgbGV2ZSBjdXJ2YXR1cmEgbmFzIGNhdWRhcywgaW5kaWNhbmRvIHBlcXVlbmEgYXNzaW1ldHJpYSBhc3NvY2lhZGEgYSByZWdpbWVzIG9wZXJhY2lvbmFpcyBleHRyZW1vcyAocmVzZXJ2YXTDs3Jpb3MgY2hlaW9zIG91IHZhemlvcykuIE8gZ3LDoWZpY28gZGUgcmVzw61kdW9zIHZlcnN1cyBwcmVkaXRvcyBleGliZSBkdWFzIGZhaXhhcyBiZW0gZGVmaW5pZGFzLCBjb3JyZXNwb25kZW50ZXMgYSBkaWZlcmVudGVzIHJlZ2ltZXMgZGUgb3BlcmHDp8OjbyBoaWRyw6F1bGljYSDigJQgdW0gZGUgYmFpeGEgZ2VyYcOnw6NvIGNvbSBFQVIgbGltaXRhZGEgZSBvdXRybyBkZSBvcGVyYcOnw6NvIHBsZW5hIGNvbSBhbHRvcyBuw612ZWlzIGRlIGRlc3BhY2hvLiBFbWJvcmEgZXNzZXMgcmVnaW1lcyBpbnRyb2R1emFtIGxldmUgZXN0cmF0aWZpY2HDp8OjbywgbsOjbyBow6EgaW5kw61jaW9zIGRlIHZpw6lzIGRpcmVjaW9uYWwgbmVtIGF1dG9jb3JyZWxhw6fDo28gcmVsZXZhbnRlLCBvIHF1ZSByZWZvcsOnYSBhIHZhbGlkYWRlIGRvIG1vZGVsbyBnYXVzc2lhbm8gY29tIGxpbmsgaWRlbnRpZGFkZS4gTyB0ZXN0ZSBkZSBkaW1lbnNpb25hbGlkYWRlIGVmZXRpdmEgKGstaW5kZXggPiAwLjkpIGUgbyBiYWl4byBuw612ZWwgZGUgY29uY29ycsOqbmNpYSAoY29uY3Vydml0eSA8IDAuMykgY29uZmlybWFtIGEgZXN0YWJpbGlkYWRlIG51bcOpcmljYSBkb3Mgc3BsaW5lcyBlIGEgYXVzw6puY2lhIGRlIHNvYnJlYWp1c3RlLg0KDQpPcyBlZmVpdG9zIHBhcmNpYWlzIGlsdXN0cmFtIGRlIGZvcm1hIGNsYXJhIGEgZGluw6JtaWNhIGbDrXNpY2EgZG8gc2lzdGVtYS4gTyBzcGxpbmUgZGEgZW5lcmdpYSBhcm1hemVuYWRhIChFQVIpIGFwcmVzZW50YSB1bSBmb3JtYXRvIGNyZXNjZW50ZSBjb20gbGV2ZSBzYXR1cmHDp8Ojbywgc3VnZXJpbmRvIHJlbmRpbWVudG8gZGVjcmVzY2VudGU6IGF1bWVudG9zIGluaWNpYWlzIGRlIGFybWF6ZW5hbWVudG8gcHJvZHV6ZW0gZ3JhbmRlcyBhY3LDqXNjaW1vcyBkZSBnZXJhw6fDo28sIG1hcyBvIGVmZWl0byBtYXJnaW5hbCBkaW1pbnVpIMOgIG1lZGlkYSBxdWUgbyByZXNlcnZhdMOzcmlvIHNlIGFwcm94aW1hIGRhIGNhcGFjaWRhZGUgbcOheGltYS4gTyBzcGxpbmUgZGEgZ2VyYcOnw6NvIGRpw6FyaWEgZG8gc3Vic2lzdGVtYSBtb3N0cmEgcmVsYcOnw6NvIHF1YXNlIGxpbmVhciBwb3NpdGl2YSwgcmVwcmVzZW50YW5kbyBvIGVmZWl0byBkZSBlc2NhbGEgZSBjb29yZGVuYcOnw6NvIGVudHJlIHVzaW5hcyBpbnRlcmxpZ2FkYXMuIEEgc2F6b25hbGlkYWRlIGFudWFsIChkb3kpIMOpIGZyYWNhLCByZWZsZXRpbmRvIG8gZmF0byBkZSBxdWUgYXMgb3NjaWxhw6fDtWVzIHNhem9uYWlzIGrDoSBzw6NvIGludGVybmFsaXphZGFzIG5vIG7DrXZlbCBkZSBhcm1hemVuYW1lbnRvLCBlbnF1YW50byBvIGVmZWl0byBhbGVhdMOzcmlvIHBvciByZXNlcnZhdMOzcmlvIGluZGljYSBhbXBsYSBoZXRlcm9nZW5laWRhZGUgZXN0cnV0dXJhbCDigJQgYWxndW5zIHJlc2VydmF0w7NyaW9zIG9wZXJhbSBjb21vIHVzaW5hcyBkZSBiYXNlLCBjb20gZWZlaXRvIHByw7N4aW1vIGRlIHplcm8sIGUgb3V0cm9zIGNvbSBmb3J0ZSBzZW5zaWJpbGlkYWRlIMOgIHZhcmlhw6fDo28gZGUgRUFSLiBFbSBjb25qdW50bywgZXNzZXMgcmVzdWx0YWRvcyBjb25maXJtYW0gcXVlIG8gbW9kZWxvIGNhcHRhIGFkZXF1YWRhbWVudGUgbyBtZWNhbmlzbW8gZGUgY29udmVyc8OjbyBoaWRyb2zDs2dpY2EgZW50cmUgZXN0b3F1ZSBlIGdlcmHDp8Ojbywgb2ZlcmVjZW5kbyBiYXNlIGNvbnNpc3RlbnRlIHBhcmEgYSBlc3RpbWF0aXZhIGNvbnRyYWZhY3R1YWwgZGEgZ2VyYcOnw6NvIGjDrWRyaWNhIHNvYiBkaWZlcmVudGVzIGNlbsOhcmlvcyBjbGltw6F0aWNvcy4NCg0KDQoNCiMjUHJlZGnDp8O1ZXMgZmFjdHVhbCB2cy4gY29udHJhZmFjdHVhbCBjb20gaW5jZXJ0ZXphIChiYXNlbGluZSAyMDAx4oCTMjAwNSkNCk8gb2JqZXRpdm8gw6kgY29tcGFyYXIgbyBhcm1hemVuYW1lbnRvIHByZXZpc3RvIHBlbG8gbW9kZWxvIHNvYiBjb25kacOnw7VlcyBjbGltw6F0aWNhcyBvYnNlcnZhZGFzIGUgc29iIGNvbmRpw6fDtWVzIG5ldXRyYXMsIHJlcHJlc2VudGFkYXMgcGVsbyBjbGltYSBtw6lkaW8gZG8gcGVyw61vZG8gMjAwMeKAkzIwMDUuIEEgZGlmZXJlbsOnYSBlbnRyZSBhcyBkdWFzIHPDqXJpZXMgKCTOlEVBUj1FXntvYnN94oiSRV57Y2Z9JCkgcmVwcmVzZW50YSBhIHBlbmFsaWRhZGUgY2xpbcOhdGljYSBsw61xdWlkYSwgZSBzdWEgaW5jZXJ0ZXphIMOpIGVzdGltYWRhIHZpYSBwcm9wYWdhw6fDo28gZG9zIGVycm9zIHBhcmFtw6l0cmljb3MgZG8gR0FNLg0KDQpgYGB7cn0NCiMgLS0tIFByZWRpw6fDtWVzIGZhY3R1YWwgZSBjb250cmFmYWN0dWFsIC0tLQ0KcmVzZXJ2JGVhcl9oYXRfb2JzIDwtIHByZWRpY3QobTFfZ2FtLCBuZXdkYXRhID0gbmRfb2JzLCB0eXBlID0gInJlc3BvbnNlIikNCnJlc2VydiRlYXJfaGF0X2NmICA8LSBwcmVkaWN0KG0xX2dhbSwgbmV3ZGF0YSA9IG5kX2NmLCAgdHlwZSA9ICJyZXNwb25zZSIpDQoNCiMgUGVuYWxpZGFkZSBtw6lkaWENCnJlc2VydiA8LSByZXNlcnYgJT4lDQogIG11dGF0ZShkZWx0YV9lYXIgPSBlYXJfaGF0X29icyAtIGVhcl9oYXRfY2YpDQoNCnJlc2VydiRnZXJfaGF0X2ZhY3R1YWwgPC0gcHJlZGljdCgNCiAgbTJfaGlkcm8sIG5ld2RhdGEgPSByZXNlcnYsDQogIHR5cGUgPSAicmVzcG9uc2UiDQopDQpyZXNlcnYkZ2VyX2hhdF9jb250cmFmIDwtIHByZWRpY3QoDQogIG0yX2hpZHJvLCBuZXdkYXRhID0gcmVzZXJ2ICU+JQ0KICAgIG11dGF0ZShlYXJfcmVzZXJ2YXRvcmlvX3N1YnNpc3RlbWFfcHJvcHJpb19td21lcyA9IGVhcl9oYXRfY2YpLA0KICB0eXBlID0gInJlc3BvbnNlIg0KKQ0KcmVzZXJ2IDwtIHJlc2VydiAlPiUNCiAgbXV0YXRlKGRlbHRhX0doaWRybyA9IGdlcl9oYXRfZmFjdHVhbCAtIGdlcl9oYXRfY29udHJhZikNCnJlc2VydlssYygiZGVsdGFfR2hpZHJvIiwiZ2VyX2hhdF9mYWN0dWFsIiwiZ2VyX2hhdF9jb250cmFmIiwidmFsX2dlcmFjYW8iKV0gJT4lIHN1bW1hcnkoKQ0KYGBgDQojICgzKSBJbmNlcnRlemEgdmlhIERlbHRhIE1ldGhvZCAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0NCg0KYGBge3J9DQpWcDIgPC0gdmNvdihtMl9oaWRybykNClhfZiA8LSBwcmVkaWN0KG0yX2hpZHJvLCBuZXdkYXRhID0gcmVzZXJ2ICwNCiAgICAgICAgICAgICAgIHR5cGUgPSAibHBtYXRyaXgiKQ0KWF9jIDwtIHByZWRpY3QobTJfaGlkcm8sIG5ld2RhdGEgPSByZXNlcnYgJT4lDQogICAgICAgICAgICAgICAgIG11dGF0ZShlYXJfcmVzZXJ2YXRvcmlvX3N1YnNpc3RlbWFfcHJvcHJpb19td21lcyA9IGVhcl9oYXRfY2YpLA0KICAgICAgICAgICAgICAgdHlwZSA9ICJscG1hdHJpeCIpDQoNClhfZGlmZjIgPC0gWF9mIC0gWF9jDQp2YXJfZGVsdGEyIDwtIHJvd1N1bXMoKFhfZGlmZjIgJSolIFZwMikgKiBYX2RpZmYyKQ0Kc2VfZGVsdGEyICA8LSBzcXJ0KHBtYXgodmFyX2RlbHRhMiwgMCkpDQp6IDwtIHFub3JtKDAuOTc1KQ0KDQpDIDwtIHJlc2VydiAlPiUNCiAgbXV0YXRlKA0KICAgIGRlbHRhX2x3cl9nZXIgPSBkZWx0YV9HaGlkcm8gLSB6ICogc2VfZGVsdGEyLA0KICAgIGRlbHRhX3Vwcl9nZXIgPSBkZWx0YV9HaGlkcm8gKyB6ICogc2VfZGVsdGEyDQogICkNCkNbLGMoImRlbHRhX0doaWRybyIsImRlbHRhX2x3cl9nZXIiLCJkZWx0YV91cHJfZ2VyIiwidmFsX2dlcmFjYW8iKV0gJT4lIHN1bW1hcnkoKQ0KYGBgDQoNCmBgYHtyfQ0KIyAoNCkgQWdyZWdhw6fDo28gcG9yIGFubyBlIHN1YnNpc3RlbWEgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0NCm0yX2RlbHRhX2FnZyA8LSBDICU+JQ0KICBtdXRhdGUoWWVhciA9IHllYXIoZGF0ZSkpICU+JQ0KICBncm91cF9ieShZZWFyLCBub21fc3Vic2lzdGVtYS54KSAlPiUNCiAgc3VtbWFyaXNlKA0KICAgIG1lYW5fcGVuYWx0eSA9IHN1bShkZWx0YV9HaGlkcm8sIG5hLnJtID0gVFJVRSksDQogICAgbHdyID0gc3VtKGRlbHRhX2x3cl9nZXIsIG5hLnJtID0gVFJVRSksDQogICAgdXByID0gc3VtKGRlbHRhX3Vwcl9nZXIsIG5hLnJtID0gVFJVRSksDQogICAgLmdyb3VwcyA9ICJkcm9wIg0KICApDQptMl9kZWx0YV9hZ2cNCmBgYA0KDQoNCmBgYHtyIG0yLXBsb3QsIGZpZy5oZWlnaHQ9NiwgZmlnLndpZHRoPTEyLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQ0KbGlicmFyeShnZ3Bsb3QyKQ0KbTJfZGVsdGFfYWdnICU+JQ0KICBnZ3Bsb3QoYWVzKHggPSBZZWFyLCB5ID0gbWVhbl9wZW5hbHR5LzEwMDApKSArDQogIGdlb21fcmliYm9uKGFlcyh5bWluID0gbHdyLzEwMDAsIHltYXggPSB1cHIvMTAwMCksIGZpbGwgPSAic3RlZWxibHVlIiwgYWxwaGEgPSAwLjgpICsNCiAgZ2VvbV9yaWJib24oYWVzKHltaW4gPSAwLCB5bWF4ID0gdXByLzEwMDApLCBmaWxsID0gInJlZDMiLCBhbHBoYSA9IDAuMSkgKw0KDQogIGdlb21fbGluZShjb2xvciA9ICJibGFjayIpICsNCiAgZmFjZXRfd3JhcCh+bm9tX3N1YnNpc3RlbWEueCwgc2NhbGVzID0gImZyZWVfeSIpICsNCiAgbGFicyh0aXRsZSA9ICJQcm9wYWdhdGVkIGNsaW1hdGUgcGVuYWx0eSBvbiBoeWRyb3Bvd2VyIGdlbmVyYXRpb24gKM6UR19oaWRybykiLA0KICAgICAgIHN1YnRpdGxlID0gIkJhc2VsaW5lIGNsaW1hdGU6IG1lYW4gMjAwMeKAkzIwMDUiLA0KICAgICAgIHkgPSAizpRHX2hpZHJvIChHV8K3bW9udGgpIiwgeCA9ICJZZWFyIikgKw0KICB0aGVtZV9taW5pbWFsKCkNCmBgYA0KYGBge3J9DQogDQptMl9zdW1tYXJ5ICA8LSBDICU+JQ0KICBtdXRhdGUoWWVhciA9IHllYXIoZGF0ZSkpICU+JSB1bmdyb3VwKCkgJT4lIA0KICBncm91cF9ieSggbm9tX3N1YnNpc3RlbWEueCkgJT4lDQogIHN1bW1hcmlzZSgNCiAgICBtZWFuX3BlbmFsdHkgPSBzdW0oZGVsdGFfR2hpZHJvLCBuYS5ybSA9IFRSVUUpLA0KICAgIGx3ciA9IHN1bShkZWx0YV9sd3JfZ2VyLCBuYS5ybSA9IFRSVUUpLA0KICAgIHVwciA9IHN1bShkZWx0YV91cHJfZ2VyLCBuYS5ybSA9IFRSVUUpLA0KICAgIC5ncm91cHMgPSAiZHJvcCINCiAgKQ0KDQpsaWJyYXJ5KGd0KQ0KbTJfc3VtbWFyeVssYygibm9tX3N1YnNpc3RlbWEueCIsIm1lYW5fcGVuYWx0eSIsImx3ciIsICJ1cHIiKV0gJT4lIGphbml0b3I6OmFkb3JuX3RvdGFscygpICU+JSANCiAgZ3QoKSAlPiUNCiAgZm10X251bWJlcihjb2x1bW5zID0gMjo0LCBkZWNpbWFscyA9IDEpICU+JQ0KICBjb2xzX2xhYmVsKA0KICAgIG5vbV9zdWJzaXN0ZW1hLnggPSAiU3Vic3lzdGVtIiwNCiAgICBtZWFuX3BlbmFsdHkgPSAiU3VtIM6UZ2VyIChNV2gpIiwNCiAgICBsd3IgID0gIkxvd2VyIDk1JSIsDQogICAgdXByICA9ICJVcHBlciA5NSUiLA0KICApICU+JQ0KICB0YWJfaGVhZGVyKA0KICAgIHRpdGxlID0gbWQoIioqQWdncmVnYXRlIGNsaW1hdGUgcGVuYWx0eSBvbiBoaWRyb3Bvd2VyIGVuZXJneSAoMjAwMeKAkzIwMTgpKioiKSwNCiAgICBzdWJ0aXRsZSA9ICJTaW11bGF0ZWQgbWVhbiBhbmQgOTUlIGNvbmZpZGVuY2UgaW50ZXJ2YWxzIHBlciBzdWJzeXN0ZW0iDQogICkNCmBgYA0KDQpBIEZpZ3VyYSBhcHJlc2VudGEgbyByZXN1bHRhZG8gZGEgKipwcm9wYWdhw6fDo28gZGEgcGVuYWxpZGFkZSBjbGltw6F0aWNhIHNvYnJlIGEgZ2VyYcOnw6NvIGhpZHJlbMOpdHJpY2EgKM6UR1xfaGlkcm8pKiosIG9idGlkYSBwZWxhIHN1YnN0aXR1acOnw6NvIGRvIGNsaW1hIG9ic2VydmFkbyBwZWxvIGNsaW1hIG3DqWRpbyBoaXN0w7NyaWNvICgyMDAx4oCTMjAwNSkgbm8gbW9kZWxvIGRlIGFybWF6ZW5hbWVudG8gZSBwZWxhIGFwbGljYcOnw6NvIGRlc3NlcyB2YWxvcmVzIGNvbnRyYWZhY3R1YWlzIG5vIG1vZGVsbyBkZSBnZXJhw6fDo28uIE8gZ3LDoWZpY28gbW9zdHJhIGEgZGlmZXJlbsOnYSBlbnRyZSBhIGdlcmHDp8OjbyBwcmV2aXN0YSBzb2IgY2xpbWEgZWZldGl2byBlIG8gY2Vuw6FyaW8gY29udHJhZmFjdHVhbCBuZXV0cm8sIGNvbSBpbnRlcnZhbG9zIGRlIGNvbmZpYW7Dp2EgY2FsY3VsYWRvcyBwb3IgZHVhcyBhYm9yZGFnZW5zOiBvIG3DqXRvZG8gYW5hbMOtdGljbyAoRGVsdGEpIGUgYSBzaW11bGHDp8OjbyBwYXJhbcOpdHJpY2EuDQoNCk9zIHJlc3VsdGFkb3MgaW5kaWNhbSBxdWUgYSBwZW5hbGlkYWRlIGNsaW3DoXRpY2EgbcOpZGlhIHNvYnJlIGEgZ2VyYcOnw6NvIGhpZHJlbMOpdHJpY2Egc2VndWUgbyBtZXNtbyBwYWRyw6NvIGVzcGFjaWFsIG9ic2VydmFkbyBuYSBlbmVyZ2lhIGFybWF6ZW5hZGEsIG1hcyBjb20gbWFnbml0dWRlIGFtcGxpZmljYWRhIGRldmlkbyDDoCByZXNwb3N0YSBlbMOhc3RpY2EgZG8gZGVzcGFjaG8gaMOtZHJpY28uIE8gKipTdWRlc3RlKiogYXByZXNlbnRhIG8gbWFpb3IgZMOpZmljaXQgbcOpZGlvLCBjb20gcmVkdcOnw7VlcyBhY3VtdWxhZGFzIHN1cGVyaW9yZXMgYSAqKuKAkzQgbWlsaMO1ZXMgZGUgTVfCt23DqnMqKiBlbSBhbm9zIHNlY29zLCByZWZsZXRpbmRvIGEgZm9ydGUgZGVwZW5kw6puY2lhIGRhIGdlcmHDp8OjbyBhbyBuw612ZWwgZGUgcmVzZXJ2YXTDs3Jpb3MuIE8gKipTdWwqKiBtb3N0cmEgcGVuYWxpZGFkZXMgaW50ZXJtZWRpw6FyaWFzIChlbnRyZSDigJMxIGUg4oCTMiBtaWxow7VlcyBkZSBNV8K3bcOqcyksIGNvbSBhbHRhIHZhcmlhYmlsaWRhZGUgaW50ZXJhbnVhbC4gTyAqKk5vcmRlc3RlKiogZSBvICoqTm9ydGUqKiBhcHJlc2VudGFtIG9zY2lsYcOnw7VlcyBtZW5vcmVzLCBtYXMgY29tIHRlbmTDqm5jaWEgbmVnYXRpdmEgYWNlbnR1YWRhIGFww7NzIDIwMTIsIGNvbXBhdMOtdmVsIGNvbSBwZXLDrW9kb3MgZGUgZXN0aWFnZW0gcHJvbG9uZ2FkYS4gIA0KDQpPcyAqKmludGVydmFsb3MgZGUgY29uZmlhbsOnYSoqIHJldmVsYW0gYXVtZW50byBleHByZXNzaXZvIGRhIGluY2VydGV6YSBhcMOzcyAyMDEwLCBxdWFuZG8gYXMgY29uZGnDp8O1ZXMgY2xpbcOhdGljYXMgc2UgdG9ybmFyYW0gbWFpcyB2b2zDoXRlaXMgZSBvcyByZXNlcnZhdMOzcmlvcyBwYXNzYXJhbSBhIG9wZXJhciBwcsOzeGltb3MgZGUgbGltaXRlcyBjcsOtdGljb3MuIEVzc2UgcGFkcsOjbyByZWZvcsOnYSBhIGludGVycHJldGHDp8OjbyBkZSBxdWUgYSAqKnBlbmFsaWRhZGUgY2xpbcOhdGljYSBwcm9wYWdhZGEgw6AgZ2VyYcOnw6NvKiogcmVwcmVzZW50YSBuw6NvIGFwZW5hcyBhIHBlcmRhIGRlIGVzdG9xdWUgaMOtZHJpY28sIG1hcyB0YW1iw6ltIGEgKipkaW1pbnVpw6fDo28gZGEgZmxleGliaWxpZGFkZSBvcGVyYXRpdmEqKiBkbyBzaXN0ZW1hLCB1bSBkb3MgcHJpbmNpcGFpcyBjYW5haXMgZGUgdHJhbnNtaXNzw6NvIGRvcyBlZmVpdG9zIGNsaW3DoXRpY29zIHBhcmEgb3MgY3VzdG9zIGRvIHNldG9yIGVsw6l0cmljby4NCg0KMy4yLjUgUHJvcGFnYcOnw6NvIGNvbmp1bnRhIGRlIGluY2VydGV6YSAozpRFQVIg4oaSIM6UR19oaWRybykNCkVzdGUgYmxvY28gcmVhbGl6YSB1bWEgc2ltdWxhw6fDo28gTW9udGUgQ2FybG8gZW5jYWRlYWRhOiBjYWRhIHNvcnRlaW8gaW5jbHVpIHNpbXVsdGFuZWFtZW50ZSBvcyBjb2VmaWNpZW50ZXMgZG8gbW9kZWxvIGNsaW3DoXRpY28gKG0xX2dhbSkgZSBkbyBtb2RlbG8gaGlkcmVsw6l0cmljbyAobTJfaGlkcm8pLg0KQXNzaW0sIGFzIGluY2VydGV6YXMgZGEgcHJldmlzw6NvIGRvIGFybWF6ZW5hbWVudG8gKEVBUikgc8OjbyB0cmFuc21pdGlkYXMgaW50ZWdyYWxtZW50ZSBwYXJhIGFzIHByZXZpc8O1ZXMgZGUgZ2VyYcOnw6NvLCBwcm9kdXppbmRvIHVtYSBkaXN0cmlidWnDp8OjbyBjb25qdW50YSBwYXJhICTOlPCdkLpfe+KEjvCdkZbwnZGR8J2Rn/CdkZx9JC4gDQoNCg0KIyMjIDMuMi42IFJlc3VsdGFkb3Mg4oCUIFByb3BhZ2HDp8OjbyBpbnRlZ3JhbCBkZSBpbmNlcnRlemEgKM6UR1xfaGlkcm8gY29uanVudG8pIHBhcnRpbmRvIGRvIG0yLS0tLS0tLS0tLS0tLS0tLS0tLS0NCg0KDQoNCmBgYHtyIHJld20xbTItam9pbnQtc2ltdWxhdGlvbiAxLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQ0KbGlicmFyeShNQVNTKQ0KbGlicmFyeShkcGx5cikNCmxpYnJhcnkobHVicmlkYXRlKQ0KDQpzZXQuc2VlZCgyMDI1MTAxMSkNCm5zaW0gPC0gNTAwICAjIHBvZGUgYXVtZW50YXIgZGVwb2lzIHBhcmEgMTAwMCwgbWFzIHRlc3RlIGNvbSA1MDAgcHJpbWVpcm8NCg0KDQojIC0tLSAxLiBDb3ZhcmnDom5jaWFzIGUgc29ydGVpb3MgZG9zIGNvZWZpY2llbnRlcyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tDQpWcDEgPC0gdmNvdihtMV9nYW0pDQpWcDIgPC0gdmNvdihtMl9oaWRybykNCmJldGFfZHJhd3NfMSA8LSBNQVNTOjptdnJub3JtKG4gPSBuc2ltLCBtdSA9IGNvZWYobTFfZ2FtKSwgU2lnbWEgPSBWcDEpDQpiZXRhX2RyYXdzXzIgPC0gTUFTUzo6bXZybm9ybShuID0gbnNpbSwgbXUgPSBjb2VmKG0yX2hpZHJvKSwgU2lnbWEgPSBWcDIpDQoNCiMgLS0tIDIuIE1hdHJpemVzIGRvIG1vZGVsbyAxIChFQVIgfiBjbGltYSkgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQ0KWF9vYnNfZWFyIDwtIHByZWRpY3QobTFfZ2FtLCBuZXdkYXRhID0gbmRfb2JzLCB0eXBlID0gImxwbWF0cml4IikNClhfY2ZfZWFyICA8LSBwcmVkaWN0KG0xX2dhbSwgbmV3ZGF0YSA9IG5kX2NmLCAgdHlwZSA9ICJscG1hdHJpeCIpDQoNCiMgLS0tIDMuIFByb3BhZ2HDp8OjbyBNb250ZSBDYXJsbyBlbmNhZGVhZGEgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0NCmRlbHRhX0dfam9pbnQgPC0gbWF0cml4KE5BX3JlYWxfLCBucm93ID0gbnJvdyhuZF9vYnMpLCBuY29sID0gbnNpbSkNCg0KZm9yIChzIGluIHNlcV9sZW4obnNpbSkpIHsNCiAgIyAxLiBFQVIgZmFjdHVhbCBlIGNvbnRyYWZhY3R1YWwgc2ltdWxhZG9zDQogIGVhcl9mIDwtIGFzLm51bWVyaWMoWF9vYnNfZWFyICUqJSBiZXRhX2RyYXdzXzFbcywgXSkNCiAgZWFyX2MgPC0gYXMubnVtZXJpYyhYX2NmX2VhciAgJSolIGJldGFfZHJhd3NfMVtzLCBdKQ0KICANCiAgIyAyLiBBdHVhbGl6YXIgaW5wdXRzIGRvIG1vZGVsbyBkZSBnZXJhw6fDo28NCiAgbmRfZiA8LSBuZF9vYnMgJT4lDQogICAgbXV0YXRlKGVhcl9yZXNlcnZhdG9yaW9fc3Vic2lzdGVtYV9wcm9wcmlvX213bWVzID0gZWFyX2YpDQogIG5kX2MgPC0gbmRfb2JzICU+JQ0KICAgIG11dGF0ZShlYXJfcmVzZXJ2YXRvcmlvX3N1YnNpc3RlbWFfcHJvcHJpb19td21lcyA9IGVhcl9jKQ0KICANCiAgIyAzLiBQcmVkacOnw7VlcyBjb21wbGV0YXMgZG8gbW9kZWxvIGRlIGdlcmHDp8OjbyAobsOjbyBsaW5lYXIpDQogIGdfZiA8LSBwcmVkaWN0KG0yX2hpZHJvLCBuZXdkYXRhID0gbmRfZiwgdHlwZSA9ICJyZXNwb25zZSIpDQogIGdfYyA8LSBwcmVkaWN0KG0yX2hpZHJvLCBuZXdkYXRhID0gbmRfYywgdHlwZSA9ICJyZXNwb25zZSIpDQogIA0KICAjIDQuIFBlbmFsaWRhZGUgcHJvcGFnYWRhDQogIGRlbHRhX0dfam9pbnRbLCBzXSA8LSBnX2YgLSBnX2MNCiAgcHJpbnQocykNCn0NCg0KDQp3cml0ZV9yZHMoZGVsdGFfR19qb2ludCwgImRlbHRhX0dfam9pbnQucmRzIikNCmBgYA0KDQoNCmBgYHtyIHJld20xbTItam9pbnQtc2ltdWxhdGlvbiAyLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQ0KZGVsdGFfR19qb2ludDwtcmVhZF9yZHMoImRlbHRhX0dfam9pbnQucmRzIikNCmRlbHRhX0dfam9pbnQgJT4lIHN1bW1hcnkoKQ0KYGBgDQoNCg0KYGBge3IgcmV3bTFtMi1qb2ludC1zaW11bGF0aW9uIDMsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9DQojIC0tLSA0LiBBZ3JlZ2FyIHBvciBzdWJzaXN0ZW1hIGUgYW5vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0NCm5kX29icyRZZWFyDQpkdCA8LSBuZF9vYnMgJT4lIHNlbGVjdChZZWFyLCBub21fc3Vic2lzdGVtYS54KQ0KZHQkWWVhcjwtbmRfb2JzJFllYXINCg0KDQpsaWJyYXJ5KGRhdGEudGFibGUpDQpkdCA8LSBhcy5kYXRhLnRhYmxlKGR0KQ0KZ3JvdXBzIDwtIHVuaXF1ZShkdFssIC4oWWVhciwgbm9tX3N1YnNpc3RlbWEueCldKQ0KDQphZ2dfam9pbnQgPC0gbGFwcGx5KHNlcV9sZW4obnJvdyhncm91cHMpKSwgZnVuY3Rpb24oZyl7DQogIGlkeCA8LSB3aGljaChkdCRZZWFyID09IGdyb3VwcyRZZWFyW2ddICYgZHQkbm9tX3N1YnNpc3RlbWEueCA9PSBncm91cHMkbm9tX3N1YnNpc3RlbWEueFtnXSkNCiAgY29sU3VtcyhkZWx0YV9HX2pvaW50W2lkeCwgLCBkcm9wID0gRkFMU0VdLCBuYS5ybSA9IFRSVUUpDQp9KQ0KYWdnX2pvaW50IDwtIGRvLmNhbGwocmJpbmQsIGFnZ19qb2ludCkNCmNvbG5hbWVzKGFnZ19qb2ludCkgPC0gcGFzdGUwKCJzaW1fIiwgMTpuc2ltKQ0KICBhZ2dfZGYgPC0gY2JpbmQoZ3JvdXBzLCBhZ2dfam9pbnQpDQojIC0tLSA1LiBFc3RhdMOtc3RpY2FzIHJlc3VtbyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tDQptMl9qb2ludF9zdW1tYXJ5IDwtIGFnZ19kZiAlPiUNCiAgdGlkeXI6OnBpdm90X2xvbmdlcihjb2xzID0gc3RhcnRzX3dpdGgoInNpbV8iKSwgdmFsdWVzX3RvID0gImRlbHRhX0ciKSAlPiUNCiAgZ3JvdXBfYnkoWWVhciwgbm9tX3N1YnNpc3RlbWEueCkgJT4lDQogIHN1bW1hcmlzZSgNCiAgICBtZWFuID0gbWVhbihkZWx0YV9HLCBuYS5ybSA9IFRSVUUpLA0KICAgIGx3ciAgPSBxdWFudGlsZShkZWx0YV9HLCAwLjAyNSwgbmEucm0gPSBUUlVFKSwNCiAgICB1cHIgID0gcXVhbnRpbGUoZGVsdGFfRywgMC45NzUsIG5hLnJtID0gVFJVRSksDQogICAgLmdyb3VwcyA9ICJkcm9wIg0KICApDQoNCmBgYA0KDQoNCmBgYHtyIG0yLWpvaW50LXBsb3QsIGZpZy5oZWlnaHQ9NiwgZmlnLndpZHRoPTEyLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQ0KbGlicmFyeShnZ3Bsb3QyKQ0KbTJfam9pbnRfc3VtbWFyeSAlPiUNCiAgZ2dwbG90KGFlcyh4ID0gWWVhciwgeSA9IG1lYW4pKSArDQogIGdlb21fcmliYm9uKGFlcyh5bWluID0gbHdyLCB5bWF4ID0gdXByKSwgZmlsbCA9ICJmaXJlYnJpY2siLCBhbHBoYSA9IDAuMykgKw0KICBnZW9tX2xpbmUoY29sb3IgPSAiYmxhY2siKSArDQogIGZhY2V0X3dyYXAofm5vbV9zdWJzaXN0ZW1hLngsIHNjYWxlcyA9ICJmcmVlX3kiKSArDQogIGxhYnModGl0bGUgPSAiSm9pbnQgcHJvcGFnYXRlZCBjbGltYXRlIHBlbmFsdHkgb24gaHlkcm9wb3dlciBnZW5lcmF0aW9uICjOlEdfaGlkcm8pIiwNCiAgICAgICBzdWJ0aXRsZSA9ICJVbmNlcnRhaW50eSBmdWxseSBwcm9wYWdhdGVkIGZyb20gY2xpbWF0ZSDihpIgc3RvcmFnZSDihpIgZ2VuZXJhdGlvbiIsDQogICAgICAgeSA9ICLOlEdfaGlkcm8gKE1Xwrdtb250aCkiLCB4ID0gIlllYXIiKSArDQogIHRoZW1lX21pbmltYWwoKQ0KYGBgDQoNCg0KYGBge3IgbTItam8gZ2lnaW50LXBsb3QsIGZpZy5oZWlnaHQ9NiwgZmlnLndpZHRoPTEyLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQ0KbGlicmFyeShnZ3Bsb3QyKQ0KbTJfam9pbnRfc3VtbWFyeSAlPiUNCiAgZ2dwbG90KGFlcyh4ID0gWWVhciwgeSA9IG1lYW4vMTAwMCkpICsNCiAgZ2VvbV9yaWJib24oYWVzKHltaW4gPSBsd3IvMTAwMCwgeW1heCA9IHVwci8xMDAwKSwgZmlsbCA9ICJzdGVlbGJsdWUiLCBhbHBoYSA9IDEpICsNCiAgICBnZW9tX3JpYmJvbihhZXMoeW1pbiA9IDAsIHltYXggPSB1cHIvMTAwMCksIGZpbGwgPSAiZmlyZWJyaWNrIiwgYWxwaGEgPSAwLjEpICsNCg0KICBnZW9tX2xpbmUoY29sb3IgPSAiYmxhY2siKSArDQogIGZhY2V0X3dyYXAofm5vbV9zdWJzaXN0ZW1hLngsIHNjYWxlcyA9ICJmcmVlX3kiKSArDQogIGxhYnModGl0bGUgPSAiSm9pbnQgcHJvcGFnYXRlZCBjbGltYXRlIHBlbmFsdHkgb24gaHlkcm9wb3dlciBnZW5lcmF0aW9uICjOlEdfaGlkcm8pIiwNCiAgICAgICBzdWJ0aXRsZSA9ICJVbmNlcnRhaW50eSBmdWxseSBwcm9wYWdhdGVkIGZyb20gY2xpbWF0ZSDihpIgc3RvcmFnZSDihpIgZ2VuZXJhdGlvbiIsDQogICAgICAgeSA9ICLOlEdfaGlkcm8gKEdXwrdtb250aCkiLCB4ID0gIlllYXIiKSArDQogIHRoZW1lX21pbmltYWwoKQ0KYGBgDQoNCkEgRmlndXJhIGFwcmVzZW50YSBhICoqcGVuYWxpZGFkZSBjbGltw6F0aWNhIHNvYnJlIGEgZ2VyYcOnw6NvIGhpZHJlbMOpdHJpY2EgKM6UR1xfaGlkcm8pKiogZXN0aW1hZGEgY29tICoqcHJvcGFnYcOnw6NvIGNvbmp1bnRhIGRlIGluY2VydGV6YSoqIGFvIGxvbmdvIGRlIHRvZGEgYSBjYWRlaWEgY2xpbWF0by1oaWRyb2zDs2dpY2EuIERpZmVyZW50ZW1lbnRlIGRhcyBhYm9yZGFnZW5zIHF1ZSB0cmF0YW0gb3MgbW9kZWxvcyBkZSBmb3JtYSBpbmRlcGVuZGVudGUsIGVzdGEgc2ltdWxhw6fDo28gaW5jb3Jwb3JhIHNpbXVsdGFuZWFtZW50ZSBhIGluY2VydGV6YSBkb3MgY29lZmljaWVudGVzIGRvIG1vZGVsbyBjbGltw6F0aWNvIChFQVIgfiBjbGltYSkgZSBkbyBtb2RlbG8gaGlkcmVsw6l0cmljbyAoZ2VyYcOnw6NvIH4gRUFSKSwgZ2VyYW5kbyB1bWEgZGlzdHJpYnVpw6fDo28gY29uanVudGEgZGUgcmVzdWx0YWRvcy4gQ2FkYSB0cmFqZXTDs3JpYSBNb250ZSBDYXJsbyByZXByZXNlbnRhIHVtYSBjb21iaW5hw6fDo28gcGxhdXPDrXZlbCBkZSBwYXLDom1ldHJvcyBlIGNvbmRpw6fDtWVzIGNsaW3DoXRpY2FzLCBwZXJtaXRpbmRvIGNhcHR1cmFyIGEgdmFyaWFiaWxpZGFkZSBlc3RydXR1cmFsIGUgY2xpbcOhdGljYSBkbyBzaXN0ZW1hLg0KDQpPcyByZXN1bHRhZG9zIG1vc3RyYW0gcXVlIGEgaW5jZXJ0ZXphIHByb3BhZ2FkYSBhbXBsaWEgb3MgaW50ZXJ2YWxvcyBkZSBjb25maWFuw6dhIGRhcyBlc3RpbWF0aXZhcyBhbnVhaXMgZGUgzpRHXF9oaWRybywgcHJpbmNpcGFsbWVudGUgYXDDs3MgMjAxMCwgcXVhbmRvIGEgdmFyaWFiaWxpZGFkZSBjbGltw6F0aWNhIGUgb3BlcmFjaW9uYWwgYXVtZW50YSBzaWduaWZpY2F0aXZhbWVudGUuIE8gKipzdWJzaXN0ZW1hIFN1ZGVzdGUqKiBjb25jZW50cmEgYXMgbWFpb3JlcyBwZXJkYXMgbcOpZGlhcyAoYXTDqSDigJM0LDUgw5cgMTDigbYgTVfCt23DqnMpIGUgYSBtYWlvciBkaXNwZXJzw6NvIGludGVyYW51YWwsIHJlZmxldGluZG8gdGFudG8gYSBtYWduaXR1ZGUgZGUgc3VhIGNhcGFjaWRhZGUgZGUgYXJtYXplbmFtZW50byBxdWFudG8gc3VhIGV4cG9zacOnw6NvIGEgc2VjYXMgcHJvbG9uZ2FkYXMuIE8gKipTdWwqKiBhcHJlc2VudGEgcGVuYWxpZGFkZXMgbWVub3JlcywgbWFzIGNvbSBhbXBsaXR1ZGVzIGRlIGluY2VydGV6YSBlbGV2YWRhcywgY29lcmVudGVzIGNvbSBzdWEgaW5zdGFiaWxpZGFkZSBoaWRyb2zDs2dpY2EuICoqTm9yZGVzdGUqKiBlICoqTm9ydGUqKiBtb3N0cmFtIG1lbm9yZXMgZMOpZmljaXRzIGFic29sdXRvcywgbWFzIGNvbSB0ZW5kw6puY2lhIG5lZ2F0aXZhIGNvbnTDrW51YS4gIA0KRXNzZXMgcmVzdWx0YWRvcyByZXByZXNlbnRhbSBhIGVzdGltYXRpdmEgbWFpcyBjb21wbGV0YSBkZSAqKmltcGFjdG8gY2xpbcOhdGljbyBwcm9wYWdhZG8gbm8gc2lzdGVtYSBlbMOpdHJpY28qKiwgcG9pcyBpbnRlZ3JhbSBpbmNlcnRlemFzIGNsaW3DoXRpY2FzLCBoaWRyb2zDs2dpY2FzIGUgb3BlcmFjaW9uYWlzIGRlbnRybyBkZSB1bWEgbWVzbWEgZXN0cnV0dXJhIHByb2JhYmlsw61zdGljYS4NCg0KDQpgYGB7cn0NCm0yX3N1bW1hcnkgPC0gbTJfam9pbnRfc3VtbWFyeSAlPiUNCiAgZ3JvdXBfYnkobm9tX3N1YnNpc3RlbWEueCkgJT4lDQogIHN1bW1hcmlzZSgNCiAgICBtZWFuX3BlbmFsdHkgPSBtZWFuKG1lYW4sIG5hLnJtID0gVFJVRSksDQogICAgbHdyXzk1ID0gbWVhbihsd3IsIG5hLnJtID0gVFJVRSksDQogICAgdXByXzk1ID0gbWVhbih1cHIsIG5hLnJtID0gVFJVRSksDQogICAgc2RfcGVuYWx0eSA9IHNkKG1lYW4sIG5hLnJtID0gVFJVRSksDQogICAgLmdyb3VwcyA9ICJkcm9wIg0KICApDQoNCiMgQ29udmVydGVuZG8gcGFyYSBHV2gvYW5vIHBhcmEgaW50ZXJwcmV0YcOnw6NvDQptMl9zdW1tYXJ5IDwtIG0yX3N1bW1hcnkgJT4lDQogIG11dGF0ZSgNCiAgICBtZWFuX0dXaCA9IG1lYW5fcGVuYWx0eSAvIDEwMDAsDQogICAgbHdyX0dXaCAgPSBsd3JfOTUgLyAxMDAwLA0KICAgIHVwcl9HV2ggID0gdXByXzk1IC8gMTAwMCwNCiAgKSAjJT4lIHNlbGVjdCgtbWVhbl9wZW5hbHR5LCAtbHdyXzk1LCAtdXByXzk1KQ0KDQojIFRhYmVsYSBmb3JtYXRhZGEgKHB1YmxpY2HDp8OjbykNCmxpYnJhcnkoZ3QpDQptMl9zdW1tYXJ5WyxjKCJub21fc3Vic2lzdGVtYS54IiwibWVhbl9HV2giLCJsd3JfR1doIiwgInVwcl9HV2giKV0gJT4lIGphbml0b3I6OmFkb3JuX3RvdGFscygpICU+JSANCiAgZ3QoKSAlPiUNCiAgZm10X251bWJlcihjb2x1bW5zID0gMjo0LCBkZWNpbWFscyA9IDEpICU+JQ0KICBjb2xzX2xhYmVsKA0KICAgIG5vbV9zdWJzaXN0ZW1hLnggPSAiU3Vic3lzdGVtIiwNCiAgICBtZWFuX0dXaCA9ICJNZWFuIM6UR19oaWRybyAoR1doKSIsDQogICAgbHdyX0dXaCAgPSAiTG93ZXIgOTUlIiwNCiAgICB1cHJfR1doICA9ICJVcHBlciA5NSUiLA0KICApICU+JQ0KICB0YWJfaGVhZGVyKA0KICAgIHRpdGxlID0gbWQoIioqQWdncmVnYXRlIGNsaW1hdGUgcGVuYWx0eSBvbiBIaWRyaWMgR2VuZXJhdGlvbiAoMjAwMeKAkzIwMTgpKioiKSwNCiAgICBzdWJ0aXRsZSA9ICJTaW11bGF0ZWQgbWVhbiBhbmQgOTUlIGNvbmZpZGVuY2UgaW50ZXJ2YWxzIHBlciBzdWJzeXN0ZW0iDQogICkNCmBgYA0KDQoNCiMgMy4zIE1vZGVsbyAzIOKAlCBHZXJhw6fDo28gVGVybWljYSAgY29tbyBGdW7Dp8OjbyBkYSBHZXJhw6fDo28gSGlkcmVsw6l0cmljYQ0KDQpgYGB7cn0NCmdlciAlPiVtdXRhdGUodXNpbmFfZm9udGU9cGFzdGUwKCJnZXJfIixub21fdGlwb3VzaW5hKSkgJT4lIA0KICBmaWx0ZXIoIW5vbV9zdWJzaXN0ZW1hPT0iUEFSQUdVQUkiKSAlPiUgIywiXyIsbm9tX3RpcG91c2luYSkpICU+JSANCiAgbXV0YXRlKHVzaW5hX2ZvbnRlPWNhc2Vfd2hlbih1c2luYV9mb250ZT09Imdlcl9CT01CRUFNRU5UTyJ+Imdlcl9ISURST0VMw4lUUklDQSIsDQogICAgICAgICAgICAgICAgICAgVFJVRX51c2luYV9mb250ZSkpICU+JSAjLCJfIixub21fdGlwb3VzaW5hKSkgJT4lIA0KDQogIGdyb3VwX2J5KGRhdGUsbm9tX3N1YnNpc3RlbWEsdXNpbmFfZm9udGUsdmFsX2dlcmFjYW9fZGF5X3N1YnNpc3RlbWEpICU+JSANCiAgc3VtbWFyaXNlKGdlcj1zdW0odmFsX2dlcmFjYW8sbmEucm0gPSBUKSkgJT4lIHVuZ3JvdXAoKSAlPiUgDQogIHNwcmVhZCh1c2luYV9mb250ZSxnZXIsZmlsbCA9IDApICU+JSBqYW5pdG9yOjpjbGVhbl9uYW1lcygpICU+JSANCiAgbXV0YXRlKCktPmdlcmFfZW5lcmdfZGF5DQpnZXJhX2VuZXJnX2RheSRkb3kgICAgPC0gbHVicmlkYXRlOjp5ZGF5KGdlcmFfZW5lcmdfZGF5JGRhdGUpDQpnZXJhX2VuZXJnX2RheSRkb3cgICAgPC0gbHVicmlkYXRlOjp3ZGF5KGdlcmFfZW5lcmdfZGF5JGRhdGUsIGxhYmVsPVRSVUUsIGFiYnI9VFJVRSkNCmdlcmFfZW5lcmdfZGF5JG1vbnRoICA8LSBsdWJyaWRhdGU6Om1vbnRoKGdlcmFfZW5lcmdfZGF5JGRhdGUpDQpnZXJhX2VuZXJnX2RheSR0cmVuZCAgPC0gbHVicmlkYXRlOjp5ZWFyKGdlcmFfZW5lcmdfZGF5JGRhdGUpDQpgYGANCg0KTyBNb2RlbG8gMyBlc3RpbWEgYSByZXNwb3N0YSBkYSBnZXJhw6fDo28gdMOpcm1pY2Egw6BzIHZhcmlhw6fDtWVzIG5hIGdlcmHDp8OjbyBoaWRyZWzDqXRyaWNhLCBpbmNvcnBvcmFuZG8gYSBjb21wZXRpw6fDo28gY29tIG91dHJhcyBmb250ZXMgZSBvIGNpY2xvIHNhem9uYWwgZGUgZGVtYW5kYS4gTyBtb2RlbG8gYWRpdGl2byBnZW5lcmFsaXphZG8gKEdBTSkgZm9pIGFqdXN0YWRvIHBhcmEgbyBwZXLDrW9kbyAyMDAw4oCTMjAxOSwgY29tIGVzdHJ1dHVyYSBzZW1pcGFyYW3DqXRyaWNhIHF1ZSBwZXJtaXRlIGNhcHR1cmFyIHJlbGHDp8O1ZXMgbsOjbyBsaW5lYXJlcyBlbnRyZSBhcyBmb250ZXMgZGUgZ2VyYcOnw6NvIGUgc2V1cyBkZXRlcm1pbmFudGVzIHRlbXBvcmFpcy4NCk9zIHJlc3VsdGFkb3MgaW5kaWNhbSB1bWEgcmVsYcOnw6NvIG5lZ2F0aXZhIGUgZXN0YXRpc3RpY2FtZW50ZSBzaWduaWZpY2F0aXZhIGVudHJlIGdlcmHDp8OjbyBoaWRyZWzDqXRyaWNhIGUgdMOpcm1pY2EsIGV2aWRlbmNpYW5kbyBvIHBhcGVsIGRhIHTDqXJtaWNhIGNvbW8gbWVjYW5pc21vIGRlIGNvbXBlbnNhw6fDo28gZHVyYW50ZSBwZXLDrW9kb3MgZGUgZXNjYXNzZXogaMOtZHJpY2EuIE8gZWZlaXRvIG1hcmdpbmFsIGRlIGdlcl9oaWRyb2VsZXRyaWNhIMOpIGZvcnRlbWVudGUgbsOjbyBsaW5lYXIsIGNvbSByZXNwb3N0YXMgbWFpcyBpbnRlbnNhcyBlbSBmYWl4YXMgaW50ZXJtZWRpw6FyaWFzIGRlIHJlZHXDp8OjbywgbyBxdWUgc3VnZXJlIHF1ZSBvIGRlc3BhY2hvIHTDqXJtaWNvIGF0aW5nZSBsaW1pdGVzIGVzdHJ1dHVyYWlzIGRlIGV4cGFuc8OjbyBlbSBhbm9zIGRlIHNlY2Egc2V2ZXJhLg0KDQpgYGB7cn0NCmxpYnJhcnkobWdjdikNCmxpYnJhcnkoZHBseXIpDQoNCiMgLS0tIFByZXBhcmHDp8OjbyBkb3MgZGFkb3MgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tDQpnZXJhX2VuZXJnX2RheSA8LSBnZXJhX2VuZXJnX2RheSAlPiUNCiAgbXV0YXRlKA0KICAgIERlbWFuZGEgPSBnZXJfZW9saWVsZXRyaWNhICsgZ2VyX2ZvdG92b2x0YWljYSArIGdlcl9oaWRyb2VsZXRyaWNhICsgZ2VyX3Rlcm1pY2EgKyBnZXJfbnVjbGVhciwNCiAgICBtb250aCA9IGFzLm51bWVyaWMoZm9ybWF0KGRhdGUsICIlbSIpKSwNCiAgICB0cmVuZCA9IGFzLm51bWVyaWMoZGF0ZSAtIG1pbihkYXRlKSkgLyAzMCAgIyB0ZW5kw6puY2lhIGxpbmVhciBlbSBtZXNlcw0KICApDQoNCiMgLS0tIE1vZGVsbyBHQU0gMzogR2VyYcOnw6NvIFTDqXJtaWNhIGNvbW8gZnVuw6fDo28gZGEgSGlkcm8gKyBvdXRyYXMgZm9udGVzIC0tLS0tDQptM19nYW1fdGVybWljYSA8LSBiYW0oDQogIGdlcl90ZXJtaWNhIH4gDQogICAgcyhnZXJfaGlkcm9lbGV0cmljYSwgayA9IDQpICsgICAgIyBwcmluY2lwYWwgZWZlaXRvIHN1YnN0aXR1dGl2bw0KICAgIHMoZ2VyX2VvbGllbGV0cmljYSwgayA9IDQpICsNCiAgICBzKGdlcl9mb3Rvdm9sdGFpY2EsIGsgPSA0KSArDQogICAgcyhnZXJfbnVjbGVhciwgayA9IDMpICsNCiAgICBzKHRyZW5kLCBrID0gMykgKw0KICAgIHMobW9udGgsIGJzID0gImNjIiwgayA9IDQpICsgICAgICMgcGFkcsOjbyBzYXpvbmFsDQogICAgcyhub21fc3Vic2lzdGVtYSwgYnMgPSAicmUiKSwgICMgZWZlaXRvIGFsZWF0w7NyaW8gcG9yIHN1YnNpc3RlbWENCiAgZGF0YSA9IGdlcmFfZW5lcmdfZGF5LA0KICBtZXRob2QgPSAiZlJFTUwiLA0KICBkaXNjcmV0ZSA9IFRSVUUsDQogIGZhbWlseSA9IGdhdXNzaWFuKCksDQogIG5hLmFjdGlvbiA9IG5hLmV4Y2x1ZGUNCikNCg0Kc3VtbWFyeShtM19nYW1fdGVybWljYSkNCg0KYGBgDQoNCmBgYHtyfQ0Kc3VtbWFyeShtM19nYW1fdGVybWljYSkNCmd0c3VtbWFyeTo6dGJsX3JlZ3Jlc3Npb24obTNfZ2FtX3Rlcm1pY2EpDQpzdW1tYXJ5KG0zX2dhbV90ZXJtaWNhKQ0KZ2FtLmNoZWNrKG0zX2dhbV90ZXJtaWNhKSAgICAgICAgICAjIHJlc8OtZHVvcywgUVEsIGstaW5kZXgNCmNvbmN1cnZpdHkobTNfZ2FtX3Rlcm1pY2EsIGZ1bGw9VFJVRSkNCnBsb3QobTNfZ2FtX3Rlcm1pY2EsIHBhZ2VzPTQsIHNjaGVtZT0xLCBzaGFkZT1UUlVFLCBzZT1UUlVFKQ0KYGBgDQoNCg0KJPCdkZTwnZGS8J2RnyDwnZGh8J2RkvCdkZ/wnZGa8J2RlvCdkZDwnZGOX/CdkaE98J2Rk18xKPCdkZTwnZGSX2jwnZGW8J2RkfCdkZ/wnZGcX/CdkaEpK/CdkZNfMijwnZGU8J2RkvCdkZ9f8J2RkvCdkZzwnZGZ8J2RlvCdkZDwnZGOX/CdkaEpK/CdkZNfMyjwnZGU8J2RkvCdkZ9f8J2RoPCdkZzwnZGZ8J2RjvCdkZ9f8J2RoSkrX/CdkZNfNCjwnZGU8J2RkvCdkZ9f8J2Rm/CdkaLwnZGQ8J2RmfCdkZLwnZGO8J2Rn/CdkaEpK/CdkZNfNSjwnZGh8J2Rn/CdkZLwnZGb8J2RkV/wnZGhKSvwnZGTXzYo8J2RmvCdkZzwnZGb8J2RoeKEjl/wnZGhKSvwnZGi8J2RoPCdkaLwnZGP8J2RoPCdkZbwnZGg8J2RofCdkZLwnZGa8J2RjivwnZyAJA0KKlF1YWxpZGFkZSBkbyBhanVzdGUqDQoNCk8gbW9kZWxvIGFwcmVzZW50YSBSwrIgYWp1c3RhZG8gZGUgMCw2NCBlIGRldmlhbmNlIGV4cGxpY2FkYSBkZSA2NCwxJSwgaW5kaWNhbmRvIGJvYSBjYXBhY2lkYWRlIHByZWRpdGl2YSBkaWFudGUgZGEgYWx0YSB2YXJpYWJpbGlkYWRlIGludGVyZGnDoXJpYS4gVG9kb3Mgb3MgZWZlaXRvcyBzdWF2ZXMgc8OjbyBhbHRhbWVudGUgc2lnbmlmaWNhdGl2b3MgKHAgPCAwLjAwMSksIGNvbSBleGNlw6fDo28gZG8gaW50ZXJjZXB0by4gTyBoaXN0b2dyYW1hIGUgbyBRUS1wbG90IGRvcyByZXPDrWR1b3MgbW9zdHJhbSBkaXN0cmlidWnDp8OjbyBhcHJveGltYWRhbWVudGUgbm9ybWFsLCBjb20gbGV2ZSBhc3NpbWV0cmlhIG5hcyBjYXVkYXMg4oCUIHJlZmxleG8gZGUgcGljb3MgZGUgZGVzcGFjaG8gdMOpcm1pY28gZW0gcGVyw61vZG9zIGRlIHNlY2Egc2V2ZXJhLg0KDQpPIGdyw6FmaWNvIOKAnFJlc8OtZHVvcyB2cy4gVmFsb3JlcyBBanVzdGFkb3PigJ0gcmV2ZWxhIGRpc3BlcnPDo28gY3Jlc2NlbnRlIGNvbSBvIGF1bWVudG8gZGEgZ2VyYcOnw6NvIHByZXZpc3RhLCBzdWdlcmluZG8gaGV0ZXJvY2VkYXN0aWNpZGFkZSBtb2RlcmFkYSBhc3NvY2lhZGEgYSByZWdpbWVzIGRpc3RpbnRvcyBkZSBvcGVyYcOnw6NvIChiYXNlIMOXIHBpY28pLiBBaW5kYSBhc3NpbSwgb3MgcmVzw61kdW9zIHPDo28gY2VudHJhZG9zIGUgc2VtIHBhZHLDo28gc2lzdGVtw6F0aWNvLCBjb25maXJtYW5kbyBhIGFkZXF1YcOnw6NvIGdlcmFsIGRhIGVzcGVjaWZpY2HDp8Ojby4NCg0KKkVmZWl0b3MgcGFyY2lhaXMqDQoNCk9zIGVmZWl0b3MgbWFyZ2luYWlzIGVzdGltYWRvcyBleGliZW0gY29tcG9ydGFtZW50b3MgY29lcmVudGVzIGNvbSBhIGzDs2dpY2EgZsOtc2ljYSBkbyBzaXN0ZW1hOg0KDQotIHMoZ2VyX2hpZHJvZWxldHJpY2EpIOKGkiBmb3J0ZSByZWxhw6fDo28gaW52ZXJzYSBlIG7Do28gbGluZWFyOiByZWR1w6fDtWVzIG5hIGdlcmHDp8OjbyBow61kcmljYSBhdW1lbnRhbSBhIGdlcmHDp8OjbyB0w6lybWljYSwgZXNwZWNpYWxtZW50ZSBlbSBmYWl4YXMgaW50ZXJtZWRpw6FyaWFzIGRlIG9wZXJhw6fDo28gKHN1YnN0aXR1acOnw6NvIGVzdHJ1dHVyYWwpLiBFbSBuw612ZWlzIGV4dHJlbW9zLCBvIGVmZWl0byBzZSBlc3RhYmlsaXphLCBpbmRpY2FuZG8gbGltaXRlIGRlIGRlc3BhY2hvIHTDqXJtaWNvLg0KDQotcyhnZXJfZW9saWVsZXRyaWNhKSBlIHMoZ2VyX2ZvdG92b2x0YWljYSkg4oaSIGFtYmFzIGFwcmVzZW50YW0gZWZlaXRvcyBzdWJzdGl0dXRpdm9zIG5lZ2F0aXZvcywgZXZpZGVuY2lhbmRvIG8gcGFwZWwgZGFzIHJlbm92w6F2ZWlzIG5hIG1pdGlnYcOnw6NvIGRvIHVzbyB0w6lybWljby4NCg0KLSBzKGdlcl9udWNsZWFyKSDihpIgcmVsYcOnw6NvIGxldmVtZW50ZSBjw7RuY2F2YSwgZXN0w6F2ZWwsIHJlZmxldGluZG8gZGVzcGFjaG8gcHJhdGljYW1lbnRlIGZpeG8uDQoNCi0gcyh0cmVuZCkg4oaSIHRlbmTDqm5jaWEgYXNjZW5kZW50ZSwgaW5kaWNhbmRvIGF1bWVudG8gZ3JhZHVhbCBkYSBiYXNlIHTDqXJtaWNhIG5vIGxvbmdvIHByYXpvLCBjb2VyZW50ZSBjb20gYSBleHBhbnPDo28gZGUgdGVybWVsw6l0cmljYXMgZW50cmUgMjAwNeKAkzIwMTUuDQoNCi0gcyhtb250aCkg4oaSIHBhZHLDo28gcXVhc2UgcGxhbm8sIGNvbSBmcmFjYSBzYXpvbmFsaWRhZGUgcmVzaWR1YWwgYXDDs3MgbyBjb250cm9sZSBoaWRyb2zDs2dpY28uDQoNCi0gRWZlaXRvIGFsZWF0w7NyaW8gKG5vbV9zdWJzaXN0ZW1hKSDihpIgbyBhanVzdGUgY29uZmlybWEgZGlmZXJlbsOnYXMgZXN0cnV0dXJhaXMgcmVnaW9uYWlzOiBzdWJzaXN0ZW1hcyBkbyBTdWRlc3RlIGUgU3VsIGV4aWJlbSBtYWlvciBpbnRlbnNpZGFkZSB0w6lybWljYSByZWxhdGl2YSBxdWUgTm9ydGUgZSBOb3JkZXN0ZS4NCg0KKlPDrW50ZXNlKg0KTyBtb2RlbG8gY29uZmlybWEgbyBwYXBlbCBjb250cmFjw61jbGljbyBkYSBnZXJhw6fDo28gdMOpcm1pY2Egbm8gc2lzdGVtYSBlbMOpdHJpY28gYnJhc2lsZWlybzoNCnF1YW5kbyBvIGNsaW1hIHJlZHV6IGEgZ2VyYcOnw6NvIGjDrWRyaWNhLCBhIHJlc3Bvc3RhIHTDqXJtaWNhIGNvbXBlbnNhIHBhcnRlIGRvIGTDqWZpY2l0LCBjb20gc2Vuc2liaWxpZGFkZSBuw6NvIGxpbmVhciBlIGxpbWl0ZXMgb3BlcmFjaW9uYWlzIGRlZmluaWRvcy4NCg0KQSBlc3RydXR1cmEgc3Vhdml6YWRhIGRvcyBlZmVpdG9zIHBlcm1pdGUgcXVhbnRpZmljYXIgYSBlbGFzdGljaWRhZGUgbWFyZ2luYWwgZW50cmUgZm9udGVzLCBxdWUgc2Vyw6EgdXNhZGEgbmEgcHLDs3hpbWEgZXRhcGEgcGFyYSBlc3RpbWFyIGEgcGVuYWxpZGFkZSB0w6lybWljYSBwcm9wYWdhZGEgKM6UR190ZXJtKSByZXN1bHRhbnRlIGRhIHBlbmFsaWRhZGUgaMOtZHJpY2EgKM6UR19oaWRybykgb2J0aWRhIG5vIE1vZGVsbyANCg0KDQojIyBQcmVkacOnw7VlcyBmYWN0dWFsIHZzLiBjb250cmFmYWN0dWFsIChwcm9wYWdhw6fDo28gZGUgaW5jZXJ0ZXphKQ0KDQoNCmBgYHtyfQ0KIyAtLS0gUHJlZGnDp8O1ZXMgZmFjdHVhbCBlIGNvbnRyYWZhY3R1YWwgLS0tDQpzZXQuc2VlZCgyMDI1MTAxMykNCm5zaW0gPC0gNTAgICMgbsO6bWVybyBkZSBzaW11bGHDp8O1ZXMgY29uanVudGFzDQoNCiMgLS0tIDEuIE1hdHJpeiBkZSBjb3ZhcmnDom5jaWEgZGUgY2FkYSBtb2RlbG8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tDQojIC0tLSBDb3ZhcmnDom5jaWFzIGUgc29ydGVpb3MgZGUgY29lZmljaWVudGVzIC0tLQ0KVnAxIDwtIHZjb3YobTFfZ2FtKSAgICAgICAgICAgICAgICAgICMgTTE6IEVBUiB+IGNsaW1hDQpWcDIgPC0gdmNvdihtMl9oaWRybykgICAgICAgICAgICAgICAgIyBNMjogR19oaWRybyB+IEVBUg0KVnAzIDwtIHZjb3YobTNfZ2FtX3Rlcm1pY2EpICAgICAgICAgICMgTTM6IEdfdGVybSB+IEdfaGlkcm8gKyBjb250cm9sZXMNCg0KYjEgPC0gTUFTUzo6bXZybm9ybShuc2ltLCBjb2VmKG0xX2dhbSksICAgICAgICAgVnAxKQ0KYjIgPC0gTUFTUzo6bXZybm9ybShuc2ltLCBjb2VmKG0yX2hpZHJvKSwgICAgICAgVnAyKQ0KYjMgPC0gTUFTUzo6bXZybm9ybShuc2ltLCBjb2VmKG0zX2dhbV90ZXJtaWNhKSwgVnAzKQ0KIyAtLS0gMi4gTWF0cml6ZXMgZGUgZGVzaWduIGRvIG1vZGVsbyAxIChjbGltYSDihpIgRUFSKSAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQ0KWDFfb2JzIDwtIHByZWRpY3QobTFfZ2FtLCBuZXdkYXRhID0gbmRfb2JzLCB0eXBlID0gImxwbWF0cml4IikNClgxX2NmICA8LSBwcmVkaWN0KG0xX2dhbSwgbmV3ZGF0YSA9IG5kX2NmLCAgdHlwZSA9ICJscG1hdHJpeCIpDQpkZWx0YV9HdGVybV9tYXQgIDwtIG1hdHJpeChOQV9yZWFsXywgbnJvdyA9IG5yb3coZ2VyYV9lbmVyZ19kYXkpLCBuY29sID0gbnNpbSkNCg0KIyBQcmVwYXJhIGNoYXZlcyBwYXJhIGFncmVnYcOnw6NvIE0y4oaSTTMNCmtleXNfbTIgPC0gcmVzZXJ2ICU+JSBzZWxlY3QoZGF0ZSwgbm9tX3N1YnNpc3RlbWEueCkgJT4lIGFzLmRhdGEuZnJhbWUoKQ0Ka2V5c19tMyA8LSBnZXJhX2VuZXJnX2RheSAlPiUgc2VsZWN0KGRhdGUsIG5vbV9zdWJzaXN0ZW1hKSAlPiUgYXMuZGF0YS5mcmFtZSgpDQoNCg0KYGBgDQoNCg0KYGBge3J9DQojIC0tLSA1LiBMb29wIHByaW5jaXBhbCBkZSBwcm9wYWdhw6fDo28gTW9udGUgQ2FybG8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0NCmZvciAocyBpbiBzZXFfbGVuKG5zaW0pKSB7DQogICMgPT09PT0gKDEpIEVBUiBmYWN0dWFsIGUgY29udHJhZmFjdHVhbCAoTTEpIG5vIG7DrXZlbCBkZSByZXNlcnZhdMOzcmlvw5dkaWENCiAgZWFyX2YgPC0gYXMubnVtZXJpYyhYMV9vYnMgJSolIGIxW3MsIF0pDQogIGVhcl9jIDwtIGFzLm51bWVyaWMoWDFfY2YgICUqJSBiMVtzLCBdKQ0KDQogICMgPT09PT0gKDIpIFByZWRpw6fDo28gZGUgR19oaWRybyBmYWN0dWFsIGUgY2YgKE0yKSBubyBuw612ZWwgZGUgcmVzZXJ2YXTDs3Jpb8OXZGlhDQogIG5kMl9mIDwtIHJlc2VydiAlPiUgbXV0YXRlKGVhcl9yZXNlcnZhdG9yaW9fc3Vic2lzdGVtYV9wcm9wcmlvX213bWVzID0gZWFyX2YpDQogIG5kMl9jIDwtIHJlc2VydiAlPiUgbXV0YXRlKGVhcl9yZXNlcnZhdG9yaW9fc3Vic2lzdGVtYV9wcm9wcmlvX213bWVzID0gZWFyX2MpDQoNCiAgWDJfZiA8LSBwcmVkaWN0KG0yX2hpZHJvLCBuZXdkYXRhID0gbmQyX2YsIHR5cGUgPSAibHBtYXRyaXgiKQ0KICBYMl9jIDwtIHByZWRpY3QobTJfaGlkcm8sIG5ld2RhdGEgPSBuZDJfYywgdHlwZSA9ICJscG1hdHJpeCIpDQoNCiAgZ19oX2ZfcmVzIDwtIGFzLm51bWVyaWMoWDJfZiAlKiUgYjJbcywgXSkgICMgcG9yIHJlc2VydmF0w7NyaW/Dl2RpYQ0KICBnX2hfY19yZXMgPC0gYXMubnVtZXJpYyhYMl9jICUqJSBiMltzLCBdKQ0KDQogICMgPT09PT0gKDMpIEFncmVnYXIgR19oaWRybyBwb3Igc3Vic2lzdGVtYcOXZGlhIChwYXJhIGFsaW1lbnRhciBNMykNCiAgZGZfaCA8LSBkYXRhLmZyYW1lKGRhdGUgPSBrZXlzX20yJGRhdGUsDQogICAgICAgICAgICAgICAgICAgICBzdWJzID0ga2V5c19tMiRub21fc3Vic2lzdGVtYS54LA0KICAgICAgICAgICAgICAgICAgICAgZ19oX2YgPSBnX2hfZl9yZXMsDQogICAgICAgICAgICAgICAgICAgICBnX2hfYyA9IGdfaF9jX3JlcykNCg0KICBnX2hfYWdnIDwtIGRmX2ggfD4NCiAgICBncm91cF9ieShkYXRlLCBzdWJzKSB8Pg0KICAgIHN1bW1hcmlzZShnX2hfZiA9IHN1bShnX2hfZiwgbmEucm0gPSBUUlVFKSwNCiAgICAgICAgICAgICAgZ19oX2MgPSBzdW0oZ19oX2MsIG5hLnJtID0gVFJVRSksIC5ncm91cHMgPSAiZHJvcCIpDQoNCiAgIyDOlEdfaGlkcm9fY2xpbWEgKHN1YnNpc3RlbWHDl2RpYSkNCiAgZ19oX2FnZyA8LSBnX2hfYWdnIHw+DQogICAgbXV0YXRlKGRlbHRhX2dfaGlkcm9fY2xpbWEgPSBnX2hfZiAtIGdfaF9jKQ0KDQogICMgPT09PT0gKDQpIENvbnN0cnVpciBpbnB1dCBkbyBNMw0KICAjIGZhY3R1YWw6IHVzYSBhIGhpZHJlbMOpdHJpY2Egb2JzZXJ2YWRhIChnZXJhX2VuZXJnX2RheSRnZXJfaGlkcm9lbGV0cmljYSkNCiAgIyBjb250cmFmYWN0dWFsOiBvYnMg4oiSIM6UR19oaWRyb19jbGltYQ0KICBuZDMgPC0gZ2VyYV9lbmVyZ19kYXkgfD4NCiAgICBsZWZ0X2pvaW4oZ19oX2FnZywNCiAgICAgICAgICAgICAgYnkgPSBjKCJkYXRlIiA9ICJkYXRlIiwgIm5vbV9zdWJzaXN0ZW1hIiA9ICJzdWJzIikpDQoNCiAgIyBzZSBmYWx0YXIgc3Vic2lzdGVtYSBlbSBhbGd1bSBkaWEsIHRyYXRhIE5BIGNvbW8gMCBkZWx0YQ0KICBuZDMkZGVsdGFfZ19oaWRyb19jbGltYVtpcy5uYShuZDMkZGVsdGFfZ19oaWRyb19jbGltYSldIDwtIDANCg0KICBnX2hfb2JzIDwtIG5kMyRnZXJfaGlkcm9lbGV0cmljYQ0KICBnX2hfY2ZNMyA8LSBnX2hfb2JzIC0gbmQzJGRlbHRhX2dfaGlkcm9fY2xpbWEjIGNsaXBwaW5nIGVtIDANCg0KICBuZDNfZiA8LSBuZDMgJT4lIG11dGF0ZShnZXJfaGlkcm9lbGV0cmljYSA9IGdfaF9vYnMpICAgIyBmYWN0dWFsIChvYnNlcnZhZG8pDQogIG5kM19jIDwtIG5kMyAlPiUgbXV0YXRlKGdlcl9oaWRyb2VsZXRyaWNhID0gZ19oX2NmTTMpICAjIGNvbnRyYWZhY3R1YWwgKG9icyDiiJIgzpRjbGltYSkNCg0KICAjID09PT09ICg1KSBQcmVkacOnw6NvIHTDqXJtaWNhIGZhY3R1YWwgZSBjZiAoTTMpIG5vIG7DrXZlbCBzdWJzaXN0ZW1hw5dkaWENCiAgWDNfZiA8LSBwcmVkaWN0KG0zX2dhbV90ZXJtaWNhLCBuZXdkYXRhID0gbmQzX2YsIHR5cGUgPSAibHBtYXRyaXgiKQ0KICBYM19jIDwtIHByZWRpY3QobTNfZ2FtX3Rlcm1pY2EsIG5ld2RhdGEgPSBuZDNfYywgdHlwZSA9ICJscG1hdHJpeCIpDQoNCiAgZ190X2YgPC0gYXMubnVtZXJpYyhYM19mICUqJSBiM1tzLCBdKQ0KICBnX3RfYyA8LSBhcy5udW1lcmljKFgzX2MgJSolIGIzW3MsIF0pDQoNCiAgZGVsdGFfR3Rlcm1fbWF0Wywgc10gPC0gZ190X2YgLSBnX3RfYw0KICBwcmludChzKQ0KfQ0KDQpgYGANCmBgYHtyfQ0KZGVsdGFfR3Rlcm1fbWF0ICU+JSBhcy5kYXRhLmZyYW1lKCkgJT4lDQogIHNldE5hbWVzKHBhc3RlMCgic2ltXyIsIHNlcV9sZW4obnNpbSkpKSAlPiUNCiAgYmluZF9jb2xzKGdlcmFfZW5lcmdfZGF5WywgYygiZGF0ZSIsICJub21fc3Vic2lzdGVtYSIpXSkgJT4lIA0KICBwaXZvdF9sb25nZXIoc3RhcnRzX3dpdGgoInNpbV8iKSwgdmFsdWVzX3RvID0gImRlbHRhX0dfdGVybSIpICU+JQ0KICBtdXRhdGUoeWVhciA9IGx1YnJpZGF0ZTo6eWVhcihkYXRlKSkgJT4lIA0KICBncm91cF9ieSh5ZWFyLA0KICAgICAgICAgICBub21fc3Vic2lzdGVtYSxuYW1lKSAlPiUNCiAgc3VtbWFyaXNlKA0KICAgIGRlbHRhX1Rfc3VtID0gc3VtKC1kZWx0YV9HX3Rlcm0sIG5hLnJtID0gVFJVRSksDQogICAgI2RlbHRhX1RfbHdyICA9IHF1YW50aWxlKGRlbHRhX0dfdGVybSwgMC4wNSwgbmEucm0gPSBUUlVFKSwNCiAgICAjZGVsdGFfVF91cHIgID0gcXVhbnRpbGUoZGVsdGFfR190ZXJtLCAwLjk1LCBuYS5ybSA9IFRSVUUpLA0KICAgICNkZWx0YV9UX3NkICAgPSBzZChkZWx0YV9HX3Rlcm0sIG5hLnJtID0gVFJVRSksDQogICAgLmdyb3VwcyA9ICJkcm9wIg0KICApICU+JSBncm91cF9ieSh5ZWFyLA0KICAgIG5vbV9zdWJzaXN0ZW1hKSAlPiUNCiAgc3VtbWFyaXNlKA0KICAgIGRlbHRhX1RfbWVhbiA9IG1lYW4oZGVsdGFfVF9zdW0sIG5hLnJtID0gVFJVRSksDQogICAgZGVsdGFfVF9sd3IgID0gcXVhbnRpbGUoZGVsdGFfVF9zdW0sIDAuMDUsIG5hLnJtID0gVFJVRSksDQogICAgZGVsdGFfVF91cHIgID0gcXVhbnRpbGUoZGVsdGFfVF9zdW0sIDAuOTUsIG5hLnJtID0gVFJVRSksDQogICAgZGVsdGFfVF9zZCAgID0gc2QoZGVsdGFfVF9zdW0sIG5hLnJtID0gVFJVRSksDQogICAgLmdyb3VwcyA9ICJkcm9wIg0KICApICAtPiBtM190ZXJtX3N1bW1hcnlfbTNfYW5udWFsDQptM190ZXJtX3N1bW1hcnlfbTNfYW5udWFsDQptM190ZXJtX3N1bW1hcnlfbTNfYW5udWFsJGRlbHRhX1RfbWVhbiAlPiUgbWVhbiggbmEucm0gPSBUUlVFKQ0KbTNfdGVybV9zdW1tYXJ5X20zX2FubnVhbCRkZWx0YV9UX21lYW4gJT4lIHNkKCBuYS5ybSA9IFRSVUUpDQptM190ZXJtX3N1bW1hcnlfbTNfYW5udWFsJGRlbHRhX1Rfc2QgJT4lIHNkKCBuYS5ybSA9IFRSVUUpDQoNCmdncGxvdChtM190ZXJtX3N1bW1hcnlfbTNfYW5udWFsLCBhZXMoeCA9IHllYXIsIHkgPSBkZWx0YV9UX21lYW4pKSArDQogIGdlb21fcmliYm9uKGFlcyh5bWluID0gZGVsdGFfVF9sd3IsIHltYXggPSBkZWx0YV9UX3VwciksZmlsbD0icmVkIiwgYWxwaGEgPSAwLjM1KSArDQogIGdlb21fcmliYm9uKGFlcyh5bWluID0gZGVsdGFfVF9tZWFuLCB5bWF4ID0gMCksIGFscGhhID0gMC4zNSkgKw0KICANCiAgZ2VvbV9saW5lKCkgKw0KICBmYWNldF93cmFwKH4gbm9tX3N1YnNpc3RlbWEsIHNjYWxlcyA9ICJmcmVlX3kiKSArDQogIGxhYnMoDQogICAgdGl0bGUgPSAiUGVuYWxpZGFkZSBjbGltw6F0aWNhIHByb3BhZ2FkYSBuYSBnZXJhw6fDo28gdMOpcm1pY2EgKM6UR190ZXJtKSIsDQogICAgc3VidGl0bGUgPSBwYXN0ZSgiTcOpdG9kbzoiLCAiPyIsICJ8IG5zaW0gPSIsIG5zaW0pLA0KICAgIHggPSAiVHJpbWVzdHJlIiwgeSA9ICLOlEdfdGVybSAoTVfCt23DqnMpIg0KICApICsNCiAgdGhlbWVfbWluaW1hbCgpDQpgYGANCg0KDQojIyMjDQoNCg0KDQpgYGB7cn0NCmRlbHRhX0d0ZXJtX21hdCAlPiUgYXMuZGF0YS5mcmFtZSgpICU+JQ0KICBzZXROYW1lcyhwYXN0ZTAoInNpbV8iLCBzZXFfbGVuKG5zaW0pKSkgJT4lDQogIGJpbmRfY29scyhnZXJhX2VuZXJnX2RheVssIGMoImRhdGUiLCAibm9tX3N1YnNpc3RlbWEiKV0pICU+JSANCiAgcGl2b3RfbG9uZ2VyKHN0YXJ0c193aXRoKCJzaW1fIiksIHZhbHVlc190byA9ICJkZWx0YV9HX3Rlcm0iKSAlPiUNCiAgbXV0YXRlKHllYXIgPSBsdWJyaWRhdGU6OnllYXIoZGF0ZSkpICU+JSANCiAgZ3JvdXBfYnkoDQogICAgICAgICAgIG5vbV9zdWJzaXN0ZW1hLG5hbWUpICU+JQ0KICBzdW1tYXJpc2UoDQogICAgZGVsdGFfVF9zdW0gPSBzdW0oLWRlbHRhX0dfdGVybSwgbmEucm0gPSBUUlVFKSwNCiAgICAjZGVsdGFfVF9sd3IgID0gcXVhbnRpbGUoZGVsdGFfR190ZXJtLCAwLjA1LCBuYS5ybSA9IFRSVUUpLA0KICAgICNkZWx0YV9UX3VwciAgPSBxdWFudGlsZShkZWx0YV9HX3Rlcm0sIDAuOTUsIG5hLnJtID0gVFJVRSksDQogICAgI2RlbHRhX1Rfc2QgICA9IHNkKGRlbHRhX0dfdGVybSwgbmEucm0gPSBUUlVFKSwNCiAgICAuZ3JvdXBzID0gImRyb3AiDQogICkgJT4lIGdyb3VwX2J5KA0KICAgICAgICAgICAgICAgICBub21fc3Vic2lzdGVtYSkgJT4lDQogIHN1bW1hcmlzZSgNCiAgICBkZWx0YV9UX21lYW4gPSBtZWFuKGRlbHRhX1Rfc3VtLCBuYS5ybSA9IFRSVUUpLA0KICAgIGRlbHRhX1RfbHdyICA9IHF1YW50aWxlKGRlbHRhX1Rfc3VtLCAwLjAyNSwgbmEucm0gPSBUUlVFKSwNCiAgICBkZWx0YV9UX3VwciAgPSBxdWFudGlsZShkZWx0YV9UX3N1bSwgMC45MjUsIG5hLnJtID0gVFJVRSksDQogICAgZGVsdGFfVF9zZCAgID0gc2QoZGVsdGFfVF9zdW0sIG5hLnJtID0gVFJVRSksDQogICAgLmdyb3VwcyA9ICJkcm9wIg0KICApICAtPiBtM190ZXJtX3N1bW1hcnlfbTNfcG9yc3Vic2lzdGVtYQ0KDQpsaWJyYXJ5KGd0KQ0KbTNfdGVybV9zdW1tYXJ5X20zX3BvcnN1YnNpc3RlbWFbLGMoIm5vbV9zdWJzaXN0ZW1hIiwiZGVsdGFfVF9tZWFuIiwiZGVsdGFfVF9sd3IiLCAiZGVsdGFfVF91cHIiKV0gJT4lIGphbml0b3I6OmFkb3JuX3RvdGFscygpICU+JSANCiAgZ3QoKSAlPiUNCiAgZm10X251bWJlcihjb2x1bW5zID0gMjo0LCBkZWNpbWFscyA9IDEpICU+JQ0KICBjb2xzX2xhYmVsKA0KICAgIG5vbV9zdWJzaXN0ZW1hID0gIlN1YnN5c3RlbSIsDQogICAgZGVsdGFfVF9tZWFuID0gIlN1bSDOlGdlciBUZXJtIChNV2gpIiwNCiAgICBkZWx0YV9UX2x3ciAgPSAiTG93ZXIgOTUlIiwNCiAgICBkZWx0YV9UX3VwciAgPSAiVXBwZXIgOTUlIiwNCiAgKSAlPiUNCiAgdGFiX2hlYWRlcigNCiAgICB0aXRsZSA9IG1kKCIqKkFnZ3JlZ2F0ZSBjbGltYXRlIHBlbmFsdHkgb24gc3RvcmVkIGVuZXJneSAoMjAwMeKAkzIwMTgpKioiKSwNCiAgICBzdWJ0aXRsZSA9ICJTaW11bGF0ZWQgbWVhbiBhbmQgOTUlIGNvbmZpZGVuY2UgaW50ZXJ2YWxzIHBlciBzdWJzeXN0ZW0iDQogICkNCmBgYA0KDQoNCg0KDQoNCg0KIzMuNCBNb2RlbG8gMyBQTEQ6IEN1c3RvIHBhcmEgbyBzaXN0ZW1hDQpgYGB7cn0NCnBsZCAgICAgPC0gcmVhZC5jc3YoInByZWNvX3NlbWFuYWwuY3N2IikgICAgICAgICAgICMgUExEIHNlbWFuYWwNCnBsZCRkYXRlIDwtIGFzLkRhdGUocGxkJERBVEFfSU5JQ0lPKSAgICMgaWRlbSBwYXJhIGEgYmFzZSBkZSBQTEQNCnBsZCR3ZWVrICA8LSBsdWJyaWRhdGU6Omlzb3dlZWsocGxkJGRhdGUpDQpwbGQkeWVhciAgPC0gbHVicmlkYXRlOjp5ZWFyKHBsZCRkYXRlKQ0KYGBgDQoNCmBgYHtyfQ0KDQojcGxkJGRhdGU8LXBsZCREQVRBX0lOSUNJTyAlPiUgYXNfZGF0ZSgpIA0KcGxkICU+JSBzcHJlYWQoU3VibWVyY2FkbyxwcmVjbyktPnBsZA0KcGxkJGRhdGUgJT4lIG1pbigpLT5pbmljaW8NCnBsZCAlPiUgZmlsdGVyKERBVEFfSU5JQ0lPPT1pbmljaW8pDQpkYXRhczwtZ2VyYV9lbmVyZ19kYXkkZGF0ZSAlPiUgdW5pcXVlDQpkYXRhLmZyYW1lKGRhdGFzKSAlPiUgZmlsdGVyKGRhdGFzPmluaWNpby0xKSAlPiUgYXJyYW5nZShkYXRhcykgJT4lIGxlZnRfam9pbihwbGQsYnkgPSBjKCJkYXRhcyI9ImRhdGUiKSktPmRhYXNfY29tcGxldGFzDQpkYWFzX2NvbXBsZXRhcw0KaT0yDQpmb3IgKGkgaW4gMTpsZW5ndGgoZGFhc19jb21wbGV0YXMkQU5PKSkgeyNsZW5ndGgoZGFhc19jb21wbGV0YXMkQU5PKQ0KICBwcmludChpKQ0KICBpZiAoaXMubmEoZGFhc19jb21wbGV0YXMkQU5PW2ldKSkgew0KICAgIGRhYXNfY29tcGxldGFzJEFOT1tpXTwtZGFhc19jb21wbGV0YXMkQU5PW2ktMV0NCiAgICBkYWFzX2NvbXBsZXRhcyRNRVNbaV08LWRhYXNfY29tcGxldGFzJE1FU1tpLTFdDQogICAgZGFhc19jb21wbGV0YXMkU0VNQU5BW2ldPC1kYWFzX2NvbXBsZXRhcyRTRU1BTkFbaS0xXQ0KICAgIGRhYXNfY29tcGxldGFzJERBVEFfRklNW2ldPC1kYWFzX2NvbXBsZXRhcyREQVRBX0ZJTVtpLTFdDQogICAgZGFhc19jb21wbGV0YXMkU1VERVNURVtpXTwtZGFhc19jb21wbGV0YXMkU1VERVNURVtpLTFdDQogICAgZGFhc19jb21wbGV0YXMkU1VMW2ldPC1kYWFzX2NvbXBsZXRhcyRTVUxbaS0xXQ0KICAgIGRhYXNfY29tcGxldGFzJE5PUkRFU1RFW2ldPC1kYWFzX2NvbXBsZXRhcyROT1JERVNURVtpLTFdDQogICAgZGFhc19jb21wbGV0YXMkTk9SVEVbaV08LWRhYXNfY29tcGxldGFzJE5PUlRFW2ktMV0NCg0KICAgIA0KICB9DQogIA0KfSAgDQpkYWFzX2NvbXBsZXRhcyAlPiUgZ2F0aGVyKGtleSA9ICJub21fc3Vic2l0ZW1hIix2YWx1ZSA9ICJwcmVjbyIsYygiTk9SREVTVEUiLCJTVURFU1RFIiwiU1VMIiwiTk9SVEUiKSktPnBsZA0Kd3JpdGVfY3N2KHBsZCwicGxkX2RpYXJpb19jb21wbGV0by5jc3YiLHJvdy5uYW1lcyA9IEYpDQpgYGANCg0KYGBge3J9DQpzZXJpZSA8LSBkYWFzX2NvbXBsZXRhcyAlPiUNCiAgcHVsbChOT1JERVNURSkgJT4lDQogIHRzKHN0YXJ0ID0gIGMoMjAwMSwgMTgxKSwgZnJlcXVlbmN5ID0gMzY1KQ0Kc3RsKHNlcmllLHMud2luZG93ID0gInBlcmlvZGljIikgJT4lIHBsb3QNCg0Kc2VyaWUgPC0gZGFhc19jb21wbGV0YXMgJT4lDQogIHB1bGwoU1VMKSAlPiUNCiAgdHMoc3RhcnQgPSAgYygyMDAxLCAxODEpLCBmcmVxdWVuY3kgPSAzNjUpDQpzdGwoc2VyaWUscy53aW5kb3cgPSAicGVyaW9kaWMiKSAlPiUgcGxvdA0KDQpzZXJpZSA8LSBkYWFzX2NvbXBsZXRhcyAlPiUNCiAgcHVsbChTVURFU1RFKSAlPiUNCiAgdHMoc3RhcnQgPSAgYygyMDAxLCAxODEpLCBmcmVxdWVuY3kgPSAzNjUpDQpzdGwoc2VyaWUscy53aW5kb3cgPSAicGVyaW9kaWMiKSAlPiUgcGxvdA0KDQpzZXJpZSA8LSBkYWFzX2NvbXBsZXRhcyAlPiUNCiAgcHVsbChOT1JURSkgJT4lDQogIHRzKHN0YXJ0ID0gIGMoMjAwMSwgMTgxKSwgZnJlcXVlbmN5ID0gMzY1KQ0Kc3RsKHNlcmllLHMud2luZG93ID0gInBlcmlvZGljIikgJT4lIHBsb3QNCg0KDQpgYGANCg0KYGBge3J9DQpwbGQkU3VibWVyY2FkbyAlPiUgdW5pcXVlKCkNCmdlcmFfZW5lcmdfZGF5JG5vbV9zdWJzaXN0ZW1hLnggJT4lIHVuaXF1ZQ0KDQojbmV3ZGF0YV9tMSAlPiUgd3JpdGUuY3N2KCJiYXNlIHZhbG9yZXMgcHJldmlzdG9zLmNzdiIpDQojZ2VyYV9lbmVyZ19kYXkgJT4lIHdyaXRlLmNzdigidmFsb3Jlc19wcmV2aXN0b3NfZGF5LmNzdiIpDQpgYGANCg0KYGBge3J9DQpnZXJhX2VuZXJnX2RheSAlPiUgaW5uZXJfam9pbihwbGQsYnk9YygiZGF0ZSI9ImRhdGFzIiwibm9tX3N1YnNpc3RlbWEiPSJub21fc3Vic2l0ZW1hIikpLT5wbGRfZnVsbA0Kd3JpdGUuY3N2KHBsZF9mdWxsLCJwbGRfZnVsbC5jc3YiKQ0KcGxkX2Z1bGwgJT4lIHN1bW1hcnkoKQ0KYGBgDQoNCg0KIyMjIE1vZGVsbyBQTEQNCg0KYGBge3J9DQpwbGRfZnVsbCAlPiUNCiAgICAgICAgICAgICAgICAgbXV0YXRlKA0KICAgICAgICAgICAgICAgICAgIGdlcl9oaWRyb2VsZXRyaWNhID0gaWZlbHNlKGdlcl9oaWRyb2VsZXRyaWNhID09IDAsIDEsIGdlcl9oaWRyb2VsZXRyaWNhKSwNCiAgICAgICAgICAgICAgICAgICBnZXJfZm90b3ZvbHRhaWNhID0gaWZlbHNlKGdlcl9mb3Rvdm9sdGFpY2EgPT0gMCwgMSwgZ2VyX2ZvdG92b2x0YWljYSksDQogICAgICAgICAgICAgICAgICAgZ2VyX2VvbGllbGV0cmljYSA9IGlmZWxzZShnZXJfZW9saWVsZXRyaWNhID09IDAsIDEsIGdlcl9lb2xpZWxldHJpY2EpLA0KICAgICAgICAgICAgICAgICAgIGdlcl90ZXJtaWNhID0gaWZlbHNlKGdlcl90ZXJtaWNhID09IDAsIDEsIGdlcl90ZXJtaWNhKSwNCiAgICAgICAgICAgICAgICAgICAjRGVtYW5kYSA9IGlmZWxzZSh2YWxfZ2VyYWNhb19kYXlfc3Vic2lzdGVtYSA9PSAwLCAxLCB2YWxfZ2VyYWNhb19kYXlfc3Vic2lzdGVtYSkNCiAgICAgICAgICAgICAgICAgICBEZW1hbmRhID0gZ2VyX2VvbGllbGV0cmljYStnZXJfZm90b3ZvbHRhaWNhK2dlcl9oaWRyb2VsZXRyaWNhK2dlcl90ZXJtaWNhK2dlcl9udWNsZWFyLA0KICAgICAgICAgICAgICAgICApLT5wbGRfZnVsbDINCmdhbV80X3BsZCA8LSBnYW0ocHJlY28gfiAjdHJlbmQrDQogICAgICAgICAgICAgICAgIHMobG9nKGdlcl9oaWRyb2VsZXRyaWNhKSkgKyANCiAgICAgICAgICAgICAgICAgcyhsb2codHJlbmQpKSArICAgICAgICAgICAgICAgIA0KICAgICAgICAgICAgICAgICBzKGxvZyhkb3kpKSsNCiAgICAgICAgICAgICAgICAgcyhsb2coZ2VyX2VvbGllbGV0cmljYSkpICsgDQogICAgICAgICAgICAgICAgIHMobG9nKGdlcl9mb3Rvdm9sdGFpY2EpKSArIA0KICAgICAgICAgICAgICAgICBzKGxvZyhEZW1hbmRhKSkgKyANCiAgICAgICAgICAgICAgICAgcyhsb2coZ2VyX3Rlcm1pY2EpKSsNCiAgICAgICAgICAgICAgICAgI3Mobm9tX3N1YnNpc3RlbWEueCwgYnMgPSAicmUiKSwjIGVmZWl0byBhbGVhdMOzcmlvIHBvciByZXNlcnZhdMOzcmlvDQogICAgICAgICAgICAgICAgIG5vbV9zdWJzaXN0ZW1hLA0KICAgICAgICAgICAgICAgZGF0YSA9IHBsZF9mdWxsMikNCg0KYGBgDQoNCmBgYHtyfQ0Kc3VtbWFyeShnYW1fNF9wbGQpDQoNCmBgYA0KDQpgYGB7cn0NCnN1bW1hcnkoZ2FtXzRfcGxkKQ0KZ3RzdW1tYXJ5Ojp0YmxfcmVncmVzc2lvbihnYW1fNF9wbGQpDQpzdW1tYXJ5KGdhbV80X3BsZCkNCmdhbS5jaGVjayhnYW1fNF9wbGQpICAgICAgICAgICMgcmVzw61kdW9zLCBRUSwgay1pbmRleA0KY29uY3Vydml0eShnYW1fNF9wbGQsIGZ1bGw9VFJVRSkNCnBsb3QoZ2FtXzRfcGxkLCBwYWdlcz00LCBzY2hlbWU9MSwgc2hhZGU9VFJVRSwgc2U9VFJVRSkNCmBgYA0KDQoNCg0KDQoNCmBgYHtyfQ0KIyAtLS0gUHJlZGnDp8O1ZXMgZmFjdHVhbCBlIGNvbnRyYWZhY3R1YWwgLS0tDQpzZXQuc2VlZCgyMDI1MTAxMykNCm5zaW0gPC0gNTAgICMgbsO6bWVybyBkZSBzaW11bGHDp8O1ZXMgY29uanVudGFzDQoNCiMgLS0tIDEuIE1hdHJpeiBkZSBjb3ZhcmnDom5jaWEgZGUgY2FkYSBtb2RlbG8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tDQojIC0tLSBDb3ZhcmnDom5jaWFzIGUgc29ydGVpb3MgZGUgY29lZmljaWVudGVzIC0tLQ0KVnAxIDwtIHZjb3YobTFfZ2FtKSAgICAgICAgICAgICAgICAgICMgTTE6IEVBUiB+IGNsaW1hDQpWcDIgPC0gdmNvdihtMl9oaWRybykgICAgICAgICAgICAgICAgIyBNMjogR19oaWRybyB+IEVBUg0KVnAzIDwtIHZjb3YobTNfZ2FtX3Rlcm1pY2EpICAgICAgICAgICMgTTM6IEdfdGVybSB+IEdfaGlkcm8gKyBjb250cm9sZXMNClZwNCA8LSB2Y292KGdhbV80X3BsZCkgICAgICAgICAgICAgICMgTTM6IFByZcOnbyB+IEdfaGlkcm8gKyBHX3Rlcm0gKyBjb250cm9sZXMNCg0KYjEgPC0gTUFTUzo6bXZybm9ybShuc2ltLCBjb2VmKG0xX2dhbSksICAgICAgICAgVnAxKQ0KYjIgPC0gTUFTUzo6bXZybm9ybShuc2ltLCBjb2VmKG0yX2hpZHJvKSwgICAgICAgVnAyKQ0KYjMgPC0gTUFTUzo6bXZybm9ybShuc2ltLCBjb2VmKG0zX2dhbV90ZXJtaWNhKSwgVnAzKQ0KYjQgPC0gTUFTUzo6bXZybm9ybShuc2ltLCBjb2VmKGdhbV80X3BsZCksIFZwNCkNCmBgYA0KDQoNCmBgYHtyfQ0KIyAtLS0gMi4gTWF0cml6ZXMgZGUgZGVzaWduIGRvIE0xIChjbGltYSDihpIgRUFSKSAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tDQpYMV9vYnMgPC0gcHJlZGljdChtMV9nYW0sIG5ld2RhdGEgPSBuZF9vYnMsIHR5cGUgPSAibHBtYXRyaXgiKQ0KWDFfY2YgIDwtIHByZWRpY3QobTFfZ2FtLCBuZXdkYXRhID0gbmRfY2YsICB0eXBlID0gImxwbWF0cml4IikNCmBgYA0KDQoNCmBgYHtyfQ0KIyAtLS0gMy4gUHJlcGFyYcOnw6NvIGRlIGJhc2VzIGUgbWF0cml6ZXMgZGUgc2HDrWRhIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQ0KZGVsdGFfUExEX21hdCA8LSBtYXRyaXgoTkFfcmVhbF8sIG5yb3cgPSBucm93KHBsZF9mdWxsMiksIG5jb2wgPSBuc2ltKQ0KDQprZXlzX20yIDwtIHJlc2VydiAlPiUgc2VsZWN0KGRhdGUsIG5vbV9zdWJzaXN0ZW1hLngpICU+JSBhcy5kYXRhLmZyYW1lKCkNCmtleXNfbTMgPC0gZ2VyYV9lbmVyZ19kYXkgJT4lIHNlbGVjdChkYXRlLCBub21fc3Vic2lzdGVtYSkgJT4lIGFzLmRhdGEuZnJhbWUoKQ0Ka2V5c19tNCA8LSBwbGRfZnVsbDIgJT4lIHNlbGVjdChkYXRlLCBub21fc3Vic2lzdGVtYSkgJT4lIGFzLmRhdGEuZnJhbWUoKQ0KDQpgYGANCg0KYGBge3J9DQojID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0NCiMgLS0tIDQuIExvb3AgcHJpbmNpcGFsIGRlIHByb3BhZ2HDp8OjbyBNb250ZSBDYXJsbyAtLS0tLS0tLS0tDQojID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0NCmZvciAocyBpbiBzZXFfbGVuKG5zaW0pKSB7DQoNCiAgIyA9PT09PSAoMSkgRUFSIGZhY3R1YWwgZSBjb250cmFmYWN0dWFsIChNMSkgcG9yIHJlc2VydmF0w7NyaW/Dl2RpYSA9PT09PT09PT09PQ0KICBlYXJfZiA8LSBhcy5udW1lcmljKFgxX29icyAlKiUgYjFbcywgXSkNCiAgZWFyX2MgPC0gYXMubnVtZXJpYyhYMV9jZiAgJSolIGIxW3MsIF0pDQoNCiAgIyA9PT09PSAoMikgUHJlZGnDp8OjbyBkZSBHX2hpZHJvIGZhY3R1YWwgZSBjZiAoTTIpID09PT09PT09PT09PT09PT09PT09PT09PT09PQ0KICBuZDJfZiA8LSByZXNlcnYgJT4lIG11dGF0ZShlYXJfcmVzZXJ2YXRvcmlvX3N1YnNpc3RlbWFfcHJvcHJpb19td21lcyA9IGVhcl9mKQ0KICBuZDJfYyA8LSByZXNlcnYgJT4lIG11dGF0ZShlYXJfcmVzZXJ2YXRvcmlvX3N1YnNpc3RlbWFfcHJvcHJpb19td21lcyA9IGVhcl9jKQ0KDQogIFgyX2YgPC0gcHJlZGljdChtMl9oaWRybywgbmV3ZGF0YSA9IG5kMl9mLCB0eXBlID0gImxwbWF0cml4IikNCiAgWDJfYyA8LSBwcmVkaWN0KG0yX2hpZHJvLCBuZXdkYXRhID0gbmQyX2MsIHR5cGUgPSAibHBtYXRyaXgiKQ0KDQogIGdfaF9mX3JlcyA8LSBhcy5udW1lcmljKFgyX2YgJSolIGIyW3MsIF0pICAjIGdlcmHDp8OjbyBow61kcmljYSBwb3IgcmVzZXJ2YXTDs3Jpb8OXZGlhDQogIGdfaF9jX3JlcyA8LSBhcy5udW1lcmljKFgyX2MgJSolIGIyW3MsIF0pDQoNCiAgIyA9PT09PSAoMykgQWdyZWdhciBHX2hpZHJvIHBhcmEgc3Vic2lzdGVtYcOXZGlhID09PT09PT09PT09PT09PT09PT09PT09PT09PT09DQogIGRmX2ggPC0gZGF0YS5mcmFtZShkYXRlID0ga2V5c19tMiRkYXRlLA0KICAgICAgICAgICAgICAgICAgICAgc3VicyA9IGtleXNfbTIkbm9tX3N1YnNpc3RlbWEueCwNCiAgICAgICAgICAgICAgICAgICAgIGdfaF9mID0gZ19oX2ZfcmVzLA0KICAgICAgICAgICAgICAgICAgICAgZ19oX2MgPSBnX2hfY19yZXMpDQoNCiAgZ19oX2FnZyA8LSBkZl9oIHw+DQogICAgZ3JvdXBfYnkoZGF0ZSwgc3VicykgfD4NCiAgICBzdW1tYXJpc2UoZ19oX2YgPSBzdW0oZ19oX2YsIG5hLnJtID0gVFJVRSksDQogICAgICAgICAgICAgIGdfaF9jID0gc3VtKGdfaF9jLCBuYS5ybSA9IFRSVUUpLCAuZ3JvdXBzID0gImRyb3AiKSB8Pg0KICAgIG11dGF0ZShkZWx0YV9nX2hpZHJvX2NsaW1hID0gZ19oX2YgLSBnX2hfYykNCg0KIyA9PT09PSAoNCkgQ29uc3RydWlyIGlucHV0IGRvIE0zIChzdWJzaXN0ZW1hw5dkaWEpID09PT09PT09PT09PT09PT09PT09PT09PT09DQogIG5kMyA8LSBnZXJhX2VuZXJnX2RheSB8Pg0KICAgIGxlZnRfam9pbihnX2hfYWdnLCBieSA9IGMoImRhdGUiID0gImRhdGUiLCAibm9tX3N1YnNpc3RlbWEiID0gInN1YnMiKSkNCg0KICBuZDMkZGVsdGFfZ19oaWRyb19jbGltYVtpcy5uYShuZDMkZGVsdGFfZ19oaWRyb19jbGltYSldIDwtIDANCg0KICBnX2hfb2JzIDwtIG5kMyRnZXJfaGlkcm9lbGV0cmljYQ0KICBnX2hfY2ZNMyA8LSBnX2hfb2JzIC0gbmQzJGRlbHRhX2dfaGlkcm9fY2xpbWEgICAjIHNlbSB0cnVuY2FnZW0NCg0KICBuZDNfZiA8LSBuZDMgJT4lIG11dGF0ZShnZXJfaGlkcm9lbGV0cmljYSA9IGdfaF9vYnMpJT4lDQogICAgICAgICAgICAgICAgIG11dGF0ZSgNCiAgICAgICAgICAgICAgICAgICBnZXJfaGlkcm9lbGV0cmljYSA9IGlmZWxzZShnZXJfaGlkcm9lbGV0cmljYSA9PSAwLCAxLCBnZXJfaGlkcm9lbGV0cmljYSksDQogICAgICAgICAgICAgICAgICAgZ2VyX2ZvdG92b2x0YWljYSA9IGlmZWxzZShnZXJfZm90b3ZvbHRhaWNhID09IDAsIDEsIGdlcl9mb3Rvdm9sdGFpY2EpLA0KICAgICAgICAgICAgICAgICAgIGdlcl9lb2xpZWxldHJpY2EgPSBpZmVsc2UoZ2VyX2VvbGllbGV0cmljYSA9PSAwLCAxLCBnZXJfZW9saWVsZXRyaWNhKSwNCiAgICAgICAgICAgICAgICAgICBnZXJfdGVybWljYSA9IGlmZWxzZShnZXJfdGVybWljYSA9PSAwLCAxLCBnZXJfdGVybWljYSksDQogICAgICAgICAgICAgICAgICAgI0RlbWFuZGEgPSBpZmVsc2UodmFsX2dlcmFjYW9fZGF5X3N1YnNpc3RlbWEgPT0gMCwgMSwgdmFsX2dlcmFjYW9fZGF5X3N1YnNpc3RlbWEpDQogICAgICAgICAgICAgICAgICAgRGVtYW5kYSA9IGdlcl9lb2xpZWxldHJpY2ErZ2VyX2ZvdG92b2x0YWljYStnZXJfaGlkcm9lbGV0cmljYStnZXJfdGVybWljYStnZXJfbnVjbGVhciwNCiAgICAgICAgICAgICAgICAgKQ0KICBuZDNfYyA8LSBuZDMgJT4lIG11dGF0ZShnZXJfaGlkcm9lbGV0cmljYSA9IGdfaF9jZk0zKSU+JQ0KICAgICAgICAgICAgICAgICBtdXRhdGUoDQogICAgICAgICAgICAgICAgICAgZ2VyX2hpZHJvZWxldHJpY2EgPSBpZmVsc2UoZ2VyX2hpZHJvZWxldHJpY2EgPT0gMCwgMSwgZ2VyX2hpZHJvZWxldHJpY2EpLA0KICAgICAgICAgICAgICAgICAgIGdlcl9mb3Rvdm9sdGFpY2EgPSBpZmVsc2UoZ2VyX2ZvdG92b2x0YWljYSA9PSAwLCAxLCBnZXJfZm90b3ZvbHRhaWNhKSwNCiAgICAgICAgICAgICAgICAgICBnZXJfZW9saWVsZXRyaWNhID0gaWZlbHNlKGdlcl9lb2xpZWxldHJpY2EgPT0gMCwgMSwgZ2VyX2VvbGllbGV0cmljYSksDQogICAgICAgICAgICAgICAgICAgZ2VyX3Rlcm1pY2EgPSBpZmVsc2UoZ2VyX3Rlcm1pY2EgPT0gMCwgMSwgZ2VyX3Rlcm1pY2EpLA0KICAgICAgICAgICAgICAgICAgICNEZW1hbmRhID0gaWZlbHNlKHZhbF9nZXJhY2FvX2RheV9zdWJzaXN0ZW1hID09IDAsIDEsIHZhbF9nZXJhY2FvX2RheV9zdWJzaXN0ZW1hKQ0KICAgICAgICAgICAgICAgICAgIERlbWFuZGEgPSBnZXJfZW9saWVsZXRyaWNhK2dlcl9mb3Rvdm9sdGFpY2ErZ2VyX2hpZHJvZWxldHJpY2ErZ2VyX3Rlcm1pY2ErZ2VyX251Y2xlYXIsDQogICAgICAgICAgICAgICAgICkNCg0KICAjID09PT09ICg1KSBQcmVkacOnw6NvIHTDqXJtaWNhIGZhY3R1YWwgZSBjZiAoTTMpID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PQ0KICBYM19mIDwtIHByZWRpY3QobTNfZ2FtX3Rlcm1pY2EsIG5ld2RhdGEgPSBuZDNfZiwgdHlwZSA9ICJscG1hdHJpeCIpDQogIFgzX2MgPC0gcHJlZGljdChtM19nYW1fdGVybWljYSwgbmV3ZGF0YSA9IG5kM19jLCB0eXBlID0gImxwbWF0cml4IikNCg0KICBnX3RfZiA8LSBhcy5udW1lcmljKFgzX2YgJSolIGIzW3MsIF0pDQogIGdfdF9jIDwtIGFzLm51bWVyaWMoWDNfYyAlKiUgYjNbcywgXSkNCg0KICBkZWx0YV9nX3Rlcm1fY2xpbWEgPC0gZ190X2YgLSBnX3RfYw0KDQojID09PT09ICg2KSBQcmVwYXJhciBpbnB1dCBwYXJhIE00IChwcmXDp28pID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0NCiAgbmQ0IDwtIHBsZF9mdWxsMiB8Pg0KICAgIGxlZnRfam9pbigNCiAgICAgIG5kMyAlPiUgc2VsZWN0KGRhdGUsIG5vbV9zdWJzaXN0ZW1hLCBnZXJfaGlkcm9lbGV0cmljYSkgJT4lIA0KICAgICAgICBtdXRhdGUoZ190X2Y9Z190X2YsZ19oX2NmTTM9Z19oX2NmTTMsDQogICAgICAgICAgICAgICBnX3RfYz1nX3RfYyxnX2hfb2JzPWdfaF9vYnMsDQogICAgICAgICAgICAgICApLA0KICAgICAgYnkgPSBjKCJkYXRlIiwgIm5vbV9zdWJzaXN0ZW1hIikNCiAgICApIHw+DQogICAgbXV0YXRlKGdlcl90ZXJtaWNhX2YgPSBnX3RfZiwNCiAgICAgICAgICAgZ2VyX3Rlcm1pY2FfYyA9IGdfdF9jLA0KICAgICAgICAgICBnZXJfaGlkcm9lbGV0cmljYV9jID0gZ19oX2NmTTMsDQogICAgICAgICAgIGdlcl9oaWRyb2VsZXRyaWNhX2YgPSBnX2hfb2JzKQ0KDQogICMgZmFjdHVhbA0KICBuZDRfZiA8LSBuZDQgJT4lIG11dGF0ZSgNCiAgICBnZXJfdGVybWljYSA9IGdlcl90ZXJtaWNhX2YsDQogICAgZ2VyX2hpZHJvZWxldHJpY2EgPSBnZXJfaGlkcm9lbGV0cmljYV9mDQogICklPiUNCiAgICAgICAgICAgICAgICAgbXV0YXRlKA0KICAgICAgICAgICAgICAgICAgIGdlcl9oaWRyb2VsZXRyaWNhID0gaWZlbHNlKGdlcl9oaWRyb2VsZXRyaWNhID09IDAsIDEsIGdlcl9oaWRyb2VsZXRyaWNhKSwNCiAgICAgICAgICAgICAgICAgICBnZXJfZm90b3ZvbHRhaWNhID0gaWZlbHNlKGdlcl9mb3Rvdm9sdGFpY2EgPT0gMCwgMSwgZ2VyX2ZvdG92b2x0YWljYSksDQogICAgICAgICAgICAgICAgICAgZ2VyX2VvbGllbGV0cmljYSA9IGlmZWxzZShnZXJfZW9saWVsZXRyaWNhID09IDAsIDEsIGdlcl9lb2xpZWxldHJpY2EpLA0KICAgICAgICAgICAgICAgICAgIGdlcl90ZXJtaWNhID0gaWZlbHNlKGdlcl90ZXJtaWNhIDw9IDAsIDEsIGdlcl90ZXJtaWNhKSwNCiAgICAgICAgICAgICAgICAgICAjRGVtYW5kYSA9IGlmZWxzZSh2YWxfZ2VyYWNhb19kYXlfc3Vic2lzdGVtYSA9PSAwLCAxLCB2YWxfZ2VyYWNhb19kYXlfc3Vic2lzdGVtYSkNCiAgICAgICAgICAgICAgICAgICBEZW1hbmRhID0gZ2VyX2VvbGllbGV0cmljYStnZXJfZm90b3ZvbHRhaWNhK2dlcl9oaWRyb2VsZXRyaWNhK2dlcl90ZXJtaWNhK2dlcl9udWNsZWFyLA0KICAgICAgICAgICAgICAgICApDQogICMgY29udHJhZmFjdHVhbCAoY29tIHBlbmFsaWRhZGUgY2xpbcOhdGljYSBwcm9wYWdhZGEpDQogIG5kNF9jIDwtIG5kNCAlPiUgbXV0YXRlKA0KICAgIGdlcl90ZXJtaWNhID0gZ2VyX3Rlcm1pY2FfYywNCiAgICBnZXJfaGlkcm9lbGV0cmljYSA9IGdlcl9oaWRyb2VsZXRyaWNhX2MNCiAgKSU+JQ0KICAgICAgICAgICAgICAgICBtdXRhdGUoDQogICAgICAgICAgICAgICAgICAgZ2VyX2hpZHJvZWxldHJpY2EgPSBpZmVsc2UoZ2VyX2hpZHJvZWxldHJpY2EgPT0gMCwgMSwgZ2VyX2hpZHJvZWxldHJpY2EpLA0KICAgICAgICAgICAgICAgICAgIGdlcl9mb3Rvdm9sdGFpY2EgPSBpZmVsc2UoZ2VyX2ZvdG92b2x0YWljYSA9PSAwLCAxLCBnZXJfZm90b3ZvbHRhaWNhKSwNCiAgICAgICAgICAgICAgICAgICBnZXJfZW9saWVsZXRyaWNhID0gaWZlbHNlKGdlcl9lb2xpZWxldHJpY2EgPT0gMCwgMSwgZ2VyX2VvbGllbGV0cmljYSksDQogICAgICAgICAgICAgICAgICAgZ2VyX3Rlcm1pY2EgPSBpZmVsc2UoZ2VyX3Rlcm1pY2EgPD0gMCwgMSwgZ2VyX3Rlcm1pY2EpLA0KICAgICAgICAgICAgICAgICAgICNEZW1hbmRhID0gaWZlbHNlKHZhbF9nZXJhY2FvX2RheV9zdWJzaXN0ZW1hID09IDAsIDEsIHZhbF9nZXJhY2FvX2RheV9zdWJzaXN0ZW1hKQ0KICAgICAgICAgICAgICAgICAgIERlbWFuZGEgPSBnZXJfZW9saWVsZXRyaWNhK2dlcl9mb3Rvdm9sdGFpY2ErZ2VyX2hpZHJvZWxldHJpY2ErZ2VyX3Rlcm1pY2ErZ2VyX251Y2xlYXIsDQogICAgICAgICAgICAgICAgICkNCiMgPT09PT0gKDcpIFByZWRpw6fDo28gZGUgcHJlw6dvIGZhY3R1YWwgZSBjZiAoTTQpID09PT09PT09PT09PT09PT09PT09PT09PT09PT09DQogIFg0X2YgPC0gcHJlZGljdChnYW1fNF9wbGQsIG5ld2RhdGEgPSBuZDRfZiwgdHlwZSA9ICJscG1hdHJpeCIpDQogIFg0X2MgPC0gcHJlZGljdChnYW1fNF9wbGQsIG5ld2RhdGEgPSBuZDRfYywgdHlwZSA9ICJscG1hdHJpeCIpDQoNCiAgcGxkX2YgPC0gYXMubnVtZXJpYyhYNF9mICUqJSBiNFtzLCBdKQ0KICBwbGRfYyA8LSBhcy5udW1lcmljKFg0X2MgJSolIGI0W3MsIF0pDQoNCiAgZGVsdGFfUExEX21hdFssIHNdIDwtIHBsZF9mIC0gcGxkX2MgICAjIHBlbmFsaWRhZGUgY2xpbcOhdGljYSBlbSBwcmXDp28gKFIkL01XaCkNCiAgcHJpbnQocykNCn0NCmBgYA0KDQoNCmBgYHtyfQ0KIyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09DQojIC0tLSA1LiBBZ3JlZ2HDp8OjbyB0ZW1wb3JhbCBlIGVzdGF0w61zdGljYXMgZGUgaW5jZXJ0ZXphIC0tLS0tDQojID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0NCm00X3BsZF9zdW1tYXJ5IDwtIGRlbHRhX1BMRF9tYXQgJT4lDQogIGFzLmRhdGEuZnJhbWUoKSAlPiUNCiAgc2V0TmFtZXMocGFzdGUwKCJzaW1fIiwgc2VxX2xlbihuc2ltKSkpICU+JQ0KICBiaW5kX2NvbHMocGxkX2Z1bGwyWywgYygiZGF0ZSIsICJub21fc3Vic2lzdGVtYSIpXSkgJT4lDQogIHBpdm90X2xvbmdlcihzdGFydHNfd2l0aCgic2ltXyIpLCB2YWx1ZXNfdG8gPSAiZGVsdGFfUExEIikgJT4lDQogIG11dGF0ZShRdWFydGVyICA9IGx1YnJpZGF0ZTo6Zmxvb3JfZGF0ZShkYXRlLCAiMyBtb250aHMiKSkgJT4lDQogIGdyb3VwX2J5KFF1YXJ0ZXIgLCBub21fc3Vic2lzdGVtYSwgbmFtZSkgJT4lDQogIHN1bW1hcmlzZSgNCiAgICBkZWx0YV9QTERfc3VtID0gbWVhbigtZGVsdGFfUExELCBuYS5ybSA9IFRSVUUpLA0KICAgIC5ncm91cHMgPSAiZHJvcCINCiAgKSAlPiUNCiAgZ3JvdXBfYnkoUXVhcnRlciwgbm9tX3N1YnNpc3RlbWEpICU+JQ0KICBzdW1tYXJpc2UoDQogICAgZGVsdGFfUExEX21lYW4gPSBtZWFuKGRlbHRhX1BMRF9zdW0sIG5hLnJtID0gVFJVRSksDQogICAgZGVsdGFfUExEX2x3ciAgPSBxdWFudGlsZShkZWx0YV9QTERfc3VtLCAwLjA1LCBuYS5ybSA9IFRSVUUpLA0KICAgIGRlbHRhX1BMRF91cHIgID0gcXVhbnRpbGUoZGVsdGFfUExEX3N1bSwgMC45NSwgbmEucm0gPSBUUlVFKSwNCiAgICBkZWx0YV9QTERfc2QgICA9IHNkKGRlbHRhX1BMRF9zdW0sIG5hLnJtID0gVFJVRSksDQogICAgLmdyb3VwcyA9ICJkcm9wIg0KICApDQpgYGANCg0KIyAtLS0gNi4gVmlzdWFsaXphw6fDo286IEZhbiBDaGFydCBkbyBpbXBhY3RvIG5vIFBMRCAtLS0tLS0tLS0tDQoNCmBgYHtyfQ0KIyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09DQojIC0tLSA2LiBWaXN1YWxpemHDp8OjbzogRmFuIENoYXJ0IGRvIGltcGFjdG8gbm8gUExEIC0tLS0tLS0tLS0NCiMgPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PQ0KZ2dwbG90KG00X3BsZF9zdW1tYXJ5LCBhZXMoeCA9IFF1YXJ0ZXIsIHkgPSBkZWx0YV9QTERfbWVhbikpICsNCiAgZ2VvbV9yaWJib24oYWVzKHltaW4gPSAwLCB5bWF4ID0gZGVsdGFfUExEX3VwciksIGZpbGwgPSAicmVkIiwgYWxwaGEgPSAwLjM1KSArDQogIGdlb21fcmliYm9uKGFlcyh5bWluID0gZGVsdGFfUExEX2x3ciwgeW1heCA9IGRlbHRhX1BMRF91cHIpLCBmaWxsID0gInN0ZWVsYmx1ZSIsIGFscGhhID0gMC43NSkgKw0KDQogIGdlb21fbGluZShjb2xvciA9ICJibGFjayIpICsNCiAgZmFjZXRfd3JhcCh+IG5vbV9zdWJzaXN0ZW1hLCBzY2FsZXMgPSAiZnJlZV95IikgKw0KICBsYWJzKA0KICAgIHRpdGxlID0gIlBlbmFsaWRhZGUgY2xpbcOhdGljYSBwcm9wYWdhZGEgbm8gcHJlw6dvIGRlIGxpcXVpZGHDp8OjbyAozpRQTEQpIiwNCiAgICBzdWJ0aXRsZSA9IHBhc3RlKCJFbmNhZGVhbWVudG8gY29tcGxldG8gYXTDqSBvIG1vZGVsbyA0IHwgbnNpbSA9IiwgbnNpbSksDQogICAgeCA9ICJBbm8iLCB5ID0gIs6UUExEIChSJC9NV2gpIg0KICApICsNCiAgdGhlbWVfbWluaW1hbCgpDQpgYGANCg0KYGBge3J9DQoNCmRlbHRhX1BMRF9tYXQgJT4lDQogIGFzLmRhdGEuZnJhbWUoKSAlPiUNCiAgc2V0TmFtZXMocGFzdGUwKCJzaW1fIiwgc2VxX2xlbihuc2ltKSkpICU+JQ0KICBiaW5kX2NvbHMocGxkX2Z1bGwyWywgYygiZGF0ZSIsICJub21fc3Vic2lzdGVtYSIpXSkgJT4lDQogIHBpdm90X2xvbmdlcihzdGFydHNfd2l0aCgic2ltXyIpLCB2YWx1ZXNfdG8gPSAiZGVsdGFfUExEIikgJT4lDQogIG11dGF0ZShRdWFydGVyICA9IGx1YnJpZGF0ZTo6Zmxvb3JfZGF0ZShkYXRlLCAiMyBtb250aHMiKSkgJT4lDQogIGdyb3VwX2J5KG5vbV9zdWJzaXN0ZW1hLCBuYW1lKSAlPiUNCiAgc3VtbWFyaXNlKA0KICAgIGRlbHRhX1BMRF9zdW0gPSBtZWFuKC1kZWx0YV9QTEQsIG5hLnJtID0gVFJVRSksDQogICAgLmdyb3VwcyA9ICJkcm9wIg0KICApICU+JQ0KICBncm91cF9ieShub21fc3Vic2lzdGVtYSkgJT4lDQogIHN1bW1hcmlzZSgNCiAgICBkZWx0YV9QTERfbWVhbiA9IG1lYW4oZGVsdGFfUExEX3N1bSwgbmEucm0gPSBUUlVFKSwNCiAgICBkZWx0YV9QTERfbHdyICA9IHF1YW50aWxlKGRlbHRhX1BMRF9zdW0sIDAuMDUsIG5hLnJtID0gVFJVRSksDQogICAgZGVsdGFfUExEX3VwciAgPSBxdWFudGlsZShkZWx0YV9QTERfc3VtLCAwLjk1LCBuYS5ybSA9IFRSVUUpLA0KICAgIGRlbHRhX1BMRF9zZCAgID0gc2QoZGVsdGFfUExEX3N1bSwgbmEucm0gPSBUUlVFKSwNCiAgICAuZ3JvdXBzID0gImRyb3AiDQogICkgLT4gbTNfdGVybV9zdW1tYXJ5X200X3BvcnN1YnNpc3RlbWENCg0KbGlicmFyeShndCkNCm0zX3Rlcm1fc3VtbWFyeV9tNF9wb3JzdWJzaXN0ZW1hWyxjKCJub21fc3Vic2lzdGVtYSIsImRlbHRhX1BMRF9tZWFuIiwiZGVsdGFfUExEX2x3ciIsICJkZWx0YV9QTERfdXByIildICU+JSBqYW5pdG9yOjphZG9ybl90b3RhbHMoKSAlPiUgDQogIGd0KCkgJT4lDQogIGZtdF9udW1iZXIoY29sdW1ucyA9IDI6NCwgZGVjaW1hbHMgPSAxKSAlPiUNCiAgY29sc19sYWJlbCgNCiAgICBub21fc3Vic2lzdGVtYSA9ICJTdWJzeXN0ZW0iLA0KICAgIGRlbHRhX1BMRF9tZWFuID0gIm1lYW4gzpRwbGQgVGVybSAoTVdoKSIsDQogICAgZGVsdGFfUExEX2x3ciAgPSAiTG93ZXIgOTUlIiwNCiAgICBkZWx0YV9QTERfdXByICA9ICJVcHBlciA5NSUiLA0KICApICU+JQ0KICB0YWJfaGVhZGVyKA0KICAgIHRpdGxlID0gbWQoIioqQWdncmVnYXRlIGNsaW1hdGUgcGVuYWx0eSBvbiBzdG9yZWQgZW5lcmd5ICgyMDAx4oCTMjAxOCkqKiIpLA0KICAgIHN1YnRpdGxlID0gIlNpbXVsYXRlZCBtZWFuIGFuZCA5NSUgY29uZmlkZW5jZSBpbnRlcnZhbHMgcGVyIHN1YnN5c3RlbSINCiAgKQ0KYGBgDQoNCg==