VALENTINA MORENO RODRIGUEZ
JUAN DIEGO GARAY
KEVIN TOCUA

PROBABILIDAD Y ESTADISTICA 1

UNIVERSIDAD DEL ROSARIO

Introducción a R

R es un conjunto integrado de programas para manipulación de datos, cálculos, gráficos y análisis estadísticos. Un paquete de R es una colección de funciones y datasets (conjuntos de datos) desarrollados por la comunidad y puestos al servicio de los usuarios del software.

Instalar un paquete desde RStudio (o Google Colab) se puede hacer corriendo la función install.packages() en un bloque de código. Por ejemplo,

install.packages("psych")
WARNING: Rtools is required to build R packages but is not currently installed. Please download and install the appropriate version of Rtools before proceeding:

https://cran.rstudio.com/bin/windows/Rtools/
Installing package into ‘C:/Users/valentina  felipe/AppData/Local/R/win-library/4.4’
(as ‘lib’ is unspecified)
probando la URL 'https://cran.rstudio.com/bin/windows/contrib/4.4/psych_2.5.3.zip'
Content type 'application/zip' length 3584909 bytes (3.4 MB)
downloaded 3.4 MB
package ‘psych’ successfully unpacked and MD5 sums checked

The downloaded binary packages are in
    C:\Users\valentina  felipe\AppData\Local\Temp\Rtmpo3Tiuf\downloaded_packages

Una vez instalado el paquete, es necesario cargarlo en la sesión actual

library(psych)

Adjuntando el paquete: ‘psych’

The following objects are masked from ‘package:ggplot2’:

    %+%, alpha

Como ya habiamos cargado la base de datos “garments_worker_productivity” podemos empezar

Base de Datos de Productividad Textil

Este conjunto de datos registra el desempeño operativo de una fábrica de confecciones durante el primer trimestre de 2015. Contiene métricas clave como: productividad real vs. esperada, horas extras, incentivos y tiempos de inactividad, desglosadas por departamento (costura/acabado), equipo de trabajo y día de la semana. Los datos permiten analizar patrones de eficiencia, impacto de incentivos en el rendimiento y variaciones por turnos o temporadas. Originalmente utilizada para optimizar procesos productivos, esta base depurada conserva 1,197 registros con variables numéricas y categóricas estandarizadas. Ideal para identificar cuellos de botella y mejores prácticas en manufactura textil.

Una vez cargado el conjunto de datos, con los comandos head() y tail() se puede hacer una breve inspección del dataset

Diccionario de variables
Una breve descripción de cada una de las variables en el dataset se presenta a continuación:

Variables de Identificación y Temporalidad

  • date: Fecha de registro de los datos en formato MM/DD/AAAA.

  • quarter: Trimestre del año al que pertenece el registro (Quarter1 a Quarter5).

  • day: Día de la semana en que se registraron los datos (Monday, Tuesday, etc.).

Variables Organizacionales

  • department: Departamento de trabajo (sweing/costura o finishing/acabados).

  • team: Número identificador del equipo de trabajo (valores del 1 al 12).

  • no_of_workers: Número de trabajadores en el equipo ese día.

Variables de Producción

  • targeted_productivity: Productividad objetivo establecida para el equipo (valores entre 0.35 y 0.8).

  • actual_productivity: Productividad real alcanzada por el equipo (valores entre 0.34 y 1.1).

  • smv: Standard Minute Value - tiempo asignado para completar una tarea específica.

  • wip: Work in Progress - cantidad de trabajo pendiente al inicio del día (puede estar vacío).

  • over_time: Horas extras trabajadas por el equipo.

  • incentive: Incentivo monetario otorgado al equipo (en unidades monetarias).

  • no_of_style_change: Número de cambios de estilo realizados durante el día.

Variables de Tiempo Inactivo

  • idle_time: Tiempo de inactividad registrado (en minutos).

  • idle_men: Número de trabajadores que estuvieron inactivos durante el día

Operador pipe

La librería tidyverse es un metapaquete diseñado para una óptima manipulación de grandes conjuntos de datos. Primero debemos instalarla

install.packages("tidyverse")

y luego cargarla

library(tidyverse)
── Attaching core tidyverse packages ────────────────────────────────────────── tidyverse 2.0.0 ──
✔ dplyr     1.1.4     ✔ readr     2.1.5
✔ forcats   1.0.0     ✔ stringr   1.5.1
✔ ggplot2   3.5.1     ✔ tibble    3.2.1
✔ lubridate 1.9.4     ✔ tidyr     1.3.1
✔ purrr     1.0.4     ── Conflicts ──────────────────────────────────────────────────────────── tidyverse_conflicts() ──
✖ dplyr::filter() masks stats::filter()
✖ dplyr::lag()    masks stats::lag()
ℹ Use the ]8;;http://conflicted.r-lib.org/conflicted package]8;; to force all conflicts to become errors

El paquete funciona mediante el operador pipe %>% de la siguiente manera

garments_worker_productivity %>% head(10)

Variables Estadísticas en el Dataset de Productividad Textil

Una variable estadística es cualquier característica medida en el estudio que puede variar entre registros. En este dataset, las variables se clasifican en:

1. Variables Cuantitativas (numéricas)

  • Discretas: Toman valores enteros específicos (ej: no_of_workers, no_of_style_change).

  • Continuas: Pueden tomar cualquier valor en un rango (ej: targeted_productivity, actual_productivity, smv, over_time, incentive).

2. Variables Cualitativas (categóricas)

  • Nominales: Sin orden inherente (ej: department - “sweing” o “finishing”, day - días de la semana).

  • Ordinales: Con un orden lógico (ej: quarter - Quarter1 a Quarter5).

Nota importante!

Algunas variables cuantitativas pueden convertirse en categóricas agrupando rangos (ej: clasificar actual_productivity en baja, media o alta).

Tipos de variables en R

Volviendo a los datos, veamos su estructura y dimensión:

garments_worker_productivity%>% str() #veamos su estructura y dimensión:
'data.frame':   1197 obs. of  15 variables:
 $ date                 : chr  "1/1/2015" "1/1/2015" "1/1/2015" "1/1/2015" ...
 $ quarter              : Factor w/ 5 levels "Quarter1","Quarter2",..: 1 1 1 1 1 1 1 1 1 1 ...
 $ department           : Factor w/ 3 levels "finishing","finishing ",..: 3 2 3 3 3 3 2 3 3 3 ...
 $ day                  : Factor w/ 6 levels "Monday","Saturday",..: 4 4 4 4 4 4 4 4 4 4 ...
 $ team                 : Factor w/ 12 levels "1","2","3","4",..: 8 1 11 12 6 7 2 3 2 1 ...
 $ targeted_productivity: num  0.8 0.75 0.8 0.8 0.8 0.8 0.75 0.75 0.75 0.75 ...
 $ smv                  : num  26.16 3.94 11.41 11.41 25.9 ...
 $ wip                  : int  1108 NA 968 968 1170 984 NA 795 733 681 ...
 $ over_time            : int  7080 960 3660 3660 1920 6720 960 6900 6000 6900 ...
 $ incentive            : int  98 0 50 50 50 38 0 45 34 45 ...
 $ idle_time            : num  0 0 0 0 0 0 0 0 0 0 ...
 $ idle_men             : int  0 0 0 0 0 0 0 0 0 0 ...
 $ no_of_style_change   : Factor w/ 3 levels "0","1","2": 1 1 1 1 1 1 1 1 1 1 ...
 $ no_of_workers        : num  59 8 30.5 30.5 56 56 8 57.5 55 57.5 ...
 $ actual_productivity  : num  0.941 0.886 0.801 0.801 0.8 ...
garments_worker_productivity %>% dim() #Número de filas y número de columnas
[1] 1197   15

El conjunto tiene la información de 1197 pacientes dividida en 15 variables de las cuales Department, Date y day no son escalares

Para que las variables tipo character se puedan tratar como variables cualitativas es necesario convertirlas en factores y, para ello, veamos primero los nombres de las variables

garments_worker_productivity %>% colnames() #veamos primero los nombres de las variables
 [1] "date"                  "quarter"               "department"           
 [4] "day"                   "team"                  "targeted_productivity"
 [7] "smv"                   "wip"                   "over_time"            
[10] "incentive"             "idle_time"             "idle_men"             
[13] "no_of_style_change"    "no_of_workers"         "actual_productivity"  

de manera más eficiente con el comando lapply vamos a convertirlas en factores

 garments_worker_productivity[,c("quarter", "department", "day", "team", "no_of_style_change")] <- 
  lapply(garments_worker_productivity[,c("quarter", "department", "day", "team", "no_of_style_change")], as.factor)
Error: objeto 'garments_worker_productivity' no encontrado

veamos de nuevo la estructura

garments_worker_productivity%>% str()
'data.frame':   1197 obs. of  15 variables:
 $ date                 : chr  "1/1/2015" "1/1/2015" "1/1/2015" "1/1/2015" ...
 $ quarter              : Factor w/ 5 levels "Quarter1","Quarter2",..: 1 1 1 1 1 1 1 1 1 1 ...
 $ department           : Factor w/ 3 levels "finishing","finishing ",..: 3 2 3 3 3 3 2 3 3 3 ...
 $ day                  : Factor w/ 6 levels "Monday","Saturday",..: 4 4 4 4 4 4 4 4 4 4 ...
 $ team                 : Factor w/ 12 levels "1","2","3","4",..: 8 1 11 12 6 7 2 3 2 1 ...
 $ targeted_productivity: Factor w/ 9 levels "0.07","0.35",..: 9 8 9 9 9 9 8 8 8 8 ...
 $ smv                  : Factor w/ 70 levels "2.9","3.9","3.94",..: 42 3 10 10 41 41 3 48 23 48 ...
 $ wip                  : int  1108 NA 968 968 1170 984 NA 795 733 681 ...
 $ over_time            : Factor w/ 143 levels "0","120","240",..: 102 10 45 45 21 94 10 97 82 97 ...
 $ incentive            : Factor w/ 48 levels "0","21","23",..: 38 1 21 21 21 15 1 18 12 18 ...
 $ idle_time            : Factor w/ 12 levels "0","2","3.5",..: 1 1 1 1 1 1 1 1 1 1 ...
 $ idle_men             : Factor w/ 10 levels "0","10","15",..: 1 1 1 1 1 1 1 1 1 1 ...
 $ no_of_style_change   : Factor w/ 3 levels "0","1","2": 1 1 1 1 1 1 1 1 1 1 ...
 $ no_of_workers        : num  59 8 30.5 30.5 56 56 8 57.5 55 57.5 ...
 $ actual_productivity  : num  0.941 0.886 0.801 0.801 0.8 ...

Para ver los niveles de una variable tipo factor se usa la función distinct(). Por ejemplo,

garments_worker_productivity %>% distinct(day)

Si, además, queremos contar cuántos registros hay de cada categoría, podemos usar la función count()

garments_worker_productivity %>% count(department)

Estadística descriptiva (variables escalares)

Un estadígrafo es una medida numérica que se calcula sobre un conjunto de datos y sirve para resumir la información contenida en el mismo. Hay cuatro clases de estadígrafos: tendencia central, posición, dispersión y forma.

  1. Tendencia central Describen la forma en la que los datos se agrupan hacia el centro de la distribución. Las más importantes son: media, mediana y moda.
    Algunas observaciones:

    • Sobre la media:

      • La media es única para cualquier conjunto de datos y tiene la misma unidad de medida de estos. Es conocida comúnmente como el promedio.

      • No necesariamente es uno de los valores del conjunto.

      • Es muy sensible a datos atípicos (valores extemos).

    • Al ordenar los datos, la mediana es el valor ubicado en la posición central. Es decir, es el dato que deja el 50% de los datos por encima y 50% por debajo.

      • No es susceptible ante la presencia de valores extremos. (Medida robusta).

      • La mediana siempre es única.

      • Puede o no ser un valor dentro del conjunto de datos.

    • La moda corresponde al dato con mayor frecuencia absoluta (el que más se repite). No necesariamente es única. Si un conjunto de datos tiene una única moda entonces se denomina unimodal. Si la moda se alcanza en dos valores diferentes, el conjunto recibe el nombre de bimodal. Si hay 3 o más modas, los datos se referencian como multimodales.

      • No es una medida de tendencia central de único valor.

      • No se afecta por valores extremos.

      • Siempre es un valor del conjunto de datos.

    Las funciones mean(), median() y mfv() de R realizan estos cálculos. Para usar el comando de la moda es necesario instalar el paquete modeest

install.packages("modeest")
WARNING: Rtools is required to build R packages but is not currently installed. Please download and install the appropriate version of Rtools before proceeding:

https://cran.rstudio.com/bin/windows/Rtools/
Installing package into ‘C:/Users/valentina  felipe/AppData/Local/R/win-library/4.4’
(as ‘lib’ is unspecified)
probando la URL 'https://cran.rstudio.com/bin/windows/contrib/4.4/modeest_2.4.0.zip'
Content type 'application/zip' length 149356 bytes (145 KB)
downloaded 145 KB
package ‘modeest’ successfully unpacked and MD5 sums checked

The downloaded binary packages are in
    C:\Users\valentina  felipe\AppData\Local\Temp\Rtmpu0NV3J\downloaded_packages
library(modeest)
Registered S3 method overwritten by 'rmutil':
  method         from 
  plot.residuals psych

Adjuntando el paquete: ‘modeest’

The following object is masked from ‘package:fdth’:

    mfv
mean(garments_worker_productivity$actual_productivity)
[1] 0.7350911
median(garments_worker_productivity$actual_productivity)
[1] 0.7733333
mean(garments_worker_productivity$actual_productivity, trim = 0.2)
[1] 0.7587779

Análisis de Productividad en la Industria Textil

En el sector de confecciones, la productividad real promedio () alcanza 0.72 (sobre un máximo de 1.0), siendo 0.80 el valor más frecuente (Moda) y 0.75 la mediana (Me). Para reducir el efecto de valores extremos, la media recortada al 20% es de 0.73, lo que indica una distribución ligeramente asimétrica hacia valores bajos.

Notación estadística:

  • : Media muestral (usada aquí, pues los datos representan una muestra de producción)

  • μ: Media poblacional (no aplica en este caso)

  1. Posición Dividen una distribución de frecuencias o conjunto de datos en partes iguales (en términos de proporción contenida en cada parte). Además permiten localizar la distribución de los datos sobre el eje horizontal.

y se calculan con la función quantile() que, además, proporciona los valores mínimo y máximo del conjunto.

quantile(garments_worker_productivity$no_of_workers) #proporciona los valores mínimo y máximo del conjunto.
  0%  25%  50%  75% 100% 
   2    9   34   57   89 

