library(data.table)
Registered S3 method overwritten by 'data.table':
  method           from
  print.data.table     
data.table 1.14.0 using 3 threads (see ?getDTthreads).  Latest news: r-datatable.com

Attaching package: 㤼㸱data.table㤼㸲

The following object is masked _by_ 㤼㸱.GlobalEnv㤼㸲:

    .N
library(tidyverse)
Registered S3 methods overwritten by 'dbplyr':
  method         from
  print.tbl_lazy     
  print.tbl_sql      
-- Attaching packages ----------------------------------------- tidyverse 1.3.1 --
v ggplot2 3.3.3     v purrr   0.3.4
v tibble  3.1.1     v dplyr   1.0.5
v tidyr   1.1.3     v stringr 1.4.0
v readr   1.4.0     v forcats 0.5.1
-- Conflicts -------------------------------------------- tidyverse_conflicts() --
x dplyr::between()   masks data.table::between()
x dplyr::filter()    masks stats::filter()
x dplyr::first()     masks data.table::first()
x dplyr::lag()       masks stats::lag()
x dplyr::last()      masks data.table::last()
x purrr::transpose() masks data.table::transpose()
library(leaflet) # Mapas
library(sp)
library(broom)
library(janitor) #Paquete para limpiar datos

Attaching package: 㤼㸱janitor㤼㸲

The following objects are masked from 㤼㸱package:stats㤼㸲:

    chisq.test, fisher.test
library(rgbif) #Datos para ejemplo de mapas
library(sf) #Geografia
Linking to GEOS 3.9.0, GDAL 3.2.1, PROJ 7.2.1
library(chilemapas) #Geograía de Chile
Registered S3 method overwritten by 'geojsonlint':
  method         from 
  print.location dplyr
library(data.table)

Mapas con Leaflet

#Leaflet es una de las librerías abiertas más populares y reconocidas de JavaScript. El #paquete de R con el mismo nombre nos permite crear mapas interactivos. Probablemente ya han #visto mapas de leaflet antes, porque muchísimas páginas web las utilizan, como por ejemplo #http://openstreetmap.org.

#leaflet funciona por capas, y al igual que en ggplot existen muchísimas capas disponibles #para mejorar el aspecto de nuestros mapas. Hoy veremos:

#- Map Tiles: Elegimos el tipo de mapa que queremos. (addTiles, addProviderTiles) #- Markers: Marcadores específicos en un punto del mapa (latitud y longitud) (addMarkers (lat= lng=), addAwesomeMarkers) #- Polígonos: una región específica del mapa, como por ejemplo una comuna.

#Para hacer nuestro primer mapa simple, vayamos a Google Maps para encontrar las coordenadas de la unviersidad. Aquí hacemos mapas con diferentes Provider Tiles

leaflet() %>% 
  addTiles() %>%   # Por defecto
  addMarkers(lat=-33.414308757047465, lng=-70.55307645736842)


mapa <- leaflet() %>% 
  addProviderTiles(providers$Stamen.Toner) %>% 
  addAwesomeMarkers(lat=-33.414308757047465, lng=-70.55307645736842)

mapa

leaflet() %>% 
  addProviderTiles(providers$CartoDB.Positron) %>% 
  addMarkers(lat=-33.414308757047465, lng=-70.5530764573684)

Mapa de la RM con datos del MINEDUC

#Ahora, vamos a aprender a agregar layers como marcadores o polígonos.

#Abrir la base de datos Rendimiento_2018.csv. Esta representa el rendimiento escolar de #alumnos de octavo básico de la Región Metropolitana, para el año 2018.

#Ahora podemos empezar a explorar nuestros datos. Primero hagamos un gráfico simple para ver la distribución de las notas en la muestra completa:

#Podemos hacer un análisis más profundo y separar los datos por género. Con esto, podemos ver diferencias entre el rendimiento de niños y niñas. (Hombres gen_alu=1 y mujeres gen_alu=2) #facet_wrap se separa el gráfico

#Ahora vamos a los mapas:

##Primero, vamos a abrir los datos georeferenciales de las comunas de Santiago, desde el paquete de CRAN chilemapas. Este paquete tiene información para generar mapas de las divisiones políticas y adminsitrativas de Chile. Incluye información a nivel comunal, provincial y regional (entre otros). Es muy útil ya que nos entrega la geometría de cada unidad geográfica que quedamos mapear. En este caso, vamos a hacer un mapa de la RM por comuna. ###Una vez que cargamos el paquete, podemos crear objetos con los datos que necesitamos. En este caso, vamos a usar la función filter del paquete dplyr para quedarnos solo con las comunas de la Región Metropolitana.

##Juntamos las comunas de los alumnos con las comunas del mapa.

##Para identificar diferencias entre las comunas de Santiago, vamos a mapear el promedio general de los alumnos, por comuna (esta base de datos, por simplicidad, solo tiene a los alumnos que aprobaron). Esto nos mostrará una representación del promedio general promedio en cada comuna, en un mapa del Gran Santiago. ###Primero, creamos la variable de promedio general:

#Luego, con distinct nos quedamos solo con una observación por comuna, y seleccionamos solo las variables relevantes para crear el mapa en un nuevo objeto. Luego lo transformamos a formato sf para poder trabajar con leaflet

notas_geo <- distinct(notas_geo) %>% 
  select(codigo_comuna, geometry, nota)
Error in distinct(notas_geo) %>% select(codigo_comuna, geometry, nota) : 
  no se pudo encontrar la función "%>%"

#Ahora, creemos un mapa. #Con el paquete RColorBrewer podemos elegir muchas paletas de colores preexistentes. Con display.brewer.all() podemos verlas y elegir otra.

pal <- colorNumeric(    # definimos la paleta de colores
  palette = "PuRd",
  domain = rend_2018_geo$nota)


