Introduction

There have been conflicts happening around the world within groups which can range from militant activity, conflicts between groups, conflicts of civilians with government bodies etc. This project aims at exploring such conflicts happening in different countries of Africa for past 20 years and clusteing to find trends.

With this dataset, it is possible to perform Exploratory data analysis and clustering to see the type of conflicts affecting different region and assessing the political situation of a particular region.

The data set I have selected for my project is “ACLED African Conflicts data for a duration of 1997-2017”. The dataset is not tidy and needs to be cleaned to be used for analysis. There are many columns which have joined data and need to be separated to different columns. There are many cases of missing and NA values which needs to be addressed.

Packages Required

Below code checks if packages required for this project are installed on the system and if not then installs them.

packages <- c("dplyr","leaflet","htmltools","ggplot2","lubridate","qdap","tm","SnowballC","wordcloud","RColorBrewer")
if (length(setdiff(packages, rownames(installed.packages()))) > 0) {
  install.packages(setdiff(packages, rownames(installed.packages())))  
}

The packages required for this project are mentioned below:

library(dplyr)      
library(leaflet)    
library(htmltools)  
library(ggplot2)    
library(lubridate)  
library(qdap)       
library(tm)     
library(SnowballC) 
library(wordcloud)  
library(RColorBrewer)    

Description of these packages are as below:

Package Description
(dplyr) #Used for data manipulation of the data set
(leaflet) #Used to make Create Interactive Web Maps
(htmltools) #Tools for HTML
(ggplot2) #Used to create elegant data visualisations using the grammar of graphics
(lubridate) #Used for easily dealing with dates
(qdap) #Used for text analysis
(tm) #Text Mining Package
(SnowballC) #Used for text and Word analysis
(wordcloud) #Used to create a word cloud
(RColorBrewer) #Used for color paletting in R

Data Preparation

The source of this data is from Kaggle - ACLED African Conflicts, 1997-2017.

This data is originally collected under ACLED project which is an acronym for ‘Armed Conflict Location and Event Data’. This project is directed by Prof. Clionadh Raleigh (University of Sussex) and operated by Senior Research Manager Andrea Carboni (University of Sussex) for Africa and Hillary Tanoff for South and South-East Asia. The aim of this project is to collate data on Political Violence in developing countries with focus on Africa. This dataset was first introduced in 2010 by Raleigh and co-authors in 2010 paper in the Journal of Peace Research. The ACLED data is used by several researchers in their research on civil wars and political violence. This dataset has also been referenced by news media agencies like The New York Times, The Guardian, BBC etc. to study recent conflict trends.

After examining the data, it was observed that missing values are recorded as 'Blanks' and with NA in a few columns. To bring consistency, we will replace Blanks with NA during reading the data. The date format is in “DD/MM/YYYY” format.

Data is imported using the read.csv() function. It takes the String values as Factors so we use the argument stringsAsFactors = FALSE to consider it as strings. We convert blanks to NA for missing data.

df <- read.csv("https://www.dropbox.com/s/0eeick4mo0zv4ug/african_conflicts.csv?dl=1", stringsAsFactors = FALSE, na.strings = "")

This dataset contains total 28 columns before making any changes.

names(df)
 [1] "ACTOR1"           "ACTOR1_ID"        "ACTOR2"           "ACTOR2_ID"       
 [5] "ACTOR_DYAD_ID"    "ADMIN1"           "ADMIN2"           "ADMIN3"          
 [9] "ALLY_ACTOR_1"     "ALLY_ACTOR_2"     "COUNTRY"          "EVENT_DATE"      
[13] "EVENT_ID_CNTY"    "EVENT_ID_NO_CNTY" "EVENT_TYPE"       "FATALITIES"      
[17] "GEO_PRECISION"    "GWNO"             "INTER1"           "INTER2"          
[21] "INTERACTION"      "LATITUDE"         "LOCATION"         "LONGITUDE"       
[25] "NOTES"            "SOURCE"           "TIME_PRECISION"   "YEAR"            

Out of these columns, ACTOR1_ID, ACTOR2_ID and ACTOR_DYAD_ID, EVENT_ID_CNTY, EVENT_ID_NO_CNTY are surrogate columns. So we will remove these columns. Most of the values in ALLY_ACTOR_1 and ALLY_ACTOR_2 are missing, so we remove these columns. GEO_PRECISION, GWNO and TIME_PRECISION are not required for our analysis. After removing these columns, we are left with 18 columns.

df1 <- df[-c(2, 4, 5, 9, 10, 13, 14, 17, 18, 27)]

The table below gives details about these columns:

Variable Description
ACTOR1 Name of first actor
ACTOR2 Name of second actor
ADMIN1 The largest sub-national administrative region in which the event took place
ADMIN2 The second-largest sub-national administrative region in which the event took place
ADMIN3 The third-largest sub-national administrative region in which the event took place
COUNTRY Country of conflict
EVENT_DATE Date of conflict, DD/MM/YYYY
FATALITIES Integer value of fatalities that occurred, as reported by source
INTER1 A numeric code indicating the type of ACTOR1
INTER2 A numeric code indicating the type of ACTOR2
INTERACTION A numeric code indicating the interaction between types of ACTOR1 and ACTOR2
LATITUDE The latitude of the location
LOCATION The location where event occurred
LONGITUDE The longitude of the location
NOTES Additional notes
SOURCE Source of conflict information
YEAR Year event occurred

Looking at columns ACTOR2, ADMIN2, ADMIN3, LOCATION, NOTES, SOURCE we see that they have some missing data.

apply(df1, 2, function(x) any(is.na(x)))
     ACTOR1      ACTOR2      ADMIN1      ADMIN2      ADMIN3     COUNTRY  EVENT_DATE 
      FALSE        TRUE       FALSE        TRUE        TRUE       FALSE       FALSE 
 EVENT_TYPE  FATALITIES      INTER1      INTER2 INTERACTION    LATITUDE    LOCATION 
      FALSE       FALSE       FALSE       FALSE       FALSE       FALSE        TRUE 
  LONGITUDE       NOTES      SOURCE        YEAR 
      FALSE        TRUE        TRUE       FALSE 

For Column ACTOR2, NA tells us that there was no second actor. So we can replace it with string “NONE”

df1$ACTOR2[is.na(df1$ACTOR2)] <- "NONE"
head(df1$ACTOR2)
[1] "Civilians (Algeria)"              "Police Forces of Algeria (1999-)"
[3] "NONE"                             "Police Forces of Algeria (1999-)"
[5] "Police Forces of Algeria (1999-)" "Police Forces of Algeria (1999-)"

Now for columns, INTER1, INTER2 and INTERACTION numerical subsitutes for categories are provided. We will replace these with the actual values from the codebook.

Preview of Column INTER1

df1$INTER1 <- as.character(df1$INTER1)
lut1 <- c("1" = "Government or mutinous force", "2" = "Rebel force",
          "3" = "Political militia", "4" = "Ethnic militia", 
          "5" = "Rioters", "6" = "Protesters", "7" = "Civilians", 
          "8" = "Outside/external force")
df1$INTER1 <- lut1[df1$INTER1]
head(df1$INTER1)
[1] "Government or mutinous force" "Rioters"                     
[3] "Protesters"                   "Rioters"                     
[5] "Rioters"                      "Rioters"                     

Preview of Column INTER2

df1$INTER2 <- as.character(df1$INTER2)
lut2 <- c("0" = "NONE", "1" = "Government or mutinous force", 
          "2" = "Rebel force", "3" = "Political militia", 
          "4" = "Ethnic militia", "5" = "Rioters", "6" = "Protesters",
          "7" = "Civilians", "8" = "Outside/external force")
df1$INTER2 <- lut2[df1$INTER2]
head(df1$INTER2)
[1] "Civilians"                    "Government or mutinous force"
[3] "NONE"                         "Government or mutinous force"
[5] "Government or mutinous force" "Government or mutinous force"

Preview of Column INTERACTION

df1$INTERACTION<-as.character(df1$INTERACTION)
lut3<-c("10" = "SOLE MILITARY ACTION", "11" = "MILITARY VERSUS MILITARY",
        "12" = "MILITARY VERSUS REBELS", "13" = "MILITARY VERSUS POLITICAL MILITIA",
        "14" = "MILITARY VERSUS COMMUNAL MILITIA", "15" = "MILITARY VERSUS RIOTERS",
        "16" = "MILITARY VERSUS PROTESTERS", "17" = "MILITARY VERSUS CIVILIANS",
        "18" = "MILITARY VERSUS OTHER", "20" = "SOLE REBEL ACTION ",
        "22" = "REBELS VERSUS REBELS", "23" = "REBELS VERSUS POLITICAL MILIITA",
        "24" = "REBELS VERSUS COMMUNAL MILITIA", "25" = "REBELS VERSUS RIOTERS",
        "26" = "REBELS VERSUS PROTESTERS", "27" = "REBELS VERSUS CIVILIANS",
        "28" = "REBELS VERSUS OTHERS", "30" = "SOLE POLITICAL MILITIA ACTION",
        "33" = "POLITICAL MILITIA VERSUS POLITICAL MILITIA", 
        "34" = "POLITICAL MILITIA VERSUS COMMUNAL MILITIA", 
        "35" = "POLITICAL MILITIA VERSUS RIOTERS", 
        "36" = "POLITICAL MILITIA VERSUS PROTESTERS", 
        "37" = "POLITICAL MILITIA VERSUS CIVILIANS",
        "38" = "POLITICAL MILITIA VERSUS OTHERS",
        "40" = "SOLE COMMUNAL MILITIA ACTION", 
        "44" = "COMMUNAL MILITIA VERSUS COMMUNAL MILITIA", 
        "45" = "COMMUNAL MILITIA VERSUS RIOTERS", 
        "46" = "COMMUNAL MILITIA VERSUS PROTESTERS", 
        "47" = "COMMUNAL MILITIA VERSUS CIVILIANS", 
        "48" = "COMMUNAL MILITIA VERSUS OTHER","50" = "SOLE RIOTER ACTION", 
        "55" = "RIOTERS VERSUS RIOTERS", "56" = "RIOTERS VERSUS PROTESTERS", 
        "57" = "RIOTERS VERSUS CIVILIANS", "58" = "RIOTERS VERSUS OTHERS", 
        "60" = "SOLE PROTESTER ACTION", "66" = "PROTESTERS VERSUS PROTESTERS", 
        "67" = "PROTESTERS VERSUS CIVILIANS", "68" = "PROTESTERS VERSUS OTHER", 
        "70" = "SOLE CIVILIANS", "77" = "CIVILIANS VERSUS CIVILIANS", 
        "78" = "OTHER ACTOR VERSUS CIVILIANS", "80" = "SOLE OTHER ACTION", 
        "88" = "OTHERS VERSUS OTHERS")
df1$INTERACTION <- lut3[df1$INTERACTION]
head(df1$INTERACTION)
[1] "MILITARY VERSUS CIVILIANS" "MILITARY VERSUS RIOTERS"   "SOLE PROTESTER ACTION"    
[4] "MILITARY VERSUS RIOTERS"   "MILITARY VERSUS RIOTERS"   "MILITARY VERSUS RIOTERS"  

Convert LONGITUDE and LATITUDE columns to Numeric

df1$LONGITUDE<-as.numeric(df1$LONGITUDE)
df1$LATITUDE<-as.numeric(df1$LATITUDE)

Examining the date column - EVENT_DATE

head(df1$EVENT_DATE)
[1] "18/04/2001" "19/04/2001" "20/04/2001" "21/04/2001" "21/04/2001" "21/04/2001"

