Load packages

library(tidyverse)
library(openintro)
head(fastfood)
## # A tibble: 6 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
## # ... with 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

ggplot(mcdonalds, aes(x=cal_fat)) + geom_histogram(binwidth = 40) + labs(x="calories from fat", y="items on menu", title ="McDonalds")

McDonalds has a much larger spread to its data with significant outliers. The IQR looks to be within to 100-400 calorie range. There is a definable center to the data around 200-300 calorie value. The shape appears somewhat symmetrical and bell curved although there is second peak nearer to 100 calories.

ggplot(dairy_queen, aes(x=cal_fat)) + geom_histogram(binwidth = 40) + labs(x="calories from fat", y="items on menu", title="Dairy Queen")

Dairy Queen has a center around 150 with some skew to the left. The data also appears somewhat bell curved and symmetrical around its center.

Exercise 2

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")
## `stat_bin()` using `bins = 30`. Pick better value with `binwidth`.

The density function appears to have a fairly flat but undeniable unimodal shape where its peak has greatest density. I would agree that this data is normally distributed.

ggplot(data = dairy_queen, aes(sample = cal_fat)) + 
  geom_line(stat = "qq")

sim_norm <- rnorm(n = nrow(dairy_queen), mean = dqmean, sd = dqsd)

Exercise 3

qqnorm(sim_norm)
qqline(sim_norm)

Not all the points fall entirely on the line as this is randomized simulated data; the residuals look to be very small however which makes sense since this is simulated normally distributed data.

qqnorm(dairy_queen$cal_fat,main="QQ Plot: DQ - Calories from Fat")
qqline(dairy_queen$cal_fat)

In the probability plot of the real data, the datapoints do adhere to a linear pattern indicating normal distribution but lift upward and away from the theoretical line. This indicates that the actual values are much greater than the expected values if this data were perfectly and normally symmetrical. The lift indicates that this is skewed to the right - most data points are distributed on the left with a long tail of extreme values to the right. This lines up with what we saw in the histogram of the same data.

Exercise 4

qqnormsim(sample = cal_fat, data = dairy_queen)

Yes, the actual real data looks pretty similar to the simulations. The lift at the far right is still noticeably different than the normally distributed simulations - that deviation indicates some deviation away from being symmetrically distributed.

Exercise 5

The points show a more noticeable curve rather than a straight line in this qq plot. The lift at the top right is much more pronounced - the deviation away from linearity indicates deviation away from the data being normally distributed.

Again, the lift of actual data vs the expected indicates the data is again skewed to the right. This curve is more pronounced in McDonald’s menu items than in DQ’s. McDonalds has more extreme values is its tail to the right than DQ has.

ggplot(data = mcdonalds, aes(sample = cal_fat)) + 
  geom_line(stat = "qq")

qqnormsim(sample = cal_fat, data = mcdonalds)

mcdmean <- mean(mcdonalds$cal_fat)
mcdsd   <- sd(mcdonalds$cal_fat)
sim_norm_mcd <- rnorm(n = nrow(mcdonalds), mean = mcdmean, sd = mcdsd)
qqnorm(sim_norm_mcd)
qqline(sim_norm_mcd)

qqnorm(mcdonalds$cal_fat, main="QQ Plot: McD - Calories from Fat")
qqline(mcdonalds$cal_fat)

Exercise 6

Let’s say I am looking to start eating healthier, starting with choosing more healthier menu items when eating fastfood. Since the recommended amount of calories from fat is about 600 (or 30% of a traditional 2000), I’m only looking for menu items that are will account for roughly 1/3 of this total daily amount. I want to know what the probability is that an menu item that either mcd’s or dq offers will be within 150 to 250 calories from fat. Enough fat to taste, but not enough for heartburn :)

Theoretical probability that menu item from Dairy Queen is between 150 to 250 calories:

round(pnorm(q = 250, mean = dqmean, sd = dqsd) - 
  pnorm(q = 150, mean = dqmean, sd = dqsd),3)
## [1] 0.233

Empirical probability that menu item from Dairy Queen is between 150 to 250 calories:

dairy_queen %>% 
  filter(cal_fat >= 150 & cal_fat <= 250) %>%
  summarise(percent = n() / nrow(dairy_queen))
## # A tibble: 1 x 1
##   percent
##     <dbl>
## 1   0.381

Theoretical probability that menu item from McDonalds is between 150 to 250 calories:

round(pnorm(q = 250, mean = mcdmean, sd = mcdsd) - 
  pnorm(q = 150, mean = mcdmean, sd = mcdsd),3)
## [1] 0.166

Empirical probability that menu item from McDonalds is between 150 to 250 calories:

mcdonalds %>% 
  filter(cal_fat >= 150 & cal_fat <= 250) %>%
  summarise(percent = n() / nrow(mcdonalds))
## # A tibble: 1 x 1
##   percent
##     <dbl>
## 1   0.368

The theoretical probability (based on assumption of normal distribution) gave a much slimmer probability of a menu item being within the range of 150 and 250 calories, respectively 23% and 16.7%. When looking at the means and standard deviation of the 2 distributions, this makes sense that 100 calorie range below mean would net these values.

However - unsurprisingly since we viewed the data visually and know that majority of the distribution for both Dairy Queen and McDonalds is skewed to the right - the empirical probabilities in both cases is much greater.

There is a 38% empirical probability of a menu item having between 150 and 250 calories from fat in the case of DQ, and a 36.8% probability in the case of McDonalds. The right tails of both distributions indicate that there are extreme values distorting the average of this dataset, suggesting a center much farther to the right than actually exists.

