1. Introdução

Diversos testes estatísticos clássicos — teste t, ANOVA, regressão linear, entre outros — baseiam-se na suposição de que a variável de interesse (ou os resíduos do modelo) segue uma distribuição Normal. Essa suposição não pode ser assumida apenas pela inspeção visual dos dados: é necessário verificá-la formalmente antes de aplicar qualquer técnica paramétrica.

Os testes de normalidade são testes de hipóteses do tipo aderência (goodness-of-fit), cujo objetivo é avaliar se uma amostra é compatível com a hipótese de ter sido gerada por uma população normalmente distribuída. Neste relatório utilizamos os dois testes formais mais empregados na prática — Shapiro-Wilk e Kolmogorov-Smirnov — complementados por recursos gráficos (histograma, boxplot e QQ-Plot).

2. Objetivo da Análise

Verificar, com base em dados reais, se as variáveis Wind e Ozone do conjunto de dados airquality são compatíveis com a distribuição Normal, por meio de:

  1. Análise exploratória e inspeção gráfica (histograma, boxplot, QQ-Plot);
  2. Verificação dos pressupostos de aplicação dos testes;
  3. Aplicação dos testes de Shapiro-Wilk e Kolmogorov-Smirnov;
  4. Resolução manual de um exemplo com amostra reduzida (n = 5);
  5. Interpretação do p-valor e comparação com o método do valor crítico;
  6. Discussão crítica sobre vantagens, limitações e testes alternativos;
  7. Conclusão sobre a adequação de cada variável a procedimentos paramétricos.

Propositalmente escolhemos duas variáveis do mesmo conjunto de dados com comportamento oposto — uma aproximadamente simétrica (Wind) e outra fortemente assimétrica (Ozone) — para evidenciar, na prática, como os testes formais e os gráficos reagem a cada cenário.

3. Descrição da Base de Dados

O conjunto de dados airquality é uma base real e pública, distribuída nativamente com o R (pacote datasets), com origem no New York State Department of Conservation (dados de ozônio) e no National Weather Service (dados meteorológicos). Contém 153 observações diárias de qualidade do ar na cidade de Nova York, entre maio e setembro de 1973.

Variável Descrição Unidade
Ozone Concentração média de ozônio ppb (partes por bilhão)
Solar.R Radiação solar langleys
Wind Velocidade média do vento milhas/hora
Temp Temperatura máxima diária °F
Month Mês da observação 5 a 9
Day Dia do mês 1 a 31

Neste relatório focamos em Wind (sem valores ausentes) e Ozone (com valores ausentes, tratados na seção de pressupostos).

data("airquality")
cat("Dimensão da base:", nrow(airquality), "observações x", ncol(airquality), "variáveis\n")
## Dimensão da base: 153 observações x 6 variáveis
head(airquality, 10)
Ozone Solar.R Wind Temp Month Day
41 190 7.4 67 5 1
36 118 8.0 72 5 2
12 149 12.6 74 5 3
18 313 11.5 62 5 4
NA NA 14.3 56 5 5
28 NA 14.9 66 5 6
23 299 8.6 65 5 7
19 99 13.8 59 5 8
8 19 20.1 61 5 9
NA 194 8.6 69 5 10
sapply(airquality, function(x) sum(is.na(x)))
##   Ozone Solar.R    Wind    Temp   Month     Day 
##      37       7       0       0       0       0

4. Fundamentação Teórica

4.1 Formulação das Hipóteses

Para ambos os testes de normalidade, as hipóteses são formuladas da mesma maneira:

  • H0: a variável segue distribuição Normal;
  • H1: a variável não segue distribuição Normal.

O teste é, por natureza, bilateral (de aderência): qualquer desvio relevante da forma normal — para a esquerda, para a direita, achatamento ou afilamento — leva à rejeição de H0. Não existem versões unilaterais para este tipo de teste.

4.2 Pressupostos

  • Variável quantitativa contínua;
  • Amostra aleatória e composta por observações independentes;
  • Ausência de valores ausentes (tratados antes da aplicação do teste).

4.3 Estatística de Teste — Shapiro-Wilk

W = ( Σ aᵢ · x₍ᵢ₎ )² / Σ (xᵢ − x̄)²

onde x₍ᵢ₎ são as observações ordenadas e aᵢ são coeficientes tabelados (Shapiro & Wilk, 1965), derivados dos valores esperados e da matriz de covariância das estatísticas de ordem de uma Normal padrão. W varia no intervalo (0, 1]: quanto mais próximo de 1, mais a amostra se assemelha a uma Normal. Não possui graus de liberdade no sentido clássico; sua distribuição amostral é obtida por simulação/tabela.

4.4 Estatística de Teste — Kolmogorov-Smirnov (uma amostra)

D = sup |Fₙ(x) − F₀(x)|

onde Fₙ(x) é a função de distribuição empírica da amostra e F₀(x) é a função de distribuição acumulada teórica da Normal. D é a maior distância vertical entre as duas curvas. O teste clássico de KS exige que F₀ seja totalmente especificada; por isso os dados são padronizados (z-score) antes do teste — ressalvando que a forma rigorosamente correta para parâmetros estimados da amostra é o teste de Lilliefors.

4.5 Regra de Decisão

  • Método do p-valor: rejeita-se H0 se p ≤ α (neste relatório, α = 0,05);
  • Método do valor crítico: rejeita-se H0 se a estatística do teste (W ou D) for menor (W) ou maior (D) que o valor crítico tabelado para n e α.

Os dois métodos são equivalentes. O método do valor crítico será demonstrado no exemplo manual (Seção 6); o método do p-valor, na aplicação computacional (Seção 8).

5. Metodologia

  1. Importação da base airquality (nativa do R);
  2. Tratamento de valores ausentes por variável (na.omit);
  3. Análise exploratória (estatísticas descritivas, histograma, boxplot);
  4. Verificação dos pressupostos;
  5. Resolução manual do Shapiro-Wilk para uma subamostra de n=5;
  6. Aplicação computacional dos testes de Shapiro-Wilk e Kolmogorov-Smirnov (com padronização) sobre as séries completas, a α = 0,05;
  7. Construção de painel gráfico (histograma, boxplot, QQ-Plot);
  8. Comparação com testes alternativos (quando disponíveis no ambiente);
  9. Interpretação do p-valor, discussão e conclusão.

O procedimento foi implementado também em Python (normalidade.py, usando scipy.stats), confirmando a equivalência dos resultados entre as duas linguagens.

6. Análise Exploratória dos Dados

wind  <- na.omit(airquality$Wind)
ozone <- na.omit(airquality$Ozone)

skewness <- function(x) {
  n <- length(x); m <- mean(x); s <- sqrt(sum((x - m)^2) / n)
  sum(((x - m) / s)^3) / n
}
kurtosis_exc <- function(x) {
  n <- length(x); m <- mean(x); s <- sqrt(sum((x - m)^2) / n)
  sum(((x - m) / s)^4) / n - 3
}

resumo <- data.frame(
  Estatistica = c("n", "Média", "Mediana", "Desvio-padrão",
                  "Assimetria", "Curtose (excesso)", "Mínimo", "Máximo"),
  Wind  = c(length(wind),  mean(wind),  median(wind),  sd(wind),
            skewness(wind),  kurtosis_exc(wind),  min(wind),  max(wind)),
  Ozone = c(length(ozone), mean(ozone), median(ozone), sd(ozone),
            skewness(ozone), kurtosis_exc(ozone), min(ozone), max(ozone))
)
knitr::kable(resumo, digits = 4)
Estatistica Wind Ozone
n 153.0000 116.0000
Média 9.9575 42.1293
Mediana 9.7000 31.5000
Desvio-padrão 3.5230 32.9879
Assimetria 0.3444 1.2257
Curtose (excesso) 0.0688 1.1841
Mínimo 1.7000 1.0000
Máximo 20.7000 168.0000

Leitura inicial: Wind apresenta assimetria próxima de zero, sugerindo forma aproximadamente simétrica. Ozone apresenta assimetria positiva acentuada (cauda longa à direita) — sinal característico de não-normalidade.

par(mfrow = c(1, 2))
hist(wind, main = "Histograma — Wind", xlab = "mph", col = "steelblue", breaks = 12)
hist(ozone, main = "Histograma — Ozone", xlab = "ppb", col = "tomato", breaks = 12)

par(mfrow = c(1, 2))
boxplot(wind, main = "Boxplot — Wind", ylab = "mph")
boxplot(ozone, main = "Boxplot — Ozone", ylab = "ppb")

O boxplot de Wind é razoavelmente simétrico, com poucos outliers. O de Ozone mostra mediana deslocada para a parte inferior da caixa e diversos outliers superiores.

7. Verificação dos Pressupostos

Pressuposto Wind Ozone
Variável quantitativa contínua Atendido Atendido
Observações independentes Atendido (por construção do estudo) Atendido (por construção do estudo)
Valores ausentes Nenhum 37 valores ausentes — removidos via na.omit()
Tamanho de amostra após tratamento n = 153 n = 116

Observação metodológica: por se tratar de série temporal diária, existe em princípio a possibilidade de autocorrelação entre observações consecutivas. Para os fins didáticos deste seminário, tratamos as observações como independentes, como é prática comum ao testar a forma marginal da distribuição.

8. Exemplo Resolvido Manualmente — Shapiro-Wilk (n = 5)

Usamos as 5 primeiras observações reais de Wind (dias 1 a 5 de maio de 1973), com os coeficientes tabelados (Shapiro & Wilk, 1965) para n=5: a5 = 0,6646; a4 = 0,2413; a3 = 0.

