ENTREGABLE 2.5 - RECURSOS HUMANOS - BAJAS

1. Conceptos Claves

K- Vecinos Más Cercanos y/o K-Means Clustering:
KNN y Kmeans clustering, son funciones las cuales ambas contribuyen a la identificación de clusters ya que KMC es un algoritmo el cual se utilizaa para agrupar, sin embargo KNN se utiliza mas que nada para la clasificación de variables. (Harrison, 2018) En la función de K-means clustering se divide un conjunto de n observaciones en k grupos, esta función se usa cuando no se tienen etiquetas de grupo existentes y desea asignar puntos de datos similares a la cantidad de grupos que especifique (K). (Jim Frost, 2022)

Aprendizaje No Supervisado y/o Unsupervised Learning:
El objetivo que tiene el unsupervised learning es el de descubrir grupos de ejemplos similares dentro de los datos, lo que se denomina “clustering”, o determinar cómo se distribuyen los datos en el espacio, lo que se conoce como estimación de densidad Esta función contribuye a la identificación de clusters ya que la agrupación en “clusters” es un método de “unsupervissed learning” que funciona en conjuntos de datos en los que no hay una variable de resultado (objetivo) ni se sabe nada sobre la relación entre las observaciones, es decir, datos sin etiquetar. (Frontiersin, 2019)

Distancia Euclidiana / Eucliedean Distance:
Al momento de usar “Euclidean distance” las observaciones con valores altos de características se “agruparán” juntas. Lo mismo se aplica a las observaciones con valores bajos de características. La correlación de Pearson mide el grado de una relación lineal entre dos perfiles. (Waref, 2020) En otras palabras, la distancia euclidiana es la distancia que hay entre dos datos en un espacio.

2. K-means Clustering

# descargar y llamar librerías
#install.packages("tidyverse")
library(tidyverse)
#install.packages("foreign")
#install.packages("dplyr")
library(ggplot2)
#install.packages("psych")
library(psych)
#install.packages("corrplot")
library(corrplot)
#install.packages("jtools")
library(jtools)
#install.packages("lmtest")
library(lmtest)
#install.packages("car")
library(car)
#install.packages("factoextra")
library(factoextra)
#install.packages("janitor")
library(janitor)
#install.packages("readr")
library(readr)
#install.packages("plotrix")
library(plotrix)

Limpiar base de datos

#file.choose()
rh <- read.csv("/Users/anapaulatejeda/Downloads/recursos_humanos_base_limpia.csv")
# Limpiar nombre
rh1 <- clean_names(rh)
# Visualizar base de datos
summary(rh1)
##   apellidos            nombre               edad       fecha_de_nacimiento
##  Length:233         Length:233         Min.   :19.00   Length:233         
##  Class :character   Class :character   1st Qu.:23.00   Class :character   
##  Mode  :character   Mode  :character   Median :29.00   Mode  :character   
##                                        Mean   :31.08                      
##                                        3rd Qu.:37.00                      
##                                        Max.   :61.00                      
##     genero              rfc            fecha_de_alta      motivo_de_baja    
##  Length:233         Length:233         Length:233         Length:233        
##  Class :character   Class :character   Class :character   Class :character  
##  Mode  :character   Mode  :character   Mode  :character   Mode  :character  
##                                                                             
##                                                                             
##                                                                             
##  dias_laborados        baja              puesto          departamento      
##  Min.   :   0.00   Length:233         Length:233         Length:233        
##  1st Qu.:   6.00   Class :character   Class :character   Class :character  
##  Median :  15.00   Mode  :character   Mode  :character   Mode  :character  
##  Mean   :  72.73                                                           
##  3rd Qu.:  47.00                                                           
##  Max.   :1966.00                                                           
##  no_seguro_social   salario_diario_imss factor_cred_infonavit
##  Length:233         Min.   :144.4       Length:233           
##  Class :character   1st Qu.:180.7       Class :character     
##  Mode  :character   Median :180.7       Mode  :character     
##                     Mean   :177.9                            
##                     3rd Qu.:180.7                            
##                     Max.   :500.0                            
##  n_credito_infonavit lugar_de_nacimiento     curp              calle          
##  Length:233          Length:233          Length:233         Length:233        
##  Class :character    Class :character    Class :character   Class :character  
##  Mode  :character    Mode  :character    Mode  :character   Mode  :character  
##                                                                               
##                                                                               
##                                                                               
##  numero_interno       colonia          codigo_postal       municipio        
##  Length:233         Length:233         Length:233         Length:233        
##  Class :character   Class :character   Class :character   Class :character  
##  Mode  :character   Mode  :character   Mode  :character   Mode  :character  
##                                                                             
##                                                                             
##                                                                             
##     estado          estado_civil       tarjeta_o_cuenta  
##  Length:233         Length:233         Length:233        
##  Class :character   Class :character   Class :character  
##  Mode  :character   Mode  :character   Mode  :character  
##                                                          
##                                                          
## 
# Eliminar columnas que no se necesitan
rh2 <- subset(rh1,select = -c (apellidos, nombre, fecha_de_nacimiento, rfc, fecha_de_alta, baja, departamento, 
                               no_seguro_social, factor_cred_infonavit, n_credito_infonavit, lugar_de_nacimiento,
                               curp, calle, numero_interno, colonia, codigo_postal, municipio, estado, tarjeta_o_cuenta))
summary(rh2)
##       edad          genero          motivo_de_baja     dias_laborados   
##  Min.   :19.00   Length:233         Length:233         Min.   :   0.00  
##  1st Qu.:23.00   Class :character   Class :character   1st Qu.:   6.00  
##  Median :29.00   Mode  :character   Mode  :character   Median :  15.00  
##  Mean   :31.08                                         Mean   :  72.73  
##  3rd Qu.:37.00                                         3rd Qu.:  47.00  
##  Max.   :61.00                                         Max.   :1966.00  
##     puesto          salario_diario_imss estado_civil      
##  Length:233         Min.   :144.4       Length:233        
##  Class :character   1st Qu.:180.7       Class :character  
##  Mode  :character   Median :180.7       Mode  :character  
##                     Mean   :177.9                         
##                     3rd Qu.:180.7                         
##                     Max.   :500.0
# na's en la base de datos
sum(is.na(rh2))
## [1] 0
sapply(rh2, function(x) sum(is.na(x)))
##                edad              genero      motivo_de_baja      dias_laborados 
##                   0                   0                   0                   0 
##              puesto salario_diario_imss        estado_civil 
##                   0                   0                   0
# no se encuentran NA's en la base de datos 

# Convertir tipos de datos
rh2$edad <- as.numeric(rh2$edad)
rh2$genero <- as.factor(rh2$genero)
rh2$motivo_de_baja <- as.factor(rh2$motivo_de_baja)
rh2$dias_laborados <- as.numeric(rh2$dias_laborados)
rh2$puesto <- as.factor(rh2$puesto)
rh2$salario_diario_imss <- as.numeric(rh2$salario_diario_imss)
rh2$estado_civil <- as.factor(rh2$estado_civil)
summary(rh2)
##       edad             genero                motivo_de_baja dias_laborados   
##  Min.   :19.00   FEMENINO :137   ABANDONO           :  1    Min.   :   0.00  
##  1st Qu.:23.00   MASCULINO: 96   BAJA POR FALTAS    :139    1st Qu.:   6.00  
##  Median :29.00                   JUBILACION         :  1    Median :  15.00  
##  Mean   :31.08                   RENUNCIA VOLUNTARIA: 84    Mean   :  72.73  
##  3rd Qu.:37.00                   TERMINO DE CONTRATO:  8    3rd Qu.:  47.00  
##  Max.   :61.00                                              Max.   :1966.00  
##                                                                              
##                    puesto    salario_diario_imss      estado_civil
##  AYUDANTE GENERAL     :171   Min.   :144.4       divorcio   :  3  
##  COSTURERA            : 10   1st Qu.:180.7       matrimonio : 63  
##  SOLDADOR             : 10   Median :180.7       Sin Conocer:  1  
##  MONTACARGUISTA       :  5   Mean   :177.9       Soltero    :107  
##  AY. GENERAL          :  4   3rd Qu.:180.7       Unión libre: 59  
##  AUXILIAR DE EMBARQUES:  3   Max.   :500.0                        
##  (Other)              : 30

Crear clusters

Cluster 1: Edad y Número de días laborados

# Normalizar Variables
rh_edad_dias <-rh2 %>% select(salario_diario_imss, edad, dias_laborados)
rh_edad_dias_norm<-scale(rh_edad_dias[2:3]) 
plot(rh_edad_dias_norm)

# Número óptimo de clústers con "Elbow Plot"
fviz_nbclust(rh_edad_dias_norm, kmeans, method="wss")+ 
  geom_vline(xintercept=6, linetype=2)+           
  labs(subtitle = "Elbow method")  

De acuerdo al elbow method, el numero óptimo de clusters son 6 pero al momento de visualizarlo se determinó que es una elevada cantidad de clusters y no sería tan sencillo el interpretar y nombrar tantos clusters por lo que se llegó a la conclusión que se elaborarán 5 clusters.

# Visualizar Clusters
cluster1 <-kmeans(rh_edad_dias_norm,5)
cluster1
## K-means clustering with 5 clusters of sizes 43, 4, 68, 8, 110
## 
## Cluster means:
##         edad dias_laborados
## 1  1.5856496     -0.1730602
## 2  1.0544820      6.6446440
## 3  0.2370717     -0.2593203
## 4  0.2767222      1.9190143
## 5 -0.8248684     -0.1532302
## 
## Clustering vector:
##   1   2   3   4   5   6   7   8   9  10  11  12  13  14  15  16  17  18  19  20 
##   4   3   5   5   3   1   3   3   1   5   5   3   5   3   4   5   5   5   5   5 
##  21  22  23  24  25  26  27  28  29  30  31  32  33  34  35  36  37  38  39  40 
##   3   2   5   3   1   5   3   5   5   5   3   5   5   5   3   5   5   4   3   5 
##  41  42  43  44  45  46  47  48  49  50  51  52  53  54  55  56  57  58  59  60 
##   4   4   5   5   5   5   5   5   1   1   1   2   5   1   5   5   1   5   5   5 
##  61  62  63  64  65  66  67  68  69  70  71  72  73  74  75  76  77  78  79  80 
##   5   5   3   5   5   1   5   4   4   5   5   5   3   5   3   5   1   5   5   1 
##  81  82  83  84  85  86  87  88  89  90  91  92  93  94  95  96  97  98  99 100 
##   2   5   1   5   5   5   1   5   5   5   3   1   1   5   5   5   1   3   5   3 
## 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 
##   5   5   1   3   5   5   3   2   3   5   3   3   5   3   3   3   1   1   1   5 
## 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 
##   5   5   5   5   3   5   3   1   5   3   5   4   5   5   5   3   1   3   1   3 
## 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 
##   3   1   1   1   5   3   3   3   5   5   5   3   1   1   5   3   5   3   1   1 
## 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 
##   1   1   3   1   5   5   3   5   5   1   3   1   5   1   3   3   1   3   3   5 
## 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 
##   5   5   3   1   3   3   5   5   3   3   3   3   3   3   5   3   3   3   3   5 
## 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 
##   3   1   3   5   5   5   1   5   5   5   3   3   5   5   3   3   3   1   5   5 
## 221 222 223 224 225 226 227 228 229 230 231 232 233 
##   3   5   5   5   5   1   3   1   5   5   5   5   5 
## 
## Within cluster sum of squares by cluster:
## [1] 11.405375 15.799166  7.976676  7.819045 14.649008
##  (between_SS / total_SS =  87.6 %)
## 
## Available components:
## 
## [1] "cluster"      "centers"      "totss"        "withinss"     "tot.withinss"
## [6] "betweenss"    "size"         "iter"         "ifault"
fviz_cluster(cluster1,data=rh_edad_dias_norm)

