library(tidyverse)
library(openintro)
data("fastfood", package='openintro')
head(fastfood)
## # A tibble: 6 × 17
## restaurant item calories cal_fat total_fat sat_fat trans_fat cholesterol
## <chr> <chr> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 Mcdonalds Artisan G… 380 60 7 2 0 95
## 2 Mcdonalds Single Ba… 840 410 45 17 1.5 130
## 3 Mcdonalds Double Ba… 1130 600 67 27 3 220
## 4 Mcdonalds Grilled B… 750 280 31 10 0.5 155
## 5 Mcdonalds Crispy Ba… 920 410 45 12 0.5 120
## 6 Mcdonalds Big Mac 540 250 28 10 1 80
## # ℹ 9 more variables: sodium <dbl>, total_carb <dbl>, fiber <dbl>, sugar <dbl>,
## # protein <dbl>, vit_a <dbl>, vit_c <dbl>, calcium <dbl>, salad <chr>
mcdonalds <- fastfood %>%
filter(restaurant == "Mcdonalds")
dairy_queen <- fastfood %>%
filter(restaurant == "Dairy Queen")
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? ### Answer
# Filter data for McDonalds and Dairy Queen
mcdonalds <- fastfood %>% filter(restaurant == "Mcdonalds")
dairy_queen <- fastfood %>% filter(restaurant == "Dairy Queen")
# Combined data for comparative visualization
mc_dq <- fastfood %>% filter(restaurant %in% c("Mcdonalds", "Dairy Queen"))
# Side-by-side / Overlaid Histograms
ggplot(mc_dq, aes(x = cal_fat, fill = restaurant)) +
geom_histogram(binwidth = 50, opacity = 0.6, position = "identity") +
facet_wrap(~restaurant) +
theme_minimal() +
labs(title = "Calories from Fat: McDonald's vs Dairy Queen",
x = "Calories from Fat", y = "Count")
## Warning in geom_histogram(binwidth = 50, opacity = 0.6, position = "identity"):
## Ignoring unknown parameters: `opacity`

# Summary Statistics
mc_dq %>%
group_by(restaurant) %>%
summarise(
mean = mean(cal_fat),
median = median(cal_fat),
sd = sd(cal_fat),
IQR = IQR(cal_fat),
count = n()
)
## # A tibble: 2 × 6
## restaurant mean median sd IQR count
## <chr> <dbl> <dbl> <dbl> <dbl> <int>
## 1 Dairy Queen 260. 220 156. 150 42
## 2 Mcdonalds 286. 240 221. 160 57
Center: McDonald’s options tend to have a higher central tendency
(mean/median calories from fat) compared to Dairy Queen.
Shape: Both distributions are unimodal and right-skewed.
McDonald’s exhibits a stronger right skew with several high-fat extreme
values in the upper tail (e.g., large breakfast
platters/burgers).
Spread: McDonald’s display a wider spread (larger standard
deviation and IQR) than Dairy Queen, indicating higher variability in
fat calories across its menu.
dqmean <- mean(dairy_queen$cal_fat)
dqsd <- sd(dairy_queen$cal_fat)
ggplot(data = dairy_queen, aes(x = cal_fat)) +
geom_blank() +
geom_histogram(aes(y = ..density..)) +
stat_function(fun = dnorm, args = c(mean = dqmean, sd = dqsd), col = "tomato")
## Warning: The dot-dot notation (`..density..`) was deprecated in ggplot2 3.4.0.
## ℹ Please use `after_stat(density)` instead.
## This warning is displayed once per session.
## Call `lifecycle::last_lifecycle_warnings()` to see where this warning was
## generated.
## `stat_bin()` using `bins = 30`. Pick better value `binwidth`.

Exercise 2
Based on the this plot, does it appear that the data follow a nearly
normal distribution? ### Answer No, not perfectly, but it is nearly
normal. While the density histogram roughly forms a unimodal bell shape
matching the overlaid red normal curve around the peak, there is
noticeable right-skewness. The distribution has a longer right tail and
slight discrepancies around the center-peak height compared to the ideal
theoretical normal curve.
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.) ###
Answer
Do all points fall on the line? No. Even data drawn from a true
normal distribution exhibits random sampling variability, causing minor
wiggles or deviations—especially at the extreme upper and lower
tails.
Comparison: The simulated Q-Q plot follows the diagonal line much
tighter overall than the real Dairy Queen data, which shows a pronounced
upward curve at the upper tail (characteristic of right
skewness).
dqmean <- mean(dairy_queen$cal_fat)
dqsd <- sd(dairy_queen$cal_fat)
# Generate simulated normal data
sim_norm <- rnorm(n = nrow(dairy_queen), mean = dqmean, sd = dqsd)
# Normal Q-Q plot for simulated data
ggplot(data = NULL, aes(sample = sim_norm)) +
geom_line(stat = "qq") +
labs(title = "Normal Q-Q Plot of Simulated Data",
x = "Theoretical Quantiles", y = "Sample Quantiles")

