EQUIPO 6
Alexa Mariana Marin Villar A00831342
Diego Martínez Ruibal A01740559
Oscar Emiliano Melendez Chavez A01276802
Librerias
#install.packages("maps")
library(maps)
library(readr)
library(dplyr)
library(forecast)
library(tidyverse)
library(janitor)
library(here)
library(plotly)
Ejemplo
El ejemplo con la librería maps no está funcionando, pero con fines
prácticos de la actividad se agregó el código.
#library(maps)
#map(database = "state", fill = TRUE, col = "lightgray") # Añade colores de fondo
#grupo1 <- c("New York", "California", "Texas")
#map(database = "state", regions = grupo1, col = "red", fill = TRUE, add = TRUE)
#grupo2 <- c("Arizona", "Florida", "Illinois")
#map(database = "state", regions = grupo2, col = "green", fill = TRUE, add = TRUE)
Generar base de datos del tipo panel

La base de datos cuenta con la información anual de los estados de
Estados Unidos desde 1900 hasta 2019.
mapa <- read_csv("C:/Users/alexa/OneDrive/Desktop/8VO/MODULO 1/historical_state_population_by_year.csv",
col_names = FALSE)
mapa<- mapa %>%
rename(estate = X1, year = X2, population = X3)
Resumen de los datos
La base de datos consta de 3 variables y 6,020 observaciones. El
mínimo de años recabados es desde 1900 hasta 2019, mientras que el
mínimo de población consta de 43,000 con un máximo de 39,512,223.
glimpse(mapa)
## Rows: 6,020
## Columns: 3
## $ estate <chr> "AK", "AK", "AK", "AK", "AK", "AK", "AK", "AK", "AK", "AK",…
## $ year <dbl> 1950, 1951, 1952, 1953, 1954, 1955, 1956, 1957, 1958, 1959,…
## $ population <dbl> 135000, 158000, 189000, 205000, 215000, 222000, 224000, 231…
summary(mapa)
## estate year population
## Length:6020 Min. :1900 Min. : 43000
## Class :character 1st Qu.:1930 1st Qu.: 901483
## Mode :character Median :1960 Median : 2359000
## Mean :1960 Mean : 3726003
## 3rd Qu.:1990 3rd Qu.: 4541883
## Max. :2019 Max. :39512223
Filtro de solo los estados a analizar
En este caso decidimos analizar los estados de:
California
Nueva York
Florida
Wyoming
Texas
california <- filter(mapa, estate =="CA")
newyork <- filter(mapa, estate =="NY")
florida <- filter(mapa, estate =="FL")
wyoming <- filter(mapa, estate =="WY")
texas <- filter(mapa, estate =="TX")
Crear modelo de series de tiempo
california$population <- as.numeric(california$population)
tscalifornia <- ts(data = california$population, start=c(1900,1),end=c(2019,1),frequency=1)
newyork$population <- as.numeric(newyork$population)
tsnewyork <- ts(data = newyork$population, start=c(1900,1),end=c(2019,1),frequency=1)
florida$population <- as.numeric(florida$population)
tsflorida <- ts(data = florida$population, start=c(1900,1),end=c(2019,1),frequency=1)
wyoming$population <- as.numeric(wyoming$population)
tswyoming <- ts(data = wyoming$population, start=c(1900,1),end=c(2019,1),frequency=1)
texas$population <- as.numeric(texas$population)
tstexas <- ts(data = texas$population, start=c(1900,1),end=c(2019,1),frequency=1)
Modelo ARIMA
Con fines del formato del documento, se decidió ejecutar el código,
pero no mostrar el resultado del modelo ARIMA por estado.
arimacali <- auto.arima(tscalifornia, D=1)
summary(arimacali)
arimany <- auto.arima(tsnewyork, D=1)
summary(arimany)
arimaflo <- auto.arima(tsflorida, D=1)
summary(arimaflo)
arimawy <- auto.arima(tswyoming, D=1)
summary(arimawy)
arimatx <- auto.arima(tstexas, D=1)
summary(arimatx)
Generar el pronóstico
pronosticocali <- forecast(arimacali,level=c(95), h=51)
pronosticony <- forecast(arimany,level=c(95), h=51)
pronosticoflorida <- forecast(arimaflo,level=c(95), h=51)
pronosticowyoming <- forecast(arimawy,level=c(95), h=51)
pronosticotx <- forecast(arimatx,level=c(95), h=51)
Observar el pronóstico por estado
plot(pronosticocali)

plot(pronosticony)

plot(pronosticoflorida)

plot(pronosticowyoming)

plot(pronosticotx)

Se puede observar un crecimiento positivo en cuanto a la poblacion de
los estados de California,Nueva York, Florida, Wyoming y Texas.
Unir los pronósticos en una sola base de datos
library(dplyr)
# Crear un data frame con los pronósticos y estados correspondientes
pronosticos <- data.frame(
estate = rep(c("CA", "NY", "FL", "WY", "TX"), each = 51),
year = rep(seq(2020, 2070), times = 5),
point_forecast = c(
pronosticocali$mean,
pronosticony$mean,
pronosticoflorida$mean,
pronosticowyoming$mean,
pronosticotx$mean
)
)
# Limpiar nombres de columnas
pronosticos <- pronosticos %>% clean_names()
Visualizaciones
California
Visualizar los años en el mapa
library(maps)
library(plotly)
# Filtra los datos para el estado de California
datos_cali <- subset(pronosticos, estate == "CA")
# Define la escala de colores personalizada
color_scale <- colorRampPalette(c("blue", "lightblue", "lightgreen", "darkgreen", "darkred", "red"))
# Crea un mapa interactivo para cada año deseado
for (ano in c(2020,2030, 2040, 2050, 2060, 2070)) {
datos_ano <- subset(datos_cali, year == ano)
mapa <- plot_ly(
data = datos_ano,
type = "choropleth",
locationmode = "USA-states",
locations = ~estate,
z = ~point_forecast,
colorscale = color_scale(100),
marker = list(line = list(color = "rgb(255,255,255)", width = 2)),
text = ~paste("Estado: ", estate, "<br>Año: ", year, "<br>Población Pronosticada: ", point_forecast),
zmin = min(datos_cali$point_forecast), # Establece el valor mínimo de la escala de colores
zmax = max(datos_cali$point_forecast) # Establece el valor máximo de la escala de colores
) %>%
layout(
title = paste("Población Pronosticada California en", ano),
geo = list(scope = "usa", projection = list(type = "albers usa")),
colorbar = list(title = "Población Pronosticada"),
showlegend = FALSE
)
# Muestra el mapa
print(mapa)
}
Al momento de hacer el ‘knit’ del documento, no se visualizan los
mapas debido al bucle creado para mostrar cada década. Por esta razón y
debido al formato del documento, se decidió adjuntar las imágenes de los
pronósticos del estado de California, pero este resultado se obtiene
para cada estado. Se eligió una escala de colores que muestra el
pronóstico del crecimiento de la población década por década.
Imagen en grande sobre como se observa el pronóstico dentro
del mapa creado

