Contexto
Una empresa de e-commerce quiere evaluar el impacto de una nueva
campaña de marketing sobre sus ventas diarias. Tienen
datos de ventas antes y después de la campaña y desean determinar si la
campaña tuvo un efecto significativo en el aumento de las ventas.
Dado que los datos de ventas pueden tener alta variabilidad y
dependencia temporal, se decide usar el doble bootstrap
para mejorar la estimación del intervalo de confianza del efecto de la
campaña.
Herramientas para la simulación
Cargar librerías
library(boot)
library(utils)
Leer base de datos y Exploración
venta <- read.csv("C:\\Users\\aleja\\Documents\\00_Carrera_y_formación\\00_TEC_Por semestre_LIT\\SEMESTRE_8\\Bases_de_Datos\\dataset_ventas.csv")
head(venta)
## dia ventas periodo
## 1 1 83.71554 antes
## 2 2 114.96018 antes
## 3 3 104.24468 antes
## 4 4 77.40558 antes
## 5 5 91.32100 antes
## 6 6 124.77155 antes
Crear subconjuntos para determinar
impacto de la campaña
venta_antes<-venta[venta$periodo == "antes",]
head(venta_antes)
## dia ventas periodo
## 1 1 83.71554 antes
## 2 2 114.96018 antes
## 3 3 104.24468 antes
## 4 4 77.40558 antes
## 5 5 91.32100 antes
## 6 6 124.77155 antes
venta_despues<-venta[venta$periodo == "despues",]
head(venta_despues)
## dia ventas periodo
## 91 1 127.25308 despues
## 92 2 90.98972 despues
## 93 3 112.71553 despues
## 94 4 127.66793 despues
## 95 5 104.97484 despues
## 96 6 125.46672 despues
Bootstrapping Sencillo
Calcular media y aplicar
bootstrapping sencillo.
#Función para calcular la media
bootstrap_media <- function(data, indices) {
return(mean(data[indices]))
}
set.seed(386)
#Aplicar Bootstrap con 100000 repeticiones
Rbootstrap_va <- boot(data = venta_antes$ventas, statistic = bootstrap_media, R = 100000)
#Mostrar resumen de resultados
print(Rbootstrap_va)
##
## ORDINARY NONPARAMETRIC BOOTSTRAP
##
##
## Call:
## boot(data = venta_antes$ventas, statistic = bootstrap_media,
## R = 1e+05)
##
##
## Bootstrap Statistics :
## original bias std. error
## t1* 100.5368 0.00116431 1.815028
#Calcular Intervalo de Confianza del 95%
intervalo_conf <- boot.ci(Rbootstrap_va, type = "perc")
print("Intervalo de confianza de ventas anteriores_________________")
## [1] "Intervalo de confianza de ventas anteriores_________________"
print(intervalo_conf)
## BOOTSTRAP CONFIDENCE INTERVAL CALCULATIONS
## Based on 100000 bootstrap replicates
##
## CALL :
## boot.ci(boot.out = Rbootstrap_va, type = "perc")
##
## Intervals :
## Level Percentile
## 95% ( 97.0, 104.1 )
## Calculations and Intervals on Original Scale
hist(Rbootstrap_va$t, main = "Distribución Bootstrap de la Media (Ventas Anteriores)",
xlab = "Media Remuestreada", col = "powderblue", border = "black")

