Autor: Gabriela Sofia Campos

1. Introducción

Este trabajo pretende ilustrar el proceso de obtención de los datos mensuales “normales” de precipitación para un periodo de tiempo entre 1981 y 2010. Para ello, se usa la librería climateR.

La precipitación normal es un promedio de valores de la precipitación durante este periodo de 30 años. En la realidad, estos valores son susceptibles de variar, ya sea por encima o por debajo de la precipitación normal encontrada.

SETUP

setwd("C:/Users/gabri/Downloads/R ultimo cuaderno")

Empezamos por limpriar la memoria de R.

rm(list=ls())
install.packages(rlang)
Error in install.packages : object 'rlang' not found
packageVersion('rlang')
[1] ‘1.0.6’

Cargamos las librerías pertinentes:

#install the packages from the console not from here
#library(remotes)
remotes::install_github("mikejohnson51/AOI")
Downloading GitHub repo mikejohnson51/AOI@HEAD
These packages have more recent versions available.
It is recommended to update all of them.
Which would you like to update?

1: All                         
2: CRAN packages only          
3: None                        
4: cli  (3.3.0 -> 3.4.1) [CRAN]
5: curl (4.3.2 -> 4.3.3) [CRAN]
library(rlang)
3
Running `R CMD build`...
* checking for file 'C:\Users\gabri\AppData\Local\Temp\RtmpKcuBSn\remotes2578448f4ebf\mikejohnson51-AOI-b6ae1d4/DESCRIPTION' ... OK
* preparing 'AOI':
* checking DESCRIPTION meta-information ... OK
* checking for LF line-endings in source and make files and shell scripts
* checking for empty or unneeded directories
* building 'AOI_0.2.1.tar.gz'
Installing package into ‘C:/Users/gabri/AppData/Local/R/win-library/4.2’
(as ‘lib’ is unspecified)
* installing *source* package 'AOI' ...
** using staged installation
** R
** data
*** moving datasets to lazyload DB
** byte-compile and prepare package for lazy loading
** help
*** installing help indices
*** copying figures
** building package indices
** testing if installed package can be loaded from temporary location
** testing if installed package can be loaded from final location
** testing if installed package keeps a record of temporary installation path
* DONE (AOI)
remotes::install_github("mikejohnson51/climateR")
Skipping install of 'climateR' from a github remote, the SHA1 (62d4c167) has not changed since last install.
  Use `force = TRUE` to force installation

library(sf)
Warning: package ‘sf’ was built under R version 4.2.2Linking to GEOS 3.9.3, GDAL 3.5.2, PROJ 8.2.1; sf_use_s2() is TRUE
library(raster)
Warning: package ‘raster’ was built under R version 4.2.2Loading required package: sp
Warning: package ‘sp’ was built under R version 4.2.2
Attaching package: ‘raster’

The following object is masked from ‘package:dplyr’:

    select
library(rasterVis)
Warning: package ‘rasterVis’ was built under R version 4.2.2Loading required package: lattice
library(dplyr)
library(leaflet)
Registered S3 methods overwritten by 'htmltools':
  method               from         
  print.html           tools:rstudio
  print.shiny.tag      tools:rstudio
  print.shiny.tag.list tools:rstudio
Registered S3 method overwritten by 'htmlwidgets':
  method           from         
  print.htmlwidget tools:rstudio
library(leafem)
library(RColorBrewer)
library(stars)
Loading required package: abind
library(climateR)
library(sf)
library(raster)
library(rasterVis)
library(dplyr)

Leemos el área de estudio

(tolima <- st_read("citiestolima.shp"))
Reading layer `citiestolima' from data source `C:\Users\gabri\Downloads\R ultimo cuaderno\citiestolima.shp' using driver `ESRI Shapefile'
Simple feature collection with 18 features and 12 fields
Geometry type: POINT
Dimension:     XYM
Bounding box:  xmin: -75.6447 ymin: 3.1964 xmax: -74.6428 ymax: 5.2069
m_range:       mmin: 7563 mmax: 541101
Geodetic CRS:  WGS 84
Simple feature collection with 18 features and 12 fields
Geometry type: POINT
Dimension:     XYM
Bounding box:  xmin: -75.6447 ymin: 3.1964 xmax: -74.6428 ymax: 5.2069
m_range:       mmin: 7563 mmax: 541101
Geodetic CRS:  WGS 84
First 10 features:
   fid         city   city_ascii    lat      lng  country iso2 iso3 admin_name capital population         id                       geometry
