## Warning: package 'tidyverse' was built under R version 4.0.3
## Warning: package 'openintro' was built under R version 4.0.3
## Warning: package 'airports' was built under R version 4.0.3
## Warning: package 'cherryblossom' was built under R version 4.0.3
## Warning: package 'usdata' was built under R version 4.0.3
data("fastfood", package = 'openintro')
view(fastfood)
#filtering restaraunt information via name
mcdonalds <- fastfood %>%
filter(restaurant == "Mcdonalds")
mcdonalds
## # A tibble: 57 x 17
## restaurant item calories cal_fat total_fat sat_fat trans_fat cholesterol
## <chr> <chr> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 Mcdonalds Arti~ 380 60 7 2 0 95
## 2 Mcdonalds Sing~ 840 410 45 17 1.5 130
## 3 Mcdonalds Doub~ 1130 600 67 27 3 220
## 4 Mcdonalds Gril~ 750 280 31 10 0.5 155
## 5 Mcdonalds Cris~ 920 410 45 12 0.5 120
## 6 Mcdonalds Big ~ 540 250 28 10 1 80
## 7 Mcdonalds Chee~ 300 100 12 5 0.5 40
## 8 Mcdonalds Clas~ 510 210 24 4 0 65
## 9 Mcdonalds Doub~ 430 190 21 11 1 85
## 10 Mcdonalds Doub~ 770 400 45 21 2.5 175
## # ... with 47 more rows, and 9 more variables: sodium <dbl>, total_carb <dbl>,
## # fiber <dbl>, sugar <dbl>, protein <dbl>, vit_a <dbl>, vit_c <dbl>,
## # calcium <dbl>, salad <chr>
#filtering restaraunt information via name
dairy_queen <- fastfood %>%
filter(restaurant == "Dairy Queen")
dairy_queen
## # A tibble: 42 x 17
## restaurant item calories cal_fat total_fat sat_fat trans_fat cholesterol
## <chr> <chr> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 Dairy Que~ 1/2 ~ 1000 660 74 26 2 170
## 2 Dairy Que~ 1/2 ~ 800 460 51 20 2 135
## 3 Dairy Que~ 1/4 ~ 630 330 37 13 1 95
## 4 Dairy Que~ 1/4 ~ 540 270 30 11 1 70
## 5 Dairy Que~ 1/4 ~ 570 310 35 11 1 75
## 6 Dairy Que~ Orig~ 400 160 18 9 1 65
## 7 Dairy Que~ Orig~ 630 310 34 18 2 125
## 8 Dairy Que~ 4 Pi~ 1030 480 53 9 1 80
## 9 Dairy Que~ 6 Pi~ 1260 590 66 11 1 120
## 10 Dairy Que~ Baco~ 420 240 26 11 1 60
## # ... with 32 more rows, and 9 more variables: sodium <dbl>, total_carb <dbl>,
## # fiber <dbl>, sugar <dbl>, protein <dbl>, vit_a <dbl>, vit_c <dbl>,
## # calcium <dbl>, salad <chr>
Exercise 1
Make a plot (or plots) to visualize the distributions of the amount of calories from fat of the options from these two restaurants. How do their centers, shapes, and spreads compare?
x1 <- mcdonalds$cal_fat
x2 <- dairy_queen$cal_fat
summary(x1)
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## 50.0 160.0 240.0 285.6 320.0 1270.0
‘Graphing citation: https://www.r-bloggers.com/2012/10/adding-measures-of-central-tendency-to-histograms-in-r/’
# McDonalds fat calories
hist(x1,
col = "peachpuff",
border = "black",
prob = TRUE, # show densities instead of frequencies
xlab = "calories",
main = "McDonalds' Fat Calories",
lwd = 2)

hist(x2,
col = "peachpuff",
border = "black",
prob = TRUE, # show densities instead of frequencies
xlab = "calories",
main = "Dairy Queen Fat Calories",
lwd = 2)

Answer to question 1:
These datum have different distributions. While they both tend to skew right, the McDonald’s plot does so more extremely, while the skewness of the DQ plot favors the center.
dqmean <- mean(dairy_queen$cal_fat)
dqstd <- sd(dairy_queen$cal_fat)
mcd_mean <- mean(mcdonalds$cal_fat)
mcd_std <- mean(mcdonalds$cal_fat)
library(ggplot2)
ggplot(data = dairy_queen, aes(x = cal_fat)) +
geom_blank() +
geom_histogram(aes(y = ..density..)) +
stat_function(fun = dnorm, args = c(mean = dqmean, sd = dqstd), col = "green")
## `stat_bin()` using `bins = 30`. Pick better value with `binwidth`.

Exercise 2
Based on the this plot, does it appear that the data follow a nearly normal distribution? > Yes, it appears this data somewhat follows a normal distribution.
Evaluating the normal distribution
Below is a QQ plot
ggplot(data = dairy_queen, aes(sample = cal_fat)) +
geom_line(stat = "qq")

sim_norm <- rnorm(n = nrow(dairy_queen), mean = dqmean, sd = dqstd)
sim_norm
## [1] 114.66729 310.09268 442.56909 315.06549 410.65596 93.80603
## [7] 440.62706 158.72589 402.10043 119.03274 133.98377 366.53149
## [13] -232.67158 357.12501 469.09034 518.72800 88.60428 398.60715
## [19] 461.07955 132.71959 323.28978 230.70975 395.67408 100.60892
## [25] 107.51827 176.23780 210.17885 77.04213 377.37179 64.41452
## [31] 34.55038 382.11210 317.46534 240.50662 541.01741 226.84458
## [37] 349.16764 127.70771 386.70136 254.74305 405.38533 432.58581
Exercise 3
Make a normal probability plot of sim_norm. Do all of the points fall on the line? How does this plot compare to the probability plot for the real data? (Since sim_norm is not a data frame, it can be put directly into the sample argument and the data argument can be dropped.) > Not all the points of this normal plot fall onto the line, although most do. It has a similar shape to the plot of the real data, but it is not exact.
qqnorm(sim_norm,
ylab = "Sample",
xlab = "Theoretical",
main = "DQ Calories from fat",)
qqline(sim_norm)
8 plotted simulations of the normal data
qqnormsim(sample = cal_fat, data = dairy_queen)

Exercise 4
Does the normal probability plot for the calories from fat look similar to the plots created for the simulated data? That is, do the plots provide evidence that the female heights are nearly normal? > Yes, the normal plot for the fat calories does look similar to the simulated plots. Because we can observe a similar cluster of data in the middle amongst all 9 plots, it is safe to say the data is nearly normal distributed.
Exercise 5
Using the same technique, determine whether or not the calories from McDonald’s menu appear to come from a normal distribution. > Yes, based on the simulation data, we can arrive at the same conclusions mentioned in the previous question regarding Mcdonalds’ calories from fat.
sim_norm2 <- rnorm(n = nrow(mcdonalds), mean = dqmean, sd = dqstd)
qqnorm(sim_norm2,
ylab = "Sample",
xlab = "Theoretical",
main = "Mcdonald's Calories from fat",)
qqline(sim_norm2)

