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

Citação

Sugestão de citação: FIGUEIREDO, Adriano Marcos Rodrigues. Séries Temporais com R: Análise do Consumo do Varejo em MS com fable.prophet. Campo Grande-MS,Brasil: RStudio/Rpubs, 2021. Disponível em http://rpubs.com/amrofi/fableprophet_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é jan/2020 obtida com o pacote BETS e importada do Banco Central do Brasil. Portanto, são 241 observações mensais.

Realizaremos os modelos ETS (Error Trend Seasonal) conforme Hyndman e Athanasopoulos (2021,2018), com fable e feasts, e Facebook Prophet ou seja, com o formato tsibble pelo fable.prophet.

Sugiro olhar meus videos no Youtube em: Aplicação de ETS com ações: https://youtu.be/s5S43QBllR0; Video teórico de ETS: https://youtu.be/ej8hH6g9j3Y.

Sobre o Facebook Prophet temos: Facebook Prophet para previsão de séries temporais - mais teórico - (https://youtu.be/9nARpNo1v5w) e Facebook Prophet - aplicação para bitcoin e para LAME4 - time series (https://youtu.be/LENLw0EagRg).

2 Dados

O leitor pode carregar os dados direto do site do Banco Central do Brasil com o pacote BETS (FERREIRA, SPERANZA e COSTA, 2018) conforme code abaixo (não rodei aqui) em data.frame.

Eu gerei a estrutura idêntica pela função dput() para os leitores que não conseguirem por qualquer motivo o acesso ao site do Banco Central (as vezes vejo isso ocorrer dependendo dos bloqueios da sua rede de internet). Esclareço ao leitor que após baixar a série pelo BETS, fiz o dput e a partir de então, desabilitei o bloco (Chunk) que acessa o BETS apenas para agilizar os cálculos.

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é jan/2020  
# 241 observações mensais
varejoms <- BETSget(1479,from="2000-01-01",to="2020-01-31",
              data.frame = TRUE,frequency = 12) 
print(varejoms)
class(varejoms)
dput(varejoms)  # opção para ter os dados como na structure abaixo
# 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é jan/2020

# library(BETS)
varejoms <- structure(list(date = structure(c(10957, 10988, 11017, 11048, 11078,
    11109, 11139, 11170, 11201, 11231, 11262, 11292, 11323, 11354, 11382, 11413,
    11443, 11474, 11504, 11535, 11566, 11596, 11627, 11657, 11688, 11719, 11747,
    11778, 11808, 11839, 11869, 11900, 11931, 11961, 11992, 12022, 12053, 12084,
    12112, 12143, 12173, 12204, 12234, 12265, 12296, 12326, 12357, 12387, 12418,
    12449, 12478, 12509, 12539, 12570, 12600, 12631, 12662, 12692, 12723, 12753,
    12784, 12815, 12843, 12874, 12904, 12935, 12965, 12996, 13027, 13057, 13088,
    13118, 13149, 13180, 13208, 13239, 13269, 13300, 13330, 13361, 13392, 13422,
    13453, 13483, 13514, 13545, 13573, 13604, 13634, 13665, 13695, 13726, 13757,
    13787, 13818, 13848, 13879, 13910, 13939, 13970, 14000, 14031, 14061, 14092,
    14123, 14153, 14184, 14214, 14245, 14276, 14304, 14335, 14365, 14396, 14426,
    14457, 14488, 14518, 14549, 14579, 14610, 14641, 14669, 14700, 14730, 14761,
    14791, 14822, 14853, 14883, 14914, 14944, 14975, 15006, 15034, 15065, 15095,
    15126, 15156, 15187, 15218, 15248, 15279, 15309, 15340, 15371, 15400, 15431,
    15461, 15492, 15522, 15553, 15584, 15614, 15645, 15675, 15706, 15737, 15765,
    15796, 15826, 15857, 15887, 15918, 15949, 15979, 16010, 16040, 16071, 16102,
    16130, 16161, 16191, 16222, 16252, 16283, 16314, 16344, 16375, 16405, 16436,
    16467, 16495, 16526, 16556, 16587, 16617, 16648, 16679, 16709, 16740, 16770,
    16801, 16832, 16861, 16892, 16922, 16953, 16983, 17014, 17045, 17075, 17106,
    17136, 17167, 17198, 17226, 17257, 17287, 17318, 17348, 17379, 17410, 17440,
    17471, 17501, 17532, 17563, 17591, 17622, 17652, 17683, 17713, 17744, 17775,
    17805, 17836, 17866, 17897, 17928, 17956, 17987, 18017, 18048, 18078, 18109,
    18140, 18170, 18201, 18231, 18262), class = "Date"), value = 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, 85.2, 91, 94.4, 93.4, 95.9, 102.6, 116, 94.9)), class = "data.frame", row.names = c(NA,
    -241L))
class(varejoms)
FALSE [1] "data.frame"

A rotina de dados obtidos pelo BETS já retorna a série em formato data.frame, ou seja, com as colunas date e value. Algumas análises eu ignorarei porque já as fiz em outros posts (FIGUEIREDO, 2021).

Precisamos reindexar a série para que ele entenda como mensal (monthly).

3 Análise da série

Farei a divisão entre amostra teste e amostra treino para controle de acurácia, pelo tradicional 80-20 (241 observações x 80% = 193 para treino), portanto a amostra treino será de jan-2000 a jan-2016. O leitor deve em geral fazer estas divisões para certificar de que o modelo é um bom preditor. Uma análise mais detalhada da série pode ser feita fazendo o chunk abaixo.

3.1 Estimação com fable e feasts

Primeiro faremos a conversão de objeto ts para tsibble, ou time series table. Converterei a série inteira varejoms e depois farei o split entre train e test.

library(tsibble)
library(tsibbledata)
library(lubridate)
library(dplyr)
library(tidyverse)

varejo.tsb <- varejoms %>%
    as_tsibble()
autoplot(varejo.tsb)

Precisamos reindexar a série para que ele entenda como mensal (monthly). No plot, pode perceber que está como date[1D], ou seja, diária. Se não corrigir, o forecast será diário! O leitor pode consultar melhor em https://cran.r-project.org/web/packages/tsibble/vignettes/faq.html.

tsibble(mth = yearmonth(mth), index = mth)

mth <- make_date("2000") + months(0:240)
dados <- cbind(varejoms[-1], time = yearmonth(mth))
varejo.tsb <- tsibble(dados, index = time) %>%
    print()
# A tsibble: 241 x 2 [1M]
   value     time
   <dbl>    <mth>
 1  35.2 2000 jan
 2  35.6 2000 fev
 3  39.2 2000 mar
 4  40.5 2000 abr
 5  41.6 2000 mai
 6  40.4 2000 jun
 7  40.8 2000 jul
 8  38.7 2000 ago
 9  37.3 2000 set
10  37.6 2000 out
# ... with 231 more rows
autoplot(varejo.tsb)

Agora sim, o objeto tsibble entende como série mensal.

Faremos o split com uso da função filter_index e especificando filter_index(~ "2016-01"):

train <- varejo.tsb %>%
    filter_index(~"2016-01")
train
h = length(varejo.tsb$value) - length(train$value)
h
[1] 48

Podemos plotar e estimar.

autoplot(train)

A função report fornecerá a saída do modelo.

library(fable.prophet)
library(fable)
library(fpp3)
fit1 <- train %>%
    model(arima = ARIMA(value), ets = ETS(value), prophet = prophet(value))
fc1 <- fit1 %>%
    forecast(h = h)
fc1 %>%
    autoplot(varejo.tsb)

report(fit1)

Agora o forecast à frente 60 meses. Coloquei 48 meses do treino mais 12 meses fora da série observada.

