SNA Grad Seminar, Fall 2017 Due: October 24th, 11:59 pm Name of Student: Jue Wu

The purpose of this lab is to develop your familiarity conducting descriptive network analysis using the statistical software package R. This assignment will make use of a data set you collect by defining a search query (a collection of your user-defined search terms) from the New York Times’s Article Search Application Programming Interface. Networks are generated from the co-occurrences between search terms included in the same search query. For example, a link exists between “apple” and “orange” if there are articles in the New York Times that contained these two terms. You will be visualizing and interpreting individual and global network properties of this network.

You will be graded primarily on the completeness and accuracy of your responses, but the clarity of the prepared report will also affect your grade. While students may work together to perform the analysis, each student must submit his or her own report and is responsible for writing the narrative in the report. You must answer all of the bolded questions.

Part 1: Collect Network Data (20 pts)

For this lab, you will search the New York Times, save that data, create networks from that data, compare the differences among networks, and demonstrate your proficiency with basic network descriptive statistics.

Loading and Installing Packages, Set Working Directory

When working with R, you should run each line of code individually, unless it is part of a function definition, so you can see the results. Generally speaking, any line of code that includes ‘{’ (the beginning of a function definition) should be run with all the other lines until you hit ‘}’.

library(magrittr)
library(httr)
library(data.table)
data.table 1.10.4.1
  The fastest way to learn (by data.table authors): https://www.datacamp.com/courses/data-analysis-the-data-table-way
  Documentation: ?data.table, example(data.table) and browseVignettes("data.table")
  Release notes, videos and slides: http://r-datatable.com

Attaching package: ‘data.table’

The following object is masked _by_ ‘.GlobalEnv’:

    .N
library(igraph)

Attaching package: ‘igraph’

The following objects are masked from ‘package:stats’:

    decompose, spectrum

The following object is masked from ‘package:base’:

    union
library(dplyr)

Attaching package: ‘dplyr’

The following objects are masked from ‘package:igraph’:

    as_data_frame, groups, union

The following objects are masked from ‘package:data.table’:

    between, first, last

The following objects are masked from ‘package:stats’:

    filter, lag

The following objects are masked from ‘package:base’:

    intersect, setdiff, setequal, union
library(xml2)

Choose a topic for your search terms

You can decide search terms based on personal interests, research interests, or popular topical areas, among others. You have flexibility in selecting your search term list. For example, you can search for some commercial brands, celebrities, countries, universities, etc. It will be most useful if you choose a collection of words that are not all extremely common. Think about a set of words that might have interesting co-occurrences in articles within the New York Times website. For example, you might be interested in the last names of every Senator involved in a certain political debate, football teams, or cities and their co-occurrence in news articles. Generally speaking, proper nouns are best, but you might have compelling reasons to choose verbs or adjectives. You might want to throw a couple of terms in that aren’t thematically related to make sure you don’t get a totally connected component. The more interesting your network is in terms of differing centrality, distinct components, etc., the easier it will be to do the written analysis. Keep in mind that the Article Search archive is very large; many terms co-occur. You might want to consider two tenuously related subjects. The example file uses four football teams and their home senators, plus a few topical terms.

Create your text input

Create a plain text file with .txt extension in the same directory as the R Markdown Notebook used in this assignment. Make a note of the file name for use in the next code snippet. Place one search term per line, and use 15–20 terms. You’ll also likely want to add quotation marks around your search terms to ensure that you’re only receiving results for the complete term. NOTE: The function will process your terms so that they work in the URL request. You do not need to encode non-alphabetic characters.

The text file cannot include any additional information or characters and it must be a .txt file; Word or RTF documents won’t work.

Analysis

a. Provide a high level overview of the terms you included in the search query. The terms in the search query include NFL teams, players, and officers (New Orleans Saints, Tampa Bay Buccaneers, Carolina Panthers, Atlanta Falcons, Roger Goodell, Colin Kaepernick), and political figures (Steve Scalise, Sen. Bill Cassidy, Sen. Bill Nelson, Sen. Marco Rubio, Sen. Lindsey Graham, Sen. Tim Scott, Sen. Johnny Isakson, Sen. David Perdue, Donald Trump).

b. Why did you choose this collection of terms? Were there some specific overarching question—intellectual or extracurricular curiosity—that motivated this collection of terms? I used the provided dataset, but I was curious about how people (or organizations) in politics and sports related to each other. For example, what is the political tendency of teams and people in NFL? Is there financial interest between sports teams and political figures?

c. How did you decide which terms to use in the search query? Were these terms you intuitively deemed important? Were they culled from a specific source or the result of some separate analysis or search query? Originally I was interested in the diplomatic relations between countries (especially how US views China and whether it is biased or not), but I couldn’t successfully collect the data I wanted. In order to finish the assignment, I just used the provided dataset.

d. What are the insights you hope to glean by looking at the network of terms in terms of individual node metrics, sub-grouping of nodes, overall global network properties? My guess is that Donald Trump will probably get most links and be the highest in degree centrality because he is the President of the United States and every word in the query is American. At sub-group level, I think it is probably going to be two communities—one set of nodes for NFL related and one set of nodes for politics related—that interact a lot within the communities. At global level, I guess this network will be centralized.

Working with the API to Collect Your Data

The New York Times controls access to its API by assigning each user a key. Each key has a limited number of calls that can be made within a certain time period. You can read more about the limitations of the API system here.

You will need to create your own API key to complete this assignment. Go to the New York Times developers page and request a key. You will copy that key (received via email) into the api variable below.

# Import your word list
name_of_file <- "NFL.txt" # Creates a variable called name_of_file that you should populate with the name of your text file between quotation marks.
word_list <- read.table(name_of_file, sep = "\n", stringsAsFactors = F) %>% unlist %>% as.vector # Reads the content of your file into a variable.
num_words <- length(word_list) # Creates a variable with the number of words in your list.
url_base <- "https://api.nytimes.com/svc/search/v2/articlesearch.json"
# When you receive the email with your API key, paste it below between the quotation marks.
api <- '76f06c3d16c54280b9233d8f3d76e4bf'

Our first function will gather all of the search terms and their number of hits to be placed in a table. All lines of a function should be run together.

Get_hits_one <- function(keyword1) {
  Sys.sleep(time=3)
  url <- paste0(url_base, "?api-key=", api, "&q=", URLencode(keyword1),"&begin_date=","20160101") # Begin date is in format YYYYMMDD; you can change it if you want only more recent results, for example.
  # The number of results
  print(keyword1)
  hits <- content(GET(url))$response$meta$hits %>% as.numeric
  print(hits)
  # Put results in table
  c(SearchTerm=keyword1,ResultsTotal=hits)
}

Now we will invoke our function to put information from the API into our global environment.

#Create a table of your words and their number of results.
total_table <- t(sapply(word_list,Get_hits_one))
total_table <- as.data.frame(total_table)
total_table$ResultsTotal <- as.numeric(as.character(total_table$ResultsTotal))

If you get zero hits for any of these terms, you should substitute that term for somethign else and rerun the lab up to this point. Next, we will define the function that will collect the article co-occurences network.

Get_hits_two <- function(row_input) {
  keyword1 <- row_input[1]
  keyword2 <- row_input[2]
  url <- paste0(url_base, "?api-key=", api, "&q=", URLencode(keyword1),"+", URLencode(keyword2),"&begin_date=","20160101") #match w/ Begin Date in Get_hits_one.
  # The number of results
  print(paste0(keyword1," ",keyword2)) 
  hits <- content(GET(url))$response$meta$hits %>% as.numeric
  print(hits)
  Sys.sleep(time=3)
  # Put results in table
  c(SearchTerm1=keyword1,SearchTerm2=keyword2,CoOccurrences=hits)
} 

In this next step, we will call the API and collect the co-occurrence network. This may take some time. If you receive “numeric(0)” in any of your resposnes, you’ve likely hit your API key limit and will either need to wait for the calls to reset (24 hours) or request a new key. If you receive the error message “$ operator is invalid for atomic vectors,” you have also hit the API call limit. This could be due to running the script multiple times, or due to hitting too many results based on very common search terms. Request a new API, shorten your word list, and try again. Don’t forget you need to reload your word list from the first part of the Lab in order to get a different set of results! You must also rerun the functions to reassign the API value. If none of your results come back as “0,” you might want to redo your search with the appropriate words.

# Convert the pairs list into a table
pairs_list <- expand.grid(word_list,word_list) %>% filter(Var1 != Var2)
pairs_list <- t(combn(word_list,2))
#Create a network table, run the Get_hits_two function using the pairs lists
network_table <- t(apply(pairs_list,1,Get_hits_two))
#Convert the network table into a dataframe
network_table <- as.data.frame(network_table)
# Read each the content of each item within the $CoOccurreences factor as characters, 
# then force those characters into the "numeric" or "double" type.
network_table$CoOccurrences <- as.numeric(as.character(network_table$CoOccurrences))
# Convert data to data.table type.
total_table <- as.data.table(total_table)
network_table <- as.data.table(network_table)

# Remove zero edges from your network
network_table <- network_table[!CoOccurrences==0] 

# Create a graph object with your data
g_valued <- graph_from_data_frame(d = network_table[,1:3,with=FALSE],directed = FALSE,vertices = total_table)

# If you're having trouble with data collection, you can load the 'NFL Lab Results.RData' file now by clicking the open folder icon on the "Environment"" tab and continue the lab from here. You'll need to figure out what the significance of the terms are yourself, however.
# You should save your data at this point by clicking the floppy disk icon under the "Environment" tab.

Analysis

Is the graph directed or undirected? Undirected

How many nodes and links does your network have? There are 15 nodes and 35 links.

numVertices <- vcount(g_valued)
numVertices
[1] 15
numEdges <- ecount(g_valued)
numEdges
[1] 35

What is the number of possible links in your network? There are 105 possible links.

maxEdges <- numVertices*(numVertices-1)/2
maxEdges
[1] 105

What is the density of your network? The density is 0.3333333

graphDensity1 <- graph.density(g_valued) # using the graph.density function from igraph
graphDensity1
[1] 0.3333333

Briefly describe how your choice of dataset may influence your findings. What differences would you expect if you use different search terms? Are the current search terms related to one another? If so, how? Do you think the limitation to one word might skew your answers? (i.e. if you’re interested in Hillary Clinton, but you include “Clinton” as a term, you will get stories that mention Chelsea, Bill, & even P-Funk Allstar George Clinton).

It was good to include the full names instead of limiting the words to just one single word, which reduces the chance of getting unwanted words. Also, including Sen. in front of people’s names ensured that the results we get are the ones about politics that we wanted. However, people might also use President Trump when referring to Donald Trump, thus using “Donald Trump” might influence the results by giving us fewer datapoints. # Part 2: Visualize Your Network (20 points)

Let’s start by visualizing the network that we’ve collected from the New York Times Article Search API. We’ll need to choose node colors and set a layout. You can learn more about Fruchterman Reingold layout and other layouts here.

Analysis

In a paragraph, describe the macro-level structure of your graphs based on the Fruchterman Reingold visualization. Is it a giant, connected component, are there distinct sub-components, or are there isolated components? Can you recognize common features of the subcomponents? Does this visualization give you any insight into the co-occurrence patterns of the search-terms? If yes, what? If not, why?

It is a giant component that everyone is connected. On the first sight, the visualization tells me that Donald Trump is a cutpoint. He is the one that connects the politics camp and the sports camp; if we remove him, the network will become two components. In addition, it is apparent that the NFL related words are more connected within the community, compared to the politics community.

Now we’ll create a second visualization using a different layout.

Analysis

In a paragraph, compare and contrast the information given to you by the two different layouts. The two layouts both suggest that Donald Trump has the highest degree centrality and he is the cutpoint. However, it seems like that the sports community is less centralized in the second layout than the first one.

Part 3: Community Detection Analysis with R (20 Points)

Identifying subgroups within a network is of great interest to social network researchers, so a variety of algorithms have been developed to identify and measure subgroups. We will use some of R’s built-in tools to identify subgroups and central nodes for visual inspection.

For the remainder of the visualizations we will use the Fruchterman Reingold layout.

Cluster the nodes in your network.

cluster <- cluster_walktrap(g_valued)
# Find the number of clusters
membership(cluster)   # affiliation list
  “New Orleans Saints”        “Steve Scalise”    “Sen. Bill Cassidy” 
                     3                      1                      2 
“Tampa Bay Buccaneers”     “Sen. Bill Nelson”     “Sen. Marco Rubio” 
                     3                      1                      1 
   “Carolina Panthers”  “Sen. Lindsey Graham”       “Sen. Tim Scott” 
                     3                      1                      2 
     “Atlanta Falcons”  “Sen. Johnny Isakson”    “Sen. David Perdue” 
                     3                      1                      1 
       “Roger Goodell”         “Donald Trump”     “Colin Kaepernick” 
                     3                      1                      3 
length(sizes(cluster)) # number of clusters
[1] 3
# Find the size the each cluster 
# Note that communities with one node are isolates, or have only a single tie
sizes(cluster) 
Community sizes
1 2 3 
7 2 6 

How many communities have been created? 3

How many nodes are in each community? In networks containing node attribute information, we can often gain insight into a network by looking at the nodes that get placed in the same partition.

There are 7, 2, and 6 nodes in each community.

For your network, what might each cluster of nodes potentially have in common? Describe each cluster, its membership, and the relationship between nodes in the cluster. Cluster 1 is all politicians, including several senators, the President, and the house majority whip. The relationship between these nodes is probably work. Cluster 2 is two senators. They are both republican, but because I’m not familiar with the politics, I don’t know why they are in a different cluster other than Cluster 1. My guess is that they might have different opinions with other politicians. Cluster 3 is all NFL related, including NFL teams, officer, and player. The relationship between these nodes is probably competition and service.

Next we visualize the clusters by coloring nodes according to their modularity class.

What information does this layout convey? Are the clusters well-separated, or is there a great deal of overlap? Is it easier to identify the common themes among clusters in this layout rather than looking only at the graphs? The cluasters are well-seperated. It is easier to identify the common themes among clusters since we can tell directly from the layout that what actors are in the same cluster.

What differences are there between nodes in the same cluster and across clusters? Nodes in the same cluster are more connected with each other and have shorter distance, whereas nodes across clusters are less connected and reaching them requires longer distance.

Describe the brokers between any components and cliques. What are common features of these brokers? About how many brokers would you have to remove from your network to “shatter” it into two or more disconnected components? Brokers are the people who have high betweenness centrality and control the group’s information flows. Based on the layout, Donald Trump is the broker to Cluster 1, without whom everyone else in Cluster 1 won’t be able to get information from outside. Sen. Bill Cassidy is the broker to Cluster 2, without whom Sen. Tim Scott won’t get information. As for Cluster 3, everyone is directly connected to Donald Trump and they are interconnected as well, so no one is the broker. Commen feature of these brokers is that people in the cluster won’t get information from outside if they are removed. If we are to break network into more disconnected components, we can remove either Donald Trump or Sen. Bill Cassidy.

Part 4: Centrality Visualization & Weighted Values (20 Points)

For each network, you will use centrality metrics to improve your visualization. You may need to adjust the size parameter to make your network more easily visible.

Degree Centrality

totalDegree <- degree(g_valued,mode="all")
sort(totalDegree,decreasing=TRUE)[1:5]
        “Donald Trump”   “New Orleans Saints” “Tampa Bay Buccaneers” 
                    13                      6                      6 
   “Carolina Panthers”      “Atlanta Falcons” 
                     6                      6 
g2 <- g_valued
V(g2)$size <- totalDegree*2 #can adjust the number if nodes are too big
plot(g2, layout = L, vertex.label=NA)

Briefly explain degree centrality and why nodes are more or less central in the network. Degree centrality measures the “popularity” of the actors by counting total number of links one has with other actors. In this case, Donald Trump has the highest degree centrality and that’s probably because he is the President and every person or every team is in this country. The four NFL teams all have relative high degree centrality and the number of links they have is exactly the same. This is probably because they will play games against one another, and the number of games between these games should be the same.

Weighted Degree Centrality

wd <- graph.strength(g_valued,weights = E(g_valued)$CoOccurrences)
sort(wd,decreasing=TRUE)[1:5]
   “Carolina Panthers”      “Atlanta Falcons”     “Colin Kaepernick” 
                   246                    213                    194 
  “New Orleans Saints” “Tampa Bay Buccaneers” 
                   190                    189 
wg2 <- g_valued
V(wg2)$size <- wd*.1 # adjust the number if nodes are too big
plot(wg2, layout = L, vertex.label=NA, edge.width=sqrt(E(g_valued)$CoOccurrences))