Interpretación: Cluster número 1 y 4 son de edades diferentes pero tienen días laborados similares, igual que el cluster 3 y 5 . Por otro lado, el cluster 2 son datos que no tienen días laborados similares pero tienen más días que los otros clusters y tiene un rango diferente de edades. Por lo que se concluye que los días laborados no tienen tanta relación con la edad.

Cluster 2: Edad y Salario Diario

# Normalizar Variables
rh_edad_sal <-rh2 %>% select(salario_diario_imss, edad, dias_laborados)
rh_edad_sal_norm<-scale(rh_edad_dias[1:2]) 
plot(rh_edad_sal_norm)

# Número óptimo de clústers con "Elbow Plot"
fviz_nbclust(rh_edad_sal_norm, kmeans, method="wss")+ 
  geom_vline(xintercept=5, linetype=2)+           
  labs(subtitle = "Elbow method")  

Se determinó que el número óptimo es de 5 clusters

# Visualizar Clusters
cluster2 <-kmeans(rh_edad_sal_norm,5)
cluster2
## K-means clustering with 5 clusters of sizes 1, 34, 40, 63, 95
## 
## Cluster means:
##   salario_diario_imss        edad
## 1         13.75965225  0.09524497
## 2         -0.11512539  1.83986677
## 3          0.11335568  0.74337807
## 4         -0.11750244 -0.10886552
## 5         -0.07344171 -0.90028748
## 
## Clustering vector:
##   1   2   3   4   5   6   7   8   9  10  11  12  13  14  15  16  17  18  19  20 
##   1   4   5   5   4   2   4   4   2   5   5   4   5   4   4   5   5   5   5   5 
##  21  22  23  24  25  26  27  28  29  30  31  32  33  34  35  36  37  38  39  40 
##   4   2   5   4   2   5   3   5   5   5   4   5   5   5   4   5   5   4   4   5 
##  41  42  43  44  45  46  47  48  49  50  51  52  53  54  55  56  57  58  59  60 
##   5   4   5   5   5   5   5   5   2   2   3   2   5   2   5   5   2   5   5   5 
##  61  62  63  64  65  66  67  68  69  70  71  72  73  74  75  76  77  78  79  80 
##   5   5   3   4   4   3   5   2   4   5   5   5   3   4   3   5   3   5   5   2 
##  81  82  83  84  85  86  87  88  89  90  91  92  93  94  95  96  97  98  99 100 
##   4   4   2   5   5   5   3   5   5   5   4   3   2   5   5   4   2   4   5   4 
## 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 
##   5   5   3   4   5   5   3   4   3   5   4   4   5   3   4   4   2   2   2   5 
## 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 
##   5   5   5   5   4   5   3   2   4   3   5   2   5   4   4   4   2   4   3   3 
## 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 
##   4   3   2   2   5   4   3   4   5   4   5   3   2   2   5   3   5   3   3   3 
## 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 
##   2   2   4   2   5   4   4   5   4   2   4   2   4   3   4   3   2   3   3   5 
## 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 
##   5   5   4   2   3   3   5   5   4   3   3   4   3   4   5   4   4   4   4   5 
## 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 
##   4   2   3   5   5   5   2   4   5   5   3   4   5   5   3   3   3   2   4   4 
## 221 222 223 224 225 226 227 228 229 230 231 232 233 
##   4   5   5   5   4   3   4   3   5   5   5   5   5 
## 
## Within cluster sum of squares by cluster:
## [1]  0.000000 13.383803  2.840067 17.829341 23.318853
##  (between_SS / total_SS =  87.6 %)
## 
## Available components:
## 
## [1] "cluster"      "centers"      "totss"        "withinss"     "tot.withinss"
## [6] "betweenss"    "size"         "iter"         "ifault"
fviz_cluster(cluster2,data=rh_edad_sal_norm)

Interpretación: Todos tienen un salario similar sin importar la edad pero en el cluster 1 (que solo es un punto) nos indica que hay alguien que gana más que los demás colaboradores y tienen una edad relativamente joven a comparación de los demás datos

Cluster 3: Número de días laborados y Salario Diario

# Normalizar Variables
rh_dias_sal <-rh2 %>% select(salario_diario_imss, dias_laborados, edad)
rh_dias_sal_norm<-scale(rh_dias_sal[1:2]) 
plot(rh_dias_sal_norm)

# Número óptimo de clústers con "Elbow Plot"
fviz_nbclust(rh_dias_sal_norm, kmeans, method="wss")+ 
  geom_vline(xintercept=5, linetype=2)+           
  labs(subtitle = "Elbow method")  

Se determinó que el número óptimo es de 5 clusters

# Visualizar Clusters
cluster3 <-kmeans(rh_dias_sal_norm,5)
cluster3
## K-means clustering with 5 clusters of sizes 4, 1, 10, 27, 191
## 
## Cluster means:
##   salario_diario_imss dias_laborados
## 1          -0.3962566     6.64464404
## 2          13.7596523     2.56751686
## 3          -0.3729089     1.50771810
## 4          -1.1243505     0.03652891
## 5           0.1147221    -0.23669924
## 
## Clustering vector:
##   1   2   3   4   5   6   7   8   9  10  11  12  13  14  15  16  17  18  19  20 
##   2   4   4   4   4   4   4   4   4   3   4   4   5   5   3   4   4   4   4   4 
##  21  22  23  24  25  26  27  28  29  30  31  32  33  34  35  36  37  38  39  40 
##   4   1   4   4   5   5   5   5   5   5   5   5   5   5   5   5   4   3   5   5 
##  41  42  43  44  45  46  47  48  49  50  51  52  53  54  55  56  57  58  59  60 
##   3   3   5   5   5   5   5   5   5   5   5   1   3   5   5   5   5   5   5   4 
##  61  62  63  64  65  66  67  68  69  70  71  72  73  74  75  76  77  78  79  80 
##   5   5   5   5   5   5   5   3   3   4   5   5   5   5   5   5   5   5   5   5 
##  81  82  83  84  85  86  87  88  89  90  91  92  93  94  95  96  97  98  99 100 
##   1   4   4   4   4   5   5   5   5   5   5   5   5   5   5   5   4   4   5   5 
## 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 
##   5   5   5   5   5   5   5   1   5   5   5   5   5   5   5   5   5   5   5   5 
## 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 
##   5   5   5   5   5   5   5   5   5   5   5   3   5   5   5   5   5   5   5   5 
## 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 
##   5   5   5   5   5   5   5   5   5   5   5   5   5   5   5   5   5   5   5   5 
## 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 
##   5   5   5   5   5   5   5   5   5   5   5   5   5   5   5   5   5   5   5   5 
## 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 
##   5   5   5   5   5   5   5   5   5   5   5   5   5   5   5   5   5   5   5   5 
## 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 
##   5   5   5   5   5   5   5   5   5   5   5   5   5   5   5   5   5   3   5   5 
## 221 222 223 224 225 226 227 228 229 230 231 232 233 
##   5   5   5   5   5   5   5   5   5   5   5   5   5 
## 
## Within cluster sum of squares by cluster:
## [1] 7.839149 0.000000 6.408768 1.637196 3.455406
##  (between_SS / total_SS =  95.8 %)
## 
## Available components:
## 
## [1] "cluster"      "centers"      "totss"        "withinss"     "tot.withinss"
## [6] "betweenss"    "size"         "iter"         "ifault"
fviz_cluster(cluster3,data=rh_dias_sal_norm)

Interpretación: Los días laborados no tienen influencia en el salario porque hay datos que indican colaboradores que trabajan más días pero tienen un salario similar a los que no tienen tantos días laborados. En el cluster 2 podemos observar que es el que tiene un mayor salario pero no es el que tiene una cantidad alta de días laborados como es en el cluster 1. Por lo tanto, los días laborados no tienen relación con el salario.

Creación de segmmentos usando el cluster 2: Edad y Salario Diario

# Incluir columna que indique el cluster de cada registro
rh3 <- rh2
rh3$Clusters<-cluster2$cluster

# visualizar la máxima edad de cada cluster
rh4 <- rh3 %>% group_by(Clusters) %>% summarise(edad=max(edad)) %>% arrange(desc(edad))

# Nombrar cada cluster 
rh3$nombres_clusters <- factor(rh3$Clusters,levels = c(1,2,3,4,5), 
                              labels=c("Excepcion", "Jubilados", "Mayores", "Adultos", "Jovenes"))

# Agrupar los datos por nombre de clusters 
library(dplyr)
rh5 <- rh3 %>% group_by(nombres_clusters) %>% summarize(edad_años=max(edad), 
                                                             salario_imss=mean(salario_diario_imss),
                                                             Count=n())

clusters<-as.data.frame(rh5)
clusters
##   nombres_clusters edad_años salario_imss Count
## 1        Excepcion        32     500.0000     1
## 2        Jubilados        61     175.2329    34
## 3          Mayores        43     180.5810    40
## 4          Adultos        36     175.1773    63
## 5          Jovenes        26     176.2086    95

Gráficos complementarios

Gráfico por nombre de cluster

ggplot(rh5,aes(x=reorder(nombres_clusters,Count),y=Count,fill=nombres_clusters)) +
  geom_bar(stat="identity")

