Resumen

Resumen: Costa Rica presenta un clima variable, con altas temperaturas, y abundantes precipitaciones. Los vientos provenientes del Caribe, generan variaciones en el comportamiento de diversos factores climáticos en el país. Esta investigación plantea analizar la variabilidad climática en los últimos 30 años en dos gradientes altitudinales en la vertiente del Caribe, para determinar los factores que producen cambios en las temperaturas y precipitación. Se trabajó una base de datos de precipitación (mm), temperatura máxima y mínima (°C) en dos estaciones, proporcionados por el Instituto Meteorológico Nacional. Mediante el programa R-ClimDex, se calcularon diversos índices climáticos, basados en un previo análisis de regresión lineal.Cada uno de los índices con valores significativos (P-value <0.05), se sometieron a la prueba de Shapiro.Wilk a los residuos para demostrar la normalidad de los datos con ayuda del programa R. Precipitaciones con mayor intensidad y temperaturas más bajas son los factores con más significancia. Dichas variaciones obedecen a los fenómenos ENOS, que generan lluvias en menos tiempo y más violentas. Los rayos del sol no penetran en su totalidad a causa de mucha nubosidad, por lo que la temperatura baja. Esto supone la existencia de variabilidad climática, afectando a largo plazo los ecosistemas y las actividades humanas.

Palabras clave: Variabilidad climática, precipitación, temperatura, gradiente altitudinal, Vertiente del Caribe.

Introducción

Costa Rica es un país que se caracteriza porque gran parte del año presenta un clima caracterizado por sus altas temperaturas y abundantes lluvias representativo de un clima tropical. Por esta razón la variación más importante es la lluvia ya que afectan los diferentes sistemas de viento y la topografía (Lizano y Salas, 2001). Costa Rica comprende la vertiente del caribe la cual presenta temperaturas muy variadas de acuerdo con la altitud, siendo ésta la distancia vertical que existe sobre cualquier punto de la Tierra tomando como referencia el nivel del mar, por lo que ésta zona se encuentra directamente expuesta a los vientos alisios que llegan cargados de humedad al Caribe. Este parámetro produce una gran cantidad de variaciones en el comportamiento de diferentes componentes o factores climáticos (Retana y Villalobos, 2000). Estas variaciones reciben el nombre de variabilidad climática la cual es un fenómeno que afecta a una gran cantidad de sectores, desde las actividades humanas como en los diferentes entornos naturales que sufren importantes variaciones en la estabilidad de sus ecosistemas (Yáñez-Arancibia, Twilley y Lara-Domínguez, 1998).

Existen varios factores a la hora de estudiar los efectos de la variabilidad climática sobre un entorno, donde la precipitación y la medición de las temperaturas máximas y mínimas ofrecen un claro panorama a la hora de determinar estos cambios (Puertas y Carvajal, 2008). La precipitación que es la caída de agua desde la atmósfera hasta la superficie terrestre, formando parte del ciclo del agua. La precipitación se genera por la condensación del agua, es decir, la formación de nubes por la acumulación de agua en la atmósfera. Otro factor importante es la temperatura atmosférica, la cual se ve reflejada cuando las radiaciones solares llegan a la superficie terrestre provocando que su energía caliente el suelo y así mismo las capas del aire que se encuentran en contacto. Este efecto se ve reflejado en el aumento de la temperatura a lo largo de los años ya que las radiaciones no son absorbidas por el suelo y se reflejan para escapar de nuevo a la atmósfera, sin embargo, se devuelven a la superficie terrestre debido al dióxido de carbono y el vapor (Alfaro y Amador, 1997). La temperatura atmosférica, comprende temperaturas máximas, que es la mayor temperatura del aire alcanzada en un lugar en un día (máxima diaria), en un mes (máxima mensual) o en un año (máxima anual), y temperaturas mínimas, que al contrario, es la menor temperatura registrada en un lugar a lo largo de un día, mes o año.

Es importante comprender la diferencia entre variabilidad y cambio climático, la variabilidad según Alzate, Rojas, Mosquera y Ramón (2015) se puede definir como cambios o modificaciones en los componentes climáticos en periodos de tiempo cortos mientras que el cambio climático se refiere a diferencias climáticas a lo largo de grandes periodos y que presentan un estado irreversible a su condición previa. Debido a esto es que la variabilidad climática debe de ser analizada en rangos temporales pequeños como meses, ya que si se promedian las variables a lo largo de un año no se detectarán las diferencias. La variabilidad climática puede ser causada por oscilaciones térmicas, que son diferencias numéricas entre los valores máximos y mínimos de temperatura observados en un punto dado durante un período de tiempo. Una de estas oscilaciones es la Oscilación del sur (ENOS), que son los cambios interanuales, con una escala de tiempo de varios años (2 a 7 años), de las condiciones atmosféricas y temperaturas oceánicas fluctuantes sobre los océanos Pacifico e Indico ecuatoriales (Fernández y Ramírez, 1991). El Niño es la fase caliente del ENOS, y se refiere a la interacción climática océano-atmósfera a gran escala, asociada a un calentamiento periódico. Por otra parte, La Niña es la fase fría del ENOS asociada al Niño, es precedida y seguida por periodos en los cuales las temperaturas superficiales del mar son más bajas de lo normal en el pacífico central y oriental y los vientos alisios son muy fuertes (Fernández y Ramírez, 1991).

En este contexto, es de gran importancia estudiar la variabilidad climática, ya que se pueden realizar perspectivas a corto y a mediano plazo, y con esto se podrían implementar acciones respecto a la adaptación de la variabilidad climática (Markus, 2017). El presente trabajo tiene como objetivo analizar la variabilidad climática en los últimos 30 años en dos gradientes altitudinales en la vertiente del Caribe (5 y 1400 msnm), para determinar los impactos que podrían producir los cambios en temperatura (máxima y mínima) y precipitación de ambas zonas.

Objetivos

Objetivo general

Analizar la variabilidad climática en los últimos 30 años en dos gradientes altitudinales en la vertiente del Caribe (5 y 1400 msnm), para determinar los impactos que podrían generar los cambios en temperatura y precipitación de ambas zonas.

Objetivos específicos

1-Determinar los principales cambios en la precipitación y temperatura (mínima y máxima) en dos altitudes de la vertiente Caribe (5 y 1400 msnm).

2-Comparar la variabilidad climática entre las dos estaciones del Caribe a diferentes altitudes (5 y 1400 msnm).

3-Generar perspectivas de los cambios en la precipitación y temperatura (máxima y mínima) de ambas zonas.

Materiales y Métodos

En esta investigación se utilizó datos de precipitación (mm) y temperatura (máxima y mínima, °C) diarios de dos estaciones meteorológicas (Linda Vista y Limón) proporcionados por el Instituto Meteorológico Nacional (IMN, Cuadro 1). Ambas estaciones poseen el mismo periodo de medición de datos diarios entre 1980 y 2010 y se encuentran en la misma vertiente Caribe, pero difieren en altitud (Limón: 5 msnm; y Linda Vista: 1400 msnm). La altitud entre ambas estaciones fue un factor determinante en esta investigación. Se tomaron en cuenta estaciones con poca similitud en términos de gradiente altitudinal, con el fin de determinar el comportamiento de las lluvias y la afectación de otros fenómenos en cada uno de las fronteras de la vertiente del Caribe. Las estaciones meteorológicas poseen un periodo de 30 años, que representa el mínimo de años requerido para el estudio de clima en una zona específica.

Figura1

Mediante el programa de R, se calculó el promedio mensual de la temperatura máxima, temperatura mínima y precipitación. Para poder calcular la temperatura promedio mensual de cada año, cada mes debe contener como mínimo el 50 % de la información completa. Con respecto a los datos de precipitación, se realiza una sumatoria, debe de existir mínimo 24 días que se refieren al 80% de la información completa por mes.

Este programa necesita de ciertos parámetros, para poder realizar un análisis estadístico. Se realizó una comparación de la información disponible durante los treinta años con de la primera década de los datos. Se calculó para los valores mínimos y máximos con el percentil 5 y 95 tanto de la temperatura máxima como de la temperatura mínima. Se calculó el percentil 95 para los datos de precipitación.

Para poder describir la variabilidad mediante análisis estadísticos se utilizan diversas metodologías, las cuales estudian el comportamiento del clima en espacio y tiempo. Un ejemplo de ello, es la aplicación de un programa estadístico llamado RClimDex, el cual realiza un análisis estadístico de la variabilidad temporal de las precipitaciones, temperaturas máximas y mínimas. (Zhang y Yang, 2004). Este programa fue diseñado para dar seguimiento y detectar el cambio climático. Además se utiliza como plataforma de trabajo, el programa R por ser vigoroso y completo en lo que respecta al análisis estadístico y al mismo tiempo muy minucioso en la elaboración de gráficos. RClimDex facilita una interfaz para el cálculo de índices extremos climáticos con límites que pueden ser definidos por el usuario. Este programa permite calcular 27 índices (Zhang y Yang, 2004), dentro de los cuales solo 26 de ellos fueron útiles para la investigación realizada. Los índices utilizados en el programa RClimDex, se basan en valores de temperatura máxima diaria, temperatura mínima diaria y precipitación diaria, donde Tx representa los valores de temperatura máxima, Tn los valores de temperatura mínima, PRCP indica la cantidad de precipitación y RR define los días húmedos (días con lluvia). Los valores de referencia que se requieren para el análisis de los índices se obtuvieron a partir de los registros diarios de los primeros 10 años de estudio (1980-1990). Se calcularon los valores máximos de precipitación diaria que se registran con el percentil 90 que se refiere al 90% de las precipitaciones; se establece este valor con el fin de eliminar los valores extremos poco frecuentes Además de ello, se calculan los valores máximos y mínimos de la temperatura máxima y los valores máximos y mínimos de la temperatura mínima. Con ello, se presenta un resumen de los 26 índices de RClimDex, que se utilizaron para el análisis de esta investigación y se describen a continuación. Cabe destacar que uno de los índices con los que trabaja este programa, se utiliza para calcular temperaturas menores a los 0°C, por ello, no cumple con los objetivos de este trabajo, ya que Costa Rica al ser un país tropical, no cuenta con esas temperaturas.}

Análisis de datos Los índices previamente mencionados se sometieron a análisis de regresión lineal (α=0.05). Todos los supuestos de regresión lineal fueron sometidos a prueba (normalidad de residuos: Shapiro Wilk, Waine (1991); e independencia de residuos). Los datos atípicos fueron previamente detectados y eliminados de todas las regresiones lineales. RClimDex genera diferentes tipos de figuras de cada uno de los índices calculados, sin embargo, para efectos de esta investigación fueron nuevamente realizados con ayuda de lenguaje de programa de R, versión 3.5.1 (RCoreTeam, 2018).

Resultados

Como lo muestra el cuadro 2, se utilizaron 26 índices, dentro de los cuales solo 17 resultaron con valores significativos (resaltados en negrita en el cuadro). Los resultados del análisis de los datos significativos diarios de tres décadas realizado tanto para la estación 81003 (Limón) y la estación 73018 (Linda Vista, El Guarco) se muestran en los cuadros a continuación:

Todos los índices mencionados en el cuadro 3 y 4, demuestran que cumplen con valores significativos a la hora de realizar el análisis de regresión, con un p-value menor a 0.005 en todos los casos, lo que demuestra que hay diversos factores que afectan la linealidad de los datos, se nota claramente que existe una tendencia a la variabilidad climática, la mayoría de los índices muestran un comportamiento creciente con respecto al tiempo. Dicha información estadística se corrobora observando los gráficos de los principales índices para las estaciones de Limón y El Guarco.

En la figura 2 los índices de la estación 73018 (Linda Vista, El Guarco) se observa que la gráfica A muestra que durante las tres últimas décadas hubo un descenso en la precipitación alrededor de 16mm a 8 mm. En la gráfica B se muestra un aumento constante de la máxima precipitación que se está concentrando en caer en 5 días seguidos. En la gráfica C hubo un aumento de las precipitaciones mayores a 10 mm durante los últimos 30 año.En la gráfica C se mostró un aumento constante de las precipitaciones mayores a 20 mm durante los últimos 30 años.

"SDII"
lm(sdii~year,data=X73018_RClimDex_SDII_sustituido)->x
summary(x)->y
y
visreg(x,main="SDII (Precipitación Diaria)",xlab="Tiempo (Días)",ylab="Precipitación (mm)")
shapiro.test(x$residuals)

"RX5DAY"
lm(annual~year,data=X73018_RClimDex_RX5day_sustituido)->x
summary(x)->y
y
visreg(x,main="RX5day(Máxima 
       precipitación 5 días seguidos)",xlab="Tiempo (Años)",ylab="Precipitación (mm)")
shapiro.test(x$residuals)

"R10mm"
lm(R10~year,data=X73018_RClimDex_R10mm_sustituido)->x
summary(x)->y
y
visreg(x,main="R10mm (Precipitacion > 10mm)",xlab="Tiempo (Años)",ylab="Precipitación (mm)")
shapiro.test(x$residuals)

"R20mm"
lm(R20~year,data=X73018_RClimDex_R20mm_sustituido)->x
summary(x)->y
y
visreg(x,main="R20mm (Precipitación > 20mm)",xlab="Tiempo (Años)",ylab="Precipitación (mm)")
shapiro.test(x$residuals)

En la figura 3 la precipitación anual en días muy húmedos de la gráfica A aumentó de manera constante ya que se observa un cambio alrededor de 100mm a 500mm durante los últimos 30 años. En la gráfica B muestra que conforme pasan los años los días secos consecutivos van disminuyendo de manera constante. En la gráfica C los días húmedos consecutivos aumentaron de manera constante durante los últimos 30 años. En la gráfica D la precipitación anual total aumentó alrededor de 1000 mm a 2000 mm de manera constante en los días húmedos durante los últimos 30 años.

"R95P"
lm(r95p~year,data =X73018_RClimDex_R95p_sustituido)->x
summary(x)->y
y
visreg(x,main="R95P(Días muy húmedos)",xlab="Tiempo(años)",ylab="Precipitación anual(mm)")
shapiro.test(x$residuals)

"CDD"
lm(cdd~year,data=X73018_RClimDex_CDD_sustituidooo)->x
summary(x)->y
y
visreg(x,main="CDD(Días secos consecutivos)",xlab="Tiempo(años)",ylab="Días secos(días)")
shapiro.test(x$residuals)
influencePlot(x)
z<-X73018_RClimDex_CDD_sustituidooo[-c(1,3,4,31),]
lm(cdd~year,data = z)->z2
shapiro.test(z2$residuals)
summary(z2)
visreg(z2,main="Días secos consecutivos",xlab="Tiempo(años",ylab="Días secos(días)")



"CWD"
lm(cwd~year,data=X73018_RClimDex_CWD_sustituido)->x
summary(x)->y
y
visreg(x,main="CWD(Días húmedos consecutivos)",xlab="Tiempo(años)",ylab="Días húmedos(días)")
shapiro.test(x$residuals)


"PRCPTOT"
lm(prcptot~year,data =X73018_RClimDex_PRCPTOT_sustituir)->x
summary(x)->y
y
visreg(x,main="PCRPTOT(Precipitación total anual en los días húmedos)",xlab="Tiempo(años)",ylab="Precipitación(mm)")
shapiro.test(x$residuals)

En la figura 4 se muestran la cantidad de días fríos (Figura A) donde se puede observar una pendiente ascendente con respecto a las últimas décadas por lo que estos días aumentan cada vez más, de igual manera las noches caliente (Figura B) tienden a presentar una pendiente ascendente ya que pasó de tener solo una noche caliente en 1980 a 5 en 1992.

"TX10P(Días Fríos)"
lm(annual~year,data=X73018_RClimDex_TX10P_sustituido)->x
summary(x)->y
y
visreg(x)
plot(x)
shapiro.test(x$residuals)
influencePlot(x)
x2<-X73018_RClimDex_TX10P_sustituido[-c(12,27,28),]
lm(annual~year,data=x2)->x3
shapiro.test(x3$residuals)
summary(x3)
visreg(x3)

"TN90P (Noches Calientes)"
lm(annual~year,data=X73018_RClimDex_TN90P_sustituido)->x
summary(x)->y
y
visreg(x,main="TX10P (Noches Calientes)",xlab="Tiempo (Años)",ylab="Noches Calientes (Días)")
shapiro.test(x$residuals)

En la figura 5 la precipitación de la estación 81003 (Limón) muestra que la intensidad de diaria de la precipitación de la gráfica A aumenta hasta alrededor de 22 mm/día durante los últimos 30 años. En el caso de la gráfica B y C la precipitación máxima aumentó en 1 día y en 5 días respectivamente durante un periodo de 30 años. En la gráfica C se muestra un aumento de los días muy húmedos con respecto a los últimos 30 años.

"RX1day(Cantaidad máxima de precipitación en 1 día)"
datosP<-lm(annual~year, data = X81003_RClimDex_RX1day_1_ )
datosP
summary(datosP)
shapiro.test (datosP$residuals)
graf<-visreg(datosP,"year", partial=F, main= "RX1day(Cantaidad máxima de precipitación en 1 día)", xlab= "Tiempo(Años)", ylab="Precipitación(mm)")
graf

En la figura 6 los índices de precipitación para la estación 18003 (Limón) muestran en la gráfica A un aumento del número de días mayores a 43 mm con respecto a los últimos 30 años y en el caso de la gráfica B se observa que los días extremadamente tienen un incremento con respecto a los últimos 30 años.

"R43(Número de días>43mm)"
dat<-lm(Rnn~year, data = X81003_RClimDex_R43_515mm)
dat
summary(dat)
shapiro.test (dat$residuals)
graf<-visreg(dat,"year", partial=F, main= "R43(Número de días>43mm)", xlab= "Tiempo(Años)", ylab="Días>43mm(días)")
graf

 "R99p(Días extremadamente húmedos)"
datosl<-lm(r99p~year, data = X81003_RClimDex_R99p)
datosl
summary(datosl)
shapiro.test (datosl$residuals)
graf<-visreg(datosl,"year", partial=F, main= "R99p(Días extremadamente húmedos)", xlab= "Tiempo(Años)", ylab="Precipitación(mm)")
graf

En la figura 7 se muestra en la gráfica A que la temperatura diurna es menor bajando un grado, en la gráfica B sin embargo los días fríos han disminuido, y las noches calientes aumentado en la (Figura C). En la figura D se observa una disminución de los días calientes de 5 a 1.

"DTR(Temperatura Diurna)"
datos1<-lm(annual~year, data = X81003_RClimDex_DTR_usar)
datos1
summary(datos1)
shapiro.test (datos1$residuals)
graf<-visreg(datos1,"year", partial=F, main= "DTR(Temperatura Diurna)", xlab= "Tiempo(días)", ylab="Temperatura(°C)")
graf

"TN90P(Noches calientes)"
datos8<-lm(annual~year, data = X81003_RClimDex_TN90P)
datos8
summary(datos8)
shapiro.test (datos8$residuals)
graf<-visreg(datos8,"year", partial=F, main= "TN90P(Noches calientes)", xlab= "Tiempo(Años)", ylab="Tiempo(días)")
graf

"TX90P(Días calientes)"
datis<-lm(annual~year, data = X81003_RClimDex_TX90P)
datis
summary(datis)
shapiro.test (datis$residuals)
graf<-visreg(datis,"year", partial=F, main= "TX90P(Días calientes)", xlab= "Tiempo(Años)", ylab="Tiempo(días)")
graf

Finalmente en la figura 8 se observa que en la figura A hay una disminución en las temperaturas máximas, esto confirmado por la figura B donde cada vez son menos los días con temperaturas mayores a 32° pasando de 20 en 1980 a 10 en el 2010.

"SU32(Días de verano>32)"
datosA<-lm(su~year, data = X81003_RClimDex_SU32_4)
datosA
summary(datosA)
shapiro.test (datosA$residuals)
graf<-visreg(datosA,"year", partial=F, main= "SU32(Días de verano>32)", xlab= "Tiempo(Años)", ylab="Días>32mm(días)")
graf

Discusión

Para la temperatura en la estación de Linda Vista, El Guarco (73018) (Figura 4) podemos observar una tendencia en las temperaturas a disminuir, este aumento de temperaturas bajas en esta región del país puede ser causado por el aumento en la nubosidad que a su vez genera una prolongación en las temperaturas mínimas y una disminución de las temperaturas máximas (Gómez y Fernández 1996, Fernández y Ramírez 1991),las cuales según nuestros resultados coinciden con estas conclusiones. De igual manera la estación localizada en Limón presenta las mismas tendencias a aumentar las temperaturas mínimas (Figuras 7 y 8) por lo que podemos concluir que a partir de los datos recolectados de ambas estaciones que una gran parte de la vertiente del Caribe está presentando una tendencia hacia temperaturas más bajas, esto se debe a que las nubes influyen en la calidez del clima, de esta manera las nubes que se encuentran bajas provocan una disminución de la temperatura ya que son más densas y no permiten que los rayos del Sol penetren en su totalidad.(Marvel, 2017)

Un aumento en la nubosidad a causa de las precipitaciones genera un fenómeno que explica el comportamiento de las noches a calentarse cada vez más. La nubosidad al reflejar la radiación, tiene un doble efecto sobre el aumento o disminución de las temperaturas en la superficie terrestre. Por el día, una alta concentración de nubes reflejan la radiación solar que incide a la superficie produciendo una sensación de frescura, mientras que en la noche, la nubosidad se encarga de reflejar la radiación infrarroja emitida desde la superficie de la tierra, generando noches más calientes. A su vez, las propias nubes llegan a calentarse durante el proceso y emiten parte de esa radiación a la superficie. (Zúñiga y Crespo, 2010)

Posteriormente al analizar los datos obtenidos con respecto a la precipitación de la estación de Linda Vista, El Guarco (Figuras 2 y 3) podemos ver que las precipitaciones diarias tienden a disminuir, esto puede ser explicado ya que ahora las precipitaciones se concentran en un número de días menor (Figura 2B), por lo que aunque diariamente hay menos precipitaciones, esto se repone en una cantidad de días menor de lluvias. En la estación localizada en Limón se observan las mismos conclusiones (Figuras 5 y 6) con la excepción de que además las lluvias diarias también aumentan lo que significa que las precipitaciones en esta región han aumentado significativamente. Fernández y Ramírez (1991) explican que estas observaciones realizadas en el Caribe obedecen a comportamientos propios del fenómenos del ENOS el cual entre los meses de julio y agosto se observa una tendencia a mucha precipitación con una inclinación a ser cortas y violentas e incluso la aparición de temporales debido al aumento de los vientos alisios sobre esta región.

Se calculó, a partir de las regresiones obtenidas, cuánto cambiarían las variables tanto de temperatura máxima y mínima como de precipitación al cabo de 5 y 10 años (Cuadro 3). Se notó que aunque los cambios van a seguir la misma tendencia, estos a corto y mediano plazo no son una gran amenaza ya que son irrelevantes y no corresponden a un cambio brusco de las condiciones climáticas por lo que también se puede inferir que estas condiciones no van a generar un cambio climático como tal. Por otro lado si analizamos los cambios a largo plazo, podrían generar cierto riesgo al alterar de manera muy significativa el ambiente físico. Se puede observar evidencia de que existen cambios poco relevantes (Cuadro 4) ya que son solo diez años de diferencia pero cuando hablamos de 40 años o más, la variabilidad climática será más visibles.

Podemos concluir que existe variabilidad climática en la vertiente del caribe lo cual puede suponer una problemática a largo plazo tanto para el ecosistema como para las actividades humanas, especialmente para los sectores más vulnerables como lo son el sector agrícola y el ecoturismo (Amador y Alfaro, 2009). En el caso de la primera situaciones como las inundaciones causan además de la pérdida de zonas de cultivo, que el agua de mar sature el suelo y esta se filtre hacia los mantos acuíferos los cuales son utilizados para el riego de los cultivos, algo indispensable para la agricultura (Altieri y Nicholls, 2009). En el caso del ecoturismo Díaz (2012) menciona que la cantidad de ganancias en los entornos naturales con gran atracción turística pueden llegar a verse influenciados negativamente, llegando a tener pérdidas económicas hasta de un 30% si estos se empiezan a ver afectados por la variabilidad climática. Con esto es pertinente realizar mayores observaciones con respecto a las medidas necesarias para disminuir los impactos que estos fenómenos causan.

Referencias

Yáñez-Arancibia, A., Twilley, R. R., y Lara-Domínguez, A. L. (1998). Los ecosistemas de manglar frente al cambio climático global. Madera y Bosques, 4(2), 3-19.

Puertas Orozco, O. L., y Carvajal Escobar, Y. (2008). Incidence of El Niño southern oscillation in the precipitation and the temperature of the air in Colombia, using Climate Explorer. Ingeniería y Desarrollo, (23), 104-118.

Alzate, D., Rojas, E., Mosquera, J., y Ramón, J. (2015). Cambio climático y variabilidad climática para el periodo 1981-2010 en las cuencas de los ríos Zulia y pamplonita, norte de Santander–Colombia. Revista Luna Azul, (40).

Lizano, O y Salas, D. (2001). Variaciones geomorfológicas en los últimos 50 años en la isla Damas, Quepos, Costa Rica. Revista Biología Tropical. 49(2):171-177.

Retana, J y Villalobos, R. (2000). Caracterización pluviométrica de la fase cálida de ENOS en Costa Rica basado en probabilidades de ocurrencia de eventos en tres escenarios: seco, normal y lluvioso. Tópicos Meteorológicos y Oceanográficos. 7(2):124-130.

Amador, J.A. y A. “Ciclones tropicales y sociedad: Una aproximación al enfoque científico de estos fenómenos atmosféricos como referente para la investigación social en desastres”, en Concepciones y Representaciones de la Naturaleza y la Ciencia en América Latina, editado por R.Viales, J. Amador y F.J. Solano. San José: Editorial de la Universidad de Costa Rica, 2009, 159-179.

Fallas, J.C y R. Oviedo. “Temporales”. Cap. III. En: Fenómenos atmosféricos y cambio climático, visión centroamericana. Instituto Meteorológico Nacional, San José, Costa Rica, (2003): 38.

Fernández, W., y Ramírez, P. (1991). El Niño, la Oscilación del Sur y sus efectos en Costa Rica: una revisión. Tecnología en Marcha, 11(1), 3-10.

R Core Team (2018). R: A language and environment for statistical computing. R Foundation for Statistical Computing, Vienna, Austria. URL https://www.R-project.org/.

Waine, D. (1991). Bioestadística, base para el análisis de las ciencias de la salud. Mexico., México DF. LIMUSA. Recuperado de http://www.academia.edu/17988752/Bioestadistica_Base_para_el_analisis_de_las_ciencias_de_la_salud

Zhang, X., y Yang, F. (2004). RClimDex (1.0). Manual de Usuario. Canadá.

N/A. S/F. Universidad Nacional de Costa Rica. Recuperado de http://www.repositorio.una.ac.cr/bitstream/handle/11056/7520/estaciones_imn_2008.216.png?sequence=1&isAllowed=y

Altieri, M. A., & Nicholls, C. I. (2009). Cambio climático y agricultura campesina: impactos y respuestas adaptativas. LEISA revista de agroecología, 14, 5-8.

Gómez, I. E., y Fernández, W. (1996). Variación interanual de la temperatura en Costa Rica. Top. Meteor. Oceanogr, 3(1), 27-44.

Amador, J. A., y Alfaro, E. J. (2009). Métodos de reducción de escala: aplicaciones al tiempo, clima, variabilidad climática y cambio climático. Revibec: revista iberoamericana de economía ecológica, 11, 39-52.

Moreno-Díaz, M. L. (2012). Actividades socioeconómicas en el Parque Nacional Isla del Coco, Costa Rica y posibles efectos de la variabilidad climática. Revista de Biología Tropical, 60(3), 113-129.

Zúñiga, I., y Crespo, E. (2010) Meteorología y climatología. Recuperado de https://books.google.co.cr/books?id=E6iXJ2QZiQ4C&pg=PA63&dq=radiacion+infrarroja+nocturna+calor+en+las+noches+nubosidad&hl=es&sa=X&ved=0ahUKEwiGlub67a_eAhUkwlkKHb7OB-gQ6AEIKzAB#v=onepage&q=radiacion%20infrarroja%20nocturna%20calor%20en%20las%20noches%20nubosidad&f=false

Anexos

Anexo 1. Precipitación mensual estación 81003 (Limón)

Anexo2. Precipitación mensual estación 73018 (Linda Vista, El Guarco)

Anexo 3.Temperatura mensual estación 81003 (Limón)

Anexo 4.Instalación de paquetes requeridos para la organización de datos

install.packages("reshape")
install.packages("splitstackshape")
install.packages("plyr")
install.packages("ggplot2")
install.packages("xts")
install.packages("dygraphs")

Anexo 5.Organización de la base de datos

#####################################################################
## Script para organizar Información Climática INAMHI 2016
## Credits: Junior Pastor PÉREZ-MOLINA
## Date: 2017/10/08
#####################################################################
rm(list = ls()) #Remove all objects
graphics.off()  #Remove all graphics
cat("\014")     #Remove script in windows console
if(!grepl("Organización información climática", getwd())){x= cat(prompt = "Please set the working directory to the project folder ")}
#####################################################################


#####################################################################
## Cargar los paquetes requeridos para organizar Información Climática
#####################################################################
# install.packages("reshape")
library(reshape)
# install.packages("splitstackshape")
library(splitstackshape)
# install.packages("plyr")
library("plyr", lib.loc="~/R/win-library/3.4")
# install.packages("ggplot2")
library(ggplot2)
# install.packages("xts")
library(xts) 
# install.packages("dygraphs")
library(dygraphs)
#####################################################################


#####################################################################
## PRECIPITACION    ->   Loading database 
#####################################################################
Precipitacion<-read.delim("Data/PRCP.txt",header=FALSE,sep="\t",dec=".")
names(Precipitacion)<-c("codigo","year","mes","d1","d2","d3","d4","d5","d6","d7","d8","d9","d10","d11","d12","d13","d14","d15","d16","d17","d18","d19","d20","d21","d22","d23","d24","d25","d26","d27","d28","d29","d30","d31")
library(reshape)
Precipitacion <- melt(Precipitacion, id=c("codigo","year","mes"))
Precipitacion$value<-as.numeric(as.character(Precipitacion$value))
names(Precipitacion)<-c("codigo","year","month","day","PRCP")
Precipitacion<-data.frame(Precipitacion)
Precipitacion$day<-as.character(Precipitacion$day)
Precipitacion$day<-gsub("d", "", Precipitacion$day)
Precipitacion$day<-as.numeric(Precipitacion$day)
Precipitacion$date<-paste(Precipitacion$year,Precipitacion$month,Precipitacion$day, sep="-")
Precipitacion$date<-as.Date(Precipitacion$date, format = "%Y-%m-%d")
Precipitacion<-Precipitacion[order(Precipitacion$codigo,Precipitacion$year, Precipitacion$month, Precipitacion$day),]
Precipitacion$PRCP<-replace(Precipitacion$PRCP, is.na(Precipitacion$PRCP), -99.9)
Precipitacion$date2<-Precipitacion$date
Precipitacion$date2<-ifelse(is.na(Precipitacion$date2),1,0)
Precipitacion[Precipitacion$date2==1,]<-NA
Precipitacion<-Precipitacion[order(Precipitacion$codigo,Precipitacion$year, Precipitacion$month, Precipitacion$day),]
Precipitacion$date2<-NULL
Precipitacion<-na.omit(Precipitacion)
Precipitacion_ok<-data.frame()
for(i in unique(Precipitacion$codigo)){
    sub<-Precipitacion[Precipitacion$codigo==i,]
    date<-data.frame(seq(as.Date(paste(format(as.Date(min(na.omit(sub$date)), format="%Y/%m/%d"),"%Y"),"-01-01"),format = "%Y -%m-%d"),
                         as.Date(paste(format(as.Date(max(na.omit(sub$date)), format="%Y/%m/%d"),"%Y"),"-12-31"),format = "%Y -%m-%d"),
                         by="day"))
    names(date)<-c("date")
    date$date<-as.Date(date$date, format = "%Y-%m-%d")
    sub2<-merge(date,sub, all=TRUE)
    sub2$codigo<-c(i)
    Precipitacion_ok <- rbind(Precipitacion_ok,data.frame(sub2))
}
Precipitacion_ok$date2<-Precipitacion_ok$date
library(splitstackshape)
Precipitacion_ok<-cSplit(Precipitacion_ok, "date2", "-")
Precipitacion_ok<-data.frame(Precipitacion_ok[,2],Precipitacion_ok[,7],Precipitacion_ok[,8],Precipitacion_ok[,9],Precipitacion_ok[,6])
names(Precipitacion_ok)<-c("codigo","year","month","day","PCPT")
#####################################################################


#####################################################################
## Tmax             ->   Loading database 
#####################################################################
Tmax<-read.delim("Data/TMAX.txt",header=FALSE,sep="\t",dec=".")
names(Tmax)<-c("codigo","year","mes","d1","d2","d3","d4","d5","d6","d7","d8","d9","d10","d11","d12","d13","d14","d15","d16","d17","d18","d19","d20","d21","d22","d23","d24","d25","d26","d27","d28","d29","d30","d31")
library(reshape)
Tmax <- melt(Tmax, id=c("codigo","year","mes"))
Tmax$value<-as.numeric(as.character(Tmax$value))
names(Tmax)<-c("codigo","year","month","day","Tmax")
Tmax<-data.frame(Tmax)
Tmax$day<-as.character(Tmax$day)
Tmax$day<-gsub("d", "", Tmax$day)
Tmax$day<-as.numeric(Tmax$day)
Tmax$date<-paste(Tmax$year,Tmax$month,Tmax$day, sep="-")
Tmax$date<-as.Date(Tmax$date, format = "%Y-%m-%d")
Tmax<-Tmax[order(Tmax$codigo,Tmax$year, Tmax$month, Tmax$day),]
Tmax$Tmax<-replace(Tmax$Tmax, is.na(Tmax$Tmax), -99.9)
Tmax$date2<-Tmax$date
Tmax$date2<-ifelse(is.na(Tmax$date2),1,0)
Tmax[Tmax$date2==1,]<-NA
Tmax<-Tmax[order(Tmax$codigo,Tmax$year, Tmax$month, Tmax$day),]
Tmax$date2<-NULL
Tmax<-na.omit(Tmax)
Tmax_ok<-data.frame()
for(i in unique(Tmax$codigo)){
    sub<-Tmax[Tmax$codigo==i,]
    date<-data.frame(seq(as.Date(paste(format(as.Date(min(na.omit(sub$date)), format="%Y/%m/%d"),"%Y"),"-01-01"),format = "%Y -%m-%d"),
                         as.Date(paste(format(as.Date(max(na.omit(sub$date)), format="%Y/%m/%d"),"%Y"),"-12-31"),format = "%Y -%m-%d"),
                         by="day"))
    names(date)<-c("date")
    date$date<-as.Date(date$date, format = "%Y-%m-%d")
    sub2<-merge(date,sub, all=TRUE)
    sub2$codigo<-c(i)
    Tmax_ok <- rbind(Tmax_ok,data.frame(sub2))
}
Tmax_ok$date2<-Tmax_ok$date
library(splitstackshape)
Tmax_ok<-cSplit(Tmax_ok, "date2", "-")
Tmax_ok<-data.frame(Tmax_ok[,2],Tmax_ok[,7],Tmax_ok[,8],Tmax_ok[,9],Tmax_ok[,6])
names(Tmax_ok)<-c("codigo","year","month","day","Tmax")
#####################################################################


#####################################################################
## Tmin             ->   Loading database 
#####################################################################
Tmin<-read.delim("Data/TMIN.txt",header=FALSE,sep="\t",dec=".")
names(Tmin)<-c("codigo","year","mes","d1","d2","d3","d4","d5","d6","d7","d8","d9","d10","d11","d12","d13","d14","d15","d16","d17","d18","d19","d20","d21","d22","d23","d24","d25","d26","d27","d28","d29","d30","d31")
library(reshape)
Tmin <- melt(Tmin, id=c("codigo","year","mes"))
Tmin$value<-as.numeric(as.character(Tmin$value))
names(Tmin)<-c("codigo","year","month","day","Tmin")
Tmin<-data.frame(Tmin)
Tmin$day<-as.character(Tmin$day)
Tmin$day<-gsub("d", "", Tmin$day)
Tmin$day<-as.numeric(Tmin$day)
Tmin$date<-paste(Tmin$year,Tmin$month,Tmin$day, sep="-")
Tmin$date<-as.Date(Tmin$date, format = "%Y-%m-%d")
Tmin<-Tmin[order(Tmin$codigo,Tmin$year, Tmin$month, Tmin$day),]
Tmin$Tmin<-replace(Tmin$Tmin, is.na(Tmin$Tmin), -99.9)
Tmin$date2<-Tmin$date
Tmin$date2<-ifelse(is.na(Tmin$date2),1,0)
Tmin[Tmin$date2==1,]<-NA
Tmin<-Tmin[order(Tmin$codigo,Tmin$year, Tmin$month, Tmin$day),]
Tmin$date2<-NULL
Tmin<-na.omit(Tmin)
Tmin_ok<-data.frame()
for(i in unique(Tmin$codigo)){
    sub<-Tmin[Tmin$codigo==i,]
    date<-data.frame(seq(as.Date(paste(format(as.Date(min(na.omit(sub$date)), format="%Y/%m/%d"),"%Y"),"-01-01"),format = "%Y -%m-%d"),
                         as.Date(paste(format(as.Date(max(na.omit(sub$date)), format="%Y/%m/%d"),"%Y"),"-12-31"),format = "%Y -%m-%d"),
                         by="day"))
    names(date)<-c("date")
    date$date<-as.Date(date$date, format = "%Y-%m-%d")
    sub2<-merge(date,sub, all=TRUE)
    sub2$codigo<-c(i)
    Tmin_ok <- rbind(Tmin_ok,data.frame(sub2))
}
Tmin_ok$date2<-Tmin_ok$date
library(splitstackshape)
Tmin_ok<-cSplit(Tmin_ok, "date2", "-")
Tmin_ok<-data.frame(Tmin_ok[,2],Tmin_ok[,7],Tmin_ok[,8],Tmin_ok[,9],Tmin_ok[,6])
names(Tmin_ok)<-c("codigo","year","month","day","Tmin")
#####################################################################



#####################################################################
## PCPT_Tmax_Tmin   ->   Loading database 
#####################################################################
PCPT_Tmax<-merge(Precipitacion,  Tmax, by=c("date","codigo", "year", "month", "day"), all=TRUE)
PCPT_Tmax_Tmin<-merge(PCPT_Tmax, Tmin, by=c("date","codigo", "year", "month", "day"), all=TRUE)
PCPT_Tmax_Tmin_ok<-data.frame()
for(i in unique(PCPT_Tmax_Tmin$codigo)){
    sub<-PCPT_Tmax_Tmin[PCPT_Tmax_Tmin$codigo==i,]
    date<-data.frame(seq(as.Date(paste(format(as.Date(min(na.omit(sub$date)), format="%Y/%m/%d"),"%Y"),"-01-01"),format = "%Y -%m-%d"),
                         as.Date(paste(format(as.Date(max(na.omit(sub$date)), format="%Y/%m/%d"),"%Y"),"-12-31"),format = "%Y -%m-%d"),
                         by="day"))
    names(date)<-c("date")
    date$date<-as.Date(date$date, format = "%Y-%m-%d")
    sub2<-merge(date,sub, all=TRUE)
    sub2$codigo<-c(i)
    PCPT_Tmax_Tmin_ok <- rbind(PCPT_Tmax_Tmin_ok,data.frame(sub2))
}
PCPT_Tmax_Tmin_ok$date2<-PCPT_Tmax_Tmin_ok$date
library(splitstackshape)
PCPT_Tmax_Tmin_ok<-cSplit(PCPT_Tmax_Tmin_ok, "date2", "-")
PCPT_Tmax_Tmin_ok<-data.frame(PCPT_Tmax_Tmin_ok[,2],PCPT_Tmax_Tmin_ok[,9],PCPT_Tmax_Tmin_ok[,10],PCPT_Tmax_Tmin_ok[,11],PCPT_Tmax_Tmin_ok[,6],PCPT_Tmax_Tmin_ok[,7],PCPT_Tmax_Tmin_ok[,8])
names(PCPT_Tmax_Tmin_ok)<-c("codigo","year","month","day","PCPT","Tmax","Tmin")
#####################################################################


#####################################################################
## Save database for RClimDex
#####################################################################
pb <- winProgressBar(title="Hola, :-) .. espera solo un poco estoy creado los RClimDex txt ... ", label="0% done", min=0, max=100, initial=0, width = 900)
for(i in unique(PCPT_Tmax_Tmin_ok$codigo)){
    sub<-PCPT_Tmax_Tmin_ok[PCPT_Tmax_Tmin_ok$codigo==i,]
    sub<-data.frame(sub)
    sub$PCPT<-replace(sub$PCPT, is.na(sub$PCPT), -99.9)
    sub$Tmax<-replace(sub$Tmax, is.na(sub$Tmax), -99.9)
    sub$Tmin<-replace(sub$Tmin, is.na(sub$Tmin), -99.9)
    write.table(sub[,c(-1)],paste("Results/Estaciones/",i,"_RClimDex.txt"),sep="\t",dec=".", col.names = F, row.names = F)
    for (ii in 1:100){
        Sys.sleep(0.0005) # slow down the code for illustration purposes
        info <- sprintf("%d%% done", round((ii/100)*100))
        setWinProgressBar(pb, ii/(100)*100, label=info)
    }
}
close(pb)
#####################################################################


#####################################################################
## Database... PCPT_Tmax_Tmin_ok
#####################################################################
PCPT_Tmax_Tmin_ok$PCPT<-replace(PCPT_Tmax_Tmin_ok$PCPT, PCPT_Tmax_Tmin_ok$PCPT==-99.9, NA)
PCPT_Tmax_Tmin_ok$Tmax<-replace(PCPT_Tmax_Tmin_ok$Tmax, PCPT_Tmax_Tmin_ok$Tmax==-99.9, NA)
PCPT_Tmax_Tmin_ok$Tmin<-replace(PCPT_Tmax_Tmin_ok$Tmin, PCPT_Tmax_Tmin_ok$Tmin==-99.9, NA)
PCPT_Tmax_Tmin_ok$date<-as.Date(paste(PCPT_Tmax_Tmin_ok$year, PCPT_Tmax_Tmin_ok$month, PCPT_Tmax_Tmin_ok$day, sep="-"))
PCPT_Tmax_Tmin_ok$year_month<-paste(PCPT_Tmax_Tmin_ok$year, PCPT_Tmax_Tmin_ok$month, "1", sep="-")
library("plyr", lib.loc="~/R/win-library/3.4")
##########################
#---- (50% completa Temperatura mensual) ----#
#---- (80% completa Precipitación mensual) ----#
##########################
COMPLETA<-15      # (15/30)*100= 50% INFORMACIÓN COMPLETA TEMPERATURA MENSUAL
COMPLETA_PCPT<-24 # (24/30)*100= 80% INFORMACIÓN COMPLETA PRECIPITACIÓN MENSUAL
library(plyr)
str(PCPT_Tmax_Tmin_ok)
PCPT_Tmax_Tmin_ok$PCPT<-as.numeric(PCPT_Tmax_Tmin_ok$PCPT)
PCPT_Tmax_Tmin_ok$Tmax<-as.numeric(PCPT_Tmax_Tmin_ok$Tmax)
PCPT_Tmax_Tmin_ok$Tmin<-as.numeric(PCPT_Tmax_Tmin_ok$Tmin)

PCPT_Tmax_Tmin_sum<-ddply(PCPT_Tmax_Tmin_ok, c("codigo","year_month"), summarise, 
                PCPT_sum  = ifelse(length(na.omit(PCPT))>COMPLETA_PCPT, sum(na.omit(PCPT)),""),
                Tmax_max  = ifelse(length(na.omit(Tmax))>COMPLETA, max(na.omit(Tmax)),""),
                Tmax_mean = ifelse(length(na.omit(Tmax))>COMPLETA, mean(na.omit(Tmax)),""),
                Tmax_min = ifelse(length(na.omit(Tmax))>COMPLETA, min(na.omit(Tmax)),""),
                Tmin_max = ifelse(length(na.omit(Tmin))>COMPLETA, max(na.omit(Tmin)),""),
                Tmin_mean = ifelse(length(na.omit(Tmin))>COMPLETA, mean(na.omit(Tmin)),""),
                Tmin_min  = ifelse(length(na.omit(Tmin))>COMPLETA, min(na.omit(Tmin)),""))
PCPT_Tmax_Tmin_sum$year_month<-as.Date(PCPT_Tmax_Tmin_sum$year_month, format = "%Y-%m-%d")
##########################
#---- (80% completa Precipitación anual) ----#
##########################
COMPLETA<-292 #(292/365)*100= 80% INFORMACIÓN COMPLETA PRECIPITACION ANUAL
PCPT_anual<-ddply(PCPT_Tmax_Tmin_ok, c("codigo","year"), summarise, 
                  PCPT_sum= ifelse(length(na.omit(PCPT))>COMPLETA, sum(na.omit(PCPT)),""))
PCPT_anual$year<-as.numeric(PCPT_anual$year)
write.table(PCPT_Tmax_Tmin_sum,"Results/PCPT_Tmax_Tmin_sum.txt",sep="\t",dec=".", col.names = T, row.names = F)
write.table(PCPT_anual,"Results/PCPT_anual.txt",sep="\t",dec=".", col.names = T, row.names = F)
#####################################################################

Anexo 6.Creación de gráficos de precipitación y temperatura mensual

## Smart graphics 
#####################################################################
####################################
Nombre_estacion<-"81003"   #########PCPT_anual PCPT_Tmax_Tmin_sum
####################################
PCPT_anual<-read.delim("Results/PCPT_anual.txt",header=TRUE,sep="\t",dec=".")
PCPT_anual$year<-as.numeric(PCPT_anual$year)
PCPT_anual$year<-as.Date(paste(PCPT_anual$year,"-01-01"), format = "%Y -%m-%d")
PCPT_Tmax_Tmin_sum<-read.delim("Results/PCPT_Tmax_Tmin_sum.txt",header=TRUE,sep="\t",dec=".")
PCPT_Tmax_Tmin_sum$year_month<-as.Date(PCPT_Tmax_Tmin_sum$year_month, format = "%Y-%m-%d")
#####################################################################
library(ggplot2)
library(xts) 
library(dygraphs)
# Function 
presAnnotation <- function(dygraph, x, text) {
    dygraph %>%
        dyAnnotation(x, text, attachAtBottom = TRUE, width = 40)
}
#####################################################################
## Temperatura escala mensual   ---- (50% completa) ----
#####################################################################
sub1<-PCPT_Tmax_Tmin_sum[PCPT_Tmax_Tmin_sum$codigo==Nombre_estacion,]
Tmax_max<- xts(sub1$Tmax_max,order.by=(sub1$year_month),tz="GMT")
Tmax_mean<- xts(sub1$Tmax_mean,order.by=(sub1$year_month),tz="GMT")
Tmax_min<- xts(sub1$Tmax_min,order.by=(sub1$year_month),tz="GMT")
Tmin_max<- xts(sub1$Tmin_max,order.by=(sub1$year_month),tz="GMT")
Tmin_mean<- xts(sub1$Tmin_mean,order.by=(sub1$year_month),tz="GMT")
Tmin_min<- xts(sub1$Tmin_min,order.by=(sub1$year_month),tz="GMT")
stocks1 <- cbind(Tmax_max,Tmax_mean,Tmax_min,Tmin_max,Tmin_mean,Tmin_min)
dygraph(stocks1,ylab=("Temperature (°C)"), main=paste("Estación: ", Nombre_estacion)) %>%
    dySeries("..1",label="Temp. max maximum (°C)", drawPoints = TRUE, pointSize = 3) %>%
    dySeries("..2",label="Temp. max promedio (°C)", drawPoints = TRUE, pointSize = 3) %>%
    dySeries("..3",label="Temp. max minimum (°C)", drawPoints = TRUE, pointSize = 3) %>%
    dySeries("..4",label="Temp. min maximum (°C)", drawPoints = TRUE, pointSize = 3) %>%
    dySeries("..5",label="Temp. min promedio (°C)", drawPoints = TRUE, pointSize = 3) %>%
    dySeries("..6",label="Temp. min minimum (°C)", drawPoints = TRUE, pointSize = 3) %>%
    dyOptions(colors = c("darkred","red","darksalmon","skyblue","orange","yellow")) %>%
    dyHighlight(highlightSeriesOpts = list(strokeWidth = 1))%>%
    dyLegend(width = 400)%>%
    dyRangeSelector()
#####################################################################
## Precipitación total mensual  ---- (80% completa) ----
#####################################################################
PCPT<- xts(sub1$PCPT_sum,order.by=(sub1$year_month),tz="GMT")
stocks1 <- cbind(PCPT)
dygraph(stocks1,ylab=("Precipitación total mensual (mm)"),main=paste("Estación: ", Nombre_estacion)) %>%
    dySeries(label="Precipitación total mensual (mm)", stepPlot = TRUE, fillGraph = TRUE, color = "blue") %>%
    dyOptions(colors = c("blue"), fillGraph = TRUE, fillAlpha = 0.4) %>%
    dyHighlight(highlightSeriesOpts = list(strokeWidth = 1))%>%
    dyLegend(width = 400)%>%
    dyRangeSelector()
#####################################################################
## Precipitación total anual    ---- (80% completa) ----
#####################################################################
sub2<-PCPT_anual[PCPT_anual$codigo==Nombre_estacion,]
PCPT<- xts(sub2$PCPT_sum,order.by=(sub2$year),tz="GMT")
stocks1 <- cbind(PCPT)
dygraph(stocks1,ylab=("Precipitación total anual (mm)"), main=paste("Estación: ", Nombre_estacion)) %>%
    dySeries(label="Precipitación total anual (mm)", stepPlot = TRUE, fillGraph = TRUE, color = "blue") %>%
    dyOptions(colors = c("blue"), fillGraph = TRUE, fillAlpha = 0.4) %>%
    dyHighlight(highlightSeriesOpts = list(strokeWidth = 1))%>%
    dyLegend(width = 400)%>%
    dyRangeSelector()
#####################################################################


#####################################################################
## Graphics PDF
#####################################################################
pdf(file="Results/Fig. Temperatura mensual.pdf", width = 10, height = 6)
par(mfrow=c(1,1),mgp = c(1.5,0.5,0), mar = c(3,3,4,1.5))
for (i in unique(PCPT_Tmax_Tmin_sum$codigo)){
    sub<-PCPT_Tmax_Tmin_sum[PCPT_Tmax_Tmin_sum$codigo==i,]
    sub<-sub[order(sub$codigo,sub$year_month),]
    sub$Tmax_max[!is.finite(sub$Tmax_max)]  <- NA
    sub$Tmax_mean[!is.finite(sub$Tmax_mean)] <- NA
    sub$Tmax_min[!is.finite(sub$Tmax_min)]  <- NA
    sub$Tmin_max[!is.finite(sub$Tmin_max)]  <- NA
    sub$Tmin_mean[!is.finite(sub$Tmin_mean)] <- NA
    sub$Tmin_min[!is.finite(sub$Tmin_min)]  <- NA
    par(xpd=FALSE)
    plot(sub$year_month, sub$Tmax_max, type = "b", pch=19, col="darkred", ylim=c(ifelse(min(na.omit(sub$Tmin_min))=="Inf",-1,min(na.omit(sub$Tmin_min))), ifelse(max(na.omit(sub$Tmax_max))=="-Inf",-1,max(na.omit(sub$Tmax_max)))), 
         main=paste("Estacion= ", i), ylab="Temperatura mensual (°C)", xlab="")
    points(sub$year_month, sub$Tmax_mean, type = "b", pch=19, col="red")
    points(sub$year_month, sub$Tmax_min, type = "b", pch=19, col="darksalmon")
    points(sub$year_month, sub$Tmin_max, type = "b", pch=19, col="skyblue")
    points(sub$year_month, sub$Tmin_mean, type = "b", pch=19, col="orange")
    points(sub$year_month, sub$Tmin_min, type = "b", pch=19, col="yellow")
    par(xpd=TRUE)
    legend("top", inset = c(0, -0.08), "", c("Tmax_max","Tmax_mean","Tmax_min","Tmin_max","Tmin_mean","Tmin_min"), pch=c(19),col=c("darkred","red","darksalmon","skyblue","orange","yellow"),h=TRUE, text.col = c("darkred","red","darksalmon","skyblue","orange","yellow"),merge = F, bg = NULL,bty='n')
}
dev.off()
#####################################################################
pdf(file="Results/Fig. Precipitacion total mensual.pdf", width = 10, height = 6)
par(mfrow=c(1,1),mgp = c(1.5,0.5,0), mar = c(3,3,4,1.5))
for (i in unique(PCPT_Tmax_Tmin_sum$codigo)){
    sub<-PCPT_Tmax_Tmin_sum[PCPT_Tmax_Tmin_sum$codigo==i,]
    sub<-sub[order(sub$codigo,sub$year_month),]
    sub$PCPT_sum[!is.finite(sub$PCPT_sum)]  <- NA
    sub$Tmax_max[!is.finite(sub$Tmax_max)]  <- NA
    sub$Tmax_mean[!is.finite(sub$Tmax_mean)] <- NA
    sub$Tmax_min[!is.finite(sub$Tmax_min)]  <- NA
    sub$Tmin_max[!is.finite(sub$Tmin_max)]  <- NA
    sub$Tmin_mean[!is.finite(sub$Tmin_mean)] <- NA
    sub$Tmin_min[!is.finite(sub$Tmin_min)]  <- NA
    par(xpd=FALSE)
    plot(sub$year_month, sub$PCPT_sum, type = "h", pch=19, col="blue", ylim=c(ifelse(min(na.omit(sub$PCPT_sum))=="Inf",0,0), ifelse(max(na.omit(sub$PCPT_sum))=="-Inf",0,max(na.omit(sub$PCPT_sum)))), 
         main=paste("Estacion= ", i), ylab="Precipitacion total mensual (mm)", xlab="", lwd=3)
    points(sub$year_month, sub$PCPT_sum, type="l", col="red", lty=3,lwd=1)
    abline(h=0, col="black", lty=1, lwd=2)
    par(xpd=TRUE)
    legend("top", inset = c(0, -0.08), "", c("Precipitación total mensual"),lty=1, lwd=3,col=c("blue"),h=TRUE, text.col = c("blue"),merge = F, bg = NULL,bty='n')
}
dev.off()
#####################################################################
pdf(file="Results/Fig. Precipitacion total anual.pdf", width = 10, height = 6)
par(mfrow=c(1,1),mgp = c(1.5,0.5,0), mar = c(3,3,4,1.5))
for (i in unique(PCPT_anual$codigo)){
    sub<-PCPT_anual[PCPT_anual$codigo==i,]
    sub<-sub[order(sub$codigo,sub$year),]
    sub$PCPT_sum[!is.finite(sub$PCPT_sum)]  <- NA
    par(xpd=FALSE)
    plot(sub$year, sub$PCPT_sum, type = "h", pch=19, col="blue", ylim=c(ifelse(min(na.omit(sub$PCPT_sum))=="Inf",0,0), ifelse(max(na.omit(sub$PCPT_sum))=="-Inf",0,max(na.omit(sub$PCPT_sum)))), 
         main=paste("Estacion= ", i), ylab="Precipitacion total anual (mm)", xlab="", lwd=3)
    points(sub$year, sub$PCPT_sum, type="l", col="red", lty=3,lwd=1)
    abline(h=0, col="black", lty=1, lwd=2)
    par(xpd=TRUE)
    legend("top", inset = c(0, -0.08), "", c("Precipitación total mensual"),lty=1, lwd=3,col=c("blue"),h=TRUE, text.col = c("blue"),merge = F, bg = NULL,bty='n')
}
dev.off()
#####################################################################


#####################################################################
## Save database summary (monthly and year) for each station
#####################################################################
pb <- winProgressBar(title="Hola de nuevo, :-) .. espera solo un poco estoy creado database para cada estación meteorológica en formato.txt ... ", label="0% done", min=0, max=100, initial=0, width = 900)
for(i in unique(PCPT_Tmax_Tmin_sum$codigo)){
    sub<-PCPT_Tmax_Tmin_sum[PCPT_Tmax_Tmin_sum$codigo==i,]
    sub<-sub[order(sub$codigo,sub$year_month),]
    sub$Tmax_max[!is.finite(sub$Tmax_max)]  <- NA
    sub$Tmax_mean[!is.finite(sub$Tmax_mean)] <- NA
    sub$Tmax_min[!is.finite(sub$Tmax_min)]  <- NA
    sub$Tmin_max[!is.finite(sub$Tmin_max)]  <- NA
    sub$Tmin_mean[!is.finite(sub$Tmin_mean)] <- NA
    sub$Tmin_min[!is.finite(sub$Tmin_min)]  <- NA
    write.table(sub,paste("Results/Estaciones datos resumidos/",i,"_database_mensual.txt"),sep="\t",dec=".", col.names = T, row.names = F)
    for (ii in 1:100){
        Sys.sleep(0.0005) # slow down the code for illustration purposes
        info <- sprintf("%d%% done", round((ii/100)*100))
        setWinProgressBar(pb, ii/(100)*100, label=info)
    }
}
close(pb)
#####################################################################
pb <- winProgressBar(title="Hola de nuevo, Soy yo otra vez :-) .. espera solo un poco estoy creado database para cada estación meteorológica en formato.txt ... ", label="0% done", min=0, max=100, initial=0, width = 900)
for(i in unique(PCPT_anual$codigo)){
    sub<-PCPT_anual[PCPT_anual$codigo==i,]
    sub<-sub[order(sub$codigo,sub$year),]
    sub$PCPT_sum[!is.finite(sub$PCPT_sum)]  <- NA
    write.table(sub,paste("Results/Estaciones datos resumidos/",i,"_database_anual.txt"),sep="\t",dec=".", col.names = T, row.names = F)
    for (ii in 1:100){
        Sys.sleep(0.0005) # slow down the code for illustration purposes
        info <- sprintf("%d%% done", round((ii/100)*100))
        setWinProgressBar(pb, ii/(100)*100, label=info)
    }
}
close(pb)

Anexo 7.Instalación de paquetes requeridos por RClimdex

install.packages("cluster")
install.packages("tcltk") 
install.packages("Rcmdr")

Anexo 8.Código para generar el software RClimdex

##################################################################################
#"Script RClimdex" 
# Rewritten: Junior Pastor PÉREZ-MOLINA
# Small modifications to adapt the analysis of climate variability in the tropics
# Date modified: "Tuesday May 31st, 2016" 
##################################################################################
rm(list = ls()) #Remove all objects
graphics.off()  #Remove all graphics
cat("\014")     #Remove script in windows console
##################################################################################


##################################################################################
# Credicts:
# Climate Indecies Calculation software
# R language with TCL/TK package
# Programmed by Yujun Ouyang,Mar,2004
# rewritten by Yang Feng, July 2004
##################################################################################
# version 1.0, 2004-10-14
# modified, 2006-01-24, 
# change .Internal(cbind) to cbind
# change .Internal(rbind) to rbind
# modified 2007-03-23
# change .Internal(rep(0,n)) to rep(0,n)
# modified, 2007-11-26,
# get rid of .Internal on some functions: min(...), sort(...), round(...)
#            max(...), also get rid of dig=.. part from sort(...) function
#            change decrease=... part to decreasing=... at sort(...)
# modified, 2008-05-05,
# output TMAX mean value and TMIN mean value in nastat() function
# modified, 2008-05-06,
# add a random series on TMAX and TMIN in exceedance rate function
# modified thresholds in TN10p calculation, add an 1e-5 item to avoid 
# computational error like 3.60000 > 3.6000, two functions involved:
# nordaytem1() and exceedance()
# modified, 2008-06-16
# change all sort() to mysort(), deal with different version, also combined
# different levels threshold()
##################################################################################


##################################################################################
# Part I
# General functions & TCL/TK functions
##################################################################################
library(cluster)
require(tcltk)
mysort<- if(getRversion()<='2.4.1') function(x,decreasing){.Internal(sort(x,decreasing=decreasing))} else function(x,decreasing){sort.int(x,decreasing=decreasing)}
fontHeading <- tkfont.create(family="times",size=40,weight="bold",slant="italic")
fontHeading1<-tkfont.create(family="times",size=20,weight="bold")
fontHeading2<-tkfont.create(family="times",size=14,weight="bold")
fontTextLabel <- tkfont.create(family="times",size=12)
fontFixedWidth <- tkfont.create(family="courier",size=12)
# initial value for check box
cbvalue1<-tclVar("1");  cbvalue2<-tclVar("1");  cbvalue3<-tclVar("1")
cbvalue4<-tclVar("1");  cbvalue5<-tclVar("1");  cbvalue6<-tclVar("1")
cbvalue7<-tclVar("1");  cbvalue8<-tclVar("1");  cbvalue9<-tclVar("1")
cbvalue10<-tclVar("1"); cbvalue11<-tclVar("1"); cbvalue12<-tclVar("1")
cbvalue13<-tclVar("1"); cbvalue14<-tclVar("1"); cbvalue15<-tclVar("1")
cbvalue16<-tclVar("0"); cbvalue17<-tclVar("0"); cbvalue18<-tclVar("0")
cbvalue19<-tclVar("0"); cbvalue21<-tclVar("1")
#  initial value for parameters
stations<-tclVar(paste(""));   stdt<-tclVar(paste("3"))
Entry1<-tclVar(paste("1961")); Entry2<-tclVar(paste("1990"))
#Entry3<-tclVar(paste("5"))
Entry4<-tclVar(paste("0"))
Entry5<-tclVar(paste("0"))
Entry6<-tclVar(paste("25"));   Entry7<-tclVar(paste("0"))
Entry8<-tclVar(paste("20"));   Entry9<-tclVar(paste("0"))
#Entry10<-tclVar(paste("10")); Entry11<-tclVar(paste("5"))
Entry12<-tclVar(paste("25"))
dayim<-as.integer(c(31,28,31,30,31,30,31,31,30,31,30,31))
crt<-3;      flag=F
treshold=5;  winsize=5
uu<-25;      lu<-20
ul<-0;       ll<-0
title1<-"Plot of Ind143";   title2<-"Ind143";   title3<-"Years"

#----------- frc -----------------------------------------
frc<-function(dd,year,month,item){
    
    a<-dd[dd$year==year & dd$month==month,item]
    a<-a[a>-99]
    frc<-length(a)/rdim(year,month)
}#end
#----------- frc ends -----------------------------------------

#----------- done -----------------------------------------
done<-function(){tkdestroy(start1)}
#----------- done ends -----------------------------------------

#----------- percentile -----------------------------------------
percentile<-function(n,x,pctile){
    x1<-x[is.na(x)==F]
    n1<-length(x1)
    a<-mysort(x1,decreasing=F)
    b<-n1*pctile+0.3333*pctile+0.3333
    bb<-trunc(b)
    percentile<-a[bb]+(b-bb)*(a[bb+1]-a[bb]) 
}#end
#----------- percentile ends -----------------------------------------

#----------- pplotts -----------------------------------------
pplotts<-function(var="prcp",type="h",tit=NULL){
    if(var=="dtr"){
        ymax<-max(dd[,"tmax"]-dd[,"tmin"],na.rm=T)
        ymin<-0
    }
    else if(var=="prcp"){
        ymax<-max(dd[,var],na.rm=T)
        ymin<-0
    }
    else{
        ymax<-max(dd[,var],na.rm=T)+1
        ymin<-min(dd[,var],na.rm=T)-1
    }
    if(is.na(ymax)|is.na(ymin)|(ymax==-Inf)|(ymin==-Inf)){
        ymax<-100
        ymin<-(-100)
    }
    par(mfrow=c(4,1))
    par(mar=c(3.1,2.1,2.1,2.1))
    for(i in seq(years,yeare,10)){
        at<-rep(1,10)
        #   if(i>yeare)
        for(j in (i+1):min(i+9,yeare+1)){
            if(leapyear(j)) at[j-i+1]<-at[j-i]+366
            else at[j-i+1]<-at[j-i]+365
        }
        if(var=="dtr")
            ttmp<-dd[dd$year>=i&dd$year<=min(i+9,yeare),"tmax"]-dd[dd$year>=i&dd$year<=min(i+9,yeare),"tmin"]
        else ttmp<-dd[dd$year>=i&dd$year<=min(i+9,yeare),var]
        plot(1:length(ttmp),ttmp,type=type,col="blue",xlab="",ylab="",xaxt="n",xlim=c(1,3660),ylim=c(ymin,ymax))
        abline(h=0)
        tt<-seq(1,length(ttmp))
        tt<-tt[is.na(ttmp)==T]
        axis(side=1,at=at,labels=c(i:(i+9)))
        for(k in 1:10) abline(v=at[k],col="yellow")
        lines(tt,rep(0,length(tt)),type="p",col="red")
        title(paste("Station: ",tit,", ",i,"~",min(i+9,yeare),",  ",var,sep=""))
    }
}
#----------- pplotts ends -----------------------------------------

#----------- ind143gsl -----------------------------------------
ind143gsl<-function(){
    if (latitude<0) south=T else south=F
    if (latitude<0) eyear=yeare-1 else eyear=yeare
    threshold<-5
    a<-eyear-years+1
    b<-rep(0,a)
    b<-cbind(b,b)
    colnames(b)<-c("year","gsl")
    i=1
    for (year in years:eyear) {
        b[i,"year"]<-year
        if(south){
            gslstart<-dd[dd$year==year&dd$month>6,]
            gslstart<-(gslstart[,"tmax"]+gslstart[,"tmin"])/2
            gslend<-dd[dd$year==(year+1)&dd$month<7,]
            gslend<-(gslend[,"tmax"]+gslend[,"tmin"])/2
        }
        else{
            gslstart<-dd[dd$year==year&dd$month<7,]
            gslstart<-(gslstart[,"tmax"]+gslstart[,"tmin"])/2
            gslend<-dd[dd$year==year&dd$month>6,]
            gslend<-(gslend[,"tmax"]+gslend[,"tmin"])/2
        }
        beginday<-0
        count=0
        for(step in 1:length(gslstart)){
            if(is.na(gslstart[step])==F){
                if(gslstart[step]>threshold) count<-count+1
                else count<-0
            }
            else count<-0
            if(count>5){
                beginday<-step-5
                break
            }
        }
        
        #    if(beginday==0){
        #      b[i,"gsl"]<-0
        #      break
        #    }
        
        endday<-0
        count<-0
        for(step in 1:length(gslend)){
            if(is.na(gslend[step])==F){
                if(gslend[step]<threshold) count<-count+1
                else count<-0
            }
            else count<-0
            if(count>5){
                endday<-step-5
                break
            }
        }
        
        if(sum(is.na(gslstart))+sum(is.na(gslend))>15)  b[i,"gsl"]<-NA
        else{
            if(beginday==0)
                b[i,"gsl"]<-0
            else {
                if(endday==0)  b[i,"gsl"]<-length(gslend)+length(gslstart)-beginday
                else b[i,"gsl"]<-endday+length(gslstart)-beginday
            }
        }
        
        i=i+1
    } 
    b<-as.data.frame(b)
    nam1<-paste(outinddir,paste(ofilename,"_GSL.csv",sep=""),sep="/")
    write.table(b,file=nam1,append=F,quote=F,sep=", ",na="-99.9",row.names=F)
    
    namt<-paste(outtrddir,paste(ofilename,"_trend.csv",sep=""),sep="/")
    if(sum(is.na(b[,"gsl"]))>=(yeare-years+1-10)){
        betahat<-NA
        betastd<-NA
        pvalue<-NA
    }
    else{
        fit1<-lsfit(b[,1],b[,"gsl"])
        out1<-ls.print(fit1,print.it=F)
        pvalue<-round(as.numeric(out1$summary[1,6]),3)
        betahat<-round(as.numeric(out1$coef.table[[1]][2,1]),3)
        betastd<-round(as.numeric(out1$coef.table[[1]][2,2]),3)
    }
    cat(file=namt,paste(latitude,longitude,"gsl",years,yeare,betahat,betastd,pvalue,sep=","),fill=180,append=T)
    
    nam2<-paste(outjpgdir,paste(ofilename,"_GSL.jpg",sep=""),sep="/")
    jpeg(file=nam2,width=1024,height=768)
    plotx(b[,1],b[,"gsl"],main=paste("GSL",ofilename,sep="   "),xlab="Year",ylab="GSL")
    dev.off()
}
#----------- ind143gsl ends -----------------------------------------

#----------- dataext -----------------------------------------
# seems this function is never used...
dataext<-function(dd,year,month,day,item){
    Dataext<-dd[dd$year==year & dd$month==month & dd$day==day,item]
}
#----------- dataext ends -----------------------------------------

# ----------- leapyear -----------------------------------------
# check if 'year' is a leap year
# returns T or F
leapyear<-function(year){
    remainder400 <-trunc(year-400*trunc(year/400))
    remainder100 <-trunc(year-100*trunc(year/100))
    remainder4 <-trunc(year-4*trunc(year/4))
    if (remainder400 == 0) leapyear = T
    else{
        if(remainder100 == 0) leapyear = F
        else{
            if(remainder4 == 0) leapyear = T
            else leapyear = F
        }
    }
}
# ----------- leapyear ends -----------------------------------------

# ----------- rdim -----------------------------------------
# day # in a month
#
rdim<-function(year,month) {
    a<-leapyear(year) 
    if (month==1) rdim<-31
    else if (month==3) rdim<-31
    else if (month==4) rdim<-30
    else if (month==5) rdim<-31
    else if (month==6) rdim<-30
    else if (month==7) rdim<-31
    else if (month==8) rdim<-31
    else if (month==9) rdim<-30
    else if (month==10) rdim<-31
    else if (month==11) rdim<-30
    else if (month==12) rdim<-31
    else if (a==T & month==2) rdim<-29
    else rdim<-28  
}
# ----------- rdim ends -----------------------------------------

# ----------- qcontrol -----------------------------------------
qcontrol<-function(){
    tkmessageBox(message=paste("Data QC(",ofilename,") may take a few minutes, click OK to continue.",sep=""))
    # output records of problematic like prcp <0 and NA
    ddu<-duplicated(dd[,c("year","month","day")])
    if(sum(ddu)>0){
        nam1<-paste(outlogdir,paste(ofilename,"dupliQC.csv",sep=""),sep="/")
        msg=paste("Date duplicated found in original data file, please check:",nam1,sep=" ")
        tkmessageBox(message=msg)
        ddu2<-dd[duplicated(dd[,c("year","month","day")])==T,c("year", "month", "day")]
        nam1<-paste(outlogdir,paste(ofilename,"dupliQC.csv",sep=""),sep="/")
        write.table(ddu2,file=nam1,append=F,quote=F,sep=", ",row.names=F)
        tkdestroy(start1)
        stop(paste("QC stopped due to duplicated date, please check ",nam1,sep=""))
    }
    
    mid<-dd[is.na(dd$prcp)==F,]  # choose non-MISSING PRCP
    mid<-mid[mid$prcp<0,]        # Is there unreasonable PRCP?
    #dd[is.na(dd$prcp)==F & dd$prcp<0,"prcp"]<-NA
    nam1<-paste(outlogdir,paste(ofilename,"_prcpQC.csv",sep=""),sep="/")
    write.table(mid,file=nam1,append=F,quote=F,sep=", ",row.names=F)
    if (dim(mid)[1]>0) tkmessageBox(message=paste("Errors in prcp, please check the log file",nam1,sep=" "))
    # output plots for PRCP
    nam1<-paste(outlogdir,paste(ofilename,"_prcpPLOT.pdf",sep=""),sep="/")
    pdf(file=nam1)
    ttmp<-dd[dd$prcp>=1,"prcp"]
    ttmp<-ttmp[is.na(ttmp)==F]
    if(length(ttmp)>30){
        hist(ttmp,main=paste("Histogram for Station:",ofilename," of PRCP>=1mm",sep=""),breaks=c(seq(0,20,2),max(30,ttmp)),xlab="",col="green",freq=F)
        lines(density(ttmp,bw=0.2,from=1),col="red")
    }
    pplotts(var="prcp",tit=ofilename)
    dev.off()
    nam1<-paste(outlogdir,paste(ofilename,"_tmaxPLOT.pdf",sep=""),sep="/")
    pdf(file=nam1)
    pplotts(var="tmax",type="l",tit=ofilename)
    dev.off()
    nam1<-paste(outlogdir,paste(ofilename,"_tminPLOT.pdf",sep=""),sep="/")
    pdf(file=nam1)
    pplotts(var="tmin",type="l",tit=ofilename)
    dev.off()
    nam1<-paste(outlogdir,paste(ofilename,"_dtrPLOT.pdf",sep=""),sep="/")
    pdf(file=nam1)
    pplotts(var="dtr",type="l",tit=ofilename)
    dev.off()
    
    #par(mfrow=c(1,1))
    # output problematic temperature like tmax < tmin
    mm<-dd[,"tmax"]-dd[,"tmin"]
    dd<-cbind(dd,mm)
    dimnames(dd)[[2]][7]<-"dtr"
    #output "log" file review
    temiss<-dd
    temiss<-temiss[is.na(temiss[,"tmax"])==F&is.na(temiss[,"tmin"])==F,]
    #  temiss<-temiss[is.na(temiss[,6])==F,]
    temiss<-temiss[temiss[,7]<=0|temiss[,5]<=(-70)|temiss[,5]>=70|temiss[,6]<=(-70)|temiss[,6]>=70,]
    dimnames(temiss)[[2]][7]<-"tmax-tmin"
    nam1<-paste(outlogdir,paste(ofilename,"_tempQC.csv",sep=""),sep="/")
    write.table(temiss,file=nam1,append=F,quote=F,sep=", ",row.names=F)
    if (dim(temiss)[1]>0) {
        tkmessageBox(message=paste("Errors in temperature, please check the log file",nam1,sep=" "))
        # records with abs(tmax)>=70, abs(tmin)>=70 set to NA
        dd[is.na(dd[,5])==F & abs(dd[,5])>=70,5]<-NA     # This is different from Fclimdex code  !!!!!!!!!!!!!!!!!!!!!!!!!!!!
        dd[is.na(dd[,6])==F & abs(dd[,6])>=70,6]<-NA
        # records with tmax < tmin are set to NA
        dd[is.na(dd[,5])==F & is.na(dd[,6])==F & dd[,"dtr"]<0,c("tmax","tmin")]<-NA
        #   dd[is.na(dd[,5])==F & dd[,"mm"]<0,"tmin"]<-NA
    }
    #  dd<-dd[,-7]
    
    # output problematic temperature which is out of 3 standard diviation (temp only)
    ys<-yeare-years+1
    
    tmaxm<-matrix(0,ys,365)
    tminm<-matrix(0,ys,365)
    tdtrm<-matrix(0,ys,365)
    
    tmaxstd<-rep(0,365)
    tminstd<-rep(0,365)
    tdtrstd<-rep(0,365)
    
    tmaxmean<-rep(0,365)
    tminmean<-rep(0,365)
    tdtrmean<-rep(0,365)
    
    for(i in 1:ys)
        tmaxm[i,]<-dd[dd[,"year"]==(i+years-1)&(dd[,"month"]*100+dd[,"day"]!=229),"tmax"]
    for(i in 1:365){
        tmaxstd[i]<-sqrt(var(tmaxm[,i],na.rm=T))
        tmaxmean[i]<-mean(tmaxm[,i],na.rm=T)
    }
    
    for(i in 1:ys)
        tminm[i,]<-dd[dd[,"year"]==(i+years-1)&(dd[,"month"]*100+dd[,"day"]!=229),"tmin"]
    for(i in 1:365){
        tminstd[i]<-sqrt(var(tminm[,i],na.rm=T))
        tminmean[i]<-mean(tminm[,i],na.rm=T)
    }
    
    for(i in 1:ys)
        tdtrm[i,]<-dd[dd[,"year"]==(i+years-1)&(dd[,"month"]*100+dd[,"day"]!=229),"dtr"]
    for(i in 1:365){
        tdtrstd[i]<-sqrt(var(tdtrm[,i],na.rm=T))
        tdtrmean[i]<-mean(tdtrm[,i],na.rm=T)
    }
    
    tmaxstdleap<-rep(0,366)
    tmaxstdleap[1:59]<-tmaxstd[1:59]
    tmaxstdleap[60]<-tmaxstd[59]
    tmaxstdleap[61:366]<-tmaxstd[60:365]
    
    tmaxmeanleap<-rep(0,366)
    tmaxmeanleap[1:59]<-tmaxmean[1:59]
    tmaxmeanleap[60]<-tmaxmean[59]
    tmaxmeanleap[61:366]<-tmaxmean[60:365]
    
    tminstdleap<-rep(0,366)
    tminstdleap[1:59]<-tminstd[1:59]
    tminstdleap[60]<-tminstd[59]
    tminstdleap[61:366]<-tminstd[60:365]
    
    tminmeanleap<-rep(0,366)
    tminmeanleap[1:59]<-tminmean[1:59]
    tminmeanleap[60]<-tminmean[59]
    tminmeanleap[61:366]<-tminmean[60:365]
    
    tdtrstdleap<-rep(0,366)
    tdtrstdleap[1:59]<-tdtrstd[1:59]
    tdtrstdleap[60]<-tdtrstd[59]
    tdtrstdleap[61:366]<-tdtrstd[60:365]
    
    tdtrmeanleap<-rep(0,366)
    tdtrmeanleap[1:59]<-tdtrmean[1:59]
    tdtrmeanleap[60]<-tdtrmean[59]
    tdtrmeanleap[61:366]<-tdtrmean[60:365]
    
    tmp<-matrix(0,dim(dd)[1],6)
    dimnames(tmp)<-list(NULL,c("tmaxlow","tmaxup","tminlow","tminup","dtrlow","dtrup"))
    
    idx<-0
    for(i in years:yeare){
        if(leapyear(i)==T){
            tmp[(idx+1):(idx+366),1]<-tmaxmeanleap-crt*tmaxstdleap
            tmp[(idx+1):(idx+366),2]<-tmaxmeanleap+crt*tmaxstdleap
            tmp[(idx+1):(idx+366),3]<-tminmeanleap-crt*tminstdleap
            tmp[(idx+1):(idx+366),4]<-tminmeanleap+crt*tminstdleap
            tmp[(idx+1):(idx+366),5]<-tdtrmeanleap-crt*tdtrstdleap
            tmp[(idx+1):(idx+366),6]<-tdtrmeanleap+crt*tdtrstdleap
            idx<-idx+366
        }
        else{
            tmp[(idx+1):(idx+365),1]<-tmaxmean-crt*tmaxstd
            tmp[(idx+1):(idx+365),2]<-tmaxmean+crt*tmaxstd
            tmp[(idx+1):(idx+365),3]<-tminmean-crt*tminstd
            tmp[(idx+1):(idx+365),4]<-tminmean+crt*tminstd
            tmp[(idx+1):(idx+365),5]<-tdtrmean-crt*tdtrstd
            tmp[(idx+1):(idx+365),6]<-tdtrmean+crt*tdtrstd
            idx<-idx+365
        }
    }
    
    odata<-cbind(dd,tmp)
    
    odata<-odata[is.na(odata[,"tmax"])==F,]
    odata<-odata[is.na(odata[,"tmin"])==F,]
    odata<-odata[is.na(odata[,"dtr"])==F,]
    o1data<-odata[odata[,5]<odata[,8]|odata[,5]>odata[,9]|odata[,6]<odata[,10]|odata[,6]>odata[,11]|odata[,7]<odata[,12]|odata[,7]>odata[,13],]
    #o2data<-odata[odata[,5]>odata[,8],]
    #o3data<-odata[odata[,6]<odata[,9],]
    #o4data<-odata[odata[,6]>odata[,10],]
    
    #write.table(errstdo,file=nam1,append=F,quote=F,sep=",",row.names=F)
    if (dim(o1data)[1] > 0){
        nam1<-paste(outlogdir,paste(ofilename,"_tepstdQC.csv",sep=""),sep="/")
        tkmessageBox(message=paste("Outliers found, please check the log file: ",nam1,sep=""))
        ofile<-cbind(o1data[,c(1,2,3,8,5,9,10,6,11,12,7,13)])
        write.table(round(ofile,digit=2),file=nam1,append=F,quote=F,sep=",",row.names=F)
    }
    
    dd<-dd[,c("year","month","day","prcp","tmax","tmin")];  assign("dd",dd,envir=.GlobalEnv)
    
    namcal<-paste(nama,"indcal.csv",sep="")
    assign("namcal",namcal,envir=.GlobalEnv)
    write.table(dd,file=namcal,append=F,quote=F,sep=",",row.names=F,na="-99.9")
    
    tkmessageBox(message=paste("If you have checked data(", namcal,"), click OK to continue.",sep=""))
}
# ------------ qcontrol ends --------------------------------

# ---------------------------------------------------------
# NASTST
nastat<-function(){
    dd <- read.table(namcal,header=T,sep=",",na.strings="-99.9",colClasses=rep("real",6))
    assign("dd",dd,envir=.GlobalEnv)
    # NA statistics
    nast<-rep(0,12)
    nast<-array(nast,c(1,12,12,(yeare-years+1)))
    dimnames(nast)<-list(NULL,c("ynapr","ynatma","ynatmi","napr","natma","natmi","mnapr>3","mnatma>3","mnatmi>3","ynapr>15","ynatma>15","ynatmi>15"),NULL,NULL)
    ys<-yeare-years+1                    
    year=years
    aa1<-matrix(NA,12*ys,4)   # monthly
    dimnames(aa1)<-list(NULL,c("year","month","tmaxm","tminm"))
    aa1[,"year"]<-years:yeare
    aa1[,"year"]<-mysort(aa1[,"year"],decreasing=F)    # Is this step necessary???
    aa1[,"month"]<-1:12
    aa2<-matrix(NA,ys,3)      # annual
    dimnames(aa2)<-list(NULL,c("year","tmaxm","tminm"))
    aa2[,"year"]<-years:yeare
    for (i in 1:(yeare-years+1)){
        month<-1;     midvalue1<-dd[dd$year==year,]   # data for each year
        aa2[i,"tmaxm"]<-mean(midvalue1[,"tmax"],na.rm=T)  # annual mean of Tmax, Tmin
        aa2[i,"tminm"]<-mean(midvalue1[,"tmin"],na.rm=T)
        for (j in 1:12){
            midvalue2<-midvalue1[midvalue1$month==month,]  # data for each month
            aa1[(i-1)*12+j,"tmaxm"]<-mean(midvalue2[,"tmax"],na.rm=T)  # monthly mean of Tmax, Tmin
            aa1[(i-1)*12+j,"tminm"]<-mean(midvalue2[,"tmin"],na.rm=T)
            nast[1,"ynapr",j,i]<-dim(midvalue1[is.na(midvalue1$prcp),])[1]  # annual missing days
            if (nast[1,"ynapr",j,i]>15) nast[1,"ynapr>15",j,i]<-NA
            nast[1,"ynatma",j,i]<-dim(midvalue1[is.na(midvalue1$tmax),])[1]
            if (nast[1,"ynatma",j,i]>15) nast[1,"ynatma>15",j,i]<-NA
            nast[1,"ynatmi",j,i]<-dim(midvalue1[is.na(midvalue1$tmin),])[1]
            if (nast[1,"ynatmi",j,i]>15) nast[1,"ynatmi>15",j,i]<-NA
            nast[1,"napr",j,i]<-dim(midvalue2[is.na(midvalue2$prcp),])[1]  # monthly missing days
            if (nast[1,"napr",j,i]>3) nast[1,"mnapr>3",j,i]<-NA
            nast[1,"natma",j,i]<-dim(midvalue2[is.na(midvalue2$tmax),])[1]
            if (nast[1,"natma",j,i]>3) nast[1,"mnatma>3",j,i]<-NA
            nast[1,"natmi",j,i]<-dim(midvalue2[is.na(midvalue2$tmin),])[1]
            if (nast[1,"natmi",j,i]>3) nast[1,"mnatmi>3",j,i]<-NA
            month=month+1 
        }
        year=year+1      
    }
    nasto<-t(nast[,,,1])
    for ( i in 2:(yeare-years+1)){
        nasto<-rbind(nasto,t(nast[,,,i])) }
    nastout<-matrix(0,(yeare-years+1)*12,2)
    dimnames(nastout)<-list(NULL,c("year","month"))                
    nastout<-as.data.frame(nastout)
    nastout[,"year"]<-years:yeare
    nastout[,"year"]<-mysort(nastout[,"year"],decreasing=F)
    nastout[,"month"]<-1:12
    
    nastout<-cbind(nastout,nasto);    assign("nastout",nastout,envir=.GlobalEnv)
    nastatistic<-nastout[,1:8]
    
    nacor<-nastout[,-(3:8)]
    ynacor<-matrix(0,ys,4)
    dimnames(ynacor)<-list(NULL,c("year","ynapr>15","ynatma>15","ynatmi>15"))
    ynacor[,"year"]<-years:yeare
    ynacor<-as.data.frame(ynacor)
    for (year in years:yeare){
        ynacor[ynacor$year==year,"ynapr>15"]<-nacor[nacor$year==year & nacor$month==1,"ynapr>15"]
        ynacor[ynacor$year==year,"ynatma>15"]<-nacor[nacor$year==year & nacor$month==1,"ynatma>15"]
        ynacor[ynacor$year==year,"ynatmi>15"]<-nacor[nacor$year==year & nacor$month==1,"ynatmi>15"]
    }
    nacor<-nacor[,1:5]
    assign("nacor",nacor,envir=.GlobalEnv)
    assign("ynacor",ynacor,envir=.GlobalEnv)
    if(sum(is.na(ynacor[,"ynapr>15"])==F)==0) prallna<-1
    else prallna<-0
    if(sum(is.na(ynacor[,"ynatma>15"])==F)==0) txallna<-1
    else txallna<-0
    if(sum(is.na(ynacor[,"ynatmi>15"])==F)==0) tnallna<-1
    else tnallna<-0
    assign("prallna",prallna,envir=.GlobalEnv)
    assign("txallna",txallna,envir=.GlobalEnv)
    assign("tnallna",tnallna,envir=.GlobalEnv)
    assign("nastatistic",nastatistic,envir=.GlobalEnv)
    nam1<-paste(outlogdir,paste(ofilename,"_nastatistic.csv",sep=""),sep="/")           # Output the result
    cat(file=nam1,"TITLE,YEAR,JAN,FEB,MAR,APR,MAY,JUN,JUL,AUG,SEP,OCT,NOV,DEC,ANN\n")
    for(year in years:yeare)
        for(i in 1:3) {
            if(i==1) tit<-"PRCP"
            if(i==2) tit<-"TMAX"
            if(i==3) tit<-"TMIN"
            line<-paste(tit,year,sep=",")
            for(mon in 1:12)
                line<-paste(line,nastatistic[nastatistic$year==year&nastatistic$month==mon,i+5],sep=",")
            line<-paste(line,nastatistic[nastatistic$year==year&nastatistic$month==1,i+2],sep=",")
            cat(file=nam1,line,fill=100,append=T)
        }
    #   write.table(nastatistic,file=nam1,append=F,quote=F,sep=", ",row.names=F)
    aa1[,"tmaxm"]<-aa1[,"tmaxm"]+nacor[,"mnatma>3"]
    aa1[,"tminm"]<-aa1[,"tminm"]+nacor[,"mnatmi>3"]
    aa2[,"tmaxm"]<-aa2[,"tmaxm"]+ynacor[,"ynatma>15"]
    aa2[,"tminm"]<-aa2[,"tminm"]+ynacor[,"ynatmi>15"]
    ofile1<-paste(outinddir,paste(ofilename,"_TMAXmean.csv",sep=""),sep="/")
    odata<-matrix(0,ys,14)
    dimnames(odata)<-list(NULL,c("year","jan","feb","mar","apr","may","jun","jul","aug","sep","oct","nov","dec","annual"))
    odata[,1]<-years:yeare
    odata[,14]<-aa2[,"tmaxm"]
    for(i in 1:ys) odata[i,2:13]<-aa1[((i-1)*12+1):(i*12),"tmaxm"]
    write.table(round(odata,2),file=ofile1,append=F,quote=F,sep=", ",na="-99.9",row.names=F)
    odata[,14]<-aa2[,"tminm"]
    for(i in 1:ys) odata[i,2:13]<-aa1[((i-1)*12+1):(i*12),"tminm"]
    ofile1<-paste(outinddir,paste(ofilename,"_TMINmean.csv",sep=""),sep="/")
    write.table(round(odata,2),file=ofile1,append=F,quote=F,sep=", ",na="-99.9",row.names=F)
    parameter()
}
# -------------- nastat ends ------------------------------------------

# -----------------------------------------------------------------
# getfile
# first step is to open a data file, and read them into "dd".
#
getfile<-function() {
    name <- tclvalue(tkgetOpenFile(filetypes="{{TEXT Files} {.txt}} {{All files} *}"))
    if (name=="") return();
    dd <- read.table(name,header=F,col.names=c("year","month","day","prcp","tmax","tmin"),colClasses=rep("real",6))
    nama<-substr(name,start=1,stop=(nchar(name)-4))
    outdirtmp<-strsplit(name,"/")[[1]]
    if(length(outdirtmp)<=2){  # for Windiws
        outinddir<-paste(strsplit(name,":")[[1]][1],"indices",sep=":/")
        outlogdir<-paste(strsplit(name,":")[[1]][1],"log",sep=":/")
        outjpgdir<-paste(strsplit(name,":")[[1]][1],"plots",sep=":/")
        outtrddir<-paste(strsplit(name,":")[[1]][1],"trend",sep=":/")
    }
    else{                   # Unix/Linux
        outdir<-outdirtmp[1]
        for(i in 2:(length(outdirtmp)-1))
            outdir<-paste(outdir,outdirtmp[i],sep="/")
        outinddir<-paste(outdir,"indices",sep="/")
        outlogdir<-paste(outdir,"log",sep="/")
        outjpgdir<-paste(outdir,"plots",sep="/")
        outtrddir<-paste(outdir,"trend",sep="/")
    }
    ofilename<-substr(outdirtmp[length(outdirtmp)],start=1,stop=(nchar(outdirtmp[length(outdirtmp)])-4))
    # create output folders
    if(!file.exists(outinddir)) dir.create(outinddir)
    if(!file.exists(outlogdir)) dir.create(outlogdir)
    if(!file.exists(outjpgdir)) dir.create(outjpgdir)
    if(!file.exists(outtrddir)) dir.create(outtrddir)
    
    #     dimnames(dd)<-list(NULL,c("year","month","day","prcp","tmax","tmin"))
    assign("nama",nama,envir=.GlobalEnv)
    assign("outinddir",outinddir,envir=.GlobalEnv)
    assign("outlogdir",outlogdir,envir=.GlobalEnv)
    assign("outjpgdir",outjpgdir,envir=.GlobalEnv)
    assign("outtrddir",outtrddir,envir=.GlobalEnv)
    assign("ofilename",ofilename,envir=.GlobalEnv)
    # dd<-dd[dd$tmax!=-99.9,]
    # dd$year<-dd$year+40 # just for the test data
    # replace missing value with NA
    dd[dd$prcp<=(-99.),"prcp"]<-NA
    dd[dd$tmax<=(-99.),"tmax"]<-NA
    dd[dd$tmin<=(-99.),"tmin"]<-NA
    # replace missing records
    ddd<-matrix(NA,365,6)
    dddl<-matrix(NA,366,6)
    dimnames(ddd)<-list(NULL,c("year","month","day","prcp","tmax","tmin"))
    dimnames(dddl)<-list(NULL,c("year","month","day","prcp","tmax","tmin"))
    ddd[1:31,"month"]<-1;     ddd[1:31,"day"]<-c(1:31);    ddd[32:59,"month"]<-2;    ddd[32:59,"day"]<-c(1:28)
    ddd[60:90,"month"]<-3;    ddd[60:90,"day"]<-c(1:31);   ddd[91:120,"month"]<-4;   ddd[91:120,"day"]<-c(1:30)
    ddd[121:151,"month"]<-5;  ddd[121:151,"day"]<-c(1:31); ddd[152:181,"month"]<-6;  ddd[152:181,"day"]<-c(1:30)
    ddd[182:212,"month"]<-7;  ddd[182:212,"day"]<-c(1:31); ddd[213:243,"month"]<-8;  ddd[213:243,"day"]<-c(1:31)
    ddd[244:273,"month"]<-9;  ddd[244:273,"day"]<-c(1:30); ddd[274:304,"month"]<-10; ddd[274:304,"day"]<-c(1:31)
    ddd[305:334,"month"]<-11; ddd[305:334,"day"]<-c(1:30); ddd[335:365,"month"]<-12; ddd[335:365,"day"]<-c(1:31)
    
    dddl[1:31,"month"]<-1;     dddl[1:31,"day"]<-c(1:31);    dddl[32:60,"month"]<-2;    dddl[32:60,"day"]<-c(1:29)
    dddl[61:91,"month"]<-3;    dddl[61:91,"day"]<-c(1:31);   dddl[92:121,"month"]<-4;   dddl[92:121,"day"]<-c(1:30)
    dddl[122:152,"month"]<-5;  dddl[122:152,"day"]<-c(1:31); dddl[153:182,"month"]<-6;  dddl[153:182,"day"]<-c(1:30)
    dddl[183:213,"month"]<-7;  dddl[183:213,"day"]<-c(1:31); dddl[214:244,"month"]<-8;  dddl[214:244,"day"]<-c(1:31)
    dddl[245:274,"month"]<-9;  dddl[245:274,"day"]<-c(1:30); dddl[275:305,"month"]<-10; dddl[275:305,"day"]<-c(1:31)
    dddl[306:335,"month"]<-11; dddl[306:335,"day"]<-c(1:30); dddl[336:366,"month"]<-12; dddl[336:366,"day"]<-c(1:31)
    
    years<-dd[1,1];yeare<-dd[dim(dd)[1],1]   # star and end years
    if (leapyear(years)) dddd<-dddl else dddd<-ddd
    dddd[,"year"]<-years
    for (year in years:yeare){                  # year loop start
        if (leapyear(year)) dddd1<-dddl else dddd1<-ddd
        dddd1[,"year"]<-year
        if (year!=years) dddd<-rbind(dddd,dddd1)
    }                                       # year loop end
    
    dddd<-as.data.frame(dddd)
    dddd2<-merge(dddd,dd,by=c("year","month","day"),all.x=T)
    dddd2<-dddd2[,-(4:6)]
    dimnames(dddd2)[[2]]<-c("year","month","day","prcp","tmax","tmin")
    tmporder<-dddd2[,"year"]*10000+dddd2[,"month"]*100+dddd2[,"day"]
    dd<-dddd2[order(tmporder),]
    
    assign("years",years,envir=.GlobalEnv)
    assign("yeare",yeare,envir=.GlobalEnv)
    assign("dd",dd,envir=.GlobalEnv)
    
    tkmessageBox(message=paste("Data(",ofilename,") loaded, click OK to continue.",sep=""))
    
    # enter station name and the times of stadard deviation
    infor1<-tktoplevel()
    tkfocus(infor1)
    tkgrab.set(infor1)
    tkwm.title(infor1,"Set Parameters for Data QC")
    
    textEntry1<-stations;        textEntry2<-stdt
    
    textEntryWidget1<-tkentry(infor1,width=30,textvariable=textEntry1)
    textEntryWidget2<-tkentry(infor1,width=30,textvariable=textEntry2)
    
    #     tkgrid(tklabel(infor1,text="!!Enter parameters please",font=fontHeading1))
    tkgrid(tklabel(infor1,text="                  Station name or code:"),textEntryWidget1)
    tkgrid(tklabel(infor1,text="Criteria(number of Standard Deviation):"),textEntryWidget2)
    
    ok1<-function(){
        station<-as.character(tclvalue(textEntry1));    assign("station",station,envir=.GlobalEnv)
        crt<-as.numeric(tclvalue(textEntry2));          assign("crt",crt,envir=.GlobalEnv)
        tkgrab.release(infor1)
        tkdestroy(infor1)
        stations<-textEntry1;      assign("stations",stations,envir=.GlobalEnv)
        stdt<-textEntry2;          assign("stdt",stdt,envir=.GlobalEnv)
        qcontrol();                tkfocus(start1)
    }# end of ok
    
    cancel1<-function(){
        tkmessageBox(message="You have to enter these parameters before you can move on.")
        tkfocus(infor1)}# end of cancel1
    
    ok1.but<-    tkbutton(infor1,text="    OK    ",command=ok1)
    cancel1.but<-tkbutton(infor1,text="  CANCEL  ",command=cancel1)
    tkgrid(ok1.but,cancel1.but)
    
}
# end of getfile
#------------------------------------------------------------

# -----------------------------------------------------------
# parameter
#
parameter<-function(){
    infor<-tktoplevel()
    tkfocus(infor)
    tkgrab.set(infor)
    tkwm.title(infor,"Set Parameter Values")
    
    textEntry1<-Entry1
    textEntry2<-Entry2
    #     textEntry3<-Entry3
    textEntry4<-Entry4
    textEntry5<-Entry5
    textEntry6<-Entry6;textEntry7<-Entry7
    textEntry8<-Entry8;textEntry9<-Entry9
    #     textEntry10<-Entry10;textEntry11<-Entry11
    textEntry12<-Entry12
    
    textEntryWidget1<-tkentry(infor,width=20,textvariable=textEntry1)
    textEntryWidget2<-tkentry(infor,width=20,textvariable=textEntry2)
    #     textEntryWidget3<-tkentry(infor,width=20,textvariable=textEntry3)
    textEntryWidget4<-tkentry(infor,width=20,textvariable=textEntry4)
    textEntryWidget5<-tkentry(infor,width=20,textvariable=textEntry5)
    textEntryWidget6<-tkentry(infor,width=20,textvariable=textEntry6)
    textEntryWidget7<-tkentry(infor,width=20,textvariable=textEntry7)
    textEntryWidget8<-tkentry(infor,width=20,textvariable=textEntry8)
    textEntryWidget9<-tkentry(infor,width=20,textvariable=textEntry9)
    #     textEntryWidget10<-tkentry(infor,width=20,textvariable=textEntry10)
    #     textEntryWidget11<-tkentry(infor,width=20,textvariable=textEntry11)
    textEntryWidget12<-tkentry(infor,width=20,textvariable=textEntry12)
    
    tkgrid(tklabel(infor,text="User defined parameters for Indices Calculation",font=fontHeading1))
    tkgrid(tklabel(infor,text="First year of base period"),textEntryWidget1)
    tkgrid(tklabel(infor,text="Last year of base period"),textEntryWidget2)
    tkgrid(tklabel(infor,text="Latitude of this station location"),textEntryWidget4)
    tkgrid(tklabel(infor,text="Longitude of this station location"),textEntryWidget5)
    tkgrid(tklabel(infor,text="User defined upper threshold of daily maximum temperature"),textEntryWidget6)
    tkgrid(tklabel(infor,text="User defined lower threshold of daily maximum temperature"),textEntryWidget7)
    tkgrid(tklabel(infor,text="User defined upper threshold of daily minimum temperature"),textEntryWidget8)
    tkgrid(tklabel(infor,text="User defined lower threshold of daily minimum temperature"),textEntryWidget9)
    tkgrid(tklabel(infor,text="User defined daily precipitation threshold"),textEntryWidget12)
    
    #----------- OK1 -----------------------------------------    
    ok1<-function(){
        #       tkmessageBox(message="This process may take 2 mins to initialize the data. Please wait until the window disapear!")
        startyear<-as.numeric(tclvalue(textEntry1));  assign("startyear",startyear,envir=.GlobalEnv)
        endyear<-as.numeric(tclvalue(textEntry2));    assign("endyear",endyear,envir=.GlobalEnv)
        if(startyear<years|endyear>yeare){
            if(startyear<years) msg<-paste("Input base period start:", startyear," less then start year of data:", years, sep=" ")
            else msg<-paste("Input base period end:", endyear," greater then end year of data:", yeare, sep=" ")
            tkmessageBox(message=msg)
            tkfocus(infor)
            return()
        }
        #       winsize<-as.numeric(tclvalue(textEntry3));   assign("winsize",winsize,envir=.GlobalEnv)
        latitude<-as.numeric(tclvalue(textEntry4));   assign("latitude",latitude,envir=.GlobalEnv)
        longitude<-as.numeric(tclvalue(textEntry5));  assign("longitude",longitude,envir=.GlobalEnv)
        #       threshold<-as.numeric(tclvalue(textEntry5)); assign("threshold",threshold,envir=.GlobalEnv)
        uuu<-as.numeric(tclvalue(textEntry6));        assign("uuu",uuu,envir=.GlobalEnv)
        ulu<-as.numeric(tclvalue(textEntry7));        assign("uul",ulu,envir=.GlobalEnv)
        uul<-as.numeric(tclvalue(textEntry8));        assign("ulu",uul,envir=.GlobalEnv)
        ull<-as.numeric(tclvalue(textEntry9));        assign("ull",ull,envir=.GlobalEnv)
        #       up<-as.numeric(tclvalue(textEntry10));       assign("up",up,envir=.GlobalEnv)
        #       lp<-as.numeric(tclvalue(textEntry11));       assign("lp",lp,envir=.GlobalEnv)
        nn<-as.numeric(tclvalue(textEntry12));        assign("nn",nn,envir=.GlobalEnv)
        startpoint<-startyear-1;   assign("startpoint",startpoint,envir=.GlobalEnv)
        endpoint<-endyear+1;       assign("endpoint",endpoint,envir=.GlobalEnv)
        nordaytem1()
        tkgrab.release(infor)
        tkdestroy(infor)
        Entry1<-textEntry1;   assign("Entry1",Entry1,envir=.GlobalEnv)
        Entry2<-textEntry2;   assign("Entry2",Entry2,envir=.GlobalEnv)
        #       Entry3<-textEntry3;  assign("Entry3",Entry3,envir=.GlobalEnv)
        Entry4<-textEntry4;   assign("Entry4",Entry4,envir=.GlobalEnv)
        Entry5<-textEntry5;   assign("Entry5",Entry5,envir=.GlobalEnv)
        Entry6<-textEntry6;   assign("Entry6",Entry6,envir=.GlobalEnv)
        Entry7<-textEntry7;   assign("Entry7",Entry7,envir=.GlobalEnv)
        Entry8<-textEntry8;   assign("Entry8",Entry8,envir=.GlobalEnv)
        Entry9<-textEntry9;   assign("Entry9",Entry9,envir=.GlobalEnv)
        #       Entry10<-textEntry10; assign("Entry10",Entry10,envir=.GlobalEnv)
        #       Entry11<-textEntry11; assign("Entry11",Entry11,envir=.GlobalEnv)
        Entry12<-textEntry12;  assign("Entry12",Entry12,envir=.GlobalEnv)
        main1()
    }
    #----------- OK1 ends -----------------------------------------  
    
    #----------- cancel1 -----------------------------------------  
    cancel1<-function(){
        #       tkmessageBox(message="Please enter these parameters before you can move forward!!")
        #       tkfocus(infor)
        tkdestroy(infor)
        #       tkdestroy(main)
        #       tkfocus(start1)
        return()
    }
    #----------- cancel1 ends -----------------------------------------  
    
    ok1.but<-    tkbutton(infor,text="    OK    ",command=ok1)
    cancel1.but<-tkbutton(infor,text="  CANCEL  ",command=cancel1)
    tkgrid(ok1.but,cancel1.but)
}
#----------- parameter ends -----------------------------------------  
# End of Part I (general functions & TCL/TK functions
##################################################################################


##################################################################################
# Part II
# Functions of calculating climate indecies
##################################################################################
#----------- hwfi -----------------------------------------  
hwfi<-function(){
    if (flag==T) return()
    hwfi<-matrix(0,(yeare-years+1),2)
    dimnames(hwfi)[[2]]<-c("year","wsdi")
    hwfi[,"year"]<-years:yeare
    for (year in years:yeare) {
        if(leapyear(year)){
            aa<-rep(0,366)
            aa[1:59]<-aas[,"pcmax90"][1:59]
            aa[60]<-aa[59]
            aa[61:366]<-aas[,"pcmax90"][60:365]
        }
        else aa<-aas[,"pcmax90"]
        bb<-dd[dd$year==year,"tmax"]
        if(length(aa)!=length(bb)) stop("ERROR in WSDI, check data!")
        midval<-bb-aa
        ylen<-length(aa)
        ycnt<-0
        icnt<-0
        for(i in 1:ylen){
            if(is.na(midval[i])==F&midval[i]>0)
                icnt<-icnt+1
            else{
                if(icnt>=6) ycnt<-ycnt+icnt
                icnt<-0
            }
            if(i==ylen&icnt>=6) ycnt<-ycnt+icnt
        }
        hwfi[year-years+1,2]<-ycnt
    }
    hwfi<-as.data.frame(hwfi)
    hwfi[,"wsdi"]<-hwfi[,"wsdi"]+ynacor[,"ynatma>15"]  
    nam1<-paste(outinddir,paste(ofilename,"_WSDI.csv",sep=""),sep="/")
    write.table(hwfi,file=nam1,append=F,quote=F,sep=", ",na="-99.9",row.names=F)
    
    namt<-paste(outtrddir,paste(ofilename,"_trend.csv",sep=""),sep="/")
    if(sum(is.na(hwfi[,"wsdi"]))>=(yeare-years+1-10)){
        betahat<-NA
        betastd<-NA
        pvalue<-NA
    }
    else{
        fit1<-lsfit(hwfi[,"year"],hwfi[,"wsdi"])
        out1<-ls.print(fit1,print.it=F)
        pvalue<-round(as.numeric(out1$summary[1,6]),3)
        betahat<-round(as.numeric(out1$coef.table[[1]][2,1]),3)
        betastd<-round(as.numeric(out1$coef.table[[1]][2,2]),3)
    }
    cat(file=namt,paste(latitude,longitude,"wsdi",years,yeare,betahat,betastd,pvalue,sep=","),fill=180,append=T)
    
    nam2<-paste(outjpgdir,paste(ofilename,"_WSDI.jpg",sep=""),sep="/")
    jpeg(nam2,width=1024,height=768)
    plotx(hwfi[,1],hwfi[,2], main=paste("WSDI",ofilename,sep="   "),ylab="WSDI",xlab="Year")
    dev.off()
} 
# ------------ hwfi ends ------------------------------------

# ------------- cwdi ----------------------------------------
cwdi<-function(){
    if (flag==T) return()
    cwdi<-matrix(0,(yeare-years+1),2)
    dimnames(cwdi)[[2]]<-c("year","csdi")
    cwdi[,"year"]<-years:yeare
    for (year in years:yeare) {
        if(leapyear(year)){
            aa<-rep(0,366)
            aa[1:59]<-aas[,"pcmin10"][1:59]
            aa[60]<-aa[59]
            aa[61:366]<-aas[,"pcmin10"][60:365]
        }
        else aa<-aas[,"pcmin10"]
        bb<-dd[dd$year==year,"tmin"]
        if(length(aa)!=length(bb)) stop("ERROR in CWDI, check data!")
        midval<-aa-bb
        ylen<-length(aa)
        ycnt<-0
        icnt<-0
        for(i in 1:ylen){
            if(is.na(midval[i])==F&midval[i]>0)
                icnt<-icnt+1
            else{
                if(icnt>=6) ycnt<-ycnt+icnt
                icnt<-0
            }
            if(i==ylen&icnt>=6) ycnt<-ycnt+icnt
        }
        cwdi[year-years+1,2]<-ycnt
    }
    cwdi<-as.data.frame(cwdi)
    cwdi[,"csdi"]<-cwdi[,"csdi"]+ynacor[,"ynatmi>15"]  
    nam1<-paste(outinddir,paste(ofilename,"_CSDI.csv",sep=""),sep="/")
    write.table(cwdi,file=nam1,append=F,quote=F,sep=", ",na="-99.9",row.names=F)
    
    namt<-paste(outtrddir,paste(ofilename,"_trend.csv",sep=""),sep="/")
    if(sum(is.na(cwdi[,"csdi"]))>=(yeare-years+1-10)){
        betahat<-NA
        betastd<-NA
        pvalue<-NA
    }
    else{
        fit1<-lsfit(cwdi[,"year"],cwdi[,"csdi"])
        out1<-ls.print(fit1,print.it=F)
        pvalue<-round(as.numeric(out1$summary[1,6]),3)
        betahat<-round(as.numeric(out1$coef.table[[1]][2,1]),3)
        betastd<-round(as.numeric(out1$coef.table[[1]][2,2]),3)
    }
    cat(file=namt,paste(latitude,longitude,"csdi",years,yeare,betahat,betastd,pvalue,sep=","),fill=180,append=T)
    
    nam2<-paste(outjpgdir,paste(ofilename,"_CSDI.jpg",sep=""),sep="/")
    jpeg(nam2,width=1024,height=768)
    plotx(cwdi[,1],cwdi[,2],main=paste("CSDI",ofilename,sep="   "),ylab="CSDI",xlab="Year")
    dev.off()
} 
# ----------------- cwdi ends -------------------------------------------

#----------- r95ptot -----------------------------------------
r95ptot<-function(){
    prcptmp<-dd[dd$year>=startyear&dd$year<=endyear&dd$prcp>=1,"prcp"]
    prcptmp<-prcptmp[is.na(prcptmp)==F]
    len<-length(prcptmp)
    prcp95<-percentile(len,prcptmp,0.95)
    prcp99<-percentile(len,prcptmp,0.99)
    
    ys<-yeare-years+1
    
    dp<-matrix(0,ys,4)
    dimnames(dp)<-list(NULL,c("year","r95p","r99p","prcptot"))
    dp[,"year"]<-years:yeare
    for(i in years:yeare){
        dp[(i-years+1),"r95p"]<-sum(dd[dd$year==i&dd$prcp>prcp95,"prcp"],na.rm=T)
        dp[(i-years+1),"r99p"]<-sum(dd[dd$year==i&dd$prcp>prcp99,"prcp"],na.rm=T)
        dp[(i-years+1),"prcptot"]<-sum(dd[dd$year==i&dd$prcp>=1,"prcp"],na.rm=T)
    }
    dp[,"r95p"]<-round(dp[,"r95p"],1)+ynacor[,"ynapr>15"]
    dp[,"r99p"]<-round(dp[,"r99p"],1)+ynacor[,"ynapr>15"]
    dp[,"prcptot"]<-round(dp[,"prcptot"],1)+ynacor[,"ynapr>15"]
    dp<-as.data.frame(dp)
    nam1<-paste(outinddir,paste(ofilename,"_R95p.csv",sep=""),sep="/")
    nam2<-paste(outinddir,paste(ofilename,"_R99p.csv",sep=""),sep="/")
    nam3<-paste(outinddir,paste(ofilename,"_PRCPTOT.csv",sep=""),sep="/")
    write.table(dp[,c("year","r95p")],file=nam1,append=F,quote=F,sep=", ",na="-99.9",row.names=F)
    write.table(dp[,c("year","r99p")],file=nam2,append=F,quote=F,sep=", ",na="-99.9",row.names=F)
    write.table(dp[,c("year","prcptot")],file=nam3,append=F,quote=F,sep=", ",na="-99.9",row.names=F)
    
    namt<-paste(outtrddir,paste(ofilename,"_trend.csv",sep=""),sep="/")
    for(i in c("r95p","r99p","prcptot")){
        if(sum(is.na(dp[,i]))>=(yeare-years+1-10)){
            betahat<-NA
            betastd<-NA
            pvalue<-NA
        }
        else{
            fit1<-lsfit(dp[,"year"],dp[,i])
            out1<-ls.print(fit1,print.it=F)
            pvalue<-round(as.numeric(out1$summary[1,6]),3)
            betahat<-round(as.numeric(out1$coef.table[[1]][2,1]),3)
            betastd<-round(as.numeric(out1$coef.table[[1]][2,2]),3)
        }
        cat(file=namt,paste(latitude,longitude,i,years,yeare,betahat,betastd,pvalue,sep=","),fill=180,append=T)
    }
    
    nam4<-paste(outjpgdir,paste(ofilename,"_R95p.jpg",sep=""),sep="/")
    jpeg(nam4,width=1024,height=768)
    plotx(dp[,1],dp[,"r95p"],main=paste("R95p",ofilename,sep="   "),xlab="Year",ylab="R95p")
    dev.off()
    nam5<-paste(outjpgdir,paste(ofilename,"_R99p.jpg",sep=""),sep="/")
    jpeg(nam5,width=1024,height=768)
    plotx(dp[,1],dp[,"r99p"],main=paste("R99p",ofilename,sep="   "),xlab="Year",ylab="R99p")
    dev.off()
    nam6<-paste(outjpgdir,paste(ofilename,"_PRCPTOT.jpg",sep=""),sep="/")
    jpeg(nam6,width=1024,height=768)
    plotx(dp[,1],dp[,"prcptot"],main=paste("PRCPTOT",ofilename,sep="   "),xlab="Year",ylab="PRCPTOT")
    dev.off()
}
#----------- r95ptot ends -----------------------------------------

#----------- daysprcp20 -----------------------------------------
daysprcp20<-function(){
    ys<-yeare-years+1
    R20<-rep(0,ys)
    yearss<-c(years:yeare)
    target<-as.data.frame(cbind(yearss,R20))
    for (year in years:yeare){
        mid<-dd[dd$year==year,"prcp"]
        mid<-mid[is.na(mid)==F]
        target[target$yearss==year,"R20"]<-length(mid[mid>=20])}# end for
    dimnames(target)[[2]][1]<-"year"
    target[,"R20"]<-target[,"R20"]+ynacor[,"ynapr>15"]
    nam1<-paste(outinddir,paste(ofilename,"_R20mm.csv",sep=""),sep="/")
    write.table(target,file=nam1,append=F,quote=F,sep=", ",na="-99.9",row.names=F)
    
    namt<-paste(outtrddir,paste(ofilename,"_trend.csv",sep=""),sep="/")
    if(sum(is.na(target[,"R20"]))>=(yeare-years+1-10)){
        betahat<-NA
        betastd<-NA
        pvalue<-NA
    }
    else{
        fit1<-lsfit(target[,"year"],target[,"R20"])
        out1<-ls.print(fit1,print.it=F)
        pvalue<-round(as.numeric(out1$summary[1,6]),3)
        betahat<-round(as.numeric(out1$coef.table[[1]][2,1]),3)
        betastd<-round(as.numeric(out1$coef.table[[1]][2,2]),3)
    }
    cat(file=namt,paste(latitude,longitude,"r20mm",years,yeare,betahat,betastd,pvalue,sep=","),fill=180,append=T)
    
    nam2<-paste(outjpgdir,paste(ofilename,"_R20mm.jpg",sep=""),sep="/")
    jpeg(nam2,width=1024,height=768)
    plotx(target[,1],target[,2],main=paste("R20mm",ofilename,sep="   "),xlab="Year",ylab="R20mm")
    dev.off()
}
#----------- daysprcp20 ends -----------------------------------------

#----------- daysprcpn -----------------------------------------
daysprcpn<-function(){
    ys<-yeare-years+1
    Rnn<-rep(0,ys)
    yearss<-c(years:yeare)
    target<-as.data.frame(cbind(yearss,Rnn))
    for (year in years:yeare){
        mid<-dd[dd$year==year,"prcp"]
        mid<-mid[is.na(mid)==F]
        target[target$yearss==year,"Rnn"]<-length(mid[mid>=nn])
    }
    dimnames(target)[[2]][1]<-"year"
    target[,"Rnn"]<-target[,"Rnn"]+ynacor[,"ynapr>15"]
    
    nam1<-paste(outinddir,paste(ofilename,"_R",as.character(nn),"mm.csv",sep=""),sep="/")
    write.table(target,file=nam1,append=F,quote=F,sep=", ",na="-99.9",row.names=F)
    
    namt<-paste(outtrddir,paste(ofilename,"_trend.csv",sep=""),sep="/")
    if(sum(is.na(target[,"Rnn"]))>=(yeare-years+1-10)){
        betahat<-NA
        betastd<-NA
        pvalue<-NA
    }
    else{
        fit1<-lsfit(target[,1],target[,"Rnn"])
        out1<-ls.print(fit1,print.it=F)
        pvalue<-round(as.numeric(out1$summary[1,6]),3)
        betahat<-round(as.numeric(out1$coef.table[[1]][2,1]),3)
        betastd<-round(as.numeric(out1$coef.table[[1]][2,2]),3)
    }
    cat(file=namt,paste(latitude,longitude,paste("R",as.character(nn),"mm",sep=""),years,yeare,betahat,betastd,pvalue,sep=","),fill=180,append=T)
    
    nam2<-paste(outjpgdir,paste(ofilename,"_R",as.character(nn),"mm.jpg",sep=""),sep="/")
    jpeg(nam2,width=1024,height=768)
    plotx(target[,1],target[,2],main=paste("R",as.character(nn),"mm",ofilename,sep="   "),xlab="Year",ylab="Rnnmm")
    dev.off()
}
#----------- daysprcpn ends -----------------------------------------

#----------- nordaytem1 -----------------------------------------
nordaytem1<-function(){  # initialize data
    # normal temp
    
    daynorm<-dd[dd$year>=startyear,]
    daynorm<-daynorm[daynorm$year<=endyear,] # initialize daynorm matrix
    daynor<-daynorm              # create target matrix
    nn<-dd[dd$year==startpoint,]
    nn<-nn[nn$month==12,]
    nn<-nn[nn$day>(31-round(winsize/2)),]
    daynorm<-rbind(nn,daynorm)
    nn<-dd[dd$year==endpoint,]
    nn<-nn[nn$month==1,]
    nn<-nn[nn$day<=round(winsize/2),]
    daynorm<-rbind(daynorm,nn)
    
    daynorm1<-daynorm[,-4]
    daynorm1[daynorm1$month==2 & daynorm1$day==29,]<--99
    daynorm1<-daynorm1[daynorm1$year!=-99,]
    dayt<-daynorm1[,c("tmax","tmin")]
    
    ddtem<-dd[,-4]
    ddtem[ddtem$month==2 & ddtem$day==29,]<--99
    ddtem<-ddtem[ddtem$year!=-99,]
    assign("ddtem",ddtem,envir=.GlobalEnv)
    
    a<-matrix(-99,5,5)
    dimnames(a)[[2]]<-c("year","month","day","tmax","tmin")
    ddtemt<-rbind(a,ddtem);    assign("ddtemt",ddtemt,envir=.GlobalEnv)
    
    ys<-endyear-startyear+1
    window<-matrix(0,winsize,2)
    windows<-array(window,c(winsize,2,366,ys))
    dimnames(windows)<-list(NULL,c("tmax","tmin"),NULL,NULL)
    
    i=winsize-round(winsize/2,digits=0)
    i1=round(winsize/2,digits=0)
    daynormm<-daynorm[,c("tmax","tmin")]
    daynormm<-as.matrix(daynormm)
    year<-startyear
    
    for (k in 1:ys){
        if (leapyear(year)==T) jj<-366 else {jj<-365;   windows[,,366,k]<--99 }
        year<-year+1
        for (j in 1:jj){
            windows[,,j,k]<-daynormm[(i-i1):(i+i1),]
            i=i+1 }}
    
    mwindows<-colMeans(windows,na.rm=T)
    tmax<-mwindows["tmax",,];    tmax<-tmax[tmax!=-99]
    tmin<-mwindows["tmin",,];    tmin<-tmin[tmin!=-99]
    daynor[,"tmax"]<-tmax;       daynor[,"tmin"]<-tmin
    
    a<-rep(0,nrow(daynor))
    a<-(daynor[,"tmax"]+daynor[,"tmin"])/2
    daytemave<-a    
    daynor<-cbind(daynor,daytemave)
    
    # output the result to globe enviroment
    assign("daynor",daynor,envir=.GlobalEnv)
    assign("daynorm",daynorm,envir=.GlobalEnv)
    assign("daynorm1",daynorm1,envir=.GlobalEnv)
    assign("dayt",dayt,envir=.GlobalEnv)
    
    # prcp percentile 95% and 99%
    prcpnorm<-dd[dd$year>=startyear,]
    prcpnorm<-prcpnorm[prcpnorm$year<=endyear,] # initialize prcpnorm matrix
    nnp<-dd[dd$year==startpoint,]
    nnp<-nnp[nnp$month==12,]
    nnp<-nnp[nnp$day>29,]
    prcpnorm<-rbind(nnp,prcpnorm)
    nnp<-dd[dd$year==endpoint,]
    nnp<-nnp[nnp$month==1,]
    nnp<-nnp[nnp$day<=2,]
    prcpnorm<-rbind(prcpnorm,nnp)
    prcpnorm<-prcpnorm[,1:4]
    # remove Feb 29
    prcpnorm[prcpnorm$month==2 & prcpnorm$day==29,]<--99
    prcpnorm<-prcpnorm[prcpnorm$year!=-99,]
    assign("prcpnorm",prcpnorm,envir=.GlobalEnv)
    
    ys<-endyear-startyear+1 
    
    aasp<-matrix(NA,365,3)
    dimnames(aasp)<-list(NULL,c("day","prcp95","prcp99"))
    aasp[,"day"]<-1:365
    
    msp<-5*ys
    prcpnorm<-as.matrix(prcpnorm)
    pwindow<-matrix(0,5,1)
    pwindows<-array(pwindow,c(5,1,365,ys)) #array used to store all windows
    ip=3
    ip1=2
    for (k in 1:ys){
        for (j in 1:365){
            
            pwindows[,,j,k]<-prcpnorm[(ip-ip1):(ip+ip1),"prcp"]
            ip=ip+1}}
    
    prcpwin<-matrix(0,msp,2)
    prcpwin[,2]<-1:ys
    prcpwin[,2]<-mysort(prcpwin[,2],decreasing=F)
    
    prcpwins<-array(prcpwin,c(msp,2,365)) 
    
    for (j in 1:365){
        for (i in 1:ys){
            prcpwins[prcpwins[,2,j]==i,1,j]<-pwindows[,,j,i]}}
    #assign("exwins",exwins,envir=.GlobalEnv)
    
    for (i in 1:365){
        assp<-prcpwins[,,i]
        if(sum(is.na(assp[,1])==F)>=1)
            aasp[i,"prcp95"]<-percentile(msp,assp[,1],0.95)
        else aasp[i,"prcp95"]<-NA
        if(sum(is.na(assp[,1])==F)>=1)
            aasp[i,"prcp99"]<-percentile(msp,assp[,1],0.99)
        else aasp[i,"prcp99"]<-NA
    }
    assign("aasp",aasp,envir=.GlobalEnv)
    
    aas<-matrix(NA,365,5)
    dimnames(aas)<-list(NULL,c("day","pcmax10","pcmax90","pcmin10","pcmin90"))
    aas[,"day"]<-1:365
    
    ms<-winsize*ys
    dayt<-as.matrix(dayt)
    window<-matrix(0,winsize,2)
    windows<-array(window,c(winsize,2,365,ys)) #array used to store all windows
    i=winsize-round(winsize/2,digits=0)
    i1=round(winsize/2,digits=0)
    for (k in 1:ys){
        for (j in 1:365){
            
            windows[,,j,k]<-dayt[(i-i1):(i+i1),]
            i=i+1}}
    
    exwin<-matrix(0,ms,3)
    exwin[,3]<-1:ys
    exwin[,3]<-mysort(exwin[,3],decreasing=F)
    assign("exwin",exwin,envir=.GlobalEnv)
    #indd<-exwin[exwin[,3]!=ys,3]
    exwins<-array(exwin,c(ms,3,365)) # array for bootstrap
    
    for (j in 1:365){
        for (i in 1:ys){
            exwins[exwins[,3,j]==i,1:2,j]<-windows[,,j,i]}}
    assign("exwins",exwins,envir=.GlobalEnv)
    
    for ( i in 1:365){
        ass<-exwins[,,i]
        ass1<-ass[,1]
        ass2<-ass[,2]
        kgb1<-length(ass1[is.na(ass1)])
        kgb2<-length(ass2[is.na(ass2)])
        if (kgb1>37.5 | kgb2>37.5) {flag=T;break}}#150*0.25=37.5
    
    assign("flag",flag,envir=.GlobalEnv)
    if (flag==T) tkmessageBox(message="More than 25% data missing, Exceedance rate, HWDI,CWDI will not be calculated!!")
    if (flag==T) return()
    for (i in 1:365){
        ass<-exwins[,,i]
        # if(i == 363) {
        # ttmp<-ms
        # assign("ttmp",ttmp,envir=.GlobalEnv)
        # }
        itmp<-percentile(ms,ass[,1],c(0.1,0.9))
        aas[i,"pcmax10"]<-itmp[1]-1e-5
        aas[i,"pcmax90"]<-itmp[2]+1e-5
        itmp<-percentile(ms,ass[,2],c(0.1,0.9))
        aas[i,"pcmin10"]<-itmp[1]-1e-5
        aas[i,"pcmin90"]<-itmp[2]+1e-5  }
    
    assign("aas",aas,envir=.GlobalEnv)# matrix to store 10 and 90 percentile
    # exceedance rate before 1961 and after 2000
    before<-dd[dd$year<startyear,]
    after<-dd[dd$year>endyear,]
    
    # dataframe store the before monthly exceedance rate
    ys1<-startyear-years;ys2<-yeare-endyear
    bmonex<-matrix(NA,ys1*12,6)
    dimnames(bmonex)<-list(NULL,c("year","month","tx10p","tx90p","tn10p","tn90p"))
    bmonex[,"month"]<-rep(1:12,ys1)
    bmonex[,"year"]<-years:(startyear-1)
    bmonex[,"year"]<-mysort(bmonex[,"year"],decreasing=F)
    bmonex<-as.data.frame(bmonex)
    
    # dataframe store the after monthly exceedance rate
    amonex<-matrix(NA,ys2*12,6)
    dimnames(amonex)<-list(NULL,c("year","month","tx10p","tx90p","tn10p","tn90p"))
    amonex[,"month"]<-rep(1:12,ys2)
    amonex[,"year"]<-(endyear+1):yeare
    amonex[,"year"]<-mysort(amonex[,"year"],decreasing=F)
    amonex<-as.data.frame(amonex)
    
    # dataframe store yearly exceedance rate (before and after)
    yearex<-c(years:(startyear-1));   txg10p<-rep(0,length(yearex))
    txg90p<-rep(0,length(yearex));    tng10p<-rep(0,length(yearex))
    tng90p<-rep(0,length(yearex))
    bd<-as.data.frame(cbind(yearex,txg10p,txg90p,tng10p,tng90p))
    colnames(bd)[1]<-"year"
    
    yearex<-c((endyear+1):yeare);     txg10p<-rep(0,length(yearex))
    txg90p<-rep(0,length(yearex));    tng10p<-rep(0,length(yearex))
    tng90p<-rep(0,length(yearex))
    ad<-as.data.frame(cbind(yearex,txg10p,txg90p,tng10p,tng90p))
    colnames(ad)[1]<-"year"
    
    year=years;jjj6=1
    for (i in 1:ys1){
        midvalue<-ddtem[ddtem$year==year,]
        exmax10<-midvalue[,4]-aas[,2]
        exmax10m1<-exmax10[1:31];      exmax10m2<-exmax10[32:59];    exmax10m3<-exmax10[60:90]
        exmax10m4<-exmax10[91:120];    exmax10m5<-exmax10[121:151];  exmax10m6<-exmax10[152:181]
        exmax10m7<-exmax10[182:212];   exmax10m8<-exmax10[213:243];  exmax10m9<-exmax10[244:273]
        exmax10m10<-exmax10[274:304];  exmax10m11<-exmax10[305:334]; exmax10m12<-exmax10[335:365]
        
        exmax90<-midvalue[,4]-aas[,3]
        exmax90m1<-exmax90[1:31];      exmax90m2<-exmax90[32:59];    exmax90m3<-exmax90[60:90]
        exmax90m4<-exmax90[91:120];    exmax90m5<-exmax90[121:151];  exmax90m6<-exmax90[152:181]
        exmax90m7<-exmax90[182:212];   exmax90m8<-exmax90[213:243];  exmax90m9<-exmax90[244:273]
        exmax90m10<-exmax90[274:304];  exmax90m11<-exmax90[305:334]; exmax90m12<-exmax90[335:365]
        
        exmin10<-midvalue[,5]-aas[,4]
        exmin10m1<-exmin10[1:31];      exmin10m2<-exmin10[32:59];    exmin10m3<-exmin10[60:90]
        exmin10m4<-exmin10[91:120];    exmin10m5<-exmin10[121:151];  exmin10m6<-exmin10[152:181]
        exmin10m7<-exmin10[182:212];   exmin10m8<-exmin10[213:243];  exmin10m9<-exmin10[244:273]
        exmin10m10<-exmin10[274:304];  exmin10m11<-exmin10[305:334]; exmin10m12<-exmin10[335:365]
        
        exmin90<-midvalue[,5]-aas[,5]
        exmin90m1<-exmin90[1:31];      exmin90m2<-exmin90[32:59];    exmin90m3<-exmin90[60:90]
        exmin90m4<-exmin90[91:120];    exmin90m5<-exmin90[121:151];  exmin90m6<-exmin90[152:181]
        exmin90m7<-exmin90[182:212];   exmin90m8<-exmin90[213:243];  exmin90m9<-exmin90[244:273]
        exmin90m10<-exmin90[274:304];  exmin90m11<-exmin90[305:334]; exmin90m12<-exmin90[335:365]
        
        bd[i,"txg10p"]<-length(exmax10[exmax10<0&is.na(exmax10)==F])
        bd[i,"txg90p"]<-length(exmax90[exmax90>0&is.na(exmax90)==F])
        bd[i,"tng10p"]<-length(exmin10[exmin10<0&is.na(exmin10)==F])
        bd[i,"tng90p"]<-length(exmin90[exmin90>0&is.na(exmin90)==F])
        
        bmonex[jjj6,"tx10p"]<-length(exmax10m1[exmax10m1<0&is.na(exmax10m1)==F])
        bmonex[jjj6,"tx90p"]<-length(exmax90m1[exmax90m1>0&is.na(exmax90m1)==F])
        bmonex[jjj6,"tn10p"]<-length(exmin10m1[exmin10m1<0&is.na(exmin10m1)==F])
        bmonex[jjj6,"tn90p"]<-length(exmin90m1[exmin90m1>0&is.na(exmin90m1)==F])
        
        bmonex[jjj6+1,"tx10p"]<-length(exmax10m2[exmax10m2<0&is.na(exmax10m2)==F])
        bmonex[jjj6+1,"tx90p"]<-length(exmax90m2[exmax90m2>0&is.na(exmax90m2)==F])
        bmonex[jjj6+1,"tn10p"]<-length(exmin10m2[exmin10m2<0&is.na(exmin10m2)==F])
        bmonex[jjj6+1,"tn90p"]<-length(exmin90m2[exmin90m2>0&is.na(exmin90m2)==F])   
        
        bmonex[jjj6+2,"tx10p"]<-length(exmax10m3[exmax10m3<0&is.na(exmax10m3)==F])
        bmonex[jjj6+2,"tx90p"]<-length(exmax90m3[exmax90m3>0&is.na(exmax90m3)==F])
        bmonex[jjj6+2,"tn10p"]<-length(exmin10m3[exmin10m3<0&is.na(exmin10m3)==F])
        bmonex[jjj6+2,"tn90p"]<-length(exmin90m3[exmin90m3>0&is.na(exmin90m3)==F])
        
        bmonex[jjj6+3,"tx10p"]<-length(exmax10m4[exmax10m4<0&is.na(exmax10m4)==F])
        bmonex[jjj6+3,"tx90p"]<-length(exmax90m4[exmax90m4>0&is.na(exmax90m4)==F])
        bmonex[jjj6+3,"tn10p"]<-length(exmin10m4[exmin10m4<0&is.na(exmin10m4)==F])
        bmonex[jjj6+3,"tn90p"]<-length(exmin90m4[exmin90m4>0&is.na(exmin90m4)==F])
        
        bmonex[jjj6+4,"tx10p"]<-length(exmax10m5[exmax10m5<0&is.na(exmax10m5)==F])
        bmonex[jjj6+4,"tx90p"]<-length(exmax90m5[exmax90m5>0&is.na(exmax90m5)==F])
        bmonex[jjj6+4,"tn10p"]<-length(exmin10m5[exmin10m5<0&is.na(exmin10m5)==F])
        bmonex[jjj6+4,"tn90p"]<-length(exmin90m5[exmin90m5>0&is.na(exmin90m5)==F])
        
        bmonex[jjj6+5,"tx10p"]<-length(exmax10m6[exmax10m6<0&is.na(exmax10m6)==F])
        bmonex[jjj6+5,"tx90p"]<-length(exmax90m6[exmax90m6>0&is.na(exmax90m6)==F])
        bmonex[jjj6+5,"tn10p"]<-length(exmin10m6[exmin10m6<0&is.na(exmin10m6)==F])
        bmonex[jjj6+5,"tn90p"]<-length(exmin90m6[exmin90m6>0&is.na(exmin90m6)==F])
        
        bmonex[jjj6+6,"tx10p"]<-length(exmax10m7[exmax10m7<0&is.na(exmax10m7)==F])
        bmonex[jjj6+6,"tx90p"]<-length(exmax90m7[exmax90m7>0&is.na(exmax90m7)==F])
        bmonex[jjj6+6,"tn10p"]<-length(exmin10m7[exmin10m7<0&is.na(exmin10m7)==F])
        bmonex[jjj6+6,"tn90p"]<-length(exmin90m7[exmin90m7>0&is.na(exmin90m7)==F])
        
        bmonex[jjj6+7,"tx10p"]<-length(exmax10m8[exmax10m8<0&is.na(exmax10m8)==F])
        bmonex[jjj6+7,"tx90p"]<-length(exmax90m8[exmax90m8>0&is.na(exmax90m8)==F])
        bmonex[jjj6+7,"tn10p"]<-length(exmin10m8[exmin10m8<0&is.na(exmin10m8)==F])
        bmonex[jjj6+7,"tn90p"]<-length(exmin90m8[exmin90m8>0&is.na(exmin90m8)==F])
        
        bmonex[jjj6+8,"tx10p"]<-length(exmax10m9[exmax10m9<0&is.na(exmax10m9)==F])
        bmonex[jjj6+8,"tx90p"]<-length(exmax90m9[exmax90m9>0&is.na(exmax90m9)==F])
        bmonex[jjj6+8,"tn10p"]<-length(exmin10m9[exmin10m9<0&is.na(exmin10m9)==F])
        bmonex[jjj6+8,"tn90p"]<-length(exmin90m9[exmin90m9>0&is.na(exmin90m9)==F])
        
        bmonex[jjj6+9,"tx10p"]<-length(exmax10m10[exmax10m10<0&is.na(exmax10m10)==F])
        bmonex[jjj6+9,"tx90p"]<-length(exmax90m10[exmax90m10>0&is.na(exmax90m10)==F])
        bmonex[jjj6+9,"tn10p"]<-length(exmin10m10[exmin10m10<0&is.na(exmin10m10)==F])
        bmonex[jjj6+9,"tn90p"]<-length(exmin90m10[exmin90m10>0&is.na(exmin90m10)==F])
        
        bmonex[jjj6+10,"tx10p"]<-length(exmax10m11[exmax10m11<0&is.na(exmax10m11)==F])
        bmonex[jjj6+10,"tx90p"]<-length(exmax90m11[exmax90m11>0&is.na(exmax90m11)==F])
        bmonex[jjj6+10,"tn10p"]<-length(exmin10m11[exmin10m11<0&is.na(exmin10m11)==F])
        bmonex[jjj6+10,"tn90p"]<-length(exmin90m11[exmin90m11>0&is.na(exmin90m11)==F])
        
        bmonex[jjj6+11,"tx10p"]<-length(exmax10m12[exmax10m12<0&is.na(exmax10m12)==F])
        bmonex[jjj6+11,"tx90p"]<-length(exmax90m12[exmax90m12>0&is.na(exmax90m12)==F])
        bmonex[jjj6+11,"tn10p"]<-length(exmin10m12[exmin10m12<0&is.na(exmin10m12)==F])
        bmonex[jjj6+11,"tn90p"]<-length(exmin90m12[exmin90m12>0&is.na(exmin90m12)==F])
        
        if(leapyear(year)){
            if(dd[dd$year==year&dd$month==2&dd$day==29,"tmax"]>aas[59,"pcmax90"]&is.na(dd[dd$year==year&dd$month==2&dd$day==29,"tmax"])==F&is.na(aas[59,"pcmax90"])==F)
                bmonex[jjj6+1,"tx90p"]<-bmonex[jjj6+1,"tx90p"]+1
            if(dd[dd$year==year&dd$month==2&dd$day==29,"tmax"]<aas[59,"pcmax10"]&is.na(dd[dd$year==year&dd$month==2&dd$day==29,"tmax"])==F&is.na(aas[59,"pcmax10"])==F)
                bmonex[jjj6+1,"tx10p"]<-bmonex[jjj6+1,"tx10p"]+1
            if(dd[dd$year==year&dd$month==2&dd$day==29,"tmin"]>aas[59,"pcmin90"]&is.na(dd[dd$year==year&dd$month==2&dd$day==29,"tmin"])==F&is.na(aas[59,"pcmin90"])==F)
                bmonex[jjj6+1,"tn90p"]<-bmonex[jjj6+1,"tn90p"]+1
            if(dd[dd$year==year&dd$month==2&dd$day==29,"tmin"]<aas[59,"pcmin10"]&is.na(dd[dd$year==year&dd$month==2&dd$day==29,"tmin"])==F&is.na(aas[59,"pcmin10"])==F)
                bmonex[jjj6+1,"tn10p"]<-bmonex[jjj6+1,"tn10p"]+1
        }
        
        jjj6<-jjj6+12
        year=year+1     
    }
    
    year=endyear+1;jjj6=1
    for (i in 1:ys2){
        midvalue<-ddtem[ddtem$year==year,]
        exmax10<-midvalue[,4]-aas[,2]
        exmax10m1<-exmax10[1:31];     exmax10m2<-exmax10[32:59];    exmax10m3<-exmax10[60:90]
        exmax10m4<-exmax10[91:120];   exmax10m5<-exmax10[121:151];  exmax10m6<-exmax10[152:181]
        exmax10m7<-exmax10[182:212];  exmax10m8<-exmax10[213:243];  exmax10m9<-exmax10[244:273]
        exmax10m10<-exmax10[274:304]; exmax10m11<-exmax10[305:334]; exmax10m12<-exmax10[335:365]
        
        exmax90<-midvalue[,4]-aas[,3]
        exmax90m1<-exmax90[1:31];     exmax90m2<-exmax90[32:59];    exmax90m3<-exmax90[60:90]
        exmax90m4<-exmax90[91:120];   exmax90m5<-exmax90[121:151];  exmax90m6<-exmax90[152:181]
        exmax90m7<-exmax90[182:212];  exmax90m8<-exmax90[213:243];  exmax90m9<-exmax90[244:273]
        exmax90m10<-exmax90[274:304]; exmax90m11<-exmax90[305:334]; exmax90m12<-exmax90[335:365]
        
        exmin10<-midvalue[,5]-aas[,4]
        exmin10m1<-exmin10[1:31];     exmin10m2<-exmin10[32:59];    exmin10m3<-exmin10[60:90]
        exmin10m4<-exmin10[91:120];   exmin10m5<-exmin10[121:151];  exmin10m6<-exmin10[152:181]
        exmin10m7<-exmin10[182:212];  exmin10m8<-exmin10[213:243];  exmin10m9<-exmin10[244:273]
        exmin10m10<-exmin10[274:304]; exmin10m11<-exmin10[305:334]; exmin10m12<-exmin10[335:365]
        
        exmin90<-midvalue[,5]-aas[,5]
        exmin90m1<-exmin90[1:31];     exmin90m2<-exmin90[32:59];    exmin90m3<-exmin90[60:90]
        exmin90m4<-exmin90[91:120];   exmin90m5<-exmin90[121:151];  exmin90m6<-exmin90[152:181]
        exmin90m7<-exmin90[182:212];  exmin90m8<-exmin90[213:243];  exmin90m9<-exmin90[244:273]
        exmin90m10<-exmin90[274:304]; exmin90m11<-exmin90[305:334]; exmin90m12<-exmin90[335:365]
        
        ad[i,"txg10p"]<-length(exmax10[exmax10<0&is.na(exmax10)==F])
        ad[i,"txg90p"]<-length(exmax90[exmax90>0&is.na(exmax90)==F])
        ad[i,"tng10p"]<-length(exmin10[exmin10<0&is.na(exmin10)==F])
        ad[i,"tng90p"]<-length(exmin90[exmin90>0&is.na(exmin90)==F])
        
        amonex[jjj6,"tx10p"]<-length(exmax10m1[exmax10m1<0&is.na(exmax10m1)==F])
        amonex[jjj6,"tx90p"]<-length(exmax90m1[exmax90m1>0&is.na(exmax90m1)==F])
        amonex[jjj6,"tn10p"]<-length(exmin10m1[exmin10m1<0&is.na(exmin10m1)==F])
        amonex[jjj6,"tn90p"]<-length(exmin90m1[exmin90m1>0&is.na(exmin90m1)==F])
        
        amonex[jjj6+1,"tx10p"]<-length(exmax10m2[exmax10m2<0&is.na(exmax10m2)==F])
        amonex[jjj6+1,"tx90p"]<-length(exmax90m2[exmax90m2>0&is.na(exmax90m2)==F])
        amonex[jjj6+1,"tn10p"]<-length(exmin10m2[exmin10m2<0&is.na(exmin10m2)==F])
        amonex[jjj6+1,"tn90p"]<-length(exmin90m2[exmin90m2>0&is.na(exmin90m2)==F])   
        
        amonex[jjj6+2,"tx10p"]<-length(exmax10m3[exmax10m3<0&is.na(exmax10m3)==F])
        amonex[jjj6+2,"tx90p"]<-length(exmax90m3[exmax90m3>0&is.na(exmax90m3)==F])
        amonex[jjj6+2,"tn10p"]<-length(exmin10m3[exmin10m3<0&is.na(exmin10m3)==F])
        amonex[jjj6+2,"tn90p"]<-length(exmin90m3[exmin90m3>0&is.na(exmin90m3)==F])
        
        amonex[jjj6+3,"tx10p"]<-length(exmax10m4[exmax10m4<0&is.na(exmax10m4)==F])
        amonex[jjj6+3,"tx90p"]<-length(exmax90m4[exmax90m4>0&is.na(exmax90m4)==F])
        amonex[jjj6+3,"tn10p"]<-length(exmin10m4[exmin10m4<0&is.na(exmin10m4)==F])
        amonex[jjj6+3,"tn90p"]<-length(exmin90m4[exmin90m4>0&is.na(exmin90m4)==F])
        
        amonex[jjj6+4,"tx10p"]<-length(exmax10m5[exmax10m5<0&is.na(exmax10m5)==F])
        amonex[jjj6+4,"tx90p"]<-length(exmax90m5[exmax90m5>0&is.na(exmax90m5)==F])
        amonex[jjj6+4,"tn10p"]<-length(exmin10m5[exmin10m5<0&is.na(exmin10m5)==F])
        amonex[jjj6+4,"tn90p"]<-length(exmin90m5[exmin90m5>0&is.na(exmin90m5)==F])
        
        amonex[jjj6+5,"tx10p"]<-length(exmax10m6[exmax10m6<0&is.na(exmax10m6)==F])
        amonex[jjj6+5,"tx90p"]<-length(exmax90m6[exmax90m6>0&is.na(exmax90m6)==F])
        amonex[jjj6+5,"tn10p"]<-length(exmin10m6[exmin10m6<0&is.na(exmin10m6)==F])
        amonex[jjj6+5,"tn90p"]<-length(exmin90m6[exmin90m6>0&is.na(exmin90m6)==F])
        
        amonex[jjj6+6,"tx10p"]<-length(exmax10m7[exmax10m7<0&is.na(exmax10m7)==F])
        amonex[jjj6+6,"tx90p"]<-length(exmax90m7[exmax90m7>0&is.na(exmax90m7)==F])
        amonex[jjj6+6,"tn10p"]<-length(exmin10m7[exmin10m7<0&is.na(exmin10m7)==F])
        amonex[jjj6+6,"tn90p"]<-length(exmin90m7[exmin90m7>0&is.na(exmin90m7)==F])
        
        amonex[jjj6+7,"tx10p"]<-length(exmax10m8[exmax10m8<0&is.na(exmax10m8)==F])
        amonex[jjj6+7,"tx90p"]<-length(exmax90m8[exmax90m8>0&is.na(exmax90m8)==F])
        amonex[jjj6+7,"tn10p"]<-length(exmin10m8[exmin10m8<0&is.na(exmin10m8)==F])
        amonex[jjj6+7,"tn90p"]<-length(exmin90m8[exmin90m8>0&is.na(exmin90m8)==F])
        
        amonex[jjj6+8,"tx10p"]<-length(exmax10m9[exmax10m9<0&is.na(exmax10m9)==F])
        amonex[jjj6+8,"tx90p"]<-length(exmax90m9[exmax90m9>0&is.na(exmax90m9)==F])
        amonex[jjj6+8,"tn10p"]<-length(exmin10m9[exmin10m9<0&is.na(exmin10m9)==F])
        amonex[jjj6+8,"tn90p"]<-length(exmin90m9[exmin90m9>0&is.na(exmin90m9)==F])
        
        amonex[jjj6+9,"tx10p"]<-length(exmax10m10[exmax10m10<0&is.na(exmax10m10)==F])
        amonex[jjj6+9,"tx90p"]<-length(exmax90m10[exmax90m10>0&is.na(exmax90m10)==F])
        amonex[jjj6+9,"tn10p"]<-length(exmin10m10[exmin10m10<0&is.na(exmin10m10)==F])
        amonex[jjj6+9,"tn90p"]<-length(exmin90m10[exmin90m10>0&is.na(exmin90m10)==F])
        
        amonex[jjj6+10,"tx10p"]<-length(exmax10m11[exmax10m11<0&is.na(exmax10m11)==F])
        amonex[jjj6+10,"tx90p"]<-length(exmax90m11[exmax90m11>0&is.na(exmax90m11)==F])
        amonex[jjj6+10,"tn10p"]<-length(exmin10m11[exmin10m11<0&is.na(exmin10m11)==F])
        amonex[jjj6+10,"tn90p"]<-length(exmin90m11[exmin90m11>0&is.na(exmin90m11)==F])
        
        amonex[jjj6+11,"tx10p"]<-length(exmax10m12[exmax10m12<0&is.na(exmax10m12)==F])
        amonex[jjj6+11,"tx90p"]<-length(exmax90m12[exmax90m12>0&is.na(exmax90m12)==F])
        amonex[jjj6+11,"tn10p"]<-length(exmin10m12[exmin10m12<0&is.na(exmin10m12)==F])
        amonex[jjj6+11,"tn90p"]<-length(exmin90m12[exmin90m12>0&is.na(exmin90m12)==F])
        
        if(leapyear(year)){
            if(dd[dd$year==year&dd$month==2&dd$day==29,"tmax"]>aas[59,"pcmax90"]&is.na(dd[dd$year==year&dd$month==2&dd$day==29,"tmax"])==F&is.na(aas[59,"pcmax90"])==F)
                amonex[jjj6+1,"tx90p"]<-amonex[jjj6+1,"tx90p"]+1
            if(dd[dd$year==year&dd$month==2&dd$day==29,"tmax"]<aas[59,"pcmax10"]&is.na(dd[dd$year==year&dd$month==2&dd$day==29,"tmax"])==F&is.na(aas[59,"pcmax10"])==F)
                amonex[jjj6+1,"tx10p"]<-amonex[jjj6+1,"tx10p"]+1
            if(dd[dd$year==year&dd$month==2&dd$day==29,"tmin"]>aas[59,"pcmin90"]&is.na(dd[dd$year==year&dd$month==2&dd$day==29,"tmin"])==F&is.na(aas[59,"pcmin90"])==F)
                amonex[jjj6+1,"tn90p"]<-amonex[jjj6+1,"tn90p"]+1
            if(dd[dd$year==year&dd$month==2&dd$day==29,"tmin"]<aas[59,"pcmin10"]&is.na(dd[dd$year==year&dd$month==2&dd$day==29,"tmin"])==F&is.na(aas[59,"pcmin10"])==F)
                amonex[jjj6+1,"tn10p"]<-amonex[jjj6+1,"tn10p"]+1
        }
        
        jjj6<-jjj6+12
        year=year+1   }
    bdm<-merge(bmonex,bd,by="year");  assign("bdm",bdm,envir=.GlobalEnv)
    adm<-merge(amonex,ad,by="year");  assign("adm",adm,envir=.GlobalEnv)
    
} # end of nordaytem1 function
#----------- nordaytem1 ends -----------------------------------------

#----------- nordaytem -----------------------------------------
nordaytem<-function(){
    nam1<-paste(nama,"_DAYNOR.csv",sep="")
    write.table(daynor,file=nam1,append=F,quote=F,sep=", ",row.names=F)
}
#----------- nordaytem ends -----------------------------------------

#----------- dtr -----------------------------------------
dtr<-function(){# day temperature range(monthly average) 
    len<-yeare-years+1
    aa1<-matrix(NA,12*len,3)
    dimnames(aa1)<-list(NULL,c("year","month","dtr"))
    aa1[,"year"]<-years:yeare
    aa1[,"year"]<-mysort(aa1[,"year"],decreasing=F)
    aa1[,"month"]<-1:12
    temrange<-dd[,"tmax"]-dd[,"tmin"]
    temrange<-cbind(dd[,1:2],temrange)
    jjj1<-1
    for (year in years:yeare){    # start year loop
        temrange1<-temrange[temrange$year==year,]
        temrangem1<-temrange1[temrange1$month==1,"temrange"]
        temrangem2<-temrange1[temrange1$month==2,"temrange"]
        temrangem3<-temrange1[temrange1$month==3,"temrange"]
        temrangem4<-temrange1[temrange1$month==4,"temrange"]
        temrangem5<-temrange1[temrange1$month==5,"temrange"]
        temrangem6<-temrange1[temrange1$month==6,"temrange"]
        temrangem7<-temrange1[temrange1$month==7,"temrange"]
        temrangem8<-temrange1[temrange1$month==8,"temrange"]
        temrangem9<-temrange1[temrange1$month==9,"temrange"]
        temrangem10<-temrange1[temrange1$month==10,"temrange"]
        temrangem11<-temrange1[temrange1$month==11,"temrange"]
        temrangem12<-temrange1[temrange1$month==12,"temrange"]
        aa1[jjj1,3]<-mean(temrangem1,na.rm=T);     aa1[jjj1+1,3]<-mean(temrangem2,na.rm=T)
        aa1[jjj1+2,3]<-mean(temrangem3,na.rm=T);   aa1[jjj1+3,3]<-mean(temrangem4,na.rm=T)
        aa1[jjj1+4,3]<-mean(temrangem5,na.rm=T);   aa1[jjj1+5,3]<-mean(temrangem6,na.rm=T)
        aa1[jjj1+6,3]<-mean(temrangem7,na.rm=T);   aa1[jjj1+7,3]<-mean(temrangem8,na.rm=T)
        aa1[jjj1+8,3]<-mean(temrangem9,na.rm=T);   aa1[jjj1+9,3]<-mean(temrangem10,na.rm=T)
        aa1[jjj1+10,3]<-mean(temrangem11,na.rm=T); aa1[jjj1+11,3]<-mean(temrangem12,na.rm=T)
        jjj1<-jjj1+12}               #end of year loop
    
    aa1[,"dtr"]<-aa1[,"dtr"]+nacor[,"mnatma>3"]+nacor[,"mnatmi>3"]
    ofile<-matrix(0,len,14)
    dimnames(ofile)<-list(NULL,c("year","jan","feb","mar","apr","may","jun","jul","aug","sep","oct","nov","dec","annual"))
    ofile<-as.data.frame(ofile)
    for(j in years:yeare){
        k<-j-years+1
        ofile[k,1]<-j
        ofile[k,2:13]<-round(aa1[aa1[,"year"]==j,"dtr"],digit=2)
        ofile[k,14]<-round(mean(t(ofile[k,2:13]),na.rm=T),digit=2)
    }
    ofile[,14]<-ofile[,14]+ynacor[,"ynatma>15"]+ynacor[,"ynatmi>15"]
    nam1<-paste(outinddir,paste(ofilename,"_DTR.csv",sep=""),sep="/")
    write.table(ofile,file=nam1,append=F,quote=F,sep=", ",na="-99.9",row.names=F)
    
    namt<-paste(outtrddir,paste(ofilename,"_trend.csv",sep=""),sep="/")
    if(sum(is.na(ofile[,14]))>=(yeare-years+1-10)){
        betahat<-NA
        betastd<-NA
        pvalue<-NA
    }
    else{
        fit1<-lsfit(ofile[,1],ofile[,14])
        out1<-ls.print(fit1,print.it=F)
        pvalue<-round(as.numeric(out1$summary[1,6]),3)
        betahat<-round(as.numeric(out1$coef.table[[1]][2,1]),3)
        betastd<-round(as.numeric(out1$coef.table[[1]][2,2]),3)
    }
    cat(file=namt,paste(latitude,longitude,"dtr",years,yeare,betahat,betastd,pvalue,sep=","),fill=180,append=T)
    
    nam2<-paste(outjpgdir,paste(ofilename,"_DTR.jpg",sep=""),sep="/")
    jpeg(nam2,width=1024,height=768)
    plotx(ofile[,1],ofile[,14],main=paste("DTR",ofilename,sep="   "),xlab="Year",ylab="DTR")
    dev.off()
} # end of dtr
#----------- dtr ends -----------------------------------------

#----------- daysprcp10 -----------------------------------------  
daysprcp10<-function(){
    ys<-yeare-years+1
    R10<-rep(0,ys)
    yearss<-c(years:yeare)
    target<-as.data.frame(cbind(yearss,R10))
    for (year in years:yeare){
        mid<-dd[dd$year==year,"prcp"]
        mid<-mid[is.na(mid)==F]
        target[target$yearss==year,"R10"]<-length(mid[mid>=10])}
    dimnames(target)[[2]][1]<-"year"
    target[,"R10"]<-target[,"R10"]+ynacor[,"ynapr>15"]
    nam1<-paste(outinddir,paste(ofilename,"_R10mm.csv",sep=""),sep="/")
    write.table(target,file=nam1,append=F,quote=F,sep=", ",na="-99.9",row.names=F)
    
    namt<-paste(outtrddir,paste(ofilename,"_trend.csv",sep=""),sep="/")
    if(sum(is.na(target[,"R10"]))>=(yeare-years+1-10)){
        betahat<-NA
        betastd<-NA
        pvalue<-NA
    }
    else{
        fit1<-lsfit(target[,1],target[,"R10"])
        out1<-ls.print(fit1,print.it=F)
        pvalue<-round(as.numeric(out1$summary[1,6]),3)
        betahat<-round(as.numeric(out1$coef.table[[1]][2,1]),3)
        betastd<-round(as.numeric(out1$coef.table[[1]][2,2]),3)
    }
    cat(file=namt,paste(latitude,longitude,"r10mm",years,yeare,betahat,betastd,pvalue,sep=","),fill=180,append=T)
    
    nam2<-paste(outjpgdir,paste(ofilename,"_R10mm.jpg",sep=""),sep="/")
    jpeg(nam2,width=1024,height=768)
    plotx(target[,1],target[,2],main=paste("R10mm",ofilename,sep="   "),xlab="Year",ylab="R10mm")
    dev.off()
}
#----------- daysprcp10 ends -----------------------------------------

#----------- extremedays -----------------------------------------  
extremedays<-function(opt=0){
    if(opt==0){
        euu=uu
        eul=ul
        elu=lu
        ell=ll
    }
    else{
        euu=uuu
        eul=uul
        elu=ulu
        ell=ull
    }
    ys<-yeare-years+1
    #  beginyear<-dd[1,1]
    #  endyear<-dd[dim(dd)[1],1]
    tclext<-c(years:yeare)
    su<-rep(0,ys)
    id<-su
    tr<-su
    fd<-su
    tclext<-cbind(tclext,su,id,tr,fd)
    dimnames(tclext)[[2]][1]<-"year"
    i=1
    for (year in years:yeare) {
        mid1<-dd[dd$year==year,"tmax"];  mid1<-mid1[is.na(mid1)==F]
        mid2<-dd[dd$year==year,"tmin"];  mid2<-mid2[is.na(mid2)==F]
        tclext[i,"su"]<-length(mid1[mid1>euu])
        tclext[i,"id"]<-length(mid1[mid1<eul])
        tclext[i,"tr"]<-length(mid2[mid2>elu])
        tclext[i,"fd"]<-length(mid2[mid2<ell])
        i<-i+1} #for end    
    tclext<-as.data.frame(tclext)
    tclext[,"su"]<-tclext[,"su"]+ynacor[,"ynatma>15"]
    tclext[,"id"]<-tclext[,"id"]+ynacor[,"ynatma>15"]
    tclext[,"tr"]<-tclext[,"tr"]+ynacor[,"ynatmi>15"]
    tclext[,"fd"]<-tclext[,"fd"]+ynacor[,"ynatmi>15"]
    #    assign("extdays",tclext,envir=.GlobalEnv)
    if(opt==0){
        nam1<-paste(outinddir,paste(ofilename,"_SU25.csv",sep=""),sep="/")
        nam2<-paste(outinddir,paste(ofilename,"_ID0.csv",sep=""),sep="/")
        nam3<-paste(outinddir,paste(ofilename,"_TR20.csv",sep=""),sep="/")
        nam4<-paste(outinddir,paste(ofilename,"_FD0.csv",sep=""),sep="/")
    }
    else{
        nam1<-paste(outinddir,paste(ofilename,"_SU",as.character(euu),".csv",sep=""),sep="/")
        nam2<-paste(outinddir,paste(ofilename,"_ID",as.character(eul),".csv",sep=""),sep="/")
        nam3<-paste(outinddir,paste(ofilename,"_TR",as.character(elu),".csv",sep=""),sep="/")
        nam4<-paste(outinddir,paste(ofilename,"_FD",as.character(ell),".csv",sep=""),sep="/")
    }
    
    write.table(tclext[,c("year","su")],file=nam1,append=F,quote=F,sep=", ",na="-99.9",row.names=F)
    write.table(tclext[,c("year","id")],file=nam2,append=F,quote=F,sep=", ",na="-99.9",row.names=F)
    write.table(tclext[,c("year","tr")],file=nam3,append=F,quote=F,sep=", ",na="-99.9",row.names=F)
    write.table(tclext[,c("year","fd")],file=nam4,append=F,quote=F,sep=", ",na="-99.9",row.names=F)
    
    # output trend base on annual indicies data
    namt<-paste(outtrddir,paste(ofilename,"_trend.csv",sep=""),sep="/")
    for( i in c("su","id","tr","fd")){
        if(sum(is.na(tclext[,i]))>=(yeare-years+1-10)){
            betahat<-NA
            betastd<-NA
            pvalue<-NA
        }
        else{
            fit1<-lsfit(tclext[,"year"],tclext[,i])
            out1<-ls.print(fit1,print.it=F)
            pvalue<-round(as.numeric(out1$summary[1,6]),3)
            betahat<-round(as.numeric(out1$coef.table[[1]][2,1]),3)
            betastd<-round(as.numeric(out1$coef.table[[1]][2,2]),3)
        }
        if(opt==0){
            if(i=="su") ii<-"su25"
            if(i=="id") ii<-"id0"
            if(i=="fd") ii<-"fd0"
            if(i=="tr") ii<-"tr20"
        }
        else{
            if(i=="su") ii<-paste("su",as.character(euu),sep="")
            if(i=="id") ii<-paste("id",as.character(eul),sep="")
            if(i=="tr") ii<-paste("tr",as.character(elu),sep="")
            if(i=="fd") ii<-paste("fd",as.character(ell),sep="")
        }
        cat(file=namt,paste(latitude,longitude,ii,years,yeare,betahat,betastd,pvalue,sep=","),fill=180,append=T)
    }
    
    namp<-c("","","","")
    if(opt==0){
        namp[1]<-paste(outjpgdir,paste(ofilename,"_SU25.jpg",sep=""),sep="/")
        namp[2]<-paste(outjpgdir,paste(ofilename,"_ID0.jpg",sep=""),sep="/")
        namp[3]<-paste(outjpgdir,paste(ofilename,"_TR20.jpg",sep=""),sep="/")
        namp[4]<-paste(outjpgdir,paste(ofilename,"_FD0.jpg",sep=""),sep="/")
    }
    else{
        namp[1]<-paste(outjpgdir,paste(ofilename,"_SU",as.character(euu),".jpg",sep=""),sep="/")
        namp[2]<-paste(outjpgdir,paste(ofilename,"_ID",as.character(eul),".jpg",sep=""),sep="/")
        namp[3]<-paste(outjpgdir,paste(ofilename,"_TR",as.character(elu),".jpg",sep=""),sep="/")
        namp[4]<-paste(outjpgdir,paste(ofilename,"_FD",as.character(ell),".jpg",sep=""),sep="/")
    }
    if(opt==0) ylab<-c("SU25","ID0","TR20","FD0")
    else ylab<-c(paste("SU",as.character(euu),sep=""), 
                 paste("ID",as.character(eul),sep=""), 
                 paste("TR",as.character(elu),sep=""), 
                 paste("FD",as.character(ell),sep=""))
    
    xlab<-rep("year",4)
    for(i in 1:4){
        title1[i]<-paste(ylab[i],ofilename,sep="   ")
        jpeg(file=namp[i],width=1024,height=768)
        plotx(tclext[,1],tclext[,i+1],main=title1[i],ylab=ylab[i],xlab="Year")
        dev.off()
    }
}
#----------- extremedays ends -----------------------------------------  

#----------- exceedance -----------------------------------------  
exceedance<-function(){
    if (flag==T) return()
    a<-1:365
    ys<-endyear-startyear+1;yss<-ys-1
    mondays<-c(31,28,31,30,31,30,31,31,30,31,30,31)
    mone<-rep(0,12);mons<-mone
    for(i in 1:12) mone[i]<-sum(mondays[1:i])
    mons[1]<-1
    for(i in 2:12) mons[i]<-mone[i-1]+1
    
    monex<-matrix(NA,ys*12,6)
    dimnames(monex)<-list(NULL,c("year","month","tx10p","tx90p","tn10p","tn90p"))
    monex[,"month"]<-rep(1:12,ys)
    monex[,"year"]<-startyear:endyear
    monex[,"year"]<-mysort(monex[,"year"],decreasing=F)
    monex<-as.data.frame(monex)
    
    
    b<-matrix(0,365,4)
    a<-cbind(a,b)
    aa<-array(a,c(365,5,ys))
    dimnames(aa)<-list(NULL,c("day","pcmax10","pcmax90","pcmin10","pcmin90"),NULL)
    ms<-winsize*ys
    i=winsize-round(winsize/2,digits=0)
    i1=round(winsize/2,digits=0)
    
    #  daynorm2<-daynorm1[-(1:i1),] # daynorm2 is total base period normalized data
    daynorm2<-dd[dd$year>=startyear,]
    daynorm2<-daynorm2[daynorm2$year<=endyear,]
    daynorm2<-daynorm2[daynorm2$month!=2|daynorm2$day!=29,]
    daynorm2<-daynorm2[,-4]
    #  i2<-dim(daynorm2)[1]
    #  i3<-i2-i1+1
    #  daynorm2<-daynorm2[-(i3:i2),]
    
    yearex<-c(startyear:endyear);   txg10p<-rep(0,length(yearex))
    txg90p<-rep(0,length(yearex));  tng10p<-rep(0,length(yearex))
    tng90p<-rep(0,length(yearex))
    d<-as.data.frame(cbind(yearex,txg10p,txg90p,tng10p,tng90p))
    colnames(d)[1]<-"year"
    
    monex<-matrix(0,ys*12,6)
    dimnames(monex)<-list(NULL,c("year","month","tx10p","tx90p","tn10p","tn90p"))
    monex[,"month"]<-rep(1:12,ys)
    monex[,"year"]<-startyear:endyear
    monex[,"year"]<-mysort(monex[,"year"],decreasing=F)
    monex<-as.data.frame(monex)
    
    ratecount<-matrix(0,365,4)
    dimnames(ratecount)<-list(NULL,c("pcmax10","pcmax90","pcmin10","pcmin90"))
    
    for (year in startyear:endyear){ # year loop start
        
        midvalue<-daynorm2[daynorm2$year==year,]
        zz=year-startpoint #index in base period, say, zzth year
        
        indd<-exwin[exwin[,3]!=ys,3]
        
        for (k in 1:(ys-1)){ # for k (boot strap) start
            
            for (i in 1:365){ # day loop start
                ppc<-exwins[,,i]
                ppc<-ppc[ppc[,3]!=zz,]
                ppc<-ppc[,-3]
                
                ppc<-cbind(ppc,indd)
                
                ppcc<-rbind(ppc[ppc[,"indd"]==k,],ppc)
                itmp<-percentile(ms,ppcc[,1],c(0.1,0.9))
                aa[i,"pcmax10",zz]<-itmp[1]-1e-5
                aa[i,"pcmax90",zz]<-itmp[2]+1e-5
                itmp<-percentile(ms,ppcc[,2],c(0.1,0.9))
                aa[i,"pcmin10",zz]<-itmp[1]-1e-5
                aa[i,"pcmin90",zz]<-itmp[2]+1e-5
            }
            ratecount[,"pcmax10"]<-midvalue[,"tmax"]-aa[,"pcmax10",zz]
            ratecount[,"pcmax90"]<-midvalue[,"tmax"]-aa[,"pcmax90",zz]
            ratecount[,"pcmin10"]<-midvalue[,"tmin"]-aa[,"pcmin10",zz]
            ratecount[,"pcmin90"]<-midvalue[,"tmin"]-aa[,"pcmin90",zz]
            for(mon in 1:12){
                tmptx10p<-ratecount[mons[mon]:mone[mon],"pcmax10"]
                tmptx90p<-ratecount[mons[mon]:mone[mon],"pcmax90"]
                tmptn10p<-ratecount[mons[mon]:mone[mon],"pcmin10"]
                tmptn90p<-ratecount[mons[mon]:mone[mon],"pcmin90"]
                monex[(zz-1)*12+mon,"tx10p"]<- monex[(zz-1)*12+mon,"tx10p"]+length(tmptx10p[tmptx10p<0&is.na(tmptx10p)==F])
                monex[(zz-1)*12+mon,"tx90p"]<- monex[(zz-1)*12+mon,"tx90p"]+length(tmptx90p[tmptx90p>0&is.na(tmptx90p)==F])
                monex[(zz-1)*12+mon,"tn10p"]<- monex[(zz-1)*12+mon,"tn10p"]+length(tmptn10p[tmptn10p<0&is.na(tmptn10p)==F])
                monex[(zz-1)*12+mon,"tn90p"]<- monex[(zz-1)*12+mon,"tn90p"]+length(tmptn90p[tmptn90p>0&is.na(tmptn90p)==F])
                if(leapyear(year)&mon==2){
                    if(dd[dd$year==year&dd$month==2&dd$day==29,"tmax"]>aa[59,"pcmax90",zz]&is.na(dd[dd$year==year&dd$month==2&dd$day==29,"tmax"])==F&is.na(aa[58,"pcmax90",zz])==F)
                        monex[(zz-1)*12+mon,"tx90p"]<-monex[(zz-1)*12+mon,"tx90p"]+1
                    if(dd[dd$year==year&dd$month==2&dd$day==29,"tmax"]<aa[59,"pcmax10",zz]&is.na(dd[dd$year==year&dd$month==2&dd$day==29,"tmax"])==F&is.na(aa[58,"pcmax10",zz])==F)
                        monex[(zz-1)*12+mon,"tx10p"]<-monex[(zz-1)*12+mon,"tx10p"]+1
                    if(dd[dd$year==year&dd$month==2&dd$day==29,"tmin"]>aa[59,"pcmin90",zz]&is.na(dd[dd$year==year&dd$month==2&dd$day==29,"tmin"])==F&is.na(aa[58,"pcmin90",zz])==F)
                        monex[(zz-1)*12+mon,"tn90p"]<-monex[(zz-1)*12+mon,"tn90p"]+1
                    if(dd[dd$year==year&dd$month==2&dd$day==29,"tmin"]<aa[59,"pcmin10",zz]&is.na(dd[dd$year==year&dd$month==2&dd$day==29,"tmin"])==F&is.na(aa[58,"pcmin10",zz])==F)
                        monex[(zz-1)*12+mon,"tn10p"]<-monex[(zz-1)*12+mon,"tn10p"]+1
                } #if end
            } #for mon end
        } #for k (boot strap) end
    }# for year (from startyear to endyear) end
    
    monex[,"tx10p"]<-monex[,"tx10p"]/29.
    monex[,"tx90p"]<-monex[,"tx90p"]/29.
    monex[,"tn10p"]<-monex[,"tn10p"]/29.
    monex[,"tn90p"]<-monex[,"tn90p"]/29.
    #  monex<-rbind(bdm,monex,adm)
    
    #  assign("dm",dm,envir=.GlobalEnv)
    
    dm<-merge(monex,d,by="year")
    dm<-rbind(bdm,dm,adm)
    
    len<-yeare-years+1
    for(i in c("tx10p","tx90p","tn10p","tn90p")){
        if (i=="tx10p") {ii<-"_TX10P.csv";   kk<-3;nastat=7}#natma
        if (i=="tx90p") {ii<-"_TX90P.csv";   kk<-4;nastat=7}#natma
        if (i=="tn10p") {ii<-"_TN10P.csv";   kk<-5;nastat=8}#natmi
        if (i=="tn90p") {ii<-"_TN90P.csv";   kk<-6;nastat=8}#natmi
        
        nam1<-paste(outinddir,paste(ofilename,ii,sep=""),sep="/")
        ofile<-matrix(0,len,14)
        dimnames(ofile)<-list(NULL,c("year","jan","feb","mar","apr","may","jun","jul","aug","sep","oct","nov","dec","annual"))
        ofile<-as.data.frame(ofile)
        for(j in years:yeare){
            if(leapyear(j)) fulldays<-c(31,29,31,30,31,30,31,31,30,31,30,31)
            else fulldays<-c(31,28,31,30,31,30,31,31,30,31,30,31)
            k<-j-years+1
            ofile[k,1]<-j
            ofile[k,2:13]<-dm[dm$year==j,kk]
            for(mon in 1:12){
                if(nastatistic[(k-1)*12+mon,nastat]>10) ofile[k,(mon+1)]<-NA
                else   ofile[k,(mon+1)]<-dm[(k-1)*12+mon,kk]*fulldays[mon]/(fulldays[mon]-nastatistic[(k-1)*12+mon,nastat])
            }
            ofile[k,14]<-sum(ofile[k,2:13],na.rm=T)
        }
        ofile[,14]<-ofile[,14]+ynacor[,nastat-4]
        for(j in years:yeare){
            k<-j-years+1
            if(leapyear(j)) fulldays<-c(31,29,31,30,31,30,31,31,30,31,30,31)
            else fulldays<-c(31,28,31,30,31,30,31,31,30,31,30,31)
            for(mon in 1:12) ofile[k,mon+1]<-ofile[k,mon+1]*100/fulldays[mon] # change output from counting days to %
        }
        ofile[,14]<-ofile[,14]*100/365 # change output from counting days to %
        write.table(round(ofile,2),file=nam1,append=F,quote=F,sep=", ",na="-99.9",row.names=F)
        
        namt<-paste(outtrddir,paste(ofilename,"_trend.csv",sep=""),sep="/")
        if(sum(is.na(ofile[,14]))>=(yeare-years+1-10)){
            betahat<-NA
            betastd<-NA
            pvalue<-NA
        }
        else{
            fit1<-lsfit(ofile[,1],ofile[,14])
            out1<-ls.print(fit1,print.it=F)
            pvalue<-round(as.numeric(out1$summary[1,6]),3)
            betahat<-round(as.numeric(out1$coef.table[[1]][2,1]),3)
            betastd<-round(as.numeric(out1$coef.table[[1]][2,2]),3)
        }
        cat(file=namt,paste(latitude,longitude,i,years,yeare,betahat,betastd,pvalue,sep=","),fill=180,append=T)
        
        nam2<-paste(outjpgdir,paste(ofilename,"_",toupper(i),".jpg",sep=""),sep="/")
        jpeg(file=nam2,width=1024,height=768)
        plotx(ofile[,1],ofile[,14],main=paste(toupper(i),ofilename,sep="   "),ylab=toupper(i),xlab="Year")
        dev.off()
    }
}
#----------- exceedance ends -----------------------------------------  

#----------- index641cdd -----------------------------------------  
index641cdd<-function(){
    ys<-yeare-years+1
    cdd<-rep(0,ys)
    year<-c(years:yeare)
    target<-as.data.frame(cbind(year,cdd))
    year=years
    for (i in 1:ys){
        mid<-dd[dd$year==year,"prcp"]
        #  mid<-mid[is.na(mid)==F]
        if(i==1) kk<-0
        mm<-0
        for(j in 1:length(mid)){
            if(mid[j]<1&is.na(mid[j])==F) kk<-kk+1
            else {
                if(mm<kk) mm<-kk
                kk<-0
            }
        }
        if(mm<kk){
            if(year==yeare) mm<-kk
            else
                if(dd[dd$year==year+1&dd$month==1&dd$day==1,"prcp"]>=1|is.na(dd[dd$year==year+1&dd$month==1&dd$day==1,"prcp"])==T) mm<-kk
                # in case whole year dry, the next year will have a CDD bigger than 365
                # then the CDD indice for current year should not be 0 but NA
                if(mm==0) mm<-NA
        }
        target[i,"cdd"]<-mm
        year=year+1
    }
    
    #for(i in 1:(ys-1))
    #  if(target[i,"cdd"]==0&target[i+1,"cdd"]>=365) target[i,"cdd"]<-NA
    
    target[,"cdd"]<-target[,"cdd"]+ynacor[,"ynapr>15"]
    nam1<-paste(outinddir,paste(ofilename,"_CDD.csv",sep=""),sep="/")
    write.table(target,file=nam1,append=F,quote=F,sep=", ",na="-99.9",row.names=F)
    
    namt<-paste(outtrddir,paste(ofilename,"_trend.csv",sep=""),sep="/")
    if(sum(is.na(target[,"cdd"]))>=(yeare-years+1-10)){
        betahat<-NA
        betastd<-NA
        pvalue<-NA
    }
    else{
        fit1<-lsfit(target[,1],target[,"cdd"])
        out1<-ls.print(fit1,print.it=F)
        pvalue<-round(as.numeric(out1$summary[1,6]),3)
        betahat<-round(as.numeric(out1$coef.table[[1]][2,1]),3)
        betastd<-round(as.numeric(out1$coef.table[[1]][2,2]),3)
    }
    cat(file=namt,paste(latitude,longitude,"cdd",years,yeare,betahat,betastd,pvalue,sep=","),fill=180,append=T)
    
    nam2<-paste(outjpgdir,paste(ofilename,"_CDD.jpg",sep=""),sep="/")
    jpeg(nam2,width=1024,height=768)
    plotx(target[,1],target[,2],main=paste("CDD",ofilename,sep="   "),xlab="Year",ylab="CDD")
    dev.off()
}
#----------- index641cdd ends -----------------------------------------  

#----------- index641cwd -----------------------------------------  
index641cwd<-function(){
    ys<-yeare-years+1
    cwd<-rep(0,ys)
    year<-years:yeare
    target<-as.data.frame(cbind(year,cwd))
    year=years
    for (i in 1:ys){
        mid<-dd[dd$year==year,"prcp"]
        #  mid<-mid[is.na(mid)==F]
        if(i==1) kk<-0
        mm<-0
        for(j in 1:length(mid)){
            if(mid[j]>=1&is.na(mid[j])==F) kk<-kk+1
            else {
                if(mm<kk) mm<-kk
                kk<-0
            }
        }
        if(mm<kk){
            if(year==yeare) mm<-kk
            else
                if(dd[dd$year==year+1&dd$month==1&dd$day==1,"prcp"]<1|is.na(dd[dd$year==year+1&dd$month==1&dd$day==1,"prcp"])==T) mm<-kk
        }
        
        target[i,"cwd"]<-mm
        year=year+1
    }
    target[,"cwd"]<-target[,"cwd"]+ynacor[,"ynapr>15"]
    nam1<-paste(outinddir,paste(ofilename,"_CWD.csv",sep=""),sep="/")
    write.table(target,file=nam1,append=F,quote=F,sep=", ",na="-99.9",row.names=F)
    
    namt<-paste(outtrddir,paste(ofilename,"_trend.csv",sep=""),sep="/")
    if(sum(is.na(target[,"cwd"]))>=(yeare-years+1-10)){
        betahat<-NA
        betastd<-NA
        pvalue<-NA
    }
    else{
        fit1<-lsfit(target[,1],target[,"cwd"])
        out1<-ls.print(fit1,print.it=F)
        pvalue<-round(as.numeric(out1$summary[1,6]),3)
        betahat<-round(as.numeric(out1$coef.table[[1]][2,1]),3)
        betastd<-round(as.numeric(out1$coef.table[[1]][2,2]),3)
    }
    cat(file=namt,paste(latitude,longitude,"cwd",years,yeare,betahat,betastd,pvalue,sep=","),fill=180,append=T)
    
    nam2<-paste(outjpgdir,paste(ofilename,"_CWD.jpg",sep=""),sep="/")
    jpeg(nam2,width=1024,height=768)
    plotx(target[,1],target[,2],main=paste("CWD",ofilename,sep="   "),xlab="Year",ylab="CWD")
    dev.off()
}
#----------- index641cwd ends -----------------------------------------  

#----------- rx1d -----------------------------------------  
rx1d<-function(){
    len<-yeare-years+1
    aa1<-matrix(NA,12*len,3)
    dimnames(aa1)<-list(NULL,c("year","month","rx1d"))
    aa1[,"year"]<-years:yeare
    aa1[,"year"]<-mysort(aa1[,"year"],decreasing=F)
    aa1[,"month"]<-1:12
    jjj3=1
    mid<-dd[,1:4]
    for (year in years:yeare){
        aaaa<-mid[mid$year==year,]
        aaaam1<-aaaa[aaaa$month==1,"prcp"];        aaaam2<-aaaa[aaaa$month==2,"prcp"]
        aaaam3<-aaaa[aaaa$month==3,"prcp"];        aaaam4<-aaaa[aaaa$month==4,"prcp"]
        aaaam5<-aaaa[aaaa$month==5,"prcp"];        aaaam6<-aaaa[aaaa$month==6,"prcp"]
        aaaam7<-aaaa[aaaa$month==7,"prcp"];        aaaam8<-aaaa[aaaa$month==8,"prcp"]
        aaaam9<-aaaa[aaaa$month==9,"prcp"];        aaaam10<-aaaa[aaaa$month==10,"prcp"]
        aaaam11<-aaaa[aaaa$month==11,"prcp"];      aaaam12<-aaaa[aaaa$month==12,"prcp"]
        aa1[jjj3,"rx1d"]<-max(aaaam1,na.rm=T);     aa1[jjj3+1,"rx1d"]<-max(aaaam2,na.rm=T)
        aa1[jjj3+2,"rx1d"]<-max(aaaam3,na.rm=T);   aa1[jjj3+3,"rx1d"]<-max(aaaam4,na.rm=T)
        aa1[jjj3+4,"rx1d"]<-max(aaaam5,na.rm=T);   aa1[jjj3+5,"rx1d"]<-max(aaaam6,na.rm=T)
        aa1[jjj3+6,"rx1d"]<-max(aaaam7,na.rm=T);   aa1[jjj3+7,"rx1d"]<-max(aaaam8,na.rm=T)
        aa1[jjj3+8,"rx1d"]<-max(aaaam9,na.rm=T);   aa1[jjj3+9,"rx1d"]<-max(aaaam10,na.rm=T)
        aa1[jjj3+10,"rx1d"]<-max(aaaam11,na.rm=T); aa1[jjj3+11,"rx1d"]<-max(aaaam12,na.rm=T)
        jjj3=jjj3+12}
    aa1[,"rx1d"]<-aa1[,"rx1d"]+nacor[,"mnapr>3"]
    ofile<-matrix(0,len,14)
    #    aa1<-as.data.frame(aa1)
    dimnames(ofile)<-list(NULL,c("year","jan","feb","mar","apr","may","jun","jul","aug","sep","oct","nov","dec","annual"))
    ofile<-as.data.frame(ofile)
    for(j in years:yeare){
        k<-j-years+1
        ofile[k,1]<-j
        ofile[k,2:13]<-aa1[aa1[,1]==j,3]
        ofile[k,14]<-max(ofile[k,2:13],na.rm=F)
    }
    nam1<-paste(outinddir,paste(ofilename,"_RX1day.csv",sep=""),sep="/")
    write.table(ofile,file=nam1,append=F,quote=F,sep=", ",na="-99.9",row.names=F)
    
    namt<-paste(outtrddir,paste(ofilename,"_trend.csv",sep=""),sep="/")
    if(sum(is.na(ofile[,14]))>=(yeare-years+1-10)){
        betahat<-NA
        betastd<-NA
        pvalue<-NA
    }
    else{
        fit1<-lsfit(ofile[,1],ofile[,14])
        out1<-ls.print(fit1,print.it=F)
        pvalue<-round(as.numeric(out1$summary[1,6]),3)
        betahat<-round(as.numeric(out1$coef.table[[1]][2,1]),3)
        betastd<-round(as.numeric(out1$coef.table[[1]][2,2]),3)
    }
    cat(file=namt,paste(latitude,longitude,"rx1day",years,yeare,betahat,betastd,pvalue,sep=","),fill=180,append=T)
    
    nam2<-paste(outjpgdir,paste(ofilename,"_RX1day.jpg",sep=""),sep="/")
    jpeg(nam2,width=1024,height=768)
    plotx(ofile[,1],ofile[,14],main=paste("RX1day",ofilename,sep="   "),xlab="Year",ylab="RX1day")
    dev.off()
}
#----------- rx1d ends -----------------------------------------  

#----------- rx5d -----------------------------------------  
rx5d<-function(){
    a2<-c(0,0,0,0)
    a1<-dd[,"prcp"]
    a1<-append(a2,a1)
    n<-length(a1)
    a<-rep(0,n)
    for (i in 5:n){
        a[i]<-sum(a1[(i-4):i],na.rm=T)}
    a<-a[-(1:4)]
    a<-cbind(dd[,1:2],a)
    
    len<-yeare-years+1
    aa1<-matrix(NA,12*len,3)
    dimnames(aa1)<-list(NULL,c("year","month","rx5d"))
    aa1[,"year"]<-years:yeare
    aa1[,"year"]<-mysort(aa1[,"year"],decreasing=F)
    aa1[,"month"]<-1:12
    jjj2=1
    for (year in years:yeare){
        aaaa<-a[a$year==year,]
        aaaam1<-aaaa[aaaa$month==1,"a"];           aaaam2<-aaaa[aaaa$month==2,"a"]
        aaaam3<-aaaa[aaaa$month==3,"a"];           aaaam4<-aaaa[aaaa$month==4,"a"]
        aaaam5<-aaaa[aaaa$month==5,"a"];           aaaam6<-aaaa[aaaa$month==6,"a"]
        aaaam7<-aaaa[aaaa$month==7,"a"];           aaaam8<-aaaa[aaaa$month==8,"a"]
        aaaam9<-aaaa[aaaa$month==9,"a"];           aaaam10<-aaaa[aaaa$month==10,"a"]
        aaaam11<-aaaa[aaaa$month==11,"a"];         aaaam12<-aaaa[aaaa$month==12,"a"]
        aa1[jjj2,"rx5d"]<-max(aaaam1,na.rm=T);     aa1[jjj2+1,"rx5d"]<-max(aaaam2,na.rm=T)
        aa1[jjj2+2,"rx5d"]<-max(aaaam3,na.rm=T);   aa1[jjj2+3,"rx5d"]<-max(aaaam4,na.rm=T)
        aa1[jjj2+4,"rx5d"]<-max(aaaam5,na.rm=T);   aa1[jjj2+5,"rx5d"]<-max(aaaam6,na.rm=T)
        aa1[jjj2+6,"rx5d"]<-max(aaaam7,na.rm=T);   aa1[jjj2+7,"rx5d"]<-max(aaaam8,na.rm=T)
        aa1[jjj2+8,"rx5d"]<-max(aaaam9,na.rm=T);   aa1[jjj2+9,"rx5d"]<-max(aaaam10,na.rm=T)
        aa1[jjj2+10,"rx5d"]<-max(aaaam11,na.rm=T); aa1[jjj2+11,"rx5d"]<-max(aaaam12,na.rm=T)
        jjj2=jjj2+12}
    
    aa1[,"rx5d"]<-aa1[,"rx5d"]+nacor[,"mnapr>3"]
    
    ofile<-matrix(0,len,14)
    #    aa1<-as.data.frame(aa1)
    dimnames(ofile)<-list(NULL,c("year","jan","feb","mar","apr","may","jun","jul","aug","sep","oct","nov","dec","annual"))
    ofile<-as.data.frame(ofile)
    for(j in years:yeare){
        k<-j-years+1
        ofile[k,1]<-j
        ofile[k,2:13]<-aa1[aa1[,1]==j,"rx5d"]
        ofile[k,14]<-max(ofile[k,2:13],na.rm=F)
    }
    #    print(dim(rx5d))
    nam1<-paste(outinddir,paste(ofilename,"_RX5day.csv",sep=""),sep="/")
    write.table(ofile,file=nam1,append=F,quote=F,sep=", ",na="-99.9",row.names=F)
    
    namt<-paste(outtrddir,paste(ofilename,"_trend.csv",sep=""),sep="/")
    if(sum(is.na(ofile[,14]))>=(yeare-years+1-10)){
        betahat<-NA
        betastd<-NA
        pvalue<-NA
    }
    else{
        fit1<-lsfit(ofile[,1],ofile[,14])
        out1<-ls.print(fit1,print.it=F)
        pvalue<-round(as.numeric(out1$summary[1,6]),3)
        betahat<-round(as.numeric(out1$coef.table[[1]][2,1]),3)
        betastd<-round(as.numeric(out1$coef.table[[1]][2,2]),3)
    }
    cat(file=namt,paste(latitude,longitude,"rx5day",years,yeare,betahat,betastd,pvalue,sep=","),fill=180,append=T)
    
    nam2<-paste(outjpgdir,paste(ofilename,"_RX5day.jpg",sep=""),sep="/")
    jpeg(nam2,width=1024,height=768)
    plotx(ofile[,1],ofile[,14],main=paste("RX5day",ofilename,sep="   "),xlab="Year",ylab="RX5day")
    dev.off()
}
#----------- rx5d ends -----------------------------------------  

#----------- extremedaytem -----------------------------------------  
extremedaytem<-function(){
    len<-yeare-years+1
    aa1<-matrix(NA,12*len,6)
    dimnames(aa1)<-list(NULL,c("year","month","txx","txn","tnx","tnn"))
    aa1[,"year"]<-years:yeare
    aa1[,"year"]<-mysort(aa1[,"year"],decreasing=F)
    aa1[,"month"]<-1:12
    jjj4=1
    for (year in years:yeare){
        aaaa<-dd[dd$year==year,]
        aaaama1<-aaaa[aaaa$month==1,"tmax"];   aaaama2<-aaaa[aaaa$month==2,"tmax"]
        aaaama3<-aaaa[aaaa$month==3,"tmax"];   aaaama4<-aaaa[aaaa$month==4,"tmax"]
        aaaama5<-aaaa[aaaa$month==5,"tmax"];   aaaama6<-aaaa[aaaa$month==6,"tmax"]
        aaaama7<-aaaa[aaaa$month==7,"tmax"];   aaaama8<-aaaa[aaaa$month==8,"tmax"]
        aaaama9<-aaaa[aaaa$month==9,"tmax"];   aaaama10<-aaaa[aaaa$month==10,"tmax"]
        aaaama11<-aaaa[aaaa$month==11,"tmax"]; aaaama12<-aaaa[aaaa$month==12,"tmax"]
        
        aaaami1<-aaaa[aaaa$month==1,"tmin"];   aaaami2<-aaaa[aaaa$month==2,"tmin"]
        aaaami3<-aaaa[aaaa$month==3,"tmin"];   aaaami4<-aaaa[aaaa$month==4,"tmin"]
        aaaami5<-aaaa[aaaa$month==5,"tmin"];   aaaami6<-aaaa[aaaa$month==6,"tmin"]
        aaaami7<-aaaa[aaaa$month==7,"tmin"];   aaaami8<-aaaa[aaaa$month==8,"tmin"]
        aaaami9<-aaaa[aaaa$month==9,"tmin"];   aaaami10<-aaaa[aaaa$month==10,"tmin"]
        aaaami11<-aaaa[aaaa$month==11,"tmin"]; aaaami12<-aaaa[aaaa$month==12,"tmin"]
        
        aa1[jjj4,"txx"]<-max(aaaama1,na.rm=T);     aa1[jjj4+1,"txx"]<-max(aaaama2,na.rm=T)
        aa1[jjj4+2,"txx"]<-max(aaaama3,na.rm=T);   aa1[jjj4+3,"txx"]<-max(aaaama4,na.rm=T)
        aa1[jjj4+4,"txx"]<-max(aaaama5,na.rm=T);   aa1[jjj4+5,"txx"]<-max(aaaama6,na.rm=T)
        aa1[jjj4+6,"txx"]<-max(aaaama7,na.rm=T);   aa1[jjj4+7,"txx"]<-max(aaaama8,na.rm=T)
        aa1[jjj4+8,"txx"]<-max(aaaama9,na.rm=T);   aa1[jjj4+9,"txx"]<-max(aaaama10,na.rm=T)
        aa1[jjj4+10,"txx"]<-max(aaaama11,na.rm=T); aa1[jjj4+11,"txx"]<-max(aaaama12,na.rm=T)
        
        aa1[jjj4,"txn"]<-min(aaaama1,na.rm=T);     aa1[jjj4+1,"txn"]<-min(aaaama2,na.rm=T)
        aa1[jjj4+2,"txn"]<-min(aaaama3,na.rm=T);   aa1[jjj4+3,"txn"]<-min(aaaama4,na.rm=T)
        aa1[jjj4+4,"txn"]<-min(aaaama5,na.rm=T);   aa1[jjj4+5,"txn"]<-min(aaaama6,na.rm=T)
        aa1[jjj4+6,"txn"]<-min(aaaama7,na.rm=T);   aa1[jjj4+7,"txn"]<-min(aaaama8,na.rm=T)
        aa1[jjj4+8,"txn"]<-min(aaaama9,na.rm=T);   aa1[jjj4+9,"txn"]<-min(aaaama10,na.rm=T)
        aa1[jjj4+10,"txn"]<-min(aaaama11,na.rm=T); aa1[jjj4+11,"txn"]<-min(aaaama12,na.rm=T)
        
        aa1[jjj4,"tnx"]<-max(aaaami1,na.rm=T);     aa1[jjj4+1,"tnx"]<-max(aaaami2,na.rm=T)
        aa1[jjj4+2,"tnx"]<-max(aaaami3,na.rm=T);   aa1[jjj4+3,"tnx"]<-max(aaaami4,na.rm=T)
        aa1[jjj4+4,"tnx"]<-max(aaaami5,na.rm=T);   aa1[jjj4+5,"tnx"]<-max(aaaami6,na.rm=T)
        aa1[jjj4+6,"tnx"]<-max(aaaami7,na.rm=T);   aa1[jjj4+7,"tnx"]<-max(aaaami8,na.rm=T)
        aa1[jjj4+8,"tnx"]<-max(aaaami9,na.rm=T);   aa1[jjj4+9,"tnx"]<-max(aaaami10,na.rm=T)
        aa1[jjj4+10,"tnx"]<-max(aaaami11,na.rm=T); aa1[jjj4+11,"tnx"]<-max(aaaami12,na.rm=T)
        
        aa1[jjj4,"tnn"]<-min(aaaami1);aa1[jjj4+1,"tnn"]<-min(aaaami2,na.rm=T)
        aa1[jjj4+2,"tnn"]<-min(aaaami3,na.rm=T);   aa1[jjj4+3,"tnn"]<-min(aaaami4,na.rm=T)
        aa1[jjj4+4,"tnn"]<-min(aaaami5,na.rm=T);   aa1[jjj4+5,"tnn"]<-min(aaaami6,na.rm=T)
        aa1[jjj4+6,"tnn"]<-min(aaaami7,na.rm=T);   aa1[jjj4+7,"tnn"]<-min(aaaami8,na.rm=T)
        aa1[jjj4+8,"tnn"]<-min(aaaami9,na.rm=T);   aa1[jjj4+9,"tnn"]<-min(aaaami10,na.rm=T)
        aa1[jjj4+10,"tnn"]<-min(aaaami11,na.rm=T); aa1[jjj4+11,"tnn"]<-min(aaaami12,na.rm=T)
        
        jjj4=jjj4+12}
    exdaytem<-as.data.frame(aa1)
    #    midnacor<-nacor[nacor$year>=startyear,]
    #    midnacor<-midnacor[midnacor$year<=endyear,]
    exdaytem[,"txx"]<-exdaytem[,"txx"]+nacor[,"mnatma>3"]
    exdaytem[,"txn"]<-exdaytem[,"txn"]+nacor[,"mnatma>3"]
    exdaytem[,"tnx"]<-exdaytem[,"tnx"]+nacor[,"mnatmi>3"]
    exdaytem[,"tnn"]<-exdaytem[,"tnn"]+nacor[,"mnatmi>3"]
    
    for(i in c("txx","txn","tnx","tnn")){
        if (i=="txx") {ii<-"_TXx.csv";ij<-"_TXx.jpg";kk<-3;ik<-1;ki<-3}# ik=1, take max as yearly record
        if (i=="txn") {ii<-"_TXn.csv";ij<-"_TXn.jpg";kk<-4;ik<-0;ki<-3}# ik=0, take min as yearly record
        if (i=="tnx") {ii<-"_TNx.csv";ij<-"_TNx.jpg";kk<-5;ik<-1;ki<-4}# ki=3, take TMAX annual missing values
        if (i=="tnn") {ii<-"_TNn.csv";ij<-"_TNn.jpg";kk<-6;ik<-0;ki<-4}# ki=4, take TMIN annual missing values
        nam<-paste(outinddir,paste(ofilename,ii,sep=""),sep="/")
        ofile<-matrix(0,len,14)
        #    ojpg<-rep(0,len)
        dimnames(ofile)<-list(NULL,c("year","jan","feb","mar","apr","may","jun","jul","aug","sep","oct","nov","dec","annual"))
        ofile<-as.data.frame(ofile)
        for(j in years:yeare){
            k<-j-years+1
            ofile[k,1]<-j
            ofile[k,2:13]<-exdaytem[exdaytem$year==j,kk]
            if(ik==1) ofile[k,14]<-max(ofile[k,2:13],na.rm=T)
            else ofile[k,14]<-min(ofile[k,2:13],na.rm=T)
        }
        ofile[,14]<-ofile[,14]+ynacor[,ki]
        write.table(ofile,file=nam,append=F,quote=F,sep=", ",na="-99.9",row.names=F)
        
        namt<-paste(outtrddir,paste(ofilename,"_trend.csv",sep=""),sep="/")
        if(sum(is.na(ofile[,14]))>=(yeare-years+1-10)){
            betahat<-NA
            betastd<-NA
            pvalue<-NA
        }
        else{
            fit1<-lsfit(ofile[,1],ofile[,14])
            out1<-ls.print(fit1,print.it=F)
            pvalue<-round(as.numeric(out1$summary[1,6]),3)
            betahat<-round(as.numeric(out1$coef.table[[1]][2,1]),3)
            betastd<-round(as.numeric(out1$coef.table[[1]][2,2]),3)
        }
        cat(file=namt,paste(latitude,longitude,i,years,yeare,betahat,betastd,pvalue,sep=","),fill=180,append=T)
        
        nam2<-paste(outjpgdir,paste(ofilename,ij,sep=""),sep="/")
        jpeg(nam2,width=1024,height=768)
        plotx(ofile[,1],ofile[,14],main=paste(toupper(i),ofilename,sep="   "),xlab="Year",ylab=(paste(toupper(substr(i,1,2)),substr(i,3,3),sep="")))
        dev.off()
    }
}
#----------- extremedaytem ends -----------------------------------------  

#----------- index646 -----------------------------------------  
index646<-function(){
    ys=yeare-years+1
    b<-matrix(0,ncol=2,nrow=ys)
    dimnames(b)<-list(NULL,c("year","sdii"))
    b[,"year"]<-c(years:yeare)
    b<-as.data.frame(b)
    year=years
    for (i in 1:ys){
        mid<-dd[dd$year==year,"prcp"]
        mid<-mid[mid>=1]
        b[i,"sdii"]<-mean(mid,na.rm=T)
        year=year+1  }
    b[,"sdii"]<-b[,"sdii"]+ynacor[,"ynapr>15"]
    nam1<-paste(outinddir,paste(ofilename,"_SDII.csv",sep=""),sep="/")
    write.table(round(b,digit=1),file=nam1,append=F,quote=F,sep=", ",na="-99.9",row.names=F)
    
    namt<-paste(outtrddir,paste(ofilename,"_trend.csv",sep=""),sep="/")
    if(sum(is.na(b[,"sdii"]))>=(yeare-years+1-10)){
        betahat<-NA
        betastd<-NA
        pvalue<-NA
    }
    else{
        fit1<-lsfit(b[,"year"],b[,"sdii"])
        out1<-ls.print(fit1,print.it=F)
        pvalue<-round(as.numeric(out1$summary[1,6]),3)
        betahat<-round(as.numeric(out1$coef.table[[1]][2,1]),3)
        betastd<-round(as.numeric(out1$coef.table[[1]][2,2]),3)
    }
    cat(file=namt,paste(latitude,longitude,"sdii",years,yeare,betahat,betastd,pvalue,sep=","),fill=180,append=T)
    
    nam2<-paste(outjpgdir,paste(ofilename,"_SDII.jpg",sep=""),sep="/")
    jpeg(nam2,width=1024,height=768)
    plotx(b[,1],b[,2],main=paste("SDII",ofilename,sep="   "),xlab="Year",ylab="SDII")
    dev.off()
}
#----------- index646 ends -----------------------------------------  

#----------- main1 -----------------------------------------  
main1<-function(){
    main<-tktoplevel()
    tkfocus(main)
    tkwm.title(main,"Calculating Climate Indices")
    tkgrid(tklabel(main,text="Check desired indices",font=fontHeading1))
    txt="It may take 5 minutes to compute all the indices, "
    #   if(prallna==1) tkgrid(tklabel(main, text="PRCP all missing, indices related to PRCP may not be calculated",font=fontHeading2))
    #   if(txallna==1|tnallna==1) tkgrid(tklabel(main,text="TMAX or TMIN all missing, indices related to TMAX and TMIN may not be calculated",font=fontHeading2))
    
    #cb0 <- tkcheckbutton(main);cb0Val <- cbvalue0
    
    cb1 <- tkcheckbutton(main);  cb1Val <- cbvalue1
    cb2 <- tkcheckbutton(main);  cb2Val <- cbvalue2
    cb3 <- tkcheckbutton(main);  cb3Val <- cbvalue3
    cb4 <- tkcheckbutton(main);  cb4Val <- cbvalue4
    cb5 <- tkcheckbutton(main);  cb5Val <- cbvalue5
    cb6 <- tkcheckbutton(main);  cb6Val <- cbvalue6
    cb7 <- tkcheckbutton(main);  cb7Val <- cbvalue7
    cb8 <- tkcheckbutton(main);  cb8Val <- cbvalue8
    cb9 <- tkcheckbutton(main);  cb9Val <- cbvalue9
    cb10 <- tkcheckbutton(main); cb10Val <- cbvalue10
    cb11 <- tkcheckbutton(main); cb11Val <- cbvalue11
    cb12 <- tkcheckbutton(main); cb12Val <- cbvalue12
    cb13 <- tkcheckbutton(main); cb13Val <- cbvalue13
    cb14 <- tkcheckbutton(main); cb14Val <- cbvalue14
    cb15 <- tkcheckbutton(main); cb15Val <- cbvalue15
    cb21 <- tkcheckbutton(main); cb21Val <- cbvalue21
    
    #tkconfigure(cb0,variable=cb0Val)#,value=cb1Val)
    tkconfigure(cb1,variable=cb1Val)#,value=cb1Val)
    tkconfigure(cb2,variable=cb2Val)#,value=cb2Val)
    tkconfigure(cb3,variable=cb3Val)#,value=cb3Val)#"dtr")
    tkconfigure(cb4,variable=cb4Val)#,value=cb4Val)#"daysprcp10")
    tkconfigure(cb5,variable=cb5Val)#,value=cb5Val)#"nordaytem1")
    tkconfigure(cb6,variable=cb6Val)#,value=cb6Val)#"extremedays")
    tkconfigure(cb7,variable=cb7Val)#,value=cb7Val)#"exceedance")
    tkconfigure(cb8,variable=cb8Val)#,value=cb8Val)#"ind144hwd")
    tkconfigure(cb9,variable=cb9Val)#,value=cb9Val)#"ind641cdd")
    tkconfigure(cb10,variable=cb10Val)#,value=cb10Val)#"rx5d")
    tkconfigure(cb11,variable=cb11Val)#,value=cb11Val)#"ind646")
    tkconfigure(cb12,variable=cb12Val)#,value=cb12Val)#"ind695")
    tkconfigure(cb13,variable=cb13Val)#,value=cb13Val)#"rx1d"
    tkconfigure(cb14,variable=cb14Val)#,value=cb14Val)#"extreme day tem"
    tkconfigure(cb15,variable=cb15Val)
    tkconfigure(cb21,variable=cb21Val)
    
    #tkgrid(tklabel(main,text="Select the indices you want to calculate:"))
    
    #tkgrid(tklabel(main,text="ALL 26 indices!!"),cb0)
    tkgrid(tklabel(main,text="SU25, FD0, TR20, ID0"),cb1)
    tkgrid(tklabel(main,text="User Defined SU, FD, TR, ID"),cb21)
    
    tkgrid(tklabel(main,text="GSL, growing season length"),cb2)#143
    
    tkgrid(tklabel(main,text="TXx, TXn, TNx, TNn"),cb3)
    #tkgrid(tklabel(main,text="TXn, TNx, TNn, following by same choice"),cb3)#extremedaytem
    
    tkgrid(tklabel(main,text="TX10p, TX90p, TN10p, TN90p"),cb4)
    #tkgrid(tklabel(main,text="TX90p, TN10p, TN90p, following by same choice"),cb4)#exceedance
    
    tkgrid(tklabel(main,text="WSDI"),cb5)#hwfi
    tkgrid(tklabel(main,text="CSDI"),cb6)#cwdi
    
    #tkgrid(tklabel(main,text="Normal day temperature with user defined window size"),cb2)
    tkgrid(tklabel(main,text="DTR"),cb7)#dtr
    
    tkgrid(tklabel(main,text="Rx1day"),cb8)#rx1d
    tkgrid(tklabel(main,text="Rx5day"),cb9)#rx5d
    
    tkgrid(tklabel(main,text="SDII"),cb10)#index646
    
    tkgrid(tklabel(main,text="R10mm"),cb11)#daysprcp10()
    tkgrid(tklabel(main,text="R20mm"),cb12)#daysprcp20()
    tkgrid(tklabel(main,text="Rnnmm"),cb13)#daysprcpn()
    
    tkgrid(tklabel(main,text="CDD, CWD"),cb14)
    #tkgrid(tklabel(main,text="CWD"),cb14)#641
    
    #tkgrid(tklabel(main,text="daynortem     "),cb5)
    #tkgrid(tklabel(main,text="ind144hwd      "),cb8)#144
    
    tkgrid(tklabel(main,text="R95p, R99p, PRCPTOT"),cb15)#695
    #tkgrid(tklabel(main,text="R99pTOT"),cb15)
    
    #tkgrid(tklabel(main,text="Annual Days with PRCP>=95 percentile"),cb17)#r95ptot
    #tkgrid(tklabel(main,text="Annual Days with PRCP>=99 percentile"),cb17)
    
    #----------- OnOK -----------------------------------------  
    OnOK <- function(){
        #filename<-tclvalue(tkgetSaveFile(filetypes="{{EXCEL Files} {.csv}} {{All files} *}"))
        #if (!nchar(filename))
        #tkmessageBox(message="No file was selected!")
        #else tkmessageBox(message=paste("The results will be saved under",filename))
        #nam<-substr(filename,start=1,stop=(nchar(filename)-4))
        #assign("nam",nam,envir=.GlobalEnv)
        
        #    cbv0 <- as.character(tclvalue(cb0Val))
        cbv1 <- as.character(tclvalue(cb1Val))
        cbv21 <- as.character(tclvalue(cb21Val))
        cbv2 <- as.character(tclvalue(cb2Val))
        cbv3 <- as.character(tclvalue(cb3Val))
        cbv4 <- as.character(tclvalue(cb4Val))
        cbv5 <- as.character(tclvalue(cb5Val))
        cbv6 <- as.character(tclvalue(cb6Val))
        cbv7 <- as.character(tclvalue(cb7Val))
        cbv8 <- as.character(tclvalue(cb8Val))
        cbv9 <- as.character(tclvalue(cb9Val))
        cbv10 <- as.character(tclvalue(cb10Val))
        cbv11 <- as.character(tclvalue(cb11Val))
        cbv12 <- as.character(tclvalue(cb12Val))
        cbv13 <- as.character(tclvalue(cb13Val))
        cbv14 <- as.character(tclvalue(cb14Val))
        cbv15 <- as.character(tclvalue(cb15Val))
        tkdestroy(main)
        #    if (cbv0==1) {cbv1<-1;cbv2<-1;cbv3<-1;cbv4<-1;cbv5<-1;
        namt<-paste(outtrddir,paste(ofilename,"_trend.csv",sep=""),sep="/")
        cat(file=namt,paste("Lon","Lat","Indices","SYear","EYear","Slope","STD_of_Slope","P_Value",sep=","),fill=180,append=F)
        if (cbv1==1) if(txallna==0&tnallna==0) extremedays()
        if (cbv21==1) if(txallna==0&tnallna==0) extremedays(opt=1)
        if (cbv2==1) if(txallna==0&tnallna==0) ind143gsl()
        if (cbv3==1) if(txallna==0&tnallna==0) extremedaytem()
        if (cbv4==1) if(txallna==0&tnallna==0) exceedance()
        if (cbv5==1) if(txallna==0) hwfi()
        if (cbv6==1) if(tnallna==0) cwdi()
        if (cbv7==1) if(txallna==0&tnallna==0) dtr()
        if (cbv8==1) if(prallna==0) rx1d()
        if (cbv9==1) if(prallna==0) rx5d()
        if (cbv10==1) if(prallna==0) index646()
        if (cbv11==1) if(prallna==0) daysprcp10()
        if (cbv12==1) if(prallna==0) daysprcp20()
        if (cbv13==1) if(prallna==0) daysprcpn()
        if (cbv14==1) if(prallna==0) {index641cdd();index641cwd()}
        if (cbv15==1) if(prallna==0) r95ptot()
        cbvalue1<-cb1Val;assign("cbvalue1",cbvalue1,envir=.GlobalEnv)
        cbvalue2<-cb2Val;assign("cbvalue2",cbvalue2,envir=.GlobalEnv)
        cbvalue3<-cb3Val;assign("cbvalue3",cbvalue3,envir=.GlobalEnv)
        cbvalue4<-cb4Val;assign("cbvalue4",cbvalue4,envir=.GlobalEnv)
        cbvalue5<-cb5Val;assign("cbvalue5",cbvalue5,envir=.GlobalEnv)
        cbvalue6<-cb6Val;assign("cbvalue6",cbvalue6,envir=.GlobalEnv)
        cbvalue7<-cb7Val;assign("cbvalue7",cbvalue7,envir=.GlobalEnv)
        cbvalue8<-cb8Val;assign("cbvalue8",cbvalue8,envir=.GlobalEnv)
        cbvalue9<-cb9Val;assign("cbvalue9",cbvalue9,envir=.GlobalEnv)
        cbvalue10<-cb10Val;assign("cbvalue10",cbvalue10,envir=.GlobalEnv)
        cbvalue11<-cb11Val;assign("cbvalue11",cbvalue11,envir=.GlobalEnv)
        cbvalue12<-cb12Val;assign("cbvalue12",cbvalue12,envir=.GlobalEnv)
        cbvalue13<-cb13Val;assign("cbvalue13",cbvalue13,envir=.GlobalEnv)
        cbvalue14<-cb14Val;assign("cbvalue14",cbvalue14,envir=.GlobalEnv)
        cbvalue15<-cb15Val;assign("cbvalue15",cbvalue15,envir=.GlobalEnv)
        cbvalue21<-cb21Val;assign("cbvalue21",cbvalue21,envir=.GlobalEnv)
        nstation<-tktoplevel()
        tkwm.title(nstation,"Calculation Done")
        tkfocus(nstation)
        okk<-function(){tkdestroy(nstation);tkfocus(start1)}
        textlabel0<-tklabel(nstation,text="     ")
        textlabel1<-tklabel(nstation,text="Indices calculation completed",font=fontHeading1)
        textlabel2<-tklabel(nstation,text=paste("Plots are in: ",outjpgdir,sep=" "),font=fontHeading1)
        okk.but<-tkbutton(nstation,text="   OK   ",command=okk,width=20)
        tkgrid(textlabel0)
        tkgrid(textlabel1)
        tkgrid(textlabel2)
        tkgrid.configure(textlabel1,sticky="w")
        tkgrid.configure(textlabel2,sticky="w")
        tkgrid.configure(textlabel0,sticky="e")
        #    cancell.but<-tkbutton(nstation,text="   NO   ",command=cancell,width=15)
        #    tkgrid(textlabel2,okk.but,cancell.but,textlabel0)
        tkgrid(okk.but,textlabel0)
        #    tkgrid.configure(cancell.but,sticky="w")
        tkgrid(textlabel0)
    }
    #----------- OnOK ends -----------------------------------------  
    
    #----------- done2 -----------------------------------------  
    done2<-function(){
        tkdestroy(main)
        tkfocus(start1)
        #  return()
    }
    #----------- done2 ends -----------------------------------------  
    
    ok.but <-tkbutton(main,text="   OK   ",command=OnOK,width=30)
    cancel.but<-tkbutton(main,text="CANCEL",command=done2,width=30)
    tkgrid(ok.but)
    tkgrid(cancel.but)
    tkgrid(tklabel(main,text="It may take more than 5 minutes to compute all the indices",font=fontHeading2))
    tkgrid(tklabel(main,text="Please be patient, you will be informed once computations are done",font=fontHeading2))
    tkgrid(tklabel(main,text="",font=fontHeading))#empty line
    
}
#----------- main1 ends ----------------------------------------- 
# End of Part II ( Functions of Calculating climate indecies )
##################################################################################


##################################################################################
# Part III
# Main program
# call getfile, read data file and store in dd.
##################################################################################
start1<-tktoplevel()
#----------- plotx -----------------------------------------  
plotx<-
    function (x,y,main="",xlab="",ylab="")
    {
        plot(x,y,xlab=xlab,ylab=ylab,type="b")
        fit<-lsfit(x,y)
        out<-ls.print(fit,print.it=F)
        r2<-round(100*as.numeric(out$summary[1,2]),1)
        pval<-round(as.numeric(out$summary[1,6]),3)
        beta<-round(as.numeric(out$coef.table[[1]][2,1]),3)
        betaerr<-round(as.numeric(out$coef.table[[1]][2,2]),3)
        abline(fit,lwd=3)
        xy<-cbind(x,y)
        xy<-na.omit(xy)
        lines(lowess(xy[,1],xy[,2]),lwd=3,lty=2)
        subtit=paste("R2=",r2," p-value=",pval," Slope estimate=",beta," Slope error=",betaerr)
        title(main=main)
        title(sub=subtit,cex=0.5)
    }
#----------- plotx ends -----------------------------------------  

#----------- ts -----------------------------------------  
ts<-function(ys=x[1,1],ye=x[nrow(x),1],x=dd) 
{
    #
    # EDA function
    #
    par(mfrow=c(3,1))
    xs<-x[(x[,1]>=ys)&(x[,1]<=ye),]
    ts.plot(xs[,4])
    title("Daily precipitation",xlab="day",ylab="precip")
    ts.plot(xs[,5])
    title("Daily maximum temperature",xlab="day",ylab="tmax")
    ts.plot(xs[,6])
    title("Daily minimum temperature",xlab="day",ylab="tmin")
    par(mfrow=c(1,1))
    
    cat(paste("Station series defined from ",x[1,1]," to ",x[nrow(x),1],"\n"))
    cat(paste("Summary statistics for window from ",ys," to ", ye,"\n"))
}
#----------- ts ends -----------------------------------------  

#----------- ?????????? -----------------------------------------  
function (y1=x[1,1],y2=dd[nrow(x),1],m=1,v=4,x=dd) 
{
    #
    # Little function to see how many NAs there are in month m
    # in period y1 to y2 for variable v:
    # 
    # Usage: nas(1960,1990,1,4)
    #
    
    xs<-x[(x[,1]>=y1)&(x[,1]<=y2)&(x[,2]==m),]
    cat(paste("Years from ",y1,"-",y2," Month=",m," Variable=",v,"\n"))
    cat(paste("Total number of days=",length(xs[,v])," Total missing=",sum(is.na(xs[,v])),"\n"))
}
#----------- ?????? ends -----------------------------------------  
startss<-function(){
    tkwm.title(start1,"RclimDex")
    tkgrid(tklabel(start1,text="     RClimDex by Junior version BETA  ",font=fontHeading))
    tkgrid(tklabel(start1,text="",font=fontHeading))#empty line
    tkgrid(tklabel(start1,text="",font=fontHeading))#empty line
    #tkgrid(tklabel(start1,text="",font=fontHeading))#empty line
    start.but<-tkbutton(start1,text="Load Data and Run QC",command=getfile,width=30)
    cal.but<-tkbutton(start1,text=" Indices Calculation ",command=nastat,width=60)
    cancel.but<-tkbutton(start1,text="Exit",command=done,width=30)
    tkgrid(start.but)
    tkgrid(cal.but)
    tkgrid(cancel.but)
    tkgrid(tklabel(start1,text="",font=fontHeading))   
}#end of startss function
startss()
##################################################################################

.

LS0tDQp0aXRsZTogVmFyaWFiaWxpZGFkIGNsaW3DoXRpY2EgZW4gZWwgZ3JhZGllbnRlIGFsdGl0dWRpbmFsIGVuIGxhIHZlcnRpZW50ZSBkZWwgQ2FyaWJlDQogICg1IG1zbm0geSAxNDAwIG1zbm0pLg0KYXV0aG9yOiAiQW5kcsOpcyBDYXJyYW56YSBRdWlyw7NzLA0KICAgICAgICBTdGFjeSBDaGFjw7NuIEZhbGxhcywNCiAgICAgICAgQW5hIE1hcsOtYSBPY2FtcG8gQ2FtYnJvbmVybywNCiAgICAgICAgQXJnZXJpZSBPdmllZG8gQm9sYcOxb3MsDQogICAgICAgIEfDqW5lc2lzIFJvZHJpZ3VleiBOYXJhbmpvLiINCm91dHB1dDoNCiAgaHRtbF9ub3RlYm9vazoNCiAgICAgIGNvZGVfZm9sZGluZzogaGlkZQ0KLS0tDQoNCmBgYHtyIHNldHVwLCBpbmNsdWRlPUZBTFNFfQ0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KGV2YWwgPSBGQUxTRSwgaW5jbHVkZSA9IEZBTFNFKQ0KYGBgDQo8ZGl2IGNsYXNzPXRleHQtanVzdGlmeT4NCiMjKipSZXN1bWVuKiojIw0KDQpSZXN1bWVuOiANCkNvc3RhIFJpY2EgcHJlc2VudGEgdW4gY2xpbWEgdmFyaWFibGUsIGNvbiBhbHRhcyB0ZW1wZXJhdHVyYXMsIHkgYWJ1bmRhbnRlcyBwcmVjaXBpdGFjaW9uZXMuIExvcyB2aWVudG9zIHByb3ZlbmllbnRlcyBkZWwgQ2FyaWJlLCBnZW5lcmFuIHZhcmlhY2lvbmVzIGVuIGVsIGNvbXBvcnRhbWllbnRvIGRlIGRpdmVyc29zIGZhY3RvcmVzIGNsaW3DoXRpY29zIGVuIGVsIHBhw61zLiBFc3RhIGludmVzdGlnYWNpw7NuIHBsYW50ZWEgYW5hbGl6YXIgbGEgdmFyaWFiaWxpZGFkIGNsaW3DoXRpY2EgZW4gbG9zIMO6bHRpbW9zIDMwIGHDsW9zIGVuIGRvcyBncmFkaWVudGVzIGFsdGl0dWRpbmFsZXMgZW4gbGEgdmVydGllbnRlIGRlbCBDYXJpYmUsIHBhcmEgZGV0ZXJtaW5hciBsb3MgZmFjdG9yZXMgcXVlIHByb2R1Y2VuIGNhbWJpb3MgZW4gbGFzIHRlbXBlcmF0dXJhcyB5IHByZWNpcGl0YWNpw7NuLiBTZSB0cmFiYWrDsyB1bmEgYmFzZSBkZSBkYXRvcyBkZSBwcmVjaXBpdGFjacOzbiAobW0pLCB0ZW1wZXJhdHVyYSBtw6F4aW1hIHkgbcOtbmltYSAowrBDKSBlbiBkb3MgZXN0YWNpb25lcywgcHJvcG9yY2lvbmFkb3MgcG9yIGVsIEluc3RpdHV0byBNZXRlb3JvbMOzZ2ljbyBOYWNpb25hbC4gTWVkaWFudGUgZWwgcHJvZ3JhbWEgUi1DbGltRGV4LCBzZSBjYWxjdWxhcm9uIGRpdmVyc29zIMOtbmRpY2VzIGNsaW3DoXRpY29zLCBiYXNhZG9zIGVuIHVuIHByZXZpbyBhbsOhbGlzaXMgZGUgcmVncmVzacOzbiBsaW5lYWwuQ2FkYSB1bm8gZGUgbG9zIMOtbmRpY2VzIGNvbiB2YWxvcmVzIHNpZ25pZmljYXRpdm9zIChQLXZhbHVlIDwwLjA1KSwgc2Ugc29tZXRpZXJvbiBhIGxhIHBydWViYSBkZSBTaGFwaXJvLldpbGsgYSBsb3MgcmVzaWR1b3MgcGFyYSBkZW1vc3RyYXIgbGEgbm9ybWFsaWRhZCBkZSBsb3MgZGF0b3MgY29uIGF5dWRhIGRlbCBwcm9ncmFtYSBSLiBQcmVjaXBpdGFjaW9uZXMgY29uIG1heW9yIGludGVuc2lkYWQgeSB0ZW1wZXJhdHVyYXMgbcOhcyBiYWphcyBzb24gbG9zIGZhY3RvcmVzIGNvbiBtw6FzIHNpZ25pZmljYW5jaWEuIERpY2hhcyB2YXJpYWNpb25lcyBvYmVkZWNlbiBhIGxvcyBmZW7Ds21lbm9zIEVOT1MsIHF1ZSBnZW5lcmFuIGxsdXZpYXMgZW4gbWVub3MgdGllbXBvIHkgbcOhcyB2aW9sZW50YXMuIExvcyByYXlvcyBkZWwgc29sIG5vIHBlbmV0cmFuIGVuIHN1IHRvdGFsaWRhZCBhIGNhdXNhIGRlIG11Y2hhIG51Ym9zaWRhZCwgcG9yICBsbyBxdWUgbGEgdGVtcGVyYXR1cmEgYmFqYS4gRXN0byBzdXBvbmUgbGEgZXhpc3RlbmNpYSBkZSB2YXJpYWJpbGlkYWQgY2xpbcOhdGljYSwgYWZlY3RhbmRvIGEgbGFyZ28gcGxhem8gbG9zIGVjb3Npc3RlbWFzIHkgbGFzIGFjdGl2aWRhZGVzIGh1bWFuYXMuDQoNCioqUGFsYWJyYXMgY2xhdmU6KiogVmFyaWFiaWxpZGFkIGNsaW3DoXRpY2EsIHByZWNpcGl0YWNpw7NuLCB0ZW1wZXJhdHVyYSwgZ3JhZGllbnRlIGFsdGl0dWRpbmFsLCBWZXJ0aWVudGUgZGVsIENhcmliZS4NCg0KDQojIyoqSW50cm9kdWNjacOzbioqIyMNCkNvc3RhIFJpY2EgZXMgdW4gcGHDrXMgcXVlIHNlIGNhcmFjdGVyaXphIHBvcnF1ZSBncmFuIHBhcnRlIGRlbCBhw7FvIHByZXNlbnRhIHVuIGNsaW1hIGNhcmFjdGVyaXphZG8gcG9yIHN1cyBhbHRhcyB0ZW1wZXJhdHVyYXMgeSBhYnVuZGFudGVzIGxsdXZpYXMgcmVwcmVzZW50YXRpdm8gZGUgdW4gY2xpbWEgdHJvcGljYWwuIFBvciBlc3RhIHJhesOzbiBsYSB2YXJpYWNpw7NuIG3DoXMgaW1wb3J0YW50ZSBlcyBsYSBsbHV2aWEgeWEgcXVlIGFmZWN0YW4gbG9zIGRpZmVyZW50ZXMgc2lzdGVtYXMgZGUgdmllbnRvIHkgbGEgdG9wb2dyYWbDrWEgKExpemFubyB5IFNhbGFzLCAyMDAxKS4gQ29zdGEgUmljYSBjb21wcmVuZGUgbGEgdmVydGllbnRlIGRlbCBjYXJpYmUgbGEgY3VhbCBwcmVzZW50YSB0ZW1wZXJhdHVyYXMgbXV5IHZhcmlhZGFzIGRlIGFjdWVyZG8gY29uIGxhIGFsdGl0dWQsIHNpZW5kbyDDqXN0YSBsYSBkaXN0YW5jaWEgdmVydGljYWwgcXVlIGV4aXN0ZSBzb2JyZSBjdWFscXVpZXIgcHVudG8gZGUgbGEgVGllcnJhIHRvbWFuZG8gY29tbyByZWZlcmVuY2lhIGVsIG5pdmVsIGRlbCBtYXIsIHBvciBsbyBxdWUgw6lzdGEgem9uYSBzZSBlbmN1ZW50cmEgZGlyZWN0YW1lbnRlIGV4cHVlc3RhIGEgbG9zIHZpZW50b3MgYWxpc2lvcyBxdWUgbGxlZ2FuIGNhcmdhZG9zIGRlIGh1bWVkYWQgYWwgQ2FyaWJlLiBFc3RlIHBhcsOhbWV0cm8gcHJvZHVjZSB1bmEgZ3JhbiBjYW50aWRhZCBkZSB2YXJpYWNpb25lcyBlbiBlbCBjb21wb3J0YW1pZW50byBkZSBkaWZlcmVudGVzIGNvbXBvbmVudGVzIG8gZmFjdG9yZXMgY2xpbcOhdGljb3MgKFJldGFuYSB5IFZpbGxhbG9ib3MsIDIwMDApLiBFc3RhcyB2YXJpYWNpb25lcyByZWNpYmVuIGVsIG5vbWJyZSBkZSB2YXJpYWJpbGlkYWQgY2xpbcOhdGljYSBsYSBjdWFsIGVzIHVuIGZlbsOzbWVubyBxdWUgYWZlY3RhIGEgdW5hIGdyYW4gY2FudGlkYWQgZGUgc2VjdG9yZXMsIGRlc2RlIGxhcyBhY3RpdmlkYWRlcyBodW1hbmFzIGNvbW8gZW4gbG9zIGRpZmVyZW50ZXMgZW50b3Jub3MgbmF0dXJhbGVzIHF1ZSBzdWZyZW4gaW1wb3J0YW50ZXMgdmFyaWFjaW9uZXMgZW4gbGEgZXN0YWJpbGlkYWQgZGUgc3VzIGVjb3Npc3RlbWFzIChZw6HDsWV6LUFyYW5jaWJpYSwgVHdpbGxleSB5IExhcmEtRG9tw61uZ3VleiwgMTk5OCkuICAgDQogDQpFeGlzdGVuIHZhcmlvcyBmYWN0b3JlcyBhIGxhIGhvcmEgZGUgZXN0dWRpYXIgbG9zIGVmZWN0b3MgZGUgbGEgdmFyaWFiaWxpZGFkIGNsaW3DoXRpY2Egc29icmUgdW4gZW50b3JubywgZG9uZGUgbGEgcHJlY2lwaXRhY2nDs24geSBsYSBtZWRpY2nDs24gZGUgbGFzIHRlbXBlcmF0dXJhcyBtw6F4aW1hcyB5IG3DrW5pbWFzIG9mcmVjZW4gdW4gY2xhcm8gcGFub3JhbWEgYSBsYSBob3JhIGRlIGRldGVybWluYXIgZXN0b3MgY2FtYmlvcyAoUHVlcnRhcyB5IENhcnZhamFsLCAyMDA4KS4gTGEgcHJlY2lwaXRhY2nDs24gcXVlIGVzIGxhIGNhw61kYSBkZSBhZ3VhIGRlc2RlIGxhIGF0bcOzc2ZlcmEgaGFzdGEgbGEgc3VwZXJmaWNpZSB0ZXJyZXN0cmUsIGZvcm1hbmRvIHBhcnRlIGRlbCBjaWNsbyBkZWwgYWd1YS4gTGEgcHJlY2lwaXRhY2nDs24gc2UgZ2VuZXJhIHBvciBsYSBjb25kZW5zYWNpw7NuIGRlbCBhZ3VhLCBlcyBkZWNpciwgbGEgZm9ybWFjacOzbiBkZSBudWJlcyBwb3IgbGEgYWN1bXVsYWNpw7NuIGRlIGFndWEgZW4gbGEgYXRtw7NzZmVyYS4gT3RybyBmYWN0b3IgaW1wb3J0YW50ZSBlcyBsYSB0ZW1wZXJhdHVyYSBhdG1vc2bDqXJpY2EsIGxhIGN1YWwgc2UgdmUgcmVmbGVqYWRhIGN1YW5kbyBsYXMgcmFkaWFjaW9uZXMgc29sYXJlcyBsbGVnYW4gYSBsYSBzdXBlcmZpY2llIHRlcnJlc3RyZSBwcm92b2NhbmRvIHF1ZSBzdSBlbmVyZ8OtYSBjYWxpZW50ZSBlbCBzdWVsbyB5IGFzw60gbWlzbW8gbGFzIGNhcGFzIGRlbCBhaXJlIHF1ZSBzZSBlbmN1ZW50cmFuIGVuIGNvbnRhY3RvLiBFc3RlIGVmZWN0byBzZSB2ZSByZWZsZWphZG8gZW4gZWwgYXVtZW50byBkZSBsYSB0ZW1wZXJhdHVyYSBhIGxvIGxhcmdvIGRlIGxvcyBhw7FvcyB5YSBxdWUgbGFzIHJhZGlhY2lvbmVzIG5vIHNvbiBhYnNvcmJpZGFzIHBvciBlbCBzdWVsbyB5IHNlIHJlZmxlamFuIHBhcmEgZXNjYXBhciBkZSBudWV2byBhIGxhIGF0bcOzc2ZlcmEsIHNpbiBlbWJhcmdvLCBzZSBkZXZ1ZWx2ZW4gYSBsYSBzdXBlcmZpY2llIHRlcnJlc3RyZSBkZWJpZG8gYWwgZGnDs3hpZG8gZGUgY2FyYm9ubyB5IGVsIHZhcG9yIChBbGZhcm8geSBBbWFkb3IsIDE5OTcpLiBMYSB0ZW1wZXJhdHVyYSBhdG1vc2bDqXJpY2EsIGNvbXByZW5kZSB0ZW1wZXJhdHVyYXMgbcOheGltYXMsIHF1ZSBlcyBsYSBtYXlvciB0ZW1wZXJhdHVyYSBkZWwgYWlyZSBhbGNhbnphZGEgZW4gdW4gbHVnYXIgZW4gdW4gZMOtYSAobcOheGltYSBkaWFyaWEpLCBlbiB1biBtZXMgKG3DoXhpbWEgbWVuc3VhbCkgbyBlbiB1biBhw7FvIChtw6F4aW1hIGFudWFsKSwgeSB0ZW1wZXJhdHVyYXMgbcOtbmltYXMsIHF1ZSBhbCBjb250cmFyaW8sIGVzIGxhIG1lbm9yIHRlbXBlcmF0dXJhIHJlZ2lzdHJhZGEgZW4gdW4gbHVnYXIgYSBsbyBsYXJnbyBkZSB1biBkw61hLCBtZXMgbyBhw7FvLiAgDQogDQpFcyBpbXBvcnRhbnRlIGNvbXByZW5kZXIgbGEgZGlmZXJlbmNpYSBlbnRyZSB2YXJpYWJpbGlkYWQgeSBjYW1iaW8gY2xpbcOhdGljbywgbGEgdmFyaWFiaWxpZGFkIHNlZ8O6biBBbHphdGUsIFJvamFzLCBNb3NxdWVyYSB5IFJhbcOzbiAoMjAxNSkgc2UgcHVlZGUgZGVmaW5pciBjb21vIGNhbWJpb3MgbyBtb2RpZmljYWNpb25lcyBlbiBsb3MgY29tcG9uZW50ZXMgY2xpbcOhdGljb3MgZW4gcGVyaW9kb3MgZGUgdGllbXBvIGNvcnRvcyBtaWVudHJhcyBxdWUgZWwgY2FtYmlvIGNsaW3DoXRpY28gc2UgcmVmaWVyZSBhIGRpZmVyZW5jaWFzIGNsaW3DoXRpY2FzIGEgbG8gbGFyZ28gZGUgZ3JhbmRlcyBwZXJpb2RvcyB5IHF1ZSBwcmVzZW50YW4gdW4gZXN0YWRvIGlycmV2ZXJzaWJsZSBhIHN1IGNvbmRpY2nDs24gcHJldmlhLiBEZWJpZG8gYSBlc3RvIGVzIHF1ZSBsYSB2YXJpYWJpbGlkYWQgY2xpbcOhdGljYSBkZWJlIGRlIHNlciBhbmFsaXphZGEgZW4gcmFuZ29zIHRlbXBvcmFsZXMgcGVxdWXDsW9zIGNvbW8gbWVzZXMsIHlhIHF1ZSBzaSBzZSBwcm9tZWRpYW4gbGFzIHZhcmlhYmxlcyBhIGxvIGxhcmdvIGRlIHVuIGHDsW8gbm8gc2UgZGV0ZWN0YXLDoW4gbGFzIGRpZmVyZW5jaWFzLiANCkxhIHZhcmlhYmlsaWRhZCBjbGltw6F0aWNhIHB1ZWRlIHNlciBjYXVzYWRhIHBvciBvc2NpbGFjaW9uZXMgdMOpcm1pY2FzLCBxdWUgc29uIGRpZmVyZW5jaWFzIG51bcOpcmljYXMgZW50cmUgbG9zIHZhbG9yZXMgbcOheGltb3MgeSBtw61uaW1vcyBkZSB0ZW1wZXJhdHVyYSBvYnNlcnZhZG9zIGVuIHVuIHB1bnRvIGRhZG8gZHVyYW50ZSB1biBwZXLDrW9kbyBkZSB0aWVtcG8uIFVuYSBkZSBlc3RhcyBvc2NpbGFjaW9uZXMgZXMgbGEgT3NjaWxhY2nDs24gZGVsIHN1ciAoRU5PUyksIHF1ZSBzb24gbG9zIGNhbWJpb3MgaW50ZXJhbnVhbGVzLCBjb24gdW5hIGVzY2FsYSBkZSB0aWVtcG8gZGUgdmFyaW9zIGHDsW9zICgyIGEgNyBhw7FvcyksIGRlIGxhcyBjb25kaWNpb25lcyBhdG1vc2bDqXJpY2FzIHkgdGVtcGVyYXR1cmFzIG9jZcOhbmljYXMgZmx1Y3R1YW50ZXMgc29icmUgbG9zIG9jw6lhbm9zIFBhY2lmaWNvIGUgSW5kaWNvIGVjdWF0b3JpYWxlcyAoRmVybsOhbmRleiB5IFJhbcOtcmV6LCAxOTkxKS4gRWwgTmnDsW8gZXMgbGEgZmFzZSBjYWxpZW50ZSBkZWwgRU5PUywgeSBzZSByZWZpZXJlIGEgbGEgaW50ZXJhY2Npw7NuIGNsaW3DoXRpY2Egb2PDqWFuby1hdG3Ds3NmZXJhIGEgZ3JhbiBlc2NhbGEsIGFzb2NpYWRhIGEgdW4gY2FsZW50YW1pZW50byBwZXJpw7NkaWNvLiBQb3Igb3RyYSBwYXJ0ZSwgTGEgTmnDsWEgZXMgbGEgZmFzZSBmcsOtYSBkZWwgRU5PUyBhc29jaWFkYSBhbCBOacOxbywgZXMgcHJlY2VkaWRhIHkgc2VndWlkYSBwb3IgcGVyaW9kb3MgZW4gbG9zIGN1YWxlcyBsYXMgdGVtcGVyYXR1cmFzIHN1cGVyZmljaWFsZXMgZGVsIG1hciBzb24gbcOhcyBiYWphcyBkZSBsbyBub3JtYWwgZW4gZWwgcGFjw61maWNvIGNlbnRyYWwgeSBvcmllbnRhbCB5IGxvcyB2aWVudG9zIGFsaXNpb3Mgc29uIG11eSBmdWVydGVzIChGZXJuw6FuZGV6IHkgUmFtw61yZXosIDE5OTEpLiANCg0KRW4gZXN0ZSBjb250ZXh0bywgZXMgZGUgZ3JhbiBpbXBvcnRhbmNpYSBlc3R1ZGlhciBsYSB2YXJpYWJpbGlkYWQgY2xpbcOhdGljYSwgeWEgcXVlIHNlIHB1ZWRlbiByZWFsaXphciBwZXJzcGVjdGl2YXMgYSBjb3J0byB5IGEgbWVkaWFubyBwbGF6bywgeSBjb24gZXN0byBzZSBwb2Ryw61hbiBpbXBsZW1lbnRhciBhY2Npb25lcyByZXNwZWN0byBhIGxhIGFkYXB0YWNpw7NuIGRlIGxhIHZhcmlhYmlsaWRhZCBjbGltw6F0aWNhIChNYXJrdXMsIDIwMTcpLiBFbCBwcmVzZW50ZSB0cmFiYWpvIHRpZW5lIGNvbW8gb2JqZXRpdm8gYW5hbGl6YXIgbGEgdmFyaWFiaWxpZGFkIGNsaW3DoXRpY2EgZW4gbG9zIMO6bHRpbW9zIDMwIGHDsW9zIGVuIGRvcyBncmFkaWVudGVzIGFsdGl0dWRpbmFsZXMgZW4gbGEgdmVydGllbnRlIGRlbCBDYXJpYmUgKDUgeSAxNDAwIG1zbm0pLCBwYXJhIGRldGVybWluYXIgbG9zIGltcGFjdG9zIHF1ZSBwb2Ryw61hbiBwcm9kdWNpciBsb3MgY2FtYmlvcyBlbiB0ZW1wZXJhdHVyYSAobcOheGltYSB5IG3DrW5pbWEpIHkgcHJlY2lwaXRhY2nDs24gZGUgYW1iYXMgem9uYXMuIA0KIA0KIyMqKk9iamV0aXZvcyoqIyMNCg0KKipPYmpldGl2byBnZW5lcmFsKioNCg0KQW5hbGl6YXIgbGEgdmFyaWFiaWxpZGFkIGNsaW3DoXRpY2EgZW4gbG9zIMO6bHRpbW9zIDMwIGHDsW9zIGVuIGRvcyBncmFkaWVudGVzIGFsdGl0dWRpbmFsZXMgZW4gbGEgdmVydGllbnRlIGRlbCBDYXJpYmUgKDUgeSAxNDAwIG1zbm0pLCBwYXJhIGRldGVybWluYXIgbG9zIGltcGFjdG9zIHF1ZSBwb2Ryw61hbiBnZW5lcmFyIGxvcyBjYW1iaW9zIGVuIHRlbXBlcmF0dXJhIHkgcHJlY2lwaXRhY2nDs24gZGUgYW1iYXMgem9uYXMuIA0KIA0KKipPYmpldGl2b3MgZXNwZWPDrWZpY29zICoqDQoNCjEtRGV0ZXJtaW5hciBsb3MgcHJpbmNpcGFsZXMgY2FtYmlvcyBlbiBsYSBwcmVjaXBpdGFjacOzbiB5IHRlbXBlcmF0dXJhIChtw61uaW1hIHkgbcOheGltYSkgZW4gZG9zIGFsdGl0dWRlcyBkZSBsYSB2ZXJ0aWVudGUgQ2FyaWJlICg1IHkgMTQwMCBtc25tKS4gIA0KDQoyLUNvbXBhcmFyIGxhIHZhcmlhYmlsaWRhZCBjbGltw6F0aWNhIGVudHJlIGxhcyBkb3MgZXN0YWNpb25lcyBkZWwgQ2FyaWJlIGEgZGlmZXJlbnRlcyBhbHRpdHVkZXMgKDUgeSAxNDAwIG1zbm0pLiANCg0KMy1HZW5lcmFyIHBlcnNwZWN0aXZhcyBkZSBsb3MgY2FtYmlvcyBlbiBsYSBwcmVjaXBpdGFjacOzbiB5IHRlbXBlcmF0dXJhIChtw6F4aW1hIHkgbcOtbmltYSkgZGUgYW1iYXMgem9uYXMuIA0KDQoNCiMjKipNYXRlcmlhbGVzIHkgTcOpdG9kb3MqKiMjDQoNCkVuIGVzdGEgaW52ZXN0aWdhY2nDs24gc2UgdXRpbGl6w7MgZGF0b3MgZGUgcHJlY2lwaXRhY2nDs24gKG1tKSB5IHRlbXBlcmF0dXJhIChtw6F4aW1hIHkgbcOtbmltYSwgwrBDKSBkaWFyaW9zIGRlIGRvcyBlc3RhY2lvbmVzIG1ldGVvcm9sw7NnaWNhcyAoTGluZGEgVmlzdGEgeSBMaW3Ds24pIHByb3BvcmNpb25hZG9zIHBvciBlbCBJbnN0aXR1dG8gTWV0ZW9yb2zDs2dpY28gTmFjaW9uYWwgKElNTiwgQ3VhZHJvIDEpLiBBbWJhcyBlc3RhY2lvbmVzIHBvc2VlbiBlbCBtaXNtbyBwZXJpb2RvIGRlIG1lZGljacOzbiBkZSBkYXRvcyBkaWFyaW9zIGVudHJlIDE5ODAgeSAyMDEwIHkgc2UgZW5jdWVudHJhbiBlbiBsYSBtaXNtYSB2ZXJ0aWVudGUgQ2FyaWJlLCBwZXJvIGRpZmllcmVuIGVuIGFsdGl0dWQgKExpbcOzbjogNSBtc25tOyB5IExpbmRhIFZpc3RhOiAxNDAwIG1zbm0pLg0KIVtdKGN1YWRyby0xLnBuZykNCkxhIGFsdGl0dWQgZW50cmUgYW1iYXMgZXN0YWNpb25lcyBmdWUgdW4gZmFjdG9yIGRldGVybWluYW50ZSBlbiBlc3RhIGludmVzdGlnYWNpw7NuLiBTZSB0b21hcm9uIGVuIGN1ZW50YSBlc3RhY2lvbmVzIGNvbiBwb2NhIHNpbWlsaXR1ZCBlbiB0w6lybWlub3MgZGUgZ3JhZGllbnRlIGFsdGl0dWRpbmFsLCBjb24gZWwgZmluIGRlIGRldGVybWluYXIgZWwgY29tcG9ydGFtaWVudG8gZGUgbGFzIGxsdXZpYXMgeSBsYSBhZmVjdGFjacOzbiBkZSBvdHJvcyBmZW7Ds21lbm9zIGVuIGNhZGEgdW5vIGRlIGxhcyBmcm9udGVyYXMgZGUgbGEgdmVydGllbnRlIGRlbCBDYXJpYmUuIExhcyBlc3RhY2lvbmVzIG1ldGVvcm9sw7NnaWNhcyBwb3NlZW4gdW4gcGVyaW9kbyBkZSAzMCBhw7FvcywgcXVlIHJlcHJlc2VudGEgZWwgbcOtbmltbyBkZSBhw7FvcyByZXF1ZXJpZG8gcGFyYSBlbCBlc3R1ZGlvIGRlIGNsaW1hIGVuIHVuYSB6b25hIGVzcGVjw61maWNhLg0KDQojIyMjIyMjIyMjIyMjIyMjIyMjRmlndXJhMSMjIyMjIyMjIyMjIyMjIyMjIyMjDQoNCk1lZGlhbnRlIGVsIHByb2dyYW1hIGRlIFIsIHNlIGNhbGN1bMOzIGVsIHByb21lZGlvIG1lbnN1YWwgZGUgbGEgdGVtcGVyYXR1cmEgbcOheGltYSwgdGVtcGVyYXR1cmEgbcOtbmltYSB5IHByZWNpcGl0YWNpw7NuLiBQYXJhIHBvZGVyIGNhbGN1bGFyIGxhIHRlbXBlcmF0dXJhIHByb21lZGlvIG1lbnN1YWwgZGUgY2FkYSBhw7FvLCBjYWRhIG1lcyBkZWJlIGNvbnRlbmVyIGNvbW8gbcOtbmltbyBlbCA1MCAlIGRlIGxhIGluZm9ybWFjacOzbiBjb21wbGV0YS4gQ29uIHJlc3BlY3RvIGEgbG9zIGRhdG9zIGRlIHByZWNpcGl0YWNpw7NuLCBzZSByZWFsaXphIHVuYSBzdW1hdG9yaWEsIGRlYmUgZGUgZXhpc3RpciBtw61uaW1vIDI0IGTDrWFzIHF1ZSBzZSByZWZpZXJlbiBhbCA4MCUgZGUgbGEgaW5mb3JtYWNpw7NuIGNvbXBsZXRhIHBvciBtZXMuDQogDQpFc3RlIHByb2dyYW1hIG5lY2VzaXRhIGRlIGNpZXJ0b3MgcGFyw6FtZXRyb3MsIHBhcmEgcG9kZXIgcmVhbGl6YXIgdW4gYW7DoWxpc2lzIGVzdGFkw61zdGljby4gU2UgcmVhbGl6w7MgdW5hIGNvbXBhcmFjacOzbiBkZSBsYSBpbmZvcm1hY2nDs24gZGlzcG9uaWJsZSBkdXJhbnRlIGxvcyB0cmVpbnRhIGHDsW9zIGNvbiBkZSBsYSBwcmltZXJhIGTDqWNhZGEgZGUgbG9zIGRhdG9zLiBTZSBjYWxjdWzDsyBwYXJhIGxvcyB2YWxvcmVzIG3DrW5pbW9zIHkgbcOheGltb3MgY29uIGVsIHBlcmNlbnRpbCA1IHkgOTUgdGFudG8gZGUgbGEgdGVtcGVyYXR1cmEgbcOheGltYSBjb21vIGRlIGxhIHRlbXBlcmF0dXJhIG3DrW5pbWEuICBTZSBjYWxjdWzDsyBlbCBwZXJjZW50aWwgOTUgcGFyYSBsb3MgZGF0b3MgZGUgcHJlY2lwaXRhY2nDs24uDQoNClBhcmEgcG9kZXIgZGVzY3JpYmlyIGxhIHZhcmlhYmlsaWRhZCBtZWRpYW50ZSBhbsOhbGlzaXMgZXN0YWTDrXN0aWNvcyBzZSB1dGlsaXphbiBkaXZlcnNhcyBtZXRvZG9sb2fDrWFzLCBsYXMgY3VhbGVzIGVzdHVkaWFuIGVsIGNvbXBvcnRhbWllbnRvIGRlbCBjbGltYSBlbiBlc3BhY2lvIHkgdGllbXBvLiBVbiBlamVtcGxvIGRlIGVsbG8sIGVzIGxhIGFwbGljYWNpw7NuIGRlIHVuIHByb2dyYW1hIGVzdGFkw61zdGljbyBsbGFtYWRvIFJDbGltRGV4LCBlbCBjdWFsIHJlYWxpemEgdW4gYW7DoWxpc2lzIGVzdGFkw61zdGljbyBkZSBsYSB2YXJpYWJpbGlkYWQgdGVtcG9yYWwgZGUgbGFzIHByZWNpcGl0YWNpb25lcywgdGVtcGVyYXR1cmFzIG3DoXhpbWFzIHkgbcOtbmltYXMuIChaaGFuZyB5IFlhbmcsIDIwMDQpLiBFc3RlIHByb2dyYW1hIGZ1ZSBkaXNlw7FhZG8gcGFyYSBkYXIgc2VndWltaWVudG8geSBkZXRlY3RhciBlbCBjYW1iaW8gY2xpbcOhdGljby4gQWRlbcOhcyBzZSB1dGlsaXphIGNvbW8gcGxhdGFmb3JtYSBkZSB0cmFiYWpvLCBlbCBwcm9ncmFtYSBSIHBvciBzZXIgdmlnb3Jvc28geSBjb21wbGV0byBlbiBsbyBxdWUgcmVzcGVjdGEgYWwgYW7DoWxpc2lzIGVzdGFkw61zdGljbyB5IGFsIG1pc21vIHRpZW1wbyBtdXkgbWludWNpb3NvIGVuIGxhIGVsYWJvcmFjacOzbiBkZSBncsOhZmljb3MuIFJDbGltRGV4IGZhY2lsaXRhIHVuYSBpbnRlcmZheiBwYXJhIGVsIGPDoWxjdWxvIGRlIMOtbmRpY2VzIGV4dHJlbW9zIGNsaW3DoXRpY29zIGNvbiBsw61taXRlcyBxdWUgcHVlZGVuIHNlciBkZWZpbmlkb3MgcG9yIGVsIHVzdWFyaW8uIEVzdGUgcHJvZ3JhbWEgcGVybWl0ZSBjYWxjdWxhciAyNyDDrW5kaWNlcyAoWmhhbmcgeSBZYW5nLCAyMDA0KSwgZGVudHJvIGRlIGxvcyBjdWFsZXMgc29sbyAyNiBkZSBlbGxvcyBmdWVyb24gw7p0aWxlcyBwYXJhIGxhIGludmVzdGlnYWNpw7NuIHJlYWxpemFkYS4gDQpMb3Mgw61uZGljZXMgdXRpbGl6YWRvcyBlbiBlbCBwcm9ncmFtYSBSQ2xpbURleCwgc2UgYmFzYW4gZW4gdmFsb3JlcyBkZSB0ZW1wZXJhdHVyYSBtw6F4aW1hIGRpYXJpYSwgdGVtcGVyYXR1cmEgbcOtbmltYSBkaWFyaWEgeSBwcmVjaXBpdGFjacOzbiBkaWFyaWEsIGRvbmRlIFR4IHJlcHJlc2VudGEgbG9zIHZhbG9yZXMgZGUgdGVtcGVyYXR1cmEgbcOheGltYSwgVG4gbG9zIHZhbG9yZXMgZGUgdGVtcGVyYXR1cmEgbcOtbmltYSwgUFJDUCBpbmRpY2EgbGEgY2FudGlkYWQgZGUgcHJlY2lwaXRhY2nDs24geSBSUiBkZWZpbmUgbG9zIGTDrWFzIGjDum1lZG9zIChkw61hcyBjb24gbGx1dmlhKS4gDQpMb3MgdmFsb3JlcyBkZSByZWZlcmVuY2lhIHF1ZSBzZSByZXF1aWVyZW4gcGFyYSBlbCBhbsOhbGlzaXMgZGUgbG9zIMOtbmRpY2VzIHNlIG9idHV2aWVyb24gYSBwYXJ0aXIgZGUgbG9zIHJlZ2lzdHJvcyBkaWFyaW9zIGRlIGxvcyBwcmltZXJvcyAxMCBhw7FvcyBkZSBlc3R1ZGlvICgxOTgwLTE5OTApLiBTZSBjYWxjdWxhcm9uIGxvcyB2YWxvcmVzIG3DoXhpbW9zIGRlIHByZWNpcGl0YWNpw7NuIGRpYXJpYSBxdWUgc2UgcmVnaXN0cmFuIGNvbiBlbCBwZXJjZW50aWwgOTAgcXVlIHNlIHJlZmllcmUgYWwgOTAlIGRlIGxhcyBwcmVjaXBpdGFjaW9uZXM7IHNlIGVzdGFibGVjZSBlc3RlIHZhbG9yIGNvbiBlbCBmaW4gZGUgZWxpbWluYXIgbG9zIHZhbG9yZXMgZXh0cmVtb3MgcG9jbyBmcmVjdWVudGVzIEFkZW3DoXMgZGUgZWxsbywgc2UgY2FsY3VsYW4gbG9zIHZhbG9yZXMgbcOheGltb3MgeSBtw61uaW1vcyBkZSBsYSB0ZW1wZXJhdHVyYSBtw6F4aW1hIHkgbG9zIHZhbG9yZXMgbcOheGltb3MgeSBtw61uaW1vcyBkZSBsYSB0ZW1wZXJhdHVyYSBtw61uaW1hLiBDb24gZWxsbywgc2UgcHJlc2VudGEgdW4gcmVzdW1lbiBkZSBsb3MgMjYgw61uZGljZXMgZGUgUkNsaW1EZXgsIHF1ZSBzZSB1dGlsaXphcm9uIHBhcmEgZWwgYW7DoWxpc2lzIGRlIGVzdGEgaW52ZXN0aWdhY2nDs24geSBzZSBkZXNjcmliZW4gYSBjb250aW51YWNpw7NuLiBDYWJlIGRlc3RhY2FyIHF1ZSB1bm8gZGUgbG9zIMOtbmRpY2VzIGNvbiBsb3MgcXVlIHRyYWJhamEgZXN0ZSBwcm9ncmFtYSwgc2UgdXRpbGl6YSBwYXJhIGNhbGN1bGFyIHRlbXBlcmF0dXJhcyBtZW5vcmVzIGEgbG9zIDDCsEMsIHBvciBlbGxvLCBubyBjdW1wbGUgY29uIGxvcyBvYmpldGl2b3MgZGUgZXN0ZSB0cmFiYWpvLCB5YSBxdWUgQ29zdGEgUmljYSBhbCBzZXIgdW4gcGHDrXMgdHJvcGljYWwsIG5vIGN1ZW50YSBjb24gZXNhcyB0ZW1wZXJhdHVyYXMufQ0KDQohW10oY3VhZHJvLTIucG5nKQ0KQW7DoWxpc2lzIGRlIGRhdG9zDQpMb3Mgw61uZGljZXMgcHJldmlhbWVudGUgbWVuY2lvbmFkb3Mgc2Ugc29tZXRpZXJvbiBhIGFuw6FsaXNpcyBkZSByZWdyZXNpw7NuIGxpbmVhbCAozrE9MC4wNSkuIFRvZG9zIGxvcyBzdXB1ZXN0b3MgZGUgcmVncmVzacOzbiBsaW5lYWwgZnVlcm9uIHNvbWV0aWRvcyBhIHBydWViYSAobm9ybWFsaWRhZCBkZSByZXNpZHVvczogU2hhcGlybyBXaWxrLCBXYWluZSAoMTk5MSk7IGUgaW5kZXBlbmRlbmNpYSBkZSByZXNpZHVvcykuIExvcyBkYXRvcyBhdMOtcGljb3MgZnVlcm9uIHByZXZpYW1lbnRlIGRldGVjdGFkb3MgeSBlbGltaW5hZG9zIGRlIHRvZGFzIGxhcyByZWdyZXNpb25lcyBsaW5lYWxlcy4gDQpSQ2xpbURleCBnZW5lcmEgZGlmZXJlbnRlcyB0aXBvcyBkZSBmaWd1cmFzIGRlIGNhZGEgdW5vIGRlIGxvcyDDrW5kaWNlcyBjYWxjdWxhZG9zLCBzaW4gZW1iYXJnbywgcGFyYSBlZmVjdG9zIGRlIGVzdGEgaW52ZXN0aWdhY2nDs24gZnVlcm9uIG51ZXZhbWVudGUgcmVhbGl6YWRvcyBjb24gYXl1ZGEgZGUgbGVuZ3VhamUgZGUgcHJvZ3JhbWEgZGUgUiwgdmVyc2nDs24gMy41LjEgKFJDb3JlVGVhbSwgMjAxOCkuICANCg0KIyMqKlJlc3VsdGFkb3MqKiMjDQoNCkNvbW8gbG8gbXVlc3RyYSBlbCBjdWFkcm8gMiwgc2UgdXRpbGl6YXJvbiAyNiDDrW5kaWNlcywgZGVudHJvIGRlIGxvcyBjdWFsZXMgc29sbyAxNyByZXN1bHRhcm9uIGNvbiB2YWxvcmVzIHNpZ25pZmljYXRpdm9zIChyZXNhbHRhZG9zIGVuIG5lZ3JpdGEgZW4gZWwgY3VhZHJvKS4gTG9zIHJlc3VsdGFkb3MgZGVsIGFuw6FsaXNpcyBkZSBsb3MgZGF0b3Mgc2lnbmlmaWNhdGl2b3MgZGlhcmlvcyBkZSB0cmVzIGTDqWNhZGFzIHJlYWxpemFkbyB0YW50byBwYXJhIGxhIGVzdGFjacOzbiA4MTAwMyAoTGltw7NuKSB5IGxhIGVzdGFjacOzbiA3MzAxOCAoTGluZGEgVmlzdGEsIEVsIEd1YXJjbykgc2UgbXVlc3RyYW4gZW4gbG9zIGN1YWRyb3MgYSBjb250aW51YWNpw7NuOg0KIVtdKGN1YWRyby0zLnBuZykNCg0KVG9kb3MgbG9zIMOtbmRpY2VzIG1lbmNpb25hZG9zIGVuIGVsIGN1YWRybyAzIHkgNCwgZGVtdWVzdHJhbiBxdWUgY3VtcGxlbiBjb24gdmFsb3JlcyBzaWduaWZpY2F0aXZvcyBhIGxhIGhvcmEgZGUgcmVhbGl6YXIgZWwgYW7DoWxpc2lzIGRlIHJlZ3Jlc2nDs24sIGNvbiB1biBwLXZhbHVlIG1lbm9yIGEgMC4wMDUgZW4gdG9kb3MgbG9zIGNhc29zLCBsbyBxdWUgZGVtdWVzdHJhIHF1ZSBoYXkgZGl2ZXJzb3MgZmFjdG9yZXMgcXVlIGFmZWN0YW4gbGEgbGluZWFsaWRhZCBkZSBsb3MgZGF0b3MsIHNlIG5vdGEgY2xhcmFtZW50ZSBxdWUgZXhpc3RlIHVuYSB0ZW5kZW5jaWEgYSBsYSB2YXJpYWJpbGlkYWQgY2xpbcOhdGljYSwgbGEgbWF5b3LDrWEgZGUgbG9zIMOtbmRpY2VzIG11ZXN0cmFuIHVuIGNvbXBvcnRhbWllbnRvIGNyZWNpZW50ZSBjb24gcmVzcGVjdG8gYWwgdGllbXBvLiBEaWNoYSBpbmZvcm1hY2nDs24gZXN0YWTDrXN0aWNhIHNlIGNvcnJvYm9yYSBvYnNlcnZhbmRvIGxvcyBncsOhZmljb3MgZGUgbG9zIHByaW5jaXBhbGVzIMOtbmRpY2VzIHBhcmEgbGFzIGVzdGFjaW9uZXMgZGUgTGltw7NuIHkgRWwgR3VhcmNvLg0KDQpFbiBsYSBmaWd1cmEgMiBsb3Mgw61uZGljZXMgZGUgbGEgZXN0YWNpw7NuIDczMDE4IChMaW5kYSBWaXN0YSwgRWwgR3VhcmNvKSBzZSBvYnNlcnZhIHF1ZSBsYSBncsOhZmljYSBBIG11ZXN0cmEgcXVlIGR1cmFudGUgbGFzIHRyZXMgw7psdGltYXMgZMOpY2FkYXMgaHVibyB1biBkZXNjZW5zbyBlbiBsYSBwcmVjaXBpdGFjacOzbiBhbHJlZGVkb3IgZGUgMTZtbSBhIDggbW0uIEVuIGxhIGdyw6FmaWNhIEIgc2UgbXVlc3RyYSB1biBhdW1lbnRvIGNvbnN0YW50ZSBkZSBsYSBtw6F4aW1hIHByZWNpcGl0YWNpw7NuIHF1ZSBzZSBlc3TDoSBjb25jZW50cmFuZG8gZW4gY2FlciBlbiA1IGTDrWFzIHNlZ3VpZG9zLiBFbiBsYSBncsOhZmljYSBDIGh1Ym8gdW4gYXVtZW50byBkZSBsYXMgcHJlY2lwaXRhY2lvbmVzIG1heW9yZXMgYSAxMCBtbSBkdXJhbnRlIGxvcyDDumx0aW1vcyAzMCBhw7FvLkVuIGxhIGdyw6FmaWNhIEMgc2UgbW9zdHLDsyB1biBhdW1lbnRvIGNvbnN0YW50ZSBkZSBsYXMgcHJlY2lwaXRhY2lvbmVzIG1heW9yZXMgYSAyMCBtbSBkdXJhbnRlIGxvcyDDumx0aW1vcyAzMCBhw7Fvcy4NCg0KIVtdKGZpZ3VyYS0yLnBuZykNCg0KYGBge3J9DQoiU0RJSSINCmxtKHNkaWl+eWVhcixkYXRhPVg3MzAxOF9SQ2xpbURleF9TRElJX3N1c3RpdHVpZG8pLT54DQpzdW1tYXJ5KHgpLT55DQp5DQp2aXNyZWcoeCxtYWluPSJTRElJIChQcmVjaXBpdGFjacOzbiBEaWFyaWEpIix4bGFiPSJUaWVtcG8gKETDrWFzKSIseWxhYj0iUHJlY2lwaXRhY2nDs24gKG1tKSIpDQpzaGFwaXJvLnRlc3QoeCRyZXNpZHVhbHMpDQoNCiJSWDVEQVkiDQpsbShhbm51YWx+eWVhcixkYXRhPVg3MzAxOF9SQ2xpbURleF9SWDVkYXlfc3VzdGl0dWlkbyktPngNCnN1bW1hcnkoeCktPnkNCnkNCnZpc3JlZyh4LG1haW49IlJYNWRheShNw6F4aW1hIA0KICAgICAgIHByZWNpcGl0YWNpw7NuIDUgZMOtYXMgc2VndWlkb3MpIix4bGFiPSJUaWVtcG8gKEHDsW9zKSIseWxhYj0iUHJlY2lwaXRhY2nDs24gKG1tKSIpDQpzaGFwaXJvLnRlc3QoeCRyZXNpZHVhbHMpDQoNCiJSMTBtbSINCmxtKFIxMH55ZWFyLGRhdGE9WDczMDE4X1JDbGltRGV4X1IxMG1tX3N1c3RpdHVpZG8pLT54DQpzdW1tYXJ5KHgpLT55DQp5DQp2aXNyZWcoeCxtYWluPSJSMTBtbSAoUHJlY2lwaXRhY2lvbiA+IDEwbW0pIix4bGFiPSJUaWVtcG8gKEHDsW9zKSIseWxhYj0iUHJlY2lwaXRhY2nDs24gKG1tKSIpDQpzaGFwaXJvLnRlc3QoeCRyZXNpZHVhbHMpDQoNCiJSMjBtbSINCmxtKFIyMH55ZWFyLGRhdGE9WDczMDE4X1JDbGltRGV4X1IyMG1tX3N1c3RpdHVpZG8pLT54DQpzdW1tYXJ5KHgpLT55DQp5DQp2aXNyZWcoeCxtYWluPSJSMjBtbSAoUHJlY2lwaXRhY2nDs24gPiAyMG1tKSIseGxhYj0iVGllbXBvIChBw7FvcykiLHlsYWI9IlByZWNpcGl0YWNpw7NuIChtbSkiKQ0Kc2hhcGlyby50ZXN0KHgkcmVzaWR1YWxzKQ0KDQpgYGANCg0KDQpFbiBsYSBmaWd1cmEgMyBsYSBwcmVjaXBpdGFjacOzbiBhbnVhbCBlbiBkw61hcyBtdXkgaMO6bWVkb3MgZGUgbGEgZ3LDoWZpY2EgQSBhdW1lbnTDsyBkZSBtYW5lcmEgY29uc3RhbnRlIHlhIHF1ZSBzZSBvYnNlcnZhIHVuIGNhbWJpbyBhbHJlZGVkb3IgZGUgMTAwbW0gYSA1MDBtbSBkdXJhbnRlIGxvcyDDumx0aW1vcyAzMCBhw7Fvcy4gRW4gbGEgZ3LDoWZpY2EgQiBtdWVzdHJhIHF1ZSBjb25mb3JtZSBwYXNhbiBsb3MgYcOxb3MgbG9zIGTDrWFzIHNlY29zIGNvbnNlY3V0aXZvcyB2YW4gZGlzbWludXllbmRvIGRlIG1hbmVyYSBjb25zdGFudGUuIEVuIGxhIGdyw6FmaWNhIEMgbG9zIGTDrWFzIGjDum1lZG9zIGNvbnNlY3V0aXZvcyBhdW1lbnRhcm9uIGRlIG1hbmVyYSBjb25zdGFudGUgZHVyYW50ZSBsb3Mgw7psdGltb3MgMzAgYcOxb3MuIEVuIGxhIGdyw6FmaWNhIEQgbGEgcHJlY2lwaXRhY2nDs24gYW51YWwgdG90YWwgYXVtZW50w7MgYWxyZWRlZG9yIGRlIDEwMDAgbW0gYSAyMDAwIG1tIGRlIG1hbmVyYSBjb25zdGFudGUgZW4gbG9zIGTDrWFzIGjDum1lZG9zIGR1cmFudGUgbG9zIMO6bHRpbW9zIDMwIGHDsW9zLg0KDQohW10oZmlndXJhLTMucG5nKQ0KDQpgYGB7cn0NCiJSOTVQIg0KbG0ocjk1cH55ZWFyLGRhdGEgPVg3MzAxOF9SQ2xpbURleF9SOTVwX3N1c3RpdHVpZG8pLT54DQpzdW1tYXJ5KHgpLT55DQp5DQp2aXNyZWcoeCxtYWluPSJSOTVQKETDrWFzIG11eSBow7ptZWRvcykiLHhsYWI9IlRpZW1wbyhhw7FvcykiLHlsYWI9IlByZWNpcGl0YWNpw7NuIGFudWFsKG1tKSIpDQpzaGFwaXJvLnRlc3QoeCRyZXNpZHVhbHMpDQoNCiJDREQiDQpsbShjZGR+eWVhcixkYXRhPVg3MzAxOF9SQ2xpbURleF9DRERfc3VzdGl0dWlkb29vKS0+eA0Kc3VtbWFyeSh4KS0+eQ0KeQ0KdmlzcmVnKHgsbWFpbj0iQ0REKETDrWFzIHNlY29zIGNvbnNlY3V0aXZvcykiLHhsYWI9IlRpZW1wbyhhw7FvcykiLHlsYWI9IkTDrWFzIHNlY29zKGTDrWFzKSIpDQpzaGFwaXJvLnRlc3QoeCRyZXNpZHVhbHMpDQppbmZsdWVuY2VQbG90KHgpDQp6PC1YNzMwMThfUkNsaW1EZXhfQ0REX3N1c3RpdHVpZG9vb1stYygxLDMsNCwzMSksXQ0KbG0oY2RkfnllYXIsZGF0YSA9IHopLT56Mg0Kc2hhcGlyby50ZXN0KHoyJHJlc2lkdWFscykNCnN1bW1hcnkoejIpDQp2aXNyZWcoejIsbWFpbj0iRMOtYXMgc2Vjb3MgY29uc2VjdXRpdm9zIix4bGFiPSJUaWVtcG8oYcOxb3MiLHlsYWI9IkTDrWFzIHNlY29zKGTDrWFzKSIpDQoNCg0KDQoiQ1dEIg0KbG0oY3dkfnllYXIsZGF0YT1YNzMwMThfUkNsaW1EZXhfQ1dEX3N1c3RpdHVpZG8pLT54DQpzdW1tYXJ5KHgpLT55DQp5DQp2aXNyZWcoeCxtYWluPSJDV0QoRMOtYXMgaMO6bWVkb3MgY29uc2VjdXRpdm9zKSIseGxhYj0iVGllbXBvKGHDsW9zKSIseWxhYj0iRMOtYXMgaMO6bWVkb3MoZMOtYXMpIikNCnNoYXBpcm8udGVzdCh4JHJlc2lkdWFscykNCg0KDQoiUFJDUFRPVCINCmxtKHByY3B0b3R+eWVhcixkYXRhID1YNzMwMThfUkNsaW1EZXhfUFJDUFRPVF9zdXN0aXR1aXIpLT54DQpzdW1tYXJ5KHgpLT55DQp5DQp2aXNyZWcoeCxtYWluPSJQQ1JQVE9UKFByZWNpcGl0YWNpw7NuIHRvdGFsIGFudWFsIGVuIGxvcyBkw61hcyBow7ptZWRvcykiLHhsYWI9IlRpZW1wbyhhw7FvcykiLHlsYWI9IlByZWNpcGl0YWNpw7NuKG1tKSIpDQpzaGFwaXJvLnRlc3QoeCRyZXNpZHVhbHMpDQoNCmBgYA0KDQoNCkVuIGxhIGZpZ3VyYSA0IHNlIG11ZXN0cmFuIGxhIGNhbnRpZGFkIGRlIGTDrWFzIGZyw61vcyAoRmlndXJhIEEpIGRvbmRlIHNlIHB1ZWRlIG9ic2VydmFyIHVuYSBwZW5kaWVudGUgYXNjZW5kZW50ZSBjb24gcmVzcGVjdG8gYSBsYXMgw7psdGltYXMgZMOpY2FkYXMgcG9yIGxvIHF1ZSBlc3RvcyBkw61hcyBhdW1lbnRhbiBjYWRhIHZleiBtw6FzLCBkZSBpZ3VhbCBtYW5lcmEgbGFzIG5vY2hlcyBjYWxpZW50ZSAoRmlndXJhIEIpIHRpZW5kZW4gYSBwcmVzZW50YXIgdW5hIHBlbmRpZW50ZSBhc2NlbmRlbnRlIHlhIHF1ZSBwYXPDsyBkZSB0ZW5lciBzb2xvIHVuYSBub2NoZSBjYWxpZW50ZSBlbiAxOTgwIGEgNSBlbiAxOTkyLg0KDQohW10oZmlndXJhLTQucG5nKQ0KDQpgYGB7cn0NCiJUWDEwUChEw61hcyBGcsOtb3MpIg0KbG0oYW5udWFsfnllYXIsZGF0YT1YNzMwMThfUkNsaW1EZXhfVFgxMFBfc3VzdGl0dWlkbyktPngNCnN1bW1hcnkoeCktPnkNCnkNCnZpc3JlZyh4KQ0KcGxvdCh4KQ0Kc2hhcGlyby50ZXN0KHgkcmVzaWR1YWxzKQ0KaW5mbHVlbmNlUGxvdCh4KQ0KeDI8LVg3MzAxOF9SQ2xpbURleF9UWDEwUF9zdXN0aXR1aWRvWy1jKDEyLDI3LDI4KSxdDQpsbShhbm51YWx+eWVhcixkYXRhPXgyKS0+eDMNCnNoYXBpcm8udGVzdCh4MyRyZXNpZHVhbHMpDQpzdW1tYXJ5KHgzKQ0KdmlzcmVnKHgzKQ0KDQoiVE45MFAgKE5vY2hlcyBDYWxpZW50ZXMpIg0KbG0oYW5udWFsfnllYXIsZGF0YT1YNzMwMThfUkNsaW1EZXhfVE45MFBfc3VzdGl0dWlkbyktPngNCnN1bW1hcnkoeCktPnkNCnkNCnZpc3JlZyh4LG1haW49IlRYMTBQIChOb2NoZXMgQ2FsaWVudGVzKSIseGxhYj0iVGllbXBvIChBw7FvcykiLHlsYWI9Ik5vY2hlcyBDYWxpZW50ZXMgKETDrWFzKSIpDQpzaGFwaXJvLnRlc3QoeCRyZXNpZHVhbHMpDQoNCmBgYA0KDQoNCkVuIGxhIGZpZ3VyYSA1IGxhIHByZWNpcGl0YWNpw7NuIGRlIGxhIGVzdGFjacOzbiA4MTAwMyAoTGltw7NuKSBtdWVzdHJhIHF1ZSBsYSBpbnRlbnNpZGFkIGRlIGRpYXJpYSBkZSBsYSBwcmVjaXBpdGFjacOzbiBkZSBsYSBncsOhZmljYSBBICBhdW1lbnRhIGhhc3RhIGFscmVkZWRvciBkZSAyMiBtbS9kw61hIGR1cmFudGUgbG9zIMO6bHRpbW9zIDMwIGHDsW9zLiBFbiBlbCBjYXNvIGRlIGxhIGdyw6FmaWNhIEIgeSBDIGxhIHByZWNpcGl0YWNpw7NuIG3DoXhpbWEgYXVtZW50w7MgZW4gMSBkw61hIHkgZW4gNSBkw61hcyByZXNwZWN0aXZhbWVudGUgZHVyYW50ZSB1biBwZXJpb2RvIGRlIDMwIGHDsW9zLiBFbiBsYSBncsOhZmljYSBDIHNlIG11ZXN0cmEgdW4gYXVtZW50byBkZSBsb3MgZMOtYXMgbXV5IGjDum1lZG9zIGNvbiByZXNwZWN0byBhIGxvcyDDumx0aW1vcyAzMCBhw7Fvcy4NCg0KIVtdKGZpZ3VyYS01LnBuZykNCg0KYGBge3J9DQoiUlgxZGF5KENhbnRhaWRhZCBtw6F4aW1hIGRlIHByZWNpcGl0YWNpw7NuIGVuIDEgZMOtYSkiDQpkYXRvc1A8LWxtKGFubnVhbH55ZWFyLCBkYXRhID0gWDgxMDAzX1JDbGltRGV4X1JYMWRheV8xXyApDQpkYXRvc1ANCnN1bW1hcnkoZGF0b3NQKQ0Kc2hhcGlyby50ZXN0IChkYXRvc1AkcmVzaWR1YWxzKQ0KZ3JhZjwtdmlzcmVnKGRhdG9zUCwieWVhciIsIHBhcnRpYWw9RiwgbWFpbj0gIlJYMWRheShDYW50YWlkYWQgbcOheGltYSBkZSBwcmVjaXBpdGFjacOzbiBlbiAxIGTDrWEpIiwgeGxhYj0gIlRpZW1wbyhBw7FvcykiLCB5bGFiPSJQcmVjaXBpdGFjacOzbihtbSkiKQ0KZ3JhZg0KDQpgYGANCg0KDQpFbiBsYSBmaWd1cmEgNiBsb3Mgw61uZGljZXMgZGUgcHJlY2lwaXRhY2nDs24gcGFyYSBsYSBlc3RhY2nDs24gMTgwMDMgKExpbcOzbikgbXVlc3RyYW4gZW4gbGEgZ3LDoWZpY2EgQSB1biBhdW1lbnRvIGRlbCBuw7ptZXJvIGRlIGTDrWFzIG1heW9yZXMgYSA0MyBtbSBjb24gcmVzcGVjdG8gYSBsb3Mgw7psdGltb3MgMzAgYcOxb3MgeSBlbiBlbCBjYXNvIGRlIGxhIGdyw6FmaWNhIEIgc2Ugb2JzZXJ2YSBxdWUgbG9zIGTDrWFzIGV4dHJlbWFkYW1lbnRlIHRpZW5lbiB1biBpbmNyZW1lbnRvIGNvbiByZXNwZWN0byBhIGxvcyDDumx0aW1vcyAzMCBhw7Fvcy4NCg0KDQohW10oZmlndXJhLTYucG5nKQ0KDQpgYGB7cn0NCiJSNDMoTsO6bWVybyBkZSBkw61hcz40M21tKSINCmRhdDwtbG0oUm5ufnllYXIsIGRhdGEgPSBYODEwMDNfUkNsaW1EZXhfUjQzXzUxNW1tKQ0KZGF0DQpzdW1tYXJ5KGRhdCkNCnNoYXBpcm8udGVzdCAoZGF0JHJlc2lkdWFscykNCmdyYWY8LXZpc3JlZyhkYXQsInllYXIiLCBwYXJ0aWFsPUYsIG1haW49ICJSNDMoTsO6bWVybyBkZSBkw61hcz40M21tKSIsIHhsYWI9ICJUaWVtcG8oQcOxb3MpIiwgeWxhYj0iRMOtYXM+NDNtbShkw61hcykiKQ0KZ3JhZg0KDQogIlI5OXAoRMOtYXMgZXh0cmVtYWRhbWVudGUgaMO6bWVkb3MpIg0KZGF0b3NsPC1sbShyOTlwfnllYXIsIGRhdGEgPSBYODEwMDNfUkNsaW1EZXhfUjk5cCkNCmRhdG9zbA0Kc3VtbWFyeShkYXRvc2wpDQpzaGFwaXJvLnRlc3QgKGRhdG9zbCRyZXNpZHVhbHMpDQpncmFmPC12aXNyZWcoZGF0b3NsLCJ5ZWFyIiwgcGFydGlhbD1GLCBtYWluPSAiUjk5cChEw61hcyBleHRyZW1hZGFtZW50ZSBow7ptZWRvcykiLCB4bGFiPSAiVGllbXBvKEHDsW9zKSIsIHlsYWI9IlByZWNpcGl0YWNpw7NuKG1tKSIpDQpncmFmDQoNCmBgYA0KDQoNCkVuIGxhIGZpZ3VyYSA3IHNlIG11ZXN0cmEgZW4gbGEgZ3LDoWZpY2EgQSBxdWUgbGEgdGVtcGVyYXR1cmEgZGl1cm5hIGVzIG1lbm9yIGJhamFuZG8gdW4gZ3JhZG8sIGVuIGxhIGdyw6FmaWNhIEIgc2luIGVtYmFyZ28gbG9zIGTDrWFzIGZyw61vcyBoYW4gZGlzbWludWlkbywgeSBsYXMgbm9jaGVzIGNhbGllbnRlcyBhdW1lbnRhZG8gZW4gbGEgKEZpZ3VyYSBDKS4gRW4gbGEgZmlndXJhIEQgc2Ugb2JzZXJ2YSB1bmEgZGlzbWludWNpw7NuIGRlIGxvcyBkw61hcyBjYWxpZW50ZXMgZGUgNSBhIDEuDQoNCiFbXShmaWd1cmEtNy5wbmcpDQoNCmBgYHtyfQ0KIkRUUihUZW1wZXJhdHVyYSBEaXVybmEpIg0KZGF0b3MxPC1sbShhbm51YWx+eWVhciwgZGF0YSA9IFg4MTAwM19SQ2xpbURleF9EVFJfdXNhcikNCmRhdG9zMQ0Kc3VtbWFyeShkYXRvczEpDQpzaGFwaXJvLnRlc3QgKGRhdG9zMSRyZXNpZHVhbHMpDQpncmFmPC12aXNyZWcoZGF0b3MxLCJ5ZWFyIiwgcGFydGlhbD1GLCBtYWluPSAiRFRSKFRlbXBlcmF0dXJhIERpdXJuYSkiLCB4bGFiPSAiVGllbXBvKGTDrWFzKSIsIHlsYWI9IlRlbXBlcmF0dXJhKMKwQykiKQ0KZ3JhZg0KDQoiVE45MFAoTm9jaGVzIGNhbGllbnRlcykiDQpkYXRvczg8LWxtKGFubnVhbH55ZWFyLCBkYXRhID0gWDgxMDAzX1JDbGltRGV4X1ROOTBQKQ0KZGF0b3M4DQpzdW1tYXJ5KGRhdG9zOCkNCnNoYXBpcm8udGVzdCAoZGF0b3M4JHJlc2lkdWFscykNCmdyYWY8LXZpc3JlZyhkYXRvczgsInllYXIiLCBwYXJ0aWFsPUYsIG1haW49ICJUTjkwUChOb2NoZXMgY2FsaWVudGVzKSIsIHhsYWI9ICJUaWVtcG8oQcOxb3MpIiwgeWxhYj0iVGllbXBvKGTDrWFzKSIpDQpncmFmDQoNCiJUWDkwUChEw61hcyBjYWxpZW50ZXMpIg0KZGF0aXM8LWxtKGFubnVhbH55ZWFyLCBkYXRhID0gWDgxMDAzX1JDbGltRGV4X1RYOTBQKQ0KZGF0aXMNCnN1bW1hcnkoZGF0aXMpDQpzaGFwaXJvLnRlc3QgKGRhdGlzJHJlc2lkdWFscykNCmdyYWY8LXZpc3JlZyhkYXRpcywieWVhciIsIHBhcnRpYWw9RiwgbWFpbj0gIlRYOTBQKETDrWFzIGNhbGllbnRlcykiLCB4bGFiPSAiVGllbXBvKEHDsW9zKSIsIHlsYWI9IlRpZW1wbyhkw61hcykiKQ0KZ3JhZg0KDQoNCmBgYA0KDQoNCkZpbmFsbWVudGUgZW4gbGEgZmlndXJhIDggc2Ugb2JzZXJ2YSBxdWUgZW4gbGEgZmlndXJhIEEgaGF5IHVuYSBkaXNtaW51Y2nDs24gZW4gbGFzIHRlbXBlcmF0dXJhcyBtw6F4aW1hcywgZXN0byBjb25maXJtYWRvIHBvciBsYSBmaWd1cmEgQiBkb25kZSBjYWRhIHZleiBzb24gbWVub3MgbG9zIGTDrWFzIGNvbiB0ZW1wZXJhdHVyYXMgbWF5b3JlcyBhIDMywrAgcGFzYW5kbyBkZSAyMCBlbiAxOTgwIGEgMTAgZW4gZWwgMjAxMC4NCg0KIVtdKGZpZ3VyYS04LnBuZykNCg0KYGBge3J9DQoiU1UzMihEw61hcyBkZSB2ZXJhbm8+MzIpIg0KZGF0b3NBPC1sbShzdX55ZWFyLCBkYXRhID0gWDgxMDAzX1JDbGltRGV4X1NVMzJfNCkNCmRhdG9zQQ0Kc3VtbWFyeShkYXRvc0EpDQpzaGFwaXJvLnRlc3QgKGRhdG9zQSRyZXNpZHVhbHMpDQpncmFmPC12aXNyZWcoZGF0b3NBLCJ5ZWFyIiwgcGFydGlhbD1GLCBtYWluPSAiU1UzMihEw61hcyBkZSB2ZXJhbm8+MzIpIiwgeGxhYj0gIlRpZW1wbyhBw7FvcykiLCB5bGFiPSJEw61hcz4zMm1tKGTDrWFzKSIpDQpncmFmDQoNCmBgYA0KDQoNCiMjKipEaXNjdXNpw7NuKiojIw0KUGFyYSBsYSB0ZW1wZXJhdHVyYSBlbiBsYSBlc3RhY2nDs24gZGUgTGluZGEgVmlzdGEsIEVsIEd1YXJjbyAoNzMwMTgpIChGaWd1cmEgNCkgcG9kZW1vcyBvYnNlcnZhciB1bmEgdGVuZGVuY2lhIGVuIGxhcyB0ZW1wZXJhdHVyYXMgYSBkaXNtaW51aXIsIGVzdGUgYXVtZW50byBkZSB0ZW1wZXJhdHVyYXMgYmFqYXMgZW4gZXN0YSByZWdpw7NuIGRlbCBwYcOtcyBwdWVkZSBzZXIgY2F1c2FkbyBwb3IgZWwgYXVtZW50byBlbiBsYSBudWJvc2lkYWQgcXVlIGEgc3UgdmV6IGdlbmVyYSB1bmEgcHJvbG9uZ2FjacOzbiBlbiBsYXMgdGVtcGVyYXR1cmFzIG3DrW5pbWFzIHkgdW5hIGRpc21pbnVjacOzbiBkZSBsYXMgdGVtcGVyYXR1cmFzIG3DoXhpbWFzIChHw7NtZXogeSBGZXJuw6FuZGV6IDE5OTYsIEZlcm7DoW5kZXogeSBSYW3DrXJleiAxOTkxKSxsYXMgY3VhbGVzIHNlZ8O6biBudWVzdHJvcyByZXN1bHRhZG9zIGNvaW5jaWRlbiBjb24gZXN0YXMgY29uY2x1c2lvbmVzLiBEZSBpZ3VhbCBtYW5lcmEgbGEgZXN0YWNpw7NuIGxvY2FsaXphZGEgZW4gTGltw7NuIHByZXNlbnRhIGxhcyBtaXNtYXMgdGVuZGVuY2lhcyBhIGF1bWVudGFyIGxhcyB0ZW1wZXJhdHVyYXMgbcOtbmltYXMgKEZpZ3VyYXMgNyB5IDgpIHBvciBsbyBxdWUgcG9kZW1vcyBjb25jbHVpciBxdWUgYSBwYXJ0aXIgZGUgbG9zIGRhdG9zIHJlY29sZWN0YWRvcyBkZSBhbWJhcyBlc3RhY2lvbmVzIHF1ZSB1bmEgZ3JhbiBwYXJ0ZSBkZSBsYSB2ZXJ0aWVudGUgZGVsIENhcmliZSBlc3TDoSBwcmVzZW50YW5kbyB1bmEgdGVuZGVuY2lhIGhhY2lhIHRlbXBlcmF0dXJhcyBtw6FzIGJhamFzLCBlc3RvIHNlIGRlYmUgYSBxdWUgbGFzIG51YmVzIGluZmx1eWVuIGVuIGxhIGNhbGlkZXogZGVsIGNsaW1hLCBkZSBlc3RhIG1hbmVyYSBsYXMgbnViZXMgcXVlIHNlIGVuY3VlbnRyYW4gYmFqYXMgcHJvdm9jYW4gdW5hIGRpc21pbnVjacOzbiBkZSBsYSB0ZW1wZXJhdHVyYSB5YSBxdWUgc29uIG3DoXMgZGVuc2FzIHkgbm8gcGVybWl0ZW4gcXVlIGxvcyByYXlvcyBkZWwgU29sIHBlbmV0cmVuIGVuIHN1IHRvdGFsaWRhZC4oTWFydmVsLCAyMDE3KQ0KDQpVbiBhdW1lbnRvIGVuIGxhIG51Ym9zaWRhZCBhIGNhdXNhIGRlIGxhcyBwcmVjaXBpdGFjaW9uZXMgZ2VuZXJhIHVuIGZlbsOzbWVubyBxdWUgZXhwbGljYSBlbCBjb21wb3J0YW1pZW50byBkZSBsYXMgbm9jaGVzIGEgY2FsZW50YXJzZSBjYWRhIHZleiBtw6FzLiBMYSBudWJvc2lkYWQgYWwgcmVmbGVqYXIgbGEgcmFkaWFjacOzbiwgdGllbmUgdW4gZG9ibGUgZWZlY3RvIHNvYnJlIGVsIGF1bWVudG8gbyBkaXNtaW51Y2nDs24gZGUgbGFzIHRlbXBlcmF0dXJhcyBlbiBsYSBzdXBlcmZpY2llIHRlcnJlc3RyZS4gUG9yIGVsIGTDrWEsIHVuYSBhbHRhIGNvbmNlbnRyYWNpw7NuIGRlIG51YmVzIHJlZmxlamFuIGxhIHJhZGlhY2nDs24gc29sYXIgcXVlIGluY2lkZSBhIGxhIHN1cGVyZmljaWUgcHJvZHVjaWVuZG8gdW5hIHNlbnNhY2nDs24gZGUgZnJlc2N1cmEsIG1pZW50cmFzIHF1ZSBlbiBsYSBub2NoZSwgbGEgbnVib3NpZGFkIHNlIGVuY2FyZ2EgZGUgcmVmbGVqYXIgbGEgcmFkaWFjacOzbiBpbmZyYXJyb2phIGVtaXRpZGEgZGVzZGUgbGEgc3VwZXJmaWNpZSBkZSBsYSB0aWVycmEsIGdlbmVyYW5kbyBub2NoZXMgbcOhcyBjYWxpZW50ZXMuIEEgc3UgdmV6LCBsYXMgcHJvcGlhcyBudWJlcyBsbGVnYW4gYSBjYWxlbnRhcnNlIGR1cmFudGUgZWwgcHJvY2VzbyB5IGVtaXRlbiBwYXJ0ZSBkZSBlc2EgcmFkaWFjacOzbiBhIGxhIHN1cGVyZmljaWUuIChaw7rDsWlnYSB5IENyZXNwbywgMjAxMCkNCg0KUG9zdGVyaW9ybWVudGUgYWwgYW5hbGl6YXIgbG9zIGRhdG9zIG9idGVuaWRvcyBjb24gcmVzcGVjdG8gYSBsYSBwcmVjaXBpdGFjacOzbiBkZSBsYSBlc3RhY2nDs24gZGUgTGluZGEgVmlzdGEsIEVsIEd1YXJjbyAoRmlndXJhcyAyIHkgMykgcG9kZW1vcyB2ZXIgcXVlIGxhcyBwcmVjaXBpdGFjaW9uZXMgZGlhcmlhcyB0aWVuZGVuIGEgZGlzbWludWlyLCBlc3RvIHB1ZWRlIHNlciBleHBsaWNhZG8gIHlhIHF1ZSBhaG9yYSBsYXMgcHJlY2lwaXRhY2lvbmVzIHNlIGNvbmNlbnRyYW4gZW4gdW4gbsO6bWVybyBkZSBkw61hcyBtZW5vciAoRmlndXJhIDJCKSwgcG9yIGxvIHF1ZSBhdW5xdWUgZGlhcmlhbWVudGUgaGF5IG1lbm9zIHByZWNpcGl0YWNpb25lcywgZXN0byBzZSByZXBvbmUgZW4gdW5hIGNhbnRpZGFkIGRlIGTDrWFzIG1lbm9yIGRlIGxsdXZpYXMuIEVuIGxhIGVzdGFjacOzbiBsb2NhbGl6YWRhIGVuIExpbcOzbiBzZSBvYnNlcnZhbiBsYXMgbWlzbW9zIGNvbmNsdXNpb25lcyAoRmlndXJhcyA1IHkgNikgY29uIGxhIGV4Y2VwY2nDs24gZGUgcXVlIGFkZW3DoXMgbGFzIGxsdXZpYXMgZGlhcmlhcyB0YW1iacOpbiBhdW1lbnRhbiBsbyBxdWUgc2lnbmlmaWNhIHF1ZSBsYXMgcHJlY2lwaXRhY2lvbmVzIGVuIGVzdGEgcmVnacOzbiBoYW4gYXVtZW50YWRvIHNpZ25pZmljYXRpdmFtZW50ZS4gRmVybsOhbmRleiB5IFJhbcOtcmV6ICgxOTkxKSBleHBsaWNhbiBxdWUgZXN0YXMgb2JzZXJ2YWNpb25lcyByZWFsaXphZGFzIGVuIGVsIENhcmliZSBvYmVkZWNlbiBhIGNvbXBvcnRhbWllbnRvcyBwcm9waW9zIGRlbCBmZW7Ds21lbm9zIGRlbCBFTk9TIGVsIGN1YWwgZW50cmUgbG9zIG1lc2VzIGRlIGp1bGlvIHkgYWdvc3RvIHNlIG9ic2VydmEgdW5hIHRlbmRlbmNpYSBhIG11Y2hhIHByZWNpcGl0YWNpw7NuIGNvbiB1bmEgaW5jbGluYWNpw7NuIGEgc2VyIGNvcnRhcyB5IHZpb2xlbnRhcyBlIGluY2x1c28gbGEgYXBhcmljacOzbiBkZSB0ZW1wb3JhbGVzIGRlYmlkbyBhbCBhdW1lbnRvIGRlIGxvcyB2aWVudG9zIGFsaXNpb3Mgc29icmUgZXN0YSByZWdpw7NuLg0KDQpTZSBjYWxjdWzDsywgYSBwYXJ0aXIgZGUgbGFzIHJlZ3Jlc2lvbmVzIG9idGVuaWRhcywgY3XDoW50byBjYW1iaWFyw61hbiBsYXMgdmFyaWFibGVzIHRhbnRvIGRlIHRlbXBlcmF0dXJhIG3DoXhpbWEgeSBtw61uaW1hIGNvbW8gZGUgcHJlY2lwaXRhY2nDs24gYWwgY2FibyBkZSA1IHkgMTAgYcOxb3MgKEN1YWRybyAzKS4gU2Ugbm90w7MgcXVlIGF1bnF1ZSBsb3MgY2FtYmlvcyB2YW4gYSBzZWd1aXIgbGEgbWlzbWEgdGVuZGVuY2lhLCBlc3RvcyBhIGNvcnRvIHkgbWVkaWFubyBwbGF6byBubyBzb24gdW5hIGdyYW4gYW1lbmF6YSB5YSBxdWUgc29uIGlycmVsZXZhbnRlcyB5IG5vIGNvcnJlc3BvbmRlbiBhIHVuIGNhbWJpbyBicnVzY28gZGUgbGFzIGNvbmRpY2lvbmVzIGNsaW3DoXRpY2FzIHBvciBsbyBxdWUgdGFtYmnDqW4gc2UgcHVlZGUgaW5mZXJpciBxdWUgZXN0YXMgY29uZGljaW9uZXMgbm8gdmFuIGEgZ2VuZXJhciB1biBjYW1iaW8gY2xpbcOhdGljbyBjb21vIHRhbC4gUG9yIG90cm8gbGFkbyBzaSBhbmFsaXphbW9zIGxvcyBjYW1iaW9zIGEgbGFyZ28gcGxhem8sIHBvZHLDrWFuIGdlbmVyYXIgY2llcnRvIHJpZXNnbyBhbCBhbHRlcmFyIGRlIG1hbmVyYSBtdXkgc2lnbmlmaWNhdGl2YSBlbCBhbWJpZW50ZSBmw61zaWNvLiBTZSBwdWVkZSBvYnNlcnZhciBldmlkZW5jaWEgZGUgcXVlIGV4aXN0ZW4gY2FtYmlvcyBwb2NvIHJlbGV2YW50ZXMgKEN1YWRybyA0KSB5YSBxdWUgc29uIHNvbG8gZGlleiBhw7FvcyBkZSBkaWZlcmVuY2lhIHBlcm8gY3VhbmRvIGhhYmxhbW9zIGRlIDQwIGHDsW9zIG8gbcOhcywgbGEgdmFyaWFiaWxpZGFkIGNsaW3DoXRpY2Egc2Vyw6EgbcOhcyB2aXNpYmxlcy4gDQoNClBvZGVtb3MgY29uY2x1aXIgcXVlIGV4aXN0ZSB2YXJpYWJpbGlkYWQgY2xpbcOhdGljYSBlbiBsYSB2ZXJ0aWVudGUgZGVsIGNhcmliZSBsbyBjdWFsIHB1ZWRlIHN1cG9uZXIgdW5hIHByb2JsZW3DoXRpY2EgYSBsYXJnbyBwbGF6byB0YW50byBwYXJhIGVsIGVjb3Npc3RlbWEgY29tbyBwYXJhIGxhcyBhY3RpdmlkYWRlcyBodW1hbmFzLCBlc3BlY2lhbG1lbnRlIHBhcmEgbG9zIHNlY3RvcmVzIG3DoXMgdnVsbmVyYWJsZXMgY29tbyBsbyBzb24gZWwgc2VjdG9yIGFncsOtY29sYSB5IGVsIGVjb3R1cmlzbW8gKEFtYWRvciB5IEFsZmFybywgMjAwOSkuIEVuIGVsIGNhc28gZGUgbGEgcHJpbWVyYSBzaXR1YWNpb25lcyBjb21vIGxhcyBpbnVuZGFjaW9uZXMgY2F1c2FuIGFkZW3DoXMgZGUgbGEgcMOpcmRpZGEgZGUgem9uYXMgZGUgY3VsdGl2bywgcXVlIGVsIGFndWEgZGUgbWFyIHNhdHVyZSBlbCBzdWVsbyB5IGVzdGEgc2UgZmlsdHJlIGhhY2lhIGxvcyBtYW50b3MgYWN1w61mZXJvcyBsb3MgY3VhbGVzIHNvbiB1dGlsaXphZG9zIHBhcmEgZWwgcmllZ28gZGUgbG9zIGN1bHRpdm9zLCBhbGdvIGluZGlzcGVuc2FibGUgcGFyYSBsYSBhZ3JpY3VsdHVyYSAoQWx0aWVyaSB5IE5pY2hvbGxzLCAyMDA5KS4gRW4gZWwgY2FzbyBkZWwgZWNvdHVyaXNtbyBEw61heiAoMjAxMikgbWVuY2lvbmEgcXVlIGxhIGNhbnRpZGFkIGRlIGdhbmFuY2lhcyBlbiBsb3MgZW50b3Jub3MgbmF0dXJhbGVzIGNvbiBncmFuIGF0cmFjY2nDs24gdHVyw61zdGljYSBwdWVkZW4gbGxlZ2FyIGEgdmVyc2UgaW5mbHVlbmNpYWRvcyBuZWdhdGl2YW1lbnRlLCBsbGVnYW5kbyBhIHRlbmVyIHDDqXJkaWRhcyBlY29uw7NtaWNhcyBoYXN0YSBkZSB1biAzMCUgc2kgZXN0b3Mgc2UgZW1waWV6YW4gYSB2ZXIgYWZlY3RhZG9zIHBvciBsYSB2YXJpYWJpbGlkYWQgY2xpbcOhdGljYS4gQ29uIGVzdG8gZXMgcGVydGluZW50ZSByZWFsaXphciBtYXlvcmVzIG9ic2VydmFjaW9uZXMgY29uIHJlc3BlY3RvIGEgbGFzIG1lZGlkYXMgbmVjZXNhcmlhcyBwYXJhIGRpc21pbnVpciBsb3MgaW1wYWN0b3MgcXVlIGVzdG9zIGZlbsOzbWVub3MgY2F1c2FuLiANCg0KDQojIyoqUmVmZXJlbmNpYXMqKiMjDQoNClnDocOxZXotQXJhbmNpYmlhLCBBLiwgVHdpbGxleSwgUi4gUi4sIHkgTGFyYS1Eb23DrW5ndWV6LCBBLiBMLiAoMTk5OCkuIExvcyBlY29zaXN0ZW1hcyBkZSBtYW5nbGFyIGZyZW50ZSBhbCBjYW1iaW8gY2xpbcOhdGljbyBnbG9iYWwuIE1hZGVyYSB5IEJvc3F1ZXMsIDQoMiksIDMtMTkuIA0KDQpQdWVydGFzIE9yb3pjbywgTy4gTC4sIHkgQ2FydmFqYWwgRXNjb2JhciwgWS4gKDIwMDgpLiBJbmNpZGVuY2Ugb2YgRWwgTmnDsW8gc291dGhlcm4gb3NjaWxsYXRpb24gaW4gdGhlIHByZWNpcGl0YXRpb24gYW5kIHRoZSB0ZW1wZXJhdHVyZSBvZiB0aGUgYWlyIGluIENvbG9tYmlhLCB1c2luZyBDbGltYXRlIEV4cGxvcmVyLiBJbmdlbmllcsOtYSB5IERlc2Fycm9sbG8sICgyMyksIDEwNC0xMTguIA0KDQpBbHphdGUsIEQuLCBSb2phcywgRS4sIE1vc3F1ZXJhLCBKLiwgeSBSYW3Ds24sIEouICgyMDE1KS4gQ2FtYmlvIGNsaW3DoXRpY28geSB2YXJpYWJpbGlkYWQgY2xpbcOhdGljYSBwYXJhIGVsIHBlcmlvZG8gMTk4MS0yMDEwIGVuIGxhcyBjdWVuY2FzIGRlIGxvcyByw61vcyBadWxpYSB5IHBhbXBsb25pdGEsIG5vcnRlIGRlIFNhbnRhbmRlcuKAk0NvbG9tYmlhLiBSZXZpc3RhIEx1bmEgQXp1bCwgKDQwKS4gDQogDQpMaXphbm8sIE8geSBTYWxhcywgRC4gKDIwMDEpLiBWYXJpYWNpb25lcyBnZW9tb3Jmb2zDs2dpY2FzIGVuIGxvcyDDumx0aW1vcyA1MCBhw7FvcyBlbiBsYSBpc2xhIERhbWFzLCBRdWVwb3MsIENvc3RhIFJpY2EuIFJldmlzdGEgQmlvbG9nw61hIFRyb3BpY2FsLiA0OSgyKToxNzEtMTc3LiANCg0KUmV0YW5hLCBKIHkgVmlsbGFsb2JvcywgUi4gKDIwMDApLiBDYXJhY3Rlcml6YWNpw7NuIHBsdXZpb23DqXRyaWNhIGRlIGxhIGZhc2UgY8OhbGlkYSBkZSBFTk9TIGVuIENvc3RhIFJpY2EgYmFzYWRvIGVuIHByb2JhYmlsaWRhZGVzIGRlIG9jdXJyZW5jaWEgZGUgZXZlbnRvcyBlbiB0cmVzIGVzY2VuYXJpb3M6IHNlY28sIG5vcm1hbCB5IGxsdXZpb3NvLiBUw7NwaWNvcyBNZXRlb3JvbMOzZ2ljb3MgeSBPY2Vhbm9ncsOhZmljb3MuIDcoMik6MTI0LTEzMC4gDQogDQpBbWFkb3IsIEouQS4geSBBLiDigJxDaWNsb25lcyB0cm9waWNhbGVzIHkgc29jaWVkYWQ6IFVuYSBhcHJveGltYWNpw7NuIGFsIGVuZm9xdWUgY2llbnTDrWZpY28gZGUgZXN0b3MgZmVuw7NtZW5vcyBhdG1vc2bDqXJpY29zIGNvbW8gcmVmZXJlbnRlIHBhcmEgbGEgaW52ZXN0aWdhY2nDs24gc29jaWFsIGVuIGRlc2FzdHJlc+KAnSwgZW7igK9Db25jZXBjaW9uZXMgeSBSZXByZXNlbnRhY2lvbmVzIGRlIGxhIE5hdHVyYWxlemEgeSBsYSBDaWVuY2lhIGVuIEFtw6lyaWNhIExhdGluYSwgZWRpdGFkbyBwb3IgUi5WaWFsZXMsIEouIEFtYWRvciB5IEYuSi4gU29sYW5vLiBTYW4gSm9zw6k6IEVkaXRvcmlhbCBkZSBsYSBVbml2ZXJzaWRhZCBkZSBDb3N0YSBSaWNhLCAyMDA5LCAxNTktMTc5LiANCiANCkZhbGxhcywgSi5DIHkgUi4gT3ZpZWRvLiDigJxUZW1wb3JhbGVz4oCdLiBDYXAuIElJSS4gRW464oCvRmVuw7NtZW5vcyBhdG1vc2bDqXJpY29zIHkgY2FtYmlvIGNsaW3DoXRpY28sIHZpc2nDs24gY2VudHJvYW1lcmljYW5hLuKAr0luc3RpdHV0byBNZXRlb3JvbMOzZ2ljbyBOYWNpb25hbCwgU2FuIEpvc8OpLCBDb3N0YSBSaWNhLCAoMjAwMyk6IDM4LiANCiANCkZlcm7DoW5kZXosIFcuLCB5IFJhbcOtcmV6LCBQLiAoMTk5MSkuIEVsIE5pw7FvLCBsYSBPc2NpbGFjacOzbiBkZWwgU3VyIHkgc3VzIGVmZWN0b3MgZW4gQ29zdGEgUmljYTogdW5hIHJldmlzacOzbi4gVGVjbm9sb2fDrWEgZW4gTWFyY2hhLCAxMSgxKSwgMy0xMC4gDQoNClIgQ29yZSBUZWFtICgyMDE4KS4gUjogQSBsYW5ndWFnZSBhbmQgZW52aXJvbm1lbnQgZm9yIHN0YXRpc3RpY2FsIGNvbXB1dGluZy4gUiBGb3VuZGF0aW9uIGZvciBTdGF0aXN0aWNhbCBDb21wdXRpbmcsIFZpZW5uYSwgQXVzdHJpYS4gVVJMIGh0dHBzOi8vd3d3LlItcHJvamVjdC5vcmcvLg0KDQpXYWluZSwgRC4gKDE5OTEpLiBCaW9lc3RhZMOtc3RpY2EsIGJhc2UgcGFyYSBlbCBhbsOhbGlzaXMgZGUgbGFzIGNpZW5jaWFzIGRlIGxhIHNhbHVkLiBNZXhpY28uLCBNw6l4aWNvIERGLiBMSU1VU0EuIFJlY3VwZXJhZG8gZGUgaHR0cDovL3d3dy5hY2FkZW1pYS5lZHUvMTc5ODg3NTIvQmlvZXN0YWRpc3RpY2FfQmFzZV9wYXJhX2VsX2FuYWxpc2lzX2RlX2xhc19jaWVuY2lhc19kZV9sYV9zYWx1ZA0KDQpaaGFuZywgWC4sIHkgWWFuZywgRi4gKDIwMDQpLiBSQ2xpbURleCAoMS4wKS4gTWFudWFsIGRlIFVzdWFyaW8uIENhbmFkw6EuDQoNCk4vQS4gUy9GLiBVbml2ZXJzaWRhZCBOYWNpb25hbCBkZSBDb3N0YSBSaWNhLiBSZWN1cGVyYWRvIGRlIGh0dHA6Ly93d3cucmVwb3NpdG9yaW8udW5hLmFjLmNyL2JpdHN0cmVhbS9oYW5kbGUvMTEwNTYvNzUyMC9lc3RhY2lvbmVzX2ltbl8yMDA4LjIxNi5wbmc/c2VxdWVuY2U9MSZpc0FsbG93ZWQ9eQ0KDQpBbHRpZXJpLCBNLiBBLiwgJiBOaWNob2xscywgQy4gSS4gKDIwMDkpLiBDYW1iaW8gY2xpbcOhdGljbyB5IGFncmljdWx0dXJhIGNhbXBlc2luYTogaW1wYWN0b3MgeSByZXNwdWVzdGFzIGFkYXB0YXRpdmFzLiBMRUlTQSByZXZpc3RhIGRlIGFncm9lY29sb2fDrWEsIDE0LCA1LTguDQoNCkfDs21leiwgSS4gRS4sIHkgRmVybsOhbmRleiwgVy4gKDE5OTYpLiBWYXJpYWNpw7NuIGludGVyYW51YWwgZGUgbGEgdGVtcGVyYXR1cmEgZW4gQ29zdGEgUmljYS4gVG9wLiBNZXRlb3IuIE9jZWFub2dyLCAzKDEpLCAyNy00NC4NCg0KQW1hZG9yLCBKLiBBLiwgeSBBbGZhcm8sIEUuIEouICgyMDA5KS4gTcOpdG9kb3MgZGUgcmVkdWNjacOzbiBkZSBlc2NhbGE6IGFwbGljYWNpb25lcyBhbCB0aWVtcG8sIGNsaW1hLCB2YXJpYWJpbGlkYWQgY2xpbcOhdGljYSB5IGNhbWJpbyBjbGltw6F0aWNvLiBSZXZpYmVjOiByZXZpc3RhIGliZXJvYW1lcmljYW5hIGRlIGVjb25vbcOtYSBlY29sw7NnaWNhLCAxMSwgMzktNTIuDQoNCk1vcmVuby1Ew61heiwgTS4gTC4gKDIwMTIpLiBBY3RpdmlkYWRlcyBzb2Npb2Vjb27Ds21pY2FzIGVuIGVsIFBhcnF1ZSBOYWNpb25hbCBJc2xhIGRlbCBDb2NvLCBDb3N0YSBSaWNhIHkgcG9zaWJsZXMgZWZlY3RvcyBkZSBsYSB2YXJpYWJpbGlkYWQgY2xpbcOhdGljYS4gUmV2aXN0YSBkZSBCaW9sb2fDrWEgVHJvcGljYWwsIDYwKDMpLCAxMTMtMTI5Lg0KDQpaw7rDsWlnYSwgSS4sIHkgQ3Jlc3BvLCBFLiAoMjAxMCkgTWV0ZW9yb2xvZ8OtYSB5IGNsaW1hdG9sb2fDrWEuIFJlY3VwZXJhZG8gZGUgaHR0cHM6Ly9ib29rcy5nb29nbGUuY28uY3IvYm9va3M/aWQ9RTZpWEoyUVppUTRDJnBnPVBBNjMmZHE9cmFkaWFjaW9uK2luZnJhcnJvamErbm9jdHVybmErY2Fsb3IrZW4rbGFzK25vY2hlcytudWJvc2lkYWQmaGw9ZXMmc2E9WCZ2ZWQ9MGFoVUtFd2lHbHViNjdhX2VBaFVrd2xrS0hiN09CLWdRNkFFSUt6QUIjdj1vbmVwYWdlJnE9cmFkaWFjaW9uJTIwaW5mcmFycm9qYSUyMG5vY3R1cm5hJTIwY2Fsb3IlMjBlbiUyMGxhcyUyMG5vY2hlcyUyMG51Ym9zaWRhZCZmPWZhbHNlDQoNCg0KIyMqKkFuZXhvcyoqIyMNCkFuZXhvIDEuIFByZWNpcGl0YWNpw7NuIG1lbnN1YWwgZXN0YWNpw7NuIDgxMDAzIChMaW3Ds24pDQoNCiFbXShhbmV4by0xLnBuZykNCg0KQW5leG8yLiBQcmVjaXBpdGFjacOzbiBtZW5zdWFsIGVzdGFjacOzbiAgNzMwMTggKExpbmRhIFZpc3RhLCBFbCBHdWFyY28pDQoNCiFbXShhbmV4by0yLnBuZykNCg0KQW5leG8gMy5UZW1wZXJhdHVyYSBtZW5zdWFsIGVzdGFjacOzbiA4MTAwMyAoTGltw7NuKQ0KDQohW10oYW5leG8tMy5wbmcpDQpBbmV4byA0Lkluc3RhbGFjacOzbiBkZSBwYXF1ZXRlcyByZXF1ZXJpZG9zIHBhcmEgbGEgb3JnYW5pemFjacOzbiBkZSBkYXRvcw0KYGBge3IgZXZhbD1GQUxTRSwgaW5jbHVkZT1UUlVFfQ0KaW5zdGFsbC5wYWNrYWdlcygicmVzaGFwZSIpDQppbnN0YWxsLnBhY2thZ2VzKCJzcGxpdHN0YWNrc2hhcGUiKQ0KaW5zdGFsbC5wYWNrYWdlcygicGx5ciIpDQppbnN0YWxsLnBhY2thZ2VzKCJnZ3Bsb3QyIikNCmluc3RhbGwucGFja2FnZXMoInh0cyIpDQppbnN0YWxsLnBhY2thZ2VzKCJkeWdyYXBocyIpDQpgYGANCg0KQW5leG8gNS5Pcmdhbml6YWNpw7NuIGRlIGxhIGJhc2UgZGUgZGF0b3MNCmBgYHtyIGV2YWw9RkFMU0UsIGluY2x1ZGU9VFJVRX0NCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyMgU2NyaXB0IHBhcmEgb3JnYW5pemFyIEluZm9ybWFjacOzbiBDbGltw6F0aWNhIElOQU1ISSAyMDE2DQojIyBDcmVkaXRzOiBKdW5pb3IgUGFzdG9yIFDDiVJFWi1NT0xJTkENCiMjIERhdGU6IDIwMTcvMTAvMDgNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0Kcm0obGlzdCA9IGxzKCkpICNSZW1vdmUgYWxsIG9iamVjdHMNCmdyYXBoaWNzLm9mZigpICAjUmVtb3ZlIGFsbCBncmFwaGljcw0KY2F0KCJcMDE0IikgICAgICNSZW1vdmUgc2NyaXB0IGluIHdpbmRvd3MgY29uc29sZQ0KaWYoIWdyZXBsKCJPcmdhbml6YWNpw7NuIGluZm9ybWFjacOzbiBjbGltw6F0aWNhIiwgZ2V0d2QoKSkpe3g9IGNhdChwcm9tcHQgPSAiUGxlYXNlIHNldCB0aGUgd29ya2luZyBkaXJlY3RvcnkgdG8gdGhlIHByb2plY3QgZm9sZGVyICIpfQ0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojIyBDYXJnYXIgbG9zIHBhcXVldGVzIHJlcXVlcmlkb3MgcGFyYSBvcmdhbml6YXIgSW5mb3JtYWNpw7NuIENsaW3DoXRpY2ENCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBpbnN0YWxsLnBhY2thZ2VzKCJyZXNoYXBlIikNCmxpYnJhcnkocmVzaGFwZSkNCiMgaW5zdGFsbC5wYWNrYWdlcygic3BsaXRzdGFja3NoYXBlIikNCmxpYnJhcnkoc3BsaXRzdGFja3NoYXBlKQ0KIyBpbnN0YWxsLnBhY2thZ2VzKCJwbHlyIikNCmxpYnJhcnkoInBseXIiLCBsaWIubG9jPSJ+L1Ivd2luLWxpYnJhcnkvMy40IikNCiMgaW5zdGFsbC5wYWNrYWdlcygiZ2dwbG90MiIpDQpsaWJyYXJ5KGdncGxvdDIpDQojIGluc3RhbGwucGFja2FnZXMoInh0cyIpDQpsaWJyYXJ5KHh0cykgDQojIGluc3RhbGwucGFja2FnZXMoImR5Z3JhcGhzIikNCmxpYnJhcnkoZHlncmFwaHMpDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCg0KDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMjIFBSRUNJUElUQUNJT04gICAgLT4gICBMb2FkaW5nIGRhdGFiYXNlIA0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQpQcmVjaXBpdGFjaW9uPC1yZWFkLmRlbGltKCJEYXRhL1BSQ1AudHh0IixoZWFkZXI9RkFMU0Usc2VwPSJcdCIsZGVjPSIuIikNCm5hbWVzKFByZWNpcGl0YWNpb24pPC1jKCJjb2RpZ28iLCJ5ZWFyIiwibWVzIiwiZDEiLCJkMiIsImQzIiwiZDQiLCJkNSIsImQ2IiwiZDciLCJkOCIsImQ5IiwiZDEwIiwiZDExIiwiZDEyIiwiZDEzIiwiZDE0IiwiZDE1IiwiZDE2IiwiZDE3IiwiZDE4IiwiZDE5IiwiZDIwIiwiZDIxIiwiZDIyIiwiZDIzIiwiZDI0IiwiZDI1IiwiZDI2IiwiZDI3IiwiZDI4IiwiZDI5IiwiZDMwIiwiZDMxIikNCmxpYnJhcnkocmVzaGFwZSkNClByZWNpcGl0YWNpb24gPC0gbWVsdChQcmVjaXBpdGFjaW9uLCBpZD1jKCJjb2RpZ28iLCJ5ZWFyIiwibWVzIikpDQpQcmVjaXBpdGFjaW9uJHZhbHVlPC1hcy5udW1lcmljKGFzLmNoYXJhY3RlcihQcmVjaXBpdGFjaW9uJHZhbHVlKSkNCm5hbWVzKFByZWNpcGl0YWNpb24pPC1jKCJjb2RpZ28iLCJ5ZWFyIiwibW9udGgiLCJkYXkiLCJQUkNQIikNClByZWNpcGl0YWNpb248LWRhdGEuZnJhbWUoUHJlY2lwaXRhY2lvbikNClByZWNpcGl0YWNpb24kZGF5PC1hcy5jaGFyYWN0ZXIoUHJlY2lwaXRhY2lvbiRkYXkpDQpQcmVjaXBpdGFjaW9uJGRheTwtZ3N1YigiZCIsICIiLCBQcmVjaXBpdGFjaW9uJGRheSkNClByZWNpcGl0YWNpb24kZGF5PC1hcy5udW1lcmljKFByZWNpcGl0YWNpb24kZGF5KQ0KUHJlY2lwaXRhY2lvbiRkYXRlPC1wYXN0ZShQcmVjaXBpdGFjaW9uJHllYXIsUHJlY2lwaXRhY2lvbiRtb250aCxQcmVjaXBpdGFjaW9uJGRheSwgc2VwPSItIikNClByZWNpcGl0YWNpb24kZGF0ZTwtYXMuRGF0ZShQcmVjaXBpdGFjaW9uJGRhdGUsIGZvcm1hdCA9ICIlWS0lbS0lZCIpDQpQcmVjaXBpdGFjaW9uPC1QcmVjaXBpdGFjaW9uW29yZGVyKFByZWNpcGl0YWNpb24kY29kaWdvLFByZWNpcGl0YWNpb24keWVhciwgUHJlY2lwaXRhY2lvbiRtb250aCwgUHJlY2lwaXRhY2lvbiRkYXkpLF0NClByZWNpcGl0YWNpb24kUFJDUDwtcmVwbGFjZShQcmVjaXBpdGFjaW9uJFBSQ1AsIGlzLm5hKFByZWNpcGl0YWNpb24kUFJDUCksIC05OS45KQ0KUHJlY2lwaXRhY2lvbiRkYXRlMjwtUHJlY2lwaXRhY2lvbiRkYXRlDQpQcmVjaXBpdGFjaW9uJGRhdGUyPC1pZmVsc2UoaXMubmEoUHJlY2lwaXRhY2lvbiRkYXRlMiksMSwwKQ0KUHJlY2lwaXRhY2lvbltQcmVjaXBpdGFjaW9uJGRhdGUyPT0xLF08LU5BDQpQcmVjaXBpdGFjaW9uPC1QcmVjaXBpdGFjaW9uW29yZGVyKFByZWNpcGl0YWNpb24kY29kaWdvLFByZWNpcGl0YWNpb24keWVhciwgUHJlY2lwaXRhY2lvbiRtb250aCwgUHJlY2lwaXRhY2lvbiRkYXkpLF0NClByZWNpcGl0YWNpb24kZGF0ZTI8LU5VTEwNClByZWNpcGl0YWNpb248LW5hLm9taXQoUHJlY2lwaXRhY2lvbikNClByZWNpcGl0YWNpb25fb2s8LWRhdGEuZnJhbWUoKQ0KZm9yKGkgaW4gdW5pcXVlKFByZWNpcGl0YWNpb24kY29kaWdvKSl7DQogICAgc3ViPC1QcmVjaXBpdGFjaW9uW1ByZWNpcGl0YWNpb24kY29kaWdvPT1pLF0NCiAgICBkYXRlPC1kYXRhLmZyYW1lKHNlcShhcy5EYXRlKHBhc3RlKGZvcm1hdChhcy5EYXRlKG1pbihuYS5vbWl0KHN1YiRkYXRlKSksIGZvcm1hdD0iJVkvJW0vJWQiKSwiJVkiKSwiLTAxLTAxIiksZm9ybWF0ID0gIiVZIC0lbS0lZCIpLA0KICAgICAgICAgICAgICAgICAgICAgICAgIGFzLkRhdGUocGFzdGUoZm9ybWF0KGFzLkRhdGUobWF4KG5hLm9taXQoc3ViJGRhdGUpKSwgZm9ybWF0PSIlWS8lbS8lZCIpLCIlWSIpLCItMTItMzEiKSxmb3JtYXQgPSAiJVkgLSVtLSVkIiksDQogICAgICAgICAgICAgICAgICAgICAgICAgYnk9ImRheSIpKQ0KICAgIG5hbWVzKGRhdGUpPC1jKCJkYXRlIikNCiAgICBkYXRlJGRhdGU8LWFzLkRhdGUoZGF0ZSRkYXRlLCBmb3JtYXQgPSAiJVktJW0tJWQiKQ0KICAgIHN1YjI8LW1lcmdlKGRhdGUsc3ViLCBhbGw9VFJVRSkNCiAgICBzdWIyJGNvZGlnbzwtYyhpKQ0KICAgIFByZWNpcGl0YWNpb25fb2sgPC0gcmJpbmQoUHJlY2lwaXRhY2lvbl9vayxkYXRhLmZyYW1lKHN1YjIpKQ0KfQ0KUHJlY2lwaXRhY2lvbl9vayRkYXRlMjwtUHJlY2lwaXRhY2lvbl9vayRkYXRlDQpsaWJyYXJ5KHNwbGl0c3RhY2tzaGFwZSkNClByZWNpcGl0YWNpb25fb2s8LWNTcGxpdChQcmVjaXBpdGFjaW9uX29rLCAiZGF0ZTIiLCAiLSIpDQpQcmVjaXBpdGFjaW9uX29rPC1kYXRhLmZyYW1lKFByZWNpcGl0YWNpb25fb2tbLDJdLFByZWNpcGl0YWNpb25fb2tbLDddLFByZWNpcGl0YWNpb25fb2tbLDhdLFByZWNpcGl0YWNpb25fb2tbLDldLFByZWNpcGl0YWNpb25fb2tbLDZdKQ0KbmFtZXMoUHJlY2lwaXRhY2lvbl9vayk8LWMoImNvZGlnbyIsInllYXIiLCJtb250aCIsImRheSIsIlBDUFQiKQ0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojIyBUbWF4ICAgICAgICAgICAgIC0+ICAgTG9hZGluZyBkYXRhYmFzZSANCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KVG1heDwtcmVhZC5kZWxpbSgiRGF0YS9UTUFYLnR4dCIsaGVhZGVyPUZBTFNFLHNlcD0iXHQiLGRlYz0iLiIpDQpuYW1lcyhUbWF4KTwtYygiY29kaWdvIiwieWVhciIsIm1lcyIsImQxIiwiZDIiLCJkMyIsImQ0IiwiZDUiLCJkNiIsImQ3IiwiZDgiLCJkOSIsImQxMCIsImQxMSIsImQxMiIsImQxMyIsImQxNCIsImQxNSIsImQxNiIsImQxNyIsImQxOCIsImQxOSIsImQyMCIsImQyMSIsImQyMiIsImQyMyIsImQyNCIsImQyNSIsImQyNiIsImQyNyIsImQyOCIsImQyOSIsImQzMCIsImQzMSIpDQpsaWJyYXJ5KHJlc2hhcGUpDQpUbWF4IDwtIG1lbHQoVG1heCwgaWQ9YygiY29kaWdvIiwieWVhciIsIm1lcyIpKQ0KVG1heCR2YWx1ZTwtYXMubnVtZXJpYyhhcy5jaGFyYWN0ZXIoVG1heCR2YWx1ZSkpDQpuYW1lcyhUbWF4KTwtYygiY29kaWdvIiwieWVhciIsIm1vbnRoIiwiZGF5IiwiVG1heCIpDQpUbWF4PC1kYXRhLmZyYW1lKFRtYXgpDQpUbWF4JGRheTwtYXMuY2hhcmFjdGVyKFRtYXgkZGF5KQ0KVG1heCRkYXk8LWdzdWIoImQiLCAiIiwgVG1heCRkYXkpDQpUbWF4JGRheTwtYXMubnVtZXJpYyhUbWF4JGRheSkNClRtYXgkZGF0ZTwtcGFzdGUoVG1heCR5ZWFyLFRtYXgkbW9udGgsVG1heCRkYXksIHNlcD0iLSIpDQpUbWF4JGRhdGU8LWFzLkRhdGUoVG1heCRkYXRlLCBmb3JtYXQgPSAiJVktJW0tJWQiKQ0KVG1heDwtVG1heFtvcmRlcihUbWF4JGNvZGlnbyxUbWF4JHllYXIsIFRtYXgkbW9udGgsIFRtYXgkZGF5KSxdDQpUbWF4JFRtYXg8LXJlcGxhY2UoVG1heCRUbWF4LCBpcy5uYShUbWF4JFRtYXgpLCAtOTkuOSkNClRtYXgkZGF0ZTI8LVRtYXgkZGF0ZQ0KVG1heCRkYXRlMjwtaWZlbHNlKGlzLm5hKFRtYXgkZGF0ZTIpLDEsMCkNClRtYXhbVG1heCRkYXRlMj09MSxdPC1OQQ0KVG1heDwtVG1heFtvcmRlcihUbWF4JGNvZGlnbyxUbWF4JHllYXIsIFRtYXgkbW9udGgsIFRtYXgkZGF5KSxdDQpUbWF4JGRhdGUyPC1OVUxMDQpUbWF4PC1uYS5vbWl0KFRtYXgpDQpUbWF4X29rPC1kYXRhLmZyYW1lKCkNCmZvcihpIGluIHVuaXF1ZShUbWF4JGNvZGlnbykpew0KICAgIHN1YjwtVG1heFtUbWF4JGNvZGlnbz09aSxdDQogICAgZGF0ZTwtZGF0YS5mcmFtZShzZXEoYXMuRGF0ZShwYXN0ZShmb3JtYXQoYXMuRGF0ZShtaW4obmEub21pdChzdWIkZGF0ZSkpLCBmb3JtYXQ9IiVZLyVtLyVkIiksIiVZIiksIi0wMS0wMSIpLGZvcm1hdCA9ICIlWSAtJW0tJWQiKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICBhcy5EYXRlKHBhc3RlKGZvcm1hdChhcy5EYXRlKG1heChuYS5vbWl0KHN1YiRkYXRlKSksIGZvcm1hdD0iJVkvJW0vJWQiKSwiJVkiKSwiLTEyLTMxIiksZm9ybWF0ID0gIiVZIC0lbS0lZCIpLA0KICAgICAgICAgICAgICAgICAgICAgICAgIGJ5PSJkYXkiKSkNCiAgICBuYW1lcyhkYXRlKTwtYygiZGF0ZSIpDQogICAgZGF0ZSRkYXRlPC1hcy5EYXRlKGRhdGUkZGF0ZSwgZm9ybWF0ID0gIiVZLSVtLSVkIikNCiAgICBzdWIyPC1tZXJnZShkYXRlLHN1YiwgYWxsPVRSVUUpDQogICAgc3ViMiRjb2RpZ288LWMoaSkNCiAgICBUbWF4X29rIDwtIHJiaW5kKFRtYXhfb2ssZGF0YS5mcmFtZShzdWIyKSkNCn0NClRtYXhfb2skZGF0ZTI8LVRtYXhfb2skZGF0ZQ0KbGlicmFyeShzcGxpdHN0YWNrc2hhcGUpDQpUbWF4X29rPC1jU3BsaXQoVG1heF9vaywgImRhdGUyIiwgIi0iKQ0KVG1heF9vazwtZGF0YS5mcmFtZShUbWF4X29rWywyXSxUbWF4X29rWyw3XSxUbWF4X29rWyw4XSxUbWF4X29rWyw5XSxUbWF4X29rWyw2XSkNCm5hbWVzKFRtYXhfb2spPC1jKCJjb2RpZ28iLCJ5ZWFyIiwibW9udGgiLCJkYXkiLCJUbWF4IikNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyMgVG1pbiAgICAgICAgICAgICAtPiAgIExvYWRpbmcgZGF0YWJhc2UgDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNClRtaW48LXJlYWQuZGVsaW0oIkRhdGEvVE1JTi50eHQiLGhlYWRlcj1GQUxTRSxzZXA9Ilx0IixkZWM9Ii4iKQ0KbmFtZXMoVG1pbik8LWMoImNvZGlnbyIsInllYXIiLCJtZXMiLCJkMSIsImQyIiwiZDMiLCJkNCIsImQ1IiwiZDYiLCJkNyIsImQ4IiwiZDkiLCJkMTAiLCJkMTEiLCJkMTIiLCJkMTMiLCJkMTQiLCJkMTUiLCJkMTYiLCJkMTciLCJkMTgiLCJkMTkiLCJkMjAiLCJkMjEiLCJkMjIiLCJkMjMiLCJkMjQiLCJkMjUiLCJkMjYiLCJkMjciLCJkMjgiLCJkMjkiLCJkMzAiLCJkMzEiKQ0KbGlicmFyeShyZXNoYXBlKQ0KVG1pbiA8LSBtZWx0KFRtaW4sIGlkPWMoImNvZGlnbyIsInllYXIiLCJtZXMiKSkNClRtaW4kdmFsdWU8LWFzLm51bWVyaWMoYXMuY2hhcmFjdGVyKFRtaW4kdmFsdWUpKQ0KbmFtZXMoVG1pbik8LWMoImNvZGlnbyIsInllYXIiLCJtb250aCIsImRheSIsIlRtaW4iKQ0KVG1pbjwtZGF0YS5mcmFtZShUbWluKQ0KVG1pbiRkYXk8LWFzLmNoYXJhY3RlcihUbWluJGRheSkNClRtaW4kZGF5PC1nc3ViKCJkIiwgIiIsIFRtaW4kZGF5KQ0KVG1pbiRkYXk8LWFzLm51bWVyaWMoVG1pbiRkYXkpDQpUbWluJGRhdGU8LXBhc3RlKFRtaW4keWVhcixUbWluJG1vbnRoLFRtaW4kZGF5LCBzZXA9Ii0iKQ0KVG1pbiRkYXRlPC1hcy5EYXRlKFRtaW4kZGF0ZSwgZm9ybWF0ID0gIiVZLSVtLSVkIikNClRtaW48LVRtaW5bb3JkZXIoVG1pbiRjb2RpZ28sVG1pbiR5ZWFyLCBUbWluJG1vbnRoLCBUbWluJGRheSksXQ0KVG1pbiRUbWluPC1yZXBsYWNlKFRtaW4kVG1pbiwgaXMubmEoVG1pbiRUbWluKSwgLTk5LjkpDQpUbWluJGRhdGUyPC1UbWluJGRhdGUNClRtaW4kZGF0ZTI8LWlmZWxzZShpcy5uYShUbWluJGRhdGUyKSwxLDApDQpUbWluW1RtaW4kZGF0ZTI9PTEsXTwtTkENClRtaW48LVRtaW5bb3JkZXIoVG1pbiRjb2RpZ28sVG1pbiR5ZWFyLCBUbWluJG1vbnRoLCBUbWluJGRheSksXQ0KVG1pbiRkYXRlMjwtTlVMTA0KVG1pbjwtbmEub21pdChUbWluKQ0KVG1pbl9vazwtZGF0YS5mcmFtZSgpDQpmb3IoaSBpbiB1bmlxdWUoVG1pbiRjb2RpZ28pKXsNCiAgICBzdWI8LVRtaW5bVG1pbiRjb2RpZ289PWksXQ0KICAgIGRhdGU8LWRhdGEuZnJhbWUoc2VxKGFzLkRhdGUocGFzdGUoZm9ybWF0KGFzLkRhdGUobWluKG5hLm9taXQoc3ViJGRhdGUpKSwgZm9ybWF0PSIlWS8lbS8lZCIpLCIlWSIpLCItMDEtMDEiKSxmb3JtYXQgPSAiJVkgLSVtLSVkIiksDQogICAgICAgICAgICAgICAgICAgICAgICAgYXMuRGF0ZShwYXN0ZShmb3JtYXQoYXMuRGF0ZShtYXgobmEub21pdChzdWIkZGF0ZSkpLCBmb3JtYXQ9IiVZLyVtLyVkIiksIiVZIiksIi0xMi0zMSIpLGZvcm1hdCA9ICIlWSAtJW0tJWQiKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICBieT0iZGF5IikpDQogICAgbmFtZXMoZGF0ZSk8LWMoImRhdGUiKQ0KICAgIGRhdGUkZGF0ZTwtYXMuRGF0ZShkYXRlJGRhdGUsIGZvcm1hdCA9ICIlWS0lbS0lZCIpDQogICAgc3ViMjwtbWVyZ2UoZGF0ZSxzdWIsIGFsbD1UUlVFKQ0KICAgIHN1YjIkY29kaWdvPC1jKGkpDQogICAgVG1pbl9vayA8LSByYmluZChUbWluX29rLGRhdGEuZnJhbWUoc3ViMikpDQp9DQpUbWluX29rJGRhdGUyPC1UbWluX29rJGRhdGUNCmxpYnJhcnkoc3BsaXRzdGFja3NoYXBlKQ0KVG1pbl9vazwtY1NwbGl0KFRtaW5fb2ssICJkYXRlMiIsICItIikNClRtaW5fb2s8LWRhdGEuZnJhbWUoVG1pbl9va1ssMl0sVG1pbl9va1ssN10sVG1pbl9va1ssOF0sVG1pbl9va1ssOV0sVG1pbl9va1ssNl0pDQpuYW1lcyhUbWluX29rKTwtYygiY29kaWdvIiwieWVhciIsIm1vbnRoIiwiZGF5IiwiVG1pbiIpDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCg0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyMgUENQVF9UbWF4X1RtaW4gICAtPiAgIExvYWRpbmcgZGF0YWJhc2UgDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNClBDUFRfVG1heDwtbWVyZ2UoUHJlY2lwaXRhY2lvbiwgIFRtYXgsIGJ5PWMoImRhdGUiLCJjb2RpZ28iLCAieWVhciIsICJtb250aCIsICJkYXkiKSwgYWxsPVRSVUUpDQpQQ1BUX1RtYXhfVG1pbjwtbWVyZ2UoUENQVF9UbWF4LCBUbWluLCBieT1jKCJkYXRlIiwiY29kaWdvIiwgInllYXIiLCAibW9udGgiLCAiZGF5IiksIGFsbD1UUlVFKQ0KUENQVF9UbWF4X1RtaW5fb2s8LWRhdGEuZnJhbWUoKQ0KZm9yKGkgaW4gdW5pcXVlKFBDUFRfVG1heF9UbWluJGNvZGlnbykpew0KICAgIHN1YjwtUENQVF9UbWF4X1RtaW5bUENQVF9UbWF4X1RtaW4kY29kaWdvPT1pLF0NCiAgICBkYXRlPC1kYXRhLmZyYW1lKHNlcShhcy5EYXRlKHBhc3RlKGZvcm1hdChhcy5EYXRlKG1pbihuYS5vbWl0KHN1YiRkYXRlKSksIGZvcm1hdD0iJVkvJW0vJWQiKSwiJVkiKSwiLTAxLTAxIiksZm9ybWF0ID0gIiVZIC0lbS0lZCIpLA0KICAgICAgICAgICAgICAgICAgICAgICAgIGFzLkRhdGUocGFzdGUoZm9ybWF0KGFzLkRhdGUobWF4KG5hLm9taXQoc3ViJGRhdGUpKSwgZm9ybWF0PSIlWS8lbS8lZCIpLCIlWSIpLCItMTItMzEiKSxmb3JtYXQgPSAiJVkgLSVtLSVkIiksDQogICAgICAgICAgICAgICAgICAgICAgICAgYnk9ImRheSIpKQ0KICAgIG5hbWVzKGRhdGUpPC1jKCJkYXRlIikNCiAgICBkYXRlJGRhdGU8LWFzLkRhdGUoZGF0ZSRkYXRlLCBmb3JtYXQgPSAiJVktJW0tJWQiKQ0KICAgIHN1YjI8LW1lcmdlKGRhdGUsc3ViLCBhbGw9VFJVRSkNCiAgICBzdWIyJGNvZGlnbzwtYyhpKQ0KICAgIFBDUFRfVG1heF9UbWluX29rIDwtIHJiaW5kKFBDUFRfVG1heF9UbWluX29rLGRhdGEuZnJhbWUoc3ViMikpDQp9DQpQQ1BUX1RtYXhfVG1pbl9vayRkYXRlMjwtUENQVF9UbWF4X1RtaW5fb2skZGF0ZQ0KbGlicmFyeShzcGxpdHN0YWNrc2hhcGUpDQpQQ1BUX1RtYXhfVG1pbl9vazwtY1NwbGl0KFBDUFRfVG1heF9UbWluX29rLCAiZGF0ZTIiLCAiLSIpDQpQQ1BUX1RtYXhfVG1pbl9vazwtZGF0YS5mcmFtZShQQ1BUX1RtYXhfVG1pbl9va1ssMl0sUENQVF9UbWF4X1RtaW5fb2tbLDldLFBDUFRfVG1heF9UbWluX29rWywxMF0sUENQVF9UbWF4X1RtaW5fb2tbLDExXSxQQ1BUX1RtYXhfVG1pbl9va1ssNl0sUENQVF9UbWF4X1RtaW5fb2tbLDddLFBDUFRfVG1heF9UbWluX29rWyw4XSkNCm5hbWVzKFBDUFRfVG1heF9UbWluX29rKTwtYygiY29kaWdvIiwieWVhciIsIm1vbnRoIiwiZGF5IiwiUENQVCIsIlRtYXgiLCJUbWluIikNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyMgU2F2ZSBkYXRhYmFzZSBmb3IgUkNsaW1EZXgNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KcGIgPC0gd2luUHJvZ3Jlc3NCYXIodGl0bGU9IkhvbGEsIDotKSAuLiBlc3BlcmEgc29sbyB1biBwb2NvIGVzdG95IGNyZWFkbyBsb3MgUkNsaW1EZXggdHh0IC4uLiAiLCBsYWJlbD0iMCUgZG9uZSIsIG1pbj0wLCBtYXg9MTAwLCBpbml0aWFsPTAsIHdpZHRoID0gOTAwKQ0KZm9yKGkgaW4gdW5pcXVlKFBDUFRfVG1heF9UbWluX29rJGNvZGlnbykpew0KICAgIHN1YjwtUENQVF9UbWF4X1RtaW5fb2tbUENQVF9UbWF4X1RtaW5fb2skY29kaWdvPT1pLF0NCiAgICBzdWI8LWRhdGEuZnJhbWUoc3ViKQ0KICAgIHN1YiRQQ1BUPC1yZXBsYWNlKHN1YiRQQ1BULCBpcy5uYShzdWIkUENQVCksIC05OS45KQ0KICAgIHN1YiRUbWF4PC1yZXBsYWNlKHN1YiRUbWF4LCBpcy5uYShzdWIkVG1heCksIC05OS45KQ0KICAgIHN1YiRUbWluPC1yZXBsYWNlKHN1YiRUbWluLCBpcy5uYShzdWIkVG1pbiksIC05OS45KQ0KICAgIHdyaXRlLnRhYmxlKHN1YlssYygtMSldLHBhc3RlKCJSZXN1bHRzL0VzdGFjaW9uZXMvIixpLCJfUkNsaW1EZXgudHh0Iiksc2VwPSJcdCIsZGVjPSIuIiwgY29sLm5hbWVzID0gRiwgcm93Lm5hbWVzID0gRikNCiAgICBmb3IgKGlpIGluIDE6MTAwKXsNCiAgICAgICAgU3lzLnNsZWVwKDAuMDAwNSkgIyBzbG93IGRvd24gdGhlIGNvZGUgZm9yIGlsbHVzdHJhdGlvbiBwdXJwb3Nlcw0KICAgICAgICBpbmZvIDwtIHNwcmludGYoIiVkJSUgZG9uZSIsIHJvdW5kKChpaS8xMDApKjEwMCkpDQogICAgICAgIHNldFdpblByb2dyZXNzQmFyKHBiLCBpaS8oMTAwKSoxMDAsIGxhYmVsPWluZm8pDQogICAgfQ0KfQ0KY2xvc2UocGIpDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCg0KDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMjIERhdGFiYXNlLi4uIFBDUFRfVG1heF9UbWluX29rDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNClBDUFRfVG1heF9UbWluX29rJFBDUFQ8LXJlcGxhY2UoUENQVF9UbWF4X1RtaW5fb2skUENQVCwgUENQVF9UbWF4X1RtaW5fb2skUENQVD09LTk5LjksIE5BKQ0KUENQVF9UbWF4X1RtaW5fb2skVG1heDwtcmVwbGFjZShQQ1BUX1RtYXhfVG1pbl9vayRUbWF4LCBQQ1BUX1RtYXhfVG1pbl9vayRUbWF4PT0tOTkuOSwgTkEpDQpQQ1BUX1RtYXhfVG1pbl9vayRUbWluPC1yZXBsYWNlKFBDUFRfVG1heF9UbWluX29rJFRtaW4sIFBDUFRfVG1heF9UbWluX29rJFRtaW49PS05OS45LCBOQSkNClBDUFRfVG1heF9UbWluX29rJGRhdGU8LWFzLkRhdGUocGFzdGUoUENQVF9UbWF4X1RtaW5fb2skeWVhciwgUENQVF9UbWF4X1RtaW5fb2skbW9udGgsIFBDUFRfVG1heF9UbWluX29rJGRheSwgc2VwPSItIikpDQpQQ1BUX1RtYXhfVG1pbl9vayR5ZWFyX21vbnRoPC1wYXN0ZShQQ1BUX1RtYXhfVG1pbl9vayR5ZWFyLCBQQ1BUX1RtYXhfVG1pbl9vayRtb250aCwgIjEiLCBzZXA9Ii0iKQ0KbGlicmFyeSgicGx5ciIsIGxpYi5sb2M9In4vUi93aW4tbGlicmFyeS8zLjQiKQ0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMtLS0tICg1MCUgY29tcGxldGEgVGVtcGVyYXR1cmEgbWVuc3VhbCkgLS0tLSMNCiMtLS0tICg4MCUgY29tcGxldGEgUHJlY2lwaXRhY2nDs24gbWVuc3VhbCkgLS0tLSMNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQpDT01QTEVUQTwtMTUgICAgICAjICgxNS8zMCkqMTAwPSA1MCUgSU5GT1JNQUNJw5NOIENPTVBMRVRBIFRFTVBFUkFUVVJBIE1FTlNVQUwNCkNPTVBMRVRBX1BDUFQ8LTI0ICMgKDI0LzMwKSoxMDA9IDgwJSBJTkZPUk1BQ0nDk04gQ09NUExFVEEgUFJFQ0lQSVRBQ0nDk04gTUVOU1VBTA0KbGlicmFyeShwbHlyKQ0Kc3RyKFBDUFRfVG1heF9UbWluX29rKQ0KUENQVF9UbWF4X1RtaW5fb2skUENQVDwtYXMubnVtZXJpYyhQQ1BUX1RtYXhfVG1pbl9vayRQQ1BUKQ0KUENQVF9UbWF4X1RtaW5fb2skVG1heDwtYXMubnVtZXJpYyhQQ1BUX1RtYXhfVG1pbl9vayRUbWF4KQ0KUENQVF9UbWF4X1RtaW5fb2skVG1pbjwtYXMubnVtZXJpYyhQQ1BUX1RtYXhfVG1pbl9vayRUbWluKQ0KDQpQQ1BUX1RtYXhfVG1pbl9zdW08LWRkcGx5KFBDUFRfVG1heF9UbWluX29rLCBjKCJjb2RpZ28iLCJ5ZWFyX21vbnRoIiksIHN1bW1hcmlzZSwgDQogICAgICAgICAgICAgICAgUENQVF9zdW0gID0gaWZlbHNlKGxlbmd0aChuYS5vbWl0KFBDUFQpKT5DT01QTEVUQV9QQ1BULCBzdW0obmEub21pdChQQ1BUKSksIiIpLA0KICAgICAgICAgICAgICAgIFRtYXhfbWF4ICA9IGlmZWxzZShsZW5ndGgobmEub21pdChUbWF4KSk+Q09NUExFVEEsIG1heChuYS5vbWl0KFRtYXgpKSwiIiksDQogICAgICAgICAgICAgICAgVG1heF9tZWFuID0gaWZlbHNlKGxlbmd0aChuYS5vbWl0KFRtYXgpKT5DT01QTEVUQSwgbWVhbihuYS5vbWl0KFRtYXgpKSwiIiksDQogICAgICAgICAgICAgICAgVG1heF9taW4gPSBpZmVsc2UobGVuZ3RoKG5hLm9taXQoVG1heCkpPkNPTVBMRVRBLCBtaW4obmEub21pdChUbWF4KSksIiIpLA0KICAgICAgICAgICAgICAgIFRtaW5fbWF4ID0gaWZlbHNlKGxlbmd0aChuYS5vbWl0KFRtaW4pKT5DT01QTEVUQSwgbWF4KG5hLm9taXQoVG1pbikpLCIiKSwNCiAgICAgICAgICAgICAgICBUbWluX21lYW4gPSBpZmVsc2UobGVuZ3RoKG5hLm9taXQoVG1pbikpPkNPTVBMRVRBLCBtZWFuKG5hLm9taXQoVG1pbikpLCIiKSwNCiAgICAgICAgICAgICAgICBUbWluX21pbiAgPSBpZmVsc2UobGVuZ3RoKG5hLm9taXQoVG1pbikpPkNPTVBMRVRBLCBtaW4obmEub21pdChUbWluKSksIiIpKQ0KUENQVF9UbWF4X1RtaW5fc3VtJHllYXJfbW9udGg8LWFzLkRhdGUoUENQVF9UbWF4X1RtaW5fc3VtJHllYXJfbW9udGgsIGZvcm1hdCA9ICIlWS0lbS0lZCIpDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIy0tLS0gKDgwJSBjb21wbGV0YSBQcmVjaXBpdGFjacOzbiBhbnVhbCkgLS0tLSMNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQpDT01QTEVUQTwtMjkyICMoMjkyLzM2NSkqMTAwPSA4MCUgSU5GT1JNQUNJw5NOIENPTVBMRVRBIFBSRUNJUElUQUNJT04gQU5VQUwNClBDUFRfYW51YWw8LWRkcGx5KFBDUFRfVG1heF9UbWluX29rLCBjKCJjb2RpZ28iLCJ5ZWFyIiksIHN1bW1hcmlzZSwgDQogICAgICAgICAgICAgICAgICBQQ1BUX3N1bT0gaWZlbHNlKGxlbmd0aChuYS5vbWl0KFBDUFQpKT5DT01QTEVUQSwgc3VtKG5hLm9taXQoUENQVCkpLCIiKSkNClBDUFRfYW51YWwkeWVhcjwtYXMubnVtZXJpYyhQQ1BUX2FudWFsJHllYXIpDQp3cml0ZS50YWJsZShQQ1BUX1RtYXhfVG1pbl9zdW0sIlJlc3VsdHMvUENQVF9UbWF4X1RtaW5fc3VtLnR4dCIsc2VwPSJcdCIsZGVjPSIuIiwgY29sLm5hbWVzID0gVCwgcm93Lm5hbWVzID0gRikNCndyaXRlLnRhYmxlKFBDUFRfYW51YWwsIlJlc3VsdHMvUENQVF9hbnVhbC50eHQiLHNlcD0iXHQiLGRlYz0iLiIsIGNvbC5uYW1lcyA9IFQsIHJvdy5uYW1lcyA9IEYpDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCg0KYGBgDQoNCkFuZXhvIDYuQ3JlYWNpw7NuIGRlIGdyw6FmaWNvcyBkZSBwcmVjaXBpdGFjacOzbiB5IHRlbXBlcmF0dXJhIG1lbnN1YWwNCmBgYHtyIGV2YWw9RkFMU0UsIGluY2x1ZGU9VFJVRX0NCiMjIFNtYXJ0IGdyYXBoaWNzIA0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCk5vbWJyZV9lc3RhY2lvbjwtIjgxMDAzIiAgICMjIyMjIyMjI1BDUFRfYW51YWwgUENQVF9UbWF4X1RtaW5fc3VtDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNClBDUFRfYW51YWw8LXJlYWQuZGVsaW0oIlJlc3VsdHMvUENQVF9hbnVhbC50eHQiLGhlYWRlcj1UUlVFLHNlcD0iXHQiLGRlYz0iLiIpDQpQQ1BUX2FudWFsJHllYXI8LWFzLm51bWVyaWMoUENQVF9hbnVhbCR5ZWFyKQ0KUENQVF9hbnVhbCR5ZWFyPC1hcy5EYXRlKHBhc3RlKFBDUFRfYW51YWwkeWVhciwiLTAxLTAxIiksIGZvcm1hdCA9ICIlWSAtJW0tJWQiKQ0KUENQVF9UbWF4X1RtaW5fc3VtPC1yZWFkLmRlbGltKCJSZXN1bHRzL1BDUFRfVG1heF9UbWluX3N1bS50eHQiLGhlYWRlcj1UUlVFLHNlcD0iXHQiLGRlYz0iLiIpDQpQQ1BUX1RtYXhfVG1pbl9zdW0keWVhcl9tb250aDwtYXMuRGF0ZShQQ1BUX1RtYXhfVG1pbl9zdW0keWVhcl9tb250aCwgZm9ybWF0ID0gIiVZLSVtLSVkIikNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KbGlicmFyeShnZ3Bsb3QyKQ0KbGlicmFyeSh4dHMpIA0KbGlicmFyeShkeWdyYXBocykNCiMgRnVuY3Rpb24gDQpwcmVzQW5ub3RhdGlvbiA8LSBmdW5jdGlvbihkeWdyYXBoLCB4LCB0ZXh0KSB7DQogICAgZHlncmFwaCAlPiUNCiAgICAgICAgZHlBbm5vdGF0aW9uKHgsIHRleHQsIGF0dGFjaEF0Qm90dG9tID0gVFJVRSwgd2lkdGggPSA0MCkNCn0NCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyMgVGVtcGVyYXR1cmEgZXNjYWxhIG1lbnN1YWwgICAtLS0tICg1MCUgY29tcGxldGEpIC0tLS0NCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0Kc3ViMTwtUENQVF9UbWF4X1RtaW5fc3VtW1BDUFRfVG1heF9UbWluX3N1bSRjb2RpZ289PU5vbWJyZV9lc3RhY2lvbixdDQpUbWF4X21heDwtIHh0cyhzdWIxJFRtYXhfbWF4LG9yZGVyLmJ5PShzdWIxJHllYXJfbW9udGgpLHR6PSJHTVQiKQ0KVG1heF9tZWFuPC0geHRzKHN1YjEkVG1heF9tZWFuLG9yZGVyLmJ5PShzdWIxJHllYXJfbW9udGgpLHR6PSJHTVQiKQ0KVG1heF9taW48LSB4dHMoc3ViMSRUbWF4X21pbixvcmRlci5ieT0oc3ViMSR5ZWFyX21vbnRoKSx0ej0iR01UIikNClRtaW5fbWF4PC0geHRzKHN1YjEkVG1pbl9tYXgsb3JkZXIuYnk9KHN1YjEkeWVhcl9tb250aCksdHo9IkdNVCIpDQpUbWluX21lYW48LSB4dHMoc3ViMSRUbWluX21lYW4sb3JkZXIuYnk9KHN1YjEkeWVhcl9tb250aCksdHo9IkdNVCIpDQpUbWluX21pbjwtIHh0cyhzdWIxJFRtaW5fbWluLG9yZGVyLmJ5PShzdWIxJHllYXJfbW9udGgpLHR6PSJHTVQiKQ0Kc3RvY2tzMSA8LSBjYmluZChUbWF4X21heCxUbWF4X21lYW4sVG1heF9taW4sVG1pbl9tYXgsVG1pbl9tZWFuLFRtaW5fbWluKQ0KZHlncmFwaChzdG9ja3MxLHlsYWI9KCJUZW1wZXJhdHVyZSAowrBDKSIpLCBtYWluPXBhc3RlKCJFc3RhY2nDs246ICIsIE5vbWJyZV9lc3RhY2lvbikpICU+JQ0KICAgIGR5U2VyaWVzKCIuLjEiLGxhYmVsPSJUZW1wLiBtYXggbWF4aW11bSAowrBDKSIsIGRyYXdQb2ludHMgPSBUUlVFLCBwb2ludFNpemUgPSAzKSAlPiUNCiAgICBkeVNlcmllcygiLi4yIixsYWJlbD0iVGVtcC4gbWF4IHByb21lZGlvICjCsEMpIiwgZHJhd1BvaW50cyA9IFRSVUUsIHBvaW50U2l6ZSA9IDMpICU+JQ0KICAgIGR5U2VyaWVzKCIuLjMiLGxhYmVsPSJUZW1wLiBtYXggbWluaW11bSAowrBDKSIsIGRyYXdQb2ludHMgPSBUUlVFLCBwb2ludFNpemUgPSAzKSAlPiUNCiAgICBkeVNlcmllcygiLi40IixsYWJlbD0iVGVtcC4gbWluIG1heGltdW0gKMKwQykiLCBkcmF3UG9pbnRzID0gVFJVRSwgcG9pbnRTaXplID0gMykgJT4lDQogICAgZHlTZXJpZXMoIi4uNSIsbGFiZWw9IlRlbXAuIG1pbiBwcm9tZWRpbyAowrBDKSIsIGRyYXdQb2ludHMgPSBUUlVFLCBwb2ludFNpemUgPSAzKSAlPiUNCiAgICBkeVNlcmllcygiLi42IixsYWJlbD0iVGVtcC4gbWluIG1pbmltdW0gKMKwQykiLCBkcmF3UG9pbnRzID0gVFJVRSwgcG9pbnRTaXplID0gMykgJT4lDQogICAgZHlPcHRpb25zKGNvbG9ycyA9IGMoImRhcmtyZWQiLCJyZWQiLCJkYXJrc2FsbW9uIiwic2t5Ymx1ZSIsIm9yYW5nZSIsInllbGxvdyIpKSAlPiUNCiAgICBkeUhpZ2hsaWdodChoaWdobGlnaHRTZXJpZXNPcHRzID0gbGlzdChzdHJva2VXaWR0aCA9IDEpKSU+JQ0KICAgIGR5TGVnZW5kKHdpZHRoID0gNDAwKSU+JQ0KICAgIGR5UmFuZ2VTZWxlY3RvcigpDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMjIFByZWNpcGl0YWNpw7NuIHRvdGFsIG1lbnN1YWwgIC0tLS0gKDgwJSBjb21wbGV0YSkgLS0tLQ0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQpQQ1BUPC0geHRzKHN1YjEkUENQVF9zdW0sb3JkZXIuYnk9KHN1YjEkeWVhcl9tb250aCksdHo9IkdNVCIpDQpzdG9ja3MxIDwtIGNiaW5kKFBDUFQpDQpkeWdyYXBoKHN0b2NrczEseWxhYj0oIlByZWNpcGl0YWNpw7NuIHRvdGFsIG1lbnN1YWwgKG1tKSIpLG1haW49cGFzdGUoIkVzdGFjacOzbjogIiwgTm9tYnJlX2VzdGFjaW9uKSkgJT4lDQogICAgZHlTZXJpZXMobGFiZWw9IlByZWNpcGl0YWNpw7NuIHRvdGFsIG1lbnN1YWwgKG1tKSIsIHN0ZXBQbG90ID0gVFJVRSwgZmlsbEdyYXBoID0gVFJVRSwgY29sb3IgPSAiYmx1ZSIpICU+JQ0KICAgIGR5T3B0aW9ucyhjb2xvcnMgPSBjKCJibHVlIiksIGZpbGxHcmFwaCA9IFRSVUUsIGZpbGxBbHBoYSA9IDAuNCkgJT4lDQogICAgZHlIaWdobGlnaHQoaGlnaGxpZ2h0U2VyaWVzT3B0cyA9IGxpc3Qoc3Ryb2tlV2lkdGggPSAxKSklPiUNCiAgICBkeUxlZ2VuZCh3aWR0aCA9IDQwMCklPiUNCiAgICBkeVJhbmdlU2VsZWN0b3IoKQ0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojIyBQcmVjaXBpdGFjacOzbiB0b3RhbCBhbnVhbCAgICAtLS0tICg4MCUgY29tcGxldGEpIC0tLS0NCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0Kc3ViMjwtUENQVF9hbnVhbFtQQ1BUX2FudWFsJGNvZGlnbz09Tm9tYnJlX2VzdGFjaW9uLF0NClBDUFQ8LSB4dHMoc3ViMiRQQ1BUX3N1bSxvcmRlci5ieT0oc3ViMiR5ZWFyKSx0ej0iR01UIikNCnN0b2NrczEgPC0gY2JpbmQoUENQVCkNCmR5Z3JhcGgoc3RvY2tzMSx5bGFiPSgiUHJlY2lwaXRhY2nDs24gdG90YWwgYW51YWwgKG1tKSIpLCBtYWluPXBhc3RlKCJFc3RhY2nDs246ICIsIE5vbWJyZV9lc3RhY2lvbikpICU+JQ0KICAgIGR5U2VyaWVzKGxhYmVsPSJQcmVjaXBpdGFjacOzbiB0b3RhbCBhbnVhbCAobW0pIiwgc3RlcFBsb3QgPSBUUlVFLCBmaWxsR3JhcGggPSBUUlVFLCBjb2xvciA9ICJibHVlIikgJT4lDQogICAgZHlPcHRpb25zKGNvbG9ycyA9IGMoImJsdWUiKSwgZmlsbEdyYXBoID0gVFJVRSwgZmlsbEFscGhhID0gMC40KSAlPiUNCiAgICBkeUhpZ2hsaWdodChoaWdobGlnaHRTZXJpZXNPcHRzID0gbGlzdChzdHJva2VXaWR0aCA9IDEpKSU+JQ0KICAgIGR5TGVnZW5kKHdpZHRoID0gNDAwKSU+JQ0KICAgIGR5UmFuZ2VTZWxlY3RvcigpDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCg0KDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMjIEdyYXBoaWNzIFBERg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQpwZGYoZmlsZT0iUmVzdWx0cy9GaWcuIFRlbXBlcmF0dXJhIG1lbnN1YWwucGRmIiwgd2lkdGggPSAxMCwgaGVpZ2h0ID0gNikNCnBhcihtZnJvdz1jKDEsMSksbWdwID0gYygxLjUsMC41LDApLCBtYXIgPSBjKDMsMyw0LDEuNSkpDQpmb3IgKGkgaW4gdW5pcXVlKFBDUFRfVG1heF9UbWluX3N1bSRjb2RpZ28pKXsNCiAgICBzdWI8LVBDUFRfVG1heF9UbWluX3N1bVtQQ1BUX1RtYXhfVG1pbl9zdW0kY29kaWdvPT1pLF0NCiAgICBzdWI8LXN1YltvcmRlcihzdWIkY29kaWdvLHN1YiR5ZWFyX21vbnRoKSxdDQogICAgc3ViJFRtYXhfbWF4WyFpcy5maW5pdGUoc3ViJFRtYXhfbWF4KV0gIDwtIE5BDQogICAgc3ViJFRtYXhfbWVhblshaXMuZmluaXRlKHN1YiRUbWF4X21lYW4pXSA8LSBOQQ0KICAgIHN1YiRUbWF4X21pblshaXMuZmluaXRlKHN1YiRUbWF4X21pbildICA8LSBOQQ0KICAgIHN1YiRUbWluX21heFshaXMuZmluaXRlKHN1YiRUbWluX21heCldICA8LSBOQQ0KICAgIHN1YiRUbWluX21lYW5bIWlzLmZpbml0ZShzdWIkVG1pbl9tZWFuKV0gPC0gTkENCiAgICBzdWIkVG1pbl9taW5bIWlzLmZpbml0ZShzdWIkVG1pbl9taW4pXSAgPC0gTkENCiAgICBwYXIoeHBkPUZBTFNFKQ0KICAgIHBsb3Qoc3ViJHllYXJfbW9udGgsIHN1YiRUbWF4X21heCwgdHlwZSA9ICJiIiwgcGNoPTE5LCBjb2w9ImRhcmtyZWQiLCB5bGltPWMoaWZlbHNlKG1pbihuYS5vbWl0KHN1YiRUbWluX21pbikpPT0iSW5mIiwtMSxtaW4obmEub21pdChzdWIkVG1pbl9taW4pKSksIGlmZWxzZShtYXgobmEub21pdChzdWIkVG1heF9tYXgpKT09Ii1JbmYiLC0xLG1heChuYS5vbWl0KHN1YiRUbWF4X21heCkpKSksIA0KICAgICAgICAgbWFpbj1wYXN0ZSgiRXN0YWNpb249ICIsIGkpLCB5bGFiPSJUZW1wZXJhdHVyYSBtZW5zdWFsICjCsEMpIiwgeGxhYj0iIikNCiAgICBwb2ludHMoc3ViJHllYXJfbW9udGgsIHN1YiRUbWF4X21lYW4sIHR5cGUgPSAiYiIsIHBjaD0xOSwgY29sPSJyZWQiKQ0KICAgIHBvaW50cyhzdWIkeWVhcl9tb250aCwgc3ViJFRtYXhfbWluLCB0eXBlID0gImIiLCBwY2g9MTksIGNvbD0iZGFya3NhbG1vbiIpDQogICAgcG9pbnRzKHN1YiR5ZWFyX21vbnRoLCBzdWIkVG1pbl9tYXgsIHR5cGUgPSAiYiIsIHBjaD0xOSwgY29sPSJza3libHVlIikNCiAgICBwb2ludHMoc3ViJHllYXJfbW9udGgsIHN1YiRUbWluX21lYW4sIHR5cGUgPSAiYiIsIHBjaD0xOSwgY29sPSJvcmFuZ2UiKQ0KICAgIHBvaW50cyhzdWIkeWVhcl9tb250aCwgc3ViJFRtaW5fbWluLCB0eXBlID0gImIiLCBwY2g9MTksIGNvbD0ieWVsbG93IikNCiAgICBwYXIoeHBkPVRSVUUpDQogICAgbGVnZW5kKCJ0b3AiLCBpbnNldCA9IGMoMCwgLTAuMDgpLCAiIiwgYygiVG1heF9tYXgiLCJUbWF4X21lYW4iLCJUbWF4X21pbiIsIlRtaW5fbWF4IiwiVG1pbl9tZWFuIiwiVG1pbl9taW4iKSwgcGNoPWMoMTkpLGNvbD1jKCJkYXJrcmVkIiwicmVkIiwiZGFya3NhbG1vbiIsInNreWJsdWUiLCJvcmFuZ2UiLCJ5ZWxsb3ciKSxoPVRSVUUsIHRleHQuY29sID0gYygiZGFya3JlZCIsInJlZCIsImRhcmtzYWxtb24iLCJza3libHVlIiwib3JhbmdlIiwieWVsbG93IiksbWVyZ2UgPSBGLCBiZyA9IE5VTEwsYnR5PSduJykNCn0NCmRldi5vZmYoKQ0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQpwZGYoZmlsZT0iUmVzdWx0cy9GaWcuIFByZWNpcGl0YWNpb24gdG90YWwgbWVuc3VhbC5wZGYiLCB3aWR0aCA9IDEwLCBoZWlnaHQgPSA2KQ0KcGFyKG1mcm93PWMoMSwxKSxtZ3AgPSBjKDEuNSwwLjUsMCksIG1hciA9IGMoMywzLDQsMS41KSkNCmZvciAoaSBpbiB1bmlxdWUoUENQVF9UbWF4X1RtaW5fc3VtJGNvZGlnbykpew0KICAgIHN1YjwtUENQVF9UbWF4X1RtaW5fc3VtW1BDUFRfVG1heF9UbWluX3N1bSRjb2RpZ289PWksXQ0KICAgIHN1Yjwtc3ViW29yZGVyKHN1YiRjb2RpZ28sc3ViJHllYXJfbW9udGgpLF0NCiAgICBzdWIkUENQVF9zdW1bIWlzLmZpbml0ZShzdWIkUENQVF9zdW0pXSAgPC0gTkENCiAgICBzdWIkVG1heF9tYXhbIWlzLmZpbml0ZShzdWIkVG1heF9tYXgpXSAgPC0gTkENCiAgICBzdWIkVG1heF9tZWFuWyFpcy5maW5pdGUoc3ViJFRtYXhfbWVhbildIDwtIE5BDQogICAgc3ViJFRtYXhfbWluWyFpcy5maW5pdGUoc3ViJFRtYXhfbWluKV0gIDwtIE5BDQogICAgc3ViJFRtaW5fbWF4WyFpcy5maW5pdGUoc3ViJFRtaW5fbWF4KV0gIDwtIE5BDQogICAgc3ViJFRtaW5fbWVhblshaXMuZmluaXRlKHN1YiRUbWluX21lYW4pXSA8LSBOQQ0KICAgIHN1YiRUbWluX21pblshaXMuZmluaXRlKHN1YiRUbWluX21pbildICA8LSBOQQ0KICAgIHBhcih4cGQ9RkFMU0UpDQogICAgcGxvdChzdWIkeWVhcl9tb250aCwgc3ViJFBDUFRfc3VtLCB0eXBlID0gImgiLCBwY2g9MTksIGNvbD0iYmx1ZSIsIHlsaW09YyhpZmVsc2UobWluKG5hLm9taXQoc3ViJFBDUFRfc3VtKSk9PSJJbmYiLDAsMCksIGlmZWxzZShtYXgobmEub21pdChzdWIkUENQVF9zdW0pKT09Ii1JbmYiLDAsbWF4KG5hLm9taXQoc3ViJFBDUFRfc3VtKSkpKSwgDQogICAgICAgICBtYWluPXBhc3RlKCJFc3RhY2lvbj0gIiwgaSksIHlsYWI9IlByZWNpcGl0YWNpb24gdG90YWwgbWVuc3VhbCAobW0pIiwgeGxhYj0iIiwgbHdkPTMpDQogICAgcG9pbnRzKHN1YiR5ZWFyX21vbnRoLCBzdWIkUENQVF9zdW0sIHR5cGU9ImwiLCBjb2w9InJlZCIsIGx0eT0zLGx3ZD0xKQ0KICAgIGFibGluZShoPTAsIGNvbD0iYmxhY2siLCBsdHk9MSwgbHdkPTIpDQogICAgcGFyKHhwZD1UUlVFKQ0KICAgIGxlZ2VuZCgidG9wIiwgaW5zZXQgPSBjKDAsIC0wLjA4KSwgIiIsIGMoIlByZWNpcGl0YWNpw7NuIHRvdGFsIG1lbnN1YWwiKSxsdHk9MSwgbHdkPTMsY29sPWMoImJsdWUiKSxoPVRSVUUsIHRleHQuY29sID0gYygiYmx1ZSIpLG1lcmdlID0gRiwgYmcgPSBOVUxMLGJ0eT0nbicpDQp9DQpkZXYub2ZmKCkNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KcGRmKGZpbGU9IlJlc3VsdHMvRmlnLiBQcmVjaXBpdGFjaW9uIHRvdGFsIGFudWFsLnBkZiIsIHdpZHRoID0gMTAsIGhlaWdodCA9IDYpDQpwYXIobWZyb3c9YygxLDEpLG1ncCA9IGMoMS41LDAuNSwwKSwgbWFyID0gYygzLDMsNCwxLjUpKQ0KZm9yIChpIGluIHVuaXF1ZShQQ1BUX2FudWFsJGNvZGlnbykpew0KICAgIHN1YjwtUENQVF9hbnVhbFtQQ1BUX2FudWFsJGNvZGlnbz09aSxdDQogICAgc3ViPC1zdWJbb3JkZXIoc3ViJGNvZGlnbyxzdWIkeWVhciksXQ0KICAgIHN1YiRQQ1BUX3N1bVshaXMuZmluaXRlKHN1YiRQQ1BUX3N1bSldICA8LSBOQQ0KICAgIHBhcih4cGQ9RkFMU0UpDQogICAgcGxvdChzdWIkeWVhciwgc3ViJFBDUFRfc3VtLCB0eXBlID0gImgiLCBwY2g9MTksIGNvbD0iYmx1ZSIsIHlsaW09YyhpZmVsc2UobWluKG5hLm9taXQoc3ViJFBDUFRfc3VtKSk9PSJJbmYiLDAsMCksIGlmZWxzZShtYXgobmEub21pdChzdWIkUENQVF9zdW0pKT09Ii1JbmYiLDAsbWF4KG5hLm9taXQoc3ViJFBDUFRfc3VtKSkpKSwgDQogICAgICAgICBtYWluPXBhc3RlKCJFc3RhY2lvbj0gIiwgaSksIHlsYWI9IlByZWNpcGl0YWNpb24gdG90YWwgYW51YWwgKG1tKSIsIHhsYWI9IiIsIGx3ZD0zKQ0KICAgIHBvaW50cyhzdWIkeWVhciwgc3ViJFBDUFRfc3VtLCB0eXBlPSJsIiwgY29sPSJyZWQiLCBsdHk9Myxsd2Q9MSkNCiAgICBhYmxpbmUoaD0wLCBjb2w9ImJsYWNrIiwgbHR5PTEsIGx3ZD0yKQ0KICAgIHBhcih4cGQ9VFJVRSkNCiAgICBsZWdlbmQoInRvcCIsIGluc2V0ID0gYygwLCAtMC4wOCksICIiLCBjKCJQcmVjaXBpdGFjacOzbiB0b3RhbCBtZW5zdWFsIiksbHR5PTEsIGx3ZD0zLGNvbD1jKCJibHVlIiksaD1UUlVFLCB0ZXh0LmNvbCA9IGMoImJsdWUiKSxtZXJnZSA9IEYsIGJnID0gTlVMTCxidHk9J24nKQ0KfQ0KZGV2Lm9mZigpDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCg0KDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMjIFNhdmUgZGF0YWJhc2Ugc3VtbWFyeSAobW9udGhseSBhbmQgeWVhcikgZm9yIGVhY2ggc3RhdGlvbg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQpwYiA8LSB3aW5Qcm9ncmVzc0Jhcih0aXRsZT0iSG9sYSBkZSBudWV2bywgOi0pIC4uIGVzcGVyYSBzb2xvIHVuIHBvY28gZXN0b3kgY3JlYWRvIGRhdGFiYXNlIHBhcmEgY2FkYSBlc3RhY2nDs24gbWV0ZW9yb2zDs2dpY2EgZW4gZm9ybWF0by50eHQgLi4uICIsIGxhYmVsPSIwJSBkb25lIiwgbWluPTAsIG1heD0xMDAsIGluaXRpYWw9MCwgd2lkdGggPSA5MDApDQpmb3IoaSBpbiB1bmlxdWUoUENQVF9UbWF4X1RtaW5fc3VtJGNvZGlnbykpew0KICAgIHN1YjwtUENQVF9UbWF4X1RtaW5fc3VtW1BDUFRfVG1heF9UbWluX3N1bSRjb2RpZ289PWksXQ0KICAgIHN1Yjwtc3ViW29yZGVyKHN1YiRjb2RpZ28sc3ViJHllYXJfbW9udGgpLF0NCiAgICBzdWIkVG1heF9tYXhbIWlzLmZpbml0ZShzdWIkVG1heF9tYXgpXSAgPC0gTkENCiAgICBzdWIkVG1heF9tZWFuWyFpcy5maW5pdGUoc3ViJFRtYXhfbWVhbildIDwtIE5BDQogICAgc3ViJFRtYXhfbWluWyFpcy5maW5pdGUoc3ViJFRtYXhfbWluKV0gIDwtIE5BDQogICAgc3ViJFRtaW5fbWF4WyFpcy5maW5pdGUoc3ViJFRtaW5fbWF4KV0gIDwtIE5BDQogICAgc3ViJFRtaW5fbWVhblshaXMuZmluaXRlKHN1YiRUbWluX21lYW4pXSA8LSBOQQ0KICAgIHN1YiRUbWluX21pblshaXMuZmluaXRlKHN1YiRUbWluX21pbildICA8LSBOQQ0KICAgIHdyaXRlLnRhYmxlKHN1YixwYXN0ZSgiUmVzdWx0cy9Fc3RhY2lvbmVzIGRhdG9zIHJlc3VtaWRvcy8iLGksIl9kYXRhYmFzZV9tZW5zdWFsLnR4dCIpLHNlcD0iXHQiLGRlYz0iLiIsIGNvbC5uYW1lcyA9IFQsIHJvdy5uYW1lcyA9IEYpDQogICAgZm9yIChpaSBpbiAxOjEwMCl7DQogICAgICAgIFN5cy5zbGVlcCgwLjAwMDUpICMgc2xvdyBkb3duIHRoZSBjb2RlIGZvciBpbGx1c3RyYXRpb24gcHVycG9zZXMNCiAgICAgICAgaW5mbyA8LSBzcHJpbnRmKCIlZCUlIGRvbmUiLCByb3VuZCgoaWkvMTAwKSoxMDApKQ0KICAgICAgICBzZXRXaW5Qcm9ncmVzc0JhcihwYiwgaWkvKDEwMCkqMTAwLCBsYWJlbD1pbmZvKQ0KICAgIH0NCn0NCmNsb3NlKHBiKQ0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQpwYiA8LSB3aW5Qcm9ncmVzc0Jhcih0aXRsZT0iSG9sYSBkZSBudWV2bywgU295IHlvIG90cmEgdmV6IDotKSAuLiBlc3BlcmEgc29sbyB1biBwb2NvIGVzdG95IGNyZWFkbyBkYXRhYmFzZSBwYXJhIGNhZGEgZXN0YWNpw7NuIG1ldGVvcm9sw7NnaWNhIGVuIGZvcm1hdG8udHh0IC4uLiAiLCBsYWJlbD0iMCUgZG9uZSIsIG1pbj0wLCBtYXg9MTAwLCBpbml0aWFsPTAsIHdpZHRoID0gOTAwKQ0KZm9yKGkgaW4gdW5pcXVlKFBDUFRfYW51YWwkY29kaWdvKSl7DQogICAgc3ViPC1QQ1BUX2FudWFsW1BDUFRfYW51YWwkY29kaWdvPT1pLF0NCiAgICBzdWI8LXN1YltvcmRlcihzdWIkY29kaWdvLHN1YiR5ZWFyKSxdDQogICAgc3ViJFBDUFRfc3VtWyFpcy5maW5pdGUoc3ViJFBDUFRfc3VtKV0gIDwtIE5BDQogICAgd3JpdGUudGFibGUoc3ViLHBhc3RlKCJSZXN1bHRzL0VzdGFjaW9uZXMgZGF0b3MgcmVzdW1pZG9zLyIsaSwiX2RhdGFiYXNlX2FudWFsLnR4dCIpLHNlcD0iXHQiLGRlYz0iLiIsIGNvbC5uYW1lcyA9IFQsIHJvdy5uYW1lcyA9IEYpDQogICAgZm9yIChpaSBpbiAxOjEwMCl7DQogICAgICAgIFN5cy5zbGVlcCgwLjAwMDUpICMgc2xvdyBkb3duIHRoZSBjb2RlIGZvciBpbGx1c3RyYXRpb24gcHVycG9zZXMNCiAgICAgICAgaW5mbyA8LSBzcHJpbnRmKCIlZCUlIGRvbmUiLCByb3VuZCgoaWkvMTAwKSoxMDApKQ0KICAgICAgICBzZXRXaW5Qcm9ncmVzc0JhcihwYiwgaWkvKDEwMCkqMTAwLCBsYWJlbD1pbmZvKQ0KICAgIH0NCn0NCmNsb3NlKHBiKQ0KYGBgDQoNCkFuZXhvIDcuSW5zdGFsYWNpw7NuIGRlIHBhcXVldGVzIHJlcXVlcmlkb3MgcG9yIFJDbGltZGV4DQpgYGB7ciBldmFsPUZBTFNFLCBpbmNsdWRlPVRSVUV9DQppbnN0YWxsLnBhY2thZ2VzKCJjbHVzdGVyIikNCmluc3RhbGwucGFja2FnZXMoInRjbHRrIikgDQppbnN0YWxsLnBhY2thZ2VzKCJSY21kciIpDQpgYGANCg0KQW5leG8gOC5Dw7NkaWdvIHBhcmEgZ2VuZXJhciBlbCBzb2Z0d2FyZSBSQ2xpbWRleA0KYGBge3IgZXZhbD1GQUxTRSwgaW5jbHVkZT1UUlVFfQ0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyJTY3JpcHQgUkNsaW1kZXgiIA0KIyBSZXdyaXR0ZW46IEp1bmlvciBQYXN0b3IgUMOJUkVaLU1PTElOQQ0KIyBTbWFsbCBtb2RpZmljYXRpb25zIHRvIGFkYXB0IHRoZSBhbmFseXNpcyBvZiBjbGltYXRlIHZhcmlhYmlsaXR5IGluIHRoZSB0cm9waWNzDQojIERhdGUgbW9kaWZpZWQ6ICJUdWVzZGF5IE1heSAzMXN0LCAyMDE2IiANCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCnJtKGxpc3QgPSBscygpKSAjUmVtb3ZlIGFsbCBvYmplY3RzDQpncmFwaGljcy5vZmYoKSAgI1JlbW92ZSBhbGwgZ3JhcGhpY3MNCmNhdCgiXDAxNCIpICAgICAjUmVtb3ZlIHNjcmlwdCBpbiB3aW5kb3dzIGNvbnNvbGUNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCg0KDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojIENyZWRpY3RzOg0KIyBDbGltYXRlIEluZGVjaWVzIENhbGN1bGF0aW9uIHNvZnR3YXJlDQojIFIgbGFuZ3VhZ2Ugd2l0aCBUQ0wvVEsgcGFja2FnZQ0KIyBQcm9ncmFtbWVkIGJ5IFl1anVuIE91eWFuZyxNYXIsMjAwNA0KIyByZXdyaXR0ZW4gYnkgWWFuZyBGZW5nLCBKdWx5IDIwMDQNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgdmVyc2lvbiAxLjAsIDIwMDQtMTAtMTQNCiMgbW9kaWZpZWQsIDIwMDYtMDEtMjQsIA0KIyBjaGFuZ2UgLkludGVybmFsKGNiaW5kKSB0byBjYmluZA0KIyBjaGFuZ2UgLkludGVybmFsKHJiaW5kKSB0byByYmluZA0KIyBtb2RpZmllZCAyMDA3LTAzLTIzDQojIGNoYW5nZSAuSW50ZXJuYWwocmVwKDAsbikpIHRvIHJlcCgwLG4pDQojIG1vZGlmaWVkLCAyMDA3LTExLTI2LA0KIyBnZXQgcmlkIG9mIC5JbnRlcm5hbCBvbiBzb21lIGZ1bmN0aW9uczogbWluKC4uLiksIHNvcnQoLi4uKSwgcm91bmQoLi4uKQ0KIyAgICAgICAgICAgIG1heCguLi4pLCBhbHNvIGdldCByaWQgb2YgZGlnPS4uIHBhcnQgZnJvbSBzb3J0KC4uLikgZnVuY3Rpb24NCiMgICAgICAgICAgICBjaGFuZ2UgZGVjcmVhc2U9Li4uIHBhcnQgdG8gZGVjcmVhc2luZz0uLi4gYXQgc29ydCguLi4pDQojIG1vZGlmaWVkLCAyMDA4LTA1LTA1LA0KIyBvdXRwdXQgVE1BWCBtZWFuIHZhbHVlIGFuZCBUTUlOIG1lYW4gdmFsdWUgaW4gbmFzdGF0KCkgZnVuY3Rpb24NCiMgbW9kaWZpZWQsIDIwMDgtMDUtMDYsDQojIGFkZCBhIHJhbmRvbSBzZXJpZXMgb24gVE1BWCBhbmQgVE1JTiBpbiBleGNlZWRhbmNlIHJhdGUgZnVuY3Rpb24NCiMgbW9kaWZpZWQgdGhyZXNob2xkcyBpbiBUTjEwcCBjYWxjdWxhdGlvbiwgYWRkIGFuIDFlLTUgaXRlbSB0byBhdm9pZCANCiMgY29tcHV0YXRpb25hbCBlcnJvciBsaWtlIDMuNjAwMDAgPiAzLjYwMDAsIHR3byBmdW5jdGlvbnMgaW52b2x2ZWQ6DQojIG5vcmRheXRlbTEoKSBhbmQgZXhjZWVkYW5jZSgpDQojIG1vZGlmaWVkLCAyMDA4LTA2LTE2DQojIGNoYW5nZSBhbGwgc29ydCgpIHRvIG15c29ydCgpLCBkZWFsIHdpdGggZGlmZmVyZW50IHZlcnNpb24sIGFsc28gY29tYmluZWQNCiMgZGlmZmVyZW50IGxldmVscyB0aHJlc2hvbGQoKQ0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgUGFydCBJDQojIEdlbmVyYWwgZnVuY3Rpb25zICYgVENML1RLIGZ1bmN0aW9ucw0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KbGlicmFyeShjbHVzdGVyKQ0KcmVxdWlyZSh0Y2x0aykNCm15c29ydDwtIGlmKGdldFJ2ZXJzaW9uKCk8PScyLjQuMScpIGZ1bmN0aW9uKHgsZGVjcmVhc2luZyl7LkludGVybmFsKHNvcnQoeCxkZWNyZWFzaW5nPWRlY3JlYXNpbmcpKX0gZWxzZSBmdW5jdGlvbih4LGRlY3JlYXNpbmcpe3NvcnQuaW50KHgsZGVjcmVhc2luZz1kZWNyZWFzaW5nKX0NCmZvbnRIZWFkaW5nIDwtIHRrZm9udC5jcmVhdGUoZmFtaWx5PSJ0aW1lcyIsc2l6ZT00MCx3ZWlnaHQ9ImJvbGQiLHNsYW50PSJpdGFsaWMiKQ0KZm9udEhlYWRpbmcxPC10a2ZvbnQuY3JlYXRlKGZhbWlseT0idGltZXMiLHNpemU9MjAsd2VpZ2h0PSJib2xkIikNCmZvbnRIZWFkaW5nMjwtdGtmb250LmNyZWF0ZShmYW1pbHk9InRpbWVzIixzaXplPTE0LHdlaWdodD0iYm9sZCIpDQpmb250VGV4dExhYmVsIDwtIHRrZm9udC5jcmVhdGUoZmFtaWx5PSJ0aW1lcyIsc2l6ZT0xMikNCmZvbnRGaXhlZFdpZHRoIDwtIHRrZm9udC5jcmVhdGUoZmFtaWx5PSJjb3VyaWVyIixzaXplPTEyKQ0KIyBpbml0aWFsIHZhbHVlIGZvciBjaGVjayBib3gNCmNidmFsdWUxPC10Y2xWYXIoIjEiKTsgIGNidmFsdWUyPC10Y2xWYXIoIjEiKTsgIGNidmFsdWUzPC10Y2xWYXIoIjEiKQ0KY2J2YWx1ZTQ8LXRjbFZhcigiMSIpOyAgY2J2YWx1ZTU8LXRjbFZhcigiMSIpOyAgY2J2YWx1ZTY8LXRjbFZhcigiMSIpDQpjYnZhbHVlNzwtdGNsVmFyKCIxIik7ICBjYnZhbHVlODwtdGNsVmFyKCIxIik7ICBjYnZhbHVlOTwtdGNsVmFyKCIxIikNCmNidmFsdWUxMDwtdGNsVmFyKCIxIik7IGNidmFsdWUxMTwtdGNsVmFyKCIxIik7IGNidmFsdWUxMjwtdGNsVmFyKCIxIikNCmNidmFsdWUxMzwtdGNsVmFyKCIxIik7IGNidmFsdWUxNDwtdGNsVmFyKCIxIik7IGNidmFsdWUxNTwtdGNsVmFyKCIxIikNCmNidmFsdWUxNjwtdGNsVmFyKCIwIik7IGNidmFsdWUxNzwtdGNsVmFyKCIwIik7IGNidmFsdWUxODwtdGNsVmFyKCIwIikNCmNidmFsdWUxOTwtdGNsVmFyKCIwIik7IGNidmFsdWUyMTwtdGNsVmFyKCIxIikNCiMgIGluaXRpYWwgdmFsdWUgZm9yIHBhcmFtZXRlcnMNCnN0YXRpb25zPC10Y2xWYXIocGFzdGUoIiIpKTsgICBzdGR0PC10Y2xWYXIocGFzdGUoIjMiKSkNCkVudHJ5MTwtdGNsVmFyKHBhc3RlKCIxOTYxIikpOyBFbnRyeTI8LXRjbFZhcihwYXN0ZSgiMTk5MCIpKQ0KI0VudHJ5MzwtdGNsVmFyKHBhc3RlKCI1IikpDQpFbnRyeTQ8LXRjbFZhcihwYXN0ZSgiMCIpKQ0KRW50cnk1PC10Y2xWYXIocGFzdGUoIjAiKSkNCkVudHJ5NjwtdGNsVmFyKHBhc3RlKCIyNSIpKTsgICBFbnRyeTc8LXRjbFZhcihwYXN0ZSgiMCIpKQ0KRW50cnk4PC10Y2xWYXIocGFzdGUoIjIwIikpOyAgIEVudHJ5OTwtdGNsVmFyKHBhc3RlKCIwIikpDQojRW50cnkxMDwtdGNsVmFyKHBhc3RlKCIxMCIpKTsgRW50cnkxMTwtdGNsVmFyKHBhc3RlKCI1IikpDQpFbnRyeTEyPC10Y2xWYXIocGFzdGUoIjI1IikpDQpkYXlpbTwtYXMuaW50ZWdlcihjKDMxLDI4LDMxLDMwLDMxLDMwLDMxLDMxLDMwLDMxLDMwLDMxKSkNCmNydDwtMzsgICAgICBmbGFnPUYNCnRyZXNob2xkPTU7ICB3aW5zaXplPTUNCnV1PC0yNTsgICAgICBsdTwtMjANCnVsPC0wOyAgICAgICBsbDwtMA0KdGl0bGUxPC0iUGxvdCBvZiBJbmQxNDMiOyAgIHRpdGxlMjwtIkluZDE0MyI7ICAgdGl0bGUzPC0iWWVhcnMiDQoNCiMtLS0tLS0tLS0tLSBmcmMgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0NCmZyYzwtZnVuY3Rpb24oZGQseWVhcixtb250aCxpdGVtKXsNCiAgICANCiAgICBhPC1kZFtkZCR5ZWFyPT15ZWFyICYgZGQkbW9udGg9PW1vbnRoLGl0ZW1dDQogICAgYTwtYVthPi05OV0NCiAgICBmcmM8LWxlbmd0aChhKS9yZGltKHllYXIsbW9udGgpDQp9I2VuZA0KIy0tLS0tLS0tLS0tIGZyYyBlbmRzIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tDQoNCiMtLS0tLS0tLS0tLSBkb25lIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tDQpkb25lPC1mdW5jdGlvbigpe3RrZGVzdHJveShzdGFydDEpfQ0KIy0tLS0tLS0tLS0tIGRvbmUgZW5kcyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQ0KDQojLS0tLS0tLS0tLS0gcGVyY2VudGlsZSAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQ0KcGVyY2VudGlsZTwtZnVuY3Rpb24obix4LHBjdGlsZSl7DQogICAgeDE8LXhbaXMubmEoeCk9PUZdDQogICAgbjE8LWxlbmd0aCh4MSkNCiAgICBhPC1teXNvcnQoeDEsZGVjcmVhc2luZz1GKQ0KICAgIGI8LW4xKnBjdGlsZSswLjMzMzMqcGN0aWxlKzAuMzMzMw0KICAgIGJiPC10cnVuYyhiKQ0KICAgIHBlcmNlbnRpbGU8LWFbYmJdKyhiLWJiKSooYVtiYisxXS1hW2JiXSkgDQp9I2VuZA0KIy0tLS0tLS0tLS0tIHBlcmNlbnRpbGUgZW5kcyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQ0KDQojLS0tLS0tLS0tLS0gcHBsb3R0cyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQ0KcHBsb3R0czwtZnVuY3Rpb24odmFyPSJwcmNwIix0eXBlPSJoIix0aXQ9TlVMTCl7DQogICAgaWYodmFyPT0iZHRyIil7DQogICAgICAgIHltYXg8LW1heChkZFssInRtYXgiXS1kZFssInRtaW4iXSxuYS5ybT1UKQ0KICAgICAgICB5bWluPC0wDQogICAgfQ0KICAgIGVsc2UgaWYodmFyPT0icHJjcCIpew0KICAgICAgICB5bWF4PC1tYXgoZGRbLHZhcl0sbmEucm09VCkNCiAgICAgICAgeW1pbjwtMA0KICAgIH0NCiAgICBlbHNlew0KICAgICAgICB5bWF4PC1tYXgoZGRbLHZhcl0sbmEucm09VCkrMQ0KICAgICAgICB5bWluPC1taW4oZGRbLHZhcl0sbmEucm09VCktMQ0KICAgIH0NCiAgICBpZihpcy5uYSh5bWF4KXxpcy5uYSh5bWluKXwoeW1heD09LUluZil8KHltaW49PS1JbmYpKXsNCiAgICAgICAgeW1heDwtMTAwDQogICAgICAgIHltaW48LSgtMTAwKQ0KICAgIH0NCiAgICBwYXIobWZyb3c9Yyg0LDEpKQ0KICAgIHBhcihtYXI9YygzLjEsMi4xLDIuMSwyLjEpKQ0KICAgIGZvcihpIGluIHNlcSh5ZWFycyx5ZWFyZSwxMCkpew0KICAgICAgICBhdDwtcmVwKDEsMTApDQogICAgICAgICMgICBpZihpPnllYXJlKQ0KICAgICAgICBmb3IoaiBpbiAoaSsxKTptaW4oaSs5LHllYXJlKzEpKXsNCiAgICAgICAgICAgIGlmKGxlYXB5ZWFyKGopKSBhdFtqLWkrMV08LWF0W2otaV0rMzY2DQogICAgICAgICAgICBlbHNlIGF0W2otaSsxXTwtYXRbai1pXSszNjUNCiAgICAgICAgfQ0KICAgICAgICBpZih2YXI9PSJkdHIiKQ0KICAgICAgICAgICAgdHRtcDwtZGRbZGQkeWVhcj49aSZkZCR5ZWFyPD1taW4oaSs5LHllYXJlKSwidG1heCJdLWRkW2RkJHllYXI+PWkmZGQkeWVhcjw9bWluKGkrOSx5ZWFyZSksInRtaW4iXQ0KICAgICAgICBlbHNlIHR0bXA8LWRkW2RkJHllYXI+PWkmZGQkeWVhcjw9bWluKGkrOSx5ZWFyZSksdmFyXQ0KICAgICAgICBwbG90KDE6bGVuZ3RoKHR0bXApLHR0bXAsdHlwZT10eXBlLGNvbD0iYmx1ZSIseGxhYj0iIix5bGFiPSIiLHhheHQ9Im4iLHhsaW09YygxLDM2NjApLHlsaW09Yyh5bWluLHltYXgpKQ0KICAgICAgICBhYmxpbmUoaD0wKQ0KICAgICAgICB0dDwtc2VxKDEsbGVuZ3RoKHR0bXApKQ0KICAgICAgICB0dDwtdHRbaXMubmEodHRtcCk9PVRdDQogICAgICAgIGF4aXMoc2lkZT0xLGF0PWF0LGxhYmVscz1jKGk6KGkrOSkpKQ0KICAgICAgICBmb3IoayBpbiAxOjEwKSBhYmxpbmUodj1hdFtrXSxjb2w9InllbGxvdyIpDQogICAgICAgIGxpbmVzKHR0LHJlcCgwLGxlbmd0aCh0dCkpLHR5cGU9InAiLGNvbD0icmVkIikNCiAgICAgICAgdGl0bGUocGFzdGUoIlN0YXRpb246ICIsdGl0LCIsICIsaSwifiIsbWluKGkrOSx5ZWFyZSksIiwgICIsdmFyLHNlcD0iIikpDQogICAgfQ0KfQ0KIy0tLS0tLS0tLS0tIHBwbG90dHMgZW5kcyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQ0KDQojLS0tLS0tLS0tLS0gaW5kMTQzZ3NsIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tDQppbmQxNDNnc2w8LWZ1bmN0aW9uKCl7DQogICAgaWYgKGxhdGl0dWRlPDApIHNvdXRoPVQgZWxzZSBzb3V0aD1GDQogICAgaWYgKGxhdGl0dWRlPDApIGV5ZWFyPXllYXJlLTEgZWxzZSBleWVhcj15ZWFyZQ0KICAgIHRocmVzaG9sZDwtNQ0KICAgIGE8LWV5ZWFyLXllYXJzKzENCiAgICBiPC1yZXAoMCxhKQ0KICAgIGI8LWNiaW5kKGIsYikNCiAgICBjb2xuYW1lcyhiKTwtYygieWVhciIsImdzbCIpDQogICAgaT0xDQogICAgZm9yICh5ZWFyIGluIHllYXJzOmV5ZWFyKSB7DQogICAgICAgIGJbaSwieWVhciJdPC15ZWFyDQogICAgICAgIGlmKHNvdXRoKXsNCiAgICAgICAgICAgIGdzbHN0YXJ0PC1kZFtkZCR5ZWFyPT15ZWFyJmRkJG1vbnRoPjYsXQ0KICAgICAgICAgICAgZ3Nsc3RhcnQ8LShnc2xzdGFydFssInRtYXgiXStnc2xzdGFydFssInRtaW4iXSkvMg0KICAgICAgICAgICAgZ3NsZW5kPC1kZFtkZCR5ZWFyPT0oeWVhcisxKSZkZCRtb250aDw3LF0NCiAgICAgICAgICAgIGdzbGVuZDwtKGdzbGVuZFssInRtYXgiXStnc2xlbmRbLCJ0bWluIl0pLzINCiAgICAgICAgfQ0KICAgICAgICBlbHNlew0KICAgICAgICAgICAgZ3Nsc3RhcnQ8LWRkW2RkJHllYXI9PXllYXImZGQkbW9udGg8NyxdDQogICAgICAgICAgICBnc2xzdGFydDwtKGdzbHN0YXJ0WywidG1heCJdK2dzbHN0YXJ0WywidG1pbiJdKS8yDQogICAgICAgICAgICBnc2xlbmQ8LWRkW2RkJHllYXI9PXllYXImZGQkbW9udGg+NixdDQogICAgICAgICAgICBnc2xlbmQ8LShnc2xlbmRbLCJ0bWF4Il0rZ3NsZW5kWywidG1pbiJdKS8yDQogICAgICAgIH0NCiAgICAgICAgYmVnaW5kYXk8LTANCiAgICAgICAgY291bnQ9MA0KICAgICAgICBmb3Ioc3RlcCBpbiAxOmxlbmd0aChnc2xzdGFydCkpew0KICAgICAgICAgICAgaWYoaXMubmEoZ3Nsc3RhcnRbc3RlcF0pPT1GKXsNCiAgICAgICAgICAgICAgICBpZihnc2xzdGFydFtzdGVwXT50aHJlc2hvbGQpIGNvdW50PC1jb3VudCsxDQogICAgICAgICAgICAgICAgZWxzZSBjb3VudDwtMA0KICAgICAgICAgICAgfQ0KICAgICAgICAgICAgZWxzZSBjb3VudDwtMA0KICAgICAgICAgICAgaWYoY291bnQ+NSl7DQogICAgICAgICAgICAgICAgYmVnaW5kYXk8LXN0ZXAtNQ0KICAgICAgICAgICAgICAgIGJyZWFrDQogICAgICAgICAgICB9DQogICAgICAgIH0NCiAgICAgICAgDQogICAgICAgICMgICAgaWYoYmVnaW5kYXk9PTApew0KICAgICAgICAjICAgICAgYltpLCJnc2wiXTwtMA0KICAgICAgICAjICAgICAgYnJlYWsNCiAgICAgICAgIyAgICB9DQogICAgICAgIA0KICAgICAgICBlbmRkYXk8LTANCiAgICAgICAgY291bnQ8LTANCiAgICAgICAgZm9yKHN0ZXAgaW4gMTpsZW5ndGgoZ3NsZW5kKSl7DQogICAgICAgICAgICBpZihpcy5uYShnc2xlbmRbc3RlcF0pPT1GKXsNCiAgICAgICAgICAgICAgICBpZihnc2xlbmRbc3RlcF08dGhyZXNob2xkKSBjb3VudDwtY291bnQrMQ0KICAgICAgICAgICAgICAgIGVsc2UgY291bnQ8LTANCiAgICAgICAgICAgIH0NCiAgICAgICAgICAgIGVsc2UgY291bnQ8LTANCiAgICAgICAgICAgIGlmKGNvdW50PjUpew0KICAgICAgICAgICAgICAgIGVuZGRheTwtc3RlcC01DQogICAgICAgICAgICAgICAgYnJlYWsNCiAgICAgICAgICAgIH0NCiAgICAgICAgfQ0KICAgICAgICANCiAgICAgICAgaWYoc3VtKGlzLm5hKGdzbHN0YXJ0KSkrc3VtKGlzLm5hKGdzbGVuZCkpPjE1KSAgYltpLCJnc2wiXTwtTkENCiAgICAgICAgZWxzZXsNCiAgICAgICAgICAgIGlmKGJlZ2luZGF5PT0wKQ0KICAgICAgICAgICAgICAgIGJbaSwiZ3NsIl08LTANCiAgICAgICAgICAgIGVsc2Ugew0KICAgICAgICAgICAgICAgIGlmKGVuZGRheT09MCkgIGJbaSwiZ3NsIl08LWxlbmd0aChnc2xlbmQpK2xlbmd0aChnc2xzdGFydCktYmVnaW5kYXkNCiAgICAgICAgICAgICAgICBlbHNlIGJbaSwiZ3NsIl08LWVuZGRheStsZW5ndGgoZ3Nsc3RhcnQpLWJlZ2luZGF5DQogICAgICAgICAgICB9DQogICAgICAgIH0NCiAgICAgICAgDQogICAgICAgIGk9aSsxDQogICAgfSANCiAgICBiPC1hcy5kYXRhLmZyYW1lKGIpDQogICAgbmFtMTwtcGFzdGUob3V0aW5kZGlyLHBhc3RlKG9maWxlbmFtZSwiX0dTTC5jc3YiLHNlcD0iIiksc2VwPSIvIikNCiAgICB3cml0ZS50YWJsZShiLGZpbGU9bmFtMSxhcHBlbmQ9RixxdW90ZT1GLHNlcD0iLCAiLG5hPSItOTkuOSIscm93Lm5hbWVzPUYpDQogICAgDQogICAgbmFtdDwtcGFzdGUob3V0dHJkZGlyLHBhc3RlKG9maWxlbmFtZSwiX3RyZW5kLmNzdiIsc2VwPSIiKSxzZXA9Ii8iKQ0KICAgIGlmKHN1bShpcy5uYShiWywiZ3NsIl0pKT49KHllYXJlLXllYXJzKzEtMTApKXsNCiAgICAgICAgYmV0YWhhdDwtTkENCiAgICAgICAgYmV0YXN0ZDwtTkENCiAgICAgICAgcHZhbHVlPC1OQQ0KICAgIH0NCiAgICBlbHNlew0KICAgICAgICBmaXQxPC1sc2ZpdChiWywxXSxiWywiZ3NsIl0pDQogICAgICAgIG91dDE8LWxzLnByaW50KGZpdDEscHJpbnQuaXQ9RikNCiAgICAgICAgcHZhbHVlPC1yb3VuZChhcy5udW1lcmljKG91dDEkc3VtbWFyeVsxLDZdKSwzKQ0KICAgICAgICBiZXRhaGF0PC1yb3VuZChhcy5udW1lcmljKG91dDEkY29lZi50YWJsZVtbMV1dWzIsMV0pLDMpDQogICAgICAgIGJldGFzdGQ8LXJvdW5kKGFzLm51bWVyaWMob3V0MSRjb2VmLnRhYmxlW1sxXV1bMiwyXSksMykNCiAgICB9DQogICAgY2F0KGZpbGU9bmFtdCxwYXN0ZShsYXRpdHVkZSxsb25naXR1ZGUsImdzbCIseWVhcnMseWVhcmUsYmV0YWhhdCxiZXRhc3RkLHB2YWx1ZSxzZXA9IiwiKSxmaWxsPTE4MCxhcHBlbmQ9VCkNCiAgICANCiAgICBuYW0yPC1wYXN0ZShvdXRqcGdkaXIscGFzdGUob2ZpbGVuYW1lLCJfR1NMLmpwZyIsc2VwPSIiKSxzZXA9Ii8iKQ0KICAgIGpwZWcoZmlsZT1uYW0yLHdpZHRoPTEwMjQsaGVpZ2h0PTc2OCkNCiAgICBwbG90eChiWywxXSxiWywiZ3NsIl0sbWFpbj1wYXN0ZSgiR1NMIixvZmlsZW5hbWUsc2VwPSIgICAiKSx4bGFiPSJZZWFyIix5bGFiPSJHU0wiKQ0KICAgIGRldi5vZmYoKQ0KfQ0KIy0tLS0tLS0tLS0tIGluZDE0M2dzbCBlbmRzIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tDQoNCiMtLS0tLS0tLS0tLSBkYXRhZXh0IC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tDQojIHNlZW1zIHRoaXMgZnVuY3Rpb24gaXMgbmV2ZXIgdXNlZC4uLg0KZGF0YWV4dDwtZnVuY3Rpb24oZGQseWVhcixtb250aCxkYXksaXRlbSl7DQogICAgRGF0YWV4dDwtZGRbZGQkeWVhcj09eWVhciAmIGRkJG1vbnRoPT1tb250aCAmIGRkJGRheT09ZGF5LGl0ZW1dDQp9DQojLS0tLS0tLS0tLS0gZGF0YWV4dCBlbmRzIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tDQoNCiMgLS0tLS0tLS0tLS0gbGVhcHllYXIgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0NCiMgY2hlY2sgaWYgJ3llYXInIGlzIGEgbGVhcCB5ZWFyDQojIHJldHVybnMgVCBvciBGDQpsZWFweWVhcjwtZnVuY3Rpb24oeWVhcil7DQogICAgcmVtYWluZGVyNDAwIDwtdHJ1bmMoeWVhci00MDAqdHJ1bmMoeWVhci80MDApKQ0KICAgIHJlbWFpbmRlcjEwMCA8LXRydW5jKHllYXItMTAwKnRydW5jKHllYXIvMTAwKSkNCiAgICByZW1haW5kZXI0IDwtdHJ1bmMoeWVhci00KnRydW5jKHllYXIvNCkpDQogICAgaWYgKHJlbWFpbmRlcjQwMCA9PSAwKSBsZWFweWVhciA9IFQNCiAgICBlbHNlew0KICAgICAgICBpZihyZW1haW5kZXIxMDAgPT0gMCkgbGVhcHllYXIgPSBGDQogICAgICAgIGVsc2V7DQogICAgICAgICAgICBpZihyZW1haW5kZXI0ID09IDApIGxlYXB5ZWFyID0gVA0KICAgICAgICAgICAgZWxzZSBsZWFweWVhciA9IEYNCiAgICAgICAgfQ0KICAgIH0NCn0NCiMgLS0tLS0tLS0tLS0gbGVhcHllYXIgZW5kcyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQ0KDQojIC0tLS0tLS0tLS0tIHJkaW0gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0NCiMgZGF5ICMgaW4gYSBtb250aA0KIw0KcmRpbTwtZnVuY3Rpb24oeWVhcixtb250aCkgew0KICAgIGE8LWxlYXB5ZWFyKHllYXIpIA0KICAgIGlmIChtb250aD09MSkgcmRpbTwtMzENCiAgICBlbHNlIGlmIChtb250aD09MykgcmRpbTwtMzENCiAgICBlbHNlIGlmIChtb250aD09NCkgcmRpbTwtMzANCiAgICBlbHNlIGlmIChtb250aD09NSkgcmRpbTwtMzENCiAgICBlbHNlIGlmIChtb250aD09NikgcmRpbTwtMzANCiAgICBlbHNlIGlmIChtb250aD09NykgcmRpbTwtMzENCiAgICBlbHNlIGlmIChtb250aD09OCkgcmRpbTwtMzENCiAgICBlbHNlIGlmIChtb250aD09OSkgcmRpbTwtMzANCiAgICBlbHNlIGlmIChtb250aD09MTApIHJkaW08LTMxDQogICAgZWxzZSBpZiAobW9udGg9PTExKSByZGltPC0zMA0KICAgIGVsc2UgaWYgKG1vbnRoPT0xMikgcmRpbTwtMzENCiAgICBlbHNlIGlmIChhPT1UICYgbW9udGg9PTIpIHJkaW08LTI5DQogICAgZWxzZSByZGltPC0yOCAgDQp9DQojIC0tLS0tLS0tLS0tIHJkaW0gZW5kcyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQ0KDQojIC0tLS0tLS0tLS0tIHFjb250cm9sIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tDQpxY29udHJvbDwtZnVuY3Rpb24oKXsNCiAgICB0a21lc3NhZ2VCb3gobWVzc2FnZT1wYXN0ZSgiRGF0YSBRQygiLG9maWxlbmFtZSwiKSBtYXkgdGFrZSBhIGZldyBtaW51dGVzLCBjbGljayBPSyB0byBjb250aW51ZS4iLHNlcD0iIikpDQogICAgIyBvdXRwdXQgcmVjb3JkcyBvZiBwcm9ibGVtYXRpYyBsaWtlIHByY3AgPDAgYW5kIE5BDQogICAgZGR1PC1kdXBsaWNhdGVkKGRkWyxjKCJ5ZWFyIiwibW9udGgiLCJkYXkiKV0pDQogICAgaWYoc3VtKGRkdSk+MCl7DQogICAgICAgIG5hbTE8LXBhc3RlKG91dGxvZ2RpcixwYXN0ZShvZmlsZW5hbWUsImR1cGxpUUMuY3N2IixzZXA9IiIpLHNlcD0iLyIpDQogICAgICAgIG1zZz1wYXN0ZSgiRGF0ZSBkdXBsaWNhdGVkIGZvdW5kIGluIG9yaWdpbmFsIGRhdGEgZmlsZSwgcGxlYXNlIGNoZWNrOiIsbmFtMSxzZXA9IiAiKQ0KICAgICAgICB0a21lc3NhZ2VCb3gobWVzc2FnZT1tc2cpDQogICAgICAgIGRkdTI8LWRkW2R1cGxpY2F0ZWQoZGRbLGMoInllYXIiLCJtb250aCIsImRheSIpXSk9PVQsYygieWVhciIsICJtb250aCIsICJkYXkiKV0NCiAgICAgICAgbmFtMTwtcGFzdGUob3V0bG9nZGlyLHBhc3RlKG9maWxlbmFtZSwiZHVwbGlRQy5jc3YiLHNlcD0iIiksc2VwPSIvIikNCiAgICAgICAgd3JpdGUudGFibGUoZGR1MixmaWxlPW5hbTEsYXBwZW5kPUYscXVvdGU9RixzZXA9IiwgIixyb3cubmFtZXM9RikNCiAgICAgICAgdGtkZXN0cm95KHN0YXJ0MSkNCiAgICAgICAgc3RvcChwYXN0ZSgiUUMgc3RvcHBlZCBkdWUgdG8gZHVwbGljYXRlZCBkYXRlLCBwbGVhc2UgY2hlY2sgIixuYW0xLHNlcD0iIikpDQogICAgfQ0KICAgIA0KICAgIG1pZDwtZGRbaXMubmEoZGQkcHJjcCk9PUYsXSAgIyBjaG9vc2Ugbm9uLU1JU1NJTkcgUFJDUA0KICAgIG1pZDwtbWlkW21pZCRwcmNwPDAsXSAgICAgICAgIyBJcyB0aGVyZSB1bnJlYXNvbmFibGUgUFJDUD8NCiAgICAjZGRbaXMubmEoZGQkcHJjcCk9PUYgJiBkZCRwcmNwPDAsInByY3AiXTwtTkENCiAgICBuYW0xPC1wYXN0ZShvdXRsb2dkaXIscGFzdGUob2ZpbGVuYW1lLCJfcHJjcFFDLmNzdiIsc2VwPSIiKSxzZXA9Ii8iKQ0KICAgIHdyaXRlLnRhYmxlKG1pZCxmaWxlPW5hbTEsYXBwZW5kPUYscXVvdGU9RixzZXA9IiwgIixyb3cubmFtZXM9RikNCiAgICBpZiAoZGltKG1pZClbMV0+MCkgdGttZXNzYWdlQm94KG1lc3NhZ2U9cGFzdGUoIkVycm9ycyBpbiBwcmNwLCBwbGVhc2UgY2hlY2sgdGhlIGxvZyBmaWxlIixuYW0xLHNlcD0iICIpKQ0KICAgICMgb3V0cHV0IHBsb3RzIGZvciBQUkNQDQogICAgbmFtMTwtcGFzdGUob3V0bG9nZGlyLHBhc3RlKG9maWxlbmFtZSwiX3ByY3BQTE9ULnBkZiIsc2VwPSIiKSxzZXA9Ii8iKQ0KICAgIHBkZihmaWxlPW5hbTEpDQogICAgdHRtcDwtZGRbZGQkcHJjcD49MSwicHJjcCJdDQogICAgdHRtcDwtdHRtcFtpcy5uYSh0dG1wKT09Rl0NCiAgICBpZihsZW5ndGgodHRtcCk+MzApew0KICAgICAgICBoaXN0KHR0bXAsbWFpbj1wYXN0ZSgiSGlzdG9ncmFtIGZvciBTdGF0aW9uOiIsb2ZpbGVuYW1lLCIgb2YgUFJDUD49MW1tIixzZXA9IiIpLGJyZWFrcz1jKHNlcSgwLDIwLDIpLG1heCgzMCx0dG1wKSkseGxhYj0iIixjb2w9ImdyZWVuIixmcmVxPUYpDQogICAgICAgIGxpbmVzKGRlbnNpdHkodHRtcCxidz0wLjIsZnJvbT0xKSxjb2w9InJlZCIpDQogICAgfQ0KICAgIHBwbG90dHModmFyPSJwcmNwIix0aXQ9b2ZpbGVuYW1lKQ0KICAgIGRldi5vZmYoKQ0KICAgIG5hbTE8LXBhc3RlKG91dGxvZ2RpcixwYXN0ZShvZmlsZW5hbWUsIl90bWF4UExPVC5wZGYiLHNlcD0iIiksc2VwPSIvIikNCiAgICBwZGYoZmlsZT1uYW0xKQ0KICAgIHBwbG90dHModmFyPSJ0bWF4Iix0eXBlPSJsIix0aXQ9b2ZpbGVuYW1lKQ0KICAgIGRldi5vZmYoKQ0KICAgIG5hbTE8LXBhc3RlKG91dGxvZ2RpcixwYXN0ZShvZmlsZW5hbWUsIl90bWluUExPVC5wZGYiLHNlcD0iIiksc2VwPSIvIikNCiAgICBwZGYoZmlsZT1uYW0xKQ0KICAgIHBwbG90dHModmFyPSJ0bWluIix0eXBlPSJsIix0aXQ9b2ZpbGVuYW1lKQ0KICAgIGRldi5vZmYoKQ0KICAgIG5hbTE8LXBhc3RlKG91dGxvZ2RpcixwYXN0ZShvZmlsZW5hbWUsIl9kdHJQTE9ULnBkZiIsc2VwPSIiKSxzZXA9Ii8iKQ0KICAgIHBkZihmaWxlPW5hbTEpDQogICAgcHBsb3R0cyh2YXI9ImR0ciIsdHlwZT0ibCIsdGl0PW9maWxlbmFtZSkNCiAgICBkZXYub2ZmKCkNCiAgICANCiAgICAjcGFyKG1mcm93PWMoMSwxKSkNCiAgICAjIG91dHB1dCBwcm9ibGVtYXRpYyB0ZW1wZXJhdHVyZSBsaWtlIHRtYXggPCB0bWluDQogICAgbW08LWRkWywidG1heCJdLWRkWywidG1pbiJdDQogICAgZGQ8LWNiaW5kKGRkLG1tKQ0KICAgIGRpbW5hbWVzKGRkKVtbMl1dWzddPC0iZHRyIg0KICAgICNvdXRwdXQgImxvZyIgZmlsZSByZXZpZXcNCiAgICB0ZW1pc3M8LWRkDQogICAgdGVtaXNzPC10ZW1pc3NbaXMubmEodGVtaXNzWywidG1heCJdKT09RiZpcy5uYSh0ZW1pc3NbLCJ0bWluIl0pPT1GLF0NCiAgICAjICB0ZW1pc3M8LXRlbWlzc1tpcy5uYSh0ZW1pc3NbLDZdKT09RixdDQogICAgdGVtaXNzPC10ZW1pc3NbdGVtaXNzWyw3XTw9MHx0ZW1pc3NbLDVdPD0oLTcwKXx0ZW1pc3NbLDVdPj03MHx0ZW1pc3NbLDZdPD0oLTcwKXx0ZW1pc3NbLDZdPj03MCxdDQogICAgZGltbmFtZXModGVtaXNzKVtbMl1dWzddPC0idG1heC10bWluIg0KICAgIG5hbTE8LXBhc3RlKG91dGxvZ2RpcixwYXN0ZShvZmlsZW5hbWUsIl90ZW1wUUMuY3N2IixzZXA9IiIpLHNlcD0iLyIpDQogICAgd3JpdGUudGFibGUodGVtaXNzLGZpbGU9bmFtMSxhcHBlbmQ9RixxdW90ZT1GLHNlcD0iLCAiLHJvdy5uYW1lcz1GKQ0KICAgIGlmIChkaW0odGVtaXNzKVsxXT4wKSB7DQogICAgICAgIHRrbWVzc2FnZUJveChtZXNzYWdlPXBhc3RlKCJFcnJvcnMgaW4gdGVtcGVyYXR1cmUsIHBsZWFzZSBjaGVjayB0aGUgbG9nIGZpbGUiLG5hbTEsc2VwPSIgIikpDQogICAgICAgICMgcmVjb3JkcyB3aXRoIGFicyh0bWF4KT49NzAsIGFicyh0bWluKT49NzAgc2V0IHRvIE5BDQogICAgICAgIGRkW2lzLm5hKGRkWyw1XSk9PUYgJiBhYnMoZGRbLDVdKT49NzAsNV08LU5BICAgICAjIFRoaXMgaXMgZGlmZmVyZW50IGZyb20gRmNsaW1kZXggY29kZSAgISEhISEhISEhISEhISEhISEhISEhISEhISEhIQ0KICAgICAgICBkZFtpcy5uYShkZFssNl0pPT1GICYgYWJzKGRkWyw2XSk+PTcwLDZdPC1OQQ0KICAgICAgICAjIHJlY29yZHMgd2l0aCB0bWF4IDwgdG1pbiBhcmUgc2V0IHRvIE5BDQogICAgICAgIGRkW2lzLm5hKGRkWyw1XSk9PUYgJiBpcy5uYShkZFssNl0pPT1GICYgZGRbLCJkdHIiXTwwLGMoInRtYXgiLCJ0bWluIildPC1OQQ0KICAgICAgICAjICAgZGRbaXMubmEoZGRbLDVdKT09RiAmIGRkWywibW0iXTwwLCJ0bWluIl08LU5BDQogICAgfQ0KICAgICMgIGRkPC1kZFssLTddDQogICAgDQogICAgIyBvdXRwdXQgcHJvYmxlbWF0aWMgdGVtcGVyYXR1cmUgd2hpY2ggaXMgb3V0IG9mIDMgc3RhbmRhcmQgZGl2aWF0aW9uICh0ZW1wIG9ubHkpDQogICAgeXM8LXllYXJlLXllYXJzKzENCiAgICANCiAgICB0bWF4bTwtbWF0cml4KDAseXMsMzY1KQ0KICAgIHRtaW5tPC1tYXRyaXgoMCx5cywzNjUpDQogICAgdGR0cm08LW1hdHJpeCgwLHlzLDM2NSkNCiAgICANCiAgICB0bWF4c3RkPC1yZXAoMCwzNjUpDQogICAgdG1pbnN0ZDwtcmVwKDAsMzY1KQ0KICAgIHRkdHJzdGQ8LXJlcCgwLDM2NSkNCiAgICANCiAgICB0bWF4bWVhbjwtcmVwKDAsMzY1KQ0KICAgIHRtaW5tZWFuPC1yZXAoMCwzNjUpDQogICAgdGR0cm1lYW48LXJlcCgwLDM2NSkNCiAgICANCiAgICBmb3IoaSBpbiAxOnlzKQ0KICAgICAgICB0bWF4bVtpLF08LWRkW2RkWywieWVhciJdPT0oaSt5ZWFycy0xKSYoZGRbLCJtb250aCJdKjEwMCtkZFssImRheSJdIT0yMjkpLCJ0bWF4Il0NCiAgICBmb3IoaSBpbiAxOjM2NSl7DQogICAgICAgIHRtYXhzdGRbaV08LXNxcnQodmFyKHRtYXhtWyxpXSxuYS5ybT1UKSkNCiAgICAgICAgdG1heG1lYW5baV08LW1lYW4odG1heG1bLGldLG5hLnJtPVQpDQogICAgfQ0KICAgIA0KICAgIGZvcihpIGluIDE6eXMpDQogICAgICAgIHRtaW5tW2ksXTwtZGRbZGRbLCJ5ZWFyIl09PShpK3llYXJzLTEpJihkZFssIm1vbnRoIl0qMTAwK2RkWywiZGF5Il0hPTIyOSksInRtaW4iXQ0KICAgIGZvcihpIGluIDE6MzY1KXsNCiAgICAgICAgdG1pbnN0ZFtpXTwtc3FydCh2YXIodG1pbm1bLGldLG5hLnJtPVQpKQ0KICAgICAgICB0bWlubWVhbltpXTwtbWVhbih0bWlubVssaV0sbmEucm09VCkNCiAgICB9DQogICAgDQogICAgZm9yKGkgaW4gMTp5cykNCiAgICAgICAgdGR0cm1baSxdPC1kZFtkZFssInllYXIiXT09KGkreWVhcnMtMSkmKGRkWywibW9udGgiXSoxMDArZGRbLCJkYXkiXSE9MjI5KSwiZHRyIl0NCiAgICBmb3IoaSBpbiAxOjM2NSl7DQogICAgICAgIHRkdHJzdGRbaV08LXNxcnQodmFyKHRkdHJtWyxpXSxuYS5ybT1UKSkNCiAgICAgICAgdGR0cm1lYW5baV08LW1lYW4odGR0cm1bLGldLG5hLnJtPVQpDQogICAgfQ0KICAgIA0KICAgIHRtYXhzdGRsZWFwPC1yZXAoMCwzNjYpDQogICAgdG1heHN0ZGxlYXBbMTo1OV08LXRtYXhzdGRbMTo1OV0NCiAgICB0bWF4c3RkbGVhcFs2MF08LXRtYXhzdGRbNTldDQogICAgdG1heHN0ZGxlYXBbNjE6MzY2XTwtdG1heHN0ZFs2MDozNjVdDQogICAgDQogICAgdG1heG1lYW5sZWFwPC1yZXAoMCwzNjYpDQogICAgdG1heG1lYW5sZWFwWzE6NTldPC10bWF4bWVhblsxOjU5XQ0KICAgIHRtYXhtZWFubGVhcFs2MF08LXRtYXhtZWFuWzU5XQ0KICAgIHRtYXhtZWFubGVhcFs2MTozNjZdPC10bWF4bWVhbls2MDozNjVdDQogICAgDQogICAgdG1pbnN0ZGxlYXA8LXJlcCgwLDM2NikNCiAgICB0bWluc3RkbGVhcFsxOjU5XTwtdG1pbnN0ZFsxOjU5XQ0KICAgIHRtaW5zdGRsZWFwWzYwXTwtdG1pbnN0ZFs1OV0NCiAgICB0bWluc3RkbGVhcFs2MTozNjZdPC10bWluc3RkWzYwOjM2NV0NCiAgICANCiAgICB0bWlubWVhbmxlYXA8LXJlcCgwLDM2NikNCiAgICB0bWlubWVhbmxlYXBbMTo1OV08LXRtaW5tZWFuWzE6NTldDQogICAgdG1pbm1lYW5sZWFwWzYwXTwtdG1pbm1lYW5bNTldDQogICAgdG1pbm1lYW5sZWFwWzYxOjM2Nl08LXRtaW5tZWFuWzYwOjM2NV0NCiAgICANCiAgICB0ZHRyc3RkbGVhcDwtcmVwKDAsMzY2KQ0KICAgIHRkdHJzdGRsZWFwWzE6NTldPC10ZHRyc3RkWzE6NTldDQogICAgdGR0cnN0ZGxlYXBbNjBdPC10ZHRyc3RkWzU5XQ0KICAgIHRkdHJzdGRsZWFwWzYxOjM2Nl08LXRkdHJzdGRbNjA6MzY1XQ0KICAgIA0KICAgIHRkdHJtZWFubGVhcDwtcmVwKDAsMzY2KQ0KICAgIHRkdHJtZWFubGVhcFsxOjU5XTwtdGR0cm1lYW5bMTo1OV0NCiAgICB0ZHRybWVhbmxlYXBbNjBdPC10ZHRybWVhbls1OV0NCiAgICB0ZHRybWVhbmxlYXBbNjE6MzY2XTwtdGR0cm1lYW5bNjA6MzY1XQ0KICAgIA0KICAgIHRtcDwtbWF0cml4KDAsZGltKGRkKVsxXSw2KQ0KICAgIGRpbW5hbWVzKHRtcCk8LWxpc3QoTlVMTCxjKCJ0bWF4bG93IiwidG1heHVwIiwidG1pbmxvdyIsInRtaW51cCIsImR0cmxvdyIsImR0cnVwIikpDQogICAgDQogICAgaWR4PC0wDQogICAgZm9yKGkgaW4geWVhcnM6eWVhcmUpew0KICAgICAgICBpZihsZWFweWVhcihpKT09VCl7DQogICAgICAgICAgICB0bXBbKGlkeCsxKTooaWR4KzM2NiksMV08LXRtYXhtZWFubGVhcC1jcnQqdG1heHN0ZGxlYXANCiAgICAgICAgICAgIHRtcFsoaWR4KzEpOihpZHgrMzY2KSwyXTwtdG1heG1lYW5sZWFwK2NydCp0bWF4c3RkbGVhcA0KICAgICAgICAgICAgdG1wWyhpZHgrMSk6KGlkeCszNjYpLDNdPC10bWlubWVhbmxlYXAtY3J0KnRtaW5zdGRsZWFwDQogICAgICAgICAgICB0bXBbKGlkeCsxKTooaWR4KzM2NiksNF08LXRtaW5tZWFubGVhcCtjcnQqdG1pbnN0ZGxlYXANCiAgICAgICAgICAgIHRtcFsoaWR4KzEpOihpZHgrMzY2KSw1XTwtdGR0cm1lYW5sZWFwLWNydCp0ZHRyc3RkbGVhcA0KICAgICAgICAgICAgdG1wWyhpZHgrMSk6KGlkeCszNjYpLDZdPC10ZHRybWVhbmxlYXArY3J0KnRkdHJzdGRsZWFwDQogICAgICAgICAgICBpZHg8LWlkeCszNjYNCiAgICAgICAgfQ0KICAgICAgICBlbHNlew0KICAgICAgICAgICAgdG1wWyhpZHgrMSk6KGlkeCszNjUpLDFdPC10bWF4bWVhbi1jcnQqdG1heHN0ZA0KICAgICAgICAgICAgdG1wWyhpZHgrMSk6KGlkeCszNjUpLDJdPC10bWF4bWVhbitjcnQqdG1heHN0ZA0KICAgICAgICAgICAgdG1wWyhpZHgrMSk6KGlkeCszNjUpLDNdPC10bWlubWVhbi1jcnQqdG1pbnN0ZA0KICAgICAgICAgICAgdG1wWyhpZHgrMSk6KGlkeCszNjUpLDRdPC10bWlubWVhbitjcnQqdG1pbnN0ZA0KICAgICAgICAgICAgdG1wWyhpZHgrMSk6KGlkeCszNjUpLDVdPC10ZHRybWVhbi1jcnQqdGR0cnN0ZA0KICAgICAgICAgICAgdG1wWyhpZHgrMSk6KGlkeCszNjUpLDZdPC10ZHRybWVhbitjcnQqdGR0cnN0ZA0KICAgICAgICAgICAgaWR4PC1pZHgrMzY1DQogICAgICAgIH0NCiAgICB9DQogICAgDQogICAgb2RhdGE8LWNiaW5kKGRkLHRtcCkNCiAgICANCiAgICBvZGF0YTwtb2RhdGFbaXMubmEob2RhdGFbLCJ0bWF4Il0pPT1GLF0NCiAgICBvZGF0YTwtb2RhdGFbaXMubmEob2RhdGFbLCJ0bWluIl0pPT1GLF0NCiAgICBvZGF0YTwtb2RhdGFbaXMubmEob2RhdGFbLCJkdHIiXSk9PUYsXQ0KICAgIG8xZGF0YTwtb2RhdGFbb2RhdGFbLDVdPG9kYXRhWyw4XXxvZGF0YVssNV0+b2RhdGFbLDldfG9kYXRhWyw2XTxvZGF0YVssMTBdfG9kYXRhWyw2XT5vZGF0YVssMTFdfG9kYXRhWyw3XTxvZGF0YVssMTJdfG9kYXRhWyw3XT5vZGF0YVssMTNdLF0NCiAgICAjbzJkYXRhPC1vZGF0YVtvZGF0YVssNV0+b2RhdGFbLDhdLF0NCiAgICAjbzNkYXRhPC1vZGF0YVtvZGF0YVssNl08b2RhdGFbLDldLF0NCiAgICAjbzRkYXRhPC1vZGF0YVtvZGF0YVssNl0+b2RhdGFbLDEwXSxdDQogICAgDQogICAgI3dyaXRlLnRhYmxlKGVycnN0ZG8sZmlsZT1uYW0xLGFwcGVuZD1GLHF1b3RlPUYsc2VwPSIsIixyb3cubmFtZXM9RikNCiAgICBpZiAoZGltKG8xZGF0YSlbMV0gPiAwKXsNCiAgICAgICAgbmFtMTwtcGFzdGUob3V0bG9nZGlyLHBhc3RlKG9maWxlbmFtZSwiX3RlcHN0ZFFDLmNzdiIsc2VwPSIiKSxzZXA9Ii8iKQ0KICAgICAgICB0a21lc3NhZ2VCb3gobWVzc2FnZT1wYXN0ZSgiT3V0bGllcnMgZm91bmQsIHBsZWFzZSBjaGVjayB0aGUgbG9nIGZpbGU6ICIsbmFtMSxzZXA9IiIpKQ0KICAgICAgICBvZmlsZTwtY2JpbmQobzFkYXRhWyxjKDEsMiwzLDgsNSw5LDEwLDYsMTEsMTIsNywxMyldKQ0KICAgICAgICB3cml0ZS50YWJsZShyb3VuZChvZmlsZSxkaWdpdD0yKSxmaWxlPW5hbTEsYXBwZW5kPUYscXVvdGU9RixzZXA9IiwiLHJvdy5uYW1lcz1GKQ0KICAgIH0NCiAgICANCiAgICBkZDwtZGRbLGMoInllYXIiLCJtb250aCIsImRheSIsInByY3AiLCJ0bWF4IiwidG1pbiIpXTsgIGFzc2lnbigiZGQiLGRkLGVudmlyPS5HbG9iYWxFbnYpDQogICAgDQogICAgbmFtY2FsPC1wYXN0ZShuYW1hLCJpbmRjYWwuY3N2IixzZXA9IiIpDQogICAgYXNzaWduKCJuYW1jYWwiLG5hbWNhbCxlbnZpcj0uR2xvYmFsRW52KQ0KICAgIHdyaXRlLnRhYmxlKGRkLGZpbGU9bmFtY2FsLGFwcGVuZD1GLHF1b3RlPUYsc2VwPSIsIixyb3cubmFtZXM9RixuYT0iLTk5LjkiKQ0KICAgIA0KICAgIHRrbWVzc2FnZUJveChtZXNzYWdlPXBhc3RlKCJJZiB5b3UgaGF2ZSBjaGVja2VkIGRhdGEoIiwgbmFtY2FsLCIpLCBjbGljayBPSyB0byBjb250aW51ZS4iLHNlcD0iIikpDQp9DQojIC0tLS0tLS0tLS0tLSBxY29udHJvbCBlbmRzIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tDQoNCiMgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tDQojIE5BU1RTVA0KbmFzdGF0PC1mdW5jdGlvbigpew0KICAgIGRkIDwtIHJlYWQudGFibGUobmFtY2FsLGhlYWRlcj1ULHNlcD0iLCIsbmEuc3RyaW5ncz0iLTk5LjkiLGNvbENsYXNzZXM9cmVwKCJyZWFsIiw2KSkNCiAgICBhc3NpZ24oImRkIixkZCxlbnZpcj0uR2xvYmFsRW52KQ0KICAgICMgTkEgc3RhdGlzdGljcw0KICAgIG5hc3Q8LXJlcCgwLDEyKQ0KICAgIG5hc3Q8LWFycmF5KG5hc3QsYygxLDEyLDEyLCh5ZWFyZS15ZWFycysxKSkpDQogICAgZGltbmFtZXMobmFzdCk8LWxpc3QoTlVMTCxjKCJ5bmFwciIsInluYXRtYSIsInluYXRtaSIsIm5hcHIiLCJuYXRtYSIsIm5hdG1pIiwibW5hcHI+MyIsIm1uYXRtYT4zIiwibW5hdG1pPjMiLCJ5bmFwcj4xNSIsInluYXRtYT4xNSIsInluYXRtaT4xNSIpLE5VTEwsTlVMTCkNCiAgICB5czwteWVhcmUteWVhcnMrMSAgICAgICAgICAgICAgICAgICAgDQogICAgeWVhcj15ZWFycw0KICAgIGFhMTwtbWF0cml4KE5BLDEyKnlzLDQpICAgIyBtb250aGx5DQogICAgZGltbmFtZXMoYWExKTwtbGlzdChOVUxMLGMoInllYXIiLCJtb250aCIsInRtYXhtIiwidG1pbm0iKSkNCiAgICBhYTFbLCJ5ZWFyIl08LXllYXJzOnllYXJlDQogICAgYWExWywieWVhciJdPC1teXNvcnQoYWExWywieWVhciJdLGRlY3JlYXNpbmc9RikgICAgIyBJcyB0aGlzIHN0ZXAgbmVjZXNzYXJ5Pz8/DQogICAgYWExWywibW9udGgiXTwtMToxMg0KICAgIGFhMjwtbWF0cml4KE5BLHlzLDMpICAgICAgIyBhbm51YWwNCiAgICBkaW1uYW1lcyhhYTIpPC1saXN0KE5VTEwsYygieWVhciIsInRtYXhtIiwidG1pbm0iKSkNCiAgICBhYTJbLCJ5ZWFyIl08LXllYXJzOnllYXJlDQogICAgZm9yIChpIGluIDE6KHllYXJlLXllYXJzKzEpKXsNCiAgICAgICAgbW9udGg8LTE7ICAgICBtaWR2YWx1ZTE8LWRkW2RkJHllYXI9PXllYXIsXSAgICMgZGF0YSBmb3IgZWFjaCB5ZWFyDQogICAgICAgIGFhMltpLCJ0bWF4bSJdPC1tZWFuKG1pZHZhbHVlMVssInRtYXgiXSxuYS5ybT1UKSAgIyBhbm51YWwgbWVhbiBvZiBUbWF4LCBUbWluDQogICAgICAgIGFhMltpLCJ0bWlubSJdPC1tZWFuKG1pZHZhbHVlMVssInRtaW4iXSxuYS5ybT1UKQ0KICAgICAgICBmb3IgKGogaW4gMToxMil7DQogICAgICAgICAgICBtaWR2YWx1ZTI8LW1pZHZhbHVlMVttaWR2YWx1ZTEkbW9udGg9PW1vbnRoLF0gICMgZGF0YSBmb3IgZWFjaCBtb250aA0KICAgICAgICAgICAgYWExWyhpLTEpKjEyK2osInRtYXhtIl08LW1lYW4obWlkdmFsdWUyWywidG1heCJdLG5hLnJtPVQpICAjIG1vbnRobHkgbWVhbiBvZiBUbWF4LCBUbWluDQogICAgICAgICAgICBhYTFbKGktMSkqMTIraiwidG1pbm0iXTwtbWVhbihtaWR2YWx1ZTJbLCJ0bWluIl0sbmEucm09VCkNCiAgICAgICAgICAgIG5hc3RbMSwieW5hcHIiLGosaV08LWRpbShtaWR2YWx1ZTFbaXMubmEobWlkdmFsdWUxJHByY3ApLF0pWzFdICAjIGFubnVhbCBtaXNzaW5nIGRheXMNCiAgICAgICAgICAgIGlmIChuYXN0WzEsInluYXByIixqLGldPjE1KSBuYXN0WzEsInluYXByPjE1IixqLGldPC1OQQ0KICAgICAgICAgICAgbmFzdFsxLCJ5bmF0bWEiLGosaV08LWRpbShtaWR2YWx1ZTFbaXMubmEobWlkdmFsdWUxJHRtYXgpLF0pWzFdDQogICAgICAgICAgICBpZiAobmFzdFsxLCJ5bmF0bWEiLGosaV0+MTUpIG5hc3RbMSwieW5hdG1hPjE1IixqLGldPC1OQQ0KICAgICAgICAgICAgbmFzdFsxLCJ5bmF0bWkiLGosaV08LWRpbShtaWR2YWx1ZTFbaXMubmEobWlkdmFsdWUxJHRtaW4pLF0pWzFdDQogICAgICAgICAgICBpZiAobmFzdFsxLCJ5bmF0bWkiLGosaV0+MTUpIG5hc3RbMSwieW5hdG1pPjE1IixqLGldPC1OQQ0KICAgICAgICAgICAgbmFzdFsxLCJuYXByIixqLGldPC1kaW0obWlkdmFsdWUyW2lzLm5hKG1pZHZhbHVlMiRwcmNwKSxdKVsxXSAgIyBtb250aGx5IG1pc3NpbmcgZGF5cw0KICAgICAgICAgICAgaWYgKG5hc3RbMSwibmFwciIsaixpXT4zKSBuYXN0WzEsIm1uYXByPjMiLGosaV08LU5BDQogICAgICAgICAgICBuYXN0WzEsIm5hdG1hIixqLGldPC1kaW0obWlkdmFsdWUyW2lzLm5hKG1pZHZhbHVlMiR0bWF4KSxdKVsxXQ0KICAgICAgICAgICAgaWYgKG5hc3RbMSwibmF0bWEiLGosaV0+MykgbmFzdFsxLCJtbmF0bWE+MyIsaixpXTwtTkENCiAgICAgICAgICAgIG5hc3RbMSwibmF0bWkiLGosaV08LWRpbShtaWR2YWx1ZTJbaXMubmEobWlkdmFsdWUyJHRtaW4pLF0pWzFdDQogICAgICAgICAgICBpZiAobmFzdFsxLCJuYXRtaSIsaixpXT4zKSBuYXN0WzEsIm1uYXRtaT4zIixqLGldPC1OQQ0KICAgICAgICAgICAgbW9udGg9bW9udGgrMSANCiAgICAgICAgfQ0KICAgICAgICB5ZWFyPXllYXIrMSAgICAgIA0KICAgIH0NCiAgICBuYXN0bzwtdChuYXN0WywsLDFdKQ0KICAgIGZvciAoIGkgaW4gMjooeWVhcmUteWVhcnMrMSkpew0KICAgICAgICBuYXN0bzwtcmJpbmQobmFzdG8sdChuYXN0WywsLGldKSkgfQ0KICAgIG5hc3RvdXQ8LW1hdHJpeCgwLCh5ZWFyZS15ZWFycysxKSoxMiwyKQ0KICAgIGRpbW5hbWVzKG5hc3RvdXQpPC1saXN0KE5VTEwsYygieWVhciIsIm1vbnRoIikpICAgICAgICAgICAgICAgIA0KICAgIG5hc3RvdXQ8LWFzLmRhdGEuZnJhbWUobmFzdG91dCkNCiAgICBuYXN0b3V0WywieWVhciJdPC15ZWFyczp5ZWFyZQ0KICAgIG5hc3RvdXRbLCJ5ZWFyIl08LW15c29ydChuYXN0b3V0WywieWVhciJdLGRlY3JlYXNpbmc9RikNCiAgICBuYXN0b3V0WywibW9udGgiXTwtMToxMg0KICAgIA0KICAgIG5hc3RvdXQ8LWNiaW5kKG5hc3RvdXQsbmFzdG8pOyAgICBhc3NpZ24oIm5hc3RvdXQiLG5hc3RvdXQsZW52aXI9Lkdsb2JhbEVudikNCiAgICBuYXN0YXRpc3RpYzwtbmFzdG91dFssMTo4XQ0KICAgIA0KICAgIG5hY29yPC1uYXN0b3V0WywtKDM6OCldDQogICAgeW5hY29yPC1tYXRyaXgoMCx5cyw0KQ0KICAgIGRpbW5hbWVzKHluYWNvcik8LWxpc3QoTlVMTCxjKCJ5ZWFyIiwieW5hcHI+MTUiLCJ5bmF0bWE+MTUiLCJ5bmF0bWk+MTUiKSkNCiAgICB5bmFjb3JbLCJ5ZWFyIl08LXllYXJzOnllYXJlDQogICAgeW5hY29yPC1hcy5kYXRhLmZyYW1lKHluYWNvcikNCiAgICBmb3IgKHllYXIgaW4geWVhcnM6eWVhcmUpew0KICAgICAgICB5bmFjb3JbeW5hY29yJHllYXI9PXllYXIsInluYXByPjE1Il08LW5hY29yW25hY29yJHllYXI9PXllYXIgJiBuYWNvciRtb250aD09MSwieW5hcHI+MTUiXQ0KICAgICAgICB5bmFjb3JbeW5hY29yJHllYXI9PXllYXIsInluYXRtYT4xNSJdPC1uYWNvcltuYWNvciR5ZWFyPT15ZWFyICYgbmFjb3IkbW9udGg9PTEsInluYXRtYT4xNSJdDQogICAgICAgIHluYWNvclt5bmFjb3IkeWVhcj09eWVhciwieW5hdG1pPjE1Il08LW5hY29yW25hY29yJHllYXI9PXllYXIgJiBuYWNvciRtb250aD09MSwieW5hdG1pPjE1Il0NCiAgICB9DQogICAgbmFjb3I8LW5hY29yWywxOjVdDQogICAgYXNzaWduKCJuYWNvciIsbmFjb3IsZW52aXI9Lkdsb2JhbEVudikNCiAgICBhc3NpZ24oInluYWNvciIseW5hY29yLGVudmlyPS5HbG9iYWxFbnYpDQogICAgaWYoc3VtKGlzLm5hKHluYWNvclssInluYXByPjE1Il0pPT1GKT09MCkgcHJhbGxuYTwtMQ0KICAgIGVsc2UgcHJhbGxuYTwtMA0KICAgIGlmKHN1bShpcy5uYSh5bmFjb3JbLCJ5bmF0bWE+MTUiXSk9PUYpPT0wKSB0eGFsbG5hPC0xDQogICAgZWxzZSB0eGFsbG5hPC0wDQogICAgaWYoc3VtKGlzLm5hKHluYWNvclssInluYXRtaT4xNSJdKT09Rik9PTApIHRuYWxsbmE8LTENCiAgICBlbHNlIHRuYWxsbmE8LTANCiAgICBhc3NpZ24oInByYWxsbmEiLHByYWxsbmEsZW52aXI9Lkdsb2JhbEVudikNCiAgICBhc3NpZ24oInR4YWxsbmEiLHR4YWxsbmEsZW52aXI9Lkdsb2JhbEVudikNCiAgICBhc3NpZ24oInRuYWxsbmEiLHRuYWxsbmEsZW52aXI9Lkdsb2JhbEVudikNCiAgICBhc3NpZ24oIm5hc3RhdGlzdGljIixuYXN0YXRpc3RpYyxlbnZpcj0uR2xvYmFsRW52KQ0KICAgIG5hbTE8LXBhc3RlKG91dGxvZ2RpcixwYXN0ZShvZmlsZW5hbWUsIl9uYXN0YXRpc3RpYy5jc3YiLHNlcD0iIiksc2VwPSIvIikgICAgICAgICAgICMgT3V0cHV0IHRoZSByZXN1bHQNCiAgICBjYXQoZmlsZT1uYW0xLCJUSVRMRSxZRUFSLEpBTixGRUIsTUFSLEFQUixNQVksSlVOLEpVTCxBVUcsU0VQLE9DVCxOT1YsREVDLEFOTlxuIikNCiAgICBmb3IoeWVhciBpbiB5ZWFyczp5ZWFyZSkNCiAgICAgICAgZm9yKGkgaW4gMTozKSB7DQogICAgICAgICAgICBpZihpPT0xKSB0aXQ8LSJQUkNQIg0KICAgICAgICAgICAgaWYoaT09MikgdGl0PC0iVE1BWCINCiAgICAgICAgICAgIGlmKGk9PTMpIHRpdDwtIlRNSU4iDQogICAgICAgICAgICBsaW5lPC1wYXN0ZSh0aXQseWVhcixzZXA9IiwiKQ0KICAgICAgICAgICAgZm9yKG1vbiBpbiAxOjEyKQ0KICAgICAgICAgICAgICAgIGxpbmU8LXBhc3RlKGxpbmUsbmFzdGF0aXN0aWNbbmFzdGF0aXN0aWMkeWVhcj09eWVhciZuYXN0YXRpc3RpYyRtb250aD09bW9uLGkrNV0sc2VwPSIsIikNCiAgICAgICAgICAgIGxpbmU8LXBhc3RlKGxpbmUsbmFzdGF0aXN0aWNbbmFzdGF0aXN0aWMkeWVhcj09eWVhciZuYXN0YXRpc3RpYyRtb250aD09MSxpKzJdLHNlcD0iLCIpDQogICAgICAgICAgICBjYXQoZmlsZT1uYW0xLGxpbmUsZmlsbD0xMDAsYXBwZW5kPVQpDQogICAgICAgIH0NCiAgICAjICAgd3JpdGUudGFibGUobmFzdGF0aXN0aWMsZmlsZT1uYW0xLGFwcGVuZD1GLHF1b3RlPUYsc2VwPSIsICIscm93Lm5hbWVzPUYpDQogICAgYWExWywidG1heG0iXTwtYWExWywidG1heG0iXStuYWNvclssIm1uYXRtYT4zIl0NCiAgICBhYTFbLCJ0bWlubSJdPC1hYTFbLCJ0bWlubSJdK25hY29yWywibW5hdG1pPjMiXQ0KICAgIGFhMlssInRtYXhtIl08LWFhMlssInRtYXhtIl0reW5hY29yWywieW5hdG1hPjE1Il0NCiAgICBhYTJbLCJ0bWlubSJdPC1hYTJbLCJ0bWlubSJdK3luYWNvclssInluYXRtaT4xNSJdDQogICAgb2ZpbGUxPC1wYXN0ZShvdXRpbmRkaXIscGFzdGUob2ZpbGVuYW1lLCJfVE1BWG1lYW4uY3N2IixzZXA9IiIpLHNlcD0iLyIpDQogICAgb2RhdGE8LW1hdHJpeCgwLHlzLDE0KQ0KICAgIGRpbW5hbWVzKG9kYXRhKTwtbGlzdChOVUxMLGMoInllYXIiLCJqYW4iLCJmZWIiLCJtYXIiLCJhcHIiLCJtYXkiLCJqdW4iLCJqdWwiLCJhdWciLCJzZXAiLCJvY3QiLCJub3YiLCJkZWMiLCJhbm51YWwiKSkNCiAgICBvZGF0YVssMV08LXllYXJzOnllYXJlDQogICAgb2RhdGFbLDE0XTwtYWEyWywidG1heG0iXQ0KICAgIGZvcihpIGluIDE6eXMpIG9kYXRhW2ksMjoxM108LWFhMVsoKGktMSkqMTIrMSk6KGkqMTIpLCJ0bWF4bSJdDQogICAgd3JpdGUudGFibGUocm91bmQob2RhdGEsMiksZmlsZT1vZmlsZTEsYXBwZW5kPUYscXVvdGU9RixzZXA9IiwgIixuYT0iLTk5LjkiLHJvdy5uYW1lcz1GKQ0KICAgIG9kYXRhWywxNF08LWFhMlssInRtaW5tIl0NCiAgICBmb3IoaSBpbiAxOnlzKSBvZGF0YVtpLDI6MTNdPC1hYTFbKChpLTEpKjEyKzEpOihpKjEyKSwidG1pbm0iXQ0KICAgIG9maWxlMTwtcGFzdGUob3V0aW5kZGlyLHBhc3RlKG9maWxlbmFtZSwiX1RNSU5tZWFuLmNzdiIsc2VwPSIiKSxzZXA9Ii8iKQ0KICAgIHdyaXRlLnRhYmxlKHJvdW5kKG9kYXRhLDIpLGZpbGU9b2ZpbGUxLGFwcGVuZD1GLHF1b3RlPUYsc2VwPSIsICIsbmE9Ii05OS45Iixyb3cubmFtZXM9RikNCiAgICBwYXJhbWV0ZXIoKQ0KfQ0KIyAtLS0tLS0tLS0tLS0tLSBuYXN0YXQgZW5kcyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0NCg0KIyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQ0KIyBnZXRmaWxlDQojIGZpcnN0IHN0ZXAgaXMgdG8gb3BlbiBhIGRhdGEgZmlsZSwgYW5kIHJlYWQgdGhlbSBpbnRvICJkZCIuDQojDQpnZXRmaWxlPC1mdW5jdGlvbigpIHsNCiAgICBuYW1lIDwtIHRjbHZhbHVlKHRrZ2V0T3BlbkZpbGUoZmlsZXR5cGVzPSJ7e1RFWFQgRmlsZXN9IHsudHh0fX0ge3tBbGwgZmlsZXN9ICp9IikpDQogICAgaWYgKG5hbWU9PSIiKSByZXR1cm4oKTsNCiAgICBkZCA8LSByZWFkLnRhYmxlKG5hbWUsaGVhZGVyPUYsY29sLm5hbWVzPWMoInllYXIiLCJtb250aCIsImRheSIsInByY3AiLCJ0bWF4IiwidG1pbiIpLGNvbENsYXNzZXM9cmVwKCJyZWFsIiw2KSkNCiAgICBuYW1hPC1zdWJzdHIobmFtZSxzdGFydD0xLHN0b3A9KG5jaGFyKG5hbWUpLTQpKQ0KICAgIG91dGRpcnRtcDwtc3Ryc3BsaXQobmFtZSwiLyIpW1sxXV0NCiAgICBpZihsZW5ndGgob3V0ZGlydG1wKTw9Mil7ICAjIGZvciBXaW5kaXdzDQogICAgICAgIG91dGluZGRpcjwtcGFzdGUoc3Ryc3BsaXQobmFtZSwiOiIpW1sxXV1bMV0sImluZGljZXMiLHNlcD0iOi8iKQ0KICAgICAgICBvdXRsb2dkaXI8LXBhc3RlKHN0cnNwbGl0KG5hbWUsIjoiKVtbMV1dWzFdLCJsb2ciLHNlcD0iOi8iKQ0KICAgICAgICBvdXRqcGdkaXI8LXBhc3RlKHN0cnNwbGl0KG5hbWUsIjoiKVtbMV1dWzFdLCJwbG90cyIsc2VwPSI6LyIpDQogICAgICAgIG91dHRyZGRpcjwtcGFzdGUoc3Ryc3BsaXQobmFtZSwiOiIpW1sxXV1bMV0sInRyZW5kIixzZXA9IjovIikNCiAgICB9DQogICAgZWxzZXsgICAgICAgICAgICAgICAgICAgIyBVbml4L0xpbnV4DQogICAgICAgIG91dGRpcjwtb3V0ZGlydG1wWzFdDQogICAgICAgIGZvcihpIGluIDI6KGxlbmd0aChvdXRkaXJ0bXApLTEpKQ0KICAgICAgICAgICAgb3V0ZGlyPC1wYXN0ZShvdXRkaXIsb3V0ZGlydG1wW2ldLHNlcD0iLyIpDQogICAgICAgIG91dGluZGRpcjwtcGFzdGUob3V0ZGlyLCJpbmRpY2VzIixzZXA9Ii8iKQ0KICAgICAgICBvdXRsb2dkaXI8LXBhc3RlKG91dGRpciwibG9nIixzZXA9Ii8iKQ0KICAgICAgICBvdXRqcGdkaXI8LXBhc3RlKG91dGRpciwicGxvdHMiLHNlcD0iLyIpDQogICAgICAgIG91dHRyZGRpcjwtcGFzdGUob3V0ZGlyLCJ0cmVuZCIsc2VwPSIvIikNCiAgICB9DQogICAgb2ZpbGVuYW1lPC1zdWJzdHIob3V0ZGlydG1wW2xlbmd0aChvdXRkaXJ0bXApXSxzdGFydD0xLHN0b3A9KG5jaGFyKG91dGRpcnRtcFtsZW5ndGgob3V0ZGlydG1wKV0pLTQpKQ0KICAgICMgY3JlYXRlIG91dHB1dCBmb2xkZXJzDQogICAgaWYoIWZpbGUuZXhpc3RzKG91dGluZGRpcikpIGRpci5jcmVhdGUob3V0aW5kZGlyKQ0KICAgIGlmKCFmaWxlLmV4aXN0cyhvdXRsb2dkaXIpKSBkaXIuY3JlYXRlKG91dGxvZ2RpcikNCiAgICBpZighZmlsZS5leGlzdHMob3V0anBnZGlyKSkgZGlyLmNyZWF0ZShvdXRqcGdkaXIpDQogICAgaWYoIWZpbGUuZXhpc3RzKG91dHRyZGRpcikpIGRpci5jcmVhdGUob3V0dHJkZGlyKQ0KICAgIA0KICAgICMgICAgIGRpbW5hbWVzKGRkKTwtbGlzdChOVUxMLGMoInllYXIiLCJtb250aCIsImRheSIsInByY3AiLCJ0bWF4IiwidG1pbiIpKQ0KICAgIGFzc2lnbigibmFtYSIsbmFtYSxlbnZpcj0uR2xvYmFsRW52KQ0KICAgIGFzc2lnbigib3V0aW5kZGlyIixvdXRpbmRkaXIsZW52aXI9Lkdsb2JhbEVudikNCiAgICBhc3NpZ24oIm91dGxvZ2RpciIsb3V0bG9nZGlyLGVudmlyPS5HbG9iYWxFbnYpDQogICAgYXNzaWduKCJvdXRqcGdkaXIiLG91dGpwZ2RpcixlbnZpcj0uR2xvYmFsRW52KQ0KICAgIGFzc2lnbigib3V0dHJkZGlyIixvdXR0cmRkaXIsZW52aXI9Lkdsb2JhbEVudikNCiAgICBhc3NpZ24oIm9maWxlbmFtZSIsb2ZpbGVuYW1lLGVudmlyPS5HbG9iYWxFbnYpDQogICAgIyBkZDwtZGRbZGQkdG1heCE9LTk5LjksXQ0KICAgICMgZGQkeWVhcjwtZGQkeWVhcis0MCAjIGp1c3QgZm9yIHRoZSB0ZXN0IGRhdGENCiAgICAjIHJlcGxhY2UgbWlzc2luZyB2YWx1ZSB3aXRoIE5BDQogICAgZGRbZGQkcHJjcDw9KC05OS4pLCJwcmNwIl08LU5BDQogICAgZGRbZGQkdG1heDw9KC05OS4pLCJ0bWF4Il08LU5BDQogICAgZGRbZGQkdG1pbjw9KC05OS4pLCJ0bWluIl08LU5BDQogICAgIyByZXBsYWNlIG1pc3NpbmcgcmVjb3Jkcw0KICAgIGRkZDwtbWF0cml4KE5BLDM2NSw2KQ0KICAgIGRkZGw8LW1hdHJpeChOQSwzNjYsNikNCiAgICBkaW1uYW1lcyhkZGQpPC1saXN0KE5VTEwsYygieWVhciIsIm1vbnRoIiwiZGF5IiwicHJjcCIsInRtYXgiLCJ0bWluIikpDQogICAgZGltbmFtZXMoZGRkbCk8LWxpc3QoTlVMTCxjKCJ5ZWFyIiwibW9udGgiLCJkYXkiLCJwcmNwIiwidG1heCIsInRtaW4iKSkNCiAgICBkZGRbMTozMSwibW9udGgiXTwtMTsgICAgIGRkZFsxOjMxLCJkYXkiXTwtYygxOjMxKTsgICAgZGRkWzMyOjU5LCJtb250aCJdPC0yOyAgICBkZGRbMzI6NTksImRheSJdPC1jKDE6MjgpDQogICAgZGRkWzYwOjkwLCJtb250aCJdPC0zOyAgICBkZGRbNjA6OTAsImRheSJdPC1jKDE6MzEpOyAgIGRkZFs5MToxMjAsIm1vbnRoIl08LTQ7ICAgZGRkWzkxOjEyMCwiZGF5Il08LWMoMTozMCkNCiAgICBkZGRbMTIxOjE1MSwibW9udGgiXTwtNTsgIGRkZFsxMjE6MTUxLCJkYXkiXTwtYygxOjMxKTsgZGRkWzE1MjoxODEsIm1vbnRoIl08LTY7ICBkZGRbMTUyOjE4MSwiZGF5Il08LWMoMTozMCkNCiAgICBkZGRbMTgyOjIxMiwibW9udGgiXTwtNzsgIGRkZFsxODI6MjEyLCJkYXkiXTwtYygxOjMxKTsgZGRkWzIxMzoyNDMsIm1vbnRoIl08LTg7ICBkZGRbMjEzOjI0MywiZGF5Il08LWMoMTozMSkNCiAgICBkZGRbMjQ0OjI3MywibW9udGgiXTwtOTsgIGRkZFsyNDQ6MjczLCJkYXkiXTwtYygxOjMwKTsgZGRkWzI3NDozMDQsIm1vbnRoIl08LTEwOyBkZGRbMjc0OjMwNCwiZGF5Il08LWMoMTozMSkNCiAgICBkZGRbMzA1OjMzNCwibW9udGgiXTwtMTE7IGRkZFszMDU6MzM0LCJkYXkiXTwtYygxOjMwKTsgZGRkWzMzNTozNjUsIm1vbnRoIl08LTEyOyBkZGRbMzM1OjM2NSwiZGF5Il08LWMoMTozMSkNCiAgICANCiAgICBkZGRsWzE6MzEsIm1vbnRoIl08LTE7ICAgICBkZGRsWzE6MzEsImRheSJdPC1jKDE6MzEpOyAgICBkZGRsWzMyOjYwLCJtb250aCJdPC0yOyAgICBkZGRsWzMyOjYwLCJkYXkiXTwtYygxOjI5KQ0KICAgIGRkZGxbNjE6OTEsIm1vbnRoIl08LTM7ICAgIGRkZGxbNjE6OTEsImRheSJdPC1jKDE6MzEpOyAgIGRkZGxbOTI6MTIxLCJtb250aCJdPC00OyAgIGRkZGxbOTI6MTIxLCJkYXkiXTwtYygxOjMwKQ0KICAgIGRkZGxbMTIyOjE1MiwibW9udGgiXTwtNTsgIGRkZGxbMTIyOjE1MiwiZGF5Il08LWMoMTozMSk7IGRkZGxbMTUzOjE4MiwibW9udGgiXTwtNjsgIGRkZGxbMTUzOjE4MiwiZGF5Il08LWMoMTozMCkNCiAgICBkZGRsWzE4MzoyMTMsIm1vbnRoIl08LTc7ICBkZGRsWzE4MzoyMTMsImRheSJdPC1jKDE6MzEpOyBkZGRsWzIxNDoyNDQsIm1vbnRoIl08LTg7ICBkZGRsWzIxNDoyNDQsImRheSJdPC1jKDE6MzEpDQogICAgZGRkbFsyNDU6Mjc0LCJtb250aCJdPC05OyAgZGRkbFsyNDU6Mjc0LCJkYXkiXTwtYygxOjMwKTsgZGRkbFsyNzU6MzA1LCJtb250aCJdPC0xMDsgZGRkbFsyNzU6MzA1LCJkYXkiXTwtYygxOjMxKQ0KICAgIGRkZGxbMzA2OjMzNSwibW9udGgiXTwtMTE7IGRkZGxbMzA2OjMzNSwiZGF5Il08LWMoMTozMCk7IGRkZGxbMzM2OjM2NiwibW9udGgiXTwtMTI7IGRkZGxbMzM2OjM2NiwiZGF5Il08LWMoMTozMSkNCiAgICANCiAgICB5ZWFyczwtZGRbMSwxXTt5ZWFyZTwtZGRbZGltKGRkKVsxXSwxXSAgICMgc3RhciBhbmQgZW5kIHllYXJzDQogICAgaWYgKGxlYXB5ZWFyKHllYXJzKSkgZGRkZDwtZGRkbCBlbHNlIGRkZGQ8LWRkZA0KICAgIGRkZGRbLCJ5ZWFyIl08LXllYXJzDQogICAgZm9yICh5ZWFyIGluIHllYXJzOnllYXJlKXsgICAgICAgICAgICAgICAgICAjIHllYXIgbG9vcCBzdGFydA0KICAgICAgICBpZiAobGVhcHllYXIoeWVhcikpIGRkZGQxPC1kZGRsIGVsc2UgZGRkZDE8LWRkZA0KICAgICAgICBkZGRkMVssInllYXIiXTwteWVhcg0KICAgICAgICBpZiAoeWVhciE9eWVhcnMpIGRkZGQ8LXJiaW5kKGRkZGQsZGRkZDEpDQogICAgfSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICMgeWVhciBsb29wIGVuZA0KICAgIA0KICAgIGRkZGQ8LWFzLmRhdGEuZnJhbWUoZGRkZCkNCiAgICBkZGRkMjwtbWVyZ2UoZGRkZCxkZCxieT1jKCJ5ZWFyIiwibW9udGgiLCJkYXkiKSxhbGwueD1UKQ0KICAgIGRkZGQyPC1kZGRkMlssLSg0OjYpXQ0KICAgIGRpbW5hbWVzKGRkZGQyKVtbMl1dPC1jKCJ5ZWFyIiwibW9udGgiLCJkYXkiLCJwcmNwIiwidG1heCIsInRtaW4iKQ0KICAgIHRtcG9yZGVyPC1kZGRkMlssInllYXIiXSoxMDAwMCtkZGRkMlssIm1vbnRoIl0qMTAwK2RkZGQyWywiZGF5Il0NCiAgICBkZDwtZGRkZDJbb3JkZXIodG1wb3JkZXIpLF0NCiAgICANCiAgICBhc3NpZ24oInllYXJzIix5ZWFycyxlbnZpcj0uR2xvYmFsRW52KQ0KICAgIGFzc2lnbigieWVhcmUiLHllYXJlLGVudmlyPS5HbG9iYWxFbnYpDQogICAgYXNzaWduKCJkZCIsZGQsZW52aXI9Lkdsb2JhbEVudikNCiAgICANCiAgICB0a21lc3NhZ2VCb3gobWVzc2FnZT1wYXN0ZSgiRGF0YSgiLG9maWxlbmFtZSwiKSBsb2FkZWQsIGNsaWNrIE9LIHRvIGNvbnRpbnVlLiIsc2VwPSIiKSkNCiAgICANCiAgICAjIGVudGVyIHN0YXRpb24gbmFtZSBhbmQgdGhlIHRpbWVzIG9mIHN0YWRhcmQgZGV2aWF0aW9uDQogICAgaW5mb3IxPC10a3RvcGxldmVsKCkNCiAgICB0a2ZvY3VzKGluZm9yMSkNCiAgICB0a2dyYWIuc2V0KGluZm9yMSkNCiAgICB0a3dtLnRpdGxlKGluZm9yMSwiU2V0IFBhcmFtZXRlcnMgZm9yIERhdGEgUUMiKQ0KICAgIA0KICAgIHRleHRFbnRyeTE8LXN0YXRpb25zOyAgICAgICAgdGV4dEVudHJ5Mjwtc3RkdA0KICAgIA0KICAgIHRleHRFbnRyeVdpZGdldDE8LXRrZW50cnkoaW5mb3IxLHdpZHRoPTMwLHRleHR2YXJpYWJsZT10ZXh0RW50cnkxKQ0KICAgIHRleHRFbnRyeVdpZGdldDI8LXRrZW50cnkoaW5mb3IxLHdpZHRoPTMwLHRleHR2YXJpYWJsZT10ZXh0RW50cnkyKQ0KICAgIA0KICAgICMgICAgIHRrZ3JpZCh0a2xhYmVsKGluZm9yMSx0ZXh0PSIhIUVudGVyIHBhcmFtZXRlcnMgcGxlYXNlIixmb250PWZvbnRIZWFkaW5nMSkpDQogICAgdGtncmlkKHRrbGFiZWwoaW5mb3IxLHRleHQ9IiAgICAgICAgICAgICAgICAgIFN0YXRpb24gbmFtZSBvciBjb2RlOiIpLHRleHRFbnRyeVdpZGdldDEpDQogICAgdGtncmlkKHRrbGFiZWwoaW5mb3IxLHRleHQ9IkNyaXRlcmlhKG51bWJlciBvZiBTdGFuZGFyZCBEZXZpYXRpb24pOiIpLHRleHRFbnRyeVdpZGdldDIpDQogICAgDQogICAgb2sxPC1mdW5jdGlvbigpew0KICAgICAgICBzdGF0aW9uPC1hcy5jaGFyYWN0ZXIodGNsdmFsdWUodGV4dEVudHJ5MSkpOyAgICBhc3NpZ24oInN0YXRpb24iLHN0YXRpb24sZW52aXI9Lkdsb2JhbEVudikNCiAgICAgICAgY3J0PC1hcy5udW1lcmljKHRjbHZhbHVlKHRleHRFbnRyeTIpKTsgICAgICAgICAgYXNzaWduKCJjcnQiLGNydCxlbnZpcj0uR2xvYmFsRW52KQ0KICAgICAgICB0a2dyYWIucmVsZWFzZShpbmZvcjEpDQogICAgICAgIHRrZGVzdHJveShpbmZvcjEpDQogICAgICAgIHN0YXRpb25zPC10ZXh0RW50cnkxOyAgICAgIGFzc2lnbigic3RhdGlvbnMiLHN0YXRpb25zLGVudmlyPS5HbG9iYWxFbnYpDQogICAgICAgIHN0ZHQ8LXRleHRFbnRyeTI7ICAgICAgICAgIGFzc2lnbigic3RkdCIsc3RkdCxlbnZpcj0uR2xvYmFsRW52KQ0KICAgICAgICBxY29udHJvbCgpOyAgICAgICAgICAgICAgICB0a2ZvY3VzKHN0YXJ0MSkNCiAgICB9IyBlbmQgb2Ygb2sNCiAgICANCiAgICBjYW5jZWwxPC1mdW5jdGlvbigpew0KICAgICAgICB0a21lc3NhZ2VCb3gobWVzc2FnZT0iWW91IGhhdmUgdG8gZW50ZXIgdGhlc2UgcGFyYW1ldGVycyBiZWZvcmUgeW91IGNhbiBtb3ZlIG9uLiIpDQogICAgICAgIHRrZm9jdXMoaW5mb3IxKX0jIGVuZCBvZiBjYW5jZWwxDQogICAgDQogICAgb2sxLmJ1dDwtICAgIHRrYnV0dG9uKGluZm9yMSx0ZXh0PSIgICAgT0sgICAgIixjb21tYW5kPW9rMSkNCiAgICBjYW5jZWwxLmJ1dDwtdGtidXR0b24oaW5mb3IxLHRleHQ9IiAgQ0FOQ0VMICAiLGNvbW1hbmQ9Y2FuY2VsMSkNCiAgICB0a2dyaWQob2sxLmJ1dCxjYW5jZWwxLmJ1dCkNCiAgICANCn0NCiMgZW5kIG9mIGdldGZpbGUNCiMtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0NCg0KIyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQ0KIyBwYXJhbWV0ZXINCiMNCnBhcmFtZXRlcjwtZnVuY3Rpb24oKXsNCiAgICBpbmZvcjwtdGt0b3BsZXZlbCgpDQogICAgdGtmb2N1cyhpbmZvcikNCiAgICB0a2dyYWIuc2V0KGluZm9yKQ0KICAgIHRrd20udGl0bGUoaW5mb3IsIlNldCBQYXJhbWV0ZXIgVmFsdWVzIikNCiAgICANCiAgICB0ZXh0RW50cnkxPC1FbnRyeTENCiAgICB0ZXh0RW50cnkyPC1FbnRyeTINCiAgICAjICAgICB0ZXh0RW50cnkzPC1FbnRyeTMNCiAgICB0ZXh0RW50cnk0PC1FbnRyeTQNCiAgICB0ZXh0RW50cnk1PC1FbnRyeTUNCiAgICB0ZXh0RW50cnk2PC1FbnRyeTY7dGV4dEVudHJ5NzwtRW50cnk3DQogICAgdGV4dEVudHJ5ODwtRW50cnk4O3RleHRFbnRyeTk8LUVudHJ5OQ0KICAgICMgICAgIHRleHRFbnRyeTEwPC1FbnRyeTEwO3RleHRFbnRyeTExPC1FbnRyeTExDQogICAgdGV4dEVudHJ5MTI8LUVudHJ5MTINCiAgICANCiAgICB0ZXh0RW50cnlXaWRnZXQxPC10a2VudHJ5KGluZm9yLHdpZHRoPTIwLHRleHR2YXJpYWJsZT10ZXh0RW50cnkxKQ0KICAgIHRleHRFbnRyeVdpZGdldDI8LXRrZW50cnkoaW5mb3Isd2lkdGg9MjAsdGV4dHZhcmlhYmxlPXRleHRFbnRyeTIpDQogICAgIyAgICAgdGV4dEVudHJ5V2lkZ2V0MzwtdGtlbnRyeShpbmZvcix3aWR0aD0yMCx0ZXh0dmFyaWFibGU9dGV4dEVudHJ5MykNCiAgICB0ZXh0RW50cnlXaWRnZXQ0PC10a2VudHJ5KGluZm9yLHdpZHRoPTIwLHRleHR2YXJpYWJsZT10ZXh0RW50cnk0KQ0KICAgIHRleHRFbnRyeVdpZGdldDU8LXRrZW50cnkoaW5mb3Isd2lkdGg9MjAsdGV4dHZhcmlhYmxlPXRleHRFbnRyeTUpDQogICAgdGV4dEVudHJ5V2lkZ2V0NjwtdGtlbnRyeShpbmZvcix3aWR0aD0yMCx0ZXh0dmFyaWFibGU9dGV4dEVudHJ5NikNCiAgICB0ZXh0RW50cnlXaWRnZXQ3PC10a2VudHJ5KGluZm9yLHdpZHRoPTIwLHRleHR2YXJpYWJsZT10ZXh0RW50cnk3KQ0KICAgIHRleHRFbnRyeVdpZGdldDg8LXRrZW50cnkoaW5mb3Isd2lkdGg9MjAsdGV4dHZhcmlhYmxlPXRleHRFbnRyeTgpDQogICAgdGV4dEVudHJ5V2lkZ2V0OTwtdGtlbnRyeShpbmZvcix3aWR0aD0yMCx0ZXh0dmFyaWFibGU9dGV4dEVudHJ5OSkNCiAgICAjICAgICB0ZXh0RW50cnlXaWRnZXQxMDwtdGtlbnRyeShpbmZvcix3aWR0aD0yMCx0ZXh0dmFyaWFibGU9dGV4dEVudHJ5MTApDQogICAgIyAgICAgdGV4dEVudHJ5V2lkZ2V0MTE8LXRrZW50cnkoaW5mb3Isd2lkdGg9MjAsdGV4dHZhcmlhYmxlPXRleHRFbnRyeTExKQ0KICAgIHRleHRFbnRyeVdpZGdldDEyPC10a2VudHJ5KGluZm9yLHdpZHRoPTIwLHRleHR2YXJpYWJsZT10ZXh0RW50cnkxMikNCiAgICANCiAgICB0a2dyaWQodGtsYWJlbChpbmZvcix0ZXh0PSJVc2VyIGRlZmluZWQgcGFyYW1ldGVycyBmb3IgSW5kaWNlcyBDYWxjdWxhdGlvbiIsZm9udD1mb250SGVhZGluZzEpKQ0KICAgIHRrZ3JpZCh0a2xhYmVsKGluZm9yLHRleHQ9IkZpcnN0IHllYXIgb2YgYmFzZSBwZXJpb2QiKSx0ZXh0RW50cnlXaWRnZXQxKQ0KICAgIHRrZ3JpZCh0a2xhYmVsKGluZm9yLHRleHQ9Ikxhc3QgeWVhciBvZiBiYXNlIHBlcmlvZCIpLHRleHRFbnRyeVdpZGdldDIpDQogICAgdGtncmlkKHRrbGFiZWwoaW5mb3IsdGV4dD0iTGF0aXR1ZGUgb2YgdGhpcyBzdGF0aW9uIGxvY2F0aW9uIiksdGV4dEVudHJ5V2lkZ2V0NCkNCiAgICB0a2dyaWQodGtsYWJlbChpbmZvcix0ZXh0PSJMb25naXR1ZGUgb2YgdGhpcyBzdGF0aW9uIGxvY2F0aW9uIiksdGV4dEVudHJ5V2lkZ2V0NSkNCiAgICB0a2dyaWQodGtsYWJlbChpbmZvcix0ZXh0PSJVc2VyIGRlZmluZWQgdXBwZXIgdGhyZXNob2xkIG9mIGRhaWx5IG1heGltdW0gdGVtcGVyYXR1cmUiKSx0ZXh0RW50cnlXaWRnZXQ2KQ0KICAgIHRrZ3JpZCh0a2xhYmVsKGluZm9yLHRleHQ9IlVzZXIgZGVmaW5lZCBsb3dlciB0aHJlc2hvbGQgb2YgZGFpbHkgbWF4aW11bSB0ZW1wZXJhdHVyZSIpLHRleHRFbnRyeVdpZGdldDcpDQogICAgdGtncmlkKHRrbGFiZWwoaW5mb3IsdGV4dD0iVXNlciBkZWZpbmVkIHVwcGVyIHRocmVzaG9sZCBvZiBkYWlseSBtaW5pbXVtIHRlbXBlcmF0dXJlIiksdGV4dEVudHJ5V2lkZ2V0OCkNCiAgICB0a2dyaWQodGtsYWJlbChpbmZvcix0ZXh0PSJVc2VyIGRlZmluZWQgbG93ZXIgdGhyZXNob2xkIG9mIGRhaWx5IG1pbmltdW0gdGVtcGVyYXR1cmUiKSx0ZXh0RW50cnlXaWRnZXQ5KQ0KICAgIHRrZ3JpZCh0a2xhYmVsKGluZm9yLHRleHQ9IlVzZXIgZGVmaW5lZCBkYWlseSBwcmVjaXBpdGF0aW9uIHRocmVzaG9sZCIpLHRleHRFbnRyeVdpZGdldDEyKQ0KICAgIA0KICAgICMtLS0tLS0tLS0tLSBPSzEgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0gICAgDQogICAgb2sxPC1mdW5jdGlvbigpew0KICAgICAgICAjICAgICAgIHRrbWVzc2FnZUJveChtZXNzYWdlPSJUaGlzIHByb2Nlc3MgbWF5IHRha2UgMiBtaW5zIHRvIGluaXRpYWxpemUgdGhlIGRhdGEuIFBsZWFzZSB3YWl0IHVudGlsIHRoZSB3aW5kb3cgZGlzYXBlYXIhIikNCiAgICAgICAgc3RhcnR5ZWFyPC1hcy5udW1lcmljKHRjbHZhbHVlKHRleHRFbnRyeTEpKTsgIGFzc2lnbigic3RhcnR5ZWFyIixzdGFydHllYXIsZW52aXI9Lkdsb2JhbEVudikNCiAgICAgICAgZW5keWVhcjwtYXMubnVtZXJpYyh0Y2x2YWx1ZSh0ZXh0RW50cnkyKSk7ICAgIGFzc2lnbigiZW5keWVhciIsZW5keWVhcixlbnZpcj0uR2xvYmFsRW52KQ0KICAgICAgICBpZihzdGFydHllYXI8eWVhcnN8ZW5keWVhcj55ZWFyZSl7DQogICAgICAgICAgICBpZihzdGFydHllYXI8eWVhcnMpIG1zZzwtcGFzdGUoIklucHV0IGJhc2UgcGVyaW9kIHN0YXJ0OiIsIHN0YXJ0eWVhciwiIGxlc3MgdGhlbiBzdGFydCB5ZWFyIG9mIGRhdGE6IiwgeWVhcnMsIHNlcD0iICIpDQogICAgICAgICAgICBlbHNlIG1zZzwtcGFzdGUoIklucHV0IGJhc2UgcGVyaW9kIGVuZDoiLCBlbmR5ZWFyLCIgZ3JlYXRlciB0aGVuIGVuZCB5ZWFyIG9mIGRhdGE6IiwgeWVhcmUsIHNlcD0iICIpDQogICAgICAgICAgICB0a21lc3NhZ2VCb3gobWVzc2FnZT1tc2cpDQogICAgICAgICAgICB0a2ZvY3VzKGluZm9yKQ0KICAgICAgICAgICAgcmV0dXJuKCkNCiAgICAgICAgfQ0KICAgICAgICAjICAgICAgIHdpbnNpemU8LWFzLm51bWVyaWModGNsdmFsdWUodGV4dEVudHJ5MykpOyAgIGFzc2lnbigid2luc2l6ZSIsd2luc2l6ZSxlbnZpcj0uR2xvYmFsRW52KQ0KICAgICAgICBsYXRpdHVkZTwtYXMubnVtZXJpYyh0Y2x2YWx1ZSh0ZXh0RW50cnk0KSk7ICAgYXNzaWduKCJsYXRpdHVkZSIsbGF0aXR1ZGUsZW52aXI9Lkdsb2JhbEVudikNCiAgICAgICAgbG9uZ2l0dWRlPC1hcy5udW1lcmljKHRjbHZhbHVlKHRleHRFbnRyeTUpKTsgIGFzc2lnbigibG9uZ2l0dWRlIixsb25naXR1ZGUsZW52aXI9Lkdsb2JhbEVudikNCiAgICAgICAgIyAgICAgICB0aHJlc2hvbGQ8LWFzLm51bWVyaWModGNsdmFsdWUodGV4dEVudHJ5NSkpOyBhc3NpZ24oInRocmVzaG9sZCIsdGhyZXNob2xkLGVudmlyPS5HbG9iYWxFbnYpDQogICAgICAgIHV1dTwtYXMubnVtZXJpYyh0Y2x2YWx1ZSh0ZXh0RW50cnk2KSk7ICAgICAgICBhc3NpZ24oInV1dSIsdXV1LGVudmlyPS5HbG9iYWxFbnYpDQogICAgICAgIHVsdTwtYXMubnVtZXJpYyh0Y2x2YWx1ZSh0ZXh0RW50cnk3KSk7ICAgICAgICBhc3NpZ24oInV1bCIsdWx1LGVudmlyPS5HbG9iYWxFbnYpDQogICAgICAgIHV1bDwtYXMubnVtZXJpYyh0Y2x2YWx1ZSh0ZXh0RW50cnk4KSk7ICAgICAgICBhc3NpZ24oInVsdSIsdXVsLGVudmlyPS5HbG9iYWxFbnYpDQogICAgICAgIHVsbDwtYXMubnVtZXJpYyh0Y2x2YWx1ZSh0ZXh0RW50cnk5KSk7ICAgICAgICBhc3NpZ24oInVsbCIsdWxsLGVudmlyPS5HbG9iYWxFbnYpDQogICAgICAgICMgICAgICAgdXA8LWFzLm51bWVyaWModGNsdmFsdWUodGV4dEVudHJ5MTApKTsgICAgICAgYXNzaWduKCJ1cCIsdXAsZW52aXI9Lkdsb2JhbEVudikNCiAgICAgICAgIyAgICAgICBscDwtYXMubnVtZXJpYyh0Y2x2YWx1ZSh0ZXh0RW50cnkxMSkpOyAgICAgICBhc3NpZ24oImxwIixscCxlbnZpcj0uR2xvYmFsRW52KQ0KICAgICAgICBubjwtYXMubnVtZXJpYyh0Y2x2YWx1ZSh0ZXh0RW50cnkxMikpOyAgICAgICAgYXNzaWduKCJubiIsbm4sZW52aXI9Lkdsb2JhbEVudikNCiAgICAgICAgc3RhcnRwb2ludDwtc3RhcnR5ZWFyLTE7ICAgYXNzaWduKCJzdGFydHBvaW50IixzdGFydHBvaW50LGVudmlyPS5HbG9iYWxFbnYpDQogICAgICAgIGVuZHBvaW50PC1lbmR5ZWFyKzE7ICAgICAgIGFzc2lnbigiZW5kcG9pbnQiLGVuZHBvaW50LGVudmlyPS5HbG9iYWxFbnYpDQogICAgICAgIG5vcmRheXRlbTEoKQ0KICAgICAgICB0a2dyYWIucmVsZWFzZShpbmZvcikNCiAgICAgICAgdGtkZXN0cm95KGluZm9yKQ0KICAgICAgICBFbnRyeTE8LXRleHRFbnRyeTE7ICAgYXNzaWduKCJFbnRyeTEiLEVudHJ5MSxlbnZpcj0uR2xvYmFsRW52KQ0KICAgICAgICBFbnRyeTI8LXRleHRFbnRyeTI7ICAgYXNzaWduKCJFbnRyeTIiLEVudHJ5MixlbnZpcj0uR2xvYmFsRW52KQ0KICAgICAgICAjICAgICAgIEVudHJ5MzwtdGV4dEVudHJ5MzsgIGFzc2lnbigiRW50cnkzIixFbnRyeTMsZW52aXI9Lkdsb2JhbEVudikNCiAgICAgICAgRW50cnk0PC10ZXh0RW50cnk0OyAgIGFzc2lnbigiRW50cnk0IixFbnRyeTQsZW52aXI9Lkdsb2JhbEVudikNCiAgICAgICAgRW50cnk1PC10ZXh0RW50cnk1OyAgIGFzc2lnbigiRW50cnk1IixFbnRyeTUsZW52aXI9Lkdsb2JhbEVudikNCiAgICAgICAgRW50cnk2PC10ZXh0RW50cnk2OyAgIGFzc2lnbigiRW50cnk2IixFbnRyeTYsZW52aXI9Lkdsb2JhbEVudikNCiAgICAgICAgRW50cnk3PC10ZXh0RW50cnk3OyAgIGFzc2lnbigiRW50cnk3IixFbnRyeTcsZW52aXI9Lkdsb2JhbEVudikNCiAgICAgICAgRW50cnk4PC10ZXh0RW50cnk4OyAgIGFzc2lnbigiRW50cnk4IixFbnRyeTgsZW52aXI9Lkdsb2JhbEVudikNCiAgICAgICAgRW50cnk5PC10ZXh0RW50cnk5OyAgIGFzc2lnbigiRW50cnk5IixFbnRyeTksZW52aXI9Lkdsb2JhbEVudikNCiAgICAgICAgIyAgICAgICBFbnRyeTEwPC10ZXh0RW50cnkxMDsgYXNzaWduKCJFbnRyeTEwIixFbnRyeTEwLGVudmlyPS5HbG9iYWxFbnYpDQogICAgICAgICMgICAgICAgRW50cnkxMTwtdGV4dEVudHJ5MTE7IGFzc2lnbigiRW50cnkxMSIsRW50cnkxMSxlbnZpcj0uR2xvYmFsRW52KQ0KICAgICAgICBFbnRyeTEyPC10ZXh0RW50cnkxMjsgIGFzc2lnbigiRW50cnkxMiIsRW50cnkxMixlbnZpcj0uR2xvYmFsRW52KQ0KICAgICAgICBtYWluMSgpDQogICAgfQ0KICAgICMtLS0tLS0tLS0tLSBPSzEgZW5kcyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSAgDQogICAgDQogICAgIy0tLS0tLS0tLS0tIGNhbmNlbDEgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0gIA0KICAgIGNhbmNlbDE8LWZ1bmN0aW9uKCl7DQogICAgICAgICMgICAgICAgdGttZXNzYWdlQm94KG1lc3NhZ2U9IlBsZWFzZSBlbnRlciB0aGVzZSBwYXJhbWV0ZXJzIGJlZm9yZSB5b3UgY2FuIG1vdmUgZm9yd2FyZCEhIikNCiAgICAgICAgIyAgICAgICB0a2ZvY3VzKGluZm9yKQ0KICAgICAgICB0a2Rlc3Ryb3koaW5mb3IpDQogICAgICAgICMgICAgICAgdGtkZXN0cm95KG1haW4pDQogICAgICAgICMgICAgICAgdGtmb2N1cyhzdGFydDEpDQogICAgICAgIHJldHVybigpDQogICAgfQ0KICAgICMtLS0tLS0tLS0tLSBjYW5jZWwxIGVuZHMgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0gIA0KICAgIA0KICAgIG9rMS5idXQ8LSAgICB0a2J1dHRvbihpbmZvcix0ZXh0PSIgICAgT0sgICAgIixjb21tYW5kPW9rMSkNCiAgICBjYW5jZWwxLmJ1dDwtdGtidXR0b24oaW5mb3IsdGV4dD0iICBDQU5DRUwgICIsY29tbWFuZD1jYW5jZWwxKQ0KICAgIHRrZ3JpZChvazEuYnV0LGNhbmNlbDEuYnV0KQ0KfQ0KIy0tLS0tLS0tLS0tIHBhcmFtZXRlciBlbmRzIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tICANCiMgRW5kIG9mIFBhcnQgSSAoZ2VuZXJhbCBmdW5jdGlvbnMgJiBUQ0wvVEsgZnVuY3Rpb25zDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBQYXJ0IElJDQojIEZ1bmN0aW9ucyBvZiBjYWxjdWxhdGluZyBjbGltYXRlIGluZGVjaWVzDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojLS0tLS0tLS0tLS0gaHdmaSAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSAgDQpod2ZpPC1mdW5jdGlvbigpew0KICAgIGlmIChmbGFnPT1UKSByZXR1cm4oKQ0KICAgIGh3Zmk8LW1hdHJpeCgwLCh5ZWFyZS15ZWFycysxKSwyKQ0KICAgIGRpbW5hbWVzKGh3ZmkpW1syXV08LWMoInllYXIiLCJ3c2RpIikNCiAgICBod2ZpWywieWVhciJdPC15ZWFyczp5ZWFyZQ0KICAgIGZvciAoeWVhciBpbiB5ZWFyczp5ZWFyZSkgew0KICAgICAgICBpZihsZWFweWVhcih5ZWFyKSl7DQogICAgICAgICAgICBhYTwtcmVwKDAsMzY2KQ0KICAgICAgICAgICAgYWFbMTo1OV08LWFhc1ssInBjbWF4OTAiXVsxOjU5XQ0KICAgICAgICAgICAgYWFbNjBdPC1hYVs1OV0NCiAgICAgICAgICAgIGFhWzYxOjM2Nl08LWFhc1ssInBjbWF4OTAiXVs2MDozNjVdDQogICAgICAgIH0NCiAgICAgICAgZWxzZSBhYTwtYWFzWywicGNtYXg5MCJdDQogICAgICAgIGJiPC1kZFtkZCR5ZWFyPT15ZWFyLCJ0bWF4Il0NCiAgICAgICAgaWYobGVuZ3RoKGFhKSE9bGVuZ3RoKGJiKSkgc3RvcCgiRVJST1IgaW4gV1NESSwgY2hlY2sgZGF0YSEiKQ0KICAgICAgICBtaWR2YWw8LWJiLWFhDQogICAgICAgIHlsZW48LWxlbmd0aChhYSkNCiAgICAgICAgeWNudDwtMA0KICAgICAgICBpY250PC0wDQogICAgICAgIGZvcihpIGluIDE6eWxlbil7DQogICAgICAgICAgICBpZihpcy5uYShtaWR2YWxbaV0pPT1GJm1pZHZhbFtpXT4wKQ0KICAgICAgICAgICAgICAgIGljbnQ8LWljbnQrMQ0KICAgICAgICAgICAgZWxzZXsNCiAgICAgICAgICAgICAgICBpZihpY250Pj02KSB5Y250PC15Y250K2ljbnQNCiAgICAgICAgICAgICAgICBpY250PC0wDQogICAgICAgICAgICB9DQogICAgICAgICAgICBpZihpPT15bGVuJmljbnQ+PTYpIHljbnQ8LXljbnQraWNudA0KICAgICAgICB9DQogICAgICAgIGh3ZmlbeWVhci15ZWFycysxLDJdPC15Y250DQogICAgfQ0KICAgIGh3Zmk8LWFzLmRhdGEuZnJhbWUoaHdmaSkNCiAgICBod2ZpWywid3NkaSJdPC1od2ZpWywid3NkaSJdK3luYWNvclssInluYXRtYT4xNSJdICANCiAgICBuYW0xPC1wYXN0ZShvdXRpbmRkaXIscGFzdGUob2ZpbGVuYW1lLCJfV1NESS5jc3YiLHNlcD0iIiksc2VwPSIvIikNCiAgICB3cml0ZS50YWJsZShod2ZpLGZpbGU9bmFtMSxhcHBlbmQ9RixxdW90ZT1GLHNlcD0iLCAiLG5hPSItOTkuOSIscm93Lm5hbWVzPUYpDQogICAgDQogICAgbmFtdDwtcGFzdGUob3V0dHJkZGlyLHBhc3RlKG9maWxlbmFtZSwiX3RyZW5kLmNzdiIsc2VwPSIiKSxzZXA9Ii8iKQ0KICAgIGlmKHN1bShpcy5uYShod2ZpWywid3NkaSJdKSk+PSh5ZWFyZS15ZWFycysxLTEwKSl7DQogICAgICAgIGJldGFoYXQ8LU5BDQogICAgICAgIGJldGFzdGQ8LU5BDQogICAgICAgIHB2YWx1ZTwtTkENCiAgICB9DQogICAgZWxzZXsNCiAgICAgICAgZml0MTwtbHNmaXQoaHdmaVssInllYXIiXSxod2ZpWywid3NkaSJdKQ0KICAgICAgICBvdXQxPC1scy5wcmludChmaXQxLHByaW50Lml0PUYpDQogICAgICAgIHB2YWx1ZTwtcm91bmQoYXMubnVtZXJpYyhvdXQxJHN1bW1hcnlbMSw2XSksMykNCiAgICAgICAgYmV0YWhhdDwtcm91bmQoYXMubnVtZXJpYyhvdXQxJGNvZWYudGFibGVbWzFdXVsyLDFdKSwzKQ0KICAgICAgICBiZXRhc3RkPC1yb3VuZChhcy5udW1lcmljKG91dDEkY29lZi50YWJsZVtbMV1dWzIsMl0pLDMpDQogICAgfQ0KICAgIGNhdChmaWxlPW5hbXQscGFzdGUobGF0aXR1ZGUsbG9uZ2l0dWRlLCJ3c2RpIix5ZWFycyx5ZWFyZSxiZXRhaGF0LGJldGFzdGQscHZhbHVlLHNlcD0iLCIpLGZpbGw9MTgwLGFwcGVuZD1UKQ0KICAgIA0KICAgIG5hbTI8LXBhc3RlKG91dGpwZ2RpcixwYXN0ZShvZmlsZW5hbWUsIl9XU0RJLmpwZyIsc2VwPSIiKSxzZXA9Ii8iKQ0KICAgIGpwZWcobmFtMix3aWR0aD0xMDI0LGhlaWdodD03NjgpDQogICAgcGxvdHgoaHdmaVssMV0saHdmaVssMl0sIG1haW49cGFzdGUoIldTREkiLG9maWxlbmFtZSxzZXA9IiAgICIpLHlsYWI9IldTREkiLHhsYWI9IlllYXIiKQ0KICAgIGRldi5vZmYoKQ0KfSANCiMgLS0tLS0tLS0tLS0tIGh3ZmkgZW5kcyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0NCg0KIyAtLS0tLS0tLS0tLS0tIGN3ZGkgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQ0KY3dkaTwtZnVuY3Rpb24oKXsNCiAgICBpZiAoZmxhZz09VCkgcmV0dXJuKCkNCiAgICBjd2RpPC1tYXRyaXgoMCwoeWVhcmUteWVhcnMrMSksMikNCiAgICBkaW1uYW1lcyhjd2RpKVtbMl1dPC1jKCJ5ZWFyIiwiY3NkaSIpDQogICAgY3dkaVssInllYXIiXTwteWVhcnM6eWVhcmUNCiAgICBmb3IgKHllYXIgaW4geWVhcnM6eWVhcmUpIHsNCiAgICAgICAgaWYobGVhcHllYXIoeWVhcikpew0KICAgICAgICAgICAgYWE8LXJlcCgwLDM2NikNCiAgICAgICAgICAgIGFhWzE6NTldPC1hYXNbLCJwY21pbjEwIl1bMTo1OV0NCiAgICAgICAgICAgIGFhWzYwXTwtYWFbNTldDQogICAgICAgICAgICBhYVs2MTozNjZdPC1hYXNbLCJwY21pbjEwIl1bNjA6MzY1XQ0KICAgICAgICB9DQogICAgICAgIGVsc2UgYWE8LWFhc1ssInBjbWluMTAiXQ0KICAgICAgICBiYjwtZGRbZGQkeWVhcj09eWVhciwidG1pbiJdDQogICAgICAgIGlmKGxlbmd0aChhYSkhPWxlbmd0aChiYikpIHN0b3AoIkVSUk9SIGluIENXREksIGNoZWNrIGRhdGEhIikNCiAgICAgICAgbWlkdmFsPC1hYS1iYg0KICAgICAgICB5bGVuPC1sZW5ndGgoYWEpDQogICAgICAgIHljbnQ8LTANCiAgICAgICAgaWNudDwtMA0KICAgICAgICBmb3IoaSBpbiAxOnlsZW4pew0KICAgICAgICAgICAgaWYoaXMubmEobWlkdmFsW2ldKT09RiZtaWR2YWxbaV0+MCkNCiAgICAgICAgICAgICAgICBpY250PC1pY250KzENCiAgICAgICAgICAgIGVsc2V7DQogICAgICAgICAgICAgICAgaWYoaWNudD49NikgeWNudDwteWNudCtpY250DQogICAgICAgICAgICAgICAgaWNudDwtMA0KICAgICAgICAgICAgfQ0KICAgICAgICAgICAgaWYoaT09eWxlbiZpY250Pj02KSB5Y250PC15Y250K2ljbnQNCiAgICAgICAgfQ0KICAgICAgICBjd2RpW3llYXIteWVhcnMrMSwyXTwteWNudA0KICAgIH0NCiAgICBjd2RpPC1hcy5kYXRhLmZyYW1lKGN3ZGkpDQogICAgY3dkaVssImNzZGkiXTwtY3dkaVssImNzZGkiXSt5bmFjb3JbLCJ5bmF0bWk+MTUiXSAgDQogICAgbmFtMTwtcGFzdGUob3V0aW5kZGlyLHBhc3RlKG9maWxlbmFtZSwiX0NTREkuY3N2IixzZXA9IiIpLHNlcD0iLyIpDQogICAgd3JpdGUudGFibGUoY3dkaSxmaWxlPW5hbTEsYXBwZW5kPUYscXVvdGU9RixzZXA9IiwgIixuYT0iLTk5LjkiLHJvdy5uYW1lcz1GKQ0KICAgIA0KICAgIG5hbXQ8LXBhc3RlKG91dHRyZGRpcixwYXN0ZShvZmlsZW5hbWUsIl90cmVuZC5jc3YiLHNlcD0iIiksc2VwPSIvIikNCiAgICBpZihzdW0oaXMubmEoY3dkaVssImNzZGkiXSkpPj0oeWVhcmUteWVhcnMrMS0xMCkpew0KICAgICAgICBiZXRhaGF0PC1OQQ0KICAgICAgICBiZXRhc3RkPC1OQQ0KICAgICAgICBwdmFsdWU8LU5BDQogICAgfQ0KICAgIGVsc2V7DQogICAgICAgIGZpdDE8LWxzZml0KGN3ZGlbLCJ5ZWFyIl0sY3dkaVssImNzZGkiXSkNCiAgICAgICAgb3V0MTwtbHMucHJpbnQoZml0MSxwcmludC5pdD1GKQ0KICAgICAgICBwdmFsdWU8LXJvdW5kKGFzLm51bWVyaWMob3V0MSRzdW1tYXJ5WzEsNl0pLDMpDQogICAgICAgIGJldGFoYXQ8LXJvdW5kKGFzLm51bWVyaWMob3V0MSRjb2VmLnRhYmxlW1sxXV1bMiwxXSksMykNCiAgICAgICAgYmV0YXN0ZDwtcm91bmQoYXMubnVtZXJpYyhvdXQxJGNvZWYudGFibGVbWzFdXVsyLDJdKSwzKQ0KICAgIH0NCiAgICBjYXQoZmlsZT1uYW10LHBhc3RlKGxhdGl0dWRlLGxvbmdpdHVkZSwiY3NkaSIseWVhcnMseWVhcmUsYmV0YWhhdCxiZXRhc3RkLHB2YWx1ZSxzZXA9IiwiKSxmaWxsPTE4MCxhcHBlbmQ9VCkNCiAgICANCiAgICBuYW0yPC1wYXN0ZShvdXRqcGdkaXIscGFzdGUob2ZpbGVuYW1lLCJfQ1NESS5qcGciLHNlcD0iIiksc2VwPSIvIikNCiAgICBqcGVnKG5hbTIsd2lkdGg9MTAyNCxoZWlnaHQ9NzY4KQ0KICAgIHBsb3R4KGN3ZGlbLDFdLGN3ZGlbLDJdLG1haW49cGFzdGUoIkNTREkiLG9maWxlbmFtZSxzZXA9IiAgICIpLHlsYWI9IkNTREkiLHhsYWI9IlllYXIiKQ0KICAgIGRldi5vZmYoKQ0KfSANCiMgLS0tLS0tLS0tLS0tLS0tLS0gY3dkaSBlbmRzIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0NCg0KIy0tLS0tLS0tLS0tIHI5NXB0b3QgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0NCnI5NXB0b3Q8LWZ1bmN0aW9uKCl7DQogICAgcHJjcHRtcDwtZGRbZGQkeWVhcj49c3RhcnR5ZWFyJmRkJHllYXI8PWVuZHllYXImZGQkcHJjcD49MSwicHJjcCJdDQogICAgcHJjcHRtcDwtcHJjcHRtcFtpcy5uYShwcmNwdG1wKT09Rl0NCiAgICBsZW48LWxlbmd0aChwcmNwdG1wKQ0KICAgIHByY3A5NTwtcGVyY2VudGlsZShsZW4scHJjcHRtcCwwLjk1KQ0KICAgIHByY3A5OTwtcGVyY2VudGlsZShsZW4scHJjcHRtcCwwLjk5KQ0KICAgIA0KICAgIHlzPC15ZWFyZS15ZWFycysxDQogICAgDQogICAgZHA8LW1hdHJpeCgwLHlzLDQpDQogICAgZGltbmFtZXMoZHApPC1saXN0KE5VTEwsYygieWVhciIsInI5NXAiLCJyOTlwIiwicHJjcHRvdCIpKQ0KICAgIGRwWywieWVhciJdPC15ZWFyczp5ZWFyZQ0KICAgIGZvcihpIGluIHllYXJzOnllYXJlKXsNCiAgICAgICAgZHBbKGkteWVhcnMrMSksInI5NXAiXTwtc3VtKGRkW2RkJHllYXI9PWkmZGQkcHJjcD5wcmNwOTUsInByY3AiXSxuYS5ybT1UKQ0KICAgICAgICBkcFsoaS15ZWFycysxKSwicjk5cCJdPC1zdW0oZGRbZGQkeWVhcj09aSZkZCRwcmNwPnByY3A5OSwicHJjcCJdLG5hLnJtPVQpDQogICAgICAgIGRwWyhpLXllYXJzKzEpLCJwcmNwdG90Il08LXN1bShkZFtkZCR5ZWFyPT1pJmRkJHByY3A+PTEsInByY3AiXSxuYS5ybT1UKQ0KICAgIH0NCiAgICBkcFssInI5NXAiXTwtcm91bmQoZHBbLCJyOTVwIl0sMSkreW5hY29yWywieW5hcHI+MTUiXQ0KICAgIGRwWywicjk5cCJdPC1yb3VuZChkcFssInI5OXAiXSwxKSt5bmFjb3JbLCJ5bmFwcj4xNSJdDQogICAgZHBbLCJwcmNwdG90Il08LXJvdW5kKGRwWywicHJjcHRvdCJdLDEpK3luYWNvclssInluYXByPjE1Il0NCiAgICBkcDwtYXMuZGF0YS5mcmFtZShkcCkNCiAgICBuYW0xPC1wYXN0ZShvdXRpbmRkaXIscGFzdGUob2ZpbGVuYW1lLCJfUjk1cC5jc3YiLHNlcD0iIiksc2VwPSIvIikNCiAgICBuYW0yPC1wYXN0ZShvdXRpbmRkaXIscGFzdGUob2ZpbGVuYW1lLCJfUjk5cC5jc3YiLHNlcD0iIiksc2VwPSIvIikNCiAgICBuYW0zPC1wYXN0ZShvdXRpbmRkaXIscGFzdGUob2ZpbGVuYW1lLCJfUFJDUFRPVC5jc3YiLHNlcD0iIiksc2VwPSIvIikNCiAgICB3cml0ZS50YWJsZShkcFssYygieWVhciIsInI5NXAiKV0sZmlsZT1uYW0xLGFwcGVuZD1GLHF1b3RlPUYsc2VwPSIsICIsbmE9Ii05OS45Iixyb3cubmFtZXM9RikNCiAgICB3cml0ZS50YWJsZShkcFssYygieWVhciIsInI5OXAiKV0sZmlsZT1uYW0yLGFwcGVuZD1GLHF1b3RlPUYsc2VwPSIsICIsbmE9Ii05OS45Iixyb3cubmFtZXM9RikNCiAgICB3cml0ZS50YWJsZShkcFssYygieWVhciIsInByY3B0b3QiKV0sZmlsZT1uYW0zLGFwcGVuZD1GLHF1b3RlPUYsc2VwPSIsICIsbmE9Ii05OS45Iixyb3cubmFtZXM9RikNCiAgICANCiAgICBuYW10PC1wYXN0ZShvdXR0cmRkaXIscGFzdGUob2ZpbGVuYW1lLCJfdHJlbmQuY3N2IixzZXA9IiIpLHNlcD0iLyIpDQogICAgZm9yKGkgaW4gYygicjk1cCIsInI5OXAiLCJwcmNwdG90Iikpew0KICAgICAgICBpZihzdW0oaXMubmEoZHBbLGldKSk+PSh5ZWFyZS15ZWFycysxLTEwKSl7DQogICAgICAgICAgICBiZXRhaGF0PC1OQQ0KICAgICAgICAgICAgYmV0YXN0ZDwtTkENCiAgICAgICAgICAgIHB2YWx1ZTwtTkENCiAgICAgICAgfQ0KICAgICAgICBlbHNlew0KICAgICAgICAgICAgZml0MTwtbHNmaXQoZHBbLCJ5ZWFyIl0sZHBbLGldKQ0KICAgICAgICAgICAgb3V0MTwtbHMucHJpbnQoZml0MSxwcmludC5pdD1GKQ0KICAgICAgICAgICAgcHZhbHVlPC1yb3VuZChhcy5udW1lcmljKG91dDEkc3VtbWFyeVsxLDZdKSwzKQ0KICAgICAgICAgICAgYmV0YWhhdDwtcm91bmQoYXMubnVtZXJpYyhvdXQxJGNvZWYudGFibGVbWzFdXVsyLDFdKSwzKQ0KICAgICAgICAgICAgYmV0YXN0ZDwtcm91bmQoYXMubnVtZXJpYyhvdXQxJGNvZWYudGFibGVbWzFdXVsyLDJdKSwzKQ0KICAgICAgICB9DQogICAgICAgIGNhdChmaWxlPW5hbXQscGFzdGUobGF0aXR1ZGUsbG9uZ2l0dWRlLGkseWVhcnMseWVhcmUsYmV0YWhhdCxiZXRhc3RkLHB2YWx1ZSxzZXA9IiwiKSxmaWxsPTE4MCxhcHBlbmQ9VCkNCiAgICB9DQogICAgDQogICAgbmFtNDwtcGFzdGUob3V0anBnZGlyLHBhc3RlKG9maWxlbmFtZSwiX1I5NXAuanBnIixzZXA9IiIpLHNlcD0iLyIpDQogICAganBlZyhuYW00LHdpZHRoPTEwMjQsaGVpZ2h0PTc2OCkNCiAgICBwbG90eChkcFssMV0sZHBbLCJyOTVwIl0sbWFpbj1wYXN0ZSgiUjk1cCIsb2ZpbGVuYW1lLHNlcD0iICAgIikseGxhYj0iWWVhciIseWxhYj0iUjk1cCIpDQogICAgZGV2Lm9mZigpDQogICAgbmFtNTwtcGFzdGUob3V0anBnZGlyLHBhc3RlKG9maWxlbmFtZSwiX1I5OXAuanBnIixzZXA9IiIpLHNlcD0iLyIpDQogICAganBlZyhuYW01LHdpZHRoPTEwMjQsaGVpZ2h0PTc2OCkNCiAgICBwbG90eChkcFssMV0sZHBbLCJyOTlwIl0sbWFpbj1wYXN0ZSgiUjk5cCIsb2ZpbGVuYW1lLHNlcD0iICAgIikseGxhYj0iWWVhciIseWxhYj0iUjk5cCIpDQogICAgZGV2Lm9mZigpDQogICAgbmFtNjwtcGFzdGUob3V0anBnZGlyLHBhc3RlKG9maWxlbmFtZSwiX1BSQ1BUT1QuanBnIixzZXA9IiIpLHNlcD0iLyIpDQogICAganBlZyhuYW02LHdpZHRoPTEwMjQsaGVpZ2h0PTc2OCkNCiAgICBwbG90eChkcFssMV0sZHBbLCJwcmNwdG90Il0sbWFpbj1wYXN0ZSgiUFJDUFRPVCIsb2ZpbGVuYW1lLHNlcD0iICAgIikseGxhYj0iWWVhciIseWxhYj0iUFJDUFRPVCIpDQogICAgZGV2Lm9mZigpDQp9DQojLS0tLS0tLS0tLS0gcjk1cHRvdCBlbmRzIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tDQoNCiMtLS0tLS0tLS0tLSBkYXlzcHJjcDIwIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tDQpkYXlzcHJjcDIwPC1mdW5jdGlvbigpew0KICAgIHlzPC15ZWFyZS15ZWFycysxDQogICAgUjIwPC1yZXAoMCx5cykNCiAgICB5ZWFyc3M8LWMoeWVhcnM6eWVhcmUpDQogICAgdGFyZ2V0PC1hcy5kYXRhLmZyYW1lKGNiaW5kKHllYXJzcyxSMjApKQ0KICAgIGZvciAoeWVhciBpbiB5ZWFyczp5ZWFyZSl7DQogICAgICAgIG1pZDwtZGRbZGQkeWVhcj09eWVhciwicHJjcCJdDQogICAgICAgIG1pZDwtbWlkW2lzLm5hKG1pZCk9PUZdDQogICAgICAgIHRhcmdldFt0YXJnZXQkeWVhcnNzPT15ZWFyLCJSMjAiXTwtbGVuZ3RoKG1pZFttaWQ+PTIwXSl9IyBlbmQgZm9yDQogICAgZGltbmFtZXModGFyZ2V0KVtbMl1dWzFdPC0ieWVhciINCiAgICB0YXJnZXRbLCJSMjAiXTwtdGFyZ2V0WywiUjIwIl0reW5hY29yWywieW5hcHI+MTUiXQ0KICAgIG5hbTE8LXBhc3RlKG91dGluZGRpcixwYXN0ZShvZmlsZW5hbWUsIl9SMjBtbS5jc3YiLHNlcD0iIiksc2VwPSIvIikNCiAgICB3cml0ZS50YWJsZSh0YXJnZXQsZmlsZT1uYW0xLGFwcGVuZD1GLHF1b3RlPUYsc2VwPSIsICIsbmE9Ii05OS45Iixyb3cubmFtZXM9RikNCiAgICANCiAgICBuYW10PC1wYXN0ZShvdXR0cmRkaXIscGFzdGUob2ZpbGVuYW1lLCJfdHJlbmQuY3N2IixzZXA9IiIpLHNlcD0iLyIpDQogICAgaWYoc3VtKGlzLm5hKHRhcmdldFssIlIyMCJdKSk+PSh5ZWFyZS15ZWFycysxLTEwKSl7DQogICAgICAgIGJldGFoYXQ8LU5BDQogICAgICAgIGJldGFzdGQ8LU5BDQogICAgICAgIHB2YWx1ZTwtTkENCiAgICB9DQogICAgZWxzZXsNCiAgICAgICAgZml0MTwtbHNmaXQodGFyZ2V0WywieWVhciJdLHRhcmdldFssIlIyMCJdKQ0KICAgICAgICBvdXQxPC1scy5wcmludChmaXQxLHByaW50Lml0PUYpDQogICAgICAgIHB2YWx1ZTwtcm91bmQoYXMubnVtZXJpYyhvdXQxJHN1bW1hcnlbMSw2XSksMykNCiAgICAgICAgYmV0YWhhdDwtcm91bmQoYXMubnVtZXJpYyhvdXQxJGNvZWYudGFibGVbWzFdXVsyLDFdKSwzKQ0KICAgICAgICBiZXRhc3RkPC1yb3VuZChhcy5udW1lcmljKG91dDEkY29lZi50YWJsZVtbMV1dWzIsMl0pLDMpDQogICAgfQ0KICAgIGNhdChmaWxlPW5hbXQscGFzdGUobGF0aXR1ZGUsbG9uZ2l0dWRlLCJyMjBtbSIseWVhcnMseWVhcmUsYmV0YWhhdCxiZXRhc3RkLHB2YWx1ZSxzZXA9IiwiKSxmaWxsPTE4MCxhcHBlbmQ9VCkNCiAgICANCiAgICBuYW0yPC1wYXN0ZShvdXRqcGdkaXIscGFzdGUob2ZpbGVuYW1lLCJfUjIwbW0uanBnIixzZXA9IiIpLHNlcD0iLyIpDQogICAganBlZyhuYW0yLHdpZHRoPTEwMjQsaGVpZ2h0PTc2OCkNCiAgICBwbG90eCh0YXJnZXRbLDFdLHRhcmdldFssMl0sbWFpbj1wYXN0ZSgiUjIwbW0iLG9maWxlbmFtZSxzZXA9IiAgICIpLHhsYWI9IlllYXIiLHlsYWI9IlIyMG1tIikNCiAgICBkZXYub2ZmKCkNCn0NCiMtLS0tLS0tLS0tLSBkYXlzcHJjcDIwIGVuZHMgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0NCg0KIy0tLS0tLS0tLS0tIGRheXNwcmNwbiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQ0KZGF5c3ByY3BuPC1mdW5jdGlvbigpew0KICAgIHlzPC15ZWFyZS15ZWFycysxDQogICAgUm5uPC1yZXAoMCx5cykNCiAgICB5ZWFyc3M8LWMoeWVhcnM6eWVhcmUpDQogICAgdGFyZ2V0PC1hcy5kYXRhLmZyYW1lKGNiaW5kKHllYXJzcyxSbm4pKQ0KICAgIGZvciAoeWVhciBpbiB5ZWFyczp5ZWFyZSl7DQogICAgICAgIG1pZDwtZGRbZGQkeWVhcj09eWVhciwicHJjcCJdDQogICAgICAgIG1pZDwtbWlkW2lzLm5hKG1pZCk9PUZdDQogICAgICAgIHRhcmdldFt0YXJnZXQkeWVhcnNzPT15ZWFyLCJSbm4iXTwtbGVuZ3RoKG1pZFttaWQ+PW5uXSkNCiAgICB9DQogICAgZGltbmFtZXModGFyZ2V0KVtbMl1dWzFdPC0ieWVhciINCiAgICB0YXJnZXRbLCJSbm4iXTwtdGFyZ2V0WywiUm5uIl0reW5hY29yWywieW5hcHI+MTUiXQ0KICAgIA0KICAgIG5hbTE8LXBhc3RlKG91dGluZGRpcixwYXN0ZShvZmlsZW5hbWUsIl9SIixhcy5jaGFyYWN0ZXIobm4pLCJtbS5jc3YiLHNlcD0iIiksc2VwPSIvIikNCiAgICB3cml0ZS50YWJsZSh0YXJnZXQsZmlsZT1uYW0xLGFwcGVuZD1GLHF1b3RlPUYsc2VwPSIsICIsbmE9Ii05OS45Iixyb3cubmFtZXM9RikNCiAgICANCiAgICBuYW10PC1wYXN0ZShvdXR0cmRkaXIscGFzdGUob2ZpbGVuYW1lLCJfdHJlbmQuY3N2IixzZXA9IiIpLHNlcD0iLyIpDQogICAgaWYoc3VtKGlzLm5hKHRhcmdldFssIlJubiJdKSk+PSh5ZWFyZS15ZWFycysxLTEwKSl7DQogICAgICAgIGJldGFoYXQ8LU5BDQogICAgICAgIGJldGFzdGQ8LU5BDQogICAgICAgIHB2YWx1ZTwtTkENCiAgICB9DQogICAgZWxzZXsNCiAgICAgICAgZml0MTwtbHNmaXQodGFyZ2V0WywxXSx0YXJnZXRbLCJSbm4iXSkNCiAgICAgICAgb3V0MTwtbHMucHJpbnQoZml0MSxwcmludC5pdD1GKQ0KICAgICAgICBwdmFsdWU8LXJvdW5kKGFzLm51bWVyaWMob3V0MSRzdW1tYXJ5WzEsNl0pLDMpDQogICAgICAgIGJldGFoYXQ8LXJvdW5kKGFzLm51bWVyaWMob3V0MSRjb2VmLnRhYmxlW1sxXV1bMiwxXSksMykNCiAgICAgICAgYmV0YXN0ZDwtcm91bmQoYXMubnVtZXJpYyhvdXQxJGNvZWYudGFibGVbWzFdXVsyLDJdKSwzKQ0KICAgIH0NCiAgICBjYXQoZmlsZT1uYW10LHBhc3RlKGxhdGl0dWRlLGxvbmdpdHVkZSxwYXN0ZSgiUiIsYXMuY2hhcmFjdGVyKG5uKSwibW0iLHNlcD0iIikseWVhcnMseWVhcmUsYmV0YWhhdCxiZXRhc3RkLHB2YWx1ZSxzZXA9IiwiKSxmaWxsPTE4MCxhcHBlbmQ9VCkNCiAgICANCiAgICBuYW0yPC1wYXN0ZShvdXRqcGdkaXIscGFzdGUob2ZpbGVuYW1lLCJfUiIsYXMuY2hhcmFjdGVyKG5uKSwibW0uanBnIixzZXA9IiIpLHNlcD0iLyIpDQogICAganBlZyhuYW0yLHdpZHRoPTEwMjQsaGVpZ2h0PTc2OCkNCiAgICBwbG90eCh0YXJnZXRbLDFdLHRhcmdldFssMl0sbWFpbj1wYXN0ZSgiUiIsYXMuY2hhcmFjdGVyKG5uKSwibW0iLG9maWxlbmFtZSxzZXA9IiAgICIpLHhsYWI9IlllYXIiLHlsYWI9IlJubm1tIikNCiAgICBkZXYub2ZmKCkNCn0NCiMtLS0tLS0tLS0tLSBkYXlzcHJjcG4gZW5kcyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQ0KDQojLS0tLS0tLS0tLS0gbm9yZGF5dGVtMSAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQ0Kbm9yZGF5dGVtMTwtZnVuY3Rpb24oKXsgICMgaW5pdGlhbGl6ZSBkYXRhDQogICAgIyBub3JtYWwgdGVtcA0KICAgIA0KICAgIGRheW5vcm08LWRkW2RkJHllYXI+PXN0YXJ0eWVhcixdDQogICAgZGF5bm9ybTwtZGF5bm9ybVtkYXlub3JtJHllYXI8PWVuZHllYXIsXSAjIGluaXRpYWxpemUgZGF5bm9ybSBtYXRyaXgNCiAgICBkYXlub3I8LWRheW5vcm0gICAgICAgICAgICAgICMgY3JlYXRlIHRhcmdldCBtYXRyaXgNCiAgICBubjwtZGRbZGQkeWVhcj09c3RhcnRwb2ludCxdDQogICAgbm48LW5uW25uJG1vbnRoPT0xMixdDQogICAgbm48LW5uW25uJGRheT4oMzEtcm91bmQod2luc2l6ZS8yKSksXQ0KICAgIGRheW5vcm08LXJiaW5kKG5uLGRheW5vcm0pDQogICAgbm48LWRkW2RkJHllYXI9PWVuZHBvaW50LF0NCiAgICBubjwtbm5bbm4kbW9udGg9PTEsXQ0KICAgIG5uPC1ubltubiRkYXk8PXJvdW5kKHdpbnNpemUvMiksXQ0KICAgIGRheW5vcm08LXJiaW5kKGRheW5vcm0sbm4pDQogICAgDQogICAgZGF5bm9ybTE8LWRheW5vcm1bLC00XQ0KICAgIGRheW5vcm0xW2RheW5vcm0xJG1vbnRoPT0yICYgZGF5bm9ybTEkZGF5PT0yOSxdPC0tOTkNCiAgICBkYXlub3JtMTwtZGF5bm9ybTFbZGF5bm9ybTEkeWVhciE9LTk5LF0NCiAgICBkYXl0PC1kYXlub3JtMVssYygidG1heCIsInRtaW4iKV0NCiAgICANCiAgICBkZHRlbTwtZGRbLC00XQ0KICAgIGRkdGVtW2RkdGVtJG1vbnRoPT0yICYgZGR0ZW0kZGF5PT0yOSxdPC0tOTkNCiAgICBkZHRlbTwtZGR0ZW1bZGR0ZW0keWVhciE9LTk5LF0NCiAgICBhc3NpZ24oImRkdGVtIixkZHRlbSxlbnZpcj0uR2xvYmFsRW52KQ0KICAgIA0KICAgIGE8LW1hdHJpeCgtOTksNSw1KQ0KICAgIGRpbW5hbWVzKGEpW1syXV08LWMoInllYXIiLCJtb250aCIsImRheSIsInRtYXgiLCJ0bWluIikNCiAgICBkZHRlbXQ8LXJiaW5kKGEsZGR0ZW0pOyAgICBhc3NpZ24oImRkdGVtdCIsZGR0ZW10LGVudmlyPS5HbG9iYWxFbnYpDQogICAgDQogICAgeXM8LWVuZHllYXItc3RhcnR5ZWFyKzENCiAgICB3aW5kb3c8LW1hdHJpeCgwLHdpbnNpemUsMikNCiAgICB3aW5kb3dzPC1hcnJheSh3aW5kb3csYyh3aW5zaXplLDIsMzY2LHlzKSkNCiAgICBkaW1uYW1lcyh3aW5kb3dzKTwtbGlzdChOVUxMLGMoInRtYXgiLCJ0bWluIiksTlVMTCxOVUxMKQ0KICAgIA0KICAgIGk9d2luc2l6ZS1yb3VuZCh3aW5zaXplLzIsZGlnaXRzPTApDQogICAgaTE9cm91bmQod2luc2l6ZS8yLGRpZ2l0cz0wKQ0KICAgIGRheW5vcm1tPC1kYXlub3JtWyxjKCJ0bWF4IiwidG1pbiIpXQ0KICAgIGRheW5vcm1tPC1hcy5tYXRyaXgoZGF5bm9ybW0pDQogICAgeWVhcjwtc3RhcnR5ZWFyDQogICAgDQogICAgZm9yIChrIGluIDE6eXMpew0KICAgICAgICBpZiAobGVhcHllYXIoeWVhcik9PVQpIGpqPC0zNjYgZWxzZSB7amo8LTM2NTsgICB3aW5kb3dzWywsMzY2LGtdPC0tOTkgfQ0KICAgICAgICB5ZWFyPC15ZWFyKzENCiAgICAgICAgZm9yIChqIGluIDE6amopew0KICAgICAgICAgICAgd2luZG93c1ssLGosa108LWRheW5vcm1tWyhpLWkxKTooaStpMSksXQ0KICAgICAgICAgICAgaT1pKzEgfX0NCiAgICANCiAgICBtd2luZG93czwtY29sTWVhbnMod2luZG93cyxuYS5ybT1UKQ0KICAgIHRtYXg8LW13aW5kb3dzWyJ0bWF4IiwsXTsgICAgdG1heDwtdG1heFt0bWF4IT0tOTldDQogICAgdG1pbjwtbXdpbmRvd3NbInRtaW4iLCxdOyAgICB0bWluPC10bWluW3RtaW4hPS05OV0NCiAgICBkYXlub3JbLCJ0bWF4Il08LXRtYXg7ICAgICAgIGRheW5vclssInRtaW4iXTwtdG1pbg0KICAgIA0KICAgIGE8LXJlcCgwLG5yb3coZGF5bm9yKSkNCiAgICBhPC0oZGF5bm9yWywidG1heCJdK2RheW5vclssInRtaW4iXSkvMg0KICAgIGRheXRlbWF2ZTwtYSAgICANCiAgICBkYXlub3I8LWNiaW5kKGRheW5vcixkYXl0ZW1hdmUpDQogICAgDQogICAgIyBvdXRwdXQgdGhlIHJlc3VsdCB0byBnbG9iZSBlbnZpcm9tZW50DQogICAgYXNzaWduKCJkYXlub3IiLGRheW5vcixlbnZpcj0uR2xvYmFsRW52KQ0KICAgIGFzc2lnbigiZGF5bm9ybSIsZGF5bm9ybSxlbnZpcj0uR2xvYmFsRW52KQ0KICAgIGFzc2lnbigiZGF5bm9ybTEiLGRheW5vcm0xLGVudmlyPS5HbG9iYWxFbnYpDQogICAgYXNzaWduKCJkYXl0IixkYXl0LGVudmlyPS5HbG9iYWxFbnYpDQogICAgDQogICAgIyBwcmNwIHBlcmNlbnRpbGUgOTUlIGFuZCA5OSUNCiAgICBwcmNwbm9ybTwtZGRbZGQkeWVhcj49c3RhcnR5ZWFyLF0NCiAgICBwcmNwbm9ybTwtcHJjcG5vcm1bcHJjcG5vcm0keWVhcjw9ZW5keWVhcixdICMgaW5pdGlhbGl6ZSBwcmNwbm9ybSBtYXRyaXgNCiAgICBubnA8LWRkW2RkJHllYXI9PXN0YXJ0cG9pbnQsXQ0KICAgIG5ucDwtbm5wW25ucCRtb250aD09MTIsXQ0KICAgIG5ucDwtbm5wW25ucCRkYXk+MjksXQ0KICAgIHByY3Bub3JtPC1yYmluZChubnAscHJjcG5vcm0pDQogICAgbm5wPC1kZFtkZCR5ZWFyPT1lbmRwb2ludCxdDQogICAgbm5wPC1ubnBbbm5wJG1vbnRoPT0xLF0NCiAgICBubnA8LW5ucFtubnAkZGF5PD0yLF0NCiAgICBwcmNwbm9ybTwtcmJpbmQocHJjcG5vcm0sbm5wKQ0KICAgIHByY3Bub3JtPC1wcmNwbm9ybVssMTo0XQ0KICAgICMgcmVtb3ZlIEZlYiAyOQ0KICAgIHByY3Bub3JtW3ByY3Bub3JtJG1vbnRoPT0yICYgcHJjcG5vcm0kZGF5PT0yOSxdPC0tOTkNCiAgICBwcmNwbm9ybTwtcHJjcG5vcm1bcHJjcG5vcm0keWVhciE9LTk5LF0NCiAgICBhc3NpZ24oInByY3Bub3JtIixwcmNwbm9ybSxlbnZpcj0uR2xvYmFsRW52KQ0KICAgIA0KICAgIHlzPC1lbmR5ZWFyLXN0YXJ0eWVhcisxIA0KICAgIA0KICAgIGFhc3A8LW1hdHJpeChOQSwzNjUsMykNCiAgICBkaW1uYW1lcyhhYXNwKTwtbGlzdChOVUxMLGMoImRheSIsInByY3A5NSIsInByY3A5OSIpKQ0KICAgIGFhc3BbLCJkYXkiXTwtMTozNjUNCiAgICANCiAgICBtc3A8LTUqeXMNCiAgICBwcmNwbm9ybTwtYXMubWF0cml4KHByY3Bub3JtKQ0KICAgIHB3aW5kb3c8LW1hdHJpeCgwLDUsMSkNCiAgICBwd2luZG93czwtYXJyYXkocHdpbmRvdyxjKDUsMSwzNjUseXMpKSAjYXJyYXkgdXNlZCB0byBzdG9yZSBhbGwgd2luZG93cw0KICAgIGlwPTMNCiAgICBpcDE9Mg0KICAgIGZvciAoayBpbiAxOnlzKXsNCiAgICAgICAgZm9yIChqIGluIDE6MzY1KXsNCiAgICAgICAgICAgIA0KICAgICAgICAgICAgcHdpbmRvd3NbLCxqLGtdPC1wcmNwbm9ybVsoaXAtaXAxKTooaXAraXAxKSwicHJjcCJdDQogICAgICAgICAgICBpcD1pcCsxfX0NCiAgICANCiAgICBwcmNwd2luPC1tYXRyaXgoMCxtc3AsMikNCiAgICBwcmNwd2luWywyXTwtMTp5cw0KICAgIHByY3B3aW5bLDJdPC1teXNvcnQocHJjcHdpblssMl0sZGVjcmVhc2luZz1GKQ0KICAgIA0KICAgIHByY3B3aW5zPC1hcnJheShwcmNwd2luLGMobXNwLDIsMzY1KSkgDQogICAgDQogICAgZm9yIChqIGluIDE6MzY1KXsNCiAgICAgICAgZm9yIChpIGluIDE6eXMpew0KICAgICAgICAgICAgcHJjcHdpbnNbcHJjcHdpbnNbLDIsal09PWksMSxqXTwtcHdpbmRvd3NbLCxqLGldfX0NCiAgICAjYXNzaWduKCJleHdpbnMiLGV4d2lucyxlbnZpcj0uR2xvYmFsRW52KQ0KICAgIA0KICAgIGZvciAoaSBpbiAxOjM2NSl7DQogICAgICAgIGFzc3A8LXByY3B3aW5zWywsaV0NCiAgICAgICAgaWYoc3VtKGlzLm5hKGFzc3BbLDFdKT09Rik+PTEpDQogICAgICAgICAgICBhYXNwW2ksInByY3A5NSJdPC1wZXJjZW50aWxlKG1zcCxhc3NwWywxXSwwLjk1KQ0KICAgICAgICBlbHNlIGFhc3BbaSwicHJjcDk1Il08LU5BDQogICAgICAgIGlmKHN1bShpcy5uYShhc3NwWywxXSk9PUYpPj0xKQ0KICAgICAgICAgICAgYWFzcFtpLCJwcmNwOTkiXTwtcGVyY2VudGlsZShtc3AsYXNzcFssMV0sMC45OSkNCiAgICAgICAgZWxzZSBhYXNwW2ksInByY3A5OSJdPC1OQQ0KICAgIH0NCiAgICBhc3NpZ24oImFhc3AiLGFhc3AsZW52aXI9Lkdsb2JhbEVudikNCiAgICANCiAgICBhYXM8LW1hdHJpeChOQSwzNjUsNSkNCiAgICBkaW1uYW1lcyhhYXMpPC1saXN0KE5VTEwsYygiZGF5IiwicGNtYXgxMCIsInBjbWF4OTAiLCJwY21pbjEwIiwicGNtaW45MCIpKQ0KICAgIGFhc1ssImRheSJdPC0xOjM2NQ0KICAgIA0KICAgIG1zPC13aW5zaXplKnlzDQogICAgZGF5dDwtYXMubWF0cml4KGRheXQpDQogICAgd2luZG93PC1tYXRyaXgoMCx3aW5zaXplLDIpDQogICAgd2luZG93czwtYXJyYXkod2luZG93LGMod2luc2l6ZSwyLDM2NSx5cykpICNhcnJheSB1c2VkIHRvIHN0b3JlIGFsbCB3aW5kb3dzDQogICAgaT13aW5zaXplLXJvdW5kKHdpbnNpemUvMixkaWdpdHM9MCkNCiAgICBpMT1yb3VuZCh3aW5zaXplLzIsZGlnaXRzPTApDQogICAgZm9yIChrIGluIDE6eXMpew0KICAgICAgICBmb3IgKGogaW4gMTozNjUpew0KICAgICAgICAgICAgDQogICAgICAgICAgICB3aW5kb3dzWywsaixrXTwtZGF5dFsoaS1pMSk6KGkraTEpLF0NCiAgICAgICAgICAgIGk9aSsxfX0NCiAgICANCiAgICBleHdpbjwtbWF0cml4KDAsbXMsMykNCiAgICBleHdpblssM108LTE6eXMNCiAgICBleHdpblssM108LW15c29ydChleHdpblssM10sZGVjcmVhc2luZz1GKQ0KICAgIGFzc2lnbigiZXh3aW4iLGV4d2luLGVudmlyPS5HbG9iYWxFbnYpDQogICAgI2luZGQ8LWV4d2luW2V4d2luWywzXSE9eXMsM10NCiAgICBleHdpbnM8LWFycmF5KGV4d2luLGMobXMsMywzNjUpKSAjIGFycmF5IGZvciBib290c3RyYXANCiAgICANCiAgICBmb3IgKGogaW4gMTozNjUpew0KICAgICAgICBmb3IgKGkgaW4gMTp5cyl7DQogICAgICAgICAgICBleHdpbnNbZXh3aW5zWywzLGpdPT1pLDE6MixqXTwtd2luZG93c1ssLGosaV19fQ0KICAgIGFzc2lnbigiZXh3aW5zIixleHdpbnMsZW52aXI9Lkdsb2JhbEVudikNCiAgICANCiAgICBmb3IgKCBpIGluIDE6MzY1KXsNCiAgICAgICAgYXNzPC1leHdpbnNbLCxpXQ0KICAgICAgICBhc3MxPC1hc3NbLDFdDQogICAgICAgIGFzczI8LWFzc1ssMl0NCiAgICAgICAga2diMTwtbGVuZ3RoKGFzczFbaXMubmEoYXNzMSldKQ0KICAgICAgICBrZ2IyPC1sZW5ndGgoYXNzMltpcy5uYShhc3MyKV0pDQogICAgICAgIGlmIChrZ2IxPjM3LjUgfCBrZ2IyPjM3LjUpIHtmbGFnPVQ7YnJlYWt9fSMxNTAqMC4yNT0zNy41DQogICAgDQogICAgYXNzaWduKCJmbGFnIixmbGFnLGVudmlyPS5HbG9iYWxFbnYpDQogICAgaWYgKGZsYWc9PVQpIHRrbWVzc2FnZUJveChtZXNzYWdlPSJNb3JlIHRoYW4gMjUlIGRhdGEgbWlzc2luZywgRXhjZWVkYW5jZSByYXRlLCBIV0RJLENXREkgd2lsbCBub3QgYmUgY2FsY3VsYXRlZCEhIikNCiAgICBpZiAoZmxhZz09VCkgcmV0dXJuKCkNCiAgICBmb3IgKGkgaW4gMTozNjUpew0KICAgICAgICBhc3M8LWV4d2luc1ssLGldDQogICAgICAgICMgaWYoaSA9PSAzNjMpIHsNCiAgICAgICAgIyB0dG1wPC1tcw0KICAgICAgICAjIGFzc2lnbigidHRtcCIsdHRtcCxlbnZpcj0uR2xvYmFsRW52KQ0KICAgICAgICAjIH0NCiAgICAgICAgaXRtcDwtcGVyY2VudGlsZShtcyxhc3NbLDFdLGMoMC4xLDAuOSkpDQogICAgICAgIGFhc1tpLCJwY21heDEwIl08LWl0bXBbMV0tMWUtNQ0KICAgICAgICBhYXNbaSwicGNtYXg5MCJdPC1pdG1wWzJdKzFlLTUNCiAgICAgICAgaXRtcDwtcGVyY2VudGlsZShtcyxhc3NbLDJdLGMoMC4xLDAuOSkpDQogICAgICAgIGFhc1tpLCJwY21pbjEwIl08LWl0bXBbMV0tMWUtNQ0KICAgICAgICBhYXNbaSwicGNtaW45MCJdPC1pdG1wWzJdKzFlLTUgIH0NCiAgICANCiAgICBhc3NpZ24oImFhcyIsYWFzLGVudmlyPS5HbG9iYWxFbnYpIyBtYXRyaXggdG8gc3RvcmUgMTAgYW5kIDkwIHBlcmNlbnRpbGUNCiAgICAjIGV4Y2VlZGFuY2UgcmF0ZSBiZWZvcmUgMTk2MSBhbmQgYWZ0ZXIgMjAwMA0KICAgIGJlZm9yZTwtZGRbZGQkeWVhcjxzdGFydHllYXIsXQ0KICAgIGFmdGVyPC1kZFtkZCR5ZWFyPmVuZHllYXIsXQ0KICAgIA0KICAgICMgZGF0YWZyYW1lIHN0b3JlIHRoZSBiZWZvcmUgbW9udGhseSBleGNlZWRhbmNlIHJhdGUNCiAgICB5czE8LXN0YXJ0eWVhci15ZWFyczt5czI8LXllYXJlLWVuZHllYXINCiAgICBibW9uZXg8LW1hdHJpeChOQSx5czEqMTIsNikNCiAgICBkaW1uYW1lcyhibW9uZXgpPC1saXN0KE5VTEwsYygieWVhciIsIm1vbnRoIiwidHgxMHAiLCJ0eDkwcCIsInRuMTBwIiwidG45MHAiKSkNCiAgICBibW9uZXhbLCJtb250aCJdPC1yZXAoMToxMix5czEpDQogICAgYm1vbmV4WywieWVhciJdPC15ZWFyczooc3RhcnR5ZWFyLTEpDQogICAgYm1vbmV4WywieWVhciJdPC1teXNvcnQoYm1vbmV4WywieWVhciJdLGRlY3JlYXNpbmc9RikNCiAgICBibW9uZXg8LWFzLmRhdGEuZnJhbWUoYm1vbmV4KQ0KICAgIA0KICAgICMgZGF0YWZyYW1lIHN0b3JlIHRoZSBhZnRlciBtb250aGx5IGV4Y2VlZGFuY2UgcmF0ZQ0KICAgIGFtb25leDwtbWF0cml4KE5BLHlzMioxMiw2KQ0KICAgIGRpbW5hbWVzKGFtb25leCk8LWxpc3QoTlVMTCxjKCJ5ZWFyIiwibW9udGgiLCJ0eDEwcCIsInR4OTBwIiwidG4xMHAiLCJ0bjkwcCIpKQ0KICAgIGFtb25leFssIm1vbnRoIl08LXJlcCgxOjEyLHlzMikNCiAgICBhbW9uZXhbLCJ5ZWFyIl08LShlbmR5ZWFyKzEpOnllYXJlDQogICAgYW1vbmV4WywieWVhciJdPC1teXNvcnQoYW1vbmV4WywieWVhciJdLGRlY3JlYXNpbmc9RikNCiAgICBhbW9uZXg8LWFzLmRhdGEuZnJhbWUoYW1vbmV4KQ0KICAgIA0KICAgICMgZGF0YWZyYW1lIHN0b3JlIHllYXJseSBleGNlZWRhbmNlIHJhdGUgKGJlZm9yZSBhbmQgYWZ0ZXIpDQogICAgeWVhcmV4PC1jKHllYXJzOihzdGFydHllYXItMSkpOyAgIHR4ZzEwcDwtcmVwKDAsbGVuZ3RoKHllYXJleCkpDQogICAgdHhnOTBwPC1yZXAoMCxsZW5ndGgoeWVhcmV4KSk7ICAgIHRuZzEwcDwtcmVwKDAsbGVuZ3RoKHllYXJleCkpDQogICAgdG5nOTBwPC1yZXAoMCxsZW5ndGgoeWVhcmV4KSkNCiAgICBiZDwtYXMuZGF0YS5mcmFtZShjYmluZCh5ZWFyZXgsdHhnMTBwLHR4ZzkwcCx0bmcxMHAsdG5nOTBwKSkNCiAgICBjb2xuYW1lcyhiZClbMV08LSJ5ZWFyIg0KICAgIA0KICAgIHllYXJleDwtYygoZW5keWVhcisxKTp5ZWFyZSk7ICAgICB0eGcxMHA8LXJlcCgwLGxlbmd0aCh5ZWFyZXgpKQ0KICAgIHR4ZzkwcDwtcmVwKDAsbGVuZ3RoKHllYXJleCkpOyAgICB0bmcxMHA8LXJlcCgwLGxlbmd0aCh5ZWFyZXgpKQ0KICAgIHRuZzkwcDwtcmVwKDAsbGVuZ3RoKHllYXJleCkpDQogICAgYWQ8LWFzLmRhdGEuZnJhbWUoY2JpbmQoeWVhcmV4LHR4ZzEwcCx0eGc5MHAsdG5nMTBwLHRuZzkwcCkpDQogICAgY29sbmFtZXMoYWQpWzFdPC0ieWVhciINCiAgICANCiAgICB5ZWFyPXllYXJzO2pqajY9MQ0KICAgIGZvciAoaSBpbiAxOnlzMSl7DQogICAgICAgIG1pZHZhbHVlPC1kZHRlbVtkZHRlbSR5ZWFyPT15ZWFyLF0NCiAgICAgICAgZXhtYXgxMDwtbWlkdmFsdWVbLDRdLWFhc1ssMl0NCiAgICAgICAgZXhtYXgxMG0xPC1leG1heDEwWzE6MzFdOyAgICAgIGV4bWF4MTBtMjwtZXhtYXgxMFszMjo1OV07ICAgIGV4bWF4MTBtMzwtZXhtYXgxMFs2MDo5MF0NCiAgICAgICAgZXhtYXgxMG00PC1leG1heDEwWzkxOjEyMF07ICAgIGV4bWF4MTBtNTwtZXhtYXgxMFsxMjE6MTUxXTsgIGV4bWF4MTBtNjwtZXhtYXgxMFsxNTI6MTgxXQ0KICAgICAgICBleG1heDEwbTc8LWV4bWF4MTBbMTgyOjIxMl07ICAgZXhtYXgxMG04PC1leG1heDEwWzIxMzoyNDNdOyAgZXhtYXgxMG05PC1leG1heDEwWzI0NDoyNzNdDQogICAgICAgIGV4bWF4MTBtMTA8LWV4bWF4MTBbMjc0OjMwNF07ICBleG1heDEwbTExPC1leG1heDEwWzMwNTozMzRdOyBleG1heDEwbTEyPC1leG1heDEwWzMzNTozNjVdDQogICAgICAgIA0KICAgICAgICBleG1heDkwPC1taWR2YWx1ZVssNF0tYWFzWywzXQ0KICAgICAgICBleG1heDkwbTE8LWV4bWF4OTBbMTozMV07ICAgICAgZXhtYXg5MG0yPC1leG1heDkwWzMyOjU5XTsgICAgZXhtYXg5MG0zPC1leG1heDkwWzYwOjkwXQ0KICAgICAgICBleG1heDkwbTQ8LWV4bWF4OTBbOTE6MTIwXTsgICAgZXhtYXg5MG01PC1leG1heDkwWzEyMToxNTFdOyAgZXhtYXg5MG02PC1leG1heDkwWzE1MjoxODFdDQogICAgICAgIGV4bWF4OTBtNzwtZXhtYXg5MFsxODI6MjEyXTsgICBleG1heDkwbTg8LWV4bWF4OTBbMjEzOjI0M107ICBleG1heDkwbTk8LWV4bWF4OTBbMjQ0OjI3M10NCiAgICAgICAgZXhtYXg5MG0xMDwtZXhtYXg5MFsyNzQ6MzA0XTsgIGV4bWF4OTBtMTE8LWV4bWF4OTBbMzA1OjMzNF07IGV4bWF4OTBtMTI8LWV4bWF4OTBbMzM1OjM2NV0NCiAgICAgICAgDQogICAgICAgIGV4bWluMTA8LW1pZHZhbHVlWyw1XS1hYXNbLDRdDQogICAgICAgIGV4bWluMTBtMTwtZXhtaW4xMFsxOjMxXTsgICAgICBleG1pbjEwbTI8LWV4bWluMTBbMzI6NTldOyAgICBleG1pbjEwbTM8LWV4bWluMTBbNjA6OTBdDQogICAgICAgIGV4bWluMTBtNDwtZXhtaW4xMFs5MToxMjBdOyAgICBleG1pbjEwbTU8LWV4bWluMTBbMTIxOjE1MV07ICBleG1pbjEwbTY8LWV4bWluMTBbMTUyOjE4MV0NCiAgICAgICAgZXhtaW4xMG03PC1leG1pbjEwWzE4MjoyMTJdOyAgIGV4bWluMTBtODwtZXhtaW4xMFsyMTM6MjQzXTsgIGV4bWluMTBtOTwtZXhtaW4xMFsyNDQ6MjczXQ0KICAgICAgICBleG1pbjEwbTEwPC1leG1pbjEwWzI3NDozMDRdOyAgZXhtaW4xMG0xMTwtZXhtaW4xMFszMDU6MzM0XTsgZXhtaW4xMG0xMjwtZXhtaW4xMFszMzU6MzY1XQ0KICAgICAgICANCiAgICAgICAgZXhtaW45MDwtbWlkdmFsdWVbLDVdLWFhc1ssNV0NCiAgICAgICAgZXhtaW45MG0xPC1leG1pbjkwWzE6MzFdOyAgICAgIGV4bWluOTBtMjwtZXhtaW45MFszMjo1OV07ICAgIGV4bWluOTBtMzwtZXhtaW45MFs2MDo5MF0NCiAgICAgICAgZXhtaW45MG00PC1leG1pbjkwWzkxOjEyMF07ICAgIGV4bWluOTBtNTwtZXhtaW45MFsxMjE6MTUxXTsgIGV4bWluOTBtNjwtZXhtaW45MFsxNTI6MTgxXQ0KICAgICAgICBleG1pbjkwbTc8LWV4bWluOTBbMTgyOjIxMl07ICAgZXhtaW45MG04PC1leG1pbjkwWzIxMzoyNDNdOyAgZXhtaW45MG05PC1leG1pbjkwWzI0NDoyNzNdDQogICAgICAgIGV4bWluOTBtMTA8LWV4bWluOTBbMjc0OjMwNF07ICBleG1pbjkwbTExPC1leG1pbjkwWzMwNTozMzRdOyBleG1pbjkwbTEyPC1leG1pbjkwWzMzNTozNjVdDQogICAgICAgIA0KICAgICAgICBiZFtpLCJ0eGcxMHAiXTwtbGVuZ3RoKGV4bWF4MTBbZXhtYXgxMDwwJmlzLm5hKGV4bWF4MTApPT1GXSkNCiAgICAgICAgYmRbaSwidHhnOTBwIl08LWxlbmd0aChleG1heDkwW2V4bWF4OTA+MCZpcy5uYShleG1heDkwKT09Rl0pDQogICAgICAgIGJkW2ksInRuZzEwcCJdPC1sZW5ndGgoZXhtaW4xMFtleG1pbjEwPDAmaXMubmEoZXhtaW4xMCk9PUZdKQ0KICAgICAgICBiZFtpLCJ0bmc5MHAiXTwtbGVuZ3RoKGV4bWluOTBbZXhtaW45MD4wJmlzLm5hKGV4bWluOTApPT1GXSkNCiAgICAgICAgDQogICAgICAgIGJtb25leFtqamo2LCJ0eDEwcCJdPC1sZW5ndGgoZXhtYXgxMG0xW2V4bWF4MTBtMTwwJmlzLm5hKGV4bWF4MTBtMSk9PUZdKQ0KICAgICAgICBibW9uZXhbampqNiwidHg5MHAiXTwtbGVuZ3RoKGV4bWF4OTBtMVtleG1heDkwbTE+MCZpcy5uYShleG1heDkwbTEpPT1GXSkNCiAgICAgICAgYm1vbmV4W2pqajYsInRuMTBwIl08LWxlbmd0aChleG1pbjEwbTFbZXhtaW4xMG0xPDAmaXMubmEoZXhtaW4xMG0xKT09Rl0pDQogICAgICAgIGJtb25leFtqamo2LCJ0bjkwcCJdPC1sZW5ndGgoZXhtaW45MG0xW2V4bWluOTBtMT4wJmlzLm5hKGV4bWluOTBtMSk9PUZdKQ0KICAgICAgICANCiAgICAgICAgYm1vbmV4W2pqajYrMSwidHgxMHAiXTwtbGVuZ3RoKGV4bWF4MTBtMltleG1heDEwbTI8MCZpcy5uYShleG1heDEwbTIpPT1GXSkNCiAgICAgICAgYm1vbmV4W2pqajYrMSwidHg5MHAiXTwtbGVuZ3RoKGV4bWF4OTBtMltleG1heDkwbTI+MCZpcy5uYShleG1heDkwbTIpPT1GXSkNCiAgICAgICAgYm1vbmV4W2pqajYrMSwidG4xMHAiXTwtbGVuZ3RoKGV4bWluMTBtMltleG1pbjEwbTI8MCZpcy5uYShleG1pbjEwbTIpPT1GXSkNCiAgICAgICAgYm1vbmV4W2pqajYrMSwidG45MHAiXTwtbGVuZ3RoKGV4bWluOTBtMltleG1pbjkwbTI+MCZpcy5uYShleG1pbjkwbTIpPT1GXSkgICANCiAgICAgICAgDQogICAgICAgIGJtb25leFtqamo2KzIsInR4MTBwIl08LWxlbmd0aChleG1heDEwbTNbZXhtYXgxMG0zPDAmaXMubmEoZXhtYXgxMG0zKT09Rl0pDQogICAgICAgIGJtb25leFtqamo2KzIsInR4OTBwIl08LWxlbmd0aChleG1heDkwbTNbZXhtYXg5MG0zPjAmaXMubmEoZXhtYXg5MG0zKT09Rl0pDQogICAgICAgIGJtb25leFtqamo2KzIsInRuMTBwIl08LWxlbmd0aChleG1pbjEwbTNbZXhtaW4xMG0zPDAmaXMubmEoZXhtaW4xMG0zKT09Rl0pDQogICAgICAgIGJtb25leFtqamo2KzIsInRuOTBwIl08LWxlbmd0aChleG1pbjkwbTNbZXhtaW45MG0zPjAmaXMubmEoZXhtaW45MG0zKT09Rl0pDQogICAgICAgIA0KICAgICAgICBibW9uZXhbampqNiszLCJ0eDEwcCJdPC1sZW5ndGgoZXhtYXgxMG00W2V4bWF4MTBtNDwwJmlzLm5hKGV4bWF4MTBtNCk9PUZdKQ0KICAgICAgICBibW9uZXhbampqNiszLCJ0eDkwcCJdPC1sZW5ndGgoZXhtYXg5MG00W2V4bWF4OTBtND4wJmlzLm5hKGV4bWF4OTBtNCk9PUZdKQ0KICAgICAgICBibW9uZXhbampqNiszLCJ0bjEwcCJdPC1sZW5ndGgoZXhtaW4xMG00W2V4bWluMTBtNDwwJmlzLm5hKGV4bWluMTBtNCk9PUZdKQ0KICAgICAgICBibW9uZXhbampqNiszLCJ0bjkwcCJdPC1sZW5ndGgoZXhtaW45MG00W2V4bWluOTBtND4wJmlzLm5hKGV4bWluOTBtNCk9PUZdKQ0KICAgICAgICANCiAgICAgICAgYm1vbmV4W2pqajYrNCwidHgxMHAiXTwtbGVuZ3RoKGV4bWF4MTBtNVtleG1heDEwbTU8MCZpcy5uYShleG1heDEwbTUpPT1GXSkNCiAgICAgICAgYm1vbmV4W2pqajYrNCwidHg5MHAiXTwtbGVuZ3RoKGV4bWF4OTBtNVtleG1heDkwbTU+MCZpcy5uYShleG1heDkwbTUpPT1GXSkNCiAgICAgICAgYm1vbmV4W2pqajYrNCwidG4xMHAiXTwtbGVuZ3RoKGV4bWluMTBtNVtleG1pbjEwbTU8MCZpcy5uYShleG1pbjEwbTUpPT1GXSkNCiAgICAgICAgYm1vbmV4W2pqajYrNCwidG45MHAiXTwtbGVuZ3RoKGV4bWluOTBtNVtleG1pbjkwbTU+MCZpcy5uYShleG1pbjkwbTUpPT1GXSkNCiAgICAgICAgDQogICAgICAgIGJtb25leFtqamo2KzUsInR4MTBwIl08LWxlbmd0aChleG1heDEwbTZbZXhtYXgxMG02PDAmaXMubmEoZXhtYXgxMG02KT09Rl0pDQogICAgICAgIGJtb25leFtqamo2KzUsInR4OTBwIl08LWxlbmd0aChleG1heDkwbTZbZXhtYXg5MG02PjAmaXMubmEoZXhtYXg5MG02KT09Rl0pDQogICAgICAgIGJtb25leFtqamo2KzUsInRuMTBwIl08LWxlbmd0aChleG1pbjEwbTZbZXhtaW4xMG02PDAmaXMubmEoZXhtaW4xMG02KT09Rl0pDQogICAgICAgIGJtb25leFtqamo2KzUsInRuOTBwIl08LWxlbmd0aChleG1pbjkwbTZbZXhtaW45MG02PjAmaXMubmEoZXhtaW45MG02KT09Rl0pDQogICAgICAgIA0KICAgICAgICBibW9uZXhbampqNis2LCJ0eDEwcCJdPC1sZW5ndGgoZXhtYXgxMG03W2V4bWF4MTBtNzwwJmlzLm5hKGV4bWF4MTBtNyk9PUZdKQ0KICAgICAgICBibW9uZXhbampqNis2LCJ0eDkwcCJdPC1sZW5ndGgoZXhtYXg5MG03W2V4bWF4OTBtNz4wJmlzLm5hKGV4bWF4OTBtNyk9PUZdKQ0KICAgICAgICBibW9uZXhbampqNis2LCJ0bjEwcCJdPC1sZW5ndGgoZXhtaW4xMG03W2V4bWluMTBtNzwwJmlzLm5hKGV4bWluMTBtNyk9PUZdKQ0KICAgICAgICBibW9uZXhbampqNis2LCJ0bjkwcCJdPC1sZW5ndGgoZXhtaW45MG03W2V4bWluOTBtNz4wJmlzLm5hKGV4bWluOTBtNyk9PUZdKQ0KICAgICAgICANCiAgICAgICAgYm1vbmV4W2pqajYrNywidHgxMHAiXTwtbGVuZ3RoKGV4bWF4MTBtOFtleG1heDEwbTg8MCZpcy5uYShleG1heDEwbTgpPT1GXSkNCiAgICAgICAgYm1vbmV4W2pqajYrNywidHg5MHAiXTwtbGVuZ3RoKGV4bWF4OTBtOFtleG1heDkwbTg+MCZpcy5uYShleG1heDkwbTgpPT1GXSkNCiAgICAgICAgYm1vbmV4W2pqajYrNywidG4xMHAiXTwtbGVuZ3RoKGV4bWluMTBtOFtleG1pbjEwbTg8MCZpcy5uYShleG1pbjEwbTgpPT1GXSkNCiAgICAgICAgYm1vbmV4W2pqajYrNywidG45MHAiXTwtbGVuZ3RoKGV4bWluOTBtOFtleG1pbjkwbTg+MCZpcy5uYShleG1pbjkwbTgpPT1GXSkNCiAgICAgICAgDQogICAgICAgIGJtb25leFtqamo2KzgsInR4MTBwIl08LWxlbmd0aChleG1heDEwbTlbZXhtYXgxMG05PDAmaXMubmEoZXhtYXgxMG05KT09Rl0pDQogICAgICAgIGJtb25leFtqamo2KzgsInR4OTBwIl08LWxlbmd0aChleG1heDkwbTlbZXhtYXg5MG05PjAmaXMubmEoZXhtYXg5MG05KT09Rl0pDQogICAgICAgIGJtb25leFtqamo2KzgsInRuMTBwIl08LWxlbmd0aChleG1pbjEwbTlbZXhtaW4xMG05PDAmaXMubmEoZXhtaW4xMG05KT09Rl0pDQogICAgICAgIGJtb25leFtqamo2KzgsInRuOTBwIl08LWxlbmd0aChleG1pbjkwbTlbZXhtaW45MG05PjAmaXMubmEoZXhtaW45MG05KT09Rl0pDQogICAgICAgIA0KICAgICAgICBibW9uZXhbampqNis5LCJ0eDEwcCJdPC1sZW5ndGgoZXhtYXgxMG0xMFtleG1heDEwbTEwPDAmaXMubmEoZXhtYXgxMG0xMCk9PUZdKQ0KICAgICAgICBibW9uZXhbampqNis5LCJ0eDkwcCJdPC1sZW5ndGgoZXhtYXg5MG0xMFtleG1heDkwbTEwPjAmaXMubmEoZXhtYXg5MG0xMCk9PUZdKQ0KICAgICAgICBibW9uZXhbampqNis5LCJ0bjEwcCJdPC1sZW5ndGgoZXhtaW4xMG0xMFtleG1pbjEwbTEwPDAmaXMubmEoZXhtaW4xMG0xMCk9PUZdKQ0KICAgICAgICBibW9uZXhbampqNis5LCJ0bjkwcCJdPC1sZW5ndGgoZXhtaW45MG0xMFtleG1pbjkwbTEwPjAmaXMubmEoZXhtaW45MG0xMCk9PUZdKQ0KICAgICAgICANCiAgICAgICAgYm1vbmV4W2pqajYrMTAsInR4MTBwIl08LWxlbmd0aChleG1heDEwbTExW2V4bWF4MTBtMTE8MCZpcy5uYShleG1heDEwbTExKT09Rl0pDQogICAgICAgIGJtb25leFtqamo2KzEwLCJ0eDkwcCJdPC1sZW5ndGgoZXhtYXg5MG0xMVtleG1heDkwbTExPjAmaXMubmEoZXhtYXg5MG0xMSk9PUZdKQ0KICAgICAgICBibW9uZXhbampqNisxMCwidG4xMHAiXTwtbGVuZ3RoKGV4bWluMTBtMTFbZXhtaW4xMG0xMTwwJmlzLm5hKGV4bWluMTBtMTEpPT1GXSkNCiAgICAgICAgYm1vbmV4W2pqajYrMTAsInRuOTBwIl08LWxlbmd0aChleG1pbjkwbTExW2V4bWluOTBtMTE+MCZpcy5uYShleG1pbjkwbTExKT09Rl0pDQogICAgICAgIA0KICAgICAgICBibW9uZXhbampqNisxMSwidHgxMHAiXTwtbGVuZ3RoKGV4bWF4MTBtMTJbZXhtYXgxMG0xMjwwJmlzLm5hKGV4bWF4MTBtMTIpPT1GXSkNCiAgICAgICAgYm1vbmV4W2pqajYrMTEsInR4OTBwIl08LWxlbmd0aChleG1heDkwbTEyW2V4bWF4OTBtMTI+MCZpcy5uYShleG1heDkwbTEyKT09Rl0pDQogICAgICAgIGJtb25leFtqamo2KzExLCJ0bjEwcCJdPC1sZW5ndGgoZXhtaW4xMG0xMltleG1pbjEwbTEyPDAmaXMubmEoZXhtaW4xMG0xMik9PUZdKQ0KICAgICAgICBibW9uZXhbampqNisxMSwidG45MHAiXTwtbGVuZ3RoKGV4bWluOTBtMTJbZXhtaW45MG0xMj4wJmlzLm5hKGV4bWluOTBtMTIpPT1GXSkNCiAgICAgICAgDQogICAgICAgIGlmKGxlYXB5ZWFyKHllYXIpKXsNCiAgICAgICAgICAgIGlmKGRkW2RkJHllYXI9PXllYXImZGQkbW9udGg9PTImZGQkZGF5PT0yOSwidG1heCJdPmFhc1s1OSwicGNtYXg5MCJdJmlzLm5hKGRkW2RkJHllYXI9PXllYXImZGQkbW9udGg9PTImZGQkZGF5PT0yOSwidG1heCJdKT09RiZpcy5uYShhYXNbNTksInBjbWF4OTAiXSk9PUYpDQogICAgICAgICAgICAgICAgYm1vbmV4W2pqajYrMSwidHg5MHAiXTwtYm1vbmV4W2pqajYrMSwidHg5MHAiXSsxDQogICAgICAgICAgICBpZihkZFtkZCR5ZWFyPT15ZWFyJmRkJG1vbnRoPT0yJmRkJGRheT09MjksInRtYXgiXTxhYXNbNTksInBjbWF4MTAiXSZpcy5uYShkZFtkZCR5ZWFyPT15ZWFyJmRkJG1vbnRoPT0yJmRkJGRheT09MjksInRtYXgiXSk9PUYmaXMubmEoYWFzWzU5LCJwY21heDEwIl0pPT1GKQ0KICAgICAgICAgICAgICAgIGJtb25leFtqamo2KzEsInR4MTBwIl08LWJtb25leFtqamo2KzEsInR4MTBwIl0rMQ0KICAgICAgICAgICAgaWYoZGRbZGQkeWVhcj09eWVhciZkZCRtb250aD09MiZkZCRkYXk9PTI5LCJ0bWluIl0+YWFzWzU5LCJwY21pbjkwIl0maXMubmEoZGRbZGQkeWVhcj09eWVhciZkZCRtb250aD09MiZkZCRkYXk9PTI5LCJ0bWluIl0pPT1GJmlzLm5hKGFhc1s1OSwicGNtaW45MCJdKT09RikNCiAgICAgICAgICAgICAgICBibW9uZXhbampqNisxLCJ0bjkwcCJdPC1ibW9uZXhbampqNisxLCJ0bjkwcCJdKzENCiAgICAgICAgICAgIGlmKGRkW2RkJHllYXI9PXllYXImZGQkbW9udGg9PTImZGQkZGF5PT0yOSwidG1pbiJdPGFhc1s1OSwicGNtaW4xMCJdJmlzLm5hKGRkW2RkJHllYXI9PXllYXImZGQkbW9udGg9PTImZGQkZGF5PT0yOSwidG1pbiJdKT09RiZpcy5uYShhYXNbNTksInBjbWluMTAiXSk9PUYpDQogICAgICAgICAgICAgICAgYm1vbmV4W2pqajYrMSwidG4xMHAiXTwtYm1vbmV4W2pqajYrMSwidG4xMHAiXSsxDQogICAgICAgIH0NCiAgICAgICAgDQogICAgICAgIGpqajY8LWpqajYrMTINCiAgICAgICAgeWVhcj15ZWFyKzEgICAgIA0KICAgIH0NCiAgICANCiAgICB5ZWFyPWVuZHllYXIrMTtqamo2PTENCiAgICBmb3IgKGkgaW4gMTp5czIpew0KICAgICAgICBtaWR2YWx1ZTwtZGR0ZW1bZGR0ZW0keWVhcj09eWVhcixdDQogICAgICAgIGV4bWF4MTA8LW1pZHZhbHVlWyw0XS1hYXNbLDJdDQogICAgICAgIGV4bWF4MTBtMTwtZXhtYXgxMFsxOjMxXTsgICAgIGV4bWF4MTBtMjwtZXhtYXgxMFszMjo1OV07ICAgIGV4bWF4MTBtMzwtZXhtYXgxMFs2MDo5MF0NCiAgICAgICAgZXhtYXgxMG00PC1leG1heDEwWzkxOjEyMF07ICAgZXhtYXgxMG01PC1leG1heDEwWzEyMToxNTFdOyAgZXhtYXgxMG02PC1leG1heDEwWzE1MjoxODFdDQogICAgICAgIGV4bWF4MTBtNzwtZXhtYXgxMFsxODI6MjEyXTsgIGV4bWF4MTBtODwtZXhtYXgxMFsyMTM6MjQzXTsgIGV4bWF4MTBtOTwtZXhtYXgxMFsyNDQ6MjczXQ0KICAgICAgICBleG1heDEwbTEwPC1leG1heDEwWzI3NDozMDRdOyBleG1heDEwbTExPC1leG1heDEwWzMwNTozMzRdOyBleG1heDEwbTEyPC1leG1heDEwWzMzNTozNjVdDQogICAgICAgIA0KICAgICAgICBleG1heDkwPC1taWR2YWx1ZVssNF0tYWFzWywzXQ0KICAgICAgICBleG1heDkwbTE8LWV4bWF4OTBbMTozMV07ICAgICBleG1heDkwbTI8LWV4bWF4OTBbMzI6NTldOyAgICBleG1heDkwbTM8LWV4bWF4OTBbNjA6OTBdDQogICAgICAgIGV4bWF4OTBtNDwtZXhtYXg5MFs5MToxMjBdOyAgIGV4bWF4OTBtNTwtZXhtYXg5MFsxMjE6MTUxXTsgIGV4bWF4OTBtNjwtZXhtYXg5MFsxNTI6MTgxXQ0KICAgICAgICBleG1heDkwbTc8LWV4bWF4OTBbMTgyOjIxMl07ICBleG1heDkwbTg8LWV4bWF4OTBbMjEzOjI0M107ICBleG1heDkwbTk8LWV4bWF4OTBbMjQ0OjI3M10NCiAgICAgICAgZXhtYXg5MG0xMDwtZXhtYXg5MFsyNzQ6MzA0XTsgZXhtYXg5MG0xMTwtZXhtYXg5MFszMDU6MzM0XTsgZXhtYXg5MG0xMjwtZXhtYXg5MFszMzU6MzY1XQ0KICAgICAgICANCiAgICAgICAgZXhtaW4xMDwtbWlkdmFsdWVbLDVdLWFhc1ssNF0NCiAgICAgICAgZXhtaW4xMG0xPC1leG1pbjEwWzE6MzFdOyAgICAgZXhtaW4xMG0yPC1leG1pbjEwWzMyOjU5XTsgICAgZXhtaW4xMG0zPC1leG1pbjEwWzYwOjkwXQ0KICAgICAgICBleG1pbjEwbTQ8LWV4bWluMTBbOTE6MTIwXTsgICBleG1pbjEwbTU8LWV4bWluMTBbMTIxOjE1MV07ICBleG1pbjEwbTY8LWV4bWluMTBbMTUyOjE4MV0NCiAgICAgICAgZXhtaW4xMG03PC1leG1pbjEwWzE4MjoyMTJdOyAgZXhtaW4xMG04PC1leG1pbjEwWzIxMzoyNDNdOyAgZXhtaW4xMG05PC1leG1pbjEwWzI0NDoyNzNdDQogICAgICAgIGV4bWluMTBtMTA8LWV4bWluMTBbMjc0OjMwNF07IGV4bWluMTBtMTE8LWV4bWluMTBbMzA1OjMzNF07IGV4bWluMTBtMTI8LWV4bWluMTBbMzM1OjM2NV0NCiAgICAgICAgDQogICAgICAgIGV4bWluOTA8LW1pZHZhbHVlWyw1XS1hYXNbLDVdDQogICAgICAgIGV4bWluOTBtMTwtZXhtaW45MFsxOjMxXTsgICAgIGV4bWluOTBtMjwtZXhtaW45MFszMjo1OV07ICAgIGV4bWluOTBtMzwtZXhtaW45MFs2MDo5MF0NCiAgICAgICAgZXhtaW45MG00PC1leG1pbjkwWzkxOjEyMF07ICAgZXhtaW45MG01PC1leG1pbjkwWzEyMToxNTFdOyAgZXhtaW45MG02PC1leG1pbjkwWzE1MjoxODFdDQogICAgICAgIGV4bWluOTBtNzwtZXhtaW45MFsxODI6MjEyXTsgIGV4bWluOTBtODwtZXhtaW45MFsyMTM6MjQzXTsgIGV4bWluOTBtOTwtZXhtaW45MFsyNDQ6MjczXQ0KICAgICAgICBleG1pbjkwbTEwPC1leG1pbjkwWzI3NDozMDRdOyBleG1pbjkwbTExPC1leG1pbjkwWzMwNTozMzRdOyBleG1pbjkwbTEyPC1leG1pbjkwWzMzNTozNjVdDQogICAgICAgIA0KICAgICAgICBhZFtpLCJ0eGcxMHAiXTwtbGVuZ3RoKGV4bWF4MTBbZXhtYXgxMDwwJmlzLm5hKGV4bWF4MTApPT1GXSkNCiAgICAgICAgYWRbaSwidHhnOTBwIl08LWxlbmd0aChleG1heDkwW2V4bWF4OTA+MCZpcy5uYShleG1heDkwKT09Rl0pDQogICAgICAgIGFkW2ksInRuZzEwcCJdPC1sZW5ndGgoZXhtaW4xMFtleG1pbjEwPDAmaXMubmEoZXhtaW4xMCk9PUZdKQ0KICAgICAgICBhZFtpLCJ0bmc5MHAiXTwtbGVuZ3RoKGV4bWluOTBbZXhtaW45MD4wJmlzLm5hKGV4bWluOTApPT1GXSkNCiAgICAgICAgDQogICAgICAgIGFtb25leFtqamo2LCJ0eDEwcCJdPC1sZW5ndGgoZXhtYXgxMG0xW2V4bWF4MTBtMTwwJmlzLm5hKGV4bWF4MTBtMSk9PUZdKQ0KICAgICAgICBhbW9uZXhbampqNiwidHg5MHAiXTwtbGVuZ3RoKGV4bWF4OTBtMVtleG1heDkwbTE+MCZpcy5uYShleG1heDkwbTEpPT1GXSkNCiAgICAgICAgYW1vbmV4W2pqajYsInRuMTBwIl08LWxlbmd0aChleG1pbjEwbTFbZXhtaW4xMG0xPDAmaXMubmEoZXhtaW4xMG0xKT09Rl0pDQogICAgICAgIGFtb25leFtqamo2LCJ0bjkwcCJdPC1sZW5ndGgoZXhtaW45MG0xW2V4bWluOTBtMT4wJmlzLm5hKGV4bWluOTBtMSk9PUZdKQ0KICAgICAgICANCiAgICAgICAgYW1vbmV4W2pqajYrMSwidHgxMHAiXTwtbGVuZ3RoKGV4bWF4MTBtMltleG1heDEwbTI8MCZpcy5uYShleG1heDEwbTIpPT1GXSkNCiAgICAgICAgYW1vbmV4W2pqajYrMSwidHg5MHAiXTwtbGVuZ3RoKGV4bWF4OTBtMltleG1heDkwbTI+MCZpcy5uYShleG1heDkwbTIpPT1GXSkNCiAgICAgICAgYW1vbmV4W2pqajYrMSwidG4xMHAiXTwtbGVuZ3RoKGV4bWluMTBtMltleG1pbjEwbTI8MCZpcy5uYShleG1pbjEwbTIpPT1GXSkNCiAgICAgICAgYW1vbmV4W2pqajYrMSwidG45MHAiXTwtbGVuZ3RoKGV4bWluOTBtMltleG1pbjkwbTI+MCZpcy5uYShleG1pbjkwbTIpPT1GXSkgICANCiAgICAgICAgDQogICAgICAgIGFtb25leFtqamo2KzIsInR4MTBwIl08LWxlbmd0aChleG1heDEwbTNbZXhtYXgxMG0zPDAmaXMubmEoZXhtYXgxMG0zKT09Rl0pDQogICAgICAgIGFtb25leFtqamo2KzIsInR4OTBwIl08LWxlbmd0aChleG1heDkwbTNbZXhtYXg5MG0zPjAmaXMubmEoZXhtYXg5MG0zKT09Rl0pDQogICAgICAgIGFtb25leFtqamo2KzIsInRuMTBwIl08LWxlbmd0aChleG1pbjEwbTNbZXhtaW4xMG0zPDAmaXMubmEoZXhtaW4xMG0zKT09Rl0pDQogICAgICAgIGFtb25leFtqamo2KzIsInRuOTBwIl08LWxlbmd0aChleG1pbjkwbTNbZXhtaW45MG0zPjAmaXMubmEoZXhtaW45MG0zKT09Rl0pDQogICAgICAgIA0KICAgICAgICBhbW9uZXhbampqNiszLCJ0eDEwcCJdPC1sZW5ndGgoZXhtYXgxMG00W2V4bWF4MTBtNDwwJmlzLm5hKGV4bWF4MTBtNCk9PUZdKQ0KICAgICAgICBhbW9uZXhbampqNiszLCJ0eDkwcCJdPC1sZW5ndGgoZXhtYXg5MG00W2V4bWF4OTBtND4wJmlzLm5hKGV4bWF4OTBtNCk9PUZdKQ0KICAgICAgICBhbW9uZXhbampqNiszLCJ0bjEwcCJdPC1sZW5ndGgoZXhtaW4xMG00W2V4bWluMTBtNDwwJmlzLm5hKGV4bWluMTBtNCk9PUZdKQ0KICAgICAgICBhbW9uZXhbampqNiszLCJ0bjkwcCJdPC1sZW5ndGgoZXhtaW45MG00W2V4bWluOTBtND4wJmlzLm5hKGV4bWluOTBtNCk9PUZdKQ0KICAgICAgICANCiAgICAgICAgYW1vbmV4W2pqajYrNCwidHgxMHAiXTwtbGVuZ3RoKGV4bWF4MTBtNVtleG1heDEwbTU8MCZpcy5uYShleG1heDEwbTUpPT1GXSkNCiAgICAgICAgYW1vbmV4W2pqajYrNCwidHg5MHAiXTwtbGVuZ3RoKGV4bWF4OTBtNVtleG1heDkwbTU+MCZpcy5uYShleG1heDkwbTUpPT1GXSkNCiAgICAgICAgYW1vbmV4W2pqajYrNCwidG4xMHAiXTwtbGVuZ3RoKGV4bWluMTBtNVtleG1pbjEwbTU8MCZpcy5uYShleG1pbjEwbTUpPT1GXSkNCiAgICAgICAgYW1vbmV4W2pqajYrNCwidG45MHAiXTwtbGVuZ3RoKGV4bWluOTBtNVtleG1pbjkwbTU+MCZpcy5uYShleG1pbjkwbTUpPT1GXSkNCiAgICAgICAgDQogICAgICAgIGFtb25leFtqamo2KzUsInR4MTBwIl08LWxlbmd0aChleG1heDEwbTZbZXhtYXgxMG02PDAmaXMubmEoZXhtYXgxMG02KT09Rl0pDQogICAgICAgIGFtb25leFtqamo2KzUsInR4OTBwIl08LWxlbmd0aChleG1heDkwbTZbZXhtYXg5MG02PjAmaXMubmEoZXhtYXg5MG02KT09Rl0pDQogICAgICAgIGFtb25leFtqamo2KzUsInRuMTBwIl08LWxlbmd0aChleG1pbjEwbTZbZXhtaW4xMG02PDAmaXMubmEoZXhtaW4xMG02KT09Rl0pDQogICAgICAgIGFtb25leFtqamo2KzUsInRuOTBwIl08LWxlbmd0aChleG1pbjkwbTZbZXhtaW45MG02PjAmaXMubmEoZXhtaW45MG02KT09Rl0pDQogICAgICAgIA0KICAgICAgICBhbW9uZXhbampqNis2LCJ0eDEwcCJdPC1sZW5ndGgoZXhtYXgxMG03W2V4bWF4MTBtNzwwJmlzLm5hKGV4bWF4MTBtNyk9PUZdKQ0KICAgICAgICBhbW9uZXhbampqNis2LCJ0eDkwcCJdPC1sZW5ndGgoZXhtYXg5MG03W2V4bWF4OTBtNz4wJmlzLm5hKGV4bWF4OTBtNyk9PUZdKQ0KICAgICAgICBhbW9uZXhbampqNis2LCJ0bjEwcCJdPC1sZW5ndGgoZXhtaW4xMG03W2V4bWluMTBtNzwwJmlzLm5hKGV4bWluMTBtNyk9PUZdKQ0KICAgICAgICBhbW9uZXhbampqNis2LCJ0bjkwcCJdPC1sZW5ndGgoZXhtaW45MG03W2V4bWluOTBtNz4wJmlzLm5hKGV4bWluOTBtNyk9PUZdKQ0KICAgICAgICANCiAgICAgICAgYW1vbmV4W2pqajYrNywidHgxMHAiXTwtbGVuZ3RoKGV4bWF4MTBtOFtleG1heDEwbTg8MCZpcy5uYShleG1heDEwbTgpPT1GXSkNCiAgICAgICAgYW1vbmV4W2pqajYrNywidHg5MHAiXTwtbGVuZ3RoKGV4bWF4OTBtOFtleG1heDkwbTg+MCZpcy5uYShleG1heDkwbTgpPT1GXSkNCiAgICAgICAgYW1vbmV4W2pqajYrNywidG4xMHAiXTwtbGVuZ3RoKGV4bWluMTBtOFtleG1pbjEwbTg8MCZpcy5uYShleG1pbjEwbTgpPT1GXSkNCiAgICAgICAgYW1vbmV4W2pqajYrNywidG45MHAiXTwtbGVuZ3RoKGV4bWluOTBtOFtleG1pbjkwbTg+MCZpcy5uYShleG1pbjkwbTgpPT1GXSkNCiAgICAgICAgDQogICAgICAgIGFtb25leFtqamo2KzgsInR4MTBwIl08LWxlbmd0aChleG1heDEwbTlbZXhtYXgxMG05PDAmaXMubmEoZXhtYXgxMG05KT09Rl0pDQogICAgICAgIGFtb25leFtqamo2KzgsInR4OTBwIl08LWxlbmd0aChleG1heDkwbTlbZXhtYXg5MG05PjAmaXMubmEoZXhtYXg5MG05KT09Rl0pDQogICAgICAgIGFtb25leFtqamo2KzgsInRuMTBwIl08LWxlbmd0aChleG1pbjEwbTlbZXhtaW4xMG05PDAmaXMubmEoZXhtaW4xMG05KT09Rl0pDQogICAgICAgIGFtb25leFtqamo2KzgsInRuOTBwIl08LWxlbmd0aChleG1pbjkwbTlbZXhtaW45MG05PjAmaXMubmEoZXhtaW45MG05KT09Rl0pDQogICAgICAgIA0KICAgICAgICBhbW9uZXhbampqNis5LCJ0eDEwcCJdPC1sZW5ndGgoZXhtYXgxMG0xMFtleG1heDEwbTEwPDAmaXMubmEoZXhtYXgxMG0xMCk9PUZdKQ0KICAgICAgICBhbW9uZXhbampqNis5LCJ0eDkwcCJdPC1sZW5ndGgoZXhtYXg5MG0xMFtleG1heDkwbTEwPjAmaXMubmEoZXhtYXg5MG0xMCk9PUZdKQ0KICAgICAgICBhbW9uZXhbampqNis5LCJ0bjEwcCJdPC1sZW5ndGgoZXhtaW4xMG0xMFtleG1pbjEwbTEwPDAmaXMubmEoZXhtaW4xMG0xMCk9PUZdKQ0KICAgICAgICBhbW9uZXhbampqNis5LCJ0bjkwcCJdPC1sZW5ndGgoZXhtaW45MG0xMFtleG1pbjkwbTEwPjAmaXMubmEoZXhtaW45MG0xMCk9PUZdKQ0KICAgICAgICANCiAgICAgICAgYW1vbmV4W2pqajYrMTAsInR4MTBwIl08LWxlbmd0aChleG1heDEwbTExW2V4bWF4MTBtMTE8MCZpcy5uYShleG1heDEwbTExKT09Rl0pDQogICAgICAgIGFtb25leFtqamo2KzEwLCJ0eDkwcCJdPC1sZW5ndGgoZXhtYXg5MG0xMVtleG1heDkwbTExPjAmaXMubmEoZXhtYXg5MG0xMSk9PUZdKQ0KICAgICAgICBhbW9uZXhbampqNisxMCwidG4xMHAiXTwtbGVuZ3RoKGV4bWluMTBtMTFbZXhtaW4xMG0xMTwwJmlzLm5hKGV4bWluMTBtMTEpPT1GXSkNCiAgICAgICAgYW1vbmV4W2pqajYrMTAsInRuOTBwIl08LWxlbmd0aChleG1pbjkwbTExW2V4bWluOTBtMTE+MCZpcy5uYShleG1pbjkwbTExKT09Rl0pDQogICAgICAgIA0KICAgICAgICBhbW9uZXhbampqNisxMSwidHgxMHAiXTwtbGVuZ3RoKGV4bWF4MTBtMTJbZXhtYXgxMG0xMjwwJmlzLm5hKGV4bWF4MTBtMTIpPT1GXSkNCiAgICAgICAgYW1vbmV4W2pqajYrMTEsInR4OTBwIl08LWxlbmd0aChleG1heDkwbTEyW2V4bWF4OTBtMTI+MCZpcy5uYShleG1heDkwbTEyKT09Rl0pDQogICAgICAgIGFtb25leFtqamo2KzExLCJ0bjEwcCJdPC1sZW5ndGgoZXhtaW4xMG0xMltleG1pbjEwbTEyPDAmaXMubmEoZXhtaW4xMG0xMik9PUZdKQ0KICAgICAgICBhbW9uZXhbampqNisxMSwidG45MHAiXTwtbGVuZ3RoKGV4bWluOTBtMTJbZXhtaW45MG0xMj4wJmlzLm5hKGV4bWluOTBtMTIpPT1GXSkNCiAgICAgICAgDQogICAgICAgIGlmKGxlYXB5ZWFyKHllYXIpKXsNCiAgICAgICAgICAgIGlmKGRkW2RkJHllYXI9PXllYXImZGQkbW9udGg9PTImZGQkZGF5PT0yOSwidG1heCJdPmFhc1s1OSwicGNtYXg5MCJdJmlzLm5hKGRkW2RkJHllYXI9PXllYXImZGQkbW9udGg9PTImZGQkZGF5PT0yOSwidG1heCJdKT09RiZpcy5uYShhYXNbNTksInBjbWF4OTAiXSk9PUYpDQogICAgICAgICAgICAgICAgYW1vbmV4W2pqajYrMSwidHg5MHAiXTwtYW1vbmV4W2pqajYrMSwidHg5MHAiXSsxDQogICAgICAgICAgICBpZihkZFtkZCR5ZWFyPT15ZWFyJmRkJG1vbnRoPT0yJmRkJGRheT09MjksInRtYXgiXTxhYXNbNTksInBjbWF4MTAiXSZpcy5uYShkZFtkZCR5ZWFyPT15ZWFyJmRkJG1vbnRoPT0yJmRkJGRheT09MjksInRtYXgiXSk9PUYmaXMubmEoYWFzWzU5LCJwY21heDEwIl0pPT1GKQ0KICAgICAgICAgICAgICAgIGFtb25leFtqamo2KzEsInR4MTBwIl08LWFtb25leFtqamo2KzEsInR4MTBwIl0rMQ0KICAgICAgICAgICAgaWYoZGRbZGQkeWVhcj09eWVhciZkZCRtb250aD09MiZkZCRkYXk9PTI5LCJ0bWluIl0+YWFzWzU5LCJwY21pbjkwIl0maXMubmEoZGRbZGQkeWVhcj09eWVhciZkZCRtb250aD09MiZkZCRkYXk9PTI5LCJ0bWluIl0pPT1GJmlzLm5hKGFhc1s1OSwicGNtaW45MCJdKT09RikNCiAgICAgICAgICAgICAgICBhbW9uZXhbampqNisxLCJ0bjkwcCJdPC1hbW9uZXhbampqNisxLCJ0bjkwcCJdKzENCiAgICAgICAgICAgIGlmKGRkW2RkJHllYXI9PXllYXImZGQkbW9udGg9PTImZGQkZGF5PT0yOSwidG1pbiJdPGFhc1s1OSwicGNtaW4xMCJdJmlzLm5hKGRkW2RkJHllYXI9PXllYXImZGQkbW9udGg9PTImZGQkZGF5PT0yOSwidG1pbiJdKT09RiZpcy5uYShhYXNbNTksInBjbWluMTAiXSk9PUYpDQogICAgICAgICAgICAgICAgYW1vbmV4W2pqajYrMSwidG4xMHAiXTwtYW1vbmV4W2pqajYrMSwidG4xMHAiXSsxDQogICAgICAgIH0NCiAgICAgICAgDQogICAgICAgIGpqajY8LWpqajYrMTINCiAgICAgICAgeWVhcj15ZWFyKzEgICB9DQogICAgYmRtPC1tZXJnZShibW9uZXgsYmQsYnk9InllYXIiKTsgIGFzc2lnbigiYmRtIixiZG0sZW52aXI9Lkdsb2JhbEVudikNCiAgICBhZG08LW1lcmdlKGFtb25leCxhZCxieT0ieWVhciIpOyAgYXNzaWduKCJhZG0iLGFkbSxlbnZpcj0uR2xvYmFsRW52KQ0KICAgIA0KfSAjIGVuZCBvZiBub3JkYXl0ZW0xIGZ1bmN0aW9uDQojLS0tLS0tLS0tLS0gbm9yZGF5dGVtMSBlbmRzIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tDQoNCiMtLS0tLS0tLS0tLSBub3JkYXl0ZW0gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0NCm5vcmRheXRlbTwtZnVuY3Rpb24oKXsNCiAgICBuYW0xPC1wYXN0ZShuYW1hLCJfREFZTk9SLmNzdiIsc2VwPSIiKQ0KICAgIHdyaXRlLnRhYmxlKGRheW5vcixmaWxlPW5hbTEsYXBwZW5kPUYscXVvdGU9RixzZXA9IiwgIixyb3cubmFtZXM9RikNCn0NCiMtLS0tLS0tLS0tLSBub3JkYXl0ZW0gZW5kcyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQ0KDQojLS0tLS0tLS0tLS0gZHRyIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tDQpkdHI8LWZ1bmN0aW9uKCl7IyBkYXkgdGVtcGVyYXR1cmUgcmFuZ2UobW9udGhseSBhdmVyYWdlKSANCiAgICBsZW48LXllYXJlLXllYXJzKzENCiAgICBhYTE8LW1hdHJpeChOQSwxMipsZW4sMykNCiAgICBkaW1uYW1lcyhhYTEpPC1saXN0KE5VTEwsYygieWVhciIsIm1vbnRoIiwiZHRyIikpDQogICAgYWExWywieWVhciJdPC15ZWFyczp5ZWFyZQ0KICAgIGFhMVssInllYXIiXTwtbXlzb3J0KGFhMVssInllYXIiXSxkZWNyZWFzaW5nPUYpDQogICAgYWExWywibW9udGgiXTwtMToxMg0KICAgIHRlbXJhbmdlPC1kZFssInRtYXgiXS1kZFssInRtaW4iXQ0KICAgIHRlbXJhbmdlPC1jYmluZChkZFssMToyXSx0ZW1yYW5nZSkNCiAgICBqamoxPC0xDQogICAgZm9yICh5ZWFyIGluIHllYXJzOnllYXJlKXsgICAgIyBzdGFydCB5ZWFyIGxvb3ANCiAgICAgICAgdGVtcmFuZ2UxPC10ZW1yYW5nZVt0ZW1yYW5nZSR5ZWFyPT15ZWFyLF0NCiAgICAgICAgdGVtcmFuZ2VtMTwtdGVtcmFuZ2UxW3RlbXJhbmdlMSRtb250aD09MSwidGVtcmFuZ2UiXQ0KICAgICAgICB0ZW1yYW5nZW0yPC10ZW1yYW5nZTFbdGVtcmFuZ2UxJG1vbnRoPT0yLCJ0ZW1yYW5nZSJdDQogICAgICAgIHRlbXJhbmdlbTM8LXRlbXJhbmdlMVt0ZW1yYW5nZTEkbW9udGg9PTMsInRlbXJhbmdlIl0NCiAgICAgICAgdGVtcmFuZ2VtNDwtdGVtcmFuZ2UxW3RlbXJhbmdlMSRtb250aD09NCwidGVtcmFuZ2UiXQ0KICAgICAgICB0ZW1yYW5nZW01PC10ZW1yYW5nZTFbdGVtcmFuZ2UxJG1vbnRoPT01LCJ0ZW1yYW5nZSJdDQogICAgICAgIHRlbXJhbmdlbTY8LXRlbXJhbmdlMVt0ZW1yYW5nZTEkbW9udGg9PTYsInRlbXJhbmdlIl0NCiAgICAgICAgdGVtcmFuZ2VtNzwtdGVtcmFuZ2UxW3RlbXJhbmdlMSRtb250aD09NywidGVtcmFuZ2UiXQ0KICAgICAgICB0ZW1yYW5nZW04PC10ZW1yYW5nZTFbdGVtcmFuZ2UxJG1vbnRoPT04LCJ0ZW1yYW5nZSJdDQogICAgICAgIHRlbXJhbmdlbTk8LXRlbXJhbmdlMVt0ZW1yYW5nZTEkbW9udGg9PTksInRlbXJhbmdlIl0NCiAgICAgICAgdGVtcmFuZ2VtMTA8LXRlbXJhbmdlMVt0ZW1yYW5nZTEkbW9udGg9PTEwLCJ0ZW1yYW5nZSJdDQogICAgICAgIHRlbXJhbmdlbTExPC10ZW1yYW5nZTFbdGVtcmFuZ2UxJG1vbnRoPT0xMSwidGVtcmFuZ2UiXQ0KICAgICAgICB0ZW1yYW5nZW0xMjwtdGVtcmFuZ2UxW3RlbXJhbmdlMSRtb250aD09MTIsInRlbXJhbmdlIl0NCiAgICAgICAgYWExW2pqajEsM108LW1lYW4odGVtcmFuZ2VtMSxuYS5ybT1UKTsgICAgIGFhMVtqamoxKzEsM108LW1lYW4odGVtcmFuZ2VtMixuYS5ybT1UKQ0KICAgICAgICBhYTFbampqMSsyLDNdPC1tZWFuKHRlbXJhbmdlbTMsbmEucm09VCk7ICAgYWExW2pqajErMywzXTwtbWVhbih0ZW1yYW5nZW00LG5hLnJtPVQpDQogICAgICAgIGFhMVtqamoxKzQsM108LW1lYW4odGVtcmFuZ2VtNSxuYS5ybT1UKTsgICBhYTFbampqMSs1LDNdPC1tZWFuKHRlbXJhbmdlbTYsbmEucm09VCkNCiAgICAgICAgYWExW2pqajErNiwzXTwtbWVhbih0ZW1yYW5nZW03LG5hLnJtPVQpOyAgIGFhMVtqamoxKzcsM108LW1lYW4odGVtcmFuZ2VtOCxuYS5ybT1UKQ0KICAgICAgICBhYTFbampqMSs4LDNdPC1tZWFuKHRlbXJhbmdlbTksbmEucm09VCk7ICAgYWExW2pqajErOSwzXTwtbWVhbih0ZW1yYW5nZW0xMCxuYS5ybT1UKQ0KICAgICAgICBhYTFbampqMSsxMCwzXTwtbWVhbih0ZW1yYW5nZW0xMSxuYS5ybT1UKTsgYWExW2pqajErMTEsM108LW1lYW4odGVtcmFuZ2VtMTIsbmEucm09VCkNCiAgICAgICAgampqMTwtampqMSsxMn0gICAgICAgICAgICAgICAjZW5kIG9mIHllYXIgbG9vcA0KICAgIA0KICAgIGFhMVssImR0ciJdPC1hYTFbLCJkdHIiXStuYWNvclssIm1uYXRtYT4zIl0rbmFjb3JbLCJtbmF0bWk+MyJdDQogICAgb2ZpbGU8LW1hdHJpeCgwLGxlbiwxNCkNCiAgICBkaW1uYW1lcyhvZmlsZSk8LWxpc3QoTlVMTCxjKCJ5ZWFyIiwiamFuIiwiZmViIiwibWFyIiwiYXByIiwibWF5IiwianVuIiwianVsIiwiYXVnIiwic2VwIiwib2N0Iiwibm92IiwiZGVjIiwiYW5udWFsIikpDQogICAgb2ZpbGU8LWFzLmRhdGEuZnJhbWUob2ZpbGUpDQogICAgZm9yKGogaW4geWVhcnM6eWVhcmUpew0KICAgICAgICBrPC1qLXllYXJzKzENCiAgICAgICAgb2ZpbGVbaywxXTwtag0KICAgICAgICBvZmlsZVtrLDI6MTNdPC1yb3VuZChhYTFbYWExWywieWVhciJdPT1qLCJkdHIiXSxkaWdpdD0yKQ0KICAgICAgICBvZmlsZVtrLDE0XTwtcm91bmQobWVhbih0KG9maWxlW2ssMjoxM10pLG5hLnJtPVQpLGRpZ2l0PTIpDQogICAgfQ0KICAgIG9maWxlWywxNF08LW9maWxlWywxNF0reW5hY29yWywieW5hdG1hPjE1Il0reW5hY29yWywieW5hdG1pPjE1Il0NCiAgICBuYW0xPC1wYXN0ZShvdXRpbmRkaXIscGFzdGUob2ZpbGVuYW1lLCJfRFRSLmNzdiIsc2VwPSIiKSxzZXA9Ii8iKQ0KICAgIHdyaXRlLnRhYmxlKG9maWxlLGZpbGU9bmFtMSxhcHBlbmQ9RixxdW90ZT1GLHNlcD0iLCAiLG5hPSItOTkuOSIscm93Lm5hbWVzPUYpDQogICAgDQogICAgbmFtdDwtcGFzdGUob3V0dHJkZGlyLHBhc3RlKG9maWxlbmFtZSwiX3RyZW5kLmNzdiIsc2VwPSIiKSxzZXA9Ii8iKQ0KICAgIGlmKHN1bShpcy5uYShvZmlsZVssMTRdKSk+PSh5ZWFyZS15ZWFycysxLTEwKSl7DQogICAgICAgIGJldGFoYXQ8LU5BDQogICAgICAgIGJldGFzdGQ8LU5BDQogICAgICAgIHB2YWx1ZTwtTkENCiAgICB9DQogICAgZWxzZXsNCiAgICAgICAgZml0MTwtbHNmaXQob2ZpbGVbLDFdLG9maWxlWywxNF0pDQogICAgICAgIG91dDE8LWxzLnByaW50KGZpdDEscHJpbnQuaXQ9RikNCiAgICAgICAgcHZhbHVlPC1yb3VuZChhcy5udW1lcmljKG91dDEkc3VtbWFyeVsxLDZdKSwzKQ0KICAgICAgICBiZXRhaGF0PC1yb3VuZChhcy5udW1lcmljKG91dDEkY29lZi50YWJsZVtbMV1dWzIsMV0pLDMpDQogICAgICAgIGJldGFzdGQ8LXJvdW5kKGFzLm51bWVyaWMob3V0MSRjb2VmLnRhYmxlW1sxXV1bMiwyXSksMykNCiAgICB9DQogICAgY2F0KGZpbGU9bmFtdCxwYXN0ZShsYXRpdHVkZSxsb25naXR1ZGUsImR0ciIseWVhcnMseWVhcmUsYmV0YWhhdCxiZXRhc3RkLHB2YWx1ZSxzZXA9IiwiKSxmaWxsPTE4MCxhcHBlbmQ9VCkNCiAgICANCiAgICBuYW0yPC1wYXN0ZShvdXRqcGdkaXIscGFzdGUob2ZpbGVuYW1lLCJfRFRSLmpwZyIsc2VwPSIiKSxzZXA9Ii8iKQ0KICAgIGpwZWcobmFtMix3aWR0aD0xMDI0LGhlaWdodD03NjgpDQogICAgcGxvdHgob2ZpbGVbLDFdLG9maWxlWywxNF0sbWFpbj1wYXN0ZSgiRFRSIixvZmlsZW5hbWUsc2VwPSIgICAiKSx4bGFiPSJZZWFyIix5bGFiPSJEVFIiKQ0KICAgIGRldi5vZmYoKQ0KfSAjIGVuZCBvZiBkdHINCiMtLS0tLS0tLS0tLSBkdHIgZW5kcyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQ0KDQojLS0tLS0tLS0tLS0gZGF5c3ByY3AxMCAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSAgDQpkYXlzcHJjcDEwPC1mdW5jdGlvbigpew0KICAgIHlzPC15ZWFyZS15ZWFycysxDQogICAgUjEwPC1yZXAoMCx5cykNCiAgICB5ZWFyc3M8LWMoeWVhcnM6eWVhcmUpDQogICAgdGFyZ2V0PC1hcy5kYXRhLmZyYW1lKGNiaW5kKHllYXJzcyxSMTApKQ0KICAgIGZvciAoeWVhciBpbiB5ZWFyczp5ZWFyZSl7DQogICAgICAgIG1pZDwtZGRbZGQkeWVhcj09eWVhciwicHJjcCJdDQogICAgICAgIG1pZDwtbWlkW2lzLm5hKG1pZCk9PUZdDQogICAgICAgIHRhcmdldFt0YXJnZXQkeWVhcnNzPT15ZWFyLCJSMTAiXTwtbGVuZ3RoKG1pZFttaWQ+PTEwXSl9DQogICAgZGltbmFtZXModGFyZ2V0KVtbMl1dWzFdPC0ieWVhciINCiAgICB0YXJnZXRbLCJSMTAiXTwtdGFyZ2V0WywiUjEwIl0reW5hY29yWywieW5hcHI+MTUiXQ0KICAgIG5hbTE8LXBhc3RlKG91dGluZGRpcixwYXN0ZShvZmlsZW5hbWUsIl9SMTBtbS5jc3YiLHNlcD0iIiksc2VwPSIvIikNCiAgICB3cml0ZS50YWJsZSh0YXJnZXQsZmlsZT1uYW0xLGFwcGVuZD1GLHF1b3RlPUYsc2VwPSIsICIsbmE9Ii05OS45Iixyb3cubmFtZXM9RikNCiAgICANCiAgICBuYW10PC1wYXN0ZShvdXR0cmRkaXIscGFzdGUob2ZpbGVuYW1lLCJfdHJlbmQuY3N2IixzZXA9IiIpLHNlcD0iLyIpDQogICAgaWYoc3VtKGlzLm5hKHRhcmdldFssIlIxMCJdKSk+PSh5ZWFyZS15ZWFycysxLTEwKSl7DQogICAgICAgIGJldGFoYXQ8LU5BDQogICAgICAgIGJldGFzdGQ8LU5BDQogICAgICAgIHB2YWx1ZTwtTkENCiAgICB9DQogICAgZWxzZXsNCiAgICAgICAgZml0MTwtbHNmaXQodGFyZ2V0WywxXSx0YXJnZXRbLCJSMTAiXSkNCiAgICAgICAgb3V0MTwtbHMucHJpbnQoZml0MSxwcmludC5pdD1GKQ0KICAgICAgICBwdmFsdWU8LXJvdW5kKGFzLm51bWVyaWMob3V0MSRzdW1tYXJ5WzEsNl0pLDMpDQogICAgICAgIGJldGFoYXQ8LXJvdW5kKGFzLm51bWVyaWMob3V0MSRjb2VmLnRhYmxlW1sxXV1bMiwxXSksMykNCiAgICAgICAgYmV0YXN0ZDwtcm91bmQoYXMubnVtZXJpYyhvdXQxJGNvZWYudGFibGVbWzFdXVsyLDJdKSwzKQ0KICAgIH0NCiAgICBjYXQoZmlsZT1uYW10LHBhc3RlKGxhdGl0dWRlLGxvbmdpdHVkZSwicjEwbW0iLHllYXJzLHllYXJlLGJldGFoYXQsYmV0YXN0ZCxwdmFsdWUsc2VwPSIsIiksZmlsbD0xODAsYXBwZW5kPVQpDQogICAgDQogICAgbmFtMjwtcGFzdGUob3V0anBnZGlyLHBhc3RlKG9maWxlbmFtZSwiX1IxMG1tLmpwZyIsc2VwPSIiKSxzZXA9Ii8iKQ0KICAgIGpwZWcobmFtMix3aWR0aD0xMDI0LGhlaWdodD03NjgpDQogICAgcGxvdHgodGFyZ2V0WywxXSx0YXJnZXRbLDJdLG1haW49cGFzdGUoIlIxMG1tIixvZmlsZW5hbWUsc2VwPSIgICAiKSx4bGFiPSJZZWFyIix5bGFiPSJSMTBtbSIpDQogICAgZGV2Lm9mZigpDQp9DQojLS0tLS0tLS0tLS0gZGF5c3ByY3AxMCBlbmRzIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tDQoNCiMtLS0tLS0tLS0tLSBleHRyZW1lZGF5cyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSAgDQpleHRyZW1lZGF5czwtZnVuY3Rpb24ob3B0PTApew0KICAgIGlmKG9wdD09MCl7DQogICAgICAgIGV1dT11dQ0KICAgICAgICBldWw9dWwNCiAgICAgICAgZWx1PWx1DQogICAgICAgIGVsbD1sbA0KICAgIH0NCiAgICBlbHNlew0KICAgICAgICBldXU9dXV1DQogICAgICAgIGV1bD11dWwNCiAgICAgICAgZWx1PXVsdQ0KICAgICAgICBlbGw9dWxsDQogICAgfQ0KICAgIHlzPC15ZWFyZS15ZWFycysxDQogICAgIyAgYmVnaW55ZWFyPC1kZFsxLDFdDQogICAgIyAgZW5keWVhcjwtZGRbZGltKGRkKVsxXSwxXQ0KICAgIHRjbGV4dDwtYyh5ZWFyczp5ZWFyZSkNCiAgICBzdTwtcmVwKDAseXMpDQogICAgaWQ8LXN1DQogICAgdHI8LXN1DQogICAgZmQ8LXN1DQogICAgdGNsZXh0PC1jYmluZCh0Y2xleHQsc3UsaWQsdHIsZmQpDQogICAgZGltbmFtZXModGNsZXh0KVtbMl1dWzFdPC0ieWVhciINCiAgICBpPTENCiAgICBmb3IgKHllYXIgaW4geWVhcnM6eWVhcmUpIHsNCiAgICAgICAgbWlkMTwtZGRbZGQkeWVhcj09eWVhciwidG1heCJdOyAgbWlkMTwtbWlkMVtpcy5uYShtaWQxKT09Rl0NCiAgICAgICAgbWlkMjwtZGRbZGQkeWVhcj09eWVhciwidG1pbiJdOyAgbWlkMjwtbWlkMltpcy5uYShtaWQyKT09Rl0NCiAgICAgICAgdGNsZXh0W2ksInN1Il08LWxlbmd0aChtaWQxW21pZDE+ZXV1XSkNCiAgICAgICAgdGNsZXh0W2ksImlkIl08LWxlbmd0aChtaWQxW21pZDE8ZXVsXSkNCiAgICAgICAgdGNsZXh0W2ksInRyIl08LWxlbmd0aChtaWQyW21pZDI+ZWx1XSkNCiAgICAgICAgdGNsZXh0W2ksImZkIl08LWxlbmd0aChtaWQyW21pZDI8ZWxsXSkNCiAgICAgICAgaTwtaSsxfSAjZm9yIGVuZCAgICANCiAgICB0Y2xleHQ8LWFzLmRhdGEuZnJhbWUodGNsZXh0KQ0KICAgIHRjbGV4dFssInN1Il08LXRjbGV4dFssInN1Il0reW5hY29yWywieW5hdG1hPjE1Il0NCiAgICB0Y2xleHRbLCJpZCJdPC10Y2xleHRbLCJpZCJdK3luYWNvclssInluYXRtYT4xNSJdDQogICAgdGNsZXh0WywidHIiXTwtdGNsZXh0WywidHIiXSt5bmFjb3JbLCJ5bmF0bWk+MTUiXQ0KICAgIHRjbGV4dFssImZkIl08LXRjbGV4dFssImZkIl0reW5hY29yWywieW5hdG1pPjE1Il0NCiAgICAjICAgIGFzc2lnbigiZXh0ZGF5cyIsdGNsZXh0LGVudmlyPS5HbG9iYWxFbnYpDQogICAgaWYob3B0PT0wKXsNCiAgICAgICAgbmFtMTwtcGFzdGUob3V0aW5kZGlyLHBhc3RlKG9maWxlbmFtZSwiX1NVMjUuY3N2IixzZXA9IiIpLHNlcD0iLyIpDQogICAgICAgIG5hbTI8LXBhc3RlKG91dGluZGRpcixwYXN0ZShvZmlsZW5hbWUsIl9JRDAuY3N2IixzZXA9IiIpLHNlcD0iLyIpDQogICAgICAgIG5hbTM8LXBhc3RlKG91dGluZGRpcixwYXN0ZShvZmlsZW5hbWUsIl9UUjIwLmNzdiIsc2VwPSIiKSxzZXA9Ii8iKQ0KICAgICAgICBuYW00PC1wYXN0ZShvdXRpbmRkaXIscGFzdGUob2ZpbGVuYW1lLCJfRkQwLmNzdiIsc2VwPSIiKSxzZXA9Ii8iKQ0KICAgIH0NCiAgICBlbHNlew0KICAgICAgICBuYW0xPC1wYXN0ZShvdXRpbmRkaXIscGFzdGUob2ZpbGVuYW1lLCJfU1UiLGFzLmNoYXJhY3RlcihldXUpLCIuY3N2IixzZXA9IiIpLHNlcD0iLyIpDQogICAgICAgIG5hbTI8LXBhc3RlKG91dGluZGRpcixwYXN0ZShvZmlsZW5hbWUsIl9JRCIsYXMuY2hhcmFjdGVyKGV1bCksIi5jc3YiLHNlcD0iIiksc2VwPSIvIikNCiAgICAgICAgbmFtMzwtcGFzdGUob3V0aW5kZGlyLHBhc3RlKG9maWxlbmFtZSwiX1RSIixhcy5jaGFyYWN0ZXIoZWx1KSwiLmNzdiIsc2VwPSIiKSxzZXA9Ii8iKQ0KICAgICAgICBuYW00PC1wYXN0ZShvdXRpbmRkaXIscGFzdGUob2ZpbGVuYW1lLCJfRkQiLGFzLmNoYXJhY3RlcihlbGwpLCIuY3N2IixzZXA9IiIpLHNlcD0iLyIpDQogICAgfQ0KICAgIA0KICAgIHdyaXRlLnRhYmxlKHRjbGV4dFssYygieWVhciIsInN1IildLGZpbGU9bmFtMSxhcHBlbmQ9RixxdW90ZT1GLHNlcD0iLCAiLG5hPSItOTkuOSIscm93Lm5hbWVzPUYpDQogICAgd3JpdGUudGFibGUodGNsZXh0WyxjKCJ5ZWFyIiwiaWQiKV0sZmlsZT1uYW0yLGFwcGVuZD1GLHF1b3RlPUYsc2VwPSIsICIsbmE9Ii05OS45Iixyb3cubmFtZXM9RikNCiAgICB3cml0ZS50YWJsZSh0Y2xleHRbLGMoInllYXIiLCJ0ciIpXSxmaWxlPW5hbTMsYXBwZW5kPUYscXVvdGU9RixzZXA9IiwgIixuYT0iLTk5LjkiLHJvdy5uYW1lcz1GKQ0KICAgIHdyaXRlLnRhYmxlKHRjbGV4dFssYygieWVhciIsImZkIildLGZpbGU9bmFtNCxhcHBlbmQ9RixxdW90ZT1GLHNlcD0iLCAiLG5hPSItOTkuOSIscm93Lm5hbWVzPUYpDQogICAgDQogICAgIyBvdXRwdXQgdHJlbmQgYmFzZSBvbiBhbm51YWwgaW5kaWNpZXMgZGF0YQ0KICAgIG5hbXQ8LXBhc3RlKG91dHRyZGRpcixwYXN0ZShvZmlsZW5hbWUsIl90cmVuZC5jc3YiLHNlcD0iIiksc2VwPSIvIikNCiAgICBmb3IoIGkgaW4gYygic3UiLCJpZCIsInRyIiwiZmQiKSl7DQogICAgICAgIGlmKHN1bShpcy5uYSh0Y2xleHRbLGldKSk+PSh5ZWFyZS15ZWFycysxLTEwKSl7DQogICAgICAgICAgICBiZXRhaGF0PC1OQQ0KICAgICAgICAgICAgYmV0YXN0ZDwtTkENCiAgICAgICAgICAgIHB2YWx1ZTwtTkENCiAgICAgICAgfQ0KICAgICAgICBlbHNlew0KICAgICAgICAgICAgZml0MTwtbHNmaXQodGNsZXh0WywieWVhciJdLHRjbGV4dFssaV0pDQogICAgICAgICAgICBvdXQxPC1scy5wcmludChmaXQxLHByaW50Lml0PUYpDQogICAgICAgICAgICBwdmFsdWU8LXJvdW5kKGFzLm51bWVyaWMob3V0MSRzdW1tYXJ5WzEsNl0pLDMpDQogICAgICAgICAgICBiZXRhaGF0PC1yb3VuZChhcy5udW1lcmljKG91dDEkY29lZi50YWJsZVtbMV1dWzIsMV0pLDMpDQogICAgICAgICAgICBiZXRhc3RkPC1yb3VuZChhcy5udW1lcmljKG91dDEkY29lZi50YWJsZVtbMV1dWzIsMl0pLDMpDQogICAgICAgIH0NCiAgICAgICAgaWYob3B0PT0wKXsNCiAgICAgICAgICAgIGlmKGk9PSJzdSIpIGlpPC0ic3UyNSINCiAgICAgICAgICAgIGlmKGk9PSJpZCIpIGlpPC0iaWQwIg0KICAgICAgICAgICAgaWYoaT09ImZkIikgaWk8LSJmZDAiDQogICAgICAgICAgICBpZihpPT0idHIiKSBpaTwtInRyMjAiDQogICAgICAgIH0NCiAgICAgICAgZWxzZXsNCiAgICAgICAgICAgIGlmKGk9PSJzdSIpIGlpPC1wYXN0ZSgic3UiLGFzLmNoYXJhY3RlcihldXUpLHNlcD0iIikNCiAgICAgICAgICAgIGlmKGk9PSJpZCIpIGlpPC1wYXN0ZSgiaWQiLGFzLmNoYXJhY3RlcihldWwpLHNlcD0iIikNCiAgICAgICAgICAgIGlmKGk9PSJ0ciIpIGlpPC1wYXN0ZSgidHIiLGFzLmNoYXJhY3RlcihlbHUpLHNlcD0iIikNCiAgICAgICAgICAgIGlmKGk9PSJmZCIpIGlpPC1wYXN0ZSgiZmQiLGFzLmNoYXJhY3RlcihlbGwpLHNlcD0iIikNCiAgICAgICAgfQ0KICAgICAgICBjYXQoZmlsZT1uYW10LHBhc3RlKGxhdGl0dWRlLGxvbmdpdHVkZSxpaSx5ZWFycyx5ZWFyZSxiZXRhaGF0LGJldGFzdGQscHZhbHVlLHNlcD0iLCIpLGZpbGw9MTgwLGFwcGVuZD1UKQ0KICAgIH0NCiAgICANCiAgICBuYW1wPC1jKCIiLCIiLCIiLCIiKQ0KICAgIGlmKG9wdD09MCl7DQogICAgICAgIG5hbXBbMV08LXBhc3RlKG91dGpwZ2RpcixwYXN0ZShvZmlsZW5hbWUsIl9TVTI1LmpwZyIsc2VwPSIiKSxzZXA9Ii8iKQ0KICAgICAgICBuYW1wWzJdPC1wYXN0ZShvdXRqcGdkaXIscGFzdGUob2ZpbGVuYW1lLCJfSUQwLmpwZyIsc2VwPSIiKSxzZXA9Ii8iKQ0KICAgICAgICBuYW1wWzNdPC1wYXN0ZShvdXRqcGdkaXIscGFzdGUob2ZpbGVuYW1lLCJfVFIyMC5qcGciLHNlcD0iIiksc2VwPSIvIikNCiAgICAgICAgbmFtcFs0XTwtcGFzdGUob3V0anBnZGlyLHBhc3RlKG9maWxlbmFtZSwiX0ZEMC5qcGciLHNlcD0iIiksc2VwPSIvIikNCiAgICB9DQogICAgZWxzZXsNCiAgICAgICAgbmFtcFsxXTwtcGFzdGUob3V0anBnZGlyLHBhc3RlKG9maWxlbmFtZSwiX1NVIixhcy5jaGFyYWN0ZXIoZXV1KSwiLmpwZyIsc2VwPSIiKSxzZXA9Ii8iKQ0KICAgICAgICBuYW1wWzJdPC1wYXN0ZShvdXRqcGdkaXIscGFzdGUob2ZpbGVuYW1lLCJfSUQiLGFzLmNoYXJhY3RlcihldWwpLCIuanBnIixzZXA9IiIpLHNlcD0iLyIpDQogICAgICAgIG5hbXBbM108LXBhc3RlKG91dGpwZ2RpcixwYXN0ZShvZmlsZW5hbWUsIl9UUiIsYXMuY2hhcmFjdGVyKGVsdSksIi5qcGciLHNlcD0iIiksc2VwPSIvIikNCiAgICAgICAgbmFtcFs0XTwtcGFzdGUob3V0anBnZGlyLHBhc3RlKG9maWxlbmFtZSwiX0ZEIixhcy5jaGFyYWN0ZXIoZWxsKSwiLmpwZyIsc2VwPSIiKSxzZXA9Ii8iKQ0KICAgIH0NCiAgICBpZihvcHQ9PTApIHlsYWI8LWMoIlNVMjUiLCJJRDAiLCJUUjIwIiwiRkQwIikNCiAgICBlbHNlIHlsYWI8LWMocGFzdGUoIlNVIixhcy5jaGFyYWN0ZXIoZXV1KSxzZXA9IiIpLCANCiAgICAgICAgICAgICAgICAgcGFzdGUoIklEIixhcy5jaGFyYWN0ZXIoZXVsKSxzZXA9IiIpLCANCiAgICAgICAgICAgICAgICAgcGFzdGUoIlRSIixhcy5jaGFyYWN0ZXIoZWx1KSxzZXA9IiIpLCANCiAgICAgICAgICAgICAgICAgcGFzdGUoIkZEIixhcy5jaGFyYWN0ZXIoZWxsKSxzZXA9IiIpKQ0KICAgIA0KICAgIHhsYWI8LXJlcCgieWVhciIsNCkNCiAgICBmb3IoaSBpbiAxOjQpew0KICAgICAgICB0aXRsZTFbaV08LXBhc3RlKHlsYWJbaV0sb2ZpbGVuYW1lLHNlcD0iICAgIikNCiAgICAgICAganBlZyhmaWxlPW5hbXBbaV0sd2lkdGg9MTAyNCxoZWlnaHQ9NzY4KQ0KICAgICAgICBwbG90eCh0Y2xleHRbLDFdLHRjbGV4dFssaSsxXSxtYWluPXRpdGxlMVtpXSx5bGFiPXlsYWJbaV0seGxhYj0iWWVhciIpDQogICAgICAgIGRldi5vZmYoKQ0KICAgIH0NCn0NCiMtLS0tLS0tLS0tLSBleHRyZW1lZGF5cyBlbmRzIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tICANCg0KIy0tLS0tLS0tLS0tIGV4Y2VlZGFuY2UgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0gIA0KZXhjZWVkYW5jZTwtZnVuY3Rpb24oKXsNCiAgICBpZiAoZmxhZz09VCkgcmV0dXJuKCkNCiAgICBhPC0xOjM2NQ0KICAgIHlzPC1lbmR5ZWFyLXN0YXJ0eWVhcisxO3lzczwteXMtMQ0KICAgIG1vbmRheXM8LWMoMzEsMjgsMzEsMzAsMzEsMzAsMzEsMzEsMzAsMzEsMzAsMzEpDQogICAgbW9uZTwtcmVwKDAsMTIpO21vbnM8LW1vbmUNCiAgICBmb3IoaSBpbiAxOjEyKSBtb25lW2ldPC1zdW0obW9uZGF5c1sxOmldKQ0KICAgIG1vbnNbMV08LTENCiAgICBmb3IoaSBpbiAyOjEyKSBtb25zW2ldPC1tb25lW2ktMV0rMQ0KICAgIA0KICAgIG1vbmV4PC1tYXRyaXgoTkEseXMqMTIsNikNCiAgICBkaW1uYW1lcyhtb25leCk8LWxpc3QoTlVMTCxjKCJ5ZWFyIiwibW9udGgiLCJ0eDEwcCIsInR4OTBwIiwidG4xMHAiLCJ0bjkwcCIpKQ0KICAgIG1vbmV4WywibW9udGgiXTwtcmVwKDE6MTIseXMpDQogICAgbW9uZXhbLCJ5ZWFyIl08LXN0YXJ0eWVhcjplbmR5ZWFyDQogICAgbW9uZXhbLCJ5ZWFyIl08LW15c29ydChtb25leFssInllYXIiXSxkZWNyZWFzaW5nPUYpDQogICAgbW9uZXg8LWFzLmRhdGEuZnJhbWUobW9uZXgpDQogICAgDQogICAgDQogICAgYjwtbWF0cml4KDAsMzY1LDQpDQogICAgYTwtY2JpbmQoYSxiKQ0KICAgIGFhPC1hcnJheShhLGMoMzY1LDUseXMpKQ0KICAgIGRpbW5hbWVzKGFhKTwtbGlzdChOVUxMLGMoImRheSIsInBjbWF4MTAiLCJwY21heDkwIiwicGNtaW4xMCIsInBjbWluOTAiKSxOVUxMKQ0KICAgIG1zPC13aW5zaXplKnlzDQogICAgaT13aW5zaXplLXJvdW5kKHdpbnNpemUvMixkaWdpdHM9MCkNCiAgICBpMT1yb3VuZCh3aW5zaXplLzIsZGlnaXRzPTApDQogICAgDQogICAgIyAgZGF5bm9ybTI8LWRheW5vcm0xWy0oMTppMSksXSAjIGRheW5vcm0yIGlzIHRvdGFsIGJhc2UgcGVyaW9kIG5vcm1hbGl6ZWQgZGF0YQ0KICAgIGRheW5vcm0yPC1kZFtkZCR5ZWFyPj1zdGFydHllYXIsXQ0KICAgIGRheW5vcm0yPC1kYXlub3JtMltkYXlub3JtMiR5ZWFyPD1lbmR5ZWFyLF0NCiAgICBkYXlub3JtMjwtZGF5bm9ybTJbZGF5bm9ybTIkbW9udGghPTJ8ZGF5bm9ybTIkZGF5IT0yOSxdDQogICAgZGF5bm9ybTI8LWRheW5vcm0yWywtNF0NCiAgICAjICBpMjwtZGltKGRheW5vcm0yKVsxXQ0KICAgICMgIGkzPC1pMi1pMSsxDQogICAgIyAgZGF5bm9ybTI8LWRheW5vcm0yWy0oaTM6aTIpLF0NCiAgICANCiAgICB5ZWFyZXg8LWMoc3RhcnR5ZWFyOmVuZHllYXIpOyAgIHR4ZzEwcDwtcmVwKDAsbGVuZ3RoKHllYXJleCkpDQogICAgdHhnOTBwPC1yZXAoMCxsZW5ndGgoeWVhcmV4KSk7ICB0bmcxMHA8LXJlcCgwLGxlbmd0aCh5ZWFyZXgpKQ0KICAgIHRuZzkwcDwtcmVwKDAsbGVuZ3RoKHllYXJleCkpDQogICAgZDwtYXMuZGF0YS5mcmFtZShjYmluZCh5ZWFyZXgsdHhnMTBwLHR4ZzkwcCx0bmcxMHAsdG5nOTBwKSkNCiAgICBjb2xuYW1lcyhkKVsxXTwtInllYXIiDQogICAgDQogICAgbW9uZXg8LW1hdHJpeCgwLHlzKjEyLDYpDQogICAgZGltbmFtZXMobW9uZXgpPC1saXN0KE5VTEwsYygieWVhciIsIm1vbnRoIiwidHgxMHAiLCJ0eDkwcCIsInRuMTBwIiwidG45MHAiKSkNCiAgICBtb25leFssIm1vbnRoIl08LXJlcCgxOjEyLHlzKQ0KICAgIG1vbmV4WywieWVhciJdPC1zdGFydHllYXI6ZW5keWVhcg0KICAgIG1vbmV4WywieWVhciJdPC1teXNvcnQobW9uZXhbLCJ5ZWFyIl0sZGVjcmVhc2luZz1GKQ0KICAgIG1vbmV4PC1hcy5kYXRhLmZyYW1lKG1vbmV4KQ0KICAgIA0KICAgIHJhdGVjb3VudDwtbWF0cml4KDAsMzY1LDQpDQogICAgZGltbmFtZXMocmF0ZWNvdW50KTwtbGlzdChOVUxMLGMoInBjbWF4MTAiLCJwY21heDkwIiwicGNtaW4xMCIsInBjbWluOTAiKSkNCiAgICANCiAgICBmb3IgKHllYXIgaW4gc3RhcnR5ZWFyOmVuZHllYXIpeyAjIHllYXIgbG9vcCBzdGFydA0KICAgICAgICANCiAgICAgICAgbWlkdmFsdWU8LWRheW5vcm0yW2RheW5vcm0yJHllYXI9PXllYXIsXQ0KICAgICAgICB6ej15ZWFyLXN0YXJ0cG9pbnQgI2luZGV4IGluIGJhc2UgcGVyaW9kLCBzYXksIHp6dGggeWVhcg0KICAgICAgICANCiAgICAgICAgaW5kZDwtZXh3aW5bZXh3aW5bLDNdIT15cywzXQ0KICAgICAgICANCiAgICAgICAgZm9yIChrIGluIDE6KHlzLTEpKXsgIyBmb3IgayAoYm9vdCBzdHJhcCkgc3RhcnQNCiAgICAgICAgICAgIA0KICAgICAgICAgICAgZm9yIChpIGluIDE6MzY1KXsgIyBkYXkgbG9vcCBzdGFydA0KICAgICAgICAgICAgICAgIHBwYzwtZXh3aW5zWywsaV0NCiAgICAgICAgICAgICAgICBwcGM8LXBwY1twcGNbLDNdIT16eixdDQogICAgICAgICAgICAgICAgcHBjPC1wcGNbLC0zXQ0KICAgICAgICAgICAgICAgIA0KICAgICAgICAgICAgICAgIHBwYzwtY2JpbmQocHBjLGluZGQpDQogICAgICAgICAgICAgICAgDQogICAgICAgICAgICAgICAgcHBjYzwtcmJpbmQocHBjW3BwY1ssImluZGQiXT09ayxdLHBwYykNCiAgICAgICAgICAgICAgICBpdG1wPC1wZXJjZW50aWxlKG1zLHBwY2NbLDFdLGMoMC4xLDAuOSkpDQogICAgICAgICAgICAgICAgYWFbaSwicGNtYXgxMCIsenpdPC1pdG1wWzFdLTFlLTUNCiAgICAgICAgICAgICAgICBhYVtpLCJwY21heDkwIix6el08LWl0bXBbMl0rMWUtNQ0KICAgICAgICAgICAgICAgIGl0bXA8LXBlcmNlbnRpbGUobXMscHBjY1ssMl0sYygwLjEsMC45KSkNCiAgICAgICAgICAgICAgICBhYVtpLCJwY21pbjEwIix6el08LWl0bXBbMV0tMWUtNQ0KICAgICAgICAgICAgICAgIGFhW2ksInBjbWluOTAiLHp6XTwtaXRtcFsyXSsxZS01DQogICAgICAgICAgICB9DQogICAgICAgICAgICByYXRlY291bnRbLCJwY21heDEwIl08LW1pZHZhbHVlWywidG1heCJdLWFhWywicGNtYXgxMCIsenpdDQogICAgICAgICAgICByYXRlY291bnRbLCJwY21heDkwIl08LW1pZHZhbHVlWywidG1heCJdLWFhWywicGNtYXg5MCIsenpdDQogICAgICAgICAgICByYXRlY291bnRbLCJwY21pbjEwIl08LW1pZHZhbHVlWywidG1pbiJdLWFhWywicGNtaW4xMCIsenpdDQogICAgICAgICAgICByYXRlY291bnRbLCJwY21pbjkwIl08LW1pZHZhbHVlWywidG1pbiJdLWFhWywicGNtaW45MCIsenpdDQogICAgICAgICAgICBmb3IobW9uIGluIDE6MTIpew0KICAgICAgICAgICAgICAgIHRtcHR4MTBwPC1yYXRlY291bnRbbW9uc1ttb25dOm1vbmVbbW9uXSwicGNtYXgxMCJdDQogICAgICAgICAgICAgICAgdG1wdHg5MHA8LXJhdGVjb3VudFttb25zW21vbl06bW9uZVttb25dLCJwY21heDkwIl0NCiAgICAgICAgICAgICAgICB0bXB0bjEwcDwtcmF0ZWNvdW50W21vbnNbbW9uXTptb25lW21vbl0sInBjbWluMTAiXQ0KICAgICAgICAgICAgICAgIHRtcHRuOTBwPC1yYXRlY291bnRbbW9uc1ttb25dOm1vbmVbbW9uXSwicGNtaW45MCJdDQogICAgICAgICAgICAgICAgbW9uZXhbKHp6LTEpKjEyK21vbiwidHgxMHAiXTwtIG1vbmV4Wyh6ei0xKSoxMittb24sInR4MTBwIl0rbGVuZ3RoKHRtcHR4MTBwW3RtcHR4MTBwPDAmaXMubmEodG1wdHgxMHApPT1GXSkNCiAgICAgICAgICAgICAgICBtb25leFsoenotMSkqMTIrbW9uLCJ0eDkwcCJdPC0gbW9uZXhbKHp6LTEpKjEyK21vbiwidHg5MHAiXStsZW5ndGgodG1wdHg5MHBbdG1wdHg5MHA+MCZpcy5uYSh0bXB0eDkwcCk9PUZdKQ0KICAgICAgICAgICAgICAgIG1vbmV4Wyh6ei0xKSoxMittb24sInRuMTBwIl08LSBtb25leFsoenotMSkqMTIrbW9uLCJ0bjEwcCJdK2xlbmd0aCh0bXB0bjEwcFt0bXB0bjEwcDwwJmlzLm5hKHRtcHRuMTBwKT09Rl0pDQogICAgICAgICAgICAgICAgbW9uZXhbKHp6LTEpKjEyK21vbiwidG45MHAiXTwtIG1vbmV4Wyh6ei0xKSoxMittb24sInRuOTBwIl0rbGVuZ3RoKHRtcHRuOTBwW3RtcHRuOTBwPjAmaXMubmEodG1wdG45MHApPT1GXSkNCiAgICAgICAgICAgICAgICBpZihsZWFweWVhcih5ZWFyKSZtb249PTIpew0KICAgICAgICAgICAgICAgICAgICBpZihkZFtkZCR5ZWFyPT15ZWFyJmRkJG1vbnRoPT0yJmRkJGRheT09MjksInRtYXgiXT5hYVs1OSwicGNtYXg5MCIsenpdJmlzLm5hKGRkW2RkJHllYXI9PXllYXImZGQkbW9udGg9PTImZGQkZGF5PT0yOSwidG1heCJdKT09RiZpcy5uYShhYVs1OCwicGNtYXg5MCIsenpdKT09RikNCiAgICAgICAgICAgICAgICAgICAgICAgIG1vbmV4Wyh6ei0xKSoxMittb24sInR4OTBwIl08LW1vbmV4Wyh6ei0xKSoxMittb24sInR4OTBwIl0rMQ0KICAgICAgICAgICAgICAgICAgICBpZihkZFtkZCR5ZWFyPT15ZWFyJmRkJG1vbnRoPT0yJmRkJGRheT09MjksInRtYXgiXTxhYVs1OSwicGNtYXgxMCIsenpdJmlzLm5hKGRkW2RkJHllYXI9PXllYXImZGQkbW9udGg9PTImZGQkZGF5PT0yOSwidG1heCJdKT09RiZpcy5uYShhYVs1OCwicGNtYXgxMCIsenpdKT09RikNCiAgICAgICAgICAgICAgICAgICAgICAgIG1vbmV4Wyh6ei0xKSoxMittb24sInR4MTBwIl08LW1vbmV4Wyh6ei0xKSoxMittb24sInR4MTBwIl0rMQ0KICAgICAgICAgICAgICAgICAgICBpZihkZFtkZCR5ZWFyPT15ZWFyJmRkJG1vbnRoPT0yJmRkJGRheT09MjksInRtaW4iXT5hYVs1OSwicGNtaW45MCIsenpdJmlzLm5hKGRkW2RkJHllYXI9PXllYXImZGQkbW9udGg9PTImZGQkZGF5PT0yOSwidG1pbiJdKT09RiZpcy5uYShhYVs1OCwicGNtaW45MCIsenpdKT09RikNCiAgICAgICAgICAgICAgICAgICAgICAgIG1vbmV4Wyh6ei0xKSoxMittb24sInRuOTBwIl08LW1vbmV4Wyh6ei0xKSoxMittb24sInRuOTBwIl0rMQ0KICAgICAgICAgICAgICAgICAgICBpZihkZFtkZCR5ZWFyPT15ZWFyJmRkJG1vbnRoPT0yJmRkJGRheT09MjksInRtaW4iXTxhYVs1OSwicGNtaW4xMCIsenpdJmlzLm5hKGRkW2RkJHllYXI9PXllYXImZGQkbW9udGg9PTImZGQkZGF5PT0yOSwidG1pbiJdKT09RiZpcy5uYShhYVs1OCwicGNtaW4xMCIsenpdKT09RikNCiAgICAgICAgICAgICAgICAgICAgICAgIG1vbmV4Wyh6ei0xKSoxMittb24sInRuMTBwIl08LW1vbmV4Wyh6ei0xKSoxMittb24sInRuMTBwIl0rMQ0KICAgICAgICAgICAgICAgIH0gI2lmIGVuZA0KICAgICAgICAgICAgfSAjZm9yIG1vbiBlbmQNCiAgICAgICAgfSAjZm9yIGsgKGJvb3Qgc3RyYXApIGVuZA0KICAgIH0jIGZvciB5ZWFyIChmcm9tIHN0YXJ0eWVhciB0byBlbmR5ZWFyKSBlbmQNCiAgICANCiAgICBtb25leFssInR4MTBwIl08LW1vbmV4WywidHgxMHAiXS8yOS4NCiAgICBtb25leFssInR4OTBwIl08LW1vbmV4WywidHg5MHAiXS8yOS4NCiAgICBtb25leFssInRuMTBwIl08LW1vbmV4WywidG4xMHAiXS8yOS4NCiAgICBtb25leFssInRuOTBwIl08LW1vbmV4WywidG45MHAiXS8yOS4NCiAgICAjICBtb25leDwtcmJpbmQoYmRtLG1vbmV4LGFkbSkNCiAgICANCiAgICAjICBhc3NpZ24oImRtIixkbSxlbnZpcj0uR2xvYmFsRW52KQ0KICAgIA0KICAgIGRtPC1tZXJnZShtb25leCxkLGJ5PSJ5ZWFyIikNCiAgICBkbTwtcmJpbmQoYmRtLGRtLGFkbSkNCiAgICANCiAgICBsZW48LXllYXJlLXllYXJzKzENCiAgICBmb3IoaSBpbiBjKCJ0eDEwcCIsInR4OTBwIiwidG4xMHAiLCJ0bjkwcCIpKXsNCiAgICAgICAgaWYgKGk9PSJ0eDEwcCIpIHtpaTwtIl9UWDEwUC5jc3YiOyAgIGtrPC0zO25hc3RhdD03fSNuYXRtYQ0KICAgICAgICBpZiAoaT09InR4OTBwIikge2lpPC0iX1RYOTBQLmNzdiI7ICAga2s8LTQ7bmFzdGF0PTd9I25hdG1hDQogICAgICAgIGlmIChpPT0idG4xMHAiKSB7aWk8LSJfVE4xMFAuY3N2IjsgICBrazwtNTtuYXN0YXQ9OH0jbmF0bWkNCiAgICAgICAgaWYgKGk9PSJ0bjkwcCIpIHtpaTwtIl9UTjkwUC5jc3YiOyAgIGtrPC02O25hc3RhdD04fSNuYXRtaQ0KICAgICAgICANCiAgICAgICAgbmFtMTwtcGFzdGUob3V0aW5kZGlyLHBhc3RlKG9maWxlbmFtZSxpaSxzZXA9IiIpLHNlcD0iLyIpDQogICAgICAgIG9maWxlPC1tYXRyaXgoMCxsZW4sMTQpDQogICAgICAgIGRpbW5hbWVzKG9maWxlKTwtbGlzdChOVUxMLGMoInllYXIiLCJqYW4iLCJmZWIiLCJtYXIiLCJhcHIiLCJtYXkiLCJqdW4iLCJqdWwiLCJhdWciLCJzZXAiLCJvY3QiLCJub3YiLCJkZWMiLCJhbm51YWwiKSkNCiAgICAgICAgb2ZpbGU8LWFzLmRhdGEuZnJhbWUob2ZpbGUpDQogICAgICAgIGZvcihqIGluIHllYXJzOnllYXJlKXsNCiAgICAgICAgICAgIGlmKGxlYXB5ZWFyKGopKSBmdWxsZGF5czwtYygzMSwyOSwzMSwzMCwzMSwzMCwzMSwzMSwzMCwzMSwzMCwzMSkNCiAgICAgICAgICAgIGVsc2UgZnVsbGRheXM8LWMoMzEsMjgsMzEsMzAsMzEsMzAsMzEsMzEsMzAsMzEsMzAsMzEpDQogICAgICAgICAgICBrPC1qLXllYXJzKzENCiAgICAgICAgICAgIG9maWxlW2ssMV08LWoNCiAgICAgICAgICAgIG9maWxlW2ssMjoxM108LWRtW2RtJHllYXI9PWosa2tdDQogICAgICAgICAgICBmb3IobW9uIGluIDE6MTIpew0KICAgICAgICAgICAgICAgIGlmKG5hc3RhdGlzdGljWyhrLTEpKjEyK21vbixuYXN0YXRdPjEwKSBvZmlsZVtrLChtb24rMSldPC1OQQ0KICAgICAgICAgICAgICAgIGVsc2UgICBvZmlsZVtrLChtb24rMSldPC1kbVsoay0xKSoxMittb24sa2tdKmZ1bGxkYXlzW21vbl0vKGZ1bGxkYXlzW21vbl0tbmFzdGF0aXN0aWNbKGstMSkqMTIrbW9uLG5hc3RhdF0pDQogICAgICAgICAgICB9DQogICAgICAgICAgICBvZmlsZVtrLDE0XTwtc3VtKG9maWxlW2ssMjoxM10sbmEucm09VCkNCiAgICAgICAgfQ0KICAgICAgICBvZmlsZVssMTRdPC1vZmlsZVssMTRdK3luYWNvclssbmFzdGF0LTRdDQogICAgICAgIGZvcihqIGluIHllYXJzOnllYXJlKXsNCiAgICAgICAgICAgIGs8LWoteWVhcnMrMQ0KICAgICAgICAgICAgaWYobGVhcHllYXIoaikpIGZ1bGxkYXlzPC1jKDMxLDI5LDMxLDMwLDMxLDMwLDMxLDMxLDMwLDMxLDMwLDMxKQ0KICAgICAgICAgICAgZWxzZSBmdWxsZGF5czwtYygzMSwyOCwzMSwzMCwzMSwzMCwzMSwzMSwzMCwzMSwzMCwzMSkNCiAgICAgICAgICAgIGZvcihtb24gaW4gMToxMikgb2ZpbGVbayxtb24rMV08LW9maWxlW2ssbW9uKzFdKjEwMC9mdWxsZGF5c1ttb25dICMgY2hhbmdlIG91dHB1dCBmcm9tIGNvdW50aW5nIGRheXMgdG8gJQ0KICAgICAgICB9DQogICAgICAgIG9maWxlWywxNF08LW9maWxlWywxNF0qMTAwLzM2NSAjIGNoYW5nZSBvdXRwdXQgZnJvbSBjb3VudGluZyBkYXlzIHRvICUNCiAgICAgICAgd3JpdGUudGFibGUocm91bmQob2ZpbGUsMiksZmlsZT1uYW0xLGFwcGVuZD1GLHF1b3RlPUYsc2VwPSIsICIsbmE9Ii05OS45Iixyb3cubmFtZXM9RikNCiAgICAgICAgDQogICAgICAgIG5hbXQ8LXBhc3RlKG91dHRyZGRpcixwYXN0ZShvZmlsZW5hbWUsIl90cmVuZC5jc3YiLHNlcD0iIiksc2VwPSIvIikNCiAgICAgICAgaWYoc3VtKGlzLm5hKG9maWxlWywxNF0pKT49KHllYXJlLXllYXJzKzEtMTApKXsNCiAgICAgICAgICAgIGJldGFoYXQ8LU5BDQogICAgICAgICAgICBiZXRhc3RkPC1OQQ0KICAgICAgICAgICAgcHZhbHVlPC1OQQ0KICAgICAgICB9DQogICAgICAgIGVsc2V7DQogICAgICAgICAgICBmaXQxPC1sc2ZpdChvZmlsZVssMV0sb2ZpbGVbLDE0XSkNCiAgICAgICAgICAgIG91dDE8LWxzLnByaW50KGZpdDEscHJpbnQuaXQ9RikNCiAgICAgICAgICAgIHB2YWx1ZTwtcm91bmQoYXMubnVtZXJpYyhvdXQxJHN1bW1hcnlbMSw2XSksMykNCiAgICAgICAgICAgIGJldGFoYXQ8LXJvdW5kKGFzLm51bWVyaWMob3V0MSRjb2VmLnRhYmxlW1sxXV1bMiwxXSksMykNCiAgICAgICAgICAgIGJldGFzdGQ8LXJvdW5kKGFzLm51bWVyaWMob3V0MSRjb2VmLnRhYmxlW1sxXV1bMiwyXSksMykNCiAgICAgICAgfQ0KICAgICAgICBjYXQoZmlsZT1uYW10LHBhc3RlKGxhdGl0dWRlLGxvbmdpdHVkZSxpLHllYXJzLHllYXJlLGJldGFoYXQsYmV0YXN0ZCxwdmFsdWUsc2VwPSIsIiksZmlsbD0xODAsYXBwZW5kPVQpDQogICAgICAgIA0KICAgICAgICBuYW0yPC1wYXN0ZShvdXRqcGdkaXIscGFzdGUob2ZpbGVuYW1lLCJfIix0b3VwcGVyKGkpLCIuanBnIixzZXA9IiIpLHNlcD0iLyIpDQogICAgICAgIGpwZWcoZmlsZT1uYW0yLHdpZHRoPTEwMjQsaGVpZ2h0PTc2OCkNCiAgICAgICAgcGxvdHgob2ZpbGVbLDFdLG9maWxlWywxNF0sbWFpbj1wYXN0ZSh0b3VwcGVyKGkpLG9maWxlbmFtZSxzZXA9IiAgICIpLHlsYWI9dG91cHBlcihpKSx4bGFiPSJZZWFyIikNCiAgICAgICAgZGV2Lm9mZigpDQogICAgfQ0KfQ0KIy0tLS0tLS0tLS0tIGV4Y2VlZGFuY2UgZW5kcyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSAgDQoNCiMtLS0tLS0tLS0tLSBpbmRleDY0MWNkZCAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSAgDQppbmRleDY0MWNkZDwtZnVuY3Rpb24oKXsNCiAgICB5czwteWVhcmUteWVhcnMrMQ0KICAgIGNkZDwtcmVwKDAseXMpDQogICAgeWVhcjwtYyh5ZWFyczp5ZWFyZSkNCiAgICB0YXJnZXQ8LWFzLmRhdGEuZnJhbWUoY2JpbmQoeWVhcixjZGQpKQ0KICAgIHllYXI9eWVhcnMNCiAgICBmb3IgKGkgaW4gMTp5cyl7DQogICAgICAgIG1pZDwtZGRbZGQkeWVhcj09eWVhciwicHJjcCJdDQogICAgICAgICMgIG1pZDwtbWlkW2lzLm5hKG1pZCk9PUZdDQogICAgICAgIGlmKGk9PTEpIGtrPC0wDQogICAgICAgIG1tPC0wDQogICAgICAgIGZvcihqIGluIDE6bGVuZ3RoKG1pZCkpew0KICAgICAgICAgICAgaWYobWlkW2pdPDEmaXMubmEobWlkW2pdKT09Rikga2s8LWtrKzENCiAgICAgICAgICAgIGVsc2Ugew0KICAgICAgICAgICAgICAgIGlmKG1tPGtrKSBtbTwta2sNCiAgICAgICAgICAgICAgICBrazwtMA0KICAgICAgICAgICAgfQ0KICAgICAgICB9DQogICAgICAgIGlmKG1tPGtrKXsNCiAgICAgICAgICAgIGlmKHllYXI9PXllYXJlKSBtbTwta2sNCiAgICAgICAgICAgIGVsc2UNCiAgICAgICAgICAgICAgICBpZihkZFtkZCR5ZWFyPT15ZWFyKzEmZGQkbW9udGg9PTEmZGQkZGF5PT0xLCJwcmNwIl0+PTF8aXMubmEoZGRbZGQkeWVhcj09eWVhcisxJmRkJG1vbnRoPT0xJmRkJGRheT09MSwicHJjcCJdKT09VCkgbW08LWtrDQogICAgICAgICAgICAgICAgIyBpbiBjYXNlIHdob2xlIHllYXIgZHJ5LCB0aGUgbmV4dCB5ZWFyIHdpbGwgaGF2ZSBhIENERCBiaWdnZXIgdGhhbiAzNjUNCiAgICAgICAgICAgICAgICAjIHRoZW4gdGhlIENERCBpbmRpY2UgZm9yIGN1cnJlbnQgeWVhciBzaG91bGQgbm90IGJlIDAgYnV0IE5BDQogICAgICAgICAgICAgICAgaWYobW09PTApIG1tPC1OQQ0KICAgICAgICB9DQogICAgICAgIHRhcmdldFtpLCJjZGQiXTwtbW0NCiAgICAgICAgeWVhcj15ZWFyKzENCiAgICB9DQogICAgDQogICAgI2ZvcihpIGluIDE6KHlzLTEpKQ0KICAgICMgIGlmKHRhcmdldFtpLCJjZGQiXT09MCZ0YXJnZXRbaSsxLCJjZGQiXT49MzY1KSB0YXJnZXRbaSwiY2RkIl08LU5BDQogICAgDQogICAgdGFyZ2V0WywiY2RkIl08LXRhcmdldFssImNkZCJdK3luYWNvclssInluYXByPjE1Il0NCiAgICBuYW0xPC1wYXN0ZShvdXRpbmRkaXIscGFzdGUob2ZpbGVuYW1lLCJfQ0RELmNzdiIsc2VwPSIiKSxzZXA9Ii8iKQ0KICAgIHdyaXRlLnRhYmxlKHRhcmdldCxmaWxlPW5hbTEsYXBwZW5kPUYscXVvdGU9RixzZXA9IiwgIixuYT0iLTk5LjkiLHJvdy5uYW1lcz1GKQ0KICAgIA0KICAgIG5hbXQ8LXBhc3RlKG91dHRyZGRpcixwYXN0ZShvZmlsZW5hbWUsIl90cmVuZC5jc3YiLHNlcD0iIiksc2VwPSIvIikNCiAgICBpZihzdW0oaXMubmEodGFyZ2V0WywiY2RkIl0pKT49KHllYXJlLXllYXJzKzEtMTApKXsNCiAgICAgICAgYmV0YWhhdDwtTkENCiAgICAgICAgYmV0YXN0ZDwtTkENCiAgICAgICAgcHZhbHVlPC1OQQ0KICAgIH0NCiAgICBlbHNlew0KICAgICAgICBmaXQxPC1sc2ZpdCh0YXJnZXRbLDFdLHRhcmdldFssImNkZCJdKQ0KICAgICAgICBvdXQxPC1scy5wcmludChmaXQxLHByaW50Lml0PUYpDQogICAgICAgIHB2YWx1ZTwtcm91bmQoYXMubnVtZXJpYyhvdXQxJHN1bW1hcnlbMSw2XSksMykNCiAgICAgICAgYmV0YWhhdDwtcm91bmQoYXMubnVtZXJpYyhvdXQxJGNvZWYudGFibGVbWzFdXVsyLDFdKSwzKQ0KICAgICAgICBiZXRhc3RkPC1yb3VuZChhcy5udW1lcmljKG91dDEkY29lZi50YWJsZVtbMV1dWzIsMl0pLDMpDQogICAgfQ0KICAgIGNhdChmaWxlPW5hbXQscGFzdGUobGF0aXR1ZGUsbG9uZ2l0dWRlLCJjZGQiLHllYXJzLHllYXJlLGJldGFoYXQsYmV0YXN0ZCxwdmFsdWUsc2VwPSIsIiksZmlsbD0xODAsYXBwZW5kPVQpDQogICAgDQogICAgbmFtMjwtcGFzdGUob3V0anBnZGlyLHBhc3RlKG9maWxlbmFtZSwiX0NERC5qcGciLHNlcD0iIiksc2VwPSIvIikNCiAgICBqcGVnKG5hbTIsd2lkdGg9MTAyNCxoZWlnaHQ9NzY4KQ0KICAgIHBsb3R4KHRhcmdldFssMV0sdGFyZ2V0WywyXSxtYWluPXBhc3RlKCJDREQiLG9maWxlbmFtZSxzZXA9IiAgICIpLHhsYWI9IlllYXIiLHlsYWI9IkNERCIpDQogICAgZGV2Lm9mZigpDQp9DQojLS0tLS0tLS0tLS0gaW5kZXg2NDFjZGQgZW5kcyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSAgDQoNCiMtLS0tLS0tLS0tLSBpbmRleDY0MWN3ZCAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSAgDQppbmRleDY0MWN3ZDwtZnVuY3Rpb24oKXsNCiAgICB5czwteWVhcmUteWVhcnMrMQ0KICAgIGN3ZDwtcmVwKDAseXMpDQogICAgeWVhcjwteWVhcnM6eWVhcmUNCiAgICB0YXJnZXQ8LWFzLmRhdGEuZnJhbWUoY2JpbmQoeWVhcixjd2QpKQ0KICAgIHllYXI9eWVhcnMNCiAgICBmb3IgKGkgaW4gMTp5cyl7DQogICAgICAgIG1pZDwtZGRbZGQkeWVhcj09eWVhciwicHJjcCJdDQogICAgICAgICMgIG1pZDwtbWlkW2lzLm5hKG1pZCk9PUZdDQogICAgICAgIGlmKGk9PTEpIGtrPC0wDQogICAgICAgIG1tPC0wDQogICAgICAgIGZvcihqIGluIDE6bGVuZ3RoKG1pZCkpew0KICAgICAgICAgICAgaWYobWlkW2pdPj0xJmlzLm5hKG1pZFtqXSk9PUYpIGtrPC1raysxDQogICAgICAgICAgICBlbHNlIHsNCiAgICAgICAgICAgICAgICBpZihtbTxraykgbW08LWtrDQogICAgICAgICAgICAgICAga2s8LTANCiAgICAgICAgICAgIH0NCiAgICAgICAgfQ0KICAgICAgICBpZihtbTxrayl7DQogICAgICAgICAgICBpZih5ZWFyPT15ZWFyZSkgbW08LWtrDQogICAgICAgICAgICBlbHNlDQogICAgICAgICAgICAgICAgaWYoZGRbZGQkeWVhcj09eWVhcisxJmRkJG1vbnRoPT0xJmRkJGRheT09MSwicHJjcCJdPDF8aXMubmEoZGRbZGQkeWVhcj09eWVhcisxJmRkJG1vbnRoPT0xJmRkJGRheT09MSwicHJjcCJdKT09VCkgbW08LWtrDQogICAgICAgIH0NCiAgICAgICAgDQogICAgICAgIHRhcmdldFtpLCJjd2QiXTwtbW0NCiAgICAgICAgeWVhcj15ZWFyKzENCiAgICB9DQogICAgdGFyZ2V0WywiY3dkIl08LXRhcmdldFssImN3ZCJdK3luYWNvclssInluYXByPjE1Il0NCiAgICBuYW0xPC1wYXN0ZShvdXRpbmRkaXIscGFzdGUob2ZpbGVuYW1lLCJfQ1dELmNzdiIsc2VwPSIiKSxzZXA9Ii8iKQ0KICAgIHdyaXRlLnRhYmxlKHRhcmdldCxmaWxlPW5hbTEsYXBwZW5kPUYscXVvdGU9RixzZXA9IiwgIixuYT0iLTk5LjkiLHJvdy5uYW1lcz1GKQ0KICAgIA0KICAgIG5hbXQ8LXBhc3RlKG91dHRyZGRpcixwYXN0ZShvZmlsZW5hbWUsIl90cmVuZC5jc3YiLHNlcD0iIiksc2VwPSIvIikNCiAgICBpZihzdW0oaXMubmEodGFyZ2V0WywiY3dkIl0pKT49KHllYXJlLXllYXJzKzEtMTApKXsNCiAgICAgICAgYmV0YWhhdDwtTkENCiAgICAgICAgYmV0YXN0ZDwtTkENCiAgICAgICAgcHZhbHVlPC1OQQ0KICAgIH0NCiAgICBlbHNlew0KICAgICAgICBmaXQxPC1sc2ZpdCh0YXJnZXRbLDFdLHRhcmdldFssImN3ZCJdKQ0KICAgICAgICBvdXQxPC1scy5wcmludChmaXQxLHByaW50Lml0PUYpDQogICAgICAgIHB2YWx1ZTwtcm91bmQoYXMubnVtZXJpYyhvdXQxJHN1bW1hcnlbMSw2XSksMykNCiAgICAgICAgYmV0YWhhdDwtcm91bmQoYXMubnVtZXJpYyhvdXQxJGNvZWYudGFibGVbWzFdXVsyLDFdKSwzKQ0KICAgICAgICBiZXRhc3RkPC1yb3VuZChhcy5udW1lcmljKG91dDEkY29lZi50YWJsZVtbMV1dWzIsMl0pLDMpDQogICAgfQ0KICAgIGNhdChmaWxlPW5hbXQscGFzdGUobGF0aXR1ZGUsbG9uZ2l0dWRlLCJjd2QiLHllYXJzLHllYXJlLGJldGFoYXQsYmV0YXN0ZCxwdmFsdWUsc2VwPSIsIiksZmlsbD0xODAsYXBwZW5kPVQpDQogICAgDQogICAgbmFtMjwtcGFzdGUob3V0anBnZGlyLHBhc3RlKG9maWxlbmFtZSwiX0NXRC5qcGciLHNlcD0iIiksc2VwPSIvIikNCiAgICBqcGVnKG5hbTIsd2lkdGg9MTAyNCxoZWlnaHQ9NzY4KQ0KICAgIHBsb3R4KHRhcmdldFssMV0sdGFyZ2V0WywyXSxtYWluPXBhc3RlKCJDV0QiLG9maWxlbmFtZSxzZXA9IiAgICIpLHhsYWI9IlllYXIiLHlsYWI9IkNXRCIpDQogICAgZGV2Lm9mZigpDQp9DQojLS0tLS0tLS0tLS0gaW5kZXg2NDFjd2QgZW5kcyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSAgDQoNCiMtLS0tLS0tLS0tLSByeDFkIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tICANCnJ4MWQ8LWZ1bmN0aW9uKCl7DQogICAgbGVuPC15ZWFyZS15ZWFycysxDQogICAgYWExPC1tYXRyaXgoTkEsMTIqbGVuLDMpDQogICAgZGltbmFtZXMoYWExKTwtbGlzdChOVUxMLGMoInllYXIiLCJtb250aCIsInJ4MWQiKSkNCiAgICBhYTFbLCJ5ZWFyIl08LXllYXJzOnllYXJlDQogICAgYWExWywieWVhciJdPC1teXNvcnQoYWExWywieWVhciJdLGRlY3JlYXNpbmc9RikNCiAgICBhYTFbLCJtb250aCJdPC0xOjEyDQogICAgampqMz0xDQogICAgbWlkPC1kZFssMTo0XQ0KICAgIGZvciAoeWVhciBpbiB5ZWFyczp5ZWFyZSl7DQogICAgICAgIGFhYWE8LW1pZFttaWQkeWVhcj09eWVhcixdDQogICAgICAgIGFhYWFtMTwtYWFhYVthYWFhJG1vbnRoPT0xLCJwcmNwIl07ICAgICAgICBhYWFhbTI8LWFhYWFbYWFhYSRtb250aD09MiwicHJjcCJdDQogICAgICAgIGFhYWFtMzwtYWFhYVthYWFhJG1vbnRoPT0zLCJwcmNwIl07ICAgICAgICBhYWFhbTQ8LWFhYWFbYWFhYSRtb250aD09NCwicHJjcCJdDQogICAgICAgIGFhYWFtNTwtYWFhYVthYWFhJG1vbnRoPT01LCJwcmNwIl07ICAgICAgICBhYWFhbTY8LWFhYWFbYWFhYSRtb250aD09NiwicHJjcCJdDQogICAgICAgIGFhYWFtNzwtYWFhYVthYWFhJG1vbnRoPT03LCJwcmNwIl07ICAgICAgICBhYWFhbTg8LWFhYWFbYWFhYSRtb250aD09OCwicHJjcCJdDQogICAgICAgIGFhYWFtOTwtYWFhYVthYWFhJG1vbnRoPT05LCJwcmNwIl07ICAgICAgICBhYWFhbTEwPC1hYWFhW2FhYWEkbW9udGg9PTEwLCJwcmNwIl0NCiAgICAgICAgYWFhYW0xMTwtYWFhYVthYWFhJG1vbnRoPT0xMSwicHJjcCJdOyAgICAgIGFhYWFtMTI8LWFhYWFbYWFhYSRtb250aD09MTIsInByY3AiXQ0KICAgICAgICBhYTFbampqMywicngxZCJdPC1tYXgoYWFhYW0xLG5hLnJtPVQpOyAgICAgYWExW2pqajMrMSwicngxZCJdPC1tYXgoYWFhYW0yLG5hLnJtPVQpDQogICAgICAgIGFhMVtqamozKzIsInJ4MWQiXTwtbWF4KGFhYWFtMyxuYS5ybT1UKTsgICBhYTFbampqMyszLCJyeDFkIl08LW1heChhYWFhbTQsbmEucm09VCkNCiAgICAgICAgYWExW2pqajMrNCwicngxZCJdPC1tYXgoYWFhYW01LG5hLnJtPVQpOyAgIGFhMVtqamozKzUsInJ4MWQiXTwtbWF4KGFhYWFtNixuYS5ybT1UKQ0KICAgICAgICBhYTFbampqMys2LCJyeDFkIl08LW1heChhYWFhbTcsbmEucm09VCk7ICAgYWExW2pqajMrNywicngxZCJdPC1tYXgoYWFhYW04LG5hLnJtPVQpDQogICAgICAgIGFhMVtqamozKzgsInJ4MWQiXTwtbWF4KGFhYWFtOSxuYS5ybT1UKTsgICBhYTFbampqMys5LCJyeDFkIl08LW1heChhYWFhbTEwLG5hLnJtPVQpDQogICAgICAgIGFhMVtqamozKzEwLCJyeDFkIl08LW1heChhYWFhbTExLG5hLnJtPVQpOyBhYTFbampqMysxMSwicngxZCJdPC1tYXgoYWFhYW0xMixuYS5ybT1UKQ0KICAgICAgICBqamozPWpqajMrMTJ9DQogICAgYWExWywicngxZCJdPC1hYTFbLCJyeDFkIl0rbmFjb3JbLCJtbmFwcj4zIl0NCiAgICBvZmlsZTwtbWF0cml4KDAsbGVuLDE0KQ0KICAgICMgICAgYWExPC1hcy5kYXRhLmZyYW1lKGFhMSkNCiAgICBkaW1uYW1lcyhvZmlsZSk8LWxpc3QoTlVMTCxjKCJ5ZWFyIiwiamFuIiwiZmViIiwibWFyIiwiYXByIiwibWF5IiwianVuIiwianVsIiwiYXVnIiwic2VwIiwib2N0Iiwibm92IiwiZGVjIiwiYW5udWFsIikpDQogICAgb2ZpbGU8LWFzLmRhdGEuZnJhbWUob2ZpbGUpDQogICAgZm9yKGogaW4geWVhcnM6eWVhcmUpew0KICAgICAgICBrPC1qLXllYXJzKzENCiAgICAgICAgb2ZpbGVbaywxXTwtag0KICAgICAgICBvZmlsZVtrLDI6MTNdPC1hYTFbYWExWywxXT09aiwzXQ0KICAgICAgICBvZmlsZVtrLDE0XTwtbWF4KG9maWxlW2ssMjoxM10sbmEucm09RikNCiAgICB9DQogICAgbmFtMTwtcGFzdGUob3V0aW5kZGlyLHBhc3RlKG9maWxlbmFtZSwiX1JYMWRheS5jc3YiLHNlcD0iIiksc2VwPSIvIikNCiAgICB3cml0ZS50YWJsZShvZmlsZSxmaWxlPW5hbTEsYXBwZW5kPUYscXVvdGU9RixzZXA9IiwgIixuYT0iLTk5LjkiLHJvdy5uYW1lcz1GKQ0KICAgIA0KICAgIG5hbXQ8LXBhc3RlKG91dHRyZGRpcixwYXN0ZShvZmlsZW5hbWUsIl90cmVuZC5jc3YiLHNlcD0iIiksc2VwPSIvIikNCiAgICBpZihzdW0oaXMubmEob2ZpbGVbLDE0XSkpPj0oeWVhcmUteWVhcnMrMS0xMCkpew0KICAgICAgICBiZXRhaGF0PC1OQQ0KICAgICAgICBiZXRhc3RkPC1OQQ0KICAgICAgICBwdmFsdWU8LU5BDQogICAgfQ0KICAgIGVsc2V7DQogICAgICAgIGZpdDE8LWxzZml0KG9maWxlWywxXSxvZmlsZVssMTRdKQ0KICAgICAgICBvdXQxPC1scy5wcmludChmaXQxLHByaW50Lml0PUYpDQogICAgICAgIHB2YWx1ZTwtcm91bmQoYXMubnVtZXJpYyhvdXQxJHN1bW1hcnlbMSw2XSksMykNCiAgICAgICAgYmV0YWhhdDwtcm91bmQoYXMubnVtZXJpYyhvdXQxJGNvZWYudGFibGVbWzFdXVsyLDFdKSwzKQ0KICAgICAgICBiZXRhc3RkPC1yb3VuZChhcy5udW1lcmljKG91dDEkY29lZi50YWJsZVtbMV1dWzIsMl0pLDMpDQogICAgfQ0KICAgIGNhdChmaWxlPW5hbXQscGFzdGUobGF0aXR1ZGUsbG9uZ2l0dWRlLCJyeDFkYXkiLHllYXJzLHllYXJlLGJldGFoYXQsYmV0YXN0ZCxwdmFsdWUsc2VwPSIsIiksZmlsbD0xODAsYXBwZW5kPVQpDQogICAgDQogICAgbmFtMjwtcGFzdGUob3V0anBnZGlyLHBhc3RlKG9maWxlbmFtZSwiX1JYMWRheS5qcGciLHNlcD0iIiksc2VwPSIvIikNCiAgICBqcGVnKG5hbTIsd2lkdGg9MTAyNCxoZWlnaHQ9NzY4KQ0KICAgIHBsb3R4KG9maWxlWywxXSxvZmlsZVssMTRdLG1haW49cGFzdGUoIlJYMWRheSIsb2ZpbGVuYW1lLHNlcD0iICAgIikseGxhYj0iWWVhciIseWxhYj0iUlgxZGF5IikNCiAgICBkZXYub2ZmKCkNCn0NCiMtLS0tLS0tLS0tLSByeDFkIGVuZHMgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0gIA0KDQojLS0tLS0tLS0tLS0gcng1ZCAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSAgDQpyeDVkPC1mdW5jdGlvbigpew0KICAgIGEyPC1jKDAsMCwwLDApDQogICAgYTE8LWRkWywicHJjcCJdDQogICAgYTE8LWFwcGVuZChhMixhMSkNCiAgICBuPC1sZW5ndGgoYTEpDQogICAgYTwtcmVwKDAsbikNCiAgICBmb3IgKGkgaW4gNTpuKXsNCiAgICAgICAgYVtpXTwtc3VtKGExWyhpLTQpOmldLG5hLnJtPVQpfQ0KICAgIGE8LWFbLSgxOjQpXQ0KICAgIGE8LWNiaW5kKGRkWywxOjJdLGEpDQogICAgDQogICAgbGVuPC15ZWFyZS15ZWFycysxDQogICAgYWExPC1tYXRyaXgoTkEsMTIqbGVuLDMpDQogICAgZGltbmFtZXMoYWExKTwtbGlzdChOVUxMLGMoInllYXIiLCJtb250aCIsInJ4NWQiKSkNCiAgICBhYTFbLCJ5ZWFyIl08LXllYXJzOnllYXJlDQogICAgYWExWywieWVhciJdPC1teXNvcnQoYWExWywieWVhciJdLGRlY3JlYXNpbmc9RikNCiAgICBhYTFbLCJtb250aCJdPC0xOjEyDQogICAgampqMj0xDQogICAgZm9yICh5ZWFyIGluIHllYXJzOnllYXJlKXsNCiAgICAgICAgYWFhYTwtYVthJHllYXI9PXllYXIsXQ0KICAgICAgICBhYWFhbTE8LWFhYWFbYWFhYSRtb250aD09MSwiYSJdOyAgICAgICAgICAgYWFhYW0yPC1hYWFhW2FhYWEkbW9udGg9PTIsImEiXQ0KICAgICAgICBhYWFhbTM8LWFhYWFbYWFhYSRtb250aD09MywiYSJdOyAgICAgICAgICAgYWFhYW00PC1hYWFhW2FhYWEkbW9udGg9PTQsImEiXQ0KICAgICAgICBhYWFhbTU8LWFhYWFbYWFhYSRtb250aD09NSwiYSJdOyAgICAgICAgICAgYWFhYW02PC1hYWFhW2FhYWEkbW9udGg9PTYsImEiXQ0KICAgICAgICBhYWFhbTc8LWFhYWFbYWFhYSRtb250aD09NywiYSJdOyAgICAgICAgICAgYWFhYW04PC1hYWFhW2FhYWEkbW9udGg9PTgsImEiXQ0KICAgICAgICBhYWFhbTk8LWFhYWFbYWFhYSRtb250aD09OSwiYSJdOyAgICAgICAgICAgYWFhYW0xMDwtYWFhYVthYWFhJG1vbnRoPT0xMCwiYSJdDQogICAgICAgIGFhYWFtMTE8LWFhYWFbYWFhYSRtb250aD09MTEsImEiXTsgICAgICAgICBhYWFhbTEyPC1hYWFhW2FhYWEkbW9udGg9PTEyLCJhIl0NCiAgICAgICAgYWExW2pqajIsInJ4NWQiXTwtbWF4KGFhYWFtMSxuYS5ybT1UKTsgICAgIGFhMVtqamoyKzEsInJ4NWQiXTwtbWF4KGFhYWFtMixuYS5ybT1UKQ0KICAgICAgICBhYTFbampqMisyLCJyeDVkIl08LW1heChhYWFhbTMsbmEucm09VCk7ICAgYWExW2pqajIrMywicng1ZCJdPC1tYXgoYWFhYW00LG5hLnJtPVQpDQogICAgICAgIGFhMVtqamoyKzQsInJ4NWQiXTwtbWF4KGFhYWFtNSxuYS5ybT1UKTsgICBhYTFbampqMis1LCJyeDVkIl08LW1heChhYWFhbTYsbmEucm09VCkNCiAgICAgICAgYWExW2pqajIrNiwicng1ZCJdPC1tYXgoYWFhYW03LG5hLnJtPVQpOyAgIGFhMVtqamoyKzcsInJ4NWQiXTwtbWF4KGFhYWFtOCxuYS5ybT1UKQ0KICAgICAgICBhYTFbampqMis4LCJyeDVkIl08LW1heChhYWFhbTksbmEucm09VCk7ICAgYWExW2pqajIrOSwicng1ZCJdPC1tYXgoYWFhYW0xMCxuYS5ybT1UKQ0KICAgICAgICBhYTFbampqMisxMCwicng1ZCJdPC1tYXgoYWFhYW0xMSxuYS5ybT1UKTsgYWExW2pqajIrMTEsInJ4NWQiXTwtbWF4KGFhYWFtMTIsbmEucm09VCkNCiAgICAgICAgampqMj1qamoyKzEyfQ0KICAgIA0KICAgIGFhMVssInJ4NWQiXTwtYWExWywicng1ZCJdK25hY29yWywibW5hcHI+MyJdDQogICAgDQogICAgb2ZpbGU8LW1hdHJpeCgwLGxlbiwxNCkNCiAgICAjICAgIGFhMTwtYXMuZGF0YS5mcmFtZShhYTEpDQogICAgZGltbmFtZXMob2ZpbGUpPC1saXN0KE5VTEwsYygieWVhciIsImphbiIsImZlYiIsIm1hciIsImFwciIsIm1heSIsImp1biIsImp1bCIsImF1ZyIsInNlcCIsIm9jdCIsIm5vdiIsImRlYyIsImFubnVhbCIpKQ0KICAgIG9maWxlPC1hcy5kYXRhLmZyYW1lKG9maWxlKQ0KICAgIGZvcihqIGluIHllYXJzOnllYXJlKXsNCiAgICAgICAgazwtai15ZWFycysxDQogICAgICAgIG9maWxlW2ssMV08LWoNCiAgICAgICAgb2ZpbGVbaywyOjEzXTwtYWExW2FhMVssMV09PWosInJ4NWQiXQ0KICAgICAgICBvZmlsZVtrLDE0XTwtbWF4KG9maWxlW2ssMjoxM10sbmEucm09RikNCiAgICB9DQogICAgIyAgICBwcmludChkaW0ocng1ZCkpDQogICAgbmFtMTwtcGFzdGUob3V0aW5kZGlyLHBhc3RlKG9maWxlbmFtZSwiX1JYNWRheS5jc3YiLHNlcD0iIiksc2VwPSIvIikNCiAgICB3cml0ZS50YWJsZShvZmlsZSxmaWxlPW5hbTEsYXBwZW5kPUYscXVvdGU9RixzZXA9IiwgIixuYT0iLTk5LjkiLHJvdy5uYW1lcz1GKQ0KICAgIA0KICAgIG5hbXQ8LXBhc3RlKG91dHRyZGRpcixwYXN0ZShvZmlsZW5hbWUsIl90cmVuZC5jc3YiLHNlcD0iIiksc2VwPSIvIikNCiAgICBpZihzdW0oaXMubmEob2ZpbGVbLDE0XSkpPj0oeWVhcmUteWVhcnMrMS0xMCkpew0KICAgICAgICBiZXRhaGF0PC1OQQ0KICAgICAgICBiZXRhc3RkPC1OQQ0KICAgICAgICBwdmFsdWU8LU5BDQogICAgfQ0KICAgIGVsc2V7DQogICAgICAgIGZpdDE8LWxzZml0KG9maWxlWywxXSxvZmlsZVssMTRdKQ0KICAgICAgICBvdXQxPC1scy5wcmludChmaXQxLHByaW50Lml0PUYpDQogICAgICAgIHB2YWx1ZTwtcm91bmQoYXMubnVtZXJpYyhvdXQxJHN1bW1hcnlbMSw2XSksMykNCiAgICAgICAgYmV0YWhhdDwtcm91bmQoYXMubnVtZXJpYyhvdXQxJGNvZWYudGFibGVbWzFdXVsyLDFdKSwzKQ0KICAgICAgICBiZXRhc3RkPC1yb3VuZChhcy5udW1lcmljKG91dDEkY29lZi50YWJsZVtbMV1dWzIsMl0pLDMpDQogICAgfQ0KICAgIGNhdChmaWxlPW5hbXQscGFzdGUobGF0aXR1ZGUsbG9uZ2l0dWRlLCJyeDVkYXkiLHllYXJzLHllYXJlLGJldGFoYXQsYmV0YXN0ZCxwdmFsdWUsc2VwPSIsIiksZmlsbD0xODAsYXBwZW5kPVQpDQogICAgDQogICAgbmFtMjwtcGFzdGUob3V0anBnZGlyLHBhc3RlKG9maWxlbmFtZSwiX1JYNWRheS5qcGciLHNlcD0iIiksc2VwPSIvIikNCiAgICBqcGVnKG5hbTIsd2lkdGg9MTAyNCxoZWlnaHQ9NzY4KQ0KICAgIHBsb3R4KG9maWxlWywxXSxvZmlsZVssMTRdLG1haW49cGFzdGUoIlJYNWRheSIsb2ZpbGVuYW1lLHNlcD0iICAgIikseGxhYj0iWWVhciIseWxhYj0iUlg1ZGF5IikNCiAgICBkZXYub2ZmKCkNCn0NCiMtLS0tLS0tLS0tLSByeDVkIGVuZHMgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0gIA0KDQojLS0tLS0tLS0tLS0gZXh0cmVtZWRheXRlbSAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSAgDQpleHRyZW1lZGF5dGVtPC1mdW5jdGlvbigpew0KICAgIGxlbjwteWVhcmUteWVhcnMrMQ0KICAgIGFhMTwtbWF0cml4KE5BLDEyKmxlbiw2KQ0KICAgIGRpbW5hbWVzKGFhMSk8LWxpc3QoTlVMTCxjKCJ5ZWFyIiwibW9udGgiLCJ0eHgiLCJ0eG4iLCJ0bngiLCJ0bm4iKSkNCiAgICBhYTFbLCJ5ZWFyIl08LXllYXJzOnllYXJlDQogICAgYWExWywieWVhciJdPC1teXNvcnQoYWExWywieWVhciJdLGRlY3JlYXNpbmc9RikNCiAgICBhYTFbLCJtb250aCJdPC0xOjEyDQogICAgampqND0xDQogICAgZm9yICh5ZWFyIGluIHllYXJzOnllYXJlKXsNCiAgICAgICAgYWFhYTwtZGRbZGQkeWVhcj09eWVhcixdDQogICAgICAgIGFhYWFtYTE8LWFhYWFbYWFhYSRtb250aD09MSwidG1heCJdOyAgIGFhYWFtYTI8LWFhYWFbYWFhYSRtb250aD09MiwidG1heCJdDQogICAgICAgIGFhYWFtYTM8LWFhYWFbYWFhYSRtb250aD09MywidG1heCJdOyAgIGFhYWFtYTQ8LWFhYWFbYWFhYSRtb250aD09NCwidG1heCJdDQogICAgICAgIGFhYWFtYTU8LWFhYWFbYWFhYSRtb250aD09NSwidG1heCJdOyAgIGFhYWFtYTY8LWFhYWFbYWFhYSRtb250aD09NiwidG1heCJdDQogICAgICAgIGFhYWFtYTc8LWFhYWFbYWFhYSRtb250aD09NywidG1heCJdOyAgIGFhYWFtYTg8LWFhYWFbYWFhYSRtb250aD09OCwidG1heCJdDQogICAgICAgIGFhYWFtYTk8LWFhYWFbYWFhYSRtb250aD09OSwidG1heCJdOyAgIGFhYWFtYTEwPC1hYWFhW2FhYWEkbW9udGg9PTEwLCJ0bWF4Il0NCiAgICAgICAgYWFhYW1hMTE8LWFhYWFbYWFhYSRtb250aD09MTEsInRtYXgiXTsgYWFhYW1hMTI8LWFhYWFbYWFhYSRtb250aD09MTIsInRtYXgiXQ0KICAgICAgICANCiAgICAgICAgYWFhYW1pMTwtYWFhYVthYWFhJG1vbnRoPT0xLCJ0bWluIl07ICAgYWFhYW1pMjwtYWFhYVthYWFhJG1vbnRoPT0yLCJ0bWluIl0NCiAgICAgICAgYWFhYW1pMzwtYWFhYVthYWFhJG1vbnRoPT0zLCJ0bWluIl07ICAgYWFhYW1pNDwtYWFhYVthYWFhJG1vbnRoPT00LCJ0bWluIl0NCiAgICAgICAgYWFhYW1pNTwtYWFhYVthYWFhJG1vbnRoPT01LCJ0bWluIl07ICAgYWFhYW1pNjwtYWFhYVthYWFhJG1vbnRoPT02LCJ0bWluIl0NCiAgICAgICAgYWFhYW1pNzwtYWFhYVthYWFhJG1vbnRoPT03LCJ0bWluIl07ICAgYWFhYW1pODwtYWFhYVthYWFhJG1vbnRoPT04LCJ0bWluIl0NCiAgICAgICAgYWFhYW1pOTwtYWFhYVthYWFhJG1vbnRoPT05LCJ0bWluIl07ICAgYWFhYW1pMTA8LWFhYWFbYWFhYSRtb250aD09MTAsInRtaW4iXQ0KICAgICAgICBhYWFhbWkxMTwtYWFhYVthYWFhJG1vbnRoPT0xMSwidG1pbiJdOyBhYWFhbWkxMjwtYWFhYVthYWFhJG1vbnRoPT0xMiwidG1pbiJdDQogICAgICAgIA0KICAgICAgICBhYTFbampqNCwidHh4Il08LW1heChhYWFhbWExLG5hLnJtPVQpOyAgICAgYWExW2pqajQrMSwidHh4Il08LW1heChhYWFhbWEyLG5hLnJtPVQpDQogICAgICAgIGFhMVtqamo0KzIsInR4eCJdPC1tYXgoYWFhYW1hMyxuYS5ybT1UKTsgICBhYTFbampqNCszLCJ0eHgiXTwtbWF4KGFhYWFtYTQsbmEucm09VCkNCiAgICAgICAgYWExW2pqajQrNCwidHh4Il08LW1heChhYWFhbWE1LG5hLnJtPVQpOyAgIGFhMVtqamo0KzUsInR4eCJdPC1tYXgoYWFhYW1hNixuYS5ybT1UKQ0KICAgICAgICBhYTFbampqNCs2LCJ0eHgiXTwtbWF4KGFhYWFtYTcsbmEucm09VCk7ICAgYWExW2pqajQrNywidHh4Il08LW1heChhYWFhbWE4LG5hLnJtPVQpDQogICAgICAgIGFhMVtqamo0KzgsInR4eCJdPC1tYXgoYWFhYW1hOSxuYS5ybT1UKTsgICBhYTFbampqNCs5LCJ0eHgiXTwtbWF4KGFhYWFtYTEwLG5hLnJtPVQpDQogICAgICAgIGFhMVtqamo0KzEwLCJ0eHgiXTwtbWF4KGFhYWFtYTExLG5hLnJtPVQpOyBhYTFbampqNCsxMSwidHh4Il08LW1heChhYWFhbWExMixuYS5ybT1UKQ0KICAgICAgICANCiAgICAgICAgYWExW2pqajQsInR4biJdPC1taW4oYWFhYW1hMSxuYS5ybT1UKTsgICAgIGFhMVtqamo0KzEsInR4biJdPC1taW4oYWFhYW1hMixuYS5ybT1UKQ0KICAgICAgICBhYTFbampqNCsyLCJ0eG4iXTwtbWluKGFhYWFtYTMsbmEucm09VCk7ICAgYWExW2pqajQrMywidHhuIl08LW1pbihhYWFhbWE0LG5hLnJtPVQpDQogICAgICAgIGFhMVtqamo0KzQsInR4biJdPC1taW4oYWFhYW1hNSxuYS5ybT1UKTsgICBhYTFbampqNCs1LCJ0eG4iXTwtbWluKGFhYWFtYTYsbmEucm09VCkNCiAgICAgICAgYWExW2pqajQrNiwidHhuIl08LW1pbihhYWFhbWE3LG5hLnJtPVQpOyAgIGFhMVtqamo0KzcsInR4biJdPC1taW4oYWFhYW1hOCxuYS5ybT1UKQ0KICAgICAgICBhYTFbampqNCs4LCJ0eG4iXTwtbWluKGFhYWFtYTksbmEucm09VCk7ICAgYWExW2pqajQrOSwidHhuIl08LW1pbihhYWFhbWExMCxuYS5ybT1UKQ0KICAgICAgICBhYTFbampqNCsxMCwidHhuIl08LW1pbihhYWFhbWExMSxuYS5ybT1UKTsgYWExW2pqajQrMTEsInR4biJdPC1taW4oYWFhYW1hMTIsbmEucm09VCkNCiAgICAgICAgDQogICAgICAgIGFhMVtqamo0LCJ0bngiXTwtbWF4KGFhYWFtaTEsbmEucm09VCk7ICAgICBhYTFbampqNCsxLCJ0bngiXTwtbWF4KGFhYWFtaTIsbmEucm09VCkNCiAgICAgICAgYWExW2pqajQrMiwidG54Il08LW1heChhYWFhbWkzLG5hLnJtPVQpOyAgIGFhMVtqamo0KzMsInRueCJdPC1tYXgoYWFhYW1pNCxuYS5ybT1UKQ0KICAgICAgICBhYTFbampqNCs0LCJ0bngiXTwtbWF4KGFhYWFtaTUsbmEucm09VCk7ICAgYWExW2pqajQrNSwidG54Il08LW1heChhYWFhbWk2LG5hLnJtPVQpDQogICAgICAgIGFhMVtqamo0KzYsInRueCJdPC1tYXgoYWFhYW1pNyxuYS5ybT1UKTsgICBhYTFbampqNCs3LCJ0bngiXTwtbWF4KGFhYWFtaTgsbmEucm09VCkNCiAgICAgICAgYWExW2pqajQrOCwidG54Il08LW1heChhYWFhbWk5LG5hLnJtPVQpOyAgIGFhMVtqamo0KzksInRueCJdPC1tYXgoYWFhYW1pMTAsbmEucm09VCkNCiAgICAgICAgYWExW2pqajQrMTAsInRueCJdPC1tYXgoYWFhYW1pMTEsbmEucm09VCk7IGFhMVtqamo0KzExLCJ0bngiXTwtbWF4KGFhYWFtaTEyLG5hLnJtPVQpDQogICAgICAgIA0KICAgICAgICBhYTFbampqNCwidG5uIl08LW1pbihhYWFhbWkxKTthYTFbampqNCsxLCJ0bm4iXTwtbWluKGFhYWFtaTIsbmEucm09VCkNCiAgICAgICAgYWExW2pqajQrMiwidG5uIl08LW1pbihhYWFhbWkzLG5hLnJtPVQpOyAgIGFhMVtqamo0KzMsInRubiJdPC1taW4oYWFhYW1pNCxuYS5ybT1UKQ0KICAgICAgICBhYTFbampqNCs0LCJ0bm4iXTwtbWluKGFhYWFtaTUsbmEucm09VCk7ICAgYWExW2pqajQrNSwidG5uIl08LW1pbihhYWFhbWk2LG5hLnJtPVQpDQogICAgICAgIGFhMVtqamo0KzYsInRubiJdPC1taW4oYWFhYW1pNyxuYS5ybT1UKTsgICBhYTFbampqNCs3LCJ0bm4iXTwtbWluKGFhYWFtaTgsbmEucm09VCkNCiAgICAgICAgYWExW2pqajQrOCwidG5uIl08LW1pbihhYWFhbWk5LG5hLnJtPVQpOyAgIGFhMVtqamo0KzksInRubiJdPC1taW4oYWFhYW1pMTAsbmEucm09VCkNCiAgICAgICAgYWExW2pqajQrMTAsInRubiJdPC1taW4oYWFhYW1pMTEsbmEucm09VCk7IGFhMVtqamo0KzExLCJ0bm4iXTwtbWluKGFhYWFtaTEyLG5hLnJtPVQpDQogICAgICAgIA0KICAgICAgICBqamo0PWpqajQrMTJ9DQogICAgZXhkYXl0ZW08LWFzLmRhdGEuZnJhbWUoYWExKQ0KICAgICMgICAgbWlkbmFjb3I8LW5hY29yW25hY29yJHllYXI+PXN0YXJ0eWVhcixdDQogICAgIyAgICBtaWRuYWNvcjwtbWlkbmFjb3JbbWlkbmFjb3IkeWVhcjw9ZW5keWVhcixdDQogICAgZXhkYXl0ZW1bLCJ0eHgiXTwtZXhkYXl0ZW1bLCJ0eHgiXStuYWNvclssIm1uYXRtYT4zIl0NCiAgICBleGRheXRlbVssInR4biJdPC1leGRheXRlbVssInR4biJdK25hY29yWywibW5hdG1hPjMiXQ0KICAgIGV4ZGF5dGVtWywidG54Il08LWV4ZGF5dGVtWywidG54Il0rbmFjb3JbLCJtbmF0bWk+MyJdDQogICAgZXhkYXl0ZW1bLCJ0bm4iXTwtZXhkYXl0ZW1bLCJ0bm4iXStuYWNvclssIm1uYXRtaT4zIl0NCiAgICANCiAgICBmb3IoaSBpbiBjKCJ0eHgiLCJ0eG4iLCJ0bngiLCJ0bm4iKSl7DQogICAgICAgIGlmIChpPT0idHh4Iikge2lpPC0iX1RYeC5jc3YiO2lqPC0iX1RYeC5qcGciO2trPC0zO2lrPC0xO2tpPC0zfSMgaWs9MSwgdGFrZSBtYXggYXMgeWVhcmx5IHJlY29yZA0KICAgICAgICBpZiAoaT09InR4biIpIHtpaTwtIl9UWG4uY3N2IjtpajwtIl9UWG4uanBnIjtrazwtNDtpazwtMDtraTwtM30jIGlrPTAsIHRha2UgbWluIGFzIHllYXJseSByZWNvcmQNCiAgICAgICAgaWYgKGk9PSJ0bngiKSB7aWk8LSJfVE54LmNzdiI7aWo8LSJfVE54LmpwZyI7a2s8LTU7aWs8LTE7a2k8LTR9IyBraT0zLCB0YWtlIFRNQVggYW5udWFsIG1pc3NpbmcgdmFsdWVzDQogICAgICAgIGlmIChpPT0idG5uIikge2lpPC0iX1RObi5jc3YiO2lqPC0iX1RObi5qcGciO2trPC02O2lrPC0wO2tpPC00fSMga2k9NCwgdGFrZSBUTUlOIGFubnVhbCBtaXNzaW5nIHZhbHVlcw0KICAgICAgICBuYW08LXBhc3RlKG91dGluZGRpcixwYXN0ZShvZmlsZW5hbWUsaWksc2VwPSIiKSxzZXA9Ii8iKQ0KICAgICAgICBvZmlsZTwtbWF0cml4KDAsbGVuLDE0KQ0KICAgICAgICAjICAgIG9qcGc8LXJlcCgwLGxlbikNCiAgICAgICAgZGltbmFtZXMob2ZpbGUpPC1saXN0KE5VTEwsYygieWVhciIsImphbiIsImZlYiIsIm1hciIsImFwciIsIm1heSIsImp1biIsImp1bCIsImF1ZyIsInNlcCIsIm9jdCIsIm5vdiIsImRlYyIsImFubnVhbCIpKQ0KICAgICAgICBvZmlsZTwtYXMuZGF0YS5mcmFtZShvZmlsZSkNCiAgICAgICAgZm9yKGogaW4geWVhcnM6eWVhcmUpew0KICAgICAgICAgICAgazwtai15ZWFycysxDQogICAgICAgICAgICBvZmlsZVtrLDFdPC1qDQogICAgICAgICAgICBvZmlsZVtrLDI6MTNdPC1leGRheXRlbVtleGRheXRlbSR5ZWFyPT1qLGtrXQ0KICAgICAgICAgICAgaWYoaWs9PTEpIG9maWxlW2ssMTRdPC1tYXgob2ZpbGVbaywyOjEzXSxuYS5ybT1UKQ0KICAgICAgICAgICAgZWxzZSBvZmlsZVtrLDE0XTwtbWluKG9maWxlW2ssMjoxM10sbmEucm09VCkNCiAgICAgICAgfQ0KICAgICAgICBvZmlsZVssMTRdPC1vZmlsZVssMTRdK3luYWNvclssa2ldDQogICAgICAgIHdyaXRlLnRhYmxlKG9maWxlLGZpbGU9bmFtLGFwcGVuZD1GLHF1b3RlPUYsc2VwPSIsICIsbmE9Ii05OS45Iixyb3cubmFtZXM9RikNCiAgICAgICAgDQogICAgICAgIG5hbXQ8LXBhc3RlKG91dHRyZGRpcixwYXN0ZShvZmlsZW5hbWUsIl90cmVuZC5jc3YiLHNlcD0iIiksc2VwPSIvIikNCiAgICAgICAgaWYoc3VtKGlzLm5hKG9maWxlWywxNF0pKT49KHllYXJlLXllYXJzKzEtMTApKXsNCiAgICAgICAgICAgIGJldGFoYXQ8LU5BDQogICAgICAgICAgICBiZXRhc3RkPC1OQQ0KICAgICAgICAgICAgcHZhbHVlPC1OQQ0KICAgICAgICB9DQogICAgICAgIGVsc2V7DQogICAgICAgICAgICBmaXQxPC1sc2ZpdChvZmlsZVssMV0sb2ZpbGVbLDE0XSkNCiAgICAgICAgICAgIG91dDE8LWxzLnByaW50KGZpdDEscHJpbnQuaXQ9RikNCiAgICAgICAgICAgIHB2YWx1ZTwtcm91bmQoYXMubnVtZXJpYyhvdXQxJHN1bW1hcnlbMSw2XSksMykNCiAgICAgICAgICAgIGJldGFoYXQ8LXJvdW5kKGFzLm51bWVyaWMob3V0MSRjb2VmLnRhYmxlW1sxXV1bMiwxXSksMykNCiAgICAgICAgICAgIGJldGFzdGQ8LXJvdW5kKGFzLm51bWVyaWMob3V0MSRjb2VmLnRhYmxlW1sxXV1bMiwyXSksMykNCiAgICAgICAgfQ0KICAgICAgICBjYXQoZmlsZT1uYW10LHBhc3RlKGxhdGl0dWRlLGxvbmdpdHVkZSxpLHllYXJzLHllYXJlLGJldGFoYXQsYmV0YXN0ZCxwdmFsdWUsc2VwPSIsIiksZmlsbD0xODAsYXBwZW5kPVQpDQogICAgICAgIA0KICAgICAgICBuYW0yPC1wYXN0ZShvdXRqcGdkaXIscGFzdGUob2ZpbGVuYW1lLGlqLHNlcD0iIiksc2VwPSIvIikNCiAgICAgICAganBlZyhuYW0yLHdpZHRoPTEwMjQsaGVpZ2h0PTc2OCkNCiAgICAgICAgcGxvdHgob2ZpbGVbLDFdLG9maWxlWywxNF0sbWFpbj1wYXN0ZSh0b3VwcGVyKGkpLG9maWxlbmFtZSxzZXA9IiAgICIpLHhsYWI9IlllYXIiLHlsYWI9KHBhc3RlKHRvdXBwZXIoc3Vic3RyKGksMSwyKSksc3Vic3RyKGksMywzKSxzZXA9IiIpKSkNCiAgICAgICAgZGV2Lm9mZigpDQogICAgfQ0KfQ0KIy0tLS0tLS0tLS0tIGV4dHJlbWVkYXl0ZW0gZW5kcyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSAgDQoNCiMtLS0tLS0tLS0tLSBpbmRleDY0NiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSAgDQppbmRleDY0NjwtZnVuY3Rpb24oKXsNCiAgICB5cz15ZWFyZS15ZWFycysxDQogICAgYjwtbWF0cml4KDAsbmNvbD0yLG5yb3c9eXMpDQogICAgZGltbmFtZXMoYik8LWxpc3QoTlVMTCxjKCJ5ZWFyIiwic2RpaSIpKQ0KICAgIGJbLCJ5ZWFyIl08LWMoeWVhcnM6eWVhcmUpDQogICAgYjwtYXMuZGF0YS5mcmFtZShiKQ0KICAgIHllYXI9eWVhcnMNCiAgICBmb3IgKGkgaW4gMTp5cyl7DQogICAgICAgIG1pZDwtZGRbZGQkeWVhcj09eWVhciwicHJjcCJdDQogICAgICAgIG1pZDwtbWlkW21pZD49MV0NCiAgICAgICAgYltpLCJzZGlpIl08LW1lYW4obWlkLG5hLnJtPVQpDQogICAgICAgIHllYXI9eWVhcisxICB9DQogICAgYlssInNkaWkiXTwtYlssInNkaWkiXSt5bmFjb3JbLCJ5bmFwcj4xNSJdDQogICAgbmFtMTwtcGFzdGUob3V0aW5kZGlyLHBhc3RlKG9maWxlbmFtZSwiX1NESUkuY3N2IixzZXA9IiIpLHNlcD0iLyIpDQogICAgd3JpdGUudGFibGUocm91bmQoYixkaWdpdD0xKSxmaWxlPW5hbTEsYXBwZW5kPUYscXVvdGU9RixzZXA9IiwgIixuYT0iLTk5LjkiLHJvdy5uYW1lcz1GKQ0KICAgIA0KICAgIG5hbXQ8LXBhc3RlKG91dHRyZGRpcixwYXN0ZShvZmlsZW5hbWUsIl90cmVuZC5jc3YiLHNlcD0iIiksc2VwPSIvIikNCiAgICBpZihzdW0oaXMubmEoYlssInNkaWkiXSkpPj0oeWVhcmUteWVhcnMrMS0xMCkpew0KICAgICAgICBiZXRhaGF0PC1OQQ0KICAgICAgICBiZXRhc3RkPC1OQQ0KICAgICAgICBwdmFsdWU8LU5BDQogICAgfQ0KICAgIGVsc2V7DQogICAgICAgIGZpdDE8LWxzZml0KGJbLCJ5ZWFyIl0sYlssInNkaWkiXSkNCiAgICAgICAgb3V0MTwtbHMucHJpbnQoZml0MSxwcmludC5pdD1GKQ0KICAgICAgICBwdmFsdWU8LXJvdW5kKGFzLm51bWVyaWMob3V0MSRzdW1tYXJ5WzEsNl0pLDMpDQogICAgICAgIGJldGFoYXQ8LXJvdW5kKGFzLm51bWVyaWMob3V0MSRjb2VmLnRhYmxlW1sxXV1bMiwxXSksMykNCiAgICAgICAgYmV0YXN0ZDwtcm91bmQoYXMubnVtZXJpYyhvdXQxJGNvZWYudGFibGVbWzFdXVsyLDJdKSwzKQ0KICAgIH0NCiAgICBjYXQoZmlsZT1uYW10LHBhc3RlKGxhdGl0dWRlLGxvbmdpdHVkZSwic2RpaSIseWVhcnMseWVhcmUsYmV0YWhhdCxiZXRhc3RkLHB2YWx1ZSxzZXA9IiwiKSxmaWxsPTE4MCxhcHBlbmQ9VCkNCiAgICANCiAgICBuYW0yPC1wYXN0ZShvdXRqcGdkaXIscGFzdGUob2ZpbGVuYW1lLCJfU0RJSS5qcGciLHNlcD0iIiksc2VwPSIvIikNCiAgICBqcGVnKG5hbTIsd2lkdGg9MTAyNCxoZWlnaHQ9NzY4KQ0KICAgIHBsb3R4KGJbLDFdLGJbLDJdLG1haW49cGFzdGUoIlNESUkiLG9maWxlbmFtZSxzZXA9IiAgICIpLHhsYWI9IlllYXIiLHlsYWI9IlNESUkiKQ0KICAgIGRldi5vZmYoKQ0KfQ0KIy0tLS0tLS0tLS0tIGluZGV4NjQ2IGVuZHMgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0gIA0KDQojLS0tLS0tLS0tLS0gbWFpbjEgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0gIA0KbWFpbjE8LWZ1bmN0aW9uKCl7DQogICAgbWFpbjwtdGt0b3BsZXZlbCgpDQogICAgdGtmb2N1cyhtYWluKQ0KICAgIHRrd20udGl0bGUobWFpbiwiQ2FsY3VsYXRpbmcgQ2xpbWF0ZSBJbmRpY2VzIikNCiAgICB0a2dyaWQodGtsYWJlbChtYWluLHRleHQ9IkNoZWNrIGRlc2lyZWQgaW5kaWNlcyIsZm9udD1mb250SGVhZGluZzEpKQ0KICAgIHR4dD0iSXQgbWF5IHRha2UgNSBtaW51dGVzIHRvIGNvbXB1dGUgYWxsIHRoZSBpbmRpY2VzLCAiDQogICAgIwlpZihwcmFsbG5hPT0xKSB0a2dyaWQodGtsYWJlbChtYWluLCB0ZXh0PSJQUkNQIGFsbCBtaXNzaW5nLCBpbmRpY2VzIHJlbGF0ZWQgdG8gUFJDUCBtYXkgbm90IGJlIGNhbGN1bGF0ZWQiLGZvbnQ9Zm9udEhlYWRpbmcyKSkNCiAgICAjCWlmKHR4YWxsbmE9PTF8dG5hbGxuYT09MSkgdGtncmlkKHRrbGFiZWwobWFpbix0ZXh0PSJUTUFYIG9yIFRNSU4gYWxsIG1pc3NpbmcsIGluZGljZXMgcmVsYXRlZCB0byBUTUFYIGFuZCBUTUlOIG1heSBub3QgYmUgY2FsY3VsYXRlZCIsZm9udD1mb250SGVhZGluZzIpKQ0KICAgIA0KICAgICNjYjAgPC0gdGtjaGVja2J1dHRvbihtYWluKTtjYjBWYWwgPC0gY2J2YWx1ZTANCiAgICANCiAgICBjYjEgPC0gdGtjaGVja2J1dHRvbihtYWluKTsgIGNiMVZhbCA8LSBjYnZhbHVlMQ0KICAgIGNiMiA8LSB0a2NoZWNrYnV0dG9uKG1haW4pOyAgY2IyVmFsIDwtIGNidmFsdWUyDQogICAgY2IzIDwtIHRrY2hlY2tidXR0b24obWFpbik7ICBjYjNWYWwgPC0gY2J2YWx1ZTMNCiAgICBjYjQgPC0gdGtjaGVja2J1dHRvbihtYWluKTsgIGNiNFZhbCA8LSBjYnZhbHVlNA0KICAgIGNiNSA8LSB0a2NoZWNrYnV0dG9uKG1haW4pOyAgY2I1VmFsIDwtIGNidmFsdWU1DQogICAgY2I2IDwtIHRrY2hlY2tidXR0b24obWFpbik7ICBjYjZWYWwgPC0gY2J2YWx1ZTYNCiAgICBjYjcgPC0gdGtjaGVja2J1dHRvbihtYWluKTsgIGNiN1ZhbCA8LSBjYnZhbHVlNw0KICAgIGNiOCA8LSB0a2NoZWNrYnV0dG9uKG1haW4pOyAgY2I4VmFsIDwtIGNidmFsdWU4DQogICAgY2I5IDwtIHRrY2hlY2tidXR0b24obWFpbik7ICBjYjlWYWwgPC0gY2J2YWx1ZTkNCiAgICBjYjEwIDwtIHRrY2hlY2tidXR0b24obWFpbik7IGNiMTBWYWwgPC0gY2J2YWx1ZTEwDQogICAgY2IxMSA8LSB0a2NoZWNrYnV0dG9uKG1haW4pOyBjYjExVmFsIDwtIGNidmFsdWUxMQ0KICAgIGNiMTIgPC0gdGtjaGVja2J1dHRvbihtYWluKTsgY2IxMlZhbCA8LSBjYnZhbHVlMTINCiAgICBjYjEzIDwtIHRrY2hlY2tidXR0b24obWFpbik7IGNiMTNWYWwgPC0gY2J2YWx1ZTEzDQogICAgY2IxNCA8LSB0a2NoZWNrYnV0dG9uKG1haW4pOyBjYjE0VmFsIDwtIGNidmFsdWUxNA0KICAgIGNiMTUgPC0gdGtjaGVja2J1dHRvbihtYWluKTsgY2IxNVZhbCA8LSBjYnZhbHVlMTUNCiAgICBjYjIxIDwtIHRrY2hlY2tidXR0b24obWFpbik7IGNiMjFWYWwgPC0gY2J2YWx1ZTIxDQogICAgDQogICAgI3RrY29uZmlndXJlKGNiMCx2YXJpYWJsZT1jYjBWYWwpIyx2YWx1ZT1jYjFWYWwpDQogICAgdGtjb25maWd1cmUoY2IxLHZhcmlhYmxlPWNiMVZhbCkjLHZhbHVlPWNiMVZhbCkNCiAgICB0a2NvbmZpZ3VyZShjYjIsdmFyaWFibGU9Y2IyVmFsKSMsdmFsdWU9Y2IyVmFsKQ0KICAgIHRrY29uZmlndXJlKGNiMyx2YXJpYWJsZT1jYjNWYWwpIyx2YWx1ZT1jYjNWYWwpIyJkdHIiKQ0KICAgIHRrY29uZmlndXJlKGNiNCx2YXJpYWJsZT1jYjRWYWwpIyx2YWx1ZT1jYjRWYWwpIyJkYXlzcHJjcDEwIikNCiAgICB0a2NvbmZpZ3VyZShjYjUsdmFyaWFibGU9Y2I1VmFsKSMsdmFsdWU9Y2I1VmFsKSMibm9yZGF5dGVtMSIpDQogICAgdGtjb25maWd1cmUoY2I2LHZhcmlhYmxlPWNiNlZhbCkjLHZhbHVlPWNiNlZhbCkjImV4dHJlbWVkYXlzIikNCiAgICB0a2NvbmZpZ3VyZShjYjcsdmFyaWFibGU9Y2I3VmFsKSMsdmFsdWU9Y2I3VmFsKSMiZXhjZWVkYW5jZSIpDQogICAgdGtjb25maWd1cmUoY2I4LHZhcmlhYmxlPWNiOFZhbCkjLHZhbHVlPWNiOFZhbCkjImluZDE0NGh3ZCIpDQogICAgdGtjb25maWd1cmUoY2I5LHZhcmlhYmxlPWNiOVZhbCkjLHZhbHVlPWNiOVZhbCkjImluZDY0MWNkZCIpDQogICAgdGtjb25maWd1cmUoY2IxMCx2YXJpYWJsZT1jYjEwVmFsKSMsdmFsdWU9Y2IxMFZhbCkjInJ4NWQiKQ0KICAgIHRrY29uZmlndXJlKGNiMTEsdmFyaWFibGU9Y2IxMVZhbCkjLHZhbHVlPWNiMTFWYWwpIyJpbmQ2NDYiKQ0KICAgIHRrY29uZmlndXJlKGNiMTIsdmFyaWFibGU9Y2IxMlZhbCkjLHZhbHVlPWNiMTJWYWwpIyJpbmQ2OTUiKQ0KICAgIHRrY29uZmlndXJlKGNiMTMsdmFyaWFibGU9Y2IxM1ZhbCkjLHZhbHVlPWNiMTNWYWwpIyJyeDFkIg0KICAgIHRrY29uZmlndXJlKGNiMTQsdmFyaWFibGU9Y2IxNFZhbCkjLHZhbHVlPWNiMTRWYWwpIyJleHRyZW1lIGRheSB0ZW0iDQogICAgdGtjb25maWd1cmUoY2IxNSx2YXJpYWJsZT1jYjE1VmFsKQ0KICAgIHRrY29uZmlndXJlKGNiMjEsdmFyaWFibGU9Y2IyMVZhbCkNCiAgICANCiAgICAjdGtncmlkKHRrbGFiZWwobWFpbix0ZXh0PSJTZWxlY3QgdGhlIGluZGljZXMgeW91IHdhbnQgdG8gY2FsY3VsYXRlOiIpKQ0KICAgIA0KICAgICN0a2dyaWQodGtsYWJlbChtYWluLHRleHQ9IkFMTCAyNiBpbmRpY2VzISEiKSxjYjApDQogICAgdGtncmlkKHRrbGFiZWwobWFpbix0ZXh0PSJTVTI1LCBGRDAsIFRSMjAsIElEMCIpLGNiMSkNCiAgICB0a2dyaWQodGtsYWJlbChtYWluLHRleHQ9IlVzZXIgRGVmaW5lZCBTVSwgRkQsIFRSLCBJRCIpLGNiMjEpDQogICAgDQogICAgdGtncmlkKHRrbGFiZWwobWFpbix0ZXh0PSJHU0wsIGdyb3dpbmcgc2Vhc29uIGxlbmd0aCIpLGNiMikjMTQzDQogICAgDQogICAgdGtncmlkKHRrbGFiZWwobWFpbix0ZXh0PSJUWHgsIFRYbiwgVE54LCBUTm4iKSxjYjMpDQogICAgI3RrZ3JpZCh0a2xhYmVsKG1haW4sdGV4dD0iVFhuLCBUTngsIFRObiwgZm9sbG93aW5nIGJ5IHNhbWUgY2hvaWNlIiksY2IzKSNleHRyZW1lZGF5dGVtDQogICAgDQogICAgdGtncmlkKHRrbGFiZWwobWFpbix0ZXh0PSJUWDEwcCwgVFg5MHAsIFROMTBwLCBUTjkwcCIpLGNiNCkNCiAgICAjdGtncmlkKHRrbGFiZWwobWFpbix0ZXh0PSJUWDkwcCwgVE4xMHAsIFROOTBwLCBmb2xsb3dpbmcgYnkgc2FtZSBjaG9pY2UiKSxjYjQpI2V4Y2VlZGFuY2UNCiAgICANCiAgICB0a2dyaWQodGtsYWJlbChtYWluLHRleHQ9IldTREkiKSxjYjUpI2h3ZmkNCiAgICB0a2dyaWQodGtsYWJlbChtYWluLHRleHQ9IkNTREkiKSxjYjYpI2N3ZGkNCiAgICANCiAgICAjdGtncmlkKHRrbGFiZWwobWFpbix0ZXh0PSJOb3JtYWwgZGF5IHRlbXBlcmF0dXJlIHdpdGggdXNlciBkZWZpbmVkIHdpbmRvdyBzaXplIiksY2IyKQ0KICAgIHRrZ3JpZCh0a2xhYmVsKG1haW4sdGV4dD0iRFRSIiksY2I3KSNkdHINCiAgICANCiAgICB0a2dyaWQodGtsYWJlbChtYWluLHRleHQ9IlJ4MWRheSIpLGNiOCkjcngxZA0KICAgIHRrZ3JpZCh0a2xhYmVsKG1haW4sdGV4dD0iUng1ZGF5IiksY2I5KSNyeDVkDQogICAgDQogICAgdGtncmlkKHRrbGFiZWwobWFpbix0ZXh0PSJTRElJIiksY2IxMCkjaW5kZXg2NDYNCiAgICANCiAgICB0a2dyaWQodGtsYWJlbChtYWluLHRleHQ9IlIxMG1tIiksY2IxMSkjZGF5c3ByY3AxMCgpDQogICAgdGtncmlkKHRrbGFiZWwobWFpbix0ZXh0PSJSMjBtbSIpLGNiMTIpI2RheXNwcmNwMjAoKQ0KICAgIHRrZ3JpZCh0a2xhYmVsKG1haW4sdGV4dD0iUm5ubW0iKSxjYjEzKSNkYXlzcHJjcG4oKQ0KICAgIA0KICAgIHRrZ3JpZCh0a2xhYmVsKG1haW4sdGV4dD0iQ0RELCBDV0QiKSxjYjE0KQ0KICAgICN0a2dyaWQodGtsYWJlbChtYWluLHRleHQ9IkNXRCIpLGNiMTQpIzY0MQ0KICAgIA0KICAgICN0a2dyaWQodGtsYWJlbChtYWluLHRleHQ9ImRheW5vcnRlbSAgICAgIiksY2I1KQ0KICAgICN0a2dyaWQodGtsYWJlbChtYWluLHRleHQ9ImluZDE0NGh3ZCAgICAgICIpLGNiOCkjMTQ0DQogICAgDQogICAgdGtncmlkKHRrbGFiZWwobWFpbix0ZXh0PSJSOTVwLCBSOTlwLCBQUkNQVE9UIiksY2IxNSkjNjk1DQogICAgI3RrZ3JpZCh0a2xhYmVsKG1haW4sdGV4dD0iUjk5cFRPVCIpLGNiMTUpDQogICAgDQogICAgI3RrZ3JpZCh0a2xhYmVsKG1haW4sdGV4dD0iQW5udWFsIERheXMgd2l0aCBQUkNQPj05NSBwZXJjZW50aWxlIiksY2IxNykjcjk1cHRvdA0KICAgICN0a2dyaWQodGtsYWJlbChtYWluLHRleHQ9IkFubnVhbCBEYXlzIHdpdGggUFJDUD49OTkgcGVyY2VudGlsZSIpLGNiMTcpDQogICAgDQogICAgIy0tLS0tLS0tLS0tIE9uT0sgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0gIA0KICAgIE9uT0sgPC0gZnVuY3Rpb24oKXsNCiAgICAgICAgI2ZpbGVuYW1lPC10Y2x2YWx1ZSh0a2dldFNhdmVGaWxlKGZpbGV0eXBlcz0ie3tFWENFTCBGaWxlc30gey5jc3Z9fSB7e0FsbCBmaWxlc30gKn0iKSkNCiAgICAgICAgI2lmICghbmNoYXIoZmlsZW5hbWUpKQ0KICAgICAgICAjdGttZXNzYWdlQm94KG1lc3NhZ2U9Ik5vIGZpbGUgd2FzIHNlbGVjdGVkISIpDQogICAgICAgICNlbHNlIHRrbWVzc2FnZUJveChtZXNzYWdlPXBhc3RlKCJUaGUgcmVzdWx0cyB3aWxsIGJlIHNhdmVkIHVuZGVyIixmaWxlbmFtZSkpDQogICAgICAgICNuYW08LXN1YnN0cihmaWxlbmFtZSxzdGFydD0xLHN0b3A9KG5jaGFyKGZpbGVuYW1lKS00KSkNCiAgICAgICAgI2Fzc2lnbigibmFtIixuYW0sZW52aXI9Lkdsb2JhbEVudikNCiAgICAgICAgDQogICAgICAgICMgICAgY2J2MCA8LSBhcy5jaGFyYWN0ZXIodGNsdmFsdWUoY2IwVmFsKSkNCiAgICAgICAgY2J2MSA8LSBhcy5jaGFyYWN0ZXIodGNsdmFsdWUoY2IxVmFsKSkNCiAgICAgICAgY2J2MjEgPC0gYXMuY2hhcmFjdGVyKHRjbHZhbHVlKGNiMjFWYWwpKQ0KICAgICAgICBjYnYyIDwtIGFzLmNoYXJhY3Rlcih0Y2x2YWx1ZShjYjJWYWwpKQ0KICAgICAgICBjYnYzIDwtIGFzLmNoYXJhY3Rlcih0Y2x2YWx1ZShjYjNWYWwpKQ0KICAgICAgICBjYnY0IDwtIGFzLmNoYXJhY3Rlcih0Y2x2YWx1ZShjYjRWYWwpKQ0KICAgICAgICBjYnY1IDwtIGFzLmNoYXJhY3Rlcih0Y2x2YWx1ZShjYjVWYWwpKQ0KICAgICAgICBjYnY2IDwtIGFzLmNoYXJhY3Rlcih0Y2x2YWx1ZShjYjZWYWwpKQ0KICAgICAgICBjYnY3IDwtIGFzLmNoYXJhY3Rlcih0Y2x2YWx1ZShjYjdWYWwpKQ0KICAgICAgICBjYnY4IDwtIGFzLmNoYXJhY3Rlcih0Y2x2YWx1ZShjYjhWYWwpKQ0KICAgICAgICBjYnY5IDwtIGFzLmNoYXJhY3Rlcih0Y2x2YWx1ZShjYjlWYWwpKQ0KICAgICAgICBjYnYxMCA8LSBhcy5jaGFyYWN0ZXIodGNsdmFsdWUoY2IxMFZhbCkpDQogICAgICAgIGNidjExIDwtIGFzLmNoYXJhY3Rlcih0Y2x2YWx1ZShjYjExVmFsKSkNCiAgICAgICAgY2J2MTIgPC0gYXMuY2hhcmFjdGVyKHRjbHZhbHVlKGNiMTJWYWwpKQ0KICAgICAgICBjYnYxMyA8LSBhcy5jaGFyYWN0ZXIodGNsdmFsdWUoY2IxM1ZhbCkpDQogICAgICAgIGNidjE0IDwtIGFzLmNoYXJhY3Rlcih0Y2x2YWx1ZShjYjE0VmFsKSkNCiAgICAgICAgY2J2MTUgPC0gYXMuY2hhcmFjdGVyKHRjbHZhbHVlKGNiMTVWYWwpKQ0KICAgICAgICB0a2Rlc3Ryb3kobWFpbikNCiAgICAgICAgIyAgICBpZiAoY2J2MD09MSkge2NidjE8LTE7Y2J2MjwtMTtjYnYzPC0xO2NidjQ8LTE7Y2J2NTwtMTsNCiAgICAgICAgbmFtdDwtcGFzdGUob3V0dHJkZGlyLHBhc3RlKG9maWxlbmFtZSwiX3RyZW5kLmNzdiIsc2VwPSIiKSxzZXA9Ii8iKQ0KICAgICAgICBjYXQoZmlsZT1uYW10LHBhc3RlKCJMb24iLCJMYXQiLCJJbmRpY2VzIiwiU1llYXIiLCJFWWVhciIsIlNsb3BlIiwiU1REX29mX1Nsb3BlIiwiUF9WYWx1ZSIsc2VwPSIsIiksZmlsbD0xODAsYXBwZW5kPUYpDQogICAgICAgIGlmIChjYnYxPT0xKSBpZih0eGFsbG5hPT0wJnRuYWxsbmE9PTApIGV4dHJlbWVkYXlzKCkNCiAgICAgICAgaWYgKGNidjIxPT0xKSBpZih0eGFsbG5hPT0wJnRuYWxsbmE9PTApIGV4dHJlbWVkYXlzKG9wdD0xKQ0KICAgICAgICBpZiAoY2J2Mj09MSkgaWYodHhhbGxuYT09MCZ0bmFsbG5hPT0wKSBpbmQxNDNnc2woKQ0KICAgICAgICBpZiAoY2J2Mz09MSkgaWYodHhhbGxuYT09MCZ0bmFsbG5hPT0wKSBleHRyZW1lZGF5dGVtKCkNCiAgICAgICAgaWYgKGNidjQ9PTEpIGlmKHR4YWxsbmE9PTAmdG5hbGxuYT09MCkgZXhjZWVkYW5jZSgpDQogICAgICAgIGlmIChjYnY1PT0xKSBpZih0eGFsbG5hPT0wKSBod2ZpKCkNCiAgICAgICAgaWYgKGNidjY9PTEpIGlmKHRuYWxsbmE9PTApIGN3ZGkoKQ0KICAgICAgICBpZiAoY2J2Nz09MSkgaWYodHhhbGxuYT09MCZ0bmFsbG5hPT0wKSBkdHIoKQ0KICAgICAgICBpZiAoY2J2OD09MSkgaWYocHJhbGxuYT09MCkgcngxZCgpDQogICAgICAgIGlmIChjYnY5PT0xKSBpZihwcmFsbG5hPT0wKSByeDVkKCkNCiAgICAgICAgaWYgKGNidjEwPT0xKSBpZihwcmFsbG5hPT0wKSBpbmRleDY0NigpDQogICAgICAgIGlmIChjYnYxMT09MSkgaWYocHJhbGxuYT09MCkgZGF5c3ByY3AxMCgpDQogICAgICAgIGlmIChjYnYxMj09MSkgaWYocHJhbGxuYT09MCkgZGF5c3ByY3AyMCgpDQogICAgICAgIGlmIChjYnYxMz09MSkgaWYocHJhbGxuYT09MCkgZGF5c3ByY3BuKCkNCiAgICAgICAgaWYgKGNidjE0PT0xKSBpZihwcmFsbG5hPT0wKSB7aW5kZXg2NDFjZGQoKTtpbmRleDY0MWN3ZCgpfQ0KICAgICAgICBpZiAoY2J2MTU9PTEpIGlmKHByYWxsbmE9PTApIHI5NXB0b3QoKQ0KICAgICAgICBjYnZhbHVlMTwtY2IxVmFsO2Fzc2lnbigiY2J2YWx1ZTEiLGNidmFsdWUxLGVudmlyPS5HbG9iYWxFbnYpDQogICAgICAgIGNidmFsdWUyPC1jYjJWYWw7YXNzaWduKCJjYnZhbHVlMiIsY2J2YWx1ZTIsZW52aXI9Lkdsb2JhbEVudikNCiAgICAgICAgY2J2YWx1ZTM8LWNiM1ZhbDthc3NpZ24oImNidmFsdWUzIixjYnZhbHVlMyxlbnZpcj0uR2xvYmFsRW52KQ0KICAgICAgICBjYnZhbHVlNDwtY2I0VmFsO2Fzc2lnbigiY2J2YWx1ZTQiLGNidmFsdWU0LGVudmlyPS5HbG9iYWxFbnYpDQogICAgICAgIGNidmFsdWU1PC1jYjVWYWw7YXNzaWduKCJjYnZhbHVlNSIsY2J2YWx1ZTUsZW52aXI9Lkdsb2JhbEVudikNCiAgICAgICAgY2J2YWx1ZTY8LWNiNlZhbDthc3NpZ24oImNidmFsdWU2IixjYnZhbHVlNixlbnZpcj0uR2xvYmFsRW52KQ0KICAgICAgICBjYnZhbHVlNzwtY2I3VmFsO2Fzc2lnbigiY2J2YWx1ZTciLGNidmFsdWU3LGVudmlyPS5HbG9iYWxFbnYpDQogICAgICAgIGNidmFsdWU4PC1jYjhWYWw7YXNzaWduKCJjYnZhbHVlOCIsY2J2YWx1ZTgsZW52aXI9Lkdsb2JhbEVudikNCiAgICAgICAgY2J2YWx1ZTk8LWNiOVZhbDthc3NpZ24oImNidmFsdWU5IixjYnZhbHVlOSxlbnZpcj0uR2xvYmFsRW52KQ0KICAgICAgICBjYnZhbHVlMTA8LWNiMTBWYWw7YXNzaWduKCJjYnZhbHVlMTAiLGNidmFsdWUxMCxlbnZpcj0uR2xvYmFsRW52KQ0KICAgICAgICBjYnZhbHVlMTE8LWNiMTFWYWw7YXNzaWduKCJjYnZhbHVlMTEiLGNidmFsdWUxMSxlbnZpcj0uR2xvYmFsRW52KQ0KICAgICAgICBjYnZhbHVlMTI8LWNiMTJWYWw7YXNzaWduKCJjYnZhbHVlMTIiLGNidmFsdWUxMixlbnZpcj0uR2xvYmFsRW52KQ0KICAgICAgICBjYnZhbHVlMTM8LWNiMTNWYWw7YXNzaWduKCJjYnZhbHVlMTMiLGNidmFsdWUxMyxlbnZpcj0uR2xvYmFsRW52KQ0KICAgICAgICBjYnZhbHVlMTQ8LWNiMTRWYWw7YXNzaWduKCJjYnZhbHVlMTQiLGNidmFsdWUxNCxlbnZpcj0uR2xvYmFsRW52KQ0KICAgICAgICBjYnZhbHVlMTU8LWNiMTVWYWw7YXNzaWduKCJjYnZhbHVlMTUiLGNidmFsdWUxNSxlbnZpcj0uR2xvYmFsRW52KQ0KICAgICAgICBjYnZhbHVlMjE8LWNiMjFWYWw7YXNzaWduKCJjYnZhbHVlMjEiLGNidmFsdWUyMSxlbnZpcj0uR2xvYmFsRW52KQ0KICAgICAgICBuc3RhdGlvbjwtdGt0b3BsZXZlbCgpDQogICAgICAgIHRrd20udGl0bGUobnN0YXRpb24sIkNhbGN1bGF0aW9uIERvbmUiKQ0KICAgICAgICB0a2ZvY3VzKG5zdGF0aW9uKQ0KICAgICAgICBva2s8LWZ1bmN0aW9uKCl7dGtkZXN0cm95KG5zdGF0aW9uKTt0a2ZvY3VzKHN0YXJ0MSl9DQogICAgICAgIHRleHRsYWJlbDA8LXRrbGFiZWwobnN0YXRpb24sdGV4dD0iICAgICAiKQ0KICAgICAgICB0ZXh0bGFiZWwxPC10a2xhYmVsKG5zdGF0aW9uLHRleHQ9IkluZGljZXMgY2FsY3VsYXRpb24gY29tcGxldGVkIixmb250PWZvbnRIZWFkaW5nMSkNCiAgICAgICAgdGV4dGxhYmVsMjwtdGtsYWJlbChuc3RhdGlvbix0ZXh0PXBhc3RlKCJQbG90cyBhcmUgaW46ICIsb3V0anBnZGlyLHNlcD0iICIpLGZvbnQ9Zm9udEhlYWRpbmcxKQ0KICAgICAgICBva2suYnV0PC10a2J1dHRvbihuc3RhdGlvbix0ZXh0PSIgICBPSyAgICIsY29tbWFuZD1va2ssd2lkdGg9MjApDQogICAgICAgIHRrZ3JpZCh0ZXh0bGFiZWwwKQ0KICAgICAgICB0a2dyaWQodGV4dGxhYmVsMSkNCiAgICAgICAgdGtncmlkKHRleHRsYWJlbDIpDQogICAgICAgIHRrZ3JpZC5jb25maWd1cmUodGV4dGxhYmVsMSxzdGlja3k9InciKQ0KICAgICAgICB0a2dyaWQuY29uZmlndXJlKHRleHRsYWJlbDIsc3RpY2t5PSJ3IikNCiAgICAgICAgdGtncmlkLmNvbmZpZ3VyZSh0ZXh0bGFiZWwwLHN0aWNreT0iZSIpDQogICAgICAgICMgICAgY2FuY2VsbC5idXQ8LXRrYnV0dG9uKG5zdGF0aW9uLHRleHQ9IiAgIE5PICAgIixjb21tYW5kPWNhbmNlbGwsd2lkdGg9MTUpDQogICAgICAgICMgICAgdGtncmlkKHRleHRsYWJlbDIsb2trLmJ1dCxjYW5jZWxsLmJ1dCx0ZXh0bGFiZWwwKQ0KICAgICAgICB0a2dyaWQob2trLmJ1dCx0ZXh0bGFiZWwwKQ0KICAgICAgICAjICAgIHRrZ3JpZC5jb25maWd1cmUoY2FuY2VsbC5idXQsc3RpY2t5PSJ3IikNCiAgICAgICAgdGtncmlkKHRleHRsYWJlbDApDQogICAgfQ0KICAgICMtLS0tLS0tLS0tLSBPbk9LIGVuZHMgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0gIA0KICAgIA0KICAgICMtLS0tLS0tLS0tLSBkb25lMiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSAgDQogICAgZG9uZTI8LWZ1bmN0aW9uKCl7DQogICAgICAgIHRrZGVzdHJveShtYWluKQ0KICAgICAgICB0a2ZvY3VzKHN0YXJ0MSkNCiAgICAgICAgIyAgcmV0dXJuKCkNCiAgICB9DQogICAgIy0tLS0tLS0tLS0tIGRvbmUyIGVuZHMgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0gIA0KICAgIA0KICAgIG9rLmJ1dCA8LXRrYnV0dG9uKG1haW4sdGV4dD0iICAgT0sgICAiLGNvbW1hbmQ9T25PSyx3aWR0aD0zMCkNCiAgICBjYW5jZWwuYnV0PC10a2J1dHRvbihtYWluLHRleHQ9IkNBTkNFTCIsY29tbWFuZD1kb25lMix3aWR0aD0zMCkNCiAgICB0a2dyaWQob2suYnV0KQ0KICAgIHRrZ3JpZChjYW5jZWwuYnV0KQ0KICAgIHRrZ3JpZCh0a2xhYmVsKG1haW4sdGV4dD0iSXQgbWF5IHRha2UgbW9yZSB0aGFuIDUgbWludXRlcyB0byBjb21wdXRlIGFsbCB0aGUgaW5kaWNlcyIsZm9udD1mb250SGVhZGluZzIpKQ0KICAgIHRrZ3JpZCh0a2xhYmVsKG1haW4sdGV4dD0iUGxlYXNlIGJlIHBhdGllbnQsIHlvdSB3aWxsIGJlIGluZm9ybWVkIG9uY2UgY29tcHV0YXRpb25zIGFyZSBkb25lIixmb250PWZvbnRIZWFkaW5nMikpDQogICAgdGtncmlkKHRrbGFiZWwobWFpbix0ZXh0PSIiLGZvbnQ9Zm9udEhlYWRpbmcpKSNlbXB0eSBsaW5lDQogICAgDQp9DQojLS0tLS0tLS0tLS0gbWFpbjEgZW5kcyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSANCiMgRW5kIG9mIFBhcnQgSUkgKCBGdW5jdGlvbnMgb2YgQ2FsY3VsYXRpbmcgY2xpbWF0ZSBpbmRlY2llcyApDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBQYXJ0IElJSQ0KIyBNYWluIHByb2dyYW0NCiMgY2FsbCBnZXRmaWxlLCByZWFkIGRhdGEgZmlsZSBhbmQgc3RvcmUgaW4gZGQuDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQpzdGFydDE8LXRrdG9wbGV2ZWwoKQ0KIy0tLS0tLS0tLS0tIHBsb3R4IC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tICANCnBsb3R4PC0NCiAgICBmdW5jdGlvbiAoeCx5LG1haW49IiIseGxhYj0iIix5bGFiPSIiKQ0KICAgIHsNCiAgICAgICAgcGxvdCh4LHkseGxhYj14bGFiLHlsYWI9eWxhYix0eXBlPSJiIikNCiAgICAgICAgZml0PC1sc2ZpdCh4LHkpDQogICAgICAgIG91dDwtbHMucHJpbnQoZml0LHByaW50Lml0PUYpDQogICAgICAgIHIyPC1yb3VuZCgxMDAqYXMubnVtZXJpYyhvdXQkc3VtbWFyeVsxLDJdKSwxKQ0KICAgICAgICBwdmFsPC1yb3VuZChhcy5udW1lcmljKG91dCRzdW1tYXJ5WzEsNl0pLDMpDQogICAgICAgIGJldGE8LXJvdW5kKGFzLm51bWVyaWMob3V0JGNvZWYudGFibGVbWzFdXVsyLDFdKSwzKQ0KICAgICAgICBiZXRhZXJyPC1yb3VuZChhcy5udW1lcmljKG91dCRjb2VmLnRhYmxlW1sxXV1bMiwyXSksMykNCiAgICAgICAgYWJsaW5lKGZpdCxsd2Q9MykNCiAgICAgICAgeHk8LWNiaW5kKHgseSkNCiAgICAgICAgeHk8LW5hLm9taXQoeHkpDQogICAgICAgIGxpbmVzKGxvd2Vzcyh4eVssMV0seHlbLDJdKSxsd2Q9MyxsdHk9MikNCiAgICAgICAgc3VidGl0PXBhc3RlKCJSMj0iLHIyLCIgcC12YWx1ZT0iLHB2YWwsIiBTbG9wZSBlc3RpbWF0ZT0iLGJldGEsIiBTbG9wZSBlcnJvcj0iLGJldGFlcnIpDQogICAgICAgIHRpdGxlKG1haW49bWFpbikNCiAgICAgICAgdGl0bGUoc3ViPXN1YnRpdCxjZXg9MC41KQ0KICAgIH0NCiMtLS0tLS0tLS0tLSBwbG90eCBlbmRzIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tICANCg0KIy0tLS0tLS0tLS0tIHRzIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tICANCnRzPC1mdW5jdGlvbih5cz14WzEsMV0seWU9eFtucm93KHgpLDFdLHg9ZGQpIA0Kew0KICAgICMNCiAgICAjIEVEQSBmdW5jdGlvbg0KICAgICMNCiAgICBwYXIobWZyb3c9YygzLDEpKQ0KICAgIHhzPC14Wyh4WywxXT49eXMpJih4WywxXTw9eWUpLF0NCiAgICB0cy5wbG90KHhzWyw0XSkNCiAgICB0aXRsZSgiRGFpbHkgcHJlY2lwaXRhdGlvbiIseGxhYj0iZGF5Iix5bGFiPSJwcmVjaXAiKQ0KICAgIHRzLnBsb3QoeHNbLDVdKQ0KICAgIHRpdGxlKCJEYWlseSBtYXhpbXVtIHRlbXBlcmF0dXJlIix4bGFiPSJkYXkiLHlsYWI9InRtYXgiKQ0KICAgIHRzLnBsb3QoeHNbLDZdKQ0KICAgIHRpdGxlKCJEYWlseSBtaW5pbXVtIHRlbXBlcmF0dXJlIix4bGFiPSJkYXkiLHlsYWI9InRtaW4iKQ0KICAgIHBhcihtZnJvdz1jKDEsMSkpDQogICAgDQogICAgY2F0KHBhc3RlKCJTdGF0aW9uIHNlcmllcyBkZWZpbmVkIGZyb20gIix4WzEsMV0sIiB0byAiLHhbbnJvdyh4KSwxXSwiXG4iKSkNCiAgICBjYXQocGFzdGUoIlN1bW1hcnkgc3RhdGlzdGljcyBmb3Igd2luZG93IGZyb20gIix5cywiIHRvICIsIHllLCJcbiIpKQ0KfQ0KIy0tLS0tLS0tLS0tIHRzIGVuZHMgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0gIA0KDQojLS0tLS0tLS0tLS0gPz8/Pz8/Pz8/PyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSAgDQpmdW5jdGlvbiAoeTE9eFsxLDFdLHkyPWRkW25yb3coeCksMV0sbT0xLHY9NCx4PWRkKSANCnsNCiAgICAjDQogICAgIyBMaXR0bGUgZnVuY3Rpb24gdG8gc2VlIGhvdyBtYW55IE5BcyB0aGVyZSBhcmUgaW4gbW9udGggbQ0KICAgICMgaW4gcGVyaW9kIHkxIHRvIHkyIGZvciB2YXJpYWJsZSB2Og0KICAgICMgDQogICAgIyBVc2FnZTogbmFzKDE5NjAsMTk5MCwxLDQpDQogICAgIw0KICAgIA0KICAgIHhzPC14Wyh4WywxXT49eTEpJih4WywxXTw9eTIpJih4WywyXT09bSksXQ0KICAgIGNhdChwYXN0ZSgiWWVhcnMgZnJvbSAiLHkxLCItIix5MiwiIE1vbnRoPSIsbSwiIFZhcmlhYmxlPSIsdiwiXG4iKSkNCiAgICBjYXQocGFzdGUoIlRvdGFsIG51bWJlciBvZiBkYXlzPSIsbGVuZ3RoKHhzWyx2XSksIiBUb3RhbCBtaXNzaW5nPSIsc3VtKGlzLm5hKHhzWyx2XSkpLCJcbiIpKQ0KfQ0KIy0tLS0tLS0tLS0tID8/Pz8/PyBlbmRzIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tICANCnN0YXJ0c3M8LWZ1bmN0aW9uKCl7DQogICAgdGt3bS50aXRsZShzdGFydDEsIlJjbGltRGV4IikNCiAgICB0a2dyaWQodGtsYWJlbChzdGFydDEsdGV4dD0iICAgICBSQ2xpbURleCBieSBKdW5pb3IgdmVyc2lvbiBCRVRBICAiLGZvbnQ9Zm9udEhlYWRpbmcpKQ0KICAgIHRrZ3JpZCh0a2xhYmVsKHN0YXJ0MSx0ZXh0PSIiLGZvbnQ9Zm9udEhlYWRpbmcpKSNlbXB0eSBsaW5lDQogICAgdGtncmlkKHRrbGFiZWwoc3RhcnQxLHRleHQ9IiIsZm9udD1mb250SGVhZGluZykpI2VtcHR5IGxpbmUNCiAgICAjdGtncmlkKHRrbGFiZWwoc3RhcnQxLHRleHQ9IiIsZm9udD1mb250SGVhZGluZykpI2VtcHR5IGxpbmUNCiAgICBzdGFydC5idXQ8LXRrYnV0dG9uKHN0YXJ0MSx0ZXh0PSJMb2FkIERhdGEgYW5kIFJ1biBRQyIsY29tbWFuZD1nZXRmaWxlLHdpZHRoPTMwKQ0KICAgIGNhbC5idXQ8LXRrYnV0dG9uKHN0YXJ0MSx0ZXh0PSIgSW5kaWNlcyBDYWxjdWxhdGlvbiAiLGNvbW1hbmQ9bmFzdGF0LHdpZHRoPTYwKQ0KICAgIGNhbmNlbC5idXQ8LXRrYnV0dG9uKHN0YXJ0MSx0ZXh0PSJFeGl0Iixjb21tYW5kPWRvbmUsd2lkdGg9MzApDQogICAgdGtncmlkKHN0YXJ0LmJ1dCkNCiAgICB0a2dyaWQoY2FsLmJ1dCkNCiAgICB0a2dyaWQoY2FuY2VsLmJ1dCkNCiAgICB0a2dyaWQodGtsYWJlbChzdGFydDEsdGV4dD0iIixmb250PWZvbnRIZWFkaW5nKSkgICANCn0jZW5kIG9mIHN0YXJ0c3MgZnVuY3Rpb24NCnN0YXJ0c3MoKQ0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KDQoNCmBgYA0KDQoNCg0KLg0KPC9kaXY+