Imagenes juntas para observar de mejor manera la escala y el
crecimiento del pronóstico.


New York
Visualizar los años en el mapa
# Instala y carga las librerías necesarias
# install.packages(c("maps", "plotly"))
library(maps)
library(plotly)
# Filtra los datos para el estado de California
datos_ny <- subset(pronosticos, estate == "NY")
# Define la escala de colores personalizada
color_scale <- colorRampPalette(c("blue", "lightblue", "lightgreen", "darkgreen", "darkred", "red"))
# Crea un mapa interactivo para cada año deseado
for (ano in c(2020,2030, 2040, 2050, 2060, 2070)) {
datos_ano <- subset(datos_ny, year == ano)
mapa <- plot_ly(
data = datos_ano,
type = "choropleth",
locationmode = "USA-states",
locations = ~estate,
z = ~point_forecast,
colorscale = color_scale(100),
marker = list(line = list(color = "rgb(255,255,255)", width = 2)),
text = ~paste("Estado: ", estate, "<br>Año: ", year, "<br>Población Pronosticada: ", point_forecast),
zmin = min(datos_ny$point_forecast), # Establece el valor mínimo de la escala de colores
zmax = max(datos_ny$point_forecast) # Establece el valor máximo de la escala de colores
) %>%
layout(
title = paste("Población Pronosticada Nueva York en", ano),
geo = list(scope = "usa", projection = list(type = "albers usa")),
colorbar = list(title = "Población Pronosticada"),
showlegend = FALSE
)
# Muestra el mapa
print(mapa)
}
Florida
Visualizar los años en el mapa
# Instala y carga las librerías necesarias
# install.packages(c("maps", "plotly"))
library(maps)
library(plotly)
# Filtra los datos para el estado de California
datos_flo <- subset(pronosticos, estate == "FL")
# Define la escala de colores personalizada
color_scale <- colorRampPalette(c("blue", "lightblue", "lightgreen", "darkgreen", "darkred", "red"))
# Crea un mapa interactivo para cada año deseado
for (ano in c(2020,2030, 2040, 2050, 2060, 2070)) {
datos_ano <- subset(datos_flo, year == ano)
mapa <- plot_ly(
data = datos_ano,
type = "choropleth",
locationmode = "USA-states",
locations = ~estate,
z = ~point_forecast,
colorscale = color_scale(100),
marker = list(line = list(color = "rgb(255,255,255)", width = 2)),
text = ~paste("Estado: ", estate, "<br>Año: ", year, "<br>Población Pronosticada: ", point_forecast),
zmin = min(datos_flo$point_forecast), # Establece el valor mínimo de la escala de colores
zmax = max(datos_flo$point_forecast) # Establece el valor máximo de la escala de colores
) %>%
layout(
title = paste("Población Pronosticada Florida en", ano),
geo = list(scope = "usa", projection = list(type = "albers usa")),
colorbar = list(title = "Población Pronosticada"),
showlegend = FALSE
)
# Muestra el mapa
print(mapa)
}
Texas
Visualizar los años en el mapa
library(maps)
library(plotly)
# Filtra los datos para el estado de California
datos_tx <- subset(pronosticos, estate == "TX")
# Define la escala de colores personalizada
color_scale <- colorRampPalette(c("blue", "lightblue", "lightgreen", "darkgreen", "darkred", "red"))
# Crea un mapa interactivo para cada año deseado
for (ano in c(2020,2030, 2040, 2050, 2060, 2070)) {
datos_ano <- subset(datos_tx, year == ano)
mapa <- plot_ly(
data = datos_ano,
type = "choropleth",
locationmode = "USA-states",
locations = ~estate,
z = ~point_forecast,
colorscale = color_scale(100),
marker = list(line = list(color = "rgb(255,255,255)", width = 2)),
text = ~paste("Estado: ", estate, "<br>Año: ", year, "<br>Población Pronosticada: ", point_forecast),
zmin = min(datos_tx$point_forecast), # Establece el valor mínimo de la escala de colores
zmax = max(datos_tx$point_forecast) # Establece el valor máximo de la escala de colores
) %>%
layout(
title = paste("Población Pronosticada Texas en", ano),
geo = list(scope = "usa", projection = list(type = "albers usa")),
colorbar = list(title = "Población Pronosticada"),
showlegend = FALSE
)
# Muestra el mapa
print(mapa)
}
Wyoming
Visualizar los años en el mapa
library(maps)
library(plotly)
# Filtra los datos para el estado de California
datos_wo <- subset(pronosticos, estate == "WY")
# Define la escala de colores personalizada
color_scale <- colorRampPalette(c("blue", "lightblue", "lightgreen", "darkgreen", "darkred", "red"))
# Crea un mapa interactivo para cada año deseado
for (ano in c(2020,2030, 2040, 2050, 2060, 2070)) {
datos_ano <- subset(datos_wo, year == ano)
mapa <- plot_ly(
data = datos_ano,
type = "choropleth",
locationmode = "USA-states",
locations = ~estate,
z = ~point_forecast,
colorscale = color_scale(100),
marker = list(line = list(color = "rgb(255,255,255)", width = 2)),
text = ~paste("Estado: ", estate, "<br>Año: ", year, "<br>Población Pronosticada: ", point_forecast),
zmin = min(datos_wo$point_forecast), # Establece el valor mínimo de la escala de colores
zmax = max(datos_wo$point_forecast) # Establece el valor máximo de la escala de colores
) %>%
layout(
title = paste("Población Pronosticada Wyoming en", ano),
geo = list(scope = "usa", projection = list(type = "albers usa")),
colorbar = list(title = "Población Pronosticada"),
showlegend = FALSE
)
# Muestra el mapa
print(mapa)
}
LS0tDQp0aXRsZTogIkFjdGl2aWRhZCBJbnRlZ3JhZG9yYSINCmRhdGU6ICJgciBTeXMuRGF0ZSgpYCINCm91dHB1dDoNCiAgcm1kZm9ybWF0czo6ZG93bmN1dGU6DQogICAgZGVmYXVsdF9zdHlsZTogImxpZ2h0Ig0KICAgIGRvd25jdXRlX3RoZW1lOiAiZGVmYXVsdCINCiAgICBjb2RlX2Rvd25sb2FkIDogdHJ1ZQ0KICAgIGxpYl9kaXI6IGxpYnMNCiAgICBzZWxmX2NvbnRhaW5lZDogZmFsc2UNCiAgaHRtbF9kb2N1bWVudDoNCiAgICBkZl9wcmludDogcGFnZWQNCi0tLQ0KDQpgYGB7ciBzZXR1cCwgaW5jbHVkZT1GQUxTRX0NCiMjIEdsb2JhbCBvcHRpb25zDQprbml0cjo6b3B0c19jaHVuayRzZXQoY2FjaGUgPSBUUlVFLGVjaG8gPSBUUlVFLHdhcm5pbmcgPSBGQUxTRSxtZXNzYWdlID0gRkFMU0UpDQpgYGANCg0KIyMgKipFUVVJUE8gNioqDQoNCi0gICBBbGV4YSBNYXJpYW5hIE1hcmluIFZpbGxhciBBMDA4MzEzNDINCg0KLSAgIERpZWdvIE1hcnTDrW5leiBSdWliYWwgQTAxNzQwNTU5DQoNCi0gICBPc2NhciBFbWlsaWFubyBNZWxlbmRleiBDaGF2ZXogQTAxMjc2ODAyDQoNCiMjICoqTGlicmVyaWFzKioNCg0KYGBge3J9DQojaW5zdGFsbC5wYWNrYWdlcygibWFwcyIpDQpsaWJyYXJ5KG1hcHMpDQpsaWJyYXJ5KHJlYWRyKQ0KbGlicmFyeShkcGx5cikNCmxpYnJhcnkoZm9yZWNhc3QpDQpsaWJyYXJ5KHRpZHl2ZXJzZSkNCmxpYnJhcnkoamFuaXRvcikNCmxpYnJhcnkoaGVyZSkNCmxpYnJhcnkocGxvdGx5KQ0KYGBgDQoNCiMjICoqRWplbXBsbyoqDQoNCkVsIGVqZW1wbG8gY29uIGxhIGxpYnJlcsOtYSBtYXBzIG5vIGVzdMOhIGZ1bmNpb25hbmRvLCBwZXJvIGNvbiBmaW5lcyBwcsOhY3RpY29zIGRlIGxhIGFjdGl2aWRhZCBzZSBhZ3JlZ8OzIGVsIGPDs2RpZ28uDQoNCmBgYHtyfQ0KI2xpYnJhcnkobWFwcykNCiNtYXAoZGF0YWJhc2UgPSAic3RhdGUiLCBmaWxsID0gVFJVRSwgY29sID0gImxpZ2h0Z3JheSIpICAjIEHDsWFkZSBjb2xvcmVzIGRlIGZvbmRvDQojZ3J1cG8xIDwtIGMoIk5ldyBZb3JrIiwgIkNhbGlmb3JuaWEiLCAiVGV4YXMiKQ0KI21hcChkYXRhYmFzZSA9ICJzdGF0ZSIsIHJlZ2lvbnMgPSBncnVwbzEsIGNvbCA9ICJyZWQiLCBmaWxsID0gVFJVRSwgYWRkID0gVFJVRSkNCiNncnVwbzIgPC0gYygiQXJpem9uYSIsICJGbG9yaWRhIiwgIklsbGlub2lzIikNCiNtYXAoZGF0YWJhc2UgPSAic3RhdGUiLCByZWdpb25zID0gZ3J1cG8yLCBjb2wgPSAiZ3JlZW4iLCBmaWxsID0gVFJVRSwgYWRkID0gVFJVRSkNCmBgYA0KDQojICoqR2VuZXJhciBiYXNlIGRlIGRhdG9zIGRlbCB0aXBvIHBhbmVsKioNCg0KIVtdKGdpcGh5JTIwKDUpLmdpZil7d2lkdGg9IjE4MyJ9DQoNCkxhIGJhc2UgZGUgZGF0b3MgY3VlbnRhIGNvbiBsYSBpbmZvcm1hY2nDs24gYW51YWwgZGUgbG9zIGVzdGFkb3MgZGUgRXN0YWRvcyBVbmlkb3MgZGVzZGUgMTkwMCBoYXN0YSAyMDE5Lg0KDQpgYGB7cn0NCm1hcGEgPC0gIHJlYWRfY3N2KCJDOi9Vc2Vycy9hbGV4YS9PbmVEcml2ZS9EZXNrdG9wLzhWTy9NT0RVTE8gMS9oaXN0b3JpY2FsX3N0YXRlX3BvcHVsYXRpb25fYnlfeWVhci5jc3YiLCANCiAgICBjb2xfbmFtZXMgPSBGQUxTRSkNCg0KbWFwYTwtIG1hcGEgJT4lIA0KICByZW5hbWUoZXN0YXRlID0gWDEsIHllYXIgPSBYMiwgcG9wdWxhdGlvbiA9IFgzKSANCmBgYA0KDQojIyAqKlJlc3VtZW4gZGUgbG9zIGRhdG9zKioNCg0KTGEgYmFzZSBkZSBkYXRvcyBjb25zdGEgZGUgMyB2YXJpYWJsZXMgeSA2LDAyMCBvYnNlcnZhY2lvbmVzLiBFbCBtw61uaW1vIGRlIGHDsW9zIHJlY2FiYWRvcyBlcyBkZXNkZSAxOTAwIGhhc3RhIDIwMTksIG1pZW50cmFzIHF1ZSBlbCBtw61uaW1vIGRlIHBvYmxhY2nDs24gY29uc3RhIGRlIDQzLDAwMCBjb24gdW4gbcOheGltbyBkZSAzOSw1MTIsMjIzLg0KDQpgYGB7cn0NCmdsaW1wc2UobWFwYSkNCnN1bW1hcnkobWFwYSkNCmBgYA0KDQpgYGB7cixpbmNsdWRlPUZBTFNFfQ0KI0ZpbHRyYXIgaW5mb3JtYWNpw7NuIHBvciBlc3RhZG9maWx0cmFyIGVzdGFkbyBwb3IgcGVxdWXDsWEgcG9ibGFjaW9uIHkgZ3JhbmRlIHBvYmxhY2lvbg0KbWFwYTIgPC0gc2VsZWN0KG1hcGEgLGMoMSwzKSkNCg0KcHJvbWVkaW9fcG9yX2VzdGFkbyA8LSBtYXBhMiAlPiUNCiAgZ3JvdXBfYnkoZXN0YXRlKSAlPiUNCiAgc3VtbWFyaXNlKHByb21lZGlvX2NvbHVtbmEgPSBtZWFuKHBvcHVsYXRpb24pKQ0KDQpwcm9tZWRpb19wb3JfZXN0YWRvIDwtIHByb21lZGlvX3Bvcl9lc3RhZG9bb3JkZXIoLXByb21lZGlvX3Bvcl9lc3RhZG8kcHJvbWVkaW9fY29sdW1uYSksIF0NCg0KcHJvbWVkaW9fcG9yX2VzdGFkbw0KDQojbWFwYTIgJT4lIGdyb3VwX2J5KHN1bWFfcG9yX2VzdGFkbykgJT4lIGZpbHRlcihwb3B1bGF0aW9uID4gbWVhbihwb3B1bGF0aW9uLCBuYS5ybSA9IFRSVUUpKQ0KI21hcGEyICU+JSBncm91cF9ieShwcm9tZWRpb19wb3JfZXN0YWRvKSAlPiUgZmlsdGVyKHBvcHVsYXRpb24gPCBtZWFuKHBvcHVsYXRpb24sIG5hLnJtID0gVFJVRSkpDQpgYGANCg0KIyMgKipGaWx0cm8gZGUgc29sbyBsb3MgZXN0YWRvcyBhIGFuYWxpemFyKioNCg0KRW4gZXN0ZSBjYXNvIGRlY2lkaW1vcyBhbmFsaXphciBsb3MgZXN0YWRvcyBkZToNCg0KMS4gICoqQ2FsaWZvcm5pYSoqDQoNCjIuICAqKk51ZXZhIFlvcmsqKg0KDQozLiAgKipGbG9yaWRhKioNCg0KNC4gICoqV3lvbWluZyoqDQoNCjUuICAqKlRleGFzKioNCg0KYGBge3J9DQpjYWxpZm9ybmlhIDwtIGZpbHRlcihtYXBhLCBlc3RhdGUgPT0iQ0EiKQ0KbmV3eW9yayA8LSBmaWx0ZXIobWFwYSwgZXN0YXRlID09Ik5ZIikNCmZsb3JpZGEgPC0gZmlsdGVyKG1hcGEsIGVzdGF0ZSA9PSJGTCIpDQp3eW9taW5nIDwtIGZpbHRlcihtYXBhLCBlc3RhdGUgPT0iV1kiKQ0KdGV4YXMgPC0gZmlsdGVyKG1hcGEsIGVzdGF0ZSA9PSJUWCIpDQpgYGANCg0KIyAqKkNyZWFyIG1vZGVsbyBkZSBzZXJpZXMgZGUgdGllbXBvKioNCg0KYGBge3J9DQpjYWxpZm9ybmlhJHBvcHVsYXRpb24gPC0gYXMubnVtZXJpYyhjYWxpZm9ybmlhJHBvcHVsYXRpb24pDQp0c2NhbGlmb3JuaWEgPC0gdHMoZGF0YSA9IGNhbGlmb3JuaWEkcG9wdWxhdGlvbiwgc3RhcnQ9YygxOTAwLDEpLGVuZD1jKDIwMTksMSksZnJlcXVlbmN5PTEpDQpuZXd5b3JrJHBvcHVsYXRpb24gPC0gYXMubnVtZXJpYyhuZXd5b3JrJHBvcHVsYXRpb24pDQp0c25ld3lvcmsgPC0gdHMoZGF0YSA9IG5ld3lvcmskcG9wdWxhdGlvbiwgc3RhcnQ9YygxOTAwLDEpLGVuZD1jKDIwMTksMSksZnJlcXVlbmN5PTEpDQpmbG9yaWRhJHBvcHVsYXRpb24gPC0gYXMubnVtZXJpYyhmbG9yaWRhJHBvcHVsYXRpb24pDQp0c2Zsb3JpZGEgPC0gdHMoZGF0YSA9IGZsb3JpZGEkcG9wdWxhdGlvbiwgc3RhcnQ9YygxOTAwLDEpLGVuZD1jKDIwMTksMSksZnJlcXVlbmN5PTEpDQp3eW9taW5nJHBvcHVsYXRpb24gPC0gYXMubnVtZXJpYyh3eW9taW5nJHBvcHVsYXRpb24pDQp0c3d5b21pbmcgPC0gdHMoZGF0YSA9IHd5b21pbmckcG9wdWxhdGlvbiwgc3RhcnQ9YygxOTAwLDEpLGVuZD1jKDIwMTksMSksZnJlcXVlbmN5PTEpDQp0ZXhhcyRwb3B1bGF0aW9uIDwtIGFzLm51bWVyaWModGV4YXMkcG9wdWxhdGlvbikNCnRzdGV4YXMgPC0gdHMoZGF0YSA9IHRleGFzJHBvcHVsYXRpb24sIHN0YXJ0PWMoMTkwMCwxKSxlbmQ9YygyMDE5LDEpLGZyZXF1ZW5jeT0xKQ0KYGBgDQoNCiMjICoqTW9kZWxvIEFSSU1BKioNCg0KQ29uIGZpbmVzIGRlbCBmb3JtYXRvIGRlbCBkb2N1bWVudG8sIHNlIGRlY2lkacOzIGVqZWN1dGFyIGVsIGPDs2RpZ28sIHBlcm8gbm8gbW9zdHJhciBlbCByZXN1bHRhZG8gZGVsIG1vZGVsbyBBUklNQSBwb3IgZXN0YWRvLg0KDQpgYGB7cixldmFsPUZBTFNFfQ0KYXJpbWFjYWxpIDwtIGF1dG8uYXJpbWEodHNjYWxpZm9ybmlhLCBEPTEpDQpzdW1tYXJ5KGFyaW1hY2FsaSkNCmFyaW1hbnkgPC0gYXV0by5hcmltYSh0c25ld3lvcmssIEQ9MSkNCnN1bW1hcnkoYXJpbWFueSkNCmFyaW1hZmxvIDwtIGF1dG8uYXJpbWEodHNmbG9yaWRhLCBEPTEpDQpzdW1tYXJ5KGFyaW1hZmxvKQ0KYXJpbWF3eSA8LSBhdXRvLmFyaW1hKHRzd3lvbWluZywgRD0xKQ0Kc3VtbWFyeShhcmltYXd5KQ0KYXJpbWF0eCA8LSBhdXRvLmFyaW1hKHRzdGV4YXMsIEQ9MSkNCnN1bW1hcnkoYXJpbWF0eCkNCmBgYA0KDQojIyAqKkdlbmVyYXIgZWwgcHJvbsOzc3RpY28qKg0KDQpgYGB7cn0NCnByb25vc3RpY29jYWxpIDwtIGZvcmVjYXN0KGFyaW1hY2FsaSxsZXZlbD1jKDk1KSwgaD01MSkNCnByb25vc3RpY29ueSA8LSBmb3JlY2FzdChhcmltYW55LGxldmVsPWMoOTUpLCBoPTUxKQ0KcHJvbm9zdGljb2Zsb3JpZGEgPC0gZm9yZWNhc3QoYXJpbWFmbG8sbGV2ZWw9Yyg5NSksIGg9NTEpDQpwcm9ub3N0aWNvd3lvbWluZyA8LSBmb3JlY2FzdChhcmltYXd5LGxldmVsPWMoOTUpLCBoPTUxKQ0KcHJvbm9zdGljb3R4IDwtIGZvcmVjYXN0KGFyaW1hdHgsbGV2ZWw9Yyg5NSksIGg9NTEpDQpgYGANCg0KIyMgKipPYnNlcnZhciBlbCBwcm9uw7NzdGljbyBwb3IgZXN0YWRvKioNCg0KYGBge3J9DQpwbG90KHByb25vc3RpY29jYWxpKQ0KcGxvdChwcm9ub3N0aWNvbnkpDQpwbG90KHByb25vc3RpY29mbG9yaWRhKQ0KcGxvdChwcm9ub3N0aWNvd3lvbWluZykNCnBsb3QocHJvbm9zdGljb3R4KQ0KYGBgDQoNClNlIHB1ZWRlIG9ic2VydmFyIHVuIGNyZWNpbWllbnRvIHBvc2l0aXZvIGVuIGN1YW50byBhIGxhIHBvYmxhY2lvbiBkZSBsb3MgZXN0YWRvcyBkZSBDYWxpZm9ybmlhLE51ZXZhIFlvcmssIEZsb3JpZGEsIFd5b21pbmcgeSBUZXhhcy4NCg0KIyMgKipVbmlyIGxvcyBwcm9uw7NzdGljb3MgZW4gdW5hIHNvbGEgYmFzZSBkZSBkYXRvcyoqDQoNCmBgYHtyfQ0KbGlicmFyeShkcGx5cikNCg0KIyBDcmVhciB1biBkYXRhIGZyYW1lIGNvbiBsb3MgcHJvbsOzc3RpY29zIHkgZXN0YWRvcyBjb3JyZXNwb25kaWVudGVzDQpwcm9ub3N0aWNvcyA8LSBkYXRhLmZyYW1lKA0KICBlc3RhdGUgPSByZXAoYygiQ0EiLCAiTlkiLCAiRkwiLCAiV1kiLCAiVFgiKSwgZWFjaCA9IDUxKSwNCiAgeWVhciA9IHJlcChzZXEoMjAyMCwgMjA3MCksIHRpbWVzID0gNSksDQogIHBvaW50X2ZvcmVjYXN0ID0gYygNCiAgICBwcm9ub3N0aWNvY2FsaSRtZWFuLA0KICAgIHByb25vc3RpY29ueSRtZWFuLA0KICAgIHByb25vc3RpY29mbG9yaWRhJG1lYW4sDQogICAgcHJvbm9zdGljb3d5b21pbmckbWVhbiwNCiAgICBwcm9ub3N0aWNvdHgkbWVhbg0KICApDQopDQoNCiMgTGltcGlhciBub21icmVzIGRlIGNvbHVtbmFzDQpwcm9ub3N0aWNvcyA8LSBwcm9ub3N0aWNvcyAlPiUgY2xlYW5fbmFtZXMoKQ0KYGBgDQoNCiMgKipWaXN1YWxpemFjaW9uZXMqKg0KDQojIyAqKkNhbGlmb3JuaWEqKg0KDQojIyMgKipWaXN1YWxpemFyIGxvcyBhw7FvcyBlbiBlbCBtYXBhKioNCg0KYGBge3J9DQpsaWJyYXJ5KG1hcHMpDQpsaWJyYXJ5KHBsb3RseSkNCg0KIyBGaWx0cmEgbG9zIGRhdG9zIHBhcmEgZWwgZXN0YWRvIGRlIENhbGlmb3JuaWENCmRhdG9zX2NhbGkgPC0gc3Vic2V0KHByb25vc3RpY29zLCBlc3RhdGUgPT0gIkNBIikNCg0KIyBEZWZpbmUgbGEgZXNjYWxhIGRlIGNvbG9yZXMgcGVyc29uYWxpemFkYQ0KY29sb3Jfc2NhbGUgPC0gY29sb3JSYW1wUGFsZXR0ZShjKCJibHVlIiwgImxpZ2h0Ymx1ZSIsICJsaWdodGdyZWVuIiwgImRhcmtncmVlbiIsICJkYXJrcmVkIiwgInJlZCIpKQ0KDQojIENyZWEgdW4gbWFwYSBpbnRlcmFjdGl2byBwYXJhIGNhZGEgYcOxbyBkZXNlYWRvDQpmb3IgKGFubyBpbiBjKDIwMjAsMjAzMCwgMjA0MCwgMjA1MCwgMjA2MCwgMjA3MCkpIHsNCiAgZGF0b3NfYW5vIDwtIHN1YnNldChkYXRvc19jYWxpLCB5ZWFyID09IGFubykNCiAgDQogIG1hcGEgPC0gcGxvdF9seSgNCiAgICBkYXRhID0gZGF0b3NfYW5vLA0KICAgIHR5cGUgPSAiY2hvcm9wbGV0aCIsDQogICAgbG9jYXRpb25tb2RlID0gIlVTQS1zdGF0ZXMiLA0KICAgIGxvY2F0aW9ucyA9IH5lc3RhdGUsDQogICAgeiA9IH5wb2ludF9mb3JlY2FzdCwNCiAgICBjb2xvcnNjYWxlID0gY29sb3Jfc2NhbGUoMTAwKSwNCiAgICBtYXJrZXIgPSBsaXN0KGxpbmUgPSBsaXN0KGNvbG9yID0gInJnYigyNTUsMjU1LDI1NSkiLCB3aWR0aCA9IDIpKSwNCiAgICB0ZXh0ID0gfnBhc3RlKCJFc3RhZG86ICIsIGVzdGF0ZSwgIjxicj5Bw7FvOiAiLCB5ZWFyLCAiPGJyPlBvYmxhY2nDs24gUHJvbm9zdGljYWRhOiAiLCBwb2ludF9mb3JlY2FzdCksDQogICAgem1pbiA9IG1pbihkYXRvc19jYWxpJHBvaW50X2ZvcmVjYXN0KSwgICMgRXN0YWJsZWNlIGVsIHZhbG9yIG3DrW5pbW8gZGUgbGEgZXNjYWxhIGRlIGNvbG9yZXMNCiAgICB6bWF4ID0gbWF4KGRhdG9zX2NhbGkkcG9pbnRfZm9yZWNhc3QpICAgIyBFc3RhYmxlY2UgZWwgdmFsb3IgbcOheGltbyBkZSBsYSBlc2NhbGEgZGUgY29sb3Jlcw0KICApICU+JQ0KICAgIGxheW91dCgNCiAgICAgIHRpdGxlID0gcGFzdGUoIlBvYmxhY2nDs24gUHJvbm9zdGljYWRhIENhbGlmb3JuaWEgZW4iLCBhbm8pLA0KICAgICAgZ2VvID0gbGlzdChzY29wZSA9ICJ1c2EiLCBwcm9qZWN0aW9uID0gbGlzdCh0eXBlID0gImFsYmVycyB1c2EiKSksDQogICAgICBjb2xvcmJhciA9IGxpc3QodGl0bGUgPSAiUG9ibGFjacOzbiBQcm9ub3N0aWNhZGEiKSwNCiAgICAgIHNob3dsZWdlbmQgPSBGQUxTRQ0KICAgICkNCiAgDQogICMgTXVlc3RyYSBlbCBtYXBhDQogIHByaW50KG1hcGEpDQp9DQoNCmBgYA0KDQpBbCBtb21lbnRvIGRlIGhhY2VyIGVsICdrbml0JyBkZWwgZG9jdW1lbnRvLCBubyBzZSB2aXN1YWxpemFuIGxvcyBtYXBhcyBkZWJpZG8gYWwgYnVjbGUgY3JlYWRvIHBhcmEgbW9zdHJhciBjYWRhIGTDqWNhZGEuIFBvciBlc3RhIHJhesOzbiB5IGRlYmlkbyBhbCBmb3JtYXRvIGRlbCBkb2N1bWVudG8sIHNlIGRlY2lkacOzIGFkanVudGFyIGxhcyBpbcOhZ2VuZXMgZGUgbG9zIHByb27Ds3N0aWNvcyBkZWwgZXN0YWRvIGRlIENhbGlmb3JuaWEsIHBlcm8gZXN0ZSByZXN1bHRhZG8gc2Ugb2J0aWVuZSBwYXJhIGNhZGEgZXN0YWRvLiBTZSBlbGlnacOzIHVuYSBlc2NhbGEgZGUgY29sb3JlcyBxdWUgbXVlc3RyYSBlbCBwcm9uw7NzdGljbyBkZWwgY3JlY2ltaWVudG8gZGUgbGEgcG9ibGFjacOzbiBkw6ljYWRhIHBvciBkw6ljYWRhLg0KDQojIyMgKipJbWFnZW4gZW4gZ3JhbmRlIHNvYnJlIGNvbW8gc2Ugb2JzZXJ2YSBlbCBwcm9uw7NzdGljbyBkZW50cm8gZGVsIG1hcGEgY3JlYWRvKioNCg0KIVtdKGltYWdlcy9TY3JlZW5zaG90JTIwMjAyNC0wMi0yMyUyMDA3MDE1Ni5wbmcpDQoNCiMjIyAqKkltYWdlbmVzIGp1bnRhcyBwYXJhIG9ic2VydmFyIGRlIG1lam9yIG1hbmVyYSBsYSBlc2NhbGEgeSBlbCBjcmVjaW1pZW50byBkZWwgcHJvbsOzc3RpY28uKioNCg0KIVtdKDEucG5nKQ0KDQohW10oMi5wbmcpDQoNCiMjICoqTmV3IFlvcmsqKg0KDQojIyMgKipWaXN1YWxpemFyIGxvcyBhw7FvcyBlbiBlbCBtYXBhKioNCg0KYGBge3J9DQojIEluc3RhbGEgeSBjYXJnYSBsYXMgbGlicmVyw61hcyBuZWNlc2FyaWFzDQojIGluc3RhbGwucGFja2FnZXMoYygibWFwcyIsICJwbG90bHkiKSkNCmxpYnJhcnkobWFwcykNCmxpYnJhcnkocGxvdGx5KQ0KDQojIEZpbHRyYSBsb3MgZGF0b3MgcGFyYSBlbCBlc3RhZG8gZGUgQ2FsaWZvcm5pYQ0KZGF0b3NfbnkgPC0gc3Vic2V0KHByb25vc3RpY29zLCBlc3RhdGUgPT0gIk5ZIikNCg0KIyBEZWZpbmUgbGEgZXNjYWxhIGRlIGNvbG9yZXMgcGVyc29uYWxpemFkYQ0KY29sb3Jfc2NhbGUgPC0gY29sb3JSYW1wUGFsZXR0ZShjKCJibHVlIiwgImxpZ2h0Ymx1ZSIsICJsaWdodGdyZWVuIiwgImRhcmtncmVlbiIsICJkYXJrcmVkIiwgInJlZCIpKQ0KDQojIENyZWEgdW4gbWFwYSBpbnRlcmFjdGl2byBwYXJhIGNhZGEgYcOxbyBkZXNlYWRvDQpmb3IgKGFubyBpbiBjKDIwMjAsMjAzMCwgMjA0MCwgMjA1MCwgMjA2MCwgMjA3MCkpIHsNCiAgZGF0b3NfYW5vIDwtIHN1YnNldChkYXRvc19ueSwgeWVhciA9PSBhbm8pDQogIA0KICBtYXBhIDwtIHBsb3RfbHkoDQogICAgZGF0YSA9IGRhdG9zX2FubywNCiAgICB0eXBlID0gImNob3JvcGxldGgiLA0KICAgIGxvY2F0aW9ubW9kZSA9ICJVU0Etc3RhdGVzIiwNCiAgICBsb2NhdGlvbnMgPSB+ZXN0YXRlLA0KICAgIHogPSB+cG9pbnRfZm9yZWNhc3QsDQogICAgY29sb3JzY2FsZSA9IGNvbG9yX3NjYWxlKDEwMCksDQogICAgbWFya2VyID0gbGlzdChsaW5lID0gbGlzdChjb2xvciA9ICJyZ2IoMjU1LDI1NSwyNTUpIiwgd2lkdGggPSAyKSksDQogICAgdGV4dCA9IH5wYXN0ZSgiRXN0YWRvOiAiLCBlc3RhdGUsICI8YnI+QcOxbzogIiwgeWVhciwgIjxicj5Qb2JsYWNpw7NuIFByb25vc3RpY2FkYTogIiwgcG9pbnRfZm9yZWNhc3QpLA0KICAgIHptaW4gPSBtaW4oZGF0b3NfbnkkcG9pbnRfZm9yZWNhc3QpLCAgIyBFc3RhYmxlY2UgZWwgdmFsb3IgbcOtbmltbyBkZSBsYSBlc2NhbGEgZGUgY29sb3Jlcw0KICAgIHptYXggPSBtYXgoZGF0b3NfbnkkcG9pbnRfZm9yZWNhc3QpICAgIyBFc3RhYmxlY2UgZWwgdmFsb3IgbcOheGltbyBkZSBsYSBlc2NhbGEgZGUgY29sb3Jlcw0KICApICU+JQ0KICAgIGxheW91dCgNCiAgICAgIHRpdGxlID0gcGFzdGUoIlBvYmxhY2nDs24gUHJvbm9zdGljYWRhIE51ZXZhIFlvcmsgZW4iLCBhbm8pLA0KICAgICAgZ2VvID0gbGlzdChzY29wZSA9ICJ1c2EiLCBwcm9qZWN0aW9uID0gbGlzdCh0eXBlID0gImFsYmVycyB1c2EiKSksDQogICAgICBjb2xvcmJhciA9IGxpc3QodGl0bGUgPSAiUG9ibGFjacOzbiBQcm9ub3N0aWNhZGEiKSwNCiAgICAgIHNob3dsZWdlbmQgPSBGQUxTRQ0KICAgICkNCiAgDQogICMgTXVlc3RyYSBlbCBtYXBhDQogIHByaW50KG1hcGEpDQp9DQoNCmBgYA0KDQojIyAqKkZsb3JpZGEqKg0KDQojIyMgKipWaXN1YWxpemFyIGxvcyBhw7FvcyBlbiBlbCBtYXBhKioNCg0KYGBge3J9DQojIEluc3RhbGEgeSBjYXJnYSBsYXMgbGlicmVyw61hcyBuZWNlc2FyaWFzDQojIGluc3RhbGwucGFja2FnZXMoYygibWFwcyIsICJwbG90bHkiKSkNCmxpYnJhcnkobWFwcykNCmxpYnJhcnkocGxvdGx5KQ0KDQojIEZpbHRyYSBsb3MgZGF0b3MgcGFyYSBlbCBlc3RhZG8gZGUgQ2FsaWZvcm5pYQ0KZGF0b3NfZmxvIDwtIHN1YnNldChwcm9ub3N0aWNvcywgZXN0YXRlID09ICJGTCIpDQoNCiMgRGVmaW5lIGxhIGVzY2FsYSBkZSBjb2xvcmVzIHBlcnNvbmFsaXphZGENCmNvbG9yX3NjYWxlIDwtIGNvbG9yUmFtcFBhbGV0dGUoYygiYmx1ZSIsICJsaWdodGJsdWUiLCAibGlnaHRncmVlbiIsICJkYXJrZ3JlZW4iLCAiZGFya3JlZCIsICJyZWQiKSkNCg0KIyBDcmVhIHVuIG1hcGEgaW50ZXJhY3Rpdm8gcGFyYSBjYWRhIGHDsW8gZGVzZWFkbw0KZm9yIChhbm8gaW4gYygyMDIwLDIwMzAsIDIwNDAsIDIwNTAsIDIwNjAsIDIwNzApKSB7DQogIGRhdG9zX2FubyA8LSBzdWJzZXQoZGF0b3NfZmxvLCB5ZWFyID09IGFubykNCiAgDQogIG1hcGEgPC0gcGxvdF9seSgNCiAgICBkYXRhID0gZGF0b3NfYW5vLA0KICAgIHR5cGUgPSAiY2hvcm9wbGV0aCIsDQogICAgbG9jYXRpb25tb2RlID0gIlVTQS1zdGF0ZXMiLA0KICAgIGxvY2F0aW9ucyA9IH5lc3RhdGUsDQogICAgeiA9IH5wb2ludF9mb3JlY2FzdCwNCiAgICBjb2xvcnNjYWxlID0gY29sb3Jfc2NhbGUoMTAwKSwNCiAgICBtYXJrZXIgPSBsaXN0KGxpbmUgPSBsaXN0KGNvbG9yID0gInJnYigyNTUsMjU1LDI1NSkiLCB3aWR0aCA9IDIpKSwNCiAgICB0ZXh0ID0gfnBhc3RlKCJFc3RhZG86ICIsIGVzdGF0ZSwgIjxicj5Bw7FvOiAiLCB5ZWFyLCAiPGJyPlBvYmxhY2nDs24gUHJvbm9zdGljYWRhOiAiLCBwb2ludF9mb3JlY2FzdCksDQogICAgem1pbiA9IG1pbihkYXRvc19mbG8kcG9pbnRfZm9yZWNhc3QpLCAgIyBFc3RhYmxlY2UgZWwgdmFsb3IgbcOtbmltbyBkZSBsYSBlc2NhbGEgZGUgY29sb3Jlcw0KICAgIHptYXggPSBtYXgoZGF0b3NfZmxvJHBvaW50X2ZvcmVjYXN0KSAgICMgRXN0YWJsZWNlIGVsIHZhbG9yIG3DoXhpbW8gZGUgbGEgZXNjYWxhIGRlIGNvbG9yZXMNCiAgKSAlPiUNCiAgICBsYXlvdXQoDQogICAgICB0aXRsZSA9IHBhc3RlKCJQb2JsYWNpw7NuIFByb25vc3RpY2FkYSBGbG9yaWRhIGVuIiwgYW5vKSwNCiAgICAgIGdlbyA9IGxpc3Qoc2NvcGUgPSAidXNhIiwgcHJvamVjdGlvbiA9IGxpc3QodHlwZSA9ICJhbGJlcnMgdXNhIikpLA0KICAgICAgY29sb3JiYXIgPSBsaXN0KHRpdGxlID0gIlBvYmxhY2nDs24gUHJvbm9zdGljYWRhIiksDQogICAgICBzaG93bGVnZW5kID0gRkFMU0UNCiAgICApDQogIA0KICAjIE11ZXN0cmEgZWwgbWFwYQ0KICBwcmludChtYXBhKQ0KfQ0KDQpgYGANCg0KIyMgKipUZXhhcyoqDQoNCiMjIyAqKlZpc3VhbGl6YXIgbG9zIGHDsW9zIGVuIGVsIG1hcGEqKg0KDQpgYGB7cn0NCmxpYnJhcnkobWFwcykNCmxpYnJhcnkocGxvdGx5KQ0KDQojIEZpbHRyYSBsb3MgZGF0b3MgcGFyYSBlbCBlc3RhZG8gZGUgQ2FsaWZvcm5pYQ0KZGF0b3NfdHggPC0gc3Vic2V0KHByb25vc3RpY29zLCBlc3RhdGUgPT0gIlRYIikNCg0KIyBEZWZpbmUgbGEgZXNjYWxhIGRlIGNvbG9yZXMgcGVyc29uYWxpemFkYQ0KY29sb3Jfc2NhbGUgPC0gY29sb3JSYW1wUGFsZXR0ZShjKCJibHVlIiwgImxpZ2h0Ymx1ZSIsICJsaWdodGdyZWVuIiwgImRhcmtncmVlbiIsICJkYXJrcmVkIiwgInJlZCIpKQ0KDQojIENyZWEgdW4gbWFwYSBpbnRlcmFjdGl2byBwYXJhIGNhZGEgYcOxbyBkZXNlYWRvDQpmb3IgKGFubyBpbiBjKDIwMjAsMjAzMCwgMjA0MCwgMjA1MCwgMjA2MCwgMjA3MCkpIHsNCiAgZGF0b3NfYW5vIDwtIHN1YnNldChkYXRvc190eCwgeWVhciA9PSBhbm8pDQogIA0KICBtYXBhIDwtIHBsb3RfbHkoDQogICAgZGF0YSA9IGRhdG9zX2FubywNCiAgICB0eXBlID0gImNob3JvcGxldGgiLA0KICAgIGxvY2F0aW9ubW9kZSA9ICJVU0Etc3RhdGVzIiwNCiAgICBsb2NhdGlvbnMgPSB+ZXN0YXRlLA0KICAgIHogPSB+cG9pbnRfZm9yZWNhc3QsDQogICAgY29sb3JzY2FsZSA9IGNvbG9yX3NjYWxlKDEwMCksDQogICAgbWFya2VyID0gbGlzdChsaW5lID0gbGlzdChjb2xvciA9ICJyZ2IoMjU1LDI1NSwyNTUpIiwgd2lkdGggPSAyKSksDQogICAgdGV4dCA9IH5wYXN0ZSgiRXN0YWRvOiAiLCBlc3RhdGUsICI8YnI+QcOxbzogIiwgeWVhciwgIjxicj5Qb2JsYWNpw7NuIFByb25vc3RpY2FkYTogIiwgcG9pbnRfZm9yZWNhc3QpLA0KICAgIHptaW4gPSBtaW4oZGF0b3NfdHgkcG9pbnRfZm9yZWNhc3QpLCAgIyBFc3RhYmxlY2UgZWwgdmFsb3IgbcOtbmltbyBkZSBsYSBlc2NhbGEgZGUgY29sb3Jlcw0KICAgIHptYXggPSBtYXgoZGF0b3NfdHgkcG9pbnRfZm9yZWNhc3QpICAgIyBFc3RhYmxlY2UgZWwgdmFsb3IgbcOheGltbyBkZSBsYSBlc2NhbGEgZGUgY29sb3Jlcw0KICApICU+JQ0KICAgIGxheW91dCgNCiAgICAgIHRpdGxlID0gcGFzdGUoIlBvYmxhY2nDs24gUHJvbm9zdGljYWRhIFRleGFzIGVuIiwgYW5vKSwNCiAgICAgIGdlbyA9IGxpc3Qoc2NvcGUgPSAidXNhIiwgcHJvamVjdGlvbiA9IGxpc3QodHlwZSA9ICJhbGJlcnMgdXNhIikpLA0KICAgICAgY29sb3JiYXIgPSBsaXN0KHRpdGxlID0gIlBvYmxhY2nDs24gUHJvbm9zdGljYWRhIiksDQogICAgICBzaG93bGVnZW5kID0gRkFMU0UNCiAgICApDQogIA0KICAjIE11ZXN0cmEgZWwgbWFwYQ0KICBwcmludChtYXBhKQ0KfQ0KDQpgYGANCg0KIyMgKipXeW9taW5nKioNCg0KIyMjICoqVmlzdWFsaXphciBsb3MgYcOxb3MgZW4gZWwgbWFwYSoqDQoNCmBgYHtyfQ0KbGlicmFyeShtYXBzKQ0KbGlicmFyeShwbG90bHkpDQoNCiMgRmlsdHJhIGxvcyBkYXRvcyBwYXJhIGVsIGVzdGFkbyBkZSBDYWxpZm9ybmlhDQpkYXRvc193byA8LSBzdWJzZXQocHJvbm9zdGljb3MsIGVzdGF0ZSA9PSAiV1kiKQ0KDQojIERlZmluZSBsYSBlc2NhbGEgZGUgY29sb3JlcyBwZXJzb25hbGl6YWRhDQpjb2xvcl9zY2FsZSA8LSBjb2xvclJhbXBQYWxldHRlKGMoImJsdWUiLCAibGlnaHRibHVlIiwgImxpZ2h0Z3JlZW4iLCAiZGFya2dyZWVuIiwgImRhcmtyZWQiLCAicmVkIikpDQoNCiMgQ3JlYSB1biBtYXBhIGludGVyYWN0aXZvIHBhcmEgY2FkYSBhw7FvIGRlc2VhZG8NCmZvciAoYW5vIGluIGMoMjAyMCwyMDMwLCAyMDQwLCAyMDUwLCAyMDYwLCAyMDcwKSkgew0KICBkYXRvc19hbm8gPC0gc3Vic2V0KGRhdG9zX3dvLCB5ZWFyID09IGFubykNCiAgDQogIG1hcGEgPC0gcGxvdF9seSgNCiAgICBkYXRhID0gZGF0b3NfYW5vLA0KICAgIHR5cGUgPSAiY2hvcm9wbGV0aCIsDQogICAgbG9jYXRpb25tb2RlID0gIlVTQS1zdGF0ZXMiLA0KICAgIGxvY2F0aW9ucyA9IH5lc3RhdGUsDQogICAgeiA9IH5wb2ludF9mb3JlY2FzdCwNCiAgICBjb2xvcnNjYWxlID0gY29sb3Jfc2NhbGUoMTAwKSwNCiAgICBtYXJrZXIgPSBsaXN0KGxpbmUgPSBsaXN0KGNvbG9yID0gInJnYigyNTUsMjU1LDI1NSkiLCB3aWR0aCA9IDIpKSwNCiAgICB0ZXh0ID0gfnBhc3RlKCJFc3RhZG86ICIsIGVzdGF0ZSwgIjxicj5Bw7FvOiAiLCB5ZWFyLCAiPGJyPlBvYmxhY2nDs24gUHJvbm9zdGljYWRhOiAiLCBwb2ludF9mb3JlY2FzdCksDQogICAgem1pbiA9IG1pbihkYXRvc193byRwb2ludF9mb3JlY2FzdCksICAjIEVzdGFibGVjZSBlbCB2YWxvciBtw61uaW1vIGRlIGxhIGVzY2FsYSBkZSBjb2xvcmVzDQogICAgem1heCA9IG1heChkYXRvc193byRwb2ludF9mb3JlY2FzdCkgICAjIEVzdGFibGVjZSBlbCB2YWxvciBtw6F4aW1vIGRlIGxhIGVzY2FsYSBkZSBjb2xvcmVzDQogICkgJT4lDQogICAgbGF5b3V0KA0KICAgICAgdGl0bGUgPSBwYXN0ZSgiUG9ibGFjacOzbiBQcm9ub3N0aWNhZGEgV3lvbWluZyBlbiIsIGFubyksDQogICAgICBnZW8gPSBsaXN0KHNjb3BlID0gInVzYSIsIHByb2plY3Rpb24gPSBsaXN0KHR5cGUgPSAiYWxiZXJzIHVzYSIpKSwNCiAgICAgIGNvbG9yYmFyID0gbGlzdCh0aXRsZSA9ICJQb2JsYWNpw7NuIFByb25vc3RpY2FkYSIpLA0KICAgICAgc2hvd2xlZ2VuZCA9IEZBTFNFDQogICAgKQ0KICANCiAgIyBNdWVzdHJhIGVsIG1hcGENCiAgcHJpbnQobWFwYSkNCn0NCg0KYGBgDQo=