Es posible que en tu trabajo tengas que presentar informes o resultados de tu análisis de datos. Tal vez te hayas encontrando guardando una y otra vez gráficos y tablas o copiando resultados de un archivo al otro hasta que el informe quedó como querías. Los archivos y el paquete RMarkdown vienen al rescate.

Un archivo RMarkdown a diferencia de un script .R permite incluir código en bloques o chunks y texto plano o con formato simple de leer usando markdown. A poder intercalar cálculos y gráficos con su análisis o explicación, se unifica el flujo de trabajo y deja de ser necesario guardar figuras o tablas para luego insertarlas en un documento de texto. Esto es muy importante si buscamos que nuestro trabajo sea reproducible, pero además ahorra tiempo.

Aún si nunca necesitaras presentar un informe, trabajar con archivos de este tipo te permite volcar todo tu trabajo en un solo lugar y te asegura que cundo vuelvas a revisar mañana o el año que viene, tendrás el código y tus ideas organizadas.

Creando archivos .Rmd

Para crear un nuevo archivo de R Markdown usá el menú desplegable de RStudio:

File → New File → R Markdown

Y se abrirá un menú donde podés agregar el título y tu nombre. Por ahora vamos a usar el formato html como salida, charlaremos de las distintas posibilidades que ofrece más adelante.

Al aceptar, se abrirá un nuevo archivo pero que no está vacío. RStudio ofrece una plantilla a partir de la cual empezar a trabajar.

Primer desafío: Crea un nuevo archivo R Markdown

Revisá la plantilla que trae el documento. ¿Podés identificar los bloques de código?

Para generar el archivo de salida el paquete knitr (que viene de tejer en inglés) y algunos otros ejecutará el código en una sesión independiente de R e interpretará el texto, su formato y cualquier otra cosa que agreguemos (por ejemplo imágenes o links externos). Esto significa que nuestro archivo debe tener todo lo necesario para generar el análisis y si nos olvidamos de algo va a dar error.

Por esta razón es recomendable knitear el archivo seguido, para encontrarnos con los errores a tiempo y de paso asegurarnos que el análisis es reproducible.

Segundo desafío: “knitea” tu R Markdown

Aprovechando la plantilla de RStudio, obtené el archivo de salida en formato html haciendo click en el botón knit (el que tiene un ovillo de lana y un par de agujas!)

Estructura de un .Rmd

Cualquier archivo de este tipo tiene 3 partes principales:

  • El encabezado o yaml que determina que pinta tendrá el archivo de salida, por ejemplo en formato html. También se puede incluir información sobre el autor, la fecha, si queremos o no una tabla de contenidos y muchas cosas más.
  • El texto o textos ya que puede estar a lo largo de todo el documento. Para darle formato a los títulos o por ejemplo resaltar parte del texto usando negrita se usa Markdown, un lenguaje que a diferencia de html es legible aún si no está compilado o en su versión final.
  • El código en bloques o chuncks. Dentro de un chunk el código de R puede ejecutarse al igual que en un script normal y cualquier comentario o explicación debe tener al principio un # para que R lo interprete correctamente.

Podés encontrar este archivo de ejemplo acá.

Al agregar nuevas opciones en el YAML, se crean jerarquías que se identifican escalonando (o indentando) los renglones. Por ejemplo:

---
title: "Mi primer RMarkdown"
output: 
  html_document:
    code_download: true
    toc: true
    toc_float: true
---

Es muy importante que no modifiques esto ya que de otra forma al hacer knit dará error.

Markdown

Markdown permite escribir una página web al igual que html pero de manera simple de leer. Si nuestro archivo de salida es un html, luego el paquete knitr se encargará de reemplazar las marcas de markdown por el código de html correspondiente. Pero como dijimos más arriba también será posible generar otro tipo de archivos de salida.

Por ejemplo podrás resaltar con negrita usando dos asteriscos así: **negrita** o italizada con un asterisco de cada lado: *italics*.

También podés hacer una lista de elementos utilizando asteriscos:

* la negrita se consigue con dos asteriscos
* la italizada con un asterisco
* y para resaltar código se usa el acento grave `

o guiones medios:

- la negrita se consigue con dos asteriscos
- la italizada con un asterisco
- y para resaltar código se usa el acento grave `

Ambas listas van a tener esta pita:

  • la negrita se consigue con dos asteriscos
  • la italizada con un asterisco
  • y para resaltar código se usa el acento grave `

Si en realidad querés una lista numerada, simplemente comenzá el renglón un número y un punto. Podrías usar siempre el mismo número, markdown se encarga del resto:

1. la negrita se consigue con dos asteriscos
1. la italizada con un asterisco
1. y para resaltar código se usa el acento grave `