mapa <- leaflet() %>% 
  addProviderTiles(providers$CartoDB.Positron) %>% 
  addPolygons(data = notas_geo,
              fillColor = ~pal(nota),
              color = "#b2aeae",  # usamos código Hex para los colores
              fillOpacity = 0.7, # rellenamos con color los polígonos
              smoothFactor = 0.2,
              weight = 1) %>%   # para el grosor de la línea
  addLegend(pal = pal, # paleta de colores 
            values = notas_geo$nota,
            position = "bottomright",
            title = "Promedio General") %>% 
  addScaleBar(position = "topright") # Agregar escala arriba a la derecha
sf layer has inconsistent datum (+proj=longlat +ellps=GRS80 +no_defs).
Need '+proj=longlat +datum=WGS84'

mapa

mapa = leaflet() %>% addProviderTiles(providers\(CartoDB.Positron) %>% addPolygons(data = notas_geo, fillColor = ~pal(nota), addPolygons(data= notas_geo, #de donde sacamos la data fillColor = ~pal(nota), #paleta que quiero, color = "#72147e", fillOpacity= 0.7, #opacidad de los poligonos smoothFactor=0.2, weight=1) %>% addLegend(pal = pal, # paleta de colores values = notas_geo\)nota, position = “bottomright”, title = “Promedio General”) %>% addScaleBar(position = “topright”)) # Agregar escala arriba a la derecha

mapa

#Vacunas contra COVID-19 en chile—-

Cargar la base de datos de las primeras dosis de las vacunas

vacuna_dosis1=fread("https://raw.githubusercontent.com/MinCiencia/Datos-COVID19/master/output/producto80/vacunacion_comuna_1eraDosis.csv")

 [0%] Downloaded 0 bytes...
 [0%] Downloaded 0 bytes...
 [0%] Downloaded 0 bytes...
 [0%] Downloaded 0 bytes...
 [0%] Downloaded 0 bytes...
 [0%] Downloaded 0 bytes...
 [0%] Downloaded 0 bytes...
 [0%] Downloaded 0 bytes...
 [0%] Downloaded 0 bytes...
 [0%] Downloaded 0 bytes...
 [0%] Downloaded 0 bytes...

#eliminar comunas desconocidas. Eliminame las variabl4s que tengan la palabra desconocido

Debemos cambiar la estructura del dataframe para realizar el mapa, por ello, vamos a crear dos columnas, una de ellas serán las fechas de vacunación y la otra será la cantidad de personas vacunas en la fecha y comuna respectiva. Utilizaremos la función melt. Está en formato wide, es decir, formato ancho, la idea es que esté en formato long, es decir largo.

Columnas necesarias para hacer melt

melt(data = vacuna_dosis1, id.vars= c("Region", "Comuna", "Codigo comuna", "Poblacion"), measure.vars= Fechas, variable.names("fecha"))
Error in melt.data.table(data = vacuna_dosis1, id.vars = c("Region", "Comuna",  : 
  Argument 'variable.name' must be a character vector

Porcentaje de primeras dosis por comuna

###Cuando tenemos el nombre de una variable con un espacio entre medio, hay que ponerle comillas.Codigo comuna

##Queremos sumar el total de vacunas por comuna

Mapa comunas—-

Hagamos un mapa para ver el porcentaje de personas vacunadas por comunas.

#Mapa final.

leaflet(mapa)%>% 
  addProviderTiles(provider = providers$OpenStreetMap.Mapnik)%>%
  addPolygons(color = ~paleta(Porcentaje_Primeras_dosis),
              weight = 1, 
              fillOpacity = 0.8,
              label = labels)%>%
  addLegend(pal = paleta, values = ~bins, opacity = 1,position = "bottomright",title ="Porc. 1º dosis") # Agregar una leyenda
sf layer has inconsistent datum (+proj=longlat +ellps=GRS80 +no_defs).
Need '+proj=longlat +datum=WGS84'Some values were outside the color scale and will be treated as NASome values were outside the color scale and will be treated as NA

leaflet(mapa)%>% addProviderTiles(provider = providers$OpenStreetMap.Mapnik)%>% addPolygons(color = ~paleta(Porcentaje_Primeras_dosis), weight = 1, fillOpacity = 0.8, label = labels)%>% addLegend(pal = paleta, values = ~bins, opacity = 1,position = “bottomright”,title =“Porc. 1º dosis”) # Agregar una leyenda

LS0tDQp0aXRsZTogIkxhYiA3Ig0Kb3V0cHV0OiBodG1sX25vdGVib29rDQotLS0NCg0KYGBge3J9DQpsaWJyYXJ5KGRhdGEudGFibGUpDQpsaWJyYXJ5KHRpZHl2ZXJzZSkNCmxpYnJhcnkobGVhZmxldCkgIyBNYXBhcw0KbGlicmFyeShzcCkNCmxpYnJhcnkoYnJvb20pDQpsaWJyYXJ5KGphbml0b3IpICNQYXF1ZXRlIHBhcmEgbGltcGlhciBkYXRvcw0KbGlicmFyeShyZ2JpZikgI0RhdG9zIHBhcmEgZWplbXBsbyBkZSBtYXBhcw0KbGlicmFyeShzZikgI0dlb2dyYWZpYQ0KbGlicmFyeShjaGlsZW1hcGFzKSAjR2VvZ3Jhw4PCrWEgZGUgQ2hpbGUNCmxpYnJhcnkoZGF0YS50YWJsZSkNCmxpYnJhcnkoa25pdHIpDQpybShsaXN0PWxzKCkpDQpgYGANCg0KIyMjIE1hcGFzIGNvbiBgTGVhZmxldGANCg0KI2BMZWFmbGV0YCBlcyB1bmEgZGUgbGFzIGxpYnJlcsODwq1hcyBhYmllcnRhcyBtw4PCoXMgcG9wdWxhcmVzIHkgcmVjb25vY2lkYXMgZGUgYEphdmFTY3JpcHRgLiBFbCAjcGFxdWV0ZSBkZSBSIGNvbiBlbCBtaXNtbyBub21icmUgbm9zIHBlcm1pdGUgY3JlYXIgbWFwYXMgaW50ZXJhY3Rpdm9zLiBQcm9iYWJsZW1lbnRlIHlhIGhhbiAjdmlzdG8gbWFwYXMgZGUgYGxlYWZsZXRgIGFudGVzLCBwb3JxdWUgbXVjaMODwq1zaW1hcyBww4PCoWdpbmFzIHdlYiBsYXMgdXRpbGl6YW4sIGNvbW8gcG9yIGVqZW1wbG8gI2h0dHA6Ly9vcGVuc3RyZWV0bWFwLm9yZy4NCg0KI2BsZWFmbGV0YCBmdW5jaW9uYSBwb3IgY2FwYXMsIHkgYWwgaWd1YWwgcXVlIGVuIGBnZ3Bsb3RgIGV4aXN0ZW4gbXVjaMODwq1zaW1hcyBjYXBhcyBkaXNwb25pYmxlcyAjcGFyYSBtZWpvcmFyIGVsIGFzcGVjdG8gZGUgbnVlc3Ryb3MgbWFwYXMuIEhveSB2ZXJlbW9zOg0KICANCiMtIE1hcCBUaWxlczogRWxlZ2ltb3MgZWwgdGlwbyBkZSBtYXBhIHF1ZSBxdWVyZW1vcy4gKGBhZGRUaWxlc2AsIGBhZGRQcm92aWRlclRpbGVzYCkNCiMtIE1hcmtlcnM6IE1hcmNhZG9yZXMgZXNwZWPDg8KtZmljb3MgZW4gdW4gcHVudG8gZGVsIG1hcGEgKGxhdGl0dWQgeSBsb25naXR1ZCkgKGBhZGRNYXJrZXJzYCAgKGxhdD0gbG5nPSksIGBhZGRBd2Vzb21lTWFya2Vyc2ApDQojLSBQb2zDg8KtZ29ub3M6IHVuYSByZWdpw4PCs24gZXNwZWPDg8KtZmljYSBkZWwgbWFwYSwgY29tbyBwb3IgZWplbXBsbyB1bmEgY29tdW5hLg0KDQojUGFyYSBoYWNlciBudWVzdHJvIHByaW1lciBtYXBhIHNpbXBsZSwgdmF5YW1vcyBhIEdvb2dsZSBNYXBzIHBhcmEgZW5jb250cmFyIGxhcyBjb29yZGVuYWRhcyBkZSBsYSB1bnZpZXJzaWRhZC4gQXF1w4PCrSBoYWNlbW9zIG1hcGFzIGNvbiBkaWZlcmVudGVzIFByb3ZpZGVyIFRpbGVzIA0KYGBge3J9DQpsZWFmbGV0KCkgJT4lIA0KICBhZGRUaWxlcygpICU+JSAgICMgUG9yIGRlZmVjdG8NCiAgYWRkTWFya2VycyhsYXQ9LTMzLjQxNDMwODc1NzA0NzQ2NSwgbG5nPS03MC41NTMwNzY0NTczNjg0MikNCg0KbWFwYSA8LSBsZWFmbGV0KCkgJT4lIA0KICBhZGRQcm92aWRlclRpbGVzKHByb3ZpZGVycyRTdGFtZW4uVG9uZXIpICU+JSANCiAgYWRkQXdlc29tZU1hcmtlcnMobGF0PS0zMy40MTQzMDg3NTcwNDc0NjUsIGxuZz0tNzAuNTUzMDc2NDU3MzY4NDIpDQoNCm1hcGENCg0KbGVhZmxldCgpICU+JSANCiAgYWRkUHJvdmlkZXJUaWxlcyhwcm92aWRlcnMkQ2FydG9EQi5Qb3NpdHJvbikgJT4lIA0KICBhZGRNYXJrZXJzKGxhdD0tMzMuNDE0MzA4NzU3MDQ3NDY1LCBsbmc9LTcwLjU1MzA3NjQ1NzM2ODQpIA0KYGBgDQojIyMgTWFwYSBkZSBsYSBSTSBjb24gZGF0b3MgZGVsIE1JTkVEVUMNCg0KI0Fob3JhLCB2YW1vcyBhIGFwcmVuZGVyIGEgYWdyZWdhciBgbGF5ZXJzYCBjb21vIG1hcmNhZG9yZXMgbyBwb2zDg8KtZ29ub3MuDQoNCiNBYnJpciBsYSBiYXNlIGRlIGRhdG9zIGBSZW5kaW1pZW50b18yMDE4LmNzdmAuIEVzdGEgcmVwcmVzZW50YSBlbCByZW5kaW1pZW50byBlc2NvbGFyIGRlICNhbHVtbm9zIGRlIG9jdGF2byBiw4PCoXNpY28gZGUgbGEgUmVnacODwrNuIE1ldHJvcG9saXRhbmEsIHBhcmEgZWwgYcODwrFvIDIwMTguDQpgYGB7cn0NCnJlbmRfMjAxOCA8LSBmcmVhZCgiUmVuZGltaWVudG9fMjAxOC5jc3YiKQ0KYGBgDQojQWhvcmEgcG9kZW1vcyBlbXBlemFyIGEgZXhwbG9yYXIgbnVlc3Ryb3MgZGF0b3MuIFByaW1lcm8gaGFnYW1vcyB1biBncsODwqFmaWNvIHNpbXBsZSBwYXJhIHZlciBsYSBkaXN0cmlidWNpw4PCs24gZGUgbGFzIG5vdGFzIGVuIGxhIG11ZXN0cmEgY29tcGxldGE6DQpgYGB7cn0NCiANCmdncGxvdChyZW5kXzIwMThbcHJvbV9ncmFsPj00MCAmIHByb21fZ3JhbDw9NzBdLCBhZXMoeD1wcm9tX2dyYWwpKSArDQogIGdlb21fYmFyKCkNCmBgYA0KDQoNCiNQb2RlbW9zIGhhY2VyIHVuIGFuw4PCoWxpc2lzIG3Dg8KhcyBwcm9mdW5kbyB5IHNlcGFyYXIgbG9zIGRhdG9zIHBvciBnw4PCqW5lcm8uICBDb24gZXN0bywgcG9kZW1vcyB2ZXIgZGlmZXJlbmNpYXMgZW50cmUgZWwgcmVuZGltaWVudG8gZGUgbmnDg8Kxb3MgeSBuacODwrFhcy4gKEhvbWJyZXMgYGdlbl9hbHU9MWAgeSBtdWplcmVzIGBnZW5fYWx1PTJgKSAjZmFjZXRfd3JhcCBzZSBzZXBhcmEgZWwgZ3LDoWZpY28gDQpgYGB7cn0NCmdncGxvdChyZW5kXzIwMThbcHJvbV9ncmFsPj00MCAmIHByb21fZ3JhbDw9NzBdLCBhZXMoeD1wcm9tX2dyYWwpKSArDQogIGdlb21fYmFyKGZpbGwgPSAicHVycGxlIikgKw0KICBsYWJzKHg9IlByb21lZGlvIEdlbmVyYWwiLCB5PSJOdW1lcm8gZGUgYWx1bW5vcyIsIHRpdGxlPSJEaXN0cmlidWNpw7NuIGRlIG5vdGFzIHBvciBnw6luZXJvIiwgY2FwdGlvbj0iRnVlbnRlOiBNSU5FRFVDIikgKw0KICBmYWNldF93cmFwKGZhY2V0cyA9ICJnZW5fYWx1IiwgbmNvbD0xKQ0KYGBgDQoNCg0KI0Fob3JhIHZhbW9zIGEgbG9zIG1hcGFzOg0KICANCiMjUHJpbWVybywgdmFtb3MgYSBhYnJpciBsb3MgZGF0b3MgZ2VvcmVmZXJlbmNpYWxlcyBkZSBsYXMgY29tdW5hcyBkZSBTYW50aWFnbywgZGVzZGUgZWwgcGFxdWV0ZSBkZSBDUkFOIGBjaGlsZW1hcGFzYC4gRXN0ZSBwYXF1ZXRlIHRpZW5lIGluZm9ybWFjacODwrNuIHBhcmEgZ2VuZXJhciBtYXBhcyBkZSBsYXMgZGl2aXNpb25lcyBwb2zDg8KtdGljYXMgeSBhZG1pbnNpdHJhdGl2YXMgZGUgQ2hpbGUuIEluY2x1eWUgaW5mb3JtYWNpw4PCs24gYSBuaXZlbCBjb211bmFsLCBwcm92aW5jaWFsIHkgcmVnaW9uYWwgKGVudHJlIG90cm9zKS4gRXMgbXV5IMODwrp0aWwgeWEgcXVlIG5vcyBlbnRyZWdhIGxhIGdlb21ldHLDg8KtYSBkZSBjYWRhIHVuaWRhZCBnZW9ncsODwqFmaWNhIHF1ZSBxdWVkYW1vcyBtYXBlYXIuIEVuIGVzdGUgY2FzbywgdmFtb3MgYSBoYWNlciB1biBtYXBhIGRlIGxhIFJNIHBvciBjb211bmEuDQojIyNVbmEgdmV6IHF1ZSBjYXJnYW1vcyBlbCBwYXF1ZXRlLCBwb2RlbW9zIGNyZWFyIG9iamV0b3MgY29uIGxvcyBkYXRvcyBxdWUgbmVjZXNpdGFtb3MuIEVuIGVzdGUgY2FzbywgdmFtb3MgYSB1c2FyIGxhIGZ1bmNpw4PCs24gYGZpbHRlcmAgZGVsIHBhcXVldGUgYGRwbHlyYCBwYXJhIHF1ZWRhcm5vcyBzb2xvIGNvbiBsYXMgY29tdW5hcyBkZSBsYSBSZWdpw4PCs24gTWV0cm9wb2xpdGFuYS4gDQpgYGB7cn0NCiMoc2kgdmFuIGEgYD8/Y2hpbGVtYXBhc2AgZW5jb250cmFyw4PCoW4gaW5mb3JtYWNpw7NuIGRlIHRvZG9zIGxvcyBkYXRvcyBxdWUgY29udGllbmUgZXN0ZSBwYXF1ZXRlKQ0KDQpjb211bmFzID0gbWFwYV9jb211bmFzICU+JSANCiAgZmlsdGVyKGNvZGlnb19yZWdpb249PTEzKQ0KY29tdW5hcw0KYGBgDQoNCiMjSnVudGFtb3MgbGFzIGNvbXVuYXMgZGUgbG9zIGFsdW1ub3MgY29uIGxhcyBjb211bmFzIGRlbCBtYXBhLg0KYGBge3J9DQpyZW5kXzIwMThfZ2VvIDwtIG1lcmdlKGNvbXVuYXMsIHJlbmRfMjAxOCwgYnkueD0iY29kaWdvX2NvbXVuYSIsIGJ5Lnk9ImNvZF9jb21fYWx1IikNCmBgYA0KDQoNCiMjUGFyYSBpZGVudGlmaWNhciBkaWZlcmVuY2lhcyBlbnRyZSBsYXMgY29tdW5hcyBkZSBTYW50aWFnbywgdmFtb3MgYSBtYXBlYXIgZWwgcHJvbWVkaW8gZ2VuZXJhbCBkZSBsb3MgYWx1bW5vcywgcG9yIGNvbXVuYSAoZXN0YSBiYXNlIGRlIGRhdG9zLCBwb3Igc2ltcGxpY2lkYWQsIHNvbG8gdGllbmUgYSBsb3MgYWx1bW5vcyBxdWUgYXByb2Jhcm9uKS4gRXN0byBub3MgbW9zdHJhcsODwqEgdW5hIHJlcHJlc2VudGFjacODwrNuIGRlbCBwcm9tZWRpbyBnZW5lcmFsIHByb21lZGlvIGVuIGNhZGEgY29tdW5hLCBlbiB1biBtYXBhIGRlbCBHcmFuIFNhbnRpYWdvLg0KIyMjUHJpbWVybywgY3JlYW1vcyBsYSB2YXJpYWJsZSBkZSBwcm9tZWRpbyBnZW5lcmFsOg0KYGBge3J9DQpyZW5kXzIwMThfZ2VvIDwtIGFzLmRhdGEudGFibGUocmVuZF8yMDE4X2dlbykNCm5vdGFzX2dlbyA8LSByZW5kXzIwMThfZ2VvWywgbm90YTo9bWVhbihwcm9tX2dyYWwpLCBieT1jb2RpZ29fY29tdW5hXQ0KYGBgDQoNCg0KI0x1ZWdvLCBjb24gYGRpc3RpbmN0YCBub3MgcXVlZGFtb3Mgc29sbyBjb24gdW5hIG9ic2VydmFjacODwrNuIHBvciBjb211bmEsIHkgc2VsZWNjaW9uYW1vcyBzb2xvIGxhcyB2YXJpYWJsZXMgcmVsZXZhbnRlcyBwYXJhIGNyZWFyIGVsIG1hcGEgZW4gdW4gbnVldm8gb2JqZXRvLiBMdWVnbyBsbyB0cmFuc2Zvcm1hbW9zIGEgZm9ybWF0byBgc2ZgIHBhcmEgcG9kZXIgdHJhYmFqYXIgY29uIGBsZWFmbGV0YA0KYGBge3J9DQojZGlzdGluY3QgZXMgcGFyYSBlbGltaW5hciBsb3MgZHVwbGljYWRvcyB5IHF1ZWRhcm1lIHNvbG8gY29uIHVuYSBvYnNlcnZhY2nDs24gcG9yIGNvbXVuYS4lPiUgZHBpcGUgY3RybCBzaGlmdCBNLCBzaXJ2ZSBwYXJhIGFwbGljYXIgdmFyaWFzIGZ1bmNpb25lcyBqdW50YXMgYWwgbWlzbW8gb2JqZXRvIChub3Rhc19nZW8pDQojI3N0X3NmLCBlcyBwYXJhIHRyYW5zZm9ybWFyIGVsIG9iamV0byBhIGZvcm1hdG8gc2YsIGhheSBxdWUgaGFjZXJsbyBzaWVtcHJlIHF1ZSBxdWllcm8gaGFjZXIgdW4gbWFwYQ0KDQpub3Rhc19nZW8gPSBkaXN0aW5jdChub3Rhc19nZW8pICU+JSANCiAgc2VsZWN0KGNvZGlnb19jb211bmEsIGdlb21ldHJ5LCBub3RhKSANCm5vdGFzX2dlbyA9IHN0X3NmKG5vdGFzX2dlbykNCmBgYA0KDQojQWhvcmEsIGNyZWVtb3MgdW4gbWFwYS4NCiNDb24gZWwgcGFxdWV0ZSBgUkNvbG9yQnJld2VyYCBwb2RlbW9zIGVsZWdpciBtdWNoYXMgcGFsZXRhcyBkZSBjb2xvcmVzIHByZWV4aXN0ZW50ZXMuIENvbiBgZGlzcGxheS5icmV3ZXIuYWxsKClgIHBvZGVtb3MgdmVybGFzIHkgZWxlZ2lyIG90cmEuDQpgYGB7cn0NCiNjcmVhciB1bmEgcGFsZXRhIGRlIGNvbG9yZXMgY29uIGNvbG9yIG51bWVyaW5nDQppbnN0YWxsLnBhY2thZ2VzKCJSQ29sb3JCcmV3ZXIiKQ0KbGlicmFyeSgiUkNvbG9yQnJld2VyIikNCiNkaXNwbGF5LmJyZXdlci5hbGwoKSBwYXJhIHZlciBsYXMgcGFsZXRhcyBkZSBjb2xvcmVzIHF1ZSBleGlzdGVuLg0KI2RvbWFpbj1kZSBkb25kZSB2b3kgYSBzYWNhciBsb3MgZGF0b3MgcGFyYSBwb25lciBsb3MgY29sb3Jlcy4gDQoNCnBhbD0gY29sb3JOdW1lcmljKHBhbGV0dGUgPSAiU2V0MyIsIA0KICAgICAgICAgICAgICAgICAgZG9tYWluID0gcmVuZF8yMDE4X2dlbyRub3RhDQogICAgICAgICAgICAgICAgICApDQoNCiNBaG9yYSBjcmVvIGVsIG1hcGEgY29uIGVsIGRpc2XDsW8gcXVlIHF1aWVybw0KICANCg0KICBwYWwgPC0gY29sb3JOdW1lcmljKCAgICAjIGRlZmluaW1vcyBsYSBwYWxldGEgZGUgY29sb3Jlcw0KICBwYWxldHRlID0gIlB1UmQiLA0KICBkb21haW4gPSByZW5kXzIwMThfZ2VvJG5vdGEpDQoNCg0KbWFwYSA8LSBsZWFmbGV0KCkgJT4lIA0KICBhZGRQcm92aWRlclRpbGVzKHByb3ZpZGVycyRDYXJ0b0RCLlBvc2l0cm9uKSAlPiUgDQogIGFkZFBvbHlnb25zKGRhdGEgPSBub3Rhc19nZW8sDQogICAgICAgICAgICAgIGZpbGxDb2xvciA9IH5wYWwobm90YSksDQogICAgICAgICAgICAgIGNvbG9yID0gIiNiMmFlYWUiLCAgIyB1c2Ftb3MgY8ODwrNkaWdvIEhleCBwYXJhIGxvcyBjb2xvcmVzDQogICAgICAgICAgICAgIGZpbGxPcGFjaXR5ID0gMC43LCAjIHJlbGxlbmFtb3MgY29uIGNvbG9yIGxvcyBwb2zDg8KtZ29ub3MNCiAgICAgICAgICAgICAgc21vb3RoRmFjdG9yID0gMC4yLA0KICAgICAgICAgICAgICB3ZWlnaHQgPSAxKSAlPiUgICAjIHBhcmEgZWwgZ3Jvc29yIGRlIGxhIGzDg8KtbmVhDQogIGFkZExlZ2VuZChwYWwgPSBwYWwsICMgcGFsZXRhIGRlIGNvbG9yZXMgDQogICAgICAgICAgICB2YWx1ZXMgPSBub3Rhc19nZW8kbm90YSwNCiAgICAgICAgICAgIHBvc2l0aW9uID0gImJvdHRvbXJpZ2h0IiwNCiAgICAgICAgICAgIHRpdGxlID0gIlByb21lZGlvIEdlbmVyYWwiKSAlPiUgDQogIGFkZFNjYWxlQmFyKHBvc2l0aW9uID0gInRvcHJpZ2h0IikgIyBBZ3JlZ2FyIGVzY2FsYSBhcnJpYmEgYSBsYSBkZXJlY2hhDQoNCm1hcGENCiAgDQpgYGANCg0KbWFwYSA9IGxlYWZsZXQoKSAlPiUgDQogIGFkZFByb3ZpZGVyVGlsZXMocHJvdmlkZXJzJENhcnRvREIuUG9zaXRyb24pICU+JSANCiAgYWRkUG9seWdvbnMoZGF0YSA9IG5vdGFzX2dlbywNCiAgICAgICAgICAgICAgZmlsbENvbG9yID0gfnBhbChub3RhKSwNCiAgYWRkUG9seWdvbnMoZGF0YT0gbm90YXNfZ2VvLCAjZGUgZG9uZGUgc2FjYW1vcyBsYSBkYXRhDQogICAgICAgICAgICAgIGZpbGxDb2xvciA9IH5wYWwobm90YSksICNwYWxldGEgcXVlIHF1aWVybywNCiAgICAgICAgICAgICBjb2xvciA9ICIjNzIxNDdlIiwNCiAgICAgICAgICAgICBmaWxsT3BhY2l0eT0gMC43LCAjb3BhY2lkYWQgZGUgbG9zIHBvbGlnb25vcw0KICAgICAgICAgICAgIHNtb290aEZhY3Rvcj0wLjIsDQogICAgICAgICAgICAgd2VpZ2h0PTEpICU+JSANCiAgICBhZGRMZWdlbmQocGFsID0gcGFsLCAjIHBhbGV0YSBkZSBjb2xvcmVzIA0KICAgICAgICAgICAgdmFsdWVzID0gbm90YXNfZ2VvJG5vdGEsDQogICAgICAgICAgICBwb3NpdGlvbiA9ICJib3R0b21yaWdodCIsDQogICAgICAgICAgICB0aXRsZSA9ICJQcm9tZWRpbyBHZW5lcmFsIikgJT4lIA0KICAgIGFkZFNjYWxlQmFyKHBvc2l0aW9uID0gInRvcHJpZ2h0IikpICMgQWdyZWdhciBlc2NhbGEgYXJyaWJhIGEgbGEgZGVyZWNoYQ0KICANCiAgbWFwYQ0KDQoNCiNWYWN1bmFzIGNvbnRyYSBDT1ZJRC0xOSBlbiBjaGlsZS0tLS0NCg0KIyMgQ2FyZ2FyIGxhIGJhc2UgZGUgZGF0b3MgZGUgbGFzIHByaW1lcmFzIGRvc2lzIGRlIGxhcyB2YWN1bmFzDQpgYGB7cn0NCiMgQ2FyZ2FyIGxhIGJhc2UgZGUgZGF0b3MgZGUgbGFzIHByaW1lcmFzIGRvc2lzIGRlIGxhcyB2YWN1bmFzDQp2YWN1bmFfZG9zaXMxIDwtIGZyZWFkKCdodHRwczovL3Jhdy5naXRodWJ1c2VyY29udGVudC5jb20vTWluQ2llbmNpYS9EYXRvcy1DT1ZJRDE5L21hc3Rlci9vdXRwdXQvcHJvZHVjdG84MC92YWN1bmFjaW9uX2NvbXVuYV8xZXJhRG9zaXMuY3N2JykNCg0KDQpgYGANCiNlbGltaW5hciBjb211bmFzIGRlc2Nvbm9jaWRhcy4gRWxpbWluYW1lIGxhcyB2YXJpYWJsNHMgcXVlIHRlbmdhbiBsYSBwYWxhYnJhIGRlc2Nvbm9jaWRvIA0KYGBge3J9DQoNCnZhY3VuYV9kb3NpczE8LXZhY3VuYV9kb3NpczFbIUNvbXVuYSVsaWtlJSJEZXNjb25vY2lkbyIsXQ0KYGBgDQoNCiMgRGViZW1vcyBjYW1iaWFyIGxhIGVzdHJ1Y3R1cmEgZGVsIGRhdGFmcmFtZSBwYXJhIHJlYWxpemFyIGVsIG1hcGEsIHBvciBlbGxvLCB2YW1vcyBhIGNyZWFyIGRvcyBjb2x1bW5hcywgdW5hIGRlIGVsbGFzIHNlcsOhbiBsYXMgZmVjaGFzIGRlIHZhY3VuYWNpw4PCs24geSBsYSBvdHJhIHNlcsODwqEgbGEgY2FudGlkYWQgZGUgcGVyc29uYXMgdmFjdW5hcyBlbiBsYSBmZWNoYSB5IGNvbXVuYSByZXNwZWN0aXZhLiBVdGlsaXphcmVtb3MgbGEgZnVuY2nDs24gbWVsdC4gRXN0w6EgZW4gZm9ybWF0byB3aWRlLCBlcyBkZWNpciwgZm9ybWF0byBhbmNobywgbGEgaWRlYSBlcyBxdWUgZXN0w6kgZW4gZm9ybWF0byBsb25nLCBlcyBkZWNpciBsYXJnby4gDQoNCiMgQ29sdW1uYXMgbmVjZXNhcmlhcyBwYXJhIGhhY2VyIG1lbHQgDQoNCmBgYHtyfQ0KRmVjaGFzIDwtIG5hbWVzKHZhY3VuYV9kb3NpczEpDQpGZWNoYXMgPC0gRmVjaGFzWzY6MTI0XQ0KDQojaGFjZW1vcyByZXNoYXBlIGNvbiBsYSBmdW5jacOzbiBtZWx0DQoNCnZhY3VuYV9kb3NpczFfMSA9IG1lbHQoZGF0YSA9IHZhY3VuYV9kb3NpczEsaWQudmFycyA9IGMoIlJlZ2lvbiIsIkNvbXVuYSIsIkNvZGlnbyBjb211bmEiLCJQb2JsYWNpb24iKSxtZWFzdXJlLnZhcnMgPSBGZWNoYXMgLHZhcmlhYmxlLm5hbWUgPSAiRmVjaGEiKQ0KYGBgDQoNCg0KIyBQb3JjZW50YWplIGRlIHByaW1lcmFzIGRvc2lzIHBvciBjb211bmENCiMjI0N1YW5kbyB0ZW5lbW9zIGVsIG5vbWJyZSBkZSB1bmEgdmFyaWFibGUgY29uIHVuIGVzcGFjaW8gZW50cmUgbWVkaW8sIGhheSBxdWUgcG9uZXJsZSBjb21pbGxhcy5gQ29kaWdvIGNvbXVuYWANCg0KIyNRdWVyZW1vcyBzdW1hciBlbCB0b3RhbCBkZSB2YWN1bmFzIHBvciBjb211bmENCmBgYHtyfQ0KDQp2YWN1bmFfZG9zaXMxX1AgPC0gdmFjdW5hX2Rvc2lzMV8xWywuKFN1bWFfUHJpbWVyYXNfZG9zaXM9c3VtKHZhbHVlKSksIGJ5PS4oYENvZGlnbyBjb211bmFgLENvbXVuYSxQb2JsYWNpb24pXQ0KDQojIFBvcmNlbnRhamUgZGUgcHJpbWVyYXMgZG9zaXMgcG9yIGNvbXVuYQ0KDQp2YWN1bmFfZG9zaXMxX1BbLFBvcmNlbnRhamVfUHJpbWVyYXNfZG9zaXM6PShTdW1hX1ByaW1lcmFzX2Rvc2lzL1BvYmxhY2lvbiksYnk9LihgQ29kaWdvIGNvbXVuYWAsQ29tdW5hKV0NCg0KI0hheSBxdWUgYWdyZWdhciB1biBjZXJvIGFkZWxhbnRlIGEgdG9kYXMgbGFzIGNvbXVuYXMgcXVlIG5vIHNlYW4gZGUgbGEgcmVnaW9uIG1ldHJvcG9saXRhbmEsIHBvcnF1ZSBjaGlsZW1hcGFzIHJlY29ub2NlIGxhcyBjb211bmFzIGNvbiA1IGNhcmFjdGVyZXMuDQoNCnZhY3VuYV9kb3NpczFfUFssIGBDb2RpZ28gY29tdW5hYCA6PSBpZmVsc2UoYENvZGlnbyBjb211bmFgIDwgMTAwMDAgLCBwYXN0ZTAoIjAiLHZhY3VuYV9kb3NpczFfUCRgQ29kaWdvIGNvbXVuYWApLCB2YWN1bmFfZG9zaXMxX1AkYENvZGlnbyBjb211bmFgKV0gIyBBZ3JlZ2FyIHVuIGNlcm8gYWRlbGFudGUgZW4gY29kaWdvIGRlIGxhcyBjb211bmFzIHF1ZSB0ZW5nYW4gNCBkaWdpdG9zIA0KDQpgYGANCg0KDQojIE1hcGEgY29tdW5hcy0tLS0NCg0KIyBIYWdhbW9zIHVuIG1hcGEgcGFyYSB2ZXIgZWwgcG9yY2VudGFqZSBkZSBwZXJzb25hcyB2YWN1bmFkYXMgcG9yIGNvbXVuYXMuDQoNCmBgYHtyfQ0KI21hcGFfY29tdW5hcywgdmllbmUgaW5jbGlkbyBlbiBjaGlsZW1hcGFzLCBzaSBsZSBkaWdvIGEgciwgeWEgdmEgYSBzYWJlciBxdWUgc2UgcmVmaWVyZSBhIGVzdGUgbWFwYS4gDQoNCm1hcGE9bWVyZ2UobWFwYV9jb211bmFzLHZhY3VuYV9kb3NpczFfUCxieS54PSdjb2RpZ29fY29tdW5hJywgYnkueT0nQ29kaWdvIGNvbXVuYScpICMgTWVyZ2UgZW50cmUgZWwgbWFwYSBkZSBsYXMgY29tdW5hcyBxdWUgbm9zIHByb3BvcmNpb25hIGVsIHBhcXVldGUgY2hpbGVtYXBhcyB5IGVsIGRhdGFmcmFtZSBkZSBsb3MgcG9yY2VudGFqZXMuIA0KDQptYXBhPC1zdF9zZihtYXBhKSAjIENvbnZlcnRpZSBlbCBkYXRhZnJhbWUgZGUgZGF0YS50YWJsZSBhIHNmDQoNCmJpbnM8LXNlcSgwLDEsMC4yKSAjIEludGVydmFsb3MgZGVsIHBvcmNlbmF0ZWplIHBhcmEgbG9zIGNvbG9yZXMgZGVsIG1hcGEgI2NvbW8gdm95IGEgc2VwYXJhciBlbCBwb3JjZW50YWplIGNvbiBsYSBnYW1hIGRlIGNvbG9yZXMsIHZhIGEgaXIgZGUgMCBhIDEsIHNlcGFyYWRvIGRlIGEgMC4yIGRlY2ltYXMgDQoNCnBhbGV0YT0gY29sb3JCaW4oJ0RhcmsyJywgZG9tYWluID0gdmFjdW5hX2Rvc2lzMV9QJFBvcmNlbnRhamVfUHJpbWVyYXNfZG9zaXMsIGJpbnMgPSBiaW5zKQ0KDQojZXN0ZSBjb2RpZ28gYXV0b21hdGl6YSBlbCBub21icmUgZGUgY2FkYSBjb211bmEgY29uIGVsIHBvcmNlbnRhamUgZGUgbGEgcHJpbWVyYSBkb3NpcyBxdWUgcXVlcmVtb3MgcXVlIG5vcyBtdWVzdHJlIGN1YW5kbyBwYXNlbW9zIGVsIG1vdXNlIHBvciBhcnJpYmEgZGVsIG1hcGENCg0KcGFsZXRhPC1jb2xvckJpbihwYWxldHRlID0gJ0RhcmsyJyxkb21haW4gPSB2YWN1bmFfZG9zaXMxX1AkUG9yY2VudGFqZV9QcmltZXJhc19kb3NpcyxiaW5zID0gYmlucykgIyBQYWxldGEgZGUgY29sb3JlcyBwYXJhIGVsIG1hcGENCg0KbGFiZWxzIDwtIHNwcmludGYoDQogICI8c3Ryb25nPiVzPC9zdHJvbmc+PGJyLz4lZyBQb3JjLiBQcmltZXJhIERvc2lzIiwNCiAgbWFwYSRDb211bmEsIG1hcGEkUG9yY2VudGFqZV9QcmltZXJhc19kb3Npcw0KKSAlPiUgbGFwcGx5KGh0bWx0b29sczo6SFRNTCkgIyBMYWJlbHMgYWwgcGFzYXIgYXJyaWJhIGRlbCBtYXBhDQoNCiAgICAgICAgICAgICAgDQpgYGANCg0KI01hcGEgZmluYWwuDQpgYGB7cn0NCmxlYWZsZXQobWFwYSklPiUgDQogIGFkZFByb3ZpZGVyVGlsZXMocHJvdmlkZXIgPSBwcm92aWRlcnMkT3BlblN0cmVldE1hcC5NYXBuaWspJT4lDQogIGFkZFBvbHlnb25zKGNvbG9yID0gfnBhbGV0YShQb3JjZW50YWplX1ByaW1lcmFzX2Rvc2lzKSwNCiAgICAgICAgICAgICAgd2VpZ2h0ID0gMSwgDQogICAgICAgICAgICAgIGZpbGxPcGFjaXR5ID0gMC44LA0KICAgICAgICAgICAgICBsYWJlbCA9IGxhYmVscyklPiUNCiAgYWRkTGVnZW5kKHBhbCA9IHBhbGV0YSwgdmFsdWVzID0gfmJpbnMsIG9wYWNpdHkgPSAxLHBvc2l0aW9uID0gImJvdHRvbXJpZ2h0Iix0aXRsZSA9IlBvcmMuIDHDgsK6IGRvc2lzIikgIyBBZ3JlZ2FyIHVuYSBsZXllbmRhDQpgYGANCg0KDQpsZWFmbGV0KG1hcGEpJT4lIA0KICBhZGRQcm92aWRlclRpbGVzKHByb3ZpZGVyID0gcHJvdmlkZXJzJE9wZW5TdHJlZXRNYXAuTWFwbmlrKSU+JQ0KICBhZGRQb2x5Z29ucyhjb2xvciA9IH5wYWxldGEoUG9yY2VudGFqZV9QcmltZXJhc19kb3NpcyksDQogICAgICAgICAgICAgIHdlaWdodCA9IDEsIA0KICAgICAgICAgICAgICBmaWxsT3BhY2l0eSA9IDAuOCwNCiAgICAgICAgICAgICAgbGFiZWwgPSBsYWJlbHMpJT4lDQogIGFkZExlZ2VuZChwYWwgPSBwYWxldGEsIHZhbHVlcyA9IH5iaW5zLCBvcGFjaXR5ID0gMSxwb3NpdGlvbiA9ICJib3R0b21yaWdodCIsdGl0bGUgPSJQb3JjLiAxw4LCuiBkb3NpcyIpICMgQWdyZWdhciB1bmEgbGV5ZW5kYQ0KDQo=