1. ¿Qué es R?

R es un lenguaje de programación estadística empleado para realizar varias funciones relacionadas a distintas disciplinas, como por ejemplo la cartografia o la estadistica.

2. Comenzando a escribir

Este cuaderno se desarrolla para la asignatura de Geomática Básica y corresponde a una breve introducción a R y sus funciones básicas. El documento fue realizado por Miguel Santiago Morales Ruiz. ### 3. Paquetes de R

Un paquete es un conjunto de comandos empleados para una función específica y se instalan con el siguiente codigo:

#install.packages("package name")

Para ejecutar los paquetes instalados se ejecuta el codigo Library de la siguiente manera:

#library(package-name)

Como ejemplo, se instalará el paquete dplyr

#install.packages("dplyr")
library(dplyr)

4.Directorio de trabajo

Es la carpeta en donde se guardaran y se buscaran los archivos que necesitamos para realizar un cuaderno de R, estos archivos una vez colocados no se pueden cambiar de lugar,con el comando getwd conocemos la ruta de lo archivos:

getwd()
[1] "C:/Users/HP LAPTOP/Documents"
 "C:/Users/HP LAPTOP/Desktop"
[1] "C:/Users/HP LAPTOP/Desktop"

En caso de que se quiera cambiar el directorio de trabajo, se usa la funcion setwd()

setwd("C:/Users/HP LAPTOP/Desktop")

5. Importar y verificar datos

Para realizar esta práctica es necesario descargar los registros entre 2000-2016 de NBN Gateway. Estos registros contienen información acerca de las especies de animales, plantas y hongos. Este archivo de excel se guardará como edidiv.csv. Después de descargar el archivo, se importa con el comando read.csv() o empleando herramientas de la consola.

