In this practical you will be analysing a sample of the teaching dataset of the Crime Survey for England and Wales available here from the UK Data Service. But you can access it from the folder Crime_workshop in the “C:” folder of the PC in the cluster.

1. Before we start

1.1. Define a working directory

You can use the directory on University-owned machines, as it provides a stable drive to work on (“C:”). If you’re using your own machine, you can specify any folder you find convenient.

Also note that you need to take your data and results with you and delete what you store on the C-drive after this session (if you are not using your own laptop).

1.2. Open a new Script

First, open a new script in R studio and save it in your working directory, so you will be able to access this script at a later time if you want to revise or modify a code.

In R Studio:

Go to File… New File…. R script

1.3. Load the packages

Remember to load the packages. We will be using tidyverse and haven

library(haven)
## Warning: package 'haven' was built under R version 3.6.2
library(tidyverse)
## Warning: package 'tidyverse' was built under R version 3.6.2
## Warning: package 'tidyr' was built under R version 3.6.2
## Warning: package 'purrr' was built under R version 3.6.2

As a first step in a research project we need to start with a purpose:

2. Import the data into R

Import the dataset called crime_survey.dta into the console using your desired method (code or point and click). This dataset can only be imported if you have loaded the package haven.

# Do it yourself

csew<- 

3. Exploratory Data Analysis

3.1 Dataset exploration

Task 1: Inspect the dataset, use the function View()

View(csew)

You can also use the function head() that shows you the first 6 rows of the data set, this function is useful to have a look at the data within the console, specially when you have large datasets.

There is also an antithesis function to head() called tail(). Can you guess what that function does?

(Hint: you can run the code in the console and see it by yourself, or a quick search in Google may also help.)

head(csew)

Data obtained from the UK Data Service always come with a wealth of resources and user guides that help us to understand the data, so I would always encourage you to check the documentation associated with the data used.This documentation also includes information about the sample, the questionnaire, the variables available and how to use them.

Sadly, this is not always the case with data from different sources, in those cases the initial exploration of the data is probably our main source of information about the data itself.

Now that we got the data in the console, let’s start with our data exploration:

Task 1.1 How many observations does the data have?____________

Task 1.2 How many variables?______________

Another function used to get a “glimpse” at your data is using the function glimpse().

glimpse(csew)

Note the data type of almost all variables is <dbl+lbl>. These are labelled variables in the haven package. It’s the way to identify variables with labels from Stata.

3.2 Variable exploration

Let’s use another function to have a closer look, this time at the variables. Let’s use this with the variable ‘sex’

attributes(csew$sex)
## $label
## [1] "Respondent's gender"
## 
## $format.stata
## [1] "%8.0g"
## 
## $class
## [1] "haven_labelled"
## 
## $labels
##   Male Female 
##      1      2

We have the $class attribute which says that sex is a haven_labelled type. We also have the $labels attribute which are the Value Labels of the variable sex: 1 Man, 2 Woman

We could have also used class(hse$sex) to check the type of the variable.

Task 2 Inspect other variables with attributes() and class()

4. Understanding our data

Now that we have had a look at what variables we have, we need to start looking for other aspects of the exploratory data analysis (EDA) process. These are some of the things to look out for:

  • Checking for outliers (unusual values)
  • Looking at the distribution of the variables
  • Exploring some relationships and patterns
  • Checking for missing cases

4.1. Univariate analysis

We can use a series of descriptive statistics and graphs to help us to understand and make sense of the data.

Univariate exploration is when we look at the characteristics of each variable of interest independently.

Univariate Descriptive statistic for categorical (factor) data

Let’s see what happens when we ask for a frequency table

table(csew$sex)
## 
##     1     2 
## 16176 19195

Right now, the variable does not contain any visible labels that help us to identify each category of response, although we know the underlying values of each label thanks to the attribute function.

This is one of the inconveniences of working with data with labels in R, but it is good for you to know what to do in this case.

Although we can use the data as it is, I prefer to see the values of the variables, so we are going to change the class of some variables to make them easier to analyse.

We can use the function as_factor() from the package haven to convert the variable into a factor variable (equivalent to categorical variable). Copy the following code in your console.

csew$sexf<-as_factor(csew$sex) 
table(csew$sexf)
## 
##   Male Female 
##  16176  19195

Here we created a new variable with the suffix “f” (for factor).

Task 3: Convert the following variables into factor using the example code before.

  • nation: adult respondent nationality
  • educat3: respondent education (5 categories)
  • ethgrp5a: ethnic group
  • bcsvictim: Experience of any crime in the previous 12 months

Missing values

In R missing values are identified as NA.

Now inspect whether there are missing values in our variables

#is.na(csew$sexf)

sum(is.na(csew$sexf))
## [1] 0
sum(is.na(csew$nationf))
## [1] 0

The function is.na is a logical function which looks at each observation and evaluates whether it is a valid case or a missing case. It will show a series of values TRUE for those observations that are missing and FALSE for valid cases (is.na = FALSE means that the cases are valid).

It is a good function to explore missingness, but it is not very practical on its own (as you could see in the example) that is why it is often used along other statistics.

I used the statistic sum which will add all the TRUE values of is.na so the result will be the number of NA (missing cases) for a particular variable.

The data shows that there are no missing values, but we can infer that the values 8 and 9 can be classified as missing cases, so we recode them as missing

csew$nationf<- recode(csew$nationf, "Refused" = "NA", "Don't know" = "NA")

table(csew$nationf)
## 
##      UK, British          English         Scottish            Welsh 
##            21106             9780              306             1519 
##         Northern Irish (Republic)            Other               NA 
##               73              269             2298               20

We have successfully recoded those values as missing, now we need to tell R Studio to treat those values as missing too

csew$nationf<- na_if(csew$nationf, "NA")

csew$nationf<- droplevels(csew$nationf) #with this code we got rid of the category for NA
table(csew$nationf)
## 
##      UK, British          English         Scottish            Welsh 
##            21106             9780              306             1519 
##         Northern Irish (Republic)            Other 
##               73              269             2298

Task 4: Check for missing values in the following variables and deal with them accordingly:

  • educat3: respondent education (5 categories)
  • ethgrp5a: ethnic group
  • bcsvictim: Experience of any crime in the previous 12 months

Univariate Descriptive statistic for continuous (numeric) data

We can get summaries of the main statistics using the base function summary(). This function gives us the minimum and maximum values, the mean, median and the quartiles.

It is really useful to check for extreme values. Let’s have a go

#This uses basic functions from R
summary(csew$age)
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
##   16.00   36.00   51.00   54.35   66.00  999.00

summary() does not give any measure of the spread of the data, we can use other functions available in base R for that sd() for standard deviation.

# Standard deviation
sd(csew$age)
## [1] 57.68425

so far we have used two different functions of base R for exploratory data analysis. We can obtain the same statistics and more using a combination of different function from the package tidyverse taking advantage of the %>% (pipe) operator from the package magrittr which is fully implemented in tidyverse, so there is no need to install anything else.

I’m a firmer believer (although I may be wrong) that the best way to learn is putting into practice, so this is a perfect opportunity to put %>% into practice. (You can check your notes of tutorial 1 for more details on how to use them).

Let’s start with the summarise function from the package dplyr (also part of tidyverse) This function allows us to create summary statistic of our variables in one single code

#using function from the package dplyr (tidyverse)
csew %>% 
  summarise(mean_age= mean(age)) # we create the variable mean_age
## # A tibble: 1 x 1
##   mean_age
##      <dbl>
## 1     54.4

That was good but not very impressive, was it? We can add more functions to that code and ask for more:

csew %>% 
  summarise(mean_age= mean(age), 
            sd_age= sd(age),
            median_age = median(age),
            min_age = min(age),
            max_age = max(age)) 
## # A tibble: 1 x 5
##   mean_age sd_age median_age min_age max_age
##      <dbl>  <dbl>  <dbl+lbl>   <dbl>   <dbl>
## 1     54.4   57.7         51      16     999

One of the advantages of using %>% is that we can add more functions to our code as a set of instructions. In the example below, I added the function filter() of the package dplyr to exclude all missing cases from the analysis.

The function is.na() (is missing?) will select all missing cases, but when used along the ! it means totally the opposite, so in this code this stand for filter all the cases of variable age that are not missing

csew %>%
  filter(!is.na(age)) %>%
  summarise(mean_age= mean(age), 
            sd_age= sd(age),
            median_age = median(age),
            min_age = min(age),
            max_age = max(age)) 
## # A tibble: 1 x 5
##   mean_age sd_age median_age min_age max_age
##      <dbl>  <dbl>  <dbl+lbl>   <dbl>   <dbl>
## 1     54.4   57.7         51      16     999

We can even add more variables! but for that we might need another function and the chance to use more pipes %>%.

  • select: This function allows to select specific variable from the datasets.
  • summarise_all: allows to apply the same transformation to multiple variables
  • list: used to make a list of functions to apply, in this example, mean and sd
