packages = c(
  "dplyr","ggplot2","stringr", "dslabs", "readr", "tidyr", "purrr",
  "lubridate"
  )
existing = as.character(installed.packages()[,1])
for(pkg in packages[!(packages %in% existing)]) install.packages(pkg)
rm(list=ls(all=T))
Sys.setlocale("LC_ALL","C")
[1] "C"
options(digits=4, scipen=12)
library(readr)
library(dplyr)
library(ggplot2)
library(stringr)
library(lubridate)
library(tidyr)
library(dslabs)

A. Tidy Data Overview

A1 Tidy Data

Q1: A collaborator sends you a file containing data for three years of average race finish times.

A <- read.csv("data/AgeGroup.txt")
incomplete final line found by readTableHeader on 'data/AgeGroup.txt'
A
A %>% setNames(c('age_group',2015:2017))

Are these data considered “tidy” in R? Why or why not?

  • No. These data are not considered “tidy” because the variable “year” is stored in the header.

Q2: Below are four versions of the same dataset.

read.table("data/state1.txt",header=T,sep="")
read.table("data/state2.txt",header=T,sep="")
read.table("data/state3.txt",header=T,sep="")
read.table("data/state4.txt",header=T,sep="")

Which one is in a tidy format?

  • ans: A
  • in tidy format, every observation is a row and every variable is a column.



B. Reshaping Data

B1. Reshaping Data

Q1: Your file called “times.csv” has age groups and average race finish times for three years of marathons. You read in the data file using the following command.

d = read_csv("data/times.csv")
Parsed with column specification:
cols(
  age_group = col_integer(),
  `2015` = col_time(format = ""),
  `2016` = col_time(format = ""),
  `2017` = col_time(format = "")
)
d
#這樣的表格可稱: 寬表格

Which commands will help you “tidy” the data?

d %>% gather(year, time, `2015`:`2017`) %>% data.frame #沒有指定value,就代表key會是value的欄位名稱,value是類別變數的值
# gather將寬表格整理成長表格
# gather(dataset,key = "類別變數,紀錄數值變數的來源" , value = "多個數值變數的累積" , key , value)
#長表格,tidy form,一個row是一次紀錄

Q2: You have a dataset on U.S. contagious diseases, but it is in the following wide format:

D = read.table("data/diseases.txt", header=T, sep="")
D

Which of the following would transform this into a tidy dataset, with each row representing an observation of the incidence of each specific disease (as shown below)?

D %>% gather(disease, count, "Hepatitis_A": "Rubella") %>% head(10)

Q3: You have successfully formatted marathon finish times into a tidy object called D. The first few lines are shown below.

D = read.table("data/times_long.txt", header=T, sep=",")
D

Select the code that converts these data back to the wide format, where each year has a separate column.

D %>% spread(year, time)

Q4: You have a file

D = read.table("data/state2.txt", header=T, sep="")
D

You would like to transform it into a dataset where population and total are each their own column (shown below). Which code would best accomplish this? Select the code that converts these data back to the wide format, where each year has a separate column.

D %>% spread(key=var, value=people)
B3 Separate and Unite

Q1: A collaborator sends you a file containing data for two years of average race finish times.

D = read.csv("data/times2.txt")
D

Which of the answers below best tidys the data?

D %>% gather(key=key, value=value, -age_group) %>%
    separate(col=key, into=c("year", "variable_name"), sep = "_") %>% 
    spread(key=variable_name, value=value) %>% data.frame
attributes are not identical across measure variables;
they will be dropped

Q2: You are in the process of tidying some data on heights, hand length, and wingspan for basketball players in the draft. Currently, you have the following:

stats = read.table("data/player.txt",header=T,sep="")
stats

Select all of the correct commands below that would turn this data into a “tidy” format.

stats %>%
    separate(col=key, into=c("player", "variable_name"), sep="_", extra="merge") %>% 
    spread(key=variable_name, value=value)
