Install Packages
packages = c('igraph', 'tidygraph', 'ggraph', 'ggrepel', 'visNetwork', 'lubridate', 'tidyverse')
for(p in packages){library
if(!require(p, character.only = T)){
install.packages(p)
}
library(p, character.only = T)
}
Data Import
GAStech_nodes <- read_csv("data/GAStech_email_node.csv")
Parsed with column specification:
cols(
id = [32mcol_double()[39m,
label = [31mcol_character()[39m,
Department = [31mcol_character()[39m,
Title = [31mcol_character()[39m
)
GAStech_edges <- read_csv("data/GAStech_email_edge-v2.csv")
Parsed with column specification:
cols(
source = [32mcol_double()[39m,
target = [32mcol_double()[39m,
SentDate = [31mcol_character()[39m,
SentTime = [34mcol_time(format = "")[39m,
Subject = [31mcol_character()[39m,
MainSubject = [31mcol_character()[39m,
sourceLabel = [31mcol_character()[39m,
targetLabel = [31mcol_character()[39m
)
Data Wrangling
GAStech_edges$SentDate = dmy(GAStech_edges$SentDate)
GAStech_edges$Weekday = wday(GAStech_edges$SentDate, label = TRUE, abbr = FALSE)
GAStech_edges_aggregated <- GAStech_edges %>%
filter(MainSubject == "Work related") %>%
group_by(source, target, Weekday) %>%
summarise(Weight = n()) %>%
filter(source!=target) %>%
filter(Weight > 1) %>%
ungroup()
GAStech_edges_aggregated
GAStech_graph <- tbl_graph(nodes = GAStech_nodes, edges = GAStech_edges_aggregated, directed = TRUE)
GAStech_graph
[38;5;246m# A tbl_graph: 54 nodes and 1456 edges
[39m[38;5;246m#
[39m[38;5;246m# A directed multigraph with 1 component
[39m[38;5;246m#
[39m[38;5;246m# Node Data: 54 x 4 (active)[39m
id label Department Title
[3m[38;5;246m<dbl>[39m[23m [3m[38;5;246m<chr>[39m[23m [3m[38;5;246m<chr>[39m[23m [3m[38;5;246m<chr>[39m[23m
[38;5;250m1[39m 1 Mat.Bramar Administrati~ Assistant to CEO
[38;5;250m2[39m 2 Anda.Ribera Administrati~ Assistant to CFO
[38;5;250m3[39m 3 Rachel.Pantanal Administrati~ Assistant to CIO
[38;5;250m4[39m 4 Linda.Lagos Administrati~ Assistant to COO
[38;5;250m5[39m 5 Ruscella.Mies.H~ Administrati~ Assistant to Engineering Gro~
[38;5;250m6[39m 6 Carla.Forluniau Administrati~ Assistant to IT Group Manager
[38;5;246m# ... with 48 more rows[39m
[38;5;246m#
[39m[38;5;246m# Edge Data: 1,456 x 4[39m
from to Weekday Weight
[3m[38;5;246m<int>[39m[23m [3m[38;5;246m<int>[39m[23m [3m[38;5;246m<ord>[39m[23m [3m[38;5;246m<int>[39m[23m
[38;5;250m1[39m 1 2 Monday 4
[38;5;250m2[39m 1 2 Tuesday 3
[38;5;250m3[39m 1 2 Wednesday 5
[38;5;246m# ... with 1,453 more rows[39m
GAStech_graph %>%
activate(edges) %>%
arrange(desc(Weight))
[38;5;246m# A tbl_graph: 54 nodes and 1456 edges
[39m[38;5;246m#
[39m[38;5;246m# A directed multigraph with 1 component
[39m[38;5;246m#
[39m[38;5;246m# Edge Data: 1,456 x 4 (active)[39m
from to Weekday Weight
[3m[38;5;246m<int>[39m[23m [3m[38;5;246m<int>[39m[23m [3m[38;5;246m<ord>[39m[23m [3m[38;5;246m<int>[39m[23m
[38;5;250m1[39m 40 41 Tuesday 23
[38;5;250m2[39m 40 43 Tuesday 19
[38;5;250m3[39m 41 43 Tuesday 15
[38;5;250m4[39m 41 40 Tuesday 14
[38;5;250m5[39m 42 41 Tuesday 13
[38;5;250m6[39m 42 40 Tuesday 12
[38;5;246m# ... with 1,450 more rows[39m
[38;5;246m#
[39m[38;5;246m# Node Data: 54 x 4[39m
id label Department Title
[3m[38;5;246m<dbl>[39m[23m [3m[38;5;246m<chr>[39m[23m [3m[38;5;246m<chr>[39m[23m [3m[38;5;246m<chr>[39m[23m
[38;5;250m1[39m 1 Mat.Bramar Administration Assistant to CEO
[38;5;250m2[39m 2 Anda.Ribera Administration Assistant to CFO
[38;5;250m3[39m 3 Rachel.Pantanal Administration Assistant to CIO
[38;5;246m# ... with 51 more rows[39m
Task 1: Static Organisation Graph
1.1 Original Network Grarph
The original network graph from section 6.1 of Hands-on-Exercise 10 is as follow:
# computing centrality indices
g <- GAStech_graph %>%
mutate(betweenness_centrality = centrality_betweenness()) %>%
mutate(closeness_centrality = centrality_closeness()) %>%
ggraph(layout = "nicely") +
geom_edge_link(aes()) +
geom_node_point(aes(colour = closeness_centrality, size=betweenness_centrality))
g + theme_graph()

The graph above shows the network of a particular employee based on the closeness centrality and betweenness centrality. However, the aesthetic and clarity of the graph is still not satisfactory. It is still leveraging on ggraph 1.0.
Negative remarks on clarity:
- I am not sure which employees are of higher clonessness centrality or betweenness centrality.
- With all the edges similar to each other, I am not sure which area has a higher weightage than the other. This means who are the employees that are more connected with each other.
- Just from looking the graph at a glance, I cannot derive much information. For example, when are the time they interacts? From which departments are they from?
Negative remarks on aesthetics:
- The nodes are overlapping of each other. Hence, making certain nodes not obvious
- Not all nodes can be seen due to the colour complement with the black edges.
1.2 Sketch for Task 1
I have drawn out the desired design to improve the aesthetics and clarity of the graph. In this sketch design, there are 2 graphs. The first graph will focus to improve on the aesthetics of the current design while the second graph will focus to improve the clarity.

1.3 Final Design for Task 1
Graph 1
In the the first graph, here is the improvement made:
1. The opacity of the node is reduced
2. Add in label for employees whose closeness centrality is very high
3. Add in the colour gradient. The higher the closeness centrality, the node will be indicated by red while lower closeness centrality will be indicated by yellow
4. Assign width = Weight in the aesthetic of the edge to show how much interactions done among the employees.
g <- GAStech_graph %>%
mutate(betweenness_centrality = centrality_betweenness()) %>%
mutate(closeness_centrality = centrality_closeness()) %>%
ggraph(layout = "nicely") +
geom_edge_link(aes(width = Weight),colour= "black", alpha=0.1, show.legend = FALSE) +
geom_node_point(aes(colour = closeness_centrality, size=betweenness_centrality),alpha=0.7) +
scale_color_gradient(low = "yellow", high = "red")+
geom_node_label(aes(filter=closeness_centrality > 0.015, label= label),
family = "serif",repel = TRUE, label.size = 0.25)
g + theme_graph()

Graph 2
Although the first graph has improved the overall aesthetics, it still does not tell much about the graph. Hence, I make the second graph to gain more information about the graph. In the second graph, we faceted by department and weekdays. Hence, we are able to see when is the most interaction occurs. Which departments has the most interaction with each other. Here is my findings from the second graph:
1. Based on the graph below, I can see that Hideki Cocinaro from security department as the highest interactions on tuesday.
2. People from Executive department do not interact with each other.
3. The interactions happeining at Administration and Information Technology department does not vary much throughout the week.
g1 <- GAStech_graph %>%
mutate(betweenness_centrality = centrality_betweenness()) %>%
mutate(closeness_centrality = centrality_closeness()) %>%
ggraph(layout = "fr") +
geom_edge_link(aes(width = Weight),colour= "black", alpha=0.6, show.legend = FALSE) +
#scale_edge_width(range = c(0.1, 5))+
geom_node_point(aes(colour = closeness_centrality, size=betweenness_centrality),alpha=0.5) +
scale_color_gradient(low = "yellow", high = "red") +
geom_label_repel(aes(x=ifelse(closeness_centrality > 0.015, x, 0),
y=ifelse(closeness_centrality > 0.015, y, 0),
label=ifelse(closeness_centrality > 0.015, label,"")),
fontface = 'bold', color = 'black',
size = 3,
box.padding = 0.80, point.padding = 0.5,
segment.colour = "white",
na.rm=TRUE)
#scale_edge_width(range = c(0.1, 5))
g1 + facet_graph(Weekday~Department,labeller = label_wrap_gen(width=10))

Task 2: Interactive Organisation Graph
2.1 Further data preparation
# data prep
GAStech_edges_aggregated <- GAStech_edges %>%
left_join(GAStech_nodes, by = c("sourceLabel" = "label")) %>%
rename(from = id) %>%
left_join(GAStech_nodes, by = c("targetLabel" = "label")) %>%
rename(to = id) %>%
filter(MainSubject == "Work related") %>%
group_by(from, to) %>%
summarise(weight = n()) %>%
filter(from!=to) %>%
filter(weight > 1) %>%
ungroup()
GAStech_nodes <- GAStech_nodes %>%
rename(group = Department)
2.2 Original Network Grarph
The original network graph from section 7.4 of Hands-on-Exercise 10 is as follow:
#interactivity
visNetwork(GAStech_nodes, GAStech_edges_aggregated) %>%
visIgraphLayout(layout = "layout_with_fr") %>%
visOptions(highlightNearest = TRUE, nodesIdSelection = TRUE)
The graph above adding an interactivity element. User can choose the name of the employee. Then, the connections related to that employees are highlighted. Other than choosing the drop down list, user can also see the highlight by clicking on the node immediately. However, there are few problems with this graph:
1. Only nodes are highlighted without knowing who are the employees exactly.In order to see the label (name),the user has to zoom in.
2. Even with zooming in, the labels are also not clearly seen. It is mixed with all the lines
3. The colour of the node does not tell what the difference is. What is red, green, blue, yellow, purple referring to?
2.3 Sketch for Task 2
For the following sketch, i have improved the aesthetics and the clarity from the previous graph. 
2.4 Final Design for Task 2
In the improved graph, here are the changes made:
1. Adding of legend to clearly show in which department does a particular employee belong to. The departments are also differentiated by colour.
2. Instead of a circle, I change the shape of the node to box. This way, we can see the labels clearly and without overlapping with the edge link.
3. I have also added tooltip to add more interactivity when user hover on the node. The tooltip shows the name of the employees clearly in case the nodes are overlapping with each other.
4. I added the arrow in the edge showing the direction of the link.
5. I have added title to show clearly what this graph is about and also change the description of the dropdown list.
GAStech_nodes$title <- paste0(GAStech_nodes$label)
visNetwork(GAStech_nodes, GAStech_edges_aggregated,main = "Task 2: Interactive Network Graph") %>%
visIgraphLayout(layout = "layout_with_fr") %>%
visEdges(arrows = "to", smooth = FALSE) %>%
visPhysics(stabilization = FALSE) %>%
visInteraction(dragNodes = TRUE, dragView = TRUE, zoomView = FALSE) %>%
visNodes(shape="box", labelHighlightBold = TRUE, font = list(size=30)) %>%
visOptions(highlightNearest = list(enabled = T,degree = list(from = 1, to = 1), hover = F,algorithm = "hierarchical"), nodesIdSelection = list(enabled = TRUE,main = "Employees' name" ))%>%
visLegend(zoom = FALSE)%>%
addFontAwesome()
LS0tDQp0aXRsZTogIklTNDI4OiBEYXRhIFZpenVhbGl6YXRpb24gTWFrZU92ZXIgMiINCmF1dGhvcjogIkF1dGhvcjogVG9tbXkgSm9obnNvbiINCmRhdGU6ICIxNiBOb3ZlbWJlciAyMDE5Ig0Kb3V0cHV0OiBodG1sX25vdGVib29rDQotLS0NCiMgSW5zdGFsbCBQYWNrYWdlcw0KYGBge3J9DQpwYWNrYWdlcyA9IGMoJ2lncmFwaCcsICd0aWR5Z3JhcGgnLCAnZ2dyYXBoJywgJ2dncmVwZWwnLCAndmlzTmV0d29yaycsICdsdWJyaWRhdGUnLCAndGlkeXZlcnNlJykNCg0KZm9yKHAgaW4gcGFja2FnZXMpe2xpYnJhcnkNCiAgaWYoIXJlcXVpcmUocCwgY2hhcmFjdGVyLm9ubHkgPSBUKSl7DQogICAgaW5zdGFsbC5wYWNrYWdlcyhwKQ0KICB9DQogIGxpYnJhcnkocCwgY2hhcmFjdGVyLm9ubHkgPSBUKQ0KfQ0KYGBgDQojIERhdGEgSW1wb3J0IA0KYGBge3J9DQpHQVN0ZWNoX25vZGVzIDwtIHJlYWRfY3N2KCJkYXRhL0dBU3RlY2hfZW1haWxfbm9kZS5jc3YiKQ0KR0FTdGVjaF9lZGdlcyA8LSByZWFkX2NzdigiZGF0YS9HQVN0ZWNoX2VtYWlsX2VkZ2UtdjIuY3N2IikNCmBgYA0KIyBEYXRhIFdyYW5nbGluZyANCmBgYHtyfQ0KDQpHQVN0ZWNoX2VkZ2VzJFNlbnREYXRlICA9IGRteShHQVN0ZWNoX2VkZ2VzJFNlbnREYXRlKQ0KR0FTdGVjaF9lZGdlcyRXZWVrZGF5ID0gd2RheShHQVN0ZWNoX2VkZ2VzJFNlbnREYXRlLCBsYWJlbCA9IFRSVUUsIGFiYnIgPSBGQUxTRSkNCmBgYA0KYGBge3J9DQpHQVN0ZWNoX2VkZ2VzX2FnZ3JlZ2F0ZWQgPC0gR0FTdGVjaF9lZGdlcyAlPiUNCiAgZmlsdGVyKE1haW5TdWJqZWN0ID09ICJXb3JrIHJlbGF0ZWQiKSAlPiUNCiAgZ3JvdXBfYnkoc291cmNlLCB0YXJnZXQsIFdlZWtkYXkpICU+JQ0KICAgIHN1bW1hcmlzZShXZWlnaHQgPSBuKCkpICU+JQ0KICBmaWx0ZXIoc291cmNlIT10YXJnZXQpICU+JQ0KICBmaWx0ZXIoV2VpZ2h0ID4gMSkgJT4lDQogIHVuZ3JvdXAoKQ0KR0FTdGVjaF9lZGdlc19hZ2dyZWdhdGVkDQpgYGANCmBgYHtyfQ0KR0FTdGVjaF9ncmFwaCA8LSB0YmxfZ3JhcGgobm9kZXMgPSBHQVN0ZWNoX25vZGVzLCBlZGdlcyA9IEdBU3RlY2hfZWRnZXNfYWdncmVnYXRlZCwgZGlyZWN0ZWQgPSBUUlVFKQ0KR0FTdGVjaF9ncmFwaA0KYGBgDQpgYGB7cn0NCkdBU3RlY2hfZ3JhcGggJT4lDQogIGFjdGl2YXRlKGVkZ2VzKSAlPiUNCiAgYXJyYW5nZShkZXNjKFdlaWdodCkpDQpgYGANCg0KIyBUYXNrIDE6IFN0YXRpYyBPcmdhbmlzYXRpb24gR3JhcGgNCg0KIyMjIDEuMSBPcmlnaW5hbCBOZXR3b3JrIEdyYXJwaA0KVGhlIDxiPm9yaWdpbmFsIG5ldHdvcmsgZ3JhcGg8L2I+IGZyb20gc2VjdGlvbiA2LjEgb2YgSGFuZHMtb24tRXhlcmNpc2UgMTAgaXMgYXMgZm9sbG93Og0KYGBge3J9DQojIGNvbXB1dGluZyBjZW50cmFsaXR5IGluZGljZXMNCmcgPC0gR0FTdGVjaF9ncmFwaCAlPiUNCiAgbXV0YXRlKGJldHdlZW5uZXNzX2NlbnRyYWxpdHkgPSBjZW50cmFsaXR5X2JldHdlZW5uZXNzKCkpICU+JQ0KICBtdXRhdGUoY2xvc2VuZXNzX2NlbnRyYWxpdHkgPSBjZW50cmFsaXR5X2Nsb3NlbmVzcygpKSAlPiUNCiAgZ2dyYXBoKGxheW91dCA9ICJuaWNlbHkiKSArIA0KICBnZW9tX2VkZ2VfbGluayhhZXMoKSkgKw0KICBnZW9tX25vZGVfcG9pbnQoYWVzKGNvbG91ciA9IGNsb3NlbmVzc19jZW50cmFsaXR5LCBzaXplPWJldHdlZW5uZXNzX2NlbnRyYWxpdHkpKQ0KDQpnICsgdGhlbWVfZ3JhcGgoKQ0KDQpgYGANCg0KVGhlIGdyYXBoIGFib3ZlIHNob3dzIHRoZSBuZXR3b3JrIG9mIGEgcGFydGljdWxhciBlbXBsb3llZSBiYXNlZCBvbiB0aGUgY2xvc2VuZXNzIGNlbnRyYWxpdHkgYW5kIGJldHdlZW5uZXNzIGNlbnRyYWxpdHkuIEhvd2V2ZXIsIHRoZSBhZXN0aGV0aWMgYW5kIGNsYXJpdHkgb2YgdGhlIGdyYXBoIGlzIHN0aWxsIG5vdCBzYXRpc2ZhY3RvcnkuIEl0IGlzIHN0aWxsIGxldmVyYWdpbmcgb24gZ2dyYXBoIDEuMC4NCjxicj4NCjxicj4NCioqTmVnYXRpdmUgcmVtYXJrcyBvbiBjbGFyaXR5OioqIDxicj4NCi0gSSBhbSBub3Qgc3VyZSB3aGljaCBlbXBsb3llZXMgYXJlIG9mIGhpZ2hlciBjbG9uZXNzbmVzcyBjZW50cmFsaXR5IG9yIGJldHdlZW5uZXNzIGNlbnRyYWxpdHkuIDxicj4NCi0gV2l0aCBhbGwgdGhlIGVkZ2VzIHNpbWlsYXIgdG8gZWFjaCBvdGhlciwgSSBhbSBub3Qgc3VyZSB3aGljaCBhcmVhIGhhcyBhIGhpZ2hlciB3ZWlnaHRhZ2UgdGhhbiB0aGUgb3RoZXIuIFRoaXMgbWVhbnMgd2hvIGFyZSB0aGUgZW1wbG95ZWVzIHRoYXQgYXJlIG1vcmUgY29ubmVjdGVkIHdpdGggZWFjaCBvdGhlci4gPGJyPg0KLSBKdXN0IGZyb20gbG9va2luZyB0aGUgZ3JhcGggYXQgYSBnbGFuY2UsIEkgY2Fubm90IGRlcml2ZSBtdWNoIGluZm9ybWF0aW9uLiBGb3IgZXhhbXBsZSwgd2hlbiBhcmUgdGhlIHRpbWUgdGhleSBpbnRlcmFjdHM/IEZyb20gd2hpY2ggZGVwYXJ0bWVudHMgYXJlIHRoZXkgZnJvbT8NCg0KKipOZWdhdGl2ZSByZW1hcmtzIG9uIGFlc3RoZXRpY3M6KiogPGJyPg0KLSBUaGUgbm9kZXMgYXJlIG92ZXJsYXBwaW5nIG9mIGVhY2ggb3RoZXIuIEhlbmNlLCBtYWtpbmcgY2VydGFpbiBub2RlcyBub3Qgb2J2aW91cyA8YnI+DQotIE5vdCBhbGwgbm9kZXMgY2FuIGJlIHNlZW4gZHVlIHRvIHRoZSBjb2xvdXIgY29tcGxlbWVudCB3aXRoIHRoZSBibGFjayBlZGdlcy48YnI+DQoNCiMjIyAxLjIgU2tldGNoIGZvciBUYXNrIDENCkkgaGF2ZSBkcmF3biBvdXQgdGhlIGRlc2lyZWQgZGVzaWduIHRvIGltcHJvdmUgdGhlIGFlc3RoZXRpY3MgYW5kIGNsYXJpdHkgb2YgdGhlIGdyYXBoLiBJbiB0aGlzIHNrZXRjaCBkZXNpZ24sIHRoZXJlIGFyZSAyIGdyYXBocy4gVGhlIGZpcnN0IGdyYXBoIHdpbGwgZm9jdXMgdG8gaW1wcm92ZSBvbiB0aGUgYWVzdGhldGljcyBvZiB0aGUgY3VycmVudCBkZXNpZ24gd2hpbGUgdGhlIHNlY29uZCBncmFwaCB3aWxsIGZvY3VzIHRvIGltcHJvdmUgdGhlIGNsYXJpdHkuIDxicj4NCg0KIVtdKFBpY3R1cmUvU2tldGNoVGFzazEuanBnKQ0KDQojIyMgMS4zIEZpbmFsIERlc2lnbiBmb3IgVGFzayAxDQojIyMjIEdyYXBoIDENCkluIHRoZSB0aGUgZmlyc3QgZ3JhcGgsIGhlcmUgaXMgdGhlIGltcHJvdmVtZW50IG1hZGU6IDxicj4gDQoxLiBUaGUgb3BhY2l0eSBvZiB0aGUgbm9kZSBpcyByZWR1Y2VkIDxicj4NCjIuIEFkZCBpbiBsYWJlbCBmb3IgZW1wbG95ZWVzIHdob3NlIGNsb3NlbmVzcyBjZW50cmFsaXR5IGlzIHZlcnkgaGlnaCA8YnI+DQozLiBBZGQgaW4gdGhlIGNvbG91ciBncmFkaWVudC4gVGhlIGhpZ2hlciB0aGUgY2xvc2VuZXNzIGNlbnRyYWxpdHksIHRoZSBub2RlIHdpbGwgYmUgaW5kaWNhdGVkIGJ5IHJlZCB3aGlsZSBsb3dlciBjbG9zZW5lc3MgY2VudHJhbGl0eSB3aWxsIGJlIGluZGljYXRlZCBieSB5ZWxsb3cgPGJyPg0KNC4gQXNzaWduIHdpZHRoID0gV2VpZ2h0IGluIHRoZSBhZXN0aGV0aWMgb2YgdGhlIGVkZ2UgdG8gc2hvdyBob3cgbXVjaCBpbnRlcmFjdGlvbnMgZG9uZSBhbW9uZyB0aGUgZW1wbG95ZWVzLg0KDQpgYGB7cn0NCmcgPC0gR0FTdGVjaF9ncmFwaCAlPiUNCiAgbXV0YXRlKGJldHdlZW5uZXNzX2NlbnRyYWxpdHkgPSBjZW50cmFsaXR5X2JldHdlZW5uZXNzKCkpICU+JQ0KICBtdXRhdGUoY2xvc2VuZXNzX2NlbnRyYWxpdHkgPSBjZW50cmFsaXR5X2Nsb3NlbmVzcygpKSAlPiUNCiAgZ2dyYXBoKGxheW91dCA9ICJuaWNlbHkiKSArDQogIGdlb21fZWRnZV9saW5rKGFlcyh3aWR0aCA9IFdlaWdodCksY29sb3VyPSAiYmxhY2siLCBhbHBoYT0wLjEsIHNob3cubGVnZW5kID0gRkFMU0UpICsNCiAgZ2VvbV9ub2RlX3BvaW50KGFlcyhjb2xvdXIgPSBjbG9zZW5lc3NfY2VudHJhbGl0eSwgc2l6ZT1iZXR3ZWVubmVzc19jZW50cmFsaXR5KSxhbHBoYT0wLjcpICsNCiAgc2NhbGVfY29sb3JfZ3JhZGllbnQobG93ID0gInllbGxvdyIsIGhpZ2ggPSAicmVkIikrDQoNCiAgZ2VvbV9ub2RlX2xhYmVsKGFlcyhmaWx0ZXI9Y2xvc2VuZXNzX2NlbnRyYWxpdHkgPiAwLjAxNSwgbGFiZWw9IGxhYmVsKSwNCiAgICAgICAgICAgICAgICAgZmFtaWx5ID0gInNlcmlmIixyZXBlbCA9IFRSVUUsIGxhYmVsLnNpemUgPSAwLjI1KSANCmcgKyB0aGVtZV9ncmFwaCgpDQpgYGANCg0KIyMjIyBHcmFwaCAyDQpBbHRob3VnaCB0aGUgZmlyc3QgZ3JhcGggaGFzIGltcHJvdmVkIHRoZSBvdmVyYWxsIGFlc3RoZXRpY3MsIGl0IHN0aWxsIGRvZXMgbm90IHRlbGwgbXVjaCBhYm91dCB0aGUgZ3JhcGguIEhlbmNlLCBJIG1ha2UgdGhlIHNlY29uZCBncmFwaCB0byBnYWluIG1vcmUgaW5mb3JtYXRpb24gYWJvdXQgdGhlIGdyYXBoLiBJbiB0aGUgc2Vjb25kIGdyYXBoLCB3ZSBmYWNldGVkIGJ5IGRlcGFydG1lbnQgYW5kIHdlZWtkYXlzLiBIZW5jZSwgd2UgYXJlIGFibGUgdG8gc2VlIHdoZW4gaXMgdGhlIG1vc3QgaW50ZXJhY3Rpb24gb2NjdXJzLiBXaGljaCBkZXBhcnRtZW50cyBoYXMgdGhlIG1vc3QgaW50ZXJhY3Rpb24gd2l0aCBlYWNoIG90aGVyLiBIZXJlIGlzIG15IGZpbmRpbmdzIGZyb20gdGhlIHNlY29uZCBncmFwaDogDQo8YnI+DQoxLiBCYXNlZCBvbiB0aGUgZ3JhcGggYmVsb3csIEkgY2FuIHNlZSB0aGF0IEhpZGVraSBDb2NpbmFybyBmcm9tIHNlY3VyaXR5IGRlcGFydG1lbnQgYXMgdGhlIGhpZ2hlc3QgaW50ZXJhY3Rpb25zIG9uIHR1ZXNkYXkuIDxicj4NCjIuIFBlb3BsZSBmcm9tIEV4ZWN1dGl2ZSBkZXBhcnRtZW50IGRvIG5vdCBpbnRlcmFjdCB3aXRoIGVhY2ggb3RoZXIuIDxicj4NCjMuIFRoZSBpbnRlcmFjdGlvbnMgaGFwcGVpbmluZyBhdCBBZG1pbmlzdHJhdGlvbiBhbmQgSW5mb3JtYXRpb24gVGVjaG5vbG9neSBkZXBhcnRtZW50IGRvZXMgbm90IHZhcnkgbXVjaCB0aHJvdWdob3V0IHRoZSB3ZWVrLg0KYGBge3IgZmlnNSwgZmlnLndpZHRoID0gMTEsIGZpZy5hc3AgPSAxfQ0KZzEgPC0gR0FTdGVjaF9ncmFwaCAlPiUNCiAgbXV0YXRlKGJldHdlZW5uZXNzX2NlbnRyYWxpdHkgPSBjZW50cmFsaXR5X2JldHdlZW5uZXNzKCkpICU+JQ0KICBtdXRhdGUoY2xvc2VuZXNzX2NlbnRyYWxpdHkgPSBjZW50cmFsaXR5X2Nsb3NlbmVzcygpKSAlPiUNCiAgZ2dyYXBoKGxheW91dCA9ICJmciIpICsNCiAgZ2VvbV9lZGdlX2xpbmsoYWVzKHdpZHRoID0gV2VpZ2h0KSxjb2xvdXI9ICJibGFjayIsIGFscGhhPTAuNiwgc2hvdy5sZWdlbmQgPSBGQUxTRSkgKw0KICAjc2NhbGVfZWRnZV93aWR0aChyYW5nZSA9IGMoMC4xLCA1KSkrDQogIA0KICBnZW9tX25vZGVfcG9pbnQoYWVzKGNvbG91ciA9IGNsb3NlbmVzc19jZW50cmFsaXR5LCBzaXplPWJldHdlZW5uZXNzX2NlbnRyYWxpdHkpLGFscGhhPTAuNSkgKw0KICBzY2FsZV9jb2xvcl9ncmFkaWVudChsb3cgPSAieWVsbG93IiwgaGlnaCA9ICJyZWQiKSAgKw0KICBnZW9tX2xhYmVsX3JlcGVsKGFlcyh4PWlmZWxzZShjbG9zZW5lc3NfY2VudHJhbGl0eSA+IDAuMDE1LCB4LCAwKSwgDQogICAgICAgICAgICAgICAgICAgICAgeT1pZmVsc2UoY2xvc2VuZXNzX2NlbnRyYWxpdHkgPiAwLjAxNSwgeSwgMCksDQogICAgICAgICAgICAgICAgICAgICAgbGFiZWw9aWZlbHNlKGNsb3NlbmVzc19jZW50cmFsaXR5ID4gMC4wMTUsIGxhYmVsLCIiKSksDQogICAgICAgICAgICAgICAgICBmb250ZmFjZSA9ICdib2xkJywgY29sb3IgPSAnYmxhY2snLA0KICAgICAgICAgICAgICAgICAgc2l6ZSA9IDMsDQogICAgICAgICAgICAgICAgICBib3gucGFkZGluZyA9IDAuODAsIHBvaW50LnBhZGRpbmcgPSAwLjUsDQogICAgICAgICAgICAgICAgICBzZWdtZW50LmNvbG91ciA9ICJ3aGl0ZSIsDQogICAgICAgICAgICAgICAgICBuYS5ybT1UUlVFKQ0KICANCiAgI3NjYWxlX2VkZ2Vfd2lkdGgocmFuZ2UgPSBjKDAuMSwgNSkpDQpnMSArIGZhY2V0X2dyYXBoKFdlZWtkYXl+RGVwYXJ0bWVudCxsYWJlbGxlciA9IGxhYmVsX3dyYXBfZ2VuKHdpZHRoPTEwKSkgDQpgYGANCg0KIyBUYXNrIDI6IEludGVyYWN0aXZlIE9yZ2FuaXNhdGlvbiBHcmFwaA0KDQojIyMgMi4xIEZ1cnRoZXIgZGF0YSBwcmVwYXJhdGlvbg0KYGBge3J9DQojIGRhdGEgcHJlcA0KR0FTdGVjaF9lZGdlc19hZ2dyZWdhdGVkIDwtIEdBU3RlY2hfZWRnZXMgJT4lDQogIGxlZnRfam9pbihHQVN0ZWNoX25vZGVzLCBieSA9IGMoInNvdXJjZUxhYmVsIiA9ICJsYWJlbCIpKSAlPiUNCiAgcmVuYW1lKGZyb20gPSBpZCkgJT4lDQogIGxlZnRfam9pbihHQVN0ZWNoX25vZGVzLCBieSA9IGMoInRhcmdldExhYmVsIiA9ICJsYWJlbCIpKSAlPiUNCiAgcmVuYW1lKHRvID0gaWQpICU+JQ0KICBmaWx0ZXIoTWFpblN1YmplY3QgPT0gIldvcmsgcmVsYXRlZCIpICU+JQ0KICBncm91cF9ieShmcm9tLCB0bykgJT4lDQogICAgc3VtbWFyaXNlKHdlaWdodCA9IG4oKSkgJT4lDQogIGZpbHRlcihmcm9tIT10bykgJT4lDQogIGZpbHRlcih3ZWlnaHQgPiAxKSAlPiUNCiAgdW5ncm91cCgpDQpgYGANCmBgYHtyfQ0KR0FTdGVjaF9ub2RlcyA8LSBHQVN0ZWNoX25vZGVzICU+JQ0KICByZW5hbWUoZ3JvdXAgPSBEZXBhcnRtZW50KQ0KYGBgDQojIyMgMi4yIE9yaWdpbmFsIE5ldHdvcmsgR3JhcnBoDQpUaGUgPGI+b3JpZ2luYWwgbmV0d29yayBncmFwaDwvYj4gZnJvbSBzZWN0aW9uIDcuNCBvZiBIYW5kcy1vbi1FeGVyY2lzZSAxMCBpcyBhcyBmb2xsb3c6DQpgYGB7cn0NCiNpbnRlcmFjdGl2aXR5DQp2aXNOZXR3b3JrKEdBU3RlY2hfbm9kZXMsIEdBU3RlY2hfZWRnZXNfYWdncmVnYXRlZCkgJT4lDQogIHZpc0lncmFwaExheW91dChsYXlvdXQgPSAibGF5b3V0X3dpdGhfZnIiKSAlPiUNCiAgdmlzT3B0aW9ucyhoaWdobGlnaHROZWFyZXN0ID0gVFJVRSwgbm9kZXNJZFNlbGVjdGlvbiA9IFRSVUUpDQpgYGANClRoZSBncmFwaCBhYm92ZSBhZGRpbmcgYW4gaW50ZXJhY3Rpdml0eSBlbGVtZW50LiBVc2VyIGNhbiBjaG9vc2UgdGhlIG5hbWUgb2YgdGhlIGVtcGxveWVlLiBUaGVuLCB0aGUgY29ubmVjdGlvbnMgcmVsYXRlZCB0byB0aGF0IGVtcGxveWVlcyBhcmUgaGlnaGxpZ2h0ZWQuIE90aGVyIHRoYW4gY2hvb3NpbmcgdGhlIGRyb3AgZG93biBsaXN0LCB1c2VyIGNhbiBhbHNvIHNlZSB0aGUgaGlnaGxpZ2h0IGJ5IGNsaWNraW5nIG9uIHRoZSBub2RlIGltbWVkaWF0ZWx5LiBIb3dldmVyLCB0aGVyZSBhcmUgZmV3IHByb2JsZW1zIHdpdGggdGhpcyBncmFwaDogPGJyPg0KMS4gT25seSBub2RlcyBhcmUgaGlnaGxpZ2h0ZWQgd2l0aG91dCBrbm93aW5nIHdobyBhcmUgdGhlIGVtcGxveWVlcyBleGFjdGx5LkluIG9yZGVyIHRvIHNlZSB0aGUgbGFiZWwgKG5hbWUpLHRoZSB1c2VyIGhhcyB0byB6b29tIGluLiA8YnI+IA0KMi4gRXZlbiB3aXRoIHpvb21pbmcgaW4sIHRoZSBsYWJlbHMgYXJlIGFsc28gbm90IGNsZWFybHkgc2Vlbi4gSXQgaXMgbWl4ZWQgd2l0aCBhbGwgdGhlIGxpbmVzIDxicj4NCjMuIFRoZSBjb2xvdXIgb2YgdGhlIG5vZGUgZG9lcyBub3QgdGVsbCB3aGF0IHRoZSBkaWZmZXJlbmNlIGlzLiBXaGF0IGlzIHJlZCwgZ3JlZW4sIGJsdWUsIHllbGxvdywgcHVycGxlIHJlZmVycmluZyB0bz8gPGJyPg0KDQojIyMgMi4zIFNrZXRjaCBmb3IgVGFzayAyDQpGb3IgdGhlIGZvbGxvd2luZyBza2V0Y2gsIGkgaGF2ZSBpbXByb3ZlZCB0aGUgYWVzdGhldGljcyBhbmQgdGhlIGNsYXJpdHkgZnJvbSB0aGUgcHJldmlvdXMgZ3JhcGguIA0KIVtdKFBpY3R1cmUvU2tldGNoVGFzazIuanBnKQ0KDQojIyMgMi40IEZpbmFsIERlc2lnbiBmb3IgVGFzayAyDQpJbiB0aGUgaW1wcm92ZWQgZ3JhcGgsIGhlcmUgYXJlIHRoZSBjaGFuZ2VzIG1hZGU6IDxicj4NCjEuIEFkZGluZyBvZiBsZWdlbmQgdG8gY2xlYXJseSBzaG93IGluIHdoaWNoIGRlcGFydG1lbnQgZG9lcyBhIHBhcnRpY3VsYXIgZW1wbG95ZWUgYmVsb25nIHRvLiBUaGUgZGVwYXJ0bWVudHMgYXJlIGFsc28gZGlmZmVyZW50aWF0ZWQgYnkgY29sb3VyLjxicj4NCjIuIEluc3RlYWQgb2YgYSBjaXJjbGUsIEkgY2hhbmdlIHRoZSBzaGFwZSBvZiB0aGUgbm9kZSB0byBib3guIFRoaXMgd2F5LCB3ZSBjYW4gc2VlIHRoZSBsYWJlbHMgY2xlYXJseSBhbmQgd2l0aG91dCBvdmVybGFwcGluZyB3aXRoIHRoZSBlZGdlIGxpbmsuIDxicj4NCjMuIEkgaGF2ZSBhbHNvIGFkZGVkIHRvb2x0aXAgdG8gYWRkIG1vcmUgaW50ZXJhY3Rpdml0eSB3aGVuIHVzZXIgaG92ZXIgb24gdGhlIG5vZGUuIFRoZSB0b29sdGlwIHNob3dzIHRoZSBuYW1lIG9mIHRoZSBlbXBsb3llZXMgY2xlYXJseSBpbiBjYXNlIHRoZSBub2RlcyBhcmUgb3ZlcmxhcHBpbmcgd2l0aCBlYWNoIG90aGVyLiA8YnI+DQo0LiBJIGFkZGVkIHRoZSBhcnJvdyBpbiB0aGUgZWRnZSBzaG93aW5nIHRoZSBkaXJlY3Rpb24gb2YgdGhlIGxpbmsuIDxicj4NCjUuIEkgaGF2ZSBhZGRlZCB0aXRsZSB0byBzaG93IGNsZWFybHkgd2hhdCB0aGlzIGdyYXBoIGlzIGFib3V0IGFuZCBhbHNvIGNoYW5nZSB0aGUgZGVzY3JpcHRpb24gb2YgdGhlIGRyb3Bkb3duIGxpc3QuIA0KDQpgYGB7ciBmaWc2LCBmaWcud2lkdGggPTEwfQ0KR0FTdGVjaF9ub2RlcyR0aXRsZSA8LSBwYXN0ZTAoR0FTdGVjaF9ub2RlcyRsYWJlbCkNCnZpc05ldHdvcmsoR0FTdGVjaF9ub2RlcywgR0FTdGVjaF9lZGdlc19hZ2dyZWdhdGVkLG1haW4gPSAiVGFzayAyOiBJbnRlcmFjdGl2ZSBOZXR3b3JrIEdyYXBoIikgJT4lDQogIHZpc0lncmFwaExheW91dChsYXlvdXQgPSAibGF5b3V0X3dpdGhfZnIiKSAlPiUNCiAgdmlzRWRnZXMoYXJyb3dzID0gInRvIiwgc21vb3RoID0gRkFMU0UpICU+JQ0KICB2aXNQaHlzaWNzKHN0YWJpbGl6YXRpb24gPSBGQUxTRSkgJT4lDQogIHZpc0ludGVyYWN0aW9uKGRyYWdOb2RlcyA9IFRSVUUsIGRyYWdWaWV3ID0gVFJVRSwgem9vbVZpZXcgPSBGQUxTRSkgJT4lDQogIHZpc05vZGVzKHNoYXBlPSJib3giLCBsYWJlbEhpZ2hsaWdodEJvbGQgPSBUUlVFLCBmb250ID0gbGlzdChzaXplPTMwKSkgJT4lDQogIHZpc09wdGlvbnMoaGlnaGxpZ2h0TmVhcmVzdCA9IGxpc3QoZW5hYmxlZCA9IFQsZGVncmVlID0gIGxpc3QoZnJvbSA9IDEsIHRvID0gMSksIGhvdmVyID0gRixhbGdvcml0aG0gPSAiaGllcmFyY2hpY2FsIiksIG5vZGVzSWRTZWxlY3Rpb24gPSBsaXN0KGVuYWJsZWQgPSBUUlVFLG1haW4gPSAiRW1wbG95ZWVzJyBuYW1lIiApKSU+JQ0KICB2aXNMZWdlbmQoem9vbSA9IEZBTFNFKSU+JQ0KICBhZGRGb250QXdlc29tZSgpDQpgYGANCiAg