1. Prefácio

Este estudo apresenta uma análise detalhada das temperaturas médias diárias registadas em Tóquio entre janeiro de 2019 e março de 2020, utilizando técnicas de modelagem de séries temporais. Através da aplicação do modelo ARIMA, exploram-se padrões sazonais e tendências que caracterizam o clima de Tóquio durante esse período. A modelagem permite não só compreender as variações históricas das temperaturas, como também prever valores futuros com um grau razoável de precisão. O relatório oferece uma abordagem prática à análise de séries temporais, desde a visualização dos dados até à validação dos modelos, proporcionando uma visão integrada dos métodos estatísticos utilizados na previsão climática.

Autor

Sylvie Borges, nascida em 1999, é uma entusiasta das Ciências Humanas e tem trilhado um percurso académico que reflete a sua paixão pelo conhecimento e pela gestão de pessoas. Iniciou a sua formação na prestigiada Universidade Católica Portuguesa, onde se graduou em Línguas Estrangeiras Aplicadas. Sempre movida pela curiosidade intelectual, continuou os estudos com um Mestrado em Gestão de Recursos Humanos, pelo ISCTE Business School, campo onde desenvolveu uma sólida compreensão da dinâmica organizacional.

Com um olhar atento às mudanças do mundo moderno, Sylvie percebeu que as Tecnologias da Informação representavam um novo horizonte para a gestão de pessoas. Desde 2021, tem-se dedicado a explorar este domínio emergente, construindo uma ponte entre a comunicação, gestão e as novas ferramentas tecnológicas. Em busca de uma compreensão ainda mais profunda, inscreveu-se numa Pós-Graduação em Data Science (Universidade Europeia), determinada a dominar os métodos e linguagens que moldam o quotidiano dos profissionais das TI, enriquecendo assim a sua capacidade de interagir com este universo em constante evolução.

Licença Este trabalho está licenciado sob uma licença Creative Commons Attribution-NonCommercial ShareAlike 4.0 International License. O resultado deste trabalho não providencia aconselhamento financeiro.

2. Introdução

O presente estudo tem como objetivo a análise de uma série temporal referente às temperaturas médias diárias registadas em Tóquio entre 1 de janeiro de 2019 e 31 de março de 2020. O dataset utilizado remete para temperatura média diária em graus Celsius e será analisado com recurso a métodos de séries temporais abordados no curso de Análise de Séries Temporais.

A análise de séries temporais apresenta-se como uma técnica estatística que permite estudar os dados sequenciais ao longo do tempo, identificar padrões e realizar previsões futuras com base em dados históricos. Este tipo de análise é amplamente utilizado em diversas áreas, como a meteorologia, economia e finanças, devido à sua capacidade de modelar e prever comportamentos futuros.

Para o desenvolvimento deste trabalho, serão explorados diferentes modelos de séries temporais, como o ARIMA e outros métodos. O objetivo é selecionar o modelo que melhor se ajusta aos dados de temperatura e, com base nesse modelo, realizar previsões para períodos futuros.

Além disso, será feita uma análise dos resíduos do modelo selecionado para verificar a sua adequação e, por fim, será apresentado um conjunto de previsões com base nos dados disponíveis. As decisões tomadas ao longo do processo serão devidamente justificadas e documentadas no relatório.

O trabalho será desenvolvido utilizando o software R, e o relatório final incluirá todas as análises, gráficos e previsões, conforme as instruções fornecidas.

3. Análise descritiva da série temporal

3.1) Visualização

O primeiro passo realizado foi o carregamento do dataset e a visualização dos dados, utilizando a linguagem R para a tarefa. Procedeu-se ao carregamento do dataset pretendudi e converteu-se a coluna ‘’Date’’ para o formato de data. De seguida, visualizaram-se os primeiros registos do dataset para garantir que os dados foram carregados corretamente. Por fim, plotou-se a série temporal utilizando a biblioteca ‘’ggplot2’’ para observar a variação da temperatura ao longo do tempo.

Quanto ao gráfico obtido, o mesmo mostra temperatura média diária em Tóquio entre 2019 e 2020, sendo que se podem retirar algumas observações:

  • Existe um padrão bem definido que segue as estações do ano. As temperaturas começam mais baixas no início de 2019, aumentando gradualmente até atingir um pico por volta de julho a agosto, representando o verão. Após o pico, as temperaturas começam a cair novamente, chegando a um ponto mais baixo no inverno (dezembro e janeiro);

  • A temperatura atinge o seu valor máximo em torno de 30°C durante o verão (por volta de julho/agosto de 2019) e o seu valor mais baixo, próximo de 0°C, no inverno (janeiro de 2020);

  • Embora o padrão geral seja uma curva suave, existem flutuações diárias consideráveis, o que reflete a variabilidade do clima no dia-a-dia.

# Carregar pacotes necessários
library(ggplot2)

# Importar o dataset
data <- read.csv("C:/Users/Sylvie/Downloads/Temperatura_Toquio_dataset.csv")

# Verificar as primeiras linhas dos dados
head(data)

# Converter a coluna 'Date' para formato de data
data$Date <- as.Date(data$Date)

# Visualizar a estrutura do dataset
str(data)

#Visualizar a série temporal
# Criar um gráfico da série temporal
ggplot(data, aes(x = Date, y = Temperature)) +
  geom_line(color = "blue") +
  labs(title = "Temperatura Média Diária em Tóquio (2019-2020)",
       x = "Data", y = "Temperatura (°C)") +
  theme_minimal()

3.2) Decomposição

Após, procedeu-se a uma análise estatística básica para compreender a distribuição inicial dos dados, obtendo informações sobre o Mínimo (0.890), 1ºQuartil (7.975), Mediana (13.790), Média (14.978), 3ºQuartil (21.830) e o Máximo (30.300); que permitem entender a distribuição, centralidade e dispersão da variável ‘’Temperatura’‘. Permite, também, identificar possíveis outliers ou comportamentos anómalos nos dados. Depois, verificaram-se os valores em falta. Esta verificação é essencial para assegurar que não há valores em falta (NA) no conjunto de dados. Valores ausentes podem impactar negativamente as análises e a modelagem, especialmente em séries temporais, pois os modelos exigem séries completas. Se existissem valores em falta (não é o caso, visto que não existem valores em falta), seria necessário tratar esses dados antes de continuar a análise, por exemplo, imputando ou interpolando os valores ausentes. De seguida, procedeu-se à decomposição da série temporal. Este método permite separar a série em componentes de tendência, sazonalidade e resíduos, o que permite um melhor entendimento da estrutura dos dados. Convertendo os dados numa série temporal (ts), podemos decompor a série usando a função’‘decompose’’. O resultado é um gráfico que demonstra a tendência (variação de longo prazo), a sazonalidade (padrões repetitivos) e os resíduos (variações aleatórias). Neste caso, a série temporal não apresenta períodos ou tem menos do que dois, o que não nos permite tirar conclusões assertivas.

# Resumo estatístico básico da temperatura
summary(data$Temperature)

# Verificar se há valores em falta (NA)
sum(is.na(data$Temperature))


# Decomposição da série temporal
# Instalar o pacote 'forecast'
# install.packages("forecast")
library(forecast)

# Converter a série temporal
ts_data <- ts(data$Temperature, start = c(2019, 1), frequency = 365)

# Decomposição da série temporal
decomposed <- decompose(ts_data)
plot(decomposed)

4. Modelação da série temporal

Primeiramente, optou-se pela divisão dos dados. Este passo permite avaliar a precisão do modelo, dividindo os dados em conjuntos de treino e de teste. O conjunto de treino é utilizado para ajustar o modelo, enquanto que o conjunto de teste é utilizado para validar previsões.Neste passo, utilizou-se a função ‘’window’’ para dividir os dados. O conjunto de treino inclui os dados até 29-02-2020 e o conjunto de teste inclui os dados a partir de 01-03-2020.

# Dividir os dados em treino e teste
train_data <- window(ts_data,end = c(2020, 59))
test_data <- window(ts_data, start = c(2020, 60))

# Verificar os dados de treino e teste
head(train_data)
head(test_data)

Após a divisão dos dados, prosseguiu-se para a aplicação do modelo ARIMA. Este modelo é utilizado para modelar séries temporais. Utiliza-se a função ‘’auto.arima’’ para identificar automaticamente o melhor modelo ARIMA para os dados de treino.

O resumo do modelo (summary) fornece informações detalhadas sobre os parâmetros do modelo. De seguida, optou-se pela função ‘’forecast’’ para fazer previsões para o período de teste e plotou-se as previsões junto com os valores reais.

# Identificação do modelo ARIMA
fit <- auto.arima(train_data)
summary(fit)

# Previsões
forecasted <- forecast(fit, h =length(test_data))
plot(forecasted)
lines(test_data, col = rgb(1,0,0))

Em média, o modelo ARIMA(2,1,2) ajustou-se bem aos dados com um erro relativamente baixo (RMSE = 1.8855) e um MAPE de 16.18%, o que sugere uma precisão razoável nas previsões. O valor de ACF1 muito próximo de 0 sugere que o modelo capturou a maior parte da estrutura da série temporal, e os resíduos parecem ser ruído aleatório, sem correlação significativa.

