VISUALIZACIÓN DE DATOS

PROYECTO GRUPAL FINAL · PARTE 1
Docente: Carlos Amortegui

Logo de la institución

1. Introducción

El presente informe tiene como propósito realizar una exploración inicial de los datos históricos de ventas de trajes, con el fin de evaluar su estructura, calidad y utilidad para la elaboración del presupuesto de ventas de 2027.

El análisis se enfocará en las cantidades y los valores de venta, así como en su comportamiento por periodo, línea de producto y color.

2. Preparación de los datos

2.1. Instalación de paquetes

Para realizar la exploración de los datos se utilizarán paquetes de R que permiten importar archivos, organizar la información y realizar cálculos estadísticos.

El siguiente código instala los paquetes necesarios para trabajar con archivos Excel y CSV, manipular datos y elaborar gráficos.

install.packages("readxl")     # Lectura de archivos Excel
install.packages("readr")      # Lectura de archivos CSV
install.packages("dplyr")      # Manipulación y transformación de datos
install.packages("tidyr")      # Organización de los datos
install.packages("ggplot2")    # Elaboración de gráficos
install.packages("knitr")      # Presentación de tablas

2.2. Carga de paquetes

Una vez instalados, los paquetes se cargan para poder utilizar sus funciones durante el análisis.

library(readxl)    # Importación de archivos Excel
library(readr)     # Importación de archivos CSV
library(dplyr)     # Manipulación de datos
library(ggplot2)   # Gráficos exploratorios
library(knitr)     # Presentación de tablas

2.3. Importación de las bases de datos

Para realizar la exploración se utilizarán dos fuentes de información. La primera corresponde a los reportes históricos de ventas, almacenados en archivos Excel separados por mes. La segunda corresponde a la base consolidada de artículos, almacenada en formato TXT, que contiene características descriptivas de los productos.

Los reportes mensuales de ventas se integrarán en una sola base de datos para facilitar el análisis del comportamiento histórico. Posteriormente, se revisará la estructura de ambas fuentes antes de realizar su integración y los análisis descriptivos.

2.3.1. Identificación de los archivos de ventas

El siguiente código permite identificar los archivos Excel ubicados en la carpeta que contiene los reportes mensuales.

# Ruta de la carpeta que contiene los reportes mensuales
ruta_ventas <- "C:/Users/jerso/OneDrive/Documentos/Educacion/R Markdown/Proyecto_Visualizacion/_ventasHistoricas"

# Identificar los archivos Excel de la carpeta
archivos_ventas <- list.files(
  path = ruta_ventas,
  pattern = "\\.xlsx$",
  full.names = TRUE,
  ignore.case = TRUE
)

# Consultar la cantidad de archivos encontrados
length(archivos_ventas)
## [1] 2
# Mostrar los nombres de los archivos encontrados
basename(archivos_ventas)
## [1] "201904.xlsx"                        "Reporte de ventas - unificado.xlsx"

2.3.2. Consolidación de los reportes mensuales

Una vez identificados los archivos, podemos leerlos y unirlos verticalmente. Este código supone que los reportes tienen una estructura compatible y que los datos están en la primera hoja de cada archivo.

(Los datos se garantizan desde la descarga que tiene el mismo formato y campos)

# Leer cada archivo Excel desde la hoja "Sheet1"
# y consolidar los registros en una sola base

ventas <- bind_rows(
  lapply(archivos_ventas, function(archivo) {
    read_excel(
      path = archivo,
      sheet = "Sheet1"
    )
  })
)

# Consultar las dimensiones de la base consolidada
dim(ventas)
## [1] 36244    35
# Visualizar los primeros registros
head(ventas)
Bodega Desc. C.O. Desc. bodega Referencia Desc. item Detalle ext. 1 Desc. detalle ext. 1 Detalle ext. 2 U.M. GRUPO SUB GRUPO LINEA SILUETA CATEGORIA PRESUPUESTO MATERIAL DESCRIPCION MATERIAL DISEÑO PRENDA PAIS DE ORIGEN PROVEEDOR Clase docto. Tipo docto. SATELITE Nro documento Desc. lista de precios Desc. causal devol. Cantidad Fecha Valor neto local Valor subtotal local Valor descuentos local Grupo dscto. cliente Obsequio Fecha y hora creación Estado
191 VILLAVICENCIO PV VILLAVICENCIO 67591-1 PANTALON INF AZUL MED CN 027 AZUL MEDI 32 UND 2 - INFORMAL NA 1 - CN 2 - REGULAR 13 - PANTALON 042 - PANTALON INFORMAL NA 01 - UNICOLOR 018 - BOLSILLOS SESGADOS 002 - ESPAÑA 034 - CONFECCIONES NALO SA Boutique FV1 NA FV1-00005121 GENERAL NA 1 2019-06-28 239990 201672 0 NA No 2019-06-28 12:09:13 Aprobada
191 VILLAVICENCIO PV VILLAVICENCIO 67591-1 PANTALON INF AZUL MED CN 027 AZUL MEDI 36 UND 2 - INFORMAL NA 1 - CN 2 - REGULAR 13 - PANTALON 042 - PANTALON INFORMAL NA 01 - UNICOLOR 018 - BOLSILLOS SESGADOS 002 - ESPAÑA 034 - CONFECCIONES NALO SA Boutique FV1 NA FV1-00005120 GENERAL NA 1 2019-06-28 239990 201672 0 NA No 2019-06-28 12:06:40 Aprobada
191 VILLAVICENCIO PV VILLAVICENCIO 67591-1 PANTALON INF AZUL MED CN 027 AZUL MEDI 38 UND 2 - INFORMAL NA 1 - CN 2 - REGULAR 13 - PANTALON 042 - PANTALON INFORMAL NA 01 - UNICOLOR 018 - BOLSILLOS SESGADOS 002 - ESPAÑA 034 - CONFECCIONES NALO SA Boutique FV1 NA FV1-00005119 GENERAL NA 1 2019-06-27 239990 201672 0 NA No 2019-06-27 18:14:31 Aprobada
191 VILLAVICENCIO PV VILLAVICENCIO 6686103 UNDER BOXER CORTO BLANCO ALGODON CN NA NA NA UND 2 - INFORMAL NA 1 - CN 8 - NO APLICA 04 - ROPA INTERIOR 061 - UNDER BOXER CORTO NA NA NA NA 037 - CORPOTEX DE COLOMBIA SAS Boutique FV1 016 - CORPOTEX FV1-00005125 GENERAL NA 1 2019-06-29 45990 38647 0 NA No 2019-06-29 11:41:26 Aprobada
191 VILLAVICENCIO PV VILLAVICENCIO 11048 1901-517 JEAN AZUL MEDIO 027 AZUL MEDI 36 UND 2 - INFORMAL NA 1 - CN 4 - SLIM 13 - PANTALON 027 - JEANS 12 - INDIGO 01 - UNICOLOR 017 - CINCO BOLSILLOS 015 - COLOMBIA 170 - PROJECT DENIM Boutique FV1 009 - PROJECT DENIM FV1-00005041 GENERAL NA 1 2019-06-10 298990 251252 0 NA No 2019-06-10 12:54:04 Aprobada
191 VILLAVICENCIO PV VILLAVICENCIO 11048 1901-517 JEAN AZUL MEDIO 027 AZUL MEDI 38 UND 2 - INFORMAL NA 1 - CN 4 - SLIM 13 - PANTALON 027 - JEANS 12 - INDIGO 01 - UNICOLOR 017 - CINCO BOLSILLOS 015 - COLOMBIA 170 - PROJECT DENIM Boutique FV1 009 - PROJECT DENIM FV1-00005037 GENERAL NA 1 2019-06-09 298990 251252 0 NA No 2019-06-09 14:29:27 Aprobada

2.3.3. Importación y depuración del maestro de artículos

El maestro de artículos se encuentra almacenado en un archivo de texto (TXT) cuyos campos están separados por tabulaciones. Después de su importación, se realizará una revisión de los registros duplicados. Cuando dos o más filas sean completamente idénticas en todas sus columnas, se conservará una sola copia. Este procedimiento permitirá reducir redundancias sin eliminar registros que presenten diferencias en sus atributos.

La base original importada se conservará y la depuración se aplicará sobre una copia de trabajo, garantizando la trazabilidad del procedimiento.

# Definir la ruta del archivo maestro
ruta_articulos <- "C:/Users/jerso/OneDrive/Documentos/Educacion/R Markdown/Proyecto_Visualizacion/_maestroArticulos/Reporte articulos.txt"

# Importar el archivo TXT separado por tabulaciones
articulos <- read_delim(
  file = ruta_articulos,
  delim = "\t",
  locale = locale(encoding = "Windows-1252"),
  trim_ws = TRUE,
  show_col_types = FALSE
)

# Contar las filas completamente duplicadas
duplicados_exactos <- sum(duplicated(articulos))

# Crear una base depurada, conservando una sola copia
# de cada fila completamente idéntica
articulos_limpio <- articulos %>%
  distinct()

# Resumir los resultados
resumen_depuracion <- data.frame(
  Registros_originales = nrow(articulos),
  Duplicados_exactos = duplicados_exactos,
  Registros_despues_depuracion = nrow(articulos_limpio)
)

knitr::kable(
  resumen_depuracion,
  caption = "Resumen de la depuración de duplicados exactos"
)
Resumen de la depuración de duplicados exactos
Registros_originales Duplicados_exactos Registros_despues_depuracion
71684 38249 33435
# Mostrar los primeros registros de la base depurada
head(articulos_limpio)
Referencia Desc. item Ext. 1 detalle Desc. ext. 1 CATEGORIA PRESUPUESTO LINEA SILUETA DISEÑO PRENDA …10 …11 …12 …13 …14 …15 …16 …17 …18 …19 …20 …21 …22 …23 …24 …25 …26 …27 …28 …29 …30 …31
0014633 SUÉTER GRIS OSCURO CERRADO 035 COL PREN 19 - PUNTO 054 - SUETER CERRADO 1 - CN 2 - REGULAR 121 - CUELLO TORTUGA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA
0014634 SUÉTER AZUL OSCURO CERRADO 028 COL PREN 19 - PUNTO 054 - SUETER CERRADO 1 - CN 2 - REGULAR 121 - CUELLO TORTUGA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA
0014635 SUÉTER NEGRO CERRADO 036 COL PREN 19 - PUNTO 054 - SUETER CERRADO 1 - CN 2 - REGULAR 121 - CUELLO TORTUGA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA
240-554 ATLAS MERINOS 100 NA NA NA NA 0 - N/A 8 - NO APLICA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA
16-040 DYSATEX UV NA NA NA NA 0 - N/A 8 - NO APLICA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA
0014650 SERVICIO DE CONFECCION BOLSAS ZAPATOS NA NA 15 - NO VENTA 125 - NO VENTA 0 - N/A 8 - NO APLICA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA

2.4. Revisión inicial de la estructura de los datos

Una vez importadas las fuentes de información, se realizará una revisión inicial de su estructura para identificar la cantidad de registros, las variables disponibles y los tipos de datos de cada base. Esta revisión permitirá reconocer las características generales de la información y detectar posibles ajustes necesarios antes de realizar el análisis exploratorio.

2.4.1. Dimensiones de las bases

Las dimensiones permiten conocer el número de registros y variables disponibles en cada fuente de información.

# Cantidad de filas y columnas de la base de ventas
dim(ventas)
## [1] 36244    35
# Cantidad de filas y columnas del maestro de artículos
dim(articulos_limpio)
## [1] 33435    31

2.4.2. Nombres de las variables

