Contexto

Los datos utilizados son el resultado de un ánalisis químico de vinos. Estos vinos fueron cultivados en la misma región de Italia pero derivado de tres cultivares diferentes. El analisis determinó las cantidades que se encuentran en cada uno de los tres tipos, basado en 13 componentes.

El vino es una bebida alcohólica obtenida de la uva mediante fermentación alcohólica de su mosto o zumo; la fermentación se produce por la acción de levaduras que transforman los azúcares del fruto en alcohol etílico y anhídrido carbónico (MAPA, 2010). Acorde a esto, se definen las siguientes variables:

  • Alcohol: La cantidad de alcohol en el vino, medida en porcentaje de volumen.
  • Malic_Acid: Ácido málico presente en el vino, un ácido orgánico que afecta la acidez y el sabor.
  • Ash: La cantidad de cenizas en el vino, medida en gramos por litro.
  • Ash_Alcanity: La alcalinidad de las cenizas del vino, que puede afectar la percepción del sabor y la estabilidad del vino.
  • Magnesium: La cantidad de magnesio en el vino, un mineral que puede influir en la fermentación y la estructura del vino.
  • Total_Phenol: La cantidad total de compuestos fenólicos en el vino, que contribuyen a su color, sabor y aroma.
  • Flavanoids: La cantidad de flavonoides en el vino, compuestos que pueden tener efectos antioxidantes y contribuir al sabor y aroma.
  • Nonflavanoid_Phenols: La cantidad de fenoles no flavonoides en el vino, que también pueden afectar el sabor y la calidad. - Proanthocyanins: La cantidad de proantocianidinas en el vino, compuestos que contribuyen a la astringencia y estabilidad del color.
  • Color_Intensity: La intensidad del color del vino, medida en unidades absorbancia a 420 nm.
  • Hue: El tono del color del vino, que puede variar desde rojo hasta amarillo. OD280: La absorbancia óptica a 280 nm, que puede proporcionar información sobre la concentración de compuestos fenólicos y la madurez del vino.
  • Proline: La cantidad de prolinas en el vino, un aminoácido que puede influir en el sabor y la estructura del vino.

Paso 1. Instalar paquetes y llamar librerias

#install.packages("cluster")
library(cluster)
#install.packages("ggplot2")
library(ggplot2)
#install.packages("data.table")
library(data.table)
#install.packages("factoextra")
library(factoextra)
## Welcome! Want to learn more? See two factoextra-related books at https://goo.gl/ve3WBa
library(dplyr)
## 
## Attaching package: 'dplyr'
## The following objects are masked from 'package:data.table':
## 
##     between, first, last
## The following objects are masked from 'package:stats':
## 
##     filter, lag
## The following objects are masked from 'package:base':
## 
##     intersect, setdiff, setequal, union
library(readxl)

Paso 2. Obtener los datos

