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 2021-2022. El repo del trabajo está aquí.

La página web de la asignatura y los trabajos de mis compañeros pueden verse aquí.


1. Introducción

Los videojuegos son un elemento con creciente importancia en la vida de las personas. Por tanto, es interesante conocer el funcionamiento de su mercado, por ejemplo, cuales son los videojuegos que más han triunfado, a que consola pertenecen, etc. Este trabajo pretende dar respuesta a estos aspectos, a través de distintas gráficas y tablas elaboradas con r.

2. Datos

A partir de la página web de kaggle, he obtenido y manipulado los datos del trabajo del siguiente dataset

2.1. Procesando los datos

El dataset se compone de tres data frames, los cuales estan formados por distintos videojuegos, la fecha de lanzamiento de los cuales se encuentra entre 1980 y 2020. El primero de ellos esta integrado por todos los videojuegos, mientras que los otros dos dataframes se centran en los videojuegos de sus respectivas plataformas. Cabe destacar que durante el análisis, a partir de 2017 existen una gran cantidad de NA, por lo que la gran mayoría de los apartados abarcan hasta 2016. Por otro lado, el Data set tiene una visión curiosa del mundo, ya que lo divide en dos continentes, un país y el resto, por lo que hace que las comparaciones territoriales no sean muy reveladoras.

#en primer lugar importamos los datos

juegos_ps4 <- rio::import(file = "./datos/PS4_GamesSales.csv")
juegos <- rio::import(file = "./datos/Video_Games_Sales_as_at_22_Dec_2016.csv")
juegos_XboxOne <- rio::import(file = "./datos/XboxOne_GameSales.csv")


#analizamos de que tipo son las variables de los df
str(juegos_ps4)
#> 'data.frame':    1034 obs. of  9 variables:
#>  $ Game         : chr  "Grand Theft Auto V" "Call of Duty: Black Ops 3" "Red Dead Redemption 2" "Call of Duty: WWII" ...
#>  $ Year         : chr  "2014" "2015" "2018" "2017" ...
#>  $ Genre        : chr  "Action" "Shooter" "Action-Adventure" "Shooter" ...
#>  $ Publisher    : chr  "Rockstar Games" "Activision" "Rockstar Games" "Activision" ...
#>  $ North America: num  6.06 6.18 5.26 4.67 1.27 1.26 4.49 3.64 3.11 2.91 ...
#>  $ Europe       : num  9.71 6.05 6.21 6.21 8.64 7.95 3.93 3.39 3.83 3.97 ...
#>  $ Japan        : num  0.6 0.41 0.21 0.4 0.15 0.12 0.21 0.32 0.19 0.27 ...
#>  $ Rest of World: num  3.02 2.44 2.26 2.12 1.73 1.61 1.7 1.41 1.36 1.34 ...
#>  $ Global       : num  19.4 15.1 13.9 13.4 11.8 ...
str(juegos)
#> 'data.frame':    16719 obs. of  16 variables:
#>  $ Name           : chr  "Wii Sports" "Super Mario Bros." "Mario Kart Wii" "Wii Sports Resort" ...
#>  $ Platform       : chr  "Wii" "NES" "Wii" "Wii" ...
#>  $ Year_of_Release: chr  "2006" "1985" "2008" "2009" ...
#>  $ Genre          : chr  "Sports" "Platform" "Racing" "Sports" ...
#>  $ Publisher      : chr  "Nintendo" "Nintendo" "Nintendo" "Nintendo" ...
#>  $ NA_Sales       : num  41.4 29.1 15.7 15.6 11.3 ...
#>  $ EU_Sales       : num  28.96 3.58 12.76 10.93 8.89 ...
#>  $ JP_Sales       : num  3.77 6.81 3.79 3.28 10.22 ...
#>  $ Other_Sales    : num  8.45 0.77 3.29 2.95 1 0.58 2.88 2.84 2.24 0.47 ...
#>  $ Global_Sales   : num  82.5 40.2 35.5 32.8 31.4 ...
#>  $ Critic_Score   : int  76 NA 82 80 NA NA 89 58 87 NA ...
#>  $ Critic_Count   : int  51 NA 73 73 NA NA 65 41 80 NA ...
#>  $ User_Score     : num  8 NA 8.3 8 NA NA 8.5 6.6 8.4 NA ...
#>  $ User_Count     : int  322 NA 709 192 NA NA 431 129 594 NA ...
#>  $ Developer      : chr  "Nintendo" "" "Nintendo" "Nintendo" ...
#>  $ Rating         : chr  "E" "" "E" "E" ...
str(juegos_XboxOne)
#> 'data.frame':    613 obs. of  10 variables:
#>  $ Pos          : int  1 2 3 4 5 6 7 8 9 10 ...
#>  $ Game         : chr  "Grand Theft Auto V" "Call of Duty: Black Ops 3" "Call of Duty: WWII" "Red Dead Redemption 2" ...
#>  $ Year         : chr  "2014" "2015" "2017" "2018" ...
#>  $ Genre        : chr  "Action" "Shooter" "Shooter" "Action-Adventure" ...
#>  $ Publisher    : chr  "Rockstar Games" "Activision" "Activision" "Rockstar Games" ...
#>  $ North America: num  4.7 4.63 3.75 3.76 3.23 3.25 3.37 2.94 2.94 2.91 ...
#>  $ Europe       : num  3.25 2.04 1.91 1.47 1.71 1.49 1.26 1.62 1.49 1.44 ...
#>  $ Japan        : num  0.01 0.02 0 0 0 0.01 0.02 0.02 0.03 0 ...
#>  $ Rest of World: num  0.76 0.68 0.57 0.54 0.49 0.48 0.48 0.45 0.45 0.44 ...
#>  $ Global       : num  8.72 7.37 6.23 5.77 5.43 5.22 5.13 5.03 4.92 4.79 ...



#ventas por regiones y total en cada año
 ventas_por_regiones <- juegos %>%
  group_by(Year_of_Release) %>% 
  mutate(Total_ventas = sum(Global_Sales)) %>%
  mutate(NA_ventas = sum(NA_Sales)) %>% 
  mutate(EU_ventas = sum(EU_Sales)) %>% 
  mutate(JP_ventas = sum(JP_Sales)) %>%
  mutate(Otros_ventas = sum(Other_Sales)) %>%
  select(Year_of_Release, Total_ventas, NA_ventas, EU_ventas, JP_ventas, Otros_ventas) %>% 
  distinct(Year_of_Release, Total_ventas, NA_ventas, EU_ventas, JP_ventas, Otros_ventas) %>% 
  arrange(Year_of_Release) %>% 
  filter(.,Year_of_Release >=1980, Year_of_Release<=2016)
 
 # a partir de 2017 los datos son poco ilustrativos, además de aparecer una gran cantidad de NA, por lo que los excluims de este apartado.
 
 
 # videojuegos con mayores ventas en cada continente  
 mas_exitosos_global <- juegos %>% slice_max(Global_Sales, n=5)
 
 mas_exitosos_EU <- juegos %>% slice_max(EU_Sales, n=5)

 mas_exitosos_JP <- juegos %>% slice_max(JP_Sales, n=5)

 mas_exitosos_NA <- juegos %>% slice_max(NA_Sales, n=5)
 
 mas_exitosos_Otros <- juegos %>% slice_max(Other_Sales, n=5)
 
 #creamos los mismos df pero solo el top 3 de cada region 
 
  mas_exitosos_global_v2 <- juegos %>% slice_max(Global_Sales, n=3)
 
 mas_exitosos_EU_v2 <- juegos %>% slice_max(EU_Sales, n=3)

 mas_exitosos_JP_v2 <- juegos %>% slice_max(JP_Sales, n=3)

 mas_exitosos_NA_v2 <- juegos %>% slice_max(NA_Sales, n=3)
 
 mas_exitosos_Otros_v2 <- juegos %>% slice_max(Other_Sales, n=3)
 
 # creamos un df con los top 3 videojuegos de cada rgión, para analizar distintos aspectos
 
 mas_exitosos_all <- full_join(mas_exitosos_global_v2, mas_exitosos_EU_v2) %>% 
   select(Name, Platform, Year_of_Release, Genre, Publisher, NA_Sales, EU_Sales, JP_Sales, Other_Sales, Global_Sales) %>% 
   full_join(., mas_exitosos_JP_v2) %>% 
   full_join(., mas_exitosos_NA_v2) %>% 
   full_join(., mas_exitosos_Otros_v2) %>% 
   distinct(Name, Platform, Year_of_Release, Genre, Publisher, NA_Sales, EU_Sales, JP_Sales, Other_Sales, Global_Sales)
 
 #desarrolladoras
 mas_exitosas_desarrolladoras <- mas_exitosos_all %>%  group_by(Publisher) %>% 
   mutate(n_desarrolladoras = sum(NN = n())) %>% 
   select(Publisher, n_desarrolladoras) %>% 
   distinct(Publisher, n_desarrolladoras)
 
 #Género
  mas_exitosos_generos <- mas_exitosos_all %>%  group_by(Genre) %>% 
   mutate(n_generos = sum(NN = n())) %>% 
   select(Genre, n_generos) %>% 
   distinct(Genre, n_generos)
 
 
 #Plataforma
 mas_exitosos_plataforma <- mas_exitosos_all %>%  group_by(Platform) %>% 
   mutate(n_plataformas = sum(NN = n())) %>% 
   select(Platform, n_plataformas) %>% 
   distinct (Platform, n_plataformas)
 
 
 #A continuación pasaré a comparar las ventas de las dos penúltimas generaciones de consolas, es decir, la Ps4 y la XboxOne. Necesito la variable de platform para el analisis posterior, por lo que introduciré manualmente en los dos df la variable. No los fusiono con el el df juegos ya que tiene el problema de los NA a partir de 2017.
juegos_ps4[, c(2)] <- sapply(juegos_ps4[, c(2)], as.numeric)

 
 juegos_ps4_ventas <- juegos_ps4 %>% mutate(Platform = "PS4") %>% 
   group_by(Year) %>% 
   mutate(Ventas_totales = sum(Global)) %>% 
   distinct(Year, Ventas_totales, Platform) %>% 
   filter (Year >= 2013, Year <= 2018)
 
 
juegos_XboxOne[, c(3)] <- sapply(juegos_XboxOne[, c(3)], as.numeric)
 
 juegos_XboxOne_ventas <- juegos_XboxOne %>% mutate(Platform = "XboxOne") %>% 
   group_by(Year) %>% 
   mutate(Ventas_totales = sum(Global)) %>% 
   distinct(Year, Ventas_totales, Platform) %>% 
   filter (Year >= 2013, Year <= 2018)

 
 # A continuación junto los dos df para poder hacer las comparaciones
juegos_XboxOne_ps4 <- full_join(juegos_ps4_ventas, juegos_XboxOne_ventas)

#Por último de este apartado realizamos una comparación entre las ventas totales de cada plataforma
ventas_totales_plataforma <- juegos_XboxOne_ps4 %>% 
  group_by(Platform) %>% 
  mutate(Ventas = sum(Ventas_totales)) %>% 
  distinct(Ventas, Platform) %>% 
  ungroup(Platform) %>% 
  mutate(final_ventas = sum(Ventas)) %>% 
  mutate(ventas_ventas_totales = Ventas / final_ventas) %>% 
  mutate(porcentaje = scales::percent(ventas_ventas_totales))

#Tabla del juego más vendido de cada año, de 1980 a 2016.

juego_del_año <- juegos %>% 
  group_by(Year_of_Release) %>% 
  slice_max(n = 1, Global_Sales) %>% 
  ungroup(Year_of_Release) %>% 
  filter(Year_of_Release >= 1980, Year_of_Release <= 2016) %>% 
  select(Year_of_Release, Name, Platform, Genre, Publisher, Global_Sales) %>% 
  rename(Videojuego = Name, Plataforma = Platform, Año = Year_of_Release, Genero = Genre, Desarrolladora = Publisher, Ventas = Global_Sales)
  

#ventas de cada género

 juegos <- na.omit(juegos) #Elimino las filas que contengan na
 
 ventas_categoria <- juegos %>% 
  group_by(Genre) %>% 
   mutate(Ventas_género = sum(Global_Sales)) %>% 
   mutate(Número_de_videojuegos = sum(NN = n())) %>%  
   mutate(Ventas_por_videojuego = Ventas_género / Número_de_videojuegos) %>% 
  distinct(Ventas_género, Número_de_videojuegos, Ventas_por_videojuego ) %>% 
 ungroup() %>% 
   arrange(desc(Ventas_por_videojuego)) %>% 
   rename(Género = Genre)
 
 
 #a continuación, de cada plataforma
 
 ventas_platform <- juegos %>% 
  group_by(Platform) %>% 
   mutate(Ventas_plataforma = sum(Global_Sales)) %>% 
   mutate(Número_de_videojuegos = sum(NN = n())) %>%  
   mutate(Ventas_por_videojuego = Ventas_plataforma / Número_de_videojuegos) %>% 
  distinct(Ventas_plataforma, Número_de_videojuegos, Ventas_por_videojuego ) %>% 
 ungroup() %>% 
   arrange(desc(Ventas_por_videojuego)) %>% 
   rename(Plataforma = Platform)
 
 

3. El mercado de los videojuegos

3.1 Análisis general

A partir del gráfico mostrado a continuación, puede verse la evolución del mercado de los videojuegos. Los videojuegos comienzan a tener cifras considerativas de ventas a partir de 1994, teniendo una increible escalada desde el 2000 hasta el 2008. A partir de entonces las cifras han ido cayendo, propiciado en parte por la cada vez mayor existencia y consolidación de videojuegos de adquisición gratuita, pero que incluyen micropagos dentro del propio videojuego.

En relación con las regiones, Norte América siempre ha sido pionera en la venta de videojuegos, seguida por Europa. En los últimos años las diferencias entre ambas regiones se han ido aproximando.

 #Para poder utilizar geom_line, es necesario que la variable años sea numérica
 str(ventas_por_regiones)