fc2 <- fit1 %>%
    forecast(h = "5 years")
fc2

E a acurácia da parte de teste foi:

fc1 %>%
    accuracy(varejo.tsb, measures = point_accuracy_measures)

Segue o plot da segunda estimação (h=60):

fc2 %>%
    autoplot(varejo.tsb)

E as nossas estimativas para até Jan/2021 são:

knitr::kable(fc2)
.model time value .mean
arima 2016 fev N(82, 5.5) 82.41162
arima 2016 mar N(91, 7.6) 90.91755
arima 2016 abr N(88, 9.9) 87.77713
arima 2016 mai N(94, 13) 93.88157
arima 2016 jun N(87, 15) 86.85013
arima 2016 jul N(92, 19) 92.43054
arima 2016 ago N(91, 21) 91.31703
arima 2016 set N(89, 24) 88.61990
arima 2016 out N(96, 26) 96.22268
arima 2016 nov N(94, 29) 93.67441
arima 2016 dez N(121, 32) 120.56047
arima 2017 jan N(89, 34) 89.08579
arima 2017 fev N(80, 44) 79.69542
arima 2017 mar N(88, 50) 87.90204
arima 2017 abr N(85, 57) 85.26464
arima 2017 mai N(91, 64) 90.87945
arima 2017 jun N(84, 71) 84.23129
arima 2017 jul N(90, 78) 89.55393
arima 2017 ago N(89, 85) 88.58998
arima 2017 set N(86, 92) 85.82168
arima 2017 out N(93, 99) 93.44647
arima 2017 nov N(91, 106) 90.90238
arima 2017 dez N(118, 113) 117.77357
arima 2018 jan N(86, 120) 86.31542
arima 2018 fev N(77, 136) 76.91118
arima 2018 mar N(85, 149) 85.12765
arima 2018 abr N(82, 161) 82.48419
arima 2018 mai N(88, 176) 88.10214
arima 2018 jun N(81, 188) 81.45277
arima 2018 jul N(87, 202) 86.77552
arima 2018 ago N(86, 215) 85.81197
arima 2018 set N(83, 228) 83.04313
arima 2018 out N(91, 241) 90.66841
arima 2018 nov N(88, 255) 88.12395
arima 2018 dez N(115, 268) 114.99538
arima 2019 jan N(84, 281) 83.53710
arima 2019 fev N(74, 307) 74.13292
arima 2019 mar N(82, 328) 82.34937
arima 2019 abr N(80, 349) 79.70591
arima 2019 mai N(85, 372) 85.32387
arima 2019 jun N(79, 392) 78.67449
arima 2019 jul N(84, 415) 83.99725
arima 2019 ago N(83, 436) 83.03369
arima 2019 set N(80, 458) 80.26485
arima 2019 out N(88, 479) 87.89013
arima 2019 nov N(85, 501) 85.34568
arima 2019 dez N(112, 522) 112.21711
arima 2020 jan N(81, 544) 80.75882
arima 2020 fev N(71, 581) 71.35464
arima 2020 mar N(80, 612) 79.57110
arima 2020 abr N(77, 643) 76.92763
arima 2020 mai N(83, 676) 82.54559
arima 2020 jun N(76, 707) 75.89621
arima 2020 jul N(81, 740) 81.21898
arima 2020 ago N(80, 771) 80.25541
arima 2020 set N(77, 804) 77.48657
arima 2020 out N(85, 836) 85.11185
arima 2020 nov N(83, 868) 82.56740
arima 2020 dez N(109, 900) 109.43883
arima 2021 jan N(78, 931) 77.98054
ets 2016 fev N(86, 8.8) 86.21033
ets 2016 mar N(95, 14) 95.09920
ets 2016 abr N(95, 17) 94.61642
ets 2016 mai N(100, 24) 100.37904
ets 2016 jun N(94, 24) 93.61309
ets 2016 jul N(99, 32) 98.96709
ets 2016 ago N(98, 36) 98.27817
ets 2016 set N(95, 39) 95.17126
ets 2016 out N(100, 48) 99.59857
ets 2016 nov N(95, 50) 95.29284
ets 2016 dez N(125, 95) 124.64406
ets 2017 jan N(93, 58) 92.61328
ets 2017 fev N(87, 56) 86.58377
ets 2017 mar N(96, 75) 95.50274
ets 2017 abr N(95, 81) 95.00972
ets 2017 mai N(101, 99) 100.78780
ets 2017 jun N(94, 93) 93.98653
ets 2017 jul N(99, 112) 99.35384
ets 2017 ago N(99, 119) 98.65441
ets 2017 set N(96, 120) 95.52819
ets 2017 out N(100, 141) 99.96450
ets 2017 nov N(96, 138) 95.63583
ets 2017 dez N(125, 252) 125.08358
ets 2018 jan N(93, 148) 92.93321
ets 2018 fev N(87, 138) 86.87680
ets 2018 mar N(96, 177) 95.81939
ets 2018 abr N(95, 186) 95.31834
ets 2018 mai N(101, 221) 101.10854
ets 2018 jun N(94, 203) 94.27956
ets 2018 jul N(100, 239) 99.65732
ets 2018 ago N(99, 248) 98.94964
ets 2018 set N(96, 244) 95.80826
ets 2018 out N(100, 280) 100.25164
ets 2018 nov N(96, 269) 95.90497
ets 2018 dez N(125, 482) 125.42845
ets 2019 jan N(93, 278) 93.18426
ets 2019 fev N(87, 254) 87.10674
ets 2019 mar N(96, 322) 96.06785
ets 2019 abr N(96, 333) 95.56050
ets 2019 mai N(101, 390) 101.36021
ets 2019 jun N(95, 353) 94.50949
ets 2019 jul N(100, 410) 99.89545
ets 2019 ago N(99, 420) 99.18130
ets 2019 set N(96, 408) 96.02803
ets 2019 out N(100, 464) 100.47695
ets 2019 nov N(96, 440) 96.11616
ets 2019 dez N(126, 780) 125.69907
ets 2020 jan N(93, 445) 93.38125
ets 2020 fev N(87, 403) 87.28716
ets 2020 mar N(96, 506) 96.26282
ets 2020 abr N(96, 517) 95.75053
ets 2020 mai N(102, 601) 101.55770
ets 2020 jun N(95, 539) 94.68991
ets 2020 jul N(100, 621) 100.08230
ets 2020 ago N(99, 631) 99.36307
ets 2020 set N(96, 610) 96.20048
ets 2020 out N(101, 687) 100.65375
ets 2020 nov N(96, 647) 96.28187
ets 2020 dez N(126, 1139) 125.91142
ets 2021 jan N(94, 646) 93.53582
prophet 2016 fev sample[5000] 99.77158
prophet 2016 mar sample[5000] 105.11582
prophet 2016 abr sample[5000] 103.72635
prophet 2016 mai sample[5000] 106.33587
prophet 2016 jun sample[5000] 104.05516
prophet 2016 jul sample[5000] 107.03838
prophet 2016 ago sample[5000] 107.34808
prophet 2016 set sample[5000] 107.33653
prophet 2016 out sample[5000] 109.09485
prophet 2016 nov sample[5000] 107.89183
prophet 2016 dez sample[5000] 126.23596
prophet 2017 jan sample[5000] 107.41729
prophet 2017 fev sample[5000] 102.78844
prophet 2017 mar sample[5000] 109.61882
prophet 2017 abr sample[5000] 108.69957
prophet 2017 mai sample[5000] 112.43162
prophet 2017 jun sample[5000] 109.90084
prophet 2017 jul sample[5000] 111.99271
prophet 2017 ago sample[5000] 112.58689
prophet 2017 set sample[5000] 110.80788
prophet 2017 out sample[5000] 113.83105
prophet 2017 nov sample[5000] 112.59431
prophet 2017 dez sample[5000] 130.70736
prophet 2018 jan sample[5000] 112.21857
prophet 2018 fev sample[5000] 109.39407
prophet 2018 mar sample[5000] 114.98214
prophet 2018 abr sample[5000] 113.18705
prophet 2018 mai sample[5000] 118.29887
prophet 2018 jun sample[5000] 113.44539
prophet 2018 jul sample[5000] 116.61454
prophet 2018 ago sample[5000] 117.41319
prophet 2018 set sample[5000] 115.77331
prophet 2018 out sample[5000] 119.28197
prophet 2018 nov sample[5000] 118.47303
prophet 2018 dez sample[5000] 136.49114
prophet 2019 jan sample[5000] 116.34167
prophet 2019 fev sample[5000] 113.76797
prophet 2019 mar sample[5000] 118.30602
prophet 2019 abr sample[5000] 118.56503
prophet 2019 mai sample[5000] 123.59568
prophet 2019 jun sample[5000] 118.42640
prophet 2019 jul sample[5000] 122.08162
prophet 2019 ago sample[5000] 123.41656
prophet 2019 set sample[5000] 120.30146
prophet 2019 out sample[5000] 124.63048
prophet 2019 nov sample[5000] 122.09866
prophet 2019 dez sample[5000] 141.83332
prophet 2020 jan sample[5000] 120.21571
prophet 2020 fev sample[5000] 119.51366
prophet 2020 mar sample[5000] 124.30931
prophet 2020 abr sample[5000] 124.11260
prophet 2020 mai sample[5000] 126.78279
prophet 2020 jun sample[5000] 124.04927
prophet 2020 jul sample[5000] 127.55469
prophet 2020 ago sample[5000] 127.09183
prophet 2020 set sample[5000] 126.65924
prophet 2020 out sample[5000] 130.28742
prophet 2020 nov sample[5000] 126.98120
prophet 2020 dez sample[5000] 145.54408
prophet 2021 jan sample[5000] 127.82523

