Carregando os pacotes

library(magrittr) 
library(lubridate)
library(tidyverse)
library(gridExtra)
library(ggforce) 
library(kableExtra) 
library(leaflet) 
library(plotly)
library(zoo)
library(forecast)
options(knitr.kable.NA = '')

Carregando os dados

raw.data.confirmed <- read.csv('https://raw.githubusercontent.com/CSSEGISandData/COVID-19/master/csse_covid_19_data/csse_covid_19_time_series/time_series_covid19_confirmed_global.csv')
raw.data.deaths <- read.csv('https://raw.githubusercontent.com/CSSEGISandData/COVID-19/master/csse_covid_19_data/csse_covid_19_time_series/time_series_covid19_deaths_global.csv')
raw.data.recovered <- read.csv('https://raw.githubusercontent.com/CSSEGISandData/COVID-19/master/csse_covid_19_data/csse_covid_19_time_series/time_series_covid19_recovered_global.csv')

n.col <- ncol(raw.data.confirmed)
dates <- names(raw.data.confirmed)[5:n.col] %>% substr(2,8) %>% mdy()

Conferindo as datas

range(dates)
[1] "2020-01-22" "2020-07-15"
min.date <- min(dates)
max.date <- max(dates)
min.date.txt <- min.date %>% format('%d %b %Y')
max.date.txt <- max.date %>% format('%d %b %Y')

cleanData <- function(data) {
  data %<>% select(-c(Province.State, Lat, Long)) %>% rename(country=Country.Region)
  data %<>% gather(key=date, value=count, -country)
  data %<>% mutate(date = date %>% substr(2,8) %>% mdy())
  data %<>% group_by(country, date) %>% summarise(count=sum(count, na.rm=T)) %>% as.data.frame()
  return(data)
}

data.confirmed <- raw.data.confirmed %>% cleanData() %>% rename(confirmed=count)
data.deaths <- raw.data.deaths %>% cleanData() %>% rename(deaths=count)
data.recovered <- raw.data.recovered %>% cleanData() %>% rename(recovered=count)
data <- data.confirmed %>% merge(data.deaths, all=T) %>% merge(data.recovered, all=T)

library(wpp2019)
data(pop)

popz <- pop[c(2,17)]

popz$name <- as.factor(popz$name)

names(popz) <- c("country", "pop")
levels(popz$country)[233] <- "US"

#subset(popz, country == "US")
data <- merge(popz,data)



data %<>% arrange(country, date)
n <- nrow(data)
day1 <- min(data$date)
data %<>% mutate(new.confirmed = ifelse(date == day1, NA, confirmed - lag(confirmed, n=1)),
                 new.deaths = ifelse(date == day1, NA, deaths - lag(deaths, n=1)),
                 new.recovered = ifelse(date == day1, NA, recovered - lag(recovered, n=1)))
data %<>% mutate(new.confirmed = ifelse(new.confirmed < 0, 0, new.confirmed),
                 new.deaths = ifelse(new.deaths < 0, 0, new.deaths),
                 new.recovered = ifelse(new.recovered < 0, 0, new.recovered))


db <- data

Selecionando o País

brz <- db %>% arrange((date)) %>% filter(country=='Brazil') 

