A análise das séries temporais de temperatura máxima diária é
fundamental na meteorologia e em várias áreas decisivas, da agricultura
ao planejamento urbano. O Instituto Nacional de Meteorologia (INMET)
disponibiliza uma vasta quantidade de informações coletadas
automaticamente por estações meteorológicas em todo o país,
proporcionando uma valiosa fonte de dados para estudos e análises.
Neste trabalho, focamos na análise da estação meteorológica de Porto
Alegre (RS), abrangendo os útlimos 11 anos, mas excluindo os dados de
2023 para validação do modelo, ou seja, os modelos foram feitos
utilizando os dados de temperatura máxima de Porto Alegre entre 2012 e
2022. Essa análise é de grande importância para compreender e prever
variações climáticas, sendo relevante na agricultura, gestão de recursos
hídricos, segurança pública, turismo, etc. Usaremos técnicas de análise
de séries temporais e modelos de previsão para ajustar dados até o final
de 2022, e avaliaremos sua precisão prevendo os dados até 31/07/2023 e
comparando com os dados já observados. Dessa forma, buscamos aplicar as
metodologias estudadas na disciplina de séries temporais contribuindo
para o entendimento das tendências climáticas locais e aprimorar a
capacidade de prever as variações nas temperaturas máximas diárias, com
potenciais aplicações em diversas áreas.
No gráfico abaixo, temos a série temporal da temperatura máxima
diária (°C) na cidade de Porto Alegre (RS) de \(01/01/2012\) até \(30/07/2023\). Em uma primeira análise, a
série aparenta ter um comportamento estacionário e uma sazonalidade
anual com 11 “ciclos” bem definidos ao longo dos 11 anos analisados.
Para reforçar essas constatações, iremos analisar a função de
autocorrelação (ACF), a função de autocorrelação parcial (ACF) e a série
decomposta.
Pelo gráfico da função de autocorrelação gerado, podemos visualizar
os padrões sazonais na série, com picos significativos na ACF em
intervalos regulares. Além disso, temos fortes indícios da presença de
componentes autoregressivos (AR).
Já com o gráfico da função de autocorrelação parcial (PACF), podemos
visualizar que não há lags significativos na PACF após os 100 primeiros
lags aproximadamente, indicando que a série não possui dependência de
longo prazo. No entanto, a presença de lags significativos no início da
série e em direções diferentes nos dão indícios da presença de
componente de média móvel (MA) e a necessidade de modelos AR de
diferentes ordens em partes diferentes da série.
Abaixo, o gráfico mostra os seguintes componentes:
Série Temporal Original: A série temporal bruta,
que inclui tendência, sazonalidade e erro.
Tendência: A componente de tendência, que
representa a direção geral do comportamento da série ao longo do
tempo.
Sazonalidade: A componente sazonal, que
representa os padrões que se repetem em intervalos regulares, como
sazonalidade anual, mensal, etc.
Erro (Resíduos): A componente de erro, que
representa o que resta na série após a remoção da tendência e da
sazonalidade.

