github <- "https://raw.githubusercontent.com/RobWHickman/Databases-and-Files/"
ministers_github <- "master/Great%20Offices/Ministers.csv"
Ministers<- read.csv(paste0(github, ministers_github), stringsAsFactors = FALSE)
Ministers$Startdate <- as.Date(Ministers$Startdate)
library(ggplot2)
library(ggthemes)
library(RColorBrewer)
ggplot(Ministers, aes(Office)) +
geom_bar(aes(fill = Power), position = "dodge") +
scale_fill_brewer(palette = "Set2") +
theme_fivethirtyeight() +
theme(axis.text.x = element_text(angle = 45, hjust = 1)) +
ggtitle("The Great Offices of State",
"Number of Holders of Each Office since 1964")

ggplot(Ministers, aes(Office)) +
geom_bar(aes(fill = paste(Party, Power)), position = "dodge") +
scale_fill_manual(values = brewer.pal(10, "Set3")[c(5,3,4,6)],
guide = guide_legend(title = "Party/Power", ncol = 2)) +
theme_fivethirtyeight() +
theme(axis.text.x = element_text(angle = 45, hjust = 1)) +
ggtitle("The Great Offices of State",
"Number of Holders of Each Office since 1964")

library(stringr)
Ministers <- Ministers[order(Ministers$Startdate),]
duration_func <- function(party, power, office){
term <- paste (party, power, office)
which <- which(paste(Ministers$Party, Ministers$Power, Ministers$Office) == term)
if(grepl("Labour shadow", term)) which <- which[1:(length(which)- 1)]
if(grepl("Conservative government", term)) which <- which[1:(length(which)- 1)]
av_days <- mean(Ministers$Duration[which])
std <- var(Ministers$Duration[which])^0.5
return(c(Term = term,
Average_Days = av_days,
St_Dev = std))
}
durations <- unique(mapply(duration_func, Ministers$Party,
Ministers$Power,
Ministers$Office,
SIMPLIFY = F))
Durations <- do.call(rbind.data.frame,
c(durations, stringsAsFactors = FALSE))
names(Durations) <- c("Holder", "Duration", "Deviation")
Durations$Duration <- as.numeric(Durations$Duration)
Durations$Deviation <- as.numeric(Durations$Deviation)
Durations <- cbind(Durations, data.frame(
do.call(rbind, c(str_split(Durations$Holder, " ")))))
head(Durations)
limits <- aes(ymax = Durations$Duration + Durations$Deviation,
ymin = Durations$Duration - Durations$Deviation)
ggplot(Durations, aes(Holder, Duration)) +
geom_bar(aes(fill = paste(X1, X2), alpha = X3), stat = "identity", position = "dodge") +
scale_fill_manual(values = brewer.pal(10, "Set3")[c(5,3,4,6)],
guide = guide_legend(title = "Party/Power", ncol = 2)) +
scale_x_discrete(labels = rep(unique(Durations$X3), 4)) +
scale_alpha_manual(values = c("Home" = 0.7, "Foreign" = 0.6,
"Chancellor" = 0.7, "Leader" = 1), guide = "none") +
geom_errorbar(limits, position= "dodge", width=0.25) +
theme_fivethirtyeight() +
theme(axis.text.x = element_text(angle = 45, hjust = 1)) +
ggtitle("The Great Offices of State",
"Duration of Holders of Each Office since 1964 +/- std.")

library(ggrepel)
elections_github <- "master/Great%20Offices/Elections.csv"
Elections <- read.csv(paste0(github, elections_github), stringsAsFactors = FALSE)
Elections$Date <- as.Date(Elections$Date)
rectangles <- data.frame(xmin = Elections$Date,
xmax = append(Elections$Date[2:length(Elections$Date)], as.Date("2017-01-01")),
ymin = rep(0, length(Elections$Date)),
ymax = rep(max(Ministers$Duration) + 500, length(Elections$Date)),
Party <- Elections$Party)
rectangles$Cols <- gsub("Labour", "red", gsub("Conservative", "blue", rectangles$Party))
long <- Ministers[which(Ministers$Duration > 1825),]
ggplot(long) +
geom_rect(data=rectangles, aes(xmin=xmin, xmax=xmax, ymin=ymin, ymax=ymax),
fill= rectangles$Cols, alpha=0.05) +
geom_text_repel(aes(Startdate, Duration,
label = gsub(".* ", "", Name),
alpha = Power, colour = Party),
min.segment.length = unit(0.1, "lines")) +
scale_color_manual( values = brewer.pal(10, "Set3")[c(5,4)], guide = "none") +
scale_alpha_manual(values = c("government" = 1, "shadow" = 0.5)) +
geom_point(data = Ministers, aes(Startdate, Duration, colour = Party), alpha = 0.5) +
scale_x_date(date_breaks = "5 years", date_labels = "%Y") +
theme_fivethirtyeight() +
ggtitle("Longest Survivors in a Great Office",
subtitle = "Days in Post vs. Start Date since 1964")