brz %>% kable("pandoc")
country pop date confirmed deaths recovered new.confirmed new.deaths new.recovered
Brazil 212559.4 2020-01-22 0 0 0
Brazil 212559.4 2020-01-23 0 0 0 0 0 0
Brazil 212559.4 2020-01-24 0 0 0 0 0 0
Brazil 212559.4 2020-01-25 0 0 0 0 0 0
Brazil 212559.4 2020-01-26 0 0 0 0 0 0
Brazil 212559.4 2020-01-27 0 0 0 0 0 0
Brazil 212559.4 2020-01-28 0 0 0 0 0 0
Brazil 212559.4 2020-01-29 0 0 0 0 0 0
Brazil 212559.4 2020-01-30 0 0 0 0 0 0
Brazil 212559.4 2020-01-31 0 0 0 0 0 0
Brazil 212559.4 2020-02-01 0 0 0 0 0 0
Brazil 212559.4 2020-02-02 0 0 0 0 0 0
Brazil 212559.4 2020-02-03 0 0 0 0 0 0
Brazil 212559.4 2020-02-04 0 0 0 0 0 0
Brazil 212559.4 2020-02-05 0 0 0 0 0 0
Brazil 212559.4 2020-02-06 0 0 0 0 0 0
Brazil 212559.4 2020-02-07 0 0 0 0 0 0
Brazil 212559.4 2020-02-08 0 0 0 0 0 0
Brazil 212559.4 2020-02-09 0 0 0 0 0 0
Brazil 212559.4 2020-02-10 0 0 0 0 0 0
Brazil 212559.4 2020-02-11 0 0 0 0 0 0
Brazil 212559.4 2020-02-12 0 0 0 0 0 0
Brazil 212559.4 2020-02-13 0 0 0 0 0 0
Brazil 212559.4 2020-02-14 0 0 0 0 0 0
Brazil 212559.4 2020-02-15 0 0 0 0 0 0
Brazil 212559.4 2020-02-16 0 0 0 0 0 0
Brazil 212559.4 2020-02-17 0 0 0 0 0 0
Brazil 212559.4 2020-02-18 0 0 0 0 0 0
Brazil 212559.4 2020-02-19 0 0 0 0 0 0
Brazil 212559.4 2020-02-20 0 0 0 0 0 0
Brazil 212559.4 2020-02-21 0 0 0 0 0 0
Brazil 212559.4 2020-02-22 0 0 0 0 0 0
Brazil 212559.4 2020-02-23 0 0 0 0 0 0
Brazil 212559.4 2020-02-24 0 0 0 0 0 0
Brazil 212559.4 2020-02-25 0 0 0 0 0 0
Brazil 212559.4 2020-02-26 1 0 0 1 0 0
Brazil 212559.4 2020-02-27 1 0 0 0 0 0
Brazil 212559.4 2020-02-28 1 0 0 0 0 0
Brazil 212559.4 2020-02-29 2 0 0 1 0 0
Brazil 212559.4 2020-03-01 2 0 0 0 0 0
Brazil 212559.4 2020-03-02 2 0 0 0 0 0
Brazil 212559.4 2020-03-03 2 0 0 0 0 0
Brazil 212559.4 2020-03-04 4 0 0 2 0 0
Brazil 212559.4 2020-03-05 4 0 0 0 0 0
Brazil 212559.4 2020-03-06 13 0 0 9 0 0
Brazil 212559.4 2020-03-07 13 0 0 0 0 0
Brazil 212559.4 2020-03-08 20 0 0 7 0 0
Brazil 212559.4 2020-03-09 25 0 0 5 0 0
Brazil 212559.4 2020-03-10 31 0 0 6 0 0
Brazil 212559.4 2020-03-11 38 0 0 7 0 0
Brazil 212559.4 2020-03-12 52 0 0 14 0 0
Brazil 212559.4 2020-03-13 151 0 0 99 0 0
Brazil 212559.4 2020-03-14 151 0 0 0 0 0
Brazil 212559.4 2020-03-15 162 0 0 11 0 0
Brazil 212559.4 2020-03-16 200 0 1 38 0 1
Brazil 212559.4 2020-03-17 321 1 2 121 1 1
Brazil 212559.4 2020-03-18 372 3 2 51 2 0
Brazil 212559.4 2020-03-19 621 6 2 249 3 0
Brazil 212559.4 2020-03-20 793 11 2 172 5 0
Brazil 212559.4 2020-03-21 1021 15 2 228 4 0
Brazil 212559.4 2020-03-22 1546 25 2 525 10 0
Brazil 212559.4 2020-03-23 1924 34 2 378 9 0
Brazil 212559.4 2020-03-24 2247 46 2 323 12 0
Brazil 212559.4 2020-03-25 2554 59 2 307 13 0
Brazil 212559.4 2020-03-26 2985 77 6 431 18 4
Brazil 212559.4 2020-03-27 3417 92 6 432 15 0
Brazil 212559.4 2020-03-28 3904 111 6 487 19 0
Brazil 212559.4 2020-03-29 4256 136 6 352 25 0
Brazil 212559.4 2020-03-30 4579 159 120 323 23 114
Brazil 212559.4 2020-03-31 5717 201 127 1138 42 7
Brazil 212559.4 2020-04-01 6836 240 127 1119 39 0
Brazil 212559.4 2020-04-02 8044 324 127 1208 84 0
Brazil 212559.4 2020-04-03 9056 359 127 1012 35 0
Brazil 212559.4 2020-04-04 10360 445 127 1304 86 0
Brazil 212559.4 2020-04-05 11130 486 127 770 41 0
Brazil 212559.4 2020-04-06 12161 564 127 1031 78 0
Brazil 212559.4 2020-04-07 14034 686 127 1873 122 0
Brazil 212559.4 2020-04-08 16170 819 127 2136 133 0
Brazil 212559.4 2020-04-09 18092 950 173 1922 131 46
Brazil 212559.4 2020-04-10 19638 1057 173 1546 107 0
Brazil 212559.4 2020-04-11 20727 1124 173 1089 67 0
Brazil 212559.4 2020-04-12 22192 1223 173 1465 99 0
Brazil 212559.4 2020-04-13 23430 1328 173 1238 105 0
Brazil 212559.4 2020-04-14 25262 1532 3046 1832 204 2873
Brazil 212559.4 2020-04-15 28320 1736 14026 3058 204 10980
Brazil 212559.4 2020-04-16 30425 1924 14026 2105 188 0
Brazil 212559.4 2020-04-17 33682 2141 14026 3257 217 0
Brazil 212559.4 2020-04-18 36658 2354 14026 2976 213 0
Brazil 212559.4 2020-04-19 38654 2462 22130 1996 108 8104
Brazil 212559.4 2020-04-20 40743 2587 22130 2089 125 0
Brazil 212559.4 2020-04-21 43079 2741 22991 2336 154 861
Brazil 212559.4 2020-04-22 45757 2906 25318 2678 165 2327
Brazil 212559.4 2020-04-23 50036 3331 26573 4279 425 1255
Brazil 212559.4 2020-04-24 54043 3704 27655 4007 373 1082
Brazil 212559.4 2020-04-25 59324 4057 29160 5281 353 1505
Brazil 212559.4 2020-04-26 63100 4286 30152 3776 229 992
Brazil 212559.4 2020-04-27 67446 4603 31142 4346 317 990
Brazil 212559.4 2020-04-28 73235 5083 32544 5789 480 1402
Brazil 212559.4 2020-04-29 79685 5513 34132 6450 430 1588
Brazil 212559.4 2020-04-30 87187 6006 35935 7502 493 1803
Brazil 212559.4 2020-05-01 92202 6412 38039 5015 406 2104
Brazil 212559.4 2020-05-02 97100 6761 40937 4898 349 2898
Brazil 212559.4 2020-05-03 101826 7051 42991 4726 290 2054
Brazil 212559.4 2020-05-04 108620 7367 45815 6794 316 2824
Brazil 212559.4 2020-05-05 115455 7938 48221 6835 571 2406
Brazil 212559.4 2020-05-06 126611 8588 51370 11156 650 3149
Brazil 212559.4 2020-05-07 135773 9190 55350 9162 602 3980
Brazil 212559.4 2020-05-08 146894 10017 59297 11121 827 3947
Brazil 212559.4 2020-05-09 156061 10656 61685 9167 639 2388
Brazil 212559.4 2020-05-10 162699 11123 64957 6638 467 3272
Brazil 212559.4 2020-05-11 169594 11653 67384 6895 530 2427
Brazil 212559.4 2020-05-12 178214 12461 72597 8620 808 5213
Brazil 212559.4 2020-05-13 190137 13240 78424 11923 779 5827
Brazil 212559.4 2020-05-14 203165 13999 79479 13028 759 1055
Brazil 212559.4 2020-05-15 220291 14962 84970 17126 963 5491
Brazil 212559.4 2020-05-16 233511 15662 89672 13220 700 4702
Brazil 212559.4 2020-05-17 241080 16118 94122 7569 456 4450
Brazil 212559.4 2020-05-18 255368 16853 100459 14288 735 6337
Brazil 212559.4 2020-05-19 271885 17983 106794 16517 1130 6335
Brazil 212559.4 2020-05-20 291579 18859 116683 19694 876 9889
Brazil 212559.4 2020-05-21 310087 20047 125960 18508 1188 9277
Brazil 212559.4 2020-05-22 330890 21048 135430 20803 1001 9470
Brazil 212559.4 2020-05-23 347398 22013 142587 16508 965 7157
Brazil 212559.4 2020-05-24 363211 22666 149911 15813 653 7324
Brazil 212559.4 2020-05-25 374898 23473 153833 11687 807 3922
Brazil 212559.4 2020-05-26 391222 24512 158593 16324 1039 4760
Brazil 212559.4 2020-05-27 411821 25598 166647 20599 1086 8054
Brazil 212559.4 2020-05-28 438238 26754 177604 26417 1156 10957
Brazil 212559.4 2020-05-29 465166 27878 189476 26928 1124 11872
Brazil 212559.4 2020-05-30 498440 28834 200892 33274 956 11416
Brazil 212559.4 2020-05-31 514849 29314 206555 16409 480 5663
Brazil 212559.4 2020-06-01 526447 29937 211080 11598 623 4525
Brazil 212559.4 2020-06-02 555383 31199 223638 28936 1262 12558
Brazil 212559.4 2020-06-03 584016 32548 238617 28633 1349 14979
Brazil 212559.4 2020-06-04 614941 34021 254963 30925 1473 16346
Brazil 212559.4 2020-06-05 645771 35026 266940 30830 1005 11977
Brazil 212559.4 2020-06-06 672846 35930 277149 27075 904 10209
Brazil 212559.4 2020-06-07 691758 36455 283952 18912 525 6803
Brazil 212559.4 2020-06-08 707412 37134 378257 15654 679 94305
Brazil 212559.4 2020-06-09 739503 38406 396737 32091 1272 18480
Brazil 212559.4 2020-06-10 772416 39680 413916 32913 1274 17179
Brazil 212559.4 2020-06-11 802828 40919 429965 30412 1239 16049
Brazil 212559.4 2020-06-12 828810 41828 445123 25982 909 15158
Brazil 212559.4 2020-06-13 850514 42720 459436 21704 892 14313
Brazil 212559.4 2020-06-14 867624 43332 469141 17110 612 9705
Brazil 212559.4 2020-06-15 888271 43959 477709 20647 627 8568
Brazil 212559.4 2020-06-16 923189 45241 490005 34918 1282 12296
Brazil 212559.4 2020-06-17 955377 46510 521046 32188 1269 31041
Brazil 212559.4 2020-06-18 978142 47748 534580 22765 1238 13534
Brazil 212559.4 2020-06-19 1032913 48954 551631 54771 1206 17051
Brazil 212559.4 2020-06-20 1067579 49976 576779 34666 1022 25148
Brazil 212559.4 2020-06-21 1083341 50591 588118 15762 615 11339
Brazil 212559.4 2020-06-22 1106470 51271 601736 23129 680 13618
Brazil 212559.4 2020-06-23 1145906 52645 627963 39436 1374 26227
Brazil 212559.4 2020-06-24 1188631 53830 660469 42725 1185 32506
Brazil 212559.4 2020-06-25 1228114 54971 679524 39483 1141 19055
Brazil 212559.4 2020-06-26 1274974 55961 702399 46860 990 22875
Brazil 212559.4 2020-06-27 1313667 57070 727715 38693 1109 25316
Brazil 212559.4 2020-06-28 1344143 57622 746018 30476 552 18303
Brazil 212559.4 2020-06-29 1368195 58314 757811 24052 692 11793
Brazil 212559.4 2020-06-30 1402041 59594 788318 33846 1280 30507
Brazil 212559.4 2020-07-01 1448753 60632 817642 46712 1038 29324
Brazil 212559.4 2020-07-02 1496858 61884 957692 48105 1252 140050
Brazil 212559.4 2020-07-03 1539081 63174 984615 42223 1290 26923
Brazil 212559.4 2020-07-04 1577004 64265 990731 37923 1091 6116
Brazil 212559.4 2020-07-05 1603055 64867 1029045 26051 602 38314
Brazil 212559.4 2020-07-06 1623284 65487 1062542 20229 620 33497
Brazil 212559.4 2020-07-07 1668589 66741 1107012 45305 1254 44470
Brazil 212559.4 2020-07-08 1713160 67964 1139844 44571 1223 32832
Brazil 212559.4 2020-07-09 1755779 69184 1171447 42619 1220 31603
Brazil 212559.4 2020-07-10 1800827 70398 1217361 45048 1214 45914
Brazil 212559.4 2020-07-11 1839850 71469 1244088 39023 1071 26727
Brazil 212559.4 2020-07-12 1864681 72100 1264843 24831 631 20755
Brazil 212559.4 2020-07-13 1884967 72833 1291251 20286 733 26408
Brazil 212559.4 2020-07-14 1926824 74133 1323425 41857 1300 32174
Brazil 212559.4 2020-07-15 1966748 75366 1350098 39924 1233 26673

