¿Por qué R?

Las hojas de cálculo son un software admirable. Son geniales para cargar datos, para ver los datos crudos y para hacer gráficos rápidos. Si venís usándolo hace tiempo, seguro que aprendiste un montón de trucos para sacarle el jugo al máximo, habrás aprendido a usar fórmulas, tablas dinámicas, e incluso macros. Pero seguro que también sufriste sus limitaciones.

En una hoja de cálculo no hay un límite claro entre datos y análisis. Sobrescribir datos es un peligro muy real y análisis complicados son imposibles de entender, especialmente si abrís una hoja de cálculo armada por otra persona (que quizás es tu vos del pasado). Además, repetir el análisis en datos distintos o cambiando algún parámetro se puede volver muy engorroso.

Si lo que necesitás son reportes frecuentes y automáticos, y análisis de datos con muchas partes móviles, estaría bueno poder escribir una receta paso a paso y que la computadora corra todo automáticamente cada vez que se lo pedís. Para poder hacer eso, ese paso a paso tiene que estar escrito en un lenguaje que la computadora pueda entender, ese lenguaje es R.

¿Cómo vamos a trabajar?

Vamos a usar R como lenguaje de programación y RStudio como una IDE (Integrated Development Environment), un Entorno Integrado de Desarrollo. Si no los tenés instalado en tu computadora, no te preocupes, tenemos este proyecto en Posit Cloud para que puedas trabajar.

Para iniciar RStudio, hacé doble click en el ícono de RStudio. Iniciar RStudio también inicia R (en realidad, es probable que nunca abras R por sí mismo).

Pantalla principal de RStudio. Paneles de consola, entorno y archivos

Pantalla principal de Posit Cloud. Paneles de consola, entorno y archivos

Observa los paneles por defecto:

No es necesario que sepamos utilizar todo esto de inmediato. Nos familiarizaremos con más opciones y capacidades a lo largo del taller.

Podemos escribir código, es decir, instrucciones para ser ejecutadas por R en la Consola. Por ejemplo, podemos calcular el resultado dos más dos escribiendo

2 + 2
## [1] 4

en la Consola y pulsando enter.

El resultado aparece justo debajo. También podemos guardar ese resultado en un objeto, en este caso llamado x.

x <- 2 + 2 

Esa flechita es el operador de asignación y funciona como un =. Ahora el resultado se guarda en el Entorno (Environment) como una variable con nombre x y no se imprime en la consola.

Esto es útil cuando estamos probando el código para ver si funciona pero lo perderemos todo cuando cerremos RStudio. Lo que tenemos que hacer es guardar el código que genera su análisis. Para ello utilizamos R Scripts y archivos RMarkdown.

Vamos a tener nuestra primera experiencia con R a través de RMarkdown, así que vamos a ver qué es un documento RMarkdown. Te preparamos este informe de ejemplo, por favor abrilo en RStudio o en Posit Cloud. El archivo aparecerá en un nuevo panel arriba en el lado izquierdo de la pantalla, y el panel de la consola se moverá hacia abajo.

RMarkdown

Un archivo RMarkdown es un archivo de texto plano, con algunas reglas y una sintaxis especial que nos permite escribir código y texto juntos. Cuando se “teje” (knit), el código se evaluará y ejecutará y el texto se formateará de manera que se cree un informe o documento reproducible que sea agradable de leer y que contenga todo tu trabajo.

Esto es realmente crítico para la reproducibilidad. También nos ahorra tiempo y puede ayudar en las tareas de automatización. Este documento recreará tus figuras por ti en el mismo documento donde estás escribiendo el texto que las explica. Esto le ahorrará el esfuerzo de hacer un análisis, guardar un gráfico en un archivo, copiar y pegar ese gráfico en Word o Power Point o Google Slides, y tener que hacerlo todo de nuevo después de descubrir un error tipográfico.

Ahora veamos cómo es nuestro Informe de Pingüinos.