stats %>%
    separate(col=key, into=c("player", "variable_name1", "variable_name2"), 
             sep="_", fill="right") %>% 
    unite(col = variable_name, variable_name1, variable_name2, sep = "_") %>% 
    spread(key = variable_name, value = value)



C. Combining Tables

C1 Combining Tables

Q1: You have created a tab1 and tab2 of state population and election data, similar to our module videos:

tab1 = read.table("data/tab1.txt",header=T,sep="",stringsAsFactors=F)
tab1
tab2 = read.table("data/tab2.txt",header=T,sep="",stringsAsFactors=F)
tab2

What are the dimensions of the table dat, created by the following command?

left_join(tab1, tab2, by = "state") %>% dim

Q2: We are still using the tab1 and tab2 tables shown in question 1. What join command would create a new table dat with three rows and two columns?

semi_join(tab1, tab2, by = "state")
C2 Binding

Q1: Which of the following are real differences between the join and bind functions? Please select all correct answers.

  • Binding functions combine by position, while join functions match by variables.
  • Joining functions can join datasets of different dimensions, but the bind functions must match on the appropriate dimension (either same row or column numbers).
  • Bind functions can combine both vectors and dataframes, while join functions work for only for dataframes.
C3 Set Operators

Q1: We have two simple tables, shown below:

df1 = data.frame(x=c("a","b"), y=c("a","a"), stringsAsFactors=F); df1
df2 = data.frame(x=c("a","a"), y=c("a","b"), stringsAsFactors=F); df2

Which command would result in the following table?

dplyr::setdiff(df1, df2)



D. Web Scraping

D1 Web Scraping

Q1: Which feature of html documents allows us to extract the table that we are interested in?

  • All elements in an html page are specified as “nodes”; we can use the node “tables” to identify and extract the specific table we are interested in before we do additional data cleaning.

Q2: In the video, we use the following code to extract the murders table (tab) from our downloaded html file h:

tab <- h %>% html_nodes(“table”) 
tab <- tab[[2]] %>% html_table

Why did we use the html_nodes() command instead of the html_node command?

  • The html_node command only selects the first node of a specified type. In this example the first “table” node is a legend table and not the actual data we are interested in.
  • We used html_nodes so that we could specify the second “table” element using the tab[[2]] command