Ahora la lista numerada se ve así:

  1. la negrita se consigue con dos asteriscos
  2. la italizada con un asterisco
  3. y para resaltar código se usa el acento grave `

Podés agregar títulos con distinta jerarquía agregando # al comienzo. Esto además define secciones dentro del documento:

# Título
## El primer subtítulo
### Otro subtítulo de menor jerarquía
#### Otro más, y podría seguir!

Tercer desafío: Agregale texto a tu archivo

Borrá el contenido del archivo .Rmd que creaste (pero no el encabezado!) y probá escribir algo y darle formato. Luego volvé a apretar el botón knit para ver el resultado.

Markdown permite muchas otras cosas, por ejemplo:

Podés agregar un link a una página externa: [text to show](http://the-web-page.com).

Podés incluir una imagen: ![pie de figura](http://url/for/file)

Y también podés agregar ecuaciones en LaTeX en la misma línea (esto:$E = mc^2$ se ve así: \(E = mc^2\)) o en una línea propia. Esto:

$$
y = \mu + \sum_{i=1}^p \beta_i x_i + \epsilon
$$

se ve así:

\[ y = \mu + \sum_{i=1}^p \beta_i x_i + \epsilon \]

Podés revisar la guía rápida de Markdown desde RStudio (en inglés):

Help → Markdown Quick Reference

Bloques de código

Los bloques de código o chunks se definen usando 3 acentos grave al principio y al final:

```{r nombre-del-chunk}