Sigamos adelante y “tejamos (knit)” el documento haciendo clic en el ovillo de hilo azul () en la parte superior del archivo RMarkdown.

¡Acabamos de crear un archivo html! Se trata de una única página web que estamos viendo localmente en nuestros propios ordenadores. Al generar este documento RMarkdown, R ha formateado el texto markdown y ha ejecutado el código R.

Rmarkdown a la izquierda. Documento generado a la derecha

Texto markdown

Podes ver una guia sobre rmakdown en esta guía rápida, pero aquí hay una sintaxis mínima para empezar:

  • encabezados empiezan con # o ##y asi siguiendo (es importante poner un espacio después del último #).
  • las palabras en negrita están rodeadas de **
  • y las cursiva, con _

Código de R

El código R se escribe dentro de “chunks (trozos)” de código. Los trozos de código comienzan con ```{r label} (donde “label” es un nombre opcional y único) y terminan con ```. En RStudio, podes crear un nuevo chunk con el atajo de teclado Ctrl + Alt + I.

Este informe muestra información sobre los pingüinos Papúa, pero podríamos cambiar algunas líneas de código para crear el mismo análisis para las otras dos especies, Adelia y Barbijo.

Ahora es tu turno. Sigue buscando en el código, si encuentras alguna mención a “Papúa”, cámbiala por cualquiera de las otras especies.

Esta tarea es un poco engorrosa si hay que cambiar muchas cosas cada vez que queremos volver a ejecutar el análisis para diferentes especies. Pero no te preocupes, aprenderemos a hacer todo más automático al final del taller.