#> grouped_df [37 × 6] (S3: grouped_df/tbl_df/tbl/data.frame)
#>  $ Year_of_Release: chr [1:37] "1980" "1981" "1982" "1983" ...
#>  $ Total_ventas   : num [1:37] 11.4 35.8 28.9 16.8 50.4 ...
#>  $ NA_ventas      : num [1:37] 10.59 33.4 26.92 7.76 33.28 ...
#>  $ EU_ventas      : num [1:37] 0.67 1.96 1.65 0.8 2.1 4.74 2.84 1.41 6.59 8.44 ...
#>  $ JP_ventas      : num [1:37] 0 0 0 8.1 14.3 ...
#>  $ Otros_ventas   : num [1:37] 0.12 0.32 0.31 0.14 0.7 0.92 1.93 0.2 0.99 1.5 ...
#>  - attr(*, "groups")= tibble [37 × 2] (S3: tbl_df/tbl/data.frame)
#>   ..$ Year_of_Release: chr [1:37] "1980" "1981" "1982" "1983" ...
#>   ..$ .rows          : list<int> [1:37] 
#>   .. ..$ : int 1
#>   .. ..$ : int 2
#>   .. ..$ : int 3
#>   .. ..$ : int 4
#>   .. ..$ : int 5
#>   .. ..$ : int 6
#>   .. ..$ : int 7
#>   .. ..$ : int 8
#>   .. ..$ : int 9
#>   .. ..$ : int 10
#>   .. ..$ : int 11
#>   .. ..$ : int 12
#>   .. ..$ : int 13
#>   .. ..$ : int 14
#>   .. ..$ : int 15
#>   .. ..$ : int 16
#>   .. ..$ : int 17
#>   .. ..$ : int 18
#>   .. ..$ : int 19
#>   .. ..$ : int 20
#>   .. ..$ : int 21
#>   .. ..$ : int 22
#>   .. ..$ : int 23
#>   .. ..$ : int 24
#>   .. ..$ : int 25
#>   .. ..$ : int 26
#>   .. ..$ : int 27
#>   .. ..$ : int 28
#>   .. ..$ : int 29
#>   .. ..$ : int 30
#>   .. ..$ : int 31
#>   .. ..$ : int 32
#>   .. ..$ : int 33
#>   .. ..$ : int 34
#>   .. ..$ : int 35
#>   .. ..$ : int 36
#>   .. ..$ : int 37
#>   .. ..@ ptype: int(0) 
#>   ..- attr(*, ".drop")= logi TRUE
ventas_por_regiones[, c(1)] <- sapply(ventas_por_regiones[, c(1)], as.numeric)
 str(ventas_por_regiones)
#> grouped_df [37 × 6] (S3: grouped_df/tbl_df/tbl/data.frame)
#>  $ Year_of_Release: num [1:37] 1980 1981 1982 1983 1984 ...
#>  $ Total_ventas   : num [1:37] 11.4 35.8 28.9 16.8 50.4 ...
#>  $ NA_ventas      : num [1:37] 10.59 33.4 26.92 7.76 33.28 ...
#>  $ EU_ventas      : num [1:37] 0.67 1.96 1.65 0.8 2.1 4.74 2.84 1.41 6.59 8.44 ...
#>  $ JP_ventas      : num [1:37] 0 0 0 8.1 14.3 ...
#>  $ Otros_ventas   : num [1:37] 0.12 0.32 0.31 0.14 0.7 0.92 1.93 0.2 0.99 1.5 ...
#>  - attr(*, "groups")= tibble [37 × 2] (S3: tbl_df/tbl/data.frame)
#>   ..$ Year_of_Release: num [1:37] 1980 1981 1982 1983 1984 ...
#>   ..$ .rows          : list<int> [1:37] 
#>   .. ..$ : int 1
#>   .. ..$ : int 2
#>   .. ..$ : int 3
#>   .. ..$ : int 4
#>   .. ..$ : int 5
#>   .. ..$ : int 6
#>   .. ..$ : int 7
#>   .. ..$ : int 8
#>   .. ..$ : int 9
#>   .. ..$ : int 10
#>   .. ..$ : int 11
#>   .. ..$ : int 12
#>   .. ..$ : int 13
#>   .. ..$ : int 14
#>   .. ..$ : int 15
#>   .. ..$ : int 16
#>   .. ..$ : int 17
#>   .. ..$ : int 18
#>   .. ..$ : int 19
#>   .. ..$ : int 20
#>   .. ..$ : int 21
#>   .. ..$ : int 22
#>   .. ..$ : int 23
#>   .. ..$ : int 24
#>   .. ..$ : int 25
#>   .. ..$ : int 26
#>   .. ..$ : int 27
#>   .. ..$ : int 28
#>   .. ..$ : int 29
#>   .. ..$ : int 30
#>   .. ..$ : int 31
#>   .. ..$ : int 32
#>   .. ..$ : int 33
#>   .. ..$ : int 34
#>   .. ..$ : int 35
#>   .. ..$ : int 36
#>   .. ..$ : int 37
#>   .. ..@ ptype: int(0) 
#>   ..- attr(*, ".drop")= logi TRUE

aa <- ggplot(ventas_por_regiones) + geom_point(aes(Year_of_Release, Total_ventas, color = "Total_ventas")) + 
   geom_line(aes(Year_of_Release, Total_ventas, color = "Total_ventas")) + 
   geom_point(aes(Year_of_Release, NA_ventas, color= "NA_ventas")) + 
   geom_line(aes(Year_of_Release, NA_ventas, color = "NA_ventas")) + 
   geom_point(aes(Year_of_Release, EU_ventas, color = "EU_ventas")) + 
   geom_line(aes(Year_of_Release, EU_ventas, color = "EU_ventas")) + 
   geom_point(aes(Year_of_Release, JP_ventas, color = "JP_ventas")) + 
   geom_line(aes(Year_of_Release, JP_ventas, color = "JP_ventas")) +
   geom_point(aes(Year_of_Release, Otros_ventas, color = "Otros_ventas")) + 
   geom_line(aes(Year_of_Release, Otros_ventas, color = "Otros_ventas")) + 
   scale_x_continuous(breaks = seq(1980,2016,2)) + 
    scale_y_continuous(breaks = seq(0,680,50)) + 
   theme(panel.grid.major = element_line(colour = "gray90",
    size = 0.3), panel.grid.minor = element_line(colour = "gray90"),
    axis.text.x = element_text(angle = 90),
    panel.background = element_rect(fill = "white"),
    plot.background = element_rect(colour = NA,
        size = 0.7)) +labs(title = "Cifra de ventas por regiones entre 1980 y 2016",
    x = "Año", y = "Cifra de ventas, en millones de euros ", colour = "Regiones") + theme(axis.title = element_text(size = 13),
    axis.text = element_text(size = 15),
    plot.title = element_text(size = 17),
    legend.text = element_text(size = 15),
    legend.title = element_text(size = 15)) + theme(axis.title = element_text(size = 15))
 
 aa
 
 
 

Otro forma más concreta de estudiar el mercado es viendo cual ha sido el best seller de cada año, como muestra la tabla siguiente. La gama de colores hace referencia a las ventas totales, yendo de más oscuro a menor cifra de ventas a más claro. De la tabla podemos extraer que, el videojuego más vendido con una gran diferencia es el Wii Sports de Wii.

Los años de mayores ventas de videojuegos se produjeron tras la salida de Wii, el 19 de noviembre de 2006. La videoconsola supuso una revolución, ya que combinaba los movimientos de la persona con el propio videojuego. Desde su salida, la Wii mantuvo un videojuego como best seller los cuatro años siguientes, como se muestra en la tabla, pero a partir de entonces el boom inicial fué desinchandose.

#Tabla de videojuego más importante de cada año

gt_tabla <- juego_del_año %>% gt()


gt_tabla <- gt_tabla %>% tab_header(title = md("**Videojuego más vendido cada año**"),
                     subtitle = md("Ventas en millones de euros")) %>% 
  tab_footnote("Videojuego más vendido", cells_body((Videojuego), row = 27)) 

q_colors =  19 
v_colors =  viridis(q_colors, option ="D")

gt_tabla <- gt_tabla %>%  data_color(columns=vars("Ventas"), 
             color=scales::col_bin( bins=c(2, 4, 6, 8, 10, 20, 30, 40, 50, 60,70, 80, 90), 
             palette = v_colors, 
             domain=c(0, 90)) )

gt_tabla
Videojuego más vendido cada año
Ventas en millones de euros
Año Videojuego Plataforma Genero Desarrolladora Ventas
1980 Asteroids 2600 Shooter Atari 4.31
1981 Pitfall! 2600 Platform Activision 4.50
1982 Pac-Man 2600 Puzzle Atari 7.81
1983 Baseball NES Sports Nintendo 3.20
1984 Duck Hunt NES Shooter Nintendo 28.31
1985 Super Mario Bros. NES Platform Nintendo 40.24
1986 The Legend of Zelda NES Action Nintendo 6.51
1987 Zelda II: The Adventure of Link NES Adventure Nintendo 4.38
1988 Super Mario Bros. 3 NES Platform Nintendo 17.28
1989 Tetris GB Puzzle Nintendo 30.26
1990 Super Mario World SNES Platform Nintendo 20.61
1991 The Legend of Zelda: A Link to the Past SNES Action Nintendo 4.61
1992 Super Mario Land 2: 6 Golden Coins GB Adventure Nintendo 11.18
1993 Super Mario All-Stars SNES Platform Nintendo 10.55
1994 Donkey Kong Country SNES Platform Nintendo 9.30
1995 Donkey Kong Country 2: Diddy's Kong Quest SNES Platform Nintendo 5.15
1996 Pokemon Red/Pokemon Blue GB Role-Playing Nintendo 31.37
1997 Gran Turismo PS Racing Sony Computer Entertainment 10.95
1998 Pokémon Yellow: Special Pikachu Edition GB Role-Playing Nintendo 14.64
1999 Pokemon Gold/Pokemon Silver GB Role-Playing Nintendo 23.10
2000 Pokémon Crystal Version GB Role-Playing Nintendo 6.39
2001 Gran Turismo 3: A-Spec PS2 Racing Sony Computer Entertainment 14.98
2002 Grand Theft Auto: Vice City PS2 Action Take-Two Interactive 16.15
2003 Need for Speed Underground PS2 Racing Electronic Arts 7.20
2004 Grand Theft Auto: San Andreas PS2 Action Take-Two Interactive 20.81
2005 Nintendogs DS Simulation Nintendo 24.67
2006 Wii Sports1 Wii Sports Nintendo 82.53
2007 Wii Fit Wii Sports Nintendo 22.70
2008 Mario Kart Wii Wii Racing Nintendo 35.52
2009 Wii Sports Resort Wii Sports Nintendo 32.77
2010 Kinect Adventures! X360 Misc Microsoft Game Studios 21.81
2011 Call of Duty: Modern Warfare 3 X360 Shooter Activision 14.73
2012 Call of Duty: Black Ops II PS3 Shooter Activision 13.79
2013 Grand Theft Auto V PS3 Action Take-Two Interactive 21.04
2014 Grand Theft Auto V PS4 Action Take-Two Interactive 12.61
2015 Call of Duty: Black Ops 3 PS4 Shooter Activision 14.63
2016 FIFA 17 PS4 Sports Electronic Arts 7.59

1 Videojuego más vendido

3.2 Top 3

A continuación se muestra en un gráfico combinado los 5 juegos más vendido de cada región, destacando 3, para realizar una análisis posterior. Los resultados de las regiones tienen coincidencias, como por ejemplo que el Wii Sports aparece en todas menos en Japon, donde han triunfado mayoritariamente los juegos de Pokemon. Por otro lado, el Super Mario Bros esta presente en 3 de las 4 regiones.

bb <- ggplot(mas_exitosos_global, aes(x = reorder(Name,Global_Sales), y = Global_Sales)) + geom_bar(stat = "identity", fill = "red") + coord_flip() +
  gghighlight::gghighlight(Name %in% c("Wii Sports", "Super Mario Bros.", "Mario Kart Wii")) + theme(panel.grid.major = element_line(colour = "gray90"),
    panel.grid.minor = element_line(colour = "gray90"),
    panel.background = element_rect(fill = NA)) +labs(x = "Videojuegos", y = "Cifra de ventas, en millones de euros") + theme(axis.title = element_text(size = 18),
    axis.text = element_text(size = 17)) + theme(plot.title = element_text(size = 19,
    hjust = 0.5)) +labs(title = "Totales")
  
cc <- ggplot(mas_exitosos_EU, aes(x = reorder(Name,EU_Sales), y = EU_Sales)) + 
  geom_bar(stat = "identity", fill = "red") + coord_flip()  + 
  gghighlight::gghighlight(Name %in% c("Wii Sports", "Nintendogs", "Mario Kart Wii")) + 
  theme(panel.grid.major = element_line(colour = "gray90"),
    panel.grid.minor = element_line(colour = "gray90"),
    panel.background = element_rect(fill = NA)) +labs(x = "Videojuegos", y = "Cifra de ventas, en millones de euros") + theme(axis.title = element_text(size = 18),
    axis.text = element_text(size = 17)) + theme(plot.title = element_text(size = 19,
    hjust = 0.5)) +labs(title = "Europa")


dd <- ggplot(mas_exitosos_NA, aes(x = reorder(Name,NA_Sales), y = NA_Sales)) + 
  geom_bar(stat = "identity", fill = "red") + coord_flip()  + 
  gghighlight::gghighlight(Name %in% c("Wii Sports", "Super Mario Bros.", "Duck Hunt")) +  
  theme(panel.grid.major = element_line(colour = "gray90"),
    panel.grid.minor = element_line(colour = "gray90"),
    panel.background = element_rect(fill = NA)) +labs(x = "Videojuegos", y = "Cifra de ventas, en millones de euros") + theme(axis.title = element_text(size = 18),
    axis.text = element_text(size = 17)) + theme(plot.title = element_text(size = 19,
    hjust = 0.5)) +labs(title = "Norte América")

ee <- ggplot(mas_exitosos_JP, aes(x = reorder(Name,JP_Sales), y = JP_Sales)) + 
  geom_bar(stat = "identity", fill = "red") + coord_flip()  + 
  gghighlight::gghighlight(Name %in% c("Pokemon Red/Pokemon Blue", "Super Mario Bros.", "Pokemon Gold/Pokemon Silver")) + theme(panel.grid.major = element_line(colour = "gray90"),
    panel.grid.minor = element_line(colour = "gray90"),
    panel.background = element_rect(fill = NA)) +labs(x = "Videojuegos", y = "Cifra de ventas, en millones de euros") + theme(axis.title = element_text(size = 18),
    axis.text = element_text(size = 17)) + theme(plot.title = element_text(size = 19,
    hjust = 0.5)) +labs(title = "Japón") 

ff <-  ggplot(mas_exitosos_Otros, aes(x = reorder(Name,Other_Sales), y = Other_Sales)) + 
  geom_bar(stat = "identity", fill = "red") + coord_flip()  + 
  gghighlight::gghighlight(Name %in% c("Grand Theft Auto: San Andreas", "Wii Sports", "Gran Turismo 4")) +  theme(panel.grid.major = element_line(colour = "gray90"),
    panel.grid.minor = element_line(colour = "gray90"),
    panel.background = element_rect(fill = NA)) +labs(x = "Videojuegos", y = "Cifra de ventas, en millones de euros") + theme(axis.title = element_text(size = 18),
    axis.text = element_text(size = 17)) + theme(plot.title = element_text(size = 19,
    hjust = 0.5)) +labs(title = "Resto de regiones")


# para juntar los gráficos no puedo usar face_wrap ya el df cambia, utilizamos el paquete patchwork
g_videojuegos <- (bb)/(cc+dd)/(ee+ff)

g_videojuegos + plot_annotation(
  title = "Top 5 juegos más vendidos en cada región") &   theme(text = element_text(size = 23)) 

Desarrolladoras

Las desarrolladoras hace referencia a las empresas encargadas de elaborar el software del videojuego. Existe una dominancia total de nintendo, siendo la desarrolladora de 7 de los 9 juegos que componen esta lista. Las otros dos desarrolladoras se encuentran con un juego cada una.


#Para poder el gráfica de barras apilado necesito una tercera variable que actue de x, por lo que creo una variable falsa