extras_github <- "master/Great%20Offices/Extras.csv"
Extras <- read.csv(paste0(github, extras_github), stringsAsFactors = FALSE)
cols <- c("Name", "Office", "Duration", "Power", "Party")
Officers <- Ministers[cols]
Officers <- rbind(Officers, Extras)
duplicates <- which(duplicated(paste(Officers$Name, Officers$Office, Officers$Power)))
Officers <- Officers[-duplicates,]
Offices_Number <- data.frame(table(Officers$Name))
Offices_Number <- Offices_Number[order(-Offices_Number$Freq),]
head(Offices_Number, n = 10)
GovOffices_Number <- data.frame(table(paste0(Officers$Name, "_", Officers$Power)))
GovOffices_Number <- GovOffices_Number[order(-GovOffices_Number$Freq),]
GovOffices_Number <- GovOffices_Number[-grep("shadow", GovOffices_Number$Var1),]
GovOffices_Number$Var1 <- gsub("_.*", "", GovOffices_Number$Var1)
head(GovOffices_Number)
Officers <- Officers[which(Officers$Name %in% GovOffices_Number$Var1),]
levels(Officers$Power) <- c("shadow", "government")
ggplot(Officers, aes(x=reorder(Name, -table(Name)[Name]))) +
geom_bar(aes(fill = Party, alpha = factor(Power, levels = c("shadow", "government")))) +
scale_alpha_manual(values = c("government" = 1, "shadow" = 0.6), guide = guide_legend(title = "Power")) +
scale_fill_manual( values = brewer.pal(10, "Set3")[c(5,4)], guide = "none") +
theme_fivethirtyeight() +
theme(axis.text.x = element_text(angle = 45, hjust = 1, size = 7)) +
ggtitle("Holders of Most Great Offices of State",
subtitle = "People who Have Held at Least One Governmental Office Since 1964")

Officers <- Ministers[cols]
Officers <- rbind(Officers, Extras)
shad_rows <- which(Officers$Power == "shadow")
gov_rows <- which(Officers$Power == "government")
power_func <- function(name){
rows <- which(Officers$Name == name)
gov <- which(gov_rows %in% rows)
gov_days <- sum(Officers$Duration[gov_rows[gov]])
shad <- which(shad_rows %in% rows)
shad_days <- sum(Officers$Duration[shad_rows[shad]])
party <- unique(Officers$Party[rows])
return(c(Name = name,
Gov = gov_days,
Shad = shad_days,
Party = party))
}
Days <- do.call(rbind.data.frame, lapply(unique(Officers$Name), power_func))
names(Days) <- c("Name", "Government", "Shadow", "Party")
Days$Shadow <- as.numeric(as.character(Days$Shadow))
Days$Government <- as.numeric(as.character(Days$Government))
selected_names <- which(Days$Name %in% c("Margaret Thatcher", "Neil Kinnock", "Roy Hattersley", "Douglas Hurd", "Tony Blair", "Gordon Brown", "James Callaghan", "Harold Wilson", "Theresa May", "David Cameron", "George Osborne", "William Hague", "Edward Heath", "John Major"))
Days_Named <- Days[selected_names,]
ggplot(Days_Named, aes(x = Government, y = Shadow, colour = Party)) +
geom_point(data = Days) +
geom_text_repel(label = Days_Named$Name, min.segment.length = unit(0.1, "lines")) +
theme_fivethirtyeight() +
scale_colour_manual( values = brewer.pal(10, "Set3")[c(5,4)], guide = "none") +
scale_x_continuous(limits = c(0, 6000), breaks = seq(0, 6000, by = 1000)) +
scale_y_continuous(limits = c(0, 6000), breaks = seq(0, 6000, by = 1000)) +
ggtitle("Length of Governmental vs. Opposition Service",
subtitle = "Total Days Holding A Shadow Great Office vs. Governmental Great Office")

