Introduction

Nuclear weapons exist. Some countries have them. Lots of countries wish they had them.

For this project we shall take a took at the proliferation of nuclear weapons since their creation at the end of the Second World War and their usage after the war up to the modern era.

How many countries have attempted to obtain nuclear weapons and of those how many have failed?

Are trends in weapon testing more easily linked to global effects or regional ones?

By using geographical and historical context we will attempt to visualize patterns of the nuclear arms race.

Libraries

  • ggplot2 for plotting

  • rgeos and rworldmap for geographical cooridanates

  • tibble for some easy data frame reshaping

  • dplyr for easy data manipulation


library(ggplot2)

library(rgeos)

library(rworldmap)

library(tibble)

library(dplyr)

Data

This dataset of Nuclear Weapons was obtained from Kaggle in the form of four files.

  1. Nuclear Weapons Proliferation (Country)
  2. Nuclear Weapons Proliferation (Global)
  3. Nuclear Weapons Stockpiles (Country)
  4. Nuclear Weapons Tests States (Country)

https://www.kaggle.com/datasets/michaelbryantds/nuclear-weapons-dataset

Preparation

We load in the four csv files as data frames.

dataPath <- "nuclear_weapons/"
dataList <- list.files(path = dataPath)
print(dataList)
[1] "nuclear_weapons_proliferation_owid.csv"       "nuclear_weapons_proliferation_total_owid.csv"
[3] "nuclear_weapons_stockpiles.csv"               "nuclear_weapons_tests_states.csv"            

Assign data frame for each data file.

for(i in 1:length(dataList)) {
  fileName <- substr(dataList[[i]],1,nchar(dataList[[i]])-4)
  csv_path <- paste0(dataPath,dataList[[i]])
  assign(paste0("data_", fileName), read.csv(csv_path))
}
rm(list = c("csv_path","fileName","i"))
dfList <- c()
for(i in 1:length(dataList)) {
  dataset <- paste0("data_",as.character(dataList[i]))
  dataset <- substr(dataset, 1, nchar(dataset)-4)
  dfList[i] <- dataset
}

Quick look at the data.

for(i in 1:length(dfList)) {
  print(c(dfList[i], str(get(dfList[i]))))
}
'data.frame':   16848 obs. of  6 variables:
 $ country_name                 : chr  "Abkhazia" "Abkhazia" "Abkhazia" "Abkhazia" ...
 $ year                         : int  1938 1939 1940 1941 1942 1943 1944 1945 1946 1947 ...
 $ nuclear_weapons_status       : int  0 0 0 0 0 0 0 0 0 0 ...
 $ nuclear_weapons_consideration: int  0 0 0 0 0 0 0 0 0 0 ...
 $ nuclear_weapons_pursuit      : int  0 0 0 0 0 0 0 0 0 0 ...
 $ nuclear_weapons_possession   : int  0 0 0 0 0 0 0 0 0 0 ...
[1] "data_nuclear_weapons_proliferation_owid"
'data.frame':   85 obs. of  5 variables:
 $ entity_name                  : chr  "World" "World" "World" "World" ...
 $ year                         : int  1938 1939 1940 1941 1942 1943 1944 1945 1946 1947 ...
 $ number_nuclweap_consideration: int  0 2 3 3 3 2 2 5 3 4 ...
 $ number_nuclweap_pursuit      : int  0 0 0 1 2 3 3 2 2 2 ...
 $ number_nuclweap_possession   : int  0 0 0 0 0 0 0 1 1 1 ...
[1] "data_nuclear_weapons_proliferation_total_owid"
'data.frame':   780 obs. of  3 variables:
 $ country_name             : chr  "China" "China" "China" "China" ...
 $ year                     : int  1945 1946 1947 1948 1949 1950 1951 1952 1953 1954 ...
 $ nuclear_weapons_stockpile: int  0 0 0 0 0 0 0 0 0 0 ...
[1] "data_nuclear_weapons_stockpiles"
'data.frame':   600 obs. of  3 variables:
 $ country_name         : chr  "China" "China" "China" "China" ...
 $ year                 : int  1945 1946 1947 1948 1949 1950 1951 1952 1953 1954 ...
 $ nuclear_weapons_tests: int  0 0 0 0 0 0 0 0 0 0 ...
[1] "data_nuclear_weapons_tests_states"

Convert “country_name” columns from character to factor.

data_nuclear_weapons_proliferation_owid$country_name <-
  factor(data_nuclear_weapons_proliferation_owid$country_name)

data_nuclear_weapons_stockpiles$country_name <-
  factor(data_nuclear_weapons_stockpiles$country_name)

data_nuclear_weapons_tests_states$country_name <-
  factor(data_nuclear_weapons_tests_states$country_name)

Exploration

Global Possession and Pursuit of Nuclear Arms

We can easily plot the countries in pursuit of and in possession of nuclear arms together.

fills <- c("Possession" = "steelblue", "Pursuit" = "goldenrod2")
ggplot(data_nuclear_weapons_proliferation_total_owid, aes(x=year)) +
  geom_col(aes(y = number_nuclweap_possession, fill = "Possession"),
           color="steelblue4") +
  geom_col(aes(y = number_nuclweap_pursuit, fill="Pursuit"),
           color="sienna",
           alpha=0.8) +
  scale_fill_manual(values=fills, name="Status") +
  scale_y_continuous(breaks=c(0:9)) +
  scale_x_continuous(breaks = seq(1941,2022,9)) +
  theme(
    panel.grid.minor.y = element_blank(),
    panel.grid.major = element_line(color="grey80"),
    panel.background = element_rect(fill="white", color ="black"),
    plot.background = element_rect(fill="white", color="white")) +
  xlab("Year") + ylab("Number of Countries") +
  ggtitle("Global Nuclear Weapon States")

We can see that possession of nuclear weapons has gradually increased over time resulting in 9 countries possessing nuclear arms in the modern era.

When a country in pursuit succeeds in their goals, they are removed from the “pursuit pool” and added to the pool of those in possession of nuclear arms. Not all countries who have actively pursued these weapons have succeeded however.

considered <- data_nuclear_weapons_proliferation_owid[
  data_nuclear_weapons_proliferation_owid$nuclear_weapons_status > 0,]

considered$country_name <-
  factor(considered$country_name)

ggplot(considered,
       aes(x=year,
           y=country_name,
           fill=factor(nuclear_weapons_status))) +
  geom_tile(aes(height=0.85)) +
  xlab("Year") + ylab("Country") +
  scale_fill_manual(values = c("springgreen4","orange1","steelblue3"),
                    name="Status",
                    labels=c("Consideration","Pursuit","Possession")) +
  scale_x_continuous(breaks=seq(1938,2022,12)) +
  geom_vline(
    xintercept=considered[max(considered$nuclear_weapons_status),]$year) +
  ggtitle(label = "Global Consideration of Nuclear Weapons") +
  theme_bw()

Here we see a more detailed view of all countries that have publicly considered attempting to obtain nuclear weapons.

1985 was the year that had the most countries labeled as either considering, pursuing, or in possession of nuclear weapons.

As of today, Iran remains the only country still actively pursuing nuclear weaponry.

Global Stockpiles of Nuclear Weapons

When did each country have their record stockpile size?

max_stockpile <- data_nuclear_weapons_stockpiles %>% 
  group_by(country_name) %>% slice(which.max(nuclear_weapons_stockpile))

