Generador de valor de datos

Paso 1. Definir el área del negocio que buscamos impactar/ mejorar y su KPI.

¿Qué objetivos esperas apoyar? ¿Cuáles son tus KPI’s establecidos que se utilizan para medir el rendimiento?

En este caso, nuestra base de datos se trata de distintas tiendas de abarrotes y lo que se busca es realizar un Market Basket Analysis, que nos ayudará a conocer que productos tienen relación y se venden en conjunto para crear después estrategias, por lo tanto, esto significa que el área que estamos buscando impactar y mejorar es el departamento de Mercadotecnia y el KPI será Ventas por mes.

Paso 2. Seleccionar plantilla(s) para crear valor a partir de los datos de los clientes.

Para crear valor es necesario seleccionar las plantillas de Segmentación para acortar el campo, es decir reducir a ciertos públicos que se caracterizan por comprar varios productos en conjunto, un ejemplo es quien vemos que compra distitnos productos para bebés, lo que nos quiere decir que ese grupo podemos segmentarlos a padres de familia, de cierto tipo nivel socioeconómico dependiendo el tipo de producto que compra. La otra plantilla a utilizar es Personalización donde a partir del Market Basket podremos crear mensajes, ofertas, jugar con los precios y productos o servicios que sean más relevantes y más valiosos.

Paso 3. Generar ideas o conceptos específicos.

Hipótesis:

Hipótesis 1: Estrategias de descuentos en los productos.
Hipótesis 2: Crear paquetes de productos con temáticas para que se lleven en conjunto.
Hipótesis 3: Generar un producto/servicio si observamos que juntos puede ser una venta más potente.
Hipótesis 4: Segmentar y personalizar el conjunto de productos.

Paso 4. Reunir los datos específicos.

¿Qué datos tenemos? ¿Qué datos necesitamos?

Previamnte se limpio la base de datos entregada anteriorimente y sus actuales variables son: vcClaveTienda, DescGiro, Fecha, Hora, Marca, Fabricante, Producto, Precio, Ult.Costo, Unidades, F.Ticket, NombreDepartamento, NombreFamilia, NombreCategoria, Estado, Mts.2, Tipo.ubicación, Giro, Hora.inicio, Hora.cierre, Dia_de_la_semana, Subtotal, Utilidad.

Paso 5. Plan de ejecución.

Fase 1. Piloto de descuentos, paquetes y precios en tiendas de abarrotes de Nuevo León (95,410 unidades).
Fase 2. Demas estados: Chiapas, Jalisco, Quintana Roo y Sinaloa.

Importar base de datos

bd_limpia <- read.csv("/Users/georginamartinez/Documents/Tec/Séptimo Semestre/Analítica para negocios, de los datos a decisiones/abarrotes_bd_limpia.csv")

Paquetes y librerías requeridas

# install.packages("plyr")
library(Matrix)
# install.packages("arules")
library(arules)
## 
## Attaching package: 'arules'
## The following objects are masked from 'package:base':
## 
##     abbreviate, write
# install.packages("arulesViz")  
library(arulesViz)
library(datasets)

Ordenar de menor a mayor los Tickets

