Set up

library(igraph)
## 
## Attaching package: 'igraph'
## The following objects are masked from 'package:stats':
## 
##     decompose, spectrum
## The following object is masked from 'package:base':
## 
##     union
load('data/example-data-compcog.RData')

There should be 3 objects loaded into your R workspace:

  • pnet
  • snet
  • pnet_edgelist

pnet refers to a section of the phonological network first described by Vitevitch (2008). The nodes represent English words, and edges connect words that are phonological neighbors of each other based on the 1-edit distance metric computed on their phonological transcriptions (Luce & Pisoni, 1998). E.g., /k@t/–/k@p/ are neighboring nodes. Specifically, this network is the 2-hop network of the word ‘speech’ - in addition to ‘speech’ itself, its immediate phonological neighbors and the neighbors of its neighbors are included in this representation.

pnet_edgelist is the raw data that is used to create pnet. It is an edgelist whereby each row depicts one edge in the network.

snet refers to a section of the word association network using data from De Deyne et al. (2020). The nodes represent English words, and edges connect words that are produced as free associations of other words. E.g., “cat”–“dog” are neighboring nodes. This network has edges with 2 interesting properties. (i) Each edge has a weight attribute that corresponds to the associative strength of two nodes, or the proportion of participants who provided a specific response to the cue word. (ii) The edges are also directed such the direction goes from the cue word to the response word, i.e., “cat”->“dog”. Specifically, this network is the 1-hop network of the word ‘cheese’ - in addition to ‘cheese’ itself, its immediate associates and the cue words that led to the response ‘cheese’ are included in this representation. See https://smallworldofwords.org/en/project/research for more information.

summary(pnet) # undirected, unweighted edges 
## IGRAPH ddad942 UN-- 39 121 -- 
## + attr: name (v/c)
summary(snet) # directed, weighted edges
## IGRAPH 9a00b73 DNW- 211 1324 -- 
## + attr: name (v/c), weight (e/n)

Notice the two numbers on the first row: The first tells you the number of nodes or vertices in the network, the second tells you the number of edges or links.

There are also some cyptic looking characters. Let’s unpack that. The first character is either “U” or “D” and tells you whether the edges are “undirected” or “directed”. The second character “N” (if present) tells you that the nodes have “names”. The third character “W” (if present) tells you that the edges are weighted. The final character is blank unless you have a special type of network known as a bipartite network (in which case the fourth character is “B”).

On the second row, additional information about node or edge attributes can be found if they have been specified in the construction of the network. Both networks have node names, and the semantic network has an edge attribute known as weight.

Loading a network into igraph

There are a number of different ways to convert your raw data into a network representation that igraph can analyze. This data first needs to be organized as an edgelist or an adjacency matrix or an adjacency list and then loaded into RStudio. Below I provide a quick example of how an edgelist can be converted into a network.

head(pnet_edgelist) # preview first few rows of the edgelist 
##      [,1]        [,2]       
## [1,] "biC;beach" "iC;each"  
## [2,] "biC;beach" "liC;leach"
## [3,] "iC;each"   "liC;leach"
## [4,] "pi;p"      "pis;peace"
## [5,] "biC;beach" "piC;peach"
## [6,] "iC;each"   "piC;peach"
pnet2 <- graph_from_edgelist(pnet_edgelist,
                             directed = F) # the edges are undirected in this network 

summary(pnet2)
## IGRAPH 2e75c97 UN-- 39 121 -- 
## + attr: name (v/c)

There are many useful functions in igraph (those that begin with graph_from_*) for converting various kinds of datasets into networks. The igraph manual is a good place to start learning about these functions and their arguments to specify edge or node attributes of the network. Outside of igraph you will probably have to spend some time curating and wrangling your data so that it is in the right formats for igraph.

Visualizations

Here are visualizations of the networks we will play around with today.

plot(pnet,
     vertex.frame.color = 'white',
     vertex.label.color = 'grey30',
     edge.color = 'black',
     vertex.label = gsub('[[:print:]]+;', '', V(pnet)$name), # regex to only print the word names and not transcriptions
     layout = layout_with_lgl,
     frame = TRUE,
     margin = c(0,0,0,0),
     main = 'A partial phonological network of English words')

plot(snet,
     vertex.frame.color = 'white',
     vertex.label.color = 'grey30',
     edge.color = 'black',
     vertex.color = 'seagreen',
     vertex.size = 5,
     edge.arrow.size = 0.4,
     layout = layout_with_graphopt,
     frame = TRUE,
     margin = c(0,0,0,0),
     main = 'A partial semantic network')

Disclaimers

Due to limited time, I assume that you have some familiarity with R and RStudio. A gentle introduction to R programming can be found here: https://psyr.djnavarro.net/