1    1       Ibagu�       Ibague 4.4378 -75.2006 Colombia   CO  COL     Tolima   admin     541101 1170245063 POINT M (-75.2006 4.4378 54...
2    2      Espinal      Espinal 4.1486 -74.8819 Colombia   CO  COL     Tolima   minor      75828 1170084447 POINT M (-74.8819 4.1486 75...
3    3    Chaparral    Chaparral 3.7236 -75.4847 Colombia   CO  COL     Tolima   minor      47397 1170193964 POINT M (-75.4847 3.7236 47...
4    4       L�bano       Libano 4.9206 -75.0611 Colombia   CO  COL     Tolima   minor      39665 1170994564 POINT M (-75.0611 4.9206 39...
5    5       Melgar       Melgar 4.2039 -74.6428 Colombia   CO  COL     Tolima   minor      37224 1170387585 POINT M (-74.6428 4.2039 37...
6    6        Guamo        Guamo 4.0281 -74.9700 Colombia   CO  COL     Tolima   minor      31350 1170113847  POINT M (-74.97 4.0281 31350)
7    7     Planadas     Planadas 3.1964 -75.6444 Colombia   CO  COL     Tolima   minor      30117 1170444880 POINT M (-75.6444 3.1964 30...
8    8       Fresno       Fresno 5.1536 -75.0369 Colombia   CO  COL     Tolima   minor      29794 1170216002 POINT M (-75.0369 5.1536 29...
9    9 Purificaci�n Purificacion 3.8567 -74.9325 Colombia   CO  COL     Tolima   minor      29777 1170787107 POINT M (-74.9325 3.8567 29...
10  10      Flandes      Flandes 4.2844 -74.8142 Colombia   CO  COL     Tolima   minor      29478 1170495426 POINT M (-74.8142 4.2844 29...

2. Obetener las normales de precipitación mensual

Para doce años:

oneyear=seq(1,12)

Ahora para descargar la precipitación normal de 1981 a 2010:

precip = getTerraClimNormals(tolima, param = "prcp", period = "19812010", month = oneyear)
Spherical geometry (s2) switched off
Spherical geometry (s2) switched on

Se visualizan los resultados:

precip
$terraclim_19812010_prcp
class      : RasterStack 
dimensions : 49, 25, 1225, 12  (nrow, ncol, ncell, nlayers)
resolution : 0.04166667, 0.04166667  (x, y)
extent     : -75.66667, -74.625, 3.166667, 5.208333  (xmin, xmax, ymin, ymax)
crs        : +proj=longlat +datum=WGS84 +no_defs 
names      :   X01,   X02,   X03,   X04,   X05,   X06,   X07,   X08,   X09,   X10,   X11,   X12 
min values :  21.0,  31.6,  80.1, 139.8, 115.7,  75.5,  34.3,  40.5,  70.6, 134.9,  89.3,  67.4 
max values : 174.6, 172.2, 243.6, 349.0, 322.0, 321.0, 236.0, 195.1, 248.8, 377.9, 334.1, 241.0 

Vale la pena señalar que el objeto “precip” tiene 12 capas.

capas <- names(precip)

Ahora visualizamos los histogramas para la precipitación de la siguiente manera:

par(mfcol=c(12,12), mfrow=c(4,3), oma=c(1,1,0,0),
    mar=c(1,1,1,0), tcl=-0.1, mgp=c(0,0,0))
for (penta in capas) {
  hist(precip[[penta]], ylab=NA, cex.axis=0.5, font.main=1, cex.main=0.8)
}

Ahora procedemos a calcular la precipitación normal para el año.

year_precip<-sum(precip$terraclim_19812010_prcp)
year_precip
class      : RasterLayer 
dimensions : 49, 25, 1225  (nrow, ncol, ncell)
resolution : 0.04166667, 0.04166667  (x, y)
extent     : -75.66667, -74.625, 3.166667, 5.208333  (xmin, xmax, ymin, ymax)
crs        : +proj=longlat +datum=WGS84 +no_defs 
source     : memory
names      : layer 
values     : 1198.1, 2623.8  (min, max)

Ahora vamos a visualizar la información. En primer lugar elegimos la paleta de colores más apropiada.

ppal <- colorNumeric(c("orange", "yellow", "#a1d99b", "#deebf7", "#9ecae1","#3182bd", "darkblue"), values(year_precip$layer),
                     na.color = "transparent")

Luegeo de esto, podemos ver la información gracias a lo que sigue:

leaflet() %>% addTiles() %>%
  addRasterImage(year_precip, colors = ppal, opacity = 0.8) %>%
  addLegend(pal = ppal, values = values(year_precip$layer),
    title = "Annual Precipitation")
Warning: Some values were outside the color scale and will be treated as NA

3. Ahora podemos obtener las temperaturas mensuales normales.

tmax=getTerraClimNormals(tolima,param="tmax", period ="19812010", month = oneyear)
Spherical geometry (s2) switched off
Spherical geometry (s2) switched on
tmax
$terraclim_19812010_tmax
class      : RasterStack 
dimensions : 49, 25, 1225, 12  (nrow, ncol, ncell, nlayers)
resolution : 0.04166667, 0.04166667  (x, y)
extent     : -75.66667, -74.625, 3.166667, 5.208333  (xmin, xmax, ymin, ymax)
crs        : +proj=longlat +datum=WGS84 +no_defs 
names      :  X01,  X02,  X03,  X04,  X05,  X06,  X07,  X08,  X09,  X10,  X11,  X12 
min values :  4.7,  4.6,  4.6,  4.4,  4.5,  3.6,  3.7,  3.8,  4.4,  4.0,  4.4,  4.4 
max values : 33.5, 33.8, 33.4, 32.3, 32.6, 33.4, 35.1, 35.8, 34.9, 32.4, 31.9, 32.3 

Podemos observar las temperaturas máximas:

(year_tmax=max(tmax$terraclim_19812010_tmax))
class      : RasterLayer 
dimensions : 49, 25, 1225  (nrow, ncol, ncell)
resolution : 0.04166667, 0.04166667  (x, y)
extent     : -75.66667, -74.625, 3.166667, 5.208333  (xmin, xmax, ymin, ymax)
crs        : +proj=longlat +datum=WGS84 +no_defs 
source     : memory
names      : layer 
values     : 4.7, 35.8  (min, max)

Y también las mínimas:

tmin= getTerraClimNormals(tolima, param = "tmin", period = "19812010", month=oneyear)
Spherical geometry (s2) switched off
Spherical geometry (s2) switched on
tmin
$terraclim_19812010_tmin
class      : RasterStack 
dimensions : 49, 25, 1225, 12  (nrow, ncol, ncell, nlayers)
resolution : 0.04166667, 0.04166667  (x, y)
extent     : -75.66667, -74.625, 3.166667, 5.208333  (xmin, xmax, ymin, ymax)
crs        : +proj=longlat +datum=WGS84 +no_defs 
names      :  X01,  X02,  X03,  X04,  X05,  X06,  X07,  X08,  X09,  X10,  X11,  X12 
min values : -3.6, -3.7, -2.7, -2.6, -2.5, -2.3, -2.9, -2.5, -2.5, -2.6, -2.6, -2.9 
max values : 23.1, 23.0, 23.9, 23.1, 22.8, 23.1, 23.2, 23.7, 23.5, 23.1, 23.1, 23.2 
(year_tmin = min(tmin$terraclim_19812010_tmin))
class      : RasterLayer 
dimensions : 49, 25, 1225  (nrow, ncol, ncell)
resolution : 0.04166667, 0.04166667  (x, y)
extent     : -75.66667, -74.625, 3.166667, 5.208333  (xmin, xmax, ymin, ymax)
crs        : +proj=longlat +datum=WGS84 +no_defs 
source     : memory
names      : layer 
values     : -3.7, 22.8  (min, max)

Y creamos una capa.

(tempera <- stack(year_tmin, year_tmax))
class      : RasterStack 
dimensions : 49, 25, 1225, 2  (nrow, ncol, ncell, nlayers)
resolution : 0.04166667, 0.04166667  (x, y)
extent     : -75.66667, -74.625, 3.166667, 5.208333  (xmin, xmax, ymin, ymax)
crs        : +proj=longlat +datum=WGS84 +no_defs 
names      : layer.1, layer.2 
min values :    -3.7,     4.7 
max values :    22.8,    35.8 

Cambiamos el nombre de la capa recién creada:

names(tempera)  <- c("tmin", "tmax")

Definimos los valores mostrados con:

tvals <- sort(c(values(tempera$tmin),values(tempera$tmax)))

Y de nuevo elegimos y creamos las paletas de colores.

pal <- colorNumeric(rev(c("red", "orange", "#fff9ae",
                        "#77ab59",  "#dcf3ff", "#a2d2df", "#257ca3")), 
                         tvals, na.color = "transparent")
capas <- names(tempera)

Y ahora sí se puede visualizar la información relativa a la temperatura del Tolima.

m <- leaflet() %>%
  addTiles(group = "OSM (default)") %>%
  addRasterImage(year_tmin, colors = pal, opacity = 0.8, group= capas[1]) %>%
  addRasterImage(year_tmax, colors = pal, opacity = 0.8, group= capas[2]) 
#
# Additional leaflet options 
m <- m %>%
  # Add layers controls
  addLayersControl(
    overlayGroups = rev(capas),
    options = layersControlOptions(collapsed = FALSE)
  ) %>%
  # Add common legend
  addLegend(pal = pal, values = tvals,
   title = "Annual Temperature")
m

Y así, hemos dado uso a algunas de las muchas funciones que tienen estos paquetes en R, relacionados con variables climáticas y espaciales.

4. Reproducibilidad y fuentes.

Adaptado de: Lizarazo, I., 2022. Get monthly climate normals using ClimateR. Available at https://rpubs.com/ials2un/climate.

sessionInfo()
R version 4.2.1 (2022-06-23 ucrt)
Platform: x86_64-w64-mingw32/x64 (64-bit)
Running under: Windows 10 x64 (build 19044)

Matrix products: default

locale:
[1] LC_COLLATE=Spanish_Colombia.utf8 
[2] LC_CTYPE=Spanish_Colombia.utf8   
[3] LC_MONETARY=Spanish_Colombia.utf8
[4] LC_NUMERIC=C                     
[5] LC_TIME=Spanish_Colombia.utf8    

attached base packages:
[1] stats     graphics  grDevices utils     datasets 
[6] methods   base     

other attached packages:
 [1] stars_0.5-6        abind_1.4-5       
 [3] RColorBrewer_1.1-3 leafem_0.2.0      
 [5] leaflet_2.1.1      rasterVis_0.51.4  
 [7] lattice_0.20-45    raster_3.6-11     
 [9] sp_1.5-1           sf_1.0-9          
[11] AOI_0.2.1          climateR_0.1.0    
[13] dplyr_1.0.10      

loaded via a namespace (and not attached):
 [1] httr_1.4.4              rnaturalearth_0.1.0    
 [3] sass_0.4.2              jsonlite_1.8.3         
 [5] viridisLite_0.4.1       foreach_1.5.2          
 [7] bslib_0.4.0             assertthat_0.2.1       
 [9] latticeExtra_0.6-30     yaml_2.3.5             
[11] remotes_2.4.2           pillar_1.8.1           
[13] glue_1.6.2              digest_0.6.29          
[15] rvest_1.0.3             colorspace_2.0-3       
[17] leaflet.providers_1.9.0 htmltools_0.5.3        
[19] pkgconfig_2.0.3         purrr_0.3.4            
[21] scales_1.2.1            terra_1.6-41           
[23] jpeg_0.1-9              tibble_3.1.8           
[25] proxy_0.4-27            farver_2.1.1           
[27] generics_0.1.3          cachem_1.0.6           
[29] hexbin_1.28.2           cli_3.3.0              
[31] fipio_1.1.1             magrittr_2.0.3         
[33] deldir_1.0-6            evaluate_0.16          
[35] fansi_1.0.3             doParallel_1.0.17      
[37] xml2_1.3.3              lwgeom_0.2-9           
[39] class_7.3-20            rsconnect_0.8.27       
[41] tools_4.2.1             lifecycle_1.0.3        
[43] stringr_1.4.1           interp_1.1-3           
[45] munsell_0.5.0           compiler_4.2.1         
[47] jquerylib_0.1.4         e1071_1.7-12           
[49] RNetCDF_2.6-1           rlang_1.0.6            
[51] classInt_0.4-8          units_0.8-0            
[53] grid_4.2.1              iterators_1.0.14       
[55] rstudioapi_0.13         htmlwidgets_1.5.4      
[57] crosstalk_1.2.0         base64enc_0.1-3        
[59] rmarkdown_2.16          codetools_0.2-18       
[61] DBI_1.1.3               curl_4.3.2             
[63] R6_2.5.1                zoo_1.8-11             
[65] knitr_1.40              fastmap_1.1.0          
[67] utf8_1.2.2              KernSmooth_2.23-20     
[69] stringi_1.7.8           parallel_4.2.1         
[71] Rcpp_1.0.9              vctrs_0.5.1            
[73] png_0.1-7               tidyselect_1.1.2       
[75] xfun_0.32              
LS0tDQp0aXRsZTogTm9ybWFsZXMgY2xpbcOhdGljYXMgbWVuc3VhbGVzIHVzYW5kbyBDbGltYXRlUi4NCm91dHB1dDogaHRtbF9ub3RlYm9vaw0KLS0tDQpBdXRvcjogR2FicmllbGEgU29maWEgQ2FtcG9zDQoNCiMgMS4gSW50cm9kdWNjacOzbg0KRXN0ZSB0cmFiYWpvIHByZXRlbmRlIGlsdXN0cmFyIGVsIHByb2Nlc28gZGUgb2J0ZW5jacOzbiBkZSBsb3MgZGF0b3MgbWVuc3VhbGVzICJub3JtYWxlcyIgZGUgcHJlY2lwaXRhY2nDs24gcGFyYSB1biBwZXJpb2RvIGRlIHRpZW1wbyBlbnRyZSAxOTgxIHkgMjAxMC4gUGFyYSBlbGxvLCBzZSB1c2EgbGEgbGlicmVyw61hIGNsaW1hdGVSLg0KDQpMYSBwcmVjaXBpdGFjacOzbiBub3JtYWwgZXMgdW4gcHJvbWVkaW8gZGUgdmFsb3JlcyBkZSBsYSBwcmVjaXBpdGFjacOzbiBkdXJhbnRlIGVzdGUgcGVyaW9kbyAgZGUgMzAgYcOxb3MuIEVuIGxhIHJlYWxpZGFkLCBlc3RvcyB2YWxvcmVzIHNvbiBzdXNjZXB0aWJsZXMgZGUgdmFyaWFyLCB5YSBzZWEgcG9yIGVuY2ltYSBvIHBvciBkZWJham8gZGUgbGEgcHJlY2lwaXRhY2nDs24gbm9ybWFsIGVuY29udHJhZGEuIA0KDQpTRVRVUA0KDQpgYGB7cn0NCnNldHdkKCJDOi9Vc2Vycy9nYWJyaS9Eb3dubG9hZHMvUiB1bHRpbW8gY3VhZGVybm8iKQ0KYGBgDQoNCkVtcGV6YW1vcyBwb3IgbGltcHJpYXIgbGEgbWVtb3JpYSBkZSBSLg0KDQpgYGB7cn0NCnJtKGxpc3Q9bHMoKSkNCmBgYA0KYGBge3J9DQppbnN0YWxsLnBhY2thZ2VzKHJsYW5nKQ0KcGFja2FnZVZlcnNpb24oJ3JsYW5nJykNCmBgYA0KDQpDYXJnYW1vcyBsYXMgbGlicmVyw61hcyBwZXJ0aW5lbnRlczoNCg0KYGBge3J9DQojaW5zdGFsbCB0aGUgcGFja2FnZXMgZnJvbSB0aGUgY29uc29sZSBub3QgZnJvbSBoZXJlDQojbGlicmFyeShyZW1vdGVzKQ0KI3JlbW90ZXM6Omluc3RhbGxfZ2l0aHViKCJtaWtlam9obnNvbjUxL0FPSSIpDQojcmVtb3Rlczo6aW5zdGFsbF9naXRodWIoIm1pa2Vqb2huc29uNTEvY2xpbWF0ZVIiKQ0KYGBgDQoNCmBgYHtyfQ0KDQpsaWJyYXJ5KHNmKQ0KbGlicmFyeShyYXN0ZXIpDQpsaWJyYXJ5KHJhc3RlclZpcykNCmxpYnJhcnkoZHBseXIpDQpsaWJyYXJ5KGxlYWZsZXQpDQpsaWJyYXJ5KGxlYWZlbSkNCmxpYnJhcnkoUkNvbG9yQnJld2VyKQ0KbGlicmFyeShzdGFycykNCmBgYA0KDQpgYGB7cn0NCmxpYnJhcnkoY2xpbWF0ZVIpDQpsaWJyYXJ5KHNmKQ0KbGlicmFyeShyYXN0ZXIpDQpsaWJyYXJ5KHJhc3RlclZpcykNCmxpYnJhcnkoZHBseXIpDQoNCmBgYA0KDQoNCkxlZW1vcyBlbCDDoXJlYSBkZSBlc3R1ZGlvDQoNCmBgYHtyfQ0KKHRvbGltYSA8LSBzdF9yZWFkKCJjaXRpZXN0b2xpbWEuc2hwIikpDQpgYGANCg0KIyAyLiBPYmV0ZW5lciBsYXMgbm9ybWFsZXMgZGUgcHJlY2lwaXRhY2nDs24gbWVuc3VhbA0KDQpQYXJhIGRvY2UgYcOxb3M6IA0KDQpgYGB7cn0NCm9uZXllYXI9c2VxKDEsMTIpDQpgYGANCg0KQWhvcmEgcGFyYSBkZXNjYXJnYXIgbGEgcHJlY2lwaXRhY2nDs24gbm9ybWFsIGRlIDE5ODEgYSAyMDEwOg0KDQpgYGB7cn0NCnByZWNpcCA9IGdldFRlcnJhQ2xpbU5vcm1hbHModG9saW1hLCBwYXJhbSA9ICJwcmNwIiwgcGVyaW9kID0gIjE5ODEyMDEwIiwgbW9udGggPSBvbmV5ZWFyKQ0KYGBgDQoNClNlIHZpc3VhbGl6YW4gbG9zIHJlc3VsdGFkb3M6IA0KYGBge3J9DQpwcmVjaXANCmBgYA0KVmFsZSBsYSBwZW5hIHNlw7FhbGFyIHF1ZSBlbCBvYmpldG8gInByZWNpcCIgdGllbmUgMTIgY2FwYXMuIA0KDQpgYGB7cn0NCmNhcGFzIDwtIG5hbWVzKHByZWNpcCkNCmBgYA0KDQoNCkFob3JhIHZpc3VhbGl6YW1vcyBsb3MgaGlzdG9ncmFtYXMgcGFyYSBsYSBwcmVjaXBpdGFjacOzbiBkZSBsYSBzaWd1aWVudGUgbWFuZXJhOg0KYGBge3J9DQpwYXIobWZjb2w9YygxMiwxMiksIG1mcm93PWMoNCwzKSwgb21hPWMoMSwxLDAsMCksDQogICAgbWFyPWMoMSwxLDEsMCksIHRjbD0tMC4xLCBtZ3A9YygwLDAsMCkpDQpmb3IgKHBlbnRhIGluIGNhcGFzKSB7DQogIGhpc3QocHJlY2lwW1twZW50YV1dLCB5bGFiPU5BLCBjZXguYXhpcz0wLjUsIGZvbnQubWFpbj0xLCBjZXgubWFpbj0wLjgpDQp9DQpgYGANCg0KQWhvcmEgcHJvY2VkZW1vcyBhIGNhbGN1bGFyIGxhIHByZWNpcGl0YWNpw7NuIG5vcm1hbCBwYXJhIGVsIGHDsW8uDQoNCmBgYHtyfQ0KeWVhcl9wcmVjaXA8LXN1bShwcmVjaXAkdGVycmFjbGltXzE5ODEyMDEwX3ByY3ApDQp5ZWFyX3ByZWNpcA0KDQpgYGANCg0KQWhvcmEgdmFtb3MgYSB2aXN1YWxpemFyIGxhIGluZm9ybWFjacOzbi4gRW4gcHJpbWVyIGx1Z2FyIGVsZWdpbW9zIGxhIHBhbGV0YSBkZSBjb2xvcmVzIG3DoXMgYXByb3BpYWRhLiANCg0KYGBge3J9DQpwcGFsIDwtIGNvbG9yTnVtZXJpYyhjKCJvcmFuZ2UiLCAieWVsbG93IiwgIiNhMWQ5OWIiLCAiI2RlZWJmNyIsICIjOWVjYWUxIiwiIzMxODJiZCIsICJkYXJrYmx1ZSIpLCB2YWx1ZXMoeWVhcl9wcmVjaXAkbGF5ZXIpLA0KICAgICAgICAgICAgICAgICAgICAgbmEuY29sb3IgPSAidHJhbnNwYXJlbnQiKQ0KYGBgDQoNCkx1ZWdlbyBkZSBlc3RvLCBwb2RlbW9zIHZlciBsYSBpbmZvcm1hY2nDs24gZ3JhY2lhcyBhIGxvIHF1ZSBzaWd1ZTogDQoNCmBgYHtyfQ0KbGVhZmxldCgpICU+JSBhZGRUaWxlcygpICU+JQ0KICBhZGRSYXN0ZXJJbWFnZSh5ZWFyX3ByZWNpcCwgY29sb3JzID0gcHBhbCwgb3BhY2l0eSA9IDAuOCkgJT4lDQogIGFkZExlZ2VuZChwYWwgPSBwcGFsLCB2YWx1ZXMgPSB2YWx1ZXMoeWVhcl9wcmVjaXAkbGF5ZXIpLA0KICAgIHRpdGxlID0gIkFubnVhbCBQcmVjaXBpdGF0aW9uIikNCmBgYA0KDQojIDMuIEFob3JhIHBvZGVtb3Mgb2J0ZW5lciBsYXMgdGVtcGVyYXR1cmFzIG1lbnN1YWxlcyBub3JtYWxlcy4gDQoNCmBgYHtyfQ0KdG1heD1nZXRUZXJyYUNsaW1Ob3JtYWxzKHRvbGltYSxwYXJhbT0idG1heCIsIHBlcmlvZCA9IjE5ODEyMDEwIiwgbW9udGggPSBvbmV5ZWFyKQ0KYGBgDQoNCg0KYGBge3J9DQp0bWF4DQpgYGANCg0KUG9kZW1vcyBvYnNlcnZhciBsYXMgdGVtcGVyYXR1cmFzIG3DoXhpbWFzOg0KYGBge3J9DQooeWVhcl90bWF4PW1heCh0bWF4JHRlcnJhY2xpbV8xOTgxMjAxMF90bWF4KSkNCmBgYA0KDQpZIHRhbWJpw6luIGxhcyBtw61uaW1hczoNCg0KYGBge3J9DQp0bWluPSBnZXRUZXJyYUNsaW1Ob3JtYWxzKHRvbGltYSwgcGFyYW0gPSAidG1pbiIsIHBlcmlvZCA9ICIxOTgxMjAxMCIsIG1vbnRoPW9uZXllYXIpDQoNCmBgYA0KDQpgYGB7cn0NCnRtaW4NCmBgYA0KDQoNCmBgYHtyfQ0KKHllYXJfdG1pbiA9IG1pbih0bWluJHRlcnJhY2xpbV8xOTgxMjAxMF90bWluKSkNCmBgYA0KDQpZIGNyZWFtb3MgdW5hIGNhcGEuDQoNCmBgYHtyfQ0KKHRlbXBlcmEgPC0gc3RhY2soeWVhcl90bWluLCB5ZWFyX3RtYXgpKQ0KYGBgDQoNCkNhbWJpYW1vcyBlbCBub21icmUgZGUgbGEgY2FwYSByZWNpw6luIGNyZWFkYToNCg0KYGBge3J9DQpuYW1lcyh0ZW1wZXJhKSAgPC0gYygidG1pbiIsICJ0bWF4IikNCmBgYA0KDQpEZWZpbmltb3MgbG9zIHZhbG9yZXMgbW9zdHJhZG9zIGNvbjogDQoNCmBgYHtyfQ0KdHZhbHMgPC0gc29ydChjKHZhbHVlcyh0ZW1wZXJhJHRtaW4pLHZhbHVlcyh0ZW1wZXJhJHRtYXgpKSkNCmBgYA0KDQpZIGRlIG51ZXZvIGVsZWdpbW9zIHkgY3JlYW1vcyBsYXMgcGFsZXRhcyBkZSBjb2xvcmVzLiANCg0KYGBge3J9DQpwYWwgPC0gY29sb3JOdW1lcmljKHJldihjKCJyZWQiLCAib3JhbmdlIiwgIiNmZmY5YWUiLA0KICAgICAgICAgICAgICAgICAgICAgICAgIiM3N2FiNTkiLCAgIiNkY2YzZmYiLCAiI2EyZDJkZiIsICIjMjU3Y2EzIikpLCANCiAgICAgICAgICAgICAgICAgICAgICAgICB0dmFscywgbmEuY29sb3IgPSAidHJhbnNwYXJlbnQiKQ0KYGBgDQpgYGB7cn0NCmNhcGFzIDwtIG5hbWVzKHRlbXBlcmEpDQpgYGANCg0KDQpZIGFob3JhIHPDrSBzZSBwdWVkZSB2aXN1YWxpemFyIGxhIGluZm9ybWFjacOzbiByZWxhdGl2YSBhIGxhIHRlbXBlcmF0dXJhIGRlbCBUb2xpbWEuDQoNCmBgYHtyfQ0KbSA8LSBsZWFmbGV0KCkgJT4lDQogIGFkZFRpbGVzKGdyb3VwID0gIk9TTSAoZGVmYXVsdCkiKSAlPiUNCiAgYWRkUmFzdGVySW1hZ2UoeWVhcl90bWluLCBjb2xvcnMgPSBwYWwsIG9wYWNpdHkgPSAwLjgsIGdyb3VwPSBjYXBhc1sxXSkgJT4lDQogIGFkZFJhc3RlckltYWdlKHllYXJfdG1heCwgY29sb3JzID0gcGFsLCBvcGFjaXR5ID0gMC44LCBncm91cD0gY2FwYXNbMl0pIA0KIw0KIyBBZGRpdGlvbmFsIGxlYWZsZXQgb3B0aW9ucyANCm0gPC0gbSAlPiUNCiAgIyBBZGQgbGF5ZXJzIGNvbnRyb2xzDQogIGFkZExheWVyc0NvbnRyb2woDQogICAgb3ZlcmxheUdyb3VwcyA9IHJldihjYXBhcyksDQogICAgb3B0aW9ucyA9IGxheWVyc0NvbnRyb2xPcHRpb25zKGNvbGxhcHNlZCA9IEZBTFNFKQ0KICApICU+JQ0KICAjIEFkZCBjb21tb24gbGVnZW5kDQogIGFkZExlZ2VuZChwYWwgPSBwYWwsIHZhbHVlcyA9IHR2YWxzLA0KICAgdGl0bGUgPSAiQW5udWFsIFRlbXBlcmF0dXJlIikNCm0NCmBgYA0KDQpZIGFzw60sIGhlbW9zIGRhZG8gdXNvIGEgYWxndW5hcyBkZSBsYXMgbXVjaGFzIGZ1bmNpb25lcyBxdWUgdGllbmVuIGVzdG9zIHBhcXVldGVzIGVuIFIsIHJlbGFjaW9uYWRvcyBjb24gdmFyaWFibGVzIGNsaW3DoXRpY2FzIHkgZXNwYWNpYWxlcy4gDQoNCiMgNC4gUmVwcm9kdWNpYmlsaWRhZCB5IGZ1ZW50ZXMuDQoNCkFkYXB0YWRvIGRlOiBMaXphcmF6bywgSS4sIDIwMjIuIEdldCBtb250aGx5IGNsaW1hdGUgbm9ybWFscyB1c2luZyBDbGltYXRlUi4gQXZhaWxhYmxlIGF0IGh0dHBzOi8vcnB1YnMuY29tL2lhbHMydW4vY2xpbWF0ZS4NCg0KYGBge3J9DQpzZXNzaW9uSW5mbygpDQpgYGANCg0K