Trabajo elaborado para la asignatura “Programación y manejo de datos en la era del Big Data” de la Universitat de València durante el curso 2020-2021. La página web de la asignatura puede verse aquí: https://perezp44.github.io/intro-ds-20-21-web/. Los trabajos de mis compañeros de curso pueden verse aquí.



Introducción

Objetivos

El objetivo de este trabajo es mostrar la evolución y el impacto de algunas variables medioambientales relevantes (las emisiones del CO2, estudiaremos su evolución así como las principales causas de sus aumentos y que países son los principales responsables) y ver el impacto negativo que provoca a nivel medioambiental en el mundo y como esto nos afecta (incrementos de temperatura). También veremos brevemente la evolución de las energias renovables a nivel mundial.

Fuente de los datos

Los datos utilizados provienen del Banco Mundial

Primeros pasos

Primero importamos las librerias básicas, utilizamos más librerias pero las llamamos cuando las necesitamos. Les remito al sessionInfo() para ver todos los paquetes utilizados.

library(tidyverse) 
library(sf)
library(viridis) #- install.packages("viridis")
library(plotly)
library(gganimate)
library(transformr) #-install.packages("transformr")
library(wordcloud2) #- install.packages("wordcloud2")
library(janitor)

Una vez cargados los paquetes que vamos a utilizar, procedemos a importar los datos que vamos a utilizar


df_co2<- read_csv("./Datos/nation_1751_2017.csv")
temp_country <-read_csv("./Datos/GlobalLandTemperaturesByCountry.csv")
coast_vs_waste <- read_csv("https://raw.githubusercontent.com/rfordatascience/tidytuesday/master/data/2019/2019-05-21/coastal-population-vs-mismanaged-plastic.csv")

mismanaged_vs_gdp <- read_csv("https://raw.githubusercontent.com/rfordatascience/tidytuesday/master/data/2019/2019-05-21/per-capita-mismanaged-plastic-waste-vs-gdp-per-capita.csv")

waste_vs_gdp <- read_csv("https://raw.githubusercontent.com/rfordatascience/tidytuesday/master/data/2019/2019-05-21/per-capita-plastic-waste-vs-gdp-per-capita.csv")
dco2_pc<- read_csv("./Datos/co2_pc.csv")

Emisiones de co2, diferentes perspectivas.

#Limpiamos el df y ponemos las variables como numericas
df_co2_2 <- df_co2[-c(1:4), ]
df_co2_2[ df_co2_2 == "." ] <- NA
 df_co2_3 <-  transform(df_co2_2, X2 = as.numeric(X2),
   X3 = as.numeric(X3),
   X4 = as.numeric(X4),
   X5 = as.numeric(X5),
   X6 = as.numeric(X6),
   X7 = as.numeric(X7),
   X8 = as.numeric(X8),
   X9 = as.numeric(X9),          
   X10 = as.numeric(X10)      
 )
 #comprobamos que las variables del df3 estan correctas
 str(df_co2_3)
#> 'data.frame':    17928 obs. of  10 variables:
#>  $ Carbon.Dioxide.emissions.from.fossil.fuel.consumption.and.cement.production.by.nation: chr  "AFGHANISTAN" "AFGHANISTAN" "AFGHANISTAN" "AFGHANISTAN" ...
#>  $ X2                                                                                   : num  1949 1950 1951 1952 1953 ...
#>  $ X3                                                                                   : num  4 23 25 25 29 29 42 50 80 90 ...
#>  $ X4                                                                                   : num  4 6 7 9 10 12 17 17 21 25 ...
#>  $ X5                                                                                   : num  0 18 18 17 18 18 25 33 59 65 ...
#>  $ X6                                                                                   : num  0 0 0 0 0 0 0 0 0 0 ...
#>  $ X7                                                                                   : num  0 0 0 0 0 0 0 0 0 0 ...
#>  $ X8                                                                                   : num  NA 0 0 0 0 0 0 0 0 0 ...
#>  $ X9                                                                                   : num  NA 0 0 0 0 0 0.01 0.01 0.01 0.01 ...
#>  $ X10                                                                                  : num  0 0 0 0 0 0 0 0 0 0 ...
 #renombramos las variables para trabajar de manera mas cómoda
             
df_co2_4 <- df_co2_3 %>% rename(country = `Carbon.Dioxide.emissions.from.fossil.fuel.consumption.and.cement.production.by.nation`,
  year = X2,
   total_co2 = X3 #`Total CO2 emissions from fossil-fuels and cement production (thousand metric tons of C)`
   ,
em_sf = X4, #`Emissions from solid fuel consumption` 
em_lf = X5, #`Emissions from liquid fuel consumption` 
em_gf = X6, #`Emissions from gas fuel consumption` 
em_cp = X7, #`Emissions from cement production` ,
em_gfl = X8, #`Emissions from gas flaring`
em_co2_pc = X9, #`Per capita CO2 emissions (metric tons of carbon)`
em_bf = X10 #`Emissions from bunker fuels`
)
#creamos los diferentes df modificados que vamos a usar 
 n_df_0 <- df_co2_4%>% select(year,country,total_co2)%>%  filter(year==2010) %>% group_by(country)%>% select(-year) %>% arrange(total_co2)
  n_df <- df_co2_4 %>% group_by(country) %>% summarise(total_co2=sum(total_co2))%>% ungroup() %>% slice_max(total_co2,n=20) %>% arrange(desc(total_co2))
  n_df2 <- df_co2_4 %>% filter(year > 2000) %>% group_by(country) %>% summarise(em_co2_pc=sum(em_co2_pc))%>% ungroup() %>% slice_max(em_co2_pc,n=40) %>% arrange(desc(em_co2_pc))
  w_df <- df_co2_4 %>% group_by(year) %>% summarise(n=sum(total_co2))%>% ungroup()

La evolución de las emisiones de co2

En primer lugar estudiamos la evolución de las emisiones de CO2, los motivos por los que han ido aumentando desde el siglo XIX y sus causas.

Observamos en el gráfico el crecimiento exponencial de las emisiones de CO2 durante el siglo XX y XXI. El crecimiento de las emisiones empieza en la década de 1850, con la Primera Revolución Industrial y la expansión de este acontecimiento por el resto de Europa, ya que la maquinaria creada durante este proceso utilizaba combustibles contaminantes como diversos tipos de carbón. Sin embargo, no es hasta finales del siglo XIX con la Segunda Revolución Industrial que el crecimiento se vuelve exponencial con Estados Unidos a la cabeza como máximo emisor de CO2. Este crecimiento se mantiene hasta el cuarto final del siglo XX, debido a la inclusión de varias innovaciones como los fertilizantes de nitrógeno, varios usos de gases fluorados, tala de selvas tropicales, etc. Después el crecimiento en emisiones se ralentiza (pero continua creciendo aunque a un ritmo mas decelerado) para continuar con el crecimiento exponencial desde principios del siglo XXI, donde China superaría a Estados Unidos como principal emisor.

Gráfico

Tabla

Año Emisiones de co2
2000 6479271
1975 4499682
1950 1579187
1900 533108
1850 53738
1800 7667

Gráfico Animado

Código


  #primer Gráfico
smoothScatter(w_df,ylab = "Em.Co2", xlab = "Año")


#Grafico animado

  o<-  w_df %>% ggplot() +
     geom_line(aes(year,n)) 

 ooo<- o +  transition_reveal(year) +
    labs(title = "Año: {as.integer(frame_along)}", y = "Emisiones co2", x = "año")
  anim_save("./imagenes/ooo.gif", ooo)
  
tabla1 <- w_df %>% filter(year %in% c(1800, 1850, 1900, 1950, 1975, 2000))
knitr::kable(tabla1)
   

La evolución de las emisiones de CO2 por país

Observamos que las emisiones de CO2 empiezan a crecer a partir de 1850, con la Primera Revolución Industrial que introdujo, entre otras cosas, el uso del carbón como combustible y fuente de energia. Reino Unido se mantiene líder en emisiones de CO2 desde 1850 a 1890, debido a que es el lugar donde empieza la Primera Revolución Industrial y por lo tanto, el país con maquinaria más contaminante en ese momento. Se observa en 1890 un cambio, Estados Unidos pasa a ser el país más contaminante coincidiendo con su paso a Reino Unido como primera potencia mundial debido a la Segunda Revolución Industrial, en la que Reino Unido se queda atrás por el alto coste de oportunidad de cambiar la maquinaria antigua de la Primera Revolución por la mas moderna de la Segunda. Estados Unidos lidera en emisiones de CO2 desde este momento y durante todo el siglo XX hasta 2006, momento en que es superado por China como país con más emisiones.

Por lo tanto distinguimos 4 etapas diferenciadas en la tabla a continuación:

  • Primera etapa: previa a la Revolución Industrial, donde no había apenas emisión de estos gases.

  • Segunda etapa: durante la primera Revolución Industrial y hasta 1890, donde Reino Unido lidera en emisiones debido a los carbones que se utilizaban en la maquinaria innovada durante esta época.

  • Tercera etapa: que abarca desde 1890 hasta 2005, donde Estados Unidos es el principal emisor de CO2 debido a la Segunda Revolución Industrial, a los varios inventos producidos durante el siglo XX (fertilizantes, ) y a la deforestación.

  • Cuarta etapa: donde China sobrepasa a Estados Unidos como principal emisor de CO2 en términos absolutos.

Gráficos

Gráfico 2

Tabla

Año País Emisiones de co2
1850 UNITED KINGDOM 33462
1889 UNITED KINGDOM 94166
1890 UNITED STATES OF AMERICA 109647
2005 UNITED STATES OF AMERICA 1577757
2006 CHINA (MAINLAND) 1736342

Código

df_co2_5 <-df_co2_4 %>% group_by(country)
 n_df_0 <- df_co2_4%>% select(year,country,total_co2)%>%  filter(year==2010) %>% group_by(country)%>% select(-year) %>% arrange(total_co2)
  n_df <- df_co2_4 %>% group_by(country) %>% summarise(total_co2=sum(total_co2))%>% ungroup() %>% slice_max(total_co2,n=20) %>% arrange(desc(total_co2))
  n_df_2 <- df_co2_4 %>% filter(year > 2000) %>% group_by(country) %>% summarise(em_co2_pc=sum(em_co2_pc))%>% ungroup() %>% slice_max(em_co2_pc,n=15) %>% arrange(desc(em_co2_pc))
 
   
  n_df_3 <- df_co2_4%>% group_by(country) %>% summarise(em_co2_pc=sum(em_co2_pc))%>% ungroup()  %>% arrange(desc(em_co2_pc))
 
  lf <- df_co2_5%>% filter(year >= 1980)  %>% group_by(year) %>%
  
  mutate(rank = rank(-total_co2),
         Value_rel = total_co2/total_co2[rank==1],
         Value_lbl = paste0(" ",round(total_co2/1e9))) %>%
  group_by(country) %>% 
  filter(rank <=15) %>%
  ungroup()
  
  lf$country <- recode(lf$country, 
                          "UNITED STATES OF AMERICA"="USA",
        "CHINA (MAINLAND)"="CHINA",
        "FRANCE (INCLUDING MONACO)"="FRANCE",
        "ITALY (INCLUDING SAN MARINO)"="ITALY",
        "RUSSIAN FEDERATION" = "RUSSIA"
        
        )
   
  

   
   staticplot = ggplot(lf, aes(rank, group = country, 
                fill = as.factor(country), color = as.factor(country))) +
  geom_tile(aes(y = total_co2/2,
                height = total_co2,
                width = 0.9), alpha = 0.8, color = NA) +
  geom_text(aes(y = 0, label = paste(country, " ")), vjust = 0.2, hjust = 1) +
  #geom_text(aes(y=total_co2,label = Value_lbl, hjust=0)) +
  coord_flip(clip = "off", expand = FALSE) +
  scale_y_continuous(labels = scales::comma) +
  scale_x_reverse() +
  guides(color = FALSE, fill = FALSE) +
  theme(axis.line=element_blank(),
        axis.text.x=element_blank(),
        axis.text.y=element_blank(),
        axis.ticks=element_blank(),
        axis.title.x=element_blank(),
         axis.title.y=element_blank(),
        legend.position="none",
        panel.background=element_blank(),
        panel.border=element_blank(),
        panel.grid.major=element_blank(),
        panel.grid.minor=element_blank(),
        panel.grid.major.x = element_line( size=.1, color="grey" ),
        panel.grid.minor.x = element_line( size=.1, color="grey" ),
        plot.title=element_text(size=25, hjust=0.5, face="bold", colour="grey", vjust=-1),
        plot.subtitle=element_text(size=18, hjust=0.5, face="italic", color="grey"),
        plot.caption =element_text(size=8, hjust=0.5, face="italic", color="grey"),
        plot.background=element_blank(),
       plot.margin = margin(2,2, 2, 4, "cm"))
   anim = staticplot + transition_states(year, transition_length = 4, state_length = 1) +
  view_follow(fixed_x = TRUE)  +
  labs(title = 'CO2 total : {closest_state}',  
       subtitle  =  "Top 15 países",
       caption  = "fuente: World Bank Data")
 
  
   anim_save("./imagenes/anim.gif", anim)
  
    
  g<-  df_co2_5 %>% ggplot() +
    geom_line(aes(year,total_co2 ,color = country,group=country) ) +
      theme(legend.position="none")
  
  
  goo <- g +  transition_reveal(year) +
    labs(title = "Año: {as.integer(frame_along)}", x = "Año", y ="Emisiones de co2")
  anim_save("./imagenes/goo.gif", goo)
  
tabla2 <- df_co2_4 %>% select(year, country, total_co2) %>% filter(year %in% c(1850, 1889, 1890, 2005, 2006)) %>% group_by(year) %>% slice_max(total_co2) %>%  rename("Año" = year, "País" = country,"Emisiones de co2" =total_co2) 

knitr::kable(tabla2)

CO2 per cápita

Pasamos a visualizar los datos con un gráfico circular, donde podemos ver los mayores emisores desde el año 2000 de dióxido de carbono per cápita.

Destacamos que los primeros paises en emisiones de dióxido de carbono per cápita utilizan como fuente de energia principal el petróleo (Qatar, Kuwait, Emiratos Árabes Unidos, Bahrein…) a la vez que también lo exportan debido a las grandes reservas del mismo. Estados Unidos aparece en la posición novena y China, el mayor emisor de CO2 en términos absolutos, no aparece entre los 40 primeros.

Gráfico

Tabla

country em_co2_pc
QATAR 224.82
TRINIDAD AND TOBAGO 141.77
KUWAIT 131.00
UNITED ARAB EMIRATES 109.74
BAHRAIN 105.22
LUXEMBOURG 94.94
ARUBA 93.69
BRUNEI (DARUSSALAM) 85.95
UNITED STATES OF AMERICA 81.33
SAUDI ARABIA 79.20

Código




 n_df3 <- n_df2 %>% mutate(id = seq(1,40))
label_data <- n_df3

number_of_bar <- nrow(label_data)
angle <-  90 - 360 * (label_data$id-0.5) /number_of_bar     
 

label_data$hjust<-ifelse( angle < -90, 1, 0)
 

label_data$angle<-ifelse(angle < -90, angle+180, angle)




p <- ggplot(n_df3, aes(x=as.factor(id), y=em_co2_pc,fill=em_co2_pc)) +       

  geom_bar(stat="identity") +
  
 
  ylim(-100,400) +
  

  theme_minimal() +
  theme(
    axis.text = element_blank(),
    axis.title = element_blank(),
    panel.grid = element_blank(),
    plot.margin = unit(rep(-1,4), "cm")      
  ) +
  
  coord_polar(start = 0) +
  
  
  geom_text(data=label_data, aes(x=id, y=em_co2_pc, label=country, hjust=hjust), color="black", fontface="bold",alpha=0.6, size=2.5, angle= label_data$angle, inherit.aes = FALSE ) +
  scale_fill_viridis_c(option = "B", trans = "sqrt")
 
p

tabla3 <- n_df3 %>% slice_max(em_co2_pc, n = 10)
knitr::kable(tabla3)

Mayores productores de co2 en la historia

Ahora estudiamos el total acumulado de emisiones de CO2 por país, y observamos que los 5 primeros son Estados Unidos (quién estuvo durante todo el siglo XX como primer emisor), China (actual primer emisor desde 2006 de CO2), la URSS (cuyos datos terminan en 1992 con su disolución), Reino Unido (principal emisor en 1850-1890 con la Revolución Industrial) y Japón. Lo vemos de dos formas:

Gráfico 1

Gráfico 2

Código


  #gráfico mayores productores co2 del mundo(acumulado total)
    
 p<- n_df %>% ggplot(aes(x = reorder(country, total_co2),total_co2,fill= total_co2)) +
    geom_bar(stat = "identity") +
    theme(legend.position = "none") +
    coord_flip()
  p
   #gráfico mayores productores co2 del mundo(acumulado total)
    
 h<- n_df %>% ggplot(aes(x = reorder(country, total_co2),total_co2,fill= total_co2)) +
    geom_bar(stat = "identity") +
    theme(legend.position = "none") +
    coord_flip() + 
  labs(x = "Co2 total" , y= " Países")
  
  h

Una forma diferente de visualizar los datos

“Wordcloud”

Código

#Gráfico paises con mas emisiones de co2

n_df6 <- df_co2_4 %>% group_by(country) %>% summarise(total_co2=sum(total_co2))%>% ungroup() %>% arrange(desc(total_co2))
  
  
      n_df_0$country <- recode(n_df_0$country, 
                          "UNITED STATES OF AMERICA"="USA",
        "CHINA (MAINLAND)"="CHINA",
        "FRANCE (INCLUDING MONACO)"="FRANCE",
        "ITALY (INCLUDING SAN MARINO)"="ITALY",
        "RUSSIAN FEDERATION" = "RUSSIA"
        
        )
  
  wordcloud2(data = n_df_0, size = 0.8
  )

Coropletas

Pasamos a utilizar una representación geográfica para ver las emisiones de CO2 por país en 2010 y las emisiones por país y per cápita para el mismo año.

Los colores más oscuros indican una mayor emisión de CO2 a la atmosfera donde claramente se distinguen China y Estados Unidos en términos absolutos.

Para las emisiones de CO2 per cápita el color más claro representa una mayor emisión de estos gases, donde observamos a varios países árabes (con reservas de petróleo) como principales emisores per cápita.

Emisiones de CO2 por país 2010

Emisiones co2 per cápita

Código

#install.packages("viridis")
library(viridis)

library(sf)

library(tidyverse)

world <- rnaturalearth::ne_countries(scale = "medium", returnclass = "sf")
world_points<- st_centroid(world)
world_points <- cbind(world, st_coordinates(st_centroid(world$geometry)))
#mapa co2 per capita
library(tidyverse)



#mapa co2 



dco2<- read_csv("./Datos/co2.csv")
world <- rnaturalearth::ne_countries(scale = "medium", returnclass = "sf")


dco2[ dco2 == ".." ] <- NA




dco2 <- dco2 %>% select(`Country Name`,`2010 [YR2010]`)
dfo3 <- dco2 %>% rename(sovereignt = `Country Name`,
                        co2 = `2010 [YR2010]`
                        
)



dfo3$sovereignt <- recode(dfo3$sovereignt, 
                          "United States"="United States of America", 
                          "Russian Federation" = "Russia",
                          "Venezuela, RB" = "Venezuela",
                          "Congo, Dem. Rep." = "Democratic Republic of the Congo" ,
                          " Congo, Rep."="Republic of Congo"     ,
                          "Egypt, Arab Rep." = "Egypt" ,
                          "Tanzania" = "United Republic of Tanzania",
                          "Cote d'Ivoire" = "Ivory Coast",
                          "Yemen, Rep." = "Yemen",
                          "Iran, Islamic Rep." = "Iran",
                          "Syrian Arab Republic" = "Syria",
                          "Slovak Republic" = "Slovakia",
                          "Serbia" = "Republic of Serbia",
                          "North Macedonia" = "Macedonia",
                          "Kyrgyz Republic" = "Kyrgyzstan",
                          "Korea, Dem. People’s Rep" = "North Korea",
                          "Korea, Rep." = "South Korea",
                          "Lao PDR" = "Laos"
)


df_inner <- left_join(world,dfo3)
df_co2 <-  transform(df_inner, co2 = as.numeric(co2)   
) %>% filter(!(sovereignt == "Antarctica"))

p <- ggplot(data = df_co2) + geom_sf() +
  labs(title = "Mapa emisiones de co2",
       caption = "Datos provenientes de World Bank")
p + geom_sf(aes(fill = co2, color =co2)) + scale_fill_viridis(direction = -1, label = scales::number,begin = 0, end = 0.8,) + 
  scale_color_viridis(direction = -1, label = scales::number,begin = 0, end = 0.8) 

#Gráfico co2 pc
library(viridis)

library(sf)

library(tidyverse)