csew %>% 
  select(age, antisocx) %>%
  summarise_all(list(mean= mean, sd= sd, median = median), na.rm = TRUE)
## # A tibble: 1 x 6
##   age_mean antisocx_mean age_sd antisocx_sd age_median antisocx_median
##      <dbl>         <dbl>  <dbl>       <dbl>  <dbl+lbl>           <dbl>
## 1     54.4 0.00000000547   57.7       1.000         51          -0.177

What can we say about age?

The distribution of the variable age seems reasonable, the mean and the median are very similar.

The standard deviation shows how spread the data are. A standard deviation of 57.68 is quite high, which might indicate a lot of variation in the distribution of age. This is clearly hinting that there is something odd about the variable.

We also saw that the maximum value for age is 999, which is clearly a number out of range; Nobody can live for 999 years! This is probably the reason why the standard deviation is so high, we clearly need further exploration of this unusual value

In certain cases the maximum values can be less obvious, so it would be difficult to determine whether there are outliers or data errors, that is why we need to complement these initial checks with visual exploration.

Diagnostic, critical points regarding age

  • high standard deviation
  • Implausible values (error?, missing values?, outliers?)

Actions

  • both problems might be related
  • check 999 values and deal with them accordingly
  • check if SD changes after 999 values are taken into account
class(csew$age)
## [1] "haven_labelled"
attributes(csew$age)
## $label
## [1] "Respondent's age"
## 
## $format.stata
## [1] "%8.0g"
## 
## $class
## [1] "haven_labelled"
## 
## $labels
##    Refused Don't know 
##        998        999

using the function attributes() we now know

  • age is formatted as “%8.0g” which is a way of storing numeric data in Stata.
  • age is a “haven_labelled” variables, which means there are certain values with labels
  • The values and labels 998 and 999 are for “refused” and “don’t know” respectively.

998 and 999 can be classified as missing cases (unless you are interested in knowing the patterns of non-response). So we can easily solve that problem.

csew$age[csew$age==998 | csew$age==999 ]<-NA 

Task 5: Get summary statistics for the variables confx, fair and effectx. Make note of any patterns or unusual values. A description of the variables can be found in this user guide

Task 5.1 Write down a short description of the main statistics you’ve obtained

Task 5.2 Is there any unusual value in the variables you have analysed?

4.2. Visual exploration

We can use a combination of bar plots, histograms, boxplots and scatter plots as the basis for our data exploration

bar plots of categorical data

ggplot(data = csew) +
  geom_bar(mapping = aes(x = sexf))

histogram for continuous data

ggplot(data = csew) +
  geom_histogram(mapping = aes(x=age), binwidth = 0.5, na.rm = TRUE)
## Don't know how to automatically pick scale for object of type haven_labelled. Defaulting to continuous.

Both bar charts and histograms can be used to detect outliers and unusual patterns of the data.

Task 6: Visually explore the variables that we have used in the previous task. Make a note of any unusual patterns that you can find.

4.3. Association between variables

More insight can be gained when looking at relationships between variables. This can be done in two main ways: using numerical representation of this association and visual representations.

Associations using “crosstabs” or “contingency” tables

For categorical data we can use contingency tables (also called crosstabs)

Here we will be using a new package called janitor.

#install.packages("janitor") 
library(janitor)
## Warning: package 'janitor' was built under R version 3.6.2
csew %>%
  tabyl(sexf, nationf, show_na = FALSE) %>% #excludes NA values from the table
  adorn_percentages("row") %>% # takes row percentage
  adorn_pct_formatting(digits = 2) %>% # limit % to 2 digits
  adorn_ns() #add the cell count
##    sexf    UK, British       English    Scottish       Welsh   Northern
##    Male 57.10%  (9232) 30.23% (4887) 0.91% (147) 4.26% (689) 0.18% (29)
##  Female 61.90% (11874) 25.51% (4893) 0.83% (159) 4.33% (830) 0.23% (44)
##  Irish (Republic)        Other
##       0.79% (127) 6.53% (1056)
##       0.74% (142) 6.47% (1242)

Task 7: Explore the relationship between victim of crime and sex, ethnic group, nationality and educational level. Make notes of your findings

Looking at association through visualisations

Now we need to focus on our variable of interest (outcome usually represented as the ‘y’ variable) and its association with other explanatory variables (x variables).

Here we will be looking at the associations between confidence in the effectiveness of Criminal Justice System (effectx) and other individual characteristics of the respondents.

Two continuous variables

-Scatter plots: For looking at the relationship between two continuous variables. This is useful to assess co-variation.

ggplot(data = csew, mapping = aes(x = age, y = effectx)) + 
  geom_point(na.rm = TRUE)
## Don't know how to automatically pick scale for object of type haven_labelled. Defaulting to continuous.

We received a warning regarding a labelled variable, further exploration reveals that the variable age is numeric but contains two labels (“haven_labelled”) for “refused” and “don’t know”.

The as.numeric() function will create a copy of the variable age of class “numeric”. The function will get rid of the labels.

csew$age2<-as.numeric(csew$age)

You can check that we now got rid of the warning.

Categorical and continuous variables

  • boxplot: ideal for detecting outliers. Here we obtain boxplots by groups
ggplot(data = csew, mapping = aes(x = sexf, y = effectx)) +
  geom_boxplot(na.rm = TRUE)

We can add colours to the ouliers

ggplot(data = csew, mapping = aes(x = sexf, y = effectx)) +
  geom_boxplot(outlier.colour = "red", na.rm = TRUE)

Task 8: Explore the associations between effectiveness in the Criminal Justice System and nationality, ethnic group, victim of crime

Task 9: After all the bivariate exploration that you have done. Have you found any difference in the perception of the effectiveness in the Criminal Justice System according to:

  • sex____________________________________________________________ _________________________________________________________________
  • ethnic group: _________________________________________________ _________________________________________________________________
  • Victims: ______________________________________________________ _________________________________________________________________

Task 10: Can you think in any hypothesis that can help us to understand the differences in the perception of how effective the Criminal Justice System is?

5. Saving data

We can save the data we have been using, we can select different export methods, depending on the format in which we want our data to be stored. Here we will save the changes that we have made to the “csew” dataset as R data. This means that we don’t need to import it again (we still need to load it) to use in another R session.

