Conceptos básicos de R

Determinar cuántas especies de diferentes taxones se han registrado en Edimburgo

Escrito por Ana María Montaño 08/03/2020 Universidad Nacional de Colombia

Para instalar un paquete se debe escribir install.packages(“package-name”), luego se pueden cargar los paquetes usando library(package name).

Para esta actividad se utilizará el paquete dplyr

install.package(“dplyr”) library(dplyr) # Note that there are quotation marks when installing a package, but not when loading it # and remember that hashtags let you add useful notes to your code!

setwd(“C:/Users/user/Documents/Intro_to_R”) getwd()

#2. Importar y verificar datos

#Se importaron los datos de biodiversidad de Edimburgo, y el directorio de trabajo donde se guardaron los datos es el siguiente:

edidiv <- read.csv("~/Intro_to_R/edidiv.csv")

#Ahora es importante verificar que los datos fueron importados sin errores. #Es una buena práctica ejecutar estos códigos que muestran los registros del primero y último dato, así como un resumen de los datos.

head(edidiv)  #Muestra las primeras filas, los primeros datos
tail(edidiv)  #Muestra los últimos datos, las últimas filas
str(edidiv)   #Indica si las variables son continuas, enteras, categóricas o caracteres
'data.frame':   25684 obs. of  5 variables:
 $ organisationName: Factor w/ 28 levels "BATS & The Millennium Link",..: 14 14 14 8 8 28 28 28 28 28 ...
 $ gridReference   : Factor w/ 1938 levels "NT200701","NT200712",..: 1314 569 569 1412 1412 1671 1671 1671 1671 1671 ...
 $ year            : int  2000 2000 2000 2000 2000 2001 2001 2001 2001 2001 ...
 $ taxonName       : Factor w/ 1275 levels "Acarospora fuscata",..: 1126 1126 1127 192 193 1202 365 977 472 947 ...
 $ taxonGroup      : Factor w/ 11 levels "Beetle","Bird",..: 2 2 2 2 2 2 2 2 2 2 ...

#str(object.name)es un comando que muestra la estructura de los datos

###La variable taxonGroup se muestra como una variable de carácter, y se va a pasar a variable categórica

head(edidiv$taxonGroup)  #Muestra solo las primeras filas de esta columna
[1] Bird Bird Bird Bird Bird Bird
11 Levels: Beetle Bird Butterfly Dragonfly Flowering.Plants ... Mollusc
class(edidiv$taxonGroup)   #Indica con qué tipo de variable se está trabajando: es carácter pero se desea que sea un factor
[1] "factor"
edidiv$taxonGroup <- as.factor(edidiv$taxonGroup)

#La función as.factor() va a convertir cualquier valor que se inserte dentro, en un factor.

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

#Información adicional

dim(edidiv)   #Muestra el número de filas y columnas
[1] 25684     5
summary(edidiv)  #Da un resumen de los datos
                                             organisationName
 Biological Records Centre                           :6744   
 RSPB                                                :5809   
 Butterfly Conservation                              :3000   
 Scottish Wildlife Trust                             :2070   
 Conchological Society of Great Britain &amp; Ireland:1998   
 The Wildlife Information Centre                     :1860   
 (Other)                                             :4203   
 gridReference        year                      taxonName    
 NT2673 : 2741   Min.   :2000   Maniola jurtina      : 1710  
 NT2773 : 2031   1st Qu.:2006   Aphantopus hyperantus: 1468  
 NT2873 : 1247   Median :2009   Turdus merula        : 1112  
 NT2570 : 1001   Mean   :2009   Lycaena phlaeas      :  972  
 NT27   :  888   3rd Qu.:2011   Aglais urticae       :  959  
 NT2871 :  767   Max.   :2016   Aglais io            :  720  
 (Other):17009                  (Other)              :18743  
            taxonGroup  
 Butterfly       :9670  
 Bird            :7366  
 Flowering.Plants:2625  
 Mollusc         :2226  
 Hymenopteran    :1391  
 Mammal          : 960  
 (Other)         :1446  