Lembrar que usamos dados apenas até Jan/2020 na série original. Se usar a série atualizada até agora, você terá mais observações que as 241 iniciais.

Para não acharmos que o fable.prophet é ruim, e desencargo de consciência, farei a estimação e forecast com o fable.prophet para fora da amostra e usando a série toda.

4 Estimação com série toda

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é abr/2021 256 observações mensais
varejoms.all <- BETSget(1479, from = "2000-01-01", data.frame = TRUE, frequency = 12)
library(tsibble)
library(tsibbledata)
library(lubridate)
library(dplyr)
library(tidyverse)

mth2 <- make_date("2000") + months(0:255)
dados2 <- cbind(varejoms.all[-1], time2 = yearmonth(mth2))
varejo.all.tsb <- tsibble(dados2, index = time2) %>%
    print()
FALSE # A tsibble: 256 x 2 [1M]
FALSE    value    time2
FALSE    <dbl>    <mth>
FALSE  1  35.2 2000 jan
FALSE  2  35.6 2000 fev
FALSE  3  39.2 2000 mar
FALSE  4  40.5 2000 abr
FALSE  5  41.6 2000 mai
FALSE  6  40.4 2000 jun
FALSE  7  40.8 2000 jul
FALSE  8  38.7 2000 ago
FALSE  9  37.3 2000 set
FALSE 10  37.6 2000 out
FALSE # ... with 246 more rows
autoplot(varejo.all.tsb)

library(fable.prophet)
library(fable)
library(fpp3)
fit3 <- varejo.all.tsb %>%
    model(prophet = prophet(value))
fc3 <- fit3 %>%
    forecast(h = 12)
fc3 %>%
    autoplot(varejo.all.tsb)

print(fc3)
FALSE # A fable: 12 x 4 [1M]
FALSE # Key:     .model [1]
FALSE    .model     time2        value .mean
FALSE    <chr>      <mth>       <dist> <dbl>
FALSE  1 prophet 2021 mai sample[5000]  96.4
FALSE  2 prophet 2021 jun sample[5000]  94.1
FALSE  3 prophet 2021 jul sample[5000]  97.5
FALSE  4 prophet 2021 ago sample[5000]  96.2
FALSE  5 prophet 2021 set sample[5000]  94.9
FALSE  6 prophet 2021 out sample[5000]  98.4
FALSE  7 prophet 2021 nov sample[5000]  97.0
FALSE  8 prophet 2021 dez sample[5000] 115. 
FALSE  9 prophet 2022 jan sample[5000]  94.4
FALSE 10 prophet 2022 fev sample[5000]  90.8
FALSE 11 prophet 2022 mar sample[5000]  96.1
FALSE 12 prophet 2022 abr sample[5000]  93.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.

FIGUEIREDO, Adriano Marcos Rodrigues. Séries Temporais com R: Análise do Consumo do Varejo em MS com fable e feasts. Campo Grande-MS,Brasil: RStudio/Rpubs, 2021. Disponível em http://rpubs.com/amrofi/fable_feasts_varejoms.

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. (2019). fpp3: Data for “Forecasting: Principles and Practice” (3rd Edition). R package. Disponível em: https://github.com/robjhyndman/fpp3-package, https://OTexts.org/fpp3/.

HYNDMAN, R.J.; ATHANASOPOULOS, G. (2020) Forecasting: principles and practice, 3rd edition, OTexts: Melbourne, Australia. Disponível em: https://otexts.com/fpp3/. Accessed on 02 Apr 2020.

O’HARA-WILD, Mitchell; TAYLOR, Sean; LETHAM, Ben (NA). fable.prophet: Prophet Modelling Interface for ‘fable’. R package version 0.1.0.9000. Available at: https://pkg.mitchelloharawild.com/fable.prophet/.

