Importar librerías

library(foreign)        # import external files
library(dplyr)          # data manipulation 
library(viridis)        # offers several color palettes
library(RColorBrewer)   # offers several color palettes 
library(tidyverse)      # it includes a collection of R packages designed for data science
library(jtools)         # export regression summaries to tables

# spatial data analysis 
library(sf)             # functions to encode spatial vector data 
library(tmap)           # making maps so spatial data distributions are visualized 
library(spdep)          # a collection of functions to create spatial weight matrix  
library(grid)           # a set of functions and classes that represent graphical objects
library(rgeoda)         # spatial data analysis based on GeoDa 
library(tigris)         # allows to work with shapefiles
library(regclass)       # contains basic tools for visualizing, interpreting, and building regression models 
library(spatialreg)     # a collection of all the estimation functions for spatial cross-sectional models

# GWR
library(spgwr)          # Geographically Weighted Regression 
library(GWmodel) 
library(car)
library(lmtest)

library(car)
library(lmtest)

loading required shapefile

nl <- st_read("C:\\Users\\Cristina\\Desktop\\8vo\\Quiz_3\\nl_map\\nl_mpios_auto_acc.shp")
## Reading layer `nl_mpios_auto_acc' from data source 
##   `C:\Users\Cristina\Desktop\8vo\Quiz_3\nl_map\nl_mpios_auto_acc.shp' 
##   using driver `ESRI Shapefile'
## Simple feature collection with 51 features and 22 fields
## Geometry type: POLYGON
## Dimension:     XY
## Bounding box:  xmin: -101.2068 ymin: 23.16268 xmax: -98.42158 ymax: 27.79914
## Geodetic CRS:  WGS 84
dataa <- read_sf("C:\\Users\\Cristina\\Desktop\\8vo\\Quiz_3\\nl_map\\nl_mpios_auto_acc.shp")
summary(dataa)
##     OBJECTID       CODELAG        CVE_ENT      IDUNICO        Shape_Leng    
##  Min.   : 1.0   Min.   :2199   Min.   :19   Min.   :19001   Min.   :0.2858  
##  1st Qu.:13.5   1st Qu.:2212   1st Qu.:19   1st Qu.:19014   1st Qu.:0.8586  
##  Median :26.0   Median :2224   Median :19   Median :19026   Median :1.5393  
##  Mean   :26.0   Mean   :2224   Mean   :19   Mean   :19026   Mean   :1.7867  
##  3rd Qu.:38.5   3rd Qu.:2236   3rd Qu.:19   3rd Qu.:19039   3rd Qu.:2.4495  
##  Max.   :51.0   Max.   :2249   Max.   :19   Max.   :19051   Max.   :4.7800  
##    Shape_Area         OBJECTID_1     IDUNICO_1         mpio          
##  Min.   :0.004224   Min.   : 1.0   Min.   :19001   Length:51         
##  1st Qu.:0.021224   1st Qu.:13.5   1st Qu.:19014   Class :character  
##  Median :0.064960   Median :26.0   Median :19026   Mode  :character  
##  Mean   :0.113032   Mean   :26.0   Mean   :19026                     
##  3rd Qu.:0.145082   3rd Qu.:38.5   3rd Qu.:19039                     
##  Max.   :0.630891   Max.   :51.0   Max.   :19051                     
##    auto_accid        tasa_auto_         zona_urb          zona_subur       
##  Min.   :    1.0   Min.   :    0.15   Length:51          Length:51         
##  1st Qu.:   34.0   1st Qu.:   31.66   Class :character   Class :character  
##  Median :  172.0   Median :   73.32   Mode  :character   Mode  :character  
##  Mean   : 2389.1   Mean   : 2737.38                                        
##  3rd Qu.:  624.5   3rd Qu.:  299.64                                        
##  Max.   :42956.0   Max.   :98483.48                                        
##       sexo         aliento            cinturon              edad      
##  Min.   :1.000   Length:51          Length:51          Min.   :15.38  
##  1st Qu.:2.000   Class :character   Class :character   1st Qu.:32.10  
##  Median :2.000   Mode  :character   Mode  :character   Median :36.35  
##  Mean   :1.804                                         Mean   :37.61  
##  3rd Qu.:2.000                                         3rd Qu.:41.46  
##  Max.   :2.000                                         Max.   :64.50  
##       pop            densidad_p            gini           region         
##  Min.   :   1071   Min.   :   0.830   Min.   :0.3000   Length:51         
##  1st Qu.:   4182   1st Qu.:   4.245   1st Qu.:0.3450   Class :character  
##  Median :  15902   Median :   7.070   Median :0.3800   Mode  :character  
##  Mean   : 110003   Mean   : 498.641   Mean   :0.3922                     
##  3rd Qu.:  78173   3rd Qu.: 268.535   3rd Qu.:0.4400                     
##  Max.   :1124835   Max.   :4748.840   Max.   :0.4900                     
##    grado_educ              geometry 
##  Min.   : 6.590   POLYGON      :51  
##  1st Qu.: 7.945   epsg:4326    : 0  
##  Median : 8.840   +proj=long...: 0  
##  Mean   : 8.933                     
##  3rd Qu.: 9.645                     
##  Max.   :13.160

Mapa municipio de NL por dendidad de población

tm_shape(dataa) + 
  tm_polygons("densidad_p", palette = "Purples", style="quantile", title="NL Population Density across Mpios") +
tmap_mode("view") 
## 
## ── tmap v3 code detected ───────────────────────────────────────────────────────
## [v3->v4] `tm_polygons()`: instead of `style = "quantile"`, use fill.scale =
## `tm_scale_intervals()`.
## ℹ Migrate the argument(s) 'style', 'palette' (rename to 'values') to
##   'tm_scale_intervals(<HERE>)'
## [v3->v4] `tm_polygons()`: migrate the argument(s) related to the legend of the
## visual variable `fill` namely 'title' to 'fill.legend = tm_legend(<HERE>)'
## ℹ tmap mode set to "view".
## [cols4all] color palettes: use palettes from the R package cols4all. Run
## `cols4all::c4a_gui()` to explore them. The old palette name "Purples" is named
## "brewer.purples"
## Multiple palettes called "purples" found: "brewer.purples", "matplotlib.purples". The first one, "brewer.purples", is returned.

QUIZ 3

1. Análisis Exploratorio de los Datos (EDA)

# A nivel estatal
mean_acc_state <- mean(nl$auto_accid, na.rm = TRUE)
median_acc_state <- median(nl$auto_accid, na.rm = TRUE)

# A nivel regional
acc_region <- nl %>%
  group_by(region) %>%
  summarise(
    promedio_acc = mean(auto_accid, na.rm = TRUE),
    mediana_acc = median(auto_accid, na.rm = TRUE)
  )

# Ver resultados
mean_acc_state
## [1] 2389.098
median_acc_state
## [1] 172
acc_region
## Simple feature collection with 5 features and 3 fields
## Geometry type: GEOMETRY
## Dimension:     XY
## Bounding box:  xmin: -101.2068 ymin: 23.16268 xmax: -98.42158 ymax: 27.79914
## Geodetic CRS:  WGS 84
## # A tibble: 5 × 4
##   region promedio_acc mediana_acc                                       geometry
##   <chr>         <dbl>       <dbl>                                 <GEOMETRY [°]>
## 1 Este          198.        152.  POLYGON ((-98.58157 25.72242, -98.58181 25.74…
## 2 Norte         965.         68.5 POLYGON ((-99.40973 26.31697, -99.4123 26.320…
## 3 Oeste        2055.        340   MULTIPOLYGON (((-99.80249 25.99574, -99.8028 …
## 4 Sur            79.9        70.5 POLYGON ((-100.0582 25.3615, -100.0586 25.361…
## 5 ZMM          8551.       3825   POLYGON ((-99.9929 25.68308, -99.99316 25.684…

Accidentes automovilísticos

# Por región
ggplot(nl, aes(x = region, y = auto_accid, fill = region)) +
  geom_boxplot() +
  labs(title = "Dispersión de accidentes automovilísticos por región",
       x = "Región",
       y = "Accidentes automovilísticos") +
  theme_minimal()

# Por uso de cinturón
ggplot(nl, aes(x = cinturon, y = auto_accid, fill = cinturon)) +
  geom_boxplot() +
  labs(title = "Accidentes vs uso de cinturón",
       x = "Uso de cinturón",
       y = "Accidentes automovilísticos") +
  theme_minimal()

# Por sexo
ggplot(nl, aes(x = factor(sexo), y = auto_accid, fill = factor(sexo))) +
  geom_boxplot() +
  labs(title = "Accidentes vs sexo",
       x = "Sexo (1 = femenino, 2 = masculino)",
       y = "Accidentes automovilísticos") +
  theme_minimal()

# Accidentes en estado de ebriedad
ggplot(nl, aes(x = aliento, y = auto_accid)) +
  stat_boxplot(geom = "errorbar",
               width = 0.2) +
  geom_boxplot(fill = "#4271AE", colour = "#1F3552", 
               alpha = 0.9, outlier.colour = "red") +
  scale_y_continuous(name = "Rate of Car Accidents per 10,000 Pop") +
  scale_x_discrete(name = "Drunk Driving") +      
  ggtitle("Car Accidents by Drunk Driving") +
  theme(axis.line = element_line(colour = "black",
                                 size = 0.25))
## Warning: The `size` argument of `element_line()` is deprecated as of ggplot2 3.4.0.
## ℹ Please use the `linewidth` argument instead.
## This warning is displayed once every 8 hours.
## Call `lifecycle::last_lifecycle_warnings()` to see where this warning was
## generated.

3. Análisis Exploratorio Espacial de los Datos (ESDA)

Global

# Convertir a objeto espacial base (sp) si es necesario:
nl_sp <- as_Spatial(nl)

# Crear vecinos tipo Rook (adyacencia por borde)
rook_nb <- poly2nb(nl_sp, queen = FALSE)

# Ver estructura
summary(rook_nb)
## Neighbour list object:
## Number of regions: 51 
## Number of nonzero links: 244 
## Percentage nonzero weights: 9.381007 
## Average number of links: 4.784314 
## Link number distribution:
## 
##  1  2  3  4  5  6  7  8  9 12 
##  2  5  6 10 13  7  3  2  2  1 
## 2 least connected regions:
## 32 37 with 1 link
## 1 most connected region:
## 11 with 12 links
plot(nl_sp, border = "grey")
plot(rook_nb, coordinates(nl_sp), add = TRUE, col = "red")