# Variables disponibles en la base de ventas
names(ventas)
##  [1] "Bodega"                 "Desc. C.O."             "Desc. bodega"          
##  [4] "Referencia"             "Desc. item"             "Detalle ext. 1"        
##  [7] "Desc. detalle ext. 1"   "Detalle ext. 2"         "U.M."                  
## [10] "GRUPO"                  "SUB GRUPO"              "LINEA"                 
## [13] "SILUETA"                "CATEGORIA"              "PRESUPUESTO"           
## [16] "MATERIAL"               "DESCRIPCION MATERIAL"   "DISEÑO PRENDA"         
## [19] "PAIS DE ORIGEN"         "PROVEEDOR"              "Clase docto."          
## [22] "Tipo docto."            "SATELITE"               "Nro documento"         
## [25] "Desc. lista de precios" "Desc. causal devol."    "Cantidad"              
## [28] "Fecha"                  "Valor neto local"       "Valor subtotal local"  
## [31] "Valor descuentos local" "Grupo dscto. cliente"   "Obsequio"              
## [34] "Fecha y hora creación"  "Estado"
# Variables disponibles en el maestro de artículos
names(articulos_limpio)
##  [1] "Referencia"     "Desc. item"     "Ext. 1 detalle" "Desc. ext. 1"  
##  [5] "CATEGORIA"      "PRESUPUESTO"    "LINEA"          "SILUETA"       
##  [9] "DISEÑO PRENDA"  "...10"          "...11"          "...12"         
## [13] "...13"          "...14"          "...15"          "...16"         
## [17] "...17"          "...18"          "...19"          "...20"         
## [21] "...21"          "...22"          "...23"          "...24"         
## [25] "...25"          "...26"          "...27"          "...28"         
## [29] "...29"          "...30"          "...31"

2.4.3. Tipos de datos y primeros registros

# Estructura de la base de ventas
glimpse(ventas)
## Rows: 36,244
## Columns: 35
## $ Bodega                   <chr> "191", "191", "191", "191", "191", "191", "19…
## $ `Desc. C.O.`             <chr> "VILLAVICENCIO", "VILLAVICENCIO", "VILLAVICEN…
## $ `Desc. bodega`           <chr> "PV VILLAVICENCIO", "PV VILLAVICENCIO", "PV V…
## $ Referencia               <chr> "67591-1", "67591-1", "67591-1", "6686103", "…
## $ `Desc. item`             <chr> "PANTALON INF AZUL MED CN", "PANTALON INF AZU…
## $ `Detalle ext. 1`         <chr> "027", "027", "027", NA, "027", "027", NA, NA…
## $ `Desc. detalle ext. 1`   <chr> "AZUL MEDI", "AZUL MEDI", "AZUL MEDI", NA, "A…
## $ `Detalle ext. 2`         <chr> "32", "36", "38", NA, "36", "38", NA, NA, NA,…
## $ U.M.                     <chr> "UND", "UND", "UND", "UND", "UND", "UND", "UN…
## $ GRUPO                    <chr> "2 - INFORMAL", "2 - INFORMAL", "2 - INFORMAL…
## $ `SUB GRUPO`              <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
## $ LINEA                    <chr> "1 - CN", "1 - CN", "1 - CN", "1 - CN", "1 - …
## $ SILUETA                  <chr> "2 - REGULAR", "2 - REGULAR", "2 - REGULAR", …
## $ CATEGORIA                <chr> "13 - PANTALON", "13 - PANTALON", "13 - PANTA…
## $ PRESUPUESTO              <chr> "042 - PANTALON INFORMAL", "042 - PANTALON IN…
## $ MATERIAL                 <chr> NA, NA, NA, NA, "12 - INDIGO", "12 - INDIGO",…
## $ `DESCRIPCION MATERIAL`   <chr> "01 - UNICOLOR", "01 - UNICOLOR", "01 - UNICO…
## $ `DISEÑO PRENDA`          <chr> "018 - BOLSILLOS SESGADOS", "018 - BOLSILLOS …
## $ `PAIS DE ORIGEN`         <chr> "002 - ESPAÑA", "002 - ESPAÑA", "002 - ESPAÑA…
## $ PROVEEDOR                <chr> "034 - CONFECCIONES NALO SA", "034 - CONFECCI…
## $ `Clase docto.`           <chr> "Boutique", "Boutique", "Boutique", "Boutique…
## $ `Tipo docto.`            <chr> "FV1", "FV1", "FV1", "FV1", "FV1", "FV1", "FV…
## $ SATELITE                 <chr> NA, NA, NA, "016 - CORPOTEX", "009 - PROJECT …
## $ `Nro documento`          <chr> "FV1-00005121", "FV1-00005120", "FV1-00005119…
## $ `Desc. lista de precios` <chr> "GENERAL", "GENERAL", "GENERAL", "GENERAL", "…
## $ `Desc. causal devol.`    <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
## $ Cantidad                 <dbl> 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, …
## $ Fecha                    <dttm> 2019-06-28, 2019-06-28, 2019-06-27, 2019-06-…
## $ `Valor neto local`       <dbl> 239990, 239990, 239990, 45990, 298990, 298990…
## $ `Valor subtotal local`   <dbl> 201672, 201672, 201672, 38647, 251252, 251252…
## $ `Valor descuentos local` <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, …
## $ `Grupo dscto. cliente`   <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
## $ Obsequio                 <chr> "No", "No", "No", "No", "No", "No", "No", "No…
## $ `Fecha y hora creación`  <dttm> 2019-06-28 12:09:13, 2019-06-28 12:06:40, 20…
## $ Estado                   <chr> "Aprobada", "Aprobada", "Aprobada", "Aprobada…
# Estructura del maestro de artículos
glimpse(articulos_limpio)
## Rows: 33,435
## Columns: 31
## $ Referencia       <chr> "0014633", "0014634", "0014635", "240-554", "16-040",…
## $ `Desc. item`     <chr> "SUÉTER GRIS OSCURO CERRADO", "SUÉTER AZUL OSCURO CER…
## $ `Ext. 1 detalle` <chr> "035", "028", "036", NA, NA, NA, "027", "028", "026",…
## $ `Desc. ext. 1`   <chr> "COL PREN", "COL PREN", "COL PREN", NA, NA, NA, "COL …
## $ CATEGORIA        <chr> "19 - PUNTO", "19 - PUNTO", "19 - PUNTO", NA, NA, "15…
## $ PRESUPUESTO      <chr> "054 - SUETER CERRADO", "054 - SUETER CERRADO", "054 …
## $ LINEA            <chr> "1 - CN", "1 - CN", "1 - CN", "0 - N/A", "0 - N/A", "…
## $ SILUETA          <chr> "2 - REGULAR", "2 - REGULAR", "2 - REGULAR", "8 - NO …
## $ `DISEÑO PRENDA`  <chr> "121 - CUELLO TORTUGA", "121 - CUELLO TORTUGA", "121 …
## $ ...10            <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
## $ ...11            <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
## $ ...12            <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
## $ ...13            <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
## $ ...14            <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
## $ ...15            <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
## $ ...16            <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
## $ ...17            <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
## $ ...18            <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
## $ ...19            <lgl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
## $ ...20            <lgl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
## $ ...21            <lgl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
## $ ...22            <lgl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
## $ ...23            <lgl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
## $ ...24            <lgl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
## $ ...25            <lgl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
## $ ...26            <lgl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
## $ ...27            <lgl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
## $ ...28            <lgl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
## $ ...29            <lgl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
## $ ...30            <lgl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
## $ ...31            <lgl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
# Primeros registros de ventas
head(ventas)
Bodega Desc. C.O. Desc. bodega Referencia Desc. item Detalle ext. 1 Desc. detalle ext. 1 Detalle ext. 2 U.M. GRUPO SUB GRUPO LINEA SILUETA CATEGORIA PRESUPUESTO MATERIAL DESCRIPCION MATERIAL DISEÑO PRENDA PAIS DE ORIGEN PROVEEDOR Clase docto. Tipo docto. SATELITE Nro documento Desc. lista de precios Desc. causal devol. Cantidad Fecha Valor neto local Valor subtotal local Valor descuentos local Grupo dscto. cliente Obsequio Fecha y hora creación Estado
191 VILLAVICENCIO PV VILLAVICENCIO 67591-1 PANTALON INF AZUL MED CN 027 AZUL MEDI 32 UND 2 - INFORMAL NA 1 - CN 2 - REGULAR 13 - PANTALON 042 - PANTALON INFORMAL NA 01 - UNICOLOR 018 - BOLSILLOS SESGADOS 002 - ESPAÑA 034 - CONFECCIONES NALO SA Boutique FV1 NA FV1-00005121 GENERAL NA 1 2019-06-28 239990 201672 0 NA No 2019-06-28 12:09:13 Aprobada
191 VILLAVICENCIO PV VILLAVICENCIO 67591-1 PANTALON INF AZUL MED CN 027 AZUL MEDI 36 UND 2 - INFORMAL NA 1 - CN 2 - REGULAR 13 - PANTALON 042 - PANTALON INFORMAL NA 01 - UNICOLOR 018 - BOLSILLOS SESGADOS 002 - ESPAÑA 034 - CONFECCIONES NALO SA Boutique FV1 NA FV1-00005120 GENERAL NA 1 2019-06-28 239990 201672 0 NA No 2019-06-28 12:06:40 Aprobada
191 VILLAVICENCIO PV VILLAVICENCIO 67591-1 PANTALON INF AZUL MED CN 027 AZUL MEDI 38 UND 2 - INFORMAL NA 1 - CN 2 - REGULAR 13 - PANTALON 042 - PANTALON INFORMAL NA 01 - UNICOLOR 018 - BOLSILLOS SESGADOS 002 - ESPAÑA 034 - CONFECCIONES NALO SA Boutique FV1 NA FV1-00005119 GENERAL NA 1 2019-06-27 239990 201672 0 NA No 2019-06-27 18:14:31 Aprobada
191 VILLAVICENCIO PV VILLAVICENCIO 6686103 UNDER BOXER CORTO BLANCO ALGODON CN NA NA NA UND 2 - INFORMAL NA 1 - CN 8 - NO APLICA 04 - ROPA INTERIOR 061 - UNDER BOXER CORTO NA NA NA NA 037 - CORPOTEX DE COLOMBIA SAS Boutique FV1 016 - CORPOTEX FV1-00005125 GENERAL NA 1 2019-06-29 45990 38647 0 NA No 2019-06-29 11:41:26 Aprobada
191 VILLAVICENCIO PV VILLAVICENCIO 11048 1901-517 JEAN AZUL MEDIO 027 AZUL MEDI 36 UND 2 - INFORMAL NA 1 - CN 4 - SLIM 13 - PANTALON 027 - JEANS 12 - INDIGO 01 - UNICOLOR 017 - CINCO BOLSILLOS 015 - COLOMBIA 170 - PROJECT DENIM Boutique FV1 009 - PROJECT DENIM FV1-00005041 GENERAL NA 1 2019-06-10 298990 251252 0 NA No 2019-06-10 12:54:04 Aprobada
191 VILLAVICENCIO PV VILLAVICENCIO 11048 1901-517 JEAN AZUL MEDIO 027 AZUL MEDI 38 UND 2 - INFORMAL NA 1 - CN 4 - SLIM 13 - PANTALON 027 - JEANS 12 - INDIGO 01 - UNICOLOR 017 - CINCO BOLSILLOS 015 - COLOMBIA 170 - PROJECT DENIM Boutique FV1 009 - PROJECT DENIM FV1-00005037 GENERAL NA 1 2019-06-09 298990 251252 0 NA No 2019-06-09 14:29:27 Aprobada
# Primeros registros del maestro de artículos
head(articulos_limpio)
Referencia Desc. item Ext. 1 detalle Desc. ext. 1 CATEGORIA PRESUPUESTO LINEA SILUETA DISEÑO PRENDA …10 …11 …12 …13 …14 …15 …16 …17 …18 …19 …20 …21 …22 …23 …24 …25 …26 …27 …28 …29 …30 …31
0014633 SUÉTER GRIS OSCURO CERRADO 035 COL PREN 19 - PUNTO 054 - SUETER CERRADO 1 - CN 2 - REGULAR 121 - CUELLO TORTUGA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA
0014634 SUÉTER AZUL OSCURO CERRADO 028 COL PREN 19 - PUNTO 054 - SUETER CERRADO 1 - CN 2 - REGULAR 121 - CUELLO TORTUGA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA
0014635 SUÉTER NEGRO CERRADO 036 COL PREN 19 - PUNTO 054 - SUETER CERRADO 1 - CN 2 - REGULAR 121 - CUELLO TORTUGA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA
240-554 ATLAS MERINOS 100 NA NA NA NA 0 - N/A 8 - NO APLICA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA
16-040 DYSATEX UV NA NA NA NA 0 - N/A 8 - NO APLICA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA
0014650 SERVICIO DE CONFECCION BOLSAS ZAPATOS NA NA 15 - NO VENTA 125 - NO VENTA 0 - N/A 8 - NO APLICA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA

