Introduction
The previous sections corresponding to the t-test
and the ANOVA
test are about the relationship of a numerical variable with a
categorical variable, in such a way that the goal is to compare and
extrapolate the means of a numerical variable by groups of a categorical
variable.
In this section we will look at bivariate relationships between two
categorical (or factor in R terminology) variables. This evaluation is
done using cross-tables (or contingency tables) and is evaluated using
the chi-square test.
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. We can download the data freely here.
This section loads a trimmed database, originally in SPSS (.sav)
format. It is recommended to clean the Environment before starting this
section.
This dataset is hosted in the “materials_edu” repository of the LAPOP
account on GitHub. Using the library rio
and the command
import
, we 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.
lapop21 = import("https://raw.github.com/lapop-central/materials_edu/main/lapop21.RData")
lapop21 = subset(lapop21, pais<=35)
Votes are counted fairly
The report The Pulse of Democracy for the 2021 round of the
AmericasBarometer reports the results of variable
COUNTFAIR1. Votes are counted correctly and fairly.
Would you say it happens always, sometimes or never? Percentages are
presented by countries.
This figure is reporting the cross of a categorical variable (or
factor in R language), called “countfair1” that has three categories
(never, sometimes and always), with other categorical variables called
“pais” that has 15 categories (each country presented).
This variable is imported in R as numeric. For be able to work with
this variable, we have to declare it as a factor variable, using the
command as.factor
. We then label this variable with the
command levels
.
library(haven)
lapop21$countfair1r = as.factor(lapop21$countfair1)
levels(lapop21$countfair1r) = c("Always", "Sometimes", "Never")
table(lapop21$countfair1r)
##
## Always Sometimes Never
## 3477 5235 1698
Cross-table of votes are counted fairly by country
Before replicating this figure, it is useful to see results in a
cross-table. We can create this table with the command
table
. However, this table presents absolute frequencies.
Also, this table shows that this question was not fielded in some
countries.
table(lapop21$pais, lapop21$countfair1r)
##
## Always Sometimes Never
## 1 0 0 0
## 2 0 0 0
## 3 0 0 0
## 4 0 0 0
## 5 186 351 173
## 6 354 272 51
## 7 215 445 120
## 8 130 362 226
## 9 158 435 143
## 10 169 408 112
## 11 177 430 97
## 12 169 315 168
## 13 428 201 39
## 14 525 111 20
## 15 346 257 116
## 17 216 350 120
## 21 170 406 99
## 22 0 0 0
## 23 122 464 97
## 24 112 428 117
To reproduce the relative frequencies, we have to use the command
prop.table
. This command returns the percentages for the
total by defect. We want to calculate percentages by rows (that is, by
country) in this case.
prop.table(table(lapop21$pais, lapop21$countfair1r))
##
## Always Sometimes Never
## 1 0.000000000 0.000000000 0.000000000
## 2 0.000000000 0.000000000 0.000000000
## 3 0.000000000 0.000000000 0.000000000
## 4 0.000000000 0.000000000 0.000000000
## 5 0.017867435 0.033717579 0.016618636
## 6 0.034005764 0.026128722 0.004899135
## 7 0.020653218 0.042747358 0.011527378
## 8 0.012487992 0.034774256 0.021709894
## 9 0.015177714 0.041786744 0.013736792
## 10 0.016234390 0.039193084 0.010758886
## 11 0.017002882 0.041306436 0.009317963
## 12 0.016234390 0.030259366 0.016138329
## 13 0.041114313 0.019308357 0.003746398
## 14 0.050432277 0.010662824 0.001921230
## 15 0.033237272 0.024687800 0.011143132
## 17 0.020749280 0.033621518 0.011527378
## 21 0.016330451 0.039000961 0.009510086
## 22 0.000000000 0.000000000 0.000000000
## 23 0.011719500 0.044572526 0.009317963
## 24 0.010758886 0.041114313 0.011239193
To calculate the percentages by rows, we have to add the
specification , 1
in prop.table
. We can also
nest this code in the command addmargins
to calculate the
sum of horizontal percentages. These are the same percentages that are
presented in a bar plot below. These percentages are not equal to those
presented in Figure 2.5 because this calculation does not include survey
weights.
addmargins(prop.table(table(lapop21$pais, lapop21$countfair1r), 1)*100, 2)
##
## Always Sometimes Never Sum
## 1
## 2
## 3
## 4
## 5 26.197183 49.436620 24.366197 100.000000
## 6 52.289513 40.177253 7.533235 100.000000
## 7 27.564103 57.051282 15.384615 100.000000
## 8 18.105850 50.417827 31.476323 100.000000
## 9 21.467391 59.103261 19.429348 100.000000
## 10 24.528302 59.216255 16.255443 100.000000
## 11 25.142045 61.079545 13.778409 100.000000
## 12 25.920245 48.312883 25.766871 100.000000
## 13 64.071856 30.089820 5.838323 100.000000
## 14 80.030488 16.920732 3.048780 100.000000
## 15 48.122392 35.744089 16.133519 100.000000
## 17 31.486880 51.020408 17.492711 100.000000
## 21 25.185185 60.148148 14.666667 100.000000
## 22
## 23 17.862372 67.935578 14.202050 100.000000
## 24 17.047184 65.144597 17.808219 100.000000
Bar graph of votes are counted fairly by country
In the same way as we did in the section about ordinal variables,
available here,
we can replicate the comparative graph by country we have to create a
contingency table between variables “countfair1” and “pais”. This
cross-table is saved in an abject “count_pais”. We should note that the
dataframe include a row for each value of “countfair1” in each country.
In this way, we have 3 options x 20 countries = 60 rows.
count_pais = as.data.frame(round(prop.table(table(lapop21$pais, lapop21$countfair1r), 1), 3)*100)
count_pais
This table presents NAs for countries where the question “countfair1”
was not asked. For this reason, we have to drop rows where there is no
data. We can do this with the specification [-c(rows)]
.
After that we create a vector with the names of countries. We repeat
names three times (15 countries x 3 options). We dd this vector to the
dataframe in column “country”.
count_pais = count_pais[-c(1:4,18,21:24,38,41:44,58),]
country = c("Nicaragua","Costa Rica", "Panama", "Colombia", "Ecuador", "Bolivia", "Peru",
"Paraguay", "Chile", "Uruguay", "Brazil", "Argentina", "Dom. Rep.","Jamaica", "Guyana", "Nicaragua","Costa Rica", "Panama", "Colombia", "Ecuador", "Bolivia", "Peru",
"Paraguay", "Chile", "Uruguay", "Brazil", "Argentina", "Dom. Rep.","Jamaica", "Guyana","Nicaragua","Costa Rica", "Panama", "Colombia", "Ecuador", "Bolivia", "Peru",
"Paraguay", "Chile", "Uruguay", "Brazil", "Argentina", "Dom. Rep.","Jamaica", "Guyana")
count_pais$country = country
count_pais
We have the elements in this dataframe “count_pais” to replicate the
stacked bar plot. We specify in aes
that percentages are in
X axis, countries in Y axis and each bar is divided by column Var2.
library(ggplot2)
ggplot(data=count_pais, aes(x=Freq, y=country, fill=Var2))+
geom_bar(stat="identity", width=0.3)+
geom_text(aes(label=paste(Freq, "%", sep="")), color="white",
position=position_stack(vjust=0.5), size=2)+
labs(x="Percentage", y="Country", fill="Votes are counted fairly",
caption="AmericasBarometer by LAPOP, 2021")
Evaluating Democracy in Practice
From page 20, the report The Pulse of Democracy evaluates
democracy in practice. In particular, this section of the report uses
the variable “pn4”. This variable is worded as follows: “In general,
would you say that you are very satisfied, satisfied, dissatisfied, or
very dissatisfied with the way democracy works in (country)?”
The report indicates that this variable is recoded as a dichotomous
variable to be able to work with percentages. In this section we are
going to work with the original variable, which is an ordinal
categorical variable (or factor).
Figure 1.14 of the report presents an evaluation of satisfaction with
democracy by demographic and socioeconomic variables, such as
educational level, quintiles of wealth, place of residence, gender or
age groups. That is, satisfaction with democracy is used as the
dependent variable and each demographic or socioeconomic variable as the
independent variable.
For example, the report indicates that among men, 42.3% are satisfied
with democracy (using the variable recoded as a dummy), while among
women, this percentage drops to 36.9%. Here we are going to analyze
these same variables, but using the variable “pn4” in its original form
(as an ordinal categorical). Before proceeding, we need to recode the
variables as factor and label them.
lapop18$gender = as.factor(lapop18$q1)
levels(lapop18$gender) = c("Male", "Female")
table(lapop18$gender)
##
## Male Female
## 13943 14084
The same is done for the variable “pn4” which becomes a new variable
“satis”.
lapop18$satis = as.factor(lapop18$pn4)
levels(lapop18$satis) = c("Very satisfied", "Satisfied", "Dissatisfied", "Very dissatisfied")
table(lapop18$satis)
##
## Very satisfied Satisfied Dissatisfied Very dissatisfied
## 1727 8916 12455 3855
Cross-table of satisfaction with democracy by gender
With the new factor variables, we first calculate a cross-table or
contingency table. The command table
is used to present the
frequencies of one or two variables. By convention, the dependent
variable “satisfaction with democracy” is placed in the rows and the
independent variable “gender” in the columns.
table(lapop18$satis, lapop18$gender)
##
## Male Female
## Very satisfied 919 803
## Satisfied 4821 4091
## Dissatisfied 5994 6457
## Very dissatisfied 1874 1979
To calculate the relative frequencies, you have to nest the command
table
inside the command prop.table
. If nested
only, this command calculates the proportions over the total
observations.
prop.table(table(lapop18$satis, lapop18$gender))
##
## Male Female
## Very satisfied 0.03411538 0.02980919
## Satisfied 0.17896652 0.15186725
## Dissatisfied 0.22251095 0.23969857
## Very dissatisfied 0.06956715 0.07346499
These proportions are not very useful for the comparison we want to
make. What we require are the conditional distributions of “satisfaction
with democracy” for each gender group. That is, calculate the
percentages for each column. In order for prop.table
to
calculate these percentages, we have to add the specification
(…, 2)
. Multiply by 100 to go from ratios to percentages.
You can also nest all code inside the command addmargins
to
check the sum of percentages over the columns, with the specification
(..., 1)
.
addmargins(prop.table(table(lapop18$satis, lapop18$gender), 2)*100, 1)
##
## Male Female
## Very satisfied 6.753380 6.024006
## Satisfied 35.427690 30.690173
## Dissatisfied 44.047619 48.439610
## Very dissatisfied 13.771311 14.846212
## Sum 100.000000 100.000000
The table shows that 6.8% of men are very satisfied with democracy, a
percentage very similar to that of women. 44% of men are dissatisfied
with democracy. In this category, women have a higher percentage
(48.4%).
In this way, it is possible to compare the percentages of the
dependent variable “satisfaction with democracy” for each category of
the independent variable “gender”.
Graphs of satisfaction with democracy by gender
In the section about descriptives
of ordinal variables, we presented a preview of what we are seeing
in this section. Here we will revisit those themes, using the
tidyverse.
To make the graph, we first create a new dataframe with the data from
the cross-table. The command as.data.frame
is used to
transform the bivariate table into a new dataframe called “table”. Using
this command, the results are sorted by new columns (Var1, Var2 and
Freq) so that they can be used to create a graph.
table = as.data.frame(prop.table(table(lapop18$satis, lapop18$gender), 2)*100)
table
We will use the library ggplot2
and the command
ggplot
to create a bar chart, using the dataframe “table”
containing the percentages of satisfaction with democracy for men and
women. This command requires an aesthetic where it is specified that
“Var1” will be included on the X axis, which corresponds to the
categories of satisfaction with democracy. The “Freq” is included on the
Y axis, which corresponds to percentages. Also included is the
specification fill
to indicate that it will be split into
Male/Female groups for each category of “Var1” and ymax
to
specify the upper limit of the Y axis.
After defining the variables in the axes, it is indicated that a bar
graph is wanted with the command geom_bar
and with the
specification position="dodge"
it is indicated that a graph
with bars separated by each combination of categories is wanted. The
specification stat="identity"
is added to indicate that the
command works with the data in the table.
The command geom_text
includes the percentages of each
bar, which is found in the “Freq” column. These percentages are rounded
with round
to 1 decimal place and the “%” symbol is added
with paste
. Also included is the specification
position=position_dodge(...)
which places these percentages
at the top of each column. The default option within this specification
is width=NULL
, but this way the percentages would be
misplaced, so width=0.9
is defined to center the
percentages.
By default, the legend includes the name of the column with the
gender data, which is “Var2”. To change this name, use the command
labs(fill="Gender")
to properly name the legend. Finally,
the Y and X axis are labeled with ylab
and
xlab.
library(ggplot2)
ggplot(data=table, aes(x=Var1, y=Freq, fill=Var2, ymax=60))+
geom_bar(position="dodge", stat="identity")+
geom_text(aes(label=paste(round(Freq, 1), "%", sep="")),
position=position_dodge(width=0.9), vjust=-0.25)+
labs(fill="Gender")+
ylab("Percentage")+
xlab("Satisfaction with democracy")
Other way to display this data is through stacked bars. That is, for
each gender category, the distribution of satisfaction with democracy is
shown. For this, we use the same command ggplot
but now the
order of the variables in the aesthetic is changed. Now the variable
“Var2” (with the gender categories) is located on the X axis and each
bar is divided according to the values of Var1.
The bar type changes in the command geom_bar
to
position="stack"
. In the same way, the data labels have to
consider the position of each slice, with
position=position_stack()
.
ggplot(data=table, aes(x=Var2, y=Freq, fill=Var1, ymax=100))+
geom_bar(position="stack", stat="identity")+
geom_text(aes(label=paste(round(Freq, 1), "%", sep="")),
position=position_stack(), vjust=2)+
labs(fill="Satisfaction with democracy")+
ylab("Percentage")+
xlab("Gender")
Cross-table of satisfaction with democracy by educational level
Figure 1.14 of the report shows the results on satisfaction with
democracy (according to the recoded dummy variable) by educational
level. As a second example, here we are going to replicate that
relationship using the original variable of type factor.
We first recode the education variable. The original variable “ed” is
a numerical variable (years of study). This variable has values ranging
from 0 to 18. It is recoded in such a way that those with zero years of
education are assigned a value of 0 “None”, those between 1 and 6 years
of education are assigned a value of 1 “Primary”, those between 7 and 11
years of education are assigns them the value of 2 “Secondary” and
between 12 and 18 years of education the value of 3
“Post-secondary”.
library(car)
lapop18$educ <- car::recode(lapop18$ed, "0=0; 1:6=1; 7:11=2; 12:18=3")
lapop18$educ <- as.factor(lapop18$educ)
levels(lapop18$educ) <- c("None", "Primary", "Secondary", "Post-secondary")
table(lapop18$educ)
##
## None Primary Secondary Post-secondary
## 643 6156 10176 10595
With the recoded variable it is possible to calculate the cross-table
of satisfaction with democracy by educational levels.
addmargins(prop.table(table(lapop18$satis, lapop18$educ), 2)*100, 1)
##
## None Primary Secondary Post-secondary
## Very satisfied 13.818182 9.874826 6.002645 4.324428
## Satisfied 38.363636 34.961752 33.045071 31.760523
## Dissatisfied 34.363636 42.576495 46.596805 48.596963
## Very dissatisfied 13.454545 12.586926 14.355479 15.318086
## Sum 100.000000 100.000000 100.000000 100.000000
To create the graph, we have to save the table as a dataframe. The
command as.data.frame
is used to save the percentages so
that they can be used with the command ggplot
.
table2 <- as.data.frame(prop.table(table(lapop18$satis, lapop18$educ), 2)*100)
table2
In this case, since we have 4 categories for satisfaction with
democracy and another 4 categories for educational levels, a bar graph
would create 16 bars, which would complicate the comparison. So, in this
case, the stacked bar type is preferred.
library(ggplot2)
ggplot(data=table2, aes(x=Var2, y=Freq, fill=Var1, ymax=100))+
geom_bar(position="stack", stat="identity")+
geom_text(aes(label=paste(round(Freq, 1), "%", sep="")),
position=position_stack(), vjust=2)+
labs(fill="Satisfaction with democracy")+
ylab("Percentage")+
xlab("Education level")
Figure 1.14 shows that there is a higher percentage of satisfaction
with democracy among the least educated. This relationship can also be
seen in this graph. The sectors “very satisfied” (in pink) and
“satisfied” (in green) decrease as we go from none to primary, secondary
and higher.
In all examples, we can observe percent differences in a variable by
categories of other variable. These percentages can be compared directly
in the graph, but we should run a significance test to evaluate if there
is a statistically significant relationship.
Chi-square test of independence
Two categorical variables are said to be statistically independent if
the conditional (population) distributions are identical for each
category of the independent variable. In the above bivariate
relationship, this means that being male or female does not change
opinions regarding satisfaction with democracy. As these conditional
distributions differ more from each other, both variables are said to be
more related or more dependent.
This evaluation is done using the chi-square or \(\chi^2\) test of independence. This test is
based on the comparison of the observed frequencies (the observations
collected in the field) versus the expected frequencies (the
observations that should be in each cell if the variables were
independent). The test statistic summarizes how close the expected
frequencies are to the observed frequencies.
\[
\chi^2 = \sum\frac{(f_o-f_e)^2}{f_e}
\]
The smaller the distance in each cell, the less likely it is to
reject the null hypothesis. The larger the distance in each cell, the
more likely it is to reject the null hypothesis.
\[
H0: f_o = f_e
\]
With the value of \(\chi^2\) and
with the degrees of freedom (rows-1*columns-1), a p-value is calculated
on the chi-square distribution. If this p-value is less than 0.05, H0 is
rejected. This test requires that there be at least 5 observations in
each cell.
Test of votes are counted fairly by country
In R, the command chisq.test
is used to calculate the
statistic and the associated p-value. The results of this test can be
saved to a new object “chitest1”.
chitest1 <- chisq.test(lapop21$countfair1r, lapop21$pais)
chitest1
##
## Pearson's Chi-squared test
##
## data: lapop21$countfair1r and lapop21$pais
## X-squared = 1691.6, df = 28, p-value < 2.2e-16
The p-value obtained is less than 0.05, so the H0 is rejected, so we
say that the observed frequencies seem to be different from the expected
frequencies that would exist in each cell if there were no relationship,
so we say that there is a relationship between the variables or that
there is a dependency between the two.
It is important to note that “chitest1” is an object of type
list. This type of object can store other information of a
different type. For example, “chitest1” saves the tables of observed
frequencies (same result as with the command table
) and the
table of expected frequencies. In this object the value of the
residuals, the standardized residuals and the value of the p-value are
also saved.
chitest1$observed
## lapop21$pais
## lapop21$countfair1r 5 6 7 8 9 10 11 12 13 14 15 17 21 23 24
## Always 186 354 215 130 158 169 177 169 428 525 346 216 170 122 112
## Sometimes 351 272 445 362 435 408 430 315 201 111 257 350 406 464 428
## Never 173 51 120 226 143 112 97 168 39 20 116 120 99 97 117
chitest1$expected
## lapop21$pais
## lapop21$countfair1r 5 6 7 8 9 10
## Always 237.1441 226.1219 260.5245 239.8161 245.8282 230.1300
## Sometimes 357.0461 340.4510 392.2478 361.0692 370.1210 346.4856
## Never 115.8098 110.4271 127.2277 117.1147 120.0507 112.3844
## lapop21$pais
## lapop21$countfair1r 11 12 13 14 15 17
## Always 235.1401 217.7718 223.1159 219.1078 240.1501 229.1280
## Sometimes 354.0288 327.8790 335.9251 329.8905 361.5720 344.9769
## Never 114.8311 106.3493 108.9591 107.0017 117.2778 111.8951
## lapop21$pais
## lapop21$countfair1r 21 23 24
## Always 225.4539 228.1259 219.4418
## Sometimes 339.4452 343.4683 330.3934
## Never 110.1009 111.4058 107.1648
To evaluate the strength of the relationship, we use the librery
vcd
that has the command assocstats
that
offers a series of measures of association for a cross-table between an
ordinal variable, as “countfair1”, and a nominal variable, as
“pais”.
The command assocstats
cannot calculate measures of
associations if cells of a cross-table have null values. Because we have
some countries where question “countfair1” was not asked, we have to
indicate that this command does not take into account these countries.
For deal with this, we create a new “country2” variable, where
observations of these countries are set as NAs.
lapop21$country_r = lapop21$pais
lapop21$country_r[lapop21$pais==1] = NA
lapop21$country_r[lapop21$pais==2] = NA
lapop21$country_r[lapop21$pais==3] = NA
lapop21$country_r[lapop21$pais==4] = NA
lapop21$country_r[lapop21$pais==22] = NA
With this new variable, we can create a cross-table between
“countfair1” and “country_r” and calculate measures of association.
library(vcd)
table2 <- table(lapop21$countfair1r, lapop21$country_r)
assocstats(table2)
## X^2 df P(> X^2)
## Likelihood Ratio 1639.2 28 0
## Pearson 1691.6 28 0
##
## Phi-Coefficient : NA
## Contingency Coeff.: 0.374
## Cramer's V : 0.285
The command assocstats
returns the contingency
coefficient and Cramer´s V as measures. These measures vary between 0
and 1. While closer to zero, the relationship is weaker. On the
contrary, while closer to 1, the relationship is stronger.
By convention, we can assume that weak relationships are between 0
and 0.3, moderate relationships betwen 0.3 and 0.6 and strong
relationships are higher than 0.6. In this case, we can indicate that
the relationship between votes are counted fairly and country is
weak.
Test of satisfaction with democracy by educational level
To evaluate the relationship between satisfaction with democracy and
gender, we can also use the test of independence of \(\chi^2\). The results of this test are
saved in an object “chitest2”.
chitest2 <- chisq.test(lapop18$satis, lapop18$educ)
chitest2
##
## Pearson's Chi-squared test
##
## data: lapop18$satis and lapop18$educ
## X-squared = 312.2, df = 9, p-value < 2.2e-16
Again, we obtain a p-value of less than 0.05, with which the null
hypothesis is rejected and it is affirmed that the observed frequencies
are different from those expected, with which we conclude that there
would be a dependency relationship between the variables.
To evaluate the strength of the relationship, we use the library
oii
and the command association.measures
, that
return a series of association measures that fit this types of
variables, that in this case are both ordinal
library(oii)
association.measures(lapop18$satis, lapop18$educ)
## Chi-square-based measures of association:
## Phi: 0.108
## Contingency coefficient: 0.108
## Cramer's V: 0.063
##
## Ordinal measures of association:
## Total number of pairs: 352092916
## Concordant pairs: 84356625 ( 23.96 %)
## Discordant pairs: 68163337 ( 19.36 %)
## Tied on first variable: 80445182 ( 22.85 %)
## Tied on second variable: 77098765 ( 21.9 %)
## Tied on both variables: 42029007 ( 11.94 %)
##
## Goodman-Kruskal Gamma: 0.106
## Somers' d (col dep.): 0.071
## Kendall's tau-b: 0.070
## Stuart's tau-c: 0.061
In this case, we observe the measures of association for ordinal
variables. This command reports 4 of these measurements, all of them
vary between -1 to +1. In our example, they all have a positive sign,
which indicates a direct relationship between both variables. This would
seem to go against what is reported in Figure 1.14 of the report where
it is clearly observed that satisfaction with democracy decreases at
higher educational levels, which would be expressed in a negative
sign.
This apparent contradiction is due on how satisfaction with democracy
(“satis” variable that is created from “pn4”) has been coded. The
original variable has values between 1 and 4, where 1 means “very
satisfied” and 4 means “very dissatisfied”. That is, high values
indicate “less”in the variable. It is for this reason that the
association test results with a positive sign, which in this case would
indicate that a higher value of the education variable means “more” of
the satisfaction with democracy variable (which is actually less).
To avoid this confusion, the monotony of the satisfaction with
democracy variable should have been changed so that higher values
indicate greater satisfaction and, with this, a negative sign is
obtained in the association measures. This has been done in this section
to draw attention to the fact that coding has consequences for the
results and can lead to confusion if care is not taken.
Finally, the value of the association measures are less than 0.3,
indicating that the relationship between the variables is weak.
Summary
In this section we have worked with bivariate relationships between
categorical variables. Cross-tables and bar graphs have been calculated
to show the descriptive results. Then, the chi-square test of
independence has been used to infer whether there is a dependency
relationship between the variables in the population and finally the
strength of the association between the variables is evaluated,
differentiating when it comes to nominal or ordinal variables.
Calculations including survey weights
We calculate the percentage of votes are counted fairly by country
including survey weights in the section about descriptives
of ordinal variables. With this data, we replicate Figure 2.5.
To calculate a chi-square test including survey weights, we can use
the library survey
and the command
svychisq
.
library(survey)
design18 = svydesign(ids = ~upm, strata = ~estratopri, weights = ~weight1500, nest=TRUE, data=lapop18)
We calculate the contingency table with the command
svytable
. In this case we cross satisfaction with democracy
by gender. This command is nested inside prop.table
to
display the relative frequencies and not the absolute ones. In turn, all
of this is nested inside the command addmargins
to present
the relative frequencies as percentages. In the same way as above, we
can save this table in an object for graphing these results.
addmargins(prop.table(svytable(~satis+gender, design=design18),2)*100,1)
## gender
## satis Male Female
## Very satisfied 6.777875 6.025175
## Satisfied 35.341585 30.695022
## Dissatisfied 44.119892 48.450745
## Very dissatisfied 13.760648 14.829058
## Sum 100.000000 100.000000
The Chi-square test of independence incorporating survey weights is
computed using the command svychisq
. The dependent
variable, the independent variable and the object are included with the
sample design.
chitest3 =svychisq(~satis+gender,design18)
chitest3
##
## Pearson's X^2: Rao & Scott adjustment
##
## data: svychisq(~satis + gender, design18)
## F = 28.172, ndf = 2.9969, ddf = 3985.8861, p-value < 2.2e-16
The results show a p-value less than 0.05, so the H0 of equal
expected and observed frequencies can be rejected, so we conclude that
there is a relationship of statistical dependence between both
variables.
Observed and expected values can be calculated. As can be seen, the
expected values differ from the results without survey weights.
chitest3$observed
## gender
## satis Male Female
## Very satisfied 960.0493 836.1461
## Satisfied 5005.9443 4259.7143
## Dissatisfied 6249.3440 6723.7720
## Very dissatisfied 1949.1214 2057.9086
chitest3$expected
## gender
## satis Male Female
## Very satisfied 907.2868 888.9086
## Satisfied 4680.2311 4585.4274
## Dissatisfied 6552.9267 6420.1893
## Very dissatisfied 2024.0144 1983.0156
In this case, there is no command to calculate the association
measures incorporating the design effect. Unweighted association
measures can be taken as reference values.
LS0tCnRpdGxlOiAiQ3Jvc3MtdGFibGVzIHdpdGggdGhlIEFtZXJpY2FzQmFyb21ldGVyIgpvdXRwdXQ6CiAgaHRtbF9kb2N1bWVudDoKICAgIHRvYzogdHJ1ZQogICAgdG9jX2Zsb2F0OiB0cnVlCiAgICBjb2xsYXBzZWQ6IGZhbHNlCiAgICBudW1iZXJfc2VjdGlvbnM6IGZhbHNlCiAgICB0b2NfZGVwdGg6IDEKICAgIGNvZGVfZG93bmxvYWQ6IHRydWUKICAgIHRoZW1lOiBmbGF0bHkKICAgIGRmX3ByaW50OiBwYWdlZAogICAgc2VsZl9jb250YWluZWQ6IG5vCiAgICBrZWVwX21kOiB5ZXMKZWRpdG9yX29wdGlvbnM6IAogIG1hcmtkb3duOiAKICAgIHdyYXA6IHNlbnRlbmNlCi0tLQoKYGBge3Igc2V0dXAsIGluY2x1ZGU9RkFMU0V9CmtuaXRyOjpvcHRzX2NodW5rJHNldChtZXNzYWdlPUZBTFNFLHdhcm5pbmc9RkFMU0UsIGNhY2hlPVRSVUUpCmBgYAoKYGBge2NzcyBjb2xvciwgZWNobz1GQUxTRX0KLmNvbHVtbnMge2Rpc3BsYXk6IGZsZXg7fQpoMSB7Y29sb3I6ICMzMzY2Q0M7fQpgYGAKCiMgSW50cm9kdWN0aW9uCgpUaGUgcHJldmlvdXMgc2VjdGlvbnMgY29ycmVzcG9uZGluZyB0byB0aGUgW3QtdGVzdF0oaHR0cHM6Ly9hcnR1cm9tYWxkb25hZG8uZ2l0aHViLmlvL0Jhcm9tZXRyb0VkdV9XZWJfRW5nL3R0ZXN0Lmh0bWwpIGFuZCB0aGUgW0FOT1ZBIHRlc3RdKGh0dHBzOi8vYXJ0dXJvbWFsZG9uYWRvLmdpdGh1Yi5pby9CYXJvbWV0cm9FZHVfV2ViX0VuZy9hbm92YS5odG1sKSBhcmUgYWJvdXQgdGhlIHJlbGF0aW9uc2hpcCBvZiBhIG51bWVyaWNhbCB2YXJpYWJsZSB3aXRoIGEgY2F0ZWdvcmljYWwgdmFyaWFibGUsIGluIHN1Y2ggYSB3YXkgdGhhdCB0aGUgZ29hbCBpcyB0byBjb21wYXJlIGFuZCBleHRyYXBvbGF0ZSB0aGUgbWVhbnMgb2YgYSBudW1lcmljYWwgdmFyaWFibGUgYnkgZ3JvdXBzIG9mIGEgY2F0ZWdvcmljYWwgdmFyaWFibGUuCgpJbiB0aGlzIHNlY3Rpb24gd2Ugd2lsbCBsb29rIGF0IGJpdmFyaWF0ZSByZWxhdGlvbnNoaXBzIGJldHdlZW4gdHdvIGNhdGVnb3JpY2FsIChvciBmYWN0b3IgaW4gUiB0ZXJtaW5vbG9neSkgdmFyaWFibGVzLgpUaGlzIGV2YWx1YXRpb24gaXMgZG9uZSB1c2luZyBjcm9zcy10YWJsZXMgKG9yIGNvbnRpbmdlbmN5IHRhYmxlcykgYW5kIGlzIGV2YWx1YXRlZCB1c2luZyB0aGUgY2hpLXNxdWFyZSB0ZXN0LgoKIyBBYm91dCB0aGUgZGF0YXNldAoKVGhlIGRhdGEgd2UgYXJlIGdvaW5nIHRvIHVzZSBzaG91bGQgYmUgY2l0ZWQgYXMgZm9sbG93czogU291cmNlOiBBbWVyaWNhc0Jhcm9tZXRlciBieSB0aGUgTGF0aW4gQW1lcmljYW4gUHVibGljIE9waW5pb24gUHJvamVjdCAoTEFQT1ApLCB3d3d3LkxhcG9wU3VydmV5cy5vcmcuCldlIGNhbiBkb3dubG9hZCB0aGUgZGF0YSBmcmVlbHkgW2hlcmVdKGh0dHA6Ly9kYXRhc2V0cy5hbWVyaWNhc2Jhcm9tZXRlci5vcmcvZGF0YWJhc2UvbG9naW4ucGhwKS4KClRoaXMgc2VjdGlvbiBsb2FkcyBhIHRyaW1tZWQgZGF0YWJhc2UsIG9yaWdpbmFsbHkgaW4gU1BTUyAoLnNhdikgZm9ybWF0LgpJdCBpcyByZWNvbW1lbmRlZCB0byBjbGVhbiB0aGUgRW52aXJvbm1lbnQgYmVmb3JlIHN0YXJ0aW5nIHRoaXMgc2VjdGlvbi4KClRoaXMgZGF0YXNldCBpcyBob3N0ZWQgaW4gdGhlICJtYXRlcmlhbHNfZWR1IiByZXBvc2l0b3J5IG9mIHRoZSBMQVBPUCBhY2NvdW50IG9uIEdpdEh1Yi4KVXNpbmcgdGhlIGxpYnJhcnkgYHJpb2AgYW5kIHRoZSBjb21tYW5kIGBpbXBvcnRgLCB3ZSBjYW4gaW1wb3J0IHRoaXMgZGF0YWJhc2UgZnJvbSB0aGlzIHJlcG9zaXRvcnkuCkluIGFkZGl0aW9uLCB0aGUgZGF0YSBmcm9tIGNvdW50cmllcyB3aXRoIGNvZGVzIGxlc3MgdGhhbiBvciBlcXVhbCB0byAzNSBhcmUgc2VsZWN0ZWQsIHRoYXQgaXMsIHRoZSBvYnNlcnZhdGlvbnMgb2YgdGhlIFVuaXRlZCBTdGF0ZXMgYW5kIENhbmFkYSBhcmUgZWxpbWluYXRlZC4KCmBgYHtyIGJhc2V9CmxpYnJhcnkocmlvKSAKbGFwb3AxOCA9IGltcG9ydCgiaHR0cHM6Ly9yYXcuZ2l0aHViLmNvbS9sYXBvcC1jZW50cmFsL21hdGVyaWFsc19lZHUvbWFpbi9MQVBPUF9BQl9NZXJnZV8yMDE4X3YxLjAuc2F2IikKbGFwb3AxOCA9IHN1YnNldChsYXBvcDE4LCBwYWlzPD0zNSkKYGBgCgpXZSBhbHNvIGxvYWQgdGhlIGRhdGFzZXQgZm9yIHRoZSAyMDIxIHJvdW5kLgoKYGBge3J9CmxhcG9wMjEgPSBpbXBvcnQoImh0dHBzOi8vcmF3LmdpdGh1Yi5jb20vbGFwb3AtY2VudHJhbC9tYXRlcmlhbHNfZWR1L21haW4vbGFwb3AyMS5SRGF0YSIpCmxhcG9wMjEgPSBzdWJzZXQobGFwb3AyMSwgcGFpczw9MzUpCmBgYAoKIyBWb3RlcyBhcmUgY291bnRlZCBmYWlybHkKClRoZSByZXBvcnQgVGhlIFB1bHNlIG9mIERlbW9jcmFjeSBmb3IgdGhlIDIwMjEgcm91bmQgb2YgdGhlIEFtZXJpY2FzQmFyb21ldGVyIHJlcG9ydHMgdGhlIHJlc3VsdHMgb2YgdmFyaWFibGUgKipDT1VOVEZBSVIxLioqIFZvdGVzIGFyZSBjb3VudGVkIGNvcnJlY3RseSBhbmQgZmFpcmx5LgpXb3VsZCB5b3Ugc2F5IGl0IGhhcHBlbnMgYWx3YXlzLCBzb21ldGltZXMgb3IgbmV2ZXI/ClBlcmNlbnRhZ2VzIGFyZSBwcmVzZW50ZWQgYnkgY291bnRyaWVzLgoKVGhpcyBmaWd1cmUgaXMgcmVwb3J0aW5nIHRoZSBjcm9zcyBvZiBhIGNhdGVnb3JpY2FsIHZhcmlhYmxlIChvciBmYWN0b3IgaW4gUiBsYW5ndWFnZSksIGNhbGxlZCAiY291bnRmYWlyMSIgdGhhdCBoYXMgdGhyZWUgY2F0ZWdvcmllcyAobmV2ZXIsIHNvbWV0aW1lcyBhbmQgYWx3YXlzKSwgd2l0aCBvdGhlciBjYXRlZ29yaWNhbCB2YXJpYWJsZXMgY2FsbGVkICJwYWlzIiB0aGF0IGhhcyAxNSBjYXRlZ29yaWVzIChlYWNoIGNvdW50cnkgcHJlc2VudGVkKS4KCiFbXShGaWd1cmUyLjUucG5nKXt3aWR0aD0iNTk2In0KClRoaXMgdmFyaWFibGUgaXMgaW1wb3J0ZWQgaW4gUiBhcyBudW1lcmljLgpGb3IgYmUgYWJsZSB0byB3b3JrIHdpdGggdGhpcyB2YXJpYWJsZSwgd2UgaGF2ZSB0byBkZWNsYXJlIGl0IGFzIGEgZmFjdG9yIHZhcmlhYmxlLCB1c2luZyB0aGUgY29tbWFuZCBgYXMuZmFjdG9yYC4KV2UgdGhlbiBsYWJlbCB0aGlzIHZhcmlhYmxlIHdpdGggdGhlIGNvbW1hbmQgYGxldmVsc2AuCgpgYGB7cn0KbGlicmFyeShoYXZlbikKbGFwb3AyMSRjb3VudGZhaXIxciA9IGFzLmZhY3RvcihsYXBvcDIxJGNvdW50ZmFpcjEpCmxldmVscyhsYXBvcDIxJGNvdW50ZmFpcjFyKSA9IGMoIkFsd2F5cyIsICJTb21ldGltZXMiLCAiTmV2ZXIiKQp0YWJsZShsYXBvcDIxJGNvdW50ZmFpcjFyKQpgYGAKCiMgQ3Jvc3MtdGFibGUgb2Ygdm90ZXMgYXJlIGNvdW50ZWQgZmFpcmx5IGJ5IGNvdW50cnkKCkJlZm9yZSByZXBsaWNhdGluZyB0aGlzIGZpZ3VyZSwgaXQgaXMgdXNlZnVsIHRvIHNlZSByZXN1bHRzIGluIGEgY3Jvc3MtdGFibGUuCldlIGNhbiBjcmVhdGUgdGhpcyB0YWJsZSB3aXRoIHRoZSBjb21tYW5kIGB0YWJsZWAuCkhvd2V2ZXIsIHRoaXMgdGFibGUgcHJlc2VudHMgYWJzb2x1dGUgZnJlcXVlbmNpZXMuCkFsc28sIHRoaXMgdGFibGUgc2hvd3MgdGhhdCB0aGlzIHF1ZXN0aW9uIHdhcyBub3QgZmllbGRlZCBpbiBzb21lIGNvdW50cmllcy4KCmBgYHtyfQp0YWJsZShsYXBvcDIxJHBhaXMsIGxhcG9wMjEkY291bnRmYWlyMXIpCmBgYAoKVG8gcmVwcm9kdWNlIHRoZSByZWxhdGl2ZSBmcmVxdWVuY2llcywgd2UgaGF2ZSB0byB1c2UgdGhlIGNvbW1hbmQgYHByb3AudGFibGVgLgpUaGlzIGNvbW1hbmQgcmV0dXJucyB0aGUgcGVyY2VudGFnZXMgZm9yIHRoZSB0b3RhbCBieSBkZWZlY3QuCldlIHdhbnQgdG8gY2FsY3VsYXRlIHBlcmNlbnRhZ2VzIGJ5IHJvd3MgKHRoYXQgaXMsIGJ5IGNvdW50cnkpIGluIHRoaXMgY2FzZS4KCmBgYHtyfQpwcm9wLnRhYmxlKHRhYmxlKGxhcG9wMjEkcGFpcywgbGFwb3AyMSRjb3VudGZhaXIxcikpCmBgYAoKVG8gY2FsY3VsYXRlIHRoZSBwZXJjZW50YWdlcyBieSByb3dzLCB3ZSBoYXZlIHRvIGFkZCB0aGUgc3BlY2lmaWNhdGlvbiBgLCAxYCBpbiBgcHJvcC50YWJsZWAuCldlIGNhbiBhbHNvIG5lc3QgdGhpcyBjb2RlIGluIHRoZSBjb21tYW5kIGBhZGRtYXJnaW5zYCB0byBjYWxjdWxhdGUgdGhlIHN1bSBvZiBob3Jpem9udGFsIHBlcmNlbnRhZ2VzLgpUaGVzZSBhcmUgdGhlIHNhbWUgcGVyY2VudGFnZXMgdGhhdCBhcmUgcHJlc2VudGVkIGluIGEgYmFyIHBsb3QgYmVsb3cuClRoZXNlIHBlcmNlbnRhZ2VzIGFyZSBub3QgZXF1YWwgdG8gdGhvc2UgcHJlc2VudGVkIGluIEZpZ3VyZSAyLjUgYmVjYXVzZSB0aGlzIGNhbGN1bGF0aW9uIGRvZXMgbm90IGluY2x1ZGUgc3VydmV5IHdlaWdodHMuCgpgYGB7cn0KYWRkbWFyZ2lucyhwcm9wLnRhYmxlKHRhYmxlKGxhcG9wMjEkcGFpcywgbGFwb3AyMSRjb3VudGZhaXIxciksIDEpKjEwMCwgMikKYGBgCgojIEJhciBncmFwaCBvZiB2b3RlcyBhcmUgY291bnRlZCBmYWlybHkgYnkgY291bnRyeQoKSW4gdGhlIHNhbWUgd2F5IGFzIHdlIGRpZCBpbiB0aGUgc2VjdGlvbiBhYm91dCBvcmRpbmFsIHZhcmlhYmxlcywgYXZhaWxhYmxlIFtoZXJlXShodHRwczovL2FydHVyb21hbGRvbmFkby5naXRodWIuaW8vQmFyb21ldHJvRWR1X1dlYl9FbmcvRGVzY3JpcHRpdmVzMi5odG1sKSwgd2UgY2FuIHJlcGxpY2F0ZSB0aGUgY29tcGFyYXRpdmUgZ3JhcGggYnkgY291bnRyeSB3ZSBoYXZlIHRvIGNyZWF0ZSBhIGNvbnRpbmdlbmN5IHRhYmxlIGJldHdlZW4gdmFyaWFibGVzICJjb3VudGZhaXIxIiBhbmQgInBhaXMiLgpUaGlzIGNyb3NzLXRhYmxlIGlzIHNhdmVkIGluIGFuIGFiamVjdCAiY291bnRfcGFpcyIuCldlIHNob3VsZCBub3RlIHRoYXQgdGhlIGRhdGFmcmFtZSBpbmNsdWRlIGEgcm93IGZvciBlYWNoIHZhbHVlIG9mICJjb3VudGZhaXIxIiBpbiBlYWNoIGNvdW50cnkuCkluIHRoaXMgd2F5LCB3ZSBoYXZlIDMgb3B0aW9ucyB4IDIwIGNvdW50cmllcyA9IDYwIHJvd3MuCgpgYGB7cn0KY291bnRfcGFpcyA9IGFzLmRhdGEuZnJhbWUocm91bmQocHJvcC50YWJsZSh0YWJsZShsYXBvcDIxJHBhaXMsIGxhcG9wMjEkY291bnRmYWlyMXIpLCAxKSwgMykqMTAwKQpjb3VudF9wYWlzCmBgYAoKVGhpcyB0YWJsZSBwcmVzZW50cyBOQXMgZm9yIGNvdW50cmllcyB3aGVyZSB0aGUgcXVlc3Rpb24gImNvdW50ZmFpcjEiIHdhcyBub3QgYXNrZWQuCkZvciB0aGlzIHJlYXNvbiwgd2UgaGF2ZSB0byBkcm9wIHJvd3Mgd2hlcmUgdGhlcmUgaXMgbm8gZGF0YS4KV2UgY2FuIGRvIHRoaXMgd2l0aCB0aGUgc3BlY2lmaWNhdGlvbiBgWy1jKHJvd3MpXWAuCkFmdGVyIHRoYXQgd2UgY3JlYXRlIGEgdmVjdG9yIHdpdGggdGhlIG5hbWVzIG9mIGNvdW50cmllcy4KV2UgcmVwZWF0IG5hbWVzIHRocmVlIHRpbWVzICgxNSBjb3VudHJpZXMgeCAzIG9wdGlvbnMpLgpXZSBkZCB0aGlzIHZlY3RvciB0byB0aGUgZGF0YWZyYW1lIGluIGNvbHVtbiAiY291bnRyeSIuCgpgYGB7cn0KY291bnRfcGFpcyA9IGNvdW50X3BhaXNbLWMoMTo0LDE4LDIxOjI0LDM4LDQxOjQ0LDU4KSxdCmNvdW50cnkgPSBjKCJOaWNhcmFndWEiLCJDb3N0YSBSaWNhIiwgIlBhbmFtYSIsICJDb2xvbWJpYSIsICJFY3VhZG9yIiwgIkJvbGl2aWEiLCAiUGVydSIsCiAgICAgICAgIlBhcmFndWF5IiwgIkNoaWxlIiwgIlVydWd1YXkiLCAiQnJhemlsIiwgIkFyZ2VudGluYSIsICJEb20uIFJlcC4iLCJKYW1haWNhIiwgIkd1eWFuYSIsICJOaWNhcmFndWEiLCJDb3N0YSBSaWNhIiwgIlBhbmFtYSIsICJDb2xvbWJpYSIsICJFY3VhZG9yIiwgIkJvbGl2aWEiLCAiUGVydSIsCiAgICAgICAgIlBhcmFndWF5IiwgIkNoaWxlIiwgIlVydWd1YXkiLCAiQnJhemlsIiwgIkFyZ2VudGluYSIsICJEb20uIFJlcC4iLCJKYW1haWNhIiwgIkd1eWFuYSIsIk5pY2FyYWd1YSIsIkNvc3RhIFJpY2EiLCAiUGFuYW1hIiwgIkNvbG9tYmlhIiwgIkVjdWFkb3IiLCAiQm9saXZpYSIsICJQZXJ1IiwKICAgICAgICAiUGFyYWd1YXkiLCAiQ2hpbGUiLCAiVXJ1Z3VheSIsICJCcmF6aWwiLCAiQXJnZW50aW5hIiwgIkRvbS4gUmVwLiIsIkphbWFpY2EiLCAiR3V5YW5hIikKY291bnRfcGFpcyRjb3VudHJ5ID0gY291bnRyeQpjb3VudF9wYWlzCmBgYAoKV2UgaGF2ZSB0aGUgZWxlbWVudHMgaW4gdGhpcyBkYXRhZnJhbWUgImNvdW50X3BhaXMiIHRvIHJlcGxpY2F0ZSB0aGUgc3RhY2tlZCBiYXIgcGxvdC4KV2Ugc3BlY2lmeSBpbiBgYWVzYCB0aGF0IHBlcmNlbnRhZ2VzIGFyZSBpbiBYIGF4aXMsIGNvdW50cmllcyBpbiBZIGF4aXMgYW5kIGVhY2ggYmFyIGlzIGRpdmlkZWQgYnkgY29sdW1uIFZhcjIuCgpgYGB7cn0KbGlicmFyeShnZ3Bsb3QyKQpnZ3Bsb3QoZGF0YT1jb3VudF9wYWlzLCBhZXMoeD1GcmVxLCB5PWNvdW50cnksIGZpbGw9VmFyMikpKwogIGdlb21fYmFyKHN0YXQ9ImlkZW50aXR5Iiwgd2lkdGg9MC4zKSsKICBnZW9tX3RleHQoYWVzKGxhYmVsPXBhc3RlKEZyZXEsICIlIiwgc2VwPSIiKSksIGNvbG9yPSJ3aGl0ZSIsIAogICAgICAgICAgICBwb3NpdGlvbj1wb3NpdGlvbl9zdGFjayh2anVzdD0wLjUpLCBzaXplPTIpKwogIGxhYnMoeD0iUGVyY2VudGFnZSIsIHk9IkNvdW50cnkiLCBmaWxsPSJWb3RlcyBhcmUgY291bnRlZCBmYWlybHkiLAogICAgICAgY2FwdGlvbj0iQW1lcmljYXNCYXJvbWV0ZXIgYnkgTEFQT1AsIDIwMjEiKQpgYGAKCiMgRXZhbHVhdGluZyBEZW1vY3JhY3kgaW4gUHJhY3RpY2UKCkZyb20gcGFnZSAyMCwgdGhlIHJlcG9ydCAqVGhlIFB1bHNlIG9mIERlbW9jcmFjeSogZXZhbHVhdGVzIGRlbW9jcmFjeSBpbiBwcmFjdGljZS4KSW4gcGFydGljdWxhciwgdGhpcyBzZWN0aW9uIG9mIHRoZSByZXBvcnQgdXNlcyB0aGUgdmFyaWFibGUgInBuNCIuClRoaXMgdmFyaWFibGUgaXMgd29yZGVkIGFzIGZvbGxvd3M6ICJJbiBnZW5lcmFsLCB3b3VsZCB5b3Ugc2F5IHRoYXQgeW91IGFyZSB2ZXJ5IHNhdGlzZmllZCwgc2F0aXNmaWVkLCBkaXNzYXRpc2ZpZWQsIG9yIHZlcnkgZGlzc2F0aXNmaWVkIHdpdGggdGhlIHdheSBkZW1vY3JhY3kgd29ya3MgaW4gKGNvdW50cnkpPyIKClRoZSByZXBvcnQgaW5kaWNhdGVzIHRoYXQgdGhpcyB2YXJpYWJsZSBpcyByZWNvZGVkIGFzIGEgZGljaG90b21vdXMgdmFyaWFibGUgdG8gYmUgYWJsZSB0byB3b3JrIHdpdGggcGVyY2VudGFnZXMuCkluIHRoaXMgc2VjdGlvbiB3ZSBhcmUgZ29pbmcgdG8gd29yayB3aXRoIHRoZSBvcmlnaW5hbCB2YXJpYWJsZSwgd2hpY2ggaXMgYW4gb3JkaW5hbCBjYXRlZ29yaWNhbCB2YXJpYWJsZSAob3IgZmFjdG9yKS4KCkZpZ3VyZSAxLjE0IG9mIHRoZSByZXBvcnQgcHJlc2VudHMgYW4gZXZhbHVhdGlvbiBvZiBzYXRpc2ZhY3Rpb24gd2l0aCBkZW1vY3JhY3kgYnkgZGVtb2dyYXBoaWMgYW5kIHNvY2lvZWNvbm9taWMgdmFyaWFibGVzLCBzdWNoIGFzIGVkdWNhdGlvbmFsIGxldmVsLCBxdWludGlsZXMgb2Ygd2VhbHRoLCBwbGFjZSBvZiByZXNpZGVuY2UsIGdlbmRlciBvciBhZ2UgZ3JvdXBzLgpUaGF0IGlzLCBzYXRpc2ZhY3Rpb24gd2l0aCBkZW1vY3JhY3kgaXMgdXNlZCBhcyB0aGUgZGVwZW5kZW50IHZhcmlhYmxlIGFuZCBlYWNoIGRlbW9ncmFwaGljIG9yIHNvY2lvZWNvbm9taWMgdmFyaWFibGUgYXMgdGhlIGluZGVwZW5kZW50IHZhcmlhYmxlLgoKIVtdKEZpZ3VyZTEuMTQuSlBHKXt3aWR0aD0iNDE5In0KCkZvciBleGFtcGxlLCB0aGUgcmVwb3J0IGluZGljYXRlcyB0aGF0IGFtb25nIG1lbiwgNDIuMyUgYXJlIHNhdGlzZmllZCB3aXRoIGRlbW9jcmFjeSAodXNpbmcgdGhlIHZhcmlhYmxlIHJlY29kZWQgYXMgYSBkdW1teSksIHdoaWxlIGFtb25nIHdvbWVuLCB0aGlzIHBlcmNlbnRhZ2UgZHJvcHMgdG8gMzYuOSUuCkhlcmUgd2UgYXJlIGdvaW5nIHRvIGFuYWx5emUgdGhlc2Ugc2FtZSB2YXJpYWJsZXMsIGJ1dCB1c2luZyB0aGUgdmFyaWFibGUgInBuNCIgaW4gaXRzIG9yaWdpbmFsIGZvcm0gKGFzIGFuIG9yZGluYWwgY2F0ZWdvcmljYWwpLgpCZWZvcmUgcHJvY2VlZGluZywgd2UgbmVlZCB0byByZWNvZGUgdGhlIHZhcmlhYmxlcyBhcyBmYWN0b3IgYW5kIGxhYmVsIHRoZW0uCgpgYGB7ciBnZW5kZXJ9CmxhcG9wMTgkZ2VuZGVyID0gYXMuZmFjdG9yKGxhcG9wMTgkcTEpCmxldmVscyhsYXBvcDE4JGdlbmRlcikgPSBjKCJNYWxlIiwgIkZlbWFsZSIpCnRhYmxlKGxhcG9wMTgkZ2VuZGVyKQpgYGAKClRoZSBzYW1lIGlzIGRvbmUgZm9yIHRoZSB2YXJpYWJsZSAicG40IiB3aGljaCBiZWNvbWVzIGEgbmV3IHZhcmlhYmxlICJzYXRpcyIuCgpgYGB7ciBzYXRpc30KbGFwb3AxOCRzYXRpcyA9IGFzLmZhY3RvcihsYXBvcDE4JHBuNCkKbGV2ZWxzKGxhcG9wMTgkc2F0aXMpID0gYygiVmVyeSBzYXRpc2ZpZWQiLCAiU2F0aXNmaWVkIiwgIkRpc3NhdGlzZmllZCIsICJWZXJ5IGRpc3NhdGlzZmllZCIpCnRhYmxlKGxhcG9wMTgkc2F0aXMpCmBgYAoKIyBDcm9zcy10YWJsZSBvZiBzYXRpc2ZhY3Rpb24gd2l0aCBkZW1vY3JhY3kgYnkgZ2VuZGVyCgpXaXRoIHRoZSBuZXcgZmFjdG9yIHZhcmlhYmxlcywgd2UgZmlyc3QgY2FsY3VsYXRlIGEgY3Jvc3MtdGFibGUgb3IgY29udGluZ2VuY3kgdGFibGUuClRoZSBjb21tYW5kIGB0YWJsZWAgaXMgdXNlZCB0byBwcmVzZW50IHRoZSBmcmVxdWVuY2llcyBvZiBvbmUgb3IgdHdvIHZhcmlhYmxlcy4KQnkgY29udmVudGlvbiwgdGhlIGRlcGVuZGVudCB2YXJpYWJsZSAic2F0aXNmYWN0aW9uIHdpdGggZGVtb2NyYWN5IiBpcyBwbGFjZWQgaW4gdGhlIHJvd3MgYW5kIHRoZSBpbmRlcGVuZGVudCB2YXJpYWJsZSAiZ2VuZGVyIiBpbiB0aGUgY29sdW1ucy4KCmBgYHtyIHRhYmxlfQp0YWJsZShsYXBvcDE4JHNhdGlzLCBsYXBvcDE4JGdlbmRlcikKYGBgCgpUbyBjYWxjdWxhdGUgdGhlIHJlbGF0aXZlIGZyZXF1ZW5jaWVzLCB5b3UgaGF2ZSB0byBuZXN0IHRoZSBjb21tYW5kIGB0YWJsZWAgaW5zaWRlIHRoZSBjb21tYW5kIGBwcm9wLnRhYmxlYC4KSWYgbmVzdGVkIG9ubHksIHRoaXMgY29tbWFuZCBjYWxjdWxhdGVzIHRoZSBwcm9wb3J0aW9ucyBvdmVyIHRoZSB0b3RhbCBvYnNlcnZhdGlvbnMuCgpgYGB7ciB0YWJsZTJ9CnByb3AudGFibGUodGFibGUobGFwb3AxOCRzYXRpcywgbGFwb3AxOCRnZW5kZXIpKQpgYGAKClRoZXNlIHByb3BvcnRpb25zIGFyZSBub3QgdmVyeSB1c2VmdWwgZm9yIHRoZSBjb21wYXJpc29uIHdlIHdhbnQgdG8gbWFrZS4KV2hhdCB3ZSByZXF1aXJlIGFyZSB0aGUgY29uZGl0aW9uYWwgZGlzdHJpYnV0aW9ucyBvZiAic2F0aXNmYWN0aW9uIHdpdGggZGVtb2NyYWN5IiBmb3IgZWFjaCBnZW5kZXIgZ3JvdXAuClRoYXQgaXMsIGNhbGN1bGF0ZSB0aGUgcGVyY2VudGFnZXMgZm9yIGVhY2ggY29sdW1uLgpJbiBvcmRlciBmb3IgYHByb3AudGFibGVgIHRvIGNhbGN1bGF0ZSB0aGVzZSBwZXJjZW50YWdlcywgd2UgaGF2ZSB0byBhZGQgdGhlIHNwZWNpZmljYXRpb24gYCjigKYsIDIpYC4KTXVsdGlwbHkgYnkgMTAwIHRvIGdvIGZyb20gcmF0aW9zIHRvIHBlcmNlbnRhZ2VzLgpZb3UgY2FuIGFsc28gbmVzdCBhbGwgY29kZSBpbnNpZGUgdGhlIGNvbW1hbmQgYGFkZG1hcmdpbnNgIHRvIGNoZWNrIHRoZSBzdW0gb2YgcGVyY2VudGFnZXMgb3ZlciB0aGUgY29sdW1ucywgd2l0aCB0aGUgc3BlY2lmaWNhdGlvbiBgKC4uLiwgMSlgLgoKYGBge3IgdGFibGVzM30KYWRkbWFyZ2lucyhwcm9wLnRhYmxlKHRhYmxlKGxhcG9wMTgkc2F0aXMsIGxhcG9wMTgkZ2VuZGVyKSwgMikqMTAwLCAxKQpgYGAKClRoZSB0YWJsZSBzaG93cyB0aGF0IDYuOCUgb2YgbWVuIGFyZSB2ZXJ5IHNhdGlzZmllZCB3aXRoIGRlbW9jcmFjeSwgYSBwZXJjZW50YWdlIHZlcnkgc2ltaWxhciB0byB0aGF0IG9mIHdvbWVuLgo0NCUgb2YgbWVuIGFyZSBkaXNzYXRpc2ZpZWQgd2l0aCBkZW1vY3JhY3kuCkluIHRoaXMgY2F0ZWdvcnksIHdvbWVuIGhhdmUgYSBoaWdoZXIgcGVyY2VudGFnZSAoNDguNCUpLgoKSW4gdGhpcyB3YXksIGl0IGlzIHBvc3NpYmxlIHRvIGNvbXBhcmUgdGhlIHBlcmNlbnRhZ2VzIG9mIHRoZSBkZXBlbmRlbnQgdmFyaWFibGUgInNhdGlzZmFjdGlvbiB3aXRoIGRlbW9jcmFjeSIgZm9yIGVhY2ggY2F0ZWdvcnkgb2YgdGhlIGluZGVwZW5kZW50IHZhcmlhYmxlICJnZW5kZXIiLgoKIyBHcmFwaHMgb2Ygc2F0aXNmYWN0aW9uIHdpdGggZGVtb2NyYWN5IGJ5IGdlbmRlcgoKSW4gdGhlIHNlY3Rpb24gYWJvdXQgW2Rlc2NyaXB0aXZlcyBvZiBvcmRpbmFsIHZhcmlhYmxlc10oaHR0cHM6Ly9hcnR1cm9tYWxkb25hZG8uZ2l0aHViLmlvL0Jhcm9tZXRyb0VkdV9XZWJfRW5nL0Rlc2NyaXB0aXZlczIuaHRtbCksIHdlIHByZXNlbnRlZCBhIHByZXZpZXcgb2Ygd2hhdCB3ZSBhcmUgc2VlaW5nIGluIHRoaXMgc2VjdGlvbi4KSGVyZSB3ZSB3aWxsIHJldmlzaXQgdGhvc2UgdGhlbWVzLCB1c2luZyB0aGUgdGlkeXZlcnNlLgoKVG8gbWFrZSB0aGUgZ3JhcGgsIHdlIGZpcnN0IGNyZWF0ZSBhIG5ldyBkYXRhZnJhbWUgd2l0aCB0aGUgZGF0YSBmcm9tIHRoZSBjcm9zcy10YWJsZS4KVGhlIGNvbW1hbmQgYGFzLmRhdGEuZnJhbWVgIGlzIHVzZWQgdG8gdHJhbnNmb3JtIHRoZSBiaXZhcmlhdGUgdGFibGUgaW50byBhIG5ldyBkYXRhZnJhbWUgY2FsbGVkICJ0YWJsZSIuClVzaW5nIHRoaXMgY29tbWFuZCwgdGhlIHJlc3VsdHMgYXJlIHNvcnRlZCBieSBuZXcgY29sdW1ucyAoVmFyMSwgVmFyMiBhbmQgRnJlcSkgc28gdGhhdCB0aGV5IGNhbiBiZSB1c2VkIHRvIGNyZWF0ZSBhIGdyYXBoLgoKYGBge3IgdGFibGU0fQp0YWJsZSA9IGFzLmRhdGEuZnJhbWUocHJvcC50YWJsZSh0YWJsZShsYXBvcDE4JHNhdGlzLCBsYXBvcDE4JGdlbmRlciksIDIpKjEwMCkKdGFibGUKYGBgCgpXZSB3aWxsIHVzZSB0aGUgbGlicmFyeSBgZ2dwbG90MmAgYW5kIHRoZSBjb21tYW5kIGBnZ3Bsb3RgIHRvIGNyZWF0ZSBhIGJhciBjaGFydCwgdXNpbmcgdGhlIGRhdGFmcmFtZSAidGFibGUiIGNvbnRhaW5pbmcgdGhlIHBlcmNlbnRhZ2VzIG9mIHNhdGlzZmFjdGlvbiB3aXRoIGRlbW9jcmFjeSBmb3IgbWVuIGFuZCB3b21lbi4KVGhpcyBjb21tYW5kIHJlcXVpcmVzIGFuIGFlc3RoZXRpYyB3aGVyZSBpdCBpcyBzcGVjaWZpZWQgdGhhdCAiVmFyMSIgd2lsbCBiZSBpbmNsdWRlZCBvbiB0aGUgWCBheGlzLCB3aGljaCBjb3JyZXNwb25kcyB0byB0aGUgY2F0ZWdvcmllcyBvZiBzYXRpc2ZhY3Rpb24gd2l0aCBkZW1vY3JhY3kuClRoZSAiRnJlcSIgaXMgaW5jbHVkZWQgb24gdGhlIFkgYXhpcywgd2hpY2ggY29ycmVzcG9uZHMgdG8gcGVyY2VudGFnZXMuCkFsc28gaW5jbHVkZWQgaXMgdGhlIHNwZWNpZmljYXRpb24gYGZpbGxgIHRvIGluZGljYXRlIHRoYXQgaXQgd2lsbCBiZSBzcGxpdCBpbnRvIE1hbGUvRmVtYWxlIGdyb3VwcyBmb3IgZWFjaCBjYXRlZ29yeSBvZiAiVmFyMSIgYW5kIGB5bWF4YCB0byBzcGVjaWZ5IHRoZSB1cHBlciBsaW1pdCBvZiB0aGUgWSBheGlzLgoKQWZ0ZXIgZGVmaW5pbmcgdGhlIHZhcmlhYmxlcyBpbiB0aGUgYXhlcywgaXQgaXMgaW5kaWNhdGVkIHRoYXQgYSBiYXIgZ3JhcGggaXMgd2FudGVkIHdpdGggdGhlIGNvbW1hbmQgYGdlb21fYmFyYCBhbmQgd2l0aCB0aGUgc3BlY2lmaWNhdGlvbiBgcG9zaXRpb249ImRvZGdlImAgaXQgaXMgaW5kaWNhdGVkIHRoYXQgYSBncmFwaCB3aXRoIGJhcnMgc2VwYXJhdGVkIGJ5IGVhY2ggY29tYmluYXRpb24gb2YgY2F0ZWdvcmllcyBpcyB3YW50ZWQuClRoZSBzcGVjaWZpY2F0aW9uIGBzdGF0PSJpZGVudGl0eSJgIGlzIGFkZGVkIHRvIGluZGljYXRlIHRoYXQgdGhlIGNvbW1hbmQgd29ya3Mgd2l0aCB0aGUgZGF0YSBpbiB0aGUgdGFibGUuCgpUaGUgY29tbWFuZCBgZ2VvbV90ZXh0YCBpbmNsdWRlcyB0aGUgcGVyY2VudGFnZXMgb2YgZWFjaCBiYXIsIHdoaWNoIGlzIGZvdW5kIGluIHRoZSAiRnJlcSIgY29sdW1uLgpUaGVzZSBwZXJjZW50YWdlcyBhcmUgcm91bmRlZCB3aXRoIGByb3VuZGAgdG8gMSBkZWNpbWFsIHBsYWNlIGFuZCB0aGUgIiUiIHN5bWJvbCBpcyBhZGRlZCB3aXRoIGBwYXN0ZWAuCkFsc28gaW5jbHVkZWQgaXMgdGhlIHNwZWNpZmljYXRpb24gYHBvc2l0aW9uPXBvc2l0aW9uX2RvZGdlKC4uLilgIHdoaWNoIHBsYWNlcyB0aGVzZSBwZXJjZW50YWdlcyBhdCB0aGUgdG9wIG9mIGVhY2ggY29sdW1uLgpUaGUgZGVmYXVsdCBvcHRpb24gd2l0aGluIHRoaXMgc3BlY2lmaWNhdGlvbiBpcyBgd2lkdGg9TlVMTGAsIGJ1dCB0aGlzIHdheSB0aGUgcGVyY2VudGFnZXMgd291bGQgYmUgbWlzcGxhY2VkLCBzbyBgd2lkdGg9MC45YCBpcyBkZWZpbmVkIHRvIGNlbnRlciB0aGUgcGVyY2VudGFnZXMuCgpCeSBkZWZhdWx0LCB0aGUgbGVnZW5kIGluY2x1ZGVzIHRoZSBuYW1lIG9mIHRoZSBjb2x1bW4gd2l0aCB0aGUgZ2VuZGVyIGRhdGEsIHdoaWNoIGlzICJWYXIyIi4KVG8gY2hhbmdlIHRoaXMgbmFtZSwgdXNlIHRoZSBjb21tYW5kIGBsYWJzKGZpbGw9IkdlbmRlciIpYCB0byBwcm9wZXJseSBuYW1lIHRoZSBsZWdlbmQuCkZpbmFsbHksIHRoZSBZIGFuZCBYIGF4aXMgYXJlIGxhYmVsZWQgd2l0aCBgeWxhYmAgYW5kIGB4bGFiLmAKCmBgYHtyIGdyYWZiYXJ9CmxpYnJhcnkoZ2dwbG90MikKZ2dwbG90KGRhdGE9dGFibGUsIGFlcyh4PVZhcjEsIHk9RnJlcSwgZmlsbD1WYXIyLCB5bWF4PTYwKSkrCiAgZ2VvbV9iYXIocG9zaXRpb249ImRvZGdlIiwgc3RhdD0iaWRlbnRpdHkiKSsKICBnZW9tX3RleHQoYWVzKGxhYmVsPXBhc3RlKHJvdW5kKEZyZXEsIDEpLCAiJSIsIHNlcD0iIikpLAogICAgICAgICAgICBwb3NpdGlvbj1wb3NpdGlvbl9kb2RnZSh3aWR0aD0wLjkpLCB2anVzdD0tMC4yNSkrCiAgbGFicyhmaWxsPSJHZW5kZXIiKSsKICB5bGFiKCJQZXJjZW50YWdlIikrCiAgeGxhYigiU2F0aXNmYWN0aW9uIHdpdGggZGVtb2NyYWN5IikKYGBgCgpPdGhlciB3YXkgdG8gZGlzcGxheSB0aGlzIGRhdGEgaXMgdGhyb3VnaCBzdGFja2VkIGJhcnMuClRoYXQgaXMsIGZvciBlYWNoIGdlbmRlciBjYXRlZ29yeSwgdGhlIGRpc3RyaWJ1dGlvbiBvZiBzYXRpc2ZhY3Rpb24gd2l0aCBkZW1vY3JhY3kgaXMgc2hvd24uCkZvciB0aGlzLCB3ZSB1c2UgdGhlIHNhbWUgY29tbWFuZCBgZ2dwbG90YCBidXQgbm93IHRoZSBvcmRlciBvZiB0aGUgdmFyaWFibGVzIGluIHRoZSBhZXN0aGV0aWMgaXMgY2hhbmdlZC4KTm93IHRoZSB2YXJpYWJsZSAiVmFyMiIgKHdpdGggdGhlIGdlbmRlciBjYXRlZ29yaWVzKSBpcyBsb2NhdGVkIG9uIHRoZSBYIGF4aXMgYW5kIGVhY2ggYmFyIGlzIGRpdmlkZWQgYWNjb3JkaW5nIHRvIHRoZSB2YWx1ZXMgb2YgVmFyMS4KClRoZSBiYXIgdHlwZSBjaGFuZ2VzIGluIHRoZSBjb21tYW5kIGBnZW9tX2JhcmAgdG8gYHBvc2l0aW9uPSJzdGFjayJgLgpJbiB0aGUgc2FtZSB3YXksIHRoZSBkYXRhIGxhYmVscyBoYXZlIHRvIGNvbnNpZGVyIHRoZSBwb3NpdGlvbiBvZiBlYWNoIHNsaWNlLCB3aXRoIGBwb3NpdGlvbj1wb3NpdGlvbl9zdGFjaygpYC4KCmBgYHtyIGdyYWZiYXJhcGlsYX0KZ2dwbG90KGRhdGE9dGFibGUsIGFlcyh4PVZhcjIsIHk9RnJlcSwgZmlsbD1WYXIxLCB5bWF4PTEwMCkpKwogIGdlb21fYmFyKHBvc2l0aW9uPSJzdGFjayIsIHN0YXQ9ImlkZW50aXR5IikrCiAgZ2VvbV90ZXh0KGFlcyhsYWJlbD1wYXN0ZShyb3VuZChGcmVxLCAxKSwgIiUiLCBzZXA9IiIpKSwKICAgICAgICAgICAgcG9zaXRpb249cG9zaXRpb25fc3RhY2soKSwgdmp1c3Q9MikrCiAgbGFicyhmaWxsPSJTYXRpc2ZhY3Rpb24gd2l0aCBkZW1vY3JhY3kiKSsKICB5bGFiKCJQZXJjZW50YWdlIikrCiAgeGxhYigiR2VuZGVyIikKYGBgCgojIENyb3NzLXRhYmxlIG9mIHNhdGlzZmFjdGlvbiB3aXRoIGRlbW9jcmFjeSBieSBlZHVjYXRpb25hbCBsZXZlbAoKRmlndXJlIDEuMTQgb2YgdGhlIHJlcG9ydCBzaG93cyB0aGUgcmVzdWx0cyBvbiBzYXRpc2ZhY3Rpb24gd2l0aCBkZW1vY3JhY3kgKGFjY29yZGluZyB0byB0aGUgcmVjb2RlZCBkdW1teSB2YXJpYWJsZSkgYnkgZWR1Y2F0aW9uYWwgbGV2ZWwuCkFzIGEgc2Vjb25kIGV4YW1wbGUsIGhlcmUgd2UgYXJlIGdvaW5nIHRvIHJlcGxpY2F0ZSB0aGF0IHJlbGF0aW9uc2hpcCB1c2luZyB0aGUgb3JpZ2luYWwgdmFyaWFibGUgb2YgdHlwZSBmYWN0b3IuCgpXZSBmaXJzdCByZWNvZGUgdGhlIGVkdWNhdGlvbiB2YXJpYWJsZS4KVGhlIG9yaWdpbmFsIHZhcmlhYmxlICJlZCIgaXMgYSBudW1lcmljYWwgdmFyaWFibGUgKHllYXJzIG9mIHN0dWR5KS4KVGhpcyB2YXJpYWJsZSBoYXMgdmFsdWVzIHJhbmdpbmcgZnJvbSAwIHRvIDE4LgpJdCBpcyByZWNvZGVkIGluIHN1Y2ggYSB3YXkgdGhhdCB0aG9zZSB3aXRoIHplcm8geWVhcnMgb2YgZWR1Y2F0aW9uIGFyZSBhc3NpZ25lZCBhIHZhbHVlIG9mIDAgIk5vbmUiLCB0aG9zZSBiZXR3ZWVuIDEgYW5kIDYgeWVhcnMgb2YgZWR1Y2F0aW9uIGFyZSBhc3NpZ25lZCBhIHZhbHVlIG9mIDEgIlByaW1hcnkiLCB0aG9zZSBiZXR3ZWVuIDcgYW5kIDExIHllYXJzIG9mIGVkdWNhdGlvbiBhcmUgYXNzaWducyB0aGVtIHRoZSB2YWx1ZSBvZiAyICJTZWNvbmRhcnkiIGFuZCBiZXR3ZWVuIDEyIGFuZCAxOCB5ZWFycyBvZiBlZHVjYXRpb24gdGhlIHZhbHVlIG9mIDMgIlBvc3Qtc2Vjb25kYXJ5Ii4KCmBgYHtyIHJlY29lZH0KbGlicmFyeShjYXIpCmxhcG9wMTgkZWR1YyA8LSBjYXI6OnJlY29kZShsYXBvcDE4JGVkLCAiMD0wOyAxOjY9MTsgNzoxMT0yOyAxMjoxOD0zIikKbGFwb3AxOCRlZHVjIDwtIGFzLmZhY3RvcihsYXBvcDE4JGVkdWMpCmxldmVscyhsYXBvcDE4JGVkdWMpIDwtIGMoIk5vbmUiLCAiUHJpbWFyeSIsICJTZWNvbmRhcnkiLCAiUG9zdC1zZWNvbmRhcnkiKQp0YWJsZShsYXBvcDE4JGVkdWMpCmBgYAoKV2l0aCB0aGUgcmVjb2RlZCB2YXJpYWJsZSBpdCBpcyBwb3NzaWJsZSB0byBjYWxjdWxhdGUgdGhlIGNyb3NzLXRhYmxlIG9mIHNhdGlzZmFjdGlvbiB3aXRoIGRlbW9jcmFjeSBieSBlZHVjYXRpb25hbCBsZXZlbHMuCgpgYGB7ciB0YWJsZWVkfQphZGRtYXJnaW5zKHByb3AudGFibGUodGFibGUobGFwb3AxOCRzYXRpcywgbGFwb3AxOCRlZHVjKSwgMikqMTAwLCAxKQpgYGAKClRvIGNyZWF0ZSB0aGUgZ3JhcGgsIHdlIGhhdmUgdG8gc2F2ZSB0aGUgdGFibGUgYXMgYSBkYXRhZnJhbWUuClRoZSBjb21tYW5kIGBhcy5kYXRhLmZyYW1lYCBpcyB1c2VkIHRvIHNhdmUgdGhlIHBlcmNlbnRhZ2VzIHNvIHRoYXQgdGhleSBjYW4gYmUgdXNlZCB3aXRoIHRoZSBjb21tYW5kIGBnZ3Bsb3RgLgoKYGBge3IgdGFibGU1fQp0YWJsZTIgPC0gYXMuZGF0YS5mcmFtZShwcm9wLnRhYmxlKHRhYmxlKGxhcG9wMTgkc2F0aXMsIGxhcG9wMTgkZWR1YyksIDIpKjEwMCkKdGFibGUyCmBgYAoKSW4gdGhpcyBjYXNlLCBzaW5jZSB3ZSBoYXZlIDQgY2F0ZWdvcmllcyBmb3Igc2F0aXNmYWN0aW9uIHdpdGggZGVtb2NyYWN5IGFuZCBhbm90aGVyIDQgY2F0ZWdvcmllcyBmb3IgZWR1Y2F0aW9uYWwgbGV2ZWxzLCBhIGJhciBncmFwaCB3b3VsZCBjcmVhdGUgMTYgYmFycywgd2hpY2ggd291bGQgY29tcGxpY2F0ZSB0aGUgY29tcGFyaXNvbi4KU28sIGluIHRoaXMgY2FzZSwgdGhlIHN0YWNrZWQgYmFyIHR5cGUgaXMgcHJlZmVycmVkLgoKYGBge3IgYmFycmFwaWxhZGFzZWR9CmxpYnJhcnkoZ2dwbG90MikKZ2dwbG90KGRhdGE9dGFibGUyLCBhZXMoeD1WYXIyLCB5PUZyZXEsIGZpbGw9VmFyMSwgeW1heD0xMDApKSsKICBnZW9tX2Jhcihwb3NpdGlvbj0ic3RhY2siLCBzdGF0PSJpZGVudGl0eSIpKwogIGdlb21fdGV4dChhZXMobGFiZWw9cGFzdGUocm91bmQoRnJlcSwgMSksICIlIiwgc2VwPSIiKSksCiAgICAgICAgICAgIHBvc2l0aW9uPXBvc2l0aW9uX3N0YWNrKCksIHZqdXN0PTIpKwogIGxhYnMoZmlsbD0iU2F0aXNmYWN0aW9uIHdpdGggZGVtb2NyYWN5IikrCiAgeWxhYigiUGVyY2VudGFnZSIpKwogIHhsYWIoIkVkdWNhdGlvbiBsZXZlbCIpCmBgYAoKRmlndXJlIDEuMTQgc2hvd3MgdGhhdCB0aGVyZSBpcyBhIGhpZ2hlciBwZXJjZW50YWdlIG9mIHNhdGlzZmFjdGlvbiB3aXRoIGRlbW9jcmFjeSBhbW9uZyB0aGUgbGVhc3QgZWR1Y2F0ZWQuClRoaXMgcmVsYXRpb25zaGlwIGNhbiBhbHNvIGJlIHNlZW4gaW4gdGhpcyBncmFwaC4KVGhlIHNlY3RvcnMgInZlcnkgc2F0aXNmaWVkIiAoaW4gcGluaykgYW5kICJzYXRpc2ZpZWQiIChpbiBncmVlbikgZGVjcmVhc2UgYXMgd2UgZ28gZnJvbSBub25lIHRvIHByaW1hcnksIHNlY29uZGFyeSBhbmQgaGlnaGVyLgoKSW4gYWxsIGV4YW1wbGVzLCB3ZSBjYW4gb2JzZXJ2ZSBwZXJjZW50IGRpZmZlcmVuY2VzIGluIGEgdmFyaWFibGUgYnkgY2F0ZWdvcmllcyBvZiBvdGhlciB2YXJpYWJsZS4KVGhlc2UgcGVyY2VudGFnZXMgY2FuIGJlIGNvbXBhcmVkIGRpcmVjdGx5IGluIHRoZSBncmFwaCwgYnV0IHdlIHNob3VsZCBydW4gYSBzaWduaWZpY2FuY2UgdGVzdCB0byBldmFsdWF0ZSBpZiB0aGVyZSBpcyBhIHN0YXRpc3RpY2FsbHkgc2lnbmlmaWNhbnQgcmVsYXRpb25zaGlwLgoKIyBDaGktc3F1YXJlIHRlc3Qgb2YgaW5kZXBlbmRlbmNlCgpUd28gY2F0ZWdvcmljYWwgdmFyaWFibGVzIGFyZSBzYWlkIHRvIGJlIHN0YXRpc3RpY2FsbHkgaW5kZXBlbmRlbnQgaWYgdGhlIGNvbmRpdGlvbmFsIChwb3B1bGF0aW9uKSBkaXN0cmlidXRpb25zIGFyZSBpZGVudGljYWwgZm9yIGVhY2ggY2F0ZWdvcnkgb2YgdGhlIGluZGVwZW5kZW50IHZhcmlhYmxlLgpJbiB0aGUgYWJvdmUgYml2YXJpYXRlIHJlbGF0aW9uc2hpcCwgdGhpcyBtZWFucyB0aGF0IGJlaW5nIG1hbGUgb3IgZmVtYWxlIGRvZXMgbm90IGNoYW5nZSBvcGluaW9ucyByZWdhcmRpbmcgc2F0aXNmYWN0aW9uIHdpdGggZGVtb2NyYWN5LgpBcyB0aGVzZSBjb25kaXRpb25hbCBkaXN0cmlidXRpb25zIGRpZmZlciBtb3JlIGZyb20gZWFjaCBvdGhlciwgYm90aCB2YXJpYWJsZXMgYXJlIHNhaWQgdG8gYmUgbW9yZSByZWxhdGVkIG9yIG1vcmUgZGVwZW5kZW50LgoKVGhpcyBldmFsdWF0aW9uIGlzIGRvbmUgdXNpbmcgdGhlIGNoaS1zcXVhcmUgb3IgJFxjaGleMiQgdGVzdCBvZiBpbmRlcGVuZGVuY2UuClRoaXMgdGVzdCBpcyBiYXNlZCBvbiB0aGUgY29tcGFyaXNvbiBvZiB0aGUgb2JzZXJ2ZWQgZnJlcXVlbmNpZXMgKHRoZSBvYnNlcnZhdGlvbnMgY29sbGVjdGVkIGluIHRoZSBmaWVsZCkgdmVyc3VzIHRoZSBleHBlY3RlZCBmcmVxdWVuY2llcyAodGhlIG9ic2VydmF0aW9ucyB0aGF0IHNob3VsZCBiZSBpbiBlYWNoIGNlbGwgaWYgdGhlIHZhcmlhYmxlcyB3ZXJlIGluZGVwZW5kZW50KS4KVGhlIHRlc3Qgc3RhdGlzdGljIHN1bW1hcml6ZXMgaG93IGNsb3NlIHRoZSBleHBlY3RlZCBmcmVxdWVuY2llcyBhcmUgdG8gdGhlIG9ic2VydmVkIGZyZXF1ZW5jaWVzLgoKJCQKXGNoaV4yID0gXHN1bVxmcmFjeyhmX28tZl9lKV4yfXtmX2V9CiQkCgpUaGUgc21hbGxlciB0aGUgZGlzdGFuY2UgaW4gZWFjaCBjZWxsLCB0aGUgbGVzcyBsaWtlbHkgaXQgaXMgdG8gcmVqZWN0IHRoZSBudWxsIGh5cG90aGVzaXMuClRoZSBsYXJnZXIgdGhlIGRpc3RhbmNlIGluIGVhY2ggY2VsbCwgdGhlIG1vcmUgbGlrZWx5IGl0IGlzIHRvIHJlamVjdCB0aGUgbnVsbCBoeXBvdGhlc2lzLgoKJCQKSDA6IGZfbyA9IGZfZQokJAoKV2l0aCB0aGUgdmFsdWUgb2YgJFxjaGleMiQgYW5kIHdpdGggdGhlIGRlZ3JlZXMgb2YgZnJlZWRvbSAocm93cy0xXCpjb2x1bW5zLTEpLCBhIHAtdmFsdWUgaXMgY2FsY3VsYXRlZCBvbiB0aGUgY2hpLXNxdWFyZSBkaXN0cmlidXRpb24uCklmIHRoaXMgcC12YWx1ZSBpcyBsZXNzIHRoYW4gMC4wNSwgSDAgaXMgcmVqZWN0ZWQuClRoaXMgdGVzdCByZXF1aXJlcyB0aGF0IHRoZXJlIGJlIGF0IGxlYXN0IDUgb2JzZXJ2YXRpb25zIGluIGVhY2ggY2VsbC4KCiMgVGVzdCBvZiB2b3RlcyBhcmUgY291bnRlZCBmYWlybHkgYnkgY291bnRyeQoKSW4gUiwgdGhlIGNvbW1hbmQgYGNoaXNxLnRlc3RgIGlzIHVzZWQgdG8gY2FsY3VsYXRlIHRoZSBzdGF0aXN0aWMgYW5kIHRoZSBhc3NvY2lhdGVkIHAtdmFsdWUuClRoZSByZXN1bHRzIG9mIHRoaXMgdGVzdCBjYW4gYmUgc2F2ZWQgdG8gYSBuZXcgb2JqZWN0ICJjaGl0ZXN0MSIuCgpgYGB7cn0KY2hpdGVzdDEgPC0gY2hpc3EudGVzdChsYXBvcDIxJGNvdW50ZmFpcjFyLCBsYXBvcDIxJHBhaXMpCmNoaXRlc3QxCmBgYAoKVGhlIHAtdmFsdWUgb2J0YWluZWQgaXMgbGVzcyB0aGFuIDAuMDUsIHNvIHRoZSBIMCBpcyByZWplY3RlZCwgc28gd2Ugc2F5IHRoYXQgdGhlIG9ic2VydmVkIGZyZXF1ZW5jaWVzIHNlZW0gdG8gYmUgZGlmZmVyZW50IGZyb20gdGhlIGV4cGVjdGVkIGZyZXF1ZW5jaWVzIHRoYXQgd291bGQgZXhpc3QgaW4gZWFjaCBjZWxsIGlmIHRoZXJlIHdlcmUgbm8gcmVsYXRpb25zaGlwLCBzbyB3ZSBzYXkgdGhhdCB0aGVyZSBpcyBhIHJlbGF0aW9uc2hpcCBiZXR3ZWVuIHRoZSB2YXJpYWJsZXMgb3IgdGhhdCB0aGVyZSBpcyBhIGRlcGVuZGVuY3kgYmV0d2VlbiB0aGUgdHdvLgoKSXQgaXMgaW1wb3J0YW50IHRvIG5vdGUgdGhhdCAiY2hpdGVzdDEiIGlzIGFuIG9iamVjdCBvZiB0eXBlICpsaXN0Ki4KVGhpcyB0eXBlIG9mIG9iamVjdCBjYW4gc3RvcmUgb3RoZXIgaW5mb3JtYXRpb24gb2YgYSBkaWZmZXJlbnQgdHlwZS4KRm9yIGV4YW1wbGUsICJjaGl0ZXN0MSIgc2F2ZXMgdGhlIHRhYmxlcyBvZiBvYnNlcnZlZCBmcmVxdWVuY2llcyAoc2FtZSByZXN1bHQgYXMgd2l0aCB0aGUgY29tbWFuZCBgdGFibGVgKSBhbmQgdGhlIHRhYmxlIG9mIGV4cGVjdGVkIGZyZXF1ZW5jaWVzLgpJbiB0aGlzIG9iamVjdCB0aGUgdmFsdWUgb2YgdGhlIHJlc2lkdWFscywgdGhlIHN0YW5kYXJkaXplZCByZXNpZHVhbHMgYW5kIHRoZSB2YWx1ZSBvZiB0aGUgcC12YWx1ZSBhcmUgYWxzbyBzYXZlZC4KCmBgYHtyfQpjaGl0ZXN0MSRvYnNlcnZlZApjaGl0ZXN0MSRleHBlY3RlZApgYGAKClRvIGV2YWx1YXRlIHRoZSBzdHJlbmd0aCBvZiB0aGUgcmVsYXRpb25zaGlwLCB3ZSB1c2UgdGhlIGxpYnJlcnkgYHZjZGAgdGhhdCBoYXMgdGhlIGNvbW1hbmQgYGFzc29jc3RhdHNgIHRoYXQgb2ZmZXJzIGEgc2VyaWVzIG9mIG1lYXN1cmVzIG9mIGFzc29jaWF0aW9uIGZvciBhIGNyb3NzLXRhYmxlIGJldHdlZW4gYW4gb3JkaW5hbCB2YXJpYWJsZSwgYXMgImNvdW50ZmFpcjEiLCBhbmQgYSBub21pbmFsIHZhcmlhYmxlLCBhcyAicGFpcyIuCgpUaGUgY29tbWFuZCBgYXNzb2NzdGF0c2AgY2Fubm90IGNhbGN1bGF0ZSBtZWFzdXJlcyBvZiBhc3NvY2lhdGlvbnMgaWYgY2VsbHMgb2YgYSBjcm9zcy10YWJsZSBoYXZlIG51bGwgdmFsdWVzLgpCZWNhdXNlIHdlIGhhdmUgc29tZSBjb3VudHJpZXMgd2hlcmUgcXVlc3Rpb24gImNvdW50ZmFpcjEiIHdhcyBub3QgYXNrZWQsIHdlIGhhdmUgdG8gaW5kaWNhdGUgdGhhdCB0aGlzIGNvbW1hbmQgZG9lcyBub3QgdGFrZSBpbnRvIGFjY291bnQgdGhlc2UgY291bnRyaWVzLgpGb3IgZGVhbCB3aXRoIHRoaXMsIHdlIGNyZWF0ZSBhIG5ldyAiY291bnRyeTIiIHZhcmlhYmxlLCB3aGVyZSBvYnNlcnZhdGlvbnMgb2YgdGhlc2UgY291bnRyaWVzIGFyZSBzZXQgYXMgTkFzLgoKYGBge3J9CmxhcG9wMjEkY291bnRyeV9yID0gbGFwb3AyMSRwYWlzCmxhcG9wMjEkY291bnRyeV9yW2xhcG9wMjEkcGFpcz09MV0gPSBOQQpsYXBvcDIxJGNvdW50cnlfcltsYXBvcDIxJHBhaXM9PTJdID0gTkEKbGFwb3AyMSRjb3VudHJ5X3JbbGFwb3AyMSRwYWlzPT0zXSA9IE5BCmxhcG9wMjEkY291bnRyeV9yW2xhcG9wMjEkcGFpcz09NF0gPSBOQQpsYXBvcDIxJGNvdW50cnlfcltsYXBvcDIxJHBhaXM9PTIyXSA9IE5BCmBgYAoKV2l0aCB0aGlzIG5ldyB2YXJpYWJsZSwgd2UgY2FuIGNyZWF0ZSBhIGNyb3NzLXRhYmxlIGJldHdlZW4gImNvdW50ZmFpcjEiIGFuZCAiY291bnRyeV9yIiBhbmQgY2FsY3VsYXRlIG1lYXN1cmVzIG9mIGFzc29jaWF0aW9uLgoKYGBge3J9CmxpYnJhcnkodmNkKQp0YWJsZTIgPC0gdGFibGUobGFwb3AyMSRjb3VudGZhaXIxciwgbGFwb3AyMSRjb3VudHJ5X3IpCmFzc29jc3RhdHModGFibGUyKQpgYGAKClRoZSBjb21tYW5kIGBhc3NvY3N0YXRzYCByZXR1cm5zIHRoZSBjb250aW5nZW5jeSBjb2VmZmljaWVudCBhbmQgQ3JhbWVywrRzIFYgYXMgbWVhc3VyZXMuClRoZXNlIG1lYXN1cmVzIHZhcnkgYmV0d2VlbiAwIGFuZCAxLgpXaGlsZSBjbG9zZXIgdG8gemVybywgdGhlIHJlbGF0aW9uc2hpcCBpcyB3ZWFrZXIuCk9uIHRoZSBjb250cmFyeSwgd2hpbGUgY2xvc2VyIHRvIDEsIHRoZSByZWxhdGlvbnNoaXAgaXMgc3Ryb25nZXIuCgpCeSBjb252ZW50aW9uLCB3ZSBjYW4gYXNzdW1lIHRoYXQgd2VhayByZWxhdGlvbnNoaXBzIGFyZSBiZXR3ZWVuIDAgYW5kIDAuMywgbW9kZXJhdGUgcmVsYXRpb25zaGlwcyBiZXR3ZW4gMC4zIGFuZCAwLjYgYW5kIHN0cm9uZyByZWxhdGlvbnNoaXBzIGFyZSBoaWdoZXIgdGhhbiAwLjYuCkluIHRoaXMgY2FzZSwgd2UgY2FuIGluZGljYXRlIHRoYXQgdGhlIHJlbGF0aW9uc2hpcCBiZXR3ZWVuIHZvdGVzIGFyZSBjb3VudGVkIGZhaXJseSBhbmQgY291bnRyeSBpcyB3ZWFrLgoKIyBUZXN0IG9mIHNhdGlzZmFjdGlvbiB3aXRoIGRlbW9jcmFjeSBieSBlZHVjYXRpb25hbCBsZXZlbAoKVG8gZXZhbHVhdGUgdGhlIHJlbGF0aW9uc2hpcCBiZXR3ZWVuIHNhdGlzZmFjdGlvbiB3aXRoIGRlbW9jcmFjeSBhbmQgZ2VuZGVyLCB3ZSBjYW4gYWxzbyB1c2UgdGhlIHRlc3Qgb2YgaW5kZXBlbmRlbmNlIG9mICRcY2hpXjIkLgpUaGUgcmVzdWx0cyBvZiB0aGlzIHRlc3QgYXJlIHNhdmVkIGluIGFuIG9iamVjdCAiY2hpdGVzdDIiLgoKYGBge3J9CmNoaXRlc3QyIDwtIGNoaXNxLnRlc3QobGFwb3AxOCRzYXRpcywgbGFwb3AxOCRlZHVjKQpjaGl0ZXN0MgpgYGAKCkFnYWluLCB3ZSBvYnRhaW4gYSBwLXZhbHVlIG9mIGxlc3MgdGhhbiAwLjA1LCB3aXRoIHdoaWNoIHRoZSBudWxsIGh5cG90aGVzaXMgaXMgcmVqZWN0ZWQgYW5kIGl0IGlzIGFmZmlybWVkIHRoYXQgdGhlIG9ic2VydmVkIGZyZXF1ZW5jaWVzIGFyZSBkaWZmZXJlbnQgZnJvbSB0aG9zZSBleHBlY3RlZCwgd2l0aCB3aGljaCB3ZSBjb25jbHVkZSB0aGF0IHRoZXJlIHdvdWxkIGJlIGEgZGVwZW5kZW5jeSByZWxhdGlvbnNoaXAgYmV0d2VlbiB0aGUgdmFyaWFibGVzLgoKVG8gZXZhbHVhdGUgdGhlIHN0cmVuZ3RoIG9mIHRoZSByZWxhdGlvbnNoaXAsIHdlIHVzZSB0aGUgbGlicmFyeSBgb2lpYCBhbmQgdGhlIGNvbW1hbmQgYGFzc29jaWF0aW9uLm1lYXN1cmVzYCwgdGhhdCByZXR1cm4gYSBzZXJpZXMgb2YgYXNzb2NpYXRpb24gbWVhc3VyZXMgdGhhdCBmaXQgdGhpcyB0eXBlcyBvZiB2YXJpYWJsZXMsIHRoYXQgaW4gdGhpcyBjYXNlIGFyZSBib3RoIG9yZGluYWwKCmBgYHtyIG9yZGluYWx9CmxpYnJhcnkob2lpKQphc3NvY2lhdGlvbi5tZWFzdXJlcyhsYXBvcDE4JHNhdGlzLCBsYXBvcDE4JGVkdWMpCmBgYAoKSW4gdGhpcyBjYXNlLCB3ZSBvYnNlcnZlIHRoZSBtZWFzdXJlcyBvZiBhc3NvY2lhdGlvbiBmb3Igb3JkaW5hbCB2YXJpYWJsZXMuClRoaXMgY29tbWFuZCByZXBvcnRzIDQgb2YgdGhlc2UgbWVhc3VyZW1lbnRzLCBhbGwgb2YgdGhlbSB2YXJ5IGJldHdlZW4gLTEgdG8gKzEuCkluIG91ciBleGFtcGxlLCB0aGV5IGFsbCBoYXZlIGEgcG9zaXRpdmUgc2lnbiwgd2hpY2ggaW5kaWNhdGVzIGEgZGlyZWN0IHJlbGF0aW9uc2hpcCBiZXR3ZWVuIGJvdGggdmFyaWFibGVzLgpUaGlzIHdvdWxkIHNlZW0gdG8gZ28gYWdhaW5zdCB3aGF0IGlzIHJlcG9ydGVkIGluIEZpZ3VyZSAxLjE0IG9mIHRoZSByZXBvcnQgd2hlcmUgaXQgaXMgY2xlYXJseSBvYnNlcnZlZCB0aGF0IHNhdGlzZmFjdGlvbiB3aXRoIGRlbW9jcmFjeSBkZWNyZWFzZXMgYXQgaGlnaGVyIGVkdWNhdGlvbmFsIGxldmVscywgd2hpY2ggd291bGQgYmUgZXhwcmVzc2VkIGluIGEgbmVnYXRpdmUgc2lnbi4KClRoaXMgYXBwYXJlbnQgY29udHJhZGljdGlvbiBpcyBkdWUgb24gaG93IHNhdGlzZmFjdGlvbiB3aXRoIGRlbW9jcmFjeSAoInNhdGlzIiB2YXJpYWJsZSB0aGF0IGlzIGNyZWF0ZWQgZnJvbSAicG40IikgaGFzIGJlZW4gY29kZWQuClRoZSBvcmlnaW5hbCB2YXJpYWJsZSBoYXMgdmFsdWVzIGJldHdlZW4gMSBhbmQgNCwgd2hlcmUgMSBtZWFucyAidmVyeSBzYXRpc2ZpZWQiIGFuZCA0IG1lYW5zICJ2ZXJ5IGRpc3NhdGlzZmllZCIuClRoYXQgaXMsIGhpZ2ggdmFsdWVzIGluZGljYXRlICJsZXNzImluIHRoZSB2YXJpYWJsZS4KSXQgaXMgZm9yIHRoaXMgcmVhc29uIHRoYXQgdGhlIGFzc29jaWF0aW9uIHRlc3QgcmVzdWx0cyB3aXRoIGEgcG9zaXRpdmUgc2lnbiwgd2hpY2ggaW4gdGhpcyBjYXNlIHdvdWxkIGluZGljYXRlIHRoYXQgYSBoaWdoZXIgdmFsdWUgb2YgdGhlIGVkdWNhdGlvbiB2YXJpYWJsZSBtZWFucyAibW9yZSIgb2YgdGhlIHNhdGlzZmFjdGlvbiB3aXRoIGRlbW9jcmFjeSB2YXJpYWJsZSAod2hpY2ggaXMgYWN0dWFsbHkgbGVzcykuCgpUbyBhdm9pZCB0aGlzIGNvbmZ1c2lvbiwgdGhlIG1vbm90b255IG9mIHRoZSBzYXRpc2ZhY3Rpb24gd2l0aCBkZW1vY3JhY3kgdmFyaWFibGUgc2hvdWxkIGhhdmUgYmVlbiBjaGFuZ2VkIHNvIHRoYXQgaGlnaGVyIHZhbHVlcyBpbmRpY2F0ZSBncmVhdGVyIHNhdGlzZmFjdGlvbiBhbmQsIHdpdGggdGhpcywgYSBuZWdhdGl2ZSBzaWduIGlzIG9idGFpbmVkIGluIHRoZSBhc3NvY2lhdGlvbiBtZWFzdXJlcy4KVGhpcyBoYXMgYmVlbiBkb25lIGluIHRoaXMgc2VjdGlvbiB0byBkcmF3IGF0dGVudGlvbiB0byB0aGUgZmFjdCB0aGF0IGNvZGluZyBoYXMgY29uc2VxdWVuY2VzIGZvciB0aGUgcmVzdWx0cyBhbmQgY2FuIGxlYWQgdG8gY29uZnVzaW9uIGlmIGNhcmUgaXMgbm90IHRha2VuLgoKRmluYWxseSwgdGhlIHZhbHVlIG9mIHRoZSBhc3NvY2lhdGlvbiBtZWFzdXJlcyBhcmUgbGVzcyB0aGFuIDAuMywgaW5kaWNhdGluZyB0aGF0IHRoZSByZWxhdGlvbnNoaXAgYmV0d2VlbiB0aGUgdmFyaWFibGVzIGlzIHdlYWsuCgojIFN1bW1hcnkKCkluIHRoaXMgc2VjdGlvbiB3ZSBoYXZlIHdvcmtlZCB3aXRoIGJpdmFyaWF0ZSByZWxhdGlvbnNoaXBzIGJldHdlZW4gY2F0ZWdvcmljYWwgdmFyaWFibGVzLgpDcm9zcy10YWJsZXMgYW5kIGJhciBncmFwaHMgaGF2ZSBiZWVuIGNhbGN1bGF0ZWQgdG8gc2hvdyB0aGUgZGVzY3JpcHRpdmUgcmVzdWx0cy4KVGhlbiwgdGhlIGNoaS1zcXVhcmUgdGVzdCBvZiBpbmRlcGVuZGVuY2UgaGFzIGJlZW4gdXNlZCB0byBpbmZlciB3aGV0aGVyIHRoZXJlIGlzIGEgZGVwZW5kZW5jeSByZWxhdGlvbnNoaXAgYmV0d2VlbiB0aGUgdmFyaWFibGVzIGluIHRoZSBwb3B1bGF0aW9uIGFuZCBmaW5hbGx5IHRoZSBzdHJlbmd0aCBvZiB0aGUgYXNzb2NpYXRpb24gYmV0d2VlbiB0aGUgdmFyaWFibGVzIGlzIGV2YWx1YXRlZCwgZGlmZmVyZW50aWF0aW5nIHdoZW4gaXQgY29tZXMgdG8gbm9taW5hbCBvciBvcmRpbmFsIHZhcmlhYmxlcy4KCiMgQ2FsY3VsYXRpb25zIGluY2x1ZGluZyBzdXJ2ZXkgd2VpZ2h0cwoKV2UgY2FsY3VsYXRlIHRoZSBwZXJjZW50YWdlIG9mIHZvdGVzIGFyZSBjb3VudGVkIGZhaXJseSBieSBjb3VudHJ5IGluY2x1ZGluZyBzdXJ2ZXkgd2VpZ2h0cyBpbiB0aGUgc2VjdGlvbiBhYm91dCBbZGVzY3JpcHRpdmVzIG9mIG9yZGluYWwgdmFyaWFibGVzXShodHRwczovL2FydHVyb21hbGRvbmFkby5naXRodWIuaW8vQmFyb21ldHJvRWR1X1dlYl9FbmcvRGVzY3JpcHRpdmVzMi5odG1sKS4KV2l0aCB0aGlzIGRhdGEsIHdlIHJlcGxpY2F0ZSBGaWd1cmUgMi41LgoKVG8gY2FsY3VsYXRlIGEgY2hpLXNxdWFyZSB0ZXN0IGluY2x1ZGluZyBzdXJ2ZXkgd2VpZ2h0cywgd2UgY2FuIHVzZSB0aGUgbGlicmFyeSBgc3VydmV5YCBhbmQgdGhlIGNvbW1hbmQgYHN2eWNoaXNxYC4KCmBgYHtyIGRlc2lnbn0KbGlicmFyeShzdXJ2ZXkpCmRlc2lnbjE4ID0gc3Z5ZGVzaWduKGlkcyA9IH51cG0sIHN0cmF0YSA9IH5lc3RyYXRvcHJpLCB3ZWlnaHRzID0gfndlaWdodDE1MDAsIG5lc3Q9VFJVRSwgZGF0YT1sYXBvcDE4KQpgYGAKCldlIGNhbGN1bGF0ZSB0aGUgY29udGluZ2VuY3kgdGFibGUgd2l0aCB0aGUgY29tbWFuZCBgc3Z5dGFibGVgLgpJbiB0aGlzIGNhc2Ugd2UgY3Jvc3Mgc2F0aXNmYWN0aW9uIHdpdGggZGVtb2NyYWN5IGJ5IGdlbmRlci4KVGhpcyBjb21tYW5kIGlzIG5lc3RlZCBpbnNpZGUgYHByb3AudGFibGVgIHRvIGRpc3BsYXkgdGhlIHJlbGF0aXZlIGZyZXF1ZW5jaWVzIGFuZCBub3QgdGhlIGFic29sdXRlIG9uZXMuCkluIHR1cm4sIGFsbCBvZiB0aGlzIGlzIG5lc3RlZCBpbnNpZGUgdGhlIGNvbW1hbmQgYGFkZG1hcmdpbnNgIHRvIHByZXNlbnQgdGhlIHJlbGF0aXZlIGZyZXF1ZW5jaWVzIGFzIHBlcmNlbnRhZ2VzLgpJbiB0aGUgc2FtZSB3YXkgYXMgYWJvdmUsIHdlIGNhbiBzYXZlIHRoaXMgdGFibGUgaW4gYW4gb2JqZWN0IGZvciBncmFwaGluZyB0aGVzZSByZXN1bHRzLgoKYGBge3IgdGFibGV3fQphZGRtYXJnaW5zKHByb3AudGFibGUoc3Z5dGFibGUofnNhdGlzK2dlbmRlciwgZGVzaWduPWRlc2lnbjE4KSwyKSoxMDAsMSkKYGBgCgpUaGUgQ2hpLXNxdWFyZSB0ZXN0IG9mIGluZGVwZW5kZW5jZSBpbmNvcnBvcmF0aW5nIHN1cnZleSB3ZWlnaHRzIGlzIGNvbXB1dGVkIHVzaW5nIHRoZSBjb21tYW5kIGBzdnljaGlzcWAuClRoZSBkZXBlbmRlbnQgdmFyaWFibGUsIHRoZSBpbmRlcGVuZGVudCB2YXJpYWJsZSBhbmQgdGhlIG9iamVjdCBhcmUgaW5jbHVkZWQgd2l0aCB0aGUgc2FtcGxlIGRlc2lnbi4KCmBgYHtyIGNoaXd9CmNoaXRlc3QzID1zdnljaGlzcSh+c2F0aXMrZ2VuZGVyLGRlc2lnbjE4KQpjaGl0ZXN0MwpgYGAKClRoZSByZXN1bHRzIHNob3cgYSBwLXZhbHVlIGxlc3MgdGhhbiAwLjA1LCBzbyB0aGUgSDAgb2YgZXF1YWwgZXhwZWN0ZWQgYW5kIG9ic2VydmVkIGZyZXF1ZW5jaWVzIGNhbiBiZSByZWplY3RlZCwgc28gd2UgY29uY2x1ZGUgdGhhdCB0aGVyZSBpcyBhIHJlbGF0aW9uc2hpcCBvZiBzdGF0aXN0aWNhbCBkZXBlbmRlbmNlIGJldHdlZW4gYm90aCB2YXJpYWJsZXMuCgpPYnNlcnZlZCBhbmQgZXhwZWN0ZWQgdmFsdWVzIGNhbiBiZSBjYWxjdWxhdGVkLgpBcyBjYW4gYmUgc2VlbiwgdGhlIGV4cGVjdGVkIHZhbHVlcyBkaWZmZXIgZnJvbSB0aGUgcmVzdWx0cyB3aXRob3V0IHN1cnZleSB3ZWlnaHRzLgoKYGBge3Igb2JzdnJleHB3fQpjaGl0ZXN0MyRvYnNlcnZlZApjaGl0ZXN0MyRleHBlY3RlZApgYGAKCkluIHRoaXMgY2FzZSwgdGhlcmUgaXMgbm8gY29tbWFuZCB0byBjYWxjdWxhdGUgdGhlIGFzc29jaWF0aW9uIG1lYXN1cmVzIGluY29ycG9yYXRpbmcgdGhlIGRlc2lnbiBlZmZlY3QuClVud2VpZ2h0ZWQgYXNzb2NpYXRpb24gbWVhc3VyZXMgY2FuIGJlIHRha2VuIGFzIHJlZmVyZW5jZSB2YWx1ZXMuCg==