Of the two, DQ had a closer predicted theoretical probability - 15% off (38 - 23) than McDonalds - 20% off (36.8 - 16.7). This is also unsurprising given that we the more significant lift in the QQ plot of McDonalds, indicating that McDonald’s had more extreme values than did DQ, and therefore more greatly distorting the actual center and spread.

Exercise 7

Evaluating for Normal Distribution in Sodium by Restaurant:

On review of the QQ plots of each restaurant, it appears that Arby’s, Burger King, and Taco Bell most clearly mirror a normal distribution. There was some curvature in Chick-Fil-A, Sonic, and Subway; the most pronounced lift (indicating right skew) appears in Dairy Queen and McDonalds.

Histograms of Sodium Distribution

ggplot(fastfood, aes(x=sodium)) + geom_histogram(binwidth = 60) + labs(x="sodium", y="items on menu", title="Sodium Amount per Item") +
  facet_wrap(~fastfood$restaurant)

Normal Probability Plots for Sodium Distribution

ggplot(data = fastfood, aes(sample = sodium))+ 
  geom_line(stat = "qq") +  
  facet_wrap(~fastfood$restaurant)

Creating Indvl QQ-Plots of Sodium Distribution

restaurants <- fastfood %>% distinct(restaurant)

chick_fil_a <- fastfood %>%
  filter(restaurant == "Chick Fil-A")

sonic <- fastfood %>%
  filter(restaurant == "Sonic")

arbys <- fastfood %>%
  filter(restaurant == "Arbys")

burger_king <- fastfood %>%
  filter(restaurant == "Burger King")

subway <- fastfood %>%
  filter(restaurant == "Subway")

taco_bell <- fastfood %>%
  filter(restaurant == "Taco Bell")

Sonic

qqnorm(sonic$sodium,main="QQ Plot: Sonic - Sodium Distrbution")
qqline(sonic$sodium)

qqnormsim(sample = sodium, data = sonic)

Arbys

qqnorm(arbys$sodium,main="QQ Plot: Arbys - Sodium Distribution")
qqline(arbys$sodium)

qqnormsim(sample = sodium, data = arbys)

Taco Bell

qqnorm(taco_bell$sodium,main="QQ Plot: Taco Bell - Sodium Distribution")
qqline(taco_bell$sodium)

qqnormsim(sample = sodium, data = taco_bell)

Burger King

qqnorm(burger_king$sodium,main="QQ Plot: Burger King - Sodium Distribution")
qqline(burger_king$sodium)

qqnormsim(sample = sodium, data = burger_king)

Subway

qqnorm(subway$sodium,main="QQ Plot: Subway - Sodium Distribution")
qqline(subway$sodium)

qqnormsim(sample = sodium, data = subway)

Chick-Fil A

qqnorm(chick_fil_a$sodium,main="QQ Plot: Chick Fil-A - Sodium Distribution")
qqline(chick_fil_a$sodium)

qqnormsim(sample = sodium, data = chick_fil_a)

McDonalds

qqnorm(mcdonalds$sodium,main="QQ Plot: McDonalds - Sodium Distribution")
qqline(mcdonalds$sodium)

qqnormsim(sample = sodium, data = mcdonalds)

Dairy Queen

qqnorm(mcdonalds$sodium,main="QQ Plot: Dairy Queen - Sodium Distribution")
qqline(dairy_queen$sodium)

qqnormsim(sample = sodium, data = dairy_queen)

Exercise 8

Stepwise patterns exist when there are repeating values. Many of the menu offerings likely have similar sodium levels to them.

Exercise 9

Looking at McDonald’s QQ plot, it appears the total carb distribution is for the most part normally distributed but with a slight right skew where some extreme values exist in the sample. This is confirmed by looking at the histogram.

ggplot(data = mcdonalds, aes(sample = total_carb))+ 
  geom_line(stat = "qq")

qqnormsim(sample = total_carb, data = mcdonalds)

qqnorm(mcdonalds$total_carb,main="QQ Plot: McDonalds - Carb Distribution")
qqline(mcdonalds$total_carb)

ggplot(mcdonalds, aes(x=total_carb)) + geom_histogram(binwidth = 5) + labs(x="total carbohydrates", y="items on menu", title="Carbohydrates per Item")

