Introducción
Actualmente, es difícil imaginar a un investigador, científico o
analista de datos realizando un análisis estadístico sin la ayuda de un
software especializado. Como menciona Fernández (2020), en general, un
software de análisis estadístico alude a los programas informáticos con
módulos orientados a la tabulación, gestión, modificación, análisis y
representación gráfica de datos. En efecto, estos programas tienen
ventajas respecto al cálculo manual, ya que reducen el tiempo dedicado
al análisis, aumentan su precisión, editan información, representaciones
gráficas y salidas para elaborar informes, entre otras funciones.
No hay más reiterar que para lograr un uso adecuado —y por ende
efectivo— de este tipo de software, se requiere del despliegue de
conocimientos estadísticos que permitan hacer los análisis e
interpretaciones que potencialmente deban realizarse. Por otro lado, a
menudo se hace la distinción entre los software de pago y los software
gratuitos.
De entre los variados softwares gratuitos actualmente disponibles
destaca uno que, por su cada vez mayor aceptación y promoción en los
ámbitos académico e investigativo, se ha convertido en un potente
referente en lo que respecta a la computación estadística de alto nivel
como apoyo a las más diversas disciplinas científicas; nos referimos a
R. Como tal R es un lenguaje de programación empleado primordialmente
para efectuar análisis estadístico de datos y construcción de gráficos.
Tiene características que lo sitúan muy por encima de prácticamente
todos sus “competidores”: es gratuito y libre, es muy versátil, permite
realizar una cantidad insospechable de procedimientos estadísticos y
gráficos, permite construir gráficos de calidad inmejorable, etc.
Es justo dentro del mundo del lenguaje de programación R que
encontramos a Shiny, que es un paquete (un conjunto de funciones) para
R. El propósito de Shiny es facilitar el desarrollo de aplicaciones web
que permiten a los usuarios interactuar con el código de R en un
navegador y mediante elementos de la interfaz de usuario (UI) como
controles deslizantes, menús desplegables, etc. En el presente trabajo
de investigación ahondaremos en aspectos básicos sobre Shiny, que
ofrecen una visión general de las capacidades de esta herramienta, un
poco de su historia, funciones y componentes, y ejemplos de uso. También
prepararemos un archivo adicional de una aplicación Shiny, que muestre
el contenido del dataset Iris.
Desarrollo
Como menciona Wickham (2021), Shiny es un paquete de R que permite
crear fácilmente aplicaciones web ricas e interactivas. Permite tomar el
trabajo en R y exponerlo a través de un navegador web para que
cualquiera pueda utilizarlo.
En el pasado, crear aplicaciones web era difícil para la mayoría de
los usuarios de R porque se necesitaba un conocimiento profundo de
tecnologías web como HTML, CSS y JavaScript y crear aplicaciones
interactivas complejas requería un análisis cuidadoso de los flujos de
interacción para asegurarse de que cuando se cambiaba una entrada, solo
las salidas relacionadas se actualizaban.
Shiny facilita significativamente a los programadores de R la
creación de aplicaciones web al proporcionar un conjunto cuidadosamente
seleccionado de funciones de interfaz de usuario (abreviado como UI) que
generan el HTML, CSS y JavaScript necesarios para tareas comunes e
introducir un nuevo estilo de programación llamado programación
reactiva, que rastrea automáticamente las dependencias de las partes del
código. Esto significa que cada vez que cambia una entrada, Shiny puede
determinar automáticamente cómo hacer la menor cantidad de trabajo para
actualizar todas las salidas relacionadas.
Historia de Shiny
Shiny fue creado por Joe Cheng, un ingeniero de software en RStudio,
en 2012. La motivación principal detrás de su desarrollo fue la
necesidad de una herramienta que permitiera a los usuarios de R,
principalmente estadísticos y científicos de datos, crear aplicaciones
web sin tener que aprender tecnologías de desarrollo web como HTML, CSS
o JavaScript.
Lanzamiento Inicial:
Shiny fue lanzado por primera vez en 2012. El paquete permitió a los
usuarios crear aplicaciones interactivas con solo unos pocos comandos en
R. Esto democratizó el acceso al desarrollo de aplicaciones web dentro
de la comunidad de usuarios de R, ya que hizo que la creación de
interfaces gráficas interactivas fuera mucho más accesible.
Crecimiento y Popularidad:
Tras su lanzamiento, Shiny ganó rápidamente popularidad debido a su
facilidad de uso y la potencia de las aplicaciones que se podían
construir con él. RStudio continuó mejorando Shiny, agregando
características y optimizaciones para manejar aplicaciones más grandes y
complejas. La comunidad alrededor de Shiny también creció, con numerosos
paquetes y extensiones desarrollados para complementar y expandir sus
capacidades.
Evolución y Actualizaciones:
A lo largo de los años, Shiny ha recibido numerosas actualizaciones
que han mejorado su funcionalidad y rendimiento. Algunas de las
adiciones más importantes incluyen la integración con bibliotecas de
visualización como ggplot2, el soporte para aplicaciones escalables, y
mejoras en la gestión de sesiones y en la implementación de aplicaciones
Shiny en servidores.
Uso en la Actualidad:
Hoy en día, Shiny es ampliamente utilizado en la academia, la
industria y el gobierno para crear dashboards, visualizaciones
interactivas, y aplicaciones de análisis de datos. Su capacidad para
integrar análisis complejos en tiempo real y su flexibilidad lo han
convertido en una herramienta esencial para muchos analistas de
datos.
Funciones principales de Shiny
Shiny permite realizar las siguientes
actividades:
Crear dashboards que rastrean indicadores clave de rendimiento a
alto nivel, mientras facilitan el análisis detallado de métricas que
necesitan más investigación.
Reemplazar cientos de páginas de PDFs con aplicaciones
interactivas que permiten al usuario ir directamente a la sección exacta
de los resultados que les interesan.
Comunicar modelos complejos a una audiencia no técnica con
visualizaciones informativas y análisis de sensibilidad
interactivos.
Proporcionar análisis de datos de autoservicio para flujos de
trabajo comunes, reemplazando solicitudes por correo electrónico con una
aplicación Shiny que permite a las personas cargar sus propios datos y
realizar análisis estándar.
Crear demostraciones interactivas para enseñar conceptos de
estadística y ciencia de datos que permiten a los estudiantes modificar
entradas y observar los efectos en el análisis.
En resumen, Shiny da la capacidad de transmitir algunos de
“superpoderes en R” a cualquier persona que pueda usar la web.
Por otro lado, Shiny proporciona varias funciones
principales que permiten a los usuarios crear aplicaciones web
interactivas utilizando R:
Esta es la función principal que se utiliza para lanzar una
aplicación Shiny. Toma dos argumentos, ui (la interfaz de usuario) y
server (la lógica del servidor), y los combina en una aplicación
completa.
Se utiliza para definir la estructura de la interfaz de usuario.
Dentro de fluidPage(), se pueden incluir varios elementos de diseño,
como filas (fluidRow()), columnas (column()), y otros componentes de la
interfaz.
Se utiliza para definir el título principal de la aplicación.
Permite dividir la interfaz en una barra lateral (sidebarPanel()) y
un panel principal (mainPanel()).
Define el contenido de la barra lateral de la interfaz. Normalmente
incluye controles de entrada como sliderInput(), selectInput(), etc.
Contiene el contenido principal de la interfaz, como gráficos, tablas
y otros elementos de salida.
En el lado del servidor, los objetos input$ y output$ se utilizan
para acceder a los valores de entrada y para definir salidas reactivas,
respectivamente.
- renderPlot(), renderTable(), renderText()
Estas funciones se utilizan en la parte del servidor para generar
salidas reactivas que pueden ser gráficos, tablas, texto, entre otros.
Estas salidas se enlazan con elementos en output$.
- observe() y observeEvent()
Estas funciones se utilizan para ejecutar código en respuesta a
cambios en entradas reactivas, sin generar un valor de salida. Son
útiles para modificar la aplicación de manera reactiva sin producir una
salida directa.
Se utiliza para crear expresiones reactivas que pueden ser
compartidas entre varias salidas. Una expresión reactiva recalcula su
valor automáticamente cuando sus entradas cambian.
Permiten generar dinámicamente partes de la interfaz de usuario con
base en el código del servidor.
Se utiliza para evitar que una expresión reactiva se vuelva a
ejecutar automáticamente cuando cambian sus entradas. Es útil para
optimizar la ejecución de código.
Componentes de una aplicación Shiny
Describiremos en esta sección los componentes de Shiny. La
información recabada sobre los componentes se obtuvo de la publicación
de Cuevas (2021).
Primero, para instalar Shiny, podemos utilizar los
siguientes códigos:
install.packages("shiny")
if (!require("devtools"))
install.packages("devtools")
devtools::install_github("shiny", "rstudio")
Tomemos en cuenta que toda aplicación web de Shiny tendrá la misma
estructura, dos bloques de códigos de R:

La estructura de código de una app Shiny se vería del siguiente
modo:
library(shiny)
ui <- fluidPage(
xxxxInput(),
xxxxOutput()
)
server <- function(input, output)
{
Codigo de R
}
shinyApp(ui = ui, server = server)
1. La Interfaz de Usuario (UI)
La interfaz de usuario define la estructura y el diseño de la
aplicación Shiny.
Shiny por default usa bootstrap (lo cual no tiene nada que ver con el
método estadístico bootstrap). Esto es un marco de trabajo de HTML, CSS
y Javascript más popular para desarrollar sitios web receptivos.
Para usar todos los tags en Shiny, podemos consultar estos tags con
la siguiente función:
shiny::tags
names(shiny::tags)
Shiny fomenta la separación del código que genera su interfaz de
usuario (el front-end) del código que impulsa el comportamiento de su
aplicación (el back-end):

Existe una comunidad rica y vibrante de paquetes de extensión, como
shinyWidgets, colorpicker y sorttable.
2. El servidor (server)
El servidor define la lógica de la aplicación, incluyendo cómo se
procesan las entradas y cómo se generan las salidas.
Hay 3 reglas para escribir código en el Server:
Especifica con output$ + ID output cada
objeto dentro de server.
Cada objeto se mostrará con un render(), ejemplo
renderPlot({})
Accesa a los valores de los inputs con input$ +
ID input