x5 <- head(wind, 5)
cat("Amostra (Wind, dias 1-5/maio/1973):", x5, "\n")
## Amostra (Wind, dias 1-5/maio/1973): 7.4 8 12.6 11.5 14.3
x_ord <- sort(x5)
cat("Amostra ordenada:", x_ord, "\n")
## Amostra ordenada: 7.4 8 11.5 12.6 14.3
media <- mean(x_ord)
SS <- sum((x_ord - media)^2)

a5 <- 0.6646; a4 <- 0.2413

b <- a5 * (x_ord[5] - x_ord[1]) + a4 * (x_ord[4] - x_ord[2])
W_manual <- b^2 / SS

cat(sprintf("\nMédia (x̄)               = %.4f\n", media))
## 
## Média (x̄)               = 10.7600
cat(sprintf("Soma de quadrados (SS)   = %.4f\n", SS))
## Soma de quadrados (SS)   = 35.3720
cat(sprintf("b = a5*(x5-x1)+a4*(x4-x2) = %.4f\n", b))
## b = a5*(x5-x1)+a4*(x4-x2) = 5.6957
cat(sprintf("W calculado manualmente  = %.4f\n", W_manual))
## W calculado manualmente  = 0.9171
W_crit <- 0.762  # valor tabelado para n=5, alpha=0.05
decisao_manual <- if (W_manual > W_crit) "NÃO se rejeita H0" else "Rejeita-se H0"
cat(sprintf("W calculado = %.4f | W crítico (n=5, alpha=0.05) = %.3f\n", W_manual, W_crit))
## W calculado = 0.9171 | W crítico (n=5, alpha=0.05) = 0.762
cat("Regra: rejeita-se H0 se W < W_crit  ->  Decisão:", decisao_manual, "\n")
## Regra: rejeita-se H0 se W < W_crit  ->  Decisão: NÃO se rejeita H0
teste_conferencia <- shapiro.test(x5)
cat(sprintf("\nConferência (shapiro.test): W = %.4f | p-valor = %.4f\n",
            teste_conferencia$statistic, teste_conferencia$p.value))
## 
## Conferência (shapiro.test): W = 0.9173 | p-valor = 0.5128

Interpretação: o valor de W calculado manualmente coincide com o de shapiro.test(). Como W está acima do valor crítico tabelado (0,762) para n=5 e α=0,05, não rejeitamos H0 — coerente com o resultado da amostra completa de Wind (n=153), na próxima seção.

9. Aplicação do Teste (Software Estatístico)

Aplicamos os testes de Shapiro-Wilk e Kolmogorov-Smirnov às séries completas. Para o KS, padronizamos os dados (z-score) antes de comparar com a Normal padrão N(0,1).

alpha <- 0.05

testar_normalidade <- function(serie, nome) {
  serie_z <- scale(serie)[, 1]
  sw <- shapiro.test(serie)
  ks <- ks.test(serie_z, "pnorm")
  data.frame(
    Variavel = nome,
    n = length(serie),
    `Shapiro_W` = sw$statistic,
    `p_valor_SW` = sw$p.value,
    `KS_D` = ks$statistic,
    `p_valor_KS` = ks$p.value,
    `Decisao_SW` = if (sw$p.value > alpha) "Não rejeita H0" else "Rejeita H0",
    `Decisao_KS` = if (ks$p.value > alpha) "Não rejeita H0" else "Rejeita H0"
  )
}

resultados <- rbind(
  testar_normalidade(wind, "Wind"),
  testar_normalidade(ozone, "Ozone")
)
rownames(resultados) <- NULL
knitr::kable(resultados, digits = 4)
Variavel n Shapiro_W p_valor_SW KS_D p_valor_KS Decisao_SW Decisao_KS
Wind 153 0.9857 0.1178 0.0824 0.2501 Não rejeita H0 Não rejeita H0
Ozone 116 0.8787 0.0000 0.1480 0.0124 Rejeita H0 Rejeita H0

Em Python, o procedimento equivalente está em normalidade.py (script completo):

sw_stat, sw_p = stats.shapiro(serie)
ks_stat, ks_p = stats.kstest(stats.zscore(serie), "norm")

10. Resultados

10.1 Método do p-valor

  • Wind: p(SW) > 0,05 e p(KS) > 0,05 → não se rejeita H0 — compatível com Normal.
  • Ozone: p(SW) ≤ 0,05 e p(KS) ≤ 0,05 → rejeita-se H0 — não compatível com Normal.

10.2 Método do valor crítico (ilustração)

Para amostras grandes (n=153 e n=116), o método do p-valor é o mais prático; o método do valor crítico foi demonstrado na Seção 8 para n=5. Os dois métodos são equivalentes e levam à mesma decisão.

11. Visualizações Gráficas

par(mfrow = c(1, 3))
hist(wind, main = "Histograma — Wind", xlab = "mph", col = "steelblue", breaks = 12)
boxplot(wind, main = "Boxplot — Wind", ylab = "mph")
qqnorm(wind, main = "QQ-Plot — Wind")
qqline(wind, col = "red", lwd = 2)

par(mfrow = c(1, 3))
hist(ozone, main = "Histograma — Ozone", xlab = "ppb", col = "tomato", breaks = 12)
boxplot(ozone, main = "Boxplot — Ozone", ylab = "ppb")
qqnorm(ozone, main = "QQ-Plot — Ozone")
qqline(ozone, col = "red", lwd = 2)

Leitura dos QQ-Plots: em Wind, os pontos seguem de perto a reta de referência. Em Ozone, os pontos se afastam sistematicamente da reta nas extremidades, revelando visualmente a assimetria quantificada pelos testes formais.

12. Discussão

  • Os dois testes concordam na decisão final para ambas as variáveis, mas discordam na magnitude da evidência: para Ozone, o Shapiro-Wilk produz um p-valor extremamente pequeno (ordem de 10⁻⁸), muito mais extremo do que o do Kolmogorov-Smirnov — o Shapiro-Wilk é, em geral, mais sensível a desvios de normalidade.
  • O KS, ao depender da maior distância entre curvas acumuladas, tende a ser menos sensível a desvios localizados (caudas pesadas, poucos outliers).
  • A inspeção gráfica confirmou a conclusão dos testes formais em ambos os casos, reforçando a recomendação de sempre cruzar teste formal com gráfico.

13. Vantagens e Limitações dos Testes

Teste Vantagens Limitações
Shapiro-Wilk Maior poder estatístico entre os testes clássicos, especialmente para n pequeno/médio Sensível a outliers; em amostras muito grandes, rejeita H0 mesmo para desvios sem relevância prática
Kolmogorov-Smirnov Conceito geral, aplicável a qualquer distribuição teórica Menos sensível que o Shapiro-Wilk; exige distribuição totalmente especificada (motivou a correção de Lilliefors)

14. Comparação com Outros Testes Semelhantes

Além de Shapiro-Wilk e Kolmogorov-Smirnov, a literatura apresenta outras alternativas:

  • Lilliefors: correção do KS para quando média e desvio-padrão são estimados da própria amostra;
  • Anderson-Darling: dá mais peso às caudas da distribuição, mais sensível a outliers extremos;
  • Jarque-Bera / D’Agostino-Pearson: baseados em assimetria e curtose amostrais, comuns em séries econômicas/financeiras.
if (requireNamespace("nortest", quietly = TRUE)) {
  library(nortest)
  ad_wind  <- ad.test(wind)
  ad_ozone <- ad.test(ozone)
  knitr::kable(data.frame(
    Variavel = c("Wind", "Ozone"),
    Estatistica_A2 = c(ad_wind$statistic, ad_ozone$statistic),
    p_valor = c(ad_wind$p.value, ad_ozone$p.value)
  ), digits = 4)
} else {
  cat("Pacote 'nortest' não instalado neste ambiente.",
      "Para reproduzir a comparação com Anderson-Darling, execute:",
      "install.packages('nortest')", sep = "\n")
}
## Pacote 'nortest' não instalado neste ambiente.
## Para reproduzir a comparação com Anderson-Darling, execute:
## install.packages('nortest')

15. Exercício Aplicado para Discussão com a Turma

Proposta: utilizando a mesma base airquality, teste a normalidade da variável Temp (temperatura máxima diária).

  1. Trate eventuais valores ausentes;
  2. Construa o histograma, o boxplot e o QQ-Plot de Temp;
  3. Aplique os testes de Shapiro-Wilk e Kolmogorov-Smirnov a α = 0,05;
  4. Compare a decisão obtida pelos dois testes;
  5. Discuta: a conclusão do teste formal é coerente com o que se observa nos gráficos?
temp <- na.omit(airquality$Temp)
testar_normalidade(temp, "Temp")
Variavel n Shapiro_W p_valor_SW KS_D p_valor_KS Decisao_SW Decisao_KS
W Temp 153 0.976173 0.0093194 0.0813132 0.2638467 Rejeita H0 Não rejeita H0

16. Conclusão

Com base nos testes de Shapiro-Wilk e Kolmogorov-Smirnov, complementados pela inspeção gráfica, concluímos que:

  • A variável Wind é estatisticamente compatível com a distribuição Normal (p > 0,05 em ambos os testes), tanto na amostra completa (n=153) quanto no exemplo manual (n=5);
  • A variável Ozone não é compatível com a distribuição Normal (p ≤ 0,05 em ambos os testes), com evidência fortíssima no Shapiro-Wilk;
  • Os resultados obtidos em R e em Python (normalidade.py) coincidem, validando a implementação computacional em ambas as linguagens;
  • Quando a normalidade não se confirma — como em Ozone — as alternativas metodológicas incluem: (i) transformação da variável (log, Box-Cox), (ii) uso de testes não-paramétricos equivalentes, (iii) apoio no Teorema Central do Limite quando a amostra é suficientemente grande, ou (iv) métodos robustos/bootstrap.