df <- read_excel("wine.xlsx")
df_scaled <- scale(df)
summary(df)
##     Alcohol        Malic_Acid         Ash         Ash_Alcanity  
##  Min.   :11.03   Min.   :0.740   Min.   :1.360   Min.   :10.60  
##  1st Qu.:12.36   1st Qu.:1.603   1st Qu.:2.210   1st Qu.:17.20  
##  Median :13.05   Median :1.865   Median :2.360   Median :19.50  
##  Mean   :13.00   Mean   :2.336   Mean   :2.367   Mean   :19.49  
##  3rd Qu.:13.68   3rd Qu.:3.083   3rd Qu.:2.558   3rd Qu.:21.50  
##  Max.   :14.83   Max.   :5.800   Max.   :3.230   Max.   :30.00  
##    Magnesium      Total_Phenols     Flavanoids    Nonflavanoid_Phenols
##  Min.   : 70.00   Min.   :0.980   Min.   :0.340   Min.   :0.1300      
##  1st Qu.: 88.00   1st Qu.:1.742   1st Qu.:1.205   1st Qu.:0.2700      
##  Median : 98.00   Median :2.355   Median :2.135   Median :0.3400      
##  Mean   : 99.74   Mean   :2.295   Mean   :2.029   Mean   :0.3619      
##  3rd Qu.:107.00   3rd Qu.:2.800   3rd Qu.:2.875   3rd Qu.:0.4375      
##  Max.   :162.00   Max.   :3.880   Max.   :5.080   Max.   :0.6600      
##  Proanthocyanins Color_Intensity       Hue             OD280      
##  Min.   :0.410   Min.   : 1.280   Min.   :0.4800   Min.   :1.270  
##  1st Qu.:1.250   1st Qu.: 3.220   1st Qu.:0.7825   1st Qu.:1.938  
##  Median :1.555   Median : 4.690   Median :0.9650   Median :2.780  
##  Mean   :1.591   Mean   : 5.058   Mean   :0.9574   Mean   :2.612  
##  3rd Qu.:1.950   3rd Qu.: 6.200   3rd Qu.:1.1200   3rd Qu.:3.170  
##  Max.   :3.580   Max.   :13.000   Max.   :1.7100   Max.   :4.000  
##     Proline      
##  Min.   : 278.0  
##  1st Qu.: 500.5  
##  Median : 673.5  
##  Mean   : 746.9  
##  3rd Qu.: 985.0  
##  Max.   :1680.0

Paso 3. Cantidad de grupos

Inicialmente se puede poner el num que quieras. No obstante, después de realizar la optimización se conoce cuál es la cantidad correcta de segmentos.

set.seed(123)
wcss <- vector()
max_k <- 10 #se puede modificar
for (k in 1:max_k) {
  kmeans_model <- kmeans(df_scaled, centers = k, nstart = 25)
  wcss[k] <- kmeans_model$tot.withinss
}

# Graficar el método del codo
par(mar = c(4, 4, 1, 1))
plot(1:max_k, wcss, type = "b", xlab = "Numero de Clusters", ylab = "WCSS", main = "Metodo del Codo", pch = 19, frame = FALSE)

grupos <- 3

Paso 4. Generar los segmentos

segmentos <- kmeans(df_scaled, grupos)
segmentos # en los resultados x es el centroide del segmento
## K-means clustering with 3 clusters of sizes 51, 62, 65
## 
## Cluster means:
##      Alcohol Malic_Acid        Ash Ash_Alcanity   Magnesium Total_Phenols
## 1  0.1644436  0.8690954  0.1863726    0.5228924 -0.07526047   -0.97657548
## 2  0.8328826 -0.3029551  0.3636801   -0.6084749  0.57596208    0.88274724
## 3 -0.9234669 -0.3929331 -0.4931257    0.1701220 -0.49032869   -0.07576891
##    Flavanoids Nonflavanoid_Phenols Proanthocyanins Color_Intensity        Hue
## 1 -1.21182921           0.72402116     -0.77751312       0.9388902 -1.1615122
## 2  0.97506900          -0.56050853      0.57865427       0.1705823  0.4726504
## 3  0.02075402          -0.03343924      0.05810161      -0.8993770  0.4605046
##        OD280    Proline
## 1 -1.2887761 -0.4059428
## 2  0.7770551  1.1220202
## 3  0.2700025 -0.7517257
## 
## Clustering vector:
##   [1] 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
##  [38] 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 3 3 1 3 3 3 3 3 3 3 3 3 3 3 2
##  [75] 3 3 3 3 3 3 3 3 3 1 3 3 3 3 3 3 3 3 3 3 3 2 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3
## [112] 3 3 3 3 3 3 3 1 3 3 2 3 3 3 3 3 3 3 3 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
## [149] 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
## 
## Within cluster sum of squares by cluster:
## [1] 326.3537 385.6983 558.6971
##  (between_SS / total_SS =  44.8 %)
## 
## Available components:
## 
## [1] "cluster"      "centers"      "totss"        "withinss"     "tot.withinss"
## [6] "betweenss"    "size"         "iter"         "ifault"