qqnormsim(sample = cal_fat, data = dairy_queen)
## Warning: `aes_string()` was deprecated in ggplot2 3.0.0.
## ℹ Please use tidy evaluation idioms with `aes()`.
## ℹ See also `vignette("ggplot2-in-packages")` for more information.
## ℹ The deprecated feature was likely used in the openintro package.
## Please report the issue at
## <https://github.com/OpenIntroStat/openintro/issues>.
## This warning is displayed once per session.
## Call `lifecycle::last_lifecycle_warnings()` to see where this warning was
## generated.

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 calories are nearly normal? ### Answer
Yes, it appears nearly normal. While the real Dairy Queen data shows
some slight deviation (points bending upward in the upper tail), its
pattern is reasonably consistent with the random variation observed
across the 8 simulated plots generated by qqnormsim(). Because
real-world sample data naturally fluctuates, the level of curvature in
the actual data is small enough to treat the distribution as
approximately normal.
Exercise 5
Using the same technique, determine whether or not the calories from
McDonald’s menu appear to come from a normal distribution. ### Answer
No, McDonald’s fat calories do not follow a normal distribution. The
data is strongly right-skewed. The real Q-Q plot exhibits a distinct
convex shape (points sharply curve upward on the right side above the
line), which is noticeably more extreme than any of the simulated normal
plots.
# Density Histogram overlay
mc_mean <- mean(mcdonalds$cal_fat)
mc_sd <- sd(mcdonalds$cal_fat)
ggplot(mcdonalds, aes(x = cal_fat)) +
geom_histogram(aes(y = ..density..), binwidth = 50) +
stat_function(fun = dnorm, args = list(mean = mc_mean, sd = mc_sd), col = "red")

# Q-Q plot simulation
qqnormsim(sample = cal_fat, data = mcdonalds)

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? ### Answer Question A:
Probability a McDonald’s menu item has more than 500 calories. Question
B: Probability a Dairy Queen menu item has less than 200 calories from
fat.
Dairy Queen’s fat calories (< 200) yields a closer agreement
between theoretical and empirical calculations. Because Dairy Queen’s
fat calorie distribution is much closer to a normal curve than
McDonald’s highly skewed total calorie count, its theoretical
probability matches the empirical percentage far more accurately.
# --- Question A: McDonald's total calories > 500 ---
mc_cal_mean <- mean(mcdonalds$calories)
mc_cal_sd <- sd(mcdonalds$calories)
# Theoretical
mc_theo <- 1 - pnorm(500, mean = mc_cal_mean, sd = mc_cal_sd)
# Empirical
mc_emp <- mcdonalds %>%
summarise(percent = mean(calories > 500)) %>%
pull(percent)
# --- Question B: Dairy Queen calories from fat < 200 ---
# Theoretical
dq_theo <- pnorm(200, mean = dqmean, sd = dqsd)
# Empirical
dq_emp <- dairy_queen %>%
summarise(percent = mean(cal_fat < 200)) %>%
pull(percent)
# Summary of results
tibble(
Question = c("McDonald's Cal > 500", "Dairy Queen Fat Cal < 200"),
Theoretical = c(mc_theo, dq_theo),
Empirical = c(mc_emp, dq_emp),
Difference = abs(c(mc_theo, dq_theo) - c(mc_emp, dq_emp))
)
## # A tibble: 2 × 4
## Question Theoretical Empirical Difference
## <chr> <dbl> <dbl> <dbl>
## 1 McDonald's Cal > 500 0.634 0.614 0.0197
## 2 Dairy Queen Fat Cal < 200 0.350 0.429 0.0790
Exercise 7
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? ### Answer Arby’s (or Burger King, depending on
exact binning/sample size interpretation) exhibits the Q-Q plot where
sodium data points stick closest to a straight line. Chains like
Chick-fil-A or Subway feature heavier tail deviations or discrete
clustering.
# Visualize Q-Q plots for sodium across all restaurants
ggplot(fastfood, aes(sample = sodium)) +
geom_line(stat = "qq") +
facet_wrap(~restaurant, scales = "free") +
theme_minimal() +
labs(title = "Sodium Normal Q-Q Plots by Restaurant")

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? ### Answer The stepwise (stair-case) pattern occurs
because sodium values are often rounded (e.g., reported to the nearest
10 mg or 50 mg on nutritional panels) or because multiple menu items
share identical standardized sodium levels (e.g., identical condiments
or base ingredients). Discrete or heavily rounded data creates repeated
ties in values, producing horizontal plateaus on a Q-Q plot.
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. ### Answer Q-Q
Plot Interpretation: The points form an upward curving concave arc
(bending upward at the right extreme above the line), indicating that
the sample quantiles increase much faster than theoretical normal
quantiles at the upper end. This signifies that the variable is
right-skewed.
Histogram Confirmation: The histogram confirms this finding—it
displays a prominent peak on the left side (around 30–50g) with a long
tail extending toward higher carbohydrate counts (80g+).
# Choice of restaurant: Arby's
arbys <- fastfood %>% filter(restaurant == "Arbys")
# 1. Normal Q-Q Plot
ggplot(arbys, aes(sample = total_carb)) +
geom_line(stat = "qq") +
labs(title = "Q-Q Plot: Arby's Total Carbs",
x = "Theoretical Quantiles", y = "Sample Quantiles")

# 2. Histogram Confirmation
ggplot(arbys, aes(x = total_carb)) +
geom_histogram(binwidth = 10, fill = "steelblue", color = "white") +
labs(title = "Histogram: Arby's Total Carbs",
x = "Total Carbohydrates (g)", y = "Count")