What does the addition of weighted degree and edge information tell you about your graph? The weighted results are much different than the original one. It takes into account of the frequency that these words co-occured on NYT instead of the relations being just present or absent. NFL related words are the ones that have the highest weighted degree centrality, and this is probably because the teams play against one another quite often and they tend to co-occur more. Whereas the non-weighted centrality only tells us whether there is link between the two nodes.

Betweenness Centrality

b <- betweenness(g_valued,directed=TRUE)
sort(b,decreasing=TRUE)[1:5]
     “Donald Trump” “Sen. Bill Cassidy”     “Steve Scalise”  “Sen. Bill Nelson” 
         65.3333333          13.0000000           2.0000000           0.3333333 
 “Sen. Marco Rubio” 
          0.3333333 
g4 <- g_valued
V(g4)$size <- b*1.2#can adjust the number
plot(g4, layout = L, vertex.label=NA)

Briefly explain betweenness centrality and why nodes are more or less central in the network. Betweeness centrality assesses how much an actor lies between distinct groups by the number of geodesics passing through actor. In this case, Donald Trump has the highest betweeness centrality, as we can see that he lies between politicians and sports related words and serves as a broker. Similarly, Sen. Bill Cassidy also has high bewtweeness centrality because Sen. Tim Scott is only able to connect with others through him. Nodes with less betweeness centrality means that they are less likely to affect information flows if they are removed.

Weighted Betweenness Centrality

wbtwn <- betweenness(g_valued,weights = E(g_valued)$CoOccurrences)
sort(wbtwn,decreasing=TRUE)[1:5]
        “Donald Trump”     “Sen. Bill Nelson” “Tampa Bay Buccaneers” 
              70.50000               37.50000               22.50000 
       “Steve Scalise”    “Sen. Bill Cassidy” 
              18.33333               13.00000 
wBtwnG <- g_valued
V(wBtwnG)$size <- wbtwn*.5 # adjust the number if nodes are too big
plot(wBtwnG, layout = L, vertex.label=NA, edge.width=sqrt(E(g_valued)$CoOccurrences))

What does the addition of weighted degree and edge information tell you about your graph? Although Donald Trump is still the highest in weighted betweeness degree, nodes appear to be different when the calculation is weighted. For example, Sen. Bill Cassidy is no longer the second highest in betweeness degree. The weighted results would provide more information in terms of how these actors are related in the real world because the relations are no longer just binary but take into account how frequent the connections appear.

Closeness Centrality

c <- closeness(g_valued)
sort(c,decreasing=TRUE)[1:5]
        “Donald Trump”   “New Orleans Saints” “Tampa Bay Buccaneers” 
            0.06666667             0.04347826             0.04347826 
   “Carolina Panthers”      “Atlanta Falcons” 
            0.04347826             0.04347826 
g5 <- g_valued
V(g5)$size <- c*500  #can adjust the number
plot(g5, layout = L, vertex.label=NA)

Briefly explain closeness centrality and why nodes are more or less central in the network. Closeness centrality measures how easily one actor can reach rest of network. Actor with shortest average path length in the network has the highest closeness centrality and serves as pulse-taker. This means that the information will be transmitted much slower if we remove nodes with high closeness centrality. In this case, Donald Trump has the highest closeness centrality, meaning that he has shortest average path length in the network. Without him, the information flows will be “pulsed”. Other than Donald Trump, all the notes appear to be kind of high in closeness centrality—they appear to be similar in size on the layout. Nodes with less closeness centrality means that they will have the least influence on information flows when being removed.

Weighted Closeness Centrality

wClsnss <- closeness(g_valued,weights = E(g_valued)$CoOccurrences)
sort(wClsnss,decreasing=TRUE)[1:5]
       “Donald Trump”    “Sen. Bill Nelson”       “Steve Scalise” 
           0.01587302            0.01515152            0.01369863 
“Sen. Johnny Isakson”   “Sen. David Perdue” 
           0.01315789            0.01315789 
wClsnssG <- g_valued
V(wClsnssG)$size <- wClsnss*1000 # adjust the number if nodes are too big
plot(wClsnssG, layout = L, vertex.label=NA, edge.width=sqrt(E(g_valued)$CoOccurrences))

What does the addition of weighted degree and edge information tell you about your graph? Although Donald Trump remains to be the highest in weighted closeness centrality, other actors that are high in the weighted measure are all politicians instead of NFL teams. This suggests that if we consider the frequency of co-occurance of the words, these politicians play a more important role in effectively transmitting information to others in the network.

Eigenvector Centrality

eigc <- eigen_centrality(g_valued,directed=TRUE)
sort(eigc$vector,decreasing=TRUE)[1:5]
        “Donald Trump” “Tampa Bay Buccaneers”    “Carolina Panthers” 
             1.0000000              0.7745642              0.7745642 
       “Roger Goodell”     “Colin Kaepernick” 
             0.7745642              0.7745642 
g6 <- g_valued
V(g6)$size <- eigc$vector*50 #can adjust the number
plot(g6, layout = L, vertex.label=NA)

Briefly explain eigenvector centrality and why nodes are more or less central in the network. Eigenvector centrality can be measured by recomputing each node’s score as weighted sum of neighbors’ centralities. Highest between and/or degree central actor is often highest eigenvalue central actor, and this is exactly right in this case. Donald Trump is the one with highest eigenvector centrality, meaning that the nodes Donald Trump connects to has lots of links. However, several nodes from the NFL cluster also have high eigenvector centrality, and this is probably because actors are much more interconnected in the NFL cluster due to competition between teams.

Analysis

Choose the visualization that you think is most interesting and briefly explain what it tells you about a central node in your network. Discuss the type of centrality, and what that node’s centrality score tells you about the search co-occurrence network. I think the most interesting one is the closeness centrality. Closeness centrality measures how easily one actor can reach rest of network. Actor with shortest average path length in the network has the highest closeness centrality and serves as pulse-taker. Based on the layout, we can see that actually a lot of actors appear to be relatively high in terms of closeness centrality and we can’t really tell who has higher closeness centrality other than Donald Trump. This is not the case for other layouts, as some actors are obviously more central in those. This result tells us that many actors are important in effectively passing on information in this network.

Briefly discuss an interesting difference between types of centrality for your network. One interesting difference is the degree centrality vesus betweeness centrality. Although Donald Trump always turns out to be the one with highest centrality in all these measures, NFL teams are among the highest ones for degree centrality, whereas senators are the highest ones for betweeness centrality. This probably suggests that although NFL teams have more links and are more popular to appear on NYT, politicians are more important in terms of whether information can be passed on.

Global Network Metrics with R

Compute the network centralization scores for your network for degree, betweenness, closeness, and eigenvector centrality.

centralization.evcent(g_valued,normalized = TRUE)
$vector
 [1] 0.77456419 0.28452963 0.20947656 0.77456419 0.29025659 0.29025659
 [7] 0.77456419 0.25123207 0.03329756 0.77456419 0.15895601 0.15895601
[13] 0.77456419 1.00000000 0.77456419

$value
[1] 6.291049

$options
$options$bmat
[1] "I"

$options$n
[1] 15

$options$which
[1] "LA"

$options$nev
[1] 1

$options$tol
[1] 0

$options$ncv
[1] 0

$options$ldv
[1] 0

$options$ishift
[1] 1

$options$maxiter
[1] 1000

$options$nb
[1] 1

$options$mode
[1] 1

$options$start
[1] 1

$options$sigma
[1] 0

$options$sigmai
[1] 0

$options$info
[1] 0

$options$iter
[1] 2

$options$nconv
[1] 1

$options$numop
[1] 11

$options$numopb
[1] 0

$options$numreo
[1] 8


$centralization
[1] 0.5904349

$theoretical_max
[1] 13

Record the centralization score of each centrality measure. Degree centralization: 0.5952381 Betweeness centralization: 0.7056515 Closeness centralization: 0.7779971 Eigenvector centralization: 0.5904349

Briefly explain what the centralization of a network is. Network centralization reflects how equal every actor in the network is. Specifically, a more centralized network would be a network with some actors who have more links and some actors who have fewer links. To give an example, one of the most centralized network is the star network, where one actor has links to everyone else in the network while the others only have one link.

Compare the centralization scores above with the graphs you created where the nodes are scaled by centrality. Describe the appearance of more centralized v. less centralized networks. Centralization scores can range from 0 to 1, with 0 means least centralized and 1 means most centralized. In this case, the network is most centralized in terms of its closeness, while least centralized in terms of its eigenvector. But overall the network is centralized.

Part 5. Power Laws & Small Worlds (20)

Power Laws

Networks often demonstrate power law distributions. Plot the degree distribution of the nodes in your base graph.

deg_distr <-degree.distribution(g_valued, cumulative=T, mode="all")
deg_distr
 [1] 1.00000000 1.00000000 0.80000000 0.80000000 0.66666667 0.46666667
 [7] 0.46666667 0.06666667 0.06666667 0.06666667 0.06666667 0.06666667
[13] 0.06666667 0.06666667
plot(deg_distr, ylim=c(.01,10), bg="black",pch=21, xlab="Degree", ylab="Cumulative Frequency") 

Test whether it’s approximately a power law, estimate log f (k) = log a − c log k. “This says that if we have a power-law relationship, and we plot log f (k) as a function of log k, then we should see a straight line: −c will be the slope, and log a will be the y-intercept. Such a “log-log” plot thus provides a quick way to see if one’s data exhibits an approximate power-law: it is easy to see if one has an approximately straight line, and one can read off the exponent from the slope.” (E&K, Chapter 18, p.546).

power <- power.law.fit(deg_distr)
power
$continuous
[1] TRUE

$alpha
[1] 3.069992

$xmin
[1] 0.4666667

$logLik
[1] 1.343847

$KS.stat
[1] 0.2920275

$KS.p
[1] 0.502511
plot(deg_distr, log="xy", ylim=c(.01,10), bg="black",pch=21, xlab="Degree", ylab="Cumulative Frequency")

Does your network exhibit a power law distribution of degree centrality? The network does not really exhibit a power law distribution of degree centrality because the plot does not look like a straight line where we can easily tell the slope.

Small Worlds

Networks often demonstrate small world characteristics. Compute the average clustering coefficient (ACC) and the characteristic path length (CPL). ACC = 1.771429 CPL = 0.8269915

average.path.length(g_valued)
[1] 1.771429

Compute the ACC and CPL for 100 random networks with the same number of nodes and ties as your test network. ACC = 0.8893372 CPL = 1.110294

accSum <- 0
cplSum <- 0
for (i in 1:100){
  grph <- erdos.renyi.game(numVertices, numEdges, type = "gnm")
  accSum <- accSum + transitivity(grph, type = c("average"))
  cplSum <- cplSum + average.path.length(grph)
}
accSum/100
[1] 0.8893372
cplSum/100
[1] 1.110294

Based on these data, would you conclude that the observed network demonstrates small world properties? Why or why not? I would say the observed network does not demonstrate small world properties. In order to be a small world network, the network should have high local clustering coefficient and low average path length to other actors. In the observed network, ACC = 0.8279915 and CPL = 1.771429. Now comparing the data to the random generated network, we can find out that ACC of the observed network is lower than the random network results and CPL of the observed network is higher than the random network. Therefore, the observed network does not demonstrate small world properities.

Wrapping up

To complete the lab, make sure output/previews have been generated for each block of code. Then click the “Publish” button on the upper right hand corner of this screen and sign up for an RPubs account. Submit the URL of the published, completed lab on Canvas.

