Pop quiz!
Sampling from a bowl of red and white balls!
About me
- PhD trained statistician
- Worked at Google in AdWords Division
- Small colleges: Reed, Middlebury, Amherst, and now Smith Colleges
- Awash in “statistics vs data science” debates
Awash in quotes…
Some more problematic than others:
- A data scientist is someone who is better at statistics than any software engineer and better at software engineering than any statistician.
- A data scientist is a statistician who lives in San Francisco
- A data scientist is a statistician who is wearing a bow tie.
- From my time at Google: An engineer knows what an average is, but an analyst knows what a standard deviation is
rudeboybert says
What can statistics bring to the data science table? Among other things, how about?
A statistician is a data scientist who understands what a standard error is.
ModernDive
A few pedagogical principles
- Have intro students “play the whole game”
- Use data science, not probability/mathematical formulas, to motivate statistical inference
- Coding as a basic skill
Principle 1: “Play the whole game”
In the context of statistics/data analysis, by “play the whole game” we mean Wickham’s data/science pipeline:
Tee-ball
Think how children learn “tee-ball” and play a simplified version of the “whole game” first…

Softball & baseball
… and then eventually graduate to softball/baseball.

Example “whole game”
- Load the Seattle house prices dataset from Kaggle saved in
moderndive::house_prices
- Model \(y\) the sale
price of house as a function of two explanatory/predictor variables:
- \(x_1\): size (
sqft_living square feet)
- \(x_2\):
condition (catgorical w/ 1 = lowest, 5 = best)
- Communicate the results to a realtor
1. Load packages and data
Load subset of variables:
library(ggplot2)
library(dplyr)
library(moderndive)
library(patchwork)
house_prices %>%
select(id, date, price, sqft_living, condition) %>%
head()
| 7129300520 |
2014-10-13 |
221900 |
1180 |
3 |
| 6414100192 |
2014-12-09 |
538000 |
2570 |
3 |
| 5631500400 |
2015-02-25 |
180000 |
770 |
3 |
| 2487200875 |
2014-12-09 |
604000 |
1960 |
5 |
| 1954400510 |
2015-02-18 |
510000 |
1680 |
3 |
| 7237550310 |
2014-05-12 |
1225000 |
5420 |
3 |
2. Exploratory data analysis
Variables price and sqft_living are right-skewed:
p1 <- ggplot(house_prices, aes(x = price)) +
geom_histogram() +
labs(x = "price", title = "House prices in Seattle")
p2 <- ggplot(house_prices, aes(x = sqft_living)) +
geom_histogram() +
labs(x = "square feet", title = "Size of houses in Seattle")
p1 + p2

Apply a log base 10 tranformation:
house_prices <- house_prices %>%
mutate(
log10_price = log10(price),
log10_sqft_living = log10(sqft_living)
)
p1 <- ggplot(house_prices, aes(x = log10_price)) +
geom_histogram() +
labs(x = "log10 price", title = "House prices in Seattle")
p2 <- ggplot(house_prices, aes(x = log10_sqft_living)) +
geom_histogram() +
labs(x = "log10 square feet", title = "Size of houses in Seattle")
p1 + p2

3. Eyeball the relationship
Visualize the relationship between the variables using facets…
ggplot(house_prices, aes(x = log10_sqft_living, y = log10_price)) +
geom_point(alpha = 0.5) +
labs(y = "log10 price", x = "log10 square footage", title = "House prices in Seattle") +
geom_smooth(method = "lm", se = FALSE) +
facet_wrap(~condition)

… or colors
ggplot(house_prices, aes(x = log10_sqft_living, y = log10_price, col = condition)) +
geom_point(alpha = 0.1) +
labs(y = "log10 price", x = "log10 square footage", title = "House prices in Seattle") +
geom_smooth(method = "lm", se = FALSE)

4. Quantify the relationship
- Fit an interaction model which allows for a unique regression line for each
condition value
- Output the regression table along with confidence intervals, not just the p-values.
model_price <- lm(log10_price ~ log10_sqft_living * condition, data = house_prices)
get_regression_table(model_price)
| intercept |
3.330 |
0.451 |
7.380 |
0.000 |
2.446 |
4.215 |
| log10_sqft_living |
0.690 |
0.148 |
4.652 |
0.000 |
0.399 |
0.980 |
| condition2 |
0.047 |
0.498 |
0.094 |
0.925 |
-0.930 |
1.024 |
| condition3 |
-0.367 |
0.452 |
-0.812 |
0.417 |
-1.253 |
0.519 |
| condition4 |
-0.398 |
0.453 |
-0.879 |
0.380 |
-1.286 |
0.490 |
| condition5 |
-0.883 |
0.457 |
-1.931 |
0.053 |
-1.779 |
0.013 |
| log10_sqft_living:condition2 |
-0.024 |
0.163 |
-0.148 |
0.882 |
-0.344 |
0.295 |
| log10_sqft_living:condition3 |
0.133 |
0.148 |
0.893 |
0.372 |
-0.158 |
0.424 |
| log10_sqft_living:condition4 |
0.146 |
0.149 |
0.979 |
0.328 |
-0.146 |
0.437 |
| log10_sqft_living:condition5 |
0.310 |
0.150 |
2.067 |
0.039 |
0.016 |
0.604 |
Objective
End goal: understand and interpret the inference for regression, which requires lot of skills/knowledge. For example:
- What’s the difference between R & RStudio? What’s an R package?
- How do effectively visualize data?
- How can I clean data as it “exists in the wild”?
- How do I model the relationship between variables?
- What is the error/uncertainty of our results?
Principle 2: Inference via data science
First: Tactile simulations
Second: Virtual simulations
- Take a virtual bowl
- Extract a virtual sample using a virtual shovel
- Construct the sampling distribution by repeating the above 1000 times.
- Plot!
library(dplyr)
library(ggplot2)
library(moderndive)
# Take 1000 virtual samples of size n = 50 from bowl
virtual_samples <- bowl %>%
rep_sample_n(size = 50, reps = 1000)
# Compute 1000 simulated p-hats based on these 1000 virtual samples
virtual_p_hats <- virtual_samples %>%
group_by(replicate) %>%
summarize(p_hat = mean(color == "red"))
# Plot sampling distribution
ggplot(virtual_p_hats, aes(x = p_hat)) +
geom_histogram(binwidth = 0.05) +
labs(title = "Sampling distribution of p_hat based on samples of n = 50")