bd_limpia <- bd_limpia[order(bd_limpia$F.Ticket),]
head(bd_limpia)
##   vcClaveTienda  DescGiro      Fecha Hora                      Marca
## 1         MX001 Abarrotes 2020-06-19    8                NUTRI LECHE
## 2         MX001 Abarrotes 2020-06-19    8                     DAN UP
## 3         MX001 Abarrotes 2020-06-19    8                      BIMBO
## 4         MX001 Abarrotes 2020-06-19    8                      PEPSI
## 5         MX001 Abarrotes 2020-06-19    8 BLANCA NIEVES (DETERGENTE)
## 6         MX001 Abarrotes 2020-06-19    8                      FLASH
##                   Fabricante                           Producto Precio
## 1                    MEXILAC                Nutri Leche 1 Litro   16.0
## 2           DANONE DE MEXICO DANUP STRAWBERRY P/BEBER 350GR NAL   14.0
## 3                GRUPO BIMBO                Rebanadas Bimbo 2Pz    5.0
## 4        PEPSI-COLA MEXICANA                   Pepsi N.R. 400Ml    8.0
## 5 FABRICA DE JABON LA CORONA      Detergente Blanca Nieves 500G   19.5
## 6                       ALEN      Flash Xtra Brisa Marina 500Ml    9.5
##   Ult.Costo Unidades F.Ticket NombreDepartamento          NombreFamilia
## 1     12.31        1        1          Abarrotes Lacteos y Refrigerados
## 2     14.00        1        2          Abarrotes Lacteos y Refrigerados
## 3      5.00        1        3          Abarrotes         Pan y Tortilla
## 4      8.00        1        3          Abarrotes                Bebidas
## 5     15.00        1        4          Abarrotes     Limpieza del Hogar
## 6      7.31        1        4          Abarrotes     Limpieza del Hogar
##             NombreCategoria     Estado Mts.2 Tipo.ubicación      Giro
## 1                     Leche Nuevo León    60        Esquina Abarrotes
## 2                    Yogurt Nuevo León    60        Esquina Abarrotes
## 3     Pan Dulce Empaquetado Nuevo León    60        Esquina Abarrotes
## 4 Refrescos Plástico (N.R.) Nuevo León    60        Esquina Abarrotes
## 5                Lavandería Nuevo León    60        Esquina Abarrotes
## 6      Limpiadores Líquidos Nuevo León    60        Esquina Abarrotes
##   Hora.inicio Hora.cierre Dia_de_la_semana Subtotal Utilidad
## 1        8:00       22:00                6     16.0     3.69
## 2        8:00       22:00                6     14.0     0.00
## 3        8:00       22:00                6      5.0     0.00
## 4        8:00       22:00                6      8.0     0.00
## 5        8:00       22:00                6     19.5     4.50
## 6        8:00       22:00                6      9.5     2.19
tail(bd_limpia)
##        vcClaveTienda   DescGiro      Fecha Hora          Marca
## 107394         MX004 Carnicería 2020-10-15   11         YEMINA
## 167771         MX004 Carnicería 2020-10-15   11     DEL FUERTE
## 149429         MX004 Carnicería 2020-10-15   11 COCA COLA ZERO
## 168750         MX004 Carnicería 2020-10-15   11       DIAMANTE
## 161193         MX004 Carnicería 2020-10-15   12          PEPSI
## 112970         MX004 Carnicería 2020-10-15   12      COCA COLA
##                  Fabricante                       Producto Precio Ult.Costo
## 107394               HERDEZ    PASTA SPAGHETTI YEMINA 200G      7      5.38
## 167771 ALIMENTOS DEL FUERTE PURE DE TOMATE DEL FUERTE 345G     12      9.23
## 149429            COCA COLA           COCA COLA ZERO 600ML     15     11.54
## 168750           EMPACADOS              ARROZ DIAMANTE225G     11      8.46
## 161193  PEPSI-COLA MEXICANA              PEPSI N. R. 500ML     10      7.69
## 112970            COCA COLA     COCA COLA RETORNABLE 500ML     10      7.69
##        Unidades F.Ticket NombreDepartamento        NombreFamilia
## 107394        2   450032          Abarrotes       Sopas y Pastas
## 167771        1   450032          Abarrotes Salsas y Sazonadores
## 149429        2   450034          Abarrotes              Bebidas
## 168750        1   450037          Abarrotes    Granos y Semillas
## 161193        1   450039          Abarrotes              Bebidas
## 112970        8   450040          Abarrotes              Bebidas
##                      NombreCategoria  Estado Mts.2 Tipo.ubicación      Giro
## 107394 Fideos, Spaguetti, Tallarines Sinaloa    53        Esquina Abarrotes
## 167771          Salsa para Spaguetti Sinaloa    53        Esquina Abarrotes
## 149429         Refrescos Retornables Sinaloa    53        Esquina Abarrotes
## 168750                         Arroz Sinaloa    53        Esquina Abarrotes
## 161193     Refrescos Plástico (N.R.) Sinaloa    53        Esquina Abarrotes
## 112970         Refrescos Retornables Sinaloa    53        Esquina Abarrotes
##        Hora.inicio Hora.cierre Dia_de_la_semana Subtotal Utilidad
## 107394        7:00       23:00                5       14     1.62
## 167771        7:00       23:00                5       12     2.77
## 149429        7:00       23:00                5       30     3.46
## 168750        7:00       23:00                5       11     2.54
## 161193        7:00       23:00                5       10     2.31
## 112970        7:00       23:00                5       80     2.31

Generar basket

# install.packages("plyr")
library(plyr)
basket <- ddply(bd_limpia,c("F.Ticket"), function(bd_limpia)paste(bd_limpia$Marca, collapse = ","))

Eliminar Número de Ticket

basket$F.Ticket <- NULL

Renombramos el nombre de la columna

colnames(basket) <- c("Marca")

Exportar basket

write.csv(basket,"basket_abarrotes.csv", quote = FALSE, row.names = FALSE)

Importar transacciones

tr <- read.transactions("/Users/georginamartinez/basket_abarrotes.csv", format = "basket" , sep= ",")