2.5. Filtrado de artículos y ventas de trajes

Con el propósito de delimitar la información relevante para el proyecto, se identificarán los artículos clasificados en la categoría 16 - TRAJE.

Posteriormente, se revisarán sus subdivisiones presupuestales para distinguir las líneas 058 - TRAJE y 060 - TRAJE LINO, de acuerdo con la clasificación registrada en el maestro de artículos.

2.5.1. Identificación de artículos de la categoría traje

# Filtrar los trajes desde el maestro ya depurado
articulos_trajes <- articulos_limpio %>%
  filter(CATEGORIA == "16 - TRAJE")

# Consultar las dimensiones de la base filtrada
dim(articulos_trajes)
## [1] 3216   31
# Mostrar los primeros registros
head(articulos_trajes)
Referencia Desc. item Ext. 1 detalle Desc. ext. 1 CATEGORIA PRESUPUESTO LINEA SILUETA DISEÑO PRENDA …10 …11 …12 …13 …14 …15 …16 …17 …18 …19 …20 …21 …22 …23 …24 …25 …26 …27 …28 …29 …30 …31
6692539 TRAJE AZUL O 2 BOT LAB CUADROS NA NA 16 - TRAJE 058 - TRAJE 1 - CN 4 - SLIM NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA
6704146 TRAJE GRIS MEDIO 2 BOT PLATINO NA NA 16 - TRAJE 058 - TRAJE 3 - PLATINO 2 - REGULAR NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA
6704546 TRAJE GRIS OSCURO 2 BOT PLATINO NA NA 16 - TRAJE 058 - TRAJE 3 - PLATINO 2 - REGULAR NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA
33208 TRAJE 2 BT AZUL OSC CUADROS LONG 028 COL PREN 16 - TRAJE 058 - TRAJE 1 - CN 5 - REGULAR LONG 011 - DOS BOTONES NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA
33210 TRAJE 2 BT GRIS OSC CUADROS LONG 035 COL PREN 16 - TRAJE 058 - TRAJE 1 - CN 5 - REGULAR LONG 011 - DOS BOTONES NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA
33212 TRAJE 2 BT GRIS OSC JASPE LONG 035 COL PREN 16 - TRAJE 058 - TRAJE 1 - CN 5 - REGULAR LONG 011 - DOS BOTONES NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA

2.5.2. Filtrado de las ventas correspondientes a trajes

# Filtrar las ventas de las referencias identificadas como trajes
ventas_trajes <- ventas %>%
  filter(Referencia %in% articulos_trajes$Referencia)

# Consultar las dimensiones de la base filtrada
dim(ventas_trajes)
## [1] 3304   35
# Revisar los primeros registros
head(ventas_trajes)
Bodega Desc. C.O. Desc. bodega Referencia Desc. item Detalle ext. 1 Desc. detalle ext. 1 Detalle ext. 2 U.M. GRUPO SUB GRUPO LINEA SILUETA CATEGORIA PRESUPUESTO MATERIAL DESCRIPCION MATERIAL DISEÑO PRENDA PAIS DE ORIGEN PROVEEDOR Clase docto. Tipo docto. SATELITE Nro documento Desc. lista de precios Desc. causal devol. Cantidad Fecha Valor neto local Valor subtotal local Valor descuentos local Grupo dscto. cliente Obsequio Fecha y hora creación Estado
191 VILLAVICENCIO PV VILLAVICENCIO 6681838 TRAJE AZUL MEDIO 2 BOT LAB NA NA NA UND 1 - FORMAL NA 1 - CN 4 - SLIM 16 - TRAJE 058 - TRAJE NA NA NA NA 173 - CAPELHI D UOMO Boutique FV1 017 - CAPHELI FV1-00004935 GENERAL NA 1 2019-05-03 759990 638647 0 NA No 2019-05-03 20:19:11 Aprobada
191 VILLAVICENCIO PV VILLAVICENCIO 6681742 TRAJE NEGRO 2 BOT LAB NA NA NA UND 1 - FORMAL NA 1 - CN 4 - SLIM 16 - TRAJE 058 - TRAJE NA NA NA NA 173 - CAPELHI D UOMO Boutique FV1 017 - CAPHELI FV1-00004875 GENERAL NA 1 2019-04-13 759990 638647 0 NA No 2019-04-13 19:34:42 Aprobada
191 VILLAVICENCIO PV VILLAVICENCIO 6681940 TRAJE GRIS MEDIO 2 BOT LAB NA NA NA UND 1 - FORMAL NA 1 - CN 4 - SLIM 16 - TRAJE 058 - TRAJE NA NA NA NA 173 - CAPELHI D UOMO Boutique FV1 017 - CAPHELI FV1-00004868 GENERAL NA 1 2019-04-10 759990 638647 0 NA No 2019-04-10 20:25:48 Aprobada
191 VILLAVICENCIO PV VILLAVICENCIO 6468140 TRAJE LINO MARFIL 2 BOT CN REGULAR FIT NA NA NA UND 2 - INFORMAL NA 1 - CN 2 - REGULAR 16 - TRAJE 060 - TRAJE LINO NA NA NA NA 035 - CONFECCOES LANCA Boutique FV1 003 - CONFECCOES LANCA FV1-00004939 GENERAL NA 1 2019-05-04 1298990 1091588 0 NA No 2019-05-04 16:10:10 Aprobada
191 VILLAVICENCIO PV VILLAVICENCIO 33209 TRAJE 2BOT CN GRIS OSC CUADROS 035 GRIS OSCU 43 UND 1 - FORMAL NA 1 - CN 2 - REGULAR 16 - TRAJE 058 - TRAJE 06 - LANA 03 - CUADROS 011 - DOS BOTONES 004 - CHINA 132 - RSK TRADING CO LTD Boutique FV1 022 - CONFECCIONES ROSDI FV1-00005020 GENERAL NA 1 2019-06-01 959990 806714 0 NA No 2019-06-01 14:45:25 Aprobada
091 GRAN ESTACION PV GRAN ESTACION 6744740 TRAJE NEGRO 2 BOT CN NA NA NA UND 1 - FORMAL NA 1 - CN 2 - REGULAR 16 - TRAJE 058 - TRAJE NA NA NA NA 035 - CONFECCOES LANCA Boutique FV1 003 - CONFECCOES LANCA FV1-00077307 GENERAL NA 1 2019-06-15 1389990 1168059 0 NA No 2019-06-15 12:23:27 Aprobada

2.6. Revisión de la calidad de los datos

La revisión de la calidad de los datos permite identificar posibles problemas en la información antes de realizar los análisis exploratorios. En esta etapa se evaluará la presencia de valores faltantes y registros duplicados en la base de ventas de trajes. Estos procedimientos permitirán conocer el estado general de los datos y determinar si es necesario realizar ajustes antes de continuar con el análisis. No se eliminarán registros automáticamente, ya que primero se debe evaluar su naturaleza y relevancia.

2.6.1. Identificación de valores faltantes

Los valores faltantes corresponden a registros en los que una o varias variables no contienen información. Su identificación permite reconocer posibles limitaciones en la integridad de los datos y determinar si las variables disponibles son adecuadas para los análisis posteriores.

# Contar los valores faltantes por variable
faltantes_ventas <- data.frame(
  Variable = names(ventas_trajes),
  Cantidad_faltante = sapply(
    ventas_trajes,
    function(x) sum(is.na(x))
  )
)

# Calcular el porcentaje de valores faltantes por variable
faltantes_ventas$Porcentaje_faltante <- round(
  faltantes_ventas$Cantidad_faltante /
    nrow(ventas_trajes) * 100,
  2
)

# Presentar las variables con valores faltantes
faltantes_ventas %>%
  filter(Cantidad_faltante > 0) %>%
  arrange(desc(Cantidad_faltante)) %>%
  knitr::kable(
    caption = "Valores faltantes en la base de ventas de trajes"
  )
Valores faltantes en la base de ventas de trajes
Variable Cantidad_faltante Porcentaje_faltante
SUB GRUPO SUB GRUPO 3301 99.91
Grupo dscto. cliente Grupo dscto. cliente 3289 99.55
Desc. causal devol. Desc. causal devol. 3156 95.52
Detalle ext. 1 Detalle ext. 1 1853 56.08
Desc. detalle ext. 1 Desc. detalle ext. 1 1853 56.08
Detalle ext. 2 Detalle ext. 2 1853 56.08
PAIS DE ORIGEN PAIS DE ORIGEN 1813 54.87
MATERIAL MATERIAL 1810 54.78
DESCRIPCION MATERIAL DESCRIPCION MATERIAL 1809 54.75
DISEÑO PRENDA DISEÑO PRENDA 1808 54.72
PROVEEDOR PROVEEDOR 621 18.80
SATELITE SATELITE 125 3.78
GRUPO GRUPO 89 2.69

2.6.2. Identificación de registros duplicados

La identificación de registros duplicados permite detectar filas que presentan exactamente los mismos valores en todas sus variables. Su revisión contribuye a prevenir posibles distorsiones en los resultados; sin embargo, la existencia de filas idénticas no implica necesariamente que correspondan a errores. Por esta razón, en esta etapa únicamente se identificarán los posibles duplicados, sin eliminarlos de la base.

# Contar las filas completamente duplicadas
duplicados_ventas <- sum(duplicated(ventas_trajes))

# Resumir los resultados de la revisión
resumen_duplicados <- data.frame(
  Total_registros = nrow(ventas_trajes),
  Registros_duplicados = duplicados_ventas,
  Porcentaje_duplicados = round(
    duplicados_ventas / nrow(ventas_trajes) * 100,
    2
  )
)

# Presentar la tabla de resultados
knitr::kable(
  resumen_duplicados,
  caption = "Revisión de registros duplicados en las ventas de trajes"
)
Revisión de registros duplicados en las ventas de trajes
Total_registros Registros_duplicados Porcentaje_duplicados
3304 0 0

2.7. Revisión de las variables principales de ventas

Para preparar la información destinada al análisis histórico y a la elaboración del presupuesto de ventas de 2027, se revisarán las variables disponibles en la base de ventas de trajes. Esta revisión permitirá identificar los campos relacionados con la fecha de la operación, las cantidades vendidas, los valores de venta y los atributos de los productos, como el color.

2.7.1. Identificación de las variables disponibles

Se consultarán los nombres de las variables de la base de ventas de trajes y del maestro de artículos para identificar los campos que se utilizarán en las siguientes etapas del análisis.