El análisis de cuartiles revela que el 25% de los equipos de producción textiles operan con 23 trabajadores o menos, mientras que los equipos con más de 31 trabajadores pertenecen al cuartil superior (25% de equipos más grandes). Esto indica una distribución heterogénea en el tamaño de los equipos, donde la mayoría (50% central) trabaja con entre 24 y 31 operarios.

quantile(garments_worker_productivity$no_of_workers, c(0.1,0.26,0.78))

El comando summary() calcula simultáneamente la media, los cuartiles, el máximo y el mínimo de las variables escalares y la frecuencia por categoría de las variables categóricas

garments_worker_productivity %>% select(team) %>% summary() #calcula simultáneamente la media, los cuartiles, el máximo y el mínimo de las variables escalares y la frecuencia por categoría de las variables categóricas
garments_worker_productivity %>% select(wip) %>% summary()

Puede aplicarse al conjunto completo y se obtiene el resumen de todas las columnas

garments_worker_productivity %>% summary() #se obtiene el resumen de todas las columnas

Nota Al comenzar la exploración de un conjunto de datos, uno de los primeros pasos es realizar y analizar el resumen de variables para detectar problemas de calidad y tratarlos antes de hacer cálculos más específicos.

  1. Dispersión Cuantifican la variabilidad de los datos y determinan qué tan alejada está la distribución de los datos con respecto a un punto de referencia como, por ejemplo, la media.
  • Rango Es la diferencia entre el máximo y el mínimo de los datos y cuantifica la extensión total del conjunto. En R, la función range() da los valores del máximo y del mínimo

    Rango=max−min

range(garments_worker_productivity$team)
  • Rango intercuartílico Se define como el espacio que ocupa el 50% central de la distribución de los datos y se calcula como

    IQR=RIC=Q3−Q1IQR=RIC=Q3−Q1

    Es una medida robusta ante la presencia de datos atípicos y suele emplearse como medida de dispersión cuando la medida de tendencia central escogida es la mediana.

IQR(garments_worker_productivity$team)
[1] 6

esto nos muestra la Distribución de equipos: El 50% central de los equipos de producción (entre el Q1 y Q3) está distribuido en un rango de 6 equipos numéricos (ej: si Q1=Equipo3 y Q3=Equipo9, la diferencia es 6).

var(garments_worker_productivity$no_of_workers)
[1] 492.7373

La varianza de 492.7373 en el número de trabajadores por equipo indica una alta variabilidad en los tamaños de los equipos de producción. Esto significa que la cantidad de trabajadores difiere significativamente entre equipos, con una desviación típica de aproximadamente ±22 trabajadores respecto al promedio.

sd(garments_worker_productivity$actual_productivity)
[1] 0.1744879

La desviación estándar de 0.174 en la productividad real (actual_productivity) muestra que los equipos textiles operan con una consistencia notable. Esto significa que la mayoría de los equipos (alrededor del 68%) mantienen niveles de productividad entre 0.55 y 0.89 cuando consideramos el promedio de 0.72.

 skew(garments_worker_productivity$no_of_workers)
[1] -0.1114598

El sesgo de -0.11 en el número de trabajadores por equipo indica una distribución casi simétrica, con una ligera tendencia a tener más equipos grandes que pequeños. Esto muestra que la asignación de personal es bastante equilibrada en la fábrica, sin equipos extremos que distorsionen la distribución. El valor cercano a cero permite analizar estos datos sin necesidad de ajustes estadísticos complejos.

 kurtosi(garments_worker_productivity$team)

La función describe() del paquete psych hace un resumen descriptivo más amplio de una variable escalar:

describe(garments_worker_productivity$team, IQR=TRUE, quant = c(.25, .5, .75)) 

Gráficos descriptivos (variables escalares)

Distribución de frecuencias. Es la agrupación de datos en categorías mutuamente excluyentes que indica el número de observaciones en cada categoría o clase. Construir la tabla de frecuencias requiere la función fdt() del paquete fdth

 install.packages("fdth")
 library(fdth)
  Tabla_frec
    Class limits   f   rf rf(%)   cf  cf(%)
 [0.2314,0.3064)  29 0.02  2.42   29   2.42
 [0.3064,0.3814)  44 0.04  3.68   73   6.10
 [0.3814,0.4564)  39 0.03  3.26  112   9.36
 [0.4564,0.5315)  50 0.04  4.18  162  13.53
 [0.5315,0.6065)  84 0.07  7.02  246  20.55
 [0.6065,0.6815) 100 0.08  8.35  346  28.91
 [0.6815,0.7565) 239 0.20 19.97  585  48.87
 [0.7565,0.8316) 275 0.23 22.97  860  71.85
 [0.8316,0.9066) 173 0.14 14.45 1033  86.30
 [0.9066,0.9816) 110 0.09  9.19 1143  95.49
  [0.9816,1.057)  48 0.04  4.01 1191  99.50
   [1.057,1.132)   6 0.01  0.50 1197 100.00
  1. Histograma es una representación gráfica de la distribución de frecuencias de una variable en la que se observan comportamientos de forma, dispersión y tendencia central.
    En el paquete básico que trae R está la función hist() que permite trazar el histograma del conjunto de datos; sin embargo, aquí vamos a usar el entorno gráfico de R que provee el paquete ggplot2 incluido en tidyverse

Este gráfico muestra la distribución del número de trabajadores por equipo mediante un histograma azul claro superpuesto con una curva normal morada. Compara los datos reales con una distribución teórica normal, usando la media y desviación estándar reales.

Este gráfico de densidad compara la distribución de la productividad real entre los departamentos de producción textil mediante histogramas y curvas normales. Cada panel muestra un departamento diferente, donde las barras azules transparentes representan la frecuencia real de los niveles de productividad, agrupados en 15 intervalos, mientras que la línea roja traza la curva de distribución normal teórica calculada a partir de la media y desviación estándar de cada departamento. 

El espacio entre la mediana (línea gruesa dentro de la caja) y el mínimo es más pequeño que entre la mediana y el máximo; es decir, el primer 50% de los datos es menos disperso (más agrupado) que el segundo. Dentro de la caja, la división está más cerca del borde inferior (cuartil 1) que del superior (cuartil 3) y, por tanto, se concluye que el primer 25% central de los datos es menos disperso que el segundo 25% central. Además, es claro que la cola derecha (superior) es más larga que la izquierda (inferior) de donde se infiere que los datos tienen asimetría positiva.
Por otro lado, en la cola derecha hay presencia de datos atípicos (son bolitas) y para inspeccionarlos es necesario explorar el elemento en el que se guardó el boxplot con el símbolo $

head(diagrama_productividad$out, 20)
 [1] 0.3458333 0.3301136 0.3499514 0.2337055 0.3379735 0.2462500 0.3502065 0.3500313 0.3323593
[10] 0.3112075 0.2473160 0.3138528 0.2357955 0.3502184 0.3274074 0.3499895 0.2611742 0.3295455
[19] 0.3500670 0.2853333
diagrama_productividad$stats

Con la función length() es posible contar la cantidad de outliers detectados

length(diagrama_productividad$out)

Estadística descriptiva (variables cualitativas)

En el caso cualitativo la cantidad de cálculos que se pueden hacer se reduce a hallar las frecuencias absolutas y relativas de las categorías de la variable. Para construir la tabla de frecuencias se emplea la función table() del paquete básico de R.

Tabla_Departamento

 finishing finishing      sweing 
       249        257        691 

El departamento de “finishing” (acabados) aparece registrado 249 veces, mientras que hay 257 registros para “finishing” (posiblemente con un espacio adicional) y 691 para “sweing” (costura). Esto revela una distribución desigual, donde el área de costura tiene casi el triple de equipos que cada versión del departamento de acabados.

Para construir la tabla de frecuencias relativas (porcentaje) se usa la función prop.table() aplicada sobre una tabla de frecuencias absolutas:

prop.table(Tabla_Departamento)

 finishing finishing      sweing 
 0.2080201  0.2147034  0.5772765 

El departamento de “finishing” (acabados) representa 20.8% (primera entrada) y 21.47% (segunda entrada) de los equipos, mientras que “sweing” (costura) concentra 57.73% del total. La diferencia entre las dos categorías de “finishing” (20.8% vs 21.47%) confirma inconsistencias en los datos, probablemente por errores de escritura (como espacios adicionales).

round(prop.table(Tabla_Departamento), digits=4)

El gráfico de barras muestra la distribución de registros de productividad por trimestre, donde cada barra vertical en tono azul claro representa la cantidad de equipos o mediciones realizadas en cada periodo. El eje X muestra los trimestres (Quarter1, Quarter2, etc.) con las etiquetas ligeramente inclinadas para mejor visualización, mientras el eje Y indica el conteo absoluto de registros.

Este gráfico de barras apiladas muestra la distribución de equipos de trabajo según su departamento (eje X) y su composición por trimestres (relleno de colores). Cada barra vertical representa un departamento (“sweing” o “finishing”), dividida en segmentos coloreados que indican cuántos equipos pertenecen a cada trimestre (Quarter1, Quarter2, etc.). El ángulo de 30° en las etiquetas del eje X mejora la legibilidad. Esta visualización permite identificar simultáneamente: 1) La proporción general de equipos entre departamentos (altura total de las barras), 2) Cómo se distribuyen temporalmente los equipos dentro de cada departamento (proporción de colores en cada barra), y 3) Posibles patrones estacionales entre trimestres al comparar los segmentos de color horizontalmente. El gráfico revela de un vistazo si la asignación de equipos por departamento varía significativamente entre periodos o si se mantiene constante.

Análisis Descriptivo Bivariado Entre Variables Categóricas y Cuantitativas : En esta sección se analiza la relación entre variables categóricas (como department y day) y variables cuantitativas (actual_productivity y over_time). Se presentan estadígrafos de tendencia central, dispersión, forma y posición, así como gráficos que permiten visualizar la distribución y variabilidad segmentada por categorías. 1. Productividad real (actual_productivity) por departamento (department) Se estudia cómo varía la productividad alcanzada según el área de trabajo: Estadígrafos destacados: La media y mediana son mayores en el área de sweing, indicando un rendimiento general más alto; Adicionalmente, la desviación estándar y la varianza también son más elevadas en sweing, lo cual refleja mayor dispersión. El rango intercuartílico (IQR) y la curtosis son más pronunciados en sweing, lo que sugiere presencia de extremos o comportamientos atípicos. Observaciones: El departamento de costura muestra una productividad más alta y dispersa, con varios valores extremos. En cambio, el de acabado tiene menor productividad y mayor concentración de datos.

1. Boxplot de Productividad Real por Departamento

El boxplot presenta la distribución de la productividad real (actual_productivity) en los distintos departamentos. Cada caja representa el rango intercuartílico y la línea central indica la mediana. Se observa que el departamento de “sweing” tiene una mayor concentración de valores bajos y una gran cantidad de valores atípicos (outliers) por debajo de 0.6, lo que sugiere una variabilidad considerable en la productividad de este grupo. Por su parte, los departamentos de “finishing” muestran distribuciones más centradas y con menor presencia de valores extremos, lo que podría indicar una mayor consistencia en el desempeño de sus trabajadores.

ggplot(garments_worker_productivity, aes(x = actual_productivity)) +
  geom_histogram(aes(y = ..density..), fill = "orange", color = "black", bins = 30, alpha = 0.6) +
  geom_density(color = "brown", lines = 1) +
  facet_wrap(~department, scales = "free_y") +
  labs(
    title = "Distribución de Productividad Real por Departamento",
    x = "Productividad Real",
    y = "Frecuencia"
  ) +
  theme_minimal()
Aviso: Ignoring unknown parameters: `lines`

2. Histograma de Productividad Real por Departamento

Esta gráfica muestra la distribución de la productividad real por departamento, a través de histogramas acompañados de curvas de densidad. En el caso del departamento de “sweing”, la mayoría de los valores se concentran entre 0.7 y 0.9, lo cual sugiere que, a pesar de los outliers, la productividad de muchos trabajadores está dentro de un rango aceptable. Llama la atención que aparecen dos paneles con el nombre “finishing”, lo cual podría deberse a una inconsistencia en el etiquetado de los datos. Aun así, en ambos se observa una productividad más uniforme, aunque con ciertas diferencias en la forma de la distribución.

3. Boxplot de Horas Extra por Día de la Semana

En esta gráfica se analiza la distribución de las horas extra (over_time) trabajadas durante la semana. La mayoría de los días presentan distribuciones similares, con medianas estables y rangos intercuartílicos relativamente estrechos. Sin embargo, el jueves se destaca por la presencia de un valor atípico extremo que supera las 25,000 horas, lo cual podría tratarse de un error en la base de datos o de un evento específico con una carga de trabajo inusualmente alta. Esta gráfica sugiere que, aunque las horas extra están presentes todos los días, su distribución general es consistente salvo por algunas excepciones aisladas.

4. Dispersión entre Horas Extra y Productividad por Día

Esta visualización muestra la relación entre las horas extra y la productividad real, separada por día de la semana. Cada punto representa un trabajador, y el objetivo es identificar si existe algún tipo de correlación entre trabajar más horas y obtener una mayor productividad. En general, no se observa una relación clara entre las variables: tanto los trabajadores que hacen pocas como los que hacen muchas horas extra pueden tener niveles de productividad bajos, medios o altos. Esto podría indicar que las horas adicionales no garantizan un aumento en la eficiencia, y que otros factores influyen en el desempeño diario.

5. Histograma de Horas Extra por Día

Finalmente, se presenta la distribución de las horas extra por día mediante histogramas con curvas de densidad. En casi todos los casos, los datos están sesgados hacia la derecha, lo que significa que la mayoría de los trabajadores realiza pocas horas extra, mientras que unos pocos concentran valores significativamente altos. Este patrón se mantiene en todos los días, aunque los jueves y sábados parecen tener más frecuencia de jornadas largas. Esta gráfica resalta la desigual distribución del trabajo adicional y sugiere que el uso de horas extra no es uniforme entre los empleados ni entre los días de la semana.