```

Y se diferencia del resto de archivo con un fondo gris.

Para insertar un nuevo chunk podés:

  • Usar el botón Insert
  • El atajo de teclado Ctrl+Alt+I
  • Escribir a mano!

Como viste en el ejemplo, los chucks pueden tener nombre y esto es útil para identificar donde ocurren los errores al momento de knitear pero también para tener una pista de lo que hace el código que incluye.

Todo lo que incluyas entre los acentos graves será interpretado por R como código e intentará ejecutarlo al knitear el archivo. Pero también podemos correr el código interactivamente como en la consola, con la diferencia de que ahora el resultado (ya sea un valor, un gráfico o cualquier otra cosa) aparecerá inmediatamente por debajo del bloque de código. Para correr una línea de código, tendrás que pararte sobre esa línea y apretar:

Ctrl+Enter

Pero también podés correr el código de todo el chunk con:

Ctrl+Shift+Enter

Cuarto desafío: Sumá un chunk a tu archivo

Usando el archivo con el que venís trabajando insertá un nuevo chunk y:

  1. Cargá la librería readr.
  2. Creá una variable que se llame variable_prueba y asignale un valor.
  3. Mostrá ese valor.
  4. Volvé a knitear el archivo para ver el resultado

Texto en línea

Finalmente es posible que te encuentres mencionando resultados en el texto, por ejemplo algo así como “la media de temperatura mínima para el mes de marzo fue de 18 grados”. Y también es posible que ese valor cambie si utilizas una base de datos distinta o si luego generas un informe pero para un mes siguiente. Las chances de de que te olvides de actualizar ese “18” son super altas, por eso RMarkdown también tiene la posibilidad de incorporar texto en línea.

Imaginemos que tenés una variables temperatura a la cual le asignamos el valor “18”:

temperatura <- 18

Para mencionarla en el texto entonces tenemos que poner el nombre de esa variable entre dos acentos graves y avisar que se trata de código de R des esta manera `r temperatura`. Entonces si en algún momento cambia el valor de la variable, la próxima vez que knites el documento se actualizará en el texto.

LS0tCnRpdGxlOiAiSW50cm9kdWNjacOzbiBhIHtSTWFya2Rvd259IgpvdXRwdXQ6IAogIGh0bWxfZG9jdW1lbnQ6CiAgICBjb2RlX2Rvd25sb2FkOiB0cnVlCiAgICB0b2M6IHRydWUKICAgIHRvY19mbG9hdDogdHJ1ZQogICAgaGlnaGxpZ2h0OiB0YW5nbwotLS0KCmBgYHtyIHNldHVwLCBpbmNsdWRlPUZBTFNFfQprbml0cjo6b3B0c19jaHVuayRzZXQoZWNobyA9IFRSVUUpCmBgYAoKRXMgcG9zaWJsZSBxdWUgZW4gdHUgdHJhYmFqbyB0ZW5nYXMgcXVlIHByZXNlbnRhciBpbmZvcm1lcyBvIHJlc3VsdGFkb3MgZGUgdHUgYW7DoWxpc2lzIGRlIGRhdG9zLiBUYWwgdmV6IHRlIGhheWFzIGVuY29udHJhbmRvIGd1YXJkYW5kbyB1bmEgeSBvdHJhIHZleiBncsOhZmljb3MgeSB0YWJsYXMgbyBjb3BpYW5kbyByZXN1bHRhZG9zIGRlIHVuIGFyY2hpdm8gYWwgb3RybyBoYXN0YSBxdWUgZWwgaW5mb3JtZSBxdWVkw7MgY29tbyBxdWVyw61hcy4gTG9zIGFyY2hpdm9zIHkgZWwgcGFxdWV0ZSBgUk1hcmtkb3duYCB2aWVuZW4gYWwgcmVzY2F0ZS4gCgpVbiBhcmNoaXZvIGBSTWFya2Rvd25gIGEgZGlmZXJlbmNpYSBkZSB1biBzY3JpcHQgYC5SYCBwZXJtaXRlIGluY2x1aXIgY8OzZGlnbyBlbiBibG9xdWVzIG8gKmNodW5rcyogeSB0ZXh0byBwbGFubyBvIGNvbiBmb3JtYXRvIHNpbXBsZSBkZSBsZWVyIHVzYW5kbyBbbWFya2Rvd25dKGh0dHBzOi8vbWFya2Rvd24uZXMvc2ludGF4aXMtbWFya2Rvd24vKS4gQSBwb2RlciBpbnRlcmNhbGFyIGPDoWxjdWxvcyB5IGdyw6FmaWNvcyBjb24gc3UgYW7DoWxpc2lzIG8gZXhwbGljYWNpw7NuLCBzZSB1bmlmaWNhIGVsIGZsdWpvIGRlIHRyYWJham8geSBkZWphIGRlIHNlciBuZWNlc2FyaW8gZ3VhcmRhciBmaWd1cmFzIG8gdGFibGFzIHBhcmEgbHVlZ28gaW5zZXJ0YXJsYXMgZW4gdW4gZG9jdW1lbnRvIGRlIHRleHRvLiBFc3RvIGVzIG11eSBpbXBvcnRhbnRlIHNpIGJ1c2NhbW9zIHF1ZSBudWVzdHJvIHRyYWJham8gc2VhIHJlcHJvZHVjaWJsZSwgcGVybyBhZGVtw6FzIGFob3JyYSB0aWVtcG8uIAoKQcO6biBzaSBudW5jYSBuZWNlc2l0YXJhcyBwcmVzZW50YXIgdW4gaW5mb3JtZSwgdHJhYmFqYXIgY29uIGFyY2hpdm9zIGRlIGVzdGUgdGlwbyB0ZSBwZXJtaXRlIHZvbGNhciB0b2RvIHR1IHRyYWJham8gZW4gdW4gc29sbyBsdWdhciB5IHRlIGFzZWd1cmEgcXVlIGN1bmRvIHZ1ZWx2YXMgYSByZXZpc2FyIG1hw7FhbmEgbyBlbCBhw7FvIHF1ZSB2aWVuZSwgdGVuZHLDoXMgZWwgY8OzZGlnbyB5IHR1cyBpZGVhcyBvcmdhbml6YWRhcy4KCiMjIyBDcmVhbmRvIGFyY2hpdm9zIC5SbWQKClBhcmEgY3JlYXIgdW4gbnVldm8gYXJjaGl2byBkZSBSIE1hcmtkb3duIHVzw6EgZWwgbWVuw7ogZGVzcGxlZ2FibGUgZGUgUlN0dWRpbzoKCjo6OiB7LmFsZXJ0IC5hbGVydC1zZWNvbmRhcnl9CkZpbGUg4oaSIE5ldyBGaWxlIOKGkiBSIE1hcmtkb3duCjo6OgoKWSBzZSBhYnJpcsOhIHVuIG1lbsO6IGRvbmRlIHBvZMOpcyBhZ3JlZ2FyIGVsIHTDrXR1bG8geSB0dSBub21icmUuIFBvciBhaG9yYSB2YW1vcyBhIHVzYXIgZWwgZm9ybWF0byBodG1sIGNvbW8gc2FsaWRhLCBjaGFybGFyZW1vcyBkZSBsYXMgZGlzdGludGFzIHBvc2liaWxpZGFkZXMgcXVlIG9mcmVjZSBtw6FzIGFkZWxhbnRlLiAKCiFbXShpbWcvbnVldm8tcm1kLnBuZykKCkFsIGFjZXB0YXIsIHNlIGFicmlyw6EgdW4gbnVldm8gYXJjaGl2byBwZXJvIHF1ZSBubyBlc3TDoSB2YWPDrW8uIFJTdHVkaW8gb2ZyZWNlIHVuYSBwbGFudGlsbGEgYSBwYXJ0aXIgZGUgbGEgY3VhbCBlbXBlemFyIGEgdHJhYmFqYXIuIAoKOjo6IHsuYWxlcnQgLmFsZXJ0LWluZm99CioqUHJpbWVyIGRlc2Fmw61vOiBDcmVhIHVuIG51ZXZvIGFyY2hpdm8gUiBNYXJrZG93bioqCgpSZXZpc8OhIGxhIHBsYW50aWxsYSBxdWUgdHJhZSBlbCBkb2N1bWVudG8uIMK/UG9kw6lzIGlkZW50aWZpY2FyIGxvcyBibG9xdWVzIGRlIGPDs2RpZ28/Cjo6OgoKUGFyYSBnZW5lcmFyIGVsIGFyY2hpdm8gZGUgc2FsaWRhIGVsIHBhcXVldGUgYGtuaXRyYCAocXVlIHZpZW5lIGRlICp0ZWplciogZW4gaW5nbMOpcykgeSBhbGd1bm9zIG90cm9zIGVqZWN1dGFyw6EgZWwgY8OzZGlnbyBlbiB1bmEgc2VzacOzbiBpbmRlcGVuZGllbnRlIGRlIFIgZSBpbnRlcnByZXRhcsOhIGVsIHRleHRvLCBzdSBmb3JtYXRvIHkgY3VhbHF1aWVyIG90cmEgY29zYSBxdWUgYWdyZWd1ZW1vcyAocG9yIGVqZW1wbG8gaW3DoWdlbmVzIG8gbGlua3MgZXh0ZXJub3MpLiBFc3RvIHNpZ25pZmljYSBxdWUgbnVlc3RybyBhcmNoaXZvIGRlYmUgdGVuZXIgKip0b2RvKiogbG8gbmVjZXNhcmlvIHBhcmEgZ2VuZXJhciBlbCBhbsOhbGlzaXMgeSBzaSBub3Mgb2x2aWRhbW9zIGRlIGFsZ28gdmEgYSBkYXIgZXJyb3IuIAoKUG9yIGVzdGEgcmF6w7NuIGVzIHJlY29tZW5kYWJsZSAqa25pdGVhciogZWwgYXJjaGl2byBzZWd1aWRvLCBwYXJhIGVuY29udHJhcm5vcyBjb24gbG9zIGVycm9yZXMgYSB0aWVtcG8geSBkZSBwYXNvIGFzZWd1cmFybm9zIHF1ZSBlbCBhbsOhbGlzaXMgZXMgcmVwcm9kdWNpYmxlLiAKCjo6OiB7LmFsZXJ0IC5hbGVydC1pbmZvfQoqKlNlZ3VuZG8gZGVzYWbDrW86ICJrbml0ZWEiIHR1IFIgTWFya2Rvd24qKgoKQXByb3ZlY2hhbmRvIGxhIHBsYW50aWxsYSBkZSBSU3R1ZGlvLCBvYnRlbsOpIGVsIGFyY2hpdm8gZGUgc2FsaWRhIGVuIGZvcm1hdG8gaHRtbCBoYWNpZW5kbyBjbGljayBlbiBlbCBib3TDs24gKiprbml0KiogKGVsIHF1ZSB0aWVuZSB1biBvdmlsbG8gZGUgbGFuYSB5IHVuIHBhciBkZSBhZ3VqYXMhKQo6OjoKCiMjIyBFc3RydWN0dXJhIGRlIHVuIC5SbWQKCkN1YWxxdWllciBhcmNoaXZvIGRlIGVzdGUgdGlwbyB0aWVuZSAzIHBhcnRlcyBwcmluY2lwYWxlczoKCi0gIEVsIGVuY2FiZXphZG8gbyAqeWFtbCogcXVlIGRldGVybWluYSBxdWUgcGludGEgdGVuZHLDoSBlbCBhcmNoaXZvIGRlIHNhbGlkYSwgcG9yIGVqZW1wbG8gZW4gZm9ybWF0byBodG1sLiBUYW1iacOpbiBzZSBwdWVkZSBpbmNsdWlyIGluZm9ybWFjacOzbiBzb2JyZSBlbCBhdXRvciwgbGEgZmVjaGEsIHNpIHF1ZXJlbW9zIG8gbm8gdW5hIHRhYmxhIGRlIGNvbnRlbmlkb3MgeSBtdWNoYXMgY29zYXMgbcOhcy4gCi0gRWwgdGV4dG8gbyB0ZXh0b3MgeWEgcXVlIHB1ZWRlIGVzdGFyIGEgbG8gbGFyZ28gZGUgdG9kbyBlbCBkb2N1bWVudG8uIFBhcmEgZGFybGUgZm9ybWF0byBhIGxvcyB0w610dWxvcyBvIHBvciBlamVtcGxvIHJlc2FsdGFyIHBhcnRlIGRlbCB0ZXh0byB1c2FuZG8gbmVncml0YSBzZSB1c2EgYE1hcmtkb3duYCwgdW4gKmxlbmd1YWplKiBxdWUgYSBkaWZlcmVuY2lhIGRlIGh0bWwgZXMgbGVnaWJsZSBhw7puIHNpIG5vIGVzdMOhIGNvbXBpbGFkbyBvIGVuIHN1IHZlcnNpw7NuIGZpbmFsLiAKLSBFbCBjw7NkaWdvIGVuIGJsb3F1ZXMgbyBgY2h1bmNrc2AuIERlbnRybyBkZSB1biBjaHVuayBlbCBjw7NkaWdvIGRlIFIgcHVlZGUgZWplY3V0YXJzZSBhbCBpZ3VhbCBxdWUgZW4gdW4gc2NyaXB0IG5vcm1hbCB5IGN1YWxxdWllciBjb21lbnRhcmlvIG8gZXhwbGljYWNpw7NuIGRlYmUgdGVuZXIgYWwgcHJpbmNpcGlvIHVuIGAjYCBwYXJhIHF1ZSBSIGxvIGludGVycHJldGUgY29ycmVjdGFtZW50ZS4gCgohW10oaW1nL3JtZC1lamVtcGxvLXNlY2Npb25lcy5wbmcpCgpQb2TDqXMgZW5jb250cmFyIGVzdGUgYXJjaGl2byBkZSBlamVtcGxvIFthY8OhXShmaWxlcy9taS1wcmltZXItcm1hcmtkb3duLlJtZCkuCgo6Ojogey5hbGVydCAuYWxlcnQtc3VjY2Vzc30KQWwgYWdyZWdhciBudWV2YXMgb3BjaW9uZXMgZW4gZWwgWUFNTCwgc2UgY3JlYW4gamVyYXJxdcOtYXMgcXVlIHNlIGlkZW50aWZpY2FuIGVzY2Fsb25hbmRvIChvICppbmRlbnRhbmRvKikgbG9zIHJlbmdsb25lcy4gUG9yIGVqZW1wbG86CgpgYGB5YW1sCi0tLQp0aXRsZTogIk1pIHByaW1lciBSTWFya2Rvd24iCm91dHB1dDogCiAgaHRtbF9kb2N1bWVudDoKICAgIGNvZGVfZG93bmxvYWQ6IHRydWUKICAgIHRvYzogdHJ1ZQogICAgdG9jX2Zsb2F0OiB0cnVlCi0tLQpgYGAKRXMgbXV5IGltcG9ydGFudGUgcXVlIG5vIG1vZGlmaXF1ZXMgZXN0byB5YSBxdWUgZGUgb3RyYSBmb3JtYSBhbCBoYWNlciBga25pdGAgZGFyw6EgZXJyb3IuCjo6OgoKIyMjIE1hcmtkb3duCgpNYXJrZG93biBwZXJtaXRlIGVzY3JpYmlyIHVuYSBww6FnaW5hIHdlYiBhbCBpZ3VhbCBxdWUgaHRtbCBwZXJvIGRlIG1hbmVyYSBzaW1wbGUgZGUgbGVlci4gU2kgbnVlc3RybyBhcmNoaXZvIGRlIHNhbGlkYSBlcyB1biBodG1sLCBsdWVnbyBlbCBwYXF1ZXRlIGBrbml0cmAgc2UgZW5jYXJnYXLDoSBkZSByZWVtcGxhemFyIGxhcyBtYXJjYXMgZGUgbWFya2Rvd24gcG9yIGVsIGPDs2RpZ28gZGUgaHRtbCBjb3JyZXNwb25kaWVudGUuIFBlcm8gY29tbyBkaWppbW9zIG3DoXMgYXJyaWJhIHRhbWJpw6luIHNlcsOhIHBvc2libGUgZ2VuZXJhciBvdHJvIHRpcG8gZGUgYXJjaGl2b3MgZGUgc2FsaWRhLiAKClBvciBlamVtcGxvIHBvZHLDoXMgcmVzYWx0YXIgY29uICoqbmVncml0YSoqIHVzYW5kbyBkb3MgYXN0ZXJpc2NvcyBhc8OtOiBgKipuZWdyaXRhKipgIG8gKml0YWxpemFkYSogY29uIHVuIGFzdGVyaXNjbyBkZSBjYWRhIGxhZG86IGAqaXRhbGljcypgLgoKVGFtYmnDqW4gcG9kw6lzIGhhY2VyIHVuYSBsaXN0YSBkZSBlbGVtZW50b3MgdXRpbGl6YW5kbyBhc3RlcmlzY29zOgoKYGBgCiogbGEgbmVncml0YSBzZSBjb25zaWd1ZSBjb24gZG9zIGFzdGVyaXNjb3MKKiBsYSBpdGFsaXphZGEgY29uIHVuIGFzdGVyaXNjbwoqIHkgcGFyYSByZXNhbHRhciBjw7NkaWdvIHNlIHVzYSBlbCBhY2VudG8gZ3JhdmUgYApgYGAKCm8gZ3Vpb25lcyBtZWRpb3M6CgpgYGAKLSBsYSBuZWdyaXRhIHNlIGNvbnNpZ3VlIGNvbiBkb3MgYXN0ZXJpc2NvcwotIGxhIGl0YWxpemFkYSBjb24gdW4gYXN0ZXJpc2NvCi0geSBwYXJhIHJlc2FsdGFyIGPDs2RpZ28gc2UgdXNhIGVsIGFjZW50byBncmF2ZSBgCmBgYApBbWJhcyBsaXN0YXMgdmFuIGEgdGVuZXIgZXN0YSBwaXRhOgoKLSBsYSBuZWdyaXRhIHNlIGNvbnNpZ3VlIGNvbiBkb3MgYXN0ZXJpc2NvcwotIGxhIGl0YWxpemFkYSBjb24gdW4gYXN0ZXJpc2NvCi0geSBwYXJhIHJlc2FsdGFyIGPDs2RpZ28gc2UgdXNhIGVsIGFjZW50byBncmF2ZSBgCgpTaSBlbiByZWFsaWRhZCBxdWVyw6lzIHVuYSBsaXN0YSBudW1lcmFkYSwgc2ltcGxlbWVudGUgY29tZW56w6EgZWwgcmVuZ2zDs24gdW4gbsO6bWVybyB5IHVuIHB1bnRvLiBQb2Ryw61hcyB1c2FyIHNpZW1wcmUgZWwgbWlzbW8gbsO6bWVybywgbWFya2Rvd24gc2UgZW5jYXJnYSBkZWwgcmVzdG86CgpgYGAKMS4gbGEgbmVncml0YSBzZSBjb25zaWd1ZSBjb24gZG9zIGFzdGVyaXNjb3MKMS4gbGEgaXRhbGl6YWRhIGNvbiB1biBhc3RlcmlzY28KMS4geSBwYXJhIHJlc2FsdGFyIGPDs2RpZ28gc2UgdXNhIGVsIGFjZW50byBncmF2ZSBgCmBgYAoKQWhvcmEgbGEgbGlzdGEgbnVtZXJhZGEgc2UgdmUgYXPDrToKCjEuIGxhIG5lZ3JpdGEgc2UgY29uc2lndWUgY29uIGRvcyBhc3RlcmlzY29zCjEuIGxhIGl0YWxpemFkYSBjb24gdW4gYXN0ZXJpc2NvCjEuIHkgcGFyYSByZXNhbHRhciBjw7NkaWdvIHNlIHVzYSBlbCBhY2VudG8gZ3JhdmUgYAoKUG9kw6lzIGFncmVnYXIgdMOtdHVsb3MgY29uIGRpc3RpbnRhIGplcmFycXXDrWEgYWdyZWdhbmRvIGAjYCBhbCBjb21pZW56by4gRXN0byBhZGVtw6FzIGRlZmluZSBzZWNjaW9uZXMgZGVudHJvIGRlbCBkb2N1bWVudG86CgpgYGAKIyBUw610dWxvCiMjIEVsIHByaW1lciBzdWJ0w610dWxvCiMjIyBPdHJvIHN1YnTDrXR1bG8gZGUgbWVub3IgamVyYXJxdcOtYQojIyMjIE90cm8gbcOhcywgeSBwb2Ryw61hIHNlZ3VpciEKYGBgCgo6Ojogey5hbGVydCAuYWxlcnQtaW5mb30KKipUZXJjZXIgZGVzYWbDrW86IEFncmVnYWxlIHRleHRvIGEgdHUgYXJjaGl2byoqCgpCb3Jyw6EgZWwgY29udGVuaWRvIGRlbCBhcmNoaXZvIGAuUm1kYCBxdWUgY3JlYXN0ZSAocGVybyBubyBlbCBlbmNhYmV6YWRvISkgeSBwcm9iw6EgZXNjcmliaXIgYWxnbyB5IGRhcmxlIGZvcm1hdG8uIEx1ZWdvIHZvbHbDqSBhIGFwcmV0YXIgZWwgYm90w7NuICoqa25pdCoqIHBhcmEgdmVyIGVsIHJlc3VsdGFkby4KOjo6CgpNYXJrZG93biBwZXJtaXRlIG11Y2hhcyBvdHJhcyBjb3NhcywgcG9yIGVqZW1wbG86CgpQb2TDqXMgYWdyZWdhciB1biBsaW5rIGEgdW5hIHDDoWdpbmEgZXh0ZXJuYTogYFt0ZXh0IHRvIHNob3ddKGh0dHA6Ly90aGUtd2ViLXBhZ2UuY29tKWAuCgpQb2TDqXMgaW5jbHVpciB1bmEgaW1hZ2VuOiBgIVtwaWUgZGUgZmlndXJhXShodHRwOi8vdXJsL2Zvci9maWxlKWAKClkgdGFtYmnDqW4gcG9kw6lzIGFncmVnYXIgZWN1YWNpb25lcyBlbiBMYVRlWCBlbiBsYSBtaXNtYSBsw61uZWEgKGVzdG86YCRFID0gbWNeMiRgIHNlIHZlIGFzw606ICRFID0gbWNeMiQpIG8gZW4gdW5hIGzDrW5lYSBwcm9waWEuIEVzdG86CgpgYGAKJCQKeSA9IFxtdSArIFxzdW1fe2k9MX1ecCBcYmV0YV9pIHhfaSArIFxlcHNpbG9uCiQkCmBgYAoKc2UgdmUgYXPDrToKCiQkCnkgPSBcbXUgKyBcc3VtX3tpPTF9XnAgXGJldGFfaSB4X2kgKyBcZXBzaWxvbgokJAoKCgo6Ojogey5hbGVydCAuYWxlcnQtc3VjY2Vzc30KUG9kw6lzIHJldmlzYXIgbGEgZ3XDrWEgcsOhcGlkYSBkZSBNYXJrZG93biBkZXNkZSBSU3R1ZGlvIChlbiBpbmdsw6lzKToKCkhlbHAg4oaSIE1hcmtkb3duIFF1aWNrIFJlZmVyZW5jZSAKOjo6CgojIyMgQmxvcXVlcyBkZSBjw7NkaWdvCgpMb3MgYmxvcXVlcyBkZSBjw7NkaWdvIG8gKipjaHVua3MqKiBzZSBkZWZpbmVuIHVzYW5kbyAzIGFjZW50b3MgZ3JhdmUgYWwgcHJpbmNpcGlvIHkgYWwgZmluYWw6CgpgYGBgbWFya2Rvd24KYHIgJydgYGBge3Igbm9tYnJlLWRlbC1jaHVua30KCmBgYApgYGBgCgpZIHNlIGRpZmVyZW5jaWEgZGVsIHJlc3RvIGRlIGFyY2hpdm8gY29uIHVuIGZvbmRvIGdyaXMuIAoKOjo6IHsuYWxlcnQgLmFsZXJ0LXN1Y2Nlc3N9ClBhcmEgaW5zZXJ0YXIgdW4gbnVldm8gY2h1bmsgcG9kw6lzOgoKKiBVc2FyIGVsIGJvdMOzbiAqKkluc2VydCoqCiogRWwgYXRham8gZGUgdGVjbGFkbyBDdHJsK0FsdCtJIAoqIEVzY3JpYmlyIGEgbWFubyEKOjo6CgpDb21vIHZpc3RlIGVuIGVsIGVqZW1wbG8sIGxvcyBjaHVja3MgcHVlZGVuIHRlbmVyIG5vbWJyZSB5IGVzdG8gZXMgw7p0aWwgcGFyYSBpZGVudGlmaWNhciBkb25kZSBvY3VycmVuIGxvcyBlcnJvcmVzIGFsIG1vbWVudG8gZGUgKmtuaXRlYXIqIHBlcm8gdGFtYmnDqW4gcGFyYSB0ZW5lciB1bmEgcGlzdGEgZGUgbG8gcXVlIGhhY2UgZWwgY8OzZGlnbyBxdWUgaW5jbHV5ZS4gCgpUb2RvIGxvIHF1ZSBpbmNsdXlhcyBlbnRyZSBsb3MgYWNlbnRvcyBncmF2ZXMgc2Vyw6EgaW50ZXJwcmV0YWRvIHBvciBSIGNvbW8gY8OzZGlnbyBlIGludGVudGFyw6EgZWplY3V0YXJsbyBhbCAqa25pdGVhciogZWwgYXJjaGl2by4gUGVybyB0YW1iacOpbiBwb2RlbW9zIGNvcnJlciBlbCBjw7NkaWdvIGludGVyYWN0aXZhbWVudGUgY29tbyBlbiBsYSBjb25zb2xhLCBjb24gbGEgZGlmZXJlbmNpYSBkZSBxdWUgYWhvcmEgZWwgcmVzdWx0YWRvICh5YSBzZWEgdW4gdmFsb3IsIHVuIGdyw6FmaWNvIG8gY3VhbHF1aWVyIG90cmEgY29zYSkgYXBhcmVjZXLDoSBpbm1lZGlhdGFtZW50ZSBwb3IgZGViYWpvIGRlbCBibG9xdWUgZGUgY8OzZGlnby4gUGFyYSBjb3JyZXIgdW5hIGzDrW5lYSBkZSBjw7NkaWdvLCB0ZW5kcsOhcyBxdWUgcGFyYXJ0ZSBzb2JyZSBlc2EgbMOtbmVhIHkgYXByZXRhcjogCgo6Ojogey5hbGVydCAuYWxlcnQtc2Vjb25kYXJ5fQpDdHJsK0VudGVyCjo6OgoKUGVybyB0YW1iacOpbiBwb2TDqXMgY29ycmVyIGVsIGPDs2RpZ28gZGUgdG9kbyBlbCBjaHVuayBjb246Cgo6Ojogey5hbGVydCAuYWxlcnQtc2Vjb25kYXJ5fQpDdHJsK1NoaWZ0K0VudGVyCjo6OgoKOjo6IHsuYWxlcnQgLmFsZXJ0LWluZm99CioqQ3VhcnRvIGRlc2Fmw61vOiBTdW3DoSB1biBjaHVuayBhIHR1IGFyY2hpdm8qKgoKVXNhbmRvIGVsIGFyY2hpdm8gY29uIGVsIHF1ZSB2ZW7DrXMgdHJhYmFqYW5kbyBpbnNlcnTDoSB1biBudWV2byBjaHVuayB5OgoKMS4gQ2FyZ8OhIGxhIGxpYnJlcsOtYSBgcmVhZHJgLgoyLiBDcmXDoSB1bmEgdmFyaWFibGUgcXVlIHNlIGxsYW1lIGB2YXJpYWJsZV9wcnVlYmFgIHkgYXNpZ25hbGUgdW4gdmFsb3IuCjMuIE1vc3Ryw6EgZXNlIHZhbG9yLgo0LiBWb2x2w6kgYSAqa25pdGVhciogZWwgYXJjaGl2byBwYXJhIHZlciBlbCByZXN1bHRhZG8KOjo6CgojIyMgVGV4dG8gZW4gbMOtbmVhCgpGaW5hbG1lbnRlIGVzIHBvc2libGUgcXVlIHRlIGVuY3VlbnRyZXMgbWVuY2lvbmFuZG8gcmVzdWx0YWRvcyBlbiBlbCB0ZXh0bywgcG9yIGVqZW1wbG8gYWxnbyBhc8OtIGNvbW8gImxhIG1lZGlhIGRlIHRlbXBlcmF0dXJhIG3DrW5pbWEgcGFyYSBlbCBtZXMgZGUgbWFyem8gZnVlIGRlIDE4IGdyYWRvcyIuIFkgdGFtYmnDqW4gZXMgcG9zaWJsZSBxdWUgZXNlIHZhbG9yIGNhbWJpZSBzaSB1dGlsaXphcyB1bmEgYmFzZSBkZSBkYXRvcyBkaXN0aW50YSBvIHNpIGx1ZWdvIGdlbmVyYXMgdW4gaW5mb3JtZSBwZXJvIHBhcmEgdW4gbWVzIHNpZ3VpZW50ZS4gTGFzIGNoYW5jZXMgZGUgZGUgcXVlIHRlIG9sdmlkZXMgZGUgYWN0dWFsaXphciBlc2UgIjE4IiBzb24gc3VwZXIgYWx0YXMsIHBvciBlc28gUk1hcmtkb3duIHRhbWJpw6luIHRpZW5lIGxhIHBvc2liaWxpZGFkIGRlIGluY29ycG9yYXIgdGV4dG8gZW4gbMOtbmVhLiAKCkltYWdpbmVtb3MgcXVlIHRlbsOpcyB1bmEgdmFyaWFibGVzIGB0ZW1wZXJhdHVyYWAgYSBsYSBjdWFsIGxlIGFzaWduYW1vcyBlbCB2YWxvciAiMTgiOgoKYGBge3J9CnRlbXBlcmF0dXJhIDwtIDE4CmBgYAoKUGFyYSBtZW5jaW9uYXJsYSBlbiBlbCB0ZXh0byBlbnRvbmNlcyB0ZW5lbW9zIHF1ZSBwb25lciBlbCBub21icmUgZGUgZXNhIHZhcmlhYmxlIGVudHJlIGRvcyBhY2VudG9zIGdyYXZlcyB5IGF2aXNhciBxdWUgc2UgdHJhdGEgZGUgY8OzZGlnbyBkZSBSIGRlcyBlc3RhIG1hbmVyYSBgYCBgYHIgInIiYCB0ZW1wZXJhdHVyYWAgYGAuIEVudG9uY2VzIHNpIGVuIGFsZ8O6biBtb21lbnRvIGNhbWJpYSBlbCB2YWxvciBkZSBsYSB2YXJpYWJsZSwgbGEgcHLDs3hpbWEgdmV6IHF1ZSAqa25pdGVzKiBlbCBkb2N1bWVudG8gc2UgYWN0dWFsaXphcsOhIGVuIGVsIHRleHRvLiAKCgo8ZGl2IGNsYXNzPSJidG4tZ3JvdXAiIHJvbGU9Imdyb3VwIiBhcmlhLWxhYmVsPSJOYXZlZ2FjacOzbiI+CiAgPGEgaHJlZj0gIjAyLXByb3llY3Rvcy5odG1sIiBjbGFzcyA9ICJidG4gYnRuLXByaW1hcnkiPkFudGVyaW9yPC9hPgogIDxhIGhyZWY9ICIwNC1sZWN0dXJhLmh0bWwiIGNsYXNzID0gImJ0biBidG4tcHJpbWFyeSI+U2lndWllbnRlPC9hPgo8L2Rpdj4KCg==