Licença

This work is licensed under the Creative Commons Attribution-ShareAlike 4.0 International License. To view a copy of this license, visit http://creativecommons.org/licenses/by-sa/4.0/ or send a letter to Creative Commons, PO Box 1866, Mountain View, CA 94042, USA.

License: CC BY-SA 4.0

License: CC BY-SA 4.0

Citação

Sugestão de citação: FIGUEIREDO, Adriano Marcos Rodrigues. Séries Temporais: suavização exponencial e acurácia. Campo Grande-MS,Brasil: RStudio/Rpubs, 2019. Disponível em http://rpubs.com/amrofi/smoothing_varejoms.

1 Introdução

Neste arquivo utilizo a série do Índice de volume de vendas no varejo Total de Mato Grosso do Sul, série mensal a partir de jan/2000 até jun/2019 obtida com o pacote BETS e importada do Banco Central do Brasil. Portanto, são 234 observações mensais.
É um exercício rápido de suavização exponencial e acurácia, similar ao realizado para decomposição clássica e x11 (em http://rpubs.com/amrofi/decompose_x11_varejoms).

2 Dados

O leitor pode carregar direto do site do Banco Central do Brasil com o pacote BETS (FERREIRA, SPERANZA e COSTA, 2018) como abixo ou usar a saída do dput(varejoms) conforme colocado abaixo.

library(BETS)
# Pegando as séries a partir do site do Banco Central do Brasil
# Índice de volume de vendas no varejo Total de Mato Grosso do Sul
# mensal a partir de jan/2000 até jun/2019 
# 234 observações mensais
varejoms <- BETSget(1479) 
print(varejoms)
class(varejoms)
dput(varejoms)  # opção para ter os dados como na structure abaixo
# uso a opção abaixo para quando a internet por algum motivo falha
varejoms <- structure(c(35.2, 35.6, 39.2, 40.5, 41.6, 40.4, 40.8, 38.7, 37.3, 
    37.6, 35.6, 47.4, 34.2, 32.2, 38, 37.5, 38.8, 35, 38.4, 40.2, 38.2, 39.3, 
    36, 46.3, 36.4, 34, 39, 37.8, 38.9, 35.3, 37.2, 38.1, 35.6, 38.3, 35.6, 
    45.7, 32.2, 31.6, 35.2, 36.8, 37.5, 34.8, 38.4, 38.1, 37, 39, 37.3, 49, 
    35.8, 35.3, 40.2, 41.3, 43.9, 41.6, 45.9, 42.3, 42.2, 44, 41.3, 56.9, 38.5, 
    38.5, 45.3, 43.6, 46.2, 44.3, 47.5, 46.5, 46.4, 46, 44.1, 61, 42, 40.2, 
    44.6, 44.5, 47.8, 45.3, 46.5, 48.5, 47.7, 50.2, 49.3, 64.5, 47, 46.8, 51, 
    50.5, 55, 51.3, 52.8, 55.3, 54.8, 55.6, 55.3, 72.2, 54.5, 52.1, 56.2, 57.2, 
    60.8, 56.1, 61.8, 61.6, 59.8, 63.3, 57.7, 77.4, 61.4, 51.9, 57.3, 57.9, 
    61.9, 57.3, 61.1, 61.1, 60.6, 65.6, 63.5, 83.1, 64.1, 60.2, 67.8, 67.1, 
    72.8, 68.5, 71.1, 69.3, 69.9, 71.1, 67.9, 92.7, 67.5, 64.8, 69.1, 69.4, 
    79.6, 70.2, 73.8, 72.5, 71.3, 75.6, 74.7, 100.8, 79.5, 75.7, 82.4, 78, 84.8, 
    83.2, 84.8, 88.5, 86.3, 91.7, 92.8, 111.4, 92.8, 83.7, 92.5, 88.3, 93.9, 
    88.8, 96, 95.9, 93.2, 98.3, 100.5, 128.8, 97.2, 90.2, 94.3, 94.4, 101.1, 
    92, 96.4, 98.2, 97.6, 105.8, 103.1, 129.6, 99.6, 87.8, 97, 94.8, 98.6, 93.4, 
    98.4, 96.4, 92.5, 100.6, 97.2, 124.5, 91.5, 85.1, 91.6, 88.5, 92.2, 87.4, 
    90.5, 88.1, 85.2, 89.4, 93.4, 116.9, 90.8, 84, 89.7, 86.3, 90, 87.3, 90.8, 
    93.5, 93.7, 91.4, 93.5, 114.1, 87.8, 81.1, 94.5, 83.2, 89.9, 88.8, 89.3, 
    93.7, 93.5, 96.3, 101.3, 118.3, 93.8, 85.2, 90, 86.6, 90, 84.5), .Tsp = c(2000, 
    2019.41666666667, 12), class = "ts")
class(varejoms)
[1] "ts"

3 Primeiras análises

Inicialmente olharei as estatísticas descritivas da série. Em seguida farei um plot básico da série e o plot pelo pacote dygraphs, útil para ver os pontos de picos e momentos específicos.

# estatisticas basicas
summary(varejoms)
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
  31.60   44.02   64.30   67.17   90.00  129.60 
# Min. 1st Qu.  Median Mean 3rd Qu.  Max.  31.60 44.02 64.30 67.17 90.00
# 129.60

# pelo pacote dygraph dá mais opções
library(dygraphs)
dygraph(varejoms)

É possível visualizar nos plots acima: sazonalidade (por exemplo, picos em dezembro de cada ano); a tendência aparentemente crescente até 2014 e decresce com a “crise” brasileira; e uma aparente não-estacionariedade (média e variância mudam no tempo). Em outra postagem aplicarei o teste de raiz unitária na série para avaliar a estacionariedade de modo mais explícito.

4 Suavização (ou alisamento) Exponencial Simples (SES) ou ainda, ‘Holt 1 parâmetro’

Este método é apropriado para séries que se movem aleatoriamente em torno de uma média ou nível constante, sem tendência e sem sazonalidade: \(Z_t=μ_t+a_t\) em que \(a_t\) é um ruído branco de média zero e variância constante e \(μ_t\) é um parâmetro localmente constante (nível); \(Z_t\) é a série em análise.

\[ {\bar Z_t} = \alpha {Z_t} + \left( {1 - \alpha } \right){\bar Z_{t - 1}} \]

Em que α é a constante de suavização, 0<α<1. Portanto, similarmente,

\[ {\bar Z_{t - 1}} = \alpha {Z_{t - 1}} + \left( {1 - \alpha } \right){\bar Z_{t - 2}} \]

O que substituindo (2) em (1) e desenvolvendo os termos tem-se:

\[ {\bar Z_t} = \alpha {Z_t} + \alpha \left( {1 - \alpha } \right){Z_{t - 1}} + \alpha {\left( {1 - \alpha } \right)^2}{Z_{t - 2}} + \ldots \]

Ou seja, a SES faz uma previsão que é a média ponderada por \(α(1-α)^k\) que, quanto mais recente, maior é o peso.

Se \(0<α<1\), então \(α>α(1-α)>α(1-α)^2>\ldots>α(1-α)^k\)

Na MMS tem-se o mesmo peso entre observações recentes e antigas. Na SES, a vantagem sobre MMS é que aplica pesos maiores às observações recentes. A questão será achar α que minimiza a soma de quadrados de ajustamento:

\[ S = \mathop \sum \limits_{t = l + 1}^N {\left( {{Z_t} - {{\hat Z}_{t - 1}}} \right)^2} \]

O forecast será constante para todas as observações futuras!!!

x <- varejoms
# simple exponential smoothing (SES)

x.ses <- ses(x, h = 12, level = c(95))
x.ses  # exibe o forecast por holt 1 parametro
         Point Forecast    Lo 95    Hi 95
Jul 2019        90.3704 75.71475 105.0260
Aug 2019        90.3704 75.36817 105.3726
Sep 2019        90.3704 75.02941 105.7114
Oct 2019        90.3704 74.69797 106.0428
Nov 2019        90.3704 74.37340 106.3674
Dec 2019        90.3704 74.05528 106.6855
Jan 2020        90.3704 73.74325 106.9975
Feb 2020        90.3704 73.43696 107.3038
Mar 2020        90.3704 73.13612 107.6047
Apr 2020        90.3704 72.84045 107.9004
May 2020        90.3704 72.54967 108.1911
Jun 2020        90.3704 72.26357 108.4772
summary(x.ses)  # fornece o relatorio da estimacao

Forecast method: Simple exponential smoothing

Model Information:
Simple exponential smoothing 

Call:
 ses(y = x, h = 12, level = c(95)) 

  Smoothing parameters:
    alpha = 0.2188 

  Initial states:
    l = 37.9823 

  sigma:  7.4775

     AIC     AICc      BIC 
2222.106 2222.210 2232.471 

Error measures:
                 ME     RMSE      MAE       MPE     MAPE     MASE
Training set 1.0234 7.445484 4.746198 0.8232233 6.805751 1.031984
                   ACF1
Training set 0.03393904

Forecasts:
         Point Forecast    Lo 95    Hi 95
Jul 2019        90.3704 75.71475 105.0260
Aug 2019        90.3704 75.36817 105.3726
Sep 2019        90.3704 75.02941 105.7114
Oct 2019        90.3704 74.69797 106.0428
Nov 2019        90.3704 74.37340 106.3674
Dec 2019        90.3704 74.05528 106.6855
Jan 2020        90.3704 73.74325 106.9975
Feb 2020        90.3704 73.43696 107.3038
Mar 2020        90.3704 73.13612 107.6047
Apr 2020        90.3704 72.84045 107.9004
May 2020        90.3704 72.54967 108.1911
Jun 2020        90.3704 72.26357 108.4772
plot(x.ses, col = 1, main = "Índice de volume de vendas no varejo Total 
     de Mato Grosso do Sul", 
    sub = "modelo SES")

5 Suavização Holt-Winters - 3 parâmetros

# Holt-Winters
x.hwm <- hw(x, seasonal = "multiplicative")  # multiplicativo
plot(x, ylab = "Indice 2011=100", main = "Índice de volume de vendas no varejo Total de Mato Grosso do Sul", 
    type = "o", xlab = "Mês/Ano")
lines(fitted(x.ses), col = "red", lty = 2)
lines(x.ses$mean, type = "o", col = "red")
lines(x.hwm$mean, type = "o", col = "green")
legend("topleft", lty = 1, pch = 1, col = 1:3, c("original", "Holt Simples", 
    "Holt Winters' Multiplicativo"))

summary(x.hwm)

Forecast method: Holt-Winters' multiplicative method

Model Information:
Holt-Winters' multiplicative method 

Call:
 hw(y = x, seasonal = "multiplicative") 

  Smoothing parameters:
    alpha = 0.4597 
    beta  = 0.0192 
    gamma = 0.2855 

  Initial states:
    l = 41.5931 
    b = -4e-04 
    s = 1.2461 0.9587 1.0374 1.0132 1.0348 1.0325
           0.9809 1.0255 0.9906 0.968 0.8487 0.8637

  sigma:  0.0348

     AIC     AICc      BIC 
1658.395 1661.228 1717.135 

Error measures:
                      ME    RMSE     MAE       MPE     MAPE     MASE
Training set -0.04501476 2.32154 1.76375 0.0133938 2.665347 0.383499
                   ACF1
Training set 0.03646486

Forecasts:
         Point Forecast     Lo 80     Hi 80     Lo 95     Hi 95
Jul 2019       88.88771  84.92468  92.85075  82.82678  94.94865
Aug 2019       90.62694  86.14540  95.10848  83.77302  97.48086
Sep 2019       88.92541  84.10245  93.74837  81.54933  96.30149
Oct 2019       91.47520  86.08043  96.86997  83.22461  99.72579
Nov 2019       93.50672  87.55113  99.46230  84.39844 102.61500
Dec 2019      113.71305 105.93485 121.49125 101.81732 125.60878
Jan 2020       88.48556  82.01555  94.95558  78.59053  98.38060
Feb 2020       80.83252  74.53942  87.12562  71.20805  90.45698
Mar 2020       87.79739  80.54427  95.05050  76.70471  98.89006
Apr 2020       82.93359  75.68515  90.18204  71.84805  94.01913
May 2020       87.87547  79.77122  95.97972  75.48108 100.26985
Jun 2020       84.38425  76.19165  92.57686  71.85475  96.91376
Jul 2020       87.80739  78.44802  97.16675  73.49348 102.12130
Aug 2020       89.52432  79.55703  99.49161  74.28067 104.76797
Sep 2020       87.84235  77.63994  98.04476  72.23911 103.44559
Oct 2020       90.35991  79.42497 101.29484  73.63637 107.08345
Nov 2020       92.36545  80.73216 103.99874  74.57387 110.15703
Dec 2020      112.32369  97.61559 127.03180  89.82959 134.81780
Jan 2021       87.40329  75.51629  99.29029  69.22370 105.58288
Feb 2021       79.84280  68.57524  91.11036  62.61056  97.07504
 [ reached 'max' / getOption("max.print") -- omitted 4 rows ]

6 Avaliação da simulação

Para uma só equação, podem-se olhar os indicadores tradicionais como o R², estatísticas F e t, critérios de informação de Akaike, Schwarz entre outros. Para modelos de previsão, devo ter um erro de previsão mínimo, definido pelo pesquisador de modo a julgá-lo adequado.

As vezes pode-se ter equações bem estimadas junto de outras com poucos parâmetros significativos, num mesmo sistema. Dependendo do objetivo a ser alcançado, se simular ou explicar, busca-se ajustamento com alta significância (para explicar) ou busca-se melhor poder de explicação. Por melhor poder de explicação entende-se: valores previstos mais próximos dos observados.

Alguns critérios para avaliação da previsão podem ser citados: Raiz do Erro de Simulação Quadrático Médio; Raiz do Erro Quadrático Médio Percentual; Erro de Simulação Médio; Erro Percentual Médio; Erro Absoluto Médio; Erro Absoluto Percentual Médio; Raiz do Erro de Simulação Ex-post Quadrático Médio; Coeficiente de desigualdade de Theil (U).

6.1 Raiz do Erro de Simulação Quadrático Médio (RMSE)

Este critério é dado pela expressão: \[ RMSE = \;\sqrt {\frac{1}{T}\mathop \sum \limits_{t = 1}^T {{\left( {Y_t^s - Y_t^a} \right)}^2}} \]

Em que: \(Y_t^s\) é o valor simulado (previsto) de \(Y_t\); \(Y_t^a\) é o valor efetivo (observado); e T é o número de períodos na simulação.

O resultado é um escalar com o valor da raiz quadrada da média da diferença quadrática entre x e y, ou seja, a raiz do erro quadrático médio. Normalmente deve ser calculado pela fórmula, mas é reportado pelo programa quando se faz um “forecast”.

Para o cálculo da Raiz do Erro de Simulação Ex-post Quadrático Médio, utilizam-se os resultados do modelo de previsão aplicado a um conjunto restrito (histórico) para checar os erros no período de simulação. Exemplo: usando os dados de 1950:01 a 1985:04, históricos, simulam-se os resultados para 1986:01 a 1988:01 e calcula-se o erro ex-post.

6.2 Raiz do Erro Quadrático Médio Percentual (PRMSE)

\[ PRMSE = \;\sqrt {\frac{1}{T}\mathop \sum \limits_{t = 1}^T {{\left( {\frac{{Y_t^s - Y_t^a}}{{Y_t^a}}} \right)}^2}} \]

Em que: \(Y_t^s\) é o valor simulado (previsto) de \(Y_t\); \(Y_t^a\) é o valor efetivo (observado); e T é o número de períodos na simulação. Neste caso, a diferença entre o previsto e o observado (o erro) é dividida pelo valor observado, obtendo-se assim em base percentual relativo ao valor observado.

6.3 Erro de Simulação Médio (ME) e o Erro Percentual Médio (MPE)

O erro de simulação é basicamente o termo \((Y_t^s - Y_t^a)\), como definido anteriormente. O erro médio (ME) é, portanto, a média dos erros para T observações, enquanto o erro percentual médio (MPE) é obtido relativizando-se pelos valores observados, como nas expressões a seguir:

\[ ME= \frac{1}{T}\sum\limits_{t = 1}^T {\left( {Y_t^s - Y_t^a} \right)} \]

\[ MPE = 100.\frac{1}{T}\sum\limits_{t = 1}^T {\frac{{\left( {Y_t^s - Y_t^a} \right)}}{{Y_t^a}}} \]

Uma ressalva necessária é que: “[…] O problema com os erros médios é que eles podem ser quase zero, quando elevados erros positivos cancelam elevados erros negativos” (PINDYCK e RUBINFELD, 2004, p.447).

Alguns autores utilizam estas duas últimas medidas com o termo entre parênteses $ {( {Y_t^s - Y_t^a} )} $ na forma de ‘valor absoluto’ \(\left| {\left( {Y_t^s - Y_t^a} \right)} \right|\) . Tal procedimento auxilia a investigar o erro de previsão do modelo evitando os problemas de ‘erros positivos’ cancelarem ‘erros negativos’. Desta forma, surgem as outras duas opções: MAE e MAPE.

6.4 Erro Absoluto Médio (MAE) e Erro Absoluto Percentual Médio (MAPE)

O erro absoluto médio (MAE) considera a expressão análoga do erro de simulação médio com os valores absolutos como na expressão:

\[ MAE = \frac{1}{T}\sum\limits_{t = 1}^T {\left| {Y_t^s - Y_t^a} \right|} \]

Similarmente ao erro percentual médio, o erro absoluto percentual médio (MAPE) será:

\[ MAPE = 100.\frac{1}{T}\sum\limits_{t = 1}^T {\left| {\frac{{\left( {Y_t^s - Y_t^a} \right)}}{{Y_t^a}}} \right|} \]

Desejam-se valores baixos das medidas. Entretanto, é importante observar se o modelo está bem ajustado para os ‘pontos de inflexão’ nos dados (oscilações, vales e picos que se observam nos gráficos previstos e realizados).

6.5 Erro Absoluto Percentual Médio Simétrico (sMAPE)

As medidas de acurácia tipo MAPE têm a desvantagem de penalizar mais os erros negativos que os positivos. Assim, surge a medida sMAPE ou MAPE “simétrico” proposto por Armstrong (1978 , p. 348), citado por Hyndman e Athanasopoulos (2018). Esta medida foi utilizada para escolha do melhor modelo na competição de previsão do M3 de Makridakis (\(M^3\) competition). A expressão para cálculo é do tipo:

\[ \text{sMAPE} = \text{mean}\left(200|{Y_t^s - Y_t^a}|/(Y_t^s+Y_t^a)\right) \]

Esta medida não está disponibilizada diretamente nas saídas do pacote forecast nem no fpp2, em virtude da crítica de Hyndman e Athanasopoulos (2018) em que citam Hyndman e Koehler (2006). A medida sMAPE pode ser obtida pelos pacotes Metrics ou TSPred.

6.6 critérios de informação, Akaike (AIC), Schwarz (SIC ou BIC) e Hannan-Quin (HQ)

A ideia é que nos critérios de informação, acrescentando lags se reduz a soma dos resíduos (pois mais variação é explicada no modelo), ou seja, foi acrescentada mais informação. Mas ainda deve-se penalizar a adição do regressor, uma ideia de redução dos graus de liberdade do modelo.

Em geral, os critérios têm a seguinte expressão: \(C=lnσ ̂^2 (T)+c_T φ(T)\).

O primeiro termo associa a variância, e seu valor deve reduzir com o aumento de variáveis. No segundo termo tem-se: \(c_T\) é o número de parâmetros estimados; e \(φ(T)\) é a ordem do processo que penaliza o acréscimo de variáveis. Assim, quanto menor C melhor é o modelo, ou seja, tem menos resíduos, menos parte não explicada. O Critério de Informação de Akaike (ou AIC de Akaike’s Information Criterion) ou o Critério de Informação de Schwarz ou Bayesiano (ou SIC de Schwarz’s Information Criterion ou em alguns livros BIC de Bayesian Information Criterion) são expressos no Eviews da forma já logaritmizada como:

\[AIC = - \frac{{2l}}{n} + \frac{{2k}}{n}\]

\[SIC = - \frac{{2l}}{n} + \frac{{k.\log n}}{n}\]

\[ l = - {\frac{n}{2}} {\left( {1 + \log(2\pi)+\log \left( {\frac{{\hat \varepsilon ^\prime \hat \varepsilon }}{n}} \right)} \right)} \]

Em que: k é o número de regressores incluindo-se o intercepto; n é o número de observações; l é o log Verossimilhança da regressão; e \(\hat \varepsilon\) são os resíduos estimados do modelo. No formato mais simplificado exposto por Greene (2002), tem-se igual ao de Bueno (2008, p.47):

\[ \begin{array}{l} SIC = BIC\left( {p,q} \right) = \ln {{\hat \sigma }^2} + k\frac{{\ln T}}{T}\\ {{\hat \sigma }^2} = \frac{{\sum\nolimits_{t = 1}^T {\hat \varepsilon _t^2} }}{T} \end{array} \]

Em que k=p+q+1 se houver intercepto.

\[ AIC\left( {p,q} \right) = \ln {{\hat \sigma }^2} + k\frac{{2}}{T} \]

\[ HQ\left( {p,q} \right) = \ln {{\hat \sigma }^2} + k\frac{2}{T} \ln T \]

Quanto mais parâmetros são estimados, menor será o erro estimado, mas isto é penalizado no segundo termo dos critérios. Desejo menores valores dos critérios. O BIC é consistente assintoticamente, e o AIC funciona melhor em pequenas amostras, mas é pior com mais parâmetros. Já o HQ é menos forte que o BIC, ou seja, o preferido é o BIC.

A função window auxiliará na extração de uma parte de uma série temporal, e criação dos subsets de treino e teste no forecast. Na função window especificamos o início (start) (e/ou fim: end) de modo a definir o subset. O treino é onde será obtido o modelo estimado e o teste é onde verificaremos o acerto, ou acurácia, do modelo. Identificado o melhor modelo, faz-se então o forecast fora da amostra. A amostra de teste é em geral 20% da amostra existente.

library(fpp2)
# farei as janelas de teste e treino, estimarei os modelos para a amostra
# treino modelo 1: cons.ses modelo 2: cons.holttrend.EXP modelo 3:
# cons.holttrend.DAMPm modelo 4: conshw2

# amostra treino até julho 2015 (187 meses)
cons <- window(varejoms, start = c(2000, 1), end = c(2015, 7))
# amostra teste (47 meses até junho 2019)
teste <- window(varejoms, start = c(2015, 8))

Vamos checar se separamos corretamente:

autoplot(varejoms) + autolayer(cons, series = "Training") + autolayer(teste, 
    series = "Test")

# estimar modelos
cons.ses <- ses(cons, h = 60, level = c(95))  # forecast até jul/2020
cons.holttrend.EXP <- holt(cons, h = 60, level = c(95), exponential = TRUE)
cons.holttrend.DAMPm <- holt(cons, h = 60, level = c(95), exponential = TRUE, 
    damped = TRUE)
conshw2 <- hw(cons, h = 60, seasonal = "multiplicative")  # multiplicativo

autoplot(varejoms) + forecast::autolayer(cons.ses, series = "SES", PI = FALSE) + 
    forecast::autolayer(cons.holttrend.EXP, series = "Holt Expon. Trend", PI = FALSE) + 
    forecast::autolayer(cons.holttrend.DAMPm, series = "Holt Trend Damped mult", 
        PI = FALSE) + forecast::autolayer(conshw2, series = "Holt-Winters mult", 
    PI = FALSE) + xlab("Ano") + ylab("Consumo") + ggtitle("Forecasts para consumo do varejo MS") + 
    guides(colour = guide_legend(title = "Forecast"))

summary(cons.ses)

Forecast method: Simple exponential smoothing

Model Information:
Simple exponential smoothing 

Call:
 ses(y = cons, h = 60, level = c(95)) 

  Smoothing parameters:
    alpha = 0.239 

  Initial states:
    l = 37.8842 

  sigma:  6.8763

     AIC     AICc      BIC 
1703.310 1703.441 1713.003 

Error measures:
                   ME     RMSE      MAE      MPE     MAPE     MASE
Training set 1.339005 6.839444 4.260657 1.242669 6.788559 0.895096
                    ACF1
Training set -0.02999918

Forecasts:
         Point Forecast    Lo 95    Hi 95
Aug 2015       97.73313 84.25580 111.2105
Sep 2015       97.73313 83.87616 111.5901
Oct 2015       97.73313 83.50666 111.9596
Nov 2015       97.73313 83.14651 112.3197
Dec 2015       97.73313 82.79504 112.6712
Jan 2016       97.73313 82.45165 113.0146
Feb 2016       97.73313 82.11581 113.3504
Mar 2016       97.73313 81.78705 113.6792
Apr 2016       97.73313 81.46492 114.0013
May 2016       97.73313 81.14905 114.3172
Jun 2016       97.73313 80.83909 114.6272
Jul 2016       97.73313 80.53471 114.9315
Aug 2016       97.73313 80.23563 115.2306
Sep 2016       97.73313 79.94157 115.5247
Oct 2016       97.73313 79.65229 115.8140
Nov 2016       97.73313 79.36757 116.0987
Dec 2016       97.73313 79.08720 116.3791
Jan 2017       97.73313 78.81098 116.6553
Feb 2017       97.73313 78.53874 116.9275
Mar 2017       97.73313 78.27030 117.1960
Apr 2017       97.73313 78.00552 117.4607
May 2017       97.73313 77.74424 117.7220
Jun 2017       97.73313 77.48633 117.9799
Jul 2017       97.73313 77.23167 118.2346
Aug 2017       97.73313 76.98013 118.4861
Sep 2017       97.73313 76.73161 118.7346
Oct 2017       97.73313 76.48599 118.9803
Nov 2017       97.73313 76.24318 119.2231
Dec 2017       97.73313 76.00308 119.4632
Jan 2018       97.73313 75.76561 119.7006
Feb 2018       97.73313 75.53068 119.9356
Mar 2018       97.73313 75.29820 120.1680
Apr 2018       97.73313 75.06811 120.3981
 [ reached 'max' / getOption("max.print") -- omitted 27 rows ]
summary(cons.holttrend.EXP)

Forecast method: Holt's method with exponential trend

Model Information:
Holt's method with exponential trend 

Call:
 holt(y = cons, h = 60, level = c(95), exponential = TRUE) 

  Smoothing parameters:
    alpha = 0.139 
    beta  = 1e-04 

  Initial states:
    l = 38.4459 
    b = 1.0059 

  sigma:  0.1038

     AIC     AICc      BIC 
1650.810 1651.141 1666.965 

Error measures:
                      ME     RMSE      MAE       MPE     MAPE     MASE
Training set -0.06616242 6.613945 4.188691 -1.273058 6.816974 0.879977
                   ACF1
Training set 0.03938391

Forecasts:
         Point Forecast    Lo 95    Hi 95
Aug 2015       102.6680 82.21325 123.6675
Sep 2015       103.2643 82.12224 125.3514
Oct 2015       103.8640 83.62881 125.2875
Nov 2015       104.4671 83.27280 126.5133
Dec 2015       105.0738 83.27614 127.6882
Jan 2016       105.6840 84.00109 128.7852
Feb 2016       106.2978 84.62298 130.1737
Mar 2016       106.9151 83.86320 131.0781
Apr 2016       107.5360 84.29447 131.9080
May 2016       108.1605 85.15207 132.6212
Jun 2016       108.7886 85.37154 133.6896
Jul 2016       109.4204 85.84993 136.1859
Aug 2016       110.0558 85.83369 135.9517
Sep 2016       110.6950 86.05295 135.8222
Oct 2016       111.3378 85.86740 138.2137
Nov 2016       111.9844 87.25056 139.5991
Dec 2016       112.6347 87.23104 140.2454
Jan 2017       113.2888 87.74143 140.6656
Feb 2017       113.9467 87.84125 143.3614
Mar 2017       114.6085 88.14357 144.0116
Apr 2017       115.2740 89.17252 143.4174
May 2017       115.9435 89.18443 146.0490
Jun 2017       116.6168 89.56823 145.7710
Jul 2017       117.2940 90.09394 147.9986
Aug 2017       117.9752 90.15779 148.5323
Sep 2017       118.6603 91.26682 150.9042
Oct 2017       119.3494 90.97347 150.8392
Nov 2017       120.0426 91.37486 152.2017
Dec 2017       120.7397 93.07605 153.2288
Jan 2018       121.4409 92.49209 153.3283
Feb 2018       122.1461 93.33783 155.9765
Mar 2018       122.8555 93.22401 157.5944
Apr 2018       123.5689 94.07154 158.8590
 [ reached 'max' / getOption("max.print") -- omitted 27 rows ]
summary(cons.holttrend.DAMPm)

Forecast method: Damped Holt's method with exponential trend

Model Information:
Damped Holt's method with exponential trend 

Call:
 holt(y = cons, h = 60, damped = TRUE, level = c(95), exponential = TRUE) 

  Smoothing parameters:
    alpha = 0.0835 
    beta  = 0.0169 
    phi   = 0.9572 

  Initial states:
    l = 38.9916 
    b = 1.0001 

  sigma:  0.1054

     AIC     AICc      BIC 
1652.699 1653.165 1672.085 

Error measures:
                    ME     RMSE      MAE        MPE     MAPE     MASE
Training set 0.4716645 6.607187 4.182636 0.09037218 6.669775 0.878705
                   ACF1
Training set 0.06912782

Forecasts:
         Point Forecast    Lo 95    Hi 95
Aug 2015      100.23830 79.59387 120.7889
Sep 2015       99.95370 79.00841 119.8228
Oct 2015       99.68205 79.08449 120.2223
Nov 2015       99.42273 79.01535 120.4963
Dec 2015       99.17515 78.39902 120.4894
Jan 2016       98.93875 78.12389 120.1448
Feb 2016       98.71300 77.72787 119.5006
Mar 2016       98.49740 77.60502 120.8873
Apr 2016       98.29148 76.60354 121.9379
May 2016       98.09479 76.75972 121.9921
Jun 2016       97.90688 75.93438 121.6110
Jul 2016       97.72737 75.41087 123.2243
Aug 2016       97.55585 74.90334 122.3694
Sep 2016       97.39196 74.49509 123.3998
Oct 2016       97.23534 74.80426 123.2504
Nov 2016       97.08567 73.43970 124.3794
Dec 2016       96.94263 73.25322 124.7477
Jan 2017       96.80591 72.13365 126.3009
Feb 2017       96.67523 72.26753 125.9150
Mar 2017       96.55031 70.99320 126.0826
Apr 2017       96.43090 70.63147 127.9588
May 2017       96.31673 70.12923 127.9068
Jun 2017       96.20758 69.92206 129.8022
Jul 2017       96.10323 69.31071 129.5336
Aug 2017       96.00345 69.44874 130.7782
Sep 2017       95.90804 67.73914 131.9182
Oct 2017       95.81680 67.82567 134.2973
Nov 2017       95.72956 67.24986 134.0381
Dec 2017       95.64613 66.54705 134.8991
Jan 2018       95.56633 65.73807 134.8337
Feb 2018       95.49002 65.50880 136.6154
Mar 2018       95.41704 65.25910 137.3355
Apr 2018       95.34723 64.50632 138.0112
 [ reached 'max' / getOption("max.print") -- omitted 27 rows ]
summary(conshw2)

Forecast method: Holt-Winters' multiplicative method

Model Information:
Holt-Winters' multiplicative method 

Call:
 hw(y = cons, h = 60, seasonal = "multiplicative") 

  Smoothing parameters:
    alpha = 0.3785 
    beta  = 0.02 
    gamma = 0.298 

  Initial states:
    l = 39.9041 
    b = -0.0938 
    s = 1.2461 0.9641 1.0256 1.0036 1.0186 1.0309
           0.9832 1.0446 0.9987 0.9644 0.8469 0.8733

  sigma:  0.0356

     AIC     AICc      BIC 
1258.334 1261.956 1313.263 

Error measures:
                     ME     RMSE      MAE       MPE     MAPE      MASE
Training set 0.07561897 2.121197 1.632621 0.2012019 2.748482 0.3429876
                  ACF1
Training set 0.1300521

Forecasts:
         Point Forecast     Lo 80     Hi 80     Lo 95     Hi 95
Aug 2015       99.83153  95.27346 104.38959  92.86056 106.80249
Sep 2015       98.12611  93.30452 102.94769  90.75213 105.50009
Oct 2015      104.02632  98.54510 109.50754  95.64352 112.40912
Nov 2015      101.94575  96.20443 107.68707  93.16516 110.72634
Dec 2015      129.15806 121.40670 136.90942 117.30337 141.01274
Jan 2016       99.39022  93.05112 105.72932  89.69540 109.08504
Feb 2016       90.18348  84.08603  96.28093  80.85824  99.50873
Mar 2016       97.95304  90.94864 104.95743  87.24074 108.66534
Apr 2016       95.91397  88.67569 103.15226  84.84397 106.98397
May 2016      102.45680  94.31291 110.60069  90.00180 114.91180
Jun 2016       96.33800  88.28751 104.38849  84.02583 108.65016
Jul 2016      101.66983  92.75319 110.58647  88.03301 115.30666
Aug 2016      102.91979  92.95323 112.88636  87.67725 118.16234
Sep 2016      101.15393  90.94955 111.35831  85.54768 116.76019
Oct 2016      107.22809  95.97031 118.48588  90.01080 124.44539
Nov 2016      105.07558  93.60513 116.54603  87.53303 122.61813
Dec 2016      133.11337 118.01810 148.20863 110.02715 156.19958
Jan 2017      102.42630  90.37071 114.48189  83.98887 120.86373
Feb 2017       92.93143  81.58845 104.27442  75.58383 110.27903
Mar 2017      100.93028  88.16543 113.69514  81.40812 120.45245
 [ reached 'max' / getOption("max.print") -- omitted 40 rows ]

Acurácia

As previsões acima foram feitas com a amostra treino até julho/2015, mas temos dados até julho/2019. Faremos a acurácia para este período. A função accuracy nos fornece várias medidas de acurácia, e para a sMAPE precisaremos do pacote Metrics e a função smape.

teste <- window(varejoms, start = c(2015, 8))
kable(forecast::accuracy(cons.ses, teste), caption = "SES")
SES
ME RMSE MAE MPE MAPE MASE ACF1 Theil’s U
Training set 1.339006 6.839444 4.260657 1.242669 6.788559 0.895096 -0.0299992 NA
Test set -4.884189 10.160182 8.684242 -6.091654 9.325527 1.824421 0.1721972 0.9967548
kable(forecast::accuracy(cons.holttrend.EXP, teste), caption = "Holt-Trend Exponencial")
Holt-Trend Exponencial
ME RMSE MAE MPE MAPE MASE ACF1 Theil’s U
Training set -0.0661624 6.613945 4.188691 -1.273058 6.816974 0.879977 0.0393839 NA
Test set -24.8072759 28.235483 25.815423 -27.810865 28.630100 5.423408 0.5854286 2.821569
kable(forecast::accuracy(cons.holttrend.DAMPm, teste), caption = "Holt-Trend Amortecida Multiplicativo")
Holt-Trend Amortecida Multiplicativo
ME RMSE MAE MPE MAPE MASE ACF1 Theil’s U
Training set 0.4716645 6.607187 4.182636 0.0903722 6.669775 0.878705 0.0691278 NA
Test set -3.7017105 9.566188 7.775848 -4.7858372 8.272414 1.633582 0.1613323 0.9301276
kable(forecast::accuracy(conshw2, teste), caption = "Holt-Winters Multiplicativo")
Holt-Winters Multiplicativo
ME RMSE MAE MPE MAPE MASE ACF1 Theil’s U
Training set 0.075619 2.121197 1.632621 0.2012019 2.748482 0.3429876 0.1300521 NA
Test set -13.116922 14.078510 13.116922 -14.2562156 14.256216 2.7556560 0.5765315 1.399466

Para o pacote Metrics, observar que ele tem funções de mesmo nome que o pacote forecast, e portanto, deves especificar exatamente qual o pacote e cuidar para alterar a ordem das séries (actual x predicted). No pacote Metrics existe uma diferença da ordem de \(10^2\) comparando com os resultados do pacote forecast!

library(Metrics)
teste <- window(varejoms, start = c(2015, 8))
smape(teste, cons.ses$mean)
[1] 0.09066301
smape(teste, cons.holttrend.EXP$mean)
[1] 0.2447362
smape(teste, cons.holttrend.DAMPm$mean)
[1] 0.08124576
smape(teste, conshw2$mean)
[1] 0.1318151
Metrics::mape(teste, cons.ses$mean)
[1] 0.09325527
Metrics::mape(teste, cons.holttrend.EXP$mean)
[1] 0.286301
Metrics::mape(teste, cons.holttrend.DAMPm$mean)
[1] 0.08272414
Metrics::mape(teste, conshw2$mean)
[1] 0.1425622

Comentário O modelo estimado utilizando a amostra de treino perde qualidade em virtude da forte queda após 2015, que a amostra não consegue perceber. Isso é ocasionado em quebras na série, de modo que o forecast ficou prejudicado pela escolha da amostra treino. Observa-se isso no item 5, quando o forecast foi realizado sem delimitar a amostra, realizando a previsão com todo o conjunto de informações.

autoplot(varejoms) + forecast::autolayer(x.hwm, series = "Holt-Winters mult", 
    PI = FALSE) + xlab("Ano") + ylab("Consumo - Indice 2011=100") + ggtitle("Forecasts para Índice de volume de vendas no varejo Total 
          de Mato Grosso do Sul") + 
    guides(colour = guide_legend(title = "Forecast"))

Outra opção pelo pacote stats e função HoltWinters:

hw <- stats::HoltWinters(varejoms)
predicted <- predict(hw, n.ahead = 24, prediction.interval = TRUE)

dygraph(predicted, main = "Previsão do Varejo de MS") %>% dyAxis("x", drawGrid = TRUE) %>% 
    dySeries(c("lwr", "fit", "upr"), label = "Varejo") %>% dyOptions(colors = RColorBrewer::brewer.pal(3, 
    "Set1"))
# combine the time series actual and forcasted values
combined <- cbind(predicted, actual = varejoms)

# plot the different values as different series
dygraph(combined, main = "Previsão do Varejo de MS - 24 meses") %>% dyAxis("x", 
    drawGrid = TRUE) %>% dySeries("actual", label = "Observado") %>% dySeries(paste0("predicted.", 
    c("lwr", "fit", "upr")), label = "Previsto") %>% dyOptions(colors = RColorBrewer::brewer.pal(3, 
    "Set1"), drawPoints = TRUE, pointSize = 2) %>% dyRangeSelector() %>% dyHighlight(highlightCircleSize = 4, 
    highlightSeriesBackgroundAlpha = 0.5, hideOnMouseOut = TRUE) %>% dyEvent("2018-01-01", 
    "2018", labelLoc = "bottom") %>% dyEvent("2019-01-01", "2019", labelLoc = "bottom") %>% 
    dyLegend(show = "follow")

Referências

BOX, G.E.P.; JENKINS, G.M. Time series analysis: forecasting and control. Revised edition, San Francisco: Holden-Day, 1976.

FERREIRA, Pedro Costa; SPERANZA, Talitha; COSTA, Jonatha (2018). BETS: Brazilian Economic Time Series. R package version 0.4.9. Disponível em: https://CRAN.R-project.org/package=BETS.

GRANGER, C.W.J.; NEWBOLD, P. Forecasting economic time series. Academic Press, 1977.edition, 1987).

HAMILTON, James D. Time Series Analysis. Princeton University Press, 1994.

HENDRY, David F. Dynamic econometrics, Oxford University Press, 1995.

HYNDMAN, Rob. (2018). fpp2: Data for “Forecasting: Principles and Practice” (2nd Edition). R package version 2.3. Disponível em: https://CRAN.R-project.org/package=fpp2.

HYNDMAN, Rob J.; ATHANASOPOULOS, George . Forecasting: principles and practice. Otexts, 2018. Second Edition. Disponível em: https://www.otexts.org/fpp2.

KENNEDY, Peter. A guide to econometrics. 4.ed. Cambridge: MIT Press, 1998. P. 278-279.

MATTOS, Rogério Silva. Decomposição com regressão (Apostila). Juiz de Fora: UFJF, 2016. Disponível em http://www.ufjf.br/rogerio_mattos/files/2009/06/Decomposição-com-Regressão.pdf. Acesso em 22/fev./2018.

MILLS, Terence C. time series techniques for economists. Cambridge University Press, 1990.

MORETTIN, Pedro A.; TOLOI, Clélia M.C. Análise de Séries Temporais. São Paulo: Edgard Blucher/ABE, 2006.

SAX C.; EDDELBUETTEL, D. (2018). Seasonal Adjustment by X-13ARIMA-SEATS in R. Journal of Statistical Software,87(11), 1-17. doi: 10.18637/jss.v087.i11 (URL: https://doi.org/10.18637/jss.v087.i11).

US BUREAU OF THE CENSUS (2013). X-13ARIMA-SEATS Reference Manual Accessible HTML Output Version. Staff Statistical Research Division, US Bureau of the Census, disponível em: http://www.census.gov/ts/x13as/docX13ASHTML.pdf.

LS0tDQp0aXRsZTogIlPDqXJpZXMgVGVtcG9yYWlzOiBzdWF2aXphw6fDo28gZXhwb25lbmNpYWwgZSBhY3Vyw6FjaWEiDQphdXRob3I6ICJBZHJpYW5vIE1hcmNvcyBSb2RyaWd1ZXMgRmlndWVpcmVkbywgKmUtbWFpbDogYWRyaWFuby5maWd1ZWlyZWRvQHVmbXMuYnIqIg0KbGlua2NvbG9yOiBibHVlDQphYnN0cmFjdDogDQogIFRoaXMgaXMgYW4gdW5kZXJncmFkIHN0dWRlbnQgbGV2ZWwgaW5zdHJ1Y3Rpb24gZm9yIGNsYXNzIHVzZS4gIA0KZGF0ZTogImByIGZvcm1hdChTeXMuRGF0ZSgpLCAnJWQgJUIgJVknKWAiDQpvdXRwdXQ6DQogIGh0bWxfZG9jdW1lbnQ6DQogICAgY29kZV9kb3dubG9hZDogdHJ1ZQ0KICAgIHRoZW1lOiBkZWZhdWx0DQogICAgbnVtYmVyX3NlY3Rpb25zOiB0cnVlDQogICAgdG9jOiB5ZXMNCiAgICB0b2NfZmxvYXQ6IHllcw0KICAgIGRmX3ByaW50OiBwYWdlZA0KICAgIGZpZ19jYXB0aW9uOiB0cnVlDQogIHBkZl9kb2N1bWVudDoNCiAgICB0b2M6IHllcw0KLS0tDQoNCmBgYHtyIGtuaXRyX2luaXQsIGVjaG89RkFMU0UsIGNhY2hlPUZBTFNFfQ0KbGlicmFyeShrbml0cikNCmxpYnJhcnkocm1hcmtkb3duKQ0KbGlicmFyeShybWRmb3JtYXRzKQ0KDQojIyBHbG9iYWwgb3B0aW9ucw0Kb3B0aW9ucyhtYXgucHJpbnQ9IjEwMCIpDQpvcHRzX2NodW5rJHNldChlY2hvPVRSVUUsDQoJICAgICAgICAgICAgIGNhY2hlPVRSVUUsDQogICAgICAgICAgICAgICBwcm9tcHQ9RkFMU0UsDQogICAgICAgICAgICAgICB0aWR5PVRSVUUsDQogICAgICAgICAgICAgICBjb21tZW50PU5BLA0KICAgICAgICAgICAgICAgbWVzc2FnZT1GQUxTRSwNCiAgICAgICAgICAgICAgIHdhcm5pbmc9RkFMU0UpDQpvcHRzX2tuaXQkc2V0KHdpZHRoPTEwMCkNCmBgYA0KDQoNCkxpY2Vuw6dhIHstI0xpY2Vuw6dhfQ0KPT09PT09PT09PT09PT09PT09PQ0KDQpUaGlzIHdvcmsgaXMgbGljZW5zZWQgdW5kZXIgdGhlIENyZWF0aXZlIENvbW1vbnMgQXR0cmlidXRpb24tU2hhcmVBbGlrZSA0LjAgSW50ZXJuYXRpb25hbCBMaWNlbnNlLiBUbyB2aWV3IGEgY29weSBvZiB0aGlzIGxpY2Vuc2UsIHZpc2l0IDxodHRwOi8vY3JlYXRpdmVjb21tb25zLm9yZy9saWNlbnNlcy9ieS1zYS80LjAvPiBvciBzZW5kIGEgbGV0dGVyIHRvIENyZWF0aXZlIENvbW1vbnMsIFBPIEJveCAxODY2LCBNb3VudGFpbiBWaWV3LCBDQSA5NDA0MiwgVVNBLg0KDQohW0xpY2Vuc2U6IENDIEJZLVNBIDQuMF0oaHR0cHM6Ly9taXJyb3JzLmNyZWF0aXZlY29tbW9ucy5vcmcvcHJlc3NraXQvYnV0dG9ucy84OHgzMS9wbmcvYnktc2EucG5nKXsgd2lkdGg9MjUlIH0NCg0KQ2l0YcOnw6NvIHstI0NpdGHDp8Ojb30NCj09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09DQoNClN1Z2VzdMOjbyBkZSBjaXRhw6fDo286DQpGSUdVRUlSRURPLCBBZHJpYW5vIE1hcmNvcyBSb2RyaWd1ZXMuIFPDqXJpZXMgVGVtcG9yYWlzOiBzdWF2aXphw6fDo28gZXhwb25lbmNpYWwgZSBhY3Vyw6FjaWEuIENhbXBvIEdyYW5kZS1NUyxCcmFzaWw6IFJTdHVkaW8vUnB1YnMsIDIwMTkuIERpc3BvbsOtdmVsIGVtIDxodHRwOi8vcnB1YnMuY29tL2Ftcm9maS9zbW9vdGhpbmdfdmFyZWpvbXM+LiANCg0KSW50cm9kdcOnw6NvDQo9PT09PT09PT09PT09PT09PT09DQoNCk5lc3RlIGFycXVpdm8gdXRpbGl6byBhIHPDqXJpZSBkbyDDjW5kaWNlIGRlIHZvbHVtZSBkZSB2ZW5kYXMgbm8gdmFyZWpvIFRvdGFsIGRlIE1hdG8gR3Jvc3NvIGRvIFN1bCwgc8OpcmllIG1lbnNhbCBhIHBhcnRpciBkZSBqYW4vMjAwMCBhdMOpIGp1bi8yMDE5IG9idGlkYSBjb20gbyBwYWNvdGUgYEJFVFNgIGUgaW1wb3J0YWRhIGRvIEJhbmNvIENlbnRyYWwgZG8gQnJhc2lsLiBQb3J0YW50bywgc8OjbyAyMzQgb2JzZXJ2YcOnw7VlcyBtZW5zYWlzLiAgICANCsOJIHVtIGV4ZXJjw61jaW8gcsOhcGlkbyBkZSBzdWF2aXphw6fDo28gZXhwb25lbmNpYWwgZSBhY3Vyw6FjaWEsIHNpbWlsYXIgYW8gcmVhbGl6YWRvIHBhcmEgZGVjb21wb3Npw6fDo28gY2zDoXNzaWNhIGUgeDExIChlbSA8aHR0cDovL3JwdWJzLmNvbS9hbXJvZmkvZGVjb21wb3NlX3gxMV92YXJlam9tcz4pLiANCg0KDQpEYWRvcw0KPT09PT09PT09PT09PT09PT09PQ0KTyBsZWl0b3IgcG9kZSBjYXJyZWdhciBkaXJldG8gZG8gc2l0ZSBkbyBCYW5jbyBDZW50cmFsIGRvIEJyYXNpbCBjb20gbyBwYWNvdGUgYEJFVFNgIChGRVJSRUlSQSwgU1BFUkFOWkEgZSBDT1NUQSwgMjAxOCkgY29tbyBhYml4byBvdSB1c2FyIGEgc2HDrWRhIGRvIGBkcHV0KHZhcmVqb21zKWAgIGNvbmZvcm1lIGNvbG9jYWRvIGFiYWl4by4NCg0KYGBgDQpsaWJyYXJ5KEJFVFMpDQojIFBlZ2FuZG8gYXMgc8OpcmllcyBhIHBhcnRpciBkbyBzaXRlIGRvIEJhbmNvIENlbnRyYWwgZG8gQnJhc2lsDQojIMONbmRpY2UgZGUgdm9sdW1lIGRlIHZlbmRhcyBubyB2YXJlam8gVG90YWwgZGUgTWF0byBHcm9zc28gZG8gU3VsDQojIG1lbnNhbCBhIHBhcnRpciBkZSBqYW4vMjAwMCBhdMOpIGp1bi8yMDE5IA0KIyAyMzQgb2JzZXJ2YcOnw7VlcyBtZW5zYWlzDQp2YXJlam9tcyA8LSBCRVRTZ2V0KDE0NzkpIA0KcHJpbnQodmFyZWpvbXMpDQpjbGFzcyh2YXJlam9tcykNCmRwdXQodmFyZWpvbXMpICAjIG9ww6fDo28gcGFyYSB0ZXIgb3MgZGFkb3MgY29tbyBuYSBzdHJ1Y3R1cmUgYWJhaXhvDQpgYGANCmBgYHtyfQ0KIyB1c28gYSBvcMOnw6NvIGFiYWl4byBwYXJhIHF1YW5kbyBhIGludGVybmV0IHBvciBhbGd1bSBtb3Rpdm8gZmFsaGENCnZhcmVqb21zIDwtIHN0cnVjdHVyZShjKDM1LjIsIDM1LjYsIDM5LjIsIDQwLjUsIDQxLjYsIDQwLjQsIDQwLjgsIDM4LjcsIDM3LjMsIA0KMzcuNiwgMzUuNiwgNDcuNCwgMzQuMiwgMzIuMiwgMzgsIDM3LjUsIDM4LjgsIDM1LCAzOC40LCA0MC4yLCANCjM4LjIsIDM5LjMsIDM2LCA0Ni4zLCAzNi40LCAzNCwgMzksIDM3LjgsIDM4LjksIDM1LjMsIDM3LjIsIDM4LjEsIA0KMzUuNiwgMzguMywgMzUuNiwgNDUuNywgMzIuMiwgMzEuNiwgMzUuMiwgMzYuOCwgMzcuNSwgMzQuOCwgMzguNCwgDQozOC4xLCAzNywgMzksIDM3LjMsIDQ5LCAzNS44LCAzNS4zLCA0MC4yLCA0MS4zLCA0My45LCA0MS42LCA0NS45LCANCjQyLjMsIDQyLjIsIDQ0LCA0MS4zLCA1Ni45LCAzOC41LCAzOC41LCA0NS4zLCA0My42LCA0Ni4yLCA0NC4zLCANCjQ3LjUsIDQ2LjUsIDQ2LjQsIDQ2LCA0NC4xLCA2MSwgNDIsIDQwLjIsIDQ0LjYsIDQ0LjUsIDQ3LjgsIDQ1LjMsIA0KNDYuNSwgNDguNSwgNDcuNywgNTAuMiwgNDkuMywgNjQuNSwgNDcsIDQ2LjgsIDUxLCA1MC41LCA1NSwgNTEuMywgDQo1Mi44LCA1NS4zLCA1NC44LCA1NS42LCA1NS4zLCA3Mi4yLCA1NC41LCA1Mi4xLCA1Ni4yLCA1Ny4yLCA2MC44LCANCjU2LjEsIDYxLjgsIDYxLjYsIDU5LjgsIDYzLjMsIDU3LjcsIDc3LjQsIDYxLjQsIDUxLjksIDU3LjMsIDU3LjksIA0KNjEuOSwgNTcuMywgNjEuMSwgNjEuMSwgNjAuNiwgNjUuNiwgNjMuNSwgODMuMSwgNjQuMSwgNjAuMiwgNjcuOCwgDQo2Ny4xLCA3Mi44LCA2OC41LCA3MS4xLCA2OS4zLCA2OS45LCA3MS4xLCA2Ny45LCA5Mi43LCA2Ny41LCA2NC44LCANCjY5LjEsIDY5LjQsIDc5LjYsIDcwLjIsIDczLjgsIDcyLjUsIDcxLjMsIDc1LjYsIDc0LjcsIDEwMC44LCANCjc5LjUsIDc1LjcsIDgyLjQsIDc4LCA4NC44LCA4My4yLCA4NC44LCA4OC41LCA4Ni4zLCA5MS43LCA5Mi44LCANCjExMS40LCA5Mi44LCA4My43LCA5Mi41LCA4OC4zLCA5My45LCA4OC44LCA5NiwgOTUuOSwgOTMuMiwgOTguMywgDQoxMDAuNSwgMTI4LjgsIDk3LjIsIDkwLjIsIDk0LjMsIDk0LjQsIDEwMS4xLCA5MiwgOTYuNCwgOTguMiwgDQo5Ny42LCAxMDUuOCwgMTAzLjEsIDEyOS42LCA5OS42LCA4Ny44LCA5NywgOTQuOCwgOTguNiwgOTMuNCwgDQo5OC40LCA5Ni40LCA5Mi41LCAxMDAuNiwgOTcuMiwgMTI0LjUsIDkxLjUsIDg1LjEsIDkxLjYsIDg4LjUsIA0KOTIuMiwgODcuNCwgOTAuNSwgODguMSwgODUuMiwgODkuNCwgOTMuNCwgMTE2LjksIDkwLjgsIDg0LCA4OS43LCANCjg2LjMsIDkwLCA4Ny4zLCA5MC44LCA5My41LCA5My43LCA5MS40LCA5My41LCAxMTQuMSwgODcuOCwgODEuMSwgDQo5NC41LCA4My4yLCA4OS45LCA4OC44LCA4OS4zLCA5My43LCA5My41LCA5Ni4zLCAxMDEuMywgMTE4LjMsIA0KOTMuOCwgODUuMiwgOTAsIDg2LjYsIDkwLCA4NC41KSwgLlRzcCA9IGMoMjAwMCwgMjAxOS40MTY2NjY2NjY2NywgDQoxMiksIGNsYXNzID0gInRzIikNCmNsYXNzKHZhcmVqb21zKQ0KYGBgDQoNClByaW1laXJhcyBhbsOhbGlzZXMNCj09PT09PT09PT09PT09PT09PT09PT09PQ0KSW5pY2lhbG1lbnRlIG9saGFyZWkgYXMgZXN0YXTDrXN0aWNhcyBkZXNjcml0aXZhcyBkYSBzw6lyaWUuIEVtIHNlZ3VpZGEgZmFyZWkgdW0gcGxvdCBiw6FzaWNvIGRhIHPDqXJpZSBlIG8gcGxvdCBwZWxvIHBhY290ZSBgZHlncmFwaHNgLCDDunRpbCBwYXJhIHZlciBvcyBwb250b3MgZGUgcGljb3MgZSBtb21lbnRvcyBlc3BlY8OtZmljb3MuDQoNCmBgYHtyfQ0KIyBlc3RhdGlzdGljYXMgYmFzaWNhcw0Kc3VtbWFyeSh2YXJlam9tcykNCiMgTWluLiAxc3QgUXUuICBNZWRpYW4gICAgTWVhbiAzcmQgUXUuICAgIE1heC4gDQojIDMxLjYwICAgNDQuMDIgICA2NC4zMCAgIDY3LjE3ICAgOTAuMDAgIDEyOS42MCANCg0KIyBwZWxvIHBhY290ZSBkeWdyYXBoIGTDoSBtYWlzIG9ww6fDtWVzDQpsaWJyYXJ5KGR5Z3JhcGhzKQ0KZHlncmFwaCh2YXJlam9tcykNCmBgYA0KDQrDiSBwb3Nzw612ZWwgdmlzdWFsaXphciBub3MgcGxvdHMgYWNpbWE6IHNhem9uYWxpZGFkZSAocG9yIGV4ZW1wbG8sIHBpY29zIGVtIGRlemVtYnJvIGRlIGNhZGEgYW5vKTsgYSB0ZW5kw6puY2lhIGFwYXJlbnRlbWVudGUgY3Jlc2NlbnRlIGF0w6kgMjAxNCBlIGRlY3Jlc2NlIGNvbSBhICJjcmlzZSIgYnJhc2lsZWlyYTsgZSB1bWEgYXBhcmVudGUgbsOjby1lc3RhY2lvbmFyaWVkYWRlIChtw6lkaWEgZSB2YXJpw6JuY2lhIG11ZGFtIG5vIHRlbXBvKS4gRW0gb3V0cmEgcG9zdGFnZW0gYXBsaWNhcmVpIG8gdGVzdGUgZGUgcmFpeiB1bml0w6FyaWEgbmEgc8OpcmllIHBhcmEgYXZhbGlhciBhIGVzdGFjaW9uYXJpZWRhZGUgZGUgbW9kbyBtYWlzIGV4cGzDrWNpdG8uDQoNCg0KU3Vhdml6YcOnw6NvIChvdSBhbGlzYW1lbnRvKSBFeHBvbmVuY2lhbCBTaW1wbGVzIChTRVMpIG91IGFpbmRhLCAg4oCYSG9sdCAxIHBhcsOibWV0cm/igJkNCj09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09DQoNCkVzdGUgbcOpdG9kbyDDqSBhcHJvcHJpYWRvIHBhcmEgc8OpcmllcyBxdWUgc2UgbW92ZW0gYWxlYXRvcmlhbWVudGUgZW0gdG9ybm8gZGUgdW1hIG3DqWRpYSBvdSBuw612ZWwgY29uc3RhbnRlLCBzZW0gdGVuZMOqbmNpYSBlIHNlbSBzYXpvbmFsaWRhZGU6ICRaX3Q9zrxfdCthX3QkIGVtIHF1ZSAkYV90JCDDqSB1bSBydcOtZG8gYnJhbmNvIGRlIG3DqWRpYSB6ZXJvIGUgdmFyacOibmNpYSBjb25zdGFudGUgZSAgJM68X3QkIMOpIHVtIHBhcsOibWV0cm8gbG9jYWxtZW50ZSBjb25zdGFudGUgKG7DrXZlbCk7ICRaX3QkIMOpIGEgc8OpcmllIGVtIGFuw6FsaXNlLg0KDQokJA0Ke1xiYXIgWl90fSA9IFxhbHBoYSB7Wl90fSArIFxsZWZ0KCB7MSAtIFxhbHBoYSB9IFxyaWdodCl7XGJhciBaX3t0IC0gMX19DQokJA0KDQoNCkVtIHF1ZSDOsSDDqSBhIGNvbnN0YW50ZSBkZSBzdWF2aXphw6fDo28sIDA8zrE8MS4NClBvcnRhbnRvLCBzaW1pbGFybWVudGUsDQoNCiQkDQp7XGJhciBaX3t0IC0gMX19ID0gXGFscGhhIHtaX3t0IC0gMX19ICsgXGxlZnQoIHsxIC0gXGFscGhhIH0gXHJpZ2h0KXtcYmFyIFpfe3QgLSAyfX0NCiQkDQoNCg0KTyBxdWUgc3Vic3RpdHVpbmRvICgyKSBlbSAoMSkgZSBkZXNlbnZvbHZlbmRvIG9zIHRlcm1vcyB0ZW0tc2U6DQoNCiQkDQp7XGJhciBaX3R9ID0gXGFscGhhIHtaX3R9ICsgXGFscGhhIFxsZWZ0KCB7MSAtIFxhbHBoYSB9IFxyaWdodCl7Wl97dCAtIDF9fSArIFxhbHBoYSB7XGxlZnQoIHsxIC0gXGFscGhhIH0gXHJpZ2h0KV4yfXtaX3t0IC0gMn19ICsgIFxsZG90cyANCiQkDQoNCg0KT3Ugc2VqYSwgYSBTRVMgZmF6IHVtYSBwcmV2aXPDo28gcXVlIMOpIGEgbcOpZGlhIHBvbmRlcmFkYSBwb3IgJM6xKDEtzrEpXmskIHF1ZSwgcXVhbnRvIG1haXMgcmVjZW50ZSwgbWFpb3Igw6kgbyBwZXNvLg0KDQpTZSAkMDzOsTwxJCwgZW50w6NvICTOsT7OsSgxLc6xKT7OsSgxLc6xKV4yPlxsZG90cz7OsSgxLc6xKV5rJA0KDQpOYSBNTVMgdGVtLXNlIG8gbWVzbW8gcGVzbyBlbnRyZSBvYnNlcnZhw6fDtWVzIHJlY2VudGVzIGUgYW50aWdhcy4gTmEgU0VTLCBhIHZhbnRhZ2VtIHNvYnJlIE1NUyDDqSBxdWUgYXBsaWNhIHBlc29zIG1haW9yZXMgw6BzIG9ic2VydmHDp8O1ZXMgcmVjZW50ZXMuDQpBIHF1ZXN0w6NvIHNlcsOhIGFjaGFyIM6xIHF1ZSBtaW5pbWl6YSBhIHNvbWEgZGUgcXVhZHJhZG9zIGRlIGFqdXN0YW1lbnRvOg0KDQokJA0KUyA9IFxtYXRob3AgXHN1bSBcbGltaXRzX3t0ID0gbCArIDF9Xk4ge1xsZWZ0KCB7e1pfdH0gLSB7e1xoYXQgWn1fe3QgLSAxfX19IFxyaWdodCleMn0NCiQkDQoNCg0KTyBmb3JlY2FzdCBzZXLDoSBjb25zdGFudGUgcGFyYSB0b2RhcyBhcyBvYnNlcnZhw6fDtWVzIGZ1dHVyYXMhISENCg0KYGBge3J9DQp4PC12YXJlam9tcw0KIyBzaW1wbGUgZXhwb25lbnRpYWwgc21vb3RoaW5nIChTRVMpDQoNCnguc2VzPC1zZXMoeCxoPTEyLGxldmVsID0gYyg5NSkpDQp4LnNlcyAgICAgICAgICAjIGV4aWJlIG8gZm9yZWNhc3QgcG9yIGhvbHQgMSBwYXJhbWV0cm8NCnN1bW1hcnkoeC5zZXMpICAjIGZvcm5lY2UgbyByZWxhdG9yaW8gZGEgZXN0aW1hY2FvDQpwbG90KHguc2VzLGNvbD0xLCANCiAgICAgbWFpbiA9ICLDjW5kaWNlIGRlIHZvbHVtZSBkZSB2ZW5kYXMgbm8gdmFyZWpvIFRvdGFsIA0KICAgICBkZSBNYXRvIEdyb3NzbyBkbyBTdWwiLCBzdWI9Im1vZGVsbyBTRVMiKQ0KYGBgDQoNClN1YXZpemHDp8OjbyBIb2x0LVdpbnRlcnMgLSAzIHBhcsOibWV0cm9zDQo9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PQ0KDQpgYGB7cn0NCiMgSG9sdC1XaW50ZXJzIA0KeC5od20gPC0gaHcoeCwgc2Vhc29uYWw9Im11bHRpcGxpY2F0aXZlIikgICMgbXVsdGlwbGljYXRpdm8NCnBsb3QoeCx5bGFiPSJJbmRpY2UgMjAxMT0xMDAiLCBtYWluPQ0KICAgICAgICLDjW5kaWNlIGRlIHZvbHVtZSBkZSB2ZW5kYXMgbm8gdmFyZWpvIFRvdGFsIGRlIE1hdG8gR3Jvc3NvIGRvIFN1bCIsDQogICAgIHR5cGU9Im8iLCAgeGxhYj0iTcOqcy9Bbm8iKQ0KbGluZXMoZml0dGVkKHguc2VzKSwgY29sPSJyZWQiLCBsdHk9MikNCmxpbmVzKHguc2VzJG1lYW4sIHR5cGU9Im8iLCBjb2w9InJlZCIpDQpsaW5lcyh4Lmh3bSRtZWFuLCB0eXBlPSJvIiwgY29sPSJncmVlbiIpDQpsZWdlbmQoInRvcGxlZnQiLGx0eT0xLCBwY2g9MSwgY29sPTE6MywgDQogICAgICAgYygib3JpZ2luYWwiLCJIb2x0IFNpbXBsZXMiLCJIb2x0IFdpbnRlcnMnIE11bHRpcGxpY2F0aXZvIikpDQpzdW1tYXJ5KHguaHdtKQ0KYGBgDQoNCkF2YWxpYcOnw6NvIGRhIHNpbXVsYcOnw6NvDQo9PT09PT09PT09PT09PT09PT09PT09PT0NCg0KUGFyYSB1bWEgc8OzIGVxdWHDp8OjbywgcG9kZW0tc2Ugb2xoYXIgb3MgaW5kaWNhZG9yZXMgdHJhZGljaW9uYWlzIGNvbW8gbyBSwrIsIGVzdGF0w61zdGljYXMgRiBlIHQsIGNyaXTDqXJpb3MgZGUgaW5mb3JtYcOnw6NvIGRlIEFrYWlrZSwgU2Nod2FyeiBlbnRyZSBvdXRyb3MuIFBhcmEgbW9kZWxvcyBkZSBwcmV2aXPDo28sIGRldm8gdGVyIHVtIGVycm8gZGUgcHJldmlzw6NvIG3DrW5pbW8sIGRlZmluaWRvIHBlbG8gcGVzcXVpc2Fkb3IgZGUgbW9kbyBhIGp1bGfDoS1sbyBhZGVxdWFkby4gICANCg0KQXMgdmV6ZXMgcG9kZS1zZSB0ZXIgZXF1YcOnw7VlcyBiZW0gZXN0aW1hZGFzIGp1bnRvIGRlIG91dHJhcyBjb20gcG91Y29zIHBhcsOibWV0cm9zIHNpZ25pZmljYXRpdm9zLCBudW0gbWVzbW8gc2lzdGVtYS4gRGVwZW5kZW5kbyBkbyBvYmpldGl2byBhIHNlciBhbGNhbsOnYWRvLCBzZSBzaW11bGFyIG91IGV4cGxpY2FyLCBidXNjYS1zZSBhanVzdGFtZW50byBjb20gYWx0YSBzaWduaWZpY8OibmNpYSAocGFyYSBleHBsaWNhcikgb3UgYnVzY2Etc2UgbWVsaG9yIHBvZGVyIGRlIGV4cGxpY2HDp8Ojby4gUG9yIG1lbGhvciBwb2RlciBkZSBleHBsaWNhw6fDo28gZW50ZW5kZS1zZTogdmFsb3JlcyBwcmV2aXN0b3MgbWFpcyBwcsOzeGltb3MgZG9zIG9ic2VydmFkb3MuICAgDQoNCkFsZ3VucyBjcml0w6lyaW9zIHBhcmEgYXZhbGlhw6fDo28gZGEgcHJldmlzw6NvIHBvZGVtIHNlciBjaXRhZG9zOiBSYWl6IGRvIEVycm8gZGUgU2ltdWxhw6fDo28gUXVhZHLDoXRpY28gTcOpZGlvOyBSYWl6IGRvIEVycm8gUXVhZHLDoXRpY28gTcOpZGlvIFBlcmNlbnR1YWw7IEVycm8gZGUgU2ltdWxhw6fDo28gTcOpZGlvOyBFcnJvIFBlcmNlbnR1YWwgTcOpZGlvOyBFcnJvIEFic29sdXRvIE3DqWRpbzsgIEVycm8gQWJzb2x1dG8gUGVyY2VudHVhbCBNw6lkaW87IFJhaXogZG8gRXJybyBkZSBTaW11bGHDp8OjbyBFeC1wb3N0IFF1YWRyw6F0aWNvIE3DqWRpbzsgQ29lZmljaWVudGUgZGUgZGVzaWd1YWxkYWRlIGRlIFRoZWlsIChVKS4gICANCg0KIyMgUmFpeiBkbyBFcnJvIGRlIFNpbXVsYcOnw6NvIFF1YWRyw6F0aWNvIE3DqWRpbyAoUk1TRSkNCg0KRXN0ZSBjcml0w6lyaW8gw6kgZGFkbyBwZWxhIGV4cHJlc3PDo286DQokJA0KUk1TRSA9IFw7XHNxcnQge1xmcmFjezF9e1R9XG1hdGhvcCBcc3VtIFxsaW1pdHNfe3QgPSAxfV5UIHt7XGxlZnQoIHtZX3RecyAtIFlfdF5hfSBccmlnaHQpfV4yfX0gDQokJA0KDQpFbSBxdWU6ICRZX3RecyQgw6kgbyB2YWxvciBzaW11bGFkbyAocHJldmlzdG8pIGRlICRZX3QkOyAkWV90XmEkIMOpIG8gdmFsb3IgZWZldGl2byAob2JzZXJ2YWRvKTsgZSBUIMOpIG8gbsO6bWVybyBkZSBwZXLDrW9kb3MgbmEgc2ltdWxhw6fDo28uIA0KDQpPIHJlc3VsdGFkbyDDqSB1bSBlc2NhbGFyIGNvbSBvIHZhbG9yIGRhIHJhaXogcXVhZHJhZGEgZGEgbcOpZGlhIGRhIGRpZmVyZW7Dp2EgcXVhZHLDoXRpY2EgZW50cmUgeCBlIHksIG91IHNlamEsIGEgcmFpeiBkbyBlcnJvIHF1YWRyw6F0aWNvIG3DqWRpby4gTm9ybWFsbWVudGUgZGV2ZSBzZXIgY2FsY3VsYWRvIHBlbGEgZsOzcm11bGEsIG1hcyDDqSByZXBvcnRhZG8gcGVsbyBwcm9ncmFtYSBxdWFuZG8gc2UgZmF6IHVtIOKAnGZvcmVjYXN04oCdLiAgIA0KDQpQYXJhIG8gY8OhbGN1bG8gZGEgUmFpeiBkbyBFcnJvIGRlIFNpbXVsYcOnw6NvIEV4LXBvc3QgUXVhZHLDoXRpY28gTcOpZGlvLCB1dGlsaXphbS1zZSBvcyByZXN1bHRhZG9zIGRvIG1vZGVsbyBkZSBwcmV2aXPDo28gYXBsaWNhZG8gYSB1bSBjb25qdW50byByZXN0cml0byAoaGlzdMOzcmljbykgcGFyYSBjaGVjYXIgb3MgZXJyb3Mgbm8gcGVyw61vZG8gZGUgc2ltdWxhw6fDo28uIEV4ZW1wbG86IHVzYW5kbyBvcyBkYWRvcyBkZSAxOTUwOjAxIGEgMTk4NTowNCwgaGlzdMOzcmljb3MsIHNpbXVsYW0tc2Ugb3MgcmVzdWx0YWRvcyBwYXJhIDE5ODY6MDEgYSAxOTg4OjAxIGUgY2FsY3VsYS1zZSBvIGVycm8gZXgtcG9zdC4gICANCg0KIyMJUmFpeiBkbyBFcnJvIFF1YWRyw6F0aWNvIE3DqWRpbyBQZXJjZW50dWFsIChQUk1TRSkNCg0KJCQNClBSTVNFID0gXDtcc3FydCB7XGZyYWN7MX17VH1cbWF0aG9wIFxzdW0gXGxpbWl0c197dCA9IDF9XlQge3tcbGVmdCgge1xmcmFje3tZX3RecyAtIFlfdF5hfX17e1lfdF5hfX19IFxyaWdodCl9XjJ9fSANCiQkDQoNCg0KRW0gcXVlOiAkWV90XnMkIMOpIG8gdmFsb3Igc2ltdWxhZG8gKHByZXZpc3RvKSBkZSAkWV90JDsgJFlfdF5hJCDDqSBvIHZhbG9yIGVmZXRpdm8gKG9ic2VydmFkbyk7IGUgVCDDqSBvIG7Dum1lcm8gZGUgcGVyw61vZG9zIG5hIHNpbXVsYcOnw6NvLiAgTmVzdGUgY2FzbywgYSBkaWZlcmVuw6dhIGVudHJlIG8gcHJldmlzdG8gZSBvIG9ic2VydmFkbyAobyBlcnJvKSDDqSBkaXZpZGlkYSBwZWxvIHZhbG9yIG9ic2VydmFkbywgb2J0ZW5kby1zZSBhc3NpbSBlbSBiYXNlIHBlcmNlbnR1YWwgcmVsYXRpdm8gYW8gdmFsb3Igb2JzZXJ2YWRvLiANCg0KDQojIyBFcnJvIGRlIFNpbXVsYcOnw6NvIE3DqWRpbyAoTUUpIGUgbyBFcnJvIFBlcmNlbnR1YWwgTcOpZGlvIChNUEUpDQoNCk8gZXJybyBkZSBzaW11bGHDp8OjbyDDqSBiYXNpY2FtZW50ZSBvIHRlcm1vICAkKFlfdF5zIC0gWV90XmEpJCwgY29tbyBkZWZpbmlkbyBhbnRlcmlvcm1lbnRlLiBPIGVycm8gbcOpZGlvIChNRSkgw6ksIHBvcnRhbnRvLCBhIG3DqWRpYSBkb3MgZXJyb3MgcGFyYSBUIG9ic2VydmHDp8O1ZXMsIGVucXVhbnRvIG8gZXJybyBwZXJjZW50dWFsIG3DqWRpbyAoTVBFKSDDqSBvYnRpZG8gcmVsYXRpdml6YW5kby1zZSBwZWxvcyB2YWxvcmVzIG9ic2VydmFkb3MsIGNvbW8gbmFzIGV4cHJlc3PDtWVzIGEgc2VndWlyOg0KDQokJA0KTUU9IFxmcmFjezF9e1R9XHN1bVxsaW1pdHNfe3QgPSAxfV5UIHtcbGVmdCgge1lfdF5zIC0gWV90XmF9IFxyaWdodCl9IA0KJCQNCg0KJCQNCk1QRSA9IDEwMC5cZnJhY3sxfXtUfVxzdW1cbGltaXRzX3t0ID0gMX1eVCB7XGZyYWN7e1xsZWZ0KCB7WV90XnMgLSBZX3ReYX0gXHJpZ2h0KX19e3tZX3ReYX19fSANCiQkDQoNClVtYSByZXNzYWx2YSBuZWNlc3PDoXJpYSDDqSBxdWU6IOKAnFsuLi5dIE8gcHJvYmxlbWEgY29tIG9zIGVycm9zIG3DqWRpb3Mgw6kgcXVlIGVsZXMgcG9kZW0gc2VyIHF1YXNlIHplcm8sIHF1YW5kbyBlbGV2YWRvcyBlcnJvcyBwb3NpdGl2b3MgY2FuY2VsYW0gZWxldmFkb3MgZXJyb3MgbmVnYXRpdm9z4oCdIChQSU5EWUNLIGUgUlVCSU5GRUxELCAyMDA0LCBwLjQ0NykuICAgDQoNCkFsZ3VucyBhdXRvcmVzIHV0aWxpemFtIGVzdGFzIGR1YXMgw7psdGltYXMgbWVkaWRhcyBjb20gbyB0ZXJtbyBlbnRyZSBwYXLDqm50ZXNlcyAgJCB7XGxlZnQoIHtZX3RecyAtIFlfdF5hfSBccmlnaHQpfSAkIG5hIGZvcm1hIGRlIOKAmHZhbG9yIGFic29sdXRv4oCZICRcbGVmdHwge1xsZWZ0KCB7WV90XnMgLSBZX3ReYX0gXHJpZ2h0KX0gXHJpZ2h0fCQgLiBUYWwgcHJvY2VkaW1lbnRvIGF1eGlsaWEgYSBpbnZlc3RpZ2FyIG8gZXJybyBkZSBwcmV2aXPDo28gZG8gbW9kZWxvIGV2aXRhbmRvIG9zIHByb2JsZW1hcyBkZSDigJhlcnJvcyBwb3NpdGl2b3PigJkgY2FuY2VsYXJlbSDigJhlcnJvcyBuZWdhdGl2b3PigJkuIERlc3RhIGZvcm1hLCBzdXJnZW0gYXMgb3V0cmFzIGR1YXMgb3DDp8O1ZXM6IE1BRSBlIE1BUEUuDQoNCiMjIEVycm8gQWJzb2x1dG8gTcOpZGlvIChNQUUpIGUgRXJybyBBYnNvbHV0byBQZXJjZW50dWFsIE3DqWRpbyAoTUFQRSkNCg0KTyBlcnJvIGFic29sdXRvIG3DqWRpbyAoTUFFKSBjb25zaWRlcmEgYSBleHByZXNzw6NvIGFuw6Fsb2dhIGRvIGVycm8gZGUgc2ltdWxhw6fDo28gbcOpZGlvIGNvbSBvcyB2YWxvcmVzIGFic29sdXRvcyBjb21vIG5hIGV4cHJlc3PDo286DQogDQokJA0KTUFFID0gXGZyYWN7MX17VH1cc3VtXGxpbWl0c197dCA9IDF9XlQge1xsZWZ0fCB7WV90XnMgLSBZX3ReYX0gXHJpZ2h0fH0gDQokJA0KDQpTaW1pbGFybWVudGUgYW8gZXJybyBwZXJjZW50dWFsIG3DqWRpbywgbyBlcnJvIGFic29sdXRvIHBlcmNlbnR1YWwgbcOpZGlvIChNQVBFKSBzZXLDoTogDQoNCiQkDQpNQVBFID0gMTAwLlxmcmFjezF9e1R9XHN1bVxsaW1pdHNfe3QgPSAxfV5UIHtcbGVmdHwge1xmcmFje3tcbGVmdCgge1lfdF5zIC0gWV90XmF9IFxyaWdodCl9fXt7WV90XmF9fX0gXHJpZ2h0fH0gDQokJA0KDQpEZXNlamFtLXNlIHZhbG9yZXMgYmFpeG9zIGRhcyBtZWRpZGFzLiBFbnRyZXRhbnRvLCDDqSBpbXBvcnRhbnRlIG9ic2VydmFyIHNlIG8gbW9kZWxvIGVzdMOhIGJlbSBhanVzdGFkbyBwYXJhIG9zIOKAmHBvbnRvcyBkZSBpbmZsZXjDo2/igJkgbm9zIGRhZG9zIChvc2NpbGHDp8O1ZXMsIHZhbGVzIGUgcGljb3MgcXVlIHNlIG9ic2VydmFtIG5vcyBncsOhZmljb3MgcHJldmlzdG9zIGUgcmVhbGl6YWRvcykuDQoNCiMjIEVycm8gQWJzb2x1dG8gUGVyY2VudHVhbCBNw6lkaW8gU2ltw6l0cmljbyAoc01BUEUpDQoNCkFzIG1lZGlkYXMgZGUgYWN1csOhY2lhIHRpcG8gTUFQRSB0w6ptIGEgZGVzdmFudGFnZW0gZGUgcGVuYWxpemFyIG1haXMgb3MgZXJyb3MgbmVnYXRpdm9zIHF1ZSBvcyBwb3NpdGl2b3MuIEFzc2ltLCBzdXJnZSBhIG1lZGlkYSBzTUFQRSBvdSBNQVBFIOKAnHNpbcOpdHJpY2/igJ0gcHJvcG9zdG8gcG9yIEFybXN0cm9uZyAoMTk3OCAsIHAuIDM0OCksIGNpdGFkbyBwb3IgSHluZG1hbiBlIEF0aGFuYXNvcG91bG9zICgyMDE4KS4gRXN0YSBtZWRpZGEgZm9pIHV0aWxpemFkYSBwYXJhIGVzY29saGEgZG8gbWVsaG9yIG1vZGVsbyBuYSBjb21wZXRpw6fDo28gZGUgcHJldmlzw6NvIGRvIE0zIGRlIE1ha3JpZGFraXMgKCRNXjMkIGNvbXBldGl0aW9uKS4gQSBleHByZXNzw6NvIHBhcmEgY8OhbGN1bG8gw6kgZG8gdGlwbzoNCg0KJCQNClx0ZXh0e3NNQVBFfSA9IFx0ZXh0e21lYW59XGxlZnQoMjAwfHtZX3RecyAtIFlfdF5hfXwvKFlfdF5zK1lfdF5hKVxyaWdodCkNCiQkDQoNCkVzdGEgbWVkaWRhIG7Do28gZXN0w6EgZGlzcG9uaWJpbGl6YWRhIGRpcmV0YW1lbnRlIG5hcyBzYcOtZGFzIGRvIHBhY290ZSBgZm9yZWNhc3RgIG5lbSBubyBgZnBwMmAsIGVtIHZpcnR1ZGUgZGEgY3LDrXRpY2EgZGUgSHluZG1hbiBlIEF0aGFuYXNvcG91bG9zICgyMDE4KSBlbSBxdWUgY2l0YW0gSHluZG1hbiBlIEtvZWhsZXIgKDIwMDYpLiBBIG1lZGlkYSBzTUFQRSBwb2RlIHNlciBvYnRpZGEgcGVsb3MgcGFjb3RlcyBgTWV0cmljc2Agb3UgYFRTUHJlZGAuICAgDQoNCiMjIGNyaXTDqXJpb3MgZGUgaW5mb3JtYcOnw6NvLCBBa2Fpa2UgKEFJQyksIFNjaHdhcnogKFNJQyBvdSBCSUMpIGUgSGFubmFuLVF1aW4gKEhRKQ0KDQpBIGlkZWlhIMOpIHF1ZSBub3MgY3JpdMOpcmlvcyBkZSBpbmZvcm1hw6fDo28sIGFjcmVzY2VudGFuZG8gbGFncyBzZSByZWR1eiBhIHNvbWEgZG9zIHJlc8OtZHVvcyAocG9pcyBtYWlzIHZhcmlhw6fDo28gw6kgZXhwbGljYWRhIG5vIG1vZGVsbyksIG91IHNlamEsIGZvaSBhY3Jlc2NlbnRhZGEgbWFpcyBpbmZvcm1hw6fDo28uIE1hcyBhaW5kYSBkZXZlLXNlIHBlbmFsaXphciBhIGFkacOnw6NvIGRvIHJlZ3Jlc3NvciwgdW1hIGlkZWlhIGRlIHJlZHXDp8OjbyBkb3MgZ3JhdXMgZGUgbGliZXJkYWRlIGRvIG1vZGVsby4gDQoNCkVtIGdlcmFsLCBvcyBjcml0w6lyaW9zIHTDqm0gYSBzZWd1aW50ZSBleHByZXNzw6NvOiAkQz1sbs+DIMyCXjIgKFQpK2NfVCDPhihUKSQuDQoNCk8gcHJpbWVpcm8gdGVybW8gYXNzb2NpYSBhIHZhcmnDom5jaWEsIGUgc2V1IHZhbG9yIGRldmUgcmVkdXppciBjb20gbyBhdW1lbnRvIGRlIHZhcmnDoXZlaXMuIE5vIHNlZ3VuZG8gdGVybW8gdGVtLXNlOiAkY19UJCDDqSBvIG7Dum1lcm8gZGUgcGFyw6JtZXRyb3MgZXN0aW1hZG9zOyBlICTPhihUKSQgw6kgYSBvcmRlbSBkbyBwcm9jZXNzbyBxdWUgcGVuYWxpemEgbyBhY3LDqXNjaW1vIGRlIHZhcmnDoXZlaXMuIEFzc2ltLCBxdWFudG8gbWVub3IgQyBtZWxob3Igw6kgbyBtb2RlbG8sIG91IHNlamEsIHRlbSBtZW5vcyByZXPDrWR1b3MsIG1lbm9zIHBhcnRlIG7Do28gZXhwbGljYWRhLiANCk8gQ3JpdMOpcmlvIGRlIEluZm9ybWHDp8OjbyBkZSBBa2Fpa2UgKG91IEFJQyBkZSBBa2Fpa2XigJlzIEluZm9ybWF0aW9uIENyaXRlcmlvbikgb3UgbyBDcml0w6lyaW8gZGUgSW5mb3JtYcOnw6NvIGRlIFNjaHdhcnogb3UgQmF5ZXNpYW5vIChvdSBTSUMgZGUgU2Nod2FyeuKAmXMgSW5mb3JtYXRpb24gQ3JpdGVyaW9uIG91IGVtIGFsZ3VucyBsaXZyb3MgQklDIGRlIEJheWVzaWFuIEluZm9ybWF0aW9uIENyaXRlcmlvbikgc8OjbyBleHByZXNzb3Mgbm8gRXZpZXdzIGRhIGZvcm1hIGrDoSBsb2dhcml0bWl6YWRhIGNvbW86DQoNCg0KXFtBSUMgPSAgLSBcZnJhY3t7Mmx9fXtufSArIFxmcmFje3sya319e259XF0NCg0KXFtTSUMgPSAgLSBcZnJhY3t7Mmx9fXtufSArIFxmcmFje3trLlxsb2cgbn19e259XF0NCg0KXFsNCmwgPSAtIHtcZnJhY3tufXsyfX0NCntcbGVmdCggezEgKyBcbG9nKDJccGkpK1xsb2cgXGxlZnQoIHtcZnJhY3t7XGhhdCBcdmFyZXBzaWxvbiBeXHByaW1lIFxoYXQgXHZhcmVwc2lsb24gfX17bn19IFxyaWdodCl9IFxyaWdodCl9DQpcXQ0KDQpFbSBxdWU6IGsgw6kgbyBuw7ptZXJvIGRlIHJlZ3Jlc3NvcmVzIGluY2x1aW5kby1zZSBvIGludGVyY2VwdG87IG4gw6kgbyBuw7ptZXJvIGRlIG9ic2VydmHDp8O1ZXM7IGwgw6kgbyBsb2cgVmVyb3NzaW1pbGhhbsOnYSBkYSByZWdyZXNzw6NvOyBlICRcaGF0IFx2YXJlcHNpbG9uJCBzw6NvIG9zIHJlc8OtZHVvcyBlc3RpbWFkb3MgZG8gbW9kZWxvLiANCk5vIGZvcm1hdG8gbWFpcyBzaW1wbGlmaWNhZG8gZXhwb3N0byBwb3IgR3JlZW5lICgyMDAyKSwgdGVtLXNlIGlndWFsIGFvIGRlIEJ1ZW5vICgyMDA4LCBwLjQ3KToNCg0KXFsNClxiZWdpbnthcnJheX17bH0NClNJQyA9IEJJQ1xsZWZ0KCB7cCxxfSBccmlnaHQpID0gXGxuIHt7XGhhdCBcc2lnbWEgfV4yfSArIGtcZnJhY3t7XGxuIFR9fXtUfVxcDQp7e1xoYXQgXHNpZ21hIH1eMn0gPSBcZnJhY3t7XHN1bVxub2xpbWl0c197dCA9IDF9XlQge1xoYXQgXHZhcmVwc2lsb24gX3ReMn0gfX17VH0NClxlbmR7YXJyYXl9DQpcXQ0KICANCkVtIHF1ZSBrPXArcSsxIHNlIGhvdXZlciBpbnRlcmNlcHRvLg0KDQpcWw0KQUlDXGxlZnQoIHtwLHF9IFxyaWdodCkgPSBcbG4ge3tcaGF0IFxzaWdtYSB9XjJ9ICsga1xmcmFje3syfX17VH0NClxdDQoNClxbDQpIUVxsZWZ0KCB7cCxxfSBccmlnaHQpID0gXGxuIHt7XGhhdCBcc2lnbWEgfV4yfSArIGtcZnJhY3syfXtUfSBcbG4gVA0KXF0NCg0KUXVhbnRvIG1haXMgcGFyw6JtZXRyb3Mgc8OjbyBlc3RpbWFkb3MsIG1lbm9yIHNlcsOhIG8gZXJybyBlc3RpbWFkbywgbWFzIGlzdG8gw6kgcGVuYWxpemFkbyBubyBzZWd1bmRvIHRlcm1vIGRvcyBjcml0w6lyaW9zLiBEZXNlam8gbWVub3JlcyB2YWxvcmVzIGRvcyBjcml0w6lyaW9zLiBPIEJJQyDDqSBjb25zaXN0ZW50ZSBhc3NpbnRvdGljYW1lbnRlLCBlIG8gQUlDIGZ1bmNpb25hIG1lbGhvciBlbSBwZXF1ZW5hcyBhbW9zdHJhcywgbWFzIMOpIHBpb3IgY29tIG1haXMgcGFyw6JtZXRyb3MuIErDoSBvIEhRIMOpIG1lbm9zIGZvcnRlIHF1ZSBvIEJJQywgb3Ugc2VqYSwgbyBwcmVmZXJpZG8gw6kgbyBCSUMuDQoNCkEgZnVuw6fDo28gYHdpbmRvd2AgIGF1eGlsaWFyw6EgbmEgZXh0cmHDp8OjbyBkZSB1bWEgcGFydGUgZGUgdW1hIHPDqXJpZSB0ZW1wb3JhbCwgZSBjcmlhw6fDo28gZG9zIHN1YnNldHMgZGUgdHJlaW5vIGUgdGVzdGUgbm8gZm9yZWNhc3QuIE5hIGZ1bsOnw6NvIGB3aW5kb3dgIGVzcGVjaWZpY2Ftb3MgbyBpbsOtY2lvIChgc3RhcnRgKSAoZS9vdSBmaW06IGBlbmRgKSBkZSBtb2RvIGEgZGVmaW5pciBvIHN1YnNldC4gTyB0cmVpbm8gw6kgb25kZSBzZXLDoSBvYnRpZG8gbyBtb2RlbG8gZXN0aW1hZG8gZSBvIHRlc3RlIMOpIG9uZGUgdmVyaWZpY2FyZW1vcyBvIGFjZXJ0bywgb3UgYWN1csOhY2lhLCBkbyBtb2RlbG8uIElkZW50aWZpY2FkbyBvIG1lbGhvciBtb2RlbG8sIGZhei1zZSBlbnTDo28gbyBmb3JlY2FzdCBmb3JhIGRhIGFtb3N0cmEuIEEgYW1vc3RyYSBkZSB0ZXN0ZSDDqSBlbSBnZXJhbCAyMCUgZGEgYW1vc3RyYSBleGlzdGVudGUuDQoNCg0KYGBge3J9DQpsaWJyYXJ5KGZwcDIpDQojIGZhcmVpIGFzIGphbmVsYXMgZGUgdGVzdGUgZSB0cmVpbm8sIGVzdGltYXJlaSBvcyBtb2RlbG9zIHBhcmEgYSBhbW9zdHJhIHRyZWlubw0KIyBtb2RlbG8gMTogY29ucy5zZXMNCiMgbW9kZWxvIDI6IGNvbnMuaG9sdHRyZW5kLkVYUA0KIyBtb2RlbG8gMzogY29ucy5ob2x0dHJlbmQuREFNUG0NCiMgbW9kZWxvIDQ6IGNvbnNodzINCg0KIyBhbW9zdHJhIHRyZWlubyBhdMOpIGp1bGhvIDIwMTUgKDE4NyBtZXNlcykNCmNvbnM8LSB3aW5kb3codmFyZWpvbXMsc3RhcnQ9YygyMDAwLDEpLGVuZD1jKDIwMTUsNykpIA0KIyBhbW9zdHJhIHRlc3RlICg0NyBtZXNlcyBhdMOpIGp1bmhvIDIwMTkpDQp0ZXN0ZTwtd2luZG93KHZhcmVqb21zLCBzdGFydD1jKDIwMTUsOCkpIA0KYGBgDQoNClZhbW9zIGNoZWNhciBzZSBzZXBhcmFtb3MgY29ycmV0YW1lbnRlOg0KYGBge3J9DQphdXRvcGxvdCh2YXJlam9tcykgKw0KICBhdXRvbGF5ZXIoY29ucywgc2VyaWVzPSJUcmFpbmluZyIpICsNCiAgYXV0b2xheWVyKHRlc3RlLCBzZXJpZXM9IlRlc3QiKQ0KYGBgDQoNCmBgYHtyfQ0KIyBlc3RpbWFyIG1vZGVsb3MNCmNvbnMuc2VzPC1zZXMoY29ucyxoPTYwLGxldmVsID0gYyg5NSkpICAjIGZvcmVjYXN0IGF0w6kganVsLzIwMjANCmNvbnMuaG9sdHRyZW5kLkVYUDwtaG9sdChjb25zLGg9NjAsbGV2ZWwgPSBjKDk1KSwgZXhwb25lbnRpYWwgPSBUUlVFKQ0KY29ucy5ob2x0dHJlbmQuREFNUG08LSBob2x0KGNvbnMsaD02MCxsZXZlbCA9IGMoOTUpLCBleHBvbmVudGlhbD1UUlVFLGRhbXBlZD1UUlVFKQ0KY29uc2h3MiA8LSBodyhjb25zLCBoPTYwLHNlYXNvbmFsPSJtdWx0aXBsaWNhdGl2ZSIpICAjIG11bHRpcGxpY2F0aXZvDQoNCmF1dG9wbG90KHZhcmVqb21zKSArDQogIGZvcmVjYXN0OjphdXRvbGF5ZXIoY29ucy5zZXMsIHNlcmllcz0iU0VTIiwgUEk9RkFMU0UpICsNCiAgZm9yZWNhc3Q6OmF1dG9sYXllcihjb25zLmhvbHR0cmVuZC5FWFAsIHNlcmllcz0iSG9sdCBFeHBvbi4gVHJlbmQiLCBQST1GQUxTRSkgKw0KICBmb3JlY2FzdDo6YXV0b2xheWVyKGNvbnMuaG9sdHRyZW5kLkRBTVBtLCBzZXJpZXM9IkhvbHQgVHJlbmQgRGFtcGVkIG11bHQiLCBQST1GQUxTRSkgKw0KICBmb3JlY2FzdDo6YXV0b2xheWVyKGNvbnNodzIsIHNlcmllcz0iSG9sdC1XaW50ZXJzIG11bHQiLCBQST1GQUxTRSkgKw0KICB4bGFiKCJBbm8iKSArIHlsYWIoIkNvbnN1bW8iKSArDQogIGdndGl0bGUoIkZvcmVjYXN0cyBwYXJhIGNvbnN1bW8gZG8gdmFyZWpvIE1TIikgKw0KICBndWlkZXMoY29sb3VyPWd1aWRlX2xlZ2VuZCh0aXRsZT0iRm9yZWNhc3QiKSkNCg0Kc3VtbWFyeShjb25zLnNlcykgIA0Kc3VtbWFyeShjb25zLmhvbHR0cmVuZC5FWFApDQpzdW1tYXJ5KGNvbnMuaG9sdHRyZW5kLkRBTVBtKQ0Kc3VtbWFyeShjb25zaHcyKQ0KYGBgDQoNCipBY3Vyw6FjaWEqDQoNCkFzIHByZXZpc8O1ZXMgYWNpbWEgZm9yYW0gZmVpdGFzIGNvbSBhIGFtb3N0cmEgdHJlaW5vIGF0w6kganVsaG8vMjAxNSwgbWFzIHRlbW9zIGRhZG9zIGF0w6kganVsaG8vMjAxOS4gRmFyZW1vcyBhIGFjdXLDoWNpYSBwYXJhIGVzdGUgcGVyw61vZG8uIEEgZnVuw6fDo28gYGFjY3VyYWN5YCBub3MgZm9ybmVjZSB2w6FyaWFzIG1lZGlkYXMgZGUgYWN1csOhY2lhLCBlIHBhcmEgYSBzTUFQRSBwcmVjaXNhcmVtb3MgZG8gcGFjb3RlIGBNZXRyaWNzYCBlIGEgZnVuw6fDo28gYHNtYXBlYC4NCg0KYGBge3J9DQp0ZXN0ZSA8LSB3aW5kb3codmFyZWpvbXMsIHN0YXJ0PWMoMjAxNSw4KSkNCmthYmxlKGZvcmVjYXN0OjphY2N1cmFjeShjb25zLnNlcyx0ZXN0ZSksIGNhcHRpb24gPSAgIlNFUyIpDQprYWJsZShmb3JlY2FzdDo6YWNjdXJhY3koY29ucy5ob2x0dHJlbmQuRVhQLHRlc3RlKSwgY2FwdGlvbiA9ICAiSG9sdC1UcmVuZCBFeHBvbmVuY2lhbCIpDQprYWJsZShmb3JlY2FzdDo6YWNjdXJhY3koY29ucy5ob2x0dHJlbmQuREFNUG0sdGVzdGUpLCBjYXB0aW9uID0gICJIb2x0LVRyZW5kIEFtb3J0ZWNpZGEgTXVsdGlwbGljYXRpdm8iKQ0Ka2FibGUoZm9yZWNhc3Q6OmFjY3VyYWN5KGNvbnNodzIsdGVzdGUpLCBjYXB0aW9uID0gICJIb2x0LVdpbnRlcnMgTXVsdGlwbGljYXRpdm8iKQ0KYGBgDQoNClBhcmEgbyBwYWNvdGUgYE1ldHJpY3NgLCBvYnNlcnZhciBxdWUgZWxlIHRlbSBmdW7Dp8O1ZXMgZGUgbWVzbW8gbm9tZSBxdWUgbyBwYWNvdGUgYGZvcmVjYXN0YCwgZSBwb3J0YW50bywgZGV2ZXMgZXNwZWNpZmljYXIgZXhhdGFtZW50ZSBxdWFsIG8gcGFjb3RlIGUgY3VpZGFyIHBhcmEgYWx0ZXJhciBhIG9yZGVtIGRhcyBzw6lyaWVzICgqYWN0dWFsKiB4ICpwcmVkaWN0ZWQqKS4gTm8gcGFjb3RlIE1ldHJpY3MgZXhpc3RlIHVtYSBkaWZlcmVuw6dhIGRhIG9yZGVtIGRlICQxMF4yJCBjb21wYXJhbmRvIGNvbSBvcyByZXN1bHRhZG9zIGRvIHBhY290ZSBmb3JlY2FzdCENCg0KYGBge3IsIGV2YWw9VFJVRX0NCmxpYnJhcnkoTWV0cmljcykNCnRlc3RlIDwtIHdpbmRvdyh2YXJlam9tcywgc3RhcnQ9YygyMDE1LDgpKQ0Kc21hcGUodGVzdGUsY29ucy5zZXMkbWVhbikNCnNtYXBlKHRlc3RlLGNvbnMuaG9sdHRyZW5kLkVYUCRtZWFuKQ0Kc21hcGUodGVzdGUsY29ucy5ob2x0dHJlbmQuREFNUG0kbWVhbikNCnNtYXBlKHRlc3RlLGNvbnNodzIkbWVhbikNCk1ldHJpY3M6Om1hcGUodGVzdGUsY29ucy5zZXMkbWVhbikNCk1ldHJpY3M6Om1hcGUodGVzdGUsY29ucy5ob2x0dHJlbmQuRVhQJG1lYW4pDQpNZXRyaWNzOjptYXBlKHRlc3RlLGNvbnMuaG9sdHRyZW5kLkRBTVBtJG1lYW4pDQpNZXRyaWNzOjptYXBlKHRlc3RlLGNvbnNodzIkbWVhbikNCmBgYA0KDQoqQ29tZW50w6FyaW8qDQpPIG1vZGVsbyBlc3RpbWFkbyB1dGlsaXphbmRvIGEgYW1vc3RyYSBkZSB0cmVpbm8gcGVyZGUgcXVhbGlkYWRlIGVtIHZpcnR1ZGUgZGEgZm9ydGUgcXVlZGEgYXDDs3MgMjAxNSwgcXVlIGEgYW1vc3RyYSBuw6NvIGNvbnNlZ3VlIHBlcmNlYmVyLiBJc3NvIMOpIG9jYXNpb25hZG8gZW0gcXVlYnJhcyBuYSBzw6lyaWUsIGRlIG1vZG8gcXVlIG8gZm9yZWNhc3QgZmljb3UgcHJlanVkaWNhZG8gcGVsYSBlc2NvbGhhIGRhIGFtb3N0cmEgdHJlaW5vLiBPYnNlcnZhLXNlIGlzc28gbm8gaXRlbSA1LCBxdWFuZG8gbyBmb3JlY2FzdCBmb2kgcmVhbGl6YWRvIHNlbSBkZWxpbWl0YXIgYSBhbW9zdHJhLCByZWFsaXphbmRvIGEgcHJldmlzw6NvIGNvbSB0b2RvIG8gY29uanVudG8gZGUgaW5mb3JtYcOnw7Vlcy4gIA0KDQpgYGB7cn0NCmF1dG9wbG90KHZhcmVqb21zKSArDQogIGZvcmVjYXN0OjphdXRvbGF5ZXIoeC5od20sIHNlcmllcz0iSG9sdC1XaW50ZXJzIG11bHQiLCBQST1GQUxTRSkgKw0KICB4bGFiKCJBbm8iKSArIHlsYWIoIkNvbnN1bW8gLSBJbmRpY2UgMjAxMT0xMDAiKSArDQogIGdndGl0bGUoIkZvcmVjYXN0cyBwYXJhIMONbmRpY2UgZGUgdm9sdW1lIGRlIHZlbmRhcyBubyB2YXJlam8gVG90YWwgDQogICAgICAgICAgZGUgTWF0byBHcm9zc28gZG8gU3VsIikgKw0KICBndWlkZXMoY29sb3VyPWd1aWRlX2xlZ2VuZCh0aXRsZT0iRm9yZWNhc3QiKSkNCmBgYA0KDQpPdXRyYSBvcMOnw6NvIHBlbG8gcGFjb3RlIGBzdGF0c2AgZSBmdW7Dp8OjbyBgSG9sdFdpbnRlcnNgOg0KDQpgYGB7cn0NCmh3IDwtIHN0YXRzOjpIb2x0V2ludGVycyh2YXJlam9tcykNCnByZWRpY3RlZCA8LSBwcmVkaWN0KGh3LCBuLmFoZWFkID0gMjQsIHByZWRpY3Rpb24uaW50ZXJ2YWwgPSBUUlVFKQ0KDQpkeWdyYXBoKHByZWRpY3RlZCwgbWFpbiA9ICJQcmV2aXPDo28gZG8gVmFyZWpvIGRlIE1TIikgJT4lDQogIGR5QXhpcygieCIsIGRyYXdHcmlkID0gVFJVRSkgJT4lDQogIGR5U2VyaWVzKGMoImx3ciIsICJmaXQiLCAidXByIiksIGxhYmVsID0gIlZhcmVqbyIpICU+JQ0KICBkeU9wdGlvbnMoY29sb3JzID0gUkNvbG9yQnJld2VyOjpicmV3ZXIucGFsKDMsICJTZXQxIikpDQoNCiMgY29tYmluZSB0aGUgdGltZSBzZXJpZXMgYWN0dWFsIGFuZCBmb3JjYXN0ZWQgdmFsdWVzDQpjb21iaW5lZCA8LSBjYmluZChwcmVkaWN0ZWQsIGFjdHVhbD12YXJlam9tcykNCg0KIyBwbG90IHRoZSBkaWZmZXJlbnQgdmFsdWVzIGFzIGRpZmZlcmVudCBzZXJpZXMgICAgDQpkeWdyYXBoKGNvbWJpbmVkICwgDQogICAgICAgIG1haW4gPSAiUHJldmlzw6NvIGRvIFZhcmVqbyBkZSBNUyAtIDI0IG1lc2VzIikgJT4lDQogIGR5QXhpcygieCIsIGRyYXdHcmlkID0gVFJVRSkgJT4lDQogIGR5U2VyaWVzKCJhY3R1YWwiLCBsYWJlbCA9ICJPYnNlcnZhZG8iKSAlPiUNCiAgZHlTZXJpZXMocGFzdGUwKCJwcmVkaWN0ZWQuIiwgDQogICAgICAgICAgICAgICAgICBjKCJsd3IiLCAiZml0IiwgInVwciIpKSwgDQogICAgICAgICAgIGxhYmVsID0gIlByZXZpc3RvIikgJT4lDQogIGR5T3B0aW9ucyhjb2xvcnMgPSBSQ29sb3JCcmV3ZXI6OmJyZXdlci5wYWwoMywgIlNldDEiKSwNCiAgICAgICAgICAgIGRyYXdQb2ludHMgPSBUUlVFLCBwb2ludFNpemUgPSAyKSU+JSANCiAgZHlSYW5nZVNlbGVjdG9yKCkgJT4lIA0KICBkeUhpZ2hsaWdodChoaWdobGlnaHRDaXJjbGVTaXplID0gNCwgDQogICAgICAgICAgICAgIGhpZ2hsaWdodFNlcmllc0JhY2tncm91bmRBbHBoYSA9IDAuNSwgDQogICAgICAgICAgICAgIGhpZGVPbk1vdXNlT3V0ID0gVFJVRSkgJT4lIA0KICBkeUV2ZW50KCIyMDE4LTAxLTAxIiwgIjIwMTgiLCBsYWJlbExvYyA9ICJib3R0b20iKSAlPiUgDQogIGR5RXZlbnQoIjIwMTktMDEtMDEiLCAiMjAxOSIsIGxhYmVsTG9jID0gImJvdHRvbSIpICU+JSANCiAgZHlMZWdlbmQoc2hvdyA9ICJmb2xsb3ciKQ0KDQpgYGANCg0KDQpSZWZlcsOqbmNpYXMgey0jUmVmZXLDqm5jaWFzfQ0KPT09PT09PT09PT09PT09PT09PT09PT09DQoNCkJPWCwgRy5FLlAuOyBKRU5LSU5TLCBHLk0uIFRpbWUgc2VyaWVzIGFuYWx5c2lzOiBmb3JlY2FzdGluZyBhbmQgY29udHJvbC4gUmV2aXNlZCBlZGl0aW9uLCBTYW4gRnJhbmNpc2NvOiBIb2xkZW4tRGF5LCAxOTc2Lg0KDQpGRVJSRUlSQSwgUGVkcm8gQ29zdGE7IFNQRVJBTlpBLCBUYWxpdGhhOyAgQ09TVEEsIEpvbmF0aGEgKDIwMTgpLiBCRVRTOiBCcmF6aWxpYW4gRWNvbm9taWMgVGltZSBTZXJpZXMuIFIgcGFja2FnZSB2ZXJzaW9uIDAuNC45LiBEaXNwb27DrXZlbCBlbTogPGh0dHBzOi8vQ1JBTi5SLXByb2plY3Qub3JnL3BhY2thZ2U9QkVUUz4uDQoNCkdSQU5HRVIsIEMuVy5KLjsgTkVXQk9MRCwgUC4gRm9yZWNhc3RpbmcgZWNvbm9taWMgdGltZSBzZXJpZXMuIEFjYWRlbWljIFByZXNzLCAxOTc3LmVkaXRpb24sIDE5ODcpLg0KICANCkhBTUlMVE9OLCBKYW1lcyBELiBUaW1lIFNlcmllcyBBbmFseXNpcy4gUHJpbmNldG9uIFVuaXZlcnNpdHkgUHJlc3MsIDE5OTQuDQoNCkhFTkRSWSwgRGF2aWQgRi4gRHluYW1pYyBlY29ub21ldHJpY3MsIE94Zm9yZCBVbml2ZXJzaXR5IFByZXNzLCAxOTk1Lg0KDQpIWU5ETUFOLCBSb2IuICgyMDE4KS4gZnBwMjogRGF0YSBmb3IgIkZvcmVjYXN0aW5nOiBQcmluY2lwbGVzIGFuZCBQcmFjdGljZSIgKDJuZCBFZGl0aW9uKS4gUiBwYWNrYWdlIHZlcnNpb24gMi4zLiBEaXNwb27DrXZlbCBlbTogPGh0dHBzOi8vQ1JBTi5SLXByb2plY3Qub3JnL3BhY2thZ2U9ZnBwMj4uICANCg0KSFlORE1BTiwgUm9iIEouOyBBVEhBTkFTT1BPVUxPUywgR2VvcmdlIC4gRm9yZWNhc3Rpbmc6IHByaW5jaXBsZXMgYW5kIHByYWN0aWNlLiBPdGV4dHMsIDIwMTguIFNlY29uZCBFZGl0aW9uLiBEaXNwb27DrXZlbCBlbTogPGh0dHBzOi8vd3d3Lm90ZXh0cy5vcmcvZnBwMj4uDQoNCktFTk5FRFksIFBldGVyLiBBIGd1aWRlIHRvIGVjb25vbWV0cmljcy4gNC5lZC4gQ2FtYnJpZGdlOiBNSVQgUHJlc3MsIDE5OTguIFAuIDI3OC0yNzkuDQoNCk1BVFRPUywgUm9nw6lyaW8gU2lsdmEuIERlY29tcG9zacOnw6NvIGNvbSByZWdyZXNzw6NvIChBcG9zdGlsYSkuIEp1aXogZGUgRm9yYTogVUZKRiwgMjAxNi4gRGlzcG9uw612ZWwgZW0gaHR0cDovL3d3dy51ZmpmLmJyL3JvZ2VyaW9fbWF0dG9zL2ZpbGVzLzIwMDkvMDYvRGVjb21wb3Npw6fDo28tY29tLVJlZ3Jlc3PDo28ucGRmLiBBY2Vzc28gZW0gMjIvZmV2Li8yMDE4Lg0KDQpNSUxMUywgVGVyZW5jZSBDLiB0aW1lIHNlcmllcyB0ZWNobmlxdWVzIGZvciBlY29ub21pc3RzLiBDYW1icmlkZ2UgVW5pdmVyc2l0eSBQcmVzcywgMTk5MC4NCg0KTU9SRVRUSU4sIFBlZHJvIEEuOyBUT0xPSSwgQ2zDqWxpYSAgTS5DLiBBbsOhbGlzZSBkZSBTw6lyaWVzIFRlbXBvcmFpcy4gU8OjbyBQYXVsbzogRWRnYXJkIEJsdWNoZXIvQUJFLCAyMDA2Lg0KDQpTQVggQy47IEVEREVMQlVFVFRFTCwgRC4gKDIwMTgpLiBTZWFzb25hbCBBZGp1c3RtZW50IGJ5IFgtMTNBUklNQS1TRUFUUyBpbiBSLiBKb3VybmFsIG9mIFN0YXRpc3RpY2FsIFNvZnR3YXJlLCo4NyooMTEpLCAxLTE3LiBkb2k6IDEwLjE4NjM3L2pzcy52MDg3LmkxMSAoVVJMOiBodHRwczovL2RvaS5vcmcvMTAuMTg2MzcvanNzLnYwODcuaTExKS4gICAgIA0KDQpVUyBCVVJFQVUgT0YgVEhFIENFTlNVUyAoMjAxMykuIFgtMTNBUklNQS1TRUFUUyBSZWZlcmVuY2UgTWFudWFsIEFjY2Vzc2libGUgSFRNTCBPdXRwdXQgVmVyc2lvbi4gU3RhZmYgU3RhdGlzdGljYWwgUmVzZWFyY2ggRGl2aXNpb24sIFVTIEJ1cmVhdSBvZiB0aGUgQ2Vuc3VzLCBkaXNwb27DrXZlbCBlbTogPGh0dHA6Ly93d3cuY2Vuc3VzLmdvdi90cy94MTNhcy9kb2NYMTNBU0hUTUwucGRmPi4g