# Variables de la base de ventas de trajes
names(ventas_trajes)
##  [1] "Bodega"                 "Desc. C.O."             "Desc. bodega"          
##  [4] "Referencia"             "Desc. item"             "Detalle ext. 1"        
##  [7] "Desc. detalle ext. 1"   "Detalle ext. 2"         "U.M."                  
## [10] "GRUPO"                  "SUB GRUPO"              "LINEA"                 
## [13] "SILUETA"                "CATEGORIA"              "PRESUPUESTO"           
## [16] "MATERIAL"               "DESCRIPCION MATERIAL"   "DISEÑO PRENDA"         
## [19] "PAIS DE ORIGEN"         "PROVEEDOR"              "Clase docto."          
## [22] "Tipo docto."            "SATELITE"               "Nro documento"         
## [25] "Desc. lista de precios" "Desc. causal devol."    "Cantidad"              
## [28] "Fecha"                  "Valor neto local"       "Valor subtotal local"  
## [31] "Valor descuentos local" "Grupo dscto. cliente"   "Obsequio"              
## [34] "Fecha y hora creación"  "Estado"
# Variables del maestro de artículos
names(articulos_trajes)
##  [1] "Referencia"     "Desc. item"     "Ext. 1 detalle" "Desc. ext. 1"  
##  [5] "CATEGORIA"      "PRESUPUESTO"    "LINEA"          "SILUETA"       
##  [9] "DISEÑO PRENDA"  "...10"          "...11"          "...12"         
## [13] "...13"          "...14"          "...15"          "...16"         
## [17] "...17"          "...18"          "...19"          "...20"         
## [21] "...21"          "...22"          "...23"          "...24"         
## [25] "...25"          "...26"          "...27"          "...28"         
## [29] "...29"          "...30"          "...31"

2.7.2. Selección de variables para el análisis

La selección de variables se realizó de acuerdo con los objetivos del proyecto y la utilidad de cada campo para la elaboración del presupuesto de ventas de 2027. Se priorizarán la fecha de la operación, la referencia del artículo, la talla y la cantidad vendida. A partir del maestro de artículos se incorporarán los atributos descriptivos actuales del producto, incluyendo la línea, el color, la categoría, el presupuesto, la silueta y el diseño de la prenda.

Se conservará la referencia como campo de relación entre las fuentes de información. La talla se mantendrá desde los registros históricos de ventas, debido a que permite distinguir las unidades vendidas por talla, mientras que el maestro aporta la clasificación general y actualizada del artículo.

Los valores monetarios y otros campos que no forman parte del alcance principal se excluirán de la base de análisis. Asimismo, se revisará el estado de los registros para excluir las operaciones canceladas, una vez identificada su denominación exacta en los datos de origen.

# 1. Seleccionar las variables necesarias de las ventas de trajes
ventas_seleccion <- ventas_trajes %>%
  select(
    Referencia,
    `Detalle ext. 2`,
    Fecha,
    Cantidad,
    Estado
  )

# 2. Seleccionar los atributos actuales del maestro de trajes
articulos_seleccion <- articulos_trajes %>%
  select(
    Referencia,
    `Desc. item`,
    `Ext. 1 detalle`,
    `Desc. ext. 1`,
    CATEGORIA,
    PRESUPUESTO,
    LINEA,
    SILUETA,
    `DISEÑO PRENDA`
  )

# 3. Revisar los estados de los registros de ventas
ventas_seleccion %>%
  count(Estado, sort = TRUE) %>%
  knitr::kable(
    caption = "Distribución de registros por estado"
  )
Distribución de registros por estado
Estado n
Aprobada 3304
# 4. Identificar referencias que aparecen varias veces
referencias_repetidas <- articulos_seleccion %>%
  count(Referencia, name = "Numero_registros") %>%
  filter(Numero_registros > 1) %>%
  arrange(desc(Numero_registros))

# Mostrar las primeras 20 referencias repetidas
head(referencias_repetidas, 20) %>%
  knitr::kable(
    caption = "Referencias repetidas en el maestro de trajes"
  )
Referencias repetidas en el maestro de trajes
Referencia Numero_registros
0015939 4
0015935 3
0015936 3
0015937 3
0014287 2
0015536 2
0015615 2
0015932 2
0015938 2
0017007 2
0017008 2
0019538 2
0020256 2
0020258 2
0020261 2
0020813 2
0021315 2
0023047 2
0023048 2
0023607 2
# 5. Resumir la revisión de referencias
data.frame(
  Referencias_unicas = n_distinct(articulos_seleccion$Referencia),
  Referencias_repetidas = nrow(referencias_repetidas)
) %>%
  knitr::kable(
    caption = "Resumen de la revisión de referencias"
  )