qqnormsim(sample = cal_fat, data = mcdonalds)

# compliment
compliment <- 1 - pnorm(q=600, mean = dqmean, sd = dqstd)
compliment
## [1] 0.01501523
# Theoretical probability
dairy_queen %>%
filter(cal_fat > 600) %>%
summarise(percent = n() / nrow(dairy_queen))
## # A tibble: 1 x 1
## percent
## <dbl>
## 1 0.0476
Exercise 6
Write out two probability questions that you would like to answer about any of the restaurants in this dataset. Calculate those probabilities using both the theoretical normal distribution as well as the empirical distribution (four probabilities in all). Which one had a closer agreement between the two methods? > What is the probability fat from calories is greater than 350 from McDonalds’ menu? What about being greater than 900 from DQ’s menu? > Findings: After performing the calculations below, we can see there is a considerably closer agreement for DQ menu items being greater than 900.
# Empirical
E1 <- 1 - pnorm(q = 350, mean = mcd_mean, sd = mcd_std)
E1
## [1] 0.4108224
# Theoretical
T1 <- mcdonalds %>%
filter(cal_fat > 350) %>%
summarise(percent = n() / nrow(mcdonalds))
T1
## # A tibble: 1 x 1
## percent
## <dbl>
## 1 0.211
# Difference
diff1 <- abs(E1 - T1)
diff1
## percent
## 1 0.2002961
Question II:: > What is the probability fat from calories is greater than than 900 from Dairy Queen’s menu?
# Empirical
E2 <- 1 - pnorm(q = 900, mean = dqmean, sd = dqstd)
E2
## [1] 2.186778e-05
# Theoretical
T2 <- dairy_queen %>%
filter(cal_fat > 900) %>%
summarise(percent = n() / nrow(dairy_queen))
T2
## # A tibble: 1 x 1
## percent
## <dbl>
## 1 0
# Difference
diff2 <- abs(E2 - T2)
diff2
## percent
## 1 2.186778e-05
dq <- data.frame(item = c(dairy_queen$item),
fat_calories = c(dairy_queen$cal_fat))
dq <- dq[order(dq$item),]
view(dq)
mcd <- data.frame(item = c(mcdonalds$item),
fat_calories = c(mcdonalds$cal_fat))
mcd <- mcd[order(mcd$item),]
view(mcd)
Exercise 6:
Now let’s consider some of the other variables in the dataset. Out of all the different restaurants, which ones’ distribution is the closest to normal for sodium? > Arby’s data is closest to the normal distribution
# Normal plot sodium Chick Fil A
chick_fil_a <- fastfood %>%
filter(restaurant == "Chick Fil-A")
view(chick_fil_a)
Chick_fil_sodi <- chick_fil_a$sodium
Chick_sodi_mean <- mean(chick_fil_a$sodium)
Chick_sodi_std <- sd(chick_fil_a$sodium)
ggplot(data = chick_fil_a, aes(sample = Chick_fil_sodi)) +
geom_line(stat = "qq")

# Normal plot histogram Chick Fil A
ggplot(data = chick_fil_a, aes(x = Chick_fil_sodi)) +
geom_blank() +
geom_histogram(aes(y = ..density..)) +
stat_function(fun = dnorm, args = c(mean = Chick_sodi_mean, sd = Chick_sodi_std), col = "red")
## `stat_bin()` using `bins = 30`. Pick better value with `binwidth`.

# Normal plot sodium Sonic
sonic <- fastfood %>%
filter(restaurant == "Sonic")
Sonic_sodi <- sonic$sodium
Sonic_sodi_mean <- mean(sonic$sodium)
Sonic_sodi_std <- sd(sonic$sodium)
ggplot(data = sonic, aes(sample = Sonic_sodi)) +
geom_line(stat = "qq")

# Normal plot histogram Sonic
ggplot(data = sonic, aes(x = Sonic_sodi)) +
geom_blank() +
geom_histogram(aes(y = ..density..)) +
stat_function(fun = dnorm, args = c(mean = Sonic_sodi_mean, sd = Sonic_sodi_std), col = "blue")
## `stat_bin()` using `bins = 30`. Pick better value with `binwidth`.

# Normal plot sodium Arbys
arbys <- fastfood %>%
filter(restaurant == "Arbys")
arbys_sodi <- arbys$sodium
arbys_sodi_mean <- mean(arbys$sodium)
arbys_sodi_std <- sd(arbys$sodium)
ggplot(data = arbys, aes(sample = arbys_sodi)) +
geom_line(stat = "qq")

# Normal plot histogram ARBYS
ggplot(data = arbys, aes(x = arbys_sodi)) +
geom_blank() +
geom_histogram(aes(y = ..density..)) +
stat_function(fun = dnorm, args = c(mean = arbys_sodi_mean, sd = arbys_sodi_std), col = "green")
## `stat_bin()` using `bins = 30`. Pick better value with `binwidth`.

# Normal plot sodium BK
burger_king <- fastfood %>%
filter(restaurant == "Burger King ")
burger_king_sodi <- burger_king$sodium
burger_king_sodi_mean <- mean(burger_king$sodium)
burger_king_sodi_std <- sd(burger_king$sodium)
ggplot(data = burger_king, aes(sample = burger_king_sodi)) +
geom_line(stat = "qq")

# # Normal plot sodium histogram BK
# ggplot(data = burger_king, aes(x = burger_king_sodi)) +
# geom_blank() +
# geom_histogram(aes(y = ..density..)) +
# stat_function(fun = dnorm, args = c(mean = burger_king_sodi_mean, sd = burger_king_sodi_std), col = "white")
# Normal plot SUBWAY
subway <- fastfood %>%
filter(restaurant == "Subway")
subway_sodi <- subway$sodium
subway_sodi_mean <- mean(subway$sodium)
subway_sodi_std <- sd(subway_sodi)
ggplot(data = subway, aes(sample = subway_sodi)) +
geom_line(stat = "qq")

# Normal plot histogram SUBWAY
ggplot(data = subway, aes(x = subway_sodi)) +
geom_blank() +
geom_histogram(aes(y = ..density..)) +
stat_function(fun = dnorm, args = c(mean = subway_sodi_mean, sd = subway_sodi_std), col = "purple")
## `stat_bin()` using `bins = 30`. Pick better value with `binwidth`.

# Normal distribution of sodium: TACO BELL
tbell <- fastfood %>%
filter(restaurant == "Taco Bell")
tbell_sodi <- tbell$sodium
tbell_sodi_mean <- mean(tbell$sodium)
tbell_sodi_std <- sd(tbell_sodi)
ggplot(data = tbell, aes(sample = tbell_sodi)) +
geom_line(stat = "qq")

# Normal plot histogram TACO BELL
ggplot(data = tbell, aes(x = tbell_sodi)) +
geom_blank() +
geom_histogram(aes(y = ..density..)) +
stat_function(fun = dnorm, args = c(mean = tbell_sodi_mean, sd = tbell_sodi_std), col = "blue")
## `stat_bin()` using `bins = 30`. Pick better value with `binwidth`.

