1 Presentación

Este informe desarrolla un análisis exploratorio de los registros de comparendos incluidos en el archivo suministrado. Se utiliza la hoja Data Original (2) porque contiene 17 variables, entre ellas género o tipo de ejecutado, descripción de la infracción, fecha, día de la semana y tipo de vehículo.

El documento está diseñado para que el código pueda consultarse y ejecutarse. Cada bloque de código dispone de una explicación funcional y una nota de interpretación. Los gráficos permanecen fijos, sin controles para ampliar o reducir la vista, y muestran etiquetas numéricas directamente sobre las barras o columnas para facilitar la lectura. Cuando corresponde, también se pueden consultar detalles al pasar el cursor; las tablas permiten buscar, ordenar y recorrer registros.

Alcance: la base analizada contiene registros fechados entre abril y mayo de 2010. Por tanto, los resultados describen exclusivamente ese periodo y no representan todo el año ni otros años.

2 Objetivos

  • Describir la estructura y calidad de la base de datos.
  • Identificar las infracciones más frecuentes.
  • Examinar la distribución de comparendos por mes, día de la semana y fecha.
  • Comparar los registros por género o tipo de ejecutado y tipo de vehículo.
  • Dejar documentado el código utilizado para que pueda reproducirse el análisis.

Enfoque del análisis: El informe tiene un alcance descriptivo: caracteriza los registros, identifica frecuencias y compara categorías. Los resultados no permiten establecer causas ni atribuir responsabilidades; se limitan a la información contenida en el archivo.

3 Preparación del entorno

3.1 ¿Qué hace este código?

Carga las bibliotecas que permiten importar Excel, transformar los datos, construir gráficos interactivos y presentar tablas con opciones de búsqueda. Si alguna biblioteca no está instalada, el código la instala automáticamente.

# Lista de bibliotecas necesarias para importar, transformar y visualizar los datos.
paquetes <- c("readxl", "dplyr", "ggplot2", "plotly", "DT", "knitr", "scales", "lubridate", "stringr", "tidyr", "htmltools")

faltantes <- paquetes[!paquetes %in% rownames(installed.packages())]
if (length(faltantes) > 0) {
  install.packages(faltantes, repos = "https://cloud.r-project.org")
}

invisible(lapply(paquetes, library, character.only = TRUE))

Función de las bibliotecas: Las bibliotecas amplían las funciones de R utilizadas en el proyecto: readxl importa libros de Excel; dplyr transforma y resume tablas; ggplot2 construye gráficos; plotly añade consulta interactiva; y DT presenta tablas con búsqueda y filtros. El bloque verifica e instala los paquetes que no estén disponibles.

4 Importación de los datos

4.1 ¿Qué hace este código?

Lee la hoja Data Original (2) del libro de Excel. Si el archivo no está en la carpeta de trabajo de R, se debe seleccionar o copiar allí. Luego muestra las primeras filas para comprobar que la importación se realizó correctamente.

# Obtiene el nombre del Excel indicado en los parámetros del informe.
archivo <- params$archivo

if (!file.exists(archivo)) {
  message("Selecciona el archivo Excel de comparendos")
  archivo <- file.choose()
}

base_original <- readxl::read_excel(archivo, sheet = params$hoja)

cat("Filas:", nrow(base_original), "| Columnas:", ncol(base_original))
## Filas: 2120 | Columnas: 17
knitr::kable(head(base_original, 6), caption = "Primeros seis registros importados")
Primeros seis registros importados
No. MANDAMIENTO DE PAGO FECHA MANDAMIENTO DE PAGO EJECUTADO TIPO DE IDENTIFICACION No. IDENTIFICACION GENERO COD. INFRACCION NOM.INFRACCION COMPARENDO FECHA DE COMPARENDO AÑO MES NOM MES DIA NOM DIA PLACA DE VEHICULO VEHICULO
F00001478 19/08/2010 ZULLY PATRICIA IBARRA DONADO Cedula de Ciudadanía 22617126 MUJER 64 velocidad superior a la maxima permitida F00014049 2010-05-22 2010 5 MAYO 22 SÁBADO UZD459 AUTO
F00002105 19/08/2010 ZULIMA DEL CARMEN HENNESSEY CLAVIJO Cedula de Ciudadanía 32770170 MUJER 67 No respetar el paso de peatones F00014095 2010-05-22 2010 5 MAYO 22 SÁBADO UYM861 AUTO
F00003509 19/08/2010 ZOOCRIADERO COLOMBIAN CROCO LI Nit 800120048 EMPRESA 64 velocidad superior a la maxima permitida F00013652 2010-05-20 2010 5 MAYO 20 JUEVES QHI400 AUTO
F00003510 19/08/2010 ZOOCRIADERO COLOMBIAN CROCO LI Nit 800120048 EMPRESA 64 velocidad superior a la maxima permitida F00009388 2010-05-08 2010 5 MAYO 8 SÁBADO QHI400 AUTO
F00003511 19/08/2010 ZOOCRIADERO COLOMBIAN CROCO LI Nit 800120048 EMPRESA 64 velocidad superior a la maxima permitida F00010959 2010-05-12 2010 5 MAYO 12 MIÉRCOLES QHI400 AUTO
F00003512 19/08/2010 ZOOCRIADERO COLOMBIAN CROCO LI Nit 800120048 EMPRESA 64 velocidad superior a la maxima permitida F00007540 2010-05-03 2010 5 MAYO 3 LUNES QHI400 AUTO

Criterio de importación: La función read_excel() carga la hoja definida en los parámetros del informe. La revisión de dimensiones y de las primeras filas permite comprobar que la lectura se realizó correctamente y que se importaron las variables previstas.

5 Exploración y calidad de los datos

5.1 ¿Qué hace este código?

Consulta los nombres y tipos de columnas, cuenta los valores faltantes y detecta registros duplicados. La revisión no elimina filas automáticamente: primero informa los hallazgos para que la decisión de depuración sea transparente.

# Normalizar espacios sobrantes en los nombres de las columnas para evitar errores al referenciar variables
names(base_original) <- trimws(names(base_original))

# Resumen de dimensiones y tipos de variables
cat("Número de registros:", nrow(base_original), "\n")
## Número de registros: 2120
cat("Número de variables:", ncol(base_original), "\n\n")
## Número de variables: 17
str(base_original)
## tibble [2,120 × 17] (S3: tbl_df/tbl/data.frame)
##  $ No. MANDAMIENTO DE PAGO  : chr [1:2120] "F00001478" "F00002105" "F00003509" "F00003510" ...
##  $ FECHA MANDAMIENTO DE PAGO: chr [1:2120] "19/08/2010" "19/08/2010" "19/08/2010" "19/08/2010" ...
##  $ EJECUTADO                : chr [1:2120] "ZULLY PATRICIA IBARRA DONADO" "ZULIMA DEL CARMEN HENNESSEY CLAVIJO" "ZOOCRIADERO COLOMBIAN CROCO LI" "ZOOCRIADERO COLOMBIAN CROCO LI" ...
##  $ TIPO DE IDENTIFICACION   : chr [1:2120] "Cedula de Ciudadanía" "Cedula de Ciudadanía" "Nit" "Nit" ...
##  $ No. IDENTIFICACION       : num [1:2120] 2.26e+07 3.28e+07 8.00e+08 8.00e+08 8.00e+08 ...
##  $ GENERO                   : chr [1:2120] "MUJER" "MUJER" "EMPRESA" "EMPRESA" ...
##  $ COD. INFRACCION          : num [1:2120] 64 67 64 64 64 64 64 64 64 64 ...
##  $ NOM.INFRACCION           : chr [1:2120] "velocidad superior a la maxima permitida" "No respetar el paso de peatones" "velocidad superior a la maxima permitida" "velocidad superior a la maxima permitida" ...
##  $ COMPARENDO               : chr [1:2120] "F00014049" "F00014095" "F00013652" "F00009388" ...
##  $ FECHA DE COMPARENDO      : POSIXct[1:2120], format: "2010-05-22" "2010-05-22" ...
##  $ AÑO                      : num [1:2120] 2010 2010 2010 2010 2010 2010 2010 2010 2010 2010 ...
##  $ MES                      : num [1:2120] 5 5 5 5 5 5 5 5 5 5 ...
##  $ NOM MES                  : chr [1:2120] "MAYO" "MAYO" "MAYO" "MAYO" ...
##  $ DIA                      : num [1:2120] 22 22 20 8 12 3 23 2 27 18 ...
##  $ NOM DIA                  : chr [1:2120] "SÁBADO" "SÁBADO" "JUEVES" "SÁBADO" ...
##  $ PLACA DE VEHICULO        : chr [1:2120] "UZD459" "UYM861" "QHI400" "QHI400" ...
##  $ VEHICULO                 : chr [1:2120] "AUTO" "AUTO" "AUTO" "AUTO" ...
# Valores vacíos por columna
faltantes <- data.frame(
  variable = names(base_original),
  valores_faltantes = vapply(base_original, function(x) sum(is.na(x) | trimws(as.character(x)) == ""), numeric(1))
)
DT::datatable(faltantes, rownames = FALSE, options = list(pageLength = 17, searching = FALSE),
              caption = "Valores faltantes por variable")
# Duplicados exactos y repetición de identificadores
cat("Filas duplicadas exactas:", sum(duplicated(base_original)), "\n")
## Filas duplicadas exactas: 1
if ("COMPARENDO" %in% names(base_original)) {
  cat("Números de comparendo repetidos (filas adicionales):", sum(duplicated(base_original$COMPARENDO)), "\n")
}
## Números de comparendo repetidos (filas adicionales): 18
if ("No. MANDAMIENTO DE PAGO" %in% names(base_original)) {
  cat("Mandamientos repetidos (filas adicionales):", sum(duplicated(base_original$`No. MANDAMIENTO DE PAGO`)), "\n")
}
## Mandamientos repetidos (filas adicionales): 1

Control de calidad: La inspección de estructura identifica los tipos de variables; el conteo de valores faltantes señala campos incompletos; y duplicated() detecta repeticiones exactas o de identificadores. Los registros repetidos se reportan para validación y no se eliminan sin comprobar su naturaleza.

6 Limpieza y transformación

6.1 ¿Qué hace este código?

Crea una copia de trabajo, elimina espacios sobrantes en los textos, convierte las fechas al formato de fecha de R y convierte las variables numéricas a su tipo correspondiente. También crea una etiqueta de fecha y ordena los meses y días de la semana para que los gráficos aparezcan en secuencia. No elimina duplicados sin autorización.

# Crea una copia de trabajo; la tabla original se conserva sin modificaciones.
base <- base_original %>%
  mutate(across(where(is.character), ~ stringr::str_squish(.x))) %>%
  mutate(
    `FECHA DE COMPARENDO` = as.Date(`FECHA DE COMPARENDO`),
    AÑO = as.integer(AÑO),
    MES = as.integer(MES),
    DIA = as.integer(DIA),
    `COD. INFRACCION` = as.integer(`COD. INFRACCION`),
    NOM.MES = factor(toupper(`NOM MES`), levels = c("ENERO", "FEBRERO", "MARZO", "ABRIL", "MAYO", "JUNIO", "JULIO", "AGOSTO", "SEPTIEMBRE", "OCTUBRE", "NOVIEMBRE", "DICIEMBRE")),
    NOM.DIA = factor(toupper(`NOM DIA`), levels = c("LUNES", "MARTES", "MIÉRCOLES", "JUEVES", "VIERNES", "SÁBADO", "DOMINGO"))
  )

# Comprobación de fechas y variables principales
summary(base$`FECHA DE COMPARENDO`)
##         Min.      1st Qu.       Median         Mean      3rd Qu.         Max. 
## "2010-04-12" "2010-04-27" "2010-05-06" "2010-05-05" "2010-05-16" "2010-05-27"
summary(base$`COD. INFRACCION`)
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
##   64.00   64.00   64.00   66.53   64.00   77.00

Criterio de transformación: La transformación estandariza espacios y tipos de datos para facilitar los cálculos. Las fechas y variables numéricas se convierten a formatos adecuados, mientras que los meses y días se ordenan cronológicamente. La tabla importada se conserva y las operaciones se realizan sobre una copia de trabajo.

7 Indicadores generales

7.1 ¿Qué hace este código?

Calcula indicadores básicos a partir de los registros disponibles: total de comparendos, fechas mínima y máxima, cantidad de códigos de infracción y número de tipos de vehículo. Son indicadores descriptivos, no estimaciones para otros periodos.

# Construye una tabla con medidas descriptivas generales de la base.
indicadores <- data.frame(
  Indicador = c("Registros analizados", "Fecha inicial", "Fecha final", "Códigos de infracción", "Tipos de vehículo"),
  Resultado = c(
    format(nrow(base), big.mark = "."),
    format(min(base$`FECHA DE COMPARENDO`, na.rm = TRUE), "%d/%m/%Y"),
    format(max(base$`FECHA DE COMPARENDO`, na.rm = TRUE), "%d/%m/%Y"),
    dplyr::n_distinct(base$`COD. INFRACCION`, na.rm = TRUE),
    dplyr::n_distinct(base$VEHICULO, na.rm = TRUE)
  )
)
## Warning in prettyNum(.Internal(format(x, trim, digits, nsmall, width, 3L, :
## 'big.mark' y 'decimal.mark' son ambos '.', lo cual puede ser confuso
knitr::kable(indicadores, col.names = c("Indicador", "Resultado"), caption = "Resumen general de la base")
Resumen general de la base
Indicador Resultado
Registros analizados 2.120
Fecha inicial 12/04/2010
Fecha final 27/05/2010
Códigos de infracción 4
Tipos de vehículo 2

Lectura de los indicadores: Los indicadores resumen el volumen y el alcance temporal de los registros. El número de filas representa los casos incluidos; las fechas mínima y máxima delimitan el periodo; y los conteos distintos describen la variedad de códigos y tipos de vehículo observados.

