Introducción

Los accidentes de tráfico o accidentes de tránsito son siniestros viales que perturban el funcionamiento normal de una vía, este debe involucrar a un vehículo automotor. Estos sucesos son clasificados según sus repercusiones (su gravedad: solo daños materiales, heridos, muertos, etc.) y su tipo (Choques, atropellos).

Atropello Choque Volcamiento

En este documento se presenta el ajuste del número de accidentes del área Urbana de la ciudad de Medellín en función del tiempo, los datos que se presentaran cumplen con las características de una serie de tiempo, por lo que metodologías aptas para el modelamiento de estas son claras candidatas a la hora de elegir un modelo para explicar el número de accidentes. Sin embargo, se pueden encontrar diferencias significativas en el número de accidentes registrados según divisiones territoriales como barrios o comunas, considerar esto significaría ajustar múltiples modelos, uno para cada división territorial que se considere.

Los modelos mixtos, jerárquicos o multinivel, son una metodología que permite crear un único modelo mientras se diferencia por una variable de agrupamiento, que usualmente representa sujetos u objetos de los que se tienen repetidos registros, permitiendo involucrar efectos aleatorios que cambian de sujeto a sujeto.

En el presente trabajo se utilizan los modelos multinivel generalizados para ajustar dos modelos: el primero un modelo con respuesta Poisson para en número total de accidentes y el segundo, un modelo Multinomial para el número de accidentes según la clase (este último es tan solo un añadido). Ambos modelos son complementarios, ya que el modelo multinomial requiere de una estimación del total de accidentes para realizar las predicciones de la cantidad de accidentes según la categoría. Se utilizara como variable de agrupamiento las comunas.

Para mejorar la legibilidad del documento se ocultaron algunas lineas de código, pero se facilita la descarga del rmd utilizado para generar el documento en la parte superior, al lado del titulo.

Carga de librerías

#CAGRA DE LIBRERIAS
## Manejo de bases de datos
library(dplyr)
library(magrittr)
## Gráficos
library(ggplot2)
library(lubridate)
## Ajuste de modelos mixtos
library(lme4)
library(brms)
## Manejo de fechas
library("zoo") 
## Tablas latex
library(kableExtra)

Objetivos

  • Construir un modelo predictivo para el número de accidentes ocurridos en la ciudad de Medellín a nivel comunal en intervalos mensuales, con base a los datos de años del 2014-2019 utilizando la regresión multinivel (conocida también como modelos jerárquicos o mixtos), utilizando los paquetes lmea4y brms de R.
  • Comprender la forma en que la accidentalidad se relaciona con el tiempo para las comunas de Medellín.

Conjunto de datos:

Los datos análizados en el presente documento se obtienen de la página del portal GeoMedellín de la Alcaldía de Medellín en su sección de datos abiertos. Corresponden a las bases de “Accidentalidad georreferenciada” entre los años 2014 y 2019, los elementos de dichas bases representan un accidente registrado por la Secretaría de Movilidad de la Alcaldía de Medellín y presentan una serie de covariables que sirven para categorizar el tipo de accidente, el momento de su incidencia y su ubicación georreferenciada.

Para el ajuste de los modelos se descartaron algunas de las covariables (no interesantes para modelar la accidentalidad) y se realizaron cambios al formato de los datos (las modificaciones realizadas y los pasos para construir el conjunto de datos que se utiliza aquí pueden ser consultados en detalle aquí). En síntesis, se limitó el estudio a las 16 comunas de la ciudad de Medellín (descartándose aquellos accidentes ocurridos en corregimientos), se omitieron covariables relativas a la georreferenciación y se agruparon los registros por barrios en periodos mensuales, para obtener la cantidad de accidentes ocurridos distinguidos por su clase.

Los datos definitivos poseen los siguientes atributos:

  • COMUNA: las 16 comunas de Medellín con niveles ‘Aranjuez’, ‘Belén’, ‘Buenos Aires’, ‘Castilla’, ‘Doce de Octubre’, ‘El Poblado’, ‘Guayabal’, ‘La América’, ‘La Candelaria’, ‘Laureles Estadio’, ‘Manrique’, ‘Popular’, ‘Robledo’, ‘San Javier’, ‘Santa Cruz’, ‘Villa Hermosa’.

  • BARRIO: los barrios de cada comuna con 265 niveles.

  • PERIODO: año en el que ocurren los accidentes.

  • MES: con niveles ‘January’, ‘February’, ‘March’, ‘April’, ‘May’, ‘June’, ‘July’, ‘August’, ‘September’, ‘October’, ‘November’, ‘December’.

  • FECHA: en formato “YY/MM”.

  • t: tiempo transcurrido, una conversión numérica de la FECHA para agregar en el modelo, equivalente al número de días transcurridos desde la fecha de referencia 2014/01/01 hasta el tiempo del registro. Dado que los registros representan periodos mensuales, el tiempo del registro corresponderá a los días transcurridos a la mitad del MES.

  • Accidentalidad: número de accidentes según tipo de categoría (también llamada CLASE).

    • Atropello: número de accidentes de esta categoría de accidentes.

    • Caida.Ocupante: número de accidentes de esta categoría de accidentes.

    • Choque: número de accidentes de esta categoría de accidentes.

    • Incendio: número de accidentes de esta categoría de accidente.

    • Volcamiento: número de accidentes de esta categoría de accidentes.

    • Otro: número de accidentes de esta categoría de accidentes.

  • nro.accidentes: total de accidentes, suma de los accidentes de todas las categorías. Variable respuesta.

Carga del conjunto de datos

A continuación se presenta como cargar el conjunto de datos y se construyen t y FECHA:

## Carga de conjunto de datos a nivel barrial

#data_men_all <- read.csv("Datasets/base_mensual_barrios_y_comunas.csv", encoding='UTF-8')

url <- "https://raw.githubusercontent.com/jfmra99/Modelos_Jerarquicos/master/AplicacionRPubs/Datasets/base_mensual_barrios_y_comunas.csv"
data_men_all <- read.csv(url, encoding='UTF-8')

## Verificación de covariables como factor
data_men_all[,c(2,3,4)] %<>% lapply(function(x) factor(as.character(x)))

## Creación de covariables FECHA y t, en base a las otras covariables
data_men_all$FECHA <- paste(data_men_all$PERIODO, data_men_all$MES, sep="-") %>% as.yearmon("%Y-%m")
# Modificación de MES a su nombre en inglés
data_men_all$MES <- factor(months(data_men_all$FECHA), levels =month.name[1:12])

# Para obtener la inversa se usaría: zoo::as.Date(data_men_all$FECHA, origin="2014-01-01")
data_men_all$t <- as.numeric(as.Date(data_men_all$FECHA, frac=0.5)) - as.numeric(as.Date("2014-01-01"))

Los accidentes del anterior conjunto son dados a nivel barrial, por lo que los agrupamos por comunas, el objeto data_men_comunas tiene los datos con los que se ajustaran los modelos. Mientras que tidy_data_men_all_comunas es una base de apoyo para construir gráficos.

## Construcción del conjunto de datos a utilizar, conseguido por Comunas.
data_men_comunas <- data_men_all %>% group_by(COMUNA, PERIODO, MES,FECHA, t) %>%
  summarise(nro.accidentes = sum(nro.accidentes), 
            Atropello = sum(Atropello), 
            Caida.Ocupante = sum(Caida.Ocupante),
            Choque=sum(Choque),
            Volcamiento = sum(Volcamiento),
            Otro = sum(Otro))

## Organización de bases de datos en formato apto para gráficar.


tidy_data_men_all <- tidyr::gather(data_men_all, "CLASE", "nro.accidentes", 5:9)

tidy_data_men_all_comunas <- tidy_data_men_all%>% group_by(COMUNA, t, CLASE) %>%
  summarise(nro.accidentes = sum(nro.accidentes))

A continuación se presenta el conjunto de datos:

Se puede ver que se tienen 12 registros por cada año para cada una de las 16 comunas, ya que los datos corresponden a un periodo de 6 años se tienen \(12*16*6=1152\) registros.

Análisis descriptivo

Nuestro objetivo primordial es predecir nro.accidentes en función de las covariables temporales, por lo que realizamos el gráfico de la serie de tiempo correspondiente a los accidentes de todas las Comunas juntas:

#Accidentalidad conjunta de TODAS las Comunas:
temp <- data_men_comunas %>% group_by(FECHA) %>% 
  summarise(nro.accidentes = sum(nro.accidentes))
## SERIE DE TIEMPO para la 
ts_monthly <- ts(temp$nro.accidentes, start=c(2014,1),frequency=12)
plot(ts_monthly)

Las series de tiempo tienen componentes de tendencia y estacionalidad. Este último corresponde a comportamientos que se repiten cada cierto tiempo en la serie, existen gráficos que evaluan que periodicidad (anual, trimestral, semestral etc.) tomar como el periodograma, pero sin necesidad de recurrir a él, del gráfico de la serie presentado anteriormente se pueden notar comportamientos marcados para algunos meses entre el 2014 y el 2018, (por ejemplo, la accidentalidad cae al mínimo principio de cada año en el mes de Enero). En el 2019 se puede intuir que se conservan los comportamientos periódicos, pero parece que ocurre un ciclo que aumento el número de accidentes en el segundo semestre del año. Debido a esto se sospecha que los datos tienen una periodicidad anual, por los que la covariable MES es candidata a ser relevanta para el modelamiento del número de accidentes.

La tendencia en cambio, describe comportamiento general de la serie (Restando los periodos). Se puede obtener una forma aproximada de la tendencia de la seria por medio de decompose:

plot(decompose(ts_monthly)$trend,ylim=c(min(ts_monthly),max(ts_monthly)), ylab = "accidentes")

Se puede ver que la tendencia varia entre 3200 y 3600 accidentes, por lo que se puede hablar de una tendencia de crecimiento/decrecimiento marcada. Para modelarla se puede recurrir polinomio del tiempo, dado que se pueden apreciar varias concavidades, un polinomio de grado 3 o 4 debería ser adecuado.

Ahora exploraremos la cantidad de accidentes según la comuna y su CLASE, a continuación se presenta una tabla con el total de accidentes de los 6 años registrados para cada una de las comunas:

COMUNA nro.accidentes Atropello Caida.Ocupante Choque Volcamiento Otro
La Candelaria 52792 5120 3171 39342 1253 3906
Laureles Estadio 28385 1733 1915 21407 708 2622
Castilla 25359 1875 2619 16757 919 3189
El Poblado 20865 707 952 17240 532 1434
Guayabal 18343 1151 1205 13618 632 1737
Belén 16608 1243 1221 11862 585 1697
Robledo 16550 1382 2466 9551 621 2530
Aranjuez 14975 2038 1485 9143 538 1771
Buenos Aires 9554 1017 911 5907 465 1254
La América 8243 683 701 5790 221 848
Manrique 7791 1641 964 3762 360 1064
Doce de Octubre 6951 1355 1325 2890 247 1134
Villa Hermosa 6688 1096 792 3602 314 884
San Javier 4435 757 606 2223 214 635
Popular 3662 1074 489 1450 155 494
Santa Cruz 3393 802 366 1687 125 413

El total de accidentes varía mucho de una comuna a otra, por lo que se sospecha que existen diferencias marcadas entre las Comunas. Esto se puede apreciar mucho mejor en el siguiente gráfico de los accidentes dado el tiempo para cada una de las 16 comunas, en este y los demás gráficos que involucren el conteo de accidentes se utilizará la escala logarítmica, para que la escala permita comparar las diferentes comunas:

Se puede ver que efectivamente existe una diferencia en la cantidad de accidentes registrados de una comuna a otra. Esto nos dice que utilizar la COMUNA como la variable de agrupamiento, en base al anterior gráfico la adición de un intercepto aleatorio parece razonable, en cambio dado que que no hay diferencias de tendencia marcadas entre las comunas, se descarta la inclusión de una pendiente aleatoria y se considera que el comportamiento es similar entre ellas.

Se puede alcanzar la misma conclusión si se gráfica el número de accidentes haciendo distinción por su clase:

Ahora veremos la densidad muestral de la cantidad de accidentes según las comunas:

## Warning: Removed 39 rows containing non-finite values (stat_density).

Se puede ver la presencia de diferentes modas, pero esto puede ser explicado por las diferencias del número de accidentes según el mes. Más adelante en el documento, se considerará que el número de accidentes de distribuye \(Poisson\), por lo que este gráfico sirve como argumento para considerar que la media esperada dependerá de covariables como el tiempo. Además, se puede ver el cambio de forma de las densidades entre las comunas.

También se presentan las densidades según la CLASE del accidente:

## Warning: Removed 39 rows containing non-finite values (stat_density).

Nuevamente se puede ver el cambio de forma de las densidades entre las comunas. Lo cual es confirmado al realizar una gráfica de barras de probabilidad:

Se puede ver que la proporción de algunas clases de accidente como los Atropellos son notablemente mayores para algunas comunas como Santa Cruz y Popular, y en general varían considerablemente entre las comunas. Lo mismo ocurre en los Choques y los accidentes con Caída de Ocupante. Mientras que otras como los volcamientos los accidentes de clase “Otro” parecen tener una proporción constante entre las comunas. La conclusión general del gráfico es que las proporciones según la clase son afectadas por la variable de agrupamiento COMUNA

Modelación y Ajuste

Modelo con respuesta Poisson

Denotaremos el número de accidentes para el tiempo \(y\) de la comuna \(j\) como \(n_{ij}\) y la modelaremos por medio de una regresión Poisson:

\[n_{ij} \sim Poisson(\lambda_{ij})\] Entonces queremos encontrar una expresión que relacione a \(\lambda_{ij}\) con las variables temporales y las comunas.

Modelos propuestos

Con base al análisis descriptivo, se tiene que la tendencia general del modelo tiene que ser modelada a través de un polinomio de alto grado para captar sus concavidades (inicialmente se considera que el grado mínimo debe ser 3). Además, dado que realmente no se notaron tendencias marcadas respecto al número de accidentes según la comuna, se descartan modelos con pendiente aleatoria y se restringe a modelo con intercepto aleatorio.

Denótese:

\[j: Comuna\; (1:16) \\ i: observación\; correspondiente\; a\; un\;mes \; entre \; 2014 \; y \; 2019 \; (1:72)\] Adicionalmente se notó una periodicidad anual marcada, por lo que para modelarla la variable MES será incluida en los modelos de la siguiente forma: \[\sum\limits_{k=1}^{11}{\delta_{k}}MES_{ijk}\;\; donde\;\; MES_{ik} = \left\{ \begin{matrix} 1 \quad si ~ la ~observación ~ij~ está~ en~la~ estación~k \\ 0 \quad~ otro~caso\end{matrix} \right\}\]

\[k = 1: Febrero, ~ k=2: Marzo, ..., k=10: Noviembre, ~ k=11: Diciembre\]

Modelo 1

Polinomio de grado 3 en función del tiempo, con estacionalidad según el MES e intercepto aleatorio:

\[\log (\lambda_{ij}) = \beta_0 + \beta_1 t + \beta_2t^2 + \beta_3t^3+\sum\limits_{k=1}^{11}{\delta_{k}}MES_{ijk} + b_{0j}\] \[b_{0j} \sim N(0, \sigma_{b0})\]

Modelo 2

Polinomio de grado 4 en función del tiempo, con estacionalidad según el MES e intercepto aleatorio:

\[\log (\lambda_{ij}) = \beta_0 + \beta_1 t + \beta_2t^2 + \beta_3 t^3+ \beta_4 t^4 +\sum\limits_{k=1}^{11}{\delta_{k}}MES_{ijk} + b_{0j}\] \[b_{0j} \sim N(0, \sigma_{b0})\]

Modelo 3

Polinomio de grado 5 en función del tiempo, con estacionalidad según el MES e intercepto aleatorio:

\[\log (\lambda_{ij}) = \beta_0 + \beta_1 t + \beta_2t^2 + \beta_3 t^3+ \beta_4 t^4+ \beta_5 t^5 +\sum\limits_{k=1}^{11}{\delta_{k}}MES_{ijk} + b_{0j}\]

\[b_{0j} \sim N(0, \sigma_{b0})\]

Modelo 4

Polinomio de grado 6 en función del tiempo, con estacionalidad según el MES e intercepto aleatorio:

\[\log (\lambda_{ij}) = \beta_0 + \beta_1 t + \beta_2t^2 + \beta_3 t^3+ \beta_4 t^4 + \beta_5 t^5 + \beta_6 t^6 +\sum\limits_{k=1}^{11}{\delta_{k}}MES_{ijk}+ b_{0j}\]

\[b_{0j} \sim N(0, \sigma_{b0})\]

Ajuste con R

Se realiza el ajuste de los modelos por medio de la función glmer de la libreria lme4, añadiendo el atributo family= poisson() para modelar la distribución de \(n_{ij}\).

## glmer attempts

##Modelo1
mod1 <- glmer(nro.accidentes ~ poly(t, 3)+MES+ (1|COMUNA),
            data = data_men_comunas, family= poisson())
##Modelo2
mod2 <- glmer(nro.accidentes ~ poly(t, 4)+MES+ (1|COMUNA),
            data = data_men_comunas, family= poisson())
##Modelo3
mod3 <- glmer(nro.accidentes ~ poly(t, 5)+MES+ (1|COMUNA),
            data = data_men_comunas, family= poisson())
##Modelo4
mod4 <- glmer(nro.accidentes ~ poly(t, 6)+MES+ (1|COMUNA),
            data = data_men_comunas, family= poisson())


# Guardado de los modelos
save(mod1, mod2, mod3, mod4, file = "Modelos/comuna_glmer.RData")

Comparación de modelos

En esta sección se elegirá uno de los modelos mostrados anteriormente, probando la significancia de los parámetros añadidos por medio del test de razón de verosimilitud. Considérese dos modelos: \(ModeloA\) y \(ModeloB\), con vectores de parámetros \(\theta^A\) y \(\theta^B\) respectivamente, que cumplen \(\theta^A \subset \theta^B\). Denotemos a los parámetros del \(ModeloB\) que no están es el \(ModeloA\) como \(\theta^c\) un vector de dimensión \(p\), entonces la prueba de hipótesis asociada a la significancia de estos parámetros será:

\[H_0: \theta^c = 0_{1\times p} \quad v.s \quad H_1: \theta^c \not= 0_{1\times p}\]

Cuyo estadístico de prueba es:

\[LR = -2 \times (loglikelihood(ModeloA)- loglikelihood(ModeloB))\]

A un nivel de significancia \(\alpha\) se rechaza \(H_0\) si \(VP =P(\chi^2_p > LR) < \alpha\)

Esa prueba se dice es anti-conservativa, es decir que su \(VP\) será más pequeños de lo normal, por lo que usualmente se utiliza en lugar de \(\chi^2_p\) la distribución muestral del estadístico, la cual puede ser estimada por métodos de remuestreo. Sin embargo, dada la naturaleza de serie de tiempo que tiene el conjunto de datos presentado, utilizar una técnica de remuestreo no tiene mucho sentido, por lo que en su lugar fijaremos un nivel de significancia más riguroso y por ende más pequeño de lo usual, haciendo \(\alpha = 0.01\).