# Normal distribution for sodium DAIRY QUEEN
dq_sodi <- dairy_queen$sodium
dq_sodi_mean <- mean(dairy_queen$sodium)
dq_sodi_std <- sd(dairy_queen$sodium)
ggplot(data = dairy_queen, aes(sample = dq_sodi)) +
geom_line(stat = "qq")

# Normal plot hihstogram DAIRY QUEEN
ggplot(data = dairy_queen, aes(x = dq_sodi)) +
geom_blank() +
geom_histogram(aes(y = ..density..)) +
stat_function(fun = dnorm, args = c(mean = dq_sodi_mean, sd = dq_sodi_std), col = "tomato")
## `stat_bin()` using `bins = 30`. Pick better value with `binwidth`.

# Normal distribution for sodium McDonalds
Mcdon_sodi <- mcdonalds$sodium
Mcdon_sodi_mean <- mean(mcdonalds$sodium)
Mcdon_sodi_std <- sd(mcdonalds$sodium)
ggplot(data = mcdonalds, aes(sample = Mcdon_sodi)) +
geom_line(stat = "qq")

# Normal plot histogram Mcdonalds
ggplot(data = mcdonalds, aes(x = Mcdon_sodi)) +
geom_blank() +
geom_histogram(aes(y = ..density..)) +
stat_function(fun = dnorm, args = c(mean = Mcdon_sodi_mean, sd = Mcdon_sodi_std), col = "green")
## `stat_bin()` using `bins = 30`. Pick better value with `binwidth`.

Exercise 8
Note that some of the normal probability plots for sodium distributions seem to have a stepwise pattern. why do you think this might be the case? > I think this is because variations of items may have similar amounts of sodium. For instance, it is likely that the many variations of chicken sandwhiches that chick fil a offers have similar amounts of sodium to each other.
Exercise 9
As you can see, normal probability plots can be used both to assess normality and visualize skewness. Make a normal probability plot for the total carbohydrates from a restaurant of your choice. Based on this normal probability plot, is this variable left skewed, symmetric, or right skewed? Use a histogram to confirm your findings. > From the plots below, we can conclude this variable is right skewed.
# Normal distribution for carbohydrates McDonalds
Mcdon_carbo <- mcdonalds$total_carb
Mcdon_carbo_mean <- mean(mcdonalds$total_carb)
Mcdon_carbo_std <- sd(mcdonalds$total_carb)
ggplot(data = mcdonalds, aes(sample = Mcdon_carbo)) +
geom_line(stat = "qq")

# Normal distribution carbs HISTOGRAM McDonalds
ggplot(data = mcdonalds, aes(x = Mcdon_carbo)) +
geom_blank() +
geom_histogram(aes(y = ..density..)) +
stat_function(fun = dnorm, args = c(mean = Mcdon_carbo_mean, sd = Mcdon_carbo_std), col = "hot pink")
## `stat_bin()` using `bins = 30`. Pick better value with `binwidth`.

