Fase 1 [Descripciones Multivariantes]

En la primera etapa del estudio, se llevarán a cabo cálculos, visualizaciones y un análisis detallado del conjunto de datos sobre videojuegos, que será descrito en la sección 1.2. Este proceso se abordará desde una perspectiva de estadística descriptiva multivariante, lo que permitirá no solo una visión general de los datos, sino también un análisis más enriquecido de las relaciones entre las diferentes variables involucradas, tales como género, plataforma, año de lanzamiento, ventas globales por región y puntuaciones de usuarios y críticos.

Este enfoque facilitará una comprensión más profunda de las relaciones entre las variables, ayudando a identificar patrones y tendencias relevantes en la industria de los videojuegos. Las visualizaciones jugarán un papel clave en la representación gráfica de estas relaciones, brindando una forma clara y accesible de explorar los datos y facilitar su comprensión. Todo esto se llevará a cabo utilizando las herramientas R y RStudio, que permitirán una ejecución eficiente y precisa de los cálculos y la creación de gráficos interactivos para una interpretación más completa de los resultados.

1.1. Objetivos

El objetivo de este proyecto es aplicar técnicas de análisis multivariado para gestionar el conjunto de datos aprobado, correspondiente a registros de videojuegos que incluyen información sobre títulos, géneros, plataformas, años de lanzamiento, ventas globales y puntuaciones de usuarios. El propósito es organizar y procesar eficazmente la información, desarrollando habilidades en la gestión y análisis de datos mediante la implementación de métodos estadísticos avanzados como análisis de componentes principales, correspondencias, conglomerados y regresión. Este trabajo se enmarca dentro del curso de Gestión de Datos, dictado por el Profesor Giancarlo Libreros Londoño en la Universidad del Valle.

1.2. Descripción de los datos

