Importar base de datos

#file.choose()
bd12 <- read.csv("C:\\Users\\danyc\\OneDrive - Instituto Tecnologico y de Estudios Superiores de Monterrey\\Desktop\\Excel y CSV\\Maestrodatos_clientes.csv")
summary(bd12)
##    CustomerID        Total             Visitas       
##  Min.   :12346   Min.   :    3.45   Min.   :  1.000  
##  1st Qu.:13832   1st Qu.:  178.30   1st Qu.:  1.000  
##  Median :15322   Median :  292.00   Median :  2.000  
##  Mean   :15316   Mean   :  415.62   Mean   :  4.227  
##  3rd Qu.:16790   3rd Qu.:  426.63   3rd Qu.:  5.000  
##  Max.   :18287   Max.   :84236.25   Max.   :209.000

Herramienta “El Generador de Valor de Datos”

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

El área serían directamente las ventas de nuestros productos pero con relación a los clientes.

Los KPI´s a impactar son:

a. Compras del cliente (Ventas) b. Retención del cliente

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

Visión / Segmentación / Personalización / Contextualización

Paso 3. Generar ideas o conceptos específicos.
Creación de estrategía para mantener a los clientes y generar un incremento en sus compras.

Paso 4. Reunir los datos requeridos. Se necesita una base de datos limpia de tickets de ventas a clientes con numeros de clientes.

Paso 5. Plan de ejecución. a. Recabar los datos, selecciónar los últimos años para recabar esta informacion para trabajarla. b.Limpiar la base de datos. c.Hacer una segmentación en clusters de los clientes. d. Definir las ubicaciones con más retorno de clientes. e. Generar estratégias para seguir reteniendo clientes y premiar la lealtad.

Limpiar base de datos

Agregar el CustomerID como nombre de los renglones

bd13<-bd12
rownames(bd13)<- bd13$CustomerID

Eliminar la columna de customer ID

bd14<-bd13
bd14<- subset(bd14, select = -c (CustomerID))

Revisar presencia de datos anormales

summary(bd14)
##      Total             Visitas       
##  Min.   :    3.45   Min.   :  1.000  
##  1st Qu.:  178.30   1st Qu.:  1.000  
##  Median :  292.00   Median :  2.000  
##  Mean   :  415.62   Mean   :  4.227  
##  3rd Qu.:  426.63   3rd Qu.:  5.000  
##  Max.   :84236.25   Max.   :209.000
plot(bd14$Total, bd14$visitas)

#Los datos fuera de lo normal estan fuera de los siguientes límites:
   #Límite inferior = Q1 - 1.5*IQR
   #Límite superior = Q3 + 1.5*IQR
#Q1: Cuartil 1, Q3: Cuartil 3, IQR: Rango Intercuartil =Q3-Q1

Calcular el límite superior del total

iqr_total<-IQR(bd14$Total)
limite_superior_total<- 426.63+ 1.5*iqr_total
limite_superior_total
## [1] 799.1277

Conservar solo los tickets promedios menores a 800

bd15 <-bd14
bd15 <- bd15[bd15$Total<800, ]
summary(bd15)
##      Total           Visitas       
##  Min.   :  3.45   Min.   :  1.000  
##  1st Qu.:172.96   1st Qu.:  1.000  
##  Median :272.23   Median :  2.000  
##  Mean   :298.21   Mean   :  4.125  
##  3rd Qu.:390.24   3rd Qu.:  5.000  
##  Max.   :799.62   Max.   :209.000

Calcular el límite superior de las visitas

iqr_Visitas<-IQR(bd14$Visitas)
limite_superior_visitas<- 5+ 1.5*iqr_Visitas
limite_superior_visitas
## [1] 11

Conservar sólo las visitas menores a 12

bd16<-bd15
bd16<-bd16[bd16$Visitas < 12, ]

