1. PREPARE
To help us better understand the context, questions, and data
sources, this section will focus on the following topics:
- Context. This paper examines definitions of
computational thinking from the literature.
- Questions. [Question for you]
- Project Setup. This should be very familiar by now,
but we’ll set up a new R project and install and load the required
packages for the walkthrough.
1a. Context
Not the same: a text network analysis on computational thinking
definitions to study its relationship with computer programming
Abstract
Even though countries from all over the world are modifying their
national educational curriculum in order to include computational
thinking skills, there is not an agreement in the definition of this
ability. This is partly caused by the myriad of definitions that has
been proposed by the scholar community. In fact, there are multiple
examples in educational scenarios in which coding and even robotics are
considered as synonymous of computational thinking. This paper presents
a text network analysis of the main definitions of this skill that have
been found in the literature, aiming to offer insights on the common
characteristics they share and on their relationship with computer
programming. As a result, a new definition of computational thinking is
proposed, which emerge from the analysed data.
Data Source
✅ Comprehension Check
Based on your reading, what’s the data source in this paper?
1b. Guiding Questions
✅ Comprehension Check
What’s the research question in this paper? Why is text network
analysis an appropriate methodology to address the research
question?
1c. Set Up
As highlighted in Chapter 6 of Data
Science in Education Using R (DSIEUR), one of the first steps of
every workflow should be to set up a “Project” within RStudio. This will
be your “home” for any files and code used or created in previous
units.
You are welcome to continue using the same project created for
previous units, or create an entirely new project for Unit 4. However,
after you’ve created your project open up a new R script, and load the
following packages that we’ll be needing for this walkthrough:
library(dplyr)
library(tidytext)
library(tidyverse)
library(tidyr)
library(ggplot2)
library(igraph)
library(ggraph)
At the end of this week, I encourage you share with me your R script
as evidence that you have complete the walkthrough. Although I highly
recommend that that you manually type the code shared throughout this
walkthrough, for large blocks of text it may be easier to copy and
paste.
2. WRANGLE
2a. Import Data
Now let’s read our data into our Environment using the
read_csv()
function and assign it to a variable name so we
can work with it like any other object in R.
CTdefinition <- read_csv("data/definition.csv")
## Rows: 8 Columns: 1
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ","
## chr (1): definition
##
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
We can see that we have 8 different definitions for CT (computational
thinking). The definitions were taken from the paper. The paper includes
more than 8 definitions. Here, we use 8 definitions as an exemplar
dataset.
2b. Tokenizing text into bigrams
Next, we will use some familiar tidytext
functions for
tokenizing text. But this time, we will tokenize bigram, instead of
unigrams (or single words) in the sentiment analysis unit. We can also
tokenize trigrams etc.
Let’s tokenize our definition text and by using the familiar
unnest_tokens()
, by specifying n=2 n = 2
to
get bigrams:
ct_bigrams <- CTdefinition %>%
unnest_tokens(bigram, definition, token = "ngrams", n = 2)
Now let’s do a quick count to see common bigrams:
ct_bigrams %>%
count(bigram, sort = TRUE)
## # A tibble: 452 × 2
## bigram n
## <chr> <int>
## 1 computer science 5
## 2 ct is 5
## 3 is a 5
## 4 a computer 4
## 5 can be 4
## 6 problem solving 4
## 7 that can 4
## 8 a problem 3
## 9 in a 3
## 10 of computer 3
## # … with 442 more rows
You might notice that the most frequent bigram is “computer science”.
This makes sense as the researcher (i.e., Jeannette M Wing) who created
the concept was from the field of computer science. You might noticed
that the largest frequency is 5. It makes sense as we only have 8
definitions. For your independent analysis, you should use a big
dataset. Here, it’s only for walkthrough demo.
2c. Remove stop words
In this context, stop words might be not helpful for us to explore
the definition. Next, we will remove stop words. Different from unigrams
(or single words), we cannot remove stop words directly. We should first
seperate the diagrams into two columns and then remove stop words in
both columns using separate
and filter
:
bigrams_separated <- ct_bigrams %>%
separate(bigram, c("word1", "word2"), sep = " ")
bigrams_filtered <- bigrams_separated %>%
filter(!word1 %in% stop_words$word) %>%
filter(!word2 %in% stop_words$word)
bigram_counts <- bigrams_filtered %>%
count(word1, word2, sort = TRUE)
bigram_counts
## # A tibble: 86 × 3
## word1 word2 n
## <chr> <chr> <int>
## 1 computer science 5
## 2 solving methodology 2
## 3 solving process 2
## 4 abstraction automation 1
## 5 abstraction decomposition 1
## 6 abstraction recursion 1
## 7 algorithmic notions 1
## 8 algorithmic thinking 1
## 9 analysis ct 1
## 10 analyze data 1
## # … with 76 more rows
Now, in bigram_counts, all stop words are removed.
We can also combine the separated words with unite
:
bigrams_united <- bigrams_filtered %>%
unite(bigram, word1, word2, sep = " ")
bigrams_united
## # A tibble: 92 × 1
## bigram
## <chr>
## 1 people engaged
## 2 computer hobbyist
## 3 hobbyist clubs
## 4 running computer
## 5 computer drop
## 6 computers simply
## 7 shareable kinds
## 8 integrate computational
## 9 computational thinking
## 10 everyday life
## # … with 82 more rows
3. VISUALIZE WORD NETWORK
This is a word network from the paper:

