Regis University

Group 3 - William Forsythe, John Neville, David Sauther

Prompt 1 - Tossing a coin:

      Each student in a large statistics class of 600 students is asked to toss a fair coin 100 times, count the resulting number of Heads, and construct a 0.95-level confidence interval for the probability of Heads. Assume that each student uses a fair coin and constructs the confidence interval correctly. True or False: We would expect approximately 570 of the confidence intervals to contain the number 0.5.

The Hypotheses are:

  • Ho: The coins are fair.

  • Ha: The coins are not fair.

      We evaluated this question by replicating 60,000 tosses by tossing 600 fair coins 100 times each to get the proportion of heads for each coin, which can be seen below. We used 100 one-sample proportion tests to statistically determine if the results are consistent with the expectation of a fair coin at a 95% confidence interval.

set.seed(25)
total.tosses = 600 * 100  #600 students toss a fair coin 100 times
total.tosses
[1] 60000
binom.tosses = rbinom(600, 100, prob = 0.5) # Calculates the Number of heads tosses
table(binom.tosses)
binom.tosses
36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 
 1  4  1  7 10  3 14 18 27 40 34 43 38 46 49 30 56 43 39 29 19 12  9 
59 60 61 62 63 
11  9  4  1  3 
binom.tosses
  [1] 52 45 44 49 53 60 52 47 50 53 46 45 57 54 61 52 52 46 45 46 45
 [22] 48 52 50 50 45 50 45 52 48 44 52 43 47 53 46 47 52 52 53 53 49
 [43] 50 44 45 40 46 45 53 50 49 52 44 46 46 45 60 51 45 50 49 47 53
 [64] 63 51 50 51 45 44 52 49 49 54 55 46 47 50 54 44 55 51 56 39 48
 [85] 52 40 54 55 63 39 50 47 53 50 45 42 44 52 47 52 55 47 47 44 51
[106] 59 50 48 46 52 50 56 48 55 51 55 52 44 45 54 53 50 48 45 55 43
[127] 45 39 45 48 40 53 52 61 56 44 48 50 46 52 47 60 45 49 50 47 58
[148] 55 45 57 40 49 54 56 51 49 51 49 56 55 53 51 58 45 46 49 52 50
[169] 48 45 58 47 53 54 48 48 49 49 53 42 47 56 52 58 46 49 55 49 45
[190] 48 47 45 49 52 48 37 50 56 48 39 46 48 38 54 50 47 49 45 57 51
[211] 45 42 43 54 41 42 47 50 54 52 50 46 37 56 46 52 52 50 50 54 53
[232] 47 51 57 54 40 44 50 47 52 44 55 47 51 43 57 45 52 40 54 55 53
[253] 46 43 56 48 44 59 48 40 47 54 53 44 46 50 53 46 48 52 49 55 49
[274] 53 48 53 42 54 57 46 53 49 54 56 53 52 53 45 49 49 59 53 42 50
[295] 51 51 59 47 43 54 60 55 45 52 50 60 56 55 48 46 41 56 52 45 50
[316] 51 43 56 59 63 47 50 52 57 47 53 48 39 53 48 45 54 52 53 50 39
[337] 48 48 49 42 47 45 52 53 52 51 47 45 49 56 50 53 52 45 54 49 54
[358] 42 44 54 60 49 53 44 52 52 54 55 46 52 44 52 47 54 48 50 50 54
[379] 51 47 53 45 44 57 54 50 47 55 48 56 47 49 40 55 44 47 53 51 44
[400] 49 51 45 47 50 53 57 52 51 48 50 49 53 55 50 62 48 46 43 48 41
[421] 50 54 55 49 53 44 59 49 43 55 49 44 43 56 52 49 47 37 59 54 43
[442] 47 46 43 46 50 42 55 55 55 51 55 46 52 40 51 54 58 59 51 48 47
[463] 44 49 51 49 43 52 45 50 52 49 57 40 47 49 54 43 48 50 43 44 49
[484] 43 50 54 44 54 55 51 46 60 47 51 52 48 55 51 47 46 58 47 53 48
[505] 49 56 52 54 52 50 54 54 44 39 54 52 46 49 46 53 48 51 53 45 43
[526] 52 59 47 50 48 52 49 54 50 56 47 58 48 60 45 53 53 49 42 49 45
[547] 60 61 53 49 52 58 57 48 53 52 59 42 54 37 47 50 50 36 49 47 54
[568] 51 52 52 57 53 58 46 46 48 45 47 46 46 43 42 49 55 53 42 46 44
[589] 55 52 54 50 59 52 42 50 51 45 56 61
barplot(table(binom.tosses), xlab = 'X = Number of Heads', ylab = 'Frequency' ,col = 'light green')

qqnorm(binom.tosses, col = 'blue')
qqline(binom.tosses, col = "red", lwd = 3)

mean(binom.tosses) # average number heads tossed # sum(binom.tosses)/total.tosses
[1] 49.76167
No.Heads<-sum(binom.tosses) # Number of heads tosses
No.Heads
[1] 29857
summary(binom.tosses)
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
  36.00   46.00   50.00   49.76   53.00   63.00 
sd(table(binom.tosses))
[1] 17.42163
binom.test(c(No.Heads, 60000-No.Heads), p = 0.95)

    Exact binomial test

data:  c(No.Heads, 60000 - No.Heads)
number of successes = 29857, number of trials = 60000, p-value
< 2.2e-16
alternative hypothesis: true probability of success is not equal to 0.95
95 percent confidence interval:
 0.4936078 0.5016257
sample estimates:
probability of success 
             0.4976167 

      Results of the experiment included the mean number of Heads = 49.8%, Sum of heads = 29,857, summary statistics, and the standard deviation = 17.42163. A binomial test, shown in the last segment above, presents a p-value < 2.2e-16, confirmed the previous results with the exact same outcome in which the probability of success was 0.4976167. The problem states the coin is a fair coin, which means that the probability of a bias causing the coin’s true mean to be anything other than 0.5. Plotted results showed a normal distribution, displayed in the qq-plots above, although there were a few potential outliers indicated at the extremes. At least 95%, 570/600 = 0.95, of the tests contain the experiment true mean of 0.5 where Heads results shown in Table 3 were 0.4936078 / 0.5016257 = 0.9840162, or 98.4 %: Therefore, fail to reject the null hypothesis, Ho, that the coins are fair.

Prompt 2 - Are they telling the truth about their light bulbs?:

      A company that manufactures light bulbs has advertised that its 75-watt bulbs burn an average of 800 hours before failing. This problem involved testing the accuracy by consumer watchdog organization of a company leader’s claim that their light bulbs lasted an average of 800 hours. The test was to determine whether the number of hours that the sample lights burned was statically significant different than the claim. Results of the test showed that the light bulb sample set lasted an average of 745.1 hours before failing, with a sample standard deviation of 238.0 hours. The null hypothesis is the claim that the light bulb average lifespan equals 800. The alternative hypothesis is that the light bulb average lifespan does not equal 800. The research question and hypotheses include:

  • RQ: Will the light bulb sample set have an average lifespan like the company claim?

  • Ho: There is no statistically significant difference between the company light bulb average lifespan and the light bulb sample set average lifespan.

  • Ha: There is a statistically significant difference between the company light bulb average lifespan and the light bulb sample set average lifespan.

      The objective of this problem was to compute the critical value at .05 significance level. The Z test statistic – (-2.306723) was less than the critical value – (-1.644854), Table 2. Therefore, at a .05 significance level, reject the claim, Ho, that average light bulb lifetime is 800 hours. A p-value, Table 3, of 0.01053514 was less than the 0.05 significance level, therefore reject the null hypothesis, Ho. Results led to the conclusion that company leaders exaggerated the lifespan of their light bulbs; However, it cannot be concluded whether the exaggeration was deliberate considering the information provided.

Xbar = 745.1         # sample mean (average hours until failure)
Muo = 800            # hypothesized value Ho
pop = 238.0          # population standard deviation (provided above)
N = 100              # sample size
z = (Xbar - Muo)/(pop/sqrt(N))
z                    # test statistic
[1] -2.306723

Next, we compute the critical value at .05 significance level:

significance = .05              # significance Level
z.significance  = qnorm(1-significance)
-z.significance                # critical value
[1] -1.644854

Test statistic of -2.306723 is less than the critical value of -1.644854 Therefore, at a .05 significance level, reject the claim that average light bulb lifetime is 800 hours.

Alternative - we calculate the p-value:

pvalue = pnorm(z)
pvalue                   # lower tail p-value
[1] 0.01053514

The P value is less than the .05 significance level, therefore reject the null hypothesis that Muo = 800. The average lightbulb lifespan is not equal to 800.

Prompt 3 - Interpreting Cereal Metrics and Shelf Displays:

      For this section we evaluate Cereal metrics to answer a few questions about some of our favorite cereal brands. The data contains the following factors for interpretation:

Breakfast cereal variables:

  • cereal name [name]

  • manufacturer (e.g., Kellogg’s) [mfr]

  • type (cold/hot) [type]

  • calories (number) [calories]

  • protein(g) [protein]

  • fat(g) [fat]

  • sodium(mg) [sodium]

  • dietary fiber(g) [fiber]

  • complex carbohydrates(g) [carbo]

  • sugars(g) [sugars]

  • display shelf (1, 2, or 3, counting from the floor) [shelf]

  • potassium(mg) [potass]

  • vitamins & minerals (0, 25, or 100, respectively indicating ‘none added’; ‘enriched, often to 25% FDA recommended’; ‘100% of FDA recommended’) [vitamins]

  • weight (in ounces) of one serving (serving size) [weight]

  • cups per serving [cups]

In our analysis, words in the brackets are the names that we use for our factors.

Question 1:

Do the sugar levels, or any other unhealthy ingredient, correlate with the shelf levels?

      We begin by reading in the data via a csv that was taken from the site: http://lib.stat.cmu.edu/datasets/1993.expo/cereal

Our hypothesis being kids will look at lower shelves and kid’s cereal will have more sugar.

setwd('C:\\Users\\JP\\Documents\\School\\PredictiveAnalytics')
cereal<-read.csv("cereals.csv",header=TRUE)
library("ggplot2")
library("caret")
library("car")

We begin by taking a look at the data presented.

head(cereal)
summary(cereal)
                        name    mfr    type      calories    
 100%_Bran                : 1   A: 1   C:74   Min.   : 50.0  
 100%_Natural_Bran        : 1   G:22   H: 3   1st Qu.:100.0  
 All-Bran                 : 1   K:23          Median :110.0  
 All-Bran_with_Extra_Fiber: 1   N: 6          Mean   :106.9  
 Almond_Delight           : 1   P: 9          3rd Qu.:110.0  
 Apple_Cinnamon_Cheerios  : 1   Q: 8          Max.   :160.0  
 (Other)                  :71   R: 8                         
    protein           fat            sodium          fiber       
 Min.   :1.000   Min.   :0.000   Min.   :  0.0   Min.   : 0.000  
 1st Qu.:2.000   1st Qu.:0.000   1st Qu.:130.0   1st Qu.: 1.000  
 Median :3.000   Median :1.000   Median :180.0   Median : 2.000  
 Mean   :2.545   Mean   :1.013   Mean   :159.7   Mean   : 2.152  
 3rd Qu.:3.000   3rd Qu.:2.000   3rd Qu.:210.0   3rd Qu.: 3.000  
 Max.   :6.000   Max.   :5.000   Max.   :320.0   Max.   :14.000  
                                                                 
     carbo          sugars           shelf           potass      
 Min.   :-1.0   Min.   :-1.000   Min.   :1.000   Min.   : -1.00  
 1st Qu.:12.0   1st Qu.: 3.000   1st Qu.:1.000   1st Qu.: 40.00  
 Median :14.0   Median : 7.000   Median :2.000   Median : 90.00  
 Mean   :14.6   Mean   : 6.922   Mean   :2.208   Mean   : 96.08  
 3rd Qu.:17.0   3rd Qu.:11.000   3rd Qu.:3.000   3rd Qu.:120.00  
 Max.   :23.0   Max.   :15.000   Max.   :3.000   Max.   :330.00  
                                                                 
    vitamins          weight             cups        
 Min.   :  0.00   Min.   :-1.0000   Min.   :-1.0000  
 1st Qu.: 25.00   1st Qu.: 1.0000   1st Qu.: 0.5000  
 Median : 25.00   Median : 1.0000   Median : 0.7500  
 Mean   : 28.25   Mean   : 0.9777   Mean   : 0.5873  
 3rd Qu.: 25.00   3rd Qu.: 1.0000   3rd Qu.: 1.0000  
 Max.   :100.00   Max.   : 1.5000   Max.   : 1.5000  
                                                     
str(cereal)
'data.frame':   77 obs. of  15 variables:
 $ name    : Factor w/ 77 levels "100%_Bran","100%_Natural_Bran",..: 1 2 3 4 5 6 7 8 9 10 ...
 $ mfr     : Factor w/ 7 levels "A","G","K","N",..: 4 6 3 3 7 2 3 2 7 5 ...
 $ type    : Factor w/ 2 levels "C","H": 1 1 1 1 1 1 1 1 1 1 ...
 $ calories: int  70 120 70 50 110 110 110 130 90 90 ...
 $ protein : int  4 3 4 4 2 2 2 3 2 3 ...
 $ fat     : int  1 5 1 0 2 2 0 2 1 0 ...
 $ sodium  : int  130 15 260 140 200 180 125 210 200 210 ...
 $ fiber   : num  10 2 9 14 1 1.5 1 2 4 5 ...
 $ carbo   : num  5 8 7 8 14 10.5 11 18 15 13 ...
 $ sugars  : int  6 8 5 0 8 10 14 8 6 5 ...
 $ shelf   : int  3 3 3 3 3 1 2 3 1 3 ...
 $ potass  : int  280 135 320 330 -1 70 30 100 125 190 ...
 $ vitamins: int  25 0 25 25 25 25 25 25 25 25 ...
 $ weight  : num  1 1 1 1 1 1 1 1.33 1 1 ...
 $ cups    : num  0.33 -1 0.33 0.5 0.75 0.75 1 0.75 0.67 0.67 ...