summary(edidiv$taxonGroup)  #Da un resumen de esa variable en particular en su conjunto de datos
          Beetle             Bird        Butterfly        Dragonfly 
             426             7366             9670              421 
Flowering.Plants           Fungus     Hymenopteran           Lichen 
            2625              334             1391              140 
       Liverwort           Mammal          Mollusc 
             125              960             2226 

#3. Calcular la riqueza de especies

##El objeto edidiv tiene los registros de ocurrencia de varias especies recolectadas en Edimburgo entre los años 2000 y 2016 ##Ahora se creará un gráfico que muestre cuántas especies se registraron en cada grupo taxonómico para explorar más acerca de la biodiversidad en esta ciudad ###La riqueza se puede calcular también en excel, pero presenta desventajas cuando se trabaja con grandes conjuntos de datos

##Riqueza: Número total de especies diferentes en un lugar dado #Para ello se usa la función filter() que dvide evidi en varios objetos, cada uno con filas para un solo grupo taxonómico.

library(dplyr)
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")

#Para calcular la riqueza se usan las funciones unique() que identifica 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))

#Ahora se corre cada letra para calcular la riqueza

a
[1] 37
b
[1] 86
c
[1] 25
d
[1] 11
e
[1] 521
f
[1] 219
g
[1] 112
h
[1] 94
i
[1] 40
j
[1] 33
k
[1] 97

#4. Crear un vector y trazarlo ##Un vector es un objeto de R que almacena valores ##Para crear el vector se usa la función c() y se agregan etiquetas con la función names()

biodiv <-  c(a,b,c,d,e,f,g,h,i,j,k)
biodiv
 [1]  37  86  25  11 521 219 112  94  40  33  97
names(biodiv) <- c("Beetle", 
                   "Bird",
                   "Butterfly",
                   "Dragonfly",
                   "Flowering.Plants", 
                   "Fungus", 
                   "Hymenopteran",
                   "Lichen", 
                   "Liverwort",
                   "Mammal",
                   "Mollusc")
names(biodiv)
 [1] "Beetle"           "Bird"             "Butterfly"       
 [4] "Dragonfly"        "Flowering.Plants" "Fungus"          
 [7] "Hymenopteran"     "Lichen"           "Liverwort"       
[10] "Mammal"           "Mollusc"         

#Se visualiza la riqueza con la siguiente función:

library(dplyr)
barplot(biodiv)

barplot 
function (height, ...) 
UseMethod("barplot")
<bytecode: 0x000001619a4d8848>
<environment: namespace:graphics>
help(barplot)
help(par)

#Se puede guardar el archivo envolviendo el código en png() y dev.off()

library(dplyr)
png("barplot.png", width = 1600, height = 600)
barplot(biodiv, xlab = "Taxón", ylab = "Número de especies", ylim = c(0,600),cex.names = 1.5, cex.axis = 1.5, cex.lab = 1.5)

barplot(biodiv)

#5. Crear un dataframe y trazarlo ##Se utiliza un dataframe cuando se tiene más de una variable y múltiples tipos de datos #Dataframe: tablas de valores de estructura bidimensional con filas y columnas. #Ahora se creará un dataframe con los datos de riqueza y luego se guardará usando write.csv()

taxa <- c("Beetle", 
          "Bird",
          "Butterfly",
          "Dragonfly",
          "Flowering.Plants", 
          "Fungus", 
          "Hymenopteran",
          "Lichen", 
          "Liverwort",
          "Mammal",
          "Mollusc")
taxa_f <- factor(taxa)
richness <- c(a,b,c,d,e,f,g,h,i,j,k)
biodata <- data.frame(taxa_f, richness)
biodata
write.csv(biodata, file = "biodata.csv")

#Si se quiere guardar un diagrama de barras usando el dataframe, se necesita cambiar el código, especificando columnas usando $

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 = "Taxón", ylab = "Número de especies", ylim = c(0,600))
dev.off()
null device 
          1 

#Ejercicio de aplicación ##Para calcular la media se usa la función mean()