reglas.asociacion <- apriori(tr, parameter = list(supp= 0.001, conf=0.2, maxlen=10))
## Apriori
## 
## Parameter specification:
##  confidence minval smax arem  aval originalSupport maxtime support minlen
##         0.2    0.1    1 none FALSE            TRUE       5   0.001      1
##  maxlen target  ext
##      10  rules TRUE
## 
## Algorithmic control:
##  filter tree heap memopt load sort verbose
##     0.1 TRUE TRUE  FALSE TRUE    2    TRUE
## 
## Absolute minimum support count: 115 
## 
## set item appearances ...[0 item(s)] done [0.00s].
## set transactions ...[604 item(s), 115111 transaction(s)] done [0.04s].
## sorting and recoding items ... [207 item(s)] done [0.00s].
## creating transaction tree ... done [0.05s].
## checking subsets of size 1 2 3 done [0.00s].
## writing ... [11 rule(s)] done [0.00s].
## creating S4 object  ... done [0.02s].
# summary(reglas.asociacion)
# inspect(reglas.asociacion)

reglas.asociacion <- sort(reglas.asociacion, by = "confidence", decreasing = TRUE)
# summary(reglas.asociacion)
# inspect(reglas.asociacion)

top10reglas <- head(reglas.asociacion, n = 10, by = "confidence")

Gráfica Top 10 reglas

plot(top10reglas, method = "graph", engine = "htmlwidget")    

Conclusiones

El Market Basket Analysis nos sirve para conocer patrones sobre que productos se llevan en conjunto o si compran uno que otros compran y más a través de un conjunto de datos, lo utilizan muchas empresas porque les permite crear estrategias para aumentar sus ventas e incluso ofrecer una experiencia personalizada a los clientes.

Para esto tuvimos que realizar una limpieza de datos a la base de datos brindada y después conocer las reglas que nos diran que productos tienen relación en las tiendas de abarrotes.

La gráfica muestra las top 10 reglas que se encontraron dentro de la base de datos sobre las tiendas de Abarrotes y a continuación se intepretaran los resultados:

  • Regla 1 y 9: Si se llevan el Salvo también compran junto el Fabuloso y viceversa si compran el Fabuloso se llevan también el Salvo. Estrategia. Armar un paquete de limpieza inclueydno el Fabuloso y Salvo complementando con otros productos ya que estamos viendo esta relación de que los dos son para limpiar y se los llevan en conjunto, asi que si ven un paquete que tenga estos dos productos, pudieran prefeir comprarlo aunque tenga mas cosas.

  • Regla 2, 5 y 7: Si compran Coca Zero o Fanta o Coca Cola Light como resultado terminan comprando una de esas bebidas y Coca Cola como segunda bebida. Estrategia. Promoción de llevate Coca-Cola en descuento si compras las siguientes cocas: Coca Zero, Fanta, Coca Cola Light.

  • Regla 3, 4 y 10: Si compran FUD o Hellmann’s o Blue House se llevan el pan Bimbo, lo que nos quiere decir que compran los ingredientes para realizar un sandiwch. Estrategia. Ofrecer el producto ya armado, es decir, vender sandwiches.

  • Regla 6: Si compran Reyma se llevan tambien productos Convermex. Estrategia. Armar un “Paquete Piñata”, podemos ver que estas dos marcas tienen productos de platos, vasos, utensilios de plástico y desechables por lo que armar este paquete atraería a la gente adulta que hace sus fiestas o reuniones, incluso puede ser “Paquete para Llevar” para los restaurantes que entregan comida.

  • Regla 8: Al comprar Pinol se llevan también el Cloralex. Estrategia. Al conocer que se llevan en conjunto estos dos productos de limpieza podemos poner en descuento el Pinol para que les atraiga y como sabemos que compran el otro producto, la idea sería recuperar el dinero en el Cloralex.

