¿Qué entendemos por inflación?
La inflación es un incremento sostenido del nivel general de precios de los bienes y servicios de una economía
Cálculo de la inflación
\[\pi_t = 100*\frac{IPC_t - IPC_{t-1}}{IPC_{t-1}}\]
ipc_historico<-read.csv("ipc_historico.csv",header = T,sep = ";",stringsAsFactors = F)
ipc_historico$indice_tiempo<-as.Date(ipc_historico$indice_tiempo,format = "%d/%m/%Y")
ipc_historico <- ipc_historico %>% mutate(inflacion_mensual = (ipc/lag(ipc) -1)*100,
inflacion_anual = (ipc/lag(ipc,12) -1)*100)
summary(ipc_historico)
indice_tiempo ipc salario dolar inflacion_mensual inflacion_anual
Min. :1943-01-01 Min. :2.000e+00 Min. : 14.08 Min. : 1.000 Min. : -6.072 Min. : -7.024
1st Qu.:1962-02-15 1st Qu.:9.000e+01 1st Qu.: 14.89 1st Qu.: 1.000 1st Qu.: 0.451 1st Qu.: 11.983
Median :1981-04-01 Median :1.985e+06 Median : 32.31 Median : 3.136 Median : 1.762 Median : 24.014
Mean :1981-04-01 Mean :2.115e+14 Mean :103.75 Mean : 6.522 Mean : 4.272 Mean : 194.022
3rd Qu.:2000-05-16 3rd Qu.:1.012e+14 3rd Qu.:121.47 3rd Qu.: 5.329 3rd Qu.: 4.622 3rd Qu.: 58.823
Max. :2019-07-01 Max. :4.440e+15 Max. :658.29 Max. :57.905 Max. :196.634 Max. :20262.873
NA's :4 NA's :4 NA's :623 NA's :618 NA's :5 NA's :16


Teorias de las Causas de la Inflacion:
“Para bajar la inflación soy monetarista, estructuralista y todo lo que sea necesario; y si hay que recurrir a la macumba, también” (Adolfo Canitrot, viceministro de Economía de Alfonsín’
1) Causas de corto plazo:
Impulsada por demanda: Exceso de demanda lleva a aumentos en los precios
Inflación impulsada por costos: contracciones de oferta generan aumentos de precios (i.e. Shock petrolero, devaluaciones en Arg.)
Fallas de coordinación: inercia inflacionaria
2) Causas de largo plazo: Si la tasa de crecimiento de la cantidad de dinero crece a un ritmo superior al crecimiento de la economía (cantidad de bienes y servicios), una mayor inflación es inevitable
- “Inflation is always and everywhere a monetary phenomenon.” (M. Friedman)
Interés para este trabajo
La inflación distorsiona los precios relativos (salario real, saldos reales, tipo de cambio real) y dificulta la comparación intertemporal de las variables. Tambien afecta la toma de decisiones de los agentes (la información es costosa y la inflación agrega ruído).
En ese marco, la inflación es un fenómeno que podría alterar el comportamiento de nuestras variables y no estamos considerando en el modelado del evento de interés. Esto podría estar afectar las conclusiones y resultados.
Vamos a ver tres formas de neutralizar el efecto de la inflación: deflactar por el IPC, deflactar por el tipo de cambio y usando rangos.
Preparación de las bases
Por un lado vamos a importar la base completa del paquete premium. Veamos que ventana de tiempo abarca la misma.
#
#mes<-unique(df$foto_mes)
#for (i in mes) {
# tmp <- df[foto_mes==i,]
# write_delim(x = tmp,path = paste0("../datasets/dias/", i, "_dias.txt"), delim = "\t")
#}
[1] 201805 201806 201807 201808 201809 201810 201811 201812 201901 201902 201903 201904
Reescalamos los índices para que sean base 201904=1
ipc_historico$foto_mes<- format(ipc_historico$indice_tiempo, "%Y%m")
ipc_historico$foto_mes<- as.numeric(ipc_historico$foto_mes)
ipc_historico<-ipc_historico %>% filter(foto_mes %in% unique(df$foto_mes))
ipc_historico <- ipc_historico %>% mutate(ipc = ipc/ipc[12],
salario = salario/salario[12],
dolar = dolar/dolar[12])
head(ipc_historico,15)
df<- df %>% left_join(ipc_historico, by=c('foto_mes'='foto_mes'))
Deflactar
Presentamos dos técnicas para “neutralizar” el efecto de la inflación en nuestro modelo. La primera forma consiste en deflactar las variables monetarias tomando como referencia la evolución del IPC. El IPC se construye eligiendo un año como “año base” al cual se le asigna un IPC de 100. A los años siguientes se le irá sumando la inflación al año base. Por ejemplo, si la inflación interanual entre el año base y el siguiente fue de 2%, el IPC de ese año será de 102. De la misma forma se procede para los años anteriores al año base, pero restando la inflación.
El calculo que vamos a realizar es:
\[\frac{VPC}{IPC}*100 \]
Con:
\(VPC = Valor\) \(en\) \(precios\) \(corrientes\) \(IPC = Indice\) \(de\) \(precios\) \(al\) \(Consumidor\).
El procedimiento será el mismo a la hora de deflactar por el Tipo de Cambio.
Deflactar por IPC
df['rent_12']=df$mrentabilidad/df$ipc
df['saldo_12']=df$mcuentas_saldo/df$ipc
df['sueldo_12']=df$mplan_sueldo/df$ipc
df['debitos_12']=df$mcuenta_debitos_automaticos/df$ipc
Deflactar por tipo de cambio
df['rent_usd']=df$mrentabilidad/df$dolar
df['saldo_usd']=df$mcuentas_saldo/df$dolar
df['sueldo_usd']=df$mplan_sueldo/df$dolar
df['debitos_usd']=df$mcuenta_debitos_automaticos/df$dolar
Deflactar por rangos
En segundo lugar, cuando deflactamos por rangos el procedimiento consiste en dividir el dataset en partes iguales (percentiles), de esta forma obtendremos un ordenamiento que es independiente de la magnitud de nuestras variables. Luego se evalúa pasaje de un rango al otro entre períodos.
df %>%
ggplot(aes(x = mrentabilidad, colour = as.factor(foto_mes) )) + geom_density()+xlim(0,5000)

df %>%
ggplot(aes(x = rent_12, colour = as.factor(foto_mes) )) + geom_density()+xlim(0,5000)

### Percentiles
meses<- unique(df$foto_mes)
beta=NULL
for (i in meses){
a<- which(df$foto_mes==i)
alpha<- df[a,c("numero_de_cliente", "foto_mes","mrentabilidad","mcuentas_saldo", "mplan_sueldo", "mcuenta_debitos_automaticos")]
alpha$mrentabilidad<-ecdf(alpha$mrentabilidad)(alpha$mrentabilidad)
alpha$mcuentas_saldo<-ecdf(alpha$mcuentas_saldo)(alpha$mcuentas_saldo)
alpha$mplan_sueldo<-ecdf(alpha$mplan_sueldo)(alpha$mplan_sueldo)
alpha$mcuenta_debitos_automaticos<-ecdf(alpha$mcuenta_debitos_automaticos)(alpha$mcuenta_debitos_automaticos)
beta=rbind(beta, alpha)
}
colnames(beta)<- c("numero_de_cliente", "foto_mes","rentabilidad_perc","saldo_perc", "sueldo_perc", "debitos_perc")
df<- df %>% left_join(beta)
Joining, by = c("numero_de_cliente", "foto_mes")
### Escalado (normalizado)
meses<- unique(df$foto_mes)
beta=NULL
for (i in meses){
a<- which(df$foto_mes==i)
alpha<- df[a,c("numero_de_cliente", "foto_mes","mrentabilidad","mcuentas_saldo", "mplan_sueldo", "mcuenta_debitos_automaticos")]
alpha$mrentabilidad<-scale(alpha$mrentabilidad)
alpha$mcuentas_saldo<-scale(alpha$mcuentas_saldo)
alpha$mplan_sueldo<-scale(alpha$mplan_sueldo)
alpha$mcuenta_debitos_automaticos<-scale(alpha$mcuenta_debitos_automaticos)
beta=rbind(beta, alpha)
}
colnames(beta)<- c("numero_de_cliente", "foto_mes","rentabilidad_norm","saldo_norm", "sueldo_norm", "debitos_norm")
df<- df %>% left_join(beta)
Joining, by = c("numero_de_cliente", "foto_mes")
Impacto en las Variables
En los gráficos a continuación se ve la evolución intermensual de las variables numéricas deflactadas y no deflactadas tomando un cliente particular. Como se puede apreciar, las trayectorias se mantienen prácticamente iguales, únicamente varían las unidades se magnitud.
Esto indica que muy probablemente no cabría esperar variaciones significativa en los resultados de los modelos.
head(df[45:74,],10)
set.seed(151515)
lista_clientes<-sample(x =unique(df$numero_de_cliente), size = 1 )
cliente<-df %>% filter(numero_de_cliente %in% lista_clientes)
attributes are not identical across measure variables; they will be dropped

attributes are not identical across measure variables; they will be dropped

attributes are not identical across measure variables; they will be dropped

attributes are not identical across measure variables; they will be dropped