Interpretación: Los jóvenes adultos son los que representan más número de bajas y se visualiza que el orden de número de bajas esta en el mismo orden de edad, esto significa que después de los jóvenes adultos el grupo que más representa bajas es el de los adultos y de ahí siguen los mayores, y por último los jubilados. En conclusión, la edad puede ser un factor importante en el número de bajas.

Gráfico del máximo de edad de cada cluster

ggplot(rh5, aes(x=nombres_clusters,y=edad_años,fill= nombres_clusters,label=round(edad_años,digits=2))) + 
  geom_col() + 
  geom_text()

Interpretación: Aquí se observa la máxima de edad de cada cluster y también muestra la razón por la que se dieron los nombres a cada cluster. Los jóvenes tienen un rango de edad de 19-26, Adultos 27-36, Mayores 37-43 y Jubilados 44-61.

Género de ex-colaboradores

library(ggplot2)
ggplot(rh3, aes(fill=genero, y=genero, x=nombres_clusters)) + 
  geom_bar(position="stack", stat="identity") 

Interpretación: En la gráfica se aprecia un número alto de género masculino en todos los clusters. En Jubilados y Mayores el género Femenino es mayor que el masculino.

Motivo de baja de ex-colaboradores

ggplot(rh3, aes(factor(nombres_clusters), fill = factor(motivo_de_baja))) +
  geom_bar(position = position_dodge2(preserve = "single"))

Interpretación: Se puede observar que el motivo de baja mas grande en todos los grupos de edades es la baja por faltas, seguido de renuncia voluntaria. En jóvenes se puede observar que hay baja por abandono, mientras que en los otros clusters no hubo ninguna baja por abandono.

Puesto de de ex-colaboradores

library(plyr)
## ------------------------------------------------------------------------------
## You have loaded plyr after dplyr - this is likely to cause problems.
## If you need functions from both plyr and dplyr, please load plyr first, then dplyr:
## library(plyr); library(dplyr)
## ------------------------------------------------------------------------------
## 
## Attaching package: 'plyr'
## The following objects are masked from 'package:dplyr':
## 
##     arrange, count, desc, failwith, id, mutate, rename, summarise,
##     summarize
## The following object is masked from 'package:purrr':
## 
##     compact
count(rh3$puesto)
##                                   x freq
## 1  ANALISTA DE NOMINAS /AUX DE R.H.    1
## 2             AUXILIAR DE EMBARQUES    3
## 3                       AY. GENERAL    4
## 4           AY.GENERAL (MATERIALES)    1
## 5                    AYUD.EMBARQUES    1
## 6             AYUDANTE DE EMBARQUES    3
## 7                  AYUDANTE DE MTTO    1
## 8              AYUDANTE DE SOLDADOR    1
## 9                  AYUDANTE GENERAL  171
## 10    AYUDANTE GENERAL DE EMBARQUES    1
## 11                           CHOFER    1
## 12                         CORTADOR    1
## 13                        COSTURERA   10
## 14                        COSTURERO    1
## 15                           DISEÑO    1
## 16             ENCARGADA DE CALIDAD    1
## 17                      FACTURACION    1
## 18             GUARDIA DE SEGURIDAD    2
## 19                INSPECTOR CALIDAD    1
## 20             INSPECTOR DE CALIDAD    2
## 21            INSPECTORA DE CALIDAD    1
## 22                         LIMPIEZA    1
## 23                        MARCADORA    1
## 24                     MATERIALISTA    2
## 25                   MONTACARGUISTA    5
## 26              PRACTICANTE DE MTTO    1
## 27                        RESIDENTE    2
## 28                Residente Yanfeng    1
## 29              SERVICIO AL CLIENTE    1
## 30                         SOLDADOR   10
proporciones <- c(176, 11, 11, 8, 26)
eti <- c("ayudante general", "ayu. soldador/soldador", "costurera", "ayu. embarque", "otros" )
pct <- round(proporciones/sum(proporciones)*100)
eti <- paste(eti, pct)
eti <- paste(eti,"%",sep="")
pie3D(proporciones,labels = eti,
    col=rainbow(length(eti)),
    main="Puestos de bajas")

Interpretación: el puesto en el que más se presentan bajas es en ayudante general, seguido de ayudante soldador/soldador, costurera, etc. Una de las posibles razones por la que haya más bajas en ayudante general, es porque en ese puesto se necesitan más colaboradores, por lo que el número de bajas en ese puesto puede ser mayor o también puede ser el ambiente general que se crea en ese puesto, estás hipotésis se comprobarían con un análisis más profundo de RH.

Estado civil de ex-colaboradores

ggplot(rh3, aes(factor(nombres_clusters), fill = factor(estado_civil))) +
  geom_bar(position = position_dodge2(preserve = "single"))

proporciones1 <- c(107, 3, 59, 63)
etiquetas <- c("soltero", "divorcio", "union libre", "matrimonio")
pct <- round(proporciones1/sum(proporciones1)*100)
etiquetas <- paste(etiquetas, pct)
etiquetas <- paste(etiquetas,"%",sep="")
pie3D(proporciones1,labels = etiquetas,
      col=rainbow(length(etiquetas)),
      main="Estado civil de bajas")

Interpretación: En el total de bajas el estado civil más común es “soltero”, siendo los jóvenes los que tienen una mayor cantidad de este atributo, seguido de los adultos. Después, está el matrimonio siendo este el más presente en el grupo de adultos, seguido de los jóvenes. El divorcio no es tán común en los grupos.

En conclusión, se puede deducir que la mayoría de los ex-colaboradores son solteros, por lo que es más fácil renunciar al no tener una extensa y/o propia familia. Ya que los solteros son la mayoría, por ende los jóvenes son los más propensos en darse de baja en FORM.

3. Principales hallazgos

  • Si bien, la empresa hace mención de incentivos salariales a los colaboradores, los datos capturados y compartidos por parte de la organización unicamente muestran los salarios fijos (es decir, independientemente de horas extra) y por consiguiente, se puede correlacionar que no necesariamente la edad tiene una relación o impacto directo al nivel de salario otorgado a los colaboradores, con excepción de una persona: tratandose del dueño/director, quien posee un salario mayor, siendo este menor que muchos colaboradores presentes en la estructura organizacional.

  • Primeramente, se demuestra que si bien, el salario de los colaboradores corresponde correctamente de acuerdo a su contrato; estrictamente refiriendose al salario IMSS, no se muestra una diferencia en los salarios con la excepción de una persona quien se infiere es el director/dueño de la empresa quien debido a su posición jerárquica, goza de mejor salario/beneficios del IMSS.

  • Entre más jóven se es, mayor la probabilidad de darse de baja de la empresa.

  • Existen grupos de edad, los cuales constan de: Adultos jóvenes, Adultos, Adultos mayores y Jubilados, que forman parte de la organización.

  • El genero femenino tiene mayor presencia en el grupo de edad de jubilados y adultos mayores, en comparación con los grupos de Adultos y Jovenes, donde se tiene mayor presencia por parte del genero masculino. Con esto, se puede inferir con sustento que la presencia de mujeres en grupos de edad mas avanzada es debido a que son madres solteras y/o recurren a lineas de trabajo de este tipo para dar sustento y contribuir a la economía familiar.

  • El grupo con más bajas en todas las categorías de dicha actividad es el de Jóvenes, con la peculiaridad de que existen personas que simplemente dejan de asistir a sus labores.

  • Respecto a las bajas en función de los diferentes puestos existentes en la planta, se puede sustentar que donde existen más bajas es en el puesto de “Ayudante general” (representa el 76% de las bajas totales) por lo que se puede inferir que al ser el puesto con mayor demanda, vacantes ofrecidas y colaboradores quienes participan en dicha area, tiene sentido que destaquen las bajas con respecto a los otros puestas. En otras palabras, el número de bajas es proporcional al número de colaboradores presentes en cada puesto.

Propuestas

  • Elevar niveles salariales y/o prestaciones de acuerdo a la antigüedad y experiencia previa del colaborador.

  • Dada la correlación de la edad jóven y la concentración de colaboradores que se dan de baja, se propone un programa de retención de talento, el cual en conjunto con areas afines a cultura organizacional (RR.HH), que se encargue desde un inicio de atraer el mejor talento, desarrollarlo, retenerlo y dar seguimiento a su “employee journey” para evitar esas bajas.

  • Diseñar un programa de apoyo a madres solteras y/o con necesidad económica, donde se den prestaciones adicionales (no necesariamente de contexto salarial) enfocadas hacia los hijos/as de las colaboradores como por ejemplo, apoyo en material escolar, comida preparada para lunches, entre otras prestaciones que contribuyan a la retención de la colaboradora, y se apoye a la necesidad, y por consiguiente razón de trabajar en Form.

  • Instaurar una política y/o proceso institucional donde el colaborador deba indicar su baja de la empresa con 1 – 2 semanas de antelación, ya que de esta manera tienen la posibilidad de ser acreedores a una indemnización, y por otra parte, la empresa puede comenzar un nuevo proceso de atracción de talento sin afectar la productividad de la planta.

  • Programa de retención de talento #2: Como se estableció previamente, el número de bajas es proporcional al número de colaboradores presentes en cada puesto, por lo que específicamente para el ayudante general, donde hay mayor número de colaboradores, es importante ofrecer mayores beneficios para el colaborador, mejores condiciones de trabajo, integración con el equipo, entre otras acciones que apunten a mitigar en lo posible, la baja de estas personas en este puesto.

Bibliografía Frost, J. (2022, August 31). What is K means clustering? with an example. Statistics By Jim. Retrieved October 9, 2022, from https://statisticsbyjim.com/basics/k-means-clustering/#:~:text=The%20K%20means%20clustering%20algorithm,groups%20you%20specify%20(K). Harrison, O. (2019, July 14). Machine learning basics with the K-nearest neighbors algorithm. Medium. Retrieved October 9, 2022, from https://towardsdatascience.com/machine-learning-basics-with-the-k-nearest-neighbors-algorithm-6a6e71d01761 Mishra, S. (2017, May 21). Unsupervised learning and data clustering. Medium. Retrieved October 9, 2022, from https://towardsdatascience.com/unsupervised-learning-and-data-clustering-eeecb78b422a#:~:text=Clustering%20can%20be%20considered%20the,are%20similar%20in%20some%20way%E2%80%9D. Modifications. euclidean_cluster. (n.d.). Retrieved October 9, 2022, from https://autowarefoundation.gitlab.io/autoware.auto/AutowareAuto/euclidean-cluster-design.html

