library(tidyverse)
library(openintro)
library(ggplot2)
head(fastfood)
## # A tibble: 6 × 17
##   restaur…¹ item  calor…² cal_fat total…³ sat_fat trans…⁴ chole…⁵ sodium total…⁶
##   <chr>     <chr>   <dbl>   <dbl>   <dbl>   <dbl>   <dbl>   <dbl>  <dbl>   <dbl>
## 1 Mcdonalds Arti…     380      60       7       2     0        95   1110      44
## 2 Mcdonalds Sing…     840     410      45      17     1.5     130   1580      62
## 3 Mcdonalds Doub…    1130     600      67      27     3       220   1920      63
## 4 Mcdonalds Gril…     750     280      31      10     0.5     155   1940      62
## 5 Mcdonalds Cris…     920     410      45      12     0.5     120   1980      81
## 6 Mcdonalds Big …     540     250      28      10     1        80    950      46
## # … with 7 more variables: fiber <dbl>, sugar <dbl>, protein <dbl>,
## #   vit_a <dbl>, vit_c <dbl>, calcium <dbl>, salad <chr>, and abbreviated
## #   variable names ¹​restaurant, ²​calories, ³​total_fat, ⁴​trans_fat,
## #   ⁵​cholesterol, ⁶​total_carb
glimpse(fastfood)
## Rows: 515
## Columns: 17
## $ restaurant  <chr> "Mcdonalds", "Mcdonalds", "Mcdonalds", "Mcdonalds", "Mcdon…
## $ item        <chr> "Artisan Grilled Chicken Sandwich", "Single Bacon Smokehou…
## $ calories    <dbl> 380, 840, 1130, 750, 920, 540, 300, 510, 430, 770, 380, 62…
## $ cal_fat     <dbl> 60, 410, 600, 280, 410, 250, 100, 210, 190, 400, 170, 300,…
## $ total_fat   <dbl> 7, 45, 67, 31, 45, 28, 12, 24, 21, 45, 18, 34, 20, 34, 8, …
## $ sat_fat     <dbl> 2.0, 17.0, 27.0, 10.0, 12.0, 10.0, 5.0, 4.0, 11.0, 21.0, 4…
## $ trans_fat   <dbl> 0.0, 1.5, 3.0, 0.5, 0.5, 1.0, 0.5, 0.0, 1.0, 2.5, 0.0, 1.5…
## $ cholesterol <dbl> 95, 130, 220, 155, 120, 80, 40, 65, 85, 175, 40, 95, 125, …
## $ sodium      <dbl> 1110, 1580, 1920, 1940, 1980, 950, 680, 1040, 1040, 1290, …
## $ total_carb  <dbl> 44, 62, 63, 62, 81, 46, 33, 49, 35, 42, 38, 48, 48, 67, 31…
## $ fiber       <dbl> 3, 2, 3, 2, 4, 3, 2, 3, 2, 3, 2, 3, 3, 5, 2, 2, 3, 3, 5, 2…
## $ sugar       <dbl> 11, 18, 18, 18, 18, 9, 7, 6, 7, 10, 5, 11, 11, 11, 6, 3, 1…
## $ protein     <dbl> 37, 46, 70, 55, 46, 25, 15, 25, 25, 51, 15, 32, 42, 33, 13…
## $ vit_a       <dbl> 4, 6, 10, 6, 6, 10, 10, 0, 20, 20, 2, 10, 10, 10, 2, 4, 6,…
## $ vit_c       <dbl> 20, 20, 20, 25, 20, 2, 2, 4, 4, 6, 0, 10, 20, 15, 2, 6, 15…
## $ calcium     <dbl> 20, 20, 50, 20, 20, 15, 10, 2, 15, 20, 15, 35, 35, 35, 4, …
## $ salad       <chr> "Other", "Other", "Other", "Other", "Other", "Other", "Oth…
summary(fastfood)
##   restaurant            item              calories         cal_fat      
##  Length:515         Length:515         Min.   :  20.0   Min.   :   0.0  
##  Class :character   Class :character   1st Qu.: 330.0   1st Qu.: 120.0  
##  Mode  :character   Mode  :character   Median : 490.0   Median : 210.0  
##                                        Mean   : 530.9   Mean   : 238.8  
##                                        3rd Qu.: 690.0   3rd Qu.: 310.0  
##                                        Max.   :2430.0   Max.   :1270.0  
##                                                                         
##    total_fat         sat_fat         trans_fat      cholesterol    
##  Min.   :  0.00   Min.   : 0.000   Min.   :0.000   Min.   :  0.00  
##  1st Qu.: 14.00   1st Qu.: 4.000   1st Qu.:0.000   1st Qu.: 35.00  
##  Median : 23.00   Median : 7.000   Median :0.000   Median : 60.00  
##  Mean   : 26.59   Mean   : 8.153   Mean   :0.465   Mean   : 72.46  
##  3rd Qu.: 35.00   3rd Qu.:11.000   3rd Qu.:1.000   3rd Qu.: 95.00  
##  Max.   :141.00   Max.   :47.000   Max.   :8.000   Max.   :805.00  
##                                                                    
##      sodium       total_carb         fiber            sugar       
##  Min.   :  15   Min.   :  0.00   Min.   : 0.000   Min.   : 0.000  
##  1st Qu.: 800   1st Qu.: 28.50   1st Qu.: 2.000   1st Qu.: 3.000  
##  Median :1110   Median : 44.00   Median : 3.000   Median : 6.000  
##  Mean   :1247   Mean   : 45.66   Mean   : 4.137   Mean   : 7.262  
##  3rd Qu.:1550   3rd Qu.: 57.00   3rd Qu.: 5.000   3rd Qu.: 9.000  
##  Max.   :6080   Max.   :156.00   Max.   :17.000   Max.   :87.000  
##                                  NA's   :12                       
##     protein           vit_a            vit_c           calcium      
##  Min.   :  1.00   Min.   :  0.00   Min.   :  0.00   Min.   :  0.00  
##  1st Qu.: 16.00   1st Qu.:  4.00   1st Qu.:  4.00   1st Qu.:  8.00  
##  Median : 24.50   Median : 10.00   Median : 10.00   Median : 20.00  
##  Mean   : 27.89   Mean   : 18.86   Mean   : 20.17   Mean   : 24.85  
##  3rd Qu.: 36.00   3rd Qu.: 20.00   3rd Qu.: 30.00   3rd Qu.: 30.00  
##  Max.   :186.00   Max.   :180.00   Max.   :400.00   Max.   :290.00  
##  NA's   :1        NA's   :214      NA's   :210      NA's   :210     
##     salad          
##  Length:515        
##  Class :character  
##  Mode  :character  
##                    
##                    
##                    
## 

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?