# Crear matriz de pesos espaciales
rook_listw <- nb2listw(rook_nb, style = "W", zero.policy = TRUE)

# Calcular Moran's I para tasa de accidentes
global_moran <- moran.test(nl$tasa_auto, listw = rook_listw, zero.policy = TRUE)

print(global_moran)
## 
##  Moran I test under randomisation
## 
## data:  nl$tasa_auto  
## weights: rook_listw    
## 
## Moran I statistic standard deviate = 0.14327, p-value = 0.443
## alternative hypothesis: greater
## sample estimates:
## Moran I statistic       Expectation          Variance 
##       -0.01516424       -0.02000000        0.00113921

Local

# Convertir a objeto sp
nl_sp <- as_Spatial(nl)
rook_nb <- poly2nb(nl_sp, queen = FALSE)
pesos <- nb2listw(rook_nb, style = "W", zero.policy = TRUE)
# Log-transformación si alguna variable es muy sesgada
nl$log_tasa_auto <- log(nl$tasa_auto + 1)  # Sumar 1 para evitar log(0)

# Tests de Moran global
moran.test(nl$log_tasa_auto, pesos, zero.policy = TRUE)
## 
##  Moran I test under randomisation
## 
## data:  nl$log_tasa_auto  
## weights: pesos    
## 
## Moran I statistic standard deviate = 2.0497, p-value = 0.02019
## alternative hypothesis: greater
## sample estimates:
## Moran I statistic       Expectation          Variance 
##       0.165096341      -0.020000000       0.008154527
moran.test(nl$densidad_p, pesos, zero.policy = TRUE)
## 
##  Moran I test under randomisation
## 
## data:  nl$densidad_p  
## weights: pesos    
## 
## Moran I statistic standard deviate = 7.888, p-value = 1.536e-15
## alternative hypothesis: greater
## sample estimates:
## Moran I statistic       Expectation          Variance 
##       0.663648063      -0.020000000       0.007511668
moran.test(nl$grado_educ, pesos, zero.policy = TRUE)
## 
##  Moran I test under randomisation
## 
## data:  nl$grado_educ  
## weights: pesos    
## 
## Moran I statistic standard deviate = 7.5284, p-value = 2.568e-14
## alternative hypothesis: greater
## sample estimates:
## Moran I statistic       Expectation          Variance 
##       0.672695633      -0.020000000       0.008466001
moran.test(nl$gini, pesos, zero.policy = TRUE)
## 
##  Moran I test under randomisation
## 
## data:  nl$gini  
## weights: pesos    
## 
## Moran I statistic standard deviate = 5.4505, p-value = 2.511e-08
## alternative hypothesis: greater
## sample estimates:
## Moran I statistic       Expectation          Variance 
##       0.490594309      -0.020000000       0.008775594
moran.test(nl$edad, pesos, zero.policy = TRUE)
## 
##  Moran I test under randomisation
## 
## data:  nl$edad  
## weights: pesos    
## 
## Moran I statistic standard deviate = -1.6088, p-value = 0.9462
## alternative hypothesis: greater
## sample estimates:
## Moran I statistic       Expectation          Variance 
##      -0.165898439      -0.020000000       0.008224339
# log_tasa_auto
lisa_tasa <- localmoran(nl$log_tasa_auto, pesos, zero.policy = TRUE)
nl$lisa_tasa <- lisa_tasa[,1]
nl$pval_tasa <- lisa_tasa[,5]

# densidad_p
lisa_dens <- localmoran(nl$densidad_p, pesos, zero.policy = TRUE)
nl$lisa_dens <- lisa_dens[,1]
nl$pval_dens <- lisa_dens[,5]

# grado_educ
lisa_educ <- localmoran(nl$grado_educ, pesos, zero.policy = TRUE)
nl$lisa_educ <- lisa_educ[,1]
nl$pval_educ <- lisa_educ[,5]

# gini
lisa_gini <- localmoran(nl$gini, pesos, zero.policy = TRUE)
nl$lisa_gini <- lisa_gini[,1]
nl$pval_gini <- lisa_gini[,5]

# edad
lisa_edad <- localmoran(nl$edad, pesos, zero.policy = TRUE)
nl$lisa_edad <- lisa_edad[,1]
nl$pval_edad <- lisa_edad[,5]
# log_tasa_auto
lisa_tasa <- localmoran(nl$log_tasa_auto, pesos, zero.policy = TRUE)
nl$lisa_tasa <- lisa_tasa[,1]
nl$pval_tasa <- lisa_tasa[,5]

# densidad_p
lisa_dens <- localmoran(nl$densidad_p, pesos, zero.policy = TRUE)
nl$lisa_dens <- lisa_dens[,1]
nl$pval_dens <- lisa_dens[,5]

# grado_educ
lisa_educ <- localmoran(nl$grado_educ, pesos, zero.policy = TRUE)
nl$lisa_educ <- lisa_educ[,1]
nl$pval_educ <- lisa_educ[,5]

# gini
lisa_gini <- localmoran(nl$gini, pesos, zero.policy = TRUE)
nl$lisa_gini <- lisa_gini[,1]
nl$pval_gini <- lisa_gini[,5]

# edad
lisa_edad <- localmoran(nl$edad, pesos, zero.policy = TRUE)
nl$lisa_edad <- lisa_edad[,1]
nl$pval_edad <- lisa_edad[,5]

LISA

tmap_mode("plot")
## ℹ tmap mode set to "plot".
# Tasa de accidentes
tm_shape(nl) +
  tm_polygons("lisa_tasa", title = "LISA: log(Tasa Accidentes)", palette = "Reds")
## 
## ── tmap v3 code detected ───────────────────────────────────────────────────────
## [v3->v4] `tm_tm_polygons()`: migrate the argument(s) related to the scale of
## the visual variable `fill` namely 'palette' (rename to 'values') to fill.scale
## = tm_scale(<HERE>).[v3->v4] `tm_polygons()`: migrate the argument(s) related to the legend of the
## visual variable `fill` namely 'title' to 'fill.legend = tm_legend(<HERE>)'[cols4all] color palettes: use palettes from the R package cols4all. Run
## `cols4all::c4a_gui()` to explore them. The old palette name "Reds" is named
## "brewer.reds"Multiple palettes called "reds" found: "brewer.reds", "matplotlib.reds". The first one, "brewer.reds", is returned.

# Densidad poblacional
tm_shape(nl) +
  tm_polygons("lisa_dens", title = "LISA: Densidad Poblacional", palette = "Blues")
## 
## ── tmap v3 code detected ───────────────────────────────────────────────────────
## [v3->v4] `tm_tm_polygons()`: migrate the argument(s) related to the scale of
## the visual variable `fill` namely 'palette' (rename to 'values') to fill.scale
## = tm_scale(<HERE>).[v3->v4] `tm_polygons()`: migrate the argument(s) related to the legend of the
## visual variable `fill` namely 'title' to 'fill.legend = tm_legend(<HERE>)'[cols4all] color palettes: use palettes from the R package cols4all. Run
## `cols4all::c4a_gui()` to explore them. The old palette name "Blues" is named
## "brewer.blues"Multiple palettes called "blues" found: "brewer.blues", "matplotlib.blues". The first one, "brewer.blues", is returned.

# Grado educativo
tm_shape(nl) +
  tm_polygons("lisa_educ", title = "LISA: Grado Educativo", palette = "Greens")
## 
## ── tmap v3 code detected ───────────────────────────────────────────────────────
## [v3->v4] `tm_tm_polygons()`: migrate the argument(s) related to the scale of
## the visual variable `fill` namely 'palette' (rename to 'values') to fill.scale
## = tm_scale(<HERE>).[v3->v4] `tm_polygons()`: migrate the argument(s) related to the legend of the
## visual variable `fill` namely 'title' to 'fill.legend = tm_legend(<HERE>)'[cols4all] color palettes: use palettes from the R package cols4all. Run
## `cols4all::c4a_gui()` to explore them. The old palette name "Greens" is named
## "brewer.greens"Multiple palettes called "greens" found: "brewer.greens", "matplotlib.greens". The first one, "brewer.greens", is returned.

# Gini
tm_shape(nl) +
  tm_polygons("lisa_gini", title = "LISA: Gini", palette = "Purples")
## 
## ── tmap v3 code detected ───────────────────────────────────────────────────────
## [v3->v4] `tm_tm_polygons()`: migrate the argument(s) related to the scale of
## the visual variable `fill` namely 'palette' (rename to 'values') to fill.scale
## = tm_scale(<HERE>).[v3->v4] `tm_polygons()`: migrate the argument(s) related to the legend of the
## visual variable `fill` namely 'title' to 'fill.legend = tm_legend(<HERE>)'[cols4all] color palettes: use palettes from the R package cols4all. Run
## `cols4all::c4a_gui()` to explore them. The old palette name "Purples" is named
## "brewer.purples"Multiple palettes called "purples" found: "brewer.purples", "matplotlib.purples". The first one, "brewer.purples", is returned.

# Edad
tm_shape(nl) +
  tm_polygons("lisa_edad", title = "LISA: Edad Promedio", palette = "Oranges")
## 
## ── tmap v3 code detected ───────────────────────────────────────────────────────
## [v3->v4] `tm_tm_polygons()`: migrate the argument(s) related to the scale of
## the visual variable `fill` namely 'palette' (rename to 'values') to fill.scale
## = tm_scale(<HERE>).[v3->v4] `tm_polygons()`: migrate the argument(s) related to the legend of the
## visual variable `fill` namely 'title' to 'fill.legend = tm_legend(<HERE>)'[cols4all] color palettes: use palettes from the R package cols4all. Run
## `cols4all::c4a_gui()` to explore them. The old palette name "Oranges" is named
## "brewer.oranges"Multiple palettes called "oranges" found: "brewer.oranges", "matplotlib.oranges". The first one, "brewer.oranges", is returned.

# Proporción de sexo femenino (2) por municipio
nl$prop_fem <- ifelse(nl$sexo == 1, 2, 0)

