library(tidyverse)
library(openintro)
library(ggplot2)
library(dplyr)
data("fastfood")
data("dfdq")
## Warning in data("dfdq"): data set 'dfdq' not found

Focus on just three columns to get started: restaurant, calories, calories from fat.

Focus on just products from McDonalds and Dairy Queen.

#extract calories and cal_fat columns for McDonald's
mcdonalds <- fastfood %>%
  filter(restaurant == "Mcdonalds")
  mcdonalds[,c(1,3,4)]
## # A tibble: 57 x 3
##    restaurant calories cal_fat
##    <chr>         <dbl>   <dbl>
##  1 Mcdonalds       380      60
##  2 Mcdonalds       840     410
##  3 Mcdonalds      1130     600
##  4 Mcdonalds       750     280
##  5 Mcdonalds       920     410
##  6 Mcdonalds       540     250
##  7 Mcdonalds       300     100
##  8 Mcdonalds       510     210
##  9 Mcdonalds       430     190
## 10 Mcdonalds       770     400
## # ... with 47 more rows
rname <- mcdonalds[c(1)]
calories <- mcdonalds [c(3)]
cal_fat <- mcdonalds [c(4)]
dfm <- data.frame(cal_fat, calories) 
#extract calories and cal_fat columns for Dairy Queen
dairy_queen <- fastfood %>%
  filter(restaurant == "Dairy Queen")
  dairy_queen[,c(1,2,4)]
## # A tibble: 42 x 3
##    restaurant  item                                          cal_fat
##    <chr>       <chr>                                           <dbl>
##  1 Dairy Queen 1/2 lb. FlameThrower® GrillBurger                 660
##  2 Dairy Queen 1/2 lb. GrillBurger with Cheese                   460
##  3 Dairy Queen 1/4 lb. Bacon Cheese GrillBurger                  330
##  4 Dairy Queen 1/4 lb. GrillBurger with Cheese                   270
##  5 Dairy Queen 1/4 lb. Mushroom Swiss GrillBurger                310
##  6 Dairy Queen Original Cheeseburger                             160
##  7 Dairy Queen Original Double Cheeseburger                      310
##  8 Dairy Queen 4 Piece Chicken Strip Basket w/ Country Gravy     480
##  9 Dairy Queen 6 Piece Chicken Strip Basket w/ Country Gravy     590
## 10 Dairy Queen Bacon Cheese Dog                                  240
## # ... with 32 more rows
rname2 <- dairy_queen[c(1)]
calories2 <- dairy_queen [c(3)]
cal_fat2 <- dairy_queen [c(4)]
dfdq <- data.frame(cal_fat2, calories2) 

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:
I used ggplot for McDonalds. When I attempted to do the same for Dairy Queen, the following error displayed: “Error in is.finite(x) : default method not implemented for type ‘list’”. There were several solutions online, however none of them worked. Apparently, from what I read, it is caused by one or more values in the Dairy Queen data. After trying many different kinds of plots, the only code that returned a result is as follows: “plot(dfdq).” I even attempted to convert the Dairy Queen data frame to a vector, however it still errored out as follows:

          #convert Dairy Queen data frame to vector and plot
          vecdcalfat <- pull(dfdq, cal_fat2)
          vecdcalories <-pull(dfdq, calories2)
          ggplot(data=NULL,aes(x=vecdcalfat,y=vecdcalories))+geom_point() 

Error: Must extract column with a single valid subscript. x Subscript var has the wrong type tbl_df<cal_fat:double>. i It must be numeric or character. Run rlang::last_error() to see where the error occurred.

In visually comparing the two plots, the calories from fat to total calories from McDonald’s and Dairy Queen, they appear to have similar distributions of calories from fat, with most food items having up to around 800 calories. Without seeing a curve and by looking at the data points, it appears the data is a bit left-skewed on both. My expectation would be that the mean, mode, and the median from both plots are similar.

#Plot for McDonalds using dataframe
data1m <- data.frame(cal_fat, calories)                     # Create first data frame - McDonald's
ggplot(data=data1m,aes(x=cal_fat,y=calories))+geom_point()  #plot data from McDonald's

#Plot for Dairy Queen
dfdq <- data.frame(cal_fat2, calories2) 
#ggplot(data=dfdq,aes(x=cal_fat2,y=calories2))+geom_point()  #plot data from Dairy Queen
data(dfdq)
## Warning in data(dfdq): data set 'dfdq' not found
print(dfdq)
##    cal_fat calories
## 1      660     1000
## 2      460      800
## 3      330      630
## 4      270      540
## 5      310      570
## 6      160      400
## 7      310      630
## 8      480     1030
## 9      590     1260
## 10     240      420
## 11     220      390
## 12     220      380
## 13     180      330
## 14     160      290
## 15     180      350
## 16      80      310
## 17      80      250
## 18     410      550
## 19     670     1050
## 20     440      760
## 21     140      260
## 22     200      470
## 23     160      400
## 24     310      640
## 25     240      540
## 26     130      350
## 27     430      780
## 28     310      580
## 29     430      910
## 30     180      350
## 31     180      500
## 32     220      640
## 33     280      520
## 34     120      280
## 35     270      600
## 36     190      350
## 37     170      380
## 38      20      150
## 39     140      360
## 40     130      280
## 41       0       20
## 42     240      550
plot(dfdq)

