El objetivo de esta sección es proporcionar una breve primera introducción a R y RStudio para personas que no han tenido contacto previo con estos programas y explicitar la forma que tendremos de interactuar con ellos; es decir, la forma de trabajar con ellos (workflow).

El curso es una introducción a la Ciencia de Datos: haremos diversos análisis con datos y para ello utilizaremos R. R será el programa que hará los cálculos, gráficos, informes, pero interactuaremos con R, le daremos las ordenes a R, a través de otro programa: RStudio. Así que tendremos que instalar los 2 programas. Por ello, en la web del curso tienes un fichero donde se explica como hacerlo: concretamente aquí.

Aquí tienes un articulo que explica, con mucho detalle, como empezar a trabajar con R: instalación, configuración, paquetes, etc…


Se puede trabajar con R/RStudio de varias formas. Nosotros trabajaremos, casi siempre, con Rprojects. Enseguida diremos qué son los Rprojects, pero de momento podemos pensar que son carpetas donde se almacenan los ficheros necesarios para hacer un análisis de datos.

Dentro de esas carpetas o Rprojects tendremos distintos tipos de ficheros: ficheros de datos, imágenes etc… y unos ficheros, llamados habitualmente scripts que contendrán las instrucciones que queramos que sean ejecutadas por R/RStudio. Bien, pues esos scripts o ficheros de ordenes pueden ser de varios tipos. Concretamente, durante el curso utilizaremos 2 tipos de ficheros para darle las ordenes a R:

  • ficheros .R , y

  • ficheros Rmarkdown o ficheros .Rmd.

Lo normal es que nunca hayas oído hablar de todo esto, así que al principio te sonará complicado, pero en nada te parecerá lo más natural del mundo. Bird by bird!!!

1. R

Ya hemos hablado de R, pero …

¿Qué es R?

Ya lo habéis visto mientras hacíamos algún ejemplo, pero para los nuevos: R es un lenguaje de programación y un entorno para el análisis estadístico y gráfico. Se puede utilizar para muchas cosas ya que es un lenguaje de programación, pero principalmente se utiliza en el campo de la estadística y la ciencia de datos; de hecho, R fue inicialmente creado en 1993 por dos estadísticos de la Universidad de Auckland: R. Ihaka y R.Gentleman1. A partir de 1997 el desarrollo de R (o base-R) es gestionado por un grupo de programadores conocido como “The R-core team”; pero actualmente, el entorno o ecosistema R es el resultado de la colaboración de toda una comunidad de usuarios que extiende las utilidades de base-R mediante la creación de nuevos paquetes y funciones.

R forma parte del sistema GNU y se distribuye bajo la licencia GNU GPL por lo que los usuarios tenemos la libertad de usar, estudiar, compartir (copiar) y modificar el software; es decir, R es software libre. Además de software libre, R es gratuito y multiplataforma: está disponible para Windows, Macintosh y GNU/Linux.

La página web oficial de R se llama: The R Project for Statistical Computing. Allí podrás encontrar toda la información y documentación oficial acerca de R. Aunque si alguna vez la necesitas, se puede consultar desde R con la función help.start() o, en un formato visualmente más agradable, en este repositorio de Collin Fay un destacado miembro de la actual comunidad R. Si quieres ver las personas que forman parte del R core-team o que han contribuido al desarrollo de R no tienes mas que teclear en R contributors().

R proporciona un amplio abanico de herramientas estadísticas y gráficas (modelos lineales y no lineales, tests estadísticos, análisis de series temporales, algoritmos de clasificación y agrupamiento, etc.). Como R también es un lenguaje de programación, permite que los usuarios lo extiendan definiendo sus propias funciones y paquetes. De hecho, actualmente R se ha convertido de un proyecto colaborativo y abierto en el que sus usuarios pueden publicar paquetes que extienden su configuración básica. Para darte una idea de lo prolífica y colaborativa que es la comunidad R puedes visitar estos 2 proyectos: R-bloggers y R-Weekly. Precisamente estos 2 aspectos (abundancia de paquetes y comunidad de usuarios) son claves en el éxito de R

Ya hemos dicho que R (junto con sus paquetes) puede implementar una gran variedad de técnicas estadísticas y gráficas. Existe un repositorio oficial de paquetes: Comprehensive R Archive Network o CRAN. CRAN alcanzó los 10.000 paquetes en enero de 2017, y actualmente, julio de 2019, tiene 14.553 paquetes. Además, existen muchos más paquetes en repositorios como Bioconductor, Github y otros.


Instalación de R

Obviamente, para usar R y sus paquetes tenemos que instalarlo primero. Para ello “solo” tienes que ir a CRAN y descargar la distribución de R adecuada para tu sistema operativo. Obviamente mejor la última versión. En el momento de re-escribir estas notas la última versión es R-4.1.1 llamada “Kick Things” released on 2021/08/10.

No te va a a hacer falta pero por si acaso, aquí tienes un vídeo de 1:30 donde se explica de manera sencilla como instalar R.

2. RStudio

¿Qué es RStudio?

Pues es un programa que utilizaremos para interactuar con R. Las instrucciones que queramos dar a R para que las ejecute se las daremos a través de RStudio. La razón es que la interfaz de usuario (GUI, Graphical User Interface) de R no es muy amigable ni versátil, así que interactuaremos con R a través de RStudio.

RStudio es un programa que nos permitirá interactuar con R de forma más amigable, además de facilitar muchas de las tareas de programación y análisis de datos en R; es decir, RStudio es una GUI (Graphical User Interface). En realidad, RStudio es más que una GUI, es una IDE, un entorno de desarrollo integrado para R, en inglés ‘integrated development environment’ o IDE.

El actual científico jefe de RStudio es Hadley Wickham. Wickham es uno de los más prolíficos desarrollador de paquetes para R y creador de un nuevo estilo de programar y analizar datos en R conocido como tidyverse. Muchos de los packages que utilizaremos en el curso han sido desarrollados por él y el equipo de RStudio.


Instalación de RStudio

La versión de escritorio de RStudio también es libre y gratuita. Se puede descargar aquí. Tienes que descargarte el ‘installer’ adecuado para tu sistema operativo.

Se puede trabajar perfectamente con las opciones por defecto de RStudio, pero os recomiendo cambiar algunas opciones, así que vamos a configurar RStudio.

Configurando RStudio

Está sección no es obligatoria, solo que es recomendable configurar las opciones de RStudio. ¿Cómo? En RStudio, sigue está ruta de menús: Tools > Global OPtions...

Se abrirá una ventana (que puedes ver abajo) con las opciones de configuración de RStudio. De momento vamos sólo a tocar la categoría que ves en la imagen; es decir, R General. Tienes que hacer dos cosas:

  1. desmarcar todas las casillas (quitarles los ticks)

  2. Es importante, poner Never en la casilla donde pone “Save workspace to .RData on exit”.

Al final, en mi ordenador, la ventana con las opciones de R General queda como:

En tu ordenador debe quedar todo igual excepto la caja de texto. El texto de la caja le dice a RStudio donde se guardarán los archivos que vayamos generando; es decir, indica el directorio de trabajo por defecto. Como mi sistema operaivo es Linux y habitualmente trabajo en el escritorio de mi PC, en la imagen de abajo pone “~/Escritorio”, si mi sistema operativo fuese Windows pondría algo como “C:/Users/perezp/Desktop”. Te recomiendo trabajar sobre el escritorio o Desktop, pero puedes seleccionar la carpeta en la que más cómoda trabajes2.

Ya explicaré en clase porqué seleccionamos estas opciones en RStudio.

Aún más configuración de RStudio

  1. En RStudio sigue está ruta de menús: Tools > Global OPtions... y selecciona Code. Intenta dejar la opciones de la pestaña Editing como ves en la imagen de abajo. Concretamente lo que más me interesa es que esté marcada la opción Insert spaces for tab

  1. En RStudio sigue está ruta de menús: Tools > Global OPtions... y selecciona Code. Ahora intenta dejar las opciones de la pestaña Saving como ves en la imagen de abajo. Lo más importante es que en la caja de texto Default text encoding ponga: UTF-8. Esto evitará que tengamos problemas con la codificación de loa caracteres, por ejemplo con la eñe o con las tildes.

Ya tenemos R y RStudio instalados y configurados, así que vamos a empezar a toquetear RStudio.

Conociendo la interfaz de RStudio

Durante el curso vamos a utilizar R para hacer análisis estadísticos pero lo vamos a hacer a través de RStudio, así que el primer paso es familiarizarnos un poco con la interfaz de RStudio. Para acostumbrase a R y RStudio lo mejor es la práctica, pero si os hiciese falta, aquí tenéis un fantástico libro para habituarse a trabajar con R y RStudio.

Al abrir RStudio verás que al principio tiene 3 paneles, aunque enseguida abriremos un cuarto panel. La consola es el panel de la izquierda. Cuando tengamos 4 paneles la consola será el panel situado izquierda-abajo. Podemos pensar que la consola es lo más parecido a R, ya que en la consola se pueden ejecutar instrucciones de R directamente.

Cuando abras RStudio veras lo siguiente:

  • Consola (izquierda)

  • Environment/History (arriba-derecha)

  • Files/Plots/Packages/Help (abajo-derecha)

Ya sabemos que el panel de la izquierda es la consola. En la consola se ve un mensaje de bienvenida que nos dice que versión de R estamos usando y alguna cosa más. Al final del texto aparece el símbolo >. A este símbolo se le conoce como prompt y simplemente nos indica que el intérprete de R, que R, está listo para ejecutar nuestras instrucciones.

¿Cómo le damos las instrucciones u ordenes a R? La forma más inmediata es escribiendo las ordenes en la consola, después del prompt (>). Por ejemplo, si escribimos en la consola 2+2 y presionamos Enter, R ejecutará la instrucción y nos devolverá el resultado.

A veces usaremos la consola para ejecutar alguna instrucción, pero en general ejecutaremos las instrucciones a través de un “script”. Una razón para no usar la consola es que trabajar en la consola es muy limitado ya que las instrucciones se han de introducir una a una. Otra razón es que queremos tener un registro con todas las instrucciones que ejecutemos para poder replicar nuestro análisis en otro momento; así que lo habitual es trabajar con scripts o ficheros de instrucciones.

Un script no es más que un fichero de texto con extensión .R en el que escribiremos las instrucciones que queramos que R ejecute.

Vamos a crear nuestro primer script. Para ello tienes que seguir esta ruta de menús en RStudio: File > New File > R Script. Visualmente:

Cuando pinches con el ratón en R Script se abrirá en RStudio un nuevo panel, el cuarto, arriba a la izquierda. Visualmente:

Este cuarto panel (arriba-izquierda) en realidad es un editor de texto. En él podemos escribir las instrucciones que queramos que ejecute R. Por ejemplo, fíjate en la siguiente imagen lo que he escrito en el panel arriba-izquierda:

He escrito estas cuatro lineas:

# mi primer script de R
2 + 2
5 * 6
400/2

Escribe tú también (o copia y pega) estás cuatro lineas de texto en el editor (arriba-izquierda) de tu Rstudio.

R ejecutará, cuando se lo indiquemos, las lineas de instrucciones una a una.

Una vez hayas escrito o pegado esas 4 lineas en RStudio, verás que la primera linea es diferente: lo más evidente es que está en color verde, pero en realidad lo importante es que comienza con el símbolo #. Este hecho, está marcando/diciendo a R que esa linea es un comentario para los humanos, para nosotros, no es código R y por tanto R no la ejecutará.

