The National- The Reynes of Castamere
I wanted to play around with the excellent networkD3 package some more and decided to try and map out the books behind the Game of Thrones TV series. I was interested as a fan of the books, but also because of the sheer number of characters that appear and weave in and out of the story.
This has been done before but only for one book (as far as I can tell) and it seemed simple enough to do it for the rest.
First get the links to each chapter from towerofthehand.com
library(rvest)
library(RCurl)
library(magrittr)
base_url <- "http://towerofthehand.com"
suffix_url <- "/index.html"
#loop for url for all 5 books
for (book in 1:5){
url <- paste0(base_url, "/books/10", book, suffix_url)
ifelse(!exists("book_urls"),
book_urls <- url,
book_urls <- append(book_urls, url))
}
rm(suffix_url)
#get the linksfor every chapter
chapter_func <- function(book_url){
read <- read_html(book_url)
nodes <- read %>% html_nodes(".binding .chaptergrid a")
links <- paste0(base_url, nodes %>% html_attr("href"))
return(links)
}
chapter_urls <- unlist(lapply(book_urls, chapter_func))
#later we'll also want the number of chapters/book
#To spare scraping again/ more complicated here they are
books <- data.frame(book = c(1:5),
chapters = c(73, 70, 82, 46, 73),
title = c("A Game of Thrones", "A Clash of Kings",
"A Storm of Swords", "A Feast for Crows",
"A Dance with Dragons"))
Then get list of all characters that appear in these chapters. There’s a little complication in that some characters are duplicated (e.g. there are three characters named “Walder Frey” because the original is a complete narcissist) so we get the unique links, THEN the names
#get the characters in each chapter
character_func <- function(chapter_url){
read <- read_html(chapter_url)
nodes <- read %>% html_nodes("#appearances > ol > li > a")
character_urls <- paste0("https://towerofthehand.com", nodes %>% html_attr("href"))
return(character_urls)
}
character_urls <- lapply(chapter_urls, character_func)
all_characters <- unlist(character_urls)
#get the names of each character from their links
names_func <- function(character_url){
read <- read_html(character_url)
nodes <- read %>% html_nodes("#headline > h2")
names <- nodes %>% html_text()
return(names)
}
names <- lapply(unique(all_characters), names_func)
Characters <- data.frame(character = unlist(names), links = unique(all_characters))
Characters$character <- make.unique(as.character(Characters$character))
Print the characters using table() and get and idea of how often each appears
#how often each character appears
head(table(all_characters))
all_characters
https://towerofthehand.com/reference/k/00002/index.html
2
https://towerofthehand.com/reference/k/00006/index.html
7
https://towerofthehand.com/reference/k/00011/index.html
29
https://towerofthehand.com/reference/k/00012/index.html
1
https://towerofthehand.com/reference/k/00013/index.html
24
https://towerofthehand.com/reference/k/00015/index.html
10
#the total number of unique characters
print(paste("There are", length(unique(all_characters)),
"named characters in the Song of Ice and Fire series"))
[1] "There are 1152 named characters in the Song of Ice and Fire series"
Then make an empty data frame to pass these characters appearances into
#make an empty data frame of characters = rows and chapters = columns
chapter_df <- data.frame(matrix(NA,
nrow = length(unique(all_characters)),
ncol = length(chapter_urls)))
row_names <- unique(all_characters)
rownames(chapter_df) <- row_names
col_names <- 1:(length(chapter_urls))
colnames(chapter_df) <- col_names
And run the function where a “1” means that character is in that chapter
#find which chapter each character appears in
#represented as "1" in chapter_df
for (character in 1:nrow(chapter_df)){
name <- rownames(chapter_df)[character]
chapter_df[character, grep(name, character_urls)] <- 1
}
#every cell that isn't 1 is 0
chapter_df[is.na(chapter_df)] <- 0
For each character, this function then find how often every character co-occurs with every other character. Given it has to connect each of 1111 characters to the other 1110 it takes a while (a few hours) to run and gives a data frame of each source, target and “value” (how often the character co-occur).
I’ve included to code I used for error checking and in case you want to do it yourself. However, in running the script I will download the .csv I uploaded to my GitHub
#find how often each character co-occurs with every other character
#for (protag in 1:nrow(chapter_df)){
# name1 <- rownames(chapter_df)[protag]
# for (other in (protag + 1):nrow(chapter_df)){
# name2 <- rownames(chapter_df)[other]
# connection <- length(which(
# chapter_df[protag,] == 1 &
# chapter_df[other,] == 1))
#
# if(connection > 0){
# newrow <- data.frame(source = name1,
# target = name2,
# value = connection)
# ifelse(!exists("Links"),
# Links <- newrow,
# Links <- rbind(Links, newrow))
# }
# }
#}
#load the Links file from my GitHub
Github <- "https://raw.githubusercontent.com/RobWHickman/"
Project <- "Databases-and-Files/master/GoT-Network/"
Network_file <- paste0(Github, Project, "GoT-Network.csv")
Links <- read.csv(Network_file, stringsAsFactors = FALSE)
To produce the network, the Nodes are also needed
#get a df of each character and their frequency
Nodes <- data.frame(table(all_characters))
#add in a size column for the nodes we plot
Nodes$size <- (Nodes$Freq^2)/8
#change names from urls to character names
Nodes$all_characters <- as.character(Nodes$all_characters)
colnames(Nodes)[1] <- "name"
for (character in 1:nrow(Nodes)){
Nodes$name[character] <- Characters$character[which(Nodes$name[character] == Characters$links)]
}
#get "actual" names (i.e. remove unduplication) and surnames
Nodes$duplicatenames <- gsub("\\..*", "", Nodes$name)
Nodes$surname <- gsub(".* ", "", Nodes$name)
Nodes$surname[which(Nodes$surname == Nodes$duplicatenames)] <- "no surname"
head(Nodes)
I wanted to use each person’s house to colour them. First get the Houses
#get every House in the series
houses_url <- "http://towerofthehand.com/books/houses.html"
houses_read <- read_html(houses_url)
houses_nodes <- houses_read %>% html_nodes("td:nth-child(2) a , td:nth-child(4) a , td:nth-child(6) a")
houses_names <- unique(houses_nodes %>% html_text())
#there are two Houses called "Fossoway"
#to avoid annoyance, take it out now and bind it back later
houses_names <- houses_names[-c(which(houses_names == "Fossoway"))]
#get the links to each House's page
links_func <- function(html, house_name){
paste0("http://towerofthehand.com",
html %>%
html_nodes(xpath=paste0('//a[text()="', house_name, '"]')) %>%
html_attr("href"))
}
house_links <- sapply(houses_names, function(x)links_func(houses_read, x))
#make a df of the House names and links
house <- data.frame(house = as.character(houses_names),
link = as.character(unlist(house_links)))
#add the Fossoway House back in
Fossoways <- data.frame(house = "Fossoway",
link = "http://towerofthehand.com/reference/k/02044/index.html")
house <- rbind(house, Fossoways)
house$surname <- gsub(" .*", "", house$house)
#remove Houses that will form duplicates when trying to find a character's House
remove <- c(which(house$house == "Arryn of Gulltown"),
which(house$house == "Brune of Brownhollow"),
which(house$house == "Baratheon of Dragonstone"),
which(house$house == "Baratheon of King's Landing"),
which(house$house == "Dayne of High Hermitage"),
which(house$house == "Farwynd of Sealskin Point"),
which(house$house == "Goodbrother of Shatterstone"),
which(house$house == "Goodbrother of Orkmont"),
which(house$house == "Kenning of Kayce"),
which(house$house == "Lannister of Lannisport"),
which(house$house == "Royce of Runestone"),
which(house$house == "Vance of Wayfarer's Rest"))
house <- house[-c(remove),]
Each House has a sigil. To get the colours we download this sigil and use RImagePalette to extract a single colour that is representative
library(jpeg)
library(RImagePalette)
#download each House's sigil and get a colour
colour_func <- function(house_link){
read <- read_html(as.character(house_link))
Cnodes <- read %>% html_nodes("div.linear-rail > div:nth-child(2) > div > a > img")
link <- Cnodes %>% html_attr("src")
#only download a file and extract colour for those Houses that have a sigil posted
if(!identical(link, character(0))){
download.file(link, "arms.jpg", mode = "wb", quiet = TRUE)
}
if(!identical(link, character(0))){
img <- readJPEG("arms.jpg")
}
ifelse(identical(link, character(0)),
#if there's no sigil, use black
colour <- "#000000",
colour <- image_palette(img, n=1))
Rnodes <- read %>% html_nodes("div:nth-child(2) > div.linear-rail > div.title > span")
region <- gsub(".* ", "", Rnodes %>% html_text())
return(c(colour, region))
}
housecolours <- do.call("rbind", lapply(house$link, colour_func))
colnames(housecolours) <- c("colours", "region")
house <- cbind(house, housecolours)
#plot a pie chart of all the Houses and their "colour"
pie(rep(1, length(house$colours)), col = house$colours,
main = "House Colours", labels = house$house)