Com base no gráfico apresentado, a linha preta representa os dados históricos, enquanto que a área sombreada e as linhas a vermelho indicam as previsões para o futuro:

Assim, o modelo ARIMA prevê que as temperaturas em Tóquio manterão o padrão de variação, mas com uma certa incerteza nos valores exatos, especialmente à medida que o período de previsão avança.

5. Previsões para a série temporal

Para avaliar a precisão das previsões, calculou-se o erro quadrático médio (MSE). O MSE apresenta-se como a medida da diferença média ao quadrado entre os valores previstos e os valores reais. Neste caso, calculou-se o MSE utilizando a diferença entre as previsões e os valores reais. Um MSE menor indica previsões mais precisas.

# Calcular o erro quadrático médio (MSE)
mse <- mean ((forecasted$mean - test_data)^2)
print(paste('Mean Squared Error:',mse))

Após o cálculo do MSE, com um valor de 15.69 (aproximadamente), prosseguiu-se com a análise dos resíduos. Esta é importante para verificar a adecuação do modelo. Os resíduos são as diferenças entre os valores observados e os valores previstos pelo modelo. Analisou-se a autocorrelação dos resíduos para identificar padrões não captados pelo modelo.

As funções ‘’acf’’ e ‘’pacf’’ foram utilizadas para plotar a função de autocorrelação e a função de autocorrelação parcial dos resíduos. Se os gráficos ‘’acf’’ e ‘’pacf’’ dos resíduos não apresentam picos significativos fora dos intervalos de confiança, indica que os resíduos são aleatórios e o modelo é adequado.

# Análise dos resíduos
residuals <- residuals(fit)
acf(residuals, main = 'ACF dos Resíduos')
pacf(residuals, main = 'PACF dos Resíduos')

# Plotar resíduos
plot(residuals, main = 'Resíduos do Modelo ARIMA', ylab = 'Resíduos')

O gráfico remetente aos resíduos exibe, portanto, os resíduos do modelo ARIMA usado para prever a temperatura em Tóquio de 2019 a 2020. Os resíduos representam a diferença entre os valores observados e os valores previstos pelo modelo ARIMA. Os resíduos parecem estar centrados em torno de zero, o que é um bom sinal. Isto sugere que o modelo ARIMA, em média, não está sistematicamente a super ou subestimar as temperaturas.

O gráfico mostra que os resíduos mantêm uma variação relativamente constante ao longo do tempo, o que é um indicativo de variância constante dos resíduos. Esta é uma boa propriedade para um modelo de série temporal, pois indica que os erros de previsão não aumentam nem diminuem de maneira sistemática ao longo do tempo.

Idealmente, os resíduos de um modelo ARIMA devem mostrar um “ruído branco”, ou seja, devem ser não correlacionados e não devem apresentar padrões ou tendências. O gráfico parece mostrar uma distribuição aleatória sem padrões visíveis, o que sugere que o modelo capturou bem as principais tendências e sazonalidades da série temporal.

Embora a maior parte dos resíduos esteja em torno de 0, há alguns picos de desvios maiores (acima de 4 ou abaixo de -6), indicando que o modelo teve alguns momentos onde não conseguiu capturar totalmente as variações da série temporal, possivelmente devido a eventos extremos ou fatores não modelados.

Por fim, decidiu-se aplicar o teste de Ljung-Box para verificar a hipótese de que os resíduiso de facto não são autocorrelacionados. Um p-value alto (geralmente superior a 0.05) indica que não existe autocorrelação significativa nos resíduos. Como p=0.69, o mesmo comprova-se.

# Teste de Ljung-Box
Box.test(residuals, lag = 20, type = 'Ljung-Box')

6. Conclusão

A análise das temperaturas médias diárias registadas em Tóquio entre 1 de janeiro de 2019 e 31 de março de 2020 proporcionou uma compreensão detalhada da estrutura da série temporal, culminando em previsões fundamentadas e pontos relevantes. O processo iniciou-se com uma análise descritiva dos dados, que revelou padrões sazonais claros e uma variabilidade diária notável, características típicas de séries temporais meteorológicas. A ausência de valores em falta facilitou a modelagem e garantiu a integridade dos resultados.

A decomposição da série temporal, apesar de limitada devido ao curto período de observação, foi capaz de isolar componentes essenciais como a tendência e a sazonalidade, reforçando a importância de modelar corretamente as oscilações ao longo das estações do ano. Isso indicou uma série temporal que segue um ciclo natural das estações, com picos no verão e mínimas no inverno.

O modelo ARIMA, selecionado automaticamente através do método ‘’auto.arima’’, mostrou-se eficaz ao capturar as dinâmicas principais da série, incluindo os padrões sazonais e a tendência de longo prazo. Com a escolha do modelo ARIMA(2,1,2), as previsões para os meses subsequentes exibiram uma trajetória consistente com os padrões históricos de temperatura, o que indica que o modelo conseguiu generalizar bem as flutuações da série temporal. O erro quadrático médio (MSE = 15.69) demonstrou que o modelo tem uma precisão razoável, embora haja espaço para melhorias, especialmente nos momentos em que ocorreram desvios maiores.

A análise dos resíduos do modelo revelou resultados positivos. Os resíduos apresentaram-se como “ruído branco”, ou seja, não mostraram padrões ou autocorrelações significativas, sugerindo que o modelo conseguiu capturar a maior parte da estrutura da série temporal. Picos esporádicos de erros, no entanto, indicam que o modelo poderia ser aprimorado para capturar eventos climáticos atípicos. A variância constante dos resíduos ao longo do tempo e o teste de Ljung-Box, com um p-valor de 0.69, confirmaram que o modelo ajustado não apresentou autocorrelação significativa, o que valida ainda mais a adequação do ARIMA para este conjunto de dados.

Em resumo, o modelo ARIMA selecionado foi eficaz para prever as temperaturas médias diárias em Tóquio, capturando com precisão os padrões sazonais e as tendências. A análise dos resíduos e os testes de diagnóstico corroboraram a adequação do modelo, tornando-o uma ferramenta confiável para previsões futuras, com uma margem de erro relativamente baixa. Este trabalho demonstra a importância de um processo rigoroso de análise de séries temporais para entender comportamentos climáticos e oferece uma base sólida para estudos meteorológicos futuros ou previsões de temperatura em outras cidades ou regiões com padrões climáticos semelhantes.

7. Referências

Morettin, P. A., & Toloi, C. M. de C. (2022). Análise de séries temporais. São Paulo: Blucher.