#Aplicar Bootstrap con 100000 repeticiones
Rbootstrap_vd <- boot(data = venta_despues$ventas, statistic = bootstrap_media, R = 100000)
#Mostrar resumen de resultados
print(Rbootstrap_vd)
##
## ORDINARY NONPARAMETRIC BOOTSTRAP
##
##
## Call:
## boot(data = venta_despues$ventas, statistic = bootstrap_media,
## R = 1e+05)
##
##
## Bootstrap Statistics :
## original bias std. error
## t1* 110.5493 0.01502967 1.484184
#Calcular Intervalo de Confianza del 95%
intervalo_conf2 <- boot.ci(Rbootstrap_vd, type = "perc")
print("Intervalo de confianza de ventas posteriores_________________")
## [1] "Intervalo de confianza de ventas posteriores_________________"
print(intervalo_conf2)
## BOOTSTRAP CONFIDENCE INTERVAL CALCULATIONS
## Based on 100000 bootstrap replicates
##
## CALL :
## boot.ci(boot.out = Rbootstrap_vd, type = "perc")
##
## Intervals :
## Level Percentile
## 95% (107.7, 113.5 )
## Calculations and Intervals on Original Scale
hist(Rbootstrap_vd$t, main = "Distribución Bootstrap de la Media (Ventas Posteriores)",
xlab = "Media Remuestreada", col = "powderblue", border = "black")

