Introdução e Contexto
O Problema de Negócio
A rotatividade dos funcionários (também conhecida por Employee
Attrition) é um dos maiores desafios das organizações, e um dos que
traz mais custos. Estudos indicam que o custo de substituir um
funcionário pode variar entre 50% a 200% do seu salário anual, sendo
considerados os custos de recrutamento, de formação e de perda de
produtividade.
Para além do impacto financeiro, uma taxa de turnover
elevada afeta a moral das equipas, a cultura da empresa e a continuidade
dos projetos. Por isso, a capacidade de prever quem
está em risco de sair e, mais importante, porquê, é uma
vantagem competitiva crucial para o Departamento de Recursos Humanos
(RH).
Sobre o Dataset
Neste projeto, foi utilizado o dataset “IBM HR
Analytics Employee Attrition & Performance”,
disponibilizado publicamente no Kaggle. Este conjunto de dados foi
criado por cientistas de dados da IBM e, embora seja fictício, reflete
desafios reais do mundo corporativo.
O dataset contém 1470 observações
(funcionários) e 35 variáveis (características)
Dicionário de Variáveis
A nossa variável-alvo (Target) é a
Attrition, que indica se o funcionário saiu
(“Yes”) ou permaneceu (“No”) na empresa.
As restantes variáveis podem ser agrupadas em três categorias
principais que iremos explorar:
Demográficas: Age,
Gender, MaritialStatus,
DistanceFromHome;
Dados do Trabalho: Department,
JobRole, JobLevel, OverTime,
BusinessTravel;
Compensação e Satisfação:
MonthlyIncome, PercentSalaryHike,
StockOptionLevel, JobSatisfaction,
EnvironmentSatisfaction.
Para facilitar a leitura, foram destacadas acima apenas as variáveis
mais relevantes para a análise. A lista completa das 35 variáveis e os
seus tipos de dados serão apresentados na secção técnica de inspeção de
dados.
Objetivos do Projeto
O objetivo central deste projeto é desenvolver uma solução de
People Analytics capaz de antecipar a rotatividade de
talentos e fornecer à gestão estratégias baseadas em dados. Para tal, a
análise foca-se em três pilares verticais:
Diagnóstico de Causa Raiz: Quantificar o impacto
real de fatores de risco, verificando a hipótese de que a sobrecarga de
trabalho (OverTime) e a logística
(DistanceFromHome) são catalisadores de
burnout.
Hierarquia de Retenção: Determinar, através de
algoritmos de Machine Learning, o que pesa mais na decisão de saída:
incentivos financeiros (MonthlyIncome) ou fatores
intangíveis como a Satisfação no Trabalho.
Modelação Preditiva: Treinar algoritmos de
classificação (Regressão Logística e Random Forest) para identificar
colaboradores em risco com elevada precisão, permitindo uma atuação
preventiva do RH.
Importação dos Dados e Inspeção Inicial
# Importação dos Dados
# Lemos o ficheiro original
ibm_hr <- read.csv("data/WA_Fn-UseC_-HR-Employee-Attrition.csv", sep = ";")
library(janitor)
library(dplyr)
# Limpeza e Padronização
# Aqui criamos o objeto 'ibm_clean'
ibm_clean <- ibm_hr %>%
clean_names() %>%
# Removemos colunas que não variam
select(-any_of(c("employee_count", "over18", "standard_hours", "employee_number")))
# Visualização (kable)
library(kableExtra)
ibm_clean %>%
select(age, attrition, monthly_income, job_role, over_time, total_working_years) %>%
head(10) %>%
kable(caption = "Tabela 1: Amostra das Variáveis Críticas para Análise de Rotatividade") %>%
kable_styling(bootstrap_options = c("striped", "hover", "condensed"),
full_width = T,
position = "center") %>%
row_spec(0, bold = T, color = "white", background = "#2c3e50")
Tabela 1: Amostra das Variáveis Críticas para Análise de Rotatividade
|
age
|
attrition
|
monthly_income
|
job_role
|
over_time
|
total_working_years
|
|
41
|
Yes
|
5993
|
Sales Executive
|
Yes
|
8
|
|
49
|
No
|
5130
|
Research Scientist
|
No
|
10
|
|
37
|
Yes
|
2090
|
Laboratory Technician
|
Yes
|
7
|
|
33
|
No
|
2909
|
Research Scientist
|
Yes
|
8
|
|
27
|
No
|
3468
|
Laboratory Technician
|
No
|
6
|
|
32
|
No
|
3068
|
Laboratory Technician
|
No
|
8
|
|
59
|
No
|
2670
|
Laboratory Technician
|
Yes
|
12
|
|
30
|
No
|
2693
|
Laboratory Technician
|
No
|
1
|
|
38
|
No
|
9526
|
Manufacturing Director
|
No
|
10
|
|
36
|
No
|
5237
|
Healthcare Representative
|
No
|
17
|
A base de dados é composta por 35 variáveis que
abrangem três dimensões centrais: características
demográficas, fatores financeiros e
indicadores de desempenho profissional.
Nesta fase inicial, a análise incide sobre variáveis com maior
potencial explicativo da rotatividade de colaboradores,
nomeadamente a remuneração mensal, os anos totais de
antiguidade na empresa e a realização de horas
extra.
Evidências empíricas e análises preliminares apontam para uma relação
significativa entre estes fatores e a probabilidade de saída dos
colaboradores, constituindo, por isso, pontos de partida
fundamentais para o aprofundamento da análise.
Análise Exploratória dos Dados (AED)
Esta fase tem como principal objetivo compreender a distribuição das
variáveis e identificar padrões ou relações que possam explicar o
fenómeno da rotatividade de colaboradores (employee
attrition).
Inicia-se a exploração pela variável alvo, Attrition,
que indica se o colaborador permaneceu na empresa
(No) ou optou pela saída
(Yes).
A análise desta variável fornece uma primeira perceção acerca do
equilíbrio entre colaboradores ativos e aqueles que deixaram a
organização, permitindo avaliar a dimensão real do fenómeno de
saída.
Análise da Variável Target (Attrition)
Quantos funcionários efetivamente saíram da empresa?
# Criar a Tabela de Frequência Profissional
tabela_target <- ibm_clean %>%
count(attrition) %>%
mutate(
percentagem = (n / sum(n)) * 100,
attrition = ifelse(attrition == "Yes", "Saiu (Yes)", "Permaneceu (No)")
)
# Exibir Tabela com o kableExtra
tabela_target %>%
kable(
caption = "Distribuição da Variável-Target (Attrition)",
col.names = c("Status", "Total (n)", "Percentagem (%)"),
digits = 1
) %>%
kable_styling(bootstrap_options = c("striped", "hover"), full_width = F) %>%
row_spec(0, bold = T, color = "white", background = "#2c3e50") %>%
column_spec(3, bold = T, color = ifelse(tabela_target$percentagem < 20, "#e74c3c", "#2c3e50"))
Distribuição da Variável-Target (Attrition)
|
Status
|
Total (n)
|
Percentagem (%)
|
|
Permaneceu (No)
|
1233
|
83.9
|
|
Saiu (Yes)
|
237
|
16.1
|
# Visualização
ggplot(ibm_clean, aes(x = attrition, fill = attrition)) +
geom_bar(width = 0.6, alpha = 0.9) +
scale_fill_manual(values = c("No" = "#2C3E50", "Yes" = "#E74C3C")) +
scale_y_continuous(expand = expansion(mult = c(0, 0.1))) +
labs(
title = "Visão Geral da Rotatividade na Empresa",
subtitle = "Apenas 16% dos colaboradores deixaram a organização no período analisado",
x = "Decisão de Saída",
y = "Número de Funcionários"
) +
theme_minimal() +
theme(
legend.position = "none",
plot.title = element_text(face = "bold", size = 16, color = "#2c3e50"),
panel.grid.major.x = element_blank()
)
Insight Inicial: Verifica-se que a
taxa de rotatividade (Attrition Rate) é de
aproximadamente 16%, o que indica que a maioria dos
colaboradores (cerca de 84%) permaneceu na empresa durante o período
analisado.
Observa-se, assim, um desequilíbrio entre as classes
da variável alvo, com predominância de colaboradores que não saíram da
organização.
Este ponto é particularmente relevante para etapas posteriores de
modelação preditiva, uma vez que a desproporção entre
classes pode levar o modelo a sobrevalorizar a classe
maioritária (colaboradores que ficam) e negligenciar os casos
de saída, que são precisamente os que mais interessam compreender e
prever.
Análise Demográfica: A Idade Influencia?
Vamos analisar a distribuição de idade entre os funcionários que
saíram e os que ficaram. Utilizamos um Boxplot para visualizar a mediana
e a dispersão dos dados.
# Gráfico: Distribuição de Idade por Rotatividade
ggplot(ibm_clean, aes(x = attrition, y = age, fill = attrition)) +
geom_jitter(alpha = 0.2, color = "grey40", width = 0.2) +
geom_boxplot(alpha = 0.8, outlier.colour = "red", width = 0.5) +
# Cores consistentes com o resto do relatório
scale_fill_manual(values = c("No" = "#2C3E50", "Yes" = "#E74C3C")) +
labs(
title = "O Fator Idade na Retenção de Talento",
subtitle = "Colaboradores que saem (Yes) apresentam uma mediana de idade visivelmente inferior",
x = "Decisão de Saída",
y = "Idade (Anos)"
) +
theme_minimal() +
theme(
legend.position = "none",
plot.title = element_text(face = "bold", size = 16, color = "#2c3e50"),
panel.grid.major.x = element_blank(),
axis.title = element_text(face = "bold")
)

Insights sobre a Idade:
A análise do boxplot evidencia uma tendência clara na relação entre
idade e rotatividade de
colaboradores:
Fator Juventude – Verifica-se uma tendência
segundo a qual os colaboradores mais jovens apresentam uma maior
propensão para sair da empresa. A mediana de idade dos
funcionários que saem é visivelmente inferior à dos que
permanecem.
Zona de Risco – A maior concentração de saídas
situa-se entre os 25 e os 35 anos, faixa etária
frequentemente associada a mobilidade profissional e
procura de progressão na carreira. Este comportamento
pode refletir desafios da organização em reter talento
jovem ou em oferecer planos de desenvolvimento
estruturados.
Estabilidade Sénior – Colaboradores com
mais de 40 anos apresentam maior
estabilidade e menor probabilidade de saída.
As poucas ocorrências nesta faixa etária surgem como outliers
no gráfico, sugerindo casos pontuais de saída da empresa (por exemplo,
reforma, mudança pessoal ou reestruturação interna).
Conclusão: Os resultados sugerem a necessidade de
uma estratégia de retenção segmentada:
Colaboradores júniores e intermédios (25-35
anos) devem ser alvo de ações focadas em engagement, progressão
interna e gestão de expectativas de carreira;
Já para os colaboradores séniores, o foco poderá
ser reconhecimento, mentoria e transmissão de know-how,
reforçando o sentimento de pertença e continuidade
organizacional.
# Gráfico de Barras: Proporção de Saída por Estado Civil
ggplot(ibm_clean, aes(x = marital_status, fill = attrition)) +
geom_bar(position = "fill", width = 0.7, alpha = 0.9) +
scale_fill_manual(values = c("No" = "#2C3E50", "Yes" = "#E74C3C")) +
# Formatação do eixo Y para percentagem
scale_y_continuous(labels = scales::percent_format(), expand = c(0,0)) +
labs(
title = "Impacto do Estado Civil na Retenção",
subtitle = "Colaboradores solteiros apresentam uma taxa de saída significativamente superior",
x = "Estado Civil",
y = "Proporção de Funcionários",
fill = "Saída?"
) +
theme_minimal() +
theme(
plot.title = element_text(face = "bold", size = 16, color = "#2c3e50"),
legend.position = "top",
panel.grid.major.x = element_blank(),
axis.text.x = element_text(face = "bold")
)
Insights sobre o Estado Civil:
A análise sugere que o estado civil constitui um
fator relevante na rotatividade de colaboradores:
Maior risco entre colaboradores solteiros – Os
trabalhadores solteiros registam uma taxa de saída superior a
25%, mais do dobro da observada entre colaboradores casados ou
divorciados (aproximadamente 11%). Este resultado indica que a
probabilidade de saída está significativamente associada ao estado
civil.
Possível explicação comportamental – Este padrão
é consistente com evidência empírica na literatura de recursos humanos,
que aponta que profissionais sem dependentes ou laços familiares diretos
tendem a apresentar maior mobilidade laboral. Essa flexibilidade
geográfica e financeira pode facilitar a procura de novas oportunidades
ou a aceitação de propostas em diferentes locais.
Conclusão: A gestão de talento poderá beneficiar de
estratégias diferenciadas de retenção entre grupos,
promovendo, por exemplo, iniciativas de progressão de carreira e
programas de envolvimento organizacional que aumentem o compromisso dos
colaboradores mais jovens e solteiros com a empresa.
Análise Profissional: Carga de Trabalho e Viagens
Será que o excesso de trabalho (OverTime) e as viagens
frequentes (BusinessTravel) levam à exaustão e consequente
saída?
# Gráfico de Horas Extra (p1)
p1 <- ggplot(ibm_clean, aes(x = over_time, fill = attrition)) +
geom_bar(position = "fill", width = 0.7, alpha = 0.9) +
scale_y_continuous(labels = scales::percent_format(), expand = c(0,0)) +
scale_fill_manual(values = c("No" = "#2C3E50", "Yes" = "#E74C3C")) +
labs(
title = "Impacto das Horas Extra",
x = "Faz Horas Extra?",
y = "Proporção"
) +
theme_minimal() +
theme(
legend.position = "none",
plot.title = element_text(face = "bold", size = 13, color = "#2c3e50"),
panel.grid.major.x = element_blank()
)
# Gráfico de Viagens de Trabalho (p2)
p2 <- ggplot(ibm_clean, aes(x = business_travel, fill = attrition)) +
geom_bar(position = "fill", width = 0.7, alpha = 0.9) +
scale_y_continuous(labels = scales::percent_format(), expand = c(0,0)) +
scale_fill_manual(values = c("No" = "#2C3E50", "Yes" = "#E74C3C")) +
labs(
title = "Impacto das Viagens",
x = "Frequência de Viagens",
y = NULL,
fill = "Saída?"
) +
theme_minimal() +
theme(
plot.title = element_text(face = "bold", size = 13, color = "#2c3e50"),
axis.text.x = element_text(angle = 45, hjust = 1),
panel.grid.major.x = element_blank()
)
# Juntar as duas visualizações
library(gridExtra)
grid.arrange(p1, p2, ncol = 2, top = grid::textGrob("Análise de Carga de Trabalho e Mobilidade",
gp = grid::gpar(fontsize = 16, font = 2, col = "#2c3e50")))
Insights sobre Carga de Trabalho e Estilo de
Vida:
A análise da carga de trabalho e da mobilidade profissional revela
uma associação evidente entre exaustão e rotatividade de
colaboradores:
Impacto das Horas Extra – O efeito das horas
extra é particularmente expressivo. Colaboradores que não realizam horas
extra apresentam uma taxa de saída próxima de 10%, enquanto entre os que
trabalham além do horário regular, essa proporção triplica para cerca de
30%. Este resultado constitui um indicador claro de risco de
burnout e sugere que o excesso de carga horária pode estar
associado à insatisfação e desgaste emocional.
O Peso da Mobilidade
(BusinessTravel) – Observa-se uma tendência crescente entre
frequência de viagens e probabilidade de saída:
Colaboradores que não viajam
(Non‑Travel) apresentam a menor taxa de rotatividade
(<10%);
Entre os que viajam com frequência
(Travel_Frequently), o risco aproxima‑se dos 25%, indicando
que o equilíbrio entre vida pessoal e profissional se encontra
consideravelmente comprometido.
Conclusão: Tanto a sobrecarga de trabalho como a
mobilidade excessiva surgem como fatores de risco relevantes para a
retenção de talento. Políticas organizacionais que promovam limites
saudáveis de jornada, flexibilidade laboral e equilíbrio vida‑trabalho
poderão mitigar significativamente este tipo de rotatividade.
Análise Financeira: O Salário Importa?
Foi analisada a distribuição salarial (MonthlyIncome)
para entender se salários mais baixos impulsionam a saída.
# Gráfico de Densidade: Salário Mensal por Rotatividade
ggplot(ibm_clean, aes(x = monthly_income, fill = attrition)) +
geom_density(alpha = 0.7, color = "white") +
scale_fill_manual(values = c("No" = "#2C3E50", "Yes" = "#E74C3C")) +
# Formatação do eixo X para Moeda (Dólar)
scale_x_continuous(labels = scales::dollar_format(), breaks = seq(0, 20000, 2500)) +
labs(
title = "Distribuição Salarial e o Risco de Rotatividade",
subtitle = "A probabilidade de saída é drasticamente superior em faixas salariais abaixo dos $5.000",
x = "Salário Mensal (USD)",
y = "Densidade de Colaboradores",
fill = "Status de Saída"
) +
theme_minimal() +
theme(
plot.title = element_text(face = "bold", size = 16, color = "#2c3e50"),
legend.position = "top",
panel.grid.minor = element_blank(),
panel.grid.major.x = element_blank()
)

Insights Financeiros:
A análise da distribuição salarial evidencia que a
remuneração é um fator determinante na probabilidade de
saída, apresentando um padrão bastante distinto entre as faixas de
rendimento:
**A barreira dos 5000\(** – Observa‑se
uma concentração significativa de saídas entre colaboradores com
salários mensais inferiores a 5000\) Nesta faixa, a densidade de
casos de attrition é substancialmente superior, sugerindo que
níveis salariais mais baixos estão associados a uma maior volatilidade
da força de trabalho.
Retenção em faixas salariais elevadas – À medida
que o salário aumenta (particularmente acima dos 10000$), a
probabilidade de saída reduz drasticamente. Entre os colaboradores com
rendimentos mais altos, a curva de densidade associada à permanência é
claramente predominante, indicando maior estabilidade e satisfação
profissional.
Conclusão: O padrão observado sugere que a empresa
enfrenta maiores desafios de retenção entre colaboradores de nível
operacional e funções júniores, onde a compensação pode não estar
alinhada com as expectativas do mercado. Estratégias salariais mais
competitivas, complementadas por planos de progressão e valorização
interna, poderão ser decisivas para reduzir a rotatividade nestas faixas
salariais.
Análise de Função e Satisfação
Antes de avançarmos para as correlações numéricas, falta analisar
duas variáveis categóricas cruciais: o Cargo (JobRole) e a
Satisfação no Trabalho (JobSatisfaction).
O objetivo é identificar se existem cargos específicos com maior
rotatividade.
# Rotatividade por Cargo
p_role <- ggplot(ibm_clean, aes(y = reorder(job_role, (attrition == "Yes")), fill = attrition)) +
geom_bar(position = "fill", width = 0.7, alpha = 0.9) +
scale_x_continuous(labels = scales::percent_format(), expand = c(0,0)) +
scale_fill_manual(values = c("No" = "#2C3E50", "Yes" = "#E74C3C")) +
labs(
title = "Rotatividade por Cargo",
subtitle = "Vendas, RH e Técnicos de Laboratório apresentam maior risco",
y = NULL,
x = "Proporção de Saída"
) +
theme_minimal() +
theme(
legend.position = "none",
plot.title = element_text(face = "bold", size = 13, color = "#2c3e50"),
panel.grid.major.y = element_blank(),
axis.text.y = element_text(size = 9, face = "bold")
)
# Impacto da Satisfação
p_sat <- ggplot(ibm_clean, aes(x = factor(job_satisfaction), fill = attrition)) +
geom_bar(position = "fill", width = 0.6, alpha = 0.9) +
scale_y_continuous(labels = scales::percent_format(), expand = c(0,0)) +
scale_fill_manual(values = c("No" = "#2C3E50", "Yes" = "#E74C3C")) +
labs(
title = "Impacto da Satisfação no Trabalho",
subtitle = "Níveis baixos de satisfação (1 e 2) correlacionam-se com maior churn",
x = "Nível de Satisfação (1: Baixa → 4: Alta)",
y = "Proporção",
fill = "Saída?"
) +
theme_minimal() +
theme(
plot.title = element_text(face = "bold", size = 13, color = "#2c3e50"),
legend.position = "right",
panel.grid.major.x = element_blank()
)
library(gridExtra)
grid.arrange(p_role, p_sat, nrow = 2,
top = grid::textGrob("Análise de Função e Sentimento",
gp = grid::gpar(fontsize = 16, font = 2, col = "#2c3e50")))
Insights sobre Função e Satisfação:
A análise evidencia padrões distintos de rotatividade por
função, revelando áreas críticas dentro da organização:
Funções de Vendas (Sales
Representatives) – Este grupo apresenta a maior taxa de
saída, próxima dos 40%, o que é indicativo de pressão comercial elevada,
objetivos exigentes ou sistemas de incentivos pouco atrativos. Trata‑se
de um foco prioritário de atuação, dada a importância estratégica destas
funções para o desempenho global da empresa.
Técnicos de Laboratório e Recursos Humanos –
Ambas as funções registam taxas de saída em torno dos 25%, claramente
acima da média organizacional.
Retenção nas funções de liderança – Os cargos de
gestão e direção (Managers e Directors) apresentam
níveis de estabilidade muito elevados, o que sugere que a rotatividade é
predominantemente um fenómeno dos níveis hierárquicos intermédios e
operacionais. Este padrão revela a importância de direcionar as
estratégias de retenção e desenvolvimento para as funções mais
vulneráveis.
Conclusão: A rotatividade parece concentrar‑se em
posições de base e funções de suporte operacional, exigindo políticas
focadas em melhoria do clima organizacional, revisão de incentivos e
oportunidades de progressão, por forma a fortalecer o compromisso e a
retenção nestes grupos.
Análise da Antiguidade e Tempo de Deslocação
Foi investigada a antiguidade na empresa
(YearsAtCompany) e a distância de casa
(DistanceFromHome). O objetivo é entender se perdemos
talento recém-contratado e se o trajeto diário influencia a decisão.
# Gráfico de Antiguidade (Anos na Empresa)
p_years <- ggplot(ibm_clean, aes(x = years_at_company, fill = attrition)) +
geom_density(alpha = 0.7, color = "white") +
scale_fill_manual(values = c("No" = "#2C3E50", "Yes" = "#E74C3C")) +
labs(
title = "Ciclo de Vida: Antiguidade na Empresa",
subtitle = "O risco de 'churn' é crítico nos primeiros 2 anos (período de onboarding)",
x = "Anos na Empresa",
y = "Densidade"
) +
theme_minimal() +
theme(
legend.position = "none",
plot.title = element_text(face = "bold", size = 13, color = "#2c3e50"),
panel.grid.minor = element_blank()
)
# Gráfico de Distância (Boxplot)
p_dist <- ggplot(ibm_clean, aes(x = attrition, y = distance_from_home, fill = attrition)) +
geom_boxplot(alpha = 0.8, width = 0.6, outlier.colour = "#E74C3C") +
scale_fill_manual(values = c("No" = "#2C3E50", "Yes" = "#E74C3C")) +
labs(
title = "Logística: Distância Casa-Trabalho",
subtitle = "Colaboradores que saem tendem a percorrer distâncias maiores",
x = "Decisão de Saída",
y = "Distância (km/milhas)"
) +
theme_minimal() +
theme(
plot.title = element_text(face = "bold", size = 13, color = "#2c3e50"),
panel.grid.major.x = element_blank()
)
# Organizar os gráficos
library(gridExtra)
grid.arrange(p_years, p_dist, nrow = 2,
top = grid::textGrob("Análise de Retenção e Logística",
gp = grid::gpar(fontsize = 16, font = 2, col = "#2c3e50")))
Insights de Tempo e Logística:
A análise evidencia pontos críticos no ciclo de vida do colaborador,
com implicações diretas para a retenção e o desempenho
organizacional:
Fase de Onboarding - Risco de saída
precoce: O gráfico de antiguidade mostra um pico acentuado de
rotatividade nos primeiros dois anos de vínculo, precisamente durante o
período de integração e adaptação. Este resultado sugere fragilidades
nos processos de acolhimento, acompanhamento inicial ou alinhamento de
expectativas entre o colaborador e a organização. Investir em programas
estruturados de onboarding e mentoria poderá reduzir
substancialmente este tipo de perda prematura de talento.
Custo da Deslocação – Fator logístico de
desgaste: O boxplot de distâncias casa‑trabalho indica que os
colaboradores que saem tendem a percorrer trajetos mais longos, o que
aponta para um potencial impacto negativo do tempo e esforço de
deslocação na satisfação geral. O desgaste associado ao
commuting diário, quando combinado com elevadas cargas de
trabalho, aumenta a probabilidade de saída voluntária. Medidas como
teletrabalho híbrido, adaptação de horários ou incentivos de transporte
podem mitigar esse efeito.
Conclusão: A retenção eficaz exige uma abordagem
holística que abranja tanto a experiência inicial do colaborador
(onboarding) como a sustentabilidade logística da sua rotina
laboral. Estas duas dimensões revelam‑se determinantes para consolidar o
compromisso organizacional nos primeiros anos de vínculo.
Análise do Género e Work-Life Balance
# Rotatividade por Género (p_gen)
p_gen <- ggplot(ibm_clean, aes(x = gender, fill = attrition)) +
geom_bar(position = "fill", width = 0.6, alpha = 0.9) +
scale_y_continuous(labels = scales::percent_format(), expand = c(0,0)) +
scale_fill_manual(values = c("No" = "#2C3E50", "Yes" = "#E74C3C")) +
labs(
title = "Rotatividade por Género",
subtitle = "Existe disparidade entre homens e mulheres?",
x = NULL,
y = "Proporção"
) +
theme_minimal() +
theme(
legend.position = "none", # Escondemos a legenda aqui para não repetir
plot.title = element_text(face = "bold", size = 13, color = "#2c3e50"),
panel.grid.major.x = element_blank(),
axis.text.x = element_text(face = "bold")
)
# Análise do Work-Life Balance (p_wlb)
p_wlb <- ggplot(ibm_clean, aes(x = factor(work_life_balance), fill = attrition)) +
geom_bar(position = "fill", width = 0.6, alpha = 0.9) +
scale_y_continuous(labels = scales::percent_format(), expand = c(0,0)) +
scale_fill_manual(values = c("No" = "#2C3E50", "Yes" = "#E74C3C")) +
labs(
title = "Equilíbrio Vida-Trabalho",
subtitle = "O impacto do equilíbrio na decisão de saída",
x = "Nível (1: Mau → 4: Excelente)",
y = NULL,
fill = "Saída?"
) +
theme_minimal() +
theme(
plot.title = element_text(face = "bold", size = 13, color = "#2c3e50"),
legend.position = "right",
panel.grid.major.x = element_blank(),
axis.text.x = element_text(face = "bold")
)
# Juntar os dois lado a lado
library(gridExtra)
grid.arrange(p_gen, p_wlb, ncol = 2,
top = grid::textGrob("Bem-Estar e Diversidade",
gp = grid::gpar(fontsize = 16, font = 2, col = "#2c3e50")))
Insights de Género e Bem-Estar:
Para concluir a análise bivariada, destacam‑se dois fatores de
natureza social e comportamental com impacto na rotatividade:
Neutralidade de Género – A taxa de saída
revela‑se relativamente uniforme entre homens e mulheres, situando‑se
entre 15% e 17%. Este resultado sugere ausência de enviesamentos ou
práticas discriminatórias associadas ao género, bem como equidade na
experiência organizacional entre grupos.
Equilíbrio Vida‑Trabalho – A variável
Work‑Life Balance evidencia um “ponto crítico” no nível mais
baixo de satisfação. Colaboradores que classificam o seu equilíbrio como
“Mau” (Nível 1) apresentam uma taxa de rotatividade próxima de 30%, o
dobro da verificada nos restantes níveis. A melhoria do equilíbrio
vida‑trabalho, mesmo que apenas de Nível 1 para Nível 2, já produz uma
redução substancial na taxa de saída. Isto indica que intervenções
pontuais e realistas, como ajustes de horário, políticas de
flexibilidade ou reforço do apoio à equipa, podem gerar efeitos
imediatos na retenção, sem ser necessário atingir níveis “ideais” de
satisfação (Nível 4).
Conclusão: Os resultados apontam para uma cultura
organizacional relativamente equilibrada em termos de género, mas
vulnerável a fatores ligados ao bem‑estar e equilíbrio
pessoal‑profissional. Investir em políticas de saúde ocupacional e
flexibilidade laboral poderá ter um retorno direto na satisfação e
fidelização dos colaboradores.
Análise Multivariada (Correlações)
Nesta etapa, foi analisada a relação entre as variáveis numéricas
para identificar multicolinearidade (redundância). Foi utilizada uma
matriz de correlação visual.
ibm_numeric <- ibm_clean %>% select(where(is.numeric))
matriz_cor <- cor(ibm_numeric, use = "complete.obs")
# Gráfico de correlações
col_paleta <- colorRampPalette(c("#E74C3C", "#FFFFFF", "#2C3E50"))(200)
corrplot(matriz_cor,
method = "color",
type = "upper",
order = "hclust",
tl.col = "black",
tl.cex = 0.7,
col = col_paleta,
title = "\n Mapa de Correlações Intervariáveis",
mar = c(0,0,2,0),
diag = FALSE)