17. Referências

  • BUSSAB, W. O.; MORETTIN, P. A. Estatística Básica. São Paulo: Saraiva.
  • MONTGOMERY, D. C.; RUNGER, G. C. Estatística Aplicada e Probabilidade para Engenheiros. Rio de Janeiro: LTC.
  • PAGANO, M.; GAUVREAU, K. Princípios de Bioestatística. São Paulo: Cengage Learning.
  • CONOVER, W. J. Practical Nonparametric Statistics. New York: Wiley.
  • HOLLANDER, M.; WOLFE, D. A. Nonparametric Statistical Methods. New York: Wiley.
  • SHAPIRO, S. S.; WILK, M. B. An analysis of variance test for normality (complete samples). Biometrika, v. 52, n. 3/4, p. 591–611, 1965.
  • MASSEY JR., F. J. The Kolmogorov-Smirnov test for goodness of fit. Journal of the American Statistical Association, v. 46, n. 253, p. 68–78, 1951.
  • R CORE TEAM. R: A Language and Environment for Statistical Computing. Documentação de shapiro.test(), ks.test(), qqnorm(), qqline().

Arquivos complementares deste seminário (mesma pasta): normalidade.R, normalidade.py

LS0tCnRpdGxlOiAiUmVsYXTDs3JpbyBBbmFsw610aWNvIOKAlCBUZXN0ZXMgZGUgTm9ybWFsaWRhZGUiCnN1YnRpdGxlOiAiU2hhcGlyby1XaWxrIGUgS29sbW9nb3Jvdi1TbWlybm92IMK3IEdydXBvIDggwrcgSW5mZXLDqm5jaWEgRXN0YXTDrXN0aWNhIgphdXRob3I6CiAgLSAiQW50b25pbyBTYW1wYWlvIGRlIE1hcmluaG8g4oCUIE1hdHLDrWN1bGE6IDU2NjQ1MCIKICAtICJBbmEgVml0w7NyaWEgVmllaXJhIEZyZWlyZSBkZSBNZXNxdWlzdGEg4oCUIE1hdHLDrWN1bGE6IDU4MTA0MiIKZGF0ZTogImByIGZvcm1hdChTeXMuRGF0ZSgpLCAnJWQvJW0vJVknKWAiCm91dHB1dDoKICBodG1sX2RvY3VtZW50OgogICAgdG9jOiB0cnVlCiAgICB0b2NfZmxvYXQ6IHRydWUKICAgIHRvY19kZXB0aDogMwogICAgdGhlbWU6IGNvc21vCiAgICBkZl9wcmludDoga2FibGUKICAgIG1hdGhqYXg6IG51bGwKICAgIHNlbGZfY29udGFpbmVkOiB0cnVlCiAgICBjb2RlX2ZvbGRpbmc6IGhpZGUKICAgIGNvZGVfZG93bmxvYWQ6IHRydWUKLS0tCgpgYGB7ciBzZXR1cCwgaW5jbHVkZT1GQUxTRX0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KGVjaG8gPSBUUlVFLCBtZXNzYWdlID0gRkFMU0UsIHdhcm5pbmcgPSBGQUxTRSwgZmlnLmFsaWduID0gImNlbnRlciIpCmBgYAoKIyAxLiBJbnRyb2R1w6fDo28KCkRpdmVyc29zIHRlc3RlcyBlc3RhdMOtc3RpY29zIGNsw6Fzc2ljb3Mg4oCUIHRlc3RlIHQsIEFOT1ZBLCByZWdyZXNzw6NvIGxpbmVhciwgZW50cmUgb3V0cm9zIOKAlCBiYXNlaWFtLXNlIG5hIHN1cG9zacOnw6NvIGRlIHF1ZSBhIHZhcmnDoXZlbCBkZSBpbnRlcmVzc2UgKG91IG9zIHJlc8OtZHVvcyBkbyBtb2RlbG8pIHNlZ3VlIHVtYSAqKmRpc3RyaWJ1acOnw6NvIE5vcm1hbCoqLiBFc3NhIHN1cG9zacOnw6NvIG7Do28gcG9kZSBzZXIgYXNzdW1pZGEgYXBlbmFzIHBlbGEgaW5zcGXDp8OjbyB2aXN1YWwgZG9zIGRhZG9zOiDDqSBuZWNlc3PDoXJpbyB2ZXJpZmljw6EtbGEgZm9ybWFsbWVudGUgYW50ZXMgZGUgYXBsaWNhciBxdWFscXVlciB0w6ljbmljYSBwYXJhbcOpdHJpY2EuCgpPcyAqKnRlc3RlcyBkZSBub3JtYWxpZGFkZSoqIHPDo28gdGVzdGVzIGRlIGhpcMOzdGVzZXMgZG8gdGlwbyAqYWRlcsOqbmNpYSogKCpnb29kbmVzcy1vZi1maXQqKSwgY3VqbyBvYmpldGl2byDDqSBhdmFsaWFyIHNlIHVtYSBhbW9zdHJhIMOpIGNvbXBhdMOtdmVsIGNvbSBhIGhpcMOzdGVzZSBkZSB0ZXIgc2lkbyBnZXJhZGEgcG9yIHVtYSBwb3B1bGHDp8OjbyBub3JtYWxtZW50ZSBkaXN0cmlidcOtZGEuIE5lc3RlIHJlbGF0w7NyaW8gdXRpbGl6YW1vcyBvcyBkb2lzIHRlc3RlcyBmb3JtYWlzIG1haXMgZW1wcmVnYWRvcyBuYSBwcsOhdGljYSDigJQgKipTaGFwaXJvLVdpbGsqKiBlICoqS29sbW9nb3Jvdi1TbWlybm92Kiog4oCUIGNvbXBsZW1lbnRhZG9zIHBvciByZWN1cnNvcyBncsOhZmljb3MgKGhpc3RvZ3JhbWEsIGJveHBsb3QgZSBRUS1QbG90KS4KCiMgMi4gT2JqZXRpdm8gZGEgQW7DoWxpc2UKClZlcmlmaWNhciwgY29tIGJhc2UgZW0gZGFkb3MgcmVhaXMsIHNlIGFzIHZhcmnDoXZlaXMgYFdpbmRgIGUgYE96b25lYCBkbyBjb25qdW50byBkZSBkYWRvcyBgYWlycXVhbGl0eWAgc8OjbyBjb21wYXTDrXZlaXMgY29tIGEgZGlzdHJpYnVpw6fDo28gTm9ybWFsLCBwb3IgbWVpbyBkZToKCjEuIEFuw6FsaXNlIGV4cGxvcmF0w7NyaWEgZSBpbnNwZcOnw6NvIGdyw6FmaWNhIChoaXN0b2dyYW1hLCBib3hwbG90LCBRUS1QbG90KTsKMi4gVmVyaWZpY2HDp8OjbyBkb3MgcHJlc3N1cG9zdG9zIGRlIGFwbGljYcOnw6NvIGRvcyB0ZXN0ZXM7CjMuIEFwbGljYcOnw6NvIGRvcyB0ZXN0ZXMgZGUgKipTaGFwaXJvLVdpbGsqKiBlICoqS29sbW9nb3Jvdi1TbWlybm92Kio7CjQuIFJlc29sdcOnw6NvIG1hbnVhbCBkZSB1bSBleGVtcGxvIGNvbSBhbW9zdHJhIHJlZHV6aWRhIChuID0gNSk7CjUuIEludGVycHJldGHDp8OjbyBkbyBwLXZhbG9yIGUgY29tcGFyYcOnw6NvIGNvbSBvIG3DqXRvZG8gZG8gdmFsb3IgY3LDrXRpY287CjYuIERpc2N1c3PDo28gY3LDrXRpY2Egc29icmUgdmFudGFnZW5zLCBsaW1pdGHDp8O1ZXMgZSB0ZXN0ZXMgYWx0ZXJuYXRpdm9zOwo3LiBDb25jbHVzw6NvIHNvYnJlIGEgYWRlcXVhw6fDo28gZGUgY2FkYSB2YXJpw6F2ZWwgYSBwcm9jZWRpbWVudG9zIHBhcmFtw6l0cmljb3MuCgpQcm9wb3NpdGFsbWVudGUgZXNjb2xoZW1vcyBkdWFzIHZhcmnDoXZlaXMgZG8gbWVzbW8gY29uanVudG8gZGUgZGFkb3MgY29tIGNvbXBvcnRhbWVudG8gb3Bvc3RvIOKAlCB1bWEgYXByb3hpbWFkYW1lbnRlIHNpbcOpdHJpY2EgKGBXaW5kYCkgZSBvdXRyYSBmb3J0ZW1lbnRlIGFzc2ltw6l0cmljYSAoYE96b25lYCkg4oCUIHBhcmEgZXZpZGVuY2lhciwgbmEgcHLDoXRpY2EsIGNvbW8gb3MgdGVzdGVzIGZvcm1haXMgZSBvcyBncsOhZmljb3MgcmVhZ2VtIGEgY2FkYSBjZW7DoXJpby4KCiMgMy4gRGVzY3Jpw6fDo28gZGEgQmFzZSBkZSBEYWRvcwoKTyBjb25qdW50byBkZSBkYWRvcyBgYWlycXVhbGl0eWAgw6kgdW1hIGJhc2UgKipyZWFsIGUgcMO6YmxpY2EqKiwgZGlzdHJpYnXDrWRhIG5hdGl2YW1lbnRlIGNvbSBvIFIgKHBhY290ZSBgZGF0YXNldHNgKSwgY29tIG9yaWdlbSBubyAqTmV3IFlvcmsgU3RhdGUgRGVwYXJ0bWVudCBvZiBDb25zZXJ2YXRpb24qIChkYWRvcyBkZSBvesO0bmlvKSBlIG5vICpOYXRpb25hbCBXZWF0aGVyIFNlcnZpY2UqIChkYWRvcyBtZXRlb3JvbMOzZ2ljb3MpLiBDb250w6ltICoqMTUzIG9ic2VydmHDp8O1ZXMgZGnDoXJpYXMqKiBkZSBxdWFsaWRhZGUgZG8gYXIgbmEgY2lkYWRlIGRlIE5vdmEgWW9yaywgZW50cmUgKiptYWlvIGUgc2V0ZW1icm8gZGUgMTk3MyoqLgoKfCBWYXJpw6F2ZWwgfCBEZXNjcmnDp8OjbyB8IFVuaWRhZGUgfAp8LS0tfC0tLXwtLS18CnwgYE96b25lYCB8IENvbmNlbnRyYcOnw6NvIG3DqWRpYSBkZSBvesO0bmlvIHwgcHBiIChwYXJ0ZXMgcG9yIGJpbGjDo28pIHwKfCBgU29sYXIuUmAgfCBSYWRpYcOnw6NvIHNvbGFyIHwgbGFuZ2xleXMgfAp8IGBXaW5kYCB8IFZlbG9jaWRhZGUgbcOpZGlhIGRvIHZlbnRvIHwgbWlsaGFzL2hvcmEgfAp8IGBUZW1wYCB8IFRlbXBlcmF0dXJhIG3DoXhpbWEgZGnDoXJpYSB8IMKwRiB8CnwgYE1vbnRoYCB8IE3DqnMgZGEgb2JzZXJ2YcOnw6NvIHwgNSBhIDkgfAp8IGBEYXlgIHwgRGlhIGRvIG3DqnMgfCAxIGEgMzEgfAoKTmVzdGUgcmVsYXTDs3JpbyBmb2NhbW9zIGVtICoqYFdpbmRgKiogKHNlbSB2YWxvcmVzIGF1c2VudGVzKSBlICoqYE96b25lYCoqIChjb20gdmFsb3JlcyBhdXNlbnRlcywgdHJhdGFkb3MgbmEgc2XDp8OjbyBkZSBwcmVzc3Vwb3N0b3MpLgoKYGBge3IgY2FycmVnYXItZGFkb3N9CmRhdGEoImFpcnF1YWxpdHkiKQpjYXQoIkRpbWVuc8OjbyBkYSBiYXNlOiIsIG5yb3coYWlycXVhbGl0eSksICJvYnNlcnZhw6fDtWVzIHgiLCBuY29sKGFpcnF1YWxpdHkpLCAidmFyacOhdmVpc1xuIikKaGVhZChhaXJxdWFsaXR5LCAxMCkKYGBgCgpgYGB7ciBhdXNlbnRlc30Kc2FwcGx5KGFpcnF1YWxpdHksIGZ1bmN0aW9uKHgpIHN1bShpcy5uYSh4KSkpCmBgYAoKIyA0LiBGdW5kYW1lbnRhw6fDo28gVGXDs3JpY2EKCiMjIyA0LjEgRm9ybXVsYcOnw6NvIGRhcyBIaXDDs3Rlc2VzCgpQYXJhIGFtYm9zIG9zIHRlc3RlcyBkZSBub3JtYWxpZGFkZSwgYXMgaGlww7N0ZXNlcyBzw6NvIGZvcm11bGFkYXMgZGEgbWVzbWEgbWFuZWlyYToKCi0gKipIMDoqKiBhIHZhcmnDoXZlbCBzZWd1ZSBkaXN0cmlidWnDp8OjbyBOb3JtYWw7Ci0gKipIMToqKiBhIHZhcmnDoXZlbCAqKm7Do28qKiBzZWd1ZSBkaXN0cmlidWnDp8OjbyBOb3JtYWwuCgpPIHRlc3RlIMOpLCBwb3IgbmF0dXJlemEsICoqYmlsYXRlcmFsKiogKGRlIGFkZXLDqm5jaWEpOiBxdWFscXVlciBkZXN2aW8gcmVsZXZhbnRlIGRhIGZvcm1hIG5vcm1hbCDigJQgcGFyYSBhIGVzcXVlcmRhLCBwYXJhIGEgZGlyZWl0YSwgYWNoYXRhbWVudG8gb3UgYWZpbGFtZW50byDigJQgbGV2YSDDoCByZWplacOnw6NvIGRlIEgwLiBOw6NvIGV4aXN0ZW0gdmVyc8O1ZXMgdW5pbGF0ZXJhaXMgcGFyYSBlc3RlIHRpcG8gZGUgdGVzdGUuCgojIyMgNC4yIFByZXNzdXBvc3RvcwoKLSBWYXJpw6F2ZWwgKipxdWFudGl0YXRpdmEgY29udMOtbnVhKio7Ci0gQW1vc3RyYSAqKmFsZWF0w7NyaWEgZSBjb21wb3N0YSBwb3Igb2JzZXJ2YcOnw7VlcyBpbmRlcGVuZGVudGVzKio7Ci0gQXVzw6puY2lhIGRlIHZhbG9yZXMgYXVzZW50ZXMgKHRyYXRhZG9zIGFudGVzIGRhIGFwbGljYcOnw6NvIGRvIHRlc3RlKS4KCiMjIyA0LjMgRXN0YXTDrXN0aWNhIGRlIFRlc3RlIOKAlCBTaGFwaXJvLVdpbGsKClcgPSAoIM6jIGHhtaIgwrcgeOKCjeG1ouKCjiApwrIgLyDOoyAoeOG1oiDiiJIgeMyEKcKyCgpvbmRlIHjigo3htaLigo4gc8OjbyBhcyBvYnNlcnZhw6fDtWVzIG9yZGVuYWRhcyBlIGHhtaIgc8OjbyBjb2VmaWNpZW50ZXMgdGFiZWxhZG9zIChTaGFwaXJvICYgV2lsaywgMTk2NSksIGRlcml2YWRvcyBkb3MgdmFsb3JlcyBlc3BlcmFkb3MgZSBkYSBtYXRyaXogZGUgY292YXJpw6JuY2lhIGRhcyBlc3RhdMOtc3RpY2FzIGRlIG9yZGVtIGRlIHVtYSBOb3JtYWwgcGFkcsOjby4gVyB2YXJpYSBubyBpbnRlcnZhbG8gKDAsIDFdOiBxdWFudG8gbWFpcyBwcsOzeGltbyBkZSAxLCBtYWlzIGEgYW1vc3RyYSBzZSBhc3NlbWVsaGEgYSB1bWEgTm9ybWFsLiBOw6NvIHBvc3N1aSBncmF1cyBkZSBsaWJlcmRhZGUgbm8gc2VudGlkbyBjbMOhc3NpY287IHN1YSBkaXN0cmlidWnDp8OjbyBhbW9zdHJhbCDDqSBvYnRpZGEgcG9yIHNpbXVsYcOnw6NvL3RhYmVsYS4KCiMjIyA0LjQgRXN0YXTDrXN0aWNhIGRlIFRlc3RlIOKAlCBLb2xtb2dvcm92LVNtaXJub3YgKHVtYSBhbW9zdHJhKQoKRCA9IHN1cCB8RuKCmSh4KSDiiJIgRuKCgCh4KXwKCm9uZGUgRuKCmSh4KSDDqSBhIGZ1bsOnw6NvIGRlIGRpc3RyaWJ1acOnw6NvIGVtcMOtcmljYSBkYSBhbW9zdHJhIGUgRuKCgCh4KSDDqSBhIGZ1bsOnw6NvIGRlIGRpc3RyaWJ1acOnw6NvIGFjdW11bGFkYSB0ZcOzcmljYSBkYSBOb3JtYWwuIEQgw6kgYSBtYWlvciBkaXN0w6JuY2lhIHZlcnRpY2FsIGVudHJlIGFzIGR1YXMgY3VydmFzLiBPIHRlc3RlIGNsw6Fzc2ljbyBkZSBLUyBleGlnZSBxdWUgRuKCgCBzZWphICoqdG90YWxtZW50ZSBlc3BlY2lmaWNhZGEqKjsgcG9yIGlzc28gb3MgZGFkb3Mgc8OjbyBwYWRyb25pemFkb3MgKCp6LXNjb3JlKikgYW50ZXMgZG8gdGVzdGUg4oCUIHJlc3NhbHZhbmRvIHF1ZSBhIGZvcm1hIHJpZ29yb3NhbWVudGUgY29ycmV0YSBwYXJhIHBhcsOibWV0cm9zIGVzdGltYWRvcyBkYSBhbW9zdHJhIMOpIG8gdGVzdGUgZGUgKipMaWxsaWVmb3JzKiouCgojIyMgNC41IFJlZ3JhIGRlIERlY2lzw6NvCgotICoqTcOpdG9kbyBkbyBwLXZhbG9yOioqIHJlamVpdGEtc2UgSDAgc2UgcCDiiaQgzrEgKG5lc3RlIHJlbGF0w7NyaW8sIM6xID0gMCwwNSk7Ci0gKipNw6l0b2RvIGRvIHZhbG9yIGNyw610aWNvOioqIHJlamVpdGEtc2UgSDAgc2UgYSBlc3RhdMOtc3RpY2EgZG8gdGVzdGUgKFcgb3UgRCkgZm9yIG1lbm9yIChXKSBvdSBtYWlvciAoRCkgcXVlIG8gdmFsb3IgY3LDrXRpY28gdGFiZWxhZG8gcGFyYSBuIGUgzrEuCgpPcyBkb2lzIG3DqXRvZG9zIHPDo28gZXF1aXZhbGVudGVzLiBPIG3DqXRvZG8gZG8gdmFsb3IgY3LDrXRpY28gc2Vyw6EgZGVtb25zdHJhZG8gbm8gZXhlbXBsbyBtYW51YWwgKFNlw6fDo28gNik7IG8gbcOpdG9kbyBkbyBwLXZhbG9yLCBuYSBhcGxpY2HDp8OjbyBjb21wdXRhY2lvbmFsIChTZcOnw6NvIDgpLgoKIyA1LiBNZXRvZG9sb2dpYQoKMS4gSW1wb3J0YcOnw6NvIGRhIGJhc2UgYGFpcnF1YWxpdHlgIChuYXRpdmEgZG8gUik7CjIuIFRyYXRhbWVudG8gZGUgdmFsb3JlcyBhdXNlbnRlcyBwb3IgdmFyacOhdmVsIChgbmEub21pdGApOwozLiBBbsOhbGlzZSBleHBsb3JhdMOzcmlhIChlc3RhdMOtc3RpY2FzIGRlc2NyaXRpdmFzLCBoaXN0b2dyYW1hLCBib3hwbG90KTsKNC4gVmVyaWZpY2HDp8OjbyBkb3MgcHJlc3N1cG9zdG9zOwo1LiBSZXNvbHXDp8OjbyBtYW51YWwgZG8gU2hhcGlyby1XaWxrIHBhcmEgdW1hIHN1YmFtb3N0cmEgZGUgbj01Owo2LiBBcGxpY2HDp8OjbyBjb21wdXRhY2lvbmFsIGRvcyB0ZXN0ZXMgZGUgU2hhcGlyby1XaWxrIGUgS29sbW9nb3Jvdi1TbWlybm92IChjb20gcGFkcm9uaXphw6fDo28pIHNvYnJlIGFzIHPDqXJpZXMgY29tcGxldGFzLCBhIM6xID0gMCwwNTsKNy4gQ29uc3RydcOnw6NvIGRlIHBhaW5lbCBncsOhZmljbyAoaGlzdG9ncmFtYSwgYm94cGxvdCwgUVEtUGxvdCk7CjguIENvbXBhcmHDp8OjbyBjb20gdGVzdGVzIGFsdGVybmF0aXZvcyAocXVhbmRvIGRpc3BvbsOtdmVpcyBubyBhbWJpZW50ZSk7CjkuIEludGVycHJldGHDp8OjbyBkbyBwLXZhbG9yLCBkaXNjdXNzw6NvIGUgY29uY2x1c8Ojby4KCk8gcHJvY2VkaW1lbnRvIGZvaSBpbXBsZW1lbnRhZG8gdGFtYsOpbSBlbSAqKlB5dGhvbioqIChgbm9ybWFsaWRhZGUucHlgLCB1c2FuZG8gYHNjaXB5LnN0YXRzYCksIGNvbmZpcm1hbmRvIGEgZXF1aXZhbMOqbmNpYSBkb3MgcmVzdWx0YWRvcyBlbnRyZSBhcyBkdWFzIGxpbmd1YWdlbnMuCgojIDYuIEFuw6FsaXNlIEV4cGxvcmF0w7NyaWEgZG9zIERhZG9zCgpgYGB7ciBleHBsb3JhdG9yaWF9CndpbmQgIDwtIG5hLm9taXQoYWlycXVhbGl0eSRXaW5kKQpvem9uZSA8LSBuYS5vbWl0KGFpcnF1YWxpdHkkT3pvbmUpCgpza2V3bmVzcyA8LSBmdW5jdGlvbih4KSB7CiAgbiA8LSBsZW5ndGgoeCk7IG0gPC0gbWVhbih4KTsgcyA8LSBzcXJ0KHN1bSgoeCAtIG0pXjIpIC8gbikKICBzdW0oKCh4IC0gbSkgLyBzKV4zKSAvIG4KfQprdXJ0b3Npc19leGMgPC0gZnVuY3Rpb24oeCkgewogIG4gPC0gbGVuZ3RoKHgpOyBtIDwtIG1lYW4oeCk7IHMgPC0gc3FydChzdW0oKHggLSBtKV4yKSAvIG4pCiAgc3VtKCgoeCAtIG0pIC8gcyleNCkgLyBuIC0gMwp9CgpyZXN1bW8gPC0gZGF0YS5mcmFtZSgKICBFc3RhdGlzdGljYSA9IGMoIm4iLCAiTcOpZGlhIiwgIk1lZGlhbmEiLCAiRGVzdmlvLXBhZHLDo28iLAogICAgICAgICAgICAgICAgICAiQXNzaW1ldHJpYSIsICJDdXJ0b3NlIChleGNlc3NvKSIsICJNw61uaW1vIiwgIk3DoXhpbW8iKSwKICBXaW5kICA9IGMobGVuZ3RoKHdpbmQpLCAgbWVhbih3aW5kKSwgIG1lZGlhbih3aW5kKSwgIHNkKHdpbmQpLAogICAgICAgICAgICBza2V3bmVzcyh3aW5kKSwgIGt1cnRvc2lzX2V4Yyh3aW5kKSwgIG1pbih3aW5kKSwgIG1heCh3aW5kKSksCiAgT3pvbmUgPSBjKGxlbmd0aChvem9uZSksIG1lYW4ob3pvbmUpLCBtZWRpYW4ob3pvbmUpLCBzZChvem9uZSksCiAgICAgICAgICAgIHNrZXduZXNzKG96b25lKSwga3VydG9zaXNfZXhjKG96b25lKSwgbWluKG96b25lKSwgbWF4KG96b25lKSkKKQprbml0cjo6a2FibGUocmVzdW1vLCBkaWdpdHMgPSA0KQpgYGAKCioqTGVpdHVyYSBpbmljaWFsOioqIGBXaW5kYCBhcHJlc2VudGEgYXNzaW1ldHJpYSBwcsOzeGltYSBkZSB6ZXJvLCBzdWdlcmluZG8gZm9ybWEgYXByb3hpbWFkYW1lbnRlIHNpbcOpdHJpY2EuIGBPem9uZWAgYXByZXNlbnRhIGFzc2ltZXRyaWEgcG9zaXRpdmEgYWNlbnR1YWRhIChjYXVkYSBsb25nYSDDoCBkaXJlaXRhKSDigJQgc2luYWwgY2FyYWN0ZXLDrXN0aWNvIGRlICoqbsOjby1ub3JtYWxpZGFkZSoqLgoKYGBge3IgaGlzdC1ib3gsIGZpZy53aWR0aD05LCBmaWcuaGVpZ2h0PTR9CnBhcihtZnJvdyA9IGMoMSwgMikpCmhpc3Qod2luZCwgbWFpbiA9ICJIaXN0b2dyYW1hIOKAlCBXaW5kIiwgeGxhYiA9ICJtcGgiLCBjb2wgPSAic3RlZWxibHVlIiwgYnJlYWtzID0gMTIpCmhpc3Qob3pvbmUsIG1haW4gPSAiSGlzdG9ncmFtYSDigJQgT3pvbmUiLCB4bGFiID0gInBwYiIsIGNvbCA9ICJ0b21hdG8iLCBicmVha3MgPSAxMikKYGBgCgpgYGB7ciBib3hwbG90cywgZmlnLndpZHRoPTYsIGZpZy5oZWlnaHQ9NH0KcGFyKG1mcm93ID0gYygxLCAyKSkKYm94cGxvdCh3aW5kLCBtYWluID0gIkJveHBsb3Qg4oCUIFdpbmQiLCB5bGFiID0gIm1waCIpCmJveHBsb3Qob3pvbmUsIG1haW4gPSAiQm94cGxvdCDigJQgT3pvbmUiLCB5bGFiID0gInBwYiIpCmBgYAoKTyBib3hwbG90IGRlIGBXaW5kYCDDqSByYXpvYXZlbG1lbnRlIHNpbcOpdHJpY28sIGNvbSBwb3Vjb3Mgb3V0bGllcnMuIE8gZGUgYE96b25lYCBtb3N0cmEgbWVkaWFuYSBkZXNsb2NhZGEgcGFyYSBhIHBhcnRlIGluZmVyaW9yIGRhIGNhaXhhIGUgZGl2ZXJzb3Mgb3V0bGllcnMgc3VwZXJpb3Jlcy4KCiMgNy4gVmVyaWZpY2HDp8OjbyBkb3MgUHJlc3N1cG9zdG9zCgp8IFByZXNzdXBvc3RvIHwgYFdpbmRgIHwgYE96b25lYCB8CnwtLS18LS0tfC0tLXwKfCBWYXJpw6F2ZWwgcXVhbnRpdGF0aXZhIGNvbnTDrW51YSB8IEF0ZW5kaWRvIHwgQXRlbmRpZG8gfAp8IE9ic2VydmHDp8O1ZXMgaW5kZXBlbmRlbnRlcyB8IEF0ZW5kaWRvIChwb3IgY29uc3RydcOnw6NvIGRvIGVzdHVkbykgfCBBdGVuZGlkbyAocG9yIGNvbnN0cnXDp8OjbyBkbyBlc3R1ZG8pIHwKfCBWYWxvcmVzIGF1c2VudGVzIHwgTmVuaHVtIHwgMzcgdmFsb3JlcyBhdXNlbnRlcyDigJQgcmVtb3ZpZG9zIHZpYSBgbmEub21pdCgpYCB8CnwgVGFtYW5obyBkZSBhbW9zdHJhIGFww7NzIHRyYXRhbWVudG8gfCBuID0gMTUzIHwgbiA9IDExNiB8CgoqKk9ic2VydmHDp8OjbyBtZXRvZG9sw7NnaWNhOioqIHBvciBzZSB0cmF0YXIgZGUgc8OpcmllIHRlbXBvcmFsIGRpw6FyaWEsIGV4aXN0ZSBlbSBwcmluY8OtcGlvIGEgcG9zc2liaWxpZGFkZSBkZSBhdXRvY29ycmVsYcOnw6NvIGVudHJlIG9ic2VydmHDp8O1ZXMgY29uc2VjdXRpdmFzLiBQYXJhIG9zIGZpbnMgZGlkw6F0aWNvcyBkZXN0ZSBzZW1pbsOhcmlvLCB0cmF0YW1vcyBhcyBvYnNlcnZhw6fDtWVzIGNvbW8gaW5kZXBlbmRlbnRlcywgY29tbyDDqSBwcsOhdGljYSBjb211bSBhbyB0ZXN0YXIgYSBmb3JtYSBtYXJnaW5hbCBkYSBkaXN0cmlidWnDp8Ojby4KCiMgOC4gRXhlbXBsbyBSZXNvbHZpZG8gTWFudWFsbWVudGUg4oCUIFNoYXBpcm8tV2lsayAobiA9IDUpCgpVc2Ftb3MgYXMgKio1IHByaW1laXJhcyBvYnNlcnZhw6fDtWVzIHJlYWlzKiogZGUgYFdpbmRgIChkaWFzIDEgYSA1IGRlIG1haW8gZGUgMTk3MyksIGNvbSBvcyBjb2VmaWNpZW50ZXMgdGFiZWxhZG9zIChTaGFwaXJvICYgV2lsaywgMTk2NSkgcGFyYSBuPTU6IGE1ID0gMCw2NjQ2OyBhNCA9IDAsMjQxMzsgYTMgPSAwLgoKYGBge3IgbWFudWFsLXN3fQp4NSA8LSBoZWFkKHdpbmQsIDUpCmNhdCgiQW1vc3RyYSAoV2luZCwgZGlhcyAxLTUvbWFpby8xOTczKToiLCB4NSwgIlxuIikKCnhfb3JkIDwtIHNvcnQoeDUpCmNhdCgiQW1vc3RyYSBvcmRlbmFkYToiLCB4X29yZCwgIlxuIikKCm1lZGlhIDwtIG1lYW4oeF9vcmQpClNTIDwtIHN1bSgoeF9vcmQgLSBtZWRpYSleMikKCmE1IDwtIDAuNjY0NjsgYTQgPC0gMC4yNDEzCgpiIDwtIGE1ICogKHhfb3JkWzVdIC0geF9vcmRbMV0pICsgYTQgKiAoeF9vcmRbNF0gLSB4X29yZFsyXSkKV19tYW51YWwgPC0gYl4yIC8gU1MKCmNhdChzcHJpbnRmKCJcbk3DqWRpYSAoeMyEKSAgICAgICAgICAgICAgID0gJS40ZlxuIiwgbWVkaWEpKQpjYXQoc3ByaW50ZigiU29tYSBkZSBxdWFkcmFkb3MgKFNTKSAgID0gJS40ZlxuIiwgU1MpKQpjYXQoc3ByaW50ZigiYiA9IGE1Kih4NS14MSkrYTQqKHg0LXgyKSA9ICUuNGZcbiIsIGIpKQpjYXQoc3ByaW50ZigiVyBjYWxjdWxhZG8gbWFudWFsbWVudGUgID0gJS40ZlxuIiwgV19tYW51YWwpKQpgYGAKCmBgYHtyIG1hbnVhbC1zdy1kZWNpc2FvfQpXX2NyaXQgPC0gMC43NjIgICMgdmFsb3IgdGFiZWxhZG8gcGFyYSBuPTUsIGFscGhhPTAuMDUKZGVjaXNhb19tYW51YWwgPC0gaWYgKFdfbWFudWFsID4gV19jcml0KSAiTsODTyBzZSByZWplaXRhIEgwIiBlbHNlICJSZWplaXRhLXNlIEgwIgpjYXQoc3ByaW50ZigiVyBjYWxjdWxhZG8gPSAlLjRmIHwgVyBjcsOtdGljbyAobj01LCBhbHBoYT0wLjA1KSA9ICUuM2ZcbiIsIFdfbWFudWFsLCBXX2NyaXQpKQpjYXQoIlJlZ3JhOiByZWplaXRhLXNlIEgwIHNlIFcgPCBXX2NyaXQgIC0+ICBEZWNpc8OjbzoiLCBkZWNpc2FvX21hbnVhbCwgIlxuIikKCnRlc3RlX2NvbmZlcmVuY2lhIDwtIHNoYXBpcm8udGVzdCh4NSkKY2F0KHNwcmludGYoIlxuQ29uZmVyw6puY2lhIChzaGFwaXJvLnRlc3QpOiBXID0gJS40ZiB8IHAtdmFsb3IgPSAlLjRmXG4iLAogICAgICAgICAgICB0ZXN0ZV9jb25mZXJlbmNpYSRzdGF0aXN0aWMsIHRlc3RlX2NvbmZlcmVuY2lhJHAudmFsdWUpKQpgYGAKCioqSW50ZXJwcmV0YcOnw6NvOioqIG8gdmFsb3IgZGUgVyBjYWxjdWxhZG8gbWFudWFsbWVudGUgY29pbmNpZGUgY29tIG8gZGUgYHNoYXBpcm8udGVzdCgpYC4gQ29tbyBXIGVzdMOhICoqYWNpbWEqKiBkbyB2YWxvciBjcsOtdGljbyB0YWJlbGFkbyAoMCw3NjIpIHBhcmEgbj01IGUgzrE9MCwwNSwgKipuw6NvIHJlamVpdGFtb3MgSDAqKiDigJQgY29lcmVudGUgY29tIG8gcmVzdWx0YWRvIGRhIGFtb3N0cmEgY29tcGxldGEgZGUgYFdpbmRgIChuPTE1MyksIG5hIHByw7N4aW1hIHNlw6fDo28uCgojIDkuIEFwbGljYcOnw6NvIGRvIFRlc3RlIChTb2Z0d2FyZSBFc3RhdMOtc3RpY28pCgpBcGxpY2Ftb3Mgb3MgdGVzdGVzIGRlICoqU2hhcGlyby1XaWxrKiogZSAqKktvbG1vZ29yb3YtU21pcm5vdioqIMOgcyBzw6lyaWVzIGNvbXBsZXRhcy4gUGFyYSBvIEtTLCBwYWRyb25pemFtb3Mgb3MgZGFkb3MgKCp6LXNjb3JlKikgYW50ZXMgZGUgY29tcGFyYXIgY29tIGEgTm9ybWFsIHBhZHLDo28gTigwLDEpLgoKYGBge3IgYXBsaWNhY2FvfQphbHBoYSA8LSAwLjA1Cgp0ZXN0YXJfbm9ybWFsaWRhZGUgPC0gZnVuY3Rpb24oc2VyaWUsIG5vbWUpIHsKICBzZXJpZV96IDwtIHNjYWxlKHNlcmllKVssIDFdCiAgc3cgPC0gc2hhcGlyby50ZXN0KHNlcmllKQogIGtzIDwtIGtzLnRlc3Qoc2VyaWVfeiwgInBub3JtIikKICBkYXRhLmZyYW1lKAogICAgVmFyaWF2ZWwgPSBub21lLAogICAgbiA9IGxlbmd0aChzZXJpZSksCiAgICBgU2hhcGlyb19XYCA9IHN3JHN0YXRpc3RpYywKICAgIGBwX3ZhbG9yX1NXYCA9IHN3JHAudmFsdWUsCiAgICBgS1NfRGAgPSBrcyRzdGF0aXN0aWMsCiAgICBgcF92YWxvcl9LU2AgPSBrcyRwLnZhbHVlLAogICAgYERlY2lzYW9fU1dgID0gaWYgKHN3JHAudmFsdWUgPiBhbHBoYSkgIk7Do28gcmVqZWl0YSBIMCIgZWxzZSAiUmVqZWl0YSBIMCIsCiAgICBgRGVjaXNhb19LU2AgPSBpZiAoa3MkcC52YWx1ZSA+IGFscGhhKSAiTsOjbyByZWplaXRhIEgwIiBlbHNlICJSZWplaXRhIEgwIgogICkKfQoKcmVzdWx0YWRvcyA8LSByYmluZCgKICB0ZXN0YXJfbm9ybWFsaWRhZGUod2luZCwgIldpbmQiKSwKICB0ZXN0YXJfbm9ybWFsaWRhZGUob3pvbmUsICJPem9uZSIpCikKcm93bmFtZXMocmVzdWx0YWRvcykgPC0gTlVMTAprbml0cjo6a2FibGUocmVzdWx0YWRvcywgZGlnaXRzID0gNCkKYGBgCgpFbSBQeXRob24sIG8gcHJvY2VkaW1lbnRvIGVxdWl2YWxlbnRlIGVzdMOhIGVtIGBub3JtYWxpZGFkZS5weWAgKHNjcmlwdCBjb21wbGV0byk6CgpgYGBweXRob24Kc3dfc3RhdCwgc3dfcCA9IHN0YXRzLnNoYXBpcm8oc2VyaWUpCmtzX3N0YXQsIGtzX3AgPSBzdGF0cy5rc3Rlc3Qoc3RhdHMuenNjb3JlKHNlcmllKSwgIm5vcm0iKQpgYGAKCiMgMTAuIFJlc3VsdGFkb3MKCiMjIyAxMC4xIE3DqXRvZG8gZG8gcC12YWxvcgoKLSAqKldpbmQ6KiogcChTVykgPiAwLDA1IGUgcChLUykgPiAwLDA1ICDihpIgICoqbsOjbyBzZSByZWplaXRhIEgwKiog4oCUIGNvbXBhdMOtdmVsIGNvbSBOb3JtYWwuCi0gKipPem9uZToqKiBwKFNXKSDiiaQgMCwwNSBlIHAoS1MpIOKJpCAwLDA1ICDihpIgICoqcmVqZWl0YS1zZSBIMCoqIOKAlCBuw6NvIGNvbXBhdMOtdmVsIGNvbSBOb3JtYWwuCgojIyMgMTAuMiBNw6l0b2RvIGRvIHZhbG9yIGNyw610aWNvIChpbHVzdHJhw6fDo28pCgpQYXJhIGFtb3N0cmFzIGdyYW5kZXMgKG49MTUzIGUgbj0xMTYpLCBvIG3DqXRvZG8gZG8gcC12YWxvciDDqSBvIG1haXMgcHLDoXRpY287IG8gbcOpdG9kbyBkbyB2YWxvciBjcsOtdGljbyBmb2kgZGVtb25zdHJhZG8gbmEgU2XDp8OjbyA4IHBhcmEgbj01LiBPcyBkb2lzIG3DqXRvZG9zIHPDo28gZXF1aXZhbGVudGVzIGUgbGV2YW0gw6AgbWVzbWEgZGVjaXPDo28uCgojIDExLiBWaXN1YWxpemHDp8O1ZXMgR3LDoWZpY2FzCgpgYGB7ciBwYWluZWwtd2luZCwgZmlnLndpZHRoPTEzLCBmaWcuaGVpZ2h0PTR9CnBhcihtZnJvdyA9IGMoMSwgMykpCmhpc3Qod2luZCwgbWFpbiA9ICJIaXN0b2dyYW1hIOKAlCBXaW5kIiwgeGxhYiA9ICJtcGgiLCBjb2wgPSAic3RlZWxibHVlIiwgYnJlYWtzID0gMTIpCmJveHBsb3Qod2luZCwgbWFpbiA9ICJCb3hwbG90IOKAlCBXaW5kIiwgeWxhYiA9ICJtcGgiKQpxcW5vcm0od2luZCwgbWFpbiA9ICJRUS1QbG90IOKAlCBXaW5kIikKcXFsaW5lKHdpbmQsIGNvbCA9ICJyZWQiLCBsd2QgPSAyKQpgYGAKCmBgYHtyIHBhaW5lbC1vem9uZSwgZmlnLndpZHRoPTEzLCBmaWcuaGVpZ2h0PTR9CnBhcihtZnJvdyA9IGMoMSwgMykpCmhpc3Qob3pvbmUsIG1haW4gPSAiSGlzdG9ncmFtYSDigJQgT3pvbmUiLCB4bGFiID0gInBwYiIsIGNvbCA9ICJ0b21hdG8iLCBicmVha3MgPSAxMikKYm94cGxvdChvem9uZSwgbWFpbiA9ICJCb3hwbG90IOKAlCBPem9uZSIsIHlsYWIgPSAicHBiIikKcXFub3JtKG96b25lLCBtYWluID0gIlFRLVBsb3Qg4oCUIE96b25lIikKcXFsaW5lKG96b25lLCBjb2wgPSAicmVkIiwgbHdkID0gMikKYGBgCgoqKkxlaXR1cmEgZG9zIFFRLVBsb3RzOioqIGVtIGBXaW5kYCwgb3MgcG9udG9zIHNlZ3VlbSBkZSBwZXJ0byBhIHJldGEgZGUgcmVmZXLDqm5jaWEuIEVtIGBPem9uZWAsIG9zIHBvbnRvcyBzZSBhZmFzdGFtIHNpc3RlbWF0aWNhbWVudGUgZGEgcmV0YSBuYXMgZXh0cmVtaWRhZGVzLCByZXZlbGFuZG8gdmlzdWFsbWVudGUgYSBhc3NpbWV0cmlhIHF1YW50aWZpY2FkYSBwZWxvcyB0ZXN0ZXMgZm9ybWFpcy4KCiMgMTIuIERpc2N1c3PDo28KCi0gT3MgZG9pcyB0ZXN0ZXMgKipjb25jb3JkYW0qKiBuYSBkZWNpc8OjbyBmaW5hbCBwYXJhIGFtYmFzIGFzIHZhcmnDoXZlaXMsIG1hcyAqKmRpc2NvcmRhbSBuYSBtYWduaXR1ZGUgZGEgZXZpZMOqbmNpYSoqOiBwYXJhIGBPem9uZWAsIG8gU2hhcGlyby1XaWxrIHByb2R1eiB1bSBwLXZhbG9yIGV4dHJlbWFtZW50ZSBwZXF1ZW5vIChvcmRlbSBkZSAxMOKBu+KBuCksIG11aXRvIG1haXMgZXh0cmVtbyBkbyBxdWUgbyBkbyBLb2xtb2dvcm92LVNtaXJub3Yg4oCUIG8gU2hhcGlyby1XaWxrIMOpLCBlbSBnZXJhbCwgbWFpcyBzZW5zw612ZWwgYSBkZXN2aW9zIGRlIG5vcm1hbGlkYWRlLgotIE8gS1MsIGFvIGRlcGVuZGVyIGRhIG1haW9yIGRpc3TDom5jaWEgZW50cmUgY3VydmFzIGFjdW11bGFkYXMsIHRlbmRlIGEgc2VyIG1lbm9zIHNlbnPDrXZlbCBhIGRlc3Zpb3MgbG9jYWxpemFkb3MgKGNhdWRhcyBwZXNhZGFzLCBwb3Vjb3Mgb3V0bGllcnMpLgotIEEgaW5zcGXDp8OjbyBncsOhZmljYSBjb25maXJtb3UgYSBjb25jbHVzw6NvIGRvcyB0ZXN0ZXMgZm9ybWFpcyBlbSBhbWJvcyBvcyBjYXNvcywgcmVmb3LDp2FuZG8gYSByZWNvbWVuZGHDp8OjbyBkZSBzZW1wcmUgY3J1emFyIHRlc3RlIGZvcm1hbCBjb20gZ3LDoWZpY28uCgojIDEzLiBWYW50YWdlbnMgZSBMaW1pdGHDp8O1ZXMgZG9zIFRlc3RlcwoKfCBUZXN0ZSB8IFZhbnRhZ2VucyB8IExpbWl0YcOnw7VlcyB8CnwtLS18LS0tfC0tLXwKfCAqKlNoYXBpcm8tV2lsayoqIHwgTWFpb3IgcG9kZXIgZXN0YXTDrXN0aWNvIGVudHJlIG9zIHRlc3RlcyBjbMOhc3NpY29zLCBlc3BlY2lhbG1lbnRlIHBhcmEgbiBwZXF1ZW5vL23DqWRpbyB8IFNlbnPDrXZlbCBhIG91dGxpZXJzOyBlbSBhbW9zdHJhcyBtdWl0byBncmFuZGVzLCByZWplaXRhIEgwIG1lc21vIHBhcmEgZGVzdmlvcyBzZW0gcmVsZXbDom5jaWEgcHLDoXRpY2EgfAp8ICoqS29sbW9nb3Jvdi1TbWlybm92KiogfCBDb25jZWl0byBnZXJhbCwgYXBsaWPDoXZlbCBhIHF1YWxxdWVyIGRpc3RyaWJ1acOnw6NvIHRlw7NyaWNhIHwgTWVub3Mgc2Vuc8OtdmVsIHF1ZSBvIFNoYXBpcm8tV2lsazsgZXhpZ2UgZGlzdHJpYnVpw6fDo28gdG90YWxtZW50ZSBlc3BlY2lmaWNhZGEgKG1vdGl2b3UgYSBjb3JyZcOnw6NvIGRlIExpbGxpZWZvcnMpIHwKCiMgMTQuIENvbXBhcmHDp8OjbyBjb20gT3V0cm9zIFRlc3RlcyBTZW1lbGhhbnRlcwoKQWzDqW0gZGUgU2hhcGlyby1XaWxrIGUgS29sbW9nb3Jvdi1TbWlybm92LCBhIGxpdGVyYXR1cmEgYXByZXNlbnRhIG91dHJhcyBhbHRlcm5hdGl2YXM6CgotICoqTGlsbGllZm9yczoqKiBjb3JyZcOnw6NvIGRvIEtTIHBhcmEgcXVhbmRvIG3DqWRpYSBlIGRlc3Zpby1wYWRyw6NvIHPDo28gZXN0aW1hZG9zIGRhIHByw7NwcmlhIGFtb3N0cmE7Ci0gKipBbmRlcnNvbi1EYXJsaW5nOioqIGTDoSBtYWlzIHBlc28gw6BzIGNhdWRhcyBkYSBkaXN0cmlidWnDp8OjbywgbWFpcyBzZW5zw612ZWwgYSBvdXRsaWVycyBleHRyZW1vczsKLSAqKkphcnF1ZS1CZXJhIC8gRCdBZ29zdGluby1QZWFyc29uOioqIGJhc2VhZG9zIGVtIGFzc2ltZXRyaWEgZSBjdXJ0b3NlIGFtb3N0cmFpcywgY29tdW5zIGVtIHPDqXJpZXMgZWNvbsO0bWljYXMvZmluYW5jZWlyYXMuCgpgYGB7ciBhbmRlcnNvbi1kYXJsaW5nfQppZiAocmVxdWlyZU5hbWVzcGFjZSgibm9ydGVzdCIsIHF1aWV0bHkgPSBUUlVFKSkgewogIGxpYnJhcnkobm9ydGVzdCkKICBhZF93aW5kICA8LSBhZC50ZXN0KHdpbmQpCiAgYWRfb3pvbmUgPC0gYWQudGVzdChvem9uZSkKICBrbml0cjo6a2FibGUoZGF0YS5mcmFtZSgKICAgIFZhcmlhdmVsID0gYygiV2luZCIsICJPem9uZSIpLAogICAgRXN0YXRpc3RpY2FfQTIgPSBjKGFkX3dpbmQkc3RhdGlzdGljLCBhZF9vem9uZSRzdGF0aXN0aWMpLAogICAgcF92YWxvciA9IGMoYWRfd2luZCRwLnZhbHVlLCBhZF9vem9uZSRwLnZhbHVlKQogICksIGRpZ2l0cyA9IDQpCn0gZWxzZSB7CiAgY2F0KCJQYWNvdGUgJ25vcnRlc3QnIG7Do28gaW5zdGFsYWRvIG5lc3RlIGFtYmllbnRlLiIsCiAgICAgICJQYXJhIHJlcHJvZHV6aXIgYSBjb21wYXJhw6fDo28gY29tIEFuZGVyc29uLURhcmxpbmcsIGV4ZWN1dGU6IiwKICAgICAgImluc3RhbGwucGFja2FnZXMoJ25vcnRlc3QnKSIsIHNlcCA9ICJcbiIpCn0KYGBgCgojIDE1LiBFeGVyY8OtY2lvIEFwbGljYWRvIHBhcmEgRGlzY3Vzc8OjbyBjb20gYSBUdXJtYQoKKipQcm9wb3N0YToqKiB1dGlsaXphbmRvIGEgbWVzbWEgYmFzZSBgYWlycXVhbGl0eWAsIHRlc3RlIGEgbm9ybWFsaWRhZGUgZGEgdmFyacOhdmVsIGBUZW1wYCAodGVtcGVyYXR1cmEgbcOheGltYSBkacOhcmlhKS4KCjEuIFRyYXRlIGV2ZW50dWFpcyB2YWxvcmVzIGF1c2VudGVzOwoyLiBDb25zdHJ1YSBvIGhpc3RvZ3JhbWEsIG8gYm94cGxvdCBlIG8gUVEtUGxvdCBkZSBgVGVtcGA7CjMuIEFwbGlxdWUgb3MgdGVzdGVzIGRlIFNoYXBpcm8tV2lsayBlIEtvbG1vZ29yb3YtU21pcm5vdiBhIM6xID0gMCwwNTsKNC4gQ29tcGFyZSBhIGRlY2lzw6NvIG9idGlkYSBwZWxvcyBkb2lzIHRlc3RlczsKNS4gRGlzY3V0YTogYSBjb25jbHVzw6NvIGRvIHRlc3RlIGZvcm1hbCDDqSBjb2VyZW50ZSBjb20gbyBxdWUgc2Ugb2JzZXJ2YSBub3MgZ3LDoWZpY29zPwoKYGBge3IgZXhlcmNpY2lvfQp0ZW1wIDwtIG5hLm9taXQoYWlycXVhbGl0eSRUZW1wKQp0ZXN0YXJfbm9ybWFsaWRhZGUodGVtcCwgIlRlbXAiKQpgYGAKCiMgMTYuIENvbmNsdXPDo28KCkNvbSBiYXNlIG5vcyB0ZXN0ZXMgZGUgKipTaGFwaXJvLVdpbGsqKiBlICoqS29sbW9nb3Jvdi1TbWlybm92KiosIGNvbXBsZW1lbnRhZG9zIHBlbGEgaW5zcGXDp8OjbyBncsOhZmljYSwgY29uY2x1w61tb3MgcXVlOgoKLSBBIHZhcmnDoXZlbCAqKmBXaW5kYCoqIMOpIGVzdGF0aXN0aWNhbWVudGUgKipjb21wYXTDrXZlbCBjb20gYSBkaXN0cmlidWnDp8OjbyBOb3JtYWwqKiAocCA+IDAsMDUgZW0gYW1ib3Mgb3MgdGVzdGVzKSwgdGFudG8gbmEgYW1vc3RyYSBjb21wbGV0YSAobj0xNTMpIHF1YW50byBubyBleGVtcGxvIG1hbnVhbCAobj01KTsKLSBBIHZhcmnDoXZlbCAqKmBPem9uZWAqKiAqKm7Do28gw6kgY29tcGF0w612ZWwqKiBjb20gYSBkaXN0cmlidWnDp8OjbyBOb3JtYWwgKHAg4omkIDAsMDUgZW0gYW1ib3Mgb3MgdGVzdGVzKSwgY29tIGV2aWTDqm5jaWEgZm9ydMOtc3NpbWEgbm8gU2hhcGlyby1XaWxrOwotIE9zIHJlc3VsdGFkb3Mgb2J0aWRvcyBlbSAqKlIqKiBlIGVtICoqUHl0aG9uKiogKGBub3JtYWxpZGFkZS5weWApIGNvaW5jaWRlbSwgdmFsaWRhbmRvIGEgaW1wbGVtZW50YcOnw6NvIGNvbXB1dGFjaW9uYWwgZW0gYW1iYXMgYXMgbGluZ3VhZ2VuczsKLSBRdWFuZG8gYSBub3JtYWxpZGFkZSBuw6NvIHNlIGNvbmZpcm1hIOKAlCBjb21vIGVtIGBPem9uZWAg4oCUIGFzIGFsdGVybmF0aXZhcyBtZXRvZG9sw7NnaWNhcyBpbmNsdWVtOiAoaSkgdHJhbnNmb3JtYcOnw6NvIGRhIHZhcmnDoXZlbCAobG9nLCBCb3gtQ294KSwgKGlpKSB1c28gZGUgdGVzdGVzIG7Do28tcGFyYW3DqXRyaWNvcyBlcXVpdmFsZW50ZXMsIChpaWkpIGFwb2lvIG5vIFRlb3JlbWEgQ2VudHJhbCBkbyBMaW1pdGUgcXVhbmRvIGEgYW1vc3RyYSDDqSBzdWZpY2llbnRlbWVudGUgZ3JhbmRlLCBvdSAoaXYpIG3DqXRvZG9zIHJvYnVzdG9zL2Jvb3RzdHJhcC4KCiMgMTcuIFJlZmVyw6puY2lhcwoKLSBCVVNTQUIsIFcuIE8uOyBNT1JFVFRJTiwgUC4gQS4gKkVzdGF0w61zdGljYSBCw6FzaWNhKi4gU8OjbyBQYXVsbzogU2FyYWl2YS4KLSBNT05UR09NRVJZLCBELiBDLjsgUlVOR0VSLCBHLiBDLiAqRXN0YXTDrXN0aWNhIEFwbGljYWRhIGUgUHJvYmFiaWxpZGFkZSBwYXJhIEVuZ2VuaGVpcm9zKi4gUmlvIGRlIEphbmVpcm86IExUQy4KLSBQQUdBTk8sIE0uOyBHQVVWUkVBVSwgSy4gKlByaW5jw61waW9zIGRlIEJpb2VzdGF0w61zdGljYSouIFPDo28gUGF1bG86IENlbmdhZ2UgTGVhcm5pbmcuCi0gQ09OT1ZFUiwgVy4gSi4gKlByYWN0aWNhbCBOb25wYXJhbWV0cmljIFN0YXRpc3RpY3MqLiBOZXcgWW9yazogV2lsZXkuCi0gSE9MTEFOREVSLCBNLjsgV09MRkUsIEQuIEEuICpOb25wYXJhbWV0cmljIFN0YXRpc3RpY2FsIE1ldGhvZHMqLiBOZXcgWW9yazogV2lsZXkuCi0gU0hBUElSTywgUy4gUy47IFdJTEssIE0uIEIuIEFuIGFuYWx5c2lzIG9mIHZhcmlhbmNlIHRlc3QgZm9yIG5vcm1hbGl0eSAoY29tcGxldGUgc2FtcGxlcykuICpCaW9tZXRyaWthKiwgdi4gNTIsIG4uIDMvNCwgcC4gNTkx4oCTNjExLCAxOTY1LgotIE1BU1NFWSBKUi4sIEYuIEouIFRoZSBLb2xtb2dvcm92LVNtaXJub3YgdGVzdCBmb3IgZ29vZG5lc3Mgb2YgZml0LiAqSm91cm5hbCBvZiB0aGUgQW1lcmljYW4gU3RhdGlzdGljYWwgQXNzb2NpYXRpb24qLCB2LiA0Niwgbi4gMjUzLCBwLiA2OOKAkzc4LCAxOTUxLgotIFIgQ09SRSBURUFNLiAqUjogQSBMYW5ndWFnZSBhbmQgRW52aXJvbm1lbnQgZm9yIFN0YXRpc3RpY2FsIENvbXB1dGluZyouIERvY3VtZW50YcOnw6NvIGRlIGBzaGFwaXJvLnRlc3QoKWAsIGBrcy50ZXN0KClgLCBgcXFub3JtKClgLCBgcXFsaW5lKClgLgoKLS0tCgoqKkFycXVpdm9zIGNvbXBsZW1lbnRhcmVzIGRlc3RlIHNlbWluw6FyaW8gKG1lc21hIHBhc3RhKToqKiBgbm9ybWFsaWRhZGUuUmAsIGBub3JtYWxpZGFkZS5weWA=