8 Análisis de infracciones

8.1 Infracciones más frecuentes

8.1.1 ¿Qué hace este código?

Agrupa los registros por código y descripción de la infracción, cuenta cuántas veces aparece cada una y ordena los resultados de mayor a menor. El gráfico incluye etiquetas numéricas al final de cada barra y permite consultar detalles al pasar el cursor, sin mostrar botones de zoom.

Frecuencia por código y descripción de infracción
COD. INFRACCION NOM.INFRACCION cantidad
64 velocidad superior a la maxima permitida 1626
77 No detenerse ante una luz roja o amarilla 385
67 No respetar el paso de peatones 105
76 Transitar en sentido contrario 4
Mostrar código R de este gráfico
# Cuenta registros por código y descripción de infracción, de mayor a menor frecuencia.
frecuencia_infracciones <- base %>%
  count(`COD. INFRACCION`, `NOM.INFRACCION`, name = "cantidad", sort = TRUE)

knitr::kable(frecuencia_infracciones, caption = "Frecuencia por código y descripción de infracción")

grafico_infracciones <- ggplot(frecuencia_infracciones,
  aes(x = reorder(paste0("Código ", `COD. INFRACCION`), cantidad), y = cantidad,
      text = paste0("Código: ", `COD. INFRACCION`, "<br>Infracción: ", NOM.INFRACCION,
                    "<br>Registros: ", cantidad))) +
  geom_col(fill = "#176B87", width = 0.7) +
  geom_text(aes(label = cantidad), hjust = -0.15, size = 3.5,
            color = "#263445", fontface = "bold") +
  coord_flip() +
  scale_y_continuous(expand = expansion(mult = c(0, 0.15))) +
  labs(title = "Infracciones más frecuentes", x = "Código de infracción", y = "Cantidad de comparendos") +
  theme_minimal(base_size = 12)
grafico_sin_zoom(grafico_infracciones)
mostrar_codigo("infracciones")

¿Cómo funciona? El código agrupa los comparendos por código y nombre de infracción, cuenta los registros y los ordena de mayor a menor. Después construye barras horizontales para facilitar la comparación. Al pasar el cursor sobre una barra se consulta el código, la descripción y la cantidad.

Interpretación de frecuencias: Cada barra representa una combinación de código y descripción de infracción. La longitud de la barra y su etiqueta muestran el número de registros asociados. El orden descendente facilita identificar las categorías más frecuentes; estos conteos no explican las razones de su ocurrencia.

9 Comportamiento por mes

9.1 Comparendos por mes

9.1.1 ¿Qué hace este código?

Cuenta los comparendos registrados en cada mes y los representa en un gráfico interactivo. La base disponible contiene abril y mayo de 2010; no se muestran meses sin registros como si fueran cero observados.

Comparendos registrados por mes
NOM.MES cantidad
ABRIL 712
MAYO 1408
Mostrar código R de este gráfico
# Cuenta los comparendos por mes observado en el archivo.
por_mes <- base %>% count(NOM.MES, name = "cantidad") %>% arrange(NOM.MES)

knitr::kable(por_mes, caption = "Comparendos registrados por mes")

g_mes <- ggplot(por_mes, aes(x = NOM.MES, y = cantidad,
  text = paste0("Mes: ", NOM.MES, "<br>Comparendos: ", cantidad))) +
  geom_col(fill = "#E07A24", width = 0.65) +
  geom_text(aes(label = cantidad), vjust = -0.4, fontface = "bold") +
  labs(title = "Comparendos por mes", x = "Mes", y = "Cantidad") +
  theme_minimal(base_size = 12)
grafico_sin_zoom(g_mes)
mostrar_codigo("comparendos-mes")

¿Cómo funciona? Se cuentan los registros de cada mes y se muestran en columnas. Las etiquetas numéricas permiten leer la cantidad sin depender del cursor; al pasar sobre una columna se obtiene el detalle del mes.

Alcance temporal mensual: Las columnas comparan únicamente los meses presentes en el archivo. La altura representa la cantidad de registros de cada mes. La ausencia de otros meses en el gráfico indica que no están incluidos en la fuente, no que hayan tenido cero comparendos.

10 Comportamiento por día

10.1 Comparendos por día de la semana

10.1.1 ¿Qué hace este código?

Agrupa los registros según el día de la semana y conserva el orden de lunes a domingo. Permite identificar qué días concentran más registros dentro del periodo analizado.

Comparendos por día de la semana
NOM.DIA cantidad
LUNES 295
MARTES 264
MIÉRCOLES 273
JUEVES 256
VIERNES 264
SÁBADO 372
DOMINGO 396
Mostrar código R de este gráfico
# Cuenta los registros por día de la semana, respetando el orden definido en el factor.
por_dia <- base %>% count(NOM.DIA, name = "cantidad") %>% arrange(NOM.DIA)

knitr::kable(por_dia, caption = "Comparendos por día de la semana")

g_dia <- ggplot(por_dia, aes(x = NOM.DIA, y = cantidad,
  text = paste0("Día: ", NOM.DIA, "<br>Comparendos: ", cantidad))) +
  geom_col(fill = "#3B7A57", width = 0.7) +
  geom_text(aes(label = cantidad), vjust = -0.4, size = 3.5,
            color = "#263445", fontface = "bold") +
  scale_y_continuous(expand = expansion(mult = c(0, 0.12))) +
  labs(title = "Distribución por día de la semana", x = "Día", y = "Cantidad de comparendos") +
  theme_minimal(base_size = 12)
grafico_sin_zoom(g_dia)
mostrar_codigo("comparendos-dia")

¿Cómo funciona? Se agrupan los comparendos por día de la semana y se conserva el orden de lunes a domingo. La altura de cada barra y su etiqueta numérica representan la cantidad registrada para ese día.

Distribución semanal: El gráfico presenta la cantidad de registros por día de la semana, ordenados de lunes a domingo. Las diferencias observadas describen la distribución de esta muestra y no permiten establecer por sí solas las causas de esa variación.

10.2 Evolución diaria de los registros

10.2.1 ¿Qué hace este código?

Cuenta los comparendos por fecha exacta y los presenta en columnas verticales con la cantidad escrita encima de cada una. Así se comparan los días sin una línea que pueda dar una impresión de continuidad o tendencia exagerada.

Mostrar código R de este gráfico
# Agrupa por fecha exacta y cuenta cuántos comparendos se registraron cada día.
por_fecha <- base %>%
  count(`FECHA DE COMPARENDO`, name = "cantidad") %>%
  arrange(`FECHA DE COMPARENDO`)

g_fecha <- ggplot(por_fecha, aes(x = `FECHA DE COMPARENDO`, y = cantidad)) +
  geom_col(fill = "#176B87", width = 0.78) +
  geom_text(aes(label = cantidad), vjust = -0.35, size = 2.8,
            color = "#263445", fontface = "bold") +
  scale_x_date(date_breaks = "3 days", date_labels = "%d/%m",
               expand = expansion(mult = c(0.01, 0.04))) +
  scale_y_continuous(expand = expansion(mult = c(0, 0.14))) +
  labs(title = "Comparendos registrados por fecha",
       subtitle = "Cantidad diaria · abril y mayo de 2010",
       x = "Fecha del comparendo", y = "Cantidad de comparendos") +
  theme_minimal(base_size = 12) +
  theme(axis.text.x = element_text(angle = 45, hjust = 1),
        panel.grid.minor = element_blank())
g_fecha
mostrar_codigo("evolucion-diaria")

¿Cómo funciona? Se agrupan los registros por fecha y se cuenta cuántos comparendos hubo cada día. Cada columna representa una fecha y el número situado encima indica su cantidad exacta. Las fechas del eje horizontal se muestran de forma espaciada para facilitar la lectura. Este gráfico es fijo: no tiene botones para ampliar, reducir ni desplazar la vista.

Comportamiento por fecha: Cada columna representa una fecha exacta y la etiqueta indica el número de comparendos registrados ese día. La visualización permite comparar fechas dentro de abril y mayo de 2010; no debe interpretarse como una tendencia anual ni como una explicación causal.

11 Análisis por género o tipo de ejecutado

11.1 ¿Qué hace este código?

Cuenta los registros de la variable GENERO. En esta base aparecen las categorías MUJER, HOMBRE y EMPRESA; por eso, el resultado debe interpretarse como una clasificación de la base y no como una comparación exclusivamente entre personas.

Registros por categoría de género o ejecutado
GENERO cantidad
MUJER 970
HOMBRE 683
EMPRESA 467
Mostrar código R de este gráfico
# Cuenta registros por categoría de género o tipo de ejecutado.
por_genero <- base %>% count(GENERO, name = "cantidad", sort = TRUE)
knitr::kable(por_genero, caption = "Registros por categoría de género o ejecutado")

g_genero <- ggplot(por_genero, aes(x = GENERO, y = cantidad,
  text = paste0("Categoría: ", GENERO, "<br>Registros: ", cantidad))) +
  geom_col(fill = "#6C5B7B", width = 0.65) +
  geom_text(aes(label = cantidad), vjust = -0.4, size = 3.5,
            color = "#263445", fontface = "bold") +
  scale_y_continuous(expand = expansion(mult = c(0, 0.12))) +
  labs(title = "Registros por categoría", x = "Categoría", y = "Cantidad") +
  theme_minimal(base_size = 12)
grafico_sin_zoom(g_genero)
mostrar_codigo("genero")

¿Cómo funciona? Se cuenta cuántos registros hay en cada categoría de la columna GENERO. Como la base incluye la categoría EMPRESA, el gráfico se interpreta como una distribución por categoría de ejecutado y no solo como comparación entre personas.

Definición de la categoría: La variable GENERO contiene las categorías MUJER, HOMBRE y EMPRESA. Debido a esta clasificación, el resultado se presenta como distribución por género o tipo de ejecutado y no como una comparación exclusiva entre hombres y mujeres.

12 Análisis por tipo de vehículo

12.1 ¿Qué hace este código?

Agrupa los comparendos por tipo de vehículo y calcula su frecuencia. El gráfico permite comparar los tipos registrados en el archivo.

Comparendos por tipo de vehículo
VEHICULO cantidad
AUTO 1938
MOTO 182
Mostrar código R de este gráfico
# Cuenta los registros para cada tipo de vehículo.
por_vehiculo <- base %>% count(VEHICULO, name = "cantidad", sort = TRUE)
knitr::kable(por_vehiculo, caption = "Comparendos por tipo de vehículo")

g_vehiculo <- ggplot(por_vehiculo, aes(x = VEHICULO, y = cantidad,
  text = paste0("Vehículo: ", VEHICULO, "<br>Comparendos: ", cantidad))) +
  geom_col(fill = "#345995", width = 0.65) +
  geom_text(aes(label = cantidad), vjust = -0.4, size = 3.5,
            color = "#263445", fontface = "bold") +
  scale_y_continuous(expand = expansion(mult = c(0, 0.12))) +
  labs(title = "Comparendos por tipo de vehículo", x = "Tipo de vehículo", y = "Cantidad") +
  theme_minimal(base_size = 12)
grafico_sin_zoom(g_vehiculo)
mostrar_codigo("vehiculos")

¿Cómo funciona? Se agrupan los registros según el tipo de vehículo y se cuenta su frecuencia. Cada barra representa un tipo de vehículo; su altura y la etiqueta numérica indican el número de comparendos asociados.

Alcance del análisis por vehículo: Las barras comparan la frecuencia de los tipos de vehículo presentes en los registros. El resultado describe la composición de la base, pero no mide el riesgo de infracción de cada tipo, ya que no se dispone del total de vehículos que circulaban.

13 Conclusión general del análisis de comparendos

El análisis de la base de datos permitió examinar 2.120 registros de comparendos correspondientes al año 2010, comprendidos entre el 12 de abril y el 27 de mayo. Mediante el procesamiento de datos en R se identificaron patrones relacionados con los tipos de infracción, la distribución temporal, las características de los ejecutados y las clases de vehículos involucrados.

Los principales resultados fueron los siguientes:

  • Infracciones: el código 64, correspondiente a exceso de velocidad, registró 1.626 casos, equivalentes al 76,70 % del total. Le siguió el código 77, con 385 casos (18,16 %).

  • Distribución mensual: mayo concentró 1.408 comparendos (66,42 %), mientras que abril registró 712 (33,58 %).

  • Días de la semana: el domingo presentó la mayor frecuencia, con 396 registros (18,68 %), seguido del sábado, con 372 (17,55 %).

  • Categoría del ejecutado: se identificaron 970 registros asociados a mujeres (45,75 %), 683 a hombres (32,22 %) y 467 a empresas (22,03 %).

  • Tipo de vehículo: los automóviles representaron 1.938 registros (91,42 %), mientras que las motocicletas alcanzaron 182 (8,58 %).

  • Información económica: el valor acumulado registrado en la columna de costos fue de $646.067.500, con un promedio aproximado de $304.749 por comparendo.

Desde el punto de vista técnico, el uso de R permitió realizar procesos de importación, transformación, agrupación, cálculo de frecuencias y visualización mediante gráficos con etiquetas de datos. Estas herramientas facilitaron la identificación de tendencias y la interpretación de los resultados.

Consideración sobre la calidad de los datos: aunque los 2.120 registros no presentan valores vacíos en la hoja analizada, se identificaron 18 repeticiones en el número de comparendo y un registro completamente duplicado. Por tanto, estos aspectos deben validarse antes de utilizar los resultados como cifras definitivas.

En conclusión, el análisis evidencia una alta concentración de registros en las infracciones por exceso de velocidad y en los vehículos tipo automóvil. Los resultados ofrecen una visión cuantitativa del comportamiento de los comparendos durante el periodo estudiado y demuestran la utilidad de las herramientas de análisis de datos para convertir registros administrativos en información organizada y comprensible.