LS0tCnRpdGxlOiA8c3BhbiBzdHlsZT0iQ29sb3I6T3JhbmdlIj4gRW50cmVnYWJsZSAyLjUgUmVjdXJzb3MgSHVtYW5vcwphdXRob3I6ICJFcXVpcG8gMSIKZGF0ZTogIjEwLzgvMjAyMiIKb3V0cHV0OiAKICBodG1sX2RvY3VtZW50OiAKICAgIHRvYzogdHJ1ZQogICAgdG9jX2Zsb2F0OiB0cnVlCiAgICBjb2RlX2Rvd25sb2FkOiB0cnVlCi0tLQoKPGltZyBzcmM9Ii9Vc2Vycy9hbmFwYXVsYXRlamVkYS9EZXNrdG9wL1NjcmVlbiBTaG90IDIwMjItMTAtMDggYXQgNy4wOS4zNCBQTS5wbmciPgoKPHNwYW4gc3R5bGU9IkNvbG9yOk9yYW5nZSI+ICoqRU5UUkVHQUJMRSAyLjUgLSBSRUNVUlNPUyBIVU1BTk9TIC0gQkFKQVMqKgoKIyAqKjEuIENvbmNlcHRvcyBDbGF2ZXMqKgoqKkstIFZlY2lub3MgTcOhcyBDZXJjYW5vcyB5L28gSy1NZWFucyBDbHVzdGVyaW5nOioqICAKS05OIHkgS21lYW5zIGNsdXN0ZXJpbmcsIHNvbiBmdW5jaW9uZXMgbGFzIGN1YWxlcyBhbWJhcyBjb250cmlidXllbiBhIGxhIGlkZW50aWZpY2FjacOzbiBkZSBjbHVzdGVycyB5YSBxdWUgS01DIGVzIHVuIGFsZ29yaXRtbyBlbCBjdWFsIHNlIHV0aWxpemFhIHBhcmEgYWdydXBhciwgc2luIGVtYmFyZ28gS05OIHNlIHV0aWxpemEgbWFzIHF1ZSBuYWRhIHBhcmEgbGEgY2xhc2lmaWNhY2nDs24gZGUgdmFyaWFibGVzLiAoSGFycmlzb24sIDIwMTgpCkVuIGxhIGZ1bmNpw7NuIGRlIEstbWVhbnMgY2x1c3RlcmluZyBzZSBkaXZpZGUgdW4gY29uanVudG8gZGUgbiBvYnNlcnZhY2lvbmVzIGVuIGsgZ3J1cG9zLCBlc3RhIGZ1bmNpw7NuIHNlIHVzYSBjdWFuZG8gbm8gc2UgdGllbmVuIGV0aXF1ZXRhcyBkZSBncnVwbyBleGlzdGVudGVzIHkgZGVzZWEgYXNpZ25hciBwdW50b3MgZGUgZGF0b3Mgc2ltaWxhcmVzIGEgbGEgY2FudGlkYWQgZGUgZ3J1cG9zIHF1ZSBlc3BlY2lmaXF1ZSAoSykuIChKaW0gRnJvc3QsIDIwMjIpICAKCioqQXByZW5kaXphamUgTm8gU3VwZXJ2aXNhZG8geS9vIFVuc3VwZXJ2aXNlZCBMZWFybmluZzoqKiAgCkVsIG9iamV0aXZvIHF1ZSB0aWVuZSBlbCB1bnN1cGVydmlzZWQgbGVhcm5pbmcgZXMgZWwgZGUgZGVzY3VicmlyIGdydXBvcyBkZSBlamVtcGxvcyBzaW1pbGFyZXMgZGVudHJvIGRlIGxvcyBkYXRvcywgbG8gcXVlIHNlIGRlbm9taW5hIOKAnGNsdXN0ZXJpbmfigJ0sIG8gZGV0ZXJtaW5hciBjw7NtbyBzZSBkaXN0cmlidXllbiBsb3MgZGF0b3MgZW4gZWwgZXNwYWNpbywgbG8gcXVlIHNlIGNvbm9jZSBjb21vIGVzdGltYWNpw7NuIGRlIGRlbnNpZGFkCkVzdGEgZnVuY2nDs24gY29udHJpYnV5ZSBhIGxhIGlkZW50aWZpY2FjacOzbiBkZSBjbHVzdGVycyB5YSBxdWUgbGEgYWdydXBhY2nDs24gZW4g4oCcY2x1c3RlcnPigJ0gZXMgdW4gbcOpdG9kbyBkZSDigJx1bnN1cGVydmlzc2VkIGxlYXJuaW5n4oCdICBxdWUgZnVuY2lvbmEgZW4gY29uanVudG9zIGRlIGRhdG9zIGVuIGxvcyBxdWUgbm8gaGF5IHVuYSB2YXJpYWJsZSBkZSByZXN1bHRhZG8gKG9iamV0aXZvKSBuaSBzZSBzYWJlIG5hZGEgc29icmUgbGEgcmVsYWNpw7NuIGVudHJlIGxhcyBvYnNlcnZhY2lvbmVzLCBlcyBkZWNpciwgZGF0b3Mgc2luIGV0aXF1ZXRhci4gIChGcm9udGllcnNpbiwgMjAxOSkgIAoKKipEaXN0YW5jaWEgRXVjbGlkaWFuYSAvIEV1Y2xpZWRlYW4gRGlzdGFuY2U6KiogIApBbCBtb21lbnRvIGRlIHVzYXIg4oCcRXVjbGlkZWFuIGRpc3RhbmNl4oCdIGxhcyBvYnNlcnZhY2lvbmVzIGNvbiB2YWxvcmVzIGFsdG9zIGRlIGNhcmFjdGVyw61zdGljYXMgc2Ug4oCcYWdydXBhcsOhbuKAnSBqdW50YXMuIExvIG1pc21vIHNlIGFwbGljYSBhIGxhcyBvYnNlcnZhY2lvbmVzIGNvbiB2YWxvcmVzIGJham9zIGRlIGNhcmFjdGVyw61zdGljYXMuIExhIGNvcnJlbGFjacOzbiBkZSBQZWFyc29uIG1pZGUgZWwgZ3JhZG8gZGUgdW5hIHJlbGFjacOzbiBsaW5lYWwgZW50cmUgZG9zIHBlcmZpbGVzLiAoV2FyZWYsIDIwMjApIEVuIG90cmFzIHBhbGFicmFzLCBsYSBkaXN0YW5jaWEgCmV1Y2xpZGlhbmEgZXMgbGEgZGlzdGFuY2lhIHF1ZSBoYXkgZW50cmUgZG9zIGRhdG9zIGVuIHVuIGVzcGFjaW8uIAoKIyAqKjIuIEstbWVhbnMgQ2x1c3RlcmluZyoqCmBgYHtyIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CiMgZGVzY2FyZ2FyIHkgbGxhbWFyIGxpYnJlcsOtYXMKI2luc3RhbGwucGFja2FnZXMoInRpZHl2ZXJzZSIpCmxpYnJhcnkodGlkeXZlcnNlKQojaW5zdGFsbC5wYWNrYWdlcygiZm9yZWlnbiIpCiNpbnN0YWxsLnBhY2thZ2VzKCJkcGx5ciIpCmxpYnJhcnkoZ2dwbG90MikKI2luc3RhbGwucGFja2FnZXMoInBzeWNoIikKbGlicmFyeShwc3ljaCkKI2luc3RhbGwucGFja2FnZXMoImNvcnJwbG90IikKbGlicmFyeShjb3JycGxvdCkKI2luc3RhbGwucGFja2FnZXMoImp0b29scyIpCmxpYnJhcnkoanRvb2xzKQojaW5zdGFsbC5wYWNrYWdlcygibG10ZXN0IikKbGlicmFyeShsbXRlc3QpCiNpbnN0YWxsLnBhY2thZ2VzKCJjYXIiKQpsaWJyYXJ5KGNhcikKI2luc3RhbGwucGFja2FnZXMoImZhY3RvZXh0cmEiKQpsaWJyYXJ5KGZhY3RvZXh0cmEpCiNpbnN0YWxsLnBhY2thZ2VzKCJqYW5pdG9yIikKbGlicmFyeShqYW5pdG9yKQojaW5zdGFsbC5wYWNrYWdlcygicmVhZHIiKQpsaWJyYXJ5KHJlYWRyKQojaW5zdGFsbC5wYWNrYWdlcygicGxvdHJpeCIpCmxpYnJhcnkocGxvdHJpeCkKYGBgCgojIyAqTGltcGlhciBiYXNlIGRlIGRhdG9zKgpgYGB7cn0KI2ZpbGUuY2hvb3NlKCkKcmggPC0gcmVhZC5jc3YoIi9Vc2Vycy9hbmFwYXVsYXRlamVkYS9Eb3dubG9hZHMvcmVjdXJzb3NfaHVtYW5vc19iYXNlX2xpbXBpYS5jc3YiKQojIExpbXBpYXIgbm9tYnJlCnJoMSA8LSBjbGVhbl9uYW1lcyhyaCkKIyBWaXN1YWxpemFyIGJhc2UgZGUgZGF0b3MKc3VtbWFyeShyaDEpCiMgRWxpbWluYXIgY29sdW1uYXMgcXVlIG5vIHNlIG5lY2VzaXRhbgpyaDIgPC0gc3Vic2V0KHJoMSxzZWxlY3QgPSAtYyAoYXBlbGxpZG9zLCBub21icmUsIGZlY2hhX2RlX25hY2ltaWVudG8sIHJmYywgZmVjaGFfZGVfYWx0YSwgYmFqYSwgZGVwYXJ0YW1lbnRvLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5vX3NlZ3Vyb19zb2NpYWwsIGZhY3Rvcl9jcmVkX2luZm9uYXZpdCwgbl9jcmVkaXRvX2luZm9uYXZpdCwgbHVnYXJfZGVfbmFjaW1pZW50bywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGN1cnAsIGNhbGxlLCBudW1lcm9faW50ZXJubywgY29sb25pYSwgY29kaWdvX3Bvc3RhbCwgbXVuaWNpcGlvLCBlc3RhZG8sIHRhcmpldGFfb19jdWVudGEpKQpzdW1tYXJ5KHJoMikKCiMgbmEncyBlbiBsYSBiYXNlIGRlIGRhdG9zCnN1bShpcy5uYShyaDIpKQpzYXBwbHkocmgyLCBmdW5jdGlvbih4KSBzdW0oaXMubmEoeCkpKQojIG5vIHNlIGVuY3VlbnRyYW4gTkEncyBlbiBsYSBiYXNlIGRlIGRhdG9zIAoKIyBDb252ZXJ0aXIgdGlwb3MgZGUgZGF0b3MKcmgyJGVkYWQgPC0gYXMubnVtZXJpYyhyaDIkZWRhZCkKcmgyJGdlbmVybyA8LSBhcy5mYWN0b3IocmgyJGdlbmVybykKcmgyJG1vdGl2b19kZV9iYWphIDwtIGFzLmZhY3RvcihyaDIkbW90aXZvX2RlX2JhamEpCnJoMiRkaWFzX2xhYm9yYWRvcyA8LSBhcy5udW1lcmljKHJoMiRkaWFzX2xhYm9yYWRvcykKcmgyJHB1ZXN0byA8LSBhcy5mYWN0b3IocmgyJHB1ZXN0bykKcmgyJHNhbGFyaW9fZGlhcmlvX2ltc3MgPC0gYXMubnVtZXJpYyhyaDIkc2FsYXJpb19kaWFyaW9faW1zcykKcmgyJGVzdGFkb19jaXZpbCA8LSBhcy5mYWN0b3IocmgyJGVzdGFkb19jaXZpbCkKc3VtbWFyeShyaDIpCmBgYAoKIyMgKkNyZWFyIGNsdXN0ZXJzKgojIyMgQ2x1c3RlciAxOiBFZGFkIHkgTsO6bWVybyBkZSBkw61hcyBsYWJvcmFkb3MKYGBge3J9CiMgTm9ybWFsaXphciBWYXJpYWJsZXMKcmhfZWRhZF9kaWFzIDwtcmgyICU+JSBzZWxlY3Qoc2FsYXJpb19kaWFyaW9faW1zcywgZWRhZCwgZGlhc19sYWJvcmFkb3MpCnJoX2VkYWRfZGlhc19ub3JtPC1zY2FsZShyaF9lZGFkX2RpYXNbMjozXSkgCnBsb3QocmhfZWRhZF9kaWFzX25vcm0pCiMgTsO6bWVybyDDs3B0aW1vIGRlIGNsw7pzdGVycyBjb24gIkVsYm93IFBsb3QiCmZ2aXpfbmJjbHVzdChyaF9lZGFkX2RpYXNfbm9ybSwga21lYW5zLCBtZXRob2Q9IndzcyIpKyAKICBnZW9tX3ZsaW5lKHhpbnRlcmNlcHQ9NiwgbGluZXR5cGU9MikrICAgICAgICAgICAKICBsYWJzKHN1YnRpdGxlID0gIkVsYm93IG1ldGhvZCIpICAKYGBgCgpEZSBhY3VlcmRvIGFsIGVsYm93IG1ldGhvZCwgZWwgbnVtZXJvIMOzcHRpbW8gZGUgY2x1c3RlcnMgc29uIDYgcGVybyBhbCBtb21lbnRvIGRlIHZpc3VhbGl6YXJsbyBzZSBkZXRlcm1pbsOzIHF1ZSBlcyB1bmEgZWxldmFkYSBjYW50aWRhZCBkZSBjbHVzdGVycyB5IG5vIHNlcsOtYSB0YW4gc2VuY2lsbG8gZWwgaW50ZXJwcmV0YXIgeSBub21icmFyIHRhbnRvcyBjbHVzdGVycyBwb3IgbG8gcXVlIHNlIGxsZWfDsyBhIGxhIGNvbmNsdXNpw7NuIHF1ZSBzZSBlbGFib3JhcsOhbiA1IGNsdXN0ZXJzLgoKYGBge3J9CiMgVmlzdWFsaXphciBDbHVzdGVycwpjbHVzdGVyMSA8LWttZWFucyhyaF9lZGFkX2RpYXNfbm9ybSw1KQpjbHVzdGVyMQpmdml6X2NsdXN0ZXIoY2x1c3RlcjEsZGF0YT1yaF9lZGFkX2RpYXNfbm9ybSkKYGBgCgpJbnRlcnByZXRhY2nDs246IENsdXN0ZXIgbsO6bWVybyAxIHkgNCBzb24gZGUgZWRhZGVzIGRpZmVyZW50ZXMgcGVybyB0aWVuZW4gZMOtYXMgbGFib3JhZG9zIHNpbWlsYXJlcywgaWd1YWwgcXVlIGVsIGNsdXN0ZXIgMyB5IDUgLiBQb3Igb3RybyBsYWRvLCBlbCBjbHVzdGVyIDIgc29uIGRhdG9zIHF1ZSBubyB0aWVuZW4gZMOtYXMgbGFib3JhZG9zIHNpbWlsYXJlcyBwZXJvIHRpZW5lbiBtw6FzIGTDrWFzIHF1ZSBsb3Mgb3Ryb3MgY2x1c3RlcnMgeSB0aWVuZSB1biByYW5nbyBkaWZlcmVudGUgZGUgZWRhZGVzLiBQb3IgbG8gcXVlIHNlIGNvbmNsdXllIHF1ZSBsb3MgZMOtYXMgbGFib3JhZG9zIG5vIHRpZW5lbiB0YW50YSByZWxhY2nDs24gY29uIGxhIGVkYWQuIAoKIyMjIENsdXN0ZXIgMjogRWRhZCB5IFNhbGFyaW8gRGlhcmlvCmBgYHtyfQojIE5vcm1hbGl6YXIgVmFyaWFibGVzCnJoX2VkYWRfc2FsIDwtcmgyICU+JSBzZWxlY3Qoc2FsYXJpb19kaWFyaW9faW1zcywgZWRhZCwgZGlhc19sYWJvcmFkb3MpCnJoX2VkYWRfc2FsX25vcm08LXNjYWxlKHJoX2VkYWRfZGlhc1sxOjJdKSAKcGxvdChyaF9lZGFkX3NhbF9ub3JtKQojIE7Dum1lcm8gw7NwdGltbyBkZSBjbMO6c3RlcnMgY29uICJFbGJvdyBQbG90Igpmdml6X25iY2x1c3QocmhfZWRhZF9zYWxfbm9ybSwga21lYW5zLCBtZXRob2Q9IndzcyIpKyAKICBnZW9tX3ZsaW5lKHhpbnRlcmNlcHQ9NSwgbGluZXR5cGU9MikrICAgICAgICAgICAKICBsYWJzKHN1YnRpdGxlID0gIkVsYm93IG1ldGhvZCIpICAKYGBgClNlIGRldGVybWluw7MgcXVlIGVsIG7Dum1lcm8gw7NwdGltbyBlcyBkZSA1IGNsdXN0ZXJzCgpgYGB7cn0KIyBWaXN1YWxpemFyIENsdXN0ZXJzCmNsdXN0ZXIyIDwta21lYW5zKHJoX2VkYWRfc2FsX25vcm0sNSkKY2x1c3RlcjIKZnZpel9jbHVzdGVyKGNsdXN0ZXIyLGRhdGE9cmhfZWRhZF9zYWxfbm9ybSkKYGBgCgpJbnRlcnByZXRhY2nDs246IFRvZG9zIHRpZW5lbiB1biBzYWxhcmlvIHNpbWlsYXIgc2luIGltcG9ydGFyIGxhIGVkYWQgcGVybyBlbiBlbCBjbHVzdGVyIDEgKHF1ZSBzb2xvIGVzIHVuIHB1bnRvKSBub3MgaW5kaWNhIHF1ZSBoYXkgYWxndWllbiBxdWUgZ2FuYSBtw6FzIHF1ZSBsb3MgZGVtw6FzIGNvbGFib3JhZG9yZXMgeSB0aWVuZW4gdW5hIGVkYWQgcmVsYXRpdmFtZW50ZSBqb3ZlbiBhIGNvbXBhcmFjacOzbiBkZSBsb3MgZGVtw6FzIGRhdG9zCgojIyMgQ2x1c3RlciAzOiBOw7ptZXJvIGRlIGTDrWFzIGxhYm9yYWRvcyB5IFNhbGFyaW8gRGlhcmlvCmBgYHtyfQojIE5vcm1hbGl6YXIgVmFyaWFibGVzCnJoX2RpYXNfc2FsIDwtcmgyICU+JSBzZWxlY3Qoc2FsYXJpb19kaWFyaW9faW1zcywgZGlhc19sYWJvcmFkb3MsIGVkYWQpCnJoX2RpYXNfc2FsX25vcm08LXNjYWxlKHJoX2RpYXNfc2FsWzE6Ml0pIApwbG90KHJoX2RpYXNfc2FsX25vcm0pCiMgTsO6bWVybyDDs3B0aW1vIGRlIGNsw7pzdGVycyBjb24gIkVsYm93IFBsb3QiCmZ2aXpfbmJjbHVzdChyaF9kaWFzX3NhbF9ub3JtLCBrbWVhbnMsIG1ldGhvZD0id3NzIikrIAogIGdlb21fdmxpbmUoeGludGVyY2VwdD01LCBsaW5ldHlwZT0yKSsgICAgICAgICAgIAogIGxhYnMoc3VidGl0bGUgPSAiRWxib3cgbWV0aG9kIikgIApgYGAKClNlIGRldGVybWluw7MgcXVlIGVsIG7Dum1lcm8gw7NwdGltbyBlcyBkZSA1IGNsdXN0ZXJzCgpgYGB7cn0KIyBWaXN1YWxpemFyIENsdXN0ZXJzCmNsdXN0ZXIzIDwta21lYW5zKHJoX2RpYXNfc2FsX25vcm0sNSkKY2x1c3RlcjMKZnZpel9jbHVzdGVyKGNsdXN0ZXIzLGRhdGE9cmhfZGlhc19zYWxfbm9ybSkKYGBgCgpJbnRlcnByZXRhY2nDs246IExvcyBkw61hcyBsYWJvcmFkb3Mgbm8gdGllbmVuIGluZmx1ZW5jaWEgZW4gZWwgc2FsYXJpbyBwb3JxdWUgaGF5IGRhdG9zIHF1ZSBpbmRpY2FuIGNvbGFib3JhZG9yZXMgcXVlIHRyYWJhamFuIG3DoXMgZMOtYXMgcGVybyB0aWVuZW4gdW4gc2FsYXJpbyBzaW1pbGFyIGEgbG9zIHF1ZSBubyB0aWVuZW4gdGFudG9zIGTDrWFzIGxhYm9yYWRvcy4gRW4gZWwgY2x1c3RlciAyIHBvZGVtb3Mgb2JzZXJ2YXIgcXVlIGVzIGVsIHF1ZSB0aWVuZSB1biBtYXlvciBzYWxhcmlvIHBlcm8gbm8gZXMgZWwgcXVlIHRpZW5lIHVuYSBjYW50aWRhZCBhbHRhIGRlIGTDrWFzIGxhYm9yYWRvcyBjb21vIGVzIGVuIGVsIGNsdXN0ZXIgMS4gUG9yIGxvIHRhbnRvLCBsb3MgZMOtYXMgbGFib3JhZG9zIG5vIHRpZW5lbiByZWxhY2nDs24gY29uIGVsIHNhbGFyaW8uIAoKIyMgKkNyZWFjacOzbiBkZSBzZWdtbWVudG9zIHVzYW5kbyBlbCBjbHVzdGVyIDI6IEVkYWQgeSBTYWxhcmlvIERpYXJpbyoKYGBge3J9CiMgSW5jbHVpciBjb2x1bW5hIHF1ZSBpbmRpcXVlIGVsIGNsdXN0ZXIgZGUgY2FkYSByZWdpc3RybwpyaDMgPC0gcmgyCnJoMyRDbHVzdGVyczwtY2x1c3RlcjIkY2x1c3RlcgoKIyB2aXN1YWxpemFyIGxhIG3DoXhpbWEgZWRhZCBkZSBjYWRhIGNsdXN0ZXIKcmg0IDwtIHJoMyAlPiUgZ3JvdXBfYnkoQ2x1c3RlcnMpICU+JSBzdW1tYXJpc2UoZWRhZD1tYXgoZWRhZCkpICU+JSBhcnJhbmdlKGRlc2MoZWRhZCkpCgojIE5vbWJyYXIgY2FkYSBjbHVzdGVyIApyaDMkbm9tYnJlc19jbHVzdGVycyA8LSBmYWN0b3IocmgzJENsdXN0ZXJzLGxldmVscyA9IGMoMSwyLDMsNCw1KSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxhYmVscz1jKCJFeGNlcGNpb24iLCAiSnViaWxhZG9zIiwgIk1heW9yZXMiLCAiQWR1bHRvcyIsICJKb3ZlbmVzIikpCgojIEFncnVwYXIgbG9zIGRhdG9zIHBvciBub21icmUgZGUgY2x1c3RlcnMgCmxpYnJhcnkoZHBseXIpCnJoNSA8LSByaDMgJT4lIGdyb3VwX2J5KG5vbWJyZXNfY2x1c3RlcnMpICU+JSBzdW1tYXJpemUoZWRhZF9hw7Fvcz1tYXgoZWRhZCksIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2FsYXJpb19pbXNzPW1lYW4oc2FsYXJpb19kaWFyaW9faW1zcyksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBDb3VudD1uKCkpCgpjbHVzdGVyczwtYXMuZGF0YS5mcmFtZShyaDUpCmNsdXN0ZXJzCmBgYAoKIyMgKkdyw6FmaWNvcyBjb21wbGVtZW50YXJpb3MqIAojIyMgR3LDoWZpY28gcG9yIG5vbWJyZSBkZSBjbHVzdGVyIApgYGB7cn0KZ2dwbG90KHJoNSxhZXMoeD1yZW9yZGVyKG5vbWJyZXNfY2x1c3RlcnMsQ291bnQpLHk9Q291bnQsZmlsbD1ub21icmVzX2NsdXN0ZXJzKSkgKwogIGdlb21fYmFyKHN0YXQ9ImlkZW50aXR5IikKYGBgCgpJbnRlcnByZXRhY2nDs246IExvcyBqw7N2ZW5lcyBhZHVsdG9zIHNvbiBsb3MgcXVlIHJlcHJlc2VudGFuIG3DoXMgbsO6bWVybyBkZSBiYWphcyB5IHNlIHZpc3VhbGl6YSBxdWUgZWwgb3JkZW4gZGUgbsO6bWVybyBkZSBiYWphcyBlc3RhIGVuIGVsIG1pc21vIG9yZGVuIGRlIGVkYWQsIGVzdG8gc2lnbmlmaWNhIHF1ZSBkZXNwdcOpcyBkZSBsb3MgasOzdmVuZXMgYWR1bHRvcyBlbCBncnVwbyBxdWUgbcOhcyByZXByZXNlbnRhIGJhamFzIGVzIGVsIGRlIGxvcyBhZHVsdG9zIHkgZGUgYWjDrSBzaWd1ZW4gbG9zIG1heW9yZXMsIHkgcG9yIMO6bHRpbW8gbG9zIGp1YmlsYWRvcy4gRW4gY29uY2x1c2nDs24sIGxhIGVkYWQgcHVlZGUgc2VyIHVuIGZhY3RvciBpbXBvcnRhbnRlIGVuIGVsIG7Dum1lcm8gZGUgYmFqYXMuCgojIyMgR3LDoWZpY28gZGVsIG3DoXhpbW8gZGUgZWRhZCBkZSBjYWRhIGNsdXN0ZXIKYGBge3J9CmdncGxvdChyaDUsIGFlcyh4PW5vbWJyZXNfY2x1c3RlcnMseT1lZGFkX2HDsW9zLGZpbGw9IG5vbWJyZXNfY2x1c3RlcnMsbGFiZWw9cm91bmQoZWRhZF9hw7FvcyxkaWdpdHM9MikpKSArIAogIGdlb21fY29sKCkgKyAKICBnZW9tX3RleHQoKQpgYGAKCkludGVycHJldGFjacOzbjogQXF1w60gc2Ugb2JzZXJ2YSBsYSBtw6F4aW1hIGRlIGVkYWQgZGUgY2FkYSBjbHVzdGVyIHkgdGFtYmnDqW4gbXVlc3RyYSBsYSByYXrDs24gcG9yIGxhIHF1ZSBzZSBkaWVyb24gbG9zIG5vbWJyZXMgYSBjYWRhIGNsdXN0ZXIuIExvcyBqw7N2ZW5lcyB0aWVuZW4gdW4gcmFuZ28gZGUgZWRhZCBkZSAxOS0yNiwgQWR1bHRvcyAyNy0zNiwgTWF5b3JlcyAzNy00MyB5IEp1YmlsYWRvcyA0NC02MS4KCiMjIyBHw6luZXJvIGRlIGV4LWNvbGFib3JhZG9yZXMKYGBge3J9CmxpYnJhcnkoZ2dwbG90MikKZ2dwbG90KHJoMywgYWVzKGZpbGw9Z2VuZXJvLCB5PWdlbmVybywgeD1ub21icmVzX2NsdXN0ZXJzKSkgKyAKICBnZW9tX2Jhcihwb3NpdGlvbj0ic3RhY2siLCBzdGF0PSJpZGVudGl0eSIpIApgYGAKCkludGVycHJldGFjacOzbjogRW4gbGEgZ3LDoWZpY2Egc2UgYXByZWNpYSB1biBuw7ptZXJvIGFsdG8gZGUgZ8OpbmVybyBtYXNjdWxpbm8gZW4gdG9kb3MgbG9zIGNsdXN0ZXJzLiBFbiBKdWJpbGFkb3MgeSBNYXlvcmVzIGVsIGfDqW5lcm8gRmVtZW5pbm8gZXMgbWF5b3IgcXVlIGVsIG1hc2N1bGluby4gCgojIyMgTW90aXZvIGRlIGJhamEgZGUgZXgtY29sYWJvcmFkb3JlcwpgYGB7cn0KZ2dwbG90KHJoMywgYWVzKGZhY3Rvcihub21icmVzX2NsdXN0ZXJzKSwgZmlsbCA9IGZhY3Rvcihtb3Rpdm9fZGVfYmFqYSkpKSArCiAgZ2VvbV9iYXIocG9zaXRpb24gPSBwb3NpdGlvbl9kb2RnZTIocHJlc2VydmUgPSAic2luZ2xlIikpCmBgYAoKSW50ZXJwcmV0YWNpw7NuOiAgU2UgcHVlZGUgb2JzZXJ2YXIgcXVlIGVsIG1vdGl2byBkZSBiYWphIG1hcyBncmFuZGUgZW4gdG9kb3MgbG9zIGdydXBvcyBkZSBlZGFkZXMgZXMgbGEgYmFqYSBwb3IgZmFsdGFzLCBzZWd1aWRvIGRlIHJlbnVuY2lhIHZvbHVudGFyaWEuIEVuIGrDs3ZlbmVzIHNlIHB1ZWRlIG9ic2VydmFyIHF1ZSBoYXkgYmFqYSBwb3IgYWJhbmRvbm8sIG1pZW50cmFzIHF1ZSBlbiBsb3Mgb3Ryb3MgY2x1c3RlcnMgbm8gaHVibyBuaW5ndW5hIGJhamEgcG9yIGFiYW5kb25vLiAKCiMjIyBQdWVzdG8gZGUgZGUgZXgtY29sYWJvcmFkb3JlcyAgCmBgYHtyfQpsaWJyYXJ5KHBseXIpCmNvdW50KHJoMyRwdWVzdG8pCnByb3BvcmNpb25lcyA8LSBjKDE3NiwgMTEsIDExLCA4LCAyNikKZXRpIDwtIGMoImF5dWRhbnRlIGdlbmVyYWwiLCAiYXl1LiBzb2xkYWRvci9zb2xkYWRvciIsICJjb3N0dXJlcmEiLCAiYXl1LiBlbWJhcnF1ZSIsICJvdHJvcyIgKQpwY3QgPC0gcm91bmQocHJvcG9yY2lvbmVzL3N1bShwcm9wb3JjaW9uZXMpKjEwMCkKZXRpIDwtIHBhc3RlKGV0aSwgcGN0KQpldGkgPC0gcGFzdGUoZXRpLCIlIixzZXA9IiIpCnBpZTNEKHByb3BvcmNpb25lcyxsYWJlbHMgPSBldGksCiAgICBjb2w9cmFpbmJvdyhsZW5ndGgoZXRpKSksCiAgICBtYWluPSJQdWVzdG9zIGRlIGJhamFzIikKYGBgCgpJbnRlcnByZXRhY2nDs246IGVsIHB1ZXN0byBlbiBlbCBxdWUgbcOhcyBzZSBwcmVzZW50YW4gYmFqYXMgZXMgZW4gYXl1ZGFudGUgZ2VuZXJhbCwgc2VndWlkbyBkZSBheXVkYW50ZSBzb2xkYWRvci9zb2xkYWRvciwgY29zdHVyZXJhLCBldGMuIFVuYSBkZSBsYXMgcG9zaWJsZXMgcmF6b25lcyBwb3IgbGEgcXVlIGhheWEgbcOhcyBiYWphcyBlbiBheXVkYW50ZSBnZW5lcmFsLCBlcyBwb3JxdWUgZW4gZXNlIHB1ZXN0byBzZSBuZWNlc2l0YW4gbcOhcyBjb2xhYm9yYWRvcmVzLCBwb3IgbG8gcXVlIGVsIG7Dum1lcm8gZGUgYmFqYXMgZW4gZXNlIHB1ZXN0byBwdWVkZSBzZXIgbWF5b3IgbyB0YW1iacOpbiBwdWVkZSBzZXIgZWwgYW1iaWVudGUgZ2VuZXJhbCBxdWUgc2UgY3JlYSBlbiBlc2UgcHVlc3RvLCBlc3TDoXMgaGlwb3TDqXNpcyBzZSBjb21wcm9iYXLDrWFuIGNvbiB1biBhbsOhbGlzaXMgbcOhcyBwcm9mdW5kbyBkZSBSSC4gCgojIyMgRXN0YWRvIGNpdmlsIGRlIGV4LWNvbGFib3JhZG9yZXMgCmBgYHtyfQpnZ3Bsb3QocmgzLCBhZXMoZmFjdG9yKG5vbWJyZXNfY2x1c3RlcnMpLCBmaWxsID0gZmFjdG9yKGVzdGFkb19jaXZpbCkpKSArCiAgZ2VvbV9iYXIocG9zaXRpb24gPSBwb3NpdGlvbl9kb2RnZTIocHJlc2VydmUgPSAic2luZ2xlIikpCgpwcm9wb3JjaW9uZXMxIDwtIGMoMTA3LCAzLCA1OSwgNjMpCmV0aXF1ZXRhcyA8LSBjKCJzb2x0ZXJvIiwgImRpdm9yY2lvIiwgInVuaW9uIGxpYnJlIiwgIm1hdHJpbW9uaW8iKQpwY3QgPC0gcm91bmQocHJvcG9yY2lvbmVzMS9zdW0ocHJvcG9yY2lvbmVzMSkqMTAwKQpldGlxdWV0YXMgPC0gcGFzdGUoZXRpcXVldGFzLCBwY3QpCmV0aXF1ZXRhcyA8LSBwYXN0ZShldGlxdWV0YXMsIiUiLHNlcD0iIikKcGllM0QocHJvcG9yY2lvbmVzMSxsYWJlbHMgPSBldGlxdWV0YXMsCiAgICAgIGNvbD1yYWluYm93KGxlbmd0aChldGlxdWV0YXMpKSwKICAgICAgbWFpbj0iRXN0YWRvIGNpdmlsIGRlIGJhamFzIikKYGBgCgpJbnRlcnByZXRhY2nDs246IEVuIGVsIHRvdGFsIGRlIGJhamFzIGVsIGVzdGFkbyBjaXZpbCBtw6FzIGNvbcO6biBlcyAic29sdGVybyIsIHNpZW5kbyBsb3MgasOzdmVuZXMgbG9zIHF1ZSB0aWVuZW4gdW5hIG1heW9yIGNhbnRpZGFkIGRlIGVzdGUgYXRyaWJ1dG8sIHNlZ3VpZG8gZGUgIGxvcyBhZHVsdG9zLiBEZXNwdcOpcywgZXN0w6EgZWwgbWF0cmltb25pbyBzaWVuZG8gZXN0ZSBlbCBtw6FzIHByZXNlbnRlIGVuIGVsIGdydXBvIGRlIGFkdWx0b3MsIHNlZ3VpZG8gZGUgbG9zIGrDs3ZlbmVzLiBFbCBkaXZvcmNpbyBubyBlcyB0w6FuIGNvbcO6biBlbiBsb3MgZ3J1cG9zLiAKCkVuIGNvbmNsdXNpw7NuLCBzZSBwdWVkZSBkZWR1Y2lyIHF1ZSBsYSBtYXlvcsOtYSBkZSBsb3MgZXgtY29sYWJvcmFkb3JlcyBzb24gc29sdGVyb3MsIHBvciBsbyBxdWUgZXMgbcOhcyBmw6FjaWwgcmVudW5jaWFyIGFsIG5vIHRlbmVyIHVuYSBleHRlbnNhIHkvbyBwcm9waWEgZmFtaWxpYS4gWWEgcXVlIGxvcyBzb2x0ZXJvcyBzb24gbGEgbWF5b3LDrWEsIHBvciBlbmRlIGxvcyBqw7N2ZW5lcyBzb24gbG9zIG3DoXMgcHJvcGVuc29zCmVuIGRhcnNlIGRlIGJhamEgZW4gRk9STS4gCgojICoqMy4gUHJpbmNpcGFsZXMgaGFsbGF6Z29zKioKCi0gU2kgYmllbiwgbGEgZW1wcmVzYSBoYWNlIG1lbmNpw7NuIGRlIGluY2VudGl2b3Mgc2FsYXJpYWxlcyBhIGxvcyBjb2xhYm9yYWRvcmVzLCBsb3MgZGF0b3MgY2FwdHVyYWRvcyB5IGNvbXBhcnRpZG9zIHBvciBwYXJ0ZSBkZSBsYSBvcmdhbml6YWNpw7NuIHVuaWNhbWVudGUgbXVlc3RyYW4gbG9zIHNhbGFyaW9zIGZpam9zIChlcyBkZWNpciwgaW5kZXBlbmRpZW50ZW1lbnRlIGRlIGhvcmFzIGV4dHJhKSB5IHBvciBjb25zaWd1aWVudGUsIHNlIHB1ZWRlIGNvcnJlbGFjaW9uYXIgcXVlIG5vIG5lY2VzYXJpYW1lbnRlIGxhIGVkYWQgdGllbmUgdW5hIHJlbGFjacOzbiBvIGltcGFjdG8gZGlyZWN0byBhbCBuaXZlbCBkZSBzYWxhcmlvIG90b3JnYWRvIGEgbG9zIGNvbGFib3JhZG9yZXMsIGNvbiBleGNlcGNpw7NuIGRlIHVuYSBwZXJzb25hOiB0cmF0YW5kb3NlIGRlbCBkdWXDsW8vZGlyZWN0b3IsIHF1aWVuIHBvc2VlIHVuIHNhbGFyaW8gbWF5b3IsIHNpZW5kbyBlc3RlIG1lbm9yIHF1ZSBtdWNob3MgY29sYWJvcmFkb3JlcyBwcmVzZW50ZXMgZW4gbGEgZXN0cnVjdHVyYSBvcmdhbml6YWNpb25hbC4gIAoKLSBQcmltZXJhbWVudGUsIHNlIGRlbXVlc3RyYSBxdWUgc2kgYmllbiwgZWwgc2FsYXJpbyBkZSBsb3MgY29sYWJvcmFkb3JlcyBjb3JyZXNwb25kZSBjb3JyZWN0YW1lbnRlIGRlIGFjdWVyZG8gYSBzdSBjb250cmF0bzsgZXN0cmljdGFtZW50ZSByZWZpcmllbmRvc2UgYWwgc2FsYXJpbyBJTVNTLCBubyBzZSBtdWVzdHJhIHVuYSBkaWZlcmVuY2lhIGVuIGxvcyBzYWxhcmlvcyBjb24gbGEgZXhjZXBjacOzbiBkZSB1bmEgcGVyc29uYSBxdWllbiBzZSBpbmZpZXJlIGVzIGVsIGRpcmVjdG9yL2R1ZcOxbyBkZSBsYSBlbXByZXNhIHF1aWVuIGRlYmlkbyBhIHN1IHBvc2ljacOzbiBqZXLDoXJxdWljYSwgZ296YSBkZSBtZWpvciBzYWxhcmlvL2JlbmVmaWNpb3MgZGVsIElNU1MuIAoKLSBFbnRyZSBtw6FzIGrDs3ZlbiBzZSBlcywgbWF5b3IgbGEgcHJvYmFiaWxpZGFkIGRlIGRhcnNlIGRlIGJhamEgZGUgbGEgZW1wcmVzYS4gIAoKLSBFeGlzdGVuIGdydXBvcyBkZSBlZGFkLCBsb3MgY3VhbGVzIGNvbnN0YW4gZGU6IEFkdWx0b3MgasOzdmVuZXMsIEFkdWx0b3MsIEFkdWx0b3MgbWF5b3JlcyB5IEp1YmlsYWRvcywgcXVlIGZvcm1hbiBwYXJ0ZSBkZSBsYSBvcmdhbml6YWNpw7NuLiAgICAKCi0gRWwgZ2VuZXJvIGZlbWVuaW5vIHRpZW5lIG1heW9yIHByZXNlbmNpYSBlbiBlbCBncnVwbyBkZSBlZGFkIGRlIGp1YmlsYWRvcyB5IGFkdWx0b3MgbWF5b3JlcywgZW4gY29tcGFyYWNpw7NuIGNvbiBsb3MgZ3J1cG9zIGRlIEFkdWx0b3MgeSBKb3ZlbmVzLCBkb25kZSBzZSB0aWVuZSBtYXlvciBwcmVzZW5jaWEgcG9yIHBhcnRlIGRlbCBnZW5lcm8gbWFzY3VsaW5vLiBDb24gZXN0bywgc2UgcHVlZGUgaW5mZXJpciBjb24gc3VzdGVudG8gcXVlIGxhIHByZXNlbmNpYSBkZSBtdWplcmVzIGVuIGdydXBvcyBkZSBlZGFkIG1hcyBhdmFuemFkYSBlcyBkZWJpZG8gYSBxdWUgc29uIG1hZHJlcyBzb2x0ZXJhcyB5L28gcmVjdXJyZW4gYSBsaW5lYXMgZGUgdHJhYmFqbyBkZSBlc3RlIHRpcG8gcGFyYSBkYXIgc3VzdGVudG8geSBjb250cmlidWlyIGEgbGEgZWNvbm9tw61hIGZhbWlsaWFyLiAgCgotIEVsIGdydXBvIGNvbiBtw6FzIGJhamFzIGVuIHRvZGFzIGxhcyBjYXRlZ29yw61hcyBkZSBkaWNoYSBhY3RpdmlkYWQgZXMgZWwgZGUgSsOzdmVuZXMsIGNvbiBsYSBwZWN1bGlhcmlkYWQgZGUgcXVlIGV4aXN0ZW4gcGVyc29uYXMgcXVlIHNpbXBsZW1lbnRlIGRlamFuIGRlIGFzaXN0aXIgYSBzdXMgbGFib3Jlcy4gICAKCi0gUmVzcGVjdG8gYSBsYXMgYmFqYXMgZW4gZnVuY2nDs24gZGUgbG9zIGRpZmVyZW50ZXMgcHVlc3RvcyBleGlzdGVudGVzIGVuIGxhIHBsYW50YSwgc2UgcHVlZGUgc3VzdGVudGFyIHF1ZSBkb25kZSBleGlzdGVuIG3DoXMgYmFqYXMgZXMgZW4gZWwgcHVlc3RvIGRlIOKAnEF5dWRhbnRlIGdlbmVyYWzigJ0gKHJlcHJlc2VudGEgZWwgNzYlIGRlIGxhcyBiYWphcyB0b3RhbGVzKSBwb3IgbG8gcXVlIHNlIHB1ZWRlIGluZmVyaXIgcXVlIGFsIHNlciBlbCBwdWVzdG8gY29uIG1heW9yIGRlbWFuZGEsIHZhY2FudGVzIG9mcmVjaWRhcyB5IGNvbGFib3JhZG9yZXMgcXVpZW5lcyBwYXJ0aWNpcGFuIGVuIGRpY2hhIGFyZWEsIHRpZW5lIHNlbnRpZG8gcXVlIGRlc3RhcXVlbiBsYXMgYmFqYXMgY29uIHJlc3BlY3RvIGEgbG9zIG90cm9zIHB1ZXN0YXMuIEVuIG90cmFzIHBhbGFicmFzLCBlbCBuw7ptZXJvIGRlIGJhamFzIGVzIHByb3BvcmNpb25hbCBhbCBuw7ptZXJvIGRlIGNvbGFib3JhZG9yZXMgcHJlc2VudGVzIGVuIGNhZGEgcHVlc3RvLiAgCgojICoqUHJvcHVlc3RhcyoqIAoKLSBFbGV2YXIgbml2ZWxlcyBzYWxhcmlhbGVzIHkvbyBwcmVzdGFjaW9uZXMgZGUgYWN1ZXJkbyBhIGxhIGFudGlnw7xlZGFkIHkgZXhwZXJpZW5jaWEgcHJldmlhIGRlbCBjb2xhYm9yYWRvci4gCgotIERhZGEgbGEgY29ycmVsYWNpw7NuIGRlIGxhIGVkYWQgasOzdmVuIHkgbGEgY29uY2VudHJhY2nDs24gZGUgY29sYWJvcmFkb3JlcyBxdWUgc2UgZGFuIGRlIGJhamEsIHNlIHByb3BvbmUgdW4gcHJvZ3JhbWEgZGUgcmV0ZW5jacOzbiBkZSB0YWxlbnRvLCBlbCBjdWFsIGVuIGNvbmp1bnRvIGNvbiBhcmVhcyBhZmluZXMgYSBjdWx0dXJhIG9yZ2FuaXphY2lvbmFsIChSUi5ISCksIHF1ZSBzZSBlbmNhcmd1ZSBkZXNkZSB1biBpbmljaW8gZGUgYXRyYWVyIGVsIG1lam9yIHRhbGVudG8sIGRlc2Fycm9sbGFybG8sIHJldGVuZXJsbyB5IGRhciBzZWd1aW1pZW50byBhIHN1IOKAnGVtcGxveWVlIGpvdXJuZXnigJ0gcGFyYSBldml0YXIgZXNhcyBiYWphcy4gICAKCi0gRGlzZcOxYXIgdW4gcHJvZ3JhbWEgZGUgYXBveW8gYSBtYWRyZXMgc29sdGVyYXMgeS9vIGNvbiBuZWNlc2lkYWQgZWNvbsOzbWljYSwgZG9uZGUgc2UgZGVuIHByZXN0YWNpb25lcyBhZGljaW9uYWxlcyAobm8gbmVjZXNhcmlhbWVudGUgZGUgY29udGV4dG8gc2FsYXJpYWwpIGVuZm9jYWRhcyBoYWNpYSBsb3MgaGlqb3MvYXMgZGUgbGFzIGNvbGFib3JhZG9yZXMgY29tbyBwb3IgZWplbXBsbywgYXBveW8gZW4gbWF0ZXJpYWwgZXNjb2xhciwgY29taWRhIHByZXBhcmFkYSBwYXJhIGx1bmNoZXMsIGVudHJlIG90cmFzIHByZXN0YWNpb25lcyBxdWUgY29udHJpYnV5YW4gYSBsYSByZXRlbmNpw7NuIGRlIGxhIGNvbGFib3JhZG9yYSwgeSBzZSBhcG95ZSBhIGxhIG5lY2VzaWRhZCwgeSBwb3IgY29uc2lndWllbnRlIHJhesOzbiBkZSB0cmFiYWphciBlbiBGb3JtLiAgCgotIEluc3RhdXJhciB1bmEgcG9sw610aWNhIHkvbyBwcm9jZXNvIGluc3RpdHVjaW9uYWwgZG9uZGUgZWwgY29sYWJvcmFkb3IgZGViYSBpbmRpY2FyIHN1IGJhamEgZGUgbGEgZW1wcmVzYSBjb24gMSDigJMgMiBzZW1hbmFzIGRlIGFudGVsYWNpw7NuLCB5YSBxdWUgZGUgZXN0YSBtYW5lcmEgdGllbmVuIGxhIHBvc2liaWxpZGFkIGRlIHNlciBhY3JlZWRvcmVzIGEgdW5hIGluZGVtbml6YWNpw7NuLCB5IHBvciBvdHJhIHBhcnRlLCBsYSBlbXByZXNhIHB1ZWRlIGNvbWVuemFyIHVuIG51ZXZvIHByb2Nlc28gZGUgYXRyYWNjacOzbiBkZSB0YWxlbnRvIHNpbiBhZmVjdGFyIGxhIHByb2R1Y3RpdmlkYWQgZGUgbGEgcGxhbnRhLiAgCgotIFByb2dyYW1hIGRlIHJldGVuY2nDs24gZGUgdGFsZW50byAjMjogQ29tbyBzZSBlc3RhYmxlY2nDsyBwcmV2aWFtZW50ZSwgZWwgbsO6bWVybyBkZSBiYWphcyBlcyBwcm9wb3JjaW9uYWwgYWwgbsO6bWVybyBkZSBjb2xhYm9yYWRvcmVzIHByZXNlbnRlcyBlbiBjYWRhIHB1ZXN0bywgcG9yIGxvIHF1ZSBlc3BlY8OtZmljYW1lbnRlIHBhcmEgZWwgYXl1ZGFudGUgZ2VuZXJhbCwgZG9uZGUgaGF5IG1heW9yIG7Dum1lcm8gZGUgY29sYWJvcmFkb3JlcywgZXMgaW1wb3J0YW50ZSBvZnJlY2VyIG1heW9yZXMgYmVuZWZpY2lvcyBwYXJhIGVsIGNvbGFib3JhZG9yLCBtZWpvcmVzIGNvbmRpY2lvbmVzIGRlIHRyYWJham8sIGludGVncmFjacOzbiBjb24gZWwgZXF1aXBvLCBlbnRyZSBvdHJhcyBhY2Npb25lcyBxdWUgYXB1bnRlbiBhIG1pdGlnYXIgZW4gbG8gcG9zaWJsZSwgbGEgYmFqYSBkZSBlc3RhcyBwZXJzb25hcyBlbiBlc3RlIHB1ZXN0by4gICAKCioqQmlibGlvZ3JhZsOtYSoqCkZyb3N0LCBKLiAoMjAyMiwgQXVndXN0IDMxKS4gV2hhdCBpcyBLIG1lYW5zIGNsdXN0ZXJpbmc/IHdpdGggYW4gZXhhbXBsZS4gU3RhdGlzdGljcyBCeSBKaW0uIFJldHJpZXZlZCBPY3RvYmVyIDksIDIwMjIsIGZyb20gaHR0cHM6Ly9zdGF0aXN0aWNzYnlqaW0uY29tL2Jhc2ljcy9rLW1lYW5zLWNsdXN0ZXJpbmcvIzp+OnRleHQ9VGhlJTIwSyUyMG1lYW5zJTIwY2x1c3RlcmluZyUyMGFsZ29yaXRobSxncm91cHMlMjB5b3UlMjBzcGVjaWZ5JTIwKEspLiAKSGFycmlzb24sIE8uICgyMDE5LCBKdWx5IDE0KS4gTWFjaGluZSBsZWFybmluZyBiYXNpY3Mgd2l0aCB0aGUgSy1uZWFyZXN0IG5laWdoYm9ycyBhbGdvcml0aG0uIE1lZGl1bS4gUmV0cmlldmVkIE9jdG9iZXIgOSwgMjAyMiwgZnJvbSBodHRwczovL3Rvd2FyZHNkYXRhc2NpZW5jZS5jb20vbWFjaGluZS1sZWFybmluZy1iYXNpY3Mtd2l0aC10aGUtay1uZWFyZXN0LW5laWdoYm9ycy1hbGdvcml0aG0tNmE2ZTcxZDAxNzYxIApNaXNocmEsIFMuICgyMDE3LCBNYXkgMjEpLiBVbnN1cGVydmlzZWQgbGVhcm5pbmcgYW5kIGRhdGEgY2x1c3RlcmluZy4gTWVkaXVtLiBSZXRyaWV2ZWQgT2N0b2JlciA5LCAyMDIyLCBmcm9tIGh0dHBzOi8vdG93YXJkc2RhdGFzY2llbmNlLmNvbS91bnN1cGVydmlzZWQtbGVhcm5pbmctYW5kLWRhdGEtY2x1c3RlcmluZy1lZWVjYjc4YjQyMmEjOn46dGV4dD1DbHVzdGVyaW5nJTIwY2FuJTIwYmUlMjBjb25zaWRlcmVkJTIwdGhlLGFyZSUyMHNpbWlsYXIlMjBpbiUyMHNvbWUlMjB3YXklRTIlODAlOUQuIApNb2RpZmljYXRpb25zLiBldWNsaWRlYW5fY2x1c3Rlci4gKG4uZC4pLiBSZXRyaWV2ZWQgT2N0b2JlciA5LCAyMDIyLCBmcm9tIGh0dHBzOi8vYXV0b3dhcmVmb3VuZGF0aW9uLmdpdGxhYi5pby9hdXRvd2FyZS5hdXRvL0F1dG93YXJlQXV0by9ldWNsaWRlYW4tY2x1c3Rlci1kZXNpZ24uaHRtbAoKCg==