You can see that all nodes are connected with lines. In this
visualization, the lines have no direction. But we can turn lines to
edges. When we have edges, we need three variables to visualize a word
net:
- from: the node an edge is coming from
- to: the node an edge is going towards
- weight: A numeric value associated with each
edge
We need to transform our dataset (bigram_counts) into these variables
in the following way: from
is the “word1”, to
is the “word2”, and weight
is “n”.
Let’s use graph_from_data_frame
to make the
transformation:
bigram_graph <- bigram_counts %>%
graph_from_data_frame()
bigram_graph
## IGRAPH 489f7e9 DN-- 117 86 --
## + attr: name (v/c), n (e/n)
## + edges from 489f7e9 (vertex names):
## [1] computer ->science solving ->methodology
## [3] solving ->process abstraction ->automation
## [5] abstraction ->decomposition abstraction ->recursion
## [7] algorithmic ->notions algorithmic ->thinking
## [9] analysis ->ct analyze ->data
## [11] analyzing ->data applicable ->attitude
## [13] artifacts ->ct automating ->solutions
## [15] broad ->story broader ->discipline
## + ... omitted several edges
Since lots of bigrams only appear one time, let’s only keep those
appearing more than one time
bigram_graph_filtered <- bigram_counts %>%
filter(n > 1) %>%
graph_from_data_frame()
bigram_graph_filtered
## IGRAPH 5d322a8 DN-- 5 3 --
## + attr: name (v/c), n (e/n)
## + edges from 5d322a8 (vertex names):
## [1] computer->science solving ->methodology solving ->process
Now, we have only three bigrams left. Please use a larger dataset so
that you will not end up with visualizing only three bigrams.
Next, let’s go ahead and visualize the word net before filtering:
set.seed(100)
a <- grid::arrow(type = "open", length = unit(.2, "inches"))
ggraph(bigram_graph, layout = "fr") +
geom_edge_link(aes(edge_alpha = n), show.legend = FALSE,
arrow = a, end_cap = circle(.07, 'inches')) +
geom_node_point(color = "red", size = 3) +
geom_node_text(aes(label = name), vjust = 1, hjust = 1) +
theme_void()

✅ Comprehension Check
Revise the code in the previous code chunk so that there are no
arrows. The graph shows lines instead of arrows.
set.seed(100)
bigram_graph2 <- bigram_counts %>%
filter(n > 1) %>%
graph_from_data_frame()
ggraph(bigram_graph2, layout = "fr") +
geom_edge_link(aes(edge_alpha = n), show.legend = FALSE)+
geom_node_point(color = "red", size = 3) +
geom_node_text(aes(label = name), vjust = 1, hjust = 1) +
theme_void()

Revise the code in the previous code chunk so that there are no
arrows and the width of the lines represents the frequency of bigrams.
This is a documentation
that you can use to find the answer.
There are many other encoding options you can play with, such as
changing the color of specific nodes. Remember you encoding should serve
the purpose of drawing useful insights from the word net.
In comparison, this is the net after filtering:
set.seed(100)
a <- grid::arrow(type = "closed", length = unit(.2, "inches"))
ggraph(bigram_graph_filtered, layout = "fr") +
geom_edge_link(aes(edge_alpha = n), show.legend = FALSE,
arrow = a, end_cap = circle(.07, 'inches')) +
geom_node_point(color = "red", size = 3) +
geom_node_text(aes(label = name), vjust = 1, hjust = 1) +
theme_void()