world <- rnaturalearth::ne_countries(scale = "medium", returnclass = "sf")
world_points<- st_centroid(world)
world_points <- cbind(world, st_coordinates(st_centroid(world$geometry)))
dco2_pc<- read_csv("./Datos/co2_pc.csv")



dco2_pc[ dco2_pc == ".." ] <- NA




dco_pc <- dco2_pc %>% select(`Country Name`,`2010 [YR2010]`)
dfo3_pc <- dco2_pc %>% rename(sovereignt = `Country Name`,
                        co2_pc = `2010 [YR2010]`
                        
)



dfo3_pc$sovereignt <- recode(dfo3_pc$sovereignt, 
                      "United States"="United States of America", 
                      "Russian Federation" = "Russia",
                      "Venezuela, RB" = "Venezuela",
                       "Congo, Dem. Rep." = "Democratic Republic of the Congo" ,
              " Congo, Rep."="Republic of Congo"     ,
              "Egypt, Arab Rep." = "Egypt" ,
             "Tanzania" = "United Republic of Tanzania",
             "Cote d'Ivoire" = "Ivory Coast",
             "Yemen, Rep." = "Yemen",
             "Iran, Islamic Rep." = "Iran",
             "Syrian Arab Republic" = "Syria",
             "Slovak Republic" = "Slovakia",
             "Serbia" = "Republic of Serbia",
             "North Macedonia" = "Macedonia",
             "Kyrgyz Republic" = "Kyrgyzstan",
             "Korea, Dem. People’s Rep" = "North Korea",
             "Korea, Rep." = "South Korea",
             "Lao PDR" = "Laos"
)


df_inner_pc <- left_join(world,dfo3_pc)
df_co2_pc <-  transform(df_inner_pc, co2_pc = as.numeric(co2_pc)   
) %>% filter(!(sovereignt == "Antarctica"))

p <- ggplot(data = df_co2_pc) + geom_sf() +
  labs(title = "Gráfico 1: Mapa del mundo",
       caption = "Datos provenientes de rnaturalearth")
p + geom_sf(aes(fill = co2_pc)) + scale_fill_viridis_c(option = "B", trans = "sqrt") 

Calentamiento Global

Con este análisis pretendemos estudiar las consecuencias de la emisión de CO2 durante todos estos años en nuestra vida, más concretamente, en los incrementos de temperatura que hemos experimentado por la liberación de estos gases a la atmósfera.

Evolución de la temperatura media global

Observamos que se ha producido un incremento de la temperatura desde 1900 hasta nuestros dias debido a la emisión de estos gases de efecto invernadero. Estos gases de efecto invernadero (entre los que se incluyen el CO2, ozono, etc.) reflejan el calor producido por la superficie terrestre, por lo que producen un incremento de la temperatura global.

La producción de CO2 que hemos analizado es una de los principales causas (y sigue un comportamiento similar) del aumento de temperatura que vamos a ver en los siguientes gráficos.

Gráfico

Código

library(tidyverse)
library(gganimate)

library(lubridate)
pct <- function(x) {((x/lag(x)
)-1)*2}
pct2 <- function(x) {((x/lag(x)
)-1)*100}


temp_country <-read_csv("./Datos/GlobalLandTemperaturesByCountry.csv")

temp_2000 <- subset(temp_country,dt> "1899-12-01")

climate_change <- temp_2000 %>% 
  mutate_at(vars(dt), funs(year, month, day)) %>% drop_na() %>% filter(Country == "Spain")

climate_change$month[climate_change$month == 1]<- "01-Enero"
climate_change$month[climate_change$month == 2]<- "02-Febrero"
climate_change$month[climate_change$month == 3]<- "03-Marzo"
climate_change$month[climate_change$month == 4]<- "04-Abril"
climate_change$month[climate_change$month == 5]<- "05-Mayo"
climate_change$month[climate_change$month == 6]<- "06-Junio"
climate_change$month[climate_change$month == 7]<- "07-Julio"
climate_change$month[climate_change$month == 8]<- "08-Agosto"
climate_change$month[climate_change$month == 9]<- "09-Septiembre"
climate_change$month[climate_change$month == 10]<- "10-Octubre"
climate_change$month[climate_change$month == 11]<- "11-Noviembre"
climate_change$month[climate_change$month == 12]<- "12-Diciembre"

t_df <- temp_2000 %>% drop_na() %>%
mutate(month = format(dt, "%m"), year = format(dt, "%Y")) %>%
group_by(month, year) %>%
summarise(mean = mean(AverageTemperature))




t_df2 <- t_df %>% group_by(year) %>% summarise(tmean= mean(mean))
 t_df2 <-  transform(t_df2, year = as.numeric(year))

 w_df2 <- w_df %>% filter(year > 1899)
 w_df3 <- w_df2  %>%  mutate_each(funs(pct), n) %>% drop_na()
t_df3 <- t_df2  %>% mutate_each(funs(pct2), tmean) %>% drop_na()
w_df4 <- w_df3 %>% mutate(tco2 = cumsum(n))
t_df4 <- t_df3  %>% mutate(temp = cumsum(tmean))

y <-ggplot() +
  
  geom_line(data =w_df4,aes(year,tco2,color="CO2")) +
  #geom_smooth(data = w_df4,aes(year,tco2)) +
 #theme(axis.text.x = element_text(angle = 90, vjust = 0.5, hjust=1)) +
   #geom_smooth(data = t_df4,aes(year,temp),colour= "purple") +
    geom_line(data = t_df4,aes(year,temp,group=1,color="Temperatura")) 
  
      
  
  
temPco2gf <- y  + transition_reveal(year) +
  labs(title = "Año: {as.integer(frame_along)}",
       x = "Año",
       y = "Temperatura y CO2",
       colour="Variables") 
  
  
anim_save("./imagenes/gf_tempco2.gif",temPco2gf  )

Evolución de la temperatura en España

Gráfico

Código



temp_country <-read_csv("./Datos/GlobalLandTemperaturesByCountry.csv")

temp_2000 <- subset(temp_country,dt> "1899-12-01")

climate_change <- temp_2000 %>% separate( "dt", c("año", "mes", "dia"), sep = "-") %>% transform( año = as.numeric(año),
   mes = as.numeric(mes),
 dia = as.numeric(dia)     
 ) %>% drop_na() %>% filter(Country == "Spain")

climate_change$mes[climate_change$mes == 1]<- "01-Enero"
climate_change$mes[climate_change$mes == 2]<- "02-Febrero"
climate_change$mes[climate_change$mes == 3]<- "03-Marzo"
climate_change$mes[climate_change$mes == 4]<- "04-Abril"
climate_change$mes[climate_change$mes == 5]<- "05-Mayo"
climate_change$mes[climate_change$mes == 6]<- "06-Junio"
climate_change$mes[climate_change$mes == 7]<- "07-Julio"
climate_change$mes[climate_change$mes == 8]<- "08-Agosto"
climate_change$mes[climate_change$mes == 9]<- "09-Septiembre"
climate_change$mes[climate_change$mes == 10]<- "10-Octubre"
climate_change$mes[climate_change$mes == 11]<- "11-Noviembre"
climate_change$mes[climate_change$mes == 12]<- "12-Diciembre"



gf_temp_month <- ggplot(climate_change, aes(año, AverageTemperature, size = AverageTemperatureUncertainty , color = mes )) + geom_point(alpha = 0.4, show.legend = FALSE) +
  facet_wrap(~mes) +
  
  labs(title = 'Año: {as.integer(frame_time)}', x = 'Año', y = 'Temperatura Media') +
  transition_time(año) +
  ease_aes('linear')
anim_save("./imagenes/gf_month.gif", gf_temp_month)

Evolución de las energías renovables 1990-2015

Analizamos ahora la evolución que han seguido las energias renovables. Estas tecnologías pretenden ser mas amigables con el medio ambiente, disminuyendo la contaminación a la vez que producen energia.

En las principales economías mundiales (Estados Unidos, Europa y parte de Asia) no se han producido ningún avance o muy poco en este sentido, y que son los países mas subdesarrollados (América del Sur y la parte central de África) los que más proporción de energia renovable usan, sin embargo, conforme se han ido desarrollando han ido utilizando menos las energias renovables. Este es el caso de Brasil, quién además ha deforestado parte de su superficie. Si nos centramos en Europa podemos ver que ha habido cierto avance en los ultimos 15 años , aunque aún hay mucho por hacer.

Mapa

Europa

Código

library(tidyverse)
library(rio)
library(plotly)
library(janitor)
library(gganimate)
library(viridis)
library("sf")

url <-("https://raw.githubusercontent.com/rodri45l/plasticwaste/main/trabajo_BigData_equipo/datos/renpwr.csv")

df <- import(url)

df_pwr <- df %>% select(-c(`Series Name`,`Series Code`)) %>% rename(sovereignt = `Country Name`)


names(df_pwr) <- stringr::str_remove(string = names(df_pwr), pattern = "\\s.*") 



df_pwr$sovereignt <- recode(df_pwr$sovereignt, 
                            "United States"="United States of America", 
                            "Russian Federation" = "Russia",
                            "Venezuela, RB" = "Venezuela",
                            "Congo, Dem. Rep." = "Democratic Republic of the Congo" ,
                            "   Congo, Rep."="Republic of Congo"     ,
                            "Egypt, Arab Rep." = "Egypt" ,
                            "Tanzania" = "United Republic of Tanzania",
                            "Cote d'Ivoire" = "Ivory Coast",
                            "Yemen, Rep." = "Yemen",
                            "Iran, Islamic Rep." = "Iran",
                            "Syrian Arab Republic" = "Syria",
                            "Slovak Republic" = "Slovakia",
                            "Serbia" = "Republic of Serbia",
                            "North Macedonia" = "Macedonia",
                            "Kyrgyz Republic" = "Kyrgyzstan",
                            "Korea, Dem. People’s Rep" = "North Korea",
                            "Korea, Rep." = "South Korea",
                            "Lao PDR" = "Laos")


df_pwr2 <- df_pwr %>% pivot_longer(cols = 3:28, names_to = "year") %>% 
           mutate(year = as.numeric(year)) %>% 
           mutate(value = as.numeric(value)) %>% 
          filter(year == 2015)



world <- rnaturalearth::ne_countries(scale = "medium", returnclass = "sf")
world_points<- st_centroid(world)
world_points <- cbind(world, st_coordinates(st_centroid(world$geometry)))


df_inner_pwr <- inner_join(world, df_pwr2, by= c("sovereignt" = "sovereignt"))


 
df_pwr4 <- df_pwr %>% pivot_longer(cols = 3:28, names_to = "year") 
df_pwr5 <-df_pwr4 %>%   mutate(year = as.numeric(year)) %>% 
  mutate(value = as.numeric(value))

df_pwr5 <- inner_join(world, df_pwr5, by= c("sovereignt" = "sovereignt"))
#df_pwr6 
names(df_pwr4)

df_pwr9 <- df_pwr5 %>% select(sovereignt, year, value)
p <- ggplot() + geom_sf(data = df_pwr9, aes(fill = value)) + 
  labs(title = "Mapa del mundo energias renovables 1990 - 2015",
       caption = "Datos provenientes de World Bank") +
  scale_fill_viridis(direction = 1, label = scales::number,begin = 0, end = 0.9) +
  transition_time(year) + labs(title = "Porcentaje de energia renovable por país", subtitle = "Año:{as.integer(frame_time)}"  ) 

anim <- animate(p)

anim_save("./imagenes/map6.gif", anim)


#-----------------------
df_pwr10 <- df_pwr5 %>% filter(continent == "Europe") 


i <- ggplot() + geom_sf(data = df_pwr10, aes(fill = value)) + 
  labs(title = "Mapa Europa energias renovables 1990 - 2015",
       caption = "Datos provenientes de World Bank") +
  coord_sf(xlim = c(-35, 50), ylim = c(30, 80))+
  scale_fill_viridis(direction = 1, label = scales::number,begin = 0, end = 0.9) +
  transition_time(year) + labs(title = "Porcentaje de energia renovable por país", subtitle = "Año:{as.integer(frame_time)}"  ) 

anim1 <- animate(i)

anim_save("./imagenes/mapp.gif", anim1)

#-----------------------------------------------------------------

df_pwr11 <- df_pwr10 %>% filter(year == 2015) %>% select(sovereignt, year, value)






library(treemapify)

ggplot(df_pwr11, aes(area = value, fill = value, label = sovereignt )) +
  geom_treemap() +
  geom_treemap_text(colour = "white", place = "centre",
                    grow = FALSE) +
  scale_fill_viridis_c(option = "D" , name = "", alpha = 0.8, begin = 0.3, end = 0.7, direction = 1,
                       guide = guide_colorbar( title = "% Energia renovable", direction = "horizontal", barheight = unit(2, units = "mm"),
                                               barwidth = unit(50, units = "mm"), draw.ulim = F,
                                               title.position = 'top', title.hjust = 0.5, label.hjust = 0.5)) +
  theme(legend.position = "bottom") + scale_x_continuous(labels=function(value){format(value, scientific = FALSE)}) +
  labs(title = "Porcentaje de energías renovables por países") + theme(plot.title = element_text(hjust = 0.5)) +
  theme(plot.subtitle = element_text(hjust = 0.5))

session info

sessioninfo::session_info() %>% details::details(summary = 'current session info') 

current session info


- Session info ---------------------------------------------------------------
 setting  value                       
 version  R version 4.0.2 (2020-06-22)
 os       Windows 10 x64              
 system   x86_64, mingw32             
 ui       RTerm                       
 language (EN)                        
 collate  Spanish_Spain.1252          
 ctype    Spanish_Spain.1252          
 tz       Europe/Paris                
 date     2020-12-18                  

- Packages -------------------------------------------------------------------
 package           * version    date       lib source                        
 assertthat          0.2.1      2019-03-21 [1] CRAN (R 4.0.2)                
 backports           1.1.9      2020-08-24 [1] CRAN (R 4.0.2)                
 base64enc           0.1-3      2015-07-28 [1] CRAN (R 4.0.0)                
 blob                1.2.1      2020-01-20 [1] CRAN (R 4.0.2)                
 broom               0.7.0      2020-07-09 [1] CRAN (R 4.0.2)                
 Cairo               1.5-12.2   2020-07-07 [1] CRAN (R 4.0.2)                
 cellranger          1.1.0      2016-07-27 [1] CRAN (R 4.0.2)                
 class               7.3-17     2020-04-26 [2] CRAN (R 4.0.2)                
 classInt            0.4-3      2020-04-07 [1] CRAN (R 4.0.2)                
 cli                 2.0.2      2020-02-28 [1] CRAN (R 4.0.2)                
 colorspace          1.4-1      2019-03-18 [1] CRAN (R 4.0.2)                
 crayon              1.3.4      2017-09-16 [1] CRAN (R 4.0.2)                
 crosstalk           1.1.0.1    2020-03-13 [1] CRAN (R 4.0.2)                
 curl                4.3        2019-12-02 [1] CRAN (R 4.0.2)                
 data.table          1.13.0     2020-07-24 [1] CRAN (R 4.0.2)                
 DBI                 1.1.0      2019-12-15 [1] CRAN (R 4.0.2)                
 dbplyr              1.4.4      2020-05-27 [1] CRAN (R 4.0.2)                
 digest              0.6.25     2020-02-23 [1] CRAN (R 4.0.2)                
 dplyr             * 1.0.2      2020-08-18 [1] CRAN (R 4.0.2)                
 e1071               1.7-3      2019-11-26 [1] CRAN (R 4.0.2)                
 ellipsis            0.3.1      2020-05-15 [1] CRAN (R 4.0.2)                
 evaluate            0.14       2019-05-28 [1] CRAN (R 4.0.2)                
 fansi               0.4.1      2020-01-08 [1] CRAN (R 4.0.2)                
 farver              2.0.3      2020-01-16 [1] CRAN (R 4.0.2)                
 forcats           * 0.5.0      2020-03-01 [1] CRAN (R 4.0.2)                
 fs                  1.5.0      2020-07-31 [1] CRAN (R 4.0.2)                
 generics            0.1.0      2020-10-31 [1] CRAN (R 4.0.3)                
 gganimate         * 1.0.6      2020-07-08 [1] CRAN (R 4.0.2)                
 ggplot2           * 3.3.2      2020-06-19 [1] CRAN (R 4.0.2)                
 gifski              0.8.6      2018-09-28 [1] CRAN (R 4.0.2)                
 glue                1.4.2      2020-08-27 [1] CRAN (R 4.0.2)                
 gridExtra           2.3        2017-09-09 [1] CRAN (R 4.0.3)                
 gtable              0.3.0      2019-03-25 [1] CRAN (R 4.0.2)                
 haven               2.3.1      2020-06-01 [1] CRAN (R 4.0.2)                
 highr               0.8        2019-03-20 [1] CRAN (R 4.0.2)                
 hms                 0.5.3      2020-01-08 [1] CRAN (R 4.0.2)                
 htmltools           0.5.0      2020-06-16 [1] CRAN (R 4.0.2)                
 htmlwidgets         1.5.1      2019-10-08 [1] CRAN (R 4.0.2)                
 httr                1.4.2      2020-07-20 [1] CRAN (R 4.0.2)                
 janitor           * 2.0.1      2020-04-12 [1] CRAN (R 4.0.3)                
 jsonlite            1.7.1      2020-09-07 [1] CRAN (R 4.0.2)                
 KernSmooth          2.23-17    2020-04-26 [2] CRAN (R 4.0.2)                
 klippy            * 0.0.0.9500 2020-11-13 [1] Github (rlesur/klippy@378c247)
 knitr             * 1.29       2020-06-23 [1] CRAN (R 4.0.2)                
 labeling            0.3        2014-08-23 [1] CRAN (R 4.0.0)                
 lattice             0.20-41    2020-04-02 [2] CRAN (R 4.0.2)                
 lazyeval            0.2.2      2019-03-15 [1] CRAN (R 4.0.2)                
 lifecycle           0.2.0      2020-03-06 [1] CRAN (R 4.0.2)                
 lpSolve             5.6.15     2020-01-24 [1] CRAN (R 4.0.3)                
 lubridate           1.7.9      2020-06-08 [1] CRAN (R 4.0.2)                
 magrittr            1.5        2014-11-22 [1] CRAN (R 4.0.2)                
 modelr              0.1.8      2020-05-19 [1] CRAN (R 4.0.2)                
 munsell             0.5.0      2018-06-12 [1] CRAN (R 4.0.2)                
 pillar              1.4.6      2020-07-10 [1] CRAN (R 4.0.2)                
 pkgconfig           2.0.3      2019-09-22 [1] CRAN (R 4.0.2)                
 plotly            * 4.9.2.1    2020-04-04 [1] CRAN (R 4.0.2)                
 plyr                1.8.6      2020-03-03 [1] CRAN (R 4.0.2)                
 prettyunits         1.1.1      2020-01-24 [1] CRAN (R 4.0.2)                
 progress            1.2.2      2019-05-16 [1] CRAN (R 4.0.2)                
 purrr             * 0.3.4      2020-04-17 [1] CRAN (R 4.0.2)                
 R6                  2.4.1      2019-11-12 [1] CRAN (R 4.0.2)                
 Rcpp                1.0.5      2020-07-06 [1] CRAN (R 4.0.2)                
 readr             * 1.3.1      2018-12-21 [1] CRAN (R 4.0.2)                
 readxl              1.3.1      2019-03-13 [1] CRAN (R 4.0.2)                
 reprex              0.3.0      2019-05-16 [1] CRAN (R 4.0.2)                
 rgeos               0.5-5      2020-09-07 [1] CRAN (R 4.0.3)                
 rlang               0.4.9      2020-11-26 [1] CRAN (R 4.0.3)                
 rmarkdown           2.3        2020-06-18 [1] CRAN (R 4.0.2)                
 rnaturalearth       0.1.0      2017-03-21 [1] CRAN (R 4.0.3)                
 rnaturalearthdata   0.1.0      2017-02-21 [1] CRAN (R 4.0.3)                
 rstudioapi          0.11       2020-02-07 [1] CRAN (R 4.0.2)                
 rvest               0.3.6      2020-07-25 [1] CRAN (R 4.0.2)                
 scales              1.1.1      2020-05-11 [1] CRAN (R 4.0.2)                
 sessioninfo         1.1.1      2018-11-05 [1] CRAN (R 4.0.2)                
 sf                * 0.9-5      2020-07-14 [1] CRAN (R 4.0.2)                
 snakecase           0.11.0     2019-05-25 [1] CRAN (R 4.0.3)                
 sp                  1.4-2      2020-05-20 [1] CRAN (R 4.0.2)                
 stringi             1.5.3      2020-09-09 [1] CRAN (R 4.0.2)                
 stringr           * 1.4.0      2019-02-10 [1] CRAN (R 4.0.2)                
 tibble            * 3.0.3      2020-07-10 [1] CRAN (R 4.0.2)                
 tidyr             * 1.1.2      2020-08-27 [1] CRAN (R 4.0.2)                
 tidyselect          1.1.0      2020-05-11 [1] CRAN (R 4.0.2)                
 tidyverse         * 1.3.0      2019-11-21 [1] CRAN (R 4.0.2)                
 transformr        * 0.1.3      2020-07-05 [1] CRAN (R 4.0.3)                
 tweenr              1.0.1      2018-12-14 [1] CRAN (R 4.0.2)                
 units               0.6-7      2020-06-13 [1] CRAN (R 4.0.2)                
 vctrs               0.3.4      2020-08-29 [1] CRAN (R 4.0.2)                
 viridis           * 0.5.1      2018-03-29 [1] CRAN (R 4.0.3)                
 viridisLite       * 0.3.0      2018-02-01 [1] CRAN (R 4.0.2)                
 withr               2.2.0      2020-04-20 [1] CRAN (R 4.0.2)                
 wordcloud2        * 0.2.1      2018-01-03 [1] CRAN (R 4.0.3)                
 xfun                0.16       2020-07-24 [1] CRAN (R 4.0.2)                
 xml2                1.3.2      2020-04-23 [1] CRAN (R 4.0.2)                
 yaml                2.2.1      2020-02-01 [1] CRAN (R 4.0.2)                