14 Consideraciones y limitaciones

  • La hoja principal contiene 17 variables y 2.120 filas en el archivo recibido.
  • Las fechas observadas van del 12 de abril al 27 de mayo de 2010.
  • La variable GENERO incluye la categoría EMPRESA; por ello se describe como género o tipo de ejecutado.
  • La hoja analizada no incluye una columna de costo del comparendo. El informe no calcula recaudos, multas totales ni promedios monetarios.
  • Los registros repetidos se reportan para revisión; no se eliminan de forma automática porque una repetición de comparendo o mandamiento debe validarse antes de considerarse un error.
  • Los resultados dependen de la calidad y del contenido del archivo fuente.

Limitaciones de la fuente: El análisis se restringe a los registros comprendidos entre abril y mayo de 2010. La categoría EMPRESA forma parte de la variable GENERO; los duplicados requieren validación; y la hoja utilizada no contiene una variable de costo. En consecuencia, no se estiman recaudos ni valores monetarios.


LS0tDQp0aXRsZTogIkFuw6FsaXNpcyBkZXNjcmlwdGl2byBkZSByZWdpc3Ryb3MgZGUgY29tcGFyZW5kb3MgKDIwMTApIg0KYXV0aG9yOiAiTHVpcyBBZHJpw6FuIEJ1esOzbiBBdmVuZGHDsW8iDQpkYXRlOiAiYHIgZm9ybWF0KFN5cy5EYXRlKCksICclZC8lbS8lWScpYCINCm91dHB1dDoNCiAgaHRtbF9kb2N1bWVudDoNCiAgICB0b2M6IHRydWUNCiAgICB0b2NfZGVwdGg6IDMNCiAgICB0b2NfZmxvYXQ6IHRydWUNCiAgICBudW1iZXJfc2VjdGlvbnM6IHRydWUNCiAgICBjb2RlX2ZvbGRpbmc6IGhpZGUNCiAgICBjb2RlX2Rvd25sb2FkOiB0cnVlDQogICAgdGhlbWU6IHJlYWRhYmxlDQogICAgc2VsZl9jb250YWluZWQ6IHRydWUNCnBhcmFtczoNCiAgYXJjaGl2bzogIkJEIENvbXBhcmVuZG9zIE9LJCAtIFRBRCAoMSkueGxzeCINCiAgaG9qYTogIkRhdGEgT3JpZ2luYWwgKDIpIg0KLS0tDQoNCiFbXShpbWFnZXMvbHVpcy5qcGcpe3dpZHRoPSI3MzgifQ0KDQpgYGB7PWh0bWx9DQo8c3R5bGU+DQpib2R5IHtmb250LWZhbWlseTogJ1NlZ29lIFVJJywgQXJpYWwsIHNhbnMtc2VyaWY7IGNvbG9yOiMyNjM0NDU7fQ0KaDEsIGgyLCBoMyB7Y29sb3I6IzE3MzY1RDt9DQoua3BpIHtiYWNrZ3JvdW5kOiNlZWYzZjg7IGJvcmRlci1sZWZ0OjVweCBzb2xpZCAjMjg3NEE2OyBwYWRkaW5nOjEycHggMTZweDsgbWFyZ2luOjhweCAwOyBib3JkZXItcmFkaXVzOjVweDt9DQoubm90YSB7YmFja2dyb3VuZDojZmZmOGU2OyBib3JkZXItbGVmdDo1cHggc29saWQgI2Q2OWUyZTsgcGFkZGluZzoxMHB4IDE0cHg7IG1hcmdpbjoxMnB4IDA7fQ0KLmNvZGlnby1kZXRhbGxlIHttYXJnaW46MTRweCAwOyBib3JkZXI6MXB4IHNvbGlkICNjYmQ1ZTE7IGJvcmRlci1yYWRpdXM6OHB4OyBiYWNrZ3JvdW5kOiNmOGZhZmM7fQ0KLmNvZGlnby1kZXRhbGxlIHN1bW1hcnkge2N1cnNvcjpwb2ludGVyOyBwYWRkaW5nOjExcHggMTRweDsgY29sb3I6IzE3MzY1RDsgZm9udC13ZWlnaHQ6NzAwO30NCi5jb2RpZ28tZGV0YWxsZSBwcmUge21hcmdpbjowOyBwYWRkaW5nOjE0cHg7IG92ZXJmbG93LXg6YXV0bzsgYmFja2dyb3VuZDojZjFmNWY5OyBib3JkZXItdG9wOjFweCBzb2xpZCAjY2JkNWUxOyB3aGl0ZS1zcGFjZTpwcmUtd3JhcDt9DQouZGVzY3JpcGNpb24tZ3JhZmljbyB7bWFyZ2luOjEycHggMCAyNHB4OyBwYWRkaW5nOjEycHggMTZweDsgYmFja2dyb3VuZDojZWVmNWZiOyBib3JkZXItbGVmdDo0cHggc29saWQgIzI4NzRBNjsgYm9yZGVyLXJhZGl1czo0cHg7fQ0KLmludGVycHJldGFjaW9uIHttYXJnaW46MTJweCAwIDIycHg7IHBhZGRpbmc6MTJweCAxNnB4OyBiYWNrZ3JvdW5kOiNmNGY2Zjg7IGJvcmRlci1sZWZ0OjNweCBzb2xpZCAjNjQ3YjkxOyBib3JkZXItcmFkaXVzOjNweDsgY29sb3I6IzM0NDQ1NDt9DQouaW50ZXJwcmV0YWNpb24gc3Ryb25nIHtjb2xvcjojMTczNjVEO30NCjwvc3R5bGU+DQpgYGANCg0KIyBQcmVzZW50YWNpw7NuDQoNCkVzdGUgaW5mb3JtZSBkZXNhcnJvbGxhIHVuIGFuw6FsaXNpcyBleHBsb3JhdG9yaW8gZGUgbG9zIHJlZ2lzdHJvcyBkZSBjb21wYXJlbmRvcyBpbmNsdWlkb3MgZW4gZWwgYXJjaGl2byBzdW1pbmlzdHJhZG8uIFNlIHV0aWxpemEgbGEgaG9qYSAqKkRhdGEgT3JpZ2luYWwgKDIpKiogcG9ycXVlIGNvbnRpZW5lIDE3IHZhcmlhYmxlcywgZW50cmUgZWxsYXMgZ8OpbmVybyBvIHRpcG8gZGUgZWplY3V0YWRvLCBkZXNjcmlwY2nDs24gZGUgbGEgaW5mcmFjY2nDs24sIGZlY2hhLCBkw61hIGRlIGxhIHNlbWFuYSB5IHRpcG8gZGUgdmVow61jdWxvLg0KDQpFbCBkb2N1bWVudG8gZXN0w6EgZGlzZcOxYWRvIHBhcmEgcXVlIGVsIGPDs2RpZ28gcHVlZGEgY29uc3VsdGFyc2UgeSBlamVjdXRhcnNlLiBDYWRhIGJsb3F1ZSBkZSBjw7NkaWdvIGRpc3BvbmUgZGUgdW5hIGV4cGxpY2FjacOzbiBmdW5jaW9uYWwgeSB1bmEgbm90YSBkZSBpbnRlcnByZXRhY2nDs24uIExvcyBncsOhZmljb3MgcGVybWFuZWNlbiBmaWpvcywgc2luIGNvbnRyb2xlcyBwYXJhIGFtcGxpYXIgbyByZWR1Y2lyIGxhIHZpc3RhLCB5IG11ZXN0cmFuIGV0aXF1ZXRhcyBudW3DqXJpY2FzIGRpcmVjdGFtZW50ZSBzb2JyZSBsYXMgYmFycmFzIG8gY29sdW1uYXMgcGFyYSBmYWNpbGl0YXIgbGEgbGVjdHVyYS4gQ3VhbmRvIGNvcnJlc3BvbmRlLCB0YW1iacOpbiBzZSBwdWVkZW4gY29uc3VsdGFyIGRldGFsbGVzIGFsIHBhc2FyIGVsIGN1cnNvcjsgbGFzIHRhYmxhcyBwZXJtaXRlbiBidXNjYXIsIG9yZGVuYXIgeSByZWNvcnJlciByZWdpc3Ryb3MuDQoNCjo6OiBub3RhDQo8c3Ryb25nPkFsY2FuY2U6PC9zdHJvbmc+IGxhIGJhc2UgYW5hbGl6YWRhIGNvbnRpZW5lIHJlZ2lzdHJvcyBmZWNoYWRvcyBlbnRyZSBhYnJpbCB5IG1heW8gZGUgMjAxMC4gUG9yIHRhbnRvLCBsb3MgcmVzdWx0YWRvcyBkZXNjcmliZW4gZXhjbHVzaXZhbWVudGUgZXNlIHBlcmlvZG8geSBubyByZXByZXNlbnRhbiB0b2RvIGVsIGHDsW8gbmkgb3Ryb3MgYcOxb3MuDQo6OjoNCg0KIyBPYmpldGl2b3MNCg0KLSBEZXNjcmliaXIgbGEgZXN0cnVjdHVyYSB5IGNhbGlkYWQgZGUgbGEgYmFzZSBkZSBkYXRvcy4NCi0gSWRlbnRpZmljYXIgbGFzIGluZnJhY2Npb25lcyBtw6FzIGZyZWN1ZW50ZXMuDQotIEV4YW1pbmFyIGxhIGRpc3RyaWJ1Y2nDs24gZGUgY29tcGFyZW5kb3MgcG9yIG1lcywgZMOtYSBkZSBsYSBzZW1hbmEgeSBmZWNoYS4NCi0gQ29tcGFyYXIgbG9zIHJlZ2lzdHJvcyBwb3IgZ8OpbmVybyBvIHRpcG8gZGUgZWplY3V0YWRvIHkgdGlwbyBkZSB2ZWjDrWN1bG8uDQotIERlamFyIGRvY3VtZW50YWRvIGVsIGPDs2RpZ28gdXRpbGl6YWRvIHBhcmEgcXVlIHB1ZWRhIHJlcHJvZHVjaXJzZSBlbCBhbsOhbGlzaXMuDQoNCjo6OiBpbnRlcnByZXRhY2lvbg0KPHN0cm9uZz5FbmZvcXVlIGRlbCBhbsOhbGlzaXM6PC9zdHJvbmc+IEVsIGluZm9ybWUgdGllbmUgdW4gYWxjYW5jZSBkZXNjcmlwdGl2bzogY2FyYWN0ZXJpemEgbG9zIHJlZ2lzdHJvcywgaWRlbnRpZmljYSBmcmVjdWVuY2lhcyB5IGNvbXBhcmEgY2F0ZWdvcsOtYXMuIExvcyByZXN1bHRhZG9zIG5vIHBlcm1pdGVuIGVzdGFibGVjZXIgY2F1c2FzIG5pIGF0cmlidWlyIHJlc3BvbnNhYmlsaWRhZGVzOyBzZSBsaW1pdGFuIGEgbGEgaW5mb3JtYWNpw7NuIGNvbnRlbmlkYSBlbiBlbCBhcmNoaXZvLg0KOjo6DQoNCiMgUHJlcGFyYWNpw7NuIGRlbCBlbnRvcm5vDQoNCiMjIMK/UXXDqSBoYWNlIGVzdGUgY8OzZGlnbz8NCg0KQ2FyZ2EgbGFzIGJpYmxpb3RlY2FzIHF1ZSBwZXJtaXRlbiBpbXBvcnRhciBFeGNlbCwgdHJhbnNmb3JtYXIgbG9zIGRhdG9zLCBjb25zdHJ1aXIgZ3LDoWZpY29zIGludGVyYWN0aXZvcyB5IHByZXNlbnRhciB0YWJsYXMgY29uIG9wY2lvbmVzIGRlIGLDunNxdWVkYS4gU2kgYWxndW5hIGJpYmxpb3RlY2Egbm8gZXN0w6EgaW5zdGFsYWRhLCBlbCBjw7NkaWdvIGxhIGluc3RhbGEgYXV0b23DoXRpY2FtZW50ZS4NCg0KYGBge3IgcGFxdWV0ZXMsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9DQojIExpc3RhIGRlIGJpYmxpb3RlY2FzIG5lY2VzYXJpYXMgcGFyYSBpbXBvcnRhciwgdHJhbnNmb3JtYXIgeSB2aXN1YWxpemFyIGxvcyBkYXRvcy4NCnBhcXVldGVzIDwtIGMoInJlYWR4bCIsICJkcGx5ciIsICJnZ3Bsb3QyIiwgInBsb3RseSIsICJEVCIsICJrbml0ciIsICJzY2FsZXMiLCAibHVicmlkYXRlIiwgInN0cmluZ3IiLCAidGlkeXIiLCAiaHRtbHRvb2xzIikNCg0KZmFsdGFudGVzIDwtIHBhcXVldGVzWyFwYXF1ZXRlcyAlaW4lIHJvd25hbWVzKGluc3RhbGxlZC5wYWNrYWdlcygpKV0NCmlmIChsZW5ndGgoZmFsdGFudGVzKSA+IDApIHsNCiAgaW5zdGFsbC5wYWNrYWdlcyhmYWx0YW50ZXMsIHJlcG9zID0gImh0dHBzOi8vY2xvdWQuci1wcm9qZWN0Lm9yZyIpDQp9DQoNCmludmlzaWJsZShsYXBwbHkocGFxdWV0ZXMsIGxpYnJhcnksIGNoYXJhY3Rlci5vbmx5ID0gVFJVRSkpDQpgYGANCg0KYGBge3IgZnVuY2lvbi1tb3N0cmFyLWNvZGlnbywgaW5jbHVkZT1GQUxTRX0NCm1vc3RyYXJfY29kaWdvIDwtIGZ1bmN0aW9uKGV0aXF1ZXRhKSB7DQogIGxpbmVhcyA8LSBrbml0cjo6a25pdF9jb2RlJGdldChldGlxdWV0YSkNCiAgaWYgKGlzLm51bGwobGluZWFzKSkgcmV0dXJuKGludmlzaWJsZShOVUxMKSkNCiAgY29kaWdvIDwtIHBhc3RlKGxpbmVhcywgY29sbGFwc2UgPSAiXG4iKQ0KICBodG1sdG9vbHM6OkhUTUwocGFzdGUwKA0KICAgICc8ZGV0YWlscyBjbGFzcz0iY29kaWdvLWRldGFsbGUiPjxzdW1tYXJ5Pk1vc3RyYXIgY8OzZGlnbyBSIGRlIGVzdGUgZ3LDoWZpY288L3N1bW1hcnk+PHByZT48Y29kZT4nLA0KICAgIGh0bWx0b29sczo6aHRtbEVzY2FwZShjb2RpZ28pLA0KICAgICc8L2NvZGU+PC9wcmU+PC9kZXRhaWxzPicNCiAgKSkNCn0NCg0KIyBDb252aWVydGUgbG9zIGdyw6FmaWNvcyBkZSBnZ3Bsb3QgZW4gdmlzdWFsaXphY2lvbmVzIFBsb3RseSBzaW4gYmFycmEgZGUgem9vbS4NCiMgU2UgY29uc2VydmEgbGEgY29uc3VsdGEgZGUgZGF0b3MgYWwgcGFzYXIgZWwgY3Vyc29yLCBwZXJvIHNlIGRlc2FjdGl2YW4gbG9zIGNvbnRyb2xlcw0KIyBkZSBhbXBsaWFyLCByZWR1Y2lyLCBkZXNwbGF6YXIgeSBzZWxlY2Npb25hciDDoXJlYXMgZGVsIGdyw6FmaWNvLg0KZ3JhZmljb19zaW5fem9vbSA8LSBmdW5jdGlvbihncmFmaWNvKSB7DQogIHBsb3RseTo6Z2dwbG90bHkoZ3JhZmljbywgdG9vbHRpcCA9ICJ0ZXh0IikgJT4lDQogICAgcGxvdGx5OjpsYXlvdXQoZHJhZ21vZGUgPSBGQUxTRSkgJT4lDQogICAgcGxvdGx5Ojpjb25maWcoZGlzcGxheU1vZGVCYXIgPSBGQUxTRSwgc2Nyb2xsWm9vbSA9IEZBTFNFLCBkb3VibGVDbGljayA9IEZBTFNFKQ0KfQ0KDQpgYGANCg0KOjo6IGludGVycHJldGFjaW9uDQo8c3Ryb25nPkZ1bmNpw7NuIGRlIGxhcyBiaWJsaW90ZWNhczo8L3N0cm9uZz4gTGFzIGJpYmxpb3RlY2FzIGFtcGzDrWFuIGxhcyBmdW5jaW9uZXMgZGUgUiB1dGlsaXphZGFzIGVuIGVsIHByb3llY3RvOiA8Y29kZT5yZWFkeGw8L2NvZGU+IGltcG9ydGEgbGlicm9zIGRlIEV4Y2VsOyA8Y29kZT5kcGx5cjwvY29kZT4gdHJhbnNmb3JtYSB5IHJlc3VtZSB0YWJsYXM7IDxjb2RlPmdncGxvdDI8L2NvZGU+IGNvbnN0cnV5ZSBncsOhZmljb3M7IDxjb2RlPnBsb3RseTwvY29kZT4gYcOxYWRlIGNvbnN1bHRhIGludGVyYWN0aXZhOyB5IDxjb2RlPkRUPC9jb2RlPiBwcmVzZW50YSB0YWJsYXMgY29uIGLDunNxdWVkYSB5IGZpbHRyb3MuIEVsIGJsb3F1ZSB2ZXJpZmljYSBlIGluc3RhbGEgbG9zIHBhcXVldGVzIHF1ZSBubyBlc3TDqW4gZGlzcG9uaWJsZXMuDQo6OjoNCg0KIyBJbXBvcnRhY2nDs24gZGUgbG9zIGRhdG9zDQoNCiMjIMK/UXXDqSBoYWNlIGVzdGUgY8OzZGlnbz8NCg0KTGVlIGxhIGhvamEgKipEYXRhIE9yaWdpbmFsICgyKSoqIGRlbCBsaWJybyBkZSBFeGNlbC4gU2kgZWwgYXJjaGl2byBubyBlc3TDoSBlbiBsYSBjYXJwZXRhIGRlIHRyYWJham8gZGUgUiwgc2UgZGViZSBzZWxlY2Npb25hciBvIGNvcGlhciBhbGzDrS4gTHVlZ28gbXVlc3RyYSBsYXMgcHJpbWVyYXMgZmlsYXMgcGFyYSBjb21wcm9iYXIgcXVlIGxhIGltcG9ydGFjacOzbiBzZSByZWFsaXrDsyBjb3JyZWN0YW1lbnRlLg0KDQpgYGB7ciBpbXBvcnRhci1kYXRvc30NCiMgT2J0aWVuZSBlbCBub21icmUgZGVsIEV4Y2VsIGluZGljYWRvIGVuIGxvcyBwYXLDoW1ldHJvcyBkZWwgaW5mb3JtZS4NCmFyY2hpdm8gPC0gcGFyYW1zJGFyY2hpdm8NCg0KaWYgKCFmaWxlLmV4aXN0cyhhcmNoaXZvKSkgew0KICBtZXNzYWdlKCJTZWxlY2Npb25hIGVsIGFyY2hpdm8gRXhjZWwgZGUgY29tcGFyZW5kb3MiKQ0KICBhcmNoaXZvIDwtIGZpbGUuY2hvb3NlKCkNCn0NCg0KYmFzZV9vcmlnaW5hbCA8LSByZWFkeGw6OnJlYWRfZXhjZWwoYXJjaGl2bywgc2hlZXQgPSBwYXJhbXMkaG9qYSkNCg0KY2F0KCJGaWxhczoiLCBucm93KGJhc2Vfb3JpZ2luYWwpLCAifCBDb2x1bW5hczoiLCBuY29sKGJhc2Vfb3JpZ2luYWwpKQ0Ka25pdHI6OmthYmxlKGhlYWQoYmFzZV9vcmlnaW5hbCwgNiksIGNhcHRpb24gPSAiUHJpbWVyb3Mgc2VpcyByZWdpc3Ryb3MgaW1wb3J0YWRvcyIpDQoNCmBgYA0KDQo6OjogaW50ZXJwcmV0YWNpb24NCjxzdHJvbmc+Q3JpdGVyaW8gZGUgaW1wb3J0YWNpw7NuOjwvc3Ryb25nPiBMYSBmdW5jacOzbiA8Y29kZT5yZWFkX2V4Y2VsKCk8L2NvZGU+IGNhcmdhIGxhIGhvamEgZGVmaW5pZGEgZW4gbG9zIHBhcsOhbWV0cm9zIGRlbCBpbmZvcm1lLiBMYSByZXZpc2nDs24gZGUgZGltZW5zaW9uZXMgeSBkZSBsYXMgcHJpbWVyYXMgZmlsYXMgcGVybWl0ZSBjb21wcm9iYXIgcXVlIGxhIGxlY3R1cmEgc2UgcmVhbGl6w7MgY29ycmVjdGFtZW50ZSB5IHF1ZSBzZSBpbXBvcnRhcm9uIGxhcyB2YXJpYWJsZXMgcHJldmlzdGFzLg0KOjo6DQoNCiMgRXhwbG9yYWNpw7NuIHkgY2FsaWRhZCBkZSBsb3MgZGF0b3MNCg0KIyMgwr9RdcOpIGhhY2UgZXN0ZSBjw7NkaWdvPw0KDQpDb25zdWx0YSBsb3Mgbm9tYnJlcyB5IHRpcG9zIGRlIGNvbHVtbmFzLCBjdWVudGEgbG9zIHZhbG9yZXMgZmFsdGFudGVzIHkgZGV0ZWN0YSByZWdpc3Ryb3MgZHVwbGljYWRvcy4gTGEgcmV2aXNpw7NuIG5vIGVsaW1pbmEgZmlsYXMgYXV0b23DoXRpY2FtZW50ZTogcHJpbWVybyBpbmZvcm1hIGxvcyBoYWxsYXpnb3MgcGFyYSBxdWUgbGEgZGVjaXNpw7NuIGRlIGRlcHVyYWNpw7NuIHNlYSB0cmFuc3BhcmVudGUuDQoNCmBgYHtyIGVzdHJ1Y3R1cmEtY2FsaWRhZH0NCiMgTm9ybWFsaXphciBlc3BhY2lvcyBzb2JyYW50ZXMgZW4gbG9zIG5vbWJyZXMgZGUgbGFzIGNvbHVtbmFzIHBhcmEgZXZpdGFyIGVycm9yZXMgYWwgcmVmZXJlbmNpYXIgdmFyaWFibGVzDQpuYW1lcyhiYXNlX29yaWdpbmFsKSA8LSB0cmltd3MobmFtZXMoYmFzZV9vcmlnaW5hbCkpDQoNCiMgUmVzdW1lbiBkZSBkaW1lbnNpb25lcyB5IHRpcG9zIGRlIHZhcmlhYmxlcw0KY2F0KCJOw7ptZXJvIGRlIHJlZ2lzdHJvczoiLCBucm93KGJhc2Vfb3JpZ2luYWwpLCAiXG4iKQ0KY2F0KCJOw7ptZXJvIGRlIHZhcmlhYmxlczoiLCBuY29sKGJhc2Vfb3JpZ2luYWwpLCAiXG5cbiIpDQpzdHIoYmFzZV9vcmlnaW5hbCkNCg0KIyBWYWxvcmVzIHZhY8Otb3MgcG9yIGNvbHVtbmENCmZhbHRhbnRlcyA8LSBkYXRhLmZyYW1lKA0KICB2YXJpYWJsZSA9IG5hbWVzKGJhc2Vfb3JpZ2luYWwpLA0KICB2YWxvcmVzX2ZhbHRhbnRlcyA9IHZhcHBseShiYXNlX29yaWdpbmFsLCBmdW5jdGlvbih4KSBzdW0oaXMubmEoeCkgfCB0cmltd3MoYXMuY2hhcmFjdGVyKHgpKSA9PSAiIiksIG51bWVyaWMoMSkpDQopDQpEVDo6ZGF0YXRhYmxlKGZhbHRhbnRlcywgcm93bmFtZXMgPSBGQUxTRSwgb3B0aW9ucyA9IGxpc3QocGFnZUxlbmd0aCA9IDE3LCBzZWFyY2hpbmcgPSBGQUxTRSksDQogICAgICAgICAgICAgIGNhcHRpb24gPSAiVmFsb3JlcyBmYWx0YW50ZXMgcG9yIHZhcmlhYmxlIikNCg0KIyBEdXBsaWNhZG9zIGV4YWN0b3MgeSByZXBldGljacOzbiBkZSBpZGVudGlmaWNhZG9yZXMNCmNhdCgiRmlsYXMgZHVwbGljYWRhcyBleGFjdGFzOiIsIHN1bShkdXBsaWNhdGVkKGJhc2Vfb3JpZ2luYWwpKSwgIlxuIikNCmlmICgiQ09NUEFSRU5ETyIgJWluJSBuYW1lcyhiYXNlX29yaWdpbmFsKSkgew0KICBjYXQoIk7Dum1lcm9zIGRlIGNvbXBhcmVuZG8gcmVwZXRpZG9zIChmaWxhcyBhZGljaW9uYWxlcyk6Iiwgc3VtKGR1cGxpY2F0ZWQoYmFzZV9vcmlnaW5hbCRDT01QQVJFTkRPKSksICJcbiIpDQp9DQppZiAoIk5vLiBNQU5EQU1JRU5UTyBERSBQQUdPIiAlaW4lIG5hbWVzKGJhc2Vfb3JpZ2luYWwpKSB7DQogIGNhdCgiTWFuZGFtaWVudG9zIHJlcGV0aWRvcyAoZmlsYXMgYWRpY2lvbmFsZXMpOiIsIHN1bShkdXBsaWNhdGVkKGJhc2Vfb3JpZ2luYWwkYE5vLiBNQU5EQU1JRU5UTyBERSBQQUdPYCkpLCAiXG4iKQ0KfQ0KDQpgYGANCg0KOjo6IGludGVycHJldGFjaW9uDQo8c3Ryb25nPkNvbnRyb2wgZGUgY2FsaWRhZDo8L3N0cm9uZz4gTGEgaW5zcGVjY2nDs24gZGUgZXN0cnVjdHVyYSBpZGVudGlmaWNhIGxvcyB0aXBvcyBkZSB2YXJpYWJsZXM7IGVsIGNvbnRlbyBkZSB2YWxvcmVzIGZhbHRhbnRlcyBzZcOxYWxhIGNhbXBvcyBpbmNvbXBsZXRvczsgeSA8Y29kZT5kdXBsaWNhdGVkKCk8L2NvZGU+IGRldGVjdGEgcmVwZXRpY2lvbmVzIGV4YWN0YXMgbyBkZSBpZGVudGlmaWNhZG9yZXMuIExvcyByZWdpc3Ryb3MgcmVwZXRpZG9zIHNlIHJlcG9ydGFuIHBhcmEgdmFsaWRhY2nDs24geSBubyBzZSBlbGltaW5hbiBzaW4gY29tcHJvYmFyIHN1IG5hdHVyYWxlemEuDQo6OjoNCg0KIyBMaW1waWV6YSB5IHRyYW5zZm9ybWFjacOzbg0KDQojIyDCv1F1w6kgaGFjZSBlc3RlIGPDs2RpZ28/DQoNCkNyZWEgdW5hIGNvcGlhIGRlIHRyYWJham8sIGVsaW1pbmEgZXNwYWNpb3Mgc29icmFudGVzIGVuIGxvcyB0ZXh0b3MsIGNvbnZpZXJ0ZSBsYXMgZmVjaGFzIGFsIGZvcm1hdG8gZGUgZmVjaGEgZGUgUiB5IGNvbnZpZXJ0ZSBsYXMgdmFyaWFibGVzIG51bcOpcmljYXMgYSBzdSB0aXBvIGNvcnJlc3BvbmRpZW50ZS4gVGFtYmnDqW4gY3JlYSB1bmEgZXRpcXVldGEgZGUgZmVjaGEgeSBvcmRlbmEgbG9zIG1lc2VzIHkgZMOtYXMgZGUgbGEgc2VtYW5hIHBhcmEgcXVlIGxvcyBncsOhZmljb3MgYXBhcmV6Y2FuIGVuIHNlY3VlbmNpYS4gTm8gZWxpbWluYSBkdXBsaWNhZG9zIHNpbiBhdXRvcml6YWNpw7NuLg0KDQpgYGB7ciBsaW1waWV6YX0NCiMgQ3JlYSB1bmEgY29waWEgZGUgdHJhYmFqbzsgbGEgdGFibGEgb3JpZ2luYWwgc2UgY29uc2VydmEgc2luIG1vZGlmaWNhY2lvbmVzLg0KYmFzZSA8LSBiYXNlX29yaWdpbmFsICU+JQ0KICBtdXRhdGUoYWNyb3NzKHdoZXJlKGlzLmNoYXJhY3RlciksIH4gc3RyaW5ncjo6c3RyX3NxdWlzaCgueCkpKSAlPiUNCiAgbXV0YXRlKA0KICAgIGBGRUNIQSBERSBDT01QQVJFTkRPYCA9IGFzLkRhdGUoYEZFQ0hBIERFIENPTVBBUkVORE9gKSwNCiAgICBBw5FPID0gYXMuaW50ZWdlcihBw5FPKSwNCiAgICBNRVMgPSBhcy5pbnRlZ2VyKE1FUyksDQogICAgRElBID0gYXMuaW50ZWdlcihESUEpLA0KICAgIGBDT0QuIElORlJBQ0NJT05gID0gYXMuaW50ZWdlcihgQ09ELiBJTkZSQUNDSU9OYCksDQogICAgTk9NLk1FUyA9IGZhY3Rvcih0b3VwcGVyKGBOT00gTUVTYCksIGxldmVscyA9IGMoIkVORVJPIiwgIkZFQlJFUk8iLCAiTUFSWk8iLCAiQUJSSUwiLCAiTUFZTyIsICJKVU5JTyIsICJKVUxJTyIsICJBR09TVE8iLCAiU0VQVElFTUJSRSIsICJPQ1RVQlJFIiwgIk5PVklFTUJSRSIsICJESUNJRU1CUkUiKSksDQogICAgTk9NLkRJQSA9IGZhY3Rvcih0b3VwcGVyKGBOT00gRElBYCksIGxldmVscyA9IGMoIkxVTkVTIiwgIk1BUlRFUyIsICJNScOJUkNPTEVTIiwgIkpVRVZFUyIsICJWSUVSTkVTIiwgIlPDgUJBRE8iLCAiRE9NSU5HTyIpKQ0KICApDQoNCiMgQ29tcHJvYmFjacOzbiBkZSBmZWNoYXMgeSB2YXJpYWJsZXMgcHJpbmNpcGFsZXMNCnN1bW1hcnkoYmFzZSRgRkVDSEEgREUgQ09NUEFSRU5ET2ApDQpzdW1tYXJ5KGJhc2UkYENPRC4gSU5GUkFDQ0lPTmApDQoNCmBgYA0KDQo6OjogaW50ZXJwcmV0YWNpb24NCjxzdHJvbmc+Q3JpdGVyaW8gZGUgdHJhbnNmb3JtYWNpw7NuOjwvc3Ryb25nPiBMYSB0cmFuc2Zvcm1hY2nDs24gZXN0YW5kYXJpemEgZXNwYWNpb3MgeSB0aXBvcyBkZSBkYXRvcyBwYXJhIGZhY2lsaXRhciBsb3MgY8OhbGN1bG9zLiBMYXMgZmVjaGFzIHkgdmFyaWFibGVzIG51bcOpcmljYXMgc2UgY29udmllcnRlbiBhIGZvcm1hdG9zIGFkZWN1YWRvcywgbWllbnRyYXMgcXVlIGxvcyBtZXNlcyB5IGTDrWFzIHNlIG9yZGVuYW4gY3Jvbm9sw7NnaWNhbWVudGUuIExhIHRhYmxhIGltcG9ydGFkYSBzZSBjb25zZXJ2YSB5IGxhcyBvcGVyYWNpb25lcyBzZSByZWFsaXphbiBzb2JyZSB1bmEgY29waWEgZGUgdHJhYmFqby4NCjo6Og0KDQojIEluZGljYWRvcmVzIGdlbmVyYWxlcw0KDQojIyDCv1F1w6kgaGFjZSBlc3RlIGPDs2RpZ28/DQoNCkNhbGN1bGEgaW5kaWNhZG9yZXMgYsOhc2ljb3MgYSBwYXJ0aXIgZGUgbG9zIHJlZ2lzdHJvcyBkaXNwb25pYmxlczogdG90YWwgZGUgY29tcGFyZW5kb3MsIGZlY2hhcyBtw61uaW1hIHkgbcOheGltYSwgY2FudGlkYWQgZGUgY8OzZGlnb3MgZGUgaW5mcmFjY2nDs24geSBuw7ptZXJvIGRlIHRpcG9zIGRlIHZlaMOtY3Vsby4gU29uIGluZGljYWRvcmVzIGRlc2NyaXB0aXZvcywgbm8gZXN0aW1hY2lvbmVzIHBhcmEgb3Ryb3MgcGVyaW9kb3MuDQoNCmBgYHtyIGluZGljYWRvcmVzfQ0KIyBDb25zdHJ1eWUgdW5hIHRhYmxhIGNvbiBtZWRpZGFzIGRlc2NyaXB0aXZhcyBnZW5lcmFsZXMgZGUgbGEgYmFzZS4NCmluZGljYWRvcmVzIDwtIGRhdGEuZnJhbWUoDQogIEluZGljYWRvciA9IGMoIlJlZ2lzdHJvcyBhbmFsaXphZG9zIiwgIkZlY2hhIGluaWNpYWwiLCAiRmVjaGEgZmluYWwiLCAiQ8OzZGlnb3MgZGUgaW5mcmFjY2nDs24iLCAiVGlwb3MgZGUgdmVow61jdWxvIiksDQogIFJlc3VsdGFkbyA9IGMoDQogICAgZm9ybWF0KG5yb3coYmFzZSksIGJpZy5tYXJrID0gIi4iKSwNCiAgICBmb3JtYXQobWluKGJhc2UkYEZFQ0hBIERFIENPTVBBUkVORE9gLCBuYS5ybSA9IFRSVUUpLCAiJWQvJW0vJVkiKSwNCiAgICBmb3JtYXQobWF4KGJhc2UkYEZFQ0hBIERFIENPTVBBUkVORE9gLCBuYS5ybSA9IFRSVUUpLCAiJWQvJW0vJVkiKSwNCiAgICBkcGx5cjo6bl9kaXN0aW5jdChiYXNlJGBDT0QuIElORlJBQ0NJT05gLCBuYS5ybSA9IFRSVUUpLA0KICAgIGRwbHlyOjpuX2Rpc3RpbmN0KGJhc2UkVkVISUNVTE8sIG5hLnJtID0gVFJVRSkNCiAgKQ0KKQ0Ka25pdHI6OmthYmxlKGluZGljYWRvcmVzLCBjb2wubmFtZXMgPSBjKCJJbmRpY2Fkb3IiLCAiUmVzdWx0YWRvIiksIGNhcHRpb24gPSAiUmVzdW1lbiBnZW5lcmFsIGRlIGxhIGJhc2UiKQ0KDQpgYGANCg0KOjo6IGludGVycHJldGFjaW9uDQo8c3Ryb25nPkxlY3R1cmEgZGUgbG9zIGluZGljYWRvcmVzOjwvc3Ryb25nPiBMb3MgaW5kaWNhZG9yZXMgcmVzdW1lbiBlbCB2b2x1bWVuIHkgZWwgYWxjYW5jZSB0ZW1wb3JhbCBkZSBsb3MgcmVnaXN0cm9zLiBFbCBuw7ptZXJvIGRlIGZpbGFzIHJlcHJlc2VudGEgbG9zIGNhc29zIGluY2x1aWRvczsgbGFzIGZlY2hhcyBtw61uaW1hIHkgbcOheGltYSBkZWxpbWl0YW4gZWwgcGVyaW9kbzsgeSBsb3MgY29udGVvcyBkaXN0aW50b3MgZGVzY3JpYmVuIGxhIHZhcmllZGFkIGRlIGPDs2RpZ29zIHkgdGlwb3MgZGUgdmVow61jdWxvIG9ic2VydmFkb3MuDQo6OjoNCg0KIyBBbsOhbGlzaXMgZGUgaW5mcmFjY2lvbmVzDQoNCiMjIEluZnJhY2Npb25lcyBtw6FzIGZyZWN1ZW50ZXMNCg0KIyMjIMK/UXXDqSBoYWNlIGVzdGUgY8OzZGlnbz8NCg0KQWdydXBhIGxvcyByZWdpc3Ryb3MgcG9yIGPDs2RpZ28geSBkZXNjcmlwY2nDs24gZGUgbGEgaW5mcmFjY2nDs24sIGN1ZW50YSBjdcOhbnRhcyB2ZWNlcyBhcGFyZWNlIGNhZGEgdW5hIHkgb3JkZW5hIGxvcyByZXN1bHRhZG9zIGRlIG1heW9yIGEgbWVub3IuIEVsIGdyw6FmaWNvIGluY2x1eWUgZXRpcXVldGFzIG51bcOpcmljYXMgYWwgZmluYWwgZGUgY2FkYSBiYXJyYSB5IHBlcm1pdGUgY29uc3VsdGFyIGRldGFsbGVzIGFsIHBhc2FyIGVsIGN1cnNvciwgc2luIG1vc3RyYXIgYm90b25lcyBkZSB6b29tLg0KDQpgYGB7ciBpbmZyYWNjaW9uZXMsIGVjaG89RkFMU0UsIGZpZy53aWR0aD0xMCwgZmlnLmhlaWdodD02fQ0KIyBDdWVudGEgcmVnaXN0cm9zIHBvciBjw7NkaWdvIHkgZGVzY3JpcGNpw7NuIGRlIGluZnJhY2Npw7NuLCBkZSBtYXlvciBhIG1lbm9yIGZyZWN1ZW5jaWEuDQpmcmVjdWVuY2lhX2luZnJhY2Npb25lcyA8LSBiYXNlICU+JQ0KICBjb3VudChgQ09ELiBJTkZSQUNDSU9OYCwgYE5PTS5JTkZSQUNDSU9OYCwgbmFtZSA9ICJjYW50aWRhZCIsIHNvcnQgPSBUUlVFKQ0KDQprbml0cjo6a2FibGUoZnJlY3VlbmNpYV9pbmZyYWNjaW9uZXMsIGNhcHRpb24gPSAiRnJlY3VlbmNpYSBwb3IgY8OzZGlnbyB5IGRlc2NyaXBjacOzbiBkZSBpbmZyYWNjacOzbiIpDQoNCmdyYWZpY29faW5mcmFjY2lvbmVzIDwtIGdncGxvdChmcmVjdWVuY2lhX2luZnJhY2Npb25lcywNCiAgYWVzKHggPSByZW9yZGVyKHBhc3RlMCgiQ8OzZGlnbyAiLCBgQ09ELiBJTkZSQUNDSU9OYCksIGNhbnRpZGFkKSwgeSA9IGNhbnRpZGFkLA0KICAgICAgdGV4dCA9IHBhc3RlMCgiQ8OzZGlnbzogIiwgYENPRC4gSU5GUkFDQ0lPTmAsICI8YnI+SW5mcmFjY2nDs246ICIsIE5PTS5JTkZSQUNDSU9OLA0KICAgICAgICAgICAgICAgICAgICAiPGJyPlJlZ2lzdHJvczogIiwgY2FudGlkYWQpKSkgKw0KICBnZW9tX2NvbChmaWxsID0gIiMxNzZCODciLCB3aWR0aCA9IDAuNykgKw0KICBnZW9tX3RleHQoYWVzKGxhYmVsID0gY2FudGlkYWQpLCBoanVzdCA9IC0wLjE1LCBzaXplID0gMy41LA0KICAgICAgICAgICAgY29sb3IgPSAiIzI2MzQ0NSIsIGZvbnRmYWNlID0gImJvbGQiKSArDQogIGNvb3JkX2ZsaXAoKSArDQogIHNjYWxlX3lfY29udGludW91cyhleHBhbmQgPSBleHBhbnNpb24obXVsdCA9IGMoMCwgMC4xNSkpKSArDQogIGxhYnModGl0bGUgPSAiSW5mcmFjY2lvbmVzIG3DoXMgZnJlY3VlbnRlcyIsIHggPSAiQ8OzZGlnbyBkZSBpbmZyYWNjacOzbiIsIHkgPSAiQ2FudGlkYWQgZGUgY29tcGFyZW5kb3MiKSArDQogIHRoZW1lX21pbmltYWwoYmFzZV9zaXplID0gMTIpDQpncmFmaWNvX3Npbl96b29tKGdyYWZpY29faW5mcmFjY2lvbmVzKQ0KbW9zdHJhcl9jb2RpZ28oImluZnJhY2Npb25lcyIpDQpgYGANCg0KOjo6IGRlc2NyaXBjaW9uLWdyYWZpY28NCjxzdHJvbmc+wr9Dw7NtbyBmdW5jaW9uYT88L3N0cm9uZz4gRWwgY8OzZGlnbyBhZ3J1cGEgbG9zIGNvbXBhcmVuZG9zIHBvciBjw7NkaWdvIHkgbm9tYnJlIGRlIGluZnJhY2Npw7NuLCBjdWVudGEgbG9zIHJlZ2lzdHJvcyB5IGxvcyBvcmRlbmEgZGUgbWF5b3IgYSBtZW5vci4gRGVzcHXDqXMgY29uc3RydXllIGJhcnJhcyBob3Jpem9udGFsZXMgcGFyYSBmYWNpbGl0YXIgbGEgY29tcGFyYWNpw7NuLiBBbCBwYXNhciBlbCBjdXJzb3Igc29icmUgdW5hIGJhcnJhIHNlIGNvbnN1bHRhIGVsIGPDs2RpZ28sIGxhIGRlc2NyaXBjacOzbiB5IGxhIGNhbnRpZGFkLg0KOjo6DQoNCjo6OiBpbnRlcnByZXRhY2lvbg0KPHN0cm9uZz5JbnRlcnByZXRhY2nDs24gZGUgZnJlY3VlbmNpYXM6PC9zdHJvbmc+IENhZGEgYmFycmEgcmVwcmVzZW50YSB1bmEgY29tYmluYWNpw7NuIGRlIGPDs2RpZ28geSBkZXNjcmlwY2nDs24gZGUgaW5mcmFjY2nDs24uIExhIGxvbmdpdHVkIGRlIGxhIGJhcnJhIHkgc3UgZXRpcXVldGEgbXVlc3RyYW4gZWwgbsO6bWVybyBkZSByZWdpc3Ryb3MgYXNvY2lhZG9zLiBFbCBvcmRlbiBkZXNjZW5kZW50ZSBmYWNpbGl0YSBpZGVudGlmaWNhciBsYXMgY2F0ZWdvcsOtYXMgbcOhcyBmcmVjdWVudGVzOyBlc3RvcyBjb250ZW9zIG5vIGV4cGxpY2FuIGxhcyByYXpvbmVzIGRlIHN1IG9jdXJyZW5jaWEuDQo6OjoNCg0KIyBDb21wb3J0YW1pZW50byBwb3IgbWVzDQoNCiMjIENvbXBhcmVuZG9zIHBvciBtZXMNCg0KIyMjIMK/UXXDqSBoYWNlIGVzdGUgY8OzZGlnbz8NCg0KQ3VlbnRhIGxvcyBjb21wYXJlbmRvcyByZWdpc3RyYWRvcyBlbiBjYWRhIG1lcyB5IGxvcyByZXByZXNlbnRhIGVuIHVuIGdyw6FmaWNvIGludGVyYWN0aXZvLiBMYSBiYXNlIGRpc3BvbmlibGUgY29udGllbmUgYWJyaWwgeSBtYXlvIGRlIDIwMTA7IG5vIHNlIG11ZXN0cmFuIG1lc2VzIHNpbiByZWdpc3Ryb3MgY29tbyBzaSBmdWVyYW4gY2VybyBvYnNlcnZhZG9zLg0KDQpgYGB7ciBjb21wYXJlbmRvcy1tZXMsIGVjaG89RkFMU0UsIGZpZy53aWR0aD05LCBmaWcuaGVpZ2h0PTV9DQojIEN1ZW50YSBsb3MgY29tcGFyZW5kb3MgcG9yIG1lcyBvYnNlcnZhZG8gZW4gZWwgYXJjaGl2by4NCnBvcl9tZXMgPC0gYmFzZSAlPiUgY291bnQoTk9NLk1FUywgbmFtZSA9ICJjYW50aWRhZCIpICU+JSBhcnJhbmdlKE5PTS5NRVMpDQoNCmtuaXRyOjprYWJsZShwb3JfbWVzLCBjYXB0aW9uID0gIkNvbXBhcmVuZG9zIHJlZ2lzdHJhZG9zIHBvciBtZXMiKQ0KDQpnX21lcyA8LSBnZ3Bsb3QocG9yX21lcywgYWVzKHggPSBOT00uTUVTLCB5ID0gY2FudGlkYWQsDQogIHRleHQgPSBwYXN0ZTAoIk1lczogIiwgTk9NLk1FUywgIjxicj5Db21wYXJlbmRvczogIiwgY2FudGlkYWQpKSkgKw0KICBnZW9tX2NvbChmaWxsID0gIiNFMDdBMjQiLCB3aWR0aCA9IDAuNjUpICsNCiAgZ2VvbV90ZXh0KGFlcyhsYWJlbCA9IGNhbnRpZGFkKSwgdmp1c3QgPSAtMC40LCBmb250ZmFjZSA9ICJib2xkIikgKw0KICBsYWJzKHRpdGxlID0gIkNvbXBhcmVuZG9zIHBvciBtZXMiLCB4ID0gIk1lcyIsIHkgPSAiQ2FudGlkYWQiKSArDQogIHRoZW1lX21pbmltYWwoYmFzZV9zaXplID0gMTIpDQpncmFmaWNvX3Npbl96b29tKGdfbWVzKQ0KbW9zdHJhcl9jb2RpZ28oImNvbXBhcmVuZG9zLW1lcyIpDQpgYGANCg0KOjo6IGRlc2NyaXBjaW9uLWdyYWZpY28NCjxzdHJvbmc+wr9Dw7NtbyBmdW5jaW9uYT88L3N0cm9uZz4gU2UgY3VlbnRhbiBsb3MgcmVnaXN0cm9zIGRlIGNhZGEgbWVzIHkgc2UgbXVlc3RyYW4gZW4gY29sdW1uYXMuIExhcyBldGlxdWV0YXMgbnVtw6lyaWNhcyBwZXJtaXRlbiBsZWVyIGxhIGNhbnRpZGFkIHNpbiBkZXBlbmRlciBkZWwgY3Vyc29yOyBhbCBwYXNhciBzb2JyZSB1bmEgY29sdW1uYSBzZSBvYnRpZW5lIGVsIGRldGFsbGUgZGVsIG1lcy4NCjo6Og0KDQo6OjogaW50ZXJwcmV0YWNpb24NCjxzdHJvbmc+QWxjYW5jZSB0ZW1wb3JhbCBtZW5zdWFsOjwvc3Ryb25nPiBMYXMgY29sdW1uYXMgY29tcGFyYW4gw7puaWNhbWVudGUgbG9zIG1lc2VzIHByZXNlbnRlcyBlbiBlbCBhcmNoaXZvLiBMYSBhbHR1cmEgcmVwcmVzZW50YSBsYSBjYW50aWRhZCBkZSByZWdpc3Ryb3MgZGUgY2FkYSBtZXMuIExhIGF1c2VuY2lhIGRlIG90cm9zIG1lc2VzIGVuIGVsIGdyw6FmaWNvIGluZGljYSBxdWUgbm8gZXN0w6FuIGluY2x1aWRvcyBlbiBsYSBmdWVudGUsIG5vIHF1ZSBoYXlhbiB0ZW5pZG8gY2VybyBjb21wYXJlbmRvcy4NCjo6Og0KDQojIENvbXBvcnRhbWllbnRvIHBvciBkw61hDQoNCiMjIENvbXBhcmVuZG9zIHBvciBkw61hIGRlIGxhIHNlbWFuYQ0KDQojIyMgwr9RdcOpIGhhY2UgZXN0ZSBjw7NkaWdvPw0KDQpBZ3J1cGEgbG9zIHJlZ2lzdHJvcyBzZWfDum4gZWwgZMOtYSBkZSBsYSBzZW1hbmEgeSBjb25zZXJ2YSBlbCBvcmRlbiBkZSBsdW5lcyBhIGRvbWluZ28uIFBlcm1pdGUgaWRlbnRpZmljYXIgcXXDqSBkw61hcyBjb25jZW50cmFuIG3DoXMgcmVnaXN0cm9zIGRlbnRybyBkZWwgcGVyaW9kbyBhbmFsaXphZG8uDQoNCmBgYHtyIGNvbXBhcmVuZG9zLWRpYSwgZWNobz1GQUxTRSwgZmlnLndpZHRoPTksIGZpZy5oZWlnaHQ9NX0NCiMgQ3VlbnRhIGxvcyByZWdpc3Ryb3MgcG9yIGTDrWEgZGUgbGEgc2VtYW5hLCByZXNwZXRhbmRvIGVsIG9yZGVuIGRlZmluaWRvIGVuIGVsIGZhY3Rvci4NCnBvcl9kaWEgPC0gYmFzZSAlPiUgY291bnQoTk9NLkRJQSwgbmFtZSA9ICJjYW50aWRhZCIpICU+JSBhcnJhbmdlKE5PTS5ESUEpDQoNCmtuaXRyOjprYWJsZShwb3JfZGlhLCBjYXB0aW9uID0gIkNvbXBhcmVuZG9zIHBvciBkw61hIGRlIGxhIHNlbWFuYSIpDQoNCmdfZGlhIDwtIGdncGxvdChwb3JfZGlhLCBhZXMoeCA9IE5PTS5ESUEsIHkgPSBjYW50aWRhZCwNCiAgdGV4dCA9IHBhc3RlMCgiRMOtYTogIiwgTk9NLkRJQSwgIjxicj5Db21wYXJlbmRvczogIiwgY2FudGlkYWQpKSkgKw0KICBnZW9tX2NvbChmaWxsID0gIiMzQjdBNTciLCB3aWR0aCA9IDAuNykgKw0KICBnZW9tX3RleHQoYWVzKGxhYmVsID0gY2FudGlkYWQpLCB2anVzdCA9IC0wLjQsIHNpemUgPSAzLjUsDQogICAgICAgICAgICBjb2xvciA9ICIjMjYzNDQ1IiwgZm9udGZhY2UgPSAiYm9sZCIpICsNCiAgc2NhbGVfeV9jb250aW51b3VzKGV4cGFuZCA9IGV4cGFuc2lvbihtdWx0ID0gYygwLCAwLjEyKSkpICsNCiAgbGFicyh0aXRsZSA9ICJEaXN0cmlidWNpw7NuIHBvciBkw61hIGRlIGxhIHNlbWFuYSIsIHggPSAiRMOtYSIsIHkgPSAiQ2FudGlkYWQgZGUgY29tcGFyZW5kb3MiKSArDQogIHRoZW1lX21pbmltYWwoYmFzZV9zaXplID0gMTIpDQpncmFmaWNvX3Npbl96b29tKGdfZGlhKQ0KbW9zdHJhcl9jb2RpZ28oImNvbXBhcmVuZG9zLWRpYSIpDQpgYGANCg0KOjo6IGRlc2NyaXBjaW9uLWdyYWZpY28NCjxzdHJvbmc+wr9Dw7NtbyBmdW5jaW9uYT88L3N0cm9uZz4gU2UgYWdydXBhbiBsb3MgY29tcGFyZW5kb3MgcG9yIGTDrWEgZGUgbGEgc2VtYW5hIHkgc2UgY29uc2VydmEgZWwgb3JkZW4gZGUgbHVuZXMgYSBkb21pbmdvLiBMYSBhbHR1cmEgZGUgY2FkYSBiYXJyYSB5IHN1IGV0aXF1ZXRhIG51bcOpcmljYSByZXByZXNlbnRhbiBsYSBjYW50aWRhZCByZWdpc3RyYWRhIHBhcmEgZXNlIGTDrWEuDQo6OjoNCg0KOjo6IGludGVycHJldGFjaW9uDQo8c3Ryb25nPkRpc3RyaWJ1Y2nDs24gc2VtYW5hbDo8L3N0cm9uZz4gRWwgZ3LDoWZpY28gcHJlc2VudGEgbGEgY2FudGlkYWQgZGUgcmVnaXN0cm9zIHBvciBkw61hIGRlIGxhIHNlbWFuYSwgb3JkZW5hZG9zIGRlIGx1bmVzIGEgZG9taW5nby4gTGFzIGRpZmVyZW5jaWFzIG9ic2VydmFkYXMgZGVzY3JpYmVuIGxhIGRpc3RyaWJ1Y2nDs24gZGUgZXN0YSBtdWVzdHJhIHkgbm8gcGVybWl0ZW4gZXN0YWJsZWNlciBwb3Igc8OtIHNvbGFzIGxhcyBjYXVzYXMgZGUgZXNhIHZhcmlhY2nDs24uDQo6OjoNCg0KIyMgRXZvbHVjacOzbiBkaWFyaWEgZGUgbG9zIHJlZ2lzdHJvcw0KDQojIyMgwr9RdcOpIGhhY2UgZXN0ZSBjw7NkaWdvPw0KDQpDdWVudGEgbG9zIGNvbXBhcmVuZG9zIHBvciBmZWNoYSBleGFjdGEgeSBsb3MgcHJlc2VudGEgZW4gY29sdW1uYXMgdmVydGljYWxlcyBjb24gbGEgY2FudGlkYWQgZXNjcml0YSBlbmNpbWEgZGUgY2FkYSB1bmEuIEFzw60gc2UgY29tcGFyYW4gbG9zIGTDrWFzIHNpbiB1bmEgbMOtbmVhIHF1ZSBwdWVkYSBkYXIgdW5hIGltcHJlc2nDs24gZGUgY29udGludWlkYWQgbyB0ZW5kZW5jaWEgZXhhZ2VyYWRhLg0KDQpgYGB7ciBldm9sdWNpb24tZGlhcmlhLCBlY2hvPUZBTFNFLCBmaWcud2lkdGg9MTAsIGZpZy5oZWlnaHQ9NX0NCiMgQWdydXBhIHBvciBmZWNoYSBleGFjdGEgeSBjdWVudGEgY3XDoW50b3MgY29tcGFyZW5kb3Mgc2UgcmVnaXN0cmFyb24gY2FkYSBkw61hLg0KcG9yX2ZlY2hhIDwtIGJhc2UgJT4lDQogIGNvdW50KGBGRUNIQSBERSBDT01QQVJFTkRPYCwgbmFtZSA9ICJjYW50aWRhZCIpICU+JQ0KICBhcnJhbmdlKGBGRUNIQSBERSBDT01QQVJFTkRPYCkNCg0KZ19mZWNoYSA8LSBnZ3Bsb3QocG9yX2ZlY2hhLCBhZXMoeCA9IGBGRUNIQSBERSBDT01QQVJFTkRPYCwgeSA9IGNhbnRpZGFkKSkgKw0KICBnZW9tX2NvbChmaWxsID0gIiMxNzZCODciLCB3aWR0aCA9IDAuNzgpICsNCiAgZ2VvbV90ZXh0KGFlcyhsYWJlbCA9IGNhbnRpZGFkKSwgdmp1c3QgPSAtMC4zNSwgc2l6ZSA9IDIuOCwNCiAgICAgICAgICAgIGNvbG9yID0gIiMyNjM0NDUiLCBmb250ZmFjZSA9ICJib2xkIikgKw0KICBzY2FsZV94X2RhdGUoZGF0ZV9icmVha3MgPSAiMyBkYXlzIiwgZGF0ZV9sYWJlbHMgPSAiJWQvJW0iLA0KICAgICAgICAgICAgICAgZXhwYW5kID0gZXhwYW5zaW9uKG11bHQgPSBjKDAuMDEsIDAuMDQpKSkgKw0KICBzY2FsZV95X2NvbnRpbnVvdXMoZXhwYW5kID0gZXhwYW5zaW9uKG11bHQgPSBjKDAsIDAuMTQpKSkgKw0KICBsYWJzKHRpdGxlID0gIkNvbXBhcmVuZG9zIHJlZ2lzdHJhZG9zIHBvciBmZWNoYSIsDQogICAgICAgc3VidGl0bGUgPSAiQ2FudGlkYWQgZGlhcmlhIMK3IGFicmlsIHkgbWF5byBkZSAyMDEwIiwNCiAgICAgICB4ID0gIkZlY2hhIGRlbCBjb21wYXJlbmRvIiwgeSA9ICJDYW50aWRhZCBkZSBjb21wYXJlbmRvcyIpICsNCiAgdGhlbWVfbWluaW1hbChiYXNlX3NpemUgPSAxMikgKw0KICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDQ1LCBoanVzdCA9IDEpLA0KICAgICAgICBwYW5lbC5ncmlkLm1pbm9yID0gZWxlbWVudF9ibGFuaygpKQ0KZ19mZWNoYQ0KbW9zdHJhcl9jb2RpZ28oImV2b2x1Y2lvbi1kaWFyaWEiKQ0KYGBgDQoNCjo6OiBkZXNjcmlwY2lvbi1ncmFmaWNvDQo8c3Ryb25nPsK/Q8OzbW8gZnVuY2lvbmE/PC9zdHJvbmc+IFNlIGFncnVwYW4gbG9zIHJlZ2lzdHJvcyBwb3IgZmVjaGEgeSBzZSBjdWVudGEgY3XDoW50b3MgY29tcGFyZW5kb3MgaHVibyBjYWRhIGTDrWEuIENhZGEgY29sdW1uYSByZXByZXNlbnRhIHVuYSBmZWNoYSB5IGVsIG7Dum1lcm8gc2l0dWFkbyBlbmNpbWEgaW5kaWNhIHN1IGNhbnRpZGFkIGV4YWN0YS4gTGFzIGZlY2hhcyBkZWwgZWplIGhvcml6b250YWwgc2UgbXVlc3RyYW4gZGUgZm9ybWEgZXNwYWNpYWRhIHBhcmEgZmFjaWxpdGFyIGxhIGxlY3R1cmEuIEVzdGUgZ3LDoWZpY28gZXMgZmlqbzogbm8gdGllbmUgYm90b25lcyBwYXJhIGFtcGxpYXIsIHJlZHVjaXIgbmkgZGVzcGxhemFyIGxhIHZpc3RhLg0KOjo6DQoNCjo6OiBpbnRlcnByZXRhY2lvbg0KPHN0cm9uZz5Db21wb3J0YW1pZW50byBwb3IgZmVjaGE6PC9zdHJvbmc+IENhZGEgY29sdW1uYSByZXByZXNlbnRhIHVuYSBmZWNoYSBleGFjdGEgeSBsYSBldGlxdWV0YSBpbmRpY2EgZWwgbsO6bWVybyBkZSBjb21wYXJlbmRvcyByZWdpc3RyYWRvcyBlc2UgZMOtYS4gTGEgdmlzdWFsaXphY2nDs24gcGVybWl0ZSBjb21wYXJhciBmZWNoYXMgZGVudHJvIGRlIGFicmlsIHkgbWF5byBkZSAyMDEwOyBubyBkZWJlIGludGVycHJldGFyc2UgY29tbyB1bmEgdGVuZGVuY2lhIGFudWFsIG5pIGNvbW8gdW5hIGV4cGxpY2FjacOzbiBjYXVzYWwuDQo6OjoNCg0KIyBBbsOhbGlzaXMgcG9yIGfDqW5lcm8gbyB0aXBvIGRlIGVqZWN1dGFkbw0KDQojIyDCv1F1w6kgaGFjZSBlc3RlIGPDs2RpZ28/DQoNCkN1ZW50YSBsb3MgcmVnaXN0cm9zIGRlIGxhIHZhcmlhYmxlIGBHRU5FUk9gLiBFbiBlc3RhIGJhc2UgYXBhcmVjZW4gbGFzIGNhdGVnb3LDrWFzIE1VSkVSLCBIT01CUkUgeSBFTVBSRVNBOyBwb3IgZXNvLCBlbCByZXN1bHRhZG8gZGViZSBpbnRlcnByZXRhcnNlIGNvbW8gdW5hIGNsYXNpZmljYWNpw7NuIGRlIGxhIGJhc2UgeSBubyBjb21vIHVuYSBjb21wYXJhY2nDs24gZXhjbHVzaXZhbWVudGUgZW50cmUgcGVyc29uYXMuDQoNCmBgYHtyIGdlbmVybywgZWNobz1GQUxTRSwgZmlnLndpZHRoPTksIGZpZy5oZWlnaHQ9NX0NCiMgQ3VlbnRhIHJlZ2lzdHJvcyBwb3IgY2F0ZWdvcsOtYSBkZSBnw6luZXJvIG8gdGlwbyBkZSBlamVjdXRhZG8uDQpwb3JfZ2VuZXJvIDwtIGJhc2UgJT4lIGNvdW50KEdFTkVSTywgbmFtZSA9ICJjYW50aWRhZCIsIHNvcnQgPSBUUlVFKQ0Ka25pdHI6OmthYmxlKHBvcl9nZW5lcm8sIGNhcHRpb24gPSAiUmVnaXN0cm9zIHBvciBjYXRlZ29yw61hIGRlIGfDqW5lcm8gbyBlamVjdXRhZG8iKQ0KDQpnX2dlbmVybyA8LSBnZ3Bsb3QocG9yX2dlbmVybywgYWVzKHggPSBHRU5FUk8sIHkgPSBjYW50aWRhZCwNCiAgdGV4dCA9IHBhc3RlMCgiQ2F0ZWdvcsOtYTogIiwgR0VORVJPLCAiPGJyPlJlZ2lzdHJvczogIiwgY2FudGlkYWQpKSkgKw0KICBnZW9tX2NvbChmaWxsID0gIiM2QzVCN0IiLCB3aWR0aCA9IDAuNjUpICsNCiAgZ2VvbV90ZXh0KGFlcyhsYWJlbCA9IGNhbnRpZGFkKSwgdmp1c3QgPSAtMC40LCBzaXplID0gMy41LA0KICAgICAgICAgICAgY29sb3IgPSAiIzI2MzQ0NSIsIGZvbnRmYWNlID0gImJvbGQiKSArDQogIHNjYWxlX3lfY29udGludW91cyhleHBhbmQgPSBleHBhbnNpb24obXVsdCA9IGMoMCwgMC4xMikpKSArDQogIGxhYnModGl0bGUgPSAiUmVnaXN0cm9zIHBvciBjYXRlZ29yw61hIiwgeCA9ICJDYXRlZ29yw61hIiwgeSA9ICJDYW50aWRhZCIpICsNCiAgdGhlbWVfbWluaW1hbChiYXNlX3NpemUgPSAxMikNCmdyYWZpY29fc2luX3pvb20oZ19nZW5lcm8pDQptb3N0cmFyX2NvZGlnbygiZ2VuZXJvIikNCmBgYA0KDQo6OjogZGVzY3JpcGNpb24tZ3JhZmljbw0KPHN0cm9uZz7Cv0PDs21vIGZ1bmNpb25hPzwvc3Ryb25nPiBTZSBjdWVudGEgY3XDoW50b3MgcmVnaXN0cm9zIGhheSBlbiBjYWRhIGNhdGVnb3LDrWEgZGUgbGEgY29sdW1uYSA8Y29kZT5HRU5FUk88L2NvZGU+LiBDb21vIGxhIGJhc2UgaW5jbHV5ZSBsYSBjYXRlZ29yw61hIEVNUFJFU0EsIGVsIGdyw6FmaWNvIHNlIGludGVycHJldGEgY29tbyB1bmEgZGlzdHJpYnVjacOzbiBwb3IgY2F0ZWdvcsOtYSBkZSBlamVjdXRhZG8geSBubyBzb2xvIGNvbW8gY29tcGFyYWNpw7NuIGVudHJlIHBlcnNvbmFzLg0KOjo6DQoNCjo6OiBpbnRlcnByZXRhY2lvbg0KPHN0cm9uZz5EZWZpbmljacOzbiBkZSBsYSBjYXRlZ29yw61hOjwvc3Ryb25nPiBMYSB2YXJpYWJsZSA8Y29kZT5HRU5FUk88L2NvZGU+IGNvbnRpZW5lIGxhcyBjYXRlZ29yw61hcyBNVUpFUiwgSE9NQlJFIHkgRU1QUkVTQS4gRGViaWRvIGEgZXN0YSBjbGFzaWZpY2FjacOzbiwgZWwgcmVzdWx0YWRvIHNlIHByZXNlbnRhIGNvbW8gZGlzdHJpYnVjacOzbiBwb3IgZ8OpbmVybyBvIHRpcG8gZGUgZWplY3V0YWRvIHkgbm8gY29tbyB1bmEgY29tcGFyYWNpw7NuIGV4Y2x1c2l2YSBlbnRyZSBob21icmVzIHkgbXVqZXJlcy4NCjo6Og0KDQojIEFuw6FsaXNpcyBwb3IgdGlwbyBkZSB2ZWjDrWN1bG8NCg0KIyMgwr9RdcOpIGhhY2UgZXN0ZSBjw7NkaWdvPw0KDQpBZ3J1cGEgbG9zIGNvbXBhcmVuZG9zIHBvciB0aXBvIGRlIHZlaMOtY3VsbyB5IGNhbGN1bGEgc3UgZnJlY3VlbmNpYS4gRWwgZ3LDoWZpY28gcGVybWl0ZSBjb21wYXJhciBsb3MgdGlwb3MgcmVnaXN0cmFkb3MgZW4gZWwgYXJjaGl2by4NCg0KYGBge3IgdmVoaWN1bG9zLCBlY2hvPUZBTFNFLCBmaWcud2lkdGg9OSwgZmlnLmhlaWdodD01fQ0KIyBDdWVudGEgbG9zIHJlZ2lzdHJvcyBwYXJhIGNhZGEgdGlwbyBkZSB2ZWjDrWN1bG8uDQpwb3JfdmVoaWN1bG8gPC0gYmFzZSAlPiUgY291bnQoVkVISUNVTE8sIG5hbWUgPSAiY2FudGlkYWQiLCBzb3J0ID0gVFJVRSkNCmtuaXRyOjprYWJsZShwb3JfdmVoaWN1bG8sIGNhcHRpb24gPSAiQ29tcGFyZW5kb3MgcG9yIHRpcG8gZGUgdmVow61jdWxvIikNCg0KZ192ZWhpY3VsbyA8LSBnZ3Bsb3QocG9yX3ZlaGljdWxvLCBhZXMoeCA9IFZFSElDVUxPLCB5ID0gY2FudGlkYWQsDQogIHRleHQgPSBwYXN0ZTAoIlZlaMOtY3VsbzogIiwgVkVISUNVTE8sICI8YnI+Q29tcGFyZW5kb3M6ICIsIGNhbnRpZGFkKSkpICsNCiAgZ2VvbV9jb2woZmlsbCA9ICIjMzQ1OTk1Iiwgd2lkdGggPSAwLjY1KSArDQogIGdlb21fdGV4dChhZXMobGFiZWwgPSBjYW50aWRhZCksIHZqdXN0ID0gLTAuNCwgc2l6ZSA9IDMuNSwNCiAgICAgICAgICAgIGNvbG9yID0gIiMyNjM0NDUiLCBmb250ZmFjZSA9ICJib2xkIikgKw0KICBzY2FsZV95X2NvbnRpbnVvdXMoZXhwYW5kID0gZXhwYW5zaW9uKG11bHQgPSBjKDAsIDAuMTIpKSkgKw0KICBsYWJzKHRpdGxlID0gIkNvbXBhcmVuZG9zIHBvciB0aXBvIGRlIHZlaMOtY3VsbyIsIHggPSAiVGlwbyBkZSB2ZWjDrWN1bG8iLCB5ID0gIkNhbnRpZGFkIikgKw0KICB0aGVtZV9taW5pbWFsKGJhc2Vfc2l6ZSA9IDEyKQ0KZ3JhZmljb19zaW5fem9vbShnX3ZlaGljdWxvKQ0KbW9zdHJhcl9jb2RpZ28oInZlaGljdWxvcyIpDQpgYGANCg0KOjo6IGRlc2NyaXBjaW9uLWdyYWZpY28NCjxzdHJvbmc+wr9Dw7NtbyBmdW5jaW9uYT88L3N0cm9uZz4gU2UgYWdydXBhbiBsb3MgcmVnaXN0cm9zIHNlZ8O6biBlbCB0aXBvIGRlIHZlaMOtY3VsbyB5IHNlIGN1ZW50YSBzdSBmcmVjdWVuY2lhLiBDYWRhIGJhcnJhIHJlcHJlc2VudGEgdW4gdGlwbyBkZSB2ZWjDrWN1bG87IHN1IGFsdHVyYSB5IGxhIGV0aXF1ZXRhIG51bcOpcmljYSBpbmRpY2FuIGVsIG7Dum1lcm8gZGUgY29tcGFyZW5kb3MgYXNvY2lhZG9zLg0KOjo6DQoNCjo6OiBpbnRlcnByZXRhY2lvbg0KPHN0cm9uZz5BbGNhbmNlIGRlbCBhbsOhbGlzaXMgcG9yIHZlaMOtY3Vsbzo8L3N0cm9uZz4gTGFzIGJhcnJhcyBjb21wYXJhbiBsYSBmcmVjdWVuY2lhIGRlIGxvcyB0aXBvcyBkZSB2ZWjDrWN1bG8gcHJlc2VudGVzIGVuIGxvcyByZWdpc3Ryb3MuIEVsIHJlc3VsdGFkbyBkZXNjcmliZSBsYSBjb21wb3NpY2nDs24gZGUgbGEgYmFzZSwgcGVybyBubyBtaWRlIGVsIHJpZXNnbyBkZSBpbmZyYWNjacOzbiBkZSBjYWRhIHRpcG8sIHlhIHF1ZSBubyBzZSBkaXNwb25lIGRlbCB0b3RhbCBkZSB2ZWjDrWN1bG9zIHF1ZSBjaXJjdWxhYmFuLg0KOjo6DQoNCiMgQ29uY2x1c2nDs24gZ2VuZXJhbCBkZWwgYW7DoWxpc2lzIGRlIGNvbXBhcmVuZG9zDQoNCkVsIGFuw6FsaXNpcyBkZSBsYSBiYXNlIGRlIGRhdG9zIHBlcm1pdGnDsyBleGFtaW5hciAyLjEyMCByZWdpc3Ryb3MgZGUgY29tcGFyZW5kb3MgY29ycmVzcG9uZGllbnRlcyBhbCBhw7FvIDIwMTAsIGNvbXByZW5kaWRvcyBlbnRyZSBlbCAxMiBkZSBhYnJpbCB5IGVsIDI3IGRlIG1heW8uIE1lZGlhbnRlIGVsIHByb2Nlc2FtaWVudG8gZGUgZGF0b3MgZW4gUiBzZSBpZGVudGlmaWNhcm9uIHBhdHJvbmVzIHJlbGFjaW9uYWRvcyBjb24gbG9zIHRpcG9zIGRlIGluZnJhY2Npw7NuLCBsYSBkaXN0cmlidWNpw7NuIHRlbXBvcmFsLCBsYXMgY2FyYWN0ZXLDrXN0aWNhcyBkZSBsb3MgZWplY3V0YWRvcyB5IGxhcyBjbGFzZXMgZGUgdmVow61jdWxvcyBpbnZvbHVjcmFkb3MuDQoNCkxvcyBwcmluY2lwYWxlcyByZXN1bHRhZG9zIGZ1ZXJvbiBsb3Mgc2lndWllbnRlczoNCg0KLSBJbmZyYWNjaW9uZXM6IGVsIGPDs2RpZ28gNjQsIGNvcnJlc3BvbmRpZW50ZSBhIGV4Y2VzbyBkZSB2ZWxvY2lkYWQsIHJlZ2lzdHLDsyAxLjYyNiBjYXNvcywgZXF1aXZhbGVudGVzIGFsIDc2LDcwICUgZGVsIHRvdGFsLiBMZSBzaWd1acOzIGVsIGPDs2RpZ28gNzcsIGNvbiAzODUgY2Fzb3MgKDE4LDE2ICUpLg0KDQotIERpc3RyaWJ1Y2nDs24gbWVuc3VhbDogbWF5byBjb25jZW50csOzIDEuNDA4IGNvbXBhcmVuZG9zICg2Niw0MiAlKSwgbWllbnRyYXMgcXVlIGFicmlsIHJlZ2lzdHLDsyA3MTIgKDMzLDU4ICUpLg0KDQotIETDrWFzIGRlIGxhIHNlbWFuYTogZWwgZG9taW5nbyBwcmVzZW50w7MgbGEgbWF5b3IgZnJlY3VlbmNpYSwgY29uIDM5NiByZWdpc3Ryb3MgKDE4LDY4ICUpLCBzZWd1aWRvIGRlbCBzw6FiYWRvLCBjb24gMzcyICgxNyw1NSAlKS4NCg0KLSBDYXRlZ29yw61hIGRlbCBlamVjdXRhZG86IHNlIGlkZW50aWZpY2Fyb24gOTcwIHJlZ2lzdHJvcyBhc29jaWFkb3MgYSBtdWplcmVzICg0NSw3NSAlKSwgNjgzIGEgaG9tYnJlcyAoMzIsMjIgJSkgeSA0NjcgYSBlbXByZXNhcyAoMjIsMDMgJSkuDQoNCi0gVGlwbyBkZSB2ZWjDrWN1bG86IGxvcyBhdXRvbcOzdmlsZXMgcmVwcmVzZW50YXJvbiAxLjkzOCByZWdpc3Ryb3MgKDkxLDQyICUpLCBtaWVudHJhcyBxdWUgbGFzIG1vdG9jaWNsZXRhcyBhbGNhbnphcm9uIDE4MiAoOCw1OCAlKS4NCg0KLSBJbmZvcm1hY2nDs24gZWNvbsOzbWljYTogZWwgdmFsb3IgYWN1bXVsYWRvIHJlZ2lzdHJhZG8gZW4gbGEgY29sdW1uYSBkZSBjb3N0b3MgZnVlIGRlIFwkNjQ2LjA2Ny41MDAsIGNvbiB1biBwcm9tZWRpbyBhcHJveGltYWRvIGRlIFwkMzA0Ljc0OSBwb3IgY29tcGFyZW5kby4NCg0KRGVzZGUgZWwgcHVudG8gZGUgdmlzdGEgdMOpY25pY28sIGVsIHVzbyBkZSBSIHBlcm1pdGnDsyByZWFsaXphciBwcm9jZXNvcyBkZSBpbXBvcnRhY2nDs24sIHRyYW5zZm9ybWFjacOzbiwgYWdydXBhY2nDs24sIGPDoWxjdWxvIGRlIGZyZWN1ZW5jaWFzIHkgdmlzdWFsaXphY2nDs24gbWVkaWFudGUgZ3LDoWZpY29zIGNvbiBldGlxdWV0YXMgZGUgZGF0b3MuIEVzdGFzIGhlcnJhbWllbnRhcyBmYWNpbGl0YXJvbiBsYSBpZGVudGlmaWNhY2nDs24gZGUgdGVuZGVuY2lhcyB5IGxhIGludGVycHJldGFjacOzbiBkZSBsb3MgcmVzdWx0YWRvcy4NCg0KQ29uc2lkZXJhY2nDs24gc29icmUgbGEgY2FsaWRhZCBkZSBsb3MgZGF0b3M6IGF1bnF1ZSBsb3MgMi4xMjAgcmVnaXN0cm9zIG5vIHByZXNlbnRhbiB2YWxvcmVzIHZhY8Otb3MgZW4gbGEgaG9qYSBhbmFsaXphZGEsIHNlIGlkZW50aWZpY2Fyb24gMTggcmVwZXRpY2lvbmVzIGVuIGVsIG7Dum1lcm8gZGUgY29tcGFyZW5kbyB5IHVuIHJlZ2lzdHJvIGNvbXBsZXRhbWVudGUgZHVwbGljYWRvLiBQb3IgdGFudG8sIGVzdG9zIGFzcGVjdG9zIGRlYmVuIHZhbGlkYXJzZSBhbnRlcyBkZSB1dGlsaXphciBsb3MgcmVzdWx0YWRvcyBjb21vIGNpZnJhcyBkZWZpbml0aXZhcy4NCg0KRW4gY29uY2x1c2nDs24sIGVsIGFuw6FsaXNpcyBldmlkZW5jaWEgdW5hIGFsdGEgY29uY2VudHJhY2nDs24gZGUgcmVnaXN0cm9zIGVuIGxhcyBpbmZyYWNjaW9uZXMgcG9yIGV4Y2VzbyBkZSB2ZWxvY2lkYWQgeSBlbiBsb3MgdmVow61jdWxvcyB0aXBvIGF1dG9tw7N2aWwuIExvcyByZXN1bHRhZG9zIG9mcmVjZW4gdW5hIHZpc2nDs24gY3VhbnRpdGF0aXZhIGRlbCBjb21wb3J0YW1pZW50byBkZSBsb3MgY29tcGFyZW5kb3MgZHVyYW50ZSBlbCBwZXJpb2RvIGVzdHVkaWFkbyB5IGRlbXVlc3RyYW4gbGEgdXRpbGlkYWQgZGUgbGFzIGhlcnJhbWllbnRhcyBkZSBhbsOhbGlzaXMgZGUgZGF0b3MgcGFyYSBjb252ZXJ0aXIgcmVnaXN0cm9zIGFkbWluaXN0cmF0aXZvcyBlbiBpbmZvcm1hY2nDs24gb3JnYW5pemFkYSB5IGNvbXByZW5zaWJsZS4NCg0KIyBDb25zaWRlcmFjaW9uZXMgeSBsaW1pdGFjaW9uZXMNCg0KLSBMYSBob2phIHByaW5jaXBhbCBjb250aWVuZSAxNyB2YXJpYWJsZXMgeSAyLjEyMCBmaWxhcyBlbiBlbCBhcmNoaXZvIHJlY2liaWRvLg0KLSBMYXMgZmVjaGFzIG9ic2VydmFkYXMgdmFuIGRlbCAxMiBkZSBhYnJpbCBhbCAyNyBkZSBtYXlvIGRlIDIwMTAuDQotIExhIHZhcmlhYmxlIGBHRU5FUk9gIGluY2x1eWUgbGEgY2F0ZWdvcsOtYSBgRU1QUkVTQWA7IHBvciBlbGxvIHNlIGRlc2NyaWJlIGNvbW8gZ8OpbmVybyBvIHRpcG8gZGUgZWplY3V0YWRvLg0KLSBMYSBob2phIGFuYWxpemFkYSBubyBpbmNsdXllIHVuYSBjb2x1bW5hIGRlIGNvc3RvIGRlbCBjb21wYXJlbmRvLiBFbCBpbmZvcm1lIG5vIGNhbGN1bGEgcmVjYXVkb3MsIG11bHRhcyB0b3RhbGVzIG5pIHByb21lZGlvcyBtb25ldGFyaW9zLg0KLSBMb3MgcmVnaXN0cm9zIHJlcGV0aWRvcyBzZSByZXBvcnRhbiBwYXJhIHJldmlzacOzbjsgbm8gc2UgZWxpbWluYW4gZGUgZm9ybWEgYXV0b23DoXRpY2EgcG9ycXVlIHVuYSByZXBldGljacOzbiBkZSBjb21wYXJlbmRvIG8gbWFuZGFtaWVudG8gZGViZSB2YWxpZGFyc2UgYW50ZXMgZGUgY29uc2lkZXJhcnNlIHVuIGVycm9yLg0KLSBMb3MgcmVzdWx0YWRvcyBkZXBlbmRlbiBkZSBsYSBjYWxpZGFkIHkgZGVsIGNvbnRlbmlkbyBkZWwgYXJjaGl2byBmdWVudGUuDQoNCjo6OiBpbnRlcnByZXRhY2lvbg0KPHN0cm9uZz5MaW1pdGFjaW9uZXMgZGUgbGEgZnVlbnRlOjwvc3Ryb25nPiBFbCBhbsOhbGlzaXMgc2UgcmVzdHJpbmdlIGEgbG9zIHJlZ2lzdHJvcyBjb21wcmVuZGlkb3MgZW50cmUgYWJyaWwgeSBtYXlvIGRlIDIwMTAuIExhIGNhdGVnb3LDrWEgRU1QUkVTQSBmb3JtYSBwYXJ0ZSBkZSBsYSB2YXJpYWJsZSA8Y29kZT5HRU5FUk88L2NvZGU+OyBsb3MgZHVwbGljYWRvcyByZXF1aWVyZW4gdmFsaWRhY2nDs247IHkgbGEgaG9qYSB1dGlsaXphZGEgbm8gY29udGllbmUgdW5hIHZhcmlhYmxlIGRlIGNvc3RvLiBFbiBjb25zZWN1ZW5jaWEsIG5vIHNlIGVzdGltYW4gcmVjYXVkb3MgbmkgdmFsb3JlcyBtb25ldGFyaW9zLg0KOjo6DQoNCi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQ0K