Introduction

There has 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

The packages required for this project are mentioned below:

library(dplyr)
library(xlsx)
library(leaflet)

The functionalities of each package is mentioned below:

dplyr - Used for data manipulation of the data set

xlsx - Used to import/export data from/to xlsx file format

leaflet -Used to make Create Interactive Web Maps

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("african_conflicts.csv", stringsAsFactors = FALSE, na.strings = "")

This dataset contains total 28 columns before making any changes.

names(df)
 [1] "ACTOR1"           "ACTOR1_ID"        "ACTOR2"          
 [4] "ACTOR2_ID"        "ACTOR_DYAD_ID"    "ADMIN1"          
 [7] "ADMIN2"           "ADMIN3"           "ALLY_ACTOR_1"    
[10] "ALLY_ACTOR_2"     "COUNTRY"          "EVENT_DATE"      
[13] "EVENT_ID_CNTY"    "EVENT_ID_NO_CNTY" "EVENT_TYPE"      
[16] "FATALITIES"       "GEO_PRECISION"    "GWNO"            
[19] "INTER1"           "INTER2"           "INTERACTION"     
[22] "LATITUDE"         "LOCATION"         "LONGITUDE"       
[25] "NOTES"            "SOURCE"           "TIME_PRECISION"  
[28] "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 
      FALSE        TRUE       FALSE        TRUE        TRUE 
    COUNTRY  EVENT_DATE  EVENT_TYPE  FATALITIES      INTER1 
      FALSE       FALSE       FALSE       FALSE       FALSE 
     INTER2 INTERACTION    LATITUDE    LOCATION   LONGITUDE 
      FALSE       FALSE       FALSE        TRUE       FALSE 
      NOTES      SOURCE        YEAR 
       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)"             
[2] "Police Forces of Algeria (1999-)"
[3] "NONE"                            
[4] "Police Forces of Algeria (1999-)"
[5] "Police Forces of Algeria (1999-)"
[6] "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

#head(df1$INTERACTION)
df1$INTERACTION<-as.character(df1$INTERACTION)
#head(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"  
[3] "SOLE PROTESTER ACTION"     "MILITARY VERSUS RIOTERS"  
[5] "MILITARY VERSUS RIOTERS"   "MILITARY VERSUS RIOTERS"  


Preview of data after cleaning is given below:

head(df1)

Looking at the summary of data using mmary() function, we see below facts:

summary(df1)
Variable Min Max Mean
Fatalities 0 25000 4.42
Year 1997 2017 -

From above summary of Fatalities, it is observed that minimum afatalities in conflicts 0 and maximum value is 25000 with a mean of 4.42

hist(df1$YEAR, xlab = "YEAR", main = "Histogram of conflicts per year ")

Looking at the histogram above, it is observed that highest number of cnflicts happened in the year 2016. With this information, we can further explore the areas which were affected by this conflict and the time of the year most conflicts happened.

boxplot(df1$FATALITIES~df$YEAR)

Looking at the boxplot above, it can be seen that there are a few outliers inthe dataset with highest being in 1997.


Proposed Exploratory Data Analysis

With this dataset, we can perform EDA using leaflets package to map the critical areas where most conflicts happen. We can further drill down to check details for areas of a country where most conflicts take place. We can see the trends to find the areas where conflicts happen at a particular time of the year. The EVENT_DATE column can be separated to Day, Month and Year to find trends on a monthly or seasonal basis. We can summarize the data to find new metrics like total fatalaties per year, total fatalaties per country, total fatalities per region in a country, frequency of conflicts per country. etc. We can plot bar plots to visialize this data and use boxplot to find out outliers.

We can create summary information as below to get insights about the top metrics.

Below are tables showing top 5 years when the fatalities were the highest 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.

A cluster analysis can be performed on this data to get new insights. Text analysis on NOTES column can be performed to understand the most popular words.