ggplot(max_stockpile,
       aes(x=reorder(country_name, nuclear_weapons_stockpile),
           y=nuclear_weapons_stockpile,
           fill = nuclear_weapons_stockpile)) + 
  geom_bar(stat="identity", color="black") +
  geom_text(aes(label=year, y = min(nuclear_weapons_stockpile)),
            vjust=7, size=3) +
  scale_y_log10(breaks=10^(0:5),
                expand=c(0,0.5), 
                labels=c("0","10","100","1,000","10,000","100,000")) +
  scale_fill_distiller(palette="RdBu",
                       name="Stockpiled Weapons") + 
  ylab(label="Number of Nuclear Weapons") +
  ggtitle(label="Maximum Nuclear Weapon Stockpile Size") +
  theme(
    axis.text.x = element_text(angle=30, hjust =0.8, vjust=0.8, size=10),
    axis.title.x = element_blank(),
    panel.grid.major.x = element_blank(),
    panel.grid.major.y = element_line(color="grey80"),
    panel.background = element_rect(fill="white", color="black"),
    legend.title = element_text(vjust=3))

Clearly Russia and the United States are far beyond the rest of the pack in regards to the size of their nuclear weapons stockpile.

Lots of weapons back 70’s and 80’s. What happened?

total_stockpile <- data_nuclear_weapons_stockpiles[
  data_nuclear_weapons_stockpiles$country_name %in% 
    c("United States", "Russia"),] %>% 
  group_by(year, country_name) %>% summarise(nuclear_weapons_stockpile)

ggplot(total_stockpile, aes(x=year,
                            y=nuclear_weapons_stockpile,
                            fill=country_name)) +
  geom_col(position = "stack") +
  scale_x_continuous(breaks=seq(1945,2022,7)) +
  scale_y_continuous(limits=c(0,70000), 
                     breaks=seq(0,70000, 10000),
                     labels=c("0",
                             "10,000",
                             "20,000",
                             "30,000",
                             "40,000",
                             "50,000",
                             "60,000",
                             "70,000")) +
  scale_fill_brewer(palette="Set1",name="Country") +
  xlab(label="Year") + ylab(label="Number of Nuclear Weapons") +
  geom_vline(xintercept=1991) +
  annotate("text", x = 2002, y = 60000, label="Post-Soviet Era") +
  ggtitle(label="USA/Russia Nuclear Weapon Stockpile Over Time") + 
  theme_bw()

The stockpile of the major player’s decreased dramatically in the 90’s before tapering off to a stable level that has remained consistent after 2008.

Lets look at just the current year with a different perspective. First we need to figure out where all these countries are. We start by getting the centroid positions of all countries.

wmap <- getMap(resolution="low")
centroids <- gCentroid(wmap, byid=TRUE)
centroid_df <- as.data.frame(centroids)
head(centroid_df)

Turn the index into a column.

centroid_df <- rownames_to_column(centroid_df, "Country")
# Rename USA to be consistent
centroid_df["Country"][centroid_df["Country"] == "United States of America"] <- "United States"
head(centroid_df)

Merge nuclear stockpile data for 2022 with centroids of countries.

stockpile_df <- subset(data_nuclear_weapons_stockpiles, data_nuclear_weapons_stockpiles$year==2022)
stockpile_df <- merge(stockpile_df, centroid_df, by.x="country_name", by.y="Country")
# remove South Africa since they don't have any weapons currently.
stockpile_df <- stockpile_df[ !stockpile_df$country_name=="South Africa", ]
head(stockpile_df)

We can now use these coordinates to show this global arms race on the next best thing to a globe: a map.

world <-map_data("world")
ggplot() +
  geom_map(
    data = world, map = world,
    aes(long,lat, map_id=region),
    color="white", fill = "grey80", linewidth=0.01) +
  geom_point(
    data=stockpile_df,
    aes(x, y, size=nuclear_weapons_stockpile, fill=nuclear_weapons_stockpile),
    shape = 21, color="gold") +
  scale_size("Stockpiled Weapons", range=c(5,20), guide="none") +
  scale_fill_distiller("Stockpiled Weapons", palette = "RdBu") +
  ggtitle("Global Nuclear Weapon Stockpiles: 2022") +
  theme(
    axis.text=element_blank(),
    axis.ticks=element_blank(),
    axis.title=element_blank(),
    panel.grid=element_blank(),
    panel.background=element_rect(fill="white", color="black"))

ggsave("2022Stockpile.png")

Country - Country Comparisons

USA - Russia

We will take a closer look at the United States and Russia. Specifically the testing of their weapons in the field.

usa_russia_tests <-
  data_nuclear_weapons_tests_states[
    data_nuclear_weapons_tests_states$country_name %in% c("United States", "Russia"),]

usa_russia_tests$country_name <-
  factor(usa_russia_tests$country_name)
summary(usa_russia_tests$nuclear_weapons_tests)
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
   0.00    0.00    2.00   11.63   18.00   96.00 

Those 96 tests in one year seem to be a slight outlier.

ggplot(usa_russia_tests,aes(x=year, y=nuclear_weapons_tests))+
  geom_line(aes(color=country_name), size=0.75) +
  scale_color_brewer(palette = "Set1", name="Country") +
  scale_x_continuous(limits = c(1944, 1994),breaks = seq(1945,1993,6)) +
  xlab("Year") + ylab("Number of Nuclear Weapon Tests") +
  ggtitle("Global Superpower Nuclear Weapon Testing") +
  annotate("rect", xmin=1962,
           xmax=1964,ymin=0,ymax=100,alpha=0.15,fill="grey",color="gold") +
  annotate("text", x = 1975, y = 85, label="1963 Partial Test Ban Treaty") +
  annotate("rect", xmin=1957.5, xmax=1959, ymin=0, ymax=100, alpha=0.05,
           fill="grey50", color="gold") +
  annotate("text", x = 1952, y = 65, label="1958 Testing") +
  annotate("text", x = 1952, y = 60, label="Moratorium") +
  theme(
    panel.grid.minor.y=element_blank(),
    panel.grid.major.y=element_line(color="grey75"),
    panel.grid.major.x = element_blank(),
    legend.key = element_rect(fill="white"),
    panel.background=element_rect(fill="white", color="black"),
    plot.background=element_rect(fill="white"))

ggsave("AmericaRussiaTesting.png")

Testing by both the United States and the former Soviet Union had large spikes in 1958 and 1963 followed immediately by a massive decrease.

Both of these slowdowns can be associated with treaties between the two superpowers, the first one not nearly as binding as the the more formal Partial Test Ban Treaty that was signed after the Cuban Missile Crisis.

India - Pakistan

Lets examine regional relationships among some of the other nuclear powers.

india_pakistan_stockpile <-
  data_nuclear_weapons_stockpiles[
    data_nuclear_weapons_stockpiles$country_name %in% c("India", "Pakistan"),]

india_pakistan_stockpile$country_name <-
  factor(india_pakistan_stockpile$country_name)

Since the start date isn’t obvious this time, let us check when we should start our timeline.

max(india_pakistan_stockpile$year[
  (india_pakistan_stockpile$nuclear_weapons_stockpile==0) &
    india_pakistan_stockpile$country_name=="India"])
[1] 1997
max(india_pakistan_stockpile$year[
  (india_pakistan_stockpile$nuclear_weapons_stockpile==0) &
    india_pakistan_stockpile$country_name=="Pakistan"])
[1] 1997

We can focus the timeline range from 1997 to 2022.

ggplot(india_pakistan_stockpile,aes(x=year))+
  geom_line(aes(color=country_name,y=nuclear_weapons_stockpile),size=0.75) +
  scale_color_manual(name="Country",
                     values=c("darkorange", "darkgreen")) +
  scale_x_continuous(limits = c(1995, 2023),breaks = seq(1996,2022,2)) +
  xlab("Year") + ylab("Number of Nuclear Weapons") +
  ggtitle("Nuclear Stockpiles of India and Pakistan") +
  theme(
    panel.grid.major = element_blank(),
    panel.grid.minor = element_blank(),
    panel.background = element_rect(fill="white", color = "grey40"),
    legend.background = element_rect(fill="white", color="white"),
    legend.key = element_rect(fill="white", color="white"),
  )