It was about this point I realised passing colours to Nodes in forceNetwork() isn’t so easy. The House colours will come in useful when I plot using igraph later, but for NetworkD3, I also scraped the “location” of each House (which of the 7 Kingdoms it is based). This is the “region” return in the colour_func().
Unfortunately, some Houses don’t have a region listed (doing some research it seems that it is unknown) so we’ll leave those as “Westeros.” For some others the function doesn’t quite find what we’re looking for, or the information is incorrect, so some quick gsubs are necessary
#gsub incorrect region data
house$region <- as.character(house$region)
house$region[which(house$region == "Farwynd.")] <- "Islands."
house$region[which(house$region == "Cronwlands.")] <- "Crownlands."
house$region[which(house$region == "Stark.")] <- "North."
house$region[which(house$region == 'Us."')] <- "Islands."
house$region[which(house$region == "house.")] <- "Crownlands."
house$region[which(house$house == "Woolfield")] <- "North."
house$region[which(house$region == "Rebellion.")] <- "Crownlands."
table(house$region)
Crownlands. Dorne. Islands. North. Reach. Riverlands. Stormlands.
34 18 26 30 54 27 27
Vale. Westerlands. Westeros.
27 34 9
#plot a pie chart of all the Houses and their "region"
regions <- data.frame(table(house$region))
pie(regions$Freq, labels = regions$Var1,
main = "Locations of Houses")

