
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