Criando a média movel com os dados diários

Infectados <- c(brz$new.deaths)
inicio <- min(brz$date)
dia <- 1:(length(Infectados))
Day <- inicio+dia

ab <- zoo(Infectados, seq(from = (inicio), to = last(brz$date), by = 1))
sm <- ma(ab,order=7) # 7 dias

brz$mm <- sm
names(brz)[10] <- "mm"

Gráfico da Média Móvel

brz %>% ggplot() + geom_bar(aes(x=date, y=new.deaths, fill="Casos"), stat = "identity", position = position_dodge(1))+
  ggtitle(paste(brz$country[1])) +
  labs(subtitle = paste("Média móvel de 7 dias = ",round(last(na.omit(sm)),0), "óbitos")) +
  geom_line(aes(x=date,y=mm, fill="Média Movel"), color="blue", size=1.5) + 
#  ylim(0, 150)+
  ylab("Óbitos") + 
  xlab("")+
  scale_x_date(
    date_minor_breaks = "1 day",
    breaks = "2 week",
    date_labels = "%d-%b-%Y") + 
  theme_classic() + 
  theme(legend.position = "none",
    text = element_text(size = 10),
        axis.text.x = element_text(angle = 45, hjust = 1)) 

Baixar dados COVID-BR

get_cor <- function (dir = "outputs", filename = "corona_brasil", 
                     cidade = NULL, uf = NULL, ibge_cod = NULL, by_uf = FALSE, 
                     save = TRUE) 
{
  res <- readr::read_csv("https://data.brasil.io/dataset/covid19/caso_full.csv.gz")
  res$date <- as.Date(res$date)
  metadado <- data.frame(intervalo = paste(range(res$date), 
                                           collapse = ";"), fonte = "https://data.brasil.io/dataset/covid19/", 
                         acesso_em = Sys.Date())
  if (!is.null(cidade) & is.null(uf)) {
    stop("Precisa fornecer um estado para evitar ambiguidade")
  }
  if (!is.null(cidade)) {
    if (sum(!cidade %in% unique(res$city)) > 0) {
      stop("algum nome de municipio em 'city' invalido ou ainda nao ha dados/casos para essa cidade")
    }
    if (sum(!uf %in% unique(res$state) > 0)) {
      stop("algum nome de estado em 'state' invalido ou ainda nao ha dados/casos para essa cidade")
    }
    if (!is.null(cidade) & !is.null(uf)) {
      res <- res %>% dplyr::filter(.data$state %in% uf & 
                                     .data$city %in% cidade)
    }
  }
  else {
    res <- res
  }
  if (!is.null(ibge_cod)) {
    if (sum(!ibge_cod %in% unique(res$city_ibge_code)) > 
        0) {
      stop("algum codigo de municipio ou estado 'ibge_code' invalido")
    }
    else {
      res <- res %>% dplyr::filter(.data$city_ibge_code %in% 
                                     ibge_cod)
    }
  }
  else {
    res <- res
  }
  if (is.null(cidade) & is.null(ibge_cod) & !is.null(uf)) {
    res <- res %>% dplyr::filter(.data$state %in% uf)
  }
  if (is.null(cidade) & is.null(ibge_cod) & is.null(uf)) {
    res <- res
  }
  if (by_uf == TRUE) {
    res <- res %>% filter(.data$place_type == "state")
  }
  res$date <- as.Date(res$date)
  res$state <- as.factor(res$state)
  if (save) {
    message(paste0("salvando ", filename, ".csv em ", 
                   dir))
    if (!dir.exists(dir)) 
      dir.create(dir)
    utils::write.csv(res, paste0(dir, "/", filename, 
                                 ".csv"), row.names = FALSE)
    utils::write.csv(metadado, paste0(dir, "/", filename, 
                                      "_metadado", ".csv"), row.names = FALSE)
  }
  return(res)
}

dad <- get_cor()