The event date column is in DD/MM/YYYY format. We assign this to the data set using dmy() function.

df1$EVENT_DATE<-dmy(df1$EVENT_DATE)

for further analysis and aggregating data on monthly basis wew mutate the dataset to add a column for month.

df1<-df1%>%mutate(MONTH=month(df1$EVENT_DATE))

Preview of data after cleaning is given below:

head(df1)

Exploratory Data Analysis

We start our Exploratory data analysis by looking at the summary statistics of numberical atributes of our data set.

summary(df1)
Variable Min Max Mean
Event Date 1997-01-01 2017-07-29 -
Fatalities 0 25000 4.42
Year 1997 2017 -

From above, we can see that minimum fatalities in conflicts 0 and maximum value is 25000 with a mean of 4.42.

Exploring Dataset with number of conflicts

Below chart shows the number of conflicts which happened every year.

#creating data set for ggplot()
plot2<-df1%>%
  group_by(YEAR)%>%summarise(count=n())%>%
  arrange(desc(count))
#using ggplot for visualization
plot2%>%ggplot(aes(x = YEAR,y=count,fill=-count)) +
  geom_bar(stat = "identity") +
  scale_x_continuous(name = "Year") +
  scale_y_continuous(name = "Total Number of Conflicts",labels = scales::comma) +
  ggtitle("Frequncy Plot for Number of Conflicts in past 20 years",
  subtitle = "Data about number of conflicts which happened from 1997 to 2017")

It can be observed that maximum number of conflicts happened in 2016.

Drilling down, we try to understand which countries were most involved in the conflicts in this year.

#creating data set for ggplot()
plot1<-df1%>%
  filter(YEAR==2016)%>%
  group_by(COUNTRY)%>%summarise(count=n())%>%
  arrange(desc(count))%>%head(n=10)
#using ggplot for visualization
plot1%>%arrange(desc(count))%>%
  ggplot(aes(x = reorder(COUNTRY,-count), y=count,fill=-count)) +
  geom_bar(stat = "identity") + 
  scale_x_discrete(name = "Country") +
  scale_y_continuous(name = "Total Number of Conflicts",labels = scales::comma) +
  ggtitle("Frequency Plot for Number of Conflicts  in 2016",
  subtitle = "Top 10 countries with highest number of conflicts in 2016")+
  coord_flip()

It can be seen that Somalia had the highest number of conflicts. We try to find the regions in Somalia where conflicts occured.

From the map below, itcan be seen that the events were spread all across the country of Somalia.

#creating dataset with desired Latitude and Longitude
data = df1 %>%
  filter(YEAR==2016&COUNTRY=="Somalia") %>% 
  filter(!is.na(LATITUDE)) %>%
  filter(!is.na(LONGITUDE))
#defining median location
center_lon = median(data$LONGITUDE)
center_lat = median(data$LATITUDE)
#creating color palette
palette_color <- colorFactor(c("red","blue","green","yellow","orange"), data$COUNTRY)
#creating map
leaflet(data) %>% addTiles() %>%
  addCircles(lng = ~LONGITUDE, lat = ~LATITUDE,#radius = ~(), 
  color = ~palette_color(COUNTRY))%>%
#setting the location of the map  
  setView(lng=center_lon, lat=center_lat,zoom = 5) %>%
#adding a minimap  
  addMiniMap("bottomright", width = 150, height = 150,
  collapsedWidth = 19, collapsedHeight = 19, zoomLevelOffset = -5,
  zoomLevelFixed = FALSE, centerFixed = FALSE, zoomAnimation = FALSE,
  toggleDisplay = FALSE, autoToggleDisplay = FALSE, minimized = FALSE,
  aimingRectOptions = list(color = "#ff7800", weight = 1, clickable = FALSE),
  shadowRectOptions = list(color = "#000000", weight = 1, clickable = FALSE,
  opacity = 0, fillOpacity = 0), strings = list(hideText = "Hide MiniMap",
  showText = "Show MiniMap"), tiles = NULL, mapOptions = list())

Exploring Dataset considering fatalities Below barplot shows comparison of fatalities happened each year due to conflicts.

df1%>%
  group_by(YEAR)%>%summarise(total=sum(FATALITIES))%>%
  ggplot(aes(x=YEAR,y=total,fill=-total))+geom_bar(stat = "identity")+
  scale_x_continuous(name = "Year") +
  scale_y_continuous(name = "Total Number of Fatalities",labels = scales::comma) +
  ggtitle("Fatalities over the years due to conflicts",
  subtitle = "Data about fatalities happening every year due to conflicts")

It can be seen from the plot above that maximum fatalities occured during conflicts in 1999.

Digging further, we try to understand which months these conflicts led to fatalities.

  
  df1%>%
  filter(YEAR==1999)%>%
  group_by(MONTH)%>%
  summarise(total=sum(FATALITIES))%>%
  ggplot(aes(x=as.factor(MONTH),y=total,fill=-total))+geom_bar(stat = "identity")+
  scale_x_discrete(name = "Month of 1999") +
  scale_y_continuous(name = "Total Fatalities",labels = scales::comma) +
  ggtitle("Number of fatalities in 1999",
  subtitle = "Data about fatalities which happened in 1999 per month")

It is observed that, maximum fatalities happened in first four months.

With below plot we try to analyze which country had maximum fatalities in 1999.

df1%>%
  filter(YEAR==1999)%>%
  group_by(COUNTRY)%>%summarise(total=sum(FATALITIES))%>%
  arrange(desc(total))%>%head(n=10)%>%
  ggplot(aes(x = reorder(COUNTRY,-total), y=total,fill=-total)) +
  geom_bar(stat = "identity") + 
  scale_x_discrete(name = "Country") +
  scale_y_continuous(name = "Total fatalities",labels = scales::comma) +
  ggtitle("Fatalities analysis for the year 1999",
  subtitle = "Analysis of fatalities in each country in the year 1999")+coord_flip()

From the plot above it is evident that Eritrea and Angola had the maximum fatalities.


Below tables give an overall picture of top 5 years and top 10 countries with highest fatalities.

df1%>%
  group_by(YEAR)%>%
  summarise(sum(FATALITIES))%>%
  arrange(desc(`sum(FATALITIES)`))%>%
  head(n=5)

From the table above, we can see that year 1999 had the highest fatalities due to conflicts.

df1%>%
  group_by(COUNTRY)%>%
  summarise(sum(FATALITIES))%>%
  arrange(desc(`sum(FATALITIES)`))%>%
  head(n=10)

Here, we can see that Angola has the highest fatalities due to conflicts over all the years.




Text Analysis

A text analysis on the notes column can help us understand which words were used the most in the text.

notes<-df1%>%filter(YEAR==c(2017,2016,2015,2014,2013))%>%select(NOTES)
#head(notes)
notes_source<-VectorSource(notes)
notes_corpus<-VCorpus(notes_source)
clean_corpus <- function(corpus){
  corpus <- tm_map(corpus, stripWhitespace)
  corpus <- tm_map(corpus, removePunctuation)
  corpus <- tm_map(corpus, content_transformer(tolower))
  corpus <- tm_map(corpus, removeNumbers)
  corpus <- tm_map(corpus, removeWords, c(stopwords("en"),"Top200Words"))
  return(corpus)
}
notes_clean<-clean_corpus(notes_corpus)
notes_tdm<-TermDocumentMatrix(notes_clean)
notes_m<-as.matrix(notes_tdm)
notes_words<-rowSums(notes_m)
notes_words<-sort(notes_words,decreasing=TRUE)
notes_freqs<-data.frame(term = names(notes_words),num = notes_words)
wordcloud(notes_freqs$term, notes_freqs$num,max.words = 30,colors = c("chartreuse", "cornflowerblue", "darkorange"))

From the above word cloud, it can be seen that most popular words in the notes column are “killed”, “police”, “forces”.

Summary

With a huge dataset like this, a lot of information can be extracted to know facts about events like which areas were affected the most, what is the degree of damage that has occured due to conflicts and many other things.

All these insights and many others can be gathered using visual tools like plots, histograms, geospatial maps etc.

In this report, we were able to get insights like the year 1999 was the worst for all the conflicts as this year witnessed very high fatalities in the countries of Angola and Eritrea.

We also observed that the highest count of conflicts happened in 2016 but the number of fatalities were less. This may indicate that police forces were able to control the conflicts on an early stage.

This kind of analysis can let the end user know about the current and historical political situations of an African country. The user can further analyse to find which groups were involved the most and can provide insightful information for possible next location of a conflict in real-time.

This project can be further developed to include interactive visualization with the help of Shiny package which can let the user to analyze data of different years or regions interactively.

More analysis can be done to find which parties were involved maximum number of times in conflicts.