LS0tDQp0aXRsZTogIkludHJvZHVjY2nDs24geSBSZXBvcnRlcyINCm91dHB1dDogDQogIGh0bWxfZG9jdW1lbnQ6DQogICAgY29kZV9kb3dubG9hZDogdHJ1ZQ0KICAgIHRvYzogdHJ1ZQ0KICAgIHRvY19mbG9hdDogZmFsc2UNCiAgICBoaWdobGlnaHQ6IHRhbmdvDQotLS0NCg0KIyMgwr9Qb3IgcXXDqSBSPw0KDQpMYXMgaG9qYXMgZGUgY8OhbGN1bG8gc29uIHVuIHNvZnR3YXJlIGFkbWlyYWJsZS4gU29uIGdlbmlhbGVzIHBhcmEgY2FyZ2FyIGRhdG9zLCBwYXJhIHZlciBsb3MgZGF0b3MgY3J1ZG9zIHkgcGFyYSBoYWNlciBncsOhZmljb3MgcsOhcGlkb3MuIFNpIHZlbsOtcyB1c8OhbmRvbG8gaGFjZSB0aWVtcG8sIHNlZ3VybyBxdWUgYXByZW5kaXN0ZSB1biBtb250w7NuIGRlIHRydWNvcyBwYXJhIHNhY2FybGUgZWwganVnbyBhbCBtw6F4aW1vLCBoYWJyw6FzIGFwcmVuZGlkbyBhIHVzYXIgZsOzcm11bGFzLCB0YWJsYXMgZGluw6FtaWNhcywgZSBpbmNsdXNvIG1hY3Jvcy4gUGVybyBzZWd1cm8gcXVlIHRhbWJpw6luIHN1ZnJpc3RlIHN1cyBsaW1pdGFjaW9uZXMuDQoNCkVuIHVuYSBob2phIGRlIGPDoWxjdWxvIG5vIGhheSB1biBsw61taXRlIGNsYXJvIGVudHJlIGRhdG9zIHkgYW7DoWxpc2lzLiBTb2JyZXNjcmliaXIgZGF0b3MgZXMgdW4gcGVsaWdybyBtdXkgcmVhbCB5IGFuw6FsaXNpcyBjb21wbGljYWRvcyBzb24gaW1wb3NpYmxlcyBkZSBlbnRlbmRlciwgZXNwZWNpYWxtZW50ZSBzaSBhYnLDrXMgdW5hIGhvamEgZGUgY8OhbGN1bG8gYXJtYWRhIHBvciBvdHJhIHBlcnNvbmEgKHF1ZSBxdWl6w6FzIGVzIHR1IHZvcyBkZWwgcGFzYWRvKS4gQWRlbcOhcywgcmVwZXRpciBlbCBhbsOhbGlzaXMgZW4gZGF0b3MgZGlzdGludG9zIG8gY2FtYmlhbmRvIGFsZ8O6biBwYXLDoW1ldHJvIHNlIHB1ZWRlIHZvbHZlciBtdXkgZW5nb3Jyb3NvLg0KDQpTaSBsbyBxdWUgbmVjZXNpdMOhcyBzb24gcmVwb3J0ZXMgZnJlY3VlbnRlcyB5IGF1dG9tw6F0aWNvcywgeSBhbsOhbGlzaXMgZGUgZGF0b3MgY29uIG11Y2hhcyBwYXJ0ZXMgbcOzdmlsZXMsIGVzdGFyw61hIGJ1ZW5vIHBvZGVyIGVzY3JpYmlyIHVuYSByZWNldGEgcGFzbyBhIHBhc28geSBxdWUgbGEgY29tcHV0YWRvcmEgY29ycmEgdG9kbyBhdXRvbcOhdGljYW1lbnRlIGNhZGEgdmV6IHF1ZSBzZSBsbyBwZWTDrXMuIFBhcmEgcG9kZXIgaGFjZXIgZXNvLCBlc2UgcGFzbyBhIHBhc28gdGllbmUgcXVlIGVzdGFyIGVzY3JpdG8gZW4gdW4gbGVuZ3VhamUgcXVlIGxhIGNvbXB1dGFkb3JhIHB1ZWRhIGVudGVuZGVyLCBlc2UgbGVuZ3VhamUgZXMgUi4NCg0KIyMgwr9Dw7NtbyB2YW1vcyBhIHRyYWJhamFyPw0KDQpWYW1vcyBhIHVzYXIgUiBjb21vIGxlbmd1YWplIGRlIHByb2dyYW1hY2nDs24geSBSU3R1ZGlvIGNvbW8gdW5hIElERSAoSW50ZWdyYXRlZCBEZXZlbG9wbWVudCBFbnZpcm9ubWVudCksIHVuIEVudG9ybm8gSW50ZWdyYWRvIGRlIERlc2Fycm9sbG8uIFNpIG5vIGxvcyB0ZW7DqXMgaW5zdGFsYWRvIGVuIHR1IGNvbXB1dGFkb3JhLCBubyB0ZSBwcmVvY3VwZXMsIHRlbmVtb3MgZXN0ZSAgW3Byb3llY3RvIGVuIFBvc2l0IENsb3VkXShodHRwczovL3Bvc2l0LmNsb3VkL2NvbnRlbnQvNDA0NjA0NCkgcGFyYSBxdWUgcHVlZGFzIHRyYWJhamFyLg0KDQpQYXJhIGluaWNpYXIgUlN0dWRpbywgaGFjw6kgZG9ibGUgY2xpY2sgZW4gZWwgw61jb25vIGRlIFJTdHVkaW8uIEluaWNpYXIgIFJTdHVkaW8gdGFtYmnDqW4gaW5pY2lhIFIgKGVuIHJlYWxpZGFkLCBlcyBwcm9iYWJsZSBxdWUgbnVuY2EgYWJyYXMgUiBwb3Igc8OtIG1pc21vKS4NCg0KDQo8aW1nIHNyYz0iaW1nL3JzdHVkaW8tcHJpbmNpcGFsLnBuZyIgYWx0PSJQYW50YWxsYSBwcmluY2lwYWwgZGUgUlN0dWRpby4gUGFuZWxlcyBkZSBjb25zb2xhLCBlbnRvcm5vIHkgYXJjaGl2b3MiIC8+DQoNCjxpbWcgc3JjPSJpbWcvcnN0dWRpby1jbG91ZC1wcmluY2lwYWwucG5nIiBhbHQ9IlBhbnRhbGxhIHByaW5jaXBhbCBkZSBQb3NpdCBDbG91ZC4gUGFuZWxlcyBkZSBjb25zb2xhLCBlbnRvcm5vIHkgYXJjaGl2b3MiIC8+DQoNCk9ic2VydmEgbG9zIHBhbmVsZXMgcG9yIGRlZmVjdG86DQoNCiAgKiBDb25zb2xhICh0b2RhIGxhIGl6cXVpZXJkYSkNCiAgKiBFbnZpcm9ubWVudC9IaXN0b3J5IChwZXN0YcOxYSBlbiBsYSBwYXJ0ZSBzdXBlcmlvciBkZXJlY2gpDQogICogRmlsZXMvUGxvdHMvUGFja2FnZXMvSGVscCAoY29uIHBlc3Rhw7FhcyBlbiBsYSBwYXJ0ZSBpbmZlcmlvciBkZXJlY2hhKQ0KDQpObyBlcyBuZWNlc2FyaW8gcXVlIHNlcGFtb3MgdXRpbGl6YXIgdG9kbyBlc3RvIGRlIGlubWVkaWF0by4gTm9zIGZhbWlsaWFyaXphcmVtb3MgY29uIG3DoXMgb3BjaW9uZXMgeSBjYXBhY2lkYWRlcyBhIGxvIGxhcmdvIGRlbCB0YWxsZXIuDQoNClBvZGVtb3MgZXNjcmliaXIgY8OzZGlnbywgZXMgZGVjaXIsIGluc3RydWNjaW9uZXMgcGFyYSBzZXIgZWplY3V0YWRhcyBwb3IgUiBlbiBsYSBDb25zb2xhLiBQb3IgZWplbXBsbywgcG9kZW1vcyBjYWxjdWxhciBlbCByZXN1bHRhZG8gZG9zIG3DoXMgZG9zIGVzY3JpYmllbmRvDQoNCmBgYHtyfQ0KMiArIDINCmBgYA0KDQplbiBsYSBDb25zb2xhIHkgcHVsc2FuZG8gZW50ZXIuIA0KDQpFbCByZXN1bHRhZG8gYXBhcmVjZSBqdXN0byBkZWJham8uIFRhbWJpw6luIHBvZGVtb3MgZ3VhcmRhciBlc2UgcmVzdWx0YWRvIGVuIHVuIG9iamV0bywgZW4gZXN0ZSBjYXNvIGxsYW1hZG8gYHhgLg0KDQpgYGB7cn0NCnggPC0gMiArIDIgDQpgYGANCg0KRXNhIGZsZWNoaXRhIGVzIGVsICpvcGVyYWRvciBkZSBhc2lnbmFjacOzbiogeSBmdW5jaW9uYSBjb21vIHVuIGA9YC4gQWhvcmEgZWwgcmVzdWx0YWRvIHNlIGd1YXJkYSBlbiBlbCBFbnRvcm5vIChFbnZpcm9ubWVudCkgY29tbyB1bmEgdmFyaWFibGUgY29uIG5vbWJyZSBgeGAgeSBubyBzZSBpbXByaW1lIGVuIGxhIGNvbnNvbGEuIA0KDQpFc3RvIGVzIMO6dGlsIGN1YW5kbyBlc3RhbW9zIHByb2JhbmRvIGVsIGPDs2RpZ28gcGFyYSB2ZXIgc2kgZnVuY2lvbmEgcGVybyBsbyBwZXJkZXJlbW9zIHRvZG8gY3VhbmRvIGNlcnJlbW9zIFJTdHVkaW8uIExvIHF1ZSB0ZW5lbW9zIHF1ZSBoYWNlciBlcyBndWFyZGFyIGVsIGPDs2RpZ28gcXVlIGdlbmVyYSBzdSBhbsOhbGlzaXMuIFBhcmEgZWxsbyB1dGlsaXphbW9zIFIgU2NyaXB0cyB5IGFyY2hpdm9zIFJNYXJrZG93bi4NCg0KVmFtb3MgYSB0ZW5lciBudWVzdHJhIHByaW1lcmEgZXhwZXJpZW5jaWEgY29uIFIgYSB0cmF2w6lzIGRlIFJNYXJrZG93biwgYXPDrSBxdWUgdmFtb3MgYSB2ZXIgcXXDqSBlcyB1biBkb2N1bWVudG8gUk1hcmtkb3duLiBUZSBwcmVwYXJhbW9zIFtlc3RlIGluZm9ybWUgZGUgZWplbXBsb10ocmVwb3J0ZV9waW5ndWlub3MuUm1kKSwgcG9yIGZhdm9yIGFicmlsbyBlbiBSU3R1ZGlvIG8gZW4gUG9zaXQgQ2xvdWQuIEVsIGFyY2hpdm8gYXBhcmVjZXLDoSBlbiB1biBudWV2byBwYW5lbCBhcnJpYmEgZW4gZWwgbGFkbyBpenF1aWVyZG8gZGUgbGEgcGFudGFsbGEsIHkgZWwgcGFuZWwgZGUgbGEgY29uc29sYSBzZSBtb3ZlcsOhIGhhY2lhIGFiYWpvLg0KDQoNCiMjIFJNYXJrZG93bg0KDQpVbiBhcmNoaXZvIFJNYXJrZG93biBlcyB1biBhcmNoaXZvIGRlIHRleHRvIHBsYW5vLCBjb24gYWxndW5hcyByZWdsYXMgeSB1bmEgc2ludGF4aXMgZXNwZWNpYWwgcXVlIG5vcyBwZXJtaXRlIGVzY3JpYmlyIGPDs2RpZ28geSB0ZXh0byBqdW50b3MuIEN1YW5kbyBzZSAidGVqZSIgKGtuaXQpLCBlbCBjw7NkaWdvIHNlIGV2YWx1YXLDoSB5IGVqZWN1dGFyw6EgeSBlbCB0ZXh0byBzZSBmb3JtYXRlYXLDoSBkZSBtYW5lcmEgcXVlIHNlIGNyZWUgdW4gaW5mb3JtZSBvIGRvY3VtZW50byByZXByb2R1Y2libGUgcXVlIHNlYSBhZ3JhZGFibGUgZGUgbGVlciB5IHF1ZSBjb250ZW5nYSB0b2RvIHR1IHRyYWJham8uDQoNCkVzdG8gZXMgcmVhbG1lbnRlIGNyw610aWNvIHBhcmEgbGEgcmVwcm9kdWNpYmlsaWRhZC4gVGFtYmnDqW4gbm9zIGFob3JyYSB0aWVtcG8geSBwdWVkZSBheXVkYXIgZW4gbGFzIHRhcmVhcyBkZSBhdXRvbWF0aXphY2nDs24uIEVzdGUgZG9jdW1lbnRvIHJlY3JlYXLDoSB0dXMgZmlndXJhcyBwb3IgdGkgZW4gZWwgbWlzbW8gZG9jdW1lbnRvIGRvbmRlIGVzdMOhcyBlc2NyaWJpZW5kbyBlbCB0ZXh0byBxdWUgbGFzIGV4cGxpY2EuIEVzdG8gbGUgYWhvcnJhcsOhIGVsIGVzZnVlcnpvIGRlIGhhY2VyIHVuIGFuw6FsaXNpcywgZ3VhcmRhciB1biBncsOhZmljbyBlbiB1biBhcmNoaXZvLCBjb3BpYXIgeSBwZWdhciBlc2UgZ3LDoWZpY28gZW4gV29yZCBvIFBvd2VyIFBvaW50IG8gR29vZ2xlIFNsaWRlcywgeSB0ZW5lciBxdWUgaGFjZXJsbyB0b2RvIGRlIG51ZXZvIGRlc3B1w6lzIGRlIGRlc2N1YnJpciB1biBlcnJvciB0aXBvZ3LDoWZpY28uDQoNCkFob3JhIHZlYW1vcyBjw7NtbyBlcyBudWVzdHJvIEluZm9ybWUgZGUgUGluZ8O8aW5vcy4NCg0KKiBMYSBwYXJ0ZSBzdXBlcmlvciB0aWVuZSBlbCBUw610dWxvIHkgZWwgdGlwbyBkZSBzYWxpZGEgKHF1ZSBlbiBlc3RlIGNhc28gZXMgdW4gZG9jdW1lbnRvIEhUTUwpLg0KKiBEZWJham8gaGF5IHNlY2Npb25lcyBhbHRlcm5hcyBfYmxhbmNhc18geSBfZ3Jpc2VzXy4gRXN0YXMgc29uIGxhcyBkb3Mgc2VjY2lvbmVzIHByaW5jaXBhbGVzIHF1ZSBjb21wb25lbiB1biBhcmNoaXZvIFJNYXJrZG93bjoNCiAgICAgICogTGFzIHNlY2Npb25lcyBncmlzZXMgc29uIGVsIGPDs2RpZ28gUg0KICAgICAgKiBMYXMgc2VjY2lvbmVzIGJsYW5jYXMgc29uIGVsIHRleHRvIGRlIE1hcmtkb3duDQoqIEhheSB0ZXh0byBuZWdybywgYXp1bCB5IHZlcmRlLg0KDQo+IFNpZ2Ftb3MgYWRlbGFudGUgeSAidGVqYW1vcyAoa25pdCkiIGVsIGRvY3VtZW50byBoYWNpZW5kbyBjbGljIGVuIGVsIG92aWxsbyBkZSBoaWxvIGF6dWwgKDxpbWcgc3JjPSJpbWcva25pdC1ib3Rvbi5wbmciPikgZW4gbGEgcGFydGUgc3VwZXJpb3IgZGVsIGFyY2hpdm8gUk1hcmtkb3duLiANCg0KwqFBY2FiYW1vcyBkZSBjcmVhciB1biBhcmNoaXZvIGh0bWwhIFNlIHRyYXRhIGRlIHVuYSDDum5pY2EgcMOhZ2luYSB3ZWIgcXVlIGVzdGFtb3MgdmllbmRvIGxvY2FsbWVudGUgZW4gbnVlc3Ryb3MgcHJvcGlvcyBvcmRlbmFkb3Jlcy4gQWwgZ2VuZXJhciBlc3RlIGRvY3VtZW50byBSTWFya2Rvd24sIFIgaGEgZm9ybWF0ZWFkbyBlbCB0ZXh0byBtYXJrZG93biB5IGhhIGVqZWN1dGFkbyBlbCBjw7NkaWdvIFIuDQoNCjxpbWcgc3JjPSJpbWcvbWFya2Rvd24ta25pdC5wbmciIGFsdD0iUm1hcmtkb3duIGEgbGEgaXpxdWllcmRhLiBEb2N1bWVudG8gZ2VuZXJhZG8gYSBsYSBkZXJlY2hhIi8+DQoNCiMjIyBUZXh0byBtYXJrZG93bg0KDQpQb2RlcyB2ZXIgdW5hIGd1aWEgc29icmUgcm1ha2Rvd24gW2VuIGVzdGEgZ3XDrWEgcsOhcGlkYV0oaHR0cHM6Ly9yYXcuZ2l0aHVidXNlcmNvbnRlbnQuY29tL3JzdHVkaW8vY2hlYXRzaGVldHMvbWFpbi90cmFuc2xhdGlvbnMvc3BhbmlzaC9ybWFya2Rvd25fZXMucGRmKSwgcGVybyBhcXXDrSBoYXkgdW5hIHNpbnRheGlzIG3DrW5pbWEgcGFyYSBlbXBlemFyOg0KDQoqIGVuY2FiZXphZG9zIGVtcGllemFuIGNvbiBgIyBgIG8gYCMjIGB5IGFzaSBzaWd1aWVuZG8gKGVzIGltcG9ydGFudGUgcG9uZXIgdW4gZXNwYWNpbyBkZXNwdcOpcyBkZWwgw7psdGltbyBgI2ApLg0KKiBsYXMgcGFsYWJyYXMgZW4gbmVncml0YSBlc3TDoW4gcm9kZWFkYXMgZGUgYCoqYA0KKiB5IGxhcyBjdXJzaXZhLCBjb24gYF9gDQoNCiMjIyBDw7NkaWdvIGRlIFINCg0KYGBge3IgaW5jbHVkZT1GQUxTRX0NCmNodW5rX3N0YXJ0IDwtICJgYGB7ciBsYWJlbH0iDQpjaHVua19lbmQgPC0gImBgYCINCmBgYA0KDQpFbCBjw7NkaWdvIFIgc2UgZXNjcmliZSBkZW50cm8gZGUgImNodW5rcyAodHJvem9zKSIgZGUgY8OzZGlnby4gTG9zIHRyb3pvcyBkZSBjw7NkaWdvIGNvbWllbnphbiBjb24gYGAgYHIgY2h1bmtfc3RhcnRgIGBgIChkb25kZSAibGFiZWwiIGVzIHVuIG5vbWJyZSBvcGNpb25hbCB5IMO6bmljbykgeSB0ZXJtaW5hbiBjb24gYGAgYHIgY2h1bmtfZW5kYCBgYC4gRW4gUlN0dWRpbywgcG9kZXMgY3JlYXIgdW4gbnVldm8gY2h1bmsgY29uIGVsIGF0YWpvIGRlIHRlY2xhZG8gYEN0cmwgKyBBbHQgKyBJYC4NCg0KRXN0ZSBpbmZvcm1lIG11ZXN0cmEgaW5mb3JtYWNpw7NuIHNvYnJlIGxvcyBwaW5nw7xpbm9zIFBhcMO6YSwgcGVybyBwb2Ryw61hbW9zIGNhbWJpYXIgYWxndW5hcyBsw61uZWFzIGRlIGPDs2RpZ28gcGFyYSBjcmVhciBlbCBtaXNtbyBhbsOhbGlzaXMgcGFyYSBsYXMgb3RyYXMgZG9zIGVzcGVjaWVzLCBBZGVsaWEgeSBCYXJiaWpvLg0KDQo+IEFob3JhIGVzIHR1IHR1cm5vLiBTaWd1ZSBidXNjYW5kbyBlbiBlbCBjw7NkaWdvLCBzaSBlbmN1ZW50cmFzIGFsZ3VuYSBtZW5jacOzbiBhICJQYXDDumEiLCBjw6FtYmlhbGEgcG9yIGN1YWxxdWllcmEgZGUgbGFzIG90cmFzIGVzcGVjaWVzLiANCg0KRXN0YSB0YXJlYSBlcyB1biBwb2NvIGVuZ29ycm9zYSBzaSBoYXkgcXVlIGNhbWJpYXIgbXVjaGFzIGNvc2FzIGNhZGEgdmV6IHF1ZSBxdWVyZW1vcyB2b2x2ZXIgYSBlamVjdXRhciBlbCBhbsOhbGlzaXMgcGFyYSBkaWZlcmVudGVzIGVzcGVjaWVzLiBQZXJvIG5vIHRlIHByZW9jdXBlcywgYXByZW5kZXJlbW9zIGEgaGFjZXIgdG9kbyBtw6FzIGF1dG9tw6F0aWNvIGFsIGZpbmFsIGRlbCB0YWxsZXIuIA0KDQo=