LS0tDQp0aXRsZTogIkRhdGEgNjA2OiBMYWIgIzQiDQphdXRob3I6ICJKb2UgQ29ubm9sbHkiDQpkYXRlOiAiYHIgU3lzLkRhdGUoKWAiDQpvdXRwdXQ6IG9wZW5pbnRybzo6bGFiX3JlcG9ydA0KLS0tDQoNCmBgYHtyIGxvYWQtcGFja2FnZXMsIG1lc3NhZ2U9RkFMU0V9DQpsaWJyYXJ5KHRpZHl2ZXJzZSkNCmxpYnJhcnkob3BlbmludHJvKQ0KbGlicmFyeShnZ3Bsb3QyKQ0KYGBgDQoNCmBgYHtyfQ0KZGF0YSgiZmFzdGZvb2QiLCBwYWNrYWdlID0gJ29wZW5pbnRybycpDQp2aWV3KGZhc3Rmb29kKQ0KYGBgDQpgYGB7cn0NCiNmaWx0ZXJpbmcgcmVzdGFyYXVudCBpbmZvcm1hdGlvbiB2aWEgbmFtZQ0KbWNkb25hbGRzIDwtIGZhc3Rmb29kICU+JQ0KICBmaWx0ZXIocmVzdGF1cmFudCA9PSAiTWNkb25hbGRzIikNCm1jZG9uYWxkcw0KYGBgDQpgYGB7cn0NCiNmaWx0ZXJpbmcgcmVzdGFyYXVudCBpbmZvcm1hdGlvbiB2aWEgbmFtZQ0KZGFpcnlfcXVlZW4gPC0gZmFzdGZvb2QgJT4lDQogIGZpbHRlcihyZXN0YXVyYW50ID09ICJEYWlyeSBRdWVlbiIpDQpkYWlyeV9xdWVlbg0KDQpgYGANCg0KIyMjIEV4ZXJjaXNlIDENCg0KTWFrZSBhIHBsb3QgKG9yIHBsb3RzKSB0byB2aXN1YWxpemUgdGhlIGRpc3RyaWJ1dGlvbnMgb2YgdGhlIGFtb3VudCBvZiBjYWxvcmllcyBmcm9tIGZhdCBvZiB0aGUgb3B0aW9ucyBmcm9tIHRoZXNlIHR3byByZXN0YXVyYW50cy4gSG93IGRvIHRoZWlyIGNlbnRlcnMsIHNoYXBlcywgYW5kIHNwcmVhZHMgY29tcGFyZT8NCg0KYGBge3IgY29kZS1jaHVuay1sYWJlbH0NCngxIDwtIG1jZG9uYWxkcyRjYWxfZmF0DQp4MiA8LSBkYWlyeV9xdWVlbiRjYWxfZmF0DQoNCnN1bW1hcnkoeDEpDQpgYGANCidHcmFwaGluZyBjaXRhdGlvbjogaHR0cHM6Ly93d3cuci1ibG9nZ2Vycy5jb20vMjAxMi8xMC9hZGRpbmctbWVhc3VyZXMtb2YtY2VudHJhbC10ZW5kZW5jeS10by1oaXN0b2dyYW1zLWluLXIvJw0KDQoNCmBgYHtyfQ0KIyBNY0RvbmFsZHMgZmF0IGNhbG9yaWVzDQoNCmhpc3QoeDEsDQogICAgIGNvbCA9ICJwZWFjaHB1ZmYiLA0KICAgICBib3JkZXIgPSAiYmxhY2siLCANCiAgICAgcHJvYiA9IFRSVUUsICMgc2hvdyBkZW5zaXRpZXMgaW5zdGVhZCBvZiBmcmVxdWVuY2llcw0KICAgICB4bGFiID0gImNhbG9yaWVzIiwNCiAgICAgbWFpbiA9ICJNY0RvbmFsZHMnIEZhdCBDYWxvcmllcyIsDQogICAgIGx3ZCA9IDIpDQoNCiMgdGhpY2tuZXNzIG9mIGxpbg0KYGBgDQoNCmBgYHtyfQ0KaGlzdCh4MiwNCiAgICAgY29sID0gInBlYWNocHVmZiIsDQogICAgIGJvcmRlciA9ICJibGFjayIsIA0KICAgICBwcm9iID0gVFJVRSwgIyBzaG93IGRlbnNpdGllcyBpbnN0ZWFkIG9mIGZyZXF1ZW5jaWVzDQogICAgIHhsYWIgPSAiY2Fsb3JpZXMiLA0KICAgICBtYWluID0gIkRhaXJ5IFF1ZWVuIEZhdCBDYWxvcmllcyIsDQogICAgIGx3ZCA9IDIpDQpgYGANCg0KIyMjIEFuc3dlciB0byBxdWVzdGlvbiAxOg0KPiBUaGVzZSBkYXR1bSBoYXZlIGRpZmZlcmVudCBkaXN0cmlidXRpb25zLiBXaGlsZSB0aGV5IGJvdGggdGVuZCB0byBza2V3IHJpZ2h0LCB0aGUgTWNEb25hbGQncyBwbG90IGRvZXMgc28gbW9yZSBleHRyZW1lbHksIHdoaWxlIHRoZSBza2V3bmVzcyBvZiB0aGUgRFEgcGxvdCBmYXZvcnMgdGhlIGNlbnRlci4gDQoNCmBgYHtyfQ0KZHFtZWFuIDwtIG1lYW4oZGFpcnlfcXVlZW4kY2FsX2ZhdCkNCmRxc3RkIDwtIHNkKGRhaXJ5X3F1ZWVuJGNhbF9mYXQpDQpgYGANCg0KYGBge3J9DQptY2RfbWVhbiA8LSBtZWFuKG1jZG9uYWxkcyRjYWxfZmF0KQ0KbWNkX3N0ZCA8LSBtZWFuKG1jZG9uYWxkcyRjYWxfZmF0KQ0KYGBgDQoNCmBgYHtyfQ0KbGlicmFyeShnZ3Bsb3QyKQ0KZ2dwbG90KGRhdGEgPSBkYWlyeV9xdWVlbiwgYWVzKHggPSBjYWxfZmF0KSkgKw0KICAgICAgICBnZW9tX2JsYW5rKCkgKw0KICAgICAgICBnZW9tX2hpc3RvZ3JhbShhZXMoeSA9IC4uZGVuc2l0eS4uKSkgKw0KICAgICAgICBzdGF0X2Z1bmN0aW9uKGZ1biA9IGRub3JtLCBhcmdzID0gYyhtZWFuID0gZHFtZWFuLCBzZCA9IGRxc3RkKSwgY29sID0gImdyZWVuIikNCmBgYA0KDQojIyMgRXhlcmNpc2UgMg0KQmFzZWQgb24gdGhlIHRoaXMgcGxvdCwgZG9lcyBpdCBhcHBlYXIgdGhhdCB0aGUgZGF0YSBmb2xsb3cgYSBuZWFybHkgbm9ybWFsIGRpc3RyaWJ1dGlvbj8NCj4gWWVzLCBpdCBhcHBlYXJzIHRoaXMgZGF0YSBzb21ld2hhdCBmb2xsb3dzIGEgbm9ybWFsIGRpc3RyaWJ1dGlvbi4NCg0KIyMjIEV2YWx1YXRpbmcgdGhlIG5vcm1hbCBkaXN0cmlidXRpb24gDQojIEJlbG93IGlzIGEgUVEgcGxvdA0KYGBge3J9DQpnZ3Bsb3QoZGF0YSA9IGRhaXJ5X3F1ZWVuLCBhZXMoc2FtcGxlID0gY2FsX2ZhdCkpICsgDQogIGdlb21fbGluZShzdGF0ID0gInFxIikNCmBgYA0KDQpgYGB7cn0NCnNpbV9ub3JtIDwtIHJub3JtKG4gPSBucm93KGRhaXJ5X3F1ZWVuKSwgbWVhbiA9IGRxbWVhbiwgc2QgPSBkcXN0ZCkNCnNpbV9ub3JtDQpgYGANCg0KIyMjIEV4ZXJjaXNlIDMNCk1ha2UgYSBub3JtYWwgcHJvYmFiaWxpdHkgcGxvdCBvZiBzaW1fbm9ybS4gRG8gYWxsIG9mIHRoZSBwb2ludHMgZmFsbCBvbiB0aGUgbGluZT8gSG93IGRvZXMgdGhpcyBwbG90IGNvbXBhcmUgdG8gdGhlIHByb2JhYmlsaXR5IHBsb3QgZm9yIHRoZSByZWFsIGRhdGE/IChTaW5jZSBzaW1fbm9ybSBpcyBub3QgYSBkYXRhIGZyYW1lLCBpdCBjYW4gYmUgcHV0IGRpcmVjdGx5IGludG8gdGhlIHNhbXBsZSBhcmd1bWVudCBhbmQgdGhlIGRhdGEgYXJndW1lbnQgY2FuIGJlIGRyb3BwZWQuKQ0KPiBOb3QgYWxsIHRoZSBwb2ludHMgb2YgdGhpcyBub3JtYWwgcGxvdCBmYWxsIG9udG8gdGhlIGxpbmUsIGFsdGhvdWdoIG1vc3QgZG8uIEl0IGhhcyBhIHNpbWlsYXIgc2hhcGUgdG8gdGhlIHBsb3Qgb2YgdGhlIHJlYWwgZGF0YSwgYnV0IGl0IGlzIG5vdCBleGFjdC4NCg0KYGBge3J9DQpxcW5vcm0oc2ltX25vcm0sDQogICAgICAgeWxhYiA9ICJTYW1wbGUiLA0KICAgICAgIHhsYWIgPSAiVGhlb3JldGljYWwiLA0KICAgICAgIG1haW4gPSAiRFEgQ2Fsb3JpZXMgZnJvbSBmYXQiLCkNCnFxbGluZShzaW1fbm9ybSkNCmBgYA0KOCBwbG90dGVkIHNpbXVsYXRpb25zIG9mIHRoZSBub3JtYWwgZGF0YQ0KYGBge3J9DQpxcW5vcm1zaW0oc2FtcGxlID0gY2FsX2ZhdCwgZGF0YSA9IGRhaXJ5X3F1ZWVuKQ0KYGBgDQoNCiMjIyBFeGVyY2lzZSA0DQpEb2VzIHRoZSBub3JtYWwgcHJvYmFiaWxpdHkgcGxvdCBmb3IgdGhlIGNhbG9yaWVzIGZyb20gZmF0IGxvb2sgc2ltaWxhciB0byB0aGUgcGxvdHMgY3JlYXRlZCBmb3IgdGhlIHNpbXVsYXRlZCBkYXRhPyBUaGF0IGlzLCBkbyB0aGUgcGxvdHMgcHJvdmlkZSBldmlkZW5jZSB0aGF0IHRoZSBmZW1hbGUgaGVpZ2h0cyBhcmUgbmVhcmx5IG5vcm1hbD8NCj4gWWVzLCB0aGUgbm9ybWFsIHBsb3QgZm9yIHRoZSBmYXQgY2Fsb3JpZXMgZG9lcyBsb29rIHNpbWlsYXIgdG8gdGhlIHNpbXVsYXRlZCBwbG90cy4gQmVjYXVzZSB3ZSBjYW4gb2JzZXJ2ZSBhIHNpbWlsYXIgY2x1c3RlciBvZiBkYXRhIGluIHRoZSBtaWRkbGUgYW1vbmdzdCBhbGwgOSBwbG90cywgaXQgaXMgc2FmZSB0byBzYXkgdGhlIGRhdGEgaXMgbmVhcmx5IG5vcm1hbCBkaXN0cmlidXRlZC4gDQoNCg0KIyMjIEV4ZXJjaXNlIDUNClVzaW5nIHRoZSBzYW1lIHRlY2huaXF1ZSwgZGV0ZXJtaW5lIHdoZXRoZXIgb3Igbm90IHRoZSBjYWxvcmllcyBmcm9tIE1jRG9uYWxk4oCZcyBtZW51IGFwcGVhciB0byBjb21lIGZyb20gYSBub3JtYWwgZGlzdHJpYnV0aW9uLg0KPiBZZXMsIGJhc2VkIG9uIHRoZSBzaW11bGF0aW9uIGRhdGEsIHdlIGNhbiBhcnJpdmUgYXQgdGhlIHNhbWUgY29uY2x1c2lvbnMgbWVudGlvbmVkIGluIHRoZSBwcmV2aW91cyBxdWVzdGlvbiByZWdhcmRpbmcgTWNkb25hbGRzJyBjYWxvcmllcyBmcm9tIGZhdC4NCg0KYGBge3J9DQpzaW1fbm9ybTIgPC0gcm5vcm0obiA9IG5yb3cobWNkb25hbGRzKSwgbWVhbiA9IGRxbWVhbiwgc2QgPSBkcXN0ZCkNCg0KcXFub3JtKHNpbV9ub3JtMiwNCiAgICAgICB5bGFiID0gIlNhbXBsZSIsDQogICAgICAgeGxhYiA9ICJUaGVvcmV0aWNhbCIsDQogICAgICAgbWFpbiA9ICJNY2RvbmFsZCdzIENhbG9yaWVzIGZyb20gZmF0IiwpDQpxcWxpbmUoc2ltX25vcm0yKQ0KDQpgYGANCg0KYGBge3J9DQpxcW5vcm1zaW0oc2FtcGxlID0gY2FsX2ZhdCwgZGF0YSA9IG1jZG9uYWxkcykNCmBgYA0KDQpgYGB7cn0NCiMgY29tcGxpbWVudA0KY29tcGxpbWVudCA8LSAxIC0gcG5vcm0ocT02MDAsIG1lYW4gPSBkcW1lYW4sIHNkID0gZHFzdGQpDQpjb21wbGltZW50DQoNCmBgYA0KDQpgYGB7cn0NCiMgVGhlb3JldGljYWwgcHJvYmFiaWxpdHkNCmRhaXJ5X3F1ZWVuICU+JQ0KICBmaWx0ZXIoY2FsX2ZhdCA+IDYwMCkgJT4lDQogIHN1bW1hcmlzZShwZXJjZW50ID0gbigpIC8gbnJvdyhkYWlyeV9xdWVlbikpDQoNCmBgYA0KDQojIyMgRXhlcmNpc2UgNg0KV3JpdGUgb3V0IHR3byBwcm9iYWJpbGl0eSBxdWVzdGlvbnMgdGhhdCB5b3Ugd291bGQgbGlrZSB0byBhbnN3ZXIgYWJvdXQgYW55IG9mIHRoZSByZXN0YXVyYW50cyBpbiB0aGlzIGRhdGFzZXQuIENhbGN1bGF0ZSB0aG9zZSBwcm9iYWJpbGl0aWVzIHVzaW5nIGJvdGggdGhlIHRoZW9yZXRpY2FsIG5vcm1hbCBkaXN0cmlidXRpb24gYXMgd2VsbCBhcyB0aGUgZW1waXJpY2FsIGRpc3RyaWJ1dGlvbiAoZm91ciBwcm9iYWJpbGl0aWVzIGluIGFsbCkuIFdoaWNoIG9uZSBoYWQgYSBjbG9zZXIgYWdyZWVtZW50IGJldHdlZW4gdGhlIHR3byBtZXRob2RzPw0KPiBXaGF0IGlzIHRoZSBwcm9iYWJpbGl0eSBmYXQgZnJvbSBjYWxvcmllcyBpcyBncmVhdGVyIHRoYW4gMzUwIGZyb20gTWNEb25hbGRzJyBtZW51PyBXaGF0IGFib3V0IGJlaW5nIGdyZWF0ZXIgdGhhbiA5MDAgZnJvbSBEUSdzIG1lbnU/DQo+IEZpbmRpbmdzOiBBZnRlciBwZXJmb3JtaW5nIHRoZSBjYWxjdWxhdGlvbnMgYmVsb3csIHdlIGNhbiBzZWUgdGhlcmUgaXMgYSBjb25zaWRlcmFibHkgY2xvc2VyIGFncmVlbWVudCBmb3IgRFEgbWVudSBpdGVtcyBiZWluZyBncmVhdGVyIHRoYW4gOTAwLg0KDQpgYGB7cn0NCiMgRW1waXJpY2FsDQpFMSA8LSAxIC0gcG5vcm0ocSA9IDM1MCwgbWVhbiA9IG1jZF9tZWFuLCBzZCA9IG1jZF9zdGQpDQpFMQ0KYGBgDQpgYGB7cn0NCiMgVGhlb3JldGljYWwNClQxIDwtIG1jZG9uYWxkcyAlPiUNCiAgZmlsdGVyKGNhbF9mYXQgPiAzNTApICU+JQ0KICBzdW1tYXJpc2UocGVyY2VudCA9IG4oKSAvIG5yb3cobWNkb25hbGRzKSkNClQxDQpgYGANCmBgYHtyfQ0KIyBEaWZmZXJlbmNlDQpkaWZmMSA8LSBhYnMoRTEgLSBUMSkNCmRpZmYxDQoNCmBgYA0KUXVlc3Rpb24gSUk6Og0KPiBXaGF0IGlzIHRoZSBwcm9iYWJpbGl0eSBmYXQgZnJvbSBjYWxvcmllcyBpcyBncmVhdGVyIHRoYW4gdGhhbiA5MDAgZnJvbSBEYWlyeSBRdWVlbidzIG1lbnU/DQoNCmBgYHtyfQ0KIyBFbXBpcmljYWwNCkUyIDwtIDEgLSBwbm9ybShxID0gOTAwLCBtZWFuID0gZHFtZWFuLCBzZCA9IGRxc3RkKQ0KRTINCmBgYA0KYGBge3J9DQojIFRoZW9yZXRpY2FsDQoNClQyIDwtIGRhaXJ5X3F1ZWVuICU+JQ0KICBmaWx0ZXIoY2FsX2ZhdCA+IDkwMCkgJT4lDQogIHN1bW1hcmlzZShwZXJjZW50ID0gbigpIC8gbnJvdyhkYWlyeV9xdWVlbikpDQpUMg0KYGBgDQoNCmBgYHtyfQ0KIyBEaWZmZXJlbmNlDQpkaWZmMiA8LSBhYnMoRTIgLSBUMikNCmRpZmYyDQpgYGANCg0KYGBge3J9DQpkcSA8LSBkYXRhLmZyYW1lKGl0ZW0gPSBjKGRhaXJ5X3F1ZWVuJGl0ZW0pLA0KICAgICAgICAgICAgICAgICBmYXRfY2Fsb3JpZXMgPSBjKGRhaXJ5X3F1ZWVuJGNhbF9mYXQpKQ0KZHEgPC0gZHFbb3JkZXIoZHEkaXRlbSksXQ0KdmlldyhkcSkNCg0KbWNkIDwtIGRhdGEuZnJhbWUoaXRlbSA9IGMobWNkb25hbGRzJGl0ZW0pLA0KICAgICAgICAgICAgICAgICBmYXRfY2Fsb3JpZXMgPSBjKG1jZG9uYWxkcyRjYWxfZmF0KSkNCm1jZCA8LSBtY2Rbb3JkZXIobWNkJGl0ZW0pLF0NCnZpZXcobWNkKQ0KYGBgDQoNCiMjIyBFeGVyY2lzZSA2Og0KTm93IGxldOKAmXMgY29uc2lkZXIgc29tZSBvZiB0aGUgb3RoZXIgdmFyaWFibGVzIGluIHRoZSBkYXRhc2V0LiBPdXQgb2YgYWxsIHRoZSBkaWZmZXJlbnQgcmVzdGF1cmFudHMsIHdoaWNoIG9uZXPigJkgZGlzdHJpYnV0aW9uIGlzIHRoZSBjbG9zZXN0IHRvIG5vcm1hbCBmb3Igc29kaXVtPw0KPiBBcmJ5J3MgZGF0YSBpcyBjbG9zZXN0IHRvIHRoZSBub3JtYWwgZGlzdHJpYnV0aW9uDQoNCmBgYHtyfQ0KIyBOb3JtYWwgcGxvdCBzb2RpdW0gQ2hpY2sgRmlsIEEgDQoNCmNoaWNrX2ZpbF9hIDwtIGZhc3Rmb29kICU+JQ0KICBmaWx0ZXIocmVzdGF1cmFudCA9PSAiQ2hpY2sgRmlsLUEiKQ0KdmlldyhjaGlja19maWxfYSkNCkNoaWNrX2ZpbF9zb2RpIDwtIGNoaWNrX2ZpbF9hJHNvZGl1bQ0KQ2hpY2tfc29kaV9tZWFuIDwtIG1lYW4oY2hpY2tfZmlsX2Ekc29kaXVtKQ0KQ2hpY2tfc29kaV9zdGQgPC0gc2QoY2hpY2tfZmlsX2Ekc29kaXVtKQ0KDQpnZ3Bsb3QoZGF0YSA9IGNoaWNrX2ZpbF9hLCBhZXMoc2FtcGxlID0gQ2hpY2tfZmlsX3NvZGkpKSArIA0KICBnZW9tX2xpbmUoc3RhdCA9ICJxcSIpDQpgYGANCmBgYHtyfQ0KIyBOb3JtYWwgcGxvdCBoaXN0b2dyYW0gQ2hpY2sgRmlsIEENCmdncGxvdChkYXRhID0gY2hpY2tfZmlsX2EsIGFlcyh4ID0gQ2hpY2tfZmlsX3NvZGkpKSArDQogICAgICAgIGdlb21fYmxhbmsoKSArDQogICAgICAgIGdlb21faGlzdG9ncmFtKGFlcyh5ID0gLi5kZW5zaXR5Li4pKSArDQogICAgICAgIHN0YXRfZnVuY3Rpb24oZnVuID0gZG5vcm0sIGFyZ3MgPSBjKG1lYW4gPSBDaGlja19zb2RpX21lYW4sIHNkID0gQ2hpY2tfc29kaV9zdGQpLCBjb2wgPSAicmVkIikNCmBgYA0KDQpgYGB7cn0NCiMgTm9ybWFsIHBsb3Qgc29kaXVtIFNvbmljDQpzb25pYyA8LSBmYXN0Zm9vZCAlPiUNCiAgZmlsdGVyKHJlc3RhdXJhbnQgPT0gIlNvbmljIikNClNvbmljX3NvZGkgPC0gc29uaWMkc29kaXVtDQpTb25pY19zb2RpX21lYW4gPC0gbWVhbihzb25pYyRzb2RpdW0pDQpTb25pY19zb2RpX3N0ZCA8LSBzZChzb25pYyRzb2RpdW0pDQoNCmdncGxvdChkYXRhID0gc29uaWMsIGFlcyhzYW1wbGUgPSBTb25pY19zb2RpKSkgKyANCiAgZ2VvbV9saW5lKHN0YXQgPSAicXEiKQ0KYGBgDQpgYGB7cn0NCiMgTm9ybWFsIHBsb3QgaGlzdG9ncmFtIFNvbmljDQpnZ3Bsb3QoZGF0YSA9IHNvbmljLCBhZXMoeCA9IFNvbmljX3NvZGkpKSArDQogICAgICAgIGdlb21fYmxhbmsoKSArDQogICAgICAgIGdlb21faGlzdG9ncmFtKGFlcyh5ID0gLi5kZW5zaXR5Li4pKSArDQogICAgICAgIHN0YXRfZnVuY3Rpb24oZnVuID0gZG5vcm0sIGFyZ3MgPSBjKG1lYW4gPSBTb25pY19zb2RpX21lYW4sIHNkID0gU29uaWNfc29kaV9zdGQpLCBjb2wgPSAiYmx1ZSIpDQoNCmBgYA0KDQpgYGB7cn0NCiMgTm9ybWFsIHBsb3Qgc29kaXVtIEFyYnlzDQphcmJ5cyA8LSBmYXN0Zm9vZCAlPiUNCiAgZmlsdGVyKHJlc3RhdXJhbnQgPT0gIkFyYnlzIikNCmFyYnlzX3NvZGkgPC0gYXJieXMkc29kaXVtDQphcmJ5c19zb2RpX21lYW4gPC0gbWVhbihhcmJ5cyRzb2RpdW0pDQphcmJ5c19zb2RpX3N0ZCA8LSBzZChhcmJ5cyRzb2RpdW0pDQoNCmdncGxvdChkYXRhID0gYXJieXMsIGFlcyhzYW1wbGUgPSBhcmJ5c19zb2RpKSkgKyANCiAgZ2VvbV9saW5lKHN0YXQgPSAicXEiKQ0KYGBgDQpgYGB7cn0NCiMgTm9ybWFsIHBsb3QgaGlzdG9ncmFtIEFSQllTDQpnZ3Bsb3QoZGF0YSA9IGFyYnlzLCBhZXMoeCA9IGFyYnlzX3NvZGkpKSArDQogICAgICAgIGdlb21fYmxhbmsoKSArDQogICAgICAgIGdlb21faGlzdG9ncmFtKGFlcyh5ID0gLi5kZW5zaXR5Li4pKSArDQogICAgICAgIHN0YXRfZnVuY3Rpb24oZnVuID0gZG5vcm0sIGFyZ3MgPSBjKG1lYW4gPSBhcmJ5c19zb2RpX21lYW4sIHNkID0gYXJieXNfc29kaV9zdGQpLCBjb2wgPSAiZ3JlZW4iKQ0KYGBgDQoNCg0KYGBge3J9DQojIE5vcm1hbCBwbG90IHNvZGl1bSBCSw0KYnVyZ2VyX2tpbmcgPC0gZmFzdGZvb2QgJT4lDQogIGZpbHRlcihyZXN0YXVyYW50ID09ICJCdXJnZXIgS2luZwkiKQ0KYnVyZ2VyX2tpbmdfc29kaSA8LSBidXJnZXJfa2luZyRzb2RpdW0NCmJ1cmdlcl9raW5nX3NvZGlfbWVhbiA8LSBtZWFuKGJ1cmdlcl9raW5nJHNvZGl1bSkNCmJ1cmdlcl9raW5nX3NvZGlfc3RkIDwtIHNkKGJ1cmdlcl9raW5nJHNvZGl1bSkNCg0KZ2dwbG90KGRhdGEgPSBidXJnZXJfa2luZywgYWVzKHNhbXBsZSA9IGJ1cmdlcl9raW5nX3NvZGkpKSArIA0KICBnZW9tX2xpbmUoc3RhdCA9ICJxcSIpDQpgYGANCg0KYGBge3J9DQojICMgTm9ybWFsIHBsb3Qgc29kaXVtIGhpc3RvZ3JhbSBCSw0KIyBnZ3Bsb3QoZGF0YSA9IGJ1cmdlcl9raW5nLCBhZXMoeCA9IGJ1cmdlcl9raW5nX3NvZGkpKSArDQojICAgICAgICAgZ2VvbV9ibGFuaygpICsNCiMgICAgICAgICBnZW9tX2hpc3RvZ3JhbShhZXMoeSA9IC4uZGVuc2l0eS4uKSkgKw0KIyAgICAgICAgIHN0YXRfZnVuY3Rpb24oZnVuID0gZG5vcm0sIGFyZ3MgPSBjKG1lYW4gPSBidXJnZXJfa2luZ19zb2RpX21lYW4sIHNkID0gYnVyZ2VyX2tpbmdfc29kaV9zdGQpLCBjb2wgPSAid2hpdGUiKQ0KDQpgYGANCg0KYGBge3J9DQojIE5vcm1hbCBwbG90IFNVQldBWQ0Kc3Vid2F5IDwtIGZhc3Rmb29kICU+JQ0KICBmaWx0ZXIocmVzdGF1cmFudCA9PSAiU3Vid2F5IikNCnN1YndheV9zb2RpIDwtIHN1YndheSRzb2RpdW0NCnN1YndheV9zb2RpX21lYW4gPC0gbWVhbihzdWJ3YXkkc29kaXVtKQ0Kc3Vid2F5X3NvZGlfc3RkIDwtIHNkKHN1YndheV9zb2RpKQ0KDQpnZ3Bsb3QoZGF0YSA9IHN1YndheSwgYWVzKHNhbXBsZSA9IHN1YndheV9zb2RpKSkgKyANCiAgZ2VvbV9saW5lKHN0YXQgPSAicXEiKQ0KYGBgDQpgYGB7cn0NCiMgTm9ybWFsIHBsb3QgaGlzdG9ncmFtIFNVQldBWQ0KZ2dwbG90KGRhdGEgPSBzdWJ3YXksIGFlcyh4ID0gc3Vid2F5X3NvZGkpKSArDQogICAgICAgIGdlb21fYmxhbmsoKSArDQogICAgICAgIGdlb21faGlzdG9ncmFtKGFlcyh5ID0gLi5kZW5zaXR5Li4pKSArDQogICAgICAgIHN0YXRfZnVuY3Rpb24oZnVuID0gZG5vcm0sIGFyZ3MgPSBjKG1lYW4gPSBzdWJ3YXlfc29kaV9tZWFuLCBzZCA9IHN1YndheV9zb2RpX3N0ZCksIGNvbCA9ICJwdXJwbGUiKQ0KDQpgYGANCg0KYGBge3J9DQojIE5vcm1hbCBkaXN0cmlidXRpb24gb2Ygc29kaXVtOiBUQUNPIEJFTEwNCnRiZWxsIDwtIGZhc3Rmb29kICU+JQ0KICBmaWx0ZXIocmVzdGF1cmFudCA9PSAiVGFjbyBCZWxsIikNCnRiZWxsX3NvZGkgPC0gdGJlbGwkc29kaXVtDQp0YmVsbF9zb2RpX21lYW4gPC0gbWVhbih0YmVsbCRzb2RpdW0pDQp0YmVsbF9zb2RpX3N0ZCA8LSBzZCh0YmVsbF9zb2RpKQ0KDQpnZ3Bsb3QoZGF0YSA9IHRiZWxsLCBhZXMoc2FtcGxlID0gdGJlbGxfc29kaSkpICsgDQogIGdlb21fbGluZShzdGF0ID0gInFxIikNCmBgYA0KDQpgYGB7cn0NCiMgTm9ybWFsIHBsb3QgaGlzdG9ncmFtIFRBQ08gQkVMTA0KZ2dwbG90KGRhdGEgPSB0YmVsbCwgYWVzKHggPSB0YmVsbF9zb2RpKSkgKw0KICAgICAgICBnZW9tX2JsYW5rKCkgKw0KICAgICAgICBnZW9tX2hpc3RvZ3JhbShhZXMoeSA9IC4uZGVuc2l0eS4uKSkgKw0KICAgICAgICBzdGF0X2Z1bmN0aW9uKGZ1biA9IGRub3JtLCBhcmdzID0gYyhtZWFuID0gdGJlbGxfc29kaV9tZWFuLCBzZCA9IHRiZWxsX3NvZGlfc3RkKSwgY29sID0gImJsdWUiKQ0KDQpgYGANCg0KYGBge3J9DQojIE5vcm1hbCBkaXN0cmlidXRpb24gZm9yIHNvZGl1bSBEQUlSWSBRVUVFTg0KZHFfc29kaSA8LSBkYWlyeV9xdWVlbiRzb2RpdW0NCmRxX3NvZGlfbWVhbiA8LSBtZWFuKGRhaXJ5X3F1ZWVuJHNvZGl1bSkNCmRxX3NvZGlfc3RkIDwtIHNkKGRhaXJ5X3F1ZWVuJHNvZGl1bSkNCg0KZ2dwbG90KGRhdGEgPSBkYWlyeV9xdWVlbiwgYWVzKHNhbXBsZSA9IGRxX3NvZGkpKSArIA0KICBnZW9tX2xpbmUoc3RhdCA9ICJxcSIpDQoNCmBgYA0KDQpgYGB7cn0NCiMgTm9ybWFsIHBsb3QgaGloc3RvZ3JhbSBEQUlSWSBRVUVFTg0KZ2dwbG90KGRhdGEgPSBkYWlyeV9xdWVlbiwgYWVzKHggPSBkcV9zb2RpKSkgKw0KICAgICAgICBnZW9tX2JsYW5rKCkgKw0KICAgICAgICBnZW9tX2hpc3RvZ3JhbShhZXMoeSA9IC4uZGVuc2l0eS4uKSkgKw0KICAgICAgICBzdGF0X2Z1bmN0aW9uKGZ1biA9IGRub3JtLCBhcmdzID0gYyhtZWFuID0gZHFfc29kaV9tZWFuLCBzZCA9IGRxX3NvZGlfc3RkKSwgY29sID0gInRvbWF0byIpDQpgYGANCmBgYHtyfQ0KIyBOb3JtYWwgZGlzdHJpYnV0aW9uIGZvciBzb2RpdW0gTWNEb25hbGRzDQpNY2Rvbl9zb2RpIDwtIG1jZG9uYWxkcyRzb2RpdW0NCk1jZG9uX3NvZGlfbWVhbiA8LSBtZWFuKG1jZG9uYWxkcyRzb2RpdW0pDQpNY2Rvbl9zb2RpX3N0ZCA8LSBzZChtY2RvbmFsZHMkc29kaXVtKQ0KDQpnZ3Bsb3QoZGF0YSA9IG1jZG9uYWxkcywgYWVzKHNhbXBsZSA9IE1jZG9uX3NvZGkpKSArIA0KICBnZW9tX2xpbmUoc3RhdCA9ICJxcSIpDQpgYGANCg0KYGBge3J9DQojIE5vcm1hbCBwbG90IGhpc3RvZ3JhbSBNY2RvbmFsZHMNCg0KZ2dwbG90KGRhdGEgPSBtY2RvbmFsZHMsIGFlcyh4ID0gTWNkb25fc29kaSkpICsNCiAgICAgICAgZ2VvbV9ibGFuaygpICsNCiAgICAgICAgZ2VvbV9oaXN0b2dyYW0oYWVzKHkgPSAuLmRlbnNpdHkuLikpICsNCiAgICAgICAgc3RhdF9mdW5jdGlvbihmdW4gPSBkbm9ybSwgYXJncyA9IGMobWVhbiA9IE1jZG9uX3NvZGlfbWVhbiwgc2QgPSBNY2Rvbl9zb2RpX3N0ZCksIGNvbCA9ICJncmVlbiIpDQpgYGANCg0KIyMjIEV4ZXJjaXNlIDgNCk5vdGUgdGhhdCBzb21lIG9mIHRoZSBub3JtYWwgcHJvYmFiaWxpdHkgcGxvdHMgZm9yIHNvZGl1bSBkaXN0cmlidXRpb25zIHNlZW0gdG8gaGF2ZSBhIHN0ZXB3aXNlIHBhdHRlcm4uIHdoeSBkbyB5b3UgdGhpbmsgdGhpcyBtaWdodCBiZSB0aGUgY2FzZT8NCj4gSSB0aGluayB0aGlzIGlzIGJlY2F1c2UgdmFyaWF0aW9ucyBvZiBpdGVtcyBtYXkgaGF2ZSBzaW1pbGFyIGFtb3VudHMgb2Ygc29kaXVtLiBGb3IgaW5zdGFuY2UsIGl0IGlzIGxpa2VseSB0aGF0IHRoZSBtYW55IHZhcmlhdGlvbnMgb2YgY2hpY2tlbiBzYW5kd2hpY2hlcyB0aGF0IGNoaWNrIGZpbCBhIG9mZmVycyBoYXZlIHNpbWlsYXIgYW1vdW50cyBvZiBzb2RpdW0gdG8gZWFjaCBvdGhlci4gDQoNCiMjIyBFeGVyY2lzZSA5DQpBcyB5b3UgY2FuIHNlZSwgbm9ybWFsIHByb2JhYmlsaXR5IHBsb3RzIGNhbiBiZSB1c2VkIGJvdGggdG8gYXNzZXNzIG5vcm1hbGl0eSBhbmQgdmlzdWFsaXplIHNrZXduZXNzLiBNYWtlIGEgbm9ybWFsIHByb2JhYmlsaXR5IHBsb3QgZm9yIHRoZSB0b3RhbCBjYXJib2h5ZHJhdGVzIGZyb20gYSByZXN0YXVyYW50IG9mIHlvdXIgY2hvaWNlLiBCYXNlZCBvbiB0aGlzIG5vcm1hbCBwcm9iYWJpbGl0eSBwbG90LCBpcyB0aGlzIHZhcmlhYmxlIGxlZnQgc2tld2VkLCBzeW1tZXRyaWMsIG9yIHJpZ2h0IHNrZXdlZD8gVXNlIGEgaGlzdG9ncmFtIHRvIGNvbmZpcm0geW91ciBmaW5kaW5ncy4NCj4gRnJvbSB0aGUgcGxvdHMgYmVsb3csIHdlIGNhbiBjb25jbHVkZSB0aGlzIHZhcmlhYmxlIGlzIHJpZ2h0IHNrZXdlZC4NCg0KYGBge3J9DQojIE5vcm1hbCBkaXN0cmlidXRpb24gZm9yIGNhcmJvaHlkcmF0ZXMgTWNEb25hbGRzDQpNY2Rvbl9jYXJibyA8LSBtY2RvbmFsZHMkdG90YWxfY2FyYg0KTWNkb25fY2FyYm9fbWVhbiA8LSBtZWFuKG1jZG9uYWxkcyR0b3RhbF9jYXJiKQ0KTWNkb25fY2FyYm9fc3RkIDwtIHNkKG1jZG9uYWxkcyR0b3RhbF9jYXJiKQ0KDQpnZ3Bsb3QoZGF0YSA9IG1jZG9uYWxkcywgYWVzKHNhbXBsZSA9IE1jZG9uX2NhcmJvKSkgKyANCiAgZ2VvbV9saW5lKHN0YXQgPSAicXEiKQ0KYGBgDQpgYGB7cn0NCiMgTm9ybWFsIGRpc3RyaWJ1dGlvbiBjYXJicyBISVNUT0dSQU0gTWNEb25hbGRzDQpnZ3Bsb3QoZGF0YSA9IG1jZG9uYWxkcywgYWVzKHggPSBNY2Rvbl9jYXJibykpICsNCiAgICAgICAgZ2VvbV9ibGFuaygpICsNCiAgICAgICAgZ2VvbV9oaXN0b2dyYW0oYWVzKHkgPSAuLmRlbnNpdHkuLikpICsNCiAgICAgICAgc3RhdF9mdW5jdGlvbihmdW4gPSBkbm9ybSwgYXJncyA9IGMobWVhbiA9IE1jZG9uX2NhcmJvX21lYW4sIHNkID0gTWNkb25fY2FyYm9fc3RkKSwgY29sID0gImhvdCBwaW5rIikNCmBgYA==