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
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. It would appear the list of words given for this assignment are names involved in the # take a knee protest. 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 did not choose this list, but I can generate some questions or hypotheses. I believe Trump and Kaepernick will be nodes of authority and will have high centrality metrics. 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? They were culled from cavnvas. It was difficult. 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? I think we’ll see Trump, as a node, will hold just about every node title imaginiable. He will bridge the senators subgroup to the NFL subgroup and have high centrality measures.
## 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.
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.
Now we will invoke our function to put information from the API into our global environment.
total_table <- t(sapply(word_list,Get_hits_one))
[1] "“New Orleans Saints”"
[1] 165
[1] "“Steve Scalise”"
[1] 85
[1] "“Sen. Bill Cassidy”"
[1] 8
[1] "“Tampa Bay Buccaneers”"
[1] 140
[1] "“Sen. Bill Nelson”"
[1] 9
[1] "“Sen. Marco Rubio”"
[1] 51
[1] "“Carolina Panthers”"
[1] 308
[1] "“Sen. Lindsey Graham”"
[1] 22
[1] "“Sen. Tim Scott”"
[1] 3
[1] "“Atlanta Falcons”"
[1] 241
[1] "“Sen. Johnny Isakson”"
[1] 3
[1] "“Sen. David Perdue”"
[1] 2
[1] "“Roger Goodell”"
[1] 229
[1] "“Donald Trump”"
[1] 9780
[1] "“Colin Kaepernick”"
[1] 396
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.
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.
network_table <- t(apply(pairs_list,1,Get_hits_two))
[1] "“New Orleans Saints” “Steve Scalise”"
[1] 0
[1] "“New Orleans Saints” “Sen. Bill Cassidy”"
[1] 0
[1] "“New Orleans Saints” “Tampa Bay Buccaneers”"
[1] 51
[1] "“New Orleans Saints” “Sen. Bill Nelson”"
[1] 0
[1] "“New Orleans Saints” “Sen. Marco Rubio”"
[1] 0
[1] "“New Orleans Saints” “Carolina Panthers”"
[1] 57
[1] "“New Orleans Saints” “Sen. Lindsey Graham”"
[1] 0
[1] "“New Orleans Saints” “Sen. Tim Scott”"
[1] 0
[1] "“New Orleans Saints” “Atlanta Falcons”"
[1] 56
[1] "“New Orleans Saints” “Sen. Johnny Isakson”"
[1] 0
[1] "“New Orleans Saints” “Sen. David Perdue”"
[1] 0
[1] "“New Orleans Saints” “Roger Goodell”"
[1] 11
[1] "“New Orleans Saints” “Donald Trump”"
[1] 2
[1] "“New Orleans Saints” “Colin Kaepernick”"
[1] 15
[1] "“Steve Scalise” “Sen. Bill Cassidy”"
[1] 1
[1] "“Steve Scalise” “Tampa Bay Buccaneers”"
[1] 0
[1] "“Steve Scalise” “Sen. Bill Nelson”"
[1] 1
[1] "“Steve Scalise” “Sen. Marco Rubio”"
[1] 1
[1] "“Steve Scalise” “Carolina Panthers”"
[1] 0
[1] "“Steve Scalise” “Sen. Lindsey Graham”"
[1] 0
[1] "“Steve Scalise” “Sen. Tim Scott”"
[1] 0
[1] "“Steve Scalise” “Atlanta Falcons”"
[1] 0
[1] "“Steve Scalise” “Sen. Johnny Isakson”"
[1] 0
[1] "“Steve Scalise” “Sen. David Perdue”"
[1] 0
[1] "“Steve Scalise” “Roger Goodell”"
[1] 0
[1] "“Steve Scalise” “Donald Trump”"
[1] 13
[1] "“Steve Scalise” “Colin Kaepernick”"
[1] 0
[1] "“Sen. Bill Cassidy” “Tampa Bay Buccaneers”"
[1] 0
[1] "“Sen. Bill Cassidy” “Sen. Bill Nelson”"
[1] 0
[1] "“Sen. Bill Cassidy” “Sen. Marco Rubio”"
[1] 0
[1] "“Sen. Bill Cassidy” “Carolina Panthers”"
[1] 0
[1] "“Sen. Bill Cassidy” “Sen. Lindsey Graham”"
[1] 0
[1] "“Sen. Bill Cassidy” “Sen. Tim Scott”"
[1] 1
[1] "“Sen. Bill Cassidy” “Atlanta Falcons”"
[1] 0
[1] "“Sen. Bill Cassidy” “Sen. Johnny Isakson”"
[1] 0
[1] "“Sen. Bill Cassidy” “Sen. David Perdue”"
[1] 0
[1] "“Sen. Bill Cassidy” “Roger Goodell”"
[1] 0
[1] "“Sen. Bill Cassidy” “Donald Trump”"
[1] 3
[1] "“Sen. Bill Cassidy” “Colin Kaepernick”"
[1] 0
[1] "“Tampa Bay Buccaneers” “Sen. Bill Nelson”"
[1] 0
[1] "“Tampa Bay Buccaneers” “Sen. Marco Rubio”"
[1] 0
[1] "“Tampa Bay Buccaneers” “Carolina Panthers”"
[1] 64
[1] "“Tampa Bay Buccaneers” “Sen. Lindsey Graham”"
[1] 0
[1] "“Tampa Bay Buccaneers” “Sen. Tim Scott”"
[1] 0
[1] "“Tampa Bay Buccaneers” “Atlanta Falcons”"
[1] 53
[1] "“Tampa Bay Buccaneers” “Sen. Johnny Isakson”"
[1] 0
[1] "“Tampa Bay Buccaneers” “Sen. David Perdue”"
[1] 0
[1] "“Tampa Bay Buccaneers” “Roger Goodell”"
[1] 7
[1] "“Tampa Bay Buccaneers” “Donald Trump”"
[1] 2
[1] "“Tampa Bay Buccaneers” “Colin Kaepernick”"
[1] 14
[1] "“Sen. Bill Nelson” “Sen. Marco Rubio”"
[1] 2
[1] "“Sen. Bill Nelson” “Carolina Panthers”"
[1] 0
[1] "“Sen. Bill Nelson” “Sen. Lindsey Graham”"
[1] 1
[1] "“Sen. Bill Nelson” “Sen. Tim Scott”"
[1] 0
[1] "“Sen. Bill Nelson” “Atlanta Falcons”"
[1] 0
[1] "“Sen. Bill Nelson” “Sen. Johnny Isakson”"
[1] 0
[1] "“Sen. Bill Nelson” “Sen. David Perdue”"
[1] 0
[1] "“Sen. Bill Nelson” “Roger Goodell”"
[1] 0
[1] "“Sen. Bill Nelson” “Donald Trump”"
[1] 2
[1] "“Sen. Bill Nelson” “Colin Kaepernick”"
[1] 0
[1] "“Sen. Marco Rubio” “Carolina Panthers”"
[1] 0
[1] "“Sen. Marco Rubio” “Sen. Lindsey Graham”"
[1] 1
[1] "“Sen. Marco Rubio” “Sen. Tim Scott”"
[1] 0
[1] "“Sen. Marco Rubio” “Atlanta Falcons”"
[1] 0
[1] "“Sen. Marco Rubio” “Sen. Johnny Isakson”"
[1] 0
[1] "“Sen. Marco Rubio” “Sen. David Perdue”"
[1] 0
[1] "“Sen. Marco Rubio” “Roger Goodell”"
[1] 0
[1] "“Sen. Marco Rubio” “Donald Trump”"
[1] 28
[1] "“Sen. Marco Rubio” “Colin Kaepernick”"
[1] 0
[1] "“Carolina Panthers” “Sen. Lindsey Graham”"
[1] 0
[1] "“Carolina Panthers” “Sen. Tim Scott”"
[1] 0
[1] "“Carolina Panthers” “Atlanta Falcons”"
[1] 60
[1] "“Carolina Panthers” “Sen. Johnny Isakson”"
[1] 0
[1] "“Carolina Panthers” “Sen. David Perdue”"
[1] 0
[1] "“Carolina Panthers” “Roger Goodell”"
[1] 17
[1] "“Carolina Panthers” “Donald Trump”"
[1] 9
[1] "“Carolina Panthers” “Colin Kaepernick”"
[1] 36
[1] "“Sen. Lindsey Graham” “Sen. Tim Scott”"
[1] 0
[1] "“Sen. Lindsey Graham” “Atlanta Falcons”"
[1] 0
[1] "“Sen. Lindsey Graham” “Sen. Johnny Isakson”"
[1] 0
[1] "“Sen. Lindsey Graham” “Sen. David Perdue”"
[1] 0
[1] "“Sen. Lindsey Graham” “Roger Goodell”"
[1] 0
[1] "“Sen. Lindsey Graham” “Donald Trump”"
[1] 15
[1] "“Sen. Lindsey Graham” “Colin Kaepernick”"
[1] 0
[1] "“Sen. Tim Scott” “Atlanta Falcons”"
[1] 0
[1] "“Sen. Tim Scott” “Sen. Johnny Isakson”"
[1] 0
[1] "“Sen. Tim Scott” “Sen. David Perdue”"
[1] 0
[1] "“Sen. Tim Scott” “Roger Goodell”"
[1] 0
[1] "“Sen. Tim Scott” “Donald Trump”"
[1] 0
[1] "“Sen. Tim Scott” “Colin Kaepernick”"
[1] 0
[1] "“Atlanta Falcons” “Sen. Johnny Isakson”"
[1] 0
[1] "“Atlanta Falcons” “Sen. David Perdue”"
[1] 0
[1] "“Atlanta Falcons” “Roger Goodell”"
[1] 20
[1] "“Atlanta Falcons” “Donald Trump”"
[1] 9
[1] "“Atlanta Falcons” “Colin Kaepernick”"
[1] 19
[1] "“Sen. Johnny Isakson” “Sen. David Perdue”"
[1] 0
[1] "“Sen. Johnny Isakson” “Roger Goodell”"
[1] 0
[1] "“Sen. Johnny Isakson” “Donald Trump”"
[1] 2
[1] "“Sen. Johnny Isakson” “Colin Kaepernick”"
[1] 0
[1] "“Sen. David Perdue” “Roger Goodell”"
[1] 0
[1] "“Sen. David Perdue” “Donald Trump”"
[1] 1
[1] "“Sen. David Perdue” “Colin Kaepernick”"
[1] 0
[1] "“Roger Goodell” “Donald Trump”"
[1] 31
[1] "“Roger Goodell” “Colin Kaepernick”"
[1] 50
[1] "“Donald Trump” “Colin Kaepernick”"
[1] 59
Analysis
Is the graph directed or undirected? undirected How many nodes and links does your network have? 35 links 15 nodes
numVertices
[1] 15
What is the number of possible links in your network? 105
maxEdges <- numVertices*(numVertices-1)/2
maxEdges
[1] 105
What is the density of your network? .0333
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).
I would expect a different structure of the network if I used different search terms. Say, for example, I used all NFL search terms, I would probably get a more connected component. There are many ways this method of data collection can skew my data. For example, the senators search terms start with ‘sen.’ instead of ‘senator’. This may alter how many hits those nodes get. As noted above, the names may pull articles on people that were not our targets.
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.
A beautiful network. As hypothesized, Trump is the bridge for the two subgroups. There are two nodes that have no connection to any other nodes except Trump, but other than those there are two main subgroups, senators and NFL related search terms. Every node in the network has a direct link with the Trump node with the exception of ’Sen. Time Scott. That node only has a connection to Trump through Sen. Bill Cassidy.
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 as there are no isolates or other distinct components. The graph does give insight into the co-occurence pattern. It is clear that the NFL terms are written about together, then the NFL and Trump, then Trump and the Senators almost creating a bow tie pattern. Trump bridges the two sub-groups with his recent Twitter tirade about kneeling during the pledge.
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.
There are no real differenced other than some changes to the distance in which edges span.
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

Briefly explain degree centrality and why nodes are more or less central in the network. Degree centrality takes into consideration the amount of ties leading to a node. In other words, the node with the most edges in an undirected network is the most central node. In this case, it’s Trump as he has the most edges and largest size in the degree centrality graph. The error here, is that his node is not orange. :) As for the NFL nodes, they all are interconnected creating many edges between nodes in that subgroup; consequently raising each node’s degree centrality. All the NFL node’s degree centrality is boosted due to the fact they are all interconnected. The smallest nodes of the graph are the pendants as they only have one edge.
Weighted Degree Centrality

What does the addition of weighted degree and edge information tell you about your graph? What a beautiful graph. The weighted edges indicates that there was a large, or largest, volume of articles about Trump and his fued with Kaepernick. In contrast, there were only a small amount of articles pertaining to Trump and about half of his senators. The other half, the closest in proximity, had quite strong ties. If anything I think this demonstrates a problem with our society; that is, articles on Trump badgering a protester get more views than articles pertaining to senators.
Betweenness Centrality

Briefly explain betweenness centrality and why nodes are more or less central in the network. Betweenness centrality computes a value based on the number of times a node acts as a bridge on the shortest path between two nodes. Trump very clearly has the highest betweenness centrality, followed by Cassidy. Cassidy’s value is probably bolstered by the fact that he has a pendant that is dependant on him. ### Weighted Betweenness Centrality

What does the addition of weighted degree and edge information tell you about your graph? Trump very clearly has the highest betweenness centrality, followed by Sen. Bill Nelson. Interestingly enough, the Tampa Bay Buccs have a moderately high betweenness centrality; this is probably because there are a slew of other nodes that are on the farthest side away from Trump, a broker node.
Closeness Centrality

Briefly explain closeness centrality and why nodes are more or less central in the network. Closeness centrality is the average length of the shortest path between the node and every nod ein the network. Again Trump is the most central node; however, this time, not by much. It seems that most nodes share an average closeness centrality.
Weighted Closeness Centrality