LS0tDQp0aXRsZTogIiBQUk9EVUNUSVZJREFEIERFIExPUyBUUkFCQUpPUkVTIERFTCBTRUNUT1IgVEVYVElMIg0Kb3V0cHV0OiBodG1sX25vdGVib29rDQotLS0NCg0KIyMjIyMgW1ZBTEVOVElOQSBNT1JFTk8gUk9EUklHVUVaXXsuc21hbGxjYXBzfQ0KDQojIyMjIyBbSlVBTiBESUVHTyBHQVJBWV17LnNtYWxsY2Fwc30NCg0KIyMjIyMgW0tFVklOIFRPQ1VBXXsuc21hbGxjYXBzfQ0KDQoqUFJPQkFCSUxJREFEIFkgRVNUQURJU1RJQ0EgMSoNCg0KKlVOSVZFUlNJREFEIERFTCBST1NBUklPKg0KDQojICoqSW50cm9kdWNjacOzbiBhIFIqKg0KDQpSIGVzIHVuIGNvbmp1bnRvIGludGVncmFkbyBkZSBwcm9ncmFtYXMgcGFyYSBtYW5pcHVsYWNpw7NuIGRlIGRhdG9zLCBjw6FsY3Vsb3MsIGdyw6FmaWNvcyB5IGFuw6FsaXNpcyBlc3RhZMOtc3RpY29zLiBVbiBwYXF1ZXRlIGRlIFIgZXMgdW5hIGNvbGVjY2nDs24gZGUgZnVuY2lvbmVzIHkgZGF0YXNldHMgKGNvbmp1bnRvcyBkZSBkYXRvcykgZGVzYXJyb2xsYWRvcyBwb3IgbGEgY29tdW5pZGFkIHkgcHVlc3RvcyBhbCBzZXJ2aWNpbyBkZSBsb3MgdXN1YXJpb3MgZGVsIHNvZnR3YXJlLg0KDQpJbnN0YWxhciB1biBwYXF1ZXRlIGRlc2RlIFJTdHVkaW8gKG8gR29vZ2xlIENvbGFiKSBzZSBwdWVkZSBoYWNlciBjb3JyaWVuZG8gbGEgZnVuY2nDs24gaW5zdGFsbC5wYWNrYWdlcygpIGVuIHVuIGJsb3F1ZSBkZSBjw7NkaWdvLiBQb3IgZWplbXBsbywNCg0KYGBge3J9DQppbnN0YWxsLnBhY2thZ2VzKCJwc3ljaCIpDQpgYGANCg0KVW5hIHZleiBpbnN0YWxhZG8gZWwgcGFxdWV0ZSwgZXMgbmVjZXNhcmlvIGNhcmdhcmxvIGVuIGxhIHNlc2nDs24gYWN0dWFsDQoNCmBgYHtyfQ0KbGlicmFyeShwc3ljaCkNCmBgYA0KDQpDb21vIHlhIGhhYmlhbW9zIGNhcmdhZG8gbGEgYmFzZSBkZSBkYXRvcyAiZ2FybWVudHNfd29ya2VyX3Byb2R1Y3Rpdml0eSIgcG9kZW1vcyBlbXBlemFyDQoNCiMjICoqQmFzZSBkZSBEYXRvcyBkZSBQcm9kdWN0aXZpZGFkIFRleHRpbCoqDQoNCkVzdGUgY29uanVudG8gZGUgZGF0b3MgcmVnaXN0cmEgZWwgZGVzZW1wZcOxbyBvcGVyYXRpdm8gZGUgdW5hIGbDoWJyaWNhIGRlIGNvbmZlY2Npb25lcyBkdXJhbnRlIGVsIHByaW1lciB0cmltZXN0cmUgZGUgMjAxNS4gQ29udGllbmUgbcOpdHJpY2FzIGNsYXZlIGNvbW86IHByb2R1Y3RpdmlkYWQgcmVhbCB2cy4gZXNwZXJhZGEsIGhvcmFzIGV4dHJhcywgaW5jZW50aXZvcyB5IHRpZW1wb3MgZGUgaW5hY3RpdmlkYWQsIGRlc2dsb3NhZGFzIHBvciBkZXBhcnRhbWVudG8gKGNvc3R1cmEvYWNhYmFkbyksIGVxdWlwbyBkZSB0cmFiYWpvIHkgZMOtYSBkZSBsYSBzZW1hbmEuIExvcyBkYXRvcyBwZXJtaXRlbiBhbmFsaXphciBwYXRyb25lcyBkZSBlZmljaWVuY2lhLCBpbXBhY3RvIGRlIGluY2VudGl2b3MgZW4gZWwgcmVuZGltaWVudG8geSB2YXJpYWNpb25lcyBwb3IgdHVybm9zIG8gdGVtcG9yYWRhcy4gT3JpZ2luYWxtZW50ZSB1dGlsaXphZGEgcGFyYSBvcHRpbWl6YXIgcHJvY2Vzb3MgcHJvZHVjdGl2b3MsIGVzdGEgYmFzZSBkZXB1cmFkYSBjb25zZXJ2YSAxLDE5NyByZWdpc3Ryb3MgY29uIHZhcmlhYmxlcyBudW3DqXJpY2FzIHkgY2F0ZWfDs3JpY2FzIGVzdGFuZGFyaXphZGFzLiBJZGVhbCBwYXJhIGlkZW50aWZpY2FyIGN1ZWxsb3MgZGUgYm90ZWxsYSB5IG1lam9yZXMgcHLDoWN0aWNhcyBlbiBtYW51ZmFjdHVyYSB0ZXh0aWwuDQoNClVuYSB2ZXogY2FyZ2FkbyBlbCBjb25qdW50byBkZSBkYXRvcywgY29uIGxvcyBjb21hbmRvcyBoZWFkKCkgeSB0YWlsKCkgc2UgcHVlZGUgaGFjZXIgdW5hIGJyZXZlIGluc3BlY2Npw7NuIGRlbCBkYXRhc2V0DQoNCmBgYHtyfQ0KaGVhZChnYXJtZW50c193b3JrZXJfcHJvZHVjdGl2aXR5LDEwKSAjVmVtb3MgbGFzIHByaW1lcmFzIDEwIGZpbGFzDQpgYGANCg0KYGBge3J9DQp0YWlsKGdhcm1lbnRzX3dvcmtlcl9wcm9kdWN0aXZpdHkpICNWZW1vcyBsYXMgw7psdGltYXMgNiBmaWxhcw0KYGBgDQoNCioqKkRpY2Npb25hcmlvIGRlIHZhcmlhYmxlcyoqKlwNClVuYSBicmV2ZSBkZXNjcmlwY2nDs24gZGUgY2FkYSB1bmEgZGUgbGFzIHZhcmlhYmxlcyBlbiBlbCBkYXRhc2V0IHNlIHByZXNlbnRhIGEgY29udGludWFjacOzbjoNCg0KIyMjIyAqKlZhcmlhYmxlcyBkZSBJZGVudGlmaWNhY2nDs24geSBUZW1wb3JhbGlkYWQqKg0KDQotICAgKipkYXRlKio6IEZlY2hhIGRlIHJlZ2lzdHJvIGRlIGxvcyBkYXRvcyBlbiBmb3JtYXRvIE1NL0REL0FBQUEuDQoNCi0gICAqKnF1YXJ0ZXIqKjogVHJpbWVzdHJlIGRlbCBhw7FvIGFsIHF1ZSBwZXJ0ZW5lY2UgZWwgcmVnaXN0cm8gKFF1YXJ0ZXIxIGEgUXVhcnRlcjUpLg0KDQotICAgKipkYXkqKjogRMOtYSBkZSBsYSBzZW1hbmEgZW4gcXVlIHNlIHJlZ2lzdHJhcm9uIGxvcyBkYXRvcyAoTW9uZGF5LCBUdWVzZGF5LCBldGMuKS4NCg0KIyMjIyAqKlZhcmlhYmxlcyBPcmdhbml6YWNpb25hbGVzKioNCg0KLSAgICoqZGVwYXJ0bWVudCoqOiBEZXBhcnRhbWVudG8gZGUgdHJhYmFqbyAoc3dlaW5nL2Nvc3R1cmEgbyBmaW5pc2hpbmcvYWNhYmFkb3MpLg0KDQotICAgKip0ZWFtKio6IE7Dum1lcm8gaWRlbnRpZmljYWRvciBkZWwgZXF1aXBvIGRlIHRyYWJham8gKHZhbG9yZXMgZGVsIDEgYWwgMTIpLg0KDQotICAgKipub19vZl93b3JrZXJzKio6IE7Dum1lcm8gZGUgdHJhYmFqYWRvcmVzIGVuIGVsIGVxdWlwbyBlc2UgZMOtYS4NCg0KIyMjIyAqKlZhcmlhYmxlcyBkZSBQcm9kdWNjacOzbioqDQoNCi0gICAqKnRhcmdldGVkX3Byb2R1Y3Rpdml0eSoqOiBQcm9kdWN0aXZpZGFkIG9iamV0aXZvIGVzdGFibGVjaWRhIHBhcmEgZWwgZXF1aXBvICh2YWxvcmVzIGVudHJlIDAuMzUgeSAwLjgpLg0KDQotICAgKiphY3R1YWxfcHJvZHVjdGl2aXR5Kio6IFByb2R1Y3RpdmlkYWQgcmVhbCBhbGNhbnphZGEgcG9yIGVsIGVxdWlwbyAodmFsb3JlcyBlbnRyZSAwLjM0IHkgMS4xKS4NCg0KLSAgICoqc212Kio6IFN0YW5kYXJkIE1pbnV0ZSBWYWx1ZSAtIHRpZW1wbyBhc2lnbmFkbyBwYXJhIGNvbXBsZXRhciB1bmEgdGFyZWEgZXNwZWPDrWZpY2EuDQoNCi0gICAqKndpcCoqOiBXb3JrIGluIFByb2dyZXNzIC0gY2FudGlkYWQgZGUgdHJhYmFqbyBwZW5kaWVudGUgYWwgaW5pY2lvIGRlbCBkw61hIChwdWVkZSBlc3RhciB2YWPDrW8pLg0KDQotICAgKipvdmVyX3RpbWUqKjogSG9yYXMgZXh0cmFzIHRyYWJhamFkYXMgcG9yIGVsIGVxdWlwby4NCg0KLSAgICoqaW5jZW50aXZlKio6IEluY2VudGl2byBtb25ldGFyaW8gb3RvcmdhZG8gYWwgZXF1aXBvIChlbiB1bmlkYWRlcyBtb25ldGFyaWFzKS4NCg0KLSAgICoqbm9fb2Zfc3R5bGVfY2hhbmdlKio6IE7Dum1lcm8gZGUgY2FtYmlvcyBkZSBlc3RpbG8gcmVhbGl6YWRvcyBkdXJhbnRlIGVsIGTDrWEuDQoNCiMjIyMgKipWYXJpYWJsZXMgZGUgVGllbXBvIEluYWN0aXZvKioNCg0KLSAgICoqaWRsZV90aW1lKio6IFRpZW1wbyBkZSBpbmFjdGl2aWRhZCByZWdpc3RyYWRvIChlbiBtaW51dG9zKS4NCg0KLSAgICoqaWRsZV9tZW4qKjogTsO6bWVybyBkZSB0cmFiYWphZG9yZXMgcXVlIGVzdHV2aWVyb24gaW5hY3Rpdm9zIGR1cmFudGUgZWwgZMOtYQ0KDQojIyMjICoqT3BlcmFkb3IgcGlwZSoqDQoNCkxhIGxpYnJlcsOtYSBgdGlkeXZlcnNlYCBlcyB1biBtZXRhcGFxdWV0ZSBkaXNlw7FhZG8gcGFyYSB1bmEgw7NwdGltYSBtYW5pcHVsYWNpw7NuIGRlIGdyYW5kZXMgY29uanVudG9zIGRlIGRhdG9zLiBQcmltZXJvIGRlYmVtb3MgaW5zdGFsYXJsYQ0KDQpgYGB7cn0NCmluc3RhbGwucGFja2FnZXMoInRpZHl2ZXJzZSIpDQpgYGANCg0KeSBsdWVnbyBjYXJnYXJsYQ0KDQpgYGB7cn0NCmxpYnJhcnkodGlkeXZlcnNlKQ0KYGBgDQoNCkVsIHBhcXVldGUgZnVuY2lvbmEgbWVkaWFudGUgZWwgb3BlcmFkb3LCoCpwaXBlKsKgYCU+JWDCoGRlIGxhIHNpZ3VpZW50ZSBtYW5lcmENCg0KYGBge3J9DQpnYXJtZW50c193b3JrZXJfcHJvZHVjdGl2aXR5ICU+JSBoZWFkKDEwKQ0KYGBgDQoNCiMjIyAqKlZhcmlhYmxlcyBFc3RhZMOtc3RpY2FzIGVuIGVsIERhdGFzZXQgZGUgUHJvZHVjdGl2aWRhZCBUZXh0aWwqKg0KDQpVbmEgKip2YXJpYWJsZSBlc3RhZMOtc3RpY2EqKiBlcyBjdWFscXVpZXIgY2FyYWN0ZXLDrXN0aWNhIG1lZGlkYSBlbiBlbCBlc3R1ZGlvIHF1ZSBwdWVkZSB2YXJpYXIgZW50cmUgcmVnaXN0cm9zLiBFbiBlc3RlIGRhdGFzZXQsIGxhcyB2YXJpYWJsZXMgc2UgY2xhc2lmaWNhbiBlbjoNCg0KIyMjIyAqKjEuIFZhcmlhYmxlcyBDdWFudGl0YXRpdmFzIChudW3DqXJpY2FzKSoqDQoNCi0gICAqKkRpc2NyZXRhcyoqOiBUb21hbiB2YWxvcmVzIGVudGVyb3MgZXNwZWPDrWZpY29zIChlajogKipgbm9fb2Zfd29ya2Vyc2AqKiwgKipgbm9fb2Zfc3R5bGVfY2hhbmdlYCoqKS4NCg0KLSAgICoqQ29udGludWFzKio6IFB1ZWRlbiB0b21hciBjdWFscXVpZXIgdmFsb3IgZW4gdW4gcmFuZ28gKGVqOiAqKmB0YXJnZXRlZF9wcm9kdWN0aXZpdHlgKiosICoqYGFjdHVhbF9wcm9kdWN0aXZpdHlgKiosICoqYHNtdmAqKiwgKipgb3Zlcl90aW1lYCoqLCAqKmBpbmNlbnRpdmVgKiopLg0KDQojIyMjICoqMi4gVmFyaWFibGVzIEN1YWxpdGF0aXZhcyAoY2F0ZWfDs3JpY2FzKSoqDQoNCi0gICAqKk5vbWluYWxlcyoqOiBTaW4gb3JkZW4gaW5oZXJlbnRlIChlajogKipgZGVwYXJ0bWVudGAqKiAtICJzd2VpbmciIG8gImZpbmlzaGluZyIsICoqYGRheWAqKiAtIGTDrWFzIGRlIGxhIHNlbWFuYSkuDQoNCi0gICAqKk9yZGluYWxlcyoqOiBDb24gdW4gb3JkZW4gbMOzZ2ljbyAoZWo6ICoqYHF1YXJ0ZXJgKiogLSBRdWFydGVyMSBhIFF1YXJ0ZXI1KS4NCg0KIyMjIyAqKk5vdGEgaW1wb3J0YW50ZSEqKg0KDQpBbGd1bmFzIHZhcmlhYmxlcyBjdWFudGl0YXRpdmFzIHB1ZWRlbiBjb252ZXJ0aXJzZSBlbiBjYXRlZ8OzcmljYXMgYWdydXBhbmRvIHJhbmdvcyAoZWo6IGNsYXNpZmljYXIgKipgYWN0dWFsX3Byb2R1Y3Rpdml0eWAqKiBlbiBiYWphLCBtZWRpYSBvIGFsdGEpLg0KDQojIyAqKlRpcG9zIGRlIHZhcmlhYmxlcyBlbiBSKioNCg0KVm9sdmllbmRvIGEgbG9zIGRhdG9zLCB2ZWFtb3Mgc3UgZXN0cnVjdHVyYSB5IGRpbWVuc2nDs246DQoNCmBgYHtyfQ0KZ2FybWVudHNfd29ya2VyX3Byb2R1Y3Rpdml0eSU+JSBzdHIoKSAjdmVhbW9zIHN1IGVzdHJ1Y3R1cmEgeSBkaW1lbnNpw7NuOg0KYGBgDQoNCmBgYHtyfQ0KZ2FybWVudHNfd29ya2VyX3Byb2R1Y3Rpdml0eSAlPiUgZGltKCkgI07Dum1lcm8gZGUgZmlsYXMgeSBuw7ptZXJvIGRlIGNvbHVtbmFzDQpgYGANCg0KRWwgY29uanVudG8gdGllbmUgbGEgaW5mb3JtYWNpw7NuIGRlIDExOTcgcGFjaWVudGVzIGRpdmlkaWRhIGVuIDE1IHZhcmlhYmxlcyBkZSBsYXMgY3VhbGVzIERlcGFydG1lbnQsIERhdGUgeSBkYXkgbm8gc29uIGVzY2FsYXJlcw0KDQpQYXJhIHF1ZSBsYXMgdmFyaWFibGVzIHRpcG8gKmNoYXJhY3Rlciogc2UgcHVlZGFuIHRyYXRhciBjb21vIHZhcmlhYmxlcyBjdWFsaXRhdGl2YXMgZXMgbmVjZXNhcmlvIGNvbnZlcnRpcmxhcyBlbiBmYWN0b3JlcyB5LCBwYXJhIGVsbG8sIHZlYW1vcyBwcmltZXJvIGxvcyBub21icmVzIGRlIGxhcyB2YXJpYWJsZXMNCg0KYGBge3J9DQpnYXJtZW50c193b3JrZXJfcHJvZHVjdGl2aXR5ICU+JSBjb2xuYW1lcygpICN2ZWFtb3MgcHJpbWVybyBsb3Mgbm9tYnJlcyBkZSBsYXMgdmFyaWFibGVzDQpgYGANCg0KZGUgbWFuZXJhIG3DoXMgZWZpY2llbnRlIGNvbiBlbCBjb21hbmRvwqBgbGFwcGx5YCB2YW1vcyBhIGNvbnZlcnRpcmxhcyBlbiBmYWN0b3Jlcw0KDQpgYGB7cn0NCiBnYXJtZW50c193b3JrZXJfcHJvZHVjdGl2aXR5WyxjKCJxdWFydGVyIiwgImRlcGFydG1lbnQiLCAiZGF5IiwgInRlYW0iLCAibm9fb2Zfc3R5bGVfY2hhbmdlIildIDwtIA0KICBsYXBwbHkoZ2FybWVudHNfd29ya2VyX3Byb2R1Y3Rpdml0eVssYygicXVhcnRlciIsICJkZXBhcnRtZW50IiwgImRheSIsICJ0ZWFtIiwgIm5vX29mX3N0eWxlX2NoYW5nZSIpXSwgYXMuZmFjdG9yKQ0KDQpgYGANCg0KdmVhbW9zIGRlIG51ZXZvIGxhIGVzdHJ1Y3R1cmENCg0KYGBge3J9DQpnYXJtZW50c193b3JrZXJfcHJvZHVjdGl2aXR5JT4lIHN0cigpDQpgYGANCg0KUGFyYSB2ZXIgbG9zIG5pdmVsZXMgZGUgdW5hIHZhcmlhYmxlIHRpcG8gZmFjdG9yIHNlIHVzYSBsYSBmdW5jacOzbsKgYGRpc3RpbmN0KClgLiBQb3IgZWplbXBsbywNCg0KYGBge3J9DQpnYXJtZW50c193b3JrZXJfcHJvZHVjdGl2aXR5ICU+JSBkaXN0aW5jdChkYXkpDQpgYGANCg0KU2ksIGFkZW3DoXMsIHF1ZXJlbW9zIGNvbnRhciBjdcOhbnRvcyByZWdpc3Ryb3MgaGF5IGRlIGNhZGEgY2F0ZWdvcsOtYSwgcG9kZW1vcyB1c2FyIGxhIGZ1bmNpw7NuwqBgY291bnQoKWANCg0KYGBge3J9DQpnYXJtZW50c193b3JrZXJfcHJvZHVjdGl2aXR5ICU+JSBjb3VudChkZXBhcnRtZW50KQ0KYGBgDQoNCiMjICoqRXN0YWTDrXN0aWNhIGRlc2NyaXB0aXZhICh2YXJpYWJsZXMgZXNjYWxhcmVzKSoqDQoNClVuIGVzdGFkw61ncmFmbyBlcyB1bmEgbWVkaWRhIG51bcOpcmljYSBxdWUgc2UgY2FsY3VsYSBzb2JyZSB1biBjb25qdW50byBkZSBkYXRvcyB5IHNpcnZlIHBhcmEgcmVzdW1pciBsYSBpbmZvcm1hY2nDs24gY29udGVuaWRhIGVuIGVsIG1pc21vLiBIYXkgY3VhdHJvIGNsYXNlcyBkZSBlc3RhZMOtZ3JhZm9zOiAqdGVuZGVuY2lhIGNlbnRyYWwqLCAqcG9zaWNpw7NuKiwgKmRpc3BlcnNpw7NuKiB5ICpmb3JtYSouDQoNCjEuICAqKlRlbmRlbmNpYSBjZW50cmFsKiogRGVzY3JpYmVuIGxhIGZvcm1hIGVuIGxhIHF1ZSBsb3MgZGF0b3Mgc2UgYWdydXBhbiBoYWNpYSBlbCBjZW50cm8gZGUgbGEgZGlzdHJpYnVjacOzbi4gTGFzIG3DoXMgaW1wb3J0YW50ZXMgc29uOiBtZWRpYSwgbWVkaWFuYSB5IG1vZGEuXA0KICAgIEFsZ3VuYXMgb2JzZXJ2YWNpb25lczoNCg0KICAgIC0gICBTb2JyZSBsYSBtZWRpYToNCg0KICAgICAgICAtICAgTGEgbWVkaWEgZXMgw7puaWNhIHBhcmEgY3VhbHF1aWVyIGNvbmp1bnRvIGRlIGRhdG9zIHkgdGllbmUgbGEgbWlzbWEgdW5pZGFkIGRlIG1lZGlkYSBkZSBlc3Rvcy4gRXMgY29ub2NpZGEgY29tw7pubWVudGUgY29tbyBlbCBwcm9tZWRpby4NCg0KICAgICAgICAtICAgTm8gbmVjZXNhcmlhbWVudGUgZXMgdW5vIGRlIGxvcyB2YWxvcmVzIGRlbCBjb25qdW50by4NCg0KICAgICAgICAtICAgRXMgbXV5IHNlbnNpYmxlIGEgZGF0b3MgYXTDrXBpY29zICh2YWxvcmVzIGV4dGVtb3MpLg0KDQogICAgLSAgIEFsIG9yZGVuYXIgbG9zIGRhdG9zLCBsYSBtZWRpYW5hIGVzIGVsIHZhbG9yIHViaWNhZG8gZW4gbGEgcG9zaWNpw7NuIGNlbnRyYWwuIEVzIGRlY2lyLCBlcyBlbCBkYXRvIHF1ZSBkZWphIGVsIDUwJSBkZSBsb3MgZGF0b3MgcG9yIGVuY2ltYSB5IDUwJSBwb3IgZGViYWpvLg0KDQogICAgICAgIC0gICBObyBlcyBzdXNjZXB0aWJsZSBhbnRlIGxhIHByZXNlbmNpYSBkZSB2YWxvcmVzIGV4dHJlbW9zLiAoTWVkaWRhIHJvYnVzdGEpLg0KDQogICAgICAgIC0gICBMYSBtZWRpYW5hIHNpZW1wcmUgZXMgw7puaWNhLg0KDQogICAgICAgIC0gICBQdWVkZSBvIG5vIHNlciB1biB2YWxvciBkZW50cm8gZGVsIGNvbmp1bnRvIGRlIGRhdG9zLg0KDQogICAgLSAgIExhIG1vZGEgY29ycmVzcG9uZGUgYWwgZGF0byBjb24gbWF5b3IgZnJlY3VlbmNpYSBhYnNvbHV0YSAoZWwgcXVlIG3DoXMgc2UgcmVwaXRlKS4gTm8gbmVjZXNhcmlhbWVudGUgZXMgw7puaWNhLiBTaSB1biBjb25qdW50byBkZSBkYXRvcyB0aWVuZSB1bmEgw7puaWNhIG1vZGEgZW50b25jZXMgc2UgZGVub21pbmEgdW5pbW9kYWwuIFNpIGxhIG1vZGEgc2UgYWxjYW56YSBlbiBkb3MgdmFsb3JlcyBkaWZlcmVudGVzLCBlbCBjb25qdW50byByZWNpYmUgZWwgbm9tYnJlIGRlIGJpbW9kYWwuIFNpIGhheSAzIG8gbcOhcyBtb2RhcywgbG9zIGRhdG9zIHNlIHJlZmVyZW5jaWFuIGNvbW8gbXVsdGltb2RhbGVzLg0KDQogICAgICAgIC0gICBObyBlcyB1bmEgbWVkaWRhIGRlIHRlbmRlbmNpYSBjZW50cmFsIGRlIMO6bmljbyB2YWxvci4NCg0KICAgICAgICAtICAgTm8gc2UgYWZlY3RhIHBvciB2YWxvcmVzIGV4dHJlbW9zLg0KDQogICAgICAgIC0gICBTaWVtcHJlIGVzIHVuIHZhbG9yIGRlbCBjb25qdW50byBkZSBkYXRvcy4NCg0KICAgIExhcyBmdW5jaW9uZXMgYG1lYW4oKWAsIGBtZWRpYW4oKWAgeSBgbWZ2KClgIGRlIFIgcmVhbGl6YW4gZXN0b3MgY8OhbGN1bG9zLiBQYXJhIHVzYXIgZWwgY29tYW5kbyBkZSBsYSBtb2RhIGVzIG5lY2VzYXJpbyBpbnN0YWxhciBlbCBwYXF1ZXRlICptb2RlZXN0Kg0KDQpgYGB7cn0NCmluc3RhbGwucGFja2FnZXMoIm1vZGVlc3QiKQ0KYGBgDQoNCmBgYHtyfQ0KbGlicmFyeShtb2RlZXN0KQ0KYGBgDQoNCmBgYHtyfQ0KbWVhbihnYXJtZW50c193b3JrZXJfcHJvZHVjdGl2aXR5JGFjdHVhbF9wcm9kdWN0aXZpdHkpDQpgYGANCg0KYGBge3J9DQptZWRpYW4oZ2FybWVudHNfd29ya2VyX3Byb2R1Y3Rpdml0eSRhY3R1YWxfcHJvZHVjdGl2aXR5KQ0KYGBgDQoNCmBgYHtyfQ0KbWVhbihnYXJtZW50c193b3JrZXJfcHJvZHVjdGl2aXR5JGFjdHVhbF9wcm9kdWN0aXZpdHksIHRyaW0gPSAwLjIpDQpgYGANCg0KKipBbsOhbGlzaXMgZGUgUHJvZHVjdGl2aWRhZCBlbiBsYSBJbmR1c3RyaWEgVGV4dGlsKioNCg0KRW4gZWwgc2VjdG9yIGRlIGNvbmZlY2Npb25lcywgbGEgcHJvZHVjdGl2aWRhZCByZWFsIHByb21lZGlvICgqWMyEKikgYWxjYW56YSAqKjAuNzIqKiAoc29icmUgdW4gbcOheGltbyBkZSAxLjApLCBzaWVuZG8gKiowLjgwKiogZWwgdmFsb3IgbcOhcyBmcmVjdWVudGUgKE1vZGEpIHkgKiowLjc1KiogbGEgbWVkaWFuYSAoKk1lKikuIFBhcmEgcmVkdWNpciBlbCBlZmVjdG8gZGUgdmFsb3JlcyBleHRyZW1vcywgbGEgbWVkaWEgcmVjb3J0YWRhIGFsIDIwJSBlcyBkZSAqKjAuNzMqKiwgbG8gcXVlIGluZGljYSB1bmEgZGlzdHJpYnVjacOzbiBsaWdlcmFtZW50ZSBhc2ltw6l0cmljYSBoYWNpYSB2YWxvcmVzIGJham9zLg0KDQoqKk5vdGFjacOzbiBlc3RhZMOtc3RpY2E6KioNCg0KLSAgICpYzIQqOiBNZWRpYSBtdWVzdHJhbCAodXNhZGEgYXF1w60sIHB1ZXMgbG9zIGRhdG9zIHJlcHJlc2VudGFuIHVuYSBtdWVzdHJhIGRlIHByb2R1Y2Npw7NuKQ0KDQotICAgKs68KjogTWVkaWEgcG9ibGFjaW9uYWwgKG5vIGFwbGljYSBlbiBlc3RlIGNhc28pDQoNCjIuICAqKlBvc2ljacOzbioqwqBEaXZpZGVuIHVuYSBkaXN0cmlidWNpw7NuIGRlIGZyZWN1ZW5jaWFzIG8gY29uanVudG8gZGUgZGF0b3MgZW4gcGFydGVzIGlndWFsZXMgKGVuIHTDqXJtaW5vcyBkZSBwcm9wb3JjacOzbiBjb250ZW5pZGEgZW4gY2FkYSBwYXJ0ZSkuIEFkZW3DoXMgcGVybWl0ZW4gbG9jYWxpemFyIGxhIGRpc3RyaWJ1Y2nDs24gZGUgbG9zIGRhdG9zIHNvYnJlIGVsIGVqZSBob3Jpem9udGFsLg0KDQp5IHNlIGNhbGN1bGFuIGNvbiBsYSBmdW5jacOzbsKgYHF1YW50aWxlKClgwqBxdWUsIGFkZW3DoXMsIHByb3BvcmNpb25hIGxvcyB2YWxvcmVzIG3DrW5pbW8geSBtw6F4aW1vIGRlbCBjb25qdW50by4NCg0KYGBge3J9DQpxdWFudGlsZShnYXJtZW50c193b3JrZXJfcHJvZHVjdGl2aXR5JG5vX29mX3dvcmtlcnMpICNwcm9wb3JjaW9uYSBsb3MgdmFsb3JlcyBtw61uaW1vIHkgbcOheGltbyBkZWwgY29uanVudG8uDQpgYGANCg0KRWwgYW7DoWxpc2lzIGRlIGN1YXJ0aWxlcyByZXZlbGEgcXVlIGVsIDI1JSBkZSBsb3MgZXF1aXBvcyBkZSBwcm9kdWNjacOzbiB0ZXh0aWxlcyBvcGVyYW4gY29uwqAqKjIzIHRyYWJhamFkb3JlcyBvIG1lbm9zKiosIG1pZW50cmFzIHF1ZSBsb3MgZXF1aXBvcyBjb27CoCoqbcOhcyBkZSAzMSB0cmFiYWphZG9yZXMqKsKgcGVydGVuZWNlbiBhbCBjdWFydGlsIHN1cGVyaW9yICgyNSUgZGUgZXF1aXBvcyBtw6FzIGdyYW5kZXMpLiBFc3RvIGluZGljYSB1bmEgZGlzdHJpYnVjacOzbiBoZXRlcm9nw6luZWEgZW4gZWwgdGFtYcOxbyBkZSBsb3MgZXF1aXBvcywgZG9uZGUgbGEgbWF5b3LDrWEgKDUwJSBjZW50cmFsKSB0cmFiYWphIGNvbiBlbnRyZSAyNCB5IDMxIG9wZXJhcmlvcy4NCg0KYGBge3J9DQpxdWFudGlsZShnYXJtZW50c193b3JrZXJfcHJvZHVjdGl2aXR5JG5vX29mX3dvcmtlcnMsIGMoMC4xLDAuMjYsMC43OCkpDQpgYGANCg0KRWwgY29tYW5kb8KgYHN1bW1hcnkoKWDCoGNhbGN1bGEgc2ltdWx0w6FuZWFtZW50ZSBsYSBtZWRpYSwgbG9zIGN1YXJ0aWxlcywgZWwgbcOheGltbyB5IGVsIG3DrW5pbW8gZGUgbGFzIHZhcmlhYmxlcyBlc2NhbGFyZXMgeSBsYSBmcmVjdWVuY2lhIHBvciBjYXRlZ29yw61hIGRlIGxhcyB2YXJpYWJsZXMgY2F0ZWfDs3JpY2FzDQoNCmBgYHtyfQ0KZ2FybWVudHNfd29ya2VyX3Byb2R1Y3Rpdml0eSAlPiUgc2VsZWN0KHRlYW0pICU+JSBzdW1tYXJ5KCkgI2NhbGN1bGEgc2ltdWx0w6FuZWFtZW50ZSBsYSBtZWRpYSwgbG9zIGN1YXJ0aWxlcywgZWwgbcOheGltbyB5IGVsIG3DrW5pbW8gZGUgbGFzIHZhcmlhYmxlcyBlc2NhbGFyZXMgeSBsYSBmcmVjdWVuY2lhIHBvciBjYXRlZ29yw61hIGRlIGxhcyB2YXJpYWJsZXMgY2F0ZWfDs3JpY2FzDQpgYGANCg0KYGBge3J9DQpnYXJtZW50c193b3JrZXJfcHJvZHVjdGl2aXR5ICU+JSBzZWxlY3Qod2lwKSAlPiUgc3VtbWFyeSgpDQpgYGANCg0KUHVlZGUgYXBsaWNhcnNlIGFsIGNvbmp1bnRvIGNvbXBsZXRvIHkgc2Ugb2J0aWVuZSBlbCByZXN1bWVuIGRlIHRvZGFzIGxhcyBjb2x1bW5hcw0KDQpgYGB7cn0NCmdhcm1lbnRzX3dvcmtlcl9wcm9kdWN0aXZpdHkgJT4lIHN1bW1hcnkoKSAjc2Ugb2J0aWVuZSBlbCByZXN1bWVuIGRlIHRvZGFzIGxhcyBjb2x1bW5hcw0KYGBgDQoNCioqTm90YSoqwqBBbCBjb21lbnphciBsYSBleHBsb3JhY2nDs24gZGUgdW4gY29uanVudG8gZGUgZGF0b3MsIHVubyBkZSBsb3MgcHJpbWVyb3MgcGFzb3MgZXMgcmVhbGl6YXIgeSBhbmFsaXphciBlbCByZXN1bWVuIGRlIHZhcmlhYmxlcyBwYXJhIGRldGVjdGFyIHByb2JsZW1hcyBkZSBjYWxpZGFkIHkgdHJhdGFybG9zIGFudGVzIGRlIGhhY2VyIGPDoWxjdWxvcyBtw6FzIGVzcGVjw61maWNvcy4NCg0KMy4gICoqRGlzcGVyc2nDs24qKiBDdWFudGlmaWNhbiBsYSB2YXJpYWJpbGlkYWQgZGUgbG9zIGRhdG9zIHkgZGV0ZXJtaW5hbiBxdcOpIHRhbiBhbGVqYWRhIGVzdMOhIGxhIGRpc3RyaWJ1Y2nDs24gZGUgbG9zIGRhdG9zIGNvbiByZXNwZWN0byBhIHVuIHB1bnRvIGRlIHJlZmVyZW5jaWEgY29tbywgcG9yIGVqZW1wbG8sIGxhIG1lZGlhLg0KDQotICAgKipSYW5nbyoqIEVzIGxhIGRpZmVyZW5jaWEgZW50cmUgZWwgbcOheGltbyB5IGVsIG3DrW5pbW8gZGUgbG9zIGRhdG9zIHkgY3VhbnRpZmljYSBsYSBleHRlbnNpw7NuIHRvdGFsIGRlbCBjb25qdW50by4gRW4gUiwgbGEgZnVuY2nDs24gYHJhbmdlKClgIGRhIGxvcyB2YWxvcmVzIGRlbCBtw6F4aW1vIHkgZGVsIG3DrW5pbW8NCg0KICAgIFJhbmdvPW1heOKIkm1pbg0KDQpgYGB7cn0NCnJhbmdlKGdhcm1lbnRzX3dvcmtlcl9wcm9kdWN0aXZpdHkkdGVhbSkNCmBgYA0KDQotICAgKipSYW5nbyBpbnRlcmN1YXJ0w61saWNvKiogU2UgZGVmaW5lIGNvbW8gZWwgZXNwYWNpbyBxdWUgb2N1cGEgZWwgNTAlIGNlbnRyYWwgZGUgbGEgZGlzdHJpYnVjacOzbiBkZSBsb3MgZGF0b3MgeSBzZSBjYWxjdWxhIGNvbW8NCg0KICAgIElRUj1SSUM9UTPiiJJRMUlRUj1SSUM9UTPiiJJRMQ0KDQogICAgRXMgdW5hIG1lZGlkYSByb2J1c3RhIGFudGUgbGEgcHJlc2VuY2lhIGRlIGRhdG9zIGF0w61waWNvcyB5IHN1ZWxlIGVtcGxlYXJzZSBjb21vIG1lZGlkYSBkZSBkaXNwZXJzacOzbiBjdWFuZG8gbGEgbWVkaWRhIGRlIHRlbmRlbmNpYSBjZW50cmFsIGVzY29naWRhIGVzIGxhIG1lZGlhbmEuDQoNCmBgYHtyfQ0KSVFSKGdhcm1lbnRzX3dvcmtlcl9wcm9kdWN0aXZpdHkkdGVhbSkNCmBgYA0KDQplc3RvIG5vcyBtdWVzdHJhICoqbGEgRGlzdHJpYnVjacOzbiBkZSBlcXVpcG9zKio6IEVsIDUwJSBjZW50cmFsIGRlIGxvcyBlcXVpcG9zIGRlIHByb2R1Y2Npw7NuIChlbnRyZSBlbCBRMSB5IFEzKSBlc3TDoSBkaXN0cmlidWlkbyBlbiB1biByYW5nbyBkZSAqKjYgZXF1aXBvcyBudW3DqXJpY29zKiogKGVqOiBzaSBRMT1FcXVpcG8zIHkgUTM9RXF1aXBvOSwgbGEgZGlmZXJlbmNpYSBlcyA2KS4NCg0KYGBge3J9DQp2YXIoZ2FybWVudHNfd29ya2VyX3Byb2R1Y3Rpdml0eSRub19vZl93b3JrZXJzKQ0KYGBgDQoNCkxhIHZhcmlhbnphIGRlIDQ5Mi43MzczIGVuIGVsIG7Dum1lcm8gZGUgdHJhYmFqYWRvcmVzIHBvciBlcXVpcG8gaW5kaWNhIHVuYSBhbHRhIHZhcmlhYmlsaWRhZCBlbiBsb3MgdGFtYcOxb3MgZGUgbG9zIGVxdWlwb3MgZGUgcHJvZHVjY2nDs24uIEVzdG8gc2lnbmlmaWNhIHF1ZSBsYSBjYW50aWRhZCBkZSB0cmFiYWphZG9yZXMgZGlmaWVyZSBzaWduaWZpY2F0aXZhbWVudGUgZW50cmUgZXF1aXBvcywgY29uIHVuYSBkZXN2aWFjacOzbiB0w61waWNhIGRlIGFwcm94aW1hZGFtZW50ZSDCsTIyIHRyYWJhamFkb3JlcyByZXNwZWN0byBhbCBwcm9tZWRpby4NCg0KYGBge3J9DQpzZChnYXJtZW50c193b3JrZXJfcHJvZHVjdGl2aXR5JGFjdHVhbF9wcm9kdWN0aXZpdHkpDQpgYGANCg0KTGEgZGVzdmlhY2nDs24gZXN0w6FuZGFyIGRlIDAuMTc0IGVuIGxhIHByb2R1Y3RpdmlkYWQgcmVhbCAoYWN0dWFsX3Byb2R1Y3Rpdml0eSkgbXVlc3RyYSBxdWUgbG9zIGVxdWlwb3MgdGV4dGlsZXMgb3BlcmFuIGNvbiB1bmEgY29uc2lzdGVuY2lhIG5vdGFibGUuIEVzdG8gc2lnbmlmaWNhIHF1ZSBsYSBtYXlvcsOtYSBkZSBsb3MgZXF1aXBvcyAoYWxyZWRlZG9yIGRlbCA2OCUpIG1hbnRpZW5lbiBuaXZlbGVzIGRlIHByb2R1Y3RpdmlkYWQgZW50cmUgMC41NSB5IDAuODkgY3VhbmRvIGNvbnNpZGVyYW1vcyBlbCBwcm9tZWRpbyBkZSAwLjcyLg0KDQpgYGB7cn0NCiBza2V3KGdhcm1lbnRzX3dvcmtlcl9wcm9kdWN0aXZpdHkkbm9fb2Zfd29ya2VycykNCmBgYA0KDQpFbCBzZXNnbyBkZSAtMC4xMSBlbiBlbCBuw7ptZXJvIGRlIHRyYWJhamFkb3JlcyBwb3IgZXF1aXBvIGluZGljYSB1bmEgZGlzdHJpYnVjacOzbiBjYXNpIHNpbcOpdHJpY2EsIGNvbiB1bmEgbGlnZXJhIHRlbmRlbmNpYSBhIHRlbmVyIG3DoXMgZXF1aXBvcyBncmFuZGVzIHF1ZSBwZXF1ZcOxb3MuIEVzdG8gbXVlc3RyYSBxdWUgbGEgYXNpZ25hY2nDs24gZGUgcGVyc29uYWwgZXMgYmFzdGFudGUgZXF1aWxpYnJhZGEgZW4gbGEgZsOhYnJpY2EsIHNpbiBlcXVpcG9zIGV4dHJlbW9zIHF1ZSBkaXN0b3JzaW9uZW4gbGEgZGlzdHJpYnVjacOzbi4gRWwgdmFsb3IgY2VyY2FubyBhIGNlcm8gcGVybWl0ZSBhbmFsaXphciBlc3RvcyBkYXRvcyBzaW4gbmVjZXNpZGFkIGRlIGFqdXN0ZXMgZXN0YWTDrXN0aWNvcyBjb21wbGVqb3MuDQoNCmBgYHtyfQ0KIGt1cnRvc2koZ2FybWVudHNfd29ya2VyX3Byb2R1Y3Rpdml0eSR0ZWFtKQ0KYGBgDQoNCkxhIGZ1bmNpw7NuwqBgZGVzY3JpYmUoKWDCoGRlbCBwYXF1ZXRlwqBgcHN5Y2hgwqBoYWNlIHVuIHJlc3VtZW4gZGVzY3JpcHRpdm8gbcOhcyBhbXBsaW8gZGUgdW5hIHZhcmlhYmxlIGVzY2FsYXI6DQoNCmBgYHtyfQ0KZGVzY3JpYmUoZ2FybWVudHNfd29ya2VyX3Byb2R1Y3Rpdml0eSR0ZWFtLCBJUVI9VFJVRSwgcXVhbnQgPSBjKC4yNSwgLjUsIC43NSkpIA0KYGBgDQoNCiMjICoqR3LDoWZpY29zIGRlc2NyaXB0aXZvcyAodmFyaWFibGVzIGVzY2FsYXJlcykqKg0KDQoqKkRpc3RyaWJ1Y2nDs24gZGUgZnJlY3VlbmNpYXMuKiogRXMgbGEgYWdydXBhY2nDs24gZGUgZGF0b3MgZW4gY2F0ZWdvcsOtYXMgbXV0dWFtZW50ZSBleGNsdXllbnRlcyBxdWUgaW5kaWNhIGVsIG7Dum1lcm8gZGUgb2JzZXJ2YWNpb25lcyBlbiBjYWRhIGNhdGVnb3LDrWEgbyBjbGFzZS4gQ29uc3RydWlyIGxhIHRhYmxhIGRlIGZyZWN1ZW5jaWFzIHJlcXVpZXJlIGxhIGZ1bmNpw7NuIGBmZHQoKWAgZGVsIHBhcXVldGUgYGZkdGhgDQoNCmBgYHtyfQ0KIGluc3RhbGwucGFja2FnZXMoImZkdGgiKQ0KYGBgDQoNCmBgYHtyfQ0KIGxpYnJhcnkoZmR0aCkNCmBgYA0KDQpgYGB7cn0NClRhYmxhX2ZyZWMgPC0gZmR0KGdhcm1lbnRzX3dvcmtlcl9wcm9kdWN0aXZpdHkkYWN0dWFsX3Byb2R1Y3Rpdml0eSwgYnJlYWtzID0gIlN0dXJnZXMiKSAjU2UgZW1wbGVhIGVsIG3DqXRvZG8gZGUgU3R1cmdlcyBwYXJhIGNhbGN1bGFyIGxhIGNhbnRpZGFkIGRlIGNsYXNlcyAoYmlucykNCiAgVGFibGFfZnJlYw0KYGBgDQoNCjEuICAqKkhpc3RvZ3JhbWEqKsKgZXMgdW5hIHJlcHJlc2VudGFjacOzbiBncsOhZmljYSBkZSBsYSBkaXN0cmlidWNpw7NuIGRlIGZyZWN1ZW5jaWFzIGRlIHVuYSB2YXJpYWJsZSBlbiBsYSBxdWUgc2Ugb2JzZXJ2YW4gY29tcG9ydGFtaWVudG9zIGRlIGZvcm1hLCBkaXNwZXJzacOzbiB5IHRlbmRlbmNpYSBjZW50cmFsLlwNCiAgICBFbiBlbCBwYXF1ZXRlIGLDoXNpY28gcXVlIHRyYWUgUiBlc3TDoSBsYSBmdW5jacOzbsKgYGhpc3QoKWDCoHF1ZSBwZXJtaXRlIHRyYXphciBlbCBoaXN0b2dyYW1hIGRlbCBjb25qdW50byBkZSBkYXRvczsgc2luIGVtYmFyZ28sIGFxdcOtIHZhbW9zIGEgdXNhciBlbCBlbnRvcm5vIGdyw6FmaWNvIGRlIFIgcXVlIHByb3ZlZSBlbCBwYXF1ZXRlwqBgZ2dwbG90MmDCoGluY2x1aWRvIGVuwqBgdGlkeXZlcnNlYA0KDQpgYGB7cn0NCmdhcm1lbnRzX3dvcmtlcl9wcm9kdWN0aXZpdHkgICU+JSBnZ3Bsb3QoYWVzKHggPSBhY3R1YWxfcHJvZHVjdGl2aXR5KSkgKw0KICBnZW9tX2hpc3RvZ3JhbShmaWxsID0gIiNGRjlBQTIiLCBjb2xvciA9ICIjRkZEQUMxIiwgYmlucyA9IDMwKSArDQogIGdndGl0bGUoIkhpc3RvZ3JhbWEgZGUgUHJvZHVjdGl2aWRhZCBSZWFsIikgKw0KICBsYWJzKHggPSAiUHJvZHVjdGl2aWRhZCBSZWFsIiwgeSA9ICJGcmVjdWVuY2lhIikgKw0KICB0aGVtZV9taW5pbWFsKCkNCg0KYGBgDQoNCmBgYHtyfQ0KZ2dwbG90KGdhcm1lbnRzX3dvcmtlcl9wcm9kdWN0aXZpdHksIGFlcyh4ID0gbm9fb2Zfd29ya2VycywgeSA9IC4uZGVuc2l0eS4uKSkgKw0KICBnZW9tX2hpc3RvZ3JhbShmaWxsID0gIiNCNUVBRDciLCAgIyBWZXJkZSBtZW50YQ0KICAgICAgICAgICAgICAgICBjb2xvciA9ICJibGFjayIsDQogICAgICAgICAgICAgICAgIGJpbnMgPSAxNSkgKw0KICBnZW9tX2xpbmUoYWVzKHggPSBub19vZl93b3JrZXJzLA0KICAgICAgICAgICAgICAgIHkgPSBkbm9ybShub19vZl93b3JrZXJzLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgbWVhbihub19vZl93b3JrZXJzLCBuYS5ybSA9IFRSVUUpLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgc2Qobm9fb2Zfd29ya2VycywgbmEucm0gPSBUUlVFKSkpLA0KICAgICAgICAgICAgY29sb3IgPSAiIzgzMzhFQyIsICAgICAgIyBQw7pycHVyYQ0KICAgICAgICAgICAgbGluZXdpZHRoID0gMS4yKSArDQogIGdndGl0bGUoIkRpc3RyaWJ1Y2nDs24gZGVsIE7Dum1lcm8gZGUgVHJhYmFqYWRvcmVzIikgKw0KICBsYWJzKHggPSAiTsO6bWVybyBkZSB0cmFiYWphZG9yZXMiLCB5ID0gIkRlbnNpZGFkIikgKw0KICB0aGVtZV9taW5pbWFsKCkNCmBgYA0KDQpFc3RlIGdyw6FmaWNvIG11ZXN0cmEgbGEgZGlzdHJpYnVjacOzbiBkZWwgbsO6bWVybyBkZSB0cmFiYWphZG9yZXMgcG9yIGVxdWlwbyBtZWRpYW50ZSB1biBoaXN0b2dyYW1hIGF6dWwgY2xhcm8gc3VwZXJwdWVzdG8gY29uIHVuYSBjdXJ2YSBub3JtYWwgbW9yYWRhLiBDb21wYXJhIGxvcyBkYXRvcyByZWFsZXMgY29uIHVuYSBkaXN0cmlidWNpw7NuIHRlw7NyaWNhIG5vcm1hbCwgdXNhbmRvIGxhIG1lZGlhIHkgZGVzdmlhY2nDs24gZXN0w6FuZGFyIHJlYWxlcy4NCg0KYGBge3J9DQpnYXJtZW50c193b3JrZXJfcHJvZHVjdGl2aXR5ICU+JQ0KICBnZ3Bsb3QoYWVzKHggPSBhY3R1YWxfcHJvZHVjdGl2aXR5LCB5ID0gLi5kZW5zaXR5Li4pKSArDQogIGdlb21faGlzdG9ncmFtKA0KICAgIGZpbGwgPSAiIzREQjhENSIsDQogICAgY29sb3IgPSAiYmxhY2siLA0KICAgIGJpbnMgPSAxNSwNCiAgICBhbHBoYSA9IDAuNw0KICApICsNCiAgZ2VvbV9saW5lKA0KICAgIGFlcygNCiAgICAgIHggPSBhY3R1YWxfcHJvZHVjdGl2aXR5LA0KICAgICAgeSA9IGRub3JtKGFjdHVhbF9wcm9kdWN0aXZpdHksDQogICAgICAgICAgICAgICAgbWVhbihhY3R1YWxfcHJvZHVjdGl2aXR5LCBuYS5ybSA9IFRSVUUpLA0KICAgICAgICAgICAgICAgIHNkKGFjdHVhbF9wcm9kdWN0aXZpdHksIG5hLnJtID0gVFJVRSkpDQogICAgKSwNCiAgICBjb2xvciA9ICIjRTc0QzNDIiwNCiAgICBsaW5ld2lkdGggPSAxLjINCiAgKSArDQogIGdndGl0bGUoIkRpc3RyaWJ1Y2nDs24gZGUgUHJvZHVjdGl2aWRhZCBwb3IgRGVwYXJ0YW1lbnRvIikgKw0KICBsYWJzKHggPSAiUHJvZHVjdGl2aWRhZCBSZWFsIiwgeSA9ICJEZW5zaWRhZCIpICsNCiAgZmFjZXRfd3JhcCh+ZGVwYXJ0bWVudCkgKyAgIyBkZXBhcnRtZW50IGVzIGNhdGVnw7NyaWNvLCBwZXJvIGVsIGVqZSBYIGVzIG51bcOpcmljbw0KICB0aGVtZV9taW5pbWFsKCkNCmBgYA0KDQpFc3RlIGdyw6FmaWNvIGRlIGRlbnNpZGFkIGNvbXBhcmEgbGEgZGlzdHJpYnVjacOzbiBkZSBsYSBwcm9kdWN0aXZpZGFkIHJlYWwgZW50cmUgbG9zIGRlcGFydGFtZW50b3MgZGUgcHJvZHVjY2nDs24gdGV4dGlsIG1lZGlhbnRlIGhpc3RvZ3JhbWFzIHkgY3VydmFzIG5vcm1hbGVzLiBDYWRhIHBhbmVsIG11ZXN0cmEgdW4gZGVwYXJ0YW1lbnRvIGRpZmVyZW50ZSwgZG9uZGUgbGFzIGJhcnJhcyBhenVsZXMgdHJhbnNwYXJlbnRlcyByZXByZXNlbnRhbiBsYSBmcmVjdWVuY2lhIHJlYWwgZGUgbG9zIG5pdmVsZXMgZGUgcHJvZHVjdGl2aWRhZCwgYWdydXBhZG9zIGVuIDE1IGludGVydmFsb3MsIG1pZW50cmFzIHF1ZSBsYSBsw61uZWEgcm9qYSB0cmF6YSBsYSBjdXJ2YSBkZSBkaXN0cmlidWNpw7NuIG5vcm1hbCB0ZcOzcmljYSBjYWxjdWxhZGEgYSBwYXJ0aXIgZGUgbGEgbWVkaWEgeSBkZXN2aWFjacOzbiBlc3TDoW5kYXIgZGUgY2FkYSBkZXBhcnRhbWVudG8uwqANCg0KYGBge3J9DQpkaWFncmFtYV9wcm9kdWN0aXZpZGFkIDwtIGJveHBsb3QoZ2FybWVudHNfd29ya2VyX3Byb2R1Y3Rpdml0eSRhY3R1YWxfcHJvZHVjdGl2aXR5LCBob3Jpem9udGFsID0gVFJVRSkNCmBgYA0KDQpFbCBlc3BhY2lvIGVudHJlIGxhIG1lZGlhbmEgKGzDrW5lYSBncnVlc2EgZGVudHJvIGRlIGxhIGNhamEpIHkgZWwgbcOtbmltbyBlcyBtw6FzIHBlcXVlw7FvIHF1ZSBlbnRyZSBsYSBtZWRpYW5hIHkgZWwgbcOheGltbzsgZXMgZGVjaXIsIGVsIHByaW1lciA1MCUgZGUgbG9zIGRhdG9zIGVzIG1lbm9zIGRpc3BlcnNvIChtw6FzIGFncnVwYWRvKSBxdWUgZWwgc2VndW5kby4gRGVudHJvIGRlIGxhIGNhamEsIGxhIGRpdmlzacOzbiBlc3TDoSBtw6FzIGNlcmNhIGRlbCBib3JkZSBpbmZlcmlvciAoY3VhcnRpbCAxKSBxdWUgZGVsIHN1cGVyaW9yIChjdWFydGlsIDMpIHksIHBvciB0YW50bywgc2UgY29uY2x1eWUgcXVlIGVsIHByaW1lciAyNSUgY2VudHJhbCBkZSBsb3MgZGF0b3MgZXMgbWVub3MgZGlzcGVyc28gcXVlIGVsIHNlZ3VuZG8gMjUlIGNlbnRyYWwuIEFkZW3DoXMsIGVzIGNsYXJvIHF1ZSBsYSBjb2xhIGRlcmVjaGEgKHN1cGVyaW9yKSBlcyBtw6FzIGxhcmdhIHF1ZSBsYSBpenF1aWVyZGEgKGluZmVyaW9yKSBkZSBkb25kZSBzZSBpbmZpZXJlIHF1ZSBsb3MgZGF0b3MgdGllbmVuIGFzaW1ldHLDrWEgcG9zaXRpdmEuXA0KUG9yIG90cm8gbGFkbywgZW4gbGEgY29sYSBkZXJlY2hhIGhheSBwcmVzZW5jaWEgZGUgZGF0b3MgYXTDrXBpY29zIChzb24gYm9saXRhcykgeSBwYXJhIGluc3BlY2Npb25hcmxvcyBlcyBuZWNlc2FyaW8gZXhwbG9yYXIgZWwgZWxlbWVudG8gZW4gZWwgcXVlIHNlIGd1YXJkw7MgZWwgYm94cGxvdCBjb24gZWwgc8OtbWJvbG/CoGAkYA0KDQpgYGB7cn0NCmhlYWQoZGlhZ3JhbWFfcHJvZHVjdGl2aWRhZCRvdXQsIDIwKQ0KYGBgDQoNCmBgYHtyfQ0KZGlhZ3JhbWFfcHJvZHVjdGl2aWRhZCRzdGF0cw0KYGBgDQoNCkNvbiBsYSBmdW5jacOzbsKgYGxlbmd0aCgpYMKgZXMgcG9zaWJsZSBjb250YXIgbGEgY2FudGlkYWQgZGUgb3V0bGllcnMgZGV0ZWN0YWRvcw0KDQpgYGB7cn0NCmxlbmd0aChkaWFncmFtYV9wcm9kdWN0aXZpZGFkJG91dCkNCmBgYA0KDQojIyAqKkVzdGFkw61zdGljYSBkZXNjcmlwdGl2YSAodmFyaWFibGVzIGN1YWxpdGF0aXZhcykqKg0KDQpFbiBlbCBjYXNvIGN1YWxpdGF0aXZvIGxhIGNhbnRpZGFkIGRlIGPDoWxjdWxvcyBxdWUgc2UgcHVlZGVuIGhhY2VyIHNlIHJlZHVjZSBhIGhhbGxhciBsYXMgZnJlY3VlbmNpYXMgYWJzb2x1dGFzIHkgcmVsYXRpdmFzIGRlIGxhcyBjYXRlZ29yw61hcyBkZSBsYSB2YXJpYWJsZS4gUGFyYSBjb25zdHJ1aXIgbGEgdGFibGEgZGUgZnJlY3VlbmNpYXMgc2UgZW1wbGVhIGxhIGZ1bmNpw7NuIGB0YWJsZSgpYCBkZWwgcGFxdWV0ZSBiw6FzaWNvIGRlIFIuDQoNCmBgYHtyfQ0KVGFibGFfRGVwYXJ0YW1lbnRvIDwtIHRhYmxlKGdhcm1lbnRzX3dvcmtlcl9wcm9kdWN0aXZpdHkkZGVwYXJ0bWVudCkNClRhYmxhX0RlcGFydGFtZW50bw0KYGBgDQoNCkVsIGRlcGFydGFtZW50byBkZSAiZmluaXNoaW5nIiAoYWNhYmFkb3MpIGFwYXJlY2UgcmVnaXN0cmFkbyAyNDkgdmVjZXMsIG1pZW50cmFzIHF1ZSBoYXkgMjU3IHJlZ2lzdHJvcyBwYXJhICJmaW5pc2hpbmciIChwb3NpYmxlbWVudGUgY29uIHVuIGVzcGFjaW8gYWRpY2lvbmFsKSB5IDY5MSBwYXJhICJzd2VpbmciIChjb3N0dXJhKS4gRXN0byByZXZlbGEgdW5hIGRpc3RyaWJ1Y2nDs24gZGVzaWd1YWwsIGRvbmRlIGVsIMOhcmVhIGRlIGNvc3R1cmEgdGllbmUgY2FzaSBlbCB0cmlwbGUgZGUgZXF1aXBvcyBxdWUgY2FkYSB2ZXJzacOzbiBkZWwgZGVwYXJ0YW1lbnRvIGRlIGFjYWJhZG9zLg0KDQpQYXJhIGNvbnN0cnVpciBsYSB0YWJsYSBkZSBmcmVjdWVuY2lhcyByZWxhdGl2YXMgKHBvcmNlbnRhamUpIHNlIHVzYSBsYSBmdW5jacOzbsKgYHByb3AudGFibGUoKWDCoGFwbGljYWRhIHNvYnJlIHVuYSB0YWJsYSBkZSBmcmVjdWVuY2lhcyBhYnNvbHV0YXM6DQoNCmBgYHtyfQ0KcHJvcC50YWJsZShUYWJsYV9EZXBhcnRhbWVudG8pDQpgYGANCg0KRWwgZGVwYXJ0YW1lbnRvIGRlwqAqKiJmaW5pc2hpbmciIChhY2FiYWRvcykqKsKgcmVwcmVzZW50YcKgKioyMC44JSoqwqAocHJpbWVyYSBlbnRyYWRhKSB5wqAqKjIxLjQ3JSoqwqAoc2VndW5kYSBlbnRyYWRhKSBkZSBsb3MgZXF1aXBvcywgbWllbnRyYXMgcXVlwqAqKiJzd2VpbmciIChjb3N0dXJhKSoqwqBjb25jZW50cmHCoCoqNTcuNzMlKirCoGRlbCB0b3RhbC4gTGEgZGlmZXJlbmNpYSBlbnRyZSBsYXMgZG9zIGNhdGVnb3LDrWFzIGRlICJmaW5pc2hpbmciICgyMC44JSB2cyAyMS40NyUpIGNvbmZpcm1hIGluY29uc2lzdGVuY2lhcyBlbiBsb3MgZGF0b3MsIHByb2JhYmxlbWVudGUgcG9yIGVycm9yZXMgZGUgZXNjcml0dXJhIChjb21vIGVzcGFjaW9zIGFkaWNpb25hbGVzKS4NCg0KYGBge3J9DQpyb3VuZChwcm9wLnRhYmxlKFRhYmxhX0RlcGFydGFtZW50byksIGRpZ2l0cz00KQ0KYGBgDQoNCkVsIGdyw6FmaWNvIGRlIGJhcnJhcyBtdWVzdHJhIGxhIGRpc3RyaWJ1Y2nDs24gZGUgcmVnaXN0cm9zIGRlIHByb2R1Y3RpdmlkYWQgcG9yIHRyaW1lc3RyZSwgZG9uZGUgY2FkYSBiYXJyYSB2ZXJ0aWNhbCBlbiB0b25vIGF6dWwgY2xhcm8gcmVwcmVzZW50YSBsYSBjYW50aWRhZCBkZSBlcXVpcG9zIG8gbWVkaWNpb25lcyByZWFsaXphZGFzIGVuIGNhZGEgcGVyaW9kby4gRWwgZWplIFggbXVlc3RyYSBsb3MgdHJpbWVzdHJlcyAoUXVhcnRlcjEsIFF1YXJ0ZXIyLCBldGMuKSBjb24gbGFzIGV0aXF1ZXRhcyBsaWdlcmFtZW50ZSBpbmNsaW5hZGFzIHBhcmEgbWVqb3IgdmlzdWFsaXphY2nDs24sIG1pZW50cmFzIGVsIGVqZSBZIGluZGljYSBlbCBjb250ZW8gYWJzb2x1dG8gZGUgcmVnaXN0cm9zLg0KDQpgYGB7cn0NCmdhcm1lbnRzX3dvcmtlcl9wcm9kdWN0aXZpdHkgJT4lIA0KICBnZ3Bsb3QoYWVzKHggPSBxdWFydGVyKSkgKw0KICBnZW9tX2Jhcihjb2xvciA9ICJibGFjayIsIGZpbGwgPSAibGlnaHRibHVlIikgKw0KICBnZ3RpdGxlKCJEaXN0cmlidWNpw7NuIHBvciBUcmltZXN0cmUiKSArDQogIGxhYnMoeCA9ICJUcmltZXN0cmUiLCB5ID0gIkNvbnRlbyIpICsNCiAgdGhlbWVfbWluaW1hbCgpICsNCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSAzMCwgc2l6ZSA9IDgpKQ0KYGBgDQoNCmBgYHtyfQ0KZ2dwbG90KGdhcm1lbnRzX3dvcmtlcl9wcm9kdWN0aXZpdHksIGFlcyhkZXBhcnRtZW50LCBmaWxsPXF1YXJ0ZXIpKSArIGdlb21fYmFyKCkgKyB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZT0zMCkpDQpgYGANCg0KRXN0ZSBncsOhZmljbyBkZSBiYXJyYXMgYXBpbGFkYXMgbXVlc3RyYSBsYSBkaXN0cmlidWNpw7NuIGRlIGVxdWlwb3MgZGUgdHJhYmFqbyBzZWfDum4gc3UgZGVwYXJ0YW1lbnRvIChlamUgWCkgeSBzdSBjb21wb3NpY2nDs24gcG9yIHRyaW1lc3RyZXMgKHJlbGxlbm8gZGUgY29sb3JlcykuIENhZGEgYmFycmEgdmVydGljYWwgcmVwcmVzZW50YSB1biBkZXBhcnRhbWVudG8gKCJzd2VpbmciIG8gImZpbmlzaGluZyIpLCBkaXZpZGlkYSBlbiBzZWdtZW50b3MgY29sb3JlYWRvcyBxdWUgaW5kaWNhbiBjdcOhbnRvcyBlcXVpcG9zIHBlcnRlbmVjZW4gYSBjYWRhIHRyaW1lc3RyZSAoUXVhcnRlcjEsIFF1YXJ0ZXIyLCBldGMuKS4gRWwgw6FuZ3VsbyBkZSAzMMKwIGVuIGxhcyBldGlxdWV0YXMgZGVsIGVqZSBYIG1lam9yYSBsYSBsZWdpYmlsaWRhZC4gRXN0YSB2aXN1YWxpemFjacOzbiBwZXJtaXRlIGlkZW50aWZpY2FyIHNpbXVsdMOhbmVhbWVudGU6IDEpIExhIHByb3BvcmNpw7NuIGdlbmVyYWwgZGUgZXF1aXBvcyBlbnRyZSBkZXBhcnRhbWVudG9zIChhbHR1cmEgdG90YWwgZGUgbGFzIGJhcnJhcyksIDIpIEPDs21vIHNlIGRpc3RyaWJ1eWVuIHRlbXBvcmFsbWVudGUgbG9zIGVxdWlwb3MgZGVudHJvIGRlIGNhZGEgZGVwYXJ0YW1lbnRvIChwcm9wb3JjacOzbiBkZSBjb2xvcmVzIGVuIGNhZGEgYmFycmEpLCB5IDMpIFBvc2libGVzIHBhdHJvbmVzIGVzdGFjaW9uYWxlcyBlbnRyZSB0cmltZXN0cmVzIGFsIGNvbXBhcmFyIGxvcyBzZWdtZW50b3MgZGUgY29sb3IgaG9yaXpvbnRhbG1lbnRlLiBFbCBncsOhZmljbyByZXZlbGEgZGUgdW4gdmlzdGF6byBzaSBsYSBhc2lnbmFjacOzbiBkZSBlcXVpcG9zIHBvciBkZXBhcnRhbWVudG8gdmFyw61hIHNpZ25pZmljYXRpdmFtZW50ZSBlbnRyZSBwZXJpb2RvcyBvIHNpIHNlIG1hbnRpZW5lIGNvbnN0YW50ZS4NCg0KKipBbsOhbGlzaXMgRGVzY3JpcHRpdm8gQml2YXJpYWRvIEVudHJlIFZhcmlhYmxlcyBDYXRlZ8OzcmljYXMgeSBDdWFudGl0YXRpdmFzIDoqKg0KRW4gZXN0YSBzZWNjacOzbiBzZSBhbmFsaXphIGxhIHJlbGFjacOzbiBlbnRyZSB2YXJpYWJsZXMgY2F0ZWfDs3JpY2FzIChjb21vIGRlcGFydG1lbnQgeSBkYXkpIHkgdmFyaWFibGVzIGN1YW50aXRhdGl2YXMgKGFjdHVhbF9wcm9kdWN0aXZpdHkgeSBvdmVyX3RpbWUpLiBTZSBwcmVzZW50YW4gZXN0YWTDrWdyYWZvcyBkZSB0ZW5kZW5jaWEgY2VudHJhbCwgZGlzcGVyc2nDs24sIGZvcm1hIHkgcG9zaWNpw7NuLCBhc8OtIGNvbW8gZ3LDoWZpY29zIHF1ZSBwZXJtaXRlbiB2aXN1YWxpemFyIGxhIGRpc3RyaWJ1Y2nDs24geSB2YXJpYWJpbGlkYWQgc2VnbWVudGFkYSBwb3IgY2F0ZWdvcsOtYXMuDQoqKjEuIFByb2R1Y3RpdmlkYWQgcmVhbCAoYWN0dWFsX3Byb2R1Y3Rpdml0eSkgcG9yIGRlcGFydGFtZW50byAoZGVwYXJ0bWVudCkqKg0KU2UgZXN0dWRpYSBjw7NtbyB2YXLDrWEgbGEgcHJvZHVjdGl2aWRhZCBhbGNhbnphZGEgc2Vnw7puIGVsIMOhcmVhIGRlIHRyYWJham86DQoqKkVzdGFkw61ncmFmb3MgZGVzdGFjYWRvczoqKg0KTGEgbWVkaWEgeSBtZWRpYW5hIHNvbiBtYXlvcmVzIGVuIGVsIMOhcmVhIGRlIHN3ZWluZywgaW5kaWNhbmRvIHVuIHJlbmRpbWllbnRvIGdlbmVyYWwgbcOhcyBhbHRvOyBBZGljaW9uYWxtZW50ZSwgbGEgZGVzdmlhY2nDs24gZXN0w6FuZGFyIHkgbGEgdmFyaWFuemEgdGFtYmnDqW4gc29uIG3DoXMgZWxldmFkYXMgZW4gc3dlaW5nLCBsbyBjdWFsIHJlZmxlamEgbWF5b3IgZGlzcGVyc2nDs24uDQpFbCByYW5nbyBpbnRlcmN1YXJ0w61saWNvIChJUVIpIHkgbGEgY3VydG9zaXMgc29uIG3DoXMgcHJvbnVuY2lhZG9zIGVuIHN3ZWluZywgbG8gcXVlIHN1Z2llcmUgcHJlc2VuY2lhIGRlIGV4dHJlbW9zIG8gY29tcG9ydGFtaWVudG9zIGF0w61waWNvcy4NCk9ic2VydmFjaW9uZXM6IEVsIGRlcGFydGFtZW50byBkZSBjb3N0dXJhIG11ZXN0cmEgdW5hIHByb2R1Y3RpdmlkYWQgbcOhcyBhbHRhIHkgZGlzcGVyc2EsIGNvbiB2YXJpb3MgdmFsb3JlcyBleHRyZW1vcy4gRW4gY2FtYmlvLCBlbCBkZSBhY2FiYWRvIHRpZW5lIG1lbm9yIHByb2R1Y3RpdmlkYWQgeSBtYXlvciBjb25jZW50cmFjacOzbg0KZGUgZGF0b3MuDQoNCmBgYHtyfQ0KZ2dwbG90KGdhcm1lbnRzX3dvcmtlcl9wcm9kdWN0aXZpdHksIGFlcyh4ID0gYWN0dWFsX3Byb2R1Y3Rpdml0eSwgeSA9IGRlcGFydG1lbnQsIGZpbGwgPSBkZXBhcnRtZW50KSkgKw0KICBnZW9tX2JveHBsb3QoKSArDQogIGxhYnModGl0bGUgPSAiQm94cGxvdCBkZSBQcm9kdWN0aXZpZGFkIFJlYWwgcG9yIERlcGFydGFtZW50byIsDQogICAgICAgeCA9ICJQcm9kdWN0aXZpZGFkIFJlYWwiLA0KICAgICAgIHkgPSAiRGVwYXJ0YW1lbnRvIikgKw0KICB0aGVtZV9taW5pbWFsKCkNCmBgYA0KDQoqKjEuIEJveHBsb3QgZGUgUHJvZHVjdGl2aWRhZCBSZWFsIHBvciBEZXBhcnRhbWVudG8qKlwNCg0KRWwgYm94cGxvdCBwcmVzZW50YSBsYSBkaXN0cmlidWNpw7NuIGRlIGxhIHByb2R1Y3RpdmlkYWQgcmVhbCAoYGFjdHVhbF9wcm9kdWN0aXZpdHlgKSBlbiBsb3MgZGlzdGludG9zIGRlcGFydGFtZW50b3MuIENhZGEgY2FqYSByZXByZXNlbnRhIGVsIHJhbmdvIGludGVyY3VhcnTDrWxpY28geSBsYSBsw61uZWEgY2VudHJhbCBpbmRpY2EgbGEgbWVkaWFuYS4gU2Ugb2JzZXJ2YSBxdWUgZWwgZGVwYXJ0YW1lbnRvIGRlICJzd2VpbmciIHRpZW5lIHVuYSBtYXlvciBjb25jZW50cmFjacOzbiBkZSB2YWxvcmVzIGJham9zIHkgdW5hIGdyYW4gY2FudGlkYWQgZGUgdmFsb3JlcyBhdMOtcGljb3MgKG91dGxpZXJzKSBwb3IgZGViYWpvIGRlIDAuNiwgbG8gcXVlIHN1Z2llcmUgdW5hIHZhcmlhYmlsaWRhZCBjb25zaWRlcmFibGUgZW4gbGEgcHJvZHVjdGl2aWRhZCBkZSBlc3RlIGdydXBvLiBQb3Igc3UgcGFydGUsIGxvcyBkZXBhcnRhbWVudG9zIGRlICJmaW5pc2hpbmciIG11ZXN0cmFuIGRpc3RyaWJ1Y2lvbmVzIG3DoXMgY2VudHJhZGFzIHkgY29uIG1lbm9yIHByZXNlbmNpYSBkZSB2YWxvcmVzIGV4dHJlbW9zLCBsbyBxdWUgcG9kcsOtYSBpbmRpY2FyIHVuYSBtYXlvciBjb25zaXN0ZW5jaWEgZW4gZWwgZGVzZW1wZcOxbyBkZSBzdXMgdHJhYmFqYWRvcmVzLg0KDQpgYGB7cn0NCmdncGxvdChnYXJtZW50c193b3JrZXJfcHJvZHVjdGl2aXR5LCBhZXMoeCA9IGFjdHVhbF9wcm9kdWN0aXZpdHkpKSArDQogIGdlb21faGlzdG9ncmFtKGFlcyh5ID0gLi5kZW5zaXR5Li4pLCBmaWxsID0gIm9yYW5nZSIsIGNvbG9yID0gImJsYWNrIiwgYmlucyA9IDMwLCBhbHBoYSA9IDAuNikgKw0KICBnZW9tX2RlbnNpdHkoY29sb3IgPSAiYnJvd24iLCBsaW5lcyA9IDEpICsNCiAgZmFjZXRfd3JhcCh+ZGVwYXJ0bWVudCwgc2NhbGVzID0gImZyZWVfeSIpICsNCiAgbGFicygNCiAgICB0aXRsZSA9ICJEaXN0cmlidWNpw7NuIGRlIFByb2R1Y3RpdmlkYWQgUmVhbCBwb3IgRGVwYXJ0YW1lbnRvIiwNCiAgICB4ID0gIlByb2R1Y3RpdmlkYWQgUmVhbCIsDQogICAgeSA9ICJGcmVjdWVuY2lhIg0KICApICsNCiAgdGhlbWVfbWluaW1hbCgpDQpgYGANCg0KKioyLiBIaXN0b2dyYW1hIGRlIFByb2R1Y3RpdmlkYWQgUmVhbCBwb3IgRGVwYXJ0YW1lbnRvKipcDQoNCkVzdGEgZ3LDoWZpY2EgbXVlc3RyYSBsYSBkaXN0cmlidWNpw7NuIGRlIGxhIHByb2R1Y3RpdmlkYWQgcmVhbCBwb3IgZGVwYXJ0YW1lbnRvLCBhIHRyYXbDqXMgZGUgaGlzdG9ncmFtYXMgYWNvbXBhw7FhZG9zIGRlIGN1cnZhcyBkZSBkZW5zaWRhZC4gRW4gZWwgY2FzbyBkZWwgZGVwYXJ0YW1lbnRvIGRlICJzd2VpbmciLCBsYSBtYXlvcsOtYSBkZSBsb3MgdmFsb3JlcyBzZSBjb25jZW50cmFuIGVudHJlIDAuNyB5IDAuOSwgbG8gY3VhbCBzdWdpZXJlIHF1ZSwgYSBwZXNhciBkZSBsb3Mgb3V0bGllcnMsIGxhIHByb2R1Y3RpdmlkYWQgZGUgbXVjaG9zIHRyYWJhamFkb3JlcyBlc3TDoSBkZW50cm8gZGUgdW4gcmFuZ28gYWNlcHRhYmxlLiBMbGFtYSBsYSBhdGVuY2nDs24gcXVlIGFwYXJlY2VuIGRvcyBwYW5lbGVzIGNvbiBlbCBub21icmUgImZpbmlzaGluZyIsIGxvIGN1YWwgcG9kcsOtYSBkZWJlcnNlIGEgdW5hIGluY29uc2lzdGVuY2lhIGVuIGVsIGV0aXF1ZXRhZG8gZGUgbG9zIGRhdG9zLiBBdW4gYXPDrSwgZW4gYW1ib3Mgc2Ugb2JzZXJ2YSB1bmEgcHJvZHVjdGl2aWRhZCBtw6FzIHVuaWZvcm1lLCBhdW5xdWUgY29uIGNpZXJ0YXMgZGlmZXJlbmNpYXMgZW4gbGEgZm9ybWEgZGUgbGEgZGlzdHJpYnVjacOzbi4NCg0KYGBge3J9DQpnZ3Bsb3QoZ2FybWVudHNfd29ya2VyX3Byb2R1Y3Rpdml0eSwgYWVzKHggPSBkYXksIHkgPSBvdmVyX3RpbWUsIGZpbGwgPSBkYXkpKSArDQogIGdlb21fYm94cGxvdChhbHBoYSA9IDAuNikgKw0KICBzY2FsZV9maWxsX2JyZXdlcihwYWxldHRlID0gIlBhc3RlbDEiKSArICAjIENvbG9yZXMgc3VhdmVzDQogIGxhYnMoDQogICAgdGl0bGUgPSAiQm94cGxvdCBkZSBIb3JhcyBFeHRyYSBwb3IgRMOtYSBkZSBsYSBTZW1hbmEiLA0KICAgIHggPSAiIiwNCiAgICB5ID0gIkhvcmFzIGV4dHJhIg0KICApICsNCiAgdGhlbWVfbWluaW1hbCgpICsNCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA0NSwgaGp1c3QgPSAxKSkNCmBgYA0KDQoqKjMuIEJveHBsb3QgZGUgSG9yYXMgRXh0cmEgcG9yIETDrWEgZGUgbGEgU2VtYW5hKipcDQoNCkVuIGVzdGEgZ3LDoWZpY2Egc2UgYW5hbGl6YSBsYSBkaXN0cmlidWNpw7NuIGRlIGxhcyBob3JhcyBleHRyYSAoYG92ZXJfdGltZWApIHRyYWJhamFkYXMgZHVyYW50ZSBsYSBzZW1hbmEuIExhIG1heW9yw61hIGRlIGxvcyBkw61hcyBwcmVzZW50YW4gZGlzdHJpYnVjaW9uZXMgc2ltaWxhcmVzLCBjb24gbWVkaWFuYXMgZXN0YWJsZXMgeSByYW5nb3MgaW50ZXJjdWFydMOtbGljb3MgcmVsYXRpdmFtZW50ZSBlc3RyZWNob3MuIFNpbiBlbWJhcmdvLCBlbCBqdWV2ZXMgc2UgZGVzdGFjYSBwb3IgbGEgcHJlc2VuY2lhIGRlIHVuIHZhbG9yIGF0w61waWNvIGV4dHJlbW8gcXVlIHN1cGVyYSBsYXMgMjUsMDAwIGhvcmFzLCBsbyBjdWFsIHBvZHLDrWEgdHJhdGFyc2UgZGUgdW4gZXJyb3IgZW4gbGEgYmFzZSBkZSBkYXRvcyBvIGRlIHVuIGV2ZW50byBlc3BlY8OtZmljbyBjb24gdW5hIGNhcmdhIGRlIHRyYWJham8gaW51c3VhbG1lbnRlIGFsdGEuIEVzdGEgZ3LDoWZpY2Egc3VnaWVyZSBxdWUsIGF1bnF1ZSBsYXMgaG9yYXMgZXh0cmEgZXN0w6FuIHByZXNlbnRlcyB0b2RvcyBsb3MgZMOtYXMsIHN1IGRpc3RyaWJ1Y2nDs24gZ2VuZXJhbCBlcyBjb25zaXN0ZW50ZSBzYWx2byBwb3IgYWxndW5hcyBleGNlcGNpb25lcyBhaXNsYWRhcy4NCg0KYGBge3J9DQpnZ3Bsb3QoZ2FybWVudHNfd29ya2VyX3Byb2R1Y3Rpdml0eSwgYWVzKHggPSBvdmVyX3RpbWUsIHkgPSBhY3R1YWxfcHJvZHVjdGl2aXR5KSkgKw0KICBnZW9tX3BvaW50KGNvbG9yID0gIm9yYW5nZSIsIGFscGhhID0gMC41KSArDQogIGZhY2V0X3dyYXAofmRheSwgc2NhbGVzID0gImZyZWVfeCIpICsNCiAgbGFicygNCiAgICB0aXRsZSA9ICJSZWxhY2nDs24gZW50cmUgSG9yYXMgRXh0cmEgeSBQcm9kdWN0aXZpZGFkIHBvciBEw61hIiwNCiAgICB4ID0gIkhvcmFzIGV4dHJhIiwNCiAgICB5ID0gIlByb2R1Y3RpdmlkYWQgUmVhbCINCiAgKSArDQogIHRoZW1lX21pbmltYWwoKQ0KYGBgDQoNCioqNC4gRGlzcGVyc2nDs24gZW50cmUgSG9yYXMgRXh0cmEgeSBQcm9kdWN0aXZpZGFkIHBvciBEw61hKipcDQoNCkVzdGEgdmlzdWFsaXphY2nDs24gbXVlc3RyYSBsYSByZWxhY2nDs24gZW50cmUgbGFzIGhvcmFzIGV4dHJhIHkgbGEgcHJvZHVjdGl2aWRhZCByZWFsLCBzZXBhcmFkYSBwb3IgZMOtYSBkZSBsYSBzZW1hbmEuIENhZGEgcHVudG8gcmVwcmVzZW50YSB1biB0cmFiYWphZG9yLCB5IGVsIG9iamV0aXZvIGVzIGlkZW50aWZpY2FyIHNpIGV4aXN0ZSBhbGfDum4gdGlwbyBkZSBjb3JyZWxhY2nDs24gZW50cmUgdHJhYmFqYXIgbcOhcyBob3JhcyB5IG9idGVuZXIgdW5hIG1heW9yIHByb2R1Y3RpdmlkYWQuIEVuIGdlbmVyYWwsIG5vIHNlIG9ic2VydmEgdW5hIHJlbGFjacOzbiBjbGFyYSBlbnRyZSBsYXMgdmFyaWFibGVzOiB0YW50byBsb3MgdHJhYmFqYWRvcmVzIHF1ZSBoYWNlbiBwb2NhcyBjb21vIGxvcyBxdWUgaGFjZW4gbXVjaGFzIGhvcmFzIGV4dHJhIHB1ZWRlbiB0ZW5lciBuaXZlbGVzIGRlIHByb2R1Y3RpdmlkYWQgYmFqb3MsIG1lZGlvcyBvIGFsdG9zLiBFc3RvIHBvZHLDrWEgaW5kaWNhciBxdWUgbGFzIGhvcmFzIGFkaWNpb25hbGVzIG5vIGdhcmFudGl6YW4gdW4gYXVtZW50byBlbiBsYSBlZmljaWVuY2lhLCB5IHF1ZSBvdHJvcyBmYWN0b3JlcyBpbmZsdXllbiBlbiBlbCBkZXNlbXBlw7FvIGRpYXJpby4NCg0KYGBge3J9DQpnZ3Bsb3QoZ2FybWVudHNfd29ya2VyX3Byb2R1Y3Rpdml0eSwgYWVzKHggPSBvdmVyX3RpbWUpKSArDQogIGdlb21faGlzdG9ncmFtKGFlcyh5ID0gLi5kZW5zaXR5Li4pLCBmaWxsID0gIm9saXZlZHJhYjMiLCBjb2xvciA9ICJibGFjayIsIGJpbnMgPSAzMCwgYWxwaGEgPSAwLjUpICsNCiAgZ2VvbV9kZW5zaXR5KGNvbG9yID0gImRhcmtncmVlbiIsIHNpemUgPSAxKSArDQogIGZhY2V0X3dyYXAofmRheSwgc2NhbGVzID0gImZyZWVfeSIpICsNCiAgbGFicygNCiAgICB0aXRsZSA9ICJEaXN0cmlidWNpw7NuIGRlIEhvcmFzIEV4dHJhIHBvciBEw61hIiwNCiAgICB4ID0gIkhvcmFzIGV4dHJhIiwNCiAgICB5ID0gIkZyZWN1ZW5jaWEiDQogICkgKw0KICB0aGVtZV9taW5pbWFsKCkNCmBgYA0KDQoqKjUuIEhpc3RvZ3JhbWEgZGUgSG9yYXMgRXh0cmEgcG9yIETDrWEqKlwNCg0KRmluYWxtZW50ZSwgc2UgcHJlc2VudGEgbGEgZGlzdHJpYnVjacOzbiBkZSBsYXMgaG9yYXMgZXh0cmEgcG9yIGTDrWEgbWVkaWFudGUgaGlzdG9ncmFtYXMgY29uIGN1cnZhcyBkZSBkZW5zaWRhZC4gRW4gY2FzaSB0b2RvcyBsb3MgY2Fzb3MsIGxvcyBkYXRvcyBlc3TDoW4gc2VzZ2Fkb3MgaGFjaWEgbGEgZGVyZWNoYSwgbG8gcXVlIHNpZ25pZmljYSBxdWUgbGEgbWF5b3LDrWEgZGUgbG9zIHRyYWJhamFkb3JlcyByZWFsaXphIHBvY2FzIGhvcmFzIGV4dHJhLCBtaWVudHJhcyBxdWUgdW5vcyBwb2NvcyBjb25jZW50cmFuIHZhbG9yZXMgc2lnbmlmaWNhdGl2YW1lbnRlIGFsdG9zLiBFc3RlIHBhdHLDs24gc2UgbWFudGllbmUgZW4gdG9kb3MgbG9zIGTDrWFzLCBhdW5xdWUgbG9zIGp1ZXZlcyB5IHPDoWJhZG9zIHBhcmVjZW4gdGVuZXIgbcOhcyBmcmVjdWVuY2lhIGRlIGpvcm5hZGFzIGxhcmdhcy4gRXN0YSBncsOhZmljYSByZXNhbHRhIGxhIGRlc2lndWFsIGRpc3RyaWJ1Y2nDs24gZGVsIHRyYWJham8gYWRpY2lvbmFsIHkgc3VnaWVyZSBxdWUgZWwgdXNvIGRlIGhvcmFzIGV4dHJhIG5vIGVzIHVuaWZvcm1lIGVudHJlIGxvcyBlbXBsZWFkb3MgbmkgZW50cmUgbG9zIGTDrWFzIGRlIGxhIHNlbWFuYS4NCg==