library(rgdal, quietly = TRUE)
map_github <- "master/Great%20Offices/compressedWestminster.zip"
url <- paste0(github, map_github)
tmp <- tempfile( fileext = ".zip" )
download.file(url, tmp, quiet = TRUE)
unzip(tmp, exdir = tempdir())
map <- readOGR(dsn = tempdir(), layer = "SimplifiedWestminster", verbose = FALSE)
plot(map)

LS0tCnRpdGxlOiAiUiBOb3RlYm9vayIKb3V0cHV0OiBodG1sX25vdGVib29rCi0tLQpgYGB7cn0KZ2l0aHViIDwtICJodHRwczovL3Jhdy5naXRodWJ1c2VyY29udGVudC5jb20vUm9iV0hpY2ttYW4vRGF0YWJhc2VzLWFuZC1GaWxlcy8iCiAgbWluaXN0ZXJzX2dpdGh1YiA8LSAibWFzdGVyL0dyZWF0JTIwT2ZmaWNlcy9NaW5pc3RlcnMuY3N2IgogIApNaW5pc3RlcnM8LSByZWFkLmNzdihwYXN0ZTAoZ2l0aHViLCBtaW5pc3RlcnNfZ2l0aHViKSwgc3RyaW5nc0FzRmFjdG9ycyA9IEZBTFNFKQogIE1pbmlzdGVycyRTdGFydGRhdGUgPC0gYXMuRGF0ZShNaW5pc3RlcnMkU3RhcnRkYXRlKQpgYGAKCmBgYHtyLG1lc3NhZ2U9RkFMU0Usd2FybmluZz1GQUxTRX0KbGlicmFyeShnZ3Bsb3QyKQpsaWJyYXJ5KGdndGhlbWVzKQpsaWJyYXJ5KFJDb2xvckJyZXdlcikKCmdncGxvdChNaW5pc3RlcnMsIGFlcyhPZmZpY2UpKSArCiAgZ2VvbV9iYXIoYWVzKGZpbGwgPSBQb3dlciksIHBvc2l0aW9uID0gImRvZGdlIikgKwogIHNjYWxlX2ZpbGxfYnJld2VyKHBhbGV0dGUgPSAiU2V0MiIpICsKICB0aGVtZV9maXZldGhpcnR5ZWlnaHQoKSArCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA0NSwgaGp1c3QgPSAxKSkgKwogIGdndGl0bGUoIlRoZSBHcmVhdCBPZmZpY2VzIG9mIFN0YXRlIiwKICAgICAgICAgICJOdW1iZXIgb2YgSG9sZGVycyBvZiBFYWNoIE9mZmljZSBzaW5jZSAxOTY0IikKCmdncGxvdChNaW5pc3RlcnMsIGFlcyhPZmZpY2UpKSArCiAgZ2VvbV9iYXIoYWVzKGZpbGwgPSBwYXN0ZShQYXJ0eSwgUG93ZXIpKSwgcG9zaXRpb24gPSAiZG9kZ2UiKSArCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gYnJld2VyLnBhbCgxMCwgIlNldDMiKVtjKDUsMyw0LDYpXSwKICAgICAgICAgICAgICAgICAgICBndWlkZSA9IGd1aWRlX2xlZ2VuZCh0aXRsZSA9ICJQYXJ0eS9Qb3dlciIsIG5jb2wgPSAyKSkgKwogIHRoZW1lX2ZpdmV0aGlydHllaWdodCgpICsKICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDQ1LCBoanVzdCA9IDEpKSArCiAgZ2d0aXRsZSgiVGhlIEdyZWF0IE9mZmljZXMgb2YgU3RhdGUiLAogICAgICAgICAgIk51bWJlciBvZiBIb2xkZXJzIG9mIEVhY2ggT2ZmaWNlIHNpbmNlIDE5NjQiKQpgYGAKYGBge3IsbWVzc2FnZT1GQUxTRSx3YXJuaW5nPUZBTFNFfQpsaWJyYXJ5KHN0cmluZ3IpCgpNaW5pc3RlcnMgPC0gTWluaXN0ZXJzW29yZGVyKE1pbmlzdGVycyRTdGFydGRhdGUpLF0KCmR1cmF0aW9uX2Z1bmMgPC0gZnVuY3Rpb24ocGFydHksIHBvd2VyLCBvZmZpY2UpewogICAgdGVybSA8LSBwYXN0ZSAocGFydHksIHBvd2VyLCBvZmZpY2UpCiAgICB3aGljaCA8LSB3aGljaChwYXN0ZShNaW5pc3RlcnMkUGFydHksIE1pbmlzdGVycyRQb3dlciwgTWluaXN0ZXJzJE9mZmljZSkgPT0gdGVybSkKICAgICAgaWYoZ3JlcGwoIkxhYm91ciBzaGFkb3ciLCB0ZXJtKSkgd2hpY2ggPC0gd2hpY2hbMToobGVuZ3RoKHdoaWNoKS0gMSldCiAgICAgIGlmKGdyZXBsKCJDb25zZXJ2YXRpdmUgZ292ZXJubWVudCIsIHRlcm0pKSB3aGljaCA8LSB3aGljaFsxOihsZW5ndGgod2hpY2gpLSAxKV0KICAgIGF2X2RheXMgPC0gbWVhbihNaW5pc3RlcnMkRHVyYXRpb25bd2hpY2hdKQogICAgc3RkIDwtIHZhcihNaW5pc3RlcnMkRHVyYXRpb25bd2hpY2hdKV4wLjUKICAgIHJldHVybihjKFRlcm0gPSB0ZXJtLAogICAgICAgICAgICAgQXZlcmFnZV9EYXlzID0gYXZfZGF5cywKICAgICAgICAgICAgIFN0X0RldiA9IHN0ZCkpCn0KCmR1cmF0aW9ucyA8LSB1bmlxdWUobWFwcGx5KGR1cmF0aW9uX2Z1bmMsIE1pbmlzdGVycyRQYXJ0eSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgTWluaXN0ZXJzJFBvd2VyLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBNaW5pc3RlcnMkT2ZmaWNlLAogICAgICAgICAgICAgICAgICAgIFNJTVBMSUZZID0gRikpCkR1cmF0aW9ucyA8LSBkby5jYWxsKHJiaW5kLmRhdGEuZnJhbWUsCiAgICAgICAgICAgICAgICAgICAgIGMoZHVyYXRpb25zLCBzdHJpbmdzQXNGYWN0b3JzID0gRkFMU0UpKQogIG5hbWVzKER1cmF0aW9ucykgPC0gYygiSG9sZGVyIiwgIkR1cmF0aW9uIiwgIkRldmlhdGlvbiIpCiAgRHVyYXRpb25zJER1cmF0aW9uIDwtIGFzLm51bWVyaWMoRHVyYXRpb25zJER1cmF0aW9uKQogIER1cmF0aW9ucyREZXZpYXRpb24gPC0gYXMubnVtZXJpYyhEdXJhdGlvbnMkRGV2aWF0aW9uKQogIER1cmF0aW9ucyA8LSBjYmluZChEdXJhdGlvbnMsIGRhdGEuZnJhbWUoCiAgICAgICAgICAgICAgICBkby5jYWxsKHJiaW5kLCBjKHN0cl9zcGxpdChEdXJhdGlvbnMkSG9sZGVyLCAiICIpKSkpKSAgICAgICAgCiAgaGVhZChEdXJhdGlvbnMpCmBgYAoKYGBge3J9CgpsaW1pdHMgPC0gYWVzKHltYXggPSBEdXJhdGlvbnMkRHVyYXRpb24gKyBEdXJhdGlvbnMkRGV2aWF0aW9uLAogICAgICAgICAgICAgIHltaW4gPSBEdXJhdGlvbnMkRHVyYXRpb24gLSBEdXJhdGlvbnMkRGV2aWF0aW9uKQoKZ2dwbG90KER1cmF0aW9ucywgYWVzKEhvbGRlciwgRHVyYXRpb24pKSArCiAgZ2VvbV9iYXIoYWVzKGZpbGwgPSBwYXN0ZShYMSwgWDIpLCBhbHBoYSA9IFgzKSwgc3RhdCA9ICJpZGVudGl0eSIsIHBvc2l0aW9uID0gImRvZGdlIikgKwogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IGJyZXdlci5wYWwoMTAsICJTZXQzIilbYyg1LDMsNCw2KV0sCiAgICAgICAgICAgICAgICAgICAgZ3VpZGUgPSBndWlkZV9sZWdlbmQodGl0bGUgPSAiUGFydHkvUG93ZXIiLCBuY29sID0gMikpICsKICBzY2FsZV94X2Rpc2NyZXRlKGxhYmVscyA9IHJlcCh1bmlxdWUoRHVyYXRpb25zJFgzKSwgNCkpICsKICBzY2FsZV9hbHBoYV9tYW51YWwodmFsdWVzID0gYygiSG9tZSIgPSAwLjcsICJGb3JlaWduIiA9IDAuNiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkNoYW5jZWxsb3IiID0gMC43LCAiTGVhZGVyIiA9IDEpLCBndWlkZSA9ICJub25lIikgKwogIGdlb21fZXJyb3JiYXIobGltaXRzLCBwb3NpdGlvbj0gImRvZGdlIiwgd2lkdGg9MC4yNSkgKwogIHRoZW1lX2ZpdmV0aGlydHllaWdodCgpICsKICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDQ1LCBoanVzdCA9IDEpKSArCiAgZ2d0aXRsZSgiVGhlIEdyZWF0IE9mZmljZXMgb2YgU3RhdGUiLAogICAgICAgICAgIkR1cmF0aW9uIG9mIEhvbGRlcnMgb2YgRWFjaCBPZmZpY2Ugc2luY2UgMTk2NCArLy0gc3RkLiIpCgpgYGAKCmBgYHtyfQpsaWJyYXJ5KGdncmVwZWwpCgplbGVjdGlvbnNfZ2l0aHViIDwtICJtYXN0ZXIvR3JlYXQlMjBPZmZpY2VzL0VsZWN0aW9ucy5jc3YiCkVsZWN0aW9ucyA8LSByZWFkLmNzdihwYXN0ZTAoZ2l0aHViLCBlbGVjdGlvbnNfZ2l0aHViKSwgc3RyaW5nc0FzRmFjdG9ycyA9IEZBTFNFKQogIEVsZWN0aW9ucyREYXRlIDwtIGFzLkRhdGUoRWxlY3Rpb25zJERhdGUpCgpyZWN0YW5nbGVzIDwtIGRhdGEuZnJhbWUoeG1pbiA9IEVsZWN0aW9ucyREYXRlLAogIHhtYXggPSBhcHBlbmQoRWxlY3Rpb25zJERhdGVbMjpsZW5ndGgoRWxlY3Rpb25zJERhdGUpXSwgYXMuRGF0ZSgiMjAxNy0wMS0wMSIpKSwKICB5bWluID0gcmVwKDAsIGxlbmd0aChFbGVjdGlvbnMkRGF0ZSkpLAogIHltYXggPSByZXAobWF4KE1pbmlzdGVycyREdXJhdGlvbikgKyA1MDAsIGxlbmd0aChFbGVjdGlvbnMkRGF0ZSkpLAogIFBhcnR5IDwtIEVsZWN0aW9ucyRQYXJ0eSkKCnJlY3RhbmdsZXMkQ29scyA8LSBnc3ViKCJMYWJvdXIiLCAicmVkIiwgZ3N1YigiQ29uc2VydmF0aXZlIiwgImJsdWUiLCByZWN0YW5nbGVzJFBhcnR5KSkKCmxvbmcgPC0gTWluaXN0ZXJzW3doaWNoKE1pbmlzdGVycyREdXJhdGlvbiA+IDE4MjUpLF0KCmdncGxvdChsb25nKSArCiAgZ2VvbV9yZWN0KGRhdGE9cmVjdGFuZ2xlcywgYWVzKHhtaW49eG1pbiwgeG1heD14bWF4LCB5bWluPXltaW4sIHltYXg9eW1heCksIAogICAgICAgICAgICBmaWxsPSByZWN0YW5nbGVzJENvbHMsIGFscGhhPTAuMDUpICsKICBnZW9tX3RleHRfcmVwZWwoYWVzKFN0YXJ0ZGF0ZSwgRHVyYXRpb24sIAogICAgICAgICAgICAgICAgICAgICAgbGFiZWwgPSBnc3ViKCIuKiAiLCAiIiwgTmFtZSksCiAgICAgICAgICAgICAgICAgICAgICBhbHBoYSA9IFBvd2VyLCBjb2xvdXIgPSBQYXJ0eSksCiAgICAgICAgICAgICAgICAgIG1pbi5zZWdtZW50Lmxlbmd0aCA9IHVuaXQoMC4xLCAibGluZXMiKSkgKwogIHNjYWxlX2NvbG9yX21hbnVhbCggdmFsdWVzID0gYnJld2VyLnBhbCgxMCwgIlNldDMiKVtjKDUsNCldLCBndWlkZSA9ICJub25lIikgKwogIHNjYWxlX2FscGhhX21hbnVhbCh2YWx1ZXMgPSBjKCJnb3Zlcm5tZW50IiA9IDEsICJzaGFkb3ciID0gMC41KSkgKwogIGdlb21fcG9pbnQoZGF0YSA9IE1pbmlzdGVycywgYWVzKFN0YXJ0ZGF0ZSwgRHVyYXRpb24sIGNvbG91ciA9IFBhcnR5KSwgYWxwaGEgPSAwLjUpICsKICBzY2FsZV94X2RhdGUoZGF0ZV9icmVha3MgPSAiNSB5ZWFycyIsIGRhdGVfbGFiZWxzID0gIiVZIikgKwogIHRoZW1lX2ZpdmV0aGlydHllaWdodCgpICsKICBnZ3RpdGxlKCJMb25nZXN0IFN1cnZpdm9ycyBpbiBhIEdyZWF0IE9mZmljZSIsCiAgICAgICAgICBzdWJ0aXRsZSA9ICJEYXlzIGluIFBvc3QgdnMuIFN0YXJ0IERhdGUgc2luY2UgMTk2NCIpCmBgYApgYGB7cn0KZXh0cmFzX2dpdGh1YiA8LSAibWFzdGVyL0dyZWF0JTIwT2ZmaWNlcy9FeHRyYXMuY3N2IgpFeHRyYXMgPC0gcmVhZC5jc3YocGFzdGUwKGdpdGh1YiwgZXh0cmFzX2dpdGh1YiksIHN0cmluZ3NBc0ZhY3RvcnMgPSBGQUxTRSkKCmNvbHMgPC0gYygiTmFtZSIsICJPZmZpY2UiLCAiRHVyYXRpb24iLCAiUG93ZXIiLCAiUGFydHkiKQpPZmZpY2VycyA8LSBNaW5pc3RlcnNbY29sc10KICBPZmZpY2VycyA8LSByYmluZChPZmZpY2VycywgRXh0cmFzKQogIGR1cGxpY2F0ZXMgPC0gd2hpY2goZHVwbGljYXRlZChwYXN0ZShPZmZpY2VycyROYW1lLCBPZmZpY2VycyRPZmZpY2UsIE9mZmljZXJzJFBvd2VyKSkpCiAgT2ZmaWNlcnMgPC0gT2ZmaWNlcnNbLWR1cGxpY2F0ZXMsXQoKT2ZmaWNlc19OdW1iZXIgPC0gZGF0YS5mcmFtZSh0YWJsZShPZmZpY2VycyROYW1lKSkKICBPZmZpY2VzX051bWJlciA8LSBPZmZpY2VzX051bWJlcltvcmRlcigtT2ZmaWNlc19OdW1iZXIkRnJlcSksXQogIGhlYWQoT2ZmaWNlc19OdW1iZXIsIG4gPSAxMCkKCkdvdk9mZmljZXNfTnVtYmVyIDwtIGRhdGEuZnJhbWUodGFibGUocGFzdGUwKE9mZmljZXJzJE5hbWUsICJfIiwgT2ZmaWNlcnMkUG93ZXIpKSkKICBHb3ZPZmZpY2VzX051bWJlciA8LSBHb3ZPZmZpY2VzX051bWJlcltvcmRlcigtR292T2ZmaWNlc19OdW1iZXIkRnJlcSksXQogIEdvdk9mZmljZXNfTnVtYmVyIDwtIEdvdk9mZmljZXNfTnVtYmVyWy1ncmVwKCJzaGFkb3ciLCBHb3ZPZmZpY2VzX051bWJlciRWYXIxKSxdCiAgR292T2ZmaWNlc19OdW1iZXIkVmFyMSA8LSBnc3ViKCJfLioiLCAiIiwgR292T2ZmaWNlc19OdW1iZXIkVmFyMSkKICBoZWFkKEdvdk9mZmljZXNfTnVtYmVyKQogIApPZmZpY2VycyA8LSBPZmZpY2Vyc1t3aGljaChPZmZpY2VycyROYW1lICVpbiUgR292T2ZmaWNlc19OdW1iZXIkVmFyMSksXQogIGxldmVscyhPZmZpY2VycyRQb3dlcikgPC0gYygic2hhZG93IiwgImdvdmVybm1lbnQiKQoKCgpnZ3Bsb3QoT2ZmaWNlcnMsIGFlcyh4PXJlb3JkZXIoTmFtZSwgLXRhYmxlKE5hbWUpW05hbWVdKSkpICsKICAgIGdlb21fYmFyKGFlcyhmaWxsID0gUGFydHksIGFscGhhID0gZmFjdG9yKFBvd2VyLCBsZXZlbHMgPSBjKCJzaGFkb3ciLCAiZ292ZXJubWVudCIpKSkpICsKICAgIHNjYWxlX2FscGhhX21hbnVhbCh2YWx1ZXMgPSBjKCJnb3Zlcm5tZW50IiA9IDEsICJzaGFkb3ciID0gMC42KSwgZ3VpZGUgPSBndWlkZV9sZWdlbmQodGl0bGUgPSAiUG93ZXIiKSkgKwogICAgc2NhbGVfZmlsbF9tYW51YWwoIHZhbHVlcyA9IGJyZXdlci5wYWwoMTAsICJTZXQzIilbYyg1LDQpXSwgZ3VpZGUgPSAibm9uZSIpICsKICAgIHRoZW1lX2ZpdmV0aGlydHllaWdodCgpICsKICAgIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gNDUsIGhqdXN0ID0gMSwgc2l6ZSA9IDcpKSArCiAgICBnZ3RpdGxlKCJIb2xkZXJzIG9mIE1vc3QgR3JlYXQgT2ZmaWNlcyBvZiBTdGF0ZSIsCiAgICAgICAgICAgIHN1YnRpdGxlID0gIlBlb3BsZSB3aG8gSGF2ZSBIZWxkIGF0IExlYXN0IE9uZSBHb3Zlcm5tZW50YWwgT2ZmaWNlIFNpbmNlIDE5NjQiKQoKYGBgCmBgYHtyfQoKT2ZmaWNlcnMgPC0gTWluaXN0ZXJzW2NvbHNdCiAgICBPZmZpY2VycyA8LSByYmluZChPZmZpY2VycywgRXh0cmFzKQoKc2hhZF9yb3dzIDwtIHdoaWNoKE9mZmljZXJzJFBvd2VyID09ICJzaGFkb3ciKQpnb3Zfcm93cyA8LSB3aGljaChPZmZpY2VycyRQb3dlciA9PSAiZ292ZXJubWVudCIpCgpwb3dlcl9mdW5jIDwtIGZ1bmN0aW9uKG5hbWUpewogIHJvd3MgPC0gd2hpY2goT2ZmaWNlcnMkTmFtZSA9PSBuYW1lKQogIGdvdiA8LSB3aGljaChnb3Zfcm93cyAlaW4lIHJvd3MpCiAgICBnb3ZfZGF5cyA8LSBzdW0oT2ZmaWNlcnMkRHVyYXRpb25bZ292X3Jvd3NbZ292XV0pCiAgc2hhZCA8LSB3aGljaChzaGFkX3Jvd3MgJWluJSByb3dzKQogICAgc2hhZF9kYXlzIDwtIHN1bShPZmZpY2VycyREdXJhdGlvbltzaGFkX3Jvd3Nbc2hhZF1dKQogIHBhcnR5IDwtIHVuaXF1ZShPZmZpY2VycyRQYXJ0eVtyb3dzXSkKICByZXR1cm4oYyhOYW1lID0gbmFtZSwKICAgICAgICAgICBHb3YgPSBnb3ZfZGF5cywKICAgICAgICAgICBTaGFkID0gc2hhZF9kYXlzLAogICAgICAgICAgIFBhcnR5ID0gcGFydHkpKQp9CgpEYXlzIDwtIGRvLmNhbGwocmJpbmQuZGF0YS5mcmFtZSwgbGFwcGx5KHVuaXF1ZShPZmZpY2VycyROYW1lKSwgcG93ZXJfZnVuYykpCiAgbmFtZXMoRGF5cykgPC0gYygiTmFtZSIsICJHb3Zlcm5tZW50IiwgIlNoYWRvdyIsICJQYXJ0eSIpCiAgRGF5cyRTaGFkb3cgPC0gYXMubnVtZXJpYyhhcy5jaGFyYWN0ZXIoRGF5cyRTaGFkb3cpKQogIERheXMkR292ZXJubWVudCA8LSBhcy5udW1lcmljKGFzLmNoYXJhY3RlcihEYXlzJEdvdmVybm1lbnQpKQoKc2VsZWN0ZWRfbmFtZXMgPC0gd2hpY2goRGF5cyROYW1lICVpbiUgYygiTWFyZ2FyZXQgVGhhdGNoZXIiLCAiTmVpbCBLaW5ub2NrIiwgIlJveSBIYXR0ZXJzbGV5IiwgIkRvdWdsYXMgSHVyZCIsICJUb255IEJsYWlyIiwgIkdvcmRvbiBCcm93biIsICJKYW1lcyBDYWxsYWdoYW4iLCAiSGFyb2xkIFdpbHNvbiIsICJUaGVyZXNhIE1heSIsICJEYXZpZCBDYW1lcm9uIiwgIkdlb3JnZSBPc2Jvcm5lIiwgIldpbGxpYW0gSGFndWUiLCAiRWR3YXJkIEhlYXRoIiwgIkpvaG4gTWFqb3IiKSkKRGF5c19OYW1lZCA8LSBEYXlzW3NlbGVjdGVkX25hbWVzLF0KCmdncGxvdChEYXlzX05hbWVkLCBhZXMoeCA9IEdvdmVybm1lbnQsIHkgPSBTaGFkb3csIGNvbG91ciA9IFBhcnR5KSkgKwogIGdlb21fcG9pbnQoZGF0YSA9IERheXMpICsKICBnZW9tX3RleHRfcmVwZWwobGFiZWwgPSBEYXlzX05hbWVkJE5hbWUsIG1pbi5zZWdtZW50Lmxlbmd0aCA9IHVuaXQoMC4xLCAibGluZXMiKSkgKwogIHRoZW1lX2ZpdmV0aGlydHllaWdodCgpICsKICBzY2FsZV9jb2xvdXJfbWFudWFsKCB2YWx1ZXMgPSBicmV3ZXIucGFsKDEwLCAiU2V0MyIpW2MoNSw0KV0sIGd1aWRlID0gIm5vbmUiKSArCiAgc2NhbGVfeF9jb250aW51b3VzKGxpbWl0cyA9IGMoMCwgNjAwMCksIGJyZWFrcyA9IHNlcSgwLCA2MDAwLCBieSA9IDEwMDApKSArCiAgc2NhbGVfeV9jb250aW51b3VzKGxpbWl0cyA9IGMoMCwgNjAwMCksIGJyZWFrcyA9IHNlcSgwLCA2MDAwLCBieSA9IDEwMDApKSArCiAgZ2d0aXRsZSgiTGVuZ3RoIG9mIEdvdmVybm1lbnRhbCB2cy4gT3Bwb3NpdGlvbiBTZXJ2aWNlIiwKICAgICAgICAgIHN1YnRpdGxlID0gIlRvdGFsIERheXMgSG9sZGluZyBBIFNoYWRvdyBHcmVhdCBPZmZpY2UgdnMuIEdvdmVybm1lbnRhbCBHcmVhdCBPZmZpY2UiKQpgYGAKCgpgYGB7cixtZXNzYWdlPUZBTFNFLHdhcm5pbmc9RkFMU0UsIGZpZy53aWR0aD0gMTAsIGZpZy5oZWlnaHQ9MTB9CmxpYnJhcnkocmdkYWwsIHF1aWV0bHkgPSBUUlVFKQptYXBfZ2l0aHViIDwtICJtYXN0ZXIvR3JlYXQlMjBPZmZpY2VzL2NvbXByZXNzZWRXZXN0bWluc3Rlci56aXAiCgp1cmwgPC0gcGFzdGUwKGdpdGh1YiwgbWFwX2dpdGh1YikKdG1wIDwtIHRlbXBmaWxlKCBmaWxlZXh0ID0gIi56aXAiICkKZG93bmxvYWQuZmlsZSh1cmwsIHRtcCwgcXVpZXQgPSBUUlVFKQp1bnppcCh0bXAsIGV4ZGlyID0gdGVtcGRpcigpKSAKCm1hcCA8LSByZWFkT0dSKGRzbiA9IHRlbXBkaXIoKSwgbGF5ZXIgPSAiU2ltcGxpZmllZFdlc3RtaW5zdGVyIiwgdmVyYm9zZSA9IEZBTFNFKQoKcGxvdChtYXApCmBgYAoK