mas_exitosas_desarrolladoras <- mas_exitosas_desarrolladoras %>% 
   mutate(x = "Desarrolladora")


 graf_des <-  ggplot(mas_exitosas_desarrolladoras, aes(x = x, y = n_desarrolladoras, fill = Publisher)) + geom_bar(stat = "identity", color = "black") +
  scale_fill_manual(values = c("#DADAEB", "#9E9AC8", "#6A51A3")) +
    scale_y_continuous(breaks = seq(0,9,1)) + 
  theme(panel.grid.major = element_line(colour = "gray90"),
    panel.grid.minor = element_line(colour = "gray90"),
    axis.title = element_text(size = 18),
    axis.text = element_text(size = 18, colour = "black"),
    plot.title = element_text(size = 18,
        hjust = 0.5), panel.background = element_rect(fill = NA)) +labs(title = "Distribución de desarrolladoras en el Top 3 videojuegos de cada región",
    x = NULL, y = "Número ", fill = "Desarrolladoras") + theme(plot.subtitle = element_text(size = 11,
    hjust = 0.5)) +labs(title = "Distribución de desarrolladoras ",
    subtitle = "En el Top 3 videojuegos de cada región")
 
  
graf_des

Géneros

En el apartado de los géneros existe una moyor homogeneidad. Destacan los géneros de racing y role-playing con dos juegos cada uno. A el resto de géneros les pertenece un vdeojuego.


#generos Top 3

mas_exitosos_generos <- mas_exitosos_generos %>% 
   mutate(x = "Género")

 graf_gen <-  ggplot(mas_exitosos_generos, aes(x = x, y = n_generos, fill = Genre)) + geom_bar(stat = "identity", color = "black") +
  scale_fill_manual(values = c("#9E3D22", "#CA5621", "#EA7E2E", "#DFCEBA", "#D0D1CA", "#5082B0", "#2B5C8A")) +
    scale_y_continuous(breaks = seq(0,9,1)) + 
  theme(panel.grid.major = element_line(colour = "gray90"),
    panel.grid.minor = element_line(colour = "gray90"),
    axis.title = element_text(size = 18),
    axis.text = element_text(size = 18, colour = "black"),
    plot.title = element_text(size = 18,
        hjust = 0.5), panel.background = element_rect(fill = NA)) +labs(title = "Distribución de géneros en el Top 3 videojuegos de cada región",
    x = NULL, y = "Número ", fill = "Géneros") + theme(plot.subtitle = element_text(size = 11,
    hjust = 0.5)) +labs(title = "Distribución de géneros ",
    subtitle = "En el Top 3 videojuegos de cada región")
 
  
graf_gen

Plataformas

Los resultados obtenidos para las plataformas están menos repartidos que en el caso de los géneros, componiendo la lista 5 videoconsolas, 4 de ellas con 2 videojuegos cada una.


# plataforma top 3

mas_exitosos_plataforma <- mas_exitosos_plataforma %>% 
   mutate(x = "Plataforma")

 graf_plat <-  ggplot(mas_exitosos_plataforma, aes(x = x, y = n_plataformas, fill = Platform)) + geom_bar(stat = "identity", color = "black") +
  scale_fill_manual(values = c("#A3123A", "#E9514C", "#D5CFBA", "#A1C893", "#59A359")) +
    scale_y_continuous(breaks = seq(0,9,1)) + 
  theme(panel.grid.major = element_line(colour = "gray90"),
    panel.grid.minor = element_line(colour = "gray90"),
    axis.title = element_text(size = 18),
    axis.text = element_text(size = 18, colour = "black"),
    plot.title = element_text(size = 18,
        hjust = 0.5), panel.background = element_rect(fill = NA)) +labs(title = "Distribución de plataformas en el Top 3 videojuegos de cada región",
    x = NULL, y = "Número ", fill = "Plataforma") + theme(plot.subtitle = element_text(size = 11,
    hjust = 0.5)) +labs(title = "Distribución de plataformas ",
    subtitle = "En el Top 3 videojuegos de cada región")
 
  
graf_plat

3.3 Profundizando en géneros y plataformas

A continuación, puede observarse a partir de dos tablas un análisis más detallado de la importancia que han tenido los distintos géneros y las distintas plataformas en el mercado de los videojuegos.

Géneros

Los géneros que menor impacto han tenido en el mundo de los videojuegos han sido Adventure y Strategy, con cifras bajas de ventas y de videojuegos lanzados, pero sobre todo el ratio ventas/número de videojuegos, estando muy por debajo de las siguientes categorias. El género con mayor proporción ventas/número de videojuegos es Misc, por lo que puede deducirse que gran parte de sus videojuegos han tenido una buena acogida. Por último, el género que más se ha desarrollado ha sido el de acción, con mayor número de ventas y videojuegos lanzados, pero si analizamos la proporción es el sexto género.


#Tabla formada por los géneros

tabla_categorias <- ventas_categoria %>% gt(rowname_col = "Género")
 
 tabla_categorias <- tabla_categorias  %>% tab_header(title = md("**Proporción de ventas por videojuego lanzado de cada género**"),
 subtitle = md("Ventas en millones de euros")) 
 
 tabla_categorias <- tabla_categorias %>% 
   data_color(
     columns = c(Ventas_género, Ventas_por_videojuego, Número_de_videojuegos),
    colors = blues9)

 tabla_categorias 
Proporción de ventas por videojuego lanzado de cada género
Ventas en millones de euros
Ventas_género Número_de_videojuegos Ventas_por_videojuego
Misc 425.48 396 1.0744444
Platform 378.64 407 0.9303194
Shooter 824.25 886 0.9303047
Sports 852.43 973 0.8760843
Racing 482.44 598 0.8067559
Action 1226.61 1677 0.7314311
Role-Playing 504.16 721 0.6992510
Simulation 205.07 306 0.6701634
Fighting 251.02 383 0.6554047
Puzzle 79.27 121 0.6551240
Adventure 81.68 265 0.3082264
Strategy 71.33 284 0.2511620

Plataformas

En relación a las plataformas, tanto la Wii como la PS1 son las consolas con más ventas por videojuego lanzado. Sin embargo, la plataforma que más ha dado de sí es la PS2, con 1161 videojuegos y 962,36 millones de ventas. La plataforma con peores datos es sin duda la PSVita, videoconsola que fue criticada desde su lanzamiento.


#Tabla formada por las plataformas
 tabla_platform <- ventas_platform %>% gt(rowname_col = "Plataforma")
 
 tabla_platform <- tabla_platform  %>% tab_header(title = md("**Proporción de ventas por videojuego lanzado de cada plataforma**"),
 subtitle = md("Ventas en millones de euros")) 
 
 tabla_platform <- tabla_platform %>% 
   data_color(
     columns = c(Ventas_plataforma, Ventas_por_videojuego, Número_de_videojuegos),
     colors = scales::col_numeric(
      palette = paletteer::paletteer_d(
        palette = "ggsci::red_material"
        ) %>% as.character(),
      domain = NULL
      )
  )

 tabla_platform
Proporción de ventas por videojuego lanzado de cada plataforma
Ventas en millones de euros
Ventas_plataforma Número_de_videojuegos Ventas_por_videojuego
Wii 672.86 492 1.3676016
PS 211.25 156 1.3541667
PS3 792.76 790 1.0034937
PS4 244.31 249 0.9811647
X360 863.50 881 0.9801362
PS2 962.36 1161 0.8289061
DS 384.02 469 0.8188060
XOne 130.30 165 0.7896970
3DS 124.00 158 0.7848101
WiiU 66.08 89 0.7424719
GBA 132.59 241 0.5501660
PSP 190.40 393 0.4844784
GC 160.79 356 0.4516573
XB 217.34 581 0.3740792
DC 4.55 14 0.3250000
PC 194.12 703 0.2761309
PSV 31.15 119 0.2617647

3.4 XboxOne vs Ps4

La competencia entre Xbox y PS es más que conocida. En los últimos años han sido las dos plataformas líderes, luchando por hacerse con la mayor cuota de mercado, vendiendo productos similares, pero siempre con una importante fidelización del cliente a través de la marca. Dicha rivalidad también se dió con la penúltima generación de videoconsolas, estrenandose incluso ambas consolas el mismo mes, con pocos días de diferencia.

Como muestran los siguientes gráficos, la batalla se ha decantado del lado de PlayStation. En el primer gráfico, en valores absolutos, las ventas de la Ps4 siempre han estado por encima de la XboxOne, existiendo una importnte diferencia, excepto el año de estreno. Por otro lado, en valores relativos, la diferencia también es clara, siendo PlayStation la clara ganadora de esta generación de videoconsolas.

Valores absolutos

graf_ventas_generaciones <- ggplot(juegos_XboxOne_ps4, aes(x=Year, y=Ventas_totales, fill = Platform)) + geom_bar(stat = "identity") +
  scale_fill_manual(values = c("black","green")) + 
   scale_x_continuous(breaks = seq(2013,2018,1)) + 
    scale_y_continuous(breaks = seq(0,240,25))  + theme(panel.grid.major = element_line(colour = "gray90"),
    panel.grid.minor = element_line(colour = NA),
    axis.title = element_text(size = 13),
    axis.text = element_text(size = 13, colour = "black"),
    plot.title = element_text(size = 16,
        hjust = 0.5), legend.text = element_text(size = 13),
    legend.title = element_text(size = 13),
    panel.background = element_rect(fill = NA),
    legend.position = "bottom", legend.direction = "horizontal") +labs(title = "Ventas globales de Ps4 y XboxOne",
    x = "Año", y = "Cifra de ventas, en millones de euros",
    fill = "Plataforma") + theme(legend.position = "right")



 ggplotly(graf_ventas_generaciones)

Valores relativos

graf_ventas_porcentuales <- ggplot(ventas_totales_plataforma, aes(x = "", y = porcentaje, fill = Platform)) + 
  geom_col(color = "white") + 
  scale_fill_manual(values = c("black", "green")) + 
  geom_label(aes(label = porcentaje),
             color = "white",
             position = position_stack(vjust = 0.5),
             show.legend = FALSE) + theme_void() +
  coord_polar(theta = "y")  + theme(plot.subtitle = element_text(size = 15,
    colour = "black", hjust = 0.5), panel.grid.major = element_line(colour = NA,
    size = 0), axis.title = element_text(size = 15),
    axis.text = element_text(size = 14, colour = "white"),
    plot.title = element_text(size = 16,
        hjust = 0.5), legend.title = element_text(size = 13),
    panel.background = element_rect(fill = NA),
    legend.position = "left") +labs(title = "Distribución de las ventas totales",
    x = NULL, y = "Ventas", fill = "Plataforma",
    subtitle = "entre 2013 y 2018") + theme(legend.text = element_text(size = 11))

graf_ventas_porcentuales

4. Bibliografia

Web del curso para la elaboración del trabajo.

Dataset utilizado.