ggsave("IndiaPakistanStockpile.png")

India and Pakistan have increased their stockpiles at approximately the same rate and at the same scale.

Summary

From this exploration we see the obvious indications of geopolitics being a dominating factor in the proliferation of nuclear weapons.

The scale of the global nuclear arms race is skewed by the presence of the Cold War superpowers. While neither Russia nor the United States are actively contributing to the growth of the total nuclear stockpile, they still remain the clear largest shareholders of the global atomic horde.

And while the scale of the overall nuclear-arms race has decreased dramatically since the latter half of the Cold War, regional races are still ongoing and the real life ramifications of the usage of nuclear arms can not be conveyed with the data used in this project.

LS0tDQp0aXRsZTogJ051Y2xlYXIgUHJvbGlmZXJhdGlvbjogSW50cm8gdG8gUiAtIEZpbmFsIFByb2plY3QnDQphdXRob3I6ICJCcmFuZG9uIFBlbm55Ig0KZGF0ZTogImByIGZvcm1hdChTeXMuRGF0ZSgpLCclZSAlQiwgJVknKWAiDQpvdXRwdXQ6DQogIGh0bWxfbm90ZWJvb2s6IA0KICAgIHRvYzogeWVzDQogICAgdGhlbWU6IHVuaXRlZA0KICBwZGZfZG9jdW1lbnQ6DQogICAgdG9jOiB5ZXMNCi0tLQ0KDQpgYGB7ciBzZXR1cCwgaW5jbHVkZT1GQUxTRX0NCmtuaXRyOjpvcHRzX2NodW5rJHNldChlY2hvID0gVFJVRSwgY2FjaGUgPSBUUlVFLCB3YXJuaW5nID0gRkFMU0UsIG1lc3NhZ2UgPSBGQUxTRSkNCmBgYA0KDQpgYGB7ciwgZWNobyA9IEZBTFNFfQ0Kcm0obGlzdD1scygpKQ0KYGBgDQoNCiMgSW50cm9kdWN0aW9uDQoNCk51Y2xlYXIgd2VhcG9ucyBleGlzdC4gU29tZSBjb3VudHJpZXMgaGF2ZSB0aGVtLiBMb3RzIG9mIGNvdW50cmllcyB3aXNoIHRoZXkgaGFkIHRoZW0uXA0KDQpGb3IgdGhpcyBwcm9qZWN0IHdlIHNoYWxsIHRha2UgYSB0b29rIGF0IHRoZSBwcm9saWZlcmF0aW9uIG9mIG51Y2xlYXIgd2VhcG9ucyBzaW5jZSB0aGVpciBjcmVhdGlvbiBhdCB0aGUgZW5kIG9mIHRoZSBTZWNvbmQgV29ybGQgV2FyIGFuZCB0aGVpciB1c2FnZSBhZnRlciB0aGUgd2FyIHVwIHRvIHRoZSBtb2Rlcm4gZXJhLlwNCg0KSG93IG1hbnkgY291bnRyaWVzIGhhdmUgYXR0ZW1wdGVkIHRvIG9idGFpbiBudWNsZWFyIHdlYXBvbnMgYW5kIG9mIHRob3NlIGhvdyBtYW55IGhhdmUgZmFpbGVkP1wNCg0KQXJlIHRyZW5kcyBpbiB3ZWFwb24gdGVzdGluZyBtb3JlIGVhc2lseSBsaW5rZWQgdG8gZ2xvYmFsIGVmZmVjdHMgb3IgcmVnaW9uYWwgb25lcz9cDQoNCkJ5IHVzaW5nIGdlb2dyYXBoaWNhbCBhbmQgaGlzdG9yaWNhbCBjb250ZXh0IHdlIHdpbGwgYXR0ZW1wdCB0byB2aXN1YWxpemUgcGF0dGVybnMgb2YgdGhlIG51Y2xlYXIgYXJtcyByYWNlLlwNCg0KIyMgTGlicmFyaWVzDQoNCiogZ2dwbG90MiBmb3IgcGxvdHRpbmcNCg0KKiByZ2VvcyBhbmQgcndvcmxkbWFwIGZvciBnZW9ncmFwaGljYWwgY29vcmlkYW5hdGVzDQoNCiogdGliYmxlIGZvciBzb21lIGVhc3kgZGF0YSBmcmFtZSByZXNoYXBpbmcNCg0KKiBkcGx5ciBmb3IgZWFzeSBkYXRhIG1hbmlwdWxhdGlvbg0KDQpgYGB7cn0NCg0KbGlicmFyeShnZ3Bsb3QyKQ0KDQpsaWJyYXJ5KHJnZW9zKQ0KDQpsaWJyYXJ5KHJ3b3JsZG1hcCkNCg0KbGlicmFyeSh0aWJibGUpDQoNCmxpYnJhcnkoZHBseXIpDQpgYGANCg0KIyBEYXRhDQoNClRoaXMgZGF0YXNldCBvZiBOdWNsZWFyIFdlYXBvbnMgd2FzIG9idGFpbmVkIGZyb20gS2FnZ2xlIGluIHRoZSBmb3JtIG9mIGZvdXIgZmlsZXMuXA0KDQoNCjEuIE51Y2xlYXIgV2VhcG9ucyBQcm9saWZlcmF0aW9uIChDb3VudHJ5KQ0KMi4gTnVjbGVhciBXZWFwb25zIFByb2xpZmVyYXRpb24gKEdsb2JhbCkNCjMuIE51Y2xlYXIgV2VhcG9ucyBTdG9ja3BpbGVzIChDb3VudHJ5KQ0KNC4gTnVjbGVhciBXZWFwb25zIFRlc3RzIFN0YXRlcyAoQ291bnRyeSkNCg0KaHR0cHM6Ly93d3cua2FnZ2xlLmNvbS9kYXRhc2V0cy9taWNoYWVsYnJ5YW50ZHMvbnVjbGVhci13ZWFwb25zLWRhdGFzZXQNCg0KIyMgUHJlcGFyYXRpb24NCg0KV2UgbG9hZCBpbiB0aGUgZm91ciBjc3YgZmlsZXMgYXMgZGF0YSBmcmFtZXMuXA0KDQpgYGB7cn0NCmRhdGFQYXRoIDwtICJudWNsZWFyX3dlYXBvbnMvIg0KZGF0YUxpc3QgPC0gbGlzdC5maWxlcyhwYXRoID0gZGF0YVBhdGgpDQpwcmludChkYXRhTGlzdCkNCmBgYA0KDQpBc3NpZ24gZGF0YSBmcmFtZSBmb3IgZWFjaCBkYXRhIGZpbGUuXA0KDQpgYGB7cn0NCmZvcihpIGluIDE6bGVuZ3RoKGRhdGFMaXN0KSkgew0KICBmaWxlTmFtZSA8LSBzdWJzdHIoZGF0YUxpc3RbW2ldXSwxLG5jaGFyKGRhdGFMaXN0W1tpXV0pLTQpDQogIGNzdl9wYXRoIDwtIHBhc3RlMChkYXRhUGF0aCxkYXRhTGlzdFtbaV1dKQ0KICBhc3NpZ24ocGFzdGUwKCJkYXRhXyIsIGZpbGVOYW1lKSwgcmVhZC5jc3YoY3N2X3BhdGgpKQ0KfQ0Kcm0obGlzdCA9IGMoImNzdl9wYXRoIiwiZmlsZU5hbWUiLCJpIikpDQpgYGANCg0KYGBge3J9DQpkZkxpc3QgPC0gYygpDQpmb3IoaSBpbiAxOmxlbmd0aChkYXRhTGlzdCkpIHsNCiAgZGF0YXNldCA8LSBwYXN0ZTAoImRhdGFfIixhcy5jaGFyYWN0ZXIoZGF0YUxpc3RbaV0pKQ0KICBkYXRhc2V0IDwtIHN1YnN0cihkYXRhc2V0LCAxLCBuY2hhcihkYXRhc2V0KS00KQ0KICBkZkxpc3RbaV0gPC0gZGF0YXNldA0KfQ0KYGBgDQoNClF1aWNrIGxvb2sgYXQgdGhlIGRhdGEuXA0KDQpgYGB7cn0NCmZvcihpIGluIDE6bGVuZ3RoKGRmTGlzdCkpIHsNCiAgcHJpbnQoYyhkZkxpc3RbaV0sIHN0cihnZXQoZGZMaXN0W2ldKSkpKQ0KfQ0KYGBgDQoNCkNvbnZlcnQgImNvdW50cnlfbmFtZSIgY29sdW1ucyBmcm9tIGNoYXJhY3RlciB0byBmYWN0b3IuXA0KDQpgYGB7cn0NCmRhdGFfbnVjbGVhcl93ZWFwb25zX3Byb2xpZmVyYXRpb25fb3dpZCRjb3VudHJ5X25hbWUgPC0NCiAgZmFjdG9yKGRhdGFfbnVjbGVhcl93ZWFwb25zX3Byb2xpZmVyYXRpb25fb3dpZCRjb3VudHJ5X25hbWUpDQoNCmRhdGFfbnVjbGVhcl93ZWFwb25zX3N0b2NrcGlsZXMkY291bnRyeV9uYW1lIDwtDQogIGZhY3RvcihkYXRhX251Y2xlYXJfd2VhcG9uc19zdG9ja3BpbGVzJGNvdW50cnlfbmFtZSkNCg0KZGF0YV9udWNsZWFyX3dlYXBvbnNfdGVzdHNfc3RhdGVzJGNvdW50cnlfbmFtZSA8LQ0KICBmYWN0b3IoZGF0YV9udWNsZWFyX3dlYXBvbnNfdGVzdHNfc3RhdGVzJGNvdW50cnlfbmFtZSkNCmBgYA0KDQojIEV4cGxvcmF0aW9uDQoNCiMjIEdsb2JhbCBQb3NzZXNzaW9uIGFuZCBQdXJzdWl0IG9mIE51Y2xlYXIgQXJtcw0KDQpXZSBjYW4gZWFzaWx5IHBsb3QgdGhlIGNvdW50cmllcyBpbiBwdXJzdWl0IG9mIGFuZCBpbiBwb3NzZXNzaW9uIG9mIG51Y2xlYXIgYXJtcyB0b2dldGhlci5cDQoNCg0KYGBge3J9DQpmaWxscyA8LSBjKCJQb3NzZXNzaW9uIiA9ICJzdGVlbGJsdWUiLCAiUHVyc3VpdCIgPSAiZ29sZGVucm9kMiIpDQpnZ3Bsb3QoZGF0YV9udWNsZWFyX3dlYXBvbnNfcHJvbGlmZXJhdGlvbl90b3RhbF9vd2lkLCBhZXMoeD15ZWFyKSkgKw0KICBnZW9tX2NvbChhZXMoeSA9IG51bWJlcl9udWNsd2VhcF9wb3NzZXNzaW9uLCBmaWxsID0gIlBvc3Nlc3Npb24iKSwNCiAgICAgICAgICAgY29sb3I9InN0ZWVsYmx1ZTQiKSArDQogIGdlb21fY29sKGFlcyh5ID0gbnVtYmVyX251Y2x3ZWFwX3B1cnN1aXQsIGZpbGw9IlB1cnN1aXQiKSwNCiAgICAgICAgICAgY29sb3I9InNpZW5uYSIsDQogICAgICAgICAgIGFscGhhPTAuOCkgKw0KICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXM9ZmlsbHMsIG5hbWU9IlN0YXR1cyIpICsNCiAgc2NhbGVfeV9jb250aW51b3VzKGJyZWFrcz1jKDA6OSkpICsNCiAgc2NhbGVfeF9jb250aW51b3VzKGJyZWFrcyA9IHNlcSgxOTQxLDIwMjIsOSkpICsNCiAgdGhlbWUoDQogICAgcGFuZWwuZ3JpZC5taW5vci55ID0gZWxlbWVudF9ibGFuaygpLA0KICAgIHBhbmVsLmdyaWQubWFqb3IgPSBlbGVtZW50X2xpbmUoY29sb3I9ImdyZXk4MCIpLA0KICAgIHBhbmVsLmJhY2tncm91bmQgPSBlbGVtZW50X3JlY3QoZmlsbD0id2hpdGUiLCBjb2xvciA9ImJsYWNrIiksDQogICAgcGxvdC5iYWNrZ3JvdW5kID0gZWxlbWVudF9yZWN0KGZpbGw9IndoaXRlIiwgY29sb3I9IndoaXRlIikpICsNCiAgeGxhYigiWWVhciIpICsgeWxhYigiTnVtYmVyIG9mIENvdW50cmllcyIpICsNCiAgZ2d0aXRsZSgiR2xvYmFsIE51Y2xlYXIgV2VhcG9uIFN0YXRlcyIpDQpgYGANCg0KV2UgY2FuIHNlZSB0aGF0IHBvc3Nlc3Npb24gb2YgbnVjbGVhciB3ZWFwb25zIGhhcyBncmFkdWFsbHkgaW5jcmVhc2VkIG92ZXIgdGltZSByZXN1bHRpbmcgaW4gOSBjb3VudHJpZXMgcG9zc2Vzc2luZyBudWNsZWFyIGFybXMgaW4gdGhlIG1vZGVybiBlcmEuXA0KDQpXaGVuIGEgY291bnRyeSBpbiBwdXJzdWl0IHN1Y2NlZWRzIGluIHRoZWlyIGdvYWxzLCB0aGV5IGFyZSByZW1vdmVkIGZyb20gdGhlICJwdXJzdWl0IHBvb2wiIGFuZCBhZGRlZCB0byB0aGUgcG9vbCBvZiB0aG9zZSBpbiBwb3NzZXNzaW9uIG9mIG51Y2xlYXIgYXJtcy4gTm90IGFsbCBjb3VudHJpZXMgd2hvIGhhdmUgYWN0aXZlbHkgcHVyc3VlZCB0aGVzZSB3ZWFwb25zIGhhdmUgc3VjY2VlZGVkIGhvd2V2ZXIuXA0KDQpgYGB7cn0NCmNvbnNpZGVyZWQgPC0gZGF0YV9udWNsZWFyX3dlYXBvbnNfcHJvbGlmZXJhdGlvbl9vd2lkWw0KICBkYXRhX251Y2xlYXJfd2VhcG9uc19wcm9saWZlcmF0aW9uX293aWQkbnVjbGVhcl93ZWFwb25zX3N0YXR1cyA+IDAsXQ0KDQpjb25zaWRlcmVkJGNvdW50cnlfbmFtZSA8LQ0KICBmYWN0b3IoY29uc2lkZXJlZCRjb3VudHJ5X25hbWUpDQoNCmdncGxvdChjb25zaWRlcmVkLA0KICAgICAgIGFlcyh4PXllYXIsDQogICAgICAgICAgIHk9Y291bnRyeV9uYW1lLA0KICAgICAgICAgICBmaWxsPWZhY3RvcihudWNsZWFyX3dlYXBvbnNfc3RhdHVzKSkpICsNCiAgZ2VvbV90aWxlKGFlcyhoZWlnaHQ9MC44NSkpICsNCiAgeGxhYigiWWVhciIpICsgeWxhYigiQ291bnRyeSIpICsNCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gYygic3ByaW5nZ3JlZW40Iiwib3JhbmdlMSIsInN0ZWVsYmx1ZTMiKSwNCiAgICAgICAgICAgICAgICAgICAgbmFtZT0iU3RhdHVzIiwNCiAgICAgICAgICAgICAgICAgICAgbGFiZWxzPWMoIkNvbnNpZGVyYXRpb24iLCJQdXJzdWl0IiwiUG9zc2Vzc2lvbiIpKSArDQogIHNjYWxlX3hfY29udGludW91cyhicmVha3M9c2VxKDE5MzgsMjAyMiwxMikpICsNCiAgZ2VvbV92bGluZSgNCiAgICB4aW50ZXJjZXB0PWNvbnNpZGVyZWRbbWF4KGNvbnNpZGVyZWQkbnVjbGVhcl93ZWFwb25zX3N0YXR1cyksXSR5ZWFyKSArDQogIGdndGl0bGUobGFiZWwgPSAiR2xvYmFsIENvbnNpZGVyYXRpb24gb2YgTnVjbGVhciBXZWFwb25zIikgKw0KICB0aGVtZV9idygpDQpgYGANCg0KSGVyZSB3ZSBzZWUgYSBtb3JlIGRldGFpbGVkIHZpZXcgb2YgYWxsIGNvdW50cmllcyB0aGF0IGhhdmUgcHVibGljbHkgY29uc2lkZXJlZCBhdHRlbXB0aW5nIHRvIG9idGFpbiBudWNsZWFyIHdlYXBvbnMuXA0KDQoxOTg1IHdhcyB0aGUgeWVhciB0aGF0IGhhZCB0aGUgbW9zdCBjb3VudHJpZXMgbGFiZWxlZCBhcyBlaXRoZXIgY29uc2lkZXJpbmcsIHB1cnN1aW5nLCBvciBpbiBwb3NzZXNzaW9uIG9mIG51Y2xlYXIgd2VhcG9ucy5cDQoNCkFzIG9mIHRvZGF5LCBJcmFuIHJlbWFpbnMgdGhlIG9ubHkgY291bnRyeSBzdGlsbCBhY3RpdmVseSBwdXJzdWluZyBudWNsZWFyIHdlYXBvbnJ5LlwNCg0KIyMgR2xvYmFsIFN0b2NrcGlsZXMgb2YgTnVjbGVhciBXZWFwb25zDQoNCldoZW4gZGlkIGVhY2ggY291bnRyeSBoYXZlIHRoZWlyIHJlY29yZCBzdG9ja3BpbGUgc2l6ZT8NCg0KYGBge3J9DQptYXhfc3RvY2twaWxlIDwtIGRhdGFfbnVjbGVhcl93ZWFwb25zX3N0b2NrcGlsZXMgJT4lIA0KICBncm91cF9ieShjb3VudHJ5X25hbWUpICU+JSBzbGljZSh3aGljaC5tYXgobnVjbGVhcl93ZWFwb25zX3N0b2NrcGlsZSkpDQoNCmdncGxvdChtYXhfc3RvY2twaWxlLA0KICAgICAgIGFlcyh4PXJlb3JkZXIoY291bnRyeV9uYW1lLCBudWNsZWFyX3dlYXBvbnNfc3RvY2twaWxlKSwNCiAgICAgICAgICAgeT1udWNsZWFyX3dlYXBvbnNfc3RvY2twaWxlLA0KICAgICAgICAgICBmaWxsID0gbnVjbGVhcl93ZWFwb25zX3N0b2NrcGlsZSkpICsgDQogIGdlb21fYmFyKHN0YXQ9ImlkZW50aXR5IiwgY29sb3I9ImJsYWNrIikgKw0KICBnZW9tX3RleHQoYWVzKGxhYmVsPXllYXIsIHkgPSBtaW4obnVjbGVhcl93ZWFwb25zX3N0b2NrcGlsZSkpLA0KICAgICAgICAgICAgdmp1c3Q9Nywgc2l6ZT0zKSArDQogIHNjYWxlX3lfbG9nMTAoYnJlYWtzPTEwXigwOjUpLA0KICAgICAgICAgICAgICAgIGV4cGFuZD1jKDAsMC41KSwgDQogICAgICAgICAgICAgICAgbGFiZWxzPWMoIjAiLCIxMCIsIjEwMCIsIjEsMDAwIiwiMTAsMDAwIiwiMTAwLDAwMCIpKSArDQogIHNjYWxlX2ZpbGxfZGlzdGlsbGVyKHBhbGV0dGU9IlJkQnUiLA0KICAgICAgICAgICAgICAgICAgICAgICBuYW1lPSJTdG9ja3BpbGVkIFdlYXBvbnMiKSArIA0KICB5bGFiKGxhYmVsPSJOdW1iZXIgb2YgTnVjbGVhciBXZWFwb25zIikgKw0KICBnZ3RpdGxlKGxhYmVsPSJNYXhpbXVtIE51Y2xlYXIgV2VhcG9uIFN0b2NrcGlsZSBTaXplIikgKw0KICB0aGVtZSgNCiAgICBheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZT0zMCwgaGp1c3QgPTAuOCwgdmp1c3Q9MC44LCBzaXplPTEwKSwNCiAgICBheGlzLnRpdGxlLnggPSBlbGVtZW50X2JsYW5rKCksDQogICAgcGFuZWwuZ3JpZC5tYWpvci54ID0gZWxlbWVudF9ibGFuaygpLA0KICAgIHBhbmVsLmdyaWQubWFqb3IueSA9IGVsZW1lbnRfbGluZShjb2xvcj0iZ3JleTgwIiksDQogICAgcGFuZWwuYmFja2dyb3VuZCA9IGVsZW1lbnRfcmVjdChmaWxsPSJ3aGl0ZSIsIGNvbG9yPSJibGFjayIpLA0KICAgIGxlZ2VuZC50aXRsZSA9IGVsZW1lbnRfdGV4dCh2anVzdD0zKSkNCmBgYA0KDQpDbGVhcmx5IFJ1c3NpYSBhbmQgdGhlIFVuaXRlZCBTdGF0ZXMgYXJlIGZhciBiZXlvbmQgdGhlIHJlc3Qgb2YgdGhlIHBhY2sgaW4gcmVnYXJkcyB0byB0aGUgc2l6ZSBvZiB0aGVpciBudWNsZWFyIHdlYXBvbnMgc3RvY2twaWxlLlwNCg0KTG90cyBvZiB3ZWFwb25zIGJhY2sgNzAncyBhbmQgODAncy4gV2hhdCBoYXBwZW5lZD9cDQoNCg0KYGBge3J9DQp0b3RhbF9zdG9ja3BpbGUgPC0gZGF0YV9udWNsZWFyX3dlYXBvbnNfc3RvY2twaWxlc1sNCiAgZGF0YV9udWNsZWFyX3dlYXBvbnNfc3RvY2twaWxlcyRjb3VudHJ5X25hbWUgJWluJSANCiAgICBjKCJVbml0ZWQgU3RhdGVzIiwgIlJ1c3NpYSIpLF0gJT4lIA0KICBncm91cF9ieSh5ZWFyLCBjb3VudHJ5X25hbWUpICU+JSBzdW1tYXJpc2UobnVjbGVhcl93ZWFwb25zX3N0b2NrcGlsZSkNCg0KZ2dwbG90KHRvdGFsX3N0b2NrcGlsZSwgYWVzKHg9eWVhciwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICB5PW51Y2xlYXJfd2VhcG9uc19zdG9ja3BpbGUsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgZmlsbD1jb3VudHJ5X25hbWUpKSArDQogIGdlb21fY29sKHBvc2l0aW9uID0gInN0YWNrIikgKw0KICBzY2FsZV94X2NvbnRpbnVvdXMoYnJlYWtzPXNlcSgxOTQ1LDIwMjIsNykpICsNCiAgc2NhbGVfeV9jb250aW51b3VzKGxpbWl0cz1jKDAsNzAwMDApLCANCiAgICAgICAgICAgICAgICAgICAgIGJyZWFrcz1zZXEoMCw3MDAwMCwgMTAwMDApLA0KICAgICAgICAgICAgICAgICAgICAgbGFiZWxzPWMoIjAiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiMTAsMDAwIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIjIwLDAwMCIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICIzMCwwMDAiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiNDAsMDAwIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIjUwLDAwMCIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICI2MCwwMDAiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiNzAsMDAwIikpICsNCiAgc2NhbGVfZmlsbF9icmV3ZXIocGFsZXR0ZT0iU2V0MSIsbmFtZT0iQ291bnRyeSIpICsNCiAgeGxhYihsYWJlbD0iWWVhciIpICsgeWxhYihsYWJlbD0iTnVtYmVyIG9mIE51Y2xlYXIgV2VhcG9ucyIpICsNCiAgZ2VvbV92bGluZSh4aW50ZXJjZXB0PTE5OTEpICsNCiAgYW5ub3RhdGUoInRleHQiLCB4ID0gMjAwMiwgeSA9IDYwMDAwLCBsYWJlbD0iUG9zdC1Tb3ZpZXQgRXJhIikgKw0KICBnZ3RpdGxlKGxhYmVsPSJVU0EvUnVzc2lhIE51Y2xlYXIgV2VhcG9uIFN0b2NrcGlsZSBPdmVyIFRpbWUiKSArIA0KICB0aGVtZV9idygpDQpgYGANCg0KVGhlIHN0b2NrcGlsZSBvZiB0aGUgbWFqb3IgcGxheWVyJ3MgZGVjcmVhc2VkIGRyYW1hdGljYWxseSBpbiB0aGUgOTAncyBiZWZvcmUgdGFwZXJpbmcgb2ZmIHRvIGEgc3RhYmxlIGxldmVsIHRoYXQgaGFzIHJlbWFpbmVkIGNvbnNpc3RlbnQgYWZ0ZXIgMjAwOC5cDQoNCkxldHMgbG9vayBhdCBqdXN0IHRoZSBjdXJyZW50IHllYXIgd2l0aCBhIGRpZmZlcmVudCBwZXJzcGVjdGl2ZS4gRmlyc3Qgd2UgbmVlZCB0byBmaWd1cmUgb3V0IHdoZXJlIGFsbCB0aGVzZSBjb3VudHJpZXMgYXJlLiBXZSBzdGFydCBieSBnZXR0aW5nIHRoZSBjZW50cm9pZCBwb3NpdGlvbnMgb2YgYWxsIGNvdW50cmllcy5cDQoNCmBgYHtyfQ0Kd21hcCA8LSBnZXRNYXAocmVzb2x1dGlvbj0ibG93IikNCmNlbnRyb2lkcyA8LSBnQ2VudHJvaWQod21hcCwgYnlpZD1UUlVFKQ0KY2VudHJvaWRfZGYgPC0gYXMuZGF0YS5mcmFtZShjZW50cm9pZHMpDQpoZWFkKGNlbnRyb2lkX2RmKQ0KYGBgDQoNClR1cm4gdGhlIGluZGV4IGludG8gYSBjb2x1bW4uXA0KDQpgYGB7cn0NCmNlbnRyb2lkX2RmIDwtIHJvd25hbWVzX3RvX2NvbHVtbihjZW50cm9pZF9kZiwgIkNvdW50cnkiKQ0KIyBSZW5hbWUgVVNBIHRvIGJlIGNvbnNpc3RlbnQNCmNlbnRyb2lkX2RmWyJDb3VudHJ5Il1bY2VudHJvaWRfZGZbIkNvdW50cnkiXSA9PSAiVW5pdGVkIFN0YXRlcyBvZiBBbWVyaWNhIl0gPC0gDQogICJVbml0ZWQgU3RhdGVzIg0KaGVhZChjZW50cm9pZF9kZikNCmBgYA0KDQpNZXJnZSBudWNsZWFyIHN0b2NrcGlsZSBkYXRhIGZvciAyMDIyIHdpdGggY2VudHJvaWRzIG9mIGNvdW50cmllcy5cDQoNCmBgYHtyfQ0Kc3RvY2twaWxlX2RmIDwtIHN1YnNldChkYXRhX251Y2xlYXJfd2VhcG9uc19zdG9ja3BpbGVzLA0KICAgICAgICAgICAgICAgICAgICAgICBkYXRhX251Y2xlYXJfd2VhcG9uc19zdG9ja3BpbGVzJHllYXI9PTIwMjIpDQpzdG9ja3BpbGVfZGYgPC0gbWVyZ2Uoc3RvY2twaWxlX2RmLCBjZW50cm9pZF9kZiwNCiAgICAgICAgICAgICAgICAgICAgICBieS54PSJjb3VudHJ5X25hbWUiLA0KICAgICAgICAgICAgICAgICAgICAgIGJ5Lnk9IkNvdW50cnkiKQ0KIyByZW1vdmUgU291dGggQWZyaWNhIHNpbmNlIHRoZXkgZG9uJ3QgaGF2ZSBhbnkgd2VhcG9ucyBjdXJyZW50bHkuDQpzdG9ja3BpbGVfZGYgPC0gc3RvY2twaWxlX2RmWyAhc3RvY2twaWxlX2RmJGNvdW50cnlfbmFtZT09IlNvdXRoIEFmcmljYSIsIF0NCmhlYWQoc3RvY2twaWxlX2RmKQ0KYGBgDQoNCldlIGNhbiBub3cgdXNlIHRoZXNlIGNvb3JkaW5hdGVzIHRvIHNob3cgdGhpcyBnbG9iYWwgYXJtcyByYWNlIG9uIHRoZSBuZXh0IGJlc3QgdGhpbmcgdG8gYSBnbG9iZTogYSBtYXAuXA0KDQpgYGB7cn0NCndvcmxkIDwtbWFwX2RhdGEoIndvcmxkIikNCmdncGxvdCgpICsNCiAgZ2VvbV9tYXAoDQogICAgZGF0YSA9IHdvcmxkLCBtYXAgPSB3b3JsZCwNCiAgICBhZXMobG9uZyxsYXQsIG1hcF9pZD1yZWdpb24pLA0KICAgIGNvbG9yPSJ3aGl0ZSIsIGZpbGwgPSAiZ3JleTgwIiwgbGluZXdpZHRoPTAuMDEpICsNCiAgZ2VvbV9wb2ludCgNCiAgICBkYXRhPXN0b2NrcGlsZV9kZiwNCiAgICBhZXMoeCwgeSwgc2l6ZT1udWNsZWFyX3dlYXBvbnNfc3RvY2twaWxlLCBmaWxsPW51Y2xlYXJfd2VhcG9uc19zdG9ja3BpbGUpLA0KICAgIHNoYXBlID0gMjEsIGNvbG9yPSJnb2xkIikgKw0KICBzY2FsZV9zaXplKCJTdG9ja3BpbGVkIFdlYXBvbnMiLCByYW5nZT1jKDUsMjApLCBndWlkZT0ibm9uZSIpICsNCiAgc2NhbGVfZmlsbF9kaXN0aWxsZXIoIlN0b2NrcGlsZWQgV2VhcG9ucyIsIHBhbGV0dGUgPSAiUmRCdSIpICsNCiAgZ2d0aXRsZSgiR2xvYmFsIE51Y2xlYXIgV2VhcG9uIFN0b2NrcGlsZXM6IDIwMjIiKSArDQogIHRoZW1lKA0KICAgIGF4aXMudGV4dD1lbGVtZW50X2JsYW5rKCksDQogICAgYXhpcy50aWNrcz1lbGVtZW50X2JsYW5rKCksDQogICAgYXhpcy50aXRsZT1lbGVtZW50X2JsYW5rKCksDQogICAgcGFuZWwuZ3JpZD1lbGVtZW50X2JsYW5rKCksDQogICAgcGFuZWwuYmFja2dyb3VuZD1lbGVtZW50X3JlY3QoZmlsbD0id2hpdGUiLCBjb2xvcj0iYmxhY2siKSkNCmBgYA0KDQoNCg0KIyMgQ291bnRyeSAtIENvdW50cnkgQ29tcGFyaXNvbnMNCg0KIyMjIFVTQSAtIFJ1c3NpYQ0KDQpXZSB3aWxsIHRha2UgYSBjbG9zZXIgbG9vayBhdCB0aGUgVW5pdGVkIFN0YXRlcyBhbmQgUnVzc2lhLiBTcGVjaWZpY2FsbHkgdGhlIHRlc3Rpbmcgb2YgdGhlaXIgd2VhcG9ucyBpbiB0aGUgZmllbGQuXA0KDQpgYGB7cn0NCnVzYV9ydXNzaWFfdGVzdHMgPC0NCiAgZGF0YV9udWNsZWFyX3dlYXBvbnNfdGVzdHNfc3RhdGVzWw0KICAgIGRhdGFfbnVjbGVhcl93ZWFwb25zX3Rlc3RzX3N0YXRlcyRjb3VudHJ5X25hbWUgJWluJQ0KICAgICAgYygiVW5pdGVkIFN0YXRlcyIsICJSdXNzaWEiKSxdDQoNCnVzYV9ydXNzaWFfdGVzdHMkY291bnRyeV9uYW1lIDwtDQogIGZhY3Rvcih1c2FfcnVzc2lhX3Rlc3RzJGNvdW50cnlfbmFtZSkNCmBgYA0KDQpgYGB7cn0NCnN1bW1hcnkodXNhX3J1c3NpYV90ZXN0cyRudWNsZWFyX3dlYXBvbnNfdGVzdHMpDQpgYGANClRob3NlIDk2IHRlc3RzIGluIG9uZSB5ZWFyIHNlZW0gdG8gYmUgYSBzbGlnaHQgb3V0bGllci5cDQoNCmBgYHtyfQ0KZ2dwbG90KHVzYV9ydXNzaWFfdGVzdHMsYWVzKHg9eWVhciwgeT1udWNsZWFyX3dlYXBvbnNfdGVzdHMpKSsNCiAgZ2VvbV9saW5lKGFlcyhjb2xvcj1jb3VudHJ5X25hbWUpLCBzaXplPTAuNzUpICsNCiAgc2NhbGVfY29sb3JfYnJld2VyKHBhbGV0dGUgPSAiU2V0MSIsIG5hbWU9IkNvdW50cnkiKSArDQogIHNjYWxlX3hfY29udGludW91cyhsaW1pdHMgPSBjKDE5NDQsIDE5OTQpLGJyZWFrcyA9IHNlcSgxOTQ1LDE5OTMsNikpICsNCiAgeGxhYigiWWVhciIpICsgeWxhYigiTnVtYmVyIG9mIE51Y2xlYXIgV2VhcG9uIFRlc3RzIikgKw0KICBnZ3RpdGxlKCJHbG9iYWwgU3VwZXJwb3dlciBOdWNsZWFyIFdlYXBvbiBUZXN0aW5nIikgKw0KICBhbm5vdGF0ZSgicmVjdCIsIHhtaW49MTk2MiwNCiAgICAgICAgICAgeG1heD0xOTY0LHltaW49MCx5bWF4PTEwMCxhbHBoYT0wLjE1LGZpbGw9ImdyZXkiLGNvbG9yPSJnb2xkIikgKw0KICBhbm5vdGF0ZSgidGV4dCIsIHggPSAxOTc1LCB5ID0gODUsIGxhYmVsPSIxOTYzIFBhcnRpYWwgVGVzdCBCYW4gVHJlYXR5IikgKw0KICBhbm5vdGF0ZSgicmVjdCIsIHhtaW49MTk1Ny41LCB4bWF4PTE5NTksIHltaW49MCwgeW1heD0xMDAsIGFscGhhPTAuMDUsDQogICAgICAgICAgIGZpbGw9ImdyZXk1MCIsIGNvbG9yPSJnb2xkIikgKw0KICBhbm5vdGF0ZSgidGV4dCIsIHggPSAxOTUyLCB5ID0gNjUsIGxhYmVsPSIxOTU4IFRlc3RpbmciKSArDQogIGFubm90YXRlKCJ0ZXh0IiwgeCA9IDE5NTIsIHkgPSA2MCwgbGFiZWw9Ik1vcmF0b3JpdW0iKSArDQogIHRoZW1lKA0KICAgIHBhbmVsLmdyaWQubWlub3IueT1lbGVtZW50X2JsYW5rKCksDQogICAgcGFuZWwuZ3JpZC5tYWpvci55PWVsZW1lbnRfbGluZShjb2xvcj0iZ3JleTc1IiksDQogICAgcGFuZWwuZ3JpZC5tYWpvci54ID0gZWxlbWVudF9ibGFuaygpLA0KICAgIGxlZ2VuZC5rZXkgPSBlbGVtZW50X3JlY3QoZmlsbD0id2hpdGUiKSwNCiAgICBwYW5lbC5iYWNrZ3JvdW5kPWVsZW1lbnRfcmVjdChmaWxsPSJ3aGl0ZSIsIGNvbG9yPSJibGFjayIpLA0KICAgIHBsb3QuYmFja2dyb3VuZD1lbGVtZW50X3JlY3QoZmlsbD0id2hpdGUiKSkNCg0KYGBgDQoNClRlc3RpbmcgYnkgYm90aCB0aGUgVW5pdGVkIFN0YXRlcyBhbmQgdGhlIGZvcm1lciBTb3ZpZXQgVW5pb24gaGFkIGxhcmdlIHNwaWtlcyBpbiAxOTU4IGFuZCAxOTYzIGZvbGxvd2VkIGltbWVkaWF0ZWx5IGJ5IGEgbWFzc2l2ZSBkZWNyZWFzZS5cDQoNCkJvdGggb2YgdGhlc2Ugc2xvd2Rvd25zIGNhbiBiZSBhc3NvY2lhdGVkIHdpdGggdHJlYXRpZXMgYmV0d2VlbiB0aGUgdHdvIHN1cGVycG93ZXJzLCB0aGUgZmlyc3Qgb25lIG5vdCBuZWFybHkgYXMgYmluZGluZyBhcyB0aGUgdGhlIG1vcmUgZm9ybWFsIFBhcnRpYWwgVGVzdCBCYW4gVHJlYXR5IHRoYXQgd2FzIHNpZ25lZCBhZnRlciB0aGUgQ3ViYW4gTWlzc2lsZSBDcmlzaXMuXA0KDQojIyMgSW5kaWEgLSBQYWtpc3Rhbg0KDQpMZXRzIGV4YW1pbmUgcmVnaW9uYWwgcmVsYXRpb25zaGlwcyBhbW9uZyBzb21lIG9mIHRoZSBvdGhlciBudWNsZWFyIHBvd2Vycy5cDQoNCmBgYHtyfQ0KaW5kaWFfcGFraXN0YW5fc3RvY2twaWxlIDwtDQogIGRhdGFfbnVjbGVhcl93ZWFwb25zX3N0b2NrcGlsZXNbDQogICAgZGF0YV9udWNsZWFyX3dlYXBvbnNfc3RvY2twaWxlcyRjb3VudHJ5X25hbWUgJWluJSBjKCJJbmRpYSIsICJQYWtpc3RhbiIpLF0NCg0KaW5kaWFfcGFraXN0YW5fc3RvY2twaWxlJGNvdW50cnlfbmFtZSA8LQ0KICBmYWN0b3IoaW5kaWFfcGFraXN0YW5fc3RvY2twaWxlJGNvdW50cnlfbmFtZSkNCmBgYA0KDQpTaW5jZSB0aGUgc3RhcnQgZGF0ZSBpc24ndCBvYnZpb3VzIHRoaXMgdGltZSwgbGV0IHVzIGNoZWNrIHdoZW4gd2Ugc2hvdWxkIHN0YXJ0IG91ciB0aW1lbGluZS5cDQoNCmBgYHtyfQ0KbWF4KGluZGlhX3Bha2lzdGFuX3N0b2NrcGlsZSR5ZWFyWw0KICAoaW5kaWFfcGFraXN0YW5fc3RvY2twaWxlJG51Y2xlYXJfd2VhcG9uc19zdG9ja3BpbGU9PTApICYNCiAgICBpbmRpYV9wYWtpc3Rhbl9zdG9ja3BpbGUkY291bnRyeV9uYW1lPT0iSW5kaWEiXSkNCg0KbWF4KGluZGlhX3Bha2lzdGFuX3N0b2NrcGlsZSR5ZWFyWw0KICAoaW5kaWFfcGFraXN0YW5fc3RvY2twaWxlJG51Y2xlYXJfd2VhcG9uc19zdG9ja3BpbGU9PTApICYNCiAgICBpbmRpYV9wYWtpc3Rhbl9zdG9ja3BpbGUkY291bnRyeV9uYW1lPT0iUGFraXN0YW4iXSkNCmBgYA0KV2UgY2FuIGZvY3VzIHRoZSB0aW1lbGluZSByYW5nZSBmcm9tIDE5OTcgdG8gMjAyMi5cDQoNCmBgYHtyfQ0KZ2dwbG90KGluZGlhX3Bha2lzdGFuX3N0b2NrcGlsZSxhZXMoeD15ZWFyKSkrDQogIGdlb21fbGluZShhZXMoY29sb3I9Y291bnRyeV9uYW1lLHk9bnVjbGVhcl93ZWFwb25zX3N0b2NrcGlsZSksc2l6ZT0wLjc1KSArDQogIHNjYWxlX2NvbG9yX21hbnVhbChuYW1lPSJDb3VudHJ5IiwNCiAgICAgICAgICAgICAgICAgICAgIHZhbHVlcz1jKCJkYXJrb3JhbmdlIiwgImRhcmtncmVlbiIpKSArDQogIHNjYWxlX3hfY29udGludW91cyhsaW1pdHMgPSBjKDE5OTUsIDIwMjMpLGJyZWFrcyA9IHNlcSgxOTk2LDIwMjIsMikpICsNCiAgeGxhYigiWWVhciIpICsgeWxhYigiTnVtYmVyIG9mIE51Y2xlYXIgV2VhcG9ucyIpICsNCiAgZ2d0aXRsZSgiTnVjbGVhciBTdG9ja3BpbGVzIG9mIEluZGlhIGFuZCBQYWtpc3RhbiIpICsNCiAgdGhlbWUoDQogICAgcGFuZWwuZ3JpZC5tYWpvciA9IGVsZW1lbnRfYmxhbmsoKSwNCiAgICBwYW5lbC5ncmlkLm1pbm9yID0gZWxlbWVudF9ibGFuaygpLA0KICAgIHBhbmVsLmJhY2tncm91bmQgPSBlbGVtZW50X3JlY3QoZmlsbD0id2hpdGUiLCBjb2xvciA9ICJncmV5NDAiKSwNCiAgICBsZWdlbmQuYmFja2dyb3VuZCA9IGVsZW1lbnRfcmVjdChmaWxsPSJ3aGl0ZSIsIGNvbG9yPSJ3aGl0ZSIpLA0KICAgIGxlZ2VuZC5rZXkgPSBlbGVtZW50X3JlY3QoZmlsbD0id2hpdGUiLCBjb2xvcj0id2hpdGUiKSwNCiAgKQ0KDQpgYGANCg0KSW5kaWEgYW5kIFBha2lzdGFuIGhhdmUgaW5jcmVhc2VkIHRoZWlyIHN0b2NrcGlsZXMgYXQgYXBwcm94aW1hdGVseSB0aGUgc2FtZSByYXRlIGFuZCBhdCB0aGUgc2FtZSBzY2FsZS5cDQoNCg0KIyBTdW1tYXJ5DQoNCkZyb20gdGhpcyBleHBsb3JhdGlvbiB3ZSBzZWUgdGhlIG9idmlvdXMgaW5kaWNhdGlvbnMgb2YgZ2VvcG9saXRpY3MgYmVpbmcgYSBkb21pbmF0aW5nIGZhY3RvciBpbiB0aGUgcHJvbGlmZXJhdGlvbiBvZiBudWNsZWFyIHdlYXBvbnMuDQoNClRoZSBzY2FsZSBvZiB0aGUgZ2xvYmFsIG51Y2xlYXIgYXJtcyByYWNlIGlzIHNrZXdlZCBieSB0aGUgcHJlc2VuY2Ugb2YgdGhlIENvbGQgV2FyIHN1cGVycG93ZXJzLiBXaGlsZSBuZWl0aGVyIFJ1c3NpYSBub3IgdGhlIFVuaXRlZCBTdGF0ZXMgYXJlIGFjdGl2ZWx5IGNvbnRyaWJ1dGluZyB0byB0aGUgZ3Jvd3RoIG9mIHRoZSB0b3RhbCBudWNsZWFyIHN0b2NrcGlsZSwgdGhleSBzdGlsbCByZW1haW4gdGhlIGNsZWFyIGxhcmdlc3Qgc2hhcmVob2xkZXJzIG9mIHRoZSBnbG9iYWwgYXRvbWljIGhvcmRlLg0KDQpBbmQgd2hpbGUgdGhlIHNjYWxlIG9mIHRoZSBvdmVyYWxsIG51Y2xlYXItYXJtcyByYWNlIGhhcyBkZWNyZWFzZWQgZHJhbWF0aWNhbGx5IHNpbmNlIHRoZSBsYXR0ZXIgaGFsZiBvZiB0aGUgQ29sZCBXYXIsIHJlZ2lvbmFsIHJhY2VzIGFyZSBzdGlsbCBvbmdvaW5nIGFuZCB0aGUgcmVhbCBsaWZlIHJhbWlmaWNhdGlvbnMgb2YgdGhlIHVzYWdlIG9mIG51Y2xlYXIgYXJtcyBjYW4gbm90IGJlIGNvbnZleWVkIHdpdGggdGhlIGRhdGEgdXNlZCBpbiB0aGlzIHByb2plY3QuDQoNCg0KDQoNCg==