A Multilevel Analysis of the impact of Brexit Leave Vote proportion on Hate Crime in England

Study Preregistration form: https://rpubs.com/SMI200142951/1185902

Information about this replication project

Workspace setup

YAML settings

output:
  html_document:
   code_download: true
    toc: true
    toc_depth: 2
    toc_float:
     collapsed: false
     smooth_scroll: true

Global settings of R chunks

# Global options
opts_chunk$set(echo=TRUE,
                 cache=TRUE,
               comment=NA,
               message=FALSE,
               warning=FALSE)

Libraries

# General
library("rmarkdown")
library("knitr")
library("rstudioapi")
library("stargazer")
library("effects")
library("sf") 
library("sp") 
library("spdep") 
library("randomForest") 
library("modelsummary") 
library("MASS") 
library("lmtest") 
library("sandwich") 
library("pscl") 
library("ggplot2")
library("dplyr")
library("plyr")
library("sjPlot")
library("readr")
library("broom")
library("broom.mixed")
library("ggstats")

# Used for mapping
library("maps")
library("mapdata")
library("ggmap")
library("broom")

# Used to plot correlations
library("correlation")
library("lme4")
library("performance")

Versions of used packages

$rmarkdown
[1] '2.26'

$knitr
[1] '1.46'

$rstudioapi
[1] '0.16.0'

$stargazer
[1] '5.2.3'

$effects
[1] '4.2.2'

$sf
[1] '1.0.16'

$sp
[1] '2.1.4'

$spdep
[1] '1.3.3'

$randomForest
[1] '4.7.1.1'

$modelsummary
[1] '2.1.0'

$MASS
[1] '7.3.60'

$lmtest
[1] '0.9.40'

$sandwich
[1] '3.1.0'

$pscl
[1] '1.5.9'

$ggplot2
[1] '3.5.1'

$dplyr
[1] '1.1.4'

$sjPlot
[1] '2.8.16'

$readr
[1] '2.1.5'

$maps
[1] '3.4.2'

$mapdata
[1] '2.3.1'

$ggmap
[1] '4.0.0'

$broom
[1] '1.0.6'

$plyr
[1] '1.8.9'

$correlation
[1] '0.8.4'

$lme4
[1] '1.1.35.1'

$performance
[1] '0.11.0'

My enviroment

[1] "R version 4.3.1 (2023-06-16 ucrt)"

1. Introduction

Belgioioso et al.’s paper ‘Local deprivation predicts right-wing hate crime in England’ (Belgioioso, et al., 2023) studied the effect local deprivation had on hate crime rates across England, finding that areas with higher levels of deprivation, particularly income deprivation, were positively correlated with a higher rate of hate crime events. The paper successfully addresses a gap in the literature, utilising neighbourhood-level hate crime and deprivation data to explore local drivers of hate crime. Their argument is that previous studies have failed to capture the impact of important factors such as feelings of community abandonment and the perception that political institutions doing nothing for individuals within a community setting, which in turn leads individuals into far-right thinking.

However, this research does not consider the importance of political events, and the political climate, on hate crime. Research performed by King & Sutton explores the relationship between single, discrete events and the way in which they affect hate crimes temporally. They found that the occurrence of very public and contentious political and social events in the US led to significant increase in hate crimes in their immediate aftermath (King D. & Sutton, 2013). An incredibly important political event occurred in the UK during the same timeframe in which the data used by the researchers, the 2016 EU Membership Referendum. Known as the ‘Brexit’ referendum this event was huge, media reports and political debates on the subject were commonplace in the months leading up to the referendum; research by Devine associated the subsequent departure of the UK from the EU with ‘an increase in hate crimes of 19-23%’ (Devine, 2018, p. 1). This hypothesis is further corroborated by Piatkowska & Stults who found that the very unique nature of Brexit in the UK political sphere led to a uniquely large increase in hate crime rates when compared to other large events, such as terrorist attacks (Piatkowska & Stults, 2022). Research exploring the reasons why people voted to leave on the local level found a strong ‘leave’ sentiment manifested in deprived individuals living in deprived areas as they felt their jobs were threatened by low-skilled migrant labour from the EU. This, coupled with strong anti-immigrant sentiments by pro-leave parties such as UKIP, culminated in communities fearing immigration (Clarke, et al., 2017). Studies performed in the Netherlands have found this fear of immigration and out-groups caused by these kinds of events led to some individuals acting out on their frustrations and committing hate crimes (Jacobs & van Spanje, 2021).

This study is going to further test Belgioioso et al.’s hypothesis by looking at whether the proportion of leave votes in an area had an impact on the hate crime rates in this area, and whether this effect might mitigate the impact of deprivation. This form of replication largely utilises similar methods of analysis to the original researchers, but with additional data to test whether my alternative hypothesis is true, making this a repeatability test (Freese & Peterson, 2017). This study will help address a gap in research in that most studies exploring the relationship between Brexit and hate crime do so temporally, not spatially.

  • Hypothesis 1: The proportion of individuals in an area which voted to Leave the European Union will have a significant and substantial impact on the hate crime rate in that area

2. Data and methods

2.1. Data

The dataset used in this paper utilises the same data used in the original paper and can be downloaded from the Harvard Dataverse repository. It contains 32201 observations of 80 variables.

Please see Data References to access data

Deprivation_2023_BDG_Replication.RData (Dworschak, 2023)

The dependent variable analysed is the logged number of hate crime per 100k. This is a numeric variable ranging between 0 (no recorded hate crime), and 10. Belgioioso et al. obtained this variable by dividing the cumulative number of hate crimes by LSOA population size (per 100k) (Belgioioso, et al., 2023, p. 11). All hate crime data was ‘recorded by the UK Police for 2015–2021 and provided by the Crime Analysis Unit of the Home Office following a Freedom of Information request by the authors (FOI 69240).’ (Belgioioso, et al., 2023, p. 4)

This also includes the following data which is included in the original dataset:

Deprivation data – Data from the English Indices of Deprivation 2015

This paper utilised 3 of these variables: income deprivation (0-0.65), education deprivation (0-100), and living environment deprivation (0-100). All variables were measured with 0 being lowest level of deprivation.

Demographic data – From the 2011 UK Census Data (Office for National Statistics, 2012) This paper utilises the following variables: • Total population size logged • Average age • Long term unemployed percentage • Percentage of Christians • Percentage of urban population • Percentage of people of Arab ethnicity • Percentage of people of BAME ethnicity

The paper will then use additional data from the EU Referendum results (The Electoral Commission, 2021).

The variable used is the percentage of votes to leave the EU, measured from 0% to 100%. This variable is measured at the Local Authority District Level and contains 382 observations of 21 variables.

In order to present data spatially this paper utilised a shapefile of the UK with all LAD boundaries. This dataset was imported from the Open Geography portal provided by the Office of National Statistics, under the following copyright. Source: Office for National Statistics licensed under the Open Government Licence v.3.0 Contains OS data © Crown copyright and database right 2001

# Original data and assisting script download
load(file = "Data/Deprivation_2023_BDG_Replication.RData")

source("Original Scripts/helpers.R")
# Creating a new dataset which omits data from Scotland, Wales and Gibraltar. This data is not needed as the original dataset contains no data on these places. 

eu_referendum_data <- read_csv("Data/EU-referendum-result-data.csv")


eu_referendum_data_1 <- subset(eu_referendum_data, !(id %in% c(381, 153, 155, 157, 159, 160, 179, 162, 163, 165, 166, 167, 168, 169, 171, 172, 152, 174, 175, 176, 177, 148, 149, 151, 161, 173, 154, 178, 150, 156, 170, 158, 164, 382, 126, 127, 128, 129, 130, 131, 133, 134, 135, 136, 137, 138, 139, 147, 140, 142, 143,   144, 145,   146, 132,   141)))
# Merging the original dataset with the EU referendum dataset