The summary shows we have -1 in the data. We will remove these -1’s. A -1 signifies that the data is null or not provided.

cereal[cereal == -1] <- NA
cereal=na.omit(cereal)

The first step in our evaluation is to do some exploratory data analysis. We will start with a box plot of the various factors.

qplot(as.factor(shelf),sugars, data = cereal,
      geom = "boxplot", main="Sugar Vs Shelf Level")+
  theme_bw() #versus sugars

It looks like there is a strong correlation between the level of the shelf and the amount of sugar. This is displayed as the boxplot for the second level of shelving is much higher than levels 1 and 3. We will continue on by looking at a similar box plot, instead evaluating the Manufacturer instead of shelf level.

qplot(mfr,sugars, data = cereal,
      geom = "boxplot", main="Sugar Vs Manufacturer Level")+
  theme_bw()

Based on this box plot, certain manufacturers sell products with a larger sugar content. Perhaps they target children? Our next step is to see if higher sugar levels indicate lower nutritional content.

qplot(fiber, sugars, data=cereal)+
  geom_smooth(method = "lm")

The linear model indicates a negative correlation but the plotted points do not appear promising. There are not many cereals with high fiber content, which skews our ability to interpret this model.

qplot(vitamins, sugars, data=cereal)+
  geom_smooth(method = "lm")

This time is no relationship between sugars and vitamins. We suspect the cereal companies add both so they can better sell their products.

qplot(potass, sugars, data=cereal)+
  geom_smooth(method = "lm")

It appears that we have a relationship between potassium levels and sugar levels. For completeness sake, we will print all the plots for continuous variables, its going to be hard to read but it might shine light on important relationships to sugar.

spm(cereal[,c(4:10,12)], reg.line=lm,
    diagonal="histogram",smoother=TRUE, spread=TRUE)

While there are several interesting plot, we have clear correlations with calories, protein, fat and carbohydrates. We will build a model below to test this. We would like to test more thoroughly the relationship between sugar and shelf levels.

cereal.shelf.mod <- aov(sugars ~ as.factor(shelf),
                        data = cereal)
summary(cereal.shelf.mod)
                 Df Sum Sq Mean Sq F value   Pr(>F)    
as.factor(shelf)  2  300.8  150.38   10.35 0.000132 ***
Residuals        62  900.6   14.53                     
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
TukeyHSD(cereal.shelf.mod)
  Tukey multiple comparisons of means
    95% family-wise confidence level

Fit: aov(formula = sugars ~ as.factor(shelf), data = cereal)

$`as.factor(shelf)`
         diff       lwr       upr     p adj
2-1  5.388889  2.338221  8.439557 0.0002199
3-1  1.128352 -1.617833  3.874538 0.5880147
3-2 -4.260536 -7.006722 -1.514351 0.0012168

Based on the output form the above there are a few things that stand out. First the relationship between the shelf level and sugar amounts is significant for levels 1 to 2 and 3 to 2.

Next we interpret an ANOVA for the manufacturer.

cereal.mfr.mod = lm(sugars ~ mfr,
                    data = cereal)
summary(cereal.mfr.mod)

Call:
lm(formula = sugars ~ mfr, data = cereal)

Residuals:
    Min      1Q  Median      3Q     Max 
-7.9048 -3.7778  0.0455  4.0000  7.0952 

Coefficients:
            Estimate Std. Error t value Pr(>|t|)    
(Intercept)  7.95455    0.88608   8.977 1.25e-12 ***
mfrK        -0.04978    1.26794  -0.039   0.9688    
mfrN        -5.95455    2.55791  -2.328   0.0234 *  
mfrP         0.82323    1.64450   0.501   0.6185    
mfrQ        -0.95455    2.05907  -0.464   0.6447    
mfrR        -4.15455    2.05907  -2.018   0.0482 *  
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 4.156 on 59 degrees of freedom
Multiple R-squared:  0.1517,    Adjusted R-squared:  0.07982 
F-statistic:  2.11 on 5 and 59 DF,  p-value: 0.0767
anova(cereal.mfr.mod)
Analysis of Variance Table

Response: sugars
          Df  Sum Sq Mean Sq F value Pr(>F)  
mfr        5  182.26  36.453  2.1104 0.0767 .
Residuals 59 1019.12  17.273                 
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
confint(cereal.mfr.mod)
                 2.5 %      97.5 %
(Intercept)   6.181494  9.72759684
mfrK         -2.586932  2.48736504
mfrN        -11.072904 -0.83618699
mfrP         -2.467412  4.11387642
mfrQ         -5.074745  3.16565363
mfrR         -8.274745 -0.03434637

Based on the results of the ANOVA above, there is no significant relationship between sugar and the manufacturer.

cereal.many.mod = lm(sugars ~ calories+protein+fat+
                       sodium+fiber+carbo+potass,
                     data = cereal)
summary(cereal.many.mod)

Call:
lm(formula = sugars ~ calories + protein + fat + sodium + fiber + 
    carbo + potass, data = cereal)

Residuals:
    Min      1Q  Median      3Q     Max 
-3.2535 -0.5569 -0.0633  0.6403  2.8434 

Coefficients:
             Estimate Std. Error t value Pr(>|t|)    
(Intercept)  4.444157   1.148128   3.871 0.000282 ***
calories     0.198943   0.011241  17.698  < 2e-16 ***
protein     -1.069138   0.165966  -6.442 2.69e-08 ***
fat         -1.896190   0.213634  -8.876 2.46e-12 ***
sodium       0.000183   0.002079   0.088 0.930156    
fiber       -0.622339   0.180278  -3.452 0.001055 ** 
carbo       -0.978777   0.047746 -20.500  < 2e-16 ***
potass       0.017867   0.005931   3.013 0.003859 ** 
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 1.139 on 57 degrees of freedom
Multiple R-squared:  0.9384,    Adjusted R-squared:  0.9308 
F-statistic:   124 on 7 and 57 DF,  p-value: < 2.2e-16

We can see that most of the continuous variables in the data have some sort of relationship with sugar. We can predict 93% of the variance in the sugar data with the continuous variables.

Question 2:

Are any of the manufacturers products differentiated based on the nutrition factors?

Our hypothesis is on an aggregate basis, the products will all be about the same. The alternate hypothesis is that a specific manufacturer will be significantly different than the others based on their cereals nutritional factors.

We begin this analysis with a box plot of the various continuous variables versus manufacturer.

qplot(mfr,calories, data = cereal,
      geom = "boxplot", main="Calories Vs Manufacturer Level")+
  theme_bw()

qplot(mfr,protein, data = cereal,
      geom = "boxplot", main="Protein Vs Manufacturer Level")+
  theme_bw()

qplot(mfr,fat, data = cereal,
      geom = "boxplot", main="Fat Vs Manufacturer Level")+
  theme_bw()

qplot(mfr,sodium, data = cereal,
      geom = "boxplot", main="Sodium Vs Manufacturer Level")+
  theme_bw()

qplot(mfr,vitamins, data = cereal,
      geom = "boxplot", main="Vitamins Vs Manufacturer Level")+
  theme_bw()

On order of the code above it looks like their are differences between manufacturers in the following items:

Protein, Fat, Sodium and vitamins

We will now perform an analysis of variance on each of the nutrition metrics.

cal.mfr.aov <- aov(calories ~ mfr, data = cereal)
summary(cal.mfr.aov)
            Df Sum Sq Mean Sq F value Pr(>F)
mfr          5   2786   557.1   1.881  0.111
Residuals   59  17470   296.1               

Here the p-value is just over .05 meaning we should not evaluate it further as there is unlikely a significant difference.

Next, we take a look at protein versus manufacturer.

protein.mfr.aov <- aov(protein ~ mfr, data = cereal)
summary(protein.mfr.aov,conf.level=0.95)
            Df Sum Sq Mean Sq F value Pr(>F)
mfr          5   5.03   1.005   0.834  0.531
Residuals   59  71.13   1.206               

Here we have no significance right off the bat. Moving forward - fat versus mfr:

fat.mfr.aov <- aov(fat ~ mfr, data = cereal)
summary(fat.mfr.aov)
            Df Sum Sq Mean Sq F value Pr(>F)  
mfr          5   9.76  1.9510   3.198 0.0127 *
Residuals   59  36.00  0.6101                 
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

We have our first case where there manufacturer is significant, we can go further by performing the Tukey test.

TukeyHSD(fat.mfr.aov,conf.level=0.95)
  Tukey multiple comparisons of means
    95% family-wise confidence level

Fit: aov(formula = fat ~ mfr, data = cereal)

$mfr
           diff        lwr         upr     p adj
K-G -0.74458874 -1.4464957 -0.04268176 0.0314295
N-G -1.03030303 -2.4463066  0.38570058 0.2800858
P-G -0.47474747 -1.3851104  0.43561548 0.6428285
Q-G  0.03636364 -1.1034973  1.17622456 0.9999989
R-G -0.96363636 -2.1034973  0.17622456 0.1437442
N-K -0.28571429 -1.7057579  1.13432929 0.9911547
P-K  0.26984127 -0.6467929  1.18647545 0.9528269
Q-K  0.78095238 -0.3639233  1.92582811 0.3496508
R-K -0.21904762 -1.3639233  0.92582811 0.9929857
P-N  0.55555556 -0.9782668  2.08937792 0.8924565
Q-N  1.06666667 -0.6135515  2.74688488 0.4305356
R-N  0.06666667 -1.6135515  1.74688488 0.9999968
Q-P  0.51111111 -0.7721767  1.79439897 0.8477395
R-P -0.48888889 -1.7721767  0.79439897 0.8702683
R-Q -1.00000000 -2.4551117  0.45511166 0.3414106

We have one example of a significant difference between two manufacturers here in K-G. However for the most part, the differences are minimal or not significant.

sodium.mfr.aov <- aov(sodium ~ mfr, data = cereal)
summary(sodium.mfr.aov)
            Df Sum Sq Mean Sq F value Pr(>F)   
mfr          5  92311   18462   4.042 0.0032 **
Residuals   59 269455    4567                  
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

While evaluating sodium, the p-value has come back low, which indicates that there could be a significant difference between manufacturers. Let’s take a look using the same methodology:

TukeyHSD(sodium.mfr.aov,conf.level=0.95)
  Tukey multiple comparisons of means
    95% family-wise confidence level

Fit: aov(formula = sodium ~ mfr, data = cereal)

$mfr
           diff        lwr        upr     p adj
K-G  -25.216450  -85.94295  35.510050 0.8238532
N-G -157.121212 -279.62882 -34.613607 0.0047673
P-G  -54.343434 -133.10481  24.417937 0.3370251
Q-G  -55.454545 -154.07127  43.162175 0.5654902
R-G   27.545455  -71.07127 126.162175 0.9621603
N-K -131.904762 -254.76189  -9.047633 0.0284047
P-K  -29.126984 -108.43092  50.176951 0.8866822
Q-K  -30.238095 -129.28868  68.812489 0.9451902
R-K   52.761905  -46.28868 151.812489 0.6217872
P-N  102.777778  -29.92309 235.478643 0.2181154
Q-N  101.666667  -43.69985 247.033182 0.3222238
R-N  184.666667   39.30015 330.033182 0.0053250
Q-P   -1.111111 -112.13662 109.914399 1.0000000
R-P   81.888889  -29.13662 192.914399 0.2660781
R-Q   83.000000  -42.89109 208.891095 0.3877310

Manufacturer N appears three times in our Tukey test. If we were only evaluating manufactures based on sodium, manufacturer N produces cereals with significantly less sodium from the others. Finally, we can look at vitamins to see if they are significantly different across manufacturers.

vitamins.mfr.aov <- aov(vitamins ~ mfr, data = cereal)
summary(vitamins.mfr.aov)
            Df Sum Sq Mean Sq F value Pr(>F)
mfr          5   2946   589.3   1.354  0.255
Residuals   59  25669   435.1               

Vitamins do not appear to be significantly different across manufacturers.

      Cereal manufacturers create very similar products in terms of their nutrituional value. Even when significance was found in a nutritional group it was between a minimal number of manufacturers. Our strongest case was for sodium, and manufacturer N, but as a whole, nothing stuck out, not enough at least to reject our null hypothesis.

Question 3:

Is the shelf level independent of the manufacturer? Does a manufacturer specialize in cereals that go on certain shelves?

      This question evaluates whether or not a shelf level is dominated by a certain manufacturer or not.

  • RQ: Will there be a manufacturer that produces cereal for a certain shelf level?

  • Ho: There is not a significant relationship between the manufacturer and a cereal’s shelf level.

  • Ha: There is a significant relationship between the manufacturer and a cereal’s shelf level.

      This question can be evaluated using the chisquared test to determine if the there is a relationship between manufacturers and shelf level, but first we need to reorganize the data. When we removed the records with missing values, manufacturer “A” was removed from the set. To perform this analysis correctly, we need to remove that as a factor level in order to avoid skewing the results.

cereal$mfr<-as.character(cereal$mfr)
cereals<-cereal[cereal$mfr!="A",]
cereal$mfr<-as.factor(cereal$mfr)
ManfShelf = table(cereals$mfr, as.factor(cereals$shelf))
ManfShelf
   
     1  2  3
  G  6  7  9
  K  4  7 10
  N  2  0  1
  P  2  1  6
  Q  0  3  2
  R  4  0  1
chisq.test(ManfShelf) 
Chi-squared approximation may be incorrect

    Pearson's Chi-squared test

data:  ManfShelf
X-squared = 15.885, df = 10, p-value = 0.103

We did get a warning, likely because there are too few records, but our p-value would indicate that there is no significant relationship between manufacturer and shelf level. We can try other configurations however, such as evaluating the problem as 3 vs other shelves:

ManfShelf <- cbind(ManfShelf[,"3"], ManfShelf[,"1"] + ManfShelf[,"2"])
ManfShelf
  [,1] [,2]
G    9   13
K   10   11
N    1    2
P    6    3
Q    2    3
R    1    4
chisq.test(ManfShelf)
Chi-squared approximation may be incorrect

    Pearson's Chi-squared test

data:  ManfShelf
X-squared = 3.3937, df = 5, p-value = 0.6395

Again, this yields no significance. We can evaluate 1 and 3 together:

ManfShelf = table(cereals$mfr, as.factor(cereals$shelf))
ManfShelf <- cbind(ManfShelf[,"2"], ManfShelf[,"1"] + ManfShelf[,"3"])
ManfShelf
  [,1] [,2]
G    7   15
K    7   14
N    0    3
P    1    8
Q    3    2
R    0    5
chisq.test(ManfShelf)
Chi-squared approximation may be incorrect

    Pearson's Chi-squared test

data:  ManfShelf
X-squared = 7.4267, df = 5, p-value = 0.1908

Again, nothing, but we do evaluate the last combination of shelves.

ManfShelf = table(cereals$mfr, as.factor(cereals$shelf))
ManfShelf <- cbind(ManfShelf[,"1"], ManfShelf[,"2"] + ManfShelf[,"3"])
ManfShelf
  [,1] [,2]
G    6   16
K    4   17
N    2    1
P    2    7
Q    0    5
R    4    1
chisq.test(ManfShelf)
Chi-squared approximation may be incorrect

    Pearson's Chi-squared test

data:  ManfShelf
X-squared = 11.943, df = 5, p-value = 0.03558

      In our final scenario, we have found something, though we still do not have many records, when we evaluate the problem as a dependence on manufacturer and shelf level, we have determined that a specific dependency does likely exist. In this case we had to group the top two shelves and compare those to the bottom shelf.

      We have rejected our null hypothesis and accepted that there is a relationship between manufacturer and shelf level.

Question 4:

Is a certain cereal nutritionally superior?

      To answer this question, we need to determine what makes a cereal nutritionally superior. The data set for this exercise does come with some recommendations for determining which cereals are the healthiest.

      Adults should consume between 20 and 35 grams of dietary fiber per day. The recommended daily intake (RDI) for calories is 2200 for women and 2900 for men. Calories come in three food components. There are 9 calories per gram of fat, and 4 calories per gram of carbohydrate and protein. Overall, in your diet, no more than 10% of your calories should be consumed from simple carbohydrates (sugars), and no more than 30% should come from fat. The RDI of protein is 50 grams for women and 63 grams for men. The balance of calories should be consumed in the form of complex carbohydrates (starches). The average adult with no defined risk factors or other dietary restrictions should consume between 1800 and 2400 mg of sodium per day.

  • RQ: Is one cereal nutritionally superior to the rest?
  • Ho = No cereal is significantly superior in terms of nutritional value based on national recommended averages.
  • Ha = A cereal is significantly superior in terms of nutritional value based on national recommended averages.

      To answer this question, we need to define some logic in accordance to the guidelines above. The first thing we do, is scale the cereals to match the average number of calories per day, given the guidelines. In scenarios where two different numbers are proved for males and females, we will take the mean of those two numbers.

AllDayCereal<-cereal[,c(1,4:10,12,13)]
AllDayCereal$portions<-2550/AllDayCereal$calories

We continue applying the logic of the description above, to get an objective measurement for measuring nutritional value. To specify, our goal is to match the guideline above. If a cereal contains more than the recommended amount of a nutrient, then it would be considered less nutritional that a cereal that has the recommended amount. Below we apply some distance functions to measure each nutrient.

AllDayCereal[,c(2:10)]<-AllDayCereal[,c(2:10)]*AllDayCereal$portions
AllDayCereal$targetFiber<-c(27.5)
AllDayCereal$targetSugar <- c(0)
AllDayCereal$targetFat<- c(0)
AllDayCereal$targetPotein<- c(56.5)
AllDayCereal$targetCarbs<-c(2550-56.5)
AllDayCereal$targetSodium<- c(2100)
AllDayCereal$fiberMeasure<-abs(AllDayCereal$targetFiber-AllDayCereal$fiber)
AllDayCereal$sugarMeasure<-abs(AllDayCereal$targetSugar-AllDayCereal$sugars)
AllDayCereal$fatMeasure<-abs(AllDayCereal$targetFat-AllDayCereal$fat)
AllDayCereal$proteinMeasure<-abs(AllDayCereal$targetPotein-AllDayCereal$protein)
AllDayCereal$carbsMeasure<-abs(AllDayCereal$targetCarbs-AllDayCereal$carbo)
AllDayCereal$sodiumMeasure<-abs(AllDayCereal$targetSodium-AllDayCereal$sodium)
AllDayCereal$nutrients<-AllDayCereal$fiberMeasure+AllDayCereal$sugarMeasure+AllDayCereal$fatMeasure+AllDayCereal$proteinMeasure+AllDayCereal$carbsMeasure+AllDayCereal$sodiumMeasure-AllDayCereal$vitamins

After compiling the numbers, we take the sum of the absolute value of the differences in recommended vs actual nutrients for each cereal. This is what we will use to see if a cereal is significantly better. Values closest to 0, will be the most in line with the nutritional recommendations above.

boxplot(AllDayCereal$nutrients, col=("gold"),
main="Nutrients", ylab="Nutrient Rating")

From the boxplot we can determine that is unlikely that a cereal performs significantly better, but we can see that there is a cereal that is way off the mark. We can find out which one that is. First we check for normality in the results.

shapiro.test(AllDayCereal$nutrients)

    Shapiro-Wilk normality test

data:  AllDayCereal$nutrients
W = 0.96091, p-value = 0.03826
qqnorm(AllDayCereal$nutrients)

The Shapiro-Wilk normality test could be a warning sign here, but looking at the qq-plot, it seems safe to assume our data is, for the most part, normally distributed.

We then need to evaluate the mean and standard deviation to determine if a cereal falls outside of the confidence intervals.

x<-mean(AllDayCereal$nutrients)
deviation<-sd(AllDayCereal$nutrients)
Lbound<-x-(2*deviation)
Ubound<-x+(2*deviation)
Results<-AllDayCereal[AllDayCereal$nutrients<Lbound,c(1,24)]
Results

      We did not return any results, which means that we have failed to reject the null hypothesis and we cannot determine if one cereal is better than the rest in terms of nutritional values. We can still see which brand did the worst.

Results2<-AllDayCereal[AllDayCereal$nutrients>Ubound,c(1,24)]
Results2

Surprisingly All-Bran performed the worst, and is an outlier in our logical solution. This is a result of having much higher than recommended nutrients at scale.

Question 5:

Is there a relationship between sugars and weight by manufacturer (mfr)?

      To evaluate this question, we will need to determine if there is a correlation between the two factors. Before we can begin, we need to break up our data to look at these relationships for each manufacturer.

  • Ho = There is not a relationship between sugars and weight by manufacturers.

  • Ha = There is a relationship between sugars and weight for at least one manufacturer.

Before we get started, we take a look at the relationship in a graphical format, which can be seen below.

Next, we can determine if there is a relationship at a manufacturer by runnign a correlation test. Below we break up our data by manufacturer and perform the analysis.

unique(cereal$mfr)
[1] N K G R P Q
Levels: G K N P Q R
N<-cereal[cereal$mfr=="N",c(10,14)]
K<-cereal[cereal$mfr=="K",c(10,14)]
G<-cereal[cereal$mfr=="G",c(10,14)]
R<-cereal[cereal$mfr=="R",c(10,14)]
P<-cereal[cereal$mfr=="P",c(10,14)]
Q<-cereal[cereal$mfr=="Q",c(10,14)]
cor.test(N$sugars,N$weight)
the standard deviation is zero

    Pearson's product-moment correlation

data:  N$sugars and N$weight
t = NA, df = 1, p-value = NA
alternative hypothesis: true correlation is not equal to 0
sample estimates:
cor 
 NA 
cor.test(K$sugars,K$weight)

    Pearson's product-moment correlation

data:  K$sugars and K$weight
t = 1.7024, df = 19, p-value = 0.105
alternative hypothesis: true correlation is not equal to 0
95 percent confidence interval:
 -0.08054844  0.68750690
sample estimates:
      cor 
0.3637879 
cor.test(G$sugars,G$weight)

    Pearson's product-moment correlation

data:  G$sugars and G$weight
t = 1.5607, df = 20, p-value = 0.1343
alternative hypothesis: true correlation is not equal to 0
95 percent confidence interval:
 -0.1069780  0.6594864
sample estimates:
      cor 
0.3294914 
cor.test(R$sugars,R$weight)
the standard deviation is zero

    Pearson's product-moment correlation

data:  R$sugars and R$weight
t = NA, df = 3, p-value = NA
alternative hypothesis: true correlation is not equal to 0
95 percent confidence interval:
 NA NA
sample estimates:
cor 
 NA 
cor.test(P$sugars,P$weight)

    Pearson's product-moment correlation

data:  P$sugars and P$weight
t = 1.2535, df = 7, p-value = 0.2503
alternative hypothesis: true correlation is not equal to 0
95 percent confidence interval:
 -0.3297336  0.8504494
sample estimates:
      cor 
0.4281446 
cor.test(Q$sugars,Q$weight)

    Pearson's product-moment correlation

data:  Q$sugars and Q$weight
t = 2.4445, df = 3, p-value = 0.09213
alternative hypothesis: true correlation is not equal to 0
95 percent confidence interval:
 -0.2367708  0.9874004
sample estimates:
      cor 
0.8159417 

      There is a correlation for manufacturer Q, but the p-value is not sufficient enough to prove that there is a correlation. As a result, we do not reject the null hypothesis and accept that there is no relationship between sugar and weight by manufacturer.