dqmean <- mean(dairy_queen$cal_fat)
dqsd   <- sd(dairy_queen$cal_fat)
mcmean <- mean(data1m$cal_fat)
mcsd <- sd(data1m$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`.

Exercise 2

Based on the this plot, does it appear that the data follow a nearly normal distribution?

**Answer: By looking at the curve, it appears to have nearly symmetrical sides indicating it is possibly a near normal distribution.

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

#simulating data from a normal distribution using rnorm.
sim_norm <- rnorm(n = nrow(dairy_queen), mean = dqmean, sd = dqsd)

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 dataframe, it can be put directly into the sample argument and the data argument can be dropped.)

**Answer: See normal probability plot of sim_norm below. While not all the points fall on the line, many of them do, indicating the distribution could be normal.

ggplot(data = NULL, aes(sample = sim_norm)) + 
geom_line(stat = "qq")

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?

***Answer: Most points fall on the line; most calories/calories from fat are from items that have somewhere under 800 calories; it appears the variable calories from fat is 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:
The distribution under the bell curve does not appear to be symmetrical; ?????????????? I have questions about the outcome of the other graphs. It is not clear to me if the random variable we are measuring is approximately normal by looking at the other graphs compared to the bell graph.

ggplot(data = data1m, aes(x = cal_fat)) +
        geom_blank() +
        geom_histogram(aes(y = ..density..)) +
        stat_function(fun = dnorm, args = c(mean = mcmean, sd = mcsd), col = "tomato")
## `stat_bin()` using `bins = 30`. Pick better value with `binwidth`.

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

#simulating data from a normal distribution using rnorm.
sim_norm <- rnorm(n = nrow(data1m), mean = mcmean, sd = mcsd)
ggplot(data = NULL, aes(sample = sim_norm)) + 
geom_line(stat = "qq")

qqnormsim(sample = cal_fat, data = data1m)

#What is the probability that a randomly chosen Dairy Queen product has more than 600 calories from fat?” If we assume that the calories from fat from Dairy Queen’s menu are normally distributed (a very close approximation is also okay), we can find this probability by calculating a Z score and consulting a Z table (also called a normal probability table). In R, this is done in one step with the function pnorm().  pnorm() gives the area under the normal curve below a given value, q, with a given mean and standard deviation. Since we’re interested in the probability that a Dairy Queen item has more than 600 calories from fat, we have to take one minus that probability.


1 - pnorm(q = 600, mean = dqmean, sd = dqsd)
## [1] 0.01501523

Assuming a normal distribution has allowed us to calculate a theoretical probability. If we want to calculate the probability empirically, we simply need to determine how many observations fall above 600 then divide this number by the total sample size.

dairy_queen %>% 
  filter(cal_fat > 600) %>%
  summarise(percent = n() / nrow(dairy_queen))
## # A tibble: 1 x 1
##   percent
##     <dbl>
## 1  0.0476

Although the probabilities are not exactly the same, they are reasonably close. The closer that your distribution is to being normal, the more accurate the theoretical probabilities will be.

#repeating for McDonald's

1 - pnorm(q = 600, mean = mcmean, sd = mcsd)
## [1] 0.07733771
data1m %>% 
  filter(cal_fat > 600) %>%
  summarise(percent = n() / nrow(data1m))
##      percent
## 1 0.07017544

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:
Q1: What is the probability that a randomly chosen McDonald’s product has more than 600 calories from fat? Q2: What is the probabilty that a randomly chosen Dairy Queen product has more than 25 calories from total fat?

Q1 had a closer agreement between the two methods at .07, indicating the variable is normally distributed. Q2 results of .58 and .47 tells me that either something is wrong with my calculation or the variable I selected, total fat, is not normally distributed. If it’s not normally distributed, answers related to probability won’t be accurate using these methods.

#Q1 - McDonald's theoretical
1 - pnorm(q = 600, mean = mcmean, sd = mcsd)
## [1] 0.07733771
#Q1 - McDonald's Emperical

data1m %>% 
  filter(cal_fat > 600) %>%
  summarise(percent = n() / nrow(data1m))
##      percent
## 1 0.07017544
#Set Dairy Queen for total_fat; plot
ggplot(data = dairy_queen, aes(sample = total_fat)) + 
  geom_line(stat = "qq")

#Q2 - Dairy Queen; total_fat; theoretical
dqmean <- mean(dairy_queen$total_fat)
dqsd   <- sd(dairy_queen$total_fat)
1 - pnorm(q = 25, mean = dqmean, sd = dqsd)
## [1] 0.5871316
#Q2 - Dairy Queen Emperical

dairy_queen %>% 
  filter(total_fat > 25) %>%
  summarise(percent = n() / nrow(dairy_queen))
## # A tibble: 1 x 1
##   percent
##     <dbl>
## 1   0.476
LS0tDQp0aXRsZTogIkRpc3RyaWJ1dGlvbnMiDQphdXRob3I6ICJBYXJ5biBaaW1tZXJtYW4iDQpkYXRlOiAiYHIgU3lzLkRhdGUoKWAiDQpvdXRwdXQ6IG9wZW5pbnRybzo6bGFiX3JlcG9ydA0KLS0tDQoNCmBgYHtyIGxvYWQtcGFja2FnZXMsIG1lc3NhZ2U9RkFMU0V9DQpsaWJyYXJ5KHRpZHl2ZXJzZSkNCmxpYnJhcnkob3BlbmludHJvKQ0KbGlicmFyeShnZ3Bsb3QyKQ0KbGlicmFyeShkcGx5cikNCmRhdGEoImZhc3Rmb29kIikNCmRhdGEoImRmZHEiKQ0KDQpgYGANCg0KRm9jdXMgb24ganVzdCB0aHJlZSBjb2x1bW5zIHRvIGdldCBzdGFydGVkOiByZXN0YXVyYW50LCBjYWxvcmllcywgY2Fsb3JpZXMgZnJvbSBmYXQuDQoNCkZvY3VzIG9uIGp1c3QgcHJvZHVjdHMgZnJvbSBNY0RvbmFsZHMgYW5kIERhaXJ5IFF1ZWVuLg0KDQpgYGB7cn0NCiNleHRyYWN0IGNhbG9yaWVzIGFuZCBjYWxfZmF0IGNvbHVtbnMgZm9yIE1jRG9uYWxkJ3MNCm1jZG9uYWxkcyA8LSBmYXN0Zm9vZCAlPiUNCiAgZmlsdGVyKHJlc3RhdXJhbnQgPT0gIk1jZG9uYWxkcyIpDQogIG1jZG9uYWxkc1ssYygxLDMsNCldDQogIA0Kcm5hbWUgPC0gbWNkb25hbGRzW2MoMSldDQpjYWxvcmllcyA8LSBtY2RvbmFsZHMgW2MoMyldDQpjYWxfZmF0IDwtIG1jZG9uYWxkcyBbYyg0KV0NCmRmbSA8LSBkYXRhLmZyYW1lKGNhbF9mYXQsIGNhbG9yaWVzKSANCg0KYGBgDQoNCmBgYHtyfQ0KI2V4dHJhY3QgY2Fsb3JpZXMgYW5kIGNhbF9mYXQgY29sdW1ucyBmb3IgRGFpcnkgUXVlZW4NCmRhaXJ5X3F1ZWVuIDwtIGZhc3Rmb29kICU+JQ0KICBmaWx0ZXIocmVzdGF1cmFudCA9PSAiRGFpcnkgUXVlZW4iKQ0KICBkYWlyeV9xdWVlblssYygxLDIsNCldDQogIA0KICAgIA0Kcm5hbWUyIDwtIGRhaXJ5X3F1ZWVuW2MoMSldDQpjYWxvcmllczIgPC0gZGFpcnlfcXVlZW4gW2MoMyldDQpjYWxfZmF0MiA8LSBkYWlyeV9xdWVlbiBbYyg0KV0NCmRmZHEgPC0gZGF0YS5mcmFtZShjYWxfZmF0MiwgY2Fsb3JpZXMyKSANCg0KYGBgDQojIyMgRXhlcmNpc2UgMQ0KTWFrZSBhIHBsb3QgKG9yIHBsb3RzKSB0byB2aXN1YWxpemUgdGhlIGRpc3RyaWJ1dGlvbnMgb2YgdGhlIGFtb3VudCBvZiBjYWxvcmllcyBmcm9tIGZhdCBvZiB0aGUgb3B0aW9ucyBmcm9tIHRoZXNlIHR3byByZXN0YXVyYW50cy4gSG93IGRvIHRoZWlyIGNlbnRlcnMsIHNoYXBlcywgYW5kIHNwcmVhZHMgY29tcGFyZT8NCg0KKipBbnN3ZXI6ICANCkkgdXNlZCBnZ3Bsb3QgZm9yIE1jRG9uYWxkcy4gIFdoZW4gSSBhdHRlbXB0ZWQgdG8gZG8gdGhlIHNhbWUgZm9yIERhaXJ5IFF1ZWVuLCB0aGUgZm9sbG93aW5nIGVycm9yIGRpc3BsYXllZDogICJFcnJvciBpbiBpcy5maW5pdGUoeCkgOiBkZWZhdWx0IG1ldGhvZCBub3QgaW1wbGVtZW50ZWQgZm9yIHR5cGUgJ2xpc3QnIi4gIFRoZXJlIHdlcmUgc2V2ZXJhbCBzb2x1dGlvbnMgb25saW5lLCBob3dldmVyIG5vbmUgb2YgdGhlbSB3b3JrZWQuICBBcHBhcmVudGx5LCBmcm9tIHdoYXQgSSByZWFkLCBpdCBpcyBjYXVzZWQgYnkgb25lIG9yIG1vcmUgdmFsdWVzIGluIHRoZSBEYWlyeSBRdWVlbiBkYXRhLiBBZnRlciB0cnlpbmcgbWFueSBkaWZmZXJlbnQga2luZHMgb2YgcGxvdHMsIHRoZSBvbmx5IGNvZGUgdGhhdCByZXR1cm5lZCBhIHJlc3VsdCBpcyBhcyBmb2xsb3dzOiAgInBsb3QoZGZkcSkuIiAgSSBldmVuIGF0dGVtcHRlZCB0byBjb252ZXJ0IHRoZSBEYWlyeSBRdWVlbiBkYXRhIGZyYW1lIHRvIGEgdmVjdG9yLCBob3dldmVyIGl0IHN0aWxsIGVycm9yZWQgb3V0IGFzIGZvbGxvd3M6DQoNCiAgICAgICAgICAgICAgI2NvbnZlcnQgRGFpcnkgUXVlZW4gZGF0YSBmcmFtZSB0byB2ZWN0b3IgYW5kIHBsb3QNCiAgICAgICAgICAgICAgdmVjZGNhbGZhdCA8LSBwdWxsKGRmZHEsIGNhbF9mYXQyKQ0KICAgICAgICAgICAgICB2ZWNkY2Fsb3JpZXMgPC1wdWxsKGRmZHEsIGNhbG9yaWVzMikNCiAgICAgICAgICAgICAgZ2dwbG90KGRhdGE9TlVMTCxhZXMoeD12ZWNkY2FsZmF0LHk9dmVjZGNhbG9yaWVzKSkrZ2VvbV9wb2ludCgpIA0KDQpFcnJvcjogTXVzdCBleHRyYWN0IGNvbHVtbiB3aXRoIGEgc2luZ2xlIHZhbGlkIHN1YnNjcmlwdC4geCBTdWJzY3JpcHQgYHZhcmAgaGFzIHRoZSB3cm9uZyB0eXBlIGB0YmxfZGY8Y2FsX2ZhdDpkb3VibGU+YC4gaSBJdCBtdXN0IGJlIG51bWVyaWMgb3IgY2hhcmFjdGVyLiBSdW4gYHJsYW5nOjpsYXN0X2Vycm9yKClgIHRvIHNlZSB3aGVyZSB0aGUgZXJyb3Igb2NjdXJyZWQuDQogICAgICAgICAgICAgIA0KDQpJbiB2aXN1YWxseSBjb21wYXJpbmcgdGhlIHR3byBwbG90cywgdGhlIGNhbG9yaWVzIGZyb20gZmF0IHRvIHRvdGFsIGNhbG9yaWVzIGZyb20gTWNEb25hbGQncyBhbmQgRGFpcnkgUXVlZW4sIHRoZXkgYXBwZWFyIHRvIGhhdmUgc2ltaWxhciBkaXN0cmlidXRpb25zIG9mIGNhbG9yaWVzIGZyb20gZmF0LCB3aXRoIG1vc3QgZm9vZCBpdGVtcyBoYXZpbmcgdXAgdG8gYXJvdW5kIDgwMCBjYWxvcmllcy4gV2l0aG91dCBzZWVpbmcgYSBjdXJ2ZSBhbmQgYnkgbG9va2luZyBhdCB0aGUgZGF0YSBwb2ludHMsIGl0IGFwcGVhcnMgdGhlIGRhdGEgaXMgYSBiaXQgbGVmdC1za2V3ZWQgb24gYm90aC4gIE15IGV4cGVjdGF0aW9uIHdvdWxkIGJlIHRoYXQgdGhlIG1lYW4sIG1vZGUsIGFuZCB0aGUgbWVkaWFuIGZyb20gYm90aCBwbG90cyBhcmUgc2ltaWxhci4gDQoNCg0KYGBge3IgY29kZS1jaHVuay1sYWJlbH0NCiNQbG90IGZvciBNY0RvbmFsZHMgdXNpbmcgZGF0YWZyYW1lDQpkYXRhMW0gPC0gZGF0YS5mcmFtZShjYWxfZmF0LCBjYWxvcmllcykgICAgICAgICAgICAgICAgICAgICAjIENyZWF0ZSBmaXJzdCBkYXRhIGZyYW1lIC0gTWNEb25hbGQncw0KZ2dwbG90KGRhdGE9ZGF0YTFtLGFlcyh4PWNhbF9mYXQseT1jYWxvcmllcykpK2dlb21fcG9pbnQoKSAgI3Bsb3QgZGF0YSBmcm9tIE1jRG9uYWxkJ3MNCmBgYA0KDQpgYGB7cn0NCiNQbG90IGZvciBEYWlyeSBRdWVlbg0KZGZkcSA8LSBkYXRhLmZyYW1lKGNhbF9mYXQyLCBjYWxvcmllczIpIA0KI2dncGxvdChkYXRhPWRmZHEsYWVzKHg9Y2FsX2ZhdDIseT1jYWxvcmllczIpKStnZW9tX3BvaW50KCkgICNwbG90IGRhdGEgZnJvbSBEYWlyeSBRdWVlbg0KZGF0YShkZmRxKQ0KcHJpbnQoZGZkcSkNCmBgYA0KDQpgYGB7cn0NCnBsb3QoZGZkcSkNCmBgYA0KDQoNCg0KYGBge3J9DQpkcW1lYW4gPC0gbWVhbihkYWlyeV9xdWVlbiRjYWxfZmF0KQ0KZHFzZCAgIDwtIHNkKGRhaXJ5X3F1ZWVuJGNhbF9mYXQpDQptY21lYW4gPC0gbWVhbihkYXRhMW0kY2FsX2ZhdCkNCm1jc2QgPC0gc2QoZGF0YTFtJGNhbF9mYXQpDQpgYGANCg0KYGBge3J9DQpnZ3Bsb3QoZGF0YSA9IGRhaXJ5X3F1ZWVuLCBhZXMoeCA9IGNhbF9mYXQpKSArDQogICAgICAgIGdlb21fYmxhbmsoKSArDQogICAgICAgIGdlb21faGlzdG9ncmFtKGFlcyh5ID0gLi5kZW5zaXR5Li4pKSArDQogICAgICAgIHN0YXRfZnVuY3Rpb24oZnVuID0gZG5vcm0sIGFyZ3MgPSBjKG1lYW4gPSBkcW1lYW4sIHNkID0gZHFzZCksIGNvbCA9ICJ0b21hdG8iKQ0KYGBgDQoNCg0KDQojIyMgRXhlcmNpc2UgMg0KDQpCYXNlZCBvbiB0aGUgdGhpcyBwbG90LCBkb2VzIGl0IGFwcGVhciB0aGF0IHRoZSBkYXRhIGZvbGxvdyBhIG5lYXJseSBub3JtYWwgZGlzdHJpYnV0aW9uPw0KDQoqKkFuc3dlcjogIEJ5IGxvb2tpbmcgYXQgdGhlIGN1cnZlLCBpdCBhcHBlYXJzIHRvIGhhdmUgbmVhcmx5IHN5bW1ldHJpY2FsIHNpZGVzIGluZGljYXRpbmcgaXQgaXMgcG9zc2libHkgYSBuZWFyIG5vcm1hbCBkaXN0cmlidXRpb24uIA0KDQoNCmBgYHtyfQ0KYGBgDQoNCg0KYGBge3J9DQpnZ3Bsb3QoZGF0YSA9IGRhaXJ5X3F1ZWVuLCBhZXMoc2FtcGxlID0gY2FsX2ZhdCkpICsgDQogIGdlb21fbGluZShzdGF0ID0gInFxIikNCmBgYA0KDQoNCmBgYHtyfQ0KYGBgDQpgYGB7cn0NCg0KI3NpbXVsYXRpbmcgZGF0YSBmcm9tIGEgbm9ybWFsIGRpc3RyaWJ1dGlvbiB1c2luZyBybm9ybS4NCnNpbV9ub3JtIDwtIHJub3JtKG4gPSBucm93KGRhaXJ5X3F1ZWVuKSwgbWVhbiA9IGRxbWVhbiwgc2QgPSBkcXNkKQ0KYGBgDQoNCg0KIyMjIEV4ZXJjaXNlIDMNCg0KTWFrZSBhIG5vcm1hbCBwcm9iYWJpbGl0eSBwbG90IG9mIHNpbV9ub3JtLiBEbyBhbGwgb2YgdGhlIHBvaW50cyBmYWxsIG9uIHRoZSBsaW5lPyBIb3cgZG9lcyB0aGlzIHBsb3QgY29tcGFyZSB0byB0aGUgcHJvYmFiaWxpdHkgcGxvdCBmb3IgdGhlIHJlYWwgZGF0YT8gKFNpbmNlIHNpbV9ub3JtIGlzIG5vdCBhIGRhdGFmcmFtZSwgaXQgY2FuIGJlIHB1dCBkaXJlY3RseSBpbnRvIHRoZSBzYW1wbGUgYXJndW1lbnQgYW5kIHRoZSBkYXRhIGFyZ3VtZW50IGNhbiBiZSBkcm9wcGVkLikNCg0KKipBbnN3ZXI6ICBTZWUgbm9ybWFsIHByb2JhYmlsaXR5IHBsb3Qgb2Ygc2ltX25vcm0gYmVsb3cuICBXaGlsZSBub3QgYWxsIHRoZSBwb2ludHMgZmFsbCBvbiB0aGUgbGluZSwgbWFueSBvZiB0aGVtIGRvLCBpbmRpY2F0aW5nIHRoZSBkaXN0cmlidXRpb24gY291bGQgYmUgbm9ybWFsLiANCg0KDQoNCmBgYHtyfQ0KDQpnZ3Bsb3QoZGF0YSA9IE5VTEwsIGFlcyhzYW1wbGUgPSBzaW1fbm9ybSkpICsgDQpnZW9tX2xpbmUoc3RhdCA9ICJxcSIpDQpgYGANCg0KDQoNCg0KDQpgYGB7cn0NCnFxbm9ybXNpbShzYW1wbGUgPSBjYWxfZmF0LCBkYXRhID0gZGFpcnlfcXVlZW4pDQpgYGANCg0KIyMjIEV4ZXJjaXNlIDQNCkRvZXMgdGhlIG5vcm1hbCBwcm9iYWJpbGl0eSBwbG90IGZvciB0aGUgY2Fsb3JpZXMgZnJvbSBmYXQgbG9vayBzaW1pbGFyIHRvIHRoZSBwbG90cyBjcmVhdGVkIGZvciB0aGUgc2ltdWxhdGVkIGRhdGE/IFRoYXQgaXMsIGRvIHRoZSBwbG90cyBwcm92aWRlIGV2aWRlbmNlIHRoYXQgdGhlIGZlbWFsZSBoZWlnaHRzIGFyZSBuZWFybHkgbm9ybWFsPw0KDQoqKipBbnN3ZXI6ICBNb3N0IHBvaW50cyBmYWxsIG9uIHRoZSBsaW5lOyBtb3N0IGNhbG9yaWVzL2NhbG9yaWVzIGZyb20gZmF0IGFyZSBmcm9tIGl0ZW1zIHRoYXQgaGF2ZSBzb21ld2hlcmUgdW5kZXIgODAwIGNhbG9yaWVzOyBpdCBhcHBlYXJzIHRoZSB2YXJpYWJsZSBjYWxvcmllcyBmcm9tIGZhdCBpcyBhcHByb3hpbWF0ZWx5IG5vcm1hbC4NCg0KIyMjIEV4ZXJjaXNlIDUNClVzaW5nIHRoZSBzYW1lIHRlY2huaXF1ZSwgZGV0ZXJtaW5lIHdoZXRoZXIgb3Igbm90IHRoZSBjYWxvcmllcyBmcm9tIE1jRG9uYWxk4oCZcyBtZW51IGFwcGVhciB0byBjb21lIGZyb20gYSBub3JtYWwgZGlzdHJpYnV0aW9uLg0KDQoqKipBbnN3ZXI6ICANClRoZSBkaXN0cmlidXRpb24gdW5kZXIgdGhlIGJlbGwgY3VydmUgZG9lcyBub3QgYXBwZWFyIHRvIGJlIHN5bW1ldHJpY2FsOyA/Pz8/Pz8/Pz8/Pz8/PyAgSSBoYXZlIHF1ZXN0aW9ucyBhYm91dCB0aGUgb3V0Y29tZSBvZiB0aGUgb3RoZXIgZ3JhcGhzLiAgSXQgaXMgbm90IGNsZWFyIHRvIG1lIGlmIHRoZSByYW5kb20gdmFyaWFibGUgd2UgYXJlIG1lYXN1cmluZyBpcyBhcHByb3hpbWF0ZWx5IG5vcm1hbCBieSBsb29raW5nIGF0IHRoZSBvdGhlciBncmFwaHMgY29tcGFyZWQgdG8gdGhlIGJlbGwgZ3JhcGguDQoNCg0KDQpgYGB7cn0NCmdncGxvdChkYXRhID0gZGF0YTFtLCBhZXMoeCA9IGNhbF9mYXQpKSArDQogICAgICAgIGdlb21fYmxhbmsoKSArDQogICAgICAgIGdlb21faGlzdG9ncmFtKGFlcyh5ID0gLi5kZW5zaXR5Li4pKSArDQogICAgICAgIHN0YXRfZnVuY3Rpb24oZnVuID0gZG5vcm0sIGFyZ3MgPSBjKG1lYW4gPSBtY21lYW4sIHNkID0gbWNzZCksIGNvbCA9ICJ0b21hdG8iKQ0KYGBgDQpgYGB7cn0NCmdncGxvdChkYXRhID0gZGF0YTFtLCBhZXMoc2FtcGxlID0gY2FsX2ZhdCkpICsgDQogIGdlb21fbGluZShzdGF0ID0gInFxIikNCmBgYA0KYGBge3J9DQojc2ltdWxhdGluZyBkYXRhIGZyb20gYSBub3JtYWwgZGlzdHJpYnV0aW9uIHVzaW5nIHJub3JtLg0Kc2ltX25vcm0gPC0gcm5vcm0obiA9IG5yb3coZGF0YTFtKSwgbWVhbiA9IG1jbWVhbiwgc2QgPSBtY3NkKQ0KDQpgYGANCg0KDQpgYGB7cn0NCmdncGxvdChkYXRhID0gTlVMTCwgYWVzKHNhbXBsZSA9IHNpbV9ub3JtKSkgKyANCmdlb21fbGluZShzdGF0ID0gInFxIikNCmBgYA0KYGBge3J9DQpxcW5vcm1zaW0oc2FtcGxlID0gY2FsX2ZhdCwgZGF0YSA9IGRhdGExbSkNCmBgYA0KYGBge3J9DQojV2hhdCBpcyB0aGUgcHJvYmFiaWxpdHkgdGhhdCBhIHJhbmRvbWx5IGNob3NlbiBEYWlyeSBRdWVlbiBwcm9kdWN0IGhhcyBtb3JlIHRoYW4gNjAwIGNhbG9yaWVzIGZyb20gZmF0P+KAnSBJZiB3ZSBhc3N1bWUgdGhhdCB0aGUgY2Fsb3JpZXMgZnJvbSBmYXQgZnJvbSBEYWlyeSBRdWVlbuKAmXMgbWVudSBhcmUgbm9ybWFsbHkgZGlzdHJpYnV0ZWQgKGEgdmVyeSBjbG9zZSBhcHByb3hpbWF0aW9uIGlzIGFsc28gb2theSksIHdlIGNhbiBmaW5kIHRoaXMgcHJvYmFiaWxpdHkgYnkgY2FsY3VsYXRpbmcgYSBaIHNjb3JlIGFuZCBjb25zdWx0aW5nIGEgWiB0YWJsZSAoYWxzbyBjYWxsZWQgYSBub3JtYWwgcHJvYmFiaWxpdHkgdGFibGUpLiBJbiBSLCB0aGlzIGlzIGRvbmUgaW4gb25lIHN0ZXAgd2l0aCB0aGUgZnVuY3Rpb24gcG5vcm0oKS4gIHBub3JtKCkgZ2l2ZXMgdGhlIGFyZWEgdW5kZXIgdGhlIG5vcm1hbCBjdXJ2ZSBiZWxvdyBhIGdpdmVuIHZhbHVlLCBxLCB3aXRoIGEgZ2l2ZW4gbWVhbiBhbmQgc3RhbmRhcmQgZGV2aWF0aW9uLiBTaW5jZSB3ZeKAmXJlIGludGVyZXN0ZWQgaW4gdGhlIHByb2JhYmlsaXR5IHRoYXQgYSBEYWlyeSBRdWVlbiBpdGVtIGhhcyBtb3JlIHRoYW4gNjAwIGNhbG9yaWVzIGZyb20gZmF0LCB3ZSBoYXZlIHRvIHRha2Ugb25lIG1pbnVzIHRoYXQgcHJvYmFiaWxpdHkuDQoNCg0KMSAtIHBub3JtKHEgPSA2MDAsIG1lYW4gPSBkcW1lYW4sIHNkID0gZHFzZCkNCmBgYA0KDQpBc3N1bWluZyBhIG5vcm1hbCBkaXN0cmlidXRpb24gaGFzIGFsbG93ZWQgdXMgdG8gY2FsY3VsYXRlIGEgdGhlb3JldGljYWwgcHJvYmFiaWxpdHkuIElmIHdlIHdhbnQgdG8gY2FsY3VsYXRlIHRoZSBwcm9iYWJpbGl0eSBlbXBpcmljYWxseSwgd2Ugc2ltcGx5IG5lZWQgdG8gZGV0ZXJtaW5lIGhvdyBtYW55IG9ic2VydmF0aW9ucyBmYWxsIGFib3ZlIDYwMCB0aGVuIGRpdmlkZSB0aGlzIG51bWJlciBieSB0aGUgdG90YWwgc2FtcGxlIHNpemUuDQpgYGB7cn0NCmRhaXJ5X3F1ZWVuICU+JSANCiAgZmlsdGVyKGNhbF9mYXQgPiA2MDApICU+JQ0KICBzdW1tYXJpc2UocGVyY2VudCA9IG4oKSAvIG5yb3coZGFpcnlfcXVlZW4pKQ0KYGBgDQoNCkFsdGhvdWdoIHRoZSBwcm9iYWJpbGl0aWVzIGFyZSBub3QgZXhhY3RseSB0aGUgc2FtZSwgdGhleSBhcmUgcmVhc29uYWJseSBjbG9zZS4gVGhlIGNsb3NlciB0aGF0IHlvdXIgZGlzdHJpYnV0aW9uIGlzIHRvIGJlaW5nIG5vcm1hbCwgdGhlIG1vcmUgYWNjdXJhdGUgdGhlIHRoZW9yZXRpY2FsIHByb2JhYmlsaXRpZXMgd2lsbCBiZS4NCg0KYGBge3J9DQojcmVwZWF0aW5nIGZvciBNY0RvbmFsZCdzDQoNCjEgLSBwbm9ybShxID0gNjAwLCBtZWFuID0gbWNtZWFuLCBzZCA9IG1jc2QpDQoNCmBgYA0KYGBge3J9DQoNCg0KZGF0YTFtICU+JSANCiAgZmlsdGVyKGNhbF9mYXQgPiA2MDApICU+JQ0KICBzdW1tYXJpc2UocGVyY2VudCA9IG4oKSAvIG5yb3coZGF0YTFtKSkNCmBgYA0KDQoNCiMjIyBFeGVyY2lzZSA2DQpXcml0ZSBvdXQgdHdvIHByb2JhYmlsaXR5IHF1ZXN0aW9ucyB0aGF0IHlvdSB3b3VsZCBsaWtlIHRvIGFuc3dlciBhYm91dCBhbnkgb2YgdGhlIHJlc3RhdXJhbnRzIGluIHRoaXMgZGF0YXNldC4gQ2FsY3VsYXRlIHRob3NlIHByb2JhYmlsaXRpZXMgdXNpbmcgYm90aCB0aGUgdGhlb3JldGljYWwgbm9ybWFsIGRpc3RyaWJ1dGlvbiBhcyB3ZWxsIGFzIHRoZSBlbXBpcmljYWwgZGlzdHJpYnV0aW9uIChmb3VyIHByb2JhYmlsaXRpZXMgaW4gYWxsKS4gV2hpY2ggb25lIGhhZCBhIGNsb3NlciBhZ3JlZW1lbnQgYmV0d2VlbiB0aGUgdHdvIG1ldGhvZHM/DQoNCioqQW5zd2VyOiAgDQpRMTogIFdoYXQgaXMgdGhlIHByb2JhYmlsaXR5IHRoYXQgYSByYW5kb21seSBjaG9zZW4gTWNEb25hbGQncyBwcm9kdWN0IGhhcyBtb3JlIHRoYW4gNjAwIGNhbG9yaWVzIGZyb20gZmF0Pw0KUTI6ICBXaGF0IGlzIHRoZSBwcm9iYWJpbHR5IHRoYXQgYSByYW5kb21seSBjaG9zZW4gRGFpcnkgUXVlZW4gcHJvZHVjdCBoYXMgbW9yZSB0aGFuIDI1IGNhbG9yaWVzIGZyb20gdG90YWwgZmF0Pw0KDQpRMSBoYWQgYSBjbG9zZXIgYWdyZWVtZW50IGJldHdlZW4gdGhlIHR3byBtZXRob2RzIGF0IC4wNywgaW5kaWNhdGluZyB0aGUgdmFyaWFibGUgaXMgbm9ybWFsbHkgZGlzdHJpYnV0ZWQuICBRMiByZXN1bHRzIG9mIC41OCBhbmQgLjQ3IHRlbGxzIG1lIHRoYXQgZWl0aGVyIHNvbWV0aGluZyBpcyB3cm9uZyB3aXRoIG15IGNhbGN1bGF0aW9uIG9yIHRoZSB2YXJpYWJsZSBJIHNlbGVjdGVkLCB0b3RhbCBmYXQsIGlzIG5vdCBub3JtYWxseSBkaXN0cmlidXRlZC4gIElmIGl0J3Mgbm90IG5vcm1hbGx5IGRpc3RyaWJ1dGVkLCBhbnN3ZXJzIHJlbGF0ZWQgdG8gcHJvYmFiaWxpdHkgd29uJ3QgYmUgYWNjdXJhdGUgdXNpbmcgdGhlc2UgbWV0aG9kcy4NCg0KYGBge3J9DQoNCiNRMSAtIE1jRG9uYWxkJ3MgdGhlb3JldGljYWwNCjEgLSBwbm9ybShxID0gNjAwLCBtZWFuID0gbWNtZWFuLCBzZCA9IG1jc2QpDQoNCmBgYA0KDQoNCmBgYHtyfQ0KI1ExIC0gTWNEb25hbGQncyBFbXBlcmljYWwNCg0KZGF0YTFtICU+JSANCiAgZmlsdGVyKGNhbF9mYXQgPiA2MDApICU+JQ0KICBzdW1tYXJpc2UocGVyY2VudCA9IG4oKSAvIG5yb3coZGF0YTFtKSkNCmBgYA0KDQpgYGB7cn0NCiNTZXQgRGFpcnkgUXVlZW4gZm9yIHRvdGFsX2ZhdDsgcGxvdA0KZ2dwbG90KGRhdGEgPSBkYWlyeV9xdWVlbiwgYWVzKHNhbXBsZSA9IHRvdGFsX2ZhdCkpICsgDQogIGdlb21fbGluZShzdGF0ID0gInFxIikNCg0KYGBgDQoNCmBgYHtyfQ0KI1EyIC0gRGFpcnkgUXVlZW47IHRvdGFsX2ZhdDsgdGhlb3JldGljYWwNCmRxbWVhbiA8LSBtZWFuKGRhaXJ5X3F1ZWVuJHRvdGFsX2ZhdCkNCmRxc2QgICA8LSBzZChkYWlyeV9xdWVlbiR0b3RhbF9mYXQpDQpgYGANCg0KYGBge3J9DQoxIC0gcG5vcm0ocSA9IDI1LCBtZWFuID0gZHFtZWFuLCBzZCA9IGRxc2QpDQpgYGANCmBgYHtyfQ0KI1EyIC0gRGFpcnkgUXVlZW4gRW1wZXJpY2FsDQoNCmRhaXJ5X3F1ZWVuICU+JSANCiAgZmlsdGVyKHRvdGFsX2ZhdCA+IDI1KSAlPiUNCiAgc3VtbWFyaXNlKHBlcmNlbnQgPSBuKCkgLyBucm93KGRhaXJ5X3F1ZWVuKSkNCmBgYA0KDQoNCg==