summary(bd16)
##      Total           Visitas      
##  Min.   :  3.45   Min.   : 1.000  
##  1st Qu.:168.67   1st Qu.: 1.000  
##  Median :267.13   Median : 2.000  
##  Mean   :293.99   Mean   : 2.971  
##  3rd Qu.:384.80   3rd Qu.: 4.000  
##  Max.   :799.62   Max.   :11.000
plot(bd16$Total, bd16$Visitas)

K-means clustering

Paso 1. Normalizar Variables

bd17<-bd16
bd17<-as.data.frame(scale(bd17))

plot(bd17$Total, bd17$Visitas)

Paso 2. k-means Clustering

#segmentos <- kmeans(bd17, 3)
#segmentos

asignacion <- cbind(bd16, cluster = segmentos$cluster)
head(asignacion, 10)
##          Total Visitas cluster
## 12347 615.7143       7       2
## 12350 334.4000       1       1
## 12352 313.2550       8       2
## 12353  89.0000       1       1
## 12355 459.4000       1       3
## 12358 584.0300       2       3
## 12361 189.9000       1       1
## 12362 522.6230      10       2
## 12363 276.0000       2       1
## 12364 328.2750       4       1

Exportar csv

#write.csv(asignacion,"clientes_segmentados.csv")

Visualizar Segmentos

#install.packages("factoextra")
library(factoextra)
## Loading required package: ggplot2
## Welcome! Want to learn more? See two factoextra-related books at https://goo.gl/ve3WBa
fviz_cluster(segmentos, data = bd17,
             palette=c("red","blue", "black", "dark green"),
             ellipse.type= "euclid",
             star.plot = T ,
             repel = T,
             ggtheme = theme())
## Warning: ggrepel: 3734 unlabeled data points (too many overlaps). Consider
## increasing max.overlaps

#install.packages("Cluster")

library(data.table)
library(cluster)
library(factoextra)

Optimizar k

set.seed(123)
optimizacion <- clusGap(bd17, FUN = kmeans, nstart = 25, K.max= 10, B = 50)
## Warning: did not converge in 10 iterations

## Warning: did not converge in 10 iterations

## Warning: did not converge in 10 iterations

## Warning: did not converge in 10 iterations

## Warning: did not converge in 10 iterations

## Warning: did not converge in 10 iterations

## Warning: did not converge in 10 iterations

## Warning: did not converge in 10 iterations

## Warning: did not converge in 10 iterations

## Warning: did not converge in 10 iterations

## Warning: did not converge in 10 iterations

## Warning: did not converge in 10 iterations
plot(optimizacion, xlab = "Numero de Clusters k")

Conclusión y Aprendizaje

Dentro de los clusters para el supermercado pudimos visualizar la manera en la que los clientes del cluster superior en color rojo son los más leales y con unas compras superiores a los demás pero debido a que la visualización del primer cluster era muy incierta por el amontonamiento de los datos, se hizo la segunda optimización de K-means la cual también reduce el error de los clusters en un 6-15% al decirnos cuál es el grupo de clusters mas óptimo para nuestro análisis, esto se complementaría con la herramienta de manera en que segmentando a los clientes por individual se les pueden dar distintos tipos de bonificaciónes o complementos adicionales para retenerlos de la competencia.

Ya visualizando los datos, esta herramienta la podríamos utilizar generalmente en el area de mercadotecnia y ventas ya que va muy relacionada con la generación de insights para distintos clusters en el mercado y al mismo tiempo la generación de estrategias. De igual manera se puede integrar esta información con un CRM para personalizar las promociones que se les dan a sus segmentos de clientes y aumentar las ventas en el area de interés del cliente, asi como lo hace Costco o Rappi al estudiar el comportamiento del consumidor con sus datos y dando ofertas que probablemente pudieran aceptar.