We have only three connections left. We can see that computer science
and problem solving are important concepts in CT, which is the core idea
from Jeannette M Wing. No matter what changes over time or how we
conceptualize CT differently, these two are the core concepts. Is that
true, though? This is an open question for the field to explore.
Once again, please use a larger dataset for your independent
analysis.
Unit Takeaway
One main lesson I’m hoping you take away from this walkthrough is
that we should find an appropriate scenario using word
net. It’s easy to visualize word net. But how could we make
meanings out of it? We should first closely read the research question
and then apply an appropriate technique to answer the research
question.
LS0tCnRpdGxlOiAiVW5pdCA0IFdhbGt0aHJvdWdoOiBCaWdyYW1zICYgd29yZCBuZXR3b3JrIgpvdXRwdXQ6IAogIGh0bWxfZG9jdW1lbnQ6CiAgICB0b2M6IHRydWUKICAgIHRvY19kZXB0aDogMwogICAgdG9jX2Zsb2F0OiB5ZXMKICAgIGNvZGVfZm9sZGluZzogaGlkZQogICAgY29kZV9kb3dubG9hZDogVFJVRQplZGl0b3Jfb3B0aW9uczogCiAgbWFya2Rvd246IAogICAgd3JhcDogNzIKLS0tCgpgYGB7ciBzZXR1cCwgaW5jbHVkZT1GQUxTRX0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KGVjaG8gPSBUUlVFKQpgYGAKCiMjIDAuIElOVFJPRFVDVElPTgoKSW4gdGhlIFVuaXQgNCB3YWxrdGhyb3VnaCwgd2Ugd2lsbCByZXBsaWNhdGUgYSBzaW1wbGVyIHZlcnNpb24gb2YgdGhlCmZvbGxvd2luZyBwYXBlcjogW05vdCB0aGUgc2FtZTogYSB0ZXh0IG5ldHdvcmsgYW5hbHlzaXMgb24gY29tcHV0YXRpb25hbAp0aGlua2luZyBkZWZpbml0aW9ucyB0byBzdHVkeSBpdHMgcmVsYXRpb25zaGlwIHdpdGggY29tcHV0ZXIKcHJvZ3JhbW1pbmddKGh0dHBzOi8vd3d3LnJlc2VhcmNoZ2F0ZS5uZXQvcHVibGljYXRpb24vMzM4MTg4OTUzX05vdF90aGVfc2FtZV9hX3RleHRfbmV0d29ya19hbmFseXNpc19vbl9jb21wdXRhdGlvbmFsX3RoaW5raW5nX2RlZmluaXRpb25zX3RvX3N0dWR5X2l0c19yZWxhdGlvbnNoaXBfd2l0aF9jb21wdXRlcl9wcm9ncmFtbWluZykuClRoaXMgcGFwZXIgcmV2aWV3cyBkZWZpbml0aW9ucyBmb3IgY29tcHV0YXRpb25hbCB0aGlua2luZyBpbiB0aGUKbGl0ZXJhdHVyZS4gWW91IG1pZ2h0IGhhdmUgbm90aWNlZCB0aGF0IGluIG91ciBmaWVsZCwgdGhlIHNhbWUKdGVybWlub2xvZ3kgY291bGQgbWVhbiBkaWZmZXJlbnQgdGhpbmdzLCBlc3BlY2lhbGx5IGZvciBlbWVyZ2luZwp0ZXJtaW5vbG9naWVzIHN1Y2ggYXMgY29tcHV0YXRpb25hbCB0aGlua2luZy4gVGhpcyBwYXBlciBjb250cmlidXRlcyB0bwp1bmRlcnN0YW5kaW5ncyBob3cgZGlmZmVyZW50IHJlc2VhcmNoIHRlYW1zIGNvbmNlcHR1YWxpemUgY29tcHV0YXRpb25hbAp0aGlua2luZy4KCiMjIyBXYWxrdGhyb3VnaCBGb2N1cwoKU2ltaWxhciB0byBwcmV2aW91cyB3YWxrdGhyb3VnaHMsIHdlIHNob3VsZCBmaXJzdCB1bmRlcnN0YW5kIHRoZSBjb250ZXh0CmFuZCBkYXRhc2V0IGJ5IHJlYWRpbmcgdGhlIHBhcGVyIChwcmVwYXJlKSwgYW5kIHRoZW4gd3JhbmdsZSB0aGUgZGF0YQood3JhbmdsZSksIGFuZCB0aGVuIGV4cGxvcmUgYW5kIHZpc3VhbGl6ZSBvdXIgZGF0YSAoZXhwbG9yZSAmCmNvbW11bmljYXRlKS4KCi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQoKIyMgMS4gUFJFUEFSRQoKVG8gaGVscCB1cyBiZXR0ZXIgdW5kZXJzdGFuZCB0aGUgY29udGV4dCwgcXVlc3Rpb25zLCBhbmQgZGF0YSBzb3VyY2VzLAp0aGlzIHNlY3Rpb24gd2lsbCBmb2N1cyBvbiB0aGUgZm9sbG93aW5nIHRvcGljczoKCmEuICAqKkNvbnRleHQqKi4gVGhpcyBwYXBlciBleGFtaW5lcyBkZWZpbml0aW9ucyBvZiBjb21wdXRhdGlvbmFsCiAgICB0aGlua2luZyBmcm9tIHRoZSBsaXRlcmF0dXJlLgpiLiAgKipRdWVzdGlvbnMuKiogW1F1ZXN0aW9uIGZvciB5b3VdCmMuICAqKlByb2plY3QgU2V0dXAuKiogVGhpcyBzaG91bGQgYmUgdmVyeSBmYW1pbGlhciBieSBub3csIGJ1dCB3ZSdsbAogICAgc2V0IHVwIGEgbmV3IFIgcHJvamVjdCBhbmQgaW5zdGFsbCBhbmQgbG9hZCB0aGUgcmVxdWlyZWQgcGFja2FnZXMKICAgIGZvciB0aGUgd2Fsa3Rocm91Z2guCgojIyMgMWEuIENvbnRleHQKCiMjIyMgTm90IHRoZSBzYW1lOiBhIHRleHQgbmV0d29yayBhbmFseXNpcyBvbiBjb21wdXRhdGlvbmFsIHRoaW5raW5nIGRlZmluaXRpb25zIHRvIHN0dWR5IGl0cyByZWxhdGlvbnNoaXAgd2l0aCBjb21wdXRlciBwcm9ncmFtbWluZwoKKipBYnN0cmFjdCoqCgpFdmVuIHRob3VnaCBjb3VudHJpZXMgZnJvbSBhbGwgb3ZlciB0aGUgd29ybGQgYXJlIG1vZGlmeWluZyB0aGVpcgpuYXRpb25hbCBlZHVjYXRpb25hbCBjdXJyaWN1bHVtIGluIG9yZGVyIHRvIGluY2x1ZGUgY29tcHV0YXRpb25hbAp0aGlua2luZyBza2lsbHMsIHRoZXJlIGlzIG5vdCBhbiBhZ3JlZW1lbnQgaW4gdGhlIGRlZmluaXRpb24gb2YgdGhpcwphYmlsaXR5LiBUaGlzIGlzIHBhcnRseSBjYXVzZWQgYnkgdGhlIG15cmlhZCBvZiBkZWZpbml0aW9ucyB0aGF0IGhhcwpiZWVuIHByb3Bvc2VkIGJ5IHRoZSBzY2hvbGFyIGNvbW11bml0eS4gSW4gZmFjdCwgdGhlcmUgYXJlIG11bHRpcGxlCmV4YW1wbGVzIGluIGVkdWNhdGlvbmFsIHNjZW5hcmlvcyBpbiB3aGljaCBjb2RpbmcgYW5kIGV2ZW4gcm9ib3RpY3MgYXJlCmNvbnNpZGVyZWQgYXMgc3lub255bW91cyBvZiBjb21wdXRhdGlvbmFsIHRoaW5raW5nLiBUaGlzIHBhcGVyIHByZXNlbnRzCmEgdGV4dCBuZXR3b3JrIGFuYWx5c2lzIG9mIHRoZSBtYWluIGRlZmluaXRpb25zIG9mIHRoaXMgc2tpbGwgdGhhdCBoYXZlCmJlZW4gZm91bmQgaW4gdGhlIGxpdGVyYXR1cmUsIGFpbWluZyB0byBvZmZlciBpbnNpZ2h0cyBvbiB0aGUgY29tbW9uCmNoYXJhY3RlcmlzdGljcyB0aGV5IHNoYXJlIGFuZCBvbiB0aGVpciByZWxhdGlvbnNoaXAgd2l0aCBjb21wdXRlcgpwcm9ncmFtbWluZy4gQXMgYSByZXN1bHQsIGEgbmV3IGRlZmluaXRpb24gb2YgY29tcHV0YXRpb25hbCB0aGlua2luZyBpcwpwcm9wb3NlZCwgd2hpY2ggZW1lcmdlIGZyb20gdGhlIGFuYWx5c2VkIGRhdGEuCgoqKkRhdGEgU291cmNlKioKCiMjIyMjIOKchSBDb21wcmVoZW5zaW9uIENoZWNrCgpCYXNlZCBvbiB5b3VyIHJlYWRpbmcsIHdoYXQncyB0aGUgZGF0YSBzb3VyY2UgaW4gdGhpcyBwYXBlcj8KCiMjIyAxYi4gR3VpZGluZyBRdWVzdGlvbnMKCiMjIyMjIOKchSBDb21wcmVoZW5zaW9uIENoZWNrCgpXaGF0J3MgdGhlIHJlc2VhcmNoIHF1ZXN0aW9uIGluIHRoaXMgcGFwZXI/IFdoeSBpcyB0ZXh0IG5ldHdvcmsgYW5hbHlzaXMKYW4gYXBwcm9wcmlhdGUgbWV0aG9kb2xvZ3kgdG8gYWRkcmVzcyB0aGUgcmVzZWFyY2ggcXVlc3Rpb24/CgojIyMgMWMuIFNldCBVcAoKQXMgaGlnaGxpZ2h0ZWQgaW4gW0NoYXB0ZXIgNiBvZiBEYXRhIFNjaWVuY2UgaW4gRWR1Y2F0aW9uIFVzaW5nClJdKGh0dHBzOi8vZGF0YXNjaWVuY2VpbmVkdWNhdGlvbi5jb20vYzA2Lmh0bWwpIChEU0lFVVIpLCBvbmUgb2YgdGhlCmZpcnN0IHN0ZXBzIG9mIGV2ZXJ5IHdvcmtmbG93IHNob3VsZCBiZSB0byBzZXQgdXAgYSAiUHJvamVjdCIgd2l0aGluClJTdHVkaW8uIFRoaXMgd2lsbCBiZSB5b3VyICJob21lIiBmb3IgYW55IGZpbGVzIGFuZCBjb2RlIHVzZWQgb3IgY3JlYXRlZAppbiBwcmV2aW91cyB1bml0cy4KCllvdSBhcmUgd2VsY29tZSB0byBjb250aW51ZSB1c2luZyB0aGUgc2FtZSBwcm9qZWN0IGNyZWF0ZWQgZm9yIHByZXZpb3VzCnVuaXRzLCBvciBjcmVhdGUgYW4gZW50aXJlbHkgbmV3IHByb2plY3QgZm9yIFVuaXQgNC4gSG93ZXZlciwgYWZ0ZXIKeW91J3ZlIGNyZWF0ZWQgeW91ciBwcm9qZWN0IG9wZW4gdXAgYSBuZXcgUiBzY3JpcHQsIGFuZCBsb2FkIHRoZQpmb2xsb3dpbmcgcGFja2FnZXMgdGhhdCB3ZSdsbCBiZSBuZWVkaW5nIGZvciB0aGlzIHdhbGt0aHJvdWdoOgoKYGBge3IgbG9hZC1wYWNrYWdlcywgbWVzc2FnZT1GQUxTRX0KbGlicmFyeShkcGx5cikKbGlicmFyeSh0aWR5dGV4dCkKbGlicmFyeSh0aWR5dmVyc2UpCmxpYnJhcnkodGlkeXIpCmxpYnJhcnkoZ2dwbG90MikKbGlicmFyeShpZ3JhcGgpCmxpYnJhcnkoZ2dyYXBoKQpgYGAKCkF0IHRoZSBlbmQgb2YgdGhpcyB3ZWVrLCBJIGVuY291cmFnZSB5b3Ugc2hhcmUgd2l0aCBtZSB5b3VyIFIgc2NyaXB0IGFzCmV2aWRlbmNlIHRoYXQgeW91IGhhdmUgY29tcGxldGUgdGhlIHdhbGt0aHJvdWdoLiBBbHRob3VnaCBJIGhpZ2hseQpyZWNvbW1lbmQgdGhhdCB0aGF0IHlvdSBtYW51YWxseSB0eXBlIHRoZSBjb2RlIHNoYXJlZCB0aHJvdWdob3V0IHRoaXMKd2Fsa3Rocm91Z2gsIGZvciBsYXJnZSBibG9ja3Mgb2YgdGV4dCBpdCBtYXkgYmUgZWFzaWVyIHRvIGNvcHkgYW5kCnBhc3RlLgoKLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCgojIyAyLiBXUkFOR0xFCgojIyMgMmEuIEltcG9ydCBEYXRhCgpOb3cgbGV0J3MgcmVhZCBvdXIgZGF0YSBpbnRvIG91ciBFbnZpcm9ubWVudCB1c2luZyB0aGUgYHJlYWRfY3N2KClgCmZ1bmN0aW9uIGFuZCBhc3NpZ24gaXQgdG8gYSB2YXJpYWJsZSBuYW1lIHNvIHdlIGNhbiB3b3JrIHdpdGggaXQgbGlrZQphbnkgb3RoZXIgb2JqZWN0IGluIFIuCgpgYGB7ciByZWFkLWNzdn0KQ1RkZWZpbml0aW9uIDwtIHJlYWRfY3N2KCJkYXRhL2RlZmluaXRpb24uY3N2IikKYGBgCgpXZSBjYW4gc2VlIHRoYXQgd2UgaGF2ZSA4IGRpZmZlcmVudCBkZWZpbml0aW9ucyBmb3IgQ1QgKGNvbXB1dGF0aW9uYWwKdGhpbmtpbmcpLiBUaGUgZGVmaW5pdGlvbnMgd2VyZSB0YWtlbiBmcm9tIHRoZSBwYXBlci4gVGhlIHBhcGVyIGluY2x1ZGVzCm1vcmUgdGhhbiA4IGRlZmluaXRpb25zLiBIZXJlLCB3ZSB1c2UgOCBkZWZpbml0aW9ucyBhcyBhbiBleGVtcGxhcgpkYXRhc2V0LgoKIyMjIDJiLiBUb2tlbml6aW5nIHRleHQgaW50byBiaWdyYW1zCgpOZXh0LCB3ZSB3aWxsIHVzZSBzb21lIGZhbWlsaWFyIGB0aWR5dGV4dGAgZnVuY3Rpb25zIGZvciB0b2tlbml6aW5nCnRleHQuIEJ1dCB0aGlzIHRpbWUsIHdlIHdpbGwgdG9rZW5pemUgYmlncmFtLCBpbnN0ZWFkIG9mIHVuaWdyYW1zIChvcgpzaW5nbGUgd29yZHMpIGluIHRoZSBzZW50aW1lbnQgYW5hbHlzaXMgdW5pdC4gV2UgY2FuIGFsc28gdG9rZW5pemUKdHJpZ3JhbXMgZXRjLgoKTGV0J3MgdG9rZW5pemUgb3VyIGRlZmluaXRpb24gdGV4dCBhbmQgYnkgdXNpbmcgdGhlIGZhbWlsaWFyCmB1bm5lc3RfdG9rZW5zKClgLCBieSBzcGVjaWZ5aW5nIG49MiBgbiA9IDJgIHRvIGdldCBiaWdyYW1zOgoKYGBge3IgdG9rZW5pemV9CmN0X2JpZ3JhbXMgPC0gQ1RkZWZpbml0aW9uICU+JQogIHVubmVzdF90b2tlbnMoYmlncmFtLCBkZWZpbml0aW9uLCB0b2tlbiA9ICJuZ3JhbXMiLCBuID0gMikKYGBgCgpOb3cgbGV0J3MgZG8gYSBxdWljayBjb3VudCB0byBzZWUgY29tbW9uIGJpZ3JhbXM6CgpgYGB7ciBjb3VudC1iaWdyYW1zfQpjdF9iaWdyYW1zICU+JQogIGNvdW50KGJpZ3JhbSwgc29ydCA9IFRSVUUpCmBgYAoKWW91IG1pZ2h0IG5vdGljZSB0aGF0IHRoZSBtb3N0IGZyZXF1ZW50IGJpZ3JhbSBpcyAiY29tcHV0ZXIgc2NpZW5jZSIuClRoaXMgbWFrZXMgc2Vuc2UgYXMgdGhlIHJlc2VhcmNoZXIgKGkuZS4sIEplYW5uZXR0ZSBNIFdpbmcpIHdobyBjcmVhdGVkCnRoZSBjb25jZXB0IHdhcyBmcm9tIHRoZSBmaWVsZCBvZiBjb21wdXRlciBzY2llbmNlLiBZb3UgbWlnaHQgbm90aWNlZAp0aGF0IHRoZSBsYXJnZXN0IGZyZXF1ZW5jeSBpcyA1LiBJdCBtYWtlcyBzZW5zZSBhcyB3ZSBvbmx5IGhhdmUgOApkZWZpbml0aW9ucy4gRm9yIHlvdXIgaW5kZXBlbmRlbnQgYW5hbHlzaXMsIHlvdSBzaG91bGQgdXNlIGEgYmlnCmRhdGFzZXQuIEhlcmUsIGl0J3Mgb25seSBmb3Igd2Fsa3Rocm91Z2ggZGVtby4KCiMjIyAyYy4gUmVtb3ZlIHN0b3Agd29yZHMKCkluIHRoaXMgY29udGV4dCwgc3RvcCB3b3JkcyBtaWdodCBiZSBub3QgaGVscGZ1bCBmb3IgdXMgdG8gZXhwbG9yZSB0aGUKZGVmaW5pdGlvbi4gTmV4dCwgd2Ugd2lsbCByZW1vdmUgc3RvcCB3b3Jkcy4gRGlmZmVyZW50IGZyb20gdW5pZ3JhbXMgKG9yCnNpbmdsZSB3b3JkcyksIHdlIGNhbm5vdCByZW1vdmUgc3RvcCB3b3JkcyBkaXJlY3RseS4gV2Ugc2hvdWxkIGZpcnN0CnNlcGVyYXRlIHRoZSBkaWFncmFtcyBpbnRvIHR3byBjb2x1bW5zIGFuZCB0aGVuIHJlbW92ZSBzdG9wIHdvcmRzIGluCmJvdGggY29sdW1ucyB1c2luZyBgc2VwYXJhdGVgIGFuZCBgZmlsdGVyYDoKCmBgYHtyIHJlbW92ZSBzdG9wIHdvcmRzfQpiaWdyYW1zX3NlcGFyYXRlZCA8LSBjdF9iaWdyYW1zICU+JQogIHNlcGFyYXRlKGJpZ3JhbSwgYygid29yZDEiLCAid29yZDIiKSwgc2VwID0gIiAiKQoKYmlncmFtc19maWx0ZXJlZCA8LSBiaWdyYW1zX3NlcGFyYXRlZCAlPiUKICBmaWx0ZXIoIXdvcmQxICVpbiUgc3RvcF93b3JkcyR3b3JkKSAlPiUKICBmaWx0ZXIoIXdvcmQyICVpbiUgc3RvcF93b3JkcyR3b3JkKQoKYmlncmFtX2NvdW50cyA8LSBiaWdyYW1zX2ZpbHRlcmVkICU+JSAKICBjb3VudCh3b3JkMSwgd29yZDIsIHNvcnQgPSBUUlVFKQoKYmlncmFtX2NvdW50cwpgYGAKCk5vdywgaW4gYmlncmFtX2NvdW50cywgYWxsIHN0b3Agd29yZHMgYXJlIHJlbW92ZWQuCgpXZSBjYW4gYWxzbyBjb21iaW5lIHRoZSBzZXBhcmF0ZWQgd29yZHMgd2l0aCBgdW5pdGVgOgoKYGBge3IgdW5pdGUgYmlncmFtc30KYmlncmFtc191bml0ZWQgPC0gYmlncmFtc19maWx0ZXJlZCAlPiUKICB1bml0ZShiaWdyYW0sIHdvcmQxLCB3b3JkMiwgc2VwID0gIiAiKQoKYmlncmFtc191bml0ZWQKYGBgCgojIyAzLiBWSVNVQUxJWkUgV09SRCBORVRXT1JLCgpUaGlzIGlzIGEgd29yZCBuZXR3b3JrIGZyb20gdGhlIHBhcGVyOgoKIVtdKGltZy9uZXQucG5nKXt3aWR0aD0iNTAlIn0KCllvdSBjYW4gc2VlIHRoYXQgYWxsIG5vZGVzIGFyZSBjb25uZWN0ZWQgd2l0aCBsaW5lcy4gSW4gdGhpcwp2aXN1YWxpemF0aW9uLCB0aGUgbGluZXMgaGF2ZSBubyBkaXJlY3Rpb24uIEJ1dCB3ZSBjYW4gdHVybiBsaW5lcyB0bwplZGdlcy4gV2hlbiB3ZSBoYXZlIGVkZ2VzLCB3ZSBuZWVkIHRocmVlIHZhcmlhYmxlcyB0byB2aXN1YWxpemUgYSB3b3JkCm5ldDoKCmEuICAqKmZyb20qKjogdGhlIG5vZGUgYW4gZWRnZSBpcyBjb21pbmcgZnJvbQpiLiAgKip0byoqOiB0aGUgbm9kZSBhbiBlZGdlIGlzIGdvaW5nIHRvd2FyZHMKYy4gICoqd2VpZ2h0Kio6IEEgbnVtZXJpYyB2YWx1ZSBhc3NvY2lhdGVkIHdpdGggZWFjaCBlZGdlCgpXZSBuZWVkIHRvIHRyYW5zZm9ybSBvdXIgZGF0YXNldCAoYmlncmFtX2NvdW50cykgaW50byB0aGVzZSB2YXJpYWJsZXMgaW4KdGhlIGZvbGxvd2luZyB3YXk6IGBmcm9tYCBpcyB0aGUgIndvcmQxIiwgYHRvYCBpcyB0aGUgIndvcmQyIiwgYW5kCmB3ZWlnaHRgIGlzICJuIi4KCkxldCdzIHVzZSBgZ3JhcGhfZnJvbV9kYXRhX2ZyYW1lYCB0byBtYWtlIHRoZSB0cmFuc2Zvcm1hdGlvbjoKCmBgYHtyIHRyYW5mb3JtIGRhdGEgZm9yIHZpc3VhbGl6aW5nIHdvcmQgbmV0fQpiaWdyYW1fZ3JhcGggPC0gYmlncmFtX2NvdW50cyAlPiUKICBncmFwaF9mcm9tX2RhdGFfZnJhbWUoKQoKYmlncmFtX2dyYXBoCmBgYAoKU2luY2UgbG90cyBvZiBiaWdyYW1zIG9ubHkgYXBwZWFyIG9uZSB0aW1lLCBsZXQncyBvbmx5IGtlZXAgdGhvc2UKYXBwZWFyaW5nIG1vcmUgdGhhbiBvbmUgdGltZQoKYGBge3IgZmlsdGVyIGluZnJlcXVlbnQgYmlncmFtc30KYmlncmFtX2dyYXBoX2ZpbHRlcmVkIDwtIGJpZ3JhbV9jb3VudHMgJT4lCiAgZmlsdGVyKG4gPiAxKSAlPiUKICBncmFwaF9mcm9tX2RhdGFfZnJhbWUoKQoKYmlncmFtX2dyYXBoX2ZpbHRlcmVkCmBgYAoKTm93LCB3ZSBoYXZlIG9ubHkgdGhyZWUgYmlncmFtcyBsZWZ0LiBQbGVhc2UgdXNlIGEgbGFyZ2VyIGRhdGFzZXQgc28KdGhhdCB5b3Ugd2lsbCBub3QgZW5kIHVwIHdpdGggdmlzdWFsaXppbmcgb25seSB0aHJlZSBiaWdyYW1zLgoKTmV4dCwgbGV0J3MgZ28gYWhlYWQgYW5kIHZpc3VhbGl6ZSB0aGUgd29yZCBuZXQgYmVmb3JlIGZpbHRlcmluZzoKCmBgYHtyIHZpc3VhbGl6ZSB1bmZpbHRlcmVkIG5ldH0Kc2V0LnNlZWQoMTAwKQoKYSA8LSBncmlkOjphcnJvdyh0eXBlID0gIm9wZW4iLCBsZW5ndGggPSB1bml0KC4yLCAiaW5jaGVzIikpCgpnZ3JhcGgoYmlncmFtX2dyYXBoLCBsYXlvdXQgPSAiZnIiKSArCiAgZ2VvbV9lZGdlX2xpbmsoYWVzKGVkZ2VfYWxwaGEgPSBuKSwgc2hvdy5sZWdlbmQgPSBGQUxTRSwKICAgICAgICAgICAgICAgICBhcnJvdyA9IGEsIGVuZF9jYXAgPSBjaXJjbGUoLjA3LCAnaW5jaGVzJykpICsKICBnZW9tX25vZGVfcG9pbnQoY29sb3IgPSAicmVkIiwgc2l6ZSA9IDMpICsKICBnZW9tX25vZGVfdGV4dChhZXMobGFiZWwgPSBuYW1lKSwgdmp1c3QgPSAxLCBoanVzdCA9IDEpICsKICB0aGVtZV92b2lkKCkKYGBgCgojIyMjIyDinIUgQ29tcHJlaGVuc2lvbiBDaGVjawoKUmV2aXNlIHRoZSBjb2RlIGluIHRoZSBwcmV2aW91cyBjb2RlIGNodW5rIHNvIHRoYXQgdGhlcmUgYXJlIG5vIGFycm93cy4KVGhlIGdyYXBoIHNob3dzIGxpbmVzIGluc3RlYWQgb2YgYXJyb3dzLgoKYGBge3IgbGluZXN9CnNldC5zZWVkKDEwMCkKYmlncmFtX2dyYXBoMiA8LSBiaWdyYW1fY291bnRzICU+JQogIGZpbHRlcihuID4gMSkgJT4lCiAgZ3JhcGhfZnJvbV9kYXRhX2ZyYW1lKCkKCmdncmFwaChiaWdyYW1fZ3JhcGgyLCBsYXlvdXQgPSAiZnIiKSArCiAgZ2VvbV9lZGdlX2xpbmsoYWVzKGVkZ2VfYWxwaGEgPSBuKSwgc2hvdy5sZWdlbmQgPSBGQUxTRSkrCiAgZ2VvbV9ub2RlX3BvaW50KGNvbG9yID0gInJlZCIsIHNpemUgPSAzKSArCiAgZ2VvbV9ub2RlX3RleHQoYWVzKGxhYmVsID0gbmFtZSksIHZqdXN0ID0gMSwgaGp1c3QgPSAxKSArCiAgdGhlbWVfdm9pZCgpCgpgYGAKClJldmlzZSB0aGUgY29kZSBpbiB0aGUgcHJldmlvdXMgY29kZSBjaHVuayBzbyB0aGF0IHRoZXJlIGFyZSBubyBhcnJvd3MKYW5kIHRoZSB3aWR0aCBvZiB0aGUgbGluZXMgcmVwcmVzZW50cyB0aGUgZnJlcXVlbmN5IG9mIGJpZ3JhbXMuIFRoaXMgaXMKYQpbZG9jdW1lbnRhdGlvbl0oaHR0cHM6Ly93d3cucmRvY3VtZW50YXRpb24ub3JnL3BhY2thZ2VzL2dncmFwaC92ZXJzaW9ucy8yLjAuNS90b3BpY3MvZ2VvbV9lZGdlX2xpbmspCnRoYXQgeW91IGNhbiB1c2UgdG8gZmluZCB0aGUgYW5zd2VyLgoKVGhlcmUgYXJlIG1hbnkgb3RoZXIgZW5jb2Rpbmcgb3B0aW9ucyB5b3UgY2FuIHBsYXkgd2l0aCwgc3VjaCBhcwpjaGFuZ2luZyB0aGUgY29sb3Igb2Ygc3BlY2lmaWMgbm9kZXMuIFJlbWVtYmVyIHlvdSBlbmNvZGluZyBzaG91bGQgc2VydmUKdGhlIHB1cnBvc2Ugb2YgZHJhd2luZyB1c2VmdWwgaW5zaWdodHMgZnJvbSB0aGUgd29yZCBuZXQuCgpJbiBjb21wYXJpc29uLCB0aGlzIGlzIHRoZSBuZXQgYWZ0ZXIgZmlsdGVyaW5nOgoKYGBge3IgdmlzdWFsaXplIGZpbHRlcmVkIG5ldH0Kc2V0LnNlZWQoMTAwKQoKYSA8LSBncmlkOjphcnJvdyh0eXBlID0gImNsb3NlZCIsIGxlbmd0aCA9IHVuaXQoLjIsICJpbmNoZXMiKSkKCmdncmFwaChiaWdyYW1fZ3JhcGhfZmlsdGVyZWQsIGxheW91dCA9ICJmciIpICsKICBnZW9tX2VkZ2VfbGluayhhZXMoZWRnZV9hbHBoYSA9IG4pLCBzaG93LmxlZ2VuZCA9IEZBTFNFLAogICAgICAgICAgICAgICAgIGFycm93ID0gYSwgZW5kX2NhcCA9IGNpcmNsZSguMDcsICdpbmNoZXMnKSkgKwogIGdlb21fbm9kZV9wb2ludChjb2xvciA9ICJyZWQiLCBzaXplID0gMykgKwogIGdlb21fbm9kZV90ZXh0KGFlcyhsYWJlbCA9IG5hbWUpLCB2anVzdCA9IDEsIGhqdXN0ID0gMSkgKwogIHRoZW1lX3ZvaWQoKQpgYGAKCldlIGhhdmUgb25seSB0aHJlZSBjb25uZWN0aW9ucyBsZWZ0LiBXZSBjYW4gc2VlIHRoYXQgY29tcHV0ZXIgc2NpZW5jZQphbmQgcHJvYmxlbSBzb2x2aW5nIGFyZSBpbXBvcnRhbnQgY29uY2VwdHMgaW4gQ1QsIHdoaWNoIGlzIHRoZSBjb3JlIGlkZWEKZnJvbSBKZWFubmV0dGUgTSBXaW5nLiBObyBtYXR0ZXIgd2hhdCBjaGFuZ2VzIG92ZXIgdGltZSBvciBob3cgd2UKY29uY2VwdHVhbGl6ZSBDVCBkaWZmZXJlbnRseSwgdGhlc2UgdHdvIGFyZSB0aGUgY29yZSBjb25jZXB0cy4gSXMgdGhhdAp0cnVlLCB0aG91Z2g/IFRoaXMgaXMgYW4gb3BlbiBxdWVzdGlvbiBmb3IgdGhlIGZpZWxkIHRvIGV4cGxvcmUuCgpPbmNlIGFnYWluLCBwbGVhc2UgdXNlIGEgbGFyZ2VyIGRhdGFzZXQgZm9yIHlvdXIgaW5kZXBlbmRlbnQgYW5hbHlzaXMuCgojIyMjIFVuaXQgVGFrZWF3YXkKCk9uZSBtYWluIGxlc3NvbiBJJ20gaG9waW5nIHlvdSB0YWtlIGF3YXkgZnJvbSB0aGlzIHdhbGt0aHJvdWdoIGlzIHRoYXQKd2Ugc2hvdWxkICoqZmluZCBhbiBhcHByb3ByaWF0ZSBzY2VuYXJpbyB1c2luZyB3b3JkIG5ldC4qKiBJdCdzIGVhc3kgdG8KdmlzdWFsaXplIHdvcmQgbmV0LiBCdXQgaG93IGNvdWxkIHdlIG1ha2UgbWVhbmluZ3Mgb3V0IG9mIGl0PyBXZSBzaG91bGQKZmlyc3QgY2xvc2VseSByZWFkIHRoZSByZXNlYXJjaCBxdWVzdGlvbiBhbmQgdGhlbiBhcHBseSBhbiBhcHByb3ByaWF0ZQp0ZWNobmlxdWUgdG8gYW5zd2VyIHRoZSByZXNlYXJjaCBxdWVzdGlvbi4K