merged_data_eu <- merge(df5, eu_referendum_data, by = "lad")
# Downloading the shapefile and merging with referndum data
lad_shp <- st_read("Data/Shapefile/LAD_DEC_2016_GB_BGC_V2.shp")
Reading layer `LAD_DEC_2016_GB_BGC_V2' from data source 
  `C:\Users\Student\Dropbox\PC\Documents\University Work\SMI205 Assessment 2\R Workfile\SMI205 Assessment 2\Data\Shapefile\LAD_DEC_2016_GB_BGC_V2.shp' 
  using driver `ESRI Shapefile'
Simple feature collection with 380 features and 8 fields
Geometry type: MULTIPOLYGON
Dimension:     XY
Bounding box:  xmin: 5512.999 ymin: 5342.7 xmax: 655644.8 ymax: 1220302
Projected CRS: OSGB36 / British National Grid
colnames(lad_shp)[colnames(lad_shp) == 'LAD16CD'] <- 'lad'

eu_shapefile_data <- merge(lad_shp, eu_referendum_data, by = "lad")

Maps

Brexit Vote Proportion Map

ggplot(hcrime_shapefile_data) +
  geom_sf(aes(fill = Pct_Leave)) +
  scale_fill_viridis_c() +
  labs(title = "Figure 1: Percentage of Leave Votes in the 2016 EU Referendum in the UK",
       fill = "Percentage of Leave Votes",
       caption = " Spatial data source: Office for National Statistics licensed under the Open 
       Government Licence v.3.0. Contains OS data © Crown copyright and database 
       right 2001")

Hate Crime Rate Map (logged)

ggplot(hcrime_shapefile_data) +
  geom_sf(aes(fill = hcrimes.cleaned.p100k.ln)) +
  scale_fill_viridis_c() +
  labs(title = "Figure 2: Logged number of Hate Crimes per 100k ",
       fill = "Logged number of Hate Crimes",
       caption = " Spatial data source: Office for National Statistics licensed under the Open 
       Government Licence v.3.0. Contains OS data © Crown copyright and database 
       right 2001")

Summary Statistics

Histogram of Leave Proportion by Region

ggplot(merged_data_eu) +
  aes(x = Pct_Leave) +
  geom_histogram(binwidth = 2, colour = "black", fill = "white") +
  facet_wrap(Region ~ .) +
  geom_vline(data = hist_facet_mean_line, aes(xintercept = grp.mean), color = "red",
             linetype = "dashed") +
  labs(title = "Figure 3: Histogram of Leave Percent Votes by Region",
       x = "Percent Leave Vote",
       y = "Number of LSOA's") 

Boxplot of Leave Proportion by Region

ggplot(merged_data_eu) +
  aes(x = Pct_Leave) +
  geom_boxplot() +
  facet_grid(Region ~ .) +
  theme(strip.text.y.right = element_text(angle = 0)) +
  labs(title = "Figure 4: Boxplot of Leave Percent Votes by Region",
       x = "Percent Leave Vote") 

Boxplot of Hate Crime Rate by Region

ggplot(merged_data_eu) +
  aes(hcrimes.cleaned.p100k.ln) +
  geom_boxplot() +
  facet_grid(Region ~ .) +
  theme(strip.text.y.right = element_text(angle = 0)) +
  labs(title = "Figure 5: Boxplot of Logged Hate Crimes by Region",
       x = "Logged Hate Crime per 100k") 

2.2. Methods

In the original paper a linear regression test was performed to create 7 models with hate crime logged per 100k as the dependent variable was added. This paper will also follow this method, with the addition of an 8th model in both the reproduction of the original model and in the models with the addition of Brexit leave vote data. Predictor variables are modeled as follows:

  • 1 – Demographics
  • 2 – Income deprivation score
  • 3 – Living environment deprivation score
  • 4 – Education deprivation score
  • 5 – Income and neighbouring LSOA deprivation score
  • 6 – Living environment and neighbouring LSOA deprivation score
  • 7 – Education and neighbouring LSOA deprivation score
  • 8 - All predictor variables

This paper will utilise a random intercept multilevel model. This method will be best as the data is captured at 2 levels. Local Level Super Output Area (LSOA) for hate crime statistics, IoD and demographic data, and at Local Authority District (LAD) level for Brexit referendum results. Comparing the reproduced model on a single and multilevel will ensure any changes caused by this change will be noted.

The LSOA and LAD data are not independent of one another, as LSOA’s and nested within LAD’s. A multi-level model allows for regression analysis to be performed on both the individual (LSOA) and group (LAD) level, taking into account that the Brexit referendum data will not change between LSOA’s in a single LAD, but does change between LAD’s (Gorard, 2003). Running a null model containing just hate crime proportion calucates an Intra-Class Correlation of 0.36, indicating 36% of variance in hate crime proportion occurs within LSOA’s in an LAD, therefore 64% occurs between LAD. Such a high between-class correlation indicates that using a single-level model would not account for this significant amount of variance.

hcrime_mlmodel_null <- lmer(hcrimes.cleaned.p100k.ln ~  (1 | id),
                                data = merged_data_eu)


tab_model(hcrime_mlmodel_null, dv.labels = 'Logged Hate Crime per 100k', title = 'Multilevel Model of Logged Hate Crime')
Multilevel Model of Logged Hate Crime
  Logged Hate Crime per 100k
Predictors Estimates CI p
(Intercept) 3.34 3.21 – 3.47 <0.001
Random Effects
σ2 2.48
τ00 id 1.36
ICC 0.36
N id 316
Observations 32201
Marginal R2 / Conditional R2 0.000 / 0.355

A coefficient analysis of the first multilevel model with just leave vote percent as a predictor demonstrates why a random intercept but not a random slopes model is needed here. The intercept of each LAD is different, but the slopes are all the same at -0.03407529. This indicates that the hate crime rate can be different for every LAD, but the effect the Brexit leave proportion has on the hate crime in each LAD is the same.

head(coef_mlm, 5)
  (Intercept)   Pct_Leave
1    6.212675 -0.03407529
2    7.017882 -0.03407529
3    6.070095 -0.03407529
4    6.148043 -0.03407529
5    6.180101 -0.03407529

Correlation coefficient analysis will test whether the percent leave vote variable is too closely correlated with other predictor variables to model successfully. Although there is some correlation, which is to be anticipated, there is not enough to indicate any multicollinearity.

kable(cor_coef_table_brexit_deprivation, col.names = c('Leave Vote Percent', 'Income Deprivation', 'Education Deprivation', 'Living Envrionment Deprivation'))
Leave Vote Percent Income Deprivation Education Deprivation Living Envrionment Deprivation
Leave Vote Percent 1.0000000 0.0232846 0.2624921 -0.2648868
Income Deprivation 0.0232846 1.0000000 0.8345010 0.2552408
Education Deprivation 0.2624921 0.8345010 1.0000000 0.1047790
Living Envrionment Deprivation -0.2648868 0.2552408 0.1047790 1.0000000
kable(cor_coef_table_brexit_demographics, col.names = c('Leave Vote Percent', 'Logged Population', 'Mean Age', 'Longterm Unemployed', 'Christian', 'Urban', 'Ethic Arab', 'Ethnic BAME'))
Leave Vote Percent Logged Population Mean Age Longterm Unemployed Christian Urban Ethic Arab Ethnic BAME
Leave Vote Percent 1.0000000 -0.0986961 0.2787429 0.0304339 0.3795592 -0.1148694 -0.3183698 -0.3957941
Logged Population -0.0986961 1.0000000 -0.2732264 0.0416853 -0.2424984 -0.0062742 0.1153764 0.2404694
Mean Age 0.2787429 -0.2732264 1.0000000 -0.4625923 0.6426317 -0.3383939 -0.2948319 -0.5669702
Longterm Unemployed 0.0304339 0.0416853 -0.4625923 1.0000000 -0.3217492 0.2748045 0.1367728 0.3472014
Christian 0.3795592 -0.2424984 0.6426317 -0.3217492 1.0000000 -0.2805148 -0.3899833 -0.7586359
Urban -0.1148694 -0.0062742 -0.3383939 0.2748045 -0.2805148 1.0000000 0.1471431 0.2758085
Ethic Arab -0.3183698 0.1153764 -0.2948319 0.1367728 -0.3899833 0.1471431 1.0000000 0.4235247
Ethnic BAME -0.3957941 0.2404694 -0.5669702 0.3472014 -0.7586359 0.2758085 0.4235247 1.0000000

3. Results

hcrime_brexit_mlmodel_table
Linear Regression of Leave Vote Percent (LAD) on Logged Hate Crime (LSOA)
  Logged Hate Crime per 100k
Predictors Estimates CI p
Intercept 5.20 4.51 – 5.88 <0.001
Leave Vote Percent -0.03 -0.05 – -0.02 <0.001
Random Effects
σ2 2.48
τ00 id 1.25
ICC 0.34
N id 316
Observations 32201
Marginal R2 / Conditional R2 0.033 / 0.358

Testing the effect the Brexit leave proportion has on hate crime with no other predictor variables, it appears that there is a slight inverse relationship to what was expected. A very slight negative correlation suggests areas with a lower Brexit leave vote proportion had less hate crimes. Although this effect is significant the fixed effects calculation of 0.033 explains only 3.3% of variance, whereas the inclusion of random effects explains 35.8%, suggesting other factors at LAD level play a significant role.

3.1 - Comparing single and multi level original model

Reproduced Model - Deprivation and Demographics on Hate Crime

full_reproduced_regression_table
Table 2: Linear Regression of Logged Hate Crime 2015-2018
  1 2 3 4 5 6 7 8
Predictors Estimates p Estimates p Estimates p Estimates p Estimates p Estimates p Estimates p Estimates p
Intercept 0.258 0.530 2.506 <0.001 2.934 <0.001 2.942 <0.001 -0.616 0.129 -0.657 0.105 -0.333 0.418 -1.448 <0.001
Population Size (log) 0.689 <0.001 0.750 <0.001 0.649 <0.001 0.723 <0.001 0.715 <0.001
Mean Age -0.013 <0.001 -0.009 <0.001 -0.010 <0.001 -0.007 0.003 -0.008 0.001
Unemployment Percentage 0.454 <0.001 0.098 <0.001 0.425 <0.001 0.315 <0.001 0.075 <0.001
Christian Religion Percentage -0.031 <0.001 -0.030 <0.001 -0.020 <0.001 -0.032 <0.001 -0.020 <0.001
Urban 0.521 <0.001 0.491 <0.001 0.673 <0.001 0.478 <0.001 0.649 <0.001
Arab Ethnicity Percentage 0.079 <0.001 0.067 <0.001 0.054 <0.001 0.087 <0.001 0.046 <0.001
BAME Percentage -0.005 <0.001 -0.009 <0.001 -0.003 <0.001 -0.006 <0.001 -0.006 <0.001
Income Deprivation 7.226 <0.001 4.048 <0.001 4.707 <0.001
Living Envrionment Deprivation 0.029 <0.001 0.020 <0.001 0.021 <0.001
Education Deprivation 0.028 <0.001 0.008 <0.001 -0.002 0.056
Neighbour Income Deprivation 1.704 <0.001 -0.012 0.969
Neighbour Living Envrionment Deprivation -0.002 0.118 -0.004 0.001
Neighbour Education Deprivation 0.008 <0.001 0.005 0.002
Observations 32201 32201 32201 32201 32201 32201 32201 32201
R2 / R2 adjusted 0.424 / 0.423 0.151 / 0.151 0.057 / 0.057 0.075 / 0.075 0.439 / 0.438 0.440 / 0.439 0.430 / 0.429 0.454 / 0.453

Multi-Level Reproduced Model without Leave Percentage

hcrime_demo_regression_tab_model
Table 2: Linear Regression Multi-Level Model of Deprivation on Hate Crime
  1 2 3 4 5 6 7 8
Predictors Estimates p Estimates p Estimates p Estimates p Estimates p Estimates p Estimates p Estimates p
Intercept -0.243 0.567 2.451 <0.001 2.734 <0.001 2.669 <0.001 -1.171 0.005 -1.230 0.003 -1.063 0.013 -2.174 <0.001
Population Size (log) 0.740 <0.001 0.808 <0.001 0.698 <0.001 0.789 <0.001 0.774 <0.001
Mean Age -0.004 0.106 0.000 0.880 -0.002 0.335 0.003 0.163 0.001 0.534
Unemployment Percentage 0.451 <0.001 0.095 <0.001 0.430 <0.001 0.303 <0.001 0.067 <0.001
Christian Religion Percentage -0.035 <0.001 -0.035 <0.001 -0.023 <0.001 -0.035 <0.001 -0.023 <0.001
Urban 0.404 <0.001 0.371 <0.001 0.575 <0.001 0.362 <0.001 0.551 <0.001
Arab Ethnicity Percentage 0.051 <0.001 0.040 <0.001 0.040 <0.001 0.059 <0.001 0.031 0.002
BAME Percentage -0.007 <0.001 -0.011 <0.001 -0.005 <0.001 -0.007 <0.001 -0.008 <0.001
Income Deprivation 6.799 <0.001 4.142 <0.001 4.802 <0.001
Living Envrionment Deprivation 0.030 <0.001 0.020 <0.001 0.020 <0.001
Education Deprivation 0.033 <0.001 0.009 <0.001 -0.002 0.169
Neighbour Income Deprivation 1.788 <0.001 0.408 0.235
Neighbour Living Envrionment Deprivation 0.001 0.528 -0.000 0.798
Neighbour Education Deprivation 0.009 <0.001 0.004 0.038
Random Effects
σ2 2.05 2.10 2.33 2.18 1.99 2.00 2.02 1.94
τ00 0.10 id 1.23 id 1.39 id 1.38 id 0.10 id 0.09 id 0.10 id 0.10 id
ICC 0.05 0.37 0.37 0.39 0.05 0.04 0.05 0.05
N 316 id 316 id 316 id 316 id 316 id 316 id 316 id 316 id
Observations 32201 32201 32201 32201 32201 32201 32201 32201
Marginal R2 / Conditional R2 0.413 / 0.439 0.129 / 0.450 0.059 / 0.409 0.093 / 0.444 0.430 / 0.457 0.434 / 0.458 0.419 / 0.447 0.449 / 0.476

Comparison of Model Coefficients

ggplot(hcrime_demo_models_coef_np, 
       aes(x = term, y = estimate, color = model)) +
  geom_point(position = position_dodge(width = 0.5)) +
  geom_errorbar(aes(ymin = conf.low, ymax = conf.high), width = 0.2, position = position_dodge(width = 0.5)) +
  coord_flip() +
  labs(title = "Comparison of Single and Multilevel Model Coefficients",
       x = "Predictors",
       y = "Estimate") +
  theme_minimal()

Comparing these models shows that most variable predictions did not change much between the single and multilevel models, indicating the patterns present at LSOA level remain quite consistent at the LAD level. The effect of age becomes insignificant in the multilevel model, suggesting age-related variations in hate crime are more homogeneous within LADs but this effect is less clear when between LAD variation is accounted for. The impact of deprivation variables changes slightly between models, showing that while there significant variations occurring at LAD level, these are quite small.

The Intra-Class Correlation between 0.37-39 indicates a significant portion of variability in hate crime rates can be attributed to differences between LADs, but this effect only occurs when including deprivation variables, indicating that while deprivation varied considerably between LADs, demographic variables did not.

The Intercept tends more to be negative in the multilevel model due to hierarchical structuring in the data; accounting for variability at the LAD level adjusts the baseline hate crime level below what was predicted in the single level model.
However the single level model has a highest R² of 0.454, whereas including random effects in the multilevel model provides a highest conditional R² pf 0.476, indicating that this model does better fit the data.

3.2 Comparing Mutlilevel models with and without Leave Percentage

Multilevel model without Leave Percentage

hcrime_demo_regression_tab_model
Table 2: Linear Regression Multi-Level Model of Deprivation on Hate Crime
  1 2 3 4 5 6 7 8
Predictors Estimates p Estimates p Estimates p Estimates p Estimates p Estimates p Estimates p Estimates p
Intercept -0.243 0.567 2.451 <0.001 2.734 <0.001 2.669 <0.001 -1.171 0.005 -1.230 0.003 -1.063 0.013 -2.174 <0.001
Population Size (log) 0.740 <0.001 0.808 <0.001 0.698 <0.001 0.789 <0.001 0.774 <0.001
Mean Age -0.004 0.106 0.000 0.880 -0.002 0.335 0.003 0.163 0.001 0.534
Unemployment Percentage 0.451 <0.001 0.095 <0.001 0.430 <0.001 0.303 <0.001 0.067 <0.001
Christian Religion Percentage -0.035 <0.001 -0.035 <0.001 -0.023 <0.001 -0.035 <0.001 -0.023 <0.001
Urban 0.404 <0.001 0.371 <0.001 0.575 <0.001 0.362 <0.001 0.551 <0.001
Arab Ethnicity Percentage 0.051 <0.001 0.040 <0.001 0.040 <0.001 0.059 <0.001 0.031 0.002
BAME Percentage -0.007 <0.001 -0.011 <0.001 -0.005 <0.001 -0.007 <0.001 -0.008 <0.001
Income Deprivation 6.799 <0.001 4.142 <0.001 4.802 <0.001
Living Envrionment Deprivation 0.030 <0.001 0.020 <0.001 0.020 <0.001
Education Deprivation 0.033 <0.001 0.009 <0.001 -0.002 0.169
Neighbour Income Deprivation 1.788 <0.001 0.408 0.235
Neighbour Living Envrionment Deprivation 0.001 0.528 -0.000 0.798
Neighbour Education Deprivation 0.009 <0.001 0.004 0.038
Random Effects
σ2 2.05 2.10 2.33 2.18 1.99 2.00 2.02 1.94
τ00 0.10 id 1.23 id 1.39 id 1.38 id 0.10 id 0.09 id 0.10 id 0.10 id
ICC 0.05 0.37 0.37 0.39 0.05 0.04 0.05 0.05
N 316 id 316 id 316 id 316 id 316 id 316 id 316 id 316 id
Observations 32201 32201 32201 32201 32201 32201 32201 32201
Marginal R2 / Conditional R2 0.413 / 0.439 0.129 / 0.450 0.059 / 0.409 0.093 / 0.444 0.430 / 0.457 0.434 / 0.458 0.419 / 0.447 0.449 / 0.476

Multilevel Model with Leave Percentage

full_regression_tab_model
Table 3: Linear Regression Model of Leave Vote Percentage and Deprivation on Hate Crime
  1 2 3 4 5 6 7 8
Predictors Estimates p Estimates p Estimates p Estimates p Estimates p Estimates p Estimates p Estimates p
Intercept -0.197 0.657 4.591 <0.001 4.071 <0.001 5.465 <0.001 -1.004 0.023 -1.324 0.003 -0.691 0.120 -2.132 <0.001
Leave Vote Percent -0.001 0.716 -0.039 <0.001 -0.025 <0.001 -0.051 <0.001 -0.004 0.195 0.002 0.455 -0.008 0.003 -0.001 0.739
Population Size (log) 0.740 <0.001 0.808 <0.001 0.698 <0.001 0.790 <0.001 0.774 <0.001
Mean Age -0.004 0.107 0.000 0.873 -0.002 0.334 0.004 0.149 0.002 0.526
Unemployment Percentage 0.451 <0.001 0.096 <0.001 0.430 <0.001 0.302 <0.001 0.067 <0.001
Christian Religion Percentage -0.035 <0.001 -0.034 <0.001 -0.023 <0.001 -0.034 <0.001 -0.023 <0.001
Urban 0.405 <0.001 0.372 <0.001 0.575 <0.001 0.364 <0.001 0.551 <0.001
Arab Ethnicity Percentage 0.051 <0.001 0.040 <0.001 0.041 <0.001 0.058 <0.001 0.031 0.002
BAME Percentage -0.007 <0.001 -0.011 <0.001 -0.005 <0.001 -0.007 <0.001 -0.008 <0.001
Income Deprivation 6.807 <0.001 4.143 <0.001 4.800 <0.001
Living Envrionment Deprivation 0.030 <0.001 0.020 <0.001 0.020 <0.001
Education Deprivation 0.033 <0.001 0.009 <0.001 -0.002 0.172
Neighbour Income Deprivation 1.797 <0.001 0.398 0.248
Neighbour Living Envrionment Deprivation 0.001 0.498 -0.000 0.787
Neighbour Education Deprivation 0.009 <0.001 0.004 0.035
Random Effects
σ2 2.05 2.10 2.33 2.18 1.99 2.00 2.02 1.94
τ00 0.10 id 1.08 id 1.33 id 1.11 id 0.10 id 0.09 id 0.10 id 0.10 id
ICC 0.05 0.34 0.36 0.34 0.05 0.04 0.05 0.05
N 316 id 316 id 316 id 316 id 316 id 316 id 316 id 316 id
Observations 32201 32201 32201 32201 32201 32201 32201 32201
Marginal R2 / Conditional R2 0.413 / 0.439 0.170 / 0.451 0.090 / 0.420 0.129 / 0.423 0.430 / 0.457 0.433 / 0.458 0.421 / 0.447 0.449 / 0.476

Comparison of Model Coefficients

ggplot(hcrime_demo_brexit_models_coef_np, 
       aes(x = term, y = estimate, color = model)) +
  geom_point(position = position_dodge(width = 0.5)) +
  geom_errorbar(aes(ymin = conf.low, ymax = conf.high), width = 0.2, position = position_dodge(width = 0.5)) +
  coord_flip() +
  labs(title = "Comparison of With and Without Brexit Coefficients",
       x = "Predictors",
       y = "Estimate") +
  theme_minimal()

In the deprivation models the proportion of Brexit leave voters has had a slight negative effect, suggesting areas with a higher leave vote proportion may experience lower hate crime rates, although this effect is quite marginal. However, this effect becomes insignificant once demographic variables are included. Although these variables were not too highly correlated as tested in the variable coefficient plots, this still suggests most of the variance in hate crimes in this model is due to demographic variables.

All other predictor variables estimates remain consistent, indicating that none of these variables were significantly influenced by the addition of voting data.

There is a slight decrease in the random effects and ICC in the leave vote model, suggesting leave vote proportion explains some of the LAD variance in hate crimes, but this effect is minimal.

The addition of the leave vote variable does slightly improve the marginal R² in some models, indicating a slightly better fit, but the conditional R² is stable, suggesting overall variance explained by fixed and random effects does not change significantly.

This rejects my hypothesis, the addition of Leave Vote Percentage does not have a significant relationship with the rate of hate crime once all predictor variables are accounted for, and neither does it have any mediating effect on these predictor variables.

3.3 Mixed Effects Models

Hate Crime and Leave Vote Model

hcrime_brexit_mlmodel_me_plot

All Predictors Model

hcrime_all_pred_me_plot

The mixed effects models indicate the importance of the inclusion of demographic and deprivation data in the final model. The random effects are substantially reduced accounting for these variables, and these effects also cluster more tightly around 0, which shows the all predictors model better accounts for variability in hate crime rates.

4. Conclusions

The findings in this paper corroborate Belgioioso et al.’s findings that deprivation factors, particularly income deprivation, have a robust association with hate crime rates. The inclusion of demographic variables make clearer the factors responsible for variations in hate crime rates. Although the initial model containing just hate crime and Brexit data does indicate a significant effect, this is mitigated with the inclusion of demographic data, indicating the same demographic variations leading to variations in hate crime rates on the LSOA level are having a similar effect on the LAD level.

A possible reason for the inverse relationship found in the initial model may be the number of LSOA’s which recorded zero hate crimes. Belgioioso et al. discuss this in their Supplementary Appendix, they run the same model but exclude LSOA’s containing no hate crime, positing this may be due to some areas failing to accurately report their hate crime statistics, however when running this model they find it does not change the analyses (Belgioioso, et al., 2023, p. 6). However, this effect may become more apparent with the inclusion of leave vote data, as LSOAs with a high Brexit leave vote percentage but zero recorded hate crimes will potentially skew the model and produce the inverse relationship as was seen in my model. Another analysis of this data excluding LSOA’s with zero hate crimes would reveal if this had an impact.

The lack of a substantial effect of leave vote on hate crime suggests Jacobs & van Spanje’s conclusions from their study in the Netherlands may not hold true here, and factors such as fear of immigration in local communities may not have been a driving factor of whether people actually commit hate crimes, further information on individual’s opinions on immigration may help explain whether this is the case, or if fear of immigration was substaintial in communities which voted for Brexit.

Academic References

Freese, J., & Peterson, D. (2017). Replication in social science. Annual Review of Sociology, 43, 147-165, doi: 10.1146.

Belgioioso, M., Dworschak, C. & GleditschI, K. S., 2023. Local deprivation predicts right-wing hate crime: S1 Supplementary Appendix. PLOS ONE, 6 September.18(9).

Belgioioso, M., Dworschak, C. & Gleditsch, K. S., 2023. Local deprivation predicts right-wing hate crime in England. Plos One, 18(9).

Clarke, H. D., Goodwin, M. & Whiteley, P., 2017. Why Britain Voted for Brexit: An Individual-Level Analysis of the 2016 Referendum Vote. Parliamentary Affairs, 70(3), p. 439–464.

Devine, D., 2018. The UK Referendum on Membership of the European Union as a Trigger Event for Hate Crimes, Southhampton: SSRN.

Freese, J. & Peterson, D., 2017. Replication in Social Science. Annual Review of Sociology, Volume 43, pp. 147-165.

Gorard, S., 2003. What is Multi–level Modelling For?. British Journal of Educational Studies, 51(1), pp. 46-63.

Jacobs, L. & van Spanje, J., 2021. A Time-Series Analysis of Contextual-Level Effects on Hate Crime in The Netherlands. Social Forces, 100(1), p. 169–193.

King D., R. & Sutton, G. M., 2013. High Times for Hate Crimes: Explaining the Temporal Clustering of Hate-Motivated Offending. Criminology, 51(4), pp. 871-894.

Piatkowska, S. J. & Stults, B. J., 2022. Brexit, Terrorist Attacks, and Hate Crime: A Longitudinal Analysis. Social Problems, 69(4), p. 968–996.

Data References

Dworschak, C., 2023. Replication Data for: Local deprivation predicts right-wing hate crime in England, s.l.: Harvard Dataverse. https://dataverse.harvard.edu/dataset.xhtml?persistentId=doi:10.7910/DVN/GSRPQY https://doi.org/10.7910/DVN/GSRPQY

The Electoral Commission, 2021. EU Referendum Results, London: Greater London Authority. Accessible here as of 16/05/2024: https://www.data.gov.uk/dataset/be2f2aec-11d8-4bfe-9800-649e5b8ec044/eu-referendum-results

LAD Shapefile by the Office of National Statistics Open Geography Portal Data is available from the following link as of 30/05/2024: https://geoportal.statistics.gov.uk/datasets/ons::local-authority-districts-december-2023-boundaries-uk-buc-2/about

Appendix

Appendix 1. My enviroment (full information)

# Detailed information about my environment
sessionInfo()
R version 4.3.1 (2023-06-16 ucrt)
Platform: x86_64-w64-mingw32/x64 (64-bit)
Running under: Windows 10 x64 (build 19045)

Matrix products: default


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

time zone: Europe/London
tzcode source: internal

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

other attached packages:
 [1] performance_0.11.0   lme4_1.1-35.1        Matrix_1.6-3        
 [4] correlation_0.8.4    plyr_1.8.9           broom_1.0.6         
 [7] ggmap_4.0.0          mapdata_2.3.1        maps_3.4.2          
[10] readr_2.1.5          sjPlot_2.8.16        dplyr_1.1.4         
[13] ggplot2_3.5.1        pscl_1.5.9           sandwich_3.1-0      
[16] lmtest_0.9-40        zoo_1.8-12           MASS_7.3-60         
[19] modelsummary_2.1.0   randomForest_4.7-1.1 spdep_1.3-3         
[22] spData_2.3.0         sp_2.1-4             sf_1.0-16           
[25] effects_4.2-2        carData_3.0-5        stargazer_5.2.3     
[28] rstudioapi_0.16.0    knitr_1.46           rmarkdown_2.26      

loaded via a namespace (and not attached):
 [1] DBI_1.1.3          bitops_1.0-7       deldir_2.0-4       s2_1.1.6          
 [5] rlang_1.1.1        magrittr_2.0.3     e1071_1.7-14       compiler_4.3.1    
 [9] png_0.1-8          vctrs_0.6.5        stringr_1.5.0      pkgconfig_2.0.3   
[13] wk_0.9.1           fastmap_1.1.1      backports_1.4.1    labeling_0.4.3    
[17] utf8_1.2.3         tzdb_0.4.0         nloptr_2.0.3       purrr_1.0.2       
[21] xfun_0.43          cachem_1.0.8       jsonlite_1.8.7     highr_0.10        
[25] sjmisc_2.8.9       ggeffects_1.3.1    jpeg_0.1-10        R6_2.5.1          
[29] stringi_1.7.12     bslib_0.5.1        tables_0.9.25      boot_1.3-28.1     
[33] jquerylib_0.1.4    estimability_1.4.1 Rcpp_1.0.11        modelr_0.1.11     
[37] splines_4.3.1      nnet_7.3-19        tidyselect_1.2.0   yaml_2.3.7        
[41] codetools_0.2-19   sjlabelled_1.2.0   lattice_0.21-8     tibble_3.2.1      
[45] withr_2.5.1        bayestestR_0.13.2  coda_0.19-4.1      evaluate_0.22     
[49] survival_3.5-5     units_0.8-5        proxy_0.4-27       survey_4.4-2      
[53] pillar_1.9.0       KernSmooth_2.23-21 insight_0.19.11    generics_0.1.3    
[57] hms_1.1.3          munsell_0.5.0      scales_1.3.0       minqa_1.2.6       
[61] xtable_1.8-4       class_7.3-22       glue_1.6.2         emmeans_1.8.9     
[65] tools_4.3.1        data.table_1.15.4  mvtnorm_1.2-3      grid_4.3.1        
[69] tidyr_1.3.0        mitools_2.4        datawizard_0.10.0  colorspace_2.1-0  
[73] nlme_3.1-162       cli_3.6.1          fansi_1.0.4        sjstats_0.18.2    
[77] gtable_0.3.4       sass_0.4.7         digest_0.6.33      classInt_0.4-10   
[81] farver_2.1.1       htmltools_0.5.6    lifecycle_1.0.3    httr_1.4.7        

Appendix 2. Entire R code used in the project

# Opening key libraries first
library(rmarkdown)
library(knitr)
# Global options
opts_chunk$set(echo=TRUE,
                 cache=TRUE,
               comment=NA,
               message=FALSE,
               warning=FALSE)
# General
library("rmarkdown")
library("knitr")
library("rstudioapi")
library("stargazer")
library("effects")
library("sf") 
library("sp") 
library("spdep") 
library("randomForest") 
library("modelsummary") 
library("MASS") 
library("lmtest") 
library("sandwich") 
library("pscl") 
library("ggplot2")
library("dplyr")
library("plyr")
library("sjPlot")
library("readr")
library("broom")
library("broom.mixed")
library("ggstats")

# Used for mapping
library("maps")
library("mapdata")
library("ggmap")
library("broom")

# Used to plot correlations
library("correlation")
library("lme4")
library("performance")

# Versions of used packages
packages <- c("rmarkdown", "knitr", "rstudioapi", "stargazer", "effects", "sf", "sp", "spdep", "randomForest", "modelsummary", "MASS", "lmtest", "sandwich", "pscl", "ggplot2", "dplyr", "sjPlot", "readr", "maps", "mapdata", "ggmap", "broom", "plyr", "correlation",
             "lme4", "performance")
names(packages) <- packages
lapply(packages, packageVersion)
# What is my R version?
version[['version.string']]
# Original data and assisting script download
load(file = "Data/Deprivation_2023_BDG_Replication.RData")

source("Original Scripts/helpers.R")
# Original data cleaning script 

main.covariates <- c("ln_pop", "age_mean", "uneployment_longterm_perct", "reli_christian", "urban", "ethn_arab_perct", "ethn_bame_perct", "police.force.name")
main.predictors <- c("Income.Score", "Living.Environment.Score", "Education.Score")
main.predictors.19 <- paste0(main.predictors, ".19"); main.predictors.19 <- c(main.predictors.19, paste0(main.predictors.19, ".splag1.mean"))
main.predictors <- c(main.predictors, paste0(main.predictors, ".splag1.mean"))
all.relevant.vars <- c(main.covariates, main.predictors)



df5 <- df4
colnames(df5) <- gsub("hcrimes\\.train", "hcrimes\\.cleaned", gsub("\\.15", "", colnames(df5)))
df5 <- df5[complete.cases(df5[,c(all.relevant.vars, "hcrimes.cleaned.p100k.ln")]),]
df5$na.19 <- as.numeric(!complete.cases(df5[,c(all.relevant.vars, "hcrimes.test2.p100k.ln")]))                                  

df5$hcrimes.cleaned.p100k.ln.zero.omit <- ifelse(df5$hcrimes.cleaned.p100k.ln==0, NA, df5$hcrimes.cleaned.p100k.ln)
colnames(df3.shapes) <- gsub("\\.15", "", colnames(df3.shapes))

# Creating a new dataset which omits data from Scotland, Wales and Gibraltar. This data is not needed as the original dataset contains no data on these places. 

eu_referendum_data <- read_csv("Data/EU-referendum-result-data.csv")


eu_referendum_data_1 <- subset(eu_referendum_data, !(id %in% c(381, 153, 155, 157, 159, 160, 179, 162, 163, 165, 166, 167, 168, 169, 171, 172, 152, 174, 175, 176, 177, 148, 149, 151, 161, 173, 154, 178, 150, 156, 170, 158, 164, 382, 126, 127, 128, 129, 130, 131, 133, 134, 135, 136, 137, 138, 139, 147, 140, 142, 143,   144, 145,   146, 132,   141)))
# Homogenising the name of the column which indicates Local Authority District code for merging

colnames(eu_referendum_data)[colnames(eu_referendum_data) == 'Area_Code'] <- 'lad'

colnames(eu_referendum_data_1)[colnames(eu_referendum_data_1) == 'Area_Code'] <- 'lad'
# Merging the original dataset with the EU referendum dataset

merged_data_eu <- merge(df5, eu_referendum_data, by = "lad")

# Downloading the shapefile and merging with referndum data
lad_shp <- st_read("Data/Shapefile/LAD_DEC_2016_GB_BGC_V2.shp")

colnames(lad_shp)[colnames(lad_shp) == 'LAD16CD'] <- 'lad'

eu_shapefile_data <- merge(lad_shp, eu_referendum_data, by = "lad")


hcrime_data_for_map <- merged_data_eu[ , c('hcrimes.cleaned.p100k.ln', 'lad', 'Pct_Leave')]


hcrime_shapefile_data <- merge(lad_shp, hcrime_data_for_map, by = "lad")


ggplot(hcrime_shapefile_data) +
  geom_sf(aes(fill = Pct_Leave)) +
  scale_fill_viridis_c() +
  labs(title = "Figure 1: Percentage of Leave Votes in the 2016 EU Referendum in the UK",
       fill = "Percentage of Leave Votes",
       caption = " Spatial data source: Office for National Statistics licensed under the Open 
       Government Licence v.3.0. Contains OS data © Crown copyright and database 
       right 2001")


ggplot(hcrime_shapefile_data) +
  geom_sf(aes(fill = hcrimes.cleaned.p100k.ln)) +
  scale_fill_viridis_c() +
  labs(title = "Figure 2: Logged number of Hate Crimes per 100k ",
       fill = "Logged number of Hate Crimes",
       caption = " Spatial data source: Office for National Statistics licensed under the Open 
       Government Licence v.3.0. Contains OS data © Crown copyright and database 
       right 2001")


hist_facet_mean_line <- ddply(merged_data_eu, "Region", summarise, 
                              grp.mean = mean(Pct_Leave))

ggplot(merged_data_eu) +
  aes(x = Pct_Leave) +
  geom_histogram(binwidth = 2, colour = "black", fill = "white") +
  facet_wrap(Region ~ .) +
  geom_vline(data = hist_facet_mean_line, aes(xintercept = grp.mean), color = "red",
             linetype = "dashed") +
  labs(title = "Figure 3: Histogram of Leave Percent Votes by Region",
       x = "Percent Leave Vote",
       y = "Number of LSOA's") 


ggplot(merged_data_eu) +
  aes(x = Pct_Leave) +
  geom_boxplot() +
  facet_grid(Region ~ .) +
  theme(strip.text.y.right = element_text(angle = 0)) +
  labs(title = "Figure 4: Boxplot of Leave Percent Votes by Region",
       x = "Percent Leave Vote") 


ggplot(merged_data_eu) +
  aes(hcrimes.cleaned.p100k.ln) +
  geom_boxplot() +
  facet_grid(Region ~ .) +
  theme(strip.text.y.right = element_text(angle = 0)) +
  labs(title = "Figure 5: Boxplot of Logged Hate Crimes by Region",
       x = "Logged Hate Crime per 100k") 

hcrime_mlmodel_null <- lmer(hcrimes.cleaned.p100k.ln ~  (1 | id),
                                data = merged_data_eu)


tab_model(hcrime_mlmodel_null, dv.labels = 'Logged Hate Crime per 100k', title = 'Multilevel Model of Logged Hate Crime')

hcrime_brexit_mlmodel <- lmer(hcrimes.cleaned.p100k.ln ~ Pct_Leave + (1 | id),
                              data = merged_data_eu)

coef_mlm <- coef(hcrime_brexit_mlmodel)$id


head(coef_mlm, 5)

cor_coef_table_brexit_deprivation <- 
merged_data_eu %>%
  as.data.frame() %>%
  select(Pct_Leave, Income.Score, Education.Score, Living.Environment.Score) %>%
  as.matrix() %>%
  cor()

rownames(cor_coef_table_brexit_deprivation) <-  c('Leave Vote Percent', 'Income Deprivation', 'Education Deprivation', 'Living Envrionment Deprivation')
kable(cor_coef_table_brexit_deprivation, col.names = c('Leave Vote Percent', 'Income Deprivation', 'Education Deprivation', 'Living Envrionment Deprivation'))

cor_coef_table_brexit_demographics <- 
  merged_data_eu %>%
  as.data.frame() %>%
  select(Pct_Leave, ln_pop , age_mean , 
           uneployment_longterm_perct , reli_christian , urban , 
           ethn_arab_perct , ethn_bame_perct) %>%
  as.matrix() %>%
  cor()

rownames(cor_coef_table_brexit_demographics) <-  c('Leave Vote Percent', 'Logged Population', 'Mean Age', 'Longterm Unemployed', 'Christian', 'Urban', 'Ethic Arab', 'Ethnic BAME')
kable(cor_coef_table_brexit_demographics, col.names = c('Leave Vote Percent', 'Logged Population', 'Mean Age', 'Longterm Unemployed', 'Christian', 'Urban', 'Ethic Arab', 'Ethnic BAME'))
hcrime_brexit_mlmodel <- lmer(hcrimes.cleaned.p100k.ln ~ Pct_Leave + (1 | id),
                              data = merged_data_eu)

hcrime_brexit_mlmodel_table <- 
  tab_model(hcrime_brexit_mlmodel, pred.labels = list("Intercept", "Leave Vote Percent"),
          title = "Linear Regression of Leave Vote Percent (LAD) on 
          Logged Hate Crime (LSOA)",
          dv.labels = "Logged Hate Crime per 100k")
hcrime_brexit_mlmodel_table
repro_formula <- formula(hcrimes.cleaned.p100k.ln ~ ln_pop + age_mean + uneployment_longterm_perct + reli_christian + urban + ethn_arab_perct + ethn_bame_perct + police.force.name, merged_data_eu)
repro_model_1 <- lm(repro_formula, df5)

repro_model_2 <- lm(update(repro_formula, ~ Income.Score), df5)

repro_model_3 <- lm(update(repro_formula, ~ Living.Environment.Score), df5)

repro_model_4 <- lm(update(repro_formula, ~ Education.Score), df5)

repro_model_5 <- lm(update(repro_formula, ~ Income.Score + Income.Score.splag1.mean + .), df5)

repro_model_6 <- lm(update(repro_formula, ~ Living.Environment.Score + Living.Environment.Score.splag1.mean + .), df5)

repro_model_7 <- lm(update(repro_formula, ~ Education.Score + Education.Score.splag1.mean + . ), df5)

repro_model_8 <- lm(update(repro_formula, ~ Income.Score + Income.Score.splag1.mean +
                             Living.Environment.Score + 
                             Living.Environment.Score.splag1.mean +
                             Education.Score + Education.Score.splag1.mean + . ), df5)


full_reproduced_regression_table <- 
  tab_model(repro_model_1, repro_model_2, repro_model_3, repro_model_4, repro_model_5, 
          repro_model_6, repro_model_7, repro_model_8, digits = 3, drop =  'police.force.name', 
         show.ci = FALSE, show.intercept = TRUE, p.style = 'numeric',
          dv.labels = list('1', '2', '3', '4', '5', '6', '7', '8'),
          pred.labels = list('Intercept', 'Population Size (log)', 'Mean Age', 'Unemployment Percentage',
          'Christian Religion Percentage', 'Urban', 'Arab Ethnicity Percentage', 
          'BAME Percentage', 'Income Deprivation', 'Living Envrionment Deprivation',
          'Education Deprivation', 'Neighbour Income Deprivation', 
          'Neighbour Living Envrionment Deprivation', 'Neighbour Education Deprivation'),
          title = 'Table 2: Linear Regression of Logged Hate Crime 2015-2018')
full_reproduced_regression_table

brexit_formula <- formula(hcrimes.cleaned.p100k.ln ~ ln_pop + age_mean + 
                            uneployment_longterm_perct + reli_christian + urban + 
                            ethn_arab_perct + ethn_bame_perct + police.force.name , 
                          data = merged_data_eu)
hcrime_demo_mlm_1 <-
  lmer(update(brexit_formula, ~ (1 | id) + .), data = merged_data_eu)

hcrime_demo_mlm_2 <-
  lmer(update(brexit_formula, ~ Income.Score + (1 | id)), data = merged_data_eu)

hcrime_demo_mlm_3 <- 
  lmer(update(brexit_formula, ~ Living.Environment.Score + (1 | id)), data = merged_data_eu)

hcrime_demo_mlm_4 <- 
  lmer(update(brexit_formula, ~ Education.Score + (1 | id)), data = merged_data_eu)

hcrime_demo_mlm_5 <- 
  lmer(update(brexit_formula, ~ Income.Score + Income.Score.splag1.mean +
                (1 | id) + .), data = merged_data_eu)

hcrime_demo_mlm_6 <- 
  lmer(update(brexit_formula, ~  Living.Environment.Score + 
                Living.Environment.Score.splag1.mean +
                (1 | id) + .), data = merged_data_eu)

hcrime_demo_mlm_7 <- 
  lmer(update(brexit_formula, ~ Education.Score + 
                Education.Score.splag1.mean + (1 | id) + .), data = merged_data_eu)

hcrime_demo_mlm_8 <- lmer(update(brexit_formula, ~ Income.Score + 
                                          Income.Score.splag1.mean + Living.Environment.Score + 
                                          Living.Environment.Score.splag1.mean +
                                          Education.Score + Education.Score.splag1.mean + 
                                          (1 | id) + .) , merged_data_eu)

hcrime_demo_regression_tab_model <-
  tab_model(hcrime_demo_mlm_1, hcrime_demo_mlm_2, hcrime_demo_mlm_3, 
            hcrime_demo_mlm_4, hcrime_demo_mlm_5, 
            hcrime_demo_mlm_6, hcrime_demo_mlm_7, hcrime_demo_mlm_8,
            digits = 3, drop = "police.force.name",
            show.ci = FALSE, show.intercept = TRUE, p.style = "numeric",
            dv.labels = list("1", "2", "3", "4", "5", "6", "7", "8"),
            pred.labels = list("Intercept", "Population Size (log)", "Mean Age", "Unemployment Percentage",
                               "Christian Religion Percentage", "Urban", "Arab Ethnicity Percentage", 
                               "BAME Percentage", "Income Deprivation", "Living Envrionment Deprivation",
                               "Education Deprivation", "Neighbour Income Deprivation", 
                               "Neighbour Living Envrionment Deprivation", "Neighbour Education Deprivation"),
            title = "Table 3: Linear Regression Multi-Level Model of Deprivation on Hate Crime")
hcrime_demo_regression_tab_model
hcrime_demo_single_coef <- lm(update(brexit_formula, ~ Income.Score + 
                             Income.Score.splag1.mean + Living.Environment.Score + 
                             Living.Environment.Score.splag1.mean +
                             Education.Score + Education.Score.splag1.mean + .), data = merged_data_eu)

hcrime_demo_mlm_coef <- 
  lmer(update(brexit_formula, ~ Income.Score + 
                             Income.Score.splag1.mean + Living.Environment.Score + 
                             Living.Environment.Score.splag1.mean +
                             Education.Score + Education.Score.splag1.mean +(1 | id) + .), data = merged_data_eu)

hcrime_demo_single_coef_ci <- tidy(hcrime_demo_single_coef, conf.int = TRUE) %>% mutate(model = "Single-Level")

hcrime_demo_mlm_ci <- tidy(hcrime_demo_mlm_coef, conf.int = TRUE) %>% mutate(model = "Multi-Level")

hcrime_demo_models_coef <- bind_rows(hcrime_demo_single_coef_ci, hcrime_demo_mlm_ci)
hcrime_demo_models_coef_np <- 
  hcrime_demo_models_coef[- grep("police", hcrime_demo_models_coef$term),]
hcrime_demo_models_coef_np <- 
  hcrime_demo_models_coef_np[- grep("sd__", hcrime_demo_models_coef_np$term),] 
hcrime_demo_models_coef_np$term <- recode(hcrime_demo_models_coef_np$term, '(Intercept)' = 'Intercept', 'ln_pop' = 'Logged Population', 'age_mean' = 'Mean Age' , 
                     'uneployment_longterm_perct' = 'Long-term Unemployed' , 'reli_christian' = 'Christian' , 'urban' = 'Urban', 
                     'ethn_arab_perct' = 'Ethnic Arab', 'ethn_bame_perct' = 'Ethnic BAME',
                     'Income.Score' = 'Income Deprivation' , 
                     'Income.Score.splag1.mean' = ' Neighbouring Income Deprivation', 'Living.Environment.Score' = 'Living Environment Deprivation',
                     'Living.Environment.Score.splag1.mean' = 'Neighbouring Living Environment Deprivation',
                     'Education.Score' = 'Education Deprivation', 'Education.Score.splag1.mean' = 'Neighbouring Education Deprivation')

ggplot(hcrime_demo_models_coef_np, 
       aes(x = term, y = estimate, color = model)) +
  geom_point(position = position_dodge(width = 0.5)) +
  geom_errorbar(aes(ymin = conf.low, ymax = conf.high), width = 0.2, position = position_dodge(width = 0.5)) +
  coord_flip() +
  labs(title = "Comparison of Single and Multilevel Model Coefficients",
       x = "Predictors",
       y = "Estimate") +
  theme_minimal()
hcrime_demo_regression_tab_model
brexit_hcrime_demo_mlm_1 <-
  lmer(update(brexit_formula, ~ Pct_Leave + (1 | id) + .), data = merged_data_eu)

brexit_hcrime_demo_mlm_2 <-
  lmer(update(brexit_formula, ~ Pct_Leave + Income.Score + (1 | id)), data = merged_data_eu)

brexit_hcrime_demo_mlm_3 <- 
  lmer(update(brexit_formula, ~ Pct_Leave + Living.Environment.Score + (1 | id)), data = merged_data_eu)

brexit_hcrime_demo_mlm_4 <- 
  lmer(update(brexit_formula, ~ Pct_Leave + Education.Score + (1 | id)), data = merged_data_eu)

brexit_hcrime_demo_mlm_5 <- 
  lmer(update(brexit_formula, ~ Pct_Leave + Income.Score + Income.Score.splag1.mean +
                (1 | id) + .), data = merged_data_eu)

brexit_hcrime_demo_mlm_6 <- 
  lmer(update(brexit_formula, ~ Pct_Leave + Living.Environment.Score + 
                Living.Environment.Score.splag1.mean +
                (1 | id) + .), data = merged_data_eu)

brexit_hcrime_demo_mlm_7 <- 
  lmer(update(brexit_formula, ~ Pct_Leave + Education.Score + 
                Education.Score.splag1.mean + (1 | id) + .), data = merged_data_eu)

brexit_hcrime_demo_mlm_8 <- lmer(update(brexit_formula, ~ Pct_Leave + Income.Score + 
                             Income.Score.splag1.mean + Living.Environment.Score + 
                             Living.Environment.Score.splag1.mean +
                             Education.Score + Education.Score.splag1.mean + 
                              (1 | id) + .) , merged_data_eu)
full_regression_tab_model <-
tab_model(brexit_hcrime_demo_mlm_1, brexit_hcrime_demo_mlm_2, brexit_hcrime_demo_mlm_3, 
          brexit_hcrime_demo_mlm_4, brexit_hcrime_demo_mlm_5, 
          brexit_hcrime_demo_mlm_6, brexit_hcrime_demo_mlm_7, brexit_hcrime_demo_mlm_8,
          digits = 3, drop = "police.force.name", show.intercept = TRUE,
          show.ci = FALSE, p.style = "numeric",
          dv.labels = list("1", "2", "3", "4", "5", "6", "7", "8"),
          pred.labels = list("Intercept", "Leave Vote Percent", "Population Size (log)", "Mean Age", "Unemployment Percentage",
                             "Christian Religion Percentage", "Urban", "Arab Ethnicity Percentage", 
                             "BAME Percentage", "Income Deprivation", "Living Envrionment Deprivation",
                             "Education Deprivation", "Neighbour Income Deprivation", 
                             "Neighbour Living Envrionment Deprivation", "Neighbour Education Deprivation"),
          title = "Table 4: Linear Regression Model of Leave Vote Percentage and Deprivation on Hate Crime")
full_regression_tab_model
hcrime_demo_brexit_mlm_coef <- lmer(update(brexit_formula, ~ Pct_Leave + Income.Score + 
                             Income.Score.splag1.mean + Living.Environment.Score + 
                             Living.Environment.Score.splag1.mean +
                             Education.Score + Education.Score.splag1.mean +(1 | id) + .), data = merged_data_eu)

hcrime_demo_mlm_ci_nobrexit <- tidy(hcrime_demo_mlm_coef, conf.int = TRUE) %>% mutate(model = "Multi-Level No Brexit")

hcrime_demo_mlm_ci_brexit <- tidy(hcrime_demo_brexit_mlm_coef, conf.int = TRUE) %>% mutate(model = "Multi-Level With Brexit")


hcrime_demo_models_coef_brexit <- bind_rows(hcrime_demo_mlm_ci_nobrexit, hcrime_demo_mlm_ci_brexit)
hcrime_demo_brexit_models_coef_np <- 
  hcrime_demo_models_coef_brexit[- grep("police", hcrime_demo_models_coef_brexit$term),]
hcrime_demo_brexit_models_coef_np <- 
  hcrime_demo_brexit_models_coef_np[- grep("sd__", hcrime_demo_brexit_models_coef_np$term),] 
hcrime_demo_brexit_models_coef_np$term <- recode(hcrime_demo_brexit_models_coef_np$term, '(Intercept)' = 'Intercept', 'ln_pop' = 'Logged Population', 'age_mean' = 'Mean Age' , 
                     'uneployment_longterm_perct' = 'Long-term Unemployed' , 'reli_christian' = 'Christian' , 'urban' = 'Urban', 
                     'ethn_arab_perct' = 'Ethnic Arab', 'ethn_bame_perct' = 'Ethnic BAME',
                     'Income.Score' = 'Income Deprivation' , 
                     'Income.Score.splag1.mean' = ' Neighbouring Income Deprivation', 'Living.Environment.Score' = 'Living Environment Deprivation',
                     'Living.Environment.Score.splag1.mean' = 'Neighbouring Living Environment Deprivation',
                     'Education.Score' = 'Education Deprivation', 'Education.Score.splag1.mean' = 'Neighbouring Education Deprivation', 'Pct_Leave' = 'Leave Vote Proportion')

ggplot(hcrime_demo_brexit_models_coef_np, 
       aes(x = term, y = estimate, color = model)) +
  geom_point(position = position_dodge(width = 0.5)) +
  geom_errorbar(aes(ymin = conf.low, ymax = conf.high), width = 0.2, position = position_dodge(width = 0.5)) +
  coord_flip() +
  labs(title = "Comparison of With and Without Brexit Coefficients",
       x = "Predictors",
       y = "Estimate") +
  theme_minimal()
hcrime_brexit_mlmodel_me_plot <- plot_model(hcrime_brexit_mlmodel, type = "re",
                                            dot.size = 1, line.size = 0.2, grid.breaks = 1) +
  theme(axis.text.y = element_text(size = 4, angle = 0, hjust = 1))
hcrime_brexit_mlmodel_me_plot
hcrime_all_pred_me_plot <- plot_model(brexit_hcrime_demo_mlm_8, type = "re",
                                      dot.size = 1, line.size = 0.2, grid.breaks = 1) +
  theme(axis.text.y = element_text(size = 4, angle = 0, hjust = 1))
hcrime_all_pred_me_plot
# Detailed information about my environment
sessionInfo()
LS0tDQp0aXRsZTogIlNNSTIwNSBSZXBsaWNhdGlvbiBQcm9qZWN0ICgyMDIzKSINCmF1dGhvcjogIjIwMDE0Mjk1MSINCmRhdGU6ICIwMS8wNi8yMDI0Ig0Kb3V0cHV0OiANCiAgaHRtbF9kb2N1bWVudDogDQogICAgY29kZV9kb3dubG9hZDogdHJ1ZQ0KICAgIHRvYzogdHJ1ZQ0KICAgIHRvY19kZXB0aDogMg0KICAgIHRvY19mbG9hdDogDQogICAgICBjb2xsYXBzZWQ6IGZhbHNlDQogICAgICBzbW9vdGhfc2Nyb2xsOiB0cnVlDQotLS0NCg0KYGBge3Igc3RhcnQsIGluY2x1ZGU9RkFMU0V9DQojIE9wZW5pbmcga2V5IGxpYnJhcmllcyBmaXJzdA0KbGlicmFyeShybWFya2Rvd24pDQpsaWJyYXJ5KGtuaXRyKQ0KYGBgDQoNCiMgQSBNdWx0aWxldmVsIEFuYWx5c2lzIG9mIHRoZSBpbXBhY3Qgb2YgQnJleGl0IExlYXZlIFZvdGUgcHJvcG9ydGlvbiBvbiBIYXRlIENyaW1lIGluIEVuZ2xhbmQNCg0KIyMjIFJwdWJzIGxpbms6IGh0dHBzOi8vcnB1YnMuY29tL1NNSTIwMDE0Mjk1MS8xMTkxMTA0DQoNCiMjIyBTdHVkeSBQcmVyZWdpc3RyYXRpb24gZm9ybTogaHR0cHM6Ly9ycHVicy5jb20vU01JMjAwMTQyOTUxLzExODU5MDINCg0KIyMgSW5mb3JtYXRpb24gYWJvdXQgdGhpcyByZXBsaWNhdGlvbiBwcm9qZWN0DQoqIFJlcGxpY2F0aW9uIHByb2plY3QgYmFzZWQgb24gcGFwZXIgYnkgQmVsZ2lvaW9zbywgTS4sIER3b3JzY2hhaywgQy4sICYgR2xlZGl0c2NoLCBLLiBTLiAoMjAyMykuIExvY2FsIGRlcHJpdmF0aW9uIHByZWRpY3RzIHJpZ2h0LXdpbmcgaGF0ZSBjcmltZSBpbiBFbmdsYW5kLiBQTE9TIE9ORSwgMTgoOSksIGUwMjg5NDIzLiAgDQpBdmFpbGFibGUgYXQ6IGh0dHBzOi8vam91cm5hbHMucGxvcy5vcmcvcGxvc29uZS9hcnRpY2xlP2lkPTEwLjEzNzEvam91cm5hbC5wb25lLjAyODk0MjNdDQoNCiogVGhpcyBwYXBlciBoYXMgcHJldmlvdXNseSBiZWVuIHJlcGxpY2F0ZWQgcGFydCB1c2luZyB0aGUgc2FtZSBkYXRhIGFuZCBtZXRob2RzLCBiYXNlZCBvbiB0aGVpciByZXBsaWNhdGlvbiBwYWNrYWdlIGF2YWlsYWJsZSBoZXJlOiBodHRwczovL2RhdGF2ZXJzZS5oYXJ2YXJkLmVkdS9kYXRhc2V0LnhodG1sP3BlcnNpc3RlbnRJZD1kb2k6MTAuNzkxMC9EVk4vR1NSUFFZDQoNCiogVGhpcyByZXBsaWNhdGlvbiBpbiBhbiBleHRlbnNpb24gb2YgdGhlIG9yaWdpbmFsIHBhcGVyLCB1c2luZyBuZXcgZGF0YSBhbmQgZGlmZmVyZW50IG1ldGhvZHMgaW4gb3JkZXIgdG8gdGVzdCByZXBlYXRhYmlsaXR5Lg0KDQojIyBXb3Jrc3BhY2Ugc2V0dXAgey50YWJzZXQgLnRhYnNldC1waWxsc30NCg0KIyMjIFlBTUwgc2V0dGluZ3MNCg0KIG91dHB1dDogPC9icj4NCiAgJm5ic3A7IGh0bWxfZG9jdW1lbnQ6IDwvYnI+DQogICAgJm5ic3A7Jm5ic3A7IGNvZGVfZG93bmxvYWQ6IHRydWUgPC9icj4NCiAgICAmbmJzcDsmbmJzcDsmbmJzcDsgdG9jOiB0cnVlIDwvYnI+DQogICAgJm5ic3A7Jm5ic3A7Jm5ic3A7IHRvY19kZXB0aDogMiA8L2JyPg0KICAgICZuYnNwOyZuYnNwOyZuYnNwOyB0b2NfZmxvYXQ6IDwvYnI+DQogICAgICAmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsgY29sbGFwc2VkOiBmYWxzZSA8L2JyPg0KICAgICAgJm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7IHNtb290aF9zY3JvbGw6IHRydWUgPC9icj4NCg0KIyMjIEdsb2JhbCBzZXR0aW5ncyBvZiBSIGNodW5rcw0KDQpgYGB7ciBzZXR1cCwgaW5jbHVkZT1UUlVFfQ0KIyBHbG9iYWwgb3B0aW9ucw0Kb3B0c19jaHVuayRzZXQoZWNobz1UUlVFLA0KCSAgICAgICAgICAgICBjYWNoZT1UUlVFLA0KICAgICAgICAgICAgICAgY29tbWVudD1OQSwNCiAgICAgICAgICAgICAgIG1lc3NhZ2U9RkFMU0UsDQogICAgICAgICAgICAgICB3YXJuaW5nPUZBTFNFKQ0KYGBgDQoNCiMjIyBMaWJyYXJpZXMNCg0KYGBge3IgbGlicmFyaWVzLCBpbmNsdWRlPVRSVUV9DQojIEdlbmVyYWwNCmxpYnJhcnkoInJtYXJrZG93biIpDQpsaWJyYXJ5KCJrbml0ciIpDQpsaWJyYXJ5KCJyc3R1ZGlvYXBpIikNCmxpYnJhcnkoInN0YXJnYXplciIpDQpsaWJyYXJ5KCJlZmZlY3RzIikNCmxpYnJhcnkoInNmIikgDQpsaWJyYXJ5KCJzcCIpIA0KbGlicmFyeSgic3BkZXAiKSANCmxpYnJhcnkoInJhbmRvbUZvcmVzdCIpIA0KbGlicmFyeSgibW9kZWxzdW1tYXJ5IikgDQpsaWJyYXJ5KCJNQVNTIikgDQpsaWJyYXJ5KCJsbXRlc3QiKSANCmxpYnJhcnkoInNhbmR3aWNoIikgDQpsaWJyYXJ5KCJwc2NsIikgDQpsaWJyYXJ5KCJnZ3Bsb3QyIikNCmxpYnJhcnkoImRwbHlyIikNCmxpYnJhcnkoInBseXIiKQ0KbGlicmFyeSgic2pQbG90IikNCmxpYnJhcnkoInJlYWRyIikNCmxpYnJhcnkoImJyb29tIikNCmxpYnJhcnkoImJyb29tLm1peGVkIikNCmxpYnJhcnkoImdnc3RhdHMiKQ0KDQojIFVzZWQgZm9yIG1hcHBpbmcNCmxpYnJhcnkoIm1hcHMiKQ0KbGlicmFyeSgibWFwZGF0YSIpDQpsaWJyYXJ5KCJnZ21hcCIpDQpsaWJyYXJ5KCJicm9vbSIpDQoNCiMgVXNlZCB0byBwbG90IGNvcnJlbGF0aW9ucw0KbGlicmFyeSgiY29ycmVsYXRpb24iKQ0KbGlicmFyeSgibG1lNCIpDQpsaWJyYXJ5KCJwZXJmb3JtYW5jZSIpDQoNCmBgYA0KDQojIyMgVmVyc2lvbnMgb2YgdXNlZCBwYWNrYWdlcw0KDQpgYGB7ciB2ZXJzaW9ucywgZWNobz1GQUxTRX0NCiMgVmVyc2lvbnMgb2YgdXNlZCBwYWNrYWdlcw0KcGFja2FnZXMgPC0gYygicm1hcmtkb3duIiwgImtuaXRyIiwgInJzdHVkaW9hcGkiLCAic3RhcmdhemVyIiwgImVmZmVjdHMiLCAic2YiLCAic3AiLCAic3BkZXAiLCAicmFuZG9tRm9yZXN0IiwgIm1vZGVsc3VtbWFyeSIsICJNQVNTIiwgImxtdGVzdCIsICJzYW5kd2ljaCIsICJwc2NsIiwgImdncGxvdDIiLCAiZHBseXIiLCAic2pQbG90IiwgInJlYWRyIiwgIm1hcHMiLCAibWFwZGF0YSIsICJnZ21hcCIsICJicm9vbSIsICJwbHlyIiwgImNvcnJlbGF0aW9uIiwNCiAgICAgICAgICAgICAibG1lNCIsICJwZXJmb3JtYW5jZSIpDQpuYW1lcyhwYWNrYWdlcykgPC0gcGFja2FnZXMNCmxhcHBseShwYWNrYWdlcywgcGFja2FnZVZlcnNpb24pDQpgYGANCg0KIyMjIE15IGVudmlyb21lbnQNCg0KYGBge3IgbXlSLCBlY2hvPUZBTFNFfQ0KIyBXaGF0IGlzIG15IFIgdmVyc2lvbj8NCnZlcnNpb25bWyd2ZXJzaW9uLnN0cmluZyddXQ0KYGBgDQoNCiMjIDEuIEludHJvZHVjdGlvbg0KDQpCZWxnaW9pb3NvIGV0IGFsLuKAmXMgcGFwZXIg4oCYTG9jYWwgZGVwcml2YXRpb24gcHJlZGljdHMgcmlnaHQtd2luZyBoYXRlIGNyaW1lIGluIEVuZ2xhbmTigJkgKEJlbGdpb2lvc28sIGV0IGFsLiwgMjAyMykgc3R1ZGllZCB0aGUgZWZmZWN0IGxvY2FsIGRlcHJpdmF0aW9uIGhhZCBvbiBoYXRlIGNyaW1lIHJhdGVzIGFjcm9zcyBFbmdsYW5kLCBmaW5kaW5nIHRoYXQgYXJlYXMgd2l0aCBoaWdoZXIgbGV2ZWxzIG9mIGRlcHJpdmF0aW9uLCBwYXJ0aWN1bGFybHkgaW5jb21lIGRlcHJpdmF0aW9uLCB3ZXJlIHBvc2l0aXZlbHkgY29ycmVsYXRlZCB3aXRoIGEgaGlnaGVyIHJhdGUgb2YgaGF0ZSBjcmltZSBldmVudHMuIFRoZSBwYXBlciBzdWNjZXNzZnVsbHkgYWRkcmVzc2VzIGEgZ2FwIGluIHRoZSBsaXRlcmF0dXJlLCB1dGlsaXNpbmcgbmVpZ2hib3VyaG9vZC1sZXZlbCBoYXRlIGNyaW1lIGFuZCBkZXByaXZhdGlvbiBkYXRhIHRvIGV4cGxvcmUgbG9jYWwgZHJpdmVycyBvZiBoYXRlIGNyaW1lLiBUaGVpciBhcmd1bWVudCBpcyB0aGF0IHByZXZpb3VzIHN0dWRpZXMgaGF2ZSBmYWlsZWQgdG8gY2FwdHVyZSB0aGUgaW1wYWN0IG9mIGltcG9ydGFudCBmYWN0b3JzIHN1Y2ggYXMgZmVlbGluZ3Mgb2YgY29tbXVuaXR5IGFiYW5kb25tZW50IGFuZCB0aGUgcGVyY2VwdGlvbiB0aGF0IHBvbGl0aWNhbCBpbnN0aXR1dGlvbnMgZG9pbmcgbm90aGluZyBmb3IgaW5kaXZpZHVhbHMgd2l0aGluIGEgY29tbXVuaXR5IHNldHRpbmcsIHdoaWNoIGluIHR1cm4gbGVhZHMgaW5kaXZpZHVhbHMgaW50byBmYXItcmlnaHQgdGhpbmtpbmcuIA0KDQpIb3dldmVyLCB0aGlzIHJlc2VhcmNoIGRvZXMgbm90IGNvbnNpZGVyIHRoZSBpbXBvcnRhbmNlIG9mIHBvbGl0aWNhbCBldmVudHMsIGFuZCB0aGUgcG9saXRpY2FsIGNsaW1hdGUsIG9uIGhhdGUgY3JpbWUuIFJlc2VhcmNoIHBlcmZvcm1lZCBieSBLaW5nICYgU3V0dG9uIGV4cGxvcmVzIHRoZSByZWxhdGlvbnNoaXAgYmV0d2VlbiBzaW5nbGUsIGRpc2NyZXRlIGV2ZW50cyBhbmQgdGhlIHdheSBpbiB3aGljaCB0aGV5IGFmZmVjdCBoYXRlIGNyaW1lcyB0ZW1wb3JhbGx5LiBUaGV5IGZvdW5kIHRoYXQgdGhlIG9jY3VycmVuY2Ugb2YgdmVyeSBwdWJsaWMgYW5kIGNvbnRlbnRpb3VzIHBvbGl0aWNhbCBhbmQgc29jaWFsIGV2ZW50cyBpbiB0aGUgVVMgbGVkIHRvIHNpZ25pZmljYW50IGluY3JlYXNlIGluIGhhdGUgY3JpbWVzIGluIHRoZWlyIGltbWVkaWF0ZSBhZnRlcm1hdGggKEtpbmcgRC4gJiBTdXR0b24sIDIwMTMpLiBBbiBpbmNyZWRpYmx5IGltcG9ydGFudCBwb2xpdGljYWwgZXZlbnQgb2NjdXJyZWQgaW4gdGhlIFVLIGR1cmluZyB0aGUgc2FtZSB0aW1lZnJhbWUgaW4gd2hpY2ggdGhlIGRhdGEgdXNlZCBieSB0aGUgcmVzZWFyY2hlcnMsIHRoZSAyMDE2IEVVIE1lbWJlcnNoaXAgUmVmZXJlbmR1bS4gS25vd24gYXMgdGhlIOKAmEJyZXhpdOKAmSByZWZlcmVuZHVtIHRoaXMgZXZlbnQgd2FzIGh1Z2UsIG1lZGlhIHJlcG9ydHMgYW5kIHBvbGl0aWNhbCBkZWJhdGVzIG9uIHRoZSBzdWJqZWN0IHdlcmUgY29tbW9ucGxhY2UgaW4gdGhlIG1vbnRocyBsZWFkaW5nIHVwIHRvIHRoZSByZWZlcmVuZHVtOyByZXNlYXJjaCBieSBEZXZpbmUgYXNzb2NpYXRlZCB0aGUgc3Vic2VxdWVudCBkZXBhcnR1cmUgb2YgdGhlIFVLIGZyb20gdGhlIEVVIHdpdGgg4oCYYW4gaW5jcmVhc2UgaW4gaGF0ZSBjcmltZXMgb2YgMTktMjMl4oCZIChEZXZpbmUsIDIwMTgsIHAuIDEpLiBUaGlzIGh5cG90aGVzaXMgaXMgZnVydGhlciBjb3Jyb2JvcmF0ZWQgYnkgUGlhdGtvd3NrYSAmIFN0dWx0cyB3aG8gZm91bmQgdGhhdCB0aGUgdmVyeSB1bmlxdWUgbmF0dXJlIG9mIEJyZXhpdCBpbiB0aGUgVUsgcG9saXRpY2FsIHNwaGVyZSBsZWQgdG8gYSB1bmlxdWVseSBsYXJnZSBpbmNyZWFzZSBpbiBoYXRlIGNyaW1lIHJhdGVzIHdoZW4gY29tcGFyZWQgdG8gb3RoZXIgbGFyZ2UgZXZlbnRzLCBzdWNoIGFzIHRlcnJvcmlzdCBhdHRhY2tzIChQaWF0a293c2thICYgU3R1bHRzLCAyMDIyKS4gUmVzZWFyY2ggZXhwbG9yaW5nIHRoZSByZWFzb25zIHdoeSBwZW9wbGUgdm90ZWQgdG8gbGVhdmUgb24gdGhlIGxvY2FsIGxldmVsIGZvdW5kIGEgc3Ryb25nIOKAmGxlYXZl4oCZIHNlbnRpbWVudCBtYW5pZmVzdGVkIGluIGRlcHJpdmVkIGluZGl2aWR1YWxzIGxpdmluZyBpbiBkZXByaXZlZCBhcmVhcyBhcyB0aGV5IGZlbHQgdGhlaXIgam9icyB3ZXJlIHRocmVhdGVuZWQgYnkgbG93LXNraWxsZWQgbWlncmFudCBsYWJvdXIgZnJvbSB0aGUgRVUuIFRoaXMsIGNvdXBsZWQgd2l0aCBzdHJvbmcgYW50aS1pbW1pZ3JhbnQgc2VudGltZW50cyBieSBwcm8tbGVhdmUgcGFydGllcyBzdWNoIGFzIFVLSVAsIGN1bG1pbmF0ZWQgaW4gY29tbXVuaXRpZXMgZmVhcmluZyBpbW1pZ3JhdGlvbiAoQ2xhcmtlLCBldCBhbC4sIDIwMTcpLiBTdHVkaWVzIHBlcmZvcm1lZCBpbiB0aGUgTmV0aGVybGFuZHMgaGF2ZSBmb3VuZCB0aGlzIGZlYXIgb2YgaW1taWdyYXRpb24gYW5kIG91dC1ncm91cHMgY2F1c2VkIGJ5IHRoZXNlIGtpbmRzIG9mIGV2ZW50cyBsZWQgdG8gc29tZSBpbmRpdmlkdWFscyBhY3Rpbmcgb3V0IG9uIHRoZWlyIGZydXN0cmF0aW9ucyBhbmQgY29tbWl0dGluZyBoYXRlIGNyaW1lcyAoSmFjb2JzICYgdmFuIFNwYW5qZSwgMjAyMSkuDQoNClRoaXMgc3R1ZHkgaXMgZ29pbmcgdG8gZnVydGhlciB0ZXN0IEJlbGdpb2lvc28gZXQgYWwu4oCZcyBoeXBvdGhlc2lzIGJ5IGxvb2tpbmcgYXQgd2hldGhlciB0aGUgcHJvcG9ydGlvbiBvZiBsZWF2ZSB2b3RlcyBpbiBhbiBhcmVhIGhhZCBhbiBpbXBhY3Qgb24gdGhlIGhhdGUgY3JpbWUgcmF0ZXMgaW4gdGhpcyBhcmVhLCBhbmQgd2hldGhlciB0aGlzIGVmZmVjdCBtaWdodCBtaXRpZ2F0ZSB0aGUgaW1wYWN0IG9mIGRlcHJpdmF0aW9uLiBUaGlzIGZvcm0gb2YgcmVwbGljYXRpb24gbGFyZ2VseSB1dGlsaXNlcyBzaW1pbGFyIG1ldGhvZHMgb2YgYW5hbHlzaXMgdG8gdGhlIG9yaWdpbmFsIHJlc2VhcmNoZXJzLCBidXQgd2l0aCBhZGRpdGlvbmFsIGRhdGEgdG8gdGVzdCB3aGV0aGVyIG15IGFsdGVybmF0aXZlIGh5cG90aGVzaXMgaXMgdHJ1ZSwgbWFraW5nIHRoaXMgYSByZXBlYXRhYmlsaXR5IHRlc3QgKEZyZWVzZSAmIFBldGVyc29uLCAyMDE3KS4gVGhpcyBzdHVkeSB3aWxsIGhlbHAgYWRkcmVzcyBhIGdhcCBpbiByZXNlYXJjaCBpbiB0aGF0IG1vc3Qgc3R1ZGllcyBleHBsb3JpbmcgdGhlIHJlbGF0aW9uc2hpcCBiZXR3ZWVuIEJyZXhpdCBhbmQgaGF0ZSBjcmltZSBkbyBzbyB0ZW1wb3JhbGx5LCBub3Qgc3BhdGlhbGx5LiANCg0KKiBIeXBvdGhlc2lzIDE6IFRoZSBwcm9wb3J0aW9uIG9mIGluZGl2aWR1YWxzIGluIGFuIGFyZWEgd2hpY2ggdm90ZWQgdG8gTGVhdmUgdGhlIEV1cm9wZWFuIFVuaW9uIHdpbGwgaGF2ZSBhIHNpZ25pZmljYW50IGFuZCBzdWJzdGFudGlhbCBpbXBhY3Qgb24gdGhlIGhhdGUgY3JpbWUgcmF0ZSBpbiB0aGF0IGFyZWENCg0KDQojIyAyLiBEYXRhIGFuZCBtZXRob2RzDQoNCiMjIyAyLjEuIERhdGENCg0KVGhlIGRhdGFzZXQgdXNlZCBpbiB0aGlzIHBhcGVyIHV0aWxpc2VzIHRoZSBzYW1lIGRhdGEgdXNlZCBpbiB0aGUgb3JpZ2luYWwgcGFwZXIgYW5kIGNhbiBiZSBkb3dubG9hZGVkIGZyb20gdGhlIEhhcnZhcmQgRGF0YXZlcnNlIHJlcG9zaXRvcnkuIEl0IGNvbnRhaW5zIDMyMjAxIG9ic2VydmF0aW9ucyBvZiA4MCB2YXJpYWJsZXMuDQoNClBsZWFzZSBzZWUgRGF0YSBSZWZlcmVuY2VzIHRvIGFjY2VzcyBkYXRhDQoNCkRlcHJpdmF0aW9uXzIwMjNfQkRHX1JlcGxpY2F0aW9uLlJEYXRhIChEd29yc2NoYWssIDIwMjMpDQoNClRoZSBkZXBlbmRlbnQgdmFyaWFibGUgYW5hbHlzZWQgaXMgdGhlIGxvZ2dlZCBudW1iZXIgb2YgaGF0ZSBjcmltZSBwZXIgMTAway4gVGhpcyBpcyBhIG51bWVyaWMgdmFyaWFibGUgcmFuZ2luZyBiZXR3ZWVuIDAgKG5vIHJlY29yZGVkIGhhdGUgY3JpbWUpLCBhbmQgMTAuIEJlbGdpb2lvc28gZXQgYWwuIG9idGFpbmVkIHRoaXMgdmFyaWFibGUgYnkgZGl2aWRpbmcgdGhlIGN1bXVsYXRpdmUgbnVtYmVyIG9mIGhhdGUgY3JpbWVzIGJ5IExTT0EgcG9wdWxhdGlvbiBzaXplIChwZXIgMTAwaykgKEJlbGdpb2lvc28sIGV0IGFsLiwgMjAyMywgcC4gMTEpLiBBbGwgaGF0ZSBjcmltZSBkYXRhIHdhcyDigJhyZWNvcmRlZCBieSB0aGUgVUsgUG9saWNlIGZvciAyMDE14oCTMjAyMSBhbmQgcHJvdmlkZWQgYnkgdGhlIENyaW1lIEFuYWx5c2lzIFVuaXQgb2YgdGhlIEhvbWUgT2ZmaWNlIGZvbGxvd2luZyBhIEZyZWVkb20gb2YgSW5mb3JtYXRpb24gcmVxdWVzdCBieSB0aGUgYXV0aG9ycyAoRk9JIDY5MjQwKS7igJkgKEJlbGdpb2lvc28sIGV0IGFsLiwgMjAyMywgcC4gNCkNCg0KDQpUaGlzIGFsc28gaW5jbHVkZXMgdGhlIGZvbGxvd2luZyBkYXRhIHdoaWNoIGlzIGluY2x1ZGVkIGluIHRoZSBvcmlnaW5hbCBkYXRhc2V0Og0KDQpEZXByaXZhdGlvbiBkYXRhIOKAkyANCkRhdGEgZnJvbSB0aGUgRW5nbGlzaCBJbmRpY2VzIG9mIERlcHJpdmF0aW9uIDIwMTUgDQoNClRoaXMgcGFwZXIgdXRpbGlzZWQgMyBvZiB0aGVzZSB2YXJpYWJsZXM6IGluY29tZSBkZXByaXZhdGlvbiAoMC0wLjY1KSwgZWR1Y2F0aW9uIGRlcHJpdmF0aW9uICgwLTEwMCksIGFuZCBsaXZpbmcgZW52aXJvbm1lbnQgZGVwcml2YXRpb24gKDAtMTAwKS4gQWxsIHZhcmlhYmxlcyB3ZXJlIG1lYXN1cmVkIHdpdGggMCBiZWluZyBsb3dlc3QgbGV2ZWwgb2YgZGVwcml2YXRpb24uIA0KDQpEZW1vZ3JhcGhpYyBkYXRhIOKAkyANCkZyb20gdGhlIDIwMTEgVUsgQ2Vuc3VzIERhdGEgICAoT2ZmaWNlIGZvciBOYXRpb25hbCBTdGF0aXN0aWNzLCAyMDEyKQ0KVGhpcyBwYXBlciB1dGlsaXNlcyB0aGUgZm9sbG93aW5nIHZhcmlhYmxlczoNCuKAoglUb3RhbCBwb3B1bGF0aW9uIHNpemUgbG9nZ2VkIA0K4oCiCUF2ZXJhZ2UgYWdlIA0K4oCiCUxvbmcgdGVybSB1bmVtcGxveWVkIHBlcmNlbnRhZ2UgDQrigKIJUGVyY2VudGFnZSBvZiBDaHJpc3RpYW5zIA0K4oCiCVBlcmNlbnRhZ2Ugb2YgdXJiYW4gcG9wdWxhdGlvbiANCuKAoglQZXJjZW50YWdlIG9mIHBlb3BsZSBvZiBBcmFiIGV0aG5pY2l0eSANCuKAoglQZXJjZW50YWdlIG9mIHBlb3BsZSBvZiBCQU1FIGV0aG5pY2l0eSANCg0KVGhlIHBhcGVyIHdpbGwgdGhlbiB1c2UgYWRkaXRpb25hbCBkYXRhIGZyb20gdGhlIEVVIFJlZmVyZW5kdW0gcmVzdWx0cyAoVGhlIEVsZWN0b3JhbCBDb21taXNzaW9uLCAyMDIxKS4NCg0KVGhlIHZhcmlhYmxlIHVzZWQgaXMgdGhlIHBlcmNlbnRhZ2Ugb2Ygdm90ZXMgdG8gbGVhdmUgdGhlIEVVLCBtZWFzdXJlZCBmcm9tIDAlIHRvIDEwMCUuIFRoaXMgdmFyaWFibGUgaXMgbWVhc3VyZWQgYXQgdGhlIExvY2FsIEF1dGhvcml0eSBEaXN0cmljdCBMZXZlbCBhbmQgY29udGFpbnMgMzgyIG9ic2VydmF0aW9ucyBvZiAyMSB2YXJpYWJsZXMuDQoNCkluIG9yZGVyIHRvIHByZXNlbnQgZGF0YSBzcGF0aWFsbHkgdGhpcyBwYXBlciB1dGlsaXNlZCBhIHNoYXBlZmlsZSBvZiB0aGUgVUsgd2l0aCBhbGwgTEFEIGJvdW5kYXJpZXMuIFRoaXMgZGF0YXNldCB3YXMgaW1wb3J0ZWQgZnJvbSB0aGUgT3BlbiBHZW9ncmFwaHkgcG9ydGFsIHByb3ZpZGVkIGJ5IHRoZSBPZmZpY2Ugb2YgTmF0aW9uYWwgU3RhdGlzdGljcywgdW5kZXIgdGhlIGZvbGxvd2luZyBjb3B5cmlnaHQuDQogU291cmNlOiBPZmZpY2UgZm9yIE5hdGlvbmFsIFN0YXRpc3RpY3MgbGljZW5zZWQgdW5kZXIgdGhlIE9wZW4gR292ZXJubWVudCBMaWNlbmNlIHYuMy4wDQpDb250YWlucyBPUyBkYXRhIMKpIENyb3duIGNvcHlyaWdodCBhbmQgZGF0YWJhc2UgcmlnaHQgMjAwMQ0KDQoNCg0KDQpgYGAge3Igb3JpZ2luYWwgZGF0YSBkb3dubG9hZH0NCiMgT3JpZ2luYWwgZGF0YSBhbmQgYXNzaXN0aW5nIHNjcmlwdCBkb3dubG9hZA0KbG9hZChmaWxlID0gIkRhdGEvRGVwcml2YXRpb25fMjAyM19CREdfUmVwbGljYXRpb24uUkRhdGEiKQ0KDQpzb3VyY2UoIk9yaWdpbmFsIFNjcmlwdHMvaGVscGVycy5SIikNCmBgYA0KDQpgYGAge3Igb3JpZ2luYWwgZGF0YSBjbGVhbiwgaW5jbHVkZSA9IEZBTFNFfQ0KIyBPcmlnaW5hbCBkYXRhIGNsZWFuaW5nIHNjcmlwdCANCg0KbWFpbi5jb3ZhcmlhdGVzIDwtIGMoImxuX3BvcCIsICJhZ2VfbWVhbiIsICJ1bmVwbG95bWVudF9sb25ndGVybV9wZXJjdCIsICJyZWxpX2NocmlzdGlhbiIsICJ1cmJhbiIsICJldGhuX2FyYWJfcGVyY3QiLCAiZXRobl9iYW1lX3BlcmN0IiwgInBvbGljZS5mb3JjZS5uYW1lIikNCm1haW4ucHJlZGljdG9ycyA8LSBjKCJJbmNvbWUuU2NvcmUiLCAiTGl2aW5nLkVudmlyb25tZW50LlNjb3JlIiwgIkVkdWNhdGlvbi5TY29yZSIpDQptYWluLnByZWRpY3RvcnMuMTkgPC0gcGFzdGUwKG1haW4ucHJlZGljdG9ycywgIi4xOSIpOyBtYWluLnByZWRpY3RvcnMuMTkgPC0gYyhtYWluLnByZWRpY3RvcnMuMTksIHBhc3RlMChtYWluLnByZWRpY3RvcnMuMTksICIuc3BsYWcxLm1lYW4iKSkNCm1haW4ucHJlZGljdG9ycyA8LSBjKG1haW4ucHJlZGljdG9ycywgcGFzdGUwKG1haW4ucHJlZGljdG9ycywgIi5zcGxhZzEubWVhbiIpKQ0KYWxsLnJlbGV2YW50LnZhcnMgPC0gYyhtYWluLmNvdmFyaWF0ZXMsIG1haW4ucHJlZGljdG9ycykNCg0KDQoNCmRmNSA8LSBkZjQNCmNvbG5hbWVzKGRmNSkgPC0gZ3N1YigiaGNyaW1lc1xcLnRyYWluIiwgImhjcmltZXNcXC5jbGVhbmVkIiwgZ3N1YigiXFwuMTUiLCAiIiwgY29sbmFtZXMoZGY1KSkpDQpkZjUgPC0gZGY1W2NvbXBsZXRlLmNhc2VzKGRmNVssYyhhbGwucmVsZXZhbnQudmFycywgImhjcmltZXMuY2xlYW5lZC5wMTAway5sbiIpXSksXQ0KZGY1JG5hLjE5IDwtIGFzLm51bWVyaWMoIWNvbXBsZXRlLmNhc2VzKGRmNVssYyhhbGwucmVsZXZhbnQudmFycywgImhjcmltZXMudGVzdDIucDEwMGsubG4iKV0pKSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICANCg0KZGY1JGhjcmltZXMuY2xlYW5lZC5wMTAway5sbi56ZXJvLm9taXQgPC0gaWZlbHNlKGRmNSRoY3JpbWVzLmNsZWFuZWQucDEwMGsubG49PTAsIE5BLCBkZjUkaGNyaW1lcy5jbGVhbmVkLnAxMDBrLmxuKQ0KY29sbmFtZXMoZGYzLnNoYXBlcykgPC0gZ3N1YigiXFwuMTUiLCAiIiwgY29sbmFtZXMoZGYzLnNoYXBlcykpDQoNCmBgYA0KDQpgYGAge3IgbmV3IGRhdGEgZG93bmxvYWR9DQojIENyZWF0aW5nIGEgbmV3IGRhdGFzZXQgd2hpY2ggb21pdHMgZGF0YSBmcm9tIFNjb3RsYW5kLCBXYWxlcyBhbmQgR2licmFsdGFyLiBUaGlzIGRhdGEgaXMgbm90IG5lZWRlZCBhcyB0aGUgb3JpZ2luYWwgZGF0YXNldCBjb250YWlucyBubyBkYXRhIG9uIHRoZXNlIHBsYWNlcy4gDQoNCmV1X3JlZmVyZW5kdW1fZGF0YSA8LSByZWFkX2NzdigiRGF0YS9FVS1yZWZlcmVuZHVtLXJlc3VsdC1kYXRhLmNzdiIpDQoNCg0KZXVfcmVmZXJlbmR1bV9kYXRhXzEgPC0gc3Vic2V0KGV1X3JlZmVyZW5kdW1fZGF0YSwgIShpZCAlaW4lIGMoMzgxLCAxNTMsIDE1NSwgMTU3LCAxNTksIDE2MCwgMTc5LCAxNjIsIDE2MywgMTY1LCAxNjYsIDE2NywgMTY4LCAxNjksIDE3MSwgMTcyLCAxNTIsIDE3NCwgMTc1LCAxNzYsIDE3NywgMTQ4LCAxNDksIDE1MSwgMTYxLCAxNzMsIDE1NCwgMTc4LCAxNTAsIDE1NiwgMTcwLCAxNTgsIDE2NCwgMzgyLCAxMjYsIDEyNywgMTI4LCAxMjksIDEzMCwgMTMxLCAxMzMsIDEzNCwgMTM1LCAxMzYsIDEzNywgMTM4LCAxMzksIDE0NywgMTQwLAkxNDIsIDE0MywJMTQ0LCAxNDUsCTE0NiwgMTMyLAkxNDEpKSkNCmBgYA0KDQpgYGAge3IgY29sdW1uIHJlbmFtZSwgaW5jbHVkZSA9IEZBTFNFfQ0KIyBIb21vZ2VuaXNpbmcgdGhlIG5hbWUgb2YgdGhlIGNvbHVtbiB3aGljaCBpbmRpY2F0ZXMgTG9jYWwgQXV0aG9yaXR5IERpc3RyaWN0IGNvZGUgZm9yIG1lcmdpbmcNCg0KY29sbmFtZXMoZXVfcmVmZXJlbmR1bV9kYXRhKVtjb2xuYW1lcyhldV9yZWZlcmVuZHVtX2RhdGEpID09ICdBcmVhX0NvZGUnXSA8LSAnbGFkJw0KDQpjb2xuYW1lcyhldV9yZWZlcmVuZHVtX2RhdGFfMSlbY29sbmFtZXMoZXVfcmVmZXJlbmR1bV9kYXRhXzEpID09ICdBcmVhX0NvZGUnXSA8LSAnbGFkJw0KYGBgDQoNCmBgYCB7ciBkYXRhIG1lcmdlfQ0KIyBNZXJnaW5nIHRoZSBvcmlnaW5hbCBkYXRhc2V0IHdpdGggdGhlIEVVIHJlZmVyZW5kdW0gZGF0YXNldA0KDQptZXJnZWRfZGF0YV9ldSA8LSBtZXJnZShkZjUsIGV1X3JlZmVyZW5kdW1fZGF0YSwgYnkgPSAibGFkIikNCg0KYGBgDQoNCmBgYCB7ciBzaGFwZWZpbGUgZGF0YSBkb3dubG9hZH0NCiMgRG93bmxvYWRpbmcgdGhlIHNoYXBlZmlsZSBhbmQgbWVyZ2luZyB3aXRoIHJlZmVybmR1bSBkYXRhDQpsYWRfc2hwIDwtIHN0X3JlYWQoIkRhdGEvU2hhcGVmaWxlL0xBRF9ERUNfMjAxNl9HQl9CR0NfVjIuc2hwIikNCg0KY29sbmFtZXMobGFkX3NocClbY29sbmFtZXMobGFkX3NocCkgPT0gJ0xBRDE2Q0QnXSA8LSAnbGFkJw0KDQpldV9zaGFwZWZpbGVfZGF0YSA8LSBtZXJnZShsYWRfc2hwLCBldV9yZWZlcmVuZHVtX2RhdGEsIGJ5ID0gImxhZCIpDQoNCmBgYA0KDQpgYGAge3Igc2hhcGVmaWxlIGZvciBtYXBwaW5nLCBpbmNsdWRlID0gRkFMU0V9DQoNCmhjcmltZV9kYXRhX2Zvcl9tYXAgPC0gbWVyZ2VkX2RhdGFfZXVbICwgYygnaGNyaW1lcy5jbGVhbmVkLnAxMDBrLmxuJywgJ2xhZCcsICdQY3RfTGVhdmUnKV0NCg0KDQpoY3JpbWVfc2hhcGVmaWxlX2RhdGEgPC0gbWVyZ2UobGFkX3NocCwgaGNyaW1lX2RhdGFfZm9yX21hcCwgYnkgPSAibGFkIikNCg0KYGBgDQoNCiMjIE1hcHMgey50YWJzZXQgLnRhYnNldC1waWxsc30NCg0KIyMjIEJyZXhpdCBWb3RlIFByb3BvcnRpb24gTWFwDQoNCmBgYCB7ciBicmV4aXQgdm90ZSBtYXB9DQoNCmdncGxvdChoY3JpbWVfc2hhcGVmaWxlX2RhdGEpICsNCiAgZ2VvbV9zZihhZXMoZmlsbCA9IFBjdF9MZWF2ZSkpICsNCiAgc2NhbGVfZmlsbF92aXJpZGlzX2MoKSArDQogIGxhYnModGl0bGUgPSAiRmlndXJlIDE6IFBlcmNlbnRhZ2Ugb2YgTGVhdmUgVm90ZXMgaW4gdGhlIDIwMTYgRVUgUmVmZXJlbmR1bSBpbiB0aGUgVUsiLA0KICAgICAgIGZpbGwgPSAiUGVyY2VudGFnZSBvZiBMZWF2ZSBWb3RlcyIsDQogICAgICAgY2FwdGlvbiA9ICIgU3BhdGlhbCBkYXRhIHNvdXJjZTogT2ZmaWNlIGZvciBOYXRpb25hbCBTdGF0aXN0aWNzIGxpY2Vuc2VkIHVuZGVyIHRoZSBPcGVuIA0KICAgICAgIEdvdmVybm1lbnQgTGljZW5jZSB2LjMuMC4gQ29udGFpbnMgT1MgZGF0YSDCqSBDcm93biBjb3B5cmlnaHQgYW5kIGRhdGFiYXNlIA0KICAgICAgIHJpZ2h0IDIwMDEiKQ0KDQpgYGANCg0KIyMjIEhhdGUgQ3JpbWUgUmF0ZSBNYXAgKGxvZ2dlZCkNCg0KYGBgIHtyIGhjcmltZSBwcm9wb3J0aW9uIG1hcH0NCg0KZ2dwbG90KGhjcmltZV9zaGFwZWZpbGVfZGF0YSkgKw0KICBnZW9tX3NmKGFlcyhmaWxsID0gaGNyaW1lcy5jbGVhbmVkLnAxMDBrLmxuKSkgKw0KICBzY2FsZV9maWxsX3ZpcmlkaXNfYygpICsNCiAgbGFicyh0aXRsZSA9ICJGaWd1cmUgMjogTG9nZ2VkIG51bWJlciBvZiBIYXRlIENyaW1lcyBwZXIgMTAwayAiLA0KICAgICAgIGZpbGwgPSAiTG9nZ2VkIG51bWJlciBvZiBIYXRlIENyaW1lcyIsDQogICAgICAgY2FwdGlvbiA9ICIgU3BhdGlhbCBkYXRhIHNvdXJjZTogT2ZmaWNlIGZvciBOYXRpb25hbCBTdGF0aXN0aWNzIGxpY2Vuc2VkIHVuZGVyIHRoZSBPcGVuIA0KICAgICAgIEdvdmVybm1lbnQgTGljZW5jZSB2LjMuMC4gQ29udGFpbnMgT1MgZGF0YSDCqSBDcm93biBjb3B5cmlnaHQgYW5kIGRhdGFiYXNlIA0KICAgICAgIHJpZ2h0IDIwMDEiKQ0KDQpgYGANCg0KIyMgU3VtbWFyeSBTdGF0aXN0aWNzIHsudGFic2V0IC50YWJzZXQtcGlsbHN9DQoNCiMjIyBIaXN0b2dyYW0gb2YgTGVhdmUgUHJvcG9ydGlvbiBieSBSZWdpb24NCg0KYGBgIHtyIGhpc3RvZ3JhbSBtZWFuIGxpbmUsIGluY2x1ZGUgPSAgRkFMU0V9DQoNCmhpc3RfZmFjZXRfbWVhbl9saW5lIDwtIGRkcGx5KG1lcmdlZF9kYXRhX2V1LCAiUmVnaW9uIiwgc3VtbWFyaXNlLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdycC5tZWFuID0gbWVhbihQY3RfTGVhdmUpKQ0KYGBgDQoNCmBgYCB7ciBoaXN0b2dyYW0gb2YgbGVhdmUgcHJvcG9ydGlvbn0NCg0KZ2dwbG90KG1lcmdlZF9kYXRhX2V1KSArDQogIGFlcyh4ID0gUGN0X0xlYXZlKSArDQogIGdlb21faGlzdG9ncmFtKGJpbndpZHRoID0gMiwgY29sb3VyID0gImJsYWNrIiwgZmlsbCA9ICJ3aGl0ZSIpICsNCiAgZmFjZXRfd3JhcChSZWdpb24gfiAuKSArDQogIGdlb21fdmxpbmUoZGF0YSA9IGhpc3RfZmFjZXRfbWVhbl9saW5lLCBhZXMoeGludGVyY2VwdCA9IGdycC5tZWFuKSwgY29sb3IgPSAicmVkIiwNCiAgICAgICAgICAgICBsaW5ldHlwZSA9ICJkYXNoZWQiKSArDQogIGxhYnModGl0bGUgPSAiRmlndXJlIDM6IEhpc3RvZ3JhbSBvZiBMZWF2ZSBQZXJjZW50IFZvdGVzIGJ5IFJlZ2lvbiIsDQogICAgICAgeCA9ICJQZXJjZW50IExlYXZlIFZvdGUiLA0KICAgICAgIHkgPSAiTnVtYmVyIG9mIExTT0EncyIpIA0KDQpgYGANCg0KIyMjIEJveHBsb3Qgb2YgTGVhdmUgUHJvcG9ydGlvbiBieSBSZWdpb24NCg0KYGBgIHtyIGJveHBsb3Qgb2YgbGVhdmUgcHJvcG9ydGlvbn0NCg0KZ2dwbG90KG1lcmdlZF9kYXRhX2V1KSArDQogIGFlcyh4ID0gUGN0X0xlYXZlKSArDQogIGdlb21fYm94cGxvdCgpICsNCiAgZmFjZXRfZ3JpZChSZWdpb24gfiAuKSArDQogIHRoZW1lKHN0cmlwLnRleHQueS5yaWdodCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDApKSArDQogIGxhYnModGl0bGUgPSAiRmlndXJlIDQ6IEJveHBsb3Qgb2YgTGVhdmUgUGVyY2VudCBWb3RlcyBieSBSZWdpb24iLA0KICAgICAgIHggPSAiUGVyY2VudCBMZWF2ZSBWb3RlIikgDQoNCmBgYA0KDQojIyMgQm94cGxvdCBvZiBIYXRlIENyaW1lIFJhdGUgYnkgUmVnaW9uDQoNCmBgYCB7ciBib3hwbG90IG9mIGhhdGUgY3JpbWUgcmF0ZX0NCg0KZ2dwbG90KG1lcmdlZF9kYXRhX2V1KSArDQogIGFlcyhoY3JpbWVzLmNsZWFuZWQucDEwMGsubG4pICsNCiAgZ2VvbV9ib3hwbG90KCkgKw0KICBmYWNldF9ncmlkKFJlZ2lvbiB+IC4pICsNCiAgdGhlbWUoc3RyaXAudGV4dC55LnJpZ2h0ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gMCkpICsNCiAgbGFicyh0aXRsZSA9ICJGaWd1cmUgNTogQm94cGxvdCBvZiBMb2dnZWQgSGF0ZSBDcmltZXMgYnkgUmVnaW9uIiwNCiAgICAgICB4ID0gIkxvZ2dlZCBIYXRlIENyaW1lIHBlciAxMDBrIikgDQoNCmBgYA0KDQojIyAyLjIuIE1ldGhvZHMgDQoNCkluIHRoZSBvcmlnaW5hbCBwYXBlciBhIGxpbmVhciByZWdyZXNzaW9uIHRlc3Qgd2FzIHBlcmZvcm1lZCB0byBjcmVhdGUgNyBtb2RlbHMgd2l0aCBoYXRlIGNyaW1lIGxvZ2dlZCBwZXIgMTAwayBhcyB0aGUgZGVwZW5kZW50IHZhcmlhYmxlIHdhcyBhZGRlZC4gVGhpcyBwYXBlciB3aWxsIGFsc28gZm9sbG93IHRoaXMgbWV0aG9kLCB3aXRoIHRoZSBhZGRpdGlvbiBvZiBhbiA4dGggbW9kZWwgaW4gYm90aCB0aGUgcmVwcm9kdWN0aW9uIG9mIHRoZSBvcmlnaW5hbCBtb2RlbCBhbmQgaW4gdGhlIG1vZGVscyB3aXRoIHRoZSBhZGRpdGlvbiBvZiBCcmV4aXQgbGVhdmUgdm90ZSBkYXRhLiBQcmVkaWN0b3IgdmFyaWFibGVzIGFyZSBtb2RlbGVkIGFzIGZvbGxvd3M6DQoNCioJMSDigJMgRGVtb2dyYXBoaWNzDQoqCTIg4oCTIEluY29tZSBkZXByaXZhdGlvbiBzY29yZSANCioJMyDigJMgTGl2aW5nIGVudmlyb25tZW50IGRlcHJpdmF0aW9uIHNjb3JlDQoqCTQg4oCTIEVkdWNhdGlvbiBkZXByaXZhdGlvbiBzY29yZQ0KKgk1IOKAkyBJbmNvbWUgYW5kIG5laWdoYm91cmluZyBMU09BIGRlcHJpdmF0aW9uIHNjb3JlIA0KKgk2IOKAkyBMaXZpbmcgZW52aXJvbm1lbnQgYW5kIG5laWdoYm91cmluZyBMU09BIGRlcHJpdmF0aW9uIHNjb3JlIA0KKgk3IOKAkyBFZHVjYXRpb24gYW5kIG5laWdoYm91cmluZyBMU09BIGRlcHJpdmF0aW9uIHNjb3JlIA0KKiA4IC0gQWxsIHByZWRpY3RvciB2YXJpYWJsZXMNCg0KVGhpcyBwYXBlciB3aWxsIHV0aWxpc2UgYSByYW5kb20gaW50ZXJjZXB0IG11bHRpbGV2ZWwgbW9kZWwuIFRoaXMgbWV0aG9kIHdpbGwgYmUgYmVzdCBhcyB0aGUgZGF0YSBpcyBjYXB0dXJlZCBhdCAyIGxldmVscy4gTG9jYWwgTGV2ZWwgU3VwZXIgT3V0cHV0IEFyZWEgKExTT0EpIGZvciBoYXRlIGNyaW1lIHN0YXRpc3RpY3MsIElvRCBhbmQgZGVtb2dyYXBoaWMgZGF0YSwgYW5kIGF0IExvY2FsIEF1dGhvcml0eSBEaXN0cmljdCAoTEFEKSBsZXZlbCBmb3IgQnJleGl0IHJlZmVyZW5kdW0gcmVzdWx0cy4gQ29tcGFyaW5nIHRoZSByZXByb2R1Y2VkIG1vZGVsIG9uIGEgc2luZ2xlIGFuZCBtdWx0aWxldmVsIHdpbGwgZW5zdXJlIGFueSBjaGFuZ2VzIGNhdXNlZCBieSB0aGlzIGNoYW5nZSB3aWxsIGJlIG5vdGVkLg0KDQpUaGUgTFNPQSBhbmQgTEFEIGRhdGEgYXJlIG5vdCBpbmRlcGVuZGVudCBvZiBvbmUgYW5vdGhlciwgYXMgTFNPQeKAmXMgYW5kIG5lc3RlZCB3aXRoaW4gTEFE4oCZcy4gQSBtdWx0aS1sZXZlbCBtb2RlbCBhbGxvd3MgZm9yIHJlZ3Jlc3Npb24gYW5hbHlzaXMgdG8gYmUgcGVyZm9ybWVkIG9uIGJvdGggdGhlIGluZGl2aWR1YWwgKExTT0EpIGFuZCBncm91cCAoTEFEKSBsZXZlbCwgdGFraW5nIGludG8gYWNjb3VudCB0aGF0IHRoZSBCcmV4aXQgcmVmZXJlbmR1bSBkYXRhIHdpbGwgbm90IGNoYW5nZSBiZXR3ZWVuIExTT0HigJlzIGluIGEgc2luZ2xlIExBRCwgYnV0IGRvZXMgY2hhbmdlIGJldHdlZW4gTEFE4oCZcyAoR29yYXJkLCAyMDAzKS4gUnVubmluZyBhIG51bGwgbW9kZWwgY29udGFpbmluZyBqdXN0IGhhdGUgY3JpbWUgcHJvcG9ydGlvbiBjYWx1Y2F0ZXMgYW4gSW50cmEtQ2xhc3MgQ29ycmVsYXRpb24gb2YgMC4zNiwgaW5kaWNhdGluZyAzNiUgb2YgdmFyaWFuY2UgaW4gaGF0ZSBjcmltZSBwcm9wb3J0aW9uIG9jY3VycyB3aXRoaW4gTFNPQSdzIGluIGFuIExBRCwgdGhlcmVmb3JlIDY0JSBvY2N1cnMgYmV0d2VlbiBMQUQuIFN1Y2ggYSBoaWdoIGJldHdlZW4tY2xhc3MgY29ycmVsYXRpb24gaW5kaWNhdGVzIHRoYXQgdXNpbmcgYSBzaW5nbGUtbGV2ZWwgbW9kZWwgd291bGQgbm90IGFjY291bnQgZm9yIHRoaXMgc2lnbmlmaWNhbnQgYW1vdW50IG9mIHZhcmlhbmNlLiANCg0KDQpgYGAge3IgbnVsbCBtb2RlbH0NCmhjcmltZV9tbG1vZGVsX251bGwgPC0gbG1lcihoY3JpbWVzLmNsZWFuZWQucDEwMGsubG4gfiAgKDEgfCBpZCksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRhdGEgPSBtZXJnZWRfZGF0YV9ldSkNCg0KDQp0YWJfbW9kZWwoaGNyaW1lX21sbW9kZWxfbnVsbCwgZHYubGFiZWxzID0gJ0xvZ2dlZCBIYXRlIENyaW1lIHBlciAxMDBrJywgdGl0bGUgPSAnTXVsdGlsZXZlbCBNb2RlbCBvZiBMb2dnZWQgSGF0ZSBDcmltZScpDQpgYGANCg0KDQpgYGAge3IgYnJleGl0IGhhdGUgY3JpbWUgbW9kZWwsIGluY2x1ZGUgPSBGQUxTRX0NCg0KaGNyaW1lX2JyZXhpdF9tbG1vZGVsIDwtIGxtZXIoaGNyaW1lcy5jbGVhbmVkLnAxMDBrLmxuIH4gUGN0X0xlYXZlICsgKDEgfCBpZCksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkYXRhID0gbWVyZ2VkX2RhdGFfZXUpDQoNCmNvZWZfbWxtIDwtIGNvZWYoaGNyaW1lX2JyZXhpdF9tbG1vZGVsKSRpZA0KDQpgYGANCg0KQSBjb2VmZmljaWVudCBhbmFseXNpcyBvZiB0aGUgZmlyc3QgbXVsdGlsZXZlbCBtb2RlbCB3aXRoIGp1c3QgbGVhdmUgdm90ZSBwZXJjZW50IGFzIGEgcHJlZGljdG9yIGRlbW9uc3RyYXRlcyB3aHkgYSByYW5kb20gaW50ZXJjZXB0IGJ1dCBub3QgYSByYW5kb20gc2xvcGVzIG1vZGVsIGlzIG5lZWRlZCBoZXJlLiBUaGUgaW50ZXJjZXB0IG9mIGVhY2ggTEFEIGlzIGRpZmZlcmVudCwgYnV0IHRoZSBzbG9wZXMgYXJlIGFsbCB0aGUgc2FtZSBhdCAtMC4wMzQwNzUyOS4gVGhpcyBpbmRpY2F0ZXMgdGhhdCB0aGUgaGF0ZSBjcmltZSByYXRlIGNhbiBiZSBkaWZmZXJlbnQgZm9yIGV2ZXJ5IExBRCwgYnV0IHRoZSBlZmZlY3QgdGhlIEJyZXhpdCBsZWF2ZSBwcm9wb3J0aW9uIGhhcyBvbiB0aGUgaGF0ZSBjcmltZSBpbiBlYWNoIExBRCBpcyB0aGUgc2FtZS4gDQoNCmBgYCB7ciBtb2RlbCBjb2VmZmljaWVudHN9DQoNCmhlYWQoY29lZl9tbG0sIDUpDQoNCmBgYA0KDQpDb3JyZWxhdGlvbiBjb2VmZmljaWVudCBhbmFseXNpcyB3aWxsIHRlc3Qgd2hldGhlciB0aGUgcGVyY2VudCBsZWF2ZSB2b3RlIHZhcmlhYmxlIGlzIHRvbyBjbG9zZWx5IGNvcnJlbGF0ZWQgd2l0aCBvdGhlciBwcmVkaWN0b3IgdmFyaWFibGVzIHRvIG1vZGVsIHN1Y2Nlc3NmdWxseS4gQWx0aG91Z2ggdGhlcmUgaXMgc29tZSBjb3JyZWxhdGlvbiwgd2hpY2ggaXMgdG8gYmUgYW50aWNpcGF0ZWQsIHRoZXJlIGlzIG5vdCBlbm91Z2ggdG8gaW5kaWNhdGUgYW55IG11bHRpY29sbGluZWFyaXR5Lg0KDQpgYGAge3IgY29ycmVsYXRpb24gY29lZiBvZiBicmV4aXQgdm90ZSBhbmQgZGVwcml2YXRpb24gdmFyaWFibGVzLCBpbmNsdWRlID0gRkFMU0V9DQpjb3JfY29lZl90YWJsZV9icmV4aXRfZGVwcml2YXRpb24gPC0gDQptZXJnZWRfZGF0YV9ldSAlPiUNCiAgYXMuZGF0YS5mcmFtZSgpICU+JQ0KICBzZWxlY3QoUGN0X0xlYXZlLCBJbmNvbWUuU2NvcmUsIEVkdWNhdGlvbi5TY29yZSwgTGl2aW5nLkVudmlyb25tZW50LlNjb3JlKSAlPiUNCiAgYXMubWF0cml4KCkgJT4lDQogIGNvcigpDQoNCnJvd25hbWVzKGNvcl9jb2VmX3RhYmxlX2JyZXhpdF9kZXByaXZhdGlvbikgPC0gIGMoJ0xlYXZlIFZvdGUgUGVyY2VudCcsICdJbmNvbWUgRGVwcml2YXRpb24nLCAnRWR1Y2F0aW9uIERlcHJpdmF0aW9uJywgJ0xpdmluZyBFbnZyaW9ubWVudCBEZXByaXZhdGlvbicpDQpgYGANCg0KYGBgIHtyIGJyZXhpdCB2b3RlIGRlcHJpdmF0aW9uIHZhcmlhYmxlcyB0YWJsZX0NCmthYmxlKGNvcl9jb2VmX3RhYmxlX2JyZXhpdF9kZXByaXZhdGlvbiwgY29sLm5hbWVzID0gYygnTGVhdmUgVm90ZSBQZXJjZW50JywgJ0luY29tZSBEZXByaXZhdGlvbicsICdFZHVjYXRpb24gRGVwcml2YXRpb24nLCAnTGl2aW5nIEVudnJpb25tZW50IERlcHJpdmF0aW9uJykpDQpgYGANCg0KYGBgIHtyIGNvcnJlbGF0aW9uIGNvZWYgb2YgYnJleGl0IHZvdGUgYW5kIGRlbW9ncmFwaGljIHZhcmlhYmxlcywgaW5jbHVkZSA9IEZBTFNFfQ0KDQpjb3JfY29lZl90YWJsZV9icmV4aXRfZGVtb2dyYXBoaWNzIDwtIA0KICBtZXJnZWRfZGF0YV9ldSAlPiUNCiAgYXMuZGF0YS5mcmFtZSgpICU+JQ0KICBzZWxlY3QoUGN0X0xlYXZlLCBsbl9wb3AgLCBhZ2VfbWVhbiAsIA0KICAgICAgICAgICB1bmVwbG95bWVudF9sb25ndGVybV9wZXJjdCAsIHJlbGlfY2hyaXN0aWFuICwgdXJiYW4gLCANCiAgICAgICAgICAgZXRobl9hcmFiX3BlcmN0ICwgZXRobl9iYW1lX3BlcmN0KSAlPiUNCiAgYXMubWF0cml4KCkgJT4lDQogIGNvcigpDQoNCnJvd25hbWVzKGNvcl9jb2VmX3RhYmxlX2JyZXhpdF9kZW1vZ3JhcGhpY3MpIDwtICBjKCdMZWF2ZSBWb3RlIFBlcmNlbnQnLCAnTG9nZ2VkIFBvcHVsYXRpb24nLCAnTWVhbiBBZ2UnLCAnTG9uZ3Rlcm0gVW5lbXBsb3llZCcsICdDaHJpc3RpYW4nLCAnVXJiYW4nLCAnRXRoaWMgQXJhYicsICdFdGhuaWMgQkFNRScpDQpgYGANCg0KYGBgIHtyIGJyZXhpdCB2b3RlIGRtb2dyYXBoaWNzIHZhcmlhYmxlcyB0YWJsZX0NCmthYmxlKGNvcl9jb2VmX3RhYmxlX2JyZXhpdF9kZW1vZ3JhcGhpY3MsIGNvbC5uYW1lcyA9IGMoJ0xlYXZlIFZvdGUgUGVyY2VudCcsICdMb2dnZWQgUG9wdWxhdGlvbicsICdNZWFuIEFnZScsICdMb25ndGVybSBVbmVtcGxveWVkJywgJ0NocmlzdGlhbicsICdVcmJhbicsICdFdGhpYyBBcmFiJywgJ0V0aG5pYyBCQU1FJykpDQpgYGANCg0KDQojIyAzLiBSZXN1bHRzIA0KDQpgYGAge3IganVzdCBicmV4aXQgaGF0ZSBjcmltZSBtbG0sIGluY2x1ZGUgPSBGQUxTRX0NCmhjcmltZV9icmV4aXRfbWxtb2RlbCA8LSBsbWVyKGhjcmltZXMuY2xlYW5lZC5wMTAway5sbiB+IFBjdF9MZWF2ZSArICgxIHwgaWQpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGF0YSA9IG1lcmdlZF9kYXRhX2V1KQ0KDQpoY3JpbWVfYnJleGl0X21sbW9kZWxfdGFibGUgPC0gDQogIHRhYl9tb2RlbChoY3JpbWVfYnJleGl0X21sbW9kZWwsIHByZWQubGFiZWxzID0gbGlzdCgiSW50ZXJjZXB0IiwgIkxlYXZlIFZvdGUgUGVyY2VudCIpLA0KICAgICAgICAgIHRpdGxlID0gIkxpbmVhciBSZWdyZXNzaW9uIG9mIExlYXZlIFZvdGUgUGVyY2VudCAoTEFEKSBvbiANCiAgICAgICAgICBMb2dnZWQgSGF0ZSBDcmltZSAoTFNPQSkiLA0KICAgICAgICAgIGR2LmxhYmVscyA9ICJMb2dnZWQgSGF0ZSBDcmltZSBwZXIgMTAwayIpDQpgYGANCg0KYGBge3IgYnJleGl0IGhhdGUgY3JpbWUgbWxtIHRhYmxlfQ0KaGNyaW1lX2JyZXhpdF9tbG1vZGVsX3RhYmxlDQpgYGANCg0KIyANClRlc3RpbmcgdGhlIGVmZmVjdCB0aGUgQnJleGl0IGxlYXZlIHByb3BvcnRpb24gaGFzIG9uIGhhdGUgY3JpbWUgd2l0aCBubyBvdGhlciBwcmVkaWN0b3IgdmFyaWFibGVzLCBpdCBhcHBlYXJzIHRoYXQgdGhlcmUgaXMgYSBzbGlnaHQgaW52ZXJzZSByZWxhdGlvbnNoaXAgdG8gd2hhdCB3YXMgZXhwZWN0ZWQuIEEgdmVyeSBzbGlnaHQgbmVnYXRpdmUgY29ycmVsYXRpb24gc3VnZ2VzdHMgYXJlYXMgd2l0aCBhIGxvd2VyIEJyZXhpdCBsZWF2ZSB2b3RlIHByb3BvcnRpb24gaGFkIGxlc3MgaGF0ZSBjcmltZXMuIEFsdGhvdWdoIHRoaXMgZWZmZWN0IGlzIHNpZ25pZmljYW50IHRoZSBmaXhlZCBlZmZlY3RzIGNhbGN1bGF0aW9uIG9mIDAuMDMzIGV4cGxhaW5zIG9ubHkgMy4zJSBvZiB2YXJpYW5jZSwgd2hlcmVhcyB0aGUgaW5jbHVzaW9uIG9mIHJhbmRvbSBlZmZlY3RzIGV4cGxhaW5zIDM1LjglLCBzdWdnZXN0aW5nIG90aGVyIGZhY3RvcnMgYXQgTEFEIGxldmVsIHBsYXkgYSBzaWduaWZpY2FudCByb2xlLg0KDQojIyAzLjEgLSBDb21wYXJpbmcgc2luZ2xlIGFuZCBtdWx0aSBsZXZlbCBvcmlnaW5hbCBtb2RlbCB7LnRhYnNldCAudGFic2V0LXBpbGxzfQ0KDQojIyMgUmVwcm9kdWNlZCBNb2RlbCAtIERlcHJpdmF0aW9uIGFuZCBEZW1vZ3JhcGhpY3Mgb24gSGF0ZSBDcmltZQ0KDQpgYGAge3Igb3JpZ2luYWwgbW9kZWwgZm9ybXVsYSwgaW5jbHVkZSA9IEZBTFNFfQ0KcmVwcm9fZm9ybXVsYSA8LSBmb3JtdWxhKGhjcmltZXMuY2xlYW5lZC5wMTAway5sbiB+IGxuX3BvcCArIGFnZV9tZWFuICsgdW5lcGxveW1lbnRfbG9uZ3Rlcm1fcGVyY3QgKyByZWxpX2NocmlzdGlhbiArIHVyYmFuICsgZXRobl9hcmFiX3BlcmN0ICsgZXRobl9iYW1lX3BlcmN0ICsgcG9saWNlLmZvcmNlLm5hbWUsIG1lcmdlZF9kYXRhX2V1KQ0KYGBgDQoNCmBgYCB7ciBvcmlnaW5hbCBtb2RlbHMsIGluY2x1ZGUgPSBGQUxTRX0NCnJlcHJvX21vZGVsXzEgPC0gbG0ocmVwcm9fZm9ybXVsYSwgZGY1KQ0KDQpyZXByb19tb2RlbF8yIDwtIGxtKHVwZGF0ZShyZXByb19mb3JtdWxhLCB+IEluY29tZS5TY29yZSksIGRmNSkNCg0KcmVwcm9fbW9kZWxfMyA8LSBsbSh1cGRhdGUocmVwcm9fZm9ybXVsYSwgfiBMaXZpbmcuRW52aXJvbm1lbnQuU2NvcmUpLCBkZjUpDQoNCnJlcHJvX21vZGVsXzQgPC0gbG0odXBkYXRlKHJlcHJvX2Zvcm11bGEsIH4gRWR1Y2F0aW9uLlNjb3JlKSwgZGY1KQ0KDQpyZXByb19tb2RlbF81IDwtIGxtKHVwZGF0ZShyZXByb19mb3JtdWxhLCB+IEluY29tZS5TY29yZSArIEluY29tZS5TY29yZS5zcGxhZzEubWVhbiArIC4pLCBkZjUpDQoNCnJlcHJvX21vZGVsXzYgPC0gbG0odXBkYXRlKHJlcHJvX2Zvcm11bGEsIH4gTGl2aW5nLkVudmlyb25tZW50LlNjb3JlICsgTGl2aW5nLkVudmlyb25tZW50LlNjb3JlLnNwbGFnMS5tZWFuICsgLiksIGRmNSkNCg0KcmVwcm9fbW9kZWxfNyA8LSBsbSh1cGRhdGUocmVwcm9fZm9ybXVsYSwgfiBFZHVjYXRpb24uU2NvcmUgKyBFZHVjYXRpb24uU2NvcmUuc3BsYWcxLm1lYW4gKyAuICksIGRmNSkNCg0KcmVwcm9fbW9kZWxfOCA8LSBsbSh1cGRhdGUocmVwcm9fZm9ybXVsYSwgfiBJbmNvbWUuU2NvcmUgKyBJbmNvbWUuU2NvcmUuc3BsYWcxLm1lYW4gKw0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICBMaXZpbmcuRW52aXJvbm1lbnQuU2NvcmUgKyANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgTGl2aW5nLkVudmlyb25tZW50LlNjb3JlLnNwbGFnMS5tZWFuICsNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgRWR1Y2F0aW9uLlNjb3JlICsgRWR1Y2F0aW9uLlNjb3JlLnNwbGFnMS5tZWFuICsgLiApLCBkZjUpDQoNCmBgYA0KDQpgYGAge3Igb3JpZ2luYWwgbW9kZWwgdGFibGUgMiwgaW5jbHVkZSA9IEZBTFNFfQ0KDQpmdWxsX3JlcHJvZHVjZWRfcmVncmVzc2lvbl90YWJsZSA8LSANCiAgdGFiX21vZGVsKHJlcHJvX21vZGVsXzEsIHJlcHJvX21vZGVsXzIsIHJlcHJvX21vZGVsXzMsIHJlcHJvX21vZGVsXzQsIHJlcHJvX21vZGVsXzUsIA0KICAgICAgICAgIHJlcHJvX21vZGVsXzYsIHJlcHJvX21vZGVsXzcsIHJlcHJvX21vZGVsXzgsIGRpZ2l0cyA9IDMsIGRyb3AgPSAgJ3BvbGljZS5mb3JjZS5uYW1lJywgDQogICAgICAgICBzaG93LmNpID0gRkFMU0UsIHNob3cuaW50ZXJjZXB0ID0gVFJVRSwgcC5zdHlsZSA9ICdudW1lcmljJywNCiAgICAgICAgICBkdi5sYWJlbHMgPSBsaXN0KCcxJywgJzInLCAnMycsICc0JywgJzUnLCAnNicsICc3JywgJzgnKSwNCiAgICAgICAgICBwcmVkLmxhYmVscyA9IGxpc3QoJ0ludGVyY2VwdCcsICdQb3B1bGF0aW9uIFNpemUgKGxvZyknLCAnTWVhbiBBZ2UnLCAnVW5lbXBsb3ltZW50IFBlcmNlbnRhZ2UnLA0KICAgICAgICAgICdDaHJpc3RpYW4gUmVsaWdpb24gUGVyY2VudGFnZScsICdVcmJhbicsICdBcmFiIEV0aG5pY2l0eSBQZXJjZW50YWdlJywgDQogICAgICAgICAgJ0JBTUUgUGVyY2VudGFnZScsICdJbmNvbWUgRGVwcml2YXRpb24nLCAnTGl2aW5nIEVudnJpb25tZW50IERlcHJpdmF0aW9uJywNCiAgICAgICAgICAnRWR1Y2F0aW9uIERlcHJpdmF0aW9uJywgJ05laWdoYm91ciBJbmNvbWUgRGVwcml2YXRpb24nLCANCiAgICAgICAgICAnTmVpZ2hib3VyIExpdmluZyBFbnZyaW9ubWVudCBEZXByaXZhdGlvbicsICdOZWlnaGJvdXIgRWR1Y2F0aW9uIERlcHJpdmF0aW9uJyksDQogICAgICAgICAgdGl0bGUgPSAnVGFibGUgMjogTGluZWFyIFJlZ3Jlc3Npb24gb2YgTG9nZ2VkIEhhdGUgQ3JpbWUgMjAxNS0yMDE4JykNCmBgYA0KDQpgYGAge3IgdGFibGV9DQpmdWxsX3JlcHJvZHVjZWRfcmVncmVzc2lvbl90YWJsZQ0KYGBgDQoNCg0KIyMjIE11bHRpLUxldmVsIFJlcHJvZHVjZWQgTW9kZWwgd2l0aG91dCBMZWF2ZSBQZXJjZW50YWdlDQoNCmBgYCB7ciBmb3JtdWxhIGZvciBtdWx0aWxldmVsIG1vZGVscywgaW5jbHVkZSA9IEZBTFNFfQ0KDQpicmV4aXRfZm9ybXVsYSA8LSBmb3JtdWxhKGhjcmltZXMuY2xlYW5lZC5wMTAway5sbiB+IGxuX3BvcCArIGFnZV9tZWFuICsgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgdW5lcGxveW1lbnRfbG9uZ3Rlcm1fcGVyY3QgKyByZWxpX2NocmlzdGlhbiArIHVyYmFuICsgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgZXRobl9hcmFiX3BlcmN0ICsgZXRobl9iYW1lX3BlcmN0ICsgcG9saWNlLmZvcmNlLm5hbWUgLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgZGF0YSA9IG1lcmdlZF9kYXRhX2V1KQ0KYGBgDQoNCmBgYHtyIG11bHRpbGV2ZWwgbW9kZWxzIG5vIGJyZXhpdCAzLCBpbmNsdWRlID0gRkFMU0V9DQpoY3JpbWVfZGVtb19tbG1fMSA8LQ0KICBsbWVyKHVwZGF0ZShicmV4aXRfZm9ybXVsYSwgfiAoMSB8IGlkKSArIC4pLCBkYXRhID0gbWVyZ2VkX2RhdGFfZXUpDQoNCmhjcmltZV9kZW1vX21sbV8yIDwtDQogIGxtZXIodXBkYXRlKGJyZXhpdF9mb3JtdWxhLCB+IEluY29tZS5TY29yZSArICgxIHwgaWQpKSwgZGF0YSA9IG1lcmdlZF9kYXRhX2V1KQ0KDQpoY3JpbWVfZGVtb19tbG1fMyA8LSANCiAgbG1lcih1cGRhdGUoYnJleGl0X2Zvcm11bGEsIH4gTGl2aW5nLkVudmlyb25tZW50LlNjb3JlICsgKDEgfCBpZCkpLCBkYXRhID0gbWVyZ2VkX2RhdGFfZXUpDQoNCmhjcmltZV9kZW1vX21sbV80IDwtIA0KICBsbWVyKHVwZGF0ZShicmV4aXRfZm9ybXVsYSwgfiBFZHVjYXRpb24uU2NvcmUgKyAoMSB8IGlkKSksIGRhdGEgPSBtZXJnZWRfZGF0YV9ldSkNCg0KaGNyaW1lX2RlbW9fbWxtXzUgPC0gDQogIGxtZXIodXBkYXRlKGJyZXhpdF9mb3JtdWxhLCB+IEluY29tZS5TY29yZSArIEluY29tZS5TY29yZS5zcGxhZzEubWVhbiArDQogICAgICAgICAgICAgICAgKDEgfCBpZCkgKyAuKSwgZGF0YSA9IG1lcmdlZF9kYXRhX2V1KQ0KDQpoY3JpbWVfZGVtb19tbG1fNiA8LSANCiAgbG1lcih1cGRhdGUoYnJleGl0X2Zvcm11bGEsIH4gIExpdmluZy5FbnZpcm9ubWVudC5TY29yZSArIA0KICAgICAgICAgICAgICAgIExpdmluZy5FbnZpcm9ubWVudC5TY29yZS5zcGxhZzEubWVhbiArDQogICAgICAgICAgICAgICAgKDEgfCBpZCkgKyAuKSwgZGF0YSA9IG1lcmdlZF9kYXRhX2V1KQ0KDQpoY3JpbWVfZGVtb19tbG1fNyA8LSANCiAgbG1lcih1cGRhdGUoYnJleGl0X2Zvcm11bGEsIH4gRWR1Y2F0aW9uLlNjb3JlICsgDQogICAgICAgICAgICAgICAgRWR1Y2F0aW9uLlNjb3JlLnNwbGFnMS5tZWFuICsgKDEgfCBpZCkgKyAuKSwgZGF0YSA9IG1lcmdlZF9kYXRhX2V1KQ0KDQpoY3JpbWVfZGVtb19tbG1fOCA8LSBsbWVyKHVwZGF0ZShicmV4aXRfZm9ybXVsYSwgfiBJbmNvbWUuU2NvcmUgKyANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEluY29tZS5TY29yZS5zcGxhZzEubWVhbiArIExpdmluZy5FbnZpcm9ubWVudC5TY29yZSArIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgTGl2aW5nLkVudmlyb25tZW50LlNjb3JlLnNwbGFnMS5tZWFuICsNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEVkdWNhdGlvbi5TY29yZSArIEVkdWNhdGlvbi5TY29yZS5zcGxhZzEubWVhbiArIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKDEgfCBpZCkgKyAuKSAsIG1lcmdlZF9kYXRhX2V1KQ0KDQpoY3JpbWVfZGVtb19yZWdyZXNzaW9uX3RhYl9tb2RlbCA8LQ0KICB0YWJfbW9kZWwoaGNyaW1lX2RlbW9fbWxtXzEsIGhjcmltZV9kZW1vX21sbV8yLCBoY3JpbWVfZGVtb19tbG1fMywgDQogICAgICAgICAgICBoY3JpbWVfZGVtb19tbG1fNCwgaGNyaW1lX2RlbW9fbWxtXzUsIA0KICAgICAgICAgICAgaGNyaW1lX2RlbW9fbWxtXzYsIGhjcmltZV9kZW1vX21sbV83LCBoY3JpbWVfZGVtb19tbG1fOCwNCiAgICAgICAgICAgIGRpZ2l0cyA9IDMsIGRyb3AgPSAicG9saWNlLmZvcmNlLm5hbWUiLA0KICAgICAgICAgICAgc2hvdy5jaSA9IEZBTFNFLCBzaG93LmludGVyY2VwdCA9IFRSVUUsIHAuc3R5bGUgPSAibnVtZXJpYyIsDQogICAgICAgICAgICBkdi5sYWJlbHMgPSBsaXN0KCIxIiwgIjIiLCAiMyIsICI0IiwgIjUiLCAiNiIsICI3IiwgIjgiKSwNCiAgICAgICAgICAgIHByZWQubGFiZWxzID0gbGlzdCgiSW50ZXJjZXB0IiwgIlBvcHVsYXRpb24gU2l6ZSAobG9nKSIsICJNZWFuIEFnZSIsICJVbmVtcGxveW1lbnQgUGVyY2VudGFnZSIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkNocmlzdGlhbiBSZWxpZ2lvbiBQZXJjZW50YWdlIiwgIlVyYmFuIiwgIkFyYWIgRXRobmljaXR5IFBlcmNlbnRhZ2UiLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiQkFNRSBQZXJjZW50YWdlIiwgIkluY29tZSBEZXByaXZhdGlvbiIsICJMaXZpbmcgRW52cmlvbm1lbnQgRGVwcml2YXRpb24iLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJFZHVjYXRpb24gRGVwcml2YXRpb24iLCAiTmVpZ2hib3VyIEluY29tZSBEZXByaXZhdGlvbiIsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJOZWlnaGJvdXIgTGl2aW5nIEVudnJpb25tZW50IERlcHJpdmF0aW9uIiwgIk5laWdoYm91ciBFZHVjYXRpb24gRGVwcml2YXRpb24iKSwNCiAgICAgICAgICAgIHRpdGxlID0gIlRhYmxlIDM6IExpbmVhciBSZWdyZXNzaW9uIE11bHRpLUxldmVsIE1vZGVsIG9mIERlcHJpdmF0aW9uIG9uIEhhdGUgQ3JpbWUiKQ0KYGBgDQoNCmBgYHtyIG11bHRpbGV2ZWwgbW9kZWwgbm8gYnJleGl0IHRhYmxlIDF9DQpoY3JpbWVfZGVtb19yZWdyZXNzaW9uX3RhYl9tb2RlbA0KYGBgDQoNCiMjIyBDb21wYXJpc29uIG9mIE1vZGVsIENvZWZmaWNpZW50cw0KDQpgYGAge3IgY3JlYXRpbmcgc2luZ2xlIGFuZCBtdWx0aWxldmVsIGNvZWZmaWNpZW50cyAxLCBpbmNsdWRlID0gRkFMU0V9DQpoY3JpbWVfZGVtb19zaW5nbGVfY29lZiA8LSBsbSh1cGRhdGUoYnJleGl0X2Zvcm11bGEsIH4gSW5jb21lLlNjb3JlICsgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgIEluY29tZS5TY29yZS5zcGxhZzEubWVhbiArIExpdmluZy5FbnZpcm9ubWVudC5TY29yZSArIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICBMaXZpbmcuRW52aXJvbm1lbnQuU2NvcmUuc3BsYWcxLm1lYW4gKw0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICBFZHVjYXRpb24uU2NvcmUgKyBFZHVjYXRpb24uU2NvcmUuc3BsYWcxLm1lYW4gKyAuKSwgZGF0YSA9IG1lcmdlZF9kYXRhX2V1KQ0KDQpoY3JpbWVfZGVtb19tbG1fY29lZiA8LSANCiAgbG1lcih1cGRhdGUoYnJleGl0X2Zvcm11bGEsIH4gSW5jb21lLlNjb3JlICsgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgIEluY29tZS5TY29yZS5zcGxhZzEubWVhbiArIExpdmluZy5FbnZpcm9ubWVudC5TY29yZSArIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICBMaXZpbmcuRW52aXJvbm1lbnQuU2NvcmUuc3BsYWcxLm1lYW4gKw0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICBFZHVjYXRpb24uU2NvcmUgKyBFZHVjYXRpb24uU2NvcmUuc3BsYWcxLm1lYW4gKygxIHwgaWQpICsgLiksIGRhdGEgPSBtZXJnZWRfZGF0YV9ldSkNCmBgYA0KDQpgYGAge3IgY29lZmZpY2llbnQgY29uZmlkZW5jZSBpbnRlcnZhbHMgMSwgaW5jbHVkZSA9IEZBTFNFfQ0KDQpoY3JpbWVfZGVtb19zaW5nbGVfY29lZl9jaSA8LSB0aWR5KGhjcmltZV9kZW1vX3NpbmdsZV9jb2VmLCBjb25mLmludCA9IFRSVUUpICU+JSBtdXRhdGUobW9kZWwgPSAiU2luZ2xlLUxldmVsIikNCg0KaGNyaW1lX2RlbW9fbWxtX2NpIDwtIHRpZHkoaGNyaW1lX2RlbW9fbWxtX2NvZWYsIGNvbmYuaW50ID0gVFJVRSkgJT4lIG11dGF0ZShtb2RlbCA9ICJNdWx0aS1MZXZlbCIpDQoNCmhjcmltZV9kZW1vX21vZGVsc19jb2VmIDwtIGJpbmRfcm93cyhoY3JpbWVfZGVtb19zaW5nbGVfY29lZl9jaSwgaGNyaW1lX2RlbW9fbWxtX2NpKQ0KYGBgDQoNCmBgYHtyIHJlbW92aW5nIHBvbGljZSBmb3JjZSwgaW5jbHVkZSA9IEZBTFNFfQ0KaGNyaW1lX2RlbW9fbW9kZWxzX2NvZWZfbnAgPC0gDQogIGhjcmltZV9kZW1vX21vZGVsc19jb2VmWy0gZ3JlcCgicG9saWNlIiwgaGNyaW1lX2RlbW9fbW9kZWxzX2NvZWYkdGVybSksXQ0KYGBgDQoNCmBgYHtyIHJlbW92aW5nIHNkIHZhbHVlcywgaW5jbHVkZSA9IEZBTFNFfQ0KaGNyaW1lX2RlbW9fbW9kZWxzX2NvZWZfbnAgPC0gDQogIGhjcmltZV9kZW1vX21vZGVsc19jb2VmX25wWy0gZ3JlcCgic2RfXyIsIGhjcmltZV9kZW1vX21vZGVsc19jb2VmX25wJHRlcm0pLF0gDQpgYGANCg0KYGBgIHtyIHJlbmFtaW5nIHZhcmlhYmxlcywgaW5jbHVkZSA9IEZBTFNFfQ0KaGNyaW1lX2RlbW9fbW9kZWxzX2NvZWZfbnAkdGVybSA8LSByZWNvZGUoaGNyaW1lX2RlbW9fbW9kZWxzX2NvZWZfbnAkdGVybSwgJyhJbnRlcmNlcHQpJyA9ICdJbnRlcmNlcHQnLCAnbG5fcG9wJyA9ICdMb2dnZWQgUG9wdWxhdGlvbicsICdhZ2VfbWVhbicgPSAnTWVhbiBBZ2UnICwgDQogICAgICAgICAgICAgICAgICAgICAndW5lcGxveW1lbnRfbG9uZ3Rlcm1fcGVyY3QnID0gJ0xvbmctdGVybSBVbmVtcGxveWVkJyAsICdyZWxpX2NocmlzdGlhbicgPSAnQ2hyaXN0aWFuJyAsICd1cmJhbicgPSAnVXJiYW4nLCANCiAgICAgICAgICAgICAgICAgICAgICdldGhuX2FyYWJfcGVyY3QnID0gJ0V0aG5pYyBBcmFiJywgJ2V0aG5fYmFtZV9wZXJjdCcgPSAnRXRobmljIEJBTUUnLA0KICAgICAgICAgICAgICAgICAgICAgJ0luY29tZS5TY29yZScgPSAnSW5jb21lIERlcHJpdmF0aW9uJyAsIA0KICAgICAgICAgICAgICAgICAgICAgJ0luY29tZS5TY29yZS5zcGxhZzEubWVhbicgPSAnIE5laWdoYm91cmluZyBJbmNvbWUgRGVwcml2YXRpb24nLCAnTGl2aW5nLkVudmlyb25tZW50LlNjb3JlJyA9ICdMaXZpbmcgRW52aXJvbm1lbnQgRGVwcml2YXRpb24nLA0KICAgICAgICAgICAgICAgICAgICAgJ0xpdmluZy5FbnZpcm9ubWVudC5TY29yZS5zcGxhZzEubWVhbicgPSAnTmVpZ2hib3VyaW5nIExpdmluZyBFbnZpcm9ubWVudCBEZXByaXZhdGlvbicsDQogICAgICAgICAgICAgICAgICAgICAnRWR1Y2F0aW9uLlNjb3JlJyA9ICdFZHVjYXRpb24gRGVwcml2YXRpb24nLCAnRWR1Y2F0aW9uLlNjb3JlLnNwbGFnMS5tZWFuJyA9ICdOZWlnaGJvdXJpbmcgRWR1Y2F0aW9uIERlcHJpdmF0aW9uJykNCg0KYGBgDQoNCmBgYCB7ciBjb2VmZmljaWVudCBwbG90IDEgMX0NCmdncGxvdChoY3JpbWVfZGVtb19tb2RlbHNfY29lZl9ucCwgDQogICAgICAgYWVzKHggPSB0ZXJtLCB5ID0gZXN0aW1hdGUsIGNvbG9yID0gbW9kZWwpKSArDQogIGdlb21fcG9pbnQocG9zaXRpb24gPSBwb3NpdGlvbl9kb2RnZSh3aWR0aCA9IDAuNSkpICsNCiAgZ2VvbV9lcnJvcmJhcihhZXMoeW1pbiA9IGNvbmYubG93LCB5bWF4ID0gY29uZi5oaWdoKSwgd2lkdGggPSAwLjIsIHBvc2l0aW9uID0gcG9zaXRpb25fZG9kZ2Uod2lkdGggPSAwLjUpKSArDQogIGNvb3JkX2ZsaXAoKSArDQogIGxhYnModGl0bGUgPSAiQ29tcGFyaXNvbiBvZiBTaW5nbGUgYW5kIE11bHRpbGV2ZWwgTW9kZWwgQ29lZmZpY2llbnRzIiwNCiAgICAgICB4ID0gIlByZWRpY3RvcnMiLA0KICAgICAgIHkgPSAiRXN0aW1hdGUiKSArDQogIHRoZW1lX21pbmltYWwoKQ0KYGBgDQoNCiMNCkNvbXBhcmluZyB0aGVzZSBtb2RlbHMgc2hvd3MgdGhhdCBtb3N0IHZhcmlhYmxlIHByZWRpY3Rpb25zIGRpZCBub3QgY2hhbmdlIG11Y2ggYmV0d2VlbiB0aGUgc2luZ2xlIGFuZCBtdWx0aWxldmVsIG1vZGVscywgaW5kaWNhdGluZyB0aGUgcGF0dGVybnMgcHJlc2VudCBhdCBMU09BIGxldmVsIHJlbWFpbiBxdWl0ZSBjb25zaXN0ZW50IGF0IHRoZSBMQUQgbGV2ZWwuIFRoZSBlZmZlY3Qgb2YgYWdlIGJlY29tZXMgaW5zaWduaWZpY2FudCBpbiB0aGUgbXVsdGlsZXZlbCBtb2RlbCwgc3VnZ2VzdGluZyBhZ2UtcmVsYXRlZCB2YXJpYXRpb25zIGluIGhhdGUgY3JpbWUgYXJlIG1vcmUgaG9tb2dlbmVvdXMgd2l0aGluIExBRHMgYnV0IHRoaXMgZWZmZWN0IGlzIGxlc3MgY2xlYXIgd2hlbiBiZXR3ZWVuIExBRCB2YXJpYXRpb24gaXMgYWNjb3VudGVkIGZvci4gVGhlIGltcGFjdCBvZiBkZXByaXZhdGlvbiB2YXJpYWJsZXMgY2hhbmdlcyBzbGlnaHRseSBiZXR3ZWVuIG1vZGVscywgc2hvd2luZyB0aGF0IHdoaWxlIHRoZXJlIHNpZ25pZmljYW50IHZhcmlhdGlvbnMgb2NjdXJyaW5nIGF0IExBRCBsZXZlbCwgdGhlc2UgYXJlIHF1aXRlIHNtYWxsLg0KDQpUaGUgSW50cmEtQ2xhc3MgQ29ycmVsYXRpb24gYmV0d2VlbiAwLjM3LTM5IGluZGljYXRlcyBhIHNpZ25pZmljYW50IHBvcnRpb24gb2YgdmFyaWFiaWxpdHkgaW4gaGF0ZSBjcmltZSByYXRlcyBjYW4gYmUgYXR0cmlidXRlZCB0byBkaWZmZXJlbmNlcyBiZXR3ZWVuIExBRHMsIGJ1dCB0aGlzIGVmZmVjdCBvbmx5IG9jY3VycyB3aGVuIGluY2x1ZGluZyBkZXByaXZhdGlvbiB2YXJpYWJsZXMsIGluZGljYXRpbmcgdGhhdCB3aGlsZSBkZXByaXZhdGlvbiB2YXJpZWQgY29uc2lkZXJhYmx5IGJldHdlZW4gTEFEcywgZGVtb2dyYXBoaWMgdmFyaWFibGVzIGRpZCBub3QuDQoNClRoZSBJbnRlcmNlcHQgdGVuZHMgbW9yZSB0byBiZSBuZWdhdGl2ZSBpbiB0aGUgbXVsdGlsZXZlbCBtb2RlbCBkdWUgdG8gaGllcmFyY2hpY2FsIHN0cnVjdHVyaW5nIGluIHRoZSBkYXRhOyBhY2NvdW50aW5nIGZvciB2YXJpYWJpbGl0eSBhdCB0aGUgTEFEIGxldmVsIGFkanVzdHMgdGhlIGJhc2VsaW5lIGhhdGUgY3JpbWUgbGV2ZWwgYmVsb3cgd2hhdCB3YXMgcHJlZGljdGVkIGluIHRoZSBzaW5nbGUgbGV2ZWwgbW9kZWwuICANCkhvd2V2ZXIgdGhlIHNpbmdsZSBsZXZlbCBtb2RlbCBoYXMgYSBoaWdoZXN0IFLCsiBvZiAwLjQ1NCwgd2hlcmVhcyBpbmNsdWRpbmcgcmFuZG9tIGVmZmVjdHMgaW4gdGhlIG11bHRpbGV2ZWwgbW9kZWwgcHJvdmlkZXMgYSBoaWdoZXN0IGNvbmRpdGlvbmFsIFLCsiBwZiAwLjQ3NiwgaW5kaWNhdGluZyB0aGF0IHRoaXMgbW9kZWwgZG9lcyBiZXR0ZXIgZml0IHRoZSBkYXRhLiANCg0KDQojIyAzLjIgQ29tcGFyaW5nIE11dGxpbGV2ZWwgbW9kZWxzIHdpdGggYW5kIHdpdGhvdXQgTGVhdmUgUGVyY2VudGFnZSB7LnRhYnNldCAudGFic2V0LXBpbGxzfQ0KDQojIyMgTXVsdGlsZXZlbCBtb2RlbCB3aXRob3V0IExlYXZlIFBlcmNlbnRhZ2UNCg0KYGBge3IgbXVsdGlsZXZlbCBtb2RlbCBubyBicmV4aXQgdGFibGUgM30NCmhjcmltZV9kZW1vX3JlZ3Jlc3Npb25fdGFiX21vZGVsDQpgYGANCg0KIyMjIE11bHRpbGV2ZWwgTW9kZWwgd2l0aCBMZWF2ZSBQZXJjZW50YWdlDQoNCmBgYHtyIG11bHRpbGV2ZWwgbW9kZWxzIHdpdGggYnJleGl0LCBpbmNsdWRlID0gRkFMU0V9DQpicmV4aXRfaGNyaW1lX2RlbW9fbWxtXzEgPC0NCiAgbG1lcih1cGRhdGUoYnJleGl0X2Zvcm11bGEsIH4gUGN0X0xlYXZlICsgKDEgfCBpZCkgKyAuKSwgZGF0YSA9IG1lcmdlZF9kYXRhX2V1KQ0KDQpicmV4aXRfaGNyaW1lX2RlbW9fbWxtXzIgPC0NCiAgbG1lcih1cGRhdGUoYnJleGl0X2Zvcm11bGEsIH4gUGN0X0xlYXZlICsgSW5jb21lLlNjb3JlICsgKDEgfCBpZCkpLCBkYXRhID0gbWVyZ2VkX2RhdGFfZXUpDQoNCmJyZXhpdF9oY3JpbWVfZGVtb19tbG1fMyA8LSANCiAgbG1lcih1cGRhdGUoYnJleGl0X2Zvcm11bGEsIH4gUGN0X0xlYXZlICsgTGl2aW5nLkVudmlyb25tZW50LlNjb3JlICsgKDEgfCBpZCkpLCBkYXRhID0gbWVyZ2VkX2RhdGFfZXUpDQoNCmJyZXhpdF9oY3JpbWVfZGVtb19tbG1fNCA8LSANCiAgbG1lcih1cGRhdGUoYnJleGl0X2Zvcm11bGEsIH4gUGN0X0xlYXZlICsgRWR1Y2F0aW9uLlNjb3JlICsgKDEgfCBpZCkpLCBkYXRhID0gbWVyZ2VkX2RhdGFfZXUpDQoNCmJyZXhpdF9oY3JpbWVfZGVtb19tbG1fNSA8LSANCiAgbG1lcih1cGRhdGUoYnJleGl0X2Zvcm11bGEsIH4gUGN0X0xlYXZlICsgSW5jb21lLlNjb3JlICsgSW5jb21lLlNjb3JlLnNwbGFnMS5tZWFuICsNCiAgICAgICAgICAgICAgICAoMSB8IGlkKSArIC4pLCBkYXRhID0gbWVyZ2VkX2RhdGFfZXUpDQoNCmJyZXhpdF9oY3JpbWVfZGVtb19tbG1fNiA8LSANCiAgbG1lcih1cGRhdGUoYnJleGl0X2Zvcm11bGEsIH4gUGN0X0xlYXZlICsgTGl2aW5nLkVudmlyb25tZW50LlNjb3JlICsgDQogICAgICAgICAgICAgICAgTGl2aW5nLkVudmlyb25tZW50LlNjb3JlLnNwbGFnMS5tZWFuICsNCiAgICAgICAgICAgICAgICAoMSB8IGlkKSArIC4pLCBkYXRhID0gbWVyZ2VkX2RhdGFfZXUpDQoNCmJyZXhpdF9oY3JpbWVfZGVtb19tbG1fNyA8LSANCiAgbG1lcih1cGRhdGUoYnJleGl0X2Zvcm11bGEsIH4gUGN0X0xlYXZlICsgRWR1Y2F0aW9uLlNjb3JlICsgDQogICAgICAgICAgICAgICAgRWR1Y2F0aW9uLlNjb3JlLnNwbGFnMS5tZWFuICsgKDEgfCBpZCkgKyAuKSwgZGF0YSA9IG1lcmdlZF9kYXRhX2V1KQ0KDQpicmV4aXRfaGNyaW1lX2RlbW9fbWxtXzggPC0gbG1lcih1cGRhdGUoYnJleGl0X2Zvcm11bGEsIH4gUGN0X0xlYXZlICsgSW5jb21lLlNjb3JlICsgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgIEluY29tZS5TY29yZS5zcGxhZzEubWVhbiArIExpdmluZy5FbnZpcm9ubWVudC5TY29yZSArIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICBMaXZpbmcuRW52aXJvbm1lbnQuU2NvcmUuc3BsYWcxLm1lYW4gKw0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICBFZHVjYXRpb24uU2NvcmUgKyBFZHVjYXRpb24uU2NvcmUuc3BsYWcxLm1lYW4gKyANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICgxIHwgaWQpICsgLikgLCBtZXJnZWRfZGF0YV9ldSkNCmBgYA0KDQpgYGB7ciBmdWxsIHJlZ3Jlc3Npb24gbW9kZWwgNCwgaW5jbHVkZSA9IEZBTFNFfQ0KZnVsbF9yZWdyZXNzaW9uX3RhYl9tb2RlbCA8LQ0KdGFiX21vZGVsKGJyZXhpdF9oY3JpbWVfZGVtb19tbG1fMSwgYnJleGl0X2hjcmltZV9kZW1vX21sbV8yLCBicmV4aXRfaGNyaW1lX2RlbW9fbWxtXzMsIA0KICAgICAgICAgIGJyZXhpdF9oY3JpbWVfZGVtb19tbG1fNCwgYnJleGl0X2hjcmltZV9kZW1vX21sbV81LCANCiAgICAgICAgICBicmV4aXRfaGNyaW1lX2RlbW9fbWxtXzYsIGJyZXhpdF9oY3JpbWVfZGVtb19tbG1fNywgYnJleGl0X2hjcmltZV9kZW1vX21sbV84LA0KICAgICAgICAgIGRpZ2l0cyA9IDMsIGRyb3AgPSAicG9saWNlLmZvcmNlLm5hbWUiLCBzaG93LmludGVyY2VwdCA9IFRSVUUsDQogICAgICAgICAgc2hvdy5jaSA9IEZBTFNFLCBwLnN0eWxlID0gIm51bWVyaWMiLA0KICAgICAgICAgIGR2LmxhYmVscyA9IGxpc3QoIjEiLCAiMiIsICIzIiwgIjQiLCAiNSIsICI2IiwgIjciLCAiOCIpLA0KICAgICAgICAgIHByZWQubGFiZWxzID0gbGlzdCgiSW50ZXJjZXB0IiwgIkxlYXZlIFZvdGUgUGVyY2VudCIsICJQb3B1bGF0aW9uIFNpemUgKGxvZykiLCAiTWVhbiBBZ2UiLCAiVW5lbXBsb3ltZW50IFBlcmNlbnRhZ2UiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiQ2hyaXN0aWFuIFJlbGlnaW9uIFBlcmNlbnRhZ2UiLCAiVXJiYW4iLCAiQXJhYiBFdGhuaWNpdHkgUGVyY2VudGFnZSIsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiQkFNRSBQZXJjZW50YWdlIiwgIkluY29tZSBEZXByaXZhdGlvbiIsICJMaXZpbmcgRW52cmlvbm1lbnQgRGVwcml2YXRpb24iLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiRWR1Y2F0aW9uIERlcHJpdmF0aW9uIiwgIk5laWdoYm91ciBJbmNvbWUgRGVwcml2YXRpb24iLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIk5laWdoYm91ciBMaXZpbmcgRW52cmlvbm1lbnQgRGVwcml2YXRpb24iLCAiTmVpZ2hib3VyIEVkdWNhdGlvbiBEZXByaXZhdGlvbiIpLA0KICAgICAgICAgIHRpdGxlID0gIlRhYmxlIDQ6IExpbmVhciBSZWdyZXNzaW9uIE1vZGVsIG9mIExlYXZlIFZvdGUgUGVyY2VudGFnZSBhbmQgRGVwcml2YXRpb24gb24gSGF0ZSBDcmltZSIpDQpgYGANCg0KYGBge3IgbXVsdGlsZXZlbCBtb2RlbCB3aXRoIGJyZXhpdCB0YWJsZSAzfSAgICANCmZ1bGxfcmVncmVzc2lvbl90YWJfbW9kZWwNCmBgYA0KDQojIyMgQ29tcGFyaXNvbiBvZiBNb2RlbCBDb2VmZmljaWVudHMNCg0KYGBgIHtyIGJyZXhpdCBtbG0gY29lZmZpY2llbnRzLCBpbmNsdWRlID0gRkFMU0V9DQpoY3JpbWVfZGVtb19icmV4aXRfbWxtX2NvZWYgPC0gbG1lcih1cGRhdGUoYnJleGl0X2Zvcm11bGEsIH4gUGN0X0xlYXZlICsgSW5jb21lLlNjb3JlICsgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgIEluY29tZS5TY29yZS5zcGxhZzEubWVhbiArIExpdmluZy5FbnZpcm9ubWVudC5TY29yZSArIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICBMaXZpbmcuRW52aXJvbm1lbnQuU2NvcmUuc3BsYWcxLm1lYW4gKw0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICBFZHVjYXRpb24uU2NvcmUgKyBFZHVjYXRpb24uU2NvcmUuc3BsYWcxLm1lYW4gKygxIHwgaWQpICsgLiksIGRhdGEgPSBtZXJnZWRfZGF0YV9ldSkNCmBgYA0KDQpgYGB7ciBicmV4aXQgbWxtIGNvZWYgY29uZmlkZW5jZSBpbnRlcnZhbHMsIGluY2x1ZGUgPSBGQUxTRX0NCg0KaGNyaW1lX2RlbW9fbWxtX2NpX25vYnJleGl0IDwtIHRpZHkoaGNyaW1lX2RlbW9fbWxtX2NvZWYsIGNvbmYuaW50ID0gVFJVRSkgJT4lIG11dGF0ZShtb2RlbCA9ICJNdWx0aS1MZXZlbCBObyBCcmV4aXQiKQ0KDQpoY3JpbWVfZGVtb19tbG1fY2lfYnJleGl0IDwtIHRpZHkoaGNyaW1lX2RlbW9fYnJleGl0X21sbV9jb2VmLCBjb25mLmludCA9IFRSVUUpICU+JSBtdXRhdGUobW9kZWwgPSAiTXVsdGktTGV2ZWwgV2l0aCBCcmV4aXQiKQ0KDQoNCmhjcmltZV9kZW1vX21vZGVsc19jb2VmX2JyZXhpdCA8LSBiaW5kX3Jvd3MoaGNyaW1lX2RlbW9fbWxtX2NpX25vYnJleGl0LCBoY3JpbWVfZGVtb19tbG1fY2lfYnJleGl0KQ0KYGBgDQoNCmBgYHtyIGJyZXhpdCByZW1vdmluZyBwb2xpY2UgZm9yY2UsIGluY2x1ZGUgPSBGQUxTRX0NCmhjcmltZV9kZW1vX2JyZXhpdF9tb2RlbHNfY29lZl9ucCA8LSANCiAgaGNyaW1lX2RlbW9fbW9kZWxzX2NvZWZfYnJleGl0Wy0gZ3JlcCgicG9saWNlIiwgaGNyaW1lX2RlbW9fbW9kZWxzX2NvZWZfYnJleGl0JHRlcm0pLF0NCmBgYA0KDQpgYGB7ciBicmV4aXQgcmVtb3Zpbmcgc2QgdmFsdWVzLCBpbmNsdWRlID0gRkFMU0V9DQpoY3JpbWVfZGVtb19icmV4aXRfbW9kZWxzX2NvZWZfbnAgPC0gDQogIGhjcmltZV9kZW1vX2JyZXhpdF9tb2RlbHNfY29lZl9ucFstIGdyZXAoInNkX18iLCBoY3JpbWVfZGVtb19icmV4aXRfbW9kZWxzX2NvZWZfbnAkdGVybSksXSANCmBgYA0KDQpgYGAge3IgYnJleGl0IHJlbmFtaW5nIHZhcmlhYmxlcywgaW5jbHVkZSA9IEZBTFNFfQ0KaGNyaW1lX2RlbW9fYnJleGl0X21vZGVsc19jb2VmX25wJHRlcm0gPC0gcmVjb2RlKGhjcmltZV9kZW1vX2JyZXhpdF9tb2RlbHNfY29lZl9ucCR0ZXJtLCAnKEludGVyY2VwdCknID0gJ0ludGVyY2VwdCcsICdsbl9wb3AnID0gJ0xvZ2dlZCBQb3B1bGF0aW9uJywgJ2FnZV9tZWFuJyA9ICdNZWFuIEFnZScgLCANCiAgICAgICAgICAgICAgICAgICAgICd1bmVwbG95bWVudF9sb25ndGVybV9wZXJjdCcgPSAnTG9uZy10ZXJtIFVuZW1wbG95ZWQnICwgJ3JlbGlfY2hyaXN0aWFuJyA9ICdDaHJpc3RpYW4nICwgJ3VyYmFuJyA9ICdVcmJhbicsIA0KICAgICAgICAgICAgICAgICAgICAgJ2V0aG5fYXJhYl9wZXJjdCcgPSAnRXRobmljIEFyYWInLCAnZXRobl9iYW1lX3BlcmN0JyA9ICdFdGhuaWMgQkFNRScsDQogICAgICAgICAgICAgICAgICAgICAnSW5jb21lLlNjb3JlJyA9ICdJbmNvbWUgRGVwcml2YXRpb24nICwgDQogICAgICAgICAgICAgICAgICAgICAnSW5jb21lLlNjb3JlLnNwbGFnMS5tZWFuJyA9ICcgTmVpZ2hib3VyaW5nIEluY29tZSBEZXByaXZhdGlvbicsICdMaXZpbmcuRW52aXJvbm1lbnQuU2NvcmUnID0gJ0xpdmluZyBFbnZpcm9ubWVudCBEZXByaXZhdGlvbicsDQogICAgICAgICAgICAgICAgICAgICAnTGl2aW5nLkVudmlyb25tZW50LlNjb3JlLnNwbGFnMS5tZWFuJyA9ICdOZWlnaGJvdXJpbmcgTGl2aW5nIEVudmlyb25tZW50IERlcHJpdmF0aW9uJywNCiAgICAgICAgICAgICAgICAgICAgICdFZHVjYXRpb24uU2NvcmUnID0gJ0VkdWNhdGlvbiBEZXByaXZhdGlvbicsICdFZHVjYXRpb24uU2NvcmUuc3BsYWcxLm1lYW4nID0gJ05laWdoYm91cmluZyBFZHVjYXRpb24gRGVwcml2YXRpb24nLCAnUGN0X0xlYXZlJyA9ICdMZWF2ZSBWb3RlIFByb3BvcnRpb24nKQ0KDQpgYGANCg0KYGBgIHtyIGNvZWZmaWNpZW50IHBsb3QgM30NCmdncGxvdChoY3JpbWVfZGVtb19icmV4aXRfbW9kZWxzX2NvZWZfbnAsIA0KICAgICAgIGFlcyh4ID0gdGVybSwgeSA9IGVzdGltYXRlLCBjb2xvciA9IG1vZGVsKSkgKw0KICBnZW9tX3BvaW50KHBvc2l0aW9uID0gcG9zaXRpb25fZG9kZ2Uod2lkdGggPSAwLjUpKSArDQogIGdlb21fZXJyb3JiYXIoYWVzKHltaW4gPSBjb25mLmxvdywgeW1heCA9IGNvbmYuaGlnaCksIHdpZHRoID0gMC4yLCBwb3NpdGlvbiA9IHBvc2l0aW9uX2RvZGdlKHdpZHRoID0gMC41KSkgKw0KICBjb29yZF9mbGlwKCkgKw0KICBsYWJzKHRpdGxlID0gIkNvbXBhcmlzb24gb2YgV2l0aCBhbmQgV2l0aG91dCBCcmV4aXQgQ29lZmZpY2llbnRzIiwNCiAgICAgICB4ID0gIlByZWRpY3RvcnMiLA0KICAgICAgIHkgPSAiRXN0aW1hdGUiKSArDQogIHRoZW1lX21pbmltYWwoKQ0KYGBgDQoNCiMNCkluIHRoZSBkZXByaXZhdGlvbiBtb2RlbHMgdGhlIHByb3BvcnRpb24gb2YgQnJleGl0IGxlYXZlIHZvdGVycyBoYXMgaGFkIGEgc2xpZ2h0IG5lZ2F0aXZlIGVmZmVjdCwgc3VnZ2VzdGluZyBhcmVhcyB3aXRoIGEgaGlnaGVyIGxlYXZlIHZvdGUgcHJvcG9ydGlvbiBtYXkgZXhwZXJpZW5jZSBsb3dlciBoYXRlIGNyaW1lIHJhdGVzLCBhbHRob3VnaCB0aGlzIGVmZmVjdCBpcyBxdWl0ZSBtYXJnaW5hbC4gSG93ZXZlciwgdGhpcyBlZmZlY3QgYmVjb21lcyBpbnNpZ25pZmljYW50IG9uY2UgZGVtb2dyYXBoaWMgdmFyaWFibGVzIGFyZSBpbmNsdWRlZC4gQWx0aG91Z2ggdGhlc2UgdmFyaWFibGVzIHdlcmUgbm90IHRvbyBoaWdobHkgY29ycmVsYXRlZCBhcyB0ZXN0ZWQgaW4gdGhlIHZhcmlhYmxlIGNvZWZmaWNpZW50IHBsb3RzLCB0aGlzIHN0aWxsIHN1Z2dlc3RzIG1vc3Qgb2YgdGhlIHZhcmlhbmNlIGluIGhhdGUgY3JpbWVzIGluIHRoaXMgbW9kZWwgaXMgZHVlIHRvIGRlbW9ncmFwaGljIHZhcmlhYmxlcy4NCg0KQWxsIG90aGVyIHByZWRpY3RvciB2YXJpYWJsZXMgZXN0aW1hdGVzIHJlbWFpbiBjb25zaXN0ZW50LCBpbmRpY2F0aW5nIHRoYXQgbm9uZSBvZiB0aGVzZSB2YXJpYWJsZXMgd2VyZSBzaWduaWZpY2FudGx5IGluZmx1ZW5jZWQgYnkgdGhlIGFkZGl0aW9uIG9mIHZvdGluZyBkYXRhLiANCg0KVGhlcmUgaXMgYSBzbGlnaHQgZGVjcmVhc2UgaW4gdGhlIHJhbmRvbSBlZmZlY3RzIGFuZCBJQ0MgaW4gdGhlIGxlYXZlIHZvdGUgbW9kZWwsIHN1Z2dlc3RpbmcgbGVhdmUgdm90ZSBwcm9wb3J0aW9uIGV4cGxhaW5zIHNvbWUgb2YgdGhlIExBRCB2YXJpYW5jZSBpbiBoYXRlIGNyaW1lcywgYnV0IHRoaXMgZWZmZWN0IGlzIG1pbmltYWwuIA0KDQpUaGUgYWRkaXRpb24gb2YgdGhlIGxlYXZlIHZvdGUgdmFyaWFibGUgZG9lcyBzbGlnaHRseSBpbXByb3ZlIHRoZSBtYXJnaW5hbCBSwrIgaW4gc29tZSBtb2RlbHMsIGluZGljYXRpbmcgYSBzbGlnaHRseSBiZXR0ZXIgZml0LCBidXQgdGhlIGNvbmRpdGlvbmFsIFLCsiBpcyBzdGFibGUsIHN1Z2dlc3Rpbmcgb3ZlcmFsbCB2YXJpYW5jZSBleHBsYWluZWQgYnkgZml4ZWQgYW5kIHJhbmRvbSBlZmZlY3RzIGRvZXMgbm90IGNoYW5nZSBzaWduaWZpY2FudGx5Lg0KDQpUaGlzIHJlamVjdHMgbXkgaHlwb3RoZXNpcywgdGhlIGFkZGl0aW9uIG9mIExlYXZlIFZvdGUgUGVyY2VudGFnZSBkb2VzIG5vdCBoYXZlIGEgc2lnbmlmaWNhbnQgcmVsYXRpb25zaGlwIHdpdGggdGhlIHJhdGUgb2YgaGF0ZSBjcmltZSBvbmNlIGFsbCBwcmVkaWN0b3IgdmFyaWFibGVzIGFyZSBhY2NvdW50ZWQgZm9yLCBhbmQgbmVpdGhlciBkb2VzIGl0IGhhdmUgYW55IG1lZGlhdGluZyBlZmZlY3Qgb24gdGhlc2UgcHJlZGljdG9yIHZhcmlhYmxlcy4gIA0KDQojIyAzLjMgTWl4ZWQgRWZmZWN0cyBNb2RlbHMgey50YWJzZXQgLnRhYnNldC1waWxsc30NCg0KIyMjIEhhdGUgQ3JpbWUgYW5kIExlYXZlIFZvdGUgTW9kZWwNCg0KYGBgIHtyIGhhdGUgY3JpbWUgbGVhdmUgdm90ZSBtZSBtb2RlbCwgaW5jbHVkZSA9IEZBTFNFfQ0KaGNyaW1lX2JyZXhpdF9tbG1vZGVsX21lX3Bsb3QgPC0gcGxvdF9tb2RlbChoY3JpbWVfYnJleGl0X21sbW9kZWwsIHR5cGUgPSAicmUiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkb3Quc2l6ZSA9IDEsIGxpbmUuc2l6ZSA9IDAuMiwgZ3JpZC5icmVha3MgPSAxKSArDQogIHRoZW1lKGF4aXMudGV4dC55ID0gZWxlbWVudF90ZXh0KHNpemUgPSA0LCBhbmdsZSA9IDAsIGhqdXN0ID0gMSkpDQpgYGANCg0KYGBgIHtyIGhhdGUgY3JpbWUgbGVhdmUgdm90ZSBtZSBtb2RlbCBwbG90fQ0KaGNyaW1lX2JyZXhpdF9tbG1vZGVsX21lX3Bsb3QNCmBgYA0KDQojIyMgQWxsIFByZWRpY3RvcnMgTW9kZWwNCg0KYGBgIHtyIGFsbCBwcmVkaWN0b3JzIG1lIG1vZGVsLCBpbmNsdWRlID0gRkFMU0V9DQpoY3JpbWVfYWxsX3ByZWRfbWVfcGxvdCA8LSBwbG90X21vZGVsKGJyZXhpdF9oY3JpbWVfZGVtb19tbG1fOCwgdHlwZSA9ICJyZSIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRvdC5zaXplID0gMSwgbGluZS5zaXplID0gMC4yLCBncmlkLmJyZWFrcyA9IDEpICsNCiAgdGhlbWUoYXhpcy50ZXh0LnkgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDQsIGFuZ2xlID0gMCwgaGp1c3QgPSAxKSkNCmBgYA0KDQpgYGAge3IgYWxsIHByZWRpY3RvcnMgbWUgbW9kZWwgcGxvdH0NCmhjcmltZV9hbGxfcHJlZF9tZV9wbG90DQpgYGANCg0KIw0KVGhlIG1peGVkIGVmZmVjdHMgbW9kZWxzIGluZGljYXRlIHRoZSBpbXBvcnRhbmNlIG9mIHRoZSBpbmNsdXNpb24gb2YgZGVtb2dyYXBoaWMgYW5kIGRlcHJpdmF0aW9uIGRhdGEgaW4gdGhlIGZpbmFsIG1vZGVsLiBUaGUgcmFuZG9tIGVmZmVjdHMgYXJlIHN1YnN0YW50aWFsbHkgcmVkdWNlZCBhY2NvdW50aW5nIGZvciB0aGVzZSB2YXJpYWJsZXMsIGFuZCB0aGVzZSBlZmZlY3RzIGFsc28gY2x1c3RlciBtb3JlIHRpZ2h0bHkgYXJvdW5kIDAsIHdoaWNoIHNob3dzIHRoZSBhbGwgcHJlZGljdG9ycyBtb2RlbCBiZXR0ZXIgYWNjb3VudHMgZm9yIHZhcmlhYmlsaXR5IGluICBoYXRlIGNyaW1lIHJhdGVzLiANCg0KDQojIyA0LiBDb25jbHVzaW9ucw0KDQpUaGUgZmluZGluZ3MgaW4gdGhpcyBwYXBlciBjb3Jyb2JvcmF0ZSBCZWxnaW9pb3NvIGV0IGFsLuKAmXMgZmluZGluZ3MgdGhhdCBkZXByaXZhdGlvbiBmYWN0b3JzLCBwYXJ0aWN1bGFybHkgaW5jb21lIGRlcHJpdmF0aW9uLCBoYXZlIGEgcm9idXN0IGFzc29jaWF0aW9uIHdpdGggaGF0ZSBjcmltZSByYXRlcy4gVGhlIGluY2x1c2lvbiBvZiBkZW1vZ3JhcGhpYyB2YXJpYWJsZXMgbWFrZSBjbGVhcmVyIHRoZSBmYWN0b3JzIHJlc3BvbnNpYmxlIGZvciB2YXJpYXRpb25zIGluIGhhdGUgY3JpbWUgcmF0ZXMuIEFsdGhvdWdoIHRoZSBpbml0aWFsIG1vZGVsIGNvbnRhaW5pbmcganVzdCBoYXRlIGNyaW1lIGFuZCBCcmV4aXQgZGF0YSBkb2VzIGluZGljYXRlIGEgc2lnbmlmaWNhbnQgZWZmZWN0LCB0aGlzIGlzIG1pdGlnYXRlZCB3aXRoIHRoZSBpbmNsdXNpb24gb2YgZGVtb2dyYXBoaWMgZGF0YSwgaW5kaWNhdGluZyB0aGUgc2FtZSBkZW1vZ3JhcGhpYyB2YXJpYXRpb25zIGxlYWRpbmcgdG8gdmFyaWF0aW9ucyBpbiBoYXRlIGNyaW1lIHJhdGVzIG9uIHRoZSBMU09BIGxldmVsIGFyZSBoYXZpbmcgYSBzaW1pbGFyIGVmZmVjdCBvbiB0aGUgTEFEIGxldmVsLiANCg0KQSBwb3NzaWJsZSByZWFzb24gZm9yIHRoZSBpbnZlcnNlIHJlbGF0aW9uc2hpcCBmb3VuZCBpbiB0aGUgaW5pdGlhbCBtb2RlbCBtYXkgYmUgdGhlIG51bWJlciBvZiBMU09B4oCZcyB3aGljaCByZWNvcmRlZCB6ZXJvIGhhdGUgY3JpbWVzLiBCZWxnaW9pb3NvIGV0IGFsLiBkaXNjdXNzIHRoaXMgaW4gdGhlaXIgU3VwcGxlbWVudGFyeSBBcHBlbmRpeCwgdGhleSBydW4gdGhlIHNhbWUgbW9kZWwgYnV0IGV4Y2x1ZGUgTFNPQeKAmXMgY29udGFpbmluZyBubyBoYXRlIGNyaW1lLCBwb3NpdGluZyB0aGlzIG1heSBiZSBkdWUgdG8gc29tZSBhcmVhcyBmYWlsaW5nIHRvIGFjY3VyYXRlbHkgcmVwb3J0IHRoZWlyIGhhdGUgY3JpbWUgc3RhdGlzdGljcywgaG93ZXZlciB3aGVuIHJ1bm5pbmcgdGhpcyBtb2RlbCB0aGV5IGZpbmQgaXQgZG9lcyBub3QgY2hhbmdlIHRoZSBhbmFseXNlcyAoQmVsZ2lvaW9zbywgZXQgYWwuLCAyMDIzLCBwLiA2KS4gSG93ZXZlciwgdGhpcyBlZmZlY3QgbWF5IGJlY29tZSBtb3JlIGFwcGFyZW50IHdpdGggdGhlIGluY2x1c2lvbiBvZiBsZWF2ZSB2b3RlIGRhdGEsIGFzIExTT0FzIHdpdGggYSBoaWdoIEJyZXhpdCBsZWF2ZSB2b3RlIHBlcmNlbnRhZ2UgYnV0IHplcm8gcmVjb3JkZWQgaGF0ZSBjcmltZXMgd2lsbCBwb3RlbnRpYWxseSBza2V3IHRoZSBtb2RlbCBhbmQgcHJvZHVjZSB0aGUgaW52ZXJzZSByZWxhdGlvbnNoaXAgYXMgd2FzIHNlZW4gaW4gbXkgbW9kZWwuIEFub3RoZXIgYW5hbHlzaXMgb2YgdGhpcyBkYXRhIGV4Y2x1ZGluZyBMU09B4oCZcyB3aXRoIHplcm8gaGF0ZSBjcmltZXMgd291bGQgcmV2ZWFsIGlmIHRoaXMgaGFkIGFuIGltcGFjdC4NCg0KVGhlIGxhY2sgb2YgYSBzdWJzdGFudGlhbCBlZmZlY3Qgb2YgbGVhdmUgdm90ZSBvbiBoYXRlIGNyaW1lICBzdWdnZXN0cyBKYWNvYnMgJiB2YW4gU3Bhbmpl4oCZcyBjb25jbHVzaW9ucyBmcm9tIHRoZWlyIHN0dWR5IGluIHRoZSBOZXRoZXJsYW5kcyBtYXkgbm90IGhvbGQgdHJ1ZSBoZXJlLCBhbmQgZmFjdG9ycyBzdWNoIGFzIGZlYXIgb2YgaW1taWdyYXRpb24gaW4gbG9jYWwgY29tbXVuaXRpZXMgbWF5IG5vdCBoYXZlIGJlZW4gYSBkcml2aW5nIGZhY3RvciBvZiB3aGV0aGVyIHBlb3BsZSBhY3R1YWxseSBjb21taXQgaGF0ZSBjcmltZXMsIGZ1cnRoZXIgaW5mb3JtYXRpb24gb24gaW5kaXZpZHVhbOKAmXMgb3BpbmlvbnMgb24gaW1taWdyYXRpb24gbWF5IGhlbHAgZXhwbGFpbiB3aGV0aGVyIHRoaXMgaXMgdGhlIGNhc2UsIG9yIGlmIGZlYXIgb2YgaW1taWdyYXRpb24gd2FzIHN1YnN0YWludGlhbCBpbiBjb21tdW5pdGllcyB3aGljaCB2b3RlZCBmb3IgQnJleGl0LiAgDQoNCg0KIyMgQWNhZGVtaWMgUmVmZXJlbmNlcw0KDQpGcmVlc2UsIEouLCAmIFBldGVyc29uLCBELiAoMjAxNykuIFJlcGxpY2F0aW9uIGluIHNvY2lhbCBzY2llbmNlLiAqQW5udWFsIFJldmlldyBvZiBTb2Npb2xvZ3kqLCA0MywgMTQ3LTE2NSwgW2RvaTogMTAuMTE0Nl0oaHR0cHM6Ly93d3cuYW5udWFscmV2aWV3cy5vcmcvZG9pL2Ficy8xMC4xMTQ2L2FubnVyZXYtc29jLTA2MDExNi0wNTM0NTApLg0KDQpCZWxnaW9pb3NvLCBNLiwgRHdvcnNjaGFrLCBDLiAmIEdsZWRpdHNjaEksIEsuIFMuLCAyMDIzLiBMb2NhbCBkZXByaXZhdGlvbiBwcmVkaWN0cyByaWdodC13aW5nIGhhdGUgY3JpbWU6IFMxIFN1cHBsZW1lbnRhcnkgQXBwZW5kaXguIFBMT1MgT05FLCA2IFNlcHRlbWJlci4xOCg5KS4NCg0KQmVsZ2lvaW9zbywgTS4sIER3b3JzY2hhaywgQy4gJiBHbGVkaXRzY2gsIEsuIFMuLCAyMDIzLiBMb2NhbCBkZXByaXZhdGlvbiBwcmVkaWN0cyByaWdodC13aW5nIGhhdGUgY3JpbWUgaW4gRW5nbGFuZC4gUGxvcyBPbmUsIDE4KDkpLg0KDQpDbGFya2UsIEguIEQuLCBHb29kd2luLCBNLiAmIFdoaXRlbGV5LCBQLiwgMjAxNy4gV2h5IEJyaXRhaW4gVm90ZWQgZm9yIEJyZXhpdDogQW4gSW5kaXZpZHVhbC1MZXZlbCBBbmFseXNpcyBvZiB0aGUgMjAxNiBSZWZlcmVuZHVtIFZvdGUuIFBhcmxpYW1lbnRhcnkgQWZmYWlycywgNzAoMyksIHAuIDQzOeKAkzQ2NC4NCg0KRGV2aW5lLCBELiwgMjAxOC4gVGhlIFVLIFJlZmVyZW5kdW0gb24gTWVtYmVyc2hpcCBvZiB0aGUgRXVyb3BlYW4gVW5pb24gYXMgYSBUcmlnZ2VyIEV2ZW50IGZvciBIYXRlIENyaW1lcywgU291dGhoYW1wdG9uOiBTU1JOLg0KDQoNCkZyZWVzZSwgSi4gJiBQZXRlcnNvbiwgRC4sIDIwMTcuIFJlcGxpY2F0aW9uIGluIFNvY2lhbCBTY2llbmNlLiBBbm51YWwgUmV2aWV3IG9mIFNvY2lvbG9neSwgVm9sdW1lIDQzLCBwcC4gMTQ3LTE2NS4NCg0KR29yYXJkLCBTLiwgMjAwMy4gV2hhdCBpcyBNdWx0aeKAk2xldmVsIE1vZGVsbGluZyBGb3I/LiBCcml0aXNoIEpvdXJuYWwgb2YgRWR1Y2F0aW9uYWwgU3R1ZGllcywgNTEoMSksIHBwLiA0Ni02My4NCg0KSmFjb2JzLCBMLiAmIHZhbiBTcGFuamUsIEouLCAyMDIxLiBBIFRpbWUtU2VyaWVzIEFuYWx5c2lzIG9mIENvbnRleHR1YWwtTGV2ZWwgRWZmZWN0cyBvbiBIYXRlIENyaW1lIGluIFRoZSBOZXRoZXJsYW5kcy4gU29jaWFsIEZvcmNlcywgMTAwKDEpLCBwLiAxNjnigJMxOTMuDQoNCktpbmcgRC4sIFIuICYgU3V0dG9uLCBHLiBNLiwgMjAxMy4gSGlnaCBUaW1lcyBmb3IgSGF0ZSBDcmltZXM6IEV4cGxhaW5pbmcgdGhlIFRlbXBvcmFsIENsdXN0ZXJpbmcgb2YgSGF0ZS1Nb3RpdmF0ZWQgT2ZmZW5kaW5nLiBDcmltaW5vbG9neSwgNTEoNCksIHBwLiA4NzEtODk0Lg0KDQpQaWF0a293c2thLCBTLiBKLiAmIFN0dWx0cywgQi4gSi4sIDIwMjIuIEJyZXhpdCwgVGVycm9yaXN0IEF0dGFja3MsIGFuZCBIYXRlIENyaW1lOiBBIExvbmdpdHVkaW5hbCBBbmFseXNpcy4gU29jaWFsIFByb2JsZW1zLCA2OSg0KSwgcC4gOTY44oCTOTk2Lg0KDQojIyBEYXRhIFJlZmVyZW5jZXMNCg0KRHdvcnNjaGFrLCBDLiwgMjAyMy4gUmVwbGljYXRpb24gRGF0YSBmb3I6IExvY2FsIGRlcHJpdmF0aW9uIHByZWRpY3RzIHJpZ2h0LXdpbmcgaGF0ZSBjcmltZSBpbiBFbmdsYW5kLCBzLmwuOiBIYXJ2YXJkIERhdGF2ZXJzZS4NCmh0dHBzOi8vZGF0YXZlcnNlLmhhcnZhcmQuZWR1L2RhdGFzZXQueGh0bWw/cGVyc2lzdGVudElkPWRvaToxMC43OTEwL0RWTi9HU1JQUVkgDQpodHRwczovL2RvaS5vcmcvMTAuNzkxMC9EVk4vR1NSUFFZIA0KDQpUaGUgRWxlY3RvcmFsIENvbW1pc3Npb24sIDIwMjEuIEVVIFJlZmVyZW5kdW0gUmVzdWx0cywgTG9uZG9uOiBHcmVhdGVyIExvbmRvbiBBdXRob3JpdHkuDQpBY2Nlc3NpYmxlIGhlcmUgYXMgb2YgMTYvMDUvMjAyNDogDQpodHRwczovL3d3dy5kYXRhLmdvdi51ay9kYXRhc2V0L2JlMmYyYWVjLTExZDgtNGJmZS05ODAwLTY0OWU1YjhlYzA0NC9ldS1yZWZlcmVuZHVtLXJlc3VsdHMNCg0KTEFEIFNoYXBlZmlsZSBieSB0aGUgT2ZmaWNlIG9mIE5hdGlvbmFsIFN0YXRpc3RpY3MgT3BlbiBHZW9ncmFwaHkgUG9ydGFsDQpEYXRhIGlzIGF2YWlsYWJsZSBmcm9tIHRoZSBmb2xsb3dpbmcgbGluayBhcyBvZiAzMC8wNS8yMDI0OiBodHRwczovL2dlb3BvcnRhbC5zdGF0aXN0aWNzLmdvdi51ay9kYXRhc2V0cy9vbnM6OmxvY2FsLWF1dGhvcml0eS1kaXN0cmljdHMtZGVjZW1iZXItMjAyMy1ib3VuZGFyaWVzLXVrLWJ1Yy0yL2Fib3V0IA0KDQoNCg0KIyMgQXBwZW5kaXgNCg0KIyMjIEFwcGVuZGl4IDEuIE15IGVudmlyb21lbnQgKGZ1bGwgaW5mb3JtYXRpb24pIA0KDQpgYGB7ciBzZXNzaW9ufQ0KIyBEZXRhaWxlZCBpbmZvcm1hdGlvbiBhYm91dCBteSBlbnZpcm9ubWVudA0Kc2Vzc2lvbkluZm8oKQ0KYGBgDQoNCiMjIyBBcHBlbmRpeCAyLiBFbnRpcmUgUiBjb2RlIHVzZWQgaW4gdGhlIHByb2plY3QNCg0KYGBge3IgcmVmLmxhYmVsPWtuaXRyOjphbGxfbGFiZWxzKCksIGVjaG89VFJVRSwgZXZhbD1GQUxTRX0NCmBgYA0K