read.csv()
Error in read.table(file = file, header = header, sep = sep, quote = quote,  : 
  el argumento "file" está ausente, sin valor por omisión

En el siguiente chunk se puede ver la ruta del archivo en donde se guardaron los datos:

edidiv <- read.csv("C:/Users/HP LAPTOP/Desktop/Semestre 2021 1/CC-RBasics-master/edidiv.csv")

6. ¿Cómo saber si se han cometido errores en los códigos?

Para tener una vista previa de los comandos que se han usado anteriormente se usa el comando head, el cual nos muestra una tabla de acuerdo a la informacion colocada anteriormente, de esta manera para no cometer errores mas adelante.

head()
Error in checkHT(n, dx <- dim(x)) : 
  el argumento "x" está ausente, sin valor por omisión

Esta opción nos permite ver las primeras filas:

head(edidiv)

tail()

Este comando muestra las últimas filas.

tail(edidiv)

str()

Esta opción indica si las variables son continuas, enteras, categóricas o caracteres.

str(edidiv)
'data.frame':   25684 obs. of  5 variables:
 $ organisationName: chr  "Joint Nature Conservation Committee" "Joint Nature Conservation Committee" "Joint Nature Conservation Committee" "British Trust for Ornithology" ...
 $ gridReference   : chr  "NT265775" "NT235775" "NT235775" "NT27" ...
 $ year            : int  2000 2000 2000 2000 2000 2001 2001 2001 2001 2001 ...
 $ taxonName       : chr  "Sterna hirundo" "Sterna hirundo" "Sterna paradisaea" "Branta canadensis" ...
 $ taxonGroup      : chr  "Bird" "Bird" "Bird" "Bird" ...

Para mirar la estructura de los datos se usa el comando str(object.name). Aunque, si se quiere cambiar la estructura, se realizan los siguientes pasos: Se emplea el cógigo head(nombre del archivo$grupo) para ver las primeras filas de la columna en esta clase.

head(edidiv$taxonGroup)
[1] "Bird" "Bird" "Bird" "Bird" "Bird" "Bird"

Se usa class(nombre del archivo$grupo) para saber con que tipo de variable se está trabajando

class(edidiv$taxonGroup)
[1] "character"

El siguiente comando, convierte cualquier valor colocado en un factor:

edidiv$taxonGroup <- as.factor(edidiv$taxonGroup)

Existen otros comandos que pueden ser utiles en distintos casos. Principalmente se trabajarán:

dim()

Es otro comando que permite ver el número de columnas y filas.

dim(edidiv)
[1] 25684     5

summary

Este comando da un resumen de los datos.

summary(edidiv)
 organisationName   gridReference           year     
 Length:25684       Length:25684       Min.   :2000  
 Class :character   Class :character   1st Qu.:2006  
 Mode  :character   Mode  :character   Median :2009  
                                       Mean   :2009  
                                       3rd Qu.:2011  
                                       Max.   :2016  
                                                     
  taxonName                    taxonGroup  
 Length:25684       Butterfly       :9670  
 Class :character   Bird            :7366  
 Mode  :character   Flowering.Plants:2625  
                    Mollusc         :2226  
                    Hymenopteran    :1391  
                    Mammal          : 960  
                    (Other)         :1446  

summary(-$-)

Da un breve resumen de una variable en particular.

summary(edidiv$taxonGroup)
          Beetle             Bird        Butterfly 
             426             7366             9670 
       Dragonfly Flowering.Plants           Fungus 
             421             2625              334 
    Hymenopteran           Lichen        Liverwort 
            1391              140              125 
          Mammal          Mollusc 
             960             2226 

7. Calcular la riqueza en especies

El comando filter() nos permiter dividir las variables de acuerdo a lo que mas se nos favorezca, en este caso, en grupos de taxonomia de distintas especies:

Beetle <- filter(edidiv, taxonGroup == "Beetle")
Bird <- filter(edidiv, taxonGroup == "Bird")
Butterfly <- filter(edidiv, taxonGroup == "Butterfly")
Dragonfly <- filter(edidiv, taxonGroup == "Dragonfly")
Flowering.Plants <- filter(edidiv, taxonGroup == "Flowering.Plants")
Fungus <- filter(edidiv, taxonGroup == "Fungus")
Hymenopteran <- filter(edidiv, taxonGroup == "Hymenopteran")
Lichen <- filter(edidiv, taxonGroup == "Lichen")
Liverwort <- filter(edidiv, taxonGroup == "Liverwort")
Mammal <- filter(edidiv, taxonGroup == "Mammal")
Mollusc <- filter(edidiv, taxonGroup == "Mollusc")

Ahora, se emplearán las funciones unique() que identifica las diferentes especies y length() que las cuenta.

a <- length(unique(Beetle$taxonName))
b <- length(unique(Bird$taxonName))
c <- length(unique(Butterfly$taxonName))
d <- length(unique(Dragonfly$taxonName))
e <- length(unique(Flowering.Plants$taxonName))
f <- length(unique(Fungus$taxonName))
g <- length(unique(Hymenopteran$taxonName))
h <- length(unique(Lichen$taxonName))
i <- length(unique(Liverwort$taxonName))
j <- length(unique(Mammal$taxonName))
k <- length(unique(Mollusc$taxonName))

8. Crear un vector y trazarlo

Un vector almacena valores en una única dimensión. Para crear un vector se emplea la función c()

biodiv <- c(a,b,c,d,e,f,g,h,i,j, k)
#Se están relacionando los valores en el mismo orden en el cual se escribieron anteriormente.
names(biodiv) <- c("Beetle", "Bird", "Butterfly", "Dragonfly", "Flowering.Plants", "Fungus", "Hymenopteran", "Lichen", "Liverwort", "Mammal", "Mollusc")

El codigo barplot nos muestra un diagrama de los datos usados anteriormente con esto se puede ver la diversidad y riqueza de especies.

help(barplot)
#Para obtener ayuda sólo con la función barplot.
help(par)
#Para tener ayuda con el trazado en general.

Para poder modificar el gráfico se pueden emplear distintos comandos como: -xlab y ylab que permiten nombrar los ejes -cex.names que permite modificar el tamaño de la fuente en el eje x -cex.axis que modifica el tamaño de fuente en el eje y -cex.lab que modifica el tamaño de fuente de los títulos de los ejes.

barplot(biodiv)

barplot(biodiv, xlab="Taxa", ylab="Number of species", ylim=c(0,600), cex.names= 0.45, cex.axis=0.9, cex.lab=1.0, col=c("darkblue","yellow"))

9. Crear un marco de datos y trazarlo

Para crear una serie de datos con etiquetas se utilizan objetos de marco de datos, con columnas y posteriormente se crea un objeto “taxa” y se usa el comando data frame

Para crear un objeto llamado “taxa” con todos los nombres del conjunto

taxa <- c("Beetle", "Bird", "Butterfly","Dragonfly","Flowering.Plants", "Fungus", "Hymenopteran", "Lichen", "Liverwort", "Mammal", "Mollusc")

Para convertir el objeto en un factor:

taxa_f <- factor(taxa)

Para combinar todos los valores en el número de especies “richness”

richness <- c(a,b,c,d,e,f,g,h,i,j,k)

Para crear un marco de datos a partir de dos vectores:

biodata <- data.frame(taxa_f, richness)

Para guardar el archivo en el directorio de trabajo:

write.csv(biodata, file ="biodata.csv")

En caso de que se quieran crear y guardar diagramas de barrasempleando sólo el marco de datos, se necesita cambiar un poco el código

png("barplot2.png", width=1600, height=600)
barplot(biodata$richness, names.arg=c("Beetle", "Bird", "Butterfly", "Dragonfly", "Flowering.Plants", "Fungus", "Hymenopteran", "Lichen", "Liverwort", "Mammal", "Mollusc"),
xlab="Taxa", ylab="Number of species", ylim=c(0,600))
dev.off()
null device 
          1 
LS0tDQp0aXRsZTogIkludHJvZHVjY2lvbiBhIFIiDQpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sNCkF1dGhvcjogTWlndWVsIFNhbnRpYWdvIE1vcmFsZXMgUnVpeg0KRGF0ZTogMDcvMDMvMjAyMQ0KLS0tDQojIyMgMS4gwr9RdcOpIGVzIFI/DQoNClIgZXMgdW4gbGVuZ3VhamUgZGUgcHJvZ3JhbWFjacOzbiBlc3RhZMOtc3RpY2EgZW1wbGVhZG8gcGFyYSByZWFsaXphciB2YXJpYXMgZnVuY2lvbmVzIHJlbGFjaW9uYWRhcyBhIGRpc3RpbnRhcyBkaXNjaXBsaW5hcywgY29tbyBwb3IgZWplbXBsbyBsYSBjYXJ0b2dyYWZpYSBvIGxhIGVzdGFkaXN0aWNhLg0KDQojIyMgMi4gQ29tZW56YW5kbyBhIGVzY3JpYmlyDQoNCkVzdGUgY3VhZGVybm8gc2UgZGVzYXJyb2xsYSBwYXJhIGxhIGFzaWduYXR1cmEgZGUgR2VvbcOhdGljYSBCw6FzaWNhIHkgY29ycmVzcG9uZGUgYSB1bmEgYnJldmUgaW50cm9kdWNjacOzbiBhIFIgeSBzdXMgZnVuY2lvbmVzIGLDoXNpY2FzLiBFbCBkb2N1bWVudG8gZnVlIHJlYWxpemFkbyBwb3IgTWlndWVsIFNhbnRpYWdvIE1vcmFsZXMgUnVpei4NCiMjIyAzLiBQYXF1ZXRlcyBkZSBSDQoNClVuIHBhcXVldGUgZXMgdW4gY29uanVudG8gZGUgY29tYW5kb3MgZW1wbGVhZG9zIHBhcmEgdW5hIGZ1bmNpw7NuIGVzcGVjw61maWNhIHkgc2UgaW5zdGFsYW4gY29uIGVsIHNpZ3VpZW50ZSBjb2RpZ286DQoNCmBgYHtyfQ0KI2luc3RhbGwucGFja2FnZXMoInBhY2thZ2UgbmFtZSIpDQpgYGANClBhcmEgZWplY3V0YXIgbG9zIHBhcXVldGVzIGluc3RhbGFkb3Mgc2UgZWplY3V0YSBlbCBjb2RpZ28gKkxpYnJhcnkqIGRlIGxhIHNpZ3VpZW50ZSBtYW5lcmE6DQpgYGB7cn0NCiNsaWJyYXJ5KHBhY2thZ2UtbmFtZSkNCmBgYA0KQ29tbyBlamVtcGxvLCBzZSBpbnN0YWxhcsOhIGVsIHBhcXVldGUgZHBseXINCmBgYHtyfQ0KI2luc3RhbGwucGFja2FnZXMoImRwbHlyIikNCmxpYnJhcnkoZHBseXIpDQpgYGANCiMjIyA0LkRpcmVjdG9yaW8gZGUgdHJhYmFqbw0KDQpFcyBsYSBjYXJwZXRhIGVuIGRvbmRlIHNlIGd1YXJkYXJhbiB5IHNlIGJ1c2NhcmFuIGxvcyBhcmNoaXZvcyBxdWUgbmVjZXNpdGFtb3MgcGFyYSByZWFsaXphciB1biBjdWFkZXJubyBkZSBSLCBlc3RvcyBhcmNoaXZvcyB1bmEgdmV6IGNvbG9jYWRvcyBubyBzZSBwdWVkZW4gY2FtYmlhciBkZSBsdWdhcixjb24gZWwgY29tYW5kbyBnZXR3ZCBjb25vY2Vtb3MgbGEgcnV0YSBkZSBsbyBhcmNoaXZvczogDQoNCmBgYHtyfQ0KZ2V0d2QoKQ0KICJDOi9Vc2Vycy9IUCBMQVBUT1AvRGVza3RvcCINCmBgYA0KRW4gY2FzbyBkZSBxdWUgc2UgcXVpZXJhIGNhbWJpYXIgZWwgZGlyZWN0b3JpbyBkZSB0cmFiYWpvLCBzZSB1c2EgbGEgZnVuY2lvbiBzZXR3ZCgpDQoNCmBgYHtyfQ0Kc2V0d2QoIkM6L1VzZXJzL0hQIExBUFRPUC9EZXNrdG9wIikNCg0KYGBgDQojIyMgNS4gSW1wb3J0YXIgeSB2ZXJpZmljYXIgZGF0b3MNCg0KUGFyYSByZWFsaXphciBlc3RhIHByw6FjdGljYSBlcyBuZWNlc2FyaW8gZGVzY2FyZ2FyIGxvcyByZWdpc3Ryb3MgZW50cmUgMjAwMC0yMDE2IGRlIE5CTiBHYXRld2F5LiBFc3RvcyByZWdpc3Ryb3MgY29udGllbmVuIGluZm9ybWFjacOzbiBhY2VyY2EgZGUgbGFzIGVzcGVjaWVzIGRlIGFuaW1hbGVzLCBwbGFudGFzIHkgaG9uZ29zLiBFc3RlIGFyY2hpdm8gZGUgZXhjZWwgc2UgZ3VhcmRhcsOhIGNvbW8gZWRpZGl2LmNzdi4gRGVzcHXDqXMgZGUgZGVzY2FyZ2FyIGVsIGFyY2hpdm8sIHNlIGltcG9ydGEgY29uIGVsIGNvbWFuZG8gcmVhZC5jc3YoKSBvIGVtcGxlYW5kbyBoZXJyYW1pZW50YXMgZGUgbGEgY29uc29sYS4NCmBgYHtyfQ0KcmVhZC5jc3YoKQ0KDQpgYGANCkVuIGVsIHNpZ3VpZW50ZSBjaHVuayBzZSBwdWVkZSB2ZXIgbGEgcnV0YSBkZWwgYXJjaGl2byBlbiBkb25kZSBzZSBndWFyZGFyb24gbG9zIGRhdG9zOg0KYGBge3J9DQplZGlkaXYgPC0gcmVhZC5jc3YoIkM6L1VzZXJzL0hQIExBUFRPUC9EZXNrdG9wL1NlbWVzdHJlIDIwMjEgMS9DQy1SQmFzaWNzLW1hc3Rlci9lZGlkaXYuY3N2IikNCg0KYGBgDQoNCiMjIyA2LiDCv0PDs21vIHNhYmVyIHNpIHNlIGhhbiBjb21ldGlkbyBlcnJvcmVzIGVuIGxvcyBjw7NkaWdvcz8NCg0KUGFyYSB0ZW5lciB1bmEgdmlzdGEgcHJldmlhIGRlIGxvcyBjb21hbmRvcyBxdWUgc2UgaGFuIHVzYWRvIGFudGVyaW9ybWVudGUgc2UgdXNhIGVsIGNvbWFuZG8gaGVhZCwgZWwgY3VhbCBub3MgbXVlc3RyYSB1bmEgdGFibGEgZGUgYWN1ZXJkbyBhIGxhIGluZm9ybWFjaW9uIGNvbG9jYWRhIGFudGVyaW9ybWVudGUsIGRlIGVzdGEgbWFuZXJhIHBhcmEgbm8gY29tZXRlciBlcnJvcmVzIG1hcyBhZGVsYW50ZS4NCmBgYHtyfQ0KaGVhZCgpDQpgYGANCkVzdGEgb3BjacOzbiBub3MgcGVybWl0ZSB2ZXIgbGFzIHByaW1lcmFzIGZpbGFzOg0KYGBge3J9DQpoZWFkKGVkaWRpdikNCmBgYA0KdGFpbCgpDQoNCkVzdGUgY29tYW5kbyBtdWVzdHJhIGxhcyDDumx0aW1hcyBmaWxhcy4NCg0KYGBge3J9DQp0YWlsKGVkaWRpdikNCmBgYA0Kc3RyKCkNCg0KRXN0YSBvcGNpw7NuIGluZGljYSBzaSBsYXMgdmFyaWFibGVzIHNvbiBjb250aW51YXMsIGVudGVyYXMsIGNhdGVnw7NyaWNhcyBvIGNhcmFjdGVyZXMuDQpgYGB7cn0NCnN0cihlZGlkaXYpDQpgYGANClBhcmEgbWlyYXIgbGEgZXN0cnVjdHVyYSBkZSBsb3MgZGF0b3Mgc2UgdXNhIGVsIGNvbWFuZG8gc3RyKG9iamVjdC5uYW1lKS4gQXVucXVlLCBzaSBzZSBxdWllcmUgY2FtYmlhciBsYSBlc3RydWN0dXJhLCBzZSByZWFsaXphbiBsb3Mgc2lndWllbnRlcyBwYXNvczogU2UgZW1wbGVhIGVsIGPDs2dpZ28gaGVhZChub21icmUgZGVsIGFyY2hpdm8kZ3J1cG8pIHBhcmEgdmVyIGxhcyBwcmltZXJhcyBmaWxhcyBkZSBsYSBjb2x1bW5hIGVuIGVzdGEgY2xhc2UuDQpgYGB7cn0NCmhlYWQoZWRpZGl2JHRheG9uR3JvdXApDQpgYGANClNlIHVzYSBjbGFzcyhub21icmUgZGVsIGFyY2hpdm8kZ3J1cG8pIHBhcmEgc2FiZXIgY29uIHF1ZSB0aXBvIGRlIHZhcmlhYmxlIHNlIGVzdMOhIHRyYWJhamFuZG8NCmBgYHtyfQ0KY2xhc3MoZWRpZGl2JHRheG9uR3JvdXApDQpgYGANCkVsIHNpZ3VpZW50ZSBjb21hbmRvLCBjb252aWVydGUgY3VhbHF1aWVyIHZhbG9yIGNvbG9jYWRvIGVuIHVuIGZhY3RvcjoNCmBgYHtyfQ0KZWRpZGl2JHRheG9uR3JvdXAgPC0gYXMuZmFjdG9yKGVkaWRpdiR0YXhvbkdyb3VwKQ0KYGBgDQpFeGlzdGVuIG90cm9zIGNvbWFuZG9zIHF1ZSBwdWVkZW4gc2VyIHV0aWxlcyBlbiBkaXN0aW50b3MgY2Fzb3MuIFByaW5jaXBhbG1lbnRlIHNlIHRyYWJhamFyw6FuOg0KDQpkaW0oKQ0KDQpFcyBvdHJvIGNvbWFuZG8gcXVlIHBlcm1pdGUgdmVyIGVsIG7Dum1lcm8gZGUgY29sdW1uYXMgeSBmaWxhcy4NCmBgYHtyfQ0KZGltKGVkaWRpdikNCmBgYA0Kc3VtbWFyeQ0KDQpFc3RlIGNvbWFuZG8gZGEgdW4gcmVzdW1lbiBkZSBsb3MgZGF0b3MuDQoNCmBgYHtyfQ0Kc3VtbWFyeShlZGlkaXYpDQpgYGANCnN1bW1hcnkoLSQtKQ0KDQpEYSB1biBicmV2ZSByZXN1bWVuIGRlIHVuYSB2YXJpYWJsZSBlbiBwYXJ0aWN1bGFyLg0KYGBge3J9DQpzdW1tYXJ5KGVkaWRpdiR0YXhvbkdyb3VwKQ0KYGBgDQojIyMgNy4gQ2FsY3VsYXIgbGEgcmlxdWV6YSBlbiBlc3BlY2llcw0KDQpFbCBjb21hbmRvIGZpbHRlcigpIG5vcyBwZXJtaXRlciBkaXZpZGlyIGxhcyB2YXJpYWJsZXMgZGUgYWN1ZXJkbyBhIGxvIHF1ZSBtYXMgc2Ugbm9zIGZhdm9yZXpjYSwgZW4gZXN0ZSBjYXNvLCBlbiBncnVwb3MgZGUgdGF4b25vbWlhIGRlIGRpc3RpbnRhcyBlc3BlY2llczoNCmBgYHtyfQ0KQmVldGxlIDwtIGZpbHRlcihlZGlkaXYsIHRheG9uR3JvdXAgPT0gIkJlZXRsZSIpDQpCaXJkIDwtIGZpbHRlcihlZGlkaXYsIHRheG9uR3JvdXAgPT0gIkJpcmQiKQ0KQnV0dGVyZmx5IDwtIGZpbHRlcihlZGlkaXYsIHRheG9uR3JvdXAgPT0gIkJ1dHRlcmZseSIpDQpEcmFnb25mbHkgPC0gZmlsdGVyKGVkaWRpdiwgdGF4b25Hcm91cCA9PSAiRHJhZ29uZmx5IikNCkZsb3dlcmluZy5QbGFudHMgPC0gZmlsdGVyKGVkaWRpdiwgdGF4b25Hcm91cCA9PSAiRmxvd2VyaW5nLlBsYW50cyIpDQpGdW5ndXMgPC0gZmlsdGVyKGVkaWRpdiwgdGF4b25Hcm91cCA9PSAiRnVuZ3VzIikNCkh5bWVub3B0ZXJhbiA8LSBmaWx0ZXIoZWRpZGl2LCB0YXhvbkdyb3VwID09ICJIeW1lbm9wdGVyYW4iKQ0KTGljaGVuIDwtIGZpbHRlcihlZGlkaXYsIHRheG9uR3JvdXAgPT0gIkxpY2hlbiIpDQpMaXZlcndvcnQgPC0gZmlsdGVyKGVkaWRpdiwgdGF4b25Hcm91cCA9PSAiTGl2ZXJ3b3J0IikNCk1hbW1hbCA8LSBmaWx0ZXIoZWRpZGl2LCB0YXhvbkdyb3VwID09ICJNYW1tYWwiKQ0KTW9sbHVzYyA8LSBmaWx0ZXIoZWRpZGl2LCB0YXhvbkdyb3VwID09ICJNb2xsdXNjIikNCmBgYA0KQWhvcmEsIHNlIGVtcGxlYXLDoW4gbGFzIGZ1bmNpb25lcyB1bmlxdWUoKSBxdWUgaWRlbnRpZmljYSBsYXMgZGlmZXJlbnRlcyBlc3BlY2llcyB5IGxlbmd0aCgpIHF1ZSBsYXMgY3VlbnRhLg0KYGBge3J9DQphIDwtIGxlbmd0aCh1bmlxdWUoQmVldGxlJHRheG9uTmFtZSkpDQpiIDwtIGxlbmd0aCh1bmlxdWUoQmlyZCR0YXhvbk5hbWUpKQ0KYyA8LSBsZW5ndGgodW5pcXVlKEJ1dHRlcmZseSR0YXhvbk5hbWUpKQ0KZCA8LSBsZW5ndGgodW5pcXVlKERyYWdvbmZseSR0YXhvbk5hbWUpKQ0KZSA8LSBsZW5ndGgodW5pcXVlKEZsb3dlcmluZy5QbGFudHMkdGF4b25OYW1lKSkNCmYgPC0gbGVuZ3RoKHVuaXF1ZShGdW5ndXMkdGF4b25OYW1lKSkNCmcgPC0gbGVuZ3RoKHVuaXF1ZShIeW1lbm9wdGVyYW4kdGF4b25OYW1lKSkNCmggPC0gbGVuZ3RoKHVuaXF1ZShMaWNoZW4kdGF4b25OYW1lKSkNCmkgPC0gbGVuZ3RoKHVuaXF1ZShMaXZlcndvcnQkdGF4b25OYW1lKSkNCmogPC0gbGVuZ3RoKHVuaXF1ZShNYW1tYWwkdGF4b25OYW1lKSkNCmsgPC0gbGVuZ3RoKHVuaXF1ZShNb2xsdXNjJHRheG9uTmFtZSkpDQpgYGANCiMjIyA4LiBDcmVhciB1biB2ZWN0b3IgeSB0cmF6YXJsbyANClVuIHZlY3RvciBhbG1hY2VuYSB2YWxvcmVzIGVuIHVuYSDDum5pY2EgZGltZW5zacOzbi4gUGFyYSBjcmVhciB1biB2ZWN0b3Igc2UgZW1wbGVhIGxhIGZ1bmNpw7NuIGMoKQ0KYGBge3J9DQpiaW9kaXYgPC0gYyhhLGIsYyxkLGUsZixnLGgsaSxqLCBrKQ0KI1NlIGVzdMOhbiByZWxhY2lvbmFuZG8gbG9zIHZhbG9yZXMgZW4gZWwgbWlzbW8gb3JkZW4gZW4gZWwgY3VhbCBzZSBlc2NyaWJpZXJvbiBhbnRlcmlvcm1lbnRlLg0KbmFtZXMoYmlvZGl2KSA8LSBjKCJCZWV0bGUiLCAiQmlyZCIsICJCdXR0ZXJmbHkiLCAiRHJhZ29uZmx5IiwgIkZsb3dlcmluZy5QbGFudHMiLCAiRnVuZ3VzIiwgIkh5bWVub3B0ZXJhbiIsICJMaWNoZW4iLCAiTGl2ZXJ3b3J0IiwgIk1hbW1hbCIsICJNb2xsdXNjIikNCmBgYA0KRWwgY29kaWdvIGJhcnBsb3Qgbm9zIG11ZXN0cmEgdW4gZGlhZ3JhbWEgZGUgbG9zIGRhdG9zIHVzYWRvcyBhbnRlcmlvcm1lbnRlIGNvbiBlc3RvIHNlIHB1ZWRlIHZlciBsYSBkaXZlcnNpZGFkIHkgcmlxdWV6YSBkZSBlc3BlY2llcy4NCmBgYHtyfQ0KaGVscChiYXJwbG90KQ0KI1BhcmEgb2J0ZW5lciBheXVkYSBzw7NsbyBjb24gbGEgZnVuY2nDs24gYmFycGxvdC4NCmhlbHAocGFyKQ0KI1BhcmEgdGVuZXIgYXl1ZGEgY29uIGVsIHRyYXphZG8gZW4gZ2VuZXJhbC4NCmBgYA0KUGFyYSBwb2RlciBtb2RpZmljYXIgZWwgZ3LDoWZpY28gc2UgcHVlZGVuIGVtcGxlYXIgZGlzdGludG9zIGNvbWFuZG9zIGNvbW86IC14bGFiIHkgeWxhYiBxdWUgcGVybWl0ZW4gbm9tYnJhciBsb3MgZWplcyAtY2V4Lm5hbWVzIHF1ZSBwZXJtaXRlIG1vZGlmaWNhciBlbCB0YW1hw7FvIGRlIGxhIGZ1ZW50ZSBlbiBlbCBlamUgeCAtY2V4LmF4aXMgcXVlIG1vZGlmaWNhIGVsIHRhbWHDsW8gZGUgZnVlbnRlIGVuIGVsIGVqZSB5IC1jZXgubGFiIHF1ZSBtb2RpZmljYSBlbCB0YW1hw7FvIGRlIGZ1ZW50ZSBkZSBsb3MgdMOtdHVsb3MgZGUgbG9zIGVqZXMuDQoNCmBgYHtyfQ0KYmFycGxvdChiaW9kaXYpDQpgYGANCmBgYHtyfQ0KYmFycGxvdChiaW9kaXYsIHhsYWI9IlRheGEiLCB5bGFiPSJOdW1iZXIgb2Ygc3BlY2llcyIsIHlsaW09YygwLDYwMCksIGNleC5uYW1lcz0gMC40NSwgY2V4LmF4aXM9MC45LCBjZXgubGFiPTEuMCwgY29sPWMoImRhcmtibHVlIiwieWVsbG93IikpDQoNCmBgYA0KIyMjIDkuIENyZWFyIHVuIG1hcmNvIGRlIGRhdG9zIHkgdHJhemFybG8NCg0KUGFyYSBjcmVhciB1bmEgc2VyaWUgZGUgZGF0b3MgY29uIGV0aXF1ZXRhcyBzZSB1dGlsaXphbiBvYmpldG9zIGRlIG1hcmNvIGRlIGRhdG9zLCBjb24gY29sdW1uYXMgeSBwb3N0ZXJpb3JtZW50ZSBzZSBjcmVhIHVuIG9iamV0byAidGF4YSIgeSBzZSB1c2EgZWwgY29tYW5kbyBkYXRhIGZyYW1lDQoNClBhcmEgY3JlYXIgdW4gb2JqZXRvIGxsYW1hZG8g4oCcdGF4YeKAnSBjb24gdG9kb3MgbG9zIG5vbWJyZXMgZGVsIGNvbmp1bnRvDQpgYGB7cn0NCnRheGEgPC0gYygiQmVldGxlIiwgIkJpcmQiLCAiQnV0dGVyZmx5IiwiRHJhZ29uZmx5IiwiRmxvd2VyaW5nLlBsYW50cyIsICJGdW5ndXMiLCAiSHltZW5vcHRlcmFuIiwgIkxpY2hlbiIsICJMaXZlcndvcnQiLCAiTWFtbWFsIiwgIk1vbGx1c2MiKQ0KYGBgDQpQYXJhIGNvbnZlcnRpciBlbCBvYmpldG8gZW4gdW4gZmFjdG9yOg0KYGBge3J9DQp0YXhhX2YgPC0gZmFjdG9yKHRheGEpDQpgYGANClBhcmEgY29tYmluYXIgdG9kb3MgbG9zIHZhbG9yZXMgZW4gZWwgbsO6bWVybyBkZSBlc3BlY2llcyDigJxyaWNobmVzc+KAnQ0KYGBge3J9DQpyaWNobmVzcyA8LSBjKGEsYixjLGQsZSxmLGcsaCxpLGosaykNCmBgYA0KUGFyYSBjcmVhciB1biBtYXJjbyBkZSBkYXRvcyBhIHBhcnRpciBkZSBkb3MgdmVjdG9yZXM6DQpgYGB7cn0NCmJpb2RhdGEgPC0gZGF0YS5mcmFtZSh0YXhhX2YsIHJpY2huZXNzKQ0KYGBgDQpQYXJhIGd1YXJkYXIgZWwgYXJjaGl2byBlbiBlbCBkaXJlY3RvcmlvIGRlIHRyYWJham86DQpgYGB7cn0NCndyaXRlLmNzdihiaW9kYXRhLCBmaWxlID0iYmlvZGF0YS5jc3YiKQ0KYGBgDQpFbiBjYXNvIGRlIHF1ZSBzZSBxdWllcmFuIGNyZWFyIHkgZ3VhcmRhciBkaWFncmFtYXMgZGUgYmFycmFzZW1wbGVhbmRvIHPDs2xvIGVsIG1hcmNvIGRlIGRhdG9zLCBzZSBuZWNlc2l0YSBjYW1iaWFyIHVuIHBvY28gZWwgY8OzZGlnbw0KDQpgYGB7cn0NCnBuZygiYmFycGxvdDIucG5nIiwgd2lkdGg9MTYwMCwgaGVpZ2h0PTYwMCkNCmJhcnBsb3QoYmlvZGF0YSRyaWNobmVzcywgbmFtZXMuYXJnPWMoIkJlZXRsZSIsICJCaXJkIiwgIkJ1dHRlcmZseSIsICJEcmFnb25mbHkiLCAiRmxvd2VyaW5nLlBsYW50cyIsICJGdW5ndXMiLCAiSHltZW5vcHRlcmFuIiwgIkxpY2hlbiIsICJMaXZlcndvcnQiLCAiTWFtbWFsIiwgIk1vbGx1c2MiKSwNCnhsYWI9IlRheGEiLCB5bGFiPSJOdW1iZXIgb2Ygc3BlY2llcyIsIHlsaW09YygwLDYwMCkpDQpkZXYub2ZmKCkNCmBgYA0KDQoNCg0KDQoNCg0KDQoNCg0KDQoNCg0KDQoNCg0KDQoNCg0KDQoNCg==