Aplicación de Doble Bootstrapping
set.seed(386)
#f(): Calcular promedio de ventas
ventas_av <- function(data,indices){
muestraE <- data[indices, ]
return(mean(muestraE$ventas))
}
#f(): Realizar simulación de Doble bootstrapping
doble_bootstrap <- function(data, n_outer, n_inner) {
set.seed(386)
outer_results <- replicate(n_outer, {
outer_sample <- data[sample(nrow(data), 90, replace = TRUE), ] # Muestra de 9 días de venta
inner_boot <- boot(data = outer_sample, statistic = ventas_av, R = n_inner)
return(mean(inner_boot$t)) #Promedio de ventas en el nivel interno
})
return(outer_results)
}
#Aplicamos el doble bootstrapping
n_outer <- 1000 #Muestras bootstrap externas
n_inner <- 750 #Muestras bootstrap internas
doble_resultados_A <- doble_bootstrap(venta_antes, n_outer, n_inner)
doble_resultados_D <- doble_bootstrap(venta_despues, n_outer, n_inner)
#Calcular intervalos de confianza al 95%
conf_intervals <- quantile(doble_resultados_A, probs = c(0.025, 0.975))
#Mostrar resultados
cat("Calificación promedio estimada:", mean(doble_resultados_A), "\n")
## Calificación promedio estimada: 100.5336
cat("Intervalo de confianza al 95%:", conf_intervals[1], "-", conf_intervals[2], "\n")
## Intervalo de confianza al 95%: 97.01549 - 104.136
#Calcular intervalos de confianza al 95%
conf_intervals <- quantile(doble_resultados_D, probs = c(0.025, 0.975))
#Mostrar resultados
cat("Calificación promedio estimada:", mean(doble_resultados_D), "\n")
## Calificación promedio estimada: 110.5021
cat("Intervalo de confianza al 95%:", conf_intervals[1], "-", conf_intervals[2], "\n")
## Intervalo de confianza al 95%: 107.5073 - 113.5529
Conclusión Comparativa
Resultados con
100,000 iteraciones de bootstrapp de primer nivel
Medias:
- Antes: $100.53 por venta
- Después: $110.54 por venta
Intervalos:
- Antes: ( 97.0, 104.1 )
- Después: (107.7, 113.5 )
Resultados con n_outer = 1000
& n_inner = 750 de iteraciones de bootstrapp de segundo
nivel
Medias:
- Antes: $100.53 por venta
- Después: $110.50 por venta
Intervalos:
- Antes: ( 97.01, 104.13 )
- Después: (107.50, 113.55 )
En ambos métodos de simulaciones podemos observar un valor similar
tanto en intervalos como en medias. Esto puede deberse a que ambos
tienen una muestra bastante grande así como un número de iteraciones
altas.
¿La campaña tuvo un impacto significativo?
Según las dos simulación realizadas puedo concluir que,
efectivamente, la campaña tuvo un impacto significativo subiendo un 10%
la media de ventas
LS0tDQp0aXRsZTogIkRvdWJsZV9Cb290c3RyYXBwaW5nX0VtcHJlc2FfRWNvbW1lcmNlX0E3NDkiDQphdXRob3I6ICJTYW1hbnRoYSAtIEEwMTQyMjc0OSINCmRhdGU6ICIyMDI1LTA4LTIwIg0Kb3V0cHV0Og0KICBodG1sX2RvY3VtZW50Og0KICAgICB0b2M6IFRSVUUNCiAgICAgdG9jX2Zsb2F0OiBUUlVFDQogICAgIGNvZGVfZG93bmxvYWQ6IFRSVUUNCiAgICAgdGhlbWU6IHlldGkNCi0tLQ0KPGNlbnRlcj4NCiFbXShodHRwczovL2Nkbi5kcmliYmJsZS5jb20vdXNlcnVwbG9hZC80MTkzMzI4Ni9maWxlL29yaWdpbmFsLTFmNzBlYmMyYjExOGQwNzEyMjdlOTVjMDRhZWJkYTUwLmdpZikNCjwvY2VudGVyPg0KDQojIDxiPiA8c3BhbiBzdHlsZT0iY29sb3I6ICNDRDEwNzY7Ij4gQ29udGV4dG8gPC9zcGFuPiA8L2I+DQoNClVuYSBlbXByZXNhIGRlIGUtY29tbWVyY2UgcXVpZXJlIGV2YWx1YXIgZWwgaW1wYWN0byBkZSB1bmEgbnVldmEgY2FtcGHDsWEgZGUgbWFya2V0aW5nIHNvYnJlIHN1cyAqKnZlbnRhcyBkaWFyaWFzKiouIFRpZW5lbiBkYXRvcyBkZSB2ZW50YXMgYW50ZXMgeSBkZXNwdcOpcyBkZSBsYSBjYW1wYcOxYSB5IGRlc2VhbiBkZXRlcm1pbmFyIHNpIGxhIGNhbXBhw7FhIHR1dm8gdW4gZWZlY3RvIHNpZ25pZmljYXRpdm8gZW4gZWwgYXVtZW50byBkZSBsYXMgdmVudGFzLg0KDQpEYWRvIHF1ZSBsb3MgZGF0b3MgZGUgdmVudGFzIHB1ZWRlbiB0ZW5lciBhbHRhIHZhcmlhYmlsaWRhZCB5IGRlcGVuZGVuY2lhIHRlbXBvcmFsLCBzZSBkZWNpZGUgdXNhciBlbCAqKmRvYmxlIGJvb3RzdHJhcCoqIHBhcmENCm1lam9yYXIgbGEgZXN0aW1hY2nDs24gZGVsIGludGVydmFsbyBkZSBjb25maWFuemEgZGVsIGVmZWN0byBkZSBsYSBjYW1wYcOxYS4NCg0KDQojIyA8c3BhbiBzdHlsZT0iY29sb3I6IHBpbms7ICI+IEluZm9ybWFjacOzbiBkZSBsYSBEYXRhIDwvc3Bhbj4NCg0KRGF0b3M6DQoNClNlIGRpc3BvbmUgZGUgdW4gZGF0YXNldCBjb24gOTAgZMOtYXMgZGUgdmVudGFzIGFudGVzIGRlIGxhIGNhbXBhw7FhIHkgOTAgZMOtYXMgZGVzcHXDqXMgZGUgbGEgY2FtcGHDsWEuDQoNCioqVmFyaWFibGVzIGRlbCBkYXRhc2V0OioqDQoNCisgRMOtYTogRXMgbGEgZXRpcXVldGEgY29ycmVzcG9uZGllbnRlIGFsIGTDrWEgZGUgbGEgdmVudGEuDQorIFZlbnRhczogRXMgZWwgbW9udG8gZGUgdmVudGEgcmVzdWx0YW50ZS4gDQorIFBlcmlvZG86IEluZGljYSBzaSBsYSB2ZW50YSBlcyBwcmV2aWEgbyBwb3N0ZXJpb3IgYSBsYSBpbXBsZW1lbnRhY2nDs24gZGUgbGEgY2FtcGHDsWEuDQoNCiMgPGI+IDxzcGFuIHN0eWxlPSJjb2xvcjojQ0QxMDc2OyAiPiBIZXJyYW1pZW50YXMgcGFyYSBsYSBzaW11bGFjacOzbiAgPC9zcGFuPiA8L2I+DQoNCiMjIDxzcGFuIHN0eWxlPSJjb2xvcjogcmVkIDsiPiBDYXJnYXIgbGlicmVyw61hcyA8L3NwYW4+DQpgYGB7cn0NCmxpYnJhcnkoYm9vdCkNCmxpYnJhcnkodXRpbHMpDQoNCmBgYA0KDQojIyA8c3BhbiBzdHlsZT0iY29sb3I6IHJlZCA7Ij4gTGVlciBiYXNlIGRlIGRhdG9zIHkgRXhwbG9yYWNpw7NuIDwvc3Bhbj4NCmBgYHtyfQ0KdmVudGEgPC0gcmVhZC5jc3YoIkM6XFxVc2Vyc1xcYWxlamFcXERvY3VtZW50c1xcMDBfQ2FycmVyYV95X2Zvcm1hY2nDs25cXDAwX1RFQ19Qb3Igc2VtZXN0cmVfTElUXFxTRU1FU1RSRV84XFxCYXNlc19kZV9EYXRvc1xcZGF0YXNldF92ZW50YXMuY3N2IikNCmhlYWQodmVudGEpDQpgYGANCg0KIyMgPHNwYW4gc3R5bGU9ImNvbG9yOiByZWQgOyI+IENyZWFyIHN1YmNvbmp1bnRvcyBwYXJhIGRldGVybWluYXIgaW1wYWN0byBkZSBsYSBjYW1wYcOxYTwvc3Bhbj4NCmBgYHtyfQ0KdmVudGFfYW50ZXM8LXZlbnRhW3ZlbnRhJHBlcmlvZG8gPT0gImFudGVzIixdDQpoZWFkKHZlbnRhX2FudGVzKQ0KDQp2ZW50YV9kZXNwdWVzPC12ZW50YVt2ZW50YSRwZXJpb2RvID09ICJkZXNwdWVzIixdDQpoZWFkKHZlbnRhX2Rlc3B1ZXMpDQpgYGANCg0KIyA8Yj4gPHNwYW4gc3R5bGU9ImNvbG9yOiAjQ0QxMDc2IDsiPiBCb290c3RyYXBwaW5nIFNlbmNpbGxvIDwvc3Bhbj4gPC9iPg0KDQojIyA8c3BhbiBzdHlsZT0iY29sb3I6IGJsYWNrICA7Ij4gQ2FsY3VsYXIgbWVkaWEgeSBhcGxpY2FyIGJvb3RzdHJhcHBpbmcgc2VuY2lsbG8uICA8L3NwYW4+DQoNCmBgYHtyfQ0KDQojRnVuY2nDs24gcGFyYSBjYWxjdWxhciBsYSBtZWRpYQ0KYm9vdHN0cmFwX21lZGlhIDwtIGZ1bmN0aW9uKGRhdGEsIGluZGljZXMpIHsNCiAgcmV0dXJuKG1lYW4oZGF0YVtpbmRpY2VzXSkpICANCn0NCg0Kc2V0LnNlZWQoMzg2KSANCg0KI0FwbGljYXIgQm9vdHN0cmFwIGNvbiAxMDAwMDAgcmVwZXRpY2lvbmVzDQpSYm9vdHN0cmFwX3ZhIDwtIGJvb3QoZGF0YSA9IHZlbnRhX2FudGVzJHZlbnRhcywgc3RhdGlzdGljID0gYm9vdHN0cmFwX21lZGlhLCBSID0gMTAwMDAwKQ0KDQojTW9zdHJhciByZXN1bWVuIGRlIHJlc3VsdGFkb3MNCnByaW50KFJib290c3RyYXBfdmEpDQoNCiNDYWxjdWxhciBJbnRlcnZhbG8gZGUgQ29uZmlhbnphIGRlbCA5NSUNCmludGVydmFsb19jb25mIDwtIGJvb3QuY2koUmJvb3RzdHJhcF92YSwgdHlwZSA9ICJwZXJjIikNCnByaW50KCJJbnRlcnZhbG8gZGUgY29uZmlhbnphIGRlIHZlbnRhcyBhbnRlcmlvcmVzX19fX19fX19fX19fX19fX18iKQ0KcHJpbnQoaW50ZXJ2YWxvX2NvbmYpDQoNCg0KaGlzdChSYm9vdHN0cmFwX3ZhJHQsIG1haW4gPSAiRGlzdHJpYnVjacOzbiBCb290c3RyYXAgZGUgbGEgTWVkaWEgKFZlbnRhcyBBbnRlcmlvcmVzKSIsDQogICAgIHhsYWIgPSAiTWVkaWEgUmVtdWVzdHJlYWRhIiwgY29sID0gInBvd2RlcmJsdWUiLCBib3JkZXIgPSAiYmxhY2siKQ0KDQojQXBsaWNhciBCb290c3RyYXAgY29uIDEwMDAwMCByZXBldGljaW9uZXMNClJib290c3RyYXBfdmQgPC0gYm9vdChkYXRhID0gdmVudGFfZGVzcHVlcyR2ZW50YXMsIHN0YXRpc3RpYyA9IGJvb3RzdHJhcF9tZWRpYSwgUiA9IDEwMDAwMCkNCg0KI01vc3RyYXIgcmVzdW1lbiBkZSByZXN1bHRhZG9zDQpwcmludChSYm9vdHN0cmFwX3ZkKQ0KDQojQ2FsY3VsYXIgSW50ZXJ2YWxvIGRlIENvbmZpYW56YSBkZWwgOTUlDQppbnRlcnZhbG9fY29uZjIgPC0gYm9vdC5jaShSYm9vdHN0cmFwX3ZkLCB0eXBlID0gInBlcmMiKQ0KcHJpbnQoIkludGVydmFsbyBkZSBjb25maWFuemEgZGUgdmVudGFzIHBvc3RlcmlvcmVzX19fX19fX19fX19fX19fX18iKQ0KcHJpbnQoaW50ZXJ2YWxvX2NvbmYyKQ0KDQoNCmhpc3QoUmJvb3RzdHJhcF92ZCR0LCBtYWluID0gIkRpc3RyaWJ1Y2nDs24gQm9vdHN0cmFwIGRlIGxhIE1lZGlhIChWZW50YXMgUG9zdGVyaW9yZXMpIiwNCiAgICAgeGxhYiA9ICJNZWRpYSBSZW11ZXN0cmVhZGEiLCBjb2wgPSAicG93ZGVyYmx1ZSIsIGJvcmRlciA9ICJibGFjayIpDQoNCg0KYGBgDQoNCiMgPGI+IDxzcGFuIHN0eWxlPSJjb2xvcjogI0NEMTA3NjsiPiBBcGxpY2FjacOzbiBkZSBEb2JsZSBCb290c3RyYXBwaW5nIDwvc3Bhbj4gPC9iPg0KYGBge3J9DQpzZXQuc2VlZCgzODYpDQoNCiNmKCk6IENhbGN1bGFyIHByb21lZGlvIGRlIHZlbnRhcw0KdmVudGFzX2F2IDwtIGZ1bmN0aW9uKGRhdGEsaW5kaWNlcyl7DQogIG11ZXN0cmFFIDwtIGRhdGFbaW5kaWNlcywgXQ0KICByZXR1cm4obWVhbihtdWVzdHJhRSR2ZW50YXMpKQ0KfQ0KDQoNCiNmKCk6IFJlYWxpemFyIHNpbXVsYWNpw7NuIGRlIERvYmxlIGJvb3RzdHJhcHBpbmcNCmRvYmxlX2Jvb3RzdHJhcCA8LSBmdW5jdGlvbihkYXRhLCBuX291dGVyLCBuX2lubmVyKSB7DQogIHNldC5zZWVkKDM4NikNCiAgb3V0ZXJfcmVzdWx0cyA8LSByZXBsaWNhdGUobl9vdXRlciwgew0KICAgIG91dGVyX3NhbXBsZSA8LSBkYXRhW3NhbXBsZShucm93KGRhdGEpLCA5MCwgcmVwbGFjZSA9IFRSVUUpLCBdICAjIE11ZXN0cmEgZGUgOSBkw61hcyBkZSB2ZW50YQ0KICAgIGlubmVyX2Jvb3QgPC0gYm9vdChkYXRhID0gb3V0ZXJfc2FtcGxlLCBzdGF0aXN0aWMgPSB2ZW50YXNfYXYsIFIgPSBuX2lubmVyKQ0KICAgIHJldHVybihtZWFuKGlubmVyX2Jvb3QkdCkpICAjUHJvbWVkaW8gZGUgdmVudGFzIGVuIGVsIG5pdmVsIGludGVybm8NCiAgfSkNCiAgDQogIHJldHVybihvdXRlcl9yZXN1bHRzKQ0KfQ0KDQojQXBsaWNhbW9zIGVsIGRvYmxlIGJvb3RzdHJhcHBpbmcNCm5fb3V0ZXIgPC0gMTAwMCAgICAjTXVlc3RyYXMgYm9vdHN0cmFwIGV4dGVybmFzDQpuX2lubmVyIDwtIDc1MCAgICAjTXVlc3RyYXMgYm9vdHN0cmFwIGludGVybmFzDQoNCmRvYmxlX3Jlc3VsdGFkb3NfQSA8LSBkb2JsZV9ib290c3RyYXAodmVudGFfYW50ZXMsIG5fb3V0ZXIsIG5faW5uZXIpDQpkb2JsZV9yZXN1bHRhZG9zX0QgPC0gZG9ibGVfYm9vdHN0cmFwKHZlbnRhX2Rlc3B1ZXMsIG5fb3V0ZXIsIG5faW5uZXIpDQoNCg0KI0NhbGN1bGFyIGludGVydmFsb3MgZGUgY29uZmlhbnphIGFsIDk1JQ0KY29uZl9pbnRlcnZhbHMgPC0gcXVhbnRpbGUoZG9ibGVfcmVzdWx0YWRvc19BLCBwcm9icyA9IGMoMC4wMjUsIDAuOTc1KSkNCg0KI01vc3RyYXIgcmVzdWx0YWRvcw0KY2F0KCJDYWxpZmljYWNpw7NuIHByb21lZGlvIGVzdGltYWRhOiIsIG1lYW4oZG9ibGVfcmVzdWx0YWRvc19BKSwgIlxuIikNCmNhdCgiSW50ZXJ2YWxvIGRlIGNvbmZpYW56YSBhbCA5NSU6IiwgY29uZl9pbnRlcnZhbHNbMV0sICItIiwgY29uZl9pbnRlcnZhbHNbMl0sICJcbiIpDQoNCiNDYWxjdWxhciBpbnRlcnZhbG9zIGRlIGNvbmZpYW56YSBhbCA5NSUNCmNvbmZfaW50ZXJ2YWxzIDwtIHF1YW50aWxlKGRvYmxlX3Jlc3VsdGFkb3NfRCwgcHJvYnMgPSBjKDAuMDI1LCAwLjk3NSkpDQoNCiNNb3N0cmFyIHJlc3VsdGFkb3MNCmNhdCgiQ2FsaWZpY2FjacOzbiBwcm9tZWRpbyBlc3RpbWFkYToiLCBtZWFuKGRvYmxlX3Jlc3VsdGFkb3NfRCksICJcbiIpDQpjYXQoIkludGVydmFsbyBkZSBjb25maWFuemEgYWwgOTUlOiIsIGNvbmZfaW50ZXJ2YWxzWzFdLCAiLSIsIGNvbmZfaW50ZXJ2YWxzWzJdLCAiXG4iKQ0KYGBgDQoNCiMgPGI+IDxzcGFuIHN0eWxlPSJjb2xvcjogI0NEMTA3NjsiPiBDb25jbHVzacOzbiBDb21wYXJhdGl2YSAgPC9zcGFuPiA8L2I+IA0KDQojIyA8c3BhbiBzdHlsZT0iY29sb3I6IGJsYWNrICA7Ij4gUmVzdWx0YWRvcyBjb24gKioxMDAsMDAwKiogaXRlcmFjaW9uZXMgZGUgYm9vdHN0cmFwcCBkZSBwcmltZXIgbml2ZWwgPC9zcGFuPg0KDQoqTWVkaWFzOioNCg0KKiBBbnRlczogJDEwMC41MyBwb3IgdmVudGENCiogRGVzcHXDqXM6ICQxMTAuNTQgcG9yIHZlbnRhDQoNCipJbnRlcnZhbG9zOioNCg0KKiBBbnRlczogKCA5Ny4wLCAxMDQuMSApDQoqIERlc3B1w6lzOiAoMTA3LjcsIDExMy41ICkNCg0KDQojIyA8c3BhbiBzdHlsZT0iY29sb3I6IGJsYWNrICA7Ij4gUmVzdWx0YWRvcyBjb24gKipuX291dGVyID0gMTAwMCAmIG5faW5uZXIgPSA3NTAqKiBkZSBpdGVyYWNpb25lcyBkZSBib290c3RyYXBwIGRlIHNlZ3VuZG8gbml2ZWwgPC9zcGFuPg0KDQoqTWVkaWFzOioNCg0KKiBBbnRlczogJDEwMC41MyBwb3IgdmVudGENCiogRGVzcHXDqXM6ICQxMTAuNTAgcG9yIHZlbnRhDQoNCipJbnRlcnZhbG9zOioNCg0KKiBBbnRlczogKCA5Ny4wMSwgMTA0LjEzICkNCiogRGVzcHXDqXM6ICgxMDcuNTAsIDExMy41NSApIA0KDQpFbiBhbWJvcyBtw6l0b2RvcyBkZSBzaW11bGFjaW9uZXMgcG9kZW1vcyBvYnNlcnZhciB1biB2YWxvciBzaW1pbGFyIHRhbnRvIGVuIGludGVydmFsb3MgY29tbyBlbiBtZWRpYXMuIEVzdG8gcHVlZGUgZGViZXJzZSBhIHF1ZSBhbWJvcyB0aWVuZW4gdW5hIG11ZXN0cmEgYmFzdGFudGUgZ3JhbmRlIGFzw60gY29tbyB1biBuw7ptZXJvIGRlIGl0ZXJhY2lvbmVzIGFsdGFzLiANCg0KKirCv0xhIGNhbXBhw7FhIHR1dm8gdW4gaW1wYWN0byBzaWduaWZpY2F0aXZvPyoqDQoNClNlZ8O6biBsYXMgZG9zIHNpbXVsYWNpw7NuIHJlYWxpemFkYXMgcHVlZG8gY29uY2x1aXIgcXVlLCBlZmVjdGl2YW1lbnRlLCBsYSBjYW1wYcOxYSB0dXZvIHVuIGltcGFjdG8gc2lnbmlmaWNhdGl2byBzdWJpZW5kbyB1biAxMCUgbGEgbWVkaWEgZGUgdmVudGFzDQoNCg0KDQo=