fastfood_short<- subset(fastfood, select= c(restaurant, calories, cal_fat))

fastfood_short_new <- fastfood_short %>%
  filter(restaurant %in% c("Mcdonalds", "Dairy Queen"))

mcdonalds <- fastfood_short %>%
  filter(restaurant == "Mcdonalds")
dairy_queen <- fastfood_short%>%
  filter(restaurant == "Dairy Queen")

hist(mcdonalds$cal_fat)

hist(dairy_queen$cal_fat)

Frequency distribution- heights of the bars add up to the total number of observations

ggplot (data = mcdonalds, aes(x = cal_fat))+
  geom_bar(width = 16)
## Warning: `position_stack()` requires non-overlapping x intervals

ggplot (data = dairy_queen, aes(x = cal_fat))+
  geom_bar(width = 16)
## Warning: `position_stack()` requires non-overlapping x intervals

ggplot(data= fastfood_short_new, aes(x = cal_fat, y=, fill = restaurant)) + 
  geom_bar(width = 16)
## Warning: `position_stack()` requires non-overlapping x intervals

While both have means around the same area, Dairy Queens has a more narrow curve and Mcdonalds has more of a skew to the right, meaning it has more high-calorie items than Dairy Queen. Dairy Queen has a more normal curve.

Exercise 2

dqmean <- mean(dairy_queen$cal_fat)
dqsd<- sd(dairy_queen$cal_fat)
mcmean <- mean(mcdonalds$cal_fat)
mcsd<- sd(mcdonalds$cal_fat)
dqmean
## [1] 260.4762
dqsd
## [1] 156.4851
mcmean
## [1] 285.614
mcsd
## [1] 220.8993

Density Histogram- areas of the bars add up to 1

ggplot(data = dairy_queen, aes(x = cal_fat)) +
  geom_blank() +
  geom_histogram(aes(y = ..density..), binwidth = 20) +
  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.

#dnorm is density of normal curve function, specifying that want the curve to have the same m and sd as the column of cal_fat

ggplot(data = mcdonalds, aes(x = cal_fat)) +
  geom_blank() + ##initializes a blank plot
  geom_histogram(aes(y = ..density..), binwidth = 20) +
  stat_function(fun = dnorm, args = c(mean = mcmean, sd = mcsd), col = "green")

Both curves are normally distributed but Dairy Queen is more of a standard normal curve while Mcdonalds’ curve is right-skewed.

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.)

Normal proabibility plot or Q-Q plot (quantile - quantile)

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

Close to diagonal line, waves at the ends show some skewness

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

Not as close to the diagonal, it deviates more and shows a lot more skewness

What do probability plots look like for data that I know came from a normal distribution?

sim_norm <- rnorm(n = nrow(dairy_queen), mean = dqmean, sd = dqsd)
#n is how many numbers you want to generate - same number of menu items in the dq dataset
sim_norm #makng simulated data given parameters
##  [1]  275.66939  500.41939  232.54665  -45.89936  197.76868  477.12807
##  [7]  580.17816  308.56847  393.35349  359.66085   44.04741  393.06487
## [13]  382.53389   65.86187  466.94803  140.00231  502.70394  485.79154
## [19]  236.29400  273.87460  464.91462  336.19600  347.03761  202.65942
## [25]  409.26349  672.68474   97.00805  186.01757  618.57195  297.63477
## [31]  504.21865   97.93330  500.55101 -104.77505   82.77431  261.91415
## [37]  200.78407  398.99426  485.16696  157.17813  219.25026   89.06227

normal probability plots based on each sample created, first is actual sample

qqnormsim(sample = cal_fat, data = dairy_queen)

All of them look fairly straight, with a few outliers, so it’s very close to normal distribution

Plotting dairy queen data and sample from normal distributions

#create colors for legend
col = c("Simulation" = "green", "Dairy Queen" = "red")

#plot dairy queen data and sample from normal distribution
ggplot()+
  geom_line(data = dairy_queen, aes(sample = cal_fat, color = "Dairy Queen"), stat = "qq")+
 #geom_line(aes(sample = sim_norm, color= "Simulation", stat = "qq"))+
  theme_classic()+
  labs(color = "Legend")+
  scale_color_manual(values = col)

ggplot(, aes(sample = sim_norm, color = "Simulation"))+
  geom_line(stat = "qq")

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

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 from fat are nearly normal?

Yes, the two are fairly close to each other, providing evidence that the calories from fat are nearly normal.

Exercise 5

Using the same technique, determine whether or not the calories from McDonald’s menu appear to come from a normal distribution.

Simulated data

sim_norm2 <- rnorm(n = nrow(mcdonalds), mean = mcmean, sd = mcsd)
sim_norm2
##  [1]  249.831220  308.770289   50.816205  196.550232  656.881015  238.400449
##  [7]  148.529039   48.775647  264.026778  284.106897  540.223214  -69.682067
## [13]  231.618779  474.643637  -25.922678  333.002027   44.096180   42.742519
## [19]  520.697014  438.750292  397.165310  403.130463  438.137816  535.892931
## [25]   84.394840  293.871354  490.943858  563.288776   44.937298  337.736413
## [31]   -2.165098  622.099810  460.717433   35.359130 -115.344097  -88.260426
## [37]  566.115811  203.392374  460.359765  387.637232  307.428947  599.946834
## [43]  233.004670  352.260431  228.514933   59.514429  -15.047228  604.758719
## [49]  624.447771  193.460795  514.822414  198.495553  325.779116  355.320473
## [55]  197.925377   99.995363  397.884103

Q-Q plots based on each sample

qqnormsim(sample = cal_fat, data = mcdonalds)

All of the simulated plots look near straight while the plot based on the sample data has a distinct curve that isn’t seen in the simulated plots. The calories from the Mcdonald’s menu do not appear to come from a normal distribution

What is the probability that a randomly chosen Dairy Queen product has more than 600 calories from fat?

1 - pnorm(q = 600, mean = dqmean, sd = dqsd)
## [1] 0.01501523
#calculates Z score and consults Z table, giving area under the normal curve below given value q

1.5% chance of a menu item having more than 600 calories

Calculate probability empirically

dairy_queen%>%
  filter(cal_fat > 600)%>% #determining how many obs fall above 600
  summarize(percent = n()/nrow(dairy_queen))#dividing # of obs over 600 by total sample size
## # A tibble: 1 × 1
##   percent
##     <dbl>
## 1  0.0476

Closer the distribution is to normal, the more accurate theoretical probabilities will be

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?

  1. What is the likelihood of choosing a menu item from McDonalds that has 300 calories or less?
hist(mcdonalds$calories)

