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 com R: Análise do consumo Morettin com X13ARIMA-SEATS. Campo Grande-MS,Brasil: RStudio/Rpubs, 2026 (atualização da versão original 14 Abril 2020). Disponível em http://rpubs.com/amrofi/consumo_morettin_x13.

1 Introdução

Os dados vem do livro de Morettin e Toloi, Análise de Séries Temporais (https://www.ime.usp.br/~pam/ST.html), consumo no varejo de São Paulo, mensais de Jan/1984 a Out/1996, em https://www.ime.usp.br/~pam/CONSUMO.XLS.

# Instalando o pacote completo
# install.packages("seasonal")
# install.packages("ggplot2")

library(readxl);library(fpp2)
# consumo morettin e toloi
#dados <- read_excel("CONSUMO morettin R.xlsx",sheet = "dados")
dados<-
  structure(list(consumo = c(114.13, 110.79, 116.46, 111.57, 120.66, 
121.15, 121.27, 127.02, 129.04, 133.3, 130.6, 179.39, 120.64, 
114.05, 130.6, 118.26, 145.54, 135.13, 153.35, 159.95, 150.01, 
164.93, 170.37, 220.96, 134.26, 133.11, 147.84, 164.46, 181.86, 
170.44, 186.64, 174.21, 181.62, 194.16, 181.9, 232.01, 140.16, 
130.78, 119.04, 120.73, 129.81, 111.04, 122.75, 133.95, 125.41, 
132.05, 129.54, 176.37, 110.09, 113.25, 124.03, 110.63, 116.72, 
124.63, 124.38, 130.27, 119.87, 115.75, 122.44, 162.43, 105.89, 
115.59, 147, 131.7, 131.32, 136.66, 126.43, 134.88, 128.26, 125.32, 
124.61, 166.11, 116.25, 96.93, 89.27, 101.87, 125.57, 113.31, 
109.39, 127.33, 120.56, 117.73, 113.81, 147.25, 100.15, 95.11, 
112.26, 109.39, 114.2, 113.8, 126.47, 128.36, 115.71, 116.09, 
99.53, 127.27, 87.08, 85.67, 82.02, 98.2, 96.44, 90.23, 97.15, 
95.08, 94, 93, 96.09, 129.21, 75.39, 77.7, 97.34, 84.97, 87.55, 
86.64, 90.52, 95.4, 95.2, 95.8, 101.23, 128.49, 85.63, 82.77, 
96.55, 81.33, 96.91, 83.76, 90.19, 114.84, 108.4, 106.05, 109.71, 
143.86, 99.12, 99.28, 114.75, 106.13, 110.02, 108.07, 112.52, 
113.87, 107.84, 112.12, 112.03, 139.37, 92.24, 93.56, 107.37, 
102.89, 114.78, 102.88, 118.41, 119.23, 117.36, 122.06)), row.names = c(NA, 
-154L), class = c("tbl_df", "tbl", "data.frame"))
#consumo.ts<-ts(dados,start = c(1984,1),frequency = 12)
# coloquei opção do dput() a seguir
consumo.ts<-structure(c(114.13, 110.79, 116.46, 111.57, 120.66, 121.15, 121.27, 
127.02, 129.04, 133.3, 130.6, 179.39, 120.64, 114.05, 130.6, 
118.26, 145.54, 135.13, 153.35, 159.95, 150.01, 164.93, 170.37, 
220.96, 134.26, 133.11, 147.84, 164.46, 181.86, 170.44, 186.64, 
174.21, 181.62, 194.16, 181.9, 232.01, 140.16, 130.78, 119.04, 
120.73, 129.81, 111.04, 122.75, 133.95, 125.41, 132.05, 129.54, 
176.37, 110.09, 113.25, 124.03, 110.63, 116.72, 124.63, 124.38, 
130.27, 119.87, 115.75, 122.44, 162.43, 105.89, 115.59, 147, 
131.7, 131.32, 136.66, 126.43, 134.88, 128.26, 125.32, 124.61, 
166.11, 116.25, 96.93, 89.27, 101.87, 125.57, 113.31, 109.39, 
127.33, 120.56, 117.73, 113.81, 147.25, 100.15, 95.11, 112.26, 
109.39, 114.2, 113.8, 126.47, 128.36, 115.71, 116.09, 99.53, 
127.27, 87.08, 85.67, 82.02, 98.2, 96.44, 90.23, 97.15, 95.08, 
94, 93, 96.09, 129.21, 75.39, 77.7, 97.34, 84.97, 87.55, 86.64, 
90.52, 95.4, 95.2, 95.8, 101.23, 128.49, 85.63, 82.77, 96.55, 
81.33, 96.91, 83.76, 90.19, 114.84, 108.4, 106.05, 109.71, 143.86, 
99.12, 99.28, 114.75, 106.13, 110.02, 108.07, 112.52, 113.87, 
107.84, 112.12, 112.03, 139.37, 92.24, 93.56, 107.37, 102.89, 
114.78, 102.88, 118.41, 119.23, 117.36, 122.06), .Dim = c(154L, 
1L), .Dimnames = list(NULL, "consumo"), .Tsp = c(1984, 1996.75, 
12), class = "ts")
(consumo.ts)
        Jan    Feb    Mar    Apr    May    Jun    Jul    Aug    Sep    Oct
1984 114.13 110.79 116.46 111.57 120.66 121.15 121.27 127.02 129.04 133.30
1985 120.64 114.05 130.60 118.26 145.54 135.13 153.35 159.95 150.01 164.93
1986 134.26 133.11 147.84 164.46 181.86 170.44 186.64 174.21 181.62 194.16
1987 140.16 130.78 119.04 120.73 129.81 111.04 122.75 133.95 125.41 132.05
1988 110.09 113.25 124.03 110.63 116.72 124.63 124.38 130.27 119.87 115.75
1989 105.89 115.59 147.00 131.70 131.32 136.66 126.43 134.88 128.26 125.32
1990 116.25  96.93  89.27 101.87 125.57 113.31 109.39 127.33 120.56 117.73
1991 100.15  95.11 112.26 109.39 114.20 113.80 126.47 128.36 115.71 116.09
        Nov    Dec
1984 130.60 179.39
1985 170.37 220.96
1986 181.90 232.01
1987 129.54 176.37
1988 122.44 162.43
1989 124.61 166.11
1990 113.81 147.25
1991  99.53 127.27
 [ reached 'max' / getOption("max.print") -- omitted 5 rows ]
attach(dados)
autoplot(consumo.ts)

#Census x13-Arima-Seats ##############################

# informando ao RStudio onde estão os arquivos para o x13as
# local <- paste0(getwd(), "/x13as")
# Sys.setenv(X13_PATH = local)

library(seasonal);library(seasonalview)  #chamando o pacote
checkX13()  #checagem se o x13 está operacional no RStudio

# vou então gerar as análises fazendo como em SAX(2017) e FERREIRA e MATTOS (2016)
# RELEMBRANDO o gráfico da série
library(ggplot2)

autoplot(consumo.ts, xlab="Tempo") +
  geom_hline(yintercept = seq(70, 230, 5), lty = 3, color = "darkgrey") +
  geom_vline(xintercept = seq(1984, 1997, 1), lty = 3, color = "darkgrey") +
  theme_minimal()

2 Modelo automático

# rodando o automático
ajuste <- seas(x=consumo.ts) # rodou x13

2.1 O modo Shiny do seasonalview

Ele abre um apps Shiny para auxiliar a modelagem e visualização. Ver figura abaixo de como sai o modelo ‘ajuste’.

Figura da tela do Shiny apps do seasonalview.
Figura da tela do Shiny apps do seasonalview.
# not run
view(ajuste)  #seasonalview vai abrir popup 

2.2 Avaliação do automático

A avaliação do modelo ‘automático’ (sem alterar as especificações default) compreende as etapas: 1. Verificar teste de sazonalidade QS; 2. Diagnosticar pré-ajuste e modelo ARIMA; 3. Verificar indícios de sazonalidade ou efeitos de dias úteis graficamente; 4. Avaliar a estabilidade do ajuste sazonal;

# specserie<-spec.ar(consumo.ts)
# specserie
options(digits = 6)
qs(ajuste)      # faz o teste QS para sazonalidade
                  qs p-val
qsori        198.629     0
qsorievadj   217.851     0
qsrsd          0.000     1
qssadj         0.000     1
qssadjevadj    0.000     1
qsirr          0.000     1
qsirrevadj     0.000     1
qssori       103.976     0
qssorievadj  110.445     0
qssrsd         0.000     1
qsssadj        0.000     1
qsssadjevadj   0.000     1
qssirr         0.000     1
qssirrevadj    0.000     1
summary(ajuste) # mostra os resultados da estimação ARIMA automatica e outliers detectados

Call:
seas(x = consumo.ts)

Coefficients:
                  Estimate Std. Error z value Pr(>|z|)    
Weekday            0.00466    0.00121    3.84  0.00012 ***
LS1987.Mar        -0.24369    0.05612   -4.34  1.4e-05 ***
AO1990.Mar        -0.23999    0.04906   -4.89  1.0e-06 ***
MA-Nonseasonal-01  0.34581    0.07059    4.90  9.6e-07 ***
MA-Seasonal-12     0.99999    0.06674   14.98  < 2e-16 ***
---
Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1

SEATS adj.  ARIMA: (0 1 1)(0 1 1)  Obs.: 154  Transform: log
AICc:  982, BIC:  999  QS (no seasonality in final):   0  
Box-Ljung (no autocorr.): 19.3   Shapiro (normality): 0.988  
final(ajuste)  # mostra a serie ajustada
          Jan      Feb      Mar      Apr      May      Jun      Jul      Aug
1984 132.0328 126.9387 120.6406 122.0129 119.2917 128.0256 121.4151 119.0353
1985 137.3050 135.9735 137.5141 127.2347 143.8890 145.1491 151.0475 152.3614
1986 152.8074 158.6975 155.6659 176.9392 182.7553 180.1137 183.8377 168.6748
1987 162.1477 155.9190 123.3108 129.8898 132.5961 115.4431 120.9073 129.6933
1988 129.4560 129.7558 126.3976 120.9811 117.2953 129.5719 126.5784 122.0786
1989 122.5011 137.8071 149.8041 146.3914 129.8308 142.0791 128.6648 126.3979
1990 132.3087 115.5603  92.4696 111.4004 124.1462 119.7428 109.5213 119.3218
1991 113.9848 113.3899 118.1968 117.6868 112.9054 122.2411 124.5714 122.2657
          Sep      Oct      Nov      Dec
1984 130.1792 127.9379 127.1244 136.8745
1985 148.8846 158.2958 168.5654 165.8639
1986 177.3393 186.3507 182.9360 171.3404
1987 122.4544 128.8257 128.1700 130.2513
1988 117.0449 114.7832 119.1854 121.9321
1989 127.2974 122.2619 121.2988 126.7478
1990 121.6234 112.9975 110.7862 112.3581
1991 114.8403 111.4232  98.4799  95.5409
 [ reached 'max' / getOption("max.print") -- omitted 5 rows ]
plot(ajuste)   # grafico da serie ajustada

static(ajuste) # permite o ajuste manual do seas

O static mostra o que foi feito e facilita a alteração de algum item específico, permitindo a replicação ou aperfeiçoamento (ajuste fino).

2.3 Replicando o automático

Replicando o modelo ‘automático’ a partir do resultado de static.

ajuste4<-seas(x = consumo.ts, regression.variables = c("td1coef", "ls1988.Mar", 
     "ao1990.Mar"), arima.model = "(1 0 1)(1 0 0)", regression.aictest = NULL, 
     outlier = NULL, transform.function = "log")
summary(ajuste4)

Call:
seas(x = consumo.ts, transform.function = "log", regression.aictest = NULL, 
    outlier = NULL, regression.variables = c("td1coef", "ls1988.Mar", 
        "ao1990.Mar"), arima.model = "(1 0 1)(1 0 0)")

Coefficients:
                  Estimate Std. Error z value Pr(>|z|)    
Weekday            0.00289    0.00180    1.61     0.11    
LS1988.Mar         0.02855    0.06184    0.46     0.64    
AO1990.Mar        -0.30026    0.05529   -5.43  5.6e-08 ***
AR-Nonseasonal-01  0.99840    0.00241  413.87  < 2e-16 ***
AR-Seasonal-12     0.80449    0.04398   18.29  < 2e-16 ***
MA-Nonseasonal-01  0.37522    0.07160    5.24  1.6e-07 ***
---
Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1

SEATS adj.  ARIMA: (1 0 1)(1 0 0)  Obs.: 154  Transform: log
AICc: 1.18e+03, BIC: 1.21e+03  QS (no seasonality in final):   0  
Box-Ljung (no autocorr.):   31   Shapiro (normality): 0.983 .
Messages generated by X-13:
Notes:
- Model used for SEATS decomposition is different from the model
  estimated in the regARIMA modeling module of X-13ARIMA-SEATS.
#seas(x = consumo.ts, regression.variables = c("td1coef", "ls1987.Mar", 
#    "ao1990.Mar"), arima.model = "(0 1 1)(0 1 1)", regression.aictest = NULL, 
#     outlier = NULL, transform.function = "log")

# reproduzindo o codigo que saiu do static()
(seas(x = consumo.ts, regression.variables = c("td1coef", "ls1987.Mar", 
    "ao1990.Mar"), arima.model = "(0 1 1)(0 1 1)", regression.aictest = NULL, 
    outlier = NULL, transform.function = "log"))

Call:
seas(x = consumo.ts, transform.function = "log", regression.aictest = NULL, 
    outlier = NULL, regression.variables = c("td1coef", "ls1987.Mar", 
        "ao1990.Mar"), arima.model = "(0 1 1)(0 1 1)")

Coefficients:
          Weekday         LS1987.Mar         AO1990.Mar  MA-Nonseasonal-01  
          0.00466           -0.24369           -0.23999            0.34580  
   MA-Seasonal-12  
          0.99996  
#ajuste.auto<-view(ajuste4)

2.4 Forecasts do ajuste

ajuste.fcst<-series(ajuste, c("forecast.forecasts"))
plot(ajuste.fcst)

2.5 Correção do ajuste automático para o Calendário Brasileiro

Faremos a rotina como em Ferreira e Mato (2017). Obtemos os arquivos eletronicamente e colocamos no diretório de trabalho do projeto. Desta forma, conseguimos rodar mesmo sem internet.

library(RCurl)
library(readr)
library(seasonal)
# building moving holidays (mh) = feriados moveis
# usingR_url_mh <- 
#   getURL("https://raw.githubusercontent.com/pedrocostaferreira/Articles/master/using-R-to-teach-seasonal-adjustment/moving_holidays.csv")
# mh <- read.csv2(text = usingR_url_mh)

# 1. Carregar os feriados móveis (Certifique-se de que o CSV está no diretório de trabalho)
# Utilizando o arquivo moving_holidays.csv que contém Year, Easter, Carnival
mh <- read.csv2("moving_holidays.csv")

# Verifique rapidamente se as colunas estão separadas corretamente
head(mh)
# 2. Converter as colunas para o formato de Data do R
dates_easter <- as.Date(mh$Easter, format = "%d/%m/%Y")
dates_carnival <- as.Date(mh$Carnival, format = "%d/%m/%Y")

# 3. Gerar os Regressores com a função genhol (Generate Holiday)
# A parametrização (start, end) deve refletir o comportamento do setor analisado.
# Exemplo para Varejo/Indústria genérico:

# Páscoa: Efeito concentrado nos 8 dias anteriores ao feriado
reg_easter <- genhol(dates_easter, start = -8, end = 1, frequency = 12, center = "mean")

# Carnaval: Impacto forte nos 3 dias que antecedem e no próprio feriado
reg_carnival <- genhol(dates_carnival, start = -3, end = 1, frequency = 12, center = "calendar")

# Matriz combinada de regressores (Alinhada com a série temporal, ajustar via window se necessário)
xreg_br <- cbind(reg_easter, reg_carnival)

# options(digits=6)

2.6 Modelo com ajuste do calendário brasileiro

ajuste2 <- seas(x = consumo.ts, xreg = xreg_br, 
                regression.variables = c("td1coef", "ls1990.Mar"), # td1coef lida com os dias úteis (Trading Days)
                regression.usertype = "holiday",
                regression.aictest = NULL, 
                outlier = NULL, # Ou manter detecção automática retirando esta linha
                transform.function = "auto",
                forecast.save = "forecasts")

options(digits=6)
#view(ajuste2)  # para inicializar seasonalview
qs(ajuste2)
                  qs p-val
qsori        198.629     0
qsorievadj   210.179     0
qsrsd          0.000     1
qssadj         0.000     1
qssadjevadj    0.000     1
qsirr          0.000     1
qsirrevadj     0.000     1
qssori       103.976     0
qssorievadj  124.056     0
qssrsd         0.000     1
qsssadj        0.000     1
qsssadjevadj   0.000     1
qssirr         0.000     1
qssirrevadj    0.000     1
summary(ajuste2)

Call:
seas(x = consumo.ts, xreg = xreg_br, transform.function = "auto", 
    regression.aictest = NULL, outlier = NULL, regression.variables = c("td1coef", 
        "ls1990.Mar"), regression.usertype = "holiday", forecast.save = "forecasts")

Coefficients:
               Estimate Std. Error z value Pr(>|z|)    
Weekday         0.00471    0.00105    4.47  7.8e-06 ***
LS1990.Mar     -0.23525    0.06551   -3.59  0.00033 ***
xreg1           0.00164    0.01892    0.09  0.93094    
xreg2          -0.07224    0.02078   -3.48  0.00051 ***
MA-Seasonal-12  0.99997    0.06721   14.88  < 2e-16 ***
---
Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1

SEATS adj.  ARIMA: (0 1 0)(0 1 1)  Obs.: 154  Transform: log
AICc: 1e+03, BIC: 1.02e+03  QS (no seasonality in final):   0  
Box-Ljung (no autocorr.): 34.2 . Shapiro (normality): 0.99  
Messages generated by X-13:
Warnings:
- At least one visually significant trading day peak has been
  found in one or more of the estimated spectra.
# Checagem de espectro para confirmar se a sazonalidade e efeitos de calendário foram removidos
plot(ajuste2)

monthplot(ajuste2, col.base = 1) # figura dos fatores sazonais
legend("topleft", legend = c("Irregular", "Seasonal", "Seasonal Average"),
       col = c(4,2,1), lwd = c(1,2,2), lty = 1, bty = "n", cex = 0.6)

# ACURACIA  
library(Metrics)
# mae(actual, predicted)
# rmse(actual, predicted)
predicted<-final(ajuste2)
actual<-consumo.ts
(mae2<-mae(actual, predicted))
[1] 9.41983
(rmse2<-rmse(actual, predicted))
[1] 14.5761
# forecasts do ajuste2
# o mesmo que ajuste2$series$fct
forecasts2<-series(ajuste2, c("forecast.forecasts"))

require(graphics);require(zoo)
data.fcst<-cbind.zoo(consumo.ts,series(ajuste2, "forecast.forecasts"))
ts.plot(data.fcst, col=c(1,2,3,4),
     main="série original de consumo e forecasts ajuste3", xlab = "Mês/Ano")
legend("bottomleft",lty=1, pch=1, col=1:4, 
       c("data","X13as","Lim Inferior","Lim Superior"))
grid()

# opcao grafica
library(dygraphs)
dygraph(data.fcst)
dygraph(data.fcst, main = "Indice de consumo do varejo de São Paulo, 
        Moretin e Toloi (2005)") %>%
  dyAxis("y", label = "Indice", valueRange = c(55, 250),
         axisLabelFontSize = 20) %>%
  dyAxis("x", label = "Mês/Ano",axisLabelFontSize = 20 ) %>%
  dyGroup(c("consumo", "forecast"), 
          drawPoints = TRUE, 
          color = c("blue", "red")) %>%
  dyLegend(width = 400)  %>%
  dyAnnotation("1990-3-1", text = "AO-mar1990",
               attachAtBottom = TRUE,width = 100) %>%
  dyOptions(drawPoints = TRUE, 
            pointSize = 5, 
            pointShape = "triangle",
            axisLineWidth = 1.5) 

Referências

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.

FERREIRA, Pedro C.; MATOS, Daiane M. Usando o R para ensinar Ajuste Sazonal. São Paulo: FGV, 2017. 18p. Disponível em: http://portalibre.fgv.br/lumis/portal/file/fileDownload.jsp?fileId=8A7C82C5519A547801533DF7BE5E2D0D

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, R.J., & ATHANASOPOULOS, G. (2018) Forecasting: principles and practice, 2nd edition, OTexts: Melbourne, Australia. Disponível em: https://otexts.com/fpp2/. Accessed on 12 Set 2019.

MORETTIN, Pedro A.; TOLOI, Clélia M.C. Análise de Séries Temporais. São paulo: Editora Edgard Blücher, 2004. https://www.ime.usp.br/~pam/st/

LS0tDQp0aXRsZTogIlPDqXJpZXMgVGVtcG9yYWlzIGNvbSBSOiBBbsOhbGlzZSBkbyBjb25zdW1vIE1vcmV0dGluIGNvbSBYMTNBUklNQS1TRUFUUyINCmF1dGhvcjogIkFkcmlhbm8gTWFyY29zIFJvZHJpZ3VlcyBGaWd1ZWlyZWRvLCAqZS1tYWlsOiBhZHJpYW5vLmZpZ3VlaXJlZG9AdWZtcy5icioiDQpsaW5rY29sb3I6IGJsdWUNCmFic3RyYWN0OiANCiAgVGhpcyBpcyBhbiBleGVyY2lzZSBmb3IgY2xhc3MgdXNlLiBXZSBhbmFseXNlIGRhdGEgb24gUmV0YWlsIGNvbnN1bXB0aW9uLiANCmRhdGU6ICJgciBmb3JtYXQoU3lzLkRhdGUoKSwgJyVkICVCICVZJylgIg0Kb3V0cHV0Og0KICBodG1sX2RvY3VtZW50Og0KICAgIGNvZGVfZG93bmxvYWQ6IHRydWUNCiAgICB0aGVtZTogZGVmYXVsdA0KICAgIG51bWJlcl9zZWN0aW9uczogdHJ1ZQ0KICAgIHRvYzogeWVzDQogICAgdG9jX2Zsb2F0OiBubw0KICAgIGRmX3ByaW50OiBwYWdlZA0KICAgIGZpZ19jYXB0aW9uOiB0cnVlDQogIHBkZl9kb2N1bWVudDoNCiAgICB0b2M6IHllcw0KLS0tDQoNCmBgYHtyIGtuaXRyX2luaXQsIGVjaG89RkFMU0UsIGNhY2hlPUZBTFNFfQ0KbGlicmFyeShrbml0cikNCmxpYnJhcnkocm1hcmtkb3duKQ0KbGlicmFyeShybWRmb3JtYXRzKQ0KDQojIyBHbG9iYWwgb3B0aW9ucw0Kb3B0aW9ucyhtYXgucHJpbnQ9IjEwMCIpDQpvcHRzX2NodW5rJHNldChlY2hvPVRSVUUsDQoJICAgICAgICAgICAgIGNhY2hlPVRSVUUsDQogICAgICAgICAgICAgICBwcm9tcHQ9RkFMU0UsDQogICAgICAgICAgICAgICB0aWR5PVRSVUUsDQogICAgICAgICAgICAgICBjb21tZW50PU5BLA0KICAgICAgICAgICAgICAgbWVzc2FnZT1GQUxTRSwNCiAgICAgICAgICAgICAgIHdhcm5pbmc9RkFMU0UpDQpvcHRzX2tuaXQkc2V0KHdpZHRoPTEwMCkNCmBgYA0KDQoNCkxpY2Vuw6dhIHstI0xpY2Vuw6dhfQ0KPT09PT09PT09PT09PT09PT09PQ0KDQpUaGlzIHdvcmsgaXMgbGljZW5zZWQgdW5kZXIgdGhlIENyZWF0aXZlIENvbW1vbnMgQXR0cmlidXRpb24tU2hhcmVBbGlrZSA0LjAgSW50ZXJuYXRpb25hbCBMaWNlbnNlLiBUbyB2aWV3IGEgY29weSBvZiB0aGlzIGxpY2Vuc2UsIHZpc2l0IDxodHRwOi8vY3JlYXRpdmVjb21tb25zLm9yZy9saWNlbnNlcy9ieS1zYS80LjAvPiBvciBzZW5kIGEgbGV0dGVyIHRvIENyZWF0aXZlIENvbW1vbnMsIFBPIEJveCAxODY2LCBNb3VudGFpbiBWaWV3LCBDQSA5NDA0MiwgVVNBLg0KDQohW0xpY2Vuc2U6IENDIEJZLVNBIDQuMF0oaHR0cHM6Ly9taXJyb3JzLmNyZWF0aXZlY29tbW9ucy5vcmcvcHJlc3NraXQvYnV0dG9ucy84OHgzMS9wbmcvYnktc2EucG5nKXsgd2lkdGg9MjUlIH0NCg0KQ2l0YcOnw6NvIHstI0NpdGHDp8Ojb30NCj09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09DQoNClN1Z2VzdMOjbyBkZSBjaXRhw6fDo286DQpGSUdVRUlSRURPLCBBZHJpYW5vIE1hcmNvcyBSb2RyaWd1ZXMuIFPDqXJpZXMgVGVtcG9yYWlzIGNvbSBSOiBBbsOhbGlzZSBkbyBjb25zdW1vIE1vcmV0dGluIGNvbSBYMTNBUklNQS1TRUFUUy4gQ2FtcG8gR3JhbmRlLU1TLEJyYXNpbDogUlN0dWRpby9ScHVicywgMjAyNiAoYXR1YWxpemHDp8OjbyBkYSB2ZXJzw6NvIG9yaWdpbmFsIDE0IEFicmlsIDIwMjApLiBEaXNwb27DrXZlbCBlbSA8aHR0cDovL3JwdWJzLmNvbS9hbXJvZmkvY29uc3Vtb19tb3JldHRpbl94MTM+LiANCg0KSW50cm9kdcOnw6NvDQo9PT09PT09PT09PT09PT09PT09DQoNCk9zIGRhZG9zIHZlbSBkbyBsaXZybyBkZSBNb3JldHRpbiBlIFRvbG9pLCBBbsOhbGlzZSBkZSBTw6lyaWVzIFRlbXBvcmFpcyAoPGh0dHBzOi8vd3d3LmltZS51c3AuYnIvfnBhbS9TVC5odG1sPiksIGNvbnN1bW8gbm8gdmFyZWpvIGRlIFPDo28gUGF1bG8sIG1lbnNhaXMgZGUgSmFuLzE5ODQgYSBPdXQvMTk5NiwgZW0gPGh0dHBzOi8vd3d3LmltZS51c3AuYnIvfnBhbS9DT05TVU1PLlhMUz4uDQoNCmBgYHtyfQ0KIyBJbnN0YWxhbmRvIG8gcGFjb3RlIGNvbXBsZXRvDQojIGluc3RhbGwucGFja2FnZXMoInNlYXNvbmFsIikNCiMgaW5zdGFsbC5wYWNrYWdlcygiZ2dwbG90MiIpDQoNCmxpYnJhcnkocmVhZHhsKTtsaWJyYXJ5KGZwcDIpDQojIGNvbnN1bW8gbW9yZXR0aW4gZSB0b2xvaQ0KI2RhZG9zIDwtIHJlYWRfZXhjZWwoIkNPTlNVTU8gbW9yZXR0aW4gUi54bHN4IixzaGVldCA9ICJkYWRvcyIpDQpkYWRvczwtDQogIHN0cnVjdHVyZShsaXN0KGNvbnN1bW8gPSBjKDExNC4xMywgMTEwLjc5LCAxMTYuNDYsIDExMS41NywgMTIwLjY2LCANCjEyMS4xNSwgMTIxLjI3LCAxMjcuMDIsIDEyOS4wNCwgMTMzLjMsIDEzMC42LCAxNzkuMzksIDEyMC42NCwgDQoxMTQuMDUsIDEzMC42LCAxMTguMjYsIDE0NS41NCwgMTM1LjEzLCAxNTMuMzUsIDE1OS45NSwgMTUwLjAxLCANCjE2NC45MywgMTcwLjM3LCAyMjAuOTYsIDEzNC4yNiwgMTMzLjExLCAxNDcuODQsIDE2NC40NiwgMTgxLjg2LCANCjE3MC40NCwgMTg2LjY0LCAxNzQuMjEsIDE4MS42MiwgMTk0LjE2LCAxODEuOSwgMjMyLjAxLCAxNDAuMTYsIA0KMTMwLjc4LCAxMTkuMDQsIDEyMC43MywgMTI5LjgxLCAxMTEuMDQsIDEyMi43NSwgMTMzLjk1LCAxMjUuNDEsIA0KMTMyLjA1LCAxMjkuNTQsIDE3Ni4zNywgMTEwLjA5LCAxMTMuMjUsIDEyNC4wMywgMTEwLjYzLCAxMTYuNzIsIA0KMTI0LjYzLCAxMjQuMzgsIDEzMC4yNywgMTE5Ljg3LCAxMTUuNzUsIDEyMi40NCwgMTYyLjQzLCAxMDUuODksIA0KMTE1LjU5LCAxNDcsIDEzMS43LCAxMzEuMzIsIDEzNi42NiwgMTI2LjQzLCAxMzQuODgsIDEyOC4yNiwgMTI1LjMyLCANCjEyNC42MSwgMTY2LjExLCAxMTYuMjUsIDk2LjkzLCA4OS4yNywgMTAxLjg3LCAxMjUuNTcsIDExMy4zMSwgDQoxMDkuMzksIDEyNy4zMywgMTIwLjU2LCAxMTcuNzMsIDExMy44MSwgMTQ3LjI1LCAxMDAuMTUsIDk1LjExLCANCjExMi4yNiwgMTA5LjM5LCAxMTQuMiwgMTEzLjgsIDEyNi40NywgMTI4LjM2LCAxMTUuNzEsIDExNi4wOSwgDQo5OS41MywgMTI3LjI3LCA4Ny4wOCwgODUuNjcsIDgyLjAyLCA5OC4yLCA5Ni40NCwgOTAuMjMsIDk3LjE1LCANCjk1LjA4LCA5NCwgOTMsIDk2LjA5LCAxMjkuMjEsIDc1LjM5LCA3Ny43LCA5Ny4zNCwgODQuOTcsIDg3LjU1LCANCjg2LjY0LCA5MC41MiwgOTUuNCwgOTUuMiwgOTUuOCwgMTAxLjIzLCAxMjguNDksIDg1LjYzLCA4Mi43NywgDQo5Ni41NSwgODEuMzMsIDk2LjkxLCA4My43NiwgOTAuMTksIDExNC44NCwgMTA4LjQsIDEwNi4wNSwgMTA5LjcxLCANCjE0My44NiwgOTkuMTIsIDk5LjI4LCAxMTQuNzUsIDEwNi4xMywgMTEwLjAyLCAxMDguMDcsIDExMi41MiwgDQoxMTMuODcsIDEwNy44NCwgMTEyLjEyLCAxMTIuMDMsIDEzOS4zNywgOTIuMjQsIDkzLjU2LCAxMDcuMzcsIA0KMTAyLjg5LCAxMTQuNzgsIDEwMi44OCwgMTE4LjQxLCAxMTkuMjMsIDExNy4zNiwgMTIyLjA2KSksIHJvdy5uYW1lcyA9IGMoTkEsIA0KLTE1NEwpLCBjbGFzcyA9IGMoInRibF9kZiIsICJ0YmwiLCAiZGF0YS5mcmFtZSIpKQ0KI2NvbnN1bW8udHM8LXRzKGRhZG9zLHN0YXJ0ID0gYygxOTg0LDEpLGZyZXF1ZW5jeSA9IDEyKQ0KIyBjb2xvcXVlaSBvcMOnw6NvIGRvIGRwdXQoKSBhIHNlZ3Vpcg0KY29uc3Vtby50czwtc3RydWN0dXJlKGMoMTE0LjEzLCAxMTAuNzksIDExNi40NiwgMTExLjU3LCAxMjAuNjYsIDEyMS4xNSwgMTIxLjI3LCANCjEyNy4wMiwgMTI5LjA0LCAxMzMuMywgMTMwLjYsIDE3OS4zOSwgMTIwLjY0LCAxMTQuMDUsIDEzMC42LCANCjExOC4yNiwgMTQ1LjU0LCAxMzUuMTMsIDE1My4zNSwgMTU5Ljk1LCAxNTAuMDEsIDE2NC45MywgMTcwLjM3LCANCjIyMC45NiwgMTM0LjI2LCAxMzMuMTEsIDE0Ny44NCwgMTY0LjQ2LCAxODEuODYsIDE3MC40NCwgMTg2LjY0LCANCjE3NC4yMSwgMTgxLjYyLCAxOTQuMTYsIDE4MS45LCAyMzIuMDEsIDE0MC4xNiwgMTMwLjc4LCAxMTkuMDQsIA0KMTIwLjczLCAxMjkuODEsIDExMS4wNCwgMTIyLjc1LCAxMzMuOTUsIDEyNS40MSwgMTMyLjA1LCAxMjkuNTQsIA0KMTc2LjM3LCAxMTAuMDksIDExMy4yNSwgMTI0LjAzLCAxMTAuNjMsIDExNi43MiwgMTI0LjYzLCAxMjQuMzgsIA0KMTMwLjI3LCAxMTkuODcsIDExNS43NSwgMTIyLjQ0LCAxNjIuNDMsIDEwNS44OSwgMTE1LjU5LCAxNDcsIA0KMTMxLjcsIDEzMS4zMiwgMTM2LjY2LCAxMjYuNDMsIDEzNC44OCwgMTI4LjI2LCAxMjUuMzIsIDEyNC42MSwgDQoxNjYuMTEsIDExNi4yNSwgOTYuOTMsIDg5LjI3LCAxMDEuODcsIDEyNS41NywgMTEzLjMxLCAxMDkuMzksIA0KMTI3LjMzLCAxMjAuNTYsIDExNy43MywgMTEzLjgxLCAxNDcuMjUsIDEwMC4xNSwgOTUuMTEsIDExMi4yNiwgDQoxMDkuMzksIDExNC4yLCAxMTMuOCwgMTI2LjQ3LCAxMjguMzYsIDExNS43MSwgMTE2LjA5LCA5OS41MywgDQoxMjcuMjcsIDg3LjA4LCA4NS42NywgODIuMDIsIDk4LjIsIDk2LjQ0LCA5MC4yMywgOTcuMTUsIDk1LjA4LCANCjk0LCA5MywgOTYuMDksIDEyOS4yMSwgNzUuMzksIDc3LjcsIDk3LjM0LCA4NC45NywgODcuNTUsIDg2LjY0LCANCjkwLjUyLCA5NS40LCA5NS4yLCA5NS44LCAxMDEuMjMsIDEyOC40OSwgODUuNjMsIDgyLjc3LCA5Ni41NSwgDQo4MS4zMywgOTYuOTEsIDgzLjc2LCA5MC4xOSwgMTE0Ljg0LCAxMDguNCwgMTA2LjA1LCAxMDkuNzEsIDE0My44NiwgDQo5OS4xMiwgOTkuMjgsIDExNC43NSwgMTA2LjEzLCAxMTAuMDIsIDEwOC4wNywgMTEyLjUyLCAxMTMuODcsIA0KMTA3Ljg0LCAxMTIuMTIsIDExMi4wMywgMTM5LjM3LCA5Mi4yNCwgOTMuNTYsIDEwNy4zNywgMTAyLjg5LCANCjExNC43OCwgMTAyLjg4LCAxMTguNDEsIDExOS4yMywgMTE3LjM2LCAxMjIuMDYpLCAuRGltID0gYygxNTRMLCANCjFMKSwgLkRpbW5hbWVzID0gbGlzdChOVUxMLCAiY29uc3VtbyIpLCAuVHNwID0gYygxOTg0LCAxOTk2Ljc1LCANCjEyKSwgY2xhc3MgPSAidHMiKQ0KKGNvbnN1bW8udHMpDQphdHRhY2goZGFkb3MpDQphdXRvcGxvdChjb25zdW1vLnRzKQ0KYGBgDQoNCmBgYHtyfQ0KI0NlbnN1cyB4MTMtQXJpbWEtU2VhdHMgIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQoNCiMgaW5mb3JtYW5kbyBhbyBSU3R1ZGlvIG9uZGUgZXN0w6NvIG9zIGFycXVpdm9zIHBhcmEgbyB4MTNhcw0KIyBsb2NhbCA8LSBwYXN0ZTAoZ2V0d2QoKSwgIi94MTNhcyIpDQojIFN5cy5zZXRlbnYoWDEzX1BBVEggPSBsb2NhbCkNCg0KbGlicmFyeShzZWFzb25hbCk7bGlicmFyeShzZWFzb25hbHZpZXcpICAjY2hhbWFuZG8gbyBwYWNvdGUNCmNoZWNrWDEzKCkgICNjaGVjYWdlbSBzZSBvIHgxMyBlc3TDoSBvcGVyYWNpb25hbCBubyBSU3R1ZGlvDQoNCiMgdm91IGVudMOjbyBnZXJhciBhcyBhbsOhbGlzZXMgZmF6ZW5kbyBjb21vIGVtIFNBWCgyMDE3KSBlIEZFUlJFSVJBIGUgTUFUVE9TICgyMDE2KQ0KIyBSRUxFTUJSQU5ETyBvIGdyw6FmaWNvIGRhIHPDqXJpZQ0KbGlicmFyeShnZ3Bsb3QyKQ0KDQphdXRvcGxvdChjb25zdW1vLnRzLCB4bGFiPSJUZW1wbyIpICsNCiAgZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0gc2VxKDcwLCAyMzAsIDUpLCBsdHkgPSAzLCBjb2xvciA9ICJkYXJrZ3JleSIpICsNCiAgZ2VvbV92bGluZSh4aW50ZXJjZXB0ID0gc2VxKDE5ODQsIDE5OTcsIDEpLCBsdHkgPSAzLCBjb2xvciA9ICJkYXJrZ3JleSIpICsNCiAgdGhlbWVfbWluaW1hbCgpDQpgYGANCg0KTW9kZWxvIGF1dG9tw6F0aWNvDQo9PT09PT09PT09PT09PT09PT09DQoNCmBgYHtyfQ0KIyByb2RhbmRvIG8gYXV0b23DoXRpY28NCmFqdXN0ZSA8LSBzZWFzKHg9Y29uc3Vtby50cykgIyByb2RvdSB4MTMNCg0KYGBgDQoNCiMjIE8gbW9kbyBTaGlueSBkbyBzZWFzb25hbHZpZXcNCg0KRWxlIGFicmUgdW0gYXBwcyBTaGlueSBwYXJhIGF1eGlsaWFyIGEgbW9kZWxhZ2VtIGUgdmlzdWFsaXphw6fDo28uIFZlciBmaWd1cmEgYWJhaXhvIGRlIGNvbW8gc2FpIG8gbW9kZWxvICdhanVzdGUnLg0KDQohW0ZpZ3VyYSBkYSB0ZWxhIGRvIFNoaW55IGFwcHMgZG8gc2Vhc29uYWx2aWV3Ll0oc2Vhc29uYWx2aWV3X2FqdXN0ZTEucG5nKXsgd2lkdGg9ODAlIH0NCg0KYGBge3IsIGV2YWw9RkFMU0V9DQojIG5vdCBydW4NCnZpZXcoYWp1c3RlKSAgI3NlYXNvbmFsdmlldyB2YWkgYWJyaXIgcG9wdXAgDQpgYGANCg0KDQojIyBBdmFsaWHDp8OjbyBkbyBhdXRvbcOhdGljbw0KDQpBIGF2YWxpYcOnw6NvIGRvIG1vZGVsbyAnYXV0b23DoXRpY28nIChzZW0gYWx0ZXJhciBhcyBlc3BlY2lmaWNhw6fDtWVzIGRlZmF1bHQpIGNvbXByZWVuZGUgYXMgZXRhcGFzOg0KMS4gIFZlcmlmaWNhciB0ZXN0ZSBkZSBzYXpvbmFsaWRhZGUgUVM7DQoyLiAgRGlhZ25vc3RpY2FyIHByw6ktYWp1c3RlIGUgbW9kZWxvIEFSSU1BOw0KMy4gIFZlcmlmaWNhciBpbmTDrWNpb3MgZGUgc2F6b25hbGlkYWRlIG91IGVmZWl0b3MgZGUgZGlhcyDDunRlaXMgZ3JhZmljYW1lbnRlOyANCjQuICBBdmFsaWFyIGEgZXN0YWJpbGlkYWRlIGRvIGFqdXN0ZSBzYXpvbmFsOw0KDQpgYGB7cn0NCiMgc3BlY3NlcmllPC1zcGVjLmFyKGNvbnN1bW8udHMpDQojIHNwZWNzZXJpZQ0Kb3B0aW9ucyhkaWdpdHMgPSA2KQ0KcXMoYWp1c3RlKSAgICAgICMgZmF6IG8gdGVzdGUgUVMgcGFyYSBzYXpvbmFsaWRhZGUNCnN1bW1hcnkoYWp1c3RlKSAjIG1vc3RyYSBvcyByZXN1bHRhZG9zIGRhIGVzdGltYcOnw6NvIEFSSU1BIGF1dG9tYXRpY2EgZSBvdXRsaWVycyBkZXRlY3RhZG9zDQpmaW5hbChhanVzdGUpICAjIG1vc3RyYSBhIHNlcmllIGFqdXN0YWRhDQpwbG90KGFqdXN0ZSkgICAjIGdyYWZpY28gZGEgc2VyaWUgYWp1c3RhZGENCnN0YXRpYyhhanVzdGUpICMgcGVybWl0ZSBvIGFqdXN0ZSBtYW51YWwgZG8gc2Vhcw0KDQpgYGANCg0KTyBgc3RhdGljYCBtb3N0cmEgbyBxdWUgZm9pIGZlaXRvIGUgZmFjaWxpdGEgYSBhbHRlcmHDp8OjbyBkZSBhbGd1bSBpdGVtIGVzcGVjw61maWNvLCBwZXJtaXRpbmRvIGEgcmVwbGljYcOnw6NvIG91IGFwZXJmZWnDp29hbWVudG8gKGFqdXN0ZSBmaW5vKS4NCg0KIyMgUmVwbGljYW5kbyBvIGF1dG9tw6F0aWNvDQoNClJlcGxpY2FuZG8gbyBtb2RlbG8gJ2F1dG9tw6F0aWNvJyBhIHBhcnRpciBkbyByZXN1bHRhZG8gZGUgYHN0YXRpY2AuDQoNCmBgYHtyfQ0KYWp1c3RlNDwtc2Vhcyh4ID0gY29uc3Vtby50cywgcmVncmVzc2lvbi52YXJpYWJsZXMgPSBjKCJ0ZDFjb2VmIiwgImxzMTk4OC5NYXIiLCANCiAgICAgImFvMTk5MC5NYXIiKSwgYXJpbWEubW9kZWwgPSAiKDEgMCAxKSgxIDAgMCkiLCByZWdyZXNzaW9uLmFpY3Rlc3QgPSBOVUxMLCANCiAgICAgb3V0bGllciA9IE5VTEwsIHRyYW5zZm9ybS5mdW5jdGlvbiA9ICJsb2ciKQ0Kc3VtbWFyeShhanVzdGU0KQ0KDQojc2Vhcyh4ID0gY29uc3Vtby50cywgcmVncmVzc2lvbi52YXJpYWJsZXMgPSBjKCJ0ZDFjb2VmIiwgImxzMTk4Ny5NYXIiLCANCiMgICAgImFvMTk5MC5NYXIiKSwgYXJpbWEubW9kZWwgPSAiKDAgMSAxKSgwIDEgMSkiLCByZWdyZXNzaW9uLmFpY3Rlc3QgPSBOVUxMLCANCiMgICAgIG91dGxpZXIgPSBOVUxMLCB0cmFuc2Zvcm0uZnVuY3Rpb24gPSAibG9nIikNCg0KIyByZXByb2R1emluZG8gbyBjb2RpZ28gcXVlIHNhaXUgZG8gc3RhdGljKCkNCihzZWFzKHggPSBjb25zdW1vLnRzLCByZWdyZXNzaW9uLnZhcmlhYmxlcyA9IGMoInRkMWNvZWYiLCAibHMxOTg3Lk1hciIsIA0KICAgICJhbzE5OTAuTWFyIiksIGFyaW1hLm1vZGVsID0gIigwIDEgMSkoMCAxIDEpIiwgcmVncmVzc2lvbi5haWN0ZXN0ID0gTlVMTCwgDQogICAgb3V0bGllciA9IE5VTEwsIHRyYW5zZm9ybS5mdW5jdGlvbiA9ICJsb2ciKSkNCg0KI2FqdXN0ZS5hdXRvPC12aWV3KGFqdXN0ZTQpDQpgYGANCg0KIyMgRm9yZWNhc3RzIGRvIGFqdXN0ZQ0KDQpgYGB7cn0NCmFqdXN0ZS5mY3N0PC1zZXJpZXMoYWp1c3RlLCBjKCJmb3JlY2FzdC5mb3JlY2FzdHMiKSkNCnBsb3QoYWp1c3RlLmZjc3QpDQpgYGANCg0KIyMgQ29ycmXDp8OjbyBkbyBhanVzdGUgYXV0b23DoXRpY28gcGFyYSBvIENhbGVuZMOhcmlvIEJyYXNpbGVpcm8NCg0KRmFyZW1vcyBhIHJvdGluYSBjb21vIGVtIEZlcnJlaXJhIGUgTWF0byAoMjAxNykuIE9idGVtb3Mgb3MgYXJxdWl2b3MgZWxldHJvbmljYW1lbnRlIGUgY29sb2NhbW9zIG5vIGRpcmV0w7NyaW8gZGUgdHJhYmFsaG8gZG8gcHJvamV0by4gRGVzdGEgZm9ybWEsIGNvbnNlZ3VpbW9zIHJvZGFyIG1lc21vIHNlbSBpbnRlcm5ldC4NCg0KYGBge3J9DQpsaWJyYXJ5KFJDdXJsKQ0KbGlicmFyeShyZWFkcikNCmxpYnJhcnkoc2Vhc29uYWwpDQojIGJ1aWxkaW5nIG1vdmluZyBob2xpZGF5cyAobWgpID0gZmVyaWFkb3MgbW92ZWlzDQojIHVzaW5nUl91cmxfbWggPC0gDQojICAgZ2V0VVJMKCJodHRwczovL3Jhdy5naXRodWJ1c2VyY29udGVudC5jb20vcGVkcm9jb3N0YWZlcnJlaXJhL0FydGljbGVzL21hc3Rlci91c2luZy1SLXRvLXRlYWNoLXNlYXNvbmFsLWFkanVzdG1lbnQvbW92aW5nX2hvbGlkYXlzLmNzdiIpDQojIG1oIDwtIHJlYWQuY3N2Mih0ZXh0ID0gdXNpbmdSX3VybF9taCkNCg0KIyAxLiBDYXJyZWdhciBvcyBmZXJpYWRvcyBtw7N2ZWlzIChDZXJ0aWZpcXVlLXNlIGRlIHF1ZSBvIENTViBlc3TDoSBubyBkaXJldMOzcmlvIGRlIHRyYWJhbGhvKQ0KIyBVdGlsaXphbmRvIG8gYXJxdWl2byBtb3ZpbmdfaG9saWRheXMuY3N2IHF1ZSBjb250w6ltIFllYXIsIEVhc3RlciwgQ2Fybml2YWwNCm1oIDwtIHJlYWQuY3N2MigibW92aW5nX2hvbGlkYXlzLmNzdiIpDQoNCiMgVmVyaWZpcXVlIHJhcGlkYW1lbnRlIHNlIGFzIGNvbHVuYXMgZXN0w6NvIHNlcGFyYWRhcyBjb3JyZXRhbWVudGUNCmhlYWQobWgpDQoNCiMgMi4gQ29udmVydGVyIGFzIGNvbHVuYXMgcGFyYSBvIGZvcm1hdG8gZGUgRGF0YSBkbyBSDQpkYXRlc19lYXN0ZXIgPC0gYXMuRGF0ZShtaCRFYXN0ZXIsIGZvcm1hdCA9ICIlZC8lbS8lWSIpDQpkYXRlc19jYXJuaXZhbCA8LSBhcy5EYXRlKG1oJENhcm5pdmFsLCBmb3JtYXQgPSAiJWQvJW0vJVkiKQ0KDQojIDMuIEdlcmFyIG9zIFJlZ3Jlc3NvcmVzIGNvbSBhIGZ1bsOnw6NvIGdlbmhvbCAoR2VuZXJhdGUgSG9saWRheSkNCiMgQSBwYXJhbWV0cml6YcOnw6NvIChzdGFydCwgZW5kKSBkZXZlIHJlZmxldGlyIG8gY29tcG9ydGFtZW50byBkbyBzZXRvciBhbmFsaXNhZG8uDQojIEV4ZW1wbG8gcGFyYSBWYXJlam8vSW5kw7pzdHJpYSBnZW7DqXJpY286DQoNCiMgUMOhc2NvYTogRWZlaXRvIGNvbmNlbnRyYWRvIG5vcyA4IGRpYXMgYW50ZXJpb3JlcyBhbyBmZXJpYWRvDQpyZWdfZWFzdGVyIDwtIGdlbmhvbChkYXRlc19lYXN0ZXIsIHN0YXJ0ID0gLTgsIGVuZCA9IDEsIGZyZXF1ZW5jeSA9IDEyLCBjZW50ZXIgPSAibWVhbiIpDQoNCiMgQ2FybmF2YWw6IEltcGFjdG8gZm9ydGUgbm9zIDMgZGlhcyBxdWUgYW50ZWNlZGVtIGUgbm8gcHLDs3ByaW8gZmVyaWFkbw0KcmVnX2Nhcm5pdmFsIDwtIGdlbmhvbChkYXRlc19jYXJuaXZhbCwgc3RhcnQgPSAtMywgZW5kID0gMSwgZnJlcXVlbmN5ID0gMTIsIGNlbnRlciA9ICJjYWxlbmRhciIpDQoNCiMgTWF0cml6IGNvbWJpbmFkYSBkZSByZWdyZXNzb3JlcyAoQWxpbmhhZGEgY29tIGEgc8OpcmllIHRlbXBvcmFsLCBhanVzdGFyIHZpYSB3aW5kb3cgc2UgbmVjZXNzw6FyaW8pDQp4cmVnX2JyIDwtIGNiaW5kKHJlZ19lYXN0ZXIsIHJlZ19jYXJuaXZhbCkNCg0KIyBvcHRpb25zKGRpZ2l0cz02KQ0KYGBgDQoNCiMjIE1vZGVsbyBjb20gYWp1c3RlIGRvIGNhbGVuZMOhcmlvIGJyYXNpbGVpcm8NCg0KYGBge3J9DQphanVzdGUyIDwtIHNlYXMoeCA9IGNvbnN1bW8udHMsIHhyZWcgPSB4cmVnX2JyLCANCiAgICAgICAgICAgICAgICByZWdyZXNzaW9uLnZhcmlhYmxlcyA9IGMoInRkMWNvZWYiLCAibHMxOTkwLk1hciIpLCAjIHRkMWNvZWYgbGlkYSBjb20gb3MgZGlhcyDDunRlaXMgKFRyYWRpbmcgRGF5cykNCiAgICAgICAgICAgICAgICByZWdyZXNzaW9uLnVzZXJ0eXBlID0gImhvbGlkYXkiLA0KICAgICAgICAgICAgICAgIHJlZ3Jlc3Npb24uYWljdGVzdCA9IE5VTEwsIA0KICAgICAgICAgICAgICAgIG91dGxpZXIgPSBOVUxMLCAjIE91IG1hbnRlciBkZXRlY8Onw6NvIGF1dG9tw6F0aWNhIHJldGlyYW5kbyBlc3RhIGxpbmhhDQogICAgICAgICAgICAgICAgdHJhbnNmb3JtLmZ1bmN0aW9uID0gImF1dG8iLA0KICAgICAgICAgICAgICAgIGZvcmVjYXN0LnNhdmUgPSAiZm9yZWNhc3RzIikNCg0Kb3B0aW9ucyhkaWdpdHM9NikNCiN2aWV3KGFqdXN0ZTIpICAjIHBhcmEgaW5pY2lhbGl6YXIgc2Vhc29uYWx2aWV3DQpxcyhhanVzdGUyKQ0Kc3VtbWFyeShhanVzdGUyKQ0KDQojIENoZWNhZ2VtIGRlIGVzcGVjdHJvIHBhcmEgY29uZmlybWFyIHNlIGEgc2F6b25hbGlkYWRlIGUgZWZlaXRvcyBkZSBjYWxlbmTDoXJpbyBmb3JhbSByZW1vdmlkb3MNCnBsb3QoYWp1c3RlMikNCm1vbnRocGxvdChhanVzdGUyLCBjb2wuYmFzZSA9IDEpICMgZmlndXJhIGRvcyBmYXRvcmVzIHNhem9uYWlzDQpsZWdlbmQoInRvcGxlZnQiLCBsZWdlbmQgPSBjKCJJcnJlZ3VsYXIiLCAiU2Vhc29uYWwiLCAiU2Vhc29uYWwgQXZlcmFnZSIpLA0KICAgICAgIGNvbCA9IGMoNCwyLDEpLCBsd2QgPSBjKDEsMiwyKSwgbHR5ID0gMSwgYnR5ID0gIm4iLCBjZXggPSAwLjYpDQoNCiMgQUNVUkFDSUEgIA0KbGlicmFyeShNZXRyaWNzKQ0KIyBtYWUoYWN0dWFsLCBwcmVkaWN0ZWQpDQojIHJtc2UoYWN0dWFsLCBwcmVkaWN0ZWQpDQpwcmVkaWN0ZWQ8LWZpbmFsKGFqdXN0ZTIpDQphY3R1YWw8LWNvbnN1bW8udHMNCihtYWUyPC1tYWUoYWN0dWFsLCBwcmVkaWN0ZWQpKQ0KKHJtc2UyPC1ybXNlKGFjdHVhbCwgcHJlZGljdGVkKSkNCg0KDQpgYGANCg0KYGBge3J9DQojIGZvcmVjYXN0cyBkbyBhanVzdGUyDQojIG8gbWVzbW8gcXVlIGFqdXN0ZTIkc2VyaWVzJGZjdA0KZm9yZWNhc3RzMjwtc2VyaWVzKGFqdXN0ZTIsIGMoImZvcmVjYXN0LmZvcmVjYXN0cyIpKQ0KDQpyZXF1aXJlKGdyYXBoaWNzKTtyZXF1aXJlKHpvbykNCmRhdGEuZmNzdDwtY2JpbmQuem9vKGNvbnN1bW8udHMsc2VyaWVzKGFqdXN0ZTIsICJmb3JlY2FzdC5mb3JlY2FzdHMiKSkNCnRzLnBsb3QoZGF0YS5mY3N0LCBjb2w9YygxLDIsMyw0KSwNCiAgICAgbWFpbj0ic8OpcmllIG9yaWdpbmFsIGRlIGNvbnN1bW8gZSBmb3JlY2FzdHMgYWp1c3RlMyIsIHhsYWIgPSAiTcOqcy9Bbm8iKQ0KbGVnZW5kKCJib3R0b21sZWZ0IixsdHk9MSwgcGNoPTEsIGNvbD0xOjQsIA0KICAgICAgIGMoImRhdGEiLCJYMTNhcyIsIkxpbSBJbmZlcmlvciIsIkxpbSBTdXBlcmlvciIpKQ0KZ3JpZCgpDQoNCiMgb3BjYW8gZ3JhZmljYQ0KbGlicmFyeShkeWdyYXBocykNCmR5Z3JhcGgoZGF0YS5mY3N0KQ0KDQpkeWdyYXBoKGRhdGEuZmNzdCwgbWFpbiA9ICJJbmRpY2UgZGUgY29uc3VtbyBkbyB2YXJlam8gZGUgU8OjbyBQYXVsbywgDQogICAgICAgIE1vcmV0aW4gZSBUb2xvaSAoMjAwNSkiKSAlPiUNCiAgZHlBeGlzKCJ5IiwgbGFiZWwgPSAiSW5kaWNlIiwgdmFsdWVSYW5nZSA9IGMoNTUsIDI1MCksDQogICAgICAgICBheGlzTGFiZWxGb250U2l6ZSA9IDIwKSAlPiUNCiAgZHlBeGlzKCJ4IiwgbGFiZWwgPSAiTcOqcy9Bbm8iLGF4aXNMYWJlbEZvbnRTaXplID0gMjAgKSAlPiUNCiAgZHlHcm91cChjKCJjb25zdW1vIiwgImZvcmVjYXN0IiksIA0KICAgICAgICAgIGRyYXdQb2ludHMgPSBUUlVFLCANCiAgICAgICAgICBjb2xvciA9IGMoImJsdWUiLCAicmVkIikpICU+JQ0KICBkeUxlZ2VuZCh3aWR0aCA9IDQwMCkgICU+JQ0KICBkeUFubm90YXRpb24oIjE5OTAtMy0xIiwgdGV4dCA9ICJBTy1tYXIxOTkwIiwNCiAgICAgICAgICAgICAgIGF0dGFjaEF0Qm90dG9tID0gVFJVRSx3aWR0aCA9IDEwMCkgJT4lDQogIGR5T3B0aW9ucyhkcmF3UG9pbnRzID0gVFJVRSwgDQogICAgICAgICAgICBwb2ludFNpemUgPSA1LCANCiAgICAgICAgICAgIHBvaW50U2hhcGUgPSAidHJpYW5nbGUiLA0KICAgICAgICAgICAgYXhpc0xpbmVXaWR0aCA9IDEuNSkgDQoNCmBgYA0KDQoNClJlZmVyw6puY2lhcyB7LSNSZWZlcsOqbmNpYXN9DQo9PT09PT09PT09PT09PT09PT09PT09PT0NCg0KRkVSUkVJUkEsIFBlZHJvIENvc3RhOyBTUEVSQU5aQSwgVGFsaXRoYTsgIENPU1RBLCBKb25hdGhhICgyMDE4KS4gQkVUUzogQnJhemlsaWFuIEVjb25vbWljIFRpbWUgU2VyaWVzLiBSIHBhY2thZ2UgdmVyc2lvbiAwLjQuOS4gRGlzcG9uw612ZWwgZW06IDxodHRwczovL0NSQU4uUi1wcm9qZWN0Lm9yZy9wYWNrYWdlPUJFVFM+LiAgICAgDQoNCkZFUlJFSVJBLCBQZWRybyBDLjsgTUFUT1MsIERhaWFuZSBNLiBVc2FuZG8gbyBSIHBhcmEgZW5zaW5hciBBanVzdGUgU2F6b25hbC4gU8OjbyBQYXVsbzogRkdWLCAyMDE3LiAxOHAuIERpc3BvbsOtdmVsIGVtOiA8aHR0cDovL3BvcnRhbGlicmUuZmd2LmJyL2x1bWlzL3BvcnRhbC9maWxlL2ZpbGVEb3dubG9hZC5qc3A/ZmlsZUlkPThBN0M4MkM1NTE5QTU0NzgwMTUzM0RGN0JFNUUyRDBEPiANCg0KSFlORE1BTiwgUm9iLiAoMjAxOCkuIGZwcDI6IERhdGEgZm9yICJGb3JlY2FzdGluZzogUHJpbmNpcGxlcyBhbmQgUHJhY3RpY2UiICgybmQgRWRpdGlvbikuIFIgcGFja2FnZSB2ZXJzaW9uIDIuMy4gRGlzcG9uw612ZWwgZW06IDxodHRwczovL0NSQU4uUi1wcm9qZWN0Lm9yZy9wYWNrYWdlPWZwcDI+LiAgICAgDQoNCkhZTkRNQU4sIFIuSi4sICYgQVRIQU5BU09QT1VMT1MsIEcuICgyMDE4KSBGb3JlY2FzdGluZzogcHJpbmNpcGxlcyBhbmQgcHJhY3RpY2UsIDJuZCBlZGl0aW9uLCBPVGV4dHM6IE1lbGJvdXJuZSwgQXVzdHJhbGlhLiBEaXNwb27DrXZlbCBlbTogPGh0dHBzOi8vb3RleHRzLmNvbS9mcHAyLz4uIEFjY2Vzc2VkIG9uIDEyIFNldCAyMDE5Lg0KDQpNT1JFVFRJTiwgUGVkcm8gQS47IFRPTE9JLCBDbMOpbGlhIE0uQy4gQW7DoWxpc2UgZGUgU8OpcmllcyBUZW1wb3JhaXMuIFPDo28gcGF1bG86IEVkaXRvcmEgRWRnYXJkIEJsw7xjaGVyLCAyMDA0LiA8aHR0cHM6Ly93d3cuaW1lLnVzcC5ici9+cGFtL3N0Lz4=