LS0tCnRpdGxlOiA8c3BhbiBzdHlsZT0iY29sb3I6R3JlZW4iPk1hcmtldCBCYXNrZXQgQW5hbHlzaXMgQWJhcnJvdGVzPC9zcGFuPiAKYXV0aG9yOiAiS2FybGEgR2VvcmdpbmEgTWFydMOtbmV6IEdvbnrDoWxleiBBMDA4Mjc1MDAiCmRhdGU6ICIyMDIyLTA5LTA4IgpvdXRwdXQ6IAogIGh0bWxfZG9jdW1lbnQ6CiAgICB0b2M6IHRydWUKICAgIHRvY19mbG9hdDogdHJ1ZQogICAgY29kZV9kb3dubG9hZDogdHJ1ZQotLS0KCjxpbWcgc3JjPSAiL1VzZXJzL2dlb3JnaW5hbWFydGluZXovRGVza3RvcC90aWVuZGEtYWJhcnJvdGVzLmpwZWciPgoKIyMgPHNwYW4gc3R5bGU9ImNvbG9yOmRhcmtibHVlIj4qKkdlbmVyYWRvciBkZSB2YWxvciBkZSBkYXRvcyoqPC9zcGFuPiAgICAKCiMjIyA8c3BhbiBzdHlsZT0iY29sb3I6Ymx1ZSI+UGFzbyAxLiBEZWZpbmlyIGVsIMOhcmVhIGRlbCBuZWdvY2lvIHF1ZSBidXNjYW1vcyBpbXBhY3Rhci8gbWVqb3JhciB5IHN1IEtQSS48L3NwYW4+ICAgICAKCiMjIyMgwr9RdcOpIG9iamV0aXZvcyBlc3BlcmFzIGFwb3lhcj8gwr9DdcOhbGVzIHNvbiB0dXMgS1BJJ3MgZXN0YWJsZWNpZG9zIHF1ZSBzZSB1dGlsaXphbiBwYXJhIG1lZGlyIGVsIHJlbmRpbWllbnRvPyAgCgojIyMjIyBFbiBlc3RlIGNhc28sIG51ZXN0cmEgYmFzZSBkZSBkYXRvcyBzZSB0cmF0YSBkZSBkaXN0aW50YXMgdGllbmRhcyBkZSBhYmFycm90ZXMgeSBsbyBxdWUgc2UgYnVzY2EgZXMgcmVhbGl6YXIgdW4gTWFya2V0IEJhc2tldCBBbmFseXNpcywgcXVlIG5vcyBheXVkYXLDoSBhIGNvbm9jZXIgcXVlIHByb2R1Y3RvcyB0aWVuZW4gcmVsYWNpw7NuIHkgc2UgdmVuZGVuIGVuIGNvbmp1bnRvIHBhcmEgY3JlYXIgZGVzcHXDqXMgZXN0cmF0ZWdpYXMsIHBvciBsbyB0YW50bywgZXN0byBzaWduaWZpY2EgcXVlIGVsIMOhcmVhIHF1ZSBlc3RhbW9zIGJ1c2NhbmRvIGltcGFjdGFyIHkgbWVqb3JhciBlcyBlbCAqKmRlcGFydGFtZW50byBkZSBNZXJjYWRvdGVjbmlhKiogeSBlbCAqKktQSSBzZXLDoSBWZW50YXMgcG9yIG1lcyoqLiAgCgojIyMgPHNwYW4gc3R5bGU9ImNvbG9yOmJsdWUiPlBhc28gMi4gU2VsZWNjaW9uYXIgcGxhbnRpbGxhKHMpIHBhcmEgY3JlYXIgdmFsb3IgYSBwYXJ0aXIgZGUgbG9zIGRhdG9zIGRlIGxvcyBjbGllbnRlcy48L3NwYW4+ICAgICAKCiMjIyMjIFBhcmEgY3JlYXIgdmFsb3IgZXMgbmVjZXNhcmlvIHNlbGVjY2lvbmFyIGxhcyBwbGFudGlsbGFzIGRlICoqU2VnbWVudGFjacOzbioqIHBhcmEgYWNvcnRhciBlbCBjYW1wbywgZXMgZGVjaXIgcmVkdWNpciBhIGNpZXJ0b3MgcMO6YmxpY29zIHF1ZSBzZSBjYXJhY3Rlcml6YW4gcG9yIGNvbXByYXIgdmFyaW9zIHByb2R1Y3RvcyBlbiBjb25qdW50bywgdW4gZWplbXBsbyBlcyBxdWllbiB2ZW1vcyBxdWUgY29tcHJhIGRpc3RpdG5vcyBwcm9kdWN0b3MgcGFyYSBiZWLDqXMsIGxvIHF1ZSBub3MgcXVpZXJlIGRlY2lyIHF1ZSBlc2UgZ3J1cG8gcG9kZW1vcyBzZWdtZW50YXJsb3MgYSBwYWRyZXMgZGUgZmFtaWxpYSwgZGUgY2llcnRvIHRpcG8gbml2ZWwgc29jaW9lY29uw7NtaWNvIGRlcGVuZGllbmRvIGVsIHRpcG8gZGUgcHJvZHVjdG8gcXVlIGNvbXByYS4gTGEgb3RyYSBwbGFudGlsbGEgYSB1dGlsaXphciBlcyAqKlBlcnNvbmFsaXphY2nDs24qKiBkb25kZSBhIHBhcnRpciBkZWwgTWFya2V0IEJhc2tldCBwb2RyZW1vcyBjcmVhciBtZW5zYWplcywgb2ZlcnRhcywganVnYXIgY29uIGxvcyBwcmVjaW9zIHkgcHJvZHVjdG9zIG8gc2VydmljaW9zIHF1ZSBzZWFuIG3DoXMgcmVsZXZhbnRlcyB5IG3DoXMgdmFsaW9zb3MuICAKCiMjIyA8c3BhbiBzdHlsZT0iY29sb3I6Ymx1ZSI+UGFzbyAzLiBHZW5lcmFyIGlkZWFzIG8gY29uY2VwdG9zIGVzcGVjw61maWNvcy48L3NwYW4+ICAgICAKIyMjIyBIaXDDs3Rlc2lzOiAKIyMjIyMgSGlww7N0ZXNpcyAxOiBFc3RyYXRlZ2lhcyBkZSBkZXNjdWVudG9zIGVuIGxvcyBwcm9kdWN0b3MuICAKIyMjIyMgSGlww7N0ZXNpcyAyOiBDcmVhciBwYXF1ZXRlcyBkZSBwcm9kdWN0b3MgY29uIHRlbcOhdGljYXMgcGFyYSBxdWUgc2UgbGxldmVuIGVuIGNvbmp1bnRvLiAgCiMjIyMjIEhpcMOzdGVzaXMgMzogR2VuZXJhciB1biBwcm9kdWN0by9zZXJ2aWNpbyBzaSBvYnNlcnZhbW9zIHF1ZSBqdW50b3MgcHVlZGUgc2VyIHVuYSB2ZW50YSBtw6FzIHBvdGVudGUuICAKIyMjIyMgSGlww7N0ZXNpcyA0OiBTZWdtZW50YXIgeSBwZXJzb25hbGl6YXIgZWwgY29uanVudG8gZGUgcHJvZHVjdG9zLiAgCgojIyMgPHNwYW4gc3R5bGU9ImNvbG9yOmJsdWUiPlBhc28gNC4gUmV1bmlyIGxvcyBkYXRvcyBlc3BlY8OtZmljb3MuPC9zcGFuPiAgICAgCiMjIyMgwr9RdcOpIGRhdG9zIHRlbmVtb3M/IMK/UXXDqSBkYXRvcyBuZWNlc2l0YW1vcz8gIAojIyMjIyBQcmV2aWFtbnRlIHNlIGxpbXBpbyBsYSBiYXNlIGRlIGRhdG9zIGVudHJlZ2FkYSBhbnRlcmlvcmltZW50ZSB5IHN1cyBhY3R1YWxlcyB2YXJpYWJsZXMgc29uOiB2Y0NsYXZlVGllbmRhLCBEZXNjR2lybywgRmVjaGEsIEhvcmEsIE1hcmNhLCBGYWJyaWNhbnRlLCBQcm9kdWN0bywgUHJlY2lvLCBVbHQuQ29zdG8sIFVuaWRhZGVzLCBGLlRpY2tldCwgTm9tYnJlRGVwYXJ0YW1lbnRvLCBOb21icmVGYW1pbGlhLCBOb21icmVDYXRlZ29yaWEsIEVzdGFkbywgTXRzLjIsIFRpcG8udWJpY2FjacOzbiwgR2lybywgSG9yYS5pbmljaW8sIEhvcmEuY2llcnJlLCBEaWFfZGVfbGFfc2VtYW5hLCBTdWJ0b3RhbCwgVXRpbGlkYWQuICAKCiMjIyA8c3BhbiBzdHlsZT0iY29sb3I6Ymx1ZSI+UGFzbyA1LiBQbGFuIGRlIGVqZWN1Y2nDs24uPC9zcGFuPiAgIAojIyMjIyBGYXNlIDEuIFBpbG90byBkZSBkZXNjdWVudG9zLCBwYXF1ZXRlcyB5IHByZWNpb3MgZW4gdGllbmRhcyBkZSBhYmFycm90ZXMgZGUgTnVldm8gTGXDs24gKDk1LDQxMCB1bmlkYWRlcykuICAKIyMjIyMgRmFzZSAyLiBEZW1hcyBlc3RhZG9zOiBDaGlhcGFzLCBKYWxpc2NvLCBRdWludGFuYSBSb28geSBTaW5hbG9hLiAgCgojIyA8c3BhbiBzdHlsZT0iY29sb3I6ZGFya2JsdWUiPioqSW1wb3J0YXIgYmFzZSBkZSBkYXRvcyoqPC9zcGFuPiAgCmBgYHtyfQpiZF9saW1waWEgPC0gcmVhZC5jc3YoIi9Vc2Vycy9nZW9yZ2luYW1hcnRpbmV6L0RvY3VtZW50cy9UZWMvU2XMgXB0aW1vIFNlbWVzdHJlL0FuYWxpzIF0aWNhIHBhcmEgbmVnb2Npb3MsIGRlIGxvcyBkYXRvcyBhIGRlY2lzaW9uZXMvYWJhcnJvdGVzX2JkX2xpbXBpYS5jc3YiKQpgYGAKCiMjIDxzcGFuIHN0eWxlPSJjb2xvcjpkYXJrYmx1ZSI+KipQYXF1ZXRlcyB5IGxpYnJlcsOtYXMgcmVxdWVyaWRhcyoqPC9zcGFuPiAgCmBgYHtyfQojIGluc3RhbGwucGFja2FnZXMoInBseXIiKQpsaWJyYXJ5KE1hdHJpeCkKIyBpbnN0YWxsLnBhY2thZ2VzKCJhcnVsZXMiKQpsaWJyYXJ5KGFydWxlcykKIyBpbnN0YWxsLnBhY2thZ2VzKCJhcnVsZXNWaXoiKSAgCmxpYnJhcnkoYXJ1bGVzVml6KQpsaWJyYXJ5KGRhdGFzZXRzKQpgYGAKCiMjIDxzcGFuIHN0eWxlPSJjb2xvcjpkYXJrYmx1ZSI+KipPcmRlbmFyIGRlIG1lbm9yIGEgbWF5b3IgbG9zIFRpY2tldHMqKjwvc3Bhbj4gIApgYGB7cn0KYmRfbGltcGlhIDwtIGJkX2xpbXBpYVtvcmRlcihiZF9saW1waWEkRi5UaWNrZXQpLF0KaGVhZChiZF9saW1waWEpCnRhaWwoYmRfbGltcGlhKQpgYGAKCiMjIDxzcGFuIHN0eWxlPSJjb2xvcjpkYXJrYmx1ZSI+KipHZW5lcmFyIGJhc2tldCoqPC9zcGFuPiAgCmBgYHtyfQojIGluc3RhbGwucGFja2FnZXMoInBseXIiKQpsaWJyYXJ5KHBseXIpCmJhc2tldCA8LSBkZHBseShiZF9saW1waWEsYygiRi5UaWNrZXQiKSwgZnVuY3Rpb24oYmRfbGltcGlhKXBhc3RlKGJkX2xpbXBpYSRNYXJjYSwgY29sbGFwc2UgPSAiLCIpKQpgYGAKCiMjIyMgPHNwYW4gc3R5bGU9ImNvbG9yOmRhcmtibHVlIj4qKkVsaW1pbmFyIE7Dum1lcm8gZGUgVGlja2V0Kio8L3NwYW4+ICAKYGBge3J9CmJhc2tldCRGLlRpY2tldCA8LSBOVUxMCmBgYAoKIyMjIyA8c3BhbiBzdHlsZT0iY29sb3I6ZGFya2JsdWUiPioqUmVub21icmFtb3MgZWwgbm9tYnJlIGRlIGxhIGNvbHVtbmEqKjwvc3Bhbj4gIApgYGB7cn0KY29sbmFtZXMoYmFza2V0KSA8LSBjKCJNYXJjYSIpCmBgYAoKIyMgPHNwYW4gc3R5bGU9ImNvbG9yOmRhcmtibHVlIj4qKkV4cG9ydGFyIGJhc2tldCoqPC9zcGFuPiAgCmBgYHtyfQp3cml0ZS5jc3YoYmFza2V0LCJiYXNrZXRfYWJhcnJvdGVzLmNzdiIsIHF1b3RlID0gRkFMU0UsIHJvdy5uYW1lcyA9IEZBTFNFKQpgYGAKCiMjIDxzcGFuIHN0eWxlPSJjb2xvcjpkYXJrYmx1ZSI+KipJbXBvcnRhciB0cmFuc2FjY2lvbmVzKio8L3NwYW4+ICAKYGBge3IgbWVzc2FnZT1UUlVFLCB3YXJuaW5nPUZBTFNFfQp0ciA8LSByZWFkLnRyYW5zYWN0aW9ucygiL1VzZXJzL2dlb3JnaW5hbWFydGluZXovYmFza2V0X2FiYXJyb3Rlcy5jc3YiLCBmb3JtYXQgPSAiYmFza2V0IiAsIHNlcD0gIiwiKQoKcmVnbGFzLmFzb2NpYWNpb24gPC0gYXByaW9yaSh0ciwgcGFyYW1ldGVyID0gbGlzdChzdXBwPSAwLjAwMSwgY29uZj0wLjIsIG1heGxlbj0xMCkpCiMgc3VtbWFyeShyZWdsYXMuYXNvY2lhY2lvbikKIyBpbnNwZWN0KHJlZ2xhcy5hc29jaWFjaW9uKQoKcmVnbGFzLmFzb2NpYWNpb24gPC0gc29ydChyZWdsYXMuYXNvY2lhY2lvbiwgYnkgPSAiY29uZmlkZW5jZSIsIGRlY3JlYXNpbmcgPSBUUlVFKQojIHN1bW1hcnkocmVnbGFzLmFzb2NpYWNpb24pCiMgaW5zcGVjdChyZWdsYXMuYXNvY2lhY2lvbikKCnRvcDEwcmVnbGFzIDwtIGhlYWQocmVnbGFzLmFzb2NpYWNpb24sIG4gPSAxMCwgYnkgPSAiY29uZmlkZW5jZSIpCmBgYAoKIyMgPHNwYW4gc3R5bGU9ImNvbG9yOmRhcmtibHVlIj4qKkdyw6FmaWNhIFRvcCAxMCByZWdsYXMqKjwvc3Bhbj4gIApgYGB7cn0KcGxvdCh0b3AxMHJlZ2xhcywgbWV0aG9kID0gImdyYXBoIiwgZW5naW5lID0gImh0bWx3aWRnZXQiKSAgICAKYGBgCgojIyA8c3BhbiBzdHlsZT0iY29sb3I6ZGFya2JsdWUiPioqQ29uY2x1c2lvbmVzKio8L3NwYW4+ICAgIAojIyMjIEVsIE1hcmtldCBCYXNrZXQgQW5hbHlzaXMgbm9zIHNpcnZlIHBhcmEgY29ub2NlciBwYXRyb25lcyBzb2JyZSBxdWUgcHJvZHVjdG9zIHNlIGxsZXZhbiBlbiBjb25qdW50byBvIHNpIGNvbXByYW4gdW5vIHF1ZSBvdHJvcyBjb21wcmFuIHkgbcOhcyBhIHRyYXbDqXMgZGUgdW4gY29uanVudG8gZGUgZGF0b3MsIGxvIHV0aWxpemFuIG11Y2hhcyBlbXByZXNhcyBwb3JxdWUgbGVzIHBlcm1pdGUgY3JlYXIgZXN0cmF0ZWdpYXMgcGFyYSBhdW1lbnRhciBzdXMgdmVudGFzIGUgaW5jbHVzbyBvZnJlY2VyIHVuYSBleHBlcmllbmNpYSBwZXJzb25hbGl6YWRhIGEgbG9zIGNsaWVudGVzLiAgCgojIyMjIFBhcmEgZXN0byB0dXZpbW9zIHF1ZSByZWFsaXphciB1bmEgbGltcGllemEgZGUgZGF0b3MgYSBsYSBiYXNlIGRlIGRhdG9zIGJyaW5kYWRhIHkgZGVzcHXDqXMgY29ub2NlciBsYXMgcmVnbGFzIHF1ZSBub3MgZGlyYW4gcXVlIHByb2R1Y3RvcyB0aWVuZW4gcmVsYWNpw7NuIGVuIGxhcyB0aWVuZGFzIGRlIGFiYXJyb3Rlcy4KCiMjIyMgTGEgZ3LDoWZpY2EgbXVlc3RyYSBsYXMgdG9wIDEwIHJlZ2xhcyBxdWUgc2UgZW5jb250cmFyb24gZGVudHJvIGRlIGxhIGJhc2UgZGUgZGF0b3Mgc29icmUgbGFzIHRpZW5kYXMgZGUgQWJhcnJvdGVzIHkgYSBjb250aW51YWNpw7NuIHNlIGludGVwcmV0YXJhbiBsb3MgcmVzdWx0YWRvczogIAoKKiAqKlJlZ2xhIDEgeSA5OioqIFNpIHNlIGxsZXZhbiBlbCBTYWx2byB0YW1iacOpbiBjb21wcmFuIGp1bnRvIGVsIEZhYnVsb3NvIHkgdmljZXZlcnNhIHNpIGNvbXByYW4gZWwgRmFidWxvc28gc2UgbGxldmFuIHRhbWJpw6luIGVsIFNhbHZvLiA8c3BhbiBzdHlsZT0iY29sb3I6cmVkIj4qKkVzdHJhdGVnaWEuKio8L3NwYW4+IEFybWFyIHVuIHBhcXVldGUgZGUgbGltcGllemEgaW5jbHVleWRubyBlbCBGYWJ1bG9zbyB5IFNhbHZvIGNvbXBsZW1lbnRhbmRvIGNvbiBvdHJvcyBwcm9kdWN0b3MgeWEgcXVlIGVzdGFtb3MgdmllbmRvIGVzdGEgcmVsYWNpw7NuIGRlIHF1ZSBsb3MgZG9zIHNvbiBwYXJhIGxpbXBpYXIgeSBzZSBsb3MgbGxldmFuIGVuIGNvbmp1bnRvLCBhc2kgcXVlIHNpIHZlbiB1biBwYXF1ZXRlIHF1ZSB0ZW5nYSBlc3RvcyBkb3MgcHJvZHVjdG9zLCBwdWRpZXJhbiBwcmVmZWlyIGNvbXByYXJsbyBhdW5xdWUgdGVuZ2EgbWFzIGNvc2FzLgoKKiAqKlJlZ2xhIDIsIDUgeSA3OioqIFNpIGNvbXByYW4gQ29jYSBaZXJvIG8gRmFudGEgbyBDb2NhIENvbGEgTGlnaHQgY29tbyByZXN1bHRhZG8gdGVybWluYW4gY29tcHJhbmRvIHVuYSBkZSBlc2FzIGJlYmlkYXMgeSBDb2NhIENvbGEgY29tbyBzZWd1bmRhIGJlYmlkYS4gIDxzcGFuIHN0eWxlPSJjb2xvcjpyZWQiPioqRXN0cmF0ZWdpYS4qKjwvc3Bhbj4gUHJvbW9jacOzbiBkZSBsbGV2YXRlIENvY2EtQ29sYSBlbiBkZXNjdWVudG8gc2kgY29tcHJhcyBsYXMgc2lndWllbnRlcyBjb2NhczogQ29jYSBaZXJvLCBGYW50YSwgQ29jYSBDb2xhIExpZ2h0LgoKKiAqKlJlZ2xhIDMsIDQgeSAxMDoqKiBTaSBjb21wcmFuIEZVRCBvIEhlbGxtYW5uJ3MgbyBCbHVlIEhvdXNlIHNlIGxsZXZhbiBlbCBwYW4gQmltYm8sIGxvIHF1ZSBub3MgcXVpZXJlIGRlY2lyIHF1ZSBjb21wcmFuIGxvcyBpbmdyZWRpZW50ZXMgcGFyYSByZWFsaXphciB1biBzYW5kaXdjaC4gPHNwYW4gc3R5bGU9ImNvbG9yOnJlZCI+KipFc3RyYXRlZ2lhLioqPC9zcGFuPiBPZnJlY2VyIGVsIHByb2R1Y3RvIHlhIGFybWFkbywgZXMgZGVjaXIsIHZlbmRlciBzYW5kd2ljaGVzLgoKKiAqKlJlZ2xhIDY6KiogU2kgY29tcHJhbiBSZXltYSBzZSBsbGV2YW4gdGFtYmllbiBwcm9kdWN0b3MgQ29udmVybWV4LiA8c3BhbiBzdHlsZT0iY29sb3I6cmVkIj4qKkVzdHJhdGVnaWEuKio8L3NwYW4+IEFybWFyIHVuICJQYXF1ZXRlIFBpw7FhdGEiLCBwb2RlbW9zIHZlciBxdWUgZXN0YXMgZG9zIG1hcmNhcyB0aWVuZW4gcHJvZHVjdG9zIGRlIHBsYXRvcywgdmFzb3MsIHV0ZW5zaWxpb3MgZGUgcGzDoXN0aWNvIHkgZGVzZWNoYWJsZXMgcG9yIGxvIHF1ZSBhcm1hciBlc3RlIHBhcXVldGUgYXRyYWVyw61hIGEgbGEgZ2VudGUgYWR1bHRhIHF1ZSBoYWNlIHN1cyBmaWVzdGFzIG8gcmV1bmlvbmVzLCBpbmNsdXNvIHB1ZWRlIHNlciAiUGFxdWV0ZSBwYXJhIExsZXZhciIgcGFyYSBsb3MgcmVzdGF1cmFudGVzIHF1ZSBlbnRyZWdhbiBjb21pZGEuCgoqICoqUmVnbGEgODoqKiBBbCBjb21wcmFyIFBpbm9sIHNlIGxsZXZhbiB0YW1iacOpbiBlbCBDbG9yYWxleC4gPHNwYW4gc3R5bGU9ImNvbG9yOnJlZCI+KipFc3RyYXRlZ2lhLioqPC9zcGFuPiBBbCBjb25vY2VyIHF1ZSBzZSBsbGV2YW4gZW4gY29uanVudG8gZXN0b3MgZG9zIHByb2R1Y3RvcyBkZSBsaW1waWV6YSBwb2RlbW9zIHBvbmVyIGVuIGRlc2N1ZW50byBlbCBQaW5vbCBwYXJhIHF1ZSBsZXMgYXRyYWlnYSB5IGNvbW8gc2FiZW1vcyBxdWUgY29tcHJhbiBlbCBvdHJvIHByb2R1Y3RvLCBsYSBpZGVhIHNlcsOtYSByZWN1cGVyYXIgZWwgZGluZXJvIGVuIGVsIENsb3JhbGV4LiAK