0. INTRODUCTION

In the Unit 4 walkthrough, we will replicate a simpler version of the following paper: Not the same: a text network analysis on computational thinking definitions to study its relationship with computer programming. This paper reviews definitions for computational thinking in the literature. You might have noticed that in our field, the same terminology could mean different things, especially for emerging terminologies such as computational thinking. This paper contributes to understandings how different research teams conceptualize computational thinking.

Walkthrough Focus

Similar to previous walkthroughs, we should first understand the context and dataset by reading the paper (prepare), and then wrangle the data (wrangle), and then explore and visualize our data (explore & communicate).


1. PREPARE

To help us better understand the context, questions, and data sources, this section will focus on the following topics:

  1. Context. This paper examines definitions of computational thinking from the literature.
  2. Questions. [Question for you]
  3. 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:

  1. from: the node an edge is coming from
  2. to: the node an edge is going towards
  3. 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