# Tabela de correlações
tabela_cor <- as.data.frame(as.table(matriz_cor))
tabela_melhorada <- tabela_cor %>%
filter(Var1 != Var2) %>%
filter(!duplicated(paste0(pmax(as.character(Var1), as.character(Var2)),
pmin(as.character(Var1), as.character(Var2))))) %>%
arrange(desc(abs(Freq))) %>%
rename(Variavel_1 = Var1, Variavel_2 = Var2, Correlacao = Freq)
# Melhorar design da tabela
kable(head(tabela_melhorada, 10),
caption = "Top 10 Correlações Mais Fortes Identificadas",
digits = 2,
col.names = c("Variável 1", "Variável 2", "Força da Correlação")) %>%
kable_styling(
bootstrap_options = c("striped", "hover", "condensed"),
full_width = T,
position = "center",
font_size = 14
) %>%
row_spec(0, bold = T, color = "white", background = "#2c3e50") %>%
# Destaca em vermelho as correlações que podem causar multicolinearidade (>0.7)
column_spec(3, bold = T,
color = ifelse(abs(head(tabela_melhorada$Correlacao, 10)) > 0.7, "#E74C3C", "black"))
Top 10 Correlações Mais Fortes Identificadas
|
Variável 1
|
Variável 2
|
Força da Correlação
|
|
monthly_income
|
job_level
|
0.95
|
|
total_working_years
|
job_level
|
0.78
|
|
performance_rating
|
percent_salary_hike
|
0.77
|
|
total_working_years
|
monthly_income
|
0.77
|
|
years_with_curr_manager
|
years_at_company
|
0.77
|
|
years_in_current_role
|
years_at_company
|
0.76
|
|
years_with_curr_manager
|
years_in_current_role
|
0.71
|
|
total_working_years
|
age
|
0.68
|
|
years_at_company
|
total_working_years
|
0.63
|
|
years_since_last_promotion
|
years_at_company
|
0.62
|
Insights da Análise de Correlação:
A matriz e a tabela de correlações evidenciam padrões de
multicolinearidade significativos, revelando variáveis fortemente
redundantes que exigirão tratamento específico na fase de
pré‑processamento dos dados:
- Redundância entre remuneração e nível hierárquico:
A correlação mais elevada de todo o conjunto é observada entre
MonthlyIncome e JobLevel (r = 0.95).
Interpretação: Estas variáveis são, na prática,
estatisticamente sobrepostas, pelo que o nível do cargo determina quase
totalmente o salário. Manter ambas no modelo poderá introduzir
instabilidade nos coeficientes e enviesar a importância preditiva.
Assim, será recomendável reter apenas uma variável representativa (por
exemplo, JobLevel).
- Antiguidade: Identifica‑se um cluster de
variáveis temporais altamente correlacionadas,
YearsAtCompany, YearsInCurrentRole e
YearsWithCurrManager, com correlações entre 0.71 e
0.77.
Interpretação: Funcionários com maior antiguidade
tendem a permanecer na mesma função e sob a mesma liderança. Convém,
portanto, evitar incluir todas simultaneamente, podendo optar‑se por
YearsAtCompany ou pela criação de uma variável agregada de
“estagnação”, que capture esta dinâmica.
- Experiência profissional e remuneração: A variável
TotalWorkingYears apresenta correlação forte com
JobLevel (0.78) e MonthlyIncome (0.77).
Interpretação: O sistema de progressão e compensação
da empresa aparenta estar altamente alinhado com a senioridade,
valorizando sobretudo a experiência acumulada.
- Desempenho e recompensas: A correlação de 0.77
entre
PerformanceRating e PercentSalaryHike
confirma que os aumentos salariais estão diretamente associados à
avaliação de desempenho anual — uma política típica de meritocracia
organizacional.
Conclusão da Análise Exploratória (EDA): A
exploração bivariada e correlacional permite concluir que a rotatividade
está associada a fatores demográficos e laborais (idade jovem, cargos
operacionais, viagens frequentes, salários mais baixos), enquanto no
plano técnico destacam‑se relações redundantes entre variáveis de
hierarquia, antiguidade e remuneração.
Estas constatações constituem o ponto de partida para o
pré‑processamento de dados, onde serão tratadas as correlações
excessivas e selecionadas as variáveis mais relevantes para os modelos
preditivos.
Pré-processamento de dados
Seleção de variáveis (Feature Selection)
# Executar a Seleção
ibm_prep <- ibm_clean %>%
select(-job_level) %>%
select(-any_of(c("employee_number", "employee_count", "over18", "standard_hours"))) %>%
mutate(attrition = ifelse(attrition == "Yes", 1, 0))
# Criar Tabela de Impacto
resumo_prep <- data.frame(
Etapa = c("Colunas Originais", "Colunas Removidas", "Total Final", "Target (Attrition)"),
Valor = c(ncol(ibm_clean),
ncol(ibm_clean) - ncol(ibm_prep),
ncol(ibm_prep),
"Convertido para Binário (0/1)")
)
resumo_prep %>%
kable(caption = "Resumo do Pré-processamento e Feature Selection") %>%
kable_styling(bootstrap_options = c("striped", "hover", "condensed"), full_width = F) %>%
row_spec(0, bold = T, color = "white", background = "#2c3e50")
Resumo do Pré-processamento e Feature Selection
|
Etapa
|
Valor
|
|
Colunas Originais
|
31
|
|
Colunas Removidas
|
1
|
|
Total Final
|
30
|
|
Target (Attrition)
|
Convertido para Binário (0/1)
|
Após a fase de análise exploratória, procedeu‑se à preparação dos
dados para a modelação preditiva.
Esta etapa é fundamental para garantir que o modelo resultante não
seja influenciado por ruído estatístico nem por informação redundante,
assegurando a robustez e interpretabilidade dos resultados.
Principais decisões nesta fase:
Eliminação de redundância (multicolinearidade) –
Conforme identificado na matriz de correlações, as variáveis
monthly_income e job_level apresentavam uma
correlação de 0,95. Para evitar sobreajuste (overfitting) e
simplificar o modelo, decidiu‑se manter apenas a variável mais
representativa, privilegiando o impacto financeiro direto.
Conversão da variável‑alvo – A variável
attrition foi transformada para formato binário (0/1), de
modo a permitir a aplicação de modelos de classificação supervisionada e
facilitar a análise de desempenho preditivo.
Estas operações asseguram que o conjunto de dados final esteja
estatisticamente equilibrado, computacionalmente eficiente e adequado à
fase seguinte de modelação.
Criação de Dummies
library(fastDummies)
ibm_final <- dummy_cols(ibm_prep,
remove_first_dummy = TRUE,
remove_selected_columns = TRUE) %>%
clean_names() # Garante que os nomes das novas colunas ficam padronizados
# Criar uma comparação visual
comparativo_dim <- data.frame(
Metrica = c("Colunas Pré-Dummies", "Colunas Pós-Dummies (Expandidas)", "Novas Variáveis Criadas"),
Quantidade = c(ncol(ibm_prep), ncol(ibm_final), ncol(ibm_final) - ncol(ibm_prep))
)
# Exibir Tabela de Impacto
comparativo_dim %>%
kable(caption = "Impacto da Transformação de Variáveis Categóricas (One-Hot Encoding)") %>%
kable_styling(bootstrap_options = c("striped", "hover", "condensed"), full_width = F) %>%
row_spec(0, bold = T, color = "white", background = "#2c3e50")
Impacto da Transformação de Variáveis Categóricas (One-Hot Encoding)
|
Metrica
|
Quantidade
|
|
Colunas Pré-Dummies
|
30
|
|
Colunas Pós-Dummies (Expandidas)
|
44
|
|
Novas Variáveis Criadas
|
14
|
# Mostrar as novas colunas
data.frame(Exemplos_Novas_Colunas = colnames(ibm_final)[(ncol(ibm_prep)+1):(ncol(ibm_prep)+6)]) %>%
kable() %>%
kable_styling(bootstrap_options = "bordered", full_width = F, position = "float_right")
|
Exemplos_Novas_Colunas
|
|
education_field_other
|
|
education_field_technical_degree
|
|
gender_male
|
|
job_role_human_resources
|
|
job_role_laboratory_technician
|
|
job_role_manager
|
A maioria dos algoritmos de Machine Learning não é capaz de processar
diretamente variáveis de texto.
Para ultrapassar esta limitação, aplicou‑se a técnica de One‑Hot
Encoding, também conhecida por criação de variáveis dummy.
Procedimentos realizados:
Transformação de variáveis categóricas –
Variáveis qualitativas, como BusinessTravel ou
Department, foram convertidas em múltiplas colunas binárias
(0/1), representando a presença ou ausência de cada categoria
distinta.
Prevenção de multicolinearidade – Para evitar a
chamada dummy variable trap, foi ativado o parâmetro
remove_first_dummy = TRUE, o que remove uma categoria de
cada grupo. Assim, por exemplo, no caso de uma variável com as
modalidades Masculino e Feminino, apenas uma delas é mantida, dado que a
ausência de uma implica a presença da outra.
Expansão controlada do dataset – Após o
processo, o número total de variáveis aumentou de 30 para 44, resultando
na criação de 14 novas variáveis derivadas.
Esta expansão permite representar de forma mais rica a informação
qualitativa, sem introduzir redundância ou comprometer a estabilidade
dos modelos preditivos.
Divisão dos Dados (Treino e Teste)
library(caTools)
library(dplyr)
library(kableExtra)
# Divisão Estratificada
set.seed(123)
split <- sample.split(ibm_final$attrition, SplitRatio = 0.70)
dados_treino <- subset(ibm_final, split == TRUE)
dados_teste <- subset(ibm_final, split == FALSE)
# Criar Tabela de Resumo
resumo_split <- data.frame(
Conjunto = c("Treino (70%)", "Teste (30%)", "Total"),
Observações = c(nrow(dados_treino), nrow(dados_teste), nrow(ibm_final)),
Taxa_Churn = c(
paste0(round(mean(dados_treino$attrition) * 100, 1), "%"),
paste0(round(mean(dados_teste$attrition) * 100, 1), "%"),
paste0(round(mean(ibm_final$attrition) * 100, 1), "%")
)
)
# Exibir Tabela
resumo_split %>%
kable(caption = "Divisão de Dados: Verificação de Consistência e Estratificação") %>%
kable_styling(bootstrap_options = c("striped", "hover", "condensed"),
full_width = F,
position = "center") %>%
row_spec(0, bold = T, color = "white", background = "#2c3e50") %>%
column_spec(3, bold = T, color = "#E74C3C")
Divisão de Dados: Verificação de Consistência e Estratificação
|
Conjunto
|
Observações
|
Taxa_Churn
|
|
Treino (70%)
|
1029
|
16.1%
|
|
Teste (30%)
|
441
|
16.1%
|
|
Total
|
1470
|
16.1%
|
A divisão do conjunto de dados foi efetuada através de uma
amostragem estratificada, assegurando que a proporção
da variável‑alvo (Attrition) fosse mantida em ambos os
subconjuntos (Treino (70%) e Teste (30%)).
Conforme ilustrado na tabela, a taxa de churn
permanece rigorosamente constante em 16,1% em ambos os
conjuntos. Esta consistência estatística é essencial para evitar
distorções na amostragem, garantindo que a amostra de teste funcione
como uma réplica representativa do dataset original.
Deste modo, as métricas de desempenho obtidas durante a fase de
validação refletem de forma realista e fiável o comportamento do
fenómeno de rotatividade na organização, aumentando a credibilidade e
generalização dos resultados do modelo.
Equilíbrio de Classes
library(ROSE)
library(ggplot2)
library(gridExtra)
# Aplicar o ROSE para equilibrar apenas o conjunto de TREINO
set.seed(123)
dados_treino_bal <- ROSE(attrition ~ ., data = dados_treino, seed = 123)$data
# Criar dados para o gráfico comparativo
antes <- as.data.frame(table(dados_treino$attrition))
antes$Estado <- "1. Antes (Desequilibrado)"
depois <- as.data.frame(table(dados_treino_bal$attrition))
depois$Estado <- "2. Depois (Equilibrado com ROSE)"
comparativo <- rbind(antes, depois)
# Gráfico
ggplot(comparativo, aes(x = Var1, y = Freq, fill = Var1)) +
geom_bar(stat = "identity", width = 0.6, alpha = 0.9) +
facet_wrap(~Estado) +
scale_fill_manual(values = c("0" = "#2C3E50", "1" = "#E74C3C")) +
scale_y_continuous(expand = c(0,0), limits = c(0, max(comparativo$Freq)*1.1)) +
labs(
title = "Estratégia de Rebalanceamento de Dados (ROSE)",
subtitle = "Ajuste da classe minoritária para otimizar a aprendizagem do modelo",
x = "Status de Saída (0 = Não, 1 = Sim)",
y = "Número de Registos"
) +
theme_minimal() +
theme(
legend.position = "none",
plot.title = element_text(face = "bold", size = 14, color = "#2c3e50"),
strip.text = element_text(face = "bold", size = 11),
panel.grid.major.x = element_blank()
)
A eficácia de um modelo preditivo depende da qualidade e do equilíbrio
estatístico dos dados de treino.
Conforme identificado anteriormente, a variável‑alvo
(Attrition) apresenta um desequilíbrio
acentuado, com apenas 16,1% de casos positivos
(colaboradores que saíram da empresa). Em contextos reais, este tipo de
assimetria tende a levar o modelo a privilegiar a previsão de
permanência e a subestimar os padrões de saída.
Para mitigar este problema, aplicou‑se o algoritmo
ROSE (Random Over‑Sampling Examples) exclusivamente ao conjunto
de treino. Esta técnica gera observações sintéticas baseadas na
distribuição da classe minoritária, mantendo a coerência
estatística do dataset original.
Principais benefícios do reequilíbrio:
Nivelamento da aprendizagem – O modelo passa a
ser exposto a uma proporção equilibrada (aproximadamente 50/50) entre
colaboradores que saem e que permanecem, o que melhora a sua capacidade
de generalização.
Melhoria da sensibilidade (recall) –
Aumenta‑se a capacidade do modelo de detetar corretamente os casos de
saída, permitindo uma identificação precoce de potenciais perdas de
talento.
Preservação da integridade do teste – O
reequilíbrio foi aplicado apenas aos dados de treino, mantendo o
conjunto de teste inalterado.
Machine Learning
Modelo 1: Regressão Logística
# Treinar o Modelo
modelo_logistico <- glm(attrition ~ ., data = dados_treino_bal, family = "binomial")
# Fazer Previsões
previsoes_prob <- predict(modelo_logistico, newdata = dados_teste, type = "response")
previsoes_classe <- ifelse(previsoes_prob > 0.50, 1, 0)
# Criar Matriz de Confusão
tabela_confusao <- table(Realidade = dados_teste$attrition, Previsao = previsoes_classe)
df_confusao <- as.data.frame(tabela_confusao)
# Gráfico de Matriz de Confusão (Heatmap)
library(ggplot2)
ggplot(df_confusao, aes(x = Previsao, y = Realidade, fill = Freq)) +
geom_tile(color = "white") +
geom_text(aes(label = Freq), color = "white", size = 8, fontface = "bold") +
scale_fill_gradient(low = "#34495E", high = "#E74C3C") +
labs(title = "Matriz de Confusão: Regressão Logística",
subtitle = "Visualização de Acertos e Erros de Previsão",
x = "Previsão do Modelo (0=Fica, 1=Sai)",
y = "Realidade (0=Fica, 1=Sai)") +
theme_minimal() +
theme(legend.position = "none",
plot.title = element_text(face = "bold", size = 16),
axis.title = element_text(face = "bold"))

# Tabela de Métricas
acuracia <- sum(diag(tabela_confusao)) / sum(tabela_confusao)
sensibilidade <- tabela_confusao[2,2] / sum(tabela_confusao[2,])
metricas <- data.frame(
Métrica = c("Acurácia Total", "Sensibilidade (Recall)"),
Resultado = c(paste0(round(acuracia * 100, 2), "%"),
paste0(round(sensibilidade * 100, 2), "%"))
)
library(kableExtra)
metricas %>%
kable(caption = "Performance do Modelo 1") %>%
kable_styling(bootstrap_options = c("striped", "hover"), full_width = F) %>%
row_spec(0, bold = T, color = "white", background = "#2c3e50")
Performance do Modelo 1
|
Métrica
|
Resultado
|
|
Acurácia Total
|
72.79%
|
|
Sensibilidade (Recall)
|
73.24%
|
Análise de Desempenho do Modelo 1 (Regressão
Logística):
O primeiro modelo foi treinado com o conjunto de dados
equilibrado obtido através da técnica ROSE, apresentando uma
acurácia total de 72,79%.Embora esta métrica seja
satisfatória, a acurácia isolada não é suficiente para avaliar o
desempenho num problema de retenção de talentos, em que o custo de
prever incorretamente uma saída é particularmente elevado.
A seguir apresentam‑se os principais resultados obtidos sobre o
conjunto de teste (441 colaboradores):
- Capacidade de deteção (Recall): 73,2%
No conjunto de teste, existiam 71 colaboradores que efetivamente
saíram da empresa. O modelo identificou corretamente 52 desses 71 casos.
O algoritmo revela uma boa capacidade de deteção, conseguindo sinalizar
aproximadamente 3 em cada 4 funcionários em risco de saída. Este é o
principal ponto forte do modelo, pois assegura que a maioria dos casos
críticos é antecipada e pode ser alvo de ações preventivas por parte dos
Recursos Humanos.
- Custo dos falsos alarmes (Precisão: ~34%)
Para maximizar a deteção das saídas, o modelo tornou‑se mais
sensível, o que resultou num aumento dos falsos positivos. Foram 153
colaboradores sinalizados como potenciais saídas, mas apenas 52
realmente deixaram a empresa. O modelo gera um volume considerável de
alertas indevidos, em que cerca de 2 em cada 3 funcionários sinalizados
permaneceram na empresa. Apesar de eficaz a antecipar saídas reais, o
seu funcionamento é “hiper‑vigilante”, podendo levar a intervenções
desnecessárias e a uma sobrecarga das equipas de RH.
- Matriz de confusão:
Verdadeiros Negativos (269): colaboradores que
permaneceram e foram corretamente classificados.
Falsos Positivos (101): colaboradores que
permaneceram, mas foram classificados como risco de saída (potencial
desperdício de recursos de gestão).
Falsos Negativos (19): colaboradores que saíram,
mas não foram antecipados (perdas imprevistas).
Verdadeiros Positivos (52): colaboradores que
saíram e foram corretamente identificados (oportunidades de retenção
antecipada).
Próximo passo: Testar um modelo mais robusto, como o
Random Forest, com o objetivo de reduzir os falsos positivos sem
comprometer a boa sensibilidade alcançada pela regressão logística.
Modelo 2: Random Forest
library(randomForest)
library(caret)
library(ggplot2)
library(dplyr)
library(kableExtra)
# Preparação e Treino
dados_treino_bal$attrition <- as.factor(dados_treino_bal$attrition)
dados_teste$attrition <- as.factor(dados_teste$attrition)
set.seed(123)
modelo_rf <- randomForest(attrition ~ .,
data = dados_treino_bal,
ntree = 500,
importance = TRUE)
# Previsões e Métricas
previsoes_rf <- predict(modelo_rf, newdata = dados_teste)
conf_matrix_rf <- confusionMatrix(data = previsoes_rf,
reference = dados_teste$attrition,
positive = "1")
# Gráfico de Importância das Variáveis
imp_df <- as.data.frame(importance(modelo_rf))
imp_df$Variavel <- rownames(imp_df)
ggplot(imp_df %>% arrange(desc(MeanDecreaseAccuracy)) %>% head(15),
aes(x = reorder(Variavel, MeanDecreaseAccuracy), y = MeanDecreaseAccuracy)) +
geom_bar(stat = "identity", fill = "#2C3E50", alpha = 0.9, width = 0.7) +
coord_flip() +
labs(title = "Top 15 Preditoras de Rotatividade",
subtitle = "Quais os fatores que mais influenciam a decisão de saída?",
x = NULL, y = "Importância (Mean Decrease Accuracy)") +
theme_minimal() +
theme(plot.title = element_text(face = "bold", size = 16),
panel.grid.major.y = element_blank())