Simulations
- Need to do tactile simulations first; too many layers of abstraction otherwise
- Draw link between tactile (actual bowl and shovel) and virtual (data frames and functions in R) then
- To perform and deconstruct latter, students need to be equipped with a data science toolbox: data visualization and basic data wrangling.
- Example involving sample means: Average year of minting of pennies using a virtual sack of \(N=800\)
pennies
State of affairs
- Beta version of above has been implemented in development version of ModernDive Chapter 8: Sampling
- Under construction: Chapters 9 thru 11 on confidence intervals, hypothesis testing, and inference for regression
- Pending developments on
infer package https://infer.netlify.com/
infer package for tidy statistical inference
Principle 3: Coding as a basic skill
- Battle is more psychological than anything else.
- I’m constantly saying: “Don’t code from scratch. Rather copy, paste, and tweak!”
- ModernDive Chapters 3 thru 5 on data visualization with
ggplot2, tidy data, and data wrangling with dplyr align near perfectly with DataCamp “Introduction to the Tidyverse” so we can outsource less sexy aspects of teaching coding for data science to beginners.

Thanks!
- Chester Ismay - Senior Curriculum Lead, DataCamp
- Albert Y. Kim - Assnt Prof. of Statistical & Data Sciences, Smith College
LS0tCnRpdGxlOiAiTW9kZXJuRGl2ZTogU3RhdGlzdGljYWwgSW5mZXJlbmNlIHZpYSBEYXRhIFNjaWVuY2UiCmF1dGhvcjogIkFsYmVydCBZLiBLaW0gLSBBbWhlcnN0IENvbGxlZ2UgLT4gU21pdGggQ29sbGVnZSAoSnVseSAyMDE4KSIKZGF0ZTogIldlZCBNYXkgMjNyZCwgMjAxOCIKb3V0cHV0OgojICBpb3NsaWRlc19wcmVzZW50YXRpb246CiAgaHRtbF9kb2N1bWVudDoKICAgIHRvYzogdHJ1ZQogICAgdG9jX2RlcHRoOiAzCiAgICB0b2NfZmxvYXQ6IHRydWUKICAgIGRmX3ByaW50OiBrYWJsZQogICAgdGhlbWU6IGNvc21vCiAgICBoaWdobGlnaHQ6IHRhbmdvICAKICAgIGNvZGVfZG93bmxvYWQ6IHRydWUKICAgIGNvZGVfZm9sZGluZzogaGlkZQotLS0KCgo8c3R5bGU+CmgxIHsgCiBjb2xvcjogIzQ1MTY3NTsJCQp9CmgyIHsgCiBjb2xvcjogIzQ1MTY3NTsJCQp9CmE6bGluayB7CiAgY29sb3I6ICM0NTE2NzU7CQp9CnNsaWRlcyA+IHNsaWRlLnRpdGxlLXNsaWRlIGhncm91cCBoMSB7CiAgZm9udC13ZWlnaHQ6IGJvbGQ7CiAgZm9udC1zaXplOiAzNXB0OwogIGNvbG9yOiAjNDUxNjc1Owp9CnNsaWRlcyA+IHNsaWRlLmJhY2tkcm9wIHsKICBiYWNrZ3JvdW5kOiB3aGl0ZTsKfQoKPC9zdHlsZT4KCmBgYHtyIHNldHVwLCBpbmNsdWRlPUZBTFNFLCBwdXJsPUZBTFNFfQppZihUUlVFKXsKICBrbml0cjo6b3B0c19jaHVuayRzZXQoCiAgICBlY2hvID0gVFJVRSwgZXZhbCA9IFRSVUUsIG1lc3NhZ2UgPSBGQUxTRSwgd2FybmluZyA9IEZBTFNFLAogICAgZmlnLndpZHRoID0gMTYvMiwgZmlnLmhlaWdodCA9IDkvMgogICAgKQp9IGVsc2UgewogIGtuaXRyOjpvcHRzX2NodW5rJHNldCgKICAgIGVjaG8gPSBUUlVFLCBldmFsID0gVFJVRSwgbWVzc2FnZSA9IEZBTFNFLCB3YXJuaW5nID0gRkFMU0UsCiAgICBmaWcud2lkdGggPSAxNi8yLCBmaWcuaGVpZ2h0ID0gOS8yKQogIGtuaXRyOjpwdXJsKCJlQ09UUy5SbWQiLCBkb2N1bWVudGF0aW9uID0gMCkKfQpgYGAKCgoKCiMjIFBvcCBxdWl6IQoKU2FtcGxpbmcgZnJvbSBhIGJvd2wgb2YgcmVkIGFuZCB3aGl0ZSBiYWxscyEKCgojIyBBYm91dCBtZQoKKiBQaEQgdHJhaW5lZCBzdGF0aXN0aWNpYW4gCiogV29ya2VkIGF0IEdvb2dsZSBpbiBBZFdvcmRzIERpdmlzaW9uCiogU21hbGwgY29sbGVnZXM6IFJlZWQsIE1pZGRsZWJ1cnksIEFtaGVyc3QsIGFuZCBub3cgU21pdGggQ29sbGVnZXMKKiBBd2FzaCBpbiAic3RhdGlzdGljcyB2cyBkYXRhIHNjaWVuY2UiIGRlYmF0ZXMKCgojIyBBd2FzaCBpbiBWZW5uIERpYWdyYW1zLi4uCgpEcmV3IENvbndheSAgICAgICAgICB8ICBEcmV3IENvbndheSAyLjAKOi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS06fDotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tOgo8aW1nIHNyYz0iaHR0cHM6Ly9naXRodWIuY29tL3J1ZGVib3liZXJ0L1NUQVQxMzUvYmxvYi9tYXN0ZXIvc3RhdGljL2ltYWdlcy9kYXRhX3NjaWVuY2VfMS5wbmc/cmF3PXRydWUiIGFsdD0iRHJhd2luZyIgc3R5bGU9ImhlaWdodDogMjAwcHg7Ii8+IHwgPGltZyBzcmM9Imh0dHA6Ly9pMi53cC5jb20vd3d3Lmpvc2UtZ29uemFsZXoub3JnL3dwLWNvbnRlbnQvdXBsb2Fkcy8yMDEzLzA4L2RhdGFzY2llbmNldmVuZGlhZ3JhbS5wbmciIGFsdD0iRHJhd2luZyIgc3R5bGU9ImhlaWdodDogMjAwcHg7Ii8+IAoKCiMjIEF3YXNoIGluIHF1b3Rlcy4uLgoKU29tZSBtb3JlIHByb2JsZW1hdGljIHRoYW4gb3RoZXJzOgoKKiBBIGRhdGEgc2NpZW50aXN0IGlzIHNvbWVvbmUgd2hvIGlzIGJldHRlciBhdCBzdGF0aXN0aWNzIHRoYW4gYW55IHNvZnR3YXJlIGVuZ2luZWVyIGFuZCBiZXR0ZXIgYXQgc29mdHdhcmUgZW5naW5lZXJpbmcgdGhhbiBhbnkgc3RhdGlzdGljaWFuLgoqIEEgZGF0YSBzY2llbnRpc3QgaXMgYSBzdGF0aXN0aWNpYW4gd2hvIGxpdmVzIGluIFNhbiBGcmFuY2lzY28KKiBbQSBkYXRhIHNjaWVudGlzdCBpcyBhIHN0YXRpc3RpY2lhbiB3aG8gaXMgd2VhcmluZyBhIGJvdyB0aWUuXShodHRwczovL3R3aXR0ZXIuY29tL2ZyYW5jZXNjYWRvbWluOC9zdGF0dXMvOTA2NjA4MTY4NzMzNTExNjgwKQoqIEZyb20gbXkgdGltZSBhdCBHb29nbGU6IEFuIGVuZ2luZWVyIGtub3dzIHdoYXQgYW4gYXZlcmFnZSBpcywgYnV0IGFuIGFuYWx5c3Qga25vd3Mgd2hhdCBhIHN0YW5kYXJkIGRldmlhdGlvbiBpcwoKCiMjIHJ1ZGVib3liZXJ0IHNheXMKCldoYXQgY2FuIHN0YXRpc3RpY3MgYnJpbmcgdG8gdGhlIGRhdGEgc2NpZW5jZSB0YWJsZT8gQW1vbmcgb3RoZXIgdGhpbmdzLCBob3cgYWJvdXQ/Cgo+ICoqQSBzdGF0aXN0aWNpYW4gaXMgYSBkYXRhIHNjaWVudGlzdCB3aG8gdW5kZXJzdGFuZHMgd2hhdCBhIHN0YW5kYXJkIGVycm9yIGlzLioqCgoKCiMjIE1vZGVybkRpdmUKCjxjZW50ZXI+CjxpbWcgc3JjPSJodHRwczovL2dpdGh1Yi5jb20vbW9kZXJuZGl2ZS9tb2Rlcm5kaXZlX2Jvb2svYmxvYi9tYXN0ZXIvaW1hZ2VzL2xvZ29zL3dpZGVfZm9ybWF0LnBuZz9yYXc9dHJ1ZSIgYWx0PSJEcmF3aW5nIiBzdHlsZT0iaGVpZ2h0OiAxMDBweDsiLz4gCjwvY2VudGVyPgoKPGJyPgoKKiBPcGVuIHNvdXJjZSBlbGVjdHJvbmljIHRleHRib29rIGF2YWlsYWJsZSBhdCBbbW9kZXJuZGl2ZS5jb21dKGh0dHA6Ly9tb2Rlcm5kaXZlLmNvbS8pCiogRGV2ZWxvcG1lbnQgdmVyc2lvbiBhdCBbbW9kZXJuZGl2ZS5uZXRsaWZ5LmNvbV0oaHR0cDovL21vZGVybmRpdmUubmV0bGlmeS5jb20vKSAoc291cmNlIG9mIHRvZGF5J3MgZXhhbXBsZXMpCiogUlN0dWRpbyBbYGJvb2tkb3duYF0oaHR0cHM6Ly9ib29rZG93bi5vcmcveWlodWkvYm9va2Rvd24vKSBwYWNrYWdlIHNvdXJjZSBjb2RlIG9uIEdpdEh1YiBhdCBbZ2l0aHViLmNvbS9tb2Rlcm5kaXZlL10oaHR0cHM6Ly9naXRodWIuY29tL21vZGVybmRpdmUvKQoqIE5vIHByb2dyYW1taW5nIGJhY2tncm91bmQgYXNzdW1lZAoKCgojIyBBIGZldyBwZWRhZ29naWNhbCBwcmluY2lwbGVzCgoxLiBIYXZlIGludHJvIHN0dWRlbnRzIFsicGxheSB0aGUgd2hvbGUgZ2FtZSJdKCBodHRwOi8vYS5jby81MENwSEdYKQoxLiBVc2UgZGF0YSBzY2llbmNlLCBub3QgcHJvYmFiaWxpdHkvbWF0aGVtYXRpY2FsIGZvcm11bGFzLCB0byBtb3RpdmF0ZSBzdGF0aXN0aWNhbCBpbmZlcmVuY2UKMS4gQ29kaW5nIGFzIGEgYmFzaWMgc2tpbGwKCgoKIyMgUHJpbmNpcGxlIDE6ICJQbGF5IHRoZSB3aG9sZSBnYW1lIgoKSW4gdGhlIGNvbnRleHQgb2Ygc3RhdGlzdGljcy9kYXRhIGFuYWx5c2lzLCBieSAicGxheSB0aGUgd2hvbGUgZ2FtZSIgd2UgbWVhbiBXaWNraGFtJ3MgZGF0YS9zY2llbmNlIHBpcGVsaW5lOgoKPGNlbnRlcj4KPGltZyBzcmM9Imh0dHBzOi8vZ2l0aHViLmNvbS9ydWRlYm95YmVydC9TVEFUMTM1L2Jsb2IvbWFzdGVyL3N0YXRpYy9pbWFnZXMvcGlwZWxpbmUucG5nP3Jhdz10cnVlIiBhbHQ9IkRyYXdpbmciIHN0eWxlPSJoZWlnaHQ6IDIwMHB4OyIvPiAKPC9jZW50ZXI+CgoKCiMjIFRlZS1iYWxsCgpUaGluayBob3cgY2hpbGRyZW4gbGVhcm4gInRlZS1iYWxsIiBhbmQgcGxheSBhIHNpbXBsaWZpZWQgdmVyc2lvbiBvZiB0aGUgIndob2xlIGdhbWUiIGZpcnN0Li4uCgo8aW1nIHNyYz0iaHR0cHM6Ly9naXRodWIuY29tL3J1ZGVib3liZXJ0L1NUQVQxMzUvYmxvYi9tYXN0ZXIvc3RhdGljL2ltYWdlcy90ZWViYWxsLkpQRz9yYXc9dHJ1ZSIgYWx0PSJEcmF3aW5nIiBzdHlsZT0iaGVpZ2h0OiAzMDBweDsiLz4KCgojIyBTb2Z0YmFsbCAmIGJhc2ViYWxsCgouLi4gYW5kIHRoZW4gZXZlbnR1YWxseSBncmFkdWF0ZSB0byBzb2Z0YmFsbC9iYXNlYmFsbC4KCjxpbWcgc3JjPSJodHRwczovL2dpdGh1Yi5jb20vcnVkZWJveWJlcnQvU1RBVDEzNS9ibG9iL21hc3Rlci9zdGF0aWMvaW1hZ2VzL3NvZnRiYWxsLmpwZz9yYXc9dHJ1ZSIgYWx0PSJEcmF3aW5nIiBzdHlsZT0iaGVpZ2h0OiAyNTBweDsiLz4gPGltZyBzcmM9Imh0dHBzOi8vZ2l0aHViLmNvbS9ydWRlYm95YmVydC9TVEFUMTM1L2Jsb2IvbWFzdGVyL3N0YXRpYy9pbWFnZXMvYmFzZWJhbGwuanBnP3Jhdz10cnVlIiBhbHQ9IkRyYXdpbmciIHN0eWxlPSJoZWlnaHQ6IDI1MHB4OyIvPgoKCgojIyBFeGFtcGxlICJ3aG9sZSBnYW1lIgoKKiBMb2FkIHRoZSBbU2VhdHRsZSBob3VzZSBwcmljZXMgZGF0YXNldF0oaHR0cHM6Ly93d3cua2FnZ2xlLmNvbS9oYXJsZm94ZW0vaG91c2VzYWxlc3ByZWRpY3Rpb24pIGZyb20gS2FnZ2xlIHNhdmVkIGluIGBtb2Rlcm5kaXZlOjpob3VzZV9wcmljZXNgCiogTW9kZWwgJHkkIHRoZSBzYWxlIGBwcmljZWAgb2YgaG91c2UgYXMgYSBmdW5jdGlvbiBvZiB0d28gZXhwbGFuYXRvcnkvcHJlZGljdG9yIHZhcmlhYmxlczoKICAgIDEuICR4XzEkOiBzaXplIChgc3FmdF9saXZpbmdgIHNxdWFyZSBmZWV0KQogICAgMS4gJHhfMiQ6IGBjb25kaXRpb25gIChjYXRnb3JpY2FsIHcvIDEgPSBsb3dlc3QsIDUgPSBiZXN0KQoqIENvbW11bmljYXRlIHRoZSByZXN1bHRzIHRvIGEgcmVhbHRvcgoKCiMjIyAxLiBMb2FkIHBhY2thZ2VzIGFuZCBkYXRhCgpMb2FkIHN1YnNldCBvZiB2YXJpYWJsZXM6CgpgYGB7cn0KbGlicmFyeShnZ3Bsb3QyKQpsaWJyYXJ5KGRwbHlyKQpsaWJyYXJ5KG1vZGVybmRpdmUpCmxpYnJhcnkocGF0Y2h3b3JrKQpob3VzZV9wcmljZXMgJT4lIAogIHNlbGVjdChpZCwgZGF0ZSwgcHJpY2UsIHNxZnRfbGl2aW5nLCBjb25kaXRpb24pICU+JSAKICBoZWFkKCkKYGBgCgojIyMgMi4gRXhwbG9yYXRvcnkgZGF0YSBhbmFseXNpcwoKVmFyaWFibGVzIGBwcmljZWAgYW5kIGBzcWZ0X2xpdmluZ2AgYXJlIHJpZ2h0LXNrZXdlZDoKCmBgYHtyfQpwMSA8LSBnZ3Bsb3QoaG91c2VfcHJpY2VzLCBhZXMoeCA9IHByaWNlKSkgKwogIGdlb21faGlzdG9ncmFtKCkgKwogIGxhYnMoeCA9ICJwcmljZSIsIHRpdGxlID0gIkhvdXNlIHByaWNlcyBpbiBTZWF0dGxlIikKcDIgPC0gZ2dwbG90KGhvdXNlX3ByaWNlcywgYWVzKHggPSBzcWZ0X2xpdmluZykpICsKICBnZW9tX2hpc3RvZ3JhbSgpICsKICBsYWJzKHggPSAic3F1YXJlIGZlZXQiLCB0aXRsZSA9ICJTaXplIG9mIGhvdXNlcyBpbiBTZWF0dGxlIikKcDEgKyBwMgpgYGAKCkFwcGx5IGEgbG9nIGJhc2UgMTAgdHJhbmZvcm1hdGlvbjogCgpgYGB7cn0KaG91c2VfcHJpY2VzIDwtIGhvdXNlX3ByaWNlcyAlPiUKICBtdXRhdGUoCiAgICBsb2cxMF9wcmljZSA9IGxvZzEwKHByaWNlKSwKICAgIGxvZzEwX3NxZnRfbGl2aW5nID0gbG9nMTAoc3FmdF9saXZpbmcpCiAgICApCgpwMSA8LSBnZ3Bsb3QoaG91c2VfcHJpY2VzLCBhZXMoeCA9IGxvZzEwX3ByaWNlKSkgKwogIGdlb21faGlzdG9ncmFtKCkgKwogIGxhYnMoeCA9ICJsb2cxMCBwcmljZSIsIHRpdGxlID0gIkhvdXNlIHByaWNlcyBpbiBTZWF0dGxlIikKcDIgPC0gZ2dwbG90KGhvdXNlX3ByaWNlcywgYWVzKHggPSBsb2cxMF9zcWZ0X2xpdmluZykpICsKICBnZW9tX2hpc3RvZ3JhbSgpICsKICBsYWJzKHggPSAibG9nMTAgc3F1YXJlIGZlZXQiLCB0aXRsZSA9ICJTaXplIG9mIGhvdXNlcyBpbiBTZWF0dGxlIikKcDEgKyBwMgpgYGAKCiMjIyAzLiBFeWViYWxsIHRoZSByZWxhdGlvbnNoaXAKClZpc3VhbGl6ZSB0aGUgcmVsYXRpb25zaGlwIGJldHdlZW4gdGhlIHZhcmlhYmxlcyB1c2luZyBmYWNldHMuLi4KCmBgYHtyLCBjYWNoZSA9IFRSVUV9CmdncGxvdChob3VzZV9wcmljZXMsIGFlcyh4ID0gbG9nMTBfc3FmdF9saXZpbmcsIHkgPSBsb2cxMF9wcmljZSkpICsKICBnZW9tX3BvaW50KGFscGhhID0gMC41KSArCiAgbGFicyh5ID0gImxvZzEwIHByaWNlIiwgeCA9ICJsb2cxMCBzcXVhcmUgZm9vdGFnZSIsIHRpdGxlID0gIkhvdXNlIHByaWNlcyBpbiBTZWF0dGxlIikgKwogIGdlb21fc21vb3RoKG1ldGhvZCA9ICJsbSIsIHNlID0gRkFMU0UpICsKICBmYWNldF93cmFwKH5jb25kaXRpb24pCmBgYAoKLi4uIG9yIGNvbG9ycwoKYGBge3IsIGNhY2hlID0gVFJVRX0KZ2dwbG90KGhvdXNlX3ByaWNlcywgYWVzKHggPSBsb2cxMF9zcWZ0X2xpdmluZywgeSA9IGxvZzEwX3ByaWNlLCBjb2wgPSBjb25kaXRpb24pKSArCiAgZ2VvbV9wb2ludChhbHBoYSA9IDAuMSkgKwogIGxhYnMoeSA9ICJsb2cxMCBwcmljZSIsIHggPSAibG9nMTAgc3F1YXJlIGZvb3RhZ2UiLCB0aXRsZSA9ICJIb3VzZSBwcmljZXMgaW4gU2VhdHRsZSIpICsKICBnZW9tX3Ntb290aChtZXRob2QgPSAibG0iLCBzZSA9IEZBTFNFKQpgYGAKCgoKIyMjIDQuIFF1YW50aWZ5IHRoZSByZWxhdGlvbnNoaXAKCiogRml0IGFuIGludGVyYWN0aW9uIG1vZGVsIHdoaWNoIGFsbG93cyBmb3IgYSB1bmlxdWUgcmVncmVzc2lvbiBsaW5lIGZvciBlYWNoIGBjb25kaXRpb25gIHZhbHVlCiogT3V0cHV0IHRoZSByZWdyZXNzaW9uIHRhYmxlICoqYWxvbmcgd2l0aCBjb25maWRlbmNlIGludGVydmFscywgbm90IGp1c3QgdGhlIHAtdmFsdWVzKiouCgpgYGB7cn0KbW9kZWxfcHJpY2UgPC0gbG0obG9nMTBfcHJpY2UgfiBsb2cxMF9zcWZ0X2xpdmluZyAqIGNvbmRpdGlvbiwgZGF0YSA9IGhvdXNlX3ByaWNlcykKZ2V0X3JlZ3Jlc3Npb25fdGFibGUobW9kZWxfcHJpY2UpCmBgYAoKCgojIyBPYmplY3RpdmUKCioqRW5kIGdvYWwqKjogdW5kZXJzdGFuZCBhbmQgaW50ZXJwcmV0IHRoZSBpbmZlcmVuY2UgZm9yIHJlZ3Jlc3Npb24sIHdoaWNoIHJlcXVpcmVzIGxvdCBvZiBza2lsbHMva25vd2xlZGdlLiBGb3IgZXhhbXBsZToKCj4gMS4gV2hhdCdzIHRoZSBkaWZmZXJlbmNlIGJldHdlZW4gUiAmIFJTdHVkaW8/IFdoYXQncyBhbiBSIHBhY2thZ2U/Cj4gMS4gSG93IGRvIGVmZmVjdGl2ZWx5IHZpc3VhbGl6ZSBkYXRhPwo+IDEuIEhvdyBjYW4gSSBjbGVhbiBkYXRhIGFzIGl0ICJleGlzdHMgaW4gdGhlIHdpbGQiPwo+IDEuIEhvdyBkbyBJIG1vZGVsIHRoZSByZWxhdGlvbnNoaXAgYmV0d2VlbiB2YXJpYWJsZXM/Cj4gMS4gV2hhdCBpcyB0aGUgZXJyb3IvdW5jZXJ0YWludHkgb2Ygb3VyIHJlc3VsdHM/CgoKCiMjIE1lYW5zIHRvIHRoZSBlbmQKCj4gMS4gQW5hbG9naWVzOiBbUiB2cyBSU3R1ZGlvXShodHRwOi8vbW9kZXJuZGl2ZS5uZXRsaWZ5LmNvbS8yLWdldHRpbmctc3RhcnRlZC5odG1sI3doYXQtYXJlLXItYW5kLXJzdHVkaW8pIGFuZCBbUiBwYWNrYWdlc10oaHR0cDovL21vZGVybmRpdmUubmV0bGlmeS5jb20vMi1nZXR0aW5nLXN0YXJ0ZWQuaHRtbCNwYWNrYWdlcykKPiAxLiBWaXN1YWxpemF0aW9uIHZpYSBgZ2dwbG90MmA6IFtHcmFtbWFyIG9mIEdyYXBoaWNzXShodHRwOi8vbW9kZXJuZGl2ZS5uZXRsaWZ5LmNvbS8zLXZpei5odG1sI2NvbXBvbmVudHMtb2YtdGhlLWdyYW1tYXIpIGFuZCBsaW1pdCBzY29wZSB0byBbIkZpdmUgTmFtZWQgR3JhcGhzIl0oaHR0cDovL21vZGVybmRpdmUubmV0bGlmeS5jb20vMy12aXouaHRtbCNGaXZlTkcpCj4gMS4gYGRwbHlyYCBbIkZpdmUgTWFpbiBWZXJicyJdKGh0dHA6Ly9tb2Rlcm5kaXZlLm5ldGxpZnkuY29tLzUtd3JhbmdsaW5nLmh0bWwjZml2ZS1tYWluLXZlcmJzLS0tdGhlLTVtdikgZm9yIGRhdGEgd3JhbmdsaW5nL3RyYW5zZm9ybWF0aW9uCj4gMS4gRGVzY3JpcHRpdmUgcmVncmVzc2lvbiBtb2RlbGluZyB3aXRoIGVtcGhhc2lzIG9uIGV4cGxvcmF0b3J5IGRhdGEgYW5hbHlzaXMgKFNlZSBbRmlndXJlIDcuNF0oaHR0cDovL21vZGVybmRpdmUubmV0bGlmeS5jb20vNy1tdWx0aXBsZS1yZWdyZXNzaW9uLmh0bWwjbW9kZWw0RURBKSkKPiAxLiBIb3cgZG8gd2UgdGVhY2ggaWRlYXMgb2YgcmVwcmVzZW50YXRpdmUgc2FtcGxpbmcsIHNhbXBsaW5nIGRpc3RyaWJ1dGlvbnMsIGFuZCBzdGFuZGFyZCBlcnJvcnM/IEEgd29yayBpbiBwcm9ncmVzcy4uLgoKCiMjIFByaW5jaXBsZSAyOiBJbmZlcmVuY2UgdmlhIGRhdGEgc2NpZW5jZQoKPGNlbnRlcj4KPGJsb2NrcXVvdGUgY2xhc3M9InR3aXR0ZXItdHdlZXQiIGRhdGEtbGFuZz0iZW4iPjxwIGxhbmc9ImVuIiBkaXI9Imx0ciI+PGEgaHJlZj0iaHR0cHM6Ly90d2l0dGVyLmNvbS9taW5lYm9jZWs/cmVmX3NyYz10d3NyYyU1RXRmdyI+QG1pbmVib2NlazwvYT4gZW1waGFzaXppbmcgdGhhdCBtb3N0IHN0dWRlbnRzIHdvbiYjMzk7dCBnZXQgZXhjaXRlZCBhYm91dCBzdGF0cy9kYXRhIHNjaWVuY2UgdmlhIHVybiBtb2RlbHMvcHJvYmFiaWxpdHkgPGEgaHJlZj0iaHR0cHM6Ly90d2l0dGVyLmNvbS9oYXNodGFnL1VTQ09UUzIwMTc/c3JjPWhhc2gmYW1wO3JlZl9zcmM9dHdzcmMlNUV0ZnciPiNVU0NPVFMyMDE3PC9hPiA8YSBocmVmPSJodHRwczovL3QuY28vdW1lMGt1dkZZVCI+cGljLnR3aXR0ZXIuY29tL3VtZTBrdXZGWVQ8L2E+PC9wPiZtZGFzaDsgQWxiZXJ0IFkuIEtpbSAoQHJ1ZGVib3liZXJ0KSA8YSBocmVmPSJodHRwczovL3R3aXR0ZXIuY29tL3J1ZGVib3liZXJ0L3N0YXR1cy84NjU5MTI2NzM0ODkzNDY1NjE/cmVmX3NyYz10d3NyYyU1RXRmdyI+TWF5IDIwLCAyMDE3PC9hPjwvYmxvY2txdW90ZT4KPHNjcmlwdCBhc3luYyBzcmM9Imh0dHBzOi8vcGxhdGZvcm0udHdpdHRlci5jb20vd2lkZ2V0cy5qcyIgY2hhcnNldD0idXRmLTgiPjwvc2NyaXB0Pgo8L2NlbnRlcj4KCgoKCiMjIFNpbXVsYXRpb25zIG5vdCBwcm9iYWJpbGl0eS9mb3JtdWxhcwoKTW9yZSBvZiB0aGlzICAgICAgICAgIHwgIExlc3Mgb2YgdGhpcwo6LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLTp8Oi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS06CjxpbWcgc3JjPSJodHRwczovL2hlYXZ5ZWRpdG9yaWFsLmZpbGVzLndvcmRwcmVzcy5jb20vMjAxNy8xMi9zY3JlZW4tc2hvdC0yMDE3LTEyLTMwLWF0LTUtMjktMTMtYW0uanBnP3F1YWxpdHk9NjUmc3RyaXA9YWxsJnc9MTAyNCIgYWx0PSJEcmF3aW5nIiBzdHlsZT0iaGVpZ2h0OiAyMDBweDsiLz4gfCA8aW1nIHNyYz0iaHR0cHM6Ly9naXRodWIuY29tL3J1ZGVib3liZXJ0L1NUQVQxMzUvYmxvYi9tYXN0ZXIvc3RhdGljL2ltYWdlcy9mb3JtdWxhcy5wbmc/cmF3PXRydWUiIGFsdD0iRHJhd2luZyIgc3R5bGU9ImhlaWdodDogMjAwcHg7Ii8+IAoKCiMjIEZpcnN0OiBUYWN0aWxlIHNpbXVsYXRpb25zCgo8Y2VudGVyPgo8YmxvY2txdW90ZSBjbGFzcz0idHdpdHRlci10d2VldCIgZGF0YS1sYW5nPSJlbiI+PHAgbGFuZz0iZW4iIGRpcj0ibHRyIj5TZW1pLWFubnVhbCB0YWN0aWxlIHNpbXVsYXRpb24gb2Ygc2FtcGxpbmcgdG8gZXN0aW1hdGUgcHJvcG9ydGlvbiBvZiBiYWxscyBpbiBhIGJvd2wgdGhhdCBhcmUgcmVkICh0aGVuIGNvbnN0cnVjdCBzYW1wbGluZyBkaXN0cmlidXRpb24pLiBXZW50IG11Y2ggY2xlYW5lciB0aGlzIHRpbWUgd2l0aCBSZWQgU29sbyBDdXBzISA8YSBocmVmPSJodHRwczovL3R3aXR0ZXIuY29tL3RvYnlrZWl0aD9yZWZfc3JjPXR3c3JjJTVFdGZ3Ij5AdG9ieWtlaXRoPC9hPiA8YSBocmVmPSJodHRwczovL3R3aXR0ZXIuY29tL2hhc2h0YWcvbGV0c2hhdmVhcGFydHk/c3JjPWhhc2gmYW1wO3JlZl9zcmM9dHdzcmMlNUV0ZnciPiNsZXRzaGF2ZWFwYXJ0eTwvYT4gPGEgaHJlZj0iaHR0cHM6Ly90LmNvLzZicUVkb0ZxdmQiPnBpYy50d2l0dGVyLmNvbS82YnFFZG9GcXZkPC9hPjwvcD4mbWRhc2g7IEFsYmVydCBZLiBLaW0gKEBydWRlYm95YmVydCkgPGEgaHJlZj0iaHR0cHM6Ly90d2l0dGVyLmNvbS9ydWRlYm95YmVydC9zdGF0dXMvOTc2ODUwMzI2ODc0NzA1OTIwP3JlZl9zcmM9dHdzcmMlNUV0ZnciPk1hcmNoIDIyLCAyMDE4PC9hPjwvYmxvY2txdW90ZT4KPHNjcmlwdCBhc3luYyBzcmM9Imh0dHBzOi8vcGxhdGZvcm0udHdpdHRlci5jb20vd2lkZ2V0cy5qcyIgY2hhcnNldD0idXRmLTgiPjwvc2NyaXB0Pgo8L2NlbnRlcj4KCgojIyBTZWNvbmQ6IFZpcnR1YWwgc2ltdWxhdGlvbnMKCiogVGFrZSBhIFt2aXJ0dWFsIGJvd2xdKGh0dHA6Ly9tb2Rlcm5kaXZlLm5ldGxpZnkuY29tLzgtc2FtcGxpbmcuaHRtbCN2aXJ0dWFsLXNhbXBsaW5nLWZyb20tYm93bCkKKiBFeHRyYWN0IGEgdmlydHVhbCBzYW1wbGUgdXNpbmcgYSBbdmlydHVhbCBzaG92ZWxdKGh0dHA6Ly9tb2Rlcm5kaXZlLm5ldGxpZnkuY29tLzgtc2FtcGxpbmcuaHRtbCN2aXJ0dWFsbHktdXNpbmctc2hvdmVsLW9uY2UpCiogQ29uc3RydWN0IHRoZSBzYW1wbGluZyBkaXN0cmlidXRpb24gYnkgcmVwZWF0aW5nIHRoZSBhYm92ZSAxMDAwIHRpbWVzLgoqIFBsb3QhCgpgYGB7cn0KbGlicmFyeShkcGx5cikKbGlicmFyeShnZ3Bsb3QyKQpsaWJyYXJ5KG1vZGVybmRpdmUpCgojIFRha2UgMTAwMCB2aXJ0dWFsIHNhbXBsZXMgb2Ygc2l6ZSBuID0gNTAgZnJvbSBib3dsCnZpcnR1YWxfc2FtcGxlcyA8LSBib3dsICU+JQogIHJlcF9zYW1wbGVfbihzaXplID0gNTAsIHJlcHMgPSAxMDAwKQoKIyBDb21wdXRlIDEwMDAgc2ltdWxhdGVkIHAtaGF0cyBiYXNlZCBvbiB0aGVzZSAxMDAwIHZpcnR1YWwgc2FtcGxlcwp2aXJ0dWFsX3BfaGF0cyA8LSB2aXJ0dWFsX3NhbXBsZXMgJT4lIAogIGdyb3VwX2J5KHJlcGxpY2F0ZSkgJT4lIAogIHN1bW1hcml6ZShwX2hhdCA9IG1lYW4oY29sb3IgPT0gInJlZCIpKQoKIyBQbG90IHNhbXBsaW5nIGRpc3RyaWJ1dGlvbgpnZ3Bsb3QodmlydHVhbF9wX2hhdHMsIGFlcyh4ID0gcF9oYXQpKSArCiAgZ2VvbV9oaXN0b2dyYW0oYmlud2lkdGggPSAwLjA1KSArCiAgbGFicyh0aXRsZSA9ICJTYW1wbGluZyBkaXN0cmlidXRpb24gb2YgcF9oYXQgYmFzZWQgb24gc2FtcGxlcyBvZiBuID0gNTAiKQpgYGAKCgojIyBTaW11bGF0aW9ucwoKPiAxLiBOZWVkIHRvIGRvIHRhY3RpbGUgc2ltdWxhdGlvbnMgZmlyc3Q7IHRvbyBtYW55IGxheWVycyBvZiBhYnN0cmFjdGlvbiBvdGhlcndpc2UgCj4gMS4gRHJhdyBsaW5rIGJldHdlZW4gdGFjdGlsZSAoYWN0dWFsIGJvd2wgYW5kIHNob3ZlbCkgYW5kIHZpcnR1YWwgKGRhdGEgZnJhbWVzIGFuZCBmdW5jdGlvbnMgaW4gUikgdGhlbgo+IDEuIFRvIHBlcmZvcm0gYW5kIGRlY29uc3RydWN0IGxhdHRlciwgc3R1ZGVudHMgbmVlZCB0byBiZSBlcXVpcHBlZCB3aXRoIGEgZGF0YSBzY2llbmNlIHRvb2xib3g6IGRhdGEgdmlzdWFsaXphdGlvbiBhbmQgYmFzaWMgZGF0YSB3cmFuZ2xpbmcuCj4gMS4gW0V4YW1wbGUgaW52b2x2aW5nIHNhbXBsZSBtZWFuc10oaHR0cHM6Ly9ydWRlYm95YmVydC5naXRodWIuaW8vU1RBVDEzNS9zdGF0aWMvUFMvUFMxMF9zb2x1dGlvbnMuaHRtbCk6IEF2ZXJhZ2UgeWVhciBvZiBtaW50aW5nIG9mIHBlbm5pZXMgdXNpbmcgYSB2aXJ0dWFsIHNhY2sgb2YgJE49ODAwJCBgcGVubmllc2AKCgojIyBTdGF0ZSBvZiBhZmZhaXJzCgoqIEJldGEgdmVyc2lvbiBvZiBhYm92ZSBoYXMgYmVlbiBpbXBsZW1lbnRlZCBpbiBkZXZlbG9wbWVudCB2ZXJzaW9uIG9mIE1vZGVybkRpdmUgW0NoYXB0ZXIgODogU2FtcGxpbmddKGh0dHBzOi8vbW9kZXJuZGl2ZS5naXRodWIuaW8vbW9kZXJuZGl2ZV9ib29rLzgtc2FtcGxpbmcuaHRtbCkKKiAqKlVuZGVyIGNvbnN0cnVjdGlvbioqOiBDaGFwdGVycyA5IHRocnUgMTEgb24gY29uZmlkZW5jZSBpbnRlcnZhbHMsIGh5cG90aGVzaXMgdGVzdGluZywgYW5kIGluZmVyZW5jZSBmb3IgcmVncmVzc2lvbgoqIFBlbmRpbmcgZGV2ZWxvcG1lbnRzIG9uIGBpbmZlcmAgcGFja2FnZSA8aHR0cHM6Ly9pbmZlci5uZXRsaWZ5LmNvbS8+CgoKIyMgaW5mZXIgcGFja2FnZSBmb3IgdGlkeSBzdGF0aXN0aWNhbCBpbmZlcmVuY2UKCjxjZW50ZXI+CjxpbWcgc3JjPSJodHRwczovL2kuaW1ndXIuY29tL1RZZmY3UzUucG5nIiBhbHQ9IkRyYXdpbmciIHN0eWxlPSJoZWlnaHQ6IDIwMHB4OyIvPgo8L2NlbnRlcj4KCgoqIENvbmZpZGVuY2UgaW50ZXJ2YWxzOiBbaW1hZ2VdKGh0dHBzOi8vaXNtYXljLmdpdGh1Yi5pby90YWxrcy9uZXNzLWluZmVyL2ltZy9pbmZlcl9jaS5qcGcpCiogSHlwb3RoZXNpcyB0ZXN0czogW2ltYWdlXShodHRwczovL2lzbWF5Yy5naXRodWIuaW8vdGFsa3MvbmVzcy1pbmZlci9zbGlkZV9kZWNrLmh0bWwjMTE5KQoqIEFsbGFuIERvd25leSBpZGVhIG9mIFsiVGhlcmUgaXMgb25seSBvbmUgdGVzdCJdKGh0dHBzOi8vaXNtYXljLmdpdGh1Yi5pby90YWxrcy9uZXNzLWluZmVyL3NsaWRlX2RlY2suaHRtbCMxNTUpCgoKCgoKCgojIyBQcmluY2lwbGUgMzogQ29kaW5nIGFzIGEgYmFzaWMgc2tpbGwKCiogQmF0dGxlIGlzIG1vcmUgcHN5Y2hvbG9naWNhbCB0aGFuIGFueXRoaW5nIGVsc2UuCiogSSdtIGNvbnN0YW50bHkgc2F5aW5nOiAiRG9uJ3QgY29kZSBmcm9tIHNjcmF0Y2guIFJhdGhlciBjb3B5LCBwYXN0ZSwgYW5kIHR3ZWFrISIKKiBNb2Rlcm5EaXZlIENoYXB0ZXJzIDMgdGhydSA1IG9uIGRhdGEgdmlzdWFsaXphdGlvbiB3aXRoIGBnZ3Bsb3QyYCwgdGlkeSBkYXRhLCBhbmQgZGF0YSB3cmFuZ2xpbmcgd2l0aCBgZHBseXJgIGFsaWduIG5lYXIgcGVyZmVjdGx5IHdpdGggRGF0YUNhbXAgWyJJbnRyb2R1Y3Rpb24gdG8gdGhlIFRpZHl2ZXJzZSJdKGh0dHBzOi8vd3d3LmRhdGFjYW1wLmNvbS9jb3Vyc2VzL2ludHJvZHVjdGlvbi10by10aGUtdGlkeXZlcnNlKSBzbyB3ZSBjYW4gb3V0c291cmNlIGxlc3Mgc2V4eSBhc3BlY3RzIG9mIHRlYWNoaW5nIGNvZGluZyBmb3IgZGF0YSBzY2llbmNlIHRvIGJlZ2lubmVycy4KCjxpbWcgc3JjPSJ0aWR5dmVyc2UucG5nIiBhbHQ9IkRyYXdpbmciIHN0eWxlPSJoZWlnaHQ6IDI1MHB4OyIvPgoKCgojIyBFeGFtcGxlcyBvZiBzdHVkZW50IHdvcmsKClNwcmluZyAyMDE4IFNUQVQxMzUgdGVybSBwcm9qZWN0czogKFtwcm9qZWN0IGd1aWRlbGluZXNdKGh0dHBzOi8vcnVkZWJveWJlcnQuZ2l0aHViLmlvL1NUQVQxMzUvdGVybV9wcm9qZWN0Lmh0bWwpKToKCjEuIFtTd2VldCBIb21lIEFsYWJhbWE6IFZvdGVyIFN1cHBvcnQgZm9yIFRydW1wIGFuZCBNb29yZSBBY3Jvc3MgUmFjaWFsbHktRGl2aWRlZCBDb3VudGllc10oaHR0cDovL3JwdWJzLmNvbS9tYmhhbmRhcmkyMC8zNzQ5NjQpCjEuIFtUaGUgV29ybGQgb2YgRGFyayBDaG9jb2xhdGVdKGh0dHA6Ly9ycHVicy5jb20vYW1lbWlseS8zODM3MjMpCjEuIFtUaGUgQXZlcmFnZSBZYXJkcyBvZiBhbiBBYm92ZS1BdmVyYWdlIFF1YXJ0ZXJiYWNrOiBFeGFtaW5pbmcgVG9tIEJyYWR54oCZcyBhdmVyYWdlIHlhcmRzIGFuZCBzY29yaW5nXShodHRwOi8vcnB1YnMuY29tL2NtYWNnaWxsaXZyYXkxOS9UQjEyZHJhZnQxKQoKCgoKCiMjIFRoYW5rcyEKCkNoZXN0ZXIgSXNtYXkgICAgICAgICAgfCAgQWxiZXJ0IFkuIEtpbQo6LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLTp8Oi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS06CjxpbWcgc3JjPSJodHRwczovL2dpdGh1Yi5jb20vbW9kZXJuZGl2ZS9tb2Rlcm5kaXZlX2Jvb2svYmxvYi9tYXN0ZXIvaW1hZ2VzL2lzbWF5LmpwZWc/cmF3PXRydWUiIGFsdD0iRHJhd2luZyIgc3R5bGU9ImhlaWdodDogMTUwcHg7Ii8+IHwgPGltZyBzcmM9Imh0dHBzOi8vZ2l0aHViLmNvbS9tb2Rlcm5kaXZlL21vZGVybmRpdmVfYm9vay9ibG9iL21hc3Rlci9pbWFnZXMva2ltLmpwZWc/cmF3PXRydWUiIGFsdD0iRHJhd2luZyIgc3R5bGU9ImhlaWdodDogMTUwcHg7Ii8+IAoKKiBDaGVzdGVyIElzbWF5IC0gU2VuaW9yIEN1cnJpY3VsdW0gTGVhZCwgRGF0YUNhbXAKICAgICsgVHdpdHRlcjogW1xAb2xkX21hbl9jaGVzdGVyXShodHRwczovL3R3aXR0ZXIuY29tL29sZF9tYW5fY2hlc3RlcikKICAgICsgR2l0SHViOiBbaXNtYXljXShodHRwczovL2dpdGh1Yi5jb20vaXNtYXljKQoqIEFsYmVydCBZLiBLaW0gLSBBc3NudCBQcm9mLiBvZiBTdGF0aXN0aWNhbCAmIERhdGEgU2NpZW5jZXMsIFNtaXRoIENvbGxlZ2UKICAgICsgVHdpdHRlcjogW1xAcnVkZWJveWJlcnRdKGh0dHBzOi8vdHdpdHRlci5jb20vcnVkZWJveWJlcnQpCiAgICArIEdpdEh1YjogW3J1ZGVib3liZXJ0XShodHRwczovL2dpdGh1Yi5jb20vcnVkZWJveWJlcnQpCgoKCiMjIFJlc291cmNlcwoKKiBTbGlkZXMgYXQgW2JpdC5seS91c2VyX2Jvc3Rvbl0oaHR0cDovL2JpdC5seS91c2VyX2Jvc3RvbikKKiBSZWxlYXNlIHZlcnNpb24gb2YgdGV4dGJvb2sgYXQgW21vZGVybmRpdmUuY29tXShodHRwOi8vbW9kZXJuZGl2ZS5jb20vKSBhbmQgZGV2ZWxvcG1lbnQgdmVyc2lvbiBhdCBbbW9kZXJuZGl2ZS5uZXRsaWZ5LmNvbV0oaHR0cDovL21vZGVybmRpdmUubmV0bGlmeS5jb20vKSAoc291cmNlIG9mIHRvZGF5J3MgZXhhbXBsZXMpCiogUlN0dWRpbyBbYGJvb2tkb3duYF0oaHR0cHM6Ly9ib29rZG93bi5vcmcveWlodWkvYm9va2Rvd24vKSBwYWNrYWdlIHNvdXJjZSBjb2RlIG9uIEdpdEh1YiBhdCBbZ2l0aHViLmNvbS9tb2Rlcm5kaXZlL10oaHR0cHM6Ly9naXRodWIuY29tL21vZGVybmRpdmUvKQoqIGBpbmZlcmAgcGFja2FnZSBob21lcGFnZTogPGh0dHBzOi8vaW5mZXIubmV0bGlmeS5jb20vPgoK