I also choose to not cover in detail a number of important topics such as how to convert your raw data into an igraph network object, network visualization in igraph (for a great introduction to this topic, see https://kateto.net/network-visualization), and other methods of quantifying the community structure of the network (i.e., meso-level). Some of these topics are briefly touched on in a different tutorial and you can find the materials here: https://vpf-netsci.netlify.app/part2-demo.html

Measuring the network

Once we have a network representation, the tools of network science can be applied to analyze the networks in different ways. In this tutorial we focus on a descriptive analysis of the network and review various network measures that can be used to describe or quantify network structure at three different levels of the network: the micro-level (referring to the local structure and other properties of individual nodes), the meso-level (subgroups or clusters of nodes), and the macro-level (referring to the overall or global structure of the network).

Micro-level (node-level)

Micro-level network measures provide you with information about specific nodes in the network. These are generally known as centrality measures in the network science literature. Centrality is the network scientist’s way of quantifying the relative “importance” of a given node relative to other nodes in the network. There are many different definitions of what counts as “central”, as you will see in the following subsections. There is no single “correct” or “best” metric - which metrics are most useful to you will depend on the nature of the system that you are modeling as well as the network behavior that you interested in.

Degree (unweighted edges)

The degree of node i refers to the number of edges or links connected to that node.

If your network has directed edges, in-degree refers to the number of edges that are going towards the target node, whereas out-degree refers to the number of edges that are going away from the target node.

# undirected network
degree(graph = pnet) # for all nodes in the network
##  xpik;apeak   biC;beach    sid;cede     iC;each   liC;leach        pi;p 
##           2           5           4           5           5           9 
##   p@C;patch   pis;peace   piC;peach    pik;peak    pil;peal   piz;pease 
##           6           9          22          12           9           9 
##    pit;peat    pin;peen    pip;peep   piv;peeve   pRC;perch   pIC;pitch 
##           9           9           9           9           6           6 
##   poC;poach   pWC;pouch priC;preach  pUC;putsch   riC;reach    sik;seek 
##           6           6           2           6           6           5 
##  slik;sleek  snik;sneak  sped;spade  spik;speak  spEk;speck   spEd;sped 
##           3           3           3          11           5           4 
## spiC;speech  spid;speed  spYk;spike  spok;spoke  spuk;spook   sp^d;spud 
##           3           8           4           4           4           3 
##  stid;steed  swid;swede   tiC;teach 
##           3           3           5
degree(graph = snet, v = 'cheese') # for a specific node in the network 
## cheese 
##    231
# directed network
degree(graph = snet, v = 'cheese', mode = 'in') # in-degree = incoming edges
## cheese 
##    185
degree(graph = snet, v = 'cheese', mode = 'out') # out-degree = outgoing edges 
## cheese 
##     46
degree(graph = snet, v = 'cheese', mode = 'all') # in-degree + out-degree
## cheese 
##    231

Strength (weighted edges)

The strength of node i refers to the sum of its adjacent edge weights. Only applicable to weighted networks.

strength(graph = snet) |> head(5)
##      age     aged     ages    aging american 
##     0.57     0.55     0.04     0.17     0.36
# for directed networks
strength(graph = snet, v = 'age', mode = 'in') # in-degree = incoming edges
##  age 
## 0.38
strength(graph = snet, v = 'age', mode = 'out') # out-degree = outgoing edges 
##  age 
## 0.19
strength(graph = snet, v = 'age', mode = 'all') # in-degree + out-degree
##  age 
## 0.57

Relevant finding in psychology: De Deyne et al. (2019) found that strength (operationalized as association frequency) was superior to, or at least similar to, word frequency as a predictor of lexical decision and semantic decision performance.

Local Clustering Coefficient (unweighted)

The local clustering coefficient, C, of node i measures the ratio of the actual number of edges existing among nodes directly connected to the target node i to the number of all possible edges among these nodes.

C ranges from 0 to 1. When C = 0, none of the neighbors of a target node are neighbors of each other. When C = 1, every neighbor is also a neighbor of all the other neighbors of a target word.

You can think of the local clustering coefficient as providing a measure of the level of interconnectivity among the local neighborhood of the node.

Both words have the same number of neighbors, but different local clustering coefficients.

Relevant finding in psychology: Chan & Vitevitch (2009) showed that words with higher clustering coefficients were responded to more slowly than words with lower clustering coefficient in spoken word recognition tasks (even after controling for the size of the phonological neighborhood.

transitivity(graph = pnet, type = 'local', vids = 'spik;speak') |> round(3) # for a specific node in the network 
## [1] 0.218
# if you do not specify the vids argument then you get a value for all nodes in the network, ordered by V(pnet)$name 

A couple of things to note:

  1. It is important to specify type = local for local clustering coefficients, as compared to the global clustering coefficient of the entire graph (this is a macro-level measure that we will visit later)

  2. Many of these functions contain additional arguments for indicating whether to consider the directionality and weights of the edges. If your graph is undirected and unweighted, these are ignored by default. If your graph is directed and weighted, you can indicate whether to include or exclude this information for the computation of the network measure.

Local Clustering Coefficient (weighted)

If you have a weighted network, you can compute local clustering coefficients using Barrat et al.’s (2004) generalization of transitivity to weighted networks by specifying type = 'weighted'. If your network is unweighted, the generalization will return the unweighted C (see example of ‘speak’ below).

# weighted network 
transitivity(graph = snet, type = 'local', vids = 'cheese') |> round(3) 
## [1] 0.043
transitivity(graph = snet, type = 'weighted', vids = 'cheese') |> round(3) 
## [1] 0.056
# unweighted network 
transitivity(graph = pnet, type = 'local', vids = 'spik;speak') |> round(3)
## [1] 0.218
transitivity(graph = pnet, type = 'weighted', vids = 'spik;speak') |> round(3) # no difference with the previous
## [1] 0.218

Closeness Centrality

Closeness centrality of node i is the inverse of the average of the length of the shortest path between node i and all other nodes in the network. If a node has high closeness centrality, it means that on average, it takes few steps to travel from that node to all other nodes in the network. If a node has low closeness centrality, it means that on average, it takes more steps to travel from that node to all other nodes in the network.

Closeness centrality is commonly viewed as an indicator of the accessibility of a node in the network from all other locations in the network.

This is a famous network (Krackhardt’s Kite) that nicely illustrates the differences between degree, closeness, and betweenness centrality.

# closeness centralities for directed networks, ignoring weights  
closeness(graph = snet, normalized = T, mode = 'all', weights = NA) |> head() # both in- and out-
##       age      aged      ages     aging  american appetizer 
## 0.5060241 0.5072464 0.5023923 0.5060241 0.5134474 0.5121951
closeness(graph = snet, normalized = T, mode = 'in', weights = NA) |> head() # only incoming edges considered 
##       age      aged      ages     aging  american appetizer 
## 0.6666667 0.6666667       NaN 0.5000000 0.2790698 0.3279743
closeness(graph = snet, normalized = T, mode = 'out', weights = NA) |> head() # only outgoing edges considered
##       age      aged      ages     aging  american appetizer 
## 0.3380282 0.3503650 0.3317422 0.3333333 0.3520408 0.3650794
# weights are considered by default if graph has a weight attribute 
closeness(graph = snet, normalized = T, mode = 'all') |> head()
##       age      aged      ages     aging  american appetizer 
##  18.46966  14.54294  18.60053  18.48592  19.84877  17.90281

Note that closeness centrality can only be meaningfully computed for connected graphs (so that a path exists between any pair of nodes). If there are distinct network components, this means that for some sets of node pairs, the path between them does not exist and closeness cannot be computed. Usually, network scientists focus their analysis on the largest connected component of the network and ignore the smaller connected components (viewed as outliers).

It is typical to have normalized = T so that the values are normalized with respect to the size of the network. As usual, you can specify the mode and weights arguments accordingly if you have directed/weighted networks to get the corresponding versions of closeness centrality computed. However, caution is needed as the interpretation of weights in this context is to interpret them as distances rather than connection strengths: higher weights = longer distances (From igraph manual: “If the graph has a weight edge attribute, then this is used by default. Weights are used for calculating weighted shortest paths, so they are interpreted as distances.”). It is highly recommended to read the manual carefully to understand the measures that are being computed.

Relevant finding in psychology: Siew (2018) showed that the closeness centrality of words in an orthographic similarity network influenced word naming and visual lexical decision performance differently. Words of higher closeness centralities were responded to more quickly in lexical decision, but were named more slowly.

Betweenness Centrality

Betweenness centrality is a measure of the degree to which nodes stand in between each other. A node with a high betweenness centrality is a node that is frequently found in the short paths of other pairs of nodes in the network. In contrast, a node with a low betweenness centrality is a node that is not usually found in the short paths of node pairs. Betweeenness can be viewed as an indicator if whether a node represents a “bottleneck” in the system.

# undirected, unweighted network 
betweenness(graph = pnet, normalized = T, weights = NA, directed = F) |> head()
## xpik;apeak  biC;beach   sid;cede    iC;each  liC;leach       pi;p 
## 0.00000000 0.00000000 0.01730678 0.00000000 0.00000000 0.00000000
# directed, weighted network 
betweenness(graph = snet, normalized = T, weights = NULL, directed = T) |> head() # use weight and direction
##          age         aged         ages        aging     american    appetizer 
## 0.0002050581 0.0009881305 0.0000000000 0.0001367054 0.0103941672 0.0098454470

The same considerations (about connected graphs, additional arguments for weighted and directed graphs, normalization, interpretation of weights as distances) from the closeness centrality section applies to this section as well.

Page Rank Centrality

PageRank is a centrality measure developed by Google to rank webpages (the historic paper describing the algorithm can be viewed here). The general idea is that a random walker will traverse the network space and their paths are biased by the link connectivity structure of the network. The random walker restarts the walk after some time (simulating “boredom” of the surfer). The number of visits received by a node provides an indicator of its importance in the network. Intuitively, we expect that nodes have a high PageRank if there are many nodes that point to it, or if there are nodes that point to it that themselves have a high PageRank.

# undirected, unweighted network 
page_rank(graph = pnet, directed = F, weights = NA)$vector |> head()
## xpik;apeak  biC;beach   sid;cede    iC;each  liC;leach       pi;p 
## 0.01085805 0.02109911 0.02350068 0.02109911 0.02109911 0.02849254
# directed, weighted network 
page_rank(graph = snet, directed = T, weights = NULL)$vector |> head()
##          age         aged         ages        aging     american    appetizer 
## 0.0016034240 0.0012433152 0.0007545644 0.0009712994 0.0011928822 0.0008034249

The weights and directed arguments can be adjusted depending on your graph type. It is important to note that the interpretation of edge weights here is that of “connection strength” (from igraph manual: “This function interprets edge weights as connection strengths. In the random surfer model, an edge with a larger weight is more likely to be selected by the surfer.”). This is different from the “distance” interpretation of edge weights by closeness and betweenness.

Relevant finding in psychology: Griffiths et al. (2007) showed that Page Rank centralities of words in a word association network provided good predictions for the words generated by participants in a letter fluency task.

Meso-level (community structure)

A common feature of many real-world networks is that they have community structure. Nodes are considered to be part of the same community if the density of connections among those nodes is relatively higher than the density of connections between nodes from different communities (Newman, 2006).

Modularity, Q, is a measure of the density of links inside communities in relation to the density of links between communities (Fortunato, 2010). Networks with higher Q are said to show strong evidence of community structure.

Communities are depicted in different colors from another famous network: Zachary’s Karate Club Network

How do network scientists “find” communities in networks?

Many community detection methods have been developed by network scientists to detect communities in networks. Each differs in their implementation, and reflects the creator’s implicit definition of what is a community. In this tutorial we go through only one of these methods (Louvain) to demonstrate an example of community detection.

If you are interested to learn more about community detection, check out Fortunato (2010) who provided a comprehensive comparison of various community detection techniques.

Louvain method (“greedy, maximization method”)

The core idea behind this method is that communities are essentially “mergers” of small communities (Blondel et al., 2008), reflecting the self-similar nature of complex networks.

  1. Each node is assigned to one community such that there are as many communities as there are nodes. Then remove node i from its community and placing it in the community of the neighbor which yields the greatest gain in modularity.
  • repeat for all nodes in the network
  1. A new network is built where nodes are the communities found in the previous phase. Repeat Step 1.
  • repeat Step 1 and 2 until it is not possible to further increase the value of Q
set.seed(8)

# run the community detection algorithm 
results_louvain <- cluster_louvain(graph = pnet)

# overall results 
modularity(results_louvain)
## [1] 0.5795028
sizes(results_louvain)
## Community sizes
## 1 2 3 4 5 
## 9 7 8 9 6
# specific community membership for each node 
cbind(
  results_louvain$names,
  results_louvain$membership
) 
##       [,1]          [,2]
##  [1,] "xpik;apeak"  "1" 
##  [2,] "biC;beach"   "2" 
##  [3,] "sid;cede"    "3" 
##  [4,] "iC;each"     "2" 
##  [5,] "liC;leach"   "2" 
##  [6,] "pi;p"        "4" 
##  [7,] "p@C;patch"   "5" 
##  [8,] "pis;peace"   "4" 
##  [9,] "piC;peach"   "2" 
## [10,] "pik;peak"    "4" 
## [11,] "pil;peal"    "4" 
## [12,] "piz;pease"   "4" 
## [13,] "pit;peat"    "4" 
## [14,] "pin;peen"    "4" 
## [15,] "pip;peep"    "4" 
## [16,] "piv;peeve"   "4" 
## [17,] "pRC;perch"   "5" 
## [18,] "pIC;pitch"   "5" 
## [19,] "poC;poach"   "5" 
## [20,] "pWC;pouch"   "5" 
## [21,] "priC;preach" "2" 
## [22,] "pUC;putsch"  "5" 
## [23,] "riC;reach"   "2" 
## [24,] "sik;seek"    "1" 
## [25,] "slik;sleek"  "1" 
## [26,] "snik;sneak"  "1" 
## [27,] "sped;spade"  "3" 
## [28,] "spik;speak"  "1" 
## [29,] "spEk;speck"  "1" 
## [30,] "spEd;sped"   "3" 
## [31,] "spiC;speech" "3" 
## [32,] "spid;speed"  "3" 
## [33,] "spYk;spike"  "1" 
## [34,] "spok;spoke"  "1" 
## [35,] "spuk;spook"  "1" 
## [36,] "sp^d;spud"   "3" 
## [37,] "stid;steed"  "3" 
## [38,] "swid;swede"  "3" 
## [39,] "tiC;teach"   "2"

Saving the community detection results as a communities object enables the use of special functions like modularity() and sizes() to obtain the modularity of the network and its community sizes. I have also included code that shows how to extract the community memberships of all nodes in the network for further analysis. This applies to the other community detection algorithms as well.

Relevant finding in psychology: Siew (2013) found robust community structure in the phonological network, and words in the same community tended to share similar lexical and phonological properties.

Macro-level (network-level)

In this section, we will review network science measures that describe the overall or global structure of the entire network. You can think of these measures as providing a “bird’s eye view” of your network, and they are useful for comparing different network representations.

Average Shortest Path Length

Average shortest path length (ASPL) refers to the mean of the shortest possible path between all possible pairs of nodes in the network. (This loosely corresponds to the idea of “six degrees of separation” in social networks.)

Example depicting the shortest path between nodes 25 and 16.

# undirected, unweighted network 
average.path.length(graph = pnet) 
## [1] 2.557355
# an alternative function - both give the same result 
mean_distance(graph = pnet)
## [1] 2.557355
# directed, weighted network 
mean_distance(graph = snet, weights = NULL, directed = T) # consider weights and direction
## [1] 0.1090017
mean_distance(graph = snet, weights = NULL, directed = F) # ignore direction 
## [1] 0.06239856
mean_distance(graph = snet, weights = NA, directed = T) # ignore weights 
## [1] 2.926504

Relevant finding in psychology: Siew (2018) showed that concept networks (constructed from concept maps generated by students) with larger average shortest path lengths were associated with higher quiz scores, after controlling for network size.

Global Clustering Coefficient

Global clustering coefficient refers to the number of closed triangles in the network relative to the number of possible triangles. It is a measure of overall level of local connectivity among nodes in the network.

A simple way of thinking about this concept is that it is measuring the probability that each pair of “friends” of a given node are also friends with each other.

transitivity(graph = pnet, type = 'global')
## [1] 0.6805869
transitivity(graph = snet, type = 'global')
## [1] 0.1588113

Small World Index

The term “small world” has a specific meaning in network science as compared to the layperson’s. A network is considered to have small world characteristics if (i) its ASPL is shorter than that of a randomly generated network with the same number of nodes and edges, and (ii) its global C is larger than that of a randomly generated network with the same number of nodes and edges. There are various ways to compute a value that quantifies the “small worldness” of a network, although we do not cover them here (see Humphries and Gurney, 2008, for an example, and Neal, 2017, for a comparison of different methods).

The main take home message is that a small world network has high levels of local clustering (nodes whose neighbors are also neighbors of each other), but there also exists a number of shortcuts that drastically reduces the overall distances/path lengths between nodes. See below for an illustration of this idea.

Network Density

Network density refers to the ratio of the number of (existing) edges and the number of possible edges among nodes in the network.

Simple example of networks with lower and higher network densities.

graph.density(graph = pnet)
## [1] 0.1632928
graph.density(graph = snet)
## [1] 0.02988039

Network Diameter

Network diameter refers to length of the longest shortest path between nodes in the network. Instead of getting the mean of all the shortest paths as you did in ASPL, what is the maximum length of those short paths?

Simple example of networks with higher and lower network diameters

# undirected, unweighted graph 
diameter(graph = pnet)
## [1] 4
# directed, weighted graph 
diameter(graph = snet, directed = T, weights = NULL) # consider weights and direction
## [1] 0.88
diameter(graph = snet, directed = F, weights = NULL) # ignore direction 
## [1] 0.56
diameter(graph = snet, directed = T, weights = NA) # ignore weights 
## [1] 7

Additional Resources

Ognyanova, K. (2021) Network visualization with R. Retrieved from www.kateto.net/network-visualization. https://kateto.net/network-visualization

The official igraph manual (v.1.3.4). https://igraph.org/r/doc/

Gephi: A multi-platform, free to download GUI app for network analysis and visualization. https://gephi.org/

References

Barrat, A., Barthélemy, M., Pastor-Satorras, R., & Vespignani, A. (2004). The architecture of complex weighted networks. Proceedings of the National Academy of Sciences, 101(11), 3747–3752. https://doi.org/10.1073/pnas.0400087101

Blondel, V. D., Guillaume, J. L., Lambiotte, R., & Lefebvre, E. (2008). Fast unfolding of communities in large networks. Journal of Statistical Mechanics: Theory and Experiment, 2008(10), P10008.

Chan, K. Y., & Vitevitch, M. S. (2009). The influence of the phonological neighborhood clustering coefficient on spoken word recognition. Journal of Experimental Psychology: Human Perception and Performance, 35(6), 1934–1949. https://doi.org/10.1037/a0016902

De Deyne, S., Navarro, D. J., Perfors, A., Brysbaert, M., & Storms, G. (2019). The “Small World of Words” English word association norms for over 12,000 cue words. Behavior Research Methods, 51, 987–1006.

Fortunato, S. (2010). Community detection in graphs. Physics Reports, 486(3-5), 75-174.

Humphries, M. D., & Gurney, K. (2008). Network ‘small-world-ness’: A quantitative method for determining canonical network equivalence. PloS One, 3(4).

Griffiths, T. L., Steyvers, M., & Firl, A. (2007). Google and the Mind: Predicting Fluency With PageRank. Psychological Science, 18(12), 1069–1076. https://doi.org/10.1111/j.1467-9280.2007.02027.x

Luce, P. A., & Pisoni, D. B. (1998). Recognizing spoken words: The Neighborhood Activation Model. Ear and Hearing, 19(1), 1–36.

Neal, Z. P. (2017). How small is it? Comparing indices of small worldliness. Network Science, 5(1), 30–44. https://doi.org/10.1017/nws.2017.5

Newman, M. E. (2006). Modularity and community structure in networks. Proceedings of the National Academy of Sciences, 103(23), 8577-8582.

Siew, C. S. Q. (2013). Community structure in the phonological network. Frontiers in Psychology, 4, 553.

Siew, C. S. Q. (2018). The orthographic similarity structure of English words: Insights from network science. Applied Network Science, 3(1), 13.

Siew, C. S. Q. (2018). Using network science to analyze concept maps of psychology undergraduates. Applied Cognitive Psychology.

Vitevitch, M. S. (2008). What can graph theory tell us about word learning and lexical retrieval? Journal of Speech, Language, and Hearing Research, 51(2), 408–422. https://doi.org/10.1044/1092-4388(2008/030)

LS0tCnRpdGxlOiAiQ29tcENvZyAyMDIzIE5ldHdvcmsgQW5hbHlzaXMgVHV0b3JpYWwiCnN1YnRpdGxlOiAiTW9kZWxpbmcgcHN5Y2hvbG9naWNhbCBkYXRhIHdpdGggY29nbml0aXZlIG5ldHdvcmtzIgphdXRob3I6ICJDeW50aGlhIFNpZXciCmRhdGU6ICIxc3QgRmViIDIwMjMiCm91dHB1dDoKICBodG1sX2RvY3VtZW50OgogICAgdG9jOiBUUlVFCiAgICB0b2NfZmxvYXQ6IFRSVUUKICAgIGRmX3ByaW50OiBwYWdlZAogICAgY29kZV9kb3dubG9hZDogdHJ1ZQotLS0KIyBTZXQgdXAgCgpgYGB7ciBzZXQtdXB9CmxpYnJhcnkoaWdyYXBoKQoKbG9hZCgnZGF0YS9leGFtcGxlLWRhdGEtY29tcGNvZy5SRGF0YScpCmBgYAoKVGhlcmUgc2hvdWxkIGJlIDMgb2JqZWN0cyBsb2FkZWQgaW50byB5b3VyIFIgd29ya3NwYWNlOgoKLSBgcG5ldGAKLSBgc25ldGAgCi0gYHBuZXRfZWRnZWxpc3RgCgpgcG5ldGAgcmVmZXJzIHRvIGEgc2VjdGlvbiBvZiB0aGUgcGhvbm9sb2dpY2FsIG5ldHdvcmsgZmlyc3QgZGVzY3JpYmVkIGJ5IFZpdGV2aXRjaCAoMjAwOCkuIFRoZSBub2RlcyByZXByZXNlbnQgRW5nbGlzaCB3b3JkcywgYW5kIGVkZ2VzIGNvbm5lY3Qgd29yZHMgdGhhdCBhcmUgcGhvbm9sb2dpY2FsIG5laWdoYm9ycyBvZiBlYWNoIG90aGVyIGJhc2VkIG9uIHRoZSAxLWVkaXQgZGlzdGFuY2UgbWV0cmljIGNvbXB1dGVkIG9uIHRoZWlyIHBob25vbG9naWNhbCB0cmFuc2NyaXB0aW9ucyAoTHVjZSAmIFBpc29uaSwgMTk5OCkuIEUuZy4sIC9rXEB0Ly0tL2tcQHAvIGFyZSBuZWlnaGJvcmluZyBub2Rlcy4gU3BlY2lmaWNhbGx5LCB0aGlzIG5ldHdvcmsgaXMgdGhlIDItaG9wIG5ldHdvcmsgb2YgdGhlIHdvcmQgJ3NwZWVjaCcgLSBpbiBhZGRpdGlvbiB0byAnc3BlZWNoJyBpdHNlbGYsIGl0cyBpbW1lZGlhdGUgcGhvbm9sb2dpY2FsIG5laWdoYm9ycyBhbmQgdGhlIG5laWdoYm9ycyBvZiBpdHMgbmVpZ2hib3JzIGFyZSBpbmNsdWRlZCBpbiB0aGlzIHJlcHJlc2VudGF0aW9uLgoKYHBuZXRfZWRnZWxpc3RgIGlzIHRoZSByYXcgZGF0YSB0aGF0IGlzIHVzZWQgdG8gY3JlYXRlIGBwbmV0YC4gSXQgaXMgYW4gZWRnZWxpc3Qgd2hlcmVieSBlYWNoIHJvdyBkZXBpY3RzIG9uZSBlZGdlIGluIHRoZSBuZXR3b3JrLgoKYHNuZXRgIHJlZmVycyB0byBhIHNlY3Rpb24gb2YgdGhlIHdvcmQgYXNzb2NpYXRpb24gbmV0d29yayB1c2luZyBkYXRhIGZyb20gRGUgRGV5bmUgZXQgYWwuICgyMDIwKS4gVGhlIG5vZGVzIHJlcHJlc2VudCBFbmdsaXNoIHdvcmRzLCBhbmQgZWRnZXMgY29ubmVjdCB3b3JkcyB0aGF0IGFyZSBwcm9kdWNlZCBhcyBmcmVlIGFzc29jaWF0aW9ucyBvZiBvdGhlciB3b3Jkcy4gRS5nLiwgImNhdCItLSJkb2ciIGFyZSBuZWlnaGJvcmluZyBub2Rlcy4gVGhpcyBuZXR3b3JrIGhhcyBlZGdlcyB3aXRoIDIgaW50ZXJlc3RpbmcgcHJvcGVydGllcy4gKGkpIEVhY2ggZWRnZSBoYXMgYSBgd2VpZ2h0YCBhdHRyaWJ1dGUgdGhhdCBjb3JyZXNwb25kcyB0byB0aGUgYXNzb2NpYXRpdmUgc3RyZW5ndGggb2YgdHdvIG5vZGVzLCBvciB0aGUgcHJvcG9ydGlvbiBvZiBwYXJ0aWNpcGFudHMgd2hvIHByb3ZpZGVkIGEgc3BlY2lmaWMgcmVzcG9uc2UgdG8gdGhlIGN1ZSB3b3JkLiAoaWkpIFRoZSBlZGdlcyBhcmUgYWxzbyBgZGlyZWN0ZWRgIHN1Y2ggdGhlIGRpcmVjdGlvbiBnb2VzICpmcm9tKiB0aGUgY3VlIHdvcmQgKnRvKiB0aGUgcmVzcG9uc2Ugd29yZCwgaS5lLiwgImNhdCItPiJkb2ciLiBTcGVjaWZpY2FsbHksIHRoaXMgbmV0d29yayBpcyB0aGUgMS1ob3AgbmV0d29yayBvZiB0aGUgd29yZCAnY2hlZXNlJyAtIGluIGFkZGl0aW9uIHRvICdjaGVlc2UnIGl0c2VsZiwgaXRzIGltbWVkaWF0ZSBhc3NvY2lhdGVzIGFuZCB0aGUgY3VlIHdvcmRzIHRoYXQgbGVkIHRvIHRoZSByZXNwb25zZSAnY2hlZXNlJyBhcmUgaW5jbHVkZWQgaW4gdGhpcyByZXByZXNlbnRhdGlvbi4gU2VlIGh0dHBzOi8vc21hbGx3b3JsZG9md29yZHMub3JnL2VuL3Byb2plY3QvcmVzZWFyY2ggZm9yIG1vcmUgaW5mb3JtYXRpb24uIAoKYGBge3IgcHJldmlld30Kc3VtbWFyeShwbmV0KSAjIHVuZGlyZWN0ZWQsIHVud2VpZ2h0ZWQgZWRnZXMgCgpzdW1tYXJ5KHNuZXQpICMgZGlyZWN0ZWQsIHdlaWdodGVkIGVkZ2VzCmBgYAoKTm90aWNlIHRoZSB0d28gbnVtYmVycyBvbiB0aGUgZmlyc3Qgcm93OiBUaGUgZmlyc3QgdGVsbHMgeW91IHRoZSBudW1iZXIgb2Ygbm9kZXMgb3IgdmVydGljZXMgaW4gdGhlIG5ldHdvcmssIHRoZSBzZWNvbmQgdGVsbHMgeW91IHRoZSBudW1iZXIgb2YgZWRnZXMgb3IgbGlua3MuIAoKVGhlcmUgYXJlIGFsc28gc29tZSBjeXB0aWMgbG9va2luZyBjaGFyYWN0ZXJzLiBMZXQncyB1bnBhY2sgdGhhdC4gVGhlIGZpcnN0IGNoYXJhY3RlciBpcyBlaXRoZXIgIlUiIG9yICJEIiBhbmQgdGVsbHMgeW91IHdoZXRoZXIgdGhlIGVkZ2VzIGFyZSAidW5kaXJlY3RlZCIgb3IgImRpcmVjdGVkIi4gVGhlIHNlY29uZCBjaGFyYWN0ZXIgIk4iIChpZiBwcmVzZW50KSB0ZWxscyB5b3UgdGhhdCB0aGUgbm9kZXMgaGF2ZSAibmFtZXMiLiBUaGUgdGhpcmQgY2hhcmFjdGVyICJXIiAoaWYgcHJlc2VudCkgdGVsbHMgeW91IHRoYXQgdGhlIGVkZ2VzIGFyZSB3ZWlnaHRlZC4gVGhlIGZpbmFsIGNoYXJhY3RlciBpcyBibGFuayB1bmxlc3MgeW91IGhhdmUgYSBzcGVjaWFsIHR5cGUgb2YgbmV0d29yayBrbm93biBhcyBhIGJpcGFydGl0ZSBuZXR3b3JrIChpbiB3aGljaCBjYXNlIHRoZSBmb3VydGggY2hhcmFjdGVyIGlzICJCIikuIAoKT24gdGhlIHNlY29uZCByb3csIGFkZGl0aW9uYWwgaW5mb3JtYXRpb24gYWJvdXQgbm9kZSBvciBlZGdlIGF0dHJpYnV0ZXMgY2FuIGJlIGZvdW5kIGlmIHRoZXkgaGF2ZSBiZWVuIHNwZWNpZmllZCBpbiB0aGUgY29uc3RydWN0aW9uIG9mIHRoZSBuZXR3b3JrLiBCb3RoIG5ldHdvcmtzIGhhdmUgbm9kZSBuYW1lcywgYW5kIHRoZSBzZW1hbnRpYyBuZXR3b3JrIGhhcyBhbiBlZGdlIGF0dHJpYnV0ZSBrbm93biBhcyBgd2VpZ2h0YC4gICAKCiMjIExvYWRpbmcgYSBuZXR3b3JrIGludG8gYGlncmFwaGAKClRoZXJlIGFyZSBhIG51bWJlciBvZiBkaWZmZXJlbnQgd2F5cyB0byBjb252ZXJ0IHlvdXIgcmF3IGRhdGEgaW50byBhIG5ldHdvcmsgcmVwcmVzZW50YXRpb24gdGhhdCBgaWdyYXBoYCBjYW4gYW5hbHl6ZS4gVGhpcyBkYXRhIGZpcnN0IG5lZWRzIHRvIGJlIG9yZ2FuaXplZCBhcyBhbiBlZGdlbGlzdCBvciBhbiBhZGphY2VuY3kgbWF0cml4IG9yIGFuIGFkamFjZW5jeSBsaXN0IGFuZCB0aGVuIGxvYWRlZCBpbnRvIFJTdHVkaW8uIEJlbG93IEkgcHJvdmlkZSBhIHF1aWNrIGV4YW1wbGUgb2YgaG93IGFuICoqZWRnZWxpc3QqKiBjYW4gYmUgY29udmVydGVkIGludG8gYSBuZXR3b3JrLiAKCmBgYHtyfQpoZWFkKHBuZXRfZWRnZWxpc3QpICMgcHJldmlldyBmaXJzdCBmZXcgcm93cyBvZiB0aGUgZWRnZWxpc3QgCgpwbmV0MiA8LSBncmFwaF9mcm9tX2VkZ2VsaXN0KHBuZXRfZWRnZWxpc3QsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGlyZWN0ZWQgPSBGKSAjIHRoZSBlZGdlcyBhcmUgdW5kaXJlY3RlZCBpbiB0aGlzIG5ldHdvcmsgCgpzdW1tYXJ5KHBuZXQyKQpgYGAKClRoZXJlIGFyZSBtYW55IHVzZWZ1bCBmdW5jdGlvbnMgaW4gYGlncmFwaGAgKHRob3NlIHRoYXQgYmVnaW4gd2l0aCBgZ3JhcGhfZnJvbV8qYCkgZm9yIGNvbnZlcnRpbmcgdmFyaW91cyBraW5kcyBvZiBkYXRhc2V0cyBpbnRvIG5ldHdvcmtzLiBUaGUgYGlncmFwaGAgbWFudWFsIGlzIGEgZ29vZCBwbGFjZSB0byBzdGFydCBsZWFybmluZyBhYm91dCB0aGVzZSBmdW5jdGlvbnMgYW5kIHRoZWlyIGFyZ3VtZW50cyB0byBzcGVjaWZ5IGVkZ2Ugb3Igbm9kZSBhdHRyaWJ1dGVzIG9mIHRoZSBuZXR3b3JrLiBPdXRzaWRlIG9mIGBpZ3JhcGhgIHlvdSB3aWxsIHByb2JhYmx5IGhhdmUgdG8gc3BlbmQgc29tZSB0aW1lIGN1cmF0aW5nIGFuZCB3cmFuZ2xpbmcgeW91ciBkYXRhIHNvIHRoYXQgaXQgaXMgaW4gdGhlIHJpZ2h0IGZvcm1hdHMgZm9yIGBpZ3JhcGhgLiAKCiMjIFZpc3VhbGl6YXRpb25zIAoKSGVyZSBhcmUgdmlzdWFsaXphdGlvbnMgb2YgdGhlIG5ldHdvcmtzIHdlIHdpbGwgcGxheSBhcm91bmQgd2l0aCB0b2RheS4gCgpgYGB7cn0KcGxvdChwbmV0LAogICAgIHZlcnRleC5mcmFtZS5jb2xvciA9ICd3aGl0ZScsCiAgICAgdmVydGV4LmxhYmVsLmNvbG9yID0gJ2dyZXkzMCcsCiAgICAgZWRnZS5jb2xvciA9ICdibGFjaycsCiAgICAgdmVydGV4LmxhYmVsID0gZ3N1YignW1s6cHJpbnQ6XV0rOycsICcnLCBWKHBuZXQpJG5hbWUpLCAjIHJlZ2V4IHRvIG9ubHkgcHJpbnQgdGhlIHdvcmQgbmFtZXMgYW5kIG5vdCB0cmFuc2NyaXB0aW9ucwogICAgIGxheW91dCA9IGxheW91dF93aXRoX2xnbCwKICAgICBmcmFtZSA9IFRSVUUsCiAgICAgbWFyZ2luID0gYygwLDAsMCwwKSwKICAgICBtYWluID0gJ0EgcGFydGlhbCBwaG9ub2xvZ2ljYWwgbmV0d29yayBvZiBFbmdsaXNoIHdvcmRzJykKYGBgCgpgYGB7cn0KcGxvdChzbmV0LAogICAgIHZlcnRleC5mcmFtZS5jb2xvciA9ICd3aGl0ZScsCiAgICAgdmVydGV4LmxhYmVsLmNvbG9yID0gJ2dyZXkzMCcsCiAgICAgZWRnZS5jb2xvciA9ICdibGFjaycsCiAgICAgdmVydGV4LmNvbG9yID0gJ3NlYWdyZWVuJywKICAgICB2ZXJ0ZXguc2l6ZSA9IDUsCiAgICAgZWRnZS5hcnJvdy5zaXplID0gMC40LAogICAgIGxheW91dCA9IGxheW91dF93aXRoX2dyYXBob3B0LAogICAgIGZyYW1lID0gVFJVRSwKICAgICBtYXJnaW4gPSBjKDAsMCwwLDApLAogICAgIG1haW4gPSAnQSBwYXJ0aWFsIHNlbWFudGljIG5ldHdvcmsnKQpgYGAKCiMjIERpc2NsYWltZXJzCgpEdWUgdG8gbGltaXRlZCB0aW1lLCBJIGFzc3VtZSB0aGF0IHlvdSBoYXZlIHNvbWUgZmFtaWxpYXJpdHkgd2l0aCBSIGFuZCBSU3R1ZGlvLiBBIGdlbnRsZSBpbnRyb2R1Y3Rpb24gdG8gUiBwcm9ncmFtbWluZyBjYW4gYmUgZm91bmQgaGVyZTogaHR0cHM6Ly9wc3lyLmRqbmF2YXJyby5uZXQvCgpJIGFsc28gY2hvb3NlIHRvIG5vdCBjb3ZlciBpbiBkZXRhaWwgYSBudW1iZXIgb2YgaW1wb3J0YW50IHRvcGljcyBzdWNoIGFzIGhvdyB0byBjb252ZXJ0IHlvdXIgcmF3IGRhdGEgaW50byBhbiBgaWdyYXBoYCBuZXR3b3JrIG9iamVjdCwgbmV0d29yayB2aXN1YWxpemF0aW9uIGluIGBpZ3JhcGhgIChmb3IgYSBncmVhdCBpbnRyb2R1Y3Rpb24gdG8gdGhpcyB0b3BpYywgc2VlIGh0dHBzOi8va2F0ZXRvLm5ldC9uZXR3b3JrLXZpc3VhbGl6YXRpb24pLCBhbmQgb3RoZXIgbWV0aG9kcyBvZiBxdWFudGlmeWluZyB0aGUgY29tbXVuaXR5IHN0cnVjdHVyZSBvZiB0aGUgbmV0d29yayAoaS5lLiwgbWVzby1sZXZlbCkuIFNvbWUgb2YgdGhlc2UgdG9waWNzIGFyZSBicmllZmx5IHRvdWNoZWQgb24gaW4gYSBkaWZmZXJlbnQgdHV0b3JpYWwgYW5kIHlvdSBjYW4gZmluZCB0aGUgbWF0ZXJpYWxzIGhlcmU6IGh0dHBzOi8vdnBmLW5ldHNjaS5uZXRsaWZ5LmFwcC9wYXJ0Mi1kZW1vLmh0bWwgCgojIE1lYXN1cmluZyB0aGUgbmV0d29yayAKCk9uY2Ugd2UgaGF2ZSBhIG5ldHdvcmsgcmVwcmVzZW50YXRpb24sIHRoZSB0b29scyBvZiBuZXR3b3JrIHNjaWVuY2UgY2FuIGJlIGFwcGxpZWQgdG8gYW5hbHl6ZSB0aGUgbmV0d29ya3MgaW4gZGlmZmVyZW50IHdheXMuIEluIHRoaXMgdHV0b3JpYWwgd2UgZm9jdXMgb24gYSAqZGVzY3JpcHRpdmUqIGFuYWx5c2lzIG9mIHRoZSBuZXR3b3JrIGFuZCByZXZpZXcgdmFyaW91cyBuZXR3b3JrIG1lYXN1cmVzIHRoYXQgY2FuIGJlIHVzZWQgdG8gZGVzY3JpYmUgb3IgcXVhbnRpZnkgbmV0d29yayBzdHJ1Y3R1cmUgYXQgdGhyZWUgZGlmZmVyZW50IGxldmVscyBvZiB0aGUgbmV0d29yazogdGhlIG1pY3JvLWxldmVsIChyZWZlcnJpbmcgdG8gdGhlIGxvY2FsIHN0cnVjdHVyZSBhbmQgb3RoZXIgcHJvcGVydGllcyBvZiBpbmRpdmlkdWFsIG5vZGVzKSwgdGhlIG1lc28tbGV2ZWwgKHN1Ymdyb3VwcyBvciBjbHVzdGVycyBvZiBub2RlcyksIGFuZCB0aGUgbWFjcm8tbGV2ZWwgKHJlZmVycmluZyB0byB0aGUgb3ZlcmFsbCBvciBnbG9iYWwgc3RydWN0dXJlIG9mIHRoZSBuZXR3b3JrKS4gCgohW10oaHR0cHM6Ly93d3cubWRwaS5jb20vZWR1Y2F0aW9uL2VkdWNhdGlvbi0xMC0wMDEwMS9hcnRpY2xlX2RlcGxveS9odG1sL2ltYWdlcy9lZHVjYXRpb24tMTAtMDAxMDEtZzAwMS5wbmcpCgojIyBNaWNyby1sZXZlbCAobm9kZS1sZXZlbCkKCk1pY3JvLWxldmVsIG5ldHdvcmsgbWVhc3VyZXMgcHJvdmlkZSB5b3Ugd2l0aCBpbmZvcm1hdGlvbiBhYm91dCBzcGVjaWZpYyBub2RlcyBpbiB0aGUgbmV0d29yay4gVGhlc2UgYXJlIGdlbmVyYWxseSBrbm93biBhcyBjZW50cmFsaXR5IG1lYXN1cmVzIGluIHRoZSBuZXR3b3JrIHNjaWVuY2UgbGl0ZXJhdHVyZS4gQ2VudHJhbGl0eSBpcyB0aGUgbmV0d29yayBzY2llbnRpc3QncyB3YXkgb2YgcXVhbnRpZnlpbmcgdGhlIHJlbGF0aXZlICJpbXBvcnRhbmNlIiBvZiBhIGdpdmVuIG5vZGUgcmVsYXRpdmUgdG8gb3RoZXIgbm9kZXMgaW4gdGhlIG5ldHdvcmsuIFRoZXJlIGFyZSBbbWFueV0oaHR0cDovL3NjaG9jaGFzdGljcy5uZXQvc25hL3BlcmlvZGljLmh0bWwpIGRpZmZlcmVudCBkZWZpbml0aW9ucyBvZiB3aGF0IGNvdW50cyBhcyAiY2VudHJhbCIsIGFzIHlvdSB3aWxsIHNlZSBpbiB0aGUgZm9sbG93aW5nIHN1YnNlY3Rpb25zLiBUaGVyZSBpcyBubyBzaW5nbGUgImNvcnJlY3QiIG9yICJiZXN0IiBtZXRyaWMgLSB3aGljaCBtZXRyaWNzIGFyZSBtb3N0IHVzZWZ1bCB0byB5b3Ugd2lsbCBkZXBlbmQgb24gdGhlIG5hdHVyZSBvZiB0aGUgc3lzdGVtIHRoYXQgeW91IGFyZSBtb2RlbGluZyBhcyB3ZWxsIGFzIHRoZSBuZXR3b3JrIGJlaGF2aW9yIHRoYXQgeW91IGludGVyZXN0ZWQgaW4uIAoKIyMjIERlZ3JlZSAodW53ZWlnaHRlZCBlZGdlcykKClRoZSAqKmRlZ3JlZSoqIG9mIG5vZGUgKmkqIHJlZmVycyB0byB0aGUgbnVtYmVyIG9mIGVkZ2VzIG9yIGxpbmtzIGNvbm5lY3RlZCB0byB0aGF0IG5vZGUuCgpJZiB5b3VyIG5ldHdvcmsgaGFzIGRpcmVjdGVkIGVkZ2VzLCAqaW4tZGVncmVlKiByZWZlcnMgdG8gdGhlIG51bWJlciBvZiBlZGdlcyB0aGF0IGFyZSBnb2luZyB0b3dhcmRzIHRoZSB0YXJnZXQgbm9kZSwgd2hlcmVhcyAqb3V0LWRlZ3JlZSogcmVmZXJzIHRvIHRoZSBudW1iZXIgb2YgZWRnZXMgdGhhdCBhcmUgZ29pbmcgYXdheSBmcm9tIHRoZSB0YXJnZXQgbm9kZS4gCgohW10oaHR0cHM6Ly93d3cudGxhYi5pdC9lbi9hbGxlZ2F0aS9oZWxwX2VuX29ubGluZS90bGFiX2ltYWdlL2luX291dF9kZWdyZWUuanBnKQoKYGBge3J9CiMgdW5kaXJlY3RlZCBuZXR3b3JrCmRlZ3JlZShncmFwaCA9IHBuZXQpICMgZm9yIGFsbCBub2RlcyBpbiB0aGUgbmV0d29yawoKZGVncmVlKGdyYXBoID0gc25ldCwgdiA9ICdjaGVlc2UnKSAjIGZvciBhIHNwZWNpZmljIG5vZGUgaW4gdGhlIG5ldHdvcmsgCgojIGRpcmVjdGVkIG5ldHdvcmsKZGVncmVlKGdyYXBoID0gc25ldCwgdiA9ICdjaGVlc2UnLCBtb2RlID0gJ2luJykgIyBpbi1kZWdyZWUgPSBpbmNvbWluZyBlZGdlcwpkZWdyZWUoZ3JhcGggPSBzbmV0LCB2ID0gJ2NoZWVzZScsIG1vZGUgPSAnb3V0JykgIyBvdXQtZGVncmVlID0gb3V0Z29pbmcgZWRnZXMgCmRlZ3JlZShncmFwaCA9IHNuZXQsIHYgPSAnY2hlZXNlJywgbW9kZSA9ICdhbGwnKSAjIGluLWRlZ3JlZSArIG91dC1kZWdyZWUKYGBgCgojIyMgU3RyZW5ndGggKHdlaWdodGVkIGVkZ2VzKQoKVGhlICoqc3RyZW5ndGgqKiBvZiBub2RlICppKiByZWZlcnMgdG8gdGhlIHN1bSBvZiBpdHMgYWRqYWNlbnQgZWRnZSAqd2VpZ2h0cyouIE9ubHkgYXBwbGljYWJsZSB0byB3ZWlnaHRlZCBuZXR3b3Jrcy4gCgpgYGB7cn0Kc3RyZW5ndGgoZ3JhcGggPSBzbmV0KSB8PiBoZWFkKDUpCgojIGZvciBkaXJlY3RlZCBuZXR3b3JrcwpzdHJlbmd0aChncmFwaCA9IHNuZXQsIHYgPSAnYWdlJywgbW9kZSA9ICdpbicpICMgaW4tZGVncmVlID0gaW5jb21pbmcgZWRnZXMKc3RyZW5ndGgoZ3JhcGggPSBzbmV0LCB2ID0gJ2FnZScsIG1vZGUgPSAnb3V0JykgIyBvdXQtZGVncmVlID0gb3V0Z29pbmcgZWRnZXMgCnN0cmVuZ3RoKGdyYXBoID0gc25ldCwgdiA9ICdhZ2UnLCBtb2RlID0gJ2FsbCcpICMgaW4tZGVncmVlICsgb3V0LWRlZ3JlZQpgYGAKCjxwIHN0eWxlPSJjb2xvcjpibHVlOyI+KlJlbGV2YW50IGZpbmRpbmcgaW4gcHN5Y2hvbG9neTogRGUgRGV5bmUgZXQgYWwuICgyMDE5KSBmb3VuZCB0aGF0IHN0cmVuZ3RoIChvcGVyYXRpb25hbGl6ZWQgYXMgYXNzb2NpYXRpb24gZnJlcXVlbmN5KSB3YXMgc3VwZXJpb3IgdG8sIG9yIGF0IGxlYXN0IHNpbWlsYXIgdG8sIHdvcmQgZnJlcXVlbmN5IGFzIGEgcHJlZGljdG9yIG9mIGxleGljYWwgZGVjaXNpb24gYW5kIHNlbWFudGljIGRlY2lzaW9uIHBlcmZvcm1hbmNlLio8L3A+CgojIyMgTG9jYWwgQ2x1c3RlcmluZyBDb2VmZmljaWVudCAodW53ZWlnaHRlZCkKClRoZSAqKmxvY2FsIGNsdXN0ZXJpbmcgY29lZmZpY2llbnQqKiwgKkMqLCBvZiBub2RlICppKiBtZWFzdXJlcyB0aGUgcmF0aW8gb2YgdGhlIGFjdHVhbCBudW1iZXIgb2YgZWRnZXMgZXhpc3RpbmcgYW1vbmcgbm9kZXMgZGlyZWN0bHkgY29ubmVjdGVkIHRvIHRoZSB0YXJnZXQgbm9kZSAqaSogdG8gdGhlIG51bWJlciBvZiBhbGwgcG9zc2libGUgZWRnZXMgYW1vbmcgdGhlc2Ugbm9kZXMuIAoKKkMqIHJhbmdlcyBmcm9tIDAgdG8gMS4gV2hlbiAqQyogPSAwLCBub25lIG9mIHRoZSBuZWlnaGJvcnMgb2YgYSB0YXJnZXQgbm9kZSBhcmUgbmVpZ2hib3JzIG9mIGVhY2ggb3RoZXIuIFdoZW4gKkMqID0gMSwgZXZlcnkgbmVpZ2hib3IgaXMgYWxzbyBhIG5laWdoYm9yIG9mIGFsbCB0aGUgb3RoZXIgbmVpZ2hib3JzIG9mIGEgdGFyZ2V0IHdvcmQuCgpZb3UgY2FuIHRoaW5rIG9mIHRoZSBsb2NhbCBjbHVzdGVyaW5nIGNvZWZmaWNpZW50IGFzIHByb3ZpZGluZyBhIG1lYXN1cmUgb2YgdGhlIGxldmVsIG9mIGludGVyY29ubmVjdGl2aXR5IGFtb25nIHRoZSBsb2NhbCBuZWlnaGJvcmhvb2Qgb2YgdGhlIG5vZGUuIAoKIVtdKGltZy9oY2MtbGNjLmpwZykKCipCb3RoIHdvcmRzIGhhdmUgdGhlIHNhbWUgbnVtYmVyIG9mIG5laWdoYm9ycywgYnV0IGRpZmZlcmVudCBsb2NhbCBjbHVzdGVyaW5nIGNvZWZmaWNpZW50cy4qCgo8cCBzdHlsZT0iY29sb3I6Ymx1ZTsiPipSZWxldmFudCBmaW5kaW5nIGluIHBzeWNob2xvZ3k6IENoYW4gJiBWaXRldml0Y2ggKDIwMDkpIHNob3dlZCB0aGF0IHdvcmRzIHdpdGggaGlnaGVyIGNsdXN0ZXJpbmcgY29lZmZpY2llbnRzIHdlcmUgcmVzcG9uZGVkIHRvIG1vcmUgc2xvd2x5IHRoYW4gd29yZHMgd2l0aCBsb3dlciBjbHVzdGVyaW5nIGNvZWZmaWNpZW50IGluIHNwb2tlbiB3b3JkIHJlY29nbml0aW9uIHRhc2tzIChldmVuIGFmdGVyIGNvbnRyb2xpbmcgZm9yIHRoZSBzaXplIG9mIHRoZSBwaG9ub2xvZ2ljYWwgbmVpZ2hib3Job29kLio8L3A+CgpgYGB7cn0KdHJhbnNpdGl2aXR5KGdyYXBoID0gcG5ldCwgdHlwZSA9ICdsb2NhbCcsIHZpZHMgPSAnc3BpaztzcGVhaycpIHw+IHJvdW5kKDMpICMgZm9yIGEgc3BlY2lmaWMgbm9kZSBpbiB0aGUgbmV0d29yayAKCiMgaWYgeW91IGRvIG5vdCBzcGVjaWZ5IHRoZSB2aWRzIGFyZ3VtZW50IHRoZW4geW91IGdldCBhIHZhbHVlIGZvciBhbGwgbm9kZXMgaW4gdGhlIG5ldHdvcmssIG9yZGVyZWQgYnkgVihwbmV0KSRuYW1lIApgYGAKCkEgY291cGxlIG9mIHRoaW5ncyB0byBub3RlOgoKMS4gSXQgaXMgaW1wb3J0YW50IHRvIHNwZWNpZnkgYHR5cGUgPSBsb2NhbGAgZm9yIGxvY2FsIGNsdXN0ZXJpbmcgY29lZmZpY2llbnRzLCBhcyBjb21wYXJlZCB0byB0aGUgZ2xvYmFsIGNsdXN0ZXJpbmcgY29lZmZpY2llbnQgb2YgdGhlIGVudGlyZSBncmFwaCAodGhpcyBpcyBhIFttYWNyby1sZXZlbCBtZWFzdXJlXSgjZ2xvYmFsLWNsdXN0ZXJpbmctY29lZmZpY2llbnQpIHRoYXQgd2Ugd2lsbCB2aXNpdCBsYXRlcikgCgoyLiBNYW55IG9mIHRoZXNlIGZ1bmN0aW9ucyBjb250YWluIGFkZGl0aW9uYWwgYXJndW1lbnRzIGZvciBpbmRpY2F0aW5nIHdoZXRoZXIgdG8gY29uc2lkZXIgdGhlIGRpcmVjdGlvbmFsaXR5IGFuZCB3ZWlnaHRzIG9mIHRoZSBlZGdlcy4gSWYgeW91ciBncmFwaCBpcyB1bmRpcmVjdGVkIGFuZCB1bndlaWdodGVkLCB0aGVzZSBhcmUgaWdub3JlZCBieSBkZWZhdWx0LiBJZiB5b3VyIGdyYXBoIGlzIGRpcmVjdGVkIGFuZCB3ZWlnaHRlZCwgeW91IGNhbiBpbmRpY2F0ZSB3aGV0aGVyIHRvIGluY2x1ZGUgb3IgZXhjbHVkZSB0aGlzIGluZm9ybWF0aW9uIGZvciB0aGUgY29tcHV0YXRpb24gb2YgdGhlIG5ldHdvcmsgbWVhc3VyZS4KCiMjIyBMb2NhbCBDbHVzdGVyaW5nIENvZWZmaWNpZW50ICh3ZWlnaHRlZCkKCklmIHlvdSBoYXZlIGEgd2VpZ2h0ZWQgbmV0d29yaywgeW91IGNhbiBjb21wdXRlIGxvY2FsIGNsdXN0ZXJpbmcgY29lZmZpY2llbnRzIHVzaW5nIEJhcnJhdCBldCBhbC4ncyAoMjAwNCkgZ2VuZXJhbGl6YXRpb24gb2YgdHJhbnNpdGl2aXR5IHRvIHdlaWdodGVkIG5ldHdvcmtzIGJ5IHNwZWNpZnlpbmcgYHR5cGUgPSAnd2VpZ2h0ZWQnYC4gSWYgeW91ciBuZXR3b3JrIGlzIHVud2VpZ2h0ZWQsIHRoZSBnZW5lcmFsaXphdGlvbiB3aWxsIHJldHVybiB0aGUgdW53ZWlnaHRlZCBDIChzZWUgZXhhbXBsZSBvZiAnc3BlYWsnIGJlbG93KS4gCgpgYGB7cn0KIyB3ZWlnaHRlZCBuZXR3b3JrIAp0cmFuc2l0aXZpdHkoZ3JhcGggPSBzbmV0LCB0eXBlID0gJ2xvY2FsJywgdmlkcyA9ICdjaGVlc2UnKSB8PiByb3VuZCgzKSAKCnRyYW5zaXRpdml0eShncmFwaCA9IHNuZXQsIHR5cGUgPSAnd2VpZ2h0ZWQnLCB2aWRzID0gJ2NoZWVzZScpIHw+IHJvdW5kKDMpIAoKIyB1bndlaWdodGVkIG5ldHdvcmsgCnRyYW5zaXRpdml0eShncmFwaCA9IHBuZXQsIHR5cGUgPSAnbG9jYWwnLCB2aWRzID0gJ3NwaWs7c3BlYWsnKSB8PiByb3VuZCgzKQoKdHJhbnNpdGl2aXR5KGdyYXBoID0gcG5ldCwgdHlwZSA9ICd3ZWlnaHRlZCcsIHZpZHMgPSAnc3BpaztzcGVhaycpIHw+IHJvdW5kKDMpICMgbm8gZGlmZmVyZW5jZSB3aXRoIHRoZSBwcmV2aW91cwpgYGAKCiMjIyBDbG9zZW5lc3MgQ2VudHJhbGl0eSAKCkNsb3NlbmVzcyBjZW50cmFsaXR5IG9mIG5vZGUgKmkqIGlzIHRoZSBpbnZlcnNlIG9mIHRoZSBhdmVyYWdlIG9mIHRoZSBsZW5ndGggb2YgdGhlIHNob3J0ZXN0IHBhdGggYmV0d2VlbiBub2RlICppKiBhbmQgYWxsIG90aGVyIG5vZGVzIGluIHRoZSBuZXR3b3JrLiBJZiBhIG5vZGUgaGFzIGhpZ2ggY2xvc2VuZXNzIGNlbnRyYWxpdHksIGl0IG1lYW5zIHRoYXQgb24gYXZlcmFnZSwgaXQgdGFrZXMgZmV3IHN0ZXBzIHRvIHRyYXZlbCBmcm9tIHRoYXQgbm9kZSB0byBhbGwgb3RoZXIgbm9kZXMgaW4gdGhlIG5ldHdvcmsuIElmIGEgbm9kZSBoYXMgbG93IGNsb3NlbmVzcyBjZW50cmFsaXR5LCBpdCBtZWFucyB0aGF0IG9uIGF2ZXJhZ2UsIGl0IHRha2VzIG1vcmUgc3RlcHMgdG8gdHJhdmVsIGZyb20gdGhhdCBub2RlIHRvIGFsbCBvdGhlciBub2RlcyBpbiB0aGUgbmV0d29yay4KCkNsb3NlbmVzcyBjZW50cmFsaXR5IGlzIGNvbW1vbmx5IHZpZXdlZCBhcyBhbiBpbmRpY2F0b3Igb2YgdGhlICphY2Nlc3NpYmlsaXR5KiBvZiBhIG5vZGUgaW4gdGhlIG5ldHdvcmsgZnJvbSBhbGwgb3RoZXIgbG9jYXRpb25zIGluIHRoZSBuZXR3b3JrLiAKCiFbXShodHRwczovL3d3dy5yZWxpYW50c3Byb2plY3QuY29tL3dwLWNvbnRlbnQvdXBsb2Fkcy8yMDIwLzA2L3JlbGlhbnRzX2tleWNvbmNlcHRzLTA0LnBuZykKKlRoaXMgaXMgYSBmYW1vdXMgbmV0d29yayAoS3JhY2toYXJkdCdzIEtpdGUpIHRoYXQgbmljZWx5IGlsbHVzdHJhdGVzIHRoZSBkaWZmZXJlbmNlcyBiZXR3ZWVuIGRlZ3JlZSwgY2xvc2VuZXNzLCBhbmQgYmV0d2Vlbm5lc3MgY2VudHJhbGl0eS4qCgpgYGB7cn0KIyBjbG9zZW5lc3MgY2VudHJhbGl0aWVzIGZvciBkaXJlY3RlZCBuZXR3b3JrcywgaWdub3Jpbmcgd2VpZ2h0cyAgCmNsb3NlbmVzcyhncmFwaCA9IHNuZXQsIG5vcm1hbGl6ZWQgPSBULCBtb2RlID0gJ2FsbCcsIHdlaWdodHMgPSBOQSkgfD4gaGVhZCgpICMgYm90aCBpbi0gYW5kIG91dC0KY2xvc2VuZXNzKGdyYXBoID0gc25ldCwgbm9ybWFsaXplZCA9IFQsIG1vZGUgPSAnaW4nLCB3ZWlnaHRzID0gTkEpIHw+IGhlYWQoKSAjIG9ubHkgaW5jb21pbmcgZWRnZXMgY29uc2lkZXJlZCAKY2xvc2VuZXNzKGdyYXBoID0gc25ldCwgbm9ybWFsaXplZCA9IFQsIG1vZGUgPSAnb3V0Jywgd2VpZ2h0cyA9IE5BKSB8PiBoZWFkKCkgIyBvbmx5IG91dGdvaW5nIGVkZ2VzIGNvbnNpZGVyZWQKCiMgd2VpZ2h0cyBhcmUgY29uc2lkZXJlZCBieSBkZWZhdWx0IGlmIGdyYXBoIGhhcyBhIHdlaWdodCBhdHRyaWJ1dGUgCmNsb3NlbmVzcyhncmFwaCA9IHNuZXQsIG5vcm1hbGl6ZWQgPSBULCBtb2RlID0gJ2FsbCcpIHw+IGhlYWQoKQpgYGAKCk5vdGUgdGhhdCBjbG9zZW5lc3MgY2VudHJhbGl0eSBjYW4gb25seSBiZSBtZWFuaW5nZnVsbHkgY29tcHV0ZWQgZm9yIGNvbm5lY3RlZCBncmFwaHMgKHNvIHRoYXQgYSBwYXRoIGV4aXN0cyBiZXR3ZWVuIGFueSBwYWlyIG9mIG5vZGVzKS4gSWYgdGhlcmUgYXJlIGRpc3RpbmN0IG5ldHdvcmsgY29tcG9uZW50cywgdGhpcyBtZWFucyB0aGF0IGZvciBzb21lIHNldHMgb2Ygbm9kZSBwYWlycywgdGhlIHBhdGggYmV0d2VlbiB0aGVtIGRvZXMgbm90IGV4aXN0IGFuZCBjbG9zZW5lc3MgY2Fubm90IGJlIGNvbXB1dGVkLiBVc3VhbGx5LCBuZXR3b3JrIHNjaWVudGlzdHMgZm9jdXMgdGhlaXIgYW5hbHlzaXMgb24gdGhlIGxhcmdlc3QgY29ubmVjdGVkIGNvbXBvbmVudCBvZiB0aGUgbmV0d29yayBhbmQgaWdub3JlIHRoZSBzbWFsbGVyIGNvbm5lY3RlZCBjb21wb25lbnRzICh2aWV3ZWQgYXMgb3V0bGllcnMpLiAKCkl0IGlzIHR5cGljYWwgdG8gaGF2ZSBgbm9ybWFsaXplZCA9IFRgIHNvIHRoYXQgdGhlIHZhbHVlcyBhcmUgbm9ybWFsaXplZCB3aXRoIHJlc3BlY3QgdG8gdGhlIHNpemUgb2YgdGhlIG5ldHdvcmsuIEFzIHVzdWFsLCB5b3UgY2FuIHNwZWNpZnkgdGhlIGBtb2RlYCBhbmQgYHdlaWdodHNgIGFyZ3VtZW50cyBhY2NvcmRpbmdseSBpZiB5b3UgaGF2ZSBkaXJlY3RlZC93ZWlnaHRlZCBuZXR3b3JrcyB0byBnZXQgdGhlIGNvcnJlc3BvbmRpbmcgdmVyc2lvbnMgb2YgY2xvc2VuZXNzIGNlbnRyYWxpdHkgY29tcHV0ZWQuIEhvd2V2ZXIsIGNhdXRpb24gaXMgbmVlZGVkIGFzIHRoZSBpbnRlcnByZXRhdGlvbiBvZiBgd2VpZ2h0c2AgaW4gdGhpcyBjb250ZXh0IGlzIHRvIGludGVycHJldCB0aGVtIGFzICoqZGlzdGFuY2VzKiogcmF0aGVyIHRoYW4gKmNvbm5lY3Rpb24gc3RyZW5ndGhzKjogaGlnaGVyIHdlaWdodHMgPSBsb25nZXIgZGlzdGFuY2VzIChGcm9tIGBpZ3JhcGhgIG1hbnVhbDogIklmIHRoZSBncmFwaCBoYXMgYSB3ZWlnaHQgZWRnZSBhdHRyaWJ1dGUsIHRoZW4gdGhpcyBpcyB1c2VkIGJ5IGRlZmF1bHQuIFdlaWdodHMgYXJlIHVzZWQgZm9yIGNhbGN1bGF0aW5nIHdlaWdodGVkIHNob3J0ZXN0IHBhdGhzLCBzbyB0aGV5IGFyZSBpbnRlcnByZXRlZCBhcyBkaXN0YW5jZXMuIikuIEl0IGlzIGhpZ2hseSByZWNvbW1lbmRlZCB0byByZWFkIHRoZSBtYW51YWwgY2FyZWZ1bGx5IHRvIHVuZGVyc3RhbmQgdGhlIG1lYXN1cmVzIHRoYXQgYXJlIGJlaW5nIGNvbXB1dGVkLiAKCjxwIHN0eWxlPSJjb2xvcjpibHVlOyI+KlJlbGV2YW50IGZpbmRpbmcgaW4gcHN5Y2hvbG9neTogU2lldyAoMjAxOCkgc2hvd2VkIHRoYXQgdGhlIGNsb3NlbmVzcyBjZW50cmFsaXR5IG9mIHdvcmRzIGluIGFuIG9ydGhvZ3JhcGhpYyBzaW1pbGFyaXR5IG5ldHdvcmsgaW5mbHVlbmNlZCB3b3JkIG5hbWluZyBhbmQgdmlzdWFsIGxleGljYWwgZGVjaXNpb24gcGVyZm9ybWFuY2UgZGlmZmVyZW50bHkuIFdvcmRzIG9mIGhpZ2hlciBjbG9zZW5lc3MgY2VudHJhbGl0aWVzIHdlcmUgcmVzcG9uZGVkIHRvIG1vcmUgcXVpY2tseSBpbiBsZXhpY2FsIGRlY2lzaW9uLCBidXQgd2VyZSBuYW1lZCBtb3JlIHNsb3dseS4qPC9wPgoKIyMjIEJldHdlZW5uZXNzIENlbnRyYWxpdHkgCgpCZXR3ZWVubmVzcyBjZW50cmFsaXR5IGlzIGEgbWVhc3VyZSBvZiB0aGUgZGVncmVlIHRvIHdoaWNoIG5vZGVzIHN0YW5kIGluIGJldHdlZW4gZWFjaCBvdGhlci4gQSBub2RlIHdpdGggYSBoaWdoIGJldHdlZW5uZXNzIGNlbnRyYWxpdHkgaXMgYSBub2RlIHRoYXQgaXMgZnJlcXVlbnRseSBmb3VuZCBpbiB0aGUgc2hvcnQgcGF0aHMgb2Ygb3RoZXIgcGFpcnMgb2Ygbm9kZXMgaW4gdGhlIG5ldHdvcmsuIEluIGNvbnRyYXN0LCBhIG5vZGUgd2l0aCBhIGxvdyBiZXR3ZWVubmVzcyBjZW50cmFsaXR5IGlzIGEgbm9kZSB0aGF0IGlzIG5vdCB1c3VhbGx5IGZvdW5kIGluIHRoZSBzaG9ydCBwYXRocyBvZiBub2RlIHBhaXJzLiBCZXR3ZWVlbm5lc3MgY2FuIGJlIHZpZXdlZCBhcyBhbiBpbmRpY2F0b3IgaWYgd2hldGhlciBhIG5vZGUgcmVwcmVzZW50cyBhICJib3R0bGVuZWNrIiBpbiB0aGUgc3lzdGVtLiAKCmBgYHtyfQojIHVuZGlyZWN0ZWQsIHVud2VpZ2h0ZWQgbmV0d29yayAKYmV0d2Vlbm5lc3MoZ3JhcGggPSBwbmV0LCBub3JtYWxpemVkID0gVCwgd2VpZ2h0cyA9IE5BLCBkaXJlY3RlZCA9IEYpIHw+IGhlYWQoKQoKIyBkaXJlY3RlZCwgd2VpZ2h0ZWQgbmV0d29yayAKYmV0d2Vlbm5lc3MoZ3JhcGggPSBzbmV0LCBub3JtYWxpemVkID0gVCwgd2VpZ2h0cyA9IE5VTEwsIGRpcmVjdGVkID0gVCkgfD4gaGVhZCgpICMgdXNlIHdlaWdodCBhbmQgZGlyZWN0aW9uCmBgYAoKVGhlIHNhbWUgY29uc2lkZXJhdGlvbnMgKGFib3V0IGNvbm5lY3RlZCBncmFwaHMsIGFkZGl0aW9uYWwgYXJndW1lbnRzIGZvciB3ZWlnaHRlZCBhbmQgZGlyZWN0ZWQgZ3JhcGhzLCBub3JtYWxpemF0aW9uLCBpbnRlcnByZXRhdGlvbiBvZiB3ZWlnaHRzIGFzIGRpc3RhbmNlcykgZnJvbSB0aGUgY2xvc2VuZXNzIGNlbnRyYWxpdHkgc2VjdGlvbiBhcHBsaWVzIHRvIHRoaXMgc2VjdGlvbiBhcyB3ZWxsLiAKCiMjIyBQYWdlIFJhbmsgQ2VudHJhbGl0eQoKUGFnZVJhbmsgaXMgYSBjZW50cmFsaXR5IG1lYXN1cmUgZGV2ZWxvcGVkIGJ5IEdvb2dsZSB0byByYW5rIHdlYnBhZ2VzICh0aGUgaGlzdG9yaWMgcGFwZXIgZGVzY3JpYmluZyB0aGUgYWxnb3JpdGhtIGNhbiBiZSB2aWV3ZWQgW2hlcmVdKGh0dHA6Ly9pbmZvbGFiLnN0YW5mb3JkLmVkdS9+YmFja3J1Yi9nb29nbGUuaHRtbCkpLiBUaGUgZ2VuZXJhbCBpZGVhIGlzIHRoYXQgYSByYW5kb20gd2Fsa2VyIHdpbGwgdHJhdmVyc2UgdGhlIG5ldHdvcmsgc3BhY2UgYW5kIHRoZWlyIHBhdGhzIGFyZSBiaWFzZWQgYnkgdGhlIGxpbmsgY29ubmVjdGl2aXR5IHN0cnVjdHVyZSBvZiB0aGUgbmV0d29yay4gVGhlIHJhbmRvbSB3YWxrZXIgcmVzdGFydHMgdGhlIHdhbGsgYWZ0ZXIgc29tZSB0aW1lIChzaW11bGF0aW5nICJib3JlZG9tIiBvZiB0aGUgc3VyZmVyKS4gVGhlIG51bWJlciBvZiB2aXNpdHMgcmVjZWl2ZWQgYnkgYSBub2RlIHByb3ZpZGVzIGFuIGluZGljYXRvciBvZiBpdHMgaW1wb3J0YW5jZSBpbiB0aGUgbmV0d29yay4gSW50dWl0aXZlbHksIHdlIGV4cGVjdCB0aGF0IG5vZGVzIGhhdmUgYSBoaWdoIFBhZ2VSYW5rIGlmIHRoZXJlIGFyZSBtYW55IG5vZGVzIHRoYXQgcG9pbnQgdG8gaXQsIG9yIGlmIHRoZXJlIGFyZSBub2RlcyB0aGF0IHBvaW50IHRvIGl0IHRoYXQgdGhlbXNlbHZlcyBoYXZlIGEgaGlnaCBQYWdlUmFuay4gCgpgYGB7cn0KIyB1bmRpcmVjdGVkLCB1bndlaWdodGVkIG5ldHdvcmsgCnBhZ2VfcmFuayhncmFwaCA9IHBuZXQsIGRpcmVjdGVkID0gRiwgd2VpZ2h0cyA9IE5BKSR2ZWN0b3IgfD4gaGVhZCgpCgojIGRpcmVjdGVkLCB3ZWlnaHRlZCBuZXR3b3JrIApwYWdlX3JhbmsoZ3JhcGggPSBzbmV0LCBkaXJlY3RlZCA9IFQsIHdlaWdodHMgPSBOVUxMKSR2ZWN0b3IgfD4gaGVhZCgpCmBgYAoKVGhlIGB3ZWlnaHRzYCBhbmQgYGRpcmVjdGVkYCBhcmd1bWVudHMgY2FuIGJlIGFkanVzdGVkIGRlcGVuZGluZyBvbiB5b3VyIGdyYXBoIHR5cGUuIEl0IGlzIGltcG9ydGFudCB0byBub3RlIHRoYXQgdGhlIGludGVycHJldGF0aW9uIG9mIGVkZ2Ugd2VpZ2h0cyBoZXJlIGlzIHRoYXQgb2YgImNvbm5lY3Rpb24gc3RyZW5ndGgiIChmcm9tIGBpZ3JhcGhgIG1hbnVhbDogIlRoaXMgZnVuY3Rpb24gaW50ZXJwcmV0cyBlZGdlIHdlaWdodHMgYXMgY29ubmVjdGlvbiBzdHJlbmd0aHMuIEluIHRoZSByYW5kb20gc3VyZmVyIG1vZGVsLCBhbiBlZGdlIHdpdGggYSBsYXJnZXIgd2VpZ2h0IGlzIG1vcmUgbGlrZWx5IHRvIGJlIHNlbGVjdGVkIGJ5IHRoZSBzdXJmZXIuIikuIFRoaXMgaXMgZGlmZmVyZW50IGZyb20gdGhlICJkaXN0YW5jZSIgaW50ZXJwcmV0YXRpb24gb2YgZWRnZSB3ZWlnaHRzIGJ5IGNsb3NlbmVzcyBhbmQgYmV0d2Vlbm5lc3MuIAoKPHAgc3R5bGU9ImNvbG9yOmJsdWU7Ij4qUmVsZXZhbnQgZmluZGluZyBpbiBwc3ljaG9sb2d5OiBHcmlmZml0aHMgZXQgYWwuICgyMDA3KSBzaG93ZWQgdGhhdCBQYWdlIFJhbmsgY2VudHJhbGl0aWVzIG9mIHdvcmRzIGluIGEgd29yZCBhc3NvY2lhdGlvbiBuZXR3b3JrIHByb3ZpZGVkIGdvb2QgcHJlZGljdGlvbnMgZm9yIHRoZSB3b3JkcyBnZW5lcmF0ZWQgYnkgcGFydGljaXBhbnRzIGluIGEgbGV0dGVyIGZsdWVuY3kgdGFzay4qPC9wPgoKIyMgTWVzby1sZXZlbCAoY29tbXVuaXR5IHN0cnVjdHVyZSkKCkEgY29tbW9uIGZlYXR1cmUgb2YgbWFueSByZWFsLXdvcmxkIG5ldHdvcmtzIGlzIHRoYXQgdGhleSBoYXZlICoqY29tbXVuaXR5IHN0cnVjdHVyZSoqLiBOb2RlcyBhcmUgY29uc2lkZXJlZCB0byBiZSBwYXJ0IG9mIHRoZSBzYW1lIGNvbW11bml0eSBpZiB0aGUgZGVuc2l0eSBvZiBjb25uZWN0aW9ucyBhbW9uZyB0aG9zZSBub2RlcyBpcyByZWxhdGl2ZWx5IGhpZ2hlciB0aGFuIHRoZSBkZW5zaXR5IG9mIGNvbm5lY3Rpb25zIGJldHdlZW4gbm9kZXMgZnJvbSBkaWZmZXJlbnQgY29tbXVuaXRpZXMgKE5ld21hbiwgMjAwNikuCgoqKk1vZHVsYXJpdHksIFEqKiwgaXMgYSBtZWFzdXJlIG9mIHRoZSBkZW5zaXR5IG9mIGxpbmtzIGluc2lkZSBjb21tdW5pdGllcyBpbiByZWxhdGlvbiB0byB0aGUgZGVuc2l0eSBvZiBsaW5rcyBiZXR3ZWVuIGNvbW11bml0aWVzIChGb3J0dW5hdG8sIDIwMTApLiBOZXR3b3JrcyB3aXRoIGhpZ2hlciBRIGFyZSBzYWlkIHRvIHNob3cgc3Ryb25nIGV2aWRlbmNlIG9mIGNvbW11bml0eSBzdHJ1Y3R1cmUuIAoKIVtdKGltZy9rYXJhdGUtY29tbXVuaXRpZXMucG5nKQoKKkNvbW11bml0aWVzIGFyZSBkZXBpY3RlZCBpbiBkaWZmZXJlbnQgY29sb3JzIGZyb20gYW5vdGhlciBmYW1vdXMgbmV0d29yazogWmFjaGFyeSdzIEthcmF0ZSBDbHViIE5ldHdvcmsqCgoqKkhvdyBkbyBuZXR3b3JrIHNjaWVudGlzdHMgImZpbmQiIGNvbW11bml0aWVzIGluIG5ldHdvcmtzPyoqIAoKTWFueSBjb21tdW5pdHkgZGV0ZWN0aW9uIG1ldGhvZHMgaGF2ZSBiZWVuIGRldmVsb3BlZCBieSBuZXR3b3JrIHNjaWVudGlzdHMgdG8gZGV0ZWN0IGNvbW11bml0aWVzIGluIG5ldHdvcmtzLiBFYWNoIGRpZmZlcnMgaW4gdGhlaXIgaW1wbGVtZW50YXRpb24sIGFuZCByZWZsZWN0cyB0aGUgY3JlYXRvcidzIGltcGxpY2l0IGRlZmluaXRpb24gb2Ygd2hhdCBpcyBhIGNvbW11bml0eS4gSW4gdGhpcyB0dXRvcmlhbCB3ZSBnbyB0aHJvdWdoIG9ubHkgb25lIG9mIHRoZXNlIG1ldGhvZHMgKExvdXZhaW4pIHRvIGRlbW9uc3RyYXRlIGFuIGV4YW1wbGUgb2YgY29tbXVuaXR5IGRldGVjdGlvbi4KCklmIHlvdSBhcmUgaW50ZXJlc3RlZCB0byBsZWFybiBtb3JlIGFib3V0IGNvbW11bml0eSBkZXRlY3Rpb24sIGNoZWNrIG91dCBGb3J0dW5hdG8gKDIwMTApIHdobyBwcm92aWRlZCBhIGNvbXByZWhlbnNpdmUgY29tcGFyaXNvbiBvZiB2YXJpb3VzIGNvbW11bml0eSBkZXRlY3Rpb24gdGVjaG5pcXVlcy4gCgojIyMgTG91dmFpbiBtZXRob2QgKCJncmVlZHksIG1heGltaXphdGlvbiBtZXRob2QiKQoKVGhlIGNvcmUgaWRlYSBiZWhpbmQgdGhpcyBtZXRob2QgaXMgdGhhdCBjb21tdW5pdGllcyBhcmUgZXNzZW50aWFsbHkg4oCcbWVyZ2Vyc+KAnSBvZiBzbWFsbCBjb21tdW5pdGllcyAoQmxvbmRlbCBldCBhbC4sIDIwMDgpLCByZWZsZWN0aW5nIHRoZSBzZWxmLXNpbWlsYXIgbmF0dXJlIG9mIGNvbXBsZXggbmV0d29ya3MuCgoxLiBFYWNoIG5vZGUgaXMgYXNzaWduZWQgdG8gb25lIGNvbW11bml0eSBzdWNoIHRoYXQgdGhlcmUgYXJlIGFzIG1hbnkgY29tbXVuaXRpZXMgYXMgdGhlcmUgYXJlIG5vZGVzLiBUaGVuIHJlbW92ZSBub2RlICppKiBmcm9tIGl0cyBjb21tdW5pdHkgYW5kIHBsYWNpbmcgaXQgaW4gdGhlIGNvbW11bml0eSBvZiB0aGUgbmVpZ2hib3Igd2hpY2ggeWllbGRzIHRoZSBncmVhdGVzdCBnYWluIGluIG1vZHVsYXJpdHkuIAogIC0gcmVwZWF0IGZvciBhbGwgbm9kZXMgaW4gdGhlIG5ldHdvcmsKCjIuIEEgbmV3IG5ldHdvcmsgaXMgYnVpbHQgd2hlcmUgbm9kZXMgYXJlIHRoZSAqY29tbXVuaXRpZXMgZm91bmQgaW4gdGhlIHByZXZpb3VzIHBoYXNlKi4gUmVwZWF0IFN0ZXAgMS4gCiAgLSByZXBlYXQgU3RlcCAxIGFuZCAyIHVudGlsIGl0IGlzIG5vdCBwb3NzaWJsZSB0byBmdXJ0aGVyIGluY3JlYXNlIHRoZSB2YWx1ZSBvZiBRCgpgYGB7cn0Kc2V0LnNlZWQoOCkKCiMgcnVuIHRoZSBjb21tdW5pdHkgZGV0ZWN0aW9uIGFsZ29yaXRobSAKcmVzdWx0c19sb3V2YWluIDwtIGNsdXN0ZXJfbG91dmFpbihncmFwaCA9IHBuZXQpCgojIG92ZXJhbGwgcmVzdWx0cyAKbW9kdWxhcml0eShyZXN1bHRzX2xvdXZhaW4pCnNpemVzKHJlc3VsdHNfbG91dmFpbikKCiMgc3BlY2lmaWMgY29tbXVuaXR5IG1lbWJlcnNoaXAgZm9yIGVhY2ggbm9kZSAKY2JpbmQoCiAgcmVzdWx0c19sb3V2YWluJG5hbWVzLAogIHJlc3VsdHNfbG91dmFpbiRtZW1iZXJzaGlwCikgCmBgYAoKU2F2aW5nIHRoZSBjb21tdW5pdHkgZGV0ZWN0aW9uIHJlc3VsdHMgYXMgYSBgY29tbXVuaXRpZXNgIG9iamVjdCBlbmFibGVzIHRoZSB1c2Ugb2Ygc3BlY2lhbCBmdW5jdGlvbnMgbGlrZSBgbW9kdWxhcml0eSgpYCBhbmQgYHNpemVzKClgIHRvIG9idGFpbiB0aGUgbW9kdWxhcml0eSBvZiB0aGUgbmV0d29yayBhbmQgaXRzIGNvbW11bml0eSBzaXplcy4gSSBoYXZlIGFsc28gaW5jbHVkZWQgY29kZSB0aGF0IHNob3dzIGhvdyB0byBleHRyYWN0IHRoZSBjb21tdW5pdHkgbWVtYmVyc2hpcHMgb2YgYWxsIG5vZGVzIGluIHRoZSBuZXR3b3JrIGZvciBmdXJ0aGVyIGFuYWx5c2lzLiBUaGlzIGFwcGxpZXMgdG8gdGhlIG90aGVyIGNvbW11bml0eSBkZXRlY3Rpb24gYWxnb3JpdGhtcyBhcyB3ZWxsLiAKCjxwIHN0eWxlPSJjb2xvcjpibHVlOyI+KlJlbGV2YW50IGZpbmRpbmcgaW4gcHN5Y2hvbG9neTogU2lldyAoMjAxMykgZm91bmQgcm9idXN0IGNvbW11bml0eSBzdHJ1Y3R1cmUgaW4gdGhlIHBob25vbG9naWNhbCBuZXR3b3JrLCBhbmQgd29yZHMgaW4gdGhlIHNhbWUgY29tbXVuaXR5IHRlbmRlZCB0byBzaGFyZSBzaW1pbGFyIGxleGljYWwgYW5kIHBob25vbG9naWNhbCBwcm9wZXJ0aWVzLio8L3A+CgojIyBNYWNyby1sZXZlbCAobmV0d29yay1sZXZlbCkKCkluIHRoaXMgc2VjdGlvbiwgd2Ugd2lsbCByZXZpZXcgbmV0d29yayBzY2llbmNlIG1lYXN1cmVzIHRoYXQgZGVzY3JpYmUgdGhlIG92ZXJhbGwgb3IgZ2xvYmFsIHN0cnVjdHVyZSBvZiB0aGUgZW50aXJlIG5ldHdvcmsuIFlvdSBjYW4gdGhpbmsgb2YgdGhlc2UgbWVhc3VyZXMgYXMgcHJvdmlkaW5nIGEgImJpcmQncyBleWUgdmlldyIgb2YgeW91ciBuZXR3b3JrLCBhbmQgdGhleSBhcmUgdXNlZnVsIGZvciBjb21wYXJpbmcgZGlmZmVyZW50IG5ldHdvcmsgcmVwcmVzZW50YXRpb25zLiAKCiMjIyBBdmVyYWdlIFNob3J0ZXN0IFBhdGggTGVuZ3RoIAoKKipBdmVyYWdlIHNob3J0ZXN0IHBhdGggbGVuZ3RoKiogKEFTUEwpIHJlZmVycyB0byB0aGUgbWVhbiBvZiB0aGUgc2hvcnRlc3QgcG9zc2libGUgcGF0aCBiZXR3ZWVuIGFsbCBwb3NzaWJsZSBwYWlycyBvZiBub2RlcyBpbiB0aGUgbmV0d29yay4gKFRoaXMgbG9vc2VseSBjb3JyZXNwb25kcyB0byB0aGUgaWRlYSBvZiAic2l4IGRlZ3JlZXMgb2Ygc2VwYXJhdGlvbiIgaW4gc29jaWFsIG5ldHdvcmtzLikgIAoKIVtdKGh0dHBzOi8vZXh0ZXJuYWwtY29udGVudC5kdWNrZHVja2dvLmNvbS9pdS8/dT1odHRwcyUzQSUyRiUyRnRzZTIubW0uYmluZy5uZXQlMkZ0aCUzRmlkJTNET0lQLjdNNXBtRzR3NU5ucDYxMGkxajdyTFFIYUZ2JTI2cGlkJTNEQXBpJmY9MSkKCipFeGFtcGxlIGRlcGljdGluZyB0aGUgc2hvcnRlc3QgcGF0aCBiZXR3ZWVuIG5vZGVzIDI1IGFuZCAxNi4qCgpgYGB7cn0KIyB1bmRpcmVjdGVkLCB1bndlaWdodGVkIG5ldHdvcmsgCmF2ZXJhZ2UucGF0aC5sZW5ndGgoZ3JhcGggPSBwbmV0KSAKCiMgYW4gYWx0ZXJuYXRpdmUgZnVuY3Rpb24gLSBib3RoIGdpdmUgdGhlIHNhbWUgcmVzdWx0IAptZWFuX2Rpc3RhbmNlKGdyYXBoID0gcG5ldCkKCiMgZGlyZWN0ZWQsIHdlaWdodGVkIG5ldHdvcmsgCm1lYW5fZGlzdGFuY2UoZ3JhcGggPSBzbmV0LCB3ZWlnaHRzID0gTlVMTCwgZGlyZWN0ZWQgPSBUKSAjIGNvbnNpZGVyIHdlaWdodHMgYW5kIGRpcmVjdGlvbgptZWFuX2Rpc3RhbmNlKGdyYXBoID0gc25ldCwgd2VpZ2h0cyA9IE5VTEwsIGRpcmVjdGVkID0gRikgIyBpZ25vcmUgZGlyZWN0aW9uIAptZWFuX2Rpc3RhbmNlKGdyYXBoID0gc25ldCwgd2VpZ2h0cyA9IE5BLCBkaXJlY3RlZCA9IFQpICMgaWdub3JlIHdlaWdodHMgCmBgYAoKPHAgc3R5bGU9ImNvbG9yOmJsdWU7Ij4qUmVsZXZhbnQgZmluZGluZyBpbiBwc3ljaG9sb2d5OiBTaWV3ICgyMDE4KSBzaG93ZWQgdGhhdCBjb25jZXB0IG5ldHdvcmtzIChjb25zdHJ1Y3RlZCBmcm9tIGNvbmNlcHQgbWFwcyBnZW5lcmF0ZWQgYnkgc3R1ZGVudHMpIHdpdGggbGFyZ2VyIGF2ZXJhZ2Ugc2hvcnRlc3QgcGF0aCBsZW5ndGhzIHdlcmUgYXNzb2NpYXRlZCB3aXRoIGhpZ2hlciBxdWl6IHNjb3JlcywgYWZ0ZXIgY29udHJvbGxpbmcgZm9yIG5ldHdvcmsgc2l6ZS4qPC9wPgoKIyMjIEdsb2JhbCBDbHVzdGVyaW5nIENvZWZmaWNpZW50ICAKCioqR2xvYmFsIGNsdXN0ZXJpbmcgY29lZmZpY2llbnQqKiByZWZlcnMgdG8gdGhlIG51bWJlciBvZiBjbG9zZWQgdHJpYW5nbGVzIGluIHRoZSBuZXR3b3JrIHJlbGF0aXZlIHRvIHRoZSBudW1iZXIgb2YgcG9zc2libGUgdHJpYW5nbGVzLiBJdCBpcyBhIG1lYXN1cmUgb2Ygb3ZlcmFsbCBsZXZlbCBvZiAqbG9jYWwqIGNvbm5lY3Rpdml0eSBhbW9uZyBub2RlcyBpbiB0aGUgbmV0d29yay4gCgpBIHNpbXBsZSB3YXkgb2YgdGhpbmtpbmcgYWJvdXQgdGhpcyBjb25jZXB0IGlzIHRoYXQgaXQgaXMgbWVhc3VyaW5nIHRoZSBwcm9iYWJpbGl0eSB0aGF0IGVhY2ggcGFpciBvZiAiZnJpZW5kcyIgb2YgYSBnaXZlbiBub2RlIGFyZSBhbHNvIGZyaWVuZHMgd2l0aCBlYWNoIG90aGVyLgoKYGBge3J9CnRyYW5zaXRpdml0eShncmFwaCA9IHBuZXQsIHR5cGUgPSAnZ2xvYmFsJykKdHJhbnNpdGl2aXR5KGdyYXBoID0gc25ldCwgdHlwZSA9ICdnbG9iYWwnKQpgYGAKCiMjIyBTbWFsbCBXb3JsZCBJbmRleCAKClRoZSB0ZXJtICJzbWFsbCB3b3JsZCIgaGFzIGEgc3BlY2lmaWMgbWVhbmluZyBpbiBuZXR3b3JrIHNjaWVuY2UgYXMgY29tcGFyZWQgdG8gdGhlIGxheXBlcnNvbidzLiBBIG5ldHdvcmsgaXMgY29uc2lkZXJlZCB0byBoYXZlIHNtYWxsIHdvcmxkIGNoYXJhY3RlcmlzdGljcyBpZiAoaSkgaXRzIEFTUEwgaXMgKnNob3J0ZXIqIHRoYW4gdGhhdCBvZiBhIHJhbmRvbWx5IGdlbmVyYXRlZCBuZXR3b3JrIHdpdGggdGhlIHNhbWUgbnVtYmVyIG9mIG5vZGVzIGFuZCBlZGdlcywgYW5kIChpaSkgaXRzIGdsb2JhbCBDIGlzICpsYXJnZXIqIHRoYW4gdGhhdCBvZiBhIHJhbmRvbWx5IGdlbmVyYXRlZCBuZXR3b3JrIHdpdGggdGhlIHNhbWUgbnVtYmVyIG9mIG5vZGVzIGFuZCBlZGdlcy4gVGhlcmUgYXJlIHZhcmlvdXMgd2F5cyB0byBjb21wdXRlIGEgdmFsdWUgdGhhdCBxdWFudGlmaWVzIHRoZSAic21hbGwgd29ybGRuZXNzIiBvZiBhIG5ldHdvcmssIGFsdGhvdWdoIHdlIGRvIG5vdCBjb3ZlciB0aGVtIGhlcmUgKHNlZSBIdW1waHJpZXMgYW5kIEd1cm5leSwgMjAwOCwgZm9yIGFuIGV4YW1wbGUsIGFuZCBOZWFsLCAyMDE3LCBmb3IgYSBjb21wYXJpc29uIG9mIGRpZmZlcmVudCBtZXRob2RzKS4KClRoZSBtYWluIHRha2UgaG9tZSBtZXNzYWdlIGlzIHRoYXQgYSBzbWFsbCB3b3JsZCBuZXR3b3JrIGhhcyBoaWdoIGxldmVscyBvZiBsb2NhbCBjbHVzdGVyaW5nIChub2RlcyB3aG9zZSBuZWlnaGJvcnMgYXJlIGFsc28gbmVpZ2hib3JzIG9mIGVhY2ggb3RoZXIpLCBidXQgdGhlcmUgYWxzbyBleGlzdHMgYSBudW1iZXIgb2Ygc2hvcnRjdXRzIHRoYXQgZHJhc3RpY2FsbHkgcmVkdWNlcyB0aGUgb3ZlcmFsbCBkaXN0YW5jZXMvcGF0aCBsZW5ndGhzIGJldHdlZW4gbm9kZXMuIFNlZSBiZWxvdyBmb3IgYW4gaWxsdXN0cmF0aW9uIG9mIHRoaXMgaWRlYS4gCgohW10oaW1nL3NtYWxsLXdvcmxkLmdpZikKCiMjIyBOZXR3b3JrIERlbnNpdHkKCioqTmV0d29yayBkZW5zaXR5KiogcmVmZXJzIHRvIHRoZSByYXRpbyBvZiB0aGUgbnVtYmVyIG9mIChleGlzdGluZykgZWRnZXMgYW5kIHRoZSBudW1iZXIgb2YgcG9zc2libGUgZWRnZXMgYW1vbmcgbm9kZXMgaW4gdGhlIG5ldHdvcmsuIAoKIVtdKGltZy9kZW5zaXR5LnBuZykKCipTaW1wbGUgZXhhbXBsZSBvZiBuZXR3b3JrcyB3aXRoIGxvd2VyIGFuZCBoaWdoZXIgbmV0d29yayBkZW5zaXRpZXMuKgoKYGBge3J9CmdyYXBoLmRlbnNpdHkoZ3JhcGggPSBwbmV0KQpncmFwaC5kZW5zaXR5KGdyYXBoID0gc25ldCkKYGBgCgojIyMgTmV0d29yayBEaWFtZXRlciAKCioqTmV0d29yayBkaWFtZXRlcioqIHJlZmVycyB0byBsZW5ndGggb2YgdGhlIGxvbmdlc3Qgc2hvcnRlc3QgcGF0aCBiZXR3ZWVuIG5vZGVzIGluIHRoZSBuZXR3b3JrLiBJbnN0ZWFkIG9mIGdldHRpbmcgdGhlIG1lYW4gb2YgYWxsIHRoZSBzaG9ydGVzdCBwYXRocyBhcyB5b3UgZGlkIGluIEFTUEwsIHdoYXQgaXMgdGhlICptYXhpbXVtKiBsZW5ndGggb2YgdGhvc2Ugc2hvcnQgcGF0aHM/IAoKIVtdKGltZy9kaWFtZXRlci5wbmcpCgoqU2ltcGxlIGV4YW1wbGUgb2YgbmV0d29ya3Mgd2l0aCBoaWdoZXIgYW5kIGxvd2VyIG5ldHdvcmsgZGlhbWV0ZXJzKgoKYGBge3J9CiMgdW5kaXJlY3RlZCwgdW53ZWlnaHRlZCBncmFwaCAKZGlhbWV0ZXIoZ3JhcGggPSBwbmV0KQoKIyBkaXJlY3RlZCwgd2VpZ2h0ZWQgZ3JhcGggCmRpYW1ldGVyKGdyYXBoID0gc25ldCwgZGlyZWN0ZWQgPSBULCB3ZWlnaHRzID0gTlVMTCkgIyBjb25zaWRlciB3ZWlnaHRzIGFuZCBkaXJlY3Rpb24KZGlhbWV0ZXIoZ3JhcGggPSBzbmV0LCBkaXJlY3RlZCA9IEYsIHdlaWdodHMgPSBOVUxMKSAjIGlnbm9yZSBkaXJlY3Rpb24gCmRpYW1ldGVyKGdyYXBoID0gc25ldCwgZGlyZWN0ZWQgPSBULCB3ZWlnaHRzID0gTkEpICMgaWdub3JlIHdlaWdodHMgCmBgYAoKIyBBZGRpdGlvbmFsIFJlc291cmNlcyAKCk9nbnlhbm92YSwgSy4gKDIwMjEpIE5ldHdvcmsgdmlzdWFsaXphdGlvbiB3aXRoIFIuIFJldHJpZXZlZCBmcm9tIHd3dy5rYXRldG8ubmV0L25ldHdvcmstdmlzdWFsaXphdGlvbi4gaHR0cHM6Ly9rYXRldG8ubmV0L25ldHdvcmstdmlzdWFsaXphdGlvbgoKVGhlIG9mZmljaWFsIGBpZ3JhcGhgIG1hbnVhbCAodi4xLjMuNCkuIGh0dHBzOi8vaWdyYXBoLm9yZy9yL2RvYy8gCgpHZXBoaTogQSBtdWx0aS1wbGF0Zm9ybSwgZnJlZSB0byBkb3dubG9hZCBHVUkgYXBwIGZvciBuZXR3b3JrIGFuYWx5c2lzIGFuZCB2aXN1YWxpemF0aW9uLiBodHRwczovL2dlcGhpLm9yZy8KCiMgUmVmZXJlbmNlcyAKCkJhcnJhdCwgQS4sIEJhcnRow6lsZW15LCBNLiwgUGFzdG9yLVNhdG9ycmFzLCBSLiwgJiBWZXNwaWduYW5pLCBBLiAoMjAwNCkuIFRoZSBhcmNoaXRlY3R1cmUgb2YgY29tcGxleCB3ZWlnaHRlZCBuZXR3b3Jrcy4gUHJvY2VlZGluZ3Mgb2YgdGhlIE5hdGlvbmFsIEFjYWRlbXkgb2YgU2NpZW5jZXMsIDEwMSgxMSksIDM3NDfigJMzNzUyLiBodHRwczovL2RvaS5vcmcvMTAuMTA3My9wbmFzLjA0MDAwODcxMDEKCkJsb25kZWwsIFYuIEQuLCBHdWlsbGF1bWUsIEouIEwuLCBMYW1iaW90dGUsIFIuLCAmIExlZmVidnJlLCBFLiAoMjAwOCkuIEZhc3QgdW5mb2xkaW5nIG9mIGNvbW11bml0aWVzIGluIGxhcmdlIG5ldHdvcmtzLiBKb3VybmFsIG9mIFN0YXRpc3RpY2FsIE1lY2hhbmljczogVGhlb3J5IGFuZCBFeHBlcmltZW50LCAyMDA4KDEwKSwgUDEwMDA4LgoKQ2hhbiwgSy4gWS4sICYgVml0ZXZpdGNoLCBNLiBTLiAoMjAwOSkuIFRoZSBpbmZsdWVuY2Ugb2YgdGhlIHBob25vbG9naWNhbCBuZWlnaGJvcmhvb2QgY2x1c3RlcmluZyBjb2VmZmljaWVudCBvbiBzcG9rZW4gd29yZCByZWNvZ25pdGlvbi4gSm91cm5hbCBvZiBFeHBlcmltZW50YWwgUHN5Y2hvbG9neTogSHVtYW4gUGVyY2VwdGlvbiBhbmQgUGVyZm9ybWFuY2UsIDM1KDYpLCAxOTM04oCTMTk0OS4gaHR0cHM6Ly9kb2kub3JnLzEwLjEwMzcvYTAwMTY5MDIKCkRlIERleW5lLCBTLiwgTmF2YXJybywgRC4gSi4sIFBlcmZvcnMsIEEuLCBCcnlzYmFlcnQsIE0uLCAmIFN0b3JtcywgRy4gKDIwMTkpLiBUaGUg4oCcU21hbGwgV29ybGQgb2YgV29yZHPigJ0gRW5nbGlzaCB3b3JkIGFzc29jaWF0aW9uIG5vcm1zIGZvciBvdmVyIDEyLDAwMCBjdWUgd29yZHMuIEJlaGF2aW9yIFJlc2VhcmNoIE1ldGhvZHMsIDUxLCA5ODfigJMxMDA2LgoKRm9ydHVuYXRvLCBTLiAoMjAxMCkuIENvbW11bml0eSBkZXRlY3Rpb24gaW4gZ3JhcGhzLiBQaHlzaWNzIFJlcG9ydHMsIDQ4NigzLTUpLCA3NS0xNzQuCgpIdW1waHJpZXMsIE0uIEQuLCAmIEd1cm5leSwgSy4gKDIwMDgpLiBOZXR3b3JrIOKAmHNtYWxsLXdvcmxkLW5lc3PigJk6IEEgcXVhbnRpdGF0aXZlIG1ldGhvZCBmb3IgZGV0ZXJtaW5pbmcgY2Fub25pY2FsIG5ldHdvcmsgZXF1aXZhbGVuY2UuIFBsb1MgT25lLCAzKDQpLgoKR3JpZmZpdGhzLCBULiBMLiwgU3RleXZlcnMsIE0uLCAmIEZpcmwsIEEuICgyMDA3KS4gR29vZ2xlIGFuZCB0aGUgTWluZDogUHJlZGljdGluZyBGbHVlbmN5IFdpdGggUGFnZVJhbmsuIFBzeWNob2xvZ2ljYWwgU2NpZW5jZSwgMTgoMTIpLCAxMDY54oCTMTA3Ni4gaHR0cHM6Ly9kb2kub3JnLzEwLjExMTEvai4xNDY3LTkyODAuMjAwNy4wMjAyNy54CgpMdWNlLCBQLiBBLiwgJiBQaXNvbmksIEQuIEIuICgxOTk4KS4gUmVjb2duaXppbmcgc3Bva2VuIHdvcmRzOiBUaGUgTmVpZ2hib3Job29kIEFjdGl2YXRpb24gTW9kZWwuIEVhciBhbmQgSGVhcmluZywgMTkoMSksIDHigJMzNi4KCk5lYWwsIFouIFAuICgyMDE3KS4gSG93IHNtYWxsIGlzIGl0PyBDb21wYXJpbmcgaW5kaWNlcyBvZiBzbWFsbCB3b3JsZGxpbmVzcy4gTmV0d29yayBTY2llbmNlLCA1KDEpLCAzMOKAkzQ0LiBodHRwczovL2RvaS5vcmcvMTAuMTAxNy9ud3MuMjAxNy41CgpOZXdtYW4sIE0uIEUuICgyMDA2KS4gTW9kdWxhcml0eSBhbmQgY29tbXVuaXR5IHN0cnVjdHVyZSBpbiBuZXR3b3Jrcy4gUHJvY2VlZGluZ3Mgb2YgdGhlIE5hdGlvbmFsIEFjYWRlbXkgb2YgU2NpZW5jZXMsIDEwMygyMyksIDg1NzctODU4Mi4gICAKClNpZXcsIEMuIFMuIFEuICgyMDEzKS4gQ29tbXVuaXR5IHN0cnVjdHVyZSBpbiB0aGUgcGhvbm9sb2dpY2FsIG5ldHdvcmsuIEZyb250aWVycyBpbiBQc3ljaG9sb2d5LCA0LCA1NTMuCgpTaWV3LCBDLiBTLiBRLiAoMjAxOCkuIFRoZSBvcnRob2dyYXBoaWMgc2ltaWxhcml0eSBzdHJ1Y3R1cmUgb2YgRW5nbGlzaCB3b3JkczogSW5zaWdodHMgZnJvbSBuZXR3b3JrIHNjaWVuY2UuIEFwcGxpZWQgTmV0d29yayBTY2llbmNlLCAzKDEpLCAxMy4KClNpZXcsIEMuIFMuIFEuICgyMDE4KS4gVXNpbmcgbmV0d29yayBzY2llbmNlIHRvIGFuYWx5emUgY29uY2VwdCBtYXBzIG9mIHBzeWNob2xvZ3kgdW5kZXJncmFkdWF0ZXMuIEFwcGxpZWQgQ29nbml0aXZlIFBzeWNob2xvZ3kuCgpWaXRldml0Y2gsIE0uIFMuICgyMDA4KS4gV2hhdCBjYW4gZ3JhcGggdGhlb3J5IHRlbGwgdXMgYWJvdXQgd29yZCBsZWFybmluZyBhbmQgbGV4aWNhbCByZXRyaWV2YWw/IEpvdXJuYWwgb2YgU3BlZWNoLCBMYW5ndWFnZSwgYW5kIEhlYXJpbmcgUmVzZWFyY2gsIDUxKDIpLCA0MDjigJM0MjIuIGh0dHBzOi8vZG9pLm9yZy8xMC4xMDQ0LzEwOTItNDM4OCgyMDA4LzAzMCkK

Copyright © 2023 CSQ Siew. All rights reserved.

Creative Commons License
This work is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License.