[1] C:/Users/rodri/OneDrive/Documentos/R/win-library/4.0
[2] C:/Program Files/R/R-4.0.2/library


LS0tDQp0aXRsZTogIkFuw6FsaXNpcyBkZWwgaW1wYWN0byBlY29sw7NnaWNvIg0KYXV0aG9yOiAiKipSb2RyaWdvIExhcmEqKihyb2xhcm9AYWx1bW5pLnV2LmVzKSAgXG5cbiAqKklnbmFjaW8gQ29yYWNoYW4gUGVyZXoqKihpZ2NvcGVAYWx1bW5pLnV2LmVzKSAgXG4gXG4gKipTZXJnaW8gRXNjb3JjaWEgVG9ycmVzKiooc2VyZXN0b0BhbHVtbmkudXYuZXMpLiBcblxuIFVuaXZlcnNpdGF0IGRlIFZhbMOobmNpYSINCmRhdGU6ICJEaWNpZW1icmUgZGUgMjAyMCAoYWN0dWFsaXphZG8gZWwgYHIgZm9ybWF0KFN5cy50aW1lKCksICclZC0lbS0lWScpYCkiDQpvdXRwdXQ6DQogIGh0bWxfZG9jdW1lbnQ6IA0KICAgIHNlbGZfY29udGFpbmVkOiB5ZXMNCiAgICBjb2RlX2Rvd25sb2FkOiB0cnVlDQogICAgY29kZV9mb2xkaW5nOiBzaG93DQogICAgdG9jOiB5ZXMNCiAgICB0b2NfZmxvYXQ6DQogICAgICBjb2xsYXBzZWQ6IHllcw0KICAgICAgc21vb3RoX3Njcm9sbDogeWVzDQogICAgZGZfcHJpbnQ6IGthYmxlDQplZGl0b3Jfb3B0aW9uczogDQogIGNodW5rX291dHB1dF90eXBlOiBjb25zb2xlDQotLS0NCg0KYGBge3IgcGFja2FnZXMtc2V0dXAsIGluY2x1ZGUgPSBGQUxTRX0NCmxpYnJhcnkodGlkeXZlcnNlKQ0KbGlicmFyeShrbGlwcHkpICAjLSByZW1vdGVzOjppbnN0YWxsX2dpdGh1Yigicmxlc3VyL2tsaXBweSIpDQpsaWJyYXJ5KGtuaXRyKQ0KYGBgDQoNCmBgYHtjc3MsIGVjaG8gPSBGQUxTRX0NCi5jb2x1bW5zIHtkaXNwbGF5OmZsZXg7fQ0KaDEudGl0bGUge2ZvbnQtc2l6ZTogNDVweDtjb2xvcjogZm9yZXN0Z3JlZW59DQpoMSB7Y29sb3I6IFNlYWdyZWVuOyBmb250LXNpemU6IDM1cHggO2ZvbnQtZmFtaWx5OiBBcmlhbCwgSGVsdmV0aWNhLCBzYW5zLXNlcmlmfQ0KaDJ7Y29sb3I6IERhcmtvbGl2ZWdyZWVuOyBmb250LXNpemU6IDI4cHg7fQ0KYm9keSB7IGJhY2tncm91bmQtY29sb3I6IGRhcmtzZWFncmVlbjsgfQ0KYSB7Y29sb3I6IGdyZWVuO30NCi5saXN0LWdyb3VwLWl0ZW0uYWN0aXZlLCAubGlzdC1ncm91cC1pdGVtLmFjdGl2ZTpmb2N1cywgLmxpc3QtZ3JvdXAtaXRlbS5hY3RpdmU6aG92ZXIgew0KICAgIHotaW5kZXg6IDI7DQogICAgY29sb3I6ICNmZmY7DQogICAgYmFja2dyb3VuZC1jb2xvcjogb2xpdmVkcmFiOw0KICAgIGJvcmRlci1jb2xvcjogcGFsZWdyZWVuOw0KfQ0KLm5hdi1waWxscyA+IGxpLmFjdGl2ZSA+IGEsIC5uYXYtcGlsbHMgPiBsaS5hY3RpdmUgPiBhOmhvdmVyLCAubmF2LXBpbGxzID4gbGkuYWN0aXZlID4gYTpmb2N1cyB7DQogICAgY29sb3I6YmxhY2s7DQogICAgYmFja2dyb3VuZC1jb2xvcjogb2xpdmVkcmFiOw0KfQ0KYm9keXsNCiAgIGZvbnQtZmFtaWx5OiAiTHVjaWRhIENvbnNvbGUiLG1vbm9zcGFjZTsNCiAgZm9udC1zaXplOiAxMXB0Ow0KfQ0KYGBgDQoNCmBgYHtyIGNodW5rLXNldHVwLCBpbmNsdWRlID0gRkFMU0V9DQprbml0cjo6b3B0c19jaHVuayRzZXQoZWNobyA9IFRSVUUsIGV2YWwgPSBUUlVFLCBtZXNzYWdlID0gRkFMU0UsIHdhcm5pbmcgPSBGQUxTRSwgDQogICAgICAgICAgICAgICAgICAgICAgI3Jlc3VsdHMgPSAiaG9sZCIsDQogICAgICAgICAgICAgICAgICAgICAgY2FjaGUgPSBGQUxTRSwgY2FjaGUucGF0aCA9ICIvY2FjaGVzLyIsIGNvbW1lbnQgPSAiIz4iLA0KICAgICAgICAgICAgICAgICAgICAgICNmaWcud2lkdGggPSA3LCAjZmlnLmhlaWdodD0gNywgICANCiAgICAgICAgICAgICAgICAgICAgICAjb3V0LndpZHRoID0gNywgb3V0LmhlaWdodCA9IDcsDQogICAgICAgICAgICAgICAgICAgICAgY29sbGFwc2UgPSBUUlVFLCAgZmlnLnNob3cgPSAiaG9sZCIsDQogICAgICAgICAgICAgICAgICAgICAgZmlnLmFzcCA9IDcvOSwgb3V0LndpZHRoID0gIjYwJSIsIGZpZy5hbGlnbiA9ICJjZW50ZXIiKQ0KIy0gcGFyYSBtZWpvcmFyIGxvcyBncsOhZmljb3MsIGJ1ZW5vIGVuIHJlYWxpZGFkIHBhcmEgcXVlIHNlIHZlYW4gaWd1YWwgZW4gZGlzdGludG9zIFNPDQojLSBodHRwczovL3d3dy5qdW1waW5ncml2ZXJzLmNvbS9ibG9nL3Ita25pdHItbWFya2Rvd24tcG5nLXBkZi1ncmFwaGljcy8NCmtuaXRyOjpvcHRzX2NodW5rJHNldChkZXYgPSAicG5nIiwgZGV2LmFyZ3MgPSBsaXN0KHR5cGUgPSAiY2Fpcm8tcG5nIikpDQpgYGANCg0KYGBge3Igb3B0aW9ucy1zZXR1cCwgaW5jbHVkZSA9IEZBTFNFfQ0Kb3B0aW9ucyhzY2lwZW4gPSA5OTkpICMtIHBhcmEgcXVpdGFyIGxhIG5vdGFjacOzbiBjaWVudMOtZmljYQ0Kb3B0aW9ucygieWFtbC5ldmFsLmV4cHIiID0gVFJVRSkgDQpgYGANCg0KDQpgYGB7ciBrbGlwcHksIGVjaG8gPSBGQUxTRX0NCmtsaXBweTo6a2xpcHB5KHBvc2l0aW9uID0gYygidG9wIiwgInJpZ2h0IikpICMtIHJlbW90ZXM6Omluc3RhbGxfZ2l0aHViKCJybGVzdXIva2xpcHB5IikNCmBgYA0KDQotLS0tLS0tLS0tLS0tLS0tLQ0KDQpUcmFiYWpvICBlbGFib3JhZG8gcGFyYSBsYSBhc2lnbmF0dXJhICJQcm9ncmFtYWNpw7NuIHkgbWFuZWpvIGRlIGRhdG9zIGVuIGxhIGVyYSBkZWwgQmlnIERhdGEiIGRlIGxhIFVuaXZlcnNpdGF0IGRlIFZhbMOobmNpYSBkdXJhbnRlIGVsIGN1cnNvIDIwMjAtMjAyMS4gTGEgcMOhZ2luYSB3ZWIgZGUgbGEgYXNpZ25hdHVyYSBwdWVkZSB2ZXJzZSBhcXXDrTogPGh0dHBzOi8vcGVyZXpwNDQuZ2l0aHViLmlvL2ludHJvLWRzLTIwLTIxLXdlYi8+LiBMb3MgdHJhYmFqb3MgZGUgbWlzIGNvbXBhw7Flcm9zIGRlIGN1cnNvIHB1ZWRlbiB2ZXJzZSBbYXF1w61dKGh0dHBzOi8vcGVyZXpwNDQuZ2l0aHViLmlvL2ludHJvLWRzLTIwLTIxLXdlYi8wNy10cmFiYWpvcy5odG1sKS4NCg0KLS0tLS0tLS0tLS0tLS0tDQoNCjxicj4NCg0KIyBJbnRyb2R1Y2Npw7NuIHsudGFic2V0IC50YWJzZXQtcGlsbHN9DQoNCiMjIE9iamV0aXZvcw0KDQpFbCBvYmpldGl2byBkZSBlc3RlIHRyYWJham8gZXMgbW9zdHJhciBsYSBldm9sdWNpw7NuIHkgZWwgaW1wYWN0byBkZSBhbGd1bmFzIHZhcmlhYmxlcyBtZWRpb2FtYmllbnRhbGVzIHJlbGV2YW50ZXMgKGxhcyBlbWlzaW9uZXMgZGVsIENPMiwgZXN0dWRpYXJlbW9zIHN1IGV2b2x1Y2nDs24gYXPDrSBjb21vIGxhcyBwcmluY2lwYWxlcyBjYXVzYXMgZGUgc3VzIGF1bWVudG9zIHkgcXVlIHBhw61zZXMgc29uIGxvcyBwcmluY2lwYWxlcyByZXNwb25zYWJsZXMpIHkgdmVyIGVsIGltcGFjdG8gbmVnYXRpdm8gcXVlIHByb3ZvY2EgYSBuaXZlbCBtZWRpb2FtYmllbnRhbCBlbiBlbCBtdW5kbyB5IGNvbW8gZXN0byBub3MgYWZlY3RhIChpbmNyZW1lbnRvcyBkZSB0ZW1wZXJhdHVyYSkuIFRhbWJpw6luIHZlcmVtb3MgYnJldmVtZW50ZSBsYSBldm9sdWNpw7NuIGRlIGxhcyBlbmVyZ2lhcyByZW5vdmFibGVzIGEgbml2ZWwgbXVuZGlhbC4NCg0KIyMgRnVlbnRlIGRlIGxvcyBkYXRvcw0KDQpMb3MgZGF0b3MgdXRpbGl6YWRvcyBwcm92aWVuZW4gZGVsIFtCYW5jbyBNdW5kaWFsIF0oaHR0cHM6Ly9kYXRvcy5iYW5jb211bmRpYWwub3JnLykgDQoNCiMjIFByaW1lcm9zIHBhc29zDQoNClByaW1lcm8gaW1wb3J0YW1vcyBsYXMgbGlicmVyaWFzIGLDoXNpY2FzLCB1dGlsaXphbW9zIG3DoXMgbGlicmVyaWFzIHBlcm8gbGFzIGxsYW1hbW9zIGN1YW5kbyBsYXMgbmVjZXNpdGFtb3MuIExlcyByZW1pdG8gYWwgYHNlc3Npb25JbmZvKClgIHBhcmEgdmVyIHRvZG9zIGxvcyBwYXF1ZXRlcyB1dGlsaXphZG9zLg0KDQpgYGB7ciBsaWJyYXJ5X3NldHVwfQ0KbGlicmFyeSh0aWR5dmVyc2UpIA0KbGlicmFyeShzZikNCmxpYnJhcnkodmlyaWRpcykgIy0gaW5zdGFsbC5wYWNrYWdlcygidmlyaWRpcyIpDQpsaWJyYXJ5KHBsb3RseSkNCmxpYnJhcnkoZ2dhbmltYXRlKQ0KbGlicmFyeSh0cmFuc2Zvcm1yKSAjLWluc3RhbGwucGFja2FnZXMoInRyYW5zZm9ybXIiKQ0KbGlicmFyeSh3b3JkY2xvdWQyKSAjLSBpbnN0YWxsLnBhY2thZ2VzKCJ3b3JkY2xvdWQyIikNCmxpYnJhcnkoamFuaXRvcikNCmBgYA0KDQpVbmEgdmV6IGNhcmdhZG9zIGxvcyBwYXF1ZXRlcyBxdWUgdmFtb3MgYSB1dGlsaXphciwgcHJvY2VkZW1vcyBhIGltcG9ydGFyIGxvcyBkYXRvcyBxdWUgdmFtb3MgYSB1dGlsaXphcg0KDQpgYGB7ciBkZl9iYXNlfQ0KDQpkZl9jbzI8LSByZWFkX2NzdigiLi9EYXRvcy9uYXRpb25fMTc1MV8yMDE3LmNzdiIpDQp0ZW1wX2NvdW50cnkgPC1yZWFkX2NzdigiLi9EYXRvcy9HbG9iYWxMYW5kVGVtcGVyYXR1cmVzQnlDb3VudHJ5LmNzdiIpDQpjb2FzdF92c193YXN0ZSA8LSByZWFkX2NzdigiaHR0cHM6Ly9yYXcuZ2l0aHVidXNlcmNvbnRlbnQuY29tL3Jmb3JkYXRhc2NpZW5jZS90aWR5dHVlc2RheS9tYXN0ZXIvZGF0YS8yMDE5LzIwMTktMDUtMjEvY29hc3RhbC1wb3B1bGF0aW9uLXZzLW1pc21hbmFnZWQtcGxhc3RpYy5jc3YiKQ0KDQptaXNtYW5hZ2VkX3ZzX2dkcCA8LSByZWFkX2NzdigiaHR0cHM6Ly9yYXcuZ2l0aHVidXNlcmNvbnRlbnQuY29tL3Jmb3JkYXRhc2NpZW5jZS90aWR5dHVlc2RheS9tYXN0ZXIvZGF0YS8yMDE5LzIwMTktMDUtMjEvcGVyLWNhcGl0YS1taXNtYW5hZ2VkLXBsYXN0aWMtd2FzdGUtdnMtZ2RwLXBlci1jYXBpdGEuY3N2IikNCg0Kd2FzdGVfdnNfZ2RwIDwtIHJlYWRfY3N2KCJodHRwczovL3Jhdy5naXRodWJ1c2VyY29udGVudC5jb20vcmZvcmRhdGFzY2llbmNlL3RpZHl0dWVzZGF5L21hc3Rlci9kYXRhLzIwMTkvMjAxOS0wNS0yMS9wZXItY2FwaXRhLXBsYXN0aWMtd2FzdGUtdnMtZ2RwLXBlci1jYXBpdGEuY3N2IikNCmRjbzJfcGM8LSByZWFkX2NzdigiLi9EYXRvcy9jbzJfcGMuY3N2IikNCmBgYA0KDQoNCiMgRW1pc2lvbmVzIGRlIGNvMiwgZGlmZXJlbnRlcyBwZXJzcGVjdGl2YXMuDQoNCg0KYGBge3IgfQ0KI0xpbXBpYW1vcyBlbCBkZiB5IHBvbmVtb3MgbGFzIHZhcmlhYmxlcyBjb21vIG51bWVyaWNhcw0KZGZfY28yXzIgPC0gZGZfY28yWy1jKDE6NCksIF0NCmRmX2NvMl8yWyBkZl9jbzJfMiA9PSAiLiIgXSA8LSBOQQ0KIGRmX2NvMl8zIDwtICB0cmFuc2Zvcm0oZGZfY28yXzIsIFgyID0gYXMubnVtZXJpYyhYMiksDQogICBYMyA9IGFzLm51bWVyaWMoWDMpLA0KICAgWDQgPSBhcy5udW1lcmljKFg0KSwNCiAgIFg1ID0gYXMubnVtZXJpYyhYNSksDQogICBYNiA9IGFzLm51bWVyaWMoWDYpLA0KICAgWDcgPSBhcy5udW1lcmljKFg3KSwNCiAgIFg4ID0gYXMubnVtZXJpYyhYOCksDQogICBYOSA9IGFzLm51bWVyaWMoWDkpLCAgICAgICAgICANCiAgIFgxMCA9IGFzLm51bWVyaWMoWDEwKSAgICAgIA0KICkNCiAjY29tcHJvYmFtb3MgcXVlIGxhcyB2YXJpYWJsZXMgZGVsIGRmMyBlc3RhbiBjb3JyZWN0YXMNCiBzdHIoZGZfY28yXzMpDQogI3Jlbm9tYnJhbW9zIGxhcyB2YXJpYWJsZXMgcGFyYSB0cmFiYWphciBkZSBtYW5lcmEgbWFzIGPDs21vZGENCiAgICAgICAgICAgICANCmRmX2NvMl80IDwtIGRmX2NvMl8zICU+JSByZW5hbWUoY291bnRyeSA9IGBDYXJib24uRGlveGlkZS5lbWlzc2lvbnMuZnJvbS5mb3NzaWwuZnVlbC5jb25zdW1wdGlvbi5hbmQuY2VtZW50LnByb2R1Y3Rpb24uYnkubmF0aW9uYCwNCiAgeWVhciA9IFgyLA0KICAgdG90YWxfY28yID0gWDMgI2BUb3RhbCBDTzIgZW1pc3Npb25zIGZyb20gZm9zc2lsLWZ1ZWxzIGFuZCBjZW1lbnQgcHJvZHVjdGlvbiAodGhvdXNhbmQgbWV0cmljIHRvbnMgb2YgQylgDQogICAsDQplbV9zZiA9IFg0LCAjYEVtaXNzaW9ucyBmcm9tIHNvbGlkIGZ1ZWwgY29uc3VtcHRpb25gIA0KZW1fbGYgPSBYNSwgI2BFbWlzc2lvbnMgZnJvbSBsaXF1aWQgZnVlbCBjb25zdW1wdGlvbmAgDQplbV9nZiA9IFg2LCAjYEVtaXNzaW9ucyBmcm9tIGdhcyBmdWVsIGNvbnN1bXB0aW9uYCANCmVtX2NwID0gWDcsICNgRW1pc3Npb25zIGZyb20gY2VtZW50IHByb2R1Y3Rpb25gICwNCmVtX2dmbCA9IFg4LCAjYEVtaXNzaW9ucyBmcm9tIGdhcyBmbGFyaW5nYA0KZW1fY28yX3BjID0gWDksICNgUGVyIGNhcGl0YSBDTzIgZW1pc3Npb25zIChtZXRyaWMgdG9ucyBvZiBjYXJib24pYA0KZW1fYmYgPSBYMTAgI2BFbWlzc2lvbnMgZnJvbSBidW5rZXIgZnVlbHNgDQopDQojY3JlYW1vcyBsb3MgZGlmZXJlbnRlcyBkZiBtb2RpZmljYWRvcyBxdWUgdmFtb3MgYSB1c2FyIA0KIG5fZGZfMCA8LSBkZl9jbzJfNCU+JSBzZWxlY3QoeWVhcixjb3VudHJ5LHRvdGFsX2NvMiklPiUgIGZpbHRlcih5ZWFyPT0yMDEwKSAlPiUgZ3JvdXBfYnkoY291bnRyeSklPiUgc2VsZWN0KC15ZWFyKSAlPiUgYXJyYW5nZSh0b3RhbF9jbzIpDQogIG5fZGYgPC0gZGZfY28yXzQgJT4lIGdyb3VwX2J5KGNvdW50cnkpICU+JSBzdW1tYXJpc2UodG90YWxfY28yPXN1bSh0b3RhbF9jbzIpKSU+JSB1bmdyb3VwKCkgJT4lIHNsaWNlX21heCh0b3RhbF9jbzIsbj0yMCkgJT4lIGFycmFuZ2UoZGVzYyh0b3RhbF9jbzIpKQ0KICBuX2RmMiA8LSBkZl9jbzJfNCAlPiUgZmlsdGVyKHllYXIgPiAyMDAwKSAlPiUgZ3JvdXBfYnkoY291bnRyeSkgJT4lIHN1bW1hcmlzZShlbV9jbzJfcGM9c3VtKGVtX2NvMl9wYykpJT4lIHVuZ3JvdXAoKSAlPiUgc2xpY2VfbWF4KGVtX2NvMl9wYyxuPTQwKSAlPiUgYXJyYW5nZShkZXNjKGVtX2NvMl9wYykpDQogIHdfZGYgPC0gZGZfY28yXzQgJT4lIGdyb3VwX2J5KHllYXIpICU+JSBzdW1tYXJpc2Uobj1zdW0odG90YWxfY28yKSklPiUgdW5ncm91cCgpDQoNCmBgYA0KDQojIyBMYSBldm9sdWNpw7NuIGRlIGxhcyBlbWlzaW9uZXMgZGUgY28yIHsudGFic2V0IC50YWJzZXQtcGlsbHN9DQoNCkVuIHByaW1lciBsdWdhciBlc3R1ZGlhbW9zIGxhIGV2b2x1Y2nDs24gZGUgbGFzIGVtaXNpb25lcyBkZSBDTzIsIGxvcyBtb3Rpdm9zIHBvciBsb3MgcXVlIGhhbiBpZG8gYXVtZW50YW5kbyBkZXNkZSBlbCBzaWdsbyBYSVggeSBzdXMgY2F1c2FzLg0KDQpPYnNlcnZhbW9zIGVuIGVsIGdyw6FmaWNvIGVsIGNyZWNpbWllbnRvIGV4cG9uZW5jaWFsIGRlIGxhcyBlbWlzaW9uZXMgZGUgQ08yIGR1cmFudGUgZWwgc2lnbG8gWFggeSBYWEkuIEVsIGNyZWNpbWllbnRvIGRlIGxhcyBlbWlzaW9uZXMgZW1waWV6YSBlbiBsYSBkw6ljYWRhIGRlIDE4NTAsIGNvbiBsYSBQcmltZXJhIFJldm9sdWNpw7NuIEluZHVzdHJpYWwgeSBsYSBleHBhbnNpw7NuIGRlIGVzdGUgYWNvbnRlY2ltaWVudG8gcG9yIGVsIHJlc3RvIGRlIEV1cm9wYSwgeWEgcXVlIGxhIG1hcXVpbmFyaWEgY3JlYWRhIGR1cmFudGUgZXN0ZSBwcm9jZXNvIHV0aWxpemFiYSBjb21idXN0aWJsZXMgY29udGFtaW5hbnRlcyBjb21vIGRpdmVyc29zIHRpcG9zIGRlIGNhcmLDs24uIFNpbiBlbWJhcmdvLCBubyBlcyBoYXN0YSBmaW5hbGVzIGRlbCBzaWdsbyBYSVggY29uIGxhIFNlZ3VuZGEgUmV2b2x1Y2nDs24gSW5kdXN0cmlhbCBxdWUgZWwgY3JlY2ltaWVudG8gc2UgdnVlbHZlIGV4cG9uZW5jaWFsIGNvbiBFc3RhZG9zIFVuaWRvcyBhIGxhIGNhYmV6YSBjb21vIG3DoXhpbW8gZW1pc29yIGRlIENPMi4gRXN0ZSBjcmVjaW1pZW50byBzZSBtYW50aWVuZSBoYXN0YSBlbCBjdWFydG8gZmluYWwgZGVsIHNpZ2xvIFhYLCBkZWJpZG8gYSBsYSBpbmNsdXNpw7NuIGRlIHZhcmlhcyBpbm5vdmFjaW9uZXMgY29tbyBsb3MgZmVydGlsaXphbnRlcyBkZSBuaXRyw7NnZW5vLCB2YXJpb3MgdXNvcyBkZSBnYXNlcyBmbHVvcmFkb3MsIHRhbGEgZGUgc2VsdmFzIHRyb3BpY2FsZXMsIGV0Yy4gRGVzcHXDqXMgZWwgY3JlY2ltaWVudG8gZW4gZW1pc2lvbmVzIHNlIHJhbGVudGl6YSAocGVybyBjb250aW51YSBjcmVjaWVuZG8gYXVucXVlIGEgdW4gcml0bW8gbWFzIGRlY2VsZXJhZG8pIHBhcmEgY29udGludWFyIGNvbiBlbCBjcmVjaW1pZW50byBleHBvbmVuY2lhbCBkZXNkZSBwcmluY2lwaW9zIGRlbCBzaWdsbyBYWEksIGRvbmRlIENoaW5hIHN1cGVyYXLDrWEgYSBFc3RhZG9zIFVuaWRvcyBjb21vIHByaW5jaXBhbCBlbWlzb3IuDQoNCiMjIyBHcsOhZmljbw0KYGBge3IsZWNobyA9IEZBTFNFfQ0Kc21vb3RoU2NhdHRlcih3X2RmLHlsYWIgPSAiRW0uQ28yIiwgeGxhYiA9ICJBw7FvIikNCg0KYGBgDQoNCiMjIyBUYWJsYQ0KDQpgYGB7ciwgZWNobyA9IEZBTFNFLCBldmFsID0gVFJVRSwgcmVzdWx0cyA9IFRSVUV9DQp0YWJsYTEgPC0gd19kZiAlPiUgZmlsdGVyKHllYXIgJWluJSBjKDE4MDAsIDE4NTAsIDE5MDAsIDE5NTAsIDE5NzUsIDIwMDApKSU+JSAgIGFycmFuZ2UoIGRlc2MobikpICU+JSByZW5hbWUoIkHDsW8iID0geWVhciwgIkVtaXNpb25lcyBkZSBjbzIiID0gbikgIA0Ka25pdHI6OmthYmxlKHRhYmxhMSkNCg0KYGBgDQoNCiMjIyBHcsOhZmljbyBBbmltYWRvDQoNCiFbXSguL2ltYWdlbmVzL29vby5naWYpDQoNCiMjIyBDw7NkaWdvDQpgYGB7ciBjbzJfZ2YyLCBtZXNzYWdlID0gRkFMU0UsIHdhcm5pbmcgPSBGQUxTRSwgZXZhbCA9IEZBTFNFfQ0KDQogICNwcmltZXIgR3LDoWZpY28NCnNtb290aFNjYXR0ZXIod19kZix5bGFiID0gIkVtLkNvMiIsIHhsYWIgPSAiQcOxbyIpDQoNCg0KI0dyYWZpY28gYW5pbWFkbw0KDQogIG88LSAgd19kZiAlPiUgZ2dwbG90KCkgKw0KICAgICBnZW9tX2xpbmUoYWVzKHllYXIsbikpIA0KDQogb29vPC0gbyArICB0cmFuc2l0aW9uX3JldmVhbCh5ZWFyKSArDQogICAgbGFicyh0aXRsZSA9ICJBw7FvOiB7YXMuaW50ZWdlcihmcmFtZV9hbG9uZyl9IiwgeSA9ICJFbWlzaW9uZXMgY28yIiwgeCA9ICJhw7FvIikNCiAgYW5pbV9zYXZlKCIuL2ltYWdlbmVzL29vby5naWYiLCBvb28pDQogIA0KdGFibGExIDwtIHdfZGYgJT4lIGZpbHRlcih5ZWFyICVpbiUgYygxODAwLCAxODUwLCAxOTAwLCAxOTUwLCAxOTc1LCAyMDAwKSkNCmtuaXRyOjprYWJsZSh0YWJsYTEpDQogICANCg0KYGBgDQoNCg0KIA0KIyMgTGEgZXZvbHVjacOzbiBkZSBsYXMgZW1pc2lvbmVzIGRlIENPMiBwb3IgcGHDrXMgey50YWJzZXQgLnRhYnNldC1waWxsc30NCg0KT2JzZXJ2YW1vcyBxdWUgbGFzIGVtaXNpb25lcyBkZSBDTzIgZW1waWV6YW4gYSBjcmVjZXIgYSBwYXJ0aXIgZGUgMTg1MCwgY29uIGxhICoqUHJpbWVyYSBSZXZvbHVjacOzbiBJbmR1c3RyaWFsKiogcXVlIGludHJvZHVqbywgZW50cmUgb3RyYXMgY29zYXMsIGVsIHVzbyBkZWwgY2FyYsOzbiBjb21vIGNvbWJ1c3RpYmxlIHkgZnVlbnRlIGRlIGVuZXJnaWEuIFJlaW5vIFVuaWRvIHNlIG1hbnRpZW5lIGzDrWRlciBlbiBlbWlzaW9uZXMgZGUgQ08yIGRlc2RlIDE4NTAgYSAxODkwLCBkZWJpZG8gYSBxdWUgZXMgZWwgbHVnYXIgZG9uZGUgZW1waWV6YSBsYSBQcmltZXJhIFJldm9sdWNpw7NuIEluZHVzdHJpYWwgeSBwb3IgbG8gdGFudG8sIGVsIHBhw61zIGNvbiBtYXF1aW5hcmlhIG3DoXMgY29udGFtaW5hbnRlIGVuIGVzZSBtb21lbnRvLiBTZSBvYnNlcnZhIGVuIDE4OTAgdW4gY2FtYmlvLCBFc3RhZG9zIFVuaWRvcyBwYXNhIGEgc2VyIGVsIHBhw61zIG3DoXMgY29udGFtaW5hbnRlIGNvaW5jaWRpZW5kbyBjb24gc3UgcGFzbyBhIFJlaW5vIFVuaWRvIGNvbW8gcHJpbWVyYSBwb3RlbmNpYSBtdW5kaWFsIGRlYmlkbyBhIGxhICoqU2VndW5kYSBSZXZvbHVjacOzbiBJbmR1c3RyaWFsKiosIGVuIGxhIHF1ZSBSZWlubyBVbmlkbyBzZSBxdWVkYSBhdHLDoXMgcG9yIGVsIGFsdG8gY29zdGUgZGUgb3BvcnR1bmlkYWQgZGUgY2FtYmlhciBsYSBtYXF1aW5hcmlhIGFudGlndWEgZGUgbGEgUHJpbWVyYSBSZXZvbHVjacOzbiBwb3IgbGEgbWFzIG1vZGVybmEgZGUgbGEgU2VndW5kYS4gRXN0YWRvcyBVbmlkb3MgbGlkZXJhIGVuIGVtaXNpb25lcyBkZSBDTzIgZGVzZGUgZXN0ZSBtb21lbnRvIHkgZHVyYW50ZSB0b2RvIGVsIHNpZ2xvIFhYIGhhc3RhIDIwMDYsIG1vbWVudG8gZW4gcXVlIGVzIHN1cGVyYWRvIHBvciBDaGluYSBjb21vIHBhw61zIGNvbiBtw6FzIGVtaXNpb25lcy4gDQoNClBvciBsbyB0YW50byBkaXN0aW5ndWltb3MgNCBldGFwYXMgZGlmZXJlbmNpYWRhcyBlbiBsYSB0YWJsYSBhIGNvbnRpbnVhY2nDs246IFxuIA0KDQorIFByaW1lcmEgZXRhcGE6IHByZXZpYSBhIGxhIFJldm9sdWNpw7NuIEluZHVzdHJpYWwsIGRvbmRlIG5vIGhhYsOtYSBhcGVuYXMgZW1pc2nDs24gZGUgZXN0b3MgZ2FzZXMuIFxuDQoNCisgU2VndW5kYSBldGFwYTogZHVyYW50ZSBsYSBwcmltZXJhIFJldm9sdWNpw7NuIEluZHVzdHJpYWwgeSBoYXN0YSAxODkwLCBkb25kZSBSZWlubyBVbmlkbyBsaWRlcmEgZW4gZW1pc2lvbmVzIGRlYmlkbyBhIGxvcyBjYXJib25lcyBxdWUgc2UgdXRpbGl6YWJhbiBlbiBsYSBtYXF1aW5hcmlhIGlubm92YWRhIGR1cmFudGUgZXN0YSDDqXBvY2EuXG4NCg0KKyBUZXJjZXJhIGV0YXBhOiBxdWUgYWJhcmNhIGRlc2RlIDE4OTAgaGFzdGEgMjAwNSwgZG9uZGUgRXN0YWRvcyBVbmlkb3MgZXMgZWwgcHJpbmNpcGFsIGVtaXNvciBkZSBDTzIgZGViaWRvIGEgbGEgU2VndW5kYSBSZXZvbHVjacOzbiBJbmR1c3RyaWFsLCBhIGxvcyB2YXJpb3MgaW52ZW50b3MgcHJvZHVjaWRvcyBkdXJhbnRlIGVsIHNpZ2xvIFhYIChmZXJ0aWxpemFudGVzLCApIHkgYSBsYSBkZWZvcmVzdGFjacOzbi4gXG4NCg0KKyBDdWFydGEgZXRhcGE6IGRvbmRlIENoaW5hIHNvYnJlcGFzYSBhIEVzdGFkb3MgVW5pZG9zIGNvbW8gcHJpbmNpcGFsIGVtaXNvciBkZSBDTzIgZW4gdMOpcm1pbm9zIGFic29sdXRvcy4NCg0KDQoNCiMjIyBHcsOhZmljb3MgDQohW10oLi9pbWFnZW5lcy9nb28uZ2lmKQ0KR3LDoWZpY28gMg0KIVtdKC4vaW1hZ2VuZXMvYW5pbS5naWYpDQoNCg0KIyMjIFRhYmxhDQoNCmBgYHtyLCBlY2hvID0gRkFMU0UsIGV2YWwgPSBUUlVFLCByZXN1bHRzID0gVFJVRX0NCnRhYmxhMiA8LSBkZl9jbzJfNCAlPiUgc2VsZWN0KHllYXIsIGNvdW50cnksIHRvdGFsX2NvMikgJT4lIGZpbHRlcih5ZWFyICVpbiUgYygxODUwLCAxODg5LCAxODkwLCAyMDA1LCAyMDA2KSkgJT4lIGdyb3VwX2J5KHllYXIpICU+JSBzbGljZV9tYXgodG90YWxfY28yKSAlPiUgIHJlbmFtZSgiQcOxbyIgPSB5ZWFyLCAiUGHDrXMiID0gY291bnRyeSwiRW1pc2lvbmVzIGRlIGNvMiIgPXRvdGFsX2NvMikgDQoNCmtuaXRyOjprYWJsZSh0YWJsYTIpDQoNCmBgYA0KDQoNCg0KDQojIyMgQ8OzZGlnbw0KDQpgYGB7ciBjbzJfZ2YxLCBtZXNzYWdlID0gRkFMU0UsIHdhcm5pbmcgPSBGQUxTRSwgcmVzdWx0cyA9IEZBTFNFfQ0KZGZfY28yXzUgPC1kZl9jbzJfNCAlPiUgZ3JvdXBfYnkoY291bnRyeSkNCiBuX2RmXzAgPC0gZGZfY28yXzQlPiUgc2VsZWN0KHllYXIsY291bnRyeSx0b3RhbF9jbzIpJT4lICBmaWx0ZXIoeWVhcj09MjAxMCkgJT4lIGdyb3VwX2J5KGNvdW50cnkpJT4lIHNlbGVjdCgteWVhcikgJT4lIGFycmFuZ2UodG90YWxfY28yKQ0KICBuX2RmIDwtIGRmX2NvMl80ICU+JSBncm91cF9ieShjb3VudHJ5KSAlPiUgc3VtbWFyaXNlKHRvdGFsX2NvMj1zdW0odG90YWxfY28yKSklPiUgdW5ncm91cCgpICU+JSBzbGljZV9tYXgodG90YWxfY28yLG49MjApICU+JSBhcnJhbmdlKGRlc2ModG90YWxfY28yKSkNCiAgbl9kZl8yIDwtIGRmX2NvMl80ICU+JSBmaWx0ZXIoeWVhciA+IDIwMDApICU+JSBncm91cF9ieShjb3VudHJ5KSAlPiUgc3VtbWFyaXNlKGVtX2NvMl9wYz1zdW0oZW1fY28yX3BjKSklPiUgdW5ncm91cCgpICU+JSBzbGljZV9tYXgoZW1fY28yX3BjLG49MTUpICU+JSBhcnJhbmdlKGRlc2MoZW1fY28yX3BjKSkNCiANCiAgIA0KICBuX2RmXzMgPC0gZGZfY28yXzQlPiUgZ3JvdXBfYnkoY291bnRyeSkgJT4lIHN1bW1hcmlzZShlbV9jbzJfcGM9c3VtKGVtX2NvMl9wYykpJT4lIHVuZ3JvdXAoKSAgJT4lIGFycmFuZ2UoZGVzYyhlbV9jbzJfcGMpKQ0KIA0KICBsZiA8LSBkZl9jbzJfNSU+JSBmaWx0ZXIoeWVhciA+PSAxOTgwKSAgJT4lIGdyb3VwX2J5KHllYXIpICU+JQ0KICANCiAgbXV0YXRlKHJhbmsgPSByYW5rKC10b3RhbF9jbzIpLA0KICAgICAgICAgVmFsdWVfcmVsID0gdG90YWxfY28yL3RvdGFsX2NvMltyYW5rPT0xXSwNCiAgICAgICAgIFZhbHVlX2xibCA9IHBhc3RlMCgiICIscm91bmQodG90YWxfY28yLzFlOSkpKSAlPiUNCiAgZ3JvdXBfYnkoY291bnRyeSkgJT4lIA0KICBmaWx0ZXIocmFuayA8PTE1KSAlPiUNCiAgdW5ncm91cCgpDQogIA0KICBsZiRjb3VudHJ5IDwtIHJlY29kZShsZiRjb3VudHJ5LCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgIlVOSVRFRCBTVEFURVMgT0YgQU1FUklDQSI9IlVTQSIsDQogICAgICAgICJDSElOQSAoTUFJTkxBTkQpIj0iQ0hJTkEiLA0KICAgICAgICAiRlJBTkNFIChJTkNMVURJTkcgTU9OQUNPKSI9IkZSQU5DRSIsDQogICAgICAgICJJVEFMWSAoSU5DTFVESU5HIFNBTiBNQVJJTk8pIj0iSVRBTFkiLA0KICAgICAgICAiUlVTU0lBTiBGRURFUkFUSU9OIiA9ICJSVVNTSUEiDQogICAgICAgIA0KICAgICAgICApDQogICANCiAgDQoNCiAgIA0KICAgc3RhdGljcGxvdCA9IGdncGxvdChsZiwgYWVzKHJhbmssIGdyb3VwID0gY291bnRyeSwgDQogICAgICAgICAgICAgICAgZmlsbCA9IGFzLmZhY3Rvcihjb3VudHJ5KSwgY29sb3IgPSBhcy5mYWN0b3IoY291bnRyeSkpKSArDQogIGdlb21fdGlsZShhZXMoeSA9IHRvdGFsX2NvMi8yLA0KICAgICAgICAgICAgICAgIGhlaWdodCA9IHRvdGFsX2NvMiwNCiAgICAgICAgICAgICAgICB3aWR0aCA9IDAuOSksIGFscGhhID0gMC44LCBjb2xvciA9IE5BKSArDQogIGdlb21fdGV4dChhZXMoeSA9IDAsIGxhYmVsID0gcGFzdGUoY291bnRyeSwgIiAiKSksIHZqdXN0ID0gMC4yLCBoanVzdCA9IDEpICsNCiAgI2dlb21fdGV4dChhZXMoeT10b3RhbF9jbzIsbGFiZWwgPSBWYWx1ZV9sYmwsIGhqdXN0PTApKSArDQogIGNvb3JkX2ZsaXAoY2xpcCA9ICJvZmYiLCBleHBhbmQgPSBGQUxTRSkgKw0KICBzY2FsZV95X2NvbnRpbnVvdXMobGFiZWxzID0gc2NhbGVzOjpjb21tYSkgKw0KICBzY2FsZV94X3JldmVyc2UoKSArDQogIGd1aWRlcyhjb2xvciA9IEZBTFNFLCBmaWxsID0gRkFMU0UpICsNCiAgdGhlbWUoYXhpcy5saW5lPWVsZW1lbnRfYmxhbmsoKSwNCiAgICAgICAgYXhpcy50ZXh0Lng9ZWxlbWVudF9ibGFuaygpLA0KICAgICAgICBheGlzLnRleHQueT1lbGVtZW50X2JsYW5rKCksDQogICAgICAgIGF4aXMudGlja3M9ZWxlbWVudF9ibGFuaygpLA0KICAgICAgICBheGlzLnRpdGxlLng9ZWxlbWVudF9ibGFuaygpLA0KICAgICAgICAgYXhpcy50aXRsZS55PWVsZW1lbnRfYmxhbmsoKSwNCiAgICAgICAgbGVnZW5kLnBvc2l0aW9uPSJub25lIiwNCiAgICAgICAgcGFuZWwuYmFja2dyb3VuZD1lbGVtZW50X2JsYW5rKCksDQogICAgICAgIHBhbmVsLmJvcmRlcj1lbGVtZW50X2JsYW5rKCksDQogICAgICAgIHBhbmVsLmdyaWQubWFqb3I9ZWxlbWVudF9ibGFuaygpLA0KICAgICAgICBwYW5lbC5ncmlkLm1pbm9yPWVsZW1lbnRfYmxhbmsoKSwNCiAgICAgICAgcGFuZWwuZ3JpZC5tYWpvci54ID0gZWxlbWVudF9saW5lKCBzaXplPS4xLCBjb2xvcj0iZ3JleSIgKSwNCiAgICAgICAgcGFuZWwuZ3JpZC5taW5vci54ID0gZWxlbWVudF9saW5lKCBzaXplPS4xLCBjb2xvcj0iZ3JleSIgKSwNCiAgICAgICAgcGxvdC50aXRsZT1lbGVtZW50X3RleHQoc2l6ZT0yNSwgaGp1c3Q9MC41LCBmYWNlPSJib2xkIiwgY29sb3VyPSJncmV5Iiwgdmp1c3Q9LTEpLA0KICAgICAgICBwbG90LnN1YnRpdGxlPWVsZW1lbnRfdGV4dChzaXplPTE4LCBoanVzdD0wLjUsIGZhY2U9Iml0YWxpYyIsIGNvbG9yPSJncmV5IiksDQogICAgICAgIHBsb3QuY2FwdGlvbiA9ZWxlbWVudF90ZXh0KHNpemU9OCwgaGp1c3Q9MC41LCBmYWNlPSJpdGFsaWMiLCBjb2xvcj0iZ3JleSIpLA0KICAgICAgICBwbG90LmJhY2tncm91bmQ9ZWxlbWVudF9ibGFuaygpLA0KICAgICAgIHBsb3QubWFyZ2luID0gbWFyZ2luKDIsMiwgMiwgNCwgImNtIikpDQogICBhbmltID0gc3RhdGljcGxvdCArIHRyYW5zaXRpb25fc3RhdGVzKHllYXIsIHRyYW5zaXRpb25fbGVuZ3RoID0gNCwgc3RhdGVfbGVuZ3RoID0gMSkgKw0KICB2aWV3X2ZvbGxvdyhmaXhlZF94ID0gVFJVRSkgICsNCiAgbGFicyh0aXRsZSA9ICdDTzIgdG90YWwgOiB7Y2xvc2VzdF9zdGF0ZX0nLCAgDQogICAgICAgc3VidGl0bGUgID0gICJUb3AgMTUgcGHDrXNlcyIsDQogICAgICAgY2FwdGlvbiAgPSAiZnVlbnRlOiBXb3JsZCBCYW5rIERhdGEiKQ0KIA0KICANCiAgIGFuaW1fc2F2ZSgiLi9pbWFnZW5lcy9hbmltLmdpZiIsIGFuaW0pDQogIA0KICAgIA0KICBnPC0gIGRmX2NvMl81ICU+JSBnZ3Bsb3QoKSArDQogICAgZ2VvbV9saW5lKGFlcyh5ZWFyLHRvdGFsX2NvMiAsY29sb3IgPSBjb3VudHJ5LGdyb3VwPWNvdW50cnkpICkgKw0KICAgICAgdGhlbWUobGVnZW5kLnBvc2l0aW9uPSJub25lIikNCiAgDQogIA0KICBnb28gPC0gZyArICB0cmFuc2l0aW9uX3JldmVhbCh5ZWFyKSArDQogICAgbGFicyh0aXRsZSA9ICJBw7FvOiB7YXMuaW50ZWdlcihmcmFtZV9hbG9uZyl9IiwgeCA9ICJBw7FvIiwgeSA9IkVtaXNpb25lcyBkZSBjbzIiKQ0KICBhbmltX3NhdmUoIi4vaW1hZ2VuZXMvZ29vLmdpZiIsIGdvbykNCiAgDQp0YWJsYTIgPC0gZGZfY28yXzQgJT4lIHNlbGVjdCh5ZWFyLCBjb3VudHJ5LCB0b3RhbF9jbzIpICU+JSBmaWx0ZXIoeWVhciAlaW4lIGMoMTg1MCwgMTg4OSwgMTg5MCwgMjAwNSwgMjAwNikpICU+JSBncm91cF9ieSh5ZWFyKSAlPiUgc2xpY2VfbWF4KHRvdGFsX2NvMikgJT4lICByZW5hbWUoIkHDsW8iID0geWVhciwgIlBhw61zIiA9IGNvdW50cnksIkVtaXNpb25lcyBkZSBjbzIiID10b3RhbF9jbzIpIA0KDQprbml0cjo6a2FibGUodGFibGEyKQ0KDQpgYGANCg0KDQojIyBDTzIgcGVyIGPDoXBpdGEgey50YWJzZXQgLnRhYnNldC1waWxsc30NCg0KUGFzYW1vcyBhIHZpc3VhbGl6YXIgbG9zIGRhdG9zIGNvbiB1biBncsOhZmljbyBjaXJjdWxhciwgZG9uZGUgcG9kZW1vcyB2ZXIgbG9zIG1heW9yZXMgZW1pc29yZXMgZGVzZGUgZWwgYcOxbyAyMDAwIGRlIGRpw7N4aWRvIGRlIGNhcmJvbm8gcGVyIGPDoXBpdGEuIA0KDQpEZXN0YWNhbW9zIHF1ZSBsb3MgcHJpbWVyb3MgcGFpc2VzIGVuIGVtaXNpb25lcyBkZSBkacOzeGlkbyBkZSBjYXJib25vIHBlciBjw6FwaXRhIHV0aWxpemFuIGNvbW8gZnVlbnRlIGRlIGVuZXJnaWEgcHJpbmNpcGFsIGVsIHBldHLDs2xlbyAoUWF0YXIsIEt1d2FpdCwgRW1pcmF0b3Mgw4FyYWJlcyBVbmlkb3MsIEJhaHJlaW4uLi4pIGEgbGEgdmV6IHF1ZSB0YW1iacOpbiBsbyBleHBvcnRhbiBkZWJpZG8gYSBsYXMgZ3JhbmRlcyByZXNlcnZhcyBkZWwgbWlzbW8uIEVzdGFkb3MgVW5pZG9zIGFwYXJlY2UgZW4gbGEgcG9zaWNpw7NuIG5vdmVuYSB5IENoaW5hLCBlbCBtYXlvciBlbWlzb3IgZGUgQ08yIGVuIHTDqXJtaW5vcyBhYnNvbHV0b3MsIG5vIGFwYXJlY2UgZW50cmUgbG9zIDQwIHByaW1lcm9zLg0KDQojIyMgR3LDoWZpY28NCiANCmBgYHtyIGNvMl9nZjQsIG1lc3NhZ2UgPSBGQUxTRSwgd2FybmluZyA9IEZBTFNFLCByZXN1bHRzID0gVFJVRSxlY2hvID0gRkFMU0UgLCBldmFsID0gVFJVRSxmaWcuaGVpZ2h0ID0gNCwgZmlnLndpZHRoID0gNiwgZmlnLmFsaWduID0gImNlbnRlciIsZHBpID0gMjAwfQ0KICAjR3JhZmljbyBjaXJjdWxhciBwYWlzZXMgY29uIG1heW9yIHByb2QuIGNvMiBwZXIgY2FwaXRhDQoNCg0KIG5fZGYzIDwtIG5fZGYyICU+JSBtdXRhdGUoaWQgPSBzZXEoMSw0MCkpDQpsYWJlbF9kYXRhIDwtIG5fZGYzDQoNCm51bWJlcl9vZl9iYXIgPC0gbnJvdyhsYWJlbF9kYXRhKQ0KYW5nbGUgPC0gIDkwIC0gMzYwICogKGxhYmVsX2RhdGEkaWQtMC41KSAvbnVtYmVyX29mX2JhciAgICAgDQogDQoNCmxhYmVsX2RhdGEkaGp1c3Q8LWlmZWxzZSggYW5nbGUgPCAtOTAsIDEsIDApDQogDQoNCmxhYmVsX2RhdGEkYW5nbGU8LWlmZWxzZShhbmdsZSA8IC05MCwgYW5nbGUrMTgwLCBhbmdsZSkNCg0KDQpwIDwtIGdncGxvdChuX2RmMywgYWVzKHg9YXMuZmFjdG9yKGlkKSwgeT1lbV9jbzJfcGMsZmlsbD1lbV9jbzJfcGMpKSArICAgICAgIA0KIA0KICAgZ2VvbV9iYXIoc3RhdD0iaWRlbnRpdHkiKSArDQogIA0KICB5bGltKC0xMDAsNDAwKSArDQogIA0KICB0aGVtZV9taW5pbWFsKCkgKw0KICB0aGVtZSgNCiAgICBheGlzLnRleHQgPSBlbGVtZW50X2JsYW5rKCksDQogICAgYXhpcy50aXRsZSA9IGVsZW1lbnRfYmxhbmsoKSwNCiAgICBwYW5lbC5ncmlkID0gZWxlbWVudF9ibGFuaygpLA0KICAgIHBsb3QubWFyZ2luID0gdW5pdChyZXAoLTEsNCksICJjbSIpICAgICAgDQogICkgKw0KICANCiAgDQogIGNvb3JkX3BvbGFyKHN0YXJ0ID0gMCkgKw0KICANCiAgDQogIGdlb21fdGV4dChkYXRhPWxhYmVsX2RhdGEsIGFlcyh4PWlkLCB5PWVtX2NvMl9wYywgbGFiZWw9Y291bnRyeSwgaGp1c3Q9aGp1c3QpLCBjb2xvcj0iYmxhY2siLCBmb250ZmFjZT0iYm9sZCIsYWxwaGE9MC42LCBzaXplPTIuNSwgYW5nbGU9IGxhYmVsX2RhdGEkYW5nbGUsIGluaGVyaXQuYWVzID0gRkFMU0UgKSArDQogIHNjYWxlX2ZpbGxfdmlyaWRpc19jKG9wdGlvbiA9ICJCIiwgdHJhbnMgPSAic3FydCIpICsNCiAgbGFicyh0aXRsZSA9ICJQYcOtc2VzIGNvbiBtYXlvcmVzIGVtaXNpb25lcyBkZSBjbzIgcGVyIGPDoXBpdGEiLCB5ID0gIkVtaXNpb25lcyBkZSBjbzIgcGVyIGPDoXBpdGEiKQ0KIA0KcA0KDQoNCg0KYGBgDQoNCiMjIyBUYWJsYQ0KDQpgYGB7ciwgZWNobyA9IEZBTFNFICwgZXZhbCA9IFRSVUV9DQp0YWJsYTMgPC0gbl9kZjMgJT4lIHNlbGVjdChjb3VudHJ5LCBlbV9jbzJfcGMpICU+JSBzbGljZV9tYXgoZW1fY28yX3BjLCBuID0gMTApDQprbml0cjo6a2FibGUodGFibGEzKQ0KYGBgDQogDQojIyMgQ8OzZGlnbw0KYGBge3IgY28yX2dmMyxlY2hvID0gVFJVRSAsIGV2YWwgPSBGQUxTRSB9DQoNCg0KDQogbl9kZjMgPC0gbl9kZjIgJT4lIG11dGF0ZShpZCA9IHNlcSgxLDQwKSkNCmxhYmVsX2RhdGEgPC0gbl9kZjMNCg0KbnVtYmVyX29mX2JhciA8LSBucm93KGxhYmVsX2RhdGEpDQphbmdsZSA8LSAgOTAgLSAzNjAgKiAobGFiZWxfZGF0YSRpZC0wLjUpIC9udW1iZXJfb2ZfYmFyICAgICANCiANCg0KbGFiZWxfZGF0YSRoanVzdDwtaWZlbHNlKCBhbmdsZSA8IC05MCwgMSwgMCkNCiANCg0KbGFiZWxfZGF0YSRhbmdsZTwtaWZlbHNlKGFuZ2xlIDwgLTkwLCBhbmdsZSsxODAsIGFuZ2xlKQ0KDQoNCg0KDQpwIDwtIGdncGxvdChuX2RmMywgYWVzKHg9YXMuZmFjdG9yKGlkKSwgeT1lbV9jbzJfcGMsZmlsbD1lbV9jbzJfcGMpKSArICAgICAgIA0KDQogIGdlb21fYmFyKHN0YXQ9ImlkZW50aXR5IikgKw0KICANCiANCiAgeWxpbSgtMTAwLDQwMCkgKw0KICANCg0KICB0aGVtZV9taW5pbWFsKCkgKw0KICB0aGVtZSgNCiAgICBheGlzLnRleHQgPSBlbGVtZW50X2JsYW5rKCksDQogICAgYXhpcy50aXRsZSA9IGVsZW1lbnRfYmxhbmsoKSwNCiAgICBwYW5lbC5ncmlkID0gZWxlbWVudF9ibGFuaygpLA0KICAgIHBsb3QubWFyZ2luID0gdW5pdChyZXAoLTEsNCksICJjbSIpICAgICAgDQogICkgKw0KICANCiAgY29vcmRfcG9sYXIoc3RhcnQgPSAwKSArDQogIA0KICANCiAgZ2VvbV90ZXh0KGRhdGE9bGFiZWxfZGF0YSwgYWVzKHg9aWQsIHk9ZW1fY28yX3BjLCBsYWJlbD1jb3VudHJ5LCBoanVzdD1oanVzdCksIGNvbG9yPSJibGFjayIsIGZvbnRmYWNlPSJib2xkIixhbHBoYT0wLjYsIHNpemU9Mi41LCBhbmdsZT0gbGFiZWxfZGF0YSRhbmdsZSwgaW5oZXJpdC5hZXMgPSBGQUxTRSApICsNCiAgc2NhbGVfZmlsbF92aXJpZGlzX2Mob3B0aW9uID0gIkIiLCB0cmFucyA9ICJzcXJ0IikNCiANCnANCg0KdGFibGEzIDwtIG5fZGYzICU+JSBzbGljZV9tYXgoZW1fY28yX3BjLCBuID0gMTApDQprbml0cjo6a2FibGUodGFibGEzKQ0KDQpgYGANCg0KDQoNCiMjIE1heW9yZXMgcHJvZHVjdG9yZXMgZGUgY28yIGVuIGxhIGhpc3RvcmlhIHsudGFic2V0IC50YWJzZXQtcGlsbHN9DQoNCkFob3JhIGVzdHVkaWFtb3MgZWwgdG90YWwgYWN1bXVsYWRvIGRlIGVtaXNpb25lcyBkZSBDTzIgcG9yIHBhw61zLCB5IG9ic2VydmFtb3MgcXVlIGxvcyA1IHByaW1lcm9zIHNvbiBFc3RhZG9zIFVuaWRvcyAocXVpw6luIGVzdHV2byBkdXJhbnRlIHRvZG8gZWwgc2lnbG8gWFggY29tbyBwcmltZXIgZW1pc29yKSwgQ2hpbmEgKGFjdHVhbCBwcmltZXIgZW1pc29yIGRlc2RlIDIwMDYgZGUgQ08yKSwgbGEgVVJTUyAoY3V5b3MgZGF0b3MgdGVybWluYW4gZW4gMTk5MiBjb24gc3UgZGlzb2x1Y2nDs24pLCBSZWlubyBVbmlkbyAocHJpbmNpcGFsIGVtaXNvciBlbiAxODUwLTE4OTAgY29uIGxhIFJldm9sdWNpw7NuIEluZHVzdHJpYWwpIHkgSmFww7NuLiBMbyB2ZW1vcyBkZSBkb3MgZm9ybWFzOg0KDQojIyMgR3LDoWZpY28gMQ0KYGBge3IsIGV2YWw9VFJVRSwgZWNobz0gRkFMU0UgfQ0KDQogICNncsOhZmljbyBtYXlvcmVzIHByb2R1Y3RvcmVzIGNvMiBkZWwgbXVuZG8oYWN1bXVsYWRvIHRvdGFsKQ0KICAgIA0KIGg8LSBuX2RmICU+JSBnZ3Bsb3QoYWVzKHggPSByZW9yZGVyKGNvdW50cnksIHRvdGFsX2NvMiksdG90YWxfY28yLGZpbGw9IHRvdGFsX2NvMikpICsNCiAgICBnZW9tX2JhcihzdGF0ID0gImlkZW50aXR5IikgKw0KICAgIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikgKw0KICAgIGNvb3JkX2ZsaXAoKSArIA0KICBsYWJzKHkgPSAiQ28yIHRvdGFsIiAsIHg9ICIgUGHDrXNlcyIpDQogIA0KICBoDQoNCmBgYA0KDQojIyMgR3LDoWZpY28gMg0KDQpgYGB7ciwgZWNobz1GQUxTRX0NCmRmX2NvMl81IDwtZGZfY28yXzQgJT4lIGdyb3VwX2J5KGNvdW50cnkpDQogbl9kZl8wIDwtIGRmX2NvMl80JT4lIHNlbGVjdCh5ZWFyLGNvdW50cnksdG90YWxfY28yKSU+JSAgZmlsdGVyKHllYXI9PTIwMTApICU+JSBncm91cF9ieShjb3VudHJ5KSU+JSBzZWxlY3QoLXllYXIpICU+JSBhcnJhbmdlKHRvdGFsX2NvMikNCiAgbl9kZl8xIDwtIGRmX2NvMl80ICU+JSBncm91cF9ieShjb3VudHJ5KSAlPiUgc3VtbWFyaXNlKHRvdGFsX2NvMj1zdW0odG90YWxfY28yKSklPiUgdW5ncm91cCgpICU+JSBzbGljZV9tYXgodG90YWxfY28yLG49MjApICU+JSBhcnJhbmdlKGRlc2ModG90YWxfY28yKSkNCiAgbl9kZl8yIDwtIGRmX2NvMl80ICU+JSBmaWx0ZXIoeWVhciA+IDIwMDApICU+JSBncm91cF9ieShjb3VudHJ5KSAlPiUgc3VtbWFyaXNlKGVtX2NvMl9wYz1zdW0oZW1fY28yX3BjKSklPiUgdW5ncm91cCgpICU+JSBzbGljZV9tYXgoZW1fY28yX3BjLG49MTUpICU+JSBhcnJhbmdlKGRlc2MoZW1fY28yX3BjKSkNCiANCiAgIA0KICBuX2RmXzMgPC0gZGZfY28yXzQlPiUgZ3JvdXBfYnkoY291bnRyeSkgJT4lIHN1bW1hcmlzZShlbV9jbzJfcGM9c3VtKGVtX2NvMl9wYykpJT4lIHVuZ3JvdXAoKSAgJT4lIGFycmFuZ2UoZGVzYyhlbV9jbzJfcGMpKQ0KcjwtIG5fZGYgJT4lIGdncGxvdChhZXMoeCA9IHJlb3JkZXIoY291bnRyeSwgdG90YWxfY28yKSx0b3RhbF9jbzIsZmlsbD0gY291bnRyeSkpICsNCiAgICBnZW9tX2JhcihzdGF0ID0gImlkZW50aXR5IikgKw0KICAgIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikgKw0KICAgIGNvb3JkX2ZsaXAoKSArDQogIGxhYnModGl0bGUgPSAiRW1pc2lvbmVzIGRlIGNvMiB0b3RhbGVzIHBvciBwYcOtcyIsIHggPSAiUGHDrXMiLCB5ID0gImVtaXNpb25lcyBkZSBjbzIgdG90YWxlcyIpDQogIGdncGxvdGx5KHIpDQogIA0KDQoNCmBgYA0KDQojIyMgQ8OzZGlnbw0KYGBge3IsIGV2YWw9IEZBTFNFLCBlY2hvPSBUUlVFIH0NCg0KICAjZ3LDoWZpY28gbWF5b3JlcyBwcm9kdWN0b3JlcyBjbzIgZGVsIG11bmRvKGFjdW11bGFkbyB0b3RhbCkNCiAgICANCiBwPC0gbl9kZiAlPiUgZ2dwbG90KGFlcyh4ID0gcmVvcmRlcihjb3VudHJ5LCB0b3RhbF9jbzIpLHRvdGFsX2NvMixmaWxsPSB0b3RhbF9jbzIpKSArDQogICAgZ2VvbV9iYXIoc3RhdCA9ICJpZGVudGl0eSIpICsNCiAgICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAibm9uZSIpICsNCiAgICBjb29yZF9mbGlwKCkNCiAgcA0KICAgI2dyw6FmaWNvIG1heW9yZXMgcHJvZHVjdG9yZXMgY28yIGRlbCBtdW5kbyhhY3VtdWxhZG8gdG90YWwpDQogICAgDQogaDwtIG5fZGYgJT4lIGdncGxvdChhZXMoeCA9IHJlb3JkZXIoY291bnRyeSwgdG90YWxfY28yKSx0b3RhbF9jbzIsZmlsbD0gdG90YWxfY28yKSkgKw0KICAgIGdlb21fYmFyKHN0YXQgPSAiaWRlbnRpdHkiKSArDQogICAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKSArDQogICAgY29vcmRfZmxpcCgpICsgDQogIGxhYnMoeCA9ICJDbzIgdG90YWwiICwgeT0gIiBQYcOtc2VzIikNCiAgDQogIGgNCg0KYGBgDQoNCg0KDQoNCg0KIyMgVW5hIGZvcm1hIGRpZmVyZW50ZSBkZSB2aXN1YWxpemFyIGxvcyBkYXRvcyAgey50YWJzZXQgLnRhYnNldC1waWxsc30NCg0KIyMjICJXb3JkY2xvdWQiDQohW10oLi9pbWFnZW5lcy9ycGxvdC5qcGVnKQ0KIA0KYGBge3IgZmlnLmhlaWdodCA9IDIsIGZpZy53aWR0aCA9IDcgLGRwaSA9IDE1MCxmaWcuYWxpZ24gPSAiY2VudGVyIiwgZXZhbD0gRkFMU0UsIGVjaG89IEZBTFNFfQ0KI0dyw6FmaWNvIHBhaXNlcyBjb24gbWFzIGVtaXNpb25lcyBkZSBjbzINCg0Kbl9kZjYgPC0gZGZfY28yXzQgJT4lIGdyb3VwX2J5KGNvdW50cnkpICU+JSBzdW1tYXJpc2UodG90YWxfY28yPXN1bSh0b3RhbF9jbzIpKSU+JSB1bmdyb3VwKCkgJT4lIGFycmFuZ2UoZGVzYyh0b3RhbF9jbzIpKQ0KICANCg0KICAgICAgbl9kZl8wJGNvdW50cnkgPC0gcmVjb2RlKG5fZGZfMCRjb3VudHJ5LCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgIlVOSVRFRCBTVEFURVMgT0YgQU1FUklDQSI9IlVTQSIsDQogICAgICAgICJDSElOQSAoTUFJTkxBTkQpIj0iQ0hJTkEiLA0KICAgICAgICAiRlJBTkNFIChJTkNMVURJTkcgTU9OQUNPKSI9IkZSQU5DRSIsDQogICAgICAgICJJVEFMWSAoSU5DTFVESU5HIFNBTiBNQVJJTk8pIj0iSVRBTFkiLA0KICAgICAgICAiUlVTU0lBTiBGRURFUkFUSU9OIiA9ICJSVVNTSUEiDQogICAgICAgIA0KICAgICAgICApDQogIA0KICB3b3JkY2xvdWQyKGRhdGEgPSBuX2RmXzAsIHNpemUgPSAwLjgNCiAgKQ0KDQoNCg0KDQpgYGANCiANCiMjIyBDw7NkaWdvDQoNCmBgYHtyIGZpZy5oZWlnaHQgPSAyLCBmaWcud2lkdGggPSA3ICxkcGkgPSAxNTAsZmlnLmFsaWduID0gImNlbnRlciJ9DQojR3LDoWZpY28gcGFpc2VzIGNvbiBtYXMgZW1pc2lvbmVzIGRlIGNvMg0KDQpuX2RmNiA8LSBkZl9jbzJfNCAlPiUgZ3JvdXBfYnkoY291bnRyeSkgJT4lIHN1bW1hcmlzZSh0b3RhbF9jbzI9c3VtKHRvdGFsX2NvMikpJT4lIHVuZ3JvdXAoKSAlPiUgYXJyYW5nZShkZXNjKHRvdGFsX2NvMikpDQogIA0KICANCiAgICAgIG5fZGZfMCRjb3VudHJ5IDwtIHJlY29kZShuX2RmXzAkY291bnRyeSwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICJVTklURUQgU1RBVEVTIE9GIEFNRVJJQ0EiPSJVU0EiLA0KICAgICAgICAiQ0hJTkEgKE1BSU5MQU5EKSI9IkNISU5BIiwNCiAgICAgICAgIkZSQU5DRSAoSU5DTFVESU5HIE1PTkFDTykiPSJGUkFOQ0UiLA0KICAgICAgICAiSVRBTFkgKElOQ0xVRElORyBTQU4gTUFSSU5PKSI9IklUQUxZIiwNCiAgICAgICAgIlJVU1NJQU4gRkVERVJBVElPTiIgPSAiUlVTU0lBIg0KICAgICAgICANCiAgICAgICAgKQ0KICANCiAgd29yZGNsb3VkMihkYXRhID0gbl9kZl8wLCBzaXplID0gMC44DQogICkNCg0KDQoNCg0KYGBgDQoNCiMjIENvcm9wbGV0YXMgey50YWJzZXQgLnRhYnNldC1waWxsc30NCg0KUGFzYW1vcyBhIHV0aWxpemFyIHVuYSByZXByZXNlbnRhY2nDs24gZ2VvZ3LDoWZpY2EgcGFyYSB2ZXIgbGFzIGVtaXNpb25lcyBkZSBDTzIgcG9yIHBhw61zIGVuIDIwMTAgeSBsYXMgZW1pc2lvbmVzIHBvciBwYcOtcyB5IHBlciBjw6FwaXRhIHBhcmEgZWwgbWlzbW8gYcOxby4gDQoNCkxvcyBjb2xvcmVzIG3DoXMgb3NjdXJvcyBpbmRpY2FuIHVuYSBtYXlvciBlbWlzacOzbiBkZSBDTzIgYSBsYSBhdG1vc2ZlcmEgZG9uZGUgY2xhcmFtZW50ZSBzZSBkaXN0aW5ndWVuIENoaW5hIHkgRXN0YWRvcyBVbmlkb3MgZW4gdMOpcm1pbm9zIGFic29sdXRvcy4NCg0KUGFyYSBsYXMgZW1pc2lvbmVzIGRlIENPMiBwZXIgY8OhcGl0YSBlbCBjb2xvciBtw6FzIGNsYXJvIHJlcHJlc2VudGEgdW5hIG1heW9yIGVtaXNpw7NuIGRlIGVzdG9zIGdhc2VzLCBkb25kZSBvYnNlcnZhbW9zIGEgdmFyaW9zIHBhw61zZXMgw6FyYWJlcyAoY29uIHJlc2VydmFzIGRlIHBldHLDs2xlbykgY29tbyBwcmluY2lwYWxlcyBlbWlzb3JlcyBwZXIgY8OhcGl0YS4NCg0KIyMjIEVtaXNpb25lcyBkZSBDTzIgcG9yIHBhw61zIDIwMTANCmBgYHtyLGV2YWw9VFJVRSxlY2hvPSBGQUxTRX0NCiNpbnN0YWxsLnBhY2thZ2VzKCJ2aXJpZGlzIikNCmxpYnJhcnkodmlyaWRpcykNCg0KbGlicmFyeShzZikNCg0KbGlicmFyeSh0aWR5dmVyc2UpDQoNCndvcmxkIDwtIHJuYXR1cmFsZWFydGg6Om5lX2NvdW50cmllcyhzY2FsZSA9ICJtZWRpdW0iLCByZXR1cm5jbGFzcyA9ICJzZiIpDQp3b3JsZF9wb2ludHM8LSBzdF9jZW50cm9pZCh3b3JsZCkNCndvcmxkX3BvaW50cyA8LSBjYmluZCh3b3JsZCwgc3RfY29vcmRpbmF0ZXMoc3RfY2VudHJvaWQod29ybGQkZ2VvbWV0cnkpKSkNCg0KDQoNCg0KI21hcGEgY28yIA0KDQoNCg0KZGNvMjwtIHJlYWRfY3N2KCIuL0RhdG9zL2NvMi5jc3YiKQ0Kd29ybGQgPC0gcm5hdHVyYWxlYXJ0aDo6bmVfY291bnRyaWVzKHNjYWxlID0gIm1lZGl1bSIsIHJldHVybmNsYXNzID0gInNmIikNCg0KDQpkY28yWyBkY28yID09ICIuLiIgXSA8LSBOQQ0KDQoNCg0KDQpkY28yIDwtIGRjbzIgJT4lIHNlbGVjdChgQ291bnRyeSBOYW1lYCxgMjAxMCBbWVIyMDEwXWApDQpkZm8zIDwtIGRjbzIgJT4lIHJlbmFtZShzb3ZlcmVpZ250ID0gYENvdW50cnkgTmFtZWAsDQogICAgICAgICAgICAgICAgICAgICAgICBjbzIgPSBgMjAxMCBbWVIyMDEwXWANCiAgICAgICAgICAgICAgICAgICAgICAgIA0KKQ0KDQoNCg0KZGZvMyRzb3ZlcmVpZ250IDwtIHJlY29kZShkZm8zJHNvdmVyZWlnbnQsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAiVW5pdGVkIFN0YXRlcyI9IlVuaXRlZCBTdGF0ZXMgb2YgQW1lcmljYSIsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAiUnVzc2lhbiBGZWRlcmF0aW9uIiA9ICJSdXNzaWEiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAiVmVuZXp1ZWxhLCBSQiIgPSAiVmVuZXp1ZWxhIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgIkNvbmdvLCBEZW0uIFJlcC4iID0gIkRlbW9jcmF0aWMgUmVwdWJsaWMgb2YgdGhlIENvbmdvIiAsDQogICAgICAgICAgICAgICAgICAgICAgICAgICIJQ29uZ28sIFJlcC4iPSJSZXB1YmxpYyBvZiBDb25nbyIJICwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgIkVneXB0LCBBcmFiIFJlcC4iID0gIkVneXB0IiAsDQogICAgICAgICAgICAgICAgICAgICAgICAgICJUYW56YW5pYSIgPSAiVW5pdGVkIFJlcHVibGljIG9mIFRhbnphbmlhIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgIkNvdGUgZCdJdm9pcmUiID0gIkl2b3J5IENvYXN0IiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgIlllbWVuLCBSZXAuIiA9ICJZZW1lbiIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICJJcmFuLCBJc2xhbWljIFJlcC4iID0gIklyYW4iLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAiU3lyaWFuIEFyYWIgUmVwdWJsaWMiID0gIlN5cmlhIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgIlNsb3ZhayBSZXB1YmxpYyIgPSAiU2xvdmFraWEiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAiU2VyYmlhIiA9ICJSZXB1YmxpYyBvZiBTZXJiaWEiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAiTm9ydGggTWFjZWRvbmlhIiA9ICJNYWNlZG9uaWEiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAiS3lyZ3l6IFJlcHVibGljIiA9ICJLeXJneXpzdGFuIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgIktvcmVhLCBEZW0uIFBlb3BsZeKAmXMgUmVwIiA9ICJOb3J0aCBLb3JlYSIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICJLb3JlYSwgUmVwLiIgPSAiU291dGggS29yZWEiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAiTGFvIFBEUiIgPSAiTGFvcyINCikNCg0KDQpkZl9pbm5lciA8LSBsZWZ0X2pvaW4od29ybGQsZGZvMykNCmRmX2NvMiA8LSAgdHJhbnNmb3JtKGRmX2lubmVyLCBjbzIgPSBhcy5udW1lcmljKGNvMikgICANCikgJT4lIGZpbHRlcighKHNvdmVyZWlnbnQgPT0gIkFudGFyY3RpY2EiKSkNCg0KcCA8LSBnZ3Bsb3QoZGF0YSA9IGRmX2NvMikgKyBnZW9tX3NmKCkgKw0KICBsYWJzKHRpdGxlID0gIk1hcGEgZW1pc2lvbmVzIGRlIGNvMiIsDQogICAgICAgY2FwdGlvbiA9ICJEYXRvcyBwcm92ZW5pZW50ZXMgZGUgV29ybGQgQmFuayIpDQpwICsgZ2VvbV9zZihhZXMoZmlsbCA9IGNvMiwgY29sb3IgPWNvMikpICsgc2NhbGVfZmlsbF92aXJpZGlzKGRpcmVjdGlvbiA9IC0xLCBsYWJlbCA9IHNjYWxlczo6bnVtYmVyLGJlZ2luID0gMCwgZW5kID0gMC44LCkgKyANCiAgc2NhbGVfY29sb3JfdmlyaWRpcyhkaXJlY3Rpb24gPSAtMSwgbGFiZWwgPSBzY2FsZXM6Om51bWJlcixiZWdpbiA9IDAsIGVuZCA9IDAuOCkgDQpgYGANCg0KIyMjIEVtaXNpb25lcyBjbzIgcGVyIGPDoXBpdGENCmBgYCB7ciwgZXZhbCA9IFRSVUUgLCBlY2hvID0gRkFMU0V9DQpsaWJyYXJ5KHZpcmlkaXMpDQoNCmxpYnJhcnkoc2YpDQoNCmxpYnJhcnkodGlkeXZlcnNlKQ0KDQp3b3JsZCA8LSBybmF0dXJhbGVhcnRoOjpuZV9jb3VudHJpZXMoc2NhbGUgPSAibWVkaXVtIiwgcmV0dXJuY2xhc3MgPSAic2YiKQ0Kd29ybGRfcG9pbnRzPC0gc3RfY2VudHJvaWQod29ybGQpDQp3b3JsZF9wb2ludHMgPC0gY2JpbmQod29ybGQsIHN0X2Nvb3JkaW5hdGVzKHN0X2NlbnRyb2lkKHdvcmxkJGdlb21ldHJ5KSkpDQpkY28yX3BjPC0gcmVhZF9jc3YoIi4vRGF0b3MvY28yX3BjLmNzdiIpDQoNCg0KDQpkY28yX3BjWyBkY28yX3BjID09ICIuLiIgXSA8LSBOQQ0KDQoNCg0KDQpkY29fcGMgPC0gZGNvMl9wYyAlPiUgc2VsZWN0KGBDb3VudHJ5IE5hbWVgLGAyMDEwIFtZUjIwMTBdYCkNCmRmbzNfcGMgPC0gZGNvMl9wYyAlPiUgcmVuYW1lKHNvdmVyZWlnbnQgPSBgQ291bnRyeSBOYW1lYCwNCiAgICAgICAgICAgICAgICAgICAgICAgIGNvMl9wYyA9IGAyMDEwIFtZUjIwMTBdYA0KICAgICAgICAgICAgICAgICAgICAgICAgDQopDQoNCg0KDQpkZm8zX3BjJHNvdmVyZWlnbnQgPC0gcmVjb2RlKGRmbzNfcGMkc292ZXJlaWdudCwgDQogICAgICAgICAgICAgICAgICAgICAgIlVuaXRlZCBTdGF0ZXMiPSJVbml0ZWQgU3RhdGVzIG9mIEFtZXJpY2EiLCANCiAgICAgICAgICAgICAgICAgICAgICAiUnVzc2lhbiBGZWRlcmF0aW9uIiA9ICJSdXNzaWEiLA0KICAgICAgICAgICAgICAgICAgICAgICJWZW5lenVlbGEsIFJCIiA9ICJWZW5lenVlbGEiLA0KICAgICAgICAgICAgICAgICAgICAgICAiQ29uZ28sIERlbS4gUmVwLiIgPSAiRGVtb2NyYXRpYyBSZXB1YmxpYyBvZiB0aGUgQ29uZ28iICwNCiAgICAgICAgICAgICAgIglDb25nbywgUmVwLiI9IlJlcHVibGljIG9mIENvbmdvIgkgLA0KICAgICAgICAgICAgICAiRWd5cHQsIEFyYWIgUmVwLiIgPSAiRWd5cHQiICwNCiAgICAgICAgICAgICAiVGFuemFuaWEiID0gIlVuaXRlZCBSZXB1YmxpYyBvZiBUYW56YW5pYSIsDQogICAgICAgICAgICAgIkNvdGUgZCdJdm9pcmUiID0gIkl2b3J5IENvYXN0IiwNCiAgICAgICAgICAgICAiWWVtZW4sIFJlcC4iID0gIlllbWVuIiwNCiAgICAgICAgICAgICAiSXJhbiwgSXNsYW1pYyBSZXAuIiA9ICJJcmFuIiwNCiAgICAgICAgICAgICAiU3lyaWFuIEFyYWIgUmVwdWJsaWMiID0gIlN5cmlhIiwNCiAgICAgICAgICAgICAiU2xvdmFrIFJlcHVibGljIiA9ICJTbG92YWtpYSIsDQogICAgICAgICAgICAgIlNlcmJpYSIgPSAiUmVwdWJsaWMgb2YgU2VyYmlhIiwNCiAgICAgICAgICAgICAiTm9ydGggTWFjZWRvbmlhIiA9ICJNYWNlZG9uaWEiLA0KICAgICAgICAgICAgICJLeXJneXogUmVwdWJsaWMiID0gIkt5cmd5enN0YW4iLA0KICAgICAgICAgICAgICJLb3JlYSwgRGVtLiBQZW9wbGXigJlzIFJlcCIgPSAiTm9ydGggS29yZWEiLA0KICAgICAgICAgICAgICJLb3JlYSwgUmVwLiIgPSAiU291dGggS29yZWEiLA0KICAgICAgICAgICAgICJMYW8gUERSIiA9ICJMYW9zIg0KKQ0KDQoNCmRmX2lubmVyX3BjIDwtIGxlZnRfam9pbih3b3JsZCxkZm8zX3BjKQ0KZGZfY28yX3BjIDwtICB0cmFuc2Zvcm0oZGZfaW5uZXJfcGMsIGNvMl9wYyA9IGFzLm51bWVyaWMoY28yX3BjKSkgJT4lIGZpbHRlcighKHNvdmVyZWlnbnQgPT0gIkFudGFyY3RpY2EiKSkNCg0KcCA8LSBnZ3Bsb3QoZGF0YSA9IGRmX2NvMl9wYykgKyBnZW9tX3NmKCkgKw0KICBsYWJzKHRpdGxlID0gIkVtaXNpb25lcyBjbzIgcGVyIGPDoXBpdGEiLA0KICAgICAgIGNhcHRpb24gPSAiRGF0b3MgcHJvdmVuaWVudGVzIGRlIFdvcmxkIEJhbmsiKQ0KcCArIGdlb21fc2YoYWVzKGZpbGwgPSBjbzJfcGMpKSArIHNjYWxlX2ZpbGxfdmlyaWRpc19jKG9wdGlvbiA9ICJCIiwgdHJhbnMgPSAic3FydCIpIA0KDQoNCiANCmBgYCANCiANCg0KIyMjIEPDs2RpZ28gDQoNCmBgYHtyLGV2YWw9IEZBTFNFLGVjaG89IFRSVUV9DQojaW5zdGFsbC5wYWNrYWdlcygidmlyaWRpcyIpDQpsaWJyYXJ5KHZpcmlkaXMpDQoNCmxpYnJhcnkoc2YpDQoNCmxpYnJhcnkodGlkeXZlcnNlKQ0KDQp3b3JsZCA8LSBybmF0dXJhbGVhcnRoOjpuZV9jb3VudHJpZXMoc2NhbGUgPSAibWVkaXVtIiwgcmV0dXJuY2xhc3MgPSAic2YiKQ0Kd29ybGRfcG9pbnRzPC0gc3RfY2VudHJvaWQod29ybGQpDQp3b3JsZF9wb2ludHMgPC0gY2JpbmQod29ybGQsIHN0X2Nvb3JkaW5hdGVzKHN0X2NlbnRyb2lkKHdvcmxkJGdlb21ldHJ5KSkpDQojbWFwYSBjbzIgcGVyIGNhcGl0YQ0KbGlicmFyeSh0aWR5dmVyc2UpDQoNCg0KDQojbWFwYSBjbzIgDQoNCg0KDQpkY28yPC0gcmVhZF9jc3YoIi4vRGF0b3MvY28yLmNzdiIpDQp3b3JsZCA8LSBybmF0dXJhbGVhcnRoOjpuZV9jb3VudHJpZXMoc2NhbGUgPSAibWVkaXVtIiwgcmV0dXJuY2xhc3MgPSAic2YiKQ0KDQoNCmRjbzJbIGRjbzIgPT0gIi4uIiBdIDwtIE5BDQoNCg0KDQoNCmRjbzIgPC0gZGNvMiAlPiUgc2VsZWN0KGBDb3VudHJ5IE5hbWVgLGAyMDEwIFtZUjIwMTBdYCkNCmRmbzMgPC0gZGNvMiAlPiUgcmVuYW1lKHNvdmVyZWlnbnQgPSBgQ291bnRyeSBOYW1lYCwNCiAgICAgICAgICAgICAgICAgICAgICAgIGNvMiA9IGAyMDEwIFtZUjIwMTBdYA0KICAgICAgICAgICAgICAgICAgICAgICAgDQopDQoNCg0KDQpkZm8zJHNvdmVyZWlnbnQgPC0gcmVjb2RlKGRmbzMkc292ZXJlaWdudCwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICJVbml0ZWQgU3RhdGVzIj0iVW5pdGVkIFN0YXRlcyBvZiBBbWVyaWNhIiwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICJSdXNzaWFuIEZlZGVyYXRpb24iID0gIlJ1c3NpYSIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICJWZW5lenVlbGEsIFJCIiA9ICJWZW5lenVlbGEiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAiQ29uZ28sIERlbS4gUmVwLiIgPSAiRGVtb2NyYXRpYyBSZXB1YmxpYyBvZiB0aGUgQ29uZ28iICwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgIglDb25nbywgUmVwLiI9IlJlcHVibGljIG9mIENvbmdvIgkgLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAiRWd5cHQsIEFyYWIgUmVwLiIgPSAiRWd5cHQiICwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgIlRhbnphbmlhIiA9ICJVbml0ZWQgUmVwdWJsaWMgb2YgVGFuemFuaWEiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAiQ290ZSBkJ0l2b2lyZSIgPSAiSXZvcnkgQ29hc3QiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAiWWVtZW4sIFJlcC4iID0gIlllbWVuIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgIklyYW4sIElzbGFtaWMgUmVwLiIgPSAiSXJhbiIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICJTeXJpYW4gQXJhYiBSZXB1YmxpYyIgPSAiU3lyaWEiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAiU2xvdmFrIFJlcHVibGljIiA9ICJTbG92YWtpYSIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICJTZXJiaWEiID0gIlJlcHVibGljIG9mIFNlcmJpYSIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICJOb3J0aCBNYWNlZG9uaWEiID0gIk1hY2Vkb25pYSIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICJLeXJneXogUmVwdWJsaWMiID0gIkt5cmd5enN0YW4iLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAiS29yZWEsIERlbS4gUGVvcGxl4oCZcyBSZXAiID0gIk5vcnRoIEtvcmVhIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgIktvcmVhLCBSZXAuIiA9ICJTb3V0aCBLb3JlYSIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICJMYW8gUERSIiA9ICJMYW9zIg0KKQ0KDQoNCmRmX2lubmVyIDwtIGxlZnRfam9pbih3b3JsZCxkZm8zKQ0KZGZfY28yIDwtICB0cmFuc2Zvcm0oZGZfaW5uZXIsIGNvMiA9IGFzLm51bWVyaWMoY28yKSAgIA0KKSAlPiUgZmlsdGVyKCEoc292ZXJlaWdudCA9PSAiQW50YXJjdGljYSIpKQ0KDQpwIDwtIGdncGxvdChkYXRhID0gZGZfY28yKSArIGdlb21fc2YoKSArDQogIGxhYnModGl0bGUgPSAiTWFwYSBlbWlzaW9uZXMgZGUgY28yIiwNCiAgICAgICBjYXB0aW9uID0gIkRhdG9zIHByb3ZlbmllbnRlcyBkZSBXb3JsZCBCYW5rIikNCnAgKyBnZW9tX3NmKGFlcyhmaWxsID0gY28yLCBjb2xvciA9Y28yKSkgKyBzY2FsZV9maWxsX3ZpcmlkaXMoZGlyZWN0aW9uID0gLTEsIGxhYmVsID0gc2NhbGVzOjpudW1iZXIsYmVnaW4gPSAwLCBlbmQgPSAwLjgsKSArIA0KICBzY2FsZV9jb2xvcl92aXJpZGlzKGRpcmVjdGlvbiA9IC0xLCBsYWJlbCA9IHNjYWxlczo6bnVtYmVyLGJlZ2luID0gMCwgZW5kID0gMC44KSANCg0KI0dyw6FmaWNvIGNvMiBwYw0KbGlicmFyeSh2aXJpZGlzKQ0KDQpsaWJyYXJ5KHNmKQ0KDQpsaWJyYXJ5KHRpZHl2ZXJzZSkNCg0Kd29ybGQgPC0gcm5hdHVyYWxlYXJ0aDo6bmVfY291bnRyaWVzKHNjYWxlID0gIm1lZGl1bSIsIHJldHVybmNsYXNzID0gInNmIikNCndvcmxkX3BvaW50czwtIHN0X2NlbnRyb2lkKHdvcmxkKQ0Kd29ybGRfcG9pbnRzIDwtIGNiaW5kKHdvcmxkLCBzdF9jb29yZGluYXRlcyhzdF9jZW50cm9pZCh3b3JsZCRnZW9tZXRyeSkpKQ0KZGNvMl9wYzwtIHJlYWRfY3N2KCIuL0RhdG9zL2NvMl9wYy5jc3YiKQ0KDQoNCg0KZGNvMl9wY1sgZGNvMl9wYyA9PSAiLi4iIF0gPC0gTkENCg0KDQoNCg0KZGNvX3BjIDwtIGRjbzJfcGMgJT4lIHNlbGVjdChgQ291bnRyeSBOYW1lYCxgMjAxMCBbWVIyMDEwXWApDQpkZm8zX3BjIDwtIGRjbzJfcGMgJT4lIHJlbmFtZShzb3ZlcmVpZ250ID0gYENvdW50cnkgTmFtZWAsDQogICAgICAgICAgICAgICAgICAgICAgICBjbzJfcGMgPSBgMjAxMCBbWVIyMDEwXWANCiAgICAgICAgICAgICAgICAgICAgICAgIA0KKQ0KDQoNCg0KZGZvM19wYyRzb3ZlcmVpZ250IDwtIHJlY29kZShkZm8zX3BjJHNvdmVyZWlnbnQsIA0KICAgICAgICAgICAgICAgICAgICAgICJVbml0ZWQgU3RhdGVzIj0iVW5pdGVkIFN0YXRlcyBvZiBBbWVyaWNhIiwgDQogICAgICAgICAgICAgICAgICAgICAgIlJ1c3NpYW4gRmVkZXJhdGlvbiIgPSAiUnVzc2lhIiwNCiAgICAgICAgICAgICAgICAgICAgICAiVmVuZXp1ZWxhLCBSQiIgPSAiVmVuZXp1ZWxhIiwNCiAgICAgICAgICAgICAgICAgICAgICAgIkNvbmdvLCBEZW0uIFJlcC4iID0gIkRlbW9jcmF0aWMgUmVwdWJsaWMgb2YgdGhlIENvbmdvIiAsDQogICAgICAgICAgICAgICIJQ29uZ28sIFJlcC4iPSJSZXB1YmxpYyBvZiBDb25nbyIJICwNCiAgICAgICAgICAgICAgIkVneXB0LCBBcmFiIFJlcC4iID0gIkVneXB0IiAsDQogICAgICAgICAgICAgIlRhbnphbmlhIiA9ICJVbml0ZWQgUmVwdWJsaWMgb2YgVGFuemFuaWEiLA0KICAgICAgICAgICAgICJDb3RlIGQnSXZvaXJlIiA9ICJJdm9yeSBDb2FzdCIsDQogICAgICAgICAgICAgIlllbWVuLCBSZXAuIiA9ICJZZW1lbiIsDQogICAgICAgICAgICAgIklyYW4sIElzbGFtaWMgUmVwLiIgPSAiSXJhbiIsDQogICAgICAgICAgICAgIlN5cmlhbiBBcmFiIFJlcHVibGljIiA9ICJTeXJpYSIsDQogICAgICAgICAgICAgIlNsb3ZhayBSZXB1YmxpYyIgPSAiU2xvdmFraWEiLA0KICAgICAgICAgICAgICJTZXJiaWEiID0gIlJlcHVibGljIG9mIFNlcmJpYSIsDQogICAgICAgICAgICAgIk5vcnRoIE1hY2Vkb25pYSIgPSAiTWFjZWRvbmlhIiwNCiAgICAgICAgICAgICAiS3lyZ3l6IFJlcHVibGljIiA9ICJLeXJneXpzdGFuIiwNCiAgICAgICAgICAgICAiS29yZWEsIERlbS4gUGVvcGxl4oCZcyBSZXAiID0gIk5vcnRoIEtvcmVhIiwNCiAgICAgICAgICAgICAiS29yZWEsIFJlcC4iID0gIlNvdXRoIEtvcmVhIiwNCiAgICAgICAgICAgICAiTGFvIFBEUiIgPSAiTGFvcyINCikNCg0KDQpkZl9pbm5lcl9wYyA8LSBsZWZ0X2pvaW4od29ybGQsZGZvM19wYykNCmRmX2NvMl9wYyA8LSAgdHJhbnNmb3JtKGRmX2lubmVyX3BjLCBjbzJfcGMgPSBhcy5udW1lcmljKGNvMl9wYykgICANCikgJT4lIGZpbHRlcighKHNvdmVyZWlnbnQgPT0gIkFudGFyY3RpY2EiKSkNCg0KcCA8LSBnZ3Bsb3QoZGF0YSA9IGRmX2NvMl9wYykgKyBnZW9tX3NmKCkgKw0KICBsYWJzKHRpdGxlID0gIkdyw6FmaWNvIDE6IE1hcGEgZGVsIG11bmRvIiwNCiAgICAgICBjYXB0aW9uID0gIkRhdG9zIHByb3ZlbmllbnRlcyBkZSBybmF0dXJhbGVhcnRoIikNCnAgKyBnZW9tX3NmKGFlcyhmaWxsID0gY28yX3BjKSkgKyBzY2FsZV9maWxsX3ZpcmlkaXNfYyhvcHRpb24gPSAiQiIsIHRyYW5zID0gInNxcnQiKSANCmBgYA0KDQojIENhbGVudGFtaWVudG8gR2xvYmFsDQoNCkNvbiBlc3RlIGFuw6FsaXNpcyBwcmV0ZW5kZW1vcyBlc3R1ZGlhciBsYXMgY29uc2VjdWVuY2lhcyBkZSBsYSBlbWlzacOzbiBkZSBDTzIgZHVyYW50ZSB0b2RvcyBlc3RvcyBhw7FvcyBlbiBudWVzdHJhIHZpZGEsIG3DoXMgY29uY3JldGFtZW50ZSwgZW4gbG9zIGluY3JlbWVudG9zIGRlIHRlbXBlcmF0dXJhIHF1ZSBoZW1vcyBleHBlcmltZW50YWRvIHBvciBsYSBsaWJlcmFjacOzbiBkZSBlc3RvcyBnYXNlcyBhIGxhIGF0bcOzc2ZlcmEuDQoNCiMjIEV2b2x1Y2nDs24gZGUgbGEgdGVtcGVyYXR1cmEgbWVkaWEgZ2xvYmFsIHsudGFic2V0IC50YWJzZXQtcGlsbHN9DQoNCk9ic2VydmFtb3MgcXVlIHNlIGhhIHByb2R1Y2lkbyB1biBpbmNyZW1lbnRvIGRlIGxhIHRlbXBlcmF0dXJhIGRlc2RlIDE5MDAgaGFzdGEgbnVlc3Ryb3MgZGlhcyBkZWJpZG8gYSBsYSBlbWlzacOzbiBkZSBlc3RvcyBnYXNlcyBkZSBlZmVjdG8gaW52ZXJuYWRlcm8uIEVzdG9zIGdhc2VzIGRlIGVmZWN0byBpbnZlcm5hZGVybyAoZW50cmUgbG9zIHF1ZSBzZSBpbmNsdXllbiBlbCBDTzIsIG96b25vLCBldGMuKSByZWZsZWphbiBlbCBjYWxvciBwcm9kdWNpZG8gcG9yIGxhIHN1cGVyZmljaWUgdGVycmVzdHJlLCBwb3IgbG8gcXVlIHByb2R1Y2VuIHVuIGluY3JlbWVudG8gZGUgbGEgdGVtcGVyYXR1cmEgZ2xvYmFsLiANCg0KTGEgcHJvZHVjY2nDs24gZGUgQ08yIHF1ZSBoZW1vcyBhbmFsaXphZG8gZXMgdW5hIGRlIGxvcyBwcmluY2lwYWxlcyBjYXVzYXMgKHkgc2lndWUgdW4gY29tcG9ydGFtaWVudG8gc2ltaWxhcikgZGVsIGF1bWVudG8gZGUgdGVtcGVyYXR1cmEgcXVlIHZhbW9zIGEgdmVyIGVuIGxvcyBzaWd1aWVudGVzIGdyw6FmaWNvcy4NCg0KIyMjIEdyw6FmaWNvDQohW10oLi9pbWFnZW5lcy9nZl90ZW1wY28yLmdpZikNCg0KIyMjIEPDs2RpZ28NCg0KYGBge3IsIGV2YWw9IEZBTFNFfQ0KbGlicmFyeSh0aWR5dmVyc2UpDQpsaWJyYXJ5KGdnYW5pbWF0ZSkNCg0KbGlicmFyeShsdWJyaWRhdGUpDQpwY3QgPC0gZnVuY3Rpb24oeCkgeygoeC9sYWcoeCkNCiktMSkqMn0NCnBjdDIgPC0gZnVuY3Rpb24oeCkgeygoeC9sYWcoeCkNCiktMSkqMTAwfQ0KDQoNCnRlbXBfY291bnRyeSA8LXJlYWRfY3N2KCIuL0RhdG9zL0dsb2JhbExhbmRUZW1wZXJhdHVyZXNCeUNvdW50cnkuY3N2IikNCg0KdGVtcF8yMDAwIDwtIHN1YnNldCh0ZW1wX2NvdW50cnksZHQ+ICIxODk5LTEyLTAxIikNCg0KY2xpbWF0ZV9jaGFuZ2UgPC0gdGVtcF8yMDAwICU+JSANCiAgbXV0YXRlX2F0KHZhcnMoZHQpLCBmdW5zKHllYXIsIG1vbnRoLCBkYXkpKSAlPiUgZHJvcF9uYSgpICU+JSBmaWx0ZXIoQ291bnRyeSA9PSAiU3BhaW4iKQ0KDQpjbGltYXRlX2NoYW5nZSRtb250aFtjbGltYXRlX2NoYW5nZSRtb250aCA9PSAxXTwtICIwMS1FbmVybyINCmNsaW1hdGVfY2hhbmdlJG1vbnRoW2NsaW1hdGVfY2hhbmdlJG1vbnRoID09IDJdPC0gIjAyLUZlYnJlcm8iDQpjbGltYXRlX2NoYW5nZSRtb250aFtjbGltYXRlX2NoYW5nZSRtb250aCA9PSAzXTwtICIwMy1NYXJ6byINCmNsaW1hdGVfY2hhbmdlJG1vbnRoW2NsaW1hdGVfY2hhbmdlJG1vbnRoID09IDRdPC0gIjA0LUFicmlsIg0KY2xpbWF0ZV9jaGFuZ2UkbW9udGhbY2xpbWF0ZV9jaGFuZ2UkbW9udGggPT0gNV08LSAiMDUtTWF5byINCmNsaW1hdGVfY2hhbmdlJG1vbnRoW2NsaW1hdGVfY2hhbmdlJG1vbnRoID09IDZdPC0gIjA2LUp1bmlvIg0KY2xpbWF0ZV9jaGFuZ2UkbW9udGhbY2xpbWF0ZV9jaGFuZ2UkbW9udGggPT0gN108LSAiMDctSnVsaW8iDQpjbGltYXRlX2NoYW5nZSRtb250aFtjbGltYXRlX2NoYW5nZSRtb250aCA9PSA4XTwtICIwOC1BZ29zdG8iDQpjbGltYXRlX2NoYW5nZSRtb250aFtjbGltYXRlX2NoYW5nZSRtb250aCA9PSA5XTwtICIwOS1TZXB0aWVtYnJlIg0KY2xpbWF0ZV9jaGFuZ2UkbW9udGhbY2xpbWF0ZV9jaGFuZ2UkbW9udGggPT0gMTBdPC0gIjEwLU9jdHVicmUiDQpjbGltYXRlX2NoYW5nZSRtb250aFtjbGltYXRlX2NoYW5nZSRtb250aCA9PSAxMV08LSAiMTEtTm92aWVtYnJlIg0KY2xpbWF0ZV9jaGFuZ2UkbW9udGhbY2xpbWF0ZV9jaGFuZ2UkbW9udGggPT0gMTJdPC0gIjEyLURpY2llbWJyZSINCg0KdF9kZiA8LSB0ZW1wXzIwMDAgJT4lIGRyb3BfbmEoKSAlPiUNCm11dGF0ZShtb250aCA9IGZvcm1hdChkdCwgIiVtIiksIHllYXIgPSBmb3JtYXQoZHQsICIlWSIpKSAlPiUNCmdyb3VwX2J5KG1vbnRoLCB5ZWFyKSAlPiUNCnN1bW1hcmlzZShtZWFuID0gbWVhbihBdmVyYWdlVGVtcGVyYXR1cmUpKQ0KDQoNCg0KDQp0X2RmMiA8LSB0X2RmICU+JSBncm91cF9ieSh5ZWFyKSAlPiUgc3VtbWFyaXNlKHRtZWFuPSBtZWFuKG1lYW4pKQ0KIHRfZGYyIDwtICB0cmFuc2Zvcm0odF9kZjIsIHllYXIgPSBhcy5udW1lcmljKHllYXIpKQ0KDQogd19kZjIgPC0gd19kZiAlPiUgZmlsdGVyKHllYXIgPiAxODk5KQ0KIHdfZGYzIDwtIHdfZGYyICAlPiUgIG11dGF0ZV9lYWNoKGZ1bnMocGN0KSwgbikgJT4lIGRyb3BfbmEoKQ0KdF9kZjMgPC0gdF9kZjIgICU+JSBtdXRhdGVfZWFjaChmdW5zKHBjdDIpLCB0bWVhbikgJT4lIGRyb3BfbmEoKQ0Kd19kZjQgPC0gd19kZjMgJT4lIG11dGF0ZSh0Y28yID0gY3Vtc3VtKG4pKQ0KdF9kZjQgPC0gdF9kZjMgICU+JSBtdXRhdGUodGVtcCA9IGN1bXN1bSh0bWVhbikpDQoNCnkgPC1nZ3Bsb3QoKSArDQogIA0KICBnZW9tX2xpbmUoZGF0YSA9d19kZjQsYWVzKHllYXIsdGNvMixjb2xvcj0iQ08yIikpICsNCiAgI2dlb21fc21vb3RoKGRhdGEgPSB3X2RmNCxhZXMoeWVhcix0Y28yKSkgKw0KICN0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDkwLCB2anVzdCA9IDAuNSwgaGp1c3Q9MSkpICsNCiAgICNnZW9tX3Ntb290aChkYXRhID0gdF9kZjQsYWVzKHllYXIsdGVtcCksY29sb3VyPSAicHVycGxlIikgKw0KICAgIGdlb21fbGluZShkYXRhID0gdF9kZjQsYWVzKHllYXIsdGVtcCxncm91cD0xLGNvbG9yPSJUZW1wZXJhdHVyYSIpKSANCiAgDQogICAgICANCiAgDQogIA0KdGVtUGNvMmdmIDwtIHkgICsgdHJhbnNpdGlvbl9yZXZlYWwoeWVhcikgKw0KICBsYWJzKHRpdGxlID0gIkHDsW86IHthcy5pbnRlZ2VyKGZyYW1lX2Fsb25nKX0iLA0KICAgICAgIHggPSAiQcOxbyIsDQogICAgICAgeSA9ICJUZW1wZXJhdHVyYSB5IENPMiIsDQogICAgICAgY29sb3VyPSJWYXJpYWJsZXMiKSANCiAgDQogIA0KYW5pbV9zYXZlKCIuL2ltYWdlbmVzL2dmX3RlbXBjbzIuZ2lmIix0ZW1QY28yZ2YgICkNCg0KDQoNCmBgYA0KDQoNCg0KDQojIyBFdm9sdWNpw7NuIGRlIGxhIHRlbXBlcmF0dXJhIGVuIEVzcGHDsWEgIHsudGFic2V0IC50YWJzZXQtcGlsbHN9DQoNCiMjIyBHcsOhZmljbw0KDQohW10oLi9pbWFnZW5lcy9nZl9tb250aC5naWYpDQoNCg0KDQoNCiMjIyBDw7NkaWdvDQpgYGB7ciBtZXNzYWdlID0gRkFMU0UsIHdhcm5pbmcgPSBGQUxTRSwgcmVzdWx0cyA9IEZBTFNFfQ0KDQoNCnRlbXBfY291bnRyeSA8LXJlYWRfY3N2KCIuL0RhdG9zL0dsb2JhbExhbmRUZW1wZXJhdHVyZXNCeUNvdW50cnkuY3N2IikNCg0KdGVtcF8yMDAwIDwtIHN1YnNldCh0ZW1wX2NvdW50cnksZHQ+ICIxODk5LTEyLTAxIikNCg0KY2xpbWF0ZV9jaGFuZ2UgPC0gdGVtcF8yMDAwICU+JSBzZXBhcmF0ZSggImR0IiwgYygiYcOxbyIsICJtZXMiLCAiZGlhIiksIHNlcCA9ICItIikgJT4lIHRyYW5zZm9ybSggYcOxbyA9IGFzLm51bWVyaWMoYcOxbyksDQogICBtZXMgPSBhcy5udW1lcmljKG1lcyksDQogZGlhID0gYXMubnVtZXJpYyhkaWEpICAgICANCiApICU+JSBkcm9wX25hKCkgJT4lIGZpbHRlcihDb3VudHJ5ID09ICJTcGFpbiIpDQoNCmNsaW1hdGVfY2hhbmdlJG1lc1tjbGltYXRlX2NoYW5nZSRtZXMgPT0gMV08LSAiMDEtRW5lcm8iDQpjbGltYXRlX2NoYW5nZSRtZXNbY2xpbWF0ZV9jaGFuZ2UkbWVzID09IDJdPC0gIjAyLUZlYnJlcm8iDQpjbGltYXRlX2NoYW5nZSRtZXNbY2xpbWF0ZV9jaGFuZ2UkbWVzID09IDNdPC0gIjAzLU1hcnpvIg0KY2xpbWF0ZV9jaGFuZ2UkbWVzW2NsaW1hdGVfY2hhbmdlJG1lcyA9PSA0XTwtICIwNC1BYnJpbCINCmNsaW1hdGVfY2hhbmdlJG1lc1tjbGltYXRlX2NoYW5nZSRtZXMgPT0gNV08LSAiMDUtTWF5byINCmNsaW1hdGVfY2hhbmdlJG1lc1tjbGltYXRlX2NoYW5nZSRtZXMgPT0gNl08LSAiMDYtSnVuaW8iDQpjbGltYXRlX2NoYW5nZSRtZXNbY2xpbWF0ZV9jaGFuZ2UkbWVzID09IDddPC0gIjA3LUp1bGlvIg0KY2xpbWF0ZV9jaGFuZ2UkbWVzW2NsaW1hdGVfY2hhbmdlJG1lcyA9PSA4XTwtICIwOC1BZ29zdG8iDQpjbGltYXRlX2NoYW5nZSRtZXNbY2xpbWF0ZV9jaGFuZ2UkbWVzID09IDldPC0gIjA5LVNlcHRpZW1icmUiDQpjbGltYXRlX2NoYW5nZSRtZXNbY2xpbWF0ZV9jaGFuZ2UkbWVzID09IDEwXTwtICIxMC1PY3R1YnJlIg0KY2xpbWF0ZV9jaGFuZ2UkbWVzW2NsaW1hdGVfY2hhbmdlJG1lcyA9PSAxMV08LSAiMTEtTm92aWVtYnJlIg0KY2xpbWF0ZV9jaGFuZ2UkbWVzW2NsaW1hdGVfY2hhbmdlJG1lcyA9PSAxMl08LSAiMTItRGljaWVtYnJlIg0KDQoNCg0KZ2ZfdGVtcF9tb250aCA8LSBnZ3Bsb3QoY2xpbWF0ZV9jaGFuZ2UsIGFlcyhhw7FvLCBBdmVyYWdlVGVtcGVyYXR1cmUsIHNpemUgPSBBdmVyYWdlVGVtcGVyYXR1cmVVbmNlcnRhaW50eSAsIGNvbG9yID0gbWVzICkpICsgZ2VvbV9wb2ludChhbHBoYSA9IDAuNCwgc2hvdy5sZWdlbmQgPSBGQUxTRSkgKw0KICBmYWNldF93cmFwKH5tZXMpICsNCiAgDQogIGxhYnModGl0bGUgPSAnQcOxbzoge2FzLmludGVnZXIoZnJhbWVfdGltZSl9JywgeCA9ICdBw7FvJywgeSA9ICdUZW1wZXJhdHVyYSBNZWRpYScpICsNCiAgdHJhbnNpdGlvbl90aW1lKGHDsW8pICsNCiAgZWFzZV9hZXMoJ2xpbmVhcicpDQphbmltX3NhdmUoIi4vaW1hZ2VuZXMvZ2ZfbW9udGguZ2lmIiwgZ2ZfdGVtcF9tb250aCkNCg0KDQpgYGANCg0KDQojIyBFdm9sdWNpw7NuIGRlIGxhcyBlbmVyZ8OtYXMgcmVub3ZhYmxlcyAxOTkwLTIwMTUgey50YWJzZXQgLnRhYnNldC1waWxsc30NCg0KQW5hbGl6YW1vcyBhaG9yYSBsYSBldm9sdWNpw7NuIHF1ZSBoYW4gc2VndWlkbyBsYXMgZW5lcmdpYXMgcmVub3ZhYmxlcy4gRXN0YXMgdGVjbm9sb2fDrWFzIHByZXRlbmRlbiBzZXIgbWFzIGFtaWdhYmxlcyBjb24gZWwgbWVkaW8gYW1iaWVudGUsIGRpc21pbnV5ZW5kbyBsYSBjb250YW1pbmFjacOzbiBhIGxhIHZleiBxdWUgcHJvZHVjZW4gZW5lcmdpYS4NCg0KRW4gbGFzIHByaW5jaXBhbGVzIGVjb25vbcOtYXMgbXVuZGlhbGVzIChFc3RhZG9zIFVuaWRvcywgRXVyb3BhIHkgcGFydGUgZGUgQXNpYSkgbm8gc2UgaGFuIHByb2R1Y2lkbyBuaW5nw7puIGF2YW5jZSBvIG11eSBwb2NvIGVuIGVzdGUgc2VudGlkbywgeSBxdWUgc29uIGxvcyBwYcOtc2VzIG1hcyBzdWJkZXNhcnJvbGxhZG9zIChBbcOpcmljYSBkZWwgU3VyIHkgbGEgcGFydGUgY2VudHJhbCBkZSDDgWZyaWNhKSBsb3MgcXVlIG3DoXMgcHJvcG9yY2nDs24gZGUgZW5lcmdpYSByZW5vdmFibGUgdXNhbiwgc2luIGVtYmFyZ28sIGNvbmZvcm1lIHNlIGhhbiBpZG8gZGVzYXJyb2xsYW5kbyBoYW4gaWRvIHV0aWxpemFuZG8gbWVub3MgbGFzIGVuZXJnaWFzIHJlbm92YWJsZXMuIEVzdGUgZXMgZWwgY2FzbyBkZSBCcmFzaWwsIHF1acOpbiBhZGVtw6FzIGhhIGRlZm9yZXN0YWRvIHBhcnRlIGRlIHN1IHN1cGVyZmljaWUuDQpTaSBub3MgY2VudHJhbW9zIGVuIEV1cm9wYSBwb2RlbW9zIHZlciBxdWUgaGEgaGFiaWRvIGNpZXJ0byBhdmFuY2UgZW4gbG9zIHVsdGltb3MgMTUgYcOxb3MgLCBhdW5xdWUgYcO6biBoYXkgbXVjaG8gcG9yIGhhY2VyLg0KDQojIyMgTWFwYQ0KPGRpdiBjbGFzcyA9ICJjZW50ZXJlZCI+DQohW10oLi9pbWFnZW5lcy9tYXA2LmdpZikNCjwvZGl2Pg0KPGRpdiBjbGFzcyA9ICJjZW50ZXJlZCI+DQojIyMgRXVyb3BhDQohW10oLi9pbWFnZW5lcy9tYXBwLmdpZikNCjwvZGl2Pg0KDQohW10oLi9pbWFnZW5lcy9ycGxvdDMuanBlZykNCg0KIyMjIEPDs2RpZ28gIA0KYGBgIHtyLCBldmFsPSBGQUxTRX0NCmxpYnJhcnkodGlkeXZlcnNlKQ0KbGlicmFyeShyaW8pDQpsaWJyYXJ5KHBsb3RseSkNCmxpYnJhcnkoamFuaXRvcikNCmxpYnJhcnkoZ2dhbmltYXRlKQ0KbGlicmFyeSh2aXJpZGlzKQ0KbGlicmFyeSgic2YiKQ0KDQp1cmwgPC0oImh0dHBzOi8vcmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbS9yb2RyaTQ1bC9wbGFzdGljd2FzdGUvbWFpbi90cmFiYWpvX0JpZ0RhdGFfZXF1aXBvL2RhdG9zL3JlbnB3ci5jc3YiKQ0KDQpkZiA8LSBpbXBvcnQodXJsKQ0KDQpkZl9wd3IgPC0gZGYgJT4lIHNlbGVjdCgtYyhgU2VyaWVzIE5hbWVgLGBTZXJpZXMgQ29kZWApKSAlPiUgcmVuYW1lKHNvdmVyZWlnbnQgPSBgQ291bnRyeSBOYW1lYCkNCg0KDQpuYW1lcyhkZl9wd3IpIDwtIHN0cmluZ3I6OnN0cl9yZW1vdmUoc3RyaW5nID0gbmFtZXMoZGZfcHdyKSwgcGF0dGVybiA9ICJcXHMuKiIpIA0KDQoNCg0KZGZfcHdyJHNvdmVyZWlnbnQgPC0gcmVjb2RlKGRmX3B3ciRzb3ZlcmVpZ250LCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAiVW5pdGVkIFN0YXRlcyI9IlVuaXRlZCBTdGF0ZXMgb2YgQW1lcmljYSIsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICJSdXNzaWFuIEZlZGVyYXRpb24iID0gIlJ1c3NpYSIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgIlZlbmV6dWVsYSwgUkIiID0gIlZlbmV6dWVsYSIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgIkNvbmdvLCBEZW0uIFJlcC4iID0gIkRlbW9jcmF0aWMgUmVwdWJsaWMgb2YgdGhlIENvbmdvIiAsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgIglDb25nbywgUmVwLiI9IlJlcHVibGljIG9mIENvbmdvIgkgLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICJFZ3lwdCwgQXJhYiBSZXAuIiA9ICJFZ3lwdCIgLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICJUYW56YW5pYSIgPSAiVW5pdGVkIFJlcHVibGljIG9mIFRhbnphbmlhIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAiQ290ZSBkJ0l2b2lyZSIgPSAiSXZvcnkgQ29hc3QiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICJZZW1lbiwgUmVwLiIgPSAiWWVtZW4iLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICJJcmFuLCBJc2xhbWljIFJlcC4iID0gIklyYW4iLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICJTeXJpYW4gQXJhYiBSZXB1YmxpYyIgPSAiU3lyaWEiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICJTbG92YWsgUmVwdWJsaWMiID0gIlNsb3Zha2lhIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAiU2VyYmlhIiA9ICJSZXB1YmxpYyBvZiBTZXJiaWEiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICJOb3J0aCBNYWNlZG9uaWEiID0gIk1hY2Vkb25pYSIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgIkt5cmd5eiBSZXB1YmxpYyIgPSAiS3lyZ3l6c3RhbiIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgIktvcmVhLCBEZW0uIFBlb3BsZeKAmXMgUmVwIiA9ICJOb3J0aCBLb3JlYSIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgIktvcmVhLCBSZXAuIiA9ICJTb3V0aCBLb3JlYSIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgIkxhbyBQRFIiID0gIkxhb3MiKQ0KDQoNCmRmX3B3cjIgPC0gZGZfcHdyICU+JSBwaXZvdF9sb25nZXIoY29scyA9IDM6MjgsIG5hbWVzX3RvID0gInllYXIiKSAlPiUgDQogICAgICAgICAgIG11dGF0ZSh5ZWFyID0gYXMubnVtZXJpYyh5ZWFyKSkgJT4lIA0KICAgICAgICAgICBtdXRhdGUodmFsdWUgPSBhcy5udW1lcmljKHZhbHVlKSkgJT4lIA0KICAgICAgICAgIGZpbHRlcih5ZWFyID09IDIwMTUpDQoNCg0KDQp3b3JsZCA8LSBybmF0dXJhbGVhcnRoOjpuZV9jb3VudHJpZXMoc2NhbGUgPSAibWVkaXVtIiwgcmV0dXJuY2xhc3MgPSAic2YiKQ0Kd29ybGRfcG9pbnRzPC0gc3RfY2VudHJvaWQod29ybGQpDQp3b3JsZF9wb2ludHMgPC0gY2JpbmQod29ybGQsIHN0X2Nvb3JkaW5hdGVzKHN0X2NlbnRyb2lkKHdvcmxkJGdlb21ldHJ5KSkpDQoNCg0KZGZfaW5uZXJfcHdyIDwtIGlubmVyX2pvaW4od29ybGQsIGRmX3B3cjIsIGJ5PSBjKCJzb3ZlcmVpZ250IiA9ICJzb3ZlcmVpZ250IikpDQoNCg0KIA0KZGZfcHdyNCA8LSBkZl9wd3IgJT4lIHBpdm90X2xvbmdlcihjb2xzID0gMzoyOCwgbmFtZXNfdG8gPSAieWVhciIpIA0KZGZfcHdyNSA8LWRmX3B3cjQgJT4lICAgbXV0YXRlKHllYXIgPSBhcy5udW1lcmljKHllYXIpKSAlPiUgDQogIG11dGF0ZSh2YWx1ZSA9IGFzLm51bWVyaWModmFsdWUpKQ0KDQpkZl9wd3I1IDwtIGlubmVyX2pvaW4od29ybGQsIGRmX3B3cjUsIGJ5PSBjKCJzb3ZlcmVpZ250IiA9ICJzb3ZlcmVpZ250IikpDQojZGZfcHdyNiANCm5hbWVzKGRmX3B3cjQpDQoNCmRmX3B3cjkgPC0gZGZfcHdyNSAlPiUgc2VsZWN0KHNvdmVyZWlnbnQsIHllYXIsIHZhbHVlKQ0KcCA8LSBnZ3Bsb3QoKSArIGdlb21fc2YoZGF0YSA9IGRmX3B3cjksIGFlcyhmaWxsID0gdmFsdWUpKSArIA0KICBsYWJzKHRpdGxlID0gIk1hcGEgZGVsIG11bmRvIGVuZXJnaWFzIHJlbm92YWJsZXMgMTk5MCAtIDIwMTUiLA0KICAgICAgIGNhcHRpb24gPSAiRGF0b3MgcHJvdmVuaWVudGVzIGRlIFdvcmxkIEJhbmsiKSArDQogIHNjYWxlX2ZpbGxfdmlyaWRpcyhkaXJlY3Rpb24gPSAxLCBsYWJlbCA9IHNjYWxlczo6bnVtYmVyLGJlZ2luID0gMCwgZW5kID0gMC45KSArDQogIHRyYW5zaXRpb25fdGltZSh5ZWFyKSArIGxhYnModGl0bGUgPSAiUG9yY2VudGFqZSBkZSBlbmVyZ2lhIHJlbm92YWJsZSBwb3IgcGHDrXMiLCBzdWJ0aXRsZSA9ICJBw7FvOnthcy5pbnRlZ2VyKGZyYW1lX3RpbWUpfSIgICkgDQoNCmFuaW0gPC0gYW5pbWF0ZShwKQ0KDQphbmltX3NhdmUoIi4vaW1hZ2VuZXMvbWFwNi5naWYiLCBhbmltKQ0KDQoNCiMtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQ0KZGZfcHdyMTAgPC0gZGZfcHdyNSAlPiUgZmlsdGVyKGNvbnRpbmVudCA9PSAiRXVyb3BlIikgDQoNCg0KaSA8LSBnZ3Bsb3QoKSArIGdlb21fc2YoZGF0YSA9IGRmX3B3cjEwLCBhZXMoZmlsbCA9IHZhbHVlKSkgKyANCiAgbGFicyh0aXRsZSA9ICJNYXBhIEV1cm9wYSBlbmVyZ2lhcyByZW5vdmFibGVzIDE5OTAgLSAyMDE1IiwNCiAgICAgICBjYXB0aW9uID0gIkRhdG9zIHByb3ZlbmllbnRlcyBkZSBXb3JsZCBCYW5rIikgKw0KICBjb29yZF9zZih4bGltID0gYygtMzUsIDUwKSwgeWxpbSA9IGMoMzAsIDgwKSkrDQogIHNjYWxlX2ZpbGxfdmlyaWRpcyhkaXJlY3Rpb24gPSAxLCBsYWJlbCA9IHNjYWxlczo6bnVtYmVyLGJlZ2luID0gMCwgZW5kID0gMC45KSArDQogIHRyYW5zaXRpb25fdGltZSh5ZWFyKSArIGxhYnModGl0bGUgPSAiUG9yY2VudGFqZSBkZSBlbmVyZ2lhIHJlbm92YWJsZSBwb3IgcGHDrXMiLCBzdWJ0aXRsZSA9ICJBw7FvOnthcy5pbnRlZ2VyKGZyYW1lX3RpbWUpfSIgICkgDQoNCmFuaW0xIDwtIGFuaW1hdGUoaSkNCg0KYW5pbV9zYXZlKCIuL2ltYWdlbmVzL21hcHAuZ2lmIiwgYW5pbTEpDQoNCiMtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQ0KDQpkZl9wd3IxMSA8LSBkZl9wd3IxMCAlPiUgZmlsdGVyKHllYXIgPT0gMjAxNSkgJT4lIHNlbGVjdChzb3ZlcmVpZ250LCB5ZWFyLCB2YWx1ZSkNCg0KDQoNCg0KDQoNCmxpYnJhcnkodHJlZW1hcGlmeSkNCg0KZ2dwbG90KGRmX3B3cjExLCBhZXMoYXJlYSA9IHZhbHVlLCBmaWxsID0gdmFsdWUsIGxhYmVsID0gc292ZXJlaWdudCApKSArDQogIGdlb21fdHJlZW1hcCgpICsNCiAgZ2VvbV90cmVlbWFwX3RleHQoY29sb3VyID0gIndoaXRlIiwgcGxhY2UgPSAiY2VudHJlIiwNCiAgICAgICAgICAgICAgICAgICAgZ3JvdyA9IEZBTFNFKSArDQogIHNjYWxlX2ZpbGxfdmlyaWRpc19jKG9wdGlvbiA9ICJEIiAsIG5hbWUgPSAiIiwgYWxwaGEgPSAwLjgsIGJlZ2luID0gMC4zLCBlbmQgPSAwLjcsIGRpcmVjdGlvbiA9IDEsDQogICAgICAgICAgICAgICAgICAgICAgIGd1aWRlID0gZ3VpZGVfY29sb3JiYXIoIHRpdGxlID0gIiUgRW5lcmdpYSByZW5vdmFibGUiLCBkaXJlY3Rpb24gPSAiaG9yaXpvbnRhbCIsIGJhcmhlaWdodCA9IHVuaXQoMiwgdW5pdHMgPSAibW0iKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYmFyd2lkdGggPSB1bml0KDUwLCB1bml0cyA9ICJtbSIpLCBkcmF3LnVsaW0gPSBGLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aXRsZS5wb3NpdGlvbiA9ICd0b3AnLCB0aXRsZS5oanVzdCA9IDAuNSwgbGFiZWwuaGp1c3QgPSAwLjUpKSArDQogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJib3R0b20iKSArIHNjYWxlX3hfY29udGludW91cyhsYWJlbHM9ZnVuY3Rpb24odmFsdWUpe2Zvcm1hdCh2YWx1ZSwgc2NpZW50aWZpYyA9IEZBTFNFKX0pICsNCiAgbGFicyh0aXRsZSA9ICJQb3JjZW50YWplIGRlIGVuZXJnw61hcyByZW5vdmFibGVzIHBvciBwYcOtc2VzIikgKyB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41KSkgKw0KICB0aGVtZShwbG90LnN1YnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41KSkNCg0KDQoNCg0KDQoNCmBgYA0KDQoNCg0KIyBgc2Vzc2lvbiBpbmZvYA0KDQoNCmBgYHtyfQ0Kc2Vzc2lvbmluZm86OnNlc3Npb25faW5mbygpICU+JSBkZXRhaWxzOjpkZXRhaWxzKHN1bW1hcnkgPSAnY3VycmVudCBzZXNzaW9uIGluZm8nKSANCmBgYA0KDQoNCg0KDQoNCg0KDQoNCg0KDQoNCg0KDQoNCg0KDQoNCg0KDQoNCg0KDQoNCg0KDQoNCg0KDQoNCg0KDQoNCg0KDQoNCg==