Trabajar con proyectos de RStudio no solo hace tus análisis más
ordenados y reproducibles, también hacen tu vida más simple.
Al comienzo posiblemente tengan un script y uno o dos archivos con
datos, pero es posible que rápidamente te encuentres con una docena de
archivos con nombres parecidos pero que pertenecen a análisis totalmente
distintos. Antes de que la cosa comience a complicarse te proponemos
trabajar con proyectos.
¿Qué ventajas tiene?
- Te permite ”cuidar” los datos que usas al ordenarnos en carpetas que
diferencien entre la versión original o cruda y los datos limpios o los
resultados finales.
- Te permite compartir tu trabajo fácilmente con otras personas. Solo
tendrías que compartir la carpeta del proyecto sabiendo que incluye todo
lo necesario para que cualquier persona reproduzca tu análisis.
- Te permite publicar de manera ordenada tu código si vas a presentar
o publicar tu trabajo.
- Te permite continuar con lo que estabas haciendo hace una semana o
hace un mes como si el tiempo no hubiera pasado. De alguna manera es un
regalo para tu yo futuro.
Primer desafío: Crea un nuevo proyecto en
RStudio
- Hacé click en el menú “Archivo” (“File”) y luego en “Nuevo Proyecto”
(“New Project”).
- Hacé click en “Nueva Carpeta” (“New Directory”).
- Hacé click en “Nuevo Proyecto” (“New Project”).
- Escribí el nombre de la carpeta que alojará a tu proyecto, por
ejemplo “mi_proyecto”
- Si aparece (y sabés usarlo), seleccioná “Crear un repositorio de
git” (“Create a git repository”).
- Hacé click en “Crear Proyecto” (“Create Project”).
Si todo salió bien, ahora deberías tener una nueva carpeta que se
llama mi_proyecto. Pero si bien es una carpeta común y
corriente, le llamamos proyecto porque además contiene un archivo con el
mismo nombre mi_proyecto.Rproj (o solo mi_proyecto si
en tu computadora no ves la extensión de los archivos).
Abrir un proyecto
La manera más simple de abrir un proyecto es abriendo la carpeta que
lo contiene y haciendo doble click sobre el archivo
mi_proyecto.Rproj. Al hacer esto se abrirá RStudio y la sesión
de R en la misma carpeta y, por defecto, cualquier archivo que quieras
abrir o guardar lo hará en esa misma ubicación. Esto ayuda a mantener tu
trabajo ordenado y que luego sea simple retomar o compartir lo que
hiciste.
RStudio permite tener varios proyectos abiertos, y esto es posible
porque justamente cada proyecto tiene su propia carpeta. Si en algún
momento trabajas con proyectos en paralelo vas a poder hacerlo sin que
el código o los resultados de un análisis interfieran con otro.
Segundo desafío: Abrí tu nuevo proyecto desde el explorador
de archivos
- Cerrá RStudio
- Desde el explorador de archivos, buscá la carpeta donde creaste tu
proyecto.
- Hacé doble click en el archivo que tiene el nombre de tu proyecto (y
que termina con .Rproj) que encontrarás en esa carpeta.
¿Cómo se organiza?
No existe una “mejor” forma de organizar un proyecto pero acá van
algunos principios generales que nos hacen la vida más simple::
- Tratar los datos como sólo de lectura Es posible
que la toma de los datos que querés analizar te haya costado mucho
trabajo, o te haya costado conseguirlos. Trabajar con datos de forma
interactiva (por ejemplo, en Excel) tiene la ventaja de permitirte hacer
algunos análisis rápidamente pero al mismo tiempo tiene la desventaja de
que esos datos pueden ser modificados fácilmente. Esto significa que a
veces no conozcas de la procedencia de los datos, o no recuerdes como
los modificaste desde que los obtuviste. Por lo tanto, es una buena idea
tratar los datos como “sólo de lectura” y nunca modificar los archivos
originales.
- Limpieza de datos En muchos casos tus datos estarán
“sucios”, necesitarán un preprocesamiento importante para organizarlos
en un formato que R (o cualquier otro lenguaje de programación) pueda
analizados fácilmente. Esta tarea se denomina a veces “amasado” o
“masticado de datos”. Es una buena costumbre guardar el código que te
permitió limpiar estos datos por si los volvieras a necesitar. También
es recomendable guardar esa versión de los datos limpios, de “sólo
lectura”, para que puedas usarlos en tu análisis sin necesidad de
repetir cada vez todo el proceso de limpieza de los datos.
- Tratar las salidas o resultados generados como
descartables Cualquier resultado (gráficos, tablas, valores)
debe poder repetirse o rehacerse a partir del código guardado. Si bien
las pruebas rápidas para ver si el código funciona se pueden
hacer en la consola, es importante guardar el código que genera los
resultados y asegurarnos de que sean reproducibles. Aún mejor, si
organizas esos resultados en distintas sub-carpetas, luego tendrás todo
aún más ordenado.
Here es la solución
Si tenés alguna experiencia programando con R es posible que tengas
estás lineas al comienzo de alguno de tus scripts o si nunca las usaste,
seguro viste que alguien más lo hacia:
setwd("/Users/pao/una_carpeta/al/proyecto_importante")
rm(list = ls())
La primera línea setea o le avisa a R cual será la carpeta
donde va a trabajar. Con el uso de proyectos esto está prácticamente
solucionado porque al abrir el proyecto ya sea desde el explorador de
archivos haciendo doble click en el archivo con extensión Rproj
o desde RStudio, R sabrá que ese directorio será el de trabajo.
Pero también dijimos que era una buena práctica organizar los datos
en una subcarpeta “datos”, los informes en otra y tal vez las figuras en
una subcarpeta distinta dentro del proyecto. ¿Cómo hacemos para que R
lea un archivo que no está en la carpeta de trabajo? Podríamos escribir
el camino hacia ese archivo, por ejemplo
"datos/mi_archivo_de_datos.csv"
pero si queremos compartir
el código a otra persona que tal vez tiene un sistema operativo distinto
y usa la barra invertida \
va a estar en problemas al
intentar correr esa línea.
Sale al rescate el paquete {here}
, que funciona
independientemente del sistema operativo. Su función principal
here()
recibe como argumentos el camino hacia el archivo
que se quiere leer, siempre entre comillas y separados por comas,
así:
mis_datos <- read_csv(here("datos", "mi_archivo_de_datos.csv"))
Internamente este paquete es suficientemente inteligente para
identificar cual es el directorio de trabajo (por ejemplo detectando que
hay un archivo .Rproj) y busca a partir de ahí la subcarpeta
“datos” y adentro de ella el archivo “mi_archivo_de_datos.csv”.
La segunda línea se usa para borrar los elementos que creamos en el
análisis normalmente cuando cambiamos de tema o empezamos a trabajar con
algo distinto. Esto está bien porque no queremos arrastrar análisis que
hicimos en un proyecto a otro, necesitamos que sean autocontenidos y
reproducibles. El problema es que este comando
no borra los paquetes activados o las opciones usuario
que hayamos seteado.
Borrón y cuenta nueva… todos los días!
¿Cómo nos aseguramos de que el análisis sea realmente reproducible?
Esta es una pregunta bastante amplia y hay muchas herramientas para
resolver este problema. Por ahora nos vamos a concentrar en que al menos
en tu computadora puedas repetir los cálculos o el análisis desde cero.
Y además de organizar proyectos y no modificar los datos originales,
¿cómo podés asegurarte de que guardaste todo el código que estuviste
escribiendo y usaste? La manera más directa es reiniciar la sesión de R
y correr el código de nuevo, si da error o no devuelve lo que esperabas
significa que te faltó guardar algún paso.
Tip: Podés reiniciar la sesión de R con el atajo
Ctrl+Shif+F10
Esto puede pasar si por ejemplo leemos una base de datos en memoria
pero no guardamos el código que lo hace. Mientras estemos trabajando, R
tendrá esa base de datos en memoria y podremos hacer cálculos y
gráficos. Por defecto además RStudio va a recordar las variables que
estés usando mañana o pasado en un archivo oculto (.RData) a menos que
le indiques lo contrario. Y si bien suena práctico volver a R al otro
día y tener el análisis tal cual lo dejamos, esto puede significar que
nunca nos demos cuenta que nos faltó guardar una línea de código clave
en nuestro análisis.
Tercer desafío: Configurá RStudio
- Hacé click en el menú “Herramientas (“Tools”) y luego “Opciones
globales” (“Global Options”).
- Destildá la opción “Recuperar .RData al inicio de la sesión”
(“Restore .RData into workspace at startup”).
- Hacé click en “Aplicar” (“Apply”).
LS0tCnRpdGxlOiAiVHJhYmFqYXIgY29uIHByb3llY3RvcyBlbiBSU3R1ZGlvIgpvdXRwdXQ6IAogIGh0bWxfZG9jdW1lbnQ6CiAgICBjb2RlX2Rvd25sb2FkOiB0cnVlCiAgICB0b2M6IHRydWUKICAgIHRvY19mbG9hdDogdHJ1ZQogICAgaGlnaGxpZ2h0OiB0YW5nbyAgIAotLS0KCgpUcmFiYWphciBjb24gcHJveWVjdG9zIGRlIFJTdHVkaW8gbm8gc29sbyBoYWNlIHR1cyBhbsOhbGlzaXMgbcOhcyBvcmRlbmFkb3MgeSByZXByb2R1Y2libGVzLCB0YW1iacOpbiBoYWNlbiB0dSB2aWRhIG3DoXMgc2ltcGxlLiAKCkFsIGNvbWllbnpvIHBvc2libGVtZW50ZSB0ZW5nYW4gdW4gc2NyaXB0IHkgdW5vIG8gZG9zIGFyY2hpdm9zIGNvbiBkYXRvcywgcGVybyBlcyBwb3NpYmxlIHF1ZSByw6FwaWRhbWVudGUgdGUgZW5jdWVudHJlcyBjb24gdW5hIGRvY2VuYSBkZSBhcmNoaXZvcyBjb24gbm9tYnJlcyBwYXJlY2lkb3MgcGVybyBxdWUgcGVydGVuZWNlbiBhIGFuw6FsaXNpcyB0b3RhbG1lbnRlIGRpc3RpbnRvcy4gQW50ZXMgZGUgcXVlIGxhIGNvc2EgY29taWVuY2UgYSBjb21wbGljYXJzZSB0ZSBwcm9wb25lbW9zIHRyYWJhamFyIGNvbiBwcm95ZWN0b3MuICAKCiMjIyDCv1F1w6kgdmVudGFqYXMgdGllbmU/CgotIFRlIHBlcm1pdGUg4oCdY3VpZGFy4oCdIGxvcyBkYXRvcyBxdWUgdXNhcyBhbCBvcmRlbmFybm9zIGVuIGNhcnBldGFzIHF1ZSBkaWZlcmVuY2llbiBlbnRyZSBsYSB2ZXJzacOzbiBvcmlnaW5hbCBvIGNydWRhIHkgbG9zIGRhdG9zIGxpbXBpb3MgbyBsb3MgcmVzdWx0YWRvcyBmaW5hbGVzLiAKLSBUZSBwZXJtaXRlIGNvbXBhcnRpciB0dSB0cmFiYWpvIGbDoWNpbG1lbnRlIGNvbiBvdHJhcyBwZXJzb25hcy4gU29sbyB0ZW5kcsOtYXMgcXVlIGNvbXBhcnRpciBsYSBjYXJwZXRhIGRlbCBwcm95ZWN0byBzYWJpZW5kbyBxdWUgaW5jbHV5ZSB0b2RvIGxvIG5lY2VzYXJpbyBwYXJhIHF1ZSBjdWFscXVpZXIgcGVyc29uYSByZXByb2R1emNhIHR1IGFuw6FsaXNpcy4KLSBUZSBwZXJtaXRlIHB1YmxpY2FyIGRlIG1hbmVyYSBvcmRlbmFkYSB0dSBjw7NkaWdvIHNpIHZhcyBhIHByZXNlbnRhciBvIHB1YmxpY2FyIHR1IHRyYWJham8uCi0gVGUgcGVybWl0ZSBjb250aW51YXIgY29uIGxvIHF1ZSBlc3RhYmFzIGhhY2llbmRvIGhhY2UgdW5hIHNlbWFuYSBvIGhhY2UgdW4gbWVzIGNvbW8gc2kgZWwgdGllbXBvIG5vIGh1YmllcmEgcGFzYWRvLiBEZSBhbGd1bmEgbWFuZXJhIGVzIHVuIHJlZ2FsbyBwYXJhIHR1IHlvIGZ1dHVyby4KCjo6OiB7LmFsZXJ0IC5hbGVydC1pbmZvfQoqKlByaW1lciBkZXNhZsOtbzogQ3JlYSB1biBudWV2byBwcm95ZWN0byBlbiBSU3R1ZGlvKioKCjEuIEhhY8OpIGNsaWNrIGVuIGVsIG1lbsO6IOKAnEFyY2hpdm/igJ0gKOKAnEZpbGXigJ0pIHkgbHVlZ28gZW4g4oCcTnVldm8gUHJveWVjdG/igJ0gKOKAnE5ldyBQcm9qZWN04oCdKS4KMi4gSGFjw6kgY2xpY2sgZW4g4oCcTnVldmEgQ2FycGV0YeKAnSAo4oCcTmV3IERpcmVjdG9yeeKAnSkuCjMuIEhhY8OpIGNsaWNrIGVuIOKAnE51ZXZvIFByb3llY3Rv4oCdICjigJxOZXcgUHJvamVjdOKAnSkuCjQuIEVzY3JpYsOtIGVsIG5vbWJyZSBkZSBsYSBjYXJwZXRhIHF1ZSBhbG9qYXLDoSBhIHR1IHByb3llY3RvLCBwb3IgZWplbXBsbyDigJxtaV9wcm95ZWN0b+KAnQo1LiBTaSBhcGFyZWNlICh5IHNhYsOpcyB1c2FybG8pLCBzZWxlY2Npb27DoSDigJxDcmVhciB1biByZXBvc2l0b3JpbyBkZSBnaXTigJ0gKOKAnENyZWF0ZSBhIGdpdCByZXBvc2l0b3J54oCdKS4KNi4gSGFjw6kgY2xpY2sgZW4g4oCcQ3JlYXIgUHJveWVjdG/igJ0gKOKAnENyZWF0ZSBQcm9qZWN04oCdKS4KOjo6CgpTaSB0b2RvIHNhbGnDsyBiaWVuLCBhaG9yYSBkZWJlcsOtYXMgdGVuZXIgdW5hIG51ZXZhIGNhcnBldGEgcXVlIHNlIGxsYW1hICptaV9wcm95ZWN0byouIFBlcm8gc2kgYmllbiBlcyB1bmEgY2FycGV0YSBjb23Dum4geSBjb3JyaWVudGUsIGxlIGxsYW1hbW9zIHByb3llY3RvIHBvcnF1ZSBhZGVtw6FzIGNvbnRpZW5lIHVuIGFyY2hpdm8gY29uIGVsIG1pc21vIG5vbWJyZSAqbWlfcHJveWVjdG8uUnByb2oqIChvIHNvbG8gKm1pX3Byb3llY3RvKiBzaSBlbiB0dSBjb21wdXRhZG9yYSBubyB2ZXMgbGEgZXh0ZW5zacOzbiBkZSBsb3MgYXJjaGl2b3MpLiAKCiMjIyBBYnJpciB1biBwcm95ZWN0bwoKTGEgbWFuZXJhIG3DoXMgc2ltcGxlIGRlIGFicmlyIHVuIHByb3llY3RvIGVzIGFicmllbmRvIGxhIGNhcnBldGEgcXVlIGxvIGNvbnRpZW5lIHkgaGFjaWVuZG8gZG9ibGUgY2xpY2sgc29icmUgZWwgYXJjaGl2byAqbWlfcHJveWVjdG8uUnByb2oqLiBBbCBoYWNlciBlc3RvIHNlIGFicmlyw6EgUlN0dWRpbyB5IGxhIHNlc2nDs24gZGUgUiBlbiBsYSBtaXNtYSBjYXJwZXRhIHksIHBvciBkZWZlY3RvLCBjdWFscXVpZXIgYXJjaGl2byBxdWUgcXVpZXJhcyBhYnJpciBvIGd1YXJkYXIgbG8gaGFyw6EgZW4gZXNhIG1pc21hIHViaWNhY2nDs24uIEVzdG8gYXl1ZGEgYSBtYW50ZW5lciB0dSB0cmFiYWpvIG9yZGVuYWRvIHkgcXVlIGx1ZWdvIHNlYSBzaW1wbGUgcmV0b21hciBvIGNvbXBhcnRpciBsbyBxdWUgaGljaXN0ZS4gCgpSU3R1ZGlvIHBlcm1pdGUgdGVuZXIgdmFyaW9zIHByb3llY3RvcyBhYmllcnRvcywgeSBlc3RvIGVzIHBvc2libGUgcG9ycXVlIGp1c3RhbWVudGUgY2FkYSBwcm95ZWN0byB0aWVuZSBzdSBwcm9waWEgY2FycGV0YS4gU2kgZW4gYWxnw7puIG1vbWVudG8gdHJhYmFqYXMgY29uIHByb3llY3RvcyBlbiBwYXJhbGVsbyB2YXMgYSBwb2RlciBoYWNlcmxvIHNpbiBxdWUgZWwgY8OzZGlnbyBvIGxvcyByZXN1bHRhZG9zIGRlIHVuIGFuw6FsaXNpcyBpbnRlcmZpZXJhbiBjb24gb3Ryby4KCjo6OiB7LmFsZXJ0IC5hbGVydC1pbmZvfQoqKlNlZ3VuZG8gZGVzYWbDrW86IEFicsOtIHR1IG51ZXZvIHByb3llY3RvIGRlc2RlIGVsIGV4cGxvcmFkb3IgZGUgYXJjaGl2b3MqKgoKMS4gQ2VycsOhIFJTdHVkaW8KMi4gRGVzZGUgZWwgZXhwbG9yYWRvciBkZSBhcmNoaXZvcywgYnVzY8OhIGxhIGNhcnBldGEgZG9uZGUgY3JlYXN0ZSB0dSBwcm95ZWN0by4KMy4gSGFjw6kgZG9ibGUgY2xpY2sgZW4gZWwgYXJjaGl2byBxdWUgdGllbmUgZWwgbm9tYnJlIGRlIHR1IHByb3llY3RvICh5IHF1ZSB0ZXJtaW5hIGNvbiAqLlJwcm9qKikgcXVlIGVuY29udHJhcsOhcyBlbiBlc2EgY2FycGV0YS4KOjo6CgojIyMgwr9Dw7NtbyBzZSBvcmdhbml6YT8KCk5vIGV4aXN0ZSB1bmEgIm1lam9yIiBmb3JtYSBkZSBvcmdhbml6YXIgdW4gcHJveWVjdG8gcGVybyBhY8OhIHZhbiBhbGd1bm9zIHByaW5jaXBpb3MgZ2VuZXJhbGVzIHF1ZSBub3MgaGFjZW4gbGEgdmlkYSBtw6FzIHNpbXBsZTo6CgoqICoqVHJhdGFyIGxvcyBkYXRvcyBjb21vIHPDs2xvIGRlIGxlY3R1cmEqKgpFcyBwb3NpYmxlIHF1ZSBsYSB0b21hIGRlIGxvcyBkYXRvcyBxdWUgcXVlcsOpcyBhbmFsaXphciB0ZSBoYXlhIGNvc3RhZG8gbXVjaG8gdHJhYmFqbywgbyB0ZSBoYXlhIGNvc3RhZG8gY29uc2VndWlybG9zLiBUcmFiYWphciBjb24gZGF0b3MgZGUgZm9ybWEgaW50ZXJhY3RpdmEgKHBvciBlamVtcGxvLCBlbiBFeGNlbCkgdGllbmUgbGEgdmVudGFqYSBkZSBwZXJtaXRpcnRlIGhhY2VyIGFsZ3Vub3MgYW7DoWxpc2lzIHLDoXBpZGFtZW50ZSBwZXJvIGFsIG1pc21vIHRpZW1wbyB0aWVuZSBsYSBkZXN2ZW50YWphIGRlIHF1ZSBlc29zIGRhdG9zIHB1ZWRlbiBzZXIgbW9kaWZpY2Fkb3MgZsOhY2lsbWVudGUuIEVzdG8gc2lnbmlmaWNhIHF1ZSBhIHZlY2VzIG5vIGNvbm96Y2FzIGRlIGxhIHByb2NlZGVuY2lhIGRlIGxvcyBkYXRvcywgbyBubyByZWN1ZXJkZXMgY29tbyBsb3MgbW9kaWZpY2FzdGUgZGVzZGUgcXVlIGxvcyBvYnR1dmlzdGUuIFBvciBsbyB0YW50bywgZXMgdW5hIGJ1ZW5hIGlkZWEgdHJhdGFyIGxvcyBkYXRvcyBjb21vICJzw7NsbyBkZSBsZWN0dXJhIiB5IG51bmNhIG1vZGlmaWNhciBsb3MgYXJjaGl2b3Mgb3JpZ2luYWxlcy4KKiAqKkxpbXBpZXphIGRlIGRhdG9zKioKRW4gbXVjaG9zIGNhc29zIHR1cyBkYXRvcyBlc3RhcsOhbiAic3VjaW9zIiwgbmVjZXNpdGFyw6FuIHVuIHByZXByb2Nlc2FtaWVudG8gaW1wb3J0YW50ZSBwYXJhIG9yZ2FuaXphcmxvcyBlbiB1biBmb3JtYXRvIHF1ZSAgUiAobyBjdWFscXVpZXIgb3RybyBsZW5ndWFqZSBkZSBwcm9ncmFtYWNpw7NuKSBwdWVkYSBhbmFsaXphZG9zIGbDoWNpbG1lbnRlLiBFc3RhIHRhcmVhIHNlIGRlbm9taW5hIGEgdmVjZXMgImFtYXNhZG8iIG8gIm1hc3RpY2FkbyBkZSBkYXRvcyIuIEVzIHVuYSBidWVuYSBjb3N0dW1icmUgZ3VhcmRhciBlbCBjw7NkaWdvIHF1ZSB0ZSBwZXJtaXRpw7MgbGltcGlhciBlc3RvcyBkYXRvcyBwb3Igc2kgbG9zIHZvbHZpZXJhcyBhIG5lY2VzaXRhci4gVGFtYmnDqW4gZXMgcmVjb21lbmRhYmxlIGd1YXJkYXIgZXNhIHZlcnNpw7NuIGRlIGxvcyBkYXRvcyBsaW1waW9zLCBkZSAic8OzbG8gbGVjdHVyYSIsIHBhcmEgcXVlIHB1ZWRhcyB1c2FybG9zIGVuIHR1IGFuw6FsaXNpcyBzaW4gbmVjZXNpZGFkIGRlIHJlcGV0aXIgY2FkYSB2ZXogdG9kbyBlbCBwcm9jZXNvIGRlIGxpbXBpZXphIGRlIGxvcyBkYXRvcy4KKiAqKlRyYXRhciBsYXMgc2FsaWRhcyBvIHJlc3VsdGFkb3MgZ2VuZXJhZG9zIGNvbW8gZGVzY2FydGFibGVzKioKQ3VhbHF1aWVyIHJlc3VsdGFkbyAoZ3LDoWZpY29zLCB0YWJsYXMsIHZhbG9yZXMpIGRlYmUgcG9kZXIgcmVwZXRpcnNlIG8gcmVoYWNlcnNlIGEgcGFydGlyIGRlbCBjw7NkaWdvIGd1YXJkYWRvLiBTaSBiaWVuIGxhcyBwcnVlYmFzIHLDoXBpZGFzIHBhcmEgKnZlciBzaSBlbCBjw7NkaWdvIGZ1bmNpb25hKiBzZSBwdWVkZW4gaGFjZXIgZW4gbGEgY29uc29sYSwgZXMgaW1wb3J0YW50ZSBndWFyZGFyIGVsIGPDs2RpZ28gcXVlIGdlbmVyYSBsb3MgcmVzdWx0YWRvcyB5IGFzZWd1cmFybm9zIGRlIHF1ZSBzZWFuIHJlcHJvZHVjaWJsZXMuIEHDum4gbWVqb3IsIHNpIG9yZ2FuaXphcyBlc29zIHJlc3VsdGFkb3MgZW4gZGlzdGludGFzIHN1Yi1jYXJwZXRhcywgbHVlZ28gdGVuZHLDoXMgdG9kbyBhw7puIG3DoXMgb3JkZW5hZG8uCgojIyMgSGVyZSBlcyBsYSBzb2x1Y2nDs24KClNpIHRlbsOpcyBhbGd1bmEgZXhwZXJpZW5jaWEgcHJvZ3JhbWFuZG8gY29uIFIgZXMgcG9zaWJsZSBxdWUgdGVuZ2FzIGVzdMOhcyBsaW5lYXMgYWwgY29taWVuem8gZGUgYWxndW5vIGRlIHR1cyBzY3JpcHRzIG8gc2kgbnVuY2EgbGFzIHVzYXN0ZSwgc2VndXJvIHZpc3RlIHF1ZSBhbGd1aWVuIG3DoXMgbG8gaGFjaWE6CgpgYGB7ciBldmFsPUZBTFNFfQoKc2V0d2QoIi9Vc2Vycy9wYW8vdW5hX2NhcnBldGEvYWwvcHJveWVjdG9faW1wb3J0YW50ZSIpCnJtKGxpc3QgPSBscygpKQoKYGBgCgpMYSBwcmltZXJhIGzDrW5lYSAqc2V0ZWEqIG8gbGUgYXZpc2EgYSBSIGN1YWwgc2Vyw6EgbGEgY2FycGV0YSBkb25kZSB2YSBhIHRyYWJhamFyLiBDb24gZWwgdXNvIGRlIHByb3llY3RvcyBlc3RvIGVzdMOhIHByw6FjdGljYW1lbnRlIHNvbHVjaW9uYWRvIHBvcnF1ZSBhbCBhYnJpciBlbCBwcm95ZWN0byB5YSBzZWEgZGVzZGUgZWwgZXhwbG9yYWRvciBkZSBhcmNoaXZvcyBoYWNpZW5kbyBkb2JsZSBjbGljayBlbiBlbCBhcmNoaXZvIGNvbiBleHRlbnNpw7NuICpScHJvaiogbyBkZXNkZSBSU3R1ZGlvLCAgUiBzYWJyw6EgcXVlIGVzZSBkaXJlY3RvcmlvIHNlcsOhIGVsIGRlIHRyYWJham8uIAoKUGVybyB0YW1iacOpbiBkaWppbW9zIHF1ZSBlcmEgdW5hIGJ1ZW5hIHByw6FjdGljYSBvcmdhbml6YXIgbG9zIGRhdG9zIGVuIHVuYSBzdWJjYXJwZXRhICJkYXRvcyIsIGxvcyBpbmZvcm1lcyBlbiBvdHJhIHkgdGFsIHZleiBsYXMgZmlndXJhcyBlbiB1bmEgc3ViY2FycGV0YSBkaXN0aW50YSBkZW50cm8gZGVsIHByb3llY3RvLiDCv0PDs21vIGhhY2Vtb3MgcGFyYSBxdWUgUiBsZWEgdW4gYXJjaGl2byBxdWUgbm8gZXN0w6EgZW4gbGEgY2FycGV0YSBkZSB0cmFiYWpvPyBQb2Ryw61hbW9zIGVzY3JpYmlyIGVsIGNhbWlubyBoYWNpYSBlc2UgYXJjaGl2bywgcG9yIGVqZW1wbG8gYCJkYXRvcy9taV9hcmNoaXZvX2RlX2RhdG9zLmNzdiJgIHBlcm8gc2kgcXVlcmVtb3MgY29tcGFydGlyIGVsIGPDs2RpZ28gYSBvdHJhIHBlcnNvbmEgcXVlIHRhbCB2ZXogdGllbmUgdW4gc2lzdGVtYSBvcGVyYXRpdm8gZGlzdGludG8geSB1c2EgbGEgYmFycmEgaW52ZXJ0aWRhIGBcYCB2YSBhIGVzdGFyIGVuIHByb2JsZW1hcyBhbCBpbnRlbnRhciBjb3JyZXIgZXNhIGzDrW5lYS4gCgpTYWxlIGFsIHJlc2NhdGUgZWwgcGFxdWV0ZSBge2hlcmV9YCwgcXVlIGZ1bmNpb25hIGluZGVwZW5kaWVudGVtZW50ZSBkZWwgc2lzdGVtYSBvcGVyYXRpdm8uIFN1IGZ1bmNpw7NuIHByaW5jaXBhbCBgaGVyZSgpYCByZWNpYmUgY29tbyBhcmd1bWVudG9zIGVsIGNhbWlubyBoYWNpYSBlbCBhcmNoaXZvIHF1ZSBzZSBxdWllcmUgbGVlciwgc2llbXByZSBlbnRyZSBjb21pbGxhcyB5IHNlcGFyYWRvcyBwb3IgY29tYXMsIGFzw606CgpgYGB7ciBldmFsPUZBTFNFfQoKbWlzX2RhdG9zIDwtIHJlYWRfY3N2KGhlcmUoImRhdG9zIiwgIm1pX2FyY2hpdm9fZGVfZGF0b3MuY3N2IikpCgpgYGAKCkludGVybmFtZW50ZSBlc3RlIHBhcXVldGUgZXMgc3VmaWNpZW50ZW1lbnRlIGludGVsaWdlbnRlIHBhcmEgaWRlbnRpZmljYXIgY3VhbCBlcyBlbCBkaXJlY3RvcmlvIGRlIHRyYWJham8gKHBvciBlamVtcGxvIGRldGVjdGFuZG8gcXVlIGhheSB1biBhcmNoaXZvICouUnByb2oqKSB5IGJ1c2NhIGEgcGFydGlyIGRlIGFow60gbGEgc3ViY2FycGV0YSAiZGF0b3MiIHkgYWRlbnRybyBkZSBlbGxhIGVsIGFyY2hpdm8gIm1pX2FyY2hpdm9fZGVfZGF0b3MuY3N2Ii4gCgpMYSBzZWd1bmRhIGzDrW5lYSBzZSB1c2EgcGFyYSBib3JyYXIgbG9zIGVsZW1lbnRvcyBxdWUgY3JlYW1vcyBlbiBlbCBhbsOhbGlzaXMgbm9ybWFsbWVudGUgY3VhbmRvIGNhbWJpYW1vcyBkZSB0ZW1hIG8gZW1wZXphbW9zIGEgdHJhYmFqYXIgY29uIGFsZ28gZGlzdGludG8uIEVzdG8gZXN0w6EgYmllbiBwb3JxdWUgbm8gcXVlcmVtb3MgYXJyYXN0cmFyIGFuw6FsaXNpcyBxdWUgaGljaW1vcyBlbiB1biBwcm95ZWN0byBhIG90cm8sIG5lY2VzaXRhbW9zIHF1ZSBzZWFuIGF1dG9jb250ZW5pZG9zIHkgKnJlcHJvZHVjaWJsZXMqLiBFbCBwcm9ibGVtYSBlcyBxdWUgZXN0ZSBjb21hbmRvICoqbm8qKiBib3JyYSBsb3MgcGFxdWV0ZXMgYWN0aXZhZG9zIG8gbGFzIG9wY2lvbmVzIHVzdWFyaW8gcXVlIGhheWFtb3Mgc2V0ZWFkby4gCgoKIyMjIEJvcnLDs24geSBjdWVudGEgbnVldmEuLi4gdG9kb3MgbG9zIGTDrWFzIQoKwr9Dw7NtbyBub3MgYXNlZ3VyYW1vcyBkZSBxdWUgZWwgYW7DoWxpc2lzIHNlYSByZWFsbWVudGUgcmVwcm9kdWNpYmxlPyBFc3RhIGVzIHVuYSBwcmVndW50YSBiYXN0YW50ZSBhbXBsaWEgeSBoYXkgbXVjaGFzIGhlcnJhbWllbnRhcyBwYXJhIHJlc29sdmVyIGVzdGUgcHJvYmxlbWEuIFBvciBhaG9yYSBub3MgdmFtb3MgYSBjb25jZW50cmFyIGVuIHF1ZSBhbCBtZW5vcyBlbiB0dSBjb21wdXRhZG9yYSBwdWVkYXMgcmVwZXRpciBsb3MgY8OhbGN1bG9zIG8gZWwgYW7DoWxpc2lzIGRlc2RlIGNlcm8uIFkgYWRlbcOhcyBkZSBvcmdhbml6YXIgcHJveWVjdG9zIHkgbm8gbW9kaWZpY2FyIGxvcyBkYXRvcyBvcmlnaW5hbGVzLCDCv2PDs21vIHBvZMOpcyBhc2VndXJhcnRlIGRlIHF1ZSBndWFyZGFzdGUgdG9kbyBlbCBjw7NkaWdvIHF1ZSBlc3R1dmlzdGUgZXNjcmliaWVuZG8geSB1c2FzdGU/IExhIG1hbmVyYSBtw6FzIGRpcmVjdGEgZXMgcmVpbmljaWFyIGxhIHNlc2nDs24gZGUgUiB5IGNvcnJlciBlbCBjw7NkaWdvIGRlIG51ZXZvLCBzaSBkYSBlcnJvciBvIG5vIGRldnVlbHZlIGxvIHF1ZSBlc3BlcmFiYXMgc2lnbmlmaWNhIHF1ZSB0ZSBmYWx0w7MgZ3VhcmRhciBhbGfDum4gcGFzby4gCgo6Ojp7LmFsZXJ0IC5hbGVydC1zdWNjZXNzfQpUaXA6IFBvZMOpcyByZWluaWNpYXIgbGEgc2VzacOzbiBkZSBSIGNvbiBlbCBhdGFqbyBgQ3RybCtTaGlmK0YxMGAKOjo6CgpFc3RvIHB1ZWRlIHBhc2FyIHNpIHBvciBlamVtcGxvIGxlZW1vcyB1bmEgYmFzZSBkZSBkYXRvcyBlbiBtZW1vcmlhIHBlcm8gbm8gZ3VhcmRhbW9zIGVsIGPDs2RpZ28gcXVlIGxvIGhhY2UuIE1pZW50cmFzIGVzdGVtb3MgdHJhYmFqYW5kbywgUiB0ZW5kcsOhIGVzYSBiYXNlIGRlIGRhdG9zIGVuIG1lbW9yaWEgeSBwb2RyZW1vcyBoYWNlciBjw6FsY3Vsb3MgeSBncsOhZmljb3MuIFBvciBkZWZlY3RvIGFkZW3DoXMgUlN0dWRpbyB2YSBhIHJlY29yZGFyIGxhcyB2YXJpYWJsZXMgcXVlIGVzdMOpcyB1c2FuZG8gbWHDsWFuYSBvIHBhc2FkbyBlbiB1biBhcmNoaXZvIG9jdWx0byAoLlJEYXRhKSBhIG1lbm9zIHF1ZSBsZSBpbmRpcXVlcyBsbyBjb250cmFyaW8uIFkgc2kgYmllbiBzdWVuYSBwcsOhY3RpY28gdm9sdmVyIGEgUiBhbCBvdHJvIGTDrWEgeSB0ZW5lciBlbCBhbsOhbGlzaXMgdGFsIGN1YWwgbG8gZGVqYW1vcywgZXN0byBwdWVkZSBzaWduaWZpY2FyIHF1ZSBudW5jYSBub3MgZGVtb3MgY3VlbnRhIHF1ZSBub3MgZmFsdMOzIGd1YXJkYXIgdW5hIGzDrW5lYSBkZSBjw7NkaWdvIGNsYXZlIGVuIG51ZXN0cm8gYW7DoWxpc2lzLgoKCjo6OiB7LmFsZXJ0IC5hbGVydC1pbmZvfQoqKlRlcmNlciBkZXNhZsOtbzogQ29uZmlndXLDoSBSU3R1ZGlvKiogCgoxLiBIYWPDqSBjbGljayBlbiBlbCBtZW7DuiDigJxIZXJyYW1pZW50YXMgKOKAnFRvb2xz4oCdKSB5IGx1ZWdvIOKAnE9wY2lvbmVzIGdsb2JhbGVz4oCdICjigJxHbG9iYWwgT3B0aW9uc+KAnSkuCjIuIERlc3RpbGTDoSBsYSBvcGNpw7NuIOKAnFJlY3VwZXJhciAuUkRhdGEgYWwgaW5pY2lvIGRlIGxhIHNlc2nDs27igJ0gKOKAnFJlc3RvcmUgLlJEYXRhIGludG8gd29ya3NwYWNlIGF0IHN0YXJ0dXDigJ0pLgozLiBIYWPDqSBjbGljayBlbiDigJxBcGxpY2Fy4oCdICjigJxBcHBseeKAnSkuCjo6OgoKCgo8ZGl2IGNsYXNzPSJidG4tZ3JvdXAiIHJvbGU9Imdyb3VwIiBhcmlhLWxhYmVsPSJOYXZlZ2FjacOzbiI+CiAgPGEgaHJlZj0gIjAxLWludHJvZHVjY2lvbi5odG1sIiBjbGFzcyA9ICJidG4gYnRuLXByaW1hcnkiPkFudGVyaW9yPC9hPgogIDxhIGhyZWY9ICIwMy1yZXBvcnRlcy1JLmh0bWwiIGNsYXNzID0gImJ0biBidG4tcHJpbWFyeSI+U2lndWllbnRlPC9hPgo8L2Rpdj4=