En un script sólo se pueden escribir 2 cosas:

  • comentarios (si la linea comienza con #). R no las ejecutará

  • instrucciones R (no comienzan con #). R las ejecutará si están escritas en R; es decir, si siguen las reglas del lenguaje R. Si están mal escritas R nos devolverá un mensaje de error. Tenemos que aprender R ya!!!

Hemos escrito cuatro lineas en nuestro script y ahora queremos que R las ejecute. R ejecutará, cuando se lo indiquemos, las lineas de instrucciones una a una.

Para ejecutar una linea, situamos el cursor en ella y pulsamos Crtl + Enter.

Please, sitúa el cursor en la primera linea y pulsa Crtl + Enter. Observa qué ha ocurrido. Le hemos dicho a R que ejecute la primera linea, pero como esta primera linea comienza con #, R la ha interpretado (correctamente) como un comentario y, por supuesto, no la ha ejecutado, por lo que ha pasado a la segunda linea, y esta vez sí que la ejecuta. Como la segunda linea no comienza con #, R la interpreta como una instrucción de R y, sí la entiende (si las has escrito correctamente siguiendo la sintaxis o lenguaje de R), ejecutará la instrucción. R entiende que significa 2 + 2, así que ejecuta la instrucción y nos devuelve el resultado en la consola.


En la imagen de abajo yo ya he ejecutado la instrucción 2 + 2. R nos muestra el resultado en la consola: primero nos muestra, en azul, la instrucción que ha ejecutado; es decir > 2 + 2 y luego nos nos muestra, en negro, el resultado de la ejecución de la instrucción; es decir [1] 4. Ya veremos que significa el [1] de la linea de resultados.

Es más fácil hacerlo que contarlo, aunque puede que te atasques en alguna cosa, normal!!. Por ejemplo, si en lugar de poner el cursor en la segunda linea, señalas o subrayas solo parte de la linea, entonces, seguramente R no te entenderá. Ahora te toca a ti: please, ejecuta la tercera linea de tu script.

¿Cómo le decimos a R que ejecute la tercera linea 5 * 6? Cuando lo hacíamos en la consola simplemente había que pulsar Enter, pero ahora estamos trabajando en un script: hay que situar el cursor en la linea que queremos ejecutar y darle a Crtl + Enter. R ejecutará la instrucción y nos devolverá el resultado en la consola.

Enseguida aprenderemos más instrucciones o funciones de R, ahora solo estamos intentando familiarizándonos con el interfaz de RStudio. Ya sabemos como crear un fichero con instrucciones de R (ó script) y como ejecutar esas instrucciones.

Lo normal es que guardes tus scripts en un archivo por si tuvieses que volver a correr las mismas instrucciones más adelante. Para guardar tus instrucciones en un fichero sólo tienes que seguir esta ruta de menús en RStudio: File > Save as ...

Tendrás que elegir un nombre para tu script y decidir en que carpeta de tu ordenador guardarlo. Si decides que tu script se llame my_script_01, se creará un fichero (donde tú hayas decidido) llamado my_script_01.R. Fíjate que la extensión del archivo es .R, está extensión identifica los scripts o ficheros con instrucciones de R.

Esto vas a acabar entendiéndolo en poco tiempo, pero cuanto antes lo entiendas mejor: damos las ordenes/instrucciones a R por escrito, generalmente usamos “scripts”; es decir, escribimos las instrucciones en un fichero con extensión .R. Para ejecutar las ordenes que hemos escrito en nuestro fichero R hemos de, linea por linea, teclear: Crtl + Enter. Si la orden tiene sentido, es decir, si R entiende la orden, la ejecutará y te mostrará el resultado en la Consola.


Bien, ya sabemos hacer que R ejecute nuestras instrucciones: podemos ejecutar ordenes en la Consola (con Enter) o en un script (Crtl + Enter). Usaremos la consola a veces, muchas veces trabajaremos con scripts o ficheros .R pero, poco a poco, acabaremos trabajando de otra forma.

Como queremos que nuestros análisis sean reproducibles, habitualmente trabajaremos con Rprojects y con ficheros .Rmd. Sí!!, en lugar de con ficheros .R (o scripts) trabajaremos con ficheros **Rmarkdown** ó ficheros .Rmd. Ya lo veremos, pero antes tendremos que familiarizarnos un poco más con el lenguaje R. De momento seguimos con el interfaz de RStudio.


Los 4 paneles de RStudio

Vamos a mirar con un poco más de detalle los 4 paneles de RStudio. Como puedes ver en la imagen de abajo, generalmente, a la izquierda encontramos la consola y el editor de scripts. Ya sabemos que desde estos dos paneles podemos dar instrucciones a R para que las ejecute.

Veamos un poco los 2 paneles de la derecha. Podemos pensar que son paneles auxiliares, nos ayudarán en determinadas tareas. Estos dos paneles de la derecha tienen cada uno varias pestañas. Por ejemplo, el panel que está en la posición arriba-derecha tiene cuatro pestañas: Environment y 3 más3. Enseguida veremos que al interactuar con R iremos creando objetos (por ejemplo un vector o una matriz o una tabla de datos). Estos objetos estarán guardados en la memoria del ordenador pero los “veremos”, aparecerán en la pestaña Environment. En la pestaña History tendremos un listado con las instrucciones de R que hayamos ejecutado previamente en nuestra actual sesión de R (por ejemplo 2 + 2). Otro ejemplo: a veces en nuestro análisis con R haremos un gráfico o varios, podremos ver el gráfico en la pestaña Plots en el panel situado abajo-derecha.

La imagen de arriba es de hace unos años, si te fijas el panel superior-derecha tiene solo 2 pestañas. En 2020 salió la versión 1.3 de RStudio, en la que en el panel superior-derecha, en lugar de haber 2 pestañas, hay 4, una de ellas, llamada “Tutorials”, permite ejecutar tutoriales para aprender R dentro de RStudio.


3. Forma de trabajar con R y RStudio

Ya hemos dejado claro que vamos a usar RStudio para interactuar con R. Ok, pero hay distintas formas de trabajar, o distintos “workflows”.

Cuando hagas un análisis estadístico complejo, por ejemplo para tu TFG, o para el trabajo final de este curso, lo normal es que para realizar el proyecto no sea suficiente con un único script; lo habitual es que cada proyecto necesite de varios inputs (datos, imágenes, scripts etc…). En estos casos, utilizaremos un Rproject para cada proyecto.

Enseguida veremos como podemos crear un Rproject, y explicaremos sus ventajas, pero de momento puedes pensar que un Rproject no es más que una carpeta dedicada en exclusiva a tu proyecto, una carpeta creada para almacenar todo lo relacionado con tu proyecto.

¿Por qué utilizaremos Rprojects? Las razones son varias, pero como casi siempre quien mejor lo explica es Jenny Bryan, por ejemplo aquí.

Voy a intentar resumir yo lo que nos aconseja Jenny:

  • es beneficioso poner todos los archivos (datos, scripts, imágenes, etc…) necesarios para un análisis en una única carpeta dedicada en exclusiva a ese análisis o proyecto.

  • en la carpeta del proyecto es útil utilizar subcarpetas, por ejemplo una carpeta para datos, otra para imágenes, etc…

  • los nombres de los archivos y las carpetas también son importantes. Hay que intentar que los nombres de los archivos sean explicativos de lo que hace o contiene el archivo. Los nombres de los ficheros han de ser legibles por las personas, pero también por las máquinas. Jenny lo explica aquí. Por favor, no dejéis espacios en blanco en los nombres de los ficheros, si queréis separar palabras usad - y/o _. No uséis espacios en blanco!!!

  • una de las características más interesantes de un Rproject es que el directorio de trabajo del proyecto es la propia carpeta del proyecto4. Repito, en un Rproject, el directorio de trabajo es la propia carpeta del Rproject, y así podemos trabajar con rutas o paths relativas, lo que tiene la ventaja de que las rutas relativas funcionarán en cualquier ordenador5.


Trato de explicarlo un poco más: cuando trabajemos en un proyecto, generalmente, tendremos que cargar unos datos. Por ejemplo, imagina que los datos que vas a usar están en el fichero “mis_datos.xlsx”, así que tendrás que decirle a R donde están los datos. Tendrás que darle la ruta o path hasta el archivo de datos. Normal!!

Pero como vamos a trabajar con proyectos, los datos estarán dentro de la carpeta de mi proyecto, quizás en una subcarpeta llamada “datos”. Es posible que la ruta real o absoluta a mis datos sea la siguiente: C:/Users/perezp/my_proyecto/datos/mis_datos.xlsx, pero como trabajamos con proyectos, nuestro directorio de trabajo es la propia carpeta del proyecto, así que solo tendremos que usar una ruta relativa, solo tendremos que poner ./datos/mis_datos.xls.

La ventaja de esto no es solamente que ahorramos tiempo escribiendo los nombres de las rutas, que también, la principal ventaja consiste en que, si por ejemplo, queremos compartir nuestro análisis con un colaborador, le daremos nuestra carpeta con todo el proyecto y los scripts seguirán funcionando en SU ordenador independientemente de donde ponga él la carpeta del proyecto que le hemos dejado.

La razón obviamente es que en nuestro proyecto hemos usado rutas relativas. Las rutas relativas, toman como referencia, empiezan desde el directorio de trabajo, y en un Rproject la carpeta de trabajo es siempre la propia carpeta del proyecto.

Para alguno de vosotros esto os parecerá complicado, pero ya veréis, en clase, que una vez lo entiendes, es muy-muy sencillo. Os habituareis enseguida a usar proyectos y rutas relativas.

Como dice Jenny:

These habits guarantee that the project can be moved around on your computer or onto other computers and will still “just work”.


Para acabar esta sección, señalaré que los nombres de los ficheros son importantes. Para ver algunos consejos sobre como poner nombre a tus archivos puedes ir aquí. No puedo resistirme a citar otra vez a Jennyfer Bryan:



Creando un Rproject

Bien, ya nos has dicho que trabajaremos con Rproject, vale, pero ¿cómo se crea un Rproject?

Simplemente has de abrir RStudio y seguir está ruta de menús: File > New Project... y se abrirá una ventana donde tendrás que seleccionar New Project. Entonces, se abrirá otra ventana y tendrás que seleccionar New Directory. Se abrirá otra ventana con dos cajas de texto, una, la de abajo, estará escrita la ruta donde se va a crear nuestra carpeta o proyecto y la caja de arriba estará vacía y has de poner allí el nombre que quieres que tenga tu proyecto. Como puedes ver en las imágenes de abajo, yo he llamado al proyecto “my_primer_project”.

Una vez hagas todo esto, RStudio creará una carpeta nueva en tu ordenador que será nuestra carpeta para el proyecto. En mi caso la carpeta estará en “C:/Users/perezp/Desktop/my_primer_proyecto”. Es una carpeta normal con un archivo dentro con un icono azulito y que tendrá por nombre “my_primer_proyecto.Rproj”; es un fichero de texto con extensión .Rproj. Ya hablaremos de él. Además de crear una carpeta en nuestro ordenador, RStudio habrá iniciado una nueva sesión de R con nuestro proyecto y verás algo como esto:

Sencillamente tenemos R y RStudio listos para trabajar; es decir, para ejecutar instrucciones en la consola o para crear nuestros scripts. Eso sí, los scripts que creemos ahora, se crearán directamente en la carpeta del proyecto. Ya parlarem mès de cómo interactuar con los Rprojects en clase.

Podemos pensar que un Rproject no es más que una carpeta en nuestro ordenador. De hecho puedes buscar la carpeta de tu proyecto en tu ordenador y manipularla como haces con cualquier carpeta de tu ordenador; es decir, puedes abrirla, moverla, cambiarle el nombre, crear subcarpetas, crear archivos, borrar archivos o borrar toda la carpeta. Insisto, para tu sistema operativo es una carpeta como cualquier otra. De momento esa carpeta solo contiene un archivo de texto con extensión .Rproj, poco a poco la iremos llenando con los archivos de nuestro proyecto (datos, scripts, etc …)

La carpeta del proyecto es una carpeta normal para tu sistema operativo, pero no es una carpeta normal para RStudio. Si vas a la carpeta de tu proyecto y pinchas en el archivo “my_primer_proyecto.Proj” se abrirá RStudio, y RStudio reconocerá esa carpeta como un proyecto; es decir, entre otras cosas fijará el directorio de trabajo a la propia carpeta del proyecto y podremos usar rutas relativas.

Acuérdate siempre de lanzar un proyecto pinchando en el archivo con extensión “.Rproj” !!!! Hay otras formas de lanzar el proyecto pero de momento usaremos esta.

¿Por qué usamos Rprojects?

Gestionar tus análisis utilizando Rprojects tiene ventajas:

  1. puedes gestionar varios proyectos a la vez, cada uno con su espacio de trabajo (ó environment), pero sobre todo,

  2. facilita el compartir tus análisis; es decir, favorece la investigación reproducible.

Podemos pensar que un Rproject es una carpeta, pero es más que eso: cada Rproject tiene su propio directorio de trabajo, espacio de trabajo (environment), historial de instrucciones; además, permite crear una estructura de carpetas donde guardar los documentos asociados al proyecto en carpetas separadas (p.ej: una carpeta para datos, otra para imágenes, …).

Cuando abres un Rproject en RStudio (pinchando en el fichero .Rproj) ocurre lo siguiente:

  • Comienza un nuevo proceso de R (esto también es importante para la investigación reproducible)

  • El directorio de trabajo se fija a la carpeta que contiene el Rproject, con lo que podemos usar rutas relativas (relativas a la carpeta del proyecto)


Cuidado con los paths!!

  • Un gran inconveniente para conseguir informes (plenamente) reproducibles son los paths o rutas de ficheros. Si un programa necesita llamar a un fichero de datos (por ejemplo para cargar unos datos), tendrás que especificar la ruta y si alguien quiere ejecutar tus scripts en su ordenador deberá cambiar la ruta.

  • Trabajar con Rprojects permite solventar este problema, ya que el directorio de trabajo del Rproject coincide con la carpeta donde está alojado el Rproject y esto permite (ya lo veremos en el próximo tutorial) trabajar con rutas (o paths) relativas en lugar de absolutas. (!!)


  • En palabras de Jenny Bryan una de mis heRoínas y destacada miembro de la comunidad R, si empiezas tus scripts con setwd(), significa que estás usando rutas absolutas, puedes hacerlo, pero Jenny nos aconseja que … PLEASE STOP DOING THAT !! Ademas Jenny nos lo explica:

    This makes your script very fragile, hard-wired to exactly one time and place. As soon as you rename or move directories, it breaks. Or maybe you get a new computer? Or maybe someone else needs to run your code?

  • Para Jenny la solución es usar el pkg here, y tiene razón, pero nosotros (de momento) sólo usaremos Rprojects (suficiente!!). 🤔 . Bueno no, eso era en el curso para profesores, a vosotros sí que os veo capacitados para aprender como usar here::here(). 👿 🤣 . Lo veremos. El que tenga curiosidad puede leer en este post porqué, a pesar de trabajar con Rprojects, tiene ventajas especificar las rutas con el paquete here.


4. RMarkdown (archivos .Rmd)

Sí, ya sabemos que trabajaremos con Rprojects. OK, pero también dije que muchas veces en lugar de dar las instrucciones a R por medio de scripts o ficheros .R, trabajaríamos con ficheros Rmarkdown. Estos ficheros Rmarkdown tienen extensión .Rmd.

  • Los documentos RMarkdown son ficheros con extensión .Rmd.

  • Si acabas utilizando R para hacer análisis estadísticos, los ficheros .Rmd te permitirán escribir muy-muy fácilmente informes, tutoriales y transparencias para presentaciones.

  • Estos ficheros .Rmd son (plenamente) reproducibles.

  • Lo veremos, pero en esos ficheros .Rmd se mezclan trozos de texto escritos en Markdown (narratives) y trozos con código R (chunks) para hacer análisis estadísticos.

  • Estos ficheros se procesan con un paquete de R llamado knitr desarrollado por Yihui Xie … y salen unos informes o transparencias fantásticas … en una gran variedad de formatos.

  • Con RStudio es muy fácil: solo hay que usar los menús desplegables de RStudio para crear un documento Rmarkdown, escribir lo que quieres contar y darle al botón Knitr y knitr tejerá el documento y lo transformará a …. pdf, word, html …


Tardaremos unas 3-4 clases en explicar en detalle qué son y para que sirven los ficheros Rmarkdown, pero vamos ya a crear uno. Para ello tienes que seguir en RStudio esta ruta de menús: File > New File > R Markdown.... Visualmente:

Se abrirá una ventana. De momento no cambies nada, sólo pincha en OK.

Verás que se ha abierto una pestaña en el editor de RStudio (arriba-izquierda), con lo que parece que son muchas lineas de código R. Sí, ha creado para nosotros un archivo .Rmd y ha puesto unas lineas de código que nos sirven como ejemplo de cómo se escribe en Rmarkdown. Ya lo veremos. Visualmente:

Estos ficheros .Rmd se ejecutan de otra forma. Tienes que pinchar en el icono que pone Knit. Visualmente:

Aparecerá una ventana pidiéndote que le pongas un nombre al fichero .Rmd. Como puedes ver abajo yo le puse el nombre “para_borrar”, pero puedes poner el nombre que quieras.

Una vez le hayas puesto nombre. R ejecutará todas las instrucciones que hay en el fichero .Rmd y generará un nuevo documento que podrás ver en el panel de abajo-derecha. Además si pinchas en el icono que aparece marcado con una mano( panel abajo-derecha) en la imagen de abajo podrás verlo en tu navegador. Visualmente:

Durante el curso vamos a trabajar mucho con ficheros .Rmd, así que tendremos que explicarlos/entenderlos bien. Pero será otro día/lesson. Si os apetece podéis ver este video donde se explica las ventajas de trabajar en con ficheros Rmarkdow. Igual mañana lo pregunto.



Para finalizar un consejo: estamos empezando, así que PATIENCE!!! cuesta un poco aprender/empezar con R. Además todo el mundo comete errores, pero la mayoría de los errores son “tontos”. Eso sí, tenéis que entender las ideas básicas: script, .R, .Rmd, Rproject, rutas relativas etc… si no lo entiendes, no lo dejes pasar, pregúntalo en clase, seguro que más de uno te lo agradece o podemos arreglarlo en tutorías, pero no lo dejes pasar.




  1. Aquí tienes un artículo con la historia de R↩︎

  2. Siempre que esa carpeta no esté muy abajo en la lista de directorios para que la ruta hacía ese directorio no sea demasiado larga para Windows↩︎

  3. Igual en vuestro ordenador tenéis más (o menos) pestañas, eso dependerá de la versión de RStudio que tengáis instalada. Yo ahora mismo tengo cuatro, pero igual la próxima versión de Rstudio puede tener 5 pestañas↩︎

  4. Sí, sé que si parece un trabalenguas, pero es muy importante que esto lo acabes entendiendo. Cuando lo entiendas, y seguro que lo haces pronto, verás que en realidad es muy fácil.↩︎

  5. Esto lo conseguiremos trabajando con Rprojects y con el paquete here. Lo veremos pronto↩︎

LS0tCnRpdGxlOiAiUiwgUlN0dWRpbyB5IGZvcm1hIGRlIHRyYWJhamFyIgphdXRob3I6ICJQZWRybyBKLiBQw6lyZXogKHBlZHJvLmoucGVyZXpAdXYuZXMpLiBVbml2ZXJzaXRhdCBkZSBWYWzDqG5jaWEgPGJyPiA8YnI+IFdlYiBkZWwgY3Vyc286IDxodHRwczovL3BlcmV6cDQ0LmdpdGh1Yi5pby9pbnRyby1kcy0yMy0yNC13ZWIvPiIKZGF0ZTogIlNlcHRpZW1icmUgZGUgMjAxOSAoYWN0dWFsaXphZG8gZWwgYHIgZm9ybWF0KFN5cy50aW1lKCksICclZC0lbS0lWScpYCkiCm91dHB1dDoKICBodG1sX2RvY3VtZW50OgogICAgY3NzOiAhZXhwciBoZXJlOjpoZXJlKCJhc3NldHMiLCAic3R5bGVzX3BqcC5jc3MiKQogICAgdGhlbWU6IHBhcGVyCiAgICBoaWdobGlnaHQ6IHRleHRtYXRlIAogICAgdG9jOiB0cnVlCiAgICB0b2NfZGVwdGg6IDMgCiAgICB0b2NfZmxvYXQ6IAogICAgICBjb2xsYXBzZWQ6IHRydWUKICAgICAgc21vb3RoX3Njcm9sbDogdHJ1ZQogICAgc2VsZl9jb250YWluZWQ6IHRydWUKICAgIG51bWJlcl9zZWN0aW9uczogZmFsc2UKICAgIGluY2x1ZGVzOgogICAgICBhZnRlcl9ib2R5OiAhZXhwciBoZXJlOjpoZXJlKCJhc3NldHMiLCAiZm9vdGVyLmh0bWwiKSAKICAgICAgaW5faGVhZGVyOiAKICAgICAgICAtICFleHByIGhlcmU6OmhlcmUoImFzc2V0cyIsICJnb29nbGUtYW5hbHl0aWNzLmh0bWwiKSAKICAgICAgICAtICFleHByIGhlcmU6OmhlcmUoImFzc2V0cyIsICJmYXZpY29uLXNvbC5odG1sIikgICAgCiAgICBkZl9wcmludDoga2FibGUKICAgIGNvZGVfZG93bmxvYWQ6IHRydWUKZWRpdG9yX29wdGlvbnM6IAogIGNodW5rX291dHB1dF90eXBlOiBjb25zb2xlCi0tLQoKYGBge3IsIGluY2x1ZGUgPSBGQUxTRX0KbGlicmFyeSh0aWR5dmVyc2UpCmBgYAoKYGBge3IgY2h1bmstc2V0dXAsIGluY2x1ZGUgPSBGQUxTRX0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KGVjaG8gPSBUUlVFLCBldmFsID0gVFJVRSwgbWVzc2FnZSA9IEZBTFNFLCB3YXJuaW5nID0gRkFMU0UsIAogICAgICAgICAgICAgICAgICAgICAgI3Jlc3VsdHMgPSAiaG9sZCIsCiAgICAgICAgICAgICAgICAgICAgICBjYWNoZSA9IEZBTFNFLCBjYWNoZS5wYXRoID0gIi9jYWNoZXMvIiwgY29tbWVudCA9ICIjPiIsCiAgICAgICAgICAgICAgICAgICAgICAjZmlnLndpZHRoID0gNywgI2ZpZy5oZWlnaHQ9IDcsICAgCiAgICAgICAgICAgICAgICAgICAgICAjb3V0LndpZHRoID0gNywgb3V0LmhlaWdodCA9IDcsCiAgICAgICAgICAgICAgICAgICAgICBjb2xsYXBzZSA9IFRSVUUsICBmaWcuc2hvdyA9ICJob2xkIiwKICAgICAgICAgICAgICAgICAgICAgIGZpZy5hc3AgPSA3LzksIG91dC53aWR0aCA9ICI2MCUiLCBmaWcuYWxpZ24gPSAiY2VudGVyIikKCiMtIHBhcmEgbWVqb3JhciBsb3MgZ3LDoWZpY29zLCBidWVubyBlbiByZWFsaWRhZCBwYXJhIHF1ZSBzZSB2ZWFuIGlndWFsIGVuIGRpc3RpbnRvcyBTTwojLSBodHRwczovL3d3dy5qdW1waW5ncml2ZXJzLmNvbS9ibG9nL3Ita25pdHItbWFya2Rvd24tcG5nLXBkZi1ncmFwaGljcy8Ka25pdHI6Om9wdHNfY2h1bmskc2V0KGRldiA9ICJwbmciLCBkZXYuYXJncyA9IGxpc3QodHlwZSA9ICJjYWlyby1wbmciKSkKYGBgCgpgYGB7ciBvcHRpb25zLXNldHVwLCBpbmNsdWRlID0gRkFMU0V9Cm9wdGlvbnMoc2NpcGVuID0gOTk5KSAjLSBwYXJhIHF1aXRhciBsYSBub3RhY2nDs24gY2llbnTDrWZpY2EKb3B0aW9ucygieWFtbC5ldmFsLmV4cHIiID0gVFJVRSkgIy0gaHR0cHM6Ly9naXRodWIuY29tL3Zpa2luZy9yLXlhbWwvaXNzdWVzLzQ3ICAobG8gcHVzZSB4IGVsIHBiIGNvbiBlbCB3YXJuaW5nKSBFbiByZWFsaWRhZCBjcmVvIHF1ZSBtZWpvciBzZXLDrWEgcG9uZXJsbyBlbiBSUHJvZmlsZQpgYGAKCmBgYHtyIGtsaXBweSwgZWNobyA9IEZBTFNFfQprbGlwcHk6OmtsaXBweShwb3NpdGlvbiA9IGMoInRvcCIsICJyaWdodCIpKSAjLSByZW1vdGVzOjppbnN0YWxsX2dpdGh1Yigicmxlc3VyL2tsaXBweSIpCmBgYAoKCi0tLS0tLS0tLS0tLS0tLS0tCgo8YnI+CgpFbCBvYmpldGl2byBkZSBlc3RhIHNlY2Npw7NuIGVzIHByb3BvcmNpb25hciB1bmEgYnJldmUgcHJpbWVyYSBpbnRyb2R1Y2Npw7NuIGEgUiB5IFJTdHVkaW8gcGFyYSBwZXJzb25hcyBxdWUgbm8gaGFuIHRlbmlkbyBjb250YWN0byBwcmV2aW8gY29uIGVzdG9zIHByb2dyYW1hcyB5IGV4cGxpY2l0YXIgbGEgZm9ybWEgcXVlIHRlbmRyZW1vcyBkZSBpbnRlcmFjdHVhciBjb24gZWxsb3M7IGVzIGRlY2lyLCBsYSBmb3JtYSBkZSB0cmFiYWphciBjb24gZWxsb3MgKCoqd29ya2Zsb3cqKikuCgpFbCBjdXJzbyBlcyB1bmEgaW50cm9kdWNjacOzbiBhIGxhIENpZW5jaWEgZGUgRGF0b3M6IGhhcmVtb3MgZGl2ZXJzb3MgYW7DoWxpc2lzIGNvbiBkYXRvcyB5IHBhcmEgZWxsbyB1dGlsaXphcmVtb3MgUi4gUiBzZXLDoSBlbCBwcm9ncmFtYSBxdWUgaGFyw6EgbG9zIGPDoWxjdWxvcywgZ3LDoWZpY29zLCBpbmZvcm1lcywgcGVybyBpbnRlcmFjdHVhcmVtb3MgY29uIFIsIGxlIGRhcmVtb3MgbGFzIG9yZGVuZXMgYSBSLCBhIHRyYXbDqXMgZGUgb3RybyBwcm9ncmFtYTogUlN0dWRpby4gQXPDrSBxdWUgdGVuZHJlbW9zIHF1ZSBpbnN0YWxhciBsb3MgMiBwcm9ncmFtYXMuIFBvciBlbGxvLCBlbiBsYSBbd2ViIGRlbCBjdXJzb10oaHR0cHM6Ly9wZXJlenA0NC5naXRodWIuaW8vaW50cm8tZHMtMjItMjMtd2ViLykgdGllbmVzIHVuIGZpY2hlcm8gZG9uZGUgc2UgZXhwbGljYSBjb21vIGhhY2VybG86IGNvbmNyZXRhbWVudGUgW2FxdcOtXShodHRwczovL3BlcmV6cDQ0LmdpdGh1Yi5pby9pbnRyby1kcy0yMi0yMy13ZWIvbWFzLXJlY3Vyc29zLzAxX2luc3RydWNjaW9uZXMtaW5zdGFsYWNpb24uaHRtbCkuCgpbQXF1w61dKGh0dHBzOi8vd3d3LmRhdGFxdWVzdC5pby9ibG9nL3R1dG9yaWFsLWdldHRpbmctc3RhcnRlZC13aXRoLXItYW5kLXJzdHVkaW8vKSB0aWVuZXMgdW4gYXJ0aWN1bG8gcXVlIGV4cGxpY2EsIGNvbiBtdWNobyBkZXRhbGxlLCBjb21vIGVtcGV6YXIgYSB0cmFiYWphciBjb24gUjogaW5zdGFsYWNpw7NuLCBjb25maWd1cmFjacOzbiwgcGFxdWV0ZXMsIGV0Yy4uLgoKPGJyPgoKU2UgcHVlZGUgdHJhYmFqYXIgY29uIFIvUlN0dWRpbyBkZSB2YXJpYXMgZm9ybWFzLiBOb3NvdHJvcyB0cmFiYWphcmVtb3MsIGNhc2kgc2llbXByZSwgY29uIGBScHJvamVjdHNgLiBFbnNlZ3VpZGEgZGlyZW1vcyBxdcOpIHNvbiBsb3MgUnByb2plY3RzLCBwZXJvIGRlIG1vbWVudG8gcG9kZW1vcyBwZW5zYXIgcXVlIHNvbiBjYXJwZXRhcyBkb25kZSBzZSBhbG1hY2VuYW4gbG9zIGZpY2hlcm9zIG5lY2VzYXJpb3MgcGFyYSBoYWNlciB1biBhbsOhbGlzaXMgZGUgZGF0b3MuCgoKRGVudHJvIGRlIGVzYXMgY2FycGV0YXMgbyBgUnByb2plY3RzYCB0ZW5kcmVtb3MgZGlzdGludG9zIHRpcG9zIGRlIGZpY2hlcm9zOiBmaWNoZXJvcyBkZSBkYXRvcywgaW3DoWdlbmVzIGV0Yy4uLiB5IHVub3MgZmljaGVyb3MsIGxsYW1hZG9zIGhhYml0dWFsbWVudGUgKipzY3JpcHRzKiogcXVlIGNvbnRlbmRyw6FuICBsYXMgaW5zdHJ1Y2Npb25lcyBxdWUgcXVlcmFtb3MgcXVlIHNlYW4gZWplY3V0YWRhcyBwb3IgUi9SU3R1ZGlvLiBCaWVuLCBwdWVzIGVzb3Mgc2NyaXB0cyBvIGZpY2hlcm9zIGRlIG9yZGVuZXMgcHVlZGVuIHNlciBkZSB2YXJpb3MgdGlwb3MuIENvbmNyZXRhbWVudGUsIGR1cmFudGUgZWwgY3Vyc28gdXRpbGl6YXJlbW9zIDIgdGlwb3MgZGUgZmljaGVyb3MgcGFyYSBkYXJsZSBsYXMgb3JkZW5lcyBhIFI6ICAgCgogIC0gYGZpY2hlcm9zIC5SYCAsIHkgICAgCiAgICAKICAtIGBmaWNoZXJvcyBSbWFya2Rvd25gIG8gYGZpY2hlcm9zIC5SbWRgLiAKICAgICAgCiAgICAgIApMbyBub3JtYWwgZXMgcXVlIG51bmNhIGhheWFzIG/DrWRvIGhhYmxhciBkZSB0b2RvIGVzdG8sIGFzw60gcXVlIGFsIHByaW5jaXBpbyB0ZSBzb25hcsOhIGNvbXBsaWNhZG8sIHBlcm8gZW4gbmFkYSB0ZSBwYXJlY2Vyw6EgbG8gbcOhcyBuYXR1cmFsIGRlbCBtdW5kby4gQmlyZCBieSBiaXJkISEhCgoKCiMjIDEuIFIKCllhIGhlbW9zIGhhYmxhZG8gZGUgUiwgcGVybyAuLi4KCiMjIyDCv1F1w6kgZXMgUj8KCllhIGxvIGhhYsOpaXMgdmlzdG8gbWllbnRyYXMgaGFjw61hbW9zIGFsZ8O6biBlamVtcGxvLCBwZXJvIHBhcmEgbG9zIG51ZXZvczogUiBlcyB1biBsZW5ndWFqZSBkZSBwcm9ncmFtYWNpw7NuIHkgdW4gZW50b3JubyBwYXJhIGVsIGFuw6FsaXNpcyBlc3RhZMOtc3RpY28geSBncsOhZmljby4gU2UgcHVlZGUgdXRpbGl6YXIgcGFyYSBtdWNoYXMgY29zYXMgeWEgcXVlIGVzIHVuIGxlbmd1YWplIGRlIHByb2dyYW1hY2nDs24sIHBlcm8gcHJpbmNpcGFsbWVudGUgc2UgdXRpbGl6YSBlbiBlbCBjYW1wbyBkZSBsYSBlc3RhZMOtc3RpY2EgeSBsYSBjaWVuY2lhIGRlIGRhdG9zOyBkZSBoZWNobywgUiBmdWUgaW5pY2lhbG1lbnRlIGNyZWFkbyBlbiAxOTkzIHBvciBkb3MgZXN0YWTDrXN0aWNvcyBkZSBsYSBVbml2ZXJzaWRhZCBkZSBBdWNrbGFuZDogUi4gSWhha2EgeSBSLkdlbnRsZW1hbl5bW0FxdcOtXShodHRwczovL2RsLmFjbS5vcmcvZG9pL2Ficy8xMC4xMTQ1LzMzODYzMzQpIHRpZW5lcyB1biBhcnTDrWN1bG8gY29uIGxhIGhpc3RvcmlhIGRlIFJdLiBBIHBhcnRpciBkZSAxOTk3IGVsIGRlc2Fycm9sbG8gZGUgUiAobyAqKmJhc2UtUioqKSBlcyBnZXN0aW9uYWRvIHBvciB1biBncnVwbyBkZSBwcm9ncmFtYWRvcmVzIGNvbm9jaWRvIGNvbW8gIlRoZSBSLWNvcmUgdGVhbSI7IHBlcm8gYWN0dWFsbWVudGUsIGVsIGVudG9ybm8gbyBlY29zaXN0ZW1hIFIgZXMgZWwgcmVzdWx0YWRvIGRlIGxhIGNvbGFib3JhY2nDs24gZGUgdG9kYSB1bmEgY29tdW5pZGFkIGRlIHVzdWFyaW9zIHF1ZSBleHRpZW5kZSBsYXMgdXRpbGlkYWRlcyBkZSBiYXNlLVIgbWVkaWFudGUgbGEgY3JlYWNpw7NuIGRlIG51ZXZvcyBwYXF1ZXRlcyB5IGZ1bmNpb25lcy4KClIgZm9ybWEgcGFydGUgZGVsIHNpc3RlbWEgW0dOVV0oaHR0cHM6Ly9lcy53aWtpcGVkaWEub3JnL3dpa2kvR05VKSB5IHNlIGRpc3RyaWJ1eWUgYmFqbyBsYSBsaWNlbmNpYSBbR05VIEdQTF0oaHR0cHM6Ly9lcy53aWtpcGVkaWEub3JnL3dpa2kvR05VX0dlbmVyYWxfUHVibGljX0xpY2Vuc2UpIHBvciBsbyBxdWUgbG9zIHVzdWFyaW9zIHRlbmVtb3MgbGEgbGliZXJ0YWQgZGUgdXNhciwgZXN0dWRpYXIsIGNvbXBhcnRpciAoY29waWFyKSB5IG1vZGlmaWNhciBlbCBzb2Z0d2FyZTsgZXMgZGVjaXIsIFIgZXMgWyoqc29mdHdhcmUgbGlicmUqKl0oaHR0cHM6Ly93d3cuZ251Lm9yZy9waGlsb3NvcGh5L2ZyZWUtc3cuZXMuaHRtbCkuIEFkZW3DoXMgZGUgc29mdHdhcmUgbGlicmUsIFIgZXMgZ3JhdHVpdG8geSBtdWx0aXBsYXRhZm9ybWE6IGVzdMOhIGRpc3BvbmlibGUgcGFyYSBXaW5kb3dzLCBNYWNpbnRvc2ggeSBHTlUvTGludXguICAKCgoKTGEgcMOhZ2luYSB3ZWIgb2ZpY2lhbCBkZSBSIHNlIGxsYW1hOiBbVGhlIFIgUHJvamVjdCBmb3IgU3RhdGlzdGljYWwgQ29tcHV0aW5nXShodHRwczovL3d3dy5yLXByb2plY3Qub3JnLykuIEFsbMOtIHBvZHLDoXMgZW5jb250cmFyIHRvZGEgbGEgaW5mb3JtYWNpw7NuIHkgZG9jdW1lbnRhY2nDs24gb2ZpY2lhbCBhY2VyY2EgZGUgUi4gQXVucXVlIHNpIGFsZ3VuYSB2ZXogbGEgbmVjZXNpdGFzLCBzZSBwdWVkZSBjb25zdWx0YXIgZGVzZGUgUiBjb24gbGEgZnVuY2nDs24gYGhlbHAuc3RhcnQoKWAgbywgZW4gdW4gZm9ybWF0byB2aXN1YWxtZW50ZSBtw6FzIGFncmFkYWJsZSwgZW4gW2VzdGUgcmVwb3NpdG9yaW9dKGh0dHBzOi8vY29saW5mYXkubWUvci1tYW51YWxzLykgZGUgQ29sbGluIEZheSB1biBkZXN0YWNhZG8gbWllbWJybyBkZSBsYSBhY3R1YWwgY29tdW5pZGFkIFIuIFNpIHF1aWVyZXMgdmVyIGxhcyBwZXJzb25hcyBxdWUgZm9ybWFuIHBhcnRlIGRlbCBSIGNvcmUtdGVhbSBvIHF1ZSBoYW4gY29udHJpYnVpZG8gYWwgZGVzYXJyb2xsbyBkZSBSIG5vIHRpZW5lcyBtYXMgcXVlIHRlY2xlYXIgZW4gUiBgY29udHJpYnV0b3JzKClgLgoKClIgcHJvcG9yY2lvbmEgdW4gYW1wbGlvIGFiYW5pY28gZGUgaGVycmFtaWVudGFzIGVzdGFkw61zdGljYXMgeSBncsOhZmljYXMgKG1vZGVsb3MgbGluZWFsZXMgeSBubyBsaW5lYWxlcywgdGVzdHMgZXN0YWTDrXN0aWNvcywgYW7DoWxpc2lzIGRlIHNlcmllcyB0ZW1wb3JhbGVzLCBhbGdvcml0bW9zIGRlIGNsYXNpZmljYWNpw7NuIHkgYWdydXBhbWllbnRvLCBldGMuKS4gQ29tbyBSIHRhbWJpw6luIGVzIHVuIGxlbmd1YWplIGRlIHByb2dyYW1hY2nDs24sIHBlcm1pdGUgcXVlIGxvcyB1c3VhcmlvcyBsbyBleHRpZW5kYW4gZGVmaW5pZW5kbyBzdXMgcHJvcGlhcyBmdW5jaW9uZXMgeSBwYXF1ZXRlcy4gRGUgaGVjaG8sIGFjdHVhbG1lbnRlIFIgc2UgaGEgY29udmVydGlkbyBkZSB1biBwcm95ZWN0byBjb2xhYm9yYXRpdm8geSBhYmllcnRvIGVuIGVsIHF1ZSBzdXMgdXN1YXJpb3MgcHVlZGVuIHB1YmxpY2FyIHBhcXVldGVzIHF1ZSBleHRpZW5kZW4gc3UgY29uZmlndXJhY2nDs24gYsOhc2ljYS4gUGFyYSBkYXJ0ZSB1bmEgaWRlYSBkZSBsbyBwcm9sw61maWNhIHkgY29sYWJvcmF0aXZhIHF1ZSBlcyBsYSBjb211bmlkYWQgUiBwdWVkZXMgdmlzaXRhciBlc3RvcyAyIHByb3llY3RvczogW1ItYmxvZ2dlcnNdKGh0dHBzOi8vd3d3LnItYmxvZ2dlcnMuY29tLykgeSBbUi1XZWVrbHldKGh0dHBzOi8vcndlZWtseS5vcmcvKS4gUHJlY2lzYW1lbnRlIGVzdG9zIDIgYXNwZWN0b3MgKGFidW5kYW5jaWEgZGUgcGFxdWV0ZXMgeSBjb211bmlkYWQgZGUgdXN1YXJpb3MpIHNvbiBjbGF2ZXMgZW4gZWwgw6l4aXRvIGRlIFIKCgpZYSBoZW1vcyBkaWNobyBxdWUgUiAoanVudG8gY29uIHN1cyBwYXF1ZXRlcykgcHVlZGUgaW1wbGVtZW50YXIgdW5hIGdyYW4gdmFyaWVkYWQgZGUgdMOpY25pY2FzIGVzdGFkw61zdGljYXMgeSBncsOhZmljYXMuIEV4aXN0ZSB1biByZXBvc2l0b3JpbyBvZmljaWFsIGRlIHBhcXVldGVzOiBDb21wcmVoZW5zaXZlIFIgQXJjaGl2ZSBOZXR3b3JrIG8gW0NSQU5dKGh0dHBzOi8vY3Jhbi5yLXByb2plY3Qub3JnLykuIENSQU4gYWxjYW56w7MgbG9zIFsxMC4wMDAgcGFxdWV0ZXNdKGh0dHBzOi8vYmxvZy5yZXZvbHV0aW9uYW5hbHl0aWNzLmNvbS8yMDE3LzAxL2NyYW4tMTAwMDAuaHRtbCkgZW4gZW5lcm8gZGUgMjAxNywgeSBhY3R1YWxtZW50ZSwganVsaW8gZGUgMjAxOSwgdGllbmUgMTQuNTUzIHBhcXVldGVzLiBBZGVtw6FzLCBleGlzdGVuIG11Y2hvcyBtw6FzIHBhcXVldGVzIGVuIHJlcG9zaXRvcmlvcyBjb21vIFtCaW9jb25kdWN0b3JdKGh0dHBzOi8vd3d3LmJpb2NvbmR1Y3Rvci5vcmcvKSwgW0dpdGh1Yl0oaHR0cHM6Ly9naXRodWIuY29tLykgeSBvdHJvcy4KCjxicj4KCiMjIyBJbnN0YWxhY2nDs24gZGUgUiAKCk9idmlhbWVudGUsIHBhcmEgdXNhciBSIHkgc3VzIHBhcXVldGVzIHRlbmVtb3MgcXVlIGluc3RhbGFybG8gcHJpbWVyby4gUGFyYSBlbGxvICJzb2xvIiB0aWVuZXMgcXVlIGlyIGEgW0NSQU5dKGh0dHBzOi8vY3Jhbi5yLXByb2plY3Qub3JnLykgeSBkZXNjYXJnYXIgbGEgZGlzdHJpYnVjacOzbiBkZSBSIGFkZWN1YWRhIHBhcmEgdHUgc2lzdGVtYSBvcGVyYXRpdm8uIE9idmlhbWVudGUgbWVqb3IgbGEgw7psdGltYSB2ZXJzacOzbi4gRW4gZWwgbW9tZW50byBkZSByZS1lc2NyaWJpciBlc3RhcyBub3RhcyBsYSDDumx0aW1hIHZlcnNpw7NuIGVzIGBSLTQuMS4xYCBsbGFtYWRhICAiS2ljayBUaGluZ3MiIHJlbGVhc2VkIG9uIDIwMjEvMDgvMTAuIAoKTm8gdGUgdmEgYSBhIGhhY2VyIGZhbHRhIHBlcm8gcG9yIHNpIGFjYXNvLCBbYXF1w61dKGh0dHBzOi8vamphbGxhaXJlLnNoaW55YXBwcy5pby9sZWFybnItdHV0b3JpYWwtMDAtc2V0dXAvI3NlY3Rpb24taW5zdGFsbC1yKSB0aWVuZXMgdW4gdsOtZGVvIGRlIDE6MzAgZG9uZGUgc2UgZXhwbGljYSBkZSBtYW5lcmEgc2VuY2lsbGEgY29tbyBpbnN0YWxhciBSLgoKCgojIyAyLiBSU3R1ZGlvIAoKIyMjIMK/UXXDqSBlcyBSU3R1ZGlvPwoKUHVlcyBlcyB1biBwcm9ncmFtYSBxdWUgdXRpbGl6YXJlbW9zIHBhcmEgaW50ZXJhY3R1YXIgY29uIFIuIExhcyBpbnN0cnVjY2lvbmVzIHF1ZSBxdWVyYW1vcyBkYXIgYSBSIHBhcmEgcXVlIGxhcyBlamVjdXRlIHNlIGxhcyBkYXJlbW9zIGEgdHJhdsOpcyBkZSBSU3R1ZGlvLiBMYSByYXrDs24gZXMgcXVlIGxhIGludGVyZmF6IGRlIHVzdWFyaW8gKEdVSSwgR3JhcGhpY2FsIFVzZXIgSW50ZXJmYWNlKSBkZSBSIG5vIGVzIG11eSBhbWlnYWJsZSBuaSB2ZXJzw6F0aWwsIGFzw60gcXVlIGludGVyYWN0dWFyZW1vcyBjb24gUiBhIHRyYXbDqXMgZGUgUlN0dWRpby4gIAoKUlN0dWRpbyBlcyB1biBwcm9ncmFtYSBxdWUgbm9zIHBlcm1pdGlyw6EgaW50ZXJhY3R1YXIgY29uIFIgZGUgZm9ybWEgbcOhcyBhbWlnYWJsZSwgYWRlbcOhcyBkZSBmYWNpbGl0YXIgbXVjaGFzIGRlIGxhcyB0YXJlYXMgZGUgcHJvZ3JhbWFjacOzbiB5IGFuw6FsaXNpcyBkZSBkYXRvcyBlbiBSOyBlcyBkZWNpciwgUlN0dWRpbyBlcyB1bmEgR1VJIChHcmFwaGljYWwgVXNlciBJbnRlcmZhY2UpLiBFbiByZWFsaWRhZCwgUlN0dWRpbyBlcyBtw6FzIHF1ZSB1bmEgR1VJLCBlcyB1bmEgSURFLCB1biBlbnRvcm5vIGRlIGRlc2Fycm9sbG8gaW50ZWdyYWRvIHBhcmEgUiwgZW4gaW5nbMOpcyAgKidpbnRlZ3JhdGVkIGRldmVsb3BtZW50IGVudmlyb25tZW50JyogbyAqKklERSoqLiAgIAoKRWwgYWN0dWFsIGNpZW50w61maWNvIGplZmUgZGUgUlN0dWRpbyBlcyBbSGFkbGV5IFdpY2toYW1dKGh0dHA6Ly9oYWRsZXkubnovKS4gV2lja2hhbSBlcyB1bm8gZGUgbG9zIG3DoXMgcHJvbMOtZmljb3MgZGVzYXJyb2xsYWRvciBkZSBwYXF1ZXRlcyBwYXJhIFIgeSBjcmVhZG9yIGRlIHVuIG51ZXZvIGVzdGlsbyBkZSBwcm9ncmFtYXIgeSBhbmFsaXphciBkYXRvcyBlbiBSIGNvbm9jaWRvIGNvbW8gKidbdGlkeXZlcnNlXShodHRwczovL2Jsb2cucnN0dWRpby5vcmcvMjAxNi8wOS8xNS90aWR5dmVyc2UtMS0wLTAvKScqLiBNdWNob3MgZGUgbG9zIHBhY2thZ2VzIHF1ZSB1dGlsaXphcmVtb3MgZW4gZWwgY3Vyc28gaGFuIHNpZG8gZGVzYXJyb2xsYWRvcyBwb3Igw6lsIHkgZWwgZXF1aXBvIGRlIFJTdHVkaW8uIAoKPGJyPgoKIyMjIEluc3RhbGFjacOzbiBkZSBSU3R1ZGlvCgpMYSB2ZXJzacOzbiBkZSBlc2NyaXRvcmlvIGRlIFJTdHVkaW8gdGFtYmnDqW4gZXMgbGlicmUgeSBncmF0dWl0YS4gU2UgcHVlZGUgZGVzY2FyZ2FyIFthcXXDrV0oaHR0cHM6Ly93d3cucnN0dWRpby5jb20vcHJvZHVjdHMvcnN0dWRpby9kb3dubG9hZC8pLiBUaWVuZXMgcXVlIGRlc2NhcmdhcnRlIGVsIConaW5zdGFsbGVyJyogYWRlY3VhZG8gcGFyYSB0dSBzaXN0ZW1hIG9wZXJhdGl2by4gCgpTZSBwdWVkZSB0cmFiYWphciBwZXJmZWN0YW1lbnRlIGNvbiBsYXMgb3BjaW9uZXMgcG9yIGRlZmVjdG8gZGUgUlN0dWRpbywgcGVybyBvcyByZWNvbWllbmRvIGNhbWJpYXIgYWxndW5hcyBvcGNpb25lcywgYXPDrSBxdWUgdmFtb3MgYSBjb25maWd1cmFyIFJTdHVkaW8uCgojIyMgQ29uZmlndXJhbmRvIFJTdHVkaW8KCkVzdMOhIHNlY2Npw7NuIG5vIGVzIG9ibGlnYXRvcmlhLCBzb2xvIHF1ZSBlcyByZWNvbWVuZGFibGUgY29uZmlndXJhciBsYXMgb3BjaW9uZXMgZGUgUlN0dWRpby4gwr9Dw7Ntbz8gRW4gUlN0dWRpbywgc2lndWUgZXN0w6EgcnV0YSBkZSBtZW7DunM6IGBUb29scyA+IEdsb2JhbCBPUHRpb25zLi4uYCAKCgpgYGB7ciwgZWNobyA9IEZBTFNFLCBvdXQud2lkdGggPSAiNzUlIn0Ka25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoaGVyZTo6aGVyZSgiaW1hZ2VuZXMiLCAidHRfMDJfaW1nXzA2X1JTdHVkaW8tb3BjaW9uZXMucG5nIikgKSAKYGBgCgoKU2UgYWJyaXLDoSB1bmEgdmVudGFuYSAocXVlIHB1ZWRlcyB2ZXIgYWJham8pIGNvbiBsYXMgb3BjaW9uZXMgZGUgY29uZmlndXJhY2nDs24gZGUgUlN0dWRpby4gRGUgbW9tZW50byB2YW1vcyBzw7NsbyBhIHRvY2FyIGxhIGNhdGVnb3LDrWEgcXVlIHZlcyBlbiBsYSBpbWFnZW47IGVzIGRlY2lyLCBgUiBHZW5lcmFsYC4gVGllbmVzIHF1ZSBoYWNlciBkb3MgY29zYXM6CgogIDEuIGRlc21hcmNhciB0b2RhcyBsYXMgY2FzaWxsYXMgKHF1aXRhcmxlcyBsb3MgdGlja3MpIAogIAogIDIuIEVzIGltcG9ydGFudGUsIHBvbmVyIGBOZXZlcmAgZW4gbGEgY2FzaWxsYSBkb25kZSBwb25lICJTYXZlIHdvcmtzcGFjZSB0byAuUkRhdGEgb24gZXhpdCIuIAogIApBbCBmaW5hbCwgZW4gbWkgb3JkZW5hZG9yLCBsYSB2ZW50YW5hIGNvbiBsYXMgb3BjaW9uZXMgZGUgYFIgR2VuZXJhbGAgcXVlZGEgY29tbzogCgoKYGBge3IsIGVjaG8gPSBGQUxTRSwgb3V0LndpZHRoID0gIjY1JSJ9CmtuaXRyOjppbmNsdWRlX2dyYXBoaWNzKGhlcmU6OmhlcmUoImltYWdlbmVzIiwgInR0XzAyX2ltZ18wN19SU3R1ZGlvLW9wY2lvbmVzLTIucG5nIikgKSAKYGBgCgpFbiB0dSBvcmRlbmFkb3IgZGViZSBxdWVkYXIgdG9kbyBpZ3VhbCBleGNlcHRvIGxhIGNhamEgZGUgdGV4dG8uIEVsIHRleHRvIGRlIGxhIGNhamEgbGUgZGljZSBhIFJTdHVkaW8gZG9uZGUgc2UgZ3VhcmRhcsOhbiBsb3MgYXJjaGl2b3MgcXVlIHZheWFtb3MgZ2VuZXJhbmRvOyBlcyBkZWNpciwgaW5kaWNhIGVsIGRpcmVjdG9yaW8gZGUgdHJhYmFqbyBwb3IgZGVmZWN0by4gIENvbW8gbWkgc2lzdGVtYSBvcGVyYWl2byBlcyBMaW51eCB5IGhhYml0dWFsbWVudGUgdHJhYmFqbyBlbiBlbCBlc2NyaXRvcmlvIGRlIG1pIFBDLCBlbiBsYSBpbWFnZW4gZGUgYWJham8gcG9uZSAifi9Fc2NyaXRvcmlvIiwgc2kgbWkgc2lzdGVtYSBvcGVyYXRpdm8gZnVlc2UgV2luZG93cyBwb25kcsOtYSBhbGdvIGNvbW8gIkM6L1VzZXJzL3BlcmV6cC9EZXNrdG9wIi4gVGUgcmVjb21pZW5kbyB0cmFiYWphciBzb2JyZSBlbCBlc2NyaXRvcmlvIG8gRGVza3RvcCwgcGVybyBwdWVkZXMgc2VsZWNjaW9uYXIgbGEgY2FycGV0YSBlbiBsYSBxdWUgbcOhcyBjw7Ntb2RhIHRyYWJhamVzXltTaWVtcHJlIHF1ZSBlc2EgY2FycGV0YSBubyBlc3TDqSBtdXkgYWJham8gZW4gbGEgbGlzdGEgZGUgZGlyZWN0b3Jpb3MgcGFyYSBxdWUgbGEgcnV0YSBoYWPDrWEgZXNlIGRpcmVjdG9yaW8gbm8gc2VhIGRlbWFzaWFkbyBsYXJnYSBwYXJhIFdpbmRvd3NdLgoKCgoKYGBge3IsIGVjaG8gPSBGQUxTRSwgb3V0LndpZHRoID0gIjUwJSJ9CmtuaXRyOjppbmNsdWRlX2dyYXBoaWNzKGhlcmU6OmhlcmUoImltYWdlbmVzIiwgInR0XzAyX2ltZ18wN19SU3R1ZGlvLW9wY2lvbmVzLTMucG5nIikgKSAKYGBgCgpZYSBleHBsaWNhcsOpIGVuIGNsYXNlIHBvcnF1w6kgc2VsZWNjaW9uYW1vcyBlc3RhcyBvcGNpb25lcyBlbiBSU3R1ZGlvLgoKCiMjIyMgQcO6biBtw6FzIGNvbmZpZ3VyYWNpw7NuIGRlIFJTdHVkaW8KCgoxLiBFbiBSU3R1ZGlvIHNpZ3VlIGVzdMOhIHJ1dGEgZGUgbWVuw7pzOiBgVG9vbHMgPiBHbG9iYWwgT1B0aW9ucy4uLmAgeSBzZWxlY2Npb25hIGBDb2RlYC4gSW50ZW50YSBkZWphciBsYSBvcGNpb25lcyBkZSBsYSBwZXN0YcOxYSBgRWRpdGluZ2AgY29tbyB2ZXMgZW4gbGEgaW1hZ2VuIGRlIGFiYWpvLiBDb25jcmV0YW1lbnRlIGxvIHF1ZSBtw6FzIG1lIGludGVyZXNhIGVzIHF1ZSBlc3TDqSBtYXJjYWRhIGxhIG9wY2nDs24gYEluc2VydCBzcGFjZXMgZm9yIHRhYmAKCgoKYGBge3IsIGVjaG8gPSBGQUxTRSwgb3V0LndpZHRoID0gIjUwJSJ9CmtuaXRyOjppbmNsdWRlX2dyYXBoaWNzKGhlcmU6OmhlcmUoImltYWdlbmVzIiwgInR0XzAyX2ltZ18wN19SU3R1ZGlvLW9wY2lvbmVzLTQucG5nIikgKSAKYGBgCgoyLiAgRW4gUlN0dWRpbyBzaWd1ZSBlc3TDoSBydXRhIGRlIG1lbsO6czogYFRvb2xzID4gR2xvYmFsIE9QdGlvbnMuLi5gIHkgc2VsZWNjaW9uYSBgQ29kZWAuIEFob3JhIGludGVudGEgZGVqYXIgbGFzIG9wY2lvbmVzIGRlIGxhIHBlc3Rhw7FhIGBTYXZpbmdgIGNvbW8gdmVzIGVuIGxhIGltYWdlbiBkZSBhYmFqby4gTG8gbcOhcyBpbXBvcnRhbnRlIGVzIHF1ZSBlbiBsYSBjYWphIGRlIHRleHRvIGBEZWZhdWx0IHRleHQgZW5jb2RpbmdgIHBvbmdhOiBgVVRGLThgLiBFc3RvIGV2aXRhcsOhIHF1ZSB0ZW5nYW1vcyBwcm9ibGVtYXMgY29uIGxhIGNvZGlmaWNhY2nDs24gZGUgbG9hIGNhcmFjdGVyZXMsIHBvciBlamVtcGxvIGNvbiBsYSBlw7FlIG8gY29uIGxhcyB0aWxkZXMuCgoKYGBge3IsIGVjaG8gPSBGQUxTRSwgb3V0LndpZHRoID0gIjUwJSJ9CmtuaXRyOjppbmNsdWRlX2dyYXBoaWNzKGhlcmU6OmhlcmUoImltYWdlbmVzIiwgInR0XzAyX2ltZ18wN19SU3R1ZGlvLW9wY2lvbmVzLTUucG5nIikgKSAKYGBgCgpZYSB0ZW5lbW9zIFIgeSBSU3R1ZGlvIGluc3RhbGFkb3MgeSBjb25maWd1cmFkb3MsIGFzw60gcXVlIHZhbW9zIGEgZW1wZXphciBhIHRvcXVldGVhciBSU3R1ZGlvLgoKIyMjIENvbm9jaWVuZG8gbGEgaW50ZXJmYXogZGUgUlN0dWRpbwoKRHVyYW50ZSBlbCBjdXJzbyB2YW1vcyBhIHV0aWxpemFyIFIgcGFyYSBoYWNlciBhbsOhbGlzaXMgZXN0YWTDrXN0aWNvcyBwZXJvIGxvIHZhbW9zIGEgaGFjZXIgYSB0cmF2w6lzIGRlIFJTdHVkaW8sIGFzw60gcXVlIGVsIHByaW1lciBwYXNvIGVzIGZhbWlsaWFyaXphcm5vcyB1biBwb2NvIGNvbiBsYSBpbnRlcmZheiBkZSBSU3R1ZGlvLiBQYXJhIGFjb3N0dW1icmFzZSBhIFIgeSBSU3R1ZGlvIGxvIG1lam9yIGVzIGxhIHByw6FjdGljYSwgcGVybyBzaSBvcyBoaWNpZXNlIGZhbHRhLCBbYXF1w61dKGh0dHBzOi8vaXNtYXljLmdpdGh1Yi5pby9yYmFzaWNzLWJvb2svaW5kZXguaHRtbCkgdGVuw6lpcyB1biBmYW50w6FzdGljbyBsaWJybyBwYXJhIGhhYml0dWFyc2UgYSB0cmFiYWphciBjb24gUiB5IFJTdHVkaW8uCgoKQWwgYWJyaXIgUlN0dWRpbyB2ZXLDoXMgcXVlIGFsIHByaW5jaXBpbyB0aWVuZSAzIHBhbmVsZXMsIGF1bnF1ZSBlbnNlZ3VpZGEgYWJyaXJlbW9zIHVuIGN1YXJ0byBwYW5lbC4gTGEgY29uc29sYSBlcyBlbCBwYW5lbCBkZSBsYSBpenF1aWVyZGEuIEN1YW5kbyB0ZW5nYW1vcyA0IHBhbmVsZXMgbGEgY29uc29sYSBzZXLDoSBlbCBwYW5lbCBzaXR1YWRvIGl6cXVpZXJkYS1hYmFqby4gUG9kZW1vcyBwZW5zYXIgcXVlIGxhIGNvbnNvbGEgZXMgbG8gbcOhcyBwYXJlY2lkbyBhIFIsIHlhIHF1ZSBlbiBsYSBjb25zb2xhIHNlIHB1ZWRlbiBlamVjdXRhciBpbnN0cnVjY2lvbmVzIGRlIFIgZGlyZWN0YW1lbnRlLiAKCkN1YW5kbyBhYnJhcyBSU3R1ZGlvIHZlcmFzIGxvIHNpZ3VpZW50ZToKCmBgYHtyLCBlY2hvID0gRkFMU0UsIG91dC53aWR0aCA9ICI4NSUifQprbml0cjo6aW5jbHVkZV9ncmFwaGljcyhoZXJlOjpoZXJlKCJpbWFnZW5lcyIsICJ0dF8wMl9pbWdfMDFfUlN0dWRpby1pbmljaWFsLmpwZyIpICkgCmBgYAoKCi0gQ29uc29sYSAoaXpxdWllcmRhKSAgCgotIEVudmlyb25tZW50L0hpc3RvcnkgKGFycmliYS1kZXJlY2hhKSAgCgotIEZpbGVzL1Bsb3RzL1BhY2thZ2VzL0hlbHAgKGFiYWpvLWRlcmVjaGEpICAKCgoKCllhIHNhYmVtb3MgcXVlIGVsIHBhbmVsIGRlIGxhIGl6cXVpZXJkYSBlcyBsYSBjb25zb2xhLiBFbiBsYSBjb25zb2xhIHNlIHZlIHVuIG1lbnNhamUgZGUgYmllbnZlbmlkYSBxdWUgbm9zIGRpY2UgcXVlIHZlcnNpw7NuIGRlIFIgZXN0YW1vcyB1c2FuZG8geSBhbGd1bmEgY29zYSBtw6FzLiBBbCBmaW5hbCBkZWwgdGV4dG8gYXBhcmVjZSBlbCBzw61tYm9sbyBgPmAuIEEgZXN0ZSBzw61tYm9sbyBzZSBsZSBjb25vY2UgY29tbyAqcHJvbXB0KiB5IHNpbXBsZW1lbnRlIG5vcyBpbmRpY2EgcXVlIGVsIGludMOpcnByZXRlIGRlIFIsIHF1ZSBSLCBlc3TDoSBsaXN0byBwYXJhIGVqZWN1dGFyIG51ZXN0cmFzIGluc3RydWNjaW9uZXMuIAoKwr9Dw7NtbyBsZSBkYW1vcyBsYXMgaW5zdHJ1Y2Npb25lcyB1IG9yZGVuZXMgYSBSPyBMYSBmb3JtYSBtw6FzIGlubWVkaWF0YSBlcyBlc2NyaWJpZW5kbyBsYXMgb3JkZW5lcyBlbiBsYSBjb25zb2xhLCBkZXNwdcOpcyBkZWwgcHJvbXB0IChgPmApLiBQb3IgZWplbXBsbywgc2kgZXNjcmliaW1vcyBlbiBsYSBjb25zb2xhIGAyKzJgIHkgcHJlc2lvbmFtb3MgIDxrYmQ+RW50ZXI8L2tiZD4sIFIgZWplY3V0YXLDoSBsYSBpbnN0cnVjY2nDs24geSBub3MgZGV2b2x2ZXLDoSBlbCByZXN1bHRhZG8uIAoKQSB2ZWNlcyB1c2FyZW1vcyBsYSBjb25zb2xhIHBhcmEgZWplY3V0YXIgYWxndW5hIGluc3RydWNjacOzbiwgcGVybyBlbiBnZW5lcmFsIGVqZWN1dGFyZW1vcyBsYXMgaW5zdHJ1Y2Npb25lcyBhIHRyYXbDqXMgZGUgdW4gInNjcmlwdCIuIFVuYSByYXrDs24gcGFyYSBubyB1c2FyIGxhIGNvbnNvbGEgZXMgcXVlIHRyYWJhamFyIGVuIGxhIGNvbnNvbGEgZXMgbXV5IGxpbWl0YWRvIHlhIHF1ZSBsYXMgaW5zdHJ1Y2Npb25lcyBzZSBoYW4gZGUgaW50cm9kdWNpciB1bmEgYSB1bmEuIE90cmEgcmF6w7NuIGVzIHF1ZSBxdWVyZW1vcyB0ZW5lciB1biByZWdpc3RybyBjb24gdG9kYXMgbGFzIGluc3RydWNjaW9uZXMgcXVlIGVqZWN1dGVtb3MgcGFyYSBwb2RlciByZXBsaWNhciBudWVzdHJvIGFuw6FsaXNpcyBlbiBvdHJvIG1vbWVudG87IGFzw60gcXVlIGxvIGhhYml0dWFsIGVzIHRyYWJhamFyIGNvbiAqKnNjcmlwdHMqKiBvICoqZmljaGVyb3MgZGUgaW5zdHJ1Y2Npb25lcyoqLiAKClVuIHNjcmlwdCBubyBlcyBtw6FzIHF1ZSB1biBmaWNoZXJvIGRlIHRleHRvIGNvbiBleHRlbnNpw7NuIGAuUmAgZW4gZWwgcXVlIGVzY3JpYmlyZW1vcyBsYXMgaW5zdHJ1Y2Npb25lcyBxdWUgcXVlcmFtb3MgcXVlIFIgZWplY3V0ZS4KClZhbW9zIGEgY3JlYXIgbnVlc3RybyBwcmltZXIgc2NyaXB0LiBQYXJhIGVsbG8gdGllbmVzIHF1ZSBzZWd1aXIgZXN0YSBydXRhIGRlIG1lbsO6cyBlbiBSU3R1ZGlvOiBgRmlsZSA+IE5ldyBGaWxlID4gUiBTY3JpcHRgLiBWaXN1YWxtZW50ZTogCgoKYGBge3IsIGVjaG8gPSBGQUxTRSwgb3V0LndpZHRoID0gIjgwJSJ9CmtuaXRyOjppbmNsdWRlX2dyYXBoaWNzKGhlcmU6OmhlcmUoImltYWdlbmVzIiwgInR0XzAyX2ltZ18wMl9SU3R1ZGlvLW5ldy1zY3JpcHQucG5nIikgKSAKYGBgCgoKQ3VhbmRvIHBpbmNoZXMgY29uIGVsIHJhdMOzbiBlbiBgUiBTY3JpcHRgIHNlIGFicmlyw6EgZW4gUlN0dWRpbyB1biBudWV2byBwYW5lbCwgZWwgY3VhcnRvLCBhcnJpYmEgYSBsYSBpenF1aWVyZGEuIFZpc3VhbG1lbnRlOgoKCmBgYHtyLCBlY2hvID0gRkFMU0UsIG91dC53aWR0aCA9ICI4MCUifQprbml0cjo6aW5jbHVkZV9ncmFwaGljcyhoZXJlOjpoZXJlKCJpbWFnZW5lcyIsICJ0dF8wMl9pbWdfMDNfUlN0dWRpby1uZXctc2NyaXB0LTEucG5nIikgKQpgYGAKCkVzdGUgY3VhcnRvIHBhbmVsIChhcnJpYmEtaXpxdWllcmRhKSBlbiByZWFsaWRhZCBlcyB1biBlZGl0b3IgZGUgdGV4dG8uIEVuIMOpbCBwb2RlbW9zIAplc2NyaWJpciBsYXMgaW5zdHJ1Y2Npb25lcyBxdWUgcXVlcmFtb3MgcXVlIGVqZWN1dGUgUi4gUG9yIGVqZW1wbG8sIGbDrWphdGUgZW4gbGEgc2lndWllbnRlIGltYWdlbiBsbyBxdWUgaGUgZXNjcml0byBlbiBlbCBwYW5lbCBhcnJpYmEtaXpxdWllcmRhOiAKCgpgYGB7ciwgZWNobyA9IEZBTFNFLCBvdXQud2lkdGggPSAiOTUlIn0Ka25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoaGVyZTo6aGVyZSgiaW1hZ2VuZXMiLCAidHRfMDJfaW1nXzAzeF9SU3R1ZGlvLW5ldy1zY3JpcHQtMi5wbmciKSkgCmBgYAoKCkhlIGVzY3JpdG8gZXN0YXMgY3VhdHJvIGxpbmVhczoKCgpgYGB7ciwgZWNobyA9IFRSVUUsIGV2YWwgPSBGQUxTRX0KIyBtaSBwcmltZXIgc2NyaXB0IGRlIFIKMiArIDIKNSAqIDYKNDAwLzIKYGBgCgoKRXNjcmliZSB0w7ogdGFtYmnDqW4gKG8gY29waWEgeSBwZWdhKSBlc3TDoXMgY3VhdHJvIGxpbmVhcyBkZSB0ZXh0byBlbiBlbCBlZGl0b3IgKGFycmliYS1penF1aWVyZGEpIGRlIHR1IFJzdHVkaW8uCgpSIGVqZWN1dGFyw6EsIGN1YW5kbyBzZSBsbyBpbmRpcXVlbW9zLCBsYXMgbGluZWFzIGRlIGluc3RydWNjaW9uZXMgdW5hIGEgdW5hLgoKVW5hIHZleiBoYXlhcyBlc2NyaXRvIG8gcGVnYWRvIGVzYXMgNCBsaW5lYXMgZW4gUlN0dWRpbywgdmVyw6FzIHF1ZSBsYSBwcmltZXJhIGxpbmVhIGVzIGRpZmVyZW50ZTogbG8gbcOhcyBldmlkZW50ZSBlcyBxdWUgZXN0w6EgZW4gY29sb3IgdmVyZGUsIHBlcm8gZW4gcmVhbGlkYWQgbG8gaW1wb3J0YW50ZSBlcyBxdWUgY29taWVuemEgY29uIGVsIHPDrW1ib2xvIGAjYC4gRXN0ZSBoZWNobywgZXN0w6EgbWFyY2FuZG8vZGljaWVuZG8gYSBSIHF1ZSBlc2EgbGluZWEgZXMgdW4gY29tZW50YXJpbyBwYXJhIGxvcyBodW1hbm9zLCBwYXJhIG5vc290cm9zLCBubyBlcyBjw7NkaWdvIFIgeSBwb3IgdGFudG8gUiBubyBsYSBlamVjdXRhcsOhLgoKCkVuIHVuIHNjcmlwdCBzw7NsbyBzZSBwdWVkZW4gZXNjcmliaXIgMiBjb3NhczoKCi0gY29tZW50YXJpb3MgKHNpIGxhIGxpbmVhIGNvbWllbnphIGNvbiBgI2ApLiBSIG5vIGxhcyBlamVjdXRhcsOhICAKCi0gaW5zdHJ1Y2Npb25lcyBSIChubyBjb21pZW56YW4gY29uIGAjYCkuIFIgbGFzIGVqZWN1dGFyw6Egc2kgZXN0w6FuIGVzY3JpdGFzIGVuIFI7IGVzIGRlY2lyLCBzaSBzaWd1ZW4gbGFzIHJlZ2xhcyBkZWwgbGVuZ3VhamUgUi4gU2kgZXN0w6FuIG1hbCBlc2NyaXRhcyBSIG5vcyBkZXZvbHZlcsOhIHVuIG1lbnNhamUgZGUgZXJyb3IuIFRlbmVtb3MgcXVlIGFwcmVuZGVyIFIgeWEhISEKCgoKSGVtb3MgZXNjcml0byBjdWF0cm8gbGluZWFzIGVuIG51ZXN0cm8gc2NyaXB0IHkgYWhvcmEgcXVlcmVtb3MgcXVlIFIgbGFzIGVqZWN1dGUuIFIgZWplY3V0YXLDoSwgY3VhbmRvIHNlIGxvIGluZGlxdWVtb3MsIGxhcyBsaW5lYXMgZGUgaW5zdHJ1Y2Npb25lcyB1bmEgYSB1bmEuCgoKUGFyYSBlamVjdXRhciB1bmEgbGluZWEsIHNpdHVhbW9zIGVsIGN1cnNvciBlbiBlbGxhIHkgcHVsc2Ftb3MgPGtiZD5DcnRsPC9rYmQ+ICsgPGtiZD5FbnRlcjwva2JkPi4KClBsZWFzZSwgc2l0w7phIGVsIGN1cnNvciBlbiBsYSBwcmltZXJhIGxpbmVhIHkgcHVsc2EgPGtiZD5DcnRsPC9rYmQ+ICsgPGtiZD5FbnRlcjwva2JkPi4gT2JzZXJ2YSBxdcOpIGhhIG9jdXJyaWRvLiBMZSBoZW1vcyBkaWNobyBhIFIgcXVlIGVqZWN1dGUgbGEgcHJpbWVyYSBsaW5lYSwgcGVybyBjb21vIGVzdGEgcHJpbWVyYSBsaW5lYSBjb21pZW56YSBjb24gYCNgLCBSIGxhIGhhIGludGVycHJldGFkbyAoY29ycmVjdGFtZW50ZSkgY29tbyB1biBjb21lbnRhcmlvIHksIHBvciBzdXB1ZXN0bywgbm8gbGEgaGEgZWplY3V0YWRvLCBwb3IgbG8gcXVlIGhhIHBhc2FkbyBhIGxhIHNlZ3VuZGEgbGluZWEsIHkgZXN0YSB2ZXogc8OtIHF1ZSBsYSBlamVjdXRhLiBDb21vIGxhIHNlZ3VuZGEgbGluZWEgbm8gY29taWVuemEgY29uIGAjYCwgUiBsYSBpbnRlcnByZXRhIGNvbW8gdW5hIGluc3RydWNjacOzbiBkZSBSIHksIHPDrSBsYSBlbnRpZW5kZSAoc2kgbGFzIGhhcyBlc2NyaXRvIGNvcnJlY3RhbWVudGUgc2lndWllbmRvIGxhIHNpbnRheGlzIG8gbGVuZ3VhamUgZGUgUiksIGVqZWN1dGFyw6EgbGEgaW5zdHJ1Y2Npw7NuLiBSIGVudGllbmRlIHF1ZSBzaWduaWZpY2EgYDIgKyAyYCwgYXPDrSBxdWUgZWplY3V0YSBsYSBpbnN0cnVjY2nDs24geSBub3MgZGV2dWVsdmUgZWwgcmVzdWx0YWRvIGVuIGxhIGNvbnNvbGEuCgo8YnI+CgpFbiBsYSBpbWFnZW4gZGUgYWJham8geW8geWEgaGUgZWplY3V0YWRvIGxhIGluc3RydWNjacOzbiBgMiArIDJgLiBSIG5vcyBtdWVzdHJhIGVsIHJlc3VsdGFkbyBlbiBsYSBjb25zb2xhOiBwcmltZXJvIG5vcyBtdWVzdHJhLCBlbiBhenVsLCBsYSBpbnN0cnVjY2nDs24gcXVlIGhhIGVqZWN1dGFkbzsgZXMgZGVjaXIgYD4gMiArIDJgIHkgbHVlZ28gbm9zIG5vcyBtdWVzdHJhLCBlbiBuZWdybywgZWwgcmVzdWx0YWRvIGRlIGxhIGVqZWN1Y2nDs24gZGUgbGEgaW5zdHJ1Y2Npw7NuOyBlcyBkZWNpciBgWzFdIDRgLiBZYSB2ZXJlbW9zIHF1ZSBzaWduaWZpY2EgZWwgWzFdIGRlIGxhIGxpbmVhIGRlIHJlc3VsdGFkb3MuCgoKYGBge3IsIGVjaG8gPSBGQUxTRSwgb3V0LndpZHRoID0gIjk1JSJ9CmtuaXRyOjppbmNsdWRlX2dyYXBoaWNzKGhlcmU6OmhlcmUoImltYWdlbmVzIiwgInR0XzAyX2ltZ18wNF9SU3R1ZGlvLW5ldy1zY3JpcHQtMi5wbmciKSkgCmBgYAoKRXMgbcOhcyBmw6FjaWwgaGFjZXJsbyBxdWUgY29udGFybG8sIGF1bnF1ZSBwdWVkZSBxdWUgdGUgYXRhc3F1ZXMgZW4gYWxndW5hIGNvc2EsIG5vcm1hbCEhLiBQb3IgZWplbXBsbywgc2kgZW4gbHVnYXIgZGUgcG9uZXIgZWwgY3Vyc29yIGVuIGxhIHNlZ3VuZGEgbGluZWEsIHNlw7FhbGFzIG8gc3VicmF5YXMgc29sbyBwYXJ0ZSBkZSBsYSBsaW5lYSwgZW50b25jZXMsIHNlZ3VyYW1lbnRlIFIgbm8gdGUgZW50ZW5kZXLDoS4gQWhvcmEgdGUgdG9jYSBhIHRpOiBwbGVhc2UsIGVqZWN1dGEgbGEgdGVyY2VyYSBsaW5lYSBkZSB0dSBzY3JpcHQuCgrCv0PDs21vIGxlIGRlY2ltb3MgYSBSIHF1ZSBlamVjdXRlIGxhIHRlcmNlcmEgbGluZWEgIGA1ICogNmA/IEN1YW5kbyBsbyBoYWPDrWFtb3MgZW4gbGEgY29uc29sYSBzaW1wbGVtZW50ZSBoYWLDrWEgcXVlIHB1bHNhciA8a2JkPkVudGVyPC9rYmQ+LCBwZXJvIGFob3JhIGVzdGFtb3MgdHJhYmFqYW5kbyBlbiB1biBzY3JpcHQ6IGhheSBxdWUgc2l0dWFyIGVsIGN1cnNvciBlbiBsYSBsaW5lYSBxdWUgcXVlcmVtb3MgZWplY3V0YXIgeSBkYXJsZSBhIDxrYmQ+Q3J0bDwva2JkPiArIDxrYmQ+RW50ZXI8L2tiZD4uIFIgZWplY3V0YXLDoSBsYSBpbnN0cnVjY2nDs24geSBub3MgZGV2b2x2ZXLDoSBlbCByZXN1bHRhZG8gZW4gbGEgY29uc29sYS4gCgoKRW5zZWd1aWRhIGFwcmVuZGVyZW1vcyBtw6FzIGluc3RydWNjaW9uZXMgbyBmdW5jaW9uZXMgZGUgUiwgYWhvcmEgc29sbyBlc3RhbW9zIGludGVudGFuZG8gZmFtaWxpYXJpesOhbmRvbm9zIGNvbiBlbCBpbnRlcmZheiBkZSBSU3R1ZGlvLiBZYSBzYWJlbW9zIGNvbW8gY3JlYXIgdW4gZmljaGVybyBjb24gaW5zdHJ1Y2Npb25lcyBkZSBSICjDsyBzY3JpcHQpIHkgY29tbyBlamVjdXRhciBlc2FzIGluc3RydWNjaW9uZXMuIAoKTG8gbm9ybWFsIGVzIHF1ZSBndWFyZGVzIHR1cyBzY3JpcHRzIGVuIHVuIGFyY2hpdm8gcG9yIHNpIHR1dmllc2VzIHF1ZSB2b2x2ZXIgYSBjb3JyZXIgbGFzIG1pc21hcyBpbnN0cnVjY2lvbmVzIG3DoXMgYWRlbGFudGUuIFBhcmEgZ3VhcmRhciB0dXMgaW5zdHJ1Y2Npb25lcyBlbiB1biBmaWNoZXJvIHPDs2xvIHRpZW5lcyBxdWUgc2VndWlyIGVzdGEgcnV0YSBkZSBtZW7DunMgZW4gUlN0dWRpbzogYEZpbGUgPiBTYXZlIGFzIC4uLmAgIAoKVGVuZHLDoXMgcXVlIGVsZWdpciB1biBub21icmUgcGFyYSB0dSBzY3JpcHQgeSBkZWNpZGlyIGVuIHF1ZSBjYXJwZXRhIGRlIHR1IG9yZGVuYWRvciBndWFyZGFybG8uIFNpIGRlY2lkZXMgcXVlIHR1IHNjcmlwdCBzZSBsbGFtZSBgbXlfc2NyaXB0XzAxYCwgc2UgY3JlYXLDoSB1biBmaWNoZXJvIChkb25kZSB0w7ogaGF5YXMgZGVjaWRpZG8pIGxsYW1hZG8gYG15X3NjcmlwdF8wMS5SYC4gRsOtamF0ZSBxdWUgbGEgZXh0ZW5zacOzbiBkZWwgYXJjaGl2byBlcyAqKmAuUmAqKiwgZXN0w6EgZXh0ZW5zacOzbiBpZGVudGlmaWNhIGxvcyBzY3JpcHRzIG8gZmljaGVyb3MgY29uIGluc3RydWNjaW9uZXMgZGUgUi4KCkVzdG8gdmFzIGEgYWNhYmFyIGVudGVuZGnDqW5kb2xvIGVuIHBvY28gdGllbXBvLCBwZXJvIGN1YW50byBhbnRlcyBsbyBlbnRpZW5kYXMgbWVqb3I6IGRhbW9zIGxhcyBvcmRlbmVzL2luc3RydWNjaW9uZXMgYSBSIHBvciBlc2NyaXRvLCBnZW5lcmFsbWVudGUgdXNhbW9zICJzY3JpcHRzIjsgZXMgZGVjaXIsIGVzY3JpYmltb3MgbGFzIGluc3RydWNjaW9uZXMgZW4gdW4gZmljaGVybyBjb24gZXh0ZW5zacOzbiAuUi4gUGFyYSBlamVjdXRhciBsYXMgb3JkZW5lcyBxdWUgaGVtb3MgZXNjcml0byBlbiBudWVzdHJvIGZpY2hlcm8gUiBoZW1vcyBkZSwgbGluZWEgcG9yIGxpbmVhLCB0ZWNsZWFyOiA8a2JkPkNydGw8L2tiZD4gKyA8a2JkPkVudGVyPC9rYmQ+LiBTaSBsYSBvcmRlbiB0aWVuZSBzZW50aWRvLCBlcyBkZWNpciwgc2kgUiBlbnRpZW5kZSBsYSBvcmRlbiwgbGEgZWplY3V0YXLDoSB5IHRlIG1vc3RyYXLDoSBlbCByZXN1bHRhZG8gZW4gbGEgQ29uc29sYS4KCjxicj4KCkJpZW4sIHlhIHNhYmVtb3MgaGFjZXIgcXVlIFIgZWplY3V0ZSBudWVzdHJhcyBpbnN0cnVjY2lvbmVzOiBwb2RlbW9zIGVqZWN1dGFyIG9yZGVuZXMgZW4gbGEgQ29uc29sYSAoY29uIDxrYmQ+RW50ZXI8L2tiZD4pIG8gZW4gdW4gc2NyaXB0ICg8a2JkPkNydGw8L2tiZD4gKyA8a2JkPkVudGVyPC9rYmQ+KS4gVXNhcmVtb3MgbGEgY29uc29sYSBhIHZlY2VzLCBtdWNoYXMgdmVjZXMgdHJhYmFqYXJlbW9zIGNvbiBzY3JpcHRzIG8gZmljaGVyb3MgLlIgcGVybywgcG9jbyBhIHBvY28sIGFjYWJhcmVtb3MgdHJhYmFqYW5kbyBkZSBvdHJhIGZvcm1hLiAKCkNvbW8gcXVlcmVtb3MgcXVlIG51ZXN0cm9zIGFuw6FsaXNpcyBzZWFuIHJlcHJvZHVjaWJsZXMsIGhhYml0dWFsbWVudGUgdHJhYmFqYXJlbW9zIGNvbiBgUnByb2plY3RzYCB5IGNvbiBgZmljaGVyb3MgLlJtZGAuICoqU8OtISEqKiwgZW4gbHVnYXIgZGUgY29uIGBmaWNoZXJvcyAuUmAgKG8gc2NyaXB0cykgdHJhYmFqYXJlbW9zIGNvbiBgZmljaGVyb3MgICoqUm1hcmtkb3duKipgIMOzIGBmaWNoZXJvcyAuUm1kYC4gWWEgbG8gdmVyZW1vcywgcGVybyBhbnRlcyB0ZW5kcmVtb3MgcXVlIGZhbWlsaWFyaXphcm5vcyB1biBwb2NvIG3DoXMgY29uIGVsIGxlbmd1YWplIFIuIERlIG1vbWVudG8gc2VndWltb3MgY29uIGVsIGludGVyZmF6IGRlIFJTdHVkaW8uCgo8YnI+CgojIyMjIExvcyA0IHBhbmVsZXMgZGUgUlN0dWRpbwoKVmFtb3MgYSBtaXJhciBjb24gdW4gcG9jbyBtw6FzIGRlIGRldGFsbGUgKipsb3MgNCBwYW5lbGVzIGRlIFJTdHVkaW8qKi4gQ29tbyBwdWVkZXMgdmVyIGVuIGxhIGltYWdlbiBkZSBhYmFqbywgZ2VuZXJhbG1lbnRlLCBhIGxhIGl6cXVpZXJkYSBlbmNvbnRyYW1vcyBsYSBjb25zb2xhIHkgZWwgZWRpdG9yIGRlIHNjcmlwdHMuIFlhIHNhYmVtb3MgcXVlIGRlc2RlIGVzdG9zIGRvcyBwYW5lbGVzIHBvZGVtb3MgZGFyIGluc3RydWNjaW9uZXMgYSBSIHBhcmEgcXVlIGxhcyBlamVjdXRlLgoKVmVhbW9zIHVuIHBvY28gbG9zIDIgcGFuZWxlcyBkZSBsYSBkZXJlY2hhLiBQb2RlbW9zIHBlbnNhciBxdWUgc29uIHBhbmVsZXMgYXV4aWxpYXJlcywgbm9zIGF5dWRhcsOhbiBlbiBkZXRlcm1pbmFkYXMgdGFyZWFzLiBFc3RvcyBkb3MgcGFuZWxlcyBkZSBsYSBkZXJlY2hhICB0aWVuZW4gY2FkYSB1bm8gdmFyaWFzIHBlc3Rhw7Fhcy4gUG9yIGVqZW1wbG8sIGVsIHBhbmVsIHF1ZSBlc3TDoSBlbiBsYSBwb3NpY2nDs24gYXJyaWJhLWRlcmVjaGEgdGllbmUgY3VhdHJvIHBlc3Rhw7FhczogYEVudmlyb25tZW50YCB5IDMgbcOhc15bSWd1YWwgZW4gdnVlc3RybyBvcmRlbmFkb3IgdGVuw6lpcyBtw6FzIChvIG1lbm9zKSBwZXN0YcOxYXMsIGVzbyBkZXBlbmRlcsOhIGRlIGxhIHZlcnNpw7NuIGRlIFJTdHVkaW8gcXVlIHRlbmfDoWlzIGluc3RhbGFkYS4gWW8gYWhvcmEgbWlzbW8gdGVuZ28gY3VhdHJvLCBwZXJvIGlndWFsIGxhIHByw7N4aW1hIHZlcnNpw7NuIGRlIFJzdHVkaW8gcHVlZGUgdGVuZXIgNSBwZXN0YcOxYXNdLiBFbnNlZ3VpZGEgdmVyZW1vcyBxdWUgYWwgaW50ZXJhY3R1YXIgY29uIFIgaXJlbW9zIGNyZWFuZG8gb2JqZXRvcyAocG9yIGVqZW1wbG8gdW4gdmVjdG9yIG8gdW5hIG1hdHJpeiBvIHVuYSB0YWJsYSBkZSBkYXRvcykuIEVzdG9zIG9iamV0b3MgZXN0YXLDoW4gZ3VhcmRhZG9zIGVuIGxhIG1lbW9yaWEgZGVsIG9yZGVuYWRvciBwZXJvIGxvcyAidmVyZW1vcyIsIGFwYXJlY2Vyw6FuIGVuIGxhIHBlc3Rhw7FhIGBFbnZpcm9ubWVudGAuIEVuIGxhIHBlc3Rhw7FhIGBIaXN0b3J5YCB0ZW5kcmVtb3MgdW4gbGlzdGFkbyBjb24gbGFzIGluc3RydWNjaW9uZXMgZGUgUiBxdWUgaGF5YW1vcyBlamVjdXRhZG8gcHJldmlhbWVudGUgZW4gbnVlc3RyYSBhY3R1YWwgc2VzacOzbiBkZSBSIChwb3IgZWplbXBsbyBgMiArIDJgKS4gT3RybyBlamVtcGxvOiBhIHZlY2VzIGVuIG51ZXN0cm8gYW7DoWxpc2lzIGNvbiBSIGhhcmVtb3MgdW4gZ3LDoWZpY28gbyB2YXJpb3MsIHBvZHJlbW9zIHZlciBlbCBncsOhZmljbyBlbiBsYSBwZXN0YcOxYSBgUGxvdHNgIGVuIGVsIHBhbmVsIHNpdHVhZG8gYWJham8tZGVyZWNoYS4KCgpgYGB7ciwgZWNobyA9IEZBTFNFfQprbml0cjo6aW5jbHVkZV9ncmFwaGljcyhoZXJlOjpoZXJlKCJpbWFnZW5lcyIsICJ0dF8wMl9pbWdfMDVfUlN0dWRpby00LXBhbmVsZXMucG5nIikgKSAKYGBgCgoKTGEgaW1hZ2VuIGRlIGFycmliYSBlcyBkZSBoYWNlIHVub3MgYcOxb3MsIHNpIHRlIGZpamFzIGVsIHBhbmVsIHN1cGVyaW9yLWRlcmVjaGEgdGllbmUgc29sbyAyIHBlc3Rhw7Fhcy4gRW4gMjAyMCBzYWxpw7MgbGEgdmVyc2nDs24gMS4zIGRlIFJTdHVkaW8sIGVuIGxhIHF1ZSBlbiBlbCBwYW5lbCBzdXBlcmlvci1kZXJlY2hhLCBlbiBsdWdhciBkZSBoYWJlciAyIHBlc3Rhw7FhcywgaGF5IDQsIHVuYSBkZSBlbGxhcywgbGxhbWFkYSAiVHV0b3JpYWxzIiwgcGVybWl0ZSBlamVjdXRhciB0dXRvcmlhbGVzIHBhcmEgYXByZW5kZXIgUiBkZW50cm8gZGUgUlN0dWRpby4KCjxicj4KCgojIyAzLiBGb3JtYSBkZSB0cmFiYWphciBjb24gUiB5IFJTdHVkaW8KCllhIGhlbW9zIGRlamFkbyBjbGFybyBxdWUgdmFtb3MgYSB1c2FyIFJTdHVkaW8gcGFyYSBpbnRlcmFjdHVhciBjb24gUi4gT2ssIHBlcm8gaGF5IGRpc3RpbnRhcyBmb3JtYXMgZGUgdHJhYmFqYXIsIG8gZGlzdGludG9zICJ3b3JrZmxvd3MiLgoKCkN1YW5kbyBoYWdhcyB1biBhbsOhbGlzaXMgZXN0YWTDrXN0aWNvIGNvbXBsZWpvLCBwb3IgZWplbXBsbyBwYXJhIHR1IFRGRywgbyBwYXJhIGVsIHRyYWJham8gZmluYWwgZGUgZXN0ZSBjdXJzbywgbG8gbm9ybWFsIGVzIHF1ZSBwYXJhIHJlYWxpemFyIGVsIHByb3llY3RvIG5vIHNlYSBzdWZpY2llbnRlIGNvbiB1biDDum5pY28gc2NyaXB0OyBsbyBoYWJpdHVhbCBlcyBxdWUgY2FkYSBwcm95ZWN0byBuZWNlc2l0ZSBkZSB2YXJpb3MgaW5wdXRzIChkYXRvcywgaW3DoWdlbmVzLCBzY3JpcHRzIGV0Yy4uLikuIEVuIGVzdG9zIGNhc29zLCB1dGlsaXphcmVtb3MgdW4gKipScHJvamVjdCoqIHBhcmEgY2FkYSBwcm95ZWN0by4gCgpFbnNlZ3VpZGEgdmVyZW1vcyBjb21vIHBvZGVtb3MgY3JlYXIgdW4gUnByb2plY3QsIHkgZXhwbGljYXJlbW9zIHN1cyB2ZW50YWphcywgcGVybyBkZSBtb21lbnRvIHB1ZWRlcyBwZW5zYXIgcXVlIHVuIFJwcm9qZWN0IG5vIGVzIG3DoXMgcXVlIHVuYSBjYXJwZXRhIGRlZGljYWRhIGVuIGV4Y2x1c2l2YSBhIHR1IHByb3llY3RvLCB1bmEgY2FycGV0YSBjcmVhZGEgcGFyYSBhbG1hY2VuYXIgdG9kbyBsbyByZWxhY2lvbmFkbyBjb24gdHUgcHJveWVjdG8uCgrCv1BvciBxdcOpIHV0aWxpemFyZW1vcyAqKlJwcm9qZWN0cyoqPyBMYXMgcmF6b25lcyBzb24gdmFyaWFzLCBwZXJvIGNvbW8gY2FzaSBzaWVtcHJlIHF1aWVuIG1lam9yIGxvIGV4cGxpY2EgZXMgW0plbm55IEJyeWFuXShodHRwczovL3R3aXR0ZXIuY29tL2plbm55YnJ5YW4/bGFuZz1lcyksIHBvciBlamVtcGxvIFthcXXDrV0oaHR0cHM6Ly93aGF0dGhleWZvcmdvdC5vcmcvcHJvamVjdC1vcmllbnRlZC13b3JrZmxvdy5odG1sKS4KClZveSBhIGludGVudGFyIHJlc3VtaXIgeW8gbG8gcXVlIG5vcyBhY29uc2VqYSBKZW5ueToKCi0gZXMgYmVuZWZpY2lvc28gcG9uZXIgdG9kb3MgbG9zIGFyY2hpdm9zIChkYXRvcywgc2NyaXB0cywgaW3DoWdlbmVzLCBldGMuLi4pIG5lY2VzYXJpb3MgcGFyYSB1biBhbsOhbGlzaXMgZW4gdW5hIMO6bmljYSBjYXJwZXRhIGRlZGljYWRhIGVuIGV4Y2x1c2l2YSBhIGVzZSBhbsOhbGlzaXMgbyBwcm95ZWN0by4gIAoKLSBlbiBsYSBjYXJwZXRhIGRlbCBwcm95ZWN0byBlcyDDunRpbCB1dGlsaXphciBzdWJjYXJwZXRhcywgcG9yIGVqZW1wbG8gdW5hIGNhcnBldGEgcGFyYSBkYXRvcywgb3RyYSBwYXJhIGltw6FnZW5lcywgZXRjLi4uICAKCi0gbG9zIG5vbWJyZXMgZGUgbG9zIGFyY2hpdm9zIHkgbGFzIGNhcnBldGFzIHRhbWJpw6luIHNvbiBpbXBvcnRhbnRlcy4gSGF5IHF1ZSBpbnRlbnRhciBxdWUgbG9zIG5vbWJyZXMgZGUgbG9zIGFyY2hpdm9zIHNlYW4gZXhwbGljYXRpdm9zIGRlIGxvIHF1ZSBoYWNlIG8gY29udGllbmUgZWwgYXJjaGl2by4gTG9zIG5vbWJyZXMgZGUgbG9zIGZpY2hlcm9zIGhhbiBkZSBzZXIgbGVnaWJsZXMgcG9yIGxhcyBwZXJzb25hcywgcGVybyB0YW1iacOpbiBwb3IgbGFzIG3DoXF1aW5hcy4gSmVubnkgbG8gZXhwbGljYSBbYXF1w61dKGh0dHBzOi8vc3BlYWtlcmRlY2suY29tL2plbm55YmMvaG93LXRvLW5hbWUtZmlsZXMpLiBQb3IgZmF2b3IsIG5vIGRlasOpaXMgZXNwYWNpb3MgZW4gYmxhbmNvIGVuIGxvcyBub21icmVzIGRlIGxvcyBmaWNoZXJvcywgc2kgcXVlcsOpaXMgc2VwYXJhciBwYWxhYnJhcyB1c2FkIGAtYCB5L28gYF9gLiBObyB1c8OpaXMgZXNwYWNpb3MgZW4gYmxhbmNvISEhCgotIHVuYSBkZSBsYXMgY2FyYWN0ZXLDrXN0aWNhcyBtw6FzIGludGVyZXNhbnRlcyBkZSB1biBScHJvamVjdCBlcyBxdWUgZWwgZGlyZWN0b3JpbyBkZSB0cmFiYWpvIGRlbCBwcm95ZWN0byBlcyBsYSBwcm9waWEgY2FycGV0YSBkZWwgcHJveWVjdG9eW1PDrSwgc8OpIHF1ZSBzaSBwYXJlY2UgdW4gdHJhYmFsZW5ndWFzLCBwZXJvIGVzIG11eSBpbXBvcnRhbnRlIHF1ZSBlc3RvIGxvIGFjYWJlcyBlbnRlbmRpZW5kby4gQ3VhbmRvIGxvIGVudGllbmRhcywgeSBzZWd1cm8gcXVlIGxvIGhhY2VzIHByb250bywgdmVyw6FzIHF1ZSBlbiByZWFsaWRhZCBlcyBtdXkgZsOhY2lsLl0uIFJlcGl0bywgZW4gdW4gUnByb2plY3QsIGVsIGRpcmVjdG9yaW8gZGUgdHJhYmFqbyBlcyBsYSBwcm9waWEgY2FycGV0YSBkZWwgUnByb2plY3QsIHkgYXPDrSBwb2RlbW9zIHRyYWJhamFyIGNvbiAqKnJ1dGFzKiogbyBwYXRocyAqKnJlbGF0aXZhcyoqLCBsbyBxdWUgdGllbmUgbGEgdmVudGFqYSBkZSBxdWUgbGFzIHJ1dGFzIHJlbGF0aXZhcyBmdW5jaW9uYXLDoW4gZW4gY3VhbHF1aWVyIG9yZGVuYWRvcl5bRXN0byBsbyBjb25zZWd1aXJlbW9zIHRyYWJhamFuZG8gY29uIFJwcm9qZWN0cyB5IGNvbiBlbCBwYXF1ZXRlIGBoZXJlYC4gTG8gdmVyZW1vcyBwcm9udG9dLgoKPGJyPgoKVHJhdG8gZGUgZXhwbGljYXJsbyB1biBwb2NvIG3DoXM6IGN1YW5kbyB0cmFiYWplbW9zIGVuIHVuIHByb3llY3RvLCBnZW5lcmFsbWVudGUsIHRlbmRyZW1vcyBxdWUgY2FyZ2FyIHVub3MgZGF0b3MuIFBvciBlamVtcGxvLCBpbWFnaW5hIHF1ZSBsb3MgZGF0b3MgcXVlIHZhcyBhIHVzYXIgZXN0w6FuIGVuIGVsIGZpY2hlcm8gIm1pc19kYXRvcy54bHN4IiwgYXPDrSBxdWUgdGVuZHLDoXMgcXVlIGRlY2lybGUgYSBSIGRvbmRlIGVzdMOhbiBsb3MgZGF0b3MuIFRlbmRyw6FzIHF1ZSBkYXJsZSBsYSBydXRhIG8gcGF0aCBoYXN0YSBlbCBhcmNoaXZvIGRlIGRhdG9zLiBOb3JtYWwhIQoKUGVybyBjb21vIHZhbW9zIGEgdHJhYmFqYXIgY29uIHByb3llY3RvcywgbG9zIGRhdG9zIGVzdGFyw6FuIGRlbnRybyBkZSBsYSBjYXJwZXRhIGRlIG1pIHByb3llY3RvLCBxdWl6w6FzIGVuIHVuYSBzdWJjYXJwZXRhIGxsYW1hZGEgImRhdG9zIi4gRXMgcG9zaWJsZSBxdWUgbGEgcnV0YSByZWFsIG8gYWJzb2x1dGEgYSBtaXMgZGF0b3Mgc2VhIGxhIHNpZ3VpZW50ZTogYEM6L1VzZXJzL3BlcmV6cC9teV9wcm95ZWN0by9kYXRvcy9taXNfZGF0b3MueGxzeGAsIHBlcm8gY29tbyB0cmFiYWphbW9zIGNvbiBwcm95ZWN0b3MsIG51ZXN0cm8gZGlyZWN0b3JpbyBkZSB0cmFiYWpvIGVzIGxhIHByb3BpYSBjYXJwZXRhIGRlbCBwcm95ZWN0bywgYXPDrSBxdWUgc29sbyB0ZW5kcmVtb3MgcXVlIHVzYXIgdW5hIHJ1dGEgcmVsYXRpdmEsIHNvbG8gdGVuZHJlbW9zIHF1ZSBwb25lciBgLi9kYXRvcy9taXNfZGF0b3MueGxzYC4KCkxhIHZlbnRhamEgZGUgZXN0byBubyBlcyBzb2xhbWVudGUgcXVlIGFob3JyYW1vcyB0aWVtcG8gZXNjcmliaWVuZG8gbG9zIG5vbWJyZXMgZGUgbGFzIHJ1dGFzLCBxdWUgdGFtYmnDqW4sIGxhIHByaW5jaXBhbCB2ZW50YWphIGNvbnNpc3RlIGVuIHF1ZSwgc2kgcG9yIGVqZW1wbG8sIHF1ZXJlbW9zIGNvbXBhcnRpciBudWVzdHJvIGFuw6FsaXNpcyBjb24gdW4gY29sYWJvcmFkb3IsIGxlIGRhcmVtb3MgbnVlc3RyYSBjYXJwZXRhIGNvbiB0b2RvIGVsIHByb3llY3RvIHkgbG9zIHNjcmlwdHMgKipzZWd1aXLDoW4gZnVuY2lvbmFuZG8gZW4gU1Ugb3JkZW5hZG9yKiogaW5kZXBlbmRpZW50ZW1lbnRlIGRlIGRvbmRlIHBvbmdhIMOpbCBsYSBjYXJwZXRhIGRlbCBwcm95ZWN0byBxdWUgbGUgaGVtb3MgZGVqYWRvLiAKCkxhIHJhesOzbiBvYnZpYW1lbnRlIGVzIHF1ZSBlbiBudWVzdHJvIHByb3llY3RvIGhlbW9zIHVzYWRvICoqcnV0YXMgcmVsYXRpdmFzKiouIExhcyBydXRhcyByZWxhdGl2YXMsIHRvbWFuIGNvbW8gcmVmZXJlbmNpYSwgZW1waWV6YW4gZGVzZGUgZWwgZGlyZWN0b3JpbyBkZSB0cmFiYWpvLCB5IGVuIHVuIGBScHJvamVjdGAgbGEgY2FycGV0YSBkZSB0cmFiYWpvIGVzIHNpZW1wcmUgbGEgcHJvcGlhIGNhcnBldGEgZGVsIHByb3llY3RvLgoKUGFyYSBhbGd1bm8gZGUgdm9zb3Ryb3MgZXN0byBvcyBwYXJlY2Vyw6EgY29tcGxpY2FkbywgcGVybyB5YSB2ZXLDqWlzLCBlbiBjbGFzZSwgcXVlIHVuYSB2ZXogbG8gZW50aWVuZGVzLCBlcyBtdXktbXV5IHNlbmNpbGxvLiBPcyBoYWJpdHVhcmVpcyBlbnNlZ3VpZGEgYSB1c2FyIHByb3llY3RvcyB5IHJ1dGFzIHJlbGF0aXZhcy4gICAKICAgIAoKQ29tbyBkaWNlIEplbm55OiAgCiAgICAKPiBUaGVzZSBoYWJpdHMgZ3VhcmFudGVlIHRoYXQgdGhlIHByb2plY3QgY2FuIGJlIG1vdmVkIGFyb3VuZCBvbiB5b3VyIGNvbXB1dGVyIG9yIG9udG8gb3RoZXIgY29tcHV0ZXJzIGFuZCB3aWxsIHN0aWxsIOKAnGp1c3Qgd29ya+KAnS4gCgo8YnI+CgpQYXJhIGFjYWJhciBlc3RhIHNlY2Npw7NuLCBzZcOxYWxhcsOpIHF1ZSBsb3Mgbm9tYnJlcyBkZSBsb3MgZmljaGVyb3Mgc29uIGltcG9ydGFudGVzLiBQYXJhIHZlciBhbGd1bm9zIGNvbnNlam9zIHNvYnJlIGNvbW8gcG9uZXIgbm9tYnJlIGEgdHVzIGFyY2hpdm9zIHB1ZWRlcyBpciBbYXF1w61dKGh0dHBzOi8vc2xpZGVzLmRqbmF2YXJyby5uZXQvcHJvamVjdC1zdHJ1Y3R1cmUvIzEpLiBObyBwdWVkbyByZXNpc3Rpcm1lIGEgY2l0YXIgb3RyYSB2ZXogYSBKZW5ueWZlciBCcnlhbjoKCjxibG9ja3F1b3RlIGNsYXNzPSJ0d2l0dGVyLXR3ZWV0Ij48cCBsYW5nPSJlbiIgZGlyPSJsdHIiPkZpbGUgb3JnYW5pemF0aW9uIGFuZCBuYW1pbmcgYXJlIHBvd2VyZnVsIHdlYXBvbnMgYWdhaW5zdCBjaGFvcyBieSA8YSBocmVmPSJodHRwczovL3R3aXR0ZXIuY29tL0plbm55QnJ5YW4/cmVmX3NyYz10d3NyYyU1RXRmdyI+QEplbm55QnJ5YW48L2E+IDxhIGhyZWY9Imh0dHBzOi8vdHdpdHRlci5jb20vaGFzaHRhZy9Nb3pmZXN0P3NyYz1oYXNoJmFtcDtyZWZfc3JjPXR3c3JjJTVFdGZ3Ij4jTW96ZmVzdDwvYT4gPGEgaHJlZj0iaHR0cHM6Ly90d2l0dGVyLmNvbS9oYXNodGFnL01vekNvb2tpZT9zcmM9aGFzaCZhbXA7cmVmX3NyYz10d3NyYyU1RXRmdyI+I01vekNvb2tpZTwvYT4gPGEgaHJlZj0iaHR0cHM6Ly90d2l0dGVyLmNvbS9oYXNodGFnL0ZvcnR1bmVDb29raWU/c3JjPWhhc2gmYW1wO3JlZl9zcmM9dHdzcmMlNUV0ZnciPiNGb3J0dW5lQ29va2llPC9hPiA8YSBocmVmPSJodHRwczovL3QuY28vVzA4dWdMTHJTYSI+cGljLnR3aXR0ZXIuY29tL1cwOHVnTExyU2E8L2E+PC9wPiZtZGFzaDsgRGF2aWQgR3VhcmNoIPCflpYg8J+Ol++4jyAoQERHdWFyY2gpIDxhIGhyZWY9Imh0dHBzOi8vdHdpdHRlci5jb20vREd1YXJjaC9zdGF0dXMvNjYzMDQ5MzUzMDA3OTMxMzkyP3JlZl9zcmM9dHdzcmMlNUV0ZnciPk5vdmVtYmVyIDcsIDIwMTU8L2E+PC9ibG9ja3F1b3RlPiA8c2NyaXB0IGFzeW5jIHNyYz0iaHR0cHM6Ly9wbGF0Zm9ybS50d2l0dGVyLmNvbS93aWRnZXRzLmpzIiBjaGFyc2V0PSJ1dGYtOCI+PC9zY3JpcHQ+IAoKPGJyPjxicj4KCiMjIyBDcmVhbmRvIHVuIFJwcm9qZWN0CgpCaWVuLCB5YSBub3MgaGFzIGRpY2hvIHF1ZSB0cmFiYWphcmVtb3MgY29uIFJwcm9qZWN0LCB2YWxlLCBwZXJvIMK/Y8OzbW8gc2UgY3JlYSB1biBScHJvamVjdD8KClNpbXBsZW1lbnRlIGhhcyBkZSBhYnJpciBSU3R1ZGlvIHkgc2VndWlyIGVzdMOhIHJ1dGEgZGUgbWVuw7pzOiBgRmlsZSA+IE5ldyBQcm9qZWN0Li4uYCB5IHNlIGFicmlyw6EgdW5hIHZlbnRhbmEgZG9uZGUgdGVuZHLDoXMgcXVlIHNlbGVjY2lvbmFyIGBOZXcgUHJvamVjdGAuIEVudG9uY2VzLCBzZSBhYnJpcsOhIG90cmEgdmVudGFuYSB5IHRlbmRyw6FzIHF1ZSBzZWxlY2Npb25hciBgTmV3IERpcmVjdG9yeWAuIFNlIGFicmlyw6Egb3RyYSB2ZW50YW5hIGNvbiBkb3MgY2FqYXMgZGUgdGV4dG8sIHVuYSwgbGEgZGUgYWJham8sIGVzdGFyw6EgZXNjcml0YSBsYSBydXRhIGRvbmRlIHNlIHZhIGEgY3JlYXIgbnVlc3RyYSBjYXJwZXRhIG8gcHJveWVjdG8geSBsYSBjYWphIGRlIGFycmliYSBlc3RhcsOhIHZhY8OtYSB5IGhhcyBkZSBwb25lciBhbGzDrSBlbCBub21icmUgcXVlIHF1aWVyZXMgcXVlIHRlbmdhIHR1IHByb3llY3RvLiBDb21vIHB1ZWRlcyB2ZXIgZW4gbGFzIGltw6FnZW5lcyBkZSBhYmFqbywgeW8gaGUgbGxhbWFkbyBhbCBwcm95ZWN0byAibXlfcHJpbWVyX3Byb2plY3QiLiAKCgpgYGB7ciwgZWNobyA9IEZBTFNFLCBvdXQud2lkdGggPSAiNzUlIn0Ka25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoaGVyZTo6aGVyZSgiaW1hZ2VuZXMiLCAidHRfMDJfaW1nXzA4X2NyZWFyLVJwcm9qZWN0LTEucG5nIikgKSAKa25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoaGVyZTo6aGVyZSgiaW1hZ2VuZXMiLCAidHRfMDJfaW1nXzA4X2NyZWFyLVJwcm9qZWN0LTIucG5nIikgKSAKa25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoaGVyZTo6aGVyZSgiaW1hZ2VuZXMiLCAidHRfMDJfaW1nXzA4X2NyZWFyLVJwcm9qZWN0LTMucG5nIikgKSAKYGBgCgoKCgpgYGB7ciwgZWNobyA9IEZBTFNFLCBvdXQud2lkdGggPSAiNzUlIn0Ka25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoaGVyZTo6aGVyZSgiaW1hZ2VuZXMiLCAidHRfMDJfaW1nXzA4X2NyZWFyLVJwcm9qZWN0LTQucG5nIikgKSAKa25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoaGVyZTo6aGVyZSgiaW1hZ2VuZXMiLCAidHRfMDJfaW1nXzA4X2NyZWFyLVJwcm9qZWN0LTUucG5nIikgKSAKYGBgCgoKVW5hIHZleiBoYWdhcyB0b2RvIGVzdG8sIFJTdHVkaW8gY3JlYXLDoSB1bmEgY2FycGV0YSBudWV2YSBlbiB0dSBvcmRlbmFkb3IgcXVlIHNlcsOhIG51ZXN0cmEgY2FycGV0YSBwYXJhIGVsIHByb3llY3RvLiBFbiBtaSBjYXNvIGxhIGNhcnBldGEgZXN0YXLDoSBlbiAiQzovVXNlcnMvcGVyZXpwL0Rlc2t0b3AvbXlfcHJpbWVyX3Byb3llY3RvIi4gRXMgdW5hIGNhcnBldGEgbm9ybWFsIGNvbiB1biBhcmNoaXZvIGRlbnRybyBjb24gdW4gaWNvbm8gYXp1bGl0byB5IHF1ZSB0ZW5kcsOhIHBvciBub21icmUgIm15X3ByaW1lcl9wcm95ZWN0by5ScHJvaiI7IGVzIHVuIGZpY2hlcm8gZGUgdGV4dG8gY29uIGV4dGVuc2nDs24gKiouUnByb2oqKi4gWWEgaGFibGFyZW1vcyBkZSDDqWwuIEFkZW3DoXMgZGUgY3JlYXIgdW5hIGNhcnBldGEgZW4gbnVlc3RybyBvcmRlbmFkb3IsIFJTdHVkaW8gaGFicsOhIGluaWNpYWRvIHVuYSBudWV2YSBzZXNpw7NuIGRlIFIgY29uIG51ZXN0cm8gcHJveWVjdG8geSB2ZXLDoXMgYWxnbyBjb21vIGVzdG86IAoKCgpgYGB7ciwgZWNobyA9IEZBTFNFfQprbml0cjo6aW5jbHVkZV9ncmFwaGljcyhoZXJlOjpoZXJlKCJpbWFnZW5lcyIsICJ0dF8wMl9pbWdfMDlfbXlfUnByb2plY3QucG5nIikgKSAKYGBgCgoKU2VuY2lsbGFtZW50ZSB0ZW5lbW9zIFIgeSBSU3R1ZGlvIGxpc3RvcyBwYXJhIHRyYWJhamFyOyBlcyBkZWNpciwgcGFyYSBlamVjdXRhciBpbnN0cnVjY2lvbmVzIGVuIGxhIGNvbnNvbGEgbyBwYXJhIGNyZWFyIG51ZXN0cm9zIHNjcmlwdHMuIEVzbyBzw60sIGxvcyBzY3JpcHRzIHF1ZSBjcmVlbW9zIGFob3JhLCBzZSBjcmVhcsOhbiBkaXJlY3RhbWVudGUgZW4gbGEgY2FycGV0YSBkZWwgcHJveWVjdG8uIFlhIHBhcmxhcmVtIG3DqHMgZGUgY8OzbW8gaW50ZXJhY3R1YXIgY29uIGxvcyBScHJvamVjdHMgZW4gY2xhc2UuCgoKUG9kZW1vcyBwZW5zYXIgcXVlIHVuIFJwcm9qZWN0IG5vIGVzIG3DoXMgcXVlIHVuYSBjYXJwZXRhIGVuIG51ZXN0cm8gb3JkZW5hZG9yLiBEZSBoZWNobyBwdWVkZXMgYnVzY2FyIGxhIGNhcnBldGEgZGUgdHUgcHJveWVjdG8gZW4gdHUgb3JkZW5hZG9yIHkgbWFuaXB1bGFybGEgY29tbyBoYWNlcyBjb24gY3VhbHF1aWVyIGNhcnBldGEgZGUgdHUgb3JkZW5hZG9yOyBlcyBkZWNpciwgcHVlZGVzIGFicmlybGEsIG1vdmVybGEsIGNhbWJpYXJsZSBlbCBub21icmUsIGNyZWFyIHN1YmNhcnBldGFzLCBjcmVhciBhcmNoaXZvcywgYm9ycmFyIGFyY2hpdm9zIG8gYm9ycmFyIHRvZGEgbGEgY2FycGV0YS4gKipJbnNpc3RvKiosIHBhcmEgdHUgc2lzdGVtYSBvcGVyYXRpdm8gZXMgdW5hIGNhcnBldGEgY29tbyBjdWFscXVpZXIgb3RyYS4gRGUgbW9tZW50byBlc2EgY2FycGV0YSBzb2xvIGNvbnRpZW5lIHVuIGFyY2hpdm8gZGUgdGV4dG8gY29uIGV4dGVuc2nDs24gKiouUnByb2oqKiwgcG9jbyBhIHBvY28gbGEgaXJlbW9zIGxsZW5hbmRvIGNvbiBsb3MgYXJjaGl2b3MgZGUgbnVlc3RybyBwcm95ZWN0byAoZGF0b3MsIHNjcmlwdHMsIGV0YyAuLi4pCgoKTGEgY2FycGV0YSBkZWwgcHJveWVjdG8gZXMgdW5hIGNhcnBldGEgbm9ybWFsIHBhcmEgdHUgc2lzdGVtYSBvcGVyYXRpdm8sIHBlcm8gbm8gZXMgdW5hIGNhcnBldGEgbm9ybWFsIHBhcmEgUlN0dWRpby4gU2kgdmFzIGEgbGEgY2FycGV0YSBkZSB0dSBwcm95ZWN0byB5IHBpbmNoYXMgZW4gZWwgYXJjaGl2byAibXlfcHJpbWVyX3Byb3llY3RvLlByb2oiIHNlIGFicmlyw6EgUlN0dWRpbywgeSBSU3R1ZGlvIHJlY29ub2NlcsOhIGVzYSBjYXJwZXRhIGNvbW8gdW4gcHJveWVjdG87IGVzIGRlY2lyLCBlbnRyZSBvdHJhcyBjb3NhcyBmaWphcsOhIGVsIGRpcmVjdG9yaW8gZGUgdHJhYmFqbyBhIGxhIHByb3BpYSBjYXJwZXRhIGRlbCBwcm95ZWN0byB5IHBvZHJlbW9zIHVzYXIgcnV0YXMgcmVsYXRpdmFzLiAKCgoKYGBge3IsIGVjaG8gPSBGQUxTRX0Ka25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoaGVyZTo6aGVyZSgiaW1hZ2VuZXMiLCAidHRfMDJfaW1nXzA5X215X1Jwcm9qZWN0LTIucG5nIikgKSAKYGBgCgoqKkFjdcOpcmRhdGUgc2llbXByZSBkZSBsYW56YXIgdW4gcHJveWVjdG8gcGluY2hhbmRvIGVuIGVsIGFyY2hpdm8gY29uIGV4dGVuc2nDs24gIi5ScHJvaiIgISEhISoqIEhheSBvdHJhcyBmb3JtYXMgZGUgbGFuemFyIGVsIHByb3llY3RvIHBlcm8gZGUgbW9tZW50byB1c2FyZW1vcyBlc3RhLgoKCiMjIyDCv1BvciBxdcOpIHVzYW1vcyBScHJvamVjdHM/CgpHZXN0aW9uYXIgdHVzIGFuw6FsaXNpcyB1dGlsaXphbmRvIFJwcm9qZWN0cyB0aWVuZSB2ZW50YWphczoKCjEpIHB1ZWRlcyBnZXN0aW9uYXIgdmFyaW9zIHByb3llY3RvcyBhIGxhIHZleiwgY2FkYSB1bm8gY29uIHN1IGVzcGFjaW8gZGUgdHJhYmFqbyAow7MgZW52aXJvbm1lbnQpLCBwZXJvIHNvYnJlIHRvZG8sCgoyKSBmYWNpbGl0YSBlbCBjb21wYXJ0aXIgdHVzIGFuw6FsaXNpczsgZXMgZGVjaXIsIGZhdm9yZWNlIGxhIGludmVzdGlnYWNpw7NuIHJlcHJvZHVjaWJsZS4KCgpQb2RlbW9zIHBlbnNhciBxdWUgdW4gUnByb2plY3QgZXMgdW5hIGNhcnBldGEsIHBlcm8gZXMgbcOhcyBxdWUgZXNvOiBjYWRhIFJwcm9qZWN0IHRpZW5lIHN1IHByb3BpbyBkaXJlY3RvcmlvIGRlIHRyYWJham8sIGVzcGFjaW8gZGUgdHJhYmFqbyAoZW52aXJvbm1lbnQpLCBoaXN0b3JpYWwgZGUgaW5zdHJ1Y2Npb25lczsgYWRlbcOhcywgcGVybWl0ZSBjcmVhciB1bmEgZXN0cnVjdHVyYSBkZSBjYXJwZXRhcyBkb25kZSBndWFyZGFyIGxvcyBkb2N1bWVudG9zIGFzb2NpYWRvcyBhbCBwcm95ZWN0byBlbiBjYXJwZXRhcyBzZXBhcmFkYXMgKHAuZWo6IHVuYSBjYXJwZXRhIHBhcmEgZGF0b3MsIG90cmEgcGFyYSBpbcOhZ2VuZXMsIC4uLikuCgpDdWFuZG8gYWJyZXMgdW4gUnByb2plY3QgZW4gUlN0dWRpbyAocGluY2hhbmRvIGVuIGVsIGZpY2hlcm8gYC5ScHJvamApIG9jdXJyZSBsbyBzaWd1aWVudGU6ICAKCiAgIC0gQ29taWVuemEgdW4gbnVldm8gcHJvY2VzbyBkZSBSIChlc3RvIHRhbWJpw6luIGVzIGltcG9ydGFudGUgcGFyYSBsYSBpbnZlc3RpZ2FjacOzbiByZXByb2R1Y2libGUpCiAgIAogICAtIEVsIGRpcmVjdG9yaW8gZGUgdHJhYmFqbyBzZSBmaWphIGEgbGEgY2FycGV0YSBxdWUgY29udGllbmUgZWwgUnByb2plY3QsIGNvbiBsbyBxdWUgcG9kZW1vcyB1c2FyIHJ1dGFzIHJlbGF0aXZhcyAocmVsYXRpdmFzIGEgbGEgY2FycGV0YSBkZWwgcHJveWVjdG8pCiAgIAogICAKICAgPGJyPgogICAKICAgCiMjIyMgQ3VpZGFkbyBjb24gbG9zIHBhdGhzISEKCi0gVW4gZ3JhbiBpbmNvbnZlbmllbnRlIHBhcmEgY29uc2VndWlyIGluZm9ybWVzIChwbGVuYW1lbnRlKSByZXByb2R1Y2libGVzIHNvbiBsb3MgcGF0aHMgbyBydXRhcyBkZSBmaWNoZXJvcy4gU2kgdW4gcHJvZ3JhbWEgbmVjZXNpdGEgbGxhbWFyIGEgdW4gZmljaGVybyBkZSBkYXRvcyAocG9yIGVqZW1wbG8gcGFyYSBjYXJnYXIgdW5vcyBkYXRvcyksIHRlbmRyw6FzIHF1ZSBlc3BlY2lmaWNhciBsYSBydXRhIHkgc2kgYWxndWllbiBxdWllcmUgZWplY3V0YXIgdHVzICpzY3JpcHRzKiBlbiAqKnN1Kiogb3JkZW5hZG9yIGRlYmVyw6EgY2FtYmlhciBsYSBydXRhLgoKLSBUcmFiYWphciBjb24gUnByb2plY3RzIHBlcm1pdGUgc29sdmVudGFyIGVzdGUgcHJvYmxlbWEsIHlhIHF1ZSBlbCBkaXJlY3RvcmlvIGRlIHRyYWJham8gZGVsIFJwcm9qZWN0IGNvaW5jaWRlIGNvbiBsYSBjYXJwZXRhIGRvbmRlIGVzdMOhIGFsb2phZG8gZWwgUnByb2plY3QgeSBlc3RvIHBlcm1pdGUgKHlhIGxvIHZlcmVtb3MgZW4gZWwgcHLDs3hpbW8gdHV0b3JpYWwpIHRyYWJhamFyIGNvbiBydXRhcyAobyBwYXRocykgcmVsYXRpdmFzIGVuIGx1Z2FyIGRlIGFic29sdXRhcy4gKCEhKQoKPGJyPgoKLSBFbiBwYWxhYnJhcyBkZSBbSmVubnkgQnJ5YW5dKGh0dHBzOi8vZ2l0aHViLmNvbS9qZW5ueWJjKSB1bmEgZGUgbWlzIGhlKipSKipvw61uYXMgeSBkZXN0YWNhZGEgbWllbWJybyBkZSBsYSBjb211bmlkYWQgUiwgc2kgZW1waWV6YXMgdHVzIHNjcmlwdHMgY29uIGBzZXR3ZCgpYCwgc2lnbmlmaWNhIHF1ZSBlc3TDoXMgdXNhbmRvIHJ1dGFzIGFic29sdXRhcywgcHVlZGVzIGhhY2VybG8sIHBlcm8gSmVubnkgbm9zIGFjb25zZWphIHF1ZSAuLi4gICoqUExFQVNFIFNUT1AgRE9JTkcgVEhBVCAhISoqIEFkZW1hcyBKZW5ueSBub3MgbG8gZXhwbGljYToKCiAgPiBUaGlzIG1ha2VzIHlvdXIgc2NyaXB0IHZlcnkgZnJhZ2lsZSwgaGFyZC13aXJlZCB0byBleGFjdGx5IG9uZSB0aW1lIGFuZCBwbGFjZS4gQXMgc29vbiBhcyB5b3UgcmVuYW1lIG9yIG1vdmUgZGlyZWN0b3JpZXMsIGl0IGJyZWFrcy4gT3IgbWF5YmUgeW91IGdldCBhIG5ldyBjb21wdXRlcj8gT3IgbWF5YmUgc29tZW9uZSBlbHNlIG5lZWRzIHRvIHJ1biB5b3VyIGNvZGU/IAoKLSBQYXJhIEplbm55IGxhIHNvbHVjacOzbiBlcyAgdXNhciBlbCBwa2cgYGhlcmVgLCB5IHRpZW5lIHJhesOzbiwgcGVybyBub3NvdHJvcyAoZGUgbW9tZW50bykgc8OzbG8gdXNhcmVtb3MgUnByb2plY3RzIChzdWZpY2llbnRlISEpLiBgciBlbW86OmppKCJ0aGlua2luZyIpYCAuIEJ1ZW5vIG5vLCBlc28gZXJhIGVuIGVsIGN1cnNvIHBhcmEgcHJvZmVzb3JlcywgYSB2b3NvdHJvcyBzw60gcXVlIG9zIHZlbyBjYXBhY2l0YWRvcyBwYXJhIGFwcmVuZGVyIGNvbW8gdXNhciBgaGVyZTo6aGVyZSgpYC4gYHIgZW1vOjpqaSgiZGV2aWwiKWAgIGByIGVtbzo6amkoImxvbCIpYCAuICBMbyB2ZXJlbW9zLiBFbCBxdWUgdGVuZ2EgY3VyaW9zaWRhZCBwdWVkZSBsZWVyIGVuIFtlc3RlIHBvc3RdKGh0dHBzOi8vbWFsY28uaW8vMjAxOC8xMS8wNS93aHktc2hvdWxkLWktdXNlLXRoZS1oZXJlLXBhY2thZ2Utd2hlbi1pLW0tYWxyZWFkeS11c2luZy1wcm9qZWN0cy8pIHBvcnF1w6ksIGEgcGVzYXIgZGUgdHJhYmFqYXIgY29uIFJwcm9qZWN0cywgdGllbmUgdmVudGFqYXMgZXNwZWNpZmljYXIgbGFzIHJ1dGFzIGNvbiBlbCBwYXF1ZXRlIGBoZXJlYC4KCgoKPGJyPgoKICAgCiMjIDQuIFJNYXJrZG93biAoYXJjaGl2b3MgKiouUm1kKiopCgpTw60sIHlhIHNhYmVtb3MgcXVlIHRyYWJhamFyZW1vcyBjb24gUnByb2plY3RzLiBPSywgcGVybyB0YW1iacOpbiBkaWplIHF1ZSBtdWNoYXMgdmVjZXMgZW4gbHVnYXIgZGUgZGFyIGxhcyBpbnN0cnVjY2lvbmVzIGEgUiBwb3IgbWVkaW8gZGUgc2NyaXB0cyBvIGZpY2hlcm9zIGAuUmAsIHRyYWJhamFyw61hbW9zIGNvbiBmaWNoZXJvcyBgUm1hcmtkb3duYC4gRXN0b3MgZmljaGVyb3MgUm1hcmtkb3duIHRpZW5lbiBleHRlbnNpw7NuIGAuUm1kYC4KCi0gTG9zIGRvY3VtZW50b3MgKipSTWFya2Rvd24qKiBzb24gZmljaGVyb3MgY29uIGV4dGVuc2nDs24gKipgLlJtZGAqKi4KCi0gU2kgYWNhYmFzIHV0aWxpemFuZG8gUiBwYXJhIGhhY2VyIGFuw6FsaXNpcyBlc3RhZMOtc3RpY29zLCBsb3MgZmljaGVyb3MgYC5SbWRgIHRlIHBlcm1pdGlyw6FuIGVzY3JpYmlyIG11eS1tdXkgZsOhY2lsbWVudGUgaW5mb3JtZXMsIHR1dG9yaWFsZXMgeSB0cmFuc3BhcmVuY2lhcyBwYXJhIHByZXNlbnRhY2lvbmVzLiAgCgotIEVzdG9zIGZpY2hlcm9zIC5SbWQgc29uIChwbGVuYW1lbnRlKSByZXByb2R1Y2libGVzLgoKLSBMbyB2ZXJlbW9zLCBwZXJvIGVuIGVzb3MgZmljaGVyb3MgLlJtZCBzZSBtZXpjbGFuIHRyb3pvcyBkZSAgdGV4dG8gZXNjcml0b3MgZW4gTWFya2Rvd24gKG5hcnJhdGl2ZXMpIHkgdHJvem9zIGNvbiBjw7NkaWdvIFIgKGNodW5rcykgcGFyYSBoYWNlciBhbsOhbGlzaXMgZXN0YWTDrXN0aWNvcy4KCi0gRXN0b3MgZmljaGVyb3Mgc2UgcHJvY2VzYW4gY29uIHVuIHBhcXVldGUgZGUgUiBsbGFtYWRvIGBrbml0cmAgZGVzYXJyb2xsYWRvIHBvciBbWWlodWkgWGllXShodHRwczovL3lpaHVpLm5hbWUva25pdHIvKSAuLi4geSBzYWxlbiB1bm9zIGluZm9ybWVzIG8gdHJhbnNwYXJlbmNpYXMgZmFudMOhc3RpY2FzIC4uLiBlbiB1bmEgZ3JhbiB2YXJpZWRhZCBkZSBmb3JtYXRvcy4KCi0gQ29uIFJTdHVkaW8gZXMgbXV5IGbDoWNpbDogc29sbyBoYXkgcXVlIHVzYXIgbG9zIG1lbsO6cyBkZXNwbGVnYWJsZXMgZGUgUlN0dWRpbyBwYXJhIGNyZWFyIHVuIGRvY3VtZW50byBSbWFya2Rvd24sIGVzY3JpYmlyIGxvIHF1ZSBxdWllcmVzIGNvbnRhciB5IGRhcmxlIGFsIGJvdMOzbiBLbml0ciB5IGBrbml0cmAgdGVqZXLDoSBlbCBkb2N1bWVudG8geSBsbyB0cmFuc2Zvcm1hcsOhIGEgLi4uLiBwZGYsIHdvcmQsIGh0bWwgLi4uCgoKPGJyPgoKClRhcmRhcmVtb3MgdW5hcyAzLTQgY2xhc2VzIGVuIGV4cGxpY2FyIGVuIGRldGFsbGUgcXXDqSBzb24geSBwYXJhIHF1ZSBzaXJ2ZW4gbG9zIGZpY2hlcm9zIFJtYXJrZG93biwgcGVybyB2YW1vcyB5YSBhIGNyZWFyIHVuby4gUGFyYSBlbGxvIHRpZW5lcyBxdWUgc2VndWlyIGVuIFJTdHVkaW8gZXN0YSBydXRhIGRlIG1lbsO6czogYEZpbGUgPiBOZXcgRmlsZSA+IFIgTWFya2Rvd24uLi5gLiBWaXN1YWxtZW50ZToKCgpgYGB7ciwgZWNobyA9IEZBTFNFfQprbml0cjo6aW5jbHVkZV9ncmFwaGljcyhoZXJlOjpoZXJlKCJpbWFnZW5lcyIsICJ0dF8wMl9pbWdfMTBfUm1kLTEucG5nIikgKSAKYGBgCgoKClNlIGFicmlyw6EgdW5hIHZlbnRhbmEuIERlIG1vbWVudG8gbm8gY2FtYmllcyBuYWRhLCBzw7NsbyBwaW5jaGEgZW4gYE9LYC4gCgoKYGBge3IsIGVjaG8gPSBGQUxTRX0Ka25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoaGVyZTo6aGVyZSgiaW1hZ2VuZXMiLCAidHRfMDJfaW1nXzEwX1JtZC0yLnBuZyIpICkgCmBgYAoKVmVyw6FzIHF1ZSBzZSBoYSBhYmllcnRvIHVuYSBwZXN0YcOxYSBlbiBlbCBlZGl0b3IgZGUgUlN0dWRpbyAoYXJyaWJhLWl6cXVpZXJkYSksIGNvbiBsbyBxdWUgcGFyZWNlIHF1ZSBzb24gbXVjaGFzIGxpbmVhcyBkZSBjw7NkaWdvIFIuIFPDrSwgaGEgY3JlYWRvIHBhcmEgbm9zb3Ryb3MgdW4gYXJjaGl2byBgLlJtZGAgeSBoYSBwdWVzdG8gdW5hcyBsaW5lYXMgZGUgY8OzZGlnbyBxdWUgbm9zIHNpcnZlbiBjb21vIGVqZW1wbG8gZGUgY8OzbW8gc2UgZXNjcmliZSBlbiBSbWFya2Rvd24uIFlhIGxvIHZlcmVtb3MuIFZpc3VhbG1lbnRlOgoKCmBgYHtyLCBlY2hvID0gRkFMU0V9CmtuaXRyOjppbmNsdWRlX2dyYXBoaWNzKGhlcmU6OmhlcmUoImltYWdlbmVzIiwgInR0XzAyX2ltZ18xMF9SbWQtMy5wbmciKSApIApgYGAKCgpFc3RvcyBmaWNoZXJvcyBgLlJtZGAgc2UgZWplY3V0YW4gZGUgb3RyYSBmb3JtYS4gVGllbmVzIHF1ZSBwaW5jaGFyIGVuIGVsIGljb25vIHF1ZSBwb25lIGBLbml0YC4gVmlzdWFsbWVudGU6IAoKCmBgYHtyLCBlY2hvID0gRkFMU0V9CmtuaXRyOjppbmNsdWRlX2dyYXBoaWNzKGhlcmU6OmhlcmUoImltYWdlbmVzIiwgInR0XzAyX2ltZ18xMF9SbWQtNC5wbmciKSApIApgYGAKCgpBcGFyZWNlcsOhIHVuYSB2ZW50YW5hIHBpZGnDqW5kb3RlIHF1ZSBsZSBwb25nYXMgdW4gbm9tYnJlIGFsIGZpY2hlcm8gYC5SbWRgLiBDb21vIHB1ZWRlcyB2ZXIgYWJham8geW8gbGUgcHVzZSBlbCBub21icmUgInBhcmFfYm9ycmFyIiwgcGVybyBwdWVkZXMgcG9uZXIgZWwgbm9tYnJlIHF1ZSBxdWllcmFzLgoKCmBgYHtyLCBlY2hvID0gRkFMU0V9CmtuaXRyOjppbmNsdWRlX2dyYXBoaWNzKGhlcmU6OmhlcmUoImltYWdlbmVzIiwgInR0XzAyX2ltZ18xMF9SbWQtNS5wbmciKSApIApgYGAKCgpVbmEgdmV6IGxlIGhheWFzIHB1ZXN0byBub21icmUuIFIgZWplY3V0YXLDoSB0b2RhcyBsYXMgaW5zdHJ1Y2Npb25lcyBxdWUgaGF5IGVuIGVsIGZpY2hlcm8gLlJtZCB5IGdlbmVyYXLDoSB1biBudWV2byBkb2N1bWVudG8gcXVlIHBvZHLDoXMgdmVyIGVuIGVsIHBhbmVsIGRlIGFiYWpvLWRlcmVjaGEuIEFkZW3DoXMgc2kgcGluY2hhcyBlbiBlbCBpY29ubyBxdWUgYXBhcmVjZSBtYXJjYWRvIGNvbiB1bmEgbWFubyggcGFuZWwgYWJham8tZGVyZWNoYSkgZW4gbGEgaW1hZ2VuIGRlIGFiYWpvIHBvZHLDoXMgdmVybG8gZW4gdHUgbmF2ZWdhZG9yLiBWaXN1YWxtZW50ZToKCgoKYGBge3IsIGVjaG8gPSBGQUxTRX0Ka25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoaGVyZTo6aGVyZSgiaW1hZ2VuZXMiLCAidHRfMDJfaW1nXzEwX1JtZC02LnBuZyIpICkgCmBgYAoKRHVyYW50ZSBlbCBjdXJzbyB2YW1vcyAgYSB0cmFiYWphciBtdWNobyBjb24gZmljaGVyb3MgLlJtZCwgYXPDrSBxdWUgdGVuZHJlbW9zIHF1ZSBleHBsaWNhcmxvcy9lbnRlbmRlcmxvcyBiaWVuLiBQZXJvIHNlcsOhIG90cm8gZMOtYS9sZXNzb24uIFNpIG9zIGFwZXRlY2UgcG9kw6lpcyB2ZXIgW2VzdGUgdmlkZW9dKGh0dHBzOi8vd3d3LnlvdXR1YmUuY29tL3dhdGNoP3Y9bE5XVlEyb3hOaG8pIGRvbmRlIHNlIGV4cGxpY2EgbGFzIHZlbnRhamFzIGRlIHRyYWJhamFyIGVuIGNvbiBmaWNoZXJvcyBSbWFya2Rvdy4gSWd1YWwgbWHDsWFuYSBsbyBwcmVndW50by4KCgoKPGJyPjxicj4KCgpQYXJhIGZpbmFsaXphciB1biBjb25zZWpvOiBlc3RhbW9zIGVtcGV6YW5kbywgYXPDrSBxdWUgUEFUSUVOQ0UhISEgY3Vlc3RhIHVuIHBvY28gYXByZW5kZXIvZW1wZXphciBjb24gUi4gQWRlbcOhcyB0b2RvIGVsIG11bmRvIGNvbWV0ZSBlcnJvcmVzLCBwZXJvIGxhIG1heW9yw61hIGRlIGxvcyBlcnJvcmVzIHNvbiAidG9udG9zIi4gRXNvIHPDrSwgdGVuw6lpcyBxdWUgZW50ZW5kZXIgbGFzIGlkZWFzIGLDoXNpY2FzOiBzY3JpcHQsIC5SLCAuUm1kLCBScHJvamVjdCwgcnV0YXMgcmVsYXRpdmFzIGV0Yy4uLiBzaSBubyBsbyBlbnRpZW5kZXMsIG5vIGxvIGRlamVzIHBhc2FyLCBwcmVnw7pudGFsbyBlbiBjbGFzZSwgc2VndXJvIHF1ZSBtw6FzIGRlIHVubyB0ZSBsbyBhZ3JhZGVjZSBvIHBvZGVtb3MgYXJyZWdsYXJsbyBlbiB0dXRvcsOtYXMsIHBlcm8gbm8gbG8gZGVqZXMgcGFzYXIuCgoKYGBge3IsIGVjaG8gPSBGQUxTRX0KdHdlZXRybWQ6OnR3ZWV0X2VtYmVkKCJodHRwczovL3R3aXR0ZXIuY29tL2FsbGlzb25faG9yc3Qvc3RhdHVzLzEyMTMyNzU3ODM2NzU4MjIwODAiLCAgYWxpZ24gPSAiY2VudGVyIiwgZG50ID0gVFJVRSwgcGxhaW4gPSBUUlVFLCBtYXh3aWR0aCA9IDcwMCkKYGBgCgo8YnI+PGJyPg==