LS0tDQp0aXRsZTogIkxhYiA0IC0gTm9ybWFsIERpc3RyaWJ1dGlvbiINCmF1dGhvcjogIkNhc3NhbmRyYSBCb3lsYW4iDQpkYXRlOiAiYHIgU3lzLkRhdGUoKWAiDQpvdXRwdXQ6IG9wZW5pbnRybzo6bGFiX3JlcG9ydA0KLS0tDQoNCiMjIyBMb2FkIHBhY2thZ2VzDQpgYGB7ciBsb2FkLWRhdGEsIG1lc3NhZ2U9RkFMU0V9DQpsaWJyYXJ5KHRpZHl2ZXJzZSkNCmxpYnJhcnkob3BlbmludHJvKQ0KaGVhZChmYXN0Zm9vZCkNCmBgYA0KDQpgYGB7ciBzdWJzZXQtYnktcmVzdGFydXJhbnR9DQptY2RvbmFsZHMgPC0gZmFzdGZvb2QgJT4lDQogIGZpbHRlcihyZXN0YXVyYW50ID09ICJNY2RvbmFsZHMiKQ0KDQpkYWlyeV9xdWVlbiA8LSBmYXN0Zm9vZCAlPiUNCiAgZmlsdGVyKHJlc3RhdXJhbnQgPT0gIkRhaXJ5IFF1ZWVuIikNCmBgYA0KDQojIyMgRXhlcmNpc2UgMQ0KYGBge3IgcGxvdC1tY2R9DQpnZ3Bsb3QobWNkb25hbGRzLCBhZXMoeD1jYWxfZmF0KSkgKyBnZW9tX2hpc3RvZ3JhbShiaW53aWR0aCA9IDQwKSArIGxhYnMoeD0iY2Fsb3JpZXMgZnJvbSBmYXQiLCB5PSJpdGVtcyBvbiBtZW51IiwgdGl0bGUgPSJNY0RvbmFsZHMiKQ0KYGBgDQoNCk1jRG9uYWxkcyBoYXMgYSBtdWNoIGxhcmdlciBzcHJlYWQgdG8gaXRzIGRhdGEgd2l0aCBzaWduaWZpY2FudCBvdXRsaWVycy4gVGhlIElRUiBsb29rcyB0byBiZSB3aXRoaW4gdG8gMTAwLTQwMCBjYWxvcmllIHJhbmdlLiBUaGVyZSBpcyBhIGRlZmluYWJsZSBjZW50ZXIgdG8gdGhlIGRhdGEgYXJvdW5kIDIwMC0zMDAgY2Fsb3JpZSB2YWx1ZS4gIFRoZSBzaGFwZSBhcHBlYXJzIHNvbWV3aGF0IHN5bW1ldHJpY2FsIGFuZCBiZWxsIGN1cnZlZCBhbHRob3VnaCB0aGVyZSBpcyBzZWNvbmQgcGVhayBuZWFyZXIgdG8gMTAwIGNhbG9yaWVzLg0KICANCmBgYHtyIHBsb3QtZHF9DQpnZ3Bsb3QoZGFpcnlfcXVlZW4sIGFlcyh4PWNhbF9mYXQpKSArIGdlb21faGlzdG9ncmFtKGJpbndpZHRoID0gNDApICsgbGFicyh4PSJjYWxvcmllcyBmcm9tIGZhdCIsIHk9Iml0ZW1zIG9uIG1lbnUiLCB0aXRsZT0iRGFpcnkgUXVlZW4iKQ0KYGBgDQogIA0KRGFpcnkgUXVlZW4gaGFzIGEgY2VudGVyIGFyb3VuZCAxNTAgd2l0aCBzb21lIHNrZXcgdG8gdGhlIGxlZnQuICBUaGUgZGF0YSBhbHNvIGFwcGVhcnMgc29tZXdoYXQgYmVsbCBjdXJ2ZWQgYW5kIHN5bW1ldHJpY2FsIGFyb3VuZCBpdHMgY2VudGVyLg0KDQoNCiMjIyBFeGVyY2lzZSAyDQoNCmBgYHtyIGRxLW1lYXN1cmVzLW9mLWNlbnRlci1jYWxvcmllc30NCmRxbWVhbiA8LSBtZWFuKGRhaXJ5X3F1ZWVuJGNhbF9mYXQpDQpkcXNkICAgPC0gc2QoZGFpcnlfcXVlZW4kY2FsX2ZhdCkNCmBgYA0KDQpgYGB7ciBoaXN0LWRxfQ0KZ2dwbG90KGRhdGEgPSBkYWlyeV9xdWVlbiwgYWVzKHggPSBjYWxfZmF0KSkgKw0KICAgICAgICBnZW9tX2JsYW5rKCkgKw0KICAgICAgICBnZW9tX2hpc3RvZ3JhbShhZXMoeSA9IC4uZGVuc2l0eS4uKSkgKw0KICAgICAgICBzdGF0X2Z1bmN0aW9uKGZ1biA9IGRub3JtLCBhcmdzID0gYyhtZWFuID0gZHFtZWFuLCBzZCA9IGRxc2QpLCBjb2wgPSAidG9tYXRvIikNCmBgYA0KDQpUaGUgZGVuc2l0eSBmdW5jdGlvbiBhcHBlYXJzIHRvIGhhdmUgYSBmYWlybHkgZmxhdCBidXQgdW5kZW5pYWJsZSB1bmltb2RhbCBzaGFwZSB3aGVyZSBpdHMgcGVhayBoYXMgZ3JlYXRlc3QgZGVuc2l0eS4gIEkgd291bGQgYWdyZWUgdGhhdCB0aGlzIGRhdGEgaXMgbm9ybWFsbHkgZGlzdHJpYnV0ZWQuDQoNCmBgYHtyIHFxfQ0KZ2dwbG90KGRhdGEgPSBkYWlyeV9xdWVlbiwgYWVzKHNhbXBsZSA9IGNhbF9mYXQpKSArIA0KICBnZW9tX2xpbmUoc3RhdCA9ICJxcSIpDQpgYGANCg0KYGBge3Igc2ltLW5vcm19DQpzaW1fbm9ybSA8LSBybm9ybShuID0gbnJvdyhkYWlyeV9xdWVlbiksIG1lYW4gPSBkcW1lYW4sIHNkID0gZHFzZCkNCmBgYA0KDQojIyMgRXhlcmNpc2UgMw0KDQpgYGB7cn0NCnFxbm9ybShzaW1fbm9ybSkNCnFxbGluZShzaW1fbm9ybSkNCmBgYA0KDQpOb3QgYWxsIHRoZSBwb2ludHMgZmFsbCBlbnRpcmVseSBvbiB0aGUgbGluZSBhcyB0aGlzIGlzIHJhbmRvbWl6ZWQgc2ltdWxhdGVkIGRhdGE7IHRoZSByZXNpZHVhbHMgbG9vayB0byBiZSB2ZXJ5IHNtYWxsIGhvd2V2ZXIgd2hpY2ggbWFrZXMgc2Vuc2Ugc2luY2UgdGhpcyBpcyBzaW11bGF0ZWQgbm9ybWFsbHkgZGlzdHJpYnV0ZWQgZGF0YS4NCg0KYGBge3J9DQpxcW5vcm0oZGFpcnlfcXVlZW4kY2FsX2ZhdCxtYWluPSJRUSBQbG90OiBEUSAtIENhbG9yaWVzIGZyb20gRmF0IikNCnFxbGluZShkYWlyeV9xdWVlbiRjYWxfZmF0KQ0KYGBgDQpJbiB0aGUgcHJvYmFiaWxpdHkgcGxvdCBvZiB0aGUgcmVhbCBkYXRhLCB0aGUgZGF0YXBvaW50cyBkbyBhZGhlcmUgdG8gYSBsaW5lYXIgcGF0dGVybiBpbmRpY2F0aW5nIG5vcm1hbCBkaXN0cmlidXRpb24gYnV0IGxpZnQgdXB3YXJkIGFuZCBhd2F5IGZyb20gdGhlIHRoZW9yZXRpY2FsIGxpbmUuICBUaGlzIGluZGljYXRlcyB0aGF0IHRoZSBhY3R1YWwgdmFsdWVzIGFyZSBtdWNoIGdyZWF0ZXIgdGhhbiB0aGUgZXhwZWN0ZWQgdmFsdWVzIGlmIHRoaXMgZGF0YSB3ZXJlIHBlcmZlY3RseSBhbmQgbm9ybWFsbHkgc3ltbWV0cmljYWwuICBUaGUgbGlmdCBpbmRpY2F0ZXMgdGhhdCB0aGlzIGlzIHNrZXdlZCB0byB0aGUgcmlnaHQgLSBtb3N0IGRhdGEgcG9pbnRzIGFyZSBkaXN0cmlidXRlZCBvbiB0aGUgbGVmdCB3aXRoIGEgbG9uZyB0YWlsIG9mIGV4dHJlbWUgdmFsdWVzIHRvIHRoZSByaWdodC4gIFRoaXMgbGluZXMgdXAgd2l0aCB3aGF0IHdlIHNhdyBpbiB0aGUgaGlzdG9ncmFtIG9mIHRoZSBzYW1lIGRhdGEuDQoNCiMjIyBFeGVyY2lzZSA0DQpgYGB7ciBxcW5vcm1zaW19DQpxcW5vcm1zaW0oc2FtcGxlID0gY2FsX2ZhdCwgZGF0YSA9IGRhaXJ5X3F1ZWVuKQ0KYGBgDQoNClllcywgdGhlIGFjdHVhbCByZWFsIGRhdGEgbG9va3MgcHJldHR5IHNpbWlsYXIgdG8gdGhlIHNpbXVsYXRpb25zLiAgVGhlIGxpZnQgYXQgdGhlIGZhciByaWdodCBpcyBzdGlsbCBub3RpY2VhYmx5IGRpZmZlcmVudCB0aGFuIHRoZSBub3JtYWxseSBkaXN0cmlidXRlZCBzaW11bGF0aW9ucyAtIHRoYXQgZGV2aWF0aW9uIGluZGljYXRlcyBzb21lIGRldmlhdGlvbiBhd2F5IGZyb20gYmVpbmcgc3ltbWV0cmljYWxseSBkaXN0cmlidXRlZC4NCg0KIyMjIEV4ZXJjaXNlIDUNClRoZSBwb2ludHMgc2hvdyBhIG1vcmUgbm90aWNlYWJsZSBjdXJ2ZSByYXRoZXIgdGhhbiBhIHN0cmFpZ2h0IGxpbmUgaW4gdGhpcyBxcSBwbG90LiAgVGhlIGxpZnQgYXQgdGhlIHRvcCByaWdodCBpcyBtdWNoIG1vcmUgcHJvbm91bmNlZCAtIHRoZSBkZXZpYXRpb24gYXdheSBmcm9tIGxpbmVhcml0eSBpbmRpY2F0ZXMgZGV2aWF0aW9uIGF3YXkgZnJvbSB0aGUgZGF0YSBiZWluZyBub3JtYWxseSBkaXN0cmlidXRlZC4gIA0KICANCkFnYWluLCB0aGUgbGlmdCBvZiBhY3R1YWwgZGF0YSB2cyB0aGUgZXhwZWN0ZWQgaW5kaWNhdGVzIHRoZSBkYXRhIGlzIGFnYWluIHNrZXdlZCB0byB0aGUgcmlnaHQuIFRoaXMgY3VydmUgaXMgbW9yZSBwcm9ub3VuY2VkIGluIE1jRG9uYWxkJ3MgbWVudSBpdGVtcyB0aGFuIGluIERRJ3MuICAgTWNEb25hbGRzIGhhcyBtb3JlIGV4dHJlbWUgdmFsdWVzIGlzIGl0cyB0YWlsIHRvIHRoZSByaWdodCB0aGFuIERRIGhhcy4NCmBgYHtyIHFxLXBsb3RzfQ0KZ2dwbG90KGRhdGEgPSBtY2RvbmFsZHMsIGFlcyhzYW1wbGUgPSBjYWxfZmF0KSkgKyANCiAgZ2VvbV9saW5lKHN0YXQgPSAicXEiKQ0KDQpxcW5vcm1zaW0oc2FtcGxlID0gY2FsX2ZhdCwgZGF0YSA9IG1jZG9uYWxkcykNCmBgYA0KDQpgYGB7ciBtY2QtbWVhc3VyZXMtb2YtY2VudGVyfQ0KbWNkbWVhbiA8LSBtZWFuKG1jZG9uYWxkcyRjYWxfZmF0KQ0KbWNkc2QgICA8LSBzZChtY2RvbmFsZHMkY2FsX2ZhdCkNCmBgYA0KDQpgYGB7ciBzaW0tbm9ybS1tY2R9DQpzaW1fbm9ybV9tY2QgPC0gcm5vcm0obiA9IG5yb3cobWNkb25hbGRzKSwgbWVhbiA9IG1jZG1lYW4sIHNkID0gbWNkc2QpDQpgYGANCg0KYGBge3J9DQpxcW5vcm0oc2ltX25vcm1fbWNkKQ0KcXFsaW5lKHNpbV9ub3JtX21jZCkNCmBgYA0KDQpgYGB7cn0NCnFxbm9ybShtY2RvbmFsZHMkY2FsX2ZhdCwgbWFpbj0iUVEgUGxvdDogTWNEIC0gQ2Fsb3JpZXMgZnJvbSBGYXQiKQ0KcXFsaW5lKG1jZG9uYWxkcyRjYWxfZmF0KQ0KYGBgDQoNCiMjIyBFeGVyY2lzZSA2DQoNCkxldCdzIHNheSBJIGFtIGxvb2tpbmcgdG8gc3RhcnQgZWF0aW5nIGhlYWx0aGllciwgc3RhcnRpbmcgd2l0aCBjaG9vc2luZyBtb3JlIGhlYWx0aGllciBtZW51IGl0ZW1zIHdoZW4gZWF0aW5nIGZhc3Rmb29kLiAgU2luY2UgdGhlIHJlY29tbWVuZGVkIGFtb3VudCBvZiBjYWxvcmllcyBmcm9tIGZhdCBpcyBhYm91dCA2MDAgKG9yIDMwJSBvZiBhIHRyYWRpdGlvbmFsIDIwMDApLCBJJ20gb25seSBsb29raW5nIGZvciBtZW51IGl0ZW1zIHRoYXQgYXJlIHdpbGwgYWNjb3VudCBmb3Igcm91Z2hseSAxLzMgb2YgdGhpcyB0b3RhbCBkYWlseSBhbW91bnQuIEkgd2FudCB0byBrbm93IHdoYXQgdGhlIHByb2JhYmlsaXR5IGlzIHRoYXQgYW4gbWVudSBpdGVtIHRoYXQgZWl0aGVyIG1jZCdzIG9yIGRxIG9mZmVycyB3aWxsIGJlIHdpdGhpbiAxNTAgdG8gMjUwIGNhbG9yaWVzIGZyb20gZmF0LiAgRW5vdWdoIGZhdCB0byB0YXN0ZSwgYnV0IG5vdCBlbm91Z2ggZm9yIGhlYXJ0YnVybiA6KQ0KDQoqKlRoZW9yZXRpY2FsIHByb2JhYmlsaXR5IHRoYXQgbWVudSBpdGVtIGZyb20gRGFpcnkgUXVlZW4gaXMgYmV0d2VlbiAxNTAgdG8gMjUwIGNhbG9yaWVzOioqDQpgYGB7cn0NCnJvdW5kKHBub3JtKHEgPSAyNTAsIG1lYW4gPSBkcW1lYW4sIHNkID0gZHFzZCkgLSANCiAgcG5vcm0ocSA9IDE1MCwgbWVhbiA9IGRxbWVhbiwgc2QgPSBkcXNkKSwzKQ0KYGBgDQogIA0KKipFbXBpcmljYWwgcHJvYmFiaWxpdHkgdGhhdCBtZW51IGl0ZW0gZnJvbSBEYWlyeSBRdWVlbiBpcyBiZXR3ZWVuIDE1MCB0byAyNTAgY2Fsb3JpZXM6KioNCmBgYHtyIHByb2JhYmlsaXR5LWRxIGNhbG9yaWVzfQ0KZGFpcnlfcXVlZW4gJT4lIA0KICBmaWx0ZXIoY2FsX2ZhdCA+PSAxNTAgJiBjYWxfZmF0IDw9IDI1MCkgJT4lDQogIHN1bW1hcmlzZShwZXJjZW50ID0gbigpIC8gbnJvdyhkYWlyeV9xdWVlbikpDQpgYGANCg0KKipUaGVvcmV0aWNhbCBwcm9iYWJpbGl0eSB0aGF0IG1lbnUgaXRlbSBmcm9tIE1jRG9uYWxkcyBpcyBiZXR3ZWVuIDE1MCB0byAyNTAgY2Fsb3JpZXM6KioNCmBgYHtyfQ0Kcm91bmQocG5vcm0ocSA9IDI1MCwgbWVhbiA9IG1jZG1lYW4sIHNkID0gbWNkc2QpIC0gDQogIHBub3JtKHEgPSAxNTAsIG1lYW4gPSBtY2RtZWFuLCBzZCA9IG1jZHNkKSwzKQ0KYGBgDQogIA0KKipFbXBpcmljYWwgcHJvYmFiaWxpdHkgdGhhdCBtZW51IGl0ZW0gZnJvbSBNY0RvbmFsZHMgaXMgYmV0d2VlbiAxNTAgdG8gMjUwIGNhbG9yaWVzOioqDQpgYGB7ciBwcm9iYWJpbGl0eS1tY2QgY2Fsb3JpZXN9DQptY2RvbmFsZHMgJT4lIA0KICBmaWx0ZXIoY2FsX2ZhdCA+PSAxNTAgJiBjYWxfZmF0IDw9IDI1MCkgJT4lDQogIHN1bW1hcmlzZShwZXJjZW50ID0gbigpIC8gbnJvdyhtY2RvbmFsZHMpKQ0KYGBgDQoNClRoZSB0aGVvcmV0aWNhbCBwcm9iYWJpbGl0eSAoYmFzZWQgb24gYXNzdW1wdGlvbiBvZiBub3JtYWwgZGlzdHJpYnV0aW9uKSBnYXZlIGEgbXVjaCBzbGltbWVyIHByb2JhYmlsaXR5IG9mIGEgbWVudSBpdGVtIGJlaW5nIHdpdGhpbiB0aGUgcmFuZ2Ugb2YgMTUwIGFuZCAyNTAgY2Fsb3JpZXMsIHJlc3BlY3RpdmVseSAyMyUgYW5kIDE2LjclLiAgV2hlbiBsb29raW5nIGF0IHRoZSBtZWFucyBhbmQgc3RhbmRhcmQgZGV2aWF0aW9uIG9mIHRoZSAyIGRpc3RyaWJ1dGlvbnMsIHRoaXMgbWFrZXMgc2Vuc2UgdGhhdCAxMDAgY2Fsb3JpZSByYW5nZSBiZWxvdyBtZWFuIHdvdWxkIG5ldCB0aGVzZSB2YWx1ZXMuICANCg0KSG93ZXZlciAtIHVuc3VycHJpc2luZ2x5IHNpbmNlIHdlIHZpZXdlZCB0aGUgZGF0YSB2aXN1YWxseSBhbmQga25vdyB0aGF0IG1ham9yaXR5IG9mIHRoZSBkaXN0cmlidXRpb24gZm9yIGJvdGggRGFpcnkgUXVlZW4gYW5kIE1jRG9uYWxkcyBpcyBza2V3ZWQgdG8gdGhlIHJpZ2h0IC0gdGhlIGVtcGlyaWNhbCBwcm9iYWJpbGl0aWVzIGluIGJvdGggY2FzZXMgaXMgbXVjaCBncmVhdGVyLiAgIA0KDQpUaGVyZSBpcyBhIDM4JSBlbXBpcmljYWwgcHJvYmFiaWxpdHkgb2YgYSBtZW51IGl0ZW0gaGF2aW5nIGJldHdlZW4gMTUwIGFuZCAyNTAgY2Fsb3JpZXMgZnJvbSBmYXQgaW4gdGhlIGNhc2Ugb2YgRFEsIGFuZCBhIDM2LjglIHByb2JhYmlsaXR5IGluIHRoZSBjYXNlIG9mIE1jRG9uYWxkcy4gVGhlIHJpZ2h0IHRhaWxzIG9mIGJvdGggZGlzdHJpYnV0aW9ucyBpbmRpY2F0ZSB0aGF0IHRoZXJlIGFyZSBleHRyZW1lIHZhbHVlcyBkaXN0b3J0aW5nIHRoZSBhdmVyYWdlIG9mIHRoaXMgZGF0YXNldCwgc3VnZ2VzdGluZyBhIGNlbnRlciBtdWNoIGZhcnRoZXIgdG8gdGhlIHJpZ2h0IHRoYW4gYWN0dWFsbHkgZXhpc3RzLiAgDQoNCk9mIHRoZSB0d28sIERRIGhhZCBhIGNsb3NlciBwcmVkaWN0ZWQgdGhlb3JldGljYWwgcHJvYmFiaWxpdHkgLSAxNSUgb2ZmICgzOCAtIDIzKSB0aGFuIE1jRG9uYWxkcyAtIDIwJSBvZmYgKDM2LjggLSAxNi43KS4gIFRoaXMgaXMgYWxzbyB1bnN1cnByaXNpbmcgZ2l2ZW4gdGhhdCB3ZSB0aGUgbW9yZSBzaWduaWZpY2FudCBsaWZ0IGluIHRoZSBRUSBwbG90IG9mIE1jRG9uYWxkcywgaW5kaWNhdGluZyB0aGF0IE1jRG9uYWxkJ3MgaGFkIG1vcmUgZXh0cmVtZSB2YWx1ZXMgdGhhbiBkaWQgRFEsIGFuZCB0aGVyZWZvcmUgbW9yZSBncmVhdGx5IGRpc3RvcnRpbmcgdGhlIGFjdHVhbCBjZW50ZXIgYW5kIHNwcmVhZC4NCg0KIyMjIEV4ZXJjaXNlIDcNCkV2YWx1YXRpbmcgZm9yIE5vcm1hbCBEaXN0cmlidXRpb24gaW4gU29kaXVtIGJ5IFJlc3RhdXJhbnQ6DQogIA0KT24gcmV2aWV3IG9mIHRoZSBRUSBwbG90cyBvZiBlYWNoIHJlc3RhdXJhbnQsIGl0IGFwcGVhcnMgdGhhdCBBcmJ5J3MsIEJ1cmdlciBLaW5nLCBhbmQgVGFjbyBCZWxsIG1vc3QgY2xlYXJseSBtaXJyb3IgYSBub3JtYWwgZGlzdHJpYnV0aW9uLiAgVGhlcmUgd2FzIHNvbWUgY3VydmF0dXJlIGluIENoaWNrLUZpbC1BLCBTb25pYywgYW5kIFN1YndheTsgdGhlIG1vc3QgcHJvbm91bmNlZCBsaWZ0IChpbmRpY2F0aW5nIHJpZ2h0IHNrZXcpIGFwcGVhcnMgaW4gRGFpcnkgUXVlZW4gYW5kIE1jRG9uYWxkcy4gIA0KICANCioqSGlzdG9ncmFtcyBvZiBTb2RpdW0gRGlzdHJpYnV0aW9uKiogICAgDQpgYGB7ciBwbG90LWhpc3QtYWxsLXJlc3RhdXJhbnRzfQ0KZ2dwbG90KGZhc3Rmb29kLCBhZXMoeD1zb2RpdW0pKSArIGdlb21faGlzdG9ncmFtKGJpbndpZHRoID0gNjApICsgbGFicyh4PSJzb2RpdW0iLCB5PSJpdGVtcyBvbiBtZW51IiwgdGl0bGU9IlNvZGl1bSBBbW91bnQgcGVyIEl0ZW0iKSArDQogIGZhY2V0X3dyYXAofmZhc3Rmb29kJHJlc3RhdXJhbnQpDQpgYGANCg0KKipOb3JtYWwgUHJvYmFiaWxpdHkgUGxvdHMgZm9yIFNvZGl1bSBEaXN0cmlidXRpb24qKg0KYGBge3IgcXEtcGxvdC1hbGwtcmVzdGF1cmFudHN9DQpnZ3Bsb3QoZGF0YSA9IGZhc3Rmb29kLCBhZXMoc2FtcGxlID0gc29kaXVtKSkrIA0KICBnZW9tX2xpbmUoc3RhdCA9ICJxcSIpICsgIA0KICBmYWNldF93cmFwKH5mYXN0Zm9vZCRyZXN0YXVyYW50KQ0KYGBgDQoNCioqQ3JlYXRpbmcgSW5kdmwgUVEtUGxvdHMgb2YgU29kaXVtIERpc3RyaWJ1dGlvbioqDQpgYGB7ciBzdWJzZXQgZWFjaCBzYW1wbGUgb2JzZXJ2YXRpb25zIGJ5IHJlc3RhdXJhbnR9DQpyZXN0YXVyYW50cyA8LSBmYXN0Zm9vZCAlPiUgZGlzdGluY3QocmVzdGF1cmFudCkNCg0KY2hpY2tfZmlsX2EgPC0gZmFzdGZvb2QgJT4lDQogIGZpbHRlcihyZXN0YXVyYW50ID09ICJDaGljayBGaWwtQSIpDQoNCnNvbmljIDwtIGZhc3Rmb29kICU+JQ0KICBmaWx0ZXIocmVzdGF1cmFudCA9PSAiU29uaWMiKQ0KDQphcmJ5cyA8LSBmYXN0Zm9vZCAlPiUNCiAgZmlsdGVyKHJlc3RhdXJhbnQgPT0gIkFyYnlzIikNCg0KYnVyZ2VyX2tpbmcgPC0gZmFzdGZvb2QgJT4lDQogIGZpbHRlcihyZXN0YXVyYW50ID09ICJCdXJnZXIgS2luZyIpDQoNCnN1YndheSA8LSBmYXN0Zm9vZCAlPiUNCiAgZmlsdGVyKHJlc3RhdXJhbnQgPT0gIlN1YndheSIpDQoNCnRhY29fYmVsbCA8LSBmYXN0Zm9vZCAlPiUNCiAgZmlsdGVyKHJlc3RhdXJhbnQgPT0gIlRhY28gQmVsbCIpDQoNCmBgYA0KICAgIA0KKipTb25pYyoqDQpgYGB7ciBxcS1wbG90cy1zb25pYyB9DQpxcW5vcm0oc29uaWMkc29kaXVtLG1haW49IlFRIFBsb3Q6IFNvbmljIC0gU29kaXVtIERpc3RyYnV0aW9uIikNCnFxbGluZShzb25pYyRzb2RpdW0pDQpxcW5vcm1zaW0oc2FtcGxlID0gc29kaXVtLCBkYXRhID0gc29uaWMpDQpgYGANCiAgDQoqKkFyYnlzKioNCmBgYHtyIHFxLXBsb3RzLWFyYnlzfQ0KcXFub3JtKGFyYnlzJHNvZGl1bSxtYWluPSJRUSBQbG90OiBBcmJ5cyAtIFNvZGl1bSBEaXN0cmlidXRpb24iKQ0KcXFsaW5lKGFyYnlzJHNvZGl1bSkNCnFxbm9ybXNpbShzYW1wbGUgPSBzb2RpdW0sIGRhdGEgPSBhcmJ5cykNCmBgYA0KDQoqKlRhY28gQmVsbCoqDQpgYGB7ciBxcS1wbG90cy10YWNvLWJlbGx9DQpxcW5vcm0odGFjb19iZWxsJHNvZGl1bSxtYWluPSJRUSBQbG90OiBUYWNvIEJlbGwgLSBTb2RpdW0gRGlzdHJpYnV0aW9uIikNCnFxbGluZSh0YWNvX2JlbGwkc29kaXVtKQ0KcXFub3Jtc2ltKHNhbXBsZSA9IHNvZGl1bSwgZGF0YSA9IHRhY29fYmVsbCkNCmBgYA0KDQoqKkJ1cmdlciBLaW5nKioNCmBgYHtyIHFxLXBsb3RzLWJ1cmdlci1raW5nfQ0KcXFub3JtKGJ1cmdlcl9raW5nJHNvZGl1bSxtYWluPSJRUSBQbG90OiBCdXJnZXIgS2luZyAtIFNvZGl1bSBEaXN0cmlidXRpb24iKQ0KcXFsaW5lKGJ1cmdlcl9raW5nJHNvZGl1bSkNCnFxbm9ybXNpbShzYW1wbGUgPSBzb2RpdW0sIGRhdGEgPSBidXJnZXJfa2luZykNCmBgYA0KDQoqKlN1YndheSoqDQpgYGB7ciBxcS1wbG90cy1zdWJ3YXl9DQpxcW5vcm0oc3Vid2F5JHNvZGl1bSxtYWluPSJRUSBQbG90OiBTdWJ3YXkgLSBTb2RpdW0gRGlzdHJpYnV0aW9uIikNCnFxbGluZShzdWJ3YXkkc29kaXVtKQ0KcXFub3Jtc2ltKHNhbXBsZSA9IHNvZGl1bSwgZGF0YSA9IHN1YndheSkNCmBgYA0KDQoqKkNoaWNrLUZpbCBBKioNCmBgYHtyIHFxLXBsb3RzLWNoaWNrLWZpbC1hfQ0KcXFub3JtKGNoaWNrX2ZpbF9hJHNvZGl1bSxtYWluPSJRUSBQbG90OiBDaGljayBGaWwtQSAtIFNvZGl1bSBEaXN0cmlidXRpb24iKQ0KcXFsaW5lKGNoaWNrX2ZpbF9hJHNvZGl1bSkNCnFxbm9ybXNpbShzYW1wbGUgPSBzb2RpdW0sIGRhdGEgPSBjaGlja19maWxfYSkNCmBgYA0KDQoqKk1jRG9uYWxkcyoqDQpgYGB7ciBxcS1wbG90cy1tY2R9DQpxcW5vcm0obWNkb25hbGRzJHNvZGl1bSxtYWluPSJRUSBQbG90OiBNY0RvbmFsZHMgLSBTb2RpdW0gRGlzdHJpYnV0aW9uIikNCnFxbGluZShtY2RvbmFsZHMkc29kaXVtKQ0KcXFub3Jtc2ltKHNhbXBsZSA9IHNvZGl1bSwgZGF0YSA9IG1jZG9uYWxkcykNCmBgYA0KDQoqKkRhaXJ5IFF1ZWVuKioNCmBgYHtyIHFxLXBsb3RzLWRxfQ0KcXFub3JtKG1jZG9uYWxkcyRzb2RpdW0sbWFpbj0iUVEgUGxvdDogRGFpcnkgUXVlZW4gLSBTb2RpdW0gRGlzdHJpYnV0aW9uIikNCnFxbGluZShkYWlyeV9xdWVlbiRzb2RpdW0pDQpxcW5vcm1zaW0oc2FtcGxlID0gc29kaXVtLCBkYXRhID0gZGFpcnlfcXVlZW4pDQpgYGANCg0KIyMjIEV4ZXJjaXNlIDgNCg0KU3RlcHdpc2UgcGF0dGVybnMgZXhpc3Qgd2hlbiB0aGVyZSBhcmUgcmVwZWF0aW5nIHZhbHVlcy4gIE1hbnkgb2YgdGhlIG1lbnUgb2ZmZXJpbmdzIGxpa2VseSBoYXZlIHNpbWlsYXIgc29kaXVtIGxldmVscyB0byB0aGVtLg0KDQojIyMgRXhlcmNpc2UgOQ0KDQpMb29raW5nIGF0IE1jRG9uYWxkJ3MgUVEgcGxvdCwgaXQgYXBwZWFycyB0aGUgdG90YWwgY2FyYiBkaXN0cmlidXRpb24gaXMgZm9yIHRoZSBtb3N0IHBhcnQgbm9ybWFsbHkgZGlzdHJpYnV0ZWQgYnV0IHdpdGggYSBzbGlnaHQgcmlnaHQgc2tldyB3aGVyZSBzb21lIGV4dHJlbWUgdmFsdWVzIGV4aXN0IGluIHRoZSBzYW1wbGUuICBUaGlzIGlzIGNvbmZpcm1lZCBieSBsb29raW5nIGF0IHRoZSBoaXN0b2dyYW0uDQpgYGB7cn0NCmdncGxvdChkYXRhID0gbWNkb25hbGRzLCBhZXMoc2FtcGxlID0gdG90YWxfY2FyYikpKyANCiAgZ2VvbV9saW5lKHN0YXQgPSAicXEiKQ0KDQpxcW5vcm1zaW0oc2FtcGxlID0gdG90YWxfY2FyYiwgZGF0YSA9IG1jZG9uYWxkcykNCnFxbm9ybShtY2RvbmFsZHMkdG90YWxfY2FyYixtYWluPSJRUSBQbG90OiBNY0RvbmFsZHMgLSBDYXJiIERpc3RyaWJ1dGlvbiIpDQpxcWxpbmUobWNkb25hbGRzJHRvdGFsX2NhcmIpDQoNCmdncGxvdChtY2RvbmFsZHMsIGFlcyh4PXRvdGFsX2NhcmIpKSArIGdlb21faGlzdG9ncmFtKGJpbndpZHRoID0gNSkgKyBsYWJzKHg9InRvdGFsIGNhcmJvaHlkcmF0ZXMiLCB5PSJpdGVtcyBvbiBtZW51IiwgdGl0bGU9IkNhcmJvaHlkcmF0ZXMgcGVyIEl0ZW0iKQ0KYGBgDQo=