save(csew, file= "csew.RData")
LS0tDQp0aXRsZTogIkV4cGxvcmF0b3J5IERhdGEgQW5hbHlzaXMgdXNpbmcgdGhlIENyaW1lIFN1cnZleSBmb3IgRW5nbGFuZCBhbmQgV2FsZXMiDQphdXRob3I6ICJBbmEgTW9yYWxlcy1Hb21leiINCmRhdGU6ICIwNCAtIEZlYiAtMjAyMCINCmZvbnRzaXplOiAxMnB0DQpvdXRwdXQ6IA0KICBodG1sX2RvY3VtZW50Og0KICAgIGhpZ2hsaWdodGVyOiBudWxsDQogICAgdGhlbWU6ICJjb3NtbyINCiAgICBjb2RlX2Rvd25sb2FkOiBUUlVFDQogICAgdG9jOiBUUlVFDQogICAgdG9jX2Zsb2F0OiBUUlVFDQogICAgdG9jX2RlcHRoOiAyDQotLS0NCg0KYGBge3Igc2V0dXAsIGluY2x1ZGU9RkFMU0V9DQprbml0cjo6b3B0c19jaHVuayRzZXQoZWNobyA9IFRSVUUpDQpgYGANCg0KSW4gdGhpcyBwcmFjdGljYWwgeW91IHdpbGwgYmUgYW5hbHlzaW5nIGEgc2FtcGxlIG9mIHRoZSB0ZWFjaGluZyBkYXRhc2V0ICBvZiB0aGUgQ3JpbWUgU3VydmV5IGZvciBFbmdsYW5kIGFuZCBXYWxlcyBhdmFpbGFibGUgW2hlcmVdKGh0dHBzOi8vYmV0YS51a2RhdGFzZXJ2aWNlLmFjLnVrL2RhdGFjYXRhbG9ndWUvc3R1ZGllcy9zdHVkeT9pZD03OTExKSBmcm9tIHRoZSBbVUsgRGF0YSBTZXJ2aWNlXShodHRwczovL3d3dy51a2RhdGFzZXJ2aWNlLmFjLnVrLykuIEJ1dCB5b3UgY2FuIGFjY2VzcyBpdCBmcm9tIHRoZSBmb2xkZXIgKipDcmltZV93b3Jrc2hvcCoqIGluIHRoZSAiQzpcV29yayIgZm9sZGVyIG9mIHRoZSBQQyBpbiB0aGUgY2x1c3Rlci4NCg0KIyAxLiBCZWZvcmUgd2Ugc3RhcnQNCg0KIyMjIDEuMS4gRGVmaW5lIGEgd29ya2luZyBkaXJlY3RvcnkNCg0KWW91IGNhbiB1c2UgdGhlIGRpcmVjdG9yeSAgb24gVW5pdmVyc2l0eS1vd25lZCBtYWNoaW5lcywgYXMgaXQgcHJvdmlkZXMgYSBzdGFibGUgZHJpdmUgdG8gd29yayBvbiAoIkM6XFdvcmsiKS4gSWYgeW91J3JlIHVzaW5nIHlvdXIgb3duIG1hY2hpbmUsIHlvdSBjYW4gc3BlY2lmeSBhbnkgZm9sZGVyIHlvdSBmaW5kIGNvbnZlbmllbnQuDQoNCkFsc28gbm90ZSB0aGF0IHlvdSBuZWVkIHRvIHRha2UgeW91ciBkYXRhIGFuZCByZXN1bHRzIHdpdGggeW91IGFuZCBkZWxldGUgd2hhdCB5b3Ugc3RvcmUgb24gdGhlIEMtZHJpdmUgYWZ0ZXIgdGhpcyBzZXNzaW9uIChpZiB5b3UgYXJlIG5vdCB1c2luZyB5b3VyIG93biBsYXB0b3ApLiAgDQoNCg0KIyMjIDEuMi4gT3BlbiBhIG5ldyBTY3JpcHQNCg0KRmlyc3QsIG9wZW4gYSBuZXcgc2NyaXB0IGluIFIgc3R1ZGlvIGFuZCBzYXZlIGl0IGluIHlvdXIgd29ya2luZyBkaXJlY3RvcnksIHNvIHlvdSB3aWxsIGJlIGFibGUgdG8gYWNjZXNzIHRoaXMgc2NyaXB0IGF0IGEgbGF0ZXIgdGltZSBpZiB5b3Ugd2FudCB0byByZXZpc2Ugb3IgbW9kaWZ5IGEgY29kZS4gIA0KDQpJbiBSIFN0dWRpbzogIA0KDQpHbyB0byBGaWxlLi4uIE5ldyBGaWxlLi4uLiBSIHNjcmlwdA0KICANCg0KIyMjIDEuMy4gTG9hZCB0aGUgcGFja2FnZXMNCg0KUmVtZW1iZXIgdG8gbG9hZCB0aGUgcGFja2FnZXMuIFdlIHdpbGwgYmUgdXNpbmcgYHRpZHl2ZXJzZWAgYW5kIGBoYXZlbmANCg0KYGBge3IsIG1lc3NhZ2U9RkFMU0V9DQoNCmxpYnJhcnkoaGF2ZW4pDQpsaWJyYXJ5KHRpZHl2ZXJzZSkNCmBgYA0KDQoNCg0KQXMgYSBmaXJzdCBzdGVwIGluIGEgcmVzZWFyY2ggcHJvamVjdCB3ZSBuZWVkIHRvIHN0YXJ0IHdpdGggYSBwdXJwb3NlOg0KDQoNCg0KDQojIDIuIEltcG9ydCB0aGUgZGF0YSBpbnRvIFINCg0KSW1wb3J0IHRoZSBkYXRhc2V0IGNhbGxlZCBjcmltZV9zdXJ2ZXkuZHRhIGludG8gdGhlIGNvbnNvbGUgdXNpbmcgeW91ciBkZXNpcmVkIG1ldGhvZCAoY29kZSBvciBwb2ludCBhbmQgY2xpY2spLiBUaGlzIGRhdGFzZXQgY2FuIG9ubHkgYmUgaW1wb3J0ZWQgaWYgeW91IGhhdmUgbG9hZGVkIHRoZSBwYWNrYWdlIGBoYXZlbmAuIA0KDQpgYGB7ciwgZWNobz1GQUxTRX0NCnNldHdkKCJDOi9Vc2Vycy9BbWFuZGEvRGVza3RvcC9hbml0YS9DcmltZS13b3Jrc2hvcCIpDQoNCmNzZXcgPC0gcmVhZF9kdGEoIkNTRVcvVUtEQS03OTExLXN0YXRhL3N0YXRhL3N0YXRhMTEvY3NldzEzMTRfdGVhY2hpbmdfZXVsMi5kdGEiKQ0KDQpgYGANCg0KYGBge3IsIGV2YWw9RkFMU0V9DQojIERvIGl0IHlvdXJzZWxmDQoNCmNzZXc8LSANCg0KYGBgDQoNCg0KDQojIDMuIEV4cGxvcmF0b3J5IERhdGEgQW5hbHlzaXMNCg0KIyMgMy4xIERhdGFzZXQgZXhwbG9yYXRpb24NCg0KKipUYXNrIDEqKjogSW5zcGVjdCB0aGUgZGF0YXNldCwgdXNlIHRoZSBmdW5jdGlvbiBWaWV3KCkNCg0KYGBge3IsIGV2YWw9RkFMU0V9DQoNClZpZXcoY3NldykNCg0KYGBgDQoNCllvdSBjYW4gYWxzbyB1c2UgdGhlIGZ1bmN0aW9uIGBoZWFkKClgIHRoYXQgc2hvd3MgeW91IHRoZSBmaXJzdCA2IHJvd3Mgb2YgdGhlIGRhdGEgc2V0LCB0aGlzIGZ1bmN0aW9uIGlzIHVzZWZ1bCB0byBoYXZlIGEgbG9vayBhdCB0aGUgZGF0YSB3aXRoaW4gdGhlIGNvbnNvbGUsIHNwZWNpYWxseSB3aGVuIHlvdSBoYXZlIGxhcmdlIGRhdGFzZXRzLg0KDQpUaGVyZSBpcyBhbHNvIGFuIGFudGl0aGVzaXMgZnVuY3Rpb24gdG8gYGhlYWQoKWAgY2FsbGVkIGB0YWlsKClgLiBDYW4geW91IGd1ZXNzIHdoYXQgdGhhdCBmdW5jdGlvbiBkb2VzPyAgIA0KDQooKipIaW50Kio6IHlvdSBjYW4gcnVuIHRoZSBjb2RlIGluIHRoZSBjb25zb2xlIGFuZCBzZWUgaXQgYnkgeW91cnNlbGYsIG9yIGEgcXVpY2sgc2VhcmNoIGluIEdvb2dsZSBtYXkgYWxzbyBoZWxwLikNCg0KYGBge3IsIGV2YWw9RkFMU0V9DQpoZWFkKGNzZXcpDQpgYGANCg0KRGF0YSBvYnRhaW5lZCBmcm9tIHRoZSBVSyBEYXRhIFNlcnZpY2UgYWx3YXlzIGNvbWUgd2l0aCBhIHdlYWx0aCBvZiByZXNvdXJjZXMgYW5kIHVzZXIgZ3VpZGVzIHRoYXQgaGVscCB1cyB0byB1bmRlcnN0YW5kIHRoZSBkYXRhLCBzbyBJIHdvdWxkIGFsd2F5cyBlbmNvdXJhZ2UgeW91IHRvIGNoZWNrIHRoZSBkb2N1bWVudGF0aW9uIGFzc29jaWF0ZWQgd2l0aCB0aGUgZGF0YSB1c2VkLlRoaXMgZG9jdW1lbnRhdGlvbiBhbHNvIGluY2x1ZGVzIGluZm9ybWF0aW9uIGFib3V0IHRoZSBzYW1wbGUsIHRoZSBxdWVzdGlvbm5haXJlLCB0aGUgdmFyaWFibGVzIGF2YWlsYWJsZSBhbmQgaG93IHRvIHVzZSB0aGVtLiAgIA0KDQpTYWRseSwgdGhpcyBpcyBub3QgYWx3YXlzIHRoZSBjYXNlIHdpdGggZGF0YSBmcm9tIGRpZmZlcmVudCBzb3VyY2VzLCBpbiB0aG9zZSBjYXNlcyB0aGUgaW5pdGlhbCBleHBsb3JhdGlvbiBvZiB0aGUgZGF0YSBpcyBwcm9iYWJseSBvdXIgbWFpbiBzb3VyY2Ugb2YgaW5mb3JtYXRpb24gYWJvdXQgdGhlIGRhdGEgaXRzZWxmLg0KDQpOb3cgdGhhdCB3ZSBnb3QgdGhlIGRhdGEgaW4gdGhlIGNvbnNvbGUsIGxldCdzIHN0YXJ0IHdpdGggb3VyIGRhdGEgZXhwbG9yYXRpb246DQoNCg0KKipUYXNrIDEuMSoqIEhvdyBtYW55IG9ic2VydmF0aW9ucyBkb2VzIHRoZSBkYXRhIGhhdmU/X19fX19fX19fX19fDQoNCg0KKipUYXNrIDEuMioqIEhvdyBtYW55IHZhcmlhYmxlcz9fX19fX19fX19fX19fXw0KDQoNCg0KDQpBbm90aGVyIGZ1bmN0aW9uIHVzZWQgdG8gZ2V0IGEgImdsaW1wc2UiIGF0IHlvdXIgZGF0YSBpcyB1c2luZyB0aGUgZnVuY3Rpb24gYGdsaW1wc2UoKWAuDQoNCg0KDQpgYGB7ciwgZXZhbD1GQUxTRX0NCg0KZ2xpbXBzZShjc2V3KQ0KDQoNCmBgYA0KDQoNCk5vdGUgdGhlIGRhdGEgdHlwZSBvZiBhbG1vc3QgYWxsIHZhcmlhYmxlcyBpcyBgPGRibCtsYmw+YC4gIFRoZXNlIGFyZSBsYWJlbGxlZCB2YXJpYWJsZXMgaW4gdGhlIGhhdmVuIHBhY2thZ2UuIEl0J3MgdGhlIHdheSB0byBpZGVudGlmeSB2YXJpYWJsZXMgd2l0aCBsYWJlbHMgZnJvbSBTdGF0YS4NCg0KDQoNCiMjMy4yIFZhcmlhYmxlIGV4cGxvcmF0aW9uIA0KDQoNCkxldCdzIHVzZSBhbm90aGVyIGZ1bmN0aW9uIHRvIGhhdmUgYSBjbG9zZXIgbG9vaywgdGhpcyB0aW1lIGF0IHRoZSB2YXJpYWJsZXMuIExldCdzIHVzZSB0aGlzIHdpdGggdGhlIHZhcmlhYmxlICdzZXgnDQpgYGB7cn0NCg0KYXR0cmlidXRlcyhjc2V3JHNleCkNCg0KYGBgDQoNCg0KV2UgaGF2ZSB0aGUgYCRjbGFzc2AgYXR0cmlidXRlIHdoaWNoIHNheXMgdGhhdCBgc2V4YCBpcyBhIGhhdmVuX2xhYmVsbGVkIHR5cGUuIFdlIGFsc28gaGF2ZSB0aGUgYCRsYWJlbHNgIGF0dHJpYnV0ZSB3aGljaCBhcmUgdGhlIFZhbHVlIExhYmVscyBvZiB0aGUgdmFyaWFibGUgYHNleGA6IDEgTWFuLCAyIFdvbWFuDQoNCldlIGNvdWxkIGhhdmUgYWxzbyB1c2VkIGBjbGFzcyhoc2Ukc2V4KWAgdG8gY2hlY2sgdGhlIHR5cGUgb2YgdGhlIHZhcmlhYmxlLg0KDQoNCioqVGFzayAyKiogSW5zcGVjdCBvdGhlciB2YXJpYWJsZXMgd2l0aCBhdHRyaWJ1dGVzKCkgYW5kIGNsYXNzKCkNCg0KDQoNCg0KIyA0LiBVbmRlcnN0YW5kaW5nIG91ciBkYXRhDQoNCk5vdyB0aGF0IHdlIGhhdmUgaGFkIGEgbG9vayBhdCB3aGF0IHZhcmlhYmxlcyB3ZSBoYXZlLCB3ZSBuZWVkIHRvIHN0YXJ0IGxvb2tpbmcgZm9yIG90aGVyIGFzcGVjdHMgb2YgdGhlIGV4cGxvcmF0b3J5IGRhdGEgYW5hbHlzaXMgKEVEQSkgcHJvY2Vzcy4gVGhlc2UgYXJlIHNvbWUgb2YgdGhlIHRoaW5ncyB0byBsb29rIG91dCBmb3I6IA0KDQotIENoZWNraW5nIGZvciBvdXRsaWVycyAodW51c3VhbCB2YWx1ZXMpDQotIExvb2tpbmcgYXQgdGhlIGRpc3RyaWJ1dGlvbiBvZiB0aGUgdmFyaWFibGVzDQotIEV4cGxvcmluZyBzb21lIHJlbGF0aW9uc2hpcHMgYW5kIHBhdHRlcm5zDQotIENoZWNraW5nIGZvciBtaXNzaW5nIGNhc2VzDQoNCiMjIDQuMS4gVW5pdmFyaWF0ZSBhbmFseXNpcw0KDQoNCldlIGNhbiB1c2UgYSBzZXJpZXMgb2YgZGVzY3JpcHRpdmUgc3RhdGlzdGljcyBhbmQgZ3JhcGhzIHRvIGhlbHAgdXMgdG8gdW5kZXJzdGFuZCBhbmQgbWFrZSBzZW5zZSBvZiB0aGUgZGF0YS4NCg0KVW5pdmFyaWF0ZSBleHBsb3JhdGlvbiBpcyB3aGVuIHdlIGxvb2sgYXQgdGhlIGNoYXJhY3RlcmlzdGljcyBvZiBlYWNoIHZhcmlhYmxlIG9mIGludGVyZXN0IGluZGVwZW5kZW50bHkuIA0KDQojIyMgVW5pdmFyaWF0ZSBEZXNjcmlwdGl2ZSBzdGF0aXN0aWMgZm9yIGNhdGVnb3JpY2FsIChmYWN0b3IpIGRhdGENCg0KDQpMZXQncyBzZWUgd2hhdCBoYXBwZW5zIHdoZW4gd2UgYXNrIGZvciBhIGZyZXF1ZW5jeSB0YWJsZQ0KDQpgYGB7cn0NCg0KdGFibGUoY3NldyRzZXgpDQpgYGANCg0KUmlnaHQgbm93LCB0aGUgdmFyaWFibGUgZG9lcyBub3QgY29udGFpbiBhbnkgdmlzaWJsZSBsYWJlbHMgdGhhdCBoZWxwIHVzIHRvIGlkZW50aWZ5IGVhY2ggY2F0ZWdvcnkgb2YgcmVzcG9uc2UsIGFsdGhvdWdoIHdlIGtub3cgdGhlIHVuZGVybHlpbmcgdmFsdWVzIG9mIGVhY2ggbGFiZWwgdGhhbmtzIHRvIHRoZSBgYXR0cmlidXRlYCBmdW5jdGlvbi4NCg0KVGhpcyBpcyBvbmUgb2YgdGhlIGluY29udmVuaWVuY2VzIG9mIHdvcmtpbmcgd2l0aCBkYXRhIHdpdGggbGFiZWxzIGluIFIsIGJ1dCBpdCBpcyBnb29kIGZvciB5b3UgdG8ga25vdyB3aGF0IHRvIGRvIGluIHRoaXMgY2FzZS4NCg0KDQpBbHRob3VnaCB3ZSBjYW4gdXNlIHRoZSBkYXRhIGFzIGl0IGlzLCBJIHByZWZlciB0byBzZWUgdGhlIHZhbHVlcyBvZiB0aGUgdmFyaWFibGVzLCBzbyB3ZSBhcmUgZ29pbmcgdG8gY2hhbmdlIHRoZSBjbGFzcyBvZiBzb21lIHZhcmlhYmxlcyB0byBtYWtlIHRoZW0gZWFzaWVyIHRvIGFuYWx5c2UuDQoNCg0KV2UgY2FuIHVzZSB0aGUgZnVuY3Rpb24gYGFzX2ZhY3RvcigpYCBmcm9tIHRoZSBwYWNrYWdlICoqaGF2ZW4qKiB0byBjb252ZXJ0IHRoZSB2YXJpYWJsZSBpbnRvIGEgZmFjdG9yIHZhcmlhYmxlIChlcXVpdmFsZW50IHRvIGNhdGVnb3JpY2FsIHZhcmlhYmxlKS4gQ29weSB0aGUgZm9sbG93aW5nIGNvZGUgaW4geW91ciBjb25zb2xlLiAgDQoNCmBgYHtyfQ0KDQpjc2V3JHNleGY8LWFzX2ZhY3Rvcihjc2V3JHNleCkgDQp0YWJsZShjc2V3JHNleGYpDQpgYGANCg0KSGVyZSB3ZSBjcmVhdGVkIGEgbmV3IHZhcmlhYmxlIHdpdGggdGhlIHN1ZmZpeCAiZiIgKGZvciBmYWN0b3IpLiANCg0KDQoqKlRhc2sgMzoqKiBDb252ZXJ0IHRoZSBmb2xsb3dpbmcgdmFyaWFibGVzIGludG8gZmFjdG9yIHVzaW5nIHRoZSBleGFtcGxlIGNvZGUgYmVmb3JlLiAgDQoNCi0gbmF0aW9uOiBhZHVsdCByZXNwb25kZW50IG5hdGlvbmFsaXR5DQotIGVkdWNhdDM6IHJlc3BvbmRlbnQgZWR1Y2F0aW9uICg1IGNhdGVnb3JpZXMpDQotIGV0aGdycDVhOiBldGhuaWMgZ3JvdXANCi0gYmNzdmljdGltOiBFeHBlcmllbmNlIG9mIGFueSBjcmltZSBpbiB0aGUgcHJldmlvdXMgMTIgbW9udGhzICANCiAgICANCiAgICANCg0KIyMjIE1pc3NpbmcgdmFsdWVzDQoNCg0KSW4gUiBtaXNzaW5nIHZhbHVlcyBhcmUgaWRlbnRpZmllZCBhcyBOQS4gIA0KDQoNCk5vdyBpbnNwZWN0IHdoZXRoZXIgdGhlcmUgYXJlIG1pc3NpbmcgdmFsdWVzIGluIG91ciB2YXJpYWJsZXMNCg0KYGBge3IsIGVjaG89RkFMU0V9DQoNCmNzZXckbmF0aW9uZjwtIGFzX2ZhY3Rvcihjc2V3JG5hdGlvbikNCg0KYGBgDQoNCmBgYHtyfQ0KDQojaXMubmEoY3NldyRzZXhmKQ0KDQpzdW0oaXMubmEoY3NldyRzZXhmKSkNCnN1bShpcy5uYShjc2V3JG5hdGlvbmYpKQ0KDQpgYGANCg0KVGhlIGZ1bmN0aW9uIGBpcy5uYWAgaXMgYSBsb2dpY2FsIGZ1bmN0aW9uIHdoaWNoIGxvb2tzIGF0IGVhY2ggb2JzZXJ2YXRpb24gYW5kIGV2YWx1YXRlcyB3aGV0aGVyIGl0IGlzIGEgdmFsaWQgY2FzZSBvciBhIG1pc3NpbmcgY2FzZS4gSXQgd2lsbCBzaG93IGEgc2VyaWVzIG9mIHZhbHVlcyBgVFJVRWAgZm9yIHRob3NlIG9ic2VydmF0aW9ucyB0aGF0IGFyZSBtaXNzaW5nIGFuZCBgRkFMU0VgIGZvciB2YWxpZCBjYXNlcyAoaXMubmEgPSBGQUxTRSBtZWFucyB0aGF0IHRoZSBjYXNlcyBhcmUgdmFsaWQpLg0KDQpJdCBpcyBhIGdvb2QgZnVuY3Rpb24gdG8gZXhwbG9yZSBtaXNzaW5nbmVzcywgYnV0IGl0IGlzIG5vdCB2ZXJ5IHByYWN0aWNhbCBvbiBpdHMgb3duIChhcyB5b3UgY291bGQgc2VlIGluIHRoZSBleGFtcGxlKSB0aGF0IGlzIHdoeSBpdCBpcyBvZnRlbiB1c2VkIGFsb25nIG90aGVyIHN0YXRpc3RpY3MuDQoNCkkgdXNlZCB0aGUgc3RhdGlzdGljIGBzdW1gIHdoaWNoIHdpbGwgYWRkIGFsbCB0aGUgYFRSVUVgIHZhbHVlcyBvZiBgaXMubmFgIHNvIHRoZSByZXN1bHQgd2lsbCBiZSB0aGUgbnVtYmVyIG9mIE5BIChtaXNzaW5nIGNhc2VzKSBmb3IgYSBwYXJ0aWN1bGFyIHZhcmlhYmxlLg0KDQpUaGUgZGF0YSBzaG93cyB0aGF0IHRoZXJlIGFyZSBubyBtaXNzaW5nIHZhbHVlcywgYnV0IHdlIGNhbiBpbmZlciB0aGF0IHRoZSB2YWx1ZXMgOCBhbmQgOSBjYW4gYmUgY2xhc3NpZmllZCBhcyBtaXNzaW5nIGNhc2VzLCBzbyB3ZSByZWNvZGUgdGhlbSBhcyBtaXNzaW5nDQoNCmBgYHtyfQ0KY3NldyRuYXRpb25mPC0gcmVjb2RlKGNzZXckbmF0aW9uZiwgIlJlZnVzZWQiID0gIk5BIiwgIkRvbid0IGtub3ciID0gIk5BIikNCg0KdGFibGUoY3NldyRuYXRpb25mKQ0KDQpgYGANCg0KV2UgaGF2ZSBzdWNjZXNzZnVsbHkgcmVjb2RlZCB0aG9zZSB2YWx1ZXMgYXMgbWlzc2luZywgbm93IHdlIG5lZWQgdG8gdGVsbCBSIFN0dWRpbyB0byB0cmVhdCB0aG9zZSB2YWx1ZXMgYXMgbWlzc2luZyB0b28NCg0KYGBge3J9DQpjc2V3JG5hdGlvbmY8LSBuYV9pZihjc2V3JG5hdGlvbmYsICJOQSIpDQoNCmNzZXckbmF0aW9uZjwtIGRyb3BsZXZlbHMoY3NldyRuYXRpb25mKSAjd2l0aCB0aGlzIGNvZGUgd2UgZ290IHJpZCBvZiB0aGUgY2F0ZWdvcnkgZm9yIE5BDQp0YWJsZShjc2V3JG5hdGlvbmYpDQoNCmBgYA0KDQoqKlRhc2sgNDoqKiBDaGVjayBmb3IgbWlzc2luZyB2YWx1ZXMgaW4gdGhlIGZvbGxvd2luZyB2YXJpYWJsZXMgYW5kIGRlYWwgd2l0aCB0aGVtIGFjY29yZGluZ2x5Og0KDQotIGVkdWNhdDM6IHJlc3BvbmRlbnQgZWR1Y2F0aW9uICg1IGNhdGVnb3JpZXMpDQotIGV0aGdycDVhOiBldGhuaWMgZ3JvdXANCi0gYmNzdmljdGltOiBFeHBlcmllbmNlIG9mIGFueSBjcmltZSBpbiB0aGUgcHJldmlvdXMgMTIgbW9udGhzDQoNCg0KDQojIyMgVW5pdmFyaWF0ZSBEZXNjcmlwdGl2ZSBzdGF0aXN0aWMgZm9yIGNvbnRpbnVvdXMgKG51bWVyaWMpIGRhdGENCg0KV2UgY2FuIGdldCBzdW1tYXJpZXMgb2YgdGhlIG1haW4gc3RhdGlzdGljcyB1c2luZyB0aGUgYmFzZSBmdW5jdGlvbiBgc3VtbWFyeSgpYC4gVGhpcyBmdW5jdGlvbiBnaXZlcyB1cyB0aGUgbWluaW11bSBhbmQgbWF4aW11bSB2YWx1ZXMsIHRoZSBtZWFuLCBtZWRpYW4gYW5kIHRoZSBxdWFydGlsZXMuICAgDQoNCkl0IGlzIHJlYWxseSB1c2VmdWwgdG8gY2hlY2sgZm9yIGV4dHJlbWUgdmFsdWVzLiBMZXQncyBoYXZlIGEgZ28NCg0KYGBge3J9DQojVGhpcyB1c2VzIGJhc2ljIGZ1bmN0aW9ucyBmcm9tIFINCnN1bW1hcnkoY3NldyRhZ2UpDQpgYGANCg0KYHN1bW1hcnkoKWAgZG9lcyBub3QgZ2l2ZSBhbnkgbWVhc3VyZSBvZiB0aGUgc3ByZWFkIG9mIHRoZSBkYXRhLCB3ZSBjYW4gdXNlIG90aGVyIGZ1bmN0aW9ucyBhdmFpbGFibGUgaW4gYmFzZSBSIGZvciB0aGF0IGBzZCgpYCBmb3Igc3RhbmRhcmQgZGV2aWF0aW9uLg0KDQpgYGB7cn0NCiMgU3RhbmRhcmQgZGV2aWF0aW9uDQpzZChjc2V3JGFnZSkNCg0KYGBgDQoNCnNvIGZhciB3ZSBoYXZlIHVzZWQgdHdvIGRpZmZlcmVudCBmdW5jdGlvbnMgb2YgYmFzZSBSIGZvciBleHBsb3JhdG9yeSBkYXRhIGFuYWx5c2lzLiBXZSBjYW4gb2J0YWluIHRoZSBzYW1lIHN0YXRpc3RpY3MgYW5kIG1vcmUgdXNpbmcgYSBjb21iaW5hdGlvbiBvZiBkaWZmZXJlbnQgZnVuY3Rpb24gZnJvbSB0aGUgcGFja2FnZSBgdGlkeXZlcnNlYCB0YWtpbmcgYWR2YW50YWdlIG9mIHRoZSBgJT4lYCAocGlwZSkgb3BlcmF0b3IgZnJvbSB0aGUgcGFja2FnZSAqKm1hZ3JpdHRyKiogd2hpY2ggaXMgZnVsbHkgaW1wbGVtZW50ZWQgaW4gdGlkeXZlcnNlLCBzbyB0aGVyZSBpcyBubyBuZWVkIHRvIGluc3RhbGwgYW55dGhpbmcgZWxzZS4NCg0KDQpJJ20gYSBmaXJtZXIgYmVsaWV2ZXIgKGFsdGhvdWdoIEkgbWF5IGJlIHdyb25nKSB0aGF0IHRoZSBiZXN0IHdheSB0byBsZWFybiBpcyBwdXR0aW5nIGludG8gcHJhY3RpY2UsIHNvIHRoaXMgaXMgYSBwZXJmZWN0IG9wcG9ydHVuaXR5IHRvIHB1dCBgJT4lYCBpbnRvIHByYWN0aWNlLiAoWW91IGNhbiBjaGVjayB5b3VyIG5vdGVzIG9mIHR1dG9yaWFsIDEgZm9yIG1vcmUgZGV0YWlscyBvbiBob3cgdG8gdXNlIHRoZW0pLg0KDQpMZXQncyBzdGFydCB3aXRoIHRoZSBgc3VtbWFyaXNlYCBmdW5jdGlvbiBmcm9tIHRoZSBwYWNrYWdlIGBkcGx5cmAgKGFsc28gcGFydCBvZiB0aWR5dmVyc2UpIFRoaXMgZnVuY3Rpb24gYWxsb3dzIHVzIHRvIGNyZWF0ZSBzdW1tYXJ5IHN0YXRpc3RpYyBvZiBvdXIgdmFyaWFibGVzIGluIG9uZSBzaW5nbGUgY29kZQ0KDQoNCmBgYHtyfQ0KDQojdXNpbmcgZnVuY3Rpb24gZnJvbSB0aGUgcGFja2FnZSBkcGx5ciAodGlkeXZlcnNlKQ0KY3NldyAlPiUgDQogIHN1bW1hcmlzZShtZWFuX2FnZT0gbWVhbihhZ2UpKSAjIHdlIGNyZWF0ZSB0aGUgdmFyaWFibGUgbWVhbl9hZ2UNCg0KDQpgYGANCg0KVGhhdCB3YXMgZ29vZCBidXQgbm90IHZlcnkgaW1wcmVzc2l2ZSwgd2FzIGl0PyBXZSBjYW4gYWRkIG1vcmUgZnVuY3Rpb25zIHRvIHRoYXQgY29kZSBhbmQgYXNrIGZvciBtb3JlOiAgDQoNCmBgYHtyfQ0KDQpjc2V3ICU+JSANCiAgc3VtbWFyaXNlKG1lYW5fYWdlPSBtZWFuKGFnZSksIA0KICAgICAgICAgICAgc2RfYWdlPSBzZChhZ2UpLA0KICAgICAgICAgICAgbWVkaWFuX2FnZSA9IG1lZGlhbihhZ2UpLA0KICAgICAgICAgICAgbWluX2FnZSA9IG1pbihhZ2UpLA0KICAgICAgICAgICAgbWF4X2FnZSA9IG1heChhZ2UpKSANCg0KYGBgDQoNCk9uZSBvZiB0aGUgYWR2YW50YWdlcyBvZiB1c2luZyBgJT4lYCBpcyB0aGF0IHdlIGNhbiBhZGQgbW9yZSBmdW5jdGlvbnMgdG8gb3VyIGNvZGUgYXMgYSBzZXQgb2YgaW5zdHJ1Y3Rpb25zLiBJbiB0aGUgZXhhbXBsZSBiZWxvdywgSSBhZGRlZCB0aGUgZnVuY3Rpb24gYGZpbHRlcigpYCBvZiB0aGUgcGFja2FnZSBgZHBseXJgIHRvIGV4Y2x1ZGUgYWxsIG1pc3NpbmcgY2FzZXMgZnJvbSB0aGUgYW5hbHlzaXMuICANCg0KDQpUaGUgZnVuY3Rpb24gYGlzLm5hKClgIChpcyBtaXNzaW5nPykgd2lsbCBzZWxlY3QgYWxsIG1pc3NpbmcgY2FzZXMsIGJ1dCB3aGVuIHVzZWQgYWxvbmcgdGhlIGAhYCBpdCBtZWFucyB0b3RhbGx5IHRoZSBvcHBvc2l0ZSwgc28gaW4gdGhpcyBjb2RlIHRoaXMgc3RhbmQgZm9yICoqZmlsdGVyIGFsbCB0aGUgY2FzZXMgb2YgdmFyaWFibGUgYWdlIHRoYXQgKmFyZSBub3QqIG1pc3NpbmcqKg0KDQoNCmBgYHtyfQ0KY3NldyAlPiUNCiAgZmlsdGVyKCFpcy5uYShhZ2UpKSAlPiUNCiAgc3VtbWFyaXNlKG1lYW5fYWdlPSBtZWFuKGFnZSksIA0KICAgICAgICAgICAgc2RfYWdlPSBzZChhZ2UpLA0KICAgICAgICAgICAgbWVkaWFuX2FnZSA9IG1lZGlhbihhZ2UpLA0KICAgICAgICAgICAgbWluX2FnZSA9IG1pbihhZ2UpLA0KICAgICAgICAgICAgbWF4X2FnZSA9IG1heChhZ2UpKSANCg0KYGBgDQoNCldlIGNhbiBldmVuIGFkZCBtb3JlIHZhcmlhYmxlcyEgYnV0IGZvciB0aGF0IHdlIG1pZ2h0IG5lZWQgYW5vdGhlciBmdW5jdGlvbiBhbmQgdGhlIGNoYW5jZSB0byB1c2UgbW9yZSBwaXBlcyAlPiUuDQoNCi0gW3NlbGVjdF0oaHR0cHM6Ly9kcGx5ci50aWR5dmVyc2Uub3JnL3JlZmVyZW5jZS9zZWxlY3QuaHRtbCk6IFRoaXMgZnVuY3Rpb24gYWxsb3dzIHRvIHNlbGVjdCBzcGVjaWZpYyB2YXJpYWJsZSBmcm9tIHRoZSBkYXRhc2V0cy4gIA0KLSBbc3VtbWFyaXNlX2FsbF0oaHR0cHM6Ly9kcGx5ci50aWR5dmVyc2Uub3JnL3JlZmVyZW5jZS9zdW1tYXJpc2VfYWxsLmh0bWwpOiBhbGxvd3MgdG8gYXBwbHkgdGhlIHNhbWUgdHJhbnNmb3JtYXRpb24gdG8gbXVsdGlwbGUgdmFyaWFibGVzDQotIFtsaXN0XShodHRwczovL3d3dy5yZG9jdW1lbnRhdGlvbi5vcmcvcGFja2FnZXMvYmFzZS92ZXJzaW9ucy8zLjYuMi90b3BpY3MvbGlzdCk6IHVzZWQgdG8gbWFrZSBhIGxpc3Qgb2YgZnVuY3Rpb25zIHRvIGFwcGx5LCBpbiB0aGlzIGV4YW1wbGUsIG1lYW4gYW5kIHNkDQoNCg0KYGBge3J9DQpjc2V3ICU+JSANCiAgc2VsZWN0KGFnZSwgYW50aXNvY3gpICU+JQ0KICBzdW1tYXJpc2VfYWxsKGxpc3QobWVhbj0gbWVhbiwgc2Q9IHNkLCBtZWRpYW4gPSBtZWRpYW4pLCBuYS5ybSA9IFRSVUUpDQoNCmBgYA0KV2hhdCBjYW4gd2Ugc2F5IGFib3V0IGFnZT8gIA0KDQpUaGUgZGlzdHJpYnV0aW9uIG9mIHRoZSB2YXJpYWJsZSBhZ2Ugc2VlbXMgcmVhc29uYWJsZSwgdGhlIG1lYW4gYW5kIHRoZSBtZWRpYW4gYXJlIHZlcnkgc2ltaWxhci4gDQoNClRoZSBzdGFuZGFyZCBkZXZpYXRpb24gc2hvd3MgaG93IHNwcmVhZCB0aGUgZGF0YSBhcmUuIEEgc3RhbmRhcmQgZGV2aWF0aW9uIG9mIDU3LjY4IGlzIHF1aXRlIGhpZ2gsIHdoaWNoIG1pZ2h0IGluZGljYXRlIGEgbG90IG9mIHZhcmlhdGlvbiBpbiB0aGUgZGlzdHJpYnV0aW9uIG9mIGFnZS4gVGhpcyBpcyBjbGVhcmx5IGhpbnRpbmcgdGhhdCB0aGVyZSBpcyBzb21ldGhpbmcgb2RkIGFib3V0IHRoZSB2YXJpYWJsZS4NCg0KV2UgYWxzbyBzYXcgdGhhdCB0aGUgbWF4aW11bSB2YWx1ZSBmb3IgYWdlIGlzICoqOTk5KiosIHdoaWNoIGlzIGNsZWFybHkgYSBudW1iZXIgb3V0IG9mIHJhbmdlOyBOb2JvZHkgY2FuIGxpdmUgZm9yIDk5OSB5ZWFycyEgVGhpcyBpcyBwcm9iYWJseSB0aGUgcmVhc29uIHdoeSB0aGUgc3RhbmRhcmQgZGV2aWF0aW9uIGlzIHNvIGhpZ2gsICoqd2UgY2xlYXJseSBuZWVkIGZ1cnRoZXIgZXhwbG9yYXRpb24gb2YgdGhpcyB1bnVzdWFsIHZhbHVlKioNCg0KSW4gY2VydGFpbiBjYXNlcyB0aGUgbWF4aW11bSB2YWx1ZXMgY2FuIGJlIGxlc3Mgb2J2aW91cywgc28gaXQgd291bGQgYmUgZGlmZmljdWx0IHRvIGRldGVybWluZSB3aGV0aGVyIHRoZXJlIGFyZSBvdXRsaWVycyBvciBkYXRhIGVycm9ycywgdGhhdCBpcyB3aHkgd2UgbmVlZCB0byBjb21wbGVtZW50IHRoZXNlIGluaXRpYWwgY2hlY2tzIHdpdGggdmlzdWFsIGV4cGxvcmF0aW9uLg0KDQoqKkRpYWdub3N0aWMsIGNyaXRpY2FsIHBvaW50cyByZWdhcmRpbmcgYWdlKioNCg0KLSBoaWdoIHN0YW5kYXJkIGRldmlhdGlvbg0KLSBJbXBsYXVzaWJsZSB2YWx1ZXMgKGVycm9yPywgbWlzc2luZyB2YWx1ZXM/LCBvdXRsaWVycz8pDQoNCioqQWN0aW9ucyoqDQoNCi0gYm90aCBwcm9ibGVtcyBtaWdodCBiZSByZWxhdGVkDQotIGNoZWNrIDk5OSB2YWx1ZXMgYW5kIGRlYWwgd2l0aCB0aGVtIGFjY29yZGluZ2x5DQotIGNoZWNrIGlmIFNEIGNoYW5nZXMgYWZ0ZXIgOTk5IHZhbHVlcyBhcmUgdGFrZW4gaW50byBhY2NvdW50DQoNCmBgYHtyfQ0KY2xhc3MoY3NldyRhZ2UpDQphdHRyaWJ1dGVzKGNzZXckYWdlKQ0KDQpgYGANCg0KdXNpbmcgdGhlIGZ1bmN0aW9uIGBhdHRyaWJ1dGVzKClgIHdlIG5vdyBrbm93ICANCg0KLSBhZ2UgaXMgZm9ybWF0dGVkIGFzICIlOC4wZyIgd2hpY2ggaXMgYSB3YXkgb2Ygc3RvcmluZyBudW1lcmljIGRhdGEgaW4gU3RhdGEuIA0KLSBhZ2UgaXMgYSAiaGF2ZW5fbGFiZWxsZWQiIHZhcmlhYmxlcywgd2hpY2ggbWVhbnMgdGhlcmUgYXJlIGNlcnRhaW4gdmFsdWVzIHdpdGggbGFiZWxzDQotIFRoZSB2YWx1ZXMgYW5kIGxhYmVscyA5OTggYW5kIDk5OSBhcmUgZm9yICJyZWZ1c2VkIiBhbmQgImRvbid0IGtub3ciIHJlc3BlY3RpdmVseS4NCg0KOTk4IGFuZCA5OTkgY2FuIGJlIGNsYXNzaWZpZWQgYXMgbWlzc2luZyBjYXNlcyAodW5sZXNzIHlvdSBhcmUgaW50ZXJlc3RlZCBpbiBrbm93aW5nIHRoZSBwYXR0ZXJucyBvZiBub24tcmVzcG9uc2UpLiBTbyB3ZSBjYW4gZWFzaWx5IHNvbHZlIHRoYXQgcHJvYmxlbS4NCg0KDQpgYGB7cn0NCmNzZXckYWdlW2NzZXckYWdlPT05OTggfCBjc2V3JGFnZT09OTk5IF08LU5BIA0KDQpgYGANCg0KDQoqKlRhc2sgNToqKiBHZXQgc3VtbWFyeSBzdGF0aXN0aWNzIGZvciB0aGUgdmFyaWFibGVzICoqY29uZngqKiwgKipmYWlyKiogYW5kICoqZWZmZWN0eCoqLiBNYWtlIG5vdGUgb2YgYW55IHBhdHRlcm5zIG9yIHVudXN1YWwgdmFsdWVzLiBBIGRlc2NyaXB0aW9uIG9mIHRoZSB2YXJpYWJsZXMgY2FuIGJlIGZvdW5kIGluIHRoaXMgW3VzZXIgZ3VpZGVdKGh0dHA6Ly9kb2MudWtkYXRhc2VydmljZS5hYy51ay9kb2MvNzkxMS9tcmRvYy9wZGYvNzkxMV9jc2V3XzIwMTMtMTRfdGVhY2hpbmdfZGF0YXNldF91c2VyX2d1aWRlLnBkZikNCg0KDQoqKlRhc2sgNS4xKiogV3JpdGUgZG93biBhIHNob3J0IGRlc2NyaXB0aW9uIG9mIHRoZSBtYWluIHN0YXRpc3RpY3MgeW91J3ZlIG9idGFpbmVkDQoNCg0KDQoqKlRhc2sgNS4yKiogSXMgdGhlcmUgYW55IHVudXN1YWwgdmFsdWUgaW4gdGhlIHZhcmlhYmxlcyB5b3UgaGF2ZSBhbmFseXNlZD8NCg0KDQoNCg0KIyMgNC4yLiBWaXN1YWwgZXhwbG9yYXRpb24NCg0KV2UgY2FuIHVzZSBhIGNvbWJpbmF0aW9uIG9mIGJhciBwbG90cywgaGlzdG9ncmFtcywgYm94cGxvdHMgYW5kIHNjYXR0ZXIgcGxvdHMgYXMgdGhlIGJhc2lzIGZvciBvdXIgZGF0YSBleHBsb3JhdGlvbg0KDQoqKmJhciBwbG90cyBvZiBjYXRlZ29yaWNhbCBkYXRhKioNCmBgYHtyfQ0KIA0KZ2dwbG90KGRhdGEgPSBjc2V3KSArDQogIGdlb21fYmFyKG1hcHBpbmcgPSBhZXMoeCA9IHNleGYpKQ0KYGBgDQoNCioqaGlzdG9ncmFtIGZvciBjb250aW51b3VzIGRhdGEqKg0KDQpgYGB7cn0NCmdncGxvdChkYXRhID0gY3NldykgKw0KICBnZW9tX2hpc3RvZ3JhbShtYXBwaW5nID0gYWVzKHg9YWdlKSwgYmlud2lkdGggPSAwLjUsIG5hLnJtID0gVFJVRSkNCmBgYA0KDQpCb3RoIGJhciBjaGFydHMgYW5kIGhpc3RvZ3JhbXMgY2FuIGJlIHVzZWQgdG8gZGV0ZWN0IG91dGxpZXJzIGFuZCB1bnVzdWFsIHBhdHRlcm5zIG9mIHRoZSBkYXRhLiANCg0KKipUYXNrIDY6KiogVmlzdWFsbHkgZXhwbG9yZSB0aGUgdmFyaWFibGVzIHRoYXQgd2UgaGF2ZSB1c2VkIGluIHRoZSBwcmV2aW91cyB0YXNrLiBNYWtlIGEgbm90ZSBvZiBhbnkgdW51c3VhbCBwYXR0ZXJucyB0aGF0IHlvdSBjYW4gZmluZC4NCg0KDQoNCiMjIDQuMy4gQXNzb2NpYXRpb24gYmV0d2VlbiB2YXJpYWJsZXMNCg0KTW9yZSBpbnNpZ2h0IGNhbiBiZSBnYWluZWQgd2hlbiBsb29raW5nIGF0IHJlbGF0aW9uc2hpcHMgYmV0d2VlbiB2YXJpYWJsZXMuIFRoaXMgY2FuIGJlIGRvbmUgaW4gdHdvIG1haW4gd2F5czogdXNpbmcgbnVtZXJpY2FsIHJlcHJlc2VudGF0aW9uIG9mIHRoaXMgYXNzb2NpYXRpb24gYW5kIHZpc3VhbCByZXByZXNlbnRhdGlvbnMuDQoNCiMjIyBBc3NvY2lhdGlvbnMgdXNpbmcgImNyb3NzdGFicyIgb3IgImNvbnRpbmdlbmN5IiB0YWJsZXMNCg0KRm9yIGNhdGVnb3JpY2FsIGRhdGEgd2UgY2FuIHVzZSBjb250aW5nZW5jeSB0YWJsZXMgKGFsc28gY2FsbGVkIGNyb3NzdGFicykNCg0KSGVyZSB3ZSB3aWxsIGJlIHVzaW5nIGEgbmV3IHBhY2thZ2UgY2FsbGVkIGBqYW5pdG9yYC4NCg0KDQpgYGB7ciwgbWVzc2FnZT1GQUxTRX0NCiNpbnN0YWxsLnBhY2thZ2VzKCJqYW5pdG9yIikgDQpsaWJyYXJ5KGphbml0b3IpDQoNCmBgYA0KDQpgYGB7cn0NCmNzZXcgJT4lDQogIHRhYnlsKHNleGYsIG5hdGlvbmYsIHNob3dfbmEgPSBGQUxTRSkgJT4lICNleGNsdWRlcyBOQSB2YWx1ZXMgZnJvbSB0aGUgdGFibGUNCiAgYWRvcm5fcGVyY2VudGFnZXMoInJvdyIpICU+JSAjIHRha2VzIHJvdyBwZXJjZW50YWdlDQogIGFkb3JuX3BjdF9mb3JtYXR0aW5nKGRpZ2l0cyA9IDIpICU+JSAjIGxpbWl0ICUgdG8gMiBkaWdpdHMNCiAgYWRvcm5fbnMoKSAjYWRkIHRoZSBjZWxsIGNvdW50DQoNCg0KYGBgDQoNCg0KDQoqKlRhc2sgNzoqKiBFeHBsb3JlIHRoZSByZWxhdGlvbnNoaXAgYmV0d2VlbiB2aWN0aW0gb2YgY3JpbWUgYW5kIHNleCwgZXRobmljIGdyb3VwLCBuYXRpb25hbGl0eSBhbmQgZWR1Y2F0aW9uYWwgbGV2ZWwuIE1ha2Ugbm90ZXMgb2YgeW91ciBmaW5kaW5ncw0KDQoNCg0KDQojIyMgTG9va2luZyBhdCBhc3NvY2lhdGlvbiB0aHJvdWdoIHZpc3VhbGlzYXRpb25zDQoNCk5vdyB3ZSBuZWVkIHRvIGZvY3VzIG9uIG91ciB2YXJpYWJsZSBvZiBpbnRlcmVzdCAob3V0Y29tZSB1c3VhbGx5IHJlcHJlc2VudGVkIGFzIHRoZSAneScgdmFyaWFibGUpIGFuZCBpdHMgYXNzb2NpYXRpb24gd2l0aCBvdGhlciBleHBsYW5hdG9yeSB2YXJpYWJsZXMgKHggdmFyaWFibGVzKS4NCg0KSGVyZSB3ZSB3aWxsIGJlIGxvb2tpbmcgYXQgdGhlIGFzc29jaWF0aW9ucyBiZXR3ZWVuIGNvbmZpZGVuY2UgaW4gdGhlIGVmZmVjdGl2ZW5lc3Mgb2YgQ3JpbWluYWwgSnVzdGljZSBTeXN0ZW0gKGVmZmVjdHgpIGFuZCBvdGhlciBpbmRpdmlkdWFsIGNoYXJhY3RlcmlzdGljcyBvZiB0aGUgcmVzcG9uZGVudHMuDQoNCioqVHdvIGNvbnRpbnVvdXMgdmFyaWFibGVzKioNCg0KDQotU2NhdHRlciBwbG90czogRm9yIGxvb2tpbmcgYXQgdGhlIHJlbGF0aW9uc2hpcCBiZXR3ZWVuIHR3byBjb250aW51b3VzIHZhcmlhYmxlcy4gVGhpcyBpcyB1c2VmdWwgdG8gYXNzZXNzIGNvLXZhcmlhdGlvbi4NCg0KYGBge3J9DQoNCmdncGxvdChkYXRhID0gY3NldywgbWFwcGluZyA9IGFlcyh4ID0gYWdlLCB5ID0gZWZmZWN0eCkpICsgDQogIGdlb21fcG9pbnQobmEucm0gPSBUUlVFKQ0KDQoNCmBgYA0KDQpXZSByZWNlaXZlZCBhIHdhcm5pbmcgcmVnYXJkaW5nIGEgbGFiZWxsZWQgdmFyaWFibGUsIGZ1cnRoZXIgZXhwbG9yYXRpb24gcmV2ZWFscyB0aGF0IHRoZSB2YXJpYWJsZSBhZ2UgaXMgbnVtZXJpYyBidXQgY29udGFpbnMgdHdvIGxhYmVscyAoImhhdmVuX2xhYmVsbGVkIikgZm9yICJyZWZ1c2VkIiBhbmQgImRvbid0IGtub3ciLg0KDQpUaGUgYGFzLm51bWVyaWMoKWAgZnVuY3Rpb24gd2lsbCBjcmVhdGUgYSBjb3B5IG9mIHRoZSB2YXJpYWJsZSBhZ2Ugb2YgY2xhc3MgIm51bWVyaWMiLiBUaGUgZnVuY3Rpb24gd2lsbCBnZXQgcmlkIG9mIHRoZSBsYWJlbHMuDQoNCmBgYHtyfQ0KDQpjc2V3JGFnZTI8LWFzLm51bWVyaWMoY3NldyRhZ2UpDQoNCmBgYA0KDQpZb3UgY2FuIGNoZWNrIHRoYXQgd2Ugbm93IGdvdCByaWQgb2YgdGhlIHdhcm5pbmcuDQoNCioqQ2F0ZWdvcmljYWwgYW5kIGNvbnRpbnVvdXMgdmFyaWFibGVzKioNCg0KLSBib3hwbG90OiBpZGVhbCBmb3IgZGV0ZWN0aW5nIG91dGxpZXJzLiBIZXJlIHdlIG9idGFpbiBib3hwbG90cyBieSBncm91cHMNCg0KYGBge3J9DQpnZ3Bsb3QoZGF0YSA9IGNzZXcsIG1hcHBpbmcgPSBhZXMoeCA9IHNleGYsIHkgPSBlZmZlY3R4KSkgKw0KICBnZW9tX2JveHBsb3QobmEucm0gPSBUUlVFKQ0KYGBgDQoNCldlIGNhbiBhZGQgY29sb3VycyB0byB0aGUgb3VsaWVycw0KDQpgYGB7cn0NCmdncGxvdChkYXRhID0gY3NldywgbWFwcGluZyA9IGFlcyh4ID0gc2V4ZiwgeSA9IGVmZmVjdHgpKSArDQogIGdlb21fYm94cGxvdChvdXRsaWVyLmNvbG91ciA9ICJyZWQiLCBuYS5ybSA9IFRSVUUpDQpgYGANCg0KDQoqKlRhc2sgODoqKiBFeHBsb3JlIHRoZSBhc3NvY2lhdGlvbnMgYmV0d2VlbiBlZmZlY3RpdmVuZXNzIGluIHRoZSBDcmltaW5hbCBKdXN0aWNlIFN5c3RlbSBhbmQgbmF0aW9uYWxpdHksIGV0aG5pYyBncm91cCwgdmljdGltIG9mIGNyaW1lDQoNCg0KDQoNCioqVGFzayA5OioqIEFmdGVyIGFsbCB0aGUgYml2YXJpYXRlIGV4cGxvcmF0aW9uIHRoYXQgeW91IGhhdmUgZG9uZS4gSGF2ZSB5b3UgZm91bmQgYW55IGRpZmZlcmVuY2UgaW4gdGhlIHBlcmNlcHRpb24gb2YgdGhlIGVmZmVjdGl2ZW5lc3MgaW4gdGhlIENyaW1pbmFsIEp1c3RpY2UgU3lzdGVtIGFjY29yZGluZyB0bzoNCg0KLSBzZXhfX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX18NCl9fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fDQotIGV0aG5pYyBncm91cDogX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fXw0KX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX18NCi0gVmljdGltczogX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fDQpfX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fXw0KDQoNCioqVGFzayAxMDoqKiBDYW4geW91IHRoaW5rIGluIGFueSBoeXBvdGhlc2lzIHRoYXQgY2FuIGhlbHAgdXMgdG8gdW5kZXJzdGFuZCB0aGUgZGlmZmVyZW5jZXMgaW4gdGhlIHBlcmNlcHRpb24gb2YgaG93IGVmZmVjdGl2ZSB0aGUgQ3JpbWluYWwgSnVzdGljZSBTeXN0ZW0gaXM/IA0KDQoNCiMgNS4gIFNhdmluZyBkYXRhDQoNCldlIGNhbiBzYXZlIHRoZSBkYXRhIHdlIGhhdmUgYmVlbiB1c2luZywgd2UgY2FuIHNlbGVjdCBkaWZmZXJlbnQgZXhwb3J0IG1ldGhvZHMsIGRlcGVuZGluZyBvbiB0aGUgZm9ybWF0IGluIHdoaWNoIHdlIHdhbnQgb3VyIGRhdGEgdG8gYmUgc3RvcmVkLiBIZXJlIHdlIHdpbGwgc2F2ZSB0aGUgY2hhbmdlcyB0aGF0IHdlIGhhdmUgbWFkZSB0byB0aGUgImNzZXciIGRhdGFzZXQgYXMgUiBkYXRhLiBUaGlzIG1lYW5zIHRoYXQgd2UgZG9uJ3QgbmVlZCB0byBpbXBvcnQgaXQgYWdhaW4gKHdlIHN0aWxsIG5lZWQgdG8gbG9hZCBpdCkgdG8gdXNlIGluIGFub3RoZXIgUiBzZXNzaW9uLg0KDQpgYGB7cn0NCnNhdmUoY3NldywgZmlsZT0gImNzZXcuUkRhdGEiKQ0KYGBgDQoNCg0KDQoNCg==