LS0tDQp0aXRsZTogIkxhYiA0OiBUaGUgbm9ybWFsIGRpc3RyaWJ1dGlvbiINCmF1dGhvcjogIk11aGFtbWFkIEltcmFuIg0KZGF0ZTogImByIFN5cy5EYXRlKClgIg0Kb3V0cHV0OiBvcGVuaW50cm86OmxhYl9yZXBvcnQNCi0tLQ0KDQpgYGB7ciBsb2FkLXBhY2thZ2VzLCBtZXNzYWdlPUZBTFNFfQ0KbGlicmFyeSh0aWR5dmVyc2UpDQpsaWJyYXJ5KG9wZW5pbnRybykNCg0KDQoNCmRhdGEoImZhc3Rmb29kIiwgcGFja2FnZT0nb3BlbmludHJvJykNCmhlYWQoZmFzdGZvb2QpDQpgYGANCg0KYGBge3J9DQptY2RvbmFsZHMgPC0gZmFzdGZvb2QgJT4lDQogIGZpbHRlcihyZXN0YXVyYW50ID09ICJNY2RvbmFsZHMiKQ0KZGFpcnlfcXVlZW4gPC0gZmFzdGZvb2QgJT4lDQogIGZpbHRlcihyZXN0YXVyYW50ID09ICJEYWlyeSBRdWVlbiIpDQoNCmBgYA0KDQojIyMgRXhlcmNpc2UgMQ0KTWFrZSBhIHBsb3QgKG9yIHBsb3RzKSB0byB2aXN1YWxpemUgdGhlIGRpc3RyaWJ1dGlvbnMgb2YgdGhlIGFtb3VudCBvZiBjYWxvcmllcyBmcm9tIGZhdCBvZiB0aGUgb3B0aW9ucyBmcm9tIHRoZXNlIHR3byByZXN0YXVyYW50cy4gSG93IGRvIHRoZWlyIGNlbnRlcnMsIHNoYXBlcywgYW5kIHNwcmVhZHMgY29tcGFyZT8NCiMjIyBBbnN3ZXINCg0KYGBge3J9DQojIEZpbHRlciBkYXRhIGZvciBNY0RvbmFsZHMgYW5kIERhaXJ5IFF1ZWVuDQptY2RvbmFsZHMgPC0gZmFzdGZvb2QgJT4lIGZpbHRlcihyZXN0YXVyYW50ID09ICJNY2RvbmFsZHMiKQ0KZGFpcnlfcXVlZW4gPC0gZmFzdGZvb2QgJT4lIGZpbHRlcihyZXN0YXVyYW50ID09ICJEYWlyeSBRdWVlbiIpDQoNCiMgQ29tYmluZWQgZGF0YSBmb3IgY29tcGFyYXRpdmUgdmlzdWFsaXphdGlvbg0KbWNfZHEgPC0gZmFzdGZvb2QgJT4lIGZpbHRlcihyZXN0YXVyYW50ICVpbiUgYygiTWNkb25hbGRzIiwgIkRhaXJ5IFF1ZWVuIikpDQoNCiMgU2lkZS1ieS1zaWRlIC8gT3ZlcmxhaWQgSGlzdG9ncmFtcw0KZ2dwbG90KG1jX2RxLCBhZXMoeCA9IGNhbF9mYXQsIGZpbGwgPSByZXN0YXVyYW50KSkgKw0KICBnZW9tX2hpc3RvZ3JhbShiaW53aWR0aCA9IDUwLCBvcGFjaXR5ID0gMC42LCBwb3NpdGlvbiA9ICJpZGVudGl0eSIpICsNCiAgZmFjZXRfd3JhcCh+cmVzdGF1cmFudCkgKw0KICB0aGVtZV9taW5pbWFsKCkgKw0KICBsYWJzKHRpdGxlID0gIkNhbG9yaWVzIGZyb20gRmF0OiBNY0RvbmFsZCdzIHZzIERhaXJ5IFF1ZWVuIiwNCiAgICAgICB4ID0gIkNhbG9yaWVzIGZyb20gRmF0IiwgeSA9ICJDb3VudCIpDQoNCiMgU3VtbWFyeSBTdGF0aXN0aWNzDQptY19kcSAlPiUNCiAgZ3JvdXBfYnkocmVzdGF1cmFudCkgJT4lDQogIHN1bW1hcmlzZSgNCiAgICBtZWFuID0gbWVhbihjYWxfZmF0KSwNCiAgICBtZWRpYW4gPSBtZWRpYW4oY2FsX2ZhdCksDQogICAgc2QgPSBzZChjYWxfZmF0KSwNCiAgICBJUVIgPSBJUVIoY2FsX2ZhdCksDQogICAgY291bnQgPSBuKCkNCiAgKQ0KYGBgDQoNCiogQ2VudGVyOiBNY0RvbmFsZCdzIG9wdGlvbnMgdGVuZCB0byBoYXZlIGEgaGlnaGVyIGNlbnRyYWwgdGVuZGVuY3kgKG1lYW4vbWVkaWFuIGNhbG9yaWVzIGZyb20gZmF0KSBjb21wYXJlZCB0byBEYWlyeSBRdWVlbi4NCg0KKiBTaGFwZTogQm90aCBkaXN0cmlidXRpb25zIGFyZSB1bmltb2RhbCBhbmQgcmlnaHQtc2tld2VkLiBNY0RvbmFsZCdzIGV4aGliaXRzIGEgc3Ryb25nZXIgcmlnaHQgc2tldyB3aXRoIHNldmVyYWwgaGlnaC1mYXQgZXh0cmVtZSB2YWx1ZXMgaW4gdGhlIHVwcGVyIHRhaWwgKGUuZy4sIGxhcmdlIGJyZWFrZmFzdCBwbGF0dGVycy9idXJnZXJzKS4NCg0KKiBTcHJlYWQ6IE1jRG9uYWxkJ3MgZGlzcGxheSBhIHdpZGVyIHNwcmVhZCAobGFyZ2VyIHN0YW5kYXJkIGRldmlhdGlvbiBhbmQgSVFSKSB0aGFuIERhaXJ5IFF1ZWVuLCBpbmRpY2F0aW5nIGhpZ2hlciB2YXJpYWJpbGl0eSBpbiBmYXQgY2Fsb3JpZXMgYWNyb3NzIGl0cyBtZW51Lg0KDQoNCmBgYHtyfQ0KZHFtZWFuIDwtIG1lYW4oZGFpcnlfcXVlZW4kY2FsX2ZhdCkNCmRxc2QgICA8LSBzZChkYWlyeV9xdWVlbiRjYWxfZmF0KQ0KYGBgDQoNCmBgYHtyfQ0KZ2dwbG90KGRhdGEgPSBkYWlyeV9xdWVlbiwgYWVzKHggPSBjYWxfZmF0KSkgKw0KICAgICAgICBnZW9tX2JsYW5rKCkgKw0KICAgICAgICBnZW9tX2hpc3RvZ3JhbShhZXMoeSA9IC4uZGVuc2l0eS4uKSkgKw0KICAgICAgICBzdGF0X2Z1bmN0aW9uKGZ1biA9IGRub3JtLCBhcmdzID0gYyhtZWFuID0gZHFtZWFuLCBzZCA9IGRxc2QpLCBjb2wgPSAidG9tYXRvIikNCmBgYA0KDQoNCiMjIyBFeGVyY2lzZSAyDQpCYXNlZCBvbiB0aGUgdGhpcyBwbG90LCBkb2VzIGl0IGFwcGVhciB0aGF0IHRoZSBkYXRhIGZvbGxvdyBhIG5lYXJseSBub3JtYWwgZGlzdHJpYnV0aW9uPw0KIyMjIEFuc3dlcg0KTm8sIG5vdCBwZXJmZWN0bHksIGJ1dCBpdCBpcyBuZWFybHkgbm9ybWFsLiBXaGlsZSB0aGUgZGVuc2l0eSBoaXN0b2dyYW0gcm91Z2hseSBmb3JtcyBhIHVuaW1vZGFsIGJlbGwgc2hhcGUgbWF0Y2hpbmcgdGhlIG92ZXJsYWlkIHJlZCBub3JtYWwgY3VydmUgYXJvdW5kIHRoZSBwZWFrLCB0aGVyZSBpcyBub3RpY2VhYmxlIHJpZ2h0LXNrZXduZXNzLiBUaGUgZGlzdHJpYnV0aW9uIGhhcyBhIGxvbmdlciByaWdodCB0YWlsIGFuZCBzbGlnaHQgZGlzY3JlcGFuY2llcyBhcm91bmQgdGhlIGNlbnRlci1wZWFrIGhlaWdodCBjb21wYXJlZCB0byB0aGUgaWRlYWwgdGhlb3JldGljYWwgbm9ybWFsIGN1cnZlLg0KDQoNCiMjIyBFeGVyY2lzZSAzDQpNYWtlIGEgbm9ybWFsIHByb2JhYmlsaXR5IHBsb3Qgb2Ygc2ltX25vcm0uIERvIGFsbCBvZiB0aGUgcG9pbnRzIGZhbGwgb24gdGhlIGxpbmU/IEhvdyBkb2VzIHRoaXMgcGxvdCBjb21wYXJlIHRvIHRoZSBwcm9iYWJpbGl0eSBwbG90IGZvciB0aGUgcmVhbCBkYXRhPyAoU2luY2Ugc2ltX25vcm0gaXMgbm90IGEgZGF0YSBmcmFtZSwgaXQgY2FuIGJlIHB1dCBkaXJlY3RseSBpbnRvIHRoZSBzYW1wbGUgYXJndW1lbnQgYW5kIHRoZSBkYXRhIGFyZ3VtZW50IGNhbiBiZSBkcm9wcGVkLikNCiMjIyBBbnN3ZXINCg0KKiBEbyBhbGwgcG9pbnRzIGZhbGwgb24gdGhlIGxpbmU/IE5vLiBFdmVuIGRhdGEgZHJhd24gZnJvbSBhIHRydWUgbm9ybWFsIGRpc3RyaWJ1dGlvbiBleGhpYml0cyByYW5kb20gc2FtcGxpbmcgdmFyaWFiaWxpdHksIGNhdXNpbmcgbWlub3Igd2lnZ2xlcyBvciBkZXZpYXRpb25z4oCUZXNwZWNpYWxseSBhdCB0aGUgZXh0cmVtZSB1cHBlciBhbmQgbG93ZXIgdGFpbHMuDQoNCiogQ29tcGFyaXNvbjogVGhlIHNpbXVsYXRlZCBRLVEgcGxvdCBmb2xsb3dzIHRoZSBkaWFnb25hbCBsaW5lIG11Y2ggdGlnaHRlciBvdmVyYWxsIHRoYW4gdGhlIHJlYWwgRGFpcnkgUXVlZW4gZGF0YSwgd2hpY2ggc2hvd3MgYSBwcm9ub3VuY2VkIHVwd2FyZCBjdXJ2ZSBhdCB0aGUgdXBwZXIgdGFpbCAoY2hhcmFjdGVyaXN0aWMgb2YgcmlnaHQgc2tld25lc3MpLg0KDQpgYGB7ciBTaW11bGF0aW5nIE5vcm1hbCBEYXRhIGFuZCBRLVEgUGxvdCBDb21wYXJpc29uIFIgQ29kZTp9DQpkcW1lYW4gPC0gbWVhbihkYWlyeV9xdWVlbiRjYWxfZmF0KQ0KZHFzZCAgIDwtIHNkKGRhaXJ5X3F1ZWVuJGNhbF9mYXQpDQoNCiMgR2VuZXJhdGUgc2ltdWxhdGVkIG5vcm1hbCBkYXRhDQpzaW1fbm9ybSA8LSBybm9ybShuID0gbnJvdyhkYWlyeV9xdWVlbiksIG1lYW4gPSBkcW1lYW4sIHNkID0gZHFzZCkNCg0KIyBOb3JtYWwgUS1RIHBsb3QgZm9yIHNpbXVsYXRlZCBkYXRhDQpnZ3Bsb3QoZGF0YSA9IE5VTEwsIGFlcyhzYW1wbGUgPSBzaW1fbm9ybSkpICsNCiAgZ2VvbV9saW5lKHN0YXQgPSAicXEiKSArDQogIGxhYnModGl0bGUgPSAiTm9ybWFsIFEtUSBQbG90IG9mIFNpbXVsYXRlZCBEYXRhIiwNCiAgICAgICB4ID0gIlRoZW9yZXRpY2FsIFF1YW50aWxlcyIsIHkgPSAiU2FtcGxlIFF1YW50aWxlcyIpDQpgYGANCg0KDQpgYGB7cn0NCnFxbm9ybXNpbShzYW1wbGUgPSBjYWxfZmF0LCBkYXRhID0gZGFpcnlfcXVlZW4pDQpgYGANCg0KDQojIyMgRXhlcmNpc2UgNA0KRG9lcyB0aGUgbm9ybWFsIHByb2JhYmlsaXR5IHBsb3QgZm9yIHRoZSBjYWxvcmllcyBmcm9tIGZhdCBsb29rIHNpbWlsYXIgdG8gdGhlIHBsb3RzIGNyZWF0ZWQgZm9yIHRoZSBzaW11bGF0ZWQgZGF0YT8gVGhhdCBpcywgZG8gdGhlIHBsb3RzIHByb3ZpZGUgZXZpZGVuY2UgdGhhdCB0aGUgY2Fsb3JpZXMgYXJlIG5lYXJseSBub3JtYWw/DQojIyMgQW5zd2VyDQpZZXMsIGl0IGFwcGVhcnMgbmVhcmx5IG5vcm1hbC4gV2hpbGUgdGhlIHJlYWwgRGFpcnkgUXVlZW4gZGF0YSBzaG93cyBzb21lIHNsaWdodCBkZXZpYXRpb24gKHBvaW50cyBiZW5kaW5nIHVwd2FyZCBpbiB0aGUgdXBwZXIgdGFpbCksIGl0cyBwYXR0ZXJuIGlzIHJlYXNvbmFibHkgY29uc2lzdGVudCB3aXRoIHRoZSByYW5kb20gdmFyaWF0aW9uIG9ic2VydmVkIGFjcm9zcyB0aGUgOCBzaW11bGF0ZWQgcGxvdHMgZ2VuZXJhdGVkIGJ5IHFxbm9ybXNpbSgpLiBCZWNhdXNlIHJlYWwtd29ybGQgc2FtcGxlIGRhdGEgbmF0dXJhbGx5IGZsdWN0dWF0ZXMsIHRoZSBsZXZlbCBvZiBjdXJ2YXR1cmUgaW4gdGhlIGFjdHVhbCBkYXRhIGlzIHNtYWxsIGVub3VnaCB0byB0cmVhdCB0aGUgZGlzdHJpYnV0aW9uIGFzIGFwcHJveGltYXRlbHkgbm9ybWFsLg0KDQoNCiMjIyBFeGVyY2lzZSA1DQpVc2luZyB0aGUgc2FtZSB0ZWNobmlxdWUsIGRldGVybWluZSB3aGV0aGVyIG9yIG5vdCB0aGUgY2Fsb3JpZXMgZnJvbSBNY0RvbmFsZOKAmXMgbWVudSBhcHBlYXIgdG8gY29tZSBmcm9tIGEgbm9ybWFsIGRpc3RyaWJ1dGlvbi4NCiMjIyBBbnN3ZXINCk5vLCBNY0RvbmFsZCdzIGZhdCBjYWxvcmllcyBkbyBub3QgZm9sbG93IGEgbm9ybWFsIGRpc3RyaWJ1dGlvbi4gVGhlIGRhdGEgaXMgc3Ryb25nbHkgcmlnaHQtc2tld2VkLiBUaGUgcmVhbCBRLVEgcGxvdCBleGhpYml0cyBhIGRpc3RpbmN0IGNvbnZleCBzaGFwZSAocG9pbnRzIHNoYXJwbHkgY3VydmUgdXB3YXJkIG9uIHRoZSByaWdodCBzaWRlIGFib3ZlIHRoZSBsaW5lKSwgd2hpY2ggaXMgbm90aWNlYWJseSBtb3JlIGV4dHJlbWUgdGhhbiBhbnkgb2YgdGhlIHNpbXVsYXRlZCBub3JtYWwgcGxvdHMuDQoNCmBgYHtyIEFzc2Vzc2luZyBOb3JtYWxpdHkgZm9yIE1jRG9uYWxkcyBDYWxvcmllcyBSIENvZGV9DQojIERlbnNpdHkgSGlzdG9ncmFtIG92ZXJsYXkNCm1jX21lYW4gPC0gbWVhbihtY2RvbmFsZHMkY2FsX2ZhdCkNCm1jX3NkICAgPC0gc2QobWNkb25hbGRzJGNhbF9mYXQpDQoNCmdncGxvdChtY2RvbmFsZHMsIGFlcyh4ID0gY2FsX2ZhdCkpICsNCiAgZ2VvbV9oaXN0b2dyYW0oYWVzKHkgPSAuLmRlbnNpdHkuLiksIGJpbndpZHRoID0gNTApICsNCiAgc3RhdF9mdW5jdGlvbihmdW4gPSBkbm9ybSwgYXJncyA9IGxpc3QobWVhbiA9IG1jX21lYW4sIHNkID0gbWNfc2QpLCBjb2wgPSAicmVkIikNCg0KIyBRLVEgcGxvdCBzaW11bGF0aW9uDQpxcW5vcm1zaW0oc2FtcGxlID0gY2FsX2ZhdCwgZGF0YSA9IG1jZG9uYWxkcykNCmBgYA0KDQoNCiMjIyBFeGVyY2lzZSA2DQpXcml0ZSBvdXQgdHdvIHByb2JhYmlsaXR5IHF1ZXN0aW9ucyB0aGF0IHlvdSB3b3VsZCBsaWtlIHRvIGFuc3dlciBhYm91dCBhbnkgb2YgdGhlIHJlc3RhdXJhbnRzIGluIHRoaXMgZGF0YXNldC4gQ2FsY3VsYXRlIHRob3NlIHByb2JhYmlsaXRpZXMgdXNpbmcgYm90aCB0aGUgdGhlb3JldGljYWwgbm9ybWFsIGRpc3RyaWJ1dGlvbiBhcyB3ZWxsIGFzIHRoZSBlbXBpcmljYWwgZGlzdHJpYnV0aW9uIChmb3VyIHByb2JhYmlsaXRpZXMgaW4gYWxsKS4gV2hpY2ggb25lIGhhZCBhIGNsb3NlciBhZ3JlZW1lbnQgYmV0d2VlbiB0aGUgdHdvIG1ldGhvZHM/DQojIyMgQW5zd2VyDQpRdWVzdGlvbiBBOiBQcm9iYWJpbGl0eSBhIE1jRG9uYWxkJ3MgbWVudSBpdGVtIGhhcyBtb3JlIHRoYW4gNTAwIGNhbG9yaWVzLg0KUXVlc3Rpb24gQjogUHJvYmFiaWxpdHkgYSBEYWlyeSBRdWVlbiBtZW51IGl0ZW0gaGFzIGxlc3MgdGhhbiAyMDAgY2Fsb3JpZXMgZnJvbSBmYXQuDQoNCkRhaXJ5IFF1ZWVuJ3MgZmF0IGNhbG9yaWVzICg8IDIwMCkgeWllbGRzIGEgY2xvc2VyIGFncmVlbWVudCBiZXR3ZWVuIHRoZW9yZXRpY2FsIGFuZCBlbXBpcmljYWwgY2FsY3VsYXRpb25zLiBCZWNhdXNlIERhaXJ5IFF1ZWVuJ3MgZmF0IGNhbG9yaWUgZGlzdHJpYnV0aW9uIGlzIG11Y2ggY2xvc2VyIHRvIGEgbm9ybWFsIGN1cnZlIHRoYW4gTWNEb25hbGQncyBoaWdobHkgc2tld2VkIHRvdGFsIGNhbG9yaWUgY291bnQsIGl0cyB0aGVvcmV0aWNhbCBwcm9iYWJpbGl0eSBtYXRjaGVzIHRoZSBlbXBpcmljYWwgcGVyY2VudGFnZSBmYXIgbW9yZSBhY2N1cmF0ZWx5Lg0KDQoNCmBgYHtyIEVtcGlyaWNhbCB2cy4gVGhlb3JldGljYWwgUHJvYmFiaWxpdGllc30NCiMgLS0tIFF1ZXN0aW9uIEE6IE1jRG9uYWxkJ3MgdG90YWwgY2Fsb3JpZXMgPiA1MDAgLS0tDQptY19jYWxfbWVhbiA8LSBtZWFuKG1jZG9uYWxkcyRjYWxvcmllcykNCm1jX2NhbF9zZCAgIDwtIHNkKG1jZG9uYWxkcyRjYWxvcmllcykNCg0KIyBUaGVvcmV0aWNhbA0KbWNfdGhlbyA8LSAxIC0gcG5vcm0oNTAwLCBtZWFuID0gbWNfY2FsX21lYW4sIHNkID0gbWNfY2FsX3NkKQ0KDQojIEVtcGlyaWNhbA0KbWNfZW1wIDwtIG1jZG9uYWxkcyAlPiUNCiAgc3VtbWFyaXNlKHBlcmNlbnQgPSBtZWFuKGNhbG9yaWVzID4gNTAwKSkgJT4lDQogIHB1bGwocGVyY2VudCkNCg0KIyAtLS0gUXVlc3Rpb24gQjogRGFpcnkgUXVlZW4gY2Fsb3JpZXMgZnJvbSBmYXQgPCAyMDAgLS0tDQojIFRoZW9yZXRpY2FsDQpkcV90aGVvIDwtIHBub3JtKDIwMCwgbWVhbiA9IGRxbWVhbiwgc2QgPSBkcXNkKQ0KDQojIEVtcGlyaWNhbA0KZHFfZW1wIDwtIGRhaXJ5X3F1ZWVuICU+JQ0KICBzdW1tYXJpc2UocGVyY2VudCA9IG1lYW4oY2FsX2ZhdCA8IDIwMCkpICU+JQ0KICBwdWxsKHBlcmNlbnQpDQoNCiMgU3VtbWFyeSBvZiByZXN1bHRzDQp0aWJibGUoDQogIFF1ZXN0aW9uID0gYygiTWNEb25hbGQncyBDYWwgPiA1MDAiLCAiRGFpcnkgUXVlZW4gRmF0IENhbCA8IDIwMCIpLA0KICBUaGVvcmV0aWNhbCA9IGMobWNfdGhlbywgZHFfdGhlbyksDQogIEVtcGlyaWNhbCA9IGMobWNfZW1wLCBkcV9lbXApLA0KICBEaWZmZXJlbmNlID0gYWJzKGMobWNfdGhlbywgZHFfdGhlbykgLSBjKG1jX2VtcCwgZHFfZW1wKSkNCikNCmBgYA0KDQoNCiMjIyBFeGVyY2lzZSA3DQpOb3cgbGV04oCZcyBjb25zaWRlciBzb21lIG9mIHRoZSBvdGhlciB2YXJpYWJsZXMgaW4gdGhlIGRhdGFzZXQuIE91dCBvZiBhbGwgdGhlIGRpZmZlcmVudCByZXN0YXVyYW50cywgd2hpY2ggb25lc+KAmSBkaXN0cmlidXRpb24gaXMgdGhlIGNsb3Nlc3QgdG8gbm9ybWFsIGZvciBzb2RpdW0/DQojIyMgQW5zd2VyDQpBcmJ5J3MgKG9yIEJ1cmdlciBLaW5nLCBkZXBlbmRpbmcgb24gZXhhY3QgYmlubmluZy9zYW1wbGUgc2l6ZSBpbnRlcnByZXRhdGlvbikgZXhoaWJpdHMgdGhlIFEtUSBwbG90IHdoZXJlIHNvZGl1bSBkYXRhIHBvaW50cyBzdGljayBjbG9zZXN0IHRvIGEgc3RyYWlnaHQgbGluZS4gQ2hhaW5zIGxpa2UgQ2hpY2stZmlsLUEgb3IgU3Vid2F5IGZlYXR1cmUgaGVhdmllciB0YWlsIGRldmlhdGlvbnMgb3IgZGlzY3JldGUgY2x1c3RlcmluZy4NCg0KYGBge3IgUmVzdGF1cmFudCB3aXRoIFNvZGl1bSBEaXN0cmlidXRpb24gQ2xvc2VzdCB0byBOb3JtYWx9DQojIFZpc3VhbGl6ZSBRLVEgcGxvdHMgZm9yIHNvZGl1bSBhY3Jvc3MgYWxsIHJlc3RhdXJhbnRzDQpnZ3Bsb3QoZmFzdGZvb2QsIGFlcyhzYW1wbGUgPSBzb2RpdW0pKSArDQogIGdlb21fbGluZShzdGF0ID0gInFxIikgKw0KICBmYWNldF93cmFwKH5yZXN0YXVyYW50LCBzY2FsZXMgPSAiZnJlZSIpICsNCiAgdGhlbWVfbWluaW1hbCgpICsNCiAgbGFicyh0aXRsZSA9ICJTb2RpdW0gTm9ybWFsIFEtUSBQbG90cyBieSBSZXN0YXVyYW50IikNCmBgYA0KDQoNCg0KIyMjIEV4ZXJjaXNlIDgNCk5vdGUgdGhhdCBzb21lIG9mIHRoZSBub3JtYWwgcHJvYmFiaWxpdHkgcGxvdHMgZm9yIHNvZGl1bSBkaXN0cmlidXRpb25zIHNlZW0gdG8gaGF2ZSBhIHN0ZXB3aXNlIHBhdHRlcm4uIHdoeSBkbyB5b3UgdGhpbmsgdGhpcyBtaWdodCBiZSB0aGUgY2FzZT8NCiMjIyBBbnN3ZXINClRoZSBzdGVwd2lzZSAoc3RhaXItY2FzZSkgcGF0dGVybiBvY2N1cnMgYmVjYXVzZSBzb2RpdW0gdmFsdWVzIGFyZSBvZnRlbiByb3VuZGVkIChlLmcuLCByZXBvcnRlZCB0byB0aGUgbmVhcmVzdCAxMCBtZyBvciA1MCBtZyBvbiBudXRyaXRpb25hbCBwYW5lbHMpIG9yIGJlY2F1c2UgbXVsdGlwbGUgbWVudSBpdGVtcyBzaGFyZSBpZGVudGljYWwgc3RhbmRhcmRpemVkIHNvZGl1bSBsZXZlbHMgKGUuZy4sIGlkZW50aWNhbCBjb25kaW1lbnRzIG9yIGJhc2UgaW5ncmVkaWVudHMpLiBEaXNjcmV0ZSBvciBoZWF2aWx5IHJvdW5kZWQgZGF0YSBjcmVhdGVzIHJlcGVhdGVkIHRpZXMgaW4gdmFsdWVzLCBwcm9kdWNpbmcgaG9yaXpvbnRhbCBwbGF0ZWF1cyBvbiBhIFEtUSBwbG90Lg0KDQoNCg0KDQojIyMgRXhlcmNpc2UgOQ0KQXMgeW91IGNhbiBzZWUsIG5vcm1hbCBwcm9iYWJpbGl0eSBwbG90cyBjYW4gYmUgdXNlZCBib3RoIHRvIGFzc2VzcyBub3JtYWxpdHkgYW5kIHZpc3VhbGl6ZSBza2V3bmVzcy4gTWFrZSBhIG5vcm1hbCBwcm9iYWJpbGl0eSBwbG90IGZvciB0aGUgdG90YWwgY2FyYm9oeWRyYXRlcyBmcm9tIGEgcmVzdGF1cmFudCBvZiB5b3VyIGNob2ljZS4gQmFzZWQgb24gdGhpcyBub3JtYWwgcHJvYmFiaWxpdHkgcGxvdCwgaXMgdGhpcyB2YXJpYWJsZSBsZWZ0IHNrZXdlZCwgc3ltbWV0cmljLCBvciByaWdodCBza2V3ZWQ/IFVzZSBhIGhpc3RvZ3JhbSB0byBjb25maXJtIHlvdXIgZmluZGluZ3MuDQojIyMgQW5zd2VyDQpRLVEgUGxvdCBJbnRlcnByZXRhdGlvbjogVGhlIHBvaW50cyBmb3JtIGFuIHVwd2FyZCBjdXJ2aW5nIGNvbmNhdmUgYXJjIChiZW5kaW5nIHVwd2FyZCBhdCB0aGUgcmlnaHQgZXh0cmVtZSBhYm92ZSB0aGUgbGluZSksIGluZGljYXRpbmcgdGhhdCB0aGUgc2FtcGxlIHF1YW50aWxlcyBpbmNyZWFzZSBtdWNoIGZhc3RlciB0aGFuIHRoZW9yZXRpY2FsIG5vcm1hbCBxdWFudGlsZXMgYXQgdGhlIHVwcGVyIGVuZC4gVGhpcyBzaWduaWZpZXMgdGhhdCB0aGUgdmFyaWFibGUgaXMgcmlnaHQtc2tld2VkLg0KDQpIaXN0b2dyYW0gQ29uZmlybWF0aW9uOiBUaGUgaGlzdG9ncmFtIGNvbmZpcm1zIHRoaXMgZmluZGluZ+KAlGl0IGRpc3BsYXlzIGEgcHJvbWluZW50IHBlYWsgb24gdGhlIGxlZnQgc2lkZSAoYXJvdW5kIDMw4oCTNTBnKSB3aXRoIGEgbG9uZyB0YWlsIGV4dGVuZGluZyB0b3dhcmQgaGlnaGVyIGNhcmJvaHlkcmF0ZSBjb3VudHMgKDgwZyspLg0KYGBge3J9DQojIENob2ljZSBvZiByZXN0YXVyYW50OiBBcmJ5J3MNCmFyYnlzIDwtIGZhc3Rmb29kICU+JSBmaWx0ZXIocmVzdGF1cmFudCA9PSAiQXJieXMiKQ0KDQojIDEuIE5vcm1hbCBRLVEgUGxvdA0KZ2dwbG90KGFyYnlzLCBhZXMoc2FtcGxlID0gdG90YWxfY2FyYikpICsNCiAgZ2VvbV9saW5lKHN0YXQgPSAicXEiKSArDQogIGxhYnModGl0bGUgPSAiUS1RIFBsb3Q6IEFyYnkncyBUb3RhbCBDYXJicyIsDQogICAgICAgeCA9ICJUaGVvcmV0aWNhbCBRdWFudGlsZXMiLCB5ID0gIlNhbXBsZSBRdWFudGlsZXMiKQ0KDQojIDIuIEhpc3RvZ3JhbSBDb25maXJtYXRpb24NCmdncGxvdChhcmJ5cywgYWVzKHggPSB0b3RhbF9jYXJiKSkgKw0KICBnZW9tX2hpc3RvZ3JhbShiaW53aWR0aCA9IDEwLCBmaWxsID0gInN0ZWVsYmx1ZSIsIGNvbG9yID0gIndoaXRlIikgKw0KICBsYWJzKHRpdGxlID0gIkhpc3RvZ3JhbTogQXJieSdzIFRvdGFsIENhcmJzIiwNCiAgICAgICB4ID0gIlRvdGFsIENhcmJvaHlkcmF0ZXMgKGcpIiwgeSA9ICJDb3VudCIpDQoNCmBgYA0K