Impacto en el modelo
A continuación, par aevaluar los efectos de la neutralización de la inflación en las variables nominales se entrenaron cuatro modelos, uno con las variables numéricas sin modificar, con las variables deflactadas por el IPC, deflactadas por el tipo de cambio y por rangos, usando los datos del mes de febrero y se lo fue probando en los meses siguientes. Se recopilaron las métricas de AUC y de ganancia y se comparó la evolución de dichas métricas para cada modelo.
|--------------------------------------------------|
|==================================================|
|--------------------------------------------------|
|==================================================|
Setting levels: control = 0, case = 1
Setting direction: controls < cases
Setting levels: control = 0, case = 1
Setting direction: controls < cases
Setting levels: control = 0, case = 1
Setting direction: controls < cases
Setting levels: control = 0, case = 1
Setting direction: controls < cases
Setting levels: control = 0, case = 1
Setting direction: controls < cases
Setting levels: control = 0, case = 1
Setting direction: controls < cases
Setting levels: control = 0, case = 1
Setting direction: controls < cases
Setting levels: control = 0, case = 1
Setting direction: controls < cases
Setting levels: control = 0, case = 1
Setting direction: controls < cases
Setting levels: control = 0, case = 1
Setting direction: controls < cases
|--------------------------------------------------|
|==================================================|
Setting levels: control = 0, case = 1
Setting direction: controls < cases
Setting levels: control = 0, case = 1
Setting direction: controls < cases
Setting levels: control = 0, case = 1
Setting direction: controls < cases
Setting levels: control = 0, case = 1
Setting direction: controls < cases
Setting levels: control = 0, case = 1
Setting direction: controls < cases
|--------------------------------------------------|
|==================================================|
Setting levels: control = 0, case = 1
Setting direction: controls < cases
Setting levels: control = 0, case = 1
Setting direction: controls < cases
Setting levels: control = 0, case = 1
Setting direction: controls < cases
Setting levels: control = 0, case = 1
Setting direction: controls < cases
Setting levels: control = 0, case = 1
Setting direction: controls < cases
|--------------------------------------------------|
|==================================================|
Setting levels: control = 0, case = 1
Setting direction: controls < cases
Setting levels: control = 0, case = 1
Setting direction: controls < cases
Setting levels: control = 0, case = 1
Setting direction: controls < cases
Setting levels: control = 0, case = 1
Setting direction: controls < cases
Setting levels: control = 0, case = 1
Setting direction: controls < cases
|--------------------------------------------------|
|==================================================|
Setting levels: control = 0, case = 1
Setting direction: controls < cases
Setting levels: control = 0, case = 1
Setting direction: controls < cases
Setting levels: control = 0, case = 1
Setting direction: controls < cases
Setting levels: control = 0, case = 1
Setting direction: controls < cases
Setting levels: control = 0, case = 1
Setting direction: controls < cases
|--------------------------------------------------|
|==================================================|
|--------------------------------------------------|
|==================================================|
Setting levels: control = 0, case = 1
Setting direction: controls < cases
Setting levels: control = 0, case = 1
Setting direction: controls < cases
Setting levels: control = 0, case = 1
Setting direction: controls < cases
Setting levels: control = 0, case = 1
Setting direction: controls < cases
Setting levels: control = 0, case = 1
Setting direction: controls < cases
|--------------------------------------------------|
|==================================================|
Setting levels: control = 0, case = 1
Setting direction: controls < cases
Setting levels: control = 0, case = 1
Setting direction: controls < cases
Setting levels: control = 0, case = 1
Setting direction: controls < cases
Setting levels: control = 0, case = 1
Setting direction: controls < cases
Setting levels: control = 0, case = 1
Setting direction: controls < cases
|--------------------------------------------------|
|==================================================|
|--------------------------------------------------|
|==================================================|
Setting levels: control = 0, case = 1
Setting direction: controls < cases
Setting levels: control = 0, case = 1
Setting direction: controls < cases
Setting levels: control = 0, case = 1
Setting direction: controls < cases
Setting levels: control = 0, case = 1
Setting direction: controls < cases
Setting levels: control = 0, case = 1
Setting direction: controls < cases
|--------------------------------------------------|
|==================================================|
Setting levels: control = 0, case = 1
Setting direction: controls < cases
Setting levels: control = 0, case = 1
Setting direction: controls < cases
Setting levels: control = 0, case = 1
Setting direction: controls < cases
Setting levels: control = 0, case = 1
Setting direction: controls < cases
Setting levels: control = 0, case = 1
Setting direction: controls < cases
|--------------------------------------------------|
|==================================================|
Setting levels: control = 0, case = 1
Setting direction: controls < cases
Setting levels: control = 0, case = 1
Setting direction: controls < cases
Setting levels: control = 0, case = 1
Setting direction: controls < cases
Setting levels: control = 0, case = 1
Setting direction: controls < cases
Setting levels: control = 0, case = 1
Setting direction: controls < cases
|--------------------------------------------------|
|==================================================|
Setting levels: control = 0, case = 1
Setting direction: controls < cases
Setting levels: control = 0, case = 1
Setting direction: controls < cases
Setting levels: control = 0, case = 1
Setting direction: controls < cases
Setting levels: control = 0, case = 1
Setting direction: controls < cases
Setting levels: control = 0, case = 1
Setting direction: controls < cases
auc_plot<-ggplot(auc_meses, aes(x = mes, y = value)) +
geom_line(aes(color = variable), size = 1) + theme_fivethirtyeight()+
theme(legend.text = element_text(size=7),axis.text.x = element_text(angle = 90, hjust = 1)) +
guides(col = guide_legend(nrow = 3))
grid.arrange(auc_plot, arrangeGrob(a, b), ncol = 2)

ganancia_plot<-ggplot(ganancia_meses, aes(x = mes, y = value,color = variable)) +
geom_line( size = 1) + theme_fivethirtyeight()+
theme(legend.text = element_text(size=7),axis.text.x = element_text(angle = 90, hjust = 1))+
guides(col = guide_legend(nrow = 3))
grid.arrange(ganancia_plot, arrangeGrob(a, b), ncol = 2)

auc_meses <- resultados %>%
select("mes", "auc_nominal", "auc_ipc",'auc_dolar') %>%
gather(key = "variable", value = "value", -mes)
auc_meses$mes<-as.Date(paste0(as.character(auc_meses$mes), '01'), format='%Y%m%d')
ganancia_meses <- resultados %>%
select("mes", "ganancia_nominal", "ganancia_ipc",'ganancia_dolar') %>%
gather(key = "variable", value = "value", -mes)
ganancia_meses$mes<-as.Date(paste0(as.character(ganancia_meses$mes), '01'), format='%Y%m%d')
auc_plot<-ggplot(auc_meses, aes(x = mes, y = value)) +
geom_line(aes(color = variable), size = 1) + theme_fivethirtyeight()+
theme(legend.text = element_text(size=7),axis.text.x = element_text(angle = 90, hjust = 1)) +
guides(col = guide_legend(nrow = 3))
grid.arrange(auc_plot, arrangeGrob(a, b), ncol = 2)

ganancia_plot<-ggplot(ganancia_meses, aes(x = mes, y = value,color = variable)) +
geom_line( size = 1) + theme_fivethirtyeight()+
theme(legend.text = element_text(size=7),axis.text.x = element_text(angle = 90, hjust = 1))+
guides(col = guide_legend(nrow = 3))
grid.arrange(ganancia_plot, arrangeGrob(a, b), ncol = 2)