Selecionando o Estado

st2 <- subset(dad, place_type == "state")
st2$state <- iconv(st2$state, "UTF-8")


st2 %<>% group_by(state) %>% mutate(cum_cases = cumsum(last_available_confirmed))

BA <- st2 %>% filter(state == "BA") %>% arrange(date)
BAn <-  BA %>%
  select(c(state, date, new_deaths)) %>% arrange(date) %>%
  gather(key=type, value=count, -c(state, date))


Infectados <- BAn$count
inicio <- min(BAn$date)
dia <- 1:(length(Infectados))
Day <- inicio+dia


ab <- zoo(Infectados, seq(from = inicio, to = last(BAn$date), by = 1))

sm <- ma(ab,order=7)
BAn$mm <- sm
names(BAn)[5] <- "mm"

Gráfico da Média Móvel do Estado

BAn %>% ggplot() + geom_bar(aes(x=date, y=count, fill="Casos"), stat = "identity", position = position_dodge(1))+
  ggtitle(paste(BAn$state[1])) +
  labs(subtitle = paste("Média móvel de 7 dias = ",round(last(na.omit(sm)),0), "óbitos")) +
  geom_line(aes(x=date,y=mm, fill="Média Movel"), color="blue", size=1.5) + 
  #  ylim(0, 150)+
  ylab("Óbitos") + 
  xlab("")+
  scale_x_date(
    date_minor_breaks = "1 day",
    breaks = "2 week",
    date_labels = "%d-%b-%Y") + 
  theme_classic() + 
  theme(legend.position = "none",
        text = element_text(size = 10),
        axis.text.x = element_text(angle = 45, hjust = 1)) 

Selecionando o Município

ios2 <- dad %>% filter(city == "Ilhéus") %>% arrange(date)

iosn <-  ios2 %>%
  select(c(city, date, new_confirmed)) %>% arrange(date) %>%
  gather(key=type, value=count, -c(city, date))

Infectados <- iosn$count
inicio <- min(iosn$date)
dia <- 1:(length(Infectados))
Day <- inicio+dia


ab <- zoo(Infectados, seq(from = inicio, to = last(iosn$date), by = 1))

sm <- ma(ab,order=7)

iosn$mm <- sm
names(iosn)[5] <- "mm"

Gráfico da Média Móvel de Ilhéus

iosn %>% ggplot() + geom_bar(aes(x=date, y=count, fill="Casos"), stat = "identity", position = position_dodge(1))+
  ggtitle(paste(iosn$city[1])) +
  labs(subtitle = paste("Média móvel de 7 dias = ",round(last(na.omit(sm)),0), "casos"),
       caption = paste("Cid Póvoas @cidedson \n Fonte: Secretaria de Saúde do Estado - ", ios2$state)) +
  geom_line(aes(x=date,y=mm, fill="Média Movel"), color="blue", size=1.5) + 
  ylim(0, round(max(iosn$count, na.rm=T),0))+
  ylab("Casos") + 
  xlab("")+
  scale_x_date(
    date_minor_breaks = "1 day",
    breaks = "2 week",
    date_labels = "%d-%b-%Y") + 
  theme_classic() + 
  theme(legend.position = "none",
        text = element_text(size = 10),
        axis.text.x = element_text(angle = 45, hjust = 1)) 