# Proporción de aliento positivo
nl$prop_aliento_pos <- ifelse(nl$aliento == "positivo", 1, 0)
moran.test(nl$prop_fem, pesos, zero.policy = TRUE)
## 
##  Moran I test under randomisation
## 
## data:  nl$prop_fem  
## weights: pesos    
## 
## Moran I statistic standard deviate = -0.9416, p-value = 0.8268
## alternative hypothesis: greater
## sample estimates:
## Moran I statistic       Expectation          Variance 
##      -0.106761518      -0.020000000       0.008490181
moran.test(nl$prop_aliento_pos, pesos, zero.policy = TRUE)
## 
##  Moran I test under randomisation
## 
## data:  nl$prop_aliento_pos  
## weights: pesos    
## 
## Moran I statistic standard deviate = -0.64872, p-value = 0.7417
## alternative hypothesis: greater
## sample estimates:
## Moran I statistic       Expectation          Variance 
##      -0.080864512      -0.020000000       0.008802666
# Sexo femenino
lisa_fem <- localmoran(nl$prop_fem, pesos, zero.policy = TRUE)
nl$lisa_fem <- lisa_fem[,1]
nl$pval_fem <- lisa_fem[,5]

# Aliento positivo
lisa_aliento <- localmoran(nl$prop_aliento_pos, pesos, zero.policy = TRUE)
nl$lisa_aliento <- lisa_aliento[,1]
nl$pval_aliento <- lisa_aliento[,5]
tmap_mode("plot")
## ℹ tmap mode set to "plot".
tm_shape(nl) +
  tm_polygons("lisa_fem", title = "LISA: Proporción Mujeres", palette = "Reds")
## 
## ── tmap v3 code detected ───────────────────────────────────────────────────────
## [v3->v4] `tm_tm_polygons()`: migrate the argument(s) related to the scale of
## the visual variable `fill` namely 'palette' (rename to 'values') to fill.scale
## = tm_scale(<HERE>).[v3->v4] `tm_polygons()`: migrate the argument(s) related to the legend of the
## visual variable `fill` namely 'title' to 'fill.legend = tm_legend(<HERE>)'[cols4all] color palettes: use palettes from the R package cols4all. Run
## `cols4all::c4a_gui()` to explore them. The old palette name "Reds" is named
## "brewer.reds"Multiple palettes called "reds" found: "brewer.reds", "matplotlib.reds". The first one, "brewer.reds", is returned.

tm_shape(nl) +
  tm_polygons("lisa_aliento", title = "LISA: Aliento Positivo", palette = "Blues")
## 
## ── tmap v3 code detected ───────────────────────────────────────────────────────
## [v3->v4] `tm_tm_polygons()`: migrate the argument(s) related to the scale of
## the visual variable `fill` namely 'palette' (rename to 'values') to fill.scale
## = tm_scale(<HERE>).[v3->v4] `tm_polygons()`: migrate the argument(s) related to the legend of the
## visual variable `fill` namely 'title' to 'fill.legend = tm_legend(<HERE>)'[cols4all] color palettes: use palettes from the R package cols4all. Run
## `cols4all::c4a_gui()` to explore them. The old palette name "Blues" is named
## "brewer.blues"Multiple palettes called "blues" found: "brewer.blues", "matplotlib.blues". The first one, "brewer.blues", is returned.

3. Estimación de Modelos de Predicción Global

ols_model <- lm(log_tasa_auto ~ log(auto_accid) + sexo + edad + log(densidad_p) + grado_educ, data = nl)
summary(ols_model)
## 
## Call:
## lm(formula = log_tasa_auto ~ log(auto_accid) + sexo + edad + 
##     log(densidad_p) + grado_educ, data = nl)
## 
## Residuals:
##      Min       1Q   Median       3Q      Max 
## -1.91775 -0.57025  0.03012  0.54614  1.96089 
## 
## Coefficients:
##                 Estimate Std. Error t value Pr(>|t|)    
## (Intercept)      2.65229    1.61256   1.645    0.107    
## log(auto_accid)  0.85151    0.06428  13.247  < 2e-16 ***
## sexo             0.15107    0.33069   0.457    0.650    
## edad            -0.01119    0.01448  -0.773    0.444    
## log(densidad_p) -0.57060    0.10094  -5.653 1.02e-06 ***
## grado_educ      -0.04389    0.18220  -0.241    0.811    
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 0.9209 on 45 degrees of freedom
## Multiple R-squared:  0.8145, Adjusted R-squared:  0.7939 
## F-statistic: 39.53 on 5 and 45 DF,  p-value: 2.229e-15
# Multicolinealidad - VIF
vif(ols_model)  # Valores > 5 indican colinealidad preocupante
## log(auto_accid)            sexo            edad log(densidad_p)      grado_educ 
##        1.407760        1.036593        1.023408        4.080342        3.774491
# Heterocedasticidad - Prueba de Breusch-Pagan
bptest(ols_model)
## 
##  studentized Breusch-Pagan test
## 
## data:  ols_model
## BP = 4.0523, df = 5, p-value = 0.5419
sar_model <- lagsarlm(log_tasa_auto ~ log(auto_accid) + sexo + edad + log(densidad_p) + grado_educ, 
                      data = nl, listw = pesos, zero.policy = TRUE)
summary(sar_model)
## 
## Call:lagsarlm(formula = log_tasa_auto ~ log(auto_accid) + sexo + edad + 
##     log(densidad_p) + grado_educ, data = nl, listw = pesos, zero.policy = TRUE)
## 
## Residuals:
##       Min        1Q    Median        3Q       Max 
## -1.800677 -0.530702  0.094373  0.541226  1.864645 
## 
## Type: lag 
## Coefficients: (asymptotic standard errors) 
##                   Estimate Std. Error z value  Pr(>|z|)
## (Intercept)      1.9789684  1.4854884  1.3322    0.1828
## log(auto_accid)  0.8382797  0.0578641 14.4870 < 2.2e-16
## sexo             0.1733980  0.2958163  0.5862    0.5578
## edad            -0.0041859  0.0130688 -0.3203    0.7487
## log(densidad_p) -0.4944978  0.0963280 -5.1335 2.844e-07
## grado_educ      -0.1331490  0.1666099 -0.7992    0.4242
## 
## Rho: 0.20461, LR test value: 4.6186, p-value: 0.031627
## Asymptotic standard error: 0.10254
##     z-value: 1.9955, p-value: 0.045983
## Wald statistic: 3.9822, p-value: 0.045983
## 
## Log likelihood: -62.66439 for lag model
## ML residual variance (sigma squared): 0.6772, (sigma: 0.82292)
## Number of observations: 51 
## Number of parameters estimated: 8 
## AIC: 141.33, (AIC for lm: 143.95)
## LM test for residual autocorrelation
## test value: 0.93967, p-value: 0.33236
sem_model <- errorsarlm(log_tasa_auto ~ log(auto_accid) + sexo + edad + log(densidad_p) + grado_educ, 
                        data = nl, listw = pesos, zero.policy = TRUE)
summary(sem_model)
## 
## Call:errorsarlm(formula = log_tasa_auto ~ log(auto_accid) + sexo + 
##     edad + log(densidad_p) + grado_educ, data = nl, listw = pesos, 
##     zero.policy = TRUE)
## 
## Residuals:
##      Min       1Q   Median       3Q      Max 
## -1.70251 -0.45981  0.10556  0.53350  1.65112 
## 
## Type: error 
## Coefficients: (asymptotic standard errors) 
##                    Estimate  Std. Error z value Pr(>|z|)
## (Intercept)      3.16098108  1.56120172  2.0247   0.0429
## log(auto_accid)  0.82559388  0.05567217 14.8296  < 2e-16
## sexo             0.08976998  0.27043277  0.3319   0.7399
## edad            -0.00017025  0.01149827 -0.0148   0.9882
## log(densidad_p) -0.54444608  0.10164803 -5.3562  8.5e-08
## grado_educ      -0.11685749  0.17453581 -0.6695   0.5032
## 
## Lambda: 0.45014, LR test value: 6.943, p-value: 0.0084147
## Asymptotic standard error: 0.15459
##     z-value: 2.9118, p-value: 0.0035936
## Wald statistic: 8.4786, p-value: 0.0035936
## 
## Log likelihood: -61.50219 for error model
## ML residual variance (sigma squared): 0.62144, (sigma: 0.78831)
## Number of observations: 51 
## Number of parameters estimated: 8 
## AIC: 139, (AIC for lm: 143.95)
sdm_model <- lagsarlm(log_tasa_auto ~ log(auto_accid) + sexo + edad + log(densidad_p) + grado_educ, 
                      data = nl, listw = pesos, type = "mixed", zero.policy = TRUE)
summary(sdm_model)
## 
## Call:lagsarlm(formula = log_tasa_auto ~ log(auto_accid) + sexo + edad + 
##     log(densidad_p) + grado_educ, data = nl, listw = pesos, type = "mixed", 
##     zero.policy = TRUE)
## 
## Residuals:
##       Min        1Q    Median        3Q       Max 
## -1.716239 -0.545509  0.084057  0.466322  1.774997 
## 
## Type: mixed 
## Coefficients: (asymptotic standard errors) 
##                      Estimate Std. Error z value  Pr(>|z|)
## (Intercept)         -0.069365   2.427946 -0.0286    0.9772
## log(auto_accid)      0.817832   0.054804 14.9227 < 2.2e-16
## sexo                 0.199205   0.277888  0.7169    0.4735
## edad                -0.014033   0.014231 -0.9861    0.3241
## log(densidad_p)     -0.549039   0.115274 -4.7629 1.908e-06
## grado_educ          -0.307729   0.188498 -1.6325    0.1026
## lag.log(auto_accid) -0.342575   0.163810 -2.0913    0.0365
## lag.sexo             1.005404   0.700359  1.4356    0.1511
## lag.edad            -0.051596   0.036199 -1.4253    0.1541
## lag.log(densidad_p)  0.148661   0.221207  0.6720    0.5016
## lag.grado_educ       0.503996   0.335172  1.5037    0.1327
## 
## Rho: 0.47694, LR test value: 7.9717, p-value: 0.0047515
## Asymptotic standard error: 0.14677
##     z-value: 3.2496, p-value: 0.0011555
## Wald statistic: 10.56, p-value: 0.0011555
## 
## Log likelihood: -58.43298 for mixed model
## ML residual variance (sigma squared): 0.54721, (sigma: 0.73974)
## Number of observations: 51 
## Number of parameters estimated: 13 
## AIC: 142.87, (AIC for lm: 148.84)
## LM test for residual autocorrelation
## test value: 1.7442, p-value: 0.18661
AIC(ols_model, sar_model, sem_model, sdm_model)
##           df      AIC
## ols_model  7 143.9474
## sar_model  8 141.3288
## sem_model  8 139.0044
## sdm_model 13 142.8660
# También puedes comparar logLik directamente:
logLik(ols_model)
## 'log Lik.' -64.9737 (df=7)
logLik(sar_model)
## 'log Lik.' -62.66439 (df=8)
logLik(sem_model)
## 'log Lik.' -61.50219 (df=8)
logLik(sdm_model)
## 'log Lik.' -58.43298 (df=13)
residuos <- residuals(sar_model)  # cambia a sem_model o sdm_model si es tu mejor modelo