# Tabela de Performance Comparativa
metricas_rf <- data.frame(
Métrica = c("Acurácia", "Sensibilidade (Recall)", "Especificidade"),
Resultado = c(paste0(round(conf_matrix_rf$overall['Accuracy'] * 100, 2), "%"),
paste0(round(conf_matrix_rf$byClass['Sensitivity'] * 100, 2), "%"),
paste0(round(conf_matrix_rf$byClass['Specificity'] * 100, 2), "%"))
)
metricas_rf %>%
kable(caption = "Performance do Modelo Random Forest") %>%
kable_styling(bootstrap_options = c("striped", "hover"), full_width = F) %>%
row_spec(0, bold = T, color = "white", background = "#2c3e50")
Performance do Modelo Random Forest
|
Métrica
|
Resultado
|
|
Acurácia
|
74.15%
|
|
Sensibilidade (Recall)
|
70.42%
|
|
Especificidade
|
74.86%
|
O modelo Random Forest apresentou um
desempenho superior e mais equilibrado em comparação
com a Regressão Logística. Com uma acurácia global de
74,15%, este algoritmo demonstrou ser uma ferramenta robusta e
fiável para apoiar decisões estratégicas de retenção de talento.
- Equilíbrio entre deteção e precisão Diferentemente
do modelo anterior, a Random Forest revelou‑se mais precisa na distinção
entre perfis de risco e de estabilidade.
Sensibilidade (Recall) de 70,4%:
Identificou corretamente 50 dos 71 colaboradores que efetivamente saíram
da empresa.
Redução dos falsos positivos: Embora ainda
existam alertas indevidos, o modelo foi mais criterioso na sinalização
de risco, diminuindo o ruído operacional para as equipas de Recursos
Humanos.
Este equilíbrio traduz‑se numa ferramenta mais “cirúrgica”, capaz de
alcançar elevada capacidade de deteção sem sacrificar de forma
significativa a precisão das previsões.
- Principais preditores de rotatividade A análise de
importância das variáveis revela os fatores que mais influenciam a
decisão de saída, oferecendo insights de gestão extremamente
relevantes:
OverTime (Horas Extra): surge como
o preditor mais forte, indicando que colaboradores expostos a longas
jornadas apresentam propensão significativamente superior à
saída.
MonthlyIncome (Salário): confirma
que as faixas salariais mais baixas constituem a zona de maior
vulnerabilidade em termos de rotatividade.
StockOptionLevel: a ausência de
incentivos de longo prazo (como planos de ações) está associada a menor
compromisso organizacional.
Age e
TotalWorkingYears: trabalhadores mais jovens e com
menos anos de experiência mostram‑se mais propensos à mobilidade
externa.
Estes resultados corroboram a literatura de Recursos Humanos,
destacando o papel conjunto de fatores financeiros, de carga laboral e
de experiência como determinantes da rotatividade.
- Conclusão técnica e interpretativa A Random Forest
mostrou‑se capaz de captar padrões não lineares e interações complexas
que modelos lineares não conseguem representar. O algoritmo identificou,
por exemplo, que um salário médio pode ser aceitável isoladamente, mas
torna‑se fator de risco quando combinado com excesso de horas extra ou
baixa satisfação na relação com o gestor. Em suma, este modelo não
apenas melhora o desempenho preditivo, mas também fornece informação
acionável para políticas de retenção personalizadas e gestão preventiva
do talento.
Análise de Drivers de Saída (Feature Importance)
# Extrair a importância das variáveis do modelo Random Forest
importancia <- as.data.frame(importance(modelo_rf))
importancia$Variavel <- rownames(importancia)
# Criar o gráfico
library(ggplot2)
library(dplyr)
ggplot(importancia %>% arrange(desc(MeanDecreaseAccuracy)) %>% head(15),
aes(x = reorder(Variavel, MeanDecreaseAccuracy), y = MeanDecreaseAccuracy)) +
geom_bar(stat = "identity", fill = "#2C3E50", alpha = 0.9, width = 0.7) +
geom_text(aes(label = round(MeanDecreaseAccuracy, 1)),
hjust = -0.2, size = 3, fontface = "bold", color = "#2C3E50") +
coord_flip() +
scale_y_continuous(expand = expansion(mult = c(0, 0.1))) +
labs(
title = "Drivers Críticos de Attrition",
subtitle = "Variáveis que mais impactam a precisão do modelo Random Forest",
x = NULL,
y = "Importância (Mean Decrease Accuracy)"
) +
theme_minimal() +
theme(
plot.title = element_text(face = "bold", size = 16, color = "#2c3e50"),
plot.subtitle = element_text(size = 11, color = "grey40"),
panel.grid.major.y = element_blank(),
axis.text.y = element_text(face = "bold", size = 10)
)
O gráfico acima apresenta as variáveis mais determinantes identificadas
pelo modelo Random Forest, ordenadas pela métrica “Mean Decrease
Accuracy”. Em termos práticos, quanto maior a importância desta métrica,
maior é o contributo da variável para a capacidade preditiva global do
modelo, ou seja, a sua remoção resultaria numa diminuição significativa
da precisão.
- O cargo como principal determinante
(
JobRole) Quatro das cinco variáveis mais
relevantes estão relacionadas com funções específicas dentro da
organização. Destacam‑se dois extremos: Research Director
(função com elevada estabilidade) e SalesRepresentative
(função mais volátil).
Esta diferença confirma as conclusões obtidas na análise
exploratória: o nível hierárquico e o tipo de função são os fatores que
mais diferenciam o comportamento de rotatividade na empresa.
Implicação: Políticas genéricas de gestão de pessoas
(“one‑size‑fits‑all”) são ineficazes.
A estratégia de retenção deve ser personalizada por área funcional,
reconhecendo que vendas e investigação/rede de liderança exigem
abordagens de motivação e reconhecimento distintas.
O peso das horas extra (OverTime) A
variável over_time_yes surge como o terceiro preditor mais
crítico de todo o conjunto. Este resultado reforça a evidência de que a
sobrecarga de trabalho e a falta de equilíbrio vida‑profissional
constituem gatilhos diretos de saída. Tratar‑se‑á menos de uma questão
de remuneração e mais de bem‑estar organizacional e prevenção de
burnout.
Estagnação e incentivos de longo prazo
Estagnação: A variável
years_in_current_role (anos na função atual) destaca‑se na
6.ª posição. A permanência prolongada na mesma função, sem progressão
visível, aumenta substancialmente o risco de saída voluntária.
Incentivos: O stock_option_level
surge logo de seguida, evidenciando que os incentivos de longo prazo têm
um efeito de retenção mais forte do que o salário mensal
(monthly_income), que aparece apenas na 15.ª
posição.
Estes resultados sugerem que a progressão de carreira e a valorização
de capital simbólico (ações, reconhecimento, visibilidade) são
mecanismos de retenção mais eficazes do que aumentos salariais
isolados.
- Perfil demográfico de risco A presença das
variáveis
marital_status_single e age entre as 15 mais
relevantes confirma o padrão identificado nas análises anteriores:
colaboradores mais jovens e solteiros tendem a apresentar maior
mobilidade e predisposição para mudança, sobretudo em contextos de
poucas perspetivas de crescimento.
Para mitigar os riscos de attrition,
recomenda‑se que as ações prioritárias da empresa incidam sobre três
eixos principais:
Rever as condições e incentivos das equipas de Vendas, onde a
taxa de saída é mais elevada;
Monitorizar e regular o volume de horas extra, promovendo
práticas de equilíbrio e bem‑estar;
Implementar planos de rotação e desenvolvimento de carreira,
especialmente para colaboradores estagnados na mesma função há vários
anos.
Estas ações estratégicas alinham‑se diretamente com os resultados do
modelo e podem reduzir substancialmente o risco de rotatividade não
desejada, fortalecendo a retenção de talento crítico.
Conclusão e Recomendações de Negócio
Este projeto teve como objetivo identificar as causas da rotatividade
de funcionários (Attrition) e criar um modelo preditivo para mitigar o
risco.
Comparação de Modelos
Foram testadas duas abordagens distintas: Regressão Logística e
Random Forest.
O Random Forest demonstrou desempenho
superior e maior estabilidade, alcançando uma acurácia
global de 74,15%.
O modelo é capaz de identificar corretamente 70,4% dos
colaboradores que efetivamente saem da empresa (sensibilidade),
mantendo, em simultâneo, uma taxa de falsos alarmes
controlada (especificidade de 74,9%).
Estas métricas evidenciam um equilíbrio adequado entre
deteção e precisão, tornando o algoritmo uma ferramenta eficaz
para uso prático em contextos de Recursos Humanos.
Fatores Críticos de Saída (Insights do Modelo)
A análise de importância das variáveis (Feature Importance)
evidenciou três pilares centrais de ação:
- O Risco Associado à Função de Vendas
A função Sales Representative surge como o maior
preditor de saída. A taxa de rotatividade neste cargo é
substancialmente superior à observada em funções estáveis como
Research Director ou Manager.
Diagnóstico provável: Desajuste no esquema de
comissões, pressão elevada por resultados ou falta de perspetivas de
progressão.
- Cultura de Horas Extra e Exaustão Ocupacional
A variável OverTime mantém‑se entre os três
fatores mais críticos, confirmando que a sobrecarga de
trabalho é um dos gatilhos diretos de saída. Colaboradores que
realizam horas extra apresentam probabilidade significativamente
superior de sair da empresa, independentemente do nível salarial.
Interpretação: este comportamento sugere sinais de
burnout e desequilíbrio vida‑trabalho, áreas que requerem
monitorização ativa.
- Retenção através de Incentivos de Capital
O StockOptionLevel mostra‑se determinante para a
retenção de colaboradores. Funcionários com participação
acionista ou incentivos de longo prazo tendem a reter‑se por mais tempo,
reforçando o sentimento de pertença e compromisso organizacional.
Inversamente, a ausência deste fator está fortemente associada a maior
propensão à saída.
Plano de Ação Recomendado (Próximos Passos)
Com base nas evidências analíticas, recomenda‑se a implementação das
seguintes medidas:
Intervenção direcionada nas equipas de Vendas:
Realizar entrevistas de saída específicas para Representantes de Vendas,
com foco na revisão de políticas de comissão, objetivos e plano de
carreira.
Auditoria de Carga Horária e Bem‑Estar:
Estabelecer mecanismos de controlo das horas extra, garantindo a sua
compensação adequada (via folgas ou benefícios). Simultaneamente,
promover programas de prevenção de burnout e de equilíbrio
vida‑trabalho.
Ferramenta de Previsão Contínua de Rotatividade:
Integrar o modelo Random Forest como um sistema mensal de monitorização
preditiva, uma “lista de risco” dinâmica, destacando colaboradores com
probabilidade de saída superior a 50%. Esta informação deve ser
utilizada de forma proativa, permitindo à equipa de RH agir antes da
decisão de sair da empresa.
LS0tCnRpdGxlOiAiQW7DoWxpc2UgZGUgUm90YXRpdmlkYWRlIChIUiBBbmFseXRpY3MpIgpzdWJ0aXRsZTogIklkZW50aWZpY2HDp8OjbyBkZSBGYXRvcmVzIENyw610aWNvcyBwYXJhIGEgUmV0ZW7Dp8OjbyBkZSBUYWxlbnRvIgphdXRob3I6ICJKb2FuYSBJbsOhY2lvIHwgRGF0YSBBbmFseXN0IgpkYXRlOiAiYHIgZm9ybWF0KFN5cy5EYXRlKCksICclZC0lbS0lWScpYCIKb3V0cHV0OgogIGh0bWxfZG9jdW1lbnQ6CiAgICBjb2RlX2ZvbGRpbmc6IGhpZGUKICAgIHRoZW1lOiBjb3NtbyAgICAgICAgICAgCiAgICBoaWdobGlnaHQ6IHB5Z21lbnRzICAgCiAgICB0b2M6IHRydWUKICAgIHRvY19mbG9hdDogdHJ1ZQogICAgY29kZV9kb3dubG9hZDogdHJ1ZSAgICAKICAgIG51bWJlcl9zZWN0aW9uczogZmFsc2UgCi0tLQpgYGB7ciBzZXR1cCwgaW5jbHVkZT1GQUxTRX0KIyBNYW5pcHVsYcOnw6NvIGUgbGltcGV6YSBkZSBkYWRvcwpsaWJyYXJ5KGRwbHlyKQpsaWJyYXJ5KGphbml0b3IpCmxpYnJhcnkoZmFzdER1bW1pZXMpCmxpYnJhcnkoc2tpbXIpCgojIFZpc3VhbGl6YcOnw6NvCmxpYnJhcnkoZ2dwbG90MikKbGlicmFyeShjb3JycGxvdCkKbGlicmFyeShncmlkRXh0cmEpCmxpYnJhcnkoa2FibGVFeHRyYSkKCiMgTW9kZWxhw6fDo28gZSBhdmFsaWHDp8OjbwpsaWJyYXJ5KGNhVG9vbHMpCmxpYnJhcnkoUk9TRSkKbGlicmFyeShyYW5kb21Gb3Jlc3QpCmxpYnJhcnkoY2FyZXQpCgprbml0cjo6b3B0c19jaHVuayRzZXQoCiAgZWNobyA9IFRSVUUsICMgTW9zdHJhIG8gY8OzZGlnbyBubyByZWxhdMOzcmlvIChUUlVFKSBvdSBlc2NvbmRlIChGQUxTRSkKICB3YXJuaW5nID0gRkFMU0UsICMgRXNjb25kZSBtZW5zYWdlbnMgZGUgYXZpc28gCiAgbWVzc2FnZSA9IEZBTFNFLCAjIEVzY29uZGUgbWVuc2FnZW5zIG5vcm1haXMKICBmaWcuYWxpZ24gPSAiY2VudGVyIiwgIyBDZW50cmEgdG9kb3Mgb3MgZ3LDoWZpY29zCiAgZmlnLndpZHRoID0gMTAsICMgw4kgYSBsYXJndXJhIHBhZHLDo28gcGFyYSBvcyBvdXRwdXRzCiAgZmlnLmhlaWdodCA9IDYsICMgw4kgYSBhbHR1cmEgcGFkcsOjbyBwYXJhIG9zIG91dHB1dHMKICBjb21tZW50ID0gTkEsICMgUmVtb3ZlIG9zICIjIyIgZGFzIGxpbmhhcyBkZSBvdXRwdXQgZGUgY8OzZGlnbwogIG91dC53aWR0aCA9ICI4MCUiICMgQSBsYXJndXJhIGRhcyBmaWd1cmFzIHRlcsOhIDgwJSBkYSBsYXJndXJhIGRhIHDDoWdpbmEKKQpgYGAKIyBJbnRyb2R1w6fDo28gZSBDb250ZXh0bwojIyBPIFByb2JsZW1hIGRlIE5lZ8OzY2lvCkEgcm90YXRpdmlkYWRlIGRvcyBmdW5jaW9uw6FyaW9zICh0YW1iw6ltIGNvbmhlY2lkYSBwb3IgX0VtcGxveWVlIEF0dHJpdGlvbl8pIMOpIHVtIGRvcyBtYWlvcmVzIGRlc2FmaW9zIGRhcyBvcmdhbml6YcOnw7VlcywgZSB1bSBkb3MgcXVlIHRyYXogbWFpcyBjdXN0b3MuIEVzdHVkb3MgaW5kaWNhbSBxdWUgbyBjdXN0byBkZSBzdWJzdGl0dWlyIHVtIGZ1bmNpb27DoXJpbyBwb2RlIHZhcmlhciBlbnRyZSA1MCUgYSAyMDAlIGRvIHNldSBzYWzDoXJpbyBhbnVhbCwgc2VuZG8gY29uc2lkZXJhZG9zIG9zIGN1c3RvcyBkZSByZWNydXRhbWVudG8sIGRlIGZvcm1hw6fDo28gZSBkZSBwZXJkYSBkZSBwcm9kdXRpdmlkYWRlLgoKUGFyYSBhbMOpbSBkbyBpbXBhY3RvIGZpbmFuY2Vpcm8sIHVtYSB0YXhhIGRlIF90dXJub3Zlcl8gZWxldmFkYSBhZmV0YSBhIG1vcmFsIGRhcyBlcXVpcGFzLCBhIGN1bHR1cmEgZGEgZW1wcmVzYSBlIGEgY29udGludWlkYWRlIGRvcyBwcm9qZXRvcy4gUG9yIGlzc28sIGEgY2FwYWNpZGFkZSBkZSBwcmV2ZXIgKipxdWVtKiogZXN0w6EgZW0gcmlzY28gZGUgc2FpciBlLCBtYWlzIGltcG9ydGFudGUsICoqcG9ycXXDqioqLCDDqSB1bWEgdmFudGFnZW0gY29tcGV0aXRpdmEgY3J1Y2lhbCBwYXJhIG8gRGVwYXJ0YW1lbnRvIGRlIFJlY3Vyc29zIEh1bWFub3MgKFJIKS4gCgojIyBTb2JyZSBvIF9EYXRhc2V0XwpOZXN0ZSBwcm9qZXRvLCBmb2kgdXRpbGl6YWRvIG8gX2RhdGFzZXRfICIqKklCTSBIUiBBbmFseXRpY3MgRW1wbG95ZWUgQXR0cml0aW9uICYgUGVyZm9ybWFuY2UqKiIsIGRpc3BvbmliaWxpemFkbyBwdWJsaWNhbWVudGUgbm8gS2FnZ2xlLiBFc3RlIGNvbmp1bnRvIGRlIGRhZG9zIGZvaSBjcmlhZG8gcG9yIGNpZW50aXN0YXMgZGUgZGFkb3MgZGEgSUJNIGUsIGVtYm9yYSBzZWphIGZpY3TDrWNpbywgcmVmbGV0ZSBkZXNhZmlvcyByZWFpcyBkbyBtdW5kbyBjb3Jwb3JhdGl2by4KCk8gX2RhdGFzZXRfIGNvbnTDqW0gKioxNDcwIG9ic2VydmHDp8O1ZXMqKiAoZnVuY2lvbsOhcmlvcykgZSAqKjM1IHZhcmnDoXZlaXMqKiAoY2FyYWN0ZXLDrXN0aWNhcykgCgojIyBEaWNpb27DoXJpbyBkZSBWYXJpw6F2ZWlzCkEgbm9zc2EgdmFyacOhdmVsLWFsdm8gKF9UYXJnZXRfKSDDqSBhICoqX0F0dHJpdGlvbl8qKiwgcXVlIGluZGljYSBzZSBvIGZ1bmNpb27DoXJpbyBzYWl1ICgiWWVzIikgb3UgcGVybWFuZWNldSAoIk5vIikgbmEgZW1wcmVzYS4gCgpBcyByZXN0YW50ZXMgdmFyacOhdmVpcyBwb2RlbSBzZXIgYWdydXBhZGFzIGVtIHRyw6pzIGNhdGVnb3JpYXMgcHJpbmNpcGFpcyBxdWUgaXJlbW9zIGV4cGxvcmFyOgoKMS4gKipEZW1vZ3LDoWZpY2FzKio6IGBBZ2VgLCBgR2VuZGVyYCwgYE1hcml0aWFsU3RhdHVzYCwgYERpc3RhbmNlRnJvbUhvbWVgOwoKMi4gKipEYWRvcyBkbyBUcmFiYWxobyoqOiBgRGVwYXJ0bWVudGAsIGBKb2JSb2xlYCwgYEpvYkxldmVsYCwgYE92ZXJUaW1lYCwgYEJ1c2luZXNzVHJhdmVsYDsKCjMuICoqQ29tcGVuc2HDp8OjbyBlIFNhdGlzZmHDp8OjbyoqOiBgTW9udGhseUluY29tZWAsIGBQZXJjZW50U2FsYXJ5SGlrZWAsIGBTdG9ja09wdGlvbkxldmVsYCwgYEpvYlNhdGlzZmFjdGlvbmAsIGBFbnZpcm9ubWVudFNhdGlzZmFjdGlvbmAuIAoKUGFyYSBmYWNpbGl0YXIgYSBsZWl0dXJhLCBmb3JhbSBkZXN0YWNhZGFzIGFjaW1hIGFwZW5hcyBhcyB2YXJpw6F2ZWlzIG1haXMgcmVsZXZhbnRlcyBwYXJhIGEgYW7DoWxpc2UuIEEgbGlzdGEgY29tcGxldGEgZGFzIDM1IHZhcmnDoXZlaXMgZSBvcyBzZXVzIHRpcG9zIGRlIGRhZG9zIHNlcsOjbyBhcHJlc2VudGFkb3MgbmEgc2Vjw6fDo28gdMOpY25pY2EgZGUgaW5zcGXDp8OjbyBkZSBkYWRvcy4KCiMjIE9iamV0aXZvcyBkbyBQcm9qZXRvCgpPIG9iamV0aXZvIGNlbnRyYWwgZGVzdGUgcHJvamV0byDDqSBkZXNlbnZvbHZlciB1bWEgc29sdcOnw6NvIGRlICoqUGVvcGxlIEFuYWx5dGljcyoqIGNhcGF6IGRlIGFudGVjaXBhciBhIHJvdGF0aXZpZGFkZSBkZSB0YWxlbnRvcyBlIGZvcm5lY2VyIMOgIGdlc3TDo28gZXN0cmF0w6lnaWFzIGJhc2VhZGFzIGVtIGRhZG9zLiBQYXJhIHRhbCwgYSBhbsOhbGlzZSBmb2NhLXNlIGVtIHRyw6pzIHBpbGFyZXMgdmVydGljYWlzOgoKKiAqKkRpYWduw7NzdGljbyBkZSBDYXVzYSBSYWl6Kio6IFF1YW50aWZpY2FyIG8gaW1wYWN0byByZWFsIGRlIGZhdG9yZXMgZGUgcmlzY28sIHZlcmlmaWNhbmRvIGEgaGlww7N0ZXNlIGRlIHF1ZSBhIHNvYnJlY2FyZ2EgZGUgdHJhYmFsaG8gKGBPdmVyVGltZWApIGUgYSBsb2fDrXN0aWNhIChgRGlzdGFuY2VGcm9tSG9tZWApIHPDo28gY2F0YWxpc2Fkb3JlcyBkZSBfYnVybm91dF8uCgoqICoqSGllcmFycXVpYSBkZSBSZXRlbsOnw6NvKio6IERldGVybWluYXIsIGF0cmF2w6lzIGRlIGFsZ29yaXRtb3MgZGUgTWFjaGluZSBMZWFybmluZywgbyBxdWUgcGVzYSBtYWlzIG5hIGRlY2lzw6NvIGRlIHNhw61kYTogaW5jZW50aXZvcyBmaW5hbmNlaXJvcyAoYE1vbnRobHlJbmNvbWVgKSBvdSBmYXRvcmVzIGludGFuZ8OtdmVpcyBjb21vIGEgU2F0aXNmYcOnw6NvIG5vIFRyYWJhbGhvLgoKKiAqKk1vZGVsYcOnw6NvIFByZWRpdGl2YSoqOiBUcmVpbmFyIGFsZ29yaXRtb3MgZGUgY2xhc3NpZmljYcOnw6NvIChSZWdyZXNzw6NvIExvZ8Otc3RpY2EgZSBSYW5kb20gRm9yZXN0KSBwYXJhIGlkZW50aWZpY2FyIGNvbGFib3JhZG9yZXMgZW0gcmlzY28gY29tIGVsZXZhZGEgcHJlY2lzw6NvLCBwZXJtaXRpbmRvIHVtYSBhdHVhw6fDo28gcHJldmVudGl2YSBkbyBSSC4KCiMgSW1wb3J0YcOnw6NvIGRvcyBEYWRvcyBlIEluc3Blw6fDo28gSW5pY2lhbAoKYGBge3IgaW1wb3J0YWNhbywgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KIyBJbXBvcnRhw6fDo28gZG9zIERhZG9zCiMgTGVtb3MgbyBmaWNoZWlybyBvcmlnaW5hbAppYm1faHIgPC0gcmVhZC5jc3YoImRhdGEvV0FfRm4tVXNlQ18tSFItRW1wbG95ZWUtQXR0cml0aW9uLmNzdiIsIHNlcCA9ICI7IikKCgpsaWJyYXJ5KGphbml0b3IpCmxpYnJhcnkoZHBseXIpCgojIExpbXBlemEgZSBQYWRyb25pemHDp8OjbwojIEFxdWkgY3JpYW1vcyBvIG9iamV0byAnaWJtX2NsZWFuJwoKaWJtX2NsZWFuIDwtIGlibV9ociAlPiUgCiAgY2xlYW5fbmFtZXMoKSAlPiUgCiAgIyBSZW1vdmVtb3MgY29sdW5hcyBxdWUgbsOjbyB2YXJpYW0KICBzZWxlY3QoLWFueV9vZihjKCJlbXBsb3llZV9jb3VudCIsICJvdmVyMTgiLCAic3RhbmRhcmRfaG91cnMiLCAiZW1wbG95ZWVfbnVtYmVyIikpKQoKIyBWaXN1YWxpemHDp8OjbyAoa2FibGUpCmxpYnJhcnkoa2FibGVFeHRyYSkKaWJtX2NsZWFuICU+JSAKICBzZWxlY3QoYWdlLCBhdHRyaXRpb24sIG1vbnRobHlfaW5jb21lLCBqb2Jfcm9sZSwgb3Zlcl90aW1lLCB0b3RhbF93b3JraW5nX3llYXJzKSAlPiUgCiAgaGVhZCgxMCkgJT4lIAogIGthYmxlKGNhcHRpb24gPSAiVGFiZWxhIDE6IEFtb3N0cmEgZGFzIFZhcmnDoXZlaXMgQ3LDrXRpY2FzIHBhcmEgQW7DoWxpc2UgZGUgUm90YXRpdmlkYWRlIikgJT4lIAogIGthYmxlX3N0eWxpbmcoYm9vdHN0cmFwX29wdGlvbnMgPSBjKCJzdHJpcGVkIiwgImhvdmVyIiwgImNvbmRlbnNlZCIpLCAKICAgICAgICAgICAgICAgIGZ1bGxfd2lkdGggPSBULCAKICAgICAgICAgICAgICAgIHBvc2l0aW9uID0gImNlbnRlciIpICU+JSAKICByb3dfc3BlYygwLCBib2xkID0gVCwgY29sb3IgPSAid2hpdGUiLCBiYWNrZ3JvdW5kID0gIiMyYzNlNTAiKSAKYGBgCgpBIGJhc2UgZGUgZGFkb3Mgw6kgY29tcG9zdGEgcG9yICoqMzUgdmFyacOhdmVpcyoqIHF1ZSBhYnJhbmdlbSB0csOqcyBkaW1lbnPDtWVzIGNlbnRyYWlzOiAqKmNhcmFjdGVyw61zdGljYXMgZGVtb2dyw6FmaWNhcyoqLCAqKmZhdG9yZXMgZmluYW5jZWlyb3MqKiBlICoqaW5kaWNhZG9yZXMgZGUgZGVzZW1wZW5obyBwcm9maXNzaW9uYWwqKi4KCk5lc3RhIGZhc2UgaW5pY2lhbCwgYSBhbsOhbGlzZSBpbmNpZGUgc29icmUgdmFyacOhdmVpcyBjb20gbWFpb3IgcG90ZW5jaWFsIGV4cGxpY2F0aXZvIGRhICoqcm90YXRpdmlkYWRlIGRlIGNvbGFib3JhZG9yZXMqKiwgbm9tZWFkYW1lbnRlIGEgKipyZW11bmVyYcOnw6NvIG1lbnNhbCoqLCBvcyBhbm9zIHRvdGFpcyBkZSAqKmFudGlndWlkYWRlIG5hIGVtcHJlc2EqKiBlIGEgcmVhbGl6YcOnw6NvIGRlICoqaG9yYXMgZXh0cmEqKi4KCkV2aWTDqm5jaWFzIGVtcMOtcmljYXMgZSBhbsOhbGlzZXMgcHJlbGltaW5hcmVzIGFwb250YW0gcGFyYSB1bWEgcmVsYcOnw6NvIHNpZ25pZmljYXRpdmEgZW50cmUgZXN0ZXMgZmF0b3JlcyBlIGEgKipwcm9iYWJpbGlkYWRlIGRlIHNhw61kYSBkb3MgY29sYWJvcmFkb3JlcyoqLCBjb25zdGl0dWluZG8sIHBvciBpc3NvLCBwb250b3MgZGUgcGFydGlkYSBmdW5kYW1lbnRhaXMgcGFyYSBvIGFwcm9mdW5kYW1lbnRvIGRhIGFuw6FsaXNlLgoKIyBUcmF0YW1lbnRvIGRlIERhZG9zCiMjIExpbXBlemEgZGUgRGFkb3MKQSBhbsOhbGlzZSBkZXNjcml0aXZhIGluaWNpYWwsIGV2aWRlbmNpb3UgZG9pcyBhc3BldG9zIHJlbGV2YW50ZXMgcmVsYXRpdmFtZW50ZSDDoCBxdWFsaWRhZGUgZSBlc3RydXR1cmEgZG8gY29uanVudG8gZGUgZGFkb3M6CgoxLiAqKlF1YWxpZGFkZSBkb3MgZGFkb3MqKiDigJMgVmVyaWZpY291LXNlIGEgaW5leGlzdMOqbmNpYSBkZSB2YWxvcmVzIGVtIGZhbHRhIChfbWlzc2luZyB2YWx1ZXNfKSBlbSB0b2RhcyBhcyB2YXJpw6F2ZWlzLCBvIHF1ZSBzaW1wbGlmaWNhIHN1YnN0YW5jaWFsbWVudGUgYXMgZXRhcGFzIGRlIHByw6ktcHJvY2Vzc2FtZW50by4KCjIuICoqVmFyacOhdmVpcyByZWR1bmRhbnRlcyBlIG7Do28gaW5mb3JtYXRpdmFzKiog4oCTIEZvcmFtIGlkZW50aWZpY2FkYXMgdHLDqnMgdmFyacOhdmVpcyBjb20gdmFsb3IgY29uc3RhbnRlIGVtIHRvZGFzIGFzIG9ic2VydmHDp8O1ZXMgKGRlc3ZpbyBwYWRyw6NvID0gMCksIGJlbSBjb21vIHVtYSB2YXJpw6F2ZWwgZGUgaWRlbnRpZmljYcOnw6NvIGluZGl2aWR1YWwuIFBvciBuw6NvIGFwcmVzZW50YXJlbSB2YXJpYWJpbGlkYWRlIG91IG7Do28gY29udHJpYnXDrXJlbSBwYXJhIGEgZXhwbGljYcOnw6NvIGRvIGZlbsOzbWVubyBlc3R1ZGFkbywgZXN0YXMgdmFyacOhdmVpcyBmb3JhbSByZW1vdmlkYXMgZG8gX2RhdGFzZXRfLgoKQXMgKip2YXJpw6F2ZWlzIGVsaW1pbmFkYXMqKiBmb3JhbToKCiogYEVtcGxveWVlQ291bnRgOiB2YWxvciBjb25zdGFudGUgaWd1YWwgYSDigJwx4oCdOwoKKiBgT3ZlcjE4YDogdG9kb3Mgb3MgY29sYWJvcmFkb3JlcyByZWdpc3RhZG9zIGNvbW8gbWFpb3JlcyBkZSBpZGFkZSAo4oCcWeKAnSk7CgoqIGBTdGFuZGFyZEhvdXJzYDogdmFsb3IgZml4byBkZSDigJw4MOKAnSBlbSB0b2RvcyBvcyByZWdpc3RvczsKCiogYEVtcGxveWVlTnVtYmVyYDogaWRlbnRpZmljYWRvciDDum5pY28gZG9zIGNvbGFib3JhZG9yZXMsIHNlbSByZWxldsOibmNpYSBwcmVkaXRpdmEuCgpBIGV4Y2x1c8OjbyBkZXN0YXMgdmFyacOhdmVpcyBwZXJtaXRlIHJlZHV6aXIgYSBkaW1lbnNpb25hbGlkYWRlIGRvcyBkYWRvcyBzZW0gcGVyZGEgZGUgaW5mb3JtYcOnw6NvIHJlbGV2YW50ZSwgY29udHJpYnVpbmRvIHBhcmEgdW0gbW9kZWxvIGFuYWzDrXRpY28gbWFpcyBlZmljaWVudGUgZSBpbnRlcnByZXTDoXZlbC4KCmBgYHtyIGxpbXBlemFfZXNwZWNpZmljYSwgbWVzc2FnZT1GQUxTRX0KIyBQYWRyb25pemHDp8OjbyBkZSBOb21lcwppYm1fY2xlYW4gPC0gaWJtX2hyICU+JSAKICBjbGVhbl9uYW1lcygpCgojIFJlbW92ZXIgVmFyacOhdmVpcyBJbnZhcmlhbnRlcwpjb2x1bmFzX3JlbW92ZXIgPC0gYygiZW1wbG95ZWVfY291bnQiLCAib3ZlcjE4IiwgInN0YW5kYXJkX2hvdXJzIiwgImVtcGxveWVlX251bWJlciIpCgppYm1fY2xlYW4gPC0gaWJtX2NsZWFuICU+JSAKICBzZWxlY3QoLWFueV9vZihjb2x1bmFzX3JlbW92ZXIpKQoKIyBSZXN1bW8gZGEgTGltcGV6YQpjYXQoIkJhc2UgZGUgZGFkb3MgbGltcGEgY29tIHN1Y2Vzc28uXG4iLAogICAgIlRvdGFsIGRlIENvbHVuYXMgT3JpZ2luYWlzOiAiLCBuY29sKGlibV9ociksICJcbiIsCiAgICAiVG90YWwgZGUgQ29sdW5hcyBBcMOzcyBMaW1wZXphOiAiLCBuY29sKGlibV9jbGVhbikpCmBgYAoKIyBBbsOhbGlzZSBFeHBsb3JhdMOzcmlhIGRvcyBEYWRvcyAoQUVEKQpFc3RhIGZhc2UgdGVtIGNvbW8gcHJpbmNpcGFsIG9iamV0aXZvIGNvbXByZWVuZGVyIGEgZGlzdHJpYnVpw6fDo28gZGFzIHZhcmnDoXZlaXMgZSBpZGVudGlmaWNhciBwYWRyw7VlcyBvdSByZWxhw6fDtWVzIHF1ZSBwb3NzYW0gZXhwbGljYXIgbyBmZW7Ds21lbm8gZGEgKipyb3RhdGl2aWRhZGUgZGUgY29sYWJvcmFkb3JlcyoqIChfZW1wbG95ZWUgYXR0cml0aW9uXykuCgpJbmljaWEtc2UgYSBleHBsb3Jhw6fDo28gcGVsYSB2YXJpw6F2ZWwgYWx2bywgYEF0dHJpdGlvbmAsIHF1ZSBpbmRpY2Egc2UgbyBjb2xhYm9yYWRvciAqKnBlcm1hbmVjZXUgbmEgZW1wcmVzYSoqIChgTm9gKSBvdSAqKm9wdG91IHBlbGEgc2HDrWRhKiogKGBZZXNgKS4KCkEgYW7DoWxpc2UgZGVzdGEgdmFyacOhdmVsIGZvcm5lY2UgdW1hIHByaW1laXJhIHBlcmNlw6fDo28gYWNlcmNhIGRvIGVxdWlsw61icmlvIGVudHJlIGNvbGFib3JhZG9yZXMgYXRpdm9zIGUgYXF1ZWxlcyBxdWUgZGVpeGFyYW0gYSBvcmdhbml6YcOnw6NvLCBwZXJtaXRpbmRvIGF2YWxpYXIgYSBkaW1lbnPDo28gcmVhbCBkbyBmZW7Ds21lbm8gZGUgc2HDrWRhLgoKIyMgQW7DoWxpc2UgZGEgVmFyacOhdmVsIF9UYXJnZXRfIChfQXR0cml0aW9uXykKUXVhbnRvcyBmdW5jaW9uw6FyaW9zIGVmZXRpdmFtZW50ZSBzYcOtcmFtIGRhIGVtcHJlc2E/CgpgYGB7ciBhbmFsaXNlX3RhcmdlfQojIENyaWFyIGEgVGFiZWxhIGRlIEZyZXF1w6puY2lhIFByb2Zpc3Npb25hbAp0YWJlbGFfdGFyZ2V0IDwtIGlibV9jbGVhbiAlPiUKICBjb3VudChhdHRyaXRpb24pICU+JQogIG11dGF0ZSgKICAgIHBlcmNlbnRhZ2VtID0gKG4gLyBzdW0obikpICogMTAwLAogICAgYXR0cml0aW9uID0gaWZlbHNlKGF0dHJpdGlvbiA9PSAiWWVzIiwgIlNhaXUgKFllcykiLCAiUGVybWFuZWNldSAoTm8pIikKICApCgojIEV4aWJpciBUYWJlbGEgY29tIG8ga2FibGVFeHRyYQp0YWJlbGFfdGFyZ2V0ICU+JQogIGthYmxlKAogICAgY2FwdGlvbiA9ICJEaXN0cmlidWnDp8OjbyBkYSBWYXJpw6F2ZWwtVGFyZ2V0IChBdHRyaXRpb24pIiwKICAgIGNvbC5uYW1lcyA9IGMoIlN0YXR1cyIsICJUb3RhbCAobikiLCAiUGVyY2VudGFnZW0gKCUpIiksCiAgICBkaWdpdHMgPSAxCiAgKSAlPiUKICBrYWJsZV9zdHlsaW5nKGJvb3RzdHJhcF9vcHRpb25zID0gYygic3RyaXBlZCIsICJob3ZlciIpLCBmdWxsX3dpZHRoID0gRikgJT4lCiAgcm93X3NwZWMoMCwgYm9sZCA9IFQsIGNvbG9yID0gIndoaXRlIiwgYmFja2dyb3VuZCA9ICIjMmMzZTUwIikgJT4lCiAgY29sdW1uX3NwZWMoMywgYm9sZCA9IFQsIGNvbG9yID0gaWZlbHNlKHRhYmVsYV90YXJnZXQkcGVyY2VudGFnZW0gPCAyMCwgIiNlNzRjM2MiLCAiIzJjM2U1MCIpKQoKIyBWaXN1YWxpemHDp8OjbwpnZ3Bsb3QoaWJtX2NsZWFuLCBhZXMoeCA9IGF0dHJpdGlvbiwgZmlsbCA9IGF0dHJpdGlvbikpICsKICBnZW9tX2Jhcih3aWR0aCA9IDAuNiwgYWxwaGEgPSAwLjkpICsKIAogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IGMoIk5vIiA9ICIjMkMzRTUwIiwgIlllcyIgPSAiI0U3NEMzQyIpKSArCiAgc2NhbGVfeV9jb250aW51b3VzKGV4cGFuZCA9IGV4cGFuc2lvbihtdWx0ID0gYygwLCAwLjEpKSkgKwogIGxhYnMoCiAgICB0aXRsZSA9ICJWaXPDo28gR2VyYWwgZGEgUm90YXRpdmlkYWRlIG5hIEVtcHJlc2EiLAogICAgc3VidGl0bGUgPSAiQXBlbmFzIDE2JSBkb3MgY29sYWJvcmFkb3JlcyBkZWl4YXJhbSBhIG9yZ2FuaXphw6fDo28gbm8gcGVyw61vZG8gYW5hbGlzYWRvIiwKICAgIHggPSAiRGVjaXPDo28gZGUgU2HDrWRhIiwKICAgIHkgPSAiTsO6bWVybyBkZSBGdW5jaW9uw6FyaW9zIgogICkgKwogIHRoZW1lX21pbmltYWwoKSArCiAgdGhlbWUoCiAgICBsZWdlbmQucG9zaXRpb24gPSAibm9uZSIsIAogICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChmYWNlID0gImJvbGQiLCBzaXplID0gMTYsIGNvbG9yID0gIiMyYzNlNTAiKSwKICAgIHBhbmVsLmdyaWQubWFqb3IueCA9IGVsZW1lbnRfYmxhbmsoKSAKICApCmBgYAoqKl9JbnNpZ2h0XyBJbmljaWFsKio6IApWZXJpZmljYS1zZSBxdWUgYSAqKnRheGEgZGUgcm90YXRpdmlkYWRlKiogKF9BdHRyaXRpb24gUmF0ZV8pIMOpIGRlIGFwcm94aW1hZGFtZW50ZSAqKjE2JSoqLCBvIHF1ZSBpbmRpY2EgcXVlIGEgbWFpb3JpYSBkb3MgY29sYWJvcmFkb3JlcyAoY2VyY2EgZGUgODQlKSBwZXJtYW5lY2V1IG5hIGVtcHJlc2EgZHVyYW50ZSBvIHBlcsOtb2RvIGFuYWxpc2Fkby4KCk9ic2VydmEtc2UsIGFzc2ltLCB1bSAqKmRlc2VxdWlsw61icmlvIGVudHJlIGFzIGNsYXNzZXMqKiBkYSB2YXJpw6F2ZWwgYWx2bywgY29tIHByZWRvbWluw6JuY2lhIGRlIGNvbGFib3JhZG9yZXMgcXVlIG7Do28gc2HDrXJhbSBkYSBvcmdhbml6YcOnw6NvLgoKRXN0ZSBwb250byDDqSBwYXJ0aWN1bGFybWVudGUgcmVsZXZhbnRlIHBhcmEgZXRhcGFzIHBvc3RlcmlvcmVzIGRlICoqbW9kZWxhw6fDo28gcHJlZGl0aXZhKiosIHVtYSB2ZXogcXVlIGEgZGVzcHJvcG9yw6fDo28gZW50cmUgY2xhc3NlcyBwb2RlIGxldmFyIG8gbW9kZWxvIGEgKipzb2JyZXZhbG9yaXphciBhIGNsYXNzZSBtYWlvcml0w6FyaWEqKiAoY29sYWJvcmFkb3JlcyBxdWUgZmljYW0pIGUgbmVnbGlnZW5jaWFyIG9zIGNhc29zIGRlIHNhw61kYSwgcXVlIHPDo28gcHJlY2lzYW1lbnRlIG9zIHF1ZSBtYWlzIGludGVyZXNzYW0gY29tcHJlZW5kZXIgZSBwcmV2ZXIuCgojIyBBbsOhbGlzZSBEZW1vZ3LDoWZpY2E6IEEgSWRhZGUgSW5mbHVlbmNpYT8KVmFtb3MgYW5hbGlzYXIgYSBkaXN0cmlidWnDp8OjbyBkZSBpZGFkZSBlbnRyZSBvcyBmdW5jaW9uw6FyaW9zIHF1ZSBzYcOtcmFtIGUgb3MgcXVlIGZpY2FyYW0uIFV0aWxpemFtb3MgdW0gQm94cGxvdCBwYXJhIHZpc3VhbGl6YXIgYSBtZWRpYW5hIGUgYSBkaXNwZXJzw6NvIGRvcyBkYWRvcy4KCmBgYHtyIGFuYWxpc2VfaWRhZGV9CiMgR3LDoWZpY286IERpc3RyaWJ1acOnw6NvIGRlIElkYWRlIHBvciBSb3RhdGl2aWRhZGUKZ2dwbG90KGlibV9jbGVhbiwgYWVzKHggPSBhdHRyaXRpb24sIHkgPSBhZ2UsIGZpbGwgPSBhdHRyaXRpb24pKSArCiAgZ2VvbV9qaXR0ZXIoYWxwaGEgPSAwLjIsIGNvbG9yID0gImdyZXk0MCIsIHdpZHRoID0gMC4yKSArCiAgZ2VvbV9ib3hwbG90KGFscGhhID0gMC44LCBvdXRsaWVyLmNvbG91ciA9ICJyZWQiLCB3aWR0aCA9IDAuNSkgKwogIAogICMgQ29yZXMgY29uc2lzdGVudGVzIGNvbSBvIHJlc3RvIGRvIHJlbGF0w7NyaW8KICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBjKCJObyIgPSAiIzJDM0U1MCIsICJZZXMiID0gIiNFNzRDM0MiKSkgKwogIAogIGxhYnMoCiAgICB0aXRsZSA9ICJPIEZhdG9yIElkYWRlIG5hIFJldGVuw6fDo28gZGUgVGFsZW50byIsCiAgICBzdWJ0aXRsZSA9ICJDb2xhYm9yYWRvcmVzIHF1ZSBzYWVtIChZZXMpIGFwcmVzZW50YW0gdW1hIG1lZGlhbmEgZGUgaWRhZGUgdmlzaXZlbG1lbnRlIGluZmVyaW9yIiwKICAgIHggPSAiRGVjaXPDo28gZGUgU2HDrWRhIiwKICAgIHkgPSAiSWRhZGUgKEFub3MpIgogICkgKwogIHRoZW1lX21pbmltYWwoKSArCiAgdGhlbWUoCiAgICBsZWdlbmQucG9zaXRpb24gPSAibm9uZSIsCiAgICBwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGZhY2UgPSAiYm9sZCIsIHNpemUgPSAxNiwgY29sb3IgPSAiIzJjM2U1MCIpLAogICAgcGFuZWwuZ3JpZC5tYWpvci54ID0gZWxlbWVudF9ibGFuaygpLAogICAgYXhpcy50aXRsZSA9IGVsZW1lbnRfdGV4dChmYWNlID0gImJvbGQiKQogICkKYGBgCgoqKl9JbnNpZ2h0c18gc29icmUgYSBJZGFkZToqKgoKQSBhbsOhbGlzZSBkbyBib3hwbG90IGV2aWRlbmNpYSB1bWEgdGVuZMOqbmNpYSBjbGFyYSBuYSByZWxhw6fDo28gZW50cmUgKippZGFkZSoqIGUgKipyb3RhdGl2aWRhZGUgZGUgY29sYWJvcmFkb3JlcyoqOgoKMS4gKipGYXRvciBKdXZlbnR1ZGUqKiDigJMgVmVyaWZpY2Etc2UgdW1hIHRlbmTDqm5jaWEgc2VndW5kbyBhIHF1YWwgb3MgY29sYWJvcmFkb3JlcyBtYWlzIGpvdmVucyBhcHJlc2VudGFtIHVtYSAqKm1haW9yIHByb3BlbnPDo28gcGFyYSBzYWlyIGRhIGVtcHJlc2EqKi4gQSBtZWRpYW5hIGRlIGlkYWRlIGRvcyBmdW5jaW9uw6FyaW9zIHF1ZSBzYWVtIMOpIHZpc2l2ZWxtZW50ZSBpbmZlcmlvciDDoCBkb3MgcXVlIHBlcm1hbmVjZW0uCgoyLiAqKlpvbmEgZGUgUmlzY28qKiDigJMgQSBtYWlvciBjb25jZW50cmHDp8OjbyBkZSBzYcOtZGFzIHNpdHVhLXNlIGVudHJlIG9zICoqMjUgZSBvcyAzNSBhbm9zKiosIGZhaXhhIGV0w6FyaWEgZnJlcXVlbnRlbWVudGUgYXNzb2NpYWRhIGEgKiptb2JpbGlkYWRlIHByb2Zpc3Npb25hbCoqIGUgKipwcm9jdXJhIGRlIHByb2dyZXNzw6NvIG5hIGNhcnJlaXJhKiouIEVzdGUgY29tcG9ydGFtZW50byBwb2RlIHJlZmxldGlyIGRlc2FmaW9zIGRhIG9yZ2FuaXphw6fDo28gZW0gKipyZXRlciB0YWxlbnRvIGpvdmVtKiogb3UgZW0gb2ZlcmVjZXIgKipwbGFub3MgZGUgZGVzZW52b2x2aW1lbnRvIGVzdHJ1dHVyYWRvcyoqLgoKMy4gKipFc3RhYmlsaWRhZGUgU8OpbmlvcioqIOKAkyBDb2xhYm9yYWRvcmVzIGNvbSAqKm1haXMgZGUgNDAgYW5vcyoqIGFwcmVzZW50YW0gKiptYWlvciBlc3RhYmlsaWRhZGUqKiBlICoqbWVub3IgcHJvYmFiaWxpZGFkZSBkZSBzYcOtZGEqKi4gQXMgcG91Y2FzIG9jb3Jyw6puY2lhcyBuZXN0YSBmYWl4YSBldMOhcmlhIHN1cmdlbSBjb21vIF9vdXRsaWVyc18gbm8gZ3LDoWZpY28sIHN1Z2VyaW5kbyBjYXNvcyBwb250dWFpcyBkZSBzYcOtZGEgZGEgZW1wcmVzYSAocG9yIGV4ZW1wbG8sIHJlZm9ybWEsIG11ZGFuw6dhIHBlc3NvYWwgb3UgcmVlc3RydXR1cmHDp8OjbyBpbnRlcm5hKS4KCioqQ29uY2x1c8OjbyoqOiBPcyByZXN1bHRhZG9zIHN1Z2VyZW0gYSBuZWNlc3NpZGFkZSBkZSB1bWEgKiplc3RyYXTDqWdpYSBkZSByZXRlbsOnw6NvIHNlZ21lbnRhZGEqKjoKCiogKipDb2xhYm9yYWRvcmVzIGrDum5pb3JlcyBlIGludGVybcOpZGlvcyoqICgyNS0zNSBhbm9zKSBkZXZlbSBzZXIgYWx2byBkZSBhw6fDtWVzIGZvY2FkYXMgZW0gX2VuZ2FnZW1lbnRfLCBwcm9ncmVzc8OjbyBpbnRlcm5hIGUgZ2VzdMOjbyBkZSBleHBlY3RhdGl2YXMgZGUgY2FycmVpcmE7CgoqIErDoSBwYXJhIG9zICoqY29sYWJvcmFkb3JlcyBzw6luaW9yZXMqKiwgbyBmb2NvIHBvZGVyw6Egc2VyIHJlY29uaGVjaW1lbnRvLCBtZW50b3JpYSBlIHRyYW5zbWlzc8OjbyBkZSBfa25vdy1ob3dfLCByZWZvcsOnYW5kbyBvIHNlbnRpbWVudG8gZGUgcGVydGVuw6dhIGUgY29udGludWlkYWRlIG9yZ2FuaXphY2lvbmFsLgoKYGBge3IgYW5hbGlzZV9lc3RhZG9fY2l2aWx9CiMgR3LDoWZpY28gZGUgQmFycmFzOiBQcm9wb3LDp8OjbyBkZSBTYcOtZGEgcG9yIEVzdGFkbyBDaXZpbApnZ3Bsb3QoaWJtX2NsZWFuLCBhZXMoeCA9IG1hcml0YWxfc3RhdHVzLCBmaWxsID0gYXR0cml0aW9uKSkgKwogIGdlb21fYmFyKHBvc2l0aW9uID0gImZpbGwiLCB3aWR0aCA9IDAuNywgYWxwaGEgPSAwLjkpICsKICAKICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBjKCJObyIgPSAiIzJDM0U1MCIsICJZZXMiID0gIiNFNzRDM0MiKSkgKwogIAogICMgRm9ybWF0YcOnw6NvIGRvIGVpeG8gWSBwYXJhIHBlcmNlbnRhZ2VtCiAgc2NhbGVfeV9jb250aW51b3VzKGxhYmVscyA9IHNjYWxlczo6cGVyY2VudF9mb3JtYXQoKSwgZXhwYW5kID0gYygwLDApKSArCiAgCiAgbGFicygKICAgIHRpdGxlID0gIkltcGFjdG8gZG8gRXN0YWRvIENpdmlsIG5hIFJldGVuw6fDo28iLAogICAgc3VidGl0bGUgPSAiQ29sYWJvcmFkb3JlcyBzb2x0ZWlyb3MgYXByZXNlbnRhbSB1bWEgdGF4YSBkZSBzYcOtZGEgc2lnbmlmaWNhdGl2YW1lbnRlIHN1cGVyaW9yIiwKICAgIHggPSAiRXN0YWRvIENpdmlsIiwKICAgIHkgPSAiUHJvcG9yw6fDo28gZGUgRnVuY2lvbsOhcmlvcyIsCiAgICBmaWxsID0gIlNhw61kYT8iCiAgKSArCiAgdGhlbWVfbWluaW1hbCgpICsKICB0aGVtZSgKICAgIHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoZmFjZSA9ICJib2xkIiwgc2l6ZSA9IDE2LCBjb2xvciA9ICIjMmMzZTUwIiksCiAgICBsZWdlbmQucG9zaXRpb24gPSAidG9wIiwgCiAgICBwYW5lbC5ncmlkLm1ham9yLnggPSBlbGVtZW50X2JsYW5rKCksCiAgICBheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChmYWNlID0gImJvbGQiKSAKICApCmBgYAoqKl9JbnNpZ2h0c18gc29icmUgbyBFc3RhZG8gQ2l2aWw6KioKCkEgYW7DoWxpc2Ugc3VnZXJlIHF1ZSBvICoqZXN0YWRvIGNpdmlsKiogY29uc3RpdHVpIHVtICoqZmF0b3IgcmVsZXZhbnRlIG5hIHJvdGF0aXZpZGFkZSBkZSBjb2xhYm9yYWRvcmVzKio6CgoxLiAqKk1haW9yIHJpc2NvIGVudHJlIGNvbGFib3JhZG9yZXMgc29sdGVpcm9zKiog4oCTIE9zIHRyYWJhbGhhZG9yZXMgc29sdGVpcm9zIHJlZ2lzdGFtIHVtYSAqKnRheGEgZGUgc2HDrWRhIHN1cGVyaW9yIGEgMjUlKiosIG1haXMgZG8gZG9icm8gZGEgb2JzZXJ2YWRhIGVudHJlIGNvbGFib3JhZG9yZXMgY2FzYWRvcyBvdSBkaXZvcmNpYWRvcyAoYXByb3hpbWFkYW1lbnRlIDExJSkuIEVzdGUgcmVzdWx0YWRvIGluZGljYSBxdWUgYSBwcm9iYWJpbGlkYWRlIGRlIHNhw61kYSBlc3TDoSBzaWduaWZpY2F0aXZhbWVudGUgYXNzb2NpYWRhIGFvIGVzdGFkbyBjaXZpbC4KCjIuICoqUG9zc8OtdmVsIGV4cGxpY2HDp8OjbyBjb21wb3J0YW1lbnRhbCoqIOKAkyBFc3RlIHBhZHLDo28gw6kgY29uc2lzdGVudGUgY29tIGV2aWTDqm5jaWEgZW1ww61yaWNhIG5hIGxpdGVyYXR1cmEgZGUgcmVjdXJzb3MgaHVtYW5vcywgcXVlIGFwb250YSBxdWUgcHJvZmlzc2lvbmFpcyBzZW0gZGVwZW5kZW50ZXMgb3UgbGHDp29zIGZhbWlsaWFyZXMgZGlyZXRvcyB0ZW5kZW0gYSBhcHJlc2VudGFyIG1haW9yIG1vYmlsaWRhZGUgbGFib3JhbC4gRXNzYSBmbGV4aWJpbGlkYWRlIGdlb2dyw6FmaWNhIGUgZmluYW5jZWlyYSBwb2RlIGZhY2lsaXRhciBhIHByb2N1cmEgZGUgbm92YXMgb3BvcnR1bmlkYWRlcyBvdSBhIGFjZWl0YcOnw6NvIGRlIHByb3Bvc3RhcyBlbSBkaWZlcmVudGVzIGxvY2Fpcy4KCioqQ29uY2x1c8OjbyoqOiBBIGdlc3TDo28gZGUgdGFsZW50byBwb2RlcsOhIGJlbmVmaWNpYXIgZGUgKiplc3RyYXTDqWdpYXMgZGlmZXJlbmNpYWRhcyBkZSByZXRlbsOnw6NvKiogZW50cmUgZ3J1cG9zLCBwcm9tb3ZlbmRvLCBwb3IgZXhlbXBsbywgaW5pY2lhdGl2YXMgZGUgcHJvZ3Jlc3PDo28gZGUgY2FycmVpcmEgZSBwcm9ncmFtYXMgZGUgZW52b2x2aW1lbnRvIG9yZ2FuaXphY2lvbmFsIHF1ZSBhdW1lbnRlbSBvIGNvbXByb21pc3NvIGRvcyBjb2xhYm9yYWRvcmVzIG1haXMgam92ZW5zIGUgc29sdGVpcm9zIGNvbSBhIGVtcHJlc2EuCgojIyBBbsOhbGlzZSBQcm9maXNzaW9uYWw6IENhcmdhIGRlIFRyYWJhbGhvIGUgVmlhZ2VucwoKU2Vyw6EgcXVlIG8gZXhjZXNzbyBkZSB0cmFiYWxobyAoYE92ZXJUaW1lYCkgZSBhcyB2aWFnZW5zIGZyZXF1ZW50ZXMgKGBCdXNpbmVzc1RyYXZlbGApIGxldmFtIMOgIGV4YXVzdMOjbyBlIGNvbnNlcXVlbnRlIHNhw61kYT8KCmBgYHtyIGFuYWxpc2VfY2FyZ2FfdHJhYmFsaG99CiMgR3LDoWZpY28gZGUgSG9yYXMgRXh0cmEgKHAxKQpwMSA8LSBnZ3Bsb3QoaWJtX2NsZWFuLCBhZXMoeCA9IG92ZXJfdGltZSwgZmlsbCA9IGF0dHJpdGlvbikpICsKICBnZW9tX2Jhcihwb3NpdGlvbiA9ICJmaWxsIiwgd2lkdGggPSAwLjcsIGFscGhhID0gMC45KSArCiAgc2NhbGVfeV9jb250aW51b3VzKGxhYmVscyA9IHNjYWxlczo6cGVyY2VudF9mb3JtYXQoKSwgZXhwYW5kID0gYygwLDApKSArCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gYygiTm8iID0gIiMyQzNFNTAiLCAiWWVzIiA9ICIjRTc0QzNDIikpICsKICBsYWJzKAogICAgdGl0bGUgPSAiSW1wYWN0byBkYXMgSG9yYXMgRXh0cmEiLCAKICAgIHggPSAiRmF6IEhvcmFzIEV4dHJhPyIsIAogICAgeSA9ICJQcm9wb3LDp8OjbyIKICApICsKICB0aGVtZV9taW5pbWFsKCkgKwogIHRoZW1lKAogICAgbGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiLCAKICAgIHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoZmFjZSA9ICJib2xkIiwgc2l6ZSA9IDEzLCBjb2xvciA9ICIjMmMzZTUwIiksCiAgICBwYW5lbC5ncmlkLm1ham9yLnggPSBlbGVtZW50X2JsYW5rKCkKICApCgojIEdyw6FmaWNvIGRlIFZpYWdlbnMgZGUgVHJhYmFsaG8gKHAyKQpwMiA8LSBnZ3Bsb3QoaWJtX2NsZWFuLCBhZXMoeCA9IGJ1c2luZXNzX3RyYXZlbCwgZmlsbCA9IGF0dHJpdGlvbikpICsKICBnZW9tX2Jhcihwb3NpdGlvbiA9ICJmaWxsIiwgd2lkdGggPSAwLjcsIGFscGhhID0gMC45KSArCiAgc2NhbGVfeV9jb250aW51b3VzKGxhYmVscyA9IHNjYWxlczo6cGVyY2VudF9mb3JtYXQoKSwgZXhwYW5kID0gYygwLDApKSArCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gYygiTm8iID0gIiMyQzNFNTAiLCAiWWVzIiA9ICIjRTc0QzNDIikpICsKICBsYWJzKAogICAgdGl0bGUgPSAiSW1wYWN0byBkYXMgVmlhZ2VucyIsIAogICAgeCA9ICJGcmVxdcOqbmNpYSBkZSBWaWFnZW5zIiwgCiAgICB5ID0gTlVMTCwKICAgIGZpbGwgPSAiU2HDrWRhPyIKICApICsKICB0aGVtZV9taW5pbWFsKCkgKwogIHRoZW1lKAogICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChmYWNlID0gImJvbGQiLCBzaXplID0gMTMsIGNvbG9yID0gIiMyYzNlNTAiKSwKICAgIGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gNDUsIGhqdXN0ID0gMSksCiAgICBwYW5lbC5ncmlkLm1ham9yLnggPSBlbGVtZW50X2JsYW5rKCkKICApCgojIEp1bnRhciBhcyBkdWFzIHZpc3VhbGl6YcOnw7VlcwpsaWJyYXJ5KGdyaWRFeHRyYSkKZ3JpZC5hcnJhbmdlKHAxLCBwMiwgbmNvbCA9IDIsIHRvcCA9IGdyaWQ6OnRleHRHcm9iKCJBbsOhbGlzZSBkZSBDYXJnYSBkZSBUcmFiYWxobyBlIE1vYmlsaWRhZGUiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZ3AgPSBncmlkOjpncGFyKGZvbnRzaXplID0gMTYsIGZvbnQgPSAyLCBjb2wgPSAiIzJjM2U1MCIpKSkKYGBgCioqX0luc2lnaHRzXyBzb2JyZSBDYXJnYSBkZSBUcmFiYWxobyBlIEVzdGlsbyBkZSBWaWRhOioqCgpBIGFuw6FsaXNlIGRhIGNhcmdhIGRlIHRyYWJhbGhvIGUgZGEgbW9iaWxpZGFkZSBwcm9maXNzaW9uYWwgcmV2ZWxhIHVtYSBhc3NvY2lhw6fDo28gZXZpZGVudGUgZW50cmUgZXhhdXN0w6NvIGUgcm90YXRpdmlkYWRlIGRlIGNvbGFib3JhZG9yZXM6CgoxLiAqKkltcGFjdG8gZGFzIEhvcmFzIEV4dHJhKiog4oCTIE8gZWZlaXRvIGRhcyBob3JhcyBleHRyYSDDqSBwYXJ0aWN1bGFybWVudGUgZXhwcmVzc2l2by4gQ29sYWJvcmFkb3JlcyBxdWUgbsOjbyByZWFsaXphbSBob3JhcyBleHRyYSBhcHJlc2VudGFtIHVtYSB0YXhhIGRlIHNhw61kYSBwcsOzeGltYSBkZSAxMCUsIGVucXVhbnRvIGVudHJlIG9zIHF1ZSB0cmFiYWxoYW0gYWzDqW0gZG8gaG9yw6FyaW8gcmVndWxhciwgZXNzYSBwcm9wb3LDp8OjbyB0cmlwbGljYSBwYXJhIGNlcmNhIGRlIDMwJS4KRXN0ZSByZXN1bHRhZG8gY29uc3RpdHVpIHVtIGluZGljYWRvciBjbGFybyBkZSByaXNjbyBkZSBfYnVybm91dF8gZSBzdWdlcmUgcXVlIG8gZXhjZXNzbyBkZSBjYXJnYSBob3LDoXJpYSBwb2RlIGVzdGFyIGFzc29jaWFkbyDDoCBpbnNhdGlzZmHDp8OjbyBlIGRlc2dhc3RlIGVtb2Npb25hbC4KCjIuICoqTyBQZXNvIGRhIE1vYmlsaWRhZGUqKiAoYEJ1c2luZXNzVHJhdmVgbCkg4oCTIE9ic2VydmEtc2UgdW1hIHRlbmTDqm5jaWEgY3Jlc2NlbnRlIGVudHJlIGZyZXF1w6puY2lhIGRlIHZpYWdlbnMgZSBwcm9iYWJpbGlkYWRlIGRlIHNhw61kYToKCiogQ29sYWJvcmFkb3JlcyBxdWUgKipuw6NvIHZpYWphbSoqIChgTm9u4oCRVHJhdmVsYCkgYXByZXNlbnRhbSBhIG1lbm9yIHRheGEgZGUgcm90YXRpdmlkYWRlICg8MTAlKTsKCiogRW50cmUgb3MgcXVlICoqdmlhamFtIGNvbSBmcmVxdcOqbmNpYSoqIChgVHJhdmVsX0ZyZXF1ZW50bHlgKSwgbyByaXNjbyBhcHJveGltYeKAkXNlIGRvcyAyNSUsIGluZGljYW5kbyBxdWUgbyBlcXVpbMOtYnJpbyBlbnRyZSB2aWRhIHBlc3NvYWwgZSBwcm9maXNzaW9uYWwgc2UgZW5jb250cmEgY29uc2lkZXJhdmVsbWVudGUgY29tcHJvbWV0aWRvLgoKKipDb25jbHVzw6NvKio6IFRhbnRvIGEgc29icmVjYXJnYSBkZSB0cmFiYWxobyBjb21vIGEgbW9iaWxpZGFkZSBleGNlc3NpdmEgc3VyZ2VtIGNvbW8gZmF0b3JlcyBkZSByaXNjbyByZWxldmFudGVzIHBhcmEgYSByZXRlbsOnw6NvIGRlIHRhbGVudG8uIFBvbMOtdGljYXMgb3JnYW5pemFjaW9uYWlzIHF1ZSBwcm9tb3ZhbSBsaW1pdGVzIHNhdWTDoXZlaXMgZGUgam9ybmFkYSwgZmxleGliaWxpZGFkZSBsYWJvcmFsIGUgZXF1aWzDrWJyaW8gdmlkYeKAkXRyYWJhbGhvIHBvZGVyw6NvIG1pdGlnYXIgc2lnbmlmaWNhdGl2YW1lbnRlIGVzdGUgdGlwbyBkZSByb3RhdGl2aWRhZGUuCgojIyBBbsOhbGlzZSBGaW5hbmNlaXJhOiBPIFNhbMOhcmlvIEltcG9ydGE/CkZvaSBhbmFsaXNhZGEgYSBkaXN0cmlidWnDp8OjbyBzYWxhcmlhbCAoYE1vbnRobHlJbmNvbWVgKSBwYXJhIGVudGVuZGVyIHNlIHNhbMOhcmlvcyBtYWlzIGJhaXhvcyBpbXB1bHNpb25hbSBhIHNhw61kYS4KCmBgYHtyIGFuYWxpc2Vfc2FsYXJpb30KIyBHcsOhZmljbyBkZSBEZW5zaWRhZGU6IFNhbMOhcmlvIE1lbnNhbCBwb3IgUm90YXRpdmlkYWRlCmdncGxvdChpYm1fY2xlYW4sIGFlcyh4ID0gbW9udGhseV9pbmNvbWUsIGZpbGwgPSBhdHRyaXRpb24pKSArCiAgZ2VvbV9kZW5zaXR5KGFscGhhID0gMC43LCBjb2xvciA9ICJ3aGl0ZSIpICsKICAKICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBjKCJObyIgPSAiIzJDM0U1MCIsICJZZXMiID0gIiNFNzRDM0MiKSkgKwogIAogICMgRm9ybWF0YcOnw6NvIGRvIGVpeG8gWCBwYXJhIE1vZWRhIChEw7NsYXIpCiAgc2NhbGVfeF9jb250aW51b3VzKGxhYmVscyA9IHNjYWxlczo6ZG9sbGFyX2Zvcm1hdCgpLCBicmVha3MgPSBzZXEoMCwgMjAwMDAsIDI1MDApKSArCiAgCiAgbGFicygKICAgIHRpdGxlID0gIkRpc3RyaWJ1acOnw6NvIFNhbGFyaWFsIGUgbyBSaXNjbyBkZSBSb3RhdGl2aWRhZGUiLAogICAgc3VidGl0bGUgPSAiQSBwcm9iYWJpbGlkYWRlIGRlIHNhw61kYSDDqSBkcmFzdGljYW1lbnRlIHN1cGVyaW9yIGVtIGZhaXhhcyBzYWxhcmlhaXMgYWJhaXhvIGRvcyAkNS4wMDAiLAogICAgeCA9ICJTYWzDoXJpbyBNZW5zYWwgKFVTRCkiLAogICAgeSA9ICJEZW5zaWRhZGUgZGUgQ29sYWJvcmFkb3JlcyIsCiAgICBmaWxsID0gIlN0YXR1cyBkZSBTYcOtZGEiCiAgKSArCiAgdGhlbWVfbWluaW1hbCgpICsKICB0aGVtZSgKICAgIHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoZmFjZSA9ICJib2xkIiwgc2l6ZSA9IDE2LCBjb2xvciA9ICIjMmMzZTUwIiksCiAgICBsZWdlbmQucG9zaXRpb24gPSAidG9wIiwKICAgIHBhbmVsLmdyaWQubWlub3IgPSBlbGVtZW50X2JsYW5rKCksCiAgICBwYW5lbC5ncmlkLm1ham9yLnggPSBlbGVtZW50X2JsYW5rKCkKICApCmBgYAoKKipfSW5zaWdodHNfIEZpbmFuY2Vpcm9zOioqCgpBIGFuw6FsaXNlIGRhIGRpc3RyaWJ1acOnw6NvIHNhbGFyaWFsIGV2aWRlbmNpYSBxdWUgYSAqKnJlbXVuZXJhw6fDo28gw6kgdW0gZmF0b3IgZGV0ZXJtaW5hbnRlKiogbmEgcHJvYmFiaWxpZGFkZSBkZSBzYcOtZGEsIGFwcmVzZW50YW5kbyB1bSBwYWRyw6NvIGJhc3RhbnRlIGRpc3RpbnRvIGVudHJlIGFzIGZhaXhhcyBkZSByZW5kaW1lbnRvOgoKMS4gKipBIGJhcnJlaXJhIGRvcyA1MDAwJCoqIOKAkyBPYnNlcnZh4oCRc2UgdW1hIGNvbmNlbnRyYcOnw6NvIHNpZ25pZmljYXRpdmEgZGUgc2HDrWRhcyBlbnRyZSBjb2xhYm9yYWRvcmVzIGNvbSBzYWzDoXJpb3MgbWVuc2FpcyBpbmZlcmlvcmVzIGEgNTAwMCQgTmVzdGEgZmFpeGEsIGEgZGVuc2lkYWRlIGRlIGNhc29zIGRlIF9hdHRyaXRpb25fIMOpIHN1YnN0YW5jaWFsbWVudGUgc3VwZXJpb3IsIHN1Z2VyaW5kbyBxdWUgbsOtdmVpcyBzYWxhcmlhaXMgbWFpcyBiYWl4b3MgZXN0w6NvIGFzc29jaWFkb3MgYSB1bWEgbWFpb3Igdm9sYXRpbGlkYWRlIGRhIGZvcsOnYSBkZSB0cmFiYWxoby4KCjIuICoqUmV0ZW7Dp8OjbyBlbSBmYWl4YXMgc2FsYXJpYWlzIGVsZXZhZGFzKiog4oCTIMOAIG1lZGlkYSBxdWUgbyBzYWzDoXJpbyBhdW1lbnRhIChwYXJ0aWN1bGFybWVudGUgYWNpbWEgZG9zIDEwMDAwJCksIGEgcHJvYmFiaWxpZGFkZSBkZSBzYcOtZGEgcmVkdXogZHJhc3RpY2FtZW50ZS4gRW50cmUgb3MgY29sYWJvcmFkb3JlcyBjb20gcmVuZGltZW50b3MgbWFpcyBhbHRvcywgYSBjdXJ2YSBkZSBkZW5zaWRhZGUgYXNzb2NpYWRhIMOgIHBlcm1hbsOqbmNpYSDDqSBjbGFyYW1lbnRlIHByZWRvbWluYW50ZSwgaW5kaWNhbmRvIG1haW9yIGVzdGFiaWxpZGFkZSBlIHNhdGlzZmHDp8OjbyBwcm9maXNzaW9uYWwuCgoqKkNvbmNsdXPDo28qKjogTyBwYWRyw6NvIG9ic2VydmFkbyBzdWdlcmUgcXVlIGEgZW1wcmVzYSBlbmZyZW50YSBtYWlvcmVzIGRlc2FmaW9zIGRlIHJldGVuw6fDo28gZW50cmUgY29sYWJvcmFkb3JlcyBkZSBuw612ZWwgb3BlcmFjaW9uYWwgZSBmdW7Dp8O1ZXMgasO6bmlvcmVzLCBvbmRlIGEgY29tcGVuc2HDp8OjbyBwb2RlIG7Do28gZXN0YXIgYWxpbmhhZGEgY29tIGFzIGV4cGVjdGF0aXZhcyBkbyBtZXJjYWRvLiBFc3RyYXTDqWdpYXMgc2FsYXJpYWlzIG1haXMgY29tcGV0aXRpdmFzLCBjb21wbGVtZW50YWRhcyBwb3IgcGxhbm9zIGRlIHByb2dyZXNzw6NvIGUgdmFsb3JpemHDp8OjbyBpbnRlcm5hLCBwb2RlcsOjbyBzZXIgZGVjaXNpdmFzIHBhcmEgcmVkdXppciBhIHJvdGF0aXZpZGFkZSBuZXN0YXMgZmFpeGFzIHNhbGFyaWFpcy4KCiMjIEFuw6FsaXNlIGRlIEZ1bsOnw6NvIGUgU2F0aXNmYcOnw6NvCkFudGVzIGRlIGF2YW7Dp2FybW9zIHBhcmEgYXMgY29ycmVsYcOnw7VlcyBudW3DqXJpY2FzLCBmYWx0YSBhbmFsaXNhciBkdWFzIHZhcmnDoXZlaXMgY2F0ZWfDs3JpY2FzIGNydWNpYWlzOiBvIENhcmdvIChgSm9iUm9sZWApIGUgYSBTYXRpc2Zhw6fDo28gbm8gVHJhYmFsaG8gKGBKb2JTYXRpc2ZhY3Rpb25gKS4KCk8gb2JqZXRpdm8gw6kgaWRlbnRpZmljYXIgc2UgZXhpc3RlbSBjYXJnb3MgZXNwZWPDrWZpY29zIGNvbSBtYWlvciByb3RhdGl2aWRhZGUuCgpgYGB7ciBhbmFsaXNlX2NhcmdvX3NhdGlzZmFjYW99CiMgUm90YXRpdmlkYWRlIHBvciBDYXJnbwpwX3JvbGUgPC0gZ2dwbG90KGlibV9jbGVhbiwgYWVzKHkgPSByZW9yZGVyKGpvYl9yb2xlLCAoYXR0cml0aW9uID09ICJZZXMiKSksIGZpbGwgPSBhdHRyaXRpb24pKSArCiAgZ2VvbV9iYXIocG9zaXRpb24gPSAiZmlsbCIsIHdpZHRoID0gMC43LCBhbHBoYSA9IDAuOSkgKwogIHNjYWxlX3hfY29udGludW91cyhsYWJlbHMgPSBzY2FsZXM6OnBlcmNlbnRfZm9ybWF0KCksIGV4cGFuZCA9IGMoMCwwKSkgKwogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IGMoIk5vIiA9ICIjMkMzRTUwIiwgIlllcyIgPSAiI0U3NEMzQyIpKSArCiAgbGFicygKICAgIHRpdGxlID0gIlJvdGF0aXZpZGFkZSBwb3IgQ2FyZ28iLAogICAgc3VidGl0bGUgPSAiVmVuZGFzLCBSSCBlIFTDqWNuaWNvcyBkZSBMYWJvcmF0w7NyaW8gYXByZXNlbnRhbSBtYWlvciByaXNjbyIsCiAgICB5ID0gTlVMTCwKICAgIHggPSAiUHJvcG9yw6fDo28gZGUgU2HDrWRhIgogICkgKwogIHRoZW1lX21pbmltYWwoKSArCiAgdGhlbWUoCiAgICBsZWdlbmQucG9zaXRpb24gPSAibm9uZSIsCiAgICBwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGZhY2UgPSAiYm9sZCIsIHNpemUgPSAxMywgY29sb3IgPSAiIzJjM2U1MCIpLAogICAgcGFuZWwuZ3JpZC5tYWpvci55ID0gZWxlbWVudF9ibGFuaygpLAogICAgYXhpcy50ZXh0LnkgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDksIGZhY2UgPSAiYm9sZCIpCiAgKQoKIyBJbXBhY3RvIGRhIFNhdGlzZmHDp8OjbwpwX3NhdCA8LSBnZ3Bsb3QoaWJtX2NsZWFuLCBhZXMoeCA9IGZhY3Rvcihqb2Jfc2F0aXNmYWN0aW9uKSwgZmlsbCA9IGF0dHJpdGlvbikpICsKICBnZW9tX2Jhcihwb3NpdGlvbiA9ICJmaWxsIiwgd2lkdGggPSAwLjYsIGFscGhhID0gMC45KSArCiAgc2NhbGVfeV9jb250aW51b3VzKGxhYmVscyA9IHNjYWxlczo6cGVyY2VudF9mb3JtYXQoKSwgZXhwYW5kID0gYygwLDApKSArCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gYygiTm8iID0gIiMyQzNFNTAiLCAiWWVzIiA9ICIjRTc0QzNDIikpICsKICBsYWJzKAogICAgdGl0bGUgPSAiSW1wYWN0byBkYSBTYXRpc2Zhw6fDo28gbm8gVHJhYmFsaG8iLAogICAgc3VidGl0bGUgPSAiTsOtdmVpcyBiYWl4b3MgZGUgc2F0aXNmYcOnw6NvICgxIGUgMikgY29ycmVsYWNpb25hbS1zZSBjb20gbWFpb3IgY2h1cm4iLAogICAgeCA9ICJOw612ZWwgZGUgU2F0aXNmYcOnw6NvICgxOiBCYWl4YSDihpIgNDogQWx0YSkiLAogICAgeSA9ICJQcm9wb3LDp8OjbyIsCiAgICBmaWxsID0gIlNhw61kYT8iCiAgKSArCiAgdGhlbWVfbWluaW1hbCgpICsKICB0aGVtZSgKICAgIHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoZmFjZSA9ICJib2xkIiwgc2l6ZSA9IDEzLCBjb2xvciA9ICIjMmMzZTUwIiksCiAgICBsZWdlbmQucG9zaXRpb24gPSAicmlnaHQiLAogICAgcGFuZWwuZ3JpZC5tYWpvci54ID0gZWxlbWVudF9ibGFuaygpCiAgKQoKbGlicmFyeShncmlkRXh0cmEpCmdyaWQuYXJyYW5nZShwX3JvbGUsIHBfc2F0LCBucm93ID0gMiwgCiAgICAgICAgICAgICB0b3AgPSBncmlkOjp0ZXh0R3JvYigiQW7DoWxpc2UgZGUgRnVuw6fDo28gZSBTZW50aW1lbnRvIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBncCA9IGdyaWQ6OmdwYXIoZm9udHNpemUgPSAxNiwgZm9udCA9IDIsIGNvbCA9ICIjMmMzZTUwIikpKQpgYGAKKipfSW5zaWdodHNfIHNvYnJlIEZ1bsOnw6NvIGUgU2F0aXNmYcOnw6NvOioqCgpBIGFuw6FsaXNlIGV2aWRlbmNpYSAqKnBhZHLDtWVzIGRpc3RpbnRvcyBkZSByb3RhdGl2aWRhZGUgcG9yIGZ1bsOnw6NvKiosIHJldmVsYW5kbyDDoXJlYXMgY3LDrXRpY2FzIGRlbnRybyBkYSBvcmdhbml6YcOnw6NvOgoKMS4gKipGdW7Dp8O1ZXMgZGUgVmVuZGFzIChfU2FsZXMgUmVwcmVzZW50YXRpdmVzXykqKiDigJMgRXN0ZSBncnVwbyBhcHJlc2VudGEgYSBtYWlvciB0YXhhIGRlIHNhw61kYSwgcHLDs3hpbWEgZG9zIDQwJSwgbyBxdWUgw6kgaW5kaWNhdGl2byBkZSBwcmVzc8OjbyBjb21lcmNpYWwgZWxldmFkYSwgb2JqZXRpdm9zIGV4aWdlbnRlcyBvdSBzaXN0ZW1hcyBkZSBpbmNlbnRpdm9zIHBvdWNvIGF0cmF0aXZvcy4gVHJhdGHigJFzZSBkZSB1bSBmb2NvIHByaW9yaXTDoXJpbyBkZSBhdHVhw6fDo28sIGRhZGEgYSBpbXBvcnTDom5jaWEgZXN0cmF0w6lnaWNhIGRlc3RhcyBmdW7Dp8O1ZXMgcGFyYSBvIGRlc2VtcGVuaG8gZ2xvYmFsIGRhIGVtcHJlc2EuCgoyLiAqKlTDqWNuaWNvcyBkZSBMYWJvcmF0w7NyaW8gZSBSZWN1cnNvcyBIdW1hbm9zKiog4oCTIEFtYmFzIGFzIGZ1bsOnw7VlcyByZWdpc3RhbSB0YXhhcyBkZSBzYcOtZGEgZW0gdG9ybm8gZG9zIDI1JSwgY2xhcmFtZW50ZSBhY2ltYSBkYSBtw6lkaWEgb3JnYW5pemFjaW9uYWwuIAoKMy4gKipSZXRlbsOnw6NvIG5hcyBmdW7Dp8O1ZXMgZGUgbGlkZXJhbsOnYSoqIOKAkyBPcyBjYXJnb3MgZGUgZ2VzdMOjbyBlIGRpcmXDp8OjbyAoX01hbmFnZXJzXyBlIF9EaXJlY3RvcnNfKSBhcHJlc2VudGFtIG7DrXZlaXMgZGUgZXN0YWJpbGlkYWRlIG11aXRvIGVsZXZhZG9zLCBvIHF1ZSBzdWdlcmUgcXVlIGEgcm90YXRpdmlkYWRlIMOpIHByZWRvbWluYW50ZW1lbnRlIHVtIGZlbsOzbWVubyBkb3MgbsOtdmVpcyBoaWVyw6FycXVpY29zIGludGVybcOpZGlvcyBlIG9wZXJhY2lvbmFpcy4gRXN0ZSBwYWRyw6NvIHJldmVsYSBhIGltcG9ydMOibmNpYSBkZSBkaXJlY2lvbmFyIGFzIGVzdHJhdMOpZ2lhcyBkZSByZXRlbsOnw6NvIGUgZGVzZW52b2x2aW1lbnRvIHBhcmEgYXMgZnVuw6fDtWVzIG1haXMgdnVsbmVyw6F2ZWlzLgoKKipDb25jbHVzw6NvKio6IEEgcm90YXRpdmlkYWRlIHBhcmVjZSBjb25jZW50cmFy4oCRc2UgZW0gcG9zacOnw7VlcyBkZSBiYXNlIGUgZnVuw6fDtWVzIGRlIHN1cG9ydGUgb3BlcmFjaW9uYWwsIGV4aWdpbmRvIHBvbMOtdGljYXMgZm9jYWRhcyBlbSBtZWxob3JpYSBkbyBjbGltYSBvcmdhbml6YWNpb25hbCwgcmV2aXPDo28gZGUgaW5jZW50aXZvcyBlIG9wb3J0dW5pZGFkZXMgZGUgcHJvZ3Jlc3PDo28sIHBvciBmb3JtYSBhIGZvcnRhbGVjZXIgbyBjb21wcm9taXNzbyBlIGEgcmV0ZW7Dp8OjbyBuZXN0ZXMgZ3J1cG9zLgoKIyMgQW7DoWxpc2UgZGEgQW50aWd1aWRhZGUgZSBUZW1wbyBkZSBEZXNsb2Nhw6fDo28gCkZvaSBpbnZlc3RpZ2FkYSBhIGFudGlndWlkYWRlIG5hIGVtcHJlc2EgKGBZZWFyc0F0Q29tcGFueWApIGUgYSBkaXN0w6JuY2lhIGRlIGNhc2EgKGBEaXN0YW5jZUZyb21Ib21lYCkuCk8gb2JqZXRpdm8gw6kgZW50ZW5kZXIgc2UgcGVyZGVtb3MgdGFsZW50byByZWPDqW0tY29udHJhdGFkbyBlIHNlIG8gdHJhamV0byBkacOhcmlvIGluZmx1ZW5jaWEgYSBkZWNpc8Ojby4KCmBgYHtyIGFuYWxpc2VfYW50aWd1aWRhZGVfZGlzdGFuY2lhfQojIEdyw6FmaWNvIGRlIEFudGlndWlkYWRlIChBbm9zIG5hIEVtcHJlc2EpCnBfeWVhcnMgPC0gZ2dwbG90KGlibV9jbGVhbiwgYWVzKHggPSB5ZWFyc19hdF9jb21wYW55LCBmaWxsID0gYXR0cml0aW9uKSkgKwogIGdlb21fZGVuc2l0eShhbHBoYSA9IDAuNywgY29sb3IgPSAid2hpdGUiKSArCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gYygiTm8iID0gIiMyQzNFNTAiLCAiWWVzIiA9ICIjRTc0QzNDIikpICsKICBsYWJzKAogICAgdGl0bGUgPSAiQ2ljbG8gZGUgVmlkYTogQW50aWd1aWRhZGUgbmEgRW1wcmVzYSIsCiAgICBzdWJ0aXRsZSA9ICJPIHJpc2NvIGRlICdjaHVybicgw6kgY3LDrXRpY28gbm9zIHByaW1laXJvcyAyIGFub3MgKHBlcsOtb2RvIGRlIG9uYm9hcmRpbmcpIiwKICAgIHggPSAiQW5vcyBuYSBFbXByZXNhIiwKICAgIHkgPSAiRGVuc2lkYWRlIgogICkgKwogIHRoZW1lX21pbmltYWwoKSArCiAgdGhlbWUoCiAgICBsZWdlbmQucG9zaXRpb24gPSAibm9uZSIsCiAgICBwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGZhY2UgPSAiYm9sZCIsIHNpemUgPSAxMywgY29sb3IgPSAiIzJjM2U1MCIpLAogICAgcGFuZWwuZ3JpZC5taW5vciA9IGVsZW1lbnRfYmxhbmsoKQogICkKCiMgR3LDoWZpY28gZGUgRGlzdMOibmNpYSAoQm94cGxvdCkKcF9kaXN0IDwtIGdncGxvdChpYm1fY2xlYW4sIGFlcyh4ID0gYXR0cml0aW9uLCB5ID0gZGlzdGFuY2VfZnJvbV9ob21lLCBmaWxsID0gYXR0cml0aW9uKSkgKwogIGdlb21fYm94cGxvdChhbHBoYSA9IDAuOCwgd2lkdGggPSAwLjYsIG91dGxpZXIuY29sb3VyID0gIiNFNzRDM0MiKSArCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gYygiTm8iID0gIiMyQzNFNTAiLCAiWWVzIiA9ICIjRTc0QzNDIikpICsKICBsYWJzKAogICAgdGl0bGUgPSAiTG9nw61zdGljYTogRGlzdMOibmNpYSBDYXNhLVRyYWJhbGhvIiwKICAgIHN1YnRpdGxlID0gIkNvbGFib3JhZG9yZXMgcXVlIHNhZW0gdGVuZGVtIGEgcGVyY29ycmVyIGRpc3TDom5jaWFzIG1haW9yZXMiLAogICAgeCA9ICJEZWNpc8OjbyBkZSBTYcOtZGEiLAogICAgeSA9ICJEaXN0w6JuY2lhIChrbS9taWxoYXMpIgogICkgKwogIHRoZW1lX21pbmltYWwoKSArCiAgdGhlbWUoCiAgICBwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGZhY2UgPSAiYm9sZCIsIHNpemUgPSAxMywgY29sb3IgPSAiIzJjM2U1MCIpLAogICAgcGFuZWwuZ3JpZC5tYWpvci54ID0gZWxlbWVudF9ibGFuaygpCiAgKQoKIyBPcmdhbml6YXIgb3MgZ3LDoWZpY29zCmxpYnJhcnkoZ3JpZEV4dHJhKQpncmlkLmFycmFuZ2UocF95ZWFycywgcF9kaXN0LCBucm93ID0gMiwgCiAgICAgICAgICAgICB0b3AgPSBncmlkOjp0ZXh0R3JvYigiQW7DoWxpc2UgZGUgUmV0ZW7Dp8OjbyBlIExvZ8Otc3RpY2EiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdwID0gZ3JpZDo6Z3Bhcihmb250c2l6ZSA9IDE2LCBmb250ID0gMiwgY29sID0gIiMyYzNlNTAiKSkpCmBgYAoqKl9JbnNpZ2h0c18gZGUgVGVtcG8gZSBMb2fDrXN0aWNhOioqCgpBIGFuw6FsaXNlIGV2aWRlbmNpYSBwb250b3MgY3LDrXRpY29zIG5vIGNpY2xvIGRlIHZpZGEgZG8gY29sYWJvcmFkb3IsIGNvbSBpbXBsaWNhw6fDtWVzIGRpcmV0YXMgcGFyYSBhIHJldGVuw6fDo28gZSBvIGRlc2VtcGVuaG8gb3JnYW5pemFjaW9uYWw6CgoxLiAqKkZhc2UgZGUgX09uYm9hcmRpbmdfIC0gUmlzY28gZGUgc2HDrWRhIHByZWNvY2UqKjogTyBncsOhZmljbyBkZSBhbnRpZ3VpZGFkZSBtb3N0cmEgdW0gcGljbyBhY2VudHVhZG8gZGUgcm90YXRpdmlkYWRlIG5vcyBwcmltZWlyb3MgZG9pcyBhbm9zIGRlIHbDrW5jdWxvLCBwcmVjaXNhbWVudGUgZHVyYW50ZSBvIHBlcsOtb2RvIGRlIGludGVncmHDp8OjbyBlIGFkYXB0YcOnw6NvLiBFc3RlIHJlc3VsdGFkbyBzdWdlcmUgZnJhZ2lsaWRhZGVzIG5vcyBwcm9jZXNzb3MgZGUgYWNvbGhpbWVudG8sIGFjb21wYW5oYW1lbnRvIGluaWNpYWwgb3UgYWxpbmhhbWVudG8gZGUgZXhwZWN0YXRpdmFzIGVudHJlIG8gY29sYWJvcmFkb3IgZSBhIG9yZ2FuaXphw6fDo28uIEludmVzdGlyIGVtIHByb2dyYW1hcyBlc3RydXR1cmFkb3MgZGUgX29uYm9hcmRpbmdfIGUgbWVudG9yaWEgcG9kZXLDoSByZWR1emlyIHN1YnN0YW5jaWFsbWVudGUgZXN0ZSB0aXBvIGRlIHBlcmRhIHByZW1hdHVyYSBkZSB0YWxlbnRvLgoKMi4gKipDdXN0byBkYSBEZXNsb2Nhw6fDo28g4oCTIEZhdG9yIGxvZ8Otc3RpY28gZGUgZGVzZ2FzdGUqKjogTyBib3hwbG90IGRlIGRpc3TDom5jaWFzIGNhc2HigJF0cmFiYWxobyBpbmRpY2EgcXVlIG9zIGNvbGFib3JhZG9yZXMgcXVlIHNhZW0gdGVuZGVtIGEgcGVyY29ycmVyIHRyYWpldG9zIG1haXMgbG9uZ29zLCBvIHF1ZSBhcG9udGEgcGFyYSB1bSBwb3RlbmNpYWwgaW1wYWN0byBuZWdhdGl2byBkbyB0ZW1wbyBlIGVzZm9yw6dvIGRlIGRlc2xvY2HDp8OjbyBuYSBzYXRpc2Zhw6fDo28gZ2VyYWwuIE8gZGVzZ2FzdGUgYXNzb2NpYWRvIGFvIF9jb21tdXRpbmdfIGRpw6FyaW8sIHF1YW5kbyBjb21iaW5hZG8gY29tIGVsZXZhZGFzIGNhcmdhcyBkZSB0cmFiYWxobywgYXVtZW50YSBhIHByb2JhYmlsaWRhZGUgZGUgc2HDrWRhIHZvbHVudMOhcmlhLiBNZWRpZGFzIGNvbW8gdGVsZXRyYWJhbGhvIGjDrWJyaWRvLCBhZGFwdGHDp8OjbyBkZSBob3LDoXJpb3Mgb3UgaW5jZW50aXZvcyBkZSB0cmFuc3BvcnRlIHBvZGVtIG1pdGlnYXIgZXNzZSBlZmVpdG8uCgoqKkNvbmNsdXPDo28qKjogQSByZXRlbsOnw6NvIGVmaWNheiBleGlnZSB1bWEgYWJvcmRhZ2VtIGhvbMOtc3RpY2EgcXVlIGFicmFuamEgdGFudG8gYSBleHBlcmnDqm5jaWEgaW5pY2lhbCBkbyBjb2xhYm9yYWRvciAoX29uYm9hcmRpbmdfKSBjb21vIGEgc3VzdGVudGFiaWxpZGFkZSBsb2fDrXN0aWNhIGRhIHN1YSByb3RpbmEgbGFib3JhbC4gRXN0YXMgZHVhcyBkaW1lbnPDtWVzIHJldmVsYW3igJFzZSBkZXRlcm1pbmFudGVzIHBhcmEgY29uc29saWRhciBvIGNvbXByb21pc3NvIG9yZ2FuaXphY2lvbmFsIG5vcyBwcmltZWlyb3MgYW5vcyBkZSB2w61uY3Vsby4KCiMjIEFuw6FsaXNlIGRvIEfDqW5lcm8gZSBXb3JrLUxpZmUgQmFsYW5jZQpgYGB7ciBhbmFsaXNlX2dlbmVyb193fQojIFJvdGF0aXZpZGFkZSBwb3IgR8OpbmVybyAocF9nZW4pCnBfZ2VuIDwtIGdncGxvdChpYm1fY2xlYW4sIGFlcyh4ID0gZ2VuZGVyLCBmaWxsID0gYXR0cml0aW9uKSkgKwogIGdlb21fYmFyKHBvc2l0aW9uID0gImZpbGwiLCB3aWR0aCA9IDAuNiwgYWxwaGEgPSAwLjkpICsKICBzY2FsZV95X2NvbnRpbnVvdXMobGFiZWxzID0gc2NhbGVzOjpwZXJjZW50X2Zvcm1hdCgpLCBleHBhbmQgPSBjKDAsMCkpICsKICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBjKCJObyIgPSAiIzJDM0U1MCIsICJZZXMiID0gIiNFNzRDM0MiKSkgKwogIGxhYnMoCiAgICB0aXRsZSA9ICJSb3RhdGl2aWRhZGUgcG9yIEfDqW5lcm8iLCAKICAgIHN1YnRpdGxlID0gIkV4aXN0ZSBkaXNwYXJpZGFkZSBlbnRyZSBob21lbnMgZSBtdWxoZXJlcz8iLAogICAgeCA9IE5VTEwsIAogICAgeSA9ICJQcm9wb3LDp8OjbyIKICApICsKICB0aGVtZV9taW5pbWFsKCkgKwogIHRoZW1lKAogICAgbGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiLCAjIEVzY29uZGVtb3MgYSBsZWdlbmRhIGFxdWkgcGFyYSBuw6NvIHJlcGV0aXIKICAgIHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoZmFjZSA9ICJib2xkIiwgc2l6ZSA9IDEzLCBjb2xvciA9ICIjMmMzZTUwIiksCiAgICBwYW5lbC5ncmlkLm1ham9yLnggPSBlbGVtZW50X2JsYW5rKCksCiAgICBheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChmYWNlID0gImJvbGQiKQogICkKCiMgQW7DoWxpc2UgZG8gV29yay1MaWZlIEJhbGFuY2UgKHBfd2xiKQpwX3dsYiA8LSBnZ3Bsb3QoaWJtX2NsZWFuLCBhZXMoeCA9IGZhY3Rvcih3b3JrX2xpZmVfYmFsYW5jZSksIGZpbGwgPSBhdHRyaXRpb24pKSArCiAgZ2VvbV9iYXIocG9zaXRpb24gPSAiZmlsbCIsIHdpZHRoID0gMC42LCBhbHBoYSA9IDAuOSkgKwogIHNjYWxlX3lfY29udGludW91cyhsYWJlbHMgPSBzY2FsZXM6OnBlcmNlbnRfZm9ybWF0KCksIGV4cGFuZCA9IGMoMCwwKSkgKwogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IGMoIk5vIiA9ICIjMkMzRTUwIiwgIlllcyIgPSAiI0U3NEMzQyIpKSArCiAgbGFicygKICAgIHRpdGxlID0gIkVxdWlsw61icmlvIFZpZGEtVHJhYmFsaG8iLCAKICAgIHN1YnRpdGxlID0gIk8gaW1wYWN0byBkbyBlcXVpbMOtYnJpbyBuYSBkZWNpc8OjbyBkZSBzYcOtZGEiLAogICAgeCA9ICJOw612ZWwgKDE6IE1hdSDihpIgNDogRXhjZWxlbnRlKSIsIAogICAgeSA9IE5VTEwsCiAgICBmaWxsID0gIlNhw61kYT8iCiAgKSArCiAgdGhlbWVfbWluaW1hbCgpICsKICB0aGVtZSgKICAgIHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoZmFjZSA9ICJib2xkIiwgc2l6ZSA9IDEzLCBjb2xvciA9ICIjMmMzZTUwIiksCiAgICBsZWdlbmQucG9zaXRpb24gPSAicmlnaHQiLAogICAgcGFuZWwuZ3JpZC5tYWpvci54ID0gZWxlbWVudF9ibGFuaygpLAogICAgYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoZmFjZSA9ICJib2xkIikKICApCgojIEp1bnRhciBvcyBkb2lzIGxhZG8gYSBsYWRvCmxpYnJhcnkoZ3JpZEV4dHJhKQpncmlkLmFycmFuZ2UocF9nZW4sIHBfd2xiLCBuY29sID0gMiwgCiAgICAgICAgICAgICB0b3AgPSBncmlkOjp0ZXh0R3JvYigiQmVtLUVzdGFyIGUgRGl2ZXJzaWRhZGUiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdwID0gZ3JpZDo6Z3Bhcihmb250c2l6ZSA9IDE2LCBmb250ID0gMiwgY29sID0gIiMyYzNlNTAiKSkpCmBgYAoqKl9JbnNpZ2h0c18gZGUgR8OpbmVybyBlIEJlbS1Fc3RhcjoqKgoKUGFyYSBjb25jbHVpciBhIGFuw6FsaXNlIGJpdmFyaWFkYSwgZGVzdGFjYW3igJFzZSBkb2lzIGZhdG9yZXMgZGUgbmF0dXJlemEgc29jaWFsIGUgY29tcG9ydGFtZW50YWwgY29tIGltcGFjdG8gbmEgcm90YXRpdmlkYWRlOgoKMS4gKipOZXV0cmFsaWRhZGUgZGUgR8OpbmVybyoqIOKAkyBBIHRheGEgZGUgc2HDrWRhIHJldmVsYeKAkXNlIHJlbGF0aXZhbWVudGUgdW5pZm9ybWUgZW50cmUgaG9tZW5zIGUgbXVsaGVyZXMsIHNpdHVhbmRv4oCRc2UgZW50cmUgMTUlIGUgMTclLiBFc3RlIHJlc3VsdGFkbyBzdWdlcmUgYXVzw6puY2lhIGRlIGVudmllc2FtZW50b3Mgb3UgcHLDoXRpY2FzIGRpc2NyaW1pbmF0w7NyaWFzIGFzc29jaWFkYXMgYW8gZ8OpbmVybywgYmVtIGNvbW8gZXF1aWRhZGUgbmEgZXhwZXJpw6puY2lhIG9yZ2FuaXphY2lvbmFsIGVudHJlIGdydXBvcy4KCjIuICoqRXF1aWzDrWJyaW8gVmlkYeKAkVRyYWJhbGhvKiog4oCTIEEgdmFyacOhdmVsIF9Xb3Jr4oCRTGlmZSBCYWxhbmNlXyBldmlkZW5jaWEgdW0g4oCccG9udG8gY3LDrXRpY2/igJ0gbm8gbsOtdmVsIG1haXMgYmFpeG8gZGUgc2F0aXNmYcOnw6NvLiBDb2xhYm9yYWRvcmVzIHF1ZSBjbGFzc2lmaWNhbSBvIHNldSBlcXVpbMOtYnJpbyBjb21vIOKAnE1hdeKAnSAoTsOtdmVsIDEpIGFwcmVzZW50YW0gdW1hIHRheGEgZGUgcm90YXRpdmlkYWRlIHByw7N4aW1hIGRlIDMwJSwgbyBkb2JybyBkYSB2ZXJpZmljYWRhIG5vcyByZXN0YW50ZXMgbsOtdmVpcy4KQSBtZWxob3JpYSBkbyBlcXVpbMOtYnJpbyB2aWRh4oCRdHJhYmFsaG8sIG1lc21vIHF1ZSBhcGVuYXMgZGUgTsOtdmVsIDEgcGFyYSBOw612ZWwgMiwgasOhIHByb2R1eiB1bWEgcmVkdcOnw6NvIHN1YnN0YW5jaWFsIG5hIHRheGEgZGUgc2HDrWRhLiBJc3RvIGluZGljYSBxdWUgaW50ZXJ2ZW7Dp8O1ZXMgcG9udHVhaXMgZSByZWFsaXN0YXMsIGNvbW8gYWp1c3RlcyBkZSBob3LDoXJpbywgcG9sw610aWNhcyBkZSBmbGV4aWJpbGlkYWRlIG91IHJlZm9yw6dvIGRvIGFwb2lvIMOgIGVxdWlwYSwgcG9kZW0gZ2VyYXIgZWZlaXRvcyBpbWVkaWF0b3MgbmEgcmV0ZW7Dp8Ojbywgc2VtIHNlciBuZWNlc3PDoXJpbyBhdGluZ2lyIG7DrXZlaXMg4oCcaWRlYWlz4oCdIGRlIHNhdGlzZmHDp8OjbyAoTsOtdmVsIDQpLgoKKipDb25jbHVzw6NvKio6IE9zIHJlc3VsdGFkb3MgYXBvbnRhbSBwYXJhIHVtYSBjdWx0dXJhIG9yZ2FuaXphY2lvbmFsIHJlbGF0aXZhbWVudGUgZXF1aWxpYnJhZGEgZW0gdGVybW9zIGRlIGfDqW5lcm8sIG1hcyB2dWxuZXLDoXZlbCBhIGZhdG9yZXMgbGlnYWRvcyBhbyBiZW3igJFlc3RhciBlIGVxdWlsw61icmlvIHBlc3NvYWzigJFwcm9maXNzaW9uYWwuIEludmVzdGlyIGVtIHBvbMOtdGljYXMgZGUgc2HDumRlIG9jdXBhY2lvbmFsIGUgZmxleGliaWxpZGFkZSBsYWJvcmFsIHBvZGVyw6EgdGVyIHVtIHJldG9ybm8gZGlyZXRvIG5hIHNhdGlzZmHDp8OjbyBlIGZpZGVsaXphw6fDo28gZG9zIGNvbGFib3JhZG9yZXMuCiAgICAKIyBBbsOhbGlzZSBNdWx0aXZhcmlhZGEgKENvcnJlbGHDp8O1ZXMpCk5lc3RhIGV0YXBhLCBmb2kgYW5hbGlzYWRhIGEgcmVsYcOnw6NvIGVudHJlIGFzIHZhcmnDoXZlaXMgbnVtw6lyaWNhcyBwYXJhIGlkZW50aWZpY2FyIG11bHRpY29saW5lYXJpZGFkZSAocmVkdW5kw6JuY2lhKS4gRm9pIHV0aWxpemFkYSB1bWEgbWF0cml6IGRlIGNvcnJlbGHDp8OjbyB2aXN1YWwuCmBgYHtyfQoKaWJtX251bWVyaWMgPC0gaWJtX2NsZWFuICU+JSBzZWxlY3Qod2hlcmUoaXMubnVtZXJpYykpCm1hdHJpel9jb3IgIDwtIGNvcihpYm1fbnVtZXJpYywgdXNlID0gImNvbXBsZXRlLm9icyIpCgojIEdyw6FmaWNvIGRlIGNvcnJlbGHDp8O1ZXMKY29sX3BhbGV0YSA8LSBjb2xvclJhbXBQYWxldHRlKGMoIiNFNzRDM0MiLCAiI0ZGRkZGRiIsICIjMkMzRTUwIikpKDIwMCkKCmNvcnJwbG90KG1hdHJpel9jb3IsIAogICAgICAgICBtZXRob2QgPSAiY29sb3IiLCAKICAgICAgICAgdHlwZSA9ICJ1cHBlciIsIAogICAgICAgICBvcmRlciA9ICJoY2x1c3QiLCAgICAgICAgIAogICAgICAgICB0bC5jb2wgPSAiYmxhY2siLCAKICAgICAgICAgdGwuY2V4ID0gMC43LCAKICAgICAgICAgY29sID0gY29sX3BhbGV0YSwgICAgICAgICAKICAgICAgICAgdGl0bGUgPSAiXG4gTWFwYSBkZSBDb3JyZWxhw6fDtWVzIEludGVydmFyacOhdmVpcyIsIAogICAgICAgICBtYXIgPSBjKDAsMCwyLDApLAogICAgICAgICBkaWFnID0gRkFMU0UpCgojIFRhYmVsYSBkZSBjb3JyZWxhw6fDtWVzCnRhYmVsYV9jb3IgPC0gYXMuZGF0YS5mcmFtZShhcy50YWJsZShtYXRyaXpfY29yKSkKCnRhYmVsYV9tZWxob3JhZGEgPC0gdGFiZWxhX2NvciAlPiUKICBmaWx0ZXIoVmFyMSAhPSBWYXIyKSAlPiUKICBmaWx0ZXIoIWR1cGxpY2F0ZWQocGFzdGUwKHBtYXgoYXMuY2hhcmFjdGVyKFZhcjEpLCBhcy5jaGFyYWN0ZXIoVmFyMikpLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBtaW4oYXMuY2hhcmFjdGVyKFZhcjEpLCBhcy5jaGFyYWN0ZXIoVmFyMikpKSkpICU+JQogIGFycmFuZ2UoZGVzYyhhYnMoRnJlcSkpKSAlPiUKICByZW5hbWUoVmFyaWF2ZWxfMSA9IFZhcjEsIFZhcmlhdmVsXzIgPSBWYXIyLCBDb3JyZWxhY2FvID0gRnJlcSkKCiMgTWVsaG9yYXIgZGVzaWduIGRhIHRhYmVsYQprYWJsZShoZWFkKHRhYmVsYV9tZWxob3JhZGEsIDEwKSwgCiAgICAgIGNhcHRpb24gPSAiVG9wIDEwIENvcnJlbGHDp8O1ZXMgTWFpcyBGb3J0ZXMgSWRlbnRpZmljYWRhcyIsIAogICAgICBkaWdpdHMgPSAyLAogICAgICBjb2wubmFtZXMgPSBjKCJWYXJpw6F2ZWwgMSIsICJWYXJpw6F2ZWwgMiIsICJGb3LDp2EgZGEgQ29ycmVsYcOnw6NvIikpICU+JQogIGthYmxlX3N0eWxpbmcoCiAgICBib290c3RyYXBfb3B0aW9ucyA9IGMoInN0cmlwZWQiLCAiaG92ZXIiLCAiY29uZGVuc2VkIiksIAogICAgZnVsbF93aWR0aCA9IFQsICAgICAgICAgICAKICAgIHBvc2l0aW9uID0gImNlbnRlciIsICAgICAgCiAgICBmb250X3NpemUgPSAxNCAgICAgICAgICAgIAogICkgJT4lCiAgcm93X3NwZWMoMCwgYm9sZCA9IFQsIGNvbG9yID0gIndoaXRlIiwgYmFja2dyb3VuZCA9ICIjMmMzZTUwIikgJT4lCiAgIyBEZXN0YWNhIGVtIHZlcm1lbGhvIGFzIGNvcnJlbGHDp8O1ZXMgcXVlIHBvZGVtIGNhdXNhciBtdWx0aWNvbGluZWFyaWRhZGUgKD4wLjcpCiAgY29sdW1uX3NwZWMoMywgYm9sZCA9IFQsIAogICAgICAgICAgICAgIGNvbG9yID0gaWZlbHNlKGFicyhoZWFkKHRhYmVsYV9tZWxob3JhZGEkQ29ycmVsYWNhbywgMTApKSA+IDAuNywgIiNFNzRDM0MiLCAiYmxhY2siKSkKYGBgCioqX0luc2lnaHRzXyBkYSBBbsOhbGlzZSBkZSBDb3JyZWxhw6fDo286KioKCkEgbWF0cml6IGUgYSB0YWJlbGEgZGUgY29ycmVsYcOnw7VlcyBldmlkZW5jaWFtIHBhZHLDtWVzIGRlIG11bHRpY29saW5lYXJpZGFkZSBzaWduaWZpY2F0aXZvcywgcmV2ZWxhbmRvIHZhcmnDoXZlaXMgZm9ydGVtZW50ZSByZWR1bmRhbnRlcyBxdWUgZXhpZ2lyw6NvIHRyYXRhbWVudG8gZXNwZWPDrWZpY28gbmEgZmFzZSBkZSBwcsOp4oCRcHJvY2Vzc2FtZW50byBkb3MgZGFkb3M6CgoKMS4gKipSZWR1bmTDom5jaWEgZW50cmUgcmVtdW5lcmHDp8OjbyBlIG7DrXZlbCBoaWVyw6FycXVpY28qKjogQSBjb3JyZWxhw6fDo28gbWFpcyBlbGV2YWRhIGRlIHRvZG8gbyBjb25qdW50byDDqSBvYnNlcnZhZGEgZW50cmUgYE1vbnRobHlJbmNvbWVgIGUgYEpvYkxldmVsYCAociA9IDAuOTUpLgoKKipJbnRlcnByZXRhw6fDo28qKjogRXN0YXMgdmFyacOhdmVpcyBzw6NvLCBuYSBwcsOhdGljYSwgZXN0YXRpc3RpY2FtZW50ZSBzb2JyZXBvc3RhcywgcGVsbyBxdWUgbyBuw612ZWwgZG8gY2FyZ28gZGV0ZXJtaW5hIHF1YXNlIHRvdGFsbWVudGUgbyBzYWzDoXJpby4KTWFudGVyIGFtYmFzIG5vIG1vZGVsbyBwb2RlcsOhIGludHJvZHV6aXIgaW5zdGFiaWxpZGFkZSBub3MgY29lZmljaWVudGVzIGUgZW52aWVzYXIgYSBpbXBvcnTDom5jaWEgcHJlZGl0aXZhLiBBc3NpbSwgc2Vyw6EgcmVjb21lbmTDoXZlbCByZXRlciBhcGVuYXMgdW1hIHZhcmnDoXZlbCByZXByZXNlbnRhdGl2YSAocG9yIGV4ZW1wbG8sIGBKb2JMZXZlbGApLgoKCjIuICoqQW50aWd1aWRhZGUqKjogSWRlbnRpZmljYeKAkXNlIHVtIF9jbHVzdGVyXyBkZSB2YXJpw6F2ZWlzIHRlbXBvcmFpcyBhbHRhbWVudGUgY29ycmVsYWNpb25hZGFzLCBgWWVhcnNBdENvbXBhbnlgLCBgWWVhcnNJbkN1cnJlbnRSb2xlYCBlIGBZZWFyc1dpdGhDdXJyTWFuYWdlcmAsIGNvbSBjb3JyZWxhw6fDtWVzIGVudHJlIDAuNzEgZSAwLjc3LgoKKipJbnRlcnByZXRhw6fDo28qKjogRnVuY2lvbsOhcmlvcyBjb20gbWFpb3IgYW50aWd1aWRhZGUgdGVuZGVtIGEgcGVybWFuZWNlciBuYSBtZXNtYSBmdW7Dp8OjbyBlIHNvYiBhIG1lc21hIGxpZGVyYW7Dp2EuIENvbnbDqW0sIHBvcnRhbnRvLCBldml0YXIgaW5jbHVpciB0b2RhcyBzaW11bHRhbmVhbWVudGUsIHBvZGVuZG8gb3B0YXLigJFzZSBwb3IgYFllYXJzQXRDb21wYW55YCBvdSBwZWxhIGNyaWHDp8OjbyBkZSB1bWEgdmFyacOhdmVsIGFncmVnYWRhIGRlIOKAnGVzdGFnbmHDp8Ojb+KAnSwgcXVlIGNhcHR1cmUgZXN0YSBkaW7Dom1pY2EuCgoKMy4gKipFeHBlcmnDqm5jaWEgcHJvZmlzc2lvbmFsIGUgcmVtdW5lcmHDp8OjbyoqOiBBIHZhcmnDoXZlbCBgVG90YWxXb3JraW5nWWVhcnNgIGFwcmVzZW50YSBjb3JyZWxhw6fDo28gZm9ydGUgY29tIGBKb2JMZXZlbGAgKDAuNzgpIGUgYE1vbnRobHlJbmNvbWVgICgwLjc3KS4KCioqSW50ZXJwcmV0YcOnw6NvKio6IE8gc2lzdGVtYSBkZSBwcm9ncmVzc8OjbyBlIGNvbXBlbnNhw6fDo28gZGEgZW1wcmVzYSBhcGFyZW50YSBlc3RhciBhbHRhbWVudGUgYWxpbmhhZG8gY29tIGEgc2VuaW9yaWRhZGUsIHZhbG9yaXphbmRvIHNvYnJldHVkbyBhIGV4cGVyacOqbmNpYSBhY3VtdWxhZGEuCgoKNC4gKipEZXNlbXBlbmhvIGUgcmVjb21wZW5zYXMqKjogQSBjb3JyZWxhw6fDo28gZGUgMC43NyBlbnRyZSBgUGVyZm9ybWFuY2VSYXRpbmdgIGUgYFBlcmNlbnRTYWxhcnlIaWtlYCBjb25maXJtYSBxdWUgb3MgYXVtZW50b3Mgc2FsYXJpYWlzIGVzdMOjbyBkaXJldGFtZW50ZSBhc3NvY2lhZG9zIMOgIGF2YWxpYcOnw6NvIGRlIGRlc2VtcGVuaG8gYW51YWwg4oCUIHVtYSBwb2zDrXRpY2EgdMOtcGljYSBkZSBtZXJpdG9jcmFjaWEgb3JnYW5pemFjaW9uYWwuCgoqKkNvbmNsdXPDo28gZGEgQW7DoWxpc2UgRXhwbG9yYXTDs3JpYSAoRURBKSoqOiBBIGV4cGxvcmHDp8OjbyBiaXZhcmlhZGEgZSBjb3JyZWxhY2lvbmFsIHBlcm1pdGUgY29uY2x1aXIgcXVlIGEgcm90YXRpdmlkYWRlIGVzdMOhIGFzc29jaWFkYSBhIGZhdG9yZXMgZGVtb2dyw6FmaWNvcyBlIGxhYm9yYWlzIChpZGFkZSBqb3ZlbSwgY2FyZ29zIG9wZXJhY2lvbmFpcywgdmlhZ2VucyBmcmVxdWVudGVzLCBzYWzDoXJpb3MgbWFpcyBiYWl4b3MpLCBlbnF1YW50byBubyBwbGFubyB0w6ljbmljbyBkZXN0YWNhbeKAkXNlIHJlbGHDp8O1ZXMgcmVkdW5kYW50ZXMgZW50cmUgdmFyacOhdmVpcyBkZSBoaWVyYXJxdWlhLCBhbnRpZ3VpZGFkZSBlIHJlbXVuZXJhw6fDo28uCgpFc3RhcyBjb25zdGF0YcOnw7VlcyBjb25zdGl0dWVtIG8gcG9udG8gZGUgcGFydGlkYSBwYXJhIG8gcHLDqeKAkXByb2Nlc3NhbWVudG8gZGUgZGFkb3MsIG9uZGUgc2Vyw6NvIHRyYXRhZGFzIGFzIGNvcnJlbGHDp8O1ZXMgZXhjZXNzaXZhcyBlIHNlbGVjaW9uYWRhcyBhcyB2YXJpw6F2ZWlzIG1haXMgcmVsZXZhbnRlcyBwYXJhIG9zIG1vZGVsb3MgcHJlZGl0aXZvcy4KCiMgUHLDqS1wcm9jZXNzYW1lbnRvIGRlIGRhZG9zCiMjIFNlbGXDp8OjbyBkZSB2YXJpw6F2ZWlzIChGZWF0dXJlIFNlbGVjdGlvbikKYGBge3J9CiMgRXhlY3V0YXIgYSBTZWxlw6fDo28KaWJtX3ByZXAgPC0gaWJtX2NsZWFuICU+JQogIHNlbGVjdCgtam9iX2xldmVsKSAlPiUgIAogIHNlbGVjdCgtYW55X29mKGMoImVtcGxveWVlX251bWJlciIsICJlbXBsb3llZV9jb3VudCIsICJvdmVyMTgiLCAic3RhbmRhcmRfaG91cnMiKSkpICU+JQogIG11dGF0ZShhdHRyaXRpb24gPSBpZmVsc2UoYXR0cml0aW9uID09ICJZZXMiLCAxLCAwKSkKCiMgQ3JpYXIgVGFiZWxhIGRlIEltcGFjdG8KcmVzdW1vX3ByZXAgPC0gZGF0YS5mcmFtZSgKICBFdGFwYSA9IGMoIkNvbHVuYXMgT3JpZ2luYWlzIiwgIkNvbHVuYXMgUmVtb3ZpZGFzIiwgIlRvdGFsIEZpbmFsIiwgIlRhcmdldCAoQXR0cml0aW9uKSIpLAogIFZhbG9yID0gYyhuY29sKGlibV9jbGVhbiksIAogICAgICAgICAgICBuY29sKGlibV9jbGVhbikgLSBuY29sKGlibV9wcmVwKSwgCiAgICAgICAgICAgIG5jb2woaWJtX3ByZXApLCAKICAgICAgICAgICAgIkNvbnZlcnRpZG8gcGFyYSBCaW7DoXJpbyAoMC8xKSIpCikKCnJlc3Vtb19wcmVwICU+JQogIGthYmxlKGNhcHRpb24gPSAiUmVzdW1vIGRvIFByw6ktcHJvY2Vzc2FtZW50byBlIEZlYXR1cmUgU2VsZWN0aW9uIikgJT4lCiAga2FibGVfc3R5bGluZyhib290c3RyYXBfb3B0aW9ucyA9IGMoInN0cmlwZWQiLCAiaG92ZXIiLCAiY29uZGVuc2VkIiksIGZ1bGxfd2lkdGggPSBGKSAlPiUKICByb3dfc3BlYygwLCBib2xkID0gVCwgY29sb3IgPSAid2hpdGUiLCBiYWNrZ3JvdW5kID0gIiMyYzNlNTAiKQpgYGAKQXDDs3MgYSBmYXNlIGRlIGFuw6FsaXNlIGV4cGxvcmF0w7NyaWEsIHByb2NlZGV14oCRc2Ugw6AgcHJlcGFyYcOnw6NvIGRvcyBkYWRvcyBwYXJhIGEgbW9kZWxhw6fDo28gcHJlZGl0aXZhLgoKRXN0YSBldGFwYSDDqSBmdW5kYW1lbnRhbCBwYXJhIGdhcmFudGlyIHF1ZSBvIG1vZGVsbyByZXN1bHRhbnRlIG7Do28gc2VqYSBpbmZsdWVuY2lhZG8gcG9yIHJ1w61kbyBlc3RhdMOtc3RpY28gbmVtIHBvciBpbmZvcm1hw6fDo28gcmVkdW5kYW50ZSwgYXNzZWd1cmFuZG8gYSByb2J1c3RleiBlIGludGVycHJldGFiaWxpZGFkZSBkb3MgcmVzdWx0YWRvcy4KClByaW5jaXBhaXMgZGVjaXPDtWVzIG5lc3RhIGZhc2U6CgoxLiAqKkVsaW1pbmHDp8OjbyBkZSByZWR1bmTDom5jaWEgKG11bHRpY29saW5lYXJpZGFkZSkqKiDigJMgQ29uZm9ybWUgaWRlbnRpZmljYWRvIG5hIG1hdHJpeiBkZSBjb3JyZWxhw6fDtWVzLCBhcyB2YXJpw6F2ZWlzIGBtb250aGx5X2luY29tZWAgZSBgam9iX2xldmVsYCBhcHJlc2VudGF2YW0gdW1hIGNvcnJlbGHDp8OjbyBkZSAwLDk1LiBQYXJhIGV2aXRhciBzb2JyZWFqdXN0ZSAoX292ZXJmaXR0aW5nXykgZSBzaW1wbGlmaWNhciBvIG1vZGVsbywgZGVjaWRpdeKAkXNlIG1hbnRlciBhcGVuYXMgYSB2YXJpw6F2ZWwgbWFpcyByZXByZXNlbnRhdGl2YSwgcHJpdmlsZWdpYW5kbyBvIGltcGFjdG8gZmluYW5jZWlybyBkaXJldG8uCgoyLiAqKkNvbnZlcnPDo28gZGEgdmFyacOhdmVs4oCRYWx2byoqIOKAkyBBIHZhcmnDoXZlbCBgYXR0cml0aW9uYCBmb2kgdHJhbnNmb3JtYWRhIHBhcmEgZm9ybWF0byBiaW7DoXJpbyAoMC8xKSwgZGUgbW9kbyBhIHBlcm1pdGlyIGEgYXBsaWNhw6fDo28gZGUgbW9kZWxvcyBkZSBjbGFzc2lmaWNhw6fDo28gc3VwZXJ2aXNpb25hZGEgZSBmYWNpbGl0YXIgYSBhbsOhbGlzZSBkZSBkZXNlbXBlbmhvIHByZWRpdGl2by4KCkVzdGFzIG9wZXJhw6fDtWVzIGFzc2VndXJhbSBxdWUgbyBjb25qdW50byBkZSBkYWRvcyBmaW5hbCBlc3RlamEgZXN0YXRpc3RpY2FtZW50ZSBlcXVpbGlicmFkbywgY29tcHV0YWNpb25hbG1lbnRlIGVmaWNpZW50ZSBlIGFkZXF1YWRvIMOgIGZhc2Ugc2VndWludGUgZGUgbW9kZWxhw6fDo28uCgojIyBDcmlhw6fDo28gZGUgRHVtbWllcwpgYGB7cn0KbGlicmFyeShmYXN0RHVtbWllcykKCmlibV9maW5hbCA8LSBkdW1teV9jb2xzKGlibV9wcmVwLCAKICAgICAgICAgICAgICAgICAgICAgICAgcmVtb3ZlX2ZpcnN0X2R1bW15ID0gVFJVRSwgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgcmVtb3ZlX3NlbGVjdGVkX2NvbHVtbnMgPSBUUlVFKSAlPiUKICAgICAgICAgICAgIGNsZWFuX25hbWVzKCkgIyBHYXJhbnRlIHF1ZSBvcyBub21lcyBkYXMgbm92YXMgY29sdW5hcyBmaWNhbSBwYWRyb25pemFkb3MKCiMgQ3JpYXIgdW1hIGNvbXBhcmHDp8OjbyB2aXN1YWwKY29tcGFyYXRpdm9fZGltIDwtIGRhdGEuZnJhbWUoCiAgTWV0cmljYSA9IGMoIkNvbHVuYXMgUHLDqS1EdW1taWVzIiwgIkNvbHVuYXMgUMOzcy1EdW1taWVzIChFeHBhbmRpZGFzKSIsICJOb3ZhcyBWYXJpw6F2ZWlzIENyaWFkYXMiKSwKICBRdWFudGlkYWRlID0gYyhuY29sKGlibV9wcmVwKSwgbmNvbChpYm1fZmluYWwpLCBuY29sKGlibV9maW5hbCkgLSBuY29sKGlibV9wcmVwKSkKKQoKIyBFeGliaXIgVGFiZWxhIGRlIEltcGFjdG8KY29tcGFyYXRpdm9fZGltICU+JQogIGthYmxlKGNhcHRpb24gPSAiSW1wYWN0byBkYSBUcmFuc2Zvcm1hw6fDo28gZGUgVmFyacOhdmVpcyBDYXRlZ8OzcmljYXMgKE9uZS1Ib3QgRW5jb2RpbmcpIikgJT4lCiAga2FibGVfc3R5bGluZyhib290c3RyYXBfb3B0aW9ucyA9IGMoInN0cmlwZWQiLCAiaG92ZXIiLCAiY29uZGVuc2VkIiksIGZ1bGxfd2lkdGggPSBGKSAlPiUKICByb3dfc3BlYygwLCBib2xkID0gVCwgY29sb3IgPSAid2hpdGUiLCBiYWNrZ3JvdW5kID0gIiMyYzNlNTAiKQoKIyBNb3N0cmFyIGFzIG5vdmFzIGNvbHVuYXMgCmRhdGEuZnJhbWUoRXhlbXBsb3NfTm92YXNfQ29sdW5hcyA9IGNvbG5hbWVzKGlibV9maW5hbClbKG5jb2woaWJtX3ByZXApKzEpOihuY29sKGlibV9wcmVwKSs2KV0pICU+JQogIGthYmxlKCkgJT4lCiAga2FibGVfc3R5bGluZyhib290c3RyYXBfb3B0aW9ucyA9ICJib3JkZXJlZCIsIGZ1bGxfd2lkdGggPSBGLCBwb3NpdGlvbiA9ICJmbG9hdF9yaWdodCIpCmBgYApBIG1haW9yaWEgZG9zIGFsZ29yaXRtb3MgZGUgTWFjaGluZSBMZWFybmluZyBuw6NvIMOpIGNhcGF6IGRlIHByb2Nlc3NhciBkaXJldGFtZW50ZSB2YXJpw6F2ZWlzIGRlIHRleHRvLgoKUGFyYSB1bHRyYXBhc3NhciBlc3RhIGxpbWl0YcOnw6NvLCBhcGxpY2914oCRc2UgYSB0w6ljbmljYSBkZSBPbmXigJFIb3QgRW5jb2RpbmcsIHRhbWLDqW0gY29uaGVjaWRhIHBvciBjcmlhw6fDo28gZGUgdmFyacOhdmVpcyBkdW1teS4KClByb2NlZGltZW50b3MgcmVhbGl6YWRvczoKCjEuICoqVHJhbnNmb3JtYcOnw6NvIGRlIHZhcmnDoXZlaXMgY2F0ZWfDs3JpY2FzKiog4oCTIFZhcmnDoXZlaXMgcXVhbGl0YXRpdmFzLCBjb21vIGBCdXNpbmVzc1RyYXZlbGAgb3UgYERlcGFydG1lbnRgLCBmb3JhbSBjb252ZXJ0aWRhcyBlbSBtw7psdGlwbGFzIGNvbHVuYXMgYmluw6FyaWFzICgwLzEpLCByZXByZXNlbnRhbmRvIGEgcHJlc2Vuw6dhIG91IGF1c8OqbmNpYSBkZSBjYWRhIGNhdGVnb3JpYSBkaXN0aW50YS4KCjIuICoqUHJldmVuw6fDo28gZGUgbXVsdGljb2xpbmVhcmlkYWRlKiog4oCTIFBhcmEgZXZpdGFyIGEgY2hhbWFkYSBfZHVtbXkgdmFyaWFibGUgdHJhcF8sIGZvaSBhdGl2YWRvIG8gcGFyw6JtZXRybyBgcmVtb3ZlX2ZpcnN0X2R1bW15ID0gVFJVRWAsIG8gcXVlIHJlbW92ZSB1bWEgY2F0ZWdvcmlhIGRlIGNhZGEgZ3J1cG8uIEFzc2ltLCBwb3IgZXhlbXBsbywgbm8gY2FzbyBkZSB1bWEgdmFyacOhdmVsIGNvbSBhcyBtb2RhbGlkYWRlcyBNYXNjdWxpbm8gZSBGZW1pbmlubywgYXBlbmFzIHVtYSBkZWxhcyDDqSBtYW50aWRhLCBkYWRvIHF1ZSBhIGF1c8OqbmNpYSBkZSB1bWEgaW1wbGljYSBhIHByZXNlbsOnYSBkYSBvdXRyYS4KCjMuICoqRXhwYW5zw6NvIGNvbnRyb2xhZGEgZG8gX2RhdGFzZXRfKiog4oCTIEFww7NzIG8gcHJvY2Vzc28sIG8gbsO6bWVybyB0b3RhbCBkZSB2YXJpw6F2ZWlzIGF1bWVudG91IGRlIDMwIHBhcmEgNDQsIHJlc3VsdGFuZG8gbmEgY3JpYcOnw6NvIGRlIDE0IG5vdmFzIHZhcmnDoXZlaXMgZGVyaXZhZGFzLgoKRXN0YSBleHBhbnPDo28gcGVybWl0ZSByZXByZXNlbnRhciBkZSBmb3JtYSBtYWlzIHJpY2EgYSBpbmZvcm1hw6fDo28gcXVhbGl0YXRpdmEsIHNlbSBpbnRyb2R1emlyIHJlZHVuZMOibmNpYSBvdSBjb21wcm9tZXRlciBhIGVzdGFiaWxpZGFkZSBkb3MgbW9kZWxvcyBwcmVkaXRpdm9zLgoKIyMgRGl2aXPDo28gZG9zIERhZG9zIChUcmVpbm8gZSBUZXN0ZSkKYGBge3IgZGl2aXNhb19kYWRvcywgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KbGlicmFyeShjYVRvb2xzKQpsaWJyYXJ5KGRwbHlyKQpsaWJyYXJ5KGthYmxlRXh0cmEpCgojIERpdmlzw6NvIEVzdHJhdGlmaWNhZGEgCnNldC5zZWVkKDEyMykKc3BsaXQgPC0gc2FtcGxlLnNwbGl0KGlibV9maW5hbCRhdHRyaXRpb24sIFNwbGl0UmF0aW8gPSAwLjcwKQoKZGFkb3NfdHJlaW5vIDwtIHN1YnNldChpYm1fZmluYWwsIHNwbGl0ID09IFRSVUUpCmRhZG9zX3Rlc3RlICA8LSBzdWJzZXQoaWJtX2ZpbmFsLCBzcGxpdCA9PSBGQUxTRSkKCiMgQ3JpYXIgVGFiZWxhIGRlIFJlc3VtbyAKcmVzdW1vX3NwbGl0IDwtIGRhdGEuZnJhbWUoCiAgQ29uanVudG8gPSBjKCJUcmVpbm8gKDcwJSkiLCAiVGVzdGUgKDMwJSkiLCAiVG90YWwiKSwKICBPYnNlcnZhw6fDtWVzID0gYyhucm93KGRhZG9zX3RyZWlubyksIG5yb3coZGFkb3NfdGVzdGUpLCBucm93KGlibV9maW5hbCkpLAogIFRheGFfQ2h1cm4gPSBjKAogICAgcGFzdGUwKHJvdW5kKG1lYW4oZGFkb3NfdHJlaW5vJGF0dHJpdGlvbikgKiAxMDAsIDEpLCAiJSIpLAogICAgcGFzdGUwKHJvdW5kKG1lYW4oZGFkb3NfdGVzdGUkYXR0cml0aW9uKSAqIDEwMCwgMSksICIlIiksCiAgICBwYXN0ZTAocm91bmQobWVhbihpYm1fZmluYWwkYXR0cml0aW9uKSAqIDEwMCwgMSksICIlIikKICApCikKCiMgRXhpYmlyIFRhYmVsYSAKcmVzdW1vX3NwbGl0ICU+JQogIGthYmxlKGNhcHRpb24gPSAiRGl2aXPDo28gZGUgRGFkb3M6IFZlcmlmaWNhw6fDo28gZGUgQ29uc2lzdMOqbmNpYSBlIEVzdHJhdGlmaWNhw6fDo28iKSAlPiUKICBrYWJsZV9zdHlsaW5nKGJvb3RzdHJhcF9vcHRpb25zID0gYygic3RyaXBlZCIsICJob3ZlciIsICJjb25kZW5zZWQiKSwgCiAgICAgICAgICAgICAgICBmdWxsX3dpZHRoID0gRiwgCiAgICAgICAgICAgICAgICBwb3NpdGlvbiA9ICJjZW50ZXIiKSAlPiUKICByb3dfc3BlYygwLCBib2xkID0gVCwgY29sb3IgPSAid2hpdGUiLCBiYWNrZ3JvdW5kID0gIiMyYzNlNTAiKSAlPiUKICBjb2x1bW5fc3BlYygzLCBib2xkID0gVCwgY29sb3IgPSAiI0U3NEMzQyIpIApgYGAKQSBkaXZpc8OjbyBkbyBjb25qdW50byBkZSBkYWRvcyBmb2kgZWZldHVhZGEgYXRyYXbDqXMgZGUgdW1hICoqYW1vc3RyYWdlbSBlc3RyYXRpZmljYWRhKiosIGFzc2VndXJhbmRvIHF1ZSBhIHByb3BvcsOnw6NvIGRhIHZhcmnDoXZlbOKAkWFsdm8gKGBBdHRyaXRpb25gKSBmb3NzZSBtYW50aWRhIGVtIGFtYm9zIG9zIHN1YmNvbmp1bnRvcyAoVHJlaW5vICg3MCUpIGUgVGVzdGUgKDMwJSkpLgoKQ29uZm9ybWUgaWx1c3RyYWRvIG5hIHRhYmVsYSwgYSAqKnRheGEgZGUgY2h1cm4qKiBwZXJtYW5lY2Ugcmlnb3Jvc2FtZW50ZSBjb25zdGFudGUgZW0gKioxNiwxJSoqIGVtIGFtYm9zIG9zIGNvbmp1bnRvcy4gRXN0YSBjb25zaXN0w6puY2lhIGVzdGF0w61zdGljYSDDqSBlc3NlbmNpYWwgcGFyYSBldml0YXIgZGlzdG9yw6fDtWVzIG5hIGFtb3N0cmFnZW0sIGdhcmFudGluZG8gcXVlIGEgYW1vc3RyYSBkZSB0ZXN0ZSBmdW5jaW9uZSBjb21vIHVtYSByw6lwbGljYSByZXByZXNlbnRhdGl2YSBkbyBfZGF0YXNldF8gb3JpZ2luYWwuCgpEZXN0ZSBtb2RvLCBhcyBtw6l0cmljYXMgZGUgZGVzZW1wZW5obyBvYnRpZGFzIGR1cmFudGUgYSBmYXNlIGRlIHZhbGlkYcOnw6NvIHJlZmxldGVtIGRlIGZvcm1hIHJlYWxpc3RhIGUgZmnDoXZlbCBvIGNvbXBvcnRhbWVudG8gZG8gZmVuw7NtZW5vIGRlIHJvdGF0aXZpZGFkZSBuYSBvcmdhbml6YcOnw6NvLCBhdW1lbnRhbmRvIGEgY3JlZGliaWxpZGFkZSBlIGdlbmVyYWxpemHDp8OjbyBkb3MgcmVzdWx0YWRvcyBkbyBtb2RlbG8uCgojIyBFcXVpbMOtYnJpbyBkZSBDbGFzc2VzCmBgYHtyfQpsaWJyYXJ5KFJPU0UpCmxpYnJhcnkoZ2dwbG90MikKbGlicmFyeShncmlkRXh0cmEpCgojIEFwbGljYXIgbyBST1NFIHBhcmEgZXF1aWxpYnJhciBhcGVuYXMgbyBjb25qdW50byBkZSBUUkVJTk8Kc2V0LnNlZWQoMTIzKQpkYWRvc190cmVpbm9fYmFsIDwtIFJPU0UoYXR0cml0aW9uIH4gLiwgZGF0YSA9IGRhZG9zX3RyZWlubywgc2VlZCA9IDEyMykkZGF0YQoKIyBDcmlhciBkYWRvcyBwYXJhIG8gZ3LDoWZpY28gY29tcGFyYXRpdm8KYW50ZXMgPC0gYXMuZGF0YS5mcmFtZSh0YWJsZShkYWRvc190cmVpbm8kYXR0cml0aW9uKSkKYW50ZXMkRXN0YWRvIDwtICIxLiBBbnRlcyAoRGVzZXF1aWxpYnJhZG8pIgoKZGVwb2lzIDwtIGFzLmRhdGEuZnJhbWUodGFibGUoZGFkb3NfdHJlaW5vX2JhbCRhdHRyaXRpb24pKQpkZXBvaXMkRXN0YWRvIDwtICIyLiBEZXBvaXMgKEVxdWlsaWJyYWRvIGNvbSBST1NFKSIKCmNvbXBhcmF0aXZvIDwtIHJiaW5kKGFudGVzLCBkZXBvaXMpCgojIEdyw6FmaWNvIApnZ3Bsb3QoY29tcGFyYXRpdm8sIGFlcyh4ID0gVmFyMSwgeSA9IEZyZXEsIGZpbGwgPSBWYXIxKSkgKwogIGdlb21fYmFyKHN0YXQgPSAiaWRlbnRpdHkiLCB3aWR0aCA9IDAuNiwgYWxwaGEgPSAwLjkpICsKICBmYWNldF93cmFwKH5Fc3RhZG8pICsKICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBjKCIwIiA9ICIjMkMzRTUwIiwgIjEiID0gIiNFNzRDM0MiKSkgKwogIHNjYWxlX3lfY29udGludW91cyhleHBhbmQgPSBjKDAsMCksIGxpbWl0cyA9IGMoMCwgbWF4KGNvbXBhcmF0aXZvJEZyZXEpKjEuMSkpICsKICBsYWJzKAogICAgdGl0bGUgPSAiRXN0cmF0w6lnaWEgZGUgUmViYWxhbmNlYW1lbnRvIGRlIERhZG9zIChST1NFKSIsCiAgICBzdWJ0aXRsZSA9ICJBanVzdGUgZGEgY2xhc3NlIG1pbm9yaXTDoXJpYSBwYXJhIG90aW1pemFyIGEgYXByZW5kaXphZ2VtIGRvIG1vZGVsbyIsCiAgICB4ID0gIlN0YXR1cyBkZSBTYcOtZGEgKDAgPSBOw6NvLCAxID0gU2ltKSIsCiAgICB5ID0gIk7Dum1lcm8gZGUgUmVnaXN0b3MiCiAgKSArCiAgdGhlbWVfbWluaW1hbCgpICsKICB0aGVtZSgKICAgIGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIiwKICAgIHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoZmFjZSA9ICJib2xkIiwgc2l6ZSA9IDE0LCBjb2xvciA9ICIjMmMzZTUwIiksCiAgICBzdHJpcC50ZXh0ID0gZWxlbWVudF90ZXh0KGZhY2UgPSAiYm9sZCIsIHNpemUgPSAxMSksCiAgICBwYW5lbC5ncmlkLm1ham9yLnggPSBlbGVtZW50X2JsYW5rKCkKICApCmBgYApBIGVmaWPDoWNpYSBkZSB1bSBtb2RlbG8gcHJlZGl0aXZvIGRlcGVuZGUgZGEgcXVhbGlkYWRlIGUgZG8gZXF1aWzDrWJyaW8gZXN0YXTDrXN0aWNvIGRvcyBkYWRvcyBkZSB0cmVpbm8uCgpDb25mb3JtZSBpZGVudGlmaWNhZG8gYW50ZXJpb3JtZW50ZSwgYSB2YXJpw6F2ZWzigJFhbHZvIChgQXR0cml0aW9uYCkgYXByZXNlbnRhIHVtICoqZGVzZXF1aWzDrWJyaW8gYWNlbnR1YWRvKiosIGNvbSBhcGVuYXMgKioxNiwxJSBkZSBjYXNvcyBwb3NpdGl2b3MqKiAoY29sYWJvcmFkb3JlcyBxdWUgc2HDrXJhbSBkYSBlbXByZXNhKS4KRW0gY29udGV4dG9zIHJlYWlzLCBlc3RlIHRpcG8gZGUgYXNzaW1ldHJpYSB0ZW5kZSBhIGxldmFyIG8gbW9kZWxvIGEgcHJpdmlsZWdpYXIgYSBwcmV2aXPDo28gZGUgcGVybWFuw6puY2lhIGUgYSBzdWJlc3RpbWFyIG9zIHBhZHLDtWVzIGRlIHNhw61kYS4KClBhcmEgbWl0aWdhciBlc3RlIHByb2JsZW1hLCBhcGxpY2914oCRc2UgbyAqKmFsZ29yaXRtbyBST1NFKiogKFJhbmRvbSBPdmVy4oCRU2FtcGxpbmcgRXhhbXBsZXMpIGV4Y2x1c2l2YW1lbnRlIGFvIGNvbmp1bnRvIGRlIHRyZWluby4KRXN0YSB0w6ljbmljYSBnZXJhICoqb2JzZXJ2YcOnw7VlcyBzaW50w6l0aWNhcyBiYXNlYWRhcyBuYSBkaXN0cmlidWnDp8OjbyBkYSBjbGFzc2UgbWlub3JpdMOhcmlhKiosIG1hbnRlbmRvIGEgY29lcsOqbmNpYSBlc3RhdMOtc3RpY2EgZG8gX2RhdGFzZXRfIG9yaWdpbmFsLgoKKipQcmluY2lwYWlzIGJlbmVmw61jaW9zIGRvIHJlZXF1aWzDrWJyaW8qKjoKCiogKipOaXZlbGFtZW50byBkYSBhcHJlbmRpemFnZW0qKiDigJMgTyBtb2RlbG8gcGFzc2EgYSBzZXIgZXhwb3N0byBhIHVtYSBwcm9wb3LDp8OjbyBlcXVpbGlicmFkYSAoYXByb3hpbWFkYW1lbnRlIDUwLzUwKSBlbnRyZSBjb2xhYm9yYWRvcmVzIHF1ZSBzYWVtIGUgcXVlIHBlcm1hbmVjZW0sIG8gcXVlIG1lbGhvcmEgYSBzdWEgY2FwYWNpZGFkZSBkZSBnZW5lcmFsaXphw6fDo28uCgoqICoqTWVsaG9yaWEgZGEgc2Vuc2liaWxpZGFkZSoqIChfcmVjYWxsXykg4oCTIEF1bWVudGHigJFzZSBhIGNhcGFjaWRhZGUgZG8gbW9kZWxvIGRlIGRldGV0YXIgY29ycmV0YW1lbnRlIG9zIGNhc29zIGRlIHNhw61kYSwgcGVybWl0aW5kbyB1bWEgaWRlbnRpZmljYcOnw6NvIHByZWNvY2UgZGUgcG90ZW5jaWFpcyBwZXJkYXMgZGUgdGFsZW50by4KCiogKipQcmVzZXJ2YcOnw6NvIGRhIGludGVncmlkYWRlIGRvIHRlc3RlKiog4oCTIE8gcmVlcXVpbMOtYnJpbyBmb2kgYXBsaWNhZG8gYXBlbmFzIGFvcyBkYWRvcyBkZSB0cmVpbm8sIG1hbnRlbmRvIG8gY29uanVudG8gZGUgdGVzdGUgaW5hbHRlcmFkby4KCiMgTWFjaGluZSBMZWFybmluZwojIyBNb2RlbG8gMTogUmVncmVzc8OjbyBMb2fDrXN0aWNhCmBgYHtyfQojIFRyZWluYXIgbyBNb2RlbG8KbW9kZWxvX2xvZ2lzdGljbyA8LSBnbG0oYXR0cml0aW9uIH4gLiwgZGF0YSA9IGRhZG9zX3RyZWlub19iYWwsIGZhbWlseSA9ICJiaW5vbWlhbCIpCgojIEZhemVyIFByZXZpc8O1ZXMKcHJldmlzb2VzX3Byb2IgPC0gcHJlZGljdChtb2RlbG9fbG9naXN0aWNvLCBuZXdkYXRhID0gZGFkb3NfdGVzdGUsIHR5cGUgPSAicmVzcG9uc2UiKQpwcmV2aXNvZXNfY2xhc3NlIDwtIGlmZWxzZShwcmV2aXNvZXNfcHJvYiA+IDAuNTAsIDEsIDApCgojIENyaWFyIE1hdHJpeiBkZSBDb25mdXPDo28gCnRhYmVsYV9jb25mdXNhbyA8LSB0YWJsZShSZWFsaWRhZGUgPSBkYWRvc190ZXN0ZSRhdHRyaXRpb24sIFByZXZpc2FvID0gcHJldmlzb2VzX2NsYXNzZSkKZGZfY29uZnVzYW8gPC0gYXMuZGF0YS5mcmFtZSh0YWJlbGFfY29uZnVzYW8pCgojIEdyw6FmaWNvIGRlIE1hdHJpeiBkZSBDb25mdXPDo28gKEhlYXRtYXApCmxpYnJhcnkoZ2dwbG90MikKZ2dwbG90KGRmX2NvbmZ1c2FvLCBhZXMoeCA9IFByZXZpc2FvLCB5ID0gUmVhbGlkYWRlLCBmaWxsID0gRnJlcSkpICsKICBnZW9tX3RpbGUoY29sb3IgPSAid2hpdGUiKSArCiAgZ2VvbV90ZXh0KGFlcyhsYWJlbCA9IEZyZXEpLCBjb2xvciA9ICJ3aGl0ZSIsIHNpemUgPSA4LCBmb250ZmFjZSA9ICJib2xkIikgKwogIHNjYWxlX2ZpbGxfZ3JhZGllbnQobG93ID0gIiMzNDQ5NUUiLCBoaWdoID0gIiNFNzRDM0MiKSArCiAgbGFicyh0aXRsZSA9ICJNYXRyaXogZGUgQ29uZnVzw6NvOiBSZWdyZXNzw6NvIExvZ8Otc3RpY2EiLAogICAgICAgc3VidGl0bGUgPSAiVmlzdWFsaXphw6fDo28gZGUgQWNlcnRvcyBlIEVycm9zIGRlIFByZXZpc8OjbyIsCiAgICAgICB4ID0gIlByZXZpc8OjbyBkbyBNb2RlbG8gKDA9RmljYSwgMT1TYWkpIiwKICAgICAgIHkgPSAiUmVhbGlkYWRlICgwPUZpY2EsIDE9U2FpKSIpICsKICB0aGVtZV9taW5pbWFsKCkgKwogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIiwKICAgICAgICBwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGZhY2UgPSAiYm9sZCIsIHNpemUgPSAxNiksCiAgICAgICAgYXhpcy50aXRsZSA9IGVsZW1lbnRfdGV4dChmYWNlID0gImJvbGQiKSkKCiMgVGFiZWxhIGRlIE3DqXRyaWNhcyAKYWN1cmFjaWEgPC0gc3VtKGRpYWcodGFiZWxhX2NvbmZ1c2FvKSkgLyBzdW0odGFiZWxhX2NvbmZ1c2FvKQpzZW5zaWJpbGlkYWRlIDwtIHRhYmVsYV9jb25mdXNhb1syLDJdIC8gc3VtKHRhYmVsYV9jb25mdXNhb1syLF0pCgptZXRyaWNhcyA8LSBkYXRhLmZyYW1lKAogIE3DqXRyaWNhID0gYygiQWN1csOhY2lhIFRvdGFsIiwgIlNlbnNpYmlsaWRhZGUgKFJlY2FsbCkiKSwKICBSZXN1bHRhZG8gPSBjKHBhc3RlMChyb3VuZChhY3VyYWNpYSAqIDEwMCwgMiksICIlIiksIAogICAgICAgICAgICAgICAgcGFzdGUwKHJvdW5kKHNlbnNpYmlsaWRhZGUgKiAxMDAsIDIpLCAiJSIpKQopCgpsaWJyYXJ5KGthYmxlRXh0cmEpCm1ldHJpY2FzICU+JQogIGthYmxlKGNhcHRpb24gPSAiUGVyZm9ybWFuY2UgZG8gTW9kZWxvIDEiKSAlPiUKICBrYWJsZV9zdHlsaW5nKGJvb3RzdHJhcF9vcHRpb25zID0gYygic3RyaXBlZCIsICJob3ZlciIpLCBmdWxsX3dpZHRoID0gRikgJT4lCiAgcm93X3NwZWMoMCwgYm9sZCA9IFQsIGNvbG9yID0gIndoaXRlIiwgYmFja2dyb3VuZCA9ICIjMmMzZTUwIikKYGBgCioqQW7DoWxpc2UgZGUgRGVzZW1wZW5obyBkbyBNb2RlbG8gMSAoUmVncmVzc8OjbyBMb2fDrXN0aWNhKToqKgoKTyBwcmltZWlybyBtb2RlbG8gZm9pIHRyZWluYWRvIGNvbSBvICoqY29uanVudG8gZGUgZGFkb3MgZXF1aWxpYnJhZG8qKiBvYnRpZG8gYXRyYXbDqXMgZGEgdMOpY25pY2EgUk9TRSwgYXByZXNlbnRhbmRvIHVtYSAqKmFjdXLDoWNpYSB0b3RhbCBkZSA3Miw3OSUqKi5FbWJvcmEgZXN0YSBtw6l0cmljYSBzZWphIHNhdGlzZmF0w7NyaWEsIGEgYWN1csOhY2lhIGlzb2xhZGEgbsOjbyDDqSBzdWZpY2llbnRlIHBhcmEgYXZhbGlhciBvIGRlc2VtcGVuaG8gbnVtIHByb2JsZW1hIGRlIHJldGVuw6fDo28gZGUgdGFsZW50b3MsIGVtIHF1ZSBvIGN1c3RvIGRlIHByZXZlciBpbmNvcnJldGFtZW50ZSB1bWEgc2HDrWRhIMOpIHBhcnRpY3VsYXJtZW50ZSBlbGV2YWRvLgoKQSBzZWd1aXIgYXByZXNlbnRhbeKAkXNlIG9zIHByaW5jaXBhaXMgcmVzdWx0YWRvcyBvYnRpZG9zIHNvYnJlIG8gKipjb25qdW50byBkZSB0ZXN0ZSAoNDQxIGNvbGFib3JhZG9yZXMpKio6CgoxLiAqKkNhcGFjaWRhZGUgZGUgZGV0ZcOnw6NvIChSZWNhbGwpOiA3MywyJSoqCgpObyBjb25qdW50byBkZSB0ZXN0ZSwgZXhpc3RpYW0gNzEgY29sYWJvcmFkb3JlcyBxdWUgZWZldGl2YW1lbnRlIHNhw61yYW0gZGEgZW1wcmVzYS4gTyBtb2RlbG8gaWRlbnRpZmljb3UgY29ycmV0YW1lbnRlIDUyIGRlc3NlcyA3MSBjYXNvcy4gTyBhbGdvcml0bW8gcmV2ZWxhIHVtYSBib2EgY2FwYWNpZGFkZSBkZSBkZXRlw6fDo28sIGNvbnNlZ3VpbmRvIHNpbmFsaXphciBhcHJveGltYWRhbWVudGUgMyBlbSBjYWRhIDQgZnVuY2lvbsOhcmlvcyBlbSByaXNjbyBkZSBzYcOtZGEuCkVzdGUgw6kgbyBwcmluY2lwYWwgcG9udG8gZm9ydGUgZG8gbW9kZWxvLCBwb2lzIGFzc2VndXJhIHF1ZSBhIG1haW9yaWEgZG9zIGNhc29zIGNyw610aWNvcyDDqSBhbnRlY2lwYWRhIGUgcG9kZSBzZXIgYWx2byBkZSBhw6fDtWVzIHByZXZlbnRpdmFzIHBvciBwYXJ0ZSBkb3MgUmVjdXJzb3MgSHVtYW5vcy4KCjIuICoqQ3VzdG8gZG9zIGZhbHNvcyBhbGFybWVzIChQcmVjaXPDo286IH4zNCUpKioKClBhcmEgbWF4aW1pemFyIGEgZGV0ZcOnw6NvIGRhcyBzYcOtZGFzLCBvIG1vZGVsbyB0b3Jub3XigJFzZSBtYWlzIHNlbnPDrXZlbCwgbyBxdWUgcmVzdWx0b3UgbnVtIGF1bWVudG8gZG9zIGZhbHNvcyBwb3NpdGl2b3MuIApGb3JhbSAxNTMgY29sYWJvcmFkb3JlcyBzaW5hbGl6YWRvcyBjb21vIHBvdGVuY2lhaXMgc2HDrWRhcywgbWFzIGFwZW5hcyA1MiByZWFsbWVudGUgZGVpeGFyYW0gYSBlbXByZXNhLgpPIG1vZGVsbyBnZXJhIHVtIHZvbHVtZSBjb25zaWRlcsOhdmVsIGRlIGFsZXJ0YXMgaW5kZXZpZG9zLCBlbSBxdWUgY2VyY2EgZGUgMiBlbSBjYWRhIDMgZnVuY2lvbsOhcmlvcyBzaW5hbGl6YWRvcyBwZXJtYW5lY2VyYW0gbmEgZW1wcmVzYS4KQXBlc2FyIGRlIGVmaWNheiBhIGFudGVjaXBhciBzYcOtZGFzIHJlYWlzLCBvIHNldSBmdW5jaW9uYW1lbnRvIMOpIOKAnGhpcGVy4oCRdmlnaWxhbnRl4oCdLCBwb2RlbmRvIGxldmFyIGEgaW50ZXJ2ZW7Dp8O1ZXMgZGVzbmVjZXNzw6FyaWFzIGUgYSB1bWEgc29icmVjYXJnYSBkYXMgZXF1aXBhcyBkZSBSSC4KCjMuICoqTWF0cml6IGRlIGNvbmZ1c8OjbyoqOgoKKiAqKlZlcmRhZGVpcm9zIE5lZ2F0aXZvcyAoMjY5KSoqOiBjb2xhYm9yYWRvcmVzIHF1ZSBwZXJtYW5lY2VyYW0gZSBmb3JhbSBjb3JyZXRhbWVudGUgY2xhc3NpZmljYWRvcy4KCiogKipGYWxzb3MgUG9zaXRpdm9zICgxMDEpKio6IGNvbGFib3JhZG9yZXMgcXVlIHBlcm1hbmVjZXJhbSwgbWFzIGZvcmFtIGNsYXNzaWZpY2Fkb3MgY29tbyByaXNjbyBkZSBzYcOtZGEgKHBvdGVuY2lhbCBkZXNwZXJkw61jaW8gZGUgcmVjdXJzb3MgZGUgZ2VzdMOjbykuCgoqICoqRmFsc29zIE5lZ2F0aXZvcyAoMTkpKio6IGNvbGFib3JhZG9yZXMgcXVlIHNhw61yYW0sIG1hcyBuw6NvIGZvcmFtIGFudGVjaXBhZG9zIChwZXJkYXMgaW1wcmV2aXN0YXMpLgoKKiAqKlZlcmRhZGVpcm9zIFBvc2l0aXZvcyAoNTIpKio6IGNvbGFib3JhZG9yZXMgcXVlIHNhw61yYW0gZSBmb3JhbSBjb3JyZXRhbWVudGUgaWRlbnRpZmljYWRvcyAob3BvcnR1bmlkYWRlcyBkZSByZXRlbsOnw6NvIGFudGVjaXBhZGEpLgoKKipQcsOzeGltbyBwYXNzbyoqOiBUZXN0YXIgdW0gbW9kZWxvIG1haXMgcm9idXN0bywgY29tbyBvIFJhbmRvbSBGb3Jlc3QsIGNvbSBvIG9iamV0aXZvIGRlIHJlZHV6aXIgb3MgZmFsc29zIHBvc2l0aXZvcyBzZW0gY29tcHJvbWV0ZXIgYSBib2Egc2Vuc2liaWxpZGFkZSBhbGNhbsOnYWRhIHBlbGEgcmVncmVzc8OjbyBsb2fDrXN0aWNhLgoKIyMgTW9kZWxvIDI6IFJhbmRvbSBGb3Jlc3QKYGBge3J9CmxpYnJhcnkocmFuZG9tRm9yZXN0KQpsaWJyYXJ5KGNhcmV0KQpsaWJyYXJ5KGdncGxvdDIpCmxpYnJhcnkoZHBseXIpCmxpYnJhcnkoa2FibGVFeHRyYSkKCiMgUHJlcGFyYcOnw6NvIGUgVHJlaW5vCmRhZG9zX3RyZWlub19iYWwkYXR0cml0aW9uIDwtIGFzLmZhY3RvcihkYWRvc190cmVpbm9fYmFsJGF0dHJpdGlvbikKZGFkb3NfdGVzdGUkYXR0cml0aW9uIDwtIGFzLmZhY3RvcihkYWRvc190ZXN0ZSRhdHRyaXRpb24pCgpzZXQuc2VlZCgxMjMpCm1vZGVsb19yZiA8LSByYW5kb21Gb3Jlc3QoYXR0cml0aW9uIH4gLiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgZGF0YSA9IGRhZG9zX3RyZWlub19iYWwsIAogICAgICAgICAgICAgICAgICAgICAgICAgIG50cmVlID0gNTAwLCAKICAgICAgICAgICAgICAgICAgICAgICAgICBpbXBvcnRhbmNlID0gVFJVRSkKCiMgUHJldmlzw7VlcyBlIE3DqXRyaWNhcwpwcmV2aXNvZXNfcmYgPC0gcHJlZGljdChtb2RlbG9fcmYsIG5ld2RhdGEgPSBkYWRvc190ZXN0ZSkKY29uZl9tYXRyaXhfcmYgPC0gY29uZnVzaW9uTWF0cml4KGRhdGEgPSBwcmV2aXNvZXNfcmYsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVmZXJlbmNlID0gZGFkb3NfdGVzdGUkYXR0cml0aW9uLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBvc2l0aXZlID0gIjEiKQoKIyBHcsOhZmljbyBkZSBJbXBvcnTDom5jaWEgZGFzIFZhcmnDoXZlaXMKaW1wX2RmIDwtIGFzLmRhdGEuZnJhbWUoaW1wb3J0YW5jZShtb2RlbG9fcmYpKQppbXBfZGYkVmFyaWF2ZWwgPC0gcm93bmFtZXMoaW1wX2RmKQoKZ2dwbG90KGltcF9kZiAlPiUgYXJyYW5nZShkZXNjKE1lYW5EZWNyZWFzZUFjY3VyYWN5KSkgJT4lIGhlYWQoMTUpLCAKICAgICAgIGFlcyh4ID0gcmVvcmRlcihWYXJpYXZlbCwgTWVhbkRlY3JlYXNlQWNjdXJhY3kpLCB5ID0gTWVhbkRlY3JlYXNlQWNjdXJhY3kpKSArCiAgZ2VvbV9iYXIoc3RhdCA9ICJpZGVudGl0eSIsIGZpbGwgPSAiIzJDM0U1MCIsIGFscGhhID0gMC45LCB3aWR0aCA9IDAuNykgKwogIGNvb3JkX2ZsaXAoKSArCiAgbGFicyh0aXRsZSA9ICJUb3AgMTUgUHJlZGl0b3JhcyBkZSBSb3RhdGl2aWRhZGUiLAogICAgICAgc3VidGl0bGUgPSAiUXVhaXMgb3MgZmF0b3JlcyBxdWUgbWFpcyBpbmZsdWVuY2lhbSBhIGRlY2lzw6NvIGRlIHNhw61kYT8iLAogICAgICAgeCA9IE5VTEwsIHkgPSAiSW1wb3J0w6JuY2lhIChNZWFuIERlY3JlYXNlIEFjY3VyYWN5KSIpICsKICB0aGVtZV9taW5pbWFsKCkgKwogIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoZmFjZSA9ICJib2xkIiwgc2l6ZSA9IDE2KSwKICAgICAgICBwYW5lbC5ncmlkLm1ham9yLnkgPSBlbGVtZW50X2JsYW5rKCkpCgojIFRhYmVsYSBkZSBQZXJmb3JtYW5jZSBDb21wYXJhdGl2YQptZXRyaWNhc19yZiA8LSBkYXRhLmZyYW1lKAogIE3DqXRyaWNhID0gYygiQWN1csOhY2lhIiwgIlNlbnNpYmlsaWRhZGUgKFJlY2FsbCkiLCAiRXNwZWNpZmljaWRhZGUiKSwKICBSZXN1bHRhZG8gPSBjKHBhc3RlMChyb3VuZChjb25mX21hdHJpeF9yZiRvdmVyYWxsWydBY2N1cmFjeSddICogMTAwLCAyKSwgIiUiKSwKICAgICAgICAgICAgICAgIHBhc3RlMChyb3VuZChjb25mX21hdHJpeF9yZiRieUNsYXNzWydTZW5zaXRpdml0eSddICogMTAwLCAyKSwgIiUiKSwKICAgICAgICAgICAgICAgIHBhc3RlMChyb3VuZChjb25mX21hdHJpeF9yZiRieUNsYXNzWydTcGVjaWZpY2l0eSddICogMTAwLCAyKSwgIiUiKSkKKQoKbWV0cmljYXNfcmYgJT4lCiAga2FibGUoY2FwdGlvbiA9ICJQZXJmb3JtYW5jZSBkbyBNb2RlbG8gUmFuZG9tIEZvcmVzdCIpICU+JQogIGthYmxlX3N0eWxpbmcoYm9vdHN0cmFwX29wdGlvbnMgPSBjKCJzdHJpcGVkIiwgImhvdmVyIiksIGZ1bGxfd2lkdGggPSBGKSAlPiUKICByb3dfc3BlYygwLCBib2xkID0gVCwgY29sb3IgPSAid2hpdGUiLCBiYWNrZ3JvdW5kID0gIiMyYzNlNTAiKQpgYGAKTyBtb2RlbG8gKipSYW5kb20gRm9yZXN0KiogYXByZXNlbnRvdSB1bSAqKmRlc2VtcGVuaG8gc3VwZXJpb3IgZSBtYWlzIGVxdWlsaWJyYWRvKiogZW0gY29tcGFyYcOnw6NvIGNvbSBhIFJlZ3Jlc3PDo28gTG9nw61zdGljYS4KQ29tIHVtYSAqKmFjdXLDoWNpYSBnbG9iYWwgZGUgNzQsMTUlKiosIGVzdGUgYWxnb3JpdG1vIGRlbW9uc3Ryb3Ugc2VyIHVtYSBmZXJyYW1lbnRhIHJvYnVzdGEgZSBmacOhdmVsIHBhcmEgYXBvaWFyIGRlY2lzw7VlcyBlc3RyYXTDqWdpY2FzIGRlIHJldGVuw6fDo28gZGUgdGFsZW50by4KCjEuICoqRXF1aWzDrWJyaW8gZW50cmUgZGV0ZcOnw6NvIGUgcHJlY2lzw6NvKioKRGlmZXJlbnRlbWVudGUgZG8gbW9kZWxvIGFudGVyaW9yLCBhIFJhbmRvbSBGb3Jlc3QgcmV2ZWxvdeKAkXNlIG1haXMgcHJlY2lzYSBuYSBkaXN0aW7Dp8OjbyBlbnRyZSBwZXJmaXMgZGUgcmlzY28gZSBkZSBlc3RhYmlsaWRhZGUuCgoqICoqU2Vuc2liaWxpZGFkZSAoX1JlY2FsbF8pIGRlIDcwLDQlKio6IElkZW50aWZpY291IGNvcnJldGFtZW50ZSA1MCBkb3MgNzEgY29sYWJvcmFkb3JlcyBxdWUgZWZldGl2YW1lbnRlIHNhw61yYW0gZGEgZW1wcmVzYS4KCiogKipSZWR1w6fDo28gZG9zIGZhbHNvcyBwb3NpdGl2b3MqKjogRW1ib3JhIGFpbmRhIGV4aXN0YW0gYWxlcnRhcyBpbmRldmlkb3MsIG8gbW9kZWxvIGZvaSBtYWlzIGNyaXRlcmlvc28gbmEgc2luYWxpemHDp8OjbyBkZSByaXNjbywgZGltaW51aW5kbyBvIHJ1w61kbyBvcGVyYWNpb25hbCBwYXJhIGFzIGVxdWlwYXMgZGUgUmVjdXJzb3MgSHVtYW5vcy4KCkVzdGUgZXF1aWzDrWJyaW8gdHJhZHV64oCRc2UgbnVtYSBmZXJyYW1lbnRhIG1haXMg4oCcY2lyw7pyZ2ljYeKAnSwgY2FwYXogZGUgYWxjYW7Dp2FyIGVsZXZhZGEgY2FwYWNpZGFkZSBkZSBkZXRlw6fDo28gc2VtIHNhY3JpZmljYXIgZGUgZm9ybWEgc2lnbmlmaWNhdGl2YSBhIHByZWNpc8OjbyBkYXMgcHJldmlzw7Vlcy4KCgoyLiAqKlByaW5jaXBhaXMgcHJlZGl0b3JlcyBkZSByb3RhdGl2aWRhZGUqKgpBIGFuw6FsaXNlIGRlIGltcG9ydMOibmNpYSBkYXMgdmFyacOhdmVpcyByZXZlbGEgb3MgZmF0b3JlcyBxdWUgbWFpcyBpbmZsdWVuY2lhbSBhIGRlY2lzw6NvIGRlIHNhw61kYSwgb2ZlcmVjZW5kbyBfaW5zaWdodHNfIGRlIGdlc3TDo28gZXh0cmVtYW1lbnRlIHJlbGV2YW50ZXM6CgoqICoqYE92ZXJUaW1lYCAoSG9yYXMgRXh0cmEpKio6IHN1cmdlIGNvbW8gbyBwcmVkaXRvciBtYWlzIGZvcnRlLCBpbmRpY2FuZG8gcXVlIGNvbGFib3JhZG9yZXMgZXhwb3N0b3MgYSBsb25nYXMgam9ybmFkYXMgYXByZXNlbnRhbSBwcm9wZW5zw6NvIHNpZ25pZmljYXRpdmFtZW50ZSBzdXBlcmlvciDDoCBzYcOtZGEuCgoqICoqYE1vbnRobHlJbmNvbWVgIChTYWzDoXJpbykqKjogY29uZmlybWEgcXVlIGFzIGZhaXhhcyBzYWxhcmlhaXMgbWFpcyBiYWl4YXMgY29uc3RpdHVlbSBhIHpvbmEgZGUgbWFpb3IgdnVsbmVyYWJpbGlkYWRlIGVtIHRlcm1vcyBkZSByb3RhdGl2aWRhZGUuCgoqICoqYFN0b2NrT3B0aW9uTGV2ZWxgKio6IGEgYXVzw6puY2lhIGRlIGluY2VudGl2b3MgZGUgbG9uZ28gcHJhem8gKGNvbW8gcGxhbm9zIGRlIGHDp8O1ZXMpIGVzdMOhIGFzc29jaWFkYSBhIG1lbm9yIGNvbXByb21pc3NvIG9yZ2FuaXphY2lvbmFsLgoKKiAqKmBBZ2VgIGUgYFRvdGFsV29ya2luZ1llYXJzYCoqOiB0cmFiYWxoYWRvcmVzIG1haXMgam92ZW5zIGUgY29tIG1lbm9zIGFub3MgZGUgZXhwZXJpw6puY2lhIG1vc3RyYW3igJFzZSBtYWlzIHByb3BlbnNvcyDDoCBtb2JpbGlkYWRlIGV4dGVybmEuCgpFc3RlcyByZXN1bHRhZG9zIGNvcnJvYm9yYW0gYSBsaXRlcmF0dXJhIGRlIFJlY3Vyc29zIEh1bWFub3MsIGRlc3RhY2FuZG8gbyBwYXBlbCBjb25qdW50byBkZSBmYXRvcmVzIGZpbmFuY2Vpcm9zLCBkZSBjYXJnYSBsYWJvcmFsIGUgZGUgZXhwZXJpw6puY2lhIGNvbW8gZGV0ZXJtaW5hbnRlcyBkYSByb3RhdGl2aWRhZGUuCgozLiAqKkNvbmNsdXPDo28gdMOpY25pY2EgZSBpbnRlcnByZXRhdGl2YSoqCkEgUmFuZG9tIEZvcmVzdCBtb3N0cm914oCRc2UgY2FwYXogZGUgY2FwdGFyIHBhZHLDtWVzIG7Do28gbGluZWFyZXMgZSBpbnRlcmHDp8O1ZXMgY29tcGxleGFzIHF1ZSBtb2RlbG9zIGxpbmVhcmVzIG7Do28gY29uc2VndWVtIHJlcHJlc2VudGFyLgpPIGFsZ29yaXRtbyBpZGVudGlmaWNvdSwgcG9yIGV4ZW1wbG8sIHF1ZSB1bSBzYWzDoXJpbyBtw6lkaW8gcG9kZSBzZXIgYWNlaXTDoXZlbCBpc29sYWRhbWVudGUsIG1hcyB0b3JuYeKAkXNlIGZhdG9yIGRlIHJpc2NvIHF1YW5kbyBjb21iaW5hZG8gY29tIGV4Y2Vzc28gZGUgaG9yYXMgZXh0cmEgb3UgYmFpeGEgc2F0aXNmYcOnw6NvIG5hIHJlbGHDp8OjbyBjb20gbyBnZXN0b3IuCkVtIHN1bWEsIGVzdGUgbW9kZWxvIG7Do28gYXBlbmFzIG1lbGhvcmEgbyBkZXNlbXBlbmhvIHByZWRpdGl2bywgbWFzIHRhbWLDqW0gZm9ybmVjZSBpbmZvcm1hw6fDo28gYWNpb27DoXZlbCBwYXJhIHBvbMOtdGljYXMgZGUgcmV0ZW7Dp8OjbyBwZXJzb25hbGl6YWRhcyBlIGdlc3TDo28gcHJldmVudGl2YSBkbyB0YWxlbnRvLgoKCiMjIEFuw6FsaXNlIGRlIERyaXZlcnMgZGUgU2HDrWRhIChGZWF0dXJlIEltcG9ydGFuY2UpCmBgYHtyfQojIEV4dHJhaXIgYSBpbXBvcnTDom5jaWEgZGFzIHZhcmnDoXZlaXMgZG8gbW9kZWxvIFJhbmRvbSBGb3Jlc3QKaW1wb3J0YW5jaWEgPC0gYXMuZGF0YS5mcmFtZShpbXBvcnRhbmNlKG1vZGVsb19yZikpCmltcG9ydGFuY2lhJFZhcmlhdmVsIDwtIHJvd25hbWVzKGltcG9ydGFuY2lhKQoKIyBDcmlhciBvIGdyw6FmaWNvCmxpYnJhcnkoZ2dwbG90MikKbGlicmFyeShkcGx5cikKCmdncGxvdChpbXBvcnRhbmNpYSAlPiUgYXJyYW5nZShkZXNjKE1lYW5EZWNyZWFzZUFjY3VyYWN5KSkgJT4lIGhlYWQoMTUpLCAKICAgICAgIGFlcyh4ID0gcmVvcmRlcihWYXJpYXZlbCwgTWVhbkRlY3JlYXNlQWNjdXJhY3kpLCB5ID0gTWVhbkRlY3JlYXNlQWNjdXJhY3kpKSArCiAgZ2VvbV9iYXIoc3RhdCA9ICJpZGVudGl0eSIsIGZpbGwgPSAiIzJDM0U1MCIsIGFscGhhID0gMC45LCB3aWR0aCA9IDAuNykgKwogIGdlb21fdGV4dChhZXMobGFiZWwgPSByb3VuZChNZWFuRGVjcmVhc2VBY2N1cmFjeSwgMSkpLCAKICAgICAgICAgICAgaGp1c3QgPSAtMC4yLCBzaXplID0gMywgZm9udGZhY2UgPSAiYm9sZCIsIGNvbG9yID0gIiMyQzNFNTAiKSArCiAgY29vcmRfZmxpcCgpICsKICBzY2FsZV95X2NvbnRpbnVvdXMoZXhwYW5kID0gZXhwYW5zaW9uKG11bHQgPSBjKDAsIDAuMSkpKSArCiAgbGFicygKICAgIHRpdGxlID0gIkRyaXZlcnMgQ3LDrXRpY29zIGRlIEF0dHJpdGlvbiIsCiAgICBzdWJ0aXRsZSA9ICJWYXJpw6F2ZWlzIHF1ZSBtYWlzIGltcGFjdGFtIGEgcHJlY2lzw6NvIGRvIG1vZGVsbyBSYW5kb20gRm9yZXN0IiwKICAgIHggPSBOVUxMLAogICAgeSA9ICJJbXBvcnTDom5jaWEgKE1lYW4gRGVjcmVhc2UgQWNjdXJhY3kpIgogICkgKwogIHRoZW1lX21pbmltYWwoKSArCiAgdGhlbWUoCiAgICBwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGZhY2UgPSAiYm9sZCIsIHNpemUgPSAxNiwgY29sb3IgPSAiIzJjM2U1MCIpLAogICAgcGxvdC5zdWJ0aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTEsIGNvbG9yID0gImdyZXk0MCIpLAogICAgcGFuZWwuZ3JpZC5tYWpvci55ID0gZWxlbWVudF9ibGFuaygpLAogICAgYXhpcy50ZXh0LnkgPSBlbGVtZW50X3RleHQoZmFjZSA9ICJib2xkIiwgc2l6ZSA9IDEwKQogICkKYGBgCk8gZ3LDoWZpY28gYWNpbWEgYXByZXNlbnRhIGFzIHZhcmnDoXZlaXMgbWFpcyBkZXRlcm1pbmFudGVzIGlkZW50aWZpY2FkYXMgcGVsbyBtb2RlbG8gUmFuZG9tIEZvcmVzdCwgb3JkZW5hZGFzIHBlbGEgbcOpdHJpY2Eg4oCcTWVhbiBEZWNyZWFzZSBBY2N1cmFjeeKAnS4KRW0gdGVybW9zIHByw6F0aWNvcywgcXVhbnRvIG1haW9yIGEgaW1wb3J0w6JuY2lhIGRlc3RhIG3DqXRyaWNhLCBtYWlvciDDqSBvIGNvbnRyaWJ1dG8gZGEgdmFyacOhdmVsIHBhcmEgYSBjYXBhY2lkYWRlIHByZWRpdGl2YSBnbG9iYWwgZG8gbW9kZWxvLCBvdSBzZWphLCBhIHN1YSByZW1vw6fDo28gcmVzdWx0YXJpYSBudW1hIGRpbWludWnDp8OjbyBzaWduaWZpY2F0aXZhIGRhIHByZWNpc8Ojby4KCjEuICoqTyBjYXJnbyBjb21vIHByaW5jaXBhbCBkZXRlcm1pbmFudGUgKGBKb2JSb2xlYCkqKgpRdWF0cm8gZGFzIGNpbmNvIHZhcmnDoXZlaXMgbWFpcyByZWxldmFudGVzIGVzdMOjbyByZWxhY2lvbmFkYXMgY29tIGZ1bsOnw7VlcyBlc3BlY8OtZmljYXMgZGVudHJvIGRhIG9yZ2FuaXphw6fDo28uCkRlc3RhY2Ft4oCRc2UgZG9pcyBleHRyZW1vczogYFJlc2VhcmNoIERpcmVjdG9yYCAoZnVuw6fDo28gY29tIGVsZXZhZGEgZXN0YWJpbGlkYWRlKSBlIFNhbGVzYCBSZXByZXNlbnRhdGl2ZWAgKGZ1bsOnw6NvIG1haXMgdm9sw6F0aWwpLgoKRXN0YSBkaWZlcmVuw6dhIGNvbmZpcm1hIGFzIGNvbmNsdXPDtWVzIG9idGlkYXMgbmEgYW7DoWxpc2UgZXhwbG9yYXTDs3JpYTogbyBuw612ZWwgaGllcsOhcnF1aWNvIGUgbyB0aXBvIGRlIGZ1bsOnw6NvIHPDo28gb3MgZmF0b3JlcyBxdWUgbWFpcyBkaWZlcmVuY2lhbSBvIGNvbXBvcnRhbWVudG8gZGUgcm90YXRpdmlkYWRlIG5hIGVtcHJlc2EuCgoqKkltcGxpY2HDp8OjbyoqOiBQb2zDrXRpY2FzIGdlbsOpcmljYXMgZGUgZ2VzdMOjbyBkZSBwZXNzb2FzICjigJxvbmXigJFzaXpl4oCRZml0c+KAkWFsbOKAnSkgc8OjbyBpbmVmaWNhemVzLgoKQSBlc3RyYXTDqWdpYSBkZSByZXRlbsOnw6NvIGRldmUgc2VyIHBlcnNvbmFsaXphZGEgcG9yIMOhcmVhIGZ1bmNpb25hbCwgcmVjb25oZWNlbmRvIHF1ZSB2ZW5kYXMgZSBpbnZlc3RpZ2HDp8Ojby9yZWRlIGRlIGxpZGVyYW7Dp2EgZXhpZ2VtIGFib3JkYWdlbnMgZGUgbW90aXZhw6fDo28gZSByZWNvbmhlY2ltZW50byBkaXN0aW50YXMuCgoyLiAqKk8gcGVzbyBkYXMgaG9yYXMgZXh0cmEgKGBPdmVyVGltZWApKioKQSB2YXJpw6F2ZWwgYG92ZXJfdGltZV95ZXNgIHN1cmdlIGNvbW8gbyB0ZXJjZWlybyBwcmVkaXRvciBtYWlzIGNyw610aWNvIGRlIHRvZG8gbyBjb25qdW50by4KRXN0ZSByZXN1bHRhZG8gcmVmb3LDp2EgYSBldmlkw6puY2lhIGRlIHF1ZSBhIHNvYnJlY2FyZ2EgZGUgdHJhYmFsaG8gZSBhIGZhbHRhIGRlIGVxdWlsw61icmlvIHZpZGHigJFwcm9maXNzaW9uYWwgY29uc3RpdHVlbSBnYXRpbGhvcyBkaXJldG9zIGRlIHNhw61kYS4KVHJhdGFy4oCRc2XigJHDoSBtZW5vcyBkZSB1bWEgcXVlc3TDo28gZGUgcmVtdW5lcmHDp8OjbyBlIG1haXMgZGUgYmVt4oCRZXN0YXIgb3JnYW5pemFjaW9uYWwgZSBwcmV2ZW7Dp8OjbyBkZSBfYnVybm91dC5fCgozLiAqKkVzdGFnbmHDp8OjbyBlIGluY2VudGl2b3MgZGUgbG9uZ28gcHJhem8qKgoKKiAqKkVzdGFnbmHDp8OjbyoqOiBBIHZhcmnDoXZlbCBgeWVhcnNfaW5fY3VycmVudF9yb2xlYCAoYW5vcyBuYSBmdW7Dp8OjbyBhdHVhbCkgZGVzdGFjYeKAkXNlIG5hIDYuwqogcG9zacOnw6NvLiBBIHBlcm1hbsOqbmNpYSBwcm9sb25nYWRhIG5hIG1lc21hIGZ1bsOnw6NvLCBzZW0gcHJvZ3Jlc3PDo28gdmlzw612ZWwsIGF1bWVudGEgc3Vic3RhbmNpYWxtZW50ZSBvIHJpc2NvIGRlIHNhw61kYSB2b2x1bnTDoXJpYS4KCiogKipJbmNlbnRpdm9zKio6IE8gYHN0b2NrX29wdGlvbl9sZXZlbGAgc3VyZ2UgbG9nbyBkZSBzZWd1aWRhLCBldmlkZW5jaWFuZG8gcXVlIG9zIGluY2VudGl2b3MgZGUgbG9uZ28gcHJhem8gdMOqbSB1bSBlZmVpdG8gZGUgcmV0ZW7Dp8OjbyBtYWlzIGZvcnRlIGRvIHF1ZSBvIHNhbMOhcmlvIG1lbnNhbCAoYG1vbnRobHlfaW5jb21lYCksIHF1ZSBhcGFyZWNlIGFwZW5hcyBuYSAxNS7CqiBwb3Npw6fDo28uCgpFc3RlcyByZXN1bHRhZG9zIHN1Z2VyZW0gcXVlIGEgcHJvZ3Jlc3PDo28gZGUgY2FycmVpcmEgZSBhIHZhbG9yaXphw6fDo28gZGUgY2FwaXRhbCBzaW1iw7NsaWNvIChhw6fDtWVzLCByZWNvbmhlY2ltZW50bywgdmlzaWJpbGlkYWRlKSBzw6NvIG1lY2FuaXNtb3MgZGUgcmV0ZW7Dp8OjbyBtYWlzIGVmaWNhemVzIGRvIHF1ZSBhdW1lbnRvcyBzYWxhcmlhaXMgaXNvbGFkb3MuCgo0LiAqKlBlcmZpbCBkZW1vZ3LDoWZpY28gZGUgcmlzY28qKgpBIHByZXNlbsOnYSBkYXMgdmFyacOhdmVpcyBgbWFyaXRhbF9zdGF0dXNfc2luZ2xlYCBlIGFnZSBlbnRyZSBhcyAxNSBtYWlzIHJlbGV2YW50ZXMgY29uZmlybWEgbyBwYWRyw6NvIGlkZW50aWZpY2FkbyBuYXMgYW7DoWxpc2VzIGFudGVyaW9yZXM6IGNvbGFib3JhZG9yZXMgbWFpcyBqb3ZlbnMgZSBzb2x0ZWlyb3MgdGVuZGVtIGEgYXByZXNlbnRhciBtYWlvciBtb2JpbGlkYWRlIGUgcHJlZGlzcG9zacOnw6NvIHBhcmEgbXVkYW7Dp2EsIHNvYnJldHVkbyBlbSBjb250ZXh0b3MgZGUgcG91Y2FzIHBlcnNwZXRpdmFzIGRlIGNyZXNjaW1lbnRvLgoKUGFyYSBtaXRpZ2FyIG9zICoqcmlzY29zIGRlIF9hdHRyaXRpb25fKiosIHJlY29tZW5kYeKAkXNlIHF1ZSBhcyBhw6fDtWVzIHByaW9yaXTDoXJpYXMgZGEgZW1wcmVzYSBpbmNpZGFtIHNvYnJlIHRyw6pzIGVpeG9zIHByaW5jaXBhaXM6CgoxLiBSZXZlciBhcyBjb25kacOnw7VlcyBlIGluY2VudGl2b3MgZGFzIGVxdWlwYXMgZGUgVmVuZGFzLCBvbmRlIGEgdGF4YSBkZSBzYcOtZGEgw6kgbWFpcyBlbGV2YWRhOwoKMi4gTW9uaXRvcml6YXIgZSByZWd1bGFyIG8gdm9sdW1lIGRlIGhvcmFzIGV4dHJhLCBwcm9tb3ZlbmRvIHByw6F0aWNhcyBkZSBlcXVpbMOtYnJpbyBlIGJlbeKAkWVzdGFyOwoKMy4gSW1wbGVtZW50YXIgcGxhbm9zIGRlIHJvdGHDp8OjbyBlIGRlc2Vudm9sdmltZW50byBkZSBjYXJyZWlyYSwgZXNwZWNpYWxtZW50ZSBwYXJhIGNvbGFib3JhZG9yZXMgZXN0YWduYWRvcyBuYSBtZXNtYSBmdW7Dp8OjbyBow6EgdsOhcmlvcyBhbm9zLgoKRXN0YXMgYcOnw7VlcyBlc3RyYXTDqWdpY2FzIGFsaW5oYW3igJFzZSBkaXJldGFtZW50ZSBjb20gb3MgcmVzdWx0YWRvcyBkbyBtb2RlbG8gZSBwb2RlbSByZWR1emlyIHN1YnN0YW5jaWFsbWVudGUgbyByaXNjbyBkZSByb3RhdGl2aWRhZGUgbsOjbyBkZXNlamFkYSwgZm9ydGFsZWNlbmRvIGEgcmV0ZW7Dp8OjbyBkZSB0YWxlbnRvIGNyw610aWNvLgoKIyBDb25jbHVzw6NvIGUgUmVjb21lbmRhw6fDtWVzIGRlIE5lZ8OzY2lvCgpFc3RlIHByb2pldG8gdGV2ZSBjb21vIG9iamV0aXZvIGlkZW50aWZpY2FyIGFzIGNhdXNhcyBkYSByb3RhdGl2aWRhZGUgZGUgZnVuY2lvbsOhcmlvcyAoQXR0cml0aW9uKSBlIGNyaWFyIHVtIG1vZGVsbyBwcmVkaXRpdm8gcGFyYSBtaXRpZ2FyIG8gcmlzY28uCgojIyBDb21wYXJhw6fDo28gZGUgTW9kZWxvcwpGb3JhbSB0ZXN0YWRhcyBkdWFzIGFib3JkYWdlbnMgZGlzdGludGFzOiBSZWdyZXNzw6NvIExvZ8Otc3RpY2EgZSBSYW5kb20gRm9yZXN0LgoKTyAqKlJhbmRvbSBGb3Jlc3QqKiBkZW1vbnN0cm91ICoqZGVzZW1wZW5obyBzdXBlcmlvciBlIG1haW9yIGVzdGFiaWxpZGFkZSoqLCBhbGNhbsOnYW5kbyB1bWEgKiphY3Vyw6FjaWEgZ2xvYmFsIGRlIDc0LDE1JSoqLgoKTyBtb2RlbG8gw6kgY2FwYXogZGUgKippZGVudGlmaWNhciBjb3JyZXRhbWVudGUgNzAsNCUgZG9zIGNvbGFib3JhZG9yZXMgcXVlIGVmZXRpdmFtZW50ZSBzYWVtIGRhIGVtcHJlc2EqKiAoc2Vuc2liaWxpZGFkZSksIG1hbnRlbmRvLCBlbSBzaW11bHTDom5lbywgdW1hICoqdGF4YSBkZSBmYWxzb3MgYWxhcm1lcyBjb250cm9sYWRhKiogKGVzcGVjaWZpY2lkYWRlIGRlIDc0LDklKS4KCkVzdGFzIG3DqXRyaWNhcyBldmlkZW5jaWFtIHVtICoqZXF1aWzDrWJyaW8gYWRlcXVhZG8gZW50cmUgZGV0ZcOnw6NvIGUgcHJlY2lzw6NvKiosIHRvcm5hbmRvIG8gYWxnb3JpdG1vIHVtYSBmZXJyYW1lbnRhIGVmaWNheiBwYXJhIHVzbyBwcsOhdGljbyBlbSBjb250ZXh0b3MgZGUgUmVjdXJzb3MgSHVtYW5vcy4KCiMjIEZhdG9yZXMgQ3LDrXRpY29zIGRlIFNhw61kYSAoX0luc2lnaHRzXyBkbyBNb2RlbG8pCkEgYW7DoWxpc2UgZGUgaW1wb3J0w6JuY2lhIGRhcyB2YXJpw6F2ZWlzIChGZWF0dXJlIEltcG9ydGFuY2UpIGV2aWRlbmNpb3UgdHLDqnMgcGlsYXJlcyBjZW50cmFpcyBkZSBhw6fDo286CgoxLiAqKk8gUmlzY28gQXNzb2NpYWRvIMOgIEZ1bsOnw6NvIGRlIFZlbmRhcyoqCgpBIGZ1bsOnw6NvIGBTYWxlcyBSZXByZXNlbnRhdGl2ZWAgc3VyZ2UgY29tbyBvICoqbWFpb3IgcHJlZGl0b3IgZGUgc2HDrWRhKiouIEEgdGF4YSBkZSByb3RhdGl2aWRhZGUgbmVzdGUgY2FyZ28gw6kgc3Vic3RhbmNpYWxtZW50ZSBzdXBlcmlvciDDoCBvYnNlcnZhZGEgZW0gZnVuw6fDtWVzIGVzdMOhdmVpcyBjb21vIGBSZXNlYXJjaCBEaXJlY3RvcmAgb3UgYE1hbmFnZXIuYAoKKipEaWFnbsOzc3RpY28gcHJvdsOhdmVsKio6IERlc2FqdXN0ZSBubyBlc3F1ZW1hIGRlIGNvbWlzc8O1ZXMsIHByZXNzw6NvIGVsZXZhZGEgcG9yIHJlc3VsdGFkb3Mgb3UgZmFsdGEgZGUgcGVyc3BldGl2YXMgZGUgcHJvZ3Jlc3PDo28uCgoyLiAqKkN1bHR1cmEgZGUgSG9yYXMgRXh0cmEgZSBFeGF1c3TDo28gT2N1cGFjaW9uYWwqKgoKQSB2YXJpw6F2ZWwgYE92ZXJUaW1lYCBtYW50w6lt4oCRc2UgZW50cmUgb3MgKip0csOqcyBmYXRvcmVzIG1haXMgY3LDrXRpY29zKiosIGNvbmZpcm1hbmRvIHF1ZSBhICoqc29icmVjYXJnYSBkZSB0cmFiYWxobyDDqSB1bSBkb3MgZ2F0aWxob3MgZGlyZXRvcyBkZSBzYcOtZGEqKi4gQ29sYWJvcmFkb3JlcyBxdWUgcmVhbGl6YW0gaG9yYXMgZXh0cmEgYXByZXNlbnRhbSBwcm9iYWJpbGlkYWRlIHNpZ25pZmljYXRpdmFtZW50ZSBzdXBlcmlvciBkZSBzYWlyIGRhIGVtcHJlc2EsIGluZGVwZW5kZW50ZW1lbnRlIGRvIG7DrXZlbCBzYWxhcmlhbC4KCioqSW50ZXJwcmV0YcOnw6NvKio6IGVzdGUgY29tcG9ydGFtZW50byBzdWdlcmUgc2luYWlzIGRlIF9idXJub3V0XyBlIGRlc2VxdWlsw61icmlvIHZpZGHigJF0cmFiYWxobywgw6FyZWFzIHF1ZSByZXF1ZXJlbSBtb25pdG9yaXphw6fDo28gYXRpdmEuCgozLiAqKlJldGVuw6fDo28gYXRyYXbDqXMgZGUgSW5jZW50aXZvcyBkZSBDYXBpdGFsKioKCk8gYFN0b2NrT3B0aW9uTGV2ZWxgIG1vc3RyYeKAkXNlICoqZGV0ZXJtaW5hbnRlIHBhcmEgYSByZXRlbsOnw6NvIGRlIGNvbGFib3JhZG9yZXMqKi4gRnVuY2lvbsOhcmlvcyBjb20gcGFydGljaXBhw6fDo28gYWNpb25pc3RhIG91IGluY2VudGl2b3MgZGUgbG9uZ28gcHJhem8gdGVuZGVtIGEgcmV0ZXLigJFzZSBwb3IgbWFpcyB0ZW1wbywgcmVmb3LDp2FuZG8gbyBzZW50aW1lbnRvIGRlIHBlcnRlbsOnYSBlIGNvbXByb21pc3NvIG9yZ2FuaXphY2lvbmFsLiBJbnZlcnNhbWVudGUsIGEgYXVzw6puY2lhIGRlc3RlIGZhdG9yIGVzdMOhIGZvcnRlbWVudGUgYXNzb2NpYWRhIGEgbWFpb3IgcHJvcGVuc8OjbyDDoCBzYcOtZGEuCgojIyBQbGFubyBkZSBBw6fDo28gUmVjb21lbmRhZG8gKFByw7N4aW1vcyBQYXNzb3MpCgpDb20gYmFzZSBuYXMgZXZpZMOqbmNpYXMgYW5hbMOtdGljYXMsIHJlY29tZW5kYeKAkXNlIGEgaW1wbGVtZW50YcOnw6NvIGRhcyBzZWd1aW50ZXMgbWVkaWRhczoKCjEuICoqSW50ZXJ2ZW7Dp8OjbyBkaXJlY2lvbmFkYSBuYXMgZXF1aXBhcyBkZSBWZW5kYXMqKjogUmVhbGl6YXIgZW50cmV2aXN0YXMgZGUgc2HDrWRhIGVzcGVjw61maWNhcyBwYXJhIFJlcHJlc2VudGFudGVzIGRlIFZlbmRhcywgY29tIGZvY28gbmEgcmV2aXPDo28gZGUgcG9sw610aWNhcyBkZSBjb21pc3PDo28sIG9iamV0aXZvcyBlIHBsYW5vIGRlIGNhcnJlaXJhLgoKMi4gKipBdWRpdG9yaWEgZGUgQ2FyZ2EgSG9yw6FyaWEgZSBCZW3igJFFc3RhcioqOiBFc3RhYmVsZWNlciBtZWNhbmlzbW9zIGRlIGNvbnRyb2xvIGRhcyBob3JhcyBleHRyYSwgZ2FyYW50aW5kbyBhIHN1YSBjb21wZW5zYcOnw6NvIGFkZXF1YWRhICh2aWEgZm9sZ2FzIG91IGJlbmVmw61jaW9zKS4gU2ltdWx0YW5lYW1lbnRlLCBwcm9tb3ZlciBwcm9ncmFtYXMgZGUgcHJldmVuw6fDo28gZGUgX2J1cm5vdXRfIGUgZGUgZXF1aWzDrWJyaW8gdmlkYeKAkXRyYWJhbGhvLgoKMy4gKipGZXJyYW1lbnRhIGRlIFByZXZpc8OjbyBDb250w61udWEgZGUgUm90YXRpdmlkYWRlKio6IEludGVncmFyIG8gbW9kZWxvIFJhbmRvbSBGb3Jlc3QgY29tbyB1bSBzaXN0ZW1hIG1lbnNhbCBkZSBtb25pdG9yaXphw6fDo28gcHJlZGl0aXZhLCB1bWEg4oCcbGlzdGEgZGUgcmlzY2/igJ0gZGluw6JtaWNhLCBkZXN0YWNhbmRvIGNvbGFib3JhZG9yZXMgY29tIHByb2JhYmlsaWRhZGUgZGUgc2HDrWRhIHN1cGVyaW9yIGEgNTAlLiBFc3RhIGluZm9ybWHDp8OjbyBkZXZlIHNlciB1dGlsaXphZGEgZGUgZm9ybWEgcHJvYXRpdmEsIHBlcm1pdGluZG8gw6AgZXF1aXBhIGRlIFJIIGFnaXIgYW50ZXMgZGEgZGVjaXPDo28gZGUgc2FpciBkYSBlbXByZXNhLg==