IycgLS0tDQojJyB0aXRsZTogIk3DqWRpYSBNw7N2ZWwgQnJhc2lsIg0KIycgYXV0aG9yOiBDaWQgRWRzb24gUMOzdm9hcw0KIycgb3V0cHV0Og0KIycgICBodG1sX25vdGVib29rOiANCiMnICAgICBjb2RlX2ZvbGRpbmc6IGhpZGUNCiMnICAgICB0b2M6IHRydWUNCiMnICAgICB0b2NfZmxvYXQ6IHRydWUNCiMnICAgICBjb2xsYXBzZWQ6IGZhbHNlDQojJyAtLS0NCiMrIHdhcm5pbmc9RkFMU0UsIGVjaG89VCwgbWVzc2FnZT1GQUxTRQ0KIysgc2V0dXAsIGluY2x1ZGU9RiwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRQ0KDQpTeXMuc2V0bG9jYWxlKGNhdGVnb3J5ID0gIkxDX0FMTCIsIGxvY2FsZSA9ICJFbmdsaXNoX1VuaXRlZCBTdGF0ZXMuMTI1MiIpDQoNCiMnICMjIENhcnJlZ2FuZG8gb3MgcGFjb3Rlcw0KIysgZWNobz1ULCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFDQoNCmxpYnJhcnkobWFncml0dHIpIA0KbGlicmFyeShsdWJyaWRhdGUpDQpsaWJyYXJ5KHRpZHl2ZXJzZSkNCmxpYnJhcnkoZ3JpZEV4dHJhKQ0KbGlicmFyeShnZ2ZvcmNlKSANCmxpYnJhcnkoa2FibGVFeHRyYSkgDQpsaWJyYXJ5KGxlYWZsZXQpIA0KbGlicmFyeShwbG90bHkpDQpsaWJyYXJ5KHpvbykNCmxpYnJhcnkoZm9yZWNhc3QpDQpvcHRpb25zKGtuaXRyLmthYmxlLk5BID0gJycpDQoNCiMnICMjIENhcnJlZ2FuZG8gb3MgZGFkb3MNCiMrIGVjaG89VCwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRQ0KDQpyYXcuZGF0YS5jb25maXJtZWQgPC0gcmVhZC5jc3YoJ2h0dHBzOi8vcmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbS9DU1NFR0lTYW5kRGF0YS9DT1ZJRC0xOS9tYXN0ZXIvY3NzZV9jb3ZpZF8xOV9kYXRhL2Nzc2VfY292aWRfMTlfdGltZV9zZXJpZXMvdGltZV9zZXJpZXNfY292aWQxOV9jb25maXJtZWRfZ2xvYmFsLmNzdicpDQpyYXcuZGF0YS5kZWF0aHMgPC0gcmVhZC5jc3YoJ2h0dHBzOi8vcmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbS9DU1NFR0lTYW5kRGF0YS9DT1ZJRC0xOS9tYXN0ZXIvY3NzZV9jb3ZpZF8xOV9kYXRhL2Nzc2VfY292aWRfMTlfdGltZV9zZXJpZXMvdGltZV9zZXJpZXNfY292aWQxOV9kZWF0aHNfZ2xvYmFsLmNzdicpDQpyYXcuZGF0YS5yZWNvdmVyZWQgPC0gcmVhZC5jc3YoJ2h0dHBzOi8vcmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbS9DU1NFR0lTYW5kRGF0YS9DT1ZJRC0xOS9tYXN0ZXIvY3NzZV9jb3ZpZF8xOV9kYXRhL2Nzc2VfY292aWRfMTlfdGltZV9zZXJpZXMvdGltZV9zZXJpZXNfY292aWQxOV9yZWNvdmVyZWRfZ2xvYmFsLmNzdicpDQoNCm4uY29sIDwtIG5jb2wocmF3LmRhdGEuY29uZmlybWVkKQ0KZGF0ZXMgPC0gbmFtZXMocmF3LmRhdGEuY29uZmlybWVkKVs1Om4uY29sXSAlPiUgc3Vic3RyKDIsOCkgJT4lIG1keSgpDQoNCiMnICMjIENvbmZlcmluZG8gYXMgZGF0YXMNCiMrIGVjaG89VCwgd2FybmluZz1GQUxTRSwgbWVzc2FnZT1GQUxTRQ0KDQpyYW5nZShkYXRlcykNCg0KbWluLmRhdGUgPC0gbWluKGRhdGVzKQ0KbWF4LmRhdGUgPC0gbWF4KGRhdGVzKQ0KbWluLmRhdGUudHh0IDwtIG1pbi5kYXRlICU+JSBmb3JtYXQoJyVkICViICVZJykNCm1heC5kYXRlLnR4dCA8LSBtYXguZGF0ZSAlPiUgZm9ybWF0KCclZCAlYiAlWScpDQoNCmNsZWFuRGF0YSA8LSBmdW5jdGlvbihkYXRhKSB7DQogIGRhdGEgJTw+JSBzZWxlY3QoLWMoUHJvdmluY2UuU3RhdGUsIExhdCwgTG9uZykpICU+JSByZW5hbWUoY291bnRyeT1Db3VudHJ5LlJlZ2lvbikNCiAgZGF0YSAlPD4lIGdhdGhlcihrZXk9ZGF0ZSwgdmFsdWU9Y291bnQsIC1jb3VudHJ5KQ0KICBkYXRhICU8PiUgbXV0YXRlKGRhdGUgPSBkYXRlICU+JSBzdWJzdHIoMiw4KSAlPiUgbWR5KCkpDQogIGRhdGEgJTw+JSBncm91cF9ieShjb3VudHJ5LCBkYXRlKSAlPiUgc3VtbWFyaXNlKGNvdW50PXN1bShjb3VudCwgbmEucm09VCkpICU+JSBhcy5kYXRhLmZyYW1lKCkNCiAgcmV0dXJuKGRhdGEpDQp9DQoNCmRhdGEuY29uZmlybWVkIDwtIHJhdy5kYXRhLmNvbmZpcm1lZCAlPiUgY2xlYW5EYXRhKCkgJT4lIHJlbmFtZShjb25maXJtZWQ9Y291bnQpDQpkYXRhLmRlYXRocyA8LSByYXcuZGF0YS5kZWF0aHMgJT4lIGNsZWFuRGF0YSgpICU+JSByZW5hbWUoZGVhdGhzPWNvdW50KQ0KZGF0YS5yZWNvdmVyZWQgPC0gcmF3LmRhdGEucmVjb3ZlcmVkICU+JSBjbGVhbkRhdGEoKSAlPiUgcmVuYW1lKHJlY292ZXJlZD1jb3VudCkNCmRhdGEgPC0gZGF0YS5jb25maXJtZWQgJT4lIG1lcmdlKGRhdGEuZGVhdGhzLCBhbGw9VCkgJT4lIG1lcmdlKGRhdGEucmVjb3ZlcmVkLCBhbGw9VCkNCg0KbGlicmFyeSh3cHAyMDE5KQ0KZGF0YShwb3ApDQoNCnBvcHogPC0gcG9wW2MoMiwxNyldDQoNCnBvcHokbmFtZSA8LSBhcy5mYWN0b3IocG9weiRuYW1lKQ0KDQpuYW1lcyhwb3B6KSA8LSBjKCJjb3VudHJ5IiwgInBvcCIpDQpsZXZlbHMocG9weiRjb3VudHJ5KVsyMzNdIDwtICJVUyINCg0KI3N1YnNldChwb3B6LCBjb3VudHJ5ID09ICJVUyIpDQpkYXRhIDwtIG1lcmdlKHBvcHosZGF0YSkNCg0KDQoNCmRhdGEgJTw+JSBhcnJhbmdlKGNvdW50cnksIGRhdGUpDQpuIDwtIG5yb3coZGF0YSkNCmRheTEgPC0gbWluKGRhdGEkZGF0ZSkNCmRhdGEgJTw+JSBtdXRhdGUobmV3LmNvbmZpcm1lZCA9IGlmZWxzZShkYXRlID09IGRheTEsIE5BLCBjb25maXJtZWQgLSBsYWcoY29uZmlybWVkLCBuPTEpKSwNCiAgICAgICAgICAgICAgICAgbmV3LmRlYXRocyA9IGlmZWxzZShkYXRlID09IGRheTEsIE5BLCBkZWF0aHMgLSBsYWcoZGVhdGhzLCBuPTEpKSwNCiAgICAgICAgICAgICAgICAgbmV3LnJlY292ZXJlZCA9IGlmZWxzZShkYXRlID09IGRheTEsIE5BLCByZWNvdmVyZWQgLSBsYWcocmVjb3ZlcmVkLCBuPTEpKSkNCmRhdGEgJTw+JSBtdXRhdGUobmV3LmNvbmZpcm1lZCA9IGlmZWxzZShuZXcuY29uZmlybWVkIDwgMCwgMCwgbmV3LmNvbmZpcm1lZCksDQogICAgICAgICAgICAgICAgIG5ldy5kZWF0aHMgPSBpZmVsc2UobmV3LmRlYXRocyA8IDAsIDAsIG5ldy5kZWF0aHMpLA0KICAgICAgICAgICAgICAgICBuZXcucmVjb3ZlcmVkID0gaWZlbHNlKG5ldy5yZWNvdmVyZWQgPCAwLCAwLCBuZXcucmVjb3ZlcmVkKSkNCg0KDQpkYiA8LSBkYXRhDQoNCiMnICMjIFNlbGVjaW9uYW5kbyBvIFBhw61zDQojKyBlY2hvPVQsIGZpZy5oZWlnaHQ9NywgZmlnLndpZHRoPTEwLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFDQoNCmJyeiA8LSBkYiAlPiUgYXJyYW5nZSgoZGF0ZSkpICU+JSBmaWx0ZXIoY291bnRyeT09J0JyYXppbCcpIA0KDQpicnogJT4lIGthYmxlKCJwYW5kb2MiKQ0KDQojJyAjIyBDcmlhbmRvIGEgbcOpZGlhIG1vdmVsIGNvbSBvcyBkYWRvcyBkacOhcmlvcw0KIysgZWNobz1ULCBmaWcuaGVpZ2h0PTcsIGZpZy53aWR0aD0xMCwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRQ0KDQpJbmZlY3RhZG9zIDwtIGMoYnJ6JG5ldy5kZWF0aHMpDQppbmljaW8gPC0gbWluKGJyeiRkYXRlKQ0KZGlhIDwtIDE6KGxlbmd0aChJbmZlY3RhZG9zKSkNCkRheSA8LSBpbmljaW8rZGlhDQoNCmFiIDwtIHpvbyhJbmZlY3RhZG9zLCBzZXEoZnJvbSA9IChpbmljaW8pLCB0byA9IGxhc3QoYnJ6JGRhdGUpLCBieSA9IDEpKQ0Kc20gPC0gbWEoYWIsb3JkZXI9NykgIyA3IGRpYXMNCg0KYnJ6JG1tIDwtIHNtDQpuYW1lcyhicnopWzEwXSA8LSAibW0iDQoNCiMnICMjIEdyw6FmaWNvIGRhIE3DqWRpYSBNw7N2ZWwNCiMrIGVjaG89VCwgZmlnLmhlaWdodD03LCBmaWcud2lkdGg9MTAsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0UNCg0KYnJ6ICU+JSBnZ3Bsb3QoKSArIGdlb21fYmFyKGFlcyh4PWRhdGUsIHk9bmV3LmRlYXRocywgZmlsbD0iQ2Fzb3MiKSwgc3RhdCA9ICJpZGVudGl0eSIsIHBvc2l0aW9uID0gcG9zaXRpb25fZG9kZ2UoMSkpKw0KICBnZ3RpdGxlKHBhc3RlKGJyeiRjb3VudHJ5WzFdKSkgKw0KICBsYWJzKHN1YnRpdGxlID0gcGFzdGUoIk3DqWRpYSBtw7N2ZWwgZGUgNyBkaWFzID0gIixyb3VuZChsYXN0KG5hLm9taXQoc20pKSwwKSwgIsOzYml0b3MiKSkgKw0KICBnZW9tX2xpbmUoYWVzKHg9ZGF0ZSx5PW1tLCBmaWxsPSJNw6lkaWEgTW92ZWwiKSwgY29sb3I9ImJsdWUiLCBzaXplPTEuNSkgKyANCiMgIHlsaW0oMCwgMTUwKSsNCiAgeWxhYigiw5NiaXRvcyIpICsgDQogIHhsYWIoIiIpKw0KICBzY2FsZV94X2RhdGUoDQogICAgZGF0ZV9taW5vcl9icmVha3MgPSAiMSBkYXkiLA0KICAgIGJyZWFrcyA9ICIyIHdlZWsiLA0KICAgIGRhdGVfbGFiZWxzID0gIiVkLSViLSVZIikgKyANCiAgdGhlbWVfY2xhc3NpYygpICsgDQogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIiwNCiAgICB0ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMCksDQogICAgICAgIGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gNDUsIGhqdXN0ID0gMSkpIA0KDQoNCiMnIA0KIysgZWNobz1GLCBmaWcuaGVpZ2h0PTcsIGZpZy53aWR0aD0xMCwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRQ0KDQoNCiMgYnJ0IDwtIGJyeiAlPiUgc2VsZWN0KHBvcCwgZGF0ZSwNCiMgICAgICAgICAgbmV3LmNvbmZpcm1lZCwNCiMgICAgICAgICAgcmVjb3ZlcmVkLCBuZXcuZGVhdGhzKSAlPiUNCiMgICBtdXRhdGUobmV3LmNvbmZpcm1lZC5wb3AgPSAobmV3LmNvbmZpcm1lZC9wb3AqMTAwMCAlPiUgcm91bmQoMCkpLA0KIyAgICAgICAgICBuZXcuZGVhdGhzLnBvcCA9IChuZXcuZGVhdGhzL3BvcCoxMDAwICU+JSByb3VuZCgwKSkpIA0KIyANCiMgDQojIEluZmVjdGFkb3MyIDwtIGMoYnJ0JG5ldy5kZWF0aHMucG9wKQ0KIyBpbmljaW8gPC0gbWluKGJydCRkYXRlKQ0KIyBkaWEgPC0gMToobGVuZ3RoKEluZmVjdGFkb3MyKSkNCiMgRGF5IDwtIGluaWNpbytkaWENCiMgDQojIGFiMiA8LSB6b28oSW5mZWN0YWRvczIsIHNlcShmcm9tID0gaW5pY2lvLCB0byA9IGxhc3QoRGF5KSwgYnkgPSAxKSkNCiMgDQojIHNtMiA8LSBtYShhYjIsb3JkZXI9NykNCiMgDQojIGJydCRtbSA8LSBzbTJbLTFdDQojIG5hbWVzKGJydClbOF0gPC0gIm1tIg0KIyANCiMgYnJ0ICU+JSBnZ3Bsb3QoKSArIGdlb21fYmFyKGFlcyh4PWRhdGUsIHk9bmV3LmRlYXRocy5wb3AsIGZpbGw9IkNhc29zIiksIHN0YXQgPSAiaWRlbnRpdHkiLCBwb3NpdGlvbiA9ICJkb2RnZSIpKw0KIyAgIGdndGl0bGUoIkJyYXNpbCIpICsNCiMgICBsYWJzKHN1YnRpdGxlID0gcGFzdGUoIk3DqWRpYSBtw7N2ZWwgZGUgNyBkaWFzID0gIixyb3VuZChsYXN0KG5hLm9taXQoc20yKSksMCksICLDs2JpdG9zIikpICsNCiMgIGdlb21fbGluZShhZXMoeD1kYXRlLHk9bW0sIGZpbGw9Ik3DqWRpYSBNb3ZlbCIpLCBjb2xvcj0iYmx1ZSIpICsgDQojICMgIHlsaW0oMCwgMTUwKSsNCiMgICB5bGFiKCLDk2JpdG9zIikgKyANCiMgICB4bGFiKCIiKSsNCiMgICBzY2FsZV94X2RhdGUoDQojICAgICBkYXRlX21pbm9yX2JyZWFrcyA9ICIxIGRheSIsDQojICAgICBicmVha3MgPSAiMSBtb250aCIsDQojICAgICBkYXRlX2xhYmVscyA9ICIlYi0lWSIpICsgDQojICAgdGhlbWVfY2xhc3NpYygpICsgDQojICAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiLA0KIyAgICAgICAgIHRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEwKSwNCiMgICAgICAgICBheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDQ1LCBoanVzdCA9IDEpKSANCg0KIycgIyMgQmFpeGFyIGRhZG9zIENPVklELUJSDQojKyBlY2hvPVQsIGZpZy5oZWlnaHQ9NywgZmlnLndpZHRoPTEwLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFDQoNCmdldF9jb3IgPC0gZnVuY3Rpb24gKGRpciA9ICJvdXRwdXRzIiwgZmlsZW5hbWUgPSAiY29yb25hX2JyYXNpbCIsIA0KICAgICAgICAgICAgICAgICAgICAgY2lkYWRlID0gTlVMTCwgdWYgPSBOVUxMLCBpYmdlX2NvZCA9IE5VTEwsIGJ5X3VmID0gRkFMU0UsIA0KICAgICAgICAgICAgICAgICAgICAgc2F2ZSA9IFRSVUUpIA0Kew0KICByZXMgPC0gcmVhZHI6OnJlYWRfY3N2KCJodHRwczovL2RhdGEuYnJhc2lsLmlvL2RhdGFzZXQvY292aWQxOS9jYXNvX2Z1bGwuY3N2Lmd6IikNCiAgcmVzJGRhdGUgPC0gYXMuRGF0ZShyZXMkZGF0ZSkNCiAgbWV0YWRhZG8gPC0gZGF0YS5mcmFtZShpbnRlcnZhbG8gPSBwYXN0ZShyYW5nZShyZXMkZGF0ZSksIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbGxhcHNlID0gIjsiKSwgZm9udGUgPSAiaHR0cHM6Ly9kYXRhLmJyYXNpbC5pby9kYXRhc2V0L2NvdmlkMTkvIiwgDQogICAgICAgICAgICAgICAgICAgICAgICAgYWNlc3NvX2VtID0gU3lzLkRhdGUoKSkNCiAgaWYgKCFpcy5udWxsKGNpZGFkZSkgJiBpcy5udWxsKHVmKSkgew0KICAgIHN0b3AoIlByZWNpc2EgZm9ybmVjZXIgdW0gZXN0YWRvIHBhcmEgZXZpdGFyIGFtYmlndWlkYWRlIikNCiAgfQ0KICBpZiAoIWlzLm51bGwoY2lkYWRlKSkgew0KICAgIGlmIChzdW0oIWNpZGFkZSAlaW4lIHVuaXF1ZShyZXMkY2l0eSkpID4gMCkgew0KICAgICAgc3RvcCgiYWxndW0gbm9tZSBkZSBtdW5pY2lwaW8gZW0gJ2NpdHknIGludmFsaWRvIG91IGFpbmRhIG5hbyBoYSBkYWRvcy9jYXNvcyBwYXJhIGVzc2EgY2lkYWRlIikNCiAgICB9DQogICAgaWYgKHN1bSghdWYgJWluJSB1bmlxdWUocmVzJHN0YXRlKSA+IDApKSB7DQogICAgICBzdG9wKCJhbGd1bSBub21lIGRlIGVzdGFkbyBlbSAnc3RhdGUnIGludmFsaWRvIG91IGFpbmRhIG5hbyBoYSBkYWRvcy9jYXNvcyBwYXJhIGVzc2EgY2lkYWRlIikNCiAgICB9DQogICAgaWYgKCFpcy5udWxsKGNpZGFkZSkgJiAhaXMubnVsbCh1ZikpIHsNCiAgICAgIHJlcyA8LSByZXMgJT4lIGRwbHlyOjpmaWx0ZXIoLmRhdGEkc3RhdGUgJWluJSB1ZiAmIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC5kYXRhJGNpdHkgJWluJSBjaWRhZGUpDQogICAgfQ0KICB9DQogIGVsc2Ugew0KICAgIHJlcyA8LSByZXMNCiAgfQ0KICBpZiAoIWlzLm51bGwoaWJnZV9jb2QpKSB7DQogICAgaWYgKHN1bSghaWJnZV9jb2QgJWluJSB1bmlxdWUocmVzJGNpdHlfaWJnZV9jb2RlKSkgPiANCiAgICAgICAgMCkgew0KICAgICAgc3RvcCgiYWxndW0gY29kaWdvIGRlIG11bmljaXBpbyBvdSBlc3RhZG8gJ2liZ2VfY29kZScgaW52YWxpZG8iKQ0KICAgIH0NCiAgICBlbHNlIHsNCiAgICAgIHJlcyA8LSByZXMgJT4lIGRwbHlyOjpmaWx0ZXIoLmRhdGEkY2l0eV9pYmdlX2NvZGUgJWluJSANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpYmdlX2NvZCkNCiAgICB9DQogIH0NCiAgZWxzZSB7DQogICAgcmVzIDwtIHJlcw0KICB9DQogIGlmIChpcy5udWxsKGNpZGFkZSkgJiBpcy5udWxsKGliZ2VfY29kKSAmICFpcy5udWxsKHVmKSkgew0KICAgIHJlcyA8LSByZXMgJT4lIGRwbHlyOjpmaWx0ZXIoLmRhdGEkc3RhdGUgJWluJSB1ZikNCiAgfQ0KICBpZiAoaXMubnVsbChjaWRhZGUpICYgaXMubnVsbChpYmdlX2NvZCkgJiBpcy5udWxsKHVmKSkgew0KICAgIHJlcyA8LSByZXMNCiAgfQ0KICBpZiAoYnlfdWYgPT0gVFJVRSkgew0KICAgIHJlcyA8LSByZXMgJT4lIGZpbHRlciguZGF0YSRwbGFjZV90eXBlID09ICJzdGF0ZSIpDQogIH0NCiAgcmVzJGRhdGUgPC0gYXMuRGF0ZShyZXMkZGF0ZSkNCiAgcmVzJHN0YXRlIDwtIGFzLmZhY3RvcihyZXMkc3RhdGUpDQogIGlmIChzYXZlKSB7DQogICAgbWVzc2FnZShwYXN0ZTAoInNhbHZhbmRvICIsIGZpbGVuYW1lLCAiLmNzdiBlbSAiLCANCiAgICAgICAgICAgICAgICAgICBkaXIpKQ0KICAgIGlmICghZGlyLmV4aXN0cyhkaXIpKSANCiAgICAgIGRpci5jcmVhdGUoZGlyKQ0KICAgIHV0aWxzOjp3cml0ZS5jc3YocmVzLCBwYXN0ZTAoZGlyLCAiLyIsIGZpbGVuYW1lLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICIuY3N2IiksIHJvdy5uYW1lcyA9IEZBTFNFKQ0KICAgIHV0aWxzOjp3cml0ZS5jc3YobWV0YWRhZG8sIHBhc3RlMChkaXIsICIvIiwgZmlsZW5hbWUsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiX21ldGFkYWRvIiwgIi5jc3YiKSwgcm93Lm5hbWVzID0gRkFMU0UpDQogIH0NCiAgcmV0dXJuKHJlcykNCn0NCg0KZGFkIDwtIGdldF9jb3IoKQ0KDQoNCiMnICMjIFNlbGVjaW9uYW5kbyBvIEVzdGFkbw0KIysgZWNobz1ULCBmaWcuaGVpZ2h0PTcsIGZpZy53aWR0aD0xMCwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRQ0KDQpzdDIgPC0gc3Vic2V0KGRhZCwgcGxhY2VfdHlwZSA9PSAic3RhdGUiKQ0Kc3QyJHN0YXRlIDwtIGljb252KHN0MiRzdGF0ZSwgIlVURi04IikNCg0KDQpzdDIgJTw+JSBncm91cF9ieShzdGF0ZSkgJT4lIG11dGF0ZShjdW1fY2FzZXMgPSBjdW1zdW0obGFzdF9hdmFpbGFibGVfY29uZmlybWVkKSkNCg0KQkEgPC0gc3QyICU+JSBmaWx0ZXIoc3RhdGUgPT0gIkJBIikgJT4lIGFycmFuZ2UoZGF0ZSkNCkJBbiA8LSAgQkEgJT4lDQogIHNlbGVjdChjKHN0YXRlLCBkYXRlLCBuZXdfZGVhdGhzKSkgJT4lIGFycmFuZ2UoZGF0ZSkgJT4lDQogIGdhdGhlcihrZXk9dHlwZSwgdmFsdWU9Y291bnQsIC1jKHN0YXRlLCBkYXRlKSkNCg0KDQpJbmZlY3RhZG9zIDwtIEJBbiRjb3VudA0KaW5pY2lvIDwtIG1pbihCQW4kZGF0ZSkNCmRpYSA8LSAxOihsZW5ndGgoSW5mZWN0YWRvcykpDQpEYXkgPC0gaW5pY2lvK2RpYQ0KDQoNCmFiIDwtIHpvbyhJbmZlY3RhZG9zLCBzZXEoZnJvbSA9IGluaWNpbywgdG8gPSBsYXN0KEJBbiRkYXRlKSwgYnkgPSAxKSkNCg0Kc20gPC0gbWEoYWIsb3JkZXI9NykNCkJBbiRtbSA8LSBzbQ0KbmFtZXMoQkFuKVs1XSA8LSAibW0iDQoNCg0KIycgIyMgR3LDoWZpY28gZGEgTcOpZGlhIE3Ds3ZlbCBkbyBFc3RhZG8NCiMrIGVjaG89VCwgZmlnLmhlaWdodD03LCBmaWcud2lkdGg9MTAsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0UNCg0KQkFuICU+JSBnZ3Bsb3QoKSArIGdlb21fYmFyKGFlcyh4PWRhdGUsIHk9Y291bnQsIGZpbGw9IkNhc29zIiksIHN0YXQgPSAiaWRlbnRpdHkiLCBwb3NpdGlvbiA9IHBvc2l0aW9uX2RvZGdlKDEpKSsNCiAgZ2d0aXRsZShwYXN0ZShCQW4kc3RhdGVbMV0pKSArDQogIGxhYnMoc3VidGl0bGUgPSBwYXN0ZSgiTcOpZGlhIG3Ds3ZlbCBkZSA3IGRpYXMgPSAiLHJvdW5kKGxhc3QobmEub21pdChzbSkpLDApLCAiw7NiaXRvcyIpKSArDQogIGdlb21fbGluZShhZXMoeD1kYXRlLHk9bW0sIGZpbGw9Ik3DqWRpYSBNb3ZlbCIpLCBjb2xvcj0iYmx1ZSIsIHNpemU9MS41KSArIA0KICAjICB5bGltKDAsIDE1MCkrDQogIHlsYWIoIsOTYml0b3MiKSArIA0KICB4bGFiKCIiKSsNCiAgc2NhbGVfeF9kYXRlKA0KICAgIGRhdGVfbWlub3JfYnJlYWtzID0gIjEgZGF5IiwNCiAgICBicmVha3MgPSAiMiB3ZWVrIiwNCiAgICBkYXRlX2xhYmVscyA9ICIlZC0lYi0lWSIpICsgDQogIHRoZW1lX2NsYXNzaWMoKSArIA0KICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAibm9uZSIsDQogICAgICAgIHRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEwKSwNCiAgICAgICAgYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA0NSwgaGp1c3QgPSAxKSkgDQoNCg0KDQoNCiMnICMjIFNlbGVjaW9uYW5kbyBvIE11bmljw61waW8NCiMrIGVjaG89VCwgZmlnLmhlaWdodD03LCBmaWcud2lkdGg9MTAsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0UNCg0KDQppb3MyIDwtIGRhZCAlPiUgZmlsdGVyKGNpdHkgPT0gIklsaMOpdXMiKSAlPiUgYXJyYW5nZShkYXRlKQ0KDQppb3NuIDwtICBpb3MyICU+JQ0KICBzZWxlY3QoYyhjaXR5LCBkYXRlLCBuZXdfY29uZmlybWVkKSkgJT4lIGFycmFuZ2UoZGF0ZSkgJT4lDQogIGdhdGhlcihrZXk9dHlwZSwgdmFsdWU9Y291bnQsIC1jKGNpdHksIGRhdGUpKQ0KDQpJbmZlY3RhZG9zIDwtIGlvc24kY291bnQNCmluaWNpbyA8LSBtaW4oaW9zbiRkYXRlKQ0KZGlhIDwtIDE6KGxlbmd0aChJbmZlY3RhZG9zKSkNCkRheSA8LSBpbmljaW8rZGlhDQoNCg0KYWIgPC0gem9vKEluZmVjdGFkb3MsIHNlcShmcm9tID0gaW5pY2lvLCB0byA9IGxhc3QoaW9zbiRkYXRlKSwgYnkgPSAxKSkNCg0Kc20gPC0gbWEoYWIsb3JkZXI9NykNCg0KaW9zbiRtbSA8LSBzbQ0KbmFtZXMoaW9zbilbNV0gPC0gIm1tIg0KDQoNCiMnICMjIEdyw6FmaWNvIGRhIE3DqWRpYSBNw7N2ZWwgZGUgSWxow6l1cw0KIysgZWNobz1ULCBmaWcuaGVpZ2h0PTcsIGZpZy53aWR0aD0xMCwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRQ0KDQppb3NuICU+JSBnZ3Bsb3QoKSArIGdlb21fYmFyKGFlcyh4PWRhdGUsIHk9Y291bnQsIGZpbGw9IkNhc29zIiksIHN0YXQgPSAiaWRlbnRpdHkiLCBwb3NpdGlvbiA9IHBvc2l0aW9uX2RvZGdlKDEpKSsNCiAgZ2d0aXRsZShwYXN0ZShpb3NuJGNpdHlbMV0pKSArDQogIGxhYnMoc3VidGl0bGUgPSBwYXN0ZSgiTcOpZGlhIG3Ds3ZlbCBkZSA3IGRpYXMgPSAiLHJvdW5kKGxhc3QobmEub21pdChzbSkpLDApLCAiY2Fzb3MiKSwNCiAgICAgICBjYXB0aW9uID0gcGFzdGUoIkNpZCBQw7N2b2FzIEBjaWRlZHNvbiBcbiBGb250ZTogU2VjcmV0YXJpYSBkZSBTYcO6ZGUgZG8gRXN0YWRvIC0gIiwgaW9zMiRzdGF0ZSkpICsNCiAgZ2VvbV9saW5lKGFlcyh4PWRhdGUseT1tbSwgZmlsbD0iTcOpZGlhIE1vdmVsIiksIGNvbG9yPSJibHVlIiwgc2l6ZT0xLjUpICsgDQogIHlsaW0oMCwgcm91bmQobWF4KGlvc24kY291bnQsIG5hLnJtPVQpLDApKSsNCiAgeWxhYigiQ2Fzb3MiKSArIA0KICB4bGFiKCIiKSsNCiAgc2NhbGVfeF9kYXRlKA0KICAgIGRhdGVfbWlub3JfYnJlYWtzID0gIjEgZGF5IiwNCiAgICBicmVha3MgPSAiMiB3ZWVrIiwNCiAgICBkYXRlX2xhYmVscyA9ICIlZC0lYi0lWSIpICsgDQogIHRoZW1lX2NsYXNzaWMoKSArIA0KICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAibm9uZSIsDQogICAgICAgIHRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEwKSwNCiAgICAgICAgYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA0NSwgaGp1c3QgPSAxKSkgDQoNCg==