El conjunto de datos fue obtenido en su totalidad desde la plataforma Kaggle:(https://www.kaggle.com/datasets/isaacmenard/playstation-games-info-2152025).Kaggle, es una plataforma en línea especializada en ciencia de datos y aprendizaje automático, propiedad de Google LLC. Se destaca por facilitar la participación en competencias en las que empresas e instituciones publican conjuntos de datos y problemas reales, permitiendo a los usuarios desarrollar modelos predictivos y poner a prueba sus habilidades analíticas. Además, la plataforma proporciona herramientas como notebooks interactivos en Python y R, una amplia biblioteca de conjuntos de datos de libre acceso y una sección educativa denominada Kaggle Learn, dedicada a la formación en programación, análisis y visualización de datos. El conjunto de datos seleccionado, fue elaborado por Isaac Menard (https://www.kaggle.com/isaacmenard), que recopila información detallada sobre diversos videojuegos de PlayStation.

En el contexto del analisis de conjuntos de datos, este estudio se relaciona con las siguientes areas de la ingenieria industrial. En el area 2. Investigación de Operaciones y Análisis,(Operations research & analysis) devido a que los datos de ventas y calificaciones sirven para aplicar modelos matemáticos orientados a la toma de decisiones estratégicas en la industria del entretenimiento digital; en el area 3. Análisis Económico de la Ingeniería,(Enginnering economic analysis) porque se consideran aspectos financieros mediante variables como el precio de venta o el modelo de negocio; en el area 13. Diseño y Desarrollo de Productos(Desing & manufacturing engineering), porque el estudio de variables como el género y la plataforma permite identificar tendencias de innovación y evolución en los videojuegos, reflejando la influencia de las preferencias de los usuarios y los avances tecnológicos en su diseño y mejora continua.

El conjunto de datos está compuesto por 12 campos y 3,526 registros que recopilan información sobre videojuegos de la marca PlayStation. Incluye variables relacionadas con el título, desarrollador, plataforma, género, precio, ventas y calificaciones, lo que permite analizar aspectos técnicos, comerciales y de preferencia del consumidor dentro de la industria del entretenimiento digital. La lista siguiente presenta las variables del conjunto de datos en el mismo orden en que aparecen en el archivo original, indicando para cada una su tipo de variable y escala de medición, siguiendo la nomenclatura (tipo_de_variable::escala_de_medición [ordenamiento]):

  • nombre_juego (cualitativa::nominal): es la denominación oficial del videojuego registrada en la PlayStation Store. Esta variable identifica de manera única cada título y se presenta en formato de texto, respetando la ortografía y estilo original establecido por la distribuidora.

  • precio_mas_alto (cuantitativa::razón): indica el Valor monetario máximo alcanzado por el videojuego dentro de la PlayStation Store, expresado en euros (€).

  • lanzamiento (cuantitativa::intervalo): indica la fecha o año correspondiente al estreno oficial del videojuego en el mercado. Esta variable permite establecer comparaciones temporales y analizar tendencias de lanzamiento a lo largo del tiempo.

  • genero (cualitativa::nominal):es la clasificación temática o tipológica del videojuego según su dinámica y estilo de juego (acción, aventura, rol, deportes, entre otros). Facilita la segmentación y el análisis comparativo entre distintos tipos de experiencias interactivas.

  • empresa_creadora (cualitativa::nominal): registra el nombre de la compañía desarrolladora o distribuidora responsable de la producción del videojuego. Esta variable permite identificar el origen empresarial y analizar la participación de distintas marcas dentro del mercado de PlayStation.

  • plataforma (cualitativa::nominal): señala el sistema o consola de la línea PlayStation en la cual fue lanzado el videojuego (ps3, ps4 o ps5). Su inclusión posibilita el estudio de la compatibilidad, la evolución tecnológica y las diferencias generacionales entre consolas.

  • metacritic_score (cuantitativa::razón):representa la puntuacion promedio ponderado de las calificaciones otorgadas por críticos especializados en el videojuego, en una escala de 0 a 100.

  • metacritic_rating_count (cuantitativa::razón): muestra el número total de reseñas profesionales recopiladas por Metacritic. Refleja el nivel de cobertura mediática y el grado de atención recibida por parte de la prensa especializada.

  • metacritic_user_score (cuantitativa::razón): registra el promedio de las valoraciones emitidas por los usuarios en la plataforma Metacritic, expresado en una escala de 0 a 10. Este indicador representa la percepción y satisfacción general del público.

  • Metacritic_user_rating_count (Cuantitativa::razón): indica el número de valoraciones emitidas por los usuarios. Mide la participación y popularidad del juego.

  • playstation_score (cuantitativa::razón): muestra la valoracion promedio de las puntuaciones otorgadas por los usuarios en la PlayStation Store, en una escala de 0 a 5. Constituye una medida directa de la valoración interna dentro de la plataforma oficial de Sony.

  • playstation_rating_count (cuantitativa::razón): refleja la cantidad total de reseñas o calificaciones emitidas por los usuarios en la PlayStation Store. Indica el nivel de interacción, aceptación y visibilidad del videojuego dentro del entorno digital de la consola.

Estructura del conjunto de Datos Original

str(resenas_juegos_electronicos_Original)
## tibble [3,526 × 12] (S3: tbl_df/tbl/data.frame)
##  $ nombre_juego                : chr [1:3526] "Grand Theft Auto IV" "Red Dead Redemption 2" "Red Dead Online" "Grand Theft Auto 3" ...
##  $ precio_mas_alto             : chr [1:3526] "€24.99" "€59.99" "€69.99" "€9.99" ...
##  $ lanzamiento                 : chr [1:3526] "Feb 15, 2012" "Oct 26, 2018" "Oct 29, 2018" "Oct 4, 2012" ...
##  $ genero                      : chr [1:3526] "Action / Shooter / Racing" "Action / Adventure / Unique" "Action / Adventure" "--" ...
##  $ empresa_creadora            : chr [1:3526] "Rockstar" "Rockstar Games" "Rockstar Games" "Rockstar Games" ...
##  $ plataforma                  : chr [1:3526] "PS3" "PS4" "PS4" "PS3" ...
##  $ metacritic_score            : num [1:3526] 98 97 97 97 97 97 96 96 96 96 ...
##  $ metacritic_rating_count     : num [1:3526] 86 99 99 56 66 66 112 86 105 98 ...
##  $ metacritic_user_score       : num [1:3526] 8.3 8.9 8.9 8 8.5 8.5 9.2 8.3 8.9 8.9 ...
##  $ metacritic_user_rating_count: num [1:3526] 5541 31932 31932 2079 14322 ...
##  $ playstation_score           : chr [1:3526] "4.32" "4.74" "4.74" "4.59" ...
##  $ playstation_rating_count    : num [1:3526] 48904 379257 379346 1437 40895 ...

Conjunto de Datos Original

resenas_juegos_electronicos_Original
## # A tibble: 3,526 × 12
##    nombre_juego   precio_mas_alto lanzamiento genero empresa_creadora plataforma
##    <chr>          <chr>           <chr>       <chr>  <chr>            <chr>     
##  1 Grand Theft A… €24.99          Feb 15, 20… Actio… Rockstar         PS3       
##  2 Red Dead Rede… €59.99          Oct 26, 20… Actio… Rockstar Games   PS4       
##  3 Red Dead Onli… €69.99          Oct 29, 20… Actio… Rockstar Games   PS4       
##  4 Grand Theft A… €9.99           Oct 4, 2012 --     Rockstar Games   PS3       
##  5 Grand Theft A… €69.99          Sep 17, 20… Actio… Rockstar Games   PS3       
##  6 Grand Theft A… €69.99          Nov 18, 20… Actio… Rockstar Games   PS4       
##  7 Baldur's Gate… €69.99          Sep 6, 2023 Role … Larian Studios … PS5 / PS4 
##  8 ELDEN RING PS… €69.99          Feb 25, 20… Role … BANDAI NAMCO EN… PS5 / PS4 
##  9 Uncharted 2: … <NA>            Oct 15, 20… --     Sony Interactiv… PS3       
## 10 Mass Effect™ 2 €14.99          Jan 21, 20… Role … EA Swiss Sarl    PS3       
## # ℹ 3,516 more rows
## # ℹ 6 more variables: metacritic_score <dbl>, metacritic_rating_count <dbl>,
## #   metacritic_user_score <dbl>, metacritic_user_rating_count <dbl>,
## #   playstation_score <chr>, playstation_rating_count <dbl>

Estructura del conjunto de Datos ETL

str(resenas_de_juegos_electronicos_depurados)
## tibble [3,457 × 13] (S3: tbl_df/tbl/data.frame)
##  $ nombre_juego    : chr [1:3457] "Grand Theft Auto IV" "Red Dead Redemption 2" "Red Dead Online" "Grand Theft Auto 3" ...
##  $ alto            : num [1:3457] 24.99 59.99 69.99 9.99 69.99 ...
##  $ lanzamiento     : Date[1:3457], format: "2012-02-15" "2018-10-26" ...
##  $ genero          : chr [1:3457] "Action / Shooter / Racing" "Action / Adventure / Unique" "Action / Adventure" "Action/Adventure" ...
##  $ empresa_creadora: chr [1:3457] "Rockstar" "Rockstar Games" "Rockstar Games" "Rockstar Games" ...
##  $ plataforma      : chr [1:3457] "PS3" "PS4" "PS4" "PS3" ...
##  $ punt_criticos   : num [1:3457] 98 97 97 97 97 97 96 96 96 96 ...
##  $ n_criticos      : num [1:3457] 86 99 99 56 66 66 112 86 115 98 ...
##  $ punt_usuarios   : num [1:3457] 8.3 8.9 8.9 8 8.5 8.5 9.2 8.3 8.9 8.9 ...
##  $ n_usuarios      : num [1:3457] 5541 31932 31932 2179 14322 ...
##  $ calif_ps        : num [1:3457] 4.32 4.74 4.74 4.59 4.65 4.48 1 1 4.14 4.81 ...
##  $ n_ps            : num [1:3457] 48914 379257 379346 1437 41895 ...
##  $ part_publi      : num [1:3457] 2 2 2 1 2 2 2 2 2 1 ...

Conjunto de Datos Original Depurado

resenas_de_juegos_electronicos_depurados
## # A tibble: 3,457 × 13
##    nombre_juego              alto lanzamiento genero empresa_creadora plataforma
##    <chr>                    <dbl> <date>      <chr>  <chr>            <chr>     
##  1 Grand Theft Auto IV      25.0  2012-02-15  Actio… Rockstar         PS3       
##  2 Red Dead Redemption 2    60.0  2018-10-26  Actio… Rockstar Games   PS4       
##  3 Red Dead Online          70.0  2018-10-29  Actio… Rockstar Games   PS4       
##  4 Grand Theft Auto 3        9.99 2012-10-04  Actio… Rockstar Games   PS3       
##  5 Grand Theft Auto V       70.0  2013-09-17  Actio… Rockstar Games   PS3       
##  6 Grand Theft Auto V       70.0  2014-11-18  Actio… Rockstar Games   PS4       
##  7 Baldur's Gate 3          70.0  2023-09-06  Role … Larian Studios … PS5 / PS4 
##  8 ELDEN RING PS4 & PS5     70.0  2022-02-25  Role … BANDAI NAMCO EN… PS5 / PS4 
##  9 Uncharted 2: Among Thie… 40.0  2009-10-15  Actio… Sony Interactiv… PS3       
## 10 Mass Effect™ 2           65.0  2011-01-21  Actio… EA Swiss Sarl    PS3       
## # ℹ 3,447 more rows
## # ℹ 7 more variables: punt_criticos <dbl>, n_criticos <dbl>,
## #   punt_usuarios <dbl>, n_usuarios <dbl>, calif_ps <dbl>, n_ps <dbl>,
## #   part_publi <dbl>

1.3. Estimaciones multivariadas

El vector de medias y la matriz de varianzas-covarianzas son elementos fundamentales del análisis estadístico multivariado, pues permiten caracterizar el comportamiento central, la dispersión y las relaciones de dependencia entre las variables de un conjunto de datos. Estas herramientas facilitan la comprensión global de la estructura interna de la información analizada. El vector de medias resume el promedio o valor esperado de cada variable, representando el punto de equilibrio alrededor del cual se distribuyen los datos. Por otro lado, la matriz de varianzas-covarianzas proporciona una medida conjunta de la variabilidad y de las relaciones lineales entre las variables. En su diagonal principal se encuentran las varianzas, que reflejan la dispersión individual de cada variable, mientras que los elementos fuera de la diagonal expresan las covarianzas, es decir, el grado en que dos variables tienden a variar simultáneamente.

Vector de Medias y Boxplots

apply(resenas_de_juegos_electronicos_depurados[,-c(1,3,4,5,6)], 2, mean, na.rm = TRUE) 
##          alto punt_criticos    n_criticos punt_usuarios    n_usuarios 
##     29.802898     20.282904      9.257159      2.446138    270.295343 
##      calif_ps          n_ps    part_publi 
##      3.431490   5470.313856      1.015910
resenas_juegos_electronicos_reducido = resenas_de_juegos_electronicos_depurados[,-c(1,3,4,5,6)]
nombres_boxplots <- c("precio","punt_criticos","n_criticos", "punt_usuarios","n_usuarios","calif_ps","n_ps","part_publi")

par(mfrow = c(1, ncol(resenas_juegos_electronicos_reducido)))
invisible(lapply(1:ncol(resenas_juegos_electronicos_reducido), function(i) {
  boxplot(resenas_juegos_electronicos_reducido[[i]],
    main = nombres_boxplots[i],
    ylim = quantile(resenas_juegos_electronicos_reducido[[i]], c(0.05, 0.99), na.rm = TRUE),
    na.rm = TRUE)}))

Matriz de Varianzas-Covarianzas

round(cov(resenas_de_juegos_electronicos_depurados[,-c(1,3,4,5,6)]),2)
##                   alto punt_criticos n_criticos punt_usuarios  n_usuarios
## alto            323.88         27.20      64.35          2.74     5444.91
## punt_criticos    27.20       1126.42     506.25         85.13    18776.60
## n_criticos       64.35        506.25     415.05         41.61    21620.69
## punt_usuarios     2.74         85.13      41.61          7.38     1418.71
## n_usuarios     5444.91      18776.60   21620.69       1418.71 10194373.38
## calif_ps         -3.41         -0.21       0.67          0.12      104.52
## n_ps          89034.89      71242.60   99376.00       6083.61 27618456.67
## part_publi        0.30          1.10       0.95          0.09      178.11
##               calif_ps         n_ps part_publi
## alto             -3.41     89034.89       0.30
## punt_criticos    -0.21     71242.60       1.10
## n_criticos        0.67     99376.00       0.95
## punt_usuarios     0.12      6083.61       0.09
## n_usuarios      104.52  27618456.67     178.11
## calif_ps          2.39      5451.33       0.01
## n_ps           5451.33 715143353.92    1006.86
## part_publi        0.01      1006.86       0.02

Matriz de Correlaciones

round(cor(resenas_de_juegos_electronicos_depurados[,-c(1,3,4,5,6)]),3)
##                 alto punt_criticos n_criticos punt_usuarios n_usuarios calif_ps
## alto           1.000         0.045      0.176         0.056      0.095   -0.123
## punt_criticos  0.045         1.000      0.740         0.933      0.175   -0.004
## n_criticos     0.176         0.740      1.000         0.752      0.332    0.021
## punt_usuarios  0.056         0.933      0.752         1.000      0.164    0.030
## n_usuarios     0.095         0.175      0.332         0.164      1.000    0.021
## calif_ps      -0.123        -0.004      0.021         0.030      0.021    1.000
## n_ps           0.185         0.079      0.182         0.084      0.323    0.132
## part_publi     0.133         0.263      0.374         0.263      0.446    0.032
##                n_ps part_publi
## alto          0.185      0.133
## punt_criticos 0.079      0.263
## n_criticos    0.182      0.374
## punt_usuarios 0.084      0.263
## n_usuarios    0.323      0.446
## calif_ps      0.132      0.032
## n_ps          1.000      0.301
## part_publi    0.301      1.000

1.4. Gráficas multivariadas

El vector de medias y la matriz de varianzas-covarianzas son elementos fundamentales del análisis estadístico multivariado, pues permiten caracterizar el comportamiento central, la dispersión y las relaciones de dependencia entre las variables de un conjunto de datos. Estas herramientas facilitan la comprensión global de la estructura interna de la información analizada.

Diagrama Conjunto de Dispersión, Distribución y Correlaciones [SA]

ggpairs(resenas_de_juegos_electronicos_depurados[,-c(1,3,4,5,6)])  #ERROR

Diagrama de Estrellas

set.seed(120522)
resenas_de_juegos_electronicos_depurados_1_Muestreado = resenas_de_juegos_electronicos_depurados[sample(1:nrow(resenas_de_juegos_electronicos_depurados),23),-c(1,3,4,5,6,13)]
stars(resenas_de_juegos_electronicos_depurados_1_Muestreado, len = 1, cex = 0.4, key.loc = c(10, 2), draw.segments = TRUE)

Caras de Chernoff

set.seed(120522)
resenas_de_juegos_electronicos_depurados_1_Muestreado = resenas_de_juegos_electronicos_depurados [sample(1:nrow(resenas_de_juegos_electronicos_depurados),23),-c(1,3,4,5,6,13)]
faces(resenas_de_juegos_electronicos_depurados_1_Muestreado)

## effect of variables:
##  modified item       Var            
##  "height of face   " "alto"         
##  "width of face    " "punt_criticos"
##  "structure of face" "n_criticos"   
##  "height of mouth  " "punt_usuarios"
##  "width of mouth   " "n_usuarios"   
##  "smiling          " "calif_ps"     
##  "height of eyes   " "n_ps"         
##  "width of eyes    " "alto"         
##  "height of hair   " "punt_criticos"
##  "width of hair   "  "n_criticos"   
##  "style of hair   "  "punt_usuarios"
##  "height of nose  "  "n_usuarios"   
##  "width of nose   "  "calif_ps"     
##  "width of ear    "  "n_ps"         
##  "height of ear   "  "alto"

1.5. Normalidad multivariada

PNM Mardia

datos_limpios <- na.omit(resenas_de_juegos_electronicos_depurados[, -c(1,3,4,5,6,13)])
mvn(datos_limpios, mvn_test = "mardia")
## $multivariate_normality
##              Test   Statistic p.value     Method          MVN
## 1 Mardia Skewness 1394600.419  <0.001 asymptotic ✗ Not normal
## 2 Mardia Kurtosis    7583.488  <0.001 asymptotic ✗ Not normal
## 
## $univariate_normality
##               Test      Variable Statistic p.value    Normality
## 1 Anderson-Darling          alto   101.852  <0.001 ✗ Not normal
## 2 Anderson-Darling punt_criticos   758.520  <0.001 ✗ Not normal
## 3 Anderson-Darling    n_criticos   768.379  <0.001 ✗ Not normal
## 4 Anderson-Darling punt_usuarios   795.200  <0.001 ✗ Not normal
## 5 Anderson-Darling    n_usuarios  1172.159  <0.001 ✗ Not normal
## 6 Anderson-Darling      calif_ps   435.598  <0.001 ✗ Not normal
## 7 Anderson-Darling          n_ps   956.080  <0.001 ✗ Not normal
## 
## $descriptives
##        Variable    n     Mean   Std.Dev Median Min      Max  25th    75th
## 1          alto 3457   29.803    17.997  24.99   0    100.0 15.99   39.99
## 2 punt_criticos 3457   20.283    33.562   1.00   1     98.0  1.00   65.00
## 3    n_criticos 3457    9.257    20.373   1.00   1    145.0  1.00    4.00
## 4 punt_usuarios 3457    2.446     2.717   1.00   1      9.5  1.00    1.00
## 5    n_usuarios 3457  270.295  3192.863   1.00   1 165959.0  1.00    1.00
## 6      calif_ps 3457    3.431     1.546   4.22   1      5.0  1.00    4.56
## 7          n_ps 3457 5470.314 26742.164 127.00   1 854788.0  1.00 1577.00
##     Skew Kurtosis
## 1  1.015    3.594
## 2  1.208    2.557
## 3  3.063   12.726
## 4  1.419    3.155
## 5 41.801 2109.524
## 6 -0.845    1.887
## 7 14.849  354.212
## 
## $data
## # A tibble: 3,457 × 7
##     alto punt_criticos n_criticos punt_usuarios n_usuarios calif_ps   n_ps
##    <dbl>         <dbl>      <dbl>         <dbl>      <dbl>    <dbl>  <dbl>
##  1 25.0             98         86           8.3       5541     4.32  48914
##  2 60.0             97         99           8.9      31932     4.74 379257
##  3 70.0             97         99           8.9      31932     4.74 379346
##  4  9.99            97         56           8         2179     4.59   1437
##  5 70.0             97         66           8.5      14322     4.65  41895
##  6 70.0             97         66           8.5      14322     4.48 854788
##  7 70.0             96        112           9.2      19439     1         1
##  8 70.0             96         86           8.3      21997     1         1
##  9 40.0             96        115           8.9       7751     4.14      7
## 10 65.0             96         98           8.9       3162     4.81   4167
## # ℹ 3,447 more rows
## 
## $subset
## NULL
## 
## $outlierMethod
## [1] "none"
## 
## attr(,"class")
## [1] "mvn"

PNM Henze-Zirkler

mvn(resenas_de_juegos_electronicos_depurados[, -c(1, 3, 4, 5, 6, 13)], mvn_test = "hz")
## $multivariate_normality
##            Test Statistic p.value     Method          MVN
## 1 Henze-Zirkler   380.187  <0.001 asymptotic ✗ Not normal
## 
## $univariate_normality
##               Test      Variable Statistic p.value    Normality
## 1 Anderson-Darling          alto   101.852  <0.001 ✗ Not normal
## 2 Anderson-Darling punt_criticos   758.520  <0.001 ✗ Not normal
## 3 Anderson-Darling    n_criticos   768.379  <0.001 ✗ Not normal
## 4 Anderson-Darling punt_usuarios   795.200  <0.001 ✗ Not normal
## 5 Anderson-Darling    n_usuarios  1172.159  <0.001 ✗ Not normal
## 6 Anderson-Darling      calif_ps   435.598  <0.001 ✗ Not normal
## 7 Anderson-Darling          n_ps   956.080  <0.001 ✗ Not normal
## 
## $descriptives
##        Variable    n     Mean   Std.Dev Median Min      Max  25th    75th
## 1          alto 3457   29.803    17.997  24.99   0    100.0 15.99   39.99
## 2 punt_criticos 3457   20.283    33.562   1.00   1     98.0  1.00   65.00
## 3    n_criticos 3457    9.257    20.373   1.00   1    145.0  1.00    4.00
## 4 punt_usuarios 3457    2.446     2.717   1.00   1      9.5  1.00    1.00
## 5    n_usuarios 3457  270.295  3192.863   1.00   1 165959.0  1.00    1.00
## 6      calif_ps 3457    3.431     1.546   4.22   1      5.0  1.00    4.56
## 7          n_ps 3457 5470.314 26742.164 127.00   1 854788.0  1.00 1577.00
##     Skew Kurtosis
## 1  1.015    3.594
## 2  1.208    2.557
## 3  3.063   12.726
## 4  1.419    3.155
## 5 41.801 2109.524
## 6 -0.845    1.887
## 7 14.849  354.212
## 
## $data
## # A tibble: 3,457 × 7
##     alto punt_criticos n_criticos punt_usuarios n_usuarios calif_ps   n_ps
##    <dbl>         <dbl>      <dbl>         <dbl>      <dbl>    <dbl>  <dbl>
##  1 25.0             98         86           8.3       5541     4.32  48914
##  2 60.0             97         99           8.9      31932     4.74 379257
##  3 70.0             97         99           8.9      31932     4.74 379346
##  4  9.99            97         56           8         2179     4.59   1437
##  5 70.0             97         66           8.5      14322     4.65  41895
##  6 70.0             97         66           8.5      14322     4.48 854788
##  7 70.0             96        112           9.2      19439     1         1
##  8 70.0             96         86           8.3      21997     1         1
##  9 40.0             96        115           8.9       7751     4.14      7
## 10 65.0             96         98           8.9       3162     4.81   4167
## # ℹ 3,447 more rows
## 
## $subset
## NULL
## 
## $outlierMethod
## [1] "none"
## 
## attr(,"class")
## [1] "mvn"

PNM Doornik-Hansen

mvn(resenas_de_juegos_electronicos_depurados[, -c(1, 3, 4, 5, 6, 13)], mvn_test = "doornik_hansen")
## $multivariate_normality
##             Test Statistic df p.value     Method          MVN
## 1 Doornik-Hansen  88299.04 14  <0.001 asymptotic ✗ Not normal
## 
## $univariate_normality
##               Test      Variable Statistic p.value    Normality
## 1 Anderson-Darling          alto   101.852  <0.001 ✗ Not normal
## 2 Anderson-Darling punt_criticos   758.520  <0.001 ✗ Not normal
## 3 Anderson-Darling    n_criticos   768.379  <0.001 ✗ Not normal
## 4 Anderson-Darling punt_usuarios   795.200  <0.001 ✗ Not normal
## 5 Anderson-Darling    n_usuarios  1172.159  <0.001 ✗ Not normal
## 6 Anderson-Darling      calif_ps   435.598  <0.001 ✗ Not normal
## 7 Anderson-Darling          n_ps   956.080  <0.001 ✗ Not normal
## 
## $descriptives
##        Variable    n     Mean   Std.Dev Median Min      Max  25th    75th
## 1          alto 3457   29.803    17.997  24.99   0    100.0 15.99   39.99
## 2 punt_criticos 3457   20.283    33.562   1.00   1     98.0  1.00   65.00
## 3    n_criticos 3457    9.257    20.373   1.00   1    145.0  1.00    4.00
## 4 punt_usuarios 3457    2.446     2.717   1.00   1      9.5  1.00    1.00
## 5    n_usuarios 3457  270.295  3192.863   1.00   1 165959.0  1.00    1.00
## 6      calif_ps 3457    3.431     1.546   4.22   1      5.0  1.00    4.56
## 7          n_ps 3457 5470.314 26742.164 127.00   1 854788.0  1.00 1577.00
##     Skew Kurtosis
## 1  1.015    3.594
## 2  1.208    2.557
## 3  3.063   12.726
## 4  1.419    3.155
## 5 41.801 2109.524
## 6 -0.845    1.887
## 7 14.849  354.212
## 
## $data
## # A tibble: 3,457 × 7
##     alto punt_criticos n_criticos punt_usuarios n_usuarios calif_ps   n_ps
##    <dbl>         <dbl>      <dbl>         <dbl>      <dbl>    <dbl>  <dbl>
##  1 25.0             98         86           8.3       5541     4.32  48914
##  2 60.0             97         99           8.9      31932     4.74 379257
##  3 70.0             97         99           8.9      31932     4.74 379346
##  4  9.99            97         56           8         2179     4.59   1437
##  5 70.0             97         66           8.5      14322     4.65  41895
##  6 70.0             97         66           8.5      14322     4.48 854788
##  7 70.0             96        112           9.2      19439     1         1
##  8 70.0             96         86           8.3      21997     1         1
##  9 40.0             96        115           8.9       7751     4.14      7
## 10 65.0             96         98           8.9       3162     4.81   4167
## # ℹ 3,447 more rows
## 
## $subset
## NULL
## 
## $outlierMethod
## [1] "none"
## 
## attr(,"class")
## [1] "mvn"

PNM Royston

datos_limpios <- na.omit(resenas_de_juegos_electronicos_depurados[, -c(1,3,4,5,6,13)])
datos_royston <- datos_limpios[1:2000, ]
mvn(datos_royston, mvn_test = "royston")
## $multivariate_normality
##      Test Statistic p.value     Method          MVN
## 1 Royston  1451.886  <0.001 asymptotic ✗ Not normal
## 
## $univariate_normality
##               Test      Variable Statistic p.value    Normality
## 1 Anderson-Darling          alto    67.914  <0.001 ✗ Not normal
## 2 Anderson-Darling punt_criticos   473.579  <0.001 ✗ Not normal
## 3 Anderson-Darling    n_criticos   452.923  <0.001 ✗ Not normal
## 4 Anderson-Darling punt_usuarios   474.064  <0.001 ✗ Not normal
## 5 Anderson-Darling    n_usuarios   653.439  <0.001 ✗ Not normal
## 6 Anderson-Darling      calif_ps   276.139  <0.001 ✗ Not normal
## 7 Anderson-Darling          n_ps   532.648  <0.001 ✗ Not normal
## 
## $descriptives
##        Variable    n     Mean   Std.Dev Median Min      Max  25th    75th
## 1          alto 2000   29.982    18.737  24.99   0    100.0 14.99   39.99
## 2 punt_criticos 2000   20.656    35.627   1.00   1     98.0  1.00    1.00
## 3    n_criticos 2000   11.213    24.150   1.00   1    145.0  1.00    1.00
## 4 punt_usuarios 2000    2.532     2.881   1.00   1      9.2  1.00    1.00
## 5    n_usuarios 2000  432.748  4179.334   1.00   1 165959.0  1.00    1.00
## 6      calif_ps 2000    3.480     1.585   4.33   1      5.0  1.00    4.62
## 7          n_ps 2000 7372.048 33040.661 192.50   1 854788.0  1.00 2478.00
##     Skew Kurtosis
## 1  1.012    3.419
## 2  1.274    2.656
## 3  2.649    9.557
## 4  1.390    3.015
## 5 32.103 1237.580
## 6 -0.860    1.867
## 7 12.934  257.141
## 
## $data
## # A tibble: 2,000 × 7
##     alto punt_criticos n_criticos punt_usuarios n_usuarios calif_ps   n_ps
##    <dbl>         <dbl>      <dbl>         <dbl>      <dbl>    <dbl>  <dbl>
##  1 25.0             98         86           8.3       5541     4.32  48914
##  2 60.0             97         99           8.9      31932     4.74 379257
##  3 70.0             97         99           8.9      31932     4.74 379346
##  4  9.99            97         56           8         2179     4.59   1437
##  5 70.0             97         66           8.5      14322     4.65  41895
##  6 70.0             97         66           8.5      14322     4.48 854788
##  7 70.0             96        112           9.2      19439     1         1
##  8 70.0             96         86           8.3      21997     1         1
##  9 40.0             96        115           8.9       7751     4.14      7
## 10 65.0             96         98           8.9       3162     4.81   4167
## # ℹ 1,990 more rows
## 
## $subset
## NULL
## 
## $outlierMethod
## [1] "none"
## 
## attr(,"class")
## [1] "mvn"

Fase 2 [Componentes Principales]

El Análisis de Componentes Principales (ACP) tiene como finalidad transformar el conjunto original de variables numéricas en un nuevo conjunto de componentes que concentren la mayor parte de la información contenida en los datos. En el presente estudio, el ACP se aplica sobre un grupo de variables cuantitativas que describen el desempeño y la recepción de los videojuegos, tales como las puntuaciones otorgadas por críticos y usuarios, así como la cantidad de reseñas registradas en diferentes plataformas. Mediante este procedimiento estadístico, se busca reducir la complejidad del conjunto de datos, identificando las combinaciones lineales de variables que mejor explican la variabilidad total observada. De esta manera, el ACP facilita una interpretación más clara de las relaciones entre las distintas medidas de valoración, permitiendo representar la información en un espacio de menor dimensión sin perder la esencia del comportamiento general de los datos.

2.1. Objetivos

El Análisis de Componentes Principales (ACP) se desarrolla a través de distintas etapas que incluyen la construcción de nuevas variables, la reducción de la dimensionalidad del conjunto de datos, la identificación y eliminación de variables con baja relevancia, y la interpretación de los componentes obtenidos dentro del contexto del problema analizado.

Estimado lector, si desea profundizar en los fundamentos teóricos que respaldan este análisis, los detalles del conjunto de datos se encuentran expuestos en la Sección 1.2,mientras que los principios conceptuales sobre los que se apoya este estudio se desarrollan con detalle en la Fase 1.

2.2. Selección de Componentes

Matriz ACP

get_eigenvalue(PCA(resenas_de_juegos_electronicos_depurados[,-c(1,3,4,5,6,13)], ncp = 6, scale.unit = TRUE, graph = F))
##       eigenvalue variance.percent cumulative.variance.percent
## Dim.1 2.77152901       39.5932715                    39.59327
## Dim.2 1.32240928       18.8915611                    58.48483
## Dim.3 1.11579204       15.9398864                    74.42472
## Dim.4 0.83296582       11.8995117                    86.32423
## Dim.5 0.62387085        8.9124408                    95.23667
## Dim.6 0.26800312        3.8286160                    99.06529
## Dim.7 0.06542988        0.9347126                   100.00000

Matriz de Correlaciones

round(cor(resenas_de_juegos_electronicos_depurados[,-c(1,3,4,5,6,13)]),2)
##                alto punt_criticos n_criticos punt_usuarios n_usuarios calif_ps
## alto           1.00          0.05       0.18          0.06       0.09    -0.12
## punt_criticos  0.05          1.00       0.74          0.93       0.18     0.00
## n_criticos     0.18          0.74       1.00          0.75       0.33     0.02
## punt_usuarios  0.06          0.93       0.75          1.00       0.16     0.03
## n_usuarios     0.09          0.18       0.33          0.16       1.00     0.02
## calif_ps      -0.12          0.00       0.02          0.03       0.02     1.00
## n_ps           0.19          0.08       0.18          0.08       0.32     0.13
##               n_ps
## alto          0.19
## punt_criticos 0.08
## n_criticos    0.18
## punt_usuarios 0.08
## n_usuarios    0.32
## calif_ps      0.13
## n_ps          1.00

Valores y Vectores Propios

datos_pca <- na.omit(resenas_de_juegos_electronicos_depurados[, -c(1,3,4,5,6,13)])
princomp(datos_pca, cor = TRUE)$sdev^2
##     Comp.1     Comp.2     Comp.3     Comp.4     Comp.5     Comp.6     Comp.7 
## 2.77152901 1.32240928 1.11579204 0.83296582 0.62387085 0.26800312 0.06542988
princomp(datos_pca, cor = TRUE)$loadings[, 1:5]
##                   Comp.1      Comp.2      Comp.3      Comp.4      Comp.5
## alto          0.11355226  0.39449420  0.57950342  0.62092472  0.30503775
## punt_criticos 0.55113462 -0.24947457 -0.01224341  0.02890210 -0.09844092
## n_criticos    0.53914184 -0.01563553  0.02938968  0.01073137  0.09774200
## punt_usuarios 0.55332162 -0.24506391 -0.03146646  0.06898482 -0.08743601
## n_usuarios    0.24306278  0.51397406 -0.06492704 -0.60533932  0.51669779
## calif_ps      0.02173065  0.13431334 -0.79744248  0.49085473  0.32111922
## n_ps          0.16421340  0.66304341 -0.14846532  0.03700057 -0.71412089

Correlaciones Comparadas

par(mfrow=c(1,2))
corrplot::corrplot(cor(resenas_de_juegos_electronicos_depurados[,-c(1,3,4,5,6,13)]), method = "color", type = "upper", number.cex = 0.4)
resultado_pca <- princomp(datos_pca, cor = TRUE)
corrplot::corrplot(cor(datos_pca), method = "color", type = "upper", number.cex = 0.4)

corrplot::corrplot(cor(resultado_pca$scores), method = "color", type = "upper", number.cex = 0.4)

Gráfico de Cattell

fviz_eig(PCA(resenas_de_juegos_electronicos_depurados[,-c(1,3,4,5,6,13)], scale.unit = T, graph = F), addlabels = T, ylim=c(0,90), main = "")
## Warning in geom_bar(stat = "identity", fill = barfill, color = barcolor, :
## Ignoring empty aesthetic: `width`.

Gráfico de Cattell-Kaiser

scree(resenas_de_juegos_electronicos_depurados[,-c(1,3,4,5,6,13)],factors = FALSE, pc = TRUE, main ="")

2.3. Calidad de Representación

Círculo de Correlaciones

fviz_pca_var(PCA(resenas_de_juegos_electronicos_depurados[,-c(1,3,4,5,6,13)], scale.unit = T, graph = F),col.var="#3B83BD", repel = T, col.circle = "#CDCDCD", ggtheme = theme_bw())
## Warning: Using `size` aesthetic for lines was deprecated in ggplot2 3.4.0.
## ℹ Please use `linewidth` instead.
## ℹ The deprecated feature was likely used in the ggpubr package.
##   Please report the issue at <https://github.com/kassambara/ggpubr/issues>.
## This warning is displayed once every 8 hours.
## Call `lifecycle::last_lifecycle_warnings()` to see where this warning was
## generated.
## Warning: `aes_string()` was deprecated in ggplot2 3.0.0.
## ℹ Please use tidy evaluation idioms with `aes()`.
## ℹ See also `vignette("ggplot2-in-packages")` for more information.
## ℹ The deprecated feature was likely used in the factoextra package.
##   Please report the issue at <https://github.com/kassambara/factoextra/issues>.
## This warning is displayed once every 8 hours.
## Call `lifecycle::last_lifecycle_warnings()` to see where this warning was
## generated.

fviz_contrib(
  PCA(resenas_de_juegos_electronicos_depurados[,-c(1,3,4,5,6,13)], ncp = 6, scale.unit = TRUE, graph = FALSE),
  choice = "var",
  axes = 1, 
  top = 10
)

Matriz de Representación

(get_pca_var(PCA(resenas_de_juegos_electronicos_depurados[,-c(1,3,4,5,6,13)], ncp = 5, scale.unit = TRUE, graph = F)))$cos2
##                     Dim.1        Dim.2        Dim.3        Dim.4       Dim.5
## alto          0.035736414 0.2058008399 0.3747099919 3.211479e-01 0.058049952
## punt_criticos 0.841850201 0.0823035291 0.0001672585 6.958026e-04 0.006045692
## n_criticos    0.805611206 0.0003232891 0.0009637689 9.592625e-05 0.005960149
## punt_usuarios 0.848544659 0.0794190332 0.0011047883 3.964005e-03 0.004769527
## n_usuarios    0.163740585 0.3493399831 0.0047036441 3.052284e-01 0.166558921
## calif_ps      0.001308774 0.0238563614 0.7095483582 2.006934e-01 0.064332038
## n_ps          0.074737166 0.5813662436 0.0245942349 1.140365e-03 0.318154575

Calidad de Representación

fviz_pca_var(PCA(resenas_de_juegos_electronicos_depurados[,-c(1,3,4,5,6,13)], ncp = 5, scale.unit = TRUE, graph = F), col.var="cos2", gradient.cols=c("#00AFBB","#E7B800","#FC4E07"), repel = TRUE)

Coordenadas Individuales

head((PCA(resenas_de_juegos_electronicos_depurados[,-c(1,3,4,5,6,13)], ncp = 5, scale.unit = TRUE, graph = F))$ind$coord, n = 23L)
##        Dim.1       Dim.2       Dim.3       Dim.4       Dim.5
## 1   5.150071  0.73285400  0.94724318 -0.56722259  -0.2523484
## 2   9.864860 13.92062745  2.39554983 -3.75196976  -4.0770507
## 3   9.928512 14.14207054  2.07399092 -3.40677406  -3.9099061
## 4   3.640097 -1.23360693  1.27706999 -0.45157345   0.1419571
## 5   5.559100  2.99251765 -0.16132201 -0.59067556   2.0882738
## 6  10.549097 23.13547503  4.26458955  0.48022360 -19.6576221
## 7   6.983748  2.36929899 -2.23157903 -2.73688630   3.4782081
## 8   6.307049  2.88227475 -2.15246537 -3.25848143   3.7964336
## 9   5.967017  0.12758991  0.10906654 -0.56471987   1.7541407
## 10  5.360400  0.11128124 -0.39610930  1.37769007   1.3817204
## 11  5.138079  0.26925069 -0.57647960  1.40010389   1.5810868
## 12  5.289006  0.36018270 -2.29333562 -0.61508191   1.3206736
## 13  5.126060 -0.58329644  0.68118514 -0.07517554   1.0466558
## 14  4.615794 -0.19868033 -1.74099535 -0.98128092   0.7468456
## 15  6.417290  2.20077331 -0.54352333 -1.11511968   3.6238097
## 16  6.362353  2.03115567  0.04333922 -1.35144880   3.4949006
## 17  4.320887 -0.49511706 -2.15903441  0.03370713   0.3701613
## 18  5.266380 -0.01536507  0.74931298 -0.07425578   0.3874144
## 19  8.507616 12.93327327  2.86640457 -2.08083730  -7.1832280
## 20  6.096352  3.10701329 -0.26346761 -1.96969181   4.2415091
## 21  3.838701 -0.73105976 -1.79126743 -0.32378831   0.1007147
## 22  6.479805  0.07843400 -2.55817516 -0.02397096   1.2939537
## 23  2.469899 -1.26175152 -1.23584923 -0.65511883  -0.5961891

2.4. Contribuciones y Biplots

2.4, 2.8 y 2.9

Fase 3 [Correspondencias]

El análisis de correspondencias se emplea para estudiar la asociación entre variables categóricas, como puede ser género y plataforma, o género y región de ventas. Este enfoque permite visualizar en un plano reducido la relación entre categorías, facilitando la interpretación de cómo se vinculan los diferentes grupos dentro del dataset. Así, por ejemplo, se puede identificar si ciertos géneros son preferidos en determinadas plataformas o regiones, descubriendo patrones relevantes en el consumo de videojuegos.

3.1. Objetivos

En esta tercera fase del estudio se presentarán los cálculos, visualizaciones e interpretaciones correspondientes al análisis de las variables cualitativas del conjunto de datos previamente trabajado en la fase 1 y fase 2. El propósito de esta etapa es aplicar el Análisis de Correspondencias Simples y Múltiples (ACS y ACM), con el fin de explorar las relaciones entre categorías y representar gráficamente las asociaciones existentes.Para ello, se llevará a cabo la construcción de tablas de contingencia y tablas disyuntivas completas, así como la evaluación de la calidad de representación, las contribuciones y la interpretación de los ejes factoriales obtenidos.

3.2. Correspondencias Simples

3.3. Correspondencias Múltiples

Fase 4 [Conglomerados]

El análisis de conglomerados busca agrupar los videojuegos en subconjuntos homogéneos según sus características multivariantes, como puntuación, ventas, género y plataforma. Utilizando algoritmos como K-means o jerárquicos, se identifican grupos de títulos que comparten similitudes, lo cual ayuda a entender la segmentación del mercado, identificar nichos o establecer perfiles de videojuegos más exitosos. Los conglomerados pueden usarse para enfocar estrategias de desarrollo o mercadeo según los grupos detectados.

4.1. Objetivos

En esta cuarta etapa del estudio se llevarán a cabo cálculos, representaciones gráficas e interpretaciones empleando el conjunto de datos previamente procesado en las Fases (1, 2 y 3). El objetivo principal de esta etapa es aplicar el Análisis de Conglomerados, tanto en su modalidad jerárquica, a través de la construcción e interpretación de dendrogramas, como en su versión no jerárquica, mediante la aplicación del método de K-medias, con el propósito de identificar grupos homogéneos dentro del conjunto de observaciones.

4.2. Agrupación Jerárquica

4.3. Agrupación No-Jerárquica

Fase 5 [Regresiones]

El análisis de regresión se emplea para modelar las relaciones entre una variable dependiente y una o varias variables independientes dentro del conjunto de datos. En el contexto de videojuegos, es común intentar predecir las ventas en función de variables como el año de lanzamiento, la puntuación de usuarios, la plataforma, o el género. Se interpreta qué factores tienen más influencia sobre el éxito comercial del videojuego y cómo pueden usarse estos hallazgos para la toma de decisiones en la industria.

5.1. Objetivos

Este estudio tiene como propósito establecer la relación entre dos o más variables mediante la obtención de información sobre una de ellas, basada en el conocimiento de los valores de las otras. Las relaciones establecidas son de carácter no determinístico, es decir, se plantearán relaciones probabilísticas y se implementarán procedimientos para realizar inferencias sobre los modelos utilizados. Además, se obtendrán medidas cuantitativas que indiquen el grado de relación entre las variables. Los modelos considerados en este trabajo corresponden a casos específicos del modelo lineal generalizado: Regresión Lineal Simple, Regresión Lineal Múltiple* y Regresión Logística. Cada modelo será descrito teóricamente en su respectiva sección, y se aplicará a un conjunto de datos específico descrito en la sección 2.

5.2. Regresión Lineal Simple

5.3. Regresión Lineal Múltiple

5.4. Regresión Logística Simple

5.5. Ajuste de Varianza

6. Conclusiones

7. Bibliografía

LS0tDQp0aXRsZTogIioqVEZDX0dERF8yMDI1XzJfR1JVUE9fNioqIg0Kc3VidGl0bGU6ICJFc3R1ZGlvIGRlIEFuw6FsaXNpcyBNdWx0aXZhcmlhZG8gY29uIGJhc2UgZW4gdW4gY29uanVudG8gZGUgZGF0b3Mgc29icmUgcmVnaXN0cm9zIGRlIHZpZGVvanVlZ29zIHJlbGFjaW9uYWRvcyBhIFBsYXlTdGF0aW9uLiINCmF1dGhvcjogIlBvcjogSnVhbiBFc3RlYmFuIExvYWl6YSBHb256YWxleiAoanVhbi5lLmxvYWl6YUBjb3JyZW91bml2YWxsZS5lZHUuY28pDQpTdGVwaGFuaSBDb3JyZWEgTWVzYSAoc3RlcGhhbmkuY29ycmVhQGNvcnJlb3VuaXZhbGxlLmVkdS5jbykgTHVuYSBTb2ZpYSBCZXJtdWRleiAobHVuYS5iZXJtdWRlekBjb3JyZW91bml2YWxsZS5lZHUuY28pDQpKb2hhbiBDYXJkZW5hcyBUcnVqaWxsbyAoY2FyZGVuYXMuam9oYW5AY29ycmVvdW5pdmFsbGUuZWR1LmNvKSBKdWFuIE1hbnVlbCBIdXJ0YWRvIEZyYW5jbyAoanVhbi5odXJ0YWRvLmZyYW5jb0Bjb3JyZW91bml2YWxsZS5lZHUuY28pIg0KZGF0ZTogIlRyYWJham8gZWxhYm9yYWRvIGVuIGVsIHBlcmlvZG8gYWNhZMOpbWljbyBjb21wcmVuZGlkbyBlbnRyZSBhZ29zdG8geSBkaWNpZW1icmUgZGVsIGHDsW8gMjAyNSwgY29tbyBhY3RpdmlkYWQgZm9ybWF0aXZhIHkgZXZhbHVhdGl2YSBkZWwgY3Vyc28gR2VzdGnDs24gZGUgRGF0b3MgcGFyYSBpbmdlbmllcsOtYSBJbmR1c3RyaWFsLiINCm91dHB1dDoNCiAgaHRtbF9kb2N1bWVudDoNCiAgICB0b2M6IFRSVUUNCiAgICB0b2NfZmxvYXQ6IFRSVUUNCiAgICBjb2RlX2Rvd25sb2FkOiBUUlVFDQogICAgdGhlbWU6IGx1bWVuDQpiaWJsaW9ncmFwaHk6IGJpYmxpb2dyYWZpYV9NRS5iaWINCmNzbDogYXBhLmNzbA0KbGluay1jaXRhdGlvbnM6IHllcw0KLS0tDQo8IS0tIENvbmZpZ3VyYWNpw7NuIEdsb2JhbCBkZSBSIC0tPg0KYGBge3Igc2V0dXAsIGluY2x1ZGU9RkFMU0V9DQpsaWJyYXJ5KHJlYWR4bCkNCmxpYnJhcnkoY29ycnBsb3QpDQpsaWJyYXJ5KEdHYWxseSkNCmxpYnJhcnkoZ2dwbG90MikNCmxpYnJhcnkoYW5kcmV3cykNCmxpYnJhcnkodGNsdGspDQpsaWJyYXJ5KGFwbHBhY2spDQpsaWJyYXJ5KGdyYXBoaWNzKQ0KbGlicmFyeShNVk4pDQpsaWJyYXJ5KHJlc2hhcGUyKQ0KbGlicmFyeShGYWN0b01pbmVSKQ0KbGlicmFyeShmYWN0b2V4dHJhKQ0KbGlicmFyeShwc3ljaCkNCmxpYnJhcnkoRmFjdG9DbGFzcykNCmxpYnJhcnkoY2x1c3RlcikNCmxpYnJhcnkoZGVuZGV4dGVuZCkNCmxpYnJhcnkobWFncml0dHIpDQpsaWJyYXJ5KE5iQ2x1c3QpDQpsaWJyYXJ5KHN0YXJnYXplcikNCg0KbGlicmFyeShyZWFkeGwpDQoNCmtuaXRyOjpvcHRzX2NodW5rJHNldChlY2hvID0gVFJVRSkNCg0KcmVzZW5hc19qdWVnb3NfZWxlY3Ryb25pY29zX09yaWdpbmFsIDwtIHJlYWRfZXhjZWwoInJlc2VuYXNfanVlZ29zX2VsZWN0cm9uaWNvc19PcmlnaW5hbC54bHN4IikNCg0KbGlicmFyeShyZWFkeGwpDQpyZXNlbmFzX2RlX2p1ZWdvc19lbGVjdHJvbmljb3NfZGVwdXJhZG9zIDwtIHJlYWRfZXhjZWwoInJlc2VuYXNfZGVfanVlZ29zX2VsZWN0cm9uaWNvc19kZXB1cmFkb3MueGxzeCIpDQoNCnJlc2VuYXNfZGVfanVlZ29zX2VsZWN0cm9uaWNvc19kZXB1cmFkb3MkbGFuemFtaWVudG8gPC0gYXMuRGF0ZShyZXNlbmFzX2RlX2p1ZWdvc19lbGVjdHJvbmljb3NfZGVwdXJhZG9zJGxhbnphbWllbnRvLCBvcmlnaW4gPSAiMTg5OS0xMi0zMCIpDQoNCnJlc2VuYXNfZGVfanVlZ29zX2VsZWN0cm9uaWNvc19kZXB1cmFkb3MkYWx0byA8LSBhcy5udW1lcmljKGdzdWIoIiwiLCAiLiIsIHJlc2VuYXNfZGVfanVlZ29zX2VsZWN0cm9uaWNvc19kZXB1cmFkb3MkYWx0bykpDQpgYGANCg0KIyMgKipGYXNlIDEgW0Rlc2NyaXBjaW9uZXMgTXVsdGl2YXJpYW50ZXNdKioNCkVuIGxhIHByaW1lcmEgZXRhcGEgZGVsIGVzdHVkaW8sIHNlIGxsZXZhcsOhbiBhIGNhYm8gY8OhbGN1bG9zLCB2aXN1YWxpemFjaW9uZXMgeSB1biBhbsOhbGlzaXMgZGV0YWxsYWRvIGRlbCBjb25qdW50byBkZSBkYXRvcyBzb2JyZSB2aWRlb2p1ZWdvcywgcXVlIHNlcsOhIGRlc2NyaXRvIGVuIGxhIHNlY2Npw7NuIDEuMi4gRXN0ZSBwcm9jZXNvIHNlIGFib3JkYXLDoSBkZXNkZSB1bmEgcGVyc3BlY3RpdmEgZGUgZXN0YWTDrXN0aWNhIGRlc2NyaXB0aXZhIG11bHRpdmFyaWFudGUsIGxvIHF1ZSBwZXJtaXRpcsOhIG5vIHNvbG8gdW5hIHZpc2nDs24gZ2VuZXJhbCBkZSBsb3MgZGF0b3MsIHNpbm8gdGFtYmnDqW4gdW4gYW7DoWxpc2lzIG3DoXMgZW5yaXF1ZWNpZG8gZGUgbGFzIHJlbGFjaW9uZXMgZW50cmUgbGFzIGRpZmVyZW50ZXMgdmFyaWFibGVzIGludm9sdWNyYWRhcywgdGFsZXMgY29tbyBnw6luZXJvLCBwbGF0YWZvcm1hLCBhw7FvIGRlIGxhbnphbWllbnRvLCB2ZW50YXMgZ2xvYmFsZXMgcG9yIHJlZ2nDs24geSBwdW50dWFjaW9uZXMgZGUgdXN1YXJpb3MgeSBjcsOtdGljb3MuDQoNCkVzdGUgZW5mb3F1ZSBmYWNpbGl0YXLDoSB1bmEgY29tcHJlbnNpw7NuIG3DoXMgcHJvZnVuZGEgZGUgbGFzIHJlbGFjaW9uZXMgZW50cmUgbGFzIHZhcmlhYmxlcywgYXl1ZGFuZG8gYSBpZGVudGlmaWNhciBwYXRyb25lcyB5IHRlbmRlbmNpYXMgcmVsZXZhbnRlcyBlbiBsYSBpbmR1c3RyaWEgZGUgbG9zIHZpZGVvanVlZ29zLiBMYXMgdmlzdWFsaXphY2lvbmVzIGp1Z2Fyw6FuIHVuIHBhcGVsIGNsYXZlIGVuIGxhIHJlcHJlc2VudGFjacOzbiBncsOhZmljYSBkZSBlc3RhcyByZWxhY2lvbmVzLCBicmluZGFuZG8gdW5hIGZvcm1hIGNsYXJhIHkgYWNjZXNpYmxlIGRlIGV4cGxvcmFyIGxvcyBkYXRvcyB5IGZhY2lsaXRhciBzdSBjb21wcmVuc2nDs24uIFRvZG8gZXN0byBzZSBsbGV2YXLDoSBhIGNhYm8gdXRpbGl6YW5kbyBsYXMgaGVycmFtaWVudGFzIFIgeSBSU3R1ZGlvLCBxdWUgcGVybWl0aXLDoW4gdW5hIGVqZWN1Y2nDs24gZWZpY2llbnRlIHkgcHJlY2lzYSBkZSBsb3MgY8OhbGN1bG9zIHkgbGEgY3JlYWNpw7NuIGRlIGdyw6FmaWNvcyBpbnRlcmFjdGl2b3MgcGFyYSB1bmEgaW50ZXJwcmV0YWNpw7NuIG3DoXMgY29tcGxldGEgZGUgbG9zIHJlc3VsdGFkb3MuDQoNCiMjIyAxLjEuIE9iamV0aXZvcw0KRWwgb2JqZXRpdm8gZGUgZXN0ZSBwcm95ZWN0byBlcyBhcGxpY2FyIHTDqWNuaWNhcyBkZSBhbsOhbGlzaXMgbXVsdGl2YXJpYWRvIHBhcmEgZ2VzdGlvbmFyIGVsIGNvbmp1bnRvIGRlIGRhdG9zIGFwcm9iYWRvLCBjb3JyZXNwb25kaWVudGUgYSByZWdpc3Ryb3MgZGUgdmlkZW9qdWVnb3MgcXVlIGluY2x1eWVuIGluZm9ybWFjacOzbiBzb2JyZSB0w610dWxvcywgZ8OpbmVyb3MsIHBsYXRhZm9ybWFzLCBhw7FvcyBkZSBsYW56YW1pZW50bywgdmVudGFzIGdsb2JhbGVzIHkgcHVudHVhY2lvbmVzIGRlIHVzdWFyaW9zLiBFbCBwcm9ww7NzaXRvIGVzIG9yZ2FuaXphciB5IHByb2Nlc2FyIGVmaWNhem1lbnRlIGxhIGluZm9ybWFjacOzbiwgZGVzYXJyb2xsYW5kbyBoYWJpbGlkYWRlcyBlbiBsYSBnZXN0acOzbiB5IGFuw6FsaXNpcyBkZSBkYXRvcyBtZWRpYW50ZSBsYSBpbXBsZW1lbnRhY2nDs24gZGUgbcOpdG9kb3MgZXN0YWTDrXN0aWNvcyBhdmFuemFkb3MgY29tbyBhbsOhbGlzaXMgZGUgY29tcG9uZW50ZXMgcHJpbmNpcGFsZXMsIGNvcnJlc3BvbmRlbmNpYXMsIGNvbmdsb21lcmFkb3MgeSByZWdyZXNpw7NuLiBFc3RlIHRyYWJham8gc2UgZW5tYXJjYSBkZW50cm8gZGVsIGN1cnNvIGRlIEdlc3Rpw7NuIGRlIERhdG9zLCBkaWN0YWRvIHBvciBlbCBQcm9mZXNvciBHaWFuY2FybG8gTGlicmVyb3MgTG9uZG/DsW8gZW4gbGEgVW5pdmVyc2lkYWQgZGVsIFZhbGxlLg0KDQojIyMgMS4yLiBEZXNjcmlwY2nDs24gZGUgbG9zIGRhdG9zIHsudGFic2V0IC50YWJzZXQtcGlsbHN9DQpFbCBjb25qdW50byBkZSBkYXRvcyBmdWUgb2J0ZW5pZG8gZW4gc3UgdG90YWxpZGFkIGRlc2RlIGxhIHBsYXRhZm9ybWEgS2FnZ2xlOihodHRwczovL3d3dy5rYWdnbGUuY29tL2RhdGFzZXRzL2lzYWFjbWVuYXJkL3BsYXlzdGF0aW9uLWdhbWVzLWluZm8tMjE1MjAyNSkuS2FnZ2xlLCBlcyB1bmEgcGxhdGFmb3JtYSBlbiBsw61uZWEgZXNwZWNpYWxpemFkYSBlbiBjaWVuY2lhIGRlIGRhdG9zIHkgYXByZW5kaXphamUgYXV0b23DoXRpY28sIHByb3BpZWRhZCBkZSBHb29nbGUgTExDLiBTZSBkZXN0YWNhIHBvciBmYWNpbGl0YXIgbGEgcGFydGljaXBhY2nDs24gZW4gY29tcGV0ZW5jaWFzIGVuIGxhcyBxdWUgZW1wcmVzYXMgZSBpbnN0aXR1Y2lvbmVzIHB1YmxpY2FuIGNvbmp1bnRvcyBkZSBkYXRvcyB5IHByb2JsZW1hcyByZWFsZXMsIHBlcm1pdGllbmRvIGEgbG9zIHVzdWFyaW9zIGRlc2Fycm9sbGFyIG1vZGVsb3MgcHJlZGljdGl2b3MgeSBwb25lciBhIHBydWViYSBzdXMgaGFiaWxpZGFkZXMgYW5hbMOtdGljYXMuIEFkZW3DoXMsIGxhIHBsYXRhZm9ybWEgcHJvcG9yY2lvbmEgaGVycmFtaWVudGFzIGNvbW8gbm90ZWJvb2tzIGludGVyYWN0aXZvcyBlbiBQeXRob24geSBSLCB1bmEgYW1wbGlhIGJpYmxpb3RlY2EgZGUgY29uanVudG9zIGRlIGRhdG9zIGRlIGxpYnJlIGFjY2VzbyB5IHVuYSBzZWNjacOzbiBlZHVjYXRpdmEgZGVub21pbmFkYSBLYWdnbGUgTGVhcm4sIGRlZGljYWRhIGEgbGEgZm9ybWFjacOzbiBlbiBwcm9ncmFtYWNpw7NuLCBhbsOhbGlzaXMgeSB2aXN1YWxpemFjacOzbiBkZSBkYXRvcy4gRWwgY29uanVudG8gZGUgZGF0b3Mgc2VsZWNjaW9uYWRvLCBmdWUgZWxhYm9yYWRvIHBvciBJc2FhYyBNZW5hcmQgKGh0dHBzOi8vd3d3LmthZ2dsZS5jb20vaXNhYWNtZW5hcmQpLCBxdWUgcmVjb3BpbGEgaW5mb3JtYWNpw7NuIGRldGFsbGFkYSBzb2JyZSBkaXZlcnNvcyB2aWRlb2p1ZWdvcyBkZSBQbGF5U3RhdGlvbi4NCg0KRW4gZWwgY29udGV4dG8gZGVsIGFuYWxpc2lzIGRlIGNvbmp1bnRvcyBkZSBkYXRvcywgZXN0ZSBlc3R1ZGlvIHNlIHJlbGFjaW9uYSBjb24gbGFzIHNpZ3VpZW50ZXMgYXJlYXMgZGUgbGEgaW5nZW5pZXJpYSBpbmR1c3RyaWFsLiBFbiBlbCBhcmVhICAqKjIuIEludmVzdGlnYWNpw7NuIGRlIE9wZXJhY2lvbmVzIHkgQW7DoWxpc2lzLCoqKE9wZXJhdGlvbnMgcmVzZWFyY2ggJiBhbmFseXNpcykgZGV2aWRvIGEgcXVlIGxvcyBkYXRvcyBkZSB2ZW50YXMgeSBjYWxpZmljYWNpb25lcyBzaXJ2ZW4gcGFyYSBhcGxpY2FyIG1vZGVsb3MgbWF0ZW3DoXRpY29zIG9yaWVudGFkb3MgYSBsYSB0b21hIGRlIGRlY2lzaW9uZXMgZXN0cmF0w6lnaWNhcyBlbiBsYSBpbmR1c3RyaWEgZGVsIGVudHJldGVuaW1pZW50byBkaWdpdGFsOyBlbiBlbCBhcmVhICoqMy4gQW7DoWxpc2lzIEVjb27Ds21pY28gZGUgbGEgSW5nZW5pZXLDrWEsKiooRW5naW5uZXJpbmcgZWNvbm9taWMgYW5hbHlzaXMpIHBvcnF1ZSBzZSBjb25zaWRlcmFuIGFzcGVjdG9zIGZpbmFuY2llcm9zIG1lZGlhbnRlIHZhcmlhYmxlcyBjb21vIGVsIHByZWNpbyBkZSB2ZW50YSBvIGVsIG1vZGVsbyBkZSBuZWdvY2lvOyBlbiBlbCBhcmVhICoqMTMuIERpc2XDsW8geSBEZXNhcnJvbGxvIGRlIFByb2R1Y3RvcyoqKERlc2luZyAmIG1hbnVmYWN0dXJpbmcgZW5naW5lZXJpbmcpLCBwb3JxdWUgZWwgZXN0dWRpbyBkZSB2YXJpYWJsZXMgY29tbyBlbCBnw6luZXJvIHkgbGEgcGxhdGFmb3JtYSBwZXJtaXRlIGlkZW50aWZpY2FyIHRlbmRlbmNpYXMgZGUgaW5ub3ZhY2nDs24geSBldm9sdWNpw7NuIGVuIGxvcyB2aWRlb2p1ZWdvcywgcmVmbGVqYW5kbyBsYSBpbmZsdWVuY2lhIGRlIGxhcyBwcmVmZXJlbmNpYXMgZGUgbG9zIHVzdWFyaW9zIHkgbG9zIGF2YW5jZXMgdGVjbm9sw7NnaWNvcyBlbiBzdSBkaXNlw7FvIHkgbWVqb3JhIGNvbnRpbnVhLg0KDQpFbCBjb25qdW50byBkZSBkYXRvcyBlc3TDoSBjb21wdWVzdG8gcG9yIDEyIGNhbXBvcyB5IDMsNTI2IHJlZ2lzdHJvcyBxdWUgcmVjb3BpbGFuIGluZm9ybWFjacOzbiBzb2JyZSB2aWRlb2p1ZWdvcyBkZSBsYSBtYXJjYSBQbGF5U3RhdGlvbi4gSW5jbHV5ZSB2YXJpYWJsZXMgcmVsYWNpb25hZGFzIGNvbiBlbCB0w610dWxvLCBkZXNhcnJvbGxhZG9yLCBwbGF0YWZvcm1hLCBnw6luZXJvLCBwcmVjaW8sIHZlbnRhcyB5IGNhbGlmaWNhY2lvbmVzLCBsbyBxdWUgcGVybWl0ZSBhbmFsaXphciBhc3BlY3RvcyB0w6ljbmljb3MsIGNvbWVyY2lhbGVzIHkgZGUgcHJlZmVyZW5jaWEgZGVsIGNvbnN1bWlkb3IgZGVudHJvIGRlIGxhIGluZHVzdHJpYSBkZWwgZW50cmV0ZW5pbWllbnRvIGRpZ2l0YWwuIExhIGxpc3RhIHNpZ3VpZW50ZSBwcmVzZW50YSBsYXMgdmFyaWFibGVzIGRlbCBjb25qdW50byBkZSBkYXRvcyBlbiBlbCBtaXNtbyBvcmRlbiBlbiBxdWUgYXBhcmVjZW4gZW4gZWwgYXJjaGl2byBvcmlnaW5hbCwgaW5kaWNhbmRvIHBhcmEgY2FkYSB1bmEgc3UgdGlwbyBkZSB2YXJpYWJsZSB5IGVzY2FsYSBkZSBtZWRpY2nDs24sIHNpZ3VpZW5kbyBsYSBub21lbmNsYXR1cmEgKHRpcG9fZGVfdmFyaWFibGU6OmVzY2FsYV9kZV9tZWRpY2nDs24gW29yZGVuYW1pZW50b10pOg0KDQotICoqbm9tYnJlX2p1ZWdvKiogKGN1YWxpdGF0aXZhOjpub21pbmFsKTogZXMgbGEgZGVub21pbmFjacOzbiBvZmljaWFsIGRlbCB2aWRlb2p1ZWdvIHJlZ2lzdHJhZGEgZW4gbGEgUGxheVN0YXRpb24gU3RvcmUuIEVzdGEgdmFyaWFibGUgaWRlbnRpZmljYSBkZSBtYW5lcmEgw7puaWNhIGNhZGEgdMOtdHVsbyB5IHNlIHByZXNlbnRhIGVuIGZvcm1hdG8gZGUgdGV4dG8sIHJlc3BldGFuZG8gbGEgb3J0b2dyYWbDrWEgeSBlc3RpbG8gb3JpZ2luYWwgZXN0YWJsZWNpZG8gcG9yIGxhIGRpc3RyaWJ1aWRvcmEuDQoNCi0gKipwcmVjaW9fbWFzX2FsdG8qKiAoY3VhbnRpdGF0aXZhOjpyYXrDs24pOiBpbmRpY2EgZWwgVmFsb3IgbW9uZXRhcmlvIG3DoXhpbW8gYWxjYW56YWRvIHBvciBlbCB2aWRlb2p1ZWdvIGRlbnRybyBkZSBsYSBQbGF5U3RhdGlvbiBTdG9yZSwgZXhwcmVzYWRvIGVuIGV1cm9zICjigqwpLg0KDQotICoqbGFuemFtaWVudG8qKiAoY3VhbnRpdGF0aXZhOjppbnRlcnZhbG8pOiBpbmRpY2EgbGEgZmVjaGEgbyBhw7FvIGNvcnJlc3BvbmRpZW50ZSBhbCBlc3RyZW5vIG9maWNpYWwgZGVsIHZpZGVvanVlZ28gZW4gZWwgbWVyY2Fkby4gRXN0YSB2YXJpYWJsZSBwZXJtaXRlIGVzdGFibGVjZXIgY29tcGFyYWNpb25lcyB0ZW1wb3JhbGVzIHkgYW5hbGl6YXIgdGVuZGVuY2lhcyBkZSBsYW56YW1pZW50byBhIGxvIGxhcmdvIGRlbCB0aWVtcG8uDQoNCi0gKipnZW5lcm8qKiAoY3VhbGl0YXRpdmE6Om5vbWluYWwpOmVzIGxhIGNsYXNpZmljYWNpw7NuIHRlbcOhdGljYSBvIHRpcG9sw7NnaWNhIGRlbCB2aWRlb2p1ZWdvIHNlZ8O6biBzdSBkaW7DoW1pY2EgeSBlc3RpbG8gZGUganVlZ28gKGFjY2nDs24sIGF2ZW50dXJhLCByb2wsIGRlcG9ydGVzLCBlbnRyZSBvdHJvcykuIEZhY2lsaXRhIGxhIHNlZ21lbnRhY2nDs24geSBlbCBhbsOhbGlzaXMgY29tcGFyYXRpdm8gZW50cmUgZGlzdGludG9zIHRpcG9zIGRlIGV4cGVyaWVuY2lhcyBpbnRlcmFjdGl2YXMuIA0KDQotICoqZW1wcmVzYV9jcmVhZG9yYSoqIChjdWFsaXRhdGl2YTo6bm9taW5hbCk6IHJlZ2lzdHJhIGVsIG5vbWJyZSBkZSBsYSBjb21wYcOxw61hIGRlc2Fycm9sbGFkb3JhIG8gZGlzdHJpYnVpZG9yYSByZXNwb25zYWJsZSBkZSBsYSBwcm9kdWNjacOzbiBkZWwgdmlkZW9qdWVnby4gRXN0YSB2YXJpYWJsZSBwZXJtaXRlIGlkZW50aWZpY2FyIGVsIG9yaWdlbiBlbXByZXNhcmlhbCB5IGFuYWxpemFyIGxhIHBhcnRpY2lwYWNpw7NuIGRlIGRpc3RpbnRhcyBtYXJjYXMgZGVudHJvIGRlbCBtZXJjYWRvIGRlIFBsYXlTdGF0aW9uLiANCg0KLSAqKnBsYXRhZm9ybWEqKiAoY3VhbGl0YXRpdmE6Om5vbWluYWwpOiBzZcOxYWxhIGVsIHNpc3RlbWEgbyBjb25zb2xhIGRlIGxhIGzDrW5lYSBQbGF5U3RhdGlvbiBlbiBsYSBjdWFsIGZ1ZSBsYW56YWRvIGVsIHZpZGVvanVlZ28gKHBzMywgcHM0IG8gcHM1KS4gU3UgaW5jbHVzacOzbiBwb3NpYmlsaXRhIGVsIGVzdHVkaW8gZGUgbGEgY29tcGF0aWJpbGlkYWQsIGxhIGV2b2x1Y2nDs24gdGVjbm9sw7NnaWNhIHkgbGFzIGRpZmVyZW5jaWFzIGdlbmVyYWNpb25hbGVzIGVudHJlIGNvbnNvbGFzLg0KIA0KLSAqKm1ldGFjcml0aWNfc2NvcmUqKiAoY3VhbnRpdGF0aXZhOjpyYXrDs24pOnJlcHJlc2VudGEgbGEgcHVudHVhY2lvbiBwcm9tZWRpbyBwb25kZXJhZG8gZGUgbGFzIGNhbGlmaWNhY2lvbmVzIG90b3JnYWRhcyBwb3IgY3LDrXRpY29zIGVzcGVjaWFsaXphZG9zIGVuIGVsIHZpZGVvanVlZ28sIGVuIHVuYSBlc2NhbGEgZGUgMCBhIDEwMC4gDQoNCi0gKiptZXRhY3JpdGljX3JhdGluZ19jb3VudCoqIChjdWFudGl0YXRpdmE6OnJhesOzbik6IG11ZXN0cmEgZWwgbsO6bWVybyB0b3RhbCBkZSByZXNlw7FhcyBwcm9mZXNpb25hbGVzIHJlY29waWxhZGFzIHBvciBNZXRhY3JpdGljLiBSZWZsZWphIGVsIG5pdmVsIGRlIGNvYmVydHVyYSBtZWRpw6F0aWNhIHkgZWwgZ3JhZG8gZGUgYXRlbmNpw7NuIHJlY2liaWRhIHBvciBwYXJ0ZSBkZSBsYSBwcmVuc2EgZXNwZWNpYWxpemFkYS4gDQoNCi0gKiptZXRhY3JpdGljX3VzZXJfc2NvcmUqKiAoY3VhbnRpdGF0aXZhOjpyYXrDs24pOiByZWdpc3RyYSBlbCBwcm9tZWRpbyBkZSBsYXMgdmFsb3JhY2lvbmVzIGVtaXRpZGFzIHBvciBsb3MgdXN1YXJpb3MgZW4gbGEgcGxhdGFmb3JtYSBNZXRhY3JpdGljLCBleHByZXNhZG8gZW4gdW5hIGVzY2FsYSBkZSAwIGEgMTAuIEVzdGUgaW5kaWNhZG9yIHJlcHJlc2VudGEgbGEgcGVyY2VwY2nDs24geSBzYXRpc2ZhY2Npw7NuIGdlbmVyYWwgZGVsIHDDumJsaWNvLg0KDQotICoqTWV0YWNyaXRpY191c2VyX3JhdGluZ19jb3VudCoqIChDdWFudGl0YXRpdmE6OnJhesOzbik6IGluZGljYSBlbCBuw7ptZXJvIGRlIHZhbG9yYWNpb25lcyBlbWl0aWRhcyBwb3IgbG9zIHVzdWFyaW9zLiBNaWRlIGxhIHBhcnRpY2lwYWNpw7NuIHkgcG9wdWxhcmlkYWQgZGVsIGp1ZWdvLg0KDQotICoqcGxheXN0YXRpb25fc2NvcmUqKiAoY3VhbnRpdGF0aXZhOjpyYXrDs24pOiBtdWVzdHJhIGxhIHZhbG9yYWNpb24gcHJvbWVkaW8gZGUgbGFzIHB1bnR1YWNpb25lcyBvdG9yZ2FkYXMgcG9yIGxvcyB1c3VhcmlvcyBlbiBsYSBQbGF5U3RhdGlvbiBTdG9yZSwgZW4gdW5hIGVzY2FsYSBkZSAwIGEgNS4gQ29uc3RpdHV5ZSB1bmEgbWVkaWRhIGRpcmVjdGEgZGUgbGEgdmFsb3JhY2nDs24gaW50ZXJuYSBkZW50cm8gZGUgbGEgcGxhdGFmb3JtYSBvZmljaWFsIGRlIFNvbnkuDQoNCi0gKipwbGF5c3RhdGlvbl9yYXRpbmdfY291bnQqKiAoY3VhbnRpdGF0aXZhOjpyYXrDs24pOiByZWZsZWphIGxhIGNhbnRpZGFkIHRvdGFsIGRlIHJlc2XDsWFzIG8gY2FsaWZpY2FjaW9uZXMgZW1pdGlkYXMgcG9yIGxvcyB1c3VhcmlvcyBlbiBsYSBQbGF5U3RhdGlvbiBTdG9yZS4gSW5kaWNhIGVsIG5pdmVsIGRlIGludGVyYWNjacOzbiwgYWNlcHRhY2nDs24geSB2aXNpYmlsaWRhZCBkZWwgdmlkZW9qdWVnbyBkZW50cm8gZGVsIGVudG9ybm8gZGlnaXRhbCBkZSBsYSBjb25zb2xhLiANCg0KIyMjIyBFc3RydWN0dXJhIGRlbCBjb25qdW50byBkZSBEYXRvcyBPcmlnaW5hbA0KYGBge3IgRXN0cnVjdHVyYV9kZWxfY29uanVudG9fZGVfRGF0b3NfT3JpZ2luYWwsIGZpZy5hbGlnbiA9ICdjZW50ZXInfQ0Kc3RyKHJlc2VuYXNfanVlZ29zX2VsZWN0cm9uaWNvc19PcmlnaW5hbCkNCmBgYA0KDQojIyMjIENvbmp1bnRvIGRlIERhdG9zIE9yaWdpbmFsDQpgYGB7ciBDb25qdW50b19kZV9EYXRvc19PcmlnaW5hbCwgZmlnLmFsaWduID0gJ2NlbnRlcid9DQpyZXNlbmFzX2p1ZWdvc19lbGVjdHJvbmljb3NfT3JpZ2luYWwNCmBgYA0KIyMjIyBFc3RydWN0dXJhIGRlbCBjb25qdW50byBkZSBEYXRvcyBFVEwNCmBgYHtyIEVzdHJ1Y3R1cmFfZGVsX2Nvbmp1bnRvX2RlX0RhdG9zX0VUTCwgZmlnLmFsaWduID0gJ2NlbnRlcid9DQpzdHIocmVzZW5hc19kZV9qdWVnb3NfZWxlY3Ryb25pY29zX2RlcHVyYWRvcykNCmBgYA0KIyMjIyBDb25qdW50byBkZSBEYXRvcyBPcmlnaW5hbCBEZXB1cmFkbw0KYGBge3IgQ29uanVudG9fZGVfRGF0b3NfRGVwdXJhZG8sIGZpZy5hbGlnbiA9ICdjZW50ZXInfQ0KcmVzZW5hc19kZV9qdWVnb3NfZWxlY3Ryb25pY29zX2RlcHVyYWRvcw0KYGBgDQoNCiMjIyAxLjMuIEVzdGltYWNpb25lcyBtdWx0aXZhcmlhZGFzIHsudGFic2V0IC50YWJzZXQtcGlsbHN9DQpFbCB2ZWN0b3IgZGUgbWVkaWFzIHkgbGEgbWF0cml6IGRlIHZhcmlhbnphcy1jb3ZhcmlhbnphcyBzb24gZWxlbWVudG9zIGZ1bmRhbWVudGFsZXMgZGVsIGFuw6FsaXNpcyBlc3RhZMOtc3RpY28gbXVsdGl2YXJpYWRvLCBwdWVzIHBlcm1pdGVuIGNhcmFjdGVyaXphciBlbCBjb21wb3J0YW1pZW50byBjZW50cmFsLCBsYSBkaXNwZXJzacOzbiB5IGxhcyByZWxhY2lvbmVzIGRlIGRlcGVuZGVuY2lhIGVudHJlIGxhcyB2YXJpYWJsZXMgZGUgdW4gY29uanVudG8gZGUgZGF0b3MuIEVzdGFzIGhlcnJhbWllbnRhcyBmYWNpbGl0YW4gbGEgY29tcHJlbnNpw7NuIGdsb2JhbCBkZSBsYSBlc3RydWN0dXJhIGludGVybmEgZGUgbGEgaW5mb3JtYWNpw7NuIGFuYWxpemFkYS4gRWwgdmVjdG9yIGRlIG1lZGlhcyByZXN1bWUgZWwgcHJvbWVkaW8gbyB2YWxvciBlc3BlcmFkbyBkZSBjYWRhIHZhcmlhYmxlLCByZXByZXNlbnRhbmRvIGVsIHB1bnRvIGRlIGVxdWlsaWJyaW8gYWxyZWRlZG9yIGRlbCBjdWFsIHNlIGRpc3RyaWJ1eWVuIGxvcyBkYXRvcy4gUG9yIG90cm8gbGFkbywgbGEgbWF0cml6IGRlIHZhcmlhbnphcy1jb3ZhcmlhbnphcyBwcm9wb3JjaW9uYSB1bmEgbWVkaWRhIGNvbmp1bnRhIGRlIGxhIHZhcmlhYmlsaWRhZCB5IGRlIGxhcyByZWxhY2lvbmVzIGxpbmVhbGVzIGVudHJlIGxhcyB2YXJpYWJsZXMuIEVuIHN1IGRpYWdvbmFsIHByaW5jaXBhbCBzZSBlbmN1ZW50cmFuIGxhcyB2YXJpYW56YXMsIHF1ZSByZWZsZWphbiBsYSBkaXNwZXJzacOzbiBpbmRpdmlkdWFsIGRlIGNhZGEgdmFyaWFibGUsIG1pZW50cmFzIHF1ZSBsb3MgZWxlbWVudG9zIGZ1ZXJhIGRlIGxhIGRpYWdvbmFsIGV4cHJlc2FuIGxhcyBjb3ZhcmlhbnphcywgZXMgZGVjaXIsIGVsIGdyYWRvIGVuIHF1ZSBkb3MgdmFyaWFibGVzIHRpZW5kZW4gYSB2YXJpYXIgc2ltdWx0w6FuZWFtZW50ZS4NCg0KIyMjIyBWZWN0b3IgZGUgTWVkaWFzIHkgQm94cGxvdHMNCmBgYHtyIFZlY3Rvcl9kZV9NZWRpYXNfeV9Cb3hwbG90cywgZmlnLmFsaWduID0gJ2NlbnRlcid9DQphcHBseShyZXNlbmFzX2RlX2p1ZWdvc19lbGVjdHJvbmljb3NfZGVwdXJhZG9zWywtYygxLDMsNCw1LDYpXSwgMiwgbWVhbiwgbmEucm0gPSBUUlVFKSANCnJlc2VuYXNfanVlZ29zX2VsZWN0cm9uaWNvc19yZWR1Y2lkbyA9IHJlc2VuYXNfZGVfanVlZ29zX2VsZWN0cm9uaWNvc19kZXB1cmFkb3NbLC1jKDEsMyw0LDUsNildDQpub21icmVzX2JveHBsb3RzIDwtIGMoInByZWNpbyIsInB1bnRfY3JpdGljb3MiLCJuX2NyaXRpY29zIiwgInB1bnRfdXN1YXJpb3MiLCJuX3VzdWFyaW9zIiwiY2FsaWZfcHMiLCJuX3BzIiwicGFydF9wdWJsaSIpDQoNCnBhcihtZnJvdyA9IGMoMSwgbmNvbChyZXNlbmFzX2p1ZWdvc19lbGVjdHJvbmljb3NfcmVkdWNpZG8pKSkNCmludmlzaWJsZShsYXBwbHkoMTpuY29sKHJlc2VuYXNfanVlZ29zX2VsZWN0cm9uaWNvc19yZWR1Y2lkbyksIGZ1bmN0aW9uKGkpIHsNCiAgYm94cGxvdChyZXNlbmFzX2p1ZWdvc19lbGVjdHJvbmljb3NfcmVkdWNpZG9bW2ldXSwNCiAgICBtYWluID0gbm9tYnJlc19ib3hwbG90c1tpXSwNCiAgICB5bGltID0gcXVhbnRpbGUocmVzZW5hc19qdWVnb3NfZWxlY3Ryb25pY29zX3JlZHVjaWRvW1tpXV0sIGMoMC4wNSwgMC45OSksIG5hLnJtID0gVFJVRSksDQogICAgbmEucm0gPSBUUlVFKX0pKQ0KYGBgDQoNCiMjIyMgTWF0cml6IGRlIFZhcmlhbnphcy1Db3Zhcmlhbnphcw0KYGBge3IgbWF0cml6X2RlX1Zhcmlhbnphc19Db3ZhcmlhbnphcywgZmlnLmFsaWduID0gJ2NlbnRlcid9DQpyb3VuZChjb3YocmVzZW5hc19kZV9qdWVnb3NfZWxlY3Ryb25pY29zX2RlcHVyYWRvc1ssLWMoMSwzLDQsNSw2KV0pLDIpDQoNCmBgYA0KDQojIyMjIE1hdHJpeiBkZSBDb3JyZWxhY2lvbmVzDQpgYGB7ciBtYXRyaXpfZGVfQ29ycmVsYWNpb25lcywgZmlnLmFsaWduID0gJ2NlbnRlcid9DQpyb3VuZChjb3IocmVzZW5hc19kZV9qdWVnb3NfZWxlY3Ryb25pY29zX2RlcHVyYWRvc1ssLWMoMSwzLDQsNSw2KV0pLDMpDQpgYGANCg0KIyMjIDEuNC4gR3LDoWZpY2FzIG11bHRpdmFyaWFkYXMgey50YWJzZXQgLnRhYnNldC1waWxsc30NCkVsIHZlY3RvciBkZSBtZWRpYXMgeSBsYSBtYXRyaXogZGUgdmFyaWFuemFzLWNvdmFyaWFuemFzIHNvbiBlbGVtZW50b3MgZnVuZGFtZW50YWxlcyBkZWwgYW7DoWxpc2lzIGVzdGFkw61zdGljbyBtdWx0aXZhcmlhZG8sIHB1ZXMgcGVybWl0ZW4gY2FyYWN0ZXJpemFyIGVsIGNvbXBvcnRhbWllbnRvIGNlbnRyYWwsIGxhIGRpc3BlcnNpw7NuIHkgbGFzIHJlbGFjaW9uZXMgZGUgZGVwZW5kZW5jaWEgZW50cmUgbGFzIHZhcmlhYmxlcyBkZSB1biBjb25qdW50byBkZSBkYXRvcy4gRXN0YXMgaGVycmFtaWVudGFzIGZhY2lsaXRhbiBsYSBjb21wcmVuc2nDs24gZ2xvYmFsIGRlIGxhIGVzdHJ1Y3R1cmEgaW50ZXJuYSBkZSBsYSBpbmZvcm1hY2nDs24gYW5hbGl6YWRhLiANCg0KIyMjIyBEaWFncmFtYSBDb25qdW50byBkZSBEaXNwZXJzacOzbiwgRGlzdHJpYnVjacOzbiB5IENvcnJlbGFjaW9uZXMgW1NBXQ0KYGBge3IgRGlhZ3JhbWFfdmlkZW9qdWVnb3MsIGZpZy5hbGlnbiA9ICdjZW50ZXInfQ0KZ2dwYWlycyhyZXNlbmFzX2RlX2p1ZWdvc19lbGVjdHJvbmljb3NfZGVwdXJhZG9zWywtYygxLDMsNCw1LDYpXSkgICNFUlJPUg0KYGBgDQoNCiMjIyMgRGlhZ3JhbWEgZGUgRXN0cmVsbGFzDQpgYGB7ciBkaWFncmFtYV9kZV9Fc3RyZWxsYXMsIGZpZy5hbGlnbiA9ICdjZW50ZXInfQ0Kc2V0LnNlZWQoMTIwNTIyKQ0KcmVzZW5hc19kZV9qdWVnb3NfZWxlY3Ryb25pY29zX2RlcHVyYWRvc18xX011ZXN0cmVhZG8gPSByZXNlbmFzX2RlX2p1ZWdvc19lbGVjdHJvbmljb3NfZGVwdXJhZG9zW3NhbXBsZSgxOm5yb3cocmVzZW5hc19kZV9qdWVnb3NfZWxlY3Ryb25pY29zX2RlcHVyYWRvcyksMjMpLC1jKDEsMyw0LDUsNiwxMyldDQpzdGFycyhyZXNlbmFzX2RlX2p1ZWdvc19lbGVjdHJvbmljb3NfZGVwdXJhZG9zXzFfTXVlc3RyZWFkbywgbGVuID0gMSwgY2V4ID0gMC40LCBrZXkubG9jID0gYygxMCwgMiksIGRyYXcuc2VnbWVudHMgPSBUUlVFKQ0KYGBgDQoNCiMjIyMgQ2FyYXMgZGUgQ2hlcm5vZmYNCmBgYHtyIGNhcmFzX2RlX0NoZXJub2ZmLCBmaWcuYWxpZ24gPSAnY2VudGVyJ30NCnNldC5zZWVkKDEyMDUyMikNCnJlc2VuYXNfZGVfanVlZ29zX2VsZWN0cm9uaWNvc19kZXB1cmFkb3NfMV9NdWVzdHJlYWRvID0gcmVzZW5hc19kZV9qdWVnb3NfZWxlY3Ryb25pY29zX2RlcHVyYWRvcyBbc2FtcGxlKDE6bnJvdyhyZXNlbmFzX2RlX2p1ZWdvc19lbGVjdHJvbmljb3NfZGVwdXJhZG9zKSwyMyksLWMoMSwzLDQsNSw2LDEzKV0NCmZhY2VzKHJlc2VuYXNfZGVfanVlZ29zX2VsZWN0cm9uaWNvc19kZXB1cmFkb3NfMV9NdWVzdHJlYWRvKQ0KYGBgDQoNCg0KIyMjIDEuNS4gTm9ybWFsaWRhZCBtdWx0aXZhcmlhZGEgey50YWJzZXQgLnRhYnNldC1waWxsc30NCg0KIyMjIyBQTk0gTWFyZGlhDQpgYGB7ciBQTk1fTWFyZGlhLCBmaWcuYWxpZ24gPSAnY2VudGVyJ30NCmRhdG9zX2xpbXBpb3MgPC0gbmEub21pdChyZXNlbmFzX2RlX2p1ZWdvc19lbGVjdHJvbmljb3NfZGVwdXJhZG9zWywgLWMoMSwzLDQsNSw2LDEzKV0pDQptdm4oZGF0b3NfbGltcGlvcywgbXZuX3Rlc3QgPSAibWFyZGlhIikNCmBgYA0KDQojIyMjIFBOTSBIZW56ZS1aaXJrbGVyDQpgYGB7ciBQTk1fSGVuemVfWmlya2xlciwgZmlnLmFsaWduID0gJ2NlbnRlcid9DQptdm4ocmVzZW5hc19kZV9qdWVnb3NfZWxlY3Ryb25pY29zX2RlcHVyYWRvc1ssIC1jKDEsIDMsIDQsIDUsIDYsIDEzKV0sIG12bl90ZXN0ID0gImh6IikNCmBgYA0KDQojIyMjIFBOTSBEb29ybmlrLUhhbnNlbg0KYGBge3IgUE5NX0Rvb3JuaWtfSGFuc2VuLCBmaWcuYWxpZ24gPSAnY2VudGVyJ30NCm12bihyZXNlbmFzX2RlX2p1ZWdvc19lbGVjdHJvbmljb3NfZGVwdXJhZG9zWywgLWMoMSwgMywgNCwgNSwgNiwgMTMpXSwgbXZuX3Rlc3QgPSAiZG9vcm5pa19oYW5zZW4iKQ0KYGBgDQoNCiMjIyMgUE5NIFJveXN0b24NCmBgYHtyIFBOTV9Sb3lzdG9uLCBmaWcuYWxpZ24gPSAnY2VudGVyJ30NCmRhdG9zX2xpbXBpb3MgPC0gbmEub21pdChyZXNlbmFzX2RlX2p1ZWdvc19lbGVjdHJvbmljb3NfZGVwdXJhZG9zWywgLWMoMSwzLDQsNSw2LDEzKV0pDQpkYXRvc19yb3lzdG9uIDwtIGRhdG9zX2xpbXBpb3NbMToyMDAwLCBdDQptdm4oZGF0b3Nfcm95c3RvbiwgbXZuX3Rlc3QgPSAicm95c3RvbiIpDQpgYGANCg0KDQojIyAqKkZhc2UgMiBbQ29tcG9uZW50ZXMgUHJpbmNpcGFsZXNdKiogDQoNCipFbCBBbsOhbGlzaXMgZGUgQ29tcG9uZW50ZXMgUHJpbmNpcGFsZXMgKEFDUCkqIHRpZW5lIGNvbW8gZmluYWxpZGFkIHRyYW5zZm9ybWFyIGVsIGNvbmp1bnRvIG9yaWdpbmFsIGRlIHZhcmlhYmxlcyBudW3DqXJpY2FzIGVuIHVuIG51ZXZvIGNvbmp1bnRvIGRlIGNvbXBvbmVudGVzIHF1ZSBjb25jZW50cmVuIGxhIG1heW9yIHBhcnRlIGRlIGxhIGluZm9ybWFjacOzbiBjb250ZW5pZGEgZW4gbG9zIGRhdG9zLiBFbiBlbCBwcmVzZW50ZSBlc3R1ZGlvLCBlbCBBQ1Agc2UgYXBsaWNhIHNvYnJlIHVuIGdydXBvIGRlIHZhcmlhYmxlcyBjdWFudGl0YXRpdmFzIHF1ZSBkZXNjcmliZW4gZWwgZGVzZW1wZcOxbyB5IGxhIHJlY2VwY2nDs24gZGUgbG9zIHZpZGVvanVlZ29zLCB0YWxlcyBjb21vIGxhcyBwdW50dWFjaW9uZXMgb3RvcmdhZGFzIHBvciBjcsOtdGljb3MgeSB1c3VhcmlvcywgYXPDrSBjb21vIGxhIGNhbnRpZGFkIGRlIHJlc2XDsWFzIHJlZ2lzdHJhZGFzIGVuIGRpZmVyZW50ZXMgcGxhdGFmb3JtYXMuIE1lZGlhbnRlIGVzdGUgcHJvY2VkaW1pZW50byBlc3RhZMOtc3RpY28sIHNlIGJ1c2NhIHJlZHVjaXIgbGEgY29tcGxlamlkYWQgZGVsIGNvbmp1bnRvIGRlIGRhdG9zLCBpZGVudGlmaWNhbmRvIGxhcyBjb21iaW5hY2lvbmVzIGxpbmVhbGVzIGRlIHZhcmlhYmxlcyBxdWUgbWVqb3IgZXhwbGljYW4gbGEgdmFyaWFiaWxpZGFkIHRvdGFsIG9ic2VydmFkYS4gRGUgZXN0YSBtYW5lcmEsIGVsIEFDUCBmYWNpbGl0YSB1bmEgaW50ZXJwcmV0YWNpw7NuIG3DoXMgY2xhcmEgZGUgbGFzIHJlbGFjaW9uZXMgZW50cmUgbGFzIGRpc3RpbnRhcyBtZWRpZGFzIGRlIHZhbG9yYWNpw7NuLCBwZXJtaXRpZW5kbyByZXByZXNlbnRhciBsYSBpbmZvcm1hY2nDs24gZW4gdW4gZXNwYWNpbyBkZSBtZW5vciBkaW1lbnNpw7NuIHNpbiBwZXJkZXIgbGEgZXNlbmNpYSBkZWwgY29tcG9ydGFtaWVudG8gZ2VuZXJhbCBkZSBsb3MgZGF0b3MuDQoNCiMjIyAyLjEuIE9iamV0aXZvcw0KRWwgQW7DoWxpc2lzIGRlIENvbXBvbmVudGVzIFByaW5jaXBhbGVzIChBQ1ApIHNlIGRlc2Fycm9sbGEgYSB0cmF2w6lzIGRlIGRpc3RpbnRhcyBldGFwYXMgcXVlIGluY2x1eWVuIGxhIGNvbnN0cnVjY2nDs24gZGUgbnVldmFzIHZhcmlhYmxlcywgbGEgcmVkdWNjacOzbiBkZSBsYSBkaW1lbnNpb25hbGlkYWQgZGVsIGNvbmp1bnRvIGRlIGRhdG9zLCBsYSBpZGVudGlmaWNhY2nDs24geSBlbGltaW5hY2nDs24gZGUgdmFyaWFibGVzIGNvbiBiYWphIHJlbGV2YW5jaWEsIHkgbGEgaW50ZXJwcmV0YWNpw7NuIGRlIGxvcyBjb21wb25lbnRlcyBvYnRlbmlkb3MgZGVudHJvIGRlbCBjb250ZXh0byBkZWwgcHJvYmxlbWEgYW5hbGl6YWRvLg0KDQpFc3RpbWFkbyBsZWN0b3IsIHNpIGRlc2VhIHByb2Z1bmRpemFyIGVuIGxvcyBmdW5kYW1lbnRvcyB0ZcOzcmljb3MgcXVlIHJlc3BhbGRhbiBlc3RlIGFuw6FsaXNpcywgbG9zIGRldGFsbGVzIGRlbCBjb25qdW50byBkZSBkYXRvcyBzZSBlbmN1ZW50cmFuIGV4cHVlc3RvcyBlbiBsYSBbU2VjY2nDs24gMS4yXSgjc2VjMS4yKSxtaWVudHJhcyBxdWUgbG9zIHByaW5jaXBpb3MgY29uY2VwdHVhbGVzIHNvYnJlIGxvcyBxdWUgc2UgYXBveWEgZXN0ZSBlc3R1ZGlvIHNlIGRlc2Fycm9sbGFuIGNvbiBkZXRhbGxlIGVuIGxhIFtGYXNlIDFdKCNzZWMxKS4NCg0KIyMjIDIuMi4gU2VsZWNjacOzbiBkZSBDb21wb25lbnRlcyB7LnRhYnNldCAudGFic2V0LXBpbGxzfQ0KDQojIyMjIE1hdHJpeiBBQ1ANCmBgYHtyIE1hdHJpel9BQ1AsIGZpZy5hbGlnbiA9ICdjZW50ZXInfQ0KZ2V0X2VpZ2VudmFsdWUoUENBKHJlc2VuYXNfZGVfanVlZ29zX2VsZWN0cm9uaWNvc19kZXB1cmFkb3NbLC1jKDEsMyw0LDUsNiwxMyldLCBuY3AgPSA2LCBzY2FsZS51bml0ID0gVFJVRSwgZ3JhcGggPSBGKSkNCmBgYA0KDQojIyMjIE1hdHJpeiBkZSBDb3JyZWxhY2lvbmVzDQpgYGB7ciBNYXRyaXpfZGVfQ29ycmVsYWNpb25lc30NCnJvdW5kKGNvcihyZXNlbmFzX2RlX2p1ZWdvc19lbGVjdHJvbmljb3NfZGVwdXJhZG9zWywtYygxLDMsNCw1LDYsMTMpXSksMikNCmBgYA0KDQojIyMjIFZhbG9yZXMgeSBWZWN0b3JlcyBQcm9waW9zDQpgYGB7ciBWYWxvcmVzX3lfVmVjdG9yZXNfUHJvcGlvcywgZmlnLmFsaWduID0gJ2NlbnRlcid9DQpkYXRvc19wY2EgPC0gbmEub21pdChyZXNlbmFzX2RlX2p1ZWdvc19lbGVjdHJvbmljb3NfZGVwdXJhZG9zWywgLWMoMSwzLDQsNSw2LDEzKV0pDQpwcmluY29tcChkYXRvc19wY2EsIGNvciA9IFRSVUUpJHNkZXZeMg0KcHJpbmNvbXAoZGF0b3NfcGNhLCBjb3IgPSBUUlVFKSRsb2FkaW5nc1ssIDE6NV0NCmBgYA0KDQojIyMjIENvcnJlbGFjaW9uZXMgQ29tcGFyYWRhcw0KYGBge3IgQ29ycmVsYWNpb25lc19Db21wYXJhZGFzLCBmaWcuYWxpZ249J2NlbnRlcid9DQpwYXIobWZyb3c9YygxLDIpKQ0KY29ycnBsb3Q6OmNvcnJwbG90KGNvcihyZXNlbmFzX2RlX2p1ZWdvc19lbGVjdHJvbmljb3NfZGVwdXJhZG9zWywtYygxLDMsNCw1LDYsMTMpXSksIG1ldGhvZCA9ICJjb2xvciIsIHR5cGUgPSAidXBwZXIiLCBudW1iZXIuY2V4ID0gMC40KQ0KcmVzdWx0YWRvX3BjYSA8LSBwcmluY29tcChkYXRvc19wY2EsIGNvciA9IFRSVUUpDQpjb3JycGxvdDo6Y29ycnBsb3QoY29yKGRhdG9zX3BjYSksIG1ldGhvZCA9ICJjb2xvciIsIHR5cGUgPSAidXBwZXIiLCBudW1iZXIuY2V4ID0gMC40KQ0KY29ycnBsb3Q6OmNvcnJwbG90KGNvcihyZXN1bHRhZG9fcGNhJHNjb3JlcyksIG1ldGhvZCA9ICJjb2xvciIsIHR5cGUgPSAidXBwZXIiLCBudW1iZXIuY2V4ID0gMC40KQ0KDQpgYGANCg0KIyMjIyBHcsOhZmljbyBkZSBDYXR0ZWxsDQpgYGB7ciBHcmFmaWNvX2RlX0NhdHRlbGwsIGZpZy5hbGlnbiA9ICdjZW50ZXInfQ0KZnZpel9laWcoUENBKHJlc2VuYXNfZGVfanVlZ29zX2VsZWN0cm9uaWNvc19kZXB1cmFkb3NbLC1jKDEsMyw0LDUsNiwxMyldLCBzY2FsZS51bml0ID0gVCwgZ3JhcGggPSBGKSwgYWRkbGFiZWxzID0gVCwgeWxpbT1jKDAsOTApLCBtYWluID0gIiIpDQpgYGANCg0KIyMjIyBHcsOhZmljbyBkZSBDYXR0ZWxsLUthaXNlcg0KYGBge3IgR3JhZmljb19kZV9DYXR0ZWxsX0thaXNlciwgZmlnLmFsaWduID0gJ2NlbnRlcid9DQpzY3JlZShyZXNlbmFzX2RlX2p1ZWdvc19lbGVjdHJvbmljb3NfZGVwdXJhZG9zWywtYygxLDMsNCw1LDYsMTMpXSxmYWN0b3JzID0gRkFMU0UsIHBjID0gVFJVRSwgbWFpbiA9IiIpDQpgYGANCg0KIyMjIDIuMy4gQ2FsaWRhZCBkZSBSZXByZXNlbnRhY2nDs24gey50YWJzZXQgLnRhYnNldC1waWxsc30NCg0KIyMjIyBDw61yY3VsbyBkZSBDb3JyZWxhY2lvbmVzDQpgYGB7ciBDaXJjdWxvX2RlX0NvcnJlbGFjaW9uZXMsIGZpZy5hbGlnbiA9ICdjZW50ZXInfQ0KZnZpel9wY2FfdmFyKFBDQShyZXNlbmFzX2RlX2p1ZWdvc19lbGVjdHJvbmljb3NfZGVwdXJhZG9zWywtYygxLDMsNCw1LDYsMTMpXSwgc2NhbGUudW5pdCA9IFQsIGdyYXBoID0gRiksY29sLnZhcj0iIzNCODNCRCIsIHJlcGVsID0gVCwgY29sLmNpcmNsZSA9ICIjQ0RDRENEIiwgZ2d0aGVtZSA9IHRoZW1lX2J3KCkpDQpgYGANCg0KYGBge3IgdW5kZWZpbmVkLCBmaWcuYWxpZ24gPSAnY2VudGVyJ30NCmZ2aXpfY29udHJpYigNCiAgUENBKHJlc2VuYXNfZGVfanVlZ29zX2VsZWN0cm9uaWNvc19kZXB1cmFkb3NbLC1jKDEsMyw0LDUsNiwxMyldLCBuY3AgPSA2LCBzY2FsZS51bml0ID0gVFJVRSwgZ3JhcGggPSBGQUxTRSksDQogIGNob2ljZSA9ICJ2YXIiLA0KICBheGVzID0gMSwgDQogIHRvcCA9IDEwDQopDQpgYGANCg0KIyMjIyBNYXRyaXogZGUgUmVwcmVzZW50YWNpw7NuDQpgYGB7ciBNYXRyaXpfZGVfUmVwcmVzc2VudGFjaW9uX0NPUzIsIGZpZy5hbGlnbiA9ICdjZW50ZXInfQ0KKGdldF9wY2FfdmFyKFBDQShyZXNlbmFzX2RlX2p1ZWdvc19lbGVjdHJvbmljb3NfZGVwdXJhZG9zWywtYygxLDMsNCw1LDYsMTMpXSwgbmNwID0gNSwgc2NhbGUudW5pdCA9IFRSVUUsIGdyYXBoID0gRikpKSRjb3MyDQpgYGANCg0KIyMjIyBDYWxpZGFkIGRlIFJlcHJlc2VudGFjacOzbg0KYGBge3IgQ2FsaWRhZF9kZV9sYV9SZXByZXNlbnRhY2lvbiwgZmlnLmFsaWduID0gJ2NlbnRlcid9DQpmdml6X3BjYV92YXIoUENBKHJlc2VuYXNfZGVfanVlZ29zX2VsZWN0cm9uaWNvc19kZXB1cmFkb3NbLC1jKDEsMyw0LDUsNiwxMyldLCBuY3AgPSA1LCBzY2FsZS51bml0ID0gVFJVRSwgZ3JhcGggPSBGKSwgY29sLnZhcj0iY29zMiIsIGdyYWRpZW50LmNvbHM9YygiIzAwQUZCQiIsIiNFN0I4MDAiLCIjRkM0RTA3IiksIHJlcGVsID0gVFJVRSkNCmBgYA0KDQojIyMjIENvb3JkZW5hZGFzIEluZGl2aWR1YWxlcw0KYGBge3IgQ29vcmRlbmFkYXNfUmVnaXN0cm9zLCBmaWcuYWxpZ24gPSAnY2VudGVyJ30NCmhlYWQoKFBDQShyZXNlbmFzX2RlX2p1ZWdvc19lbGVjdHJvbmljb3NfZGVwdXJhZG9zWywtYygxLDMsNCw1LDYsMTMpXSwgbmNwID0gNSwgc2NhbGUudW5pdCA9IFRSVUUsIGdyYXBoID0gRikpJGluZCRjb29yZCwgbiA9IDIzTCkNCmBgYA0KDQojIyMgMi40LiBDb250cmlidWNpb25lcyB5IEJpcGxvdHMgey50YWJzZXQgLnRhYnNldC1waWxsc30NCg0KMi40LCAyLjggeSAyLjkgDQoNCg0KDQojIyAqKkZhc2UgMyBbQ29ycmVzcG9uZGVuY2lhc10qKg0KRWwgYW7DoWxpc2lzIGRlIGNvcnJlc3BvbmRlbmNpYXMgc2UgZW1wbGVhIHBhcmEgZXN0dWRpYXIgbGEgYXNvY2lhY2nDs24gZW50cmUgdmFyaWFibGVzIGNhdGVnw7NyaWNhcywgY29tbyBwdWVkZSBzZXIgZ8OpbmVybyB5IHBsYXRhZm9ybWEsIG8gZ8OpbmVybyB5IHJlZ2nDs24gZGUgdmVudGFzLiBFc3RlIGVuZm9xdWUgcGVybWl0ZSB2aXN1YWxpemFyIGVuIHVuIHBsYW5vIHJlZHVjaWRvIGxhIHJlbGFjacOzbiBlbnRyZSBjYXRlZ29yw61hcywgZmFjaWxpdGFuZG8gbGEgaW50ZXJwcmV0YWNpw7NuIGRlIGPDs21vIHNlIHZpbmN1bGFuIGxvcyBkaWZlcmVudGVzIGdydXBvcyBkZW50cm8gZGVsIGRhdGFzZXQuIEFzw60sIHBvciBlamVtcGxvLCBzZSBwdWVkZSBpZGVudGlmaWNhciBzaSBjaWVydG9zIGfDqW5lcm9zIHNvbiBwcmVmZXJpZG9zIGVuIGRldGVybWluYWRhcyBwbGF0YWZvcm1hcyBvIHJlZ2lvbmVzLCBkZXNjdWJyaWVuZG8gcGF0cm9uZXMgcmVsZXZhbnRlcyBlbiBlbCBjb25zdW1vIGRlIHZpZGVvanVlZ29zLg0KDQojIyMgMy4xLiBPYmpldGl2b3MNCkVuIGVzdGEgdGVyY2VyYSBmYXNlIGRlbCBlc3R1ZGlvIHNlIHByZXNlbnRhcsOhbiBsb3MgY8OhbGN1bG9zLCB2aXN1YWxpemFjaW9uZXMgZSBpbnRlcnByZXRhY2lvbmVzIGNvcnJlc3BvbmRpZW50ZXMgYWwgYW7DoWxpc2lzIGRlIGxhcyB2YXJpYWJsZXMgY3VhbGl0YXRpdmFzIGRlbCBjb25qdW50byBkZSBkYXRvcyBwcmV2aWFtZW50ZSB0cmFiYWphZG8gZW4gbGEgW2Zhc2UgMV0oI3NlYzEpIHkgW2Zhc2UgMl0oI3NlYzIpLiBFbCBwcm9ww7NzaXRvIGRlIGVzdGEgZXRhcGEgZXMgYXBsaWNhciBlbCBBbsOhbGlzaXMgZGUgQ29ycmVzcG9uZGVuY2lhcyBTaW1wbGVzIHkgTcO6bHRpcGxlcyAoQUNTIHkgQUNNKSwgY29uIGVsIGZpbiBkZSBleHBsb3JhciBsYXMgcmVsYWNpb25lcyBlbnRyZSBjYXRlZ29yw61hcyB5IHJlcHJlc2VudGFyIGdyw6FmaWNhbWVudGUgbGFzIGFzb2NpYWNpb25lcyBleGlzdGVudGVzLlBhcmEgZWxsbywgc2UgbGxldmFyw6EgYSBjYWJvIGxhIGNvbnN0cnVjY2nDs24gZGUgdGFibGFzIGRlIGNvbnRpbmdlbmNpYSB5IHRhYmxhcyBkaXN5dW50aXZhcyBjb21wbGV0YXMsIGFzw60gY29tbyBsYSBldmFsdWFjacOzbiBkZSBsYSBjYWxpZGFkIGRlIHJlcHJlc2VudGFjacOzbiwgbGFzIGNvbnRyaWJ1Y2lvbmVzIHkgbGEgaW50ZXJwcmV0YWNpw7NuIGRlIGxvcyBlamVzIGZhY3RvcmlhbGVzIG9idGVuaWRvcy4NCg0KIyMjIDMuMi4gQ29ycmVzcG9uZGVuY2lhcyBTaW1wbGVzDQojIyMgMy4zLiBDb3JyZXNwb25kZW5jaWFzIE3Dumx0aXBsZXMNCg0KIyMgKipGYXNlICA0IFtDb25nbG9tZXJhZG9zXSoqDQpFbCBhbsOhbGlzaXMgZGUgY29uZ2xvbWVyYWRvcyBidXNjYSBhZ3J1cGFyIGxvcyB2aWRlb2p1ZWdvcyBlbiBzdWJjb25qdW50b3MgaG9tb2fDqW5lb3Mgc2Vnw7puIHN1cyBjYXJhY3RlcsOtc3RpY2FzIG11bHRpdmFyaWFudGVzLCBjb21vIHB1bnR1YWNpw7NuLCB2ZW50YXMsIGfDqW5lcm8geSBwbGF0YWZvcm1hLiBVdGlsaXphbmRvIGFsZ29yaXRtb3MgY29tbyBLLW1lYW5zIG8gamVyw6FycXVpY29zLCBzZSBpZGVudGlmaWNhbiBncnVwb3MgZGUgdMOtdHVsb3MgcXVlIGNvbXBhcnRlbiBzaW1pbGl0dWRlcywgbG8gY3VhbCBheXVkYSBhIGVudGVuZGVyIGxhIHNlZ21lbnRhY2nDs24gZGVsIG1lcmNhZG8sIGlkZW50aWZpY2FyIG5pY2hvcyBvIGVzdGFibGVjZXIgcGVyZmlsZXMgZGUgdmlkZW9qdWVnb3MgbcOhcyBleGl0b3Nvcy4gTG9zIGNvbmdsb21lcmFkb3MgcHVlZGVuIHVzYXJzZSBwYXJhIGVuZm9jYXIgZXN0cmF0ZWdpYXMgZGUgZGVzYXJyb2xsbyBvIG1lcmNhZGVvIHNlZ8O6biBsb3MgZ3J1cG9zIGRldGVjdGFkb3MuDQoNCiMjIyA0LjEuIE9iamV0aXZvcw0KRW4gZXN0YSAqY3VhcnRhIGV0YXBhKiBkZWwgZXN0dWRpbyBzZSBsbGV2YXLDoW4gYSBjYWJvIGPDoWxjdWxvcywgcmVwcmVzZW50YWNpb25lcyBncsOhZmljYXMgZSBpbnRlcnByZXRhY2lvbmVzIGVtcGxlYW5kbyBlbCBjb25qdW50byBkZSBkYXRvcyBwcmV2aWFtZW50ZSBwcm9jZXNhZG8gZW4gbGFzIEZhc2VzICooMSwgMiB5IDMpLioNCkVsIG9iamV0aXZvIHByaW5jaXBhbCBkZSBlc3RhIGV0YXBhIGVzIGFwbGljYXIgZWwgKkFuw6FsaXNpcyBkZSBDb25nbG9tZXJhZG9zKiwgdGFudG8gZW4gc3UgbW9kYWxpZGFkIGplcsOhcnF1aWNhLCBhIHRyYXbDqXMgZGUgbGEgY29uc3RydWNjacOzbiBlIGludGVycHJldGFjacOzbiBkZSBkZW5kcm9ncmFtYXMsIGNvbW8gZW4gc3UgdmVyc2nDs24gbm8gamVyw6FycXVpY2EsIG1lZGlhbnRlIGxhIGFwbGljYWNpw7NuIGRlbCBtw6l0b2RvIGRlIEstbWVkaWFzLCBjb24gZWwgcHJvcMOzc2l0byBkZSBpZGVudGlmaWNhciBncnVwb3MgaG9tb2fDqW5lb3MgZGVudHJvIGRlbCBjb25qdW50byBkZSBvYnNlcnZhY2lvbmVzLg0KDQojIyMgNC4yLiBBZ3J1cGFjacOzbiBKZXLDoXJxdWljYQ0KIyMjIDQuMy4gQWdydXBhY2nDs24gTm8tSmVyw6FycXVpY2ENCg0KIyMgKipGYXNlIDUgW1JlZ3Jlc2lvbmVzXSoqDQpFbCBhbsOhbGlzaXMgZGUgcmVncmVzacOzbiBzZSBlbXBsZWEgcGFyYSBtb2RlbGFyIGxhcyByZWxhY2lvbmVzIGVudHJlIHVuYSB2YXJpYWJsZSBkZXBlbmRpZW50ZSB5IHVuYSBvIHZhcmlhcyB2YXJpYWJsZXMgaW5kZXBlbmRpZW50ZXMgZGVudHJvIGRlbCBjb25qdW50byBkZSBkYXRvcy4gRW4gZWwgY29udGV4dG8gZGUgdmlkZW9qdWVnb3MsIGVzIGNvbcO6biBpbnRlbnRhciBwcmVkZWNpciBsYXMgdmVudGFzIGVuIGZ1bmNpw7NuIGRlIHZhcmlhYmxlcyBjb21vIGVsIGHDsW8gZGUgbGFuemFtaWVudG8sIGxhIHB1bnR1YWNpw7NuIGRlIHVzdWFyaW9zLCBsYSBwbGF0YWZvcm1hLCBvIGVsIGfDqW5lcm8uIFNlIGludGVycHJldGEgcXXDqSBmYWN0b3JlcyB0aWVuZW4gbcOhcyBpbmZsdWVuY2lhIHNvYnJlIGVsIMOpeGl0byBjb21lcmNpYWwgZGVsIHZpZGVvanVlZ28geSBjw7NtbyBwdWVkZW4gdXNhcnNlIGVzdG9zIGhhbGxhemdvcyBwYXJhIGxhIHRvbWEgZGUgZGVjaXNpb25lcyBlbiBsYSBpbmR1c3RyaWEuDQoNCiMjIyA1LjEuIE9iamV0aXZvcw0KRXN0ZSBlc3R1ZGlvIHRpZW5lIGNvbW8gcHJvcMOzc2l0byBlc3RhYmxlY2VyIGxhICpyZWxhY2nDs24gZW50cmUgZG9zIG8gbcOhcyB2YXJpYWJsZXMqIG1lZGlhbnRlIGxhIG9idGVuY2nDs24gZGUgaW5mb3JtYWNpw7NuIHNvYnJlIHVuYSBkZSBlbGxhcywgYmFzYWRhIGVuIGVsIGNvbm9jaW1pZW50byBkZSBsb3MgdmFsb3JlcyBkZSBsYXMgb3RyYXMuIExhcyByZWxhY2lvbmVzIGVzdGFibGVjaWRhcyBzb24gZGUgY2Fyw6FjdGVyIG5vIGRldGVybWluw61zdGljbywgZXMgZGVjaXIsIHNlIHBsYW50ZWFyw6FuIHJlbGFjaW9uZXMgcHJvYmFiaWzDrXN0aWNhcyB5IHNlIGltcGxlbWVudGFyw6FuIHByb2NlZGltaWVudG9zIHBhcmEgcmVhbGl6YXIgaW5mZXJlbmNpYXMgc29icmUgbG9zIG1vZGVsb3MgdXRpbGl6YWRvcy4gQWRlbcOhcywgc2Ugb2J0ZW5kcsOhbiBtZWRpZGFzIGN1YW50aXRhdGl2YXMgcXVlIGluZGlxdWVuIGVsIGdyYWRvIGRlIHJlbGFjacOzbiBlbnRyZSBsYXMgdmFyaWFibGVzLiBMb3MgbW9kZWxvcyBjb25zaWRlcmFkb3MgZW4gZXN0ZSB0cmFiYWpvIGNvcnJlc3BvbmRlbiBhIGNhc29zIGVzcGVjw61maWNvcyBkZWwgbW9kZWxvIGxpbmVhbCBnZW5lcmFsaXphZG86ICoqUmVncmVzacOzbiBMaW5lYWwgU2ltcGxlLCAqKlJlZ3Jlc2nDs24gTGluZWFsIE3Dumx0aXBsZSogeSAqUmVncmVzacOzbiBMb2fDrXN0aWNhKi4gQ2FkYSBtb2RlbG8gc2Vyw6EgZGVzY3JpdG8gdGXDs3JpY2FtZW50ZSBlbiBzdSByZXNwZWN0aXZhIHNlY2Npw7NuLCB5IHNlIGFwbGljYXLDoSBhIHVuIGNvbmp1bnRvIGRlIGRhdG9zIGVzcGVjw61maWNvIGRlc2NyaXRvIGVuIGxhIFtzZWNjacOzbiAyXSgjc2VjMikuDQoNCiMjIyA1LjIuIFJlZ3Jlc2nDs24gTGluZWFsIFNpbXBsZQ0KIyMjIDUuMy4gUmVncmVzacOzbiBMaW5lYWwgTcO6bHRpcGxlDQojIyMgNS40LiBSZWdyZXNpw7NuIExvZ8Otc3RpY2EgU2ltcGxlDQojIyMgNS41LiBBanVzdGUgZGUgVmFyaWFuemENCg0KIyMgKio2LiBDb25jbHVzaW9uZXMqKg0KDQojIyAqKjcuIEJpYmxpb2dyYWbDrWEqKg0KDQoNCg==