LS0tDQp0aXRsZTogIkFDTEVEIEFmcmljYW4gQ29uZmxpY3RzIg0KYXV0aG9yOiAiQW51cmFnIEphaW4iDQpkYXRlOiAiQXByaWwgMjIsIDIwMTgiDQpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sNCi0tLQ0KDQpgYGB7ciBzZXR1cCwgaW5jbHVkZT1GQUxTRX0NCmtuaXRyOjpvcHRzX2NodW5rJHNldChlY2hvID0gVFJVRSkNCmBgYA0KDQojIHsudGFic2V0IC50YWJzZXQtZmFkZSAudGFic2V0LXBpbGxzfQ0KIyMgSW50cm9kdWN0aW9uDQo8IS0tIA0KMS4xIFByb3ZpZGUgYW4gaW50cm9kdWN0aW9uIHRoYXQgZXhwbGFpbnMgdGhlIHByb2JsZW0gc3RhdGVtZW50IHlvdSBhcmUgYWRkcmVzc2luZy4gV2h5IHNob3VsZCBJIGJlIGludGVyZXN0ZWQgaW4gdGhpcz8gDQoxLjIgUHJvdmlkZSBhIHNob3J0IGV4cGxhbmF0aW9uIG9mIGhvdyB5b3UgcGxhbiB0byBhZGRyZXNzIHRoaXMgcHJvYmxlbSBzdGF0ZW1lbnQgKHRoZSBkYXRhIHVzZWQgYW5kIHRoZSBtZXRob2RvbG9neSBlbXBsb3llZCkgDQoxLjMgRGlzY3VzcyB5b3VyIGN1cnJlbnQgcHJvcG9zZWQgYXBwcm9hY2gvYW5hbHl0aWMgdGVjaG5pcXVlIHlvdSB0aGluayB3aWxsIGFkZHJlc3MgKGZ1bGx5IG9yIHBhcnRpYWxseSkgdGhpcyBwcm9ibGVtLiANCjEuNCBFeHBsYWluIGhvdyB5b3VyIGFuYWx5c2lzIHdpbGwgaGVscCB0aGUgY29uc3VtZXIgb2YgeW91ciBhbmFseXNpcy4NCi0tPg0KVGhlcmUgaGF2ZSBiZWVuIGNvbmZsaWN0cyBoYXBwZW5pbmcgYXJvdW5kIHRoZSB3b3JsZCB3aXRoaW4gZ3JvdXBzIHdoaWNoIGNhbiByYW5nZSBmcm9tIG1pbGl0YW50IGFjdGl2aXR5LCBjb25mbGljdHMgYmV0d2VlbiBncm91cHMsIGNvbmZsaWN0cyBvZiBjaXZpbGlhbnMgd2l0aCBnb3Zlcm5tZW50IGJvZGllcyBldGMuIFRoaXMgcHJvamVjdCBhaW1zIGF0IGV4cGxvcmluZyBzdWNoIGNvbmZsaWN0cyBoYXBwZW5pbmcgaW4gZGlmZmVyZW50IGNvdW50cmllcyBvZiBBZnJpY2EgZm9yIHBhc3QgMjAgeWVhcnMgYW5kIGNsdXN0ZWluZyB0byBmaW5kIHRyZW5kcy4NCg0KV2l0aCB0aGlzIGRhdGFzZXQsIGl0IGlzIHBvc3NpYmxlIHRvIHBlcmZvcm0gRXhwbG9yYXRvcnkgZGF0YSBhbmFseXNpcyBhbmQgY2x1c3RlcmluZyB0byBzZWUgdGhlIHR5cGUgb2YgY29uZmxpY3RzIGFmZmVjdGluZyBkaWZmZXJlbnQgcmVnaW9uIGFuZCBhc3Nlc3NpbmcgdGhlIHBvbGl0aWNhbCBzaXR1YXRpb24gb2YgYSBwYXJ0aWN1bGFyIHJlZ2lvbi4gDQoNClRoZSBkYXRhIHNldCBJIGhhdmUgc2VsZWN0ZWQgZm9yIG15IHByb2plY3QgaXMgIkFDTEVEIEFmcmljYW4gQ29uZmxpY3RzIGRhdGEgZm9yIGEgZHVyYXRpb24gb2YgMTk5Ny0yMDE3Ii4gVGhlIGRhdGFzZXQgaXMgbm90IHRpZHkgYW5kIG5lZWRzIHRvIGJlIGNsZWFuZWQgdG8gYmUgdXNlZCBmb3IgYW5hbHlzaXMuIFRoZXJlIGFyZSBtYW55IGNvbHVtbnMgd2hpY2ggaGF2ZSBqb2luZWQgZGF0YSBhbmQgbmVlZCB0byBiZSBzZXBhcmF0ZWQgdG8gZGlmZmVyZW50IGNvbHVtbnMuIFRoZXJlIGFyZSBtYW55IGNhc2VzIG9mIG1pc3NpbmcgYW5kIE5BIHZhbHVlcyB3aGljaCBuZWVkcyB0byBiZSBhZGRyZXNzZWQuDQoNCg0KIyMgUGFja2FnZXMgUmVxdWlyZWQNCjwhLS0NCjIuMSBBbGwgcGFja2FnZXMgdXNlZCBhcmUgbG9hZGVkIHVwZnJvbnQgc28gdGhlIHJlYWRlciBrbm93cyB3aGljaCBhcmUgcmVxdWlyZWQgdG8gcmVwbGljYXRlIHRoZSBhbmFseXNpcy4gDQoyLjIgTWVzc2FnZXMgYW5kIHdhcm5pbmdzIHJlc3VsdGluZyBmcm9tIGxvYWRpbmcgdGhlIHBhY2thZ2UgYXJlIHN1cHByZXNzZWQuIA0KMi4zIEV4cGxhbmF0aW9uIGlzIHByb3ZpZGVkIHJlZ2FyZGluZyB0aGUgcHVycG9zZSBvZiBlYWNoIHBhY2thZ2UgKHRoZXJlIGFyZSBvdmVyIDEwLDAwMCBwYWNrYWdlcywgZG9uJ3QgYXNzdW1lIHRoYXQgSSBrbm93IHdoeSB5b3UgbG9hZGVkIGVhY2ggcGFja2FnZSkuDQotLT4NCg0KQmVsb3cgY29kZSBjaGVja3MgaWYgcGFja2FnZXMgcmVxdWlyZWQgZm9yIHRoaXMgcHJvamVjdCBhcmUgaW5zdGFsbGVkIG9uIHRoZSBzeXN0ZW0gYW5kIGlmIG5vdCB0aGVuIGluc3RhbGxzIHRoZW0uDQoNCmBgYHtyfQ0KcGFja2FnZXMgPC0gYygiZHBseXIiLCJsZWFmbGV0IiwiaHRtbHRvb2xzIiwiZ2dwbG90MiIsImx1YnJpZGF0ZSIsInFkYXAiLCJ0bSIsIlNub3diYWxsQyIsIndvcmRjbG91ZCIsIlJDb2xvckJyZXdlciIpDQppZiAobGVuZ3RoKHNldGRpZmYocGFja2FnZXMsIHJvd25hbWVzKGluc3RhbGxlZC5wYWNrYWdlcygpKSkpID4gMCkgew0KICBpbnN0YWxsLnBhY2thZ2VzKHNldGRpZmYocGFja2FnZXMsIHJvd25hbWVzKGluc3RhbGxlZC5wYWNrYWdlcygpKSkpICANCn0NCmBgYA0KDQoNClRoZSBwYWNrYWdlcyByZXF1aXJlZCBmb3IgdGhpcyBwcm9qZWN0IGFyZSBtZW50aW9uZWQgYmVsb3c6DQoNCmBgYHtyIHBhY2thZ2VzLCB3YXJuaW5nPUZBTFNFLCBlcnJvcj1GQUxTRSwgbWVzc2FnZT1GQUxTRX0NCmxpYnJhcnkoZHBseXIpICAgICAgDQpsaWJyYXJ5KGxlYWZsZXQpICAgIA0KbGlicmFyeShodG1sdG9vbHMpICANCmxpYnJhcnkoZ2dwbG90MikgICAgDQpsaWJyYXJ5KGx1YnJpZGF0ZSkgIA0KbGlicmFyeShxZGFwKSAgICAgICANCmxpYnJhcnkodG0pICAgICANCmxpYnJhcnkoU25vd2JhbGxDKSANCmxpYnJhcnkod29yZGNsb3VkKSAgDQpsaWJyYXJ5KFJDb2xvckJyZXdlcikgICAgDQpgYGANCg0KRGVzY3JpcHRpb24gb2YgdGhlc2UgcGFja2FnZXMgYXJlIGFzIGJlbG93Og0KDQpQYWNrYWdlICAgIHwgRGVzY3JpcHRpb24gfA0KLS0tLS0tLS0tLS0tLS0tLS0tLS0tIHwgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS18DQooZHBseXIpICB8ICAgIAkgICNVc2VkIGZvciBkYXRhIG1hbmlwdWxhdGlvbiBvZiB0aGUgZGF0YSBzZXR8DQoobGVhZmxldCkgICAgCXwgICNVc2VkIHRvIG1ha2UgQ3JlYXRlIEludGVyYWN0aXZlIFdlYiBNYXBzfA0KKGh0bWx0b29scykgIAkgfCAjVG9vbHMgZm9yIEhUTUx8DQooZ2dwbG90MikgICAgCXwgICNVc2VkIHRvIGNyZWF0ZSBlbGVnYW50IGRhdGEgdmlzdWFsaXNhdGlvbnMgdXNpbmcgdGhlIGdyYW1tYXIgb2YgZ3JhcGhpY3N8DQoobHVicmlkYXRlKSAgCSB8ICNVc2VkIGZvciBlYXNpbHkgZGVhbGluZyB3aXRoIGRhdGVzfA0KKHFkYXApICAgICAgIAkgfCAjVXNlZCBmb3IgdGV4dCBhbmFseXNpc3wNCih0bSkgICAgICAgIAkgfCAjVGV4dCBNaW5pbmcgUGFja2FnZXwNCihTbm93YmFsbEMpIAkgfCAjVXNlZCBmb3IgdGV4dCBhbmQgV29yZCBhbmFseXNpc3wNCih3b3JkY2xvdWQpICAJfCAgI1VzZWQgdG8gY3JlYXRlIGEgd29yZCBjbG91ZHwNCihSQ29sb3JCcmV3ZXIpIHwgI1VzZWQgZm9yIGNvbG9yIHBhbGV0dGluZyBpbiBSfA0KDQoNCiMjIERhdGEgUHJlcGFyYXRpb24NCjwhLS0NCjMuMSBPcmlnaW5hbCBzb3VyY2Ugd2hlcmUgdGhlIGRhdGEgd2FzIG9idGFpbmVkIGlzIGNpdGVkIGFuZCwgaWYgcG9zc2libGUsIGh5cGVybGlua2VkLiANCjMuMiBTb3VyY2UgZGF0YSBpcyB0aG9yb3VnaGx5IGV4cGxhaW5lZCAoaS5lLiB3aGF0IHdhcyB0aGUgb3JpZ2luYWwgcHVycG9zZSBvZiB0aGUgZGF0YSwgd2hlbiB3YXMgaXQgY29sbGVjdGVkLCBob3cgbWFueSB2YXJpYWJsZXMgZGlkIHRoZSBvcmlnaW5hbCBoYXZlLCBleHBsYWluIGFueSBwZWN1bGlhcml0aWVzIG9mIHRoZSBzb3VyY2UgZGF0YSBzdWNoIGFzIGhvdyBtaXNzaW5nIHZhbHVlcyBhcmUgcmVjb3JkZWQsIG9yIGhvdyBkYXRhIHdhcyBpbXB1dGVkLCBldGMuKS4gDQogDQotLT4NCg0KVGhlIHNvdXJjZSBvZiB0aGlzIGRhdGEgaXMgZnJvbSBbS2FnZ2xlIC0gQUNMRUQgQWZyaWNhbiBDb25mbGljdHMsIDE5OTctMjAxN10oaHR0cHM6Ly93d3cua2FnZ2xlLmNvbS9qYm95c2VuL2FmcmljYW4tY29uZmxpY3RzKS4NCg0KVGhpcyBkYXRhIGlzIG9yaWdpbmFsbHkgY29sbGVjdGVkIHVuZGVyIEFDTEVEIHByb2plY3Qgd2hpY2ggaXMgYW4gYWNyb255bSBmb3IgJ0FybWVkIENvbmZsaWN0IExvY2F0aW9uIGFuZCBFdmVudCBEYXRhJy4gVGhpcyBwcm9qZWN0IGlzIGRpcmVjdGVkIGJ5IFByb2YuIENsaW9uYWRoIFJhbGVpZ2ggKFVuaXZlcnNpdHkgb2YgU3Vzc2V4KSBhbmQgb3BlcmF0ZWQgYnkgU2VuaW9yIFJlc2VhcmNoIE1hbmFnZXIgQW5kcmVhIENhcmJvbmkgKFVuaXZlcnNpdHkgb2YgU3Vzc2V4KSBmb3IgQWZyaWNhIGFuZCBIaWxsYXJ5IFRhbm9mZiBmb3IgU291dGggYW5kIFNvdXRoLUVhc3QgQXNpYS4gVGhlIGFpbSBvZiB0aGlzIHByb2plY3QgaXMgdG8gY29sbGF0ZSBkYXRhIG9uIFBvbGl0aWNhbCBWaW9sZW5jZSBpbiBkZXZlbG9waW5nIGNvdW50cmllcyB3aXRoIGZvY3VzIG9uIEFmcmljYS4gVGhpcyBkYXRhc2V0IHdhcyBmaXJzdCBpbnRyb2R1Y2VkIGluIDIwMTAgYnkgUmFsZWlnaCBhbmQgY28tYXV0aG9ycyBpbiAyMDEwIHBhcGVyIGluIHRoZSBbSm91cm5hbCBvZiBQZWFjZSBSZXNlYXJjaF0oaHR0cHM6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvSm91cm5hbF9vZl9QZWFjZV9SZXNlYXJjaCkuIFRoZSBBQ0xFRCBkYXRhIGlzIHVzZWQgYnkgc2V2ZXJhbCByZXNlYXJjaGVycyBpbiB0aGVpciByZXNlYXJjaCBvbiBjaXZpbCB3YXJzIGFuZCBwb2xpdGljYWwgdmlvbGVuY2UuIFRoaXMgZGF0YXNldCBoYXMgYWxzbyBiZWVuIHJlZmVyZW5jZWQgYnkgbmV3cyBtZWRpYSBhZ2VuY2llcyBsaWtlIFRoZSBOZXcgWW9yayBUaW1lcywgVGhlIEd1YXJkaWFuLCBCQkMgZXRjLiB0byBzdHVkeSByZWNlbnQgY29uZmxpY3QgdHJlbmRzLg0KDQpBZnRlciBleGFtaW5pbmcgdGhlIGRhdGEsIGl0IHdhcyBvYnNlcnZlZCB0aGF0IG1pc3NpbmcgdmFsdWVzIGFyZSByZWNvcmRlZCBhcyBgJ0JsYW5rcydgIGFuZCB3aXRoIGBOQWAgaW4gYSBmZXcgY29sdW1ucy4gVG8gYnJpbmcgY29uc2lzdGVuY3ksIHdlIHdpbGwgcmVwbGFjZSBCbGFua3Mgd2l0aCBOQSBkdXJpbmcgcmVhZGluZyB0aGUgZGF0YS4gVGhlIGRhdGUgZm9ybWF0IGlzIGluICJERC9NTS9ZWVlZIiBmb3JtYXQuDQoNCjwhLS0NCjMuMyBEYXRhIGltcG9ydGluZyBhbmQgY2xlYW5pbmcgc3RlcHMgYXJlIGV4cGxhaW5lZCBpbiB0aGUgdGV4dCAodGVsbCBtZSB3aHkgeW91IGFyZSBkb2luZyB0aGUgZGF0YSBjbGVhbmluZyBhY3Rpdml0aWVzIHRoYXQgeW91IHBlcmZvcm0pIGFuZCBmb2xsb3cgYSBsb2dpY2FsIHByb2Nlc3MuDQotLT4NCkRhdGEgaXMgaW1wb3J0ZWQgdXNpbmcgdGhlIHJlYWQuY3N2KCkgZnVuY3Rpb24uIEl0IHRha2VzIHRoZSBTdHJpbmcgdmFsdWVzIGFzIEZhY3RvcnMgc28gd2UgdXNlIHRoZSBhcmd1bWVudCBzdHJpbmdzQXNGYWN0b3JzID0gRkFMU0UgdG8gY29uc2lkZXIgaXQgYXMgc3RyaW5ncy4gV2UgY29udmVydCBibGFua3MgdG8gTkEgZm9yIG1pc3NpbmcgZGF0YS4NCg0KYGBge3IgcmVhZGNzdiwgZWNobz1UUlVFfQ0KZGYgPC0gcmVhZC5jc3YoImh0dHBzOi8vd3d3LmRyb3Bib3guY29tL3MvMGVlaWNrNG1vMHp2NHVnL2FmcmljYW5fY29uZmxpY3RzLmNzdj9kbD0xIiwgc3RyaW5nc0FzRmFjdG9ycyA9IEZBTFNFLCBuYS5zdHJpbmdzID0gIiIpDQoNCmBgYA0KDQpUaGlzIGRhdGFzZXQgY29udGFpbnMgdG90YWwgMjggY29sdW1ucyBiZWZvcmUgbWFraW5nIGFueSBjaGFuZ2VzLg0KDQpgYGB7ciBuYW1lcywgZWNobz1UUlVFfQ0KbmFtZXMoZGYpDQpgYGANCg0KT3V0IG9mIHRoZXNlIGNvbHVtbnMsIEFDVE9SMV9JRCwgQUNUT1IyX0lEIGFuZCBBQ1RPUl9EWUFEX0lELCBFVkVOVF9JRF9DTlRZLCBFVkVOVF9JRF9OT19DTlRZIGFyZSBzdXJyb2dhdGUgY29sdW1ucy4gU28gd2Ugd2lsbCByZW1vdmUgdGhlc2UgY29sdW1ucy4gTW9zdCBvZiB0aGUgdmFsdWVzIGluIEFMTFlfQUNUT1JfMSBhbmQgQUxMWV9BQ1RPUl8yIGFyZSBtaXNzaW5nLCBzbyB3ZSByZW1vdmUgdGhlc2UgY29sdW1ucy4gR0VPX1BSRUNJU0lPTiwgR1dOTyBhbmQgVElNRV9QUkVDSVNJT04gYXJlIG5vdCByZXF1aXJlZCBmb3Igb3VyIGFuYWx5c2lzLg0KQWZ0ZXIgcmVtb3ZpbmcgdGhlc2UgY29sdW1ucywgd2UgYXJlIGxlZnQgd2l0aCAxOCBjb2x1bW5zLg0KDQpgYGB7ciByZW1vdmVfY29sdW1ucywgZWNobz1UUlVFfQ0KZGYxIDwtIGRmWy1jKDIsIDQsIDUsIDksIDEwLCAxMywgMTQsIDE3LCAxOCwgMjcpXQ0KYGBgDQoNClRoZSB0YWJsZSBiZWxvdyBnaXZlcyBkZXRhaWxzIGFib3V0IHRoZXNlIGNvbHVtbnM6DQoNCiAgVmFyaWFibGUgICAgfCBEZXNjcmlwdGlvbiB8DQotLS0tLS0tLS0tLS0tLS0tLS0tLS0gfCAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tfA0KQUNUT1IxIHwgTmFtZSBvZiBmaXJzdCBhY3RvcnwNCkFDVE9SMiAgfCBOYW1lIG9mIHNlY29uZCBhY3RvcnwNCkFETUlOMSB8IFRoZSBsYXJnZXN0IHN1Yi1uYXRpb25hbCBhZG1pbmlzdHJhdGl2ZSByZWdpb24gaW4gd2hpY2ggdGhlIGV2ZW50IHRvb2sgcGxhY2V8DQpBRE1JTjIgfCBUaGUgc2Vjb25kLWxhcmdlc3Qgc3ViLW5hdGlvbmFsIGFkbWluaXN0cmF0aXZlIHJlZ2lvbiBpbiB3aGljaCB0aGUgZXZlbnQgdG9vayBwbGFjZXwNCkFETUlOMyB8IFRoZSB0aGlyZC1sYXJnZXN0IHN1Yi1uYXRpb25hbCBhZG1pbmlzdHJhdGl2ZSByZWdpb24gaW4gd2hpY2ggdGhlIGV2ZW50IHRvb2sgcGxhY2V8DQpDT1VOVFJZIHwgQ291bnRyeSBvZiBjb25mbGljdHwNCkVWRU5UX0RBVEUgfCBEYXRlIG9mIGNvbmZsaWN0LCBERC9NTS9ZWVlZfA0KRkFUQUxJVElFUyB8IEludGVnZXIgdmFsdWUgb2YgZmF0YWxpdGllcyB0aGF0IG9jY3VycmVkLCBhcyByZXBvcnRlZCBieSBzb3VyY2V8DQogSU5URVIxIHwgQSBudW1lcmljIGNvZGUgaW5kaWNhdGluZyB0aGUgdHlwZSBvZiBBQ1RPUjF8DQogSU5URVIyIHwgQSBudW1lcmljIGNvZGUgaW5kaWNhdGluZyB0aGUgdHlwZSBvZiBBQ1RPUjJ8DQogSU5URVJBQ1RJT04gfCBBIG51bWVyaWMgY29kZSBpbmRpY2F0aW5nIHRoZSBpbnRlcmFjdGlvbiBiZXR3ZWVuIHR5cGVzIG9mIEFDVE9SMSBhbmQgQUNUT1IyfA0KTEFUSVRVREUgfCBUaGUgbGF0aXR1ZGUgb2YgdGhlIGxvY2F0aW9ufA0KTE9DQVRJT04gfCBUaGUgbG9jYXRpb24gd2hlcmUgZXZlbnQgb2NjdXJyZWR8DQpMT05HSVRVREUgfCBUaGUgbG9uZ2l0dWRlIG9mIHRoZSBsb2NhdGlvbnwNCk5PVEVTIHwgQWRkaXRpb25hbCBub3Rlc3wNClNPVVJDRSB8IFNvdXJjZSBvZiBjb25mbGljdCBpbmZvcm1hdGlvbnwNCllFQVIgICAgICB8ICBZZWFyIGV2ZW50IG9jY3VycmVkfA0KDQpgYGB7ciBzdHIsIGV2YWw9RkFMU0UsIGVjaG89RkFMU0V9DQpzdHIoZGYxKQ0KYGBgDQoNCg0KDQoNCjwhLS0NClJlbW92aW5nIGJsYW5rIGNlbGxzDQotLT4NCg0KTG9va2luZyBhdCBjb2x1bW5zIEFDVE9SMiwgQURNSU4yLCBBRE1JTjMsIExPQ0FUSU9OLCBOT1RFUywgU09VUkNFIHdlIHNlZSB0aGF0IHRoZXkgaGF2ZSBzb21lIG1pc3NpbmcgZGF0YS4NCmBgYHtyIE1pc3NfY2hlY2ssIGVjaG89VFJVRX0NCmFwcGx5KGRmMSwgMiwgZnVuY3Rpb24oeCkgYW55KGlzLm5hKHgpKSkNCmBgYA0KRm9yIENvbHVtbiBBQ1RPUjIsIE5BIHRlbGxzIHVzIHRoYXQgdGhlcmUgd2FzIG5vIHNlY29uZCBhY3Rvci4gU28gd2UgY2FuIHJlcGxhY2UgaXQgd2l0aCBzdHJpbmcgIk5PTkUiDQoNCmBgYHtyIGJsYW5rcywgZWNobz1UUlVFfQ0KZGYxJEFDVE9SMltpcy5uYShkZjEkQUNUT1IyKV0gPC0gIk5PTkUiDQpoZWFkKGRmMSRBQ1RPUjIpDQpgYGANCk5vdyBmb3IgY29sdW1ucywgSU5URVIxLCBJTlRFUjIgYW5kIElOVEVSQUNUSU9OIG51bWVyaWNhbCBzdWJzaXR1dGVzIGZvciBjYXRlZ29yaWVzIGFyZSBwcm92aWRlZC4gV2Ugd2lsbCByZXBsYWNlIHRoZXNlIHdpdGggdGhlIGFjdHVhbCB2YWx1ZXMgZnJvbSB0aGUgY29kZWJvb2suDQoNClByZXZpZXcgb2YgQ29sdW1uIElOVEVSMQ0KYGBge3IgcmVwbGFjZV9jYXRlZ29yaWNhbCwgZWNobz1UUlVFfQ0KDQpkZjEkSU5URVIxIDwtIGFzLmNoYXJhY3RlcihkZjEkSU5URVIxKQ0KbHV0MSA8LSBjKCIxIiA9ICJHb3Zlcm5tZW50IG9yIG11dGlub3VzIGZvcmNlIiwgIjIiID0gIlJlYmVsIGZvcmNlIiwNCiAgICAgICAgICAiMyIgPSAiUG9saXRpY2FsIG1pbGl0aWEiLCAiNCIgPSAiRXRobmljIG1pbGl0aWEiLCANCiAgICAgICAgICAiNSIgPSAiUmlvdGVycyIsICI2IiA9ICJQcm90ZXN0ZXJzIiwgIjciID0gIkNpdmlsaWFucyIsIA0KICAgICAgICAgICI4IiA9ICJPdXRzaWRlL2V4dGVybmFsIGZvcmNlIikNCmRmMSRJTlRFUjEgPC0gbHV0MVtkZjEkSU5URVIxXQ0KaGVhZChkZjEkSU5URVIxKQ0KYGBgDQoNClByZXZpZXcgb2YgQ29sdW1uIElOVEVSMg0KDQpgYGB7ciByZXBsYWNlX2NhdGVnb3JpY2FsXzEsIGVjaG89VFJVRX0NCmRmMSRJTlRFUjIgPC0gYXMuY2hhcmFjdGVyKGRmMSRJTlRFUjIpDQpsdXQyIDwtIGMoIjAiID0gIk5PTkUiLCAiMSIgPSAiR292ZXJubWVudCBvciBtdXRpbm91cyBmb3JjZSIsIA0KICAgICAgICAgICIyIiA9ICJSZWJlbCBmb3JjZSIsICIzIiA9ICJQb2xpdGljYWwgbWlsaXRpYSIsIA0KICAgICAgICAgICI0IiA9ICJFdGhuaWMgbWlsaXRpYSIsICI1IiA9ICJSaW90ZXJzIiwgIjYiID0gIlByb3Rlc3RlcnMiLA0KICAgICAgICAgICI3IiA9ICJDaXZpbGlhbnMiLCAiOCIgPSAiT3V0c2lkZS9leHRlcm5hbCBmb3JjZSIpDQpkZjEkSU5URVIyIDwtIGx1dDJbZGYxJElOVEVSMl0NCmhlYWQoZGYxJElOVEVSMikNCmBgYA0KDQoNClByZXZpZXcgb2YgQ29sdW1uIElOVEVSQUNUSU9ODQoNCmBgYHtyIHJlcGxhY2VfY2F0ZWdvcmljYWxfMiwgZWNobz1UUlVFfQ0KZGYxJElOVEVSQUNUSU9OPC1hcy5jaGFyYWN0ZXIoZGYxJElOVEVSQUNUSU9OKQ0KbHV0MzwtYygiMTAiID0gIlNPTEUgTUlMSVRBUlkgQUNUSU9OIiwgIjExIiA9ICJNSUxJVEFSWSBWRVJTVVMgTUlMSVRBUlkiLA0KICAgICAgICAiMTIiID0gIk1JTElUQVJZIFZFUlNVUyBSRUJFTFMiLCAiMTMiID0gIk1JTElUQVJZIFZFUlNVUyBQT0xJVElDQUwgTUlMSVRJQSIsDQogICAgICAgICIxNCIgPSAiTUlMSVRBUlkgVkVSU1VTIENPTU1VTkFMIE1JTElUSUEiLCAiMTUiID0gIk1JTElUQVJZIFZFUlNVUyBSSU9URVJTIiwNCiAgICAgICAgIjE2IiA9ICJNSUxJVEFSWSBWRVJTVVMgUFJPVEVTVEVSUyIsICIxNyIgPSAiTUlMSVRBUlkgVkVSU1VTIENJVklMSUFOUyIsDQogICAgICAgICIxOCIgPSAiTUlMSVRBUlkgVkVSU1VTIE9USEVSIiwgIjIwIiA9ICJTT0xFIFJFQkVMIEFDVElPTiAiLA0KICAgICAgICAiMjIiID0gIlJFQkVMUyBWRVJTVVMgUkVCRUxTIiwgIjIzIiA9ICJSRUJFTFMgVkVSU1VTIFBPTElUSUNBTCBNSUxJSVRBIiwNCiAgICAgICAgIjI0IiA9ICJSRUJFTFMgVkVSU1VTIENPTU1VTkFMIE1JTElUSUEiLCAiMjUiID0gIlJFQkVMUyBWRVJTVVMgUklPVEVSUyIsDQogICAgICAgICIyNiIgPSAiUkVCRUxTIFZFUlNVUyBQUk9URVNURVJTIiwgIjI3IiA9ICJSRUJFTFMgVkVSU1VTIENJVklMSUFOUyIsDQogICAgICAgICIyOCIgPSAiUkVCRUxTIFZFUlNVUyBPVEhFUlMiLCAiMzAiID0gIlNPTEUgUE9MSVRJQ0FMIE1JTElUSUEgQUNUSU9OIiwNCiAgICAgICAgIjMzIiA9ICJQT0xJVElDQUwgTUlMSVRJQSBWRVJTVVMgUE9MSVRJQ0FMIE1JTElUSUEiLCANCiAgICAgICAgIjM0IiA9ICJQT0xJVElDQUwgTUlMSVRJQSBWRVJTVVMgQ09NTVVOQUwgTUlMSVRJQSIsIA0KICAgICAgICAiMzUiID0gIlBPTElUSUNBTCBNSUxJVElBIFZFUlNVUyBSSU9URVJTIiwgDQogICAgICAgICIzNiIgPSAiUE9MSVRJQ0FMIE1JTElUSUEgVkVSU1VTIFBST1RFU1RFUlMiLCANCiAgICAgICAgIjM3IiA9ICJQT0xJVElDQUwgTUlMSVRJQSBWRVJTVVMgQ0lWSUxJQU5TIiwNCiAgICAgICAgIjM4IiA9ICJQT0xJVElDQUwgTUlMSVRJQSBWRVJTVVMgT1RIRVJTIiwNCiAgICAgICAgIjQwIiA9ICJTT0xFIENPTU1VTkFMIE1JTElUSUEgQUNUSU9OIiwgDQogICAgICAgICI0NCIgPSAiQ09NTVVOQUwgTUlMSVRJQSBWRVJTVVMgQ09NTVVOQUwgTUlMSVRJQSIsIA0KICAgICAgICAiNDUiID0gIkNPTU1VTkFMIE1JTElUSUEgVkVSU1VTIFJJT1RFUlMiLCANCiAgICAgICAgIjQ2IiA9ICJDT01NVU5BTCBNSUxJVElBIFZFUlNVUyBQUk9URVNURVJTIiwgDQogICAgICAgICI0NyIgPSAiQ09NTVVOQUwgTUlMSVRJQSBWRVJTVVMgQ0lWSUxJQU5TIiwgDQogICAgICAgICI0OCIgPSAiQ09NTVVOQUwgTUlMSVRJQSBWRVJTVVMgT1RIRVIiLCI1MCIgPSAiU09MRSBSSU9URVIgQUNUSU9OIiwgDQogICAgICAgICI1NSIgPSAiUklPVEVSUyBWRVJTVVMgUklPVEVSUyIsICI1NiIgPSAiUklPVEVSUyBWRVJTVVMgUFJPVEVTVEVSUyIsIA0KICAgICAgICAiNTciID0gIlJJT1RFUlMgVkVSU1VTIENJVklMSUFOUyIsICI1OCIgPSAiUklPVEVSUyBWRVJTVVMgT1RIRVJTIiwgDQogICAgICAgICI2MCIgPSAiU09MRSBQUk9URVNURVIgQUNUSU9OIiwgIjY2IiA9ICJQUk9URVNURVJTIFZFUlNVUyBQUk9URVNURVJTIiwgDQogICAgICAgICI2NyIgPSAiUFJPVEVTVEVSUyBWRVJTVVMgQ0lWSUxJQU5TIiwgIjY4IiA9ICJQUk9URVNURVJTIFZFUlNVUyBPVEhFUiIsIA0KICAgICAgICAiNzAiID0gIlNPTEUgQ0lWSUxJQU5TIiwgIjc3IiA9ICJDSVZJTElBTlMgVkVSU1VTIENJVklMSUFOUyIsIA0KICAgICAgICAiNzgiID0gIk9USEVSIEFDVE9SIFZFUlNVUyBDSVZJTElBTlMiLCAiODAiID0gIlNPTEUgT1RIRVIgQUNUSU9OIiwgDQogICAgICAgICI4OCIgPSAiT1RIRVJTIFZFUlNVUyBPVEhFUlMiKQ0KZGYxJElOVEVSQUNUSU9OIDwtIGx1dDNbZGYxJElOVEVSQUNUSU9OXQ0KaGVhZChkZjEkSU5URVJBQ1RJT04pDQpgYGANCg0KDQpDb252ZXJ0IExPTkdJVFVERSBhbmQgTEFUSVRVREUgY29sdW1ucyB0byBOdW1lcmljDQpgYGB7ciwgbWVzc2FnZT1GQUxTRSwgZXJyb3I9RkFMU0UsIHdhcm5pbmc9RkFMU0V9DQpkZjEkTE9OR0lUVURFPC1hcy5udW1lcmljKGRmMSRMT05HSVRVREUpDQpkZjEkTEFUSVRVREU8LWFzLm51bWVyaWMoZGYxJExBVElUVURFKQ0KDQpgYGANCg0KRXhhbWluaW5nIHRoZSBkYXRlIGNvbHVtbiAtIEVWRU5UX0RBVEUNCg0KYGBge3J9DQpoZWFkKGRmMSRFVkVOVF9EQVRFKQ0KDQpgYGANCg0KVGhlIGV2ZW50IGRhdGUgY29sdW1uIGlzIGluIEREL01NL1lZWVkgZm9ybWF0LiBXZSBhc3NpZ24gdGhpcyB0byB0aGUgZGF0YSBzZXQgdXNpbmcgZG15KCkgZnVuY3Rpb24uDQoNCg0KDQpgYGB7cn0NCg0KZGYxJEVWRU5UX0RBVEU8LWRteShkZjEkRVZFTlRfREFURSkNCg0KYGBgDQoNCg0KZm9yIGZ1cnRoZXIgYW5hbHlzaXMgYW5kIGFnZ3JlZ2F0aW5nIGRhdGEgb24gbW9udGhseSBiYXNpcyB3ZXcgbXV0YXRlIHRoZSBkYXRhc2V0IHRvIGFkZCBhIGNvbHVtbiBmb3IgbW9udGguDQoNCmBgYHtyLCB3YXJuaW5nPUZBTFNFLCBlcnJvcj1GQUxTRSwgbWVzc2FnZT1GQUxTRX0NCmRmMTwtZGYxJT4lbXV0YXRlKE1PTlRIPW1vbnRoKGRmMSRFVkVOVF9EQVRFKSkNCmBgYA0KDQoNCjwhLS0NCjMuNCBPbmNlIHlvdXIgZGF0YSBpcyBjbGVhbiwgc2hvdyB3aGF0IHRoZSBmaW5hbCBkYXRhIHNldCBsb29rcyBsaWtlLiBIb3dldmVyLCBkbyBub3QgcHJpbnQgb2ZmIGEgZGF0YSBmcmFtZSB3aXRoIDIwMCsgcm93czsgc2hvdyBtZSB0aGUgZGF0YSBpbiB0aGUgbW9zdCBjb25kZW5zZWQgZm9ybSBwb3NzaWJsZS4gDQozLjUgUHJvdmlkZSBzdW1tYXJ5IGluZm9ybWF0aW9uIGFib3V0IHRoZSB2YXJpYWJsZXMgb2YgY29uY2VybiBpbiB5b3VyIGNsZWFuZWQgZGF0YSBzZXQuIERvIG5vdCBqdXN0IHByaW50IG9mZiBhIGJ1bmNoIG9mIGNvZGUgY2h1bmtzIHdpdGggc3RyKCksIHN1bW1hcnkoKSwgZXRjLiBSYXRoZXIsIHByb3ZpZGUgbWUgd2l0aCBhIGNvbnNvbGlkYXRlZCBleHBsYW5hdGlvbiwgZWl0aGVyIHdpdGggYSB0YWJsZSB0aGF0IHByb3ZpZGVzIHN1bW1hcnkgaW5mbyBmb3IgZWFjaCB2YXJpYWJsZSBvciBhIG5pY2VseSB3cml0dGVuIHN1bW1hcnkgcGFyYWdyYXBoIHdpdGggaW5saW5lIGNvZGUuDQoNCi0tPg0KDQpQcmV2aWV3IG9mIGRhdGEgYWZ0ZXIgY2xlYW5pbmcgaXMgZ2l2ZW4gYmVsb3c6DQoNCg0KYGBge3IgY2xlYW5fZGF0YSwgZWNobz1UUlVFfQ0KDQpoZWFkKGRmMSkNCmBgYA0KIyMgRXhwbG9yYXRvcnkgRGF0YSBBbmFseXNpcw0KV2Ugc3RhcnQgb3VyIEV4cGxvcmF0b3J5IGRhdGEgYW5hbHlzaXMgYnkgbG9va2luZyBhdCB0aGUgc3VtbWFyeSBzdGF0aXN0aWNzIG9mIG51bWJlcmljYWwgYXRyaWJ1dGVzIG9mIG91ciBkYXRhIHNldC4NCg0KYGBge3Igc3VtbWFyeSwgZWNobz1UUlVFLGV2YWw9RkFMU0V9DQoNCnN1bW1hcnkoZGYxKQ0KYGBgDQoNCg0KICBWYXJpYWJsZSAgICB8IE1pbiAgICAgICAgICAgfE1heCAgICAgICAgICB8TWVhbiAgICAgfA0KLS0tLS0tLS0tLS0tLSB8IC0tLS0tLS0tLS0tLS0gfC0tLS0tLS0tLS0tLS18LS0tLS0tLS0tfA0KRXZlbnQgRGF0ZSB8IDE5OTctMDEtMDEgfCAyMDE3LTA3LTI5IHwgLSB8DQpGYXRhbGl0aWVzICAgIHwgMCAgICAgICAgfCAgMjUwMDAgICAgICAgICAgIHwgICAgNC40MiAgICAgfA0KWWVhciAgICAgICAgfCAxOTk3ICAgICAgICB8ICAgMjAxNyAgICAgICAgICB8ICAgICAtICAgIHwNCg0KDQoNCkZyb20gYWJvdmUsIHdlIGNhbiBzZWUgdGhhdCBtaW5pbXVtIGZhdGFsaXRpZXMgaW4gY29uZmxpY3RzIDAgYW5kIG1heGltdW0gdmFsdWUgaXMgMjUwMDAgd2l0aCBhIG1lYW4gb2YgNC40Mi4NCg0KKipFeHBsb3JpbmcgRGF0YXNldCB3aXRoIG51bWJlciBvZiBjb25mbGljdHMqKg0KDQpCZWxvdyBjaGFydCBzaG93cyB0aGUgbnVtYmVyIG9mIGNvbmZsaWN0cyB3aGljaCBoYXBwZW5lZCBldmVyeSB5ZWFyLg0KYGBge3IgaGlzdCwgZWNobz1UUlVFfQ0KI2NyZWF0aW5nIGRhdGEgc2V0IGZvciBnZ3Bsb3QoKQ0KcGxvdDI8LWRmMSU+JQ0KICBncm91cF9ieShZRUFSKSU+JXN1bW1hcmlzZShjb3VudD1uKCkpJT4lDQogIGFycmFuZ2UoZGVzYyhjb3VudCkpDQoNCiN1c2luZyBnZ3Bsb3QgZm9yIHZpc3VhbGl6YXRpb24NCnBsb3QyJT4lZ2dwbG90KGFlcyh4ID0gWUVBUix5PWNvdW50LGZpbGw9LWNvdW50KSkgKw0KICBnZW9tX2JhcihzdGF0ID0gImlkZW50aXR5IikgKw0KICBzY2FsZV94X2NvbnRpbnVvdXMobmFtZSA9ICJZZWFyIikgKw0KICBzY2FsZV95X2NvbnRpbnVvdXMobmFtZSA9ICJUb3RhbCBOdW1iZXIgb2YgQ29uZmxpY3RzIixsYWJlbHMgPSBzY2FsZXM6OmNvbW1hKSArDQogIGdndGl0bGUoIkZyZXF1bmN5IFBsb3QgZm9yIE51bWJlciBvZiBDb25mbGljdHMgaW4gcGFzdCAyMCB5ZWFycyIsDQogIHN1YnRpdGxlID0gIkRhdGEgYWJvdXQgbnVtYmVyIG9mIGNvbmZsaWN0cyB3aGljaCBoYXBwZW5lZCBmcm9tIDE5OTcgdG8gMjAxNyIpDQoNCg0KYGBgDQogSXQgY2FuIGJlIG9ic2VydmVkIHRoYXQgbWF4aW11bSBudW1iZXIgb2YgY29uZmxpY3RzIGhhcHBlbmVkIGluIDIwMTYuIA0KIA0KIERyaWxsaW5nIGRvd24sIHdlIHRyeSB0byB1bmRlcnN0YW5kIHdoaWNoIGNvdW50cmllcyB3ZXJlIG1vc3QgaW52b2x2ZWQgaW4gdGhlIGNvbmZsaWN0cyBpbiB0aGlzIHllYXIuDQoNCg0KYGBge3J9DQojY3JlYXRpbmcgZGF0YSBzZXQgZm9yIGdncGxvdCgpDQpwbG90MTwtZGYxJT4lDQogIGZpbHRlcihZRUFSPT0yMDE2KSU+JQ0KICBncm91cF9ieShDT1VOVFJZKSU+JXN1bW1hcmlzZShjb3VudD1uKCkpJT4lDQogIGFycmFuZ2UoZGVzYyhjb3VudCkpJT4laGVhZChuPTEwKQ0KDQojdXNpbmcgZ2dwbG90IGZvciB2aXN1YWxpemF0aW9uDQpwbG90MSU+JWFycmFuZ2UoZGVzYyhjb3VudCkpJT4lDQogIGdncGxvdChhZXMoeCA9IHJlb3JkZXIoQ09VTlRSWSwtY291bnQpLCB5PWNvdW50LGZpbGw9LWNvdW50KSkgKw0KICBnZW9tX2JhcihzdGF0ID0gImlkZW50aXR5IikgKyANCiAgc2NhbGVfeF9kaXNjcmV0ZShuYW1lID0gIkNvdW50cnkiKSArDQogIHNjYWxlX3lfY29udGludW91cyhuYW1lID0gIlRvdGFsIE51bWJlciBvZiBDb25mbGljdHMiLGxhYmVscyA9IHNjYWxlczo6Y29tbWEpICsNCiAgZ2d0aXRsZSgiRnJlcXVlbmN5IFBsb3QgZm9yIE51bWJlciBvZiBDb25mbGljdHMgIGluIDIwMTYiLA0KICBzdWJ0aXRsZSA9ICJUb3AgMTAgY291bnRyaWVzIHdpdGggaGlnaGVzdCBudW1iZXIgb2YgY29uZmxpY3RzIGluIDIwMTYiKSsNCiAgY29vcmRfZmxpcCgpDQpgYGANCg0KSXQgY2FuIGJlIHNlZW4gdGhhdCBTb21hbGlhIGhhZCB0aGUgaGlnaGVzdCBudW1iZXIgb2YgY29uZmxpY3RzLiBXZSB0cnkgdG8gZmluZCB0aGUgcmVnaW9ucyBpbiBTb21hbGlhIHdoZXJlIGNvbmZsaWN0cyBvY2N1cmVkLg0KDQpGcm9tIHRoZSBtYXAgYmVsb3csIGl0Y2FuIGJlIHNlZW4gdGhhdCB0aGUgZXZlbnRzIHdlcmUgc3ByZWFkIGFsbCBhY3Jvc3MgdGhlIGNvdW50cnkgb2YgU29tYWxpYS4NCg0KYGBge3J9DQojY3JlYXRpbmcgZGF0YXNldCB3aXRoIGRlc2lyZWQgTGF0aXR1ZGUgYW5kIExvbmdpdHVkZQ0KZGF0YSA9IGRmMSAlPiUNCiAgZmlsdGVyKFlFQVI9PTIwMTYmQ09VTlRSWT09IlNvbWFsaWEiKSAlPiUgDQogIGZpbHRlcighaXMubmEoTEFUSVRVREUpKSAlPiUNCiAgZmlsdGVyKCFpcy5uYShMT05HSVRVREUpKQ0KDQojZGVmaW5pbmcgbWVkaWFuIGxvY2F0aW9uDQpjZW50ZXJfbG9uID0gbWVkaWFuKGRhdGEkTE9OR0lUVURFKQ0KY2VudGVyX2xhdCA9IG1lZGlhbihkYXRhJExBVElUVURFKQ0KDQojY3JlYXRpbmcgY29sb3IgcGFsZXR0ZQ0KcGFsZXR0ZV9jb2xvciA8LSBjb2xvckZhY3RvcihjKCJyZWQiLCJibHVlIiwiZ3JlZW4iLCJ5ZWxsb3ciLCJvcmFuZ2UiKSwgZGF0YSRDT1VOVFJZKQ0KDQojY3JlYXRpbmcgbWFwDQpsZWFmbGV0KGRhdGEpICU+JSBhZGRUaWxlcygpICU+JQ0KICBhZGRDaXJjbGVzKGxuZyA9IH5MT05HSVRVREUsIGxhdCA9IH5MQVRJVFVERSwjcmFkaXVzID0gfigpLCANCiAgY29sb3IgPSB+cGFsZXR0ZV9jb2xvcihDT1VOVFJZKSklPiUNCg0KI3NldHRpbmcgdGhlIGxvY2F0aW9uIG9mIHRoZSBtYXAgIA0KICBzZXRWaWV3KGxuZz1jZW50ZXJfbG9uLCBsYXQ9Y2VudGVyX2xhdCx6b29tID0gNSkgJT4lDQoNCiNhZGRpbmcgYSBtaW5pbWFwICANCiAgYWRkTWluaU1hcCgiYm90dG9tcmlnaHQiLCB3aWR0aCA9IDE1MCwgaGVpZ2h0ID0gMTUwLA0KICBjb2xsYXBzZWRXaWR0aCA9IDE5LCBjb2xsYXBzZWRIZWlnaHQgPSAxOSwgem9vbUxldmVsT2Zmc2V0ID0gLTUsDQogIHpvb21MZXZlbEZpeGVkID0gRkFMU0UsIGNlbnRlckZpeGVkID0gRkFMU0UsIHpvb21BbmltYXRpb24gPSBGQUxTRSwNCiAgdG9nZ2xlRGlzcGxheSA9IEZBTFNFLCBhdXRvVG9nZ2xlRGlzcGxheSA9IEZBTFNFLCBtaW5pbWl6ZWQgPSBGQUxTRSwNCiAgYWltaW5nUmVjdE9wdGlvbnMgPSBsaXN0KGNvbG9yID0gIiNmZjc4MDAiLCB3ZWlnaHQgPSAxLCBjbGlja2FibGUgPSBGQUxTRSksDQogIHNoYWRvd1JlY3RPcHRpb25zID0gbGlzdChjb2xvciA9ICIjMDAwMDAwIiwgd2VpZ2h0ID0gMSwgY2xpY2thYmxlID0gRkFMU0UsDQogIG9wYWNpdHkgPSAwLCBmaWxsT3BhY2l0eSA9IDApLCBzdHJpbmdzID0gbGlzdChoaWRlVGV4dCA9ICJIaWRlIE1pbmlNYXAiLA0KICBzaG93VGV4dCA9ICJTaG93IE1pbmlNYXAiKSwgdGlsZXMgPSBOVUxMLCBtYXBPcHRpb25zID0gbGlzdCgpKQ0KDQpgYGANCg0KKipFeHBsb3JpbmcgRGF0YXNldCBjb25zaWRlcmluZyBmYXRhbGl0aWVzKioNCkJlbG93IGJhcnBsb3Qgc2hvd3MgY29tcGFyaXNvbiBvZiBmYXRhbGl0aWVzIGhhcHBlbmVkIGVhY2ggeWVhciBkdWUgdG8gY29uZmxpY3RzLg0KDQpgYGB7ciBoaXN0XzEsIGVjaG89VFJVRX0NCmRmMSU+JQ0KICBncm91cF9ieShZRUFSKSU+JXN1bW1hcmlzZSh0b3RhbD1zdW0oRkFUQUxJVElFUykpJT4lDQogIGdncGxvdChhZXMoeD1ZRUFSLHk9dG90YWwsZmlsbD0tdG90YWwpKStnZW9tX2JhcihzdGF0ID0gImlkZW50aXR5IikrDQogIHNjYWxlX3hfY29udGludW91cyhuYW1lID0gIlllYXIiKSArDQogIHNjYWxlX3lfY29udGludW91cyhuYW1lID0gIlRvdGFsIE51bWJlciBvZiBGYXRhbGl0aWVzIixsYWJlbHMgPSBzY2FsZXM6OmNvbW1hKSArDQogIGdndGl0bGUoIkZhdGFsaXRpZXMgb3ZlciB0aGUgeWVhcnMgZHVlIHRvIGNvbmZsaWN0cyIsDQogIHN1YnRpdGxlID0gIkRhdGEgYWJvdXQgZmF0YWxpdGllcyBoYXBwZW5pbmcgZXZlcnkgeWVhciBkdWUgdG8gY29uZmxpY3RzIikNCg0KYGBgDQoNCkl0IGNhbiBiZSBzZWVuIGZyb20gdGhlIHBsb3QgYWJvdmUgdGhhdCBtYXhpbXVtIGZhdGFsaXRpZXMgb2NjdXJlZCBkdXJpbmcgY29uZmxpY3RzIGluIDE5OTkuDQoNCkRpZ2dpbmcgZnVydGhlciwgd2UgdHJ5IHRvIHVuZGVyc3RhbmQgd2hpY2ggbW9udGhzIHRoZXNlIGNvbmZsaWN0cyBsZWQgdG8gZmF0YWxpdGllcy4NCg0KDQpgYGB7cn0NCg0KICANCiAgZGYxJT4lDQogIGZpbHRlcihZRUFSPT0xOTk5KSU+JQ0KICBncm91cF9ieShNT05USCklPiUNCiAgc3VtbWFyaXNlKHRvdGFsPXN1bShGQVRBTElUSUVTKSklPiUNCiAgZ2dwbG90KGFlcyh4PWFzLmZhY3RvcihNT05USCkseT10b3RhbCxmaWxsPS10b3RhbCkpK2dlb21fYmFyKHN0YXQgPSAiaWRlbnRpdHkiKSsNCiAgc2NhbGVfeF9kaXNjcmV0ZShuYW1lID0gIk1vbnRoIG9mIDE5OTkiKSArDQogIHNjYWxlX3lfY29udGludW91cyhuYW1lID0gIlRvdGFsIEZhdGFsaXRpZXMiLGxhYmVscyA9IHNjYWxlczo6Y29tbWEpICsNCiAgZ2d0aXRsZSgiTnVtYmVyIG9mIGZhdGFsaXRpZXMgaW4gMTk5OSIsDQogIHN1YnRpdGxlID0gIkRhdGEgYWJvdXQgZmF0YWxpdGllcyB3aGljaCBoYXBwZW5lZCBpbiAxOTk5IHBlciBtb250aCIpDQoNCmBgYA0KDQpJdCBpcyBvYnNlcnZlZCB0aGF0LCBtYXhpbXVtIGZhdGFsaXRpZXMgaGFwcGVuZWQgaW4gZmlyc3QgZm91ciBtb250aHMuDQoNCg0KV2l0aCBiZWxvdyBwbG90IHdlIHRyeSB0byBhbmFseXplIHdoaWNoIGNvdW50cnkgaGFkIG1heGltdW0gZmF0YWxpdGllcyBpbiAxOTk5Lg0KYGBge3J9DQpkZjElPiUNCiAgZmlsdGVyKFlFQVI9PTE5OTkpJT4lDQogIGdyb3VwX2J5KENPVU5UUlkpJT4lc3VtbWFyaXNlKHRvdGFsPXN1bShGQVRBTElUSUVTKSklPiUNCiAgYXJyYW5nZShkZXNjKHRvdGFsKSklPiVoZWFkKG49MTApJT4lDQogIGdncGxvdChhZXMoeCA9IHJlb3JkZXIoQ09VTlRSWSwtdG90YWwpLCB5PXRvdGFsLGZpbGw9LXRvdGFsKSkgKw0KICBnZW9tX2JhcihzdGF0ID0gImlkZW50aXR5IikgKyANCiAgc2NhbGVfeF9kaXNjcmV0ZShuYW1lID0gIkNvdW50cnkiKSArDQogIHNjYWxlX3lfY29udGludW91cyhuYW1lID0gIlRvdGFsIGZhdGFsaXRpZXMiLGxhYmVscyA9IHNjYWxlczo6Y29tbWEpICsNCiAgZ2d0aXRsZSgiRmF0YWxpdGllcyBhbmFseXNpcyBmb3IgdGhlIHllYXIgMTk5OSIsDQogIHN1YnRpdGxlID0gIkFuYWx5c2lzIG9mIGZhdGFsaXRpZXMgaW4gZWFjaCBjb3VudHJ5IGluIHRoZSB5ZWFyIDE5OTkiKStjb29yZF9mbGlwKCkNCmBgYA0KDQpGcm9tIHRoZSBwbG90IGFib3ZlIGl0IGlzIGV2aWRlbnQgdGhhdCBFcml0cmVhIGFuZCBBbmdvbGEgaGFkIHRoZSBtYXhpbXVtIGZhdGFsaXRpZXMuDQoNCg0KDQoNCg0KPGJyIC8+DQoNCg0KPCEtLQ0KNC4xIERpc2N1c3MgaG93IHlvdSBwbGFuIHRvIHVuY292ZXIgbmV3IGluZm9ybWF0aW9uIGluIHRoZSBkYXRhIHRoYXQgaXMgbm90IHNlbGYtZXZpZGVudC4gV2hhdCBhcmUgZGlmZmVyZW50IHdheXMgeW91IGNvdWxkIGxvb2sgYXQgdGhpcyBkYXRhIHRvIGFuc3dlciB0aGUgcXVlc3Rpb25zIHlvdSB3YW50IHRvIGFuc3dlcj8gRG8geW91IHBsYW4gdG8gc2xpY2UgYW5kIGRpY2UgdGhlIGRhdGEgaW4gZGlmZmVyZW50IHdheXMsIGNyZWF0ZSBuZXcgdmFyaWFibGVzLCBvciBqb2luIHNlcGFyYXRlIGRhdGEgZnJhbWVzIHRvIGNyZWF0ZSBuZXcgc3VtbWFyeSBpbmZvcm1hdGlvbj8gSG93IGNvdWxkIHlvdSBzdW1tYXJpemUgeW91ciBkYXRhIHRvIGFuc3dlciBrZXkgcXVlc3Rpb25zPyANCjQuMiBXaGF0IHR5cGVzIG9mIHBsb3RzIGFuZCB0YWJsZXMgd2lsbCBoZWxwIHlvdSB0byBpbGx1c3RyYXRlIHRoZSBmaW5kaW5ncyB0byB5b3VyIHF1ZXN0aW9ucz8gDQo0LjMgV2hhdCBkbyB5b3Ugbm90IGtub3cgaG93IHRvIGRvIHJpZ2h0IG5vdyB0aGF0IHlvdSBuZWVkIHRvIGxlYXJuIHRvIGFuc3dlciB5b3VyIHF1ZXN0aW9ucz8gDQo0LjQgRG8geW91IHBsYW4gb24gaW5jb3Jwb3JhdGluZyBhbnkgbWFjaGluZSBsZWFybmluZyB0ZWNobmlxdWVzIChpLmUuIGxpbmVhciByZWdyZXNzaW9uLCBkaXNjcmltaW5hbnQgYW5hbHlzaXMsIGNsdXN0ZXIgYW5hbHlzaXMpIHRvIGFuc3dlciB5b3VyIHF1ZXN0aW9ucz8gDQotLT4NCg0KQmVsb3cgdGFibGVzIGdpdmUgYW4gb3ZlcmFsbCBwaWN0dXJlIG9mIHRvcCA1IHllYXJzIGFuZCB0b3AgMTAgY291bnRyaWVzIHdpdGggaGlnaGVzdCBmYXRhbGl0aWVzLg0KDQoNCmBgYHtyIHN1bTN9DQpkZjElPiUNCiAgZ3JvdXBfYnkoWUVBUiklPiUNCiAgc3VtbWFyaXNlKHN1bShGQVRBTElUSUVTKSklPiUNCiAgYXJyYW5nZShkZXNjKGBzdW0oRkFUQUxJVElFUylgKSklPiUNCiAgaGVhZChuPTUpDQoNCmBgYA0KDQpGcm9tIHRoZSB0YWJsZSBhYm92ZSwgd2UgY2FuIHNlZSB0aGF0IHllYXIgMTk5OSBoYWQgdGhlIGhpZ2hlc3QgZmF0YWxpdGllcyBkdWUgdG8gY29uZmxpY3RzLg0KDQpgYGB7ciBzdW00LCBlY2hvPVRSVUV9DQoNCmRmMSU+JQ0KICBncm91cF9ieShDT1VOVFJZKSU+JQ0KICBzdW1tYXJpc2Uoc3VtKEZBVEFMSVRJRVMpKSU+JQ0KICBhcnJhbmdlKGRlc2MoYHN1bShGQVRBTElUSUVTKWApKSU+JQ0KICBoZWFkKG49MTApDQpgYGANCkhlcmUsIHdlIGNhbiBzZWUgdGhhdCBBbmdvbGEgaGFzIHRoZSBoaWdoZXN0IGZhdGFsaXRpZXMgZHVlIHRvIGNvbmZsaWN0cyBvdmVyIGFsbCB0aGUgeWVhcnMuDQoNCjwhLS0NCg0KIyMgRm9ybWF0dGluZyAmIE90aGVyIFJlcXVpcmVtZW50cw0KDQo3LjEgQWxsIGNvZGUgaXMgdmlzaWJsZSwgcHJvcGVyIGNvZGluZyBzdHlsZSBpcyBmb2xsb3dlZCwgYW5kIGNvZGUgaXMgd2VsbCBjb21tZW50ZWQgKHNlZSBzZWN0aW9uIHJlZ2FyZGluZyBzeWxlKS4gDQo3LjIgQ29kaW5nIGlzIHN5c3RlbWF0aWMgLSBjb21wbGljYXRlZCBwcm9ibGVtIGJyb2tlbiBkb3duIGludG8gc3ViLXByb2JsZW1zIHRoYXQgYXJlIGluZGl2aWR1YWxseSBtdWNoIHNpbXBsZXIuIENvZGUgaXMgZWZmaWNpZW50LCBjb3JyZWN0LCBhbmQgbWluaW1hbC4gQ29kZSB1c2VzIGFwcHJvcHJpYXRlIGRhdGEgc3RydWN0dXJlIChsaXN0LCBkYXRhIGZyYW1lLCB2ZWN0b3IvbWF0cml4L2FycmF5KS4gQ29kZSBjaGVja3MgZm9yIGNvbW1vbiBlcnJvcnMuIA0KNy4zIEFjaGlldmVtZW50LCBtYXN0ZXJ5LCBjbGV2ZXJuZXNzLCBjcmVhdGl2aXR5OiBUb29scyBhbmQgdGVjaG5pcXVlcyBmcm9tIHRoZSBjb3Vyc2UgYXJlIGFwcGxpZWQgdmVyeSBjb21wZXRlbnRseSBhbmQsIHBlcmhhcHMsc29tZXdoYXQgY3JlYXRpdmVseS4gUGVyaGFwcyBzdHVkZW50IGhhcyBnb25lIGJleW9uZCB3aGF0IHdhcyBleHBlY3RlZCBhbmQgcmVxdWlyZWQsIGUuZy4sIGV4dHJhb3JkaW5hcnkgZWZmb3J0LCBhZGRpdGlvbmFsIHRvb2xzIG5vdCBhZGRyZXNzZWQgYnkgdGhpcyBjb3Vyc2UsIHVudXN1YWxseSBzb3BoaXN0aWNhdGVkIGFwcGxpY2F0aW9uIG9mIHRvb2xzIGZyb20gY291cnNlLiANCjcuNCAuUm1kIGZ1bGx5IGV4ZWN1dGVzIHdpdGhvdXQgYW55IGVycm9ycyBhbmQgSFRNTCBwcm9kdWNlZCBtYXRjaGVzIHRoZSBIVE1MIHJlcG9ydCBzdWJtaXR0ZWQgYnkgc3R1ZGVudC4NCi0tPg0KPGJyIC8+DQo8YnIgLz4NCjxiciAvPg0KDQojI1RleHQgQW5hbHlzaXMNCg0KQSB0ZXh0IGFuYWx5c2lzIG9uIHRoZSBub3RlcyBjb2x1bW4gY2FuIGhlbHAgdXMgdW5kZXJzdGFuZCB3aGljaCB3b3JkcyB3ZXJlIHVzZWQgdGhlIG1vc3QgaW4gdGhlIHRleHQuIA0KDQoNCmBgYHtyIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0UsIGVycm9yPUZBTFNFfQ0Kbm90ZXM8LWRmMSU+JWZpbHRlcihZRUFSPT1jKDIwMTcsMjAxNiwyMDE1LDIwMTQsMjAxMykpJT4lc2VsZWN0KE5PVEVTKQ0KI2hlYWQobm90ZXMpDQpub3Rlc19zb3VyY2U8LVZlY3RvclNvdXJjZShub3RlcykNCm5vdGVzX2NvcnB1czwtVkNvcnB1cyhub3Rlc19zb3VyY2UpDQoNCmNsZWFuX2NvcnB1cyA8LSBmdW5jdGlvbihjb3JwdXMpew0KICBjb3JwdXMgPC0gdG1fbWFwKGNvcnB1cywgc3RyaXBXaGl0ZXNwYWNlKQ0KICBjb3JwdXMgPC0gdG1fbWFwKGNvcnB1cywgcmVtb3ZlUHVuY3R1YXRpb24pDQogIGNvcnB1cyA8LSB0bV9tYXAoY29ycHVzLCBjb250ZW50X3RyYW5zZm9ybWVyKHRvbG93ZXIpKQ0KICBjb3JwdXMgPC0gdG1fbWFwKGNvcnB1cywgcmVtb3ZlTnVtYmVycykNCiAgY29ycHVzIDwtIHRtX21hcChjb3JwdXMsIHJlbW92ZVdvcmRzLCBjKHN0b3B3b3JkcygiZW4iKSwiVG9wMjAwV29yZHMiKSkNCiAgcmV0dXJuKGNvcnB1cykNCn0NCg0Kbm90ZXNfY2xlYW48LWNsZWFuX2NvcnB1cyhub3Rlc19jb3JwdXMpDQpgYGANCg0KYGBge3J9DQpub3Rlc190ZG08LVRlcm1Eb2N1bWVudE1hdHJpeChub3Rlc19jbGVhbikNCm5vdGVzX208LWFzLm1hdHJpeChub3Rlc190ZG0pDQpub3Rlc193b3Jkczwtcm93U3Vtcyhub3Rlc19tKQ0Kbm90ZXNfd29yZHM8LXNvcnQobm90ZXNfd29yZHMsZGVjcmVhc2luZz1UUlVFKQ0KDQpub3Rlc19mcmVxczwtZGF0YS5mcmFtZSh0ZXJtID0gbmFtZXMobm90ZXNfd29yZHMpLG51bSA9IG5vdGVzX3dvcmRzKQ0Kd29yZGNsb3VkKG5vdGVzX2ZyZXFzJHRlcm0sIG5vdGVzX2ZyZXFzJG51bSxtYXgud29yZHMgPSAzMCxjb2xvcnMgPSBjKCJjaGFydHJldXNlIiwgImNvcm5mbG93ZXJibHVlIiwgImRhcmtvcmFuZ2UiKSkNCg0KDQpgYGANCg0KRnJvbSB0aGUgYWJvdmUgd29yZCBjbG91ZCwgaXQgY2FuIGJlIHNlZW4gdGhhdCBtb3N0IHBvcHVsYXIgd29yZHMgaW4gdGhlIG5vdGVzIGNvbHVtbiBhcmUgImtpbGxlZCIsICJwb2xpY2UiLCAiZm9yY2VzIi4NCg0KDQojI1N1bW1hcnkNCjwhLS0NCjYuMSBTdW1tYXJpemUgdGhlIHByb2JsZW0gc3RhdGVtZW50IHlvdSBhZGRyZXNzZWQuIA0KNi4yIFN1bW1hcml6ZSBob3cgeW91IGFkZHJlc3NlZCB0aGlzIHByb2JsZW0gc3RhdGVtZW50ICh0aGUgZGF0YSB1c2VkIGFuZCB0aGUgbWV0aG9kb2xvZ3kgZW1wbG95ZWQpLiANCjYuMyBTdW1tYXJpemUgdGhlIGludGVyZXN0aW5nIGluc2lnaHRzIHRoYXQgeW91ciBhbmFseXNpcyBwcm92aWRlZC4gDQo2LjQgU3VtbWFyaXplIHRoZSBpbXBsaWNhdGlvbnMgdG8gdGhlIGNvbnN1bWVyIG9mIHlvdXIgYW5hbHlzaXMuIA0KNi41IERpc2N1c3MgdGhlIGxpbWl0YXRpb25zIG9mIHlvdXIgYW5hbHlzaXMgYW5kIGhvdyB5b3UsIG9yIHNvbWVvbmUgZWxzZSwgY291bGQgaW1wcm92ZSBvciBidWlsZCBvbiBpdC4NCi0tPg0KDQpXaXRoIGEgaHVnZSBkYXRhc2V0IGxpa2UgdGhpcywgYSBsb3Qgb2YgaW5mb3JtYXRpb24gY2FuIGJlIGV4dHJhY3RlZCB0byBrbm93IGZhY3RzIGFib3V0IGV2ZW50cyBsaWtlIHdoaWNoIGFyZWFzIHdlcmUgYWZmZWN0ZWQgdGhlIG1vc3QsIHdoYXQgaXMgdGhlIGRlZ3JlZSBvZiBkYW1hZ2UgdGhhdCBoYXMgb2NjdXJlZCBkdWUgdG8gY29uZmxpY3RzIGFuZCBtYW55IG90aGVyIHRoaW5ncy4gDQoNCkFsbCB0aGVzZSBpbnNpZ2h0cyBhbmQgbWFueSBvdGhlcnMgY2FuIGJlIGdhdGhlcmVkIHVzaW5nIHZpc3VhbCB0b29scyBsaWtlIHBsb3RzLCBoaXN0b2dyYW1zLCBnZW9zcGF0aWFsIG1hcHMgZXRjLg0KDQpJbiB0aGlzIHJlcG9ydCwgd2Ugd2VyZSBhYmxlIHRvIGdldCBpbnNpZ2h0cyBsaWtlIHRoZSB5ZWFyIDE5OTkgd2FzIHRoZSB3b3JzdCBmb3IgYWxsIHRoZSBjb25mbGljdHMgYXMgdGhpcyB5ZWFyIHdpdG5lc3NlZCB2ZXJ5IGhpZ2ggZmF0YWxpdGllcyBpbiB0aGUgY291bnRyaWVzIG9mIEFuZ29sYSBhbmQgRXJpdHJlYS4NCg0KV2UgYWxzbyBvYnNlcnZlZCB0aGF0IHRoZSBoaWdoZXN0IGNvdW50IG9mIGNvbmZsaWN0cyBoYXBwZW5lZCBpbiAyMDE2IGJ1dCB0aGUgbnVtYmVyIG9mIGZhdGFsaXRpZXMgd2VyZSBsZXNzLiBUaGlzIG1heSBpbmRpY2F0ZSB0aGF0IHBvbGljZSBmb3JjZXMgd2VyZSBhYmxlIHRvIGNvbnRyb2wgdGhlIGNvbmZsaWN0cyBvbiBhbiBlYXJseSBzdGFnZS4NCg0KVGhpcyBraW5kIG9mIGFuYWx5c2lzIGNhbiBsZXQgdGhlIGVuZCB1c2VyIGtub3cgYWJvdXQgdGhlIGN1cnJlbnQgYW5kIGhpc3RvcmljYWwgcG9saXRpY2FsIHNpdHVhdGlvbnMgb2YgYW4gQWZyaWNhbiBjb3VudHJ5LiBUaGUgdXNlciBjYW4gZnVydGhlciBhbmFseXNlIHRvIGZpbmQgd2hpY2ggZ3JvdXBzIHdlcmUgaW52b2x2ZWQgdGhlIG1vc3QgYW5kIGNhbiBwcm92aWRlIGluc2lnaHRmdWwgaW5mb3JtYXRpb24gZm9yIHBvc3NpYmxlIG5leHQgbG9jYXRpb24gb2YgYSBjb25mbGljdCBpbiByZWFsLXRpbWUuDQoNClRoaXMgcHJvamVjdCBjYW4gYmUgZnVydGhlciBkZXZlbG9wZWQgdG8gaW5jbHVkZSBpbnRlcmFjdGl2ZSB2aXN1YWxpemF0aW9uIHdpdGggdGhlIGhlbHAgb2YgU2hpbnkgcGFja2FnZSB3aGljaCBjYW4gbGV0IHRoZSB1c2VyIHRvIGFuYWx5emUgZGF0YSBvZiBkaWZmZXJlbnQgeWVhcnMgb3IgcmVnaW9ucyBpbnRlcmFjdGl2ZWx5Lg0KDQpNb3JlIGFuYWx5c2lzIGNhbiBiZSBkb25lIHRvIGZpbmQgd2hpY2ggcGFydGllcyB3ZXJlIGludm9sdmVkIG1heGltdW0gbnVtYmVyIG9mIHRpbWVzIGluIGNvbmZsaWN0cy4NCg0K