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)
Warning message:
In scan(file = file, what = what, sep = sep, quote = quote, dec = dec, :
EOF within quoted string
library(httr)
library(data.table)
library(igraph)
library(dplyr)
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 included in the search query are famous celebrities and car brands. I choose 16 terms in total which are “Taylor Swift”, “Lady Gaga”, “Kesha”, “Tom Cruise”, “George Clooney”, “Jennifer Lawrence”, “Emma Stone”, “Dwayne Johnson”, “Ferrari”, “Lamborghini”, “Mercedes”, “BMW”, “Audi”, “Volov”, “Porsche”, “Lexus”.
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? #Celebrities always like fansy and luxury cars. I hope to find whether some car brands are mostly shown in article with celebrities, then I could guess celebrities are mostly favoriable with these brands.
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? #The terms I choose are most famous celebrities and luxury brands I found in Google. Celebrities and luxury car brands shall have certain number of records on NYT. Also, celebrities tend to choose luxury brands.
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? #For individual node: I hope to see which car brand is mostly connected by celebrities. #For sub-grouping of nodes: I hope to see if some celebrities are connected, they might be good friends. #For overall network: I hope to see the density of network.
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] "Taylor-Swift"
[1] 353
[1] "Lady-Gaga"
[1] 335
[1] "Kesha"
[1] 50
[1] "Tom-Cruise"
[1] 156
[1] "George-Clooney"
[1] 160
[1] "Jennifer-Lawrence"
[1] 224
[1] "Emma-Stone"
[1] 190
[1] "Dwayne-Johnson"
[1] 128
[1] "Ferrari"
[1] 388
[1] "Lamborghini"
[1] 74
[1] "Mercedes"
[1] 853
[1] "BMW"
[1] 521
[1] "Audi"
[1] 335
[1] "Volvo"
[1] 229
[1] "Porsche"
[1] 301
[1] "Lexus"
[1] 116
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.
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)
package <U+393C><U+3E31>bindrcpp<U+393C><U+3E32> was built under R version 3.4.2
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))
[1] "Taylor-Swift Lady-Gaga"
[1] 38
[1] "Taylor-Swift Kesha"
[1] 16
[1] "Taylor-Swift Tom-Cruise"
[1] 2
[1] "Taylor-Swift George-Clooney"
[1] 2
[1] "Taylor-Swift Jennifer-Lawrence"
[1] 5
[1] "Taylor-Swift Emma-Stone"
[1] 1
[1] "Taylor-Swift Dwayne-Johnson"
[1] 2
[1] "Taylor-Swift Ferrari"
[1] 1
[1] "Taylor-Swift Lamborghini"
[1] 0
[1] "Taylor-Swift Mercedes"
[1] 3
[1] "Taylor-Swift BMW"
[1] 0
[1] "Taylor-Swift Audi"
[1] 0
[1] "Taylor-Swift Volvo"
[1] 1
[1] "Taylor-Swift Porsche"
[1] 0
[1] "Taylor-Swift Lexus"
[1] 0
[1] "Lady-Gaga Kesha"
[1] 8
[1] "Lady-Gaga Tom-Cruise"
[1] 3
[1] "Lady-Gaga George-Clooney"
[1] 1
[1] "Lady-Gaga Jennifer-Lawrence"
[1] 10
[1] "Lady-Gaga Emma-Stone"
[1] 1
[1] "Lady-Gaga Dwayne-Johnson"
[1] 1
[1] "Lady-Gaga Ferrari"
[1] 1
[1] "Lady-Gaga Lamborghini"
[1] 1
[1] "Lady-Gaga Mercedes"
[1] 1
[1] "Lady-Gaga BMW"
[1] 0
[1] "Lady-Gaga Audi"
[1] 1
[1] "Lady-Gaga Volvo"
[1] 0
[1] "Lady-Gaga Porsche"
[1] 0
[1] "Lady-Gaga Lexus"
[1] 0
[1] "Kesha Tom-Cruise"
[1] 0
[1] "Kesha George-Clooney"
[1] 0
[1] "Kesha Jennifer-Lawrence"
[1] 0
[1] "Kesha Emma-Stone"
[1] 0
[1] "Kesha Dwayne-Johnson"
[1] 0
[1] "Kesha Ferrari"
[1] 0
[1] "Kesha Lamborghini"
[1] 0
[1] "Kesha Mercedes"
[1] 1
[1] "Kesha BMW"
[1] 0
[1] "Kesha Audi"
[1] 0
[1] "Kesha Volvo"
[1] 0
[1] "Kesha Porsche"
[1] 0
[1] "Kesha Lexus"
[1] 0
[1] "Tom-Cruise George-Clooney"
[1] 8
[1] "Tom-Cruise Jennifer-Lawrence"
[1] 5
[1] "Tom-Cruise Emma-Stone"
[1] 4
[1] "Tom-Cruise Dwayne-Johnson"
[1] 6
[1] "Tom-Cruise Ferrari"
[1] 0
[1] "Tom-Cruise Lamborghini"
[1] 0
[1] "Tom-Cruise Mercedes"
[1] 2
[1] "Tom-Cruise BMW"
[1] 0
[1] "Tom-Cruise Audi"
[1] 0
[1] "Tom-Cruise Volvo"
[1] 1
[1] "Tom-Cruise Porsche"
[1] 0
[1] "Tom-Cruise Lexus"
[1] 0
[1] "George-Clooney Jennifer-Lawrence"
[1] 14
[1] "George-Clooney Emma-Stone"
[1] 2
[1] "George-Clooney Dwayne-Johnson"
[1] 6
[1] "George-Clooney Ferrari"
[1] 0
[1] "George-Clooney Lamborghini"
[1] 0
[1] "George-Clooney Mercedes"
[1] 2
[1] "George-Clooney BMW"
[1] 0
[1] "George-Clooney Audi"
[1] 0
[1] "George-Clooney Volvo"
[1] 0
[1] "George-Clooney Porsche"
[1] 1
[1] "George-Clooney Lexus"
[1] 1
[1] "Jennifer-Lawrence Emma-Stone"
[1] 12
[1] "Jennifer-Lawrence Dwayne-Johnson"
[1] 7
[1] "Jennifer-Lawrence Ferrari"
[1] 0
[1] "Jennifer-Lawrence Lamborghini"
[1] 0
[1] "Jennifer-Lawrence Mercedes"
[1] 1
[1] "Jennifer-Lawrence BMW"
[1] 0
[1] "Jennifer-Lawrence Audi"
[1] 1
[1] "Jennifer-Lawrence Volvo"
[1] 2
[1] "Jennifer-Lawrence Porsche"
[1] 1
[1] "Jennifer-Lawrence Lexus"
[1] 0
[1] "Emma-Stone Dwayne-Johnson"
[1] 4
[1] "Emma-Stone Ferrari"
[1] 0
[1] "Emma-Stone Lamborghini"
[1] 0
[1] "Emma-Stone Mercedes"
[1] 0
[1] "Emma-Stone BMW"
[1] 0
[1] "Emma-Stone Audi"
[1] 0
[1] "Emma-Stone Volvo"
[1] 1
[1] "Emma-Stone Porsche"
[1] 0
[1] "Emma-Stone Lexus"
[1] 0
[1] "Dwayne-Johnson Ferrari"
[1] 0
[1] "Dwayne-Johnson Lamborghini"
[1] 0
[1] "Dwayne-Johnson Mercedes"
[1] 1
[1] "Dwayne-Johnson BMW"
[1] 0
[1] "Dwayne-Johnson Audi"
[1] 0
[1] "Dwayne-Johnson Volvo"
[1] 2
[1] "Dwayne-Johnson Porsche"
[1] 0
[1] "Dwayne-Johnson Lexus"
[1] 0
[1] "Ferrari Lamborghini"
[1] 19
[1] "Ferrari Mercedes"
[1] 182
[1] "Ferrari BMW"
[1] 16
[1] "Ferrari Audi"
[1] 14
[1] "Ferrari Volvo"
[1] 4
[1] "Ferrari Porsche"
[1] 33
[1] "Ferrari Lexus"
[1] 6
[1] "Lamborghini Mercedes"
[1] 15
[1] "Lamborghini BMW"
[1] 13
[1] "Lamborghini Audi"
[1] 17
[1] "Lamborghini Volvo"
[1] 2
[1] "Lamborghini Porsche"
[1] 22
[1] "Lamborghini Lexus"
[1] 4
[1] "Mercedes BMW"
[1] 134
[1] "Mercedes Audi"
[1] 81
[1] "Mercedes Volvo"
[1] 40
[1] "Mercedes Porsche"
[1] 44
[1] "Mercedes Lexus"
[1] 36
[1] "BMW Audi"
[1] 106
[1] "BMW Volvo"
[1] 50
[1] "BMW Porsche"
[1] 47
[1] "BMW Lexus"
[1] 40
[1] "Audi Volvo"
[1] 38
[1] "Audi Porsche"
[1] 94
[1] "Audi Lexus"
[1] 32
[1] "Volvo Porsche"
[1] 7
[1] "Volvo Lexus"
[1] 16
[1] "Porsche Lexus"
[1] 10
#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)
Analysis
Is the graph directed or undirected? #The graph is undirected. How many nodes and links does your network have?
numVertices <- vcount(g_valued)
numVertices
[1] 16
numEdges <- ecount(g_valued)
numEdges
[1] 71
What is the number of possible links in your network?
maxEdges <- numVertices*(numVertices-1)/2
maxEdges
[1] 120
What is the density of your network?
graphDensity <- numEdges/maxEdges # manual calculation
graphDensity
[1] 0.5916667
graphDensity1 <- graph.density(g_valued) # using the graph.density function from igraph
graphDensity1
[1] 0.5916667
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). #If I choose different terms like unknown singers, it will be mentioned less frequently in NYT, thus there might be less edges, the results would be less interesting. #For current search terms are related to one anther, but the weight of edge varies. #The limitation of one word would significantly reduce the accuracy of network. For example, if âTom Cruiseâ was limited as âCruiseâ, then even people not “Tom Cruise” would also be counted which is messed up with correct counts.
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]
Mercedes Volvo Lady-Gaga Taylor-Swift Jennifer-Lawrence
14 12 11 10 10
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 indicates number of nodes it has connection to.Most of nodes has high centrality in this network, some nodes are less central such as Kesha, as Kesha was not as popular as other celebrities, thus it has fewer connections.
Weighted Degree Centrality
wd <- graph.strength(g_valued,weights = E(g_valued)$CoOccurrences)
sort(wd,decreasing=TRUE)[1:5]
Mercedes BMW Audi Ferrari Porsche
543 406 384 276 259
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 addition of weighted degree and edge show the difference of edge values. Some nodes with large number of cooccurance indicate large node value. Thus Mercedes, BMW and Audi become largest node in graph.
Betweenness Centrality
b <- betweenness(g_valued,directed=TRUE)
sort(b,decreasing=TRUE)[1:5]
Mercedes Volvo Lady-Gaga Taylor-Swift George-Clooney
13.886111 9.026190 7.609524 4.245635 3.159524
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. #Betweenness centrality indicates how many times geodestic distance pass a node. The nodes at edge typically has small betweenness centrality and nodes at center has higher betweenness centraliy as nodes at center shortens geodestic distance at two sides.
Weighted Betweenness Centrality
wbtwn <- betweenness(g_valued,weights = E(g_valued)$CoOccurrences)
sort(wbtwn,decreasing=TRUE)[1:5]
Lady-Gaga Mercedes George-Clooney Lamborghini Volvo
49.623810 20.638095 20.500000 14.000000 9.090476
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? While considering the weight of betweenness, Lady gaga is the winner and is double higher than Mercedes. Edge at car brand cluster are thicker than celebrity cluster as its value of cooccourance is higer than celebrity cluster.
Closeness Centrality
c <- closeness(g_valued)
sort(c,decreasing=TRUE)[1:5]
Mercedes Volvo Lady-Gaga Taylor-Swift Jennifer-Lawrence
0.06250000 0.05555556 0.05263158 0.05000000 0.05000000
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 the average length of geodesic paths beween one node to the rest of nodes. In this network, as most of nodes are directly connected, thus they all have high closeness centrality and value of closeness centrality is very close.
Weighted Closeness Centrality
wClsnss <- closeness(g_valued,weights = E(g_valued)$CoOccurrences)
sort(wClsnss,decreasing=TRUE)[1:5]
Lady-Gaga Mercedes George-Clooney Emma-Stone Dwayne-Johnson
0.02777778 0.02380952 0.02272727 0.02272727 0.02272727
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? #While considering the weight, Lady Gaga has highest closeness centrality.
Eigenvector Centrality
eigc <- eigen_centrality(g_valued,directed=TRUE)
sort(eigc$vector,decreasing=TRUE)[1:5]
Mercedes Volvo Lady-Gaga Jennifer-Lawrence Taylor-Swift
1.0000000 0.8851732 0.7860427 0.7835956 0.7414936
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 shows that a node’s centrality is a function of its neighvors centrality. If a node is sorrounded by nodes with high strength, this node will also have high strength. Nodes at center typically has higher eigenvector centrality than nodes at edge.
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. #The most interesting network is the graph with clusterings, this graph shows the central node might be Mercedes as it has most connections with other nodes.Mercedes has highest (weighted)degree centrality, betweenness, closeness and eigenvector centrality. #The weighted centrality considers the factor of co-occurrence.However, by considering this factor, Mercedes doesn’t have highest weighted betweenness and closeness centrality and ranked second.
Briefly discuss an interesting difference between types of centrality for your network. #For betweenness and closeness centrality, the highest value is always Mercedes. While considering the weights, Lady Gaga will be higher than Mercedes.
Global Network Metrics with R
Compute the network centralization scores for your network for degree, betweenness, closeness, and eigenvector centrality.
centralization.degree(g_valued,normalized = TRUE)
$res
[1] 10 11 3 8 9 10 7 8 9 8 14 7 9 12 9 8
$centralization
[1] 0.3416667
$theoretical_max
[1] 240
# Betweenness centralization
centralization.betweenness(g_valued,normalized = TRUE)
$res
[1] 4.2456349 7.6095238 0.0000000 0.3789683 3.1595238 2.8123016 0.2361111 0.3789683 1.9611111
[10] 0.7277778 13.8861111 0.0000000 1.5444444 9.0261905 1.9250000 1.1083333
$centralization
[1] 0.1099541
$theoretical_max
[1] 1575
# Closeness centralization
centralization.closeness(g_valued,normalized = TRUE)
$res
[1] 0.7500000 0.7894737 0.5555556 0.6818182 0.7142857 0.7500000 0.6521739 0.6818182 0.7142857 0.6818182
[11] 0.9375000 0.6521739 0.7142857 0.8333333 0.7142857 0.6818182
$centralization
[1] 0.4826945
$theoretical_max
[1] 7.241379
# Eigenvector centralization
centralization.evcent(g_valued,normalized = TRUE)
$vector
[1] 0.7414936 0.7860427 0.2689500 0.6475531 0.6903315 0.7835956 0.5513788 0.6475531 0.7078242 0.6365116
[11] 1.0000000 0.5609145 0.7118733 0.8851732 0.7026684 0.6273066
$value
[1] 9.397791
$options
$options$bmat
[1] "I"
$options$n
[1] 16
$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] 3
$options$nconv
[1] 1
$options$numop
[1] 16
$options$numopb
[1] 0
$options$numreo
[1] 14
$centralization
[1] 0.3607736
$theoretical_max
[1] 14
Record the centralization score of each centrality measure. #degree centralization: 0.3416667 #betweenness centralization: 0.1099541 #closeness centralization: 0.4826945 #eigenvector centralization: 0.3607736 Briefly explain what the centralization of a network is. #Centralization of network indicates the difference among nodes in terms of number of nodes they connect to.
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. #The centralization scores are not high, it is reasonable there are two big cliques and a small clique. To get a more centralized network, the one of formation is like star, one node has connection to many other nodes, while other nodes has low connectivity. A less centralized network is like every node has similar connectivity.
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.0000 1.0000 1.0000 1.0000 0.9375 0.9375 0.9375 0.9375 0.8125 0.5625 0.3125 0.1875 0.1250 0.0625
[15] 0.0625
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] 1.467411
$xmin
[1] 0.0625
$logLik
[1] -13.96778
$KS.stat
[1] 0.3322858
$KS.p
[1] 0.0584186
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? #Yes
Small Worlds
Networks often demonstrate small world characteristics. Compute the average clustering coefficient (ACC) and the characteristic path length (CPL).
transitivity(g_valued, type = c("average"))
[1] 0.7726208
# Characteristic path length (CPL)
average.path.length(g_valued)
[1] 1.408333
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.5925709
cplSum/100
[1] 1.409
Based on these data, would you conclude that the observed network demonstrates small world properties? Why or why not? #The observed network has small world properties, as it has high local clustering coefficient and small average path length to other nodes.
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.
LS0tDQp0aXRsZTogJ0Rlc2NyaXB0aXZlIEFuYWx5dGljIEV4ZXJjaXNlIDE6IFZpc3VhbGl6aW5nIGFuZCBJbnRlcnByZXRpbmcgTmV0d29ya3MnDQpvdXRwdXQ6DQogIGh0bWxfbm90ZWJvb2s6IGRlZmF1bHQNCiAgaHRtbF9kb2N1bWVudDogZGVmYXVsdA0KICBwZGZfZG9jdW1lbnQ6IGRlZmF1bHQNCiAgd29yZF9kb2N1bWVudDogZGVmYXVsdA0KLS0tDQoqKlNOQSBHcmFkIFNlbWluYXIsIEZhbGwgMjAxNyoqDQoqKkR1ZToqKiBPY3RvYmVyIDI0dGgsIDExOjU5IHBtDQoqKk5hbWUgb2YgU3R1ZGVudCoqOiANCg0KVGhlIHB1cnBvc2Ugb2YgdGhpcyBsYWIgaXMgdG8gZGV2ZWxvcCB5b3VyIGZhbWlsaWFyaXR5IGNvbmR1Y3RpbmcgZGVzY3JpcHRpdmUgbmV0d29yayBhbmFseXNpcyB1c2luZyB0aGUgc3RhdGlzdGljYWwgc29mdHdhcmUgcGFja2FnZSBSLiBUaGlzIGFzc2lnbm1lbnQgd2lsbCBtYWtlIHVzZSBvZiBhIGRhdGEgc2V0IHlvdSBjb2xsZWN0IGJ5IGRlZmluaW5nIGEgc2VhcmNoIHF1ZXJ5IChhIGNvbGxlY3Rpb24gb2YgeW91ciB1c2VyLWRlZmluZWQgc2VhcmNoIHRlcm1zKSBmcm9tIHRoZSAqW05ldyBZb3JrIFRpbWVzXSh3d3cubnl0aW1lcy5jb20pKidzIEFydGljbGUgU2VhcmNoIFtBcHBsaWNhdGlvbiBQcm9ncmFtbWluZyBJbnRlcmZhY2VdKGh0dHBzOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL0FwcGxpY2F0aW9uX3Byb2dyYW1taW5nX2ludGVyZmFjZSkuIE5ldHdvcmtzIGFyZSBnZW5lcmF0ZWQgZnJvbSB0aGUgY28tb2NjdXJyZW5jZXMgYmV0d2VlbiBzZWFyY2ggdGVybXMgaW5jbHVkZWQgaW4gdGhlIHNhbWUgc2VhcmNoIHF1ZXJ5LiBGb3IgZXhhbXBsZSwgYSBsaW5rIGV4aXN0cyBiZXR3ZWVuIOKAnGFwcGxl4oCdIGFuZCDigJxvcmFuZ2XigJ0gaWYgdGhlcmUgYXJlIGFydGljbGVzIGluIHRoZSAqTmV3IFlvcmsgVGltZXMqIHRoYXQgY29udGFpbmVkIHRoZXNlIHR3byB0ZXJtcy4gIFlvdSB3aWxsIGJlIHZpc3VhbGl6aW5nIGFuZCBpbnRlcnByZXRpbmcgaW5kaXZpZHVhbCBhbmQgZ2xvYmFsIG5ldHdvcmsgcHJvcGVydGllcyBvZiB0aGlzIG5ldHdvcmsuDQoNCllvdSB3aWxsIGJlIGdyYWRlZCBwcmltYXJpbHkgb24gdGhlIGNvbXBsZXRlbmVzcyBhbmQgYWNjdXJhY3kgb2YgeW91ciByZXNwb25zZXMsIGJ1dCB0aGUgY2xhcml0eSBvZiB0aGUgcHJlcGFyZWQgcmVwb3J0IHdpbGwgYWxzbyBhZmZlY3QgeW91ciBncmFkZS4gIFdoaWxlIHN0dWRlbnRzIG1heSB3b3JrIHRvZ2V0aGVyIHRvIHBlcmZvcm0gdGhlIGFuYWx5c2lzLCBlYWNoIHN0dWRlbnQgbXVzdCBzdWJtaXQgaGlzIG9yIGhlciBvd24gcmVwb3J0IGFuZCBpcyByZXNwb25zaWJsZSBmb3Igd3JpdGluZyB0aGUgbmFycmF0aXZlIGluIHRoZSByZXBvcnQuIFlvdSBtdXN0IGFuc3dlciBhbGwgb2YgdGhlIGJvbGRlZCBxdWVzdGlvbnMuDQoNCiMgUGFydCAxOiBDb2xsZWN0IE5ldHdvcmsgRGF0YSAoMjAgcHRzKQ0KDQpGb3IgdGhpcyBsYWIsIHlvdSB3aWxsIHNlYXJjaCB0aGUgKk5ldyBZb3JrIFRpbWVzKiwgc2F2ZSB0aGF0IGRhdGEsIGNyZWF0ZSBuZXR3b3JrcyBmcm9tIHRoYXQgZGF0YSwgY29tcGFyZSB0aGUgZGlmZmVyZW5jZXMgYW1vbmcgbmV0d29ya3MsIGFuZCBkZW1vbnN0cmF0ZSB5b3VyIHByb2ZpY2llbmN5IHdpdGggYmFzaWMgbmV0d29yayBkZXNjcmlwdGl2ZSBzdGF0aXN0aWNzLg0KDQojIyBMb2FkaW5nIGFuZCBJbnN0YWxsaW5nIFBhY2thZ2VzLCBTZXQgV29ya2luZyBEaXJlY3RvcnkNCg0KV2hlbiB3b3JraW5nIHdpdGggUiwgeW91IHNob3VsZCBydW4gZWFjaCBsaW5lIG9mIGNvZGUgaW5kaXZpZHVhbGx5LCB1bmxlc3MgaXQgaXMgcGFydCBvZiBhIGZ1bmN0aW9uIGRlZmluaXRpb24sIHNvIHlvdSBjYW4gc2VlIHRoZSByZXN1bHRzLiBHZW5lcmFsbHkgc3BlYWtpbmcsIGFueSBsaW5lIG9mIGNvZGUgdGhhdCBpbmNsdWRlcyAneycgKHRoZSBiZWdpbm5pbmcgb2YgYSBmdW5jdGlvbiBkZWZpbml0aW9uKSBzaG91bGQgYmUgcnVuIHdpdGggYWxsIHRoZSBvdGhlciBsaW5lcyB1bnRpbCB5b3UgaGl0ICd9Jy4NCg0KYGBge3J9DQojIExpbmVzIHRoYXQgc3RhcnQgd2l0aCBhIGhhc2h0YWcvcG91bmQgc3ltYm9sLCBsaWtlIHRoaXMgb25lLCBhcmUgY29tbWVudCBsaW5lcy4gQ29tbWVudCBsaW5lcyBhcmUgaWdub3JlZCBieSBSIHdoZW4gaXQgaXMgaW50ZXJwcmV0aW5nIGNvZGUuDQojIFlvdSBvbmx5IG5lZWQgdG8gaW5zdGFsbCBwYWNrYWdlcyBvbmNlLiBSZW1vdmUgdGhlICMgaW4gZnJvbnQgb2YgZWFjaCBsaW5lIGFuZCB0aGVuIHJ1biBpdCB0byBpbnN0YWxsIGVhY2ggcGFja2FnZS4gQWZ0ZXIgc3VjY2Vzc2Z1bCBpbnN0YWxsYXRpb24sIGRlbGV0ZSB0aGUgbGluZSBvZiBjb2RlIG9yIHJlcGxhY2UgdGhlICNzIHNvIHRoZSBSIE5vdGVib29rIGRvZXNuJ3QgcnVuIGludG8gcHJvYmxlbXMuDQogaW5zdGFsbC5wYWNrYWdlcygnbWFncml0dHInLCByZXBvcyA9ICJodHRwczovL2NyYW4ucnN0dWRpby5jb20iKQ0KIGluc3RhbGwucGFja2FnZXMoJ2lncmFwaCcsIHJlcG9zID0gImh0dHBzOi8vY3Jhbi5yc3R1ZGlvLmNvbSIpDQppbnN0YWxsLnBhY2thZ2VzKCdodHRyJywgcmVwb3MgPSAiaHR0cHM6Ly9jcmFuLnJzdHVkaW8uY29tIikNCiBpbnN0YWxsLnBhY2thZ2VzKCdkYXRhLnRhYmxlJywgcmVwb3MgPSAiaHR0cHM6Ly9jcmFuLnJzdHVkaW8uY29tIikNCiBpbnN0YWxsLnBhY2thZ2VzKCdkcGx5cicsIHJlcG9zID0gImh0dHBzOi8vY3Jhbi5yc3R1ZGlvLmNvbSIpDQogaW5zdGFsbC5wYWNrYWdlcygneG1sMicsIHJlcG9zID0gImh0dHBzOi8vY3Jhbi5yc3R1ZGlvLmNvbSIpDQojIFlvdSBuZWVkIHRvIGxvYWQgcGFja2FnZXMgZXZlcnkgdGltZSB5b3UgcnVuIHRoZSBzY3JpcHQgb3IgcmVzdGFydCBSLg0KbGlicmFyeShtYWdyaXR0cikNCmxpYnJhcnkoaHR0cikNCmxpYnJhcnkoZGF0YS50YWJsZSkNCmxpYnJhcnkoaWdyYXBoKQ0KbGlicmFyeShkcGx5cikNCmxpYnJhcnkoeG1sMikNCiMgU2V0IHlvdXIgZGlyZWN0b3J5IGZvciB0aGUgcHJvamVjdA0KIyBZb3UgY2FuIGVpdGhlciBlbnRlciB5b3VyIGZpbGVuYW1lIHBhdGggd2l0aGluIHRoZSBwYXJlbnRoZXNlcyBiZWxvdyBhbmQgcmVtb3ZlIHRoZSAjIGNyZWF0aW5nIHRoZSBjb21tZW50LCBvciBzZWxlY3QgIlNlc3Npb24gPiBTZXQgV29ya2luZyBEaXJlY3RvcnkgLi4uIFNvdXJjZSBGaWxlIExvY2F0aW9uIiBpbiBSIFN0dWRpby4NCiMgc2V0d2QoIklucHV0IERpcmVjdG9yeSIpDQpgYGANCg0KIyMgQ2hvb3NlIGEgdG9waWMgZm9yIHlvdXIgc2VhcmNoIHRlcm1zDQoNCllvdSBjYW4gZGVjaWRlIHNlYXJjaCB0ZXJtcyBiYXNlZCBvbiBwZXJzb25hbCBpbnRlcmVzdHMsIHJlc2VhcmNoIGludGVyZXN0cywgb3IgcG9wdWxhciB0b3BpY2FsIGFyZWFzLCBhbW9uZyBvdGhlcnMuIFlvdSBoYXZlIGZsZXhpYmlsaXR5IGluIHNlbGVjdGluZyB5b3VyIHNlYXJjaCB0ZXJtIGxpc3QuIEZvciBleGFtcGxlLCB5b3UgY2FuIHNlYXJjaCBmb3Igc29tZSBjb21tZXJjaWFsIGJyYW5kcywgY2VsZWJyaXRpZXMsIGNvdW50cmllcywgdW5pdmVyc2l0aWVzLCBldGMuIEl0IHdpbGwgYmUgbW9zdCB1c2VmdWwgaWYgeW91IGNob29zZSBhIGNvbGxlY3Rpb24gb2Ygd29yZHMgdGhhdCBhcmUgbm90IGFsbCBleHRyZW1lbHkgY29tbW9uLiBUaGluayBhYm91dCBhIHNldCBvZiB3b3JkcyB0aGF0IG1pZ2h0IGhhdmUgaW50ZXJlc3RpbmcgY28tb2NjdXJyZW5jZXMgaW4gYXJ0aWNsZXMgd2l0aGluIHRoZSAqTmV3IFlvcmsgVGltZXMqIHdlYnNpdGUuIEZvciBleGFtcGxlLCB5b3UgbWlnaHQgYmUgaW50ZXJlc3RlZCBpbiB0aGUgbGFzdCBuYW1lcyBvZiBldmVyeSBTZW5hdG9yIGludm9sdmVkIGluIGEgY2VydGFpbiBwb2xpdGljYWwgZGViYXRlLCBmb290YmFsbCB0ZWFtcywgb3IgY2l0aWVzIGFuZCB0aGVpciBjby1vY2N1cnJlbmNlIGluIG5ld3MgYXJ0aWNsZXMuIEdlbmVyYWxseSBzcGVha2luZywgcHJvcGVyIG5vdW5zIGFyZSBiZXN0LCBidXQgeW91IG1pZ2h0IGhhdmUgY29tcGVsbGluZyByZWFzb25zIHRvIGNob29zZSB2ZXJicyBvciBhZGplY3RpdmVzLiBZb3UgbWlnaHQgd2FudCB0byB0aHJvdyBhIGNvdXBsZSBvZiB0ZXJtcyBpbiB0aGF0IGFyZW4ndCB0aGVtYXRpY2FsbHkgcmVsYXRlZCB0byBtYWtlIHN1cmUgeW91IGRvbid0IGdldCBhIHRvdGFsbHkgY29ubmVjdGVkIGNvbXBvbmVudC4gVGhlIG1vcmUgaW50ZXJlc3RpbmcgeW91ciBuZXR3b3JrIGlzIGluIHRlcm1zIG9mIGRpZmZlcmluZyBjZW50cmFsaXR5LCBkaXN0aW5jdCBjb21wb25lbnRzLCBldGMuLCB0aGUgZWFzaWVyIGl0IHdpbGwgYmUgdG8gZG8gdGhlIHdyaXR0ZW4gYW5hbHlzaXMuIEtlZXAgaW4gbWluZCB0aGF0IHRoZSBBcnRpY2xlIFNlYXJjaCBhcmNoaXZlIGlzIHZlcnkgbGFyZ2U7IG1hbnkgdGVybXMgY28tb2NjdXIuIFlvdSBtaWdodCB3YW50IHRvIGNvbnNpZGVyIHR3byB0ZW51b3VzbHkgcmVsYXRlZCBzdWJqZWN0cy4gVGhlIGV4YW1wbGUgZmlsZSB1c2VzIGZvdXIgZm9vdGJhbGwgdGVhbXMgYW5kIHRoZWlyIGhvbWUgc2VuYXRvcnMsIHBsdXMgYSBmZXcgdG9waWNhbCB0ZXJtcy4NCg0KIyMgQ3JlYXRlIHlvdXIgdGV4dCBpbnB1dA0KDQpDcmVhdGUgYSBwbGFpbiB0ZXh0IGZpbGUgd2l0aCAudHh0IGV4dGVuc2lvbiBpbiB0aGUgc2FtZSBkaXJlY3RvcnkgYXMgdGhlIFIgTWFya2Rvd24gTm90ZWJvb2sgdXNlZCBpbiB0aGlzIGFzc2lnbm1lbnQuIE1ha2UgYSBub3RlIG9mIHRoZSBmaWxlIG5hbWUgZm9yIHVzZSBpbiB0aGUgbmV4dCBjb2RlIHNuaXBwZXQuIFBsYWNlIG9uZSBzZWFyY2ggdGVybSBwZXIgbGluZSwgYW5kIHVzZSAxNeKAkzIwIHRlcm1zLiAgWW91J2xsIGFsc28gbGlrZWx5IHdhbnQgdG8gYWRkIHF1b3RhdGlvbiBtYXJrcyBhcm91bmQgeW91ciBzZWFyY2ggdGVybXMgdG8gZW5zdXJlIHRoYXQgeW91J3JlIG9ubHkgcmVjZWl2aW5nIHJlc3VsdHMgZm9yIHRoZSBjb21wbGV0ZSB0ZXJtLiBOT1RFOiBUaGUgZnVuY3Rpb24gd2lsbCBwcm9jZXNzIHlvdXIgdGVybXMgc28gdGhhdCB0aGV5IHdvcmsgaW4gdGhlIFVSTCByZXF1ZXN0LiBZb3UgZG8gbm90IG5lZWQgdG8gZW5jb2RlIG5vbi1hbHBoYWJldGljIGNoYXJhY3RlcnMuDQoNClRoZSB0ZXh0IGZpbGUgY2Fubm90IGluY2x1ZGUgYW55IGFkZGl0aW9uYWwgaW5mb3JtYXRpb24gb3IgY2hhcmFjdGVycyBhbmQgaXQgbXVzdCBiZSBhIC50eHQgZmlsZTsgV29yZCBvciBSVEYgZG9jdW1lbnRzIHdvbuKAmXQgd29yay4NCg0KIyMgQW5hbHlzaXMNCg0KKiphLglQcm92aWRlIGEgaGlnaCBsZXZlbCBvdmVydmlldyBvZiB0aGUgdGVybXMgeW91IGluY2x1ZGVkIGluIHRoZSBzZWFyY2ggcXVlcnkuKioNCiNUaGUgdGVybXMgaW5jbHVkZWQgaW4gdGhlIHNlYXJjaCBxdWVyeSBhcmUgZmFtb3VzIGNlbGVicml0aWVzIGFuZCBjYXIgYnJhbmRzLiBJIGNob29zZSAxNiB0ZXJtcyBpbiB0b3RhbCB3aGljaCBhcmUgIlRheWxvciBTd2lmdCIsICJMYWR5IEdhZ2EiLCAiS2VzaGEiLCAiVG9tIENydWlzZSIsICJHZW9yZ2UgQ2xvb25leSIsICJKZW5uaWZlciBMYXdyZW5jZSIsICJFbW1hIFN0b25lIiwgIkR3YXluZSBKb2huc29uIiwgIkZlcnJhcmkiLCAiTGFtYm9yZ2hpbmkiLCAiTWVyY2VkZXMiLCAiQk1XIiwgIkF1ZGkiLCAiVm9sb3YiLCAiUG9yc2NoZSIsICJMZXh1cyIuDQoNCioqYi4JV2h5IGRpZCB5b3UgY2hvb3NlIHRoaXMgY29sbGVjdGlvbiBvZiB0ZXJtcz8gIFdlcmUgdGhlcmUgc29tZSBzcGVjaWZpYyBvdmVyYXJjaGluZyBxdWVzdGlvbuKAlGludGVsbGVjdHVhbCBvciBleHRyYWN1cnJpY3VsYXIgY3VyaW9zaXR54oCUdGhhdCBtb3RpdmF0ZWQgdGhpcyBjb2xsZWN0aW9uIG9mIHRlcm1zPyoqDQojQ2VsZWJyaXRpZXMgYWx3YXlzIGxpa2UgZmFuc3kgYW5kIGx1eHVyeSBjYXJzLiBJIGhvcGUgdG8gZmluZCB3aGV0aGVyIHNvbWUgY2FyIGJyYW5kcyBhcmUgbW9zdGx5IHNob3duIGluIGFydGljbGUgd2l0aCBjZWxlYnJpdGllcywgdGhlbiBJIGNvdWxkIGd1ZXNzIGNlbGVicml0aWVzIGFyZSBtb3N0bHkgZmF2b3JpYWJsZSB3aXRoIHRoZXNlIGJyYW5kcy4gDQoNCioqYy4JSG93IGRpZCB5b3UgZGVjaWRlIHdoaWNoIHRlcm1zIHRvIHVzZSBpbiB0aGUgc2VhcmNoIHF1ZXJ5PyBXZXJlIHRoZXNlIHRlcm1zIHlvdSBpbnR1aXRpdmVseSBkZWVtZWQgaW1wb3J0YW50PyBXZXJlIHRoZXkgY3VsbGVkIGZyb20gYSBzcGVjaWZpYyBzb3VyY2Ugb3IgdGhlIHJlc3VsdCBvZiBzb21lIHNlcGFyYXRlIGFuYWx5c2lzIG9yIHNlYXJjaCBxdWVyeT8qKg0KI1RoZSB0ZXJtcyBJIGNob29zZSBhcmUgbW9zdCBmYW1vdXMgY2VsZWJyaXRpZXMgYW5kIGx1eHVyeSBicmFuZHMgSSBmb3VuZCBpbiBHb29nbGUuIENlbGVicml0aWVzIGFuZCBsdXh1cnkgY2FyIGJyYW5kcyBzaGFsbCBoYXZlIGNlcnRhaW4gbnVtYmVyIG9mIHJlY29yZHMgb24gTllULiBBbHNvLCBjZWxlYnJpdGllcyB0ZW5kIHRvIGNob29zZSBsdXh1cnkgYnJhbmRzLg0KDQoqKmQuCVdoYXQgYXJlIHRoZSBpbnNpZ2h0cyB5b3UgaG9wZSB0byBnbGVhbiBieSBsb29raW5nIGF0IHRoZSBuZXR3b3JrIG9mIHRlcm1zIGluIHRlcm1zIG9mIGluZGl2aWR1YWwgbm9kZSBtZXRyaWNzLCBzdWItZ3JvdXBpbmcgb2Ygbm9kZXMsIG92ZXJhbGwgZ2xvYmFsIG5ldHdvcmsgcHJvcGVydGllcz8qKg0KI0ZvciBpbmRpdmlkdWFsIG5vZGU6IEkgaG9wZSB0byBzZWUgd2hpY2ggY2FyIGJyYW5kIGlzIG1vc3RseSBjb25uZWN0ZWQgYnkgY2VsZWJyaXRpZXMuDQojRm9yIHN1Yi1ncm91cGluZyBvZiBub2RlczogSSBob3BlIHRvIHNlZSBpZiBzb21lIGNlbGVicml0aWVzIGFyZSBjb25uZWN0ZWQsIHRoZXkgbWlnaHQgYmUgZ29vZCBmcmllbmRzLg0KI0ZvciBvdmVyYWxsIG5ldHdvcms6IEkgaG9wZSB0byBzZWUgdGhlIGRlbnNpdHkgb2YgbmV0d29yay4NCg0KDQojIyBXb3JraW5nIHdpdGggdGhlIEFQSSB0byBDb2xsZWN0IFlvdXIgRGF0YQ0KVGhlICpOZXcgWW9yayBUaW1lcyogY29udHJvbHMgYWNjZXNzIHRvIGl0cyBBUEkgYnkgYXNzaWduaW5nIGVhY2ggdXNlciBhIGtleS4gRWFjaCBrZXkgaGFzIGEgbGltaXRlZCBudW1iZXIgb2YgY2FsbHMgdGhhdCBjYW4gYmUgbWFkZSB3aXRoaW4gYSBjZXJ0YWluIHRpbWUgcGVyaW9kLiBZb3UgY2FuIHJlYWQgbW9yZSBhYm91dCB0aGUgbGltaXRhdGlvbnMgb2YgdGhlIEFQSSBzeXN0ZW0gW2hlcmVdKGh0dHA6Ly9kZXZlbG9wZXIubnl0aW1lcy5jb20vYXJ0aWNsZV9zZWFyY2hfdjIuanNvbiMpLg0KDQpZb3Ugd2lsbCBuZWVkIHRvIGNyZWF0ZSB5b3VyIG93biBBUEkga2V5IHRvIGNvbXBsZXRlIHRoaXMgYXNzaWdubWVudC4gR28gdG8gdGhlICpOZXcgWW9yayBUaW1lcyogW2RldmVsb3BlcnMgcGFnZV0oaHR0cHM6Ly9kZXZlbG9wZXIubnl0aW1lcy5jb20vc2lnbnVwKSBhbmQgcmVxdWVzdCBhIGtleS4gWW91IHdpbGwgY29weSB0aGF0IGtleSAocmVjZWl2ZWQgdmlhIGVtYWlsKSBpbnRvIHRoZSBhcGkgdmFyaWFibGUgYmVsb3cuDQoNCmBgYHtyfQ0KIyBJbXBvcnQgeW91ciB3b3JkIGxpc3QNCm5hbWVfb2ZfZmlsZSA8LSAiTGlzdE9mV29yZHMudHh0IiAjIENyZWF0ZXMgYSB2YXJpYWJsZSBjYWxsZWQgbmFtZV9vZl9maWxlIHRoYXQgeW91IHNob3VsZCBwb3B1bGF0ZSB3aXRoIHRoZSBuYW1lIG9mIHlvdXIgdGV4dCBmaWxlIGJldHdlZW4gcXVvdGF0aW9uIG1hcmtzLg0Kd29yZF9saXN0IDwtIHJlYWQudGFibGUobmFtZV9vZl9maWxlLCBzZXAgPSAiXG4iLCBzdHJpbmdzQXNGYWN0b3JzID0gRikgJT4lIHVubGlzdCAlPiUgYXMudmVjdG9yICMgUmVhZHMgdGhlIGNvbnRlbnQgb2YgeW91ciBmaWxlIGludG8gYSB2YXJpYWJsZS4NCm51bV93b3JkcyA8LSBsZW5ndGgod29yZF9saXN0KSAjIENyZWF0ZXMgYSB2YXJpYWJsZSB3aXRoIHRoZSBudW1iZXIgb2Ygd29yZHMgaW4geW91ciBsaXN0Lg0KdXJsX2Jhc2UgPC0gImh0dHBzOi8vYXBpLm55dGltZXMuY29tL3N2Yy9zZWFyY2gvdjIvYXJ0aWNsZXNlYXJjaC5qc29uIg0KIyBXaGVuIHlvdSByZWNlaXZlIHRoZSBlbWFpbCB3aXRoIHlvdXIgQVBJIGtleSwgcGFzdGUgaXQgYmVsb3cgYmV0d2VlbiB0aGUgcXVvdGF0aW9uIG1hcmtzLg0KYXBpIDwtICczYjM5M2I1MmVmYzM0ZWRhYmM5MWE1YTMwYjdlYTQ1NCcNCmBgYA0KDQpPdXIgZmlyc3QgZnVuY3Rpb24gd2lsbCBnYXRoZXIgYWxsIG9mIHRoZSBzZWFyY2ggdGVybXMgYW5kIHRoZWlyIG51bWJlciBvZiBoaXRzIHRvIGJlIHBsYWNlZCBpbiBhIHRhYmxlLiBBbGwgbGluZXMgb2YgYSBmdW5jdGlvbiBzaG91bGQgYmUgcnVuIHRvZ2V0aGVyLg0KDQpgYGB7cn0NCkdldF9oaXRzX29uZSA8LSBmdW5jdGlvbihrZXl3b3JkMSkgew0KICBTeXMuc2xlZXAodGltZT0zKQ0KICB1cmwgPC0gcGFzdGUwKHVybF9iYXNlLCAiP2FwaS1rZXk9IiwgYXBpLCAiJnE9IiwgVVJMZW5jb2RlKGtleXdvcmQxKSwiJmJlZ2luX2RhdGU9IiwiMjAxNjAxMDEiKSAjIEJlZ2luIGRhdGUgaXMgaW4gZm9ybWF0IFlZWVlNTUREOyB5b3UgY2FuIGNoYW5nZSBpdCBpZiB5b3Ugd2FudCBvbmx5IG1vcmUgcmVjZW50IHJlc3VsdHMsIGZvciBleGFtcGxlLg0KICAjIFRoZSBudW1iZXIgb2YgcmVzdWx0cw0KICBwcmludChrZXl3b3JkMSkNCiAgaGl0cyA8LSBjb250ZW50KEdFVCh1cmwpKSRyZXNwb25zZSRtZXRhJGhpdHMgJT4lIGFzLm51bWVyaWMNCiAgcHJpbnQoaGl0cykNCiAgIyBQdXQgcmVzdWx0cyBpbiB0YWJsZQ0KICBjKFNlYXJjaFRlcm09a2V5d29yZDEsUmVzdWx0c1RvdGFsPWhpdHMpDQp9DQpgYGANCg0KTm93IHdlIHdpbGwgaW52b2tlIG91ciBmdW5jdGlvbiB0byBwdXQgaW5mb3JtYXRpb24gZnJvbSB0aGUgQVBJIGludG8gb3VyIGdsb2JhbCBlbnZpcm9ubWVudC4NCg0KYGBge3J9DQojQ3JlYXRlIGEgdGFibGUgb2YgeW91ciB3b3JkcyBhbmQgdGhlaXIgbnVtYmVyIG9mIHJlc3VsdHMuDQp0b3RhbF90YWJsZSA8LSB0KHNhcHBseSh3b3JkX2xpc3QsR2V0X2hpdHNfb25lKSkNCnRvdGFsX3RhYmxlIDwtIGFzLmRhdGEuZnJhbWUodG90YWxfdGFibGUpDQp0b3RhbF90YWJsZSRSZXN1bHRzVG90YWwgPC0gYXMubnVtZXJpYyhhcy5jaGFyYWN0ZXIodG90YWxfdGFibGUkUmVzdWx0c1RvdGFsKSkNCmBgYA0KSWYgeW91IGdldCB6ZXJvIGhpdHMgZm9yIGFueSBvZiB0aGVzZSB0ZXJtcywgeW91IHNob3VsZCBzdWJzdGl0dXRlIHRoYXQgdGVybSBmb3Igc29tZXRoaWduIGVsc2UgYW5kIHJlcnVuIHRoZSBsYWIgdXAgdG8gdGhpcyBwb2ludC4NCk5leHQsIHdlIHdpbGwgZGVmaW5lIHRoZSBmdW5jdGlvbiB0aGF0IHdpbGwgY29sbGVjdCB0aGUgYXJ0aWNsZSBjby1vY2N1cmVuY2VzIG5ldHdvcmsuDQpgYGB7cn0NCkdldF9oaXRzX3R3byA8LSBmdW5jdGlvbihyb3dfaW5wdXQpIHsNCiAga2V5d29yZDEgPC0gcm93X2lucHV0WzFdDQogIGtleXdvcmQyIDwtIHJvd19pbnB1dFsyXQ0KICB1cmwgPC0gcGFzdGUwKHVybF9iYXNlLCAiP2FwaS1rZXk9IiwgYXBpLCAiJnE9IiwgVVJMZW5jb2RlKGtleXdvcmQxKSwiKyIsIFVSTGVuY29kZShrZXl3b3JkMiksIiZiZWdpbl9kYXRlPSIsIjIwMTYwMTAxIikgI21hdGNoIHcvIEJlZ2luIERhdGUgaW4gR2V0X2hpdHNfb25lLg0KICAjIFRoZSBudW1iZXIgb2YgcmVzdWx0cw0KICBwcmludChwYXN0ZTAoa2V5d29yZDEsIiAiLGtleXdvcmQyKSkgDQogIGhpdHMgPC0gY29udGVudChHRVQodXJsKSkkcmVzcG9uc2UkbWV0YSRoaXRzICU+JSBhcy5udW1lcmljDQogIHByaW50KGhpdHMpDQogIFN5cy5zbGVlcCh0aW1lPTMpDQogICMgUHV0IHJlc3VsdHMgaW4gdGFibGUNCiAgYyhTZWFyY2hUZXJtMT1rZXl3b3JkMSxTZWFyY2hUZXJtMj1rZXl3b3JkMixDb09jY3VycmVuY2VzPWhpdHMpDQp9IA0KYGBgDQoNCkluIHRoaXMgbmV4dCBzdGVwLCB3ZSB3aWxsIGNhbGwgdGhlIEFQSSBhbmQgY29sbGVjdCB0aGUgY28tb2NjdXJyZW5jZSBuZXR3b3JrLiBUaGlzIG1heSB0YWtlIHNvbWUgdGltZS4gSWYgeW91IHJlY2VpdmUgIm51bWVyaWMoMCkiIGluIGFueSBvZiB5b3VyIHJlc3Bvc25lcywgeW91J3ZlIGxpa2VseSBoaXQgeW91ciBBUEkga2V5IGxpbWl0IGFuZCB3aWxsIGVpdGhlciBuZWVkIHRvIHdhaXQgZm9yIHRoZSBjYWxscyB0byByZXNldCAoMjQgaG91cnMpIG9yIHJlcXVlc3QgYSBuZXcga2V5LiBJZiB5b3UgcmVjZWl2ZSB0aGUgZXJyb3IgbWVzc2FnZSAiJCBvcGVyYXRvciBpcyBpbnZhbGlkIGZvciBhdG9taWMgdmVjdG9ycywiIHlvdSBoYXZlIGFsc28gaGl0IHRoZSBBUEkgY2FsbCBsaW1pdC4gVGhpcyBjb3VsZCBiZSBkdWUgdG8gcnVubmluZyB0aGUgc2NyaXB0IG11bHRpcGxlIHRpbWVzLCBvciBkdWUgdG8gaGl0dGluZyB0b28gbWFueSByZXN1bHRzIGJhc2VkIG9uIHZlcnkgY29tbW9uIHNlYXJjaCB0ZXJtcy4gUmVxdWVzdCBhIG5ldyBBUEksIHNob3J0ZW4geW91ciB3b3JkIGxpc3QsIGFuZCB0cnkgYWdhaW4uIERvbid0IGZvcmdldCB5b3UgbmVlZCB0byByZWxvYWQgeW91ciB3b3JkIGxpc3QgZnJvbSB0aGUgZmlyc3QgcGFydCBvZiB0aGUgTGFiIGluIG9yZGVyIHRvIGdldCBhIGRpZmZlcmVudCBzZXQgb2YgcmVzdWx0cyEgWW91IG11c3QgYWxzbyByZXJ1biB0aGUgZnVuY3Rpb25zIHRvIHJlYXNzaWduIHRoZSBBUEkgdmFsdWUuIElmIG5vbmUgb2YgeW91ciByZXN1bHRzIGNvbWUgYmFjayBhcyAiMCwiIHlvdSBtaWdodCB3YW50IHRvIHJlZG8geW91ciBzZWFyY2ggd2l0aCB0aGUgYXBwcm9wcmlhdGUgd29yZHMuDQoNCmBgYHtyfQ0KIyBDb252ZXJ0IHRoZSBwYWlycyBsaXN0IGludG8gYSB0YWJsZQ0KcGFpcnNfbGlzdCA8LSBleHBhbmQuZ3JpZCh3b3JkX2xpc3Qsd29yZF9saXN0KSAlPiUgZmlsdGVyKFZhcjEgIT0gVmFyMikNCnBhaXJzX2xpc3QgPC0gdChjb21ibih3b3JkX2xpc3QsMikpDQojQ3JlYXRlIGEgbmV0d29yayB0YWJsZSwgcnVuIHRoZSBHZXRfaGl0c190d28gZnVuY3Rpb24gdXNpbmcgdGhlIHBhaXJzIGxpc3RzDQpuZXR3b3JrX3RhYmxlIDwtIHQoYXBwbHkocGFpcnNfbGlzdCwxLEdldF9oaXRzX3R3bykpDQojQ29udmVydCB0aGUgbmV0d29yayB0YWJsZSBpbnRvIGEgZGF0YWZyYW1lDQpuZXR3b3JrX3RhYmxlIDwtIGFzLmRhdGEuZnJhbWUobmV0d29ya190YWJsZSkNCiMgUmVhZCBlYWNoIHRoZSBjb250ZW50IG9mIGVhY2ggaXRlbSB3aXRoaW4gdGhlICRDb09jY3VycmVlbmNlcyBmYWN0b3IgYXMgY2hhcmFjdGVycywgDQojIHRoZW4gZm9yY2UgdGhvc2UgY2hhcmFjdGVycyBpbnRvIHRoZSAibnVtZXJpYyIgb3IgImRvdWJsZSIgdHlwZS4NCm5ldHdvcmtfdGFibGUkQ29PY2N1cnJlbmNlcyA8LSBhcy5udW1lcmljKGFzLmNoYXJhY3RlcihuZXR3b3JrX3RhYmxlJENvT2NjdXJyZW5jZXMpKQ0KIyBDb252ZXJ0IGRhdGEgdG8gZGF0YS50YWJsZSB0eXBlLg0KdG90YWxfdGFibGUgPC0gYXMuZGF0YS50YWJsZSh0b3RhbF90YWJsZSkNCm5ldHdvcmtfdGFibGUgPC0gYXMuZGF0YS50YWJsZShuZXR3b3JrX3RhYmxlKQ0KDQojIFJlbW92ZSB6ZXJvIGVkZ2VzIGZyb20geW91ciBuZXR3b3JrDQpuZXR3b3JrX3RhYmxlIDwtIG5ldHdvcmtfdGFibGVbIUNvT2NjdXJyZW5jZXM9PTBdIA0KDQojIENyZWF0ZSBhIGdyYXBoIG9iamVjdCB3aXRoIHlvdXIgZGF0YQ0KZ192YWx1ZWQgPC0gZ3JhcGhfZnJvbV9kYXRhX2ZyYW1lKGQgPSBuZXR3b3JrX3RhYmxlWywxOjMsd2l0aD1GQUxTRV0sZGlyZWN0ZWQgPSBGQUxTRSx2ZXJ0aWNlcyA9IHRvdGFsX3RhYmxlKQ0KDQojIElmIHlvdSdyZSBoYXZpbmcgdHJvdWJsZSB3aXRoIGRhdGEgY29sbGVjdGlvbiwgeW91IGNhbiBsb2FkIHRoZSAnTkZMIExhYiBSZXN1bHRzLlJEYXRhJyBmaWxlIG5vdyBieSBjbGlja2luZyB0aGUgb3BlbiBmb2xkZXIgaWNvbiBvbiB0aGUgIkVudmlyb25tZW50IiIgdGFiIGFuZCBjb250aW51ZSB0aGUgbGFiIGZyb20gaGVyZS4gWW91J2xsIG5lZWQgdG8gZmlndXJlIG91dCB3aGF0IHRoZSBzaWduaWZpY2FuY2Ugb2YgdGhlIHRlcm1zIGFyZSB5b3Vyc2VsZiwgaG93ZXZlci4NCiMgWW91IHNob3VsZCBzYXZlIHlvdXIgZGF0YSBhdCB0aGlzIHBvaW50IGJ5IGNsaWNraW5nIHRoZSBmbG9wcHkgZGlzayBpY29uIHVuZGVyIHRoZSAiRW52aXJvbm1lbnQiIHRhYi4NCmBgYA0KDQojIyBBbmFseXNpcw0KDQoqKklzIHRoZSBncmFwaCBkaXJlY3RlZCBvciB1bmRpcmVjdGVkPyoqIA0KI1RoZSBncmFwaCBpcyB1bmRpcmVjdGVkLg0KKipIb3cgbWFueSBub2RlcyBhbmQgbGlua3MgZG9lcyB5b3VyIG5ldHdvcmsgaGF2ZT8gKioNCmBgYHtyfQ0KbnVtVmVydGljZXMgPC0gdmNvdW50KGdfdmFsdWVkKQ0KbnVtVmVydGljZXMNCm51bUVkZ2VzIDwtIGVjb3VudChnX3ZhbHVlZCkNCm51bUVkZ2VzDQpgYGANCg0KKipXaGF0IGlzIHRoZSBudW1iZXIgb2YgcG9zc2libGUgbGlua3MgaW4geW91ciBuZXR3b3JrPyAqKg0KYGBge3J9DQptYXhFZGdlcyA8LSBudW1WZXJ0aWNlcyoobnVtVmVydGljZXMtMSkvMg0KbWF4RWRnZXMNCmBgYA0KDQoqKldoYXQgaXMgdGhlIGRlbnNpdHkgb2YgeW91ciBuZXR3b3JrPyoqIA0KYGBge3J9DQpncmFwaERlbnNpdHkgPC0gbnVtRWRnZXMvbWF4RWRnZXMgIyBtYW51YWwgY2FsY3VsYXRpb24NCmdyYXBoRGVuc2l0eQ0KZ3JhcGhEZW5zaXR5MSA8LSBncmFwaC5kZW5zaXR5KGdfdmFsdWVkKSAjIHVzaW5nIHRoZSBncmFwaC5kZW5zaXR5IGZ1bmN0aW9uIGZyb20gaWdyYXBoDQpncmFwaERlbnNpdHkxDQpgYGANCg0KKipCcmllZmx5IGRlc2NyaWJlIGhvdyB5b3VyIGNob2ljZSBvZiBkYXRhc2V0IG1heSBpbmZsdWVuY2UgeW91ciBmaW5kaW5ncy4qKiAgV2hhdCBkaWZmZXJlbmNlcyB3b3VsZCB5b3UgZXhwZWN0IGlmIHlvdSB1c2UgZGlmZmVyZW50IHNlYXJjaCB0ZXJtcz8gQXJlIHRoZSBjdXJyZW50IHNlYXJjaCB0ZXJtcyByZWxhdGVkIHRvIG9uZSBhbm90aGVyPyBJZiBzbywgaG93PyBEbyB5b3UgdGhpbmsgdGhlIGxpbWl0YXRpb24gdG8gb25lIHdvcmQgbWlnaHQgc2tldyB5b3VyIGFuc3dlcnM/IChpLmUuIGlmIHlvdeKAmXJlIGludGVyZXN0ZWQgaW4gSGlsbGFyeSBDbGludG9uLCBidXQgeW91IGluY2x1ZGUg4oCcQ2xpbnRvbuKAnSBhcyBhIHRlcm0sIHlvdSB3aWxsIGdldCBzdG9yaWVzIHRoYXQgbWVudGlvbiBDaGVsc2VhLCBCaWxsLCAmIGV2ZW4gUC1GdW5rIEFsbHN0YXIgR2VvcmdlIENsaW50b24pLg0KI0lmIEkgY2hvb3NlIGRpZmZlcmVudCB0ZXJtcyBsaWtlIHVua25vd24gc2luZ2VycywgaXQgd2lsbCBiZSBtZW50aW9uZWQgbGVzcyBmcmVxdWVudGx5IGluIE5ZVCwgdGh1cyB0aGVyZSBtaWdodCBiZSBsZXNzIGVkZ2VzLCB0aGUgcmVzdWx0cyB3b3VsZCBiZSBsZXNzIGludGVyZXN0aW5nLiANCiNGb3IgY3VycmVudCBzZWFyY2ggdGVybXMgYXJlIHJlbGF0ZWQgdG8gb25lIGFudGhlciwgYnV0IHRoZSB3ZWlnaHQgb2YgZWRnZSB2YXJpZXMuIA0KI1RoZSBsaW1pdGF0aW9uIG9mIG9uZSB3b3JkIHdvdWxkIHNpZ25pZmljYW50bHkgcmVkdWNlIHRoZSBhY2N1cmFjeSBvZiBuZXR3b3JrLiBGb3IgZXhhbXBsZSwgaWYg4oCcVG9tIENydWlzZeKAnSB3YXMgbGltaXRlZCBhcyDigJxDcnVpc2XigJ0sIHRoZW4gZXZlbiBwZW9wbGUgbm90ICJUb20gQ3J1aXNlIiB3b3VsZCBhbHNvIGJlIGNvdW50ZWQgd2hpY2ggaXMgbWVzc2VkIHVwIHdpdGggY29ycmVjdCBjb3VudHMuIA0KDQoNCiMgUGFydCAyOiBWaXN1YWxpemUgWW91ciBOZXR3b3JrICgyMCBwb2ludHMpDQoNCkxldCdzIHN0YXJ0IGJ5IHZpc3VhbGl6aW5nIHRoZSBuZXR3b3JrIHRoYXQgd2UndmUgY29sbGVjdGVkIGZyb20gdGhlICpOZXcgWW9yayBUaW1lcyogQXJ0aWNsZSBTZWFyY2ggQVBJLiBXZSdsbCBuZWVkIHRvIGNob29zZSBub2RlIGNvbG9ycyBhbmQgc2V0IGEgbGF5b3V0LiBZb3UgY2FuIGxlYXJuIG1vcmUgYWJvdXQgRnJ1Y2h0ZXJtYW4gUmVpbmdvbGQgbGF5b3V0IGFuZCBvdGhlciBsYXlvdXRzIFtoZXJlXShodHRwOi8vaWdyYXBoLm9yZy9yL2RvYy9sYXlvdXRfd2l0aF9mci5odG1sKS4NCg0KYGBge3J9DQojIyBMZWFybiBtb3JlIGFib3V0IHBsb3R0aW5nIHdpdGggaWdyYXBoDQo/PyBpZ3JhcGgucGxvdHRpbmcNCmNvbGJhciA9IHJhaW5ib3cobGVuZ3RoKHdvcmRfbGlzdCkpICMjIHdlIGFyZSBzZWxlY3RpbmcgZGlmZmVyZW50IGNvbG9ycyB0byBjb3JyZXNwb25kIHRvIGVhY2ggd29yZA0KVihnX3ZhbHVlZCkkY29sb3IgPSBjb2xiYXINCiMgU2V0IGxheW91dCBoZXJlIA0KTCA9IGxheW91dF93aXRoX2ZyKGdfdmFsdWVkKSAgIyBGcnVjaHRlcm1hbiBSZWluZ29sZA0KcGxvdChnX3ZhbHVlZCx2ZXJ0ZXguY29sb3I9VihnX3ZhbHVlZCkkY29sb3IsIGxheW91dCA9IEwsIHZlcnRleC5zaXplPTYpIA0KDQpgYGANCiMjIEFuYWx5c2lzDQoqKkluIGEgcGFyYWdyYXBoLCBkZXNjcmliZSB0aGUgbWFjcm8tbGV2ZWwgc3RydWN0dXJlIG9mIHlvdXIgZ3JhcGhzIGJhc2VkIG9uIHRoZSBGcnVjaHRlcm1hbiBSZWluZ29sZCB2aXN1YWxpemF0aW9uLioqDQpJcyBpdCBhIGdpYW50LCBjb25uZWN0ZWQgY29tcG9uZW50LCBhcmUgdGhlcmUgZGlzdGluY3Qgc3ViLWNvbXBvbmVudHMsIG9yIGFyZSB0aGVyZSBpc29sYXRlZCBjb21wb25lbnRzPyAgQ2FuIHlvdSByZWNvZ25pemUgY29tbW9uIGZlYXR1cmVzIG9mIHRoZSBzdWJjb21wb25lbnRzPyAgRG9lcyB0aGlzIHZpc3VhbGl6YXRpb24gZ2l2ZSB5b3UgYW55IGluc2lnaHQgaW50byB0aGUgY28tb2NjdXJyZW5jZSBwYXR0ZXJucyBvZiB0aGUgc2VhcmNoLXRlcm1zPyAgSWYgeWVzLCB3aGF0PyBJZiBub3QsIHdoeT8NCiNUaGUgbmV0d29yayBpcyBhIGdhaW50IGNvbm5lY3RlZCBjb21wb25lbnRzLCB0aGVyZSBpcyBubyBpc29sYXRlZCBjb21wb25lbnRzLiBBY2NvcmRpbmcgdG8gdmlzdWxpemF0aW9uLCB0aGUgdGVybSBoYXMgbW9zdCBjb25uZWN0aW9ucyB3aXRoIG90aGVyIHRlcm1zIGFyZSBwbGFjZWQgYXQgY2VudGVyIHBsYWNlIHN1Y2ggYXMgTWVyY2VkZXMsIHdoaWxlIHNvbWUgdGVybXMgaGFzIGxlYXN0IGNvbm5lY3Rpb25zIHdpdGggb3RoZXIgdGVybXMgYXJlIHBsYWNlZCBvdXRzaWRlIHN1Y2ggYXMgS2VzaGEuDQoNCk5vdyB3ZSdsbCBjcmVhdGUgYSBzZWNvbmQgdmlzdWFsaXphdGlvbiB1c2luZyBhIGRpZmZlcmVudCBsYXlvdXQuDQpgYGB7cn0NCiMjIFlvdSBjYW4gY2hhbmdlIHRoZSBsYXlvdXQgYnkgcGlja2luZyBvbmUgb2YgdGhlIG90aGVyIG9wdGlvbnMuIFVuY29tbWVudCBvbmUgb2YgdGhlIGxpbmVzIGJlbG93IGJ5IGVyYXNpbmcgdGhlICMgYW5kIHJ1bm5pbmcgdGhlIGxpbmUuIFRyeSB0byBmaW5kIGEgbGF5b3V0IHRoYXQgZ2l2ZXMgeW91IGRpZmZlcmVudCBpbmZvcm1hdGlvbiB0aGF0IEZydWNodGVybWFuIFJlaW5nb2xkLg0KDQogTCA9IGxheW91dF93aXRoX2RoKGdfdmFsdWVkKSAjIyBEYXZpZHNvbiBhbmQgSGFyZWwNCg0KI0wgPSBsYXlvdXRfd2l0aF9kcmwoZ192YWx1ZWQpICMjIEZvcmNlLWRpcmVjdGVkDQoNCiMgTCA9IGxheW91dF93aXRoX2trKGdfdmFsdWVkKSAjIyBTcHJpbmcNCnBsb3QoZ192YWx1ZWQsdmVydGV4LmNvbG9yPVYoZ192YWx1ZWQpJGNvbG9yLCBsYXlvdXQgPSBMLCB2ZXJ0ZXguc2l6ZT02KSANCmBgYA0KIyMgQW5hbHlzaXMNCioqSW4gYSBwYXJhZ3JhcGgsIGNvbXBhcmUgYW5kIGNvbnRyYXN0IHRoZSBpbmZvcm1hdGlvbiBnaXZlbiB0byB5b3UgYnkgdGhlIHR3byBkaWZmZXJlbnQgbGF5b3V0cy4qKg0KI0JvdGggbGF5b3V0cyBoYXZlIGNsZWFyIHNlcGVyYXRpb24gYmV0d2VlbiBjYXIgYnJhbmRzIGFuZCBjZWxlYnJpdGllcy4gDQojQWNjb3JkaW5nIHRvIGdyYXBoIHdpdGggRnJ1Y2h0ZXJtYW4gUmVpbmdvbGQgbGF5b3V0LCBpdCBzaG93cyB0aGF0IGF0IHN1YmNvbXBvbmVudHMgb2YgY2FyIGJyYW5kcywgaXQgZm9ybXMgYSBjbG9zZWQgbmV0d29yayBhbmQgQXVkaSBpcyBhdCBjZW50ZXIgb2YgdGhpcyBjaXJjbGUuIE1lcmNlZGVzIGFuZCBWb2xvdmUgaXMgbGlrZSBicm9rZXJzIHdoaWNoIGhhcyBtb3N0IGNvbm5lY3Rpb24gd2l0aCBjZWxlYnJpdGllcyBzdWJjb21wb25lbnRzLiBGZXJyYXJpIGFuZCBQb3JzY2hlIGhhcyBmZXdlciBjb25uZWN0aW9ucyB3aXRoIGNlbGVicml0aWVzIHN1YmNvbXBvbmVudHMuIExhbWJvcmdoaW5pLCBMZXh1cywgQk1XICBhbmQgQXVkaSBhcmUgbWFpbmx5IGludGVybmFsIGNvbm5lY3RlZCBpbiBjYXIgc3ViY29tcG9uZW50cy4gQXQgY2VsZWJyaXR5IHN1YmNvbXBvZW50IHNpZGUsIExhZHkgR2FnYSwgSmVubmlmZXIgYW5kIEdlb3JnZSBoYXMgbW9zdCBjb25uZWN0aW9uIHdpdGggY2FyIGJyYW5kcy4gS2VzaGEgaGFzIGxlYXN0IGNvbm5lY3Rpb24gYW5kIG9ubHkgY29ubmVjdHMgdG8gTGFkeSBHYWdhIGFuZCBUYXlsb3IgU3dpZnQuDQojQWNjb3JkaW5nIHRvIGdyYXBoIHdpdGggRGF2aWRzb24gYW5kIEhhcmVsIGxheW91dC4gRm9yIGNhciBicmFuZCBzdWJjb21wb25lbnQsIEF1ZGkgaXMgc3RpbGwgYXQgY2VudGVyLCB3aGljaCBtZWFucyBBdWRpIG1pZ2h0IGhhcyBoaWdoZXN0IHdlaWdodCBvZiBjb25uZWN0aW9uIHdpdGggb3RoZXIgY2FyIGJyYW5kcy4gDQoNCg0KDQoNCiMgUGFydCAzOiBDb21tdW5pdHkgRGV0ZWN0aW9uIEFuYWx5c2lzIHdpdGggUiAoMjAgUG9pbnRzKQ0KDQpJZGVudGlmeWluZyBzdWJncm91cHMgd2l0aGluIGEgbmV0d29yayBpcyBvZiBncmVhdCBpbnRlcmVzdCB0byBzb2NpYWwgbmV0d29yayByZXNlYXJjaGVycywgc28gYSB2YXJpZXR5IG9mIGFsZ29yaXRobXMgaGF2ZSBiZWVuIGRldmVsb3BlZCB0byBpZGVudGlmeSBhbmQgbWVhc3VyZSBzdWJncm91cHMuICBXZSB3aWxsIHVzZSBzb21lIG9mIFLigJlzIGJ1aWx0LWluIHRvb2xzIHRvIGlkZW50aWZ5IHN1Ymdyb3VwcyBhbmQgY2VudHJhbCBub2RlcyBmb3IgdmlzdWFsIGluc3BlY3Rpb24uDQoNCkZvciB0aGUgcmVtYWluZGVyIG9mIHRoZSB2aXN1YWxpemF0aW9ucyB3ZSB3aWxsIHVzZSB0aGUgRnJ1Y2h0ZXJtYW4gUmVpbmdvbGQgbGF5b3V0Lg0KYGBge3J9DQpMID0gbGF5b3V0X3dpdGhfZnIoZ192YWx1ZWQpIA0KYGBgDQoNCkNsdXN0ZXIgdGhlIG5vZGVzIGluIHlvdXIgbmV0d29yay4NCmBgYHtyfQ0KIyBMZWFybiBtb3JlIGFib3V0IHRoZSBjbHVzdGVyaW5nIGFsZ29yaXRobS4NCj8/IGNsdXN0ZXJfd2Fsa3RyYXANCmNsdXN0ZXIgPC0gY2x1c3Rlcl93YWxrdHJhcChnX3ZhbHVlZCkNCiMgRmluZCB0aGUgbnVtYmVyIG9mIGNsdXN0ZXJzDQptZW1iZXJzaGlwKGNsdXN0ZXIpICAgIyBhZmZpbGlhdGlvbiBsaXN0DQpsZW5ndGgoc2l6ZXMoY2x1c3RlcikpICMgbnVtYmVyIG9mIGNsdXN0ZXJzDQojIEZpbmQgdGhlIHNpemUgdGhlIGVhY2ggY2x1c3RlciANCiMgTm90ZSB0aGF0IGNvbW11bml0aWVzIHdpdGggb25lIG5vZGUgYXJlIGlzb2xhdGVzLCBvciBoYXZlIG9ubHkgYSBzaW5nbGUgdGllDQpzaXplcyhjbHVzdGVyKSANCmBgYA0KDQoqKkhvdyBtYW55IGNvbW11bml0aWVzIGhhdmUgYmVlbiBjcmVhdGVkPyoqDQojIDIgDQoqKkhvdyBtYW55IG5vZGVzIGFyZSBpbiBlYWNoIGNvbW11bml0eT8qKg0KIyA4IGZvciBlYWNoIGNvbW11bml0eQ0KSW4gbmV0d29ya3MgY29udGFpbmluZyBub2RlIGF0dHJpYnV0ZSBpbmZvcm1hdGlvbiwgd2UgY2FuIG9mdGVuIGdhaW4gaW5zaWdodCBpbnRvIGEgbmV0d29yayBieSBsb29raW5nIGF0IHRoZSBub2RlcyB0aGF0IGdldCBwbGFjZWQgaW4gdGhlIHNhbWUgcGFydGl0aW9uLiANCioqRm9yIHlvdXIgbmV0d29yaywgd2hhdCBtaWdodCBlYWNoIGNsdXN0ZXIgb2Ygbm9kZXMgcG90ZW50aWFsbHkgaGF2ZSBpbiBjb21tb24/IERlc2NyaWJlIGVhY2ggY2x1c3RlciwgaXRzIG1lbWJlcnNoaXAsIGFuZCB0aGUgcmVsYXRpb25zaGlwIGJldHdlZW4gbm9kZXMgaW4gdGhlIGNsdXN0ZXIuKioNCiNUaGUgZmlyc3QgY2x1c3RlciBpcyBhbGwgY2VsZWJyaXRpZXMsIHNlY29uZCBjbHVzdGVyIGlzIGFsbCBjYXIgYnJhbmRzLiBUaGUgcmVsYXRpb25zaGlwIGJldHdlZW4gY2x1c3RlciAxIG1pZ2h0IGJlIGZyaW5kcywgcmVsYXRpb25zaGlwIGJldHdlZW4gY2x1c3RlciAyIG1pZ2h0IGJlIGNvbXBldGl0b3JzLg0KDQpOZXh0IHdlIHZpc3VhbGl6ZSB0aGUgY2x1c3RlcnMgYnkgY29sb3Jpbmcgbm9kZXMgYWNjb3JkaW5nIHRvIHRoZWlyIG1vZHVsYXJpdHkgY2xhc3MuIA0KYGBge3J9DQpwbG90KGNsdXN0ZXIsIGdfdmFsdWVkLCBjb2wgPSBWKGdfdmFsdWVkKSRjb2xvciwgbGF5b3V0ID0gTCwgdmVydGV4LnNpemU9NikNCmBgYA0KDQoqKldoYXQgaW5mb3JtYXRpb24gZG9lcyB0aGlzIGxheW91dCBjb252ZXk/ICBBcmUgdGhlIGNsdXN0ZXJzIHdlbGwtc2VwYXJhdGVkLCBvciBpcyB0aGVyZSBhIGdyZWF0IGRlYWwgb2Ygb3ZlcmxhcD8gSXMgaXQgZWFzaWVyIHRvIGlkZW50aWZ5IHRoZSBjb21tb24gdGhlbWVzIGFtb25nIGNsdXN0ZXJzIGluIHRoaXMgbGF5b3V0IHJhdGhlciB0aGFuIGxvb2tpbmcgb25seSBhdCB0aGUgZ3JhcGhzPyoqDQojVGhlIGNsdXN0ZXJzIGFyZSB3ZWxsIHNlcGVyYXRlZC4gQm90aCB3YXlzIGFyZSBlYXN5IHRvIGlkZW50aWZ5IHRoZSB0aGVtZXMgb2YgdGVybXMuIA0KDQoNCioqV2hhdCBkaWZmZXJlbmNlcyBhcmUgdGhlcmUgYmV0d2VlbiBub2RlcyBpbiB0aGUgc2FtZSBjbHVzdGVyIGFuZCBhY3Jvc3MgY2x1c3RlcnM/KioNCiMgTm9kZXMgaW4gc2FtZSBjbHVzdGVyIGJlbG9uZyB0byBzYW1lIHRoZW1lLCB0aGVyZSBpcyBubyBub2RlIGJlbG9uZyB0byBib3RoIGNsdXN0ZXIuDQoNCioqRGVzY3JpYmUgdGhlIGJyb2tlcnMgYmV0d2VlbiBhbnkgY29tcG9uZW50cyBhbmQgY2xpcXVlcy4gIFdoYXQgYXJlIGNvbW1vbiBmZWF0dXJlcyBvZiB0aGVzZSBicm9rZXJzPyAgQWJvdXQgaG93IG1hbnkgYnJva2VycyB3b3VsZCB5b3UgaGF2ZSB0byByZW1vdmUgZnJvbSB5b3VyIG5ldHdvcmsgdG8gInNoYXR0ZXIiIGl0IGludG8gdHdvIG9yIG1vcmUgZGlzY29ubmVjdGVkIGNvbXBvbmVudHM/KioNCiNUaGVyZSBhcmUgdGhyZWUgY2xpcXVlcyBmb3IgaW50ZXJldHMsIGZpcnN0IGNsaXF1ZSBpbmNsdWRlIGFsbCBjYXIgYnJhbmRzLCBzZWNvbmQgY2xpcXVlIGlubGN1ZGUgYWxsIGNlbGVicml0aWVzIGV4Y2VwdCBLZXNoYSwgdGhpcmQgY2xpcXVlIGluY2x1ZGUgS2VzaGEsIFRhbG9yIFN3aWZ0LCBMYWR5IEdhZ2EgYW5kIE1lcmNlZGVzLiBUaGUgYnJva2VyIGJldHdlZW4gZmlyc3QgYW5kIHRoaXJkIGNsaXF1ZSBpcyBNZXJjZWRlcy4gVGhlcmUgYXJlIG1hbnkgY29ubmVjdGlvbnMgYmV0d2VlbiBmaXJzdCBhbmQgc2Vjb25kIGNsaXF1ZXMuDQojVG8gInNoYXR0ZXIgY29tcG9uZW50cyIsIFRheWxvciBTd2lmdCwgTGFkeSBHYWdhLCBNZXJjZWRlcyBjYW4gYmUgcmVtb3ZlZCwgdGhlcmUgd2lsbCBiZSB0d28gY29tcG9uZW50cywgS2VzaGEgaXMgb25lIGNvbXBvbmVudCBhbmQgcmVzdCBvZiBub2RlcyBmb3JtIGFub3RoZXIgY29tcG9uZW50LiANCg0KIyBQYXJ0IDQ6IENlbnRyYWxpdHkgVmlzdWFsaXphdGlvbiAmIFdlaWdodGVkIFZhbHVlcyAoMjAgUG9pbnRzKQ0KDQpGb3IgZWFjaCBuZXR3b3JrLCB5b3Ugd2lsbCB1c2UgY2VudHJhbGl0eSBtZXRyaWNzIHRvIGltcHJvdmUgeW91ciB2aXN1YWxpemF0aW9uLiBZb3UgbWF5IG5lZWQgdG8gYWRqdXN0IHRoZSBzaXplIHBhcmFtZXRlciB0byBtYWtlIHlvdXIgbmV0d29yayBtb3JlIGVhc2lseSB2aXNpYmxlLg0KDQojIyBEZWdyZWUgQ2VudHJhbGl0eQ0KYGBge3J9DQp0b3RhbERlZ3JlZSA8LSBkZWdyZWUoZ192YWx1ZWQsbW9kZT0iYWxsIikNCnNvcnQodG90YWxEZWdyZWUsZGVjcmVhc2luZz1UUlVFKVsxOjVdDQpnMiA8LSBnX3ZhbHVlZA0KVihnMikkc2l6ZSA8LSB0b3RhbERlZ3JlZSoyICNjYW4gYWRqdXN0IHRoZSBudW1iZXIgaWYgbm9kZXMgYXJlIHRvbyBiaWcNCnBsb3QoZzIsIGxheW91dCA9IEwsIHZlcnRleC5sYWJlbD1OQSkNCmBgYA0KKipCcmllZmx5IGV4cGxhaW4gZGVncmVlIGNlbnRyYWxpdHkgYW5kIHdoeSBub2RlcyBhcmUgbW9yZSBvciBsZXNzIGNlbnRyYWwgaW4gdGhlIG5ldHdvcmsuKioNCiNEZWdyZWUgY2VudHJhbGl0eSBpbmRpY2F0ZXMgbnVtYmVyIG9mIG5vZGVzIGl0IGhhcyBjb25uZWN0aW9uIHRvLk1vc3Qgb2Ygbm9kZXMgaGFzIGhpZ2ggY2VudHJhbGl0eSBpbiB0aGlzIG5ldHdvcmssIHNvbWUgbm9kZXMgYXJlIGxlc3MgY2VudHJhbCBzdWNoIGFzIEtlc2hhLCBhcyBLZXNoYSB3YXMgbm90IGFzIHBvcHVsYXIgYXMgb3RoZXIgY2VsZWJyaXRpZXMsIHRodXMgaXQgaGFzIGZld2VyIGNvbm5lY3Rpb25zLg0KDQoNCiMjIFdlaWdodGVkIERlZ3JlZSBDZW50cmFsaXR5DQpgYGB7cn0NCndkIDwtIGdyYXBoLnN0cmVuZ3RoKGdfdmFsdWVkLHdlaWdodHMgPSBFKGdfdmFsdWVkKSRDb09jY3VycmVuY2VzKQ0Kc29ydCh3ZCxkZWNyZWFzaW5nPVRSVUUpWzE6NV0NCndnMiA8LSBnX3ZhbHVlZA0KVih3ZzIpJHNpemUgPC0gd2QqLjEgIyBhZGp1c3QgdGhlIG51bWJlciBpZiBub2RlcyBhcmUgdG9vIGJpZw0KcGxvdCh3ZzIsIGxheW91dCA9IEwsIHZlcnRleC5sYWJlbD1OQSwgZWRnZS53aWR0aD1zcXJ0KEUoZ192YWx1ZWQpJENvT2NjdXJyZW5jZXMpKSAjdGFraW5nIHRoZSBzcXVhcmUgcm9vdCBpcyBhIGdvb2Qgd2F5IHRvIG1ha2UgYSBsYXJnZSByYW5nZSBvZiBudW1iZXJzIHZpc2libGUgaW4gYW4gZWRnZS4gT3RoZXJ3aXNlIGVkZ2VzIHRlbmQgdG8gY292ZXIgdXAgYWxsIHRoZSBvdGhlciBlZGdlcyBhbmQgb2JzY3VyZSB0aGUgcmVsYXRpb25zaGlwcy4NCmBgYA0KKipXaGF0IGRvZXMgdGhlIGFkZGl0aW9uIG9mIHdlaWdodGVkIGRlZ3JlZSBhbmQgZWRnZSBpbmZvcm1hdGlvbiB0ZWxsIHlvdSBhYm91dCB5b3VyIGdyYXBoPyoqDQojVGhlIGFkZGl0aW9uIG9mIHdlaWdodGVkIGRlZ3JlZSBhbmQgZWRnZSBzaG93IHRoZSBkaWZmZXJlbmNlIG9mIGVkZ2UgdmFsdWVzLiBTb21lIG5vZGVzIHdpdGggbGFyZ2UgbnVtYmVyIG9mIGNvb2NjdXJhbmNlIGluZGljYXRlIGxhcmdlIG5vZGUgdmFsdWUuIFRodXMgTWVyY2VkZXMsIEJNVyBhbmQgQXVkaSBiZWNvbWUgbGFyZ2VzdCBub2RlIGluIGdyYXBoLg0KDQoNCiMjIEJldHdlZW5uZXNzIENlbnRyYWxpdHkNCmBgYHtyfQ0KYiA8LSBiZXR3ZWVubmVzcyhnX3ZhbHVlZCxkaXJlY3RlZD1UUlVFKQ0Kc29ydChiLGRlY3JlYXNpbmc9VFJVRSlbMTo1XQ0KZzQgPC0gZ192YWx1ZWQNClYoZzQpJHNpemUgPC0gYioxLjIjY2FuIGFkanVzdCB0aGUgbnVtYmVyDQpwbG90KGc0LCBsYXlvdXQgPSBMLCB2ZXJ0ZXgubGFiZWw9TkEpDQpgYGANCioqQnJpZWZseSBleHBsYWluIGJldHdlZW5uZXNzIGNlbnRyYWxpdHkgYW5kIHdoeSBub2RlcyBhcmUgbW9yZSBvciBsZXNzIGNlbnRyYWwgaW4gdGhlIG5ldHdvcmsuKioNCiNCZXR3ZWVubmVzcyBjZW50cmFsaXR5IGluZGljYXRlcyBob3cgbWFueSB0aW1lcyBnZW9kZXN0aWMgZGlzdGFuY2UgcGFzcyBhIG5vZGUuIFRoZSBub2RlcyBhdCBlZGdlIHR5cGljYWxseSBoYXMgc21hbGwgYmV0d2Vlbm5lc3MgY2VudHJhbGl0eSBhbmQgbm9kZXMgYXQgY2VudGVyIGhhcyBoaWdoZXIgYmV0d2Vlbm5lc3MgY2VudHJhbGl5IGFzIG5vZGVzIGF0IGNlbnRlciBzaG9ydGVucyBnZW9kZXN0aWMgZGlzdGFuY2UgYXQgdHdvIHNpZGVzLiANCg0KIyMjIFdlaWdodGVkIEJldHdlZW5uZXNzIENlbnRyYWxpdHkNCmBgYHtyfQ0Kd2J0d24gPC0gYmV0d2Vlbm5lc3MoZ192YWx1ZWQsd2VpZ2h0cyA9IEUoZ192YWx1ZWQpJENvT2NjdXJyZW5jZXMpDQpzb3J0KHdidHduLGRlY3JlYXNpbmc9VFJVRSlbMTo1XQ0Kd0J0d25HIDwtIGdfdmFsdWVkDQpWKHdCdHduRykkc2l6ZSA8LSB3YnR3biouNSAjIGFkanVzdCB0aGUgbnVtYmVyIGlmIG5vZGVzIGFyZSB0b28gYmlnDQpwbG90KHdCdHduRywgbGF5b3V0ID0gTCwgdmVydGV4LmxhYmVsPU5BLCBlZGdlLndpZHRoPXNxcnQoRShnX3ZhbHVlZCkkQ29PY2N1cnJlbmNlcykpICN0YWtpbmcgdGhlIHNxdWFyZSByb290IGlzIGEgZ29vZCB3YXkgdG8gbWFrZSBhIGxhcmdlIHJhbmdlIG9mIG51bWJlcnMgdmlzaWJsZSBpbiBhbiBlZGdlLg0KYGBgDQoqKldoYXQgZG9lcyB0aGUgYWRkaXRpb24gb2Ygd2VpZ2h0ZWQgZGVncmVlIGFuZCBlZGdlIGluZm9ybWF0aW9uIHRlbGwgeW91IGFib3V0IHlvdXIgZ3JhcGg/KioNCldoaWxlIGNvbnNpZGVyaW5nIHRoZSB3ZWlnaHQgb2YgYmV0d2Vlbm5lc3MsIExhZHkgZ2FnYSBpcyB0aGUgd2lubmVyIGFuZCBpcyBkb3VibGUgaGlnaGVyIHRoYW4gTWVyY2VkZXMuIEVkZ2UgYXQgY2FyIGJyYW5kIGNsdXN0ZXIgYXJlIHRoaWNrZXIgdGhhbiBjZWxlYnJpdHkgY2x1c3RlciBhcyBpdHMgdmFsdWUgb2YgY29vY2NvdXJhbmNlIGlzIGhpZ2VyIHRoYW4gY2VsZWJyaXR5IGNsdXN0ZXIuDQoNCg0KDQojIyBDbG9zZW5lc3MgQ2VudHJhbGl0eQ0KYGBge3J9DQpjIDwtIGNsb3NlbmVzcyhnX3ZhbHVlZCkNCnNvcnQoYyxkZWNyZWFzaW5nPVRSVUUpWzE6NV0NCmc1IDwtIGdfdmFsdWVkDQpWKGc1KSRzaXplIDwtIGMqNTAwICAjY2FuIGFkanVzdCB0aGUgbnVtYmVyDQpwbG90KGc1LCBsYXlvdXQgPSBMLCB2ZXJ0ZXgubGFiZWw9TkEpDQpgYGANCioqQnJpZWZseSBleHBsYWluIGNsb3NlbmVzcyBjZW50cmFsaXR5IGFuZCB3aHkgbm9kZXMgYXJlIG1vcmUgb3IgbGVzcyBjZW50cmFsIGluIHRoZSBuZXR3b3JrLioqDQpjbG9zZW5lc3MgY2VudHJhbGl0eSBtZWFzdXJlcyB0aGUgYXZlcmFnZSBsZW5ndGggb2YgZ2VvZGVzaWMgcGF0aHMgYmV3ZWVuIG9uZSBub2RlIHRvIHRoZSByZXN0IG9mIG5vZGVzLiBJbiB0aGlzIG5ldHdvcmssIGFzIG1vc3Qgb2Ygbm9kZXMgYXJlIGRpcmVjdGx5IGNvbm5lY3RlZCwgdGh1cyB0aGV5IGFsbCBoYXZlIGhpZ2ggY2xvc2VuZXNzIGNlbnRyYWxpdHkgYW5kIHZhbHVlIG9mIGNsb3NlbmVzcyBjZW50cmFsaXR5IGlzIHZlcnkgY2xvc2UuIA0KDQojIyMgV2VpZ2h0ZWQgQ2xvc2VuZXNzIENlbnRyYWxpdHkNCg0KYGBge3J9DQp3Q2xzbnNzIDwtIGNsb3NlbmVzcyhnX3ZhbHVlZCx3ZWlnaHRzID0gRShnX3ZhbHVlZCkkQ29PY2N1cnJlbmNlcykNCnNvcnQod0Nsc25zcyxkZWNyZWFzaW5nPVRSVUUpWzE6NV0NCndDbHNuc3NHIDwtIGdfdmFsdWVkDQpWKHdDbHNuc3NHKSRzaXplIDwtIHdDbHNuc3MqMTAwMCAjIGFkanVzdCB0aGUgbnVtYmVyIGlmIG5vZGVzIGFyZSB0b28gYmlnDQpwbG90KHdDbHNuc3NHLCBsYXlvdXQgPSBMLCB2ZXJ0ZXgubGFiZWw9TkEsIGVkZ2Uud2lkdGg9c3FydChFKGdfdmFsdWVkKSRDb09jY3VycmVuY2VzKSkgI3Rha2luZyB0aGUgc3F1YXJlIHJvb3QgaXMgYSBnb29kIHdheSB0byBtYWtlIGEgbGFyZ2UgcmFuZ2Ugb2YgbnVtYmVycyB2aXNpYmxlIGluIGFuIGVkZ2UuDQpgYGANCioqV2hhdCBkb2VzIHRoZSBhZGRpdGlvbiBvZiB3ZWlnaHRlZCBkZWdyZWUgYW5kIGVkZ2UgaW5mb3JtYXRpb24gdGVsbCB5b3UgYWJvdXQgeW91ciBncmFwaD8qKg0KI1doaWxlIGNvbnNpZGVyaW5nIHRoZSB3ZWlnaHQsIExhZHkgR2FnYSBoYXMgaGlnaGVzdCBjbG9zZW5lc3MgY2VudHJhbGl0eS4NCg0KDQojIyBFaWdlbnZlY3RvciBDZW50cmFsaXR5DQpgYGB7cn0NCmVpZ2MgPC0gZWlnZW5fY2VudHJhbGl0eShnX3ZhbHVlZCxkaXJlY3RlZD1UUlVFKQ0Kc29ydChlaWdjJHZlY3RvcixkZWNyZWFzaW5nPVRSVUUpWzE6NV0NCmc2IDwtIGdfdmFsdWVkDQpWKGc2KSRzaXplIDwtIGVpZ2MkdmVjdG9yKjUwICNjYW4gYWRqdXN0IHRoZSBudW1iZXINCnBsb3QoZzYsIGxheW91dCA9IEwsIHZlcnRleC5sYWJlbD1OQSkNCmBgYA0KDQoqKkJyaWVmbHkgZXhwbGFpbiBlaWdlbnZlY3RvciBjZW50cmFsaXR5IGFuZCB3aHkgbm9kZXMgYXJlIG1vcmUgb3IgbGVzcyBjZW50cmFsIGluIHRoZSBuZXR3b3JrLioqDQojRWlnZW52ZWN0b3IgY2VudHJhbGl0eSBzaG93cyB0aGF0IGEgbm9kZSdzIGNlbnRyYWxpdHkgaXMgYSBmdW5jdGlvbiBvZiBpdHMgbmVpZ2h2b3JzIGNlbnRyYWxpdHkuIElmIGEgbm9kZSBpcyBzb3Jyb3VuZGVkIGJ5IG5vZGVzIHdpdGggaGlnaCBzdHJlbmd0aCwgdGhpcyBub2RlIHdpbGwgYWxzbyBoYXZlIGhpZ2ggc3RyZW5ndGguIE5vZGVzIGF0IGNlbnRlciB0eXBpY2FsbHkgaGFzIGhpZ2hlciBlaWdlbnZlY3RvciBjZW50cmFsaXR5IHRoYW4gbm9kZXMgYXQgZWRnZS4NCg0KIyMgQW5hbHlzaXMNCioqQ2hvb3NlIHRoZSB2aXN1YWxpemF0aW9uIHRoYXQgeW91IHRoaW5rIGlzIG1vc3QgaW50ZXJlc3RpbmcgYW5kIGJyaWVmbHkgZXhwbGFpbiB3aGF0IGl0IHRlbGxzIHlvdSBhYm91dCBhIGNlbnRyYWwgbm9kZSBpbiB5b3VyIG5ldHdvcmsuIERpc2N1c3MgdGhlIHR5cGUgb2YgY2VudHJhbGl0eSwgYW5kIHdoYXQgdGhhdCBub2Rl4oCZcyBjZW50cmFsaXR5IHNjb3JlIHRlbGxzIHlvdSBhYm91dCB0aGUgc2VhcmNoIGNvLW9jY3VycmVuY2UgbmV0d29yay4qKg0KI1RoZSBtb3N0IGludGVyZXN0aW5nIG5ldHdvcmsgaXMgdGhlIGdyYXBoIHdpdGggY2x1c3RlcmluZ3MsIHRoaXMgZ3JhcGggc2hvd3MgdGhlIGNlbnRyYWwgbm9kZSBtaWdodCBiZSBNZXJjZWRlcyBhcyBpdCBoYXMgbW9zdCBjb25uZWN0aW9ucyB3aXRoIG90aGVyIG5vZGVzLk1lcmNlZGVzIGhhcyBoaWdoZXN0ICh3ZWlnaHRlZClkZWdyZWUgY2VudHJhbGl0eSwgYmV0d2Vlbm5lc3MsIGNsb3NlbmVzcyBhbmQgZWlnZW52ZWN0b3IgY2VudHJhbGl0eS4gDQojVGhlIHdlaWdodGVkIGNlbnRyYWxpdHkgY29uc2lkZXJzIHRoZSBmYWN0b3Igb2YgY28tb2NjdXJyZW5jZS5Ib3dldmVyLCBieSBjb25zaWRlcmluZyB0aGlzIGZhY3RvciwgTWVyY2VkZXMgZG9lc24ndCBoYXZlIGhpZ2hlc3Qgd2VpZ2h0ZWQgYmV0d2Vlbm5lc3MgYW5kIGNsb3NlbmVzcyBjZW50cmFsaXR5IGFuZCByYW5rZWQgc2Vjb25kLiANCg0KKipCcmllZmx5IGRpc2N1c3MgYW4gaW50ZXJlc3RpbmcgZGlmZmVyZW5jZSBiZXR3ZWVuIHR5cGVzIG9mIGNlbnRyYWxpdHkgZm9yIHlvdXIgbmV0d29yay4qKg0KI0ZvciBiZXR3ZWVubmVzcyBhbmQgY2xvc2VuZXNzIGNlbnRyYWxpdHksIHRoZSBoaWdoZXN0IHZhbHVlIGlzIGFsd2F5cyBNZXJjZWRlcy4gV2hpbGUgY29uc2lkZXJpbmcgdGhlIHdlaWdodHMsIExhZHkgR2FnYSB3aWxsIGJlIGhpZ2hlciB0aGFuIE1lcmNlZGVzLiANCg0KDQojIyBHbG9iYWwgTmV0d29yayBNZXRyaWNzIHdpdGggUg0KDQpDb21wdXRlIHRoZSBuZXR3b3JrIGNlbnRyYWxpemF0aW9uIHNjb3JlcyBmb3IgeW91ciBuZXR3b3JrIGZvciBkZWdyZWUsIGJldHdlZW5uZXNzLCBjbG9zZW5lc3MsIGFuZCBlaWdlbnZlY3RvciBjZW50cmFsaXR5Lg0KDQpgYGB7cn0NCiMgRGVncmVlIGNlbnRyYWxpemF0aW9uDQpjZW50cmFsaXphdGlvbi5kZWdyZWUoZ192YWx1ZWQsbm9ybWFsaXplZCA9IFRSVUUpDQoNCiMgQmV0d2Vlbm5lc3MgY2VudHJhbGl6YXRpb24NCmNlbnRyYWxpemF0aW9uLmJldHdlZW5uZXNzKGdfdmFsdWVkLG5vcm1hbGl6ZWQgPSBUUlVFKQ0KDQojIENsb3NlbmVzcyBjZW50cmFsaXphdGlvbiANCmNlbnRyYWxpemF0aW9uLmNsb3NlbmVzcyhnX3ZhbHVlZCxub3JtYWxpemVkID0gVFJVRSkNCg0KIyBFaWdlbnZlY3RvciBjZW50cmFsaXphdGlvbiANCmNlbnRyYWxpemF0aW9uLmV2Y2VudChnX3ZhbHVlZCxub3JtYWxpemVkID0gVFJVRSkNCg0KYGBgDQoqKlJlY29yZCB0aGUgY2VudHJhbGl6YXRpb24gc2NvcmUgb2YgZWFjaCBjZW50cmFsaXR5IG1lYXN1cmUuKioNCiNkZWdyZWUgY2VudHJhbGl6YXRpb246IDAuMzQxNjY2Nw0KI2JldHdlZW5uZXNzIGNlbnRyYWxpemF0aW9uOiAwLjEwOTk1NDENCiNjbG9zZW5lc3MgY2VudHJhbGl6YXRpb246IDAuNDgyNjk0NQ0KI2VpZ2VudmVjdG9yIGNlbnRyYWxpemF0aW9uOiAwLjM2MDc3MzYNCioqQnJpZWZseSBleHBsYWluIHdoYXQgdGhlIGNlbnRyYWxpemF0aW9uIG9mIGEgbmV0d29yayBpcy4qKg0KI0NlbnRyYWxpemF0aW9uIG9mIG5ldHdvcmsgaW5kaWNhdGVzIHRoZSBkaWZmZXJlbmNlIGFtb25nIG5vZGVzIGluIHRlcm1zIG9mIG51bWJlciBvZiBub2RlcyB0aGV5IGNvbm5lY3QgdG8uIA0KDQoqKkNvbXBhcmUgdGhlIGNlbnRyYWxpemF0aW9uIHNjb3JlcyBhYm92ZSB3aXRoIHRoZSBncmFwaHMgeW91IGNyZWF0ZWQgd2hlcmUgdGhlIG5vZGVzIGFyZSBzY2FsZWQgYnkgY2VudHJhbGl0eS4gRGVzY3JpYmUgdGhlIGFwcGVhcmFuY2Ugb2YgbW9yZSBjZW50cmFsaXplZCB2LiBsZXNzIGNlbnRyYWxpemVkIG5ldHdvcmtzLioqDQojVGhlIGNlbnRyYWxpemF0aW9uIHNjb3JlcyBhcmUgbm90IGhpZ2gsIGl0IGlzIHJlYXNvbmFibGUgdGhlcmUgYXJlIHR3byBiaWcgY2xpcXVlcyBhbmQgYSBzbWFsbCBjbGlxdWUuIFRvIGdldCBhIG1vcmUgY2VudHJhbGl6ZWQgbmV0d29yaywgdGhlIG9uZSBvZiBmb3JtYXRpb24gaXMgbGlrZSBzdGFyLCBvbmUgbm9kZSBoYXMgY29ubmVjdGlvbiB0byBtYW55IG90aGVyIG5vZGVzLCB3aGlsZSBvdGhlciBub2RlcyBoYXMgbG93IGNvbm5lY3Rpdml0eS4gQSBsZXNzIGNlbnRyYWxpemVkIG5ldHdvcmsgaXMgbGlrZSBldmVyeSBub2RlIGhhcyBzaW1pbGFyIGNvbm5lY3Rpdml0eS4NCg0KDQojIyBQYXJ0IDUuIFBvd2VyIExhd3MgJiBTbWFsbCBXb3JsZHMgKDIwKQ0KDQojIyBQb3dlciBMYXdzDQpOZXR3b3JrcyBvZnRlbiBkZW1vbnN0cmF0ZSBwb3dlciBsYXcgZGlzdHJpYnV0aW9ucy4gUGxvdCB0aGUgZGVncmVlIGRpc3RyaWJ1dGlvbiBvZiB0aGUgbm9kZXMgaW4geW91ciBiYXNlIGdyYXBoLiANCmBgYHtyfQ0KIyBDYWxjdWxhdGUgZGVncmVlIGRpc3RyaWJ1dGlvbg0KZGVnIDwtIGRlZ3JlZShnX3ZhbHVlZCx2PVYoZ192YWx1ZWQpLCBtb2RlPSJhbGwiKQ0KZGVnDQoNCiMgRGVncmVlIGRpc3RyaWJ1dGlvbiBpcyB0aGUgY3VtdWxhdGl2ZSBmcmVxdWVuY3kgb2Ygbm9kZXMgd2l0aCBhIGdpdmVuIGRlZ3JlZQ0KZGVnX2Rpc3RyIDwtZGVncmVlLmRpc3RyaWJ1dGlvbihnX3ZhbHVlZCwgY3VtdWxhdGl2ZT1ULCBtb2RlPSJhbGwiKQ0KZGVnX2Rpc3RyDQpwbG90KGRlZ19kaXN0ciwgeWxpbT1jKC4wMSwxMCksIGJnPSJibGFjayIscGNoPTIxLCB4bGFiPSJEZWdyZWUiLCB5bGFiPSJDdW11bGF0aXZlIEZyZXF1ZW5jeSIpICNZb3UgbWF5IG5lZWQgdG8gYWRqdXN0IHRoZSB5bGltIHRvIGEgbGFyZ2VyIG9yIHNtYWxsZXIgbnVtYmVyIHRvIG1ha2UgdGhlIGdyYXBoIHNob3cgbW9yZSBkYXRhLg0KYGBgDQoNClRlc3Qgd2hldGhlciBpdOKAmXMgYXBwcm94aW1hdGVseSBhIHBvd2VyIGxhdywgZXN0aW1hdGUgbG9nIGYgKGspID0gbG9nIGEg4oiSIGMgbG9nIGsuIOKAnFRoaXMgc2F5cyB0aGF0IGlmIHdlIGhhdmUgYSBwb3dlci1sYXcgcmVsYXRpb25zaGlwLCBhbmQgd2UgcGxvdCBsb2cgZiAoaykgYXMgYSBmdW5jdGlvbiBvZiBsb2cgaywgdGhlbiB3ZSBzaG91bGQgc2VlIGEgc3RyYWlnaHQgbGluZTog4oiSYyB3aWxsIGJlIHRoZSBzbG9wZSwgYW5kIGxvZyBhIHdpbGwgYmUgdGhlIHktaW50ZXJjZXB0LiBTdWNoIGEg4oCcbG9nLWxvZ+KAnSBwbG90IHRodXMgcHJvdmlkZXMgYSBxdWljayB3YXkgdG8gc2VlIGlmIG9uZeKAmXMgZGF0YSBleGhpYml0cyBhbiBhcHByb3hpbWF0ZSBwb3dlci1sYXc6IGl0IGlzIGVhc3kgdG8gc2VlIGlmIG9uZSBoYXMgYW4gYXBwcm94aW1hdGVseSBzdHJhaWdodCBsaW5lLCBhbmQgb25lIGNhbiByZWFkIG9mZiB0aGUgZXhwb25lbnQgZnJvbSB0aGUgc2xvcGUu4oCdIChFJkssIENoYXB0ZXIgMTgsIHAuNTQ2KS4NCg0KYGBge3J9DQpwb3dlciA8LSBwb3dlci5sYXcuZml0KGRlZ19kaXN0cikNCnBvd2VyDQpwbG90KGRlZ19kaXN0ciwgbG9nPSJ4eSIsIHlsaW09YyguMDEsMTApLCBiZz0iYmxhY2siLHBjaD0yMSwgeGxhYj0iRGVncmVlIiwgeWxhYj0iQ3VtdWxhdGl2ZSBGcmVxdWVuY3kiKQ0KYGBgDQoNCioqRG9lcyB5b3VyIG5ldHdvcmsgZXhoaWJpdCBhIHBvd2VyIGxhdyBkaXN0cmlidXRpb24gb2YgZGVncmVlIGNlbnRyYWxpdHk/KioNCiNZZXMNCg0KDQoNCiMjIFNtYWxsIFdvcmxkcw0KDQpOZXR3b3JrcyBvZnRlbiBkZW1vbnN0cmF0ZSBzbWFsbCB3b3JsZCBjaGFyYWN0ZXJpc3RpY3MuIENvbXB1dGUgdGhlIGF2ZXJhZ2UgY2x1c3RlcmluZyBjb2VmZmljaWVudCAoQUNDKSBhbmQgdGhlIGNoYXJhY3RlcmlzdGljIHBhdGggbGVuZ3RoIChDUEwpLg0KYGBge3J9DQojIEF2ZXJhZ2UgY2x1c3RlcmluZyBjb2VmZmljaWVudCAoQUNDKQ0KdHJhbnNpdGl2aXR5KGdfdmFsdWVkLCB0eXBlID0gYygiYXZlcmFnZSIpKQ0KDQojIENoYXJhY3RlcmlzdGljIHBhdGggbGVuZ3RoIChDUEwpDQphdmVyYWdlLnBhdGgubGVuZ3RoKGdfdmFsdWVkKQ0KYGBgDQoNCkNvbXB1dGUgdGhlIEFDQyBhbmQgQ1BMIGZvciAxMDAgcmFuZG9tIG5ldHdvcmtzIHdpdGggdGhlIHNhbWUgbnVtYmVyIG9mIG5vZGVzIGFuZCB0aWVzIGFzIHlvdXIgdGVzdCBuZXR3b3JrLiANCg0KYGBge3J9DQphY2NTdW0gPC0gMA0KY3BsU3VtIDwtIDANCmZvciAoaSBpbiAxOjEwMCl7DQogIGdycGggPC0gZXJkb3MucmVueWkuZ2FtZShudW1WZXJ0aWNlcywgbnVtRWRnZXMsIHR5cGUgPSAiZ25tIikNCiAgYWNjU3VtIDwtIGFjY1N1bSArIHRyYW5zaXRpdml0eShncnBoLCB0eXBlID0gYygiYXZlcmFnZSIpKQ0KICBjcGxTdW0gPC0gY3BsU3VtICsgYXZlcmFnZS5wYXRoLmxlbmd0aChncnBoKQ0KfQ0KYWNjU3VtLzEwMA0KY3BsU3VtLzEwMA0KYGBgDQoNCioqQmFzZWQgb24gdGhlc2UgZGF0YSwgd291bGQgeW91IGNvbmNsdWRlIHRoYXQgdGhlIG9ic2VydmVkIG5ldHdvcmsgZGVtb25zdHJhdGVzIHNtYWxsIHdvcmxkIHByb3BlcnRpZXM/IFdoeSBvciB3aHkgbm90PyoqDQojVGhlIG9ic2VydmVkIG5ldHdvcmsgaGFzIHNtYWxsIHdvcmxkIHByb3BlcnRpZXMsIGFzIGl0IGhhcyBoaWdoIGxvY2FsIGNsdXN0ZXJpbmcgY29lZmZpY2llbnQgYW5kIHNtYWxsIGF2ZXJhZ2UgcGF0aCBsZW5ndGggdG8gb3RoZXIgbm9kZXMuIA0KDQoNCiMjIFdyYXBwaW5nIHVwDQpUbyBjb21wbGV0ZSB0aGUgbGFiLCBtYWtlIHN1cmUgb3V0cHV0L3ByZXZpZXdzIGhhdmUgYmVlbiBnZW5lcmF0ZWQgZm9yIGVhY2ggYmxvY2sgb2YgY29kZS4gVGhlbiBjbGljayB0aGUgIlB1Ymxpc2giIGJ1dHRvbiBvbiB0aGUgdXBwZXIgcmlnaHQgaGFuZCBjb3JuZXIgb2YgdGhpcyBzY3JlZW4gYW5kIHNpZ24gdXAgZm9yIGFuIFJQdWJzIGFjY291bnQuIFN1Ym1pdCB0aGUgVVJMIG9mIHRoZSBwdWJsaXNoZWQsIGNvbXBsZXRlZCBsYWIgb24gQ2FudmFzLg==