3. Reactividad
Shiny está basado en un modelo reactivo que actualiza automáticamente
las salidas cuando cambian las entradas. Los componentes clave para
manejar la reactividad incluyen:
Expresiones reactivas: Se crean usando
reactive() y se pueden compartir entre múltiples
salidas.
Observadores: Usan observe() para
monitorear cambios en las entradas y ejecutar código en
consecuencia.
Aislamiento de reactivos: La función
isolate() evita que una expresión reactiva se recalcula
cuando cambian sus dependencias.
4. Componentes de Extensión
shinyModules: Permiten la
modularización del código Shiny, dividiendo la aplicación en componentes
reutilizables.
shinyWidgets: Un paquete adicional
que proporciona widgets adicionales para mejorar la interactividad y la
estética de las aplicaciones.
shinyjs: Permite integrar
funcionalidades de JavaScript en una aplicación Shiny, ofreciendo un
control más detallado de la interacción del usuario.
Los anteriores son los componentes principales de Shiny que permiten
construir aplicaciones web interactivas. Cada uno juega un papel crucial
en la estructura y funcionalidad de una aplicación Shiny, haciendo
posible la creación de interfaces dinámicas y reactivas con un esfuerzo
relativamente bajo.
Ejemplos de uso
Shiny es una biblioteca en R que facilita la creación de aplicaciones
web interactivas. Entre lo que permite hacer tenemos:
Crear Interfaces Interactivas: construir
aplicaciones web con interfaces gráficas interactivas para visualizar
datos, realizar análisis y crear dashboards.
Visualizar Datos: crear gráficos dinámicos y
tablas que se actualizan en tiempo real en función de las entradas del
usuario.
Desarrollar Aplicaciones de Datos: construir
aplicaciones para realizar análisis estadísticos, modelado predictivo o
cualquier tipo de procesamiento de datos en línea.
Construir Dashboards: construir paneles de
control completos para supervisar métricas y datos en tiempo
real.
Crear Formularios y Aplicaciones de Entrada de
Datos: diseñar formularios para la entrada de datos y procesar
los resultados directamente en la aplicación.
Integrar con Otras Herramientas: Shiny puede
integrarse con otras herramientas y paquetes de R, como ggplot2 para
gráficos y dplyr para manipulación de datos.
Implementar Modelos de Machine Learning:
construir aplicaciones que muestren predicciones y resultados de modelos
de aprendizaje automático en una interfaz de usuario
interactiva.
Desplegar Aplicaciones: Puedes desplegar tus
aplicaciones Shiny en servidores locales o en la nube, como ShinyApps.io
o en servidores propios usando Shiny Server.
A continuación, se estudian dos ejemplos de uso concretos de Shiny
para la creación de aplicaciones:
Cálculo de la distancia punto a línea
En el 2018, un autor de blog utilizó la librería para poder
visualizar la distancia de un punto especifico de Mexico a la línea
fronteriza con Estados Unidos.
- Para poder filtrar la información necesaria en cuanto a la
localización de estados y demás, se descargó la información sobre la
línea de la frontera para poder utilizarla en R. Una vez cargada la
información, fue posible realizar su lectura utilizando la función
sf::st_read().
f <- st_read("Mexico_and_US_Border.shp")
- Seguidamente, se dibujaron los datos con el fin de confirmar que se
tenían los datos necesarios.
plot(f, max.plot = 1)
- Se definió el punto que se tomaría de referencia para sacar la
distancia con respecto a la frontera. Se eligió tomar como referencia el
Colegio de México. Para la utilización de las coordenadas de dicho
lugar, se usó Google Maps. Con esta referencia se creó la tabla
latitud/longitud.
pto <- data.frame(x = -99.20775, y = 19.303741) %>%
st_as_sf(coords = c("x", "y"))
# Homologando el Sistema de Coordenadas de Referencia con la base de la línea de la Frontera Norte
st_crs(pto) <- st_crs(f)
- Se calculó la distancia utilizando la función
st_distance() para calcular la distancia geodésica que hay
entre dos elementos geográficos del mapa.
- Con la información anterior se determinó el punto más cercano de la
frontera al Colegio de México, pero surgió la pregunta de en dónde está,
por lo que se descompuso la línea de la frontera norte en vértices y
componentes con el fin de determinar la línea con la menor longitud
- Después de una serie de pasos, se logró visualizar el punto con el
uso del código:
linea <- st_linestring(matrix(c(pto[,"geometry"] %>%
st_coordinates(),
punto_frontera[,"geometry"] %>% st_coordinates()), ncol = 2, byrow = TRUE))
- Se plasmó en un mapa de
leaflet
leaflet() %>%
addTiles() %>%
addCircleMarkers(data = pto) %>%
addCircleMarkers(data = punto_frontera) %>%
addPolylines(data = linea) %>%
addPolylines(data = f, color = "red")
Finalmente, se obtuvieron los siguientes resultados, que le
permitió determinar que el punto más cercano a la frontera norte se
encuentra unos kilómetros al Este de la Ciudad de Matamoros, en el
Estado de Tamaulipas.

Con la información anterior, el autor creó un Shiny app, con el fin
de que cualquier usuario pueda calcular la distancia de cualquier punto
a la frontera sur de Estados Unidos. En este caso, el
superpoder que se pasó fue el de poder calcular la
distancia y poder construir la línea de mínima distancia tan solo con
presionar un punto en el mapa.

Ecobici(Datatón)
Esta aplicación fué una entrada para el Datatón de Visualización de
datos de ecobici del CIMAT. Su realización fué un trabajo conjunto entre
analistas que usaron Python y R para el análisis de datos, comunicando
los resultados a la aplicación a través de una API.
Ecobici es un sistema de bicicletas compartidas lanzado en febrero de
2010 por el gobierno de la Ciudad de México para la realización de
viajes de corta distancia y duración a precios reducidos o de forma
gratuita. El sistema cuenta con 480 cicloestaciones y más de 6 mil 800
bicicletas, de las cuales 28 estaciones y 340 bicicletas forman parte
del nuevo sistema de bicicletas eléctricas de pedaleo asistido.

