Introduction

In this section we will see how to compare two means and know if the differences can be inferred to the population, through the means comparison t-test. For that, we will continue to use the latest regional report “The Pulse of Democracy”, available here, where the main findings of the 2018/19 round of the AmericasBarometer are presented. This report shows the results on support for electoral democracy, a variable that is crossed with some other sociodemographic variables such as gender or place of residence (see Figure 1.5).

About the dataset

The data we are going to use should be cited as follows: Source: AmericasBarometer by the Latin American Public Opinion Project (LAPOP), wwww.LapopSurveys.org. This section reloads a trimmed database. It is recommended to clean the Environment before starting this section.

This database is hosted in the “materials_edu” repository of the LAPOP account on GitHub. Using the rio library and the import command, you can import this database from this repository. In addition, the data from countries with codes less than or equal to 35 are selected, that is, the observations of the United States and Canada are eliminated.

library(rio)
lapop18 = import("https://raw.github.com/lapop-central/materials_edu/main/LAPOP_AB_Merge_2018_v1.0.sav")
lapop18 = subset(lapop18, pais<=35)

We also load the dataset for the 2021 round of the AmericasBarometer.

lapop21 = import("https://raw.github.com/lapop-central/materials_edu/main/lapop21.RData")
lapop21 = subset(lapop21, pais<=35)

Crime victimization

Victimization for crime is measure with the variable “vic1ext”. The question is worded: “Now, changing the subject, have you been a victim of any type of crime in the past 12 months? That is, have you been a victim of robbery, burglary, assault, fraud, blackmail, extortion, violent threats or any other type of crime in the past 12 months?”.

This variable is coded 1 “Yes” and 2 “No”. To be able to replicate the results in Figure 3.12, we have to recode this variable. As we indicate in a previous section, this recodification allows to calculate the percentage of victims for crime with the command mean. The results indicate that 22% of citizens report having been victim of crime.

library(car)
lapop21$crime = car::recode(lapop21$vic1ext, "1=100; 2=0")
mean(lapop21$crime, na.rm=T)
## [1] 21.92233

Figure 3.12 shows a comparison of victimization for crime crossed by four sociodemographic variables: gender, age, education and quintiles of wealth.


To replicate difference between gender, we have to recode variable “q1tb” and then declare this new variable as factor.

lapop21$gender = car::recode(lapop21$q1tb, "1=2; 2=1; 3=1")
lapop21$gender = as.factor(lapop21$gender)
levels(lapop21$gender) = c("Female", "Male")
table(lapop21$gender)
## 
## Female   Male 
##  31487  29174

In the same way as in the section about confidence intervals, we use the command tapply to calculate the percentage of crime victimization by groups of gender.

tapply(lapop21$crime, lapop21$gender, mean, na.rm=T) #Para género
##   Female     Male 
## 20.87127 23.06949

To reproduce the bar plot, including the confidence intervals, first we have to produce a table that saves the percentages for each group and the upper and lower limits of the confidence intervals. We can do this with the command group.CI of the library Rmisc .

With this table, we can use the library ggplot to reproduce the first pane of Figure 3.12. Results are not the same due to we have not used survey weights.

library(Rmisc)
crxgen = group.CI(crime~gender, lapop21)
library(ggplot2)
graf3.12a = ggplot(crxgen, aes(x=gender, y=crime.mean))+
  geom_bar(width=0.5, fill="darkcyan", colour="black", stat="identity")+
  geom_errorbar(aes(ymin=crime.lower, ymax=crime.upper), width=0.2)+
  geom_text(aes(label=paste(round(crime.mean, 1), "%")), vjust=-1.5, size=4)+
  xlab("Gender") + ylab("Crime victimización (%)")+
  ylim(0, 40)
graf3.12a

We can compare visually the confidence intervals between groups in this graph. Because they do not overlap, we can conclude that the difference between men and women in crime victimization is statistically significant (initially).

This result, however, has to be confirmed formally with a significance test that we will see below.

Support for Democracy

Support for democracy, variable “ING4”, measured on a scale from 1 to 7, where 1 means “strongly disagree” and 7 means “strongly agree”, has to be recoded. According to the report “Responses are considered in the portion of the scale that indicates agreement, this is the values from 5 to 7, to indicate the percentage that supports democracy” (p. 11). The command mean is used to report the regional average of support for democracy. We specify na.rm=T so that the command does not take missing values into account in the calculation.

library(car)
lapop18$ing4r = car::recode(lapop18$ing4, "1:4=0; 5:7=100")
mean(lapop18$ing4r, na.rm=T)
## [1] 57.67924

It is observed that in general, 57.7% of those interviewed support democracy in the set of countries evaluated in 2018.

Factors associated with support for democracy

Figure 1.5 shows how support for democracy varies by sociodemographic groups. In particular, the results are presented for the variable place of residence that distinguishes the urban and rural areas, and for the variable gender, which distinguishes between men and women.

As we saw in the section on confidence intervals, the percentage of support for each group can be calculated. First, we are going to create new factor variables for place of residence and gender, which are imported as numeric variables. These new variables are then labeled.

lapop18$gender = as.factor(lapop18$q1)
levels(lapop18$gender) = c("Male", "Female")
lapop18$ambito = as.factor(lapop18$ur)
levels(lapop18$ambito) = c("Urban", "Rural")

As in the section on confidence intervals, we use the command tapply to calculate average support for democracy by gender and urban/rural setting.

tapply(lapop18$ing4r, lapop18$gender, mean, na.rm=T) #To gender
##     Male   Female 
## 59.42899 55.90933
tapply(lapop18$ing4r, lapop18$ambito, mean, na.rm=T) #To urban-rural
##    Urban    Rural 
## 58.71664 55.07453

We can reproduce the bar plots that compare the average support for democracy between groups by gender and urban/rural. First, for gender, you have to create a table with the data of the mean and the limits of the confidence intervals for each group. We will do this with the command group.CI which is part of the library Rmisc. We save this data in an R object called “sdxgen”.

This table saves the results of the mean support for democracy for each group (“ing4r.mean” column) and the upper and lower limits of the confidence intervals (“ing4r.lower” and “ing4r.upper” columns). It also saves the “gender” column with the names of the groups.

Figure 1.5 is reproduced using the command ggplot in the same way as in previous sections.

library(Rmisc)
sdxgen = group.CI(ing4r~gender, lapop18)
library(ggplot2)
graf1.5 = ggplot(sdxgen, aes(x=gender, y=ing4r.mean))+
  geom_bar(width=0.5, fill="darkcyan", colour="black", stat="identity")+
  geom_errorbar(aes(ymin=ing4r.lower, ymax=ing4r.upper), width=0.2)+
  geom_text(aes(label=paste(round(ing4r.mean, 1), "%")), vjust=-1.5, size=4)+
  xlab("Gender") + ylab("Support for democracy (%)")+
  ylim(0, 70)
graf1.5

A similar graph can be generated that presents the percentage of support for democracy and the confidence intervals by urban and rural groups.

sdxamb <- group.CI(ing4r~ambito, lapop18)
library(ggplot2)
graf1.5_2 = ggplot(sdxamb, aes(x=ambito, y=ing4r.mean))+
  geom_bar(width=0.5, fill="darkcyan", colour="black", stat="identity")+
  geom_errorbar(aes(ymin=ing4r.lower, ymax=ing4r.upper), width=0.2)+
  geom_text(aes(label=paste(round(ing4r.mean, 1), "%")), vjust=-1.5, size=4)+
  xlab("Place of residence") + ylab("Support for democracy (%)")+
  ylim(0, 70)
graf1.5_2

The LAPOP Lab generally presents the confidence intervals of each group in its graphs. These gray bars on the report serve as a quick way to compare. If the bars overlap, that would mean that there would be no statistically significant differences between the groups. On the contrary, if the gray bars do not overlap, it would mean that the difference between the groups is significant at 95% confidence. However, to check these conclusions, a statistical test has to be calculated. When the comparison is between the means of two groups, the appropriate statistical test is the t-test for differences of means. In this section we are assuming that we can treat the variable “jc15a” and “ing4r” as numerical variables, from which the mean and standard deviation can be calculated, although these variables are strictly a nominal qualitative type.

T-test

Student’s t tests the following hypotheses:

\[ H_0: µ_1 = µ_2 \]

\[ H_a: µ_1 ≠ µ_2 \]

The t-test statistic is calculated with a standard error that depends on whether the variances appear different or whether the variances appear equal. To determine this condition, the first thing is to calculate a test of equality of variances between the groups, called Levene’s test.

\[ H_0: var_1 = var_2 \]

\[ H_a: var_1 ≠ var_2 \]

T-test for the difference in means of crime victimization by gender

The first step is to run the Levene test to evaluate if variances are equal or different, which is a condition that then is used in the t-test. To run this test, we use the library DescTools that includes the command LeveneTest.

library(DescTools)
LeveneTest(lapop21$crime, lapop21$gender)