A continuación, se presentan las pruebas de hipótesis para cada comparación:

Modelo 1 v.s Modelo 2

\[H_0: \beta_4 = 0 \quad v.s \quad H_1: \beta_4 \not=0\]

anova(mod1, mod2)

Con un \(VP = 2.2e-16 < 0.01\) se rechaza la hipótesis nula y se considera que \(\beta_4\) es significativa.

Modelo 2 v.s Modelo 3

\[H_0: \beta_4 = 0 \quad v.s \quad H_1: \beta_4 \not=0\]

anova(mod2, mod3)

Con un \(VP = 0.01764 > 0.01\) no se puede rechazar la hipótesis nula al nivel de significancia establecido y se considera que \(\beta_4\) es no significativa.

Modelo 2 v.s Modelo 4

En este caso se espera que se obtenga el mismo resultado que en la prueba del Modelo 2 v.s Modelo 3, pero igualmente se incluye:

\[H_0: \beta_4 = \beta_5 = 0 \quad v.s \quad H_1: \beta_4 \not=0 ~ | ~ \beta_5 \not=0 \]

anova(mod2, mod4)

Con un \(VP = 0.05913 > 0.01\) no se puede rechazar la hipótesis nula al nivel de significancia establecido y se considera que \(\beta_4\) y \(\beta_5\) son no significativas.

De las pruebas anteriores se encuentra que el modelo óptimo es el numero 2, por lo que se procede a realizar el análisis de sus residuales.

Evaluación de residuales

Queremos chequear si se cumplen los típicos supuestos de varianza constante y normalidad de los residuales. Pero además, se evaluará si existe falta de ajuste respecto al tiempo y el supuesto de normalidad de los interceptos aleatorios \[b_{0j} \sim N(0, \sigma_{b0})\]

Los gráficos de la primera fila, correspondientes a los residuales estandarizados contra los valores ajustados (A) y a los residuales estandarizados contra el tiempo (B), no muestran ningún indicio de heterocedasticidad. los residuales en (B) no tienen ninguna tendencia marcada y se dispersan aleatoriamente, por lo que se considera no hay falta de ajuste del modelo.

En la segunda fila encontramos los qqplot de los residuales estandarizados (C) y de los intervalos aleatorios ajustados (D). De (C) se puede ver que los cuantiles de los residuales se desvían de los cuantiles teóricos, por lo que seguirían una distribución de cola pesada. De (D) no se encuentran evidencias gráficas contundentes contra la normalidad de los interceptos aleatorios.

El summary() del modelo se presenta a continuación:

summary(res1)
## data: t, r, y, w [1152x4]
## mapping:  x = ~w
## scales:   x, xmin, xmax, xend, xintercept, xmin_final, xmax_final, xlower, xmiddle, xupper, x0 
## faceting: <ggproto object: Class FacetNull, Facet, gg>
##     compute_layout: function
##     draw_back: function
##     draw_front: function
##     draw_labels: function
##     draw_panels: function
##     finish_data: function
##     init_scales: function
##     map_data: function
##     params: list
##     setup_data: function
##     setup_params: function
##     shrink: TRUE
##     train_scales: function
##     vars: function
##     super:  <ggproto object: Class FacetNull, Facet, gg>
## -----------------------------------
## geom_density: na.rm = FALSE
## stat_density: na.rm = FALSE
## position_identity

Expresión del modelo

\[\log (\widehat{\lambda_{ij}}) = 4.9180 -0.1385t + 0.0906t^2 + 0.6405t^3+ 0.9706 t^4 +0.1074MES_{Febrero}+\\0.1680MES_{marzo}+0.1287MES_{Abril}+0.1924MES_{Mayo}+0.1126MES_{Junio}+\\ 0.1855MES_{Julio}+0.2369MES_{Agosto}+ 0.2147MES_{Septiembre}+ 0.2028MES_{Octubre}+\\0.1274MES_{Noviembre}+0.1641MES_{Diciembre} + b_{0j}\]

Los valores estimados de \(b_{0j}\) se muestran a continuación:

j Comuna b0
1 Aranjuez 0.2636229
2 Belén 0.3671174
3 Buenos Aires -0.1857351
4 Castilla 0.7903509
5 Doce de Octubre -0.5037175
6 El Poblado 0.5952949
7 Guayabal 0.4664752
8 La América -0.3332942
9 La Candelaria 1.5235809
10 Laureles Estadio 0.9030769
11 Manrique -0.3896728
12 Popular -1.1441775
13 Robledo 0.3636193
14 San Javier -0.9528285
15 Santa Cruz -1.2203906
16 Villa Hermosa -0.5422732

Y la estimación de su varianza es: \(\widehat{\sigma^2_{b0}} = 0.5765\)

Modelo Ajustado

A continuación se muestra el modelo ajustado sobre los datos reales para cada una de las 16 comunas del área urbana:

Aranjuez

Belén

Buenos Aires

Castilla

Doce de Octubre

El Poblado

Guayabal

La América

La Candelaria

Laureles Estadio

Manrique

Robledo

San Javier

Santa Cruz

Villa Hermosa

Modelo con respuesta Multinomial

Como se notó en el análisis descriptivo, existen diferencias en la cantidad de accidentes según la CLASE, por lo que adicional al modelo Poisson, se presenta el ajuste una regresión con respuesta multinomial la cual puede diferenciarse de la más conocida regresión logística Multinomial, que es un método de clasificación, la respuesta multinomial tiene por respuesta conteo en diferentes categorías. Sean:

\[o = Atropello,\;\; p = Caida.Ocupante,\;\; q = Choque,\;\; r = Volcamiento,\;\; s = Otro \\ j: Comuna\; (1:16) \\ i: observación\; correspondiente\; a\; un\;mes \; entre \; 2014 \; y \; 2019 \; (1:72)\]

Ell vector de Accidentalidad \(y_{i,j}\):

\[y_{i,j} = (y_{i,j}^o, y_{i,j}^p, y_{i,j}^q, y_{i,j}^r, y_{i,j}^s)\]

Con un total de accidentes (nro.accidentes) dado por: \[n_{ij} = y_{i,j}^o + y_{i,j}^p + y_{i,j}^q + y_{i,j}^r + y_{i,j}^s\]

Y \(\theta_{ij}\) el vector de probabilidad según la clase del accidente.

\[\theta_{ij} = (\theta_{ij}^o, \theta_{ij}^p,\theta_{ij}^q, \theta_{ij}^r, \theta_{ij}^s)\]

Para ajustar nuestro modelo consideraremos que:

\[y_{ij}|\theta_{ij} \sim Multinomial(n_{ij}, \theta_{ij})\]

\[\theta_i = Softmax(0, \mu_j^p,\mu_j^q, \mu_j^r, \mu_j^s)\]

Entonces, nuestro objetivo es modelar \(\mu_j^p,\mu_j^q, \mu_j^r, \mu_j^s\) incluyendo covariables.

Para ajustar el modelo utilizaremos el paquete brmsde R, que permite ajustar modelo multinivel considerando una gran variedad de distribuciones para la variable respuesta y tiene un gran fundamento en la estadística Bayesiana. Sin embargo, se ha de mencionar que la familia multinomial es relativamente nueva en brms, por lo que carece de muchos estadísticos comparativos y metodologías para realizar comparaciones entre modelos o probar la significancia de efectos. Un modelo podría ser elegido en base a su capacidad predictiva, realizando métodos de validación cruzada (específicos para series de tiempo), tal y como expone [3]. Sin embargo, brms por sus metodologías bayesianas para el ajuste, consume muchos recursos computacionales y consiguientemente, tarda mucho en su ajuste, por lo que calcular múltiples modelos es una tarea larga y tediosa.

Dado que el ajuste de este modelo no es el objetivo principal de este documento y es tan solo un añadido que parte de la curiosidad de quien escribe estas palabras, se ajustará un único modelo.

Ajuste del modelo

\[\mu_j^p = \beta_0^p + \beta_1^p t + \beta_2^pt^2 + \beta^p_3 t^3 +\sum\limits_{k=1}^{11}{\delta^p_{k}}MES_{ijk} + b^p_{0j}\] \[\mu_j^q = \beta_0^q + \beta_1^q t + \beta_2^qt^2 + \beta^q_3 t^3+\sum\limits_{k=1}^{11}{\delta^q_{k}}MES_{ijk} + b^q_{0j}\] \[\mu_j^r = \beta_0^r + \beta_1^r t + \beta_2^rt^2 + \beta^r_3 t^3+\sum\limits_{k=1}^{11}{\delta^r_{k}}MES_{ijk} + b^r_{0j}\] \[\mu_j^s = \beta_0^s + \beta_1^s t + \beta_2^st^2 + \beta^s_3 t^3 +\sum\limits_{k=1}^{11}{\delta^s_{k}}MES_{ijk} + b^s_{0j}\]

Con \(b^p_{0}\sim N(0, \sigma^2_{b^p_{0}})\), \(b^q_{0}\sim N(0, \sigma^2_{b^q_{0}})\), \(b^r_{0}\sim N(0, \sigma^2_{b^r_{0}})\) y \(b^s_{0}\sim N(0, \sigma^2_{b^s_{0}})\)

Código en R:

El ajuste de este modelo se realizó basado en los ejemplos de [1] y [2]. Primero se hace necesario indicarle a brms cuales son las categorías para las que va a predecir, esto se hace de esta manera:

data_men_comunas$Accidentalidad <- with(data_men_comunas, cbind(Atropello, Caida.Ocupante, Choque, Volcamiento, Otro))

Luego el modelo es ajustado utilizando:

formula1 <- bf( Accidentalidad | trials(nro.accidentes) ~ poly(t, 3) + MES + (1 | COMUNA))
fit1 <- brm(formula1, data = test_Data, family = multinomial(), seed = 314, cores= 4)

Expresión del modelo estimado

\[\widehat{\mu^p} = -0.17 +1.53 t -0.45 t^2 -1.30 t^3 -0.04 MES_{February} + 0.06 MES_{March}\\ + 0.02 MES_{April} +0.10MES_{May} -0.05MES_{June} + 0.01MES_{July} +0.15MES_{August} + 0.08MES_{September}\\ + 0.03MES_{October} +0.09MES_{November} -0.04MES_{December} + b^p_{0}\]

\[\widehat{\mu^q} = 3.25 -1.81 t -1.81 t^2 -1.04 t^3 +0.07 MES_{February} - 0.00 MES_{March}\\ + 0.08 MES_{April} +0.08 MES_{May} +0.02MES_{June} + 0.05 MES_{July} +0.06MES_{August} + 0.04 MES_{September}\\ + 0.06 MES_{October} + 0.06 MES_{November} -0.04MES_{December} + b^q_{0}\]

\[\widehat{\mu^r} = -1.26 -3.82 t +3.91 t^2 +0.07 t^3 -0.04 MES_{February} -0.00 MES_{March}\\ + 0.13 MES_{April} + 0.11 MES_{May} +0.14 MES_{June} + 0.16 MES_{July} +0.16MES_{August} + 0.12MES_{September}\\ + 0.17MES_{October} +0.17MES_{November} +0.01MES_{December} + b^r_{0}\]

\[\widehat{\mu^s} = 0.03 +2.43 t -1.67 t^2 + 0.42 t^3 -0.00 MES_{February} - 0.08 MES_{March}\\ -0.05 MES_{April} + 0.06 MES_{May} - 0.00MES_{June} + 0.08MES_{July} +0.05MES_{August} + 0.04MES_{September}\\ + 0.02 MES_{October} - 0.02MES_{November} -0.09MES_{December} + b^p_{0}\]

Con estimación de efectos aleatorios:

ranef(fit1)
## $COMUNA
## , , muCaidaOcupante_Intercept
## 
##                     Estimate Est.Error        Q2.5       Q97.5
## Aranjuez         -0.17633503 0.1103515 -0.39641088  0.03923586
## Belén             0.11234978 0.1100846 -0.10408913  0.32507215
## Buenos Aires      0.02353400 0.1118086 -0.20053442  0.24226193
## Castilla          0.46421326 0.1078272  0.24385820  0.67452564
## Doce de Octubre   0.11530043 0.1095012 -0.10731818  0.32724246
## El Poblado        0.40995730 0.1142855  0.18523787  0.63664518
## Guayabal          0.17442081 0.1109708 -0.04346020  0.39200274
## La América        0.15818200 0.1153638 -0.06896101  0.38222401
## La Candelaria    -0.33996102 0.1062530 -0.55341313 -0.13627760
## Laureles Estadio  0.23276200 0.1089999  0.01540726  0.45050019
## Manrique         -0.38530005 0.1109014 -0.60915505 -0.16963704
## Popular          -0.62892691 0.1161356 -0.85824658 -0.40264120
## Robledo           0.70912014 0.1086911  0.49335820  0.91791067
## San Javier       -0.07783837 0.1160330 -0.31644390  0.14968296
## Santa Cruz       -0.62164818 0.1199816 -0.86470707 -0.38860883
## Villa Hermosa    -0.18321080 0.1125102 -0.41102886  0.03027084
## 
## , , muChoque_Intercept
## 
##                     Estimate Est.Error         Q2.5       Q97.5
## Aranjuez         -0.17964631 0.2269217 -0.623603546  0.28826907
## Belén             0.56543043 0.2275043  0.129524181  1.03688482
## Buenos Aires      0.07276403 0.2288188 -0.365839712  0.54172839
## Castilla          0.49973461 0.2263414  0.063099844  0.95623166
## Doce de Octubre  -0.92548920 0.2279626 -1.369956621 -0.46044689
## El Poblado        1.48718262 0.2275926  1.051009034  1.94917304
## Guayabal          0.77844484 0.2279301  0.339581113  1.23864579
## La América        0.45123315 0.2283199  0.008402249  0.92122259
## La Candelaria     0.35785731 0.2264577 -0.082027794  0.81802482
## Laureles Estadio  0.82765424 0.2272842  0.385293218  1.28682341
## Manrique         -0.84386603 0.2273367 -1.284379943 -0.37970620
## Popular          -1.36875564 0.2291793 -1.807781777 -0.90459627
## Robledo           0.24454496 0.2273629 -0.186766797  0.71259579
## San Javier       -0.59852315 0.2283576 -1.037116049 -0.13374706
## Santa Cruz       -0.92381070 0.2306542 -1.374102641 -0.44599501
## Villa Hermosa    -0.48853926 0.2278985 -0.932435497 -0.02829169
## 
## , , muVolcamiento_Intercept
## 
##                      Estimate Est.Error        Q2.5        Q97.5
## Aranjuez         -0.188126739 0.1375472 -0.47319240  0.079181001
## Belén             0.373479626 0.1371022  0.09775886  0.639987413
## Buenos Aires      0.346128366 0.1386338  0.06788652  0.622129113
## Castilla          0.420207804 0.1340944  0.14279893  0.685373484
## Doce de Octubre  -0.548467923 0.1429298 -0.83713319 -0.261412830
## El Poblado        0.823750674 0.1381171  0.54453138  1.095997320
## Guayabal          0.525571749 0.1369229  0.25399286  0.800126041
## La América        0.009832633 0.1461457 -0.28865850  0.295376608
## La Candelaria    -0.267687045 0.1320386 -0.53401125 -0.006857978
## Laureles Estadio  0.241080256 0.1354838 -0.03913449  0.509678349
## Manrique         -0.367388682 0.1389197 -0.64676351 -0.091710126
## Popular          -0.761581347 0.1524242 -1.06914341 -0.456985946
## Robledo           0.336005725 0.1351578  0.07039200  0.603987230
## San Javier       -0.109303704 0.1492565 -0.40065837  0.187427923
## Santa Cruz       -0.680556167 0.1550127 -0.99782053 -0.381939934
## Villa Hermosa    -0.106320531 0.1418453 -0.39432627  0.171114082
## 
## , , muOtro_Intercept
## 
##                    Estimate Est.Error        Q2.5       Q97.5
## Aranjuez         -0.1689083 0.1278364 -0.42466836  0.08429566
## Belén             0.2738271 0.1285301  0.02397624  0.53078837
## Buenos Aires      0.1746305 0.1289375 -0.08417407  0.43319601
## Castilla          0.4956057 0.1272579  0.24262191  0.74995827
## Doce de Octubre  -0.2053506 0.1301302 -0.46556586  0.05235482
## El Poblado        0.6529525 0.1295005  0.40040169  0.91058603
## Guayabal          0.3708110 0.1300784  0.11532366  0.63046246
## La América        0.1815452 0.1339048 -0.08320888  0.44299547
## La Candelaria    -0.2994731 0.1255367 -0.54818321 -0.05001284
## Laureles Estadio  0.3802947 0.1273853  0.12699345  0.63798496
## Manrique         -0.4546204 0.1300006 -0.71787878 -0.19357927
## Popular          -0.7852137 0.1328777 -1.05284059 -0.52070687
## Robledo           0.5676279 0.1282647  0.31714458  0.82401303
## San Javier       -0.1980646 0.1337548 -0.46126894  0.06514869
## Santa Cruz       -0.6689358 0.1367521 -0.93397112 -0.39835821
## Villa Hermosa    -0.2406480 0.1306308 -0.49657523  0.01608736

Y varianzas de efectos aleatorios estimadas \(\widehat{\sigma^2_{b^p_{0}}} = 0.42\) , \(\widehat{\sigma^2_{b^q_{0}}} = 0.87\) \(\widehat{\sigma^2_{b^r_{0}}} = 0.51\) , \(\widehat{\sigma^2_{b^s_{0}}} = 0.48\)

Comentarios generales

  • Los modelos mixtos son una herramienta que permite ajustar modelos globales que se caractericen a las particularidades de individuos (en este caso Comunas), lo que permite tener modelos versátiles y precisos para las predicciones.

  • Una expansión de este trabajo puede ir dirigida a ajustar un modelo en una escala temporal distinta, digamos semanal o diariamente. O utilizar los barrios como la variable de agrupamiento.

  • Enlazar un modelo Poisson para predecir el número total de accidentes y un modelo multinomial para predecir el número de accidentes por cada clase podría proveer de una herramienta útil para tomar planes de acción respecto a la movilidad de la ciudad. Aunque su utilidad inmediata podría verse afectada por el hecho de que la última vez que miré por mi ventana apenas y había vehículos en tránsito, producto de las medidas estatales de aislamiento social.

Referencias