LS0tDQp0aXRsZTogIkxpYnJlcsOtYSBTaGlueSBkZSBSIg0Kb3V0cHV0Og0KICBodG1sX25vdGVib29rOiBkZWZhdWx0DQogIHBkZl9kb2N1bWVudDogZGVmYXVsdA0KICBodG1sX2RvY3VtZW50Og0KICAgIGRmX3ByaW50OiBwYWdlZA0KICB3b3JkX2RvY3VtZW50OiBkZWZhdWx0DQotLS0NCg0KLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tDQoNClRlY25vbMOzZ2ljbyBkZSBDb3N0YSBSaWNhDQoNCkN1cnNvOiBJbnRyb2R1Y2Npw7NuIGEgbGEgUHJvZ3JhbWFjacOzbiBjb24gUg0KDQpUcmFiYWpvIGRlIEludmVzdGlnYWNpw7NuIDENCg0KUHJvZmVzb3I6IEx1aXMgRmVybmFuZG8gQ2FzdHJvDQoNCkVzdHVkaWFudGVzOg0KDQotICAgTWFyaWNydXogVmFyZ2FzIFJhbcOtcmV6DQotICAgTGF1cmEgUm9kcsOtZ3VleiBWYXJnYXMNCi0gICBNYXLDrWEgR2FicmllbGEgU2V2ZXJpbm8gQ2FsZGVyw7NuDQotICAgU2ViYXN0acOhbiBDYWJlemFzIEppbcOpbmV6DQoNCi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQ0KDQojIyBJbnRyb2R1Y2Npw7NuDQoNCkFjdHVhbG1lbnRlLCBlcyBkaWbDrWNpbCBpbWFnaW5hciBhIHVuIGludmVzdGlnYWRvciwgY2llbnTDrWZpY28gbyBhbmFsaXN0YSBkZSBkYXRvcyByZWFsaXphbmRvIHVuIGFuw6FsaXNpcyBlc3RhZMOtc3RpY28gc2luIGxhIGF5dWRhIGRlIHVuIHNvZnR3YXJlIGVzcGVjaWFsaXphZG8uIENvbW8gbWVuY2lvbmEgRmVybsOhbmRleiAoMjAyMCksIGVuIGdlbmVyYWwsIHVuIHNvZnR3YXJlIGRlIGFuw6FsaXNpcyBlc3RhZMOtc3RpY28gYWx1ZGUgYSBsb3MgcHJvZ3JhbWFzIGluZm9ybcOhdGljb3MgY29uIG3Ds2R1bG9zIG9yaWVudGFkb3MgYSBsYSB0YWJ1bGFjacOzbiwgZ2VzdGnDs24sIG1vZGlmaWNhY2nDs24sIGFuw6FsaXNpcyB5IHJlcHJlc2VudGFjacOzbiBncsOhZmljYSBkZSBkYXRvcy4gRW4gZWZlY3RvLCBlc3RvcyBwcm9ncmFtYXMgdGllbmVuIHZlbnRhamFzIHJlc3BlY3RvIGFsIGPDoWxjdWxvIG1hbnVhbCwgeWEgcXVlIHJlZHVjZW4gZWwgdGllbXBvIGRlZGljYWRvIGFsIGFuw6FsaXNpcywgYXVtZW50YW4gc3UgcHJlY2lzacOzbiwgZWRpdGFuIGluZm9ybWFjacOzbiwgcmVwcmVzZW50YWNpb25lcyBncsOhZmljYXMgeSBzYWxpZGFzIHBhcmEgZWxhYm9yYXIgaW5mb3JtZXMsIGVudHJlIG90cmFzIGZ1bmNpb25lcy4NCg0KTm8gaGF5IG3DoXMgcmVpdGVyYXIgcXVlIHBhcmEgbG9ncmFyIHVuIHVzbyBhZGVjdWFkbyDigJR5IHBvciBlbmRlIGVmZWN0aXZv4oCUIGRlIGVzdGUgdGlwbyBkZSBzb2Z0d2FyZSwgc2UgcmVxdWllcmUgZGVsIGRlc3BsaWVndWUgZGUgY29ub2NpbWllbnRvcyBlc3RhZMOtc3RpY29zIHF1ZSBwZXJtaXRhbiBoYWNlciBsb3MgYW7DoWxpc2lzIGUgaW50ZXJwcmV0YWNpb25lcyBxdWUgcG90ZW5jaWFsbWVudGUgZGViYW4gcmVhbGl6YXJzZS4gUG9yIG90cm8gbGFkbywgYSBtZW51ZG8gc2UgaGFjZSBsYSBkaXN0aW5jacOzbiBlbnRyZSBsb3Mgc29mdHdhcmUgZGUgcGFnbyB5IGxvcyBzb2Z0d2FyZSBncmF0dWl0b3MuDQoNCkRlIGVudHJlIGxvcyB2YXJpYWRvcyBzb2Z0d2FyZXMgZ3JhdHVpdG9zIGFjdHVhbG1lbnRlIGRpc3BvbmlibGVzIGRlc3RhY2EgdW5vIHF1ZSwgcG9yIHN1IGNhZGEgdmV6IG1heW9yIGFjZXB0YWNpw7NuIHkgcHJvbW9jacOzbiBlbiBsb3Mgw6FtYml0b3MgYWNhZMOpbWljbyBlIGludmVzdGlnYXRpdm8sIHNlIGhhIGNvbnZlcnRpZG8gZW4gdW4gcG90ZW50ZSByZWZlcmVudGUgZW4gbG8gcXVlIHJlc3BlY3RhIGEgbGEgY29tcHV0YWNpw7NuIGVzdGFkw61zdGljYSBkZSBhbHRvIG5pdmVsIGNvbW8gYXBveW8gYSBsYXMgbcOhcyBkaXZlcnNhcyBkaXNjaXBsaW5hcyBjaWVudMOtZmljYXM7IG5vcyByZWZlcmltb3MgYSBSLiBDb21vIHRhbCBSIGVzIHVuIGxlbmd1YWplIGRlIHByb2dyYW1hY2nDs24gZW1wbGVhZG8gcHJpbW9yZGlhbG1lbnRlIHBhcmEgZWZlY3R1YXIgYW7DoWxpc2lzIGVzdGFkw61zdGljbyBkZSBkYXRvcyB5IGNvbnN0cnVjY2nDs24gZGUgZ3LDoWZpY29zLiBUaWVuZSBjYXJhY3RlcsOtc3RpY2FzIHF1ZSBsbyBzaXTDumFuIG11eSBwb3IgZW5jaW1hIGRlIHByw6FjdGljYW1lbnRlIHRvZG9zIHN1cyDigJxjb21wZXRpZG9yZXPigJ06IGVzIGdyYXR1aXRvIHkgbGlicmUsIGVzIG11eSB2ZXJzw6F0aWwsIHBlcm1pdGUgcmVhbGl6YXIgdW5hIGNhbnRpZGFkIGluc29zcGVjaGFibGUgZGUgcHJvY2VkaW1pZW50b3MgZXN0YWTDrXN0aWNvcyB5IGdyw6FmaWNvcywgcGVybWl0ZSBjb25zdHJ1aXIgZ3LDoWZpY29zIGRlIGNhbGlkYWQgaW5tZWpvcmFibGUsIGV0Yy4NCg0KRXMganVzdG8gZGVudHJvIGRlbCBtdW5kbyBkZWwgbGVuZ3VhamUgZGUgcHJvZ3JhbWFjacOzbiBSIHF1ZSBlbmNvbnRyYW1vcyBhIFNoaW55LCBxdWUgZXMgdW4gcGFxdWV0ZSAodW4gY29uanVudG8gZGUgZnVuY2lvbmVzKSBwYXJhIFIuIEVsIHByb3DDs3NpdG8gZGUgU2hpbnkgZXMgZmFjaWxpdGFyIGVsIGRlc2Fycm9sbG8gZGUgYXBsaWNhY2lvbmVzIHdlYiBxdWUgcGVybWl0ZW4gYSBsb3MgdXN1YXJpb3MgaW50ZXJhY3R1YXIgY29uIGVsIGPDs2RpZ28gZGUgUiBlbiB1biBuYXZlZ2Fkb3IgeSBtZWRpYW50ZSBlbGVtZW50b3MgZGUgbGEgaW50ZXJmYXogZGUgdXN1YXJpbyAoVUkpIGNvbW8gY29udHJvbGVzIGRlc2xpemFudGVzLCBtZW7DunMgZGVzcGxlZ2FibGVzLCBldGMuIEVuIGVsIHByZXNlbnRlIHRyYWJham8gZGUgaW52ZXN0aWdhY2nDs24gYWhvbmRhcmVtb3MgZW4gYXNwZWN0b3MgYsOhc2ljb3Mgc29icmUgU2hpbnksIHF1ZSBvZnJlY2VuIHVuYSB2aXNpw7NuIGdlbmVyYWwgZGUgbGFzIGNhcGFjaWRhZGVzIGRlIGVzdGEgaGVycmFtaWVudGEsIHVuIHBvY28gZGUgc3UgaGlzdG9yaWEsIGZ1bmNpb25lcyB5IGNvbXBvbmVudGVzLCB5IGVqZW1wbG9zIGRlIHVzby4gVGFtYmnDqW4gcHJlcGFyYXJlbW9zIHVuIGFyY2hpdm8gYWRpY2lvbmFsIGRlIHVuYSBhcGxpY2FjacOzbiBTaGlueSwgcXVlIG11ZXN0cmUgZWwgY29udGVuaWRvIGRlbCBkYXRhc2V0IElyaXMuDQoNCiMjIERlc2Fycm9sbG8NCg0KIyMjIMK/UXXDqSBlcyBbU2hpbnldKGh0dHBzOi8vc2hpbnkucG9zaXQuY28vci9nZXRzdGFydGVkL3NoaW55LWJhc2ljcy9sZXNzb24xL2luZGV4Lmh0bWwpID8NCg0KQ29tbyBtZW5jaW9uYSBXaWNraGFtICgyMDIxKSwgU2hpbnkgZXMgdW4gcGFxdWV0ZSBkZSBSIHF1ZSBwZXJtaXRlIGNyZWFyIGbDoWNpbG1lbnRlIGFwbGljYWNpb25lcyB3ZWIgcmljYXMgZSBpbnRlcmFjdGl2YXMuIFBlcm1pdGUgdG9tYXIgZWwgdHJhYmFqbyBlbiBSIHkgZXhwb25lcmxvIGEgdHJhdsOpcyBkZSB1biBuYXZlZ2Fkb3Igd2ViIHBhcmEgcXVlIGN1YWxxdWllcmEgcHVlZGEgdXRpbGl6YXJsby4NCg0KRW4gZWwgcGFzYWRvLCBjcmVhciBhcGxpY2FjaW9uZXMgd2ViIGVyYSBkaWbDrWNpbCBwYXJhIGxhIG1heW9yw61hIGRlIGxvcyB1c3VhcmlvcyBkZSBSIHBvcnF1ZSBzZSBuZWNlc2l0YWJhIHVuIGNvbm9jaW1pZW50byBwcm9mdW5kbyBkZSB0ZWNub2xvZ8OtYXMgd2ViIGNvbW8gSFRNTCwgQ1NTIHkgSmF2YVNjcmlwdCB5IGNyZWFyIGFwbGljYWNpb25lcyBpbnRlcmFjdGl2YXMgY29tcGxlamFzIHJlcXVlcsOtYSB1biBhbsOhbGlzaXMgY3VpZGFkb3NvIGRlIGxvcyBmbHVqb3MgZGUgaW50ZXJhY2Npw7NuIHBhcmEgYXNlZ3VyYXJzZSBkZSBxdWUgY3VhbmRvIHNlIGNhbWJpYWJhIHVuYSBlbnRyYWRhLCBzb2xvIGxhcyBzYWxpZGFzIHJlbGFjaW9uYWRhcyBzZSBhY3R1YWxpemFiYW4uDQoNClNoaW55IGZhY2lsaXRhIHNpZ25pZmljYXRpdmFtZW50ZSBhIGxvcyBwcm9ncmFtYWRvcmVzIGRlIFIgbGEgY3JlYWNpw7NuIGRlIGFwbGljYWNpb25lcyB3ZWIgYWwgcHJvcG9yY2lvbmFyIHVuIGNvbmp1bnRvIGN1aWRhZG9zYW1lbnRlIHNlbGVjY2lvbmFkbyBkZSBmdW5jaW9uZXMgZGUgaW50ZXJmYXogZGUgdXN1YXJpbyAoYWJyZXZpYWRvIGNvbW8gVUkpIHF1ZSBnZW5lcmFuIGVsIEhUTUwsIENTUyB5IEphdmFTY3JpcHQgbmVjZXNhcmlvcyBwYXJhIHRhcmVhcyBjb211bmVzIGUgaW50cm9kdWNpciB1biBudWV2byBlc3RpbG8gZGUgcHJvZ3JhbWFjacOzbiBsbGFtYWRvIHByb2dyYW1hY2nDs24gcmVhY3RpdmEsIHF1ZSByYXN0cmVhIGF1dG9tw6F0aWNhbWVudGUgbGFzIGRlcGVuZGVuY2lhcyBkZSBsYXMgcGFydGVzIGRlbCBjw7NkaWdvLiBFc3RvIHNpZ25pZmljYSBxdWUgY2FkYSB2ZXogcXVlIGNhbWJpYSB1bmEgZW50cmFkYSwgU2hpbnkgcHVlZGUgZGV0ZXJtaW5hciBhdXRvbcOhdGljYW1lbnRlIGPDs21vIGhhY2VyIGxhIG1lbm9yIGNhbnRpZGFkIGRlIHRyYWJham8gcGFyYSBhY3R1YWxpemFyIHRvZGFzIGxhcyBzYWxpZGFzIHJlbGFjaW9uYWRhcy4NCg0KIyMjIEhpc3RvcmlhIGRlIFNoaW55DQoNClNoaW55IGZ1ZSBjcmVhZG8gcG9yIEpvZSBDaGVuZywgdW4gaW5nZW5pZXJvIGRlIHNvZnR3YXJlIGVuIFJTdHVkaW8sIGVuIDIwMTIuIExhIG1vdGl2YWNpw7NuIHByaW5jaXBhbCBkZXRyw6FzIGRlIHN1IGRlc2Fycm9sbG8gZnVlIGxhIG5lY2VzaWRhZCBkZSB1bmEgaGVycmFtaWVudGEgcXVlIHBlcm1pdGllcmEgYSBsb3MgdXN1YXJpb3MgZGUgUiwgcHJpbmNpcGFsbWVudGUgZXN0YWTDrXN0aWNvcyB5IGNpZW50w61maWNvcyBkZSBkYXRvcywgY3JlYXIgYXBsaWNhY2lvbmVzIHdlYiBzaW4gdGVuZXIgcXVlIGFwcmVuZGVyIHRlY25vbG9nw61hcyBkZSBkZXNhcnJvbGxvIHdlYiBjb21vIEhUTUwsIENTUyBvIEphdmFTY3JpcHQuDQoNCioqTGFuemFtaWVudG8gSW5pY2lhbDoqKg0KDQpTaGlueSBmdWUgbGFuemFkbyBwb3IgcHJpbWVyYSB2ZXogZW4gMjAxMi4gRWwgcGFxdWV0ZSBwZXJtaXRpw7MgYSBsb3MgdXN1YXJpb3MgY3JlYXIgYXBsaWNhY2lvbmVzIGludGVyYWN0aXZhcyBjb24gc29sbyB1bm9zIHBvY29zIGNvbWFuZG9zIGVuIFIuIEVzdG8gZGVtb2NyYXRpesOzIGVsIGFjY2VzbyBhbCBkZXNhcnJvbGxvIGRlIGFwbGljYWNpb25lcyB3ZWIgZGVudHJvIGRlIGxhIGNvbXVuaWRhZCBkZSB1c3VhcmlvcyBkZSBSLCB5YSBxdWUgaGl6byBxdWUgbGEgY3JlYWNpw7NuIGRlIGludGVyZmFjZXMgZ3LDoWZpY2FzIGludGVyYWN0aXZhcyBmdWVyYSBtdWNobyBtw6FzIGFjY2VzaWJsZS4NCg0KKipDcmVjaW1pZW50byB5IFBvcHVsYXJpZGFkOioqDQoNClRyYXMgc3UgbGFuemFtaWVudG8sIFNoaW55IGdhbsOzIHLDoXBpZGFtZW50ZSBwb3B1bGFyaWRhZCBkZWJpZG8gYSBzdSBmYWNpbGlkYWQgZGUgdXNvIHkgbGEgcG90ZW5jaWEgZGUgbGFzIGFwbGljYWNpb25lcyBxdWUgc2UgcG9kw61hbiBjb25zdHJ1aXIgY29uIMOpbC4gUlN0dWRpbyBjb250aW51w7MgbWVqb3JhbmRvIFNoaW55LCBhZ3JlZ2FuZG8gY2FyYWN0ZXLDrXN0aWNhcyB5IG9wdGltaXphY2lvbmVzIHBhcmEgbWFuZWphciBhcGxpY2FjaW9uZXMgbcOhcyBncmFuZGVzIHkgY29tcGxlamFzLiBMYSBjb211bmlkYWQgYWxyZWRlZG9yIGRlIFNoaW55IHRhbWJpw6luIGNyZWNpw7MsIGNvbiBudW1lcm9zb3MgcGFxdWV0ZXMgeSBleHRlbnNpb25lcyBkZXNhcnJvbGxhZG9zIHBhcmEgY29tcGxlbWVudGFyIHkgZXhwYW5kaXIgc3VzIGNhcGFjaWRhZGVzLg0KDQoqKkV2b2x1Y2nDs24geSBBY3R1YWxpemFjaW9uZXM6KioNCg0KQSBsbyBsYXJnbyBkZSBsb3MgYcOxb3MsIFNoaW55IGhhIHJlY2liaWRvIG51bWVyb3NhcyBhY3R1YWxpemFjaW9uZXMgcXVlIGhhbiBtZWpvcmFkbyBzdSBmdW5jaW9uYWxpZGFkIHkgcmVuZGltaWVudG8uIEFsZ3VuYXMgZGUgbGFzIGFkaWNpb25lcyBtw6FzIGltcG9ydGFudGVzIGluY2x1eWVuIGxhIGludGVncmFjacOzbiBjb24gYmlibGlvdGVjYXMgZGUgdmlzdWFsaXphY2nDs24gY29tbyBnZ3Bsb3QyLCBlbCBzb3BvcnRlIHBhcmEgYXBsaWNhY2lvbmVzIGVzY2FsYWJsZXMsIHkgbWVqb3JhcyBlbiBsYSBnZXN0acOzbiBkZSBzZXNpb25lcyB5IGVuIGxhIGltcGxlbWVudGFjacOzbiBkZSBhcGxpY2FjaW9uZXMgU2hpbnkgZW4gc2Vydmlkb3Jlcy4NCg0KKipVc28gZW4gbGEgQWN0dWFsaWRhZDoqKg0KDQpIb3kgZW4gZMOtYSwgU2hpbnkgZXMgYW1wbGlhbWVudGUgdXRpbGl6YWRvIGVuIGxhIGFjYWRlbWlhLCBsYSBpbmR1c3RyaWEgeSBlbCBnb2JpZXJubyBwYXJhIGNyZWFyIGRhc2hib2FyZHMsIHZpc3VhbGl6YWNpb25lcyBpbnRlcmFjdGl2YXMsIHkgYXBsaWNhY2lvbmVzIGRlIGFuw6FsaXNpcyBkZSBkYXRvcy4gU3UgY2FwYWNpZGFkIHBhcmEgaW50ZWdyYXIgYW7DoWxpc2lzIGNvbXBsZWpvcyBlbiB0aWVtcG8gcmVhbCB5IHN1IGZsZXhpYmlsaWRhZCBsbyBoYW4gY29udmVydGlkbyBlbiB1bmEgaGVycmFtaWVudGEgZXNlbmNpYWwgcGFyYSBtdWNob3MgYW5hbGlzdGFzIGRlIGRhdG9zLg0KDQojIyMgRnVuY2lvbmVzIHByaW5jaXBhbGVzIGRlIFNoaW55DQoNClNoaW55IHBlcm1pdGUgcmVhbGl6YXIgbGFzIHNpZ3VpZW50ZXMgKiphY3RpdmlkYWRlczoqKg0KDQotICAgQ3JlYXIgZGFzaGJvYXJkcyBxdWUgcmFzdHJlYW4gaW5kaWNhZG9yZXMgY2xhdmUgZGUgcmVuZGltaWVudG8gYSBhbHRvIG5pdmVsLCBtaWVudHJhcyBmYWNpbGl0YW4gZWwgYW7DoWxpc2lzIGRldGFsbGFkbyBkZSBtw6l0cmljYXMgcXVlIG5lY2VzaXRhbiBtw6FzIGludmVzdGlnYWNpw7NuLg0KDQotICAgUmVlbXBsYXphciBjaWVudG9zIGRlIHDDoWdpbmFzIGRlIFBERnMgY29uIGFwbGljYWNpb25lcyBpbnRlcmFjdGl2YXMgcXVlIHBlcm1pdGVuIGFsIHVzdWFyaW8gaXIgZGlyZWN0YW1lbnRlIGEgbGEgc2VjY2nDs24gZXhhY3RhIGRlIGxvcyByZXN1bHRhZG9zIHF1ZSBsZXMgaW50ZXJlc2FuLg0KDQotICAgQ29tdW5pY2FyIG1vZGVsb3MgY29tcGxlam9zIGEgdW5hIGF1ZGllbmNpYSBubyB0w6ljbmljYSBjb24gdmlzdWFsaXphY2lvbmVzIGluZm9ybWF0aXZhcyB5IGFuw6FsaXNpcyBkZSBzZW5zaWJpbGlkYWQgaW50ZXJhY3Rpdm9zLg0KDQotICAgUHJvcG9yY2lvbmFyIGFuw6FsaXNpcyBkZSBkYXRvcyBkZSBhdXRvc2VydmljaW8gcGFyYSBmbHVqb3MgZGUgdHJhYmFqbyBjb211bmVzLCByZWVtcGxhemFuZG8gc29saWNpdHVkZXMgcG9yIGNvcnJlbyBlbGVjdHLDs25pY28gY29uIHVuYSBhcGxpY2FjacOzbiBTaGlueSBxdWUgcGVybWl0ZSBhIGxhcyBwZXJzb25hcyBjYXJnYXIgc3VzIHByb3Bpb3MgZGF0b3MgeSByZWFsaXphciBhbsOhbGlzaXMgZXN0w6FuZGFyLg0KDQotICAgQ3JlYXIgZGVtb3N0cmFjaW9uZXMgaW50ZXJhY3RpdmFzIHBhcmEgZW5zZcOxYXIgY29uY2VwdG9zIGRlIGVzdGFkw61zdGljYSB5IGNpZW5jaWEgZGUgZGF0b3MgcXVlIHBlcm1pdGVuIGEgbG9zIGVzdHVkaWFudGVzIG1vZGlmaWNhciBlbnRyYWRhcyB5IG9ic2VydmFyIGxvcyBlZmVjdG9zIGVuIGVsIGFuw6FsaXNpcy4NCg0KRW4gcmVzdW1lbiwgU2hpbnkgZGEgbGEgY2FwYWNpZGFkIGRlIHRyYW5zbWl0aXIgYWxndW5vcyBkZSAic3VwZXJwb2RlcmVzIGVuIFIiIGEgY3VhbHF1aWVyIHBlcnNvbmEgcXVlIHB1ZWRhIHVzYXIgbGEgd2ViLg0KDQpQb3Igb3RybyBsYWRvLCBTaGlueSBwcm9wb3JjaW9uYSB2YXJpYXMgKipmdW5jaW9uZXMgcHJpbmNpcGFsZXMqKiBxdWUgcGVybWl0ZW4gYSBsb3MgdXN1YXJpb3MgY3JlYXIgYXBsaWNhY2lvbmVzIHdlYiBpbnRlcmFjdGl2YXMgdXRpbGl6YW5kbyBSOg0KDQotICAgKnNoaW55QXBwKCkqDQoNCkVzdGEgZXMgbGEgZnVuY2nDs24gcHJpbmNpcGFsIHF1ZSBzZSB1dGlsaXphIHBhcmEgbGFuemFyIHVuYSBhcGxpY2FjacOzbiBTaGlueS4gVG9tYSBkb3MgYXJndW1lbnRvcywgdWkgKGxhIGludGVyZmF6IGRlIHVzdWFyaW8pIHkgc2VydmVyIChsYSBsw7NnaWNhIGRlbCBzZXJ2aWRvciksIHkgbG9zIGNvbWJpbmEgZW4gdW5hIGFwbGljYWNpw7NuIGNvbXBsZXRhLg0KDQotICAgKmZsdWlkUGFnZSgpKg0KDQpTZSB1dGlsaXphIHBhcmEgZGVmaW5pciBsYSBlc3RydWN0dXJhIGRlIGxhIGludGVyZmF6IGRlIHVzdWFyaW8uIERlbnRybyBkZSBmbHVpZFBhZ2UoKSwgc2UgcHVlZGVuIGluY2x1aXIgdmFyaW9zIGVsZW1lbnRvcyBkZSBkaXNlw7FvLCBjb21vIGZpbGFzIChmbHVpZFJvdygpKSwgY29sdW1uYXMgKGNvbHVtbigpKSwgeSBvdHJvcyBjb21wb25lbnRlcyBkZSBsYSBpbnRlcmZhei4NCg0KLSAgICp0aXRsZVBhbmVsKCkqDQoNClNlIHV0aWxpemEgcGFyYSBkZWZpbmlyIGVsIHTDrXR1bG8gcHJpbmNpcGFsIGRlIGxhIGFwbGljYWNpw7NuLg0KDQotICAgKnNpZGViYXJMYXlvdXQoKSoNCg0KUGVybWl0ZSBkaXZpZGlyIGxhIGludGVyZmF6IGVuIHVuYSBiYXJyYSBsYXRlcmFsIChzaWRlYmFyUGFuZWwoKSkgeSB1biBwYW5lbCBwcmluY2lwYWwgKG1haW5QYW5lbCgpKS4NCg0KLSAgICpzaWRlYmFyUGFuZWwoKSoNCg0KRGVmaW5lIGVsIGNvbnRlbmlkbyBkZSBsYSBiYXJyYSBsYXRlcmFsIGRlIGxhIGludGVyZmF6LiBOb3JtYWxtZW50ZSBpbmNsdXllIGNvbnRyb2xlcyBkZSBlbnRyYWRhIGNvbW8gc2xpZGVySW5wdXQoKSwgc2VsZWN0SW5wdXQoKSwgZXRjLg0KDQotICAgKm1haW5QYW5lbCgpKg0KDQpDb250aWVuZSBlbCBjb250ZW5pZG8gcHJpbmNpcGFsIGRlIGxhIGludGVyZmF6LCBjb21vIGdyw6FmaWNvcywgdGFibGFzIHkgb3Ryb3MgZWxlbWVudG9zIGRlIHNhbGlkYS4NCg0KLSAgICppbnB1dFwkIHkgb3V0cHV0XCQqDQoNCkVuIGVsIGxhZG8gZGVsIHNlcnZpZG9yLCBsb3Mgb2JqZXRvcyBpbnB1dFwkIHkgb3V0cHV0XCQgc2UgdXRpbGl6YW4gcGFyYSBhY2NlZGVyIGEgbG9zIHZhbG9yZXMgZGUgZW50cmFkYSB5IHBhcmEgZGVmaW5pciBzYWxpZGFzIHJlYWN0aXZhcywgcmVzcGVjdGl2YW1lbnRlLg0KDQotICAgKnJlbmRlclBsb3QoKSwgcmVuZGVyVGFibGUoKSwgcmVuZGVyVGV4dCgpKg0KDQpFc3RhcyBmdW5jaW9uZXMgc2UgdXRpbGl6YW4gZW4gbGEgcGFydGUgZGVsIHNlcnZpZG9yIHBhcmEgZ2VuZXJhciBzYWxpZGFzIHJlYWN0aXZhcyBxdWUgcHVlZGVuIHNlciBncsOhZmljb3MsIHRhYmxhcywgdGV4dG8sIGVudHJlIG90cm9zLiBFc3RhcyBzYWxpZGFzIHNlIGVubGF6YW4gY29uIGVsZW1lbnRvcyBlbiBvdXRwdXRcJC4NCg0KLSAgICpvYnNlcnZlKCkgeSBvYnNlcnZlRXZlbnQoKSoNCg0KRXN0YXMgZnVuY2lvbmVzIHNlIHV0aWxpemFuIHBhcmEgZWplY3V0YXIgY8OzZGlnbyBlbiByZXNwdWVzdGEgYSBjYW1iaW9zIGVuIGVudHJhZGFzIHJlYWN0aXZhcywgc2luIGdlbmVyYXIgdW4gdmFsb3IgZGUgc2FsaWRhLiBTb24gw7p0aWxlcyBwYXJhIG1vZGlmaWNhciBsYSBhcGxpY2FjacOzbiBkZSBtYW5lcmEgcmVhY3RpdmEgc2luIHByb2R1Y2lyIHVuYSBzYWxpZGEgZGlyZWN0YS4NCg0KLSAgICpyZWFjdGl2ZSgpKg0KDQpTZSB1dGlsaXphIHBhcmEgY3JlYXIgZXhwcmVzaW9uZXMgcmVhY3RpdmFzIHF1ZSBwdWVkZW4gc2VyIGNvbXBhcnRpZGFzIGVudHJlIHZhcmlhcyBzYWxpZGFzLiBVbmEgZXhwcmVzacOzbiByZWFjdGl2YSByZWNhbGN1bGEgc3UgdmFsb3IgYXV0b23DoXRpY2FtZW50ZSBjdWFuZG8gc3VzIGVudHJhZGFzIGNhbWJpYW4uDQoNCi0gICAqdWlPdXRwdXQoKSB5IHJlbmRlclVJKCkqDQoNClBlcm1pdGVuIGdlbmVyYXIgZGluw6FtaWNhbWVudGUgcGFydGVzIGRlIGxhIGludGVyZmF6IGRlIHVzdWFyaW8gY29uIGJhc2UgZW4gZWwgY8OzZGlnbyBkZWwgc2Vydmlkb3IuDQoNCi0gICAqaXNvbGF0ZSgpKg0KDQpTZSB1dGlsaXphIHBhcmEgZXZpdGFyIHF1ZSB1bmEgZXhwcmVzacOzbiByZWFjdGl2YSBzZSB2dWVsdmEgYSBlamVjdXRhciBhdXRvbcOhdGljYW1lbnRlIGN1YW5kbyBjYW1iaWFuIHN1cyBlbnRyYWRhcy4gRXMgw7p0aWwgcGFyYSBvcHRpbWl6YXIgbGEgZWplY3VjacOzbiBkZSBjw7NkaWdvLg0KDQojIyMgQ29tcG9uZW50ZXMgZGUgdW5hIGFwbGljYWNpw7NuIFNoaW55DQoNCkRlc2NyaWJpcmVtb3MgZW4gZXN0YSBzZWNjacOzbiBsb3MgY29tcG9uZW50ZXMgZGUgU2hpbnkuIExhIGluZm9ybWFjacOzbiByZWNhYmFkYSBzb2JyZSBsb3MgY29tcG9uZW50ZXMgc2Ugb2J0dXZvIGRlIGxhIHB1YmxpY2FjacOzbiBkZSBDdWV2YXMgKDIwMjEpLg0KDQpQcmltZXJvLCBwYXJhICoqaW5zdGFsYXIgU2hpbnkqKiwgcG9kZW1vcyB1dGlsaXphciBsb3Mgc2lndWllbnRlcyBjw7NkaWdvczoNCg0KYGBge3J9DQppbnN0YWxsLnBhY2thZ2VzKCJzaGlueSIpIA0KaWYgKCFyZXF1aXJlKCJkZXZ0b29scyIpKSANCiAgaW5zdGFsbC5wYWNrYWdlcygiZGV2dG9vbHMiKSANCmRldnRvb2xzOjppbnN0YWxsX2dpdGh1Yigic2hpbnkiLCAicnN0dWRpbyIpIA0KYGBgDQoNClRvbWVtb3MgZW4gY3VlbnRhIHF1ZSB0b2RhIGFwbGljYWNpw7NuIHdlYiBkZSBTaGlueSB0ZW5kcsOhIGxhIG1pc21hIGVzdHJ1Y3R1cmEsIGRvcyBibG9xdWVzIGRlIGPDs2RpZ29zIGRlIFI6DQoNCi0gICBVSTogZ2VuZXJhIHVuYSBpbnRlcmZheiBkZSB1c3VhcmlvDQoNCi0gICBTZXJ2ZXI6IGNvbnRpZW5lIGxhcyBpbnN0cnVjY2lvbmVzIHF1ZSBsYSBjb21wdXRhZG9yYSBuZWNlc2l0YSBwYXJhIGNyZWFyIGxhIGFwcC4NCg0KIVtdKGltYWdlcy8zLWJsYW5rLnBuZykNCg0KTGEgZXN0cnVjdHVyYSBkZSBjw7NkaWdvIGRlIHVuYSBhcHAgU2hpbnkgc2UgdmVyw61hIGRlbCBzaWd1aWVudGUgbW9kbzoNCg0KYGBge3J9DQpsaWJyYXJ5KHNoaW55KSANCnVpIDwtIGZsdWlkUGFnZSggDQp4eHh4SW5wdXQoKSwgDQp4eHh4T3V0cHV0KCkgDQopIA0Kc2VydmVyIDwtIGZ1bmN0aW9uKGlucHV0LCBvdXRwdXQpIA0KeyANCiBDb2RpZ28gZGUgUiANCn0gDQpzaGlueUFwcCh1aSA9IHVpLCBzZXJ2ZXIgPSBzZXJ2ZXIpIA0KYGBgDQoNCioqMS4gTGEgSW50ZXJmYXogZGUgVXN1YXJpbyAoVUkpKioNCg0KTGEgaW50ZXJmYXogZGUgdXN1YXJpbyBkZWZpbmUgbGEgZXN0cnVjdHVyYSB5IGVsIGRpc2XDsW8gZGUgbGEgYXBsaWNhY2nDs24gU2hpbnkuDQoNClNoaW55IHBvciBkZWZhdWx0IHVzYSBib290c3RyYXAgKGxvIGN1YWwgbm8gdGllbmUgbmFkYSBxdWUgdmVyIGNvbiBlbCBtw6l0b2RvIGVzdGFkw61zdGljbyBib290c3RyYXApLiBFc3RvIGVzIHVuIG1hcmNvIGRlIHRyYWJham8gZGUgSFRNTCwgQ1NTIHkgSmF2YXNjcmlwdCBtw6FzIHBvcHVsYXIgcGFyYSBkZXNhcnJvbGxhciBzaXRpb3Mgd2ViIHJlY2VwdGl2b3MuDQoNClBhcmEgdXNhciB0b2RvcyBsb3MgdGFncyBlbiBTaGlueSwgcG9kZW1vcyBjb25zdWx0YXIgZXN0b3MgdGFncyBjb24gbGEgc2lndWllbnRlIGZ1bmNpw7NuOg0KDQpgYGB7cn0NCnNoaW55Ojp0YWdzIA0KbmFtZXMoc2hpbnk6OnRhZ3MpIA0KYGBgDQoNClNoaW55IGZvbWVudGEgbGEgc2VwYXJhY2nDs24gZGVsIGPDs2RpZ28gcXVlIGdlbmVyYSBzdSBpbnRlcmZheiBkZSB1c3VhcmlvIChlbCBmcm9udC1lbmQpIGRlbCBjw7NkaWdvIHF1ZSBpbXB1bHNhIGVsIGNvbXBvcnRhbWllbnRvIGRlIHN1IGFwbGljYWNpw7NuIChlbCBiYWNrLWVuZCk6DQoNCiFbXShpbWFnZXMvdW5uYW1lZC5wbmcpDQoNCkV4aXN0ZSB1bmEgY29tdW5pZGFkIHJpY2EgeSB2aWJyYW50ZSBkZSBwYXF1ZXRlcyBkZSBleHRlbnNpw7NuLCBjb21vIHNoaW55V2lkZ2V0cywgY29sb3JwaWNrZXIgeSBzb3J0dGFibGUuDQoNCioqMi4gRWwgc2Vydmlkb3IgKHNlcnZlcikqKg0KDQpFbCBzZXJ2aWRvciBkZWZpbmUgbGEgbMOzZ2ljYSBkZSBsYSBhcGxpY2FjacOzbiwgaW5jbHV5ZW5kbyBjw7NtbyBzZSBwcm9jZXNhbiBsYXMgZW50cmFkYXMgeSBjw7NtbyBzZSBnZW5lcmFuIGxhcyBzYWxpZGFzLg0KDQpIYXkgMyByZWdsYXMgcGFyYSBlc2NyaWJpciBjw7NkaWdvIGVuIGVsIFNlcnZlcjoNCg0KLSAgIEVzcGVjaWZpY2EgY29uIGBvdXRwdXQkYCArIGBJRCBvdXRwdXRgIGNhZGEgb2JqZXRvIGRlbnRybyBkZSBgc2VydmVyYC4NCg0KLSAgIENhZGEgb2JqZXRvIHNlIG1vc3RyYXLDoSBjb24gdW4gYHJlbmRlcigpYCwgZWplbXBsbyBgcmVuZGVyUGxvdCh7fSlgDQoNCi0gICBBY2Nlc2EgYSBsb3MgdmFsb3JlcyBkZSBsb3MgaW5wdXRzIGNvbiBgaW5wdXQkYCArIGBJRCBpbnB1dGANCg0KIVtdKGltYWdlcy9zaGlueV84LnBuZykNCg0KKiozLiBSZWFjdGl2aWRhZCoqDQoNClNoaW55IGVzdMOhIGJhc2FkbyBlbiB1biBtb2RlbG8gcmVhY3Rpdm8gcXVlIGFjdHVhbGl6YSBhdXRvbcOhdGljYW1lbnRlIGxhcyBzYWxpZGFzIGN1YW5kbyBjYW1iaWFuIGxhcyBlbnRyYWRhcy4gTG9zIGNvbXBvbmVudGVzIGNsYXZlIHBhcmEgbWFuZWphciBsYSByZWFjdGl2aWRhZCBpbmNsdXllbjoNCg0KLSAgICoqRXhwcmVzaW9uZXMgcmVhY3RpdmFzKio6IFNlIGNyZWFuIHVzYW5kbyBgcmVhY3RpdmUoKWAgeSBzZSBwdWVkZW4gY29tcGFydGlyIGVudHJlIG3Dumx0aXBsZXMgc2FsaWRhcy4NCg0KLSAgICoqT2JzZXJ2YWRvcmVzKio6IFVzYW4gYG9ic2VydmUoKWAgcGFyYSBtb25pdG9yZWFyIGNhbWJpb3MgZW4gbGFzIGVudHJhZGFzIHkgZWplY3V0YXIgY8OzZGlnbyBlbiBjb25zZWN1ZW5jaWEuDQoNCi0gICAqKkFpc2xhbWllbnRvIGRlIHJlYWN0aXZvcyoqOiBMYSBmdW5jacOzbiBgaXNvbGF0ZSgpYCBldml0YSBxdWUgdW5hIGV4cHJlc2nDs24gcmVhY3RpdmEgc2UgcmVjYWxjdWxhIGN1YW5kbyBjYW1iaWFuIHN1cyBkZXBlbmRlbmNpYXMuDQoNCioqNC4gQ29tcG9uZW50ZXMgZGUgRXh0ZW5zacOzbioqDQoNCi0gICAqKmBzaGlueU1vZHVsZXNgKio6IFBlcm1pdGVuIGxhIG1vZHVsYXJpemFjacOzbiBkZWwgY8OzZGlnbyBTaGlueSwgZGl2aWRpZW5kbyBsYSBhcGxpY2FjacOzbiBlbiBjb21wb25lbnRlcyByZXV0aWxpemFibGVzLg0KDQotICAgKipgc2hpbnlXaWRnZXRzYCoqOiBVbiBwYXF1ZXRlIGFkaWNpb25hbCBxdWUgcHJvcG9yY2lvbmEgd2lkZ2V0cyBhZGljaW9uYWxlcyBwYXJhIG1lam9yYXIgbGEgaW50ZXJhY3RpdmlkYWQgeSBsYSBlc3TDqXRpY2EgZGUgbGFzIGFwbGljYWNpb25lcy4NCg0KLSAgICoqYHNoaW55anNgKio6IFBlcm1pdGUgaW50ZWdyYXIgZnVuY2lvbmFsaWRhZGVzIGRlIEphdmFTY3JpcHQgZW4gdW5hIGFwbGljYWNpw7NuIFNoaW55LCBvZnJlY2llbmRvIHVuIGNvbnRyb2wgbcOhcyBkZXRhbGxhZG8gZGUgbGEgaW50ZXJhY2Npw7NuIGRlbCB1c3VhcmlvLg0KDQpMb3MgYW50ZXJpb3JlcyBzb24gbG9zIGNvbXBvbmVudGVzIHByaW5jaXBhbGVzIGRlIFNoaW55IHF1ZSBwZXJtaXRlbiBjb25zdHJ1aXIgYXBsaWNhY2lvbmVzIHdlYiBpbnRlcmFjdGl2YXMuIENhZGEgdW5vIGp1ZWdhIHVuIHBhcGVsIGNydWNpYWwgZW4gbGEgZXN0cnVjdHVyYSB5IGZ1bmNpb25hbGlkYWQgZGUgdW5hIGFwbGljYWNpw7NuIFNoaW55LCBoYWNpZW5kbyBwb3NpYmxlIGxhIGNyZWFjacOzbiBkZSBpbnRlcmZhY2VzIGRpbsOhbWljYXMgeSByZWFjdGl2YXMgY29uIHVuIGVzZnVlcnpvIHJlbGF0aXZhbWVudGUgYmFqby4NCg0KIyMjIEVqZW1wbG9zIGRlIHVzbw0KDQpTaGlueSBlcyB1bmEgYmlibGlvdGVjYSBlbiBSIHF1ZSBmYWNpbGl0YSBsYSBjcmVhY2nDs24gZGUgYXBsaWNhY2lvbmVzIHdlYiBpbnRlcmFjdGl2YXMuIEVudHJlIGxvIHF1ZSBwZXJtaXRlIGhhY2VyIHRlbmVtb3M6DQoNCjEuICAqKkNyZWFyIEludGVyZmFjZXMgSW50ZXJhY3RpdmFzKio6IGNvbnN0cnVpciBhcGxpY2FjaW9uZXMgd2ViIGNvbiBpbnRlcmZhY2VzIGdyw6FmaWNhcyBpbnRlcmFjdGl2YXMgcGFyYSB2aXN1YWxpemFyIGRhdG9zLCByZWFsaXphciBhbsOhbGlzaXMgeSBjcmVhciBkYXNoYm9hcmRzLg0KDQoyLiAgKipWaXN1YWxpemFyIERhdG9zKio6IGNyZWFyIGdyw6FmaWNvcyBkaW7DoW1pY29zIHkgdGFibGFzIHF1ZSBzZSBhY3R1YWxpemFuIGVuIHRpZW1wbyByZWFsIGVuIGZ1bmNpw7NuIGRlIGxhcyBlbnRyYWRhcyBkZWwgdXN1YXJpby4NCg0KMy4gICoqRGVzYXJyb2xsYXIgQXBsaWNhY2lvbmVzIGRlIERhdG9zKio6IGNvbnN0cnVpciBhcGxpY2FjaW9uZXMgcGFyYSByZWFsaXphciBhbsOhbGlzaXMgZXN0YWTDrXN0aWNvcywgbW9kZWxhZG8gcHJlZGljdGl2byBvIGN1YWxxdWllciB0aXBvIGRlIHByb2Nlc2FtaWVudG8gZGUgZGF0b3MgZW4gbMOtbmVhLg0KDQo0LiAgKipDb25zdHJ1aXIgRGFzaGJvYXJkcyoqOiBjb25zdHJ1aXIgcGFuZWxlcyBkZSBjb250cm9sIGNvbXBsZXRvcyBwYXJhIHN1cGVydmlzYXIgbcOpdHJpY2FzIHkgZGF0b3MgZW4gdGllbXBvIHJlYWwuDQoNCjUuICAqKkNyZWFyIEZvcm11bGFyaW9zIHkgQXBsaWNhY2lvbmVzIGRlIEVudHJhZGEgZGUgRGF0b3MqKjogZGlzZcOxYXIgZm9ybXVsYXJpb3MgcGFyYSBsYSBlbnRyYWRhIGRlIGRhdG9zIHkgcHJvY2VzYXIgbG9zIHJlc3VsdGFkb3MgZGlyZWN0YW1lbnRlIGVuIGxhIGFwbGljYWNpw7NuLg0KDQo2LiAgKipJbnRlZ3JhciBjb24gT3RyYXMgSGVycmFtaWVudGFzKio6IFNoaW55IHB1ZWRlIGludGVncmFyc2UgY29uIG90cmFzIGhlcnJhbWllbnRhcyB5IHBhcXVldGVzIGRlIFIsIGNvbW8gZ2dwbG90MiBwYXJhIGdyw6FmaWNvcyB5IGRwbHlyIHBhcmEgbWFuaXB1bGFjacOzbiBkZSBkYXRvcy4NCg0KNy4gICoqSW1wbGVtZW50YXIgTW9kZWxvcyBkZSBNYWNoaW5lIExlYXJuaW5nKio6IGNvbnN0cnVpciBhcGxpY2FjaW9uZXMgcXVlIG11ZXN0cmVuIHByZWRpY2Npb25lcyB5IHJlc3VsdGFkb3MgZGUgbW9kZWxvcyBkZSBhcHJlbmRpemFqZSBhdXRvbcOhdGljbyBlbiB1bmEgaW50ZXJmYXogZGUgdXN1YXJpbyBpbnRlcmFjdGl2YS4NCg0KOC4gICoqRGVzcGxlZ2FyIEFwbGljYWNpb25lcyoqOiBQdWVkZXMgZGVzcGxlZ2FyIHR1cyBhcGxpY2FjaW9uZXMgU2hpbnkgZW4gc2Vydmlkb3JlcyBsb2NhbGVzIG8gZW4gbGEgbnViZSwgY29tbyBTaGlueUFwcHMuaW8gbyBlbiBzZXJ2aWRvcmVzIHByb3Bpb3MgdXNhbmRvIFNoaW55IFNlcnZlci4NCg0KLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tDQoNCkEgY29udGludWFjacOzbiwgc2UgZXN0dWRpYW4gZG9zIGVqZW1wbG9zIGRlIHVzbyBjb25jcmV0b3MgZGUgU2hpbnkgcGFyYSBsYSBjcmVhY2nDs24gZGUgYXBsaWNhY2lvbmVzOg0KDQoqKkPDoWxjdWxvIGRlIGxhIGRpc3RhbmNpYSBwdW50byBhIGzDrW5lYSoqDQoNCkVuIGVsIDIwMTgsIHVuIGF1dG9yIGRlIGJsb2cgdXRpbGl6w7MgbGEgbGlicmVyw61hIHBhcmEgcG9kZXIgdmlzdWFsaXphciBsYSBkaXN0YW5jaWEgZGUgdW4gcHVudG8gZXNwZWNpZmljbyBkZSBNZXhpY28gYSBsYSBsw61uZWEgZnJvbnRlcml6YSBjb24gRXN0YWRvcyBVbmlkb3MuDQoNCjEuICBQYXJhIHBvZGVyIGZpbHRyYXIgbGEgaW5mb3JtYWNpw7NuIG5lY2VzYXJpYSBlbiBjdWFudG8gYSBsYSBsb2NhbGl6YWNpw7NuIGRlIGVzdGFkb3MgeSBkZW3DoXMsIHNlIGRlc2NhcmfDsyBsYSBpbmZvcm1hY2nDs24gc29icmUgbGEgbMOtbmVhIGRlIGxhIGZyb250ZXJhIHBhcmEgcG9kZXIgdXRpbGl6YXJsYSBlbiBSLiBVbmEgdmV6IGNhcmdhZGEgbGEgaW5mb3JtYWNpw7NuLCBmdWUgcG9zaWJsZSByZWFsaXphciBzdSBsZWN0dXJhIHV0aWxpemFuZG8gbGEgZnVuY2nDs24gYHNmOjpzdF9yZWFkKClgLg0KDQpgYGB7cn0NCiBmIDwtIHN0X3JlYWQoIk1leGljb19hbmRfVVNfQm9yZGVyLnNocCIpDQpgYGANCg0KMi4gIFNlZ3VpZGFtZW50ZSwgc2UgZGlidWphcm9uIGxvcyBkYXRvcyBjb24gZWwgZmluIGRlIGNvbmZpcm1hciBxdWUgc2UgdGVuw61hbiBsb3MgZGF0b3MgbmVjZXNhcmlvcy4NCg0KYGBge3J9DQogIHBsb3QoZiwgbWF4LnBsb3QgPSAxKQ0KYGBgDQoNCjMuICBTZSBkZWZpbmnDsyBlbCBwdW50byBxdWUgc2UgdG9tYXLDrWEgZGUgcmVmZXJlbmNpYSBwYXJhIHNhY2FyIGxhIGRpc3RhbmNpYSBjb24gcmVzcGVjdG8gYSBsYSBmcm9udGVyYS4gU2UgZWxpZ2nDsyB0b21hciBjb21vIHJlZmVyZW5jaWEgZWwgQ29sZWdpbyBkZSBNw6l4aWNvLiBQYXJhIGxhIHV0aWxpemFjacOzbiBkZSBsYXMgY29vcmRlbmFkYXMgZGUgZGljaG8gbHVnYXIsIHNlIHVzw7MgR29vZ2xlIE1hcHMuIENvbiBlc3RhIHJlZmVyZW5jaWEgc2UgY3Jlw7MgbGEgdGFibGEgbGF0aXR1ZC9sb25naXR1ZC4NCg0KYGBge3J9DQpwdG8gPC0gZGF0YS5mcmFtZSh4ID0gLTk5LjIwNzc1LCB5ID0gMTkuMzAzNzQxKSAlPiUgDQogIHN0X2FzX3NmKGNvb3JkcyA9IGMoIngiLCAieSIpKSANCg0KIyBIb21vbG9nYW5kbyBlbCBTaXN0ZW1hIGRlIENvb3JkZW5hZGFzIGRlIFJlZmVyZW5jaWEgY29uIGxhIGJhc2UgZGUgbGEgbMOtbmVhIGRlIGxhIEZyb250ZXJhIE5vcnRlDQpzdF9jcnMocHRvKSA8LSBzdF9jcnMoZikNCmBgYA0KDQo0LiAgU2UgY2FsY3Vsw7MgbGEgZGlzdGFuY2lhIHV0aWxpemFuZG8gbGEgZnVuY2nDs24gYHN0X2Rpc3RhbmNlKClgIHBhcmEgY2FsY3VsYXIgbGEgZGlzdGFuY2lhIGdlb2TDqXNpY2EgcXVlIGhheSBlbnRyZSBkb3MgZWxlbWVudG9zIGdlb2dyw6FmaWNvcyBkZWwgbWFwYS4NCjUuICBDb24gbGEgaW5mb3JtYWNpw7NuIGFudGVyaW9yIHNlIGRldGVybWluw7MgZWwgcHVudG8gbcOhcyBjZXJjYW5vIGRlIGxhIGZyb250ZXJhIGFsIENvbGVnaW8gZGUgTcOpeGljbywgcGVybyBzdXJnacOzIGxhIHByZWd1bnRhIGRlIGVuIGTDs25kZSBlc3TDoSwgcG9yIGxvIHF1ZSBzZSBkZXNjb21wdXNvIGxhIGzDrW5lYSBkZSBsYSBmcm9udGVyYSBub3J0ZSBlbiB2w6lydGljZXMgeSBjb21wb25lbnRlcyBjb24gZWwgZmluIGRlIGRldGVybWluYXIgbGEgbMOtbmVhIGNvbiBsYSBtZW5vciBsb25naXR1ZA0KNi4gIERlc3B1w6lzIGRlIHVuYSBzZXJpZSBkZSBwYXNvcywgc2UgbG9ncsOzIHZpc3VhbGl6YXIgZWwgcHVudG8gY29uIGVsIHVzbyBkZWwgY8OzZGlnbzoNCg0KYGBge3J9DQpsaW5lYSA8LSBzdF9saW5lc3RyaW5nKG1hdHJpeChjKHB0b1ssImdlb21ldHJ5Il0gJT4lIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RfY29vcmRpbmF0ZXMoKSwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwdW50b19mcm9udGVyYVssImdlb21ldHJ5Il0gJT4lIHN0X2Nvb3JkaW5hdGVzKCkpLCBuY29sID0gMiwgYnlyb3cgPSBUUlVFKSkNCmBgYA0KDQo3LiAgU2UgcGxhc23DsyBlbiB1biBtYXBhIGRlIGBsZWFmbGV0YA0KDQpgYGB7cn0NCiBsZWFmbGV0KCkgJT4lIA0KICAgICAgYWRkVGlsZXMoKSAlPiUgDQogICAgICBhZGRDaXJjbGVNYXJrZXJzKGRhdGEgPSBwdG8pICU+JSANCiAgICAgIGFkZENpcmNsZU1hcmtlcnMoZGF0YSA9IHB1bnRvX2Zyb250ZXJhKSAlPiUgDQogICAgICBhZGRQb2x5bGluZXMoZGF0YSA9IGxpbmVhKSAlPiUgDQogICAgICBhZGRQb2x5bGluZXMoZGF0YSA9IGYsIGNvbG9yID0gInJlZCIpDQpgYGANCg0KOC4gIEZpbmFsbWVudGUsIHNlIG9idHV2aWVyb24gbG9zIHNpZ3VpZW50ZXMgcmVzdWx0YWRvcywgcXVlIGxlIHBlcm1pdGnDsyBkZXRlcm1pbmFyIHF1ZSBlbCBwdW50byBtw6FzIGNlcmNhbm8gYSBsYSBmcm9udGVyYSBub3J0ZSBzZSBlbmN1ZW50cmEgdW5vcyBraWzDs21ldHJvcyBhbCBFc3RlIGRlIGxhIENpdWRhZCBkZSBNYXRhbW9yb3MsIGVuIGVsIEVzdGFkbyBkZSBUYW1hdWxpcGFzLg0KDQogICAgIVtdKENhcHR1cmEgZGUgcGFudGFsbGEgMjAyNC0wOC0yNSAxOTMxMDMucG5nKQ0KDQpDb24gbGEgaW5mb3JtYWNpw7NuIGFudGVyaW9yLCBlbCBhdXRvciBjcmXDsyB1biBTaGlueSBhcHAsIGNvbiBlbCBmaW4gZGUgcXVlIGN1YWxxdWllciB1c3VhcmlvIHB1ZWRhIGNhbGN1bGFyIGxhIGRpc3RhbmNpYSBkZSBjdWFscXVpZXIgcHVudG8gYSBsYSBmcm9udGVyYSBzdXIgZGUgRXN0YWRvcyBVbmlkb3MuIEVuIGVzdGUgY2FzbywgZWwgKipzdXBlcnBvZGVyKiogcXVlIHNlIHBhc8OzIGZ1ZSBlbCBkZSBwb2RlciBjYWxjdWxhciBsYSBkaXN0YW5jaWEgeSBwb2RlciBjb25zdHJ1aXIgbGEgbMOtbmVhIGRlIG3DrW5pbWEgZGlzdGFuY2lhIHRhbiBzb2xvIGNvbiBwcmVzaW9uYXIgdW4gcHVudG8gZW4gZWwgbWFwYS4NCg0KIVtdKENhcHR1cmEgZGUgcGFudGFsbGEgMjAyNC0wOC0yNSAxOTMzNTkucG5nKQ0KDQpbKipFY29iaWNpKipdKGh0dHBzOi8vbG5wcG1pY3Jvc2l0aW8uc2hpbnlhcHBzLmlvL2Vjb2JpY2lEYXRhdG9uLykqKihEYXRhdMOzbikqKg0KDQpFc3RhIGFwbGljYWNpw7NuIGZ1w6kgdW5hIGVudHJhZGEgcGFyYSBlbCBEYXRhdMOzbiBkZSBWaXN1YWxpemFjacOzbiBkZSBkYXRvcyBkZSBlY29iaWNpIGRlbCBDSU1BVC4gU3UgcmVhbGl6YWNpw7NuIGZ1w6kgdW4gdHJhYmFqbyBjb25qdW50byBlbnRyZSBhbmFsaXN0YXMgcXVlIHVzYXJvbiBQeXRob24geSBSIHBhcmEgZWwgYW7DoWxpc2lzIGRlIGRhdG9zLCBjb211bmljYW5kbyBsb3MgcmVzdWx0YWRvcyBhIGxhIGFwbGljYWNpw7NuIGEgdHJhdsOpcyBkZSB1bmEgQVBJLg0KDQpFY29iaWNpIGVzIHVuIHNpc3RlbWEgZGUgYmljaWNsZXRhcyBjb21wYXJ0aWRhcyBsYW56YWRvIGVuIGZlYnJlcm8gZGUgMjAxMCBwb3IgZWwgZ29iaWVybm8gZGUgbGEgQ2l1ZGFkIGRlIE3DqXhpY28gcGFyYSBsYSByZWFsaXphY2nDs24gZGUgdmlhamVzIGRlIGNvcnRhIGRpc3RhbmNpYSB5IGR1cmFjacOzbiBhIHByZWNpb3MgcmVkdWNpZG9zIG8gZGUgZm9ybWEgZ3JhdHVpdGEuIEVsIHNpc3RlbWEgY3VlbnRhIGNvbiA0ODAgY2ljbG9lc3RhY2lvbmVzIHkgbcOhcyBkZSA2IG1pbCA4MDAgYmljaWNsZXRhcywgZGUgbGFzIGN1YWxlcyAyOCBlc3RhY2lvbmVzIHkgMzQwIGJpY2ljbGV0YXMgZm9ybWFuIHBhcnRlIGRlbCBudWV2byBzaXN0ZW1hIGRlIGJpY2ljbGV0YXMgZWzDqWN0cmljYXMgZGUgcGVkYWxlbyBhc2lzdGlkby4NCg0KIVtdKENhcHR1cmEgZGUgcGFudGFsbGEgMjAyNC0wOC0yNSAxOTQzMzIucG5nKQ0KDQojIyBDb25jbHVzaW9uZXMNCg0KU2hpbnkgaGEgdHJhbnNmb3JtYWRvIGVsIHBhbm9yYW1hIGRlbCBhbsOhbGlzaXMgZGUgZGF0b3MgeSBsYSB2aXN1YWxpemFjacOzbiBhbCBwZXJtaXRpciBhIGxvcyB1c3VhcmlvcyBkZSBSIGNyZWFyIGFwbGljYWNpb25lcyB3ZWIgaW50ZXJhY3RpdmFzIHNpbiBuZWNlc2lkYWQgZGUgY29ub2NpbWllbnRvcyBhdmFuemFkb3MgZW4gZGVzYXJyb2xsbyB3ZWIuIFN1IGZsZXhpYmlsaWRhZCwgY29tYmluYWRhIGNvbiBlbCBwb2RlciBkZSBSLCBsbyBjb252aWVydGUgZW4gdW5hIGhlcnJhbWllbnRhIGludmFsdWFibGUgcGFyYSBjaWVudMOtZmljb3MgZGUgZGF0b3MsIGFuYWxpc3RhcyB5IGRlc2Fycm9sbGFkb3JlcyBlbiB1bmEgdmFyaWVkYWQgZGUgY2FtcG9zLg0KDQpBIG1lZGlkYSBxdWUgbGEgdGVjbm9sb2fDrWEgYXZhbnphLCBlcyBwcm9iYWJsZSBxdWUgU2hpbnkgY29udGluw7plIGV2b2x1Y2lvbmFuZG8sIGluY29ycG9yYW5kbyBudWV2YXMgZnVuY2lvbmVzIHkgY2FwYWNpZGFkZXMgcXVlIGZhY2lsaXRlbiBhw7puIG3DoXMgbGEgY3JlYWNpw7NuIGRlIGFwbGljYWNpb25lcyB3ZWIgc29maXN0aWNhZGFzIHkgYXRyYWN0aXZhcy4NCg0KIyMgQmlibGlvZ3JhZsOtYQ0KDQotICAgQmVlbGV5LCBDLiwgJiBDaGVuZywgSi4gKDIwMTgpLiBXZWIgQXBwbGljYXRpb24gRGV2ZWxvcG1lbnQgd2l0aCBSIFVzaW5nIFNoaW55OiBCdWlsZCBTdHVubmluZyBHcmFwaGljcyBhbmQgSW50ZXJhY3RpdmUgRGF0YSBWaXN1YWxpemF0aW9ucy4gUGFja3QgUHVibGlzaGluZy4NCg0KLSAgIENoYW5nLCBXLiwgQ2hlbmcsIEouLCBBbGxhaXJlLCBKLiwgWGllLCBZLiwgJiBNY1BoZXJzb24sIEouICgyMDE4KS4gU2hpbnk6IFdlYiBBcHBsaWNhdGlvbiBGcmFtZXdvcmsgZm9yIFIuIFIgcGFja2FnZSB2ZXJzaW9uIDEuMi4wLg0KDQotICAgQ3VldmFzLUZlcm5hbmRleiwgRS4gKDIwMjEpLiBJbnRyb2R1Y2Npw7NuIGEgU2hpbnkuIFdvcmtzaG9wIENEU0IgMjAyMTogRmx1am9zIGRlIHRyYWJham8gY29uIFJTdHVkaW8geSBjcmVhY2nDs24gZGUgU2hpbnkgYXBwcy4gaHR0cHM6Ly9jb211bmlkYWRiaW9pbmZvLmdpdGh1Yi5pby9jZHNiMjAyMV93b3JrZmxvd3MvaW50cm9kdWNjaSVDMyVCM24tYS1zaGlueS5odG1sI3F1JUMzJUE5LWVzLXktcGFyYS1xdSVDMyVBOS1tZS1zaXJ2ZS1zaGlueQ0KDQotICAgRmVybsOhbmRleiwgTS5JLiAoMjAyMCkgVmVudGFqYXMgZGUgUiBjb21vIGhlcnJhbWllbnRhIHBhcmEgZWwgQW7DoWxpc2lzIHkgVmlzdWFsaXphY2nDs24gZGUgZGF0b3MgZW4gQ2llbmNpYXMgU29jaWFsZXMuIFJldi4gY2llbnRlLiBVQ1NBIHZvbC43IG5vLjIgQXN1bmNpw7NuIEF1Zy4gMjAyMC4gUmVjdXBlcmFkbyBkZSBodHRwOi8vc2NpZWxvLmlpY3MudW5hLnB5L3NjaWVsby5waHA/c2NyaXB0PXNjaV9hcnR0ZXh0JnBpZD1TMjQwOS04NzUyMjAyMDAwMDIwMDA5Nw0KDQotICAgR3JvbGVtdW5kLCBHLiwgJiBXaWNraGFtLCBILiAoMjAxNikuIFIgZm9yIERhdGEgU2NpZW5jZTogSW1wb3J0LCBUaWR5LCBUcmFuc2Zvcm0sIFZpc3VhbGl6ZSwgYW5kIE1vZGVsIERhdGEuIE8nUmVpbGx5IE1lZGlhLg0KDQotICAgSnV2ZSBCbG9nLiAoMjAyMCkuIERpc3RhbmNpYSBwdW50byBhIGxpbmVhIGh0dHBzOi8vanV2ZW5hbGNhbXBvcy5jb20vMjAyMC8wMi8xOC9kaXN0YW5jaWEtcHVudG8tYS1saW5lYS8NCg0KLSAgIEp1dmUgQmxvZy4oMjAyMCkuRWplbXBsb3MgZGUgbG8gcXVlIHNlIHB1ZWRlIGhhY2VyIGVuIHNoaW55IC0gaHR0cHM6Ly9qdXZlbmFsY2FtcG9zLmNvbS8yMDIwLzAzLzAzL2VqZW1wbG9zLWRlLWxvLXF1ZS1zZS1wdWVkZS1oYWNlci1lbi1zaGlueS8NCg0KLSAgIFJTdHVkaW8uICgyMDIwKS4gU2hpbnk6IEVhc3kgd2ViIGFwcGxpY2F0aW9ucyBpbiBSLiBSU3R1ZGlvLCBJbmMuDQoNCi0gICBSeWFuLCBZLiAoMjAyMywgRGVjZW1iZXIgMTMpLiBDcmVhY2nDs24gZGUgYXBsaWNhY2lvbmVzIHdlYiBpbnRlcmFjdGl2YXMgY29uIFIgeSBTaGlueS4gUHJvZ3JhbW1pbmcgSGlzdG9yaWFuLiBodHRwczovL3Byb2dyYW1taW5naGlzdG9yaWFuLm9yZy9lcy9sZWNjaW9uZXMvY3JlYWNpb24tZGUtYXBsaWNhY2lvbi1zaGlueQ0KDQotICAgU2hpbnkgaHR0cHM6Ly9zaGlueS5wb3NpdC5jbw0KDQotICAgU2lldmVydCwgQy4gKDIwMjApLiBJbnRlcmFjdGl2ZSBXZWItQmFzZWQgRGF0YSBWaXN1YWxpemF0aW9uIHdpdGggUiwgcGxvdGx5LCBhbmQgc2hpbnkuIENoYXBtYW4gYW5kIEhhbGwvQ1JDLg0KDQotICAgV2lja2hhbSwgSC4gKDIwMjEpLiBNYXN0ZXJpbmcgU2hpbnk6IEJ1aWxkIGludGVyYWN0aXZlIGFwcHMsIHJlcG9ydHMsIGFuZCBkYXNoYm9hcmRzIHBvd2VyZWQgYnkgUi4gTydSZWlsbHkgTWVkaWEuIFJlY3VwZXJhZG8gZGUgaHR0cHM6Ly9tYXN0ZXJpbmctc2hpbnkub3JnL2luZGV4Lmh0bWwNCg==