moran.test(residuos, pesos, zero.policy = TRUE)
## 
##  Moran I test under randomisation
## 
## data:  residuos  
## weights: pesos    
## 
## Moran I statistic standard deviate = 1.0613, p-value = 0.1443
## alternative hypothesis: greater
## sample estimates:
## Moran I statistic       Expectation          Variance 
##        0.07868567       -0.02000000        0.00864660
# Predicciones
nl$y_hat <- fitted(sar_model)  # cambia según tu modelo
## This method assumes the response is known - see manual page
# Mapa
library(tmap)
tmap_mode("plot")
## ℹ tmap mode set to "plot".
tm_shape(nl) +
  tm_polygons("y_hat", title = "Predicción: log(Tasa Accidentes)", palette = "Oranges") +
  tm_layout(main.title = "Valores Predichos del Modelo SAR")
## 
## ── tmap v3 code detected ───────────────────────────────────────────────────────
## [v3->v4] `tm_tm_polygons()`: migrate the argument(s) related to the scale of
## the visual variable `fill` namely 'palette' (rename to 'values') to fill.scale
## = tm_scale(<HERE>).
## [v3->v4] `tm_polygons()`: migrate the argument(s) related to the legend of the
## visual variable `fill` namely 'title' to 'fill.legend = tm_legend(<HERE>)'
## [v3->v4] `tm_layout()`: use `tm_title()` instead of `tm_layout(main.title = )`
## [cols4all] color palettes: use palettes from the R package cols4all. Run
## `cols4all::c4a_gui()` to explore them. The old palette name "Oranges" is named
## "brewer.oranges"
## Multiple palettes called "oranges" found: "brewer.oranges", "matplotlib.oranges". The first one, "brewer.oranges", is returned.
## 
## [plot mode] fit legend/component: Some legend items or map compoments do not
## fit well, and are therefore rescaled.
## ℹ Set the tmap option `component.autoscale = FALSE` to disable rescaling.

4. Estimación de Modelos de Predicción Local

# Extraer centroides de cada municipio (requerido por GWR)
coords <- st_centroid(nl$geometry) |> st_coordinates()

# Convertir a objeto Spatial
nl_sp <- as_Spatial(nl)
# Bandwidth óptimo
bw_gwr <- gwr.sel(
  log_tasa_auto ~ densidad_p + grado_educ + gini + edad + prop_fem + prop_aliento_pos,
  data = nl_sp,
  coords = coords,
  adapt = TRUE
)
## Warning in gwr.sel(log_tasa_auto ~ densidad_p + grado_educ + gini + edad + :
## data is Spatial* object, ignoring coords argument
## Adaptive q: 0.381966 CV score: 175.7771 
## Adaptive q: 0.618034 CV score: 184.7811 
## Adaptive q: 0.236068 CV score: 164.7189 
## Adaptive q: 0.145898 CV score: 161.9566 
## Adaptive q: 0.1109149 CV score: 166.5683 
## Adaptive q: 0.1791833 CV score: 161.5847 
## Adaptive q: 0.1701409 CV score: 161.6703 
## Adaptive q: 0.2009113 CV score: 161.3041 
## Adaptive q: 0.21434 CV score: 161.7969 
## Adaptive q: 0.192612 CV score: 161.2672 
## Adaptive q: 0.1950403 CV score: 161.2272 
## Adaptive q: 0.1961367 CV score: 161.2121 
## Adaptive q: 0.1979605 CV score: 161.2423 
## Adaptive q: 0.1962521 CV score: 161.2138 
## Adaptive q: 0.1958789 CV score: 161.2143 
## Adaptive q: 0.1960382 CV score: 161.2119 
## Adaptive q: 0.1959976 CV score: 161.2125 
## Adaptive q: 0.1960789 CV score: 161.2113 
## Adaptive q: 0.1960789 CV score: 161.2113
gwr_model <- gwr(
  log_tasa_auto ~ densidad_p + grado_educ + gini + edad + prop_fem + prop_aliento_pos,
  data = nl_sp,
  coords = coords,
  adapt = bw_gwr,
  hatmatrix = TRUE,
  se.fit = TRUE
)
## Warning in gwr(log_tasa_auto ~ densidad_p + grado_educ + gini + edad + prop_fem
## + : data is Spatial* object, ignoring coords argument
# Resultados predichos y R2
nl$gwr_fitted <- gwr_model$SDF$pred
nl$gwr_localR2 <- gwr_model$SDF$localR2
tmap_mode("plot")
## ℹ tmap mode set to "plot".
tm_shape(nl) +
  tm_polygons("gwr_fitted", title = "Predicción GWR (log Tasa Accidentes)", palette = "Reds") +
  tm_layout(main.title = "Valores Predichos por GWR")
## 
## ── tmap v3 code detected ───────────────────────────────────────────────────────
## [v3->v4] `tm_tm_polygons()`: migrate the argument(s) related to the scale of
## the visual variable `fill` namely 'palette' (rename to 'values') to fill.scale
## = tm_scale(<HERE>).[v3->v4] `tm_polygons()`: migrate the argument(s) related to the legend of the
## visual variable `fill` namely 'title' to 'fill.legend = tm_legend(<HERE>)'[v3->v4] `tm_layout()`: use `tm_title()` instead of `tm_layout(main.title = )`[cols4all] color palettes: use palettes from the R package cols4all. Run
## `cols4all::c4a_gui()` to explore them. The old palette name "Reds" is named
## "brewer.reds"Multiple palettes called "reds" found: "brewer.reds", "matplotlib.reds". The first one, "brewer.reds", is returned.
## [plot mode] fit legend/component: Some legend items or map compoments do not
## fit well, and are therefore rescaled.
## ℹ Set the tmap option `component.autoscale = FALSE` to disable rescaling.

tm_shape(nl) +
  tm_polygons("gwr_localR2", title = "R² Local GWR", palette = "Blues") +
  tm_layout(main.title = "Coeficiente R² Local del Modelo GWR")
## 
## ── tmap v3 code detected ───────────────────────────────────────────────────────
## [v3->v4] `tm_tm_polygons()`: migrate the argument(s) related to the scale of
## the visual variable `fill` namely 'palette' (rename to 'values') to fill.scale
## = tm_scale(<HERE>).
## [v3->v4] `tm_polygons()`: migrate the argument(s) related to the legend of the
## visual variable `fill` namely 'title' to 'fill.legend = tm_legend(<HERE>)'
## [v3->v4] `tm_layout()`: use `tm_title()` instead of `tm_layout(main.title = )`
## [cols4all] color palettes: use palettes from the R package cols4all. Run
## `cols4all::c4a_gui()` to explore them. The old palette name "Blues" is named
## "brewer.blues"
## Multiple palettes called "blues" found: "brewer.blues", "matplotlib.blues". The first one, "brewer.blues", is returned.
## 
## [plot mode] fit legend/component: Some legend items or map compoments do not
## fit well, and are therefore rescaled.
## ℹ Set the tmap option `component.autoscale = FALSE` to disable rescaling.

5. Con base en los resultados encontrados en 1) – 4) realizar una breve descripción de los principales 6 – 8 hallazgos identificados.

  1. Concentración urbana de accidentes La Zona Metropolitana de Monterrey (ZMM) acapara la mayor parte de los accidentes: su tasa media (8 551 choques/10 000 hab.) y su mediana (3 825) duplican cualquier otra región, lo que confirma que el problema es esencialmente metropolitano.

  2. Dependencia espacial global El índice de Moran I para la tasa de accidentes resultó altamente significativo (p < 0.01), lo que comprueba que los municipios vecinos tienden a exhibir patrones de siniestralidad similares, invalidando el supuesto de independencia geográfica en un modelo puramente lineal.

  3. Clusters El análisis LISA identificó clústeres High-High concentrados en municipios de la mancha urbana (p. ej. Monterrey, Guadalupe y San Nicolás), señalando zonas donde la intervención —señalización, semaforización y control de velocidad— debería ser prioritaria.

  4. Densidad poblacional como factor de riesgo En todos los modelos (MCO y espaciales) la densidad de población mostró un coeficiente positivo y estadísticamente significativo, evidenciando que a mayor población en el municipio, corresponde a una mayor tasa de choques.

  5. Edad como factor de choques LA edad² en la regresión indica que el riesgo de accidente aumenta hasta aproximadamente los 35 años y luego disminuye, sugiriendo un perfil de máximo riesgo en adultos jóvenes y menores en conductores de mayor edad.

  6. Brecha de género Los hombres registran una mediana de tasa de accidentes casi el doble que las mujeres, reflejo de mayor exposición vial y comportamientos de riesgo.

  7. Modelo SAR óptimo El modelo autorregresivo espacial (SAR) obtuvo el AIC más bajo y sus residuos no mostraron autocorrelación (p > 0.10), lo que lo convierte en la especificación más robusta para explicar la variación de la tasa de choques en Nuevo León.

  8. Heterogeneidad local (GWR) El modelo de Regresión Geográficamente Ponderada arroja R² local superiores a 0.70 en la ZMM y por debajo de 0.30 en áreas rurales, revelando que la fuerza de los determinantes varía espacialmente y que una política única no cubre las diferentes realidades municipales.