LS0tDQp0aXRsZTogPHNwYW4gc3R5bGU9IkNvbG9yOiNFOEJDMDAiPiAiQ2x1c3RlcnMgU3VwZXJtZXJjYWRvcyI8L3NwYW4+DQphdXRob3I6ICJEYW5pZWxhIEPDoXJkZW5hcyBaIC8vIEEwMTcyMDUzNSINCmRhdGU6ICIyMDIyLTA5LTIwIg0Kb3V0cHV0OiANCiAgICAgIGh0bWxfZG9jdW1lbnQ6DQogICAgICAgIHRvYzogdHJ1ZQ0KICAgICAgICB0b2NfZmxvYXQ6IHRydWUNCiAgICAgICAgY29kZV9mb2xkaW5nOiAiaGlkZSINCiAgICAgICAgY29kZV9kb3dubG9hZDogdHJ1ZQ0KLS0tDQoqKioNCg0KIyA8aW1nIHNyYz0gIkM6XFxVc2Vyc1xcZGFueWNcXERvd25sb2Fkc1xcbWFya2V0LmpwZyIgLz4NCg0KIyA8c3BhbiBzdHlsZT0iQ29sb3I6cmVkIj5JbXBvcnRhciBiYXNlIGRlIGRhdG9zIDwvc3Bhbj4NCmBgYHtyfQ0KI2ZpbGUuY2hvb3NlKCkNCmJkMTIgPC0gcmVhZC5jc3YoIkM6XFxVc2Vyc1xcZGFueWNcXE9uZURyaXZlIC0gSW5zdGl0dXRvIFRlY25vbG9naWNvIHkgZGUgRXN0dWRpb3MgU3VwZXJpb3JlcyBkZSBNb250ZXJyZXlcXERlc2t0b3BcXEV4Y2VsIHkgQ1NWXFxNYWVzdHJvZGF0b3NfY2xpZW50ZXMuY3N2IikNCnN1bW1hcnkoYmQxMikNCmBgYA0KDQojIDxzcGFuIHN0eWxlPSJDb2xvcjpyZWQiPiBIZXJyYW1pZW50YSDigJxFbCBHZW5lcmFkb3IgZGUgVmFsb3IgZGUgRGF0b3PigJ0gPC9zcGFuPg0KPHN0eWxlPg0KZGl2LmJsdWUgeyBiYWNrZ3JvdW5kLWNvbG9yOiM1ODk4MWY7IGJvcmRlci1yYWRpdXM6IDVweDsgcGFkZGluZzogMjBweDt9DQo8L3N0eWxlPg0KPGRpdiBjbGFzcyA9ICJibHVlIj4NCg0KKlBhc28gMS4qIERlZmluaXIgZWwgw6FyZWEgZGVsIG5lZ29jaW8gcXVlIGJ1c2NhbW9zIGltcGFjdGFyIG8gbWVqb3JhciB5IHN1IEtQSSANCg0KRWwgw6FyZWEgc2Vyw61hbiBkaXJlY3RhbWVudGUgbGFzIHZlbnRhcyBkZSBudWVzdHJvcyBwcm9kdWN0b3MgcGVybyBjb24gcmVsYWNpw7NuIGEgbG9zIGNsaWVudGVzLiAgDQoNCkxvcyBLUEnCtHMgYSBpbXBhY3RhciBzb246ICANCg0KKiphLiBDb21wcmFzIGRlbCBjbGllbnRlIChWZW50YXMpIA0KYi4gUmV0ZW5jacOzbiBkZWwgY2xpZW50ZSoqDQoNCipQYXNvIDIuKiBTZWxlY2Npb25hciBwbGFudGlsbGEoLXMpIHBhcmEgY3JlYXIgdmFsb3IgYSBwYXJ0aXIgZGUgbG9zIGRhdG9zIGRlIGxvcyBjbGllbnRlcy4gICAgIA0KDQpWaXNpw7NuIC8gKipTZWdtZW50YWNpw7NuKiogLyBQZXJzb25hbGl6YWNpw7NuIC8gQ29udGV4dHVhbGl6YWNpw7NuICAgICAgIA0KDQoqUGFzbyAzLiogR2VuZXJhciBpZGVhcyBvIGNvbmNlcHRvcyBlc3BlY8OtZmljb3MuICAgDQpDcmVhY2nDs24gZGUgZXN0cmF0ZWfDrWEgcGFyYSBtYW50ZW5lciBhIGxvcyBjbGllbnRlcyB5IGdlbmVyYXIgdW4gaW5jcmVtZW50byBlbiBzdXMgY29tcHJhcy4gDQoNCipQYXNvIDQuKiBSZXVuaXIgbG9zIGRhdG9zIHJlcXVlcmlkb3MuIA0KU2UgbmVjZXNpdGEgdW5hIGJhc2UgZGUgZGF0b3MgbGltcGlhIGRlIHRpY2tldHMgZGUgdmVudGFzIGEgY2xpZW50ZXMgY29uIG51bWVyb3MgZGUgY2xpZW50ZXMuDQoNCipQYXNvIDUuKiBQbGFuIGRlIGVqZWN1Y2nDs24uIA0KYS4gUmVjYWJhciBsb3MgZGF0b3MsIHNlbGVjY2nDs25hciBsb3Mgw7psdGltb3MgYcOxb3MgcGFyYSByZWNhYmFyIGVzdGEgaW5mb3JtYWNpb24gcGFyYSB0cmFiYWphcmxhLiANCmIuTGltcGlhciBsYSBiYXNlIGRlIGRhdG9zLiANCmMuSGFjZXIgdW5hIHNlZ21lbnRhY2nDs24gZW4gY2x1c3RlcnMgZGUgbG9zIGNsaWVudGVzLiANCmQuIERlZmluaXIgbGFzIHViaWNhY2lvbmVzIGNvbiBtw6FzIHJldG9ybm8gZGUgY2xpZW50ZXMuIA0KZS4gR2VuZXJhciBlc3RyYXTDqWdpYXMgcGFyYSBzZWd1aXIgcmV0ZW5pZW5kbyBjbGllbnRlcyB5IHByZW1pYXIgbGEgbGVhbHRhZC4gDQo8L2Rpdj4gDQoNCiMgPHNwYW4gc3R5bGU9IkNvbG9yOnJlZCI+TGltcGlhciBiYXNlIGRlIGRhdG9zPC9zcGFuPg0KDQojIyA8c3BhbiBzdHlsZT0iQ29sb3I6b3JhbmdlIj5BZ3JlZ2FyIGVsIEN1c3RvbWVySUQgY29tbyBub21icmUgZGUgbG9zIHJlbmdsb25lcyA8L3NwYW4+IA0KYGBge3J9DQpiZDEzPC1iZDEyDQpyb3duYW1lcyhiZDEzKTwtIGJkMTMkQ3VzdG9tZXJJRA0KDQpgYGANCg0KIyMgPHNwYW4gc3R5bGU9IkNvbG9yOm9yYW5nZSI+RWxpbWluYXIgbGEgY29sdW1uYSBkZSBjdXN0b21lciBJRCA8L3NwYW4+IA0KYGBge3J9DQpiZDE0PC1iZDEzDQpiZDE0PC0gc3Vic2V0KGJkMTQsIHNlbGVjdCA9IC1jIChDdXN0b21lcklEKSkNCg0KYGBgDQoNCiMjIDxzcGFuIHN0eWxlPSJDb2xvcjpvcmFuZ2UiPiBSZXZpc2FyIHByZXNlbmNpYSBkZSBkYXRvcyBhbm9ybWFsZXMgPC9zcGFuPiANCmBgYHtyfQ0Kc3VtbWFyeShiZDE0KQ0KcGxvdChiZDE0JFRvdGFsLCBiZDE0JHZpc2l0YXMpDQoNCiNMb3MgZGF0b3MgZnVlcmEgZGUgbG8gbm9ybWFsIGVzdGFuIGZ1ZXJhIGRlIGxvcyBzaWd1aWVudGVzIGzDrW1pdGVzOg0KICAgI0zDrW1pdGUgaW5mZXJpb3IgPSBRMSAtIDEuNSpJUVINCiAgICNMw61taXRlIHN1cGVyaW9yID0gUTMgKyAxLjUqSVFSDQojUTE6IEN1YXJ0aWwgMSwgUTM6IEN1YXJ0aWwgMywgSVFSOiBSYW5nbyBJbnRlcmN1YXJ0aWwgPVEzLVExDQpgYGANCg0KDQoNCiMjIDxzcGFuIHN0eWxlPSJDb2xvcjpvcmFuZ2UiPkNhbGN1bGFyIGVsIGzDrW1pdGUgc3VwZXJpb3IgZGVsIHRvdGFsIDwvc3Bhbj4gDQpgYGB7cn0NCmlxcl90b3RhbDwtSVFSKGJkMTQkVG90YWwpDQpsaW1pdGVfc3VwZXJpb3JfdG90YWw8LSA0MjYuNjMrIDEuNSppcXJfdG90YWwNCmxpbWl0ZV9zdXBlcmlvcl90b3RhbA0KYGBgDQoNCg0KIyMgPHNwYW4gc3R5bGU9IkNvbG9yOm9yYW5nZSI+Q29uc2VydmFyIHNvbG8gbG9zIHRpY2tldHMgcHJvbWVkaW9zIG1lbm9yZXMgYSA4MDA8L3NwYW4+IA0KYGBge3J9DQpiZDE1IDwtYmQxNA0KYmQxNSA8LSBiZDE1W2JkMTUkVG90YWw8ODAwLCBdDQpzdW1tYXJ5KGJkMTUpDQpgYGANCg0KDQojIyA8c3BhbiBzdHlsZT0iQ29sb3I6b3JhbmdlIj5DYWxjdWxhciBlbCBsw61taXRlIHN1cGVyaW9yIGRlIGxhcyB2aXNpdGFzPC9zcGFuPiANCmBgYHtyfQ0KaXFyX1Zpc2l0YXM8LUlRUihiZDE0JFZpc2l0YXMpDQpsaW1pdGVfc3VwZXJpb3JfdmlzaXRhczwtIDUrIDEuNSppcXJfVmlzaXRhcw0KbGltaXRlX3N1cGVyaW9yX3Zpc2l0YXMNCmBgYA0KDQoNCiMjIDxzcGFuIHN0eWxlPSJDb2xvcjpvcmFuZ2UiPkNvbnNlcnZhciBzw7NsbyBsYXMgdmlzaXRhcyBtZW5vcmVzIGEgMTI8L3NwYW4+IA0KYGBge3J9DQpiZDE2PC1iZDE1DQpiZDE2PC1iZDE2W2JkMTYkVmlzaXRhcyA8IDEyLCBdDQoNCnN1bW1hcnkoYmQxNikNCnBsb3QoYmQxNiRUb3RhbCwgYmQxNiRWaXNpdGFzKQ0KYGBgDQoNCg0KDQojIDxzcGFuIHN0eWxlPSJDb2xvcjpyZWQiPkstbWVhbnMgY2x1c3RlcmluZzwvc3Bhbj4NCg0KIyMgPHNwYW4gc3R5bGU9IkNvbG9yOm9yYW5nZSI+UGFzbyAxLiBOb3JtYWxpemFyIFZhcmlhYmxlczwvc3Bhbj4gDQpgYGB7cn0NCmJkMTc8LWJkMTYNCmJkMTc8LWFzLmRhdGEuZnJhbWUoc2NhbGUoYmQxNykpDQoNCnBsb3QoYmQxNyRUb3RhbCwgYmQxNyRWaXNpdGFzKQ0KDQpgYGANCg0KIyMgPHNwYW4gc3R5bGU9IkNvbG9yOm9yYW5nZSI+UGFzbyAyLiBrLW1lYW5zIENsdXN0ZXJpbmc8L3NwYW4+IA0KYGBge3IsIGluY2x1ZGU9RkFMU0V9DQpzZWdtZW50b3MgPC0ga21lYW5zKGJkMTcsIDMpDQpzZWdtZW50b3MNCmBgYA0KDQpgYGB7cn0NCiNzZWdtZW50b3MgPC0ga21lYW5zKGJkMTcsIDMpDQojc2VnbWVudG9zDQoNCmFzaWduYWNpb24gPC0gY2JpbmQoYmQxNiwgY2x1c3RlciA9IHNlZ21lbnRvcyRjbHVzdGVyKQ0KaGVhZChhc2lnbmFjaW9uLCAxMCkNCmBgYA0KDQoNCiMjIDxzcGFuIHN0eWxlPSJDb2xvcjpvcmFuZ2UiPiBFeHBvcnRhciBjc3Y8L3NwYW4+IA0KYGBge3J9DQojd3JpdGUuY3N2KGFzaWduYWNpb24sImNsaWVudGVzX3NlZ21lbnRhZG9zLmNzdiIpDQpgYGANCg0KDQojIyA8c3BhbiBzdHlsZT0iQ29sb3I6b3JhbmdlIj5WaXN1YWxpemFyIFNlZ21lbnRvcyA8L3NwYW4+IA0KDQpgYGB7cn0NCiNpbnN0YWxsLnBhY2thZ2VzKCJmYWN0b2V4dHJhIikNCmxpYnJhcnkoZmFjdG9leHRyYSkNCmZ2aXpfY2x1c3RlcihzZWdtZW50b3MsIGRhdGEgPSBiZDE3LA0KICAgICAgICAgICAgIHBhbGV0dGU9YygicmVkIiwiYmx1ZSIsICJibGFjayIsICJkYXJrIGdyZWVuIiksDQogICAgICAgICAgICAgZWxsaXBzZS50eXBlPSAiZXVjbGlkIiwNCiAgICAgICAgICAgICBzdGFyLnBsb3QgPSBUICwNCiAgICAgICAgICAgICByZXBlbCA9IFQsDQogICAgICAgICAgICAgZ2d0aGVtZSA9IHRoZW1lKCkpDQoNCiNpbnN0YWxsLnBhY2thZ2VzKCJDbHVzdGVyIikNCg0KbGlicmFyeShkYXRhLnRhYmxlKQ0KbGlicmFyeShjbHVzdGVyKQ0KbGlicmFyeShmYWN0b2V4dHJhKQ0KYGBgDQoNCg0KIyMgPHNwYW4gc3R5bGU9IkNvbG9yOm9yYW5nZSI+T3B0aW1pemFyIGs8L3NwYW4+ICANCmBgYHtyfQ0Kc2V0LnNlZWQoMTIzKQ0Kb3B0aW1pemFjaW9uIDwtIGNsdXNHYXAoYmQxNywgRlVOID0ga21lYW5zLCBuc3RhcnQgPSAyNSwgSy5tYXg9IDEwLCBCID0gNTApDQpwbG90KG9wdGltaXphY2lvbiwgeGxhYiA9ICJOdW1lcm8gZGUgQ2x1c3RlcnMgayIpDQpgYGANCg0KDQojIDxzcGFuIHN0eWxlPSJDb2xvcjojRThCQzAwIj4gQ29uY2x1c2nDs24geSBBcHJlbmRpemFqZSA8L3NwYW4+DQoNCjxzdHlsZT4NCmRpdi5ibHVlIHsgYmFja2dyb3VuZC1jb2xvcjpiZWlnZTsgYm9yZGVyLXJhZGl1czogNXB4OyBwYWRkaW5nOiAyMHB4O30NCjwvc3R5bGU+DQo8ZGl2IGNsYXNzID0gImJsdWUiPg0KDQpEZW50cm8gZGUgbG9zIGNsdXN0ZXJzIHBhcmEgZWwgc3VwZXJtZXJjYWRvIHB1ZGltb3MgdmlzdWFsaXphciBsYSBtYW5lcmEgZW4gbGEgcXVlIGxvcyBjbGllbnRlcyBkZWwgY2x1c3RlciBzdXBlcmlvciBlbiBjb2xvciByb2pvIHNvbiBsb3MgbcOhcyBsZWFsZXMgeSBjb24gdW5hcyBjb21wcmFzIHN1cGVyaW9yZXMgYSBsb3MgZGVtw6FzIHBlcm8gZGViaWRvIGEgcXVlIGxhIHZpc3VhbGl6YWNpw7NuIGRlbCBwcmltZXIgY2x1c3RlciBlcmEgbXV5IGluY2llcnRhIHBvciBlbCBhbW9udG9uYW1pZW50byBkZSBsb3MgZGF0b3MsIHNlIGhpem8gbGEgc2VndW5kYSBvcHRpbWl6YWNpw7NuIGRlIEstbWVhbnMgbGEgY3VhbCB0YW1iacOpbiByZWR1Y2UgZWwgZXJyb3IgZGUgbG9zIGNsdXN0ZXJzIGVuIHVuIDYtMTUlIGFsIGRlY2lybm9zIGN1w6FsIGVzIGVsIGdydXBvIGRlIGNsdXN0ZXJzIG1hcyDDs3B0aW1vIHBhcmEgbnVlc3RybyBhbsOhbGlzaXMsIGVzdG8gc2UgY29tcGxlbWVudGFyw61hIGNvbiBsYSBoZXJyYW1pZW50YSBkZSBtYW5lcmEgZW4gcXVlIHNlZ21lbnRhbmRvIGEgbG9zIGNsaWVudGVzIHBvciBpbmRpdmlkdWFsIHNlIGxlcyBwdWVkZW4gZGFyIGRpc3RpbnRvcyB0aXBvcyBkZSBib25pZmljYWNpw7NuZXMgbyBjb21wbGVtZW50b3MgYWRpY2lvbmFsZXMgcGFyYSByZXRlbmVybG9zIGRlIGxhIGNvbXBldGVuY2lhLg0KDQpZYSB2aXN1YWxpemFuZG8gbG9zIGRhdG9zLCBlc3RhIGhlcnJhbWllbnRhIGxhIHBvZHLDrWFtb3MgdXRpbGl6YXIgZ2VuZXJhbG1lbnRlIGVuIGVsIGFyZWEgZGUgbWVyY2Fkb3RlY25pYSB5IHZlbnRhcyB5YSBxdWUgdmEgbXV5IHJlbGFjaW9uYWRhIGNvbiBsYSBnZW5lcmFjacOzbiBkZSBpbnNpZ2h0cyBwYXJhIGRpc3RpbnRvcyBjbHVzdGVycyBlbiBlbCBtZXJjYWRvIHkgYWwgbWlzbW8gdGllbXBvIGxhIGdlbmVyYWNpw7NuIGRlIGVzdHJhdGVnaWFzLiBEZSBpZ3VhbCBtYW5lcmEgc2UgcHVlZGUgaW50ZWdyYXIgZXN0YSBpbmZvcm1hY2nDs24gY29uIHVuIENSTSBwYXJhIHBlcnNvbmFsaXphciBsYXMgcHJvbW9jaW9uZXMgcXVlIHNlIGxlcyBkYW4gYSBzdXMgc2VnbWVudG9zIGRlIGNsaWVudGVzIHkgYXVtZW50YXIgbGFzIHZlbnRhcyBlbiBlbCBhcmVhIGRlIGludGVyw6lzIGRlbCBjbGllbnRlLCBhc2kgY29tbyBsbyBoYWNlIENvc3RjbyBvIFJhcHBpIGFsIGVzdHVkaWFyIGVsIGNvbXBvcnRhbWllbnRvIGRlbCBjb25zdW1pZG9yIGNvbiBzdXMgZGF0b3MgeSBkYW5kbyBvZmVydGFzIHF1ZSBwcm9iYWJsZW1lbnRlIHB1ZGllcmFuIGFjZXB0YXIuDQoNCjwvZGl2Pg0K