¿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

Formas de medir el nivel general de precios

1) Deflactor del PIB: El deflactor del PIB (\(DPIB\)) es un índice que mide el precio medio de los bienes y servicios producidos en un año de referencia.

\[DPIB_t = \frac{\sum^N_{i=1}{p^i_t.q^i_t}}{\sum^N_{i=1}p^i_0.q^i_t}*100 = \frac{\text{PIB a precios corriente}}{\text{PIB a precios de año base}}\] Con

  • \(q^i_t\) la cantidad del bien i en el período t
  • \(p^i_t\) precio del bien i en el período t
  • \(p^i_0\) el precio del bien i en el período de referencia (en Argentina es 2004 actualmente)

2) Inflación medida por el IPC: El índice de precios al consumidor (IPC) mide el costo de una canasta de bienes y servicios que los hogares suelen comprar en un período de referencia \[IPC_t = \frac{\sum^N_{i=1}{p^i_t.q^i_0}}{\sum^N_{i=1}p^i_0.q^i_0}*100 = \frac{\text{Canasta a precios corrientes}}{\text{Canasta a precios de período de referencia}}\]

3) Otras menos conocidas : El índice de precios al por mayor (IPM) o el índice de precios al productor (IPP)

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)

Conclusiones

  • Los ajuste por rangos (percentiles) y normalizado son claramente peores al benchmark (varaibles nominales).

  • Los ajustes por IPC y dólar logran superar al benchmark en algunos casos pero no está claro que sean superiores.

  • Estas observaciones se verifican tanto para el AUC como para la ganancia.

  • Una veta a explorar es incorporar variables rezagadas en el mes en curso (i.e. mcuentasaldo, mcuentasaldo_t_1, mcuentasaldo_t_2)

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