Paso 5. Asignar el grupo al que pertenece cada observación

asignacion <- cbind(df, cluster = segmentos$cluster)

Paso 6. Graficar los clusters

fviz_cluster(segmentos, data=df_scaled)

Paso 7. Optimización de grupos

set.seed(123)
optimizacion <- clusGap(df_scaled, FUN=kmeans, nstart=1, K.max=10)
plot(optimizacion, xlab="Número de clusters k")

Paso 8. Comparar segmentos

promedio <- aggregate(asignacion, by=list(asignacion$cluster), FUN=mean)
promedio
##   Group.1  Alcohol Malic_Acid      Ash Ash_Alcanity Magnesium Total_Phenols
## 1       1 13.13412   3.307255 2.417647     21.24118  98.66667      1.683922
## 2       2 13.67677   1.997903 2.466290     17.46290 107.96774      2.847581
## 3       3 12.25092   1.897385 2.231231     20.06308  92.73846      2.247692
##   Flavanoids Nonflavanoid_Phenols Proanthocyanins Color_Intensity       Hue
## 1  0.8188235            0.4519608        1.145882        7.234706 0.6919608
## 2  3.0032258            0.2920968        1.922097        5.453548 1.0654839
## 3  2.0500000            0.3576923        1.624154        2.973077 1.0627077
##      OD280   Proline cluster
## 1 1.696667  619.0588       1
## 2 3.163387 1100.2258       2
## 3 2.803385  510.1692       3

Conclusión

La segmentación es una herramienta útil para generar la agrupación de datos y en este caso nos sirvio para identificar el cultivar correspondiente a cada vino. Sin embargo, es imporante escalar los datos antes de realizar un ánalisis para evitar que la magnitud de alguna influya más en el proceso. Acorde a esto, se determinó que el númro de cluster óptimo para este caso es 3, ya que despues este número representa un punto de inflexión en la curva o el “codo”; es decir, los clusters o números siguientes no minimizan la varianza dentro de los clusters de forma suficientemente significativa como para justificar agrupaciones adicionales en el conjunto de datos. Por último, se establece una comparación de promedios entre segmentos con la función aggregate que es útil para resumir datos en función de uno o más factores.

Referencias

R for Data Science (2da edicion)

Wine dataset

MAPA. (2010). Ministerio de Servicos de Agricultura, Pesca y Alimentacion. Recuperado de: https://www.mapa.gob.es/es/ministerio/servicios/informacion/vino_tcm30-102868.pdf