LS0tDQp0aXRsZTogIkFuw6FsaXNlIGRlIFPDqXJpZXMgVGVtcG9yYWlzIGVtIFIiDQpzdWJ0aXRsZTogJ1RlbXBlcmF0dXJhIE3DqWRpYSBEacOhcmlhIGVtIFTDs3F1aW8nDQphdXRob3I6ICdTeWx2aWUgTWFydGlucyBCb3JnZXMnDQpkYXRlOiAnMjEtMDktMjAyNCcNCm91dHB1dDogaHRtbF9ub3RlYm9vaw0KICAgDQotLS0NCg0KIyAxLiBQcmVmw6FjaW8NCg0KRXN0ZSBlc3R1ZG8gYXByZXNlbnRhIHVtYSBhbsOhbGlzZSBkZXRhbGhhZGEgZGFzIHRlbXBlcmF0dXJhcyBtw6lkaWFzIGRpw6FyaWFzIHJlZ2lzdGFkYXMgZW0gVMOzcXVpbyBlbnRyZSBqYW5laXJvIGRlIDIwMTkgZSBtYXLDp28gZGUgMjAyMCwgdXRpbGl6YW5kbyB0w6ljbmljYXMgZGUgbW9kZWxhZ2VtIGRlIHPDqXJpZXMgdGVtcG9yYWlzLiBBdHJhdsOpcyBkYSBhcGxpY2HDp8OjbyBkbyBtb2RlbG8gQVJJTUEsIGV4cGxvcmFtLXNlIHBhZHLDtWVzIHNhem9uYWlzIGUgdGVuZMOqbmNpYXMgcXVlIGNhcmFjdGVyaXphbSBvIGNsaW1hIGRlIFTDs3F1aW8gZHVyYW50ZSBlc3NlIHBlcsOtb2RvLiBBIG1vZGVsYWdlbSBwZXJtaXRlIG7Do28gc8OzIGNvbXByZWVuZGVyIGFzIHZhcmlhw6fDtWVzIGhpc3TDs3JpY2FzIGRhcyB0ZW1wZXJhdHVyYXMsIGNvbW8gdGFtYsOpbSBwcmV2ZXIgdmFsb3JlcyBmdXR1cm9zIGNvbSB1bSBncmF1IHJhem/DoXZlbCBkZSBwcmVjaXPDo28uIE8gcmVsYXTDs3JpbyBvZmVyZWNlIHVtYSBhYm9yZGFnZW0gcHLDoXRpY2Egw6AgYW7DoWxpc2UgZGUgc8OpcmllcyB0ZW1wb3JhaXMsIGRlc2RlIGEgdmlzdWFsaXphw6fDo28gZG9zIGRhZG9zIGF0w6kgw6AgdmFsaWRhw6fDo28gZG9zIG1vZGVsb3MsIHByb3BvcmNpb25hbmRvIHVtYSB2aXPDo28gaW50ZWdyYWRhIGRvcyBtw6l0b2RvcyBlc3RhdMOtc3RpY29zIHV0aWxpemFkb3MgbmEgcHJldmlzw6NvIGNsaW3DoXRpY2EuDQoNCkF1dG9yDQoNClN5bHZpZSBCb3JnZXMsIG5hc2NpZGEgZW0gMTk5OSwgw6kgdW1hIGVudHVzaWFzdGEgZGFzIENpw6puY2lhcyBIdW1hbmFzIGUgdGVtIHRyaWxoYWRvIHVtIHBlcmN1cnNvIGFjYWTDqW1pY28gcXVlIHJlZmxldGUgYSBzdWEgcGFpeMOjbyBwZWxvIGNvbmhlY2ltZW50byBlIHBlbGEgZ2VzdMOjbyBkZSBwZXNzb2FzLiBJbmljaW91IGEgc3VhIGZvcm1hw6fDo28gbmEgcHJlc3RpZ2lhZGEgVW5pdmVyc2lkYWRlIENhdMOzbGljYSBQb3J0dWd1ZXNhLCBvbmRlIHNlIGdyYWR1b3UgZW0gTMOtbmd1YXMgRXN0cmFuZ2VpcmFzIEFwbGljYWRhcy4gU2VtcHJlIG1vdmlkYSBwZWxhIGN1cmlvc2lkYWRlIGludGVsZWN0dWFsLCBjb250aW51b3Ugb3MgZXN0dWRvcyBjb20gdW0gTWVzdHJhZG8gZW0gR2VzdMOjbyBkZSBSZWN1cnNvcyBIdW1hbm9zLCBwZWxvIElTQ1RFIEJ1c2luZXNzIFNjaG9vbCwgY2FtcG8gb25kZSBkZXNlbnZvbHZldSB1bWEgc8OzbGlkYSBjb21wcmVlbnPDo28gZGEgZGluw6JtaWNhIG9yZ2FuaXphY2lvbmFsLg0KDQpDb20gdW0gb2xoYXIgYXRlbnRvIMOgcyBtdWRhbsOnYXMgZG8gbXVuZG8gbW9kZXJubywgU3lsdmllIHBlcmNlYmV1IHF1ZSBhcyBUZWNub2xvZ2lhcyBkYSBJbmZvcm1hw6fDo28gcmVwcmVzZW50YXZhbSB1bSBub3ZvIGhvcml6b250ZSBwYXJhIGEgZ2VzdMOjbyBkZSBwZXNzb2FzLiBEZXNkZSAyMDIxLCB0ZW0tc2UgZGVkaWNhZG8gYSBleHBsb3JhciBlc3RlIGRvbcOtbmlvIGVtZXJnZW50ZSwgY29uc3RydWluZG8gdW1hIHBvbnRlIGVudHJlIGEgY29tdW5pY2HDp8OjbywgZ2VzdMOjbyBlIGFzIG5vdmFzIGZlcnJhbWVudGFzIHRlY25vbMOzZ2ljYXMuIEVtIGJ1c2NhIGRlIHVtYSBjb21wcmVlbnPDo28gYWluZGEgbWFpcyBwcm9mdW5kYSwgaW5zY3JldmV1LXNlIG51bWEgUMOzcy1HcmFkdWHDp8OjbyBlbSBEYXRhIFNjaWVuY2UgKFVuaXZlcnNpZGFkZSBFdXJvcGVpYSksIGRldGVybWluYWRhIGEgZG9taW5hciBvcyBtw6l0b2RvcyBlIGxpbmd1YWdlbnMgcXVlIG1vbGRhbSBvIHF1b3RpZGlhbm8gZG9zIHByb2Zpc3Npb25haXMgZGFzIFRJLCBlbnJpcXVlY2VuZG8gYXNzaW0gYSBzdWEgY2FwYWNpZGFkZSBkZSBpbnRlcmFnaXIgY29tIGVzdGUgdW5pdmVyc28gZW0gY29uc3RhbnRlIGV2b2x1w6fDo28uDQoNCkxpY2Vuw6dhIEVzdGUgdHJhYmFsaG8gZXN0w6EgbGljZW5jaWFkbyBzb2IgdW1hIGxpY2Vuw6dhIENyZWF0aXZlIENvbW1vbnMgQXR0cmlidXRpb24tTm9uQ29tbWVyY2lhbCBTaGFyZUFsaWtlIDQuMCBJbnRlcm5hdGlvbmFsIExpY2Vuc2UuIE8gcmVzdWx0YWRvIGRlc3RlIHRyYWJhbGhvIG7Do28gcHJvdmlkZW5jaWEgYWNvbnNlbGhhbWVudG8gZmluYW5jZWlyby4NCg0KDQoNCiMgMi4gSW50cm9kdcOnw6NvDQoNCk8gcHJlc2VudGUgZXN0dWRvIHRlbSBjb21vIG9iamV0aXZvIGEgYW7DoWxpc2UgZGUgdW1hIHPDqXJpZSB0ZW1wb3JhbCByZWZlcmVudGUgw6BzIHRlbXBlcmF0dXJhcyBtw6lkaWFzIGRpw6FyaWFzIHJlZ2lzdGFkYXMgZW0gVMOzcXVpbyBlbnRyZSAxIGRlIGphbmVpcm8gZGUgMjAxOSBlIDMxIGRlIG1hcsOnbyBkZSAyMDIwLiBPIGRhdGFzZXQgdXRpbGl6YWRvIHJlbWV0ZSBwYXJhIHRlbXBlcmF0dXJhIG3DqWRpYSBkacOhcmlhIGVtIGdyYXVzIENlbHNpdXMgZSBzZXLDoSBhbmFsaXNhZG8gY29tIHJlY3Vyc28gYSBtw6l0b2RvcyBkZSBzw6lyaWVzIHRlbXBvcmFpcyBhYm9yZGFkb3Mgbm8gY3Vyc28gZGUgQW7DoWxpc2UgZGUgU8OpcmllcyBUZW1wb3JhaXMuDQoNCkEgYW7DoWxpc2UgZGUgc8OpcmllcyB0ZW1wb3JhaXMgYXByZXNlbnRhLXNlIGNvbW8gdW1hIHTDqWNuaWNhIGVzdGF0w61zdGljYSBxdWUgcGVybWl0ZSBlc3R1ZGFyIG9zIGRhZG9zIHNlcXVlbmNpYWlzIGFvIGxvbmdvIGRvIHRlbXBvLCBpZGVudGlmaWNhciBwYWRyw7VlcyBlIHJlYWxpemFyIHByZXZpc8O1ZXMgZnV0dXJhcyBjb20gYmFzZSBlbSBkYWRvcyBoaXN0w7NyaWNvcy4gRXN0ZSB0aXBvIGRlIGFuw6FsaXNlIMOpIGFtcGxhbWVudGUgdXRpbGl6YWRvIGVtIGRpdmVyc2FzIMOhcmVhcywgY29tbyBhIG1ldGVvcm9sb2dpYSwgZWNvbm9taWEgZSBmaW5hbsOnYXMsIGRldmlkbyDDoCBzdWEgY2FwYWNpZGFkZSBkZSBtb2RlbGFyIGUgcHJldmVyIGNvbXBvcnRhbWVudG9zIGZ1dHVyb3MuDQoNClBhcmEgbyBkZXNlbnZvbHZpbWVudG8gZGVzdGUgdHJhYmFsaG8sIHNlcsOjbyBleHBsb3JhZG9zIGRpZmVyZW50ZXMgbW9kZWxvcyBkZSBzw6lyaWVzIHRlbXBvcmFpcywgY29tbyBvIEFSSU1BIGUgb3V0cm9zIG3DqXRvZG9zLiBPIG9iamV0aXZvIMOpIHNlbGVjaW9uYXIgbyBtb2RlbG8gcXVlIG1lbGhvciBzZSBhanVzdGEgYW9zIGRhZG9zIGRlIHRlbXBlcmF0dXJhIGUsIGNvbSBiYXNlIG5lc3NlIG1vZGVsbywgcmVhbGl6YXIgcHJldmlzw7VlcyBwYXJhIHBlcsOtb2RvcyBmdXR1cm9zLg0KDQpBbMOpbSBkaXNzbywgc2Vyw6EgZmVpdGEgdW1hIGFuw6FsaXNlIGRvcyByZXPDrWR1b3MgZG8gbW9kZWxvIHNlbGVjaW9uYWRvIHBhcmEgdmVyaWZpY2FyIGEgc3VhIGFkZXF1YcOnw6NvIGUsIHBvciBmaW0sIHNlcsOhIGFwcmVzZW50YWRvIHVtIGNvbmp1bnRvIGRlIHByZXZpc8O1ZXMgY29tIGJhc2Ugbm9zIGRhZG9zIGRpc3BvbsOtdmVpcy4gQXMgZGVjaXPDtWVzIHRvbWFkYXMgYW8gbG9uZ28gZG8gcHJvY2Vzc28gc2Vyw6NvIGRldmlkYW1lbnRlIGp1c3RpZmljYWRhcyBlIGRvY3VtZW50YWRhcyBubyByZWxhdMOzcmlvLg0KDQpPIHRyYWJhbGhvIHNlcsOhIGRlc2Vudm9sdmlkbyB1dGlsaXphbmRvIG8gc29mdHdhcmUgUiwgZSBvIHJlbGF0w7NyaW8gZmluYWwgaW5jbHVpcsOhIHRvZGFzIGFzIGFuw6FsaXNlcywgZ3LDoWZpY29zIGUgcHJldmlzw7VlcywgY29uZm9ybWUgYXMgaW5zdHJ1w6fDtWVzIGZvcm5lY2lkYXMuDQoNCiMgMy4gQW7DoWxpc2UgZGVzY3JpdGl2YSBkYSBzw6lyaWUgdGVtcG9yYWwNCg0KIyMgMy4xKSBWaXN1YWxpemHDp8Ojbw0KDQpPIHByaW1laXJvIHBhc3NvIHJlYWxpemFkbyBmb2kgbyBjYXJyZWdhbWVudG8gZG8gZGF0YXNldCBlIGEgdmlzdWFsaXphw6fDo28gZG9zIGRhZG9zLCB1dGlsaXphbmRvIGEgbGluZ3VhZ2VtIFIgcGFyYSBhIHRhcmVmYS4gUHJvY2VkZXUtc2UgYW8gY2FycmVnYW1lbnRvIGRvIGRhdGFzZXQgcHJldGVuZHVkaSBlIGNvbnZlcnRldS1zZSBhIGNvbHVuYSAnJ0RhdGUnJyBwYXJhIG8gZm9ybWF0byBkZSBkYXRhLiBEZSBzZWd1aWRhLCB2aXN1YWxpemFyYW0tc2Ugb3MgcHJpbWVpcm9zIHJlZ2lzdG9zIGRvIGRhdGFzZXQgcGFyYSBnYXJhbnRpciBxdWUgb3MgZGFkb3MgZm9yYW0gY2FycmVnYWRvcyBjb3JyZXRhbWVudGUuIFBvciBmaW0sIHBsb3RvdS1zZSBhIHPDqXJpZSB0ZW1wb3JhbCB1dGlsaXphbmRvIGEgYmlibGlvdGVjYSAnJ2dncGxvdDInJyBwYXJhIG9ic2VydmFyIGEgdmFyaWHDp8OjbyBkYSB0ZW1wZXJhdHVyYSBhbyBsb25nbyBkbyB0ZW1wby4NCg0KUXVhbnRvIGFvIGdyw6FmaWNvIG9idGlkbywgbyBtZXNtbyBtb3N0cmEgdGVtcGVyYXR1cmEgbcOpZGlhIGRpw6FyaWEgZW0gVMOzcXVpbyBlbnRyZSAyMDE5IGUgMjAyMCwgc2VuZG8gcXVlIHNlIHBvZGVtIHJldGlyYXIgYWxndW1hcyBvYnNlcnZhw6fDtWVzOg0KDQohW10oMi5WaXN1YWxpemFyJTIwYSUyMGVzdHJ1dHVyYSUyMGRvJTIwZGF0YXNldC5wbmcpDQoNCi0gICBFeGlzdGUgdW0gcGFkcsOjbyBiZW0gZGVmaW5pZG8gcXVlIHNlZ3VlIGFzIGVzdGHDp8O1ZXMgZG8gYW5vLiBBcyB0ZW1wZXJhdHVyYXMgY29tZcOnYW0gbWFpcyBiYWl4YXMgbm8gaW7DrWNpbyBkZSAyMDE5LCBhdW1lbnRhbmRvIGdyYWR1YWxtZW50ZSBhdMOpIGF0aW5naXIgdW0gcGljbyBwb3Igdm9sdGEgZGUganVsaG8gYSBhZ29zdG8sIHJlcHJlc2VudGFuZG8gbyB2ZXLDo28uIEFww7NzIG8gcGljbywgYXMgdGVtcGVyYXR1cmFzIGNvbWXDp2FtIGEgY2FpciBub3ZhbWVudGUsIGNoZWdhbmRvIGEgdW0gcG9udG8gbWFpcyBiYWl4byBubyBpbnZlcm5vIChkZXplbWJybyBlIGphbmVpcm8pOw0KDQotICAgQSB0ZW1wZXJhdHVyYSBhdGluZ2UgbyBzZXUgdmFsb3IgbcOheGltbyBlbSB0b3JubyBkZSAzMMKwQyBkdXJhbnRlIG8gdmVyw6NvIChwb3Igdm9sdGEgZGUganVsaG8vYWdvc3RvIGRlIDIwMTkpIGUgbyBzZXUgdmFsb3IgbWFpcyBiYWl4bywgcHLDs3hpbW8gZGUgMMKwQywgbm8gaW52ZXJubyAoamFuZWlybyBkZSAyMDIwKTsNCg0KLSAgIEVtYm9yYSBvIHBhZHLDo28gZ2VyYWwgc2VqYSB1bWEgY3VydmEgc3VhdmUsIGV4aXN0ZW0gZmx1dHVhw6fDtWVzIGRpw6FyaWFzIGNvbnNpZGVyw6F2ZWlzLCBvIHF1ZSByZWZsZXRlIGEgdmFyaWFiaWxpZGFkZSBkbyBjbGltYSBubyBkaWEtYS1kaWEuDQoNCmBgYHtyfQ0KIyBDYXJyZWdhciBwYWNvdGVzIG5lY2Vzc8Ohcmlvcw0KbGlicmFyeShnZ3Bsb3QyKQ0KDQojIEltcG9ydGFyIG8gZGF0YXNldA0KZGF0YSA8LSByZWFkLmNzdigiQzovVXNlcnMvU3lsdmllL0Rvd25sb2Fkcy9UZW1wZXJhdHVyYV9Ub3F1aW9fZGF0YXNldC5jc3YiKQ0KDQojIFZlcmlmaWNhciBhcyBwcmltZWlyYXMgbGluaGFzIGRvcyBkYWRvcw0KaGVhZChkYXRhKQ0KDQojIENvbnZlcnRlciBhIGNvbHVuYSAnRGF0ZScgcGFyYSBmb3JtYXRvIGRlIGRhdGENCmRhdGEkRGF0ZSA8LSBhcy5EYXRlKGRhdGEkRGF0ZSkNCg0KIyBWaXN1YWxpemFyIGEgZXN0cnV0dXJhIGRvIGRhdGFzZXQNCnN0cihkYXRhKQ0KDQojVmlzdWFsaXphciBhIHPDqXJpZSB0ZW1wb3JhbA0KIyBDcmlhciB1bSBncsOhZmljbyBkYSBzw6lyaWUgdGVtcG9yYWwNCmdncGxvdChkYXRhLCBhZXMoeCA9IERhdGUsIHkgPSBUZW1wZXJhdHVyZSkpICsNCiAgZ2VvbV9saW5lKGNvbG9yID0gImJsdWUiKSArDQogIGxhYnModGl0bGUgPSAiVGVtcGVyYXR1cmEgTcOpZGlhIERpw6FyaWEgZW0gVMOzcXVpbyAoMjAxOS0yMDIwKSIsDQogICAgICAgeCA9ICJEYXRhIiwgeSA9ICJUZW1wZXJhdHVyYSAowrBDKSIpICsNCiAgdGhlbWVfbWluaW1hbCgpDQoNCmBgYA0KDQojIyAzLjIpIERlY29tcG9zacOnw6NvDQoNCkFww7NzLCBwcm9jZWRldS1zZSBhIHVtYSBhbsOhbGlzZSBlc3RhdMOtc3RpY2EgYsOhc2ljYSBwYXJhIGNvbXByZWVuZGVyIGEgZGlzdHJpYnVpw6fDo28gaW5pY2lhbCBkb3MgZGFkb3MsIG9idGVuZG8gaW5mb3JtYcOnw7VlcyBzb2JyZSBvIE3DrW5pbW8gKDAuODkwKSwgMcK6UXVhcnRpbCAoNy45NzUpLCBNZWRpYW5hICgxMy43OTApLCBNw6lkaWEgKDE0Ljk3OCksIDPCulF1YXJ0aWwgKDIxLjgzMCkgZSBvIE3DoXhpbW8gKDMwLjMwMCk7IHF1ZSBwZXJtaXRlbSBlbnRlbmRlciBhIGRpc3RyaWJ1acOnw6NvLCBjZW50cmFsaWRhZGUgZSBkaXNwZXJzw6NvIGRhIHZhcmnDoXZlbCAnJ1RlbXBlcmF0dXJhJycuIFBlcm1pdGUsIHRhbWLDqW0sIGlkZW50aWZpY2FyIHBvc3PDrXZlaXMgb3V0bGllcnMgb3UgY29tcG9ydGFtZW50b3MgYW7Ds21hbG9zIG5vcyBkYWRvcy4gRGVwb2lzLCB2ZXJpZmljYXJhbS1zZSBvcyB2YWxvcmVzIGVtIGZhbHRhLiBFc3RhIHZlcmlmaWNhw6fDo28gw6kgZXNzZW5jaWFsIHBhcmEgYXNzZWd1cmFyIHF1ZSBuw6NvIGjDoSB2YWxvcmVzIGVtIGZhbHRhIChOQSkgbm8gY29uanVudG8gZGUgZGFkb3MuIFZhbG9yZXMgYXVzZW50ZXMgcG9kZW0gaW1wYWN0YXIgbmVnYXRpdmFtZW50ZSBhcyBhbsOhbGlzZXMgZSBhIG1vZGVsYWdlbSwgZXNwZWNpYWxtZW50ZSBlbSBzw6lyaWVzIHRlbXBvcmFpcywgcG9pcyBvcyBtb2RlbG9zIGV4aWdlbSBzw6lyaWVzIGNvbXBsZXRhcy4gU2UgZXhpc3Rpc3NlbSB2YWxvcmVzIGVtIGZhbHRhIChuw6NvIMOpIG8gY2FzbywgdmlzdG8gcXVlIG7Do28gZXhpc3RlbSB2YWxvcmVzIGVtIGZhbHRhKSwgc2VyaWEgbmVjZXNzw6FyaW8gdHJhdGFyIGVzc2VzIGRhZG9zIGFudGVzIGRlIGNvbnRpbnVhciBhIGFuw6FsaXNlLCBwb3IgZXhlbXBsbywgaW1wdXRhbmRvIG91IGludGVycG9sYW5kbyBvcyB2YWxvcmVzIGF1c2VudGVzLiBEZSBzZWd1aWRhLCBwcm9jZWRldS1zZSDDoCBkZWNvbXBvc2nDp8OjbyBkYSBzw6lyaWUgdGVtcG9yYWwuIEVzdGUgbcOpdG9kbyBwZXJtaXRlIHNlcGFyYXIgYSBzw6lyaWUgZW0gY29tcG9uZW50ZXMgZGUgdGVuZMOqbmNpYSwgc2F6b25hbGlkYWRlIGUgcmVzw61kdW9zLCBvIHF1ZSBwZXJtaXRlIHVtIG1lbGhvciBlbnRlbmRpbWVudG8gZGEgZXN0cnV0dXJhIGRvcyBkYWRvcy4gQ29udmVydGVuZG8gb3MgZGFkb3MgbnVtYSBzw6lyaWUgdGVtcG9yYWwgKHRzKSwgcG9kZW1vcyBkZWNvbXBvciBhIHPDqXJpZSB1c2FuZG8gYSBmdW7Dp8OjbyAnJ2RlY29tcG9zZScnLiBPIHJlc3VsdGFkbyDDqSB1bSBncsOhZmljbyBxdWUgZGVtb25zdHJhIGEgdGVuZMOqbmNpYSAodmFyaWHDp8OjbyBkZSBsb25nbyBwcmF6byksIGEgc2F6b25hbGlkYWRlIChwYWRyw7VlcyByZXBldGl0aXZvcykgZSBvcyByZXPDrWR1b3MgKHZhcmlhw6fDtWVzIGFsZWF0w7NyaWFzKS4gTmVzdGUgY2FzbywgYSBzw6lyaWUgdGVtcG9yYWwgbsOjbyBhcHJlc2VudGEgcGVyw61vZG9zIG91IHRlbSBtZW5vcyBkbyBxdWUgZG9pcywgbyBxdWUgbsOjbyBub3MgcGVybWl0ZSB0aXJhciBjb25jbHVzw7VlcyBhc3NlcnRpdmFzLg0KDQpgYGB7cn0NCiMgUmVzdW1vIGVzdGF0w61zdGljbyBiw6FzaWNvIGRhIHRlbXBlcmF0dXJhDQpzdW1tYXJ5KGRhdGEkVGVtcGVyYXR1cmUpDQoNCiMgVmVyaWZpY2FyIHNlIGjDoSB2YWxvcmVzIGVtIGZhbHRhIChOQSkNCnN1bShpcy5uYShkYXRhJFRlbXBlcmF0dXJlKSkNCg0KDQojIERlY29tcG9zacOnw6NvIGRhIHPDqXJpZSB0ZW1wb3JhbA0KIyBJbnN0YWxhciBvIHBhY290ZSAnZm9yZWNhc3QnDQojIGluc3RhbGwucGFja2FnZXMoImZvcmVjYXN0IikNCmxpYnJhcnkoZm9yZWNhc3QpDQoNCiMgQ29udmVydGVyIGEgc8OpcmllIHRlbXBvcmFsDQp0c19kYXRhIDwtIHRzKGRhdGEkVGVtcGVyYXR1cmUsIHN0YXJ0ID0gYygyMDE5LCAxKSwgZnJlcXVlbmN5ID0gMzY1KQ0KDQojIERlY29tcG9zacOnw6NvIGRhIHPDqXJpZSB0ZW1wb3JhbA0KZGVjb21wb3NlZCA8LSBkZWNvbXBvc2UodHNfZGF0YSkNCnBsb3QoZGVjb21wb3NlZCkNCmBgYA0KDQojIDQuIE1vZGVsYcOnw6NvIGRhIHPDqXJpZSB0ZW1wb3JhbA0KDQpQcmltZWlyYW1lbnRlLCBvcHRvdS1zZSBwZWxhIGRpdmlzw6NvIGRvcyBkYWRvcy4gRXN0ZSBwYXNzbyBwZXJtaXRlIGF2YWxpYXIgYSBwcmVjaXPDo28gZG8gbW9kZWxvLCBkaXZpZGluZG8gb3MgZGFkb3MgZW0gY29uanVudG9zIGRlIHRyZWlubyBlIGRlIHRlc3RlLiBPIGNvbmp1bnRvIGRlIHRyZWlubyDDqSB1dGlsaXphZG8gcGFyYSBhanVzdGFyIG8gbW9kZWxvLCBlbnF1YW50byBxdWUgbyBjb25qdW50byBkZSB0ZXN0ZSDDqSB1dGlsaXphZG8gcGFyYSB2YWxpZGFyIHByZXZpc8O1ZXMuTmVzdGUgcGFzc28sIHV0aWxpem91LXNlIGEgZnVuw6fDo28gJyd3aW5kb3cnJyBwYXJhIGRpdmlkaXIgb3MgZGFkb3MuIE8gY29uanVudG8gZGUgdHJlaW5vIGluY2x1aSBvcyBkYWRvcyBhdMOpIDI5LTAyLTIwMjAgZSBvIGNvbmp1bnRvIGRlIHRlc3RlIGluY2x1aSBvcyBkYWRvcyBhIHBhcnRpciBkZSAwMS0wMy0yMDIwLg0KDQpgYGB7cn0NCiMgRGl2aWRpciBvcyBkYWRvcyBlbSB0cmVpbm8gZSB0ZXN0ZQ0KdHJhaW5fZGF0YSA8LSB3aW5kb3codHNfZGF0YSxlbmQgPSBjKDIwMjAsIDU5KSkNCnRlc3RfZGF0YSA8LSB3aW5kb3codHNfZGF0YSwgc3RhcnQgPSBjKDIwMjAsIDYwKSkNCg0KIyBWZXJpZmljYXIgb3MgZGFkb3MgZGUgdHJlaW5vIGUgdGVzdGUNCmhlYWQodHJhaW5fZGF0YSkNCmhlYWQodGVzdF9kYXRhKQ0KYGBgDQoNCkFww7NzIGEgZGl2aXPDo28gZG9zIGRhZG9zLCBwcm9zc2VndWl1LXNlIHBhcmEgYSBhcGxpY2HDp8OjbyBkbyBtb2RlbG8gQVJJTUEuIEVzdGUgbW9kZWxvIMOpIHV0aWxpemFkbyBwYXJhIG1vZGVsYXIgc8OpcmllcyB0ZW1wb3JhaXMuIFV0aWxpemEtc2UgYSBmdW7Dp8OjbyAnJ2F1dG8uYXJpbWEnJyBwYXJhIGlkZW50aWZpY2FyIGF1dG9tYXRpY2FtZW50ZSBvIG1lbGhvciBtb2RlbG8gQVJJTUEgcGFyYSBvcyBkYWRvcyBkZSB0cmVpbm8uDQoNCk8gcmVzdW1vIGRvIG1vZGVsbyAoc3VtbWFyeSkgZm9ybmVjZSBpbmZvcm1hw6fDtWVzIGRldGFsaGFkYXMgc29icmUgb3MgcGFyw6JtZXRyb3MgZG8gbW9kZWxvLiBEZSBzZWd1aWRhLCBvcHRvdS1zZSBwZWxhIGZ1bsOnw6NvICcnZm9yZWNhc3QnJyBwYXJhIGZhemVyIHByZXZpc8O1ZXMgcGFyYSBvIHBlcsOtb2RvIGRlIHRlc3RlIGUgcGxvdG91LXNlIGFzIHByZXZpc8O1ZXMganVudG8gY29tIG9zIHZhbG9yZXMgcmVhaXMuDQoNCmBgYHtyfQ0KIyBJZGVudGlmaWNhw6fDo28gZG8gbW9kZWxvIEFSSU1BDQpmaXQgPC0gYXV0by5hcmltYSh0cmFpbl9kYXRhKQ0Kc3VtbWFyeShmaXQpDQoNCiMgUHJldmlzw7Vlcw0KZm9yZWNhc3RlZCA8LSBmb3JlY2FzdChmaXQsIGggPWxlbmd0aCh0ZXN0X2RhdGEpKQ0KcGxvdChmb3JlY2FzdGVkKQ0KbGluZXModGVzdF9kYXRhLCBjb2wgPSByZ2IoMSwwLDApKQ0KYGBgDQoNCkVtIG3DqWRpYSwgbyBtb2RlbG8gQVJJTUEoMiwxLDIpIGFqdXN0b3Utc2UgYmVtIGFvcyBkYWRvcyBjb20gdW0gZXJybyByZWxhdGl2YW1lbnRlIGJhaXhvIChSTVNFID0gMS44ODU1KSBlIHVtIE1BUEUgZGUgMTYuMTglLCBvIHF1ZSBzdWdlcmUgdW1hIHByZWNpc8OjbyByYXpvw6F2ZWwgbmFzIHByZXZpc8O1ZXMuIE8gdmFsb3IgZGUgQUNGMSBtdWl0byBwcsOzeGltbyBkZSAwIHN1Z2VyZSBxdWUgbyBtb2RlbG8gY2FwdHVyb3UgYSBtYWlvciBwYXJ0ZSBkYSBlc3RydXR1cmEgZGEgc8OpcmllIHRlbXBvcmFsLCBlIG9zIHJlc8OtZHVvcyBwYXJlY2VtIHNlciBydcOtZG8gYWxlYXTDs3Jpbywgc2VtIGNvcnJlbGHDp8OjbyBzaWduaWZpY2F0aXZhLg0KDQpDb20gYmFzZSBubyBncsOhZmljbyBhcHJlc2VudGFkbywgYSBsaW5oYSBwcmV0YSByZXByZXNlbnRhIG9zIGRhZG9zIGhpc3TDs3JpY29zLCBlbnF1YW50byBxdWUgYSDDoXJlYSBzb21icmVhZGEgZSBhcyBsaW5oYXMgYSB2ZXJtZWxobyBpbmRpY2FtIGFzIHByZXZpc8O1ZXMgcGFyYSBvIGZ1dHVybzoNCg0KIVtdKDYuRm9yZWNhc3QlMjBBcmltYS5wbmcpDQoNCi0gICBPIG1vZGVsbyBBUklNQSgyLDEsMikgZm9pIHVzYWRvIHBhcmEgcHJldmVyIGFzIHRlbXBlcmF0dXJhcyBmdXR1cmFzLCBzZW5kbyDDunRpbCBwYXJhIGNhcHR1cmFyIHBhZHLDtWVzIHNhem9uYWlzIGUgdGVuZMOqbmNpYXMgbmEgc8OpcmllIHRlbXBvcmFsOw0KDQotICAgQSDDoXJlYSBzb21icmVhZGEgZW0gY2luemEgYW8gcmVkb3IgZGEgcHJldmlzw6NvIGluZGljYSBvIGludGVydmFsbyBkZSBjb25maWFuw6dhLCBvdSBzZWphLCBhIGluY2VydGV6YSBkYSBwcmV2aXPDo28uIFF1YW50byBtYWlzIGxvbmdlIG5vIGZ1dHVybywgbWFpb3IgYSBmYWl4YSwgbyBxdWUgcmVmbGV0ZSBvIGF1bWVudG8gZGEgaW5jZXJ0ZXphLiBObyBncsOhZmljbywgbyBpbnRlcnZhbG8gZXhwYW5kZS1zZSBsaWdlaXJhbWVudGUgY29uZm9ybWUgbyB0ZW1wbyBhdmFuw6dhLCBvIHF1ZSDDqSBjb211bSBlbSBwcmV2aXPDtWVzIGRlIHPDqXJpZXMgdGVtcG9yYWlzOw0KDQotICAgQSBsaW5oYSB2ZXJtZWxoYSBpbmRpY2EgYSBwcmV2aXPDo28sIHF1ZSBzZWd1ZSB1bSBwYWRyw6NvIHJlbGF0aXZhbWVudGUgc2VtZWxoYW50ZSBhbyBjaWNsbyBzYXpvbmFsIG9ic2VydmFkbyBhbnRlcmlvcm1lbnRlLCBjb20gb3NjaWxhw6fDtWVzIHByZXZpc3RhcywgcHJvdmF2ZWxtZW50ZSBpbmZsdWVuY2lhZGFzIHBvciBmbHV0dWHDp8O1ZXMgc2F6b25haXMuIEEgcHJldmlzw6NvIHN1Z2VyZSBxdWUgYSB0ZW1wZXJhdHVyYSBpcsOhIGNvbnRpbnVhciBjb20gdmFyaWHDp8O1ZXMgZW0gdG9ybm8gZG9zIG7DrXZlaXMgb2JzZXJ2YWRvcyBubyBmaW5hbCBkZSAyMDE5Lg0KDQpBc3NpbSwgbyBtb2RlbG8gQVJJTUEgcHJldsOqIHF1ZSBhcyB0ZW1wZXJhdHVyYXMgZW0gVMOzcXVpbyBtYW50ZXLDo28gbyBwYWRyw6NvIGRlIHZhcmlhw6fDo28sIG1hcyBjb20gdW1hIGNlcnRhIGluY2VydGV6YSBub3MgdmFsb3JlcyBleGF0b3MsIGVzcGVjaWFsbWVudGUgw6AgbWVkaWRhIHF1ZSBvIHBlcsOtb2RvIGRlIHByZXZpc8OjbyBhdmFuw6dhLg0KDQojIDUuIFByZXZpc8O1ZXMgcGFyYSBhIHPDqXJpZSB0ZW1wb3JhbA0KDQpQYXJhIGF2YWxpYXIgYSBwcmVjaXPDo28gZGFzIHByZXZpc8O1ZXMsIGNhbGN1bG91LXNlIG8gZXJybyBxdWFkcsOhdGljbyBtw6lkaW8gKE1TRSkuIE8gTVNFIGFwcmVzZW50YS1zZSBjb21vIGEgbWVkaWRhIGRhIGRpZmVyZW7Dp2EgbcOpZGlhIGFvIHF1YWRyYWRvIGVudHJlIG9zIHZhbG9yZXMgcHJldmlzdG9zIGUgb3MgdmFsb3JlcyByZWFpcy4gTmVzdGUgY2FzbywgY2FsY3Vsb3Utc2UgbyBNU0UgdXRpbGl6YW5kbyBhIGRpZmVyZW7Dp2EgZW50cmUgYXMgcHJldmlzw7VlcyBlIG9zIHZhbG9yZXMgcmVhaXMuIFVtIE1TRSBtZW5vciBpbmRpY2EgcHJldmlzw7VlcyBtYWlzIHByZWNpc2FzLg0KDQpgYGB7cn0NCiMgQ2FsY3VsYXIgbyBlcnJvIHF1YWRyw6F0aWNvIG3DqWRpbyAoTVNFKQ0KbXNlIDwtIG1lYW4gKChmb3JlY2FzdGVkJG1lYW4gLSB0ZXN0X2RhdGEpXjIpDQpwcmludChwYXN0ZSgnTWVhbiBTcXVhcmVkIEVycm9yOicsbXNlKSkNCmBgYA0KDQpBcMOzcyBvIGPDoWxjdWxvIGRvIE1TRSwgY29tIHVtIHZhbG9yIGRlIDE1LjY5IChhcHJveGltYWRhbWVudGUpLCBwcm9zc2VndWl1LXNlIGNvbSBhIGFuw6FsaXNlIGRvcyByZXPDrWR1b3MuIEVzdGEgw6kgaW1wb3J0YW50ZSBwYXJhIHZlcmlmaWNhciBhIGFkZWN1YcOnw6NvIGRvIG1vZGVsby4gT3MgcmVzw61kdW9zIHPDo28gYXMgZGlmZXJlbsOnYXMgZW50cmUgb3MgdmFsb3JlcyBvYnNlcnZhZG9zIGUgb3MgdmFsb3JlcyBwcmV2aXN0b3MgcGVsbyBtb2RlbG8uIEFuYWxpc291LXNlIGEgYXV0b2NvcnJlbGHDp8OjbyBkb3MgcmVzw61kdW9zIHBhcmEgaWRlbnRpZmljYXIgcGFkcsO1ZXMgbsOjbyBjYXB0YWRvcyBwZWxvIG1vZGVsby4NCg0KQXMgZnVuw6fDtWVzICcnYWNmJycgZSAnJ3BhY2YnJyBmb3JhbSB1dGlsaXphZGFzIHBhcmEgcGxvdGFyIGEgZnVuw6fDo28gZGUgYXV0b2NvcnJlbGHDp8OjbyBlIGEgZnVuw6fDo28gZGUgYXV0b2NvcnJlbGHDp8OjbyBwYXJjaWFsIGRvcyByZXPDrWR1b3MuIFNlIG9zIGdyw6FmaWNvcyAnJ2FjZicnIGUgJydwYWNmJycgZG9zIHJlc8OtZHVvcyBuw6NvIGFwcmVzZW50YW0gcGljb3Mgc2lnbmlmaWNhdGl2b3MgZm9yYSBkb3MgaW50ZXJ2YWxvcyBkZSBjb25maWFuw6dhLCBpbmRpY2EgcXVlIG9zIHJlc8OtZHVvcyBzw6NvIGFsZWF0w7NyaW9zIGUgbyBtb2RlbG8gw6kgYWRlcXVhZG8uDQoNCiFbXShpbWFnZXMvQ2FwdHVyYSUyMGRlJTIwZWNyw6MlMjAyMDI0LTA5LTE2JTIwMjAwNjMwLnBuZyl7d2lkdGg9IjIzMiJ9DQoNCiFbXShpbWFnZXMvQ2FwdHVyYSUyMGRlJTIwZWNyw6MlMjAyMDI0LTA5LTE2JTIwMjAwNTM1LnBuZyl7d2lkdGg9IjIzNiJ9DQoNCmBgYHtyfQ0KIyBBbsOhbGlzZSBkb3MgcmVzw61kdW9zDQpyZXNpZHVhbHMgPC0gcmVzaWR1YWxzKGZpdCkNCmFjZihyZXNpZHVhbHMsIG1haW4gPSAnQUNGIGRvcyBSZXPDrWR1b3MnKQ0KcGFjZihyZXNpZHVhbHMsIG1haW4gPSAnUEFDRiBkb3MgUmVzw61kdW9zJykNCg0KIyBQbG90YXIgcmVzw61kdW9zDQpwbG90KHJlc2lkdWFscywgbWFpbiA9ICdSZXPDrWR1b3MgZG8gTW9kZWxvIEFSSU1BJywgeWxhYiA9ICdSZXPDrWR1b3MnKQ0KYGBgDQoNCk8gZ3LDoWZpY28gcmVtZXRlbnRlIGFvcyByZXPDrWR1b3MgZXhpYmUsIHBvcnRhbnRvLCBvcyByZXPDrWR1b3MgZG8gbW9kZWxvIEFSSU1BIHVzYWRvIHBhcmEgcHJldmVyIGEgdGVtcGVyYXR1cmEgZW0gVMOzcXVpbyBkZSAyMDE5IGEgMjAyMC4gT3MgcmVzw61kdW9zIHJlcHJlc2VudGFtIGEgZGlmZXJlbsOnYSBlbnRyZSBvcyB2YWxvcmVzIG9ic2VydmFkb3MgZSBvcyB2YWxvcmVzIHByZXZpc3RvcyBwZWxvIG1vZGVsbyBBUklNQS4gT3MgcmVzw61kdW9zIHBhcmVjZW0gZXN0YXIgY2VudHJhZG9zIGVtIHRvcm5vIGRlIHplcm8sIG8gcXVlIMOpIHVtIGJvbSBzaW5hbC4gSXN0byBzdWdlcmUgcXVlIG8gbW9kZWxvIEFSSU1BLCBlbSBtw6lkaWEsIG7Do28gZXN0w6Egc2lzdGVtYXRpY2FtZW50ZSBhIHN1cGVyIG91IHN1YmVzdGltYXIgYXMgdGVtcGVyYXR1cmFzLg0KDQohW10oOC5SZXPDrWR1b3MlMjBtb2RlbG8lMjBhcmltYS5wbmcpDQoNCk8gZ3LDoWZpY28gbW9zdHJhIHF1ZSBvcyByZXPDrWR1b3MgbWFudMOqbSB1bWEgdmFyaWHDp8OjbyByZWxhdGl2YW1lbnRlIGNvbnN0YW50ZSBhbyBsb25nbyBkbyB0ZW1wbywgbyBxdWUgw6kgdW0gaW5kaWNhdGl2byBkZSB2YXJpw6JuY2lhIGNvbnN0YW50ZSBkb3MgcmVzw61kdW9zLiBFc3RhIMOpIHVtYSBib2EgcHJvcHJpZWRhZGUgcGFyYSB1bSBtb2RlbG8gZGUgc8OpcmllIHRlbXBvcmFsLCBwb2lzIGluZGljYSBxdWUgb3MgZXJyb3MgZGUgcHJldmlzw6NvIG7Do28gYXVtZW50YW0gbmVtIGRpbWludWVtIGRlIG1hbmVpcmEgc2lzdGVtw6F0aWNhIGFvIGxvbmdvIGRvIHRlbXBvLg0KDQpJZGVhbG1lbnRlLCBvcyByZXPDrWR1b3MgZGUgdW0gbW9kZWxvIEFSSU1BIGRldmVtIG1vc3RyYXIgdW0gInJ1w61kbyBicmFuY28iLCBvdSBzZWphLCBkZXZlbSBzZXIgbsOjbyBjb3JyZWxhY2lvbmFkb3MgZSBuw6NvIGRldmVtIGFwcmVzZW50YXIgcGFkcsO1ZXMgb3UgdGVuZMOqbmNpYXMuIE8gZ3LDoWZpY28gcGFyZWNlIG1vc3RyYXIgdW1hIGRpc3RyaWJ1acOnw6NvIGFsZWF0w7NyaWEgc2VtIHBhZHLDtWVzIHZpc8OtdmVpcywgbyBxdWUgc3VnZXJlIHF1ZSBvIG1vZGVsbyBjYXB0dXJvdSBiZW0gYXMgcHJpbmNpcGFpcyB0ZW5kw6puY2lhcyBlIHNhem9uYWxpZGFkZXMgZGEgc8OpcmllIHRlbXBvcmFsLg0KDQpFbWJvcmEgYSBtYWlvciBwYXJ0ZSBkb3MgcmVzw61kdW9zIGVzdGVqYSBlbSB0b3JubyBkZSAwLCBow6EgYWxndW5zIHBpY29zIGRlIGRlc3Zpb3MgbWFpb3JlcyAoYWNpbWEgZGUgNCBvdSBhYmFpeG8gZGUgLTYpLCBpbmRpY2FuZG8gcXVlIG8gbW9kZWxvIHRldmUgYWxndW5zIG1vbWVudG9zIG9uZGUgbsOjbyBjb25zZWd1aXUgY2FwdHVyYXIgdG90YWxtZW50ZSBhcyB2YXJpYcOnw7VlcyBkYSBzw6lyaWUgdGVtcG9yYWwsIHBvc3NpdmVsbWVudGUgZGV2aWRvIGEgZXZlbnRvcyBleHRyZW1vcyBvdSBmYXRvcmVzIG7Do28gbW9kZWxhZG9zLg0KDQpQb3IgZmltLCBkZWNpZGl1LXNlIGFwbGljYXIgbyB0ZXN0ZSBkZSBManVuZy1Cb3ggcGFyYSB2ZXJpZmljYXIgYSBoaXDDs3Rlc2UgZGUgcXVlIG9zIHJlc8OtZHVpc28gZGUgZmFjdG8gbsOjbyBzw6NvIGF1dG9jb3JyZWxhY2lvbmFkb3MuIFVtIHAtdmFsdWUgYWx0byAoZ2VyYWxtZW50ZSBzdXBlcmlvciBhIDAuMDUpIGluZGljYSBxdWUgbsOjbyBleGlzdGUgYXV0b2NvcnJlbGHDp8OjbyBzaWduaWZpY2F0aXZhIG5vcyByZXPDrWR1b3MuIENvbW8gcD0wLjY5LCBvIG1lc21vIGNvbXByb3ZhLXNlLg0KDQpgYGB7cn0NCiMgVGVzdGUgZGUgTGp1bmctQm94DQpCb3gudGVzdChyZXNpZHVhbHMsIGxhZyA9IDIwLCB0eXBlID0gJ0xqdW5nLUJveCcpDQpgYGANCg0KDQoNCiMgNi4gQ29uY2x1c8Ojbw0KDQpBIGFuw6FsaXNlIGRhcyB0ZW1wZXJhdHVyYXMgbcOpZGlhcyBkacOhcmlhcyByZWdpc3RhZGFzIGVtIFTDs3F1aW8gZW50cmUgMSBkZSBqYW5laXJvIGRlIDIwMTkgZSAzMSBkZSBtYXLDp28gZGUgMjAyMCBwcm9wb3JjaW9ub3UgdW1hIGNvbXByZWVuc8OjbyBkZXRhbGhhZGEgZGEgZXN0cnV0dXJhIGRhIHPDqXJpZSB0ZW1wb3JhbCwgY3VsbWluYW5kbyBlbSBwcmV2aXPDtWVzIGZ1bmRhbWVudGFkYXMgZSBwb250b3MgcmVsZXZhbnRlcy4gTyBwcm9jZXNzbyBpbmljaW91LXNlIGNvbSB1bWEgYW7DoWxpc2UgZGVzY3JpdGl2YSBkb3MgZGFkb3MsIHF1ZSByZXZlbG91IHBhZHLDtWVzIHNhem9uYWlzIGNsYXJvcyBlIHVtYSB2YXJpYWJpbGlkYWRlIGRpw6FyaWEgbm90w6F2ZWwsIGNhcmFjdGVyw61zdGljYXMgdMOtcGljYXMgZGUgc8OpcmllcyB0ZW1wb3JhaXMgbWV0ZW9yb2zDs2dpY2FzLiBBIGF1c8OqbmNpYSBkZSB2YWxvcmVzIGVtIGZhbHRhIGZhY2lsaXRvdSBhIG1vZGVsYWdlbSBlIGdhcmFudGl1IGEgaW50ZWdyaWRhZGUgZG9zIHJlc3VsdGFkb3MuDQoNCkEgZGVjb21wb3Npw6fDo28gZGEgc8OpcmllIHRlbXBvcmFsLCBhcGVzYXIgZGUgbGltaXRhZGEgZGV2aWRvIGFvIGN1cnRvIHBlcsOtb2RvIGRlIG9ic2VydmHDp8OjbywgZm9pIGNhcGF6IGRlIGlzb2xhciBjb21wb25lbnRlcyBlc3NlbmNpYWlzIGNvbW8gYSB0ZW5kw6puY2lhIGUgYSBzYXpvbmFsaWRhZGUsIHJlZm9yw6dhbmRvIGEgaW1wb3J0w6JuY2lhIGRlIG1vZGVsYXIgY29ycmV0YW1lbnRlIGFzIG9zY2lsYcOnw7VlcyBhbyBsb25nbyBkYXMgZXN0YcOnw7VlcyBkbyBhbm8uIElzc28gaW5kaWNvdSB1bWEgc8OpcmllIHRlbXBvcmFsIHF1ZSBzZWd1ZSB1bSBjaWNsbyBuYXR1cmFsIGRhcyBlc3Rhw6fDtWVzLCBjb20gcGljb3Mgbm8gdmVyw6NvIGUgbcOtbmltYXMgbm8gaW52ZXJuby4NCg0KTyBtb2RlbG8gQVJJTUEsIHNlbGVjaW9uYWRvIGF1dG9tYXRpY2FtZW50ZSBhdHJhdsOpcyBkbyBtw6l0b2RvICcnYXV0by5hcmltYScnLCBtb3N0cm91LXNlIGVmaWNheiBhbyBjYXB0dXJhciBhcyBkaW7Dom1pY2FzIHByaW5jaXBhaXMgZGEgc8OpcmllLCBpbmNsdWluZG8gb3MgcGFkcsO1ZXMgc2F6b25haXMgZSBhIHRlbmTDqm5jaWEgZGUgbG9uZ28gcHJhem8uIENvbSBhIGVzY29saGEgZG8gbW9kZWxvIEFSSU1BKDIsMSwyKSwgYXMgcHJldmlzw7VlcyBwYXJhIG9zIG1lc2VzIHN1YnNlcXVlbnRlcyBleGliaXJhbSB1bWEgdHJhamV0w7NyaWEgY29uc2lzdGVudGUgY29tIG9zIHBhZHLDtWVzIGhpc3TDs3JpY29zIGRlIHRlbXBlcmF0dXJhLCBvIHF1ZSBpbmRpY2EgcXVlIG8gbW9kZWxvIGNvbnNlZ3VpdSBnZW5lcmFsaXphciBiZW0gYXMgZmx1dHVhw6fDtWVzIGRhIHPDqXJpZSB0ZW1wb3JhbC4gTyBlcnJvIHF1YWRyw6F0aWNvIG3DqWRpbyAoTVNFID0gMTUuNjkpIGRlbW9uc3Ryb3UgcXVlIG8gbW9kZWxvIHRlbSB1bWEgcHJlY2lzw6NvIHJhem/DoXZlbCwgZW1ib3JhIGhhamEgZXNwYcOnbyBwYXJhIG1lbGhvcmlhcywgZXNwZWNpYWxtZW50ZSBub3MgbW9tZW50b3MgZW0gcXVlIG9jb3JyZXJhbSBkZXN2aW9zIG1haW9yZXMuDQoNCkEgYW7DoWxpc2UgZG9zIHJlc8OtZHVvcyBkbyBtb2RlbG8gcmV2ZWxvdSByZXN1bHRhZG9zIHBvc2l0aXZvcy4gT3MgcmVzw61kdW9zIGFwcmVzZW50YXJhbS1zZSBjb21vICJydcOtZG8gYnJhbmNvIiwgb3Ugc2VqYSwgbsOjbyBtb3N0cmFyYW0gcGFkcsO1ZXMgb3UgYXV0b2NvcnJlbGHDp8O1ZXMgc2lnbmlmaWNhdGl2YXMsIHN1Z2VyaW5kbyBxdWUgbyBtb2RlbG8gY29uc2VndWl1IGNhcHR1cmFyIGEgbWFpb3IgcGFydGUgZGEgZXN0cnV0dXJhIGRhIHPDqXJpZSB0ZW1wb3JhbC4gUGljb3MgZXNwb3LDoWRpY29zIGRlIGVycm9zLCBubyBlbnRhbnRvLCBpbmRpY2FtIHF1ZSBvIG1vZGVsbyBwb2RlcmlhIHNlciBhcHJpbW9yYWRvIHBhcmEgY2FwdHVyYXIgZXZlbnRvcyBjbGltw6F0aWNvcyBhdMOtcGljb3MuIEEgdmFyacOibmNpYSBjb25zdGFudGUgZG9zIHJlc8OtZHVvcyBhbyBsb25nbyBkbyB0ZW1wbyBlIG8gdGVzdGUgZGUgTGp1bmctQm94LCBjb20gdW0gcC12YWxvciBkZSAwLjY5LCBjb25maXJtYXJhbSBxdWUgbyBtb2RlbG8gYWp1c3RhZG8gbsOjbyBhcHJlc2VudG91IGF1dG9jb3JyZWxhw6fDo28gc2lnbmlmaWNhdGl2YSwgbyBxdWUgdmFsaWRhIGFpbmRhIG1haXMgYSBhZGVxdWHDp8OjbyBkbyBBUklNQSBwYXJhIGVzdGUgY29uanVudG8gZGUgZGFkb3MuDQoNCkVtIHJlc3VtbywgbyBtb2RlbG8gQVJJTUEgc2VsZWNpb25hZG8gZm9pIGVmaWNheiBwYXJhIHByZXZlciBhcyB0ZW1wZXJhdHVyYXMgbcOpZGlhcyBkacOhcmlhcyBlbSBUw7NxdWlvLCBjYXB0dXJhbmRvIGNvbSBwcmVjaXPDo28gb3MgcGFkcsO1ZXMgc2F6b25haXMgZSBhcyB0ZW5kw6puY2lhcy4gQSBhbsOhbGlzZSBkb3MgcmVzw61kdW9zIGUgb3MgdGVzdGVzIGRlIGRpYWduw7NzdGljbyBjb3Jyb2JvcmFyYW0gYSBhZGVxdWHDp8OjbyBkbyBtb2RlbG8sIHRvcm5hbmRvLW8gdW1hIGZlcnJhbWVudGEgY29uZmnDoXZlbCBwYXJhIHByZXZpc8O1ZXMgZnV0dXJhcywgY29tIHVtYSBtYXJnZW0gZGUgZXJybyByZWxhdGl2YW1lbnRlIGJhaXhhLiBFc3RlIHRyYWJhbGhvIGRlbW9uc3RyYSBhIGltcG9ydMOibmNpYSBkZSB1bSBwcm9jZXNzbyByaWdvcm9zbyBkZSBhbsOhbGlzZSBkZSBzw6lyaWVzIHRlbXBvcmFpcyBwYXJhIGVudGVuZGVyIGNvbXBvcnRhbWVudG9zIGNsaW3DoXRpY29zIGUgb2ZlcmVjZSB1bWEgYmFzZSBzw7NsaWRhIHBhcmEgZXN0dWRvcyBtZXRlb3JvbMOzZ2ljb3MgZnV0dXJvcyBvdSBwcmV2aXPDtWVzIGRlIHRlbXBlcmF0dXJhIGVtIG91dHJhcyBjaWRhZGVzIG91IHJlZ2nDtWVzIGNvbSBwYWRyw7VlcyBjbGltw6F0aWNvcyBzZW1lbGhhbnRlcy4NCg0KDQoNCiMgNy4gUmVmZXLDqm5jaWFzDQoNCk1vcmV0dGluLCBQLiBBLiwgJiBUb2xvaSwgQy4gTS4gZGUgQy4gKDIwMjIpLiBBbsOhbGlzZSBkZSBzw6lyaWVzIHRlbXBvcmFpcy4gU8OjbyBQYXVsbzogQmx1Y2hlci4NCg==