LS0tDQp0aXRsZTogIkFqdXN0ZSBwb3IgaW5mbGFjacOzbiINCmF1dGhvcjogIlNhbnRpYWdvIFJvc3NpIg0KZGF0ZTogIjIxLzEwLzIwMTkiDQpvdXRwdXQ6IA0KICBodG1sX25vdGVib29rOiANCiAgICBmaWdfaGVpZ2h0OiAxMg0KICAgIGZpZ193aWR0aDogMTANCiAgICB0aGVtZTogc3BhY2VsYWINCiAgICB0b2M6IHllcw0KICAgIHRvY19mbG9hdDogeWVzDQotLS0NCg0KYGBge3Igc2V0dXAsIGluY2x1ZGU9RkFMU0UsIHdhcm5pbmc9RkFMU0V9DQpsaWJyYXJ5KHJlYWRyKQ0KbGlicmFyeShkcGx5cikNCmxpYnJhcnkoZGF0YS50YWJsZSkNCmxpYnJhcnkoZ2dwbG90MikNCmxpYnJhcnkoR0dhbGx5KQ0KbGlicmFyeSh0aWR5cikNCmxpYnJhcnkoeGdib29zdCkNCmxpYnJhcnkocFJPQykNCmxpYnJhcnkoZ2d0aGVtZXMpDQpsaWJyYXJ5KGdyaWRFeHRyYSkNCmBgYA0KDQojwr9RdcOpIGVudGVuZGVtb3MgcG9yIGluZmxhY2nDs24/DQoNCkxhIGluZmxhY2nDs24gZXMgdW4gKippbmNyZW1lbnRvIHNvc3RlbmlkbyBkZWwgbml2ZWwgZ2VuZXJhbCBkZSBwcmVjaW9zKiogZGUgbG9zIGJpZW5lcyB5IHNlcnZpY2lvcyBkZSB1bmEgZWNvbm9tw61hDQoNCg0KIyMgRm9ybWFzIGRlIG1lZGlyIGVsIG5pdmVsIGdlbmVyYWwgZGUgcHJlY2lvcw0KDQpfXzEpIERlZmxhY3RvciBkZWwgUElCX186IEVsIGRlZmxhY3RvciBkZWwgUElCICgkRFBJQiQpIGVzIHVuIMOtbmRpY2UgcXVlIG1pZGUgZWwgcHJlY2lvIG1lZGlvIGRlIGxvcyBiaWVuZXMgeSBzZXJ2aWNpb3MgcHJvZHVjaWRvcyBlbiB1biBhw7FvIGRlIHJlZmVyZW5jaWEuIA0KDQokJERQSUJfdCA9IFxmcmFje1xzdW1eTl97aT0xfXtwXmlfdC5xXmlfdH19e1xzdW1eTl97aT0xfXBeaV8wLnFeaV90fSoxMDAgPSAgXGZyYWN7XHRleHR7UElCIGEgcHJlY2lvcyBjb3JyaWVudGV9fXtcdGV4dHtQSUIgYSBwcmVjaW9zIGRlIGHDsW8gYmFzZX19JCQNCkNvbg0KDQoqICRxXmlfdCQgbGEgY2FudGlkYWQgZGVsIGJpZW4gaSBlbiBlbCBwZXLDrW9kbyB0IA0KKiAkcF5pX3QkIHByZWNpbyBkZWwgYmllbiBpIGVuIGVsIHBlcsOtb2RvIHQNCiogJHBeaV8wJCBlbCBwcmVjaW8gZGVsIGJpZW4gaSBlbiBlbCBwZXLDrW9kbyBkZSByZWZlcmVuY2lhIChlbiBBcmdlbnRpbmEgZXMgMjAwNCBhY3R1YWxtZW50ZSkNCg0KX18yKSBJbmZsYWNpw7NuIG1lZGlkYSBwb3IgZWwgSVBDX186IEVsIMOtbmRpY2UgZGUgcHJlY2lvcyBhbCBjb25zdW1pZG9yIChJUEMpIG1pZGUgZWwgY29zdG8gZGUgdW5hIGNhbmFzdGEgZGUgYmllbmVzIHkgc2VydmljaW9zIHF1ZSBsb3MgaG9nYXJlcyBzdWVsZW4gY29tcHJhciBlbiB1biBwZXLDrW9kbyBkZSByZWZlcmVuY2lhDQokJElQQ190ID0gXGZyYWN7XHN1bV5OX3tpPTF9e3BeaV90LnFeaV8wfX17XHN1bV5OX3tpPTF9cF5pXzAucV5pXzB9KjEwMCA9IFxmcmFje1x0ZXh0e0NhbmFzdGEgYSBwcmVjaW9zIGNvcnJpZW50ZXN9fXtcdGV4dHtDYW5hc3RhIGEgcHJlY2lvcyBkZSBwZXLDrW9kbyBkZSByZWZlcmVuY2lhfX0kJA0KDQpfXzMpIE90cmFzIG1lbm9zIGNvbm9jaWRhcyBfXzogRWwgw61uZGljZSBkZSBwcmVjaW9zIGFsIHBvciBtYXlvciAoSVBNKSBvIGVsIMOtbmRpY2UgZGUgcHJlY2lvcyBhbCBwcm9kdWN0b3IgKElQUCkNCg0KDQojIyBDw6FsY3VsbyBkZSBsYSBpbmZsYWNpw7NuDQoNCiQkXHBpX3QgPSAxMDAqXGZyYWN7SVBDX3QgLSBJUENfe3QtMX19e0lQQ197dC0xfX0kJA0KDQpgYGB7cn0NCmlwY19oaXN0b3JpY288LXJlYWQuY3N2KCJpcGNfaGlzdG9yaWNvLmNzdiIsaGVhZGVyID0gVCxzZXAgPSAiOyIsc3RyaW5nc0FzRmFjdG9ycyA9IEYpDQoNCmlwY19oaXN0b3JpY28kaW5kaWNlX3RpZW1wbzwtYXMuRGF0ZShpcGNfaGlzdG9yaWNvJGluZGljZV90aWVtcG8sZm9ybWF0ID0gIiVkLyVtLyVZIikNCg0KaXBjX2hpc3RvcmljbyA8LSBpcGNfaGlzdG9yaWNvICU+JSBtdXRhdGUoaW5mbGFjaW9uX21lbnN1YWwgPSAoaXBjL2xhZyhpcGMpIC0xKSoxMDAsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbmZsYWNpb25fYW51YWwgPSAoaXBjL2xhZyhpcGMsMTIpIC0xKSoxMDApDQoNCnN1bW1hcnkoaXBjX2hpc3RvcmljbykNCmBgYA0KDQpgYGB7ciwgZWNobz1GQUxTRSwgd2FybmluZz1GQUxTRX0NCg0KZ2dwbG90KGlwY19oaXN0b3JpY28sIGFlcyh4ID0gaW5kaWNlX3RpZW1wbywgeSA9IGluZmxhY2lvbl9hbnVhbCAsIGdyb3VwID0xKSkgKw0KICBnZW9tX2xpbmUoc2l6ZSA9IDEuNSwgY29sb3VyPSIjMTM4MEExIikgKw0KICBsYWJzKHRpdGxlID0gIklQQy4gVmFyaWFjacOzbiBhbnVhbC4gMTk0My0yMDE5ICIsDQogICAgICAgc3VidGl0bGUgPSAiRnVlbnRlOiBJTkRFQyB5IEdDQkEgKDIwMTItMjAxNikgeSBGSUVMICgyMDA3LTIwMTIpIikgKw0KICBsYWJzKHggPSAiWWVhciIsIHkgPSAiVVNEIG1pbGxpb24iKSArDQogIGdlb21faGxpbmUoeWludGVyY2VwdCA9IDApKw0KICB0aGVtZV9maXZldGhpcnR5ZWlnaHQoKSArIHNjYWxlX2NvbG91cl9maXZldGhpcnR5ZWlnaHQoKSArDQogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJib3R0b20iLCBsZWdlbmQuZGlyZWN0aW9uID0gImhvcml6b250YWwiLA0KICAgICAgICBsZWdlbmQudGl0bGUgPSBlbGVtZW50X2JsYW5rKCksYXhpcy50ZXh0LnggPWVsZW1lbnRfdGV4dChhbmdsZSA9IDkwKSkNCg0KYGBgDQoNCmBgYHtyLCBlY2hvPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQ0KDQpwPC1nZ3Bsb3QoaXBjX2hpc3RvcmljbywgYWVzKHggPSBpbmRpY2VfdGllbXBvLCB5ID0gaW5mbGFjaW9uX2FudWFsICwgZ3JvdXAgPTEpKSArDQogIGdlb21fbGluZShzaXplID0gMS41LGNvbG91cj0iIzEzODBBMSIpICsNCiAgbGFicyh0aXRsZSA9ICJJUEMuIFZhcmlhY2nDs24gYW51YWwuIDE5OTMgLSAyMDE5ICIsDQogICAgICAgc3VidGl0bGUgPSAiRnVlbnRlOiBJTkRFQyB5IEdDQkEgKDIwMTItMjAxNikgeSBGSUVMICgyMDA3LTIwMTIpIikgKw0KICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQgPSAwKSsNCiAgdGhlbWVfZml2ZXRoaXJ0eWVpZ2h0KCkgKyBzY2FsZV9jb2xvdXJfZml2ZXRoaXJ0eWVpZ2h0KCkgKw0KICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAiYm90dG9tIiwgbGVnZW5kLmRpcmVjdGlvbiA9ICJob3Jpem9udGFsIiwNCiAgICAgICAgbGVnZW5kLnRpdGxlID0gZWxlbWVudF9ibGFuaygpLGF4aXMudGV4dC54ID1lbGVtZW50X3RleHQoYW5nbGUgPSA5MCksDQogICAgICAgIHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE0LCBmYWNlID0gImJvbGQiKSkgKw0KICBsYWJzKHggPSAiQcOxbyIsIHkgPSAiaW5mbGFjacOzbiBhbnVhbCAoJSkiKSArDQogICBzY2FsZV94X2RhdGUobGltaXRzID0gYXMuRGF0ZShjKCcxOTkzLTAxLTAxJywnMjAxOS0wMS0wMScpKSkgKw0KICB5bGltKC01LDYwKQ0KDQpwDQpgYGANCg0KDQoNCiMjVGVvcmlhcyBkZSBsYXMgQ2F1c2FzIGRlIGxhIEluZmxhY2lvbjoNCg0KKiJQYXJhIGJhamFyIGxhIGluZmxhY2nDs24gc295IG1vbmV0YXJpc3RhLCBlc3RydWN0dXJhbGlzdGEgeSB0b2RvIGxvIHF1ZSBzZWEgbmVjZXNhcmlvOyB5IHNpIGhheSBxdWUgcmVjdXJyaXIgYSBsYSBtYWN1bWJhLCB0YW1iacOpbuKAnSAoQWRvbGZvIENhbml0cm90LCB2aWNlbWluaXN0cm8gZGUgRWNvbm9tw61hIGRlIEFsZm9uc8OtbicqDQoNCl9fMSkgQ2F1c2FzIGRlIGNvcnRvIHBsYXpvX186DQoNCiogSW1wdWxzYWRhIHBvciBkZW1hbmRhOiBFeGNlc28gZGUgZGVtYW5kYSBsbGV2YSBhIGF1bWVudG9zIGVuIGxvcyBwcmVjaW9zDQoNCiogSW5mbGFjacOzbiBpbXB1bHNhZGEgcG9yIGNvc3RvczogY29udHJhY2Npb25lcyBkZSBvZmVydGEgZ2VuZXJhbiBhdW1lbnRvcyBkZSBwcmVjaW9zIChpLmUuIFNob2NrIHBldHJvbGVybywgZGV2YWx1YWNpb25lcyBlbiBBcmcuKQ0KDQoqIEZhbGxhcyBkZSBjb29yZGluYWNpw7NuOiBpbmVyY2lhIGluZmxhY2lvbmFyaWENCg0KX18yKSBDYXVzYXMgZGUgbGFyZ28gcGxhem9fXzogU2kgbGEgdGFzYSBkZSBjcmVjaW1pZW50byBkZSBsYSBjYW50aWRhZCBkZSBkaW5lcm8gY3JlY2UgYSB1biByaXRtbyBzdXBlcmlvciBhbCBjcmVjaW1pZW50byBkZSBsYSBlY29ub23DrWEgKGNhbnRpZGFkIGRlIGJpZW5lcyB5IHNlcnZpY2lvcyksIHVuYSBtYXlvciBpbmZsYWNpw7NuIGVzIGluZXZpdGFibGUgDQoNCiog4oCcSW5mbGF0aW9uIGlzIGFsd2F5cyBhbmQgZXZlcnl3aGVyZSBhIG1vbmV0YXJ5IHBoZW5vbWVub24u4oCdDQogIChNLiBGcmllZG1hbikNCg0KDQpgYGB7ciwgZWNobz1GQUxTRSwgd2FybmluZz1GQUxTRX0NCg0KaXBjX2hpc3RvcmljbyA8LSBpcGNfaGlzdG9yaWNvICU+JSBtdXRhdGUoZGV2YV9hbnVhbCA9IChkb2xhci9sYWcoZG9sYXIsMTIpIC0xKSoxMDAsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzYWxhcmlvX2FudWFsID0gKHNhbGFyaW8vbGFnKHNhbGFyaW8sMTIpIC0xKSoxMDApDQoNCmdncGxvdChpcGNfaGlzdG9yaWNvLCBhZXMoeCA9IGluZGljZV90aWVtcG8sIHkgPSBpbmZsYWNpb25fYW51YWwpKSArDQogIGdlb21fbGluZShzaXplID0gMS41LGNvbG91cj0iIzEzODBBMSIpICsNCiAgbGFicyh0aXRsZSA9ICJJUEMsIFNhbGFyaW9zIHkgRMOzbGFyLiBWYXJpYWNpw7NuIGFudWFsLiAyMDEwIC0gMjAxOSAiLA0KICAgICAgIHN1YnRpdGxlID0gIkZ1ZW50ZTogSU5ERUMsIEZJRUwsIEdDQkEgeSBNaW5pc3RlcmlvIGRlIEhhY2llbmRhIikgKw0KICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQgPSAwKSsNCiAgdGhlbWVfZml2ZXRoaXJ0eWVpZ2h0KCkgKw0KICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAidG9wIiwNCiAgICAgICAgYXhpcy50ZXh0LnggPWVsZW1lbnRfdGV4dChhbmdsZSA9IDApLA0KICAgICAgICBwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNCwgZmFjZSA9ICJib2xkIikpICsNCiAgbGFicyh4ID0gIkHDsW8iLCB5ID0gIlZhcmlhY2nDs24gYW51YWwgKCUpIikgKw0KICBzY2FsZV94X2RhdGUobGltaXRzID0gYXMuRGF0ZShjKCcyMDEwLTAxLTAxJywnMjAxOS0wMS0wMScpKSkgKw0KICB5bGltKC01LDgwKSsNCiAgZ2VvbV9saW5lKGFlcyh5ID0gc2FsYXJpb19hbnVhbCksIGNvbG91cj0iI0ZBQUIxOCIsc2l6ZT0xLjUpK2dlb21fbGluZShhZXMoeSA9IGRldmFfYW51YWwpLCBjb2xvdXI9IiM5OTAwMDAiLHNpemU9MS41KSsNCiAgZ2VvbV9sYWJlbChhZXMoeCA9IGFzLkRhdGUoYygnMjAxMS0wMS0wMScpKSwgeSA9IDQ1LCBsYWJlbCA9ICJTYWxhcmlvcyIpLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgIGhqdXN0ID0gMCwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICB2anVzdCA9IDAuNSwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICBmaWxsID0gInRyYW5zcGFyZW50IiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgIGxhYmVsLnNpemUgPSBOQSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbG91ciA9ICIjRkFBQjE4IiwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICBzaXplID0gNikrDQogIGdlb21fbGFiZWwoYWVzKHggPSBhcy5EYXRlKGMoJzIwMTQtMTItMDEnKSksIHkgPSA3MCwgbGFiZWwgPSAiRMOzbGFyIiksIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgaGp1c3QgPSAwLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgIHZqdXN0ID0gMC41LCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgIGZpbGwgPSAidHJhbnNwYXJlbnQiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgbGFiZWwuc2l6ZSA9IE5BLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgY29sb3VyID0gIiM5OTAwMDAiLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgIHNpemUgPSA2KSsNCiAgZ2VvbV9sYWJlbChhZXMoeCA9IGFzLkRhdGUoYygnMjAxMi0wMS0wMScpKSwgeSA9IDE1LCBsYWJlbCA9ICJJUEMiKSwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICBoanVzdCA9IDAsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgdmp1c3QgPSAwLjUsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgZmlsbCA9ICJ0cmFuc3BhcmVudCIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICBsYWJlbC5zaXplID0gTkEsDQogICAgICAgICAgICAgICAgICAgICAgICAgICBjb2xvdXIgPSAiIzEzODBBMSIsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgc2l6ZSA9IDYpDQoNCmBgYA0KDQoNCiMjSW50ZXLDqXMgcGFyYSBlc3RlIHRyYWJham8NCg0KTGEgaW5mbGFjacOzbiBkaXN0b3JzaW9uYSBsb3MgcHJlY2lvcyByZWxhdGl2b3MgKHNhbGFyaW8gcmVhbCwgc2FsZG9zIHJlYWxlcywgdGlwbyBkZSBjYW1iaW8gcmVhbCkgeSBkaWZpY3VsdGEgbGEgY29tcGFyYWNpw7NuIGludGVydGVtcG9yYWwgZGUgbGFzIHZhcmlhYmxlcy4gVGFtYmllbiBhZmVjdGEgbGEgdG9tYSBkZSBkZWNpc2lvbmVzIGRlIGxvcyBhZ2VudGVzIChsYSBpbmZvcm1hY2nDs24gZXMgY29zdG9zYSB5IGxhIGluZmxhY2nDs24gYWdyZWdhIHJ1w61kbykuDQoNCkVuIGVzZSBtYXJjbywgbGEgaW5mbGFjacOzbiBlcyB1biBmZW7Ds21lbm8gcXVlIHBvZHLDrWEgYWx0ZXJhciBlbCBjb21wb3J0YW1pZW50byBkZSBudWVzdHJhcyB2YXJpYWJsZXMgeSBubyBlc3RhbW9zIGNvbnNpZGVyYW5kbyBlbiBlbCBtb2RlbGFkbyBkZWwgZXZlbnRvIGRlIGludGVyw6lzLiBFc3RvIHBvZHLDrWEgZXN0YXIgYWZlY3RhciBsYXMgY29uY2x1c2lvbmVzIHkgcmVzdWx0YWRvcy4NCg0KVmFtb3MgYSB2ZXIgdHJlcyBmb3JtYXMgZGUgbmV1dHJhbGl6YXIgZWwgZWZlY3RvIGRlIGxhIGluZmxhY2nDs246IGRlZmxhY3RhciBwb3IgZWwgSVBDLCBkZWZsYWN0YXIgcG9yIGVsIHRpcG8gZGUgY2FtYmlvIHkgdXNhbmRvIHJhbmdvcy4NCg0KI1ByZXBhcmFjacOzbiBkZSBsYXMgYmFzZXMNCg0KUG9yIHVuIGxhZG8gdmFtb3MgYSBpbXBvcnRhciBsYSBiYXNlIGNvbXBsZXRhIGRlbCBwYXF1ZXRlIHByZW1pdW0uIFZlYW1vcyBxdWUgdmVudGFuYSBkZSB0aWVtcG8gYWJhcmNhIGxhIG1pc21hLg0KDQpgYGB7ciBpbmNsdWRlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQ0KI0lNUE9SVE8gUEFRVUVURSBQUkVNSVVNDQpkZjwtIGZyZWFkKCcuLi9kYXRhc2V0cy9wYXF1ZXRlX3ByZW1pdW1fZGlhc18xYW5vLnR4dCcsIGhlYWRlcj1UUlVFKQ0KDQpoZWFkKGRmW2ZvdG9fbWVzPT0yMDE4MDUsXSkNCmBgYA0KDQpgYGB7cn0NCiMNCiNtZXM8LXVuaXF1ZShkZiRmb3RvX21lcykNCiNmb3IgKGkgaW4gbWVzKSB7DQojICB0bXAgPC0gZGZbZm90b19tZXM9PWksXQ0KIyAgd3JpdGVfZGVsaW0oeCA9IHRtcCxwYXRoID0gcGFzdGUwKCIuLi9kYXRhc2V0cy9kaWFzLyIsIGksICJfZGlhcy50eHQiKSwgZGVsaW0gPSAiXHQiKQ0KI30NCmBgYA0KDQoNCmBgYHtyIGVjaG89RkFMU0UsIHdhcm5pbmc9RkFMU0V9DQp1bmlxdWUoZGYkZm90b19tZXMpDQpgYGANCg0KUmVlc2NhbGFtb3MgbG9zIMOtbmRpY2VzIHBhcmEgcXVlIHNlYW4gYmFzZSAyMDE5MDQ9MQ0KDQoNCmBgYHtyfQ0KaXBjX2hpc3RvcmljbyRmb3RvX21lczwtIGZvcm1hdChpcGNfaGlzdG9yaWNvJGluZGljZV90aWVtcG8sICIlWSVtIikNCmlwY19oaXN0b3JpY28kZm90b19tZXM8LSBhcy5udW1lcmljKGlwY19oaXN0b3JpY28kZm90b19tZXMpDQppcGNfaGlzdG9yaWNvPC1pcGNfaGlzdG9yaWNvICU+JSBmaWx0ZXIoZm90b19tZXMgJWluJSB1bmlxdWUoZGYkZm90b19tZXMpKQ0KDQoNCmlwY19oaXN0b3JpY28gPC0gaXBjX2hpc3RvcmljbyAlPiUgbXV0YXRlKGlwYyA9IGlwYy9pcGNbMTJdLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2FsYXJpbyA9IHNhbGFyaW8vc2FsYXJpb1sxMl0sDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkb2xhciA9IGRvbGFyL2RvbGFyWzEyXSkNCg0KYGBgDQoNCmBgYHtyfQ0KaGVhZChpcGNfaGlzdG9yaWNvLDE1KQ0KDQpgYGANCg0KYGBge3IsIHdhcm5pbmc9RkFMU0V9DQoNCmRmPC0gZGYgJT4lIGxlZnRfam9pbihpcGNfaGlzdG9yaWNvLCBieT1jKCdmb3RvX21lcyc9J2ZvdG9fbWVzJykpDQpgYGANCg0KICANCg0KI0RlZmxhY3Rhcg0KDQpQcmVzZW50YW1vcyBkb3MgdMOpY25pY2FzIHBhcmEgIm5ldXRyYWxpemFyIiBlbCBlZmVjdG8gZGUgbGEgaW5mbGFjacOzbiBlbiBudWVzdHJvIG1vZGVsby4gTGEgcHJpbWVyYSBmb3JtYSBjb25zaXN0ZSBlbiBkZWZsYWN0YXIgbGFzIHZhcmlhYmxlcyBtb25ldGFyaWFzIHRvbWFuZG8gY29tbyByZWZlcmVuY2lhIGxhIGV2b2x1Y2nDs24gZGVsIElQQy4gRWwgSVBDIHNlIGNvbnN0cnV5ZSBlbGlnaWVuZG8gdW4gYcOxbyBjb21vICJhw7FvIGJhc2UiIGFsIGN1YWwgc2UgbGUgYXNpZ25hIHVuIElQQyBkZSAxMDAuIEEgbG9zIGHDsW9zIHNpZ3VpZW50ZXMgc2UgbGUgaXLDoSBzdW1hbmRvIGxhIGluZmxhY2nDs24gYWwgYcOxbyBiYXNlLiBQb3IgZWplbXBsbywgc2kgbGEgaW5mbGFjacOzbiBpbnRlcmFudWFsIGVudHJlIGVsIGHDsW8gYmFzZSB5IGVsIHNpZ3VpZW50ZSBmdWUgZGUgMiUsIGVsIElQQyBkZSBlc2UgYcOxbyBzZXLDoSBkZSAxMDIuIERlIGxhIG1pc21hIGZvcm1hIHNlIHByb2NlZGUgcGFyYSBsb3MgYcOxb3MgYW50ZXJpb3JlcyBhbCBhw7FvIGJhc2UsIHBlcm8gcmVzdGFuZG8gbGEgaW5mbGFjacOzbi4NCg0KRWwgY2FsY3VsbyBxdWUgdmFtb3MgYSByZWFsaXphciBlczogDQoNCiQkXGZyYWN7VlBDfXtJUEN9KjEwMCAkJA0KDQpDb246DQoNCiRWUEMgPSBWYWxvciQgJGVuJCAkcHJlY2lvcyQgJGNvcnJpZW50ZXMkIA0KJElQQyA9IEluZGljZSQgJGRlJCAkcHJlY2lvcyQgJGFsJCAkQ29uc3VtaWRvciQuDQoNCkVsIHByb2NlZGltaWVudG8gc2Vyw6EgZWwgbWlzbW8gYSBsYSBob3JhIGRlIGRlZmxhY3RhciBwb3IgZWwgVGlwbyBkZSBDYW1iaW8uDQoNCiMjRGVmbGFjdGFyIHBvciBJUEMNCg0KYGBge3IsIHdhcm5pbmc9RkFMU0V9DQpkZlsncmVudF8xMiddPWRmJG1yZW50YWJpbGlkYWQvZGYkaXBjDQpkZlsnc2FsZG9fMTInXT1kZiRtY3VlbnRhc19zYWxkby9kZiRpcGMNCmRmWydzdWVsZG9fMTInXT1kZiRtcGxhbl9zdWVsZG8vZGYkaXBjDQpkZlsnZGViaXRvc18xMiddPWRmJG1jdWVudGFfZGViaXRvc19hdXRvbWF0aWNvcy9kZiRpcGMNCmBgYA0KDQoNCiMjRGVmbGFjdGFyIHBvciB0aXBvIGRlIGNhbWJpbw0KYGBge3IsIHdhcm5pbmc9RkFMU0V9DQpkZlsncmVudF91c2QnXT1kZiRtcmVudGFiaWxpZGFkL2RmJGRvbGFyDQpkZlsnc2FsZG9fdXNkJ109ZGYkbWN1ZW50YXNfc2FsZG8vZGYkZG9sYXINCmRmWydzdWVsZG9fdXNkJ109ZGYkbXBsYW5fc3VlbGRvL2RmJGRvbGFyDQpkZlsnZGViaXRvc191c2QnXT1kZiRtY3VlbnRhX2RlYml0b3NfYXV0b21hdGljb3MvZGYkZG9sYXINCg0KYGBgDQoNCiMjRGVmbGFjdGFyIHBvciByYW5nb3MNCg0KRW4gc2VndW5kbyBsdWdhciwgY3VhbmRvIGRlZmxhY3RhbW9zIHBvciByYW5nb3MgZWwgcHJvY2VkaW1pZW50byBjb25zaXN0ZSBlbiBkaXZpZGlyIGVsIGRhdGFzZXQgZW4gcGFydGVzIGlndWFsZXMgKHBlcmNlbnRpbGVzKSwgZGUgZXN0YSBmb3JtYSBvYnRlbmRyZW1vcyB1biBvcmRlbmFtaWVudG8gcXVlIGVzIGluZGVwZW5kaWVudGUgZGUgbGEgbWFnbml0dWQgZGUgbnVlc3RyYXMgdmFyaWFibGVzLiBMdWVnbyBzZSBldmFsw7phIHBhc2FqZSBkZSB1biByYW5nbyBhbCBvdHJvIGVudHJlIHBlcsOtb2Rvcy4gDQoNCmBgYHtyfQ0KZGYgJT4lIA0KICBnZ3Bsb3QoYWVzKHggPSBtcmVudGFiaWxpZGFkLCBjb2xvdXIgPSBhcy5mYWN0b3IoZm90b19tZXMpICkpICsgZ2VvbV9kZW5zaXR5KCkreGxpbSgwLDUwMDApDQoNCmBgYA0KDQpgYGB7cn0NCmRmICU+JSANCiAgZ2dwbG90KGFlcyh4ID0gcmVudF8xMiwgY29sb3VyID0gYXMuZmFjdG9yKGZvdG9fbWVzKSApKSArIGdlb21fZGVuc2l0eSgpK3hsaW0oMCw1MDAwKQ0KDQpgYGANCg0KDQpgYGB7ciwgd2FybmluZz1GQUxTRX0NCiMjIyBQZXJjZW50aWxlcw0KDQptZXNlczwtIHVuaXF1ZShkZiRmb3RvX21lcykNCmJldGE9TlVMTA0KZm9yIChpIGluIG1lc2VzKXsNCiAgYTwtIHdoaWNoKGRmJGZvdG9fbWVzPT1pKQ0KICBhbHBoYTwtIGRmW2EsYygibnVtZXJvX2RlX2NsaWVudGUiLCAiZm90b19tZXMiLCJtcmVudGFiaWxpZGFkIiwibWN1ZW50YXNfc2FsZG8iLCAibXBsYW5fc3VlbGRvIiwgIm1jdWVudGFfZGViaXRvc19hdXRvbWF0aWNvcyIpXQ0KICBhbHBoYSRtcmVudGFiaWxpZGFkPC1lY2RmKGFscGhhJG1yZW50YWJpbGlkYWQpKGFscGhhJG1yZW50YWJpbGlkYWQpDQogIGFscGhhJG1jdWVudGFzX3NhbGRvPC1lY2RmKGFscGhhJG1jdWVudGFzX3NhbGRvKShhbHBoYSRtY3VlbnRhc19zYWxkbykNCiAgYWxwaGEkbXBsYW5fc3VlbGRvPC1lY2RmKGFscGhhJG1wbGFuX3N1ZWxkbykoYWxwaGEkbXBsYW5fc3VlbGRvKQ0KICBhbHBoYSRtY3VlbnRhX2RlYml0b3NfYXV0b21hdGljb3M8LWVjZGYoYWxwaGEkbWN1ZW50YV9kZWJpdG9zX2F1dG9tYXRpY29zKShhbHBoYSRtY3VlbnRhX2RlYml0b3NfYXV0b21hdGljb3MpDQogIGJldGE9cmJpbmQoYmV0YSwgYWxwaGEpDQogIH0NCg0KY29sbmFtZXMoYmV0YSk8LSBjKCJudW1lcm9fZGVfY2xpZW50ZSIsICJmb3RvX21lcyIsInJlbnRhYmlsaWRhZF9wZXJjIiwic2FsZG9fcGVyYyIsICJzdWVsZG9fcGVyYyIsICJkZWJpdG9zX3BlcmMiKQ0KDQpkZjwtIGRmICU+JSBsZWZ0X2pvaW4oYmV0YSkNCmBgYA0KDQoNCmBgYHtyLCB3YXJuaW5nPUZBTFNFfQ0KIyMjIEVzY2FsYWRvIChub3JtYWxpemFkbykNCg0KbWVzZXM8LSB1bmlxdWUoZGYkZm90b19tZXMpDQpiZXRhPU5VTEwNCmZvciAoaSBpbiBtZXNlcyl7DQogIGE8LSB3aGljaChkZiRmb3RvX21lcz09aSkNCiAgYWxwaGE8LSBkZlthLGMoIm51bWVyb19kZV9jbGllbnRlIiwgImZvdG9fbWVzIiwibXJlbnRhYmlsaWRhZCIsIm1jdWVudGFzX3NhbGRvIiwgIm1wbGFuX3N1ZWxkbyIsICJtY3VlbnRhX2RlYml0b3NfYXV0b21hdGljb3MiKV0NCiAgYWxwaGEkbXJlbnRhYmlsaWRhZDwtc2NhbGUoYWxwaGEkbXJlbnRhYmlsaWRhZCkNCiAgYWxwaGEkbWN1ZW50YXNfc2FsZG88LXNjYWxlKGFscGhhJG1jdWVudGFzX3NhbGRvKQ0KICBhbHBoYSRtcGxhbl9zdWVsZG88LXNjYWxlKGFscGhhJG1wbGFuX3N1ZWxkbykNCiAgYWxwaGEkbWN1ZW50YV9kZWJpdG9zX2F1dG9tYXRpY29zPC1zY2FsZShhbHBoYSRtY3VlbnRhX2RlYml0b3NfYXV0b21hdGljb3MpDQogIGJldGE9cmJpbmQoYmV0YSwgYWxwaGEpDQogIH0NCg0KY29sbmFtZXMoYmV0YSk8LSBjKCJudW1lcm9fZGVfY2xpZW50ZSIsICJmb3RvX21lcyIsInJlbnRhYmlsaWRhZF9ub3JtIiwic2FsZG9fbm9ybSIsICJzdWVsZG9fbm9ybSIsICJkZWJpdG9zX25vcm0iKQ0KDQpkZjwtIGRmICU+JSBsZWZ0X2pvaW4oYmV0YSkNCmBgYA0KDQoNCiNJbXBhY3RvIGVuIGxhcyBWYXJpYWJsZXMNCg0KRW4gbG9zIGdyw6FmaWNvcyBhIGNvbnRpbnVhY2nDs24gc2UgdmUgbGEgZXZvbHVjacOzbiBpbnRlcm1lbnN1YWwgZGUgbGFzIHZhcmlhYmxlcyBudW3DqXJpY2FzIGRlZmxhY3RhZGFzIHkgbm8gZGVmbGFjdGFkYXMgdG9tYW5kbyB1biBjbGllbnRlIHBhcnRpY3VsYXIuIENvbW8gc2UgcHVlZGUgYXByZWNpYXIsIGxhcyB0cmF5ZWN0b3JpYXMgc2UgbWFudGllbmVuIHByw6FjdGljYW1lbnRlIGlndWFsZXMsIMO6bmljYW1lbnRlIHZhcsOtYW4gbGFzIHVuaWRhZGVzIHNlIG1hZ25pdHVkLiANCg0KRXN0byBpbmRpY2EgcXVlICBtdXkgcHJvYmFibGVtZW50ZSBubyBjYWJyw61hIGVzcGVyYXIgdmFyaWFjaW9uZXMgc2lnbmlmaWNhdGl2YSBlbiBsb3MgcmVzdWx0YWRvcyBkZSBsb3MgbW9kZWxvcy4NCmBgYHtyfQ0KaGVhZChkZls0NTo3NCxdLDEwKQ0KYGBgDQpgYGB7cn0NCnNldC5zZWVkKDE1MTUxNSkNCmxpc3RhX2NsaWVudGVzPC1zYW1wbGUoeCA9dW5pcXVlKGRmJG51bWVyb19kZV9jbGllbnRlKSwgc2l6ZSA9IDEgKSANCmNsaWVudGU8LWRmICU+JSAgZmlsdGVyKG51bWVyb19kZV9jbGllbnRlICVpbiUgbGlzdGFfY2xpZW50ZXMpDQpgYGANCg0KDQpgYGB7ciwgZWNobz1GQUxTRX0NCg0KY2xpZW50ZSRmb3RvX21lczwtYXMuRGF0ZShwYXN0ZTAoYXMuY2hhcmFjdGVyKGNsaWVudGUkZm90b19tZXMpLCAnMDEnKSwgZm9ybWF0PSclWSVtJWQnKQ0KY2xpZW50ZWp1bnRvIDwtIG1lbHQoY2xpZW50ZVssIGMoImZvdG9fbWVzIiwgIm1wbGFuX3N1ZWxkbyIsICJzdWVsZG9fMTIiLCdzdWVsZG9fdXNkJywgInN1ZWxkb19wZXJjIiwic3VlbGRvX25vcm0iKV0sIGlkPSJmb3RvX21lcyIpDQpnZ3Bsb3QoY2xpZW50ZWp1bnRvKSArIGdlb21fbGluZShhZXMoeD1mb3RvX21lcywgeT12YWx1ZSwgY29sb3I9dmFyaWFibGUpKSAgKyBmYWNldF93cmFwKCB+IHZhcmlhYmxlLCBzY2FsZXM9ImZyZWUiKSArDQogIHRoZW1lX21pbmltYWwoKSsNCiAgdGhlbWUobGVnZW5kLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZT03KSxheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDkwLCBoanVzdCA9IDEpLHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUpKSsNCiAgICBsYWJzKHg9Ik1lcyIsIHk9IiIsDQogICAgICAgdGl0bGU9IkV2b2x1Y2lvbiAgU3VlbGRvIikNCg0KY2xpZW50ZWp1bnRvIDwtIG1lbHQoY2xpZW50ZVssIGMoImZvdG9fbWVzIiwgIm1yZW50YWJpbGlkYWQiLCAicmVudF8xMiIsJ3JlbnRfdXNkJywicmVudGFiaWxpZGFkX3BlcmMiLCJyZW50YWJpbGlkYWRfbm9ybSIpXSwgaWQ9ImZvdG9fbWVzIikNCmdncGxvdChjbGllbnRlanVudG8pICsgZ2VvbV9saW5lKGFlcyh4PWZvdG9fbWVzLCB5PXZhbHVlLCBjb2xvcj12YXJpYWJsZSkpICArIGZhY2V0X3dyYXAoIH4gdmFyaWFibGUsIHNjYWxlcz0iZnJlZSIpKyANCiAgdGhlbWVfbWluaW1hbCgpKw0KICB0aGVtZShsZWdlbmQudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplPTcpLGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gOTAsIGhqdXN0ID0gMSkscGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSkpKw0KICBsYWJzKHg9Ik1lcyIsIHk9IiIsDQogICAgICAgdGl0bGU9IkV2b2x1Y2lvbiAgUmVudGFiaWxpZGFkIikNCg0KY2xpZW50ZWp1bnRvIDwtIG1lbHQoY2xpZW50ZVssIGMoImZvdG9fbWVzIiwgIm1jdWVudGFzX3NhbGRvIiwgInNhbGRvXzEyIiwnc2FsZG9fdXNkJywic2FsZG9fcGVyYyIsInNhbGRvX25vcm0iKV0sIGlkPSJmb3RvX21lcyIpDQpnZ3Bsb3QoY2xpZW50ZWp1bnRvKSArIGdlb21fbGluZShhZXMoeD1mb3RvX21lcywgeT12YWx1ZSwgY29sb3I9dmFyaWFibGUpKSAgKyBmYWNldF93cmFwKCB+IHZhcmlhYmxlLCBzY2FsZXM9ImZyZWUiKSsNCiAgICB0aGVtZV9taW5pbWFsKCkrDQogIHRoZW1lKGxlZ2VuZC50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemU9NyksYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA5MCwgaGp1c3QgPSAxKSxwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41KSkrDQogIGxhYnMoeD0iTWVzIiwgeT0iIiwNCiAgICAgICB0aXRsZT0iRXZvbHVjaW9uICBTYWxkbyBlbiBDdWVudGEiKQ0KDQpjbGllbnRlanVudG8gPC0gbWVsdChjbGllbnRlWywgYygiZm90b19tZXMiLCAibWN1ZW50YV9kZWJpdG9zX2F1dG9tYXRpY29zIiwgImRlYml0b3NfMTIiLCdkZWJpdG9zX3VzZCcsImRlYml0b3NfcGVyYyIsImRlYml0b3Nfbm9ybSIpXSwgaWQ9ImZvdG9fbWVzIikNCmdncGxvdChjbGllbnRlanVudG8pICsgZ2VvbV9saW5lKGFlcyh4PWZvdG9fbWVzLCB5PXZhbHVlLCBjb2xvcj12YXJpYWJsZSkpICArIGZhY2V0X3dyYXAoIH4gdmFyaWFibGUsIHNjYWxlcz0iZnJlZSIpKw0KICAgIHRoZW1lX21pbmltYWwoKSsNCiAgICB0aGVtZShsZWdlbmQudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplPTcpLGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gOTAsIGhqdXN0ID0gMSkscGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSkpKw0KICBsYWJzKHg9Ik1lcyIsIHk9IiIsDQogICAgICAgdGl0bGU9IkV2b2x1Y2lvbiAgRGViaXRvcyBBdXRvbWF0aWNvcyIpDQpgYGANCg0KDQojSW1wYWN0byBlbiBlbCBtb2RlbG8NCg0KQSBjb250aW51YWNpw7NuLCBwYXIgYWV2YWx1YXIgbG9zIGVmZWN0b3MgZGUgbGEgbmV1dHJhbGl6YWNpw7NuIGRlIGxhIGluZmxhY2nDs24gZW4gbGFzIHZhcmlhYmxlcyBub21pbmFsZXMgc2UgZW50cmVuYXJvbiBjdWF0cm8gbW9kZWxvcywgdW5vIGNvbiBsYXMgdmFyaWFibGVzIG51bcOpcmljYXMgc2luIG1vZGlmaWNhciwgY29uIGxhcyB2YXJpYWJsZXMgZGVmbGFjdGFkYXMgcG9yIGVsIElQQywgZGVmbGFjdGFkYXMgcG9yIGVsIHRpcG8gZGUgY2FtYmlvIHkgcG9yIHJhbmdvcywgdXNhbmRvIGxvcyBkYXRvcyBkZWwgbWVzIGRlIGZlYnJlcm8geSBzZSBsbyBmdWUgcHJvYmFuZG8gZW4gbG9zIG1lc2VzIHNpZ3VpZW50ZXMuIFNlIHJlY29waWxhcm9uIGxhcyBtw6l0cmljYXMgZGUgQVVDIHkgZGUgZ2FuYW5jaWEgeSBzZSBjb21wYXLDsyBsYSBldm9sdWNpw7NuIGRlIGRpY2hhcyBtw6l0cmljYXMgcGFyYSBjYWRhIG1vZGVsby4NCg0KYGBge3IsIGVjaG89RkFMU0V9DQpnYW5hbmNpYSAgIDwtIGZ1bmN0aW9uKHByb2JzLCBjbGFzZXMpIA0Kew0KDQogICB2bGFiZWxzIDwtIGdldGluZm8oY2xhc2VzLCAibGFiZWwiKQ0KDQogICBnYW5hbmNpYV9jYWxjdWxhZGEgIDwtIHN1bSggICAgKHByb2JzID4oIDAuMDI1KSApICogDQoJCSAgICAgICAgICAgICAgICAgICBpZmVsc2UoIHZsYWJlbHM9PSAxLCAxMTcwMCwgLTMwMCApICAgDQogICAgICAgICAgICAgIAkJICAgICApIA0KICAgcmV0dXJuKCAgbGlzdChtZXRyaWMgPSAiZ2FuYW5jaWEiLCB2YWx1ZSA9IGdhbmFuY2lhX2NhbGN1bGFkYSApICApDQp9DQoNCg0KI1ZhbW9zIGEgYWp1c3RhciBjb24gZmVicmVybyB5IHZlciBjb21vIHBlcmZvcm1hbiBsb3MgbW9kZWxvcyBzZWd1biBlbCB0aXBvIGRlIHZhcmlhYmxlIHF1ZSB1c2Vtb3MNCg0KZmVicmVybyAgPC0gIGZyZWFkKCIuLi9kYXRhc2V0cy9kaWFzLzIwMTkwMl9kaWFzLnR4dCIsIGhlYWRlcj1UUlVFLCBzZXA9Ilx0IikNCg0KY2xhc2VzX2ZlYnJlcm8gPC0gaWZlbHNlKGZlYnJlcm8kY2xhc2VfdGVybmFyaWEgPT0gIkJBSkErMiIsIDEsIDApDQoNCmNvbHM8LWMoIm51bWVyb19kZV9jbGllbnRlIiwgImZvdG9fbWVzIiwibXJlbnRhYmlsaWRhZCIsIm1jdWVudGFzX3NhbGRvIiwgIm1wbGFuX3N1ZWxkbyIsICJtY3VlbnRhX2RlYml0b3NfYXV0b21hdGljb3MiLCAiY2xhc2VfdGVybmFyaWEiKQ0KDQpmZWJyZXJvPC0gZmVicmVybyAlPiUgc2VsZWN0KGNvbHMpDQpmZWJyZXJvPC0gZmVicmVybyAlPiUgbGVmdF9qb2luKGlwY19oaXN0b3JpY28sIGJ5PWMoJ2ZvdG9fbWVzJz0nZm90b19tZXMnKSkNCiANCmtiYXNlX3Njb3JlICA8LSAgc3VtKCBjbGFzZXNfZmVicmVybyApIC8gbGVuZ3RoKGNsYXNlc19mZWJyZXJvKQ0KI0RlZmxhY3RvIHBvciBJUEMNCmZlYnJlcm9bJ3JlbnRfMTInXT1mZWJyZXJvJG1yZW50YWJpbGlkYWQvZmVicmVybyRpcGMNCmZlYnJlcm9bJ3NhbGRvXzEyJ109ZmVicmVybyRtY3VlbnRhc19zYWxkby9mZWJyZXJvJGlwYw0KZmVicmVyb1snc3VlbGRvXzEyJ109ZmVicmVybyRtcGxhbl9zdWVsZG8vZmVicmVybyRpcGMNCmZlYnJlcm9bJ2RlYml0b3NfMTInXT1mZWJyZXJvJG1jdWVudGFfZGViaXRvc19hdXRvbWF0aWNvcy9mZWJyZXJvJGlwYw0KDQojRGVmbGFjdGFtb3MgcG9yIFRDDQpmZWJyZXJvWydyZW50X3VzZCddPWZlYnJlcm8kbXJlbnRhYmlsaWRhZC9mZWJyZXJvJGRvbGFyDQpmZWJyZXJvWydzYWxkb191c2QnXT1mZWJyZXJvJG1jdWVudGFzX3NhbGRvL2ZlYnJlcm8kZG9sYXINCmZlYnJlcm9bJ3N1ZWxkb191c2QnXT1mZWJyZXJvJG1wbGFuX3N1ZWxkby9mZWJyZXJvJGRvbGFyDQpmZWJyZXJvWydkZWJpdG9zX3VzZCddPWZlYnJlcm8kbWN1ZW50YV9kZWJpdG9zX2F1dG9tYXRpY29zL2ZlYnJlcm8kZG9sYXINCg0KI0dlbmVyYW1vcyBSYW5nb3MNCmZlYnJlcm9bInJlbnRhYmlsaWRhZF9wZXJjIl08LWVjZGYoZmVicmVybyRtcmVudGFiaWxpZGFkKShmZWJyZXJvJG1yZW50YWJpbGlkYWQpDQpmZWJyZXJvWyJzYWxkb19wZXJjIl08LWVjZGYoZmVicmVybyRtY3VlbnRhc19zYWxkbykoZmVicmVybyRtY3VlbnRhc19zYWxkbykNCmZlYnJlcm9bInN1ZWxkb19wZXJjIl08LWVjZGYoZmVicmVybyRtcGxhbl9zdWVsZG8pKGZlYnJlcm8kbXBsYW5fc3VlbGRvKQ0KZmVicmVyb1siZGViaXRvc19wZXJjIl08LWVjZGYoZmVicmVybyRtY3VlbnRhX2RlYml0b3NfYXV0b21hdGljb3MpKGZlYnJlcm8kbWN1ZW50YV9kZWJpdG9zX2F1dG9tYXRpY29zKQ0KDQojbm9ybWFsaXphY2lvbg0KZmVicmVyb1sicmVudGFiaWxpZGFkX25vcm0iXTwtc2NhbGUoZmVicmVybyRtcmVudGFiaWxpZGFkKQ0KZmVicmVyb1sic2FsZG9fbm9ybSJdPC1zY2FsZShmZWJyZXJvJG1jdWVudGFzX3NhbGRvKQ0KZmVicmVyb1sic3VlbGRvX25vcm0iXTwtc2NhbGUoZmVicmVybyRtcGxhbl9zdWVsZG8pDQpmZWJyZXJvWyJkZWJpdG9zX25vcm0iXTwtc2NhbGUoZmVicmVybyRtY3VlbnRhX2RlYml0b3NfYXV0b21hdGljb3MpDQoNCg0Kbm9taW5hbDwtIGMoIm51bWVyb19kZV9jbGllbnRlIiwgImZvdG9fbWVzIiwibXJlbnRhYmlsaWRhZCIsIm1jdWVudGFzX3NhbGRvIiwgIm1wbGFuX3N1ZWxkbyIsICJtY3VlbnRhX2RlYml0b3NfYXV0b21hdGljb3MiKQ0KaW5mbGFjaW9uPC0gYygibnVtZXJvX2RlX2NsaWVudGUiLCAiZm90b19tZXMiLCJyZW50XzEyIiwic2FsZG9fMTIiLCAic3VlbGRvXzEyIiwgImRlYml0b3NfMTIiKQ0KdGlwb19kZV9jYW1iaW88LSBjKCJudW1lcm9fZGVfY2xpZW50ZSIsICJmb3RvX21lcyIsInJlbnRfdXNkIiwic2FsZG9fdXNkIiwgInN1ZWxkb191c2QiLCAiZGViaXRvc191c2QiKQ0KcmFuZ288LSBjKCJudW1lcm9fZGVfY2xpZW50ZSIsICJmb3RvX21lcyIsInJlbnRhYmlsaWRhZF9wZXJjIiwic2FsZG9fcGVyYyIsICJzdWVsZG9fcGVyYyIsICJkZWJpdG9zX3BlcmMiKQ0Kbm9ybWFsPC0gYygibnVtZXJvX2RlX2NsaWVudGUiLCAiZm90b19tZXMiLCJyZW50YWJpbGlkYWRfbm9ybSIsInNhbGRvX25vcm0iLCAic3VlbGRvX25vcm0iLCAiZGViaXRvc19ub3JtIikNCg0KDQojTW9kZWxvIE5vbWluYWwNCmR0cmFpbl9ub20gPC0geGdiLkRNYXRyaXgoIGRhdGEgPSBkYXRhLm1hdHJpeChmZWJyZXJvW25vbWluYWxdKSwgIGxhYmVsID0gY2xhc2VzX2ZlYnJlcm8sIG1pc3Npbmc9TkEgKQ0KDQptb2RlbG9fbm9tID0geGdiLnRyYWluKCANCgkJCQlkYXRhID0gZHRyYWluX25vbSwgIA0KCQkJCW1pc3NpbmcgPSBOQSwNCgkJCQlucm91bmQ9IDIwLA0KICAgIAkgIGV2YWxfbWV0cmljPSAiYXVjIiwgDQoJCQkJbWF4aW1pemUgPVRSVUUsDQoJCQkJb2JqZWN0aXZlPSJiaW5hcnk6bG9naXN0aWMiLA0KCQkJICB2ZXJib3NlID0gMg0KCQkJKQ0KDQojTW9kZWxvIERlZmxhY3RvZG8NCmR0cmFpbl9pcGMgPC0geGdiLkRNYXRyaXgoIGRhdGEgPSBkYXRhLm1hdHJpeChmZWJyZXJvW2luZmxhY2lvbl0pLCAgbGFiZWwgPSBjbGFzZXNfZmVicmVybywgbWlzc2luZz1OQSApDQoNCm1vZGVsb19pcGMgPSB4Z2IudHJhaW4oIA0KCQkJCWRhdGEgPSBkdHJhaW5faXBjLCAgDQoJCQkJbWlzc2luZyA9IE5BLA0KCQkJCW5yb3VuZD0gMjAsDQogICAgCSAgZXZhbF9tZXRyaWM9ICJhdWMiLCANCgkJCQltYXhpbWl6ZSA9VFJVRSwNCgkJCQlvYmplY3RpdmU9ImJpbmFyeTpsb2dpc3RpYyIsDQoJCQkgIHZlcmJvc2UgPSAyDQoJCQkpDQoNCiNNb2RlbG8gRGVmbGFjdG9kbw0KZHRyYWluX3VzZCA8LSB4Z2IuRE1hdHJpeCggZGF0YSA9IGRhdGEubWF0cml4KGZlYnJlcm9bdGlwb19kZV9jYW1iaW9dKSwgIGxhYmVsID0gY2xhc2VzX2ZlYnJlcm8sIG1pc3Npbmc9TkEgKQ0KDQptb2RlbG9fdXNkID0geGdiLnRyYWluKCANCgkJCQlkYXRhID0gZHRyYWluX3VzZCwgIA0KCQkJCW1pc3NpbmcgPSBOQSwNCgkJCQlucm91bmQ9IDIwLA0KICAgIAkgIGV2YWxfbWV0cmljPSAiYXVjIiwgDQoJCQkJbWF4aW1pemUgPVRSVUUsDQoJCQkJb2JqZWN0aXZlPSJiaW5hcnk6bG9naXN0aWMiLA0KCQkJICB2ZXJib3NlID0gMg0KCQkJKQ0KDQojTW9kZWxvIHJhbmdvDQpkdHJhaW5fcmFuZyA8LSB4Z2IuRE1hdHJpeCggZGF0YSA9IGRhdGEubWF0cml4KGZlYnJlcm9bcmFuZ29dKSwgIGxhYmVsID0gY2xhc2VzX2ZlYnJlcm8sIG1pc3Npbmc9TkEgKQ0KDQptb2RlbG9fcmFuZyA9IHhnYi50cmFpbiggDQoJCQkJZGF0YSA9IGR0cmFpbl9yYW5nLCAgDQoJCQkJbWlzc2luZyA9IE5BLA0KCQkJCW5yb3VuZD0gMjAsDQogICAgCSAgZXZhbF9tZXRyaWM9ICJhdWMiLCANCgkJCQltYXhpbWl6ZSA9VFJVRSwNCgkJCQlvYmplY3RpdmU9ImJpbmFyeTpsb2dpc3RpYyIsDQoJCQkgIHZlcmJvc2UgPSAyDQoJCQkpDQoNCg0KI01vZGVsbyBub3JtYWxpemFkbw0KZHRyYWluX25vcm0gPC0geGdiLkRNYXRyaXgoIGRhdGEgPSBkYXRhLm1hdHJpeChmZWJyZXJvW25vcm1hbF0pLCAgbGFiZWwgPSBjbGFzZXNfZmVicmVybywgbWlzc2luZz1OQSApDQoNCm1vZGVsb19ub3JtID0geGdiLnRyYWluKCANCgkJCQlkYXRhID0gZHRyYWluX25vcm0sICANCgkJCQltaXNzaW5nID0gTkEsDQoJCQkJbnJvdW5kPSAyMCwNCiAgICAJICBldmFsX21ldHJpYz0gImF1YyIsIA0KCQkJCW1heGltaXplID1UUlVFLA0KCQkJCW9iamVjdGl2ZT0iYmluYXJ5OmxvZ2lzdGljIiwNCgkJCSAgdmVyYm9zZSA9IDINCgkJCSkNCg0KIyBtZXNlcyBhIHZhbGlkYXINCm1lc2VzIDwtIGModW5pcXVlKGRmJGZvdG9fbWVzKSkNCg0KcmVzdWx0YWRvcyA8LSBkYXRhLmZyYW1lKCkNCg0KZm9yIChtIGluIG1lc2VzKSB7DQogICAgbWVzIDwtIGZyZWFkKHBhc3RlMCgiLi4vZGF0YXNldHMvZGlhcy8iLCBtLCAiX2RpYXMudHh0IiksIGhlYWRlcj1UUlVFLCBzZXA9Ilx0IikNCiAgICBjbGFzZXNfbWVzIDwtIGlmZWxzZShtZXMkY2xhc2VfdGVybmFyaWEgPT0gIkJBSkErMiIsIDEsIDApDQoNCiAgICBtZXM8LSBtZXMgJT4lIHNlbGVjdChjb2xzKQ0KICAgIG1lczwtIG1lcyAlPiUgbGVmdF9qb2luKGlwY19oaXN0b3JpY28sIGJ5PWMoJ2ZvdG9fbWVzJz0nZm90b19tZXMnKSkNCiANCg0KICAgICNEZWZsYWN0byBwb3IgSVBDDQogICAgbWVzWydyZW50XzEyJ109bWVzJG1yZW50YWJpbGlkYWQvbWVzJGlwYw0KICAgIG1lc1snc2FsZG9fMTInXT1tZXMkbWN1ZW50YXNfc2FsZG8vbWVzJGlwYw0KICAgIG1lc1snc3VlbGRvXzEyJ109bWVzJG1wbGFuX3N1ZWxkby9tZXMkaXBjDQogICAgbWVzWydkZWJpdG9zXzEyJ109bWVzJG1jdWVudGFfZGViaXRvc19hdXRvbWF0aWNvcy9tZXMkaXBjDQoNCiAgICAjRGVmbGFjdGFtb3MgcG9yIFRDDQogICAgbWVzWydyZW50X3VzZCddPW1lcyRtcmVudGFiaWxpZGFkL21lcyRkb2xhcg0KICAgIG1lc1snc2FsZG9fdXNkJ109bWVzJG1jdWVudGFzX3NhbGRvL21lcyRkb2xhcg0KICAgIG1lc1snc3VlbGRvX3VzZCddPW1lcyRtcGxhbl9zdWVsZG8vbWVzJGRvbGFyDQogICAgbWVzWydkZWJpdG9zX3VzZCddPW1lcyRtY3VlbnRhX2RlYml0b3NfYXV0b21hdGljb3MvbWVzJGRvbGFyDQogICAgDQogICAgI0dlbmVyYW1vcyBSYW5nb3MNCiAgICBtZXNbInJlbnRhYmlsaWRhZF9wZXJjIl08LWVjZGYobWVzJG1yZW50YWJpbGlkYWQpKG1lcyRtcmVudGFiaWxpZGFkKQ0KICAgIG1lc1sic2FsZG9fcGVyYyJdPC1lY2RmKG1lcyRtY3VlbnRhc19zYWxkbykobWVzJG1jdWVudGFzX3NhbGRvKQ0KICAgIG1lc1sic3VlbGRvX3BlcmMiXTwtZWNkZihtZXMkbXBsYW5fc3VlbGRvKShtZXMkbXBsYW5fc3VlbGRvKQ0KICAgIG1lc1siZGViaXRvc19wZXJjIl08LWVjZGYobWVzJG1jdWVudGFfZGViaXRvc19hdXRvbWF0aWNvcykobWVzJG1jdWVudGFfZGViaXRvc19hdXRvbWF0aWNvcykNCiAgICANCiAgICAjR2VuZXJhbW9zIE5vcm1hbA0KICAgIG1lc1sicmVudGFiaWxpZGFkX25vcm0iXTwtc2NhbGUobWVzJG1yZW50YWJpbGlkYWQpDQogICAgbWVzWyJzYWxkb19ub3JtIl08LXNjYWxlKG1lcyRtY3VlbnRhc19zYWxkbykNCiAgICBtZXNbInN1ZWxkb19ub3JtIl08LXNjYWxlKG1lcyRtcGxhbl9zdWVsZG8pDQogICAgbWVzWyJkZWJpdG9zX25vcm0iXTwtc2NhbGUobWVzJG1jdWVudGFfZGViaXRvc19hdXRvbWF0aWNvcykNCg0KICAgIG1lc19ub21pbmFsPC0gbWVzICU+JSBzZWxlY3Qobm9taW5hbCkNCiAgICBtZXNfaXBjPC0gbWVzICU+JSBzZWxlY3QoaW5mbGFjaW9uKQ0KICAgIG1lc19kb2xhcjwtIG1lcyAlPiUgc2VsZWN0KHRpcG9fZGVfY2FtYmlvKQ0KICAgIG1lc19yYW5nPC0gbWVzICU+JSBzZWxlY3QocmFuZ28pDQogICAgbWVzX25vcm08LSBtZXMgJT4lIHNlbGVjdChub3JtYWwpDQogICAgDQogICAgI1ByZWRpY2Npb24gbW9kZWxvIG5vbWluYWwNCiAgICB5X3ByZWRfbm9tIDwtIHByZWRpY3QobW9kZWxvX25vbSwgZGF0YS5tYXRyaXgobWVzX25vbWluYWwpLCAgdHlwZSA9ICJwcm9iIikNCiAgICBwcmVkaWNjaW9uX25vbTwtIGlmZWxzZSgoeV9wcmVkX25vbSA+KCAwLjAyNSkpLDEsMCkNCiAgICByb2NfY2FsY19ub208LSByb2MoY2xhc2VzX21lcyxwcmVkaWNjaW9uX25vbSkNCiAgICBhdWNfbm9tPC1hdWMocm9jX2NhbGNfbm9tKQ0KICAgIGdhbl9ub208LXN1bSgoeV9wcmVkX25vbSA+KCAwLjAyNSkgKSAqIGlmZWxzZSggY2xhc2VzX21lcz09IDEsIDExNzAwLCAtMzAwICkpIA0KICAgIA0KICAgICNQcmVkaWNjaW9uIG1vZGVsbyBJUEMNCiAgICB5X3ByZWRfaXBjIDwtIHByZWRpY3QobW9kZWxvX2lwYywgZGF0YS5tYXRyaXgobWVzX2lwYyksICB0eXBlID0gInByb2IiKQ0KICAgIHByZWRpY2Npb25faXBjPC0gaWZlbHNlKCh5X3ByZWRfaXBjID4oIDAuMDI1KSksMSwwKQ0KICAgIHJvY19jYWxjX2lwYzwtIHJvYyhjbGFzZXNfbWVzLHByZWRpY2Npb25faXBjKQ0KICAgIGF1Y19pcGM8LWF1Yyhyb2NfY2FsY19pcGMpDQogICAgZ2FuX2lwYzwtc3VtKCh5X3ByZWRfaXBjID4oIDAuMDI1KSApICogaWZlbHNlKCBjbGFzZXNfbWVzPT0gMSwgMTE3MDAsIC0zMDAgKSkgDQogICAgDQogICAgI1ByZWRpY2Npb24gbW9kZWxvIFVTRA0KICAgIHlfcHJlZF9kb2xhciA8LSBwcmVkaWN0KG1vZGVsb191c2QsIGRhdGEubWF0cml4KG1lc19kb2xhciksICB0eXBlID0gInByb2IiKQ0KICAgIHByZWRpY2Npb25fZG9sYXI8LSBpZmVsc2UoKHlfcHJlZF9kb2xhciA+KCAwLjAyNSkpLDEsMCkNCiAgICByb2NfY2FsY19kb2xhcjwtIHJvYyhjbGFzZXNfbWVzLHByZWRpY2Npb25fZG9sYXIpDQogICAgYXVjX2RvbGFyPC1hdWMocm9jX2NhbGNfZG9sYXIpDQogICAgZ2FuX2RvbGFyPC1zdW0oKHlfcHJlZF9kb2xhciA+KCAwLjAyNSkgKSAqIGlmZWxzZSggY2xhc2VzX21lcz09IDEsIDExNzAwLCAtMzAwICkpDQogICAgDQogICAgDQogICAgI1ByZWRpY2Npb24gbW9kZWxvIHJhbmdvDQogICAgeV9wcmVkX3JhbmdvIDwtIHByZWRpY3QobW9kZWxvX3JhbmcsIGRhdGEubWF0cml4KG1lc19yYW5nKSwgIHR5cGUgPSAicHJvYiIpDQogICAgcHJlZGljY2lvbl9yYW5nbzwtIGlmZWxzZSgoeV9wcmVkX3JhbmdvID4oIDAuMDI1KSksMSwwKQ0KICAgIHJvY19jYWxjX3JhbmdvPC0gcm9jKGNsYXNlc19tZXMscHJlZGljY2lvbl9yYW5nbykNCiAgICBhdWNfcmFuZ288LWF1Yyhyb2NfY2FsY19yYW5nbykNCiAgICBnYW5fcmFuZ288LXN1bSgoeV9wcmVkX3JhbmdvID4oIDAuMDI1KSApICogaWZlbHNlKCBjbGFzZXNfbWVzPT0gMSwgMTE3MDAsIC0zMDAgKSkNCiAgICANCiAgICAjUHJlZGljY2lvbiBtb2RlbG8gbm9ybWFsDQogICAgeV9wcmVkX25vcm1hbCA8LSBwcmVkaWN0KG1vZGVsb19ub3JtLCBkYXRhLm1hdHJpeChtZXNfbm9ybSksICB0eXBlID0gInByb2IiKQ0KICAgIHByZWRpY2Npb25fbm9ybWFsPC0gaWZlbHNlKCh5X3ByZWRfbm9ybWFsID4oIDAuMDI1KSksMSwwKQ0KICAgIHJvY19jYWxjX25vcm1hbDwtIHJvYyhjbGFzZXNfbWVzLHByZWRpY2Npb25fbm9ybWFsKQ0KICAgIGF1Y19ub3JtYWw8LWF1Yyhyb2NfY2FsY19ub3JtYWwpDQogICAgZ2FuX25vcm1hbDwtc3VtKCh5X3ByZWRfbm9ybWFsID4oIDAuMDI1KSApICogaWZlbHNlKCBjbGFzZXNfbWVzPT0gMSwgMTE3MDAsIC0zMDAgKSkNCiAgICANCiAgICANCiAgICAgICAgcmVzdW1lbj1jKG0sIGF1Y19ub20sIGdhbl9ub20sIGF1Y19pcGMsIGdhbl9pcGMsIGF1Y19kb2xhciwgZ2FuX2RvbGFyLCBhdWNfcmFuZ28sZ2FuX3JhbmdvLGF1Y19ub3JtYWwsZ2FuX25vcm1hbCkNCiAgICAgICAgDQogICAgcmVzdW1lbj0gdChyZXN1bWVuKQ0KICAgIA0KICAgIHJlc3VsdGFkb3MgPC0gcmJpbmQocmVzdWx0YWRvcyxyZXN1bWVuKQ0KfQ0KDQpjb2xuYW1lcyhyZXN1bHRhZG9zKTwtYygibWVzIiwiYXVjX25vbWluYWwiLCAiZ2FuYW5jaWFfbm9taW5hbCIsImF1Y19pcGMiLCAiZ2FuYW5jaWFfaXBjIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICJhdWNfZG9sYXIiLCJnYW5hbmNpYV9kb2xhciIsImF1Y19yYW5nb3MiLCJnYW5hbmNpYV9yYW5nb3MiLCJhdWNfbm9ybWFsIiwiZ2FuYW5jaWFfbm9ybWFsIikNCg0KIyMjR3JhZmljbw0KaXBjdjwtaXBjX2hpc3Rvcmljbw0KDQppcGN2JE1lczwtYXMuRGF0ZShwYXN0ZTAoYXMuY2hhcmFjdGVyKGlwY3YkZm90b19tZXMpLCAnMDEnKSwgZm9ybWF0PSclWSVtJWQnKQ0KDQphPC1nZ3Bsb3QoaXBjdiwgYWVzKHggPSBNZXMsIHkgPSBpcGMpKSArIA0KICBnZW9tX2xpbmUoYWVzKGNvbG9yID0gaXBjKSwgc2l6ZSA9IDEuNSkgKyB0aGVtZV9maXZldGhpcnR5ZWlnaHQoKSsNCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiLGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gOTAsIGhqdXN0ID0gMSkpIA0KDQpiPC1nZ3Bsb3QoaXBjdiwgYWVzKHggPSBNZXMsIHkgPSBkb2xhcikpICsgDQogIGdlb21fbGluZShhZXMoY29sb3IgPSBkb2xhciksIHNpemUgPSAxLjUpICsgdGhlbWVfZml2ZXRoaXJ0eWVpZ2h0KCkgKw0KICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAibm9uZSIsYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA5MCwgaGp1c3QgPSAxKSkNCg0KDQphdWNfbWVzZXMgPC0gcmVzdWx0YWRvcyAlPiUNCiAgc2VsZWN0KCJtZXMiLCAiYXVjX25vbWluYWwiLCAiYXVjX2lwYyIsJ2F1Y19kb2xhcicsICJhdWNfcmFuZ29zIiwiYXVjX25vcm1hbCIpICU+JQ0KICBnYXRoZXIoa2V5ID0gInZhcmlhYmxlIiwgdmFsdWUgPSAidmFsdWUiLCAtbWVzKQ0KDQphdWNfbWVzZXMkbWVzPC1hcy5EYXRlKHBhc3RlMChhcy5jaGFyYWN0ZXIoYXVjX21lc2VzJG1lcyksICcwMScpLCBmb3JtYXQ9JyVZJW0lZCcpDQoNCg0KDQpnYW5hbmNpYV9tZXNlcyA8LSByZXN1bHRhZG9zICU+JQ0KICBzZWxlY3QoIm1lcyIsICJnYW5hbmNpYV9ub21pbmFsIiwgImdhbmFuY2lhX2lwYyIsJ2dhbmFuY2lhX2RvbGFyJywgImdhbmFuY2lhX3JhbmdvcyIsICJnYW5hbmNpYV9ub3JtYWwiKSAlPiUNCiAgZ2F0aGVyKGtleSA9ICJ2YXJpYWJsZSIsIHZhbHVlID0gInZhbHVlIiwgLW1lcykNCg0KZ2FuYW5jaWFfbWVzZXMkbWVzPC1hcy5EYXRlKHBhc3RlMChhcy5jaGFyYWN0ZXIoZ2FuYW5jaWFfbWVzZXMkbWVzKSwgJzAxJyksIGZvcm1hdD0nJVklbSVkJykNCg0KDQpgYGANCg0KYGBge3J9DQoNCmF1Y19wbG90PC1nZ3Bsb3QoYXVjX21lc2VzLCBhZXMoeCA9IG1lcywgeSA9IHZhbHVlKSkgKyANCiAgICAgICAgICBnZW9tX2xpbmUoYWVzKGNvbG9yID0gdmFyaWFibGUpLCBzaXplID0gMSkgKyB0aGVtZV9maXZldGhpcnR5ZWlnaHQoKSsNCiAgdGhlbWUobGVnZW5kLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZT03KSxheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDkwLCBoanVzdCA9IDEpKSArDQogICBndWlkZXMoY29sID0gZ3VpZGVfbGVnZW5kKG5yb3cgPSAzKSkNCg0KZ3JpZC5hcnJhbmdlKGF1Y19wbG90LCBhcnJhbmdlR3JvYihhLCBiKSwgbmNvbCA9IDIpDQoNCg0KZ2FuYW5jaWFfcGxvdDwtZ2dwbG90KGdhbmFuY2lhX21lc2VzLCBhZXMoeCA9IG1lcywgeSA9IHZhbHVlLGNvbG9yID0gdmFyaWFibGUpKSArIA0KICAgICAgICAgICAgICBnZW9tX2xpbmUoIHNpemUgPSAxKSArIHRoZW1lX2ZpdmV0aGlydHllaWdodCgpKw0KICAgICAgICAgICAgICB0aGVtZShsZWdlbmQudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplPTcpLGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gOTAsIGhqdXN0ID0gMSkpKw0KICAgICAgICAgICAgICBndWlkZXMoY29sID0gZ3VpZGVfbGVnZW5kKG5yb3cgPSAzKSkNCg0KDQpncmlkLmFycmFuZ2UoZ2FuYW5jaWFfcGxvdCwgYXJyYW5nZUdyb2IoYSwgYiksIG5jb2wgPSAyKQ0KYGBgDQoNCg0KYGBge3J9DQoNCg0KYXVjX21lc2VzIDwtIHJlc3VsdGFkb3MgJT4lDQogIHNlbGVjdCgibWVzIiwgImF1Y19ub21pbmFsIiwgImF1Y19pcGMiLCdhdWNfZG9sYXInKSAlPiUNCiAgZ2F0aGVyKGtleSA9ICJ2YXJpYWJsZSIsIHZhbHVlID0gInZhbHVlIiwgLW1lcykNCg0KYXVjX21lc2VzJG1lczwtYXMuRGF0ZShwYXN0ZTAoYXMuY2hhcmFjdGVyKGF1Y19tZXNlcyRtZXMpLCAnMDEnKSwgZm9ybWF0PSclWSVtJWQnKQ0KDQoNCg0KZ2FuYW5jaWFfbWVzZXMgPC0gcmVzdWx0YWRvcyAlPiUNCiAgc2VsZWN0KCJtZXMiLCAiZ2FuYW5jaWFfbm9taW5hbCIsICJnYW5hbmNpYV9pcGMiLCdnYW5hbmNpYV9kb2xhcicpICU+JQ0KICBnYXRoZXIoa2V5ID0gInZhcmlhYmxlIiwgdmFsdWUgPSAidmFsdWUiLCAtbWVzKQ0KDQpnYW5hbmNpYV9tZXNlcyRtZXM8LWFzLkRhdGUocGFzdGUwKGFzLmNoYXJhY3RlcihnYW5hbmNpYV9tZXNlcyRtZXMpLCAnMDEnKSwgZm9ybWF0PSclWSVtJWQnKQ0KDQoNCmBgYA0KDQoNCmBgYHtyfQ0KDQphdWNfcGxvdDwtZ2dwbG90KGF1Y19tZXNlcywgYWVzKHggPSBtZXMsIHkgPSB2YWx1ZSkpICsgDQogICAgICAgICAgZ2VvbV9saW5lKGFlcyhjb2xvciA9IHZhcmlhYmxlKSwgc2l6ZSA9IDEpICsgdGhlbWVfZml2ZXRoaXJ0eWVpZ2h0KCkrDQogIHRoZW1lKGxlZ2VuZC50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemU9NyksYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA5MCwgaGp1c3QgPSAxKSkgKw0KICAgZ3VpZGVzKGNvbCA9IGd1aWRlX2xlZ2VuZChucm93ID0gMykpDQoNCmdyaWQuYXJyYW5nZShhdWNfcGxvdCwgYXJyYW5nZUdyb2IoYSwgYiksIG5jb2wgPSAyKQ0KDQoNCmdhbmFuY2lhX3Bsb3Q8LWdncGxvdChnYW5hbmNpYV9tZXNlcywgYWVzKHggPSBtZXMsIHkgPSB2YWx1ZSxjb2xvciA9IHZhcmlhYmxlKSkgKyANCiAgICAgICAgICAgICAgZ2VvbV9saW5lKCBzaXplID0gMSkgKyB0aGVtZV9maXZldGhpcnR5ZWlnaHQoKSsNCiAgICAgICAgICAgICAgdGhlbWUobGVnZW5kLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZT03KSxheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDkwLCBoanVzdCA9IDEpKSsNCiAgICAgICAgICAgICAgZ3VpZGVzKGNvbCA9IGd1aWRlX2xlZ2VuZChucm93ID0gMykpDQoNCg0KZ3JpZC5hcnJhbmdlKGdhbmFuY2lhX3Bsb3QsIGFycmFuZ2VHcm9iKGEsIGIpLCBuY29sID0gMikNCmBgYA0KDQojIENvbmNsdXNpb25lcw0KDQoqIExvcyBhanVzdGUgcG9yIHJhbmdvcyAocGVyY2VudGlsZXMpIHkgbm9ybWFsaXphZG8gc29uIGNsYXJhbWVudGUgcGVvcmVzIGFsIGJlbmNobWFyayAodmFyYWlibGVzIG5vbWluYWxlcykuDQoNCiogTG9zIGFqdXN0ZXMgcG9yIElQQyB5IGTDs2xhciBsb2dyYW4gc3VwZXJhciBhbCBiZW5jaG1hcmsgZW4gYWxndW5vcyBjYXNvcyBwZXJvIG5vIGVzdMOhIGNsYXJvIHF1ZSBzZWFuIHN1cGVyaW9yZXMuDQoNCiogRXN0YXMgb2JzZXJ2YWNpb25lcyBzZSB2ZXJpZmljYW4gdGFudG8gcGFyYSBlbCBBVUMgY29tbyBwYXJhIGxhIGdhbmFuY2lhLg0KDQoqIFVuYSB2ZXRhIGEgZXhwbG9yYXIgZXMgaW5jb3Jwb3JhciB2YXJpYWJsZXMgcmV6YWdhZGFzIGVuIGVsIG1lcyBlbiBjdXJzbyAoaS5lLiBtY3VlbnRhc2FsZG8sIG1jdWVudGFzYWxkb190XzEsIG1jdWVudGFzYWxkb190XzIpDQoNCg==