LS0tCnRpdGxlOiAiU2VnbWVudGFjacOzbiAtIFZpbm8iCmF1dGhvcjogIkxpc3NldCBIZXJuw6FuZGV6IEEwMTI4NDYxMSB5IEF2cmlsIExvYmF0byBBMDA4MzMxMTMiCmRhdGU6ICIyMDI0LTAyLTE5IgpvdXRwdXQ6CiAgaHRtbF9kb2N1bWVudDoKICAgIHRvYzogVFJVRQogICAgdG9jX2Zsb2F0OiB0cnVlCiAgICBjb2RlX2Rvd25sb2FkOiBUUlVFCi0tLQoKIVtdKGh0dHBzOi8vc2FsdWRjb25sdXBhLmNvbS9tZWRpYS9pbWFnZXMvcmVkLXdpbmUtcG91cmluZy1mcm9tLWJvdHRsZS1nbGFzcy53aWR0aC0xOTIwLmpwZykKCiMgKipDb250ZXh0byoqCkxvcyBkYXRvcyB1dGlsaXphZG9zIHNvbiBlbCByZXN1bHRhZG8gZGUgdW4gw6FuYWxpc2lzIHF1w61taWNvIGRlIHZpbm9zLiBFc3RvcyB2aW5vcyBmdWVyb24gY3VsdGl2YWRvcyBlbiBsYSBtaXNtYSByZWdpw7NuIGRlIEl0YWxpYSBwZXJvIGRlcml2YWRvIGRlIHRyZXMgY3VsdGl2YXJlcyBkaWZlcmVudGVzLiBFbCBhbmFsaXNpcyBkZXRlcm1pbsOzIGxhcyBjYW50aWRhZGVzIHF1ZSBzZSBlbmN1ZW50cmFuIGVuIGNhZGEgdW5vIGRlIGxvcyB0cmVzIHRpcG9zLCBiYXNhZG8gZW4gMTMgY29tcG9uZW50ZXMuCgpFbCB2aW5vIGVzIHVuYSBiZWJpZGEgYWxjb2jDs2xpY2Egb2J0ZW5pZGEgZGUgbGEgdXZhIG1lZGlhbnRlIGZlcm1lbnRhY2nDs24gYWxjb2jDs2xpY2EgZGUgc3UgbW9zdG8gbyB6dW1vOyBsYSBmZXJtZW50YWNpw7NuIHNlIHByb2R1Y2UgcG9yIGxhIGFjY2nDs24gZGUgbGV2YWR1cmFzIHF1ZSB0cmFuc2Zvcm1hbiBsb3MgYXrDumNhcmVzIGRlbCBmcnV0byBlbiBhbGNvaG9sIGV0w61saWNvIHkgYW5ow61kcmlkbyBjYXJiw7NuaWNvIChNQVBBLCAyMDEwKS4gQWNvcmRlIGEgZXN0bywgc2UgZGVmaW5lbiBsYXMgc2lndWllbnRlcyB2YXJpYWJsZXM6ICAKCi0gQWxjb2hvbDogTGEgY2FudGlkYWQgZGUgYWxjb2hvbCBlbiBlbCB2aW5vLCBtZWRpZGEgZW4gcG9yY2VudGFqZSBkZSB2b2x1bWVuLiAgCi0gTWFsaWNfQWNpZDogw4FjaWRvIG3DoWxpY28gcHJlc2VudGUgZW4gZWwgdmlubywgdW4gw6FjaWRvIG9yZ8OhbmljbyBxdWUgYWZlY3RhIGxhIGFjaWRleiB5IGVsIHNhYm9yLiAgCi0gQXNoOiBMYSBjYW50aWRhZCBkZSBjZW5pemFzIGVuIGVsIHZpbm8sIG1lZGlkYSBlbiBncmFtb3MgcG9yIGxpdHJvLiAgCi0gQXNoX0FsY2FuaXR5OiBMYSBhbGNhbGluaWRhZCBkZSBsYXMgY2VuaXphcyBkZWwgdmlubywgcXVlIHB1ZWRlIGFmZWN0YXIgbGEgcGVyY2VwY2nDs24gZGVsIHNhYm9yIHkgbGEgZXN0YWJpbGlkYWQgZGVsIHZpbm8uICAKLSBNYWduZXNpdW06IExhIGNhbnRpZGFkIGRlIG1hZ25lc2lvIGVuIGVsIHZpbm8sIHVuIG1pbmVyYWwgcXVlIHB1ZWRlIGluZmx1aXIgZW4gbGEgZmVybWVudGFjacOzbiB5IGxhIGVzdHJ1Y3R1cmEgZGVsIHZpbm8uCi0gVG90YWxfUGhlbm9sOiBMYSBjYW50aWRhZCB0b3RhbCBkZSBjb21wdWVzdG9zIGZlbsOzbGljb3MgZW4gZWwgdmlubywgcXVlIGNvbnRyaWJ1eWVuIGEgc3UgY29sb3IsIHNhYm9yIHkgYXJvbWEuCi0gRmxhdmFub2lkczogTGEgY2FudGlkYWQgZGUgZmxhdm9ub2lkZXMgZW4gZWwgdmlubywgY29tcHVlc3RvcyBxdWUgcHVlZGVuIHRlbmVyIGVmZWN0b3MgYW50aW94aWRhbnRlcyB5IGNvbnRyaWJ1aXIgYWwgc2Fib3IgeSBhcm9tYS4gIAotIE5vbmZsYXZhbm9pZF9QaGVub2xzOiBMYSBjYW50aWRhZCBkZSBmZW5vbGVzIG5vIGZsYXZvbm9pZGVzIGVuIGVsIHZpbm8sIHF1ZSB0YW1iacOpbiBwdWVkZW4gYWZlY3RhciBlbCBzYWJvciB5IGxhIGNhbGlkYWQuIC0gUHJvYW50aG9jeWFuaW5zOiBMYSBjYW50aWRhZCBkZSBwcm9hbnRvY2lhbmlkaW5hcyBlbiBlbCB2aW5vLCBjb21wdWVzdG9zIHF1ZSBjb250cmlidXllbiBhIGxhIGFzdHJpbmdlbmNpYSB5IGVzdGFiaWxpZGFkIGRlbCBjb2xvci4gIAotIENvbG9yX0ludGVuc2l0eTogTGEgaW50ZW5zaWRhZCBkZWwgY29sb3IgZGVsIHZpbm8sIG1lZGlkYSBlbiB1bmlkYWRlcyBhYnNvcmJhbmNpYSBhIDQyMCBubS4gIAotIEh1ZTogRWwgdG9ubyBkZWwgY29sb3IgZGVsIHZpbm8sIHF1ZSBwdWVkZSB2YXJpYXIgZGVzZGUgcm9qbyBoYXN0YSBhbWFyaWxsby4KT0QyODA6IExhIGFic29yYmFuY2lhIMOzcHRpY2EgYSAyODAgbm0sIHF1ZSBwdWVkZSBwcm9wb3JjaW9uYXIgaW5mb3JtYWNpw7NuIHNvYnJlIGxhIGNvbmNlbnRyYWNpw7NuIGRlIGNvbXB1ZXN0b3MgZmVuw7NsaWNvcyB5IGxhIG1hZHVyZXogZGVsIHZpbm8uICAKLSBQcm9saW5lOiBMYSBjYW50aWRhZCBkZSBwcm9saW5hcyBlbiBlbCB2aW5vLCB1biBhbWlub8OhY2lkbyBxdWUgcHVlZGUgaW5mbHVpciBlbiBlbCBzYWJvciB5IGxhIGVzdHJ1Y3R1cmEgZGVsIHZpbm8uCgojICoqUGFzbyAxLioqIEluc3RhbGFyIHBhcXVldGVzIHkgbGxhbWFyIGxpYnJlcmlhcwpgYGB7cn0KI2luc3RhbGwucGFja2FnZXMoImNsdXN0ZXIiKQpsaWJyYXJ5KGNsdXN0ZXIpCiNpbnN0YWxsLnBhY2thZ2VzKCJnZ3Bsb3QyIikKbGlicmFyeShnZ3Bsb3QyKQojaW5zdGFsbC5wYWNrYWdlcygiZGF0YS50YWJsZSIpCmxpYnJhcnkoZGF0YS50YWJsZSkKI2luc3RhbGwucGFja2FnZXMoImZhY3RvZXh0cmEiKQpsaWJyYXJ5KGZhY3RvZXh0cmEpCmxpYnJhcnkoZHBseXIpCmxpYnJhcnkocmVhZHhsKQpgYGAKCiMgKipQYXNvIDIuKiogT2J0ZW5lciBsb3MgZGF0b3MKYGBge3J9CmRmIDwtIHJlYWRfZXhjZWwoIndpbmUueGxzeCIpCmRmX3NjYWxlZCA8LSBzY2FsZShkZikKYGBgCmBgYHtyfQpzdW1tYXJ5KGRmKQpgYGAKCgojICoqUGFzbyAzLioqIENhbnRpZGFkIGRlIGdydXBvcwpJbmljaWFsbWVudGUgc2UgcHVlZGUgcG9uZXIgZWwgbnVtIHF1ZSBxdWllcmFzLiBObyBvYnN0YW50ZSwgZGVzcHXDqXMgZGUgcmVhbGl6YXIgbGEgb3B0aW1pemFjacOzbiBzZSBjb25vY2UgY3XDoWwgZXMgbGEgY2FudGlkYWQgY29ycmVjdGEgZGUgc2VnbWVudG9zLgpgYGB7cn0KCnNldC5zZWVkKDEyMykKd2NzcyA8LSB2ZWN0b3IoKQptYXhfayA8LSAxMCAjc2UgcHVlZGUgbW9kaWZpY2FyCmZvciAoayBpbiAxOm1heF9rKSB7CiAga21lYW5zX21vZGVsIDwtIGttZWFucyhkZl9zY2FsZWQsIGNlbnRlcnMgPSBrLCBuc3RhcnQgPSAyNSkKICB3Y3NzW2tdIDwtIGttZWFuc19tb2RlbCR0b3Qud2l0aGluc3MKfQoKIyBHcmFmaWNhciBlbCBtw6l0b2RvIGRlbCBjb2RvCnBhcihtYXIgPSBjKDQsIDQsIDEsIDEpKQpwbG90KDE6bWF4X2ssIHdjc3MsIHR5cGUgPSAiYiIsIHhsYWIgPSAiTnVtZXJvIGRlIENsdXN0ZXJzIiwgeWxhYiA9ICJXQ1NTIiwgbWFpbiA9ICJNZXRvZG8gZGVsIENvZG8iLCBwY2ggPSAxOSwgZnJhbWUgPSBGQUxTRSkKYGBgCgpgYGB7cn0KZ3J1cG9zIDwtIDMKYGBgCgoKIyAqKlBhc28gNC4qKiBHZW5lcmFyIGxvcyBzZWdtZW50b3MKYGBge3J9CnNlZ21lbnRvcyA8LSBrbWVhbnMoZGZfc2NhbGVkLCBncnVwb3MpCnNlZ21lbnRvcyAjIGVuIGxvcyByZXN1bHRhZG9zIHggZXMgZWwgY2VudHJvaWRlIGRlbCBzZWdtZW50bwpgYGAKCiMgKipQYXNvIDUuKiogQXNpZ25hciBlbCBncnVwbyBhbCBxdWUgcGVydGVuZWNlIGNhZGEgb2JzZXJ2YWNpw7NuCmBgYHtyfQphc2lnbmFjaW9uIDwtIGNiaW5kKGRmLCBjbHVzdGVyID0gc2VnbWVudG9zJGNsdXN0ZXIpCmBgYAoKIyAqKlBhc28gNi4qKiBHcmFmaWNhciBsb3MgY2x1c3RlcnMKYGBge3J9CmZ2aXpfY2x1c3RlcihzZWdtZW50b3MsIGRhdGE9ZGZfc2NhbGVkKQpgYGAKCgojICoqUGFzbyA3LioqIE9wdGltaXphY2nDs24gZGUgZ3J1cG9zIApgYGB7cn0Kc2V0LnNlZWQoMTIzKQpvcHRpbWl6YWNpb24gPC0gY2x1c0dhcChkZl9zY2FsZWQsIEZVTj1rbWVhbnMsIG5zdGFydD0xLCBLLm1heD0xMCkKcGxvdChvcHRpbWl6YWNpb24sIHhsYWI9Ik7Dum1lcm8gZGUgY2x1c3RlcnMgayIpCmBgYAoKIyAqKlBhc28gOC4qKiBDb21wYXJhciBzZWdtZW50b3MKYGBge3J9CnByb21lZGlvIDwtIGFnZ3JlZ2F0ZShhc2lnbmFjaW9uLCBieT1saXN0KGFzaWduYWNpb24kY2x1c3RlciksIEZVTj1tZWFuKQpwcm9tZWRpbwpgYGAKCgojICoqQ29uY2x1c2nDs24qKgpMYSBzZWdtZW50YWNpw7NuIGVzIHVuYSBoZXJyYW1pZW50YSDDunRpbCBwYXJhIGdlbmVyYXIgbGEgYWdydXBhY2nDs24gZGUgZGF0b3MgeSBlbiBlc3RlIGNhc28gbm9zIHNpcnZpbyBwYXJhIGlkZW50aWZpY2FyIGVsIGN1bHRpdmFyIGNvcnJlc3BvbmRpZW50ZSBhIGNhZGEgdmluby4gU2luIGVtYmFyZ28sIGVzIGltcG9yYW50ZSBlc2NhbGFyIGxvcyBkYXRvcyBhbnRlcyBkZSByZWFsaXphciB1biDDoW5hbGlzaXMgcGFyYSBldml0YXIgcXVlIGxhIG1hZ25pdHVkIGRlIGFsZ3VuYSBpbmZsdXlhIG3DoXMgZW4gZWwgcHJvY2Vzby4gQWNvcmRlIGEgZXN0bywgc2UgZGV0ZXJtaW7DsyBxdWUgZWwgbsO6bXJvIGRlIGNsdXN0ZXIgw7NwdGltbyBwYXJhIGVzdGUgY2FzbyBlcyAzLCB5YSBxdWUgZGVzcHVlcyBlc3RlIG7Dum1lcm8gcmVwcmVzZW50YSB1biBwdW50byBkZSBpbmZsZXhpw7NuIGVuIGxhIGN1cnZhIG8gZWwgImNvZG8iOyBlcyBkZWNpciwgbG9zIGNsdXN0ZXJzIG8gbsO6bWVyb3Mgc2lndWllbnRlcyBubyBtaW5pbWl6YW4gbGEgdmFyaWFuemEgZGVudHJvIGRlIGxvcyBjbHVzdGVycyBkZSBmb3JtYSBzdWZpY2llbnRlbWVudGUgc2lnbmlmaWNhdGl2YSBjb21vIHBhcmEganVzdGlmaWNhciBhZ3J1cGFjaW9uZXMgYWRpY2lvbmFsZXMgZW4gZWwgY29uanVudG8gZGUgZGF0b3MuIFBvciDDumx0aW1vLCBzZSBlc3RhYmxlY2UgdW5hIGNvbXBhcmFjacOzbiBkZSBwcm9tZWRpb3MgZW50cmUgc2VnbWVudG9zIGNvbiBsYSBmdW5jacOzbiBhZ2dyZWdhdGUgcXVlIGVzIMO6dGlsIHBhcmEgcmVzdW1pciBkYXRvcyBlbiBmdW5jacOzbiBkZSB1bm8gbyBtw6FzIGZhY3RvcmVzLgoKIyAqKlJlZmVyZW5jaWFzKioKW1IgZm9yIERhdGEgU2NpZW5jZSAoMmRhIGVkaWNpb24pXShodHRwczovL2VzLnI0ZHMuaGFkbGV5Lm56LykKCltXaW5lIGRhdGFzZXRdKGh0dHBzOi8vc2VhcmNoLnItcHJvamVjdC5vcmcvQ1JBTi9yZWZtYW5zL0hEY2xhc3NpZi9odG1sL3dpbmUuaHRtbCkgCgpNQVBBLiAoMjAxMCkuIE1pbmlzdGVyaW8gZGUgU2Vydmljb3MgZGUgQWdyaWN1bHR1cmEsIFBlc2NhIHkgQWxpbWVudGFjaW9uLiBSZWN1cGVyYWRvIGRlOiBodHRwczovL3d3dy5tYXBhLmdvYi5lcy9lcy9taW5pc3RlcmlvL3NlcnZpY2lvcy9pbmZvcm1hY2lvbi92aW5vX3RjbTMwLTEwMjg2OC5wZGYK