Metodologia
Teste de Raíz Unitária
Antes de partirmos para a modelagem da série, iremos realizar o teste
Teste de Dickey-Fuller Aumentado (ADF), utilizado para avaliar se a
série temporal é realmente estacionária ou não estacionária.
##
## Augmented Dickey-Fuller Test
##
## data: treino
## Dickey-Fuller = -5.7667, Lag order = 15, p-value = 0.01
## alternative hypothesis: stationary
Pelo resultado acima podemos ver que o \(p.valor < 0.05\), ou seja, a um nível de
significância de 5%, rejeitamos a hipótese nula. Portando, concluímos
que há evidências de que a série seja estacionária, estando também de
acordo com os resultados das análises gráficas realizadas
anteriormente.
Modelo 1 - ARIMA(1,0,3)
Para modelar séries temporais com componentes sazonais, utilizamos
modelos ARIMA sazonais, conhecidos como SARIMA (Seasonal AutoRegressive
Integrated Moving Average). Um modelo SARIMA é uma extensão do ARIMA que
incorpora termos sazonais para capturar a variação sazonal nos
dados.
O SARIMA é denotado como \(SARIMA(p, d,
q)(P, D, Q)\), onde:
- “p”: é a ordem do componente AR não sazonal.
- “d”: é a ordem de integração não sazonal.
- “q”: é a ordem do componente MA não sazonal.
- “P”: é a ordem do componente AR sazonal.
- “D”: é a ordem de integração sazonal.
- “Q”: é a ordem do componente MA sazonal.
No software R, utilizamos a função \(auto.arima()\) que automatiza o processo de
seleção do modelo ARIMA. Ela explora várias combinações de parâmetros p
(ordem do componente AR), d (ordem de integração) e q (ordem do
componente MA) e fornece o modelo ARIMA com o menor valor de AIC ou BIC
como o melhor modelo. Após identificar possíveis modelos ARIMA não
sazonais, utilizando o parâmetro \(seazonal=TRUE\), o algoritmo então estende
a busca para modelos SARIMA, que incluem componentes sazonais (P, D, Q,
s) além dos componentes não sazonais. Ele ajusta modelos SARIMA com
diferentes valores de P (AR sazonal), D (integração sazonal), Q (MA
sazonal) e s (período da sazonalidade) e calcula os critérios de
informação para cada modelo.
Para ajustar o modelo, utilizamos apenas os dados até 2022 (no qual
chamamos de “treino”) para então fazer a previsão até os dias atuais (a
qual chamamos de “teste”).
model1 <- auto.arima(treino, seasonal = TRUE)
summary(model1)
## Series: treino
## ARIMA(1,0,3) with non-zero mean
##
## Coefficients:
## ar1 ma1 ma2 ma3 mean
## 0.9899 -0.2715 -0.3643 -0.175 25.7374
## s.e. 0.0027 0.0155 0.0164 0.015 0.9371
##
## sigma^2 = 10.6: log likelihood = -10437.78
## AIC=20887.56 AICc=20887.58 BIC=20925.34
##
## Training set error measures:
## ME RMSE MAE MPE MAPE MASE
## Training set 0.002761661 3.254056 2.566752 -1.981664 10.87387 0.5666404
## ACF1
## Training set 0.01244031
O modelo pode ser definido como,
\[X_t = c + \phi X_{t-1} + \theta
\epsilon_{t-1} + \theta \epsilon_{t-2} + \theta \epsilon_{t-3} +
\epsilon\]
em que os parâmetros encontrados foram,
\[X_t = 25.74 + 0.99 X_{t-1} -0.27
\epsilon_{t-1} -0.36 \epsilon_{t-2} -0.17 \epsilon_{t-3} +
\epsilon\]
Fazendo o forecast (previsão) do modelo para os dias atuais
temos:
No entanto, para validarmos o modelo, precisamos antes verificar se
os resíduos não são autocorrelacionados a partir da análise da função de
autocorrelação dos resíduos e do teste Ljung-Box:
##
## Box-Ljung test
##
## data: forecasted$residuals
## X-squared = 34.597, df = 20, p-value = 0.02236
O correlograma mostra que as autocorrelações para os erros de
previsão praticamente não excedem os limites de significância para
defasagens 1-20. Além disso, o p-valor para o teste Ljung-Box é \(0.02236\) indicando que não há muita
evidência de autocorrelações diferentes de zero nas defasagens 1-20.
Portanto, podemos concluir que os resíduos não são
autocorrelacionados.
Ademais, outro passo para verificar se o modelo preditivo pode ser
melhorado é investigar se os erros de previsão são normalmente
distribuídos com média zero e variância constante.
O teste Ljung-Box não revela evidências suficientes de que exista
autocorrelações diferentes de zero nos erros de previsão na amostra, as
variações nos erros de previsão parecem aproximadamente constantes e os
erros de previsão parecem distribuídos normalmente. Portanto, podemos
concluir que o modelo ARIMA(1,0,3) é um modelo
válido.
Modelo 2 - SARIMA(3,0,0)(0,1,0)[365]
Apesar do modelo anterior ter sido considerado válido e com uma
acurácia significativa ao ajuste dos dados de treino, podemos perceber
que mesmo com o parâmetro \(seazonal=TRUE\) a função auto.arima() não
indicou componentes sazonais que havíamos verificado que estão presentes
na série nas etapas anteriores. Portanto, neste modelo iremos utilizar o
parâmetro \(D=1\), indicando que se
deseja aplicar uma diferenciação sazonal de primeira ordem à série
temporal. Isso significa que, em cada período sazonal, os valores da
série serão subtraídos dos valores do período sazonal anterior para
remover a sazonalidade.
model2 <- auto.arima(treino, D = 1)
summary(model2)
## Series: treino
## ARIMA(3,0,0)(0,1,0)[365]
##
## Coefficients:
## ar1 ar2 ar3
## 0.7051 -0.1854 0.0507
## s.e. 0.0165 0.0200 0.0165
##
## sigma^2 = 19.94: log likelihood = -10642.58
## AIC=21293.16 AICc=21293.18 BIC=21317.98
##
## Training set error measures:
## ME RMSE MAE MPE MAPE MASE
## Training set -0.03650731 4.255992 3.212511 -1.85509 13.57526 0.7091991
## ACF1
## Training set -0.001597896
O modelo pode ser definido como,
\[\nabla_{365}X_t = \phi X_{t-1} + \phi
X_{t-2} + \phi X_{t-3} + \epsilon\]
em que os parâmetros encontrados foram
\[\nabla_{365}X_t = 0.71 X_{t-1} -0.19
X_{t-2} + 0.05 X_{t-3} + \epsilon\]
Fazendo o forecast (previsão) do modelo para os dias atuais
temos:
Assim como feito anteriormento, iremos verificar se o novo modelo é
válido,
##
## Box-Ljung test
##
## data: forecasted2$residuals
## X-squared = 33.538, df = 20, p-value = 0.02943
O correlograma mostra que as autocorrelações para os erros de
previsão praticamente não excedem os limites de significância para
defasagens 1-20. Além disso, o p-valor para o teste Ljung-Box é \(0.02943\) indicando que não há muita
evidência de autocorrelações diferentes de zero nas defasagens 1-20.
Portanto, podemos concluir que os resíduos não são
autocorrelacionados.
Além disso, os erros de previsão têm variância constante ao longo do
tempo e são normalmente distribuídos com média zero
Portanto, podemos concluir que o modelo SARIMA(3,0,0)(0,1,0)[365]
também é válido.
|
|
Modelo.1
|
Modelo.2
|
|
AIC
|
20887.56
|
21293.16
|
Portanto, encontramos que os dois modelos gerados são válidos. Pelo
AIC, podemos ver que o menor deles é o Modelo 1, indicando que este
teria um melhor ajuste aos dados. No entanto, o gráfico evidencia que o
Modelo 2 teve um desempenho muito mais acurado ao compararmos as médias
dos valores preditos.
LS0tDQp0aXRsZTogIkFuw6FsaXNlIGRlIFPDqXJpZXMgVGVtcG9yYWlzIC0gVHJhYmFsaG8gRmluYWwiDQpzdWJ0aXRsZTogIk1vZGVsYWdlbSBkYSBUZW1wZXJhdHVyYSBNw6F4aW1hIGRlIFBvcnRvIEFsZWdyZSAoUlMpIg0KYXV0aG9yOiAiSm/Do28gTC4gU2ltb24iDQpvdXRwdXQ6DQogIGh0bWxfZG9jdW1lbnQ6DQogICAgY29kZV9kb3dubG9hZDogdHJ1ZQ0KICAgIHRoZW1lOiBmbGF0bHkNCiAgICB0b2M6IHRydWUNCiAgICB0b2NfZGVwdGg6IDMNCiAgICB0b2NfZmxvYXQ6DQogICAgICBjb2xsYXBzZWQ6IHRydWUNCiAgICAgIHNtb290aF9zY3JvbGw6IHRydWUNCi0tLQ0KDQpgYGB7ciBzZXR1cCwgaW5jbHVkZT1GQUxTRSwgd2FybmluZz1GQUxTRSwgZWNobz1GQUxTRX0NCmtuaXRyOjpvcHRzX2NodW5rJHNldChlY2hvID0gRkFMU0UpDQpsaWJyYXJ5KGdncGxvdDIpDQpsaWJyYXJ5KGRwbHlyKQ0KbGlicmFyeShwbG90bHkpDQpsaWJyYXJ5KGhyYnJ0aGVtZXMpDQpsaWJyYXJ5KHpvbykNCmxpYnJhcnkoZm9yZWNhc3QpDQpsaWJyYXJ5KHRzZXJpZXMpDQpsaWJyYXJ5KGx1YnJpZGF0ZSkNCmxpYnJhcnkoaGlnaGNoYXJ0ZXIpDQpsaWJyYXJ5KHRpZHl2ZXJzZSkNCmxpYnJhcnkoa2FibGVFeHRyYSkNCmBgYA0KDQpgYGB7cn0NCmRmMTIgPC0gcmVhZC5jc3YoIklOTUVUX1NfUlNfQTgwMV9QT1JUTyBBTEVHUkVfMDEtMDEtMjAxMl9BXzMxLTEyLTIwMTIuY3N2Iiwgc2VwID0gIjsiLCBza2lwID0gOSwgaGVhZGVyID0gRikNCmRmMTMgPC0gcmVhZC5jc3YoIklOTUVUX1NfUlNfQTgwMV9QT1JUTyBBTEVHUkVfMDEtMDEtMjAxM19BXzMxLTEyLTIwMTMuY3N2Iiwgc2VwID0gIjsiLCBza2lwID0gOSwgaGVhZGVyID0gRikNCmRmMTQgPC0gcmVhZC5jc3YoIklOTUVUX1NfUlNfQTgwMV9QT1JUTyBBTEVHUkVfMDEtMDEtMjAxNF9BXzMxLTEyLTIwMTQuY3N2Iiwgc2VwID0gIjsiLCBza2lwID0gOSwgaGVhZGVyID0gRikNCmRmMTUgPC0gcmVhZC5jc3YoIklOTUVUX1NfUlNfQTgwMV9QT1JUTyBBTEVHUkVfMDEtMDEtMjAxNV9BXzMxLTEyLTIwMTUuY3N2Iiwgc2VwID0gIjsiLCBza2lwID0gOSwgaGVhZGVyID0gRikNCmRmMTYgPC0gcmVhZC5jc3YoIklOTUVUX1NfUlNfQTgwMV9QT1JUTyBBTEVHUkVfMDEtMDEtMjAxNl9BXzMxLTEyLTIwMTYuY3N2Iiwgc2VwID0gIjsiLCBza2lwID0gOSwgaGVhZGVyID0gRikNCmRmMTcgPC0gcmVhZC5jc3YoIklOTUVUX1NfUlNfQTgwMV9QT1JUTyBBTEVHUkVfMDEtMDEtMjAxN19BXzMxLTEyLTIwMTcuY3N2Iiwgc2VwID0gIjsiLCBza2lwID0gOSwgaGVhZGVyID0gRikNCmRmMTggPC0gcmVhZC5jc3YoIklOTUVUX1NfUlNfQTgwMV9QT1JUTyBBTEVHUkVfMDEtMDEtMjAxOF9BXzMxLTEyLTIwMTguY3N2Iiwgc2VwID0gIjsiLCBza2lwID0gOSwgaGVhZGVyID0gRikNCmRmMTkgPC0gcmVhZC5jc3YoIklOTUVUX1NfUlNfQTgwMV9QT1JUTyBBTEVHUkVfMDEtMDEtMjAxOV9BXzMxLTEyLTIwMTkuY3N2Iiwgc2VwID0gIjsiLCBza2lwID0gOSwgaGVhZGVyID0gRikNCmRmMjAgPC0gcmVhZC5jc3YoIklOTUVUX1NfUlNfQTgwMV9QT1JUTyBBTEVHUkVfMDEtMDEtMjAyMF9BXzMxLTEyLTIwMjAuY3N2Iiwgc2VwID0gIjsiLCBza2lwID0gOSwgaGVhZGVyID0gRikNCmRmMjEgPC0gcmVhZC5jc3YoIklOTUVUX1NfUlNfQTgwMV9QT1JUTyBBTEVHUkVfMDEtMDEtMjAyMV9BXzMxLTEyLTIwMjEuY3N2Iiwgc2VwID0gIjsiLCBza2lwID0gOSwgaGVhZGVyID0gRikNCmRmMjIgPC0gcmVhZC5jc3YoIklOTUVUX1NfUlNfQTgwMV9QT1JUTyBBTEVHUkUgLSBKQVJESU0gQk9UQU5JQ09fMDEtMDEtMjAyMl9BXzMxLTEyLTIwMjIuY3N2Iiwgc2VwID0gIjsiLCBza2lwID0gOSwgaGVhZGVyID0gRikNCmRmMjMgPC0gcmVhZC5jc3YoIklOTUVUX1NfUlNfQTgwMV9QT1JUTyBBTEVHUkUgLSBKQVJESU0gQk9UQU5JQ09fMDEtMDEtMjAyM19BXzMxLTA3LTIwMjMuY3N2Iiwgc2VwID0gIjsiLCBza2lwID0gOSwgaGVhZGVyID0gRikNCg0KZGZfdG90YWwgPC0gcmJpbmQoZGYxMiwgZGYxMywgZGYxNCwgZGYxNSwgZGYxNiwgZGYxNywgZGYxOCwgZGYxOSwgZGYyMCwgZGYyMSwgZGYyMiwgZGYyMykgIyBqdW50YWRvIHRvZG9zIG9zIGRhdGFmcmFtZXMNCmRmX3RvdGFsIDwtIGRmX3RvdGFsICU+JSBzZWxlY3QoVjEsIFYxMCkgIyBzZWxlY2lvbmFuZG8gYXBlbmFzIGFzIHZhcmlhdmVpcyBEQVRBIGUgVEVNUEVSQVRVUkEgTUFYDQpjb2xuYW1lcyhkZl90b3RhbCkgPC0gYygnRGF0YScsICdUZW1wZXJhdHVyYScpICMgbXVkYW5kbyBvIG5vbWUgZGFzIGNvbHVuYXMNCmRmX3RvdGFsJFRlbXBlcmF0dXJhIDwtIGFzLm51bWVyaWMoZ3N1YigiLCIsICIuIiwgZGZfdG90YWwkVGVtcGVyYXR1cmEpKSAjIHN1YnN0aXR1aW5kbyAsIHBvciAuIHBhcmEgYSB2YXJpYXZlbCBmaWNhciBudW1lcmljYQ0KDQpkZl90b3RhbCA8LSBkZl90b3RhbCAlPiUgDQogIGdyb3VwX2J5KERhdGEpICU+JSANCiAgc3VtbWFyaXNlKFRlbXBlcmF0dXJhX01heCA9IG1heChUZW1wZXJhdHVyYSkpICMgcGVnYW5kbyBhcGVuYXMgYSB0ZW1wZXJhdHVyYSBtYXjDrW1hIGRlIGNhZGEgZGlhDQoNCg0KZGZfdG90YWwkRGF0YSA8LSBsdWJyaWRhdGU6OnltZChkZl90b3RhbCREYXRhKSAjIGRlaXhhbmRvIGEgdmFyaWF2ZWwgbm8gZm9ybWF0byBEQVRBKCV5ICVtICVkKQ0KDQpkZl90b3RhbCA8LSBkZl90b3RhbCAlPiUNCiAgbXV0YXRlKFRlbXBlcmF0dXJhX01heCA9IGlmZWxzZShUZW1wZXJhdHVyYV9NYXggPCAtMTAwMCwgTkEsIFRlbXBlcmF0dXJhX01heCkpICMgcmVtb3ZlbmRvIG91dGxpZXJzDQoNCmRmX3RvdGFsJFRlbXBlcmF0dXJhX01heCA8LSBuYS5sb2NmKGRmX3RvdGFsJFRlbXBlcmF0dXJhX01heCwgbmEucm0gPSBGQUxTRSkgIyBsYXN0IG9ic2VydmF0aW9uIGNhcnJpZWQgZm9yd2FyZCAoTkEncyBwcmVlbmNoaWRvcyBjb20gYSBvYnNlcnZhw6fDo28gYW50ZXJpb3IgYSBjYWRhIHVtIGRlbGVzKQ0KDQoNCnRyZWlubzEgPC0gZGZfdG90YWwgJT4lIGZpbHRlcih5ZWFyKERhdGEpIDwgMjAyMykgDQoNCnRlc3RlMSA8LSAgZGZfdG90YWwgJT4lIGZpbHRlcih5ZWFyKERhdGEpID09IDIwMjMpDQpgYGANCg0KYGBge2NzcywgZWNobz1GQUxTRX0NCi5jZW50ZXIgew0KICBkaXNwbGF5OiB0YWJsZTsNCiAgbWFyZ2luLXJpZ2h0OiBhdXRvOw0KICBtYXJnaW4tbGVmdDogYXV0bzsNCn0NCmBgYA0KDQpgYGB7PWh0bWx9DQo8c3R5bGU+DQpib2R5IHsNCnRleHQtYWxpZ246IGp1c3RpZnl9DQo8L3N0eWxlPg0KYGBgDQoNCjxicj48YnI+DQoNCjxkaXYgY2xhc3M9InBhbmVsIHBhbmVsLWRlZmF1bHQiPg0KICA8ZGl2IGNsYXNzPSJwYW5lbC1oZWFkaW5nIj4gDQoNCiMgSW50cm9kdcOnw6NvDQoNCjwvZGl2Pg0KPC9kaXY+DQoNCkEgYW7DoWxpc2UgZGFzIHPDqXJpZXMgdGVtcG9yYWlzIGRlIHRlbXBlcmF0dXJhIG3DoXhpbWEgZGnDoXJpYSDDqSBmdW5kYW1lbnRhbCBuYSBtZXRlb3JvbG9naWEgZSBlbSB2w6FyaWFzIMOhcmVhcyBkZWNpc2l2YXMsIGRhIGFncmljdWx0dXJhIGFvIHBsYW5lamFtZW50byB1cmJhbm8uIE8gSW5zdGl0dXRvIE5hY2lvbmFsIGRlIE1ldGVvcm9sb2dpYSAoSU5NRVQpIGRpc3BvbmliaWxpemEgdW1hIHZhc3RhIHF1YW50aWRhZGUgZGUgaW5mb3JtYcOnw7VlcyBjb2xldGFkYXMgYXV0b21hdGljYW1lbnRlIHBvciBlc3Rhw6fDtWVzIG1ldGVvcm9sw7NnaWNhcyBlbSB0b2RvIG8gcGHDrXMsIHByb3BvcmNpb25hbmRvIHVtYSB2YWxpb3NhIGZvbnRlIGRlIGRhZG9zIHBhcmEgZXN0dWRvcyBlIGFuw6FsaXNlcy4NCg0KTmVzdGUgdHJhYmFsaG8sIGZvY2Ftb3MgbmEgYW7DoWxpc2UgZGEgZXN0YcOnw6NvIG1ldGVvcm9sw7NnaWNhIGRlIFBvcnRvIEFsZWdyZSAoUlMpLCBhYnJhbmdlbmRvIG9zIMO6dGxpbW9zIDExIGFub3MsIG1hcyBleGNsdWluZG8gb3MgZGFkb3MgZGUgMjAyMyBwYXJhIHZhbGlkYcOnw6NvIGRvIG1vZGVsbywgb3Ugc2VqYSwgb3MgbW9kZWxvcyBmb3JhbSBmZWl0b3MgdXRpbGl6YW5kbyBvcyBkYWRvcyBkZSB0ZW1wZXJhdHVyYSBtw6F4aW1hIGRlIFBvcnRvIEFsZWdyZSBlbnRyZSAyMDEyIGUgMjAyMi4gRXNzYSBhbsOhbGlzZSDDqSBkZSBncmFuZGUgaW1wb3J0w6JuY2lhIHBhcmEgY29tcHJlZW5kZXIgZSBwcmV2ZXIgdmFyaWHDp8O1ZXMgY2xpbcOhdGljYXMsIHNlbmRvIHJlbGV2YW50ZSBuYSBhZ3JpY3VsdHVyYSwgZ2VzdMOjbyBkZSByZWN1cnNvcyBow61kcmljb3MsIHNlZ3VyYW7Dp2EgcMO6YmxpY2EsIHR1cmlzbW8sIGV0Yy4gVXNhcmVtb3MgdMOpY25pY2FzIGRlIGFuw6FsaXNlIGRlIHPDqXJpZXMgdGVtcG9yYWlzIGUgbW9kZWxvcyBkZSBwcmV2aXPDo28gcGFyYSBhanVzdGFyIGRhZG9zIGF0w6kgbyBmaW5hbCBkZSAyMDIyLCBlIGF2YWxpYXJlbW9zIHN1YSBwcmVjaXPDo28gcHJldmVuZG8gb3MgZGFkb3MgYXTDqSAzMS8wNy8yMDIzIGUgY29tcGFyYW5kbyBjb20gb3MgZGFkb3MgasOhIG9ic2VydmFkb3MuIERlc3NhIGZvcm1hLCBidXNjYW1vcyBhcGxpY2FyIGFzIG1ldG9kb2xvZ2lhcyBlc3R1ZGFkYXMgbmEgZGlzY2lwbGluYSBkZSBzw6lyaWVzIHRlbXBvcmFpcyBjb250cmlidWluZG8gcGFyYSBvIGVudGVuZGltZW50byBkYXMgdGVuZMOqbmNpYXMgY2xpbcOhdGljYXMgbG9jYWlzIGUgYXByaW1vcmFyIGEgY2FwYWNpZGFkZSBkZSBwcmV2ZXIgYXMgdmFyaWHDp8O1ZXMgbmFzIHRlbXBlcmF0dXJhcyBtw6F4aW1hcyBkacOhcmlhcywgY29tIHBvdGVuY2lhaXMgYXBsaWNhw6fDtWVzIGVtIGRpdmVyc2FzIMOhcmVhcy4NCg0KPGJyPjxicj4NCg0KPGRpdiBjbGFzcz0icGFuZWwgcGFuZWwtZGVmYXVsdCI+DQogIDxkaXYgY2xhc3M9InBhbmVsLWhlYWRpbmciPiANCiAgDQojIEFuw6FsaXNlIERlc2NyaXRpdmENCg0KPC9kaXY+DQo8L2Rpdj4NCg0KTm8gZ3LDoWZpY28gYWJhaXhvLCB0ZW1vcyBhIHPDqXJpZSB0ZW1wb3JhbCBkYSB0ZW1wZXJhdHVyYSBtw6F4aW1hIGRpw6FyaWEgKMKwQykgbmEgY2lkYWRlIGRlIFBvcnRvIEFsZWdyZSAoUlMpIGRlICQwMS8wMS8yMDEyJCBhdMOpICQzMC8wNy8yMDIzJC4gRW0gdW1hIHByaW1laXJhIGFuw6FsaXNlLCBhIHPDqXJpZSBhcGFyZW50YSB0ZXIgdW0gY29tcG9ydGFtZW50byBlc3RhY2lvbsOhcmlvIGUgdW1hIHNhem9uYWxpZGFkZSBhbnVhbCBjb20gMTEgImNpY2xvcyIgYmVtIGRlZmluaWRvcyBhbyBsb25nbyBkb3MgMTEgYW5vcyBhbmFsaXNhZG9zLiBQYXJhIHJlZm9yw6dhciBlc3NhcyBjb25zdGF0YcOnw7VlcywgaXJlbW9zIGFuYWxpc2FyIGEgZnVuw6fDo28gZGUgYXV0b2NvcnJlbGHDp8OjbyAoQUNGKSwgYSBmdW7Dp8OjbyBkZSBhdXRvY29ycmVsYcOnw6NvIHBhcmNpYWwgKEFDRikgZSBhIHPDqXJpZSBkZWNvbXBvc3RhLg0KDQo8ZGl2IGNsYXNzID0gJ2NlbnRlcic+DQpgYGB7cn0NCmhpZ2hjaGFydCh0eXBlID0gInN0b2NrIikgJT4lDQogIGhjX3RpdGxlKHRleHQgPSAiVGVtcGVyYXR1cmEgTcOheGltYSBEacOhcmlhIGVtIFBvcnRvIEFsZWdyZSAoUlMpIikgJT4lIA0KICBoY19zY3JvbGxiYXIoDQogICAgYmFyQmFja2dyb3VuZENvbG9yID0gImdyYXkiLA0KICAgIGJhckJvcmRlclJhZGl1cyA9IDcsDQogICAgYmFyQm9yZGVyV2lkdGggPSAwLA0KICAgIGJ1dHRvbkJhY2tncm91bmRDb2xvciA9ICJncmF5IiwNCiAgICBidXR0b25Cb3JkZXJXaWR0aCA9IDAsDQogICAgYnV0dG9uQXJyb3dDb2xvciA9ICJ3aGl0ZSIsDQogICAgYnV0dG9uQm9yZGVyUmFkaXVzID0gNywNCiAgICByaWZsZUNvbG9yID0gIndoaXRlIiwNCiAgICB0cmFja0JhY2tncm91bmRDb2xvciA9ICJ3aGl0ZSIsDQogICAgdHJhY2tCb3JkZXJXaWR0aCA9IDEsDQogICAgdHJhY2tCb3JkZXJDb2xvciA9ICJzaWx2ZXIiLA0KICAgIHRyYWNrQm9yZGVyUmFkaXVzID0gNykgJT4lIA0KICBoY19hZGRfc2VyaWVzKGRhdGEgPSBkZl90b3RhbCwgdHlwZSA9ICJsaW5lIiwgaGNhZXMoeCA9IERhdGEsIHkgPSByb3VuZChkZl90b3RhbCRUZW1wZXJhdHVyYV9NYXgsMSkpLCBuYW1lPSJTw6lyaWUgVG90YWwiKSAlPiUgDQogICAgaGNfdG9vbHRpcCgNCiAgICBwb2ludEZvcm1hdCA9ICJUZW1wZXJhdHVyYSBNw6F4aW1hOiB7cG9pbnQueTouMmZ9IMKwQyINCiAgKQ0KYGBgDQo8L2Rpdj4NCg0KDQo8YnI+DQoNClBlbG8gZ3LDoWZpY28gZGEgZnVuw6fDo28gZGUgYXV0b2NvcnJlbGHDp8OjbyBnZXJhZG8sIHBvZGVtb3MgdmlzdWFsaXphciBvcyBwYWRyw7VlcyBzYXpvbmFpcyBuYSBzw6lyaWUsIGNvbSBwaWNvcyBzaWduaWZpY2F0aXZvcyBuYSBBQ0YgZW0gaW50ZXJ2YWxvcyByZWd1bGFyZXMuIEFsw6ltIGRpc3NvLCB0ZW1vcyBmb3J0ZXMgaW5kw61jaW9zIGRhIHByZXNlbsOnYSBkZSBjb21wb25lbnRlcyBhdXRvcmVncmVzc2l2b3MgKEFSKS4NCg0KDQo8ZGl2IGNsYXNzID0gJ2NlbnRlcic+DQpgYGB7cn0NCmFjZjEgPC0gYWNmKHRyZWlubzEkVGVtcGVyYXR1cmFfTWF4LCBsYWcubWF4ID0gNDAwMCwgbWFpbiA9ICJBQ0YgLSBUZW1wZXJhdHVyYSBNw6F4aW1hIiwgcGxvdCA9IEYpDQpoY2hhcnQoYWNmMSkNCmBgYA0KPC9kaXY+DQoNCjxicj4NCg0KSsOhIGNvbSBvIGdyw6FmaWNvIGRhIGZ1bsOnw6NvIGRlIGF1dG9jb3JyZWxhw6fDo28gcGFyY2lhbCAoUEFDRiksIHBvZGVtb3MgdmlzdWFsaXphciBxdWUgbsOjbyBow6EgbGFncyBzaWduaWZpY2F0aXZvcyBuYSBQQUNGIGFww7NzIG9zIDEwMCBwcmltZWlyb3MgbGFncyBhcHJveGltYWRhbWVudGUsIGluZGljYW5kbyBxdWUgYSBzw6lyaWUgbsOjbyBwb3NzdWkgZGVwZW5kw6puY2lhIGRlIGxvbmdvIHByYXpvLiBObyBlbnRhbnRvLCBhIHByZXNlbsOnYSBkZSBsYWdzIHNpZ25pZmljYXRpdm9zIG5vIGluw61jaW8gZGEgc8OpcmllIGUgZW0gZGlyZcOnw7VlcyBkaWZlcmVudGVzIG5vcyBkw6NvIGluZMOtY2lvcyBkYSBwcmVzZW7Dp2EgZGUgY29tcG9uZW50ZSBkZSBtw6lkaWEgbcOzdmVsIChNQSkgZSBhIG5lY2Vzc2lkYWRlIGRlIG1vZGVsb3MgQVIgZGUgZGlmZXJlbnRlcyBvcmRlbnMgZW0gcGFydGVzIGRpZmVyZW50ZXMgZGEgc8OpcmllLg0KDQoNCjxkaXYgY2xhc3MgPSAnY2VudGVyJz4NCmBgYHtyIGVjaG89RkFMU0V9DQpwYWNmMSA8LSBwYWNmKHRyZWlubzEkVGVtcGVyYXR1cmFfTWF4LCBsYWcubWF4ID0gMTAwMCwgbWFpbiA9ICJQQUNGIC0gVGVtcGVyYXR1cmEgTcOheGltYSIsIHBsb3QgPSBGKQ0KaGNoYXJ0KHBhY2YxKQ0KYGBgDQo8L2Rpdj4NCg0KDQpgYGB7cn0NCnRyZWlubyA8LSB0cyh0cmVpbm8xJFRlbXBlcmF0dXJhX01heCwgZnJlcXVlbmN5ID0gMzY1LCBzdGFydCA9IGMoMjAxMiwxLDEpLCBlbmQgPSBjKDIwMjMsMSwxKSkNCnRlc3RlIDwtIHRzKHRlc3RlMSRUZW1wZXJhdHVyYV9NYXgsIHN0YXJ0ID0gYygyMDIzLCAxLDEpLCBmcmVxdWVuY3kgPSAzNjUpDQp0b3RhbCA8LSB0cyhkZl90b3RhbCRUZW1wZXJhdHVyYV9NYXgsIHN0YXJ0ID0gYygyMDEyLDEsMSksIGVuZCA9IGMoMjAyMyw3LDMxKSwgZnJlcXVlbmN5ID0gMzY1KQ0KYGBgDQoNCjxicj4NCg0KQWJhaXhvLCBvIGdyw6FmaWNvIG1vc3RyYSBvcyBzZWd1aW50ZXMgY29tcG9uZW50ZXM6DQoNCi0gICAqKlPDqXJpZSBUZW1wb3JhbCBPcmlnaW5hbDoqKiBBIHPDqXJpZSB0ZW1wb3JhbCBicnV0YSwgcXVlIGluY2x1aSB0ZW5kw6puY2lhLCBzYXpvbmFsaWRhZGUgZSBlcnJvLg0KDQotICAgKipUZW5kw6puY2lhOioqIEEgY29tcG9uZW50ZSBkZSB0ZW5kw6puY2lhLCBxdWUgcmVwcmVzZW50YSBhIGRpcmXDp8OjbyBnZXJhbCBkbyBjb21wb3J0YW1lbnRvIGRhIHPDqXJpZSBhbyBsb25nbyBkbyB0ZW1wby4NCg0KLSAgICoqU2F6b25hbGlkYWRlOioqIEEgY29tcG9uZW50ZSBzYXpvbmFsLCBxdWUgcmVwcmVzZW50YSBvcyBwYWRyw7VlcyBxdWUgc2UgcmVwZXRlbSBlbSBpbnRlcnZhbG9zIHJlZ3VsYXJlcywgY29tbyBzYXpvbmFsaWRhZGUgYW51YWwsIG1lbnNhbCwgZXRjLg0KDQotICAgKipFcnJvIChSZXPDrWR1b3MpOioqIEEgY29tcG9uZW50ZSBkZSBlcnJvLCBxdWUgcmVwcmVzZW50YSBvIHF1ZSByZXN0YSBuYSBzw6lyaWUgYXDDs3MgYSByZW1vw6fDo28gZGEgdGVuZMOqbmNpYSBlIGRhIHNhem9uYWxpZGFkZS4NCg0KPGRpdiBjbGFzcyA9ICdjZW50ZXInPg0KYGBge3IgZmlnLmFsaWduPSdjZW50ZXInfQ0KdHJlaW5vICU+JQ0KICBkZWNvbXBvc2UoKSAlPiUNCiAgYXV0b3Bsb3QoKSArIA0KICB0aGVtZV9taW5pbWFsKCkNCmBgYA0KPC9kaXY+DQoNCjxicj48YnI+DQoNCiMgTWV0b2RvbG9naWENCg0KDQoNCg0KDQogIA0KIyMjIFRlc3RlIGRlIFJhw616IFVuaXTDoXJpYQ0KDQoNCg0KQW50ZXMgZGUgcGFydGlybW9zIHBhcmEgYSBtb2RlbGFnZW0gZGEgc8OpcmllLCBpcmVtb3MgcmVhbGl6YXIgbyB0ZXN0ZSBUZXN0ZSBkZSBEaWNrZXktRnVsbGVyIEF1bWVudGFkbyAoQURGKSwgdXRpbGl6YWRvIHBhcmEgYXZhbGlhciBzZSBhIHPDqXJpZSB0ZW1wb3JhbCDDqSByZWFsbWVudGUgZXN0YWNpb27DoXJpYSBvdSBuw6NvIGVzdGFjaW9uw6FyaWEuDQoNCmBgYHtyIHdhcm5pbmc9RkFMU0V9DQphZGYudGVzdCh0cmVpbm8pDQpgYGANCg0KUGVsbyByZXN1bHRhZG8gYWNpbWEgcG9kZW1vcyB2ZXIgcXVlIG8gJHAudmFsb3IgPCAwLjA1JCwgb3Ugc2VqYSwgYSB1bSBuw612ZWwgZGUgc2lnbmlmaWPDom5jaWEgZGUgNSUsIHJlamVpdGFtb3MgYSBoaXDDs3Rlc2UgbnVsYS4gUG9ydGFuZG8sIGNvbmNsdcOtbW9zIHF1ZSBow6EgZXZpZMOqbmNpYXMgZGUgcXVlIGEgc8OpcmllIHNlamEgZXN0YWNpb27DoXJpYSwgZXN0YW5kbyB0YW1iw6ltIGRlIGFjb3JkbyBjb20gb3MgcmVzdWx0YWRvcyBkYXMgYW7DoWxpc2VzIGdyw6FmaWNhcyByZWFsaXphZGFzIGFudGVyaW9ybWVudGUuDQoNCg0KDQo8YnI+PGJyPg0KDQoNCiMjIyBNb2RlbG8gMSAtIEFSSU1BKDEsMCwzKQ0KDQoNCg0KUGFyYSBtb2RlbGFyIHPDqXJpZXMgdGVtcG9yYWlzIGNvbSBjb21wb25lbnRlcyBzYXpvbmFpcywgdXRpbGl6YW1vcyBtb2RlbG9zIEFSSU1BIHNhem9uYWlzLCBjb25oZWNpZG9zIGNvbW8gU0FSSU1BIChTZWFzb25hbCBBdXRvUmVncmVzc2l2ZSBJbnRlZ3JhdGVkIE1vdmluZyBBdmVyYWdlKS4gVW0gbW9kZWxvIFNBUklNQSDDqSB1bWEgZXh0ZW5zw6NvIGRvIEFSSU1BIHF1ZSBpbmNvcnBvcmEgdGVybW9zIHNhem9uYWlzIHBhcmEgY2FwdHVyYXIgYSB2YXJpYcOnw6NvIHNhem9uYWwgbm9zIGRhZG9zLg0KDQpPIFNBUklNQSDDqSBkZW5vdGFkbyBjb21vICRTQVJJTUEocCwgZCwgcSkoUCwgRCwgUSkkLCBvbmRlOg0KDQotICAgInAiOiDDqSBhIG9yZGVtIGRvIGNvbXBvbmVudGUgQVIgbsOjbyBzYXpvbmFsLg0KLSAgICJkIjogw6kgYSBvcmRlbSBkZSBpbnRlZ3Jhw6fDo28gbsOjbyBzYXpvbmFsLg0KLSAgICJxIjogw6kgYSBvcmRlbSBkbyBjb21wb25lbnRlIE1BIG7Do28gc2F6b25hbC4NCi0gICAiUCI6IMOpIGEgb3JkZW0gZG8gY29tcG9uZW50ZSBBUiBzYXpvbmFsLg0KLSAgICJEIjogw6kgYSBvcmRlbSBkZSBpbnRlZ3Jhw6fDo28gc2F6b25hbC4NCi0gICAiUSI6IMOpIGEgb3JkZW0gZG8gY29tcG9uZW50ZSBNQSBzYXpvbmFsLg0KDQpObyAqc29mdHdhcmUgUiosIHV0aWxpemFtb3MgYSBmdW7Dp8OjbyAkYXV0by5hcmltYSgpJCBxdWUgYXV0b21hdGl6YSBvIHByb2Nlc3NvIGRlIHNlbGXDp8OjbyBkbyBtb2RlbG8gQVJJTUEuIEVsYSBleHBsb3JhIHbDoXJpYXMgY29tYmluYcOnw7VlcyBkZSBwYXLDom1ldHJvcyBwIChvcmRlbSBkbyBjb21wb25lbnRlIEFSKSwgZCAob3JkZW0gZGUgaW50ZWdyYcOnw6NvKSBlIHEgKG9yZGVtIGRvIGNvbXBvbmVudGUgTUEpIGUgZm9ybmVjZSBvIG1vZGVsbyBBUklNQSBjb20gbyBtZW5vciB2YWxvciBkZSBBSUMgb3UgQklDIGNvbW8gbyBtZWxob3IgbW9kZWxvLiBBcMOzcyBpZGVudGlmaWNhciBwb3Nzw612ZWlzIG1vZGVsb3MgQVJJTUEgbsOjbyBzYXpvbmFpcywgdXRpbGl6YW5kbyBvIHBhcsOibWV0cm8gJHNlYXpvbmFsPVRSVUUkLCBvIGFsZ29yaXRtbyBlbnTDo28gZXN0ZW5kZSBhIGJ1c2NhIHBhcmEgbW9kZWxvcyBTQVJJTUEsIHF1ZSBpbmNsdWVtIGNvbXBvbmVudGVzIHNhem9uYWlzIChQLCBELCBRLCBzKSBhbMOpbSBkb3MgY29tcG9uZW50ZXMgbsOjbyBzYXpvbmFpcy4gRWxlIGFqdXN0YSBtb2RlbG9zIFNBUklNQSBjb20gZGlmZXJlbnRlcyB2YWxvcmVzIGRlIFAgKEFSIHNhem9uYWwpLCBEIChpbnRlZ3Jhw6fDo28gc2F6b25hbCksIFEgKE1BIHNhem9uYWwpIGUgcyAocGVyw61vZG8gZGEgc2F6b25hbGlkYWRlKSBlIGNhbGN1bGEgb3MgY3JpdMOpcmlvcyBkZSBpbmZvcm1hw6fDo28gcGFyYSBjYWRhIG1vZGVsby4NCg0KUGFyYSBhanVzdGFyIG8gbW9kZWxvLCB1dGlsaXphbW9zIGFwZW5hcyBvcyBkYWRvcyBhdMOpIDIwMjIgKG5vIHF1YWwgY2hhbWFtb3MgZGUgInRyZWlubyIpIHBhcmEgZW50w6NvIGZhemVyIGEgcHJldmlzw6NvIGF0w6kgb3MgZGlhcyBhdHVhaXMgKGEgcXVhbCBjaGFtYW1vcyBkZSAidGVzdGUiKS4NCg0KYGBge3IgZWNobz1UUlVFfQ0KbW9kZWwxIDwtIGF1dG8uYXJpbWEodHJlaW5vLCBzZWFzb25hbCA9IFRSVUUpDQpzdW1tYXJ5KG1vZGVsMSkNCmBgYA0KDQpPIG1vZGVsbyBwb2RlIHNlciBkZWZpbmlkbyBjb21vLA0KDQokJFhfdCA9IGMgKyBccGhpIFhfe3QtMX0gKyBcdGhldGEgXGVwc2lsb25fe3QtMX0gKyBcdGhldGEgXGVwc2lsb25fe3QtMn0gKyBcdGhldGEgXGVwc2lsb25fe3QtM30gKyBcZXBzaWxvbiQkDQoNCmVtIHF1ZSBvcyBwYXLDom1ldHJvcyBlbmNvbnRyYWRvcyBmb3JhbSwNCg0KJCRYX3QgPSAyNS43NCArIDAuOTkgWF97dC0xfSAtMC4yNyBcZXBzaWxvbl97dC0xfSAtMC4zNiBcZXBzaWxvbl97dC0yfSAtMC4xNyBcZXBzaWxvbl97dC0zfSArIFxlcHNpbG9uJCQNCg0KPGJyPg0KDQpGYXplbmRvIG8gZm9yZWNhc3QgKHByZXZpc8OjbykgZG8gbW9kZWxvIHBhcmEgb3MgZGlhcyBhdHVhaXMgdGVtb3M6DQoNCjxkaXYgY2xhc3MgPSAnY2VudGVyJz4NCmBgYHtyfQ0KZm9yZWNhc3RlZCA8LSBmb3JlY2FzdChtb2RlbDEsIGggPSBsZW5ndGgodGVzdGUpKQ0KDQpmb3JlY2FzdGVkX2RhdGEgPC0gZGF0YS5mcmFtZSgNCiAgRGF0ZSA9IHRlc3RlMSREYXRhLA0KICBNZWFuID0gZm9yZWNhc3RlZCRtZWFuLA0KICBsbzgwID0gZm9yZWNhc3RlZCRsb3dlciwNCiAgdXA4MCA9IGZvcmVjYXN0ZWQkdXBwZXINCikNCg0KaGlnaGNoYXJ0KHR5cGUgPSAic3RvY2siKSAlPiUNCiAgaGNfdGl0bGUodGV4dCA9ICJUZW1wZXJhdHVyYSBNw6F4aW1hIERpw6FyaWEgZW0gUG9ydG8gQWxlZ3JlIChSUykiKSAlPiUgDQogIGhjX3JhbmdlU2VsZWN0b3Ioc2VsZWN0ZWQgPSA0KSAlPiUgDQogIGhjX3Njcm9sbGJhcigpICU+JSANCiAgaGNfYWRkX3NlcmllcyhkYXRhID0gZGZfdG90YWwsIHR5cGUgPSAibGluZSIsIGhjYWVzKHggPSBEYXRhLCB5ID0gcm91bmQoZGZfdG90YWwkVGVtcGVyYXR1cmFfTWF4LCAxKSksIG5hbWUgPSAiVGVtcGVyYXR1cmEgTcOheGltYSIsIGRhdGFMYWJlbHMgPSBsaXN0KGZvcm1hdCA9ICJ7eTouMmZ9IMKwQyIpKSAlPiUgDQogIGhjX2FkZF9zZXJpZXMoZGF0YSA9IGZvcmVjYXN0ZWRfZGF0YSwgdHlwZSA9ICJhcmVhcmFuZ2UiLCBoY2Flcyh4ID0gRGF0ZSwgbG93ID0gbG84MC45NS4sIGhpZ2ggPSB1cDgwLjk1LiksIG5hbWUgPSAiSW50ZXJ2YWxvIikgJT4lIA0KICBoY19hZGRfc2VyaWVzKGRhdGEgPSBmb3JlY2FzdGVkX2RhdGEsIHR5cGUgPSAibGluZSIsIGhjYWVzKHggPSBEYXRlLCB5ID0gTWVhbiksIG5hbWUgPSAiTcOpZGlhIFByZXZpc3RhIikgJT4lIA0KICBoY190b29sdGlwKA0KICAgIHBvaW50Rm9ybWF0ID0gIntzZXJpZXMubmFtZX06IHtwb2ludC55Oi4yZn0gwrBDIg0KICApDQoNCmBgYA0KPC9kaXY+DQoNCg0KTm8gZW50YW50bywgcGFyYSB2YWxpZGFybW9zIG8gbW9kZWxvLCBwcmVjaXNhbW9zIGFudGVzIHZlcmlmaWNhciBzZSBvcyByZXPDrWR1b3MgbsOjbyBzw6NvIGF1dG9jb3JyZWxhY2lvbmFkb3MgYSBwYXJ0aXIgZGEgYW7DoWxpc2UgZGEgZnVuw6fDo28gZGUgYXV0b2NvcnJlbGHDp8OjbyBkb3MgcmVzw61kdW9zIGUgZG8gdGVzdGUgTGp1bmctQm94Og0KDQo8YnI+DQo8ZGl2IGNsYXNzID0gJ2NlbnRlcic+DQpgYGB7cn0NCiMgUmVhbGl6ZSBvIHRlc3RlIGRlIER1cmJpbi1XYXRzb24gbm9zIHJlc8OtZHVvcyBkbyBzZXUgbW9kZWxvDQphY2YyIDwtIGFjZihtb2RlbDEkcmVzaWR1YWxzLCBsYWcubWF4ID0gMjAsIHBsb3QgPSBGKQ0KaGNoYXJ0KGFjZjIpDQoNCkJveC50ZXN0KGZvcmVjYXN0ZWQkcmVzaWR1YWxzLCBsYWc9MjAsIHR5cGU9IkxqdW5nLUJveCIpDQoNCmBgYA0KPC9kaXY+DQoNCjxicj4NCg0KTyBjb3JyZWxvZ3JhbWEgbW9zdHJhIHF1ZSBhcyBhdXRvY29ycmVsYcOnw7VlcyBwYXJhIG9zIGVycm9zIGRlIHByZXZpc8OjbyBwcmF0aWNhbWVudGUgbsOjbyBleGNlZGVtIG9zIGxpbWl0ZXMgZGUgc2lnbmlmaWPDom5jaWEgcGFyYSBkZWZhc2FnZW5zIDEtMjAuIEFsw6ltIGRpc3NvLCBvIHAtdmFsb3IgcGFyYSBvIHRlc3RlIExqdW5nLUJveCDDqSAkMC4wMjIzNiQgaW5kaWNhbmRvIHF1ZSBuw6NvIGjDoSBtdWl0YSBldmlkw6puY2lhIGRlIGF1dG9jb3JyZWxhw6fDtWVzIGRpZmVyZW50ZXMgZGUgemVybyBuYXMgZGVmYXNhZ2VucyAxLTIwLiBQb3J0YW50bywgcG9kZW1vcyBjb25jbHVpciBxdWUgb3MgcmVzw61kdW9zIG7Do28gc8OjbyBhdXRvY29ycmVsYWNpb25hZG9zLg0KDQpBZGVtYWlzLCBvdXRybyBwYXNzbyBwYXJhIHZlcmlmaWNhciBzZSBvIG1vZGVsbyBwcmVkaXRpdm8gcG9kZSBzZXIgbWVsaG9yYWRvIMOpIGludmVzdGlnYXIgc2Ugb3MgZXJyb3MgZGUgcHJldmlzw6NvIHPDo28gbm9ybWFsbWVudGUgZGlzdHJpYnXDrWRvcyBjb20gbcOpZGlhIHplcm8gZSB2YXJpw6JuY2lhIGNvbnN0YW50ZS4NCg0KDQo8ZGl2IGNsYXNzID0gJ2NlbnRlcic+DQpgYGB7cn0NCnBsb3RGb3JlY2FzdEVycm9ycyA8LSBmdW5jdGlvbihmb3JlY2FzdGVycm9ycykNCiAgew0KICAgICMgbWFrZSBhIGhpc3RvZ3JhbSBvZiB0aGUgZm9yZWNhc3QgZXJyb3JzOg0KICBteWJpbnNpemUgPC0gSVFSKGZvcmVjYXN0ZXJyb3JzLCBuYS5ybSA9IFRSVUUpLzQNCiAgICBteXNkICAgPC0gc2QoZm9yZWNhc3RlcnJvcnMsIG5hLnJtID0gVFJVRSkNCiAgICBteW1pbiAgPC0gbWluKGZvcmVjYXN0ZXJyb3JzLCBuYS5ybSA9IFRSVUUpIC0gbXlzZCo1DQogICAgbXltYXggIDwtIG1heChmb3JlY2FzdGVycm9ycywgbmEucm0gPSBUUlVFKSArIG15c2QqMw0KICAgICMgZ2VuZXJhdGUgbm9ybWFsbHkgZGlzdHJpYnV0ZWQgZGF0YSB3aXRoIG1lYW4gMCBhbmQgc3RhbmRhcmQgZGV2aWF0aW9uIG15c2QNCiAgICBteW5vcm0gPC0gcm5vcm0oMTAwMDAsIG1lYW49MCwgc2Q9bXlzZCkNCiAgICBteW1pbjIgPC0gbWluKG15bm9ybSwgbmEucm0gPSBUUlVFKQ0KICAgIG15bWF4MiA8LSBtYXgobXlub3JtLCBuYS5ybSA9IFRSVUUpDQogICAgaWYgKG15bWluMiA8IG15bWluICkgeyBteW1pbiA8LSBteW1pbjJ9DQogICAgaWYgKG15bWF4MiA+IG15bWF4KSB7IG15bWF4IDwtIG15bWF4Mn0NCiAgICAjIG1ha2UgYSByZWQgaGlzdG9ncmFtIG9mIHRoZSBmb3JlY2FzdCBlcnJvcnMsIHdpdGggdGhlIG5vcm1hbGx5IGRpc3RyaWJ1dGVkIGRhdGEgb3ZlcmxhaWQ6DQogICAgbXliaW5zIDwtIHNlcShteW1pbiwgbXltYXgsIG15Ymluc2l6ZSkNCiAgICBoaXN0KGZvcmVjYXN0ZXJyb3JzLCBjb2w9InJlZCIsIGZyZXE9RkFMU0UsIGJyZWFrcz1teWJpbnMpDQogICAgIyBmcmVxPUZBTFNFIGVuc3VyZXMgdGhlIGFyZWEgdW5kZXIgdGhlIGhpc3RvZ3JhbSA9IDENCiAgICAjIGdlbmVyYXRlIG5vcm1hbGx5IGRpc3RyaWJ1dGVkIGRhdGEgd2l0aCBtZWFuIDAgYW5kIHN0YW5kYXJkIGRldmlhdGlvbiBteXNkDQogICAgbXloaXN0IDwtIGhpc3QobXlub3JtLCBwbG90PUZBTFNFLCBicmVha3M9bXliaW5zKQ0KICAgICMgcGxvdCB0aGUgbm9ybWFsIGN1cnZlIGFzIGEgYmx1ZSBsaW5lIG9uIHRvcCBvZiB0aGUgaGlzdG9ncmFtIG9mIGZvcmVjYXN0IGVycm9yczoNCiAgICBwb2ludHMobXloaXN0JG1pZHMsIG15aGlzdCRkZW5zaXR5LCB0eXBlPSJsIiwgY29sPSJibHVlIiwgbHdkPTIpDQp9DQojcGxvdCBhIGhpc3RvZ3JhbSAod2l0aCBvdmVybGFpZCBub3JtYWwgY3VydmUpIG9mIHRoZSBmb3JlY2FzdCBlcnJvcnMgZm9yIHRoZSByYWluZmFsbCBwcmVkaWN0aW9ucw0KI3Bsb3RGb3JlY2FzdEVycm9ycyhmb3JlY2FzdGVkJHJlc2lkdWFscykNCg0KZGF0YSA8LSBmb3JlY2FzdGVkJHJlc2lkdWFscw0KZGF0YSA8LSByb3VuZChkYXRhLCAzKQ0KIyBDcmllIG8gaGlzdG9ncmFtYSB1c2FuZG8gaGlnaGNoYXJ0ZXINCmhpZ2hjaGFydCgpICU+JQ0KICBoY19jaGFydCh0eXBlID0gImNvbHVtbiIpICU+JQ0KICBoY190aXRsZSh0ZXh0ID0gIkhpc3RvZ3JhbWEgZGUgUmVzw61kdW9zIikgJT4lDQogIGhjX3hBeGlzKGNhdGVnb3JpZXMgPSBoaXN0KGRhdGEsIHBsb3QgPSBGQUxTRSkkYnJlYWtzKSAlPiUNCiAgaGNfeUF4aXModGl0bGUgPSBsaXN0KHRleHQgPSAiRnJlcXXDqm5jaWEiKSkgJT4lDQogIGhjX2FkZF9zZXJpZXMoZGF0YSA9IGhpc3QoZGF0YSwgcGxvdCA9IEZBTFNFKSRjb3VudHMsIG5hbWUgPSAiRnJlcXXDqm5jaWEiLCBjb2xvciA9ICJyZWQiKQ0KICAgICAgICANCmBgYA0KDQo8L2Rpdj4NCg0KTyB0ZXN0ZSBManVuZy1Cb3ggbsOjbyByZXZlbGEgZXZpZMOqbmNpYXMgc3VmaWNpZW50ZXMgZGUgcXVlIGV4aXN0YSBhdXRvY29ycmVsYcOnw7VlcyBkaWZlcmVudGVzIGRlIHplcm8gbm9zIGVycm9zIGRlIHByZXZpc8OjbyBuYSBhbW9zdHJhLCBhcyB2YXJpYcOnw7VlcyBub3MgZXJyb3MgZGUgcHJldmlzw6NvIHBhcmVjZW0gYXByb3hpbWFkYW1lbnRlIGNvbnN0YW50ZXMgZSBvcyBlcnJvcyBkZSBwcmV2aXPDo28gcGFyZWNlbSBkaXN0cmlidcOtZG9zIG5vcm1hbG1lbnRlLiBQb3J0YW50bywgcG9kZW1vcyBjb25jbHVpciBxdWUgbyAqKm1vZGVsbyBBUklNQSgxLDAsMykgw6kgdW0gbW9kZWxvIHbDoWxpZG8uKioNCg0KDQoNCg0KPGJyPjxicj4NCg0KDQogIA0KIyMjIE1vZGVsbyAyIC0gU0FSSU1BKDMsMCwwKSgwLDEsMClbMzY1XQ0KDQoNCg0KQXBlc2FyIGRvIG1vZGVsbyBhbnRlcmlvciB0ZXIgc2lkbyBjb25zaWRlcmFkbyB2w6FsaWRvIGUgY29tIHVtYSBhY3Vyw6FjaWEgc2lnbmlmaWNhdGl2YSBhbyBhanVzdGUgZG9zIGRhZG9zIGRlIHRyZWlubywgcG9kZW1vcyBwZXJjZWJlciBxdWUgbWVzbW8gY29tIG8gcGFyw6JtZXRybyAkc2Vhem9uYWw9VFJVRSQgYSBmdW7Dp8OjbyBhdXRvLmFyaW1hKCkgbsOjbyBpbmRpY291IGNvbXBvbmVudGVzIHNhem9uYWlzIHF1ZSBoYXbDrWFtb3MgdmVyaWZpY2FkbyBxdWUgZXN0w6NvIHByZXNlbnRlcyBuYSBzw6lyaWUgbmFzIGV0YXBhcyBhbnRlcmlvcmVzLiBQb3J0YW50bywgbmVzdGUgbW9kZWxvIGlyZW1vcyB1dGlsaXphciBvIHBhcsOibWV0cm8gJEQ9MSQsIGluZGljYW5kbyBxdWUgc2UgZGVzZWphIGFwbGljYXIgdW1hIGRpZmVyZW5jaWHDp8OjbyBzYXpvbmFsIGRlIHByaW1laXJhIG9yZGVtIMOgIHPDqXJpZSB0ZW1wb3JhbC4gSXNzbyBzaWduaWZpY2EgcXVlLCBlbSBjYWRhIHBlcsOtb2RvIHNhem9uYWwsIG9zIHZhbG9yZXMgZGEgc8OpcmllIHNlcsOjbyBzdWJ0cmHDrWRvcyBkb3MgdmFsb3JlcyBkbyBwZXLDrW9kbyBzYXpvbmFsIGFudGVyaW9yIHBhcmEgcmVtb3ZlciBhIHNhem9uYWxpZGFkZS4NCg0KYGBge3IgZWNobz1UUlVFfQ0KbW9kZWwyIDwtIGF1dG8uYXJpbWEodHJlaW5vLCBEID0gMSkNCnN1bW1hcnkobW9kZWwyKQ0KYGBgDQoNCk8gbW9kZWxvIHBvZGUgc2VyIGRlZmluaWRvIGNvbW8sDQoNCiQkXG5hYmxhX3szNjV9WF90ID0gXHBoaSBYX3t0LTF9ICsgXHBoaSBYX3t0LTJ9ICsgXHBoaSBYX3t0LTN9ICsgXGVwc2lsb24kJA0KDQplbSBxdWUgb3MgcGFyw6JtZXRyb3MgZW5jb250cmFkb3MgZm9yYW0NCg0KJCRcbmFibGFfezM2NX1YX3QgPSAwLjcxIFhfe3QtMX0gLTAuMTkgWF97dC0yfSArIDAuMDUgWF97dC0zfSArIFxlcHNpbG9uJCQNCg0KPGJyPg0KDQpGYXplbmRvIG8gZm9yZWNhc3QgKHByZXZpc8OjbykgZG8gbW9kZWxvIHBhcmEgb3MgZGlhcyBhdHVhaXMgdGVtb3M6DQoNCjxkaXYgY2xhc3MgPSAnY2VudGVyJz4NCmBgYHtyfQ0KIyBGYXplciBhcyBwcmV2aXPDtWVzDQpmb3JlY2FzdGVkMiA8LSBmb3JlY2FzdChtb2RlbDIsIGggPSBsZW5ndGgodGVzdGUpKQ0KDQpmb3JlY2FzdGVkX2RhdGEyIDwtIGRhdGEuZnJhbWUoDQogIERhdGUgPSB0ZXN0ZTEkRGF0YSwNCiAgTWVhbiA9IGZvcmVjYXN0ZWQyJG1lYW4sDQogIGxvODAgPSBmb3JlY2FzdGVkMiRsb3dlciwNCiAgdXA4MCA9IGZvcmVjYXN0ZWQyJHVwcGVyDQopDQoNCiMgQ3JpYXIgdW0gZ3LDoWZpY28gaW50ZXJhdGl2byB1c2FuZG8gaGlnaGNoYXJ0ZXINCiANCmhpZ2hjaGFydCh0eXBlID0gInN0b2NrIikgJT4lDQogIGhjX3RpdGxlKHRleHQgPSAiVGVtcGVyYXR1cmEgTcOheGltYSBEacOhcmlhIGVtIFBvcnRvIEFsZWdyZSAoUlMpIikgJT4lIA0KICBoY19yYW5nZVNlbGVjdG9yKHNlbGVjdGVkID0gNCkgJT4lIA0KICBoY19zY3JvbGxiYXIoKSAlPiUgDQogIGhjX2FkZF9zZXJpZXMoZGF0YSA9IGRmX3RvdGFsLCB0eXBlID0gImxpbmUiLCBoY2Flcyh4ID0gRGF0YSwgeSA9IHJvdW5kKGRmX3RvdGFsJFRlbXBlcmF0dXJhX01heCwgMSkpLCBuYW1lID0gIlRlbXBlcmF0dXJhIE3DoXhpbWEiLCBkYXRhTGFiZWxzID0gbGlzdChmb3JtYXQgPSAie3k6LjJmfSDCsEMiKSkgJT4lIA0KICBoY19hZGRfc2VyaWVzKGRhdGEgPSBmb3JlY2FzdGVkX2RhdGEyLCB0eXBlID0gImFyZWFyYW5nZSIsIGhjYWVzKHggPSBEYXRlLCBsb3cgPSBsbzgwLjk1LiwgaGlnaCA9IHVwODAuOTUuKSwgbmFtZSA9ICJJbnRlcnZhbG8iKSAlPiUgDQogIGhjX2FkZF9zZXJpZXMoZGF0YSA9IGZvcmVjYXN0ZWRfZGF0YTIsIHR5cGUgPSAibGluZSIsIGhjYWVzKHggPSBEYXRlLCB5ID0gTWVhbiksIG5hbWUgPSAiTcOpZGlhIFByZXZpc3RhIikgJT4lIA0KICBoY190b29sdGlwKA0KICAgIHBvaW50Rm9ybWF0ID0gIntzZXJpZXMubmFtZX06IHtwb2ludC55Oi4yZn0gwrBDIg0KICApDQoNCmBgYA0KDQo8L2Rpdj4NCjxicj4NCg0KQXNzaW0gY29tbyBmZWl0byBhbnRlcmlvcm1lbnRvLCBpcmVtb3MgdmVyaWZpY2FyIHNlIG8gbm92byBtb2RlbG8gw6kgdsOhbGlkbywNCg0KPGRpdiBjbGFzcyA9ICdjZW50ZXInPg0KYGBge3J9DQojIFJlYWxpemUgbyB0ZXN0ZSBkZSBEdXJiaW4tV2F0c29uIG5vcyByZXPDrWR1b3MgZG8gc2V1IG1vZGVsbw0KYWNmMyA8LSBhY2YobW9kZWwyJHJlc2lkdWFscywgbGFnLm1heCA9IDIwLCBwbG90ID0gRikNCmhjaGFydChhY2YzKQ0KYGBgDQo8L2Rpdj4NCg0KYGBge3J9DQpCb3gudGVzdChmb3JlY2FzdGVkMiRyZXNpZHVhbHMsIGxhZz0yMCwgdHlwZT0iTGp1bmctQm94IikNCmBgYA0KDQo8YnI+DQoNCk8gY29ycmVsb2dyYW1hIG1vc3RyYSBxdWUgYXMgYXV0b2NvcnJlbGHDp8O1ZXMgcGFyYSBvcyBlcnJvcyBkZSBwcmV2aXPDo28gcHJhdGljYW1lbnRlIG7Do28gZXhjZWRlbSBvcyBsaW1pdGVzIGRlIHNpZ25pZmljw6JuY2lhIHBhcmEgZGVmYXNhZ2VucyAxLTIwLiBBbMOpbSBkaXNzbywgbyBwLXZhbG9yIHBhcmEgbyB0ZXN0ZSBManVuZy1Cb3ggw6kgJDAuMDI5NDMkIGluZGljYW5kbyBxdWUgbsOjbyBow6EgbXVpdGEgZXZpZMOqbmNpYSBkZSBhdXRvY29ycmVsYcOnw7VlcyBkaWZlcmVudGVzIGRlIHplcm8gbmFzIGRlZmFzYWdlbnMgMS0yMC4gUG9ydGFudG8sIHBvZGVtb3MgY29uY2x1aXIgcXVlIG9zIHJlc8OtZHVvcyBuw6NvIHPDo28gYXV0b2NvcnJlbGFjaW9uYWRvcy4NCg0KQWzDqW0gZGlzc28sIG9zIGVycm9zIGRlIHByZXZpc8OjbyB0w6ptIHZhcmnDom5jaWEgY29uc3RhbnRlIGFvIGxvbmdvIGRvIHRlbXBvIGUgc8OjbyBub3JtYWxtZW50ZSBkaXN0cmlidcOtZG9zIGNvbSBtw6lkaWEgemVybw0KDQo8ZGl2IGNsYXNzID0gJ2NlbnRlcic+DQpgYGB7cn0NCiNwbG90IGEgaGlzdG9ncmFtICh3aXRoIG92ZXJsYWlkIG5vcm1hbCBjdXJ2ZSkgb2YgdGhlIGZvcmVjYXN0IGVycm9ycyBmb3IgdGhlIHJhaW5mYWxsIHByZWRpY3Rpb25zDQpkYXRhIDwtIGZvcmVjYXN0ZWQyJHJlc2lkdWFscw0KZGF0YSA8LSByb3VuZChkYXRhLCAzKQ0KIyBDcmllIG8gaGlzdG9ncmFtYSB1c2FuZG8gaGlnaGNoYXJ0ZXINCmhpZ2hjaGFydCgpICU+JQ0KICBoY19jaGFydCh0eXBlID0gImNvbHVtbiIpICU+JQ0KICBoY190aXRsZSh0ZXh0ID0gIkhpc3RvZ3JhbWEgZGUgUmVzw61kdW9zIikgJT4lDQogIGhjX3hBeGlzKGNhdGVnb3JpZXMgPSBoaXN0KGRhdGEsIHBsb3QgPSBGQUxTRSkkYnJlYWtzKSAlPiUNCiAgaGNfeUF4aXModGl0bGUgPSBsaXN0KHRleHQgPSAiRnJlcXXDqm5jaWEiKSkgJT4lDQogIGhjX2FkZF9zZXJpZXMoZGF0YSA9IGhpc3QoZGF0YSwgcGxvdCA9IEZBTFNFKSRjb3VudHMsIG5hbWUgPSAiRnJlcXXDqm5jaWEiLCBjb2xvciA9ICJyZWQiKQ0KYGBgDQo8L2Rpdj4NCg0KUG9ydGFudG8sIHBvZGVtb3MgY29uY2x1aXIgcXVlIG8gbW9kZWxvIFNBUklNQSgzLDAsMCkoMCwxLDApWzM2NV0gdGFtYsOpbSDDqSB2w6FsaWRvLg0KDQoNCg0KPGJyPjxicj4NCg0KDQoNCjxkaXYgY2xhc3M9InBhbmVsIHBhbmVsLWRlZmF1bHQiPg0KICA8ZGl2IGNsYXNzPSJwYW5lbC1oZWFkaW5nIj4gDQoNCiMgQ29uY2x1c8Ojbw0KDQo8L2Rpdj4NCjwvZGl2Pg0KDQoNCjxkaXYgY2xhc3MgPSAnY2VudGVyJz4NCmBgYHtyfQ0KaGlnaGNoYXJ0KHR5cGUgPSAic3RvY2siKSAlPiUNCiAgaGNfdGl0bGUodGV4dCA9ICJUZW1wZXJhdHVyYSBNw6F4aW1hIERpw6FyaWEgZW0gUG9ydG8gQWxlZ3JlIChSUykiKSAlPiUgDQogIGhjX3JhbmdlU2VsZWN0b3Ioc2VsZWN0ZWQgPSA0KSAlPiUgDQogIGhjX3Njcm9sbGJhcigpICU+JSANCiAgaGNfYWRkX3NlcmllcyhkYXRhID0gZGZfdG90YWwsIHR5cGUgPSAibGluZSIsIGhjYWVzKHggPSBEYXRhLCB5ID0gcm91bmQoZGZfdG90YWwkVGVtcGVyYXR1cmFfTWF4LCAxKSksIG5hbWUgPSAiVGVtcGVyYXR1cmEgTcOheGltYSIsIGRhdGFMYWJlbHMgPSBsaXN0KGZvcm1hdCA9ICJ7eTouMmZ9IMKwQyIpKSAlPiUgDQogIGhjX2FkZF9zZXJpZXMoZGF0YSA9IGZvcmVjYXN0ZWRfZGF0YTIsIHR5cGUgPSAibGluZSIsIGhjYWVzKHggPSBEYXRlLCB5ID0gTWVhbiksIG5hbWUgPSAiTW9kZWxvIDIiKSAlPiUgDQogIGhjX2FkZF9zZXJpZXMoZGF0YSA9IGZvcmVjYXN0ZWRfZGF0YSwgdHlwZSA9ICJsaW5lIiwgaGNhZXMoeCA9IERhdGUsIHkgPSBNZWFuKSwgbmFtZSA9ICJNb2RlbG8gMSIpICU+JSANCiAgaGNfdG9vbHRpcCgNCiAgICBwb2ludEZvcm1hdCA9ICJ7c2VyaWVzLm5hbWV9OiB7cG9pbnQueTouMmZ9IMKwQyINCiAgKQ0KYGBgDQoNCjwvZGl2Pg0KDQo8YnI+DQoNCmBgYHtyfQ0KQUlDcyA8LSBkYXRhLmZyYW1lKCJNb2RlbG8gMSIgPSBtb2RlbDEkYWljLA0KICAgICAgICAgICAgICAgICAgICJNb2RlbG8gMiIgPSBtb2RlbDIkYWljKQ0KDQpyb3duYW1lcyhBSUNzKSA8LSAiQUlDIg0KDQoNCmtibChBSUNzLCBlc2NhcGUgPSBGQUxTRSkgJT4lDQogIGthYmxlX3BhcGVyKCJzdHJpcGVkIiwgZnVsbF93aWR0aCA9IEZBTFNFKQ0KYGBgDQoNCjxicj4NCg0KUG9ydGFudG8sIGVuY29udHJhbW9zIHF1ZSBvcyBkb2lzIG1vZGVsb3MgZ2VyYWRvcyBzw6NvIHbDoWxpZG9zLiBQZWxvIEFJQywgcG9kZW1vcyB2ZXIgcXVlIG8gbWVub3IgZGVsZXMgw6kgbyBNb2RlbG8gMSwgaW5kaWNhbmRvIHF1ZSBlc3RlIHRlcmlhIHVtIG1lbGhvciBhanVzdGUgYW9zIGRhZG9zLiBObyBlbnRhbnRvLCBvIGdyw6FmaWNvIGV2aWRlbmNpYSBxdWUgbyBNb2RlbG8gMiB0ZXZlIHVtIGRlc2VtcGVuaG8gbXVpdG8gbWFpcyBhY3VyYWRvIGFvIGNvbXBhcmFybW9zIGFzIG3DqWRpYXMgZG9zIHZhbG9yZXMgcHJlZGl0b3MuDQo=