Introdução

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.



Análise Descritiva

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.



Conclusão


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=