gorrion <- mean(22, 24, 21)
martinpescador <- mean(26, 23, 25)
aguila <- mean(195, 201, 185)
colibri <- mean(8, 9, 9)

Envergadura <- c(gorrion, martinpescador, aguila, colibri)
Especiesaves <- c("gorrion", "martinpescador", "aguila", "colibri")
class(Especiesaves)
[1] "character"
Especiesaves <- as.factor(Especiesaves)
class(Especiesaves)
[1] "factor"
Aves <- data.frame(Especiesaves, Envergadura)

#Si se quiere guardar un diagrama de barras usando el dataframe, se necesita cambiar el código, especificando columnas usando $

png("avesplot3.png", width = 800, height = 600)
barplot(Aves$Envergadura, names.arg = Aves$Especiesaves,
xlab = "Especiesaves", ylab = "Envergadura", ylim = c(0,200),
col = "red")
dev.off()
null device 
          1 
Aves
LS0tDQp0aXRsZTogIkludHJvZHVjY2lvbl9hX1IiDQpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sNCi0tLQ0KIyBDb25jZXB0b3MgYsOhc2ljb3MgZGUgUg0KIyBEZXRlcm1pbmFyIGN1w6FudGFzIGVzcGVjaWVzIGRlIGRpZmVyZW50ZXMgdGF4b25lcyBzZSBoYW4gcmVnaXN0cmFkbyBlbiBFZGltYnVyZ28NCiMgRXNjcml0byBwb3IgQW5hIE1hcsOtYSBNb250YcOxbyAwOC8wMy8yMDIwIFVuaXZlcnNpZGFkIE5hY2lvbmFsIGRlIENvbG9tYmlhDQoNCiMjIyBQYXJhIGluc3RhbGFyIHVuIHBhcXVldGUgc2UgZGViZSBlc2NyaWJpciBpbnN0YWxsLnBhY2thZ2VzKCJwYWNrYWdlLW5hbWUiKSwgbHVlZ28gc2UgcHVlZGVuIGNhcmdhciBsb3MgcGFxdWV0ZXMgdXNhbmRvIGxpYnJhcnkocGFja2FnZSBuYW1lKS4NCiMgUGFyYSBlc3RhIGFjdGl2aWRhZCBzZSB1dGlsaXphcsOhIGVsIHBhcXVldGUgZHBseXINCg0KaW5zdGFsbC5wYWNrYWdlKCJkcGx5ciIpDQpsaWJyYXJ5KGRwbHlyKQ0KIyBOb3RlIHRoYXQgdGhlcmUgYXJlIHF1b3RhdGlvbiBtYXJrcyB3aGVuIGluc3RhbGxpbmcgYSBwYWNrYWdlLCBidXQgbm90IHdoZW4gbG9hZGluZyBpdA0KIyBhbmQgcmVtZW1iZXIgdGhhdCBoYXNodGFncyBsZXQgeW91IGFkZCB1c2VmdWwgbm90ZXMgdG8geW91ciBjb2RlIQ0KDQpzZXR3ZCgiQzovVXNlcnMvdXNlci9Eb2N1bWVudHMvSW50cm9fdG9fUiIpDQpnZXR3ZCgpDQoNCiMyLiBJbXBvcnRhciB5IHZlcmlmaWNhciBkYXRvcw0KDQojU2UgaW1wb3J0YXJvbiBsb3MgZGF0b3MgZGUgYmlvZGl2ZXJzaWRhZCBkZSBFZGltYnVyZ28sIHkgZWwgZGlyZWN0b3JpbyBkZSB0cmFiYWpvIGRvbmRlIHNlIGd1YXJkYXJvbiBsb3MgZGF0b3MgZXMgZWwgc2lndWllbnRlOg0KDQpgYGB7cn0NCmVkaWRpdiA8LSByZWFkLmNzdigifi9JbnRyb190b19SL2VkaWRpdi5jc3YiKQ0KYGBgDQoNCiNBaG9yYSBlcyBpbXBvcnRhbnRlIHZlcmlmaWNhciBxdWUgbG9zIGRhdG9zIGZ1ZXJvbiBpbXBvcnRhZG9zIHNpbiBlcnJvcmVzLiANCiNFcyB1bmEgYnVlbmEgcHLDoWN0aWNhIGVqZWN1dGFyIGVzdG9zIGPDs2RpZ29zIHF1ZSBtdWVzdHJhbiBsb3MgcmVnaXN0cm9zIGRlbCBwcmltZXJvIHkgw7psdGltbyBkYXRvLCBhc8OtIGNvbW8gdW4gcmVzdW1lbiBkZSBsb3MgZGF0b3MuDQoNCmBgYHtyfQ0KaGVhZChlZGlkaXYpICAjTXVlc3RyYSBsYXMgcHJpbWVyYXMgZmlsYXMsIGxvcyBwcmltZXJvcyBkYXRvcw0KdGFpbChlZGlkaXYpICAjTXVlc3RyYSBsb3Mgw7psdGltb3MgZGF0b3MsIGxhcyDDumx0aW1hcyBmaWxhcw0Kc3RyKGVkaWRpdikgICAjSW5kaWNhIHNpIGxhcyB2YXJpYWJsZXMgc29uIGNvbnRpbnVhcywgZW50ZXJhcywgY2F0ZWfDs3JpY2FzIG8gY2FyYWN0ZXJlcw0KYGBgDQoNCiNzdHIob2JqZWN0Lm5hbWUpZXMgdW4gY29tYW5kbyBxdWUgbXVlc3RyYSBsYSBlc3RydWN0dXJhIGRlIGxvcyBkYXRvcw0KDQojIyNMYSB2YXJpYWJsZSB0YXhvbkdyb3VwIHNlIG11ZXN0cmEgY29tbyB1bmEgdmFyaWFibGUgZGUgY2Fyw6FjdGVyLCB5IHNlIHZhIGEgcGFzYXIgYSB2YXJpYWJsZSBjYXRlZ8OzcmljYQ0KDQpgYGB7cn0NCmhlYWQoZWRpZGl2JHRheG9uR3JvdXApICAjTXVlc3RyYSBzb2xvIGxhcyBwcmltZXJhcyBmaWxhcyBkZSBlc3RhIGNvbHVtbmENCmNsYXNzKGVkaWRpdiR0YXhvbkdyb3VwKSAgICNJbmRpY2EgY29uIHF1w6kgdGlwbyBkZSB2YXJpYWJsZSBzZSBlc3TDoSB0cmFiYWphbmRvOiBlcyBjYXLDoWN0ZXIgcGVybyBzZSBkZXNlYSBxdWUgc2VhIHVuIGZhY3Rvcg0KZWRpZGl2JHRheG9uR3JvdXAgPC0gYXMuZmFjdG9yKGVkaWRpdiR0YXhvbkdyb3VwKQ0KYGBgDQoNCiNMYSBmdW5jacOzbiBhcy5mYWN0b3IoKSB2YSBhIGNvbnZlcnRpciBjdWFscXVpZXIgdmFsb3IgcXVlIHNlIGluc2VydGUgZGVudHJvLCBlbiB1biBmYWN0b3IuDQoNCmBgYHtyfQ0KY2xhc3MoZWRpZGl2JHRheG9uR3JvdXApDQpgYGANCg0KI0luZm9ybWFjacOzbiBhZGljaW9uYWwNCg0KYGBge3J9DQpkaW0oZWRpZGl2KSAgICNNdWVzdHJhIGVsIG7Dum1lcm8gZGUgZmlsYXMgeSBjb2x1bW5hcw0Kc3VtbWFyeShlZGlkaXYpICAjRGEgdW4gcmVzdW1lbiBkZSBsb3MgZGF0b3MNCnN1bW1hcnkoZWRpZGl2JHRheG9uR3JvdXApICAjRGEgdW4gcmVzdW1lbiBkZSBlc2EgdmFyaWFibGUgZW4gcGFydGljdWxhciBlbiBzdSBjb25qdW50byBkZSBkYXRvcw0KYGBgDQoNCiMzLiBDYWxjdWxhciBsYSByaXF1ZXphIGRlIGVzcGVjaWVzDQoNCiMjRWwgb2JqZXRvIGVkaWRpdiB0aWVuZSBsb3MgcmVnaXN0cm9zIGRlIG9jdXJyZW5jaWEgZGUgdmFyaWFzIGVzcGVjaWVzIHJlY29sZWN0YWRhcyBlbiBFZGltYnVyZ28gZW50cmUgbG9zIGHDsW9zIDIwMDAgeSAyMDE2DQojI0Fob3JhIHNlIGNyZWFyw6EgdW4gZ3LDoWZpY28gcXVlIG11ZXN0cmUgY3XDoW50YXMgZXNwZWNpZXMgc2UgcmVnaXN0cmFyb24gZW4gY2FkYSBncnVwbyB0YXhvbsOzbWljbyBwYXJhIGV4cGxvcmFyIG3DoXMgYWNlcmNhIGRlIGxhIGJpb2RpdmVyc2lkYWQgZW4gZXN0YSBjaXVkYWQNCiMjI0xhIHJpcXVlemEgc2UgcHVlZGUgY2FsY3VsYXIgdGFtYmnDqW4gZW4gZXhjZWwsIHBlcm8gcHJlc2VudGEgZGVzdmVudGFqYXMgY3VhbmRvIHNlIHRyYWJhamEgY29uIGdyYW5kZXMgY29uanVudG9zIGRlIGRhdG9zDQoNCiMjUmlxdWV6YTogTsO6bWVybyB0b3RhbCBkZSBlc3BlY2llcyBkaWZlcmVudGVzIGVuIHVuIGx1Z2FyIGRhZG8NCiNQYXJhIGVsbG8gc2UgdXNhIGxhIGZ1bmNpw7NuIGZpbHRlcigpIHF1ZSBkdmlkZSBldmlkaSBlbiB2YXJpb3Mgb2JqZXRvcywgY2FkYSB1bm8gY29uIGZpbGFzIHBhcmEgdW4gc29sbyBncnVwbyB0YXhvbsOzbWljby4NCg0KYGBge3J9DQpsaWJyYXJ5KGRwbHlyKQ0KQmVldGxlID0gZmlsdGVyKGVkaWRpdiwgdGF4b25Hcm91cCA9PSAiQmVldGxlIikgDQpCaXJkID0gZmlsdGVyKGVkaWRpdiwgdGF4b25Hcm91cCA9PSAiQmlyZCIpDQpCdXR0ZXJmbHkgPSBmaWx0ZXIoZWRpZGl2LCB0YXhvbkdyb3VwID09ICJCdXR0ZXJmbHkiKQ0KRHJhZ29uZmx5ID0gZmlsdGVyKGVkaWRpdiwgdGF4b25Hcm91cCA9PSAiRHJhZ29uZmx5IikNCkZsb3dlcmluZy5QbGFudHMgPSBmaWx0ZXIoZWRpZGl2LCB0YXhvbkdyb3VwID09ICJGbG93ZXJpbmcuUGxhbnRzIikNCkZ1bmd1cyA9IGZpbHRlcihlZGlkaXYsIHRheG9uR3JvdXAgPT0gIkZ1bmd1cyIpDQpIeW1lbm9wdGVyYW4gPSBmaWx0ZXIoZWRpZGl2LCB0YXhvbkdyb3VwID09ICJIeW1lbm9wdGVyYW4iKQ0KTGljaGVuID0gZmlsdGVyKGVkaWRpdiwgdGF4b25Hcm91cCA9PSAiTGljaGVuIikNCkxpdmVyd29ydCA9IGZpbHRlcihlZGlkaXYsIHRheG9uR3JvdXAgPT0gIkxpdmVyd29ydCIpDQpNYW1tYWwgPSBmaWx0ZXIoZWRpZGl2LCB0YXhvbkdyb3VwID09ICJNYW1tYWwiKQ0KTW9sbHVzYyA9IGZpbHRlcihlZGlkaXYsIHRheG9uR3JvdXAgPT0gIk1vbGx1c2MiKQ0KYGBgDQoNCiNQYXJhIGNhbGN1bGFyIGxhIHJpcXVlemEgc2UgdXNhbiBsYXMgZnVuY2lvbmVzIHVuaXF1ZSgpIHF1ZSBpZGVudGlmaWNhIGRpZmVyZW50ZXMgZXNwZWNpZXMgeSBsZW5ndGgoKSBxdWUgbGFzIGN1ZW50YS4NCg0KYGBge3J9DQphIDwtIGxlbmd0aCh1bmlxdWUoQmVldGxlJHRheG9uTmFtZSkpDQpiIDwtIGxlbmd0aCh1bmlxdWUoQmlyZCR0YXhvbk5hbWUpKQ0KYyA8LSBsZW5ndGgodW5pcXVlKEJ1dHRlcmZseSR0YXhvbk5hbWUpKQ0KZCA8LSBsZW5ndGgodW5pcXVlKERyYWdvbmZseSR0YXhvbk5hbWUpKQ0KZSA8LSBsZW5ndGgodW5pcXVlKEZsb3dlcmluZy5QbGFudHMkdGF4b25OYW1lKSkNCmYgPC0gbGVuZ3RoKHVuaXF1ZShGdW5ndXMkdGF4b25OYW1lKSkNCmcgPC0gbGVuZ3RoKHVuaXF1ZShIeW1lbm9wdGVyYW4kdGF4b25OYW1lKSkNCmggPC0gbGVuZ3RoKHVuaXF1ZShMaWNoZW4kdGF4b25OYW1lKSkNCmkgPC0gbGVuZ3RoKHVuaXF1ZShMaXZlcndvcnQkdGF4b25OYW1lKSkNCmogPC0gbGVuZ3RoKHVuaXF1ZShNYW1tYWwkdGF4b25OYW1lKSkNCmsgPC0gbGVuZ3RoKHVuaXF1ZShNb2xsdXNjJHRheG9uTmFtZSkpDQpgYGANCg0KI0Fob3JhIHNlIGNvcnJlIGNhZGEgbGV0cmEgcGFyYSBjYWxjdWxhciBsYSByaXF1ZXphDQoNCmBgYHtyfQ0KYQ0KYg0KYw0KZA0KZQ0KZg0KZw0KaA0KaQ0Kag0Kaw0KDQpgYGANCiM0LiBDcmVhciB1biB2ZWN0b3IgeSB0cmF6YXJsbw0KIyNVbiB2ZWN0b3IgZXMgdW4gb2JqZXRvIGRlIFIgcXVlIGFsbWFjZW5hIHZhbG9yZXMNCiMjUGFyYSBjcmVhciBlbCB2ZWN0b3Igc2UgdXNhIGxhIGZ1bmNpw7NuIGMoKSB5IHNlIGFncmVnYW4gZXRpcXVldGFzIGNvbiBsYSBmdW5jacOzbiBuYW1lcygpDQoNCmBgYHtyfQ0KYmlvZGl2IDwtICBjKGEsYixjLGQsZSxmLGcsaCxpLGosaykNCmJpb2Rpdg0KbmFtZXMoYmlvZGl2KSA8LSBjKCJCZWV0bGUiLCANCiAgICAgICAgICAgICAgICAgICAiQmlyZCIsDQogICAgICAgICAgICAgICAgICAgIkJ1dHRlcmZseSIsDQogICAgICAgICAgICAgICAgICAgIkRyYWdvbmZseSIsDQogICAgICAgICAgICAgICAgICAgIkZsb3dlcmluZy5QbGFudHMiLCANCiAgICAgICAgICAgICAgICAgICAiRnVuZ3VzIiwgDQogICAgICAgICAgICAgICAgICAgIkh5bWVub3B0ZXJhbiIsDQogICAgICAgICAgICAgICAgICAgIkxpY2hlbiIsIA0KICAgICAgICAgICAgICAgICAgICJMaXZlcndvcnQiLA0KICAgICAgICAgICAgICAgICAgICJNYW1tYWwiLA0KICAgICAgICAgICAgICAgICAgICJNb2xsdXNjIikNCm5hbWVzKGJpb2RpdikNCmBgYA0KDQojU2UgdmlzdWFsaXphIGxhIHJpcXVlemEgY29uIGxhIHNpZ3VpZW50ZSBmdW5jacOzbjoNCmBgYHtyfQ0KbGlicmFyeShkcGx5cikNCmJhcnBsb3QoYmlvZGl2KQ0KYmFycGxvdCANCg0KaGVscChiYXJwbG90KQ0KaGVscChwYXIpDQpgYGANCiNTZSBwdWVkZSBndWFyZGFyIGVsIGFyY2hpdm8gZW52b2x2aWVuZG8gZWwgY8OzZGlnbyBlbiBwbmcoKSB5IGRldi5vZmYoKQ0KDQpgYGB7cn0NCmxpYnJhcnkoZHBseXIpDQpwbmcoImJhcnBsb3QucG5nIiwgd2lkdGggPSAxNjAwLCBoZWlnaHQgPSA2MDApDQpiYXJwbG90KGJpb2RpdiwgeGxhYiA9ICJUYXjDs24iLCB5bGFiID0gIk7Dum1lcm8gZGUgZXNwZWNpZXMiLCB5bGltID0gYygwLDYwMCksY2V4Lm5hbWVzID0gMS41LCBjZXguYXhpcyA9IDEuNSwgY2V4LmxhYiA9IDEuNSkNCmRldi5vZmYoKQ0KYmFycGxvdChiaW9kaXYpDQpgYGANCiM1LiBDcmVhciB1biBkYXRhZnJhbWUgeSB0cmF6YXJsbw0KIyNTZSB1dGlsaXphIHVuIGRhdGFmcmFtZSBjdWFuZG8gc2UgdGllbmUgbcOhcyBkZSB1bmEgdmFyaWFibGUgeSBtw7psdGlwbGVzIHRpcG9zIGRlIGRhdG9zDQojRGF0YWZyYW1lOiB0YWJsYXMgZGUgdmFsb3JlcyBkZSBlc3RydWN0dXJhIGJpZGltZW5zaW9uYWwgY29uIGZpbGFzIHkgY29sdW1uYXMuDQojQWhvcmEgc2UgY3JlYXLDoSB1biBkYXRhZnJhbWUgY29uIGxvcyBkYXRvcyBkZSByaXF1ZXphIHkgbHVlZ28gc2UgZ3VhcmRhcsOhIHVzYW5kbyB3cml0ZS5jc3YoKQ0KYGBge3J9DQp0YXhhIDwtIGMoIkJlZXRsZSIsIA0KICAgICAgICAgICJCaXJkIiwNCiAgICAgICAgICAiQnV0dGVyZmx5IiwNCiAgICAgICAgICAiRHJhZ29uZmx5IiwNCiAgICAgICAgICAiRmxvd2VyaW5nLlBsYW50cyIsIA0KICAgICAgICAgICJGdW5ndXMiLCANCiAgICAgICAgICAiSHltZW5vcHRlcmFuIiwNCiAgICAgICAgICAiTGljaGVuIiwgDQogICAgICAgICAgIkxpdmVyd29ydCIsDQogICAgICAgICAgIk1hbW1hbCIsDQogICAgICAgICAgIk1vbGx1c2MiKQ0KdGF4YV9mIDwtIGZhY3Rvcih0YXhhKQ0KcmljaG5lc3MgPC0gYyhhLGIsYyxkLGUsZixnLGgsaSxqLGspDQpiaW9kYXRhIDwtIGRhdGEuZnJhbWUodGF4YV9mLCByaWNobmVzcykNCmJpb2RhdGENCndyaXRlLmNzdihiaW9kYXRhLCBmaWxlID0gImJpb2RhdGEuY3N2IikNCmBgYA0KDQojU2kgc2UgcXVpZXJlIGd1YXJkYXIgdW4gZGlhZ3JhbWEgZGUgYmFycmFzIHVzYW5kbyBlbCBkYXRhZnJhbWUsIHNlIG5lY2VzaXRhIGNhbWJpYXIgZWwgY8OzZGlnbywgZXNwZWNpZmljYW5kbyBjb2x1bW5hcyB1c2FuZG8gJA0KDQpgYGB7cn0NCnBuZygiYmFycGxvdDIucG5nIiwgd2lkdGggPSAxNjAwLCBoZWlnaHQgPSA2MDApDQpiYXJwbG90KGJpb2RhdGEkcmljaG5lc3MsIG5hbWVzLmFyZyA9IGMoIkJlZXRsZSIsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkJpcmQiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkJ1dHRlcmZseSIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiRHJhZ29uZmx5IiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJGbG93ZXJpbmcuUGxhbnRzIiwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiRnVuZ3VzIiwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiSHltZW5vcHRlcmFuIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJMaWNoZW4iLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJMaXZlcndvcnQiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIk1hbW1hbCIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiTW9sbHVzYyIpLA0KICAgICAgICB4bGFiID0gIlRheMOzbiIsIHlsYWIgPSAiTsO6bWVybyBkZSBlc3BlY2llcyIsIHlsaW0gPSBjKDAsNjAwKSkNCmRldi5vZmYoKQ0KYGBgDQojRWplcmNpY2lvIGRlIGFwbGljYWNpw7NuDQojI1BhcmEgY2FsY3VsYXIgbGEgbWVkaWEgc2UgdXNhIGxhIGZ1bmNpw7NuIG1lYW4oKQ0KDQpgYGB7cn0NCmdvcnJpb24gPC0gbWVhbigyMiwgMjQsIDIxKQ0KbWFydGlucGVzY2Fkb3IgPC0gbWVhbigyNiwgMjMsIDI1KQ0KYWd1aWxhIDwtIG1lYW4oMTk1LCAyMDEsIDE4NSkNCmNvbGlicmkgPC0gbWVhbig4LCA5LCA5KQ0KDQpFbnZlcmdhZHVyYSA8LSBjKGdvcnJpb24sIG1hcnRpbnBlc2NhZG9yLCBhZ3VpbGEsIGNvbGlicmkpDQpFc3BlY2llc2F2ZXMgPC0gYygiZ29ycmlvbiIsICJtYXJ0aW5wZXNjYWRvciIsICJhZ3VpbGEiLCAiY29saWJyaSIpDQpjbGFzcyhFc3BlY2llc2F2ZXMpDQpFc3BlY2llc2F2ZXMgPC0gYXMuZmFjdG9yKEVzcGVjaWVzYXZlcykNCmNsYXNzKEVzcGVjaWVzYXZlcykNCg0KQXZlcyA8LSBkYXRhLmZyYW1lKEVzcGVjaWVzYXZlcywgRW52ZXJnYWR1cmEpDQpgYGANCiNTaSBzZSBxdWllcmUgZ3VhcmRhciB1biBkaWFncmFtYSBkZSBiYXJyYXMgdXNhbmRvIGVsIGRhdGFmcmFtZSwgc2UgbmVjZXNpdGEgY2FtYmlhciBlbCBjw7NkaWdvLCBlc3BlY2lmaWNhbmRvIGNvbHVtbmFzIHVzYW5kbyAkDQpgYGB7cn0NCnBuZygiYXZlc3Bsb3QzLnBuZyIsIHdpZHRoID0gODAwLCBoZWlnaHQgPSA2MDApDQpiYXJwbG90KEF2ZXMkRW52ZXJnYWR1cmEsIG5hbWVzLmFyZyA9IEF2ZXMkRXNwZWNpZXNhdmVzLA0KeGxhYiA9ICJFc3BlY2llc2F2ZXMiLCB5bGFiID0gIkVudmVyZ2FkdXJhIiwgeWxpbSA9IGMoMCwyMDApLA0KY29sID0gInJlZCIpDQpkZXYub2ZmKCkNCkF2ZXMNCmBgYA0KDQo=