LS0tDQp0aXRsZTogIldyYW5nbGluZywgVGlkeSBEYXRhIg0Kb3V0cHV0OiBodG1sX25vdGVib29rDQplZGl0b3Jfb3B0aW9uczogDQogIGNodW5rX291dHB1dF90eXBlOiBpbmxpbmUNCi0tLQ0KDQo8YnI+DQoNCmBgYHtyfQ0KcGFja2FnZXMgPSBjKA0KICAiZHBseXIiLCJnZ3Bsb3QyIiwic3RyaW5nciIsICJkc2xhYnMiLCAicmVhZHIiLCAidGlkeXIiLCAicHVycnIiLA0KICAibHVicmlkYXRlIg0KICApDQpleGlzdGluZyA9IGFzLmNoYXJhY3RlcihpbnN0YWxsZWQucGFja2FnZXMoKVssMV0pDQpmb3IocGtnIGluIHBhY2thZ2VzWyEocGFja2FnZXMgJWluJSBleGlzdGluZyldKSBpbnN0YWxsLnBhY2thZ2VzKHBrZykNCmBgYA0KDQpgYGB7ciBlY2hvPVQsIG1lc3NhZ2U9RiwgY2FjaGU9Riwgd2FybmluZz1GfQ0Kcm0obGlzdD1scyhhbGw9VCkpDQpTeXMuc2V0bG9jYWxlKCJMQ19BTEwiLCJDIikNCm9wdGlvbnMoZGlnaXRzPTQsIHNjaXBlbj0xMikNCmxpYnJhcnkocmVhZHIpDQpsaWJyYXJ5KGRwbHlyKQ0KbGlicmFyeShnZ3Bsb3QyKQ0KbGlicmFyeShzdHJpbmdyKQ0KbGlicmFyeShsdWJyaWRhdGUpDQpsaWJyYXJ5KHRpZHlyKQ0KbGlicmFyeShkc2xhYnMpDQpgYGANCg0KLSAtIC0NCg0KIyMjIEEuIFRpZHkgRGF0YSBPdmVydmlldw0KDQojIyMjIyBBMSBUaWR5IERhdGENCg0KKipRMToqKiBBIGNvbGxhYm9yYXRvciBzZW5kcyB5b3UgYSBmaWxlIGNvbnRhaW5pbmcgZGF0YSBmb3IgdGhyZWUgeWVhcnMgb2YgYXZlcmFnZSByYWNlIGZpbmlzaCB0aW1lcy4gDQpgYGB7cn0NCkEgPC0gcmVhZC5jc3YoImRhdGEvQWdlR3JvdXAudHh0IikNCkENCkEgJT4lIHNldE5hbWVzKGMoJ2FnZV9ncm91cCcsMjAxNToyMDE3KSkNCmBgYA0KX0FyZSB0aGVzZSBkYXRhIGNvbnNpZGVyZWQg4oCcdGlkeeKAnSBpbiBSPyBXaHkgb3Igd2h5IG5vdD9fDQoNCisgTm8uIFRoZXNlIGRhdGEgYXJlIG5vdCBjb25zaWRlcmVkIOKAnHRpZHnigJ0gYmVjYXVzZSB0aGUgdmFyaWFibGUg4oCceWVhcuKAnSBpcyBzdG9yZWQgaW4gdGhlIGhlYWRlci4NCisNCg0KKipRMjoqKiBCZWxvdyBhcmUgZm91ciB2ZXJzaW9ucyBvZiB0aGUgc2FtZSBkYXRhc2V0LiANCmBgYHtyfQ0KcmVhZC50YWJsZSgiZGF0YS9zdGF0ZTEudHh0IixoZWFkZXI9VCxzZXA9IiIpDQpgYGANCg0KYGBge3J9DQpyZWFkLnRhYmxlKCJkYXRhL3N0YXRlMi50eHQiLGhlYWRlcj1ULHNlcD0iIikNCmBgYA0KDQpgYGB7ciBldmFsPUZ9DQpyZWFkLnRhYmxlKCJkYXRhL3N0YXRlMy50eHQiLGhlYWRlcj1ULHNlcD0iIikNCmBgYA0KDQpgYGB7cn0NCnJlYWQudGFibGUoImRhdGEvc3RhdGU0LnR4dCIsaGVhZGVyPVQsc2VwPSIiKQ0KYGBgDQpfV2hpY2ggb25lIGlzIGluIGEgdGlkeSBmb3JtYXQ/Xw0KDQorIGFuczogQQ0KKyBpbiB0aWR5IGZvcm1hdCwgZXZlcnkgb2JzZXJ2YXRpb24gaXMgYSByb3cgYW5kIGV2ZXJ5IHZhcmlhYmxlIGlzIGEgY29sdW1uLiANCg0KPGJyPg0KDQotIC0gLQ0KDQojIyMgQi4gUmVzaGFwaW5nIERhdGENCg0KIyMjIyMgQjEuIFJlc2hhcGluZyBEYXRhDQoNCioqUTE6KiogWW91ciBmaWxlIGNhbGxlZCDigJx0aW1lcy5jc3bigJ0gaGFzIGFnZSBncm91cHMgYW5kIGF2ZXJhZ2UgcmFjZSBmaW5pc2ggdGltZXMgZm9yIHRocmVlIHllYXJzIG9mIG1hcmF0aG9ucy4gWW91IHJlYWQgaW4gdGhlIGRhdGEgZmlsZSB1c2luZyB0aGUgZm9sbG93aW5nIGNvbW1hbmQuDQoNCmBgYHtyfQ0KZCA9IHJlYWRfY3N2KCJkYXRhL3RpbWVzLmNzdiIpDQpkDQoj6YCZ5qij55qE6KGo5qC85Y+v56ixOiDlr6zooajmoLwNCmBgYA0KDQpfV2hpY2ggY29tbWFuZHMgd2lsbCBoZWxwIHlvdSDigJx0aWR54oCdIHRoZSBkYXRhP18NCmBgYHtyfQ0KZCAlPiUgZ2F0aGVyKHllYXIsIHRpbWUsIGAyMDE1YDpgMjAxN2ApICU+JSBkYXRhLmZyYW1lICPmspLmnInmjIflrpp2YWx1Ze+8jOWwseS7o+ihqGtleeacg+aYr3ZhbHVl55qE5qyE5L2N5ZCN56ix77yMdmFsdWXmmK/poZ7liKXorormlbjnmoTlgLwNCiMgZ2F0aGVy5bCH5a+s6KGo5qC85pW055CG5oiQ6ZW36KGo5qC8DQojIGdhdGhlcihkYXRhc2V0LGtleSA9ICLpoZ7liKXorormlbjvvIzntIDpjITmlbjlgLzorormlbjnmoTkvobmupAiICwgdmFsdWUgPSAi5aSa5YCL5pW45YC86K6K5pW455qE57Sv56mNIiAsIGtleSAsIHZhbHVlKQ0KDQoj6ZW36KGo5qC877yMdGlkeSBmb3Jt77yM5LiA5YCLcm935piv5LiA5qyh57SA6YyEDQpgYGANCg0KKipRMjoqKiBZb3UgaGF2ZSBhIGRhdGFzZXQgb24gVS5TLiBjb250YWdpb3VzIGRpc2Vhc2VzLCBidXQgaXQgaXMgaW4gdGhlIGZvbGxvd2luZyB3aWRlIGZvcm1hdDoNCmBgYHtyfQ0KRCA9IHJlYWQudGFibGUoImRhdGEvZGlzZWFzZXMudHh0IiwgaGVhZGVyPVQsIHNlcD0iIikNCkQNCmBgYA0KDQpfV2hpY2ggb2YgdGhlIGZvbGxvd2luZyB3b3VsZCB0cmFuc2Zvcm0gdGhpcyBpbnRvIGEgdGlkeSBkYXRhc2V0LCB3aXRoIGVhY2ggcm93IHJlcHJlc2VudGluZyBhbiBvYnNlcnZhdGlvbiBvZiB0aGUgaW5jaWRlbmNlIG9mIGVhY2ggc3BlY2lmaWMgZGlzZWFzZSAoYXMgc2hvd24gYmVsb3cpP18NCmBgYHtyfQ0KRCAlPiUgZ2F0aGVyKGRpc2Vhc2UsIGNvdW50LCAiSGVwYXRpdGlzX0EiOiAiUnViZWxsYSIpICU+JSBoZWFkKDEwKQ0KYGBgDQoNCioqUTM6KiogWW91IGhhdmUgc3VjY2Vzc2Z1bGx5IGZvcm1hdHRlZCBtYXJhdGhvbiBmaW5pc2ggdGltZXMgaW50byBhIHRpZHkgb2JqZWN0IGNhbGxlZCBgRGAuIFRoZSBmaXJzdCBmZXcgbGluZXMgYXJlIHNob3duIGJlbG93Lg0KYGBge3J9DQpEID0gcmVhZC50YWJsZSgiZGF0YS90aW1lc19sb25nLnR4dCIsIGhlYWRlcj1ULCBzZXA9IiwiKQ0KRA0KYGBgDQoNCl9TZWxlY3QgdGhlIGNvZGUgdGhhdCBjb252ZXJ0cyB0aGVzZSBkYXRhIGJhY2sgdG8gdGhlIHdpZGUgZm9ybWF0LCB3aGVyZSBlYWNoIHllYXIgaGFzIGEgc2VwYXJhdGUgY29sdW1uLl8NCmBgYHtyfQ0KRCAlPiUgc3ByZWFkKHllYXIsIHRpbWUpDQpgYGANCg0KKipRNDoqKiBZb3UgaGF2ZSBhIGZpbGUNCmBgYHtyfQ0KRCA9IHJlYWQudGFibGUoImRhdGEvc3RhdGUyLnR4dCIsIGhlYWRlcj1ULCBzZXA9IiIpDQpEDQpgYGANCllvdSB3b3VsZCBsaWtlIHRvIHRyYW5zZm9ybSBpdCBpbnRvIGEgZGF0YXNldCB3aGVyZSBwb3B1bGF0aW9uIGFuZCB0b3RhbCBhcmUgZWFjaCB0aGVpciBvd24gY29sdW1uIChzaG93biBiZWxvdykuIF9XaGljaCBjb2RlIHdvdWxkIGJlc3QgYWNjb21wbGlzaCB0aGlzPyBTZWxlY3QgdGhlIGNvZGUgdGhhdCBjb252ZXJ0cyB0aGVzZSBkYXRhIGJhY2sgdG8gdGhlIHdpZGUgZm9ybWF0LCB3aGVyZSBlYWNoIHllYXIgaGFzIGEgc2VwYXJhdGUgY29sdW1uLl8NCmBgYHtyfQ0KRCAlPiUgc3ByZWFkKGtleT12YXIsIHZhbHVlPXBlb3BsZSkNCmBgYA0KDQojIyMjIyBCMyBTZXBhcmF0ZSBhbmQgVW5pdGUNCg0KKipRMToqKiBBIGNvbGxhYm9yYXRvciBzZW5kcyB5b3UgYSBmaWxlIGNvbnRhaW5pbmcgZGF0YSBmb3IgdHdvIHllYXJzIG9mIGF2ZXJhZ2UgcmFjZSBmaW5pc2ggdGltZXMuDQpgYGB7cn0NCkQgPSByZWFkLmNzdigiZGF0YS90aW1lczIudHh0IikNCkQNCmBgYA0KDQpfV2hpY2ggb2YgdGhlIGFuc3dlcnMgYmVsb3cgYmVzdCB0aWR5cyB0aGUgZGF0YT9fDQpgYGB7cn0NCkQgJT4lIGdhdGhlcihrZXk9a2V5LCB2YWx1ZT12YWx1ZSwgLWFnZV9ncm91cCkgJT4lDQoJc2VwYXJhdGUoY29sPWtleSwgaW50bz1jKCJ5ZWFyIiwgInZhcmlhYmxlX25hbWUiKSwgc2VwID0gIl8iKSAlPiUgDQoJc3ByZWFkKGtleT12YXJpYWJsZV9uYW1lLCB2YWx1ZT12YWx1ZSkgJT4lIGRhdGEuZnJhbWUNCmBgYA0KDQoqKlEyOioqIFlvdSBhcmUgaW4gdGhlIHByb2Nlc3Mgb2YgdGlkeWluZyBzb21lIGRhdGEgb24gaGVpZ2h0cywgaGFuZCBsZW5ndGgsIGFuZCB3aW5nc3BhbiBmb3IgYmFza2V0YmFsbCBwbGF5ZXJzIGluIHRoZSBkcmFmdC4gQ3VycmVudGx5LCB5b3UgaGF2ZSB0aGUgZm9sbG93aW5nOg0KYGBge3J9DQpzdGF0cyA9IHJlYWQudGFibGUoImRhdGEvcGxheWVyLnR4dCIsaGVhZGVyPVQsc2VwPSIiKQ0Kc3RhdHMNCmBgYA0KDQpfU2VsZWN0IGFsbCBvZiB0aGUgY29ycmVjdCBjb21tYW5kcyBiZWxvdyB0aGF0IHdvdWxkIHR1cm4gdGhpcyBkYXRhIGludG8gYSDigJx0aWR54oCdIGZvcm1hdC5fDQoNCmBgYHtyfQ0Kc3RhdHMgJT4lDQoJc2VwYXJhdGUoY29sPWtleSwgaW50bz1jKCJwbGF5ZXIiLCAidmFyaWFibGVfbmFtZSIpLCBzZXA9Il8iLCBleHRyYT0ibWVyZ2UiKSAlPiUgDQoJc3ByZWFkKGtleT12YXJpYWJsZV9uYW1lLCB2YWx1ZT12YWx1ZSkNCmBgYA0KDQpgYGB7cn0NCnN0YXRzICU+JQ0KCXNlcGFyYXRlKGNvbD1rZXksIGludG89YygicGxheWVyIiwgInZhcmlhYmxlX25hbWUxIiwgInZhcmlhYmxlX25hbWUyIiksIA0KCSAgICAgICAgIHNlcD0iXyIsIGZpbGw9InJpZ2h0IikgJT4lIA0KCXVuaXRlKGNvbCA9IHZhcmlhYmxlX25hbWUsIHZhcmlhYmxlX25hbWUxLCB2YXJpYWJsZV9uYW1lMiwgc2VwID0gIl8iKSAlPiUgDQoJc3ByZWFkKGtleSA9IHZhcmlhYmxlX25hbWUsIHZhbHVlID0gdmFsdWUpDQpgYGANCg0KPGJyPg0KDQotIC0gLQ0KDQojIyMgQy4gQ29tYmluaW5nIFRhYmxlcw0KDQojIyMjIyBDMSBDb21iaW5pbmcgVGFibGVzDQoNCioqUTE6KiogWW91IGhhdmUgY3JlYXRlZCBhIHRhYjEgYW5kIHRhYjIgb2Ygc3RhdGUgcG9wdWxhdGlvbiBhbmQgZWxlY3Rpb24gZGF0YSwgc2ltaWxhciB0byBvdXIgbW9kdWxlIHZpZGVvczoNCmBgYHtyfQ0KdGFiMSA9IHJlYWQudGFibGUoImRhdGEvdGFiMS50eHQiLGhlYWRlcj1ULHNlcD0iIixzdHJpbmdzQXNGYWN0b3JzPUYpDQp0YWIxDQp0YWIyID0gcmVhZC50YWJsZSgiZGF0YS90YWIyLnR4dCIsaGVhZGVyPVQsc2VwPSIiLHN0cmluZ3NBc0ZhY3RvcnM9RikNCnRhYjINCmBgYA0KDQpfV2hhdCBhcmUgdGhlIGRpbWVuc2lvbnMgb2YgdGhlIHRhYmxlIGRhdCwgY3JlYXRlZCBieSB0aGUgZm9sbG93aW5nIGNvbW1hbmQ/Xw0KYGBge3J9DQpsZWZ0X2pvaW4odGFiMSwgdGFiMiwgYnkgPSAic3RhdGUiKSAlPiUgZGltDQpgYGANCg0KDQoqKlEyOioqIF9XZSBhcmUgc3RpbGwgdXNpbmcgdGhlIHRhYjEgYW5kIHRhYjIgdGFibGVzIHNob3duIGluIHF1ZXN0aW9uIDEuIFdoYXQgam9pbiBjb21tYW5kIHdvdWxkIGNyZWF0ZSBhIG5ldyB0YWJsZSBgZGF0YCB3aXRoIHRocmVlIHJvd3MgYW5kIHR3byBjb2x1bW5zP18NCmBgYHtyfQ0Kc2VtaV9qb2luKHRhYjEsIHRhYjIsIGJ5ID0gInN0YXRlIikNCmBgYA0KDQojIyMjIyBDMiBCaW5kaW5nDQoNCioqUTE6KiogX1doaWNoIG9mIHRoZSBmb2xsb3dpbmcgYXJlIHJlYWwgZGlmZmVyZW5jZXMgYmV0d2VlbiB0aGUgam9pbiBhbmQgYmluZCBmdW5jdGlvbnM/IFBsZWFzZSBzZWxlY3QgYWxsIGNvcnJlY3QgYW5zd2Vycy5fDQoNCisgQmluZGluZyBmdW5jdGlvbnMgY29tYmluZSBieSBwb3NpdGlvbiwgd2hpbGUgam9pbiBmdW5jdGlvbnMgbWF0Y2ggYnkgdmFyaWFibGVzLg0KKyBKb2luaW5nIGZ1bmN0aW9ucyBjYW4gam9pbiBkYXRhc2V0cyBvZiBkaWZmZXJlbnQgZGltZW5zaW9ucywgYnV0IHRoZSBiaW5kIGZ1bmN0aW9ucyBtdXN0IG1hdGNoIG9uIHRoZSBhcHByb3ByaWF0ZSBkaW1lbnNpb24gKGVpdGhlciBzYW1lIHJvdyBvciBjb2x1bW4gbnVtYmVycykuDQorIEJpbmQgZnVuY3Rpb25zIGNhbiBjb21iaW5lIGJvdGggdmVjdG9ycyBhbmQgZGF0YWZyYW1lcywgd2hpbGUgam9pbiBmdW5jdGlvbnMgd29yayBmb3Igb25seSBmb3IgZGF0YWZyYW1lcy4NCisNCg0KDQojIyMjIyBDMyBTZXQgT3BlcmF0b3JzDQoNCioqUTE6KiogV2UgaGF2ZSB0d28gc2ltcGxlIHRhYmxlcywgc2hvd24gYmVsb3c6DQpgYGB7cn0NCmRmMSA9IGRhdGEuZnJhbWUoeD1jKCJhIiwiYiIpLCB5PWMoImEiLCJhIiksIHN0cmluZ3NBc0ZhY3RvcnM9Rik7IGRmMQ0KZGYyID0gZGF0YS5mcmFtZSh4PWMoImEiLCJhIiksIHk9YygiYSIsImIiKSwgc3RyaW5nc0FzRmFjdG9ycz1GKTsgZGYyDQpgYGANCg0KX1doaWNoIGNvbW1hbmQgd291bGQgcmVzdWx0IGluIHRoZSBmb2xsb3dpbmcgdGFibGU/Xw0KYGBge3J9DQpkcGx5cjo6c2V0ZGlmZihkZjEsIGRmMikNCmBgYA0KDQo8YnI+DQoNCi0gLSAtDQoNCiMjIyBELiBXZWIgU2NyYXBpbmcNCg0KIyMjIyMgRDEgV2ViIFNjcmFwaW5nDQoNCioqUTE6KiogX1doaWNoIGZlYXR1cmUgb2YgaHRtbCBkb2N1bWVudHMgYWxsb3dzIHVzIHRvIGV4dHJhY3QgdGhlIHRhYmxlIHRoYXQgd2UgYXJlIGludGVyZXN0ZWQgaW4/Xw0KDQorIEFsbCBlbGVtZW50cyBpbiBhbiBodG1sIHBhZ2UgYXJlIHNwZWNpZmllZCBhcyDigJxub2Rlc+KAnTsgd2UgY2FuIHVzZSB0aGUgbm9kZSDigJx0YWJsZXPigJ0gdG8gaWRlbnRpZnkgYW5kIGV4dHJhY3QgdGhlIHNwZWNpZmljIHRhYmxlIHdlIGFyZSBpbnRlcmVzdGVkIGluIGJlZm9yZSB3ZSBkbyBhZGRpdGlvbmFsIGRhdGEgY2xlYW5pbmcuDQorDQoNCioqUTI6KiogSW4gdGhlIHZpZGVvLCB3ZSB1c2UgdGhlIGZvbGxvd2luZyBjb2RlIHRvIGV4dHJhY3QgdGhlIG11cmRlcnMgdGFibGUgKHRhYikgZnJvbSBvdXIgZG93bmxvYWRlZCBodG1sIGZpbGUgYGhgOg0KYGBge3IgZXZhbD1GfQ0KdGFiIDwtIGggJT4lIGh0bWxfbm9kZXMo4oCcdGFibGXigJ0pIA0KdGFiIDwtIHRhYltbMl1dICU+JSBodG1sX3RhYmxlDQpgYGANCg0KX1doeSBkaWQgd2UgdXNlIHRoZSBodG1sX25vZGVzKCkgY29tbWFuZCBpbnN0ZWFkIG9mIHRoZSBodG1sX25vZGUgY29tbWFuZD9fDQoNCisgVGhlIGh0bWxfbm9kZSBjb21tYW5kIG9ubHkgc2VsZWN0cyB0aGUgZmlyc3Qgbm9kZSBvZiBhIHNwZWNpZmllZCB0eXBlLiBJbiB0aGlzIGV4YW1wbGUgdGhlIGZpcnN0IOKAnHRhYmxl4oCdIG5vZGUgaXMgYSBsZWdlbmQgdGFibGUgYW5kIG5vdCB0aGUgYWN0dWFsIGRhdGEgd2UgYXJlIGludGVyZXN0ZWQgaW4uDQorIFdlIHVzZWQgaHRtbF9ub2RlcyBzbyB0aGF0IHdlIGNvdWxkIHNwZWNpZnkgdGhlIHNlY29uZCDigJx0YWJsZeKAnSBlbGVtZW50IHVzaW5nIHRoZSB0YWJbWzJdXSBjb21tYW5kDQorDQoNCjxicj4NCg0KLSAtIC0NCg0KPGJyPjxicj48YnI+PGJyPjxicj4NCg0KPHN0eWxlPg0KLmNhcHRpb24gew0KICBjb2xvcjogIzc3NzsNCiAgbWFyZ2luLXRvcDogMTBweDsNCn0NCnAgY29kZSB7DQogIHdoaXRlLXNwYWNlOiBpbmhlcml0Ow0KfQ0KcHJlIHsNCiAgd29yZC1icmVhazogbm9ybWFsOw0KICB3b3JkLXdyYXA6IG5vcm1hbDsNCiAgbGluZS1oZWlnaHQ6IDE7DQp9DQpwcmUgY29kZSB7DQogIHdoaXRlLXNwYWNlOiBpbmhlcml0Ow0KfQ0KcCxsaSB7DQogIGZvbnQtZmFtaWx5OiAiVHJlYnVjaGV0IE1TIiwgIuW+rui7n+ato+m7kemrlCIsICJNaWNyb3NvZnQgSmhlbmdIZWkiOw0KfQ0KDQoucnsNCiAgbGluZS1oZWlnaHQ6IDEuMjsNCn0NCg0KdGl0bGV7DQogIGNvbG9yOiAjY2MwMDAwOw0KICBmb250LWZhbWlseTogIlRyZWJ1Y2hldCBNUyIsICLlvq7ou5/mraPpu5Hpq5QiLCAiTWljcm9zb2Z0IEpoZW5nSGVpIjsNCn0NCg0KYm9keXsNCiAgZm9udC1mYW1pbHk6ICJUcmVidWNoZXQgTVMiLCAi5b6u6Luf5q2j6buR6auUIiwgIk1pY3Jvc29mdCBKaGVuZ0hlaSI7DQp9DQoNCmgxLGgyLGgzLGg0LGg1ew0KICBjb2xvcjogIzAwODgwMDsNCiAgZm9udC1mYW1pbHk6ICJUcmVidWNoZXQgTVMiLCAi5b6u6Luf5q2j6buR6auUIiwgIk1pY3Jvc29mdCBKaGVuZ0hlaSI7DQp9DQoNCmgzew0KICBjb2xvcjogI2IzNmIwMDsNCiAgYmFja2dyb3VuZDogI2ZmZTBiMzsNCiAgbGluZS1oZWlnaHQ6IDI7DQogIGZvbnQtd2VpZ2h0OiBib2xkOw0KfQ0KDQpoNXsNCiAgY29sb3I6ICMwMDYwMDA7DQogIGJhY2tncm91bmQ6ICNmZmZmZTA7DQogIGxpbmUtaGVpZ2h0OiAyOw0KICBmb250LXdlaWdodDogYm9sZDsNCn0NCg0KZW17DQogIGNvbG9yOiAjMDAwMGMwOw0KICBiYWNrZ3JvdW5kOiAjZjBmMGYwOw0KICB9DQo8L3N0eWxlPg0K