LS0tCnRpdGxlOiAiRWwgbWVyY2FkbyBkZSBsb3MgdmlkZW9qdWVnb3MiCnN1YnRpdGxlOiAiQWxlamFuZHJvIEdhcmPDrWEgU2VnYXJyYSAoYWdhcnNlNEBhbHVtbmkudXYuZXMpIiAKYXV0aG9yOiAiVW5pdmVyc2l0YXQgZGUgVmFsw6huY2lhIgpkYXRlOiAiRGljaWVtYnJlIGRlIDIwMjEgKGFjdHVhbGl6YWRvIGVsIGByIGZvcm1hdChTeXMudGltZSgpLCAnJWQtJW0tJVknKWApIgpvdXRwdXQ6CiAgaHRtbF9kb2N1bWVudDoKICAgIGNvZGVfZm9sZGluZzogaGlkZQogICAgI2NzczogIi4vYXNzZXRzL215X2Nzc19maWxlLmNzcyIKICAgIHRoZW1lOiBwYXBlcgogICAgaGlnaGxpZ2h0OiB0ZXh0bWF0ZSAKICAgIHRvYzogdHJ1ZQogICAgdG9jX2RlcHRoOiAzIAogICAgdG9jX2Zsb2F0OiAKICAgICAgY29sbGFwc2VkOiB0cnVlCiAgICAgIHNtb290aF9zY3JvbGw6IHRydWUKICAgIHNlbGZfY29udGFpbmVkOiB0cnVlCiAgICBudW1iZXJfc2VjdGlvbnM6IGZhbHNlCiAgICBkZl9wcmludDoga2FibGUKICAgIGNvZGVfZG93bmxvYWQ6IHRydWUKZWRpdG9yX29wdGlvbnM6IAogIGNodW5rX291dHB1dF90eXBlOiBjb25zb2xlCi0tLQoKYGBge3IgcGFja2FnZXMtc2V0dXAsIGluY2x1ZGUgPSBGQUxTRX0KbGlicmFyeSh0aWR5dmVyc2UpCmxpYnJhcnkoa2xpcHB5KSAgIy0gcmVtb3Rlczo6aW5zdGFsbF9naXRodWIoInJsZXN1ci9rbGlwcHkiKQpsaWJyYXJ5KGtuaXRyKQpsaWJyYXJ5KHJpbykKbGlicmFyeShnZ3Bsb3QyKQpsaWJyYXJ5KGdnVGhlbWVBc3Npc3QpCmxpYnJhcnkocGF0Y2h3b3JrKQpsaWJyYXJ5KCBnZ2hpZ2hsaWdodCkKbGlicmFyeShwbG90bHkpCmxpYnJhcnkoZ3QpCmxpYnJhcnkoZ3RFeHRyYXMpCmxpYnJhcnkodmlyaWRpcykgICNpbnN0YWxsLnBhY2thZ2VzKCJ2aXJpZGlzIikKbGlicmFyeShzY2FsZXMpCmxpYnJhcnkoRFQpICAgI3JlbW90ZXM6Omluc3RhbGxfZ2l0aHViKCdyc3R1ZGlvL0RUJykKbGlicmFyeShwYWxldHRlZXIpCgoKYGBgCgpgYGB7ciBjaHVuay1zZXR1cCwgaW5jbHVkZSA9IEZBTFNFfQprbml0cjo6b3B0c19jaHVuayRzZXQoZWNobyA9IFRSVUUsIGV2YWwgPSBUUlVFLCBtZXNzYWdlID0gRkFMU0UsIHdhcm5pbmcgPSBGQUxTRSwgCiAgICAgICAgICAgICAgICAgICAgICAjcmVzdWx0cyA9ICJob2xkIiwKICAgICAgICAgICAgICAgICAgICAgIGNhY2hlID0gRkFMU0UsIGNhY2hlLnBhdGggPSAiL2NhY2hlcy8iLCBjb21tZW50ID0gIiM+IiwKICAgICAgICAgICAgICAgICAgICAgICNmaWcud2lkdGggPSA3LCAjZmlnLmhlaWdodD0gNywgICAKICAgICAgICAgICAgICAgICAgICAgICNvdXQud2lkdGggPSA3LCBvdXQuaGVpZ2h0ID0gNywKICAgICAgICAgICAgICAgICAgICAgIGNvbGxhcHNlID0gVFJVRSwgIGZpZy5zaG93ID0gImhvbGQiLAogICAgICAgICAgICAgICAgICAgICAgZmlnLmFzcCA9IDAuNjI4LCBvdXQud2lkdGggPSAiNzUlIiwgZmlnLmFsaWduID0gImNlbnRlciIpCmtuaXRyOjpvcHRzX2NodW5rJHNldChkZXYgPSAicG5nIiwgZGV2LmFyZ3MgPSBsaXN0KHR5cGUgPSAiY2Fpcm8tcG5nIikpCmBgYAoKCmBgYHtyIG9wdGlvbnMtc2V0dXAsIGluY2x1ZGUgPSBGQUxTRX0Kb3B0aW9ucyhzY2lwZW4gPSA5OTkpICMtIHBhcmEgcXVpdGFyIGxhIG5vdGFjacOzbiBjaWVudMOtZmljYQpvcHRpb25zKCJ5YW1sLmV2YWwuZXhwciIgPSBUUlVFKSAKYGBgCgoKYGBge3Iga2xpcHB5LCBlY2hvID0gRkFMU0V9CmtsaXBweTo6a2xpcHB5KHBvc2l0aW9uID0gYygidG9wIiwgInJpZ2h0IikpICMtIHJlbW90ZXM6Omluc3RhbGxfZ2l0aHViKCJybGVzdXIva2xpcHB5IikKYGBgCgoKPGhyIGNsYXNzPSJsaW5lYS1ibGFjayI+Cgo8ZGl2IHN0eWxlPSJ0ZXh0LWFsaWduOiBqdXN0aWZ5Ij48ZGl2Lz4KCjwhLS0gRWwgcMOhcnJhZm8gZGUgYWJham8gaGFzIGRlIGRlamFybG8gY2FzaSBpZ3VhbCwgc29sbyBIQVMgZGUgU1VTVElUVUlSICJwZXJlenA0NCIgcG9yIHR1IHVzdWFyaW8gZGUgR2l0aHViLS0+ClRyYWJham8gZWxhYm9yYWRvIHBhcmEgbGEgYXNpZ25hdHVyYSAiUHJvZ3JhbWFjacOzbiB5IG1hbmVqbyBkZSBkYXRvcyBlbiBsYSBlcmEgZGVsIEJpZyBEYXRhIiBkZSBsYSBVbml2ZXJzaXRhdCBkZSBWYWzDqG5jaWEgZHVyYW50ZSBlbCBjdXJzbyAyMDIxLTIwMjIuIEVsIHJlcG8gZGVsIHRyYWJham8gZXN0w6EgW2FxdcOtXShodHRwczovL2dpdGh1Yi5jb20vYWdhcnNlNC90cmFiYWpvX0JpZ0RhdGEpe3RhcmdldD0iX2JsYW5rIn0uIAoKPCEtLSBFbCBww6FycmFmbyBkZSBhYmFqbyBoYXMgZGUgZGVqYXJsbyBleGFjdGFtZW50ZSBpZ3VhbCwgTk8gSEFTIERFIENBTUJJQVIgTkFEQS0tPgoKTGEgcMOhZ2luYSB3ZWIgZGUgbGEgYXNpZ25hdHVyYSB5IGxvcyB0cmFiYWpvcyBkZSBtaXMgY29tcGHDsWVyb3MgcHVlZGVuIHZlcnNlIFthcXXDrV0oaHR0cHM6Ly9wZXJlenA0NC5naXRodWIuaW8vaW50cm8tZHMtMjEtMjItd2ViLzA3LXRyYWJham9zLmh0bWwpe3RhcmdldD0iX2JsYW5rIn0uCgoKPGhyIGNsYXNzPSJsaW5lYS1yZWQiPgoKIyAqKjEuIEludHJvZHVjY2nDs24qKgoKTG9zIHZpZGVvanVlZ29zIHNvbiB1biBlbGVtZW50byBjb24gY3JlY2llbnRlIGltcG9ydGFuY2lhIGVuIGxhIHZpZGEgZGUgbGFzIHBlcnNvbmFzLiBQb3IgdGFudG8sIGVzIGludGVyZXNhbnRlIGNvbm9jZXIgZWwgZnVuY2lvbmFtaWVudG8gZGUgc3UgbWVyY2FkbywgcG9yIGVqZW1wbG8sIGN1YWxlcyBzb24gbG9zIHZpZGVvanVlZ29zIHF1ZSBtw6FzIGhhbiB0cml1bmZhZG8sIGEgcXVlIGNvbnNvbGEgcGVydGVuZWNlbiwgZXRjLiBFc3RlIHRyYWJham8gcHJldGVuZGUgZGFyIHJlc3B1ZXN0YSBhIGVzdG9zIGFzcGVjdG9zLCBhIHRyYXbDqXMgZGUgZGlzdGludGFzIGdyw6FmaWNhcyB5IHRhYmxhcyBlbGFib3JhZGFzIGNvbiByLiAKCgpgYGB7cn0KCmBgYAoKCiMgICoqMi4gRGF0b3MqKgoKQSBwYXJ0aXIgZGUgbGEgcMOhZ2luYSB3ZWIgZGUgW2thZ2dsZV0oaHR0cHM6Ly93d3cua2FnZ2xlLmNvbSksIGhlIG9idGVuaWRvIHkgbWFuaXB1bGFkbyBsb3MgZGF0b3MgZGVsIHRyYWJham8gIGRlbCBzaWd1aWVudGUgW2RhdGFzZXRdKGh0dHBzOi8vd3d3LmthZ2dsZS5jb20vc2lkdHdyL3ZpZGVvZ2FtZXMtc2FsZXMtZGF0YXNldCkKCgojIyAyLjEuIFByb2Nlc2FuZG8gbG9zIGRhdG9zCgpFbCBkYXRhc2V0IHNlIGNvbXBvbmUgZGUgdHJlcyBkYXRhIGZyYW1lcywgbG9zIGN1YWxlcyBlc3RhbiBmb3JtYWRvcyBwb3IgZGlzdGludG9zIHZpZGVvanVlZ29zLCBsYSBmZWNoYSBkZSBsYW56YW1pZW50byBkZSBsb3MgY3VhbGVzIHNlIGVuY3VlbnRyYSBlbnRyZSAxOTgwIHkgMjAyMC4gRWwgcHJpbWVybyBkZSBlbGxvcyBlc3RhIGludGVncmFkbyBwb3IgdG9kb3MgbG9zIHZpZGVvanVlZ29zLCBtaWVudHJhcyBxdWUgbG9zIG90cm9zIGRvcyBkYXRhZnJhbWVzIHNlIGNlbnRyYW4gZW4gbG9zIHZpZGVvanVlZ29zIGRlIHN1cyByZXNwZWN0aXZhcyBwbGF0YWZvcm1hcy4gQ2FiZSBkZXN0YWNhciBxdWUgZHVyYW50ZSBlbCBhbsOhbGlzaXMsIGEgcGFydGlyIGRlIDIwMTcgZXhpc3RlbiB1bmEgZ3JhbiBjYW50aWRhZCBkZSBOQSwgcG9yIGxvIHF1ZSBsYSBncmFuIG1heW9yw61hIGRlIGxvcyBhcGFydGFkb3MgYWJhcmNhbiBoYXN0YSAyMDE2LiBQb3Igb3RybyBsYWRvLCBlbCBEYXRhIHNldCB0aWVuZSB1bmEgdmlzacOzbiBjdXJpb3NhIGRlbCBtdW5kbywgeWEgcXVlIGxvIGRpdmlkZSBlbiBkb3MgY29udGluZW50ZXMsIHVuIHBhw61zIHkgZWwgcmVzdG8sIHBvciBsbyBxdWUgaGFjZSBxdWUgbGFzIGNvbXBhcmFjaW9uZXMgdGVycml0b3JpYWxlcyBubyBzZWFuIG11eSByZXZlbGFkb3Jhcy4gCgpgYGB7ciwgZXZhbCA9IFRSVUV9CiNlbiBwcmltZXIgbHVnYXIgaW1wb3J0YW1vcyBsb3MgZGF0b3MKCmp1ZWdvc19wczQgPC0gcmlvOjppbXBvcnQoZmlsZSA9ICIuL2RhdG9zL1BTNF9HYW1lc1NhbGVzLmNzdiIpCmp1ZWdvcyA8LSByaW86OmltcG9ydChmaWxlID0gIi4vZGF0b3MvVmlkZW9fR2FtZXNfU2FsZXNfYXNfYXRfMjJfRGVjXzIwMTYuY3N2IikKanVlZ29zX1hib3hPbmUgPC0gcmlvOjppbXBvcnQoZmlsZSA9ICIuL2RhdG9zL1hib3hPbmVfR2FtZVNhbGVzLmNzdiIpCgoKI2FuYWxpemFtb3MgZGUgcXVlIHRpcG8gc29uIGxhcyB2YXJpYWJsZXMgZGUgbG9zIGRmCnN0cihqdWVnb3NfcHM0KQpzdHIoanVlZ29zKQpzdHIoanVlZ29zX1hib3hPbmUpCgoKCiN2ZW50YXMgcG9yIHJlZ2lvbmVzIHkgdG90YWwgZW4gY2FkYSBhw7FvCiB2ZW50YXNfcG9yX3JlZ2lvbmVzIDwtIGp1ZWdvcyAlPiUKICBncm91cF9ieShZZWFyX29mX1JlbGVhc2UpICU+JSAKICBtdXRhdGUoVG90YWxfdmVudGFzID0gc3VtKEdsb2JhbF9TYWxlcykpICU+JQogIG11dGF0ZShOQV92ZW50YXMgPSBzdW0oTkFfU2FsZXMpKSAlPiUgCiAgbXV0YXRlKEVVX3ZlbnRhcyA9IHN1bShFVV9TYWxlcykpICU+JSAKICBtdXRhdGUoSlBfdmVudGFzID0gc3VtKEpQX1NhbGVzKSkgJT4lCiAgbXV0YXRlKE90cm9zX3ZlbnRhcyA9IHN1bShPdGhlcl9TYWxlcykpICU+JQogIHNlbGVjdChZZWFyX29mX1JlbGVhc2UsIFRvdGFsX3ZlbnRhcywgTkFfdmVudGFzLCBFVV92ZW50YXMsIEpQX3ZlbnRhcywgT3Ryb3NfdmVudGFzKSAlPiUgCiAgZGlzdGluY3QoWWVhcl9vZl9SZWxlYXNlLCBUb3RhbF92ZW50YXMsIE5BX3ZlbnRhcywgRVVfdmVudGFzLCBKUF92ZW50YXMsIE90cm9zX3ZlbnRhcykgJT4lIAogIGFycmFuZ2UoWWVhcl9vZl9SZWxlYXNlKSAlPiUgCiAgZmlsdGVyKC4sWWVhcl9vZl9SZWxlYXNlID49MTk4MCwgWWVhcl9vZl9SZWxlYXNlPD0yMDE2KQogCiAjIGEgcGFydGlyIGRlIDIwMTcgbG9zIGRhdG9zIHNvbiBwb2NvIGlsdXN0cmF0aXZvcywgYWRlbcOhcyBkZSBhcGFyZWNlciB1bmEgZ3JhbiBjYW50aWRhZCBkZSBOQSwgcG9yIGxvIHF1ZSBsb3MgZXhjbHVpbXMgZGUgZXN0ZSBhcGFydGFkby4KIAogCiAjIHZpZGVvanVlZ29zIGNvbiBtYXlvcmVzIHZlbnRhcyBlbiBjYWRhIGNvbnRpbmVudGUgIAogbWFzX2V4aXRvc29zX2dsb2JhbCA8LSBqdWVnb3MgJT4lIHNsaWNlX21heChHbG9iYWxfU2FsZXMsIG49NSkKIAogbWFzX2V4aXRvc29zX0VVIDwtIGp1ZWdvcyAlPiUgc2xpY2VfbWF4KEVVX1NhbGVzLCBuPTUpCgogbWFzX2V4aXRvc29zX0pQIDwtIGp1ZWdvcyAlPiUgc2xpY2VfbWF4KEpQX1NhbGVzLCBuPTUpCgogbWFzX2V4aXRvc29zX05BIDwtIGp1ZWdvcyAlPiUgc2xpY2VfbWF4KE5BX1NhbGVzLCBuPTUpCiAKIG1hc19leGl0b3Nvc19PdHJvcyA8LSBqdWVnb3MgJT4lIHNsaWNlX21heChPdGhlcl9TYWxlcywgbj01KQogCiAjY3JlYW1vcyBsb3MgbWlzbW9zIGRmIHBlcm8gc29sbyBlbCB0b3AgMyBkZSBjYWRhIHJlZ2lvbiAKIAogIG1hc19leGl0b3Nvc19nbG9iYWxfdjIgPC0ganVlZ29zICU+JSBzbGljZV9tYXgoR2xvYmFsX1NhbGVzLCBuPTMpCiAKIG1hc19leGl0b3Nvc19FVV92MiA8LSBqdWVnb3MgJT4lIHNsaWNlX21heChFVV9TYWxlcywgbj0zKQoKIG1hc19leGl0b3Nvc19KUF92MiA8LSBqdWVnb3MgJT4lIHNsaWNlX21heChKUF9TYWxlcywgbj0zKQoKIG1hc19leGl0b3Nvc19OQV92MiA8LSBqdWVnb3MgJT4lIHNsaWNlX21heChOQV9TYWxlcywgbj0zKQogCiBtYXNfZXhpdG9zb3NfT3Ryb3NfdjIgPC0ganVlZ29zICU+JSBzbGljZV9tYXgoT3RoZXJfU2FsZXMsIG49MykKIAogIyBjcmVhbW9zIHVuIGRmIGNvbiBsb3MgdG9wIDMgdmlkZW9qdWVnb3MgZGUgY2FkYSByZ2nDs24sIHBhcmEgYW5hbGl6YXIgZGlzdGludG9zIGFzcGVjdG9zCiAKIG1hc19leGl0b3Nvc19hbGwgPC0gZnVsbF9qb2luKG1hc19leGl0b3Nvc19nbG9iYWxfdjIsIG1hc19leGl0b3Nvc19FVV92MikgJT4lIAogICBzZWxlY3QoTmFtZSwgUGxhdGZvcm0sIFllYXJfb2ZfUmVsZWFzZSwgR2VucmUsIFB1Ymxpc2hlciwgTkFfU2FsZXMsIEVVX1NhbGVzLCBKUF9TYWxlcywgT3RoZXJfU2FsZXMsIEdsb2JhbF9TYWxlcykgJT4lIAogICBmdWxsX2pvaW4oLiwgbWFzX2V4aXRvc29zX0pQX3YyKSAlPiUgCiAgIGZ1bGxfam9pbiguLCBtYXNfZXhpdG9zb3NfTkFfdjIpICU+JSAKICAgZnVsbF9qb2luKC4sIG1hc19leGl0b3Nvc19PdHJvc192MikgJT4lIAogICBkaXN0aW5jdChOYW1lLCBQbGF0Zm9ybSwgWWVhcl9vZl9SZWxlYXNlLCBHZW5yZSwgUHVibGlzaGVyLCBOQV9TYWxlcywgRVVfU2FsZXMsIEpQX1NhbGVzLCBPdGhlcl9TYWxlcywgR2xvYmFsX1NhbGVzKQogCiAjZGVzYXJyb2xsYWRvcmFzCiBtYXNfZXhpdG9zYXNfZGVzYXJyb2xsYWRvcmFzIDwtIG1hc19leGl0b3Nvc19hbGwgJT4lICBncm91cF9ieShQdWJsaXNoZXIpICU+JSAKICAgbXV0YXRlKG5fZGVzYXJyb2xsYWRvcmFzID0gc3VtKE5OID0gbigpKSkgJT4lIAogICBzZWxlY3QoUHVibGlzaGVyLCBuX2Rlc2Fycm9sbGFkb3JhcykgJT4lIAogICBkaXN0aW5jdChQdWJsaXNoZXIsIG5fZGVzYXJyb2xsYWRvcmFzKQogCiAjR8OpbmVybwogIG1hc19leGl0b3Nvc19nZW5lcm9zIDwtIG1hc19leGl0b3Nvc19hbGwgJT4lICBncm91cF9ieShHZW5yZSkgJT4lIAogICBtdXRhdGUobl9nZW5lcm9zID0gc3VtKE5OID0gbigpKSkgJT4lIAogICBzZWxlY3QoR2VucmUsIG5fZ2VuZXJvcykgJT4lIAogICBkaXN0aW5jdChHZW5yZSwgbl9nZW5lcm9zKQogCiAKICNQbGF0YWZvcm1hCiBtYXNfZXhpdG9zb3NfcGxhdGFmb3JtYSA8LSBtYXNfZXhpdG9zb3NfYWxsICU+JSAgZ3JvdXBfYnkoUGxhdGZvcm0pICU+JSAKICAgbXV0YXRlKG5fcGxhdGFmb3JtYXMgPSBzdW0oTk4gPSBuKCkpKSAlPiUgCiAgIHNlbGVjdChQbGF0Zm9ybSwgbl9wbGF0YWZvcm1hcykgJT4lIAogICBkaXN0aW5jdCAoUGxhdGZvcm0sIG5fcGxhdGFmb3JtYXMpCiAKIAogI0EgY29udGludWFjacOzbiBwYXNhcsOpIGEgY29tcGFyYXIgbGFzIHZlbnRhcyBkZSBsYXMgZG9zIHBlbsO6bHRpbWFzIGdlbmVyYWNpb25lcyBkZSBjb25zb2xhcywgZXMgZGVjaXIsIGxhIFBzNCB5IGxhIFhib3hPbmUuIE5lY2VzaXRvIGxhIHZhcmlhYmxlIGRlIHBsYXRmb3JtIHBhcmEgZWwgYW5hbGlzaXMgcG9zdGVyaW9yLCBwb3IgbG8gcXVlIGludHJvZHVjaXLDqSBtYW51YWxtZW50ZSBlbiBsb3MgZG9zIGRmIGxhIHZhcmlhYmxlLiBObyBsb3MgZnVzaW9ubyBjb24gZWwgZWwgZGYganVlZ29zIHlhIHF1ZSB0aWVuZSBlbCBwcm9ibGVtYSBkZSBsb3MgTkEgYSBwYXJ0aXIgZGUgMjAxNy4KanVlZ29zX3BzNFssIGMoMildIDwtIHNhcHBseShqdWVnb3NfcHM0WywgYygyKV0sIGFzLm51bWVyaWMpCgogCiBqdWVnb3NfcHM0X3ZlbnRhcyA8LSBqdWVnb3NfcHM0ICU+JSBtdXRhdGUoUGxhdGZvcm0gPSAiUFM0IikgJT4lIAogICBncm91cF9ieShZZWFyKSAlPiUgCiAgIG11dGF0ZShWZW50YXNfdG90YWxlcyA9IHN1bShHbG9iYWwpKSAlPiUgCiAgIGRpc3RpbmN0KFllYXIsIFZlbnRhc190b3RhbGVzLCBQbGF0Zm9ybSkgJT4lIAogICBmaWx0ZXIgKFllYXIgPj0gMjAxMywgWWVhciA8PSAyMDE4KQogCiAKanVlZ29zX1hib3hPbmVbLCBjKDMpXSA8LSBzYXBwbHkoanVlZ29zX1hib3hPbmVbLCBjKDMpXSwgYXMubnVtZXJpYykKIAoganVlZ29zX1hib3hPbmVfdmVudGFzIDwtIGp1ZWdvc19YYm94T25lICU+JSBtdXRhdGUoUGxhdGZvcm0gPSAiWGJveE9uZSIpICU+JSAKICAgZ3JvdXBfYnkoWWVhcikgJT4lIAogICBtdXRhdGUoVmVudGFzX3RvdGFsZXMgPSBzdW0oR2xvYmFsKSkgJT4lIAogICBkaXN0aW5jdChZZWFyLCBWZW50YXNfdG90YWxlcywgUGxhdGZvcm0pICU+JSAKICAgZmlsdGVyIChZZWFyID49IDIwMTMsIFllYXIgPD0gMjAxOCkKCiAKICMgQSBjb250aW51YWNpw7NuIGp1bnRvIGxvcyBkb3MgZGYgcGFyYSBwb2RlciBoYWNlciBsYXMgY29tcGFyYWNpb25lcwpqdWVnb3NfWGJveE9uZV9wczQgPC0gZnVsbF9qb2luKGp1ZWdvc19wczRfdmVudGFzLCBqdWVnb3NfWGJveE9uZV92ZW50YXMpCgojUG9yIMO6bHRpbW8gZGUgZXN0ZSBhcGFydGFkbyByZWFsaXphbW9zIHVuYSBjb21wYXJhY2nDs24gZW50cmUgbGFzIHZlbnRhcyB0b3RhbGVzIGRlIGNhZGEgcGxhdGFmb3JtYQp2ZW50YXNfdG90YWxlc19wbGF0YWZvcm1hIDwtIGp1ZWdvc19YYm94T25lX3BzNCAlPiUgCiAgZ3JvdXBfYnkoUGxhdGZvcm0pICU+JSAKICBtdXRhdGUoVmVudGFzID0gc3VtKFZlbnRhc190b3RhbGVzKSkgJT4lIAogIGRpc3RpbmN0KFZlbnRhcywgUGxhdGZvcm0pICU+JSAKICB1bmdyb3VwKFBsYXRmb3JtKSAlPiUgCiAgbXV0YXRlKGZpbmFsX3ZlbnRhcyA9IHN1bShWZW50YXMpKSAlPiUgCiAgbXV0YXRlKHZlbnRhc192ZW50YXNfdG90YWxlcyA9IFZlbnRhcyAvIGZpbmFsX3ZlbnRhcykgJT4lIAogIG11dGF0ZShwb3JjZW50YWplID0gc2NhbGVzOjpwZXJjZW50KHZlbnRhc192ZW50YXNfdG90YWxlcykpCgojVGFibGEgZGVsIGp1ZWdvIG3DoXMgdmVuZGlkbyBkZSBjYWRhIGHDsW8sIGRlIDE5ODAgYSAyMDE2LgoKanVlZ29fZGVsX2HDsW8gPC0ganVlZ29zICU+JSAKICBncm91cF9ieShZZWFyX29mX1JlbGVhc2UpICU+JSAKICBzbGljZV9tYXgobiA9IDEsIEdsb2JhbF9TYWxlcykgJT4lIAogIHVuZ3JvdXAoWWVhcl9vZl9SZWxlYXNlKSAlPiUgCiAgZmlsdGVyKFllYXJfb2ZfUmVsZWFzZSA+PSAxOTgwLCBZZWFyX29mX1JlbGVhc2UgPD0gMjAxNikgJT4lIAogIHNlbGVjdChZZWFyX29mX1JlbGVhc2UsIE5hbWUsIFBsYXRmb3JtLCBHZW5yZSwgUHVibGlzaGVyLCBHbG9iYWxfU2FsZXMpICU+JSAKICByZW5hbWUoVmlkZW9qdWVnbyA9IE5hbWUsIFBsYXRhZm9ybWEgPSBQbGF0Zm9ybSwgQcOxbyA9IFllYXJfb2ZfUmVsZWFzZSwgR2VuZXJvID0gR2VucmUsIERlc2Fycm9sbGFkb3JhID0gUHVibGlzaGVyLCBWZW50YXMgPSBHbG9iYWxfU2FsZXMpCiAgCgojdmVudGFzIGRlIGNhZGEgZ8OpbmVybwoKIGp1ZWdvcyA8LSBuYS5vbWl0KGp1ZWdvcykgI0VsaW1pbm8gbGFzIGZpbGFzIHF1ZSBjb250ZW5nYW4gbmEKIAogdmVudGFzX2NhdGVnb3JpYSA8LSBqdWVnb3MgJT4lIAogIGdyb3VwX2J5KEdlbnJlKSAlPiUgCiAgIG11dGF0ZShWZW50YXNfZ8OpbmVybyA9IHN1bShHbG9iYWxfU2FsZXMpKSAlPiUgCiAgIG11dGF0ZShOw7ptZXJvX2RlX3ZpZGVvanVlZ29zID0gc3VtKE5OID0gbigpKSkgJT4lICAKICAgbXV0YXRlKFZlbnRhc19wb3JfdmlkZW9qdWVnbyA9IFZlbnRhc19nw6luZXJvIC8gTsO6bWVyb19kZV92aWRlb2p1ZWdvcykgJT4lIAogIGRpc3RpbmN0KFZlbnRhc19nw6luZXJvLCBOw7ptZXJvX2RlX3ZpZGVvanVlZ29zLCBWZW50YXNfcG9yX3ZpZGVvanVlZ28gKSAlPiUgCiB1bmdyb3VwKCkgJT4lIAogICBhcnJhbmdlKGRlc2MoVmVudGFzX3Bvcl92aWRlb2p1ZWdvKSkgJT4lIAogICByZW5hbWUoR8OpbmVybyA9IEdlbnJlKQogCiAKICNhIGNvbnRpbnVhY2nDs24sIGRlIGNhZGEgcGxhdGFmb3JtYQogCiB2ZW50YXNfcGxhdGZvcm0gPC0ganVlZ29zICU+JSAKICBncm91cF9ieShQbGF0Zm9ybSkgJT4lIAogICBtdXRhdGUoVmVudGFzX3BsYXRhZm9ybWEgPSBzdW0oR2xvYmFsX1NhbGVzKSkgJT4lIAogICBtdXRhdGUoTsO6bWVyb19kZV92aWRlb2p1ZWdvcyA9IHN1bShOTiA9IG4oKSkpICU+JSAgCiAgIG11dGF0ZShWZW50YXNfcG9yX3ZpZGVvanVlZ28gPSBWZW50YXNfcGxhdGFmb3JtYSAvIE7Dum1lcm9fZGVfdmlkZW9qdWVnb3MpICU+JSAKICBkaXN0aW5jdChWZW50YXNfcGxhdGFmb3JtYSwgTsO6bWVyb19kZV92aWRlb2p1ZWdvcywgVmVudGFzX3Bvcl92aWRlb2p1ZWdvICkgJT4lIAogdW5ncm91cCgpICU+JSAKICAgYXJyYW5nZShkZXNjKFZlbnRhc19wb3JfdmlkZW9qdWVnbykpICU+JSAKICAgcmVuYW1lKFBsYXRhZm9ybWEgPSBQbGF0Zm9ybSkKIAogCmBgYAoKCgojICoqMy4gRWwgbWVyY2FkbyBkZSBsb3MgdmlkZW9qdWVnb3MqKgoKIyMgMy4xIEFuw6FsaXNpcyBnZW5lcmFsCgpBIHBhcnRpciBkZWwgZ3LDoWZpY28gbW9zdHJhZG8gYSBjb250aW51YWNpw7NuLCBwdWVkZSB2ZXJzZSBsYSBldm9sdWNpw7NuIGRlbCBtZXJjYWRvIGRlIGxvcyB2aWRlb2p1ZWdvcy4gTG9zIHZpZGVvanVlZ29zIGNvbWllbnphbiBhIHRlbmVyIGNpZnJhcyBjb25zaWRlcmF0aXZhcyBkZSB2ZW50YXMgYSBwYXJ0aXIgZGUgMTk5NCwgdGVuaWVuZG8gdW5hIGluY3JlaWJsZSBlc2NhbGFkYSBkZXNkZSBlbCAyMDAwIGhhc3RhIGVsIDIwMDguIEEgcGFydGlyIGRlIGVudG9uY2VzIGxhcyBjaWZyYXMgaGFuIGlkbyBjYXllbmRvLCBwcm9waWNpYWRvIGVuIHBhcnRlIHBvciBsYSBjYWRhIHZleiBtYXlvciBleGlzdGVuY2lhIHkgY29uc29saWRhY2nDs24gZGUgdmlkZW9qdWVnb3MgZGUgYWRxdWlzaWNpw7NuIGdyYXR1aXRhLCBwZXJvIHF1ZSBpbmNsdXllbiBtaWNyb3BhZ29zIGRlbnRybyBkZWwgcHJvcGlvIHZpZGVvanVlZ28uICAKCkVuIHJlbGFjacOzbiBjb24gbGFzIHJlZ2lvbmVzLCBOb3J0ZSBBbcOpcmljYSBzaWVtcHJlIGhhIHNpZG8gcGlvbmVyYSBlbiBsYSB2ZW50YSBkZSB2aWRlb2p1ZWdvcywgc2VndWlkYSBwb3IgRXVyb3BhLiBFbiBsb3Mgw7psdGltb3MgYcOxb3MgbGFzIGRpZmVyZW5jaWFzIGVudHJlIGFtYmFzIHJlZ2lvbmVzIHNlIGhhbiBpZG8gYXByb3hpbWFuZG8uCgpgYGB7ciwgZmlnLndpZHRoPTEwLCBmaWcuaGVpZ2h0PTEwfQogI1BhcmEgcG9kZXIgdXRpbGl6YXIgZ2VvbV9saW5lLCBlcyBuZWNlc2FyaW8gcXVlIGxhIHZhcmlhYmxlIGHDsW9zIHNlYSBudW3DqXJpY2EKIHN0cih2ZW50YXNfcG9yX3JlZ2lvbmVzKQp2ZW50YXNfcG9yX3JlZ2lvbmVzWywgYygxKV0gPC0gc2FwcGx5KHZlbnRhc19wb3JfcmVnaW9uZXNbLCBjKDEpXSwgYXMubnVtZXJpYykKIHN0cih2ZW50YXNfcG9yX3JlZ2lvbmVzKQoKYWEgPC0gZ2dwbG90KHZlbnRhc19wb3JfcmVnaW9uZXMpICsgZ2VvbV9wb2ludChhZXMoWWVhcl9vZl9SZWxlYXNlLCBUb3RhbF92ZW50YXMsIGNvbG9yID0gIlRvdGFsX3ZlbnRhcyIpKSArIAogICBnZW9tX2xpbmUoYWVzKFllYXJfb2ZfUmVsZWFzZSwgVG90YWxfdmVudGFzLCBjb2xvciA9ICJUb3RhbF92ZW50YXMiKSkgKyAKICAgZ2VvbV9wb2ludChhZXMoWWVhcl9vZl9SZWxlYXNlLCBOQV92ZW50YXMsIGNvbG9yPSAiTkFfdmVudGFzIikpICsgCiAgIGdlb21fbGluZShhZXMoWWVhcl9vZl9SZWxlYXNlLCBOQV92ZW50YXMsIGNvbG9yID0gIk5BX3ZlbnRhcyIpKSArIAogICBnZW9tX3BvaW50KGFlcyhZZWFyX29mX1JlbGVhc2UsIEVVX3ZlbnRhcywgY29sb3IgPSAiRVVfdmVudGFzIikpICsgCiAgIGdlb21fbGluZShhZXMoWWVhcl9vZl9SZWxlYXNlLCBFVV92ZW50YXMsIGNvbG9yID0gIkVVX3ZlbnRhcyIpKSArIAogICBnZW9tX3BvaW50KGFlcyhZZWFyX29mX1JlbGVhc2UsIEpQX3ZlbnRhcywgY29sb3IgPSAiSlBfdmVudGFzIikpICsgCiAgIGdlb21fbGluZShhZXMoWWVhcl9vZl9SZWxlYXNlLCBKUF92ZW50YXMsIGNvbG9yID0gIkpQX3ZlbnRhcyIpKSArCiAgIGdlb21fcG9pbnQoYWVzKFllYXJfb2ZfUmVsZWFzZSwgT3Ryb3NfdmVudGFzLCBjb2xvciA9ICJPdHJvc192ZW50YXMiKSkgKyAKICAgZ2VvbV9saW5lKGFlcyhZZWFyX29mX1JlbGVhc2UsIE90cm9zX3ZlbnRhcywgY29sb3IgPSAiT3Ryb3NfdmVudGFzIikpICsgCiAgIHNjYWxlX3hfY29udGludW91cyhicmVha3MgPSBzZXEoMTk4MCwyMDE2LDIpKSArIAogICAgc2NhbGVfeV9jb250aW51b3VzKGJyZWFrcyA9IHNlcSgwLDY4MCw1MCkpICsgCiAgIHRoZW1lKHBhbmVsLmdyaWQubWFqb3IgPSBlbGVtZW50X2xpbmUoY29sb3VyID0gImdyYXk5MCIsCiAgICBzaXplID0gMC4zKSwgcGFuZWwuZ3JpZC5taW5vciA9IGVsZW1lbnRfbGluZShjb2xvdXIgPSAiZ3JheTkwIiksCiAgICBheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDkwKSwKICAgIHBhbmVsLmJhY2tncm91bmQgPSBlbGVtZW50X3JlY3QoZmlsbCA9ICJ3aGl0ZSIpLAogICAgcGxvdC5iYWNrZ3JvdW5kID0gZWxlbWVudF9yZWN0KGNvbG91ciA9IE5BLAogICAgICAgIHNpemUgPSAwLjcpKSArbGFicyh0aXRsZSA9ICJDaWZyYSBkZSB2ZW50YXMgcG9yIHJlZ2lvbmVzIGVudHJlIDE5ODAgeSAyMDE2IiwKICAgIHggPSAiQcOxbyIsIHkgPSAiQ2lmcmEgZGUgdmVudGFzLCBlbiBtaWxsb25lcyBkZSBldXJvcyAiLCBjb2xvdXIgPSAiUmVnaW9uZXMiKSArIHRoZW1lKGF4aXMudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEzKSwKICAgIGF4aXMudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTUpLAogICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTcpLAogICAgbGVnZW5kLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE1KSwKICAgIGxlZ2VuZC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTUpKSArIHRoZW1lKGF4aXMudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE1KSkKIAogYWEKIAogCiAKCmBgYAoKCk90cm8gZm9ybWEgbcOhcyBjb25jcmV0YSBkZSBlc3R1ZGlhciBlbCBtZXJjYWRvIGVzIHZpZW5kbyBjdWFsIGhhIHNpZG8gZWwgKmJlc3Qgc2VsbGVyKiBkZSBjYWRhIGHDsW8sIGNvbW8gbXVlc3RyYSBsYSB0YWJsYSBzaWd1aWVudGUuIExhIGdhbWEgZGUgY29sb3JlcyBoYWNlIHJlZmVyZW5jaWEgYSBsYXMgdmVudGFzIHRvdGFsZXMsIHllbmRvIGRlIG3DoXMgb3NjdXJvIGEgbWVub3IgY2lmcmEgZGUgdmVudGFzIGEgbcOhcyBjbGFyby4gRGUgbGEgdGFibGEgcG9kZW1vcyBleHRyYWVyIHF1ZSwgZWwgdmlkZW9qdWVnbyBtw6FzIHZlbmRpZG8gY29uIHVuYSBncmFuIGRpZmVyZW5jaWEgZXMgZWwgV2lpIFNwb3J0cyBkZSBXaWkuICAKCkxvcyBhw7FvcyBkZSBtYXlvcmVzIHZlbnRhcyBkZSB2aWRlb2p1ZWdvcyBzZSBwcm9kdWplcm9uIHRyYXMgbGEgc2FsaWRhIGRlIFdpaSwgZWwgMTkgZGUgbm92aWVtYnJlIGRlIDIwMDYuIExhIHZpZGVvY29uc29sYSBzdXB1c28gdW5hIHJldm9sdWNpw7NuLCB5YSBxdWUgY29tYmluYWJhIGxvcyBtb3ZpbWllbnRvcyBkZSBsYSBwZXJzb25hIGNvbiBlbCBwcm9waW8gdmlkZW9qdWVnby4gRGVzZGUgc3Ugc2FsaWRhLCBsYSBXaWkgbWFudHV2byB1biB2aWRlb2p1ZWdvIGNvbW8gKmJlc3Qgc2VsbGVyKiBsb3MgY3VhdHJvIGHDsW9zIHNpZ3VpZW50ZXMsIGNvbW8gc2UgbXVlc3RyYSBlbiBsYSB0YWJsYSwgcGVybyBhIHBhcnRpciBkZSBlbnRvbmNlcyBlbCBib29tIGluaWNpYWwgZnXDqSBkZXNpbmNoYW5kb3NlLiAKIApgYGB7cn0KI1RhYmxhIGRlIHZpZGVvanVlZ28gbcOhcyBpbXBvcnRhbnRlIGRlIGNhZGEgYcOxbwoKZ3RfdGFibGEgPC0ganVlZ29fZGVsX2HDsW8gJT4lIGd0KCkKCgpndF90YWJsYSA8LSBndF90YWJsYSAlPiUgdGFiX2hlYWRlcih0aXRsZSA9IG1kKCIqKlZpZGVvanVlZ28gbcOhcyB2ZW5kaWRvIGNhZGEgYcOxbyoqIiksCiAgICAgICAgICAgICAgICAgICAgIHN1YnRpdGxlID0gbWQoIlZlbnRhcyBlbiBtaWxsb25lcyBkZSBldXJvcyIpKSAlPiUgCiAgdGFiX2Zvb3Rub3RlKCJWaWRlb2p1ZWdvIG3DoXMgdmVuZGlkbyIsIGNlbGxzX2JvZHkoKFZpZGVvanVlZ28pLCByb3cgPSAyNykpIAoKcV9jb2xvcnMgPSAgMTkgCnZfY29sb3JzID0gIHZpcmlkaXMocV9jb2xvcnMsIG9wdGlvbiA9IkQiKQoKZ3RfdGFibGEgPC0gZ3RfdGFibGEgJT4lICBkYXRhX2NvbG9yKGNvbHVtbnM9dmFycygiVmVudGFzIiksIAogICAgICAgICAgICAgY29sb3I9c2NhbGVzOjpjb2xfYmluKCBiaW5zPWMoMiwgNCwgNiwgOCwgMTAsIDIwLCAzMCwgNDAsIDUwLCA2MCw3MCwgODAsIDkwKSwgCiAgICAgICAgICAgICBwYWxldHRlID0gdl9jb2xvcnMsIAogICAgICAgICAgICAgZG9tYWluPWMoMCwgOTApKSApCgpndF90YWJsYQpgYGAKCgoKCiMjIDMuMiBUb3AgMyB7LnRhYnNldH0KCkEgY29udGludWFjacOzbiBzZSBtdWVzdHJhIGVuIHVuIGdyw6FmaWNvIGNvbWJpbmFkbyBsb3MgNSBqdWVnb3MgbcOhcyB2ZW5kaWRvIGRlIGNhZGEgcmVnacOzbiwgZGVzdGFjYW5kbyAzLCBwYXJhIHJlYWxpemFyIHVuYSBhbsOhbGlzaXMgcG9zdGVyaW9yLiBMb3MgcmVzdWx0YWRvcyBkZSBsYXMgIHJlZ2lvbmVzIHRpZW5lbiBjb2luY2lkZW5jaWFzLCBjb21vIHBvciBlamVtcGxvIHF1ZSBlbCBXaWkgU3BvcnRzIGFwYXJlY2UgZW4gdG9kYXMgbWVub3MgZW4gSmFwb24sIGRvbmRlIGhhbiB0cml1bmZhZG8gbWF5b3JpdGFyaWFtZW50ZSBsb3MganVlZ29zIGRlIFBva2Vtb24uIFBvciBvdHJvIGxhZG8sIGVsIFN1cGVyIE1hcmlvIEJyb3MgZXN0YSBwcmVzZW50ZSBlbiAzIGRlIGxhcyA0IHJlZ2lvbmVzLgoKYGBge3IsIGZpZy53aWR0aD0xNCwgZmlnLmhlaWdodD0xNH0KYmIgPC0gZ2dwbG90KG1hc19leGl0b3Nvc19nbG9iYWwsIGFlcyh4ID0gcmVvcmRlcihOYW1lLEdsb2JhbF9TYWxlcyksIHkgPSBHbG9iYWxfU2FsZXMpKSArIGdlb21fYmFyKHN0YXQgPSAiaWRlbnRpdHkiLCBmaWxsID0gInJlZCIpICsgY29vcmRfZmxpcCgpICsKICBnZ2hpZ2hsaWdodDo6Z2doaWdobGlnaHQoTmFtZSAlaW4lIGMoIldpaSBTcG9ydHMiLCAiU3VwZXIgTWFyaW8gQnJvcy4iLCAiTWFyaW8gS2FydCBXaWkiKSkgKyB0aGVtZShwYW5lbC5ncmlkLm1ham9yID0gZWxlbWVudF9saW5lKGNvbG91ciA9ICJncmF5OTAiKSwKICAgIHBhbmVsLmdyaWQubWlub3IgPSBlbGVtZW50X2xpbmUoY29sb3VyID0gImdyYXk5MCIpLAogICAgcGFuZWwuYmFja2dyb3VuZCA9IGVsZW1lbnRfcmVjdChmaWxsID0gTkEpKSArbGFicyh4ID0gIlZpZGVvanVlZ29zIiwgeSA9ICJDaWZyYSBkZSB2ZW50YXMsIGVuIG1pbGxvbmVzIGRlIGV1cm9zIikgKyB0aGVtZShheGlzLnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxOCksCiAgICBheGlzLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE3KSkgKyB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxOSwKICAgIGhqdXN0ID0gMC41KSkgK2xhYnModGl0bGUgPSAiVG90YWxlcyIpCiAgCmNjIDwtIGdncGxvdChtYXNfZXhpdG9zb3NfRVUsIGFlcyh4ID0gcmVvcmRlcihOYW1lLEVVX1NhbGVzKSwgeSA9IEVVX1NhbGVzKSkgKyAKICBnZW9tX2JhcihzdGF0ID0gImlkZW50aXR5IiwgZmlsbCA9ICJyZWQiKSArIGNvb3JkX2ZsaXAoKSAgKyAKICBnZ2hpZ2hsaWdodDo6Z2doaWdobGlnaHQoTmFtZSAlaW4lIGMoIldpaSBTcG9ydHMiLCAiTmludGVuZG9ncyIsICJNYXJpbyBLYXJ0IFdpaSIpKSArIAogIHRoZW1lKHBhbmVsLmdyaWQubWFqb3IgPSBlbGVtZW50X2xpbmUoY29sb3VyID0gImdyYXk5MCIpLAogICAgcGFuZWwuZ3JpZC5taW5vciA9IGVsZW1lbnRfbGluZShjb2xvdXIgPSAiZ3JheTkwIiksCiAgICBwYW5lbC5iYWNrZ3JvdW5kID0gZWxlbWVudF9yZWN0KGZpbGwgPSBOQSkpICtsYWJzKHggPSAiVmlkZW9qdWVnb3MiLCB5ID0gIkNpZnJhIGRlIHZlbnRhcywgZW4gbWlsbG9uZXMgZGUgZXVyb3MiKSArIHRoZW1lKGF4aXMudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE4KSwKICAgIGF4aXMudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTcpKSArIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE5LAogICAgaGp1c3QgPSAwLjUpKSArbGFicyh0aXRsZSA9ICJFdXJvcGEiKQoKCmRkIDwtIGdncGxvdChtYXNfZXhpdG9zb3NfTkEsIGFlcyh4ID0gcmVvcmRlcihOYW1lLE5BX1NhbGVzKSwgeSA9IE5BX1NhbGVzKSkgKyAKICBnZW9tX2JhcihzdGF0ID0gImlkZW50aXR5IiwgZmlsbCA9ICJyZWQiKSArIGNvb3JkX2ZsaXAoKSAgKyAKICBnZ2hpZ2hsaWdodDo6Z2doaWdobGlnaHQoTmFtZSAlaW4lIGMoIldpaSBTcG9ydHMiLCAiU3VwZXIgTWFyaW8gQnJvcy4iLCAiRHVjayBIdW50IikpICsgIAogIHRoZW1lKHBhbmVsLmdyaWQubWFqb3IgPSBlbGVtZW50X2xpbmUoY29sb3VyID0gImdyYXk5MCIpLAogICAgcGFuZWwuZ3JpZC5taW5vciA9IGVsZW1lbnRfbGluZShjb2xvdXIgPSAiZ3JheTkwIiksCiAgICBwYW5lbC5iYWNrZ3JvdW5kID0gZWxlbWVudF9yZWN0KGZpbGwgPSBOQSkpICtsYWJzKHggPSAiVmlkZW9qdWVnb3MiLCB5ID0gIkNpZnJhIGRlIHZlbnRhcywgZW4gbWlsbG9uZXMgZGUgZXVyb3MiKSArIHRoZW1lKGF4aXMudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE4KSwKICAgIGF4aXMudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTcpKSArIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE5LAogICAgaGp1c3QgPSAwLjUpKSArbGFicyh0aXRsZSA9ICJOb3J0ZSBBbcOpcmljYSIpCgplZSA8LSBnZ3Bsb3QobWFzX2V4aXRvc29zX0pQLCBhZXMoeCA9IHJlb3JkZXIoTmFtZSxKUF9TYWxlcyksIHkgPSBKUF9TYWxlcykpICsgCiAgZ2VvbV9iYXIoc3RhdCA9ICJpZGVudGl0eSIsIGZpbGwgPSAicmVkIikgKyBjb29yZF9mbGlwKCkgICsgCiAgZ2doaWdobGlnaHQ6OmdnaGlnaGxpZ2h0KE5hbWUgJWluJSBjKCJQb2tlbW9uIFJlZC9Qb2tlbW9uIEJsdWUiLCAiU3VwZXIgTWFyaW8gQnJvcy4iLCAiUG9rZW1vbiBHb2xkL1Bva2Vtb24gU2lsdmVyIikpICsgdGhlbWUocGFuZWwuZ3JpZC5tYWpvciA9IGVsZW1lbnRfbGluZShjb2xvdXIgPSAiZ3JheTkwIiksCiAgICBwYW5lbC5ncmlkLm1pbm9yID0gZWxlbWVudF9saW5lKGNvbG91ciA9ICJncmF5OTAiKSwKICAgIHBhbmVsLmJhY2tncm91bmQgPSBlbGVtZW50X3JlY3QoZmlsbCA9IE5BKSkgK2xhYnMoeCA9ICJWaWRlb2p1ZWdvcyIsIHkgPSAiQ2lmcmEgZGUgdmVudGFzLCBlbiBtaWxsb25lcyBkZSBldXJvcyIpICsgdGhlbWUoYXhpcy50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTgpLAogICAgYXhpcy50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNykpICsgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTksCiAgICBoanVzdCA9IDAuNSkpICtsYWJzKHRpdGxlID0gIkphcMOzbiIpIAoKZmYgPC0gIGdncGxvdChtYXNfZXhpdG9zb3NfT3Ryb3MsIGFlcyh4ID0gcmVvcmRlcihOYW1lLE90aGVyX1NhbGVzKSwgeSA9IE90aGVyX1NhbGVzKSkgKyAKICBnZW9tX2JhcihzdGF0ID0gImlkZW50aXR5IiwgZmlsbCA9ICJyZWQiKSArIGNvb3JkX2ZsaXAoKSAgKyAKICBnZ2hpZ2hsaWdodDo6Z2doaWdobGlnaHQoTmFtZSAlaW4lIGMoIkdyYW5kIFRoZWZ0IEF1dG86IFNhbiBBbmRyZWFzIiwgIldpaSBTcG9ydHMiLCAiR3JhbiBUdXJpc21vIDQiKSkgKyAgdGhlbWUocGFuZWwuZ3JpZC5tYWpvciA9IGVsZW1lbnRfbGluZShjb2xvdXIgPSAiZ3JheTkwIiksCiAgICBwYW5lbC5ncmlkLm1pbm9yID0gZWxlbWVudF9saW5lKGNvbG91ciA9ICJncmF5OTAiKSwKICAgIHBhbmVsLmJhY2tncm91bmQgPSBlbGVtZW50X3JlY3QoZmlsbCA9IE5BKSkgK2xhYnMoeCA9ICJWaWRlb2p1ZWdvcyIsIHkgPSAiQ2lmcmEgZGUgdmVudGFzLCBlbiBtaWxsb25lcyBkZSBldXJvcyIpICsgdGhlbWUoYXhpcy50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTgpLAogICAgYXhpcy50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNykpICsgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTksCiAgICBoanVzdCA9IDAuNSkpICtsYWJzKHRpdGxlID0gIlJlc3RvIGRlIHJlZ2lvbmVzIikKCgojIHBhcmEganVudGFyIGxvcyBncsOhZmljb3Mgbm8gcHVlZG8gdXNhciBmYWNlX3dyYXAgeWEgZWwgZGYgY2FtYmlhLCB1dGlsaXphbW9zIGVsIHBhcXVldGUgcGF0Y2h3b3JrCmdfdmlkZW9qdWVnb3MgPC0gKGJiKS8oY2MrZGQpLyhlZStmZikKCmdfdmlkZW9qdWVnb3MgKyBwbG90X2Fubm90YXRpb24oCiAgdGl0bGUgPSAiVG9wIDUganVlZ29zIG3DoXMgdmVuZGlkb3MgZW4gY2FkYSByZWdpw7NuIikgJiAgIHRoZW1lKHRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDIzKSkgCmBgYAoKCiMjIyBEZXNhcnJvbGxhZG9yYXMgCgpMYXMgZGVzYXJyb2xsYWRvcmFzIGhhY2UgcmVmZXJlbmNpYSBhIGxhcyBlbXByZXNhcyBlbmNhcmdhZGFzIGRlIGVsYWJvcmFyIGVsIHNvZnR3YXJlIGRlbCB2aWRlb2p1ZWdvLiBFeGlzdGUgdW5hIGRvbWluYW5jaWEgdG90YWwgZGUgbmludGVuZG8sIHNpZW5kbyBsYSBkZXNhcnJvbGxhZG9yYSBkZSA3IGRlIGxvcyA5IGp1ZWdvcyBxdWUgY29tcG9uZW4gZXN0YSBsaXN0YS4gTGFzIG90cm9zIGRvcyBkZXNhcnJvbGxhZG9yYXMgc2UgZW5jdWVudHJhbiBjb24gdW4ganVlZ28gY2FkYSB1bmEuCgpgYGB7ciwgZWNobz1UUlVFLCBldmFsPVRSVUV9CgojUGFyYSBwb2RlciBlbCBncsOhZmljYSBkZSBiYXJyYXMgYXBpbGFkbyBuZWNlc2l0byB1bmEgdGVyY2VyYSB2YXJpYWJsZSBxdWUgYWN0dWUgZGUgeCwgcG9yIGxvIHF1ZSBjcmVvIHVuYSB2YXJpYWJsZSBmYWxzYQoKbWFzX2V4aXRvc2FzX2Rlc2Fycm9sbGFkb3JhcyA8LSBtYXNfZXhpdG9zYXNfZGVzYXJyb2xsYWRvcmFzICU+JSAKICAgbXV0YXRlKHggPSAiRGVzYXJyb2xsYWRvcmEiKQoKCiBncmFmX2RlcyA8LSAgZ2dwbG90KG1hc19leGl0b3Nhc19kZXNhcnJvbGxhZG9yYXMsIGFlcyh4ID0geCwgeSA9IG5fZGVzYXJyb2xsYWRvcmFzLCBmaWxsID0gUHVibGlzaGVyKSkgKyBnZW9tX2JhcihzdGF0ID0gImlkZW50aXR5IiwgY29sb3IgPSAiYmxhY2siKSArCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gYygiI0RBREFFQiIsICIjOUU5QUM4IiwgIiM2QTUxQTMiKSkgKwogICAgc2NhbGVfeV9jb250aW51b3VzKGJyZWFrcyA9IHNlcSgwLDksMSkpICsgCiAgdGhlbWUocGFuZWwuZ3JpZC5tYWpvciA9IGVsZW1lbnRfbGluZShjb2xvdXIgPSAiZ3JheTkwIiksCiAgICBwYW5lbC5ncmlkLm1pbm9yID0gZWxlbWVudF9saW5lKGNvbG91ciA9ICJncmF5OTAiKSwKICAgIGF4aXMudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE4KSwKICAgIGF4aXMudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTgsIGNvbG91ciA9ICJibGFjayIpLAogICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTgsCiAgICAgICAgaGp1c3QgPSAwLjUpLCBwYW5lbC5iYWNrZ3JvdW5kID0gZWxlbWVudF9yZWN0KGZpbGwgPSBOQSkpICtsYWJzKHRpdGxlID0gIkRpc3RyaWJ1Y2nDs24gZGUgZGVzYXJyb2xsYWRvcmFzIGVuIGVsIFRvcCAzIHZpZGVvanVlZ29zIGRlIGNhZGEgcmVnacOzbiIsCiAgICB4ID0gTlVMTCwgeSA9ICJOw7ptZXJvICIsIGZpbGwgPSAiRGVzYXJyb2xsYWRvcmFzIikgKyB0aGVtZShwbG90LnN1YnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMSwKICAgIGhqdXN0ID0gMC41KSkgK2xhYnModGl0bGUgPSAiRGlzdHJpYnVjacOzbiBkZSBkZXNhcnJvbGxhZG9yYXMgIiwKICAgIHN1YnRpdGxlID0gIkVuIGVsIFRvcCAzIHZpZGVvanVlZ29zIGRlIGNhZGEgcmVnacOzbiIpCiAKICAKZ3JhZl9kZXMKYGBgCgoKIyMjIEfDqW5lcm9zCgpFbiBlbCBhcGFydGFkbyBkZSBsb3MgZ8OpbmVyb3MgZXhpc3RlIHVuYSBtb3lvciBob21vZ2VuZWlkYWQuIERlc3RhY2FuIGxvcyBnw6luZXJvcyBkZSAqcmFjaW5nKiB5ICpyb2xlLXBsYXlpbmcqIGNvbiBkb3MganVlZ29zIGNhZGEgdW5vLiBBIGVsIHJlc3RvIGRlIGfDqW5lcm9zIGxlcyBwZXJ0ZW5lY2UgdW4gdmRlb2p1ZWdvLiAKCmBgYHtyfQoKI2dlbmVyb3MgVG9wIDMKCm1hc19leGl0b3Nvc19nZW5lcm9zIDwtIG1hc19leGl0b3Nvc19nZW5lcm9zICU+JSAKICAgbXV0YXRlKHggPSAiR8OpbmVybyIpCgogZ3JhZl9nZW4gPC0gIGdncGxvdChtYXNfZXhpdG9zb3NfZ2VuZXJvcywgYWVzKHggPSB4LCB5ID0gbl9nZW5lcm9zLCBmaWxsID0gR2VucmUpKSArIGdlb21fYmFyKHN0YXQgPSAiaWRlbnRpdHkiLCBjb2xvciA9ICJibGFjayIpICsKICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBjKCIjOUUzRDIyIiwgIiNDQTU2MjEiLCAiI0VBN0UyRSIsICIjREZDRUJBIiwgIiNEMEQxQ0EiLCAiIzUwODJCMCIsICIjMkI1QzhBIikpICsKICAgIHNjYWxlX3lfY29udGludW91cyhicmVha3MgPSBzZXEoMCw5LDEpKSArIAogIHRoZW1lKHBhbmVsLmdyaWQubWFqb3IgPSBlbGVtZW50X2xpbmUoY29sb3VyID0gImdyYXk5MCIpLAogICAgcGFuZWwuZ3JpZC5taW5vciA9IGVsZW1lbnRfbGluZShjb2xvdXIgPSAiZ3JheTkwIiksCiAgICBheGlzLnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxOCksCiAgICBheGlzLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE4LCBjb2xvdXIgPSAiYmxhY2siKSwKICAgIHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE4LAogICAgICAgIGhqdXN0ID0gMC41KSwgcGFuZWwuYmFja2dyb3VuZCA9IGVsZW1lbnRfcmVjdChmaWxsID0gTkEpKSArbGFicyh0aXRsZSA9ICJEaXN0cmlidWNpw7NuIGRlIGfDqW5lcm9zIGVuIGVsIFRvcCAzIHZpZGVvanVlZ29zIGRlIGNhZGEgcmVnacOzbiIsCiAgICB4ID0gTlVMTCwgeSA9ICJOw7ptZXJvICIsIGZpbGwgPSAiR8OpbmVyb3MiKSArIHRoZW1lKHBsb3Quc3VidGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDExLAogICAgaGp1c3QgPSAwLjUpKSArbGFicyh0aXRsZSA9ICJEaXN0cmlidWNpw7NuIGRlIGfDqW5lcm9zICIsCiAgICBzdWJ0aXRsZSA9ICJFbiBlbCBUb3AgMyB2aWRlb2p1ZWdvcyBkZSBjYWRhIHJlZ2nDs24iKQogCiAgCmdyYWZfZ2VuCmBgYAoKCgojIyMgUGxhdGFmb3JtYXMKCkxvcyByZXN1bHRhZG9zIG9idGVuaWRvcyBwYXJhIGxhcyBwbGF0YWZvcm1hcyBlc3TDoW4gbWVub3MgcmVwYXJ0aWRvcyBxdWUgZW4gZWwgY2FzbyBkZSBsb3MgZ8OpbmVyb3MsIGNvbXBvbmllbmRvIGxhIGxpc3RhIDUgdmlkZW9jb25zb2xhcywgNCBkZSBlbGxhcyBjb24gMiB2aWRlb2p1ZWdvcyBjYWRhIHVuYS4KCmBgYHtyfQoKIyBwbGF0YWZvcm1hIHRvcCAzCgptYXNfZXhpdG9zb3NfcGxhdGFmb3JtYSA8LSBtYXNfZXhpdG9zb3NfcGxhdGFmb3JtYSAlPiUgCiAgIG11dGF0ZSh4ID0gIlBsYXRhZm9ybWEiKQoKIGdyYWZfcGxhdCA8LSAgZ2dwbG90KG1hc19leGl0b3Nvc19wbGF0YWZvcm1hLCBhZXMoeCA9IHgsIHkgPSBuX3BsYXRhZm9ybWFzLCBmaWxsID0gUGxhdGZvcm0pKSArIGdlb21fYmFyKHN0YXQgPSAiaWRlbnRpdHkiLCBjb2xvciA9ICJibGFjayIpICsKICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBjKCIjQTMxMjNBIiwgIiNFOTUxNEMiLCAiI0Q1Q0ZCQSIsICIjQTFDODkzIiwgIiM1OUEzNTkiKSkgKwogICAgc2NhbGVfeV9jb250aW51b3VzKGJyZWFrcyA9IHNlcSgwLDksMSkpICsgCiAgdGhlbWUocGFuZWwuZ3JpZC5tYWpvciA9IGVsZW1lbnRfbGluZShjb2xvdXIgPSAiZ3JheTkwIiksCiAgICBwYW5lbC5ncmlkLm1pbm9yID0gZWxlbWVudF9saW5lKGNvbG91ciA9ICJncmF5OTAiKSwKICAgIGF4aXMudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE4KSwKICAgIGF4aXMudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTgsIGNvbG91ciA9ICJibGFjayIpLAogICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTgsCiAgICAgICAgaGp1c3QgPSAwLjUpLCBwYW5lbC5iYWNrZ3JvdW5kID0gZWxlbWVudF9yZWN0KGZpbGwgPSBOQSkpICtsYWJzKHRpdGxlID0gIkRpc3RyaWJ1Y2nDs24gZGUgcGxhdGFmb3JtYXMgZW4gZWwgVG9wIDMgdmlkZW9qdWVnb3MgZGUgY2FkYSByZWdpw7NuIiwKICAgIHggPSBOVUxMLCB5ID0gIk7Dum1lcm8gIiwgZmlsbCA9ICJQbGF0YWZvcm1hIikgKyB0aGVtZShwbG90LnN1YnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMSwKICAgIGhqdXN0ID0gMC41KSkgK2xhYnModGl0bGUgPSAiRGlzdHJpYnVjacOzbiBkZSBwbGF0YWZvcm1hcyAiLAogICAgc3VidGl0bGUgPSAiRW4gZWwgVG9wIDMgdmlkZW9qdWVnb3MgZGUgY2FkYSByZWdpw7NuIikKIAogIApncmFmX3BsYXQKYGBgCgoKIyMgMy4zICBQcm9mdW5kaXphbmRvIGVuIGfDqW5lcm9zIHkgcGxhdGFmb3JtYXMgIHsudGFic2V0fQoKQSBjb250aW51YWNpw7NuLCBwdWVkZSBvYnNlcnZhcnNlIGEgcGFydGlyIGRlIGRvcyB0YWJsYXMgdW4gYW7DoWxpc2lzIG3DoXMgZGV0YWxsYWRvIGRlIGxhIGltcG9ydGFuY2lhIHF1ZSBoYW4gdGVuaWRvIGxvcyBkaXN0aW50b3MgZ8OpbmVyb3MgeSBsYXMgZGlzdGludGFzIHBsYXRhZm9ybWFzIGVuIGVsIG1lcmNhZG8gZGUgbG9zIHZpZGVvanVlZ29zLgoKIyMjIEfDqW5lcm9zCgpMb3MgZ8OpbmVyb3MgcXVlIG1lbm9yIGltcGFjdG8gaGFuIHRlbmlkbyBlbiBlbCBtdW5kbyBkZSBsb3MgdmlkZW9qdWVnb3MgaGFuIHNpZG8gKkFkdmVudHVyZSogeSAqU3RyYXRlZ3kqLCBjb24gY2lmcmFzIGJhamFzIGRlIHZlbnRhcyB5IGRlIHZpZGVvanVlZ29zIGxhbnphZG9zLCBwZXJvIHNvYnJlIHRvZG8gZWwgcmF0aW8gdmVudGFzL27Dum1lcm8gZGUgdmlkZW9qdWVnb3MsIGVzdGFuZG8gbXV5IHBvciBkZWJham8gZGUgbGFzIHNpZ3VpZW50ZXMgY2F0ZWdvcmlhcy4gRWwgZ8OpbmVybyBjb24gbWF5b3IgcHJvcG9yY2nDs24gdmVudGFzL27Dum1lcm8gZGUgdmlkZW9qdWVnb3MgZXMgKk1pc2MqLCBwb3IgbG8gcXVlIHB1ZWRlIGRlZHVjaXJzZSBxdWUgZ3JhbiBwYXJ0ZSBkZSBzdXMgdmlkZW9qdWVnb3MgaGFuIHRlbmlkbyB1bmEgYnVlbmEgYWNvZ2lkYS4gUG9yIMO6bHRpbW8sIGVsIGfDqW5lcm8gcXVlIG3DoXMgc2UgaGEgZGVzYXJyb2xsYWRvIGhhIHNpZG8gZWwgZGUgYWNjacOzbiwgY29uIG1heW9yIG7Dum1lcm8gZGUgdmVudGFzIHkgdmlkZW9qdWVnb3MgbGFuemFkb3MsIHBlcm8gc2kgYW5hbGl6YW1vcyBsYSBwcm9wb3JjacOzbiBlcyBlbCBzZXh0byBnw6luZXJvLgoKYGBge3J9CgojVGFibGEgZm9ybWFkYSBwb3IgbG9zIGfDqW5lcm9zCgp0YWJsYV9jYXRlZ29yaWFzIDwtIHZlbnRhc19jYXRlZ29yaWEgJT4lIGd0KHJvd25hbWVfY29sID0gIkfDqW5lcm8iKQogCiB0YWJsYV9jYXRlZ29yaWFzIDwtIHRhYmxhX2NhdGVnb3JpYXMgICU+JSB0YWJfaGVhZGVyKHRpdGxlID0gbWQoIioqUHJvcG9yY2nDs24gZGUgdmVudGFzIHBvciB2aWRlb2p1ZWdvIGxhbnphZG8gZGUgY2FkYSBnw6luZXJvKioiKSwKIHN1YnRpdGxlID0gbWQoIlZlbnRhcyBlbiBtaWxsb25lcyBkZSBldXJvcyIpKSAKIAogdGFibGFfY2F0ZWdvcmlhcyA8LSB0YWJsYV9jYXRlZ29yaWFzICU+JSAKICAgZGF0YV9jb2xvcigKICAgICBjb2x1bW5zID0gYyhWZW50YXNfZ8OpbmVybywgVmVudGFzX3Bvcl92aWRlb2p1ZWdvLCBOw7ptZXJvX2RlX3ZpZGVvanVlZ29zKSwKICAgIGNvbG9ycyA9IGJsdWVzOSkKCiB0YWJsYV9jYXRlZ29yaWFzIAoKYGBgCgoKIyMjIFBsYXRhZm9ybWFzCgpFbiByZWxhY2nDs24gYSBsYXMgcGxhdGFmb3JtYXMsIHRhbnRvIGxhIFdpaSBjb21vIGxhIFBTMSBzb24gbGFzIGNvbnNvbGFzIGNvbiBtw6FzIHZlbnRhcyBwb3IgdmlkZW9qdWVnbyBsYW56YWRvLiBTaW4gZW1iYXJnbywgbGEgcGxhdGFmb3JtYSBxdWUgbcOhcyBoYSBkYWRvIGRlIHPDrSBlcyBsYSBQUzIsIGNvbiAxMTYxIHZpZGVvanVlZ29zIHkgOTYyLDM2IG1pbGxvbmVzIGRlIHZlbnRhcy4gTGEgcGxhdGFmb3JtYSBjb24gcGVvcmVzIGRhdG9zIGVzIHNpbiBkdWRhIGxhIFBTVml0YSwgdmlkZW9jb25zb2xhIHF1ZSBmdWUgY3JpdGljYWRhIGRlc2RlIHN1IGxhbnphbWllbnRvLgoKYGBge3J9CgojVGFibGEgZm9ybWFkYSBwb3IgbGFzIHBsYXRhZm9ybWFzCiB0YWJsYV9wbGF0Zm9ybSA8LSB2ZW50YXNfcGxhdGZvcm0gJT4lIGd0KHJvd25hbWVfY29sID0gIlBsYXRhZm9ybWEiKQogCiB0YWJsYV9wbGF0Zm9ybSA8LSB0YWJsYV9wbGF0Zm9ybSAgJT4lIHRhYl9oZWFkZXIodGl0bGUgPSBtZCgiKipQcm9wb3JjacOzbiBkZSB2ZW50YXMgcG9yIHZpZGVvanVlZ28gbGFuemFkbyBkZSBjYWRhIHBsYXRhZm9ybWEqKiIpLAogc3VidGl0bGUgPSBtZCgiVmVudGFzIGVuIG1pbGxvbmVzIGRlIGV1cm9zIikpIAogCiB0YWJsYV9wbGF0Zm9ybSA8LSB0YWJsYV9wbGF0Zm9ybSAlPiUgCiAgIGRhdGFfY29sb3IoCiAgICAgY29sdW1ucyA9IGMoVmVudGFzX3BsYXRhZm9ybWEsIFZlbnRhc19wb3JfdmlkZW9qdWVnbywgTsO6bWVyb19kZV92aWRlb2p1ZWdvcyksCiAgICAgY29sb3JzID0gc2NhbGVzOjpjb2xfbnVtZXJpYygKICAgICAgcGFsZXR0ZSA9IHBhbGV0dGVlcjo6cGFsZXR0ZWVyX2QoCiAgICAgICAgcGFsZXR0ZSA9ICJnZ3NjaTo6cmVkX21hdGVyaWFsIgogICAgICAgICkgJT4lIGFzLmNoYXJhY3RlcigpLAogICAgICBkb21haW4gPSBOVUxMCiAgICAgICkKICApCgogdGFibGFfcGxhdGZvcm0KYGBgCgoKCiMjIDMuNCBYYm94T25lIHZzIFBzNCB7LnRhYnNldH0KCkxhIGNvbXBldGVuY2lhIGVudHJlIFhib3ggeSBQUyBlcyBtw6FzIHF1ZSBjb25vY2lkYS4gRW4gbG9zIMO6bHRpbW9zIGHDsW9zIGhhbiBzaWRvIGxhcyBkb3MgcGxhdGFmb3JtYXMgbMOtZGVyZXMsIGx1Y2hhbmRvIHBvciBoYWNlcnNlIGNvbiBsYSBtYXlvciBjdW90YSBkZSBtZXJjYWRvLCB2ZW5kaWVuZG8gcHJvZHVjdG9zIHNpbWlsYXJlcywgcGVybyBzaWVtcHJlIGNvbiB1bmEgaW1wb3J0YW50ZSBmaWRlbGl6YWNpw7NuIGRlbCBjbGllbnRlIGEgdHJhdsOpcyBkZSBsYSBtYXJjYS4gRGljaGEgcml2YWxpZGFkIHRhbWJpw6luIHNlIGRpw7MgY29uIGxhIHBlbsO6bHRpbWEgZ2VuZXJhY2nDs24gZGUgdmlkZW9jb25zb2xhcywgZXN0cmVuYW5kb3NlIGluY2x1c28gYW1iYXMgY29uc29sYXMgZWwgbWlzbW8gbWVzLCBjb24gcG9jb3MgZMOtYXMgZGUgZGlmZXJlbmNpYS4gIAoKQ29tbyBtdWVzdHJhbiBsb3Mgc2lndWllbnRlcyBncsOhZmljb3MsIGxhIGJhdGFsbGEgc2UgaGEgZGVjYW50YWRvIGRlbCBsYWRvIGRlIFBsYXlTdGF0aW9uLiBFbiBlbCBwcmltZXIgZ3LDoWZpY28sIGVuIHZhbG9yZXMgYWJzb2x1dG9zLCBsYXMgdmVudGFzIGRlIGxhIFBzNCBzaWVtcHJlIGhhbiBlc3RhZG8gcG9yIGVuY2ltYSBkZSBsYSBYYm94T25lLCBleGlzdGllbmRvIHVuYSBpbXBvcnRudGUgZGlmZXJlbmNpYSwgZXhjZXB0byBlbCBhw7FvIGRlIGVzdHJlbm8uIFBvciBvdHJvIGxhZG8sIGVuIHZhbG9yZXMgcmVsYXRpdm9zLCBsYSBkaWZlcmVuY2lhIHRhbWJpw6luIGVzIGNsYXJhLCBzaWVuZG8gUGxheVN0YXRpb24gbGEgY2xhcmEgZ2FuYWRvcmEgZGUgZXN0YSBnZW5lcmFjacOzbiBkZSB2aWRlb2NvbnNvbGFzLgoKIyMjIFZhbG9yZXMgYWJzb2x1dG9zCgpgYGB7cn0KZ3JhZl92ZW50YXNfZ2VuZXJhY2lvbmVzIDwtIGdncGxvdChqdWVnb3NfWGJveE9uZV9wczQsIGFlcyh4PVllYXIsIHk9VmVudGFzX3RvdGFsZXMsIGZpbGwgPSBQbGF0Zm9ybSkpICsgZ2VvbV9iYXIoc3RhdCA9ICJpZGVudGl0eSIpICsKICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBjKCJibGFjayIsImdyZWVuIikpICsgCiAgIHNjYWxlX3hfY29udGludW91cyhicmVha3MgPSBzZXEoMjAxMywyMDE4LDEpKSArIAogICAgc2NhbGVfeV9jb250aW51b3VzKGJyZWFrcyA9IHNlcSgwLDI0MCwyNSkpICArIHRoZW1lKHBhbmVsLmdyaWQubWFqb3IgPSBlbGVtZW50X2xpbmUoY29sb3VyID0gImdyYXk5MCIpLAogICAgcGFuZWwuZ3JpZC5taW5vciA9IGVsZW1lbnRfbGluZShjb2xvdXIgPSBOQSksCiAgICBheGlzLnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMyksCiAgICBheGlzLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEzLCBjb2xvdXIgPSAiYmxhY2siKSwKICAgIHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE2LAogICAgICAgIGhqdXN0ID0gMC41KSwgbGVnZW5kLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEzKSwKICAgIGxlZ2VuZC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTMpLAogICAgcGFuZWwuYmFja2dyb3VuZCA9IGVsZW1lbnRfcmVjdChmaWxsID0gTkEpLAogICAgbGVnZW5kLnBvc2l0aW9uID0gImJvdHRvbSIsIGxlZ2VuZC5kaXJlY3Rpb24gPSAiaG9yaXpvbnRhbCIpICtsYWJzKHRpdGxlID0gIlZlbnRhcyBnbG9iYWxlcyBkZSBQczQgeSBYYm94T25lIiwKICAgIHggPSAiQcOxbyIsIHkgPSAiQ2lmcmEgZGUgdmVudGFzLCBlbiBtaWxsb25lcyBkZSBldXJvcyIsCiAgICBmaWxsID0gIlBsYXRhZm9ybWEiKSArIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJyaWdodCIpCgoKCiBnZ3Bsb3RseShncmFmX3ZlbnRhc19nZW5lcmFjaW9uZXMpCgoKYGBgCgoKIyMjIFZhbG9yZXMgcmVsYXRpdm9zCgpgYGB7cn0KZ3JhZl92ZW50YXNfcG9yY2VudHVhbGVzIDwtIGdncGxvdCh2ZW50YXNfdG90YWxlc19wbGF0YWZvcm1hLCBhZXMoeCA9ICIiLCB5ID0gcG9yY2VudGFqZSwgZmlsbCA9IFBsYXRmb3JtKSkgKyAKICBnZW9tX2NvbChjb2xvciA9ICJ3aGl0ZSIpICsgCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gYygiYmxhY2siLCAiZ3JlZW4iKSkgKyAKICBnZW9tX2xhYmVsKGFlcyhsYWJlbCA9IHBvcmNlbnRhamUpLAogICAgICAgICAgICAgY29sb3IgPSAid2hpdGUiLAogICAgICAgICAgICAgcG9zaXRpb24gPSBwb3NpdGlvbl9zdGFjayh2anVzdCA9IDAuNSksCiAgICAgICAgICAgICBzaG93LmxlZ2VuZCA9IEZBTFNFKSArIHRoZW1lX3ZvaWQoKSArCiAgY29vcmRfcG9sYXIodGhldGEgPSAieSIpICArIHRoZW1lKHBsb3Quc3VidGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE1LAogICAgY29sb3VyID0gImJsYWNrIiwgaGp1c3QgPSAwLjUpLCBwYW5lbC5ncmlkLm1ham9yID0gZWxlbWVudF9saW5lKGNvbG91ciA9IE5BLAogICAgc2l6ZSA9IDApLCBheGlzLnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNSksCiAgICBheGlzLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE0LCBjb2xvdXIgPSAid2hpdGUiKSwKICAgIHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE2LAogICAgICAgIGhqdXN0ID0gMC41KSwgbGVnZW5kLnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMyksCiAgICBwYW5lbC5iYWNrZ3JvdW5kID0gZWxlbWVudF9yZWN0KGZpbGwgPSBOQSksCiAgICBsZWdlbmQucG9zaXRpb24gPSAibGVmdCIpICtsYWJzKHRpdGxlID0gIkRpc3RyaWJ1Y2nDs24gZGUgbGFzIHZlbnRhcyB0b3RhbGVzIiwKICAgIHggPSBOVUxMLCB5ID0gIlZlbnRhcyIsIGZpbGwgPSAiUGxhdGFmb3JtYSIsCiAgICBzdWJ0aXRsZSA9ICJlbnRyZSAyMDEzIHkgMjAxOCIpICsgdGhlbWUobGVnZW5kLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDExKSkKCmdyYWZfdmVudGFzX3BvcmNlbnR1YWxlcwpgYGAKCgoKIyAqKjQuIEJpYmxpb2dyYWZpYSoqCgpbV2ViIGRlbCBjdXJzb10oaHR0cHM6Ly9wZXJlenA0NC5naXRodWIuaW8vaW50cm8tZHMtMjEtMjItd2ViLykgcGFyYSBsYSBlbGFib3JhY2nDs24gZGVsIHRyYWJham8uICAKCltEYXRhc2V0XShodHRwczovL3d3dy5rYWdnbGUuY29tL3NpZHR3ci92aWRlb2dhbWVzLXNhbGVzLWRhdGFzZXQpIHV0aWxpemFkby4gIAoKCgoK