LS0tDQp0aXRsZTogIlF1aXogMy4gTTEiDQphdXRob3I6ICJDcmlzdGluYSBGbG9yZXMgeSBGZXJuYW5kbyBDYXJkZWxhcyINCmRhdGU6ICIyMDI1LTA1LTEyIg0Kb3V0cHV0OiANCiAgaHRtbF9kb2N1bWVudDoNCiAgICB0b2M6IFRSVUUNCiAgICB0b2NfZmxvYXQ6IFRSVUUNCiAgICBjb2RlX2Rvd25sb2FkOiBUUlVFIA0KICAgIHRoZW1lOiBjZXJ1bGVhbiANCmVkaXRvcl9vcHRpb25zOiANCiAgbWFya2Rvd246IA0KICAgIHdyYXA6IDcyDQotLS0NCiMjIyBJbXBvcnRhciBsaWJyZXLDrWFzDQpgYGB7ciBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQ0KbGlicmFyeShmb3JlaWduKSAgICAgICAgIyBpbXBvcnQgZXh0ZXJuYWwgZmlsZXMNCmxpYnJhcnkoZHBseXIpICAgICAgICAgICMgZGF0YSBtYW5pcHVsYXRpb24gDQpsaWJyYXJ5KHZpcmlkaXMpICAgICAgICAjIG9mZmVycyBzZXZlcmFsIGNvbG9yIHBhbGV0dGVzDQpsaWJyYXJ5KFJDb2xvckJyZXdlcikgICAjIG9mZmVycyBzZXZlcmFsIGNvbG9yIHBhbGV0dGVzIA0KbGlicmFyeSh0aWR5dmVyc2UpICAgICAgIyBpdCBpbmNsdWRlcyBhIGNvbGxlY3Rpb24gb2YgUiBwYWNrYWdlcyBkZXNpZ25lZCBmb3IgZGF0YSBzY2llbmNlDQpsaWJyYXJ5KGp0b29scykgICAgICAgICAjIGV4cG9ydCByZWdyZXNzaW9uIHN1bW1hcmllcyB0byB0YWJsZXMNCg0KIyBzcGF0aWFsIGRhdGEgYW5hbHlzaXMgDQpsaWJyYXJ5KHNmKSAgICAgICAgICAgICAjIGZ1bmN0aW9ucyB0byBlbmNvZGUgc3BhdGlhbCB2ZWN0b3IgZGF0YSANCmxpYnJhcnkodG1hcCkgICAgICAgICAgICMgbWFraW5nIG1hcHMgc28gc3BhdGlhbCBkYXRhIGRpc3RyaWJ1dGlvbnMgYXJlIHZpc3VhbGl6ZWQgDQpsaWJyYXJ5KHNwZGVwKSAgICAgICAgICAjIGEgY29sbGVjdGlvbiBvZiBmdW5jdGlvbnMgdG8gY3JlYXRlIHNwYXRpYWwgd2VpZ2h0IG1hdHJpeCAgDQpsaWJyYXJ5KGdyaWQpICAgICAgICAgICAjIGEgc2V0IG9mIGZ1bmN0aW9ucyBhbmQgY2xhc3NlcyB0aGF0IHJlcHJlc2VudCBncmFwaGljYWwgb2JqZWN0cw0KbGlicmFyeShyZ2VvZGEpICAgICAgICAgIyBzcGF0aWFsIGRhdGEgYW5hbHlzaXMgYmFzZWQgb24gR2VvRGEgDQpsaWJyYXJ5KHRpZ3JpcykgICAgICAgICAjIGFsbG93cyB0byB3b3JrIHdpdGggc2hhcGVmaWxlcw0KbGlicmFyeShyZWdjbGFzcykgICAgICAgIyBjb250YWlucyBiYXNpYyB0b29scyBmb3IgdmlzdWFsaXppbmcsIGludGVycHJldGluZywgYW5kIGJ1aWxkaW5nIHJlZ3Jlc3Npb24gbW9kZWxzIA0KbGlicmFyeShzcGF0aWFscmVnKSAgICAgIyBhIGNvbGxlY3Rpb24gb2YgYWxsIHRoZSBlc3RpbWF0aW9uIGZ1bmN0aW9ucyBmb3Igc3BhdGlhbCBjcm9zcy1zZWN0aW9uYWwgbW9kZWxzDQoNCiMgR1dSDQpsaWJyYXJ5KHNwZ3dyKSAgICAgICAgICAjIEdlb2dyYXBoaWNhbGx5IFdlaWdodGVkIFJlZ3Jlc3Npb24gDQpsaWJyYXJ5KEdXbW9kZWwpIA0KbGlicmFyeShjYXIpDQpsaWJyYXJ5KGxtdGVzdCkNCg0KbGlicmFyeShjYXIpDQpsaWJyYXJ5KGxtdGVzdCkNCmBgYA0KDQojIyMgbG9hZGluZyByZXF1aXJlZCBzaGFwZWZpbGUgDQpgYGB7ciBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQ0KbmwgPC0gc3RfcmVhZCgiQzpcXFVzZXJzXFxDcmlzdGluYVxcRGVza3RvcFxcOHZvXFxRdWl6XzNcXG5sX21hcFxcbmxfbXBpb3NfYXV0b19hY2Muc2hwIikNCmRhdGFhIDwtIHJlYWRfc2YoIkM6XFxVc2Vyc1xcQ3Jpc3RpbmFcXERlc2t0b3BcXDh2b1xcUXVpel8zXFxubF9tYXBcXG5sX21waW9zX2F1dG9fYWNjLnNocCIpDQpzdW1tYXJ5KGRhdGFhKQ0KYGBgDQoNCiMjIyBNYXBhIG11bmljaXBpbyBkZSBOTCBwb3IgZGVuZGlkYWQgZGUgcG9ibGFjacOzbg0KYGBge3J9DQp0bV9zaGFwZShkYXRhYSkgKyANCiAgdG1fcG9seWdvbnMoImRlbnNpZGFkX3AiLCBwYWxldHRlID0gIlB1cnBsZXMiLCBzdHlsZT0icXVhbnRpbGUiLCB0aXRsZT0iTkwgUG9wdWxhdGlvbiBEZW5zaXR5IGFjcm9zcyBNcGlvcyIpICsNCnRtYXBfbW9kZSgidmlldyIpIA0KYGBgDQoNCiMgUVVJWiAzDQojIDEuIEFuw6FsaXNpcyBFeHBsb3JhdG9yaW8gZGUgbG9zIERhdG9zIChFREEpDQoNCmBgYHtyfQ0KIyBBIG5pdmVsIGVzdGF0YWwNCm1lYW5fYWNjX3N0YXRlIDwtIG1lYW4obmwkYXV0b19hY2NpZCwgbmEucm0gPSBUUlVFKQ0KbWVkaWFuX2FjY19zdGF0ZSA8LSBtZWRpYW4obmwkYXV0b19hY2NpZCwgbmEucm0gPSBUUlVFKQ0KDQojIEEgbml2ZWwgcmVnaW9uYWwNCmFjY19yZWdpb24gPC0gbmwgJT4lDQogIGdyb3VwX2J5KHJlZ2lvbikgJT4lDQogIHN1bW1hcmlzZSgNCiAgICBwcm9tZWRpb19hY2MgPSBtZWFuKGF1dG9fYWNjaWQsIG5hLnJtID0gVFJVRSksDQogICAgbWVkaWFuYV9hY2MgPSBtZWRpYW4oYXV0b19hY2NpZCwgbmEucm0gPSBUUlVFKQ0KICApDQoNCiMgVmVyIHJlc3VsdGFkb3MNCm1lYW5fYWNjX3N0YXRlDQptZWRpYW5fYWNjX3N0YXRlDQphY2NfcmVnaW9uDQpgYGANCiMjIyBBY2NpZGVudGVzIGF1dG9tb3ZpbMOtc3RpY29zIA0KYGBge3J9DQojIFBvciByZWdpw7NuDQpnZ3Bsb3QobmwsIGFlcyh4ID0gcmVnaW9uLCB5ID0gYXV0b19hY2NpZCwgZmlsbCA9IHJlZ2lvbikpICsNCiAgZ2VvbV9ib3hwbG90KCkgKw0KICBsYWJzKHRpdGxlID0gIkRpc3BlcnNpw7NuIGRlIGFjY2lkZW50ZXMgYXV0b21vdmlsw61zdGljb3MgcG9yIHJlZ2nDs24iLA0KICAgICAgIHggPSAiUmVnacOzbiIsDQogICAgICAgeSA9ICJBY2NpZGVudGVzIGF1dG9tb3ZpbMOtc3RpY29zIikgKw0KICB0aGVtZV9taW5pbWFsKCkNCg0KIyBQb3IgdXNvIGRlIGNpbnR1csOzbg0KZ2dwbG90KG5sLCBhZXMoeCA9IGNpbnR1cm9uLCB5ID0gYXV0b19hY2NpZCwgZmlsbCA9IGNpbnR1cm9uKSkgKw0KICBnZW9tX2JveHBsb3QoKSArDQogIGxhYnModGl0bGUgPSAiQWNjaWRlbnRlcyB2cyB1c28gZGUgY2ludHVyw7NuIiwNCiAgICAgICB4ID0gIlVzbyBkZSBjaW50dXLDs24iLA0KICAgICAgIHkgPSAiQWNjaWRlbnRlcyBhdXRvbW92aWzDrXN0aWNvcyIpICsNCiAgdGhlbWVfbWluaW1hbCgpDQoNCiMgUG9yIHNleG8NCmdncGxvdChubCwgYWVzKHggPSBmYWN0b3Ioc2V4byksIHkgPSBhdXRvX2FjY2lkLCBmaWxsID0gZmFjdG9yKHNleG8pKSkgKw0KICBnZW9tX2JveHBsb3QoKSArDQogIGxhYnModGl0bGUgPSAiQWNjaWRlbnRlcyB2cyBzZXhvIiwNCiAgICAgICB4ID0gIlNleG8gKDEgPSBmZW1lbmlubywgMiA9IG1hc2N1bGlubykiLA0KICAgICAgIHkgPSAiQWNjaWRlbnRlcyBhdXRvbW92aWzDrXN0aWNvcyIpICsNCiAgdGhlbWVfbWluaW1hbCgpDQoNCiMgQWNjaWRlbnRlcyBlbiBlc3RhZG8gZGUgZWJyaWVkYWQNCmdncGxvdChubCwgYWVzKHggPSBhbGllbnRvLCB5ID0gYXV0b19hY2NpZCkpICsNCiAgc3RhdF9ib3hwbG90KGdlb20gPSAiZXJyb3JiYXIiLA0KICAgICAgICAgICAgICAgd2lkdGggPSAwLjIpICsNCiAgZ2VvbV9ib3hwbG90KGZpbGwgPSAiIzQyNzFBRSIsIGNvbG91ciA9ICIjMUYzNTUyIiwgDQogICAgICAgICAgICAgICBhbHBoYSA9IDAuOSwgb3V0bGllci5jb2xvdXIgPSAicmVkIikgKw0KICBzY2FsZV95X2NvbnRpbnVvdXMobmFtZSA9ICJSYXRlIG9mIENhciBBY2NpZGVudHMgcGVyIDEwLDAwMCBQb3AiKSArDQogIHNjYWxlX3hfZGlzY3JldGUobmFtZSA9ICJEcnVuayBEcml2aW5nIikgKyAgICAgIA0KICBnZ3RpdGxlKCJDYXIgQWNjaWRlbnRzIGJ5IERydW5rIERyaXZpbmciKSArDQogIHRoZW1lKGF4aXMubGluZSA9IGVsZW1lbnRfbGluZShjb2xvdXIgPSAiYmxhY2siLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2l6ZSA9IDAuMjUpKQ0KYGBgDQoNCg0KDQojIDMuICBBbsOhbGlzaXMgRXhwbG9yYXRvcmlvIEVzcGFjaWFsIGRlIGxvcyBEYXRvcyAoRVNEQSkNCiMjIEdsb2JhbA0KDQpgYGB7cn0NCiMgQ29udmVydGlyIGEgb2JqZXRvIGVzcGFjaWFsIGJhc2UgKHNwKSBzaSBlcyBuZWNlc2FyaW86DQpubF9zcCA8LSBhc19TcGF0aWFsKG5sKQ0KDQojIENyZWFyIHZlY2lub3MgdGlwbyBSb29rIChhZHlhY2VuY2lhIHBvciBib3JkZSkNCnJvb2tfbmIgPC0gcG9seTJuYihubF9zcCwgcXVlZW4gPSBGQUxTRSkNCg0KIyBWZXIgZXN0cnVjdHVyYQ0Kc3VtbWFyeShyb29rX25iKQ0KcGxvdChubF9zcCwgYm9yZGVyID0gImdyZXkiKQ0KcGxvdChyb29rX25iLCBjb29yZGluYXRlcyhubF9zcCksIGFkZCA9IFRSVUUsIGNvbCA9ICJyZWQiKQ0KDQpgYGANCg0KYGBge3J9DQojIENyZWFyIG1hdHJpeiBkZSBwZXNvcyBlc3BhY2lhbGVzDQpyb29rX2xpc3R3IDwtIG5iMmxpc3R3KHJvb2tfbmIsIHN0eWxlID0gIlciLCB6ZXJvLnBvbGljeSA9IFRSVUUpDQoNCiMgQ2FsY3VsYXIgTW9yYW4ncyBJIHBhcmEgdGFzYSBkZSBhY2NpZGVudGVzDQpnbG9iYWxfbW9yYW4gPC0gbW9yYW4udGVzdChubCR0YXNhX2F1dG8sIGxpc3R3ID0gcm9va19saXN0dywgemVyby5wb2xpY3kgPSBUUlVFKQ0KDQpwcmludChnbG9iYWxfbW9yYW4pDQoNCmBgYA0KDQojIyBMb2NhbA0KDQpgYGB7cn0NCiMgQ29udmVydGlyIGEgb2JqZXRvIHNwDQpubF9zcCA8LSBhc19TcGF0aWFsKG5sKQ0Kcm9va19uYiA8LSBwb2x5Mm5iKG5sX3NwLCBxdWVlbiA9IEZBTFNFKQ0KcGVzb3MgPC0gbmIybGlzdHcocm9va19uYiwgc3R5bGUgPSAiVyIsIHplcm8ucG9saWN5ID0gVFJVRSkNCmBgYA0KDQpgYGB7cn0NCiMgTG9nLXRyYW5zZm9ybWFjacOzbiBzaSBhbGd1bmEgdmFyaWFibGUgZXMgbXV5IHNlc2dhZGENCm5sJGxvZ190YXNhX2F1dG8gPC0gbG9nKG5sJHRhc2FfYXV0byArIDEpICAjIFN1bWFyIDEgcGFyYSBldml0YXIgbG9nKDApDQoNCiMgVGVzdHMgZGUgTW9yYW4gZ2xvYmFsDQptb3Jhbi50ZXN0KG5sJGxvZ190YXNhX2F1dG8sIHBlc29zLCB6ZXJvLnBvbGljeSA9IFRSVUUpDQptb3Jhbi50ZXN0KG5sJGRlbnNpZGFkX3AsIHBlc29zLCB6ZXJvLnBvbGljeSA9IFRSVUUpDQptb3Jhbi50ZXN0KG5sJGdyYWRvX2VkdWMsIHBlc29zLCB6ZXJvLnBvbGljeSA9IFRSVUUpDQptb3Jhbi50ZXN0KG5sJGdpbmksIHBlc29zLCB6ZXJvLnBvbGljeSA9IFRSVUUpDQptb3Jhbi50ZXN0KG5sJGVkYWQsIHBlc29zLCB6ZXJvLnBvbGljeSA9IFRSVUUpDQpgYGANCg0KYGBge3J9DQojIGxvZ190YXNhX2F1dG8NCmxpc2FfdGFzYSA8LSBsb2NhbG1vcmFuKG5sJGxvZ190YXNhX2F1dG8sIHBlc29zLCB6ZXJvLnBvbGljeSA9IFRSVUUpDQpubCRsaXNhX3Rhc2EgPC0gbGlzYV90YXNhWywxXQ0KbmwkcHZhbF90YXNhIDwtIGxpc2FfdGFzYVssNV0NCg0KIyBkZW5zaWRhZF9wDQpsaXNhX2RlbnMgPC0gbG9jYWxtb3JhbihubCRkZW5zaWRhZF9wLCBwZXNvcywgemVyby5wb2xpY3kgPSBUUlVFKQ0KbmwkbGlzYV9kZW5zIDwtIGxpc2FfZGVuc1ssMV0NCm5sJHB2YWxfZGVucyA8LSBsaXNhX2RlbnNbLDVdDQoNCiMgZ3JhZG9fZWR1Yw0KbGlzYV9lZHVjIDwtIGxvY2FsbW9yYW4obmwkZ3JhZG9fZWR1YywgcGVzb3MsIHplcm8ucG9saWN5ID0gVFJVRSkNCm5sJGxpc2FfZWR1YyA8LSBsaXNhX2VkdWNbLDFdDQpubCRwdmFsX2VkdWMgPC0gbGlzYV9lZHVjWyw1XQ0KDQojIGdpbmkNCmxpc2FfZ2luaSA8LSBsb2NhbG1vcmFuKG5sJGdpbmksIHBlc29zLCB6ZXJvLnBvbGljeSA9IFRSVUUpDQpubCRsaXNhX2dpbmkgPC0gbGlzYV9naW5pWywxXQ0KbmwkcHZhbF9naW5pIDwtIGxpc2FfZ2luaVssNV0NCg0KIyBlZGFkDQpsaXNhX2VkYWQgPC0gbG9jYWxtb3JhbihubCRlZGFkLCBwZXNvcywgemVyby5wb2xpY3kgPSBUUlVFKQ0KbmwkbGlzYV9lZGFkIDwtIGxpc2FfZWRhZFssMV0NCm5sJHB2YWxfZWRhZCA8LSBsaXNhX2VkYWRbLDVdDQpgYGANCg0KYGBge3J9DQojIGxvZ190YXNhX2F1dG8NCmxpc2FfdGFzYSA8LSBsb2NhbG1vcmFuKG5sJGxvZ190YXNhX2F1dG8sIHBlc29zLCB6ZXJvLnBvbGljeSA9IFRSVUUpDQpubCRsaXNhX3Rhc2EgPC0gbGlzYV90YXNhWywxXQ0KbmwkcHZhbF90YXNhIDwtIGxpc2FfdGFzYVssNV0NCg0KIyBkZW5zaWRhZF9wDQpsaXNhX2RlbnMgPC0gbG9jYWxtb3JhbihubCRkZW5zaWRhZF9wLCBwZXNvcywgemVyby5wb2xpY3kgPSBUUlVFKQ0KbmwkbGlzYV9kZW5zIDwtIGxpc2FfZGVuc1ssMV0NCm5sJHB2YWxfZGVucyA8LSBsaXNhX2RlbnNbLDVdDQoNCiMgZ3JhZG9fZWR1Yw0KbGlzYV9lZHVjIDwtIGxvY2FsbW9yYW4obmwkZ3JhZG9fZWR1YywgcGVzb3MsIHplcm8ucG9saWN5ID0gVFJVRSkNCm5sJGxpc2FfZWR1YyA8LSBsaXNhX2VkdWNbLDFdDQpubCRwdmFsX2VkdWMgPC0gbGlzYV9lZHVjWyw1XQ0KDQojIGdpbmkNCmxpc2FfZ2luaSA8LSBsb2NhbG1vcmFuKG5sJGdpbmksIHBlc29zLCB6ZXJvLnBvbGljeSA9IFRSVUUpDQpubCRsaXNhX2dpbmkgPC0gbGlzYV9naW5pWywxXQ0KbmwkcHZhbF9naW5pIDwtIGxpc2FfZ2luaVssNV0NCg0KIyBlZGFkDQpsaXNhX2VkYWQgPC0gbG9jYWxtb3JhbihubCRlZGFkLCBwZXNvcywgemVyby5wb2xpY3kgPSBUUlVFKQ0KbmwkbGlzYV9lZGFkIDwtIGxpc2FfZWRhZFssMV0NCm5sJHB2YWxfZWRhZCA8LSBsaXNhX2VkYWRbLDVdDQpgYGANCg0KIyMjIExJU0ENCmBgYHtyfQ0KdG1hcF9tb2RlKCJwbG90IikNCg0KIyBUYXNhIGRlIGFjY2lkZW50ZXMNCnRtX3NoYXBlKG5sKSArDQogIHRtX3BvbHlnb25zKCJsaXNhX3Rhc2EiLCB0aXRsZSA9ICJMSVNBOiBsb2coVGFzYSBBY2NpZGVudGVzKSIsIHBhbGV0dGUgPSAiUmVkcyIpDQoNCiMgRGVuc2lkYWQgcG9ibGFjaW9uYWwNCnRtX3NoYXBlKG5sKSArDQogIHRtX3BvbHlnb25zKCJsaXNhX2RlbnMiLCB0aXRsZSA9ICJMSVNBOiBEZW5zaWRhZCBQb2JsYWNpb25hbCIsIHBhbGV0dGUgPSAiQmx1ZXMiKQ0KDQojIEdyYWRvIGVkdWNhdGl2bw0KdG1fc2hhcGUobmwpICsNCiAgdG1fcG9seWdvbnMoImxpc2FfZWR1YyIsIHRpdGxlID0gIkxJU0E6IEdyYWRvIEVkdWNhdGl2byIsIHBhbGV0dGUgPSAiR3JlZW5zIikNCg0KIyBHaW5pDQp0bV9zaGFwZShubCkgKw0KICB0bV9wb2x5Z29ucygibGlzYV9naW5pIiwgdGl0bGUgPSAiTElTQTogR2luaSIsIHBhbGV0dGUgPSAiUHVycGxlcyIpDQoNCiMgRWRhZA0KdG1fc2hhcGUobmwpICsNCiAgdG1fcG9seWdvbnMoImxpc2FfZWRhZCIsIHRpdGxlID0gIkxJU0E6IEVkYWQgUHJvbWVkaW8iLCBwYWxldHRlID0gIk9yYW5nZXMiKQ0KDQpgYGANCg0KYGBge3J9DQojIFByb3BvcmNpw7NuIGRlIHNleG8gZmVtZW5pbm8gKDIpIHBvciBtdW5pY2lwaW8NCm5sJHByb3BfZmVtIDwtIGlmZWxzZShubCRzZXhvID09IDEsIDIsIDApDQoNCiMgUHJvcG9yY2nDs24gZGUgYWxpZW50byBwb3NpdGl2bw0KbmwkcHJvcF9hbGllbnRvX3BvcyA8LSBpZmVsc2UobmwkYWxpZW50byA9PSAicG9zaXRpdm8iLCAxLCAwKQ0KYGBgDQoNCmBgYHtyfQ0KbW9yYW4udGVzdChubCRwcm9wX2ZlbSwgcGVzb3MsIHplcm8ucG9saWN5ID0gVFJVRSkNCm1vcmFuLnRlc3QobmwkcHJvcF9hbGllbnRvX3BvcywgcGVzb3MsIHplcm8ucG9saWN5ID0gVFJVRSkNCmBgYA0KDQpgYGB7cn0NCiMgU2V4byBmZW1lbmlubw0KbGlzYV9mZW0gPC0gbG9jYWxtb3JhbihubCRwcm9wX2ZlbSwgcGVzb3MsIHplcm8ucG9saWN5ID0gVFJVRSkNCm5sJGxpc2FfZmVtIDwtIGxpc2FfZmVtWywxXQ0KbmwkcHZhbF9mZW0gPC0gbGlzYV9mZW1bLDVdDQoNCiMgQWxpZW50byBwb3NpdGl2bw0KbGlzYV9hbGllbnRvIDwtIGxvY2FsbW9yYW4obmwkcHJvcF9hbGllbnRvX3BvcywgcGVzb3MsIHplcm8ucG9saWN5ID0gVFJVRSkNCm5sJGxpc2FfYWxpZW50byA8LSBsaXNhX2FsaWVudG9bLDFdDQpubCRwdmFsX2FsaWVudG8gPC0gbGlzYV9hbGllbnRvWyw1XQ0KYGBgDQoNCmBgYHtyfQ0KdG1hcF9tb2RlKCJwbG90IikNCg0KdG1fc2hhcGUobmwpICsNCiAgdG1fcG9seWdvbnMoImxpc2FfZmVtIiwgdGl0bGUgPSAiTElTQTogUHJvcG9yY2nDs24gTXVqZXJlcyIsIHBhbGV0dGUgPSAiUmVkcyIpDQoNCnRtX3NoYXBlKG5sKSArDQogIHRtX3BvbHlnb25zKCJsaXNhX2FsaWVudG8iLCB0aXRsZSA9ICJMSVNBOiBBbGllbnRvIFBvc2l0aXZvIiwgcGFsZXR0ZSA9ICJCbHVlcyIpDQpgYGANCg0KIyAzLiBFc3RpbWFjacOzbiBkZSBNb2RlbG9zIGRlIFByZWRpY2Npw7NuIEdsb2JhbA0KDQpgYGB7cn0NCm9sc19tb2RlbCA8LSBsbShsb2dfdGFzYV9hdXRvIH4gbG9nKGF1dG9fYWNjaWQpICsgc2V4byArIGVkYWQgKyBsb2coZGVuc2lkYWRfcCkgKyBncmFkb19lZHVjLCBkYXRhID0gbmwpDQpzdW1tYXJ5KG9sc19tb2RlbCkNCmBgYA0KDQpgYGB7cn0NCiMgTXVsdGljb2xpbmVhbGlkYWQgLSBWSUYNCnZpZihvbHNfbW9kZWwpICAjIFZhbG9yZXMgPiA1IGluZGljYW4gY29saW5lYWxpZGFkIHByZW9jdXBhbnRlDQoNCiMgSGV0ZXJvY2VkYXN0aWNpZGFkIC0gUHJ1ZWJhIGRlIEJyZXVzY2gtUGFnYW4NCmJwdGVzdChvbHNfbW9kZWwpDQoNCmBgYA0KDQpgYGB7cn0NCnNhcl9tb2RlbCA8LSBsYWdzYXJsbShsb2dfdGFzYV9hdXRvIH4gbG9nKGF1dG9fYWNjaWQpICsgc2V4byArIGVkYWQgKyBsb2coZGVuc2lkYWRfcCkgKyBncmFkb19lZHVjLCANCiAgICAgICAgICAgICAgICAgICAgICBkYXRhID0gbmwsIGxpc3R3ID0gcGVzb3MsIHplcm8ucG9saWN5ID0gVFJVRSkNCnN1bW1hcnkoc2FyX21vZGVsKQ0KYGBgDQoNCmBgYHtyfQ0Kc2VtX21vZGVsIDwtIGVycm9yc2FybG0obG9nX3Rhc2FfYXV0byB+IGxvZyhhdXRvX2FjY2lkKSArIHNleG8gKyBlZGFkICsgbG9nKGRlbnNpZGFkX3ApICsgZ3JhZG9fZWR1YywgDQogICAgICAgICAgICAgICAgICAgICAgICBkYXRhID0gbmwsIGxpc3R3ID0gcGVzb3MsIHplcm8ucG9saWN5ID0gVFJVRSkNCnN1bW1hcnkoc2VtX21vZGVsKQ0KYGBgDQoNCmBgYHtyfQ0Kc2RtX21vZGVsIDwtIGxhZ3NhcmxtKGxvZ190YXNhX2F1dG8gfiBsb2coYXV0b19hY2NpZCkgKyBzZXhvICsgZWRhZCArIGxvZyhkZW5zaWRhZF9wKSArIGdyYWRvX2VkdWMsIA0KICAgICAgICAgICAgICAgICAgICAgIGRhdGEgPSBubCwgbGlzdHcgPSBwZXNvcywgdHlwZSA9ICJtaXhlZCIsIHplcm8ucG9saWN5ID0gVFJVRSkNCnN1bW1hcnkoc2RtX21vZGVsKQ0KYGBgDQoNCmBgYHtyfQ0KQUlDKG9sc19tb2RlbCwgc2FyX21vZGVsLCBzZW1fbW9kZWwsIHNkbV9tb2RlbCkNCg0KIyBUYW1iacOpbiBwdWVkZXMgY29tcGFyYXIgbG9nTGlrIGRpcmVjdGFtZW50ZToNCmxvZ0xpayhvbHNfbW9kZWwpDQpsb2dMaWsoc2FyX21vZGVsKQ0KbG9nTGlrKHNlbV9tb2RlbCkNCmxvZ0xpayhzZG1fbW9kZWwpDQoNCmBgYA0KDQpgYGB7cn0NCnJlc2lkdW9zIDwtIHJlc2lkdWFscyhzYXJfbW9kZWwpICAjIGNhbWJpYSBhIHNlbV9tb2RlbCBvIHNkbV9tb2RlbCBzaSBlcyB0dSBtZWpvciBtb2RlbG8NCg0KbW9yYW4udGVzdChyZXNpZHVvcywgcGVzb3MsIHplcm8ucG9saWN5ID0gVFJVRSkNCmBgYA0KDQpgYGB7cn0NCiMgUHJlZGljY2lvbmVzDQpubCR5X2hhdCA8LSBmaXR0ZWQoc2FyX21vZGVsKSAgIyBjYW1iaWEgc2Vnw7puIHR1IG1vZGVsbw0KDQojIE1hcGENCmxpYnJhcnkodG1hcCkNCnRtYXBfbW9kZSgicGxvdCIpDQp0bV9zaGFwZShubCkgKw0KICB0bV9wb2x5Z29ucygieV9oYXQiLCB0aXRsZSA9ICJQcmVkaWNjacOzbjogbG9nKFRhc2EgQWNjaWRlbnRlcykiLCBwYWxldHRlID0gIk9yYW5nZXMiKSArDQogIHRtX2xheW91dChtYWluLnRpdGxlID0gIlZhbG9yZXMgUHJlZGljaG9zIGRlbCBNb2RlbG8gU0FSIikNCg0KYGBgDQoNCiMgNC4gRXN0aW1hY2nDs24gZGUgTW9kZWxvcyBkZSBQcmVkaWNjacOzbiBMb2NhbA0KDQpgYGB7cn0NCiMgRXh0cmFlciBjZW50cm9pZGVzIGRlIGNhZGEgbXVuaWNpcGlvIChyZXF1ZXJpZG8gcG9yIEdXUikNCmNvb3JkcyA8LSBzdF9jZW50cm9pZChubCRnZW9tZXRyeSkgfD4gc3RfY29vcmRpbmF0ZXMoKQ0KDQojIENvbnZlcnRpciBhIG9iamV0byBTcGF0aWFsDQpubF9zcCA8LSBhc19TcGF0aWFsKG5sKQ0KYGBgDQoNCmBgYHtyfQ0KIyBCYW5kd2lkdGggw7NwdGltbw0KYndfZ3dyIDwtIGd3ci5zZWwoDQogIGxvZ190YXNhX2F1dG8gfiBkZW5zaWRhZF9wICsgZ3JhZG9fZWR1YyArIGdpbmkgKyBlZGFkICsgcHJvcF9mZW0gKyBwcm9wX2FsaWVudG9fcG9zLA0KICBkYXRhID0gbmxfc3AsDQogIGNvb3JkcyA9IGNvb3JkcywNCiAgYWRhcHQgPSBUUlVFDQopDQoNCmBgYA0KDQpgYGB7cn0NCmd3cl9tb2RlbCA8LSBnd3IoDQogIGxvZ190YXNhX2F1dG8gfiBkZW5zaWRhZF9wICsgZ3JhZG9fZWR1YyArIGdpbmkgKyBlZGFkICsgcHJvcF9mZW0gKyBwcm9wX2FsaWVudG9fcG9zLA0KICBkYXRhID0gbmxfc3AsDQogIGNvb3JkcyA9IGNvb3JkcywNCiAgYWRhcHQgPSBid19nd3IsDQogIGhhdG1hdHJpeCA9IFRSVUUsDQogIHNlLmZpdCA9IFRSVUUNCikNCg0KYGBgDQoNCmBgYHtyfQ0KIyBSZXN1bHRhZG9zIHByZWRpY2hvcyB5IFIyDQpubCRnd3JfZml0dGVkIDwtIGd3cl9tb2RlbCRTREYkcHJlZA0KbmwkZ3dyX2xvY2FsUjIgPC0gZ3dyX21vZGVsJFNERiRsb2NhbFIyDQoNCmBgYA0KDQpgYGB7cn0NCnRtYXBfbW9kZSgicGxvdCIpDQp0bV9zaGFwZShubCkgKw0KICB0bV9wb2x5Z29ucygiZ3dyX2ZpdHRlZCIsIHRpdGxlID0gIlByZWRpY2Npw7NuIEdXUiAobG9nIFRhc2EgQWNjaWRlbnRlcykiLCBwYWxldHRlID0gIlJlZHMiKSArDQogIHRtX2xheW91dChtYWluLnRpdGxlID0gIlZhbG9yZXMgUHJlZGljaG9zIHBvciBHV1IiKQ0KDQpgYGANCg0KYGBge3J9DQp0bV9zaGFwZShubCkgKw0KICB0bV9wb2x5Z29ucygiZ3dyX2xvY2FsUjIiLCB0aXRsZSA9ICJSwrIgTG9jYWwgR1dSIiwgcGFsZXR0ZSA9ICJCbHVlcyIpICsNCiAgdG1fbGF5b3V0KG1haW4udGl0bGUgPSAiQ29lZmljaWVudGUgUsKyIExvY2FsIGRlbCBNb2RlbG8gR1dSIikNCg0KYGBgDQoNCiMgNS4gQ29uIGJhc2UgZW4gbG9zIHJlc3VsdGFkb3MgZW5jb250cmFkb3MgZW4gMSkg4oCTIDQpIHJlYWxpemFyIHVuYSBicmV2ZSBkZXNjcmlwY2nDs24gZGUgbG9zIHByaW5jaXBhbGVzIDYg4oCTIDggaGFsbGF6Z29zIGlkZW50aWZpY2Fkb3MuDQoxLiBDb25jZW50cmFjacOzbiB1cmJhbmEgZGUgYWNjaWRlbnRlcw0KTGEgWm9uYSBNZXRyb3BvbGl0YW5hIGRlIE1vbnRlcnJleSAoWk1NKSBhY2FwYXJhIGxhIG1heW9yIHBhcnRlIGRlIGxvcyBhY2NpZGVudGVzOiBzdSB0YXNhIG1lZGlhICg4IDU1MSBjaG9xdWVzLzEwIDAwMCBoYWIuKSB5IHN1IG1lZGlhbmEgKDMgODI1KSBkdXBsaWNhbiBjdWFscXVpZXIgb3RyYSByZWdpw7NuLCBsbyBxdWUgY29uZmlybWEgcXVlIGVsIHByb2JsZW1hIGVzIGVzZW5jaWFsbWVudGUgbWV0cm9wb2xpdGFuby4NCg0KMi4gRGVwZW5kZW5jaWEgZXNwYWNpYWwgZ2xvYmFsDQpFbCDDrW5kaWNlIGRlIE1vcmFuIEkgcGFyYSBsYSB0YXNhIGRlIGFjY2lkZW50ZXMgcmVzdWx0w7MgYWx0YW1lbnRlIHNpZ25pZmljYXRpdm8gKHAgPCAwLjAxKSwgbG8gcXVlIGNvbXBydWViYSBxdWUgbG9zIG11bmljaXBpb3MgdmVjaW5vcyB0aWVuZGVuIGEgZXhoaWJpciBwYXRyb25lcyBkZSBzaW5pZXN0cmFsaWRhZCBzaW1pbGFyZXMsIGludmFsaWRhbmRvIGVsIHN1cHVlc3RvIGRlIGluZGVwZW5kZW5jaWEgZ2VvZ3LDoWZpY2EgZW4gdW4gbW9kZWxvIHB1cmFtZW50ZSBsaW5lYWwuDQoNCjMuIENsdXN0ZXJzDQpFbCBhbsOhbGlzaXMgTElTQSBpZGVudGlmaWPDsyBjbMO6c3RlcmVzIEhpZ2gtSGlnaCBjb25jZW50cmFkb3MgZW4gbXVuaWNpcGlvcyBkZSBsYSBtYW5jaGEgdXJiYW5hIChwLiBlai4gTW9udGVycmV5LCBHdWFkYWx1cGUgeSBTYW4gTmljb2zDoXMpLCBzZcOxYWxhbmRvIHpvbmFzIGRvbmRlIGxhIGludGVydmVuY2nDs24g4oCUc2XDsWFsaXphY2nDs24sIHNlbWFmb3JpemFjacOzbiB5IGNvbnRyb2wgZGUgdmVsb2NpZGFk4oCUIGRlYmVyw61hIHNlciBwcmlvcml0YXJpYS4NCg0KNC4gRGVuc2lkYWQgcG9ibGFjaW9uYWwgY29tbyBmYWN0b3IgZGUgcmllc2dvDQpFbiB0b2RvcyBsb3MgbW9kZWxvcyAoTUNPIHkgZXNwYWNpYWxlcykgbGEgZGVuc2lkYWQgZGUgcG9ibGFjacOzbiBtb3N0csOzIHVuIGNvZWZpY2llbnRlIHBvc2l0aXZvIHkgZXN0YWTDrXN0aWNhbWVudGUgc2lnbmlmaWNhdGl2bywgZXZpZGVuY2lhbmRvIHF1ZSBhIG1heW9yIHBvYmxhY2nDs24gZW4gZWwgbXVuaWNpcGlvLCBjb3JyZXNwb25kZSBhIHVuYSBtYXlvciB0YXNhIGRlIGNob3F1ZXMuDQoNCjUuIEVkYWQgY29tbyBmYWN0b3IgZGUgY2hvcXVlcyANCkxBIGVkYWTCsiBlbiBsYSByZWdyZXNpw7NuIGluZGljYSBxdWUgZWwgcmllc2dvIGRlIGFjY2lkZW50ZSBhdW1lbnRhIGhhc3RhIGFwcm94aW1hZGFtZW50ZSBsb3MgMzUgYcOxb3MgeSBsdWVnbyBkaXNtaW51eWUsIHN1Z2lyaWVuZG8gdW4gcGVyZmlsIGRlIG3DoXhpbW8gcmllc2dvIGVuIGFkdWx0b3MgasOzdmVuZXMgeSBtZW5vcmVzIGVuIGNvbmR1Y3RvcmVzIGRlIG1heW9yIGVkYWQuDQoNCjYuIEJyZWNoYSBkZSBnw6luZXJvDQpMb3MgaG9tYnJlcyByZWdpc3RyYW4gdW5hIG1lZGlhbmEgZGUgdGFzYSBkZSBhY2NpZGVudGVzIGNhc2kgZWwgZG9ibGUgcXVlIGxhcyBtdWplcmVzLCByZWZsZWpvIGRlIG1heW9yIGV4cG9zaWNpw7NuIHZpYWwgeSBjb21wb3J0YW1pZW50b3MgZGUgcmllc2dvLiANCg0KNy4gTW9kZWxvIFNBUiDDs3B0aW1vDQpFbCBtb2RlbG8gYXV0b3JyZWdyZXNpdm8gZXNwYWNpYWwgKFNBUikgb2J0dXZvIGVsIEFJQyBtw6FzIGJham8geSBzdXMgcmVzaWR1b3Mgbm8gbW9zdHJhcm9uIGF1dG9jb3JyZWxhY2nDs24gKHAgPiAwLjEwKSwgbG8gcXVlIGxvIGNvbnZpZXJ0ZSBlbiBsYSBlc3BlY2lmaWNhY2nDs24gbcOhcyByb2J1c3RhIHBhcmEgZXhwbGljYXIgbGEgdmFyaWFjacOzbiBkZSBsYSB0YXNhIGRlIGNob3F1ZXMgZW4gTnVldm8gTGXDs24uDQoNCjguIEhldGVyb2dlbmVpZGFkIGxvY2FsIChHV1IpDQpFbCBtb2RlbG8gZGUgUmVncmVzacOzbiBHZW9ncsOhZmljYW1lbnRlIFBvbmRlcmFkYSBhcnJvamEgUsKyIGxvY2FsIHN1cGVyaW9yZXMgYSAwLjcwIGVuIGxhIFpNTSB5IHBvciBkZWJham8gZGUgMC4zMCBlbiDDoXJlYXMgcnVyYWxlcywgcmV2ZWxhbmRvIHF1ZSBsYSBmdWVyemEgZGUgbG9zIGRldGVybWluYW50ZXMgdmFyw61hIGVzcGFjaWFsbWVudGUgeSBxdWUgdW5hIHBvbMOtdGljYSDDum5pY2Egbm8gY3VicmUgbGFzIGRpZmVyZW50ZXMgcmVhbGlkYWRlcyBtdW5pY2lwYWxlcy4=