Add this colour/region information to each node using a quick lookup function
#add the colour/region to each character in the Node df
node_func <- function(name){
region <- house$region[which(house$surname == name)]
ifelse(length(region) > 0,
region <- unlist(region),
region <- "none")
colour <- house$colours[which(house$surname == name)]
ifelse(length(colour) > 0,
colour <- unlist(colour),
colour <- "#000000")
return(c(colour, region))
}
colourinfo <- do.call("rbind", lapply(Nodes$surname, node_func))
colnames(colourinfo) <- c("colour", "region")
#cbind it to the Nodes
#Nodes <- cbind(Nodes, colourinfo)
head(Nodes)
Before plotting, the names in the Links df need to be indexed to the rownames for the Nodes. Again, just use a simple lookup loop to do this.
And then plot using forceNetwork() from networkD3. I’m far from an expert at this so there’s probably some more that can be done to make the network clearer/ more aesthetic, but for now I’m not displeased with the results.
If you just want to see the output network, you can find it at my rPubs page
library(networkD3)
#networkD3 uses zero-indexing
for (node in 1:nrow(Nodes)){
Norder <- which(Nodes$name[node] == Characters$character) - 1
ifelse(node < 2, order <- Norder, order <- append(order, Norder))
}
Nodes$order <- order
rownames(Nodes) <- Nodes$order
Nodes <- Nodes[order(Nodes$order),]
Links$source <- as.numeric(Links$source) -1
Links$target <- as.numeric(Links$target) -1
#plot it!
#very large file
#forceNetwork(Links = Links, Nodes = Nodes, NodeID = "duplicatenames", Group = "region", Source = "source", Target = "target", Value = "value", zoom = TRUE, Nodesize = "size", fontSize = 30, linkColour = "#d8d8d8", opacity = 0.8, linkDistance = networkD3::JS("function(d) { return 100*d.value; }"), linkWidth = networkD3::JS("function(d) { return d.value/5; }"), charge = -100, legend = TRUE, colourScale = JS("d3.scale.category20()"))
LS0tCnRpdGxlOiAiQSBQbG90IG9mIE5ldHdvcmtzIChwYXJ0IDEpIgpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sKLS0tCltUaGUgTmF0aW9uYWwtIFRoZSBSZXluZXMgb2YgQ2FzdGFtZXJlXShodHRwczovL3d3dy55b3V0dWJlLmNvbS93YXRjaD92PW96VmNiSWM1eVdJKQoKSSB3YW50ZWQgdG8gcGxheSBhcm91bmQgd2l0aCB0aGUgZXhjZWxsZW50IFtuZXR3b3JrRDMgcGFja2FnZV0oaHR0cHM6Ly9jaHJpc3RvcGhlcmdhbmRydWQuZ2l0aHViLmlvL25ldHdvcmtEMy8pIHNvbWUgbW9yZSBhbmQgZGVjaWRlZCB0byB0cnkgYW5kIG1hcCBvdXQgdGhlIGJvb2tzIGJlaGluZCB0aGUgR2FtZSBvZiBUaHJvbmVzIFRWIHNlcmllcy4gSSB3YXMgaW50ZXJlc3RlZCBhcyBhIGZhbiBvZiB0aGUgYm9va3MsIGJ1dCBhbHNvIGJlY2F1c2Ugb2YgdGhlIHNoZWVyIG51bWJlciBvZiBjaGFyYWN0ZXJzIHRoYXQgYXBwZWFyIGFuZCB3ZWF2ZSBpbiBhbmQgb3V0IG9mIHRoZSBzdG9yeS4KClRoaXMgaGFzIGJlZW4gW2RvbmUgYmVmb3JlXShodHRwOi8vd3d3Lm1hYS5vcmcvc2l0ZXMvZGVmYXVsdC9maWxlcy9wZGYvTWF0aGhvcml6b25zL05ldHdvcmtvZlRocm9uZXMlMjAoMSkucGRmKSBidXQgb25seSBmb3Igb25lIGJvb2sgKGFzIGZhciBhcyBJIGNhbiB0ZWxsKSBhbmQgaXQgc2VlbWVkIHNpbXBsZSBlbm91Z2ggdG8gZG8gaXQgZm9yIHRoZSByZXN0LgoKRmlyc3QgZ2V0IHRoZSBsaW5rcyB0byBlYWNoIGNoYXB0ZXIgZnJvbSBbdG93ZXJvZnRoZWhhbmQuY29tXShodHRwOi8vdG93ZXJvZnRoZWhhbmQuY29tL2Jvb2tzLzEwMS8wMDEvaW5kZXguaHRtbCkKYGBge3IsIHdhcm5pbmcgPSBGQUxTRSwgbWVzc2FnZSA9IEZBTFNFLCBlcnJvciA9IEZBTFNFfQpsaWJyYXJ5KHJ2ZXN0KQpsaWJyYXJ5KFJDdXJsKQpsaWJyYXJ5KG1hZ3JpdHRyKQoKYmFzZV91cmwgPC0gImh0dHA6Ly90b3dlcm9mdGhlaGFuZC5jb20iCnN1ZmZpeF91cmwgPC0gIi9pbmRleC5odG1sIgoKI2xvb3AgZm9yIHVybCBmb3IgYWxsIDUgYm9va3MKZm9yIChib29rIGluIDE6NSl7Cgl1cmwgPC0gcGFzdGUwKGJhc2VfdXJsLCAiL2Jvb2tzLzEwIiwgYm9vaywgc3VmZml4X3VybCkKCWlmZWxzZSghZXhpc3RzKCJib29rX3VybHMiKSwKCQkJCWJvb2tfdXJscyA8LSB1cmwsCgkJCQlib29rX3VybHMgPC0gYXBwZW5kKGJvb2tfdXJscywgdXJsKSkKfQpybShzdWZmaXhfdXJsKQoKI2dldCB0aGUgbGlua3Nmb3IgZXZlcnkgY2hhcHRlcgpjaGFwdGVyX2Z1bmMgPC0gZnVuY3Rpb24oYm9va191cmwpewogIHJlYWQgPC0gcmVhZF9odG1sKGJvb2tfdXJsKQogICAgbm9kZXMgPC0gcmVhZCAlPiUgaHRtbF9ub2RlcygiLmJpbmRpbmcgLmNoYXB0ZXJncmlkIGEiKQogICAgbGlua3MgPC0gcGFzdGUwKGJhc2VfdXJsLCBub2RlcyAlPiUgaHRtbF9hdHRyKCJocmVmIikpCiAgcmV0dXJuKGxpbmtzKQp9CgpjaGFwdGVyX3VybHMgPC0gdW5saXN0KGxhcHBseShib29rX3VybHMsIGNoYXB0ZXJfZnVuYykpCgojbGF0ZXIgd2UnbGwgYWxzbyB3YW50IHRoZSBudW1iZXIgb2YgY2hhcHRlcnMvYm9vawojVG8gc3BhcmUgc2NyYXBpbmcgYWdhaW4vIG1vcmUgY29tcGxpY2F0ZWQgaGVyZSB0aGV5IGFyZQpib29rcyA8LSBkYXRhLmZyYW1lKGJvb2sgPSBjKDE6NSksCiAgICAgICAgICAgICAgICAgICAgY2hhcHRlcnMgPSBjKDczLCA3MCwgODIsIDQ2LCA3MyksCiAgICAgICAgICAgICAgICAgICAgdGl0bGUgPSBjKCJBIEdhbWUgb2YgVGhyb25lcyIsICJBIENsYXNoIG9mIEtpbmdzIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkEgU3Rvcm0gb2YgU3dvcmRzIiwgIkEgRmVhc3QgZm9yIENyb3dzIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkEgRGFuY2Ugd2l0aCBEcmFnb25zIikpCmBgYAoKVGhlbiBnZXQgbGlzdCBvZiBhbGwgY2hhcmFjdGVycyB0aGF0IGFwcGVhciBpbiB0aGVzZSBjaGFwdGVycy4gVGhlcmUncyBhIGxpdHRsZSBjb21wbGljYXRpb24gaW4gdGhhdCBzb21lIGNoYXJhY3RlcnMgYXJlIGR1cGxpY2F0ZWQgKGUuZy4gdGhlcmUgYXJlIHRocmVlIGNoYXJhY3RlcnMgbmFtZWQgIldhbGRlciBGcmV5IiBiZWNhdXNlIHRoZSBvcmlnaW5hbCBpcyBhIGNvbXBsZXRlIG5hcmNpc3Npc3QpIHNvIHdlIGdldCB0aGUgdW5pcXVlIGxpbmtzLCBUSEVOIHRoZSBuYW1lcwoKYGBge3J9CiNnZXQgdGhlIGNoYXJhY3RlcnMgaW4gZWFjaCBjaGFwdGVyCmNoYXJhY3Rlcl9mdW5jIDwtIGZ1bmN0aW9uKGNoYXB0ZXJfdXJsKXsKCXJlYWQgPC0gcmVhZF9odG1sKGNoYXB0ZXJfdXJsKQoJbm9kZXMgPC0gcmVhZCAlPiUgaHRtbF9ub2RlcygiI2FwcGVhcmFuY2VzID4gb2wgPiBsaSA+IGEiKQoJY2hhcmFjdGVyX3VybHMgPC0gcGFzdGUwKCJodHRwczovL3Rvd2Vyb2Z0aGVoYW5kLmNvbSIsIG5vZGVzICU+JSBodG1sX2F0dHIoImhyZWYiKSkKCXJldHVybihjaGFyYWN0ZXJfdXJscykKfQoKY2hhcmFjdGVyX3VybHMgPC0gbGFwcGx5KGNoYXB0ZXJfdXJscywgY2hhcmFjdGVyX2Z1bmMpCiAgYWxsX2NoYXJhY3RlcnMgPC0gdW5saXN0KGNoYXJhY3Rlcl91cmxzKQoKI2dldCB0aGUgbmFtZXMgb2YgZWFjaCBjaGFyYWN0ZXIgZnJvbSB0aGVpciBsaW5rcwpuYW1lc19mdW5jIDwtIGZ1bmN0aW9uKGNoYXJhY3Rlcl91cmwpewogIHJlYWQgPC0gcmVhZF9odG1sKGNoYXJhY3Rlcl91cmwpCiAgbm9kZXMgPC0gcmVhZCAlPiUgaHRtbF9ub2RlcygiI2hlYWRsaW5lID4gaDIiKQogIG5hbWVzIDwtIG5vZGVzICU+JSBodG1sX3RleHQoKQogIHJldHVybihuYW1lcykKfQoKbmFtZXMgPC0gbGFwcGx5KHVuaXF1ZShhbGxfY2hhcmFjdGVycyksIG5hbWVzX2Z1bmMpCgpDaGFyYWN0ZXJzIDwtIGRhdGEuZnJhbWUoY2hhcmFjdGVyID0gdW5saXN0KG5hbWVzKSwgbGlua3MgPSB1bmlxdWUoYWxsX2NoYXJhY3RlcnMpKQogIENoYXJhY3RlcnMkY2hhcmFjdGVyIDwtIG1ha2UudW5pcXVlKGFzLmNoYXJhY3RlcihDaGFyYWN0ZXJzJGNoYXJhY3RlcikpCmBgYAoKUHJpbnQgdGhlIGNoYXJhY3RlcnMgdXNpbmcgdGFibGUoKSBhbmQgZ2V0IGFuZCBpZGVhIG9mIGhvdyBvZnRlbiBlYWNoIGFwcGVhcnMKYGBge3J9CiNob3cgb2Z0ZW4gZWFjaCBjaGFyYWN0ZXIgYXBwZWFycwpoZWFkKHRhYmxlKGFsbF9jaGFyYWN0ZXJzKSkKCiN0aGUgdG90YWwgbnVtYmVyIG9mIHVuaXF1ZSBjaGFyYWN0ZXJzCnByaW50KHBhc3RlKCJUaGVyZSBhcmUiLCBsZW5ndGgodW5pcXVlKGFsbF9jaGFyYWN0ZXJzKSksCgkJCSJuYW1lZCBjaGFyYWN0ZXJzIGluIHRoZSBTb25nIG9mIEljZSBhbmQgRmlyZSBzZXJpZXMiKSkKYGBgCgpUaGVuIG1ha2UgYW4gZW1wdHkgZGF0YSBmcmFtZSB0byBwYXNzIHRoZXNlIGNoYXJhY3RlcnMgYXBwZWFyYW5jZXMgaW50bwoKYGBge3J9CiNtYWtlIGFuIGVtcHR5IGRhdGEgZnJhbWUgb2YgY2hhcmFjdGVycyA9IHJvd3MgYW5kIGNoYXB0ZXJzID0gY29sdW1ucyAKY2hhcHRlcl9kZiA8LSBkYXRhLmZyYW1lKG1hdHJpeChOQSwKCQkJCQkJbnJvdyA9IGxlbmd0aCh1bmlxdWUoYWxsX2NoYXJhY3RlcnMpKSwKCQkJCQkJbmNvbCA9IGxlbmd0aChjaGFwdGVyX3VybHMpKSkKCXJvd19uYW1lcyA8LSB1bmlxdWUoYWxsX2NoYXJhY3RlcnMpCgkJcm93bmFtZXMoY2hhcHRlcl9kZikgPC0gcm93X25hbWVzCgljb2xfbmFtZXMgPC0gMToobGVuZ3RoKGNoYXB0ZXJfdXJscykpCgkJY29sbmFtZXMoY2hhcHRlcl9kZikgPC0gY29sX25hbWVzCmBgYAoKQW5kIHJ1biB0aGUgZnVuY3Rpb24gd2hlcmUgYSAiMSIgbWVhbnMgdGhhdCBjaGFyYWN0ZXIgaXMgaW4gdGhhdCBjaGFwdGVyCgpgYGB7cn0KI2ZpbmQgd2hpY2ggY2hhcHRlciBlYWNoIGNoYXJhY3RlciBhcHBlYXJzIGluCiNyZXByZXNlbnRlZCBhcyAiMSIgaW4gY2hhcHRlcl9kZgpmb3IgKGNoYXJhY3RlciBpbiAxOm5yb3coY2hhcHRlcl9kZikpewoJbmFtZSA8LSByb3duYW1lcyhjaGFwdGVyX2RmKVtjaGFyYWN0ZXJdCgljaGFwdGVyX2RmW2NoYXJhY3RlciwgZ3JlcChuYW1lLCBjaGFyYWN0ZXJfdXJscyldIDwtIDEKfQoKI2V2ZXJ5IGNlbGwgdGhhdCBpc24ndCAxIGlzIDAKY2hhcHRlcl9kZltpcy5uYShjaGFwdGVyX2RmKV0gPC0gMApgYGAKCkZvciBlYWNoIGNoYXJhY3RlciwgdGhpcyBmdW5jdGlvbiB0aGVuIGZpbmQgaG93IG9mdGVuIGV2ZXJ5IGNoYXJhY3RlciBjby1vY2N1cnMgd2l0aCBldmVyeSBvdGhlciBjaGFyYWN0ZXIuIEdpdmVuIGl0IGhhcyB0byBjb25uZWN0IGVhY2ggb2YgMTExMSBjaGFyYWN0ZXJzIHRvIHRoZSBvdGhlciAxMTEwIGl0IHRha2VzIGEgd2hpbGUgKGEgZmV3IGhvdXJzKSB0byBydW4gYW5kIGdpdmVzIGEgZGF0YSBmcmFtZSBvZiBlYWNoIHNvdXJjZSwgdGFyZ2V0IGFuZCAidmFsdWUiIChob3cgb2Z0ZW4gdGhlIGNoYXJhY3RlciBjby1vY2N1cikuCgpJJ3ZlIGluY2x1ZGVkIHRvIGNvZGUgSSB1c2VkIGZvciBlcnJvciBjaGVja2luZyBhbmQgaW4gY2FzZSB5b3Ugd2FudCB0byBkbyBpdCB5b3Vyc2VsZi4gSG93ZXZlciwgaW4gcnVubmluZyB0aGUgc2NyaXB0IEkgd2lsbCBkb3dubG9hZCB0aGUgLmNzdiBJIHVwbG9hZGVkIHRvIG15IEdpdEh1YgoKYGBge3IsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CiNmaW5kIGhvdyBvZnRlbiBlYWNoIGNoYXJhY3RlciBjby1vY2N1cnMgd2l0aCBldmVyeSBvdGhlciBjaGFyYWN0ZXIKI2ZvciAocHJvdGFnIGluIDE6bnJvdyhjaGFwdGVyX2RmKSl7CiMgCW5hbWUxIDwtIHJvd25hbWVzKGNoYXB0ZXJfZGYpW3Byb3RhZ10KIyAJZm9yIChvdGhlciBpbiAocHJvdGFnICsgMSk6bnJvdyhjaGFwdGVyX2RmKSl7CiMgCQluYW1lMiA8LSByb3duYW1lcyhjaGFwdGVyX2RmKVtvdGhlcl0KIyAJCWNvbm5lY3Rpb24gPC0gbGVuZ3RoKHdoaWNoKAojIAkJCQkJCWNoYXB0ZXJfZGZbcHJvdGFnLF0gPT0gMSAmCiMgCQkJCQkJY2hhcHRlcl9kZltvdGhlcixdID09IDEpKQojCiMgCQlpZihjb25uZWN0aW9uID4gMCl7CiMgCQkgIG5ld3JvdyA8LSBkYXRhLmZyYW1lKHNvdXJjZSA9IG5hbWUxLAojIAkJCQkJCQkgICAgICAgICAgdGFyZ2V0ID0gbmFtZTIsCiMgCQkJCQkJICAgICAgICAgIAl2YWx1ZSA9IGNvbm5lY3Rpb24pCiMgCQkJaWZlbHNlKCFleGlzdHMoIkxpbmtzIiksCiMgCQkJICBMaW5rcyA8LSBuZXdyb3csCiMgCQkgIAlMaW5rcyA8LSByYmluZChMaW5rcywgbmV3cm93KSkKIyAJCX0KIyAJfQojfQoKI2xvYWQgdGhlIExpbmtzIGZpbGUgZnJvbSBteSBHaXRIdWIKR2l0aHViIDwtICJodHRwczovL3Jhdy5naXRodWJ1c2VyY29udGVudC5jb20vUm9iV0hpY2ttYW4vIgpQcm9qZWN0IDwtICJEYXRhYmFzZXMtYW5kLUZpbGVzL21hc3Rlci9Hb1QtTmV0d29yay8iCk5ldHdvcmtfZmlsZSA8LSBwYXN0ZTAoR2l0aHViLCBQcm9qZWN0LCAiR29ULU5ldHdvcmsuY3N2IikKCkxpbmtzIDwtIHJlYWQuY3N2KE5ldHdvcmtfZmlsZSwgc3RyaW5nc0FzRmFjdG9ycyA9IEZBTFNFKQpgYGAKClRvIHByb2R1Y2UgdGhlIG5ldHdvcmssIHRoZSBOb2RlcyBhcmUgYWxzbyBuZWVkZWQKCmBgYHtyfQojZ2V0IGEgZGYgb2YgZWFjaCBjaGFyYWN0ZXIgYW5kIHRoZWlyIGZyZXF1ZW5jeQpOb2RlcyA8LSBkYXRhLmZyYW1lKHRhYmxlKGFsbF9jaGFyYWN0ZXJzKSkKCiNhZGQgaW4gYSBzaXplIGNvbHVtbiBmb3IgdGhlIG5vZGVzIHdlIHBsb3QKTm9kZXMkc2l6ZSA8LSAoTm9kZXMkRnJlcV4yKS84CgojY2hhbmdlIG5hbWVzIGZyb20gdXJscyB0byBjaGFyYWN0ZXIgbmFtZXMKTm9kZXMkYWxsX2NoYXJhY3RlcnMgPC0gYXMuY2hhcmFjdGVyKE5vZGVzJGFsbF9jaGFyYWN0ZXJzKQogIGNvbG5hbWVzKE5vZGVzKVsxXSA8LSAibmFtZSIKCmZvciAoY2hhcmFjdGVyIGluIDE6bnJvdyhOb2RlcykpewogIE5vZGVzJG5hbWVbY2hhcmFjdGVyXSA8LSBDaGFyYWN0ZXJzJGNoYXJhY3Rlclt3aGljaChOb2RlcyRuYW1lW2NoYXJhY3Rlcl0gPT0gQ2hhcmFjdGVycyRsaW5rcyldCn0KICAKI2dldCAiYWN0dWFsIiBuYW1lcyAoaS5lLiByZW1vdmUgdW5kdXBsaWNhdGlvbikgYW5kIHN1cm5hbWVzCk5vZGVzJGR1cGxpY2F0ZW5hbWVzIDwtIGdzdWIoIlxcLi4qIiwgIiIsIE5vZGVzJG5hbWUpCk5vZGVzJHN1cm5hbWUgPC0gZ3N1YigiLiogIiwgIiIsIE5vZGVzJG5hbWUpCiAgTm9kZXMkc3VybmFtZVt3aGljaChOb2RlcyRzdXJuYW1lID09IE5vZGVzJGR1cGxpY2F0ZW5hbWVzKV0gPC0gIm5vIHN1cm5hbWUiCiAgCmhlYWQoTm9kZXMpCmBgYAoKSSB3YW50ZWQgdG8gdXNlIGVhY2ggcGVyc29uJ3MgaG91c2UgdG8gY29sb3VyIHRoZW0uIEZpcnN0IGdldCB0aGUgSG91c2VzCgpgYGB7cn0KI2dldCBldmVyeSBIb3VzZSBpbiB0aGUgc2VyaWVzCmhvdXNlc191cmwgPC0gImh0dHA6Ly90b3dlcm9mdGhlaGFuZC5jb20vYm9va3MvaG91c2VzLmh0bWwiCiAgaG91c2VzX3JlYWQgPC0gcmVhZF9odG1sKGhvdXNlc191cmwpCiAgaG91c2VzX25vZGVzIDwtIGhvdXNlc19yZWFkICU+JSBodG1sX25vZGVzKCJ0ZDpudGgtY2hpbGQoMikgYSAsIHRkOm50aC1jaGlsZCg0KSBhICwgICAgIHRkOm50aC1jaGlsZCg2KSBhIikKICBob3VzZXNfbmFtZXMgPC0gdW5pcXVlKGhvdXNlc19ub2RlcyAlPiUgaHRtbF90ZXh0KCkpCiAgICAjdGhlcmUgYXJlIHR3byBIb3VzZXMgY2FsbGVkICJGb3Nzb3dheSIKICAgICN0byBhdm9pZCBhbm5veWFuY2UsIHRha2UgaXQgb3V0IG5vdyBhbmQgYmluZCBpdCBiYWNrIGxhdGVyCgkgIGhvdXNlc19uYW1lcyA8LSBob3VzZXNfbmFtZXNbLWMod2hpY2goaG91c2VzX25hbWVzID09ICJGb3Nzb3dheSIpKV0KCiNnZXQgdGhlIGxpbmtzIHRvIGVhY2ggSG91c2UncyBwYWdlCmxpbmtzX2Z1bmMgPC0gZnVuY3Rpb24oaHRtbCwgaG91c2VfbmFtZSl7CglwYXN0ZTAoImh0dHA6Ly90b3dlcm9mdGhlaGFuZC5jb20iLAoJCWh0bWwgJT4lIAoJCWh0bWxfbm9kZXMoeHBhdGg9cGFzdGUwKCcvL2FbdGV4dCgpPSInLCBob3VzZV9uYW1lLCAnIl0nKSkgJT4lCgkJaHRtbF9hdHRyKCJocmVmIikpCn0KCmhvdXNlX2xpbmtzIDwtIHNhcHBseShob3VzZXNfbmFtZXMsIGZ1bmN0aW9uKHgpbGlua3NfZnVuYyhob3VzZXNfcmVhZCwgeCkpCgojbWFrZSBhIGRmIG9mIHRoZSBIb3VzZSBuYW1lcyBhbmQgbGlua3MKaG91c2UgPC0gZGF0YS5mcmFtZShob3VzZSA9IGFzLmNoYXJhY3Rlcihob3VzZXNfbmFtZXMpLAoJCQkJCWxpbmsgPSBhcy5jaGFyYWN0ZXIodW5saXN0KGhvdXNlX2xpbmtzKSkpCiAgI2FkZCB0aGUgRm9zc293YXkgSG91c2UgYmFjayBpbgogIEZvc3Nvd2F5cyA8LSBkYXRhLmZyYW1lKGhvdXNlID0gIkZvc3Nvd2F5IiwKCQkJCQkJCWxpbmsgPSAiaHR0cDovL3Rvd2Vyb2Z0aGVoYW5kLmNvbS9yZWZlcmVuY2Uvay8wMjA0NC9pbmRleC5odG1sIikKCWhvdXNlIDwtIHJiaW5kKGhvdXNlLCBGb3Nzb3dheXMpCglob3VzZSRzdXJuYW1lIDwtIGdzdWIoIiAuKiIsICIiLCBob3VzZSRob3VzZSkKCiNyZW1vdmUgSG91c2VzIHRoYXQgd2lsbCBmb3JtIGR1cGxpY2F0ZXMgd2hlbiB0cnlpbmcgdG8gZmluZCBhIGNoYXJhY3RlcidzIEhvdXNlCnJlbW92ZSA8LSBjKHdoaWNoKGhvdXNlJGhvdXNlID09ICJBcnJ5biBvZiBHdWxsdG93biIpLAogICAgICAgICAgICB3aGljaChob3VzZSRob3VzZSA9PSAiQnJ1bmUgb2YgQnJvd25ob2xsb3ciKSwKCQkJICAgICAgd2hpY2goaG91c2UkaG91c2UgPT0gIkJhcmF0aGVvbiBvZiBEcmFnb25zdG9uZSIpLCAKCQkJICAgICAgd2hpY2goaG91c2UkaG91c2UgPT0gIkJhcmF0aGVvbiBvZiBLaW5nJ3MgTGFuZGluZyIpLAogICAgICAJCQl3aGljaChob3VzZSRob3VzZSA9PSAiRGF5bmUgb2YgSGlnaCBIZXJtaXRhZ2UiKSwgCiAgICAgIAkJCXdoaWNoKGhvdXNlJGhvdXNlID09ICJGYXJ3eW5kIG9mIFNlYWxza2luIFBvaW50IiksCiAgICAgIAkJCXdoaWNoKGhvdXNlJGhvdXNlID09ICJHb29kYnJvdGhlciBvZiBTaGF0dGVyc3RvbmUiKSwgCiAgICAgIAkJCXdoaWNoKGhvdXNlJGhvdXNlID09ICJHb29kYnJvdGhlciBvZiBPcmttb250IiksCiAgICAgIAkJCXdoaWNoKGhvdXNlJGhvdXNlID09ICJLZW5uaW5nIG9mIEtheWNlIiksIAogICAgICAJCQl3aGljaChob3VzZSRob3VzZSA9PSAiTGFubmlzdGVyIG9mIExhbm5pc3BvcnQiKSwKICAgICAgCQkJd2hpY2goaG91c2UkaG91c2UgPT0gIlJveWNlIG9mIFJ1bmVzdG9uZSIpLCAKICAgICAgCQkJd2hpY2goaG91c2UkaG91c2UgPT0gIlZhbmNlIG9mIFdheWZhcmVyJ3MgUmVzdCIpKQpob3VzZSA8LSBob3VzZVstYyhyZW1vdmUpLF0KYGBgCgpFYWNoIEhvdXNlIGhhcyBhIFtzaWdpbF0oaHR0cDovL3Rvd2Vyb2Z0aGVoYW5kLmNvbS9yZWZlcmVuY2Uvay8wMTA2Ny8pLiBUbyBnZXQgdGhlIGNvbG91cnMgd2UgZG93bmxvYWQgdGhpcyBzaWdpbCBhbmQgdXNlIFJJbWFnZVBhbGV0dGUgdG8gZXh0cmFjdCBhIHNpbmdsZSBjb2xvdXIgdGhhdCBpcyByZXByZXNlbnRhdGl2ZQoKYGBge3IsIG1lc3NhZ2UgPSBGQUxTRSwgd2FybmluZyA9IEZBTFNFLCBmaWcud2lkdGggPSAxNSwgZmlnLmhlaWdodCA9IDh9CmxpYnJhcnkoanBlZykKbGlicmFyeShSSW1hZ2VQYWxldHRlKQoKI2Rvd25sb2FkIGVhY2ggSG91c2UncyBzaWdpbCBhbmQgZ2V0IGEgY29sb3VyCmNvbG91cl9mdW5jIDwtIGZ1bmN0aW9uKGhvdXNlX2xpbmspewoJcmVhZCA8LSByZWFkX2h0bWwoYXMuY2hhcmFjdGVyKGhvdXNlX2xpbmspKQoJQ25vZGVzIDwtIHJlYWQgJT4lIGh0bWxfbm9kZXMoImRpdi5saW5lYXItcmFpbCA+IGRpdjpudGgtY2hpbGQoMikgPiBkaXYgPiBhID4gaW1nIikKCWxpbmsgPC0gQ25vZGVzICU+JSBodG1sX2F0dHIoInNyYyIpCgkjb25seSBkb3dubG9hZCBhIGZpbGUgYW5kIGV4dHJhY3QgY29sb3VyIGZvciB0aG9zZSBIb3VzZXMgdGhhdCBoYXZlIGEgc2lnaWwgcG9zdGVkCgkJaWYoIWlkZW50aWNhbChsaW5rLCBjaGFyYWN0ZXIoMCkpKXsKCQkJZG93bmxvYWQuZmlsZShsaW5rLCAiYXJtcy5qcGciLCBtb2RlID0gIndiIiwgcXVpZXQgPSBUUlVFKQoJCX0KCQlpZighaWRlbnRpY2FsKGxpbmssIGNoYXJhY3RlcigwKSkpewoJCQlpbWcgPC0gcmVhZEpQRUcoImFybXMuanBnIikKCQl9CgkJaWZlbHNlKGlkZW50aWNhbChsaW5rLCBjaGFyYWN0ZXIoMCkpLAoJCSAgI2lmIHRoZXJlJ3Mgbm8gc2lnaWwsIHVzZSBibGFjawoJCQljb2xvdXIgPC0gIiMwMDAwMDAiLAoJCQljb2xvdXIgPC0gaW1hZ2VfcGFsZXR0ZShpbWcsIG49MSkpCglSbm9kZXMgPC0gcmVhZCAlPiUgaHRtbF9ub2RlcygiZGl2Om50aC1jaGlsZCgyKSA+IGRpdi5saW5lYXItcmFpbCA+IGRpdi50aXRsZSA+IHNwYW4iKQoJcmVnaW9uIDwtIGdzdWIoIi4qICIsICIiLCBSbm9kZXMgJT4lIGh0bWxfdGV4dCgpKQpyZXR1cm4oYyhjb2xvdXIsIHJlZ2lvbikpCn0KCmhvdXNlY29sb3VycyA8LSBkby5jYWxsKCJyYmluZCIsIGxhcHBseShob3VzZSRsaW5rLCBjb2xvdXJfZnVuYykpCiAgY29sbmFtZXMoaG91c2Vjb2xvdXJzKSA8LSBjKCJjb2xvdXJzIiwgInJlZ2lvbiIpCiAgaG91c2UgPC0gY2JpbmQoaG91c2UsIGhvdXNlY29sb3VycykKCiNwbG90IGEgcGllIGNoYXJ0IG9mIGFsbCB0aGUgSG91c2VzIGFuZCB0aGVpciAiY29sb3VyIgpwaWUocmVwKDEsIGxlbmd0aChob3VzZSRjb2xvdXJzKSksIGNvbCA9IGhvdXNlJGNvbG91cnMsCgltYWluID0gIkhvdXNlIENvbG91cnMiLCBsYWJlbHMgPSBob3VzZSRob3VzZSkKYGBgCgpJdCB3YXMgYWJvdXQgdGhpcyBwb2ludCBJIHJlYWxpc2VkIHBhc3NpbmcgY29sb3VycyB0byBOb2RlcyBpbiBmb3JjZU5ldHdvcmsoKSBpc24ndCBzbyBlYXN5LiBUaGUgSG91c2UgY29sb3VycyB3aWxsIGNvbWUgaW4gdXNlZnVsIHdoZW4gSSBwbG90IHVzaW5nIGlncmFwaCBsYXRlciwgYnV0IGZvciBOZXR3b3JrRDMsIEkgYWxzbyBzY3JhcGVkIHRoZSAibG9jYXRpb24iIG9mIGVhY2ggSG91c2UgKHdoaWNoIG9mIHRoZSA3IEtpbmdkb21zIGl0IGlzIGJhc2VkKS4gVGhpcyBpcyB0aGUgInJlZ2lvbiIgcmV0dXJuIGluIHRoZSBjb2xvdXJfZnVuYygpLiAKClVuZm9ydHVuYXRlbHksIHNvbWUgSG91c2VzIGRvbid0IGhhdmUgYSByZWdpb24gbGlzdGVkIChkb2luZyBzb21lIHJlc2VhcmNoIGl0IHNlZW1zIHRoYXQgaXQgaXMgdW5rbm93bikgc28gd2UnbGwgbGVhdmUgdGhvc2UgYXMgIldlc3Rlcm9zLiIgRm9yIHNvbWUgb3RoZXJzIHRoZSBmdW5jdGlvbiBkb2Vzbid0IHF1aXRlIGZpbmQgd2hhdCB3ZSdyZSBsb29raW5nIGZvciwgb3IgdGhlIGluZm9ybWF0aW9uIGlzIGluY29ycmVjdCwgc28gc29tZSBxdWljayBnc3VicyBhcmUgbmVjZXNzYXJ5CgpgYGB7ciwgbWVzc2FnZSA9IEZBTFNFLCB3YXJuaW5nID0gRkFMU0UsIGZpZy53aWR0aCA9IDE1LCBmaWcuaGVpZ2h0ID0gOH0KI2dzdWIgaW5jb3JyZWN0IHJlZ2lvbiBkYXRhCmhvdXNlJHJlZ2lvbiA8LSBhcy5jaGFyYWN0ZXIoaG91c2UkcmVnaW9uKQogIGhvdXNlJHJlZ2lvblt3aGljaChob3VzZSRyZWdpb24gPT0gIkZhcnd5bmQuIildIDwtICJJc2xhbmRzLiIKICBob3VzZSRyZWdpb25bd2hpY2goaG91c2UkcmVnaW9uID09ICJDcm9ud2xhbmRzLiIpXSA8LSAiQ3Jvd25sYW5kcy4iCiAgaG91c2UkcmVnaW9uW3doaWNoKGhvdXNlJHJlZ2lvbiA9PSAiU3RhcmsuIildIDwtICJOb3J0aC4iCiAgaG91c2UkcmVnaW9uW3doaWNoKGhvdXNlJHJlZ2lvbiA9PSAnVXMuIicpXSA8LSAiSXNsYW5kcy4iCiAgaG91c2UkcmVnaW9uW3doaWNoKGhvdXNlJHJlZ2lvbiA9PSAiaG91c2UuIildIDwtICJDcm93bmxhbmRzLiIKICBob3VzZSRyZWdpb25bd2hpY2goaG91c2UkaG91c2UgPT0gIldvb2xmaWVsZCIpXSA8LSAiTm9ydGguIgogIGhvdXNlJHJlZ2lvblt3aGljaChob3VzZSRyZWdpb24gPT0gIlJlYmVsbGlvbi4iKV0gPC0gIkNyb3dubGFuZHMuIgogIAp0YWJsZShob3VzZSRyZWdpb24pCgojcGxvdCBhIHBpZSBjaGFydCBvZiBhbGwgdGhlIEhvdXNlcyBhbmQgdGhlaXIgInJlZ2lvbiIKcmVnaW9ucyA8LSBkYXRhLmZyYW1lKHRhYmxlKGhvdXNlJHJlZ2lvbikpCnBpZShyZWdpb25zJEZyZXEsIGxhYmVscyA9IHJlZ2lvbnMkVmFyMSwKICAgIG1haW4gPSAiTG9jYXRpb25zIG9mIEhvdXNlcyIpCmBgYAoKQWRkIHRoaXMgY29sb3VyL3JlZ2lvbiBpbmZvcm1hdGlvbiB0byBlYWNoIG5vZGUgdXNpbmcgYSBxdWljayBsb29rdXAgZnVuY3Rpb24KCmBgYHtyfQojYWRkIHRoZSBjb2xvdXIvcmVnaW9uIHRvIGVhY2ggY2hhcmFjdGVyIGluIHRoZSBOb2RlIGRmCm5vZGVfZnVuYyA8LSBmdW5jdGlvbihuYW1lKXsKCXJlZ2lvbiA8LSBob3VzZSRyZWdpb25bd2hpY2goaG91c2Ukc3VybmFtZSA9PSBuYW1lKV0KCQlpZmVsc2UobGVuZ3RoKHJlZ2lvbikgPiAwLAoJCXJlZ2lvbiA8LSB1bmxpc3QocmVnaW9uKSwKCQlyZWdpb24gPC0gIm5vbmUiKQoJY29sb3VyIDwtIGhvdXNlJGNvbG91cnNbd2hpY2goaG91c2Ukc3VybmFtZSA9PSBuYW1lKV0KCWlmZWxzZShsZW5ndGgoY29sb3VyKSA+IDAsCgkJY29sb3VyIDwtIHVubGlzdChjb2xvdXIpLAoJCWNvbG91ciA8LSAiIzAwMDAwMCIpCnJldHVybihjKGNvbG91ciwgcmVnaW9uKSkKfQoKY29sb3VyaW5mbyA8LSBkby5jYWxsKCJyYmluZCIsIGxhcHBseShOb2RlcyRzdXJuYW1lLCBub2RlX2Z1bmMpKQogIGNvbG5hbWVzKGNvbG91cmluZm8pIDwtIGMoImNvbG91ciIsICJyZWdpb24iKQoKI2NiaW5kIGl0IHRvIHRoZSBOb2RlcwpOb2RlcyA8LSBjYmluZChOb2RlcywgY29sb3VyaW5mbykKCmhlYWQoTm9kZXMpCmBgYAoKQmVmb3JlIHBsb3R0aW5nLCB0aGUgbmFtZXMgaW4gdGhlIExpbmtzIGRmIG5lZWQgdG8gYmUgaW5kZXhlZCB0byB0aGUgcm93bmFtZXMgZm9yIHRoZSBOb2Rlcy4gQWdhaW4sIGp1c3QgdXNlIGEgc2ltcGxlIGxvb2t1cCBsb29wIHRvIGRvIHRoaXMuCgpBbmQgdGhlbiBwbG90IHVzaW5nIGZvcmNlTmV0d29yaygpIGZyb20gbmV0d29ya0QzLiBJJ20gZmFyIGZyb20gYW4gZXhwZXJ0IGF0IHRoaXMgc28gdGhlcmUncyBwcm9iYWJseSBzb21lIG1vcmUgdGhhdCBjYW4gYmUgZG9uZSB0byBtYWtlIHRoZSBuZXR3b3JrIGNsZWFyZXIvIG1vcmUgYWVzdGhldGljLCBidXQgZm9yIG5vdyBJJ20gbm90IGRpc3BsZWFzZWQgd2l0aCB0aGUgcmVzdWx0cy4KCklmIHlvdSBqdXN0IHdhbnQgdG8gc2VlIHRoZSBvdXRwdXQgbmV0d29yaywgeW91IGNhbiBmaW5kIGl0IGF0IG15IFtyUHVicyBwYWdlXShodHRwOi8vcnB1YnMuY29tL1JvYldIaWNrbWFuL0dvVDMpCmBgYHtyfQpsaWJyYXJ5KG5ldHdvcmtEMykKCiNuZXR3b3JrRDMgdXNlcyB6ZXJvLWluZGV4aW5nCmZvciAobm9kZSBpbiAxOm5yb3coTm9kZXMpKXsKICAgIE5vcmRlciA8LSB3aGljaChOb2RlcyRuYW1lW25vZGVdID09IENoYXJhY3RlcnMkY2hhcmFjdGVyKSAtIDEKICAgIGlmZWxzZShub2RlIDwgMiwgb3JkZXIgPC0gTm9yZGVyLCBvcmRlciA8LSBhcHBlbmQob3JkZXIsIE5vcmRlcikpCn0KTm9kZXMkb3JkZXIgPC0gb3JkZXIKcm93bmFtZXMoTm9kZXMpIDwtIE5vZGVzJG9yZGVyCk5vZGVzIDwtIE5vZGVzW29yZGVyKE5vZGVzJG9yZGVyKSxdCgpMaW5rcyRzb3VyY2UgPC0gYXMubnVtZXJpYyhMaW5rcyRzb3VyY2UpIC0xCkxpbmtzJHRhcmdldCA8LSBhcy5udW1lcmljKExpbmtzJHRhcmdldCkgLTEKCiNwbG90IGl0IQojdmVyeSBsYXJnZSBmaWxlCiNmb3JjZU5ldHdvcmsoTGlua3MgPSBMaW5rcywgTm9kZXMgPSBOb2RlcywgTm9kZUlEID0gImR1cGxpY2F0ZW5hbWVzIiwgR3JvdXAgPSAicmVnaW9uIiwgU291cmNlID0gInNvdXJjZSIsIFRhcmdldCA9ICJ0YXJnZXQiLCBWYWx1ZSA9ICJ2YWx1ZSIsIHpvb20gPSBUUlVFLCBOb2Rlc2l6ZSA9ICJzaXplIiwgZm9udFNpemUgPSAzMCwgbGlua0NvbG91ciA9ICIjZDhkOGQ4Iiwgb3BhY2l0eSA9IDAuOCwgbGlua0Rpc3RhbmNlID0gbmV0d29ya0QzOjpKUygiZnVuY3Rpb24oZCkgeyByZXR1cm4gMTAwKmQudmFsdWU7IH0iKSwgbGlua1dpZHRoID0gbmV0d29ya0QzOjpKUygiZnVuY3Rpb24oZCkgeyByZXR1cm4gZC52YWx1ZS81OyB9IiksIGNoYXJnZSA9IC0xMDAsIGxlZ2VuZCA9IFRSVUUsIGNvbG91clNjYWxlID0gSlMoImQzLnNjYWxlLmNhdGVnb3J5MjAoKSIpKQpgYGAKCg==