cal_mean<- mean(mcdonalds$calories)
cal_sd<- sd(mcdonalds$calories)
cal_mean
## [1] 640.3509
cal_sd
## [1] 410.6961
pnorm(q = 300, mean = cal_mean, sd = cal_sd)
## [1] 0.2036323

There is a 20% chance of picking a menu item that has 300 calories or less

mcdonalds%>%
  filter(calories <= 300)%>% 
  summarize(percent = n()/nrow(mcdonalds))
## # A tibble: 1 × 1
##   percent
##     <dbl>
## 1   0.158

There is a 15% chance of picking a menu item that has 300 calories or less

  1. What is the probability of picking a menu item at Arby’s with more than 40g of protein?
arbys <- fastfood%>%
  select(restaurant, protein)%>%
  filter(restaurant == "Arbys")
head(arbys)
## # A tibble: 6 × 2
##   restaurant protein
##   <chr>        <dbl>
## 1 Arbys           18
## 2 Arbys           18
## 3 Arbys           23
## 4 Arbys           39
## 5 Arbys           38
## 6 Arbys           38
hist(arbys$protein)

mean(arbys$protein)
## [1] 29.25455
amean <- mean(arbys$protein)
asd<- sd(arbys$protein)
amean
## [1] 29.25455
asd
## [1] 12.3861
arbys%>%
  filter(protein > 40)%>%
  summarize(percent = n()/nrow(arbys))
## # A tibble: 1 × 1
##   percent
##     <dbl>
## 1   0.182

There is an 18% chance of picking a menu item with more than 40g of protein

1-pnorm(q = 40, mean = amean, sd = asd)
## [1] 0.1928227

There is an 19% chance of picking a menu item with more than 40g of protein

The question about Arby’s protein had a closer agreement between the two methods, probably because the distribution was closer to a normal curve

###Exercise 7 Out of all the different restaurants, which ones’ distribution is the closest to normal for sodium?

sodium <- fastfood%>%
  select(restaurant, sodium)

ggplot(data = sodium, aes(x = sodium))+
  facet_wrap(~restaurant)+
  geom_blank()+
  geom_histogram(aes( y = ..density..))+
  stat_function(fun = dnorm, args = c(mean = mean(sodium$sodium), sd = sd(sodium$sodium)), col = "tomato")
## `stat_bin()` using `bins = 30`. Pick better value with `binwidth`.

Subway’s distribution is the closest to normal for sodium.

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?

It may not be as smooth as the normal curve because the data is composed of discrete, whole numbers/grams of sodium

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.

bk <-fastfood%>%
  select(restaurant, total_carb)%>%
  filter(restaurant == "Burger King")
head(bk)
## # A tibble: 6 × 2
##   restaurant  total_carb
##   <chr>            <dbl>
## 1 Burger King         21
## 2 Burger King         48
## 3 Burger King         32
## 4 Burger King         28
## 5 Burger King         48
## 6 Burger King         63
ggplot(data = bk, aes(sample = total_carb)) +
  geom_line(stat = "qq")

This plot is normally distributed with a slight left skew

hist(bk$total_carb)

ggplot(data = bk, aes(x = total_carb, y = ))+
  geom_bar()

#Tidyverse

cancer_reg <- readr::read_csv("https://raw.githubusercontent.com/Arnab777as3uj/STAT6021-Cancer-Prediction-Project/master/cancer_reg.csv")
## Rows: 3047 Columns: 34
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ","
## chr  (2): binnedInc, Geography
## dbl (32): avgAnnCount, avgDeathsPerYear, TARGET_deathRate, incidenceRate, me...
## 
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
summary(cancer_reg)
##   avgAnnCount      avgDeathsPerYear TARGET_deathRate incidenceRate   
##  Min.   :    6.0   Min.   :    3    Min.   : 59.7    Min.   : 201.3  
##  1st Qu.:   76.0   1st Qu.:   28    1st Qu.:161.2    1st Qu.: 420.3  
##  Median :  171.0   Median :   61    Median :178.1    Median : 453.5  
##  Mean   :  606.3   Mean   :  186    Mean   :178.7    Mean   : 448.3  
##  3rd Qu.:  518.0   3rd Qu.:  149    3rd Qu.:195.2    3rd Qu.: 480.9  
##  Max.   :38150.0   Max.   :14010    Max.   :362.8    Max.   :1206.9  
##                                                                      
##    medIncome        popEst2015       povertyPercent   studyPerCap     
##  Min.   : 22640   Min.   :     827   Min.   : 3.20   Min.   :   0.00  
##  1st Qu.: 38882   1st Qu.:   11684   1st Qu.:12.15   1st Qu.:   0.00  
##  Median : 45207   Median :   26643   Median :15.90   Median :   0.00  
##  Mean   : 47063   Mean   :  102637   Mean   :16.88   Mean   : 155.40  
##  3rd Qu.: 52492   3rd Qu.:   68671   3rd Qu.:20.40   3rd Qu.:  83.65  
##  Max.   :125635   Max.   :10170292   Max.   :47.40   Max.   :9762.31  
##                                                                       
##   binnedInc           MedianAge      MedianAgeMale   MedianAgeFemale
##  Length:3047        Min.   : 22.30   Min.   :22.40   Min.   :22.30  
##  Class :character   1st Qu.: 37.70   1st Qu.:36.35   1st Qu.:39.10  
##  Mode  :character   Median : 41.00   Median :39.60   Median :42.40  
##                     Mean   : 45.27   Mean   :39.57   Mean   :42.15  
##                     3rd Qu.: 44.00   3rd Qu.:42.50   3rd Qu.:45.30  
##                     Max.   :624.00   Max.   :64.70   Max.   :65.70  
##                                                                     
##   Geography         AvgHouseholdSize PercentMarried   PctNoHS18_24  
##  Length:3047        Min.   :0.0221   Min.   :23.10   Min.   : 0.00  
##  Class :character   1st Qu.:2.3700   1st Qu.:47.75   1st Qu.:12.80  
##  Mode  :character   Median :2.5000   Median :52.40   Median :17.10  
##                     Mean   :2.4797   Mean   :51.77   Mean   :18.22  
##                     3rd Qu.:2.6300   3rd Qu.:56.40   3rd Qu.:22.70  
##                     Max.   :3.9700   Max.   :72.50   Max.   :64.10  
##                                                                     
##    PctHS18_24   PctSomeCol18_24 PctBachDeg18_24   PctHS25_Over  
##  Min.   : 0.0   Min.   : 7.10   Min.   : 0.000   Min.   : 7.50  
##  1st Qu.:29.2   1st Qu.:34.00   1st Qu.: 3.100   1st Qu.:30.40  
##  Median :34.7   Median :40.40   Median : 5.400   Median :35.30  
##  Mean   :35.0   Mean   :40.98   Mean   : 6.158   Mean   :34.80  
##  3rd Qu.:40.7   3rd Qu.:46.40   3rd Qu.: 8.200   3rd Qu.:39.65  
##  Max.   :72.5   Max.   :79.00   Max.   :51.800   Max.   :54.80  
##                 NA's   :2285                                    
##  PctBachDeg25_Over PctEmployed16_Over PctUnemployed16_Over PctPrivateCoverage
##  Min.   : 2.50     Min.   :17.60      Min.   : 0.400       Min.   :22.30     
##  1st Qu.: 9.40     1st Qu.:48.60      1st Qu.: 5.500       1st Qu.:57.20     
##  Median :12.30     Median :54.50      Median : 7.600       Median :65.10     
##  Mean   :13.28     Mean   :54.15      Mean   : 7.852       Mean   :64.35     
##  3rd Qu.:16.10     3rd Qu.:60.30      3rd Qu.: 9.700       3rd Qu.:72.10     
##  Max.   :42.20     Max.   :80.10      Max.   :29.400       Max.   :92.30     
##                    NA's   :152                                               
##  PctPrivateCoverageAlone PctEmpPrivCoverage PctPublicCoverage
##  Min.   :15.70           Min.   :13.5       Min.   :11.20    
##  1st Qu.:41.00           1st Qu.:34.5       1st Qu.:30.90    
##  Median :48.70           Median :41.1       Median :36.30    
##  Mean   :48.45           Mean   :41.2       Mean   :36.25    
##  3rd Qu.:55.60           3rd Qu.:47.7       3rd Qu.:41.55    
##  Max.   :78.90           Max.   :70.7       Max.   :65.10    
##  NA's   :609                                                 
##  PctPublicCoverageAlone    PctWhite         PctBlack          PctAsian      
##  Min.   : 2.60          Min.   : 10.20   Min.   : 0.0000   Min.   : 0.0000  
##  1st Qu.:14.85          1st Qu.: 77.30   1st Qu.: 0.6207   1st Qu.: 0.2542  
##  Median :18.80          Median : 90.06   Median : 2.2476   Median : 0.5498  
##  Mean   :19.24          Mean   : 83.65   Mean   : 9.1080   Mean   : 1.2540  
##  3rd Qu.:23.10          3rd Qu.: 95.45   3rd Qu.:10.5097   3rd Qu.: 1.2210  
##  Max.   :46.60          Max.   :100.00   Max.   :85.9478   Max.   :42.6194  
##                                                                             
##   PctOtherRace     PctMarriedHouseholds   BirthRate     
##  Min.   : 0.0000   Min.   :22.99        Min.   : 0.000  
##  1st Qu.: 0.2952   1st Qu.:47.76        1st Qu.: 4.521  
##  Median : 0.8262   Median :51.67        Median : 5.381  
##  Mean   : 1.9835   Mean   :51.24        Mean   : 5.640  
##  3rd Qu.: 2.1780   3rd Qu.:55.40        3rd Qu.: 6.494  
##  Max.   :41.9303   Max.   :78.08        Max.   :21.326  
## 
cancer_reg<- dplyr::rename(cancer_reg, "cancer_death_rate" = "TARGET_deathRate")
ggplot(cancer_reg, aes(x = povertyPercent, y = cancer_death_rate))+
  geom_point(alpha = 0.25)+
  xlab("Poverty Percentage")+
  ylab("Cancer Death Rate")+
  ggtitle("Cancer Deah vs Poverty by County in US")