LS0tDQp0aXRsZTogIlPDqXJpZXMgVGVtcG9yYWlzIGNvbSBSOiBBbsOhbGlzZSBkbyBDb25zdW1vIGRvIFZhcmVqbyBlbSBNUyBjb20gYGZhYmxlLnByb3BoZXRgIg0KYXV0aG9yOiAiQWRyaWFubyBNYXJjb3MgUm9kcmlndWVzIEZpZ3VlaXJlZG8sICplLW1haWw6IGFkcmlhbm8uZmlndWVpcmVkb0B1Zm1zLmJyKiINCmxpbmtjb2xvcjogYmx1ZQ0KYWJzdHJhY3Q6IA0KICBUaGlzIGlzIGFuIGV4ZXJjaXNlIGZvciBjbGFzcyB1c2UuIFdlIGFuYWx5c2UgZGF0YSBvbiBSZXRhaWwgY29uc3VtcHRpb24sIGZyb20gSmFudWFyeS8yMDAwIHRvIG5vd2FkYXlzLiANCmRhdGU6ICJgciBmb3JtYXQoU3lzLkRhdGUoKSwgJyVkICVCICVZJylgIg0Kb3V0cHV0Og0KICBodG1sX2RvY3VtZW50Og0KICAgIGNvZGVfZG93bmxvYWQ6IHRydWUNCiAgICB0aGVtZTogZGVmYXVsdA0KICAgIG51bWJlcl9zZWN0aW9uczogdHJ1ZQ0KICAgIHRvYzogeWVzDQogICAgdG9jX2Zsb2F0OiBubw0KICAgIGRmX3ByaW50OiBwYWdlZA0KICAgIGZpZ19jYXB0aW9uOiB0cnVlDQogIHBkZl9kb2N1bWVudDoNCiAgICB0b2M6IHllcw0KYWx3YXlzX2FsbG93X2h0bWw6IHRydWUNCi0tLQ0KDQpgYGB7ciBrbml0cl9pbml0LCBlY2hvPUZBTFNFLCBjYWNoZT1GQUxTRX0NCmxpYnJhcnkoa25pdHIpDQpsaWJyYXJ5KHJtYXJrZG93bikNCmxpYnJhcnkocm1kZm9ybWF0cykNCnNldC5zZWVkKDEpDQojIyBHbG9iYWwgb3B0aW9ucw0Kb3B0aW9ucyhtYXgucHJpbnQ9IjEwMCIpDQpvcHRzX2NodW5rJHNldChlY2hvPVRSVUUsDQoJICAgICAgICAgICAgIGNhY2hlPVRSVUUsDQogICAgICAgICAgICAgICBwcm9tcHQ9RkFMU0UsDQogICAgICAgICAgICAgICB0aWR5PVRSVUUsDQogICAgICAgICAgICAgICBjb21tZW50PU5BLA0KICAgICAgICAgICAgICAgbWVzc2FnZT1GQUxTRSwNCiAgICAgICAgICAgICAgIHdhcm5pbmc9RkFMU0UpDQpvcHRzX2tuaXQkc2V0KHdpZHRoPTEwMCkNCmBgYA0KDQojIExpY2Vuw6dhIHsjTGljZW7Dp2EgLnVubnVtYmVyZWR9DQoNClRoaXMgd29yayBpcyBsaWNlbnNlZCB1bmRlciB0aGUgQ3JlYXRpdmUgQ29tbW9ucyBBdHRyaWJ1dGlvbi1TaGFyZUFsaWtlIDQuMCBJbnRlcm5hdGlvbmFsIExpY2Vuc2UuIFRvIHZpZXcgYSBjb3B5IG9mIHRoaXMgbGljZW5zZSwgdmlzaXQgPGh0dHA6Ly9jcmVhdGl2ZWNvbW1vbnMub3JnL2xpY2Vuc2VzL2J5LXNhLzQuMC8+IG9yIHNlbmQgYSBsZXR0ZXIgdG8gQ3JlYXRpdmUgQ29tbW9ucywgUE8gQm94IDE4NjYsIE1vdW50YWluIFZpZXcsIENBIDk0MDQyLCBVU0EuDQoNCiFbTGljZW5zZTogQ0MgQlktU0EgNC4wXShjY19ieV9zYS5wbmcpe3dpZHRoPSIyNSUifQ0KDQojIENpdGHDp8OjbyB7I0NpdGHDp8OjbyAudW5udW1iZXJlZH0NCg0KU3VnZXN0w6NvIGRlIGNpdGHDp8OjbzogRklHVUVJUkVETywgQWRyaWFubyBNYXJjb3MgUm9kcmlndWVzLiBTw6lyaWVzIFRlbXBvcmFpcyBjb20gUjogQW7DoWxpc2UgZG8gQ29uc3VtbyBkbyBWYXJlam8gZW0gTVMgY29tIGBmYWJsZS5wcm9waGV0YC4gQ2FtcG8gR3JhbmRlLU1TLEJyYXNpbDogUlN0dWRpby9ScHVicywgMjAyMS4gRGlzcG9uw612ZWwgZW0gPGh0dHA6Ly9ycHVicy5jb20vYW1yb2ZpL2ZhYmxlcHJvcGhldF92YXJlam9tcz4uDQoNCiMgSW50cm9kdcOnw6NvDQoNCk5lc3RlIGFycXVpdm8gdXRpbGl6byBhIHPDqXJpZSBkbyDDjW5kaWNlIGRlIHZvbHVtZSBkZSB2ZW5kYXMgbm8gdmFyZWpvIFRvdGFsIGRlIE1hdG8gR3Jvc3NvIGRvIFN1bCwgc8OpcmllIG1lbnNhbCBhIHBhcnRpciBkZSBqYW4vMjAwMCBhdMOpIGphbi8yMDIwIG9idGlkYSBjb20gbyBwYWNvdGUgYEJFVFNgIGUgaW1wb3J0YWRhIGRvIEJhbmNvIENlbnRyYWwgZG8gQnJhc2lsLiBQb3J0YW50bywgc8OjbyAyNDEgb2JzZXJ2YcOnw7VlcyBtZW5zYWlzLg0KDQpSZWFsaXphcmVtb3Mgb3MgbW9kZWxvcyBFVFMgKEVycm9yIFRyZW5kIFNlYXNvbmFsKSBjb25mb3JtZSBIeW5kbWFuIGUgQXRoYW5hc29wb3Vsb3MgKDIwMjEsMjAxOCksIGNvbSBgZmFibGVgIGUgYGZlYXN0c2AsIGUgRmFjZWJvb2sgUHJvcGhldCBvdSBzZWphLCBjb20gbyBmb3JtYXRvIGB0c2liYmxlYCBwZWxvIGBmYWJsZS5wcm9waGV0YC4NCg0KU3VnaXJvIG9saGFyIG1ldXMgdmlkZW9zIG5vIFlvdXR1YmUgZW06IEFwbGljYcOnw6NvIGRlIEVUUyBjb20gYcOnw7VlczogPGh0dHBzOi8veW91dHUuYmUvczVTNDNRQmxsUjA+OyBWaWRlbyB0ZcOzcmljbyBkZSBFVFM6IDxodHRwczovL3lvdXR1LmJlL2VqOGhINmc5ajNZPi4NCg0KU29icmUgbyBGYWNlYm9vayBQcm9waGV0IHRlbW9zOiBGYWNlYm9vayBQcm9waGV0IHBhcmEgcHJldmlzw6NvIGRlIHPDqXJpZXMgdGVtcG9yYWlzIC0gbWFpcyB0ZcOzcmljbyAtICg8aHR0cHM6Ly95b3V0dS5iZS85bkFScE5vMXY1dz4pIGUgRmFjZWJvb2sgUHJvcGhldCAtIGFwbGljYcOnw6NvIHBhcmEgYml0Y29pbiBlIHBhcmEgTEFNRTQgLSB0aW1lIHNlcmllcyAoPGh0dHBzOi8veW91dHUuYmUvTEVOTHcwRWFnUmc+KS4NCg0KIyBEYWRvcw0KDQpPIGxlaXRvciBwb2RlIGNhcnJlZ2FyIG9zIGRhZG9zIGRpcmV0byBkbyBzaXRlIGRvIEJhbmNvIENlbnRyYWwgZG8gQnJhc2lsIGNvbSBvIHBhY290ZSBgQkVUU2AgKEZFUlJFSVJBLCBTUEVSQU5aQSBlIENPU1RBLCAyMDE4KSBjb25mb3JtZSBjb2RlIGFiYWl4byAobsOjbyByb2RlaSBhcXVpKSBlbSBkYXRhLmZyYW1lLg0KDQpFdSBnZXJlaSBhIGVzdHJ1dHVyYSBpZMOqbnRpY2EgcGVsYSBmdW7Dp8OjbyBgZHB1dCgpYCBwYXJhIG9zIGxlaXRvcmVzIHF1ZSBuw6NvIGNvbnNlZ3VpcmVtIHBvciBxdWFscXVlciBtb3Rpdm8gbyBhY2Vzc28gYW8gc2l0ZSBkbyBCYW5jbyBDZW50cmFsIChhcyB2ZXplcyB2ZWpvIGlzc28gb2NvcnJlciBkZXBlbmRlbmRvIGRvcyBibG9xdWVpb3MgZGEgc3VhIHJlZGUgZGUgaW50ZXJuZXQpLiBFc2NsYXJlw6dvIGFvIGxlaXRvciBxdWUgYXDDs3MgYmFpeGFyIGEgc8OpcmllIHBlbG8gQkVUUywgZml6IG8gZHB1dCBlIGEgcGFydGlyIGRlIGVudMOjbywgZGVzYWJpbGl0ZWkgbyBibG9jbyAoYENodW5rYCkgcXVlIGFjZXNzYSBvIEJFVFMgYXBlbmFzIHBhcmEgYWdpbGl6YXIgb3MgY8OhbGN1bG9zLg0KDQogICAgbGlicmFyeShCRVRTKQ0KICAgICMgUGVnYW5kbyBhcyBzw6lyaWVzIGEgcGFydGlyIGRvIHNpdGUgZG8gQmFuY28gQ2VudHJhbCBkbyBCcmFzaWwNCiAgICAjIMONbmRpY2UgZGUgdm9sdW1lIGRlIHZlbmRhcyBubyB2YXJlam8gVG90YWwgZGUgTWF0byBHcm9zc28gZG8gU3VsDQogICAgIyBtZW5zYWwgYSBwYXJ0aXIgZGUgamFuLzIwMDAgYXTDqSBqYW4vMjAyMCAgDQogICAgIyAyNDEgb2JzZXJ2YcOnw7VlcyBtZW5zYWlzDQogICAgdmFyZWpvbXMgPC0gQkVUU2dldCgxNDc5LGZyb209IjIwMDAtMDEtMDEiLHRvPSIyMDIwLTAxLTMxIiwNCiAgICAgICAgICAgICAgICAgIGRhdGEuZnJhbWUgPSBUUlVFLGZyZXF1ZW5jeSA9IDEyKSANCiAgICBwcmludCh2YXJlam9tcykNCiAgICBjbGFzcyh2YXJlam9tcykNCiAgICBkcHV0KHZhcmVqb21zKSAgIyBvcMOnw6NvIHBhcmEgdGVyIG9zIGRhZG9zIGNvbW8gbmEgc3RydWN0dXJlIGFiYWl4bw0KDQpgYGB7ciwgd2FybmluZz1GQUxTRSwgY29tbWVudD1GQUxTRX0NCiMgUGVnYW5kbyBhcyBzw6lyaWVzIGEgcGFydGlyIGRvIHNpdGUgZG8gQmFuY28gQ2VudHJhbCBkbyBCcmFzaWwNCiMgw41uZGljZSBkZSB2b2x1bWUgZGUgdmVuZGFzIG5vIHZhcmVqbyBUb3RhbCBkZSBNYXRvIEdyb3NzbyBkbyBTdWwNCiMgbWVuc2FsIGEgcGFydGlyIGRlIGphbi8yMDAwIGF0w6kgamFuLzIwMjAgIA0KDQojbGlicmFyeShCRVRTKQ0KdmFyZWpvbXM8LSBzdHJ1Y3R1cmUobGlzdChkYXRlID0gc3RydWN0dXJlKGMoMTA5NTcsIDEwOTg4LCAxMTAxNywgMTEwNDgsIA0KMTEwNzgsIDExMTA5LCAxMTEzOSwgMTExNzAsIDExMjAxLCAxMTIzMSwgMTEyNjIsIDExMjkyLCAxMTMyMywgDQoxMTM1NCwgMTEzODIsIDExNDEzLCAxMTQ0MywgMTE0NzQsIDExNTA0LCAxMTUzNSwgMTE1NjYsIDExNTk2LCANCjExNjI3LCAxMTY1NywgMTE2ODgsIDExNzE5LCAxMTc0NywgMTE3NzgsIDExODA4LCAxMTgzOSwgMTE4NjksIA0KMTE5MDAsIDExOTMxLCAxMTk2MSwgMTE5OTIsIDEyMDIyLCAxMjA1MywgMTIwODQsIDEyMTEyLCAxMjE0MywgDQoxMjE3MywgMTIyMDQsIDEyMjM0LCAxMjI2NSwgMTIyOTYsIDEyMzI2LCAxMjM1NywgMTIzODcsIDEyNDE4LCANCjEyNDQ5LCAxMjQ3OCwgMTI1MDksIDEyNTM5LCAxMjU3MCwgMTI2MDAsIDEyNjMxLCAxMjY2MiwgMTI2OTIsIA0KMTI3MjMsIDEyNzUzLCAxMjc4NCwgMTI4MTUsIDEyODQzLCAxMjg3NCwgMTI5MDQsIDEyOTM1LCAxMjk2NSwgDQoxMjk5NiwgMTMwMjcsIDEzMDU3LCAxMzA4OCwgMTMxMTgsIDEzMTQ5LCAxMzE4MCwgMTMyMDgsIDEzMjM5LCANCjEzMjY5LCAxMzMwMCwgMTMzMzAsIDEzMzYxLCAxMzM5MiwgMTM0MjIsIDEzNDUzLCAxMzQ4MywgMTM1MTQsIA0KMTM1NDUsIDEzNTczLCAxMzYwNCwgMTM2MzQsIDEzNjY1LCAxMzY5NSwgMTM3MjYsIDEzNzU3LCAxMzc4NywgDQoxMzgxOCwgMTM4NDgsIDEzODc5LCAxMzkxMCwgMTM5MzksIDEzOTcwLCAxNDAwMCwgMTQwMzEsIDE0MDYxLCANCjE0MDkyLCAxNDEyMywgMTQxNTMsIDE0MTg0LCAxNDIxNCwgMTQyNDUsIDE0Mjc2LCAxNDMwNCwgMTQzMzUsIA0KMTQzNjUsIDE0Mzk2LCAxNDQyNiwgMTQ0NTcsIDE0NDg4LCAxNDUxOCwgMTQ1NDksIDE0NTc5LCAxNDYxMCwgDQoxNDY0MSwgMTQ2NjksIDE0NzAwLCAxNDczMCwgMTQ3NjEsIDE0NzkxLCAxNDgyMiwgMTQ4NTMsIDE0ODgzLCANCjE0OTE0LCAxNDk0NCwgMTQ5NzUsIDE1MDA2LCAxNTAzNCwgMTUwNjUsIDE1MDk1LCAxNTEyNiwgMTUxNTYsIA0KMTUxODcsIDE1MjE4LCAxNTI0OCwgMTUyNzksIDE1MzA5LCAxNTM0MCwgMTUzNzEsIDE1NDAwLCAxNTQzMSwgDQoxNTQ2MSwgMTU0OTIsIDE1NTIyLCAxNTU1MywgMTU1ODQsIDE1NjE0LCAxNTY0NSwgMTU2NzUsIDE1NzA2LCANCjE1NzM3LCAxNTc2NSwgMTU3OTYsIDE1ODI2LCAxNTg1NywgMTU4ODcsIDE1OTE4LCAxNTk0OSwgMTU5NzksIA0KMTYwMTAsIDE2MDQwLCAxNjA3MSwgMTYxMDIsIDE2MTMwLCAxNjE2MSwgMTYxOTEsIDE2MjIyLCAxNjI1MiwgDQoxNjI4MywgMTYzMTQsIDE2MzQ0LCAxNjM3NSwgMTY0MDUsIDE2NDM2LCAxNjQ2NywgMTY0OTUsIDE2NTI2LCANCjE2NTU2LCAxNjU4NywgMTY2MTcsIDE2NjQ4LCAxNjY3OSwgMTY3MDksIDE2NzQwLCAxNjc3MCwgMTY4MDEsIA0KMTY4MzIsIDE2ODYxLCAxNjg5MiwgMTY5MjIsIDE2OTUzLCAxNjk4MywgMTcwMTQsIDE3MDQ1LCAxNzA3NSwgDQoxNzEwNiwgMTcxMzYsIDE3MTY3LCAxNzE5OCwgMTcyMjYsIDE3MjU3LCAxNzI4NywgMTczMTgsIDE3MzQ4LCANCjE3Mzc5LCAxNzQxMCwgMTc0NDAsIDE3NDcxLCAxNzUwMSwgMTc1MzIsIDE3NTYzLCAxNzU5MSwgMTc2MjIsIA0KMTc2NTIsIDE3NjgzLCAxNzcxMywgMTc3NDQsIDE3Nzc1LCAxNzgwNSwgMTc4MzYsIDE3ODY2LCAxNzg5NywgDQoxNzkyOCwgMTc5NTYsIDE3OTg3LCAxODAxNywgMTgwNDgsIDE4MDc4LCAxODEwOSwgMTgxNDAsIDE4MTcwLCANCjE4MjAxLCAxODIzMSwgMTgyNjIpLCBjbGFzcyA9ICJEYXRlIiksIHZhbHVlID0gYygzNS4yLCAzNS42LCANCjM5LjIsIDQwLjUsIDQxLjYsIDQwLjQsIDQwLjgsIDM4LjcsIDM3LjMsIDM3LjYsIDM1LjYsIDQ3LjQsIDM0LjIsIA0KMzIuMiwgMzgsIDM3LjUsIDM4LjgsIDM1LCAzOC40LCA0MC4yLCAzOC4yLCAzOS4zLCAzNiwgNDYuMywgMzYuNCwgDQozNCwgMzksIDM3LjgsIDM4LjksIDM1LjMsIDM3LjIsIDM4LjEsIDM1LjYsIDM4LjMsIDM1LjYsIDQ1LjcsIA0KMzIuMiwgMzEuNiwgMzUuMiwgMzYuOCwgMzcuNSwgMzQuOCwgMzguNCwgMzguMSwgMzcsIDM5LCAzNy4zLCANCjQ5LCAzNS44LCAzNS4zLCA0MC4yLCA0MS4zLCA0My45LCA0MS42LCA0NS45LCA0Mi4zLCA0Mi4yLCA0NCwgDQo0MS4zLCA1Ni45LCAzOC41LCAzOC41LCA0NS4zLCA0My42LCA0Ni4yLCA0NC4zLCA0Ny41LCA0Ni41LCA0Ni40LCANCjQ2LCA0NC4xLCA2MSwgNDIsIDQwLjIsIDQ0LjYsIDQ0LjUsIDQ3LjgsIDQ1LjMsIDQ2LjUsIDQ4LjUsIDQ3LjcsIA0KNTAuMiwgNDkuMywgNjQuNSwgNDcsIDQ2LjgsIDUxLCA1MC41LCA1NSwgNTEuMywgNTIuOCwgNTUuMywgNTQuOCwgDQo1NS42LCA1NS4zLCA3Mi4yLCA1NC41LCA1Mi4xLCA1Ni4yLCA1Ny4yLCA2MC44LCA1Ni4xLCA2MS44LCA2MS42LCANCjU5LjgsIDYzLjMsIDU3LjcsIDc3LjQsIDYxLjQsIDUxLjksIDU3LjMsIDU3LjksIDYxLjksIDU3LjMsIDYxLjEsIA0KNjEuMSwgNjAuNiwgNjUuNiwgNjMuNSwgODMuMSwgNjQuMSwgNjAuMiwgNjcuOCwgNjcuMSwgNzIuOCwgNjguNSwgDQo3MS4xLCA2OS4zLCA2OS45LCA3MS4xLCA2Ny45LCA5Mi43LCA2Ny41LCA2NC44LCA2OS4xLCA2OS40LCA3OS42LCANCjcwLjIsIDczLjgsIDcyLjUsIDcxLjMsIDc1LjYsIDc0LjcsIDEwMC44LCA3OS41LCA3NS43LCA4Mi40LCANCjc4LCA4NC44LCA4My4yLCA4NC44LCA4OC41LCA4Ni4zLCA5MS43LCA5Mi44LCAxMTEuNCwgOTIuOCwgODMuNywgDQo5Mi41LCA4OC4zLCA5My45LCA4OC44LCA5NiwgOTUuOSwgOTMuMiwgOTguMywgMTAwLjUsIDEyOC44LCA5Ny4yLCANCjkwLjIsIDk0LjMsIDk0LjQsIDEwMS4xLCA5MiwgOTYuNCwgOTguMiwgOTcuNiwgMTA1LjgsIDEwMy4xLCANCjEyOS42LCA5OS42LCA4Ny44LCA5NywgOTQuOCwgOTguNiwgOTMuNCwgOTguNCwgOTYuNCwgOTIuNSwgMTAwLjYsIA0KOTcuMiwgMTI0LjUsIDkxLjUsIDg1LjEsIDkxLjYsIDg4LjUsIDkyLjIsIDg3LjQsIDkwLjUsIDg4LjEsIA0KODUuMiwgODkuNCwgOTMuNCwgMTE2LjksIDkwLjgsIDg0LCA4OS43LCA4Ni4zLCA5MCwgODcuMywgOTAuOCwgDQo5My41LCA5My43LCA5MS40LCA5My41LCAxMTQuMSwgODcuOCwgODEuMSwgOTQuNSwgODMuMiwgODkuOSwgDQo4OC44LCA4OS4zLCA5My43LCA5My41LCA5Ni4zLCAxMDEuMywgMTE4LjMsIDkzLjgsIDg1LjIsIDkwLCA4Ni42LCANCjkwLCA4NS4yLCA5MSwgOTQuNCwgOTMuNCwgOTUuOSwgMTAyLjYsIDExNiwgOTQuOSkpLCANCmNsYXNzID0gImRhdGEuZnJhbWUiLCByb3cubmFtZXMgPSBjKE5BLC0yNDFMKSkNCmNsYXNzKHZhcmVqb21zKQ0KYGBgDQoNCkEgcm90aW5hIGRlIGRhZG9zIG9idGlkb3MgcGVsbyBCRVRTIGrDoSByZXRvcm5hIGEgc8OpcmllIGVtIGZvcm1hdG8gYGRhdGEuZnJhbWVgLCBvdSBzZWphLCBjb20gYXMgY29sdW5hcyBkYXRlIGUgdmFsdWUuIEFsZ3VtYXMgYW7DoWxpc2VzIGV1IGlnbm9yYXJlaSBwb3JxdWUgasOhIGFzIGZpeiBlbSBvdXRyb3MgcG9zdHMgKEZJR1VFSVJFRE8sIDIwMjEpLg0KDQpQcmVjaXNhbW9zIHJlaW5kZXhhciBhIHPDqXJpZSBwYXJhIHF1ZSBlbGUgZW50ZW5kYSBjb21vIG1lbnNhbCAobW9udGhseSkuDQoNCiMgQW7DoWxpc2UgZGEgc8OpcmllDQoNCkZhcmVpIGEgZGl2aXPDo28gZW50cmUgYW1vc3RyYSB0ZXN0ZSBlIGFtb3N0cmEgdHJlaW5vIHBhcmEgY29udHJvbGUgZGUgYWN1csOhY2lhLCBwZWxvIHRyYWRpY2lvbmFsIDgwLTIwICgyNDEgb2JzZXJ2YcOnw7VlcyB4IDgwJSA9IDE5MyBwYXJhIHRyZWlubyksIHBvcnRhbnRvIGEgYW1vc3RyYSB0cmVpbm8gc2Vyw6EgZGUgamFuLTIwMDAgYSBqYW4tMjAxNi4gTyBsZWl0b3IgZGV2ZSBlbSBnZXJhbCBmYXplciBlc3RhcyBkaXZpc8O1ZXMgcGFyYSBjZXJ0aWZpY2FyIGRlIHF1ZSBvIG1vZGVsbyDDqSB1bSBib20gcHJlZGl0b3IuIFVtYSBhbsOhbGlzZSBtYWlzIGRldGFsaGFkYSBkYSBzw6lyaWUgcG9kZSBzZXIgZmVpdGEgZmF6ZW5kbyBvIGNodW5rIGFiYWl4by4NCg0KIyMgRXN0aW1hw6fDo28gY29tIGBmYWJsZWAgZSBgZmVhc3RzYA0KDQpQcmltZWlybyBmYXJlbW9zIGEgY29udmVyc8OjbyBkZSBvYmpldG8gYHRzYCBwYXJhIGB0c2liYmxlYCwgb3UgKnRpbWUgc2VyaWVzIHRhYmxlKi4gQ29udmVydGVyZWkgYSBzw6lyaWUgaW50ZWlyYSB2YXJlam9tcyBlIGRlcG9pcyBmYXJlaSBvIHNwbGl0IGVudHJlIHRyYWluIGUgdGVzdC4NCg0KYGBge3IgZmFibGUsIG1lc3NhZ2U9RkFMU0Usd2FybmluZz1GQUxTRX0NCg0KbGlicmFyeSh0c2liYmxlKQ0KbGlicmFyeSh0c2liYmxlZGF0YSkNCmxpYnJhcnkobHVicmlkYXRlKQ0KbGlicmFyeShkcGx5cik7bGlicmFyeSh0aWR5dmVyc2UpDQoNCnZhcmVqby50c2I8LXZhcmVqb21zICU+JSBhc190c2liYmxlKCkNCmF1dG9wbG90KHZhcmVqby50c2IpDQpgYGANCg0KUHJlY2lzYW1vcyByZWluZGV4YXIgYSBzw6lyaWUgcGFyYSBxdWUgZWxlIGVudGVuZGEgY29tbyBtZW5zYWwgKG1vbnRobHkpLiBObyBwbG90LCBwb2RlIHBlcmNlYmVyIHF1ZSBlc3TDoSBjb21vIGRhdGVbMURdLCBvdSBzZWphLCBkacOhcmlhLiBTZSBuw6NvIGNvcnJpZ2lyLCBvIGZvcmVjYXN0IHNlcsOhIGRpw6FyaW8hIE8gbGVpdG9yIHBvZGUgY29uc3VsdGFyIG1lbGhvciBlbSA8aHR0cHM6Ly9jcmFuLnItcHJvamVjdC5vcmcvd2ViL3BhY2thZ2VzL3RzaWJibGUvdmlnbmV0dGVzL2ZhcS5odG1sPi4NCg0KdHNpYmJsZShtdGggPSB5ZWFybW9udGgobXRoKSwgaW5kZXggPSBtdGgpDQoNCmBgYHtyfQ0KbXRoIDwtIG1ha2VfZGF0ZSgiMjAwMCIpICsgbW9udGhzKDA6MjQwKQ0KZGFkb3M8LWNiaW5kKHZhcmVqb21zWy0xXSx0aW1lPXllYXJtb250aChtdGgpKQ0KdmFyZWpvLnRzYiA8LSB0c2liYmxlKGRhZG9zLA0KICBpbmRleCA9IHRpbWUpICU+JSANCiAgcHJpbnQoKQ0KYXV0b3Bsb3QodmFyZWpvLnRzYikNCmBgYA0KDQpBZ29yYSBzaW0sIG8gb2JqZXRvIHRzaWJibGUgZW50ZW5kZSBjb21vIHPDqXJpZSBtZW5zYWwuDQoNCkZhcmVtb3MgbyBzcGxpdCBjb20gdXNvIGRhIGZ1bsOnw6NvIGBmaWx0ZXJfaW5kZXhgIGUgZXNwZWNpZmljYW5kbyBgZmlsdGVyX2luZGV4KH4gIjIwMTYtMDEiKWA6DQoNCmBgYHtyIHNwbGl0c2VyaWVzfQ0KdHJhaW4gPC0gdmFyZWpvLnRzYiAlPiUNCiAgZmlsdGVyX2luZGV4KH4gIjIwMTYtMDEiKQ0KdHJhaW4NCmg9bGVuZ3RoKHZhcmVqby50c2IkdmFsdWUpLWxlbmd0aCh0cmFpbiR2YWx1ZSkNCmgNCmBgYA0KDQpQb2RlbW9zIHBsb3RhciBlIGVzdGltYXIuDQoNCmBgYHtyfQ0KYXV0b3Bsb3QodHJhaW4pDQpgYGANCg0KQSBmdW7Dp8OjbyBgcmVwb3J0YCBmb3JuZWNlcsOhIGEgc2HDrWRhIGRvIG1vZGVsby4NCg0KYGBge3IgdHNpYmJsZV9vYmplY3R9DQpsaWJyYXJ5KGZhYmxlLnByb3BoZXQpO2xpYnJhcnkoZmFibGUpDQpsaWJyYXJ5KGZwcDMpDQpmaXQxIDwtIHRyYWluICU+JSBtb2RlbChhcmltYSA9IEFSSU1BKHZhbHVlKSwgZXRzID0gRVRTKHZhbHVlKSwgcHJvcGhldCA9IHByb3BoZXQodmFsdWUpKSANCmZjMSA8LSBmaXQxICU+JSBmb3JlY2FzdChoID0gaCkNCmZjMSAlPiUgYXV0b3Bsb3QodmFyZWpvLnRzYikNCnJlcG9ydChmaXQxKQ0KYGBgDQoNCkFnb3JhIG8gZm9yZWNhc3Qgw6AgZnJlbnRlIDYwIG1lc2VzLiBDb2xvcXVlaSA0OCBtZXNlcyBkbyB0cmVpbm8gbWFpcyAxMiBtZXNlcyBmb3JhIGRhIHPDqXJpZSBvYnNlcnZhZGEuDQoNCmBgYHtyfQ0KZmMyIDwtIGZpdDEgJT4lIGZvcmVjYXN0KGggPSAiNSB5ZWFycyIpDQpmYzINCmBgYA0KDQpFIGEgYWN1csOhY2lhIGRhIHBhcnRlIGRlIHRlc3RlIGZvaToNCg0KYGBge3J9DQpmYzEgJT4lDQogIGFjY3VyYWN5KHZhcmVqby50c2IsDQogICAgbWVhc3VyZXMgPSBwb2ludF9hY2N1cmFjeV9tZWFzdXJlcw0KICApDQpgYGANCg0KU2VndWUgbyBwbG90IGRhIHNlZ3VuZGEgZXN0aW1hw6fDo28gKGg9NjApOg0KDQpgYGB7ciBwbG90ZmVhc3RzfQ0KZmMyICU+JSBhdXRvcGxvdCh2YXJlam8udHNiKQ0KYGBgDQoNCkUgYXMgbm9zc2FzIGVzdGltYXRpdmFzIHBhcmEgYXTDqSBKYW4vMjAyMSBzw6NvOg0KDQpgYGB7cn0NCmtuaXRyOjprYWJsZShmYzIpDQpgYGANCg0KTGVtYnJhciBxdWUgdXNhbW9zIGRhZG9zIGFwZW5hcyBhdMOpIEphbi8yMDIwIG5hIHPDqXJpZSBvcmlnaW5hbC4gU2UgdXNhciBhIHPDqXJpZSBhdHVhbGl6YWRhIGF0w6kgYWdvcmEsIHZvY8OqIHRlcsOhIG1haXMgb2JzZXJ2YcOnw7VlcyBxdWUgYXMgMjQxIGluaWNpYWlzLg0KDQpQYXJhIG7Do28gYWNoYXJtb3MgcXVlIG8gYGZhYmxlLnByb3BoZXRgIMOpIHJ1aW0sIGUgZGVzZW5jYXJnbyBkZSBjb25zY2nDqm5jaWEsIGZhcmVpIGEgZXN0aW1hw6fDo28gZSBmb3JlY2FzdCBjb20gbyBmYWJsZS5wcm9waGV0IHBhcmEgZm9yYSBkYSBhbW9zdHJhIGUgdXNhbmRvIGEgc8OpcmllIHRvZGEuDQoNCiMgRXN0aW1hw6fDo28gY29tIHPDqXJpZSB0b2RhDQoNCmBgYHtyIERBVEEsIHdhcm5pbmc9RkFMU0UsY29tbWVudD1GQUxTRX0NCmxpYnJhcnkoQkVUUykNCiMgUGVnYW5kbyBhcyBzw6lyaWVzIGEgcGFydGlyIGRvIHNpdGUgZG8gQmFuY28gQ2VudHJhbCBkbyBCcmFzaWwNCiMgw41uZGljZSBkZSB2b2x1bWUgZGUgdmVuZGFzIG5vIHZhcmVqbyBUb3RhbCBkZSBNYXRvIEdyb3NzbyBkbyBTdWwNCiMgbWVuc2FsIGEgcGFydGlyIGRlIGphbi8yMDAwIGF0w6kgYWJyLzIwMjEgIA0KIyAyNTYgb2JzZXJ2YcOnw7VlcyBtZW5zYWlzDQp2YXJlam9tcy5hbGwgPC0gQkVUU2dldCgxNDc5LGZyb209IjIwMDAtMDEtMDEiLA0KICAgICAgICAgICAgICBkYXRhLmZyYW1lID0gVFJVRSxmcmVxdWVuY3kgPSAxMikNCmBgYA0KDQpgYGB7ciBUU0lCQkxFLCB3YXJuaW5nPUZBTFNFLGNvbW1lbnQ9RkFMU0V9DQpsaWJyYXJ5KHRzaWJibGUpDQpsaWJyYXJ5KHRzaWJibGVkYXRhKQ0KbGlicmFyeShsdWJyaWRhdGUpDQpsaWJyYXJ5KGRwbHlyKTtsaWJyYXJ5KHRpZHl2ZXJzZSkNCg0KbXRoMiA8LSBtYWtlX2RhdGUoIjIwMDAiKSArIG1vbnRocygwOjI1NSkNCmRhZG9zMjwtY2JpbmQodmFyZWpvbXMuYWxsWy0xXSx0aW1lMj15ZWFybW9udGgobXRoMikpDQp2YXJlam8uYWxsLnRzYiA8LSB0c2liYmxlKGRhZG9zMiwNCiAgaW5kZXggPSB0aW1lMikgJT4lIA0KICBwcmludCgpDQphdXRvcGxvdCh2YXJlam8uYWxsLnRzYikNCmBgYA0KDQpgYGB7ciBmYzMsd2FybmluZz1GQUxTRSxjb21tZW50PUZBTFNFfQ0KbGlicmFyeShmYWJsZS5wcm9waGV0KTtsaWJyYXJ5KGZhYmxlKQ0KbGlicmFyeShmcHAzKQ0KZml0MyA8LSB2YXJlam8uYWxsLnRzYiAlPiUgbW9kZWwocHJvcGhldCA9IHByb3BoZXQodmFsdWUpKSANCmZjMyA8LSBmaXQzICU+JSBmb3JlY2FzdChoID0gMTIpDQpmYzMgJT4lIGF1dG9wbG90KHZhcmVqby5hbGwudHNiKQ0KcHJpbnQoZmMzKQ0KYGBgDQoNCiMgUmVmZXLDqm5jaWFzIHsjUmVmZXLDqm5jaWFzIC51bm51bWJlcmVkfQ0KDQpGRVJSRUlSQSwgUGVkcm8gQ29zdGE7IFNQRVJBTlpBLCBUYWxpdGhhOyBDT1NUQSwgSm9uYXRoYSAoMjAxOCkuIEJFVFM6IEJyYXppbGlhbiBFY29ub21pYyBUaW1lIFNlcmllcy4gUiBwYWNrYWdlIHZlcnNpb24gMC40LjkuIERpc3BvbsOtdmVsIGVtOiA8aHR0cHM6Ly9DUkFOLlItcHJvamVjdC5vcmcvcGFja2FnZT1CRVRTPi4NCg0KRklHVUVJUkVETywgQWRyaWFubyBNYXJjb3MgUm9kcmlndWVzLiBTw6lyaWVzIFRlbXBvcmFpcyBjb20gUjogQW7DoWxpc2UgZG8gQ29uc3VtbyBkbyBWYXJlam8gZW0gTVMgY29tIGBmYWJsZWAgZSBgZmVhc3RzYC4gQ2FtcG8gR3JhbmRlLU1TLEJyYXNpbDogUlN0dWRpby9ScHVicywgMjAyMS4gRGlzcG9uw612ZWwgZW0gPGh0dHA6Ly9ycHVicy5jb20vYW1yb2ZpL2ZhYmxlX2ZlYXN0c192YXJlam9tcz4uDQoNCkhZTkRNQU4sIFJvYi4gKDIwMTgpLiBmcHAyOiBEYXRhIGZvciAiRm9yZWNhc3Rpbmc6IFByaW5jaXBsZXMgYW5kIFByYWN0aWNlIiAoMm5kIEVkaXRpb24pLiBSIHBhY2thZ2UgdmVyc2lvbiAyLjMuIERpc3BvbsOtdmVsIGVtOiA8aHR0cHM6Ly9DUkFOLlItcHJvamVjdC5vcmcvcGFja2FnZT1mcHAyPi4NCg0KSFlORE1BTiwgUm9iLiAoMjAxOSkuIGZwcDM6IERhdGEgZm9yICJGb3JlY2FzdGluZzogUHJpbmNpcGxlcyBhbmQgUHJhY3RpY2UiICgzcmQgRWRpdGlvbikuIFIgcGFja2FnZS4gRGlzcG9uw612ZWwgZW06IDxodHRwczovL2dpdGh1Yi5jb20vcm9iamh5bmRtYW4vZnBwMy1wYWNrYWdlPiwgPGh0dHBzOi8vT1RleHRzLm9yZy9mcHAzLz4uDQoNCkhZTkRNQU4sIFIuSi47IEFUSEFOQVNPUE9VTE9TLCBHLiAoMjAyMCkgRm9yZWNhc3Rpbmc6IHByaW5jaXBsZXMgYW5kIHByYWN0aWNlLCAzcmQgZWRpdGlvbiwgT1RleHRzOiBNZWxib3VybmUsIEF1c3RyYWxpYS4gRGlzcG9uw612ZWwgZW06IDxodHRwczovL290ZXh0cy5jb20vZnBwMy8+LiBBY2Nlc3NlZCBvbiAwMiBBcHIgMjAyMC4NCg0KTydIQVJBLVdJTEQsIE1pdGNoZWxsOyBUQVlMT1IsIFNlYW47IExFVEhBTSwgQmVuIChOQSkuIGZhYmxlLnByb3BoZXQ6IFByb3BoZXQgTW9kZWxsaW5nIEludGVyZmFjZSBmb3IgJ2ZhYmxlJy4gUiBwYWNrYWdlIHZlcnNpb24gMC4xLjAuOTAwMC4gQXZhaWxhYmxlIGF0OiA8aHR0cHM6Ly9wa2cubWl0Y2hlbGxvaGFyYXdpbGQuY29tL2ZhYmxlLnByb3BoZXQvPi4NCg==