LS0tCnRpdGxlOiAnRGVzY3JpcHRpdmUgQW5hbHl0aWMgRXhlcmNpc2UgMTogVmlzdWFsaXppbmcgYW5kIEludGVycHJldGluZyBOZXR3b3JrcycKb3V0cHV0OgogIGh0bWxfbm90ZWJvb2s6IGRlZmF1bHQKICBodG1sX2RvY3VtZW50OiBkZWZhdWx0CiAgcGRmX2RvY3VtZW50OiBkZWZhdWx0CiAgd29yZF9kb2N1bWVudDogZGVmYXVsdAotLS0KKipTTkEgR3JhZCBTZW1pbmFyLCBGYWxsIDIwMTcqKgoqKkR1ZToqKiBPY3RvYmVyIDI0dGgsIDExOjU5IHBtCioqTmFtZSBvZiBTdHVkZW50Kio6IEp1ZSBXdQoKVGhlIHB1cnBvc2Ugb2YgdGhpcyBsYWIgaXMgdG8gZGV2ZWxvcCB5b3VyIGZhbWlsaWFyaXR5IGNvbmR1Y3RpbmcgZGVzY3JpcHRpdmUgbmV0d29yayBhbmFseXNpcyB1c2luZyB0aGUgc3RhdGlzdGljYWwgc29mdHdhcmUgcGFja2FnZSBSLiBUaGlzIGFzc2lnbm1lbnQgd2lsbCBtYWtlIHVzZSBvZiBhIGRhdGEgc2V0IHlvdSBjb2xsZWN0IGJ5IGRlZmluaW5nIGEgc2VhcmNoIHF1ZXJ5IChhIGNvbGxlY3Rpb24gb2YgeW91ciB1c2VyLWRlZmluZWQgc2VhcmNoIHRlcm1zKSBmcm9tIHRoZSAqW05ldyBZb3JrIFRpbWVzXSh3d3cubnl0aW1lcy5jb20pKidzIEFydGljbGUgU2VhcmNoIFtBcHBsaWNhdGlvbiBQcm9ncmFtbWluZyBJbnRlcmZhY2VdKGh0dHBzOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL0FwcGxpY2F0aW9uX3Byb2dyYW1taW5nX2ludGVyZmFjZSkuIE5ldHdvcmtzIGFyZSBnZW5lcmF0ZWQgZnJvbSB0aGUgY28tb2NjdXJyZW5jZXMgYmV0d2VlbiBzZWFyY2ggdGVybXMgaW5jbHVkZWQgaW4gdGhlIHNhbWUgc2VhcmNoIHF1ZXJ5LiBGb3IgZXhhbXBsZSwgYSBsaW5rIGV4aXN0cyBiZXR3ZWVuIOKAnGFwcGxl4oCdIGFuZCDigJxvcmFuZ2XigJ0gaWYgdGhlcmUgYXJlIGFydGljbGVzIGluIHRoZSAqTmV3IFlvcmsgVGltZXMqIHRoYXQgY29udGFpbmVkIHRoZXNlIHR3byB0ZXJtcy4gIFlvdSB3aWxsIGJlIHZpc3VhbGl6aW5nIGFuZCBpbnRlcnByZXRpbmcgaW5kaXZpZHVhbCBhbmQgZ2xvYmFsIG5ldHdvcmsgcHJvcGVydGllcyBvZiB0aGlzIG5ldHdvcmsuCgpZb3Ugd2lsbCBiZSBncmFkZWQgcHJpbWFyaWx5IG9uIHRoZSBjb21wbGV0ZW5lc3MgYW5kIGFjY3VyYWN5IG9mIHlvdXIgcmVzcG9uc2VzLCBidXQgdGhlIGNsYXJpdHkgb2YgdGhlIHByZXBhcmVkIHJlcG9ydCB3aWxsIGFsc28gYWZmZWN0IHlvdXIgZ3JhZGUuICBXaGlsZSBzdHVkZW50cyBtYXkgd29yayB0b2dldGhlciB0byBwZXJmb3JtIHRoZSBhbmFseXNpcywgZWFjaCBzdHVkZW50IG11c3Qgc3VibWl0IGhpcyBvciBoZXIgb3duIHJlcG9ydCBhbmQgaXMgcmVzcG9uc2libGUgZm9yIHdyaXRpbmcgdGhlIG5hcnJhdGl2ZSBpbiB0aGUgcmVwb3J0LiBZb3UgbXVzdCBhbnN3ZXIgYWxsIG9mIHRoZSBib2xkZWQgcXVlc3Rpb25zLgoKIyBQYXJ0IDE6IENvbGxlY3QgTmV0d29yayBEYXRhICgyMCBwdHMpCgpGb3IgdGhpcyBsYWIsIHlvdSB3aWxsIHNlYXJjaCB0aGUgKk5ldyBZb3JrIFRpbWVzKiwgc2F2ZSB0aGF0IGRhdGEsIGNyZWF0ZSBuZXR3b3JrcyBmcm9tIHRoYXQgZGF0YSwgY29tcGFyZSB0aGUgZGlmZmVyZW5jZXMgYW1vbmcgbmV0d29ya3MsIGFuZCBkZW1vbnN0cmF0ZSB5b3VyIHByb2ZpY2llbmN5IHdpdGggYmFzaWMgbmV0d29yayBkZXNjcmlwdGl2ZSBzdGF0aXN0aWNzLgoKIyMgTG9hZGluZyBhbmQgSW5zdGFsbGluZyBQYWNrYWdlcywgU2V0IFdvcmtpbmcgRGlyZWN0b3J5CgpXaGVuIHdvcmtpbmcgd2l0aCBSLCB5b3Ugc2hvdWxkIHJ1biBlYWNoIGxpbmUgb2YgY29kZSBpbmRpdmlkdWFsbHksIHVubGVzcyBpdCBpcyBwYXJ0IG9mIGEgZnVuY3Rpb24gZGVmaW5pdGlvbiwgc28geW91IGNhbiBzZWUgdGhlIHJlc3VsdHMuIEdlbmVyYWxseSBzcGVha2luZywgYW55IGxpbmUgb2YgY29kZSB0aGF0IGluY2x1ZGVzICd7JyAodGhlIGJlZ2lubmluZyBvZiBhIGZ1bmN0aW9uIGRlZmluaXRpb24pIHNob3VsZCBiZSBydW4gd2l0aCBhbGwgdGhlIG90aGVyIGxpbmVzIHVudGlsIHlvdSBoaXQgJ30nLgoKYGBge3J9CiMgTGluZXMgdGhhdCBzdGFydCB3aXRoIGEgaGFzaHRhZy9wb3VuZCBzeW1ib2wsIGxpa2UgdGhpcyBvbmUsIGFyZSBjb21tZW50IGxpbmVzLiBDb21tZW50IGxpbmVzIGFyZSBpZ25vcmVkIGJ5IFIgd2hlbiBpdCBpcyBpbnRlcnByZXRpbmcgY29kZS4KIyBZb3Ugb25seSBuZWVkIHRvIGluc3RhbGwgcGFja2FnZXMgb25jZS4gUmVtb3ZlIHRoZSAjIGluIGZyb250IG9mIGVhY2ggbGluZSBhbmQgdGhlbiBydW4gaXQgdG8gaW5zdGFsbCBlYWNoIHBhY2thZ2UuIEFmdGVyIHN1Y2Nlc3NmdWwgaW5zdGFsbGF0aW9uLCBkZWxldGUgdGhlIGxpbmUgb2YgY29kZSBvciByZXBsYWNlIHRoZSAjcyBzbyB0aGUgUiBOb3RlYm9vayBkb2Vzbid0IHJ1biBpbnRvIHByb2JsZW1zLgojIGluc3RhbGwucGFja2FnZXMoJ21hZ3JpdHRyJywgcmVwb3MgPSAiaHR0cHM6Ly9jcmFuLnJzdHVkaW8uY29tIikKIyBpbnN0YWxsLnBhY2thZ2VzKCdpZ3JhcGgnLCByZXBvcyA9ICJodHRwczovL2NyYW4ucnN0dWRpby5jb20iKQojIGluc3RhbGwucGFja2FnZXMoJ2h0dHInLCByZXBvcyA9ICJodHRwczovL2NyYW4ucnN0dWRpby5jb20iKQojIGluc3RhbGwucGFja2FnZXMoJ2RhdGEudGFibGUnLCByZXBvcyA9ICJodHRwczovL2NyYW4ucnN0dWRpby5jb20iKQojIGluc3RhbGwucGFja2FnZXMoJ2RwbHlyJywgcmVwb3MgPSAiaHR0cHM6Ly9jcmFuLnJzdHVkaW8uY29tIikKIyBpbnN0YWxsLnBhY2thZ2VzKCd4bWwyJywgcmVwb3MgPSAiaHR0cHM6Ly9jcmFuLnJzdHVkaW8uY29tIikKIyBZb3UgbmVlZCB0byBsb2FkIHBhY2thZ2VzIGV2ZXJ5IHRpbWUgeW91IHJ1biB0aGUgc2NyaXB0IG9yIHJlc3RhcnQgUi4KbGlicmFyeShtYWdyaXR0cikKbGlicmFyeShodHRyKQpsaWJyYXJ5KGRhdGEudGFibGUpCmxpYnJhcnkoaWdyYXBoKQpsaWJyYXJ5KGRwbHlyKQpsaWJyYXJ5KHhtbDIpCiMgU2V0IHlvdXIgZGlyZWN0b3J5IGZvciB0aGUgcHJvamVjdAojIFlvdSBjYW4gZWl0aGVyIGVudGVyIHlvdXIgZmlsZW5hbWUgcGF0aCB3aXRoaW4gdGhlIHBhcmVudGhlc2VzIGJlbG93IGFuZCByZW1vdmUgdGhlICMgY3JlYXRpbmcgdGhlIGNvbW1lbnQsIG9yIHNlbGVjdCAiU2Vzc2lvbiA+IFNldCBXb3JraW5nIERpcmVjdG9yeSAuLi4gU291cmNlIEZpbGUgTG9jYXRpb24iIGluIFIgU3R1ZGlvLgojIHNldHdkKCJJbnB1dCBEaXJlY3RvcnkiKQpgYGAKCiMjIENob29zZSBhIHRvcGljIGZvciB5b3VyIHNlYXJjaCB0ZXJtcwoKWW91IGNhbiBkZWNpZGUgc2VhcmNoIHRlcm1zIGJhc2VkIG9uIHBlcnNvbmFsIGludGVyZXN0cywgcmVzZWFyY2ggaW50ZXJlc3RzLCBvciBwb3B1bGFyIHRvcGljYWwgYXJlYXMsIGFtb25nIG90aGVycy4gWW91IGhhdmUgZmxleGliaWxpdHkgaW4gc2VsZWN0aW5nIHlvdXIgc2VhcmNoIHRlcm0gbGlzdC4gRm9yIGV4YW1wbGUsIHlvdSBjYW4gc2VhcmNoIGZvciBzb21lIGNvbW1lcmNpYWwgYnJhbmRzLCBjZWxlYnJpdGllcywgY291bnRyaWVzLCB1bml2ZXJzaXRpZXMsIGV0Yy4gSXQgd2lsbCBiZSBtb3N0IHVzZWZ1bCBpZiB5b3UgY2hvb3NlIGEgY29sbGVjdGlvbiBvZiB3b3JkcyB0aGF0IGFyZSBub3QgYWxsIGV4dHJlbWVseSBjb21tb24uIFRoaW5rIGFib3V0IGEgc2V0IG9mIHdvcmRzIHRoYXQgbWlnaHQgaGF2ZSBpbnRlcmVzdGluZyBjby1vY2N1cnJlbmNlcyBpbiBhcnRpY2xlcyB3aXRoaW4gdGhlICpOZXcgWW9yayBUaW1lcyogd2Vic2l0ZS4gRm9yIGV4YW1wbGUsIHlvdSBtaWdodCBiZSBpbnRlcmVzdGVkIGluIHRoZSBsYXN0IG5hbWVzIG9mIGV2ZXJ5IFNlbmF0b3IgaW52b2x2ZWQgaW4gYSBjZXJ0YWluIHBvbGl0aWNhbCBkZWJhdGUsIGZvb3RiYWxsIHRlYW1zLCBvciBjaXRpZXMgYW5kIHRoZWlyIGNvLW9jY3VycmVuY2UgaW4gbmV3cyBhcnRpY2xlcy4gR2VuZXJhbGx5IHNwZWFraW5nLCBwcm9wZXIgbm91bnMgYXJlIGJlc3QsIGJ1dCB5b3UgbWlnaHQgaGF2ZSBjb21wZWxsaW5nIHJlYXNvbnMgdG8gY2hvb3NlIHZlcmJzIG9yIGFkamVjdGl2ZXMuIFlvdSBtaWdodCB3YW50IHRvIHRocm93IGEgY291cGxlIG9mIHRlcm1zIGluIHRoYXQgYXJlbid0IHRoZW1hdGljYWxseSByZWxhdGVkIHRvIG1ha2Ugc3VyZSB5b3UgZG9uJ3QgZ2V0IGEgdG90YWxseSBjb25uZWN0ZWQgY29tcG9uZW50LiBUaGUgbW9yZSBpbnRlcmVzdGluZyB5b3VyIG5ldHdvcmsgaXMgaW4gdGVybXMgb2YgZGlmZmVyaW5nIGNlbnRyYWxpdHksIGRpc3RpbmN0IGNvbXBvbmVudHMsIGV0Yy4sIHRoZSBlYXNpZXIgaXQgd2lsbCBiZSB0byBkbyB0aGUgd3JpdHRlbiBhbmFseXNpcy4gS2VlcCBpbiBtaW5kIHRoYXQgdGhlIEFydGljbGUgU2VhcmNoIGFyY2hpdmUgaXMgdmVyeSBsYXJnZTsgbWFueSB0ZXJtcyBjby1vY2N1ci4gWW91IG1pZ2h0IHdhbnQgdG8gY29uc2lkZXIgdHdvIHRlbnVvdXNseSByZWxhdGVkIHN1YmplY3RzLiBUaGUgZXhhbXBsZSBmaWxlIHVzZXMgZm91ciBmb290YmFsbCB0ZWFtcyBhbmQgdGhlaXIgaG9tZSBzZW5hdG9ycywgcGx1cyBhIGZldyB0b3BpY2FsIHRlcm1zLgoKIyMgQ3JlYXRlIHlvdXIgdGV4dCBpbnB1dAoKQ3JlYXRlIGEgcGxhaW4gdGV4dCBmaWxlIHdpdGggLnR4dCBleHRlbnNpb24gaW4gdGhlIHNhbWUgZGlyZWN0b3J5IGFzIHRoZSBSIE1hcmtkb3duIE5vdGVib29rIHVzZWQgaW4gdGhpcyBhc3NpZ25tZW50LiBNYWtlIGEgbm90ZSBvZiB0aGUgZmlsZSBuYW1lIGZvciB1c2UgaW4gdGhlIG5leHQgY29kZSBzbmlwcGV0LiBQbGFjZSBvbmUgc2VhcmNoIHRlcm0gcGVyIGxpbmUsIGFuZCB1c2UgMTXigJMyMCB0ZXJtcy4gIFlvdSdsbCBhbHNvIGxpa2VseSB3YW50IHRvIGFkZCBxdW90YXRpb24gbWFya3MgYXJvdW5kIHlvdXIgc2VhcmNoIHRlcm1zIHRvIGVuc3VyZSB0aGF0IHlvdSdyZSBvbmx5IHJlY2VpdmluZyByZXN1bHRzIGZvciB0aGUgY29tcGxldGUgdGVybS4gTk9URTogVGhlIGZ1bmN0aW9uIHdpbGwgcHJvY2VzcyB5b3VyIHRlcm1zIHNvIHRoYXQgdGhleSB3b3JrIGluIHRoZSBVUkwgcmVxdWVzdC4gWW91IGRvIG5vdCBuZWVkIHRvIGVuY29kZSBub24tYWxwaGFiZXRpYyBjaGFyYWN0ZXJzLgoKVGhlIHRleHQgZmlsZSBjYW5ub3QgaW5jbHVkZSBhbnkgYWRkaXRpb25hbCBpbmZvcm1hdGlvbiBvciBjaGFyYWN0ZXJzIGFuZCBpdCBtdXN0IGJlIGEgLnR4dCBmaWxlOyBXb3JkIG9yIFJURiBkb2N1bWVudHMgd29u4oCZdCB3b3JrLgoKIyMgQW5hbHlzaXMKCioqYS4JUHJvdmlkZSBhIGhpZ2ggbGV2ZWwgb3ZlcnZpZXcgb2YgdGhlIHRlcm1zIHlvdSBpbmNsdWRlZCBpbiB0aGUgc2VhcmNoIHF1ZXJ5LioqClRoZSB0ZXJtcyBpbiB0aGUgc2VhcmNoIHF1ZXJ5IGluY2x1ZGUgTkZMIHRlYW1zLCBwbGF5ZXJzLCBhbmQgb2ZmaWNlcnMgKE5ldyBPcmxlYW5zIFNhaW50cywgVGFtcGEgQmF5IEJ1Y2NhbmVlcnMsIENhcm9saW5hIFBhbnRoZXJzLCBBdGxhbnRhIEZhbGNvbnMsIFJvZ2VyIEdvb2RlbGwsIENvbGluIEthZXBlcm5pY2spLCBhbmQgcG9saXRpY2FsIGZpZ3VyZXMgKFN0ZXZlIFNjYWxpc2UsIFNlbi4gQmlsbCBDYXNzaWR5LCBTZW4uIEJpbGwgTmVsc29uLCBTZW4uIE1hcmNvIFJ1YmlvLCBTZW4uIExpbmRzZXkgR3JhaGFtLCBTZW4uIFRpbSBTY290dCwgU2VuLiBKb2hubnkgSXNha3NvbiwgU2VuLiBEYXZpZCBQZXJkdWUsIERvbmFsZCBUcnVtcCkuCgoqKmIuCVdoeSBkaWQgeW91IGNob29zZSB0aGlzIGNvbGxlY3Rpb24gb2YgdGVybXM/ICBXZXJlIHRoZXJlIHNvbWUgc3BlY2lmaWMgb3ZlcmFyY2hpbmcgcXVlc3Rpb27igJRpbnRlbGxlY3R1YWwgb3IgZXh0cmFjdXJyaWN1bGFyIGN1cmlvc2l0eeKAlHRoYXQgbW90aXZhdGVkIHRoaXMgY29sbGVjdGlvbiBvZiB0ZXJtcz8qKgpJIHVzZWQgdGhlIHByb3ZpZGVkIGRhdGFzZXQsIGJ1dCBJIHdhcyBjdXJpb3VzIGFib3V0IGhvdyBwZW9wbGUgKG9yIG9yZ2FuaXphdGlvbnMpIGluIHBvbGl0aWNzIGFuZCBzcG9ydHMgcmVsYXRlZCB0byBlYWNoIG90aGVyLiBGb3IgZXhhbXBsZSwgd2hhdCBpcyB0aGUgcG9saXRpY2FsIHRlbmRlbmN5IG9mIHRlYW1zIGFuZCBwZW9wbGUgaW4gTkZMPyBJcyB0aGVyZSBmaW5hbmNpYWwgaW50ZXJlc3QgYmV0d2VlbiBzcG9ydHMgdGVhbXMgYW5kIHBvbGl0aWNhbCBmaWd1cmVzPwoKKipjLglIb3cgZGlkIHlvdSBkZWNpZGUgd2hpY2ggdGVybXMgdG8gdXNlIGluIHRoZSBzZWFyY2ggcXVlcnk/IFdlcmUgdGhlc2UgdGVybXMgeW91IGludHVpdGl2ZWx5IGRlZW1lZCBpbXBvcnRhbnQ/IFdlcmUgdGhleSBjdWxsZWQgZnJvbSBhIHNwZWNpZmljIHNvdXJjZSBvciB0aGUgcmVzdWx0IG9mIHNvbWUgc2VwYXJhdGUgYW5hbHlzaXMgb3Igc2VhcmNoIHF1ZXJ5PyoqCk9yaWdpbmFsbHkgSSB3YXMgaW50ZXJlc3RlZCBpbiB0aGUgZGlwbG9tYXRpYyByZWxhdGlvbnMgYmV0d2VlbiBjb3VudHJpZXMgKGVzcGVjaWFsbHkgaG93IFVTIHZpZXdzIENoaW5hIGFuZCB3aGV0aGVyIGl0IGlzIGJpYXNlZCBvciBub3QpLCBidXQgSSBjb3VsZG4ndCBzdWNjZXNzZnVsbHkgY29sbGVjdCB0aGUgZGF0YSBJIHdhbnRlZC4gSW4gb3JkZXIgdG8gZmluaXNoIHRoZSBhc3NpZ25tZW50LCBJIGp1c3QgdXNlZCB0aGUgcHJvdmlkZWQgZGF0YXNldC4gCgoqKmQuCVdoYXQgYXJlIHRoZSBpbnNpZ2h0cyB5b3UgaG9wZSB0byBnbGVhbiBieSBsb29raW5nIGF0IHRoZSBuZXR3b3JrIG9mIHRlcm1zIGluIHRlcm1zIG9mIGluZGl2aWR1YWwgbm9kZSBtZXRyaWNzLCBzdWItZ3JvdXBpbmcgb2Ygbm9kZXMsIG92ZXJhbGwgZ2xvYmFsIG5ldHdvcmsgcHJvcGVydGllcz8qKgpNeSBndWVzcyBpcyB0aGF0IERvbmFsZCBUcnVtcCB3aWxsIHByb2JhYmx5IGdldCBtb3N0IGxpbmtzIGFuZCBiZSB0aGUgaGlnaGVzdCBpbiBkZWdyZWUgY2VudHJhbGl0eSBiZWNhdXNlIGhlIGlzIHRoZSBQcmVzaWRlbnQgb2YgdGhlIFVuaXRlZCBTdGF0ZXMgYW5kIGV2ZXJ5IHdvcmQgaW4gdGhlIHF1ZXJ5IGlzIEFtZXJpY2FuLiBBdCBzdWItZ3JvdXAgbGV2ZWwsIEkgdGhpbmsgaXQgaXMgcHJvYmFibHkgZ29pbmcgdG8gYmUgdHdvIGNvbW11bml0aWVzLS0tb25lIHNldCBvZiBub2RlcyBmb3IgTkZMIHJlbGF0ZWQgYW5kIG9uZSBzZXQgb2Ygbm9kZXMgZm9yIHBvbGl0aWNzIHJlbGF0ZWQtLS10aGF0IGludGVyYWN0IGEgbG90IHdpdGhpbiB0aGUgY29tbXVuaXRpZXMuIEF0IGdsb2JhbCBsZXZlbCwgSSBndWVzcyB0aGlzIG5ldHdvcmsgd2lsbCBiZSBjZW50cmFsaXplZC4gCgojIyBXb3JraW5nIHdpdGggdGhlIEFQSSB0byBDb2xsZWN0IFlvdXIgRGF0YQpUaGUgKk5ldyBZb3JrIFRpbWVzKiBjb250cm9scyBhY2Nlc3MgdG8gaXRzIEFQSSBieSBhc3NpZ25pbmcgZWFjaCB1c2VyIGEga2V5LiBFYWNoIGtleSBoYXMgYSBsaW1pdGVkIG51bWJlciBvZiBjYWxscyB0aGF0IGNhbiBiZSBtYWRlIHdpdGhpbiBhIGNlcnRhaW4gdGltZSBwZXJpb2QuIFlvdSBjYW4gcmVhZCBtb3JlIGFib3V0IHRoZSBsaW1pdGF0aW9ucyBvZiB0aGUgQVBJIHN5c3RlbSBbaGVyZV0oaHR0cDovL2RldmVsb3Blci5ueXRpbWVzLmNvbS9hcnRpY2xlX3NlYXJjaF92Mi5qc29uIykuCgpZb3Ugd2lsbCBuZWVkIHRvIGNyZWF0ZSB5b3VyIG93biBBUEkga2V5IHRvIGNvbXBsZXRlIHRoaXMgYXNzaWdubWVudC4gR28gdG8gdGhlICpOZXcgWW9yayBUaW1lcyogW2RldmVsb3BlcnMgcGFnZV0oaHR0cHM6Ly9kZXZlbG9wZXIubnl0aW1lcy5jb20vc2lnbnVwKSBhbmQgcmVxdWVzdCBhIGtleS4gWW91IHdpbGwgY29weSB0aGF0IGtleSAocmVjZWl2ZWQgdmlhIGVtYWlsKSBpbnRvIHRoZSBhcGkgdmFyaWFibGUgYmVsb3cuCgpgYGB7ciwgZXZhbCA9IEZBTFNFfQojIEltcG9ydCB5b3VyIHdvcmQgbGlzdApuYW1lX29mX2ZpbGUgPC0gIk5GTC50eHQiICMgQ3JlYXRlcyBhIHZhcmlhYmxlIGNhbGxlZCBuYW1lX29mX2ZpbGUgdGhhdCB5b3Ugc2hvdWxkIHBvcHVsYXRlIHdpdGggdGhlIG5hbWUgb2YgeW91ciB0ZXh0IGZpbGUgYmV0d2VlbiBxdW90YXRpb24gbWFya3MuCndvcmRfbGlzdCA8LSByZWFkLnRhYmxlKG5hbWVfb2ZfZmlsZSwgc2VwID0gIlxuIiwgc3RyaW5nc0FzRmFjdG9ycyA9IEYpICU+JSB1bmxpc3QgJT4lIGFzLnZlY3RvciAjIFJlYWRzIHRoZSBjb250ZW50IG9mIHlvdXIgZmlsZSBpbnRvIGEgdmFyaWFibGUuCm51bV93b3JkcyA8LSBsZW5ndGgod29yZF9saXN0KSAjIENyZWF0ZXMgYSB2YXJpYWJsZSB3aXRoIHRoZSBudW1iZXIgb2Ygd29yZHMgaW4geW91ciBsaXN0Lgp1cmxfYmFzZSA8LSAiaHR0cHM6Ly9hcGkubnl0aW1lcy5jb20vc3ZjL3NlYXJjaC92Mi9hcnRpY2xlc2VhcmNoLmpzb24iCiMgV2hlbiB5b3UgcmVjZWl2ZSB0aGUgZW1haWwgd2l0aCB5b3VyIEFQSSBrZXksIHBhc3RlIGl0IGJlbG93IGJldHdlZW4gdGhlIHF1b3RhdGlvbiBtYXJrcy4KYXBpIDwtICc3NmYwNmMzZDE2YzU0MjgwYjkyMzNkOGYzZDc2ZTRiZicKYGBgCgpPdXIgZmlyc3QgZnVuY3Rpb24gd2lsbCBnYXRoZXIgYWxsIG9mIHRoZSBzZWFyY2ggdGVybXMgYW5kIHRoZWlyIG51bWJlciBvZiBoaXRzIHRvIGJlIHBsYWNlZCBpbiBhIHRhYmxlLiBBbGwgbGluZXMgb2YgYSBmdW5jdGlvbiBzaG91bGQgYmUgcnVuIHRvZ2V0aGVyLgoKYGBge3IsIGV2YWwgPSBGQUxTRX0KR2V0X2hpdHNfb25lIDwtIGZ1bmN0aW9uKGtleXdvcmQxKSB7CiAgU3lzLnNsZWVwKHRpbWU9MykKICB1cmwgPC0gcGFzdGUwKHVybF9iYXNlLCAiP2FwaS1rZXk9IiwgYXBpLCAiJnE9IiwgVVJMZW5jb2RlKGtleXdvcmQxKSwiJmJlZ2luX2RhdGU9IiwiMjAxNjAxMDEiKSAjIEJlZ2luIGRhdGUgaXMgaW4gZm9ybWF0IFlZWVlNTUREOyB5b3UgY2FuIGNoYW5nZSBpdCBpZiB5b3Ugd2FudCBvbmx5IG1vcmUgcmVjZW50IHJlc3VsdHMsIGZvciBleGFtcGxlLgogICMgVGhlIG51bWJlciBvZiByZXN1bHRzCiAgcHJpbnQoa2V5d29yZDEpCiAgaGl0cyA8LSBjb250ZW50KEdFVCh1cmwpKSRyZXNwb25zZSRtZXRhJGhpdHMgJT4lIGFzLm51bWVyaWMKICBwcmludChoaXRzKQogICMgUHV0IHJlc3VsdHMgaW4gdGFibGUKICBjKFNlYXJjaFRlcm09a2V5d29yZDEsUmVzdWx0c1RvdGFsPWhpdHMpCn0KYGBgCgpOb3cgd2Ugd2lsbCBpbnZva2Ugb3VyIGZ1bmN0aW9uIHRvIHB1dCBpbmZvcm1hdGlvbiBmcm9tIHRoZSBBUEkgaW50byBvdXIgZ2xvYmFsIGVudmlyb25tZW50LgoKYGBge3IsIGV2YWwgPSBGQUxTRX0KI0NyZWF0ZSBhIHRhYmxlIG9mIHlvdXIgd29yZHMgYW5kIHRoZWlyIG51bWJlciBvZiByZXN1bHRzLgp0b3RhbF90YWJsZSA8LSB0KHNhcHBseSh3b3JkX2xpc3QsR2V0X2hpdHNfb25lKSkKdG90YWxfdGFibGUgPC0gYXMuZGF0YS5mcmFtZSh0b3RhbF90YWJsZSkKdG90YWxfdGFibGUkUmVzdWx0c1RvdGFsIDwtIGFzLm51bWVyaWMoYXMuY2hhcmFjdGVyKHRvdGFsX3RhYmxlJFJlc3VsdHNUb3RhbCkpCmBgYApJZiB5b3UgZ2V0IHplcm8gaGl0cyBmb3IgYW55IG9mIHRoZXNlIHRlcm1zLCB5b3Ugc2hvdWxkIHN1YnN0aXR1dGUgdGhhdCB0ZXJtIGZvciBzb21ldGhpZ24gZWxzZSBhbmQgcmVydW4gdGhlIGxhYiB1cCB0byB0aGlzIHBvaW50LgpOZXh0LCB3ZSB3aWxsIGRlZmluZSB0aGUgZnVuY3Rpb24gdGhhdCB3aWxsIGNvbGxlY3QgdGhlIGFydGljbGUgY28tb2NjdXJlbmNlcyBuZXR3b3JrLgpgYGB7ciwgZXZhbCA9IEZBTFNFfQpHZXRfaGl0c190d28gPC0gZnVuY3Rpb24ocm93X2lucHV0KSB7CiAga2V5d29yZDEgPC0gcm93X2lucHV0WzFdCiAga2V5d29yZDIgPC0gcm93X2lucHV0WzJdCiAgdXJsIDwtIHBhc3RlMCh1cmxfYmFzZSwgIj9hcGkta2V5PSIsIGFwaSwgIiZxPSIsIFVSTGVuY29kZShrZXl3b3JkMSksIisiLCBVUkxlbmNvZGUoa2V5d29yZDIpLCImYmVnaW5fZGF0ZT0iLCIyMDE2MDEwMSIpICNtYXRjaCB3LyBCZWdpbiBEYXRlIGluIEdldF9oaXRzX29uZS4KICAjIFRoZSBudW1iZXIgb2YgcmVzdWx0cwogIHByaW50KHBhc3RlMChrZXl3b3JkMSwiICIsa2V5d29yZDIpKSAKICBoaXRzIDwtIGNvbnRlbnQoR0VUKHVybCkpJHJlc3BvbnNlJG1ldGEkaGl0cyAlPiUgYXMubnVtZXJpYwogIHByaW50KGhpdHMpCiAgU3lzLnNsZWVwKHRpbWU9MykKICAjIFB1dCByZXN1bHRzIGluIHRhYmxlCiAgYyhTZWFyY2hUZXJtMT1rZXl3b3JkMSxTZWFyY2hUZXJtMj1rZXl3b3JkMixDb09jY3VycmVuY2VzPWhpdHMpCn0gCmBgYAoKSW4gdGhpcyBuZXh0IHN0ZXAsIHdlIHdpbGwgY2FsbCB0aGUgQVBJIGFuZCBjb2xsZWN0IHRoZSBjby1vY2N1cnJlbmNlIG5ldHdvcmsuIFRoaXMgbWF5IHRha2Ugc29tZSB0aW1lLiBJZiB5b3UgcmVjZWl2ZSAibnVtZXJpYygwKSIgaW4gYW55IG9mIHlvdXIgcmVzcG9zbmVzLCB5b3UndmUgbGlrZWx5IGhpdCB5b3VyIEFQSSBrZXkgbGltaXQgYW5kIHdpbGwgZWl0aGVyIG5lZWQgdG8gd2FpdCBmb3IgdGhlIGNhbGxzIHRvIHJlc2V0ICgyNCBob3Vycykgb3IgcmVxdWVzdCBhIG5ldyBrZXkuIElmIHlvdSByZWNlaXZlIHRoZSBlcnJvciBtZXNzYWdlICIkIG9wZXJhdG9yIGlzIGludmFsaWQgZm9yIGF0b21pYyB2ZWN0b3JzLCIgeW91IGhhdmUgYWxzbyBoaXQgdGhlIEFQSSBjYWxsIGxpbWl0LiBUaGlzIGNvdWxkIGJlIGR1ZSB0byBydW5uaW5nIHRoZSBzY3JpcHQgbXVsdGlwbGUgdGltZXMsIG9yIGR1ZSB0byBoaXR0aW5nIHRvbyBtYW55IHJlc3VsdHMgYmFzZWQgb24gdmVyeSBjb21tb24gc2VhcmNoIHRlcm1zLiBSZXF1ZXN0IGEgbmV3IEFQSSwgc2hvcnRlbiB5b3VyIHdvcmQgbGlzdCwgYW5kIHRyeSBhZ2Fpbi4gRG9uJ3QgZm9yZ2V0IHlvdSBuZWVkIHRvIHJlbG9hZCB5b3VyIHdvcmQgbGlzdCBmcm9tIHRoZSBmaXJzdCBwYXJ0IG9mIHRoZSBMYWIgaW4gb3JkZXIgdG8gZ2V0IGEgZGlmZmVyZW50IHNldCBvZiByZXN1bHRzISBZb3UgbXVzdCBhbHNvIHJlcnVuIHRoZSBmdW5jdGlvbnMgdG8gcmVhc3NpZ24gdGhlIEFQSSB2YWx1ZS4gSWYgbm9uZSBvZiB5b3VyIHJlc3VsdHMgY29tZSBiYWNrIGFzICIwLCIgeW91IG1pZ2h0IHdhbnQgdG8gcmVkbyB5b3VyIHNlYXJjaCB3aXRoIHRoZSBhcHByb3ByaWF0ZSB3b3Jkcy4KCmBgYHtyLCBldmFsID0gRkFMU0V9CiMgQ29udmVydCB0aGUgcGFpcnMgbGlzdCBpbnRvIGEgdGFibGUKcGFpcnNfbGlzdCA8LSBleHBhbmQuZ3JpZCh3b3JkX2xpc3Qsd29yZF9saXN0KSAlPiUgZmlsdGVyKFZhcjEgIT0gVmFyMikKcGFpcnNfbGlzdCA8LSB0KGNvbWJuKHdvcmRfbGlzdCwyKSkKI0NyZWF0ZSBhIG5ldHdvcmsgdGFibGUsIHJ1biB0aGUgR2V0X2hpdHNfdHdvIGZ1bmN0aW9uIHVzaW5nIHRoZSBwYWlycyBsaXN0cwpuZXR3b3JrX3RhYmxlIDwtIHQoYXBwbHkocGFpcnNfbGlzdCwxLEdldF9oaXRzX3R3bykpCiNDb252ZXJ0IHRoZSBuZXR3b3JrIHRhYmxlIGludG8gYSBkYXRhZnJhbWUKbmV0d29ya190YWJsZSA8LSBhcy5kYXRhLmZyYW1lKG5ldHdvcmtfdGFibGUpCiMgUmVhZCBlYWNoIHRoZSBjb250ZW50IG9mIGVhY2ggaXRlbSB3aXRoaW4gdGhlICRDb09jY3VycmVlbmNlcyBmYWN0b3IgYXMgY2hhcmFjdGVycywgCiMgdGhlbiBmb3JjZSB0aG9zZSBjaGFyYWN0ZXJzIGludG8gdGhlICJudW1lcmljIiBvciAiZG91YmxlIiB0eXBlLgpuZXR3b3JrX3RhYmxlJENvT2NjdXJyZW5jZXMgPC0gYXMubnVtZXJpYyhhcy5jaGFyYWN0ZXIobmV0d29ya190YWJsZSRDb09jY3VycmVuY2VzKSkKIyBDb252ZXJ0IGRhdGEgdG8gZGF0YS50YWJsZSB0eXBlLgp0b3RhbF90YWJsZSA8LSBhcy5kYXRhLnRhYmxlKHRvdGFsX3RhYmxlKQpuZXR3b3JrX3RhYmxlIDwtIGFzLmRhdGEudGFibGUobmV0d29ya190YWJsZSkKCiMgUmVtb3ZlIHplcm8gZWRnZXMgZnJvbSB5b3VyIG5ldHdvcmsKbmV0d29ya190YWJsZSA8LSBuZXR3b3JrX3RhYmxlWyFDb09jY3VycmVuY2VzPT0wXSAKCiMgQ3JlYXRlIGEgZ3JhcGggb2JqZWN0IHdpdGggeW91ciBkYXRhCmdfdmFsdWVkIDwtIGdyYXBoX2Zyb21fZGF0YV9mcmFtZShkID0gbmV0d29ya190YWJsZVssMTozLHdpdGg9RkFMU0VdLGRpcmVjdGVkID0gRkFMU0UsdmVydGljZXMgPSB0b3RhbF90YWJsZSkKCiMgSWYgeW91J3JlIGhhdmluZyB0cm91YmxlIHdpdGggZGF0YSBjb2xsZWN0aW9uLCB5b3UgY2FuIGxvYWQgdGhlICdORkwgTGFiIFJlc3VsdHMuUkRhdGEnIGZpbGUgbm93IGJ5IGNsaWNraW5nIHRoZSBvcGVuIGZvbGRlciBpY29uIG9uIHRoZSAiRW52aXJvbm1lbnQiIiB0YWIgYW5kIGNvbnRpbnVlIHRoZSBsYWIgZnJvbSBoZXJlLiBZb3UnbGwgbmVlZCB0byBmaWd1cmUgb3V0IHdoYXQgdGhlIHNpZ25pZmljYW5jZSBvZiB0aGUgdGVybXMgYXJlIHlvdXJzZWxmLCBob3dldmVyLgojIFlvdSBzaG91bGQgc2F2ZSB5b3VyIGRhdGEgYXQgdGhpcyBwb2ludCBieSBjbGlja2luZyB0aGUgZmxvcHB5IGRpc2sgaWNvbiB1bmRlciB0aGUgIkVudmlyb25tZW50IiB0YWIuCmBgYAoKIyMgQW5hbHlzaXMKCioqSXMgdGhlIGdyYXBoIGRpcmVjdGVkIG9yIHVuZGlyZWN0ZWQ/KiogClVuZGlyZWN0ZWQKCioqSG93IG1hbnkgbm9kZXMgYW5kIGxpbmtzIGRvZXMgeW91ciBuZXR3b3JrIGhhdmU/ICoqClRoZXJlIGFyZSAxNSBub2RlcyBhbmQgMzUgbGlua3MuCmBgYHtyfQpudW1WZXJ0aWNlcyA8LSB2Y291bnQoZ192YWx1ZWQpCm51bVZlcnRpY2VzCm51bUVkZ2VzIDwtIGVjb3VudChnX3ZhbHVlZCkKbnVtRWRnZXMKYGBgCgoqKldoYXQgaXMgdGhlIG51bWJlciBvZiBwb3NzaWJsZSBsaW5rcyBpbiB5b3VyIG5ldHdvcms/ICoqClRoZXJlIGFyZSAxMDUgcG9zc2libGUgbGlua3MuCmBgYHtyfQptYXhFZGdlcyA8LSBudW1WZXJ0aWNlcyoobnVtVmVydGljZXMtMSkvMgptYXhFZGdlcwpgYGAKCioqV2hhdCBpcyB0aGUgZGVuc2l0eSBvZiB5b3VyIG5ldHdvcms/KiogClRoZSBkZW5zaXR5IGlzIDAuMzMzMzMzMwpgYGB7cn0KZ3JhcGhEZW5zaXR5IDwtIG51bUVkZ2VzL21heEVkZ2VzICMgbWFudWFsIGNhbGN1bGF0aW9uCmdyYXBoRGVuc2l0eQpncmFwaERlbnNpdHkxIDwtIGdyYXBoLmRlbnNpdHkoZ192YWx1ZWQpICMgdXNpbmcgdGhlIGdyYXBoLmRlbnNpdHkgZnVuY3Rpb24gZnJvbSBpZ3JhcGgKZ3JhcGhEZW5zaXR5MQpgYGAKCioqQnJpZWZseSBkZXNjcmliZSBob3cgeW91ciBjaG9pY2Ugb2YgZGF0YXNldCBtYXkgaW5mbHVlbmNlIHlvdXIgZmluZGluZ3MuKiogIFdoYXQgZGlmZmVyZW5jZXMgd291bGQgeW91IGV4cGVjdCBpZiB5b3UgdXNlIGRpZmZlcmVudCBzZWFyY2ggdGVybXM/IEFyZSB0aGUgY3VycmVudCBzZWFyY2ggdGVybXMgcmVsYXRlZCB0byBvbmUgYW5vdGhlcj8gSWYgc28sIGhvdz8gRG8geW91IHRoaW5rIHRoZSBsaW1pdGF0aW9uIHRvIG9uZSB3b3JkIG1pZ2h0IHNrZXcgeW91ciBhbnN3ZXJzPyAoaS5lLiBpZiB5b3XigJlyZSBpbnRlcmVzdGVkIGluIEhpbGxhcnkgQ2xpbnRvbiwgYnV0IHlvdSBpbmNsdWRlIOKAnENsaW50b27igJ0gYXMgYSB0ZXJtLCB5b3Ugd2lsbCBnZXQgc3RvcmllcyB0aGF0IG1lbnRpb24gQ2hlbHNlYSwgQmlsbCwgJiBldmVuIFAtRnVuayBBbGxzdGFyIEdlb3JnZSBDbGludG9uKS4KCkl0IHdhcyBnb29kIHRvIGluY2x1ZGUgdGhlIGZ1bGwgbmFtZXMgaW5zdGVhZCBvZiBsaW1pdGluZyB0aGUgd29yZHMgdG8ganVzdCBvbmUgc2luZ2xlIHdvcmQsIHdoaWNoIHJlZHVjZXMgdGhlIGNoYW5jZSBvZiBnZXR0aW5nIHVud2FudGVkIHdvcmRzLiBBbHNvLCBpbmNsdWRpbmcgU2VuLiBpbiBmcm9udCBvZiBwZW9wbGUncyBuYW1lcyBlbnN1cmVkIHRoYXQgdGhlIHJlc3VsdHMgd2UgZ2V0IGFyZSB0aGUgb25lcyBhYm91dCBwb2xpdGljcyB0aGF0IHdlIHdhbnRlZC4gSG93ZXZlciwgcGVvcGxlIG1pZ2h0IGFsc28gdXNlIFByZXNpZGVudCBUcnVtcCB3aGVuIHJlZmVycmluZyB0byBEb25hbGQgVHJ1bXAsIHRodXMgdXNpbmcgIkRvbmFsZCBUcnVtcCIgbWlnaHQgaW5mbHVlbmNlIHRoZSByZXN1bHRzIGJ5IGdpdmluZyB1cyBmZXdlciBkYXRhcG9pbnRzLiAKIyBQYXJ0IDI6IFZpc3VhbGl6ZSBZb3VyIE5ldHdvcmsgKDIwIHBvaW50cykKCkxldCdzIHN0YXJ0IGJ5IHZpc3VhbGl6aW5nIHRoZSBuZXR3b3JrIHRoYXQgd2UndmUgY29sbGVjdGVkIGZyb20gdGhlICpOZXcgWW9yayBUaW1lcyogQXJ0aWNsZSBTZWFyY2ggQVBJLiBXZSdsbCBuZWVkIHRvIGNob29zZSBub2RlIGNvbG9ycyBhbmQgc2V0IGEgbGF5b3V0LiBZb3UgY2FuIGxlYXJuIG1vcmUgYWJvdXQgRnJ1Y2h0ZXJtYW4gUmVpbmdvbGQgbGF5b3V0IGFuZCBvdGhlciBsYXlvdXRzIFtoZXJlXShodHRwOi8vaWdyYXBoLm9yZy9yL2RvYy9sYXlvdXRfd2l0aF9mci5odG1sKS4KCmBgYHtyfQojIyBMZWFybiBtb3JlIGFib3V0IHBsb3R0aW5nIHdpdGggaWdyYXBoCj8/IGlncmFwaC5wbG90dGluZwpjb2xiYXIgPSByYWluYm93KGxlbmd0aCh3b3JkX2xpc3QpKSAjIyB3ZSBhcmUgc2VsZWN0aW5nIGRpZmZlcmVudCBjb2xvcnMgdG8gY29ycmVzcG9uZCB0byBlYWNoIHdvcmQKVihnX3ZhbHVlZCkkY29sb3IgPSBjb2xiYXIKIyBTZXQgbGF5b3V0IGhlcmUgCkwgPSBsYXlvdXRfd2l0aF9mcihnX3ZhbHVlZCkgICMgRnJ1Y2h0ZXJtYW4gUmVpbmdvbGQKcGxvdChnX3ZhbHVlZCx2ZXJ0ZXguY29sb3I9VihnX3ZhbHVlZCkkY29sb3IsIGxheW91dCA9IEwsIHZlcnRleC5zaXplPTYpIAoKYGBgCiMjIEFuYWx5c2lzCioqSW4gYSBwYXJhZ3JhcGgsIGRlc2NyaWJlIHRoZSBtYWNyby1sZXZlbCBzdHJ1Y3R1cmUgb2YgeW91ciBncmFwaHMgYmFzZWQgb24gdGhlIEZydWNodGVybWFuIFJlaW5nb2xkIHZpc3VhbGl6YXRpb24uKioKSXMgaXQgYSBnaWFudCwgY29ubmVjdGVkIGNvbXBvbmVudCwgYXJlIHRoZXJlIGRpc3RpbmN0IHN1Yi1jb21wb25lbnRzLCBvciBhcmUgdGhlcmUgaXNvbGF0ZWQgY29tcG9uZW50cz8gIENhbiB5b3UgcmVjb2duaXplIGNvbW1vbiBmZWF0dXJlcyBvZiB0aGUgc3ViY29tcG9uZW50cz8gIERvZXMgdGhpcyB2aXN1YWxpemF0aW9uIGdpdmUgeW91IGFueSBpbnNpZ2h0IGludG8gdGhlIGNvLW9jY3VycmVuY2UgcGF0dGVybnMgb2YgdGhlIHNlYXJjaC10ZXJtcz8gIElmIHllcywgd2hhdD8gSWYgbm90LCB3aHk/CgpJdCBpcyBhIGdpYW50IGNvbXBvbmVudCB0aGF0IGV2ZXJ5b25lIGlzIGNvbm5lY3RlZC4gT24gdGhlIGZpcnN0IHNpZ2h0LCB0aGUgdmlzdWFsaXphdGlvbiB0ZWxscyBtZSB0aGF0IERvbmFsZCBUcnVtcCBpcyBhIGN1dHBvaW50LiBIZSBpcyB0aGUgb25lIHRoYXQgY29ubmVjdHMgdGhlIHBvbGl0aWNzIGNhbXAgYW5kIHRoZSBzcG9ydHMgY2FtcDsgaWYgd2UgcmVtb3ZlIGhpbSwgdGhlIG5ldHdvcmsgd2lsbCBiZWNvbWUgdHdvIGNvbXBvbmVudHMuIEluIGFkZGl0aW9uLCBpdCBpcyBhcHBhcmVudCB0aGF0IHRoZSBORkwgcmVsYXRlZCB3b3JkcyBhcmUgbW9yZSBjb25uZWN0ZWQgd2l0aGluIHRoZSBjb21tdW5pdHksIGNvbXBhcmVkIHRvIHRoZSBwb2xpdGljcyBjb21tdW5pdHkuCgpOb3cgd2UnbGwgY3JlYXRlIGEgc2Vjb25kIHZpc3VhbGl6YXRpb24gdXNpbmcgYSBkaWZmZXJlbnQgbGF5b3V0LgpgYGB7cn0KIyMgWW91IGNhbiBjaGFuZ2UgdGhlIGxheW91dCBieSBwaWNraW5nIG9uZSBvZiB0aGUgb3RoZXIgb3B0aW9ucy4gVW5jb21tZW50IG9uZSBvZiB0aGUgbGluZXMgYmVsb3cgYnkgZXJhc2luZyB0aGUgIyBhbmQgcnVubmluZyB0aGUgbGluZS4gVHJ5IHRvIGZpbmQgYSBsYXlvdXQgdGhhdCBnaXZlcyB5b3UgZGlmZmVyZW50IGluZm9ybWF0aW9uIHRoYXQgRnJ1Y2h0ZXJtYW4gUmVpbmdvbGQuCgogTCA9IGxheW91dF93aXRoX2RoKGdfdmFsdWVkKSAjIyBEYXZpZHNvbiBhbmQgSGFyZWwKCiMgTCA9IGxheW91dF93aXRoX2RybChnX3ZhbHVlZCkgIyMgRm9yY2UtZGlyZWN0ZWQKCiMgTCA9IGxheW91dF93aXRoX2trKGdfdmFsdWVkKSAjIyBTcHJpbmcKcGxvdChnX3ZhbHVlZCx2ZXJ0ZXguY29sb3I9VihnX3ZhbHVlZCkkY29sb3IsIGxheW91dCA9IEwsIHZlcnRleC5zaXplPTYpIApgYGAKIyMgQW5hbHlzaXMKCioqSW4gYSBwYXJhZ3JhcGgsIGNvbXBhcmUgYW5kIGNvbnRyYXN0IHRoZSBpbmZvcm1hdGlvbiBnaXZlbiB0byB5b3UgYnkgdGhlIHR3byBkaWZmZXJlbnQgbGF5b3V0cy4qKgpUaGUgdHdvIGxheW91dHMgYm90aCBzdWdnZXN0IHRoYXQgRG9uYWxkIFRydW1wIGhhcyB0aGUgaGlnaGVzdCBkZWdyZWUgY2VudHJhbGl0eSBhbmQgaGUgaXMgdGhlIGN1dHBvaW50LiBIb3dldmVyLCBpdCBzZWVtcyBsaWtlIHRoYXQgdGhlIHNwb3J0cyBjb21tdW5pdHkgaXMgbGVzcyBjZW50cmFsaXplZCBpbiB0aGUgc2Vjb25kIGxheW91dCB0aGFuIHRoZSBmaXJzdCBvbmUuIAoKIyBQYXJ0IDM6IENvbW11bml0eSBEZXRlY3Rpb24gQW5hbHlzaXMgd2l0aCBSICgyMCBQb2ludHMpCgpJZGVudGlmeWluZyBzdWJncm91cHMgd2l0aGluIGEgbmV0d29yayBpcyBvZiBncmVhdCBpbnRlcmVzdCB0byBzb2NpYWwgbmV0d29yayByZXNlYXJjaGVycywgc28gYSB2YXJpZXR5IG9mIGFsZ29yaXRobXMgaGF2ZSBiZWVuIGRldmVsb3BlZCB0byBpZGVudGlmeSBhbmQgbWVhc3VyZSBzdWJncm91cHMuICBXZSB3aWxsIHVzZSBzb21lIG9mIFLigJlzIGJ1aWx0LWluIHRvb2xzIHRvIGlkZW50aWZ5IHN1Ymdyb3VwcyBhbmQgY2VudHJhbCBub2RlcyBmb3IgdmlzdWFsIGluc3BlY3Rpb24uCgpGb3IgdGhlIHJlbWFpbmRlciBvZiB0aGUgdmlzdWFsaXphdGlvbnMgd2Ugd2lsbCB1c2UgdGhlIEZydWNodGVybWFuIFJlaW5nb2xkIGxheW91dC4KYGBge3J9CkwgPSBsYXlvdXRfd2l0aF9mcihnX3ZhbHVlZCkgCmBgYAoKQ2x1c3RlciB0aGUgbm9kZXMgaW4geW91ciBuZXR3b3JrLgpgYGB7cn0KIyBMZWFybiBtb3JlIGFib3V0IHRoZSBjbHVzdGVyaW5nIGFsZ29yaXRobS4KPz8gY2x1c3Rlcl93YWxrdHJhcApjbHVzdGVyIDwtIGNsdXN0ZXJfd2Fsa3RyYXAoZ192YWx1ZWQpCiMgRmluZCB0aGUgbnVtYmVyIG9mIGNsdXN0ZXJzCm1lbWJlcnNoaXAoY2x1c3RlcikgICAjIGFmZmlsaWF0aW9uIGxpc3QKbGVuZ3RoKHNpemVzKGNsdXN0ZXIpKSAjIG51bWJlciBvZiBjbHVzdGVycwojIEZpbmQgdGhlIHNpemUgdGhlIGVhY2ggY2x1c3RlciAKIyBOb3RlIHRoYXQgY29tbXVuaXRpZXMgd2l0aCBvbmUgbm9kZSBhcmUgaXNvbGF0ZXMsIG9yIGhhdmUgb25seSBhIHNpbmdsZSB0aWUKc2l6ZXMoY2x1c3RlcikgCmBgYAoKKipIb3cgbWFueSBjb21tdW5pdGllcyBoYXZlIGJlZW4gY3JlYXRlZD8qKgozCgoqKkhvdyBtYW55IG5vZGVzIGFyZSBpbiBlYWNoIGNvbW11bml0eT8qKgpJbiBuZXR3b3JrcyBjb250YWluaW5nIG5vZGUgYXR0cmlidXRlIGluZm9ybWF0aW9uLCB3ZSBjYW4gb2Z0ZW4gZ2FpbiBpbnNpZ2h0IGludG8gYSBuZXR3b3JrIGJ5IGxvb2tpbmcgYXQgdGhlIG5vZGVzIHRoYXQgZ2V0IHBsYWNlZCBpbiB0aGUgc2FtZSBwYXJ0aXRpb24uIAoKVGhlcmUgYXJlIDcsIDIsIGFuZCA2IG5vZGVzIGluIGVhY2ggY29tbXVuaXR5LgoKKipGb3IgeW91ciBuZXR3b3JrLCB3aGF0IG1pZ2h0IGVhY2ggY2x1c3RlciBvZiBub2RlcyBwb3RlbnRpYWxseSBoYXZlIGluIGNvbW1vbj8gRGVzY3JpYmUgZWFjaCBjbHVzdGVyLCBpdHMgbWVtYmVyc2hpcCwgYW5kIHRoZSByZWxhdGlvbnNoaXAgYmV0d2VlbiBub2RlcyBpbiB0aGUgY2x1c3Rlci4qKgpDbHVzdGVyIDEgaXMgYWxsIHBvbGl0aWNpYW5zLCBpbmNsdWRpbmcgc2V2ZXJhbCBzZW5hdG9ycywgdGhlIFByZXNpZGVudCwgYW5kIHRoZSBob3VzZSBtYWpvcml0eSB3aGlwLiBUaGUgcmVsYXRpb25zaGlwIGJldHdlZW4gdGhlc2Ugbm9kZXMgaXMgcHJvYmFibHkgd29yay4gQ2x1c3RlciAyIGlzIHR3byBzZW5hdG9ycy4gVGhleSBhcmUgYm90aCByZXB1YmxpY2FuLCBidXQgYmVjYXVzZSBJJ20gbm90IGZhbWlsaWFyIHdpdGggdGhlIHBvbGl0aWNzLCBJIGRvbid0IGtub3cgd2h5IHRoZXkgYXJlIGluIGEgZGlmZmVyZW50IGNsdXN0ZXIgb3RoZXIgdGhhbiBDbHVzdGVyIDEuIE15IGd1ZXNzIGlzIHRoYXQgdGhleSBtaWdodCBoYXZlIGRpZmZlcmVudCBvcGluaW9ucyB3aXRoIG90aGVyIHBvbGl0aWNpYW5zLiBDbHVzdGVyIDMgaXMgYWxsIE5GTCByZWxhdGVkLCBpbmNsdWRpbmcgTkZMIHRlYW1zLCBvZmZpY2VyLCBhbmQgcGxheWVyLiBUaGUgcmVsYXRpb25zaGlwIGJldHdlZW4gdGhlc2Ugbm9kZXMgaXMgcHJvYmFibHkgY29tcGV0aXRpb24gYW5kIHNlcnZpY2UuIAoKTmV4dCB3ZSB2aXN1YWxpemUgdGhlIGNsdXN0ZXJzIGJ5IGNvbG9yaW5nIG5vZGVzIGFjY29yZGluZyB0byB0aGVpciBtb2R1bGFyaXR5IGNsYXNzLiAKYGBge3J9CnBsb3QoY2x1c3RlciwgZ192YWx1ZWQsIGNvbCA9IFYoZ192YWx1ZWQpJGNvbG9yLCBsYXlvdXQgPSBMLCB2ZXJ0ZXguc2l6ZT02KQpgYGAKCioqV2hhdCBpbmZvcm1hdGlvbiBkb2VzIHRoaXMgbGF5b3V0IGNvbnZleT8gIEFyZSB0aGUgY2x1c3RlcnMgd2VsbC1zZXBhcmF0ZWQsIG9yIGlzIHRoZXJlIGEgZ3JlYXQgZGVhbCBvZiBvdmVybGFwPyBJcyBpdCBlYXNpZXIgdG8gaWRlbnRpZnkgdGhlIGNvbW1vbiB0aGVtZXMgYW1vbmcgY2x1c3RlcnMgaW4gdGhpcyBsYXlvdXQgcmF0aGVyIHRoYW4gbG9va2luZyBvbmx5IGF0IHRoZSBncmFwaHM/KioKVGhlIGNsdWFzdGVycyBhcmUgd2VsbC1zZXBlcmF0ZWQuIEl0IGlzIGVhc2llciB0byBpZGVudGlmeSB0aGUgY29tbW9uIHRoZW1lcyBhbW9uZyBjbHVzdGVycyBzaW5jZSB3ZSBjYW4gdGVsbCBkaXJlY3RseSBmcm9tIHRoZSBsYXlvdXQgdGhhdCB3aGF0IGFjdG9ycyBhcmUgaW4gdGhlIHNhbWUgY2x1c3Rlci4KCioqV2hhdCBkaWZmZXJlbmNlcyBhcmUgdGhlcmUgYmV0d2VlbiBub2RlcyBpbiB0aGUgc2FtZSBjbHVzdGVyIGFuZCBhY3Jvc3MgY2x1c3RlcnM/KioKTm9kZXMgaW4gdGhlIHNhbWUgY2x1c3RlciBhcmUgbW9yZSBjb25uZWN0ZWQgd2l0aCBlYWNoIG90aGVyIGFuZCBoYXZlIHNob3J0ZXIgZGlzdGFuY2UsIHdoZXJlYXMgbm9kZXMgYWNyb3NzIGNsdXN0ZXJzIGFyZSBsZXNzIGNvbm5lY3RlZCBhbmQgcmVhY2hpbmcgdGhlbSByZXF1aXJlcyBsb25nZXIgZGlzdGFuY2UuIAoKKipEZXNjcmliZSB0aGUgYnJva2VycyBiZXR3ZWVuIGFueSBjb21wb25lbnRzIGFuZCBjbGlxdWVzLiAgV2hhdCBhcmUgY29tbW9uIGZlYXR1cmVzIG9mIHRoZXNlIGJyb2tlcnM/ICBBYm91dCBob3cgbWFueSBicm9rZXJzIHdvdWxkIHlvdSBoYXZlIHRvIHJlbW92ZSBmcm9tIHlvdXIgbmV0d29yayB0byAic2hhdHRlciIgaXQgaW50byB0d28gb3IgbW9yZSBkaXNjb25uZWN0ZWQgY29tcG9uZW50cz8qKgpCcm9rZXJzIGFyZSB0aGUgcGVvcGxlIHdobyBoYXZlIGhpZ2ggYmV0d2Vlbm5lc3MgY2VudHJhbGl0eSBhbmQgY29udHJvbCB0aGUgZ3JvdXDigJlzIGluZm9ybWF0aW9uIGZsb3dzLiBCYXNlZCBvbiB0aGUgbGF5b3V0LCBEb25hbGQgVHJ1bXAgaXMgdGhlIGJyb2tlciB0byBDbHVzdGVyIDEsIHdpdGhvdXQgd2hvbSBldmVyeW9uZSBlbHNlIGluIENsdXN0ZXIgMSB3b24ndCBiZSBhYmxlIHRvIGdldCBpbmZvcm1hdGlvbiBmcm9tIG91dHNpZGUuIFNlbi4gQmlsbCBDYXNzaWR5IGlzIHRoZSBicm9rZXIgdG8gQ2x1c3RlciAyLCB3aXRob3V0IHdob20gU2VuLiBUaW0gU2NvdHQgd29uJ3QgZ2V0IGluZm9ybWF0aW9uLiBBcyBmb3IgQ2x1c3RlciAzLCBldmVyeW9uZSBpcyBkaXJlY3RseSBjb25uZWN0ZWQgdG8gRG9uYWxkIFRydW1wIGFuZCB0aGV5IGFyZSBpbnRlcmNvbm5lY3RlZCBhcyB3ZWxsLCBzbyBubyBvbmUgaXMgdGhlIGJyb2tlci4gQ29tbWVuIGZlYXR1cmUgb2YgdGhlc2UgYnJva2VycyBpcyB0aGF0IHBlb3BsZSBpbiB0aGUgY2x1c3RlciB3b24ndCBnZXQgaW5mb3JtYXRpb24gZnJvbSBvdXRzaWRlIGlmIHRoZXkgYXJlIHJlbW92ZWQuIElmIHdlIGFyZSB0byBicmVhayBuZXR3b3JrIGludG8gbW9yZSBkaXNjb25uZWN0ZWQgY29tcG9uZW50cywgd2UgY2FuIHJlbW92ZSBlaXRoZXIgRG9uYWxkIFRydW1wIG9yIFNlbi4gQmlsbCBDYXNzaWR5LgoKIyBQYXJ0IDQ6IENlbnRyYWxpdHkgVmlzdWFsaXphdGlvbiAmIFdlaWdodGVkIFZhbHVlcyAoMjAgUG9pbnRzKQoKRm9yIGVhY2ggbmV0d29yaywgeW91IHdpbGwgdXNlIGNlbnRyYWxpdHkgbWV0cmljcyB0byBpbXByb3ZlIHlvdXIgdmlzdWFsaXphdGlvbi4gWW91IG1heSBuZWVkIHRvIGFkanVzdCB0aGUgc2l6ZSBwYXJhbWV0ZXIgdG8gbWFrZSB5b3VyIG5ldHdvcmsgbW9yZSBlYXNpbHkgdmlzaWJsZS4KCiMjIERlZ3JlZSBDZW50cmFsaXR5CmBgYHtyfQp0b3RhbERlZ3JlZSA8LSBkZWdyZWUoZ192YWx1ZWQsbW9kZT0iYWxsIikKc29ydCh0b3RhbERlZ3JlZSxkZWNyZWFzaW5nPVRSVUUpWzE6NV0KZzIgPC0gZ192YWx1ZWQKVihnMikkc2l6ZSA8LSB0b3RhbERlZ3JlZSoyICNjYW4gYWRqdXN0IHRoZSBudW1iZXIgaWYgbm9kZXMgYXJlIHRvbyBiaWcKcGxvdChnMiwgbGF5b3V0ID0gTCwgdmVydGV4LmxhYmVsPU5BKQpgYGAKKipCcmllZmx5IGV4cGxhaW4gZGVncmVlIGNlbnRyYWxpdHkgYW5kIHdoeSBub2RlcyBhcmUgbW9yZSBvciBsZXNzIGNlbnRyYWwgaW4gdGhlIG5ldHdvcmsuKioKRGVncmVlIGNlbnRyYWxpdHkgbWVhc3VyZXMgdGhlICJwb3B1bGFyaXR5IiBvZiB0aGUgYWN0b3JzIGJ5IGNvdW50aW5nIHRvdGFsIG51bWJlciBvZiBsaW5rcyBvbmUgaGFzIHdpdGggb3RoZXIgYWN0b3JzLiBJbiB0aGlzIGNhc2UsIERvbmFsZCBUcnVtcCBoYXMgdGhlIGhpZ2hlc3QgZGVncmVlIGNlbnRyYWxpdHkgYW5kIHRoYXQncyBwcm9iYWJseSBiZWNhdXNlIGhlIGlzIHRoZSBQcmVzaWRlbnQgYW5kIGV2ZXJ5IHBlcnNvbiBvciBldmVyeSB0ZWFtIGlzIGluIHRoaXMgY291bnRyeS4gVGhlIGZvdXIgTkZMIHRlYW1zIGFsbCBoYXZlIHJlbGF0aXZlIGhpZ2ggZGVncmVlIGNlbnRyYWxpdHkgYW5kIHRoZSBudW1iZXIgb2YgbGlua3MgdGhleSBoYXZlIGlzIGV4YWN0bHkgdGhlIHNhbWUuIFRoaXMgaXMgcHJvYmFibHkgYmVjYXVzZSB0aGV5IHdpbGwgcGxheSBnYW1lcyBhZ2FpbnN0IG9uZSBhbm90aGVyLCBhbmQgdGhlIG51bWJlciBvZiBnYW1lcyBiZXR3ZWVuIHRoZXNlIGdhbWVzIHNob3VsZCBiZSB0aGUgc2FtZS4gCgojIyBXZWlnaHRlZCBEZWdyZWUgQ2VudHJhbGl0eQpgYGB7cn0Kd2QgPC0gZ3JhcGguc3RyZW5ndGgoZ192YWx1ZWQsd2VpZ2h0cyA9IEUoZ192YWx1ZWQpJENvT2NjdXJyZW5jZXMpCnNvcnQod2QsZGVjcmVhc2luZz1UUlVFKVsxOjVdCndnMiA8LSBnX3ZhbHVlZApWKHdnMikkc2l6ZSA8LSB3ZCouMSAjIGFkanVzdCB0aGUgbnVtYmVyIGlmIG5vZGVzIGFyZSB0b28gYmlnCnBsb3Qod2cyLCBsYXlvdXQgPSBMLCB2ZXJ0ZXgubGFiZWw9TkEsIGVkZ2Uud2lkdGg9c3FydChFKGdfdmFsdWVkKSRDb09jY3VycmVuY2VzKSkgI3Rha2luZyB0aGUgc3F1YXJlIHJvb3QgaXMgYSBnb29kIHdheSB0byBtYWtlIGEgbGFyZ2UgcmFuZ2Ugb2YgbnVtYmVycyB2aXNpYmxlIGluIGFuIGVkZ2UuIE90aGVyd2lzZSBlZGdlcyB0ZW5kIHRvIGNvdmVyIHVwIGFsbCB0aGUgb3RoZXIgZWRnZXMgYW5kIG9ic2N1cmUgdGhlIHJlbGF0aW9uc2hpcHMuCmBgYAoqKldoYXQgZG9lcyB0aGUgYWRkaXRpb24gb2Ygd2VpZ2h0ZWQgZGVncmVlIGFuZCBlZGdlIGluZm9ybWF0aW9uIHRlbGwgeW91IGFib3V0IHlvdXIgZ3JhcGg/KioKVGhlIHdlaWdodGVkIHJlc3VsdHMgYXJlIG11Y2ggZGlmZmVyZW50IHRoYW4gdGhlIG9yaWdpbmFsIG9uZS4gSXQgdGFrZXMgaW50byBhY2NvdW50IG9mIHRoZSBmcmVxdWVuY3kgdGhhdCB0aGVzZSB3b3JkcyBjby1vY2N1cmVkIG9uIE5ZVCBpbnN0ZWFkIG9mIHRoZSByZWxhdGlvbnMgYmVpbmcganVzdCBwcmVzZW50IG9yIGFic2VudC4gTkZMIHJlbGF0ZWQgd29yZHMgYXJlIHRoZSBvbmVzIHRoYXQgaGF2ZSB0aGUgaGlnaGVzdCB3ZWlnaHRlZCBkZWdyZWUgY2VudHJhbGl0eSwgYW5kIHRoaXMgaXMgcHJvYmFibHkgYmVjYXVzZSB0aGUgdGVhbXMgcGxheSBhZ2FpbnN0IG9uZSBhbm90aGVyIHF1aXRlIG9mdGVuIGFuZCB0aGV5IHRlbmQgdG8gY28tb2NjdXIgbW9yZS4gV2hlcmVhcyB0aGUgbm9uLXdlaWdodGVkIGNlbnRyYWxpdHkgb25seSB0ZWxscyB1cyB3aGV0aGVyIHRoZXJlIGlzIGxpbmsgYmV0d2VlbiB0aGUgdHdvIG5vZGVzLiAKCiMjIEJldHdlZW5uZXNzIENlbnRyYWxpdHkKYGBge3J9CmIgPC0gYmV0d2Vlbm5lc3MoZ192YWx1ZWQsZGlyZWN0ZWQ9VFJVRSkKc29ydChiLGRlY3JlYXNpbmc9VFJVRSlbMTo1XQpnNCA8LSBnX3ZhbHVlZApWKGc0KSRzaXplIDwtIGIqMS4yI2NhbiBhZGp1c3QgdGhlIG51bWJlcgpwbG90KGc0LCBsYXlvdXQgPSBMLCB2ZXJ0ZXgubGFiZWw9TkEpCmBgYAoqKkJyaWVmbHkgZXhwbGFpbiBiZXR3ZWVubmVzcyBjZW50cmFsaXR5IGFuZCB3aHkgbm9kZXMgYXJlIG1vcmUgb3IgbGVzcyBjZW50cmFsIGluIHRoZSBuZXR3b3JrLioqCkJldHdlZW5lc3MgY2VudHJhbGl0eSBhc3Nlc3NlcyBob3cgbXVjaCBhbiBhY3RvciBsaWVzIGJldHdlZW4gZGlzdGluY3QgZ3JvdXBzIGJ5IHRoZSBudW1iZXIgb2YgZ2VvZGVzaWNzIHBhc3NpbmcgdGhyb3VnaCBhY3Rvci4gSW4gdGhpcyBjYXNlLCBEb25hbGQgVHJ1bXAgaGFzIHRoZSBoaWdoZXN0IGJldHdlZW5lc3MgY2VudHJhbGl0eSwgYXMgd2UgY2FuIHNlZSB0aGF0IGhlIGxpZXMgYmV0d2VlbiBwb2xpdGljaWFucyBhbmQgc3BvcnRzIHJlbGF0ZWQgd29yZHMgYW5kIHNlcnZlcyBhcyBhIGJyb2tlci4gU2ltaWxhcmx5LCBTZW4uIEJpbGwgQ2Fzc2lkeSBhbHNvIGhhcyBoaWdoIGJld3R3ZWVuZXNzIGNlbnRyYWxpdHkgYmVjYXVzZSBTZW4uIFRpbSBTY290dCBpcyBvbmx5IGFibGUgdG8gY29ubmVjdCB3aXRoIG90aGVycyB0aHJvdWdoIGhpbS4gTm9kZXMgd2l0aCBsZXNzIGJldHdlZW5lc3MgY2VudHJhbGl0eSBtZWFucyB0aGF0IHRoZXkgYXJlIGxlc3MgbGlrZWx5IHRvIGFmZmVjdCBpbmZvcm1hdGlvbiBmbG93cyBpZiB0aGV5IGFyZSByZW1vdmVkLgoKIyMjIFdlaWdodGVkIEJldHdlZW5uZXNzIENlbnRyYWxpdHkKYGBge3J9CndidHduIDwtIGJldHdlZW5uZXNzKGdfdmFsdWVkLHdlaWdodHMgPSBFKGdfdmFsdWVkKSRDb09jY3VycmVuY2VzKQpzb3J0KHdidHduLGRlY3JlYXNpbmc9VFJVRSlbMTo1XQp3QnR3bkcgPC0gZ192YWx1ZWQKVih3QnR3bkcpJHNpemUgPC0gd2J0d24qLjUgIyBhZGp1c3QgdGhlIG51bWJlciBpZiBub2RlcyBhcmUgdG9vIGJpZwpwbG90KHdCdHduRywgbGF5b3V0ID0gTCwgdmVydGV4LmxhYmVsPU5BLCBlZGdlLndpZHRoPXNxcnQoRShnX3ZhbHVlZCkkQ29PY2N1cnJlbmNlcykpICN0YWtpbmcgdGhlIHNxdWFyZSByb290IGlzIGEgZ29vZCB3YXkgdG8gbWFrZSBhIGxhcmdlIHJhbmdlIG9mIG51bWJlcnMgdmlzaWJsZSBpbiBhbiBlZGdlLgpgYGAKKipXaGF0IGRvZXMgdGhlIGFkZGl0aW9uIG9mIHdlaWdodGVkIGRlZ3JlZSBhbmQgZWRnZSBpbmZvcm1hdGlvbiB0ZWxsIHlvdSBhYm91dCB5b3VyIGdyYXBoPyoqCkFsdGhvdWdoIERvbmFsZCBUcnVtcCBpcyBzdGlsbCB0aGUgaGlnaGVzdCBpbiB3ZWlnaHRlZCBiZXR3ZWVuZXNzIGRlZ3JlZSwgbm9kZXMgYXBwZWFyIHRvIGJlIGRpZmZlcmVudCB3aGVuIHRoZSBjYWxjdWxhdGlvbiBpcyB3ZWlnaHRlZC4gRm9yIGV4YW1wbGUsIFNlbi4gQmlsbCBDYXNzaWR5IGlzIG5vIGxvbmdlciB0aGUgc2Vjb25kIGhpZ2hlc3QgaW4gYmV0d2VlbmVzcyBkZWdyZWUuIFRoZSB3ZWlnaHRlZCByZXN1bHRzIHdvdWxkIHByb3ZpZGUgbW9yZSBpbmZvcm1hdGlvbiBpbiB0ZXJtcyBvZiBob3cgdGhlc2UgYWN0b3JzIGFyZSByZWxhdGVkIGluIHRoZSByZWFsIHdvcmxkIGJlY2F1c2UgdGhlIHJlbGF0aW9ucyBhcmUgbm8gbG9uZ2VyIGp1c3QgYmluYXJ5IGJ1dCB0YWtlIGludG8gYWNjb3VudCBob3cgZnJlcXVlbnQgdGhlIGNvbm5lY3Rpb25zIGFwcGVhci4KCiMjIENsb3NlbmVzcyBDZW50cmFsaXR5CmBgYHtyfQpjIDwtIGNsb3NlbmVzcyhnX3ZhbHVlZCkKc29ydChjLGRlY3JlYXNpbmc9VFJVRSlbMTo1XQpnNSA8LSBnX3ZhbHVlZApWKGc1KSRzaXplIDwtIGMqNTAwICAjY2FuIGFkanVzdCB0aGUgbnVtYmVyCnBsb3QoZzUsIGxheW91dCA9IEwsIHZlcnRleC5sYWJlbD1OQSkKYGBgCioqQnJpZWZseSBleHBsYWluIGNsb3NlbmVzcyBjZW50cmFsaXR5IGFuZCB3aHkgbm9kZXMgYXJlIG1vcmUgb3IgbGVzcyBjZW50cmFsIGluIHRoZSBuZXR3b3JrLioqCkNsb3NlbmVzcyBjZW50cmFsaXR5IG1lYXN1cmVzIGhvdyBlYXNpbHkgb25lIGFjdG9yIGNhbiByZWFjaCByZXN0IG9mIG5ldHdvcmsuIEFjdG9yIHdpdGggc2hvcnRlc3QgYXZlcmFnZSBwYXRoIGxlbmd0aCBpbiB0aGUgbmV0d29yayBoYXMgdGhlIGhpZ2hlc3QgY2xvc2VuZXNzIGNlbnRyYWxpdHkgYW5kIHNlcnZlcyBhcyBwdWxzZS10YWtlci4gVGhpcyBtZWFucyB0aGF0IHRoZSBpbmZvcm1hdGlvbiB3aWxsIGJlIHRyYW5zbWl0dGVkIG11Y2ggc2xvd2VyIGlmIHdlIHJlbW92ZSBub2RlcyB3aXRoIGhpZ2ggY2xvc2VuZXNzIGNlbnRyYWxpdHkuIEluIHRoaXMgY2FzZSwgRG9uYWxkIFRydW1wIGhhcyB0aGUgaGlnaGVzdCBjbG9zZW5lc3MgY2VudHJhbGl0eSwgbWVhbmluZyB0aGF0IGhlIGhhcyBzaG9ydGVzdCBhdmVyYWdlIHBhdGggbGVuZ3RoIGluIHRoZSBuZXR3b3JrLiBXaXRob3V0IGhpbSwgdGhlIGluZm9ybWF0aW9uIGZsb3dzIHdpbGwgYmUgInB1bHNlZCIuIE90aGVyIHRoYW4gRG9uYWxkIFRydW1wLCBhbGwgdGhlIG5vdGVzIGFwcGVhciB0byBiZSBraW5kIG9mIGhpZ2ggaW4gY2xvc2VuZXNzIGNlbnRyYWxpdHktLS10aGV5IGFwcGVhciB0byBiZSBzaW1pbGFyIGluIHNpemUgb24gdGhlIGxheW91dC4gTm9kZXMgd2l0aCBsZXNzIGNsb3NlbmVzcyBjZW50cmFsaXR5IG1lYW5zIHRoYXQgdGhleSB3aWxsIGhhdmUgdGhlIGxlYXN0IGluZmx1ZW5jZSBvbiBpbmZvcm1hdGlvbiBmbG93cyB3aGVuIGJlaW5nIHJlbW92ZWQuCgojIyMgV2VpZ2h0ZWQgQ2xvc2VuZXNzIENlbnRyYWxpdHkKCmBgYHtyfQp3Q2xzbnNzIDwtIGNsb3NlbmVzcyhnX3ZhbHVlZCx3ZWlnaHRzID0gRShnX3ZhbHVlZCkkQ29PY2N1cnJlbmNlcykKc29ydCh3Q2xzbnNzLGRlY3JlYXNpbmc9VFJVRSlbMTo1XQp3Q2xzbnNzRyA8LSBnX3ZhbHVlZApWKHdDbHNuc3NHKSRzaXplIDwtIHdDbHNuc3MqMTAwMCAjIGFkanVzdCB0aGUgbnVtYmVyIGlmIG5vZGVzIGFyZSB0b28gYmlnCnBsb3Qod0Nsc25zc0csIGxheW91dCA9IEwsIHZlcnRleC5sYWJlbD1OQSwgZWRnZS53aWR0aD1zcXJ0KEUoZ192YWx1ZWQpJENvT2NjdXJyZW5jZXMpKSAjdGFraW5nIHRoZSBzcXVhcmUgcm9vdCBpcyBhIGdvb2Qgd2F5IHRvIG1ha2UgYSBsYXJnZSByYW5nZSBvZiBudW1iZXJzIHZpc2libGUgaW4gYW4gZWRnZS4KYGBgCioqV2hhdCBkb2VzIHRoZSBhZGRpdGlvbiBvZiB3ZWlnaHRlZCBkZWdyZWUgYW5kIGVkZ2UgaW5mb3JtYXRpb24gdGVsbCB5b3UgYWJvdXQgeW91ciBncmFwaD8qKgpBbHRob3VnaCBEb25hbGQgVHJ1bXAgcmVtYWlucyB0byBiZSB0aGUgaGlnaGVzdCBpbiB3ZWlnaHRlZCBjbG9zZW5lc3MgY2VudHJhbGl0eSwgb3RoZXIgYWN0b3JzIHRoYXQgYXJlIGhpZ2ggaW4gdGhlIHdlaWdodGVkIG1lYXN1cmUgYXJlIGFsbCBwb2xpdGljaWFucyBpbnN0ZWFkIG9mIE5GTCB0ZWFtcy4gVGhpcyBzdWdnZXN0cyB0aGF0IGlmIHdlIGNvbnNpZGVyIHRoZSBmcmVxdWVuY3kgb2YgY28tb2NjdXJhbmNlIG9mIHRoZSB3b3JkcywgdGhlc2UgcG9saXRpY2lhbnMgcGxheSBhIG1vcmUgaW1wb3J0YW50IHJvbGUgaW4gZWZmZWN0aXZlbHkgdHJhbnNtaXR0aW5nIGluZm9ybWF0aW9uIHRvIG90aGVycyBpbiB0aGUgbmV0d29yay4KCiMjIEVpZ2VudmVjdG9yIENlbnRyYWxpdHkKYGBge3J9CmVpZ2MgPC0gZWlnZW5fY2VudHJhbGl0eShnX3ZhbHVlZCxkaXJlY3RlZD1UUlVFKQpzb3J0KGVpZ2MkdmVjdG9yLGRlY3JlYXNpbmc9VFJVRSlbMTo1XQpnNiA8LSBnX3ZhbHVlZApWKGc2KSRzaXplIDwtIGVpZ2MkdmVjdG9yKjUwICNjYW4gYWRqdXN0IHRoZSBudW1iZXIKcGxvdChnNiwgbGF5b3V0ID0gTCwgdmVydGV4LmxhYmVsPU5BKQpgYGAKCioqQnJpZWZseSBleHBsYWluIGVpZ2VudmVjdG9yIGNlbnRyYWxpdHkgYW5kIHdoeSBub2RlcyBhcmUgbW9yZSBvciBsZXNzIGNlbnRyYWwgaW4gdGhlIG5ldHdvcmsuKioKRWlnZW52ZWN0b3IgY2VudHJhbGl0eSBjYW4gYmUgbWVhc3VyZWQgYnkgcmVjb21wdXRpbmcgZWFjaCBub2Rl4oCZcyBzY29yZSBhcyB3ZWlnaHRlZCBzdW0gb2YgbmVpZ2hib3Jz4oCZIGNlbnRyYWxpdGllcy4gSGlnaGVzdCBiZXR3ZWVuIGFuZC9vciBkZWdyZWUgY2VudHJhbCBhY3RvciBpcyBvZnRlbiBoaWdoZXN0IGVpZ2VudmFsdWUgY2VudHJhbCBhY3RvciwgYW5kIHRoaXMgaXMgZXhhY3RseSByaWdodCBpbiB0aGlzIGNhc2UuIERvbmFsZCBUcnVtcCBpcyB0aGUgb25lIHdpdGggaGlnaGVzdCBlaWdlbnZlY3RvciBjZW50cmFsaXR5LCBtZWFuaW5nIHRoYXQgdGhlIG5vZGVzIERvbmFsZCBUcnVtcCBjb25uZWN0cyB0byBoYXMgbG90cyBvZiBsaW5rcy4gSG93ZXZlciwgc2V2ZXJhbCBub2RlcyBmcm9tIHRoZSBORkwgY2x1c3RlciBhbHNvIGhhdmUgaGlnaCBlaWdlbnZlY3RvciBjZW50cmFsaXR5LCBhbmQgdGhpcyBpcyBwcm9iYWJseSBiZWNhdXNlIGFjdG9ycyBhcmUgbXVjaCBtb3JlIGludGVyY29ubmVjdGVkIGluIHRoZSBORkwgY2x1c3RlciBkdWUgdG8gY29tcGV0aXRpb24gYmV0d2VlbiB0ZWFtcy4KCiMjIEFuYWx5c2lzCioqQ2hvb3NlIHRoZSB2aXN1YWxpemF0aW9uIHRoYXQgeW91IHRoaW5rIGlzIG1vc3QgaW50ZXJlc3RpbmcgYW5kIGJyaWVmbHkgZXhwbGFpbiB3aGF0IGl0IHRlbGxzIHlvdSBhYm91dCBhIGNlbnRyYWwgbm9kZSBpbiB5b3VyIG5ldHdvcmsuIERpc2N1c3MgdGhlIHR5cGUgb2YgY2VudHJhbGl0eSwgYW5kIHdoYXQgdGhhdCBub2Rl4oCZcyBjZW50cmFsaXR5IHNjb3JlIHRlbGxzIHlvdSBhYm91dCB0aGUgc2VhcmNoIGNvLW9jY3VycmVuY2UgbmV0d29yay4qKgpJIHRoaW5rIHRoZSBtb3N0IGludGVyZXN0aW5nIG9uZSBpcyB0aGUgY2xvc2VuZXNzIGNlbnRyYWxpdHkuIENsb3NlbmVzcyBjZW50cmFsaXR5IG1lYXN1cmVzIGhvdyBlYXNpbHkgb25lIGFjdG9yIGNhbiByZWFjaCByZXN0IG9mIG5ldHdvcmsuIEFjdG9yIHdpdGggc2hvcnRlc3QgYXZlcmFnZSBwYXRoIGxlbmd0aCBpbiB0aGUgbmV0d29yayBoYXMgdGhlIGhpZ2hlc3QgY2xvc2VuZXNzIGNlbnRyYWxpdHkgYW5kIHNlcnZlcyBhcyBwdWxzZS10YWtlci4gQmFzZWQgb24gdGhlIGxheW91dCwgd2UgY2FuIHNlZSB0aGF0IGFjdHVhbGx5IGEgbG90IG9mIGFjdG9ycyBhcHBlYXIgdG8gYmUgcmVsYXRpdmVseSBoaWdoIGluIHRlcm1zIG9mIGNsb3NlbmVzcyBjZW50cmFsaXR5IGFuZCB3ZSBjYW4ndCByZWFsbHkgdGVsbCB3aG8gaGFzIGhpZ2hlciBjbG9zZW5lc3MgY2VudHJhbGl0eSBvdGhlciB0aGFuIERvbmFsZCBUcnVtcC4gVGhpcyBpcyBub3QgdGhlIGNhc2UgZm9yIG90aGVyIGxheW91dHMsIGFzIHNvbWUgYWN0b3JzIGFyZSBvYnZpb3VzbHkgbW9yZSBjZW50cmFsIGluIHRob3NlLiBUaGlzIHJlc3VsdCB0ZWxscyB1cyB0aGF0IG1hbnkgYWN0b3JzIGFyZSBpbXBvcnRhbnQgaW4gZWZmZWN0aXZlbHkgcGFzc2luZyBvbiBpbmZvcm1hdGlvbiBpbiB0aGlzIG5ldHdvcmsuCgoqKkJyaWVmbHkgZGlzY3VzcyBhbiBpbnRlcmVzdGluZyBkaWZmZXJlbmNlIGJldHdlZW4gdHlwZXMgb2YgY2VudHJhbGl0eSBmb3IgeW91ciBuZXR3b3JrLioqCk9uZSBpbnRlcmVzdGluZyBkaWZmZXJlbmNlIGlzIHRoZSBkZWdyZWUgY2VudHJhbGl0eSB2ZXN1cyBiZXR3ZWVuZXNzIGNlbnRyYWxpdHkuIEFsdGhvdWdoIERvbmFsZCBUcnVtcCBhbHdheXMgdHVybnMgb3V0IHRvIGJlIHRoZSBvbmUgd2l0aCBoaWdoZXN0IGNlbnRyYWxpdHkgaW4gYWxsIHRoZXNlIG1lYXN1cmVzLCBORkwgdGVhbXMgYXJlIGFtb25nIHRoZSBoaWdoZXN0IG9uZXMgZm9yIGRlZ3JlZSBjZW50cmFsaXR5LCB3aGVyZWFzIHNlbmF0b3JzIGFyZSB0aGUgaGlnaGVzdCBvbmVzIGZvciBiZXR3ZWVuZXNzIGNlbnRyYWxpdHkuIFRoaXMgcHJvYmFibHkgc3VnZ2VzdHMgdGhhdCBhbHRob3VnaCBORkwgdGVhbXMgaGF2ZSBtb3JlIGxpbmtzIGFuZCBhcmUgbW9yZSBwb3B1bGFyIHRvIGFwcGVhciBvbiBOWVQsIHBvbGl0aWNpYW5zIGFyZSBtb3JlIGltcG9ydGFudCBpbiB0ZXJtcyBvZiB3aGV0aGVyIGluZm9ybWF0aW9uIGNhbiBiZSBwYXNzZWQgb24uIAoKIyMgR2xvYmFsIE5ldHdvcmsgTWV0cmljcyB3aXRoIFIKCkNvbXB1dGUgdGhlIG5ldHdvcmsgY2VudHJhbGl6YXRpb24gc2NvcmVzIGZvciB5b3VyIG5ldHdvcmsgZm9yIGRlZ3JlZSwgYmV0d2Vlbm5lc3MsIGNsb3NlbmVzcywgYW5kIGVpZ2VudmVjdG9yIGNlbnRyYWxpdHkuCgpgYGB7cn0KIyBEZWdyZWUgY2VudHJhbGl6YXRpb24KY2VudHJhbGl6YXRpb24uZGVncmVlKGdfdmFsdWVkLG5vcm1hbGl6ZWQgPSBUUlVFKQoKIyBCZXR3ZWVubmVzcyBjZW50cmFsaXphdGlvbgpjZW50cmFsaXphdGlvbi5iZXR3ZWVubmVzcyhnX3ZhbHVlZCxub3JtYWxpemVkID0gVFJVRSkKCiMgQ2xvc2VuZXNzIGNlbnRyYWxpemF0aW9uIApjZW50cmFsaXphdGlvbi5jbG9zZW5lc3MoZ192YWx1ZWQsbm9ybWFsaXplZCA9IFRSVUUpCgojIEVpZ2VudmVjdG9yIGNlbnRyYWxpemF0aW9uIApjZW50cmFsaXphdGlvbi5ldmNlbnQoZ192YWx1ZWQsbm9ybWFsaXplZCA9IFRSVUUpCgpgYGAKKipSZWNvcmQgdGhlIGNlbnRyYWxpemF0aW9uIHNjb3JlIG9mIGVhY2ggY2VudHJhbGl0eSBtZWFzdXJlLioqCkRlZ3JlZSBjZW50cmFsaXphdGlvbjogMC41OTUyMzgxCkJldHdlZW5lc3MgY2VudHJhbGl6YXRpb246IDAuNzA1NjUxNQpDbG9zZW5lc3MgY2VudHJhbGl6YXRpb246IDAuNzc3OTk3MQpFaWdlbnZlY3RvciBjZW50cmFsaXphdGlvbjogMC41OTA0MzQ5CgoqKkJyaWVmbHkgZXhwbGFpbiB3aGF0IHRoZSBjZW50cmFsaXphdGlvbiBvZiBhIG5ldHdvcmsgaXMuKioKTmV0d29yayBjZW50cmFsaXphdGlvbiByZWZsZWN0cyBob3cgZXF1YWwgZXZlcnkgYWN0b3IgaW4gdGhlIG5ldHdvcmsgaXMuIFNwZWNpZmljYWxseSwgYSBtb3JlIGNlbnRyYWxpemVkIG5ldHdvcmsgd291bGQgYmUgYSBuZXR3b3JrIHdpdGggc29tZSBhY3RvcnMgd2hvIGhhdmUgbW9yZSBsaW5rcyBhbmQgc29tZSBhY3RvcnMgd2hvIGhhdmUgZmV3ZXIgbGlua3MuIFRvIGdpdmUgYW4gZXhhbXBsZSwgb25lIG9mIHRoZSBtb3N0IGNlbnRyYWxpemVkIG5ldHdvcmsgaXMgdGhlIHN0YXIgbmV0d29yaywgd2hlcmUgb25lIGFjdG9yIGhhcyBsaW5rcyB0byBldmVyeW9uZSBlbHNlIGluIHRoZSBuZXR3b3JrIHdoaWxlIHRoZSBvdGhlcnMgb25seSBoYXZlIG9uZSBsaW5rLgoKKipDb21wYXJlIHRoZSBjZW50cmFsaXphdGlvbiBzY29yZXMgYWJvdmUgd2l0aCB0aGUgZ3JhcGhzIHlvdSBjcmVhdGVkIHdoZXJlIHRoZSBub2RlcyBhcmUgc2NhbGVkIGJ5IGNlbnRyYWxpdHkuIERlc2NyaWJlIHRoZSBhcHBlYXJhbmNlIG9mIG1vcmUgY2VudHJhbGl6ZWQgdi4gbGVzcyBjZW50cmFsaXplZCBuZXR3b3Jrcy4qKgpDZW50cmFsaXphdGlvbiBzY29yZXMgY2FuIHJhbmdlIGZyb20gMCB0byAxLCB3aXRoIDAgbWVhbnMgbGVhc3QgY2VudHJhbGl6ZWQgYW5kIDEgbWVhbnMgbW9zdCBjZW50cmFsaXplZC4gSW4gdGhpcyBjYXNlLCB0aGUgbmV0d29yayBpcyBtb3N0IGNlbnRyYWxpemVkIGluIHRlcm1zIG9mIGl0cyBjbG9zZW5lc3MsIHdoaWxlIGxlYXN0IGNlbnRyYWxpemVkIGluIHRlcm1zIG9mIGl0cyBlaWdlbnZlY3Rvci4gQnV0IG92ZXJhbGwgdGhlIG5ldHdvcmsgaXMgY2VudHJhbGl6ZWQuIAoKIyMgUGFydCA1LiBQb3dlciBMYXdzICYgU21hbGwgV29ybGRzICgyMCkKCiMjIFBvd2VyIExhd3MKTmV0d29ya3Mgb2Z0ZW4gZGVtb25zdHJhdGUgcG93ZXIgbGF3IGRpc3RyaWJ1dGlvbnMuIFBsb3QgdGhlIGRlZ3JlZSBkaXN0cmlidXRpb24gb2YgdGhlIG5vZGVzIGluIHlvdXIgYmFzZSBncmFwaC4gCmBgYHtyfQojIENhbGN1bGF0ZSBkZWdyZWUgZGlzdHJpYnV0aW9uCmRlZyA8LSBkZWdyZWUoZ192YWx1ZWQsdj1WKGdfdmFsdWVkKSwgbW9kZT0iYWxsIikKZGVnCgojIERlZ3JlZSBkaXN0cmlidXRpb24gaXMgdGhlIGN1bXVsYXRpdmUgZnJlcXVlbmN5IG9mIG5vZGVzIHdpdGggYSBnaXZlbiBkZWdyZWUKZGVnX2Rpc3RyIDwtZGVncmVlLmRpc3RyaWJ1dGlvbihnX3ZhbHVlZCwgY3VtdWxhdGl2ZT1ULCBtb2RlPSJhbGwiKQpkZWdfZGlzdHIKcGxvdChkZWdfZGlzdHIsIHlsaW09YyguMDEsMTApLCBiZz0iYmxhY2siLHBjaD0yMSwgeGxhYj0iRGVncmVlIiwgeWxhYj0iQ3VtdWxhdGl2ZSBGcmVxdWVuY3kiKSAjWW91IG1heSBuZWVkIHRvIGFkanVzdCB0aGUgeWxpbSB0byBhIGxhcmdlciBvciBzbWFsbGVyIG51bWJlciB0byBtYWtlIHRoZSBncmFwaCBzaG93IG1vcmUgZGF0YS4KYGBgCgpUZXN0IHdoZXRoZXIgaXTigJlzIGFwcHJveGltYXRlbHkgYSBwb3dlciBsYXcsIGVzdGltYXRlIGxvZyBmIChrKSA9IGxvZyBhIOKIkiBjIGxvZyBrLiDigJxUaGlzIHNheXMgdGhhdCBpZiB3ZSBoYXZlIGEgcG93ZXItbGF3IHJlbGF0aW9uc2hpcCwgYW5kIHdlIHBsb3QgbG9nIGYgKGspIGFzIGEgZnVuY3Rpb24gb2YgbG9nIGssIHRoZW4gd2Ugc2hvdWxkIHNlZSBhIHN0cmFpZ2h0IGxpbmU6IOKIkmMgd2lsbCBiZSB0aGUgc2xvcGUsIGFuZCBsb2cgYSB3aWxsIGJlIHRoZSB5LWludGVyY2VwdC4gU3VjaCBhIOKAnGxvZy1sb2figJ0gcGxvdCB0aHVzIHByb3ZpZGVzIGEgcXVpY2sgd2F5IHRvIHNlZSBpZiBvbmXigJlzIGRhdGEgZXhoaWJpdHMgYW4gYXBwcm94aW1hdGUgcG93ZXItbGF3OiBpdCBpcyBlYXN5IHRvIHNlZSBpZiBvbmUgaGFzIGFuIGFwcHJveGltYXRlbHkgc3RyYWlnaHQgbGluZSwgYW5kIG9uZSBjYW4gcmVhZCBvZmYgdGhlIGV4cG9uZW50IGZyb20gdGhlIHNsb3BlLuKAnSAoRSZLLCBDaGFwdGVyIDE4LCBwLjU0NikuCgpgYGB7cn0KcG93ZXIgPC0gcG93ZXIubGF3LmZpdChkZWdfZGlzdHIpCnBvd2VyCnBsb3QoZGVnX2Rpc3RyLCBsb2c9Inh5IiwgeWxpbT1jKC4wMSwxMCksIGJnPSJibGFjayIscGNoPTIxLCB4bGFiPSJEZWdyZWUiLCB5bGFiPSJDdW11bGF0aXZlIEZyZXF1ZW5jeSIpCmBgYAoKKipEb2VzIHlvdXIgbmV0d29yayBleGhpYml0IGEgcG93ZXIgbGF3IGRpc3RyaWJ1dGlvbiBvZiBkZWdyZWUgY2VudHJhbGl0eT8qKgpUaGUgbmV0d29yayBkb2VzIG5vdCByZWFsbHkgZXhoaWJpdCBhIHBvd2VyIGxhdyBkaXN0cmlidXRpb24gb2YgZGVncmVlIGNlbnRyYWxpdHkgYmVjYXVzZSB0aGUgcGxvdCBkb2VzIG5vdCBsb29rIGxpa2UgYSBzdHJhaWdodCBsaW5lIHdoZXJlIHdlIGNhbiBlYXNpbHkgdGVsbCB0aGUgc2xvcGUuCgojIyBTbWFsbCBXb3JsZHMKCk5ldHdvcmtzIG9mdGVuIGRlbW9uc3RyYXRlIHNtYWxsIHdvcmxkIGNoYXJhY3RlcmlzdGljcy4gQ29tcHV0ZSB0aGUgYXZlcmFnZSBjbHVzdGVyaW5nIGNvZWZmaWNpZW50IChBQ0MpIGFuZCB0aGUgY2hhcmFjdGVyaXN0aWMgcGF0aCBsZW5ndGggKENQTCkuCkFDQyA9IDEuNzcxNDI5CkNQTCA9IDAuODI2OTkxNQpgYGB7cn0KIyBBdmVyYWdlIGNsdXN0ZXJpbmcgY29lZmZpY2llbnQgKEFDQykKdHJhbnNpdGl2aXR5KGdfdmFsdWVkLCB0eXBlID0gYygiYXZlcmFnZSIpKQoKIyBDaGFyYWN0ZXJpc3RpYyBwYXRoIGxlbmd0aCAoQ1BMKQphdmVyYWdlLnBhdGgubGVuZ3RoKGdfdmFsdWVkKQpgYGAKCkNvbXB1dGUgdGhlIEFDQyBhbmQgQ1BMIGZvciAxMDAgcmFuZG9tIG5ldHdvcmtzIHdpdGggdGhlIHNhbWUgbnVtYmVyIG9mIG5vZGVzIGFuZCB0aWVzIGFzIHlvdXIgdGVzdCBuZXR3b3JrLiAKQUNDID0gMC44ODkzMzcyCkNQTCA9IDEuMTEwMjk0CmBgYHtyfQphY2NTdW0gPC0gMApjcGxTdW0gPC0gMApmb3IgKGkgaW4gMToxMDApewogIGdycGggPC0gZXJkb3MucmVueWkuZ2FtZShudW1WZXJ0aWNlcywgbnVtRWRnZXMsIHR5cGUgPSAiZ25tIikKICBhY2NTdW0gPC0gYWNjU3VtICsgdHJhbnNpdGl2aXR5KGdycGgsIHR5cGUgPSBjKCJhdmVyYWdlIikpCiAgY3BsU3VtIDwtIGNwbFN1bSArIGF2ZXJhZ2UucGF0aC5sZW5ndGgoZ3JwaCkKfQphY2NTdW0vMTAwCmNwbFN1bS8xMDAKYGBgCgoqKkJhc2VkIG9uIHRoZXNlIGRhdGEsIHdvdWxkIHlvdSBjb25jbHVkZSB0aGF0IHRoZSBvYnNlcnZlZCBuZXR3b3JrIGRlbW9uc3RyYXRlcyBzbWFsbCB3b3JsZCBwcm9wZXJ0aWVzPyBXaHkgb3Igd2h5IG5vdD8qKgpJIHdvdWxkIHNheSB0aGUgb2JzZXJ2ZWQgbmV0d29yayBkb2VzIG5vdCBkZW1vbnN0cmF0ZSBzbWFsbCB3b3JsZCBwcm9wZXJ0aWVzLiBJbiBvcmRlciB0byBiZSBhIHNtYWxsIHdvcmxkIG5ldHdvcmssIHRoZSBuZXR3b3JrIHNob3VsZCBoYXZlIGhpZ2ggbG9jYWwgY2x1c3RlcmluZyBjb2VmZmljaWVudCBhbmQgbG93IGF2ZXJhZ2UgcGF0aCBsZW5ndGggdG8gb3RoZXIgYWN0b3JzLiBJbiB0aGUgb2JzZXJ2ZWQgbmV0d29yaywgQUNDID0gMC44Mjc5OTE1IGFuZCBDUEwgPSAxLjc3MTQyOS4gTm93IGNvbXBhcmluZyB0aGUgZGF0YSB0byB0aGUgcmFuZG9tIGdlbmVyYXRlZCBuZXR3b3JrLCB3ZSBjYW4gZmluZCBvdXQgdGhhdCBBQ0Mgb2YgdGhlIG9ic2VydmVkIG5ldHdvcmsgaXMgbG93ZXIgdGhhbiB0aGUgcmFuZG9tIG5ldHdvcmsgcmVzdWx0cyBhbmQgQ1BMIG9mIHRoZSBvYnNlcnZlZCBuZXR3b3JrIGlzIGhpZ2hlciB0aGFuIHRoZSByYW5kb20gbmV0d29yay4gVGhlcmVmb3JlLCB0aGUgb2JzZXJ2ZWQgbmV0d29yayBkb2VzIG5vdCBkZW1vbnN0cmF0ZSBzbWFsbCB3b3JsZCBwcm9wZXJpdGllcy4KCiMjIFdyYXBwaW5nIHVwClRvIGNvbXBsZXRlIHRoZSBsYWIsIG1ha2Ugc3VyZSBvdXRwdXQvcHJldmlld3MgaGF2ZSBiZWVuIGdlbmVyYXRlZCBmb3IgZWFjaCBibG9jayBvZiBjb2RlLiBUaGVuIGNsaWNrIHRoZSAiUHVibGlzaCIgYnV0dG9uIG9uIHRoZSB1cHBlciByaWdodCBoYW5kIGNvcm5lciBvZiB0aGlzIHNjcmVlbiBhbmQgc2lnbiB1cCBmb3IgYW4gUlB1YnMgYWNjb3VudC4gU3VibWl0IHRoZSBVUkwgb2YgdGhlIHB1Ymxpc2hlZCwgY29tcGxldGVkIGxhYiBvbiBDYW52YXMu