LS0tCnRpdGxlOiAiTGFiIDIiCmF1dGhvcjogIk5hemlqYSBBa3RlciIKZGF0ZTogImByIFN5cy5EYXRlKClgIgpvdXRwdXQ6IG9wZW5pbnRybzo6bGFiX3JlcG9ydAotLS0KCmBgYHtyIGxvYWQtcGFja2FnZXMsIG1lc3NhZ2U9RkFMU0V9CmxpYnJhcnkodGlkeXZlcnNlKQpsaWJyYXJ5KG9wZW5pbnRybykKbGlicmFyeShnZ3Bsb3QyKQpoZWFkKGZhc3Rmb29kKQpnbGltcHNlKGZhc3Rmb29kKQpzdW1tYXJ5KGZhc3Rmb29kKQpgYGAKCiMjIyBFeGVyY2lzZSAxCgpNYWtlIGEgcGxvdCAob3IgcGxvdHMpIHRvIHZpc3VhbGl6ZSB0aGUgZGlzdHJpYnV0aW9ucyBvZiB0aGUgYW1vdW50IG9mIGNhbG9yaWVzIGZyb20gZmF0IG9mIHRoZSBvcHRpb25zIGZyb20gdGhlc2UgdHdvIHJlc3RhdXJhbnRzLiBIb3cgZG8gdGhlaXIgY2VudGVycywgc2hhcGVzLCBhbmQgc3ByZWFkcyBjb21wYXJlPwoKCmBgYHtyIGNvZGUtY2h1bmstbGFiZWx9CmZhc3Rmb29kX3Nob3J0PC0gc3Vic2V0KGZhc3Rmb29kLCBzZWxlY3Q9IGMocmVzdGF1cmFudCwgY2Fsb3JpZXMsIGNhbF9mYXQpKQoKZmFzdGZvb2Rfc2hvcnRfbmV3IDwtIGZhc3Rmb29kX3Nob3J0ICU+JQogIGZpbHRlcihyZXN0YXVyYW50ICVpbiUgYygiTWNkb25hbGRzIiwgIkRhaXJ5IFF1ZWVuIikpCgptY2RvbmFsZHMgPC0gZmFzdGZvb2Rfc2hvcnQgJT4lCiAgZmlsdGVyKHJlc3RhdXJhbnQgPT0gIk1jZG9uYWxkcyIpCmRhaXJ5X3F1ZWVuIDwtIGZhc3Rmb29kX3Nob3J0JT4lCiAgZmlsdGVyKHJlc3RhdXJhbnQgPT0gIkRhaXJ5IFF1ZWVuIikKCmhpc3QobWNkb25hbGRzJGNhbF9mYXQpCmhpc3QoZGFpcnlfcXVlZW4kY2FsX2ZhdCkKYGBgCgpGcmVxdWVuY3kgZGlzdHJpYnV0aW9uLSBoZWlnaHRzIG9mIHRoZSBiYXJzIGFkZCB1cCB0byB0aGUgdG90YWwgbnVtYmVyIG9mIG9ic2VydmF0aW9ucwpgYGB7cn0KZ2dwbG90IChkYXRhID0gbWNkb25hbGRzLCBhZXMoeCA9IGNhbF9mYXQpKSsKICBnZW9tX2Jhcih3aWR0aCA9IDE2KQoKZ2dwbG90IChkYXRhID0gZGFpcnlfcXVlZW4sIGFlcyh4ID0gY2FsX2ZhdCkpKwogIGdlb21fYmFyKHdpZHRoID0gMTYpCmBgYAoKYGBge3J9CmdncGxvdChkYXRhPSBmYXN0Zm9vZF9zaG9ydF9uZXcsIGFlcyh4ID0gY2FsX2ZhdCwgeT0sIGZpbGwgPSByZXN0YXVyYW50KSkgKyAKICBnZW9tX2Jhcih3aWR0aCA9IDE2KQpgYGAKV2hpbGUgYm90aCBoYXZlIG1lYW5zIGFyb3VuZCB0aGUgc2FtZSBhcmVhLCBEYWlyeSBRdWVlbnMgaGFzIGEgbW9yZSBuYXJyb3cgY3VydmUgYW5kIE1jZG9uYWxkcyBoYXMgbW9yZSBvZiBhIHNrZXcgdG8gdGhlIHJpZ2h0LCBtZWFuaW5nIGl0IGhhcyBtb3JlIGhpZ2gtY2Fsb3JpZSBpdGVtcyB0aGFuIERhaXJ5IFF1ZWVuLiBEYWlyeSBRdWVlbiBoYXMgYSBtb3JlIG5vcm1hbCBjdXJ2ZS4KCiMjIyBFeGVyY2lzZSAyCgoKYGBge3J9CmRxbWVhbiA8LSBtZWFuKGRhaXJ5X3F1ZWVuJGNhbF9mYXQpCmRxc2Q8LSBzZChkYWlyeV9xdWVlbiRjYWxfZmF0KQptY21lYW4gPC0gbWVhbihtY2RvbmFsZHMkY2FsX2ZhdCkKbWNzZDwtIHNkKG1jZG9uYWxkcyRjYWxfZmF0KQpkcW1lYW4KZHFzZAptY21lYW4KbWNzZApgYGAKRGVuc2l0eSBIaXN0b2dyYW0tIGFyZWFzIG9mIHRoZSBiYXJzIGFkZCB1cCB0byAxCmBgYHtyfQpnZ3Bsb3QoZGF0YSA9IGRhaXJ5X3F1ZWVuLCBhZXMoeCA9IGNhbF9mYXQpKSArCiAgZ2VvbV9ibGFuaygpICsKICBnZW9tX2hpc3RvZ3JhbShhZXMoeSA9IC4uZGVuc2l0eS4uKSwgYmlud2lkdGggPSAyMCkgKwogIHN0YXRfZnVuY3Rpb24oZnVuID0gZG5vcm0sIGFyZ3MgPSBjKG1lYW4gPSBkcW1lYW4sIHNkID0gZHFzZCksIGNvbCA9ICJ0b21hdG8iKQoKI2Rub3JtIGlzIGRlbnNpdHkgb2Ygbm9ybWFsIGN1cnZlIGZ1bmN0aW9uLCBzcGVjaWZ5aW5nIHRoYXQgd2FudCB0aGUgY3VydmUgdG8gaGF2ZSB0aGUgc2FtZSBtIGFuZCBzZCBhcyB0aGUgY29sdW1uIG9mIGNhbF9mYXQKCmdncGxvdChkYXRhID0gbWNkb25hbGRzLCBhZXMoeCA9IGNhbF9mYXQpKSArCiAgZ2VvbV9ibGFuaygpICsgIyNpbml0aWFsaXplcyBhIGJsYW5rIHBsb3QKICBnZW9tX2hpc3RvZ3JhbShhZXMoeSA9IC4uZGVuc2l0eS4uKSwgYmlud2lkdGggPSAyMCkgKwogIHN0YXRfZnVuY3Rpb24oZnVuID0gZG5vcm0sIGFyZ3MgPSBjKG1lYW4gPSBtY21lYW4sIHNkID0gbWNzZCksIGNvbCA9ICJncmVlbiIpCmBgYAoKQm90aCBjdXJ2ZXMgYXJlIG5vcm1hbGx5IGRpc3RyaWJ1dGVkIGJ1dCBEYWlyeSBRdWVlbiBpcyBtb3JlIG9mIGEgc3RhbmRhcmQgbm9ybWFsIGN1cnZlIHdoaWxlIE1jZG9uYWxkcycgY3VydmUgaXMgcmlnaHQtc2tld2VkLgoKIyMjIEV4ZXJjaXNlIDMKTWFrZSBhIG5vcm1hbCBwcm9iYWJpbGl0eSBwbG90IG9mIHNpbV9ub3JtLiBEbyBhbGwgb2YgdGhlIHBvaW50cyBmYWxsIG9uIHRoZSBsaW5lPyBIb3cgZG9lcyB0aGlzIHBsb3QgY29tcGFyZSB0byB0aGUgcHJvYmFiaWxpdHkgcGxvdCBmb3IgdGhlIHJlYWwgZGF0YT8gKFNpbmNlIHNpbV9ub3JtIGlzIG5vdCBhIGRhdGFmcmFtZSwgaXQgY2FuIGJlIHB1dCBkaXJlY3RseSBpbnRvIHRoZSBzYW1wbGUgYXJndW1lbnQgYW5kIHRoZSBkYXRhIGFyZ3VtZW50IGNhbiBiZSBkcm9wcGVkLikKCk5vcm1hbCBwcm9hYmliaWxpdHkgcGxvdCBvciBRLVEgcGxvdCAocXVhbnRpbGUgLSBxdWFudGlsZSkKYGBge3J9CmdncGxvdChkYXRhID0gZGFpcnlfcXVlZW4sIGFlcyhzYW1wbGUgPSBjYWxfZmF0KSkgKwogIGdlb21fbGluZShzdGF0ID0gInFxIikKYGBgCkNsb3NlIHRvIGRpYWdvbmFsIGxpbmUsIHdhdmVzIGF0IHRoZSBlbmRzIHNob3cgc29tZSBza2V3bmVzcwoKYGBge3J9CmdncGxvdChkYXRhID0gbWNkb25hbGRzLCBhZXMoc2FtcGxlID0gY2FsX2ZhdCkpICsKICBnZW9tX2xpbmUoc3RhdCA9ICJxcSIpCmBgYApOb3QgYXMgY2xvc2UgdG8gdGhlIGRpYWdvbmFsLCBpdCBkZXZpYXRlcyBtb3JlIGFuZCBzaG93cyBhIGxvdCBtb3JlIHNrZXduZXNzCgpXaGF0IGRvIHByb2JhYmlsaXR5IHBsb3RzIGxvb2sgbGlrZSBmb3IgZGF0YSB0aGF0IEkga25vdyBjYW1lIGZyb20gYSBub3JtYWwgZGlzdHJpYnV0aW9uPwpgYGB7cn0Kc2ltX25vcm0gPC0gcm5vcm0obiA9IG5yb3coZGFpcnlfcXVlZW4pLCBtZWFuID0gZHFtZWFuLCBzZCA9IGRxc2QpCiNuIGlzIGhvdyBtYW55IG51bWJlcnMgeW91IHdhbnQgdG8gZ2VuZXJhdGUgLSBzYW1lIG51bWJlciBvZiBtZW51IGl0ZW1zIGluIHRoZSBkcSBkYXRhc2V0CnNpbV9ub3JtICNtYWtuZyBzaW11bGF0ZWQgZGF0YSBnaXZlbiBwYXJhbWV0ZXJzCmBgYApub3JtYWwgcHJvYmFiaWxpdHkgcGxvdHMgYmFzZWQgb24gZWFjaCBzYW1wbGUgY3JlYXRlZCwgZmlyc3QgaXMgYWN0dWFsIHNhbXBsZQpgYGB7cn0KcXFub3Jtc2ltKHNhbXBsZSA9IGNhbF9mYXQsIGRhdGEgPSBkYWlyeV9xdWVlbikKYGBgCkFsbCBvZiB0aGVtIGxvb2sgZmFpcmx5IHN0cmFpZ2h0LCB3aXRoIGEgZmV3IG91dGxpZXJzLCBzbyBpdCdzIHZlcnkgY2xvc2UgdG8gbm9ybWFsIGRpc3RyaWJ1dGlvbgoKUGxvdHRpbmcgZGFpcnkgcXVlZW4gZGF0YSBhbmQgc2FtcGxlIGZyb20gbm9ybWFsIGRpc3RyaWJ1dGlvbnMKYGBge3J9CiNjcmVhdGUgY29sb3JzIGZvciBsZWdlbmQKY29sID0gYygiU2ltdWxhdGlvbiIgPSAiZ3JlZW4iLCAiRGFpcnkgUXVlZW4iID0gInJlZCIpCgojcGxvdCBkYWlyeSBxdWVlbiBkYXRhIGFuZCBzYW1wbGUgZnJvbSBub3JtYWwgZGlzdHJpYnV0aW9uCmdncGxvdCgpKwogIGdlb21fbGluZShkYXRhID0gZGFpcnlfcXVlZW4sIGFlcyhzYW1wbGUgPSBjYWxfZmF0LCBjb2xvciA9ICJEYWlyeSBRdWVlbiIpLCBzdGF0ID0gInFxIikrCiAjZ2VvbV9saW5lKGFlcyhzYW1wbGUgPSBzaW1fbm9ybSwgY29sb3I9ICJTaW11bGF0aW9uIiwgc3RhdCA9ICJxcSIpKSsKICB0aGVtZV9jbGFzc2ljKCkrCiAgbGFicyhjb2xvciA9ICJMZWdlbmQiKSsKICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gY29sKQpgYGAKYGBge3J9CmdncGxvdCgsIGFlcyhzYW1wbGUgPSBzaW1fbm9ybSwgY29sb3IgPSAiU2ltdWxhdGlvbiIpKSsKICBnZW9tX2xpbmUoc3RhdCA9ICJxcSIpCmdncGxvdChkYXRhID0gZGFpcnlfcXVlZW4sIGFlcyhzYW1wbGUgPSBjYWxfZmF0LCBjb2xvciA9ICJEYWlyeSBRdWVlbiIpKSsKICBnZW9tX2xpbmUoc3RhdCA9ICJxcSIpCmBgYAoKIyMjIEV4ZXJjaXNlIDQKRG9lcyB0aGUgbm9ybWFsIHByb2JhYmlsaXR5IHBsb3QgZm9yIHRoZSBjYWxvcmllcyBmcm9tIGZhdCBsb29rIHNpbWlsYXIgdG8gdGhlIHBsb3RzIGNyZWF0ZWQgZm9yIHRoZSBzaW11bGF0ZWQgZGF0YT8gVGhhdCBpcywgZG8gdGhlIHBsb3RzIHByb3ZpZGUgZXZpZGVuY2UgdGhhdCB0aGUgY2Fsb3JpZXMgZnJvbSBmYXQgYXJlIG5lYXJseSBub3JtYWw/CgpZZXMsIHRoZSB0d28gYXJlIGZhaXJseSBjbG9zZSB0byBlYWNoIG90aGVyLCBwcm92aWRpbmcgZXZpZGVuY2UgdGhhdCB0aGUgY2Fsb3JpZXMgZnJvbSBmYXQgYXJlIG5lYXJseSBub3JtYWwuCgojIyMgRXhlcmNpc2UgNQpVc2luZyB0aGUgc2FtZSB0ZWNobmlxdWUsIGRldGVybWluZSB3aGV0aGVyIG9yIG5vdCB0aGUgY2Fsb3JpZXMgZnJvbSBNY0RvbmFsZOKAmXMgbWVudSBhcHBlYXIgdG8gY29tZSBmcm9tIGEgbm9ybWFsIGRpc3RyaWJ1dGlvbi4KClNpbXVsYXRlZCBkYXRhCmBgYHtyfQpzaW1fbm9ybTIgPC0gcm5vcm0obiA9IG5yb3cobWNkb25hbGRzKSwgbWVhbiA9IG1jbWVhbiwgc2QgPSBtY3NkKQpzaW1fbm9ybTIKYGBgClEtUSBwbG90cyBiYXNlZCBvbiBlYWNoIHNhbXBsZQpgYGB7cn0KcXFub3Jtc2ltKHNhbXBsZSA9IGNhbF9mYXQsIGRhdGEgPSBtY2RvbmFsZHMpCmBgYApBbGwgb2YgdGhlIHNpbXVsYXRlZCBwbG90cyBsb29rIG5lYXIgc3RyYWlnaHQgd2hpbGUgdGhlIHBsb3QgYmFzZWQgb24gdGhlIHNhbXBsZSBkYXRhIGhhcyBhIGRpc3RpbmN0IGN1cnZlIHRoYXQgaXNuJ3Qgc2VlbiBpbiB0aGUgc2ltdWxhdGVkIHBsb3RzLiBUaGUgY2Fsb3JpZXMgZnJvbSB0aGUgTWNkb25hbGQncyBtZW51IGRvIG5vdCBhcHBlYXIgdG8gY29tZSBmcm9tIGEgbm9ybWFsIGRpc3RyaWJ1dGlvbgoKV2hhdCBpcyB0aGUgcHJvYmFiaWxpdHkgdGhhdCBhIHJhbmRvbWx5IGNob3NlbiBEYWlyeSBRdWVlbiBwcm9kdWN0IGhhcyBtb3JlIHRoYW4gNjAwIGNhbG9yaWVzIGZyb20gZmF0PwpgYGB7cn0KMSAtIHBub3JtKHEgPSA2MDAsIG1lYW4gPSBkcW1lYW4sIHNkID0gZHFzZCkKI2NhbGN1bGF0ZXMgWiBzY29yZSBhbmQgY29uc3VsdHMgWiB0YWJsZSwgZ2l2aW5nIGFyZWEgdW5kZXIgdGhlIG5vcm1hbCBjdXJ2ZSBiZWxvdyBnaXZlbiB2YWx1ZSBxCmBgYAoxLjUlIGNoYW5jZSBvZiBhIG1lbnUgaXRlbSBoYXZpbmcgbW9yZSB0aGFuIDYwMCBjYWxvcmllcwoKCkNhbGN1bGF0ZSBwcm9iYWJpbGl0eSBlbXBpcmljYWxseQpgYGB7cn0KZGFpcnlfcXVlZW4lPiUKICBmaWx0ZXIoY2FsX2ZhdCA+IDYwMCklPiUgI2RldGVybWluaW5nIGhvdyBtYW55IG9icyBmYWxsIGFib3ZlIDYwMAogIHN1bW1hcml6ZShwZXJjZW50ID0gbigpL25yb3coZGFpcnlfcXVlZW4pKSNkaXZpZGluZyAjIG9mIG9icyBvdmVyIDYwMCBieSB0b3RhbCBzYW1wbGUgc2l6ZQpgYGAKQ2xvc2VyIHRoZSBkaXN0cmlidXRpb24gaXMgdG8gbm9ybWFsLCB0aGUgbW9yZSBhY2N1cmF0ZSB0aGVvcmV0aWNhbCBwcm9iYWJpbGl0aWVzIHdpbGwgYmUKCiMjIyBFeGVyY2lzZSA2CldyaXRlIG91dCB0d28gcHJvYmFiaWxpdHkgcXVlc3Rpb25zIHRoYXQgeW91IHdvdWxkIGxpa2UgdG8gYW5zd2VyIGFib3V0IGFueSBvZiB0aGUgcmVzdGF1cmFudHMgaW4gdGhpcyBkYXRhc2V0LiBDYWxjdWxhdGUgdGhvc2UgcHJvYmFiaWxpdGllcyB1c2luZyBib3RoIHRoZSB0aGVvcmV0aWNhbCBub3JtYWwgZGlzdHJpYnV0aW9uIGFzIHdlbGwgYXMgdGhlIGVtcGlyaWNhbCBkaXN0cmlidXRpb24gKGZvdXIgcHJvYmFiaWxpdGllcyBpbiBhbGwpLiBXaGljaCBvbmUgaGFkIGEgY2xvc2VyIGFncmVlbWVudCBiZXR3ZWVuIHRoZSB0d28gbWV0aG9kcz8KCjEuIFdoYXQgaXMgdGhlIGxpa2VsaWhvb2Qgb2YgY2hvb3NpbmcgYSBtZW51IGl0ZW0gZnJvbSBNY0RvbmFsZHMgdGhhdCBoYXMgMzAwIGNhbG9yaWVzIG9yIGxlc3M/CmBgYHtyfQpoaXN0KG1jZG9uYWxkcyRjYWxvcmllcykKYGBgCmBgYHtyfQpjYWxfbWVhbjwtIG1lYW4obWNkb25hbGRzJGNhbG9yaWVzKQpjYWxfc2Q8LSBzZChtY2RvbmFsZHMkY2Fsb3JpZXMpCmNhbF9tZWFuCmNhbF9zZApgYGAKCmBgYHtyfQpwbm9ybShxID0gMzAwLCBtZWFuID0gY2FsX21lYW4sIHNkID0gY2FsX3NkKQpgYGAKVGhlcmUgaXMgYSAyMCUgY2hhbmNlIG9mIHBpY2tpbmcgYSBtZW51IGl0ZW0gdGhhdCBoYXMgMzAwIGNhbG9yaWVzIG9yIGxlc3MKYGBge3J9Cm1jZG9uYWxkcyU+JQogIGZpbHRlcihjYWxvcmllcyA8PSAzMDApJT4lIAogIHN1bW1hcml6ZShwZXJjZW50ID0gbigpL25yb3cobWNkb25hbGRzKSkKYGBgClRoZXJlIGlzIGEgMTUlIGNoYW5jZSBvZiBwaWNraW5nIGEgbWVudSBpdGVtIHRoYXQgaGFzIDMwMCBjYWxvcmllcyBvciBsZXNzCgoyLiBXaGF0IGlzIHRoZSBwcm9iYWJpbGl0eSBvZiBwaWNraW5nIGEgbWVudSBpdGVtIGF0IEFyYnkncyB3aXRoIG1vcmUgdGhhbiA0MGcgb2YgcHJvdGVpbj8KYGBge3J9CmFyYnlzIDwtIGZhc3Rmb29kJT4lCiAgc2VsZWN0KHJlc3RhdXJhbnQsIHByb3RlaW4pJT4lCiAgZmlsdGVyKHJlc3RhdXJhbnQgPT0gIkFyYnlzIikKaGVhZChhcmJ5cykKYGBgCmBgYHtyfQpoaXN0KGFyYnlzJHByb3RlaW4pCm1lYW4oYXJieXMkcHJvdGVpbikKYGBgCmBgYHtyfQphbWVhbiA8LSBtZWFuKGFyYnlzJHByb3RlaW4pCmFzZDwtIHNkKGFyYnlzJHByb3RlaW4pCmFtZWFuCmFzZApgYGAKYGBge3J9CmFyYnlzJT4lCiAgZmlsdGVyKHByb3RlaW4gPiA0MCklPiUKICBzdW1tYXJpemUocGVyY2VudCA9IG4oKS9ucm93KGFyYnlzKSkKYGBgClRoZXJlIGlzIGFuIDE4JSBjaGFuY2Ugb2YgcGlja2luZyBhIG1lbnUgaXRlbSB3aXRoIG1vcmUgdGhhbiA0MGcgb2YgcHJvdGVpbgpgYGB7cn0KMS1wbm9ybShxID0gNDAsIG1lYW4gPSBhbWVhbiwgc2QgPSBhc2QpCmBgYApUaGVyZSBpcyBhbiAxOSUgY2hhbmNlIG9mIHBpY2tpbmcgYSBtZW51IGl0ZW0gd2l0aCBtb3JlIHRoYW4gNDBnIG9mIHByb3RlaW4KClRoZSBxdWVzdGlvbiBhYm91dCBBcmJ5J3MgcHJvdGVpbiBoYWQgYSBjbG9zZXIgYWdyZWVtZW50IGJldHdlZW4gdGhlIHR3byBtZXRob2RzLCBwcm9iYWJseSBiZWNhdXNlIHRoZSBkaXN0cmlidXRpb24gd2FzIGNsb3NlciB0byBhIG5vcm1hbCBjdXJ2ZQoKIyMjRXhlcmNpc2UgNwpPdXQgb2YgYWxsIHRoZSBkaWZmZXJlbnQgcmVzdGF1cmFudHMsIHdoaWNoIG9uZXPigJkgZGlzdHJpYnV0aW9uIGlzIHRoZSBjbG9zZXN0IHRvIG5vcm1hbCBmb3Igc29kaXVtPwpgYGB7cn0Kc29kaXVtIDwtIGZhc3Rmb29kJT4lCiAgc2VsZWN0KHJlc3RhdXJhbnQsIHNvZGl1bSkKCmdncGxvdChkYXRhID0gc29kaXVtLCBhZXMoeCA9IHNvZGl1bSkpKwogIGZhY2V0X3dyYXAofnJlc3RhdXJhbnQpKwogIGdlb21fYmxhbmsoKSsKICBnZW9tX2hpc3RvZ3JhbShhZXMoIHkgPSAuLmRlbnNpdHkuLikpKwogIHN0YXRfZnVuY3Rpb24oZnVuID0gZG5vcm0sIGFyZ3MgPSBjKG1lYW4gPSBtZWFuKHNvZGl1bSRzb2RpdW0pLCBzZCA9IHNkKHNvZGl1bSRzb2RpdW0pKSwgY29sID0gInRvbWF0byIpCmBgYApTdWJ3YXkncyBkaXN0cmlidXRpb24gaXMgdGhlIGNsb3Nlc3QgdG8gbm9ybWFsIGZvciBzb2RpdW0uCgojIyMgRXhlcmNpc2UgOApOb3RlIHRoYXQgc29tZSBvZiB0aGUgbm9ybWFsIHByb2JhYmlsaXR5IHBsb3RzIGZvciBzb2RpdW0gZGlzdHJpYnV0aW9ucyBzZWVtIHRvIGhhdmUgYSBzdGVwd2lzZSBwYXR0ZXJuLiB3aHkgZG8geW91IHRoaW5rIHRoaXMgbWlnaHQgYmUgdGhlIGNhc2U/CgpJdCBtYXkgbm90IGJlIGFzIHNtb290aCBhcyB0aGUgbm9ybWFsIGN1cnZlIGJlY2F1c2UgdGhlIGRhdGEgaXMgY29tcG9zZWQgb2YgZGlzY3JldGUsIHdob2xlIG51bWJlcnMvZ3JhbXMgb2Ygc29kaXVtCgojIyMgRXhlcmNpc2UgOQpBcyB5b3UgY2FuIHNlZSwgbm9ybWFsIHByb2JhYmlsaXR5IHBsb3RzIGNhbiBiZSB1c2VkIGJvdGggdG8gYXNzZXNzIG5vcm1hbGl0eSBhbmQgdmlzdWFsaXplIHNrZXduZXNzLiBNYWtlIGEgbm9ybWFsIHByb2JhYmlsaXR5IHBsb3QgZm9yIHRoZSB0b3RhbCBjYXJib2h5ZHJhdGVzIGZyb20gYSByZXN0YXVyYW50IG9mIHlvdXIgY2hvaWNlLiBCYXNlZCBvbiB0aGlzIG5vcm1hbCBwcm9iYWJpbGl0eSBwbG90LCBpcyB0aGlzIHZhcmlhYmxlIGxlZnQgc2tld2VkLCBzeW1tZXRyaWMsIG9yIHJpZ2h0IHNrZXdlZD8KVXNlIGEgaGlzdG9ncmFtIHRvIGNvbmZpcm0geW91ciBmaW5kaW5ncy4KYGBge3J9CmJrIDwtZmFzdGZvb2QlPiUKICBzZWxlY3QocmVzdGF1cmFudCwgdG90YWxfY2FyYiklPiUKICBmaWx0ZXIocmVzdGF1cmFudCA9PSAiQnVyZ2VyIEtpbmciKQpoZWFkKGJrKQpgYGAKYGBge3J9CmdncGxvdChkYXRhID0gYmssIGFlcyhzYW1wbGUgPSB0b3RhbF9jYXJiKSkgKwogIGdlb21fbGluZShzdGF0ID0gInFxIikKYGBgClRoaXMgcGxvdCBpcyBub3JtYWxseSBkaXN0cmlidXRlZCB3aXRoIGEgc2xpZ2h0IGxlZnQgc2tldwpgYGB7cn0KaGlzdChiayR0b3RhbF9jYXJiKQoKZ2dwbG90KGRhdGEgPSBiaywgYWVzKHggPSB0b3RhbF9jYXJiLCB5ID0gKSkrCiAgZ2VvbV9iYXIoKQpgYGAKCiNUaWR5dmVyc2UgCmBgYHtyfQpjYW5jZXJfcmVnIDwtIHJlYWRyOjpyZWFkX2NzdigiaHR0cHM6Ly9yYXcuZ2l0aHVidXNlcmNvbnRlbnQuY29tL0FybmFiNzc3YXMzdWovU1RBVDYwMjEtQ2FuY2VyLVByZWRpY3Rpb24tUHJvamVjdC9tYXN0ZXIvY2FuY2VyX3JlZy5jc3YiKQpzdW1tYXJ5KGNhbmNlcl9yZWcpCmBgYApgYGB7cn0KY2FuY2VyX3JlZzwtIGRwbHlyOjpyZW5hbWUoY2FuY2VyX3JlZywgImNhbmNlcl9kZWF0aF9yYXRlIiA9ICJUQVJHRVRfZGVhdGhSYXRlIikKYGBgCgpgYGB7cn0KZ2dwbG90KGNhbmNlcl9yZWcsIGFlcyh4ID0gcG92ZXJ0eVBlcmNlbnQsIHkgPSBjYW5jZXJfZGVhdGhfcmF0ZSkpKwogIGdlb21fcG9pbnQoYWxwaGEgPSAwLjI1KSsKICB4bGFiKCJQb3ZlcnR5IFBlcmNlbnRhZ2UiKSsKICB5bGFiKCJDYW5jZXIgRGVhdGggUmF0ZSIpKwogIGdndGl0bGUoIkNhbmNlciBEZWFoIHZzIFBvdmVydHkgYnkgQ291bnR5IGluIFVTIikKYGBgCgo=