LS0tDQp0aXRsZTogIk1vZGVsYWNpw7NuIGRlIGxhIEFjY2lkZW50YWxpZGFkIHZlaGljdWxhciBwYXJhIGxhcyAxNiBjb211bmFzIGRlbCDDoXJlYSB1cmJhbmEgZGUgTWVkZWxsw61uIGVudHJlIGxvcyBhw7FvcyAyMDE0LTIwMTkgYSB0cmF2w6lzIGRlIHJlZ3Jlc2nDs24gbXVsdGluaXZlbCINCmF1dGhvcjogIkp1YW4gRmVsaXBlIE3Dum5lcmEgVmVyZ2FyYSINCmRhdGU6ICIzLzIxLzIwMjAiDQpvdXRwdXQ6IA0KICBodG1sX2RvY3VtZW50Og0KICAgIGNzczogRm9ybWF0LmNzcw0KICAgIHRoZW1lOiB1bml0ZWQNCiAgICBjb2RlX2Rvd25sb2FkOiB5ZXMNCiAgICBkZl9wcmludDogcGFnZWQNCiAgICB0b2M6IHRydWUNCiAgICB0b2NfZmxvYXQ6DQogICAgICBjb2xsYXBzZWQ6IGZhbHNlDQogICAgYmlibGlvZ3JhcGh5OiBiaWJsaW9ncmFwaHkuYmliDQotLS0NCg0KYGBge3Igc2V0dXAsIGluY2x1ZGU9RkFMU0V9DQprbml0cjo6b3B0c19jaHVuayRzZXQoZWNobyA9IFRSVUUpDQpgYGANCg0KDQoNCg0KDQojIEludHJvZHVjY2nDs24NCg0KTG9zIGFjY2lkZW50ZXMgZGUgdHLDoWZpY28gbyBhY2NpZGVudGVzIGRlIHRyw6Fuc2l0byBzb24gc2luaWVzdHJvcyB2aWFsZXMgcXVlIHBlcnR1cmJhbiBlbCBmdW5jaW9uYW1pZW50byBub3JtYWwgZGUgdW5hIHbDrWEsIGVzdGUgZGViZSBpbnZvbHVjcmFyIGEgdW4gdmVow61jdWxvIGF1dG9tb3Rvci4gRXN0b3Mgc3VjZXNvcyBzb24gY2xhc2lmaWNhZG9zIHNlZ8O6biBzdXMgcmVwZXJjdXNpb25lcyAoc3UgZ3JhdmVkYWQ6IHNvbG8gZGHDsW9zIG1hdGVyaWFsZXMsIGhlcmlkb3MsIG11ZXJ0b3MsIGV0Yy4pIHkgc3UgdGlwbyAoQ2hvcXVlcywgYXRyb3BlbGxvcykuDQoNCg0KDQohW0F0cm9wZWxsb10oaHR0cHM6Ly9yYXcuZ2l0aHVidXNlcmNvbnRlbnQuY29tL2pmbXJhOTkvTW9kZWxvc19KZXJhcnF1aWNvcy9tYXN0ZXIvQXBsaWNhY2lvblJQdWJzL0ltYWdlcy9BdHJvcGVsbG8uZ2lmKXtoZWlnaHQ9MjUwcHh9ICFbQ2hvcXVlXShodHRwczovL3Jhdy5naXRodWJ1c2VyY29udGVudC5jb20vamZtcmE5OS9Nb2RlbG9zX0plcmFycXVpY29zL21hc3Rlci9BcGxpY2FjaW9uUlB1YnMvSW1hZ2VzL0Nob3F1ZXMuZ2lmKXtoZWlnaHQ9MjUwcHh9IA0KIVtWb2xjYW1pZW50b10oaHR0cHM6Ly9yYXcuZ2l0aHVidXNlcmNvbnRlbnQuY29tL2pmbXJhOTkvTW9kZWxvc19KZXJhcnF1aWNvcy9tYXN0ZXIvQXBsaWNhY2lvblJQdWJzL0ltYWdlcy9Wb2xjYW1pZW50by5naWYpe2hlaWdodD0yNTBweH0NCg0KRW4gZXN0ZSBkb2N1bWVudG8gc2UgcHJlc2VudGEgZWwgYWp1c3RlIGRlbCBuw7ptZXJvIGRlIGFjY2lkZW50ZXMgZGVsIMOhcmVhIFVyYmFuYSBkZSBsYSBjaXVkYWQgZGUgTWVkZWxsw61uIGVuIGZ1bmNpw7NuIGRlbCB0aWVtcG8sIGxvcyBkYXRvcyBxdWUgc2UgcHJlc2VudGFyYW4gY3VtcGxlbiBjb24gbGFzIGNhcmFjdGVyw61zdGljYXMgZGUgdW5hIHNlcmllIGRlIHRpZW1wbywgcG9yIGxvIHF1ZSBtZXRvZG9sb2fDrWFzIGFwdGFzIHBhcmEgZWwgbW9kZWxhbWllbnRvIGRlIGVzdGFzIHNvbiBjbGFyYXMgY2FuZGlkYXRhcyBhIGxhIGhvcmEgZGUgZWxlZ2lyIHVuIG1vZGVsbyBwYXJhIGV4cGxpY2FyIGVsIG7Dum1lcm8gZGUgYWNjaWRlbnRlcy4gU2luIGVtYmFyZ28sIHNlIHB1ZWRlbiBlbmNvbnRyYXIgZGlmZXJlbmNpYXMgc2lnbmlmaWNhdGl2YXMgZW4gZWwgbsO6bWVybyBkZSBhY2NpZGVudGVzIHJlZ2lzdHJhZG9zIHNlZ8O6biBkaXZpc2lvbmVzIHRlcnJpdG9yaWFsZXMgY29tbyBiYXJyaW9zIG8gY29tdW5hcywgY29uc2lkZXJhciBlc3RvIHNpZ25pZmljYXLDrWEgYWp1c3RhciBtw7psdGlwbGVzIG1vZGVsb3MsIHVubyBwYXJhIGNhZGEgZGl2aXNpw7NuIHRlcnJpdG9yaWFsIHF1ZSBzZSBjb25zaWRlcmUuDQoNCkxvcyBtb2RlbG9zIG1peHRvcywgamVyw6FycXVpY29zIG8gbXVsdGluaXZlbCwgc29uIHVuYSBtZXRvZG9sb2fDrWEgcXVlIHBlcm1pdGUgY3JlYXIgdW4gw7puaWNvIG1vZGVsbyBtaWVudHJhcyBzZSBkaWZlcmVuY2lhIHBvciB1bmEgdmFyaWFibGUgZGUgYWdydXBhbWllbnRvLCBxdWUgdXN1YWxtZW50ZSByZXByZXNlbnRhIHN1amV0b3MgdSBvYmpldG9zIGRlIGxvcyBxdWUgc2UgdGllbmVuIHJlcGV0aWRvcyByZWdpc3Ryb3MsIHBlcm1pdGllbmRvIGludm9sdWNyYXIgZWZlY3RvcyBhbGVhdG9yaW9zIHF1ZSBjYW1iaWFuIGRlIHN1amV0byBhIHN1amV0by4gDQoNCkVuIGVsIHByZXNlbnRlIHRyYWJham8gc2UgdXRpbGl6YW4gbG9zIG1vZGVsb3MgbXVsdGluaXZlbCBnZW5lcmFsaXphZG9zIHBhcmEgYWp1c3RhciBkb3MgbW9kZWxvczogZWwgcHJpbWVybyB1biBtb2RlbG8gY29uIHJlc3B1ZXN0YSBQb2lzc29uIHBhcmEgZW4gbsO6bWVybyB0b3RhbCBkZSBhY2NpZGVudGVzIHkgZWwgc2VndW5kbywgdW4gbW9kZWxvIE11bHRpbm9taWFsIHBhcmEgZWwgbsO6bWVybyBkZSBhY2NpZGVudGVzIHNlZ8O6biBsYSBjbGFzZSAoZXN0ZSDDumx0aW1vIGVzIHRhbiBzb2xvIHVuIGHDsWFkaWRvKS4gQW1ib3MgbW9kZWxvcyBzb24gY29tcGxlbWVudGFyaW9zLCB5YSBxdWUgZWwgbW9kZWxvIG11bHRpbm9taWFsIHJlcXVpZXJlIGRlIHVuYSBlc3RpbWFjacOzbiBkZWwgdG90YWwgZGUgYWNjaWRlbnRlcyBwYXJhIHJlYWxpemFyIGxhcyBwcmVkaWNjaW9uZXMgZGUgbGEgY2FudGlkYWQgZGUgYWNjaWRlbnRlcyBzZWfDum4gbGEgY2F0ZWdvcsOtYS4gU2UgdXRpbGl6YXJhIGNvbW8gdmFyaWFibGUgZGUgYWdydXBhbWllbnRvIGxhcyBjb211bmFzLg0KDQpQYXJhIG1lam9yYXIgbGEgbGVnaWJpbGlkYWQgZGVsIGRvY3VtZW50byBzZSBvY3VsdGFyb24gYWxndW5hcyBsaW5lYXMgZGUgY8OzZGlnbywgcGVybyBzZSBmYWNpbGl0YSBsYSBkZXNjYXJnYSBkZWwgX3JtZF8gdXRpbGl6YWRvIHBhcmEgZ2VuZXJhciBlbCBkb2N1bWVudG8gZW4gbGEgcGFydGUgc3VwZXJpb3IsIGFsIGxhZG8gZGVsIHRpdHVsby4NCg0KIyBDYXJnYSBkZSBsaWJyZXLDrWFzDQpgYGB7ciBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFLCByZXN1bHRzID0gJ2hpZGUnLCBlY2hvPVR9DQojQ0FHUkEgREUgTElCUkVSSUFTDQojIyBNYW5lam8gZGUgYmFzZXMgZGUgZGF0b3MNCmxpYnJhcnkoZHBseXIpDQpsaWJyYXJ5KG1hZ3JpdHRyKQ0KIyMgR3LDoWZpY29zDQpsaWJyYXJ5KGdncGxvdDIpDQpsaWJyYXJ5KGx1YnJpZGF0ZSkNCiMjIEFqdXN0ZSBkZSBtb2RlbG9zIG1peHRvcw0KbGlicmFyeShsbWU0KQ0KbGlicmFyeShicm1zKQ0KIyMgTWFuZWpvIGRlIGZlY2hhcw0KbGlicmFyeSgiem9vIikgDQojIyBUYWJsYXMgbGF0ZXgNCmxpYnJhcnkoa2FibGVFeHRyYSkNCmBgYA0KDQojIE9iamV0aXZvcw0KDQotIENvbnN0cnVpciB1biBtb2RlbG8gcHJlZGljdGl2byBwYXJhIGVsIG7Dum1lcm8gZGUgYWNjaWRlbnRlcyBvY3Vycmlkb3MgZW4gbGEgY2l1ZGFkIGRlIE1lZGVsbMOtbiBhIG5pdmVsIGNvbXVuYWwgZW4gaW50ZXJ2YWxvcyBtZW5zdWFsZXMsIGNvbiBiYXNlIGEgbG9zIGRhdG9zIGRlIGHDsW9zIGRlbCAyMDE0LTIwMTkgdXRpbGl6YW5kbyBsYSByZWdyZXNpw7NuIG11bHRpbml2ZWwgKGNvbm9jaWRhIHRhbWJpw6luIGNvbW8gbW9kZWxvcyBqZXLDoXJxdWljb3MgbyBtaXh0b3MpLCB1dGlsaXphbmRvIGxvcyBwYXF1ZXRlcyBgbG1lYTRgeSBgYnJtc2AgZGUgUi4NCi0gQ29tcHJlbmRlciBsYSBmb3JtYSBlbiBxdWUgbGEgYWNjaWRlbnRhbGlkYWQgc2UgcmVsYWNpb25hIGNvbiBlbCB0aWVtcG8gcGFyYSBsYXMgY29tdW5hcyBkZSBNZWRlbGzDrW4uDQoNCg0KDQojIENvbmp1bnRvIGRlIGRhdG9zOg0KDQpMb3MgZGF0b3MgYW7DoWxpemFkb3MgZW4gZWwgcHJlc2VudGUgZG9jdW1lbnRvIHNlIG9idGllbmVuIGRlIGxhIFtww6FnaW5hXShodHRwczovL2dlb21lZGVsbGluLW0tbWVkZWxsaW4ub3BlbmRhdGEuYXJjZ2lzLmNvbS9zZWFyY2g/dGFncz1tb3ZpbGlkYWQpIGRlbCBwb3J0YWwgW0dlb01lZGVsbMOtbl0oaHR0cHM6Ly93d3cubWVkZWxsaW4uZ292LmNvL2dlb21lZGVsbGluLykgZGUgbGEgQWxjYWxkw61hIGRlIE1lZGVsbMOtbiBlbiBzdSBzZWNjacOzbiBkZSBkYXRvcyBhYmllcnRvcy4gQ29ycmVzcG9uZGVuIGEgbGFzIGJhc2VzIGRlICJBY2NpZGVudGFsaWRhZCBnZW9ycmVmZXJlbmNpYWRhIiBlbnRyZSBsb3MgYcOxb3MgMjAxNCB5IDIwMTksIGxvcyBlbGVtZW50b3MgZGUgZGljaGFzIGJhc2VzIHJlcHJlc2VudGFuIHVuIGFjY2lkZW50ZSByZWdpc3RyYWRvIHBvciBsYSBTZWNyZXRhcsOtYSBkZSBNb3ZpbGlkYWQgZGUgbGEgQWxjYWxkw61hIGRlIE1lZGVsbMOtbiB5IHByZXNlbnRhbiB1bmEgc2VyaWUgZGUgY292YXJpYWJsZXMgcXVlIHNpcnZlbiBwYXJhIGNhdGVnb3JpemFyIGVsIHRpcG8gZGUgYWNjaWRlbnRlLCBlbCBtb21lbnRvIGRlIHN1IGluY2lkZW5jaWEgeSBzdSB1YmljYWNpw7NuIGdlb3JyZWZlcmVuY2lhZGEuDQoNClBhcmEgZWwgYWp1c3RlIGRlIGxvcyBtb2RlbG9zIHNlIGRlc2NhcnRhcm9uIGFsZ3VuYXMgZGUgbGFzIGNvdmFyaWFibGVzIChubyBpbnRlcmVzYW50ZXMgcGFyYSBtb2RlbGFyIGxhIGFjY2lkZW50YWxpZGFkKSB5IHNlIHJlYWxpemFyb24gY2FtYmlvcyBhbCBmb3JtYXRvIGRlIGxvcyBkYXRvcyAobGFzIG1vZGlmaWNhY2lvbmVzIHJlYWxpemFkYXMgeSBsb3MgcGFzb3MgcGFyYSBjb25zdHJ1aXIgZWwgY29uanVudG8gZGUgZGF0b3MgcXVlIHNlIHV0aWxpemEgYXF1w60gcHVlZGVuIHNlciBjb25zdWx0YWRvcyBlbiBkZXRhbGxlICBbYXF1w61dKGh0dHBzOi8vcmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbS9qZm1yYTk5L01vZGVsb3NfSmVyYXJxdWljb3MvbWFzdGVyL0FwbGljYWNpb25SUHVicy9DbGVhbmluZ0RhdGEuUm1kKSkuIEVuIHPDrW50ZXNpcywgc2UgbGltaXTDsyBlbCBlc3R1ZGlvIGEgbGFzIDE2IGNvbXVuYXMgZGUgbGEgY2l1ZGFkIGRlIE1lZGVsbMOtbiAoZGVzY2FydMOhbmRvc2UgYXF1ZWxsb3MgYWNjaWRlbnRlcyBvY3Vycmlkb3MgZW4gY29ycmVnaW1pZW50b3MpLCBzZSBvbWl0aWVyb24gY292YXJpYWJsZXMgcmVsYXRpdmFzIGEgbGEgZ2VvcnJlZmVyZW5jaWFjacOzbiB5IHNlIGFncnVwYXJvbiBsb3MgcmVnaXN0cm9zIHBvciBiYXJyaW9zIGVuIHBlcmlvZG9zIG1lbnN1YWxlcywgcGFyYSBvYnRlbmVyIGxhIGNhbnRpZGFkIGRlIGFjY2lkZW50ZXMgb2N1cnJpZG9zIGRpc3Rpbmd1aWRvcyBwb3Igc3UgY2xhc2UuDQoNCg0KDQpMb3MgZGF0b3MgZGVmaW5pdGl2b3MgcG9zZWVuIGxvcyBzaWd1aWVudGVzIGF0cmlidXRvczoNCg0KLSAqKkNPTVVOQSoqOiBsYXMgMTYgY29tdW5hcyBkZSBNZWRlbGzDrW4gY29uIG5pdmVsZXMgJ0FyYW5qdWV6JywgJ0JlbMOpbicsICdCdWVub3MgQWlyZXMnLCAnQ2FzdGlsbGEnLCAnRG9jZSBkZSBPY3R1YnJlJywgJ0VsIFBvYmxhZG8nLCAnR3VheWFiYWwnLCAnTGEgQW3DqXJpY2EnLCAnTGEgQ2FuZGVsYXJpYScsICdMYXVyZWxlcyBFc3RhZGlvJywgJ01hbnJpcXVlJywgJ1BvcHVsYXInLCAnUm9ibGVkbycsICdTYW4gSmF2aWVyJywgJ1NhbnRhIENydXonLCAnVmlsbGEgSGVybW9zYScuDQoNCi0gKipCQVJSSU8qKjogbG9zIGJhcnJpb3MgZGUgY2FkYSBjb211bmEgY29uIDI2NSBuaXZlbGVzLg0KDQotICoqUEVSSU9ETyoqOiBhw7FvIGVuIGVsIHF1ZSBvY3VycmVuIGxvcyBhY2NpZGVudGVzLg0KDQotICoqTUVTKio6IGNvbiBuaXZlbGVzICdKYW51YXJ5JywgJ0ZlYnJ1YXJ5JywgJ01hcmNoJywgJ0FwcmlsJywgJ01heScsICdKdW5lJywgJ0p1bHknLCAnQXVndXN0JywgJ1NlcHRlbWJlcicsICdPY3RvYmVyJywgJ05vdmVtYmVyJywgJ0RlY2VtYmVyJy4NCg0KLSAqKkZFQ0hBKio6IGVuIGZvcm1hdG8gIllZL01NIi4NCg0KLSAqKnQqKjogdGllbXBvIHRyYW5zY3VycmlkbywgdW5hIGNvbnZlcnNpw7NuIG51bcOpcmljYSBkZSBsYSBGRUNIQSBwYXJhIGFncmVnYXIgZW4gZWwgbW9kZWxvLCBlcXVpdmFsZW50ZSBhbCBuw7ptZXJvIGRlIGTDrWFzIHRyYW5zY3Vycmlkb3MgZGVzZGUgbGEgZmVjaGEgZGUgcmVmZXJlbmNpYSAyMDE0LzAxLzAxIGhhc3RhIGVsIHRpZW1wbyBkZWwgcmVnaXN0cm8uIERhZG8gcXVlIGxvcyByZWdpc3Ryb3MgcmVwcmVzZW50YW4gcGVyaW9kb3MgbWVuc3VhbGVzLCBlbCB0aWVtcG8gZGVsIHJlZ2lzdHJvIGNvcnJlc3BvbmRlcsOhIGEgbG9zIGTDrWFzIHRyYW5zY3Vycmlkb3MgYSBsYSBtaXRhZCBkZWwgTUVTLg0KDQotICoqQWNjaWRlbnRhbGlkYWQqKjogbsO6bWVybyBkZSBhY2NpZGVudGVzIHNlZ8O6biB0aXBvIGRlIGNhdGVnb3LDrWEgKHRhbWJpw6luIGxsYW1hZGEgQ0xBU0UpLg0KDQogICogKipBdHJvcGVsbG8qKjogbsO6bWVybyBkZSBhY2NpZGVudGVzIGRlIGVzdGEgY2F0ZWdvcsOtYSBkZSBhY2NpZGVudGVzLg0KICANCiAgKiAqKkNhaWRhLk9jdXBhbnRlKio6IG7Dum1lcm8gZGUgYWNjaWRlbnRlcyBkZSBlc3RhIGNhdGVnb3LDrWEgZGUgYWNjaWRlbnRlcy4NCiAgDQogICogKipDaG9xdWUqKjogbsO6bWVybyBkZSBhY2NpZGVudGVzIGRlIGVzdGEgY2F0ZWdvcsOtYSBkZSBhY2NpZGVudGVzLg0KICANCiAgKiAqKkluY2VuZGlvKio6IG7Dum1lcm8gZGUgYWNjaWRlbnRlcyBkZSBlc3RhIGNhdGVnb3LDrWEgZGUgYWNjaWRlbnRlLg0KICANCiAgKiAqKlZvbGNhbWllbnRvKio6IG7Dum1lcm8gZGUgYWNjaWRlbnRlcyBkZSBlc3RhIGNhdGVnb3LDrWEgZGUgYWNjaWRlbnRlcy4NCiAgDQogICogKipPdHJvKio6IG7Dum1lcm8gZGUgYWNjaWRlbnRlcyBkZSBlc3RhIGNhdGVnb3LDrWEgZGUgYWNjaWRlbnRlcy4NCg0KLSAqKm5yby5hY2NpZGVudGVzKio6IHRvdGFsIGRlIGFjY2lkZW50ZXMsIHN1bWEgZGUgbG9zIGFjY2lkZW50ZXMgZGUgdG9kYXMgbGFzIGNhdGVnb3LDrWFzLiBWYXJpYWJsZSByZXNwdWVzdGEuDQoNCiMjIENhcmdhIGRlbCBjb25qdW50byBkZSBkYXRvcw0KDQpBIGNvbnRpbnVhY2nDs24gc2UgcHJlc2VudGEgY29tbyBjYXJnYXIgZWwgY29uanVudG8gZGUgZGF0b3MgeSBzZSBjb25zdHJ1eWVuICoqdCoqIHkgKipGRUNIQSoqOg0KDQpgYGB7ciwgZWNobz1ULCByZXN1bHRzPSdoaWRlJ30NCiMjIENhcmdhIGRlIGNvbmp1bnRvIGRlIGRhdG9zIGEgbml2ZWwgYmFycmlhbA0KDQojZGF0YV9tZW5fYWxsIDwtIHJlYWQuY3N2KCJEYXRhc2V0cy9iYXNlX21lbnN1YWxfYmFycmlvc195X2NvbXVuYXMuY3N2IiwgZW5jb2Rpbmc9J1VURi04JykNCg0KdXJsIDwtICJodHRwczovL3Jhdy5naXRodWJ1c2VyY29udGVudC5jb20vamZtcmE5OS9Nb2RlbG9zX0plcmFycXVpY29zL21hc3Rlci9BcGxpY2FjaW9uUlB1YnMvRGF0YXNldHMvYmFzZV9tZW5zdWFsX2JhcnJpb3NfeV9jb211bmFzLmNzdiINCmRhdGFfbWVuX2FsbCA8LSByZWFkLmNzdih1cmwsIGVuY29kaW5nPSdVVEYtOCcpDQoNCiMjIFZlcmlmaWNhY2nDs24gZGUgY292YXJpYWJsZXMgY29tbyBmYWN0b3INCmRhdGFfbWVuX2FsbFssYygyLDMsNCldICU8PiUgbGFwcGx5KGZ1bmN0aW9uKHgpIGZhY3Rvcihhcy5jaGFyYWN0ZXIoeCkpKQ0KDQojIyBDcmVhY2nDs24gZGUgY292YXJpYWJsZXMgRkVDSEEgeSB0LCBlbiBiYXNlIGEgbGFzIG90cmFzIGNvdmFyaWFibGVzDQpkYXRhX21lbl9hbGwkRkVDSEEgPC0gcGFzdGUoZGF0YV9tZW5fYWxsJFBFUklPRE8sIGRhdGFfbWVuX2FsbCRNRVMsIHNlcD0iLSIpICU+JSBhcy55ZWFybW9uKCIlWS0lbSIpDQojIE1vZGlmaWNhY2nDs24gZGUgTUVTIGEgc3Ugbm9tYnJlIGVuIGluZ2zDqXMNCmRhdGFfbWVuX2FsbCRNRVMgPC0gZmFjdG9yKG1vbnRocyhkYXRhX21lbl9hbGwkRkVDSEEpLCBsZXZlbHMgPW1vbnRoLm5hbWVbMToxMl0pDQoNCiMgUGFyYSBvYnRlbmVyIGxhIGludmVyc2Egc2UgdXNhcsOtYTogem9vOjphcy5EYXRlKGRhdGFfbWVuX2FsbCRGRUNIQSwgb3JpZ2luPSIyMDE0LTAxLTAxIikNCmRhdGFfbWVuX2FsbCR0IDwtIGFzLm51bWVyaWMoYXMuRGF0ZShkYXRhX21lbl9hbGwkRkVDSEEsIGZyYWM9MC41KSkgLSBhcy5udW1lcmljKGFzLkRhdGUoIjIwMTQtMDEtMDEiKSkNCmBgYA0KDQpMb3MgYWNjaWRlbnRlcyBkZWwgYW50ZXJpb3IgY29uanVudG8gc29uIGRhZG9zIGEgbml2ZWwgYmFycmlhbCwgcG9yIGxvIHF1ZSBsb3MgYWdydXBhbW9zIHBvciBjb211bmFzLCBlbCBvYmpldG8gYGRhdGFfbWVuX2NvbXVuYXNgIHRpZW5lIGxvcyBkYXRvcyBjb24gbG9zIHF1ZSBzZSBhanVzdGFyYW4gbG9zIG1vZGVsb3MuIE1pZW50cmFzIHF1ZSBgdGlkeV9kYXRhX21lbl9hbGxfY29tdW5hc2AgZXMgdW5hIGJhc2UgZGUgYXBveW8gcGFyYSBjb25zdHJ1aXIgZ3LDoWZpY29zLg0KDQpgYGB7ciwgZWNobz1ULCByZXN1bHRzPSdoaWRlJ30NCiMjIENvbnN0cnVjY2nDs24gZGVsIGNvbmp1bnRvIGRlIGRhdG9zIGEgdXRpbGl6YXIsIGNvbnNlZ3VpZG8gcG9yIENvbXVuYXMuDQpkYXRhX21lbl9jb211bmFzIDwtIGRhdGFfbWVuX2FsbCAlPiUgZ3JvdXBfYnkoQ09NVU5BLCBQRVJJT0RPLCBNRVMsRkVDSEEsIHQpICU+JQ0KICBzdW1tYXJpc2UobnJvLmFjY2lkZW50ZXMgPSBzdW0obnJvLmFjY2lkZW50ZXMpLCANCiAgICAgICAgICAgIEF0cm9wZWxsbyA9IHN1bShBdHJvcGVsbG8pLCANCiAgICAgICAgICAgIENhaWRhLk9jdXBhbnRlID0gc3VtKENhaWRhLk9jdXBhbnRlKSwNCiAgICAgICAgICAgIENob3F1ZT1zdW0oQ2hvcXVlKSwNCiAgICAgICAgICAgIFZvbGNhbWllbnRvID0gc3VtKFZvbGNhbWllbnRvKSwNCiAgICAgICAgICAgIE90cm8gPSBzdW0oT3RybykpDQoNCiMjIE9yZ2FuaXphY2nDs24gZGUgYmFzZXMgZGUgZGF0b3MgZW4gZm9ybWF0byBhcHRvIHBhcmEgZ3LDoWZpY2FyLg0KDQoNCnRpZHlfZGF0YV9tZW5fYWxsIDwtIHRpZHlyOjpnYXRoZXIoZGF0YV9tZW5fYWxsLCAiQ0xBU0UiLCAibnJvLmFjY2lkZW50ZXMiLCA1OjkpDQoNCnRpZHlfZGF0YV9tZW5fYWxsX2NvbXVuYXMgPC0gdGlkeV9kYXRhX21lbl9hbGwlPiUgZ3JvdXBfYnkoQ09NVU5BLCB0LCBDTEFTRSkgJT4lDQogIHN1bW1hcmlzZShucm8uYWNjaWRlbnRlcyA9IHN1bShucm8uYWNjaWRlbnRlcykpDQoNCmBgYA0KDQoNCkEgY29udGludWFjacOzbiBzZSBwcmVzZW50YSBlbCBjb25qdW50byBkZSBkYXRvczoNCg0KYGBge3IgZWNobz1GLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFLCBjb2xzLnByaW50ID0gNX0NCmRhdGFfbWVuX2NvbXVuYXMNCmBgYA0KU2UgcHVlZGUgdmVyIHF1ZSBzZSB0aWVuZW4gMTIgcmVnaXN0cm9zIHBvciBjYWRhIGHDsW8gcGFyYSBjYWRhIHVuYSBkZSBsYXMgMTYgY29tdW5hcywgeWEgcXVlIGxvcyBkYXRvcyBjb3JyZXNwb25kZW4gYSB1biBwZXJpb2RvIGRlIDYgYcOxb3Mgc2UgdGllbmVuICQxMioxNio2PTExNTIkIHJlZ2lzdHJvcy4NCg0KIyBBbsOhbGlzaXMgZGVzY3JpcHRpdm8gDQoNCg0KTnVlc3RybyBvYmpldGl2byBwcmltb3JkaWFsIGVzIHByZWRlY2lyICoqbnJvLmFjY2lkZW50ZXMqKiBlbiBmdW5jacOzbiBkZSBsYXMgY292YXJpYWJsZXMgdGVtcG9yYWxlcywgcG9yIGxvIHF1ZSByZWFsaXphbW9zIGVsIGdyw6FmaWNvIGRlIGxhIHNlcmllIGRlIHRpZW1wbyBjb3JyZXNwb25kaWVudGUgYSBsb3MgYWNjaWRlbnRlcyBkZSB0b2RhcyBsYXMgQ29tdW5hcyBqdW50YXM6DQoNCmBgYHtyLCBlY2hvPVR9DQojQWNjaWRlbnRhbGlkYWQgY29uanVudGEgZGUgVE9EQVMgbGFzIENvbXVuYXM6DQp0ZW1wIDwtIGRhdGFfbWVuX2NvbXVuYXMgJT4lIGdyb3VwX2J5KEZFQ0hBKSAlPiUgDQogIHN1bW1hcmlzZShucm8uYWNjaWRlbnRlcyA9IHN1bShucm8uYWNjaWRlbnRlcykpDQojIyBTRVJJRSBERSBUSUVNUE8gcGFyYSBsYSANCnRzX21vbnRobHkgPC0gdHModGVtcCRucm8uYWNjaWRlbnRlcywgc3RhcnQ9YygyMDE0LDEpLGZyZXF1ZW5jeT0xMikNCnBsb3QodHNfbW9udGhseSkNCmBgYA0KDQpMYXMgc2VyaWVzIGRlIHRpZW1wbyB0aWVuZW4gY29tcG9uZW50ZXMgZGUgdGVuZGVuY2lhIHkgZXN0YWNpb25hbGlkYWQuIEVzdGUgw7psdGltbyBjb3JyZXNwb25kZSBhIGNvbXBvcnRhbWllbnRvcyBxdWUgc2UgcmVwaXRlbiBjYWRhIGNpZXJ0byB0aWVtcG8gZW4gbGEgc2VyaWUsIGV4aXN0ZW4gZ3LDoWZpY29zIHF1ZSBldmFsdWFuIHF1ZSBwZXJpb2RpY2lkYWQgKGFudWFsLCB0cmltZXN0cmFsLCBzZW1lc3RyYWwgZXRjLikgdG9tYXIgY29tbyBlbCBwZXJpb2RvZ3JhbWEsIHBlcm8gc2luIG5lY2VzaWRhZCBkZSByZWN1cnJpciBhIMOpbCwgZGVsIGdyw6FmaWNvIGRlIGxhIHNlcmllIHByZXNlbnRhZG8gYW50ZXJpb3JtZW50ZSBzZSBwdWVkZW4gbm90YXIgY29tcG9ydGFtaWVudG9zIG1hcmNhZG9zIHBhcmEgYWxndW5vcyBtZXNlcyBlbnRyZSBlbCAyMDE0IHkgZWwgMjAxOCwgKHBvciBlamVtcGxvLCBsYSBhY2NpZGVudGFsaWRhZCBjYWUgYWwgbcOtbmltbyBwcmluY2lwaW8gZGUgY2FkYSBhw7FvIGVuIGVsIG1lcyBkZSBFbmVybykuIEVuIGVsIDIwMTkgc2UgcHVlZGUgaW50dWlyIHF1ZSBzZSBjb25zZXJ2YW4gbG9zIGNvbXBvcnRhbWllbnRvcyBwZXJpw7NkaWNvcywgcGVybyBwYXJlY2UgcXVlIG9jdXJyZSB1biBjaWNsbyBxdWUgYXVtZW50byBlbCBuw7ptZXJvIGRlIGFjY2lkZW50ZXMgZW4gZWwgc2VndW5kbyBzZW1lc3RyZSBkZWwgYcOxby4gRGViaWRvIGEgZXN0byBzZSBzb3NwZWNoYSBxdWUgbG9zIGRhdG9zIHRpZW5lbiB1bmEgcGVyaW9kaWNpZGFkIGFudWFsLCBwb3IgbG9zIHF1ZSBsYSBjb3ZhcmlhYmxlICpNRVMqIGVzIGNhbmRpZGF0YSBhIHNlciByZWxldmFudGEgcGFyYSBlbCBtb2RlbGFtaWVudG8gZGVsIG7Dum1lcm8gZGUgYWNjaWRlbnRlcy4NCg0KTGEgdGVuZGVuY2lhIGVuIGNhbWJpbywgZGVzY3JpYmUgY29tcG9ydGFtaWVudG8gZ2VuZXJhbCBkZSBsYSBzZXJpZSAoUmVzdGFuZG8gbG9zIHBlcmlvZG9zKS4gU2UgcHVlZGUgb2J0ZW5lciB1bmEgZm9ybWEgYXByb3hpbWFkYSBkZSBsYSB0ZW5kZW5jaWEgZGUgbGEgc2VyaWEgcG9yIG1lZGlvIGRlIGBkZWNvbXBvc2VgOg0KDQpgYGB7cn0NCnBsb3QoZGVjb21wb3NlKHRzX21vbnRobHkpJHRyZW5kLHlsaW09YyhtaW4odHNfbW9udGhseSksbWF4KHRzX21vbnRobHkpKSwgeWxhYiA9ICJhY2NpZGVudGVzIikNCg0KYGBgDQoNClNlIHB1ZWRlIHZlciBxdWUgbGEgdGVuZGVuY2lhIHZhcmlhIGVudHJlIDMyMDAgeSAzNjAwIGFjY2lkZW50ZXMsIHBvciBsbyBxdWUgc2UgcHVlZGUgaGFibGFyIGRlIHVuYSB0ZW5kZW5jaWEgZGUgY3JlY2ltaWVudG8vZGVjcmVjaW1pZW50byBtYXJjYWRhLiBQYXJhIG1vZGVsYXJsYSBzZSBwdWVkZSByZWN1cnJpciBwb2xpbm9taW8gZGVsIHRpZW1wbywgZGFkbyBxdWUgc2UgcHVlZGVuIGFwcmVjaWFyIHZhcmlhcyBjb25jYXZpZGFkZXMsIHVuIHBvbGlub21pbyBkZSBncmFkbyAzIG8gNCBkZWJlcsOtYSBzZXIgYWRlY3VhZG8uDQoNCkFob3JhIGV4cGxvcmFyZW1vcyBsYSBjYW50aWRhZCBkZSBhY2NpZGVudGVzIHNlZ8O6biBsYSBjb211bmEgeSBzdSBDTEFTRSwgYSBjb250aW51YWNpw7NuIHNlIHByZXNlbnRhIHVuYSB0YWJsYSBjb24gZWwgdG90YWwgZGUgYWNjaWRlbnRlcyBkZSBsb3MgNiBhw7FvcyByZWdpc3RyYWRvcyBwYXJhIGNhZGEgdW5hIGRlIGxhcyBjb211bmFzOg0KDQpgYGB7ciwgZWNobz1GfQ0KdGVtcCA8LSBkYXRhX21lbl9jb211bmFzICU+JSBncm91cF9ieShDT01VTkEpICU+JSANCiAgc3VtbWFyaXNlKG5yby5hY2NpZGVudGVzID0gc3VtKG5yby5hY2NpZGVudGVzKSwNCiAgICAgICAgICAgIEF0cm9wZWxsbyA9IHN1bShBdHJvcGVsbG8pLCANCiAgICAgICAgICAgIENhaWRhLk9jdXBhbnRlID0gc3VtKENhaWRhLk9jdXBhbnRlKSwNCiAgICAgICAgICAgIENob3F1ZT1zdW0oQ2hvcXVlKSwNCiAgICAgICAgICAgIFZvbGNhbWllbnRvID0gc3VtKFZvbGNhbWllbnRvKSwNCiAgICAgICAgICAgIE90cm8gPSBzdW0oT3RybykpDQoNCg0KdGVtcFtvcmRlcih0ZW1wJG5yby5hY2NpZGVudGVzLCBkZWNyZWFzaW5nPVQpLF0gJT4lIGthYmxlKGFsaWduID0gImMiLGZ1bGxfd2lkdGggPSBGLCBib29rdGFicyA9IFQpJT4lDQogIGthYmxlX3N0eWxpbmcoYm9vdHN0cmFwX29wdGlvbnMgPSBjKCJzdHJpcGVkIiwgImNvbmRlbnNlZCIpKQ0KDQpgYGANCg0KRWwgdG90YWwgZGUgYWNjaWRlbnRlcyB2YXLDrWEgbXVjaG8gZGUgdW5hIGNvbXVuYSBhIG90cmEsIHBvciBsbyBxdWUgc2Ugc29zcGVjaGEgcXVlIGV4aXN0ZW4gZGlmZXJlbmNpYXMgbWFyY2FkYXMgZW50cmUgbGFzIENvbXVuYXMuIEVzdG8gc2UgcHVlZGUgYXByZWNpYXIgbXVjaG8gbWVqb3IgZW4gZWwgc2lndWllbnRlIGdyw6FmaWNvIGRlIGxvcyBhY2NpZGVudGVzIGRhZG8gZWwgdGllbXBvIHBhcmEgY2FkYSB1bmEgZGUgbGFzIDE2IGNvbXVuYXMsIGVuIGVzdGUgeSBsb3MgZGVtw6FzIGdyw6FmaWNvcyBxdWUgaW52b2x1Y3JlbiBlbCBjb250ZW8gZGUgYWNjaWRlbnRlcyBzZSB1dGlsaXphcsOhIGxhIGVzY2FsYSBsb2dhcsOtdG1pY2EsIHBhcmEgcXVlIGxhIGVzY2FsYSBwZXJtaXRhIGNvbXBhcmFyIGxhcyBkaWZlcmVudGVzIGNvbXVuYXM6DQoNCg0KDQpgYGB7ciwgZWNobz1GLCBmaWcuaGVpZ2h0ID0gMTUsIGZpZy53aWR0aD0xMH0NCnBsb3RfbnJvX2FjYyA8LSBnZ3Bsb3QoYWVzKHggPSAodCksIHkgPSBsb2cobnJvLmFjY2lkZW50ZXMpKSwgZGF0YSA9IGRhdGFfbWVuX2NvbXVuYXMpICsNCiAgZ2VvbV9wb2ludCggZmlsbCA9ICJnb2xkZW5yb2Q0IikgKw0KICB0aGVtZV9idygpICsgDQogIGdlb21fbGluZSgpKw0KICBmYWNldF93cmFwKH4gQ09NVU5BLCBuY29sID0gMikrDQogIHNjYWxlX3hfY29udGludW91cyggYnJlYWtzID0gZGF0YV9tZW5fY29tdW5hcyR0W3NlcShmcm9tPTEsIHRvID0gMTMqNSwgYnkgPTEyKV0sIA0KICAgICAgbGFiZWxzID0gZGF0YV9tZW5fY29tdW5hcyRGRUNIQVtzZXEoZnJvbT0xLCB0byA9IDEzKjUsIGJ5ID0xMildKQ0KDQpwbG90X25yb19hY2MgKyB0aGVtZShheGlzLnRleHQueSA9IGVsZW1lbnRfdGV4dChzaXplPTEzKSkNCmBgYA0KDQpTZSBwdWVkZSB2ZXIgcXVlIGVmZWN0aXZhbWVudGUgZXhpc3RlIHVuYSBkaWZlcmVuY2lhIGVuIGxhIGNhbnRpZGFkIGRlIGFjY2lkZW50ZXMgcmVnaXN0cmFkb3MgZGUgdW5hIGNvbXVuYSBhIG90cmEuIEVzdG8gbm9zIGRpY2UgcXVlIHV0aWxpemFyIGxhICpDT01VTkEqIGNvbW8gbGEgdmFyaWFibGUgZGUgYWdydXBhbWllbnRvLCBlbiBiYXNlIGFsIGFudGVyaW9yIGdyw6FmaWNvIGxhIGFkaWNpw7NuIGRlIHVuIGludGVyY2VwdG8gYWxlYXRvcmlvIHBhcmVjZSByYXpvbmFibGUsIGVuIGNhbWJpbyBkYWRvIHF1ZSBxdWUgbm8gaGF5IGRpZmVyZW5jaWFzIGRlIHRlbmRlbmNpYSBtYXJjYWRhcyBlbnRyZSBsYXMgY29tdW5hcywgc2UgZGVzY2FydGEgbGEgaW5jbHVzacOzbiBkZSB1bmEgcGVuZGllbnRlIGFsZWF0b3JpYSB5IHNlIGNvbnNpZGVyYSBxdWUgZWwgY29tcG9ydGFtaWVudG8gZXMgc2ltaWxhciBlbnRyZSBlbGxhcy4NCg0KU2UgcHVlZGUgYWxjYW56YXIgbGEgbWlzbWEgY29uY2x1c2nDs24gc2kgc2UgZ3LDoWZpY2EgZWwgbsO6bWVybyBkZSBhY2NpZGVudGVzIGhhY2llbmRvIGRpc3RpbmNpw7NuIHBvciBzdSBjbGFzZToNCg0KYGBge3IsIGVjaG89RiwgZmlnLmhlaWdodCA9IDIwLCBmaWcud2lkdGg9MTB9DQpncm91cC5jb2xvcnMgPC0gUkNvbG9yQnJld2VyOjpicmV3ZXIucGFsKDUsICJTZXQyIikNCg0KZ2dwbG90KGFlcyh4ID0gdCwgeSA9IGxvZyhucm8uYWNjaWRlbnRlcyksIGNvbG9yID0gQ0xBU0UpLCBkYXRhID0gdGlkeV9kYXRhX21lbl9hbGxfY29tdW5hcykgKw0KICBnZW9tX3BvaW50KGFlcyhmaWxsID0gQ0xBU0UsIGNvbG91ciA9IENMQVNFKSkgKw0KICB0aGVtZV9idygpICsNCiAgc2NhbGVfY29sb3VyX21hbnVhbCh2YWx1ZXM9Z3JvdXAuY29sb3JzKSsNCiMgIHNjYWxlX3lfbG9nMTAoKSArIA0KICMgc2NhbGVfeF9kYXRlKGRhdGVfbGFiZWxzID0gIiVtLSVZIikrDQogIGdlb21fbGluZSgpKw0KICBmYWNldF93cmFwKH4gQ09NVU5BLCBuY29sID0gMikrDQogIHNjYWxlX3hfY29udGludW91cyggYnJlYWtzID0gZGF0YV9tZW5fY29tdW5hcyR0W3NlcShmcm9tPTEsIHRvID0gMTMqNSwgYnkgPTEyKV0sIA0KICAgICAgbGFiZWxzID0gZGF0YV9tZW5fY29tdW5hcyRGRUNIQVtzZXEoZnJvbT0xLCB0byA9IDEzKjUsIGJ5ID0xMildKSsNCiAgZ3VpZGVzKGZpbGwgPSBndWlkZV9sZWdlbmQodGl0bGUucG9zaXRpb24gPSAidG9wIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGFiZWwucG9zaXRpb24gPSAiYm90dG9tIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbnJvdyA9IDEpKSArIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJ0b3AiKQ0KYGBgDQoNCkFob3JhIHZlcmVtb3MgbGEgZGVuc2lkYWQgbXVlc3RyYWwgZGUgbGEgY2FudGlkYWQgZGUgYWNjaWRlbnRlcyBzZWfDum4gbGFzIGNvbXVuYXM6DQoNCmBgYHtyLCBlY2hvPUYsIGZpZy5oZWlnaHQgPSAxMCwgZmlnLndpZHRoPTEwfQ0KDQpwIDwtIGdncGxvdCh0aWR5X2RhdGFfbWVuX2FsbF9jb211bmFzLCANCiAgICAgICAgICAgIGFlcyh4ID0gbG9nKG5yby5hY2NpZGVudGVzKSkpICsNCiAgZ2VvbV9kZW5zaXR5KHBvc2l0aW9uID0gInN0YWNrIiwgYWxwaGE9LjUsIGNvbCA9ICJnb2xkZW5yb2Q0IiwgZmlsbD0iZ29sZCIpICsNCiAgZmFjZXRfd3JhcCh+IENPTVVOQSwgbmNvbD00KSsNCiAgdGhlbWVfYncoKQ0KcCMrc2NhbGVfeV9jb250aW51b3VzKGxpbWl0cyA9IGMoMCwgMC40KSkNCmBgYA0KDQpTZSBwdWVkZSB2ZXIgbGEgcHJlc2VuY2lhIGRlIGRpZmVyZW50ZXMgbW9kYXMsIHBlcm8gZXN0byBwdWVkZSBzZXIgZXhwbGljYWRvIHBvciBsYXMgZGlmZXJlbmNpYXMgZGVsIG7Dum1lcm8gZGUgYWNjaWRlbnRlcyBzZWfDum4gZWwgbWVzLiBNw6FzIGFkZWxhbnRlIGVuIGVsIGRvY3VtZW50bywgc2UgY29uc2lkZXJhcsOhIHF1ZSBlbCBuw7ptZXJvIGRlIGFjY2lkZW50ZXMgZGUgZGlzdHJpYnV5ZSAkUG9pc3NvbiQsIHBvciBsbyBxdWUgZXN0ZSBncsOhZmljbyBzaXJ2ZSBjb21vIGFyZ3VtZW50byBwYXJhIGNvbnNpZGVyYXIgcXVlIGxhIG1lZGlhIGVzcGVyYWRhIGRlcGVuZGVyw6EgZGUgY292YXJpYWJsZXMgY29tbyBlbCB0aWVtcG8uIEFkZW3DoXMsIHNlIHB1ZWRlIHZlciBlbCBjYW1iaW8gZGUgZm9ybWEgZGUgbGFzIGRlbnNpZGFkZXMgZW50cmUgbGFzIGNvbXVuYXMuDQoNClRhbWJpw6luIHNlIHByZXNlbnRhbiBsYXMgZGVuc2lkYWRlcyBzZWfDum4gbGEgQ0xBU0UgZGVsIGFjY2lkZW50ZToNCg0KYGBge3IsIGVjaG89RiwgZmlnLmhlaWdodCA9IDEwLCBmaWcud2lkdGg9MTB9DQpncm91cC5jb2xvcnMgPC0gYygiZ29sZDEiLCAiZGFya29saXZlZ3JlZW4zIiwgInR1cnF1b2lzZTIiLCAic3RlZWxibHVlNCIsICJzbGF0ZWJsdWU0IikNCg0KcCA8LSBnZ3Bsb3QodGlkeV9kYXRhX21lbl9hbGxfY29tdW5hcywgDQogICAgICAgICAgICBhZXMoeCA9IGxvZyhucm8uYWNjaWRlbnRlcyksIGZpbGwgPSBDTEFTRSkpICsNCiAgZ2VvbV9kZW5zaXR5KHBvc2l0aW9uID0gInN0YWNrIiwgYWxwaGE9LjUpICsNCiAgZmFjZXRfd3JhcCh+IENPTVVOQSwgbmNvbD00KSsNCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzPWdyb3VwLmNvbG9ycykrDQogIHRoZW1lX2J3KCkgKyB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAidG9wIikNCnAjK3NjYWxlX3lfY29udGludW91cyhsaW1pdHMgPSBjKDAsIDAuNCkpDQpgYGANCg0KTnVldmFtZW50ZSBzZSBwdWVkZSB2ZXIgZWwgY2FtYmlvIGRlIGZvcm1hIGRlIGxhcyBkZW5zaWRhZGVzIGVudHJlIGxhcyBjb211bmFzLiBMbyBjdWFsIGVzIGNvbmZpcm1hZG8gYWwgcmVhbGl6YXIgdW5hIGdyw6FmaWNhIGRlIGJhcnJhcyBkZSBwcm9iYWJpbGlkYWQ6DQoNCg0KYGBge3IsIGVjaG89RiwgZmlnLmhlaWdodCA9IDYsIGZpZy53aWR0aD02LjgsZmlnLmFsaWduPSdjZW50ZXInfQ0KZ3JvdXAuY29sb3JzIDwtIFJDb2xvckJyZXdlcjo6YnJld2VyLnBhbCg1LCAiU2V0MiIpDQojIyBHcsOhZmljbyBkZSBwcm9wb3JjaW9uZXMgcG9yIGNvbXVuYQ0KdGVtcCA8LSB0aWR5X2RhdGFfbWVuX2FsbF9jb211bmFzJT4lZ3JvdXBfYnkoQ09NVU5BLCBDTEFTRSkgJT4lDQogIHN1bW1hcmlzZShwID0gc3VtKG5yby5hY2NpZGVudGVzKSkNCg0KZ2dwbG90KHRlbXAsIGFlcyhmaWxsPUNMQVNFLCB5PXAsIHg9Q09NVU5BKSkgKyANCiAgICBnZW9tX2Jhcihwb3NpdGlvbj0iZmlsbCIsIHN0YXQ9ImlkZW50aXR5IikreWxhYigicHJvYmFiaWxpZGFkIikrDQogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcz1ncm91cC5jb2xvcnNbMTo1XSkrDQogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KCBjb2xvciA9ICJCbGFjayIsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgc2l6ZSA9IDEyLCBhbmdsZSA9IDMwKSkNCmBgYA0KDQoNClNlIHB1ZWRlIHZlciBxdWUgbGEgcHJvcG9yY2nDs24gZGUgYWxndW5hcyBjbGFzZXMgZGUgYWNjaWRlbnRlIGNvbW8gbG9zIEF0cm9wZWxsb3Mgc29uIG5vdGFibGVtZW50ZSBtYXlvcmVzIHBhcmEgYWxndW5hcyBjb211bmFzIGNvbW8gX1NhbnRhIENydXpfIHkgX1BvcHVsYXJfLCB5IGVuIGdlbmVyYWwgdmFyw61hbiBjb25zaWRlcmFibGVtZW50ZSBlbnRyZSBsYXMgY29tdW5hcy4gTG8gbWlzbW8gb2N1cnJlIGVuIGxvcyBDaG9xdWVzIHkgbG9zIGFjY2lkZW50ZXMgY29uIENhw61kYSBkZSBPY3VwYW50ZS4gIE1pZW50cmFzIHF1ZSBvdHJhcyBjb21vIGxvcyB2b2xjYW1pZW50b3MgbG9zIGFjY2lkZW50ZXMgZGUgY2xhc2UgIk90cm8iIHBhcmVjZW4gdGVuZXIgdW5hIHByb3BvcmNpw7NuIGNvbnN0YW50ZSBlbnRyZSBsYXMgY29tdW5hcy4gTGEgY29uY2x1c2nDs24gZ2VuZXJhbCBkZWwgZ3LDoWZpY28gZXMgcXVlIGxhcyBwcm9wb3JjaW9uZXMgc2Vnw7puIGxhIGNsYXNlIHNvbiBhZmVjdGFkYXMgcG9yIGxhIHZhcmlhYmxlIGRlIGFncnVwYW1pZW50byAqQ09NVU5BKg0KDQojIE1vZGVsYWNpw7NuIHkgQWp1c3RlIA0KDQojIyBNb2RlbG8gY29uIHJlc3B1ZXN0YSBQb2lzc29uDQoNCkRlbm90YXJlbW9zIGVsIG7Dum1lcm8gZGUgYWNjaWRlbnRlcyBwYXJhIGVsIHRpZW1wbyAkeSQgZGUgbGEgY29tdW5hICRqJCBjb21vICRuX3tpan0kIHkgbGEgbW9kZWxhcmVtb3MgcG9yIG1lZGlvIGRlIHVuYSByZWdyZXNpw7NuIFBvaXNzb246DQoNCiQkbl97aWp9IFxzaW0gUG9pc3NvbihcbGFtYmRhX3tpan0pJCQNCkVudG9uY2VzIHF1ZXJlbW9zIGVuY29udHJhciB1bmEgZXhwcmVzacOzbiBxdWUgcmVsYWNpb25lIGEgJFxsYW1iZGFfe2lqfSQgY29uIGxhcyB2YXJpYWJsZXMgdGVtcG9yYWxlcyB5IGxhcyBjb211bmFzLg0KDQoNCg0KIyMjIE1vZGVsb3MgcHJvcHVlc3RvcyB7LnRhYnNldH0NCg0KQ29uIGJhc2UgYWwgYW7DoWxpc2lzIGRlc2NyaXB0aXZvLCBzZSB0aWVuZSBxdWUgbGEgdGVuZGVuY2lhIGdlbmVyYWwgZGVsIG1vZGVsbyB0aWVuZSBxdWUgc2VyIG1vZGVsYWRhIGEgdHJhdsOpcyBkZSB1biBwb2xpbm9taW8gZGUgYWx0byBncmFkbyBwYXJhIGNhcHRhciBzdXMgY29uY2F2aWRhZGVzIChpbmljaWFsbWVudGUgc2UgY29uc2lkZXJhIHF1ZSBlbCBncmFkbyBtw61uaW1vIGRlYmUgc2VyIDMpLiBBZGVtw6FzLCBkYWRvIHF1ZSByZWFsbWVudGUgbm8gc2Ugbm90YXJvbiB0ZW5kZW5jaWFzIG1hcmNhZGFzIHJlc3BlY3RvIGFsIG7Dum1lcm8gZGUgYWNjaWRlbnRlcyBzZWfDum4gbGEgY29tdW5hLCBzZSBkZXNjYXJ0YW4gbW9kZWxvcyBjb24gcGVuZGllbnRlIGFsZWF0b3JpYSB5IHNlIHJlc3RyaW5nZSBhIG1vZGVsbyBjb24gaW50ZXJjZXB0byBhbGVhdG9yaW8uDQoNCkRlbsOzdGVzZToNCg0KJCRqOiBDb211bmFcOyAoMToxNikgXFwgaTogb2JzZXJ2YWNpw7NuXDsgY29ycmVzcG9uZGllbnRlXDsgYVw7IHVuXDttZXMgXDsgZW50cmUgXDsgMjAxNCBcOyB5IFw7IDIwMTkgXDsgKDE6NzIpJCQNCkFkaWNpb25hbG1lbnRlIHNlIG5vdMOzIHVuYSBwZXJpb2RpY2lkYWQgYW51YWwgbWFyY2FkYSwgIHBvciBsbyBxdWUgcGFyYSBtb2RlbGFybGEgbGEgdmFyaWFibGUgTUVTIHNlcsOhIGluY2x1aWRhIGVuIGxvcyBtb2RlbG9zIGRlIGxhIHNpZ3VpZW50ZSBmb3JtYTogJCRcc3VtXGxpbWl0c197az0xfV57MTF9e1xkZWx0YV97a319TUVTX3tpamt9XDtcOyBkb25kZVw7XDsgTUVTX3tpa30gPSBcbGVmdFx7IFxiZWdpbnttYXRyaXh9IDEgXHF1YWQgc2kgfiBsYSB+b2JzZXJ2YWNpw7NuIH5pan4gZXN0w6F+IGVufmxhfiBlc3RhY2nDs25+ayAgXFwgMCBccXVhZH4gb3Ryb35jYXNvXGVuZHttYXRyaXh9IFxyaWdodFx9JCQNCg0KJCRrID0gMTogRmVicmVybywgfiBrPTI6IE1hcnpvLCAuLi4sIGs9MTA6IE5vdmllbWJyZSwgfiBrPTExOiBEaWNpZW1icmUkJA0KDQoNCiMjIyMgTW9kZWxvIDENCg0KUG9saW5vbWlvIGRlIGdyYWRvIDMgZW4gZnVuY2nDs24gZGVsIHRpZW1wbywgY29uIGVzdGFjaW9uYWxpZGFkIHNlZ8O6biBlbCBNRVMgZSBpbnRlcmNlcHRvIGFsZWF0b3JpbzoNCg0KYGBge3IsIGluY2x1ZGU9Rn0NCg0KI2xvYWQoIk1vZGVsb3MvY29tdW5hX2dsbWVyLlJEYXRhIikNCmxvYWQodXJsKCJodHRwczovL2dpdGh1Yi5jb20vamZtcmE5OS9Nb2RlbG9zX0plcmFycXVpY29zL3Jhdy9tYXN0ZXIvQXBsaWNhY2lvblJQdWJzL01vZGVsb3MvY29tdW5hX2dsbWVyLlJEYXRhIikpDQpgYGANCg0KJCRcbG9nIChcbGFtYmRhX3tpan0pID0gXGJldGFfMCArIFxiZXRhXzEgdCArIFxiZXRhXzJ0XjIgKyBcYmV0YV8zdF4zK1xzdW1cbGltaXRzX3trPTF9XnsxMX17XGRlbHRhX3trfX1NRVNfe2lqa30gKyBiX3swan0kJA0KJCRiX3swan0gXHNpbSBOKDAsIFxzaWdtYV97YjB9KSQkDQoNCg0KIyMjIyBNb2RlbG8gMg0KDQpQb2xpbm9taW8gZGUgZ3JhZG8gNCBlbiBmdW5jacOzbiBkZWwgdGllbXBvLCBjb24gZXN0YWNpb25hbGlkYWQgc2Vnw7puIGVsIE1FUyBlIGludGVyY2VwdG8gYWxlYXRvcmlvOg0KDQokJFxsb2cgKFxsYW1iZGFfe2lqfSkgPSBcYmV0YV8wICsgXGJldGFfMSB0ICsgXGJldGFfMnReMiArIFxiZXRhXzMgdF4zKyBcYmV0YV80IHReNCArXHN1bVxsaW1pdHNfe2s9MX1eezExfXtcZGVsdGFfe2t9fU1FU197aWprfSAgKyBiX3swan0kJA0KJCRiX3swan0gXHNpbSBOKDAsIFxzaWdtYV97YjB9KSQkDQoNCiMjIyMgTW9kZWxvIDMNCg0KUG9saW5vbWlvIGRlIGdyYWRvIDUgZW4gZnVuY2nDs24gZGVsIHRpZW1wbywgY29uIGVzdGFjaW9uYWxpZGFkIHNlZ8O6biBlbCBNRVMgZSBpbnRlcmNlcHRvIGFsZWF0b3JpbzoNCg0KJCRcbG9nIChcbGFtYmRhX3tpan0pID0gXGJldGFfMCArIFxiZXRhXzEgdCArIFxiZXRhXzJ0XjIgKyBcYmV0YV8zIHReMysgXGJldGFfNCB0XjQrIFxiZXRhXzUgdF41ICtcc3VtXGxpbWl0c197az0xfV57MTF9e1xkZWx0YV97a319TUVTX3tpamt9ICsgYl97MGp9JCQNCg0KJCRiX3swan0gXHNpbSBOKDAsIFxzaWdtYV97YjB9KSQkDQoNCiMjIyMgTW9kZWxvIDQNCg0KUG9saW5vbWlvIGRlIGdyYWRvIDYgZW4gZnVuY2nDs24gZGVsIHRpZW1wbywgY29uIGVzdGFjaW9uYWxpZGFkIHNlZ8O6biBlbCBNRVMgZSBpbnRlcmNlcHRvIGFsZWF0b3JpbzoNCg0KJCRcbG9nIChcbGFtYmRhX3tpan0pID0gXGJldGFfMCArIFxiZXRhXzEgdCArIFxiZXRhXzJ0XjIgKyBcYmV0YV8zIHReMysgXGJldGFfNCB0XjQgKyBcYmV0YV81IHReNSArIFxiZXRhXzYgdF42ICtcc3VtXGxpbWl0c197az0xfV57MTF9e1xkZWx0YV97a319TUVTX3tpamt9KyBiX3swan0kJA0KDQokJGJfezBqfSBcc2ltIE4oMCwgXHNpZ21hX3tiMH0pJCQNCg0KDQoNCiMjIyBBanVzdGUgY29uIFINCg0KU2UgcmVhbGl6YSBlbCBhanVzdGUgZGUgbG9zIG1vZGVsb3MgcG9yIG1lZGlvIGRlIGxhIGZ1bmNpw7NuIGBnbG1lcmAgZGUgbGEgbGlicmVyaWEgYGxtZTRgLCBhw7FhZGllbmRvIGVsIGF0cmlidXRvIGBmYW1pbHk9IHBvaXNzb24oKWAgcGFyYSBtb2RlbGFyIGxhIGRpc3RyaWJ1Y2nDs24gZGUgJG5fe2lqfSQuDQoNCmBgYHtyLCBlY2hvPSB0LCByZXN1bHRzPSdoaWRlJywgZXZhbCA9IEZ9DQojIyBnbG1lciBhdHRlbXB0cw0KDQojI01vZGVsbzENCm1vZDEgPC0gZ2xtZXIobnJvLmFjY2lkZW50ZXMgfiBwb2x5KHQsIDMpK01FUysgKDF8Q09NVU5BKSwNCiAgICAgICAgICAgIGRhdGEgPSBkYXRhX21lbl9jb211bmFzLCBmYW1pbHk9IHBvaXNzb24oKSkNCiMjTW9kZWxvMg0KbW9kMiA8LSBnbG1lcihucm8uYWNjaWRlbnRlcyB+IHBvbHkodCwgNCkrTUVTKyAoMXxDT01VTkEpLA0KICAgICAgICAgICAgZGF0YSA9IGRhdGFfbWVuX2NvbXVuYXMsIGZhbWlseT0gcG9pc3NvbigpKQ0KIyNNb2RlbG8zDQptb2QzIDwtIGdsbWVyKG5yby5hY2NpZGVudGVzIH4gcG9seSh0LCA1KStNRVMrICgxfENPTVVOQSksDQogICAgICAgICAgICBkYXRhID0gZGF0YV9tZW5fY29tdW5hcywgZmFtaWx5PSBwb2lzc29uKCkpDQojI01vZGVsbzQNCm1vZDQgPC0gZ2xtZXIobnJvLmFjY2lkZW50ZXMgfiBwb2x5KHQsIDYpK01FUysgKDF8Q09NVU5BKSwNCiAgICAgICAgICAgIGRhdGEgPSBkYXRhX21lbl9jb211bmFzLCBmYW1pbHk9IHBvaXNzb24oKSkNCg0KDQojIEd1YXJkYWRvIGRlIGxvcyBtb2RlbG9zDQpzYXZlKG1vZDEsIG1vZDIsIG1vZDMsIG1vZDQsIGZpbGUgPSAiTW9kZWxvcy9jb211bmFfZ2xtZXIuUkRhdGEiKQ0KDQpgYGANCg0KDQoNCiMjIyBDb21wYXJhY2nDs24gZGUgbW9kZWxvcyB7LnRhYnNldH0NCg0KRW4gZXN0YSBzZWNjacOzbiBzZSBlbGVnaXLDoSB1bm8gZGUgbG9zIG1vZGVsb3MgbW9zdHJhZG9zIGFudGVyaW9ybWVudGUsIHByb2JhbmRvIGxhIHNpZ25pZmljYW5jaWEgZGUgbG9zIHBhcsOhbWV0cm9zIGHDsWFkaWRvcyBwb3IgbWVkaW8gZGVsIHRlc3QgZGUgcmF6w7NuIGRlIHZlcm9zaW1pbGl0dWQuIENvbnNpZMOpcmVzZSBkb3MgbW9kZWxvczogJE1vZGVsb0EkIHkgJE1vZGVsb0IkLCBjb24gdmVjdG9yZXMgZGUgcGFyw6FtZXRyb3MgJFx0aGV0YV5BJCB5ICRcdGhldGFeQiQgcmVzcGVjdGl2YW1lbnRlLCBxdWUgY3VtcGxlbiAkXHRoZXRhXkEgXHN1YnNldCBcdGhldGFeQiQuIERlbm90ZW1vcyBhIGxvcyBwYXLDoW1ldHJvcyBkZWwgJE1vZGVsb0IkIHF1ZSBubyBlc3TDoW4gZXMgZWwgJE1vZGVsb0EkIGNvbW8gJFx0aGV0YV5jJCB1biB2ZWN0b3IgZGUgZGltZW5zacOzbiAkcCQsIGVudG9uY2VzIGxhIHBydWViYSBkZSBoaXDDs3Rlc2lzIGFzb2NpYWRhIGEgbGEgc2lnbmlmaWNhbmNpYSBkZSBlc3RvcyBwYXLDoW1ldHJvcyBzZXLDoToNCg0KJCRIXzA6IFx0aGV0YV5jID0gMF97MVx0aW1lcyBwfSBccXVhZCB2LnMgXHF1YWQgSF8xOiBcdGhldGFeYyBcbm90PSAwX3sxXHRpbWVzIHB9JCQNCg0KQ3V5byBlc3RhZMOtc3RpY28gZGUgcHJ1ZWJhIGVzOg0KDQokJExSID0gLTIgXHRpbWVzIChsb2dsaWtlbGlob29kKE1vZGVsb0EpLSBsb2dsaWtlbGlob29kKE1vZGVsb0IpKSQkDQoNCkEgdW4gbml2ZWwgZGUgc2lnbmlmaWNhbmNpYSAkXGFscGhhJCBzZSByZWNoYXphICRIXzAkIHNpICRWUCA9UChcY2hpXjJfcCA+IExSKSA8IFxhbHBoYSQNCg0KDQpFc2EgcHJ1ZWJhIHNlIGRpY2UgZXMgYW50aS1jb25zZXJ2YXRpdmEsIGVzIGRlY2lyIHF1ZSBzdSAkVlAkIHNlcsOhIG3DoXMgcGVxdWXDsW9zIGRlIGxvIG5vcm1hbCwgcG9yIGxvIHF1ZSB1c3VhbG1lbnRlIHNlIHV0aWxpemEgZW4gbHVnYXIgZGUgJFxjaGleMl9wJCBsYSBkaXN0cmlidWNpw7NuIG11ZXN0cmFsIGRlbCBlc3RhZMOtc3RpY28sIGxhIGN1YWwgcHVlZGUgc2VyIGVzdGltYWRhIHBvciBtw6l0b2RvcyBkZSByZW11ZXN0cmVvLiBTaW4gZW1iYXJnbywgZGFkYSBsYSBuYXR1cmFsZXphIGRlIHNlcmllIGRlIHRpZW1wbyBxdWUgdGllbmUgZWwgY29uanVudG8gZGUgZGF0b3MgcHJlc2VudGFkbywgdXRpbGl6YXIgdW5hIHTDqWNuaWNhIGRlIHJlbXVlc3RyZW8gbm8gdGllbmUgbXVjaG8gc2VudGlkbywgcG9yIGxvIHF1ZSBlbiBzdSBsdWdhciBmaWphcmVtb3MgdW4gbml2ZWwgZGUgc2lnbmlmaWNhbmNpYSBtw6FzIHJpZ3Vyb3NvIHkgcG9yIGVuZGUgbcOhcyBwZXF1ZcOxbyBkZSBsbyB1c3VhbCwgaGFjaWVuZG8gJFxhbHBoYSA9IDAuMDEkLg0KDQpBIGNvbnRpbnVhY2nDs24sIHNlIHByZXNlbnRhbiBsYXMgcHJ1ZWJhcyBkZSBoaXDDs3Rlc2lzIHBhcmEgY2FkYSBjb21wYXJhY2nDs246DQoNCg0KIyMjIyBNb2RlbG8gMSB2LnMgTW9kZWxvIDINCg0KJCRIXzA6IFxiZXRhXzQgPSAwIFxxdWFkIHYucyBccXVhZCBIXzE6IFxiZXRhXzQgXG5vdD0wJCQNCg0KYGBge3J9DQphbm92YShtb2QxLCBtb2QyKQ0KYGBgDQoNCkNvbiB1biAkVlAgPSAyLjJlLTE2IDwgMC4wMSQgc2UgcmVjaGF6YSBsYSBoaXDDs3Rlc2lzIG51bGEgeSBzZSBjb25zaWRlcmEgcXVlICRcYmV0YV80JCBlcyBzaWduaWZpY2F0aXZhLg0KDQojIyMjIE1vZGVsbyAyIHYucyBNb2RlbG8gMw0KJCRIXzA6IFxiZXRhXzQgPSAwIFxxdWFkIHYucyBccXVhZCBIXzE6IFxiZXRhXzQgXG5vdD0wJCQNCg0KYGBge3J9DQphbm92YShtb2QyLCBtb2QzKQ0KYGBgDQoNCkNvbiB1biAkVlAgPSAgMC4wMTc2NCA+IDAuMDEkIG5vIHNlIHB1ZWRlIHJlY2hhemFyIGxhIGhpcMOzdGVzaXMgbnVsYSBhbCBuaXZlbCBkZSBzaWduaWZpY2FuY2lhIGVzdGFibGVjaWRvIHkgc2UgY29uc2lkZXJhIHF1ZSAkXGJldGFfNCQgZXMgbm8gc2lnbmlmaWNhdGl2YS4NCg0KIyMjIyBNb2RlbG8gMiB2LnMgTW9kZWxvIDQNCg0KRW4gZXN0ZSBjYXNvIHNlIGVzcGVyYSBxdWUgc2Ugb2J0ZW5nYSBlbCBtaXNtbyByZXN1bHRhZG8gcXVlIGVuIGxhIHBydWViYSBkZWwgTW9kZWxvIDIgdi5zIE1vZGVsbyAzLCBwZXJvIGlndWFsbWVudGUgc2UgaW5jbHV5ZToNCg0KJCRIXzA6IFxiZXRhXzQgPSBcYmV0YV81ID0gMCBccXVhZCB2LnMgXHF1YWQgSF8xOiBcYmV0YV80IFxub3Q9MCB+IHwgfiAgXGJldGFfNSBcbm90PTAgJCQNCg0KYGBge3J9DQphbm92YShtb2QyLCBtb2Q0KQ0KYGBgDQoNCkNvbiB1biAkVlAgPSAgMC4wNTkxMyA+IDAuMDEkIG5vIHNlIHB1ZWRlIHJlY2hhemFyIGxhIGhpcMOzdGVzaXMgbnVsYSBhbCBuaXZlbCBkZSBzaWduaWZpY2FuY2lhIGVzdGFibGVjaWRvIHkgc2UgY29uc2lkZXJhIHF1ZSAkXGJldGFfNCQgeSAkXGJldGFfNSQgc29uIG5vIHNpZ25pZmljYXRpdmFzLg0KDQoNCg0KDQoqKkRlIGxhcyBwcnVlYmFzIGFudGVyaW9yZXMgc2UgZW5jdWVudHJhIHF1ZSBlbCBtb2RlbG8gw7NwdGltbyBlcyBlbCBudW1lcm8gMioqLCBwb3IgbG8gcXVlIHNlIHByb2NlZGUgYSByZWFsaXphciBlbCBhbsOhbGlzaXMgZGUgc3VzIHJlc2lkdWFsZXMuDQoNCiMjIyBFdmFsdWFjacOzbiBkZSByZXNpZHVhbGVzDQoNClF1ZXJlbW9zIGNoZXF1ZWFyIHNpIHNlIGN1bXBsZW4gbG9zIHTDrXBpY29zIHN1cHVlc3RvcyBkZSB2YXJpYW56YSBjb25zdGFudGUgeSBub3JtYWxpZGFkIGRlIGxvcyByZXNpZHVhbGVzLiBQZXJvIGFkZW3DoXMsIHNlIGV2YWx1YXLDoSBzaSBleGlzdGUgZmFsdGEgZGUgYWp1c3RlIHJlc3BlY3RvIGFsIHRpZW1wbyB5IGVsIHN1cHVlc3RvIGRlIG5vcm1hbGlkYWQgZGUgbG9zIGludGVyY2VwdG9zIGFsZWF0b3Jpb3MgJCRiX3swan0gXHNpbSBOKDAsIFxzaWdtYV97YjB9KSQkDQoNCg0KYGBge3IgZWNobz1GLCBmaWcuaGVpZ2h0PTcuNSwgZmlnLndpZHRoPTcuNSwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0NCm1vZGVsb19maW5hbCA8LSBtb2QyDQojIyBHZXR0aW5nIHRoZSByZXNpZHVhbHMgaW4gYSBkYXRhZnJhbWUNCnRlbXAgPC0gZGF0YS5mcmFtZSh0PSBkYXRhX21lbl9jb211bmFzJHQsDQogICAgICAgICAgICAgICAgICAgcj0gZGF0YV9tZW5fY29tdW5hcyRucm8uYWNjaWRlbnRlcywNCiAgICAgICAgICAgICAgICAgICB5ID0gZml0dGVkKG1vZGVsb19maW5hbCksDQogICAgICAgICAgICAgICAgICAgdyA9IHJlc2lkdWFscyhtb2RlbG9fZmluYWwsIHR5cGU9InBlYXJzb24iKSkNCg0KIyMgQSBjdXN0b20gZnVuY3Rpb24gdG8gY3JlYXRlIGEgcXFwbG90DQpxcXBsb3QuZGF0YSA8LSBmdW5jdGlvbiAodmVjKSAjIGFyZ3VtZW50OiB2ZWN0b3Igb2YgbnVtYmVycw0Kew0KICAjIGZvbGxvd2luZyBmb3VyIGxpbmVzIGZyb20gYmFzZSBSJ3MgcXFsaW5lKCkNCiAgeSA8LSBxdWFudGlsZSh2ZWNbIWlzLm5hKHZlYyldLCBjKDAuMjUsIDAuNzUpKQ0KICB4IDwtIHFub3JtKGMoMC4yNSwgMC43NSkpDQogIHNsb3BlIDwtIGRpZmYoeSkvZGlmZih4KQ0KICBpbnQgPC0geVsxTF0gLSBzbG9wZSAqIHhbMUxdDQogIGQgPC0gZGF0YS5mcmFtZShyZXNpZHMgPSB2ZWMpDQoNCiAgZ2dwbG90KGQsIGFlcyhzYW1wbGUgPSByZXNpZHMpKSArIHN0YXRfcXEoc2hhcGU9MjEsc2l6ZT0zLCBmaWxsPSJsaWdodGdvbGRlbnJvZDEiKSsNCiAgICBnZW9tX2FibGluZShpbnRlcmNlcHQgPSAwLCBzbG9wZSA9IDEsIGNvbG9yPSJnb2xkZW5yb2QzIiwgc2l6ZT0xKSsNCiAgICBsYWJzKHggPSAiQ3VhbnRpbGVzIHRlw7NyaWNvcyIsIHkgPSJDdWFudGlsZXMgbXVlc3RyYWxlcyIpKw0KICAgIHRoZW1lX2J3KCkNCg0KfQ0KDQojIyB0ZW8gcmVzIHZzIHNhbXAgcmVzDQpyZXMyIDwtIHFxcGxvdC5kYXRhKHJlc2lkdWFscyhtb2RlbG9fZmluYWwsIHR5cGU9InBlYXJzb24iKSkrDQogIGNvb3JkX2NhcnRlc2lhbih4bGltPWMoLTIuMiwyLjgpLCB5bGltPWMoLTIuMiwyLjgpKQ0KDQojIyBGaXR0ZWQgdnMgUmVzDQpyZXMzIDwtIGdncGxvdChkYXRhPXRlbXAsIGFlcyh4PXksIHk9dykpICsgDQogIHRoZW1lX2J3KCkrZ2VvbV9wb2ludChmaWxsPSJsaWdodGdvbGRlbnJvZDEiLCBzaXplPTIsIHNoYXBlPTIxKSsNCiAgbGFicyh4ID0gIlZhbG9yZXMgYWp1c3RhZG9zIiwgeSA9IlJlc2lkdWFsZXMgZXN0YW5kYXJpemFkb3MiKStnZW9tX2hsaW5lKHlpbnRlcmNlcHQ9YygwLDIsLTIpKSsNCiAgc2NhbGVfeV9jb250aW51b3VzKGxpbWl0cyA9IGMoLTQsIDQpKQ0KDQojIyB0IHZzIHJlcw0KcmVzNCA8LSBnZ3Bsb3QoZGF0YT10ZW1wLCBhZXMoeD10LCB5PXcpKSArIA0KICB0aGVtZV9idygpK2dlb21fcG9pbnQoZmlsbD0ibGlnaHRnb2xkZW5yb2QxIiwgc2l6ZT0yLCBzaGFwZSA9IDIxKStnZW9tX2hsaW5lKHlpbnRlcmNlcHQ9YygtMiwwLDIpKSsNCiAgbGFicyh4ID0gInQiLCB5ID0iUmVzaWR1YWxlcyBlc3RhbmRhcml6YWRvcyIpKw0KICBzY2FsZV95X2NvbnRpbnVvdXMobGltaXRzID0gYygtNCwgNCkpKw0KICBzY2FsZV94X2NvbnRpbnVvdXMoIGJyZWFrcyA9IGRhdGFfbWVuX2NvbXVuYXMkdFtzZXEoZnJvbT0xLCB0byA9IDEzKjUsIGJ5ID0xMildKQ0KDQojIyBRUXBsb3QgZGUgbG9zIGVmZWN0b3MgYWxlYXRvcmlvcw0KZWZmZWN0cyA8LSBkYXRhLmZyYW1lKChyYW5lZihtb2RlbG9fZmluYWwpKSkNCnJlczUgPC0gcXFwbG90LmRhdGEoZWZmZWN0cyRjb25kdmFsKSt5bGFiKCJjdWFudGlsZXMgbXVlc3RhbGVzIGRlIGxvcyBJbnRlcmNlcHRvcyBhbGVhdG9yaW9zIikrDQogIGNvb3JkX2NhcnRlc2lhbih4bGltPWMoLTIsMiksIHlsaW09YygtMiwyKSkNCg0KDQpncmlkRXh0cmE6OmdyaWQuYXJyYW5nZShyZXMzLHJlczQsIHJlczIsIHJlczUsIG5jb2w9MikNCg0KYGBgDQoNCkxvcyBncsOhZmljb3MgZGUgbGEgcHJpbWVyYSBmaWxhLCBjb3JyZXNwb25kaWVudGVzIGEgbG9zIHJlc2lkdWFsZXMgZXN0YW5kYXJpemFkb3MgY29udHJhIGxvcyB2YWxvcmVzIGFqdXN0YWRvcyAoQSkgeSBhIGxvcyByZXNpZHVhbGVzIGVzdGFuZGFyaXphZG9zIGNvbnRyYSBlbCB0aWVtcG8gKEIpLCBubyBtdWVzdHJhbiBuaW5nw7puIGluZGljaW8gZGUgaGV0ZXJvY2VkYXN0aWNpZGFkLiBsb3MgcmVzaWR1YWxlcyBlbiAoQikgbm8gdGllbmVuIG5pbmd1bmEgdGVuZGVuY2lhIG1hcmNhZGEgeSBzZSBkaXNwZXJzYW4gYWxlYXRvcmlhbWVudGUsIHBvciBsbyBxdWUgc2UgY29uc2lkZXJhIG5vIGhheSBmYWx0YSBkZSBhanVzdGUgZGVsIG1vZGVsby4NCg0KRW4gbGEgc2VndW5kYSBmaWxhIGVuY29udHJhbW9zIGxvcyBxcXBsb3QgZGUgbG9zIHJlc2lkdWFsZXMgZXN0YW5kYXJpemFkb3MgKEMpIHkgZGUgbG9zIGludGVydmFsb3MgYWxlYXRvcmlvcyBhanVzdGFkb3MgKEQpLiBEZSAoQykgc2UgcHVlZGUgdmVyIHF1ZSBsb3MgY3VhbnRpbGVzIGRlIGxvcyByZXNpZHVhbGVzIHNlIGRlc3bDrWFuIGRlIGxvcyBjdWFudGlsZXMgdGXDs3JpY29zLCBwb3IgbG8gcXVlIHNlZ3VpcsOtYW4gdW5hIGRpc3RyaWJ1Y2nDs24gZGUgY29sYSBwZXNhZGEuIERlIChEKSBubyBzZSBlbmN1ZW50cmFuIGV2aWRlbmNpYXMgZ3LDoWZpY2FzIGNvbnR1bmRlbnRlcyBjb250cmEgbGEgbm9ybWFsaWRhZCBkZSBsb3MgaW50ZXJjZXB0b3MgYWxlYXRvcmlvcy4NCg0KYGBge3IsIGluY2x1ZGU9Rn0NCiMjIFJlcyBkZW5zaXR5DQpyZXMxIDwtIGdncGxvdCh0ZW1wLCBhZXMoeD13KSkgKyANCiAgdGhlbWVfYncoKStnZW9tX2RlbnNpdHkoYWxwaGE9LjEsICBzaXplID0gMC41LCBjb2w9ImdvbGRlbnJvZDMiKSsNCiAgbGFicyh4ID0gIlJlc2lkdWFsZXMiLCB5ID0iRGVuc2lkYWQiKSt4bGltKC00LDQpDQoNCmBgYA0KDQpFbCBgc3VtbWFyeSgpYCBkZWwgbW9kZWxvIHNlIHByZXNlbnRhIGEgY29udGludWFjacOzbjoNCg0KYGBge3J9DQpzdW1tYXJ5KHJlczEpDQpgYGANCg0KDQoNCg0KIyMjIEV4cHJlc2nDs24gZGVsIG1vZGVsbw0KDQokJFxsb2cgKFx3aWRlaGF0e1xsYW1iZGFfe2lqfX0pID0gNC45MTgwICAtMC4xMzg1dCArIDAuMDkwNnReMiArIDAuNjQwNXReMysgMC45NzA2IHReNCArMC4xMDc0TUVTX3tGZWJyZXJvfStcXDAuMTY4ME1FU197bWFyem99KzAuMTI4N01FU197QWJyaWx9KzAuMTkyNE1FU197TWF5b30rMC4xMTI2TUVTX3tKdW5pb30rXFwgMC4xODU1TUVTX3tKdWxpb30rMC4yMzY5TUVTX3tBZ29zdG99KyAwLjIxNDdNRVNfe1NlcHRpZW1icmV9KyAwLjIwMjhNRVNfe09jdHVicmV9K1xcMC4xMjc0TUVTX3tOb3ZpZW1icmV9KzAuMTY0MU1FU197RGljaWVtYnJlfSArIGJfezBqfSQkDQoNCg0KTG9zIHZhbG9yZXMgZXN0aW1hZG9zIGRlICRiX3swan0kIHNlIG11ZXN0cmFuIGEgY29udGludWFjacOzbjoNCg0KYGBge3IsIGVjaG89Rn0NCnRlbXAgPC0gcmFuZWYobW9kZWxvX2ZpbmFsKVtbMV1dDQp0ZW1wJENvbXVuYSA8LSByb3cubmFtZXModGVtcCkNCnRlbXAkaiA8LTE6MTYNCnRlbXAkYjAgPC0gdGVtcCRgKEludGVyY2VwdClgDQp0ZW1wIDwtIHRlbXBbLGMoMywyLDQpXQ0Kcm93Lm5hbWVzKHRlbXApIDwtIE5VTEwNCnRlbXAlPiUga2FibGUoYWxpZ24gPSAiYyIsZnVsbF93aWR0aCA9IEYsIGJvb2t0YWJzID0gVCklPiUNCiAga2FibGVfc3R5bGluZyhib290c3RyYXBfb3B0aW9ucyA9IGMoInN0cmlwZWQiLCAiY29uZGVuc2VkIikpDQpgYGANCg0KDQpZIGxhIGVzdGltYWNpw7NuIGRlIHN1IHZhcmlhbnphIGVzOiAkXHdpZGVoYXR7XHNpZ21hXjJfe2IwfX0gPSAwLjU3NjUkDQoNCiMjIyBNb2RlbG8gQWp1c3RhZG8gey50YWJzZXR9DQpBIGNvbnRpbnVhY2nDs24gc2UgbXVlc3RyYSBlbCBtb2RlbG8gYWp1c3RhZG8gc29icmUgbG9zIGRhdG9zIHJlYWxlcyBwYXJhIGNhZGEgdW5hIGRlIGxhcyAxNiBjb211bmFzIGRlbCDDoXJlYSB1cmJhbmE6DQoNCmBgYHtyLCBlY2hvPUYsIGluY2x1ZGU9Rn0NCiMjQcOxYWRpZW5kbyB2YWxvcmVzIGFqdXN0YWRvcw0KZGF0YV9tZW5fY29tdW5hcyRmaXQgPC0gZml0dGVkKG1vZGVsb19maW5hbCkNCg0KY29tdW5hcyA8LWxldmVscyhkYXRhX21lbl9jb211bmFzJENPTVVOQSkNCmFkanVzdHMgPC0gbGlzdCgpDQpkYXRhX21lbl9jb211bmFzDQpqIDwtIDENCmZvcihpIGluIGNvbXVuYXMpew0KICBmaXR0ZWRfcGxvdCA8LSBnZ3Bsb3QoYWVzKHggPSAodCksIHkgPSBucm8uYWNjaWRlbnRlcyksIA0KICAgICAgICAgICAgICAgICAgICAgICAgZGF0YSA9IGZpbHRlcihkYXRhX21lbl9jb211bmFzLCBDT01VTkE9PWkpKSArDQogICAgZ2VvbV9wb2ludCggZmlsbCA9ICJnb2xkZW5yb2Q0IikgKw0KICAgIHRoZW1lX2J3KCkgKyANCiAgICBnZW9tX2xpbmUoKSsNCiAgICBzY2FsZV94X2NvbnRpbnVvdXMoIGJyZWFrcyA9IGRhdGFfbWVuX2NvbXVuYXMkdFtzZXEoZnJvbT0xLCB0byA9IDEzKjUsIGJ5ID0xMildLCANCiAgICAgICAgbGFiZWxzID0gZGF0YV9tZW5fY29tdW5hcyRGRUNIQVtzZXEoZnJvbT0xLCB0byA9IDEzKjUsIGJ5ID0xMildKSsgDQogICAgZ2VvbV9saW5lKHNpemUgPSAxLCBhZXMoeSA9IChmaXQpKSwgY29sb3VyPSJyZWQiKQ0KICBhZGp1c3RzW1tqXV0gPC0gZml0dGVkX3Bsb3QNCiAgaiA8LSBqKzENCn0NCmBgYA0KDQojIyMjIEFyYW5qdWV6DQpgYGB7ciwgZWNobz1GLCBmaWcuaGVpZ2h0ID0gNSwgZmlnLndpZHRoPTh9DQphZGp1c3RzW1sxXV0NCmBgYA0KDQojIyMjIEJlbMOpbg0KYGBge3IsIGVjaG89RiwgZmlnLmhlaWdodCA9IDUsIGZpZy53aWR0aD04fQ0KYWRqdXN0c1tbMl1dDQpgYGANCg0KIyMjIyBCdWVub3MgQWlyZXMNCmBgYHtyLCBlY2hvPUYsIGZpZy5oZWlnaHQgPSA1LCBmaWcud2lkdGg9OH0NCmFkanVzdHNbWzNdXQ0KYGBgDQoNCiMjIyMgQ2FzdGlsbGENCmBgYHtyLCBlY2hvPUYsIGZpZy5oZWlnaHQgPSA1LCBmaWcud2lkdGg9OH0NCmFkanVzdHNbWzRdXQ0KYGBgDQoNCiMjIyMgRG9jZSBkZSBPY3R1YnJlDQpgYGB7ciwgZWNobz1GLCBmaWcuaGVpZ2h0ID0gNSwgZmlnLndpZHRoPTh9DQphZGp1c3RzW1s1XV0NCmBgYA0KDQojIyMjIEVsIFBvYmxhZG8NCmBgYHtyLCBlY2hvPUYsIGZpZy5oZWlnaHQgPSA1LCBmaWcud2lkdGg9OH0NCmFkanVzdHNbWzZdXQ0KYGBgDQoNCiMjIyMgR3VheWFiYWwNCmBgYHtyLCBlY2hvPUYsIGZpZy5oZWlnaHQgPSA1LCBmaWcud2lkdGg9OH0NCmFkanVzdHNbWzddXQ0KYGBgDQoNCiMjIyMgTGEgQW3DqXJpY2ENCmBgYHtyLCBlY2hvPUYsIGZpZy5oZWlnaHQgPSA1LCBmaWcud2lkdGg9OH0NCmFkanVzdHNbWzhdXQ0KYGBgDQoNCiMjIyMgTGEgQ2FuZGVsYXJpYQ0KYGBge3IsIGVjaG89RiwgZmlnLmhlaWdodCA9IDUsIGZpZy53aWR0aD04fQ0KYWRqdXN0c1tbOV1dDQpgYGANCg0KIyMjIyBMYXVyZWxlcyBFc3RhZGlvDQpgYGB7ciwgZWNobz1GLCBmaWcuaGVpZ2h0ID0gNSwgZmlnLndpZHRoPTh9DQphZGp1c3RzW1sxMF1dDQpgYGANCg0KIyMjIyBNYW5yaXF1ZQ0KYGBge3IsIGVjaG89RiwgZmlnLmhlaWdodCA9IDUsIGZpZy53aWR0aD04fQ0KYWRqdXN0c1tbMTFdXQ0KYGBgDQoNCiMjIyMgUG9wdWxhcg0KYGBge3IsIGVjaG89RiwgZmlnLmhlaWdodCA9IDUsIGZpZy53aWR0aD04fQ0KYWRqdXN0c1tbMTJdXQ0KYGBgDQoNCiMjIyMgUm9ibGVkbw0KYGBge3IsIGVjaG89RiwgZmlnLmhlaWdodCA9IDUsIGZpZy53aWR0aD04fQ0KYWRqdXN0c1tbMTNdXQ0KYGBgDQoNCiMjIyMgU2FuIEphdmllcg0KYGBge3IsIGVjaG89RiwgZmlnLmhlaWdodCA9IDUsIGZpZy53aWR0aD04fQ0KYWRqdXN0c1tbMTRdXQ0KYGBgDQoNCiMjIyMgU2FudGEgQ3J1eg0KYGBge3IsIGVjaG89RiwgZmlnLmhlaWdodCA9IDUsIGZpZy53aWR0aD04fQ0KYWRqdXN0c1tbMTVdXQ0KYGBgDQoNCiMjIyMgVmlsbGEgSGVybW9zYQ0KYGBge3IsIGVjaG89RiwgZmlnLmhlaWdodCA9IDUsIGZpZy53aWR0aD04fQ0KYWRqdXN0c1tbMTZdXQ0KYGBgDQoNCg0KDQoNCiMjIE1vZGVsbyBjb24gcmVzcHVlc3RhIE11bHRpbm9taWFsDQoNCkNvbW8gc2Ugbm90w7MgZW4gZWwgYW7DoWxpc2lzIGRlc2NyaXB0aXZvLCBleGlzdGVuIGRpZmVyZW5jaWFzIGVuIGxhIGNhbnRpZGFkIGRlIGFjY2lkZW50ZXMgc2Vnw7puIGxhIENMQVNFLCBwb3IgbG8gcXVlIGFkaWNpb25hbCBhbCBtb2RlbG8gUG9pc3Nvbiwgc2UgcHJlc2VudGEgZWwgYWp1c3RlIHVuYSByZWdyZXNpw7NuIGNvbiByZXNwdWVzdGEgbXVsdGlub21pYWwgbGEgY3VhbCBwdWVkZSBkaWZlcmVuY2lhcnNlIGRlIGxhIG3DoXMgY29ub2NpZGEgcmVncmVzacOzbiBsb2fDrXN0aWNhIE11bHRpbm9taWFsLCBxdWUgZXMgdW4gbcOpdG9kbyBkZSBjbGFzaWZpY2FjacOzbiwgbGEgcmVzcHVlc3RhIG11bHRpbm9taWFsIHRpZW5lIHBvciByZXNwdWVzdGEgY29udGVvIGVuIGRpZmVyZW50ZXMgY2F0ZWdvcsOtYXMuIFNlYW46DQoNCiQkbyA9IEF0cm9wZWxsbyxcO1w7IHAgPSBDYWlkYS5PY3VwYW50ZSxcO1w7IHEgPSBDaG9xdWUsXDtcOyByID0gVm9sY2FtaWVudG8sXDtcOyBzID0gT3RybyBcXCBqOiBDb211bmFcOyAoMToxNikgXFwgaTogb2JzZXJ2YWNpw7NuXDsgY29ycmVzcG9uZGllbnRlXDsgYVw7IHVuXDttZXMgXDsgZW50cmUgXDsgMjAxNCBcOyB5IFw7IDIwMTkgXDsgKDE6NzIpJCQNCg0KRWxsIHZlY3RvciBkZSBBY2NpZGVudGFsaWRhZCAkeV97aSxqfSQ6DQoNCiQkeV97aSxqfSA9ICh5X3tpLGp9Xm8sIHlfe2ksan1ecCwgeV97aSxqfV5xLCB5X3tpLGp9XnIsIHlfe2ksan1ecykkJA0KDQpDb24gdW4gdG90YWwgZGUgYWNjaWRlbnRlcyAobnJvLmFjY2lkZW50ZXMpIGRhZG8gcG9yOg0KJCRuX3tpan0gPSB5X3tpLGp9Xm8gKyB5X3tpLGp9XnAgKyB5X3tpLGp9XnEgKyB5X3tpLGp9XnIgKyB5X3tpLGp9XnMkJA0KDQpZICRcdGhldGFfe2lqfSQgZWwgdmVjdG9yIGRlIHByb2JhYmlsaWRhZCBzZWfDum4gbGEgY2xhc2UgZGVsIGFjY2lkZW50ZS4NCg0KJCRcdGhldGFfe2lqfSA9IChcdGhldGFfe2lqfV5vLCBcdGhldGFfe2lqfV5wLFx0aGV0YV97aWp9XnEsIFx0aGV0YV97aWp9XnIsIFx0aGV0YV97aWp9XnMpJCQNCg0KDQpQYXJhIGFqdXN0YXIgbnVlc3RybyBtb2RlbG8gY29uc2lkZXJhcmVtb3MgcXVlOg0KDQokJHlfe2lqfXxcdGhldGFfe2lqfSBcc2ltIE11bHRpbm9taWFsKG5fe2lqfSwgXHRoZXRhX3tpan0pJCQNCg0KDQokJFx0aGV0YV9pID0gU29mdG1heCgwLCBcbXVfal5wLFxtdV9qXnEsIFxtdV9qXnIsIFxtdV9qXnMpJCQNCg0KRW50b25jZXMsIG51ZXN0cm8gb2JqZXRpdm8gZXMgbW9kZWxhciAkXG11X2pecCxcbXVfal5xLCBcbXVfal5yLCBcbXVfal5zJCBpbmNsdXllbmRvIGNvdmFyaWFibGVzLg0KDQpQYXJhIGFqdXN0YXIgZWwgbW9kZWxvIHV0aWxpemFyZW1vcyBlbCBwYXF1ZXRlIGBicm1zYGRlIFIsIHF1ZSBwZXJtaXRlIGFqdXN0YXIgbW9kZWxvIG11bHRpbml2ZWwgY29uc2lkZXJhbmRvIHVuYSBncmFuIHZhcmllZGFkIGRlIGRpc3RyaWJ1Y2lvbmVzIHBhcmEgbGEgdmFyaWFibGUgcmVzcHVlc3RhIHkgdGllbmUgdW4gZ3JhbiBmdW5kYW1lbnRvIGVuIGxhIGVzdGFkw61zdGljYSBCYXllc2lhbmEuIFNpbiBlbWJhcmdvLCBzZSBoYSBkZSBtZW5jaW9uYXIgcXVlIGxhIGZhbWlsaWEgbXVsdGlub21pYWwgZXMgcmVsYXRpdmFtZW50ZSBudWV2YSBlbiBgYnJtc2AsIHBvciBsbyBxdWUgY2FyZWNlIGRlIG11Y2hvcyBlc3RhZMOtc3RpY29zIGNvbXBhcmF0aXZvcyB5IG1ldG9kb2xvZ8OtYXMgcGFyYSByZWFsaXphciBjb21wYXJhY2lvbmVzIGVudHJlIG1vZGVsb3MgbyBwcm9iYXIgbGEgc2lnbmlmaWNhbmNpYSBkZSBlZmVjdG9zLg0KVW4gbW9kZWxvIHBvZHLDrWEgc2VyIGVsZWdpZG8gZW4gYmFzZSBhIHN1IGNhcGFjaWRhZCBwcmVkaWN0aXZhLCByZWFsaXphbmRvIG3DqXRvZG9zIGRlIHZhbGlkYWNpw7NuIGNydXphZGEgKGVzcGVjw61maWNvcyBwYXJhIHNlcmllcyBkZSB0aWVtcG8pLCB0YWwgeSBjb21vIGV4cG9uZSBbM10uIFNpbiBlbWJhcmdvLCBgYnJtc2AgcG9yIHN1cyBtZXRvZG9sb2fDrWFzIGJheWVzaWFuYXMgcGFyYSBlbCBhanVzdGUsIGNvbnN1bWUgbXVjaG9zIHJlY3Vyc29zIGNvbXB1dGFjaW9uYWxlcyB5IGNvbnNpZ3VpZW50ZW1lbnRlLCB0YXJkYSBtdWNobyBlbiBzdSBhanVzdGUsIHBvciBsbyBxdWUgY2FsY3VsYXIgbcO6bHRpcGxlcyBtb2RlbG9zIGVzIHVuYSB0YXJlYSBsYXJnYSB5IHRlZGlvc2EuDQoNCkRhZG8gcXVlIGVsIGFqdXN0ZSBkZSBlc3RlIG1vZGVsbyBubyBlcyBlbCBvYmpldGl2byBwcmluY2lwYWwgZGUgZXN0ZSBkb2N1bWVudG8geSBlcyB0YW4gc29sbyB1biBhw7FhZGlkbyBxdWUgcGFydGUgZGUgbGEgY3VyaW9zaWRhZCBkZSBxdWllbiBlc2NyaWJlIGVzdGFzIHBhbGFicmFzLCBzZSBhanVzdGFyw6EgdW4gw7puaWNvIG1vZGVsby4NCg0KDQojIyMgQWp1c3RlIGRlbCBtb2RlbG8NCg0KDQokJFxtdV9qXnAgPSBcYmV0YV8wXnAgKyBcYmV0YV8xXnAgdCArIFxiZXRhXzJecHReMiArIFxiZXRhXnBfMyB0XjMgK1xzdW1cbGltaXRzX3trPTF9XnsxMX17XGRlbHRhXnBfe2t9fU1FU197aWprfSAgKyBiXnBfezBqfSQkDQokJFxtdV9qXnEgPSBcYmV0YV8wXnEgKyBcYmV0YV8xXnEgdCArIFxiZXRhXzJecXReMiArIFxiZXRhXnFfMyB0XjMrXHN1bVxsaW1pdHNfe2s9MX1eezExfXtcZGVsdGFecV97a319TUVTX3tpamt9ICArIGJecV97MGp9JCQNCiQkXG11X2peciA9IFxiZXRhXzBeciArIFxiZXRhXzFeciB0ICsgXGJldGFfMl5ydF4yICsgXGJldGFecl8zIHReMytcc3VtXGxpbWl0c197az0xfV57MTF9e1xkZWx0YV5yX3trfX1NRVNfe2lqa30gICsgYl5yX3swan0kJA0KJCRcbXVfal5zID0gXGJldGFfMF5zICsgXGJldGFfMV5zIHQgKyBcYmV0YV8yXnN0XjIgKyBcYmV0YV5zXzMgdF4zICtcc3VtXGxpbWl0c197az0xfV57MTF9e1xkZWx0YV5zX3trfX1NRVNfe2lqa30gKyBiXnNfezBqfSQkDQoNCkNvbiAkYl5wX3swfVxzaW0gTigwLCBcc2lnbWFeMl97Yl5wX3swfX0pJCwgJGJecV97MH1cc2ltIE4oMCwgXHNpZ21hXjJfe2JecV97MH19KSQsICRiXnJfezB9XHNpbSBOKDAsIFxzaWdtYV4yX3tiXnJfezB9fSkkIHkgICRiXnNfezB9XHNpbSBOKDAsIFxzaWdtYV4yX3tiXnNfezB9fSkkDQoNCg0KIyMjIEPDs2RpZ28gZW4gUjoNCkVsIGFqdXN0ZSBkZSBlc3RlIG1vZGVsbyBzZSByZWFsaXrDsyBiYXNhZG8gZW4gbG9zIGVqZW1wbG9zIGRlIFsxXSB5IFsyXS4NClByaW1lcm8gc2UgaGFjZSBuZWNlc2FyaW8gaW5kaWNhcmxlIGEgYGJybXNgIGN1YWxlcyBzb24gbGFzIGNhdGVnb3LDrWFzIHBhcmEgbGFzIHF1ZSB2YSBhIHByZWRlY2lyLCBlc3RvIHNlIGhhY2UgZGUgZXN0YSBtYW5lcmE6DQoNCmBgYHtyLCBpbmNsdWRlPUZ9DQojbG9hZCgiTW9kZWxvcy9maXQxX2JybXNfbXVsdGkuUkRhdGEiKQ0KbG9hZCh1cmwoImh0dHBzOi8vZ2l0aHViLmNvbS9qZm1yYTk5L01vZGVsb3NfSmVyYXJxdWljb3MvcmF3L21hc3Rlci9BcGxpY2FjaW9uUlB1YnMvTW9kZWxvcy9maXQxX2JybXNfbXVsdGkuUkRhdGEiKSkNCmBgYA0KDQpgYGB7cn0NCmRhdGFfbWVuX2NvbXVuYXMkQWNjaWRlbnRhbGlkYWQgPC0gd2l0aChkYXRhX21lbl9jb211bmFzLCBjYmluZChBdHJvcGVsbG8sIENhaWRhLk9jdXBhbnRlLCBDaG9xdWUsIFZvbGNhbWllbnRvLCBPdHJvKSkNCmBgYA0KDQpMdWVnbyBlbCBtb2RlbG8gZXMgYWp1c3RhZG8gdXRpbGl6YW5kbzoNCmBgYHtyLCBldmFsPUZBTFNFfQ0KZm9ybXVsYTEgPC0gYmYoIEFjY2lkZW50YWxpZGFkIHwgdHJpYWxzKG5yby5hY2NpZGVudGVzKSB+IHBvbHkodCwgMykgKyBNRVMgKyAoMSB8IENPTVVOQSkpDQpmaXQxIDwtIGJybShmb3JtdWxhMSwgZGF0YSA9IHRlc3RfRGF0YSwgZmFtaWx5ID0gbXVsdGlub21pYWwoKSwgc2VlZCA9IDMxNCwgY29yZXM9IDQpDQpgYGANCg0KIyMjIEV4cHJlc2nDs24gZGVsIG1vZGVsbyBlc3RpbWFkbw0KDQokJFx3aWRlaGF0e1xtdV5wfSA9ICAtMC4xNyArMS41MyB0IC0wLjQ1IHReMiAtMS4zMCB0XjMgLTAuMDQgTUVTX3tGZWJydWFyeX0gKyAwLjA2IE1FU197TWFyY2h9XFwgKyAwLjAyIE1FU197QXByaWx9ICswLjEwTUVTX3tNYXl9ICAtMC4wNU1FU197SnVuZX0gKyAwLjAxTUVTX3tKdWx5fSArMC4xNU1FU197QXVndXN0fSArIDAuMDhNRVNfe1NlcHRlbWJlcn1cXCArIDAuMDNNRVNfe09jdG9iZXJ9ICswLjA5TUVTX3tOb3ZlbWJlcn0gIC0wLjA0TUVTX3tEZWNlbWJlcn0gKyBiXnBfezB9JCQNCg0KJCRcd2lkZWhhdHtcbXVecX0gPSAgIDMuMjUgLTEuODEgdCAtMS44MSB0XjIgLTEuMDQgdF4zICswLjA3IE1FU197RmVicnVhcnl9IC0gMC4wMCBNRVNfe01hcmNofVxcICsgMC4wOCBNRVNfe0FwcmlsfSArMC4wOCBNRVNfe01heX0gICswLjAyTUVTX3tKdW5lfSArIDAuMDUgTUVTX3tKdWx5fSArMC4wNk1FU197QXVndXN0fSArIDAuMDQgTUVTX3tTZXB0ZW1iZXJ9XFwgKyAwLjA2IE1FU197T2N0b2Jlcn0gKyAwLjA2IE1FU197Tm92ZW1iZXJ9ICAtMC4wNE1FU197RGVjZW1iZXJ9ICsgYl5xX3swfSQkDQoNCiQkXHdpZGVoYXR7XG11XnJ9ID0gIC0xLjI2IC0zLjgyIHQgKzMuOTEgdF4yICswLjA3IHReMyAtMC4wNCBNRVNfe0ZlYnJ1YXJ5fSAtMC4wMCBNRVNfe01hcmNofVxcICsgMC4xMyBNRVNfe0FwcmlsfSArIDAuMTEgTUVTX3tNYXl9ICArMC4xNCBNRVNfe0p1bmV9ICsgMC4xNiBNRVNfe0p1bHl9ICswLjE2TUVTX3tBdWd1c3R9ICsgMC4xMk1FU197U2VwdGVtYmVyfVxcICsgMC4xN01FU197T2N0b2Jlcn0gKzAuMTdNRVNfe05vdmVtYmVyfSAgKzAuMDFNRVNfe0RlY2VtYmVyfSArIGJecl97MH0kJA0KDQokJFx3aWRlaGF0e1xtdV5zfSA9ICAgMC4wMyArMi40MyB0IC0xLjY3IHReMiArIDAuNDIgdF4zIC0wLjAwIE1FU197RmVicnVhcnl9IC0gMC4wOCBNRVNfe01hcmNofVxcIC0wLjA1IE1FU197QXByaWx9ICsgMC4wNiBNRVNfe01heX0gLSAwLjAwTUVTX3tKdW5lfSArIDAuMDhNRVNfe0p1bHl9ICswLjA1TUVTX3tBdWd1c3R9ICsgMC4wNE1FU197U2VwdGVtYmVyfVxcICsgMC4wMiBNRVNfe09jdG9iZXJ9IC0gMC4wMk1FU197Tm92ZW1iZXJ9IC0wLjA5TUVTX3tEZWNlbWJlcn0gKyBiXnBfezB9JCQNCg0KYGBge3IsIGluY2x1ZGU9Rn0NCnN1bW1hcnkoZml0MSkNCmBgYA0KDQpDb24gZXN0aW1hY2nDs24gZGUgZWZlY3RvcyBhbGVhdG9yaW9zOg0KDQpgYGB7cn0NCnJhbmVmKGZpdDEpDQpgYGANCg0KWSB2YXJpYW56YXMgZGUgZWZlY3RvcyBhbGVhdG9yaW9zIGVzdGltYWRhcyAkXHdpZGVoYXR7XHNpZ21hXjJfe2JecF97MH19fSA9IDAuNDIkICwgJFx3aWRlaGF0e1xzaWdtYV4yX3tiXnFfezB9fX0gPSAwLjg3JCAkXHdpZGVoYXR7XHNpZ21hXjJfe2Jecl97MH19fSA9IDAuNTEkICwgJFx3aWRlaGF0e1xzaWdtYV4yX3tiXnNfezB9fX0gPSAwLjQ4JA0KDQojIENvbWVudGFyaW9zIGdlbmVyYWxlcw0KDQotIExvcyBtb2RlbG9zIG1peHRvcyBzb24gdW5hIGhlcnJhbWllbnRhIHF1ZSBwZXJtaXRlIGFqdXN0YXIgbW9kZWxvcyBnbG9iYWxlcyBxdWUgc2UgY2FyYWN0ZXJpY2VuIGEgbGFzIHBhcnRpY3VsYXJpZGFkZXMgZGUgaW5kaXZpZHVvcyAoZW4gZXN0ZSBjYXNvIENvbXVuYXMpLCBsbyBxdWUgcGVybWl0ZSB0ZW5lciBtb2RlbG9zIHZlcnPDoXRpbGVzIHkgcHJlY2lzb3MgcGFyYSBsYXMgcHJlZGljY2lvbmVzLg0KDQoNCi0gVW5hIGV4cGFuc2nDs24gZGUgZXN0ZSB0cmFiYWpvIHB1ZWRlIGlyIGRpcmlnaWRhIGEgYWp1c3RhciB1biBtb2RlbG8gZW4gdW5hIGVzY2FsYSB0ZW1wb3JhbCBkaXN0aW50YSwgZGlnYW1vcyBzZW1hbmFsIG8gZGlhcmlhbWVudGUuIE8gdXRpbGl6YXIgbG9zIGJhcnJpb3MgY29tbyBsYSB2YXJpYWJsZSBkZSBhZ3J1cGFtaWVudG8uDQoJDQotIEVubGF6YXIgdW4gbW9kZWxvIFBvaXNzb24gcGFyYSBwcmVkZWNpciBlbCBuw7ptZXJvIHRvdGFsIGRlIGFjY2lkZW50ZXMgeSB1biBtb2RlbG8gbXVsdGlub21pYWwgcGFyYSBwcmVkZWNpciBlbCBuw7ptZXJvIGRlIGFjY2lkZW50ZXMgcG9yIGNhZGEgY2xhc2UgcG9kcsOtYSBwcm92ZWVyIGRlIHVuYSBoZXJyYW1pZW50YSDDunRpbCBwYXJhIHRvbWFyIHBsYW5lcyBkZSBhY2Npw7NuIHJlc3BlY3RvIGEgbGEgbW92aWxpZGFkIGRlIGxhIGNpdWRhZC4gQXVucXVlIHN1IHV0aWxpZGFkIGlubWVkaWF0YSBwb2Ryw61hIHZlcnNlIGFmZWN0YWRhIHBvciBlbCBoZWNobyBkZSBxdWUgbGEgw7psdGltYSB2ZXogcXVlIG1pcsOpIHBvciBtaSB2ZW50YW5hIGFwZW5hcyB5IGhhYsOtYSB2ZWjDrWN1bG9zIGVuIHRyw6Fuc2l0bywgcHJvZHVjdG8gZGUgbGFzIG1lZGlkYXMgZXN0YXRhbGVzIGRlIGFpc2xhbWllbnRvIHNvY2lhbC4NCg0KIyBSZWZlcmVuY2lhcw0KDQotIFsxXSBJdmFuIFVraG92ICgyMDIwKS4gQmF5ZXNpYW4gaW5mZXJlbmNlIG9mIHRoZSBuZXQgcHJvbW90ZXIgc2NvcmUgdmlhIG11bHRpbGV2ZWwgcmVncmVzc2lvbiB3aXRoIHBvc3RzdHJhdGlmaWNhdGlvbi4gUmVjdXBlcmFkbyBkZSBodHRwczovL2Jsb2cuaXZhbnVraG92LmNvbS8yMDIwLzAyLzAzL25ldC1wcm9tb3Rlci5odG1sDQoNCi0gWzJdIEV4YW1wbGUgd2l0aCBGYW1pbHkgTXVsdGlub21pYWwuIFJlY3VwZXJhZG8gZGUgaHR0cHM6Ly9kaXNjb3Vyc2UubWMtc3Rhbi5vcmcvdC9leGFtcGxlLXdpdGgtZmFtaWx5LW11bHRpbm9taWFsLzg3MDcNCg0KLSBbM10gUm9iIEogSHluZG1hbiAoMjAxNikuIENyb3NzLXZhbGlkYXRpb24gZm9yIHRpbWUgc2VyaWVzLiBSZWN1cGVyYWRvIGRlIGh0dHBzOi8vcm9iamh5bmRtYW4uY29tL2h5bmRzaWdodC90c2N2Lw0KDQotIFs0XSBGcmVkZHkgSGVybsOhbmRleiBCYXJhamFzIHkgSm9yZ2UgTGVvbmFyZG8gTMOzcGV6IE1hcnTDrW5leiAoMjAyMCkuIE1vZGVsb3MgTWl4dG9zIGNvbiBSLiBodHRwczovL2ZoZXJuYW5iLmdpdGh1Yi5pby9saWJyb19tb2RlbG9zX21peHRvcy8NCg0KLSBbNV0gUGF1bC1DaHJpc3RpYW4gQsO8cmtuZXIgKDIwMTcpLiBicm1zOiBBbiBSIFBhY2thZ2UgZm9yIEJheWVzaWFuIE11bHRpbGV2ZWwgTW9kZWxzIFVzaW5nIFN0YW4uDQogIEpvdXJuYWwgb2YgU3RhdGlzdGljYWwgU29mdHdhcmUsIDgwKDEpLCAxLTI4LiBkb2k6MTAuMTg2MzcvanNzLnYwODAuaTAxDQogIA0KLSBbNl0gRG91Z2xhcyBCYXRlcywgTWFydGluIE1hZWNobGVyLCBCZW4gQm9sa2VyLCBTdGV2ZSBXYWxrZXIgKDIwMTUpLiBGaXR0aW5nIExpbmVhciBNaXhlZC1FZmZlY3RzDQogIE1vZGVscyBVc2luZyBsbWU0LiBKb3VybmFsIG9mIFN0YXRpc3RpY2FsIFNvZnR3YXJlLCA2NygxKSwgMS00OC4gZG9pOjEwLjE4NjM3L2pzcy52MDY3LmkwMS4NCg0K