LS0tDQp0aXRsZTogIldlZWsgMyBQcm9qZWN0Ig0Kb3V0cHV0OiBodG1sX25vdGVib29rDQphdXRob3JzOiAiV2lsbGlhbSBGb3JzeXRoZSwgSm9obiBOZXZpbGxlLCBEYXZpZCBTYXV0aGVyIg0KLS0tDQoNCg0KIyMjIFJlZ2lzIFVuaXZlcnNpdHkNCiMjIyBHcm91cCAzIC0gV2lsbGlhbSBGb3JzeXRoZSwgSm9obiBOZXZpbGxlLCBEYXZpZCBTYXV0aGVyDQoNCiMjIyMgUHJvbXB0IDEgLSBUb3NzaW5nIGEgY29pbjoNCg0KJm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7RWFjaCBzdHVkZW50IGluIGEgbGFyZ2Ugc3RhdGlzdGljcyBjbGFzcyBvZiA2MDAgc3R1ZGVudHMgaXMgYXNrZWQgdG8gdG9zcyBhIGZhaXIgY29pbiAxMDAgdGltZXMsIGNvdW50IHRoZSByZXN1bHRpbmcgbnVtYmVyIG9mIEhlYWRzLCBhbmQgY29uc3RydWN0IGEgMC45NS1sZXZlbCBjb25maWRlbmNlIGludGVydmFsIGZvciB0aGUgcHJvYmFiaWxpdHkgb2YgSGVhZHMuIEFzc3VtZSB0aGF0IGVhY2ggc3R1ZGVudCB1c2VzIGEgZmFpciBjb2luIGFuZCBjb25zdHJ1Y3RzIHRoZSBjb25maWRlbmNlIGludGVydmFsIGNvcnJlY3RseS4gVHJ1ZSBvciBGYWxzZTogV2Ugd291bGQgZXhwZWN0IGFwcHJveGltYXRlbHkgNTcwIG9mIHRoZSBjb25maWRlbmNlIGludGVydmFscyB0byBjb250YWluIHRoZSBudW1iZXIgMC41Lg0KDQpUaGUgSHlwb3RoZXNlcyBhcmU6DQoNCisgSG86IFRoZSBjb2lucyBhcmUgZmFpci4NCg0KKyBIYTogVGhlIGNvaW5zIGFyZSBub3QgZmFpci4NCg0KJm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7V2UgZXZhbHVhdGVkIHRoaXMgcXVlc3Rpb24gYnkgcmVwbGljYXRpbmcgNjAsMDAwIHRvc3NlcyBieSB0b3NzaW5nIDYwMCBmYWlyIGNvaW5zIDEwMA0KdGltZXMgZWFjaCB0byBnZXQgdGhlIHByb3BvcnRpb24gb2YgaGVhZHMgZm9yIGVhY2ggY29pbiwgd2hpY2ggY2FuIGJlIHNlZW4gYmVsb3cuIFdlIHVzZWQgMTAwIG9uZS1zYW1wbGUNCnByb3BvcnRpb24gdGVzdHMgdG8gc3RhdGlzdGljYWxseSBkZXRlcm1pbmUgaWYgdGhlIHJlc3VsdHMgYXJlIGNvbnNpc3RlbnQgd2l0aCB0aGUgZXhwZWN0YXRpb24gb2YgYQ0KZmFpciBjb2luIGF0IGEgOTUlIGNvbmZpZGVuY2UgaW50ZXJ2YWwuDQoNCg0KYGBge3J9DQoNCnNldC5zZWVkKDI1KQ0KdG90YWwudG9zc2VzID0gNjAwICogMTAwICAjNjAwIHN0dWRlbnRzIHRvc3MgYSBmYWlyIGNvaW4gMTAwIHRpbWVzDQp0b3RhbC50b3NzZXMNCg0KYGBgDQoNCmBgYHtyfQ0KYmlub20udG9zc2VzID0gcmJpbm9tKDYwMCwgMTAwLCBwcm9iID0gMC41KSAjIENhbGN1bGF0ZXMgdGhlIE51bWJlciBvZiBoZWFkcyB0b3NzZXMNCnRhYmxlKGJpbm9tLnRvc3NlcykNCmBgYA0KYGBge3J9DQpiaW5vbS50b3NzZXMNCmBgYA0KYGBge3J9DQpiYXJwbG90KHRhYmxlKGJpbm9tLnRvc3NlcyksIHhsYWIgPSAnWCA9IE51bWJlciBvZiBIZWFkcycsIHlsYWIgPSAnRnJlcXVlbmN5JyAsY29sID0gJ2xpZ2h0IGdyZWVuJykNCmBgYA0KYGBge3J9DQpxcW5vcm0oYmlub20udG9zc2VzLCBjb2wgPSAnYmx1ZScpDQpxcWxpbmUoYmlub20udG9zc2VzLCBjb2wgPSAicmVkIiwgbHdkID0gMykNCmBgYA0KYGBge3J9DQptZWFuKGJpbm9tLnRvc3NlcykgIyBhdmVyYWdlIG51bWJlciBoZWFkcyB0b3NzZWQgIyBzdW0oYmlub20udG9zc2VzKS90b3RhbC50b3NzZXMNCmBgYA0KDQpgYGB7cn0NCk5vLkhlYWRzPC1zdW0oYmlub20udG9zc2VzKSAjIE51bWJlciBvZiBoZWFkcyB0b3NzZXMNCk5vLkhlYWRzDQpgYGANCg0KYGBge3J9DQpzdW1tYXJ5KGJpbm9tLnRvc3NlcykNCmBgYA0KDQpgYGB7cn0NCnNkKHRhYmxlKGJpbm9tLnRvc3NlcykpDQpgYGANCg0KYGBge3J9DQpiaW5vbS50ZXN0KGMoTm8uSGVhZHMsIDYwMDAwLU5vLkhlYWRzKSwgcCA9IDAuOTUpDQoNCmBgYA0KDQombmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDtSZXN1bHRzIG9mIHRoZSBleHBlcmltZW50IGluY2x1ZGVkIHRoZSBtZWFuIG51bWJlciBvZiBIZWFkcyA9IDQ5LjglLCBTdW0gb2YgaGVhZHMgPSAyOSw4NTcsIHN1bW1hcnkgc3RhdGlzdGljcywgYW5kIHRoZSBzdGFuZGFyZCBkZXZpYXRpb24gPSAxNy40MjE2My4gDQpBIGJpbm9taWFsIHRlc3QsIHNob3duIGluIHRoZSBsYXN0IHNlZ21lbnQgYWJvdmUsIHByZXNlbnRzIGEgcC12YWx1ZSAmbHQ7IDIuMmUtMTYsIGNvbmZpcm1lZCB0aGUgcHJldmlvdXMgcmVzdWx0cyB3aXRoIHRoZSBleGFjdCBzYW1lIG91dGNvbWUgaW4gd2hpY2ggdGhlIHByb2JhYmlsaXR5IG9mIHN1Y2Nlc3Mgd2FzIDAuNDk3NjE2Ny4gDQpUaGUgcHJvYmxlbSBzdGF0ZXMgdGhlIGNvaW4gaXMgYSBmYWlyIGNvaW4sIHdoaWNoIG1lYW5zIHRoYXQgdGhlIHByb2JhYmlsaXR5IG9mIGEgYmlhcyBjYXVzaW5nIHRoZSBjb2luknMgdHJ1ZSBtZWFuIHRvIGJlIGFueXRoaW5nIG90aGVyIHRoYW4gMC41LiANClBsb3R0ZWQgcmVzdWx0cyBzaG93ZWQgYSBub3JtYWwgZGlzdHJpYnV0aW9uLCBkaXNwbGF5ZWQgaW4gdGhlIHFxLXBsb3RzIGFib3ZlLCBhbHRob3VnaCB0aGVyZSB3ZXJlIGEgZmV3IHBvdGVudGlhbCBvdXRsaWVycyBpbmRpY2F0ZWQgYXQgdGhlIGV4dHJlbWVzLiANCkF0IGxlYXN0IDk1JSwgNTcwLzYwMCA9IDAuOTUsIG9mIHRoZSB0ZXN0cyBjb250YWluIHRoZQ0KZXhwZXJpbWVudCB0cnVlIG1lYW4gb2YgMC41IHdoZXJlIEhlYWRzIHJlc3VsdHMgc2hvd24gaW4gVGFibGUgMyB3ZXJlIDAuNDkzNjA3OCAvIDAuNTAxNjI1NyA9IDAuOTg0MDE2Miwgb3IgOTguNCAlOiBUaGVyZWZvcmUsIGZhaWwgdG8gcmVqZWN0IHRoZSBudWxsIGh5cG90aGVzaXMsIEhvLCB0aGF0IHRoZSBjb2lucyBhcmUgZmFpci4NCiANCiANCiANCiMjIyMgUHJvbXB0IDIgLSBBcmUgdGhleSB0ZWxsaW5nIHRoZSB0cnV0aCBhYm91dCB0aGVpciBsaWdodCBidWxicz86DQoNCiZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwO0EgY29tcGFueSB0aGF0IG1hbnVmYWN0dXJlcyBsaWdodCBidWxicyBoYXMgYWR2ZXJ0aXNlZCB0aGF0IGl0cyA3NS13YXR0IGJ1bGJzIGJ1cm4gYW4gYXZlcmFnZSBvZiA4MDAgaG91cnMgYmVmb3JlIGZhaWxpbmcuICBUaGlzIHByb2JsZW0gaW52b2x2ZWQgdGVzdGluZyB0aGUgYWNjdXJhY3kgYnkgY29uc3VtZXIgd2F0Y2hkb2cgb3JnYW5pemF0aW9uIG9mIGEgY29tcGFueSBsZWFkZXKScyBjbGFpbSB0aGF0IHRoZWlyIGxpZ2h0IGJ1bGJzIGxhc3RlZCBhbiBhdmVyYWdlIG9mIDgwMCBob3Vycy4gIFRoZSB0ZXN0IHdhcyB0byBkZXRlcm1pbmUgd2hldGhlciB0aGUgbnVtYmVyIG9mIGhvdXJzIHRoYXQgdGhlIHNhbXBsZSBsaWdodHMgYnVybmVkIHdhcyBzdGF0aWNhbGx5IHNpZ25pZmljYW50IGRpZmZlcmVudCB0aGFuIHRoZSBjbGFpbS4gUmVzdWx0cyBvZiB0aGUgdGVzdCBzaG93ZWQgdGhhdCB0aGUgbGlnaHQgYnVsYiBzYW1wbGUgc2V0IGxhc3RlZCBhbiBhdmVyYWdlIG9mIDc0NS4xIGhvdXJzIGJlZm9yZSBmYWlsaW5nLCB3aXRoIGEgc2FtcGxlIHN0YW5kYXJkIGRldmlhdGlvbiBvZiAyMzguMCBob3Vycy4gVGhlIG51bGwgaHlwb3RoZXNpcyBpcyB0aGUgY2xhaW0gdGhhdCB0aGUgbGlnaHQgYnVsYiBhdmVyYWdlIGxpZmVzcGFuIGVxdWFscyA4MDAuICBUaGUgYWx0ZXJuYXRpdmUgaHlwb3RoZXNpcyBpcyB0aGF0IHRoZSBsaWdodCBidWxiIGF2ZXJhZ2UgbGlmZXNwYW4gZG9lcyBub3QgZXF1YWwgODAwLiAgVGhlIHJlc2VhcmNoIHF1ZXN0aW9uIGFuZCBoeXBvdGhlc2VzIGluY2x1ZGU6DQoNCisgUlE6IFdpbGwgdGhlIGxpZ2h0IGJ1bGIgc2FtcGxlIHNldCBoYXZlIGFuIGF2ZXJhZ2UgbGlmZXNwYW4gbGlrZSB0aGUgY29tcGFueSBjbGFpbT8NCg0KKyBIbzogVGhlcmUgaXMgbm8gc3RhdGlzdGljYWxseSBzaWduaWZpY2FudCBkaWZmZXJlbmNlIGJldHdlZW4gdGhlIGNvbXBhbnkgbGlnaHQgYnVsYiBhdmVyYWdlIGxpZmVzcGFuIGFuZCB0aGUgbGlnaHQgYnVsYiBzYW1wbGUgc2V0IGF2ZXJhZ2UgbGlmZXNwYW4uDQoNCisgSGE6IFRoZXJlIGlzIGEgc3RhdGlzdGljYWxseSBzaWduaWZpY2FudCBkaWZmZXJlbmNlIGJldHdlZW4gdGhlIGNvbXBhbnkgbGlnaHQgYnVsYiBhdmVyYWdlIGxpZmVzcGFuIGFuZCB0aGUgbGlnaHQgYnVsYiBzYW1wbGUgc2V0IGF2ZXJhZ2UgbGlmZXNwYW4uDQoNCiZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwO1RoZSBvYmplY3RpdmUgb2YgdGhpcyBwcm9ibGVtIHdhcyB0byBjb21wdXRlIHRoZSBjcml0aWNhbCB2YWx1ZSBhdCAuMDUgc2lnbmlmaWNhbmNlIGxldmVsLiAgVGhlIFogdGVzdCBzdGF0aXN0aWMgliAoLTIuMzA2NzIzKSB3YXMgbGVzcyB0aGFuIHRoZSBjcml0aWNhbCB2YWx1ZSCWICgtMS42NDQ4NTQpLCBUYWJsZSAyLiAgVGhlcmVmb3JlLCBhdCBhIC4wNSBzaWduaWZpY2FuY2UgbGV2ZWwsIHJlamVjdCB0aGUgY2xhaW0sIEhvLCB0aGF0IGF2ZXJhZ2UgbGlnaHQgYnVsYiBsaWZldGltZSBpcyA4MDAgaG91cnMuICBBIHAtdmFsdWUsIFRhYmxlIDMsIG9mIDAuMDEwNTM1MTQgd2FzIGxlc3MgdGhhbiB0aGUgMC4wNSBzaWduaWZpY2FuY2UgbGV2ZWwsIHRoZXJlZm9yZSByZWplY3QgdGhlIG51bGwgaHlwb3RoZXNpcywgSG8uICBSZXN1bHRzIGxlZCB0byB0aGUgY29uY2x1c2lvbiB0aGF0IGNvbXBhbnkgbGVhZGVycyBleGFnZ2VyYXRlZCB0aGUgbGlmZXNwYW4gb2YgdGhlaXIgbGlnaHQgYnVsYnM7IEhvd2V2ZXIsIGl0IGNhbm5vdCBiZSBjb25jbHVkZWQgd2hldGhlciB0aGUgZXhhZ2dlcmF0aW9uIHdhcyBkZWxpYmVyYXRlIGNvbnNpZGVyaW5nIHRoZSBpbmZvcm1hdGlvbiBwcm92aWRlZC4gDQoNCg0KDQpgYGB7cn0NClhiYXIgPSA3NDUuMSAgICAgICAgICMgc2FtcGxlIG1lYW4gKGF2ZXJhZ2UgaG91cnMgdW50aWwgZmFpbHVyZSkNCk11byA9IDgwMCAgICAgICAgICAgICMgaHlwb3RoZXNpemVkIHZhbHVlIEhvDQpwb3AgPSAyMzguMCAgICAgICAgICAjIHBvcHVsYXRpb24gc3RhbmRhcmQgZGV2aWF0aW9uIChwcm92aWRlZCBhYm92ZSkNCk4gPSAxMDAgICAgICAgICAgICAgICMgc2FtcGxlIHNpemUNCnogPSAoWGJhciAtIE11bykvKHBvcC9zcXJ0KE4pKQ0KeiAgICAgICAgICAgICAgICAgICAgIyB0ZXN0IHN0YXRpc3RpYw0KDQpgYGANCg0KTmV4dCwgd2UgY29tcHV0ZSB0aGUgY3JpdGljYWwgdmFsdWUgYXQgLjA1IHNpZ25pZmljYW5jZSBsZXZlbDoNCg0KYGBge3J9DQpzaWduaWZpY2FuY2UgPSAuMDUgICAgICAgICAgICAgICMgc2lnbmlmaWNhbmNlIExldmVsDQp6LnNpZ25pZmljYW5jZSAgPSBxbm9ybSgxLXNpZ25pZmljYW5jZSkNCi16LnNpZ25pZmljYW5jZSAgICAgICAgICAgICAgICAjIGNyaXRpY2FsIHZhbHVlDQpgYGANCg0KICANClRlc3Qgc3RhdGlzdGljIG9mIC0yLjMwNjcyMyBpcyBsZXNzIHRoYW4gdGhlIGNyaXRpY2FsIHZhbHVlIG9mIC0xLjY0NDg1NA0KVGhlcmVmb3JlLCBhdCBhIC4wNSBzaWduaWZpY2FuY2UgbGV2ZWwsIHJlamVjdCB0aGUgY2xhaW0gdGhhdCBhdmVyYWdlIGxpZ2h0IGJ1bGIgbGlmZXRpbWUgaXMgODAwIGhvdXJzLg0KDQpBbHRlcm5hdGl2ZSAtIHdlIGNhbGN1bGF0ZSB0aGUgcC12YWx1ZToNCmBgYHtyfQ0KcHZhbHVlID0gcG5vcm0oeikNCnB2YWx1ZSAgICAgICAgICAgICAgICAgICAjIGxvd2VyIHRhaWwgcC12YWx1ZQ0KYGBgDQoNClRoZSBQIHZhbHVlIGlzIGxlc3MgdGhhbiB0aGUgLjA1IHNpZ25pZmljYW5jZSBsZXZlbCwgdGhlcmVmb3JlIHJlamVjdCB0aGUgbnVsbCBoeXBvdGhlc2lzIHRoYXQgTXVvID0gODAwLg0KVGhlIGF2ZXJhZ2UgbGlnaHRidWxiIGxpZmVzcGFuIGlzIG5vdCBlcXVhbCB0byA4MDAuDQoNCg0KIyMjIyBQcm9tcHQgMyAtIEludGVycHJldGluZyBDZXJlYWwgTWV0cmljcyBhbmQgIFNoZWxmIERpc3BsYXlzOg0KDQombmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDtGb3IgdGhpcyBzZWN0aW9uIHdlIGV2YWx1YXRlIENlcmVhbCBtZXRyaWNzIHRvIGFuc3dlciBhIGZldyBxdWVzdGlvbnMgYWJvdXQgc29tZSBvZiBvdXIgZmF2b3JpdGUgY2VyZWFsIGJyYW5kcy4NClRoZSBkYXRhIGNvbnRhaW5zIHRoZSBmb2xsb3dpbmcgZmFjdG9ycyBmb3IgaW50ZXJwcmV0YXRpb246DQoNCiANCiMjIyMgIEJyZWFrZmFzdCBjZXJlYWwgdmFyaWFibGVzOiANCg0KKyBjZXJlYWwgbmFtZSBbbmFtZV0NCg0KKyBtYW51ZmFjdHVyZXIgKGUuZy4sIEtlbGxvZ2cncykgW21mcl0NCg0KKyB0eXBlIChjb2xkL2hvdCkgW3R5cGVdIA0KDQorIGNhbG9yaWVzIChudW1iZXIpIFtjYWxvcmllc10NCg0KKyBwcm90ZWluKGcpIFtwcm90ZWluXQ0KDQorIGZhdChnKSBbZmF0XQ0KDQorIHNvZGl1bShtZykgW3NvZGl1bV0NCg0KKyBkaWV0YXJ5IGZpYmVyKGcpIFtmaWJlcl0NCg0KKyBjb21wbGV4IGNhcmJvaHlkcmF0ZXMoZykgW2NhcmJvXQ0KDQorIHN1Z2FycyhnKSBbc3VnYXJzXQ0KDQorIGRpc3BsYXkgc2hlbGYgKDEsIDIsIG9yIDMsIGNvdW50aW5nIGZyb20gdGhlIGZsb29yKSBbc2hlbGZdDQoNCisgcG90YXNzaXVtKG1nKSBbcG90YXNzXSANCg0KKyB2aXRhbWlucyAmIG1pbmVyYWxzICgwLCAyNSwgb3IgMTAwLCByZXNwZWN0aXZlbHkgaW5kaWNhdGluZyAnbm9uZSBhZGRlZCc7ICdlbnJpY2hlZCwgb2Z0ZW4gdG8gMjUlIEZEQSByZWNvbW1lbmRlZCc7ICcxMDAlIG9mIEZEQSByZWNvbW1lbmRlZCcpIFt2aXRhbWluc10NCg0KKyB3ZWlnaHQgKGluIG91bmNlcykgb2Ygb25lIHNlcnZpbmcgKHNlcnZpbmcgc2l6ZSkgW3dlaWdodF0NCg0KKyBjdXBzIHBlciBzZXJ2aW5nIFtjdXBzXQ0KDQoNCkluIG91ciBhbmFseXNpcywgd29yZHMgaW4gdGhlIGJyYWNrZXRzIGFyZSB0aGUgbmFtZXMgdGhhdCB3ZSB1c2UgZm9yIG91ciBmYWN0b3JzLg0KDQojIyMjICBRdWVzdGlvbiAxOg0KDQojIyMjIERvIHRoZSBzdWdhciBsZXZlbHMsIG9yIGFueSBvdGhlciB1bmhlYWx0aHkgaW5ncmVkaWVudCwgY29ycmVsYXRlIHdpdGggdGhlIHNoZWxmIGxldmVscz8NCg0KJm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7V2UgYmVnaW4gYnkgcmVhZGluZyBpbiB0aGUgZGF0YSB2aWEgYSBjc3YgdGhhdCB3YXMgdGFrZW4gZnJvbSB0aGUgc2l0ZTogaHR0cDovL2xpYi5zdGF0LmNtdS5lZHUvZGF0YXNldHMvMTk5My5leHBvL2NlcmVhbA0KDQogIE91ciBoeXBvdGhlc2lzIGJlaW5nIGtpZHMgd2lsbCBsb29rIGF0IGxvd2VyIHNoZWx2ZXMgYW5kIGtpZCdzIGNlcmVhbCB3aWxsIGhhdmUgbW9yZSBzdWdhci4NCiAgDQoNCmBgYHtyfQ0KDQpzZXR3ZCgnQzpcXFVzZXJzXFxKUFxcRG9jdW1lbnRzXFxTY2hvb2xcXFByZWRpY3RpdmVBbmFseXRpY3MnKQ0KY2VyZWFsPC1yZWFkLmNzdigiY2VyZWFscy5jc3YiLGhlYWRlcj1UUlVFKQ0KbGlicmFyeSgiZ2dwbG90MiIpDQpsaWJyYXJ5KCJjYXJldCIpDQpsaWJyYXJ5KCJjYXIiKQ0KDQpgYGANCg0KV2UgYmVnaW4gYnkgdGFraW5nIGEgbG9vayBhdCB0aGUgZGF0YSBwcmVzZW50ZWQuDQoNCmBgYHtyfQ0KaGVhZChjZXJlYWwpDQpgYGANCmBgYHtyfQ0Kc3VtbWFyeShjZXJlYWwpDQpgYGANCmBgYHtyfQ0Kc3RyKGNlcmVhbCkNCmBgYA0KDQpUaGUgc3VtbWFyeSBzaG93cyB3ZSBoYXZlIC0xIGluIHRoZSBkYXRhLiAgV2Ugd2lsbCByZW1vdmUgdGhlc2UgLTEncy4gIEEgLTEgc2lnbmlmaWVzIHRoYXQgdGhlIGRhdGEgaXMgbnVsbCBvciBub3QgcHJvdmlkZWQuDQoNCmBgYHtyfQ0KY2VyZWFsW2NlcmVhbCA9PSAtMV0gPC0gTkENCmNlcmVhbD1uYS5vbWl0KGNlcmVhbCkNCmBgYA0KDQpUaGUgZmlyc3Qgc3RlcCBpbiBvdXIgZXZhbHVhdGlvbiBpcyB0byBkbyBzb21lIGV4cGxvcmF0b3J5IGRhdGEgYW5hbHlzaXMuICBXZSB3aWxsIHN0YXJ0IHdpdGggYSBib3ggcGxvdCBvZiB0aGUgdmFyaW91cyBmYWN0b3JzLg0KDQpgYGB7cn0NCnFwbG90KGFzLmZhY3RvcihzaGVsZiksc3VnYXJzLCBkYXRhID0gY2VyZWFsLA0KICAgICAgZ2VvbSA9ICJib3hwbG90IiwgbWFpbj0iU3VnYXIgVnMgU2hlbGYgTGV2ZWwiKSsNCiAgdGhlbWVfYncoKSAjdmVyc3VzIHN1Z2Fycw0KYGBgICANCkl0IGxvb2tzIGxpa2UgdGhlcmUgaXMgYSBzdHJvbmcgY29ycmVsYXRpb24gYmV0d2VlbiB0aGUgbGV2ZWwgb2YgdGhlIHNoZWxmIGFuZCB0aGUgYW1vdW50IG9mIHN1Z2FyLiAgVGhpcyBpcyBkaXNwbGF5ZWQgYXMgdGhlIGJveHBsb3QgZm9yIHRoZSBzZWNvbmQgbGV2ZWwgb2Ygc2hlbHZpbmcgaXMgbXVjaCBoaWdoZXIgdGhhbiBsZXZlbHMgMSBhbmQgMy4NCldlIHdpbGwgY29udGludWUgb24gYnkgbG9va2luZyBhdCBhIHNpbWlsYXIgYm94IHBsb3QsIGluc3RlYWQgZXZhbHVhdGluZyB0aGUgTWFudWZhY3R1cmVyIGluc3RlYWQgb2Ygc2hlbGYgbGV2ZWwuDQpgYGB7cn0NCnFwbG90KG1mcixzdWdhcnMsIGRhdGEgPSBjZXJlYWwsDQogICAgICBnZW9tID0gImJveHBsb3QiLCBtYWluPSJTdWdhciBWcyBNYW51ZmFjdHVyZXIgTGV2ZWwiKSsNCiAgdGhlbWVfYncoKQ0KYGBgDQpCYXNlZCBvbiB0aGlzIGJveCBwbG90LCBjZXJ0YWluIG1hbnVmYWN0dXJlcnMgc2VsbCBwcm9kdWN0cyB3aXRoIGEgbGFyZ2VyIHN1Z2FyIGNvbnRlbnQuIFBlcmhhcHMgdGhleSB0YXJnZXQgY2hpbGRyZW4/DQpPdXIgbmV4dCBzdGVwIGlzIHRvIHNlZSBpZiBoaWdoZXIgc3VnYXIgbGV2ZWxzIGluZGljYXRlIGxvd2VyIG51dHJpdGlvbmFsIGNvbnRlbnQuDQpgYGB7cn0NCnFwbG90KGZpYmVyLCBzdWdhcnMsIGRhdGE9Y2VyZWFsKSsNCiAgZ2VvbV9zbW9vdGgobWV0aG9kID0gImxtIikNCmBgYA0KVGhlIGxpbmVhciBtb2RlbCBpbmRpY2F0ZXMgYSBuZWdhdGl2ZSBjb3JyZWxhdGlvbiBidXQgdGhlIHBsb3R0ZWQgcG9pbnRzIGRvIG5vdCBhcHBlYXIgcHJvbWlzaW5nLiAgVGhlcmUgYXJlIG5vdCBtYW55IGNlcmVhbHMgd2l0aCBoaWdoIGZpYmVyIGNvbnRlbnQsIHdoaWNoIHNrZXdzIG91ciBhYmlsaXR5IHRvIGludGVycHJldCB0aGlzIG1vZGVsLg0KDQoNCmBgYHtyfQ0KcXBsb3Qodml0YW1pbnMsIHN1Z2FycywgZGF0YT1jZXJlYWwpKw0KICBnZW9tX3Ntb290aChtZXRob2QgPSAibG0iKQ0KYGBgDQpUaGlzIHRpbWUgaXMgbm8gcmVsYXRpb25zaGlwIGJldHdlZW4gc3VnYXJzIGFuZCB2aXRhbWlucy4gV2Ugc3VzcGVjdCB0aGUgY2VyZWFsIGNvbXBhbmllcyBhZGQgYm90aCBzbyB0aGV5IGNhbiBiZXR0ZXIgc2VsbCB0aGVpciBwcm9kdWN0cy4NCmBgYHtyfQ0KcXBsb3QocG90YXNzLCBzdWdhcnMsIGRhdGE9Y2VyZWFsKSsNCiAgZ2VvbV9zbW9vdGgobWV0aG9kID0gImxtIikNCmBgYA0KSXQgYXBwZWFycyB0aGF0IHdlIGhhdmUgYSByZWxhdGlvbnNoaXAgYmV0d2VlbiBwb3Rhc3NpdW0gbGV2ZWxzIGFuZCBzdWdhciBsZXZlbHMuDQpGb3IgY29tcGxldGVuZXNzIHNha2UsIHdlIHdpbGwgcHJpbnQgYWxsIHRoZSBwbG90cyBmb3IgY29udGludW91cyB2YXJpYWJsZXMsIGl0cyBnb2luZyB0byBiZSBoYXJkIHRvIHJlYWQgYnV0IGl0IG1pZ2h0IHNoaW5lIGxpZ2h0IG9uIGltcG9ydGFudCByZWxhdGlvbnNoaXBzIHRvIHN1Z2FyLg0KYGBge3J9DQpzcG0oY2VyZWFsWyxjKDQ6MTAsMTIpXSwgcmVnLmxpbmU9bG0sDQogICAgZGlhZ29uYWw9Imhpc3RvZ3JhbSIsc21vb3RoZXI9VFJVRSwgc3ByZWFkPVRSVUUpDQpgYGANCldoaWxlIHRoZXJlIGFyZSBzZXZlcmFsIGludGVyZXN0aW5nIHBsb3QsIHdlIGhhdmUgY2xlYXIgY29ycmVsYXRpb25zIHdpdGggY2Fsb3JpZXMsIHByb3RlaW4sIGZhdCBhbmQgY2FyYm9oeWRyYXRlcy4gV2Ugd2lsbCBidWlsZCBhIG1vZGVsIGJlbG93IHRvIHRlc3QgdGhpcy4NCldlIHdvdWxkIGxpa2UgdG8gdGVzdCBtb3JlIHRob3JvdWdobHkgdGhlIHJlbGF0aW9uc2hpcCBiZXR3ZWVuIHN1Z2FyIGFuZCBzaGVsZiBsZXZlbHMuDQpgYGB7cn0NCmNlcmVhbC5zaGVsZi5tb2QgPC0gYW92KHN1Z2FycyB+IGFzLmZhY3RvcihzaGVsZiksDQogICAgICAgICAgICAgICAgICAgICAgICBkYXRhID0gY2VyZWFsKQ0Kc3VtbWFyeShjZXJlYWwuc2hlbGYubW9kKQ0KYGBgDQpgYGB7cn0NClR1a2V5SFNEKGNlcmVhbC5zaGVsZi5tb2QpDQpgYGANCkJhc2VkIG9uIHRoZSBvdXRwdXQgZm9ybSB0aGUgYWJvdmUgdGhlcmUgYXJlIGEgZmV3IHRoaW5ncyB0aGF0IHN0YW5kIG91dC4NCkZpcnN0IHRoZSByZWxhdGlvbnNoaXAgYmV0d2VlbiB0aGUgc2hlbGYgbGV2ZWwgYW5kIHN1Z2FyIGFtb3VudHMgaXMgc2lnbmlmaWNhbnQgZm9yIGxldmVscyAxIHRvIDIgYW5kIDMgdG8gMi4NCg0KTmV4dCB3ZSBpbnRlcnByZXQgYW4gQU5PVkEgZm9yIHRoZSBtYW51ZmFjdHVyZXIuDQpgYGB7cn0NCmNlcmVhbC5tZnIubW9kID0gbG0oc3VnYXJzIH4gbWZyLA0KICAgICAgICAgICAgICAgICAgICBkYXRhID0gY2VyZWFsKQ0Kc3VtbWFyeShjZXJlYWwubWZyLm1vZCkNCmBgYA0KYGBge3J9DQphbm92YShjZXJlYWwubWZyLm1vZCkNCmBgYA0KYGBge3J9DQpjb25maW50KGNlcmVhbC5tZnIubW9kKQ0KYGBgDQpCYXNlZCBvbiB0aGUgcmVzdWx0cyBvZiB0aGUgQU5PVkEgYWJvdmUsIHRoZXJlIGlzIG5vIHNpZ25pZmljYW50IHJlbGF0aW9uc2hpcCBiZXR3ZWVuIHN1Z2FyIGFuZCB0aGUgbWFudWZhY3R1cmVyLg0KDQpgYGB7cn0NCmNlcmVhbC5tYW55Lm1vZCA9IGxtKHN1Z2FycyB+IGNhbG9yaWVzK3Byb3RlaW4rZmF0Kw0KICAgICAgICAgICAgICAgICAgICAgICBzb2RpdW0rZmliZXIrY2FyYm8rcG90YXNzLA0KICAgICAgICAgICAgICAgICAgICAgZGF0YSA9IGNlcmVhbCkNCnN1bW1hcnkoY2VyZWFsLm1hbnkubW9kKQ0KYGBgDQoNCldlIGNhbiBzZWUgdGhhdCBtb3N0IG9mIHRoZSBjb250aW51b3VzIHZhcmlhYmxlcyBpbiB0aGUgZGF0YSBoYXZlIHNvbWUgc29ydCBvZiByZWxhdGlvbnNoaXAgd2l0aCBzdWdhci4NCldlIGNhbiBwcmVkaWN0IDkzJSBvZiB0aGUgdmFyaWFuY2UgaW4gdGhlIHN1Z2FyIGRhdGEgd2l0aCB0aGUgY29udGludW91cyB2YXJpYWJsZXMuDQogDQogDQogDQogDQojIyMjICBRdWVzdGlvbiAyOg0KIyMjIyBBcmUgYW55IG9mIHRoZSBtYW51ZmFjdHVyZXJzIHByb2R1Y3RzIGRpZmZlcmVudGlhdGVkIGJhc2VkIG9uIHRoZSBudXRyaXRpb24gZmFjdG9ycz8NCg0KT3VyIGh5cG90aGVzaXMgaXMgb24gYW4gYWdncmVnYXRlIGJhc2lzLCB0aGUgcHJvZHVjdHMgd2lsbCBhbGwgYmUgYWJvdXQgdGhlIHNhbWUuDQpUaGUgYWx0ZXJuYXRlIGh5cG90aGVzaXMgaXMgdGhhdCBhIHNwZWNpZmljIG1hbnVmYWN0dXJlciB3aWxsIGJlIHNpZ25pZmljYW50bHkgZGlmZmVyZW50IHRoYW4gdGhlIG90aGVycyBiYXNlZCBvbiB0aGVpciBjZXJlYWxzIG51dHJpdGlvbmFsIGZhY3RvcnMuIA0KDQpXZSBiZWdpbiB0aGlzIGFuYWx5c2lzIHdpdGggYSBib3ggcGxvdCBvZiB0aGUgdmFyaW91cyBjb250aW51b3VzIHZhcmlhYmxlcyB2ZXJzdXMgbWFudWZhY3R1cmVyLg0KDQpgYGB7cn0NCnFwbG90KG1mcixjYWxvcmllcywgZGF0YSA9IGNlcmVhbCwNCiAgICAgIGdlb20gPSAiYm94cGxvdCIsIG1haW49IkNhbG9yaWVzIFZzIE1hbnVmYWN0dXJlciBMZXZlbCIpKw0KICB0aGVtZV9idygpDQpxcGxvdChtZnIscHJvdGVpbiwgZGF0YSA9IGNlcmVhbCwNCiAgICAgIGdlb20gPSAiYm94cGxvdCIsIG1haW49IlByb3RlaW4gVnMgTWFudWZhY3R1cmVyIExldmVsIikrDQogIHRoZW1lX2J3KCkNCnFwbG90KG1mcixmYXQsIGRhdGEgPSBjZXJlYWwsDQogICAgICBnZW9tID0gImJveHBsb3QiLCBtYWluPSJGYXQgVnMgTWFudWZhY3R1cmVyIExldmVsIikrDQogIHRoZW1lX2J3KCkNCnFwbG90KG1mcixzb2RpdW0sIGRhdGEgPSBjZXJlYWwsDQogICAgICBnZW9tID0gImJveHBsb3QiLCBtYWluPSJTb2RpdW0gVnMgTWFudWZhY3R1cmVyIExldmVsIikrDQogIHRoZW1lX2J3KCkNCnFwbG90KG1mcix2aXRhbWlucywgZGF0YSA9IGNlcmVhbCwNCiAgICAgIGdlb20gPSAiYm94cGxvdCIsIG1haW49IlZpdGFtaW5zIFZzIE1hbnVmYWN0dXJlciBMZXZlbCIpKw0KICB0aGVtZV9idygpDQpgYGANCk9uIG9yZGVyIG9mIHRoZSBjb2RlIGFib3ZlIGl0IGxvb2tzIGxpa2UgdGhlaXIgYXJlIGRpZmZlcmVuY2VzIGJldHdlZW4gbWFudWZhY3R1cmVycyBpbiB0aGUgZm9sbG93aW5nIGl0ZW1zOg0KDQpQcm90ZWluLCBGYXQsIFNvZGl1bSBhbmQgdml0YW1pbnMNCg0KV2Ugd2lsbCBub3cgcGVyZm9ybSBhbiBhbmFseXNpcyBvZiB2YXJpYW5jZSBvbiBlYWNoIG9mIHRoZSBudXRyaXRpb24gbWV0cmljcy4NCg0KYGBge3J9DQpjYWwubWZyLmFvdiA8LSBhb3YoY2Fsb3JpZXMgfiBtZnIsIGRhdGEgPSBjZXJlYWwpDQpzdW1tYXJ5KGNhbC5tZnIuYW92KQ0KYGBgDQoNCkhlcmUgdGhlIHAtdmFsdWUgaXMganVzdCBvdmVyIC4wNSBtZWFuaW5nIHdlIHNob3VsZCBub3QgZXZhbHVhdGUgaXQgZnVydGhlciBhcyB0aGVyZSBpcyB1bmxpa2VseSBhIHNpZ25pZmljYW50IGRpZmZlcmVuY2UuIA0KDQpOZXh0LCB3ZSB0YWtlIGEgbG9vayBhdCBwcm90ZWluIHZlcnN1cyBtYW51ZmFjdHVyZXIuDQoNCmBgYHtyfQ0KcHJvdGVpbi5tZnIuYW92IDwtIGFvdihwcm90ZWluIH4gbWZyLCBkYXRhID0gY2VyZWFsKQ0Kc3VtbWFyeShwcm90ZWluLm1mci5hb3YsY29uZi5sZXZlbD0wLjk1KQ0KYGBgDQpIZXJlIHdlIGhhdmUgbm8gc2lnbmlmaWNhbmNlIHJpZ2h0IG9mZiB0aGUgYmF0LiAgTW92aW5nIGZvcndhcmQgLSBmYXQgdmVyc3VzIG1mcjoNCmBgYHtyfQ0KZmF0Lm1mci5hb3YgPC0gYW92KGZhdCB+IG1mciwgZGF0YSA9IGNlcmVhbCkNCnN1bW1hcnkoZmF0Lm1mci5hb3YpDQpgYGANCldlIGhhdmUgb3VyIGZpcnN0IGNhc2Ugd2hlcmUgdGhlcmUgbWFudWZhY3R1cmVyIGlzIHNpZ25pZmljYW50LCB3ZSBjYW4gZ28gZnVydGhlciBieSBwZXJmb3JtaW5nIHRoZSBUdWtleSB0ZXN0Lg0KYGBge3J9DQpUdWtleUhTRChmYXQubWZyLmFvdixjb25mLmxldmVsPTAuOTUpDQpgYGANCldlIGhhdmUgb25lIGV4YW1wbGUgb2YgYSBzaWduaWZpY2FudCBkaWZmZXJlbmNlIGJldHdlZW4gdHdvIG1hbnVmYWN0dXJlcnMgaGVyZSBpbiBLLUcuICBIb3dldmVyIGZvciB0aGUgbW9zdCBwYXJ0LCB0aGUgZGlmZmVyZW5jZXMgYXJlIG1pbmltYWwgb3Igbm90IHNpZ25pZmljYW50Lg0KDQpgYGB7cn0NCnNvZGl1bS5tZnIuYW92IDwtIGFvdihzb2RpdW0gfiBtZnIsIGRhdGEgPSBjZXJlYWwpDQpzdW1tYXJ5KHNvZGl1bS5tZnIuYW92KQ0KYGBgDQpXaGlsZSBldmFsdWF0aW5nIHNvZGl1bSwgdGhlIHAtdmFsdWUgaGFzIGNvbWUgYmFjayBsb3csIHdoaWNoIGluZGljYXRlcyB0aGF0IHRoZXJlIGNvdWxkIGJlIGEgc2lnbmlmaWNhbnQgZGlmZmVyZW5jZSBiZXR3ZWVuIG1hbnVmYWN0dXJlcnMuIA0KTGV0J3MgdGFrZSBhIGxvb2sgdXNpbmcgdGhlIHNhbWUgbWV0aG9kb2xvZ3k6DQpgYGB7cn0NClR1a2V5SFNEKHNvZGl1bS5tZnIuYW92LGNvbmYubGV2ZWw9MC45NSkNCmBgYA0KTWFudWZhY3R1cmVyIE4gYXBwZWFycyB0aHJlZSB0aW1lcyBpbiBvdXIgVHVrZXkgdGVzdC4gIElmIHdlIHdlcmUgb25seSBldmFsdWF0aW5nIG1hbnVmYWN0dXJlcyBiYXNlZCBvbiBzb2RpdW0sIG1hbnVmYWN0dXJlciBOIHByb2R1Y2VzIGNlcmVhbHMgd2l0aCBzaWduaWZpY2FudGx5IGxlc3Mgc29kaXVtIGZyb20gdGhlIG90aGVycy4NCkZpbmFsbHksIHdlIGNhbiBsb29rIGF0IHZpdGFtaW5zIHRvIHNlZSBpZiB0aGV5IGFyZSBzaWduaWZpY2FudGx5IGRpZmZlcmVudCBhY3Jvc3MgbWFudWZhY3R1cmVycy4NCmBgYHtyfQ0Kdml0YW1pbnMubWZyLmFvdiA8LSBhb3Yodml0YW1pbnMgfiBtZnIsIGRhdGEgPSBjZXJlYWwpDQpzdW1tYXJ5KHZpdGFtaW5zLm1mci5hb3YpDQpgYGANClZpdGFtaW5zIGRvIG5vdCBhcHBlYXIgdG8gYmUgc2lnbmlmaWNhbnRseSBkaWZmZXJlbnQgYWNyb3NzIG1hbnVmYWN0dXJlcnMuDQoNCiZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwO0NlcmVhbCBtYW51ZmFjdHVyZXJzIGNyZWF0ZSB2ZXJ5IHNpbWlsYXIgcHJvZHVjdHMgaW4gdGVybXMgb2YgdGhlaXIgbnV0cml0dWlvbmFsIHZhbHVlLiAgRXZlbiB3aGVuIHNpZ25pZmljYW5jZSB3YXMgZm91bmQgaW4gYSBudXRyaXRpb25hbCBncm91cCBpdCB3YXMgYmV0d2VlbiBhIG1pbmltYWwgbnVtYmVyIG9mIG1hbnVmYWN0dXJlcnMuICBPdXIgc3Ryb25nZXN0IGNhc2Ugd2FzIGZvciBzb2RpdW0sIGFuZCBtYW51ZmFjdHVyZXIgTiwgYnV0IGFzIGEgd2hvbGUsIG5vdGhpbmcgc3R1Y2sgb3V0LCBub3QgZW5vdWdoIGF0IGxlYXN0IHRvIHJlamVjdCBvdXIgbnVsbCBoeXBvdGhlc2lzLg0KDQoNCiMjIyMgIFF1ZXN0aW9uIDM6DQojIyMjIElzIHRoZSBzaGVsZiBsZXZlbCBpbmRlcGVuZGVudCBvZiB0aGUgbWFudWZhY3R1cmVyPyAgRG9lcyBhIG1hbnVmYWN0dXJlciBzcGVjaWFsaXplIGluIGNlcmVhbHMgdGhhdCBnbyBvbiBjZXJ0YWluIHNoZWx2ZXM/DQoNCiZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwO1RoaXMgcXVlc3Rpb24gZXZhbHVhdGVzIHdoZXRoZXIgb3Igbm90IGEgc2hlbGYgbGV2ZWwgaXMgZG9taW5hdGVkIGJ5IGEgY2VydGFpbiBtYW51ZmFjdHVyZXIgb3Igbm90Lg0KDQorIFJROiBXaWxsIHRoZXJlIGJlIGEgbWFudWZhY3R1cmVyIHRoYXQgcHJvZHVjZXMgY2VyZWFsIGZvciBhIGNlcnRhaW4gc2hlbGYgbGV2ZWw/DQoNCisgSG86IFRoZXJlIGlzIG5vdCBhIHNpZ25pZmljYW50IHJlbGF0aW9uc2hpcCBiZXR3ZWVuIHRoZSBtYW51ZmFjdHVyZXIgYW5kIGEgY2VyZWFsJ3Mgc2hlbGYgbGV2ZWwuDQoNCisgSGE6IFRoZXJlIGlzIGEgc2lnbmlmaWNhbnQgcmVsYXRpb25zaGlwIGJldHdlZW4gdGhlIG1hbnVmYWN0dXJlciBhbmQgYSBjZXJlYWwncyBzaGVsZiBsZXZlbC4NCg0KJm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7VGhpcyBxdWVzdGlvbiBjYW4gYmUgZXZhbHVhdGVkIHVzaW5nIHRoZSBjaGlzcXVhcmVkIHRlc3QgdG8gZGV0ZXJtaW5lIGlmIHRoZSB0aGVyZSBpcyBhIHJlbGF0aW9uc2hpcCBiZXR3ZWVuIG1hbnVmYWN0dXJlcnMgYW5kIHNoZWxmIGxldmVsLCBidXQgZmlyc3Qgd2UgbmVlZCB0byByZW9yZ2FuaXplIHRoZSBkYXRhLiAgV2hlbiB3ZSByZW1vdmVkIHRoZSByZWNvcmRzIHdpdGggbWlzc2luZyB2YWx1ZXMsIG1hbnVmYWN0dXJlciAiQSIgd2FzIHJlbW92ZWQgZnJvbSB0aGUgc2V0LiAgVG8gcGVyZm9ybSB0aGlzIGFuYWx5c2lzIGNvcnJlY3RseSwgd2UgbmVlZCB0byByZW1vdmUgdGhhdCBhcyBhIGZhY3RvciBsZXZlbCBpbiBvcmRlciB0byBhdm9pZCBza2V3aW5nIHRoZSByZXN1bHRzLg0KDQpgYGB7cn0NCmNlcmVhbCRtZnI8LWFzLmNoYXJhY3RlcihjZXJlYWwkbWZyKQ0KY2VyZWFsczwtY2VyZWFsW2NlcmVhbCRtZnIhPSJBIixdDQpjZXJlYWwkbWZyPC1hcy5mYWN0b3IoY2VyZWFsJG1mcikNCk1hbmZTaGVsZiA9IHRhYmxlKGNlcmVhbHMkbWZyLCBhcy5mYWN0b3IoY2VyZWFscyRzaGVsZikpDQpNYW5mU2hlbGYNCmNoaXNxLnRlc3QoTWFuZlNoZWxmKSANCmBgYA0KV2UgZGlkIGdldCBhIHdhcm5pbmcsIGxpa2VseSBiZWNhdXNlIHRoZXJlIGFyZSB0b28gZmV3IHJlY29yZHMsIGJ1dCBvdXIgcC12YWx1ZSB3b3VsZCBpbmRpY2F0ZSB0aGF0IHRoZXJlIGlzIG5vIHNpZ25pZmljYW50IHJlbGF0aW9uc2hpcCBiZXR3ZWVuIG1hbnVmYWN0dXJlciBhbmQgc2hlbGYgbGV2ZWwuDQpXZSBjYW4gdHJ5IG90aGVyIGNvbmZpZ3VyYXRpb25zIGhvd2V2ZXIsIHN1Y2ggYXMgZXZhbHVhdGluZyB0aGUgcHJvYmxlbSBhcyAzIHZzIG90aGVyIHNoZWx2ZXM6DQoNCmBgYHtyfQ0KDQpNYW5mU2hlbGYgPC0gY2JpbmQoTWFuZlNoZWxmWywiMyJdLCBNYW5mU2hlbGZbLCIxIl0gKyBNYW5mU2hlbGZbLCIyIl0pDQpNYW5mU2hlbGYNCg0KY2hpc3EudGVzdChNYW5mU2hlbGYpDQpgYGANCg0KQWdhaW4sIHRoaXMgeWllbGRzIG5vIHNpZ25pZmljYW5jZS4gIFdlIGNhbiBldmFsdWF0ZSAxIGFuZCAzIHRvZ2V0aGVyOg0KDQoNCmBgYHtyfQ0KTWFuZlNoZWxmID0gdGFibGUoY2VyZWFscyRtZnIsIGFzLmZhY3RvcihjZXJlYWxzJHNoZWxmKSkNCk1hbmZTaGVsZiA8LSBjYmluZChNYW5mU2hlbGZbLCIyIl0sIE1hbmZTaGVsZlssIjEiXSArIE1hbmZTaGVsZlssIjMiXSkNCk1hbmZTaGVsZg0KDQpjaGlzcS50ZXN0KE1hbmZTaGVsZikNCmBgYA0KDQpBZ2Fpbiwgbm90aGluZywgYnV0IHdlIGRvIGV2YWx1YXRlIHRoZSBsYXN0IGNvbWJpbmF0aW9uIG9mIHNoZWx2ZXMuDQoNCmBgYHtyfQ0KTWFuZlNoZWxmID0gdGFibGUoY2VyZWFscyRtZnIsIGFzLmZhY3RvcihjZXJlYWxzJHNoZWxmKSkNCk1hbmZTaGVsZiA8LSBjYmluZChNYW5mU2hlbGZbLCIxIl0sIE1hbmZTaGVsZlssIjIiXSArIE1hbmZTaGVsZlssIjMiXSkNCk1hbmZTaGVsZg0KDQpjaGlzcS50ZXN0KE1hbmZTaGVsZikNCg0KYGBgDQombmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDtJbiBvdXIgZmluYWwgc2NlbmFyaW8sIHdlIGhhdmUgZm91bmQgc29tZXRoaW5nLCB0aG91Z2ggd2Ugc3RpbGwgZG8gbm90IGhhdmUgbWFueSByZWNvcmRzLCB3aGVuIHdlIGV2YWx1YXRlIHRoZSBwcm9ibGVtIGFzIGEgZGVwZW5kZW5jZSBvbiBtYW51ZmFjdHVyZXIgYW5kIHNoZWxmIGxldmVsLCB3ZSBoYXZlIGRldGVybWluZWQgdGhhdCBhIHNwZWNpZmljIGRlcGVuZGVuY3kgZG9lcyBsaWtlbHkgZXhpc3QuICBJbiB0aGlzIGNhc2Ugd2UgaGFkIHRvIGdyb3VwIHRoZSB0b3AgdHdvIHNoZWx2ZXMgYW5kIGNvbXBhcmUgdGhvc2UgdG8gdGhlIGJvdHRvbSBzaGVsZi4NCg0KJm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7V2UgaGF2ZSByZWplY3RlZCBvdXIgbnVsbCBoeXBvdGhlc2lzIGFuZCBhY2NlcHRlZCB0aGF0IHRoZXJlIGlzIGEgcmVsYXRpb25zaGlwIGJldHdlZW4gbWFudWZhY3R1cmVyIGFuZCBzaGVsZiBsZXZlbC4NCg0KIyMjIyAgUXVlc3Rpb24gNDoNCiMjIyMgSXMgYSBjZXJ0YWluIGNlcmVhbCBudXRyaXRpb25hbGx5IHN1cGVyaW9yPw0KDQombmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDtUbyBhbnN3ZXIgdGhpcyBxdWVzdGlvbiwgd2UgbmVlZCB0byBkZXRlcm1pbmUgd2hhdCBtYWtlcyBhIGNlcmVhbCBudXRyaXRpb25hbGx5IHN1cGVyaW9yLiAgVGhlIGRhdGEgc2V0IGZvciB0aGlzIGV4ZXJjaXNlIGRvZXMgY29tZSB3aXRoIHNvbWUgcmVjb21tZW5kYXRpb25zIGZvciBkZXRlcm1pbmluZyB3aGljaCBjZXJlYWxzIGFyZSB0aGUgaGVhbHRoaWVzdC4NCg0KJm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7KkFkdWx0cyBzaG91bGQgY29uc3VtZSBiZXR3ZWVuIDIwIGFuZCAzNSBncmFtcyBvZiBkaWV0YXJ5IGZpYmVyIHBlciBkYXkuDQpUaGUgcmVjb21tZW5kZWQgZGFpbHkgaW50YWtlIChSREkpIGZvciBjYWxvcmllcyBpcyAyMjAwIGZvciB3b21lbiBhbmQgMjkwMCBmb3IgbWVuLg0KQ2Fsb3JpZXMgY29tZSBpbiB0aHJlZSBmb29kIGNvbXBvbmVudHMuIFRoZXJlIGFyZSA5IGNhbG9yaWVzIHBlciBncmFtIG9mIGZhdCwgYW5kIDQgY2Fsb3JpZXMgcGVyIGdyYW0gb2YgY2FyYm9oeWRyYXRlIGFuZCBwcm90ZWluLg0KT3ZlcmFsbCwgaW4geW91ciBkaWV0LCBubyBtb3JlIHRoYW4gMTAlIG9mIHlvdXIgY2Fsb3JpZXMgc2hvdWxkIGJlIGNvbnN1bWVkIGZyb20gc2ltcGxlIGNhcmJvaHlkcmF0ZXMgKHN1Z2FycyksIGFuZCBubyBtb3JlIHRoYW4gMzAlIHNob3VsZCBjb21lIGZyb20gZmF0LiANClRoZSBSREkgb2YgcHJvdGVpbiBpcyA1MCBncmFtcyBmb3Igd29tZW4gYW5kIDYzIGdyYW1zIGZvciBtZW4uIFRoZSBiYWxhbmNlIG9mIGNhbG9yaWVzIHNob3VsZCBiZSBjb25zdW1lZCBpbiB0aGUgZm9ybSBvZiBjb21wbGV4IGNhcmJvaHlkcmF0ZXMgKHN0YXJjaGVzKS4NClRoZSBhdmVyYWdlIGFkdWx0IHdpdGggbm8gZGVmaW5lZCByaXNrIGZhY3RvcnMgb3Igb3RoZXIgZGlldGFyeSByZXN0cmljdGlvbnMgc2hvdWxkIGNvbnN1bWUgYmV0d2VlbiAxODAwIGFuZCAyNDAwIG1nIG9mIHNvZGl1bSBwZXIgZGF5LioNCg0KKyBSUTogSXMgb25lIGNlcmVhbCBudXRyaXRpb25hbGx5IHN1cGVyaW9yIHRvIHRoZSByZXN0Pw0KKyBIbyA9IE5vIGNlcmVhbCBpcyBzaWduaWZpY2FudGx5IHN1cGVyaW9yIGluIHRlcm1zIG9mIG51dHJpdGlvbmFsIHZhbHVlIGJhc2VkIG9uIG5hdGlvbmFsIHJlY29tbWVuZGVkIGF2ZXJhZ2VzLg0KKyBIYSA9IEEgY2VyZWFsIGlzIHNpZ25pZmljYW50bHkgc3VwZXJpb3IgaW4gdGVybXMgb2YgbnV0cml0aW9uYWwgdmFsdWUgYmFzZWQgb24gbmF0aW9uYWwgcmVjb21tZW5kZWQgYXZlcmFnZXMuDQoNCiZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwO1RvIGFuc3dlciB0aGlzIHF1ZXN0aW9uLCB3ZSBuZWVkIHRvIGRlZmluZSBzb21lIGxvZ2ljIGluIGFjY29yZGFuY2UgdG8gdGhlIGd1aWRlbGluZXMgYWJvdmUuDQpUaGUgZmlyc3QgdGhpbmcgd2UgZG8sIGlzIHNjYWxlIHRoZSBjZXJlYWxzIHRvIG1hdGNoIHRoZSBhdmVyYWdlIG51bWJlciBvZiBjYWxvcmllcyBwZXIgZGF5LCBnaXZlbiB0aGUgZ3VpZGVsaW5lcy4gIEluIHNjZW5hcmlvcyB3aGVyZSB0d28gZGlmZmVyZW50IG51bWJlcnMgYXJlIHByb3ZlZCBmb3IgbWFsZXMgYW5kIGZlbWFsZXMsIHdlIHdpbGwgdGFrZSB0aGUgbWVhbiBvZiB0aG9zZSB0d28gbnVtYmVycy4NCmBgYHtyfQ0KQWxsRGF5Q2VyZWFsPC1jZXJlYWxbLGMoMSw0OjEwLDEyLDEzKV0NCkFsbERheUNlcmVhbCRwb3J0aW9uczwtMjU1MC9BbGxEYXlDZXJlYWwkY2Fsb3JpZXMNCmBgYA0KV2UgY29udGludWUgYXBwbHlpbmcgdGhlIGxvZ2ljIG9mIHRoZSBkZXNjcmlwdGlvbiBhYm92ZSwgdG8gZ2V0IGFuIG9iamVjdGl2ZSBtZWFzdXJlbWVudCBmb3IgbWVhc3VyaW5nIG51dHJpdGlvbmFsIHZhbHVlLg0KVG8gc3BlY2lmeSwgb3VyIGdvYWwgaXMgdG8gbWF0Y2ggdGhlIGd1aWRlbGluZSBhYm92ZS4gIElmIGEgY2VyZWFsIGNvbnRhaW5zIG1vcmUgdGhhbiB0aGUgcmVjb21tZW5kZWQgYW1vdW50IG9mIGEgbnV0cmllbnQsIHRoZW4gaXQgd291bGQgYmUgY29uc2lkZXJlZCBsZXNzIG51dHJpdGlvbmFsIHRoYXQgYSBjZXJlYWwgdGhhdCBoYXMgdGhlIHJlY29tbWVuZGVkIGFtb3VudC4NCkJlbG93IHdlIGFwcGx5IHNvbWUgZGlzdGFuY2UgZnVuY3Rpb25zIHRvIG1lYXN1cmUgZWFjaCBudXRyaWVudC4NCmBgYHtyfQ0KQWxsRGF5Q2VyZWFsWyxjKDI6MTApXTwtQWxsRGF5Q2VyZWFsWyxjKDI6MTApXSpBbGxEYXlDZXJlYWwkcG9ydGlvbnMNCkFsbERheUNlcmVhbCR0YXJnZXRGaWJlcjwtYygyNy41KQ0KQWxsRGF5Q2VyZWFsJHRhcmdldFN1Z2FyIDwtIGMoMCkNCkFsbERheUNlcmVhbCR0YXJnZXRGYXQ8LSBjKDApDQpBbGxEYXlDZXJlYWwkdGFyZ2V0UG90ZWluPC0gYyg1Ni41KQ0KQWxsRGF5Q2VyZWFsJHRhcmdldENhcmJzPC1jKDI1NTAtNTYuNSkNCkFsbERheUNlcmVhbCR0YXJnZXRTb2RpdW08LSBjKDIxMDApDQpBbGxEYXlDZXJlYWwkZmliZXJNZWFzdXJlPC1hYnMoQWxsRGF5Q2VyZWFsJHRhcmdldEZpYmVyLUFsbERheUNlcmVhbCRmaWJlcikNCkFsbERheUNlcmVhbCRzdWdhck1lYXN1cmU8LWFicyhBbGxEYXlDZXJlYWwkdGFyZ2V0U3VnYXItQWxsRGF5Q2VyZWFsJHN1Z2FycykNCkFsbERheUNlcmVhbCRmYXRNZWFzdXJlPC1hYnMoQWxsRGF5Q2VyZWFsJHRhcmdldEZhdC1BbGxEYXlDZXJlYWwkZmF0KQ0KQWxsRGF5Q2VyZWFsJHByb3RlaW5NZWFzdXJlPC1hYnMoQWxsRGF5Q2VyZWFsJHRhcmdldFBvdGVpbi1BbGxEYXlDZXJlYWwkcHJvdGVpbikNCkFsbERheUNlcmVhbCRjYXJic01lYXN1cmU8LWFicyhBbGxEYXlDZXJlYWwkdGFyZ2V0Q2FyYnMtQWxsRGF5Q2VyZWFsJGNhcmJvKQ0KQWxsRGF5Q2VyZWFsJHNvZGl1bU1lYXN1cmU8LWFicyhBbGxEYXlDZXJlYWwkdGFyZ2V0U29kaXVtLUFsbERheUNlcmVhbCRzb2RpdW0pDQpBbGxEYXlDZXJlYWwkbnV0cmllbnRzPC1BbGxEYXlDZXJlYWwkZmliZXJNZWFzdXJlK0FsbERheUNlcmVhbCRzdWdhck1lYXN1cmUrQWxsRGF5Q2VyZWFsJGZhdE1lYXN1cmUrQWxsRGF5Q2VyZWFsJHByb3RlaW5NZWFzdXJlK0FsbERheUNlcmVhbCRjYXJic01lYXN1cmUrQWxsRGF5Q2VyZWFsJHNvZGl1bU1lYXN1cmUtQWxsRGF5Q2VyZWFsJHZpdGFtaW5zDQpgYGANCkFmdGVyIGNvbXBpbGluZyB0aGUgbnVtYmVycywgd2UgdGFrZSB0aGUgc3VtIG9mIHRoZSBhYnNvbHV0ZSB2YWx1ZSBvZiB0aGUgZGlmZmVyZW5jZXMgaW4gcmVjb21tZW5kZWQgdnMgYWN0dWFsIG51dHJpZW50cyBmb3IgZWFjaCBjZXJlYWwuDQpUaGlzIGlzIHdoYXQgd2Ugd2lsbCB1c2UgdG8gc2VlIGlmIGEgY2VyZWFsIGlzIHNpZ25pZmljYW50bHkgYmV0dGVyLiAgVmFsdWVzIGNsb3Nlc3QgdG8gMCwgd2lsbCBiZSB0aGUgbW9zdCBpbiBsaW5lIHdpdGggdGhlIG51dHJpdGlvbmFsIHJlY29tbWVuZGF0aW9ucyBhYm92ZS4NCmBgYHtyfQ0KYm94cGxvdChBbGxEYXlDZXJlYWwkbnV0cmllbnRzLCBjb2w9KCJnb2xkIiksDQptYWluPSJOdXRyaWVudHMiLCB5bGFiPSJOdXRyaWVudCBSYXRpbmciKQ0KYGBgDQoNCkZyb20gdGhlIGJveHBsb3Qgd2UgY2FuIGRldGVybWluZSB0aGF0IGlzIHVubGlrZWx5IHRoYXQgYSBjZXJlYWwgcGVyZm9ybXMgc2lnbmlmaWNhbnRseSBiZXR0ZXIsIGJ1dCB3ZSBjYW4gc2VlIHRoYXQgdGhlcmUgaXMgYSBjZXJlYWwgdGhhdCBpcyB3YXkgb2ZmIHRoZSBtYXJrLg0KV2UgY2FuIGZpbmQgb3V0IHdoaWNoIG9uZSB0aGF0IGlzLiAgRmlyc3Qgd2UgY2hlY2sgZm9yIG5vcm1hbGl0eSBpbiB0aGUgcmVzdWx0cy4NCmBgYHtyfQ0Kc2hhcGlyby50ZXN0KEFsbERheUNlcmVhbCRudXRyaWVudHMpDQpxcW5vcm0oQWxsRGF5Q2VyZWFsJG51dHJpZW50cykNCg0KYGBgDQoNClRoZSBTaGFwaXJvLVdpbGsgbm9ybWFsaXR5IHRlc3QgY291bGQgYmUgYSB3YXJuaW5nIHNpZ24gaGVyZSwgYnV0IGxvb2tpbmcgYXQgdGhlIHFxLXBsb3QsIGl0IHNlZW1zIHNhZmUgdG8gYXNzdW1lIG91ciBkYXRhIGlzLCBmb3IgdGhlIG1vc3QgcGFydCwgbm9ybWFsbHkgZGlzdHJpYnV0ZWQuDQoNCldlIHRoZW4gbmVlZCB0byBldmFsdWF0ZSB0aGUgbWVhbiBhbmQgc3RhbmRhcmQgZGV2aWF0aW9uIHRvIGRldGVybWluZSBpZiBhIGNlcmVhbCBmYWxscyBvdXRzaWRlIG9mIHRoZSBjb25maWRlbmNlIGludGVydmFscy4NCmBgYHtyfQ0KeDwtbWVhbihBbGxEYXlDZXJlYWwkbnV0cmllbnRzKQ0KZGV2aWF0aW9uPC1zZChBbGxEYXlDZXJlYWwkbnV0cmllbnRzKQ0KDQpMYm91bmQ8LXgtKDIqZGV2aWF0aW9uKQ0KVWJvdW5kPC14KygyKmRldmlhdGlvbikNClJlc3VsdHM8LUFsbERheUNlcmVhbFtBbGxEYXlDZXJlYWwkbnV0cmllbnRzPExib3VuZCxjKDEsMjQpXQ0KUmVzdWx0cw0KYGBgDQombmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDtXZSBkaWQgbm90IHJldHVybiBhbnkgcmVzdWx0cywgd2hpY2ggbWVhbnMgdGhhdCB3ZSBoYXZlIGZhaWxlZCB0byByZWplY3QgdGhlIG51bGwgaHlwb3RoZXNpcyBhbmQgd2UgY2Fubm90IGRldGVybWluZSBpZiBvbmUgY2VyZWFsIGlzIGJldHRlciB0aGFuIHRoZSByZXN0IGluIHRlcm1zIG9mIG51dHJpdGlvbmFsIHZhbHVlcy4gIFdlIGNhbiBzdGlsbCBzZWUgd2hpY2ggYnJhbmQgZGlkIHRoZSB3b3JzdC4NCmBgYHtyfQ0KUmVzdWx0czI8LUFsbERheUNlcmVhbFtBbGxEYXlDZXJlYWwkbnV0cmllbnRzPlVib3VuZCxjKDEsMjQpXQ0KDQpSZXN1bHRzMg0KYGBgDQoNClN1cnByaXNpbmdseSBBbGwtQnJhbiBwZXJmb3JtZWQgdGhlIHdvcnN0LCBhbmQgaXMgYW4gb3V0bGllciBpbiBvdXIgbG9naWNhbCBzb2x1dGlvbi4gIFRoaXMgaXMgYSByZXN1bHQgb2YgaGF2aW5nIG11Y2ggaGlnaGVyIHRoYW4gcmVjb21tZW5kZWQgbnV0cmllbnRzIGF0IHNjYWxlLg0KDQoNCg0KIyMjIyAgUXVlc3Rpb24gNToNCiMjIyMgSXMgdGhlcmUgYSByZWxhdGlvbnNoaXAgYmV0d2VlbiBzdWdhcnMgYW5kIHdlaWdodCBieSBtYW51ZmFjdHVyZXIgKG1mcik/DQoNCiZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwO1RvIGV2YWx1YXRlIHRoaXMgcXVlc3Rpb24sIHdlIHdpbGwgbmVlZCB0byBkZXRlcm1pbmUgaWYgdGhlcmUgaXMgYSBjb3JyZWxhdGlvbiBiZXR3ZWVuIHRoZSB0d28gZmFjdG9ycy4gIEJlZm9yZSB3ZSBjYW4gYmVnaW4sIHdlIG5lZWQgdG8gYnJlYWsgdXAgb3VyIGRhdGEgdG8gbG9vayBhdCB0aGVzZSByZWxhdGlvbnNoaXBzIGZvciBlYWNoIG1hbnVmYWN0dXJlci4NCg0KKyBIbyA9IFRoZXJlIGlzIG5vdCBhIHJlbGF0aW9uc2hpcCBiZXR3ZWVuIHN1Z2FycyBhbmQgd2VpZ2h0IGJ5IG1hbnVmYWN0dXJlcnMuDQoNCisgSGEgPSBUaGVyZSBpcyBhIHJlbGF0aW9uc2hpcCBiZXR3ZWVuIHN1Z2FycyBhbmQgd2VpZ2h0IGZvciBhdCBsZWFzdCBvbmUgbWFudWZhY3R1cmVyLg0KDQpCZWZvcmUgd2UgZ2V0IHN0YXJ0ZWQsIHdlIHRha2UgYSBsb29rIGF0IHRoZSByZWxhdGlvbnNoaXAgaW4gYSBncmFwaGljYWwgZm9ybWF0LCB3aGljaCBjYW4gYmUgc2VlbiBiZWxvdy4NCg0KYGBge3J9DQpoaXN0b2dyYW0oY2VyZWFsJHN1Z2FycyB+IGNlcmVhbCR3ZWlnaHQgfCBjZXJlYWwkbWZyLCB5bGFiPSJzdWdhcnMiLA0KeGxhYiA9IldlaWdodCBwZXIgTWFudWZhY3R1cmVyIiwNCiBtYWluPSJTdWdhcnMgYnkgV2VpZ2h0IHBlciBNYW51ZmFjdHVyZXIiLA0KIHR5cGUgPSAiZGVuc2l0eSIscGFuZWw9ZnVuY3Rpb24oeCwgLi4uKQ0KIHsNCiBwYW5lbC5oaXN0b2dyYW0oeCwgLi4uKQ0KIHBhbmVsLmRlbnNpdHlwbG90KHgsIGRhcmc9bGlzdChidyA9IDAuMiwNCiBrZXJuZWw9ImdhdXNzaWFuIiksLi4uKQ0KIH0pDQpgYGANCg0KDQpOZXh0LCB3ZSBjYW4gZGV0ZXJtaW5lIGlmIHRoZXJlIGlzIGEgcmVsYXRpb25zaGlwIGF0IGEgbWFudWZhY3R1cmVyIGJ5IHJ1bm5pZ24gYSBjb3JyZWxhdGlvbiB0ZXN0LiAgQmVsb3cgd2UgYnJlYWsgdXAgb3VyIGRhdGEgYnkgbWFudWZhY3R1cmVyIGFuZCBwZXJmb3JtIHRoZSBhbmFseXNpcy4NCg0KYGBge3J9DQp1bmlxdWUoY2VyZWFsJG1mcikgIyBFYWNoIG1hbnVmYWN0dXJlciBjb2RlDQpOPC1jZXJlYWxbY2VyZWFsJG1mcj09Ik4iLGMoMTAsMTQpXQ0KSzwtY2VyZWFsW2NlcmVhbCRtZnI9PSJLIixjKDEwLDE0KV0NCkc8LWNlcmVhbFtjZXJlYWwkbWZyPT0iRyIsYygxMCwxNCldDQpSPC1jZXJlYWxbY2VyZWFsJG1mcj09IlIiLGMoMTAsMTQpXQ0KUDwtY2VyZWFsW2NlcmVhbCRtZnI9PSJQIixjKDEwLDE0KV0NClE8LWNlcmVhbFtjZXJlYWwkbWZyPT0iUSIsYygxMCwxNCldDQoNCmNvci50ZXN0KE4kc3VnYXJzLE4kd2VpZ2h0KQ0KY29yLnRlc3QoSyRzdWdhcnMsSyR3ZWlnaHQpDQpjb3IudGVzdChHJHN1Z2FycyxHJHdlaWdodCkNCmNvci50ZXN0KFIkc3VnYXJzLFIkd2VpZ2h0KQ0KY29yLnRlc3QoUCRzdWdhcnMsUCR3ZWlnaHQpDQpjb3IudGVzdChRJHN1Z2FycyxRJHdlaWdodCkNCg0KYGBgDQoNCiZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwO1RoZXJlIGlzIGEgY29ycmVsYXRpb24gZm9yIG1hbnVmYWN0dXJlciBRLCBidXQgdGhlIHAtdmFsdWUgaXMgbm90IHN1ZmZpY2llbnQgZW5vdWdoIHRvIHByb3ZlIHRoYXQgdGhlcmUgaXMgYSBjb3JyZWxhdGlvbi4gIEFzIGEgcmVzdWx0LCB3ZSBkbyBub3QgcmVqZWN0IHRoZSBudWxsIGh5cG90aGVzaXMgYW5kIGFjY2VwdCB0aGF0IHRoZXJlIGlzIG5vIHJlbGF0aW9uc2hpcCBiZXR3ZWVuIHN1Z2FyIGFuZCB3ZWlnaHQgYnkgbWFudWZhY3R1cmVyLg0KDQoNCg0KDQoNCg==