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 Venn Diagrams…

Drew Conway Drew Conway 2.0
Drawing Drawing

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

Drawing


A few pedagogical principles

  1. Have intro students “play the whole game”
  2. Use data science, not probability/mathematical formulas, to motivate statistical inference
  3. 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:

Drawing

Tee-ball

Think how children learn “tee-ball” and play a simplified version of the “whole game” first…

Drawing

Softball & baseball

… and then eventually graduate to softball/baseball.

Drawing Drawing

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:
    1. \(x_1\): size (sqft_living square feet)
    2. \(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()
id date price sqft_living condition
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)
term estimate std_error statistic p_value conf_low conf_high
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:

  1. What’s the difference between R & RStudio? What’s an R package?
  2. How do effectively visualize data?
  3. How can I clean data as it “exists in the wild”?
  4. How do I model the relationship between variables?
  5. What is the error/uncertainty of our results?

Means to the end

  1. Analogies: R vs RStudio and R packages
  2. Visualization via ggplot2: Grammar of Graphics and limit scope to “Five Named Graphs”
  3. dplyr “Five Main Verbs” for data wrangling/transformation
  4. Descriptive regression modeling with emphasis on exploratory data analysis (See Figure 7.4)
  5. How do we teach ideas of representative sampling, sampling distributions, and standard errors? A work in progress…

Principle 2: Inference via data science

Simulations not probability/formulas

More of this Less of this
Drawing Drawing

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

  1. Need to do tactile simulations first; too many layers of abstraction otherwise
  2. Draw link between tactile (actual bowl and shovel) and virtual (data frames and functions in R) then
  3. To perform and deconstruct latter, students need to be equipped with a data science toolbox: data visualization and basic data wrangling.
  4. 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

Drawing

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.

Drawing

Thanks!

Chester Ismay Albert Y. Kim
Drawing Drawing

Resources

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