LS0tDQp0aXRsZTogIkFDTEVEIEFmcmljYW4gQ29uZmxpY3RzIg0KYXV0aG9yOiAiQW51cmFnIEphaW4iDQpkYXRlOiAiTWFyY2ggMzEsIDIwMTgiDQpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sNCi0tLQ0KDQpgYGB7ciBzZXR1cCwgaW5jbHVkZT1GQUxTRX0NCmtuaXRyOjpvcHRzX2NodW5rJHNldChlY2hvID0gVFJVRSkNCmBgYA0KDQojIyBJbnRyb2R1Y3Rpb24NCjwhLS0gDQoxLjEgUHJvdmlkZSBhbiBpbnRyb2R1Y3Rpb24gdGhhdCBleHBsYWlucyB0aGUgcHJvYmxlbSBzdGF0ZW1lbnQgeW91IGFyZSBhZGRyZXNzaW5nLiBXaHkgc2hvdWxkIEkgYmUgaW50ZXJlc3RlZCBpbiB0aGlzPyANCjEuMiBQcm92aWRlIGEgc2hvcnQgZXhwbGFuYXRpb24gb2YgaG93IHlvdSBwbGFuIHRvIGFkZHJlc3MgdGhpcyBwcm9ibGVtIHN0YXRlbWVudCAodGhlIGRhdGEgdXNlZCBhbmQgdGhlIG1ldGhvZG9sb2d5IGVtcGxveWVkKSANCjEuMyBEaXNjdXNzIHlvdXIgY3VycmVudCBwcm9wb3NlZCBhcHByb2FjaC9hbmFseXRpYyB0ZWNobmlxdWUgeW91IHRoaW5rIHdpbGwgYWRkcmVzcyAoZnVsbHkgb3IgcGFydGlhbGx5KSB0aGlzIHByb2JsZW0uIA0KMS40IEV4cGxhaW4gaG93IHlvdXIgYW5hbHlzaXMgd2lsbCBoZWxwIHRoZSBjb25zdW1lciBvZiB5b3VyIGFuYWx5c2lzLg0KLS0+DQpUaGVyZSBoYXMgYmVlbiBjb25mbGljdHMgaGFwcGVuaW5nIGFyb3VuZCB0aGUgd29ybGQgd2l0aGluIGdyb3VwcyB3aGljaCBjYW4gcmFuZ2UgZnJvbSBtaWxpdGFudCBhY3Rpdml0eSwgY29uZmxpY3RzIGJldHdlZW4gZ3JvdXBzLCBjb25mbGljdHMgb2YgY2l2aWxpYW5zIHdpdGggZ292ZXJubWVudCBib2RpZXMgZXRjLiBUaGlzIHByb2plY3QgYWltcyBhdCBleHBsb3Jpbmcgc3VjaCBjb25mbGljdHMgaGFwcGVuaW5nIGluIGRpZmZlcmVudCBjb3VudHJpZXMgb2YgQWZyaWNhIGZvciBwYXN0IDIwIHllYXJzIGFuZCBjbHVzdGVpbmcgdG8gZmluZCB0cmVuZHMuDQoNCldpdGggdGhpcyBkYXRhc2V0LCBpdCBpcyBwb3NzaWJsZSB0byBwZXJmb3JtIEV4cGxvcmF0b3J5IGRhdGEgYW5hbHlzaXMgYW5kIGNsdXN0ZXJpbmcgdG8gc2VlIHRoZSB0eXBlIG9mIGNvbmZsaWN0cyBhZmZlY3RpbmcgZGlmZmVyZW50IHJlZ2lvbiBhbmQgYXNzZXNzaW5nIHRoZSBwb2xpdGljYWwgc2l0dWF0aW9uIG9mIGEgcGFydGljdWxhciByZWdpb24uIA0KDQpUaGUgZGF0YSBzZXQgSSBoYXZlIHNlbGVjdGVkIGZvciBteSBwcm9qZWN0IGlzICJBQ0xFRCBBZnJpY2FuIENvbmZsaWN0cyBkYXRhIGZvciBhIGR1cmF0aW9uIG9mIDE5OTctMjAxNyIuIFRoZSBkYXRhc2V0IGlzIG5vdCB0aWR5IGFuZCBuZWVkcyB0byBiZSBjbGVhbmVkIHRvIGJlIHVzZWQgZm9yIGFuYWx5c2lzLiBUaGVyZSBhcmUgbWFueSBjb2x1bW5zIHdoaWNoIGhhdmUgam9pbmVkIGRhdGEgYW5kIG5lZWQgdG8gYmUgc2VwYXJhdGVkIHRvIGRpZmZlcmVudCBjb2x1bW5zLiBUaGVyZSBhcmUgbWFueSBjYXNlcyBvZiBtaXNzaW5nIGFuZCBOQSB2YWx1ZXMgd2hpY2ggbmVlZHMgdG8gYmUgYWRkcmVzc2VkLg0KDQoNCiMjIFBhY2thZ2VzIFJlcXVpcmVkDQo8IS0tDQoyLjEgQWxsIHBhY2thZ2VzIHVzZWQgYXJlIGxvYWRlZCB1cGZyb250IHNvIHRoZSByZWFkZXIga25vd3Mgd2hpY2ggYXJlIHJlcXVpcmVkIHRvIHJlcGxpY2F0ZSB0aGUgYW5hbHlzaXMuIA0KMi4yIE1lc3NhZ2VzIGFuZCB3YXJuaW5ncyByZXN1bHRpbmcgZnJvbSBsb2FkaW5nIHRoZSBwYWNrYWdlIGFyZSBzdXBwcmVzc2VkLiANCjIuMyBFeHBsYW5hdGlvbiBpcyBwcm92aWRlZCByZWdhcmRpbmcgdGhlIHB1cnBvc2Ugb2YgZWFjaCBwYWNrYWdlICh0aGVyZSBhcmUgb3ZlciAxMCwwMDAgcGFja2FnZXMsIGRvbid0IGFzc3VtZSB0aGF0IEkga25vdyB3aHkgeW91IGxvYWRlZCBlYWNoIHBhY2thZ2UpLg0KLS0+DQpUaGUgcGFja2FnZXMgcmVxdWlyZWQgZm9yIHRoaXMgcHJvamVjdCBhcmUgbWVudGlvbmVkIGJlbG93Og0KDQpgYGB7ciBwYWNrYWdlcywgd2FybmluZz1GQUxTRSwgZXJyb3I9RkFMU0UsIG1lc3NhZ2U9RkFMU0V9DQpsaWJyYXJ5KGRwbHlyKQ0KbGlicmFyeSh4bHN4KQ0KbGlicmFyeShsZWFmbGV0KQ0KYGBgDQoNClRoZSBmdW5jdGlvbmFsaXRpZXMgb2YgZWFjaCBwYWNrYWdlIGlzIG1lbnRpb25lZCBiZWxvdzoNCg0KZHBseXIgLSBVc2VkIGZvciBkYXRhIG1hbmlwdWxhdGlvbiBvZiB0aGUgZGF0YSBzZXQgDQoNCnhsc3ggLSBVc2VkIHRvIGltcG9ydC9leHBvcnQgZGF0YSBmcm9tL3RvIHhsc3ggZmlsZSBmb3JtYXQNCg0KbGVhZmxldCAtVXNlZCB0byBtYWtlIENyZWF0ZSBJbnRlcmFjdGl2ZSBXZWIgTWFwcw0KDQojIyBEYXRhIFByZXBhcmF0aW9uDQo8IS0tDQozLjEgT3JpZ2luYWwgc291cmNlIHdoZXJlIHRoZSBkYXRhIHdhcyBvYnRhaW5lZCBpcyBjaXRlZCBhbmQsIGlmIHBvc3NpYmxlLCBoeXBlcmxpbmtlZC4gDQozLjIgU291cmNlIGRhdGEgaXMgdGhvcm91Z2hseSBleHBsYWluZWQgKGkuZS4gd2hhdCB3YXMgdGhlIG9yaWdpbmFsIHB1cnBvc2Ugb2YgdGhlIGRhdGEsIHdoZW4gd2FzIGl0IGNvbGxlY3RlZCwgaG93IG1hbnkgdmFyaWFibGVzIGRpZCB0aGUgb3JpZ2luYWwgaGF2ZSwgZXhwbGFpbiBhbnkgcGVjdWxpYXJpdGllcyBvZiB0aGUgc291cmNlIGRhdGEgc3VjaCBhcyBob3cgbWlzc2luZyB2YWx1ZXMgYXJlIHJlY29yZGVkLCBvciBob3cgZGF0YSB3YXMgaW1wdXRlZCwgZXRjLikuIA0KIA0KLS0+DQoNClRoZSBzb3VyY2Ugb2YgdGhpcyBkYXRhIGlzIGZyb20gW0thZ2dsZSAtIEFDTEVEIEFmcmljYW4gQ29uZmxpY3RzLCAxOTk3LTIwMTddKGh0dHBzOi8vd3d3LmthZ2dsZS5jb20vamJveXNlbi9hZnJpY2FuLWNvbmZsaWN0cykuDQoNClRoaXMgZGF0YSBpcyBvcmlnaW5hbGx5IGNvbGxlY3RlZCB1bmRlciBBQ0xFRCBwcm9qZWN0IHdoaWNoIGlzIGFuIGFjcm9ueW0gZm9yICdBcm1lZCBDb25mbGljdCBMb2NhdGlvbiBhbmQgRXZlbnQgRGF0YScuIFRoaXMgcHJvamVjdCBpcyBkaXJlY3RlZCBieSBQcm9mLiBDbGlvbmFkaCBSYWxlaWdoIChVbml2ZXJzaXR5IG9mIFN1c3NleCkgYW5kIG9wZXJhdGVkIGJ5IFNlbmlvciBSZXNlYXJjaCBNYW5hZ2VyIEFuZHJlYSBDYXJib25pIChVbml2ZXJzaXR5IG9mIFN1c3NleCkgZm9yIEFmcmljYSBhbmQgSGlsbGFyeSBUYW5vZmYgZm9yIFNvdXRoIGFuZCBTb3V0aC1FYXN0IEFzaWEuIFRoZSBhaW0gb2YgdGhpcyBwcm9qZWN0IGlzIHRvIGNvbGxhdGUgZGF0YSBvbiBQb2xpdGljYWwgVmlvbGVuY2UgaW4gZGV2ZWxvcGluZyBjb3VudHJpZXMgd2l0aCBmb2N1cyBvbiBBZnJpY2EuIFRoaXMgZGF0YXNldCB3YXMgZmlyc3QgaW50cm9kdWNlZCBpbiAyMDEwIGJ5IFJhbGVpZ2ggYW5kIGNvLWF1dGhvcnMgaW4gMjAxMCBwYXBlciBpbiB0aGUgW0pvdXJuYWwgb2YgUGVhY2UgUmVzZWFyY2hdKGh0dHBzOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL0pvdXJuYWxfb2ZfUGVhY2VfUmVzZWFyY2gpLiBUaGUgQUNMRUQgZGF0YSBpcyB1c2VkIGJ5IHNldmVyYWwgcmVzZWFyY2hlcnMgaW4gdGhlaXIgcmVzZWFyY2ggb24gY2l2aWwgd2FycyBhbmQgcG9saXRpY2FsIHZpb2xlbmNlLiBUaGlzIGRhdGFzZXQgaGFzIGFsc28gYmVlbiByZWZlcmVuY2VkIGJ5IG5ld3MgbWVkaWEgYWdlbmNpZXMgbGlrZSBUaGUgTmV3IFlvcmsgVGltZXMsIFRoZSBHdWFyZGlhbiwgQkJDIGV0Yy4gdG8gc3R1ZHkgcmVjZW50IGNvbmZsaWN0IHRyZW5kcy4NCg0KQWZ0ZXIgZXhhbWluaW5nIHRoZSBkYXRhLCBpdCB3YXMgb2JzZXJ2ZWQgdGhhdCBtaXNzaW5nIHZhbHVlcyBhcmUgcmVjb3JkZWQgYXMgYCdCbGFua3MnYCBhbmQgd2l0aCBgTkFgIGluIGEgZmV3IGNvbHVtbnMuIFRvIGJyaW5nIGNvbnNpc3RlbmN5LCB3ZSB3aWxsIHJlcGxhY2UgQmxhbmtzIHdpdGggTkEgZHVyaW5nIHJlYWRpbmcgdGhlIGRhdGEuIFRoZSBkYXRlIGZvcm1hdCBpcyBpbiAiREQvTU0vWVlZWSIgZm9ybWF0Lg0KDQo8IS0tDQozLjMgRGF0YSBpbXBvcnRpbmcgYW5kIGNsZWFuaW5nIHN0ZXBzIGFyZSBleHBsYWluZWQgaW4gdGhlIHRleHQgKHRlbGwgbWUgd2h5IHlvdSBhcmUgZG9pbmcgdGhlIGRhdGEgY2xlYW5pbmcgYWN0aXZpdGllcyB0aGF0IHlvdSBwZXJmb3JtKSBhbmQgZm9sbG93IGEgbG9naWNhbCBwcm9jZXNzLg0KLS0+DQpEYXRhIGlzIGltcG9ydGVkIHVzaW5nIHRoZSByZWFkLmNzdigpIGZ1bmN0aW9uLiBJdCB0YWtlcyB0aGUgU3RyaW5nIHZhbHVlcyBhcyBGYWN0b3JzIHNvIHdlIHVzZSB0aGUgYXJndW1lbnQgc3RyaW5nc0FzRmFjdG9ycyA9IEZBTFNFIHRvIGNvbnNpZGVyIGl0IGFzIHN0cmluZ3MuIFdlIGNvbnZlcnQgYmxhbmtzIHRvIE5BIGZvciBtaXNzaW5nIGRhdGEuDQoNCmBgYHtyIHJlYWRjc3YsIGVjaG89VFJVRX0NCmRmIDwtIHJlYWQuY3N2KCJhZnJpY2FuX2NvbmZsaWN0cy5jc3YiLCBzdHJpbmdzQXNGYWN0b3JzID0gRkFMU0UsIG5hLnN0cmluZ3MgPSAiIikNCmBgYA0KDQpUaGlzIGRhdGFzZXQgY29udGFpbnMgdG90YWwgMjggY29sdW1ucyBiZWZvcmUgbWFraW5nIGFueSBjaGFuZ2VzLg0KDQpgYGB7ciBuYW1lcywgZWNobz1UUlVFfQ0KbmFtZXMoZGYpDQpgYGANCg0KT3V0IG9mIHRoZXNlIGNvbHVtbnMsIEFDVE9SMV9JRCwgQUNUT1IyX0lEIGFuZCBBQ1RPUl9EWUFEX0lELCBFVkVOVF9JRF9DTlRZLCBFVkVOVF9JRF9OT19DTlRZIGFyZSBzdXJyb2dhdGUgY29sdW1ucy4gU28gd2Ugd2lsbCByZW1vdmUgdGhlc2UgY29sdW1ucy4gTW9zdCBvZiB0aGUgdmFsdWVzIGluIEFMTFlfQUNUT1JfMSBhbmQgQUxMWV9BQ1RPUl8yIGFyZSBtaXNzaW5nLCBzbyB3ZSByZW1vdmUgdGhlc2UgY29sdW1ucy4gR0VPX1BSRUNJU0lPTiwgR1dOTyBhbmQgVElNRV9QUkVDSVNJT04gYXJlIG5vdCByZXF1aXJlZCBmb3Igb3VyIGFuYWx5c2lzLg0KQWZ0ZXIgcmVtb3ZpbmcgdGhlc2UgY29sdW1ucywgd2UgYXJlIGxlZnQgd2l0aCAxOCBjb2x1bW5zLg0KDQpgYGB7ciByZW1vdmVfY29sdW1ucywgZWNobz1UUlVFfQ0KZGYxIDwtIGRmWy1jKDIsIDQsIDUsIDksIDEwLCAxMywgMTQsIDE3LCAxOCwgMjcpXQ0KYGBgDQoNClRoZSB0YWJsZSBiZWxvdyBnaXZlcyBkZXRhaWxzIGFib3V0IHRoZXNlIGNvbHVtbnM6DQoNCiAgVmFyaWFibGUgICAgfCBEZXNjcmlwdGlvbiB8DQotLS0tLS0tLS0tLS0tLS0tLS0tLS0gfCAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tfA0KQUNUT1IxIHwgTmFtZSBvZiBmaXJzdCBhY3RvcnwNCkFDVE9SMiAgfCBOYW1lIG9mIHNlY29uZCBhY3RvcnwNCkFETUlOMSB8IFRoZSBsYXJnZXN0IHN1Yi1uYXRpb25hbCBhZG1pbmlzdHJhdGl2ZSByZWdpb24gaW4gd2hpY2ggdGhlIGV2ZW50IHRvb2sgcGxhY2V8DQpBRE1JTjIgfCBUaGUgc2Vjb25kLWxhcmdlc3Qgc3ViLW5hdGlvbmFsIGFkbWluaXN0cmF0aXZlIHJlZ2lvbiBpbiB3aGljaCB0aGUgZXZlbnQgdG9vayBwbGFjZXwNCkFETUlOMyB8IFRoZSB0aGlyZC1sYXJnZXN0IHN1Yi1uYXRpb25hbCBhZG1pbmlzdHJhdGl2ZSByZWdpb24gaW4gd2hpY2ggdGhlIGV2ZW50IHRvb2sgcGxhY2V8DQpDT1VOVFJZIHwgQ291bnRyeSBvZiBjb25mbGljdHwNCkVWRU5UX0RBVEUgfCBEYXRlIG9mIGNvbmZsaWN0LCBERC9NTS9ZWVlZfA0KRkFUQUxJVElFUyB8IEludGVnZXIgdmFsdWUgb2YgZmF0YWxpdGllcyB0aGF0IG9jY3VycmVkLCBhcyByZXBvcnRlZCBieSBzb3VyY2V8DQogSU5URVIxIHwgQSBudW1lcmljIGNvZGUgaW5kaWNhdGluZyB0aGUgdHlwZSBvZiBBQ1RPUjF8DQogSU5URVIyIHwgQSBudW1lcmljIGNvZGUgaW5kaWNhdGluZyB0aGUgdHlwZSBvZiBBQ1RPUjJ8DQogSU5URVJBQ1RJT04gfCBBIG51bWVyaWMgY29kZSBpbmRpY2F0aW5nIHRoZSBpbnRlcmFjdGlvbiBiZXR3ZWVuIHR5cGVzIG9mIEFDVE9SMSBhbmQgQUNUT1IyfA0KTEFUSVRVREUgfCBUaGUgbGF0aXR1ZGUgb2YgdGhlIGxvY2F0aW9ufA0KTE9DQVRJT04gfCBUaGUgbG9jYXRpb24gd2hlcmUgZXZlbnQgb2NjdXJyZWR8DQpMT05HSVRVREUgfCBUaGUgbG9uZ2l0dWRlIG9mIHRoZSBsb2NhdGlvbnwNCk5PVEVTIHwgQWRkaXRpb25hbCBub3Rlc3wNClNPVVJDRSB8IFNvdXJjZSBvZiBjb25mbGljdCBpbmZvcm1hdGlvbnwNCllFQVIgICAgICB8ICBZZWFyIGV2ZW50IG9jY3VycmVkfA0KDQpgYGB7ciBzdHIsIGV2YWw9RkFMU0UsIGVjaG89RkFMU0V9DQpzdHIoZGYxKQ0KYGBgDQoNCg0KDQoNCjwhLS0NClJlbW92aW5nIGJsYW5rIGNlbGxzDQotLT4NCg0KTG9va2luZyBhdCBjb2x1bW5zIEFDVE9SMiwgQURNSU4yLCBBRE1JTjMsIExPQ0FUSU9OLCBOT1RFUywgU09VUkNFIHdlIHNlZSB0aGF0IHRoZXkgaGF2ZSBzb21lIG1pc3NpbmcgZGF0YS4NCmBgYHtyIE1pc3NfY2hlY2ssIGVjaG89VFJVRX0NCmFwcGx5KGRmMSwgMiwgZnVuY3Rpb24oeCkgYW55KGlzLm5hKHgpKSkNCmBgYA0KRm9yIENvbHVtbiBBQ1RPUjIsIE5BIHRlbGxzIHVzIHRoYXQgdGhlcmUgd2FzIG5vIHNlY29uZCBhY3Rvci4gU28gd2UgY2FuIHJlcGxhY2UgaXQgd2l0aCBzdHJpbmcgIk5PTkUiDQoNCmBgYHtyIGJsYW5rcywgZWNobz1UUlVFfQ0KZGYxJEFDVE9SMltpcy5uYShkZjEkQUNUT1IyKV0gPC0gIk5PTkUiDQpoZWFkKGRmMSRBQ1RPUjIpDQpgYGANCk5vdyBmb3IgY29sdW1ucywgSU5URVIxLCBJTlRFUjIgYW5kIElOVEVSQUNUSU9OIG51bWVyaWNhbCBzdWJzaXR1dGVzIGZvciBjYXRlZ29yaWVzIGFyZSBwcm92aWRlZC4gV2Ugd2lsbCByZXBsYWNlIHRoZXNlIHdpdGggdGhlIGFjdHVhbCB2YWx1ZXMgZnJvbSB0aGUgY29kZWJvb2suDQoNClByZXZpZXcgb2YgQ29sdW1uIElOVEVSMQ0KYGBge3IgcmVwbGFjZV9jYXRlZ29yaWNhbCwgZWNobz1UUlVFfQ0KDQpkZjEkSU5URVIxIDwtIGFzLmNoYXJhY3RlcihkZjEkSU5URVIxKQ0KbHV0MSA8LSBjKCIxIiA9ICJHb3Zlcm5tZW50IG9yIG11dGlub3VzIGZvcmNlIiwgIjIiID0gIlJlYmVsIGZvcmNlIiwgIjMiID0gIlBvbGl0aWNhbCBtaWxpdGlhIiwgIjQiID0gIkV0aG5pYyBtaWxpdGlhIiwgIjUiID0gIlJpb3RlcnMiLCAiNiIgPSAiUHJvdGVzdGVycyIsICI3IiA9ICJDaXZpbGlhbnMiLCAiOCIgPSAiT3V0c2lkZS9leHRlcm5hbCBmb3JjZSIpDQpkZjEkSU5URVIxIDwtIGx1dDFbZGYxJElOVEVSMV0NCmhlYWQoZGYxJElOVEVSMSkNCmBgYA0KDQpQcmV2aWV3IG9mIENvbHVtbiBJTlRFUjINCg0KYGBge3IgcmVwbGFjZV9jYXRlZ29yaWNhbF8xLCBlY2hvPVRSVUV9DQpkZjEkSU5URVIyIDwtIGFzLmNoYXJhY3RlcihkZjEkSU5URVIyKQ0KbHV0MiA8LSBjKCIwIiA9ICJOT05FIiwgIjEiID0gIkdvdmVybm1lbnQgb3IgbXV0aW5vdXMgZm9yY2UiLCAiMiIgPSAiUmViZWwgZm9yY2UiLCAiMyIgPSAiUG9saXRpY2FsIG1pbGl0aWEiLCAiNCIgPSAiRXRobmljIG1pbGl0aWEiLCAiNSIgPSAiUmlvdGVycyIsICI2IiA9ICJQcm90ZXN0ZXJzIiwgIjciID0gIkNpdmlsaWFucyIsICI4IiA9ICJPdXRzaWRlL2V4dGVybmFsIGZvcmNlIikNCmRmMSRJTlRFUjIgPC0gbHV0MltkZjEkSU5URVIyXQ0KaGVhZChkZjEkSU5URVIyKQ0KYGBgDQoNCg0KUHJldmlldyBvZiBDb2x1bW4gSU5URVJBQ1RJT04NCg0KYGBge3IgcmVwbGFjZV9jYXRlZ29yaWNhbF8yLCBlY2hvPVRSVUV9DQojaGVhZChkZjEkSU5URVJBQ1RJT04pDQpkZjEkSU5URVJBQ1RJT048LWFzLmNoYXJhY3RlcihkZjEkSU5URVJBQ1RJT04pDQojaGVhZChkZjEkSU5URVJBQ1RJT04pDQpsdXQzPC1jKCIxMCIgPSAiU09MRSBNSUxJVEFSWSBBQ1RJT04iLCAiMTEiID0gIk1JTElUQVJZIFZFUlNVUyBNSUxJVEFSWSIsICIxMiIgPSAiTUlMSVRBUlkgVkVSU1VTIFJFQkVMUyIsICIxMyIgPSAiTUlMSVRBUlkgVkVSU1VTIFBPTElUSUNBTCBNSUxJVElBIiwgIjE0IiA9ICJNSUxJVEFSWSBWRVJTVVMgQ09NTVVOQUwgTUlMSVRJQSIsICIxNSIgPSAiTUlMSVRBUlkgVkVSU1VTIFJJT1RFUlMiLCAiMTYiID0gIk1JTElUQVJZIFZFUlNVUyBQUk9URVNURVJTIiwgIjE3IiA9ICJNSUxJVEFSWSBWRVJTVVMgQ0lWSUxJQU5TIiwgIjE4IiA9ICJNSUxJVEFSWSBWRVJTVVMgT1RIRVIiLCAiMjAiID0gIlNPTEUgUkVCRUwgQUNUSU9OICIsICIyMiIgPSAiUkVCRUxTIFZFUlNVUyBSRUJFTFMiLCAiMjMiID0gIlJFQkVMUyBWRVJTVVMgUE9MSVRJQ0FMIE1JTElJVEEiLCAiMjQiID0gIlJFQkVMUyBWRVJTVVMgQ09NTVVOQUwgTUlMSVRJQSIsICIyNSIgPSAiUkVCRUxTIFZFUlNVUyBSSU9URVJTIiwgIjI2IiA9ICJSRUJFTFMgVkVSU1VTIFBST1RFU1RFUlMiLCAiMjciID0gIlJFQkVMUyBWRVJTVVMgQ0lWSUxJQU5TIiwgIjI4IiA9ICJSRUJFTFMgVkVSU1VTIE9USEVSUyIsICIzMCIgPSAiU09MRSBQT0xJVElDQUwgTUlMSVRJQSBBQ1RJT04iLCIzMyIgPSAiUE9MSVRJQ0FMIE1JTElUSUEgVkVSU1VTIFBPTElUSUNBTCBNSUxJVElBIiwgIjM0IiA9ICJQT0xJVElDQUwgTUlMSVRJQSBWRVJTVVMgQ09NTVVOQUwgTUlMSVRJQSIsICIzNSIgPSAiUE9MSVRJQ0FMIE1JTElUSUEgVkVSU1VTIFJJT1RFUlMiLCAiMzYiID0gIlBPTElUSUNBTCBNSUxJVElBIFZFUlNVUyBQUk9URVNURVJTIiwgIjM3IiA9ICJQT0xJVElDQUwgTUlMSVRJQSBWRVJTVVMgQ0lWSUxJQU5TIiwgIjM4IiA9ICJQT0xJVElDQUwgTUlMSVRJQSBWRVJTVVMgT1RIRVJTIiwgIjQwIiA9ICJTT0xFIENPTU1VTkFMIE1JTElUSUEgQUNUSU9OIiwgIjQ0IiA9ICJDT01NVU5BTCBNSUxJVElBIFZFUlNVUyBDT01NVU5BTCBNSUxJVElBIiwgIjQ1IiA9ICJDT01NVU5BTCBNSUxJVElBIFZFUlNVUyBSSU9URVJTIiwgIjQ2IiA9ICJDT01NVU5BTCBNSUxJVElBIFZFUlNVUyBQUk9URVNURVJTIiwgIjQ3IiA9ICJDT01NVU5BTCBNSUxJVElBIFZFUlNVUyBDSVZJTElBTlMiLCAiNDgiID0gIkNPTU1VTkFMIE1JTElUSUEgVkVSU1VTIE9USEVSIiwiNTAiID0gIlNPTEUgUklPVEVSIEFDVElPTiIsICI1NSIgPSAiUklPVEVSUyBWRVJTVVMgUklPVEVSUyIsICI1NiIgPSAiUklPVEVSUyBWRVJTVVMgUFJPVEVTVEVSUyIsICI1NyIgPSAiUklPVEVSUyBWRVJTVVMgQ0lWSUxJQU5TIiwgIjU4IiA9ICJSSU9URVJTIFZFUlNVUyBPVEhFUlMiLCAiNjAiID0gIlNPTEUgUFJPVEVTVEVSIEFDVElPTiIsICI2NiIgPSAiUFJPVEVTVEVSUyBWRVJTVVMgUFJPVEVTVEVSUyIsICI2NyIgPSAiUFJPVEVTVEVSUyBWRVJTVVMgQ0lWSUxJQU5TIiwgIjY4IiA9ICJQUk9URVNURVJTIFZFUlNVUyBPVEhFUiIsICI3MCIgPSAiU09MRSBDSVZJTElBTlMiLCAiNzciID0gIkNJVklMSUFOUyBWRVJTVVMgQ0lWSUxJQU5TIiwgIjc4IiA9ICJPVEhFUiBBQ1RPUiBWRVJTVVMgQ0lWSUxJQU5TIiwgIjgwIiA9ICJTT0xFIE9USEVSIEFDVElPTiIsICI4OCIgPSAiT1RIRVJTIFZFUlNVUyBPVEhFUlMiKQ0KZGYxJElOVEVSQUNUSU9OIDwtIGx1dDNbZGYxJElOVEVSQUNUSU9OXQ0KaGVhZChkZjEkSU5URVJBQ1RJT04pDQpgYGANCg0KPGJyIC8+DQoNCjwhLS0NCjMuNCBPbmNlIHlvdXIgZGF0YSBpcyBjbGVhbiwgc2hvdyB3aGF0IHRoZSBmaW5hbCBkYXRhIHNldCBsb29rcyBsaWtlLiBIb3dldmVyLCBkbyBub3QgcHJpbnQgb2ZmIGEgZGF0YSBmcmFtZSB3aXRoIDIwMCsgcm93czsgc2hvdyBtZSB0aGUgZGF0YSBpbiB0aGUgbW9zdCBjb25kZW5zZWQgZm9ybSBwb3NzaWJsZS4gDQozLjUgUHJvdmlkZSBzdW1tYXJ5IGluZm9ybWF0aW9uIGFib3V0IHRoZSB2YXJpYWJsZXMgb2YgY29uY2VybiBpbiB5b3VyIGNsZWFuZWQgZGF0YSBzZXQuIERvIG5vdCBqdXN0IHByaW50IG9mZiBhIGJ1bmNoIG9mIGNvZGUgY2h1bmtzIHdpdGggc3RyKCksIHN1bW1hcnkoKSwgZXRjLiBSYXRoZXIsIHByb3ZpZGUgbWUgd2l0aCBhIGNvbnNvbGlkYXRlZCBleHBsYW5hdGlvbiwgZWl0aGVyIHdpdGggYSB0YWJsZSB0aGF0IHByb3ZpZGVzIHN1bW1hcnkgaW5mbyBmb3IgZWFjaCB2YXJpYWJsZSBvciBhIG5pY2VseSB3cml0dGVuIHN1bW1hcnkgcGFyYWdyYXBoIHdpdGggaW5saW5lIGNvZGUuDQoNCi0tPg0KDQpQcmV2aWV3IG9mIGRhdGEgYWZ0ZXIgY2xlYW5pbmcgaXMgZ2l2ZW4gYmVsb3c6DQoNCg0KYGBge3IgY2xlYW5fZGF0YSwgZWNobz1UUlVFfQ0KDQpoZWFkKGRmMSkNCmBgYA0KDQpMb29raW5nIGF0IHRoZSBzdW1tYXJ5IG9mIGRhdGEgdXNpbmcgbW1hcnkoKSBmdW5jdGlvbiwgd2Ugc2VlIGJlbG93IGZhY3RzOg0KDQpgYGB7ciBzdW1tYXJ5LCBlY2hvPVRSVUUsIGV2YWw9RkFMU0V9DQoNCnN1bW1hcnkoZGYxKQ0KYGBgDQoNCg0KICBWYXJpYWJsZSAgICB8IE1pbiAgICAgICAgICAgfE1heCAgICAgICAgICB8TWVhbiAgICAgfA0KLS0tLS0tLS0tLS0tLSB8IC0tLS0tLS0tLS0tLS0gfC0tLS0tLS0tLS0tLS18LS0tLS0tLS0tfA0KRmF0YWxpdGllcyAgICB8IDAgICAgICAgIHwgIDI1MDAwICAgICAgICAgICB8ICAgIDQuNDIgICAgIHwNClllYXIgICAgICAgIHwgMTk5NyAgICAgICAgfCAgIDIwMTcgICAgICAgICAgfCAgICAgLSAgICB8DQoNCkZyb20gYWJvdmUgc3VtbWFyeSBvZiBGYXRhbGl0aWVzLCBpdCBpcyBvYnNlcnZlZCB0aGF0IG1pbmltdW0gYWZhdGFsaXRpZXMgaW4gY29uZmxpY3RzIDAgYW5kIG1heGltdW0gdmFsdWUgaXMgMjUwMDAgd2l0aCBhIG1lYW4gb2YgNC40Mg0KDQoNCmBgYHtyIGhpc3QsIGVjaG89VFJVRX0NCmhpc3QoZGYxJFlFQVIsIHhsYWIgPSAiWUVBUiIsIG1haW4gPSAiSGlzdG9ncmFtIG9mIGNvbmZsaWN0cyBwZXIgeWVhciAiKQ0KYGBgDQpMb29raW5nIGF0IHRoZSBoaXN0b2dyYW0gYWJvdmUsIGl0IGlzIG9ic2VydmVkIHRoYXQgaGlnaGVzdCBudW1iZXIgb2YgY25mbGljdHMgaGFwcGVuZWQgaW4gdGhlIHllYXIgMjAxNi4gV2l0aCB0aGlzIGluZm9ybWF0aW9uLCB3ZSBjYW4gZnVydGhlciBleHBsb3JlIHRoZSBhcmVhcyB3aGljaCB3ZXJlIGFmZmVjdGVkIGJ5IHRoaXMgY29uZmxpY3QgYW5kIHRoZSB0aW1lIG9mIHRoZSB5ZWFyIG1vc3QgY29uZmxpY3RzIGhhcHBlbmVkLg0KDQpgYGB7ciBoaXN0XzEsIGVjaG89VFJVRX0NCmJveHBsb3QoZGYxJEZBVEFMSVRJRVN+ZGYkWUVBUikNCmBgYA0KDQpMb29raW5nIGF0IHRoZSBib3hwbG90IGFib3ZlLCBpdCBjYW4gYmUgc2VlbiB0aGF0IHRoZXJlIGFyZSBhIGZldyBvdXRsaWVycyBpbnRoZSBkYXRhc2V0IHdpdGggaGlnaGVzdCBiZWluZyBpbiAxOTk3Lg0KDQo8YnIgLz4NCg0KIyMgUHJvcG9zZWQgRXhwbG9yYXRvcnkgRGF0YSBBbmFseXNpcw0KPCEtLQ0KNC4xIERpc2N1c3MgaG93IHlvdSBwbGFuIHRvIHVuY292ZXIgbmV3IGluZm9ybWF0aW9uIGluIHRoZSBkYXRhIHRoYXQgaXMgbm90IHNlbGYtZXZpZGVudC4gV2hhdCBhcmUgZGlmZmVyZW50IHdheXMgeW91IGNvdWxkIGxvb2sgYXQgdGhpcyBkYXRhIHRvIGFuc3dlciB0aGUgcXVlc3Rpb25zIHlvdSB3YW50IHRvIGFuc3dlcj8gRG8geW91IHBsYW4gdG8gc2xpY2UgYW5kIGRpY2UgdGhlIGRhdGEgaW4gZGlmZmVyZW50IHdheXMsIGNyZWF0ZSBuZXcgdmFyaWFibGVzLCBvciBqb2luIHNlcGFyYXRlIGRhdGEgZnJhbWVzIHRvIGNyZWF0ZSBuZXcgc3VtbWFyeSBpbmZvcm1hdGlvbj8gSG93IGNvdWxkIHlvdSBzdW1tYXJpemUgeW91ciBkYXRhIHRvIGFuc3dlciBrZXkgcXVlc3Rpb25zPyANCjQuMiBXaGF0IHR5cGVzIG9mIHBsb3RzIGFuZCB0YWJsZXMgd2lsbCBoZWxwIHlvdSB0byBpbGx1c3RyYXRlIHRoZSBmaW5kaW5ncyB0byB5b3VyIHF1ZXN0aW9ucz8gDQo0LjMgV2hhdCBkbyB5b3Ugbm90IGtub3cgaG93IHRvIGRvIHJpZ2h0IG5vdyB0aGF0IHlvdSBuZWVkIHRvIGxlYXJuIHRvIGFuc3dlciB5b3VyIHF1ZXN0aW9ucz8gDQo0LjQgRG8geW91IHBsYW4gb24gaW5jb3Jwb3JhdGluZyBhbnkgbWFjaGluZSBsZWFybmluZyB0ZWNobmlxdWVzIChpLmUuIGxpbmVhciByZWdyZXNzaW9uLCBkaXNjcmltaW5hbnQgYW5hbHlzaXMsIGNsdXN0ZXIgYW5hbHlzaXMpIHRvIGFuc3dlciB5b3VyIHF1ZXN0aW9ucz8gDQotLT4NCg0KV2l0aCB0aGlzIGRhdGFzZXQsIHdlIGNhbiBwZXJmb3JtIEVEQSB1c2luZyBsZWFmbGV0cyBwYWNrYWdlIHRvIG1hcCB0aGUgY3JpdGljYWwgYXJlYXMgd2hlcmUgbW9zdCBjb25mbGljdHMgaGFwcGVuLiBXZSBjYW4gZnVydGhlciBkcmlsbCBkb3duIHRvIGNoZWNrIGRldGFpbHMgZm9yIGFyZWFzIG9mIGEgY291bnRyeSB3aGVyZSBtb3N0IGNvbmZsaWN0cyB0YWtlIHBsYWNlLiANCldlIGNhbiBzZWUgdGhlIHRyZW5kcyB0byBmaW5kIHRoZSBhcmVhcyB3aGVyZSBjb25mbGljdHMgaGFwcGVuIGF0IGEgcGFydGljdWxhciB0aW1lIG9mIHRoZSB5ZWFyLiBUaGUgRVZFTlRfREFURSBjb2x1bW4gY2FuIGJlIHNlcGFyYXRlZCB0byBEYXksIE1vbnRoIGFuZCBZZWFyIHRvIGZpbmQgdHJlbmRzIG9uIGEgbW9udGhseSBvciBzZWFzb25hbCBiYXNpcy4gV2UgY2FuIHN1bW1hcml6ZSB0aGUgZGF0YSB0byBmaW5kIG5ldyBtZXRyaWNzIGxpa2UgdG90YWwgZmF0YWxhdGllcyBwZXIgeWVhciwgdG90YWwgZmF0YWxhdGllcyBwZXIgY291bnRyeSwgdG90YWwgZmF0YWxpdGllcyBwZXIgcmVnaW9uIGluIGEgY291bnRyeSwgZnJlcXVlbmN5IG9mIGNvbmZsaWN0cyBwZXIgY291bnRyeS4gZXRjLiBXZSBjYW4gcGxvdCBiYXIgcGxvdHMgdG8gdmlzaWFsaXplIHRoaXMgZGF0YSBhbmQgdXNlIGJveHBsb3QgdG8gZmluZCBvdXQgb3V0bGllcnMuIA0KDQoNCldlIGNhbiBjcmVhdGUgc3VtbWFyeSBpbmZvcm1hdGlvbiBhcyBiZWxvdyB0byBnZXQgaW5zaWdodHMgYWJvdXQgdGhlIHRvcCBtZXRyaWNzLiANCg0KQmVsb3cgYXJlIHRhYmxlcyBzaG93aW5nIHRvcCA1IHllYXJzIHdoZW4gdGhlIGZhdGFsaXRpZXMgd2VyZSB0aGUgaGlnaGVzdCBhbmQgdG9wIDEwIGNvdW50cmllcyB3aXRoIGhpZ2hlc3QgZmF0YWxpdGllcy4NCg0KDQpgYGB7ciBzdW0zfQ0KZGYxJT4lZ3JvdXBfYnkoWUVBUiklPiVzdW1tYXJpc2Uoc3VtKEZBVEFMSVRJRVMpKSU+JWFycmFuZ2UoZGVzYyhgc3VtKEZBVEFMSVRJRVMpYCkpJT4laGVhZChuPTUpDQoNCmBgYA0KDQpGcm9tIHRoZSB0YWJsZSBhYm92ZSwgd2UgY2FuIHNlZSB0aGF0IHllYXIgMTk5OSBoYWQgdGhlIGhpZ2hlc3QgZmF0YWxpdGllcyBkdWUgdG8gY29uZmxpY3RzLg0KDQpgYGB7ciBzdW00LCBlY2hvPVRSVUV9DQoNCmRmMSU+JWdyb3VwX2J5KENPVU5UUlkpJT4lc3VtbWFyaXNlKHN1bShGQVRBTElUSUVTKSklPiVhcnJhbmdlKGRlc2MoYHN1bShGQVRBTElUSUVTKWApKSU+JWhlYWQobj0xMCkNCmBgYA0KSGVyZSwgd2UgY2FuIHNlZSB0aGF0IEFuZ29sYSBoYXMgdGhlIGhpZ2hlc3QgZmF0YWxpdGllcyBkdWUgdG8gY29uZmxpY3RzLg0KDQo8IS0tDQoNCiMjIEZvcm1hdHRpbmcgJiBPdGhlciBSZXF1aXJlbWVudHMNCg0KNy4xIEFsbCBjb2RlIGlzIHZpc2libGUsIHByb3BlciBjb2Rpbmcgc3R5bGUgaXMgZm9sbG93ZWQsIGFuZCBjb2RlIGlzIHdlbGwgY29tbWVudGVkIChzZWUgc2VjdGlvbiByZWdhcmRpbmcgc3lsZSkuIA0KNy4yIENvZGluZyBpcyBzeXN0ZW1hdGljIC0gY29tcGxpY2F0ZWQgcHJvYmxlbSBicm9rZW4gZG93biBpbnRvIHN1Yi1wcm9ibGVtcyB0aGF0IGFyZSBpbmRpdmlkdWFsbHkgbXVjaCBzaW1wbGVyLiBDb2RlIGlzIGVmZmljaWVudCwgY29ycmVjdCwgYW5kIG1pbmltYWwuIENvZGUgdXNlcyBhcHByb3ByaWF0ZSBkYXRhIHN0cnVjdHVyZSAobGlzdCwgZGF0YSBmcmFtZSwgdmVjdG9yL21hdHJpeC9hcnJheSkuIENvZGUgY2hlY2tzIGZvciBjb21tb24gZXJyb3JzLiANCjcuMyBBY2hpZXZlbWVudCwgbWFzdGVyeSwgY2xldmVybmVzcywgY3JlYXRpdml0eTogVG9vbHMgYW5kIHRlY2huaXF1ZXMgZnJvbSB0aGUgY291cnNlIGFyZSBhcHBsaWVkIHZlcnkgY29tcGV0ZW50bHkgYW5kLCBwZXJoYXBzLHNvbWV3aGF0IGNyZWF0aXZlbHkuIFBlcmhhcHMgc3R1ZGVudCBoYXMgZ29uZSBiZXlvbmQgd2hhdCB3YXMgZXhwZWN0ZWQgYW5kIHJlcXVpcmVkLCBlLmcuLCBleHRyYW9yZGluYXJ5IGVmZm9ydCwgYWRkaXRpb25hbCB0b29scyBub3QgYWRkcmVzc2VkIGJ5IHRoaXMgY291cnNlLCB1bnVzdWFsbHkgc29waGlzdGljYXRlZCBhcHBsaWNhdGlvbiBvZiB0b29scyBmcm9tIGNvdXJzZS4gDQo3LjQgLlJtZCBmdWxseSBleGVjdXRlcyB3aXRob3V0IGFueSBlcnJvcnMgYW5kIEhUTUwgcHJvZHVjZWQgbWF0Y2hlcyB0aGUgSFRNTCByZXBvcnQgc3VibWl0dGVkIGJ5IHN0dWRlbnQuDQotLT4NCg0KQSBjbHVzdGVyIGFuYWx5c2lzIGNhbiBiZSBwZXJmb3JtZWQgb24gdGhpcyBkYXRhIHRvIGdldCBuZXcgaW5zaWdodHMuIFRleHQgYW5hbHlzaXMgb24gTk9URVMgY29sdW1uIGNhbiBiZSBwZXJmb3JtZWQgdG8gdW5kZXJzdGFuZCB0aGUgbW9zdCBwb3B1bGFyIHdvcmRzLg0KDQo8YnIgLz4NCjxiciAvPg0KPGJyIC8+DQoNCg0K