Resumen de la revisión de referencias
Referencias_unicas Referencias_repetidas
3164 47
LS0tDQp0aXRsZTogIlByb3llY3RvIFByZXN1cHVlc3RvIDIwMjciDQphdXRob3I6ICJKZXJzb24gRGF2aWQgQ3VlbGxhciBWYW5lZ2FzLCBKb3NlIEVmcmFpbiBDYXN0aWxsbyB5IERhbmllbCINCmRhdGU6ICJgciBmb3JtYXQoU3lzLkRhdGUoKSwgJyVkIGRlICVCIGRlICVZJylgIg0Kb3V0cHV0Og0KICBodG1sX2RvY3VtZW50Og0KICAgIHRvYzogdHJ1ZQ0KICAgIHRvY19mbG9hdDogdHJ1ZQ0KICAgIHRoZW1lOiBmbGF0bHkNCiAgICBkZl9wcmludDoga2FibGUNCiAgICBjb2RlX2ZvbGRpbmc6IGhpZGUNCiAgICBjb2RlX2Rvd25sb2FkOiB0cnVlICAgIyBhZ3JlZ2EgdW4gYm90w7NuIHBhcmEgZGVzY2FyZ2FyIGVsIC5SbWQgb3JpZ2luYWwgLS0gcmVmdWVyemEgbGEgcmVwcm9kdWNpYmlsaWRhZA0KLS0tDQoNCg0KYGBgez1odG1sfQ0KPHN0eWxlPg0KLyogVGlwb2dyYWbDrWEgZWRpdG9yaWFsIGRlbCBjdXJzbyAobWlzbWEgcXVlIGxsZXZhbiBsb3MgZ3LDoWZpY29zIHbDrWENCiAgIHNob3d0ZXh0KSB0YW1iacOpbiBwYXJhIGVsIHRleHRvIGRlbCBkb2N1bWVudG8gLS0gcXVlIHRvZG8gZWwgaW5mb3JtZQ0KICAgc2Ugc2llbnRhIGNvbW8gdW5hIHNvbGEgcGllemEsIG5vIHVuIEhUTUwgZ2Vuw6lyaWNvIGNvbiBncsOhZmljb3MgcGVnYWRvcy4gKi8NCkBpbXBvcnQgdXJsKCdodHRwczovL2ZvbnRzLmdvb2dsZWFwaXMuY29tL2NzczI/ZmFtaWx5PUZpcmErU2Fuczp3Z2h0QDQwMDs2MDA7NzAwJmRpc3BsYXk9c3dhcCcpOw0KDQpib2R5IHsgZm9udC1mYW1pbHk6ICdGaXJhIFNhbnMnLCAtYXBwbGUtc3lzdGVtLCBCbGlua01hY1N5c3RlbUZvbnQsIHNhbnMtc2VyaWY7IGNvbG9yOiAjMkIyNTMwOyB9DQpoMSwgaDIsIGgzIHsgZm9udC1mYW1pbHk6ICdGaXJhIFNhbnMnLCBzYW5zLXNlcmlmOyBjb2xvcjogIzM1MUE0RjsgfQ0KaDEgeyBib3JkZXItYm90dG9tOiAzcHggc29saWQgI0Q5MDA2QzsgcGFkZGluZy1ib3R0b206IDhweDsgbWFyZ2luLXRvcDogNDhweDsgfQ0KaDIgeyBtYXJnaW4tdG9wOiAzNnB4OyB9DQphIHsgY29sb3I6ICNEOTAwNkM7IH0NCmE6aG92ZXIgeyBjb2xvcjogIzE2OEM4NjsgfQ0KI1RPQyB7IGJvcmRlci1yYWRpdXM6IDEwcHg7IH0NCi5uYXYtcGlsbHMgPiBsaS5hY3RpdmUgPiBhLCAubmF2LXBpbGxzID4gbGkuYWN0aXZlID4gYTpob3ZlciB7IGJhY2tncm91bmQtY29sb3I6ICMzNTFBNEYgIWltcG9ydGFudDsgfQ0KY2FwdGlvbiB7IGNvbG9yOiAjNUE1NTYwOyBmb250LXN0eWxlOiBpdGFsaWM7IGNhcHRpb24tc2lkZTogdG9wOyB9DQpjb2RlIHsgY29sb3I6ICM4QTFBNUM7IGJhY2tncm91bmQ6ICNGNkVFRjI7IHBhZGRpbmc6IDFweCA1cHg7IGJvcmRlci1yYWRpdXM6IDRweDsgfQ0KdGFibGUuZGF0YVRhYmxlIHsgZm9udC1zaXplOiAwLjkycmVtOyB9DQoubGVhZmxldC1jb250YWluZXIgeyBib3JkZXItcmFkaXVzOiAxMHB4OyBiYWNrZ3JvdW5kOiAjRUFGMEY0ICFpbXBvcnRhbnQ7IH0NCjwvc3R5bGU+DQpgYGANCg0KDQo6Ojo6Ojo6IHtzdHlsZT0iYmFja2dyb3VuZDogbGluZWFyLWdyYWRpZW50KDEzNWRlZywgIzM1MUE0RiAwJSwgI0Q5MDA2QyAxMDAlKTsgcGFkZGluZzogMjZweCAzMHB4OyBib3JkZXItcmFkaXVzOiAxNHB4OyBtYXJnaW4tYm90dG9tOiAzMHB4OyBkaXNwbGF5OiBmbGV4OyBhbGlnbi1pdGVtczogY2VudGVyOyBqdXN0aWZ5LWNvbnRlbnQ6IHNwYWNlLWJldHdlZW47IGZsZXgtd3JhcDogd3JhcDsgZ2FwOiAxOHB4OyJ9DQo6Ojo6OiB7c3R5bGU9Im1heC13aWR0aDogNjIwcHg7In0NCjo6OiB7c3R5bGU9ImNvbG9yOiB3aGl0ZTsgZm9udC1zaXplOiAxLjU1cmVtOyBmb250LXdlaWdodDogNzAwOyBsaW5lLWhlaWdodDogMS4yNTsifQ0KVklTVUFMSVpBQ0nDk04gREUgREFUT1MNCjo6Og0KDQo6Ojoge3N0eWxlPSJjb2xvcjogI0Y0RENFOTsgZm9udC1zaXplOiAxcmVtOyBtYXJnaW4tdG9wOiA2cHg7In0NClBST1lFQ1RPIEdSVVBBTCBGSU5BTCDCtyBQQVJURSAxIDxicj4NCkRvY2VudGU6IENhcmxvcyBBbW9ydGVndWkNCjo6Og0KOjo6OjoNCg0KOjo6IHtzdHlsZT0iYmFja2dyb3VuZDogd2hpdGU7IHBhZGRpbmc6IDEwcHggMThweDsgYm9yZGVyLXJhZGl1czogMTBweDsgZmxleC1zaHJpbms6IDA7In0NCjxpbWcgc3JjPSJDOi9Vc2Vycy9qZXJzby9PbmVEcml2ZS9Eb2N1bWVudG9zL0VkdWNhY2lvbi9SJTIwTWFya2Rvd24vUHJveWVjdG9fVmlzdWFsaXphY2lvbi9fb3Ryb3MvbG9nb19Lb25yYWRfTG9yZW56LnBuZyINCiAgICAgYWx0PSJMb2dvIGRlIGxhIGluc3RpdHVjacOzbiINCiAgICAgc3R5bGU9Im1heC13aWR0aDogMjEwcHg7IGRpc3BsYXk6IGJsb2NrOyIvPg0KOjo6DQo6Ojo6Ojo6DQoNCmBgYHtyIHNldHVwLCBpbmNsdWRlPUZBTFNFfQ0KIyBpbmNsdWRlPUZBTFNFOiBlc3RlIGNodW5rIGNvbmZpZ3VyYSBlbCBkb2N1bWVudG8gcGVybyBubyBhcGFyZWNlIGVuIGVsDQojIEhUTUwgZmluYWwgLS0gbmkgZWwgY8OzZGlnbyBuaSBuaW5nw7puIHJlc3VsdGFkby4NCiMNCiMga25pdHI6Om9wdHNfY2h1bmskc2V0KCkgY2FtYmlhIGVsIGNvbXBvcnRhbWllbnRvIGRlIFRPRE9TIGxvcyBjaHVua3MNCiMgcXVlIHZpZW5lbiBkZXNwdcOpcywgZGUgdW5hIHNvbGEgdmV6LCBlbiB2ZXogZGUgcmVwZXRpciBsYSBtaXNtYSBvcGNpw7NuDQojIGNodW5rIHBvciBjaHVuay4NCmtuaXRyOjpvcHRzX2NodW5rJHNldCgNCiAgZWNobyA9IFRSVUUsICAgICAgICAjIG11ZXN0cmEgZWwgY8OzZGlnbyBkZSBSIGVuIGVsIEhUTUwgKGNvbiAiY29kZV9mb2xkaW5nOiBoaWRlIiBhcnJpYmEsIHF1ZWRhIG9jdWx0byBwb3IgZGVmZWN0byBwZXJvIHNlIHB1ZWRlIGRlc3BsZWdhcikNCiAgd2FybmluZyA9IEZBTFNFLCAgICAgIyBubyBtdWVzdHJhIHdhcm5pbmdzIGRlIFIgZW4gZWwgcmVwb3J0ZQ0KICBtZXNzYWdlID0gRkFMU0UsICAgICAjIG5vIG11ZXN0cmEgbWVuc2FqZXMgaW5mb3JtYXRpdm9zIChjb21vIGxvcyBkZSBsaWJyYXJ5KCkpDQogIGZpZy5hbGlnbiA9ICJjZW50ZXIiLA0KICBmaWcud2lkdGggPSA4LA0KICBmaWcuaGVpZ2h0ID0gNQ0KKQ0KYGBgDQoNCiMgMS4gSW50cm9kdWNjacOzbg0KRWwgcHJlc2VudGUgaW5mb3JtZSB0aWVuZSBjb21vIHByb3DDs3NpdG8gcmVhbGl6YXIgdW5hIGV4cGxvcmFjacOzbg0KaW5pY2lhbCBkZSBsb3MgZGF0b3MgaGlzdMOzcmljb3MgZGUgdmVudGFzIGRlIHRyYWplcywgY29uIGVsIGZpbiBkZQ0KZXZhbHVhciBzdSBlc3RydWN0dXJhLCBjYWxpZGFkIHkgdXRpbGlkYWQgcGFyYSBsYSBlbGFib3JhY2nDs24gZGVsDQpwcmVzdXB1ZXN0byBkZSB2ZW50YXMgZGUgMjAyNy4NCg0KRWwgYW7DoWxpc2lzIHNlIGVuZm9jYXLDoSBlbiBsYXMgY2FudGlkYWRlcyB5IGxvcyB2YWxvcmVzIGRlIHZlbnRhLA0KYXPDrSBjb21vIGVuIHN1IGNvbXBvcnRhbWllbnRvIHBvciBwZXJpb2RvLCBsw61uZWEgZGUgcHJvZHVjdG8geSBjb2xvci4NCg0KIyAyLiBQcmVwYXJhY2nDs24gZGUgbG9zIGRhdG9zDQoNCiMjIDIuMS4gSW5zdGFsYWNpw7NuIGRlIHBhcXVldGVzDQpQYXJhIHJlYWxpemFyIGxhIGV4cGxvcmFjacOzbiBkZSBsb3MgZGF0b3Mgc2UgdXRpbGl6YXLDoW4gcGFxdWV0ZXMNCmRlIFIgcXVlIHBlcm1pdGVuIGltcG9ydGFyIGFyY2hpdm9zLCBvcmdhbml6YXIgbGEgaW5mb3JtYWNpw7NuDQp5IHJlYWxpemFyIGPDoWxjdWxvcyBlc3RhZMOtc3RpY29zLg0KDQpFbCBzaWd1aWVudGUgY8OzZGlnbyBpbnN0YWxhIGxvcyBwYXF1ZXRlcyBuZWNlc2FyaW9zIHBhcmEgdHJhYmFqYXINCmNvbiBhcmNoaXZvcyBFeGNlbCB5IENTViwgbWFuaXB1bGFyIGRhdG9zIHkgZWxhYm9yYXIgZ3LDoWZpY29zLg0KDQpgYGB7ciBpbnN0YWxhY2lvbi1wYXF1ZXRlcywgZXZhbD1GQUxTRX0NCmluc3RhbGwucGFja2FnZXMoInJlYWR4bCIpICAgICAjIExlY3R1cmEgZGUgYXJjaGl2b3MgRXhjZWwNCmluc3RhbGwucGFja2FnZXMoInJlYWRyIikgICAgICAjIExlY3R1cmEgZGUgYXJjaGl2b3MgQ1NWDQppbnN0YWxsLnBhY2thZ2VzKCJkcGx5ciIpICAgICAgIyBNYW5pcHVsYWNpw7NuIHkgdHJhbnNmb3JtYWNpw7NuIGRlIGRhdG9zDQppbnN0YWxsLnBhY2thZ2VzKCJ0aWR5ciIpICAgICAgIyBPcmdhbml6YWNpw7NuIGRlIGxvcyBkYXRvcw0KaW5zdGFsbC5wYWNrYWdlcygiZ2dwbG90MiIpICAgICMgRWxhYm9yYWNpw7NuIGRlIGdyw6FmaWNvcw0KaW5zdGFsbC5wYWNrYWdlcygia25pdHIiKSAgICAgICMgUHJlc2VudGFjacOzbiBkZSB0YWJsYXMNCmBgYA0KDQojIyAyLjIuIENhcmdhIGRlIHBhcXVldGVzDQpVbmEgdmV6IGluc3RhbGFkb3MsIGxvcyBwYXF1ZXRlcyBzZSBjYXJnYW4gcGFyYSBwb2RlciB1dGlsaXphcg0Kc3VzIGZ1bmNpb25lcyBkdXJhbnRlIGVsIGFuw6FsaXNpcy4NCg0KYGBge3IgY2FyZ2EtcGFxdWV0ZXMsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9DQpsaWJyYXJ5KHJlYWR4bCkgICAgIyBJbXBvcnRhY2nDs24gZGUgYXJjaGl2b3MgRXhjZWwNCmxpYnJhcnkocmVhZHIpICAgICAjIEltcG9ydGFjacOzbiBkZSBhcmNoaXZvcyBDU1YNCmxpYnJhcnkoZHBseXIpICAgICAjIE1hbmlwdWxhY2nDs24gZGUgZGF0b3MNCmxpYnJhcnkoZ2dwbG90MikgICAjIEdyw6FmaWNvcyBleHBsb3JhdG9yaW9zDQpsaWJyYXJ5KGtuaXRyKSAgICAgIyBQcmVzZW50YWNpw7NuIGRlIHRhYmxhcw0KYGBgDQoNCiMjIDIuMy4gSW1wb3J0YWNpw7NuIGRlIGxhcyBiYXNlcyBkZSBkYXRvcw0KUGFyYSByZWFsaXphciBsYSBleHBsb3JhY2nDs24gc2UgdXRpbGl6YXLDoW4gZG9zIGZ1ZW50ZXMgZGUgaW5mb3JtYWNpw7NuLg0KTGEgcHJpbWVyYSBjb3JyZXNwb25kZSBhIGxvcyByZXBvcnRlcyBoaXN0w7NyaWNvcyBkZSB2ZW50YXMsIGFsbWFjZW5hZG9zDQplbiBhcmNoaXZvcyBFeGNlbCBzZXBhcmFkb3MgcG9yIG1lcy4gTGEgc2VndW5kYSBjb3JyZXNwb25kZSBhIGxhIGJhc2UNCmNvbnNvbGlkYWRhIGRlIGFydMOtY3Vsb3MsIGFsbWFjZW5hZGEgZW4gZm9ybWF0byBUWFQsIHF1ZSBjb250aWVuZQ0KY2FyYWN0ZXLDrXN0aWNhcyBkZXNjcmlwdGl2YXMgZGUgbG9zIHByb2R1Y3Rvcy4NCg0KTG9zIHJlcG9ydGVzIG1lbnN1YWxlcyBkZSB2ZW50YXMgc2UgaW50ZWdyYXLDoW4gZW4gdW5hIHNvbGEgYmFzZSBkZSBkYXRvcw0KcGFyYSBmYWNpbGl0YXIgZWwgYW7DoWxpc2lzIGRlbCBjb21wb3J0YW1pZW50byBoaXN0w7NyaWNvLiBQb3N0ZXJpb3JtZW50ZSwNCnNlIHJldmlzYXLDoSBsYSBlc3RydWN0dXJhIGRlIGFtYmFzIGZ1ZW50ZXMgYW50ZXMgZGUgcmVhbGl6YXIgc3UNCmludGVncmFjacOzbiB5IGxvcyBhbsOhbGlzaXMgZGVzY3JpcHRpdm9zLg0KDQojIyMgMi4zLjEuIElkZW50aWZpY2FjacOzbiBkZSBsb3MgYXJjaGl2b3MgZGUgdmVudGFzDQpFbCBzaWd1aWVudGUgY8OzZGlnbyBwZXJtaXRlIGlkZW50aWZpY2FyIGxvcyBhcmNoaXZvcyBFeGNlbCB1YmljYWRvcw0KZW4gbGEgY2FycGV0YSBxdWUgY29udGllbmUgbG9zIHJlcG9ydGVzIG1lbnN1YWxlcy4NCg0KYGBge3IgaWRlbnRpZmljYWNpb24tYXJjaGl2b3N9DQojIFJ1dGEgZGUgbGEgY2FycGV0YSBxdWUgY29udGllbmUgbG9zIHJlcG9ydGVzIG1lbnN1YWxlcw0KcnV0YV92ZW50YXMgPC0gIkM6L1VzZXJzL2plcnNvL09uZURyaXZlL0RvY3VtZW50b3MvRWR1Y2FjaW9uL1IgTWFya2Rvd24vUHJveWVjdG9fVmlzdWFsaXphY2lvbi9fdmVudGFzSGlzdG9yaWNhcyINCg0KIyBJZGVudGlmaWNhciBsb3MgYXJjaGl2b3MgRXhjZWwgZGUgbGEgY2FycGV0YQ0KYXJjaGl2b3NfdmVudGFzIDwtIGxpc3QuZmlsZXMoDQogIHBhdGggPSBydXRhX3ZlbnRhcywNCiAgcGF0dGVybiA9ICJcXC54bHN4JCIsDQogIGZ1bGwubmFtZXMgPSBUUlVFLA0KICBpZ25vcmUuY2FzZSA9IFRSVUUNCikNCg0KIyBDb25zdWx0YXIgbGEgY2FudGlkYWQgZGUgYXJjaGl2b3MgZW5jb250cmFkb3MNCmxlbmd0aChhcmNoaXZvc192ZW50YXMpDQoNCiMgTW9zdHJhciBsb3Mgbm9tYnJlcyBkZSBsb3MgYXJjaGl2b3MgZW5jb250cmFkb3MNCmJhc2VuYW1lKGFyY2hpdm9zX3ZlbnRhcykNCmBgYA0KDQojIyMgMi4zLjIuIENvbnNvbGlkYWNpw7NuIGRlIGxvcyByZXBvcnRlcyBtZW5zdWFsZXMNClVuYSB2ZXogaWRlbnRpZmljYWRvcyBsb3MgYXJjaGl2b3MsIHBvZGVtb3MgbGVlcmxvcyB5IHVuaXJsb3MgdmVydGljYWxtZW50ZS4NCkVzdGUgY8OzZGlnbyBzdXBvbmUgcXVlIGxvcyByZXBvcnRlcyB0aWVuZW4gdW5hIGVzdHJ1Y3R1cmEgY29tcGF0aWJsZSB5IHF1ZSANCmxvcyBkYXRvcyBlc3TDoW4gZW4gbGEgcHJpbWVyYSBob2phIGRlIGNhZGEgYXJjaGl2by4NCg0KKExvcyBkYXRvcyBzZSBnYXJhbnRpemFuIGRlc2RlIGxhIGRlc2NhcmdhIHF1ZSB0aWVuZSBlbCBtaXNtbyBmb3JtYXRvIHkgY2FtcG9zKQ0KDQpgYGB7ciBjb25zb2xpZGFjaW9uLXZlbnRhc30NCiMgTGVlciBjYWRhIGFyY2hpdm8gRXhjZWwgZGVzZGUgbGEgaG9qYSAiU2hlZXQxIg0KIyB5IGNvbnNvbGlkYXIgbG9zIHJlZ2lzdHJvcyBlbiB1bmEgc29sYSBiYXNlDQoNCnZlbnRhcyA8LSBiaW5kX3Jvd3MoDQogIGxhcHBseShhcmNoaXZvc192ZW50YXMsIGZ1bmN0aW9uKGFyY2hpdm8pIHsNCiAgICByZWFkX2V4Y2VsKA0KICAgICAgcGF0aCA9IGFyY2hpdm8sDQogICAgICBzaGVldCA9ICJTaGVldDEiDQogICAgKQ0KICB9KQ0KKQ0KDQojIENvbnN1bHRhciBsYXMgZGltZW5zaW9uZXMgZGUgbGEgYmFzZSBjb25zb2xpZGFkYQ0KZGltKHZlbnRhcykNCg0KIyBWaXN1YWxpemFyIGxvcyBwcmltZXJvcyByZWdpc3Ryb3MNCmhlYWQodmVudGFzKQ0KYGBgDQoNCiMjIyAyLjMuMy4gSW1wb3J0YWNpw7NuIHkgZGVwdXJhY2nDs24gZGVsIG1hZXN0cm8gZGUgYXJ0w61jdWxvcw0KRWwgbWFlc3RybyBkZSBhcnTDrWN1bG9zIHNlIGVuY3VlbnRyYSBhbG1hY2VuYWRvIGVuIHVuIGFyY2hpdm8gZGUgdGV4dG8gKFRYVCkgY3V5b3MgY2FtcG9zIGVzdMOhbiBzZXBhcmFkb3MgcG9yIHRhYnVsYWNpb25lcy4gRGVzcHXDqXMgZGUgc3UgaW1wb3J0YWNpw7NuLCBzZSByZWFsaXphcsOhIHVuYSByZXZpc2nDs24gZGUgbG9zIHJlZ2lzdHJvcyBkdXBsaWNhZG9zLiBDdWFuZG8gZG9zIG8gbcOhcyBmaWxhcyBzZWFuIGNvbXBsZXRhbWVudGUgaWTDqW50aWNhcyBlbiB0b2RhcyBzdXMgY29sdW1uYXMsIHNlIGNvbnNlcnZhcsOhIHVuYSBzb2xhIGNvcGlhLiBFc3RlIHByb2NlZGltaWVudG8gcGVybWl0aXLDoSByZWR1Y2lyIHJlZHVuZGFuY2lhcyBzaW4gZWxpbWluYXIgcmVnaXN0cm9zIHF1ZSBwcmVzZW50ZW4gZGlmZXJlbmNpYXMgZW4gc3VzIGF0cmlidXRvcy4NCg0KTGEgYmFzZSBvcmlnaW5hbCBpbXBvcnRhZGEgc2UgY29uc2VydmFyw6EgeSBsYSBkZXB1cmFjacOzbiBzZSBhcGxpY2Fyw6Egc29icmUgdW5hIGNvcGlhIGRlIHRyYWJham8sIGdhcmFudGl6YW5kbyBsYSB0cmF6YWJpbGlkYWQgZGVsIHByb2NlZGltaWVudG8uDQoNCmBgYHtyIGltcG9ydGFjaW9uLWFydGljdWxvc30NCiMgRGVmaW5pciBsYSBydXRhIGRlbCBhcmNoaXZvIG1hZXN0cm8NCnJ1dGFfYXJ0aWN1bG9zIDwtICJDOi9Vc2Vycy9qZXJzby9PbmVEcml2ZS9Eb2N1bWVudG9zL0VkdWNhY2lvbi9SIE1hcmtkb3duL1Byb3llY3RvX1Zpc3VhbGl6YWNpb24vX21hZXN0cm9BcnRpY3Vsb3MvUmVwb3J0ZSBhcnRpY3Vsb3MudHh0Ig0KDQojIEltcG9ydGFyIGVsIGFyY2hpdm8gVFhUIHNlcGFyYWRvIHBvciB0YWJ1bGFjaW9uZXMNCmFydGljdWxvcyA8LSByZWFkX2RlbGltKA0KICBmaWxlID0gcnV0YV9hcnRpY3Vsb3MsDQogIGRlbGltID0gIlx0IiwNCiAgbG9jYWxlID0gbG9jYWxlKGVuY29kaW5nID0gIldpbmRvd3MtMTI1MiIpLA0KICB0cmltX3dzID0gVFJVRSwNCiAgc2hvd19jb2xfdHlwZXMgPSBGQUxTRQ0KKQ0KDQojIENvbnRhciBsYXMgZmlsYXMgY29tcGxldGFtZW50ZSBkdXBsaWNhZGFzDQpkdXBsaWNhZG9zX2V4YWN0b3MgPC0gc3VtKGR1cGxpY2F0ZWQoYXJ0aWN1bG9zKSkNCg0KIyBDcmVhciB1bmEgYmFzZSBkZXB1cmFkYSwgY29uc2VydmFuZG8gdW5hIHNvbGEgY29waWENCiMgZGUgY2FkYSBmaWxhIGNvbXBsZXRhbWVudGUgaWTDqW50aWNhDQphcnRpY3Vsb3NfbGltcGlvIDwtIGFydGljdWxvcyAlPiUNCiAgZGlzdGluY3QoKQ0KDQojIFJlc3VtaXIgbG9zIHJlc3VsdGFkb3MNCnJlc3VtZW5fZGVwdXJhY2lvbiA8LSBkYXRhLmZyYW1lKA0KICBSZWdpc3Ryb3Nfb3JpZ2luYWxlcyA9IG5yb3coYXJ0aWN1bG9zKSwNCiAgRHVwbGljYWRvc19leGFjdG9zID0gZHVwbGljYWRvc19leGFjdG9zLA0KICBSZWdpc3Ryb3NfZGVzcHVlc19kZXB1cmFjaW9uID0gbnJvdyhhcnRpY3Vsb3NfbGltcGlvKQ0KKQ0KDQprbml0cjo6a2FibGUoDQogIHJlc3VtZW5fZGVwdXJhY2lvbiwNCiAgY2FwdGlvbiA9ICJSZXN1bWVuIGRlIGxhIGRlcHVyYWNpw7NuIGRlIGR1cGxpY2Fkb3MgZXhhY3RvcyINCikNCg0KIyBNb3N0cmFyIGxvcyBwcmltZXJvcyByZWdpc3Ryb3MgZGUgbGEgYmFzZSBkZXB1cmFkYQ0KaGVhZChhcnRpY3Vsb3NfbGltcGlvKQ0KYGBgDQoNCiMjIDIuNC4gUmV2aXNpw7NuIGluaWNpYWwgZGUgbGEgZXN0cnVjdHVyYSBkZSBsb3MgZGF0b3MNClVuYSB2ZXogaW1wb3J0YWRhcyBsYXMgZnVlbnRlcyBkZSBpbmZvcm1hY2nDs24sIHNlIHJlYWxpemFyw6EgdW5hIHJldmlzacOzbiBpbmljaWFsIGRlIHN1IGVzdHJ1Y3R1cmEgcGFyYSBpZGVudGlmaWNhciBsYSBjYW50aWRhZCBkZSByZWdpc3Ryb3MsIGxhcyB2YXJpYWJsZXMgZGlzcG9uaWJsZXMgeSBsb3MgdGlwb3MgZGUgZGF0b3MgZGUgY2FkYSBiYXNlLiBFc3RhIHJldmlzacOzbiBwZXJtaXRpcsOhIHJlY29ub2NlciBsYXMgY2FyYWN0ZXLDrXN0aWNhcyBnZW5lcmFsZXMgZGUgbGEgaW5mb3JtYWNpw7NuIHkgZGV0ZWN0YXIgcG9zaWJsZXMgYWp1c3RlcyBuZWNlc2FyaW9zIGFudGVzIGRlIHJlYWxpemFyIGVsIGFuw6FsaXNpcyBleHBsb3JhdG9yaW8uDQoNCiMjIyAyLjQuMS4gRGltZW5zaW9uZXMgZGUgbGFzIGJhc2VzDQpMYXMgZGltZW5zaW9uZXMgcGVybWl0ZW4gY29ub2NlciBlbCBuw7ptZXJvIGRlIHJlZ2lzdHJvcyB5IHZhcmlhYmxlcyBkaXNwb25pYmxlcyBlbiBjYWRhIGZ1ZW50ZSBkZSBpbmZvcm1hY2nDs24uDQoNCmBgYHtyIGRpbWVuc2lvbmVzLWJhc2VzfQ0KIyBDYW50aWRhZCBkZSBmaWxhcyB5IGNvbHVtbmFzIGRlIGxhIGJhc2UgZGUgdmVudGFzDQpkaW0odmVudGFzKQ0KDQojIENhbnRpZGFkIGRlIGZpbGFzIHkgY29sdW1uYXMgZGVsIG1hZXN0cm8gZGUgYXJ0w61jdWxvcw0KZGltKGFydGljdWxvc19saW1waW8pDQpgYGANCiMjIyAyLjQuMi4gTm9tYnJlcyBkZSBsYXMgdmFyaWFibGVzDQoNCmBgYHtyIG5vbWJyZXMtdmFyaWFibGVzfQ0KIyBWYXJpYWJsZXMgZGlzcG9uaWJsZXMgZW4gbGEgYmFzZSBkZSB2ZW50YXMNCm5hbWVzKHZlbnRhcykNCg0KIyBWYXJpYWJsZXMgZGlzcG9uaWJsZXMgZW4gZWwgbWFlc3RybyBkZSBhcnTDrWN1bG9zDQpuYW1lcyhhcnRpY3Vsb3NfbGltcGlvKQ0KYGBgDQoNCiMjIyAyLjQuMy4gVGlwb3MgZGUgZGF0b3MgeSBwcmltZXJvcyByZWdpc3Ryb3MNCg0KYGBge3IgZXN0cnVjdHVyYS1iYXNlc30NCiMgRXN0cnVjdHVyYSBkZSBsYSBiYXNlIGRlIHZlbnRhcw0KZ2xpbXBzZSh2ZW50YXMpDQoNCiMgRXN0cnVjdHVyYSBkZWwgbWFlc3RybyBkZSBhcnTDrWN1bG9zDQpnbGltcHNlKGFydGljdWxvc19saW1waW8pDQoNCiMgUHJpbWVyb3MgcmVnaXN0cm9zIGRlIHZlbnRhcw0KaGVhZCh2ZW50YXMpDQoNCiMgUHJpbWVyb3MgcmVnaXN0cm9zIGRlbCBtYWVzdHJvIGRlIGFydMOtY3Vsb3MNCmhlYWQoYXJ0aWN1bG9zX2xpbXBpbykNCmBgYA0KDQojIyAyLjUuIEZpbHRyYWRvIGRlIGFydMOtY3Vsb3MgeSB2ZW50YXMgZGUgdHJhamVzDQpDb24gZWwgcHJvcMOzc2l0byBkZSBkZWxpbWl0YXIgbGEgaW5mb3JtYWNpw7NuIHJlbGV2YW50ZSBwYXJhIGVsIHByb3llY3RvLCBzZSBpZGVudGlmaWNhcsOhbiBsb3MgYXJ0w61jdWxvcyBjbGFzaWZpY2Fkb3MgZW4gbGEgY2F0ZWdvcsOtYSAxNiAtIFRSQUpFLg0KDQpQb3N0ZXJpb3JtZW50ZSwgc2UgcmV2aXNhcsOhbiBzdXMgc3ViZGl2aXNpb25lcyBwcmVzdXB1ZXN0YWxlcyBwYXJhIGRpc3Rpbmd1aXIgbGFzIGzDrW5lYXMgMDU4IC0gVFJBSkUgeSAwNjAgLSBUUkFKRSBMSU5PLCBkZSBhY3VlcmRvIGNvbiBsYSBjbGFzaWZpY2FjacOzbiByZWdpc3RyYWRhIGVuIGVsIG1hZXN0cm8gZGUgYXJ0w61jdWxvcy4NCg0KIyMjIDIuNS4xLiBJZGVudGlmaWNhY2nDs24gZGUgYXJ0w61jdWxvcyBkZSBsYSBjYXRlZ29yw61hIHRyYWplDQoNCmBgYHtyIGZpbHRyby1hcnRpY3Vsb3MtdHJhamVzfQ0KIyBGaWx0cmFyIGxvcyB0cmFqZXMgZGVzZGUgZWwgbWFlc3RybyB5YSBkZXB1cmFkbw0KYXJ0aWN1bG9zX3RyYWplcyA8LSBhcnRpY3Vsb3NfbGltcGlvICU+JQ0KICBmaWx0ZXIoQ0FURUdPUklBID09ICIxNiAtIFRSQUpFIikNCg0KIyBDb25zdWx0YXIgbGFzIGRpbWVuc2lvbmVzIGRlIGxhIGJhc2UgZmlsdHJhZGENCmRpbShhcnRpY3Vsb3NfdHJhamVzKQ0KDQojIE1vc3RyYXIgbG9zIHByaW1lcm9zIHJlZ2lzdHJvcw0KaGVhZChhcnRpY3Vsb3NfdHJhamVzKQ0KYGBgDQoNCiMjIyAyLjUuMi4gRmlsdHJhZG8gZGUgbGFzIHZlbnRhcyBjb3JyZXNwb25kaWVudGVzIGEgdHJhamVzDQoNCmBgYHtyIGZpbHRyby12ZW50YXMtdHJhamVzfQ0KIyBGaWx0cmFyIGxhcyB2ZW50YXMgZGUgbGFzIHJlZmVyZW5jaWFzIGlkZW50aWZpY2FkYXMgY29tbyB0cmFqZXMNCnZlbnRhc190cmFqZXMgPC0gdmVudGFzICU+JQ0KICBmaWx0ZXIoUmVmZXJlbmNpYSAlaW4lIGFydGljdWxvc190cmFqZXMkUmVmZXJlbmNpYSkNCg0KIyBDb25zdWx0YXIgbGFzIGRpbWVuc2lvbmVzIGRlIGxhIGJhc2UgZmlsdHJhZGENCmRpbSh2ZW50YXNfdHJhamVzKQ0KDQojIFJldmlzYXIgbG9zIHByaW1lcm9zIHJlZ2lzdHJvcw0KaGVhZCh2ZW50YXNfdHJhamVzKQ0KYGBgDQoNCiMjIDIuNi4gUmV2aXNpw7NuIGRlIGxhIGNhbGlkYWQgZGUgbG9zIGRhdG9zDQpMYSByZXZpc2nDs24gZGUgbGEgY2FsaWRhZCBkZSBsb3MgZGF0b3MgcGVybWl0ZSBpZGVudGlmaWNhciBwb3NpYmxlcyBwcm9ibGVtYXMgZW4gbGEgaW5mb3JtYWNpw7NuIGFudGVzIGRlIHJlYWxpemFyIGxvcyBhbsOhbGlzaXMgZXhwbG9yYXRvcmlvcy4gRW4gZXN0YSBldGFwYSBzZSBldmFsdWFyw6EgbGEgcHJlc2VuY2lhIGRlIHZhbG9yZXMgZmFsdGFudGVzIHkgcmVnaXN0cm9zIGR1cGxpY2Fkb3MgZW4gbGEgYmFzZSBkZSB2ZW50YXMgZGUgdHJhamVzLiBFc3RvcyBwcm9jZWRpbWllbnRvcyBwZXJtaXRpcsOhbiBjb25vY2VyIGVsIGVzdGFkbyBnZW5lcmFsIGRlIGxvcyBkYXRvcyB5IGRldGVybWluYXIgc2kgZXMgbmVjZXNhcmlvIHJlYWxpemFyIGFqdXN0ZXMgYW50ZXMgZGUgY29udGludWFyIGNvbiBlbCBhbsOhbGlzaXMuIE5vIHNlIGVsaW1pbmFyw6FuIHJlZ2lzdHJvcyBhdXRvbcOhdGljYW1lbnRlLCB5YSBxdWUgcHJpbWVybyBzZSBkZWJlIGV2YWx1YXIgc3UgbmF0dXJhbGV6YSB5IHJlbGV2YW5jaWEuDQoNCiMjIyAyLjYuMS4gSWRlbnRpZmljYWNpw7NuIGRlIHZhbG9yZXMgZmFsdGFudGVzDQpMb3MgdmFsb3JlcyBmYWx0YW50ZXMgY29ycmVzcG9uZGVuIGEgcmVnaXN0cm9zIGVuIGxvcyBxdWUgdW5hIG8gdmFyaWFzIHZhcmlhYmxlcyBubyBjb250aWVuZW4gaW5mb3JtYWNpw7NuLiBTdSBpZGVudGlmaWNhY2nDs24gcGVybWl0ZSByZWNvbm9jZXIgcG9zaWJsZXMgbGltaXRhY2lvbmVzIGVuIGxhIGludGVncmlkYWQgZGUgbG9zIGRhdG9zIHkgZGV0ZXJtaW5hciBzaSBsYXMgdmFyaWFibGVzIGRpc3BvbmlibGVzIHNvbiBhZGVjdWFkYXMgcGFyYSBsb3MgYW7DoWxpc2lzIHBvc3RlcmlvcmVzLg0KDQpgYGB7ciB2YWxvcmVzLWZhbHRhbnRlc30NCiMgQ29udGFyIGxvcyB2YWxvcmVzIGZhbHRhbnRlcyBwb3IgdmFyaWFibGUNCmZhbHRhbnRlc192ZW50YXMgPC0gZGF0YS5mcmFtZSgNCiAgVmFyaWFibGUgPSBuYW1lcyh2ZW50YXNfdHJhamVzKSwNCiAgQ2FudGlkYWRfZmFsdGFudGUgPSBzYXBwbHkoDQogICAgdmVudGFzX3RyYWplcywNCiAgICBmdW5jdGlvbih4KSBzdW0oaXMubmEoeCkpDQogICkNCikNCg0KIyBDYWxjdWxhciBlbCBwb3JjZW50YWplIGRlIHZhbG9yZXMgZmFsdGFudGVzIHBvciB2YXJpYWJsZQ0KZmFsdGFudGVzX3ZlbnRhcyRQb3JjZW50YWplX2ZhbHRhbnRlIDwtIHJvdW5kKA0KICBmYWx0YW50ZXNfdmVudGFzJENhbnRpZGFkX2ZhbHRhbnRlIC8NCiAgICBucm93KHZlbnRhc190cmFqZXMpICogMTAwLA0KICAyDQopDQoNCiMgUHJlc2VudGFyIGxhcyB2YXJpYWJsZXMgY29uIHZhbG9yZXMgZmFsdGFudGVzDQpmYWx0YW50ZXNfdmVudGFzICU+JQ0KICBmaWx0ZXIoQ2FudGlkYWRfZmFsdGFudGUgPiAwKSAlPiUNCiAgYXJyYW5nZShkZXNjKENhbnRpZGFkX2ZhbHRhbnRlKSkgJT4lDQogIGtuaXRyOjprYWJsZSgNCiAgICBjYXB0aW9uID0gIlZhbG9yZXMgZmFsdGFudGVzIGVuIGxhIGJhc2UgZGUgdmVudGFzIGRlIHRyYWplcyINCiAgKQ0KYGBgDQoNCiMjIyAyLjYuMi4gSWRlbnRpZmljYWNpw7NuIGRlIHJlZ2lzdHJvcyBkdXBsaWNhZG9zDQpMYSBpZGVudGlmaWNhY2nDs24gZGUgcmVnaXN0cm9zIGR1cGxpY2Fkb3MgcGVybWl0ZSBkZXRlY3RhciBmaWxhcyBxdWUgcHJlc2VudGFuIGV4YWN0YW1lbnRlIGxvcyBtaXNtb3MgdmFsb3JlcyBlbiB0b2RhcyBzdXMgdmFyaWFibGVzLiBTdSByZXZpc2nDs24gY29udHJpYnV5ZSBhIHByZXZlbmlyIHBvc2libGVzIGRpc3RvcnNpb25lcyBlbiBsb3MgcmVzdWx0YWRvczsgc2luIGVtYmFyZ28sIGxhIGV4aXN0ZW5jaWEgZGUgZmlsYXMgaWTDqW50aWNhcyBubyBpbXBsaWNhIG5lY2VzYXJpYW1lbnRlIHF1ZSBjb3JyZXNwb25kYW4gYSBlcnJvcmVzLiBQb3IgZXN0YSByYXrDs24sIGVuIGVzdGEgZXRhcGEgw7puaWNhbWVudGUgc2UgaWRlbnRpZmljYXLDoW4gbG9zIHBvc2libGVzIGR1cGxpY2Fkb3MsIHNpbiBlbGltaW5hcmxvcyBkZSBsYSBiYXNlLg0KDQpgYGB7ciByZWdpc3Ryb3MtZHVwbGljYWRvc30NCiMgQ29udGFyIGxhcyBmaWxhcyBjb21wbGV0YW1lbnRlIGR1cGxpY2FkYXMNCmR1cGxpY2Fkb3NfdmVudGFzIDwtIHN1bShkdXBsaWNhdGVkKHZlbnRhc190cmFqZXMpKQ0KDQojIFJlc3VtaXIgbG9zIHJlc3VsdGFkb3MgZGUgbGEgcmV2aXNpw7NuDQpyZXN1bWVuX2R1cGxpY2Fkb3MgPC0gZGF0YS5mcmFtZSgNCiAgVG90YWxfcmVnaXN0cm9zID0gbnJvdyh2ZW50YXNfdHJhamVzKSwNCiAgUmVnaXN0cm9zX2R1cGxpY2Fkb3MgPSBkdXBsaWNhZG9zX3ZlbnRhcywNCiAgUG9yY2VudGFqZV9kdXBsaWNhZG9zID0gcm91bmQoDQogICAgZHVwbGljYWRvc192ZW50YXMgLyBucm93KHZlbnRhc190cmFqZXMpICogMTAwLA0KICAgIDINCiAgKQ0KKQ0KDQojIFByZXNlbnRhciBsYSB0YWJsYSBkZSByZXN1bHRhZG9zDQprbml0cjo6a2FibGUoDQogIHJlc3VtZW5fZHVwbGljYWRvcywNCiAgY2FwdGlvbiA9ICJSZXZpc2nDs24gZGUgcmVnaXN0cm9zIGR1cGxpY2Fkb3MgZW4gbGFzIHZlbnRhcyBkZSB0cmFqZXMiDQopDQpgYGANCiMjIDIuNy4gUmV2aXNpw7NuIGRlIGxhcyB2YXJpYWJsZXMgcHJpbmNpcGFsZXMgZGUgdmVudGFzDQpQYXJhIHByZXBhcmFyIGxhIGluZm9ybWFjacOzbiBkZXN0aW5hZGEgYWwgYW7DoWxpc2lzIGhpc3TDs3JpY28geSBhIGxhIGVsYWJvcmFjacOzbiBkZWwgcHJlc3VwdWVzdG8gZGUgdmVudGFzIGRlIDIwMjcsIHNlIHJldmlzYXLDoW4gbGFzIHZhcmlhYmxlcyBkaXNwb25pYmxlcyBlbiBsYSBiYXNlIGRlIHZlbnRhcyBkZSB0cmFqZXMuIEVzdGEgcmV2aXNpw7NuIHBlcm1pdGlyw6EgaWRlbnRpZmljYXIgbG9zIGNhbXBvcyByZWxhY2lvbmFkb3MgY29uIGxhIGZlY2hhIGRlIGxhIG9wZXJhY2nDs24sIGxhcyBjYW50aWRhZGVzIHZlbmRpZGFzLCBsb3MgdmFsb3JlcyBkZSB2ZW50YSB5IGxvcyBhdHJpYnV0b3MgZGUgbG9zIHByb2R1Y3RvcywgY29tbyBlbCBjb2xvci4NCg0KIyMjIDIuNy4xLiBJZGVudGlmaWNhY2nDs24gZGUgbGFzIHZhcmlhYmxlcyBkaXNwb25pYmxlcw0KU2UgY29uc3VsdGFyw6FuIGxvcyBub21icmVzIGRlIGxhcyB2YXJpYWJsZXMgZGUgbGEgYmFzZSBkZSB2ZW50YXMgZGUgdHJhamVzIHkgZGVsIG1hZXN0cm8gZGUgYXJ0w61jdWxvcyBwYXJhIGlkZW50aWZpY2FyIGxvcyBjYW1wb3MgcXVlIHNlIHV0aWxpemFyw6FuIGVuIGxhcyBzaWd1aWVudGVzIGV0YXBhcyBkZWwgYW7DoWxpc2lzLg0KDQpgYGB7ciByZXZpc2lvbi12YXJpYWJsZXMtcHJpbmNpcGFsZXN9DQojIFZhcmlhYmxlcyBkZSBsYSBiYXNlIGRlIHZlbnRhcyBkZSB0cmFqZXMNCm5hbWVzKHZlbnRhc190cmFqZXMpDQoNCiMgVmFyaWFibGVzIGRlbCBtYWVzdHJvIGRlIGFydMOtY3Vsb3MNCm5hbWVzKGFydGljdWxvc190cmFqZXMpDQpgYGANCg0KIyMjIDIuNy4yLiBTZWxlY2Npw7NuIGRlIHZhcmlhYmxlcyBwYXJhIGVsIGFuw6FsaXNpcw0KDQpMYSBzZWxlY2Npw7NuIGRlIHZhcmlhYmxlcyBzZSByZWFsaXrDsyBkZSBhY3VlcmRvIGNvbiBsb3Mgb2JqZXRpdm9zIGRlbCBwcm95ZWN0byB5IGxhIHV0aWxpZGFkIGRlIGNhZGEgY2FtcG8gcGFyYSBsYSBlbGFib3JhY2nDs24gZGVsIHByZXN1cHVlc3RvIGRlIHZlbnRhcyBkZSAyMDI3LiBTZSBwcmlvcml6YXLDoW4gbGEgZmVjaGEgZGUgbGEgb3BlcmFjacOzbiwgbGEgcmVmZXJlbmNpYSBkZWwgYXJ0w61jdWxvLCBsYSB0YWxsYSB5IGxhIGNhbnRpZGFkIHZlbmRpZGEuIEEgcGFydGlyIGRlbCBtYWVzdHJvIGRlIGFydMOtY3Vsb3Mgc2UgaW5jb3Jwb3JhcsOhbiBsb3MgYXRyaWJ1dG9zIGRlc2NyaXB0aXZvcyBhY3R1YWxlcyBkZWwgcHJvZHVjdG8sIGluY2x1eWVuZG8gbGEgbMOtbmVhLCBlbCBjb2xvciwgbGEgY2F0ZWdvcsOtYSwgZWwgcHJlc3VwdWVzdG8sIGxhIHNpbHVldGEgeSBlbCBkaXNlw7FvIGRlIGxhIHByZW5kYS4NCg0KU2UgY29uc2VydmFyw6EgbGEgcmVmZXJlbmNpYSBjb21vIGNhbXBvIGRlIHJlbGFjacOzbiBlbnRyZSBsYXMgZnVlbnRlcyBkZSBpbmZvcm1hY2nDs24uIExhIHRhbGxhIHNlIG1hbnRlbmRyw6EgZGVzZGUgbG9zIHJlZ2lzdHJvcyBoaXN0w7NyaWNvcyBkZSB2ZW50YXMsIGRlYmlkbyBhIHF1ZSBwZXJtaXRlIGRpc3Rpbmd1aXIgbGFzIHVuaWRhZGVzIHZlbmRpZGFzIHBvciB0YWxsYSwgbWllbnRyYXMgcXVlIGVsIG1hZXN0cm8gYXBvcnRhIGxhIGNsYXNpZmljYWNpw7NuIGdlbmVyYWwgeSBhY3R1YWxpemFkYSBkZWwgYXJ0w61jdWxvLg0KDQpMb3MgdmFsb3JlcyBtb25ldGFyaW9zIHkgb3Ryb3MgY2FtcG9zIHF1ZSBubyBmb3JtYW4gcGFydGUgZGVsIGFsY2FuY2UgcHJpbmNpcGFsIHNlIGV4Y2x1aXLDoW4gZGUgbGEgYmFzZSBkZSBhbsOhbGlzaXMuIEFzaW1pc21vLCBzZSByZXZpc2Fyw6EgZWwgZXN0YWRvIGRlIGxvcyByZWdpc3Ryb3MgcGFyYSBleGNsdWlyIGxhcyBvcGVyYWNpb25lcyBjYW5jZWxhZGFzLCB1bmEgdmV6IGlkZW50aWZpY2FkYSBzdSBkZW5vbWluYWNpw7NuIGV4YWN0YSBlbiBsb3MgZGF0b3MgZGUgb3JpZ2VuLg0KDQpgYGB7ciBzZWxlY2Npb24tdmFyaWFibGVzfQ0KIyAxLiBTZWxlY2Npb25hciBsYXMgdmFyaWFibGVzIG5lY2VzYXJpYXMgZGUgbGFzIHZlbnRhcyBkZSB0cmFqZXMNCnZlbnRhc19zZWxlY2Npb24gPC0gdmVudGFzX3RyYWplcyAlPiUNCiAgc2VsZWN0KA0KICAgIFJlZmVyZW5jaWEsDQogICAgYERldGFsbGUgZXh0LiAyYCwNCiAgICBGZWNoYSwNCiAgICBDYW50aWRhZCwNCiAgICBFc3RhZG8NCiAgKQ0KDQojIDIuIFNlbGVjY2lvbmFyIGxvcyBhdHJpYnV0b3MgYWN0dWFsZXMgZGVsIG1hZXN0cm8gZGUgdHJhamVzDQphcnRpY3Vsb3Nfc2VsZWNjaW9uIDwtIGFydGljdWxvc190cmFqZXMgJT4lDQogIHNlbGVjdCgNCiAgICBSZWZlcmVuY2lhLA0KICAgIGBEZXNjLiBpdGVtYCwNCiAgICBgRXh0LiAxIGRldGFsbGVgLA0KICAgIGBEZXNjLiBleHQuIDFgLA0KICAgIENBVEVHT1JJQSwNCiAgICBQUkVTVVBVRVNUTywNCiAgICBMSU5FQSwNCiAgICBTSUxVRVRBLA0KICAgIGBESVNFw5FPIFBSRU5EQWANCiAgKQ0KDQojIDMuIFJldmlzYXIgbG9zIGVzdGFkb3MgZGUgbG9zIHJlZ2lzdHJvcyBkZSB2ZW50YXMNCnZlbnRhc19zZWxlY2Npb24gJT4lDQogIGNvdW50KEVzdGFkbywgc29ydCA9IFRSVUUpICU+JQ0KICBrbml0cjo6a2FibGUoDQogICAgY2FwdGlvbiA9ICJEaXN0cmlidWNpw7NuIGRlIHJlZ2lzdHJvcyBwb3IgZXN0YWRvIg0KICApDQoNCiMgNC4gSWRlbnRpZmljYXIgcmVmZXJlbmNpYXMgcXVlIGFwYXJlY2VuIHZhcmlhcyB2ZWNlcw0KcmVmZXJlbmNpYXNfcmVwZXRpZGFzIDwtIGFydGljdWxvc19zZWxlY2Npb24gJT4lDQogIGNvdW50KFJlZmVyZW5jaWEsIG5hbWUgPSAiTnVtZXJvX3JlZ2lzdHJvcyIpICU+JQ0KICBmaWx0ZXIoTnVtZXJvX3JlZ2lzdHJvcyA+IDEpICU+JQ0KICBhcnJhbmdlKGRlc2MoTnVtZXJvX3JlZ2lzdHJvcykpDQoNCiMgTW9zdHJhciBsYXMgcHJpbWVyYXMgMjAgcmVmZXJlbmNpYXMgcmVwZXRpZGFzDQpoZWFkKHJlZmVyZW5jaWFzX3JlcGV0aWRhcywgMjApICU+JQ0KICBrbml0cjo6a2FibGUoDQogICAgY2FwdGlvbiA9ICJSZWZlcmVuY2lhcyByZXBldGlkYXMgZW4gZWwgbWFlc3RybyBkZSB0cmFqZXMiDQogICkNCg0KIyA1LiBSZXN1bWlyIGxhIHJldmlzacOzbiBkZSByZWZlcmVuY2lhcw0KZGF0YS5mcmFtZSgNCiAgUmVmZXJlbmNpYXNfdW5pY2FzID0gbl9kaXN0aW5jdChhcnRpY3Vsb3Nfc2VsZWNjaW9uJFJlZmVyZW5jaWEpLA0KICBSZWZlcmVuY2lhc19yZXBldGlkYXMgPSBucm93KHJlZmVyZW5jaWFzX3JlcGV0aWRhcykNCikgJT4lDQogIGtuaXRyOjprYWJsZSgNCiAgICBjYXB0aW9uID0gIlJlc3VtZW4gZGUgbGEgcmV2aXNpw7NuIGRlIHJlZmVyZW5jaWFzIg0KICApDQpgYGA=