Because the p-value (Pr(>F)) is lower than 0.05, we reject the null hypothesis and affirm that variances are different. With this result, we can run the command t.test, which null hypothesis indicates that means of crime victimization are equal between men and women, and the alternative hypothesis indicates that both means are different. We include the specification var.equal = F because the results of the Levene test indicates that variances seem different.

t.test(crime ~ gender, data = lapop21, var.equal=F)
## 
##  Welch Two Sample t-test
## 
## data:  crime by gender
## t = -4.6147, df = 29850, p-value = 3.952e-06
## alternative hypothesis: true difference in means between group Female and group Male is not equal to 0
## 95 percent confidence interval:
##  -3.131886 -1.264558
## sample estimates:
## mean in group Female   mean in group Male 
##             20.87127             23.06949

The p-value is lower than 0.05. With this result, we can reject the null hypotesis and affirm the alternative hypothesis that means between both groups are different. We conclude that men report a higher crime victimization than women in the region.

T-test for the difference in means of support for democracy by gender

The first step is to do the Levene test. To run this test, the library DescTools is used, which includes the command LeveneTest.

library(DescTools)
LeveneTest(lapop18$ing4r, lapop18$gender)

As the p-value (Pr(>F) is less than 0.05, the null hypothesis is rejected and it is stated that the variances are different. With this result, the command t.test can be run, whose null hypothesis indicates that the means of support for democracy are the same between men and women and the alternative hypothesis indicates that both means are different. The specification var.equal = F is included due to the result of Levene’s test indicating that the variances appear different.

t.test(ing4r ~ gender, data = lapop18, var.equal=F)
## 
##  Welch Two Sample t-test
## 
## data:  ing4r by gender
## t = 5.8633, df = 27046, p-value = 4.59e-09
## alternative hypothesis: true difference in means between group Male and group Female is not equal to 0
## 95 percent confidence interval:
##  2.343068 4.696255
## sample estimates:
##   mean in group Male mean in group Female 
##             59.42899             55.90933

The value of the p-value (4.59e-09) is less than 0.05, so the null hypothesis is rejected and the alternative is affirmed, concluding that the differences are different in the population at 95% confidence.

T-test for the difference in means of support for democracy by domain groups

In the same way as in the previous case, Levene’s test is first run to analyze the equality of variances.

LeveneTest(lapop18$ing4r, lapop18$ambito)

Again, the p-value is less than 0.05, which rejects the hypothesis of equality of variances. The t-test is then run with the specification of different variances.

t.test(ing4r ~ ambito, data = lapop18, var.equal=F)
## 
##  Welch Two Sample t-test
## 
## data:  ing4r by ambito
## t = 5.4543, df = 14056, p-value = 5e-08
## alternative hypothesis: true difference in means between group Urban and group Rural is not equal to 0
## 95 percent confidence interval:
##  2.333228 4.950988
## sample estimates:
## mean in group Urban mean in group Rural 
##            58.71664            55.07453

In this comparison, the p-value is also less than 0.05, so the null hypothesis is rejected and it is found that the differences in support for democracy between urban and rural areas is statistically significant at 95% confidence. As the report indicates, “Considering the region as a whole, Figure 1.5 shows statistically significant relationships between five demographic variables and socioeconomic groups (education, wealth, urban/rural residence, gender, and age) and support for democracy” (p. 13). In this section we have checked these statistical results for demographic variables of two groups, such as gender and urban/rural residence.

Summary

In this section we have described and plotted a variable, such as support for democracy, by groups of other variable, such as gender. Starting from the comparison of confidence intervals, we formalize this comparison with a statistical test, such as the t-test, to conclude whether the differences between groups are statistically significant.

Calculations including survey weights

For crime victimization

To calculate the difference of means including a survey weight, we can use the library survey. This library requires a change in the dataset, in the same way as we did in this section.

Once we fit the dataset, we have to define the sampling design with the command svydesign and we save this design in an object called “design21”.

library(survey)
design21 = svydesign(ids = ~upm, strata = ~strata, weights = ~weight1500, nest=TRUE, data=lapop21)

Now we can calculate the table of the mean of crime victimization for each group of gender, including the survey weight. In the same way as we see in the section on confidence intervals, we use the command svyby.

crxgen.w = svyby(~crime, ~gender, design21, svymean, na.rm=T, vartype = "ci")
crxgen.w

It should be noted that these results are equal to those presented in Figure 3.12. With this table we can proceed to replicate the left panel of this figure, in the same manner as we did above in this section.

For the calculation of the t-test of difference of means, the library survey has a native command, called svyttest, that allows to perform this test. However, we do not have a command to evaluate the variances, as the Levene test. The command svyttest is a development of a more general command for generalized linear models, which assume variances are equal. If we would like to validate this assumption, we can do it manually, as explained in this link. Here we are going to proceed as if assumption is correct. We observe this command get results very similar to those obtained with no survey weights and, for all effect, we arrive to the same conclusions. The p-value is lower than 0.05, so we can reject the null hypothesis and affirm there are differences between men and women in their levels of crime victimization, taking into account the survey weights.

svyttest(crime~gender, design21)
## 
##  Design-based t-test
## 
## data:  crime ~ gender
## t = 4.3654, df = 30282, p-value = 1.273e-05
## alternative hypothesis: true difference in mean is not equal to 0
## 95 percent confidence interval:
##  1.370025 3.602805
## sample estimates:
## difference in mean 
##           2.486415

For support for democracy

Other way to calculate the difference of means including the survey wieight is by using the library survey. For this we have to define the sample design with the command svydesign and save this design in an object, here called “design18”.

library(survey)
design18 = svydesign(ids = ~upm, strata = ~estratopri, weights = ~weight1500, nest=TRUE, data=lapop18)

First, the table of the mean support for democracy can be calculated for each value of the variable gender, including the survey weight. In the same way as seen in the section on confidence intervals, and use the command svyby.

sdxgen.w = svyby(~ing4r, ~gender, design18, svymean, na.rm=T, vartype = "ci")
sdxgen.w

With this table you can proceed to create the bar plot, in the same way that was done above in this section.

For the calculation of the t-test for difference of means, the package survey has a native command svyttestthat allows this calculation.

svyttest(ing4r~gender, design18)
## 
##  Design-based t-test
## 
## data:  ing4r ~ gender
## t = -5.8332, df = 1329, p-value = 6.822e-09
## alternative hypothesis: true difference in mean is not equal to 0
## 95 percent confidence interval:
##  -4.672004 -2.320395
## sample estimates:
## difference in mean 
##          -3.496199

Because the p-value is lower than 0.05, we conclude there are differences between men and women in their levels of support for democracy in the region.

LS0tCnRpdGxlOiAiQ29tcGFyaW5nIDIgbWVhbnMgd2l0aCB0aGUgQW1lcmljYXNCYXJvbWV0ZXIiCm91dHB1dDoKICBodG1sX2RvY3VtZW50OgogICAgdG9jOiB0cnVlCiAgICB0b2NfZmxvYXQ6IHRydWUKICAgIGNvbGxhcHNlZDogZmFsc2UKICAgIG51bWJlcl9zZWN0aW9uczogZmFsc2UKICAgIHRvY19kZXB0aDogMQogICAgY29kZV9kb3dubG9hZDogdHJ1ZQogICAgdGhlbWU6IGZsYXRseQogICAgZGZfcHJpbnQ6IHBhZ2VkCiAgICBzZWxmX2NvbnRhaW5lZDogbm8KICAgIGtlZXBfbWQ6IHllcwplZGl0b3Jfb3B0aW9uczogCiAgbWFya2Rvd246IAogICAgd3JhcDogc2VudGVuY2UKLS0tCgpgYGB7ciBzZXR1cCwgaW5jbHVkZT1GQUxTRX0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KG1lc3NhZ2U9RkFMU0Usd2FybmluZz1GQUxTRSwgY2FjaGU9VFJVRSkKYGBgCgpgYGB7Y3NzIGNvbG9yLCBlY2hvPUZBTFNFfQouY29sdW1ucyB7ZGlzcGxheTogZmxleDt9CmgxIHtjb2xvcjogIzMzNjZDQzt9CmBgYAoKIyBJbnRyb2R1Y3Rpb24KCkluIHRoaXMgc2VjdGlvbiB3ZSB3aWxsIHNlZSBob3cgdG8gY29tcGFyZSB0d28gbWVhbnMgYW5kIGtub3cgaWYgdGhlIGRpZmZlcmVuY2VzIGNhbiBiZSBpbmZlcnJlZCB0byB0aGUgcG9wdWxhdGlvbiwgdGhyb3VnaCB0aGUgbWVhbnMgY29tcGFyaXNvbiB0LXRlc3QuCkZvciB0aGF0LCB3ZSB3aWxsIGNvbnRpbnVlIHRvIHVzZSB0aGUgbGF0ZXN0IHJlZ2lvbmFsIHJlcG9ydCAiVGhlIFB1bHNlIG9mIERlbW9jcmFjeSIsIGF2YWlsYWJsZSBbaGVyZV0oaHR0cHM6Ly93d3cudmFuZGVyYmlsdC5lZHUvbGFwb3AvYWIyMDIxLzIwMjFfTEFQT1BfQW1lcmljYXNCYXJvbWV0ZXJfMjAyMV9QdWxzZV9vZl9EZW1vY3JhY3kucGRmKSwgd2hlcmUgdGhlIG1haW4gZmluZGluZ3Mgb2YgdGhlIDIwMTgvMTkgcm91bmQgb2YgdGhlIEFtZXJpY2FzQmFyb21ldGVyIGFyZSBwcmVzZW50ZWQuClRoaXMgcmVwb3J0IHNob3dzIHRoZSByZXN1bHRzIG9uIHN1cHBvcnQgZm9yIGVsZWN0b3JhbCBkZW1vY3JhY3ksIGEgdmFyaWFibGUgdGhhdCBpcyBjcm9zc2VkIHdpdGggc29tZSBvdGhlciBzb2Npb2RlbW9ncmFwaGljIHZhcmlhYmxlcyBzdWNoIGFzIGdlbmRlciBvciBwbGFjZSBvZiByZXNpZGVuY2UgKHNlZSBGaWd1cmUgMS41KS4KCiMgQWJvdXQgdGhlIGRhdGFzZXQKClRoZSBkYXRhIHdlIGFyZSBnb2luZyB0byB1c2Ugc2hvdWxkIGJlIGNpdGVkIGFzIGZvbGxvd3M6IFNvdXJjZTogQW1lcmljYXNCYXJvbWV0ZXIgYnkgdGhlIExhdGluIEFtZXJpY2FuIFB1YmxpYyBPcGluaW9uIFByb2plY3QgKExBUE9QKSwgd3d3dy5MYXBvcFN1cnZleXMub3JnLgpUaGlzIHNlY3Rpb24gcmVsb2FkcyBhIHRyaW1tZWQgZGF0YWJhc2UuCkl0IGlzIHJlY29tbWVuZGVkIHRvIGNsZWFuIHRoZSBFbnZpcm9ubWVudCBiZWZvcmUgc3RhcnRpbmcgdGhpcyBzZWN0aW9uLgoKVGhpcyBkYXRhYmFzZSBpcyBob3N0ZWQgaW4gdGhlICJtYXRlcmlhbHNfZWR1IiByZXBvc2l0b3J5IG9mIHRoZSBMQVBPUCBhY2NvdW50IG9uIEdpdEh1Yi4KVXNpbmcgdGhlIGByaW9gIGxpYnJhcnkgYW5kIHRoZSBgaW1wb3J0YCBjb21tYW5kLCB5b3UgY2FuIGltcG9ydCB0aGlzIGRhdGFiYXNlIGZyb20gdGhpcyByZXBvc2l0b3J5LgpJbiBhZGRpdGlvbiwgdGhlIGRhdGEgZnJvbSBjb3VudHJpZXMgd2l0aCBjb2RlcyBsZXNzIHRoYW4gb3IgZXF1YWwgdG8gMzUgYXJlIHNlbGVjdGVkLCB0aGF0IGlzLCB0aGUgb2JzZXJ2YXRpb25zIG9mIHRoZSBVbml0ZWQgU3RhdGVzIGFuZCBDYW5hZGEgYXJlIGVsaW1pbmF0ZWQuCgpgYGB7ciBiYXNlfQpsaWJyYXJ5KHJpbykKbGFwb3AxOCA9IGltcG9ydCgiaHR0cHM6Ly9yYXcuZ2l0aHViLmNvbS9sYXBvcC1jZW50cmFsL21hdGVyaWFsc19lZHUvbWFpbi9MQVBPUF9BQl9NZXJnZV8yMDE4X3YxLjAuc2F2IikKbGFwb3AxOCA9IHN1YnNldChsYXBvcDE4LCBwYWlzPD0zNSkKYGBgCgpXZSBhbHNvIGxvYWQgdGhlIGRhdGFzZXQgZm9yIHRoZSAyMDIxIHJvdW5kIG9mIHRoZSBBbWVyaWNhc0Jhcm9tZXRlci4KCmBgYHtyfQpsYXBvcDIxID0gaW1wb3J0KCJodHRwczovL3Jhdy5naXRodWIuY29tL2xhcG9wLWNlbnRyYWwvbWF0ZXJpYWxzX2VkdS9tYWluL2xhcG9wMjEuUkRhdGEiKQpsYXBvcDIxID0gc3Vic2V0KGxhcG9wMjEsIHBhaXM8PTM1KQpgYGAKCiMgQ3JpbWUgdmljdGltaXphdGlvbgoKVmljdGltaXphdGlvbiBmb3IgY3JpbWUgaXMgbWVhc3VyZSB3aXRoIHRoZSB2YXJpYWJsZSAidmljMWV4dCIuClRoZSBxdWVzdGlvbiBpcyB3b3JkZWQ6ICJOb3csIGNoYW5naW5nIHRoZSBzdWJqZWN0LCBoYXZlIHlvdSBiZWVuIGEgdmljdGltIG9mIGFueSB0eXBlIG9mIGNyaW1lIGluIHRoZSBwYXN0IDEyIG1vbnRocz8gVGhhdCBpcywgaGF2ZSB5b3UgYmVlbiBhIHZpY3RpbSBvZiByb2JiZXJ5LCBidXJnbGFyeSwgYXNzYXVsdCwgZnJhdWQsIGJsYWNrbWFpbCwgZXh0b3J0aW9uLCB2aW9sZW50IHRocmVhdHMgb3IgKiphbnkgb3RoZXIgdHlwZSoqIG9mIGNyaW1lIGluIHRoZSBwYXN0IDEyIG1vbnRocz8iLgoKVGhpcyB2YXJpYWJsZSBpcyBjb2RlZCAxICJZZXMiIGFuZCAyICJObyIuClRvIGJlIGFibGUgdG8gcmVwbGljYXRlIHRoZSByZXN1bHRzIGluIEZpZ3VyZSAzLjEyLCB3ZSBoYXZlIHRvIHJlY29kZSB0aGlzIHZhcmlhYmxlLgpBcyB3ZSBpbmRpY2F0ZSBpbiBhIHByZXZpb3VzIHNlY3Rpb24sIHRoaXMgcmVjb2RpZmljYXRpb24gYWxsb3dzIHRvIGNhbGN1bGF0ZSB0aGUgcGVyY2VudGFnZSBvZiB2aWN0aW1zIGZvciBjcmltZSB3aXRoIHRoZSBjb21tYW5kIGBtZWFuYC4KVGhlIHJlc3VsdHMgaW5kaWNhdGUgdGhhdCAyMiUgb2YgY2l0aXplbnMgcmVwb3J0IGhhdmluZyBiZWVuIHZpY3RpbSBvZiBjcmltZS4KCmBgYHtyfQpsaWJyYXJ5KGNhcikKbGFwb3AyMSRjcmltZSA9IGNhcjo6cmVjb2RlKGxhcG9wMjEkdmljMWV4dCwgIjE9MTAwOyAyPTAiKQptZWFuKGxhcG9wMjEkY3JpbWUsIG5hLnJtPVQpCmBgYAoKRmlndXJlIDMuMTIgc2hvd3MgYSBjb21wYXJpc29uIG9mIHZpY3RpbWl6YXRpb24gZm9yIGNyaW1lIGNyb3NzZWQgYnkgZm91ciBzb2Npb2RlbW9ncmFwaGljIHZhcmlhYmxlczogZ2VuZGVyLCBhZ2UsIGVkdWNhdGlvbiBhbmQgcXVpbnRpbGVzIG9mIHdlYWx0aC4KCiFbXShGaWd1cmUzLjEyLnBuZyl7d2lkdGg9IjUxMiJ9XApUbyByZXBsaWNhdGUgZGlmZmVyZW5jZSBiZXR3ZWVuIGdlbmRlciwgd2UgaGF2ZSB0byByZWNvZGUgdmFyaWFibGUgInExdGIiIGFuZCB0aGVuIGRlY2xhcmUgdGhpcyBuZXcgdmFyaWFibGUgYXMgZmFjdG9yLgoKYGBge3J9CmxhcG9wMjEkZ2VuZGVyID0gY2FyOjpyZWNvZGUobGFwb3AyMSRxMXRiLCAiMT0yOyAyPTE7IDM9MSIpCmxhcG9wMjEkZ2VuZGVyID0gYXMuZmFjdG9yKGxhcG9wMjEkZ2VuZGVyKQpsZXZlbHMobGFwb3AyMSRnZW5kZXIpID0gYygiRmVtYWxlIiwgIk1hbGUiKQp0YWJsZShsYXBvcDIxJGdlbmRlcikKYGBgCgpJbiB0aGUgc2FtZSB3YXkgYXMgaW4gdGhlIHNlY3Rpb24gYWJvdXQgY29uZmlkZW5jZSBpbnRlcnZhbHMsIHdlIHVzZSB0aGUgY29tbWFuZCBgdGFwcGx5YCB0byBjYWxjdWxhdGUgdGhlIHBlcmNlbnRhZ2Ugb2YgY3JpbWUgdmljdGltaXphdGlvbiBieSBncm91cHMgb2YgZ2VuZGVyLgoKYGBge3J9CnRhcHBseShsYXBvcDIxJGNyaW1lLCBsYXBvcDIxJGdlbmRlciwgbWVhbiwgbmEucm09VCkgI1BhcmEgZ8OpbmVybwpgYGAKClRvIHJlcHJvZHVjZSB0aGUgYmFyIHBsb3QsIGluY2x1ZGluZyB0aGUgY29uZmlkZW5jZSBpbnRlcnZhbHMsIGZpcnN0IHdlIGhhdmUgdG8gcHJvZHVjZSBhIHRhYmxlIHRoYXQgc2F2ZXMgdGhlIHBlcmNlbnRhZ2VzIGZvciBlYWNoIGdyb3VwIGFuZCB0aGUgdXBwZXIgYW5kIGxvd2VyIGxpbWl0cyBvZiB0aGUgY29uZmlkZW5jZSBpbnRlcnZhbHMuCldlIGNhbiBkbyB0aGlzIHdpdGggdGhlIGNvbW1hbmQgYGdyb3VwLkNJYCBvZiB0aGUgbGlicmFyeSBgUm1pc2NgIC4KCldpdGggdGhpcyB0YWJsZSwgd2UgY2FuIHVzZSB0aGUgbGlicmFyeSBgZ2dwbG90YCB0byByZXByb2R1Y2UgdGhlIGZpcnN0IHBhbmUgb2YgRmlndXJlIDMuMTIuClJlc3VsdHMgYXJlIG5vdCB0aGUgc2FtZSBkdWUgdG8gd2UgaGF2ZSBub3QgdXNlZCBzdXJ2ZXkgd2VpZ2h0cy4KCmBgYHtyfQpsaWJyYXJ5KFJtaXNjKQpjcnhnZW4gPSBncm91cC5DSShjcmltZX5nZW5kZXIsIGxhcG9wMjEpCmxpYnJhcnkoZ2dwbG90MikKZ3JhZjMuMTJhID0gZ2dwbG90KGNyeGdlbiwgYWVzKHg9Z2VuZGVyLCB5PWNyaW1lLm1lYW4pKSsKICBnZW9tX2Jhcih3aWR0aD0wLjUsIGZpbGw9ImRhcmtjeWFuIiwgY29sb3VyPSJibGFjayIsIHN0YXQ9ImlkZW50aXR5IikrCiAgZ2VvbV9lcnJvcmJhcihhZXMoeW1pbj1jcmltZS5sb3dlciwgeW1heD1jcmltZS51cHBlciksIHdpZHRoPTAuMikrCiAgZ2VvbV90ZXh0KGFlcyhsYWJlbD1wYXN0ZShyb3VuZChjcmltZS5tZWFuLCAxKSwgIiUiKSksIHZqdXN0PS0xLjUsIHNpemU9NCkrCiAgeGxhYigiR2VuZGVyIikgKyB5bGFiKCJDcmltZSB2aWN0aW1pemFjacOzbiAoJSkiKSsKICB5bGltKDAsIDQwKQpncmFmMy4xMmEKYGBgCgpXZSBjYW4gY29tcGFyZSB2aXN1YWxseSB0aGUgY29uZmlkZW5jZSBpbnRlcnZhbHMgYmV0d2VlbiBncm91cHMgaW4gdGhpcyBncmFwaC4KQmVjYXVzZSB0aGV5IGRvIG5vdCBvdmVybGFwLCB3ZSBjYW4gY29uY2x1ZGUgdGhhdCB0aGUgZGlmZmVyZW5jZSBiZXR3ZWVuIG1lbiBhbmQgd29tZW4gaW4gY3JpbWUgdmljdGltaXphdGlvbiBpcyBzdGF0aXN0aWNhbGx5IHNpZ25pZmljYW50IChpbml0aWFsbHkpLgoKVGhpcyByZXN1bHQsIGhvd2V2ZXIsIGhhcyB0byBiZSBjb25maXJtZWQgZm9ybWFsbHkgd2l0aCBhIHNpZ25pZmljYW5jZSB0ZXN0IHRoYXQgd2Ugd2lsbCBzZWUgYmVsb3cuCgojIFN1cHBvcnQgZm9yIERlbW9jcmFjeQoKU3VwcG9ydCBmb3IgZGVtb2NyYWN5LCB2YXJpYWJsZSAiSU5HNCIsIG1lYXN1cmVkIG9uIGEgc2NhbGUgZnJvbSAxIHRvIDcsIHdoZXJlIDEgbWVhbnMgInN0cm9uZ2x5IGRpc2FncmVlIiBhbmQgNyBtZWFucyAic3Ryb25nbHkgYWdyZWUiLCBoYXMgdG8gYmUgcmVjb2RlZC4KQWNjb3JkaW5nIHRvIHRoZSByZXBvcnQgIlJlc3BvbnNlcyBhcmUgY29uc2lkZXJlZCBpbiB0aGUgcG9ydGlvbiBvZiB0aGUgc2NhbGUgdGhhdCBpbmRpY2F0ZXMgYWdyZWVtZW50LCB0aGlzIGlzIHRoZSB2YWx1ZXMgZnJvbSA1IHRvIDcsIHRvIGluZGljYXRlIHRoZSBwZXJjZW50YWdlIHRoYXQgc3VwcG9ydHMgZGVtb2NyYWN5IiAocC4gMTEpLgpUaGUgY29tbWFuZCBgbWVhbmAgaXMgdXNlZCB0byByZXBvcnQgdGhlIHJlZ2lvbmFsIGF2ZXJhZ2Ugb2Ygc3VwcG9ydCBmb3IgZGVtb2NyYWN5LgpXZSBzcGVjaWZ5IGBuYS5ybT1UYCBzbyB0aGF0IHRoZSBjb21tYW5kIGRvZXMgbm90IHRha2UgbWlzc2luZyB2YWx1ZXMgaW50byBhY2NvdW50IGluIHRoZSBjYWxjdWxhdGlvbi4KCmBgYHtyIHJlY29kZX0KbGlicmFyeShjYXIpCmxhcG9wMTgkaW5nNHIgPSBjYXI6OnJlY29kZShsYXBvcDE4JGluZzQsICIxOjQ9MDsgNTo3PTEwMCIpCm1lYW4obGFwb3AxOCRpbmc0ciwgbmEucm09VCkKYGBgCgpJdCBpcyBvYnNlcnZlZCB0aGF0IGluIGdlbmVyYWwsIDU3LjclIG9mIHRob3NlIGludGVydmlld2VkIHN1cHBvcnQgZGVtb2NyYWN5IGluIHRoZSBzZXQgb2YgY291bnRyaWVzIGV2YWx1YXRlZCBpbiAyMDE4LgoKIyBGYWN0b3JzIGFzc29jaWF0ZWQgd2l0aCBzdXBwb3J0IGZvciBkZW1vY3JhY3kKCkZpZ3VyZSAxLjUgc2hvd3MgaG93IHN1cHBvcnQgZm9yIGRlbW9jcmFjeSB2YXJpZXMgYnkgc29jaW9kZW1vZ3JhcGhpYyBncm91cHMuCkluIHBhcnRpY3VsYXIsIHRoZSByZXN1bHRzIGFyZSBwcmVzZW50ZWQgZm9yIHRoZSB2YXJpYWJsZSBwbGFjZSBvZiByZXNpZGVuY2UgdGhhdCBkaXN0aW5ndWlzaGVzIHRoZSB1cmJhbiBhbmQgcnVyYWwgYXJlYXMsIGFuZCBmb3IgdGhlIHZhcmlhYmxlIGdlbmRlciwgd2hpY2ggZGlzdGluZ3Vpc2hlcyBiZXR3ZWVuIG1lbiBhbmQgd29tZW4uCgohW10oRmlndXJlMS41LkpQRyl7d2lkdGg9IjM5NSJ9CgpBcyB3ZSBzYXcgaW4gdGhlIHNlY3Rpb24gb24gY29uZmlkZW5jZSBpbnRlcnZhbHMsIHRoZSBwZXJjZW50YWdlIG9mIHN1cHBvcnQgZm9yIGVhY2ggZ3JvdXAgY2FuIGJlIGNhbGN1bGF0ZWQuCkZpcnN0LCB3ZSBhcmUgZ29pbmcgdG8gY3JlYXRlIG5ldyBmYWN0b3IgdmFyaWFibGVzIGZvciBwbGFjZSBvZiByZXNpZGVuY2UgYW5kIGdlbmRlciwgd2hpY2ggYXJlIGltcG9ydGVkIGFzIG51bWVyaWMgdmFyaWFibGVzLgpUaGVzZSBuZXcgdmFyaWFibGVzIGFyZSB0aGVuIGxhYmVsZWQuCgpgYGB7ciBmYWN0b3JzfQpsYXBvcDE4JGdlbmRlciA9IGFzLmZhY3RvcihsYXBvcDE4JHExKQpsZXZlbHMobGFwb3AxOCRnZW5kZXIpID0gYygiTWFsZSIsICJGZW1hbGUiKQpsYXBvcDE4JGFtYml0byA9IGFzLmZhY3RvcihsYXBvcDE4JHVyKQpsZXZlbHMobGFwb3AxOCRhbWJpdG8pID0gYygiVXJiYW4iLCAiUnVyYWwiKQpgYGAKCkFzIGluIHRoZSBzZWN0aW9uIG9uIGNvbmZpZGVuY2UgaW50ZXJ2YWxzLCB3ZSB1c2UgdGhlIGNvbW1hbmQgYHRhcHBseWAgdG8gY2FsY3VsYXRlIGF2ZXJhZ2Ugc3VwcG9ydCBmb3IgZGVtb2NyYWN5IGJ5IGdlbmRlciBhbmQgdXJiYW4vcnVyYWwgc2V0dGluZy4KCmBgYHtyIGdyb3VwIHN1cHBvcnR9CnRhcHBseShsYXBvcDE4JGluZzRyLCBsYXBvcDE4JGdlbmRlciwgbWVhbiwgbmEucm09VCkgI1RvIGdlbmRlcgp0YXBwbHkobGFwb3AxOCRpbmc0ciwgbGFwb3AxOCRhbWJpdG8sIG1lYW4sIG5hLnJtPVQpICNUbyB1cmJhbi1ydXJhbApgYGAKCldlIGNhbiByZXByb2R1Y2UgdGhlIGJhciBwbG90cyB0aGF0IGNvbXBhcmUgdGhlIGF2ZXJhZ2Ugc3VwcG9ydCBmb3IgZGVtb2NyYWN5IGJldHdlZW4gZ3JvdXBzIGJ5IGdlbmRlciBhbmQgdXJiYW4vcnVyYWwuCkZpcnN0LCBmb3IgZ2VuZGVyLCB5b3UgaGF2ZSB0byBjcmVhdGUgYSB0YWJsZSB3aXRoIHRoZSBkYXRhIG9mIHRoZSBtZWFuIGFuZCB0aGUgbGltaXRzIG9mIHRoZSBjb25maWRlbmNlIGludGVydmFscyBmb3IgZWFjaCBncm91cC4KV2Ugd2lsbCBkbyB0aGlzIHdpdGggdGhlIGNvbW1hbmQgYGdyb3VwLkNJYCB3aGljaCBpcyBwYXJ0IG9mIHRoZSBsaWJyYXJ5IGBSbWlzY2AuCldlIHNhdmUgdGhpcyBkYXRhIGluIGFuIFIgb2JqZWN0IGNhbGxlZCAic2R4Z2VuIi4KClRoaXMgdGFibGUgc2F2ZXMgdGhlIHJlc3VsdHMgb2YgdGhlIG1lYW4gc3VwcG9ydCBmb3IgZGVtb2NyYWN5IGZvciBlYWNoIGdyb3VwICgiaW5nNHIubWVhbiIgY29sdW1uKSBhbmQgdGhlIHVwcGVyIGFuZCBsb3dlciBsaW1pdHMgb2YgdGhlIGNvbmZpZGVuY2UgaW50ZXJ2YWxzICgiaW5nNHIubG93ZXIiIGFuZCAiaW5nNHIudXBwZXIiIGNvbHVtbnMpLgpJdCBhbHNvIHNhdmVzIHRoZSAiZ2VuZGVyIiBjb2x1bW4gd2l0aCB0aGUgbmFtZXMgb2YgdGhlIGdyb3Vwcy4KCkZpZ3VyZSAxLjUgaXMgcmVwcm9kdWNlZCB1c2luZyB0aGUgY29tbWFuZCBgZ2dwbG90YCBpbiB0aGUgc2FtZSB3YXkgYXMgaW4gcHJldmlvdXMgc2VjdGlvbnMuCgpgYGB7ciBhcG95b3hnZW59CmxpYnJhcnkoUm1pc2MpCnNkeGdlbiA9IGdyb3VwLkNJKGluZzRyfmdlbmRlciwgbGFwb3AxOCkKbGlicmFyeShnZ3Bsb3QyKQpncmFmMS41ID0gZ2dwbG90KHNkeGdlbiwgYWVzKHg9Z2VuZGVyLCB5PWluZzRyLm1lYW4pKSsKICBnZW9tX2Jhcih3aWR0aD0wLjUsIGZpbGw9ImRhcmtjeWFuIiwgY29sb3VyPSJibGFjayIsIHN0YXQ9ImlkZW50aXR5IikrCiAgZ2VvbV9lcnJvcmJhcihhZXMoeW1pbj1pbmc0ci5sb3dlciwgeW1heD1pbmc0ci51cHBlciksIHdpZHRoPTAuMikrCiAgZ2VvbV90ZXh0KGFlcyhsYWJlbD1wYXN0ZShyb3VuZChpbmc0ci5tZWFuLCAxKSwgIiUiKSksIHZqdXN0PS0xLjUsIHNpemU9NCkrCiAgeGxhYigiR2VuZGVyIikgKyB5bGFiKCJTdXBwb3J0IGZvciBkZW1vY3JhY3kgKCUpIikrCiAgeWxpbSgwLCA3MCkKZ3JhZjEuNQpgYGAKCkEgc2ltaWxhciBncmFwaCBjYW4gYmUgZ2VuZXJhdGVkIHRoYXQgcHJlc2VudHMgdGhlIHBlcmNlbnRhZ2Ugb2Ygc3VwcG9ydCBmb3IgZGVtb2NyYWN5IGFuZCB0aGUgY29uZmlkZW5jZSBpbnRlcnZhbHMgYnkgdXJiYW4gYW5kIHJ1cmFsIGdyb3Vwcy4KCmBgYHtyIGFwb3lveGFtYn0Kc2R4YW1iIDwtIGdyb3VwLkNJKGluZzRyfmFtYml0bywgbGFwb3AxOCkKbGlicmFyeShnZ3Bsb3QyKQpncmFmMS41XzIgPSBnZ3Bsb3Qoc2R4YW1iLCBhZXMoeD1hbWJpdG8sIHk9aW5nNHIubWVhbikpKwogIGdlb21fYmFyKHdpZHRoPTAuNSwgZmlsbD0iZGFya2N5YW4iLCBjb2xvdXI9ImJsYWNrIiwgc3RhdD0iaWRlbnRpdHkiKSsKICBnZW9tX2Vycm9yYmFyKGFlcyh5bWluPWluZzRyLmxvd2VyLCB5bWF4PWluZzRyLnVwcGVyKSwgd2lkdGg9MC4yKSsKICBnZW9tX3RleHQoYWVzKGxhYmVsPXBhc3RlKHJvdW5kKGluZzRyLm1lYW4sIDEpLCAiJSIpKSwgdmp1c3Q9LTEuNSwgc2l6ZT00KSsKICB4bGFiKCJQbGFjZSBvZiByZXNpZGVuY2UiKSArIHlsYWIoIlN1cHBvcnQgZm9yIGRlbW9jcmFjeSAoJSkiKSsKICB5bGltKDAsIDcwKQpncmFmMS41XzIKYGBgCgpUaGUgTEFQT1AgTGFiIGdlbmVyYWxseSBwcmVzZW50cyB0aGUgY29uZmlkZW5jZSBpbnRlcnZhbHMgb2YgZWFjaCBncm91cCBpbiBpdHMgZ3JhcGhzLgpUaGVzZSBncmF5IGJhcnMgb24gdGhlIHJlcG9ydCBzZXJ2ZSBhcyBhIHF1aWNrIHdheSB0byBjb21wYXJlLgpJZiB0aGUgYmFycyBvdmVybGFwLCB0aGF0IHdvdWxkIG1lYW4gdGhhdCB0aGVyZSB3b3VsZCBiZSBubyBzdGF0aXN0aWNhbGx5IHNpZ25pZmljYW50IGRpZmZlcmVuY2VzIGJldHdlZW4gdGhlIGdyb3Vwcy4KT24gdGhlIGNvbnRyYXJ5LCBpZiB0aGUgZ3JheSBiYXJzIGRvIG5vdCBvdmVybGFwLCBpdCB3b3VsZCBtZWFuIHRoYXQgdGhlIGRpZmZlcmVuY2UgYmV0d2VlbiB0aGUgZ3JvdXBzIGlzIHNpZ25pZmljYW50IGF0IDk1JSBjb25maWRlbmNlLgpIb3dldmVyLCB0byBjaGVjayB0aGVzZSBjb25jbHVzaW9ucywgYSBzdGF0aXN0aWNhbCB0ZXN0IGhhcyB0byBiZSBjYWxjdWxhdGVkLgpXaGVuIHRoZSBjb21wYXJpc29uIGlzIGJldHdlZW4gdGhlIG1lYW5zIG9mIHR3byBncm91cHMsIHRoZSBhcHByb3ByaWF0ZSBzdGF0aXN0aWNhbCB0ZXN0IGlzIHRoZSB0LXRlc3QgZm9yIGRpZmZlcmVuY2VzIG9mIG1lYW5zLgpJbiB0aGlzIHNlY3Rpb24gd2UgYXJlIGFzc3VtaW5nIHRoYXQgd2UgY2FuIHRyZWF0IHRoZSB2YXJpYWJsZSAiamMxNWEiIGFuZCAiaW5nNHIiIGFzIG51bWVyaWNhbCB2YXJpYWJsZXMsIGZyb20gd2hpY2ggdGhlIG1lYW4gYW5kIHN0YW5kYXJkIGRldmlhdGlvbiBjYW4gYmUgY2FsY3VsYXRlZCwgYWx0aG91Z2ggdGhlc2UgdmFyaWFibGVzIGFyZSBzdHJpY3RseSBhIG5vbWluYWwgcXVhbGl0YXRpdmUgdHlwZS4KCiMgVC10ZXN0CgpTdHVkZW50J3MgdCB0ZXN0cyB0aGUgZm9sbG93aW5nIGh5cG90aGVzZXM6CgokJApIXzA6IMK1XzEgPSDCtV8yCiQkCgokJApIX2E6IMK1XzEg4omgIMK1XzIKJCQKClRoZSB0LXRlc3Qgc3RhdGlzdGljIGlzIGNhbGN1bGF0ZWQgd2l0aCBhIHN0YW5kYXJkIGVycm9yIHRoYXQgZGVwZW5kcyBvbiB3aGV0aGVyIHRoZSB2YXJpYW5jZXMgYXBwZWFyIGRpZmZlcmVudCBvciB3aGV0aGVyIHRoZSB2YXJpYW5jZXMgYXBwZWFyIGVxdWFsLgpUbyBkZXRlcm1pbmUgdGhpcyBjb25kaXRpb24sIHRoZSBmaXJzdCB0aGluZyBpcyB0byBjYWxjdWxhdGUgYSB0ZXN0IG9mIGVxdWFsaXR5IG9mIHZhcmlhbmNlcyBiZXR3ZWVuIHRoZSBncm91cHMsIGNhbGxlZCBMZXZlbmUncyB0ZXN0LgoKJCQKSF8wOiB2YXJfMSA9IHZhcl8yCiQkCgokJApIX2E6IHZhcl8xIOKJoCB2YXJfMgokJAoKIyMgVC10ZXN0IGZvciB0aGUgZGlmZmVyZW5jZSBpbiBtZWFucyBvZiBjcmltZSB2aWN0aW1pemF0aW9uIGJ5IGdlbmRlcgoKVGhlIGZpcnN0IHN0ZXAgaXMgdG8gcnVuIHRoZSBMZXZlbmUgdGVzdCB0byBldmFsdWF0ZSBpZiB2YXJpYW5jZXMgYXJlIGVxdWFsIG9yIGRpZmZlcmVudCwgd2hpY2ggaXMgYSBjb25kaXRpb24gdGhhdCB0aGVuIGlzIHVzZWQgaW4gdGhlIHQtdGVzdC4KVG8gcnVuIHRoaXMgdGVzdCwgd2UgdXNlIHRoZSBsaWJyYXJ5IGBEZXNjVG9vbHNgIHRoYXQgaW5jbHVkZXMgdGhlIGNvbW1hbmQgYExldmVuZVRlc3RgLgoKYGBge3J9CmxpYnJhcnkoRGVzY1Rvb2xzKQpMZXZlbmVUZXN0KGxhcG9wMjEkY3JpbWUsIGxhcG9wMjEkZ2VuZGVyKQpgYGAKCkJlY2F1c2UgdGhlIHAtdmFsdWUgKFByKFw+RikpIGlzIGxvd2VyIHRoYW4gMC4wNSwgd2UgcmVqZWN0IHRoZSBudWxsIGh5cG90aGVzaXMgYW5kIGFmZmlybSB0aGF0IHZhcmlhbmNlcyBhcmUgZGlmZmVyZW50LgpXaXRoIHRoaXMgcmVzdWx0LCB3ZSBjYW4gcnVuIHRoZSBjb21tYW5kIGB0LnRlc3RgLCB3aGljaCBudWxsIGh5cG90aGVzaXMgaW5kaWNhdGVzIHRoYXQgbWVhbnMgb2YgY3JpbWUgdmljdGltaXphdGlvbiBhcmUgZXF1YWwgYmV0d2VlbiBtZW4gYW5kIHdvbWVuLCBhbmQgdGhlIGFsdGVybmF0aXZlIGh5cG90aGVzaXMgaW5kaWNhdGVzIHRoYXQgYm90aCBtZWFucyBhcmUgZGlmZmVyZW50LgpXZSBpbmNsdWRlIHRoZSBzcGVjaWZpY2F0aW9uIGB2YXIuZXF1YWwgPSBGYCBiZWNhdXNlIHRoZSByZXN1bHRzIG9mIHRoZSBMZXZlbmUgdGVzdCBpbmRpY2F0ZXMgdGhhdCB2YXJpYW5jZXMgc2VlbSBkaWZmZXJlbnQuCgpgYGB7cn0KdC50ZXN0KGNyaW1lIH4gZ2VuZGVyLCBkYXRhID0gbGFwb3AyMSwgdmFyLmVxdWFsPUYpCmBgYAoKVGhlIHAtdmFsdWUgaXMgbG93ZXIgdGhhbiAwLjA1LgpXaXRoIHRoaXMgcmVzdWx0LCB3ZSBjYW4gcmVqZWN0IHRoZSBudWxsIGh5cG90ZXNpcyBhbmQgYWZmaXJtIHRoZSBhbHRlcm5hdGl2ZSBoeXBvdGhlc2lzIHRoYXQgbWVhbnMgYmV0d2VlbiBib3RoIGdyb3VwcyBhcmUgZGlmZmVyZW50LgpXZSBjb25jbHVkZSB0aGF0IG1lbiByZXBvcnQgYSBoaWdoZXIgY3JpbWUgdmljdGltaXphdGlvbiB0aGFuIHdvbWVuIGluIHRoZSByZWdpb24uCgojIyBULXRlc3QgZm9yIHRoZSBkaWZmZXJlbmNlIGluIG1lYW5zIG9mIHN1cHBvcnQgZm9yIGRlbW9jcmFjeSBieSBnZW5kZXIKClRoZSBmaXJzdCBzdGVwIGlzIHRvIGRvIHRoZSBMZXZlbmUgdGVzdC4KVG8gcnVuIHRoaXMgdGVzdCwgdGhlIGxpYnJhcnkgYERlc2NUb29sc2AgaXMgdXNlZCwgd2hpY2ggaW5jbHVkZXMgdGhlIGNvbW1hbmQgYExldmVuZVRlc3RgLgoKYGBge3IgTGV2ZW5lfQpsaWJyYXJ5KERlc2NUb29scykKTGV2ZW5lVGVzdChsYXBvcDE4JGluZzRyLCBsYXBvcDE4JGdlbmRlcikKYGBgCgpBcyB0aGUgcC12YWx1ZSAoUHIoXD5GKSBpcyBsZXNzIHRoYW4gMC4wNSwgdGhlIG51bGwgaHlwb3RoZXNpcyBpcyByZWplY3RlZCBhbmQgaXQgaXMgc3RhdGVkIHRoYXQgdGhlIHZhcmlhbmNlcyBhcmUgZGlmZmVyZW50LgpXaXRoIHRoaXMgcmVzdWx0LCB0aGUgY29tbWFuZCBgdC50ZXN0YCBjYW4gYmUgcnVuLCB3aG9zZSBudWxsIGh5cG90aGVzaXMgaW5kaWNhdGVzIHRoYXQgdGhlIG1lYW5zIG9mIHN1cHBvcnQgZm9yIGRlbW9jcmFjeSBhcmUgdGhlIHNhbWUgYmV0d2VlbiBtZW4gYW5kIHdvbWVuIGFuZCB0aGUgYWx0ZXJuYXRpdmUgaHlwb3RoZXNpcyBpbmRpY2F0ZXMgdGhhdCBib3RoIG1lYW5zIGFyZSBkaWZmZXJlbnQuClRoZSBzcGVjaWZpY2F0aW9uIGB2YXIuZXF1YWwgPSBGYCBpcyBpbmNsdWRlZCBkdWUgdG8gdGhlIHJlc3VsdCBvZiBMZXZlbmUncyB0ZXN0IGluZGljYXRpbmcgdGhhdCB0aGUgdmFyaWFuY2VzIGFwcGVhciBkaWZmZXJlbnQuCgpgYGB7ciB0LXRlc3R9CnQudGVzdChpbmc0ciB+IGdlbmRlciwgZGF0YSA9IGxhcG9wMTgsIHZhci5lcXVhbD1GKQpgYGAKClRoZSB2YWx1ZSBvZiB0aGUgcC12YWx1ZSAoNC41OWUtMDkpIGlzIGxlc3MgdGhhbiAwLjA1LCBzbyB0aGUgbnVsbCBoeXBvdGhlc2lzIGlzIHJlamVjdGVkIGFuZCB0aGUgYWx0ZXJuYXRpdmUgaXMgYWZmaXJtZWQsIGNvbmNsdWRpbmcgdGhhdCB0aGUgZGlmZmVyZW5jZXMgYXJlIGRpZmZlcmVudCBpbiB0aGUgcG9wdWxhdGlvbiBhdCA5NSUgY29uZmlkZW5jZS4KCiMjIFQtdGVzdCBmb3IgdGhlIGRpZmZlcmVuY2UgaW4gbWVhbnMgb2Ygc3VwcG9ydCBmb3IgZGVtb2NyYWN5IGJ5IGRvbWFpbiBncm91cHMKCkluIHRoZSBzYW1lIHdheSBhcyBpbiB0aGUgcHJldmlvdXMgY2FzZSwgTGV2ZW5lJ3MgdGVzdCBpcyBmaXJzdCBydW4gdG8gYW5hbHl6ZSB0aGUgZXF1YWxpdHkgb2YgdmFyaWFuY2VzLgoKYGBge3IgTGV2ZW5lIDJ9CkxldmVuZVRlc3QobGFwb3AxOCRpbmc0ciwgbGFwb3AxOCRhbWJpdG8pCmBgYAoKQWdhaW4sIHRoZSBwLXZhbHVlIGlzIGxlc3MgdGhhbiAwLjA1LCB3aGljaCByZWplY3RzIHRoZSBoeXBvdGhlc2lzIG9mIGVxdWFsaXR5IG9mIHZhcmlhbmNlcy4KVGhlIHQtdGVzdCBpcyB0aGVuIHJ1biB3aXRoIHRoZSBzcGVjaWZpY2F0aW9uIG9mIGRpZmZlcmVudCB2YXJpYW5jZXMuCgpgYGB7ciB0LXRlc3QgMn0KdC50ZXN0KGluZzRyIH4gYW1iaXRvLCBkYXRhID0gbGFwb3AxOCwgdmFyLmVxdWFsPUYpCmBgYAoKSW4gdGhpcyBjb21wYXJpc29uLCB0aGUgcC12YWx1ZSBpcyBhbHNvIGxlc3MgdGhhbiAwLjA1LCBzbyB0aGUgbnVsbCBoeXBvdGhlc2lzIGlzIHJlamVjdGVkIGFuZCBpdCBpcyBmb3VuZCB0aGF0IHRoZSBkaWZmZXJlbmNlcyBpbiBzdXBwb3J0IGZvciBkZW1vY3JhY3kgYmV0d2VlbiB1cmJhbiBhbmQgcnVyYWwgYXJlYXMgaXMgc3RhdGlzdGljYWxseSBzaWduaWZpY2FudCBhdCA5NSUgY29uZmlkZW5jZS4KQXMgdGhlIHJlcG9ydCBpbmRpY2F0ZXMsICJDb25zaWRlcmluZyB0aGUgcmVnaW9uIGFzIGEgd2hvbGUsIEZpZ3VyZSAxLjUgc2hvd3Mgc3RhdGlzdGljYWxseSBzaWduaWZpY2FudCByZWxhdGlvbnNoaXBzIGJldHdlZW4gZml2ZSBkZW1vZ3JhcGhpYyB2YXJpYWJsZXMgYW5kIHNvY2lvZWNvbm9taWMgZ3JvdXBzIChlZHVjYXRpb24sIHdlYWx0aCwgdXJiYW4vcnVyYWwgcmVzaWRlbmNlLCBnZW5kZXIsIGFuZCBhZ2UpIGFuZCBzdXBwb3J0IGZvciBkZW1vY3JhY3kiIChwLiAxMykuCkluIHRoaXMgc2VjdGlvbiB3ZSBoYXZlIGNoZWNrZWQgdGhlc2Ugc3RhdGlzdGljYWwgcmVzdWx0cyBmb3IgZGVtb2dyYXBoaWMgdmFyaWFibGVzIG9mIHR3byBncm91cHMsIHN1Y2ggYXMgZ2VuZGVyIGFuZCB1cmJhbi9ydXJhbCByZXNpZGVuY2UuCgojIFN1bW1hcnkKCkluIHRoaXMgc2VjdGlvbiB3ZSBoYXZlIGRlc2NyaWJlZCBhbmQgcGxvdHRlZCBhIHZhcmlhYmxlLCBzdWNoIGFzIHN1cHBvcnQgZm9yIGRlbW9jcmFjeSwgYnkgZ3JvdXBzIG9mIG90aGVyIHZhcmlhYmxlLCBzdWNoIGFzIGdlbmRlci4KU3RhcnRpbmcgZnJvbSB0aGUgY29tcGFyaXNvbiBvZiBjb25maWRlbmNlIGludGVydmFscywgd2UgZm9ybWFsaXplIHRoaXMgY29tcGFyaXNvbiB3aXRoIGEgc3RhdGlzdGljYWwgdGVzdCwgc3VjaCBhcyB0aGUgdC10ZXN0LCB0byBjb25jbHVkZSB3aGV0aGVyIHRoZSBkaWZmZXJlbmNlcyBiZXR3ZWVuIGdyb3VwcyBhcmUgc3RhdGlzdGljYWxseSBzaWduaWZpY2FudC4KCiMgQ2FsY3VsYXRpb25zIGluY2x1ZGluZyBzdXJ2ZXkgd2VpZ2h0cwoKIyMgRm9yIGNyaW1lIHZpY3RpbWl6YXRpb24KClRvIGNhbGN1bGF0ZSB0aGUgZGlmZmVyZW5jZSBvZiBtZWFucyBpbmNsdWRpbmcgYSBzdXJ2ZXkgd2VpZ2h0LCB3ZSBjYW4gdXNlIHRoZSBsaWJyYXJ5IGBzdXJ2ZXlgLgpUaGlzIGxpYnJhcnkgcmVxdWlyZXMgYSBjaGFuZ2UgaW4gdGhlIGRhdGFzZXQsIGluIHRoZSBzYW1lIHdheSBhcyB3ZSBkaWQgaW4gdGhpcyBbc2VjdGlvbl0oaHR0cHM6Ly9hcnR1cm9tYWxkb25hZG8uZ2l0aHViLmlvL0Jhcm9tZXRyb0VkdV9XZWJfRW5nL0Rlc2NyaXB0aXZlczIuaHRtbCkuCgpgYGB7ciBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFLCBpbmNsdWRlPUZBTFNFfQpsYXBvcDIxID0gc3Vic2V0KGxhcG9wMjEsICFpcy5uYSh3ZWlnaHQxNTAwKSkKc2FwcGx5KGxhcG9wMjEsIGhhdmVuOjp6YXBfbGFiZWxzKQpgYGAKCk9uY2Ugd2UgZml0IHRoZSBkYXRhc2V0LCB3ZSBoYXZlIHRvIGRlZmluZSB0aGUgc2FtcGxpbmcgZGVzaWduIHdpdGggdGhlIGNvbW1hbmQgYHN2eWRlc2lnbmAgYW5kIHdlIHNhdmUgdGhpcyBkZXNpZ24gaW4gYW4gb2JqZWN0IGNhbGxlZCAiZGVzaWduMjEiLgoKYGBge3J9CmxpYnJhcnkoc3VydmV5KQpkZXNpZ24yMSA9IHN2eWRlc2lnbihpZHMgPSB+dXBtLCBzdHJhdGEgPSB+c3RyYXRhLCB3ZWlnaHRzID0gfndlaWdodDE1MDAsIG5lc3Q9VFJVRSwgZGF0YT1sYXBvcDIxKQpgYGAKCk5vdyB3ZSBjYW4gY2FsY3VsYXRlIHRoZSB0YWJsZSBvZiB0aGUgbWVhbiBvZiBjcmltZSB2aWN0aW1pemF0aW9uIGZvciBlYWNoIGdyb3VwIG9mIGdlbmRlciwgaW5jbHVkaW5nIHRoZSBzdXJ2ZXkgd2VpZ2h0LgpJbiB0aGUgc2FtZSB3YXkgYXMgd2Ugc2VlIGluIHRoZSBzZWN0aW9uIG9uIFtjb25maWRlbmNlIGludGVydmFsc10oaHR0cHM6Ly9hcnR1cm9tYWxkb25hZG8uZ2l0aHViLmlvL0Jhcm9tZXRyb0VkdV9XZWJfRW5nL0lDLmh0bWwpLCB3ZSB1c2UgdGhlIGNvbW1hbmQgYHN2eWJ5YC4KCmBgYHtyfQpjcnhnZW4udyA9IHN2eWJ5KH5jcmltZSwgfmdlbmRlciwgZGVzaWduMjEsIHN2eW1lYW4sIG5hLnJtPVQsIHZhcnR5cGUgPSAiY2kiKQpjcnhnZW4udwpgYGAKCkl0IHNob3VsZCBiZSBub3RlZCB0aGF0IHRoZXNlIHJlc3VsdHMgYXJlIGVxdWFsIHRvIHRob3NlIHByZXNlbnRlZCBpbiBGaWd1cmUgMy4xMi4KV2l0aCB0aGlzIHRhYmxlIHdlIGNhbiBwcm9jZWVkIHRvIHJlcGxpY2F0ZSB0aGUgbGVmdCBwYW5lbCBvZiB0aGlzIGZpZ3VyZSwgaW4gdGhlIHNhbWUgbWFubmVyIGFzIHdlIGRpZCBhYm92ZSBpbiB0aGlzIHNlY3Rpb24uCgpGb3IgdGhlIGNhbGN1bGF0aW9uIG9mIHRoZSB0LXRlc3Qgb2YgZGlmZmVyZW5jZSBvZiBtZWFucywgdGhlIGxpYnJhcnkgYHN1cnZleWAgaGFzIGEgbmF0aXZlIGNvbW1hbmQsIGNhbGxlZCBgc3Z5dHRlc3RgLCB0aGF0IGFsbG93cyB0byBwZXJmb3JtIHRoaXMgdGVzdC4KSG93ZXZlciwgd2UgZG8gbm90IGhhdmUgYSBjb21tYW5kIHRvIGV2YWx1YXRlIHRoZSB2YXJpYW5jZXMsIGFzIHRoZSBMZXZlbmUgdGVzdC4KVGhlIGNvbW1hbmQgYHN2eXR0ZXN0YCBpcyBhIGRldmVsb3BtZW50IG9mIGEgbW9yZSBnZW5lcmFsIGNvbW1hbmQgZm9yIGdlbmVyYWxpemVkIGxpbmVhciBtb2RlbHMsIHdoaWNoIGFzc3VtZSB2YXJpYW5jZXMgYXJlIGVxdWFsLgpJZiB3ZSB3b3VsZCBsaWtlIHRvIHZhbGlkYXRlIHRoaXMgYXNzdW1wdGlvbiwgd2UgY2FuIGRvIGl0IG1hbnVhbGx5LCBhcyBleHBsYWluZWQgaW4gdGhpcyBbbGlua10oaHR0cHM6Ly9zdGF0cy5zdGFja2V4Y2hhbmdlLmNvbS9xdWVzdGlvbnMvMTQ4MzE0L2YtdGVzdC1mb3ItZXF1YWxpdHktb2YtdmFyaWFuY2VzLXdpdGgtd2VpZ2h0ZWQtc3VydmV5LWRhdGEpLgpIZXJlIHdlIGFyZSBnb2luZyB0byBwcm9jZWVkIGFzIGlmIGFzc3VtcHRpb24gaXMgY29ycmVjdC4KV2Ugb2JzZXJ2ZSB0aGlzIGNvbW1hbmQgZ2V0IHJlc3VsdHMgdmVyeSBzaW1pbGFyIHRvIHRob3NlIG9idGFpbmVkIHdpdGggbm8gc3VydmV5IHdlaWdodHMgYW5kLCBmb3IgYWxsIGVmZmVjdCwgd2UgYXJyaXZlIHRvIHRoZSBzYW1lIGNvbmNsdXNpb25zLgpUaGUgcC12YWx1ZSBpcyBsb3dlciB0aGFuIDAuMDUsIHNvIHdlIGNhbiByZWplY3QgdGhlIG51bGwgaHlwb3RoZXNpcyBhbmQgYWZmaXJtIHRoZXJlIGFyZSBkaWZmZXJlbmNlcyBiZXR3ZWVuIG1lbiBhbmQgd29tZW4gaW4gdGhlaXIgbGV2ZWxzIG9mIGNyaW1lIHZpY3RpbWl6YXRpb24sIHRha2luZyBpbnRvIGFjY291bnQgdGhlIHN1cnZleSB3ZWlnaHRzLgoKYGBge3J9CnN2eXR0ZXN0KGNyaW1lfmdlbmRlciwgZGVzaWduMjEpCmBgYAoKIyMgRm9yIHN1cHBvcnQgZm9yIGRlbW9jcmFjeQoKT3RoZXIgd2F5IHRvIGNhbGN1bGF0ZSB0aGUgZGlmZmVyZW5jZSBvZiBtZWFucyBpbmNsdWRpbmcgdGhlIHN1cnZleSB3aWVpZ2h0IGlzIGJ5IHVzaW5nIHRoZSBsaWJyYXJ5IGBzdXJ2ZXlgLgpGb3IgdGhpcyB3ZSBoYXZlIHRvIGRlZmluZSB0aGUgc2FtcGxlIGRlc2lnbiB3aXRoIHRoZSBjb21tYW5kIGBzdnlkZXNpZ25gIGFuZCBzYXZlIHRoaXMgZGVzaWduIGluIGFuIG9iamVjdCwgaGVyZSBjYWxsZWQgImRlc2lnbjE4Ii4KCmBgYHtyIHN1cnZleSwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KbGlicmFyeShzdXJ2ZXkpCmRlc2lnbjE4ID0gc3Z5ZGVzaWduKGlkcyA9IH51cG0sIHN0cmF0YSA9IH5lc3RyYXRvcHJpLCB3ZWlnaHRzID0gfndlaWdodDE1MDAsIG5lc3Q9VFJVRSwgZGF0YT1sYXBvcDE4KQpgYGAKCkZpcnN0LCB0aGUgdGFibGUgb2YgdGhlIG1lYW4gc3VwcG9ydCBmb3IgZGVtb2NyYWN5IGNhbiBiZSBjYWxjdWxhdGVkIGZvciBlYWNoIHZhbHVlIG9mIHRoZSB2YXJpYWJsZSBnZW5kZXIsIGluY2x1ZGluZyB0aGUgc3VydmV5IHdlaWdodC4KSW4gdGhlIHNhbWUgd2F5IGFzIHNlZW4gaW4gdGhlIHNlY3Rpb24gb24gW2NvbmZpZGVuY2UgaW50ZXJ2YWxzXShodHRwczovL2FydHVyb21hbGRvbmFkby5naXRodWIuaW8vQmFyb21ldHJvRWR1X1dlYi9JQy5odG1sKSwgYW5kIHVzZSB0aGUgY29tbWFuZCBgc3Z5YnlgLgoKYGBge3IgdGFibGV3ZWlnaHRlZH0Kc2R4Z2VuLncgPSBzdnlieSh+aW5nNHIsIH5nZW5kZXIsIGRlc2lnbjE4LCBzdnltZWFuLCBuYS5ybT1ULCB2YXJ0eXBlID0gImNpIikKc2R4Z2VuLncKYGBgCgpXaXRoIHRoaXMgdGFibGUgeW91IGNhbiBwcm9jZWVkIHRvIGNyZWF0ZSB0aGUgYmFyIHBsb3QsIGluIHRoZSBzYW1lIHdheSB0aGF0IHdhcyBkb25lIGFib3ZlIGluIHRoaXMgc2VjdGlvbi4KCkZvciB0aGUgY2FsY3VsYXRpb24gb2YgdGhlIHQtdGVzdCBmb3IgZGlmZmVyZW5jZSBvZiBtZWFucywgdGhlIHBhY2thZ2UgYHN1cnZleWAgaGFzIGEgbmF0aXZlIGNvbW1hbmQgYHN2eXR0ZXN0YHRoYXQgYWxsb3dzIHRoaXMgY2FsY3VsYXRpb24uCgpgYGB7ciB0d2VpZ2h0ZWR9CnN2eXR0ZXN0KGluZzRyfmdlbmRlciwgZGVzaWduMTgpCmBgYAoKQmVjYXVzZSB0aGUgcC12YWx1ZSBpcyBsb3dlciB0aGFuIDAuMDUsIHdlIGNvbmNsdWRlIHRoZXJlIGFyZSBkaWZmZXJlbmNlcyBiZXR3ZWVuIG1lbiBhbmQgd29tZW4gaW4gdGhlaXIgbGV2ZWxzIG9mIHN1cHBvcnQgZm9yIGRlbW9jcmFjeSBpbiB0aGUgcmVnaW9uLgo=