What does the addition of weighted degree and edge information tell you about your graph? I actually lose information, and gain counter-intuitive information. I lost any meaning in the node size. I gained confusing information like the two Trump node pendants being almost the same size as every node in the network while having very little weight on their edges.
Eigenvector Centrality
eigc <- eigen_centrality(g_valued,directed=TRUE)
sort(eigc$vector,decreasing=TRUE)[1:5]
“Donald Trump” “New Orleans Saints” “Carolina Panthers”
1.0000000 0.7745642 0.7745642
“Colin Kaepernick” “Tampa Bay Buccaneers”
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. This measure of centrality computes scores based on other scores in the network. In other words, if a node has a high score, then nodes directly connecting to it will also have high scores. This makes sense looking at the visualization and knowing the weight of the edges from previous graphs. The Trump node is the highest rated as it’s the most important node to the network. The NFL nodes are deemed important because each one has a direct connection with Trump, then amplified by having connections between each other NFL node. The NFL nodes are deemed even more important due to the volume of articles in which Trump’s search term co-occurs with the NFL nodes.
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 find the unweighted betweenness centrality to be the most interesting as, visually, it has the most striking node size difference. It is very evident from that graph that Trump is the most important, central node in the network.
Briefly discuss an interesting difference between types of centrality for your network.
I think the most interesting difference is that in some centrality visualizations many of the nodes are equally as important as Trump. I think the values are getting gamed a little in the way they are calculated, but it is interesting nonetheless.
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 0.77456419
[8] 0.25123207 0.03329756 0.77456419 0.15895601 0.15895601 0.77456419 1.00000000
[15] 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: 0.5952381 Betweenness: 0.7056515 Closeness: 0.7779971 Eigenvector: 0.5904349 Briefly explain what the centralization of a network is. These centrality values are network wide. Previous computations of centrality metrics were node level, where as these scores are network level.
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. It would appear as though the lower the number, the more network wide variance in node centrality metrics. Consequently, the most interesting graphs have the largest variance in node sizes/node metrics.
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.

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).

Does your network exhibit a power law distribution of degree centrality?
There is no evidence of a power law present in the network. A power law would be represented as an straight line with a negative slope.
Small Worlds
Networks often demonstrate small world characteristics. Compute the average clustering coefficient (ACC) and the characteristic path length (CPL).
# Average clustering coefficient (ACC)
transitivity(g_valued, type = c("average"))
[1] 0.8279915
# Characteristic path length (CPL)
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.
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.3382114
cplSum/100
[1] 1.795348
Based on these data, would you conclude that the observed network demonstrates small world properties? Why or why not? Yes, my network does appear to demonstrate small world properties. The clustering coefficient is higher than that of the random ACC indicating clustering and in support of small world. And, additionally, the characteristic path length is high, almost as high as the CPL in the random, which would indicate small world properties. ## 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.
LS0tCnRpdGxlOiAnRGVzY3JpcHRpdmUgQW5hbHl0aWMgRXhlcmNpc2UgMTogVmlzdWFsaXppbmcgYW5kIEludGVycHJldGluZyBOZXR3b3JrcycKb3V0cHV0OgogIGh0bWxfbm90ZWJvb2s6IGRlZmF1bHQKICBodG1sX2RvY3VtZW50OiBkZWZhdWx0CiAgcGRmX2RvY3VtZW50OiBkZWZhdWx0CiAgd29yZF9kb2N1bWVudDogZGVmYXVsdAotLS0KKipTTkEgR3JhZCBTZW1pbmFyLCBGYWxsIDIwMTcqKgoqKkR1ZToqKiBPY3RvYmVyIDI0dGgsIDExOjU5IHBtCioqTmFtZSBvZiBTdHVkZW50Kio6IAoKVGhlIHB1cnBvc2Ugb2YgdGhpcyBsYWIgaXMgdG8gZGV2ZWxvcCB5b3VyIGZhbWlsaWFyaXR5IGNvbmR1Y3RpbmcgZGVzY3JpcHRpdmUgbmV0d29yayBhbmFseXNpcyB1c2luZyB0aGUgc3RhdGlzdGljYWwgc29mdHdhcmUgcGFja2FnZSBSLiBUaGlzIGFzc2lnbm1lbnQgd2lsbCBtYWtlIHVzZSBvZiBhIGRhdGEgc2V0IHlvdSBjb2xsZWN0IGJ5IGRlZmluaW5nIGEgc2VhcmNoIHF1ZXJ5IChhIGNvbGxlY3Rpb24gb2YgeW91ciB1c2VyLWRlZmluZWQgc2VhcmNoIHRlcm1zKSBmcm9tIHRoZSAqW05ldyBZb3JrIFRpbWVzXSh3d3cubnl0aW1lcy5jb20pKidzIEFydGljbGUgU2VhcmNoIFtBcHBsaWNhdGlvbiBQcm9ncmFtbWluZyBJbnRlcmZhY2VdKGh0dHBzOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL0FwcGxpY2F0aW9uX3Byb2dyYW1taW5nX2ludGVyZmFjZSkuIE5ldHdvcmtzIGFyZSBnZW5lcmF0ZWQgZnJvbSB0aGUgY28tb2NjdXJyZW5jZXMgYmV0d2VlbiBzZWFyY2ggdGVybXMgaW5jbHVkZWQgaW4gdGhlIHNhbWUgc2VhcmNoIHF1ZXJ5LiBGb3IgZXhhbXBsZSwgYSBsaW5rIGV4aXN0cyBiZXR3ZWVuIOKAnGFwcGxl4oCdIGFuZCDigJxvcmFuZ2XigJ0gaWYgdGhlcmUgYXJlIGFydGljbGVzIGluIHRoZSAqTmV3IFlvcmsgVGltZXMqIHRoYXQgY29udGFpbmVkIHRoZXNlIHR3byB0ZXJtcy4gIFlvdSB3aWxsIGJlIHZpc3VhbGl6aW5nIGFuZCBpbnRlcnByZXRpbmcgaW5kaXZpZHVhbCBhbmQgZ2xvYmFsIG5ldHdvcmsgcHJvcGVydGllcyBvZiB0aGlzIG5ldHdvcmsuCgpZb3Ugd2lsbCBiZSBncmFkZWQgcHJpbWFyaWx5IG9uIHRoZSBjb21wbGV0ZW5lc3MgYW5kIGFjY3VyYWN5IG9mIHlvdXIgcmVzcG9uc2VzLCBidXQgdGhlIGNsYXJpdHkgb2YgdGhlIHByZXBhcmVkIHJlcG9ydCB3aWxsIGFsc28gYWZmZWN0IHlvdXIgZ3JhZGUuICBXaGlsZSBzdHVkZW50cyBtYXkgd29yayB0b2dldGhlciB0byBwZXJmb3JtIHRoZSBhbmFseXNpcywgZWFjaCBzdHVkZW50IG11c3Qgc3VibWl0IGhpcyBvciBoZXIgb3duIHJlcG9ydCBhbmQgaXMgcmVzcG9uc2libGUgZm9yIHdyaXRpbmcgdGhlIG5hcnJhdGl2ZSBpbiB0aGUgcmVwb3J0LiBZb3UgbXVzdCBhbnN3ZXIgYWxsIG9mIHRoZSBib2xkZWQgcXVlc3Rpb25zLgoKIyBQYXJ0IDE6IENvbGxlY3QgTmV0d29yayBEYXRhICgyMCBwdHMpCgpGb3IgdGhpcyBsYWIsIHlvdSB3aWxsIHNlYXJjaCB0aGUgKk5ldyBZb3JrIFRpbWVzKiwgc2F2ZSB0aGF0IGRhdGEsIGNyZWF0ZSBuZXR3b3JrcyBmcm9tIHRoYXQgZGF0YSwgY29tcGFyZSB0aGUgZGlmZmVyZW5jZXMgYW1vbmcgbmV0d29ya3MsIGFuZCBkZW1vbnN0cmF0ZSB5b3VyIHByb2ZpY2llbmN5IHdpdGggYmFzaWMgbmV0d29yayBkZXNjcmlwdGl2ZSBzdGF0aXN0aWNzLgoKIyMgTG9hZGluZyBhbmQgSW5zdGFsbGluZyBQYWNrYWdlcywgU2V0IFdvcmtpbmcgRGlyZWN0b3J5CgpXaGVuIHdvcmtpbmcgd2l0aCBSLCB5b3Ugc2hvdWxkIHJ1biBlYWNoIGxpbmUgb2YgY29kZSBpbmRpdmlkdWFsbHksIHVubGVzcyBpdCBpcyBwYXJ0IG9mIGEgZnVuY3Rpb24gZGVmaW5pdGlvbiwgc28geW91IGNhbiBzZWUgdGhlIHJlc3VsdHMuIEdlbmVyYWxseSBzcGVha2luZywgYW55IGxpbmUgb2YgY29kZSB0aGF0IGluY2x1ZGVzICd7JyAodGhlIGJlZ2lubmluZyBvZiBhIGZ1bmN0aW9uIGRlZmluaXRpb24pIHNob3VsZCBiZSBydW4gd2l0aCBhbGwgdGhlIG90aGVyIGxpbmVzIHVudGlsIHlvdSBoaXQgJ30nLgoKYGBge3J9CiMgTGluZXMgdGhhdCBzdGFydCB3aXRoIGEgaGFzaHRhZy9wb3VuZCBzeW1ib2wsIGxpa2UgdGhpcyBvbmUsIGFyZSBjb21tZW50IGxpbmVzLiBDb21tZW50IGxpbmVzIGFyZSBpZ25vcmVkIGJ5IFIgd2hlbiBpdCBpcyBpbnRlcnByZXRpbmcgY29kZS4KIyBZb3Ugb25seSBuZWVkIHRvIGluc3RhbGwgcGFja2FnZXMgb25jZS4gUmVtb3ZlIHRoZSAjIGluIGZyb250IG9mIGVhY2ggbGluZSBhbmQgdGhlbiBydW4gaXQgdG8gaW5zdGFsbCBlYWNoIHBhY2thZ2UuIEFmdGVyIHN1Y2Nlc3NmdWwgaW5zdGFsbGF0aW9uLCBkZWxldGUgdGhlIGxpbmUgb2YgY29kZSBvciByZXBsYWNlIHRoZSAjcyBzbyB0aGUgUiBOb3RlYm9vayBkb2Vzbid0IHJ1biBpbnRvIHByb2JsZW1zLgojIGluc3RhbGwucGFja2FnZXMoJ21hZ3JpdHRyJywgcmVwb3MgPSAiaHR0cHM6Ly9jcmFuLnJzdHVkaW8uY29tIikKIyBpbnN0YWxsLnBhY2thZ2VzKCdpZ3JhcGgnLCByZXBvcyA9ICJodHRwczovL2NyYW4ucnN0dWRpby5jb20iKQojIGluc3RhbGwucGFja2FnZXMoJ2h0dHInLCByZXBvcyA9ICJodHRwczovL2NyYW4ucnN0dWRpby5jb20iKQojIGluc3RhbGwucGFja2FnZXMoJ2RhdGEudGFibGUnLCByZXBvcyA9ICJodHRwczovL2NyYW4ucnN0dWRpby5jb20iKQojIGluc3RhbGwucGFja2FnZXMoJ2RwbHlyJywgcmVwb3MgPSAiaHR0cHM6Ly9jcmFuLnJzdHVkaW8uY29tIikKIyBpbnN0YWxsLnBhY2thZ2VzKCd4bWwyJywgcmVwb3MgPSAiaHR0cHM6Ly9jcmFuLnJzdHVkaW8uY29tIikKIyBZb3UgbmVlZCB0byBsb2FkIHBhY2thZ2VzIGV2ZXJ5IHRpbWUgeW91IHJ1biB0aGUgc2NyaXB0IG9yIHJlc3RhcnQgUi4KbGlicmFyeShtYWdyaXR0cikKbGlicmFyeShodHRyKQpsaWJyYXJ5KGRhdGEudGFibGUpCmxpYnJhcnkoaWdyYXBoKQpsaWJyYXJ5KGRwbHlyKQpsaWJyYXJ5KHhtbDIpCiMgU2V0IHlvdXIgZGlyZWN0b3J5IGZvciB0aGUgcHJvamVjdAojIFlvdSBjYW4gZWl0aGVyIGVudGVyIHlvdXIgZmlsZW5hbWUgcGF0aCB3aXRoaW4gdGhlIHBhcmVudGhlc2VzIGJlbG93IGFuZCByZW1vdmUgdGhlICMgY3JlYXRpbmcgdGhlIGNvbW1lbnQsIG9yIHNlbGVjdCAiU2Vzc2lvbiA+IFNldCBXb3JraW5nIERpcmVjdG9yeSAuLi4gU291cmNlIEZpbGUgTG9jYXRpb24iIGluIFIgU3R1ZGlvLgojIHNldHdkKCJJbnB1dCBEaXJlY3RvcnkiKQpgYGAKCiMjIENob29zZSBhIHRvcGljIGZvciB5b3VyIHNlYXJjaCB0ZXJtcwoKWW91IGNhbiBkZWNpZGUgc2VhcmNoIHRlcm1zIGJhc2VkIG9uIHBlcnNvbmFsIGludGVyZXN0cywgcmVzZWFyY2ggaW50ZXJlc3RzLCBvciBwb3B1bGFyIHRvcGljYWwgYXJlYXMsIGFtb25nIG90aGVycy4gWW91IGhhdmUgZmxleGliaWxpdHkgaW4gc2VsZWN0aW5nIHlvdXIgc2VhcmNoIHRlcm0gbGlzdC4gRm9yIGV4YW1wbGUsIHlvdSBjYW4gc2VhcmNoIGZvciBzb21lIGNvbW1lcmNpYWwgYnJhbmRzLCBjZWxlYnJpdGllcywgY291bnRyaWVzLCB1bml2ZXJzaXRpZXMsIGV0Yy4gSXQgd2lsbCBiZSBtb3N0IHVzZWZ1bCBpZiB5b3UgY2hvb3NlIGEgY29sbGVjdGlvbiBvZiB3b3JkcyB0aGF0IGFyZSBub3QgYWxsIGV4dHJlbWVseSBjb21tb24uIFRoaW5rIGFib3V0IGEgc2V0IG9mIHdvcmRzIHRoYXQgbWlnaHQgaGF2ZSBpbnRlcmVzdGluZyBjby1vY2N1cnJlbmNlcyBpbiBhcnRpY2xlcyB3aXRoaW4gdGhlICpOZXcgWW9yayBUaW1lcyogd2Vic2l0ZS4gRm9yIGV4YW1wbGUsIHlvdSBtaWdodCBiZSBpbnRlcmVzdGVkIGluIHRoZSBsYXN0IG5hbWVzIG9mIGV2ZXJ5IFNlbmF0b3IgaW52b2x2ZWQgaW4gYSBjZXJ0YWluIHBvbGl0aWNhbCBkZWJhdGUsIGZvb3RiYWxsIHRlYW1zLCBvciBjaXRpZXMgYW5kIHRoZWlyIGNvLW9jY3VycmVuY2UgaW4gbmV3cyBhcnRpY2xlcy4gR2VuZXJhbGx5IHNwZWFraW5nLCBwcm9wZXIgbm91bnMgYXJlIGJlc3QsIGJ1dCB5b3UgbWlnaHQgaGF2ZSBjb21wZWxsaW5nIHJlYXNvbnMgdG8gY2hvb3NlIHZlcmJzIG9yIGFkamVjdGl2ZXMuIFlvdSBtaWdodCB3YW50IHRvIHRocm93IGEgY291cGxlIG9mIHRlcm1zIGluIHRoYXQgYXJlbid0IHRoZW1hdGljYWxseSByZWxhdGVkIHRvIG1ha2Ugc3VyZSB5b3UgZG9uJ3QgZ2V0IGEgdG90YWxseSBjb25uZWN0ZWQgY29tcG9uZW50LiBUaGUgbW9yZSBpbnRlcmVzdGluZyB5b3VyIG5ldHdvcmsgaXMgaW4gdGVybXMgb2YgZGlmZmVyaW5nIGNlbnRyYWxpdHksIGRpc3RpbmN0IGNvbXBvbmVudHMsIGV0Yy4sIHRoZSBlYXNpZXIgaXQgd2lsbCBiZSB0byBkbyB0aGUgd3JpdHRlbiBhbmFseXNpcy4gS2VlcCBpbiBtaW5kIHRoYXQgdGhlIEFydGljbGUgU2VhcmNoIGFyY2hpdmUgaXMgdmVyeSBsYXJnZTsgbWFueSB0ZXJtcyBjby1vY2N1ci4gWW91IG1pZ2h0IHdhbnQgdG8gY29uc2lkZXIgdHdvIHRlbnVvdXNseSByZWxhdGVkIHN1YmplY3RzLiBUaGUgZXhhbXBsZSBmaWxlIHVzZXMgZm91ciBmb290YmFsbCB0ZWFtcyBhbmQgdGhlaXIgaG9tZSBzZW5hdG9ycywgcGx1cyBhIGZldyB0b3BpY2FsIHRlcm1zLgoKIyMgQ3JlYXRlIHlvdXIgdGV4dCBpbnB1dAoKQ3JlYXRlIGEgcGxhaW4gdGV4dCBmaWxlIHdpdGggLnR4dCBleHRlbnNpb24gaW4gdGhlIHNhbWUgZGlyZWN0b3J5IGFzIHRoZSBSIE1hcmtkb3duIE5vdGVib29rIHVzZWQgaW4gdGhpcyBhc3NpZ25tZW50LiBNYWtlIGEgbm90ZSBvZiB0aGUgZmlsZSBuYW1lIGZvciB1c2UgaW4gdGhlIG5leHQgY29kZSBzbmlwcGV0LiBQbGFjZSBvbmUgc2VhcmNoIHRlcm0gcGVyIGxpbmUsIGFuZCB1c2UgMTXigJMyMCB0ZXJtcy4gIFlvdSdsbCBhbHNvIGxpa2VseSB3YW50IHRvIGFkZCBxdW90YXRpb24gbWFya3MgYXJvdW5kIHlvdXIgc2VhcmNoIHRlcm1zIHRvIGVuc3VyZSB0aGF0IHlvdSdyZSBvbmx5IHJlY2VpdmluZyByZXN1bHRzIGZvciB0aGUgY29tcGxldGUgdGVybS4gTk9URTogVGhlIGZ1bmN0aW9uIHdpbGwgcHJvY2VzcyB5b3VyIHRlcm1zIHNvIHRoYXQgdGhleSB3b3JrIGluIHRoZSBVUkwgcmVxdWVzdC4gWW91IGRvIG5vdCBuZWVkIHRvIGVuY29kZSBub24tYWxwaGFiZXRpYyBjaGFyYWN0ZXJzLgoKVGhlIHRleHQgZmlsZSBjYW5ub3QgaW5jbHVkZSBhbnkgYWRkaXRpb25hbCBpbmZvcm1hdGlvbiBvciBjaGFyYWN0ZXJzIGFuZCBpdCBtdXN0IGJlIGEgLnR4dCBmaWxlOyBXb3JkIG9yIFJURiBkb2N1bWVudHMgd29u4oCZdCB3b3JrLgoKIyMgQW5hbHlzaXMKCioqYS4JUHJvdmlkZSBhIGhpZ2ggbGV2ZWwgb3ZlcnZpZXcgb2YgdGhlIHRlcm1zIHlvdSBpbmNsdWRlZCBpbiB0aGUgc2VhcmNoIHF1ZXJ5LioqCiAgSXQgd291bGQgYXBwZWFyIHRoZSBsaXN0IG9mIHdvcmRzIGdpdmVuIGZvciB0aGlzIGFzc2lnbm1lbnQgYXJlIG5hbWVzIGludm9sdmVkIGluIHRoZSAjIHRha2UgYSBrbmVlIHByb3Rlc3QuCioqYi4JV2h5IGRpZCB5b3UgY2hvb3NlIHRoaXMgY29sbGVjdGlvbiBvZiB0ZXJtcz8gIFdlcmUgdGhlcmUgc29tZSBzcGVjaWZpYyBvdmVyYXJjaGluZyBxdWVzdGlvbuKAlGludGVsbGVjdHVhbCBvciBleHRyYWN1cnJpY3VsYXIgY3VyaW9zaXR54oCUdGhhdCBtb3RpdmF0ZWQgdGhpcyBjb2xsZWN0aW9uIG9mIHRlcm1zPyoqCiAgSSBkaWQgbm90IGNob29zZSB0aGlzIGxpc3QsIGJ1dCBJIGNhbiBnZW5lcmF0ZSBzb21lIHF1ZXN0aW9ucyBvciBoeXBvdGhlc2VzLiBJIGJlbGlldmUgVHJ1bXAgYW5kIEthZXBlcm5pY2sgd2lsbCBiZSBub2RlcyBvZiBhdXRob3JpdHkgYW5kIHdpbGwgaGF2ZSBoaWdoIGNlbnRyYWxpdHkgbWV0cmljcy4KKipjLglIb3cgZGlkIHlvdSBkZWNpZGUgd2hpY2ggdGVybXMgdG8gdXNlIGluIHRoZSBzZWFyY2ggcXVlcnk/IFdlcmUgdGhlc2UgdGVybXMgeW91IGludHVpdGl2ZWx5IGRlZW1lZCBpbXBvcnRhbnQ/IFdlcmUgdGhleSBjdWxsZWQgZnJvbSBhIHNwZWNpZmljIHNvdXJjZSBvciB0aGUgcmVzdWx0IG9mIHNvbWUgc2VwYXJhdGUgYW5hbHlzaXMgb3Igc2VhcmNoIHF1ZXJ5PyoqCiBUaGV5IHdlcmUgY3VsbGVkIGZyb20gY2F2bnZhcy4gSXQgd2FzIGRpZmZpY3VsdC4KKipkLglXaGF0IGFyZSB0aGUgaW5zaWdodHMgeW91IGhvcGUgdG8gZ2xlYW4gYnkgbG9va2luZyBhdCB0aGUgbmV0d29yayBvZiB0ZXJtcyBpbiB0ZXJtcyBvZiBpbmRpdmlkdWFsIG5vZGUgbWV0cmljcywgc3ViLWdyb3VwaW5nIG9mIG5vZGVzLCBvdmVyYWxsIGdsb2JhbCBuZXR3b3JrIHByb3BlcnRpZXM/KioKICBJIHRoaW5rIHdlJ2xsIHNlZSBUcnVtcCwgYXMgYSBub2RlLCB3aWxsIGhvbGQganVzdCBhYm91dCBldmVyeSBub2RlIHRpdGxlIGltYWdpbmlhYmxlLiBIZSB3aWxsIGJyaWRnZSB0aGUgc2VuYXRvcnMgc3ViZ3JvdXAgdG8gdGhlIE5GTCBzdWJncm91cCBhbmQgaGF2ZSBoaWdoIGNlbnRyYWxpdHkgbWVhc3VyZXMuICAKIyMgV29ya2luZyB3aXRoIHRoZSBBUEkgdG8gQ29sbGVjdCBZb3VyIERhdGEKVGhlICpOZXcgWW9yayBUaW1lcyogY29udHJvbHMgYWNjZXNzIHRvIGl0cyBBUEkgYnkgYXNzaWduaW5nIGVhY2ggdXNlciBhIGtleS4gRWFjaCBrZXkgaGFzIGEgbGltaXRlZCBudW1iZXIgb2YgY2FsbHMgdGhhdCBjYW4gYmUgbWFkZSB3aXRoaW4gYSBjZXJ0YWluIHRpbWUgcGVyaW9kLiBZb3UgY2FuIHJlYWQgbW9yZSBhYm91dCB0aGUgbGltaXRhdGlvbnMgb2YgdGhlIEFQSSBzeXN0ZW0gW2hlcmVdKGh0dHA6Ly9kZXZlbG9wZXIubnl0aW1lcy5jb20vYXJ0aWNsZV9zZWFyY2hfdjIuanNvbiMpLgoKWW91IHdpbGwgbmVlZCB0byBjcmVhdGUgeW91ciBvd24gQVBJIGtleSB0byBjb21wbGV0ZSB0aGlzIGFzc2lnbm1lbnQuIEdvIHRvIHRoZSAqTmV3IFlvcmsgVGltZXMqIFtkZXZlbG9wZXJzIHBhZ2VdKGh0dHBzOi8vZGV2ZWxvcGVyLm55dGltZXMuY29tL3NpZ251cCkgYW5kIHJlcXVlc3QgYSBrZXkuIFlvdSB3aWxsIGNvcHkgdGhhdCBrZXkgKHJlY2VpdmVkIHZpYSBlbWFpbCkgaW50byB0aGUgYXBpIHZhcmlhYmxlIGJlbG93LgoKYGBge3J9CiMgSW1wb3J0IHlvdXIgd29yZCBsaXN0Cm5hbWVfb2ZfZmlsZSA8LSAiTkZMLnR4dCIgIyBDcmVhdGVzIGEgdmFyaWFibGUgY2FsbGVkIG5hbWVfb2ZfZmlsZSB0aGF0IHlvdSBzaG91bGQgcG9wdWxhdGUgd2l0aCB0aGUgbmFtZSBvZiB5b3VyIHRleHQgZmlsZSBiZXR3ZWVuIHF1b3RhdGlvbiBtYXJrcy4Kd29yZF9saXN0IDwtIHJlYWQudGFibGUobmFtZV9vZl9maWxlLCBzZXAgPSAiXG4iLCBzdHJpbmdzQXNGYWN0b3JzID0gRikgJT4lIHVubGlzdCAlPiUgYXMudmVjdG9yICMgUmVhZHMgdGhlIGNvbnRlbnQgb2YgeW91ciBmaWxlIGludG8gYSB2YXJpYWJsZS4KbnVtX3dvcmRzIDwtIGxlbmd0aCh3b3JkX2xpc3QpICMgQ3JlYXRlcyBhIHZhcmlhYmxlIHdpdGggdGhlIG51bWJlciBvZiB3b3JkcyBpbiB5b3VyIGxpc3QuCnVybF9iYXNlIDwtICJodHRwczovL2FwaS5ueXRpbWVzLmNvbS9zdmMvc2VhcmNoL3YyL2FydGljbGVzZWFyY2guanNvbiIKIyBXaGVuIHlvdSByZWNlaXZlIHRoZSBlbWFpbCB3aXRoIHlvdXIgQVBJIGtleSwgcGFzdGUgaXQgYmVsb3cgYmV0d2VlbiB0aGUgcXVvdGF0aW9uIG1hcmtzLgphcGkgPC0gJzRjOTkyZDQ1MjI4NjRmNTZiNTJkNmYzMDVkNWM0ZDRmJwpgYGAKCk91ciBmaXJzdCBmdW5jdGlvbiB3aWxsIGdhdGhlciBhbGwgb2YgdGhlIHNlYXJjaCB0ZXJtcyBhbmQgdGhlaXIgbnVtYmVyIG9mIGhpdHMgdG8gYmUgcGxhY2VkIGluIGEgdGFibGUuIEFsbCBsaW5lcyBvZiBhIGZ1bmN0aW9uIHNob3VsZCBiZSBydW4gdG9nZXRoZXIuCgpgYGB7cn0KR2V0X2hpdHNfb25lIDwtIGZ1bmN0aW9uKGtleXdvcmQxKSB7CiAgU3lzLnNsZWVwKHRpbWU9MykKICB1cmwgPC0gcGFzdGUwKHVybF9iYXNlLCAiP2FwaS1rZXk9IiwgYXBpLCAiJnE9IiwgVVJMZW5jb2RlKGtleXdvcmQxKSwiJmJlZ2luX2RhdGU9IiwiMjAxNjAxMDEiKSAjIEJlZ2luIGRhdGUgaXMgaW4gZm9ybWF0IFlZWVlNTUREOyB5b3UgY2FuIGNoYW5nZSBpdCBpZiB5b3Ugd2FudCBvbmx5IG1vcmUgcmVjZW50IHJlc3VsdHMsIGZvciBleGFtcGxlLgogICMgVGhlIG51bWJlciBvZiByZXN1bHRzCiAgcHJpbnQoa2V5d29yZDEpCiAgaGl0cyA8LSBjb250ZW50KEdFVCh1cmwpKSRyZXNwb25zZSRtZXRhJGhpdHMgJT4lIGFzLm51bWVyaWMKICBwcmludChoaXRzKQogICMgUHV0IHJlc3VsdHMgaW4gdGFibGUKICBjKFNlYXJjaFRlcm09a2V5d29yZDEsUmVzdWx0c1RvdGFsPWhpdHMpCn0KYGBgCgpOb3cgd2Ugd2lsbCBpbnZva2Ugb3VyIGZ1bmN0aW9uIHRvIHB1dCBpbmZvcm1hdGlvbiBmcm9tIHRoZSBBUEkgaW50byBvdXIgZ2xvYmFsIGVudmlyb25tZW50LgoKYGBge3J9CiNDcmVhdGUgYSB0YWJsZSBvZiB5b3VyIHdvcmRzIGFuZCB0aGVpciBudW1iZXIgb2YgcmVzdWx0cy4KdG90YWxfdGFibGUgPC0gdChzYXBwbHkod29yZF9saXN0LEdldF9oaXRzX29uZSkpCnRvdGFsX3RhYmxlIDwtIGFzLmRhdGEuZnJhbWUodG90YWxfdGFibGUpCnRvdGFsX3RhYmxlJFJlc3VsdHNUb3RhbCA8LSBhcy5udW1lcmljKGFzLmNoYXJhY3Rlcih0b3RhbF90YWJsZSRSZXN1bHRzVG90YWwpKQpgYGAKSWYgeW91IGdldCB6ZXJvIGhpdHMgZm9yIGFueSBvZiB0aGVzZSB0ZXJtcywgeW91IHNob3VsZCBzdWJzdGl0dXRlIHRoYXQgdGVybSBmb3Igc29tZXRoaWduIGVsc2UgYW5kIHJlcnVuIHRoZSBsYWIgdXAgdG8gdGhpcyBwb2ludC4KTmV4dCwgd2Ugd2lsbCBkZWZpbmUgdGhlIGZ1bmN0aW9uIHRoYXQgd2lsbCBjb2xsZWN0IHRoZSBhcnRpY2xlIGNvLW9jY3VyZW5jZXMgbmV0d29yay4KYGBge3J9CkdldF9oaXRzX3R3byA8LSBmdW5jdGlvbihyb3dfaW5wdXQpIHsKICBrZXl3b3JkMSA8LSByb3dfaW5wdXRbMV0KICBrZXl3b3JkMiA8LSByb3dfaW5wdXRbMl0KICB1cmwgPC0gcGFzdGUwKHVybF9iYXNlLCAiP2FwaS1rZXk9IiwgYXBpLCAiJnE9IiwgVVJMZW5jb2RlKGtleXdvcmQxKSwiKyIsIFVSTGVuY29kZShrZXl3b3JkMiksIiZiZWdpbl9kYXRlPSIsIjIwMTYwMTAxIikgI21hdGNoIHcvIEJlZ2luIERhdGUgaW4gR2V0X2hpdHNfb25lLgogICMgVGhlIG51bWJlciBvZiByZXN1bHRzCiAgcHJpbnQocGFzdGUwKGtleXdvcmQxLCIgIixrZXl3b3JkMikpIAogIGhpdHMgPC0gY29udGVudChHRVQodXJsKSkkcmVzcG9uc2UkbWV0YSRoaXRzICU+JSBhcy5udW1lcmljCiAgcHJpbnQoaGl0cykKICBTeXMuc2xlZXAodGltZT0zKQogICMgUHV0IHJlc3VsdHMgaW4gdGFibGUKICBjKFNlYXJjaFRlcm0xPWtleXdvcmQxLFNlYXJjaFRlcm0yPWtleXdvcmQyLENvT2NjdXJyZW5jZXM9aGl0cykKfSAKYGBgCgpJbiB0aGlzIG5leHQgc3RlcCwgd2Ugd2lsbCBjYWxsIHRoZSBBUEkgYW5kIGNvbGxlY3QgdGhlIGNvLW9jY3VycmVuY2UgbmV0d29yay4gVGhpcyBtYXkgdGFrZSBzb21lIHRpbWUuIElmIHlvdSByZWNlaXZlICJudW1lcmljKDApIiBpbiBhbnkgb2YgeW91ciByZXNwb3NuZXMsIHlvdSd2ZSBsaWtlbHkgaGl0IHlvdXIgQVBJIGtleSBsaW1pdCBhbmQgd2lsbCBlaXRoZXIgbmVlZCB0byB3YWl0IGZvciB0aGUgY2FsbHMgdG8gcmVzZXQgKDI0IGhvdXJzKSBvciByZXF1ZXN0IGEgbmV3IGtleS4gSWYgeW91IHJlY2VpdmUgdGhlIGVycm9yIG1lc3NhZ2UgIiQgb3BlcmF0b3IgaXMgaW52YWxpZCBmb3IgYXRvbWljIHZlY3RvcnMsIiB5b3UgaGF2ZSBhbHNvIGhpdCB0aGUgQVBJIGNhbGwgbGltaXQuIFRoaXMgY291bGQgYmUgZHVlIHRvIHJ1bm5pbmcgdGhlIHNjcmlwdCBtdWx0aXBsZSB0aW1lcywgb3IgZHVlIHRvIGhpdHRpbmcgdG9vIG1hbnkgcmVzdWx0cyBiYXNlZCBvbiB2ZXJ5IGNvbW1vbiBzZWFyY2ggdGVybXMuIFJlcXVlc3QgYSBuZXcgQVBJLCBzaG9ydGVuIHlvdXIgd29yZCBsaXN0LCBhbmQgdHJ5IGFnYWluLiBEb24ndCBmb3JnZXQgeW91IG5lZWQgdG8gcmVsb2FkIHlvdXIgd29yZCBsaXN0IGZyb20gdGhlIGZpcnN0IHBhcnQgb2YgdGhlIExhYiBpbiBvcmRlciB0byBnZXQgYSBkaWZmZXJlbnQgc2V0IG9mIHJlc3VsdHMhIFlvdSBtdXN0IGFsc28gcmVydW4gdGhlIGZ1bmN0aW9ucyB0byByZWFzc2lnbiB0aGUgQVBJIHZhbHVlLiBJZiBub25lIG9mIHlvdXIgcmVzdWx0cyBjb21lIGJhY2sgYXMgIjAsIiB5b3UgbWlnaHQgd2FudCB0byByZWRvIHlvdXIgc2VhcmNoIHdpdGggdGhlIGFwcHJvcHJpYXRlIHdvcmRzLgoKYGBge3J9CiMgQ29udmVydCB0aGUgcGFpcnMgbGlzdCBpbnRvIGEgdGFibGUKcGFpcnNfbGlzdCA8LSBleHBhbmQuZ3JpZCh3b3JkX2xpc3Qsd29yZF9saXN0KSAlPiUgZmlsdGVyKFZhcjEgIT0gVmFyMikKcGFpcnNfbGlzdCA8LSB0KGNvbWJuKHdvcmRfbGlzdCwyKSkKI0NyZWF0ZSBhIG5ldHdvcmsgdGFibGUsIHJ1biB0aGUgR2V0X2hpdHNfdHdvIGZ1bmN0aW9uIHVzaW5nIHRoZSBwYWlycyBsaXN0cwpuZXR3b3JrX3RhYmxlIDwtIHQoYXBwbHkocGFpcnNfbGlzdCwxLEdldF9oaXRzX3R3bykpCiNDb252ZXJ0IHRoZSBuZXR3b3JrIHRhYmxlIGludG8gYSBkYXRhZnJhbWUKbmV0d29ya190YWJsZSA8LSBhcy5kYXRhLmZyYW1lKG5ldHdvcmtfdGFibGUpCiMgUmVhZCBlYWNoIHRoZSBjb250ZW50IG9mIGVhY2ggaXRlbSB3aXRoaW4gdGhlICRDb09jY3VycmVlbmNlcyBmYWN0b3IgYXMgY2hhcmFjdGVycywgCiMgdGhlbiBmb3JjZSB0aG9zZSBjaGFyYWN0ZXJzIGludG8gdGhlICJudW1lcmljIiBvciAiZG91YmxlIiB0eXBlLgpuZXR3b3JrX3RhYmxlJENvT2NjdXJyZW5jZXMgPC0gYXMubnVtZXJpYyhhcy5jaGFyYWN0ZXIobmV0d29ya190YWJsZSRDb09jY3VycmVuY2VzKSkKIyBDb252ZXJ0IGRhdGEgdG8gZGF0YS50YWJsZSB0eXBlLgp0b3RhbF90YWJsZSA8LSBhcy5kYXRhLnRhYmxlKHRvdGFsX3RhYmxlKQpuZXR3b3JrX3RhYmxlIDwtIGFzLmRhdGEudGFibGUobmV0d29ya190YWJsZSkKCiMgUmVtb3ZlIHplcm8gZWRnZXMgZnJvbSB5b3VyIG5ldHdvcmsKbmV0d29ya190YWJsZSA8LSBuZXR3b3JrX3RhYmxlWyFDb09jY3VycmVuY2VzPT0wXSAKCiMgQ3JlYXRlIGEgZ3JhcGggb2JqZWN0IHdpdGggeW91ciBkYXRhCmdfdmFsdWVkIDwtIGdyYXBoX2Zyb21fZGF0YV9mcmFtZShkID0gbmV0d29ya190YWJsZVssMTozLHdpdGg9RkFMU0VdLGRpcmVjdGVkID0gRkFMU0UsdmVydGljZXMgPSB0b3RhbF90YWJsZSkKCiMgSWYgeW91J3JlIGhhdmluZyB0cm91YmxlIHdpdGggZGF0YSBjb2xsZWN0aW9uLCB5b3UgY2FuIGxvYWQgdGhlICdORkwgTGFiIFJlc3VsdHMuUkRhdGEnIGZpbGUgbm93IGJ5IGNsaWNraW5nIHRoZSBvcGVuIGZvbGRlciBpY29uIG9uIHRoZSAiRW52aXJvbm1lbnQiIiB0YWIgYW5kIGNvbnRpbnVlIHRoZSBsYWIgZnJvbSBoZXJlLiBZb3UnbGwgbmVlZCB0byBmaWd1cmUgb3V0IHdoYXQgdGhlIHNpZ25pZmljYW5jZSBvZiB0aGUgdGVybXMgYXJlIHlvdXJzZWxmLCBob3dldmVyLgojIFlvdSBzaG91bGQgc2F2ZSB5b3VyIGRhdGEgYXQgdGhpcyBwb2ludCBieSBjbGlja2luZyB0aGUgZmxvcHB5IGRpc2sgaWNvbiB1bmRlciB0aGUgIkVudmlyb25tZW50IiB0YWIuCmBgYAoKIyMgQW5hbHlzaXMKCioqSXMgdGhlIGdyYXBoIGRpcmVjdGVkIG9yIHVuZGlyZWN0ZWQ/KiogCnVuZGlyZWN0ZWQKKipIb3cgbWFueSBub2RlcyBhbmQgbGlua3MgZG9lcyB5b3VyIG5ldHdvcmsgaGF2ZT8gKioKMzUgbGlua3MgMTUgbm9kZXMKYGBge3J9Cm51bVZlcnRpY2VzIDwtIHZjb3VudChnX3ZhbHVlZCkKbnVtVmVydGljZXMKbnVtRWRnZXMgPC0gZWNvdW50KGdfdmFsdWVkKQpudW1FZGdlcwpgYGAKCioqV2hhdCBpcyB0aGUgbnVtYmVyIG9mIHBvc3NpYmxlIGxpbmtzIGluIHlvdXIgbmV0d29yaz8gKioKMTA1CmBgYHtyfQptYXhFZGdlcyA8LSBudW1WZXJ0aWNlcyoobnVtVmVydGljZXMtMSkvMgptYXhFZGdlcwpgYGAKCioqV2hhdCBpcyB0aGUgZGVuc2l0eSBvZiB5b3VyIG5ldHdvcms/KiogCi4wMzMzCmBgYHtyfQpncmFwaERlbnNpdHkgPC0gbnVtRWRnZXMvbWF4RWRnZXMgIyBtYW51YWwgY2FsY3VsYXRpb24KZ3JhcGhEZW5zaXR5CmdyYXBoRGVuc2l0eTEgPC0gZ3JhcGguZGVuc2l0eShnX3ZhbHVlZCkgIyB1c2luZyB0aGUgZ3JhcGguZGVuc2l0eSBmdW5jdGlvbiBmcm9tIGlncmFwaApncmFwaERlbnNpdHkxCmBgYAoKKipCcmllZmx5IGRlc2NyaWJlIGhvdyB5b3VyIGNob2ljZSBvZiBkYXRhc2V0IG1heSBpbmZsdWVuY2UgeW91ciBmaW5kaW5ncy4qKiAgV2hhdCBkaWZmZXJlbmNlcyB3b3VsZCB5b3UgZXhwZWN0IGlmIHlvdSB1c2UgZGlmZmVyZW50IHNlYXJjaCB0ZXJtcz8gQXJlIHRoZSBjdXJyZW50IHNlYXJjaCB0ZXJtcyByZWxhdGVkIHRvIG9uZSBhbm90aGVyPyBJZiBzbywgaG93PyBEbyB5b3UgdGhpbmsgdGhlIGxpbWl0YXRpb24gdG8gb25lIHdvcmQgbWlnaHQgc2tldyB5b3VyIGFuc3dlcnM/IChpLmUuIGlmIHlvdeKAmXJlIGludGVyZXN0ZWQgaW4gSGlsbGFyeSBDbGludG9uLCBidXQgeW91IGluY2x1ZGUg4oCcQ2xpbnRvbuKAnSBhcyBhIHRlcm0sIHlvdSB3aWxsIGdldCBzdG9yaWVzIHRoYXQgbWVudGlvbiBDaGVsc2VhLCBCaWxsLCAmIGV2ZW4gUC1GdW5rIEFsbHN0YXIgR2VvcmdlIENsaW50b24pLgoKSSB3b3VsZCBleHBlY3QgYSBkaWZmZXJlbnQgc3RydWN0dXJlIG9mIHRoZSBuZXR3b3JrIGlmIEkgdXNlZCBkaWZmZXJlbnQgc2VhcmNoIHRlcm1zLiBTYXksIGZvciBleGFtcGxlLCBJIHVzZWQgYWxsIE5GTCBzZWFyY2ggdGVybXMsIEkgd291bGQgcHJvYmFibHkgZ2V0IGEgbW9yZSBjb25uZWN0ZWQgY29tcG9uZW50LiBUaGVyZSBhcmUgbWFueSB3YXlzIHRoaXMgbWV0aG9kIG9mIGRhdGEgY29sbGVjdGlvbiBjYW4gc2tldyBteSBkYXRhLiBGb3IgZXhhbXBsZSwgdGhlIHNlbmF0b3JzIHNlYXJjaCB0ZXJtcyBzdGFydCB3aXRoICdzZW4uJyBpbnN0ZWFkIG9mICdzZW5hdG9yJy4gVGhpcyBtYXkgYWx0ZXIgaG93IG1hbnkgaGl0cyB0aG9zZSBub2RlcyBnZXQuIEFzIG5vdGVkIGFib3ZlLCB0aGUgbmFtZXMgbWF5IHB1bGwgYXJ0aWNsZXMgb24gcGVvcGxlIHRoYXQgd2VyZSBub3Qgb3VyIHRhcmdldHMuIAoKIyBQYXJ0IDI6IFZpc3VhbGl6ZSBZb3VyIE5ldHdvcmsgKDIwIHBvaW50cykKCkxldCdzIHN0YXJ0IGJ5IHZpc3VhbGl6aW5nIHRoZSBuZXR3b3JrIHRoYXQgd2UndmUgY29sbGVjdGVkIGZyb20gdGhlICpOZXcgWW9yayBUaW1lcyogQXJ0aWNsZSBTZWFyY2ggQVBJLiBXZSdsbCBuZWVkIHRvIGNob29zZSBub2RlIGNvbG9ycyBhbmQgc2V0IGEgbGF5b3V0LiBZb3UgY2FuIGxlYXJuIG1vcmUgYWJvdXQgRnJ1Y2h0ZXJtYW4gUmVpbmdvbGQgbGF5b3V0IGFuZCBvdGhlciBsYXlvdXRzIFtoZXJlXShodHRwOi8vaWdyYXBoLm9yZy9yL2RvYy9sYXlvdXRfd2l0aF9mci5odG1sKS4KCmBgYHtyfQojIyBMZWFybiBtb3JlIGFib3V0IHBsb3R0aW5nIHdpdGggaWdyYXBoCj8/IGlncmFwaC5wbG90dGluZwpjb2xiYXIgPSByYWluYm93KGxlbmd0aCh3b3JkX2xpc3QpKSAjIyB3ZSBhcmUgc2VsZWN0aW5nIGRpZmZlcmVudCBjb2xvcnMgdG8gY29ycmVzcG9uZCB0byBlYWNoIHdvcmQKVihnX3ZhbHVlZCkkY29sb3IgPSBjb2xiYXIKIyBTZXQgbGF5b3V0IGhlcmUgCkwgPSBsYXlvdXRfd2l0aF9mcihnX3ZhbHVlZCkgICMgRnJ1Y2h0ZXJtYW4gUmVpbmdvbGQKcGxvdChnX3ZhbHVlZCx2ZXJ0ZXguY29sb3I9VihnX3ZhbHVlZCkkY29sb3IsIGxheW91dCA9IEwsIHZlcnRleC5zaXplPTYpIAoKYGBgCiMjIEFuYWx5c2lzCioqSW4gYSBwYXJhZ3JhcGgsIGRlc2NyaWJlIHRoZSBtYWNyby1sZXZlbCBzdHJ1Y3R1cmUgb2YgeW91ciBncmFwaHMgYmFzZWQgb24gdGhlIEZydWNodGVybWFuIFJlaW5nb2xkIHZpc3VhbGl6YXRpb24uKioKCkEgYmVhdXRpZnVsIG5ldHdvcmsuIEFzIGh5cG90aGVzaXplZCwgVHJ1bXAgaXMgdGhlIGJyaWRnZSBmb3IgdGhlIHR3byBzdWJncm91cHMuIFRoZXJlIGFyZSB0d28gbm9kZXMgdGhhdCBoYXZlIG5vIGNvbm5lY3Rpb24gdG8gYW55IG90aGVyIG5vZGVzIGV4Y2VwdCBUcnVtcCwgYnV0IG90aGVyIHRoYW4gdGhvc2UgdGhlcmUgYXJlIHR3byBtYWluIHN1Ymdyb3Vwcywgc2VuYXRvcnMgYW5kIE5GTCByZWxhdGVkIHNlYXJjaCB0ZXJtcy4gRXZlcnkgbm9kZSBpbiB0aGUgbmV0d29yayBoYXMgYSBkaXJlY3QgbGluayB3aXRoIHRoZSBUcnVtcCBub2RlIHdpdGggdGhlIGV4Y2VwdGlvbiBvZiAnU2VuLiBUaW1lIFNjb3R0LiBUaGF0IG5vZGUgb25seSBoYXMgYSBjb25uZWN0aW9uIHRvIFRydW1wIHRocm91Z2ggU2VuLiBCaWxsIENhc3NpZHkuCgpJcyBpdCBhIGdpYW50LCBjb25uZWN0ZWQgY29tcG9uZW50LCBhcmUgdGhlcmUgZGlzdGluY3Qgc3ViLWNvbXBvbmVudHMsIG9yIGFyZSB0aGVyZSBpc29sYXRlZCBjb21wb25lbnRzPyAgQ2FuIHlvdSByZWNvZ25pemUgY29tbW9uIGZlYXR1cmVzIG9mIHRoZSBzdWJjb21wb25lbnRzPyAgRG9lcyB0aGlzIHZpc3VhbGl6YXRpb24gZ2l2ZSB5b3UgYW55IGluc2lnaHQgaW50byB0aGUgY28tb2NjdXJyZW5jZSBwYXR0ZXJucyBvZiB0aGUgc2VhcmNoLXRlcm1zPyAgSWYgeWVzLCB3aGF0PyBJZiBub3QsIHdoeT8KCkl0IGlzIGEgZ2lhbnQgY29tcG9uZW50IGFzIHRoZXJlIGFyZSBubyBpc29sYXRlcyBvciBvdGhlciBkaXN0aW5jdCBjb21wb25lbnRzLiBUaGUgZ3JhcGggZG9lcyBnaXZlIGluc2lnaHQgaW50byB0aGUgY28tb2NjdXJlbmNlIHBhdHRlcm4uIEl0IGlzIGNsZWFyIHRoYXQgdGhlIE5GTCB0ZXJtcyBhcmUgd3JpdHRlbiBhYm91dCB0b2dldGhlciwgdGhlbiB0aGUgTkZMIGFuZCBUcnVtcCwgdGhlbiBUcnVtcCBhbmQgdGhlIFNlbmF0b3JzIGFsbW9zdCBjcmVhdGluZyBhIGJvdyB0aWUgcGF0dGVybi4gVHJ1bXAgYnJpZGdlcyB0aGUgdHdvIHN1Yi1ncm91cHMgd2l0aCBoaXMgcmVjZW50IFR3aXR0ZXIgdGlyYWRlIGFib3V0IGtuZWVsaW5nIGR1cmluZyB0aGUgcGxlZGdlLgoKTm93IHdlJ2xsIGNyZWF0ZSBhIHNlY29uZCB2aXN1YWxpemF0aW9uIHVzaW5nIGEgZGlmZmVyZW50IGxheW91dC4KYGBge3J9CiMjIFlvdSBjYW4gY2hhbmdlIHRoZSBsYXlvdXQgYnkgcGlja2luZyBvbmUgb2YgdGhlIG90aGVyIG9wdGlvbnMuIFVuY29tbWVudCBvbmUgb2YgdGhlIGxpbmVzIGJlbG93IGJ5IGVyYXNpbmcgdGhlICMgYW5kIHJ1bm5pbmcgdGhlIGxpbmUuIFRyeSB0byBmaW5kIGEgbGF5b3V0IHRoYXQgZ2l2ZXMgeW91IGRpZmZlcmVudCBpbmZvcm1hdGlvbiB0aGF0IEZydWNodGVybWFuIFJlaW5nb2xkLgoKIEwgPSBsYXlvdXRfd2l0aF9kaChnX3ZhbHVlZCkgIyMgRGF2aWRzb24gYW5kIEhhcmVsCgojIEwgPSBsYXlvdXRfd2l0aF9kcmwoZ192YWx1ZWQpICMjIEZvcmNlLWRpcmVjdGVkCgojIEwgPSBsYXlvdXRfd2l0aF9rayhnX3ZhbHVlZCkgIyMgU3ByaW5nCnBsb3QoZ192YWx1ZWQsdmVydGV4LmNvbG9yPVYoZ192YWx1ZWQpJGNvbG9yLCBsYXlvdXQgPSBMLCB2ZXJ0ZXguc2l6ZT02KSAKYGBgCiMjIEFuYWx5c2lzCgoqKkluIGEgcGFyYWdyYXBoLCBjb21wYXJlIGFuZCBjb250cmFzdCB0aGUgaW5mb3JtYXRpb24gZ2l2ZW4gdG8geW91IGJ5IHRoZSB0d28gZGlmZmVyZW50IGxheW91dHMuKioKClRoZXJlIGFyZSBubyByZWFsIGRpZmZlcmVuY2VkIG90aGVyIHRoYW4gc29tZSBjaGFuZ2VzIHRvIHRoZSBkaXN0YW5jZSBpbiB3aGljaCBlZGdlcyBzcGFuLiAKCiMgUGFydCAzOiBDb21tdW5pdHkgRGV0ZWN0aW9uIEFuYWx5c2lzIHdpdGggUiAoMjAgUG9pbnRzKQoKSWRlbnRpZnlpbmcgc3ViZ3JvdXBzIHdpdGhpbiBhIG5ldHdvcmsgaXMgb2YgZ3JlYXQgaW50ZXJlc3QgdG8gc29jaWFsIG5ldHdvcmsgcmVzZWFyY2hlcnMsIHNvIGEgdmFyaWV0eSBvZiBhbGdvcml0aG1zIGhhdmUgYmVlbiBkZXZlbG9wZWQgdG8gaWRlbnRpZnkgYW5kIG1lYXN1cmUgc3ViZ3JvdXBzLiAgV2Ugd2lsbCB1c2Ugc29tZSBvZiBS4oCZcyBidWlsdC1pbiB0b29scyB0byBpZGVudGlmeSBzdWJncm91cHMgYW5kIGNlbnRyYWwgbm9kZXMgZm9yIHZpc3VhbCBpbnNwZWN0aW9uLgoKRm9yIHRoZSByZW1haW5kZXIgb2YgdGhlIHZpc3VhbGl6YXRpb25zIHdlIHdpbGwgdXNlIHRoZSBGcnVjaHRlcm1hbiBSZWluZ29sZCBsYXlvdXQuCmBgYHtyfQpMID0gbGF5b3V0X3dpdGhfZnIoZ192YWx1ZWQpIApgYGAKCkNsdXN0ZXIgdGhlIG5vZGVzIGluIHlvdXIgbmV0d29yay4KYGBge3J9CiMgTGVhcm4gbW9yZSBhYm91dCB0aGUgY2x1c3RlcmluZyBhbGdvcml0aG0uCj8/IGNsdXN0ZXJfd2Fsa3RyYXAKY2x1c3RlciA8LSBjbHVzdGVyX3dhbGt0cmFwKGdfdmFsdWVkKQojIEZpbmQgdGhlIG51bWJlciBvZiBjbHVzdGVycwptZW1iZXJzaGlwKGNsdXN0ZXIpICAgIyBhZmZpbGlhdGlvbiBsaXN0Cmxlbmd0aChzaXplcyhjbHVzdGVyKSkgIyBudW1iZXIgb2YgY2x1c3RlcnMKIyBGaW5kIHRoZSBzaXplIHRoZSBlYWNoIGNsdXN0ZXIgCiMgTm90ZSB0aGF0IGNvbW11bml0aWVzIHdpdGggb25lIG5vZGUgYXJlIGlzb2xhdGVzLCBvciBoYXZlIG9ubHkgYSBzaW5nbGUgdGllCnNpemVzKGNsdXN0ZXIpIApgYGAKCioqSG93IG1hbnkgY29tbXVuaXRpZXMgaGF2ZSBiZWVuIGNyZWF0ZWQ/KioKMwoqKkhvdyBtYW55IG5vZGVzIGFyZSBpbiBlYWNoIGNvbW11bml0eT8qKgpJbiBuZXR3b3JrcyBjb250YWluaW5nIG5vZGUgYXR0cmlidXRlIGluZm9ybWF0aW9uLCB3ZSBjYW4gb2Z0ZW4gZ2FpbiBpbnNpZ2h0IGludG8gYSBuZXR3b3JrIGJ5IGxvb2tpbmcgYXQgdGhlIG5vZGVzIHRoYXQgZ2V0IHBsYWNlZCBpbiB0aGUgc2FtZSBwYXJ0aXRpb24uIAoxIDIgMyAKNyAyIDYgCgoqKkZvciB5b3VyIG5ldHdvcmssIHdoYXQgbWlnaHQgZWFjaCBjbHVzdGVyIG9mIG5vZGVzIHBvdGVudGlhbGx5IGhhdmUgaW4gY29tbW9uPyBEZXNjcmliZSBlYWNoIGNsdXN0ZXIsIGl0cyBtZW1iZXJzaGlwLCBhbmQgdGhlIHJlbGF0aW9uc2hpcCBiZXR3ZWVuIG5vZGVzIGluIHRoZSBjbHVzdGVyLioqCgpNb3N0IGxpa2VseSBJIHdpbGwgZmluZCB0aGF0IHRoZSB0aHJlZSBjbHVzdGVycyBhcmUgc3BsaXR0aW5nIHRoZSBzZWFyY2ggdGVybXMgaW50byB0aGUgTkZMOyBUcnVtcCBhbmQgU2VuYXRvcnM7IGFuZCwgc2luY2UgdGhlcmUgYXJlIG9ubHkgdHdvIG5vZGVzIGluIHRoZSBzZWNvbmQgY29tbXVuaXR5LCBJJ20gZ3Vlc3NpbmcgdGhvc2UgbXVzdCBiZSB0aGUgdHdvIHBlbmRhbnQgU2VuYXRvcnMgb2ZmIHRoZSBUcnVtcCBub2RlLgoKTmV4dCB3ZSB2aXN1YWxpemUgdGhlIGNsdXN0ZXJzIGJ5IGNvbG9yaW5nIG5vZGVzIGFjY29yZGluZyB0byB0aGVpciBtb2R1bGFyaXR5IGNsYXNzLiAKYGBge3J9CnBsb3QoY2x1c3RlciwgZ192YWx1ZWQsIGNvbCA9IFYoZ192YWx1ZWQpJGNvbG9yLCBsYXlvdXQgPSBMLCB2ZXJ0ZXguc2l6ZT02KQpgYGAKCioqV2hhdCBpbmZvcm1hdGlvbiBkb2VzIHRoaXMgbGF5b3V0IGNvbnZleT8gIEFyZSB0aGUgY2x1c3RlcnMgd2VsbC1zZXBhcmF0ZWQsIG9yIGlzIHRoZXJlIGEgZ3JlYXQgZGVhbCBvZiBvdmVybGFwPyBJcyBpdCBlYXNpZXIgdG8gaWRlbnRpZnkgdGhlIGNvbW1vbiB0aGVtZXMgYW1vbmcgY2x1c3RlcnMgaW4gdGhpcyBsYXlvdXQgcmF0aGVyIHRoYW4gbG9va2luZyBvbmx5IGF0IHRoZSBncmFwaHM/KioKT25seSBvbmUgb2YgdGhlIHRocmVlIGNvbW11bml0aWVzIHdlcmUgYXMgcHJlZGljdGVkLiBUaGUgb25lIGNvbW11bml0eSBjb3JyZWN0bHkgcHJlZGljdGVkIHdhcyBORkwuIFRoZSByZWFzb24gdGhlIG90aGVyIHR3byB3ZXJlIHdyb25nIGlzIGJlY2F1c2UgdGhlIGNvbW11bml0eSBvZiB0d28gaXMgbm90IGNvbXByaXNlZCBvZiB0aGUgdHdvIHRydW1wIHBlbmRhbnRzLCBidXQsIGluc3RlYWQsIGNvbXByaXNlZCBvZiBTZW4uIENhc3NpZHkgYW5kIFNjb3R0LiBUaGV5IGFyZSB3ZWxsLXNlcGFyYXRlZCB3aXRoIGFic29sdXRlbHkgbm8gb3ZlcmxhcC4gSSBmb3VuZCBpdCBlYXN5IHRvIHNlZSB0aGUgY29tbW9uIHRoZW1lIGJlZm9yZSB0aGUgaHlwZXJncmFwaCwgYnV0IHRoZSBoeXBlcmdyYXBoIGlzIG5pY2UuCgoqKldoYXQgZGlmZmVyZW5jZXMgYXJlIHRoZXJlIGJldHdlZW4gbm9kZXMgaW4gdGhlIHNhbWUgY2x1c3RlciBhbmQgYWNyb3NzIGNsdXN0ZXJzPyoqCkl0J3MgZWFzeSB0byBzZWUgd2h5IHRoZSBORkwgaXMgZ3JvdXBlZCBsaWtlIHRoYXQ7IGhvd2V2ZXIsIGl0IGlzIG5vdCBldmlkZW50IGFzIHRvIHdoeSB0aGUgU2VuYXRvcnMgYW5kIFRydW1wIG5vZGVzIGFyZSBncm91cGVkIGxpa2UgdGhhdC4KCioqRGVzY3JpYmUgdGhlIGJyb2tlcnMgYmV0d2VlbiBhbnkgY29tcG9uZW50cyBhbmQgY2xpcXVlcy4gIFdoYXQgYXJlIGNvbW1vbiBmZWF0dXJlcyBvZiB0aGVzZSBicm9rZXJzPyAgQWJvdXQgaG93IG1hbnkgYnJva2VycyB3b3VsZCB5b3UgaGF2ZSB0byByZW1vdmUgZnJvbSB5b3VyIG5ldHdvcmsgdG8gInNoYXR0ZXIiIGl0IGludG8gdHdvIG9yIG1vcmUgZGlzY29ubmVjdGVkIGNvbXBvbmVudHM/KioKSXQncyB2ZXJ5IGV2aWRlbnQgdGhhdCBUcnVtcCBpcyBhIGJyb2tlciBhbmQgYnJpZGdlIGZvciB0aGUgbmV0d29yay4gSXQncyBsZXNzIG9ic3Zpb3VzIHRoYXQgQ2Fzc2lkeSBpcyBhbHNvIGEgYnJva2VyLiBXaXRob3V0IENhc3NpZHksIFNjb3R0IHdvdWxkIGJlIGZyYWdtZW50ZWQgaW50byBhbiBpc29sYXRlLiBIb3dldmVyLCB3aXRob3V0IHRoZSBUcnVtcCBub2RlIHRoZSBuZXR3b3JrIGJlY29tZXMgc2hhdHRlcmVkIGludG8gNCBjb21wb25lbnRzLgoKIyBQYXJ0IDQ6IENlbnRyYWxpdHkgVmlzdWFsaXphdGlvbiAmIFdlaWdodGVkIFZhbHVlcyAoMjAgUG9pbnRzKQoKRm9yIGVhY2ggbmV0d29yaywgeW91IHdpbGwgdXNlIGNlbnRyYWxpdHkgbWV0cmljcyB0byBpbXByb3ZlIHlvdXIgdmlzdWFsaXphdGlvbi4gWW91IG1heSBuZWVkIHRvIGFkanVzdCB0aGUgc2l6ZSBwYXJhbWV0ZXIgdG8gbWFrZSB5b3VyIG5ldHdvcmsgbW9yZSBlYXNpbHkgdmlzaWJsZS4KCiMjIERlZ3JlZSBDZW50cmFsaXR5CmBgYHtyfQp0b3RhbERlZ3JlZSA8LSBkZWdyZWUoZ192YWx1ZWQsbW9kZT0iYWxsIikKc29ydCh0b3RhbERlZ3JlZSxkZWNyZWFzaW5nPVRSVUUpWzE6NV0KZzIgPC0gZ192YWx1ZWQKVihnMikkc2l6ZSA8LSB0b3RhbERlZ3JlZSoyICNjYW4gYWRqdXN0IHRoZSBudW1iZXIgaWYgbm9kZXMgYXJlIHRvbyBiaWcKcGxvdChnMiwgbGF5b3V0ID0gTCwgdmVydGV4LmxhYmVsPU5BKQpgYGAKKipCcmllZmx5IGV4cGxhaW4gZGVncmVlIGNlbnRyYWxpdHkgYW5kIHdoeSBub2RlcyBhcmUgbW9yZSBvciBsZXNzIGNlbnRyYWwgaW4gdGhlIG5ldHdvcmsuKioKRGVncmVlIGNlbnRyYWxpdHkgdGFrZXMgaW50byBjb25zaWRlcmF0aW9uIHRoZSBhbW91bnQgb2YgdGllcyBsZWFkaW5nIHRvIGEgbm9kZS4gSW4gb3RoZXIgd29yZHMsIHRoZSBub2RlIHdpdGggdGhlIG1vc3QgZWRnZXMgaW4gYW4gdW5kaXJlY3RlZCBuZXR3b3JrIGlzIHRoZSBtb3N0IGNlbnRyYWwgbm9kZS4gSW4gdGhpcyBjYXNlLCBpdCdzIFRydW1wIGFzIGhlIGhhcyB0aGUgbW9zdCBlZGdlcyBhbmQgbGFyZ2VzdCBzaXplIGluIHRoZSBkZWdyZWUgY2VudHJhbGl0eSBncmFwaC4gVGhlIGVycm9yIGhlcmUsIGlzIHRoYXQgaGlzIG5vZGUgaXMgbm90IG9yYW5nZS4gOikgQXMgZm9yIHRoZSBORkwgbm9kZXMsIHRoZXkgYWxsIGFyZSBpbnRlcmNvbm5lY3RlZCBjcmVhdGluZyBtYW55IGVkZ2VzIGJldHdlZW4gbm9kZXMgaW4gdGhhdCBzdWJncm91cDsgY29uc2VxdWVudGx5IHJhaXNpbmcgZWFjaCBub2RlJ3MgZGVncmVlIGNlbnRyYWxpdHkuIEFsbCB0aGUgTkZMIG5vZGUncyBkZWdyZWUgY2VudHJhbGl0eSBpcyBib29zdGVkIGR1ZSB0byB0aGUgZmFjdCB0aGV5IGFyZSBhbGwgaW50ZXJjb25uZWN0ZWQuIFRoZSBzbWFsbGVzdCBub2RlcyBvZiB0aGUgZ3JhcGggYXJlIHRoZSBwZW5kYW50cyBhcyB0aGV5IG9ubHkgaGF2ZSBvbmUgZWRnZS4KCiMjIFdlaWdodGVkIERlZ3JlZSBDZW50cmFsaXR5CmBgYHtyfQp3ZCA8LSBncmFwaC5zdHJlbmd0aChnX3ZhbHVlZCx3ZWlnaHRzID0gRShnX3ZhbHVlZCkkQ29PY2N1cnJlbmNlcykKc29ydCh3ZCxkZWNyZWFzaW5nPVRSVUUpWzE6NV0Kd2cyIDwtIGdfdmFsdWVkClYod2cyKSRzaXplIDwtIHdkKi4xICMgYWRqdXN0IHRoZSBudW1iZXIgaWYgbm9kZXMgYXJlIHRvbyBiaWcKcGxvdCh3ZzIsIGxheW91dCA9IEwsIGVkZ2Uud2lkdGg9c3FydChFKGdfdmFsdWVkKSRDb09jY3VycmVuY2VzKSkgI3Rha2luZyB0aGUgc3F1YXJlIHJvb3QgaXMgYSBnb29kIHdheSB0byBtYWtlIGEgbGFyZ2UgcmFuZ2Ugb2YgbnVtYmVycyB2aXNpYmxlIGluIGFuIGVkZ2UuIE90aGVyd2lzZSBlZGdlcyB0ZW5kIHRvIGNvdmVyIHVwIGFsbCB0aGUgb3RoZXIgZWRnZXMgYW5kIG9ic2N1cmUgdGhlIHJlbGF0aW9uc2hpcHMuCmBgYAoqKldoYXQgZG9lcyB0aGUgYWRkaXRpb24gb2Ygd2VpZ2h0ZWQgZGVncmVlIGFuZCBlZGdlIGluZm9ybWF0aW9uIHRlbGwgeW91IGFib3V0IHlvdXIgZ3JhcGg/KioKV2hhdCBhIGJlYXV0aWZ1bCBncmFwaC4gVGhlIHdlaWdodGVkIGVkZ2VzIGluZGljYXRlcyB0aGF0IHRoZXJlIHdhcyBhIGxhcmdlLCBvciBsYXJnZXN0LCB2b2x1bWUgb2YgYXJ0aWNsZXMgYWJvdXQgVHJ1bXAgYW5kIGhpcyBmdWVkIHdpdGggS2FlcGVybmljay4gSW4gY29udHJhc3QsIHRoZXJlIHdlcmUgb25seSBhIHNtYWxsIGFtb3VudCBvZiBhcnRpY2xlcyBwZXJ0YWluaW5nIHRvIFRydW1wIGFuZCBhYm91dCBoYWxmIG9mIGhpcyBzZW5hdG9ycy4gVGhlIG90aGVyIGhhbGYsIHRoZSBjbG9zZXN0IGluIHByb3hpbWl0eSwgaGFkIHF1aXRlIHN0cm9uZyB0aWVzLiBJZiBhbnl0aGluZyBJIHRoaW5rIHRoaXMgZGVtb25zdHJhdGVzIGEgcHJvYmxlbSB3aXRoIG91ciBzb2NpZXR5OyB0aGF0IGlzLCBhcnRpY2xlcyBvbiBUcnVtcCBiYWRnZXJpbmcgYSBwcm90ZXN0ZXIgZ2V0IG1vcmUgdmlld3MgdGhhbiBhcnRpY2xlcyBwZXJ0YWluaW5nIHRvIHNlbmF0b3JzLgoKIyMgQmV0d2Vlbm5lc3MgQ2VudHJhbGl0eQpgYGB7cn0KYiA8LSBiZXR3ZWVubmVzcyhnX3ZhbHVlZCxkaXJlY3RlZD1UUlVFKQpzb3J0KGIsZGVjcmVhc2luZz1UUlVFKVsxOjVdCmc0IDwtIGdfdmFsdWVkClYoZzQpJHNpemUgPC0gYioxLjIjY2FuIGFkanVzdCB0aGUgbnVtYmVyCnBsb3QoZzQsIGxheW91dCA9IEwsIHZlcnRleC5sYWJlbD1OQSkKYGBgCioqQnJpZWZseSBleHBsYWluIGJldHdlZW5uZXNzIGNlbnRyYWxpdHkgYW5kIHdoeSBub2RlcyBhcmUgbW9yZSBvciBsZXNzIGNlbnRyYWwgaW4gdGhlIG5ldHdvcmsuKioKQmV0d2Vlbm5lc3MgY2VudHJhbGl0eSBjb21wdXRlcyBhIHZhbHVlIGJhc2VkIG9uIHRoZSBudW1iZXIgb2YgdGltZXMgYSBub2RlIGFjdHMgYXMgYSBicmlkZ2Ugb24gdGhlIHNob3J0ZXN0IHBhdGggYmV0d2VlbiB0d28gbm9kZXMuIFRydW1wIHZlcnkgY2xlYXJseSBoYXMgdGhlIGhpZ2hlc3QgYmV0d2Vlbm5lc3MgY2VudHJhbGl0eSwgZm9sbG93ZWQgYnkgQ2Fzc2lkeS4gQ2Fzc2lkeSdzIHZhbHVlIGlzIHByb2JhYmx5IGJvbHN0ZXJlZCBieSB0aGUgZmFjdCB0aGF0IGhlIGhhcyBhIHBlbmRhbnQgdGhhdCBpcyBkZXBlbmRhbnQgb24gaGltLgojIyMgV2VpZ2h0ZWQgQmV0d2Vlbm5lc3MgQ2VudHJhbGl0eQpgYGB7cn0Kd2J0d24gPC0gYmV0d2Vlbm5lc3MoZ192YWx1ZWQsd2VpZ2h0cyA9IEUoZ192YWx1ZWQpJENvT2NjdXJyZW5jZXMpCnNvcnQod2J0d24sZGVjcmVhc2luZz1UUlVFKVsxOjVdCndCdHduRyA8LSBnX3ZhbHVlZApWKHdCdHduRykkc2l6ZSA8LSB3YnR3biouNSAjIGFkanVzdCB0aGUgbnVtYmVyIGlmIG5vZGVzIGFyZSB0b28gYmlnCnBsb3Qod0J0d25HLCBsYXlvdXQgPSBMLCBlZGdlLndpZHRoPXNxcnQoRShnX3ZhbHVlZCkkQ29PY2N1cnJlbmNlcykpICN0YWtpbmcgdGhlIHNxdWFyZSByb290IGlzIGEgZ29vZCB3YXkgdG8gbWFrZSBhIGxhcmdlIHJhbmdlIG9mIG51bWJlcnMgdmlzaWJsZSBpbiBhbiBlZGdlLgpgYGAKKipXaGF0IGRvZXMgdGhlIGFkZGl0aW9uIG9mIHdlaWdodGVkIGRlZ3JlZSBhbmQgZWRnZSBpbmZvcm1hdGlvbiB0ZWxsIHlvdSBhYm91dCB5b3VyIGdyYXBoPyoqClRydW1wIHZlcnkgY2xlYXJseSBoYXMgdGhlIGhpZ2hlc3QgYmV0d2Vlbm5lc3MgY2VudHJhbGl0eSwgZm9sbG93ZWQgYnkgU2VuLiBCaWxsIE5lbHNvbi4gSW50ZXJlc3RpbmdseSBlbm91Z2gsIHRoZSBUYW1wYSBCYXkgQnVjY3MgaGF2ZSBhIG1vZGVyYXRlbHkgaGlnaCBiZXR3ZWVubmVzcyBjZW50cmFsaXR5OyB0aGlzIGlzIHByb2JhYmx5IGJlY2F1c2UgdGhlcmUgYXJlIGEgc2xldyBvZiBvdGhlciBub2RlcyB0aGF0IGFyZSBvbiB0aGUgZmFydGhlc3Qgc2lkZSBhd2F5IGZyb20gVHJ1bXAsIGEgYnJva2VyIG5vZGUuIAoKIyMgQ2xvc2VuZXNzIENlbnRyYWxpdHkKYGBge3J9CmMgPC0gY2xvc2VuZXNzKGdfdmFsdWVkKQpzb3J0KGMsZGVjcmVhc2luZz1UUlVFKVsxOjVdCmc1IDwtIGdfdmFsdWVkClYoZzUpJHNpemUgPC0gYyo1MDAgICNjYW4gYWRqdXN0IHRoZSBudW1iZXIKcGxvdChnNSwgbGF5b3V0ID0gTCwgdmVydGV4LmxhYmVsPU5BKQpgYGAKKipCcmllZmx5IGV4cGxhaW4gY2xvc2VuZXNzIGNlbnRyYWxpdHkgYW5kIHdoeSBub2RlcyBhcmUgbW9yZSBvciBsZXNzIGNlbnRyYWwgaW4gdGhlIG5ldHdvcmsuKioKQ2xvc2VuZXNzIGNlbnRyYWxpdHkgaXMgdGhlIGF2ZXJhZ2UgbGVuZ3RoIG9mIHRoZSBzaG9ydGVzdCBwYXRoIGJldHdlZW4gdGhlIG5vZGUgYW5kIGV2ZXJ5IG5vZCBlaW4gdGhlIG5ldHdvcmsuIEFnYWluIFRydW1wIGlzIHRoZSBtb3N0IGNlbnRyYWwgbm9kZTsgaG93ZXZlciwgdGhpcyB0aW1lLCBub3QgYnkgbXVjaC4gSXQgc2VlbXMgdGhhdCBtb3N0IG5vZGVzIHNoYXJlIGFuIGF2ZXJhZ2UgY2xvc2VuZXNzIGNlbnRyYWxpdHkuCgojIyMgV2VpZ2h0ZWQgQ2xvc2VuZXNzIENlbnRyYWxpdHkKCmBgYHtyfQp3Q2xzbnNzIDwtIGNsb3NlbmVzcyhnX3ZhbHVlZCx3ZWlnaHRzID0gRShnX3ZhbHVlZCkkQ29PY2N1cnJlbmNlcykKc29ydCh3Q2xzbnNzLGRlY3JlYXNpbmc9VFJVRSlbMTo1XQp3Q2xzbnNzRyA8LSBnX3ZhbHVlZApWKHdDbHNuc3NHKSRzaXplIDwtIHdDbHNuc3MqMTAwMCAjIGFkanVzdCB0aGUgbnVtYmVyIGlmIG5vZGVzIGFyZSB0b28gYmlnCnBsb3Qod0Nsc25zc0csIGxheW91dCA9IEwsIHZlcnRleC5sYWJlbD1OQSwgZWRnZS53aWR0aD1zcXJ0KEUoZ192YWx1ZWQpJENvT2NjdXJyZW5jZXMpKSAjdGFraW5nIHRoZSBzcXVhcmUgcm9vdCBpcyBhIGdvb2Qgd2F5IHRvIG1ha2UgYSBsYXJnZSByYW5nZSBvZiBudW1iZXJzIHZpc2libGUgaW4gYW4gZWRnZS4KYGBgCioqV2hhdCBkb2VzIHRoZSBhZGRpdGlvbiBvZiB3ZWlnaHRlZCBkZWdyZWUgYW5kIGVkZ2UgaW5mb3JtYXRpb24gdGVsbCB5b3UgYWJvdXQgeW91ciBncmFwaD8qKgpJIGFjdHVhbGx5IGxvc2UgaW5mb3JtYXRpb24sIGFuZCBnYWluIGNvdW50ZXItaW50dWl0aXZlIGluZm9ybWF0aW9uLiBJIGxvc3QgYW55IG1lYW5pbmcgaW4gdGhlIG5vZGUgc2l6ZS4gSSBnYWluZWQgY29uZnVzaW5nIGluZm9ybWF0aW9uIGxpa2UgdGhlIHR3byBUcnVtcCBub2RlIHBlbmRhbnRzIGJlaW5nIGFsbW9zdCB0aGUgc2FtZSBzaXplIGFzIGV2ZXJ5IG5vZGUgaW4gdGhlIG5ldHdvcmsgd2hpbGUgaGF2aW5nIHZlcnkgbGl0dGxlIHdlaWdodCBvbiB0aGVpciBlZGdlcy4KCiMjIEVpZ2VudmVjdG9yIENlbnRyYWxpdHkKYGBge3J9CmVpZ2MgPC0gZWlnZW5fY2VudHJhbGl0eShnX3ZhbHVlZCxkaXJlY3RlZD1UUlVFKQpzb3J0KGVpZ2MkdmVjdG9yLGRlY3JlYXNpbmc9VFJVRSlbMTo1XQpnNiA8LSBnX3ZhbHVlZApWKGc2KSRzaXplIDwtIGVpZ2MkdmVjdG9yKjUwICNjYW4gYWRqdXN0IHRoZSBudW1iZXIKcGxvdChnNiwgbGF5b3V0ID0gTCwgdmVydGV4LmxhYmVsPU5BKQpgYGAKCioqQnJpZWZseSBleHBsYWluIGVpZ2VudmVjdG9yIGNlbnRyYWxpdHkgYW5kIHdoeSBub2RlcyBhcmUgbW9yZSBvciBsZXNzIGNlbnRyYWwgaW4gdGhlIG5ldHdvcmsuKioKVGhpcyBtZWFzdXJlIG9mIGNlbnRyYWxpdHkgY29tcHV0ZXMgc2NvcmVzIGJhc2VkIG9uIG90aGVyIHNjb3JlcyBpbiB0aGUgbmV0d29yay4gSW4gb3RoZXIgd29yZHMsIGlmIGEgbm9kZSBoYXMgYSBoaWdoIHNjb3JlLCB0aGVuIG5vZGVzIGRpcmVjdGx5IGNvbm5lY3RpbmcgdG8gaXQgd2lsbCBhbHNvIGhhdmUgaGlnaCBzY29yZXMuIFRoaXMgbWFrZXMgc2Vuc2UgbG9va2luZyBhdCB0aGUgdmlzdWFsaXphdGlvbiBhbmQga25vd2luZyB0aGUgd2VpZ2h0IG9mIHRoZSBlZGdlcyBmcm9tIHByZXZpb3VzIGdyYXBocy4gVGhlIFRydW1wIG5vZGUgaXMgdGhlIGhpZ2hlc3QgcmF0ZWQgYXMgaXQncyB0aGUgbW9zdCBpbXBvcnRhbnQgbm9kZSB0byB0aGUgbmV0d29yay4gVGhlIE5GTCBub2RlcyBhcmUgZGVlbWVkIGltcG9ydGFudCBiZWNhdXNlIGVhY2ggb25lIGhhcyBhIGRpcmVjdCBjb25uZWN0aW9uIHdpdGggVHJ1bXAsIHRoZW4gYW1wbGlmaWVkIGJ5IGhhdmluZyBjb25uZWN0aW9ucyBiZXR3ZWVuIGVhY2ggb3RoZXIgTkZMIG5vZGUuIFRoZSBORkwgbm9kZXMgYXJlIGRlZW1lZCBldmVuIG1vcmUgaW1wb3J0YW50IGR1ZSB0byB0aGUgdm9sdW1lIG9mIGFydGljbGVzIGluIHdoaWNoIFRydW1wJ3Mgc2VhcmNoIHRlcm0gY28tb2NjdXJzIHdpdGggdGhlIE5GTCBub2Rlcy4KCiMjIEFuYWx5c2lzCioqQ2hvb3NlIHRoZSB2aXN1YWxpemF0aW9uIHRoYXQgeW91IHRoaW5rIGlzIG1vc3QgaW50ZXJlc3RpbmcgYW5kIGJyaWVmbHkgZXhwbGFpbiB3aGF0IGl0IHRlbGxzIHlvdSBhYm91dCBhIGNlbnRyYWwgbm9kZSBpbiB5b3VyIG5ldHdvcmsuIERpc2N1c3MgdGhlIHR5cGUgb2YgY2VudHJhbGl0eSwgYW5kIHdoYXQgdGhhdCBub2Rl4oCZcyBjZW50cmFsaXR5IHNjb3JlIHRlbGxzIHlvdSBhYm91dCB0aGUgc2VhcmNoIGNvLW9jY3VycmVuY2UgbmV0d29yay4qKgpJIGZpbmQgdGhlIHVud2VpZ2h0ZWQgYmV0d2Vlbm5lc3MgY2VudHJhbGl0eSB0byBiZSB0aGUgbW9zdCBpbnRlcmVzdGluZyBhcywgdmlzdWFsbHksIGl0IGhhcyB0aGUgbW9zdCBzdHJpa2luZyBub2RlIHNpemUgZGlmZmVyZW5jZS4gSXQgaXMgdmVyeSBldmlkZW50IGZyb20gdGhhdCBncmFwaCB0aGF0IFRydW1wIGlzIHRoZSBtb3N0IGltcG9ydGFudCwgY2VudHJhbCBub2RlIGluIHRoZSBuZXR3b3JrLgoKKipCcmllZmx5IGRpc2N1c3MgYW4gaW50ZXJlc3RpbmcgZGlmZmVyZW5jZSBiZXR3ZWVuIHR5cGVzIG9mIGNlbnRyYWxpdHkgZm9yIHlvdXIgbmV0d29yay4qKgoKSSB0aGluayB0aGUgbW9zdCBpbnRlcmVzdGluZyBkaWZmZXJlbmNlIGlzIHRoYXQgaW4gc29tZSBjZW50cmFsaXR5IHZpc3VhbGl6YXRpb25zIG1hbnkgb2YgdGhlIG5vZGVzIGFyZSBlcXVhbGx5IGFzIGltcG9ydGFudCBhcyBUcnVtcC4gSSB0aGluayB0aGUgdmFsdWVzIGFyZSBnZXR0aW5nIGdhbWVkIGEgbGl0dGxlIGluIHRoZSB3YXkgdGhleSBhcmUgY2FsY3VsYXRlZCwgYnV0IGl0IGlzIGludGVyZXN0aW5nIG5vbmV0aGVsZXNzLgoKIyMgR2xvYmFsIE5ldHdvcmsgTWV0cmljcyB3aXRoIFIKCkNvbXB1dGUgdGhlIG5ldHdvcmsgY2VudHJhbGl6YXRpb24gc2NvcmVzIGZvciB5b3VyIG5ldHdvcmsgZm9yIGRlZ3JlZSwgYmV0d2Vlbm5lc3MsIGNsb3NlbmVzcywgYW5kIGVpZ2VudmVjdG9yIGNlbnRyYWxpdHkuCgpgYGB7cn0KIyBEZWdyZWUgY2VudHJhbGl6YXRpb24KY2VudHJhbGl6YXRpb24uZGVncmVlKGdfdmFsdWVkLG5vcm1hbGl6ZWQgPSBUUlVFKQoKIyBCZXR3ZWVubmVzcyBjZW50cmFsaXphdGlvbgpjZW50cmFsaXphdGlvbi5iZXR3ZWVubmVzcyhnX3ZhbHVlZCxub3JtYWxpemVkID0gVFJVRSkKCiMgQ2xvc2VuZXNzIGNlbnRyYWxpemF0aW9uIApjZW50cmFsaXphdGlvbi5jbG9zZW5lc3MoZ192YWx1ZWQsbm9ybWFsaXplZCA9IFRSVUUpCgojIEVpZ2VudmVjdG9yIGNlbnRyYWxpemF0aW9uIApjZW50cmFsaXphdGlvbi5ldmNlbnQoZ192YWx1ZWQsbm9ybWFsaXplZCA9IFRSVUUpCgpgYGAKKipSZWNvcmQgdGhlIGNlbnRyYWxpemF0aW9uIHNjb3JlIG9mIGVhY2ggY2VudHJhbGl0eSBtZWFzdXJlLioqCkRlZ3JlZTogMC41OTUyMzgxCkJldHdlZW5uZXNzOiAwLjcwNTY1MTUKQ2xvc2VuZXNzOiAwLjc3Nzk5NzEKRWlnZW52ZWN0b3I6IDAuNTkwNDM0OQoqKkJyaWVmbHkgZXhwbGFpbiB3aGF0IHRoZSBjZW50cmFsaXphdGlvbiBvZiBhIG5ldHdvcmsgaXMuKioKVGhlc2UgY2VudHJhbGl0eSB2YWx1ZXMgYXJlIG5ldHdvcmsgd2lkZS4gUHJldmlvdXMgY29tcHV0YXRpb25zIG9mIGNlbnRyYWxpdHkgbWV0cmljcyB3ZXJlIG5vZGUgbGV2ZWwsIHdoZXJlIGFzIHRoZXNlIHNjb3JlcyBhcmUgbmV0d29yayBsZXZlbC4KCioqQ29tcGFyZSB0aGUgY2VudHJhbGl6YXRpb24gc2NvcmVzIGFib3ZlIHdpdGggdGhlIGdyYXBocyB5b3UgY3JlYXRlZCB3aGVyZSB0aGUgbm9kZXMgYXJlIHNjYWxlZCBieSBjZW50cmFsaXR5LiBEZXNjcmliZSB0aGUgYXBwZWFyYW5jZSBvZiBtb3JlIGNlbnRyYWxpemVkIHYuIGxlc3MgY2VudHJhbGl6ZWQgbmV0d29ya3MuKioKSXQgd291bGQgYXBwZWFyIGFzIHRob3VnaCB0aGUgbG93ZXIgdGhlIG51bWJlciwgdGhlIG1vcmUgbmV0d29yayB3aWRlIHZhcmlhbmNlIGluIG5vZGUgY2VudHJhbGl0eSBtZXRyaWNzLiBDb25zZXF1ZW50bHksIHRoZSBtb3N0IGludGVyZXN0aW5nIGdyYXBocyBoYXZlIHRoZSBsYXJnZXN0IHZhcmlhbmNlIGluIG5vZGUgc2l6ZXMvbm9kZSBtZXRyaWNzLgoKIyMgUGFydCA1LiBQb3dlciBMYXdzICYgU21hbGwgV29ybGRzICgyMCkKCiMjIFBvd2VyIExhd3MKTmV0d29ya3Mgb2Z0ZW4gZGVtb25zdHJhdGUgcG93ZXIgbGF3IGRpc3RyaWJ1dGlvbnMuIFBsb3QgdGhlIGRlZ3JlZSBkaXN0cmlidXRpb24gb2YgdGhlIG5vZGVzIGluIHlvdXIgYmFzZSBncmFwaC4gCmBgYHtyfQojIENhbGN1bGF0ZSBkZWdyZWUgZGlzdHJpYnV0aW9uCmRlZyA8LSBkZWdyZWUoZ192YWx1ZWQsdj1WKGdfdmFsdWVkKSwgbW9kZT0iYWxsIikKZGVnCgojIERlZ3JlZSBkaXN0cmlidXRpb24gaXMgdGhlIGN1bXVsYXRpdmUgZnJlcXVlbmN5IG9mIG5vZGVzIHdpdGggYSBnaXZlbiBkZWdyZWUKZGVnX2Rpc3RyIDwtZGVncmVlLmRpc3RyaWJ1dGlvbihnX3ZhbHVlZCwgY3VtdWxhdGl2ZT1ULCBtb2RlPSJhbGwiKQpkZWdfZGlzdHIKcGxvdChkZWdfZGlzdHIsIHlsaW09YyguMDEsMTApLCBiZz0iYmxhY2siLHBjaD0yMSwgeGxhYj0iRGVncmVlIiwgeWxhYj0iQ3VtdWxhdGl2ZSBGcmVxdWVuY3kiKSAjWW91IG1heSBuZWVkIHRvIGFkanVzdCB0aGUgeWxpbSB0byBhIGxhcmdlciBvciBzbWFsbGVyIG51bWJlciB0byBtYWtlIHRoZSBncmFwaCBzaG93IG1vcmUgZGF0YS4KYGBgCgpUZXN0IHdoZXRoZXIgaXTigJlzIGFwcHJveGltYXRlbHkgYSBwb3dlciBsYXcsIGVzdGltYXRlIGxvZyBmIChrKSA9IGxvZyBhIOKIkiBjIGxvZyBrLiDigJxUaGlzIHNheXMgdGhhdCBpZiB3ZSBoYXZlIGEgcG93ZXItbGF3IHJlbGF0aW9uc2hpcCwgYW5kIHdlIHBsb3QgbG9nIGYgKGspIGFzIGEgZnVuY3Rpb24gb2YgbG9nIGssIHRoZW4gd2Ugc2hvdWxkIHNlZSBhIHN0cmFpZ2h0IGxpbmU6IOKIkmMgd2lsbCBiZSB0aGUgc2xvcGUsIGFuZCBsb2cgYSB3aWxsIGJlIHRoZSB5LWludGVyY2VwdC4gU3VjaCBhIOKAnGxvZy1sb2figJ0gcGxvdCB0aHVzIHByb3ZpZGVzIGEgcXVpY2sgd2F5IHRvIHNlZSBpZiBvbmXigJlzIGRhdGEgZXhoaWJpdHMgYW4gYXBwcm94aW1hdGUgcG93ZXItbGF3OiBpdCBpcyBlYXN5IHRvIHNlZSBpZiBvbmUgaGFzIGFuIGFwcHJveGltYXRlbHkgc3RyYWlnaHQgbGluZSwgYW5kIG9uZSBjYW4gcmVhZCBvZmYgdGhlIGV4cG9uZW50IGZyb20gdGhlIHNsb3BlLuKAnSAoRSZLLCBDaGFwdGVyIDE4LCBwLjU0NikuCgoKYGBge3J9CnBvd2VyIDwtIHBvd2VyLmxhdy5maXQoZGVnX2Rpc3RyKQpwb3dlcgpwbG90KGRlZ19kaXN0ciwgbG9nPSJ4eSIsIHlsaW09YyguMDEsMTApLCBiZz0iYmxhY2siLHBjaD0yMSwgeGxhYj0iRGVncmVlIiwgeWxhYj0iQ3VtdWxhdGl2ZSBGcmVxdWVuY3kiKQpgYGAKCioqRG9lcyB5b3VyIG5ldHdvcmsgZXhoaWJpdCBhIHBvd2VyIGxhdyBkaXN0cmlidXRpb24gb2YgZGVncmVlIGNlbnRyYWxpdHk/KioKClRoZXJlIGlzIG5vIGV2aWRlbmNlIG9mIGEgcG93ZXIgbGF3IHByZXNlbnQgaW4gdGhlIG5ldHdvcmsuIEEgcG93ZXIgbGF3IHdvdWxkIGJlIHJlcHJlc2VudGVkIGFzIGFuIHN0cmFpZ2h0IGxpbmUgd2l0aCBhIG5lZ2F0aXZlIHNsb3BlLgoKIyMgU21hbGwgV29ybGRzCgpOZXR3b3JrcyBvZnRlbiBkZW1vbnN0cmF0ZSBzbWFsbCB3b3JsZCBjaGFyYWN0ZXJpc3RpY3MuIENvbXB1dGUgdGhlIGF2ZXJhZ2UgY2x1c3RlcmluZyBjb2VmZmljaWVudCAoQUNDKSBhbmQgdGhlIGNoYXJhY3RlcmlzdGljIHBhdGggbGVuZ3RoIChDUEwpLgpgYGB7cn0KIyBBdmVyYWdlIGNsdXN0ZXJpbmcgY29lZmZpY2llbnQgKEFDQykKdHJhbnNpdGl2aXR5KGdfdmFsdWVkLCB0eXBlID0gYygiYXZlcmFnZSIpKQoKIyBDaGFyYWN0ZXJpc3RpYyBwYXRoIGxlbmd0aCAoQ1BMKQphdmVyYWdlLnBhdGgubGVuZ3RoKGdfdmFsdWVkKQpgYGAKCkNvbXB1dGUgdGhlIEFDQyBhbmQgQ1BMIGZvciAxMDAgcmFuZG9tIG5ldHdvcmtzIHdpdGggdGhlIHNhbWUgbnVtYmVyIG9mIG5vZGVzIGFuZCB0aWVzIGFzIHlvdXIgdGVzdCBuZXR3b3JrLiAKCmBgYHtyfQphY2NTdW0gPC0gMApjcGxTdW0gPC0gMApmb3IgKGkgaW4gMToxMDApewogIGdycGggPC0gZXJkb3MucmVueWkuZ2FtZShudW1WZXJ0aWNlcywgbnVtRWRnZXMsIHR5cGUgPSAiZ25tIikKICBhY2NTdW0gPC0gYWNjU3VtICsgdHJhbnNpdGl2aXR5KGdycGgsIHR5cGUgPSBjKCJhdmVyYWdlIikpCiAgY3BsU3VtIDwtIGNwbFN1bSArIGF2ZXJhZ2UucGF0aC5sZW5ndGgoZ3JwaCkKfQphY2NTdW0vMTAwCmNwbFN1bS8xMDAKYGBgCgoKKipCYXNlZCBvbiB0aGVzZSBkYXRhLCB3b3VsZCB5b3UgY29uY2x1ZGUgdGhhdCB0aGUgb2JzZXJ2ZWQgbmV0d29yayBkZW1vbnN0cmF0ZXMgc21hbGwgd29ybGQgcHJvcGVydGllcz8gV2h5IG9yIHdoeSBub3Q/KioKWWVzLCBteSBuZXR3b3JrIGRvZXMgIGFwcGVhciB0byBkZW1vbnN0cmF0ZSBzbWFsbCB3b3JsZCBwcm9wZXJ0aWVzLiBUaGUgY2x1c3RlcmluZyBjb2VmZmljaWVudCBpcyBoaWdoZXIgdGhhbiB0aGF0IG9mIHRoZSByYW5kb20gQUNDIGluZGljYXRpbmcgY2x1c3RlcmluZyBhbmQgaW4gc3VwcG9ydCBvZiBzbWFsbCB3b3JsZC4gQW5kLCBhZGRpdGlvbmFsbHksIHRoZSBjaGFyYWN0ZXJpc3RpYyBwYXRoIGxlbmd0aCBpcyBoaWdoLCBhbG1vc3QgYXMgaGlnaCBhcyB0aGUgQ1BMIGluIHRoZSByYW5kb20sIHdoaWNoIHdvdWxkIGluZGljYXRlIHNtYWxsIHdvcmxkIHByb3BlcnRpZXMuIAojIyBXcmFwcGluZyB1cApUbyBjb21wbGV0ZSB0aGUgbGFiLCBtYWtlIHN1cmUgb3V0cHV0L3ByZXZpZXdzIGhhdmUgYmVlbiBnZW5lcmF0ZWQgZm9yIGVhY2ggYmxvY2sgb2YgY29kZS4gVGhlbiBjbGljayB0aGUgIlB1Ymxpc2giIGJ1dHRvbiBvbiB0aGUgdXBwZXIgcmlnaHQgaGFuZCBjb3JuZXIgb2YgdGhpcyBzY3JlZW4gYW5kIHNpZ24gdXAgZm9yIGFuIFJQdWJzIGFjY291bnQuIFN1Ym1pdCB0aGUgVVJMIG9mIHRoZSBwdWJsaXNoZWQsIGNvbXBsZXRlZCBsYWIgb24gQ2FudmFzLg==