Introduction

In this section we will see how to construct confidence intervals of the mean using the data from the AmericasBarometer. For that, we will use the 2021 regional report “The Pulse of Democracy”, available here and the 2018/19 report, available here. The 2021 round reports data on executive coups. Figure 1.7 shows the percentage of citizens that tolerates an executive coup by country. In both cases, results include descriptive estimators and confidence intervals. The 2018/19 round of the AmericasBarometer reports data on social networks and political attitudes. In particular, Figure 3.9 reports the degree of satisfaction with democracy by type of user of social networks.

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 document loads a trimmed database. This database is hosted in the “materials_edu” repository of the LAPOP account on GitHub. It is recommended to clean the Environment before proceeding with this section.

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 upload the dataset for the 2021 round.

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

Tolerance to executive coups

Figure 1.7 of the report The Pulse of Democracy for the 2021 round of the AmericasBarometer shows the results of the percentage of citizens that tolerates an executive coup by country. This graph also displays the 95% confidence interval for each country.

The variable used in this figure is “jc15a”. Its wording is: “Do you believe that when the country is facing very difficult times, it is justifiable for the president of the country to close the Congress and govern without Congress?” The options are:

  1. Yes, it is justified

  2. No, it is not justified

Describing tolerance to executive coups

To calculate the percentage of citizens that justify or tolerate an executive coup, we have to recode this variable in a way that those who justify have a value of 100 and those who do not justify have a value of 0. In this case, we use the command recode and we tabulate with table to verify the recodification.

lapop21$jc15ar = car::recode(lapop21$jc15a, "1=100; 2=0")
table(lapop21$jc15ar)
## 
##     0   100 
## 14711  5908

To calculate the percentsage of citizens who tolerate an executive coup we can use the command table and prop.table. The new variable “jc15ar” is a dummy variable. With this type of variable, the mean is the proportion of responses with 100. It means that if we calculate the mean of this variable, the results is the percentage for all respondents. In this section we proceed as this variable is numeric. In strict sense, this is a categorical nominal variable. The calculation of standard deviations and confidence intervals are then referential.

The result indicates that the percentage of citizens that tolerates an executive coup is 28.7% for the whole sample.

summary(lapop21$jc15ar)
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max.    NA's 
##    0.00    0.00    0.00   28.65  100.00  100.00   40042

Confidence intervals for tolerance to executive coups

To calculate the 95% confidence interval of this percentage, we can use the command t.test or the library lsr that has the command ciMean.

t.test(lapop21$jc15ar)
## 
##  One Sample t-test
## 
## data:  lapop21$jc15ar
## t = 90.996, df = 20618, p-value < 2.2e-16
## alternative hypothesis: true mean is not equal to 0
## 95 percent confidence interval:
##  28.03599 29.27038
## sample estimates:
## mean of x 
##  28.65318
library(lsr)
ciMean(as.numeric(lapop21$jc15ar), na.rm = T)
##          2.5%    97.5%
## [1,] 28.03599 29.27038

Tolerance to executive coups by country

Figure 1.7 shows the percentage of citizens that tolerates an executive coup by country To replicate this results, we have to define the variable “pais” as factor. We saved this change in a new variable “paises” that we label with the initials of each country.

lapop21$paises = as.factor(lapop21$pais)
levels(lapop21$paises) <- c("MX", "GT", "SV", "HN", "NI", "CR",
                            "PN", "CO", "EC", "BO", "PE",
                            "PY", "CL", "UY", "BR", "AR", "DO",
                            "HT", "JA", "GU")
table(lapop21$paises)
## 
##   MX   GT   SV   HN   NI   CR   PN   CO   EC   BO   PE   PY   CL   UY   BR   AR 
## 2998 3000 3245 2999 2997 2977 3183 3003 3005 3002 3038 3004 2954 3009 3016 3011 
##   DO   HT   JA   GU 
## 3000 3088 3121 3011

To calculate these percentages by country, we can use several alternatives. For example, the command tapply allows to calculate the mean of a variable by groups of other variable.

tapply(lapop21$jc15ar, lapop21$paises, mean, na.rm=T)
##        MX        GT        SV        HN        NI        CR        PN        CO 
## 30.312500 36.687307 48.068670 22.660819 31.111111       NaN 28.962444 35.041447 
##        EC        BO        PE        PY        CL        UY        BR        AR 
## 31.944444 32.082414 43.805613 34.459459 16.544118  8.552632 23.862069 13.795620 
##        DO        HT        JA        GU 
## 25.495959 44.042553 30.583215       NaN

Other way is to ude the library plyr and dplyr that include the command ddply. This command requires a definition of a dataframe “lapop21”, the grouping variable “paises”, and then the functions to calculate in each group, “mean” and “sd”.

library(plyr)
library(dplyr)
ddply(lapop21, "paises", summarise, mean=mean(jc15ar, na.rm=T), sd=sd(jc15ar, na.rm=T))

As we observe in the table, there is no data for Costa Rica, nor Guyana. With the standard deviation, we can calculate the lower and upper limits of the confidence interval.

We can do this directly with the library Rmisc. This library has the command group.CI that calculates the mean, the upper limit and the lower limit of a variable by groups of other variable. This table is saved in an object “coup”. This command does not include rows of countries with no data, so there are no rows for Costa Rica and Guyana.

library(Rmisc)
coup = group.CI(jc15ar~paises, lapop21)
coup

With this table, we can replicate Figure 1.7 with the library ggplot. In a previous section, we produce a bar graph by country, specifying variables in axis with aes and using geom_bar(…). Now, we want to add confidence intervals. For this, we add a new layer with the specification geom_errorbar(…). This specification requires a new aes where we have to specify a “ymin” and a “ymax” of the confidence interval. The table “coup” has the information for “ymin” in the column “jc15ar.lower” and the information for “ymax” in the column “jc15ar.upper”.

We also have options like width to specify the width of the whiskers of the error bars, color to specify the color of error bars, cex to specify the width of lines and linetype to specify the type of line, in this case dashed lines.

library(ggplot2)
fig1.7 = ggplot(coup, aes(x=reorder(paises, -jc15ar.mean), y=jc15ar.mean))+
  geom_bar(width=0.5, fill="darkslategray3", colour="#69b3a2", stat="identity")+
  geom_errorbar(aes(ymin=jc15ar.lower, ymax=jc15ar.upper), width=0.4, 
                color="darkcyan", cex=0.4, linetype=3)+
  geom_text(aes(label=paste(round(jc15ar.mean, 1), "%")), vjust=-4.4, size=2.5)+
  xlab("Country") + ylab("Tolerance to executive coups (%)")+
  ylim(0, 60)
fig1.7

These results, however, are not equal to those presented in Figure 1.7. This is due to the fact that these calculations do not include survey weights. Below, we will show how to include survey weights in calculations to replicate this figure.

Describing of satisfaction with democracy

Figure 3.9 presents the percentage of respondents who are satisfied with democracy by type of social network user.

The variable satisfaction with democracy is called “pn4” and is coded as follows:

  1. Very satisfied
  2. Satisfied
  3. Dissatisfied
  4. Very dissatisfied

Footnote 21 indicates that “Interviewees who select (1) or (2) are coded as satisfied with democracy.” Therefore, this variable has to be recoded. In this case, the command recode is used and tabulated, via table, to verify the recoding.

library(car)
table(lapop18$pn4)
## 
##     1     2     3     4 
##  1727  8916 12455  3855
lapop18$pn4rr = car::recode(lapop18$pn4, "1:2=100; 3:4=0")
table(lapop18$pn4rr)
## 
##     0   100 
## 16310 10643

The new variable “pn4rr” is a dummy variable. In this type of variables, the mean corresponds to the proportion of responses of 100. That is, if we calculate the mean of this variable, we are calculating the percentage for all the interviewees. In this section we will treat this variable as if it were a numeric variable. Strictly speaking, it is a nominal categorical variable. The calculations of standard deviations and then of confidence intervals, therefore, are referential.

summary(lapop18$pn4rr)
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max.    NA's 
##    0.00    0.00    0.00   39.49  100.00  100.00    1089

These results show an average of 39.5, that is, 39.5% of those interviewed are satisfied with democracy. We can also calculate the confidence interval for this variable in several ways. A first way is by performing a one-sample t-test, using the command t.test. Other way is using the command ciMean from the library lsr.

t.test(lapop18$pn4rr)
## 
##  One Sample t-test
## 
## data:  lapop18$pn4rr
## t = 132.62, df = 26952, p-value < 2.2e-16
## alternative hypothesis: true mean is not equal to 0
## 95 percent confidence interval:
##  38.90364 40.07087
## sample estimates:
## mean of x 
##  39.48726
library(lsr)
ciMean(lapop18$pn4rr, na.rm=T)
##          2.5%    97.5%
## [1,] 38.90364 40.07087

These results indicate that the 95% confidence interval of the mean for satisfaction with democracy varies between 38.9% and 40.1% . We could change this default value to 99% confidence by adding the specification conf = 0.99 to the command ciMean.

Satisfaction with democracy by groups of consumption of information in social networks

The 2018/19 report uses a variable that measures “frequent exposure to political information.” This variable is constructed in a complex way, based on the 3 social networks. In this case we are going to start with a simpler recoding to recreate the confidence intervals of the variable “satisfaction with democracy” by groups of consumption of information in each social network. Later the variable used in the report will be replicated. The frequency of information consumption (variables “smedia2” for Facebook, “smedia5” for Twitter and “smedia8” for WhatsApp) of each social network is measured on the following scale:

  1. Daily
  2. A few times a week
  3. A few times a month
  4. A few times a year
  5. Never

We are going to recode these variables in such a way that those who respond daily or a few times a week will be classified as “high use”, those who respond from 3 to 4 will be classified as “low use” and those who respond “never”. they will be classified as “non-users”. A similar classification scheme is used to define the users of the 3 social networks. The new recoded variables are converted to a factor and labeled.

table(lapop18$smedia2)
## 
##    1    2    3    4    5 
## 8633 4927 1286  282  231
table(lapop18$smedia5)
## 
##   1   2   3   4   5 
## 795 728 422 193 220
table(lapop18$smedia8)
## 
##     1     2     3     4     5 
## 14151  2646   495    50    87
lapop18$smedia2r = car::recode(lapop18$smedia2, "1:2=1; 3:4=2; 5=3")
lapop18$smedia5r = car::recode(lapop18$smedia5, "1:2=1; 3:4=2; 5=3")
lapop18$smedia8r = car::recode(lapop18$smedia8, "1:2=1; 3:4=2; 5=3")
lapop18$smedia2r = as.factor(lapop18$smedia2r)
lapop18$smedia5r = as.factor(lapop18$smedia5r)
lapop18$smedia8r = as.factor(lapop18$smedia8r)
levels(lapop18$smedia2r) = c("High use", "Low use", "Non user")
levels(lapop18$smedia5r) = c("High use", "Low use", "Non user")
levels(lapop18$smedia8r) = c("High use", "Low use", "Non user")
table(lapop18$smedia2r)
## 
## High use  Low use Non user 
##    13560     1568      231
table(lapop18$smedia5r)
## 
## High use  Low use Non user 
##     1523      615      220
table(lapop18$smedia8r)
## 
## High use  Low use Non user 
##    16797      545       87

With these recoded variables, it is possible to calculate the mean (which are the percentages) of satisfaction with democracy for each group of information consumption in social networks. This can be done in multiple ways. If you want to compare the means, you can use the command tapply.

tapply(lapop18$pn4rr, lapop18$smedia2r, mean, na.rm=T) #Facebook
## High use  Low use Non user 
## 37.55182 37.94466 40.74074
tapply(lapop18$pn4rr, lapop18$smedia5r, mean, na.rm=T) #Twitter
## High use  Low use Non user 
## 39.66777 37.37542 41.78404
tapply(lapop18$pn4rr, lapop18$smedia8r, mean, na.rm=T) #Whatsapp
## High use  Low use Non user 
## 37.39093 38.92100 43.37349

Other option that can display both the mean and the standard deviation is through the library plyr and the command ddply. The code for Facebook would be:

library(plyr)
ddply(lapop18, "smedia2r", summarise, mean=mean(pn4rr, na.rm=T), sd=sd(pn4rr, na.rm=T))

It is important to note that in this case we have not indicated that internally we do not work with missing values (using the specification filter(!is.na(wa_user))), so the table above presents a row of NA, observations with no information of using of the social network, where the average and the standard deviation of the variable satisfaction with democracy are calculated. Finally, an option that allows you to display many statistics for each group is describeBy from the library psych. The code for Twitter is:

library(psych)
describeBy(lapop18$pn4rr, group=lapop18$smedia5r)
## 
##  Descriptive statistics by group 
## group: High use
##    vars    n  mean    sd median trimmed mad min max range skew kurtosis   se
## X1    1 1505 39.67 48.94      0    37.1   0   0 100   100 0.42    -1.82 1.26
## ------------------------------------------------------------ 
## group: Low use
##    vars   n  mean    sd median trimmed mad min max range skew kurtosis   se
## X1    1 602 37.38 48.42      0   34.23   0   0 100   100 0.52    -1.73 1.97
## ------------------------------------------------------------ 
## group: Non user
##    vars   n  mean    sd median trimmed mad min max range skew kurtosis   se
## X1    1 213 41.78 49.44      0   39.77   0   0 100   100 0.33     -1.9 3.39

However, what interests us is to calculate the confidence intervals for each group. Figure 3.9 of the report presents the mean of satisfaction with democracy, shown as a point, and the confidence intervals for each group, shown as a gray area with lower and upper limits. The library Rmisc and the command group.CI can be used to calculate the confidence intervals of the variable satisfaction with democracy by groups of information consumption on Facebook.

library(Rmisc)
group.CI(pn4rr~smedia2r, lapop18)

With these data, for example, the average satisfaction with democracy among the group with high use of information on Facebook is 37.6%. The lower limit of the confidence interval is 36.7% and the upper limit is 38.4%. With these data, a bar chart similar to 3.9 could be replicated.

Confidence Intervals for satisfaction with democracy by groups of Twitter users

The easiest way to plot confidence intervals by groups is to use the command plotmeans.

library(gplots)
plotmeans(lapop18$pn4rr~lapop18$smedia5r,
          xlab="Type of Twitter user",
          ylab="Satisfaction with democracy",
          ylim=c(0, 50),
          mean.labels=T, digits=1,
          connect=F
         )

This option displays the confidence intervals but is difficult if you want to plot the bars. The library ggplot gives us more options and allows us to plot in a similar way to Figure 3.9 of the report. For this, a “tw.use” dataframe is first saved with the data of the mean and the upper and lower limits of each group, using the command group.CI. It is the data from this dataframe that is used with ggplot and a graph is created which is saved in a “graf1” object. With this library, the layer geom_bar() is added to define that you want a bar graph of the variables specified in aes. Then the layer geom_errorbar() is added to add the error bars and then the mean values with geom_text(). Finally, the X and Y axis are labeled with xlab and ylab and the limits of the Y axis are defined with ylim.

tw.use <- group.CI(pn4rr~smedia5r, lapop18)
library(ggplot2)
graf1 <- ggplot(tw.use, aes(x=smedia5r, y=pn4rr.mean))+
  geom_bar(width=0.5, fill="darkcyan", colour="black", stat="identity")+
  geom_errorbar(aes(ymin=pn4rr.lower, ymax=pn4rr.upper), width=0.2)+
  geom_text(aes(label=paste(round(pn4rr.mean, 1), "%")), vjust=-4.2, size=4)+
  xlab("Type of Twitter user") + ylab("Satisfaction with democracy (%)")+
  ylim(0, 50)
graf1

According to these results, satisfaction with democracy is higher in non-Twitter users, compared to users, although the differences are not statistically significant from a visual comparison between confidence intervals.

Satisfaction with democracy by groups of type of user of social networks

So far, confidence intervals of satisfaction with democracy have been created by type of Twitter user. The report aggregates the users of the three social networks to identify three types of users: high-users, low-users, and non-users of any social network. The way of recoding this type of user of three social networks is based on several conditions. As the report says: “We use the same coding as in the previous section, to distinguish between those who frequentle use social media (those with accounts that they access a few times a week or daily) and those who do not use social networks frequently (those with accounts that they access a few times a month or a few times a year). We also include non-users: those who do not have any social network accounts (those who indicate that they do not have an account on Facebook, Twitter or Whatsapp) and those who have an account, but never use it” (p.81). We first identify those who use each social network a few times a week or daily as 1 and if they use each social network a few times a month or a few times a year, as 0. For this we use the command ifelse. Then, we add the values of each social network in a single variable, with values between 0 and 3. The command rowSums is used, which allows the horizontal sum of defined variables, in this case those at position [, 89:91]. In this command, we use the specification na.rm=T so that the sum does not take missing values into account.

lapop18$sm2 = ifelse(lapop18$smedia2==1 | lapop18$smedia2==2, 1, 0)
lapop18$sm5 = ifelse(lapop18$smedia5==1 | lapop18$smedia5==2, 1, 0)
lapop18$sm8 = ifelse(lapop18$smedia8==1 | lapop18$smedia8==2, 1, 0)
lapop18$anyhi = rowSums(lapop18[,89:91], na.rm=T)
table(lapop18$anyhi)
## 
##     0     1     2     3 
##  9831  5811 11131  1269

Starting from this variable, a variable is created that aggregates the three social networks, called “hi_lo_non”. First, this variable is created as a vector of NAs. Values of 1, 2, 3 or NA are then imputed to it, depending on the values of “anyhi” or the values of the social network variables. A new variable of type factor is then created, with identical values as “hi_lo_non” and is labeled. The definition of the conditionality is worked through the square brackets [...]. In this way, the conditions are defined as follows:

  • The variable “hi_lo_non is equal to 1 if the variable anyhi is greater than or equal to 1 (use daily or a few times a week) = lapop18$hi_lo_non[lapop18$anyhi>=1] = 1

  • The variable “hi_lo_non is equal to 2 if the variable anyhi is equal to 0 (use a few times a year or never) = lapop18$hi_lo_non[lapop18$anyhi==0] = 2

  • The variable “hi_lo_non is equal to 3 if the variables of account holding are equal to 2 (No) = lapop18$hi_lo_non[lapop18$smedia1==2 & lapop18$smedia4==2 & lapop18$smedia7==2] = 3

The following coding rules follow the same logic of combining other variables to impute the value 3 or NA.

lapop18$hi_lo_non = NA #create a vector with NAs#
lapop18$hi_lo_non[lapop18$anyhi>=1] = 1 #1 is coded for those who use a social network daily or a few times a week.#
lapop18$hi_lo_non[lapop18$anyhi==0] = 2 #Those who use a social network a few times a month and a year are coded as 2#
lapop18$hi_lo_non[lapop18$smedia1==2 & lapop18$smedia4==2 & lapop18$smedia7==2] = 3 #Those who do not have social networks are coded as 3#
lapop18$hi_lo_non[lapop18$smedia2==5 & lapop18$smedia5==5 & lapop18$smedia8==5] = 3 #Those who never use any social network are coded as 3#
lapop18$hi_lo_non[lapop18$pais==3 & (lapop18$smedia2==5 | lapop18$smedia5==5 | lapop18$smedia8==5)] = 3 #A particular code is applied to country 3#
lapop18$hi_lo_non[lapop18$pais==3 & (lapop18$smedia1==2 | lapop18$smedia4==2 | lapop18$smedia7==2)] = 3 #A particular code is applied to country 3#

lapop18$hilon = as.factor(lapop18$hi_lo_non)
levels(lapop18$hilon) = c("High use", "Low use", "Non user")
prop.table(table(lapop18$hilon))*100
## 
##  High use   Low use  Non user 
## 64.941873  3.480494 31.577634

According to these data, 64.9% of those interviewed report a high use of social networks, while, at the other extreme, there are 31.6% who do not use any social network. These data differ slightly from those reported in the Appendix to the report, available here, where 65.34% of high use and 31.60% of non-users are reported. These differences may be due to differences in the interpretation of the coding rules from Stata to R.

In the same way that the graph of average satisfaction with democracy by type of Twitter user was produced using ggplot, now the same will be done but for the users of the three social networks, variable “hilon”.

library(Rmisc)
satis.use = group.CI(pn4rr~hilon, lapop18)
library(ggplot2)
fig3.9 = ggplot(satis.use, aes(x=hilon, y=pn4rr.mean))+
  geom_bar(width=0.5, fill="darkcyan", colour="black", stat="identity")+
  geom_errorbar(aes(ymin=pn4rr.lower, ymax=pn4rr.upper), width=0.2)+
  geom_text(aes(label=paste(round(pn4rr.mean, 1), "%")), vjust=-2.5, size=4)+
  xlab("Type of social network user") + ylab("Satisfaction with democracy (%)")+
  ylim(0, 50)
fig3.9

This graph would be a replication of the one presented in the report (Figure 3.9 on page 62), with minor differences due to the encoding of the resulting data.

Summary

In this section we have worked with a recoded dummy variable (satisfaction with democracy), which can be used as a numerical variable for calculating confidence intervals of proportions. With this variable, the confidence interval of the mean has been calculated, which would be that of the proportion of respondents who are satisfied with democracy. Then, these variables have been described by groups of a factor variable (consumption of political information). It has been presented how to calculate the confidence intervals of the numerical variable by groups of the factor variable. Finally, it has been presented how to plot the confidence intervals by groups.

Calculations including survey weights

Other way to calculate the confidence interval, including the survey weight, is by using the library survey and the command confint along with the native command svymean.

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

In the same way as in the previous section, the satisfaction with democracy variable can be described by incorporating survey weights using the command svymean.

svymean(~pn4rr, design18, na.rm=T)
##         mean     SE
## pn4rr 39.459 0.3317

To calculate the confidence interval, the above code has to be nested inside the command confint. This command calculates the 95% confidence interval by default. You could change this default value to 99% confidence by adding the conf = 0.99 specification to the command.

confint(svymean(~pn4rr, design18, na.rm=T))
##          2.5 %   97.5 %
## pn4rr 38.80884 40.10901

The mean and confidence interval of satisfaction with democracy can also be calculated incorporating the survey weight using the command svyby. Within this command, the numerical variable to be described (~pn4rr), the variable that forms the groups (~smedia5r), the sample design (design18), the function to be calculated ( svymean), that does not take into account missing values (na.rm=T) and the confidence interval of each group (vartype="ci") are defined.

tw.uso.weighted <- svyby(~pn4rr, ~smedia5r, design18, svymean, na.rm=T, vartype = "ci")
tw.uso.weighted

To be able to plot, these calculations are saved in a “tw.uso.weighted” dataframe, which includes the mean data for each group and the lower and upper limit of the confidence interval. In the same way as with data that does not include the survey effect, the library ggplot is used and a plot is created which is saved in a “graf2” object. Very similar specifications to the previous examples are used.

graf2 <- ggplot(tw.uso.weighted, aes(x=smedia5r, y=pn4rr))+
  geom_bar(width=0.5, fill="darkcyan", colour="black", stat="identity")+
  geom_errorbar(aes(ymin=ci_l, ymax=ci_u), width=0.2)+
  geom_text(aes(label=paste(round(pn4rr, 1), "%")), vjust=-4.2, size=4)+
  xlab("Twitter user type") + ylab("Satisfaction with democracy (%)")+
  ylim(0, 50)
graf2

LS0tCnRpdGxlOiAiQ29uZmlkZW5jZSBpbnRlcnZhbHMgdXNpbmcgdGhlIEFtZXJpY2FzIEJhcm9tZXRlciIKb3V0cHV0OgogIGh0bWxfZG9jdW1lbnQ6CiAgICB0b2M6IHRydWUKICAgIHRvY19mbG9hdDogdHJ1ZQogICAgY29sbGFwc2VkOiBmYWxzZQogICAgbnVtYmVyX3NlY3Rpb25zOiBmYWxzZQogICAgdG9jX2RlcHRoOiAxCiAgICBjb2RlX2Rvd25sb2FkOiB0cnVlCiAgICB0aGVtZTogZmxhdGx5CiAgICBkZl9wcmludDogcGFnZWQKICAgIHNlbGZfY29udGFpbmVkOiBubwogICAga2VlcF9tZDogeWVzCmVkaXRvcl9vcHRpb25zOiAKICBtYXJrZG93bjogCiAgICB3cmFwOiBzZW50ZW5jZQotLS0KCmBgYHtyIHNldHVwLCBpbmNsdWRlPUZBTFNFfQprbml0cjo6b3B0c19jaHVuayRzZXQobWVzc2FnZT1GQUxTRSx3YXJuaW5nPUZBTFNFLCBjYWNoZT1UUlVFKQpgYGAKCmBgYHtjc3MgY29sb3IsIGVjaG89RkFMU0V9Ci5jb2x1bW5zIHtkaXNwbGF5OiBmbGV4O30KaDEge2NvbG9yOiAjMzM2NkNDO30KYGBgCgojIEludHJvZHVjdGlvbgoKSW4gdGhpcyBzZWN0aW9uIHdlIHdpbGwgc2VlIGhvdyB0byBjb25zdHJ1Y3QgY29uZmlkZW5jZSBpbnRlcnZhbHMgb2YgdGhlIG1lYW4gdXNpbmcgdGhlIGRhdGEgZnJvbSB0aGUgQW1lcmljYXNCYXJvbWV0ZXIuCkZvciB0aGF0LCB3ZSB3aWxsIHVzZSB0aGUgMjAyMSByZWdpb25hbCByZXBvcnQgIlRoZSBQdWxzZSBvZiBEZW1vY3JhY3kiLCBhdmFpbGFibGUgW2hlcmVdKGh0dHBzOi8vd3d3LnZhbmRlcmJpbHQuZWR1L2xhcG9wL2FiMjAyMS8yMDIxX0xBUE9QX0FtZXJpY2FzQmFyb21ldGVyXzIwMjFfUHVsc2Vfb2ZfRGVtb2NyYWN5LnBkZikgYW5kIHRoZSAyMDE4LzE5IHJlcG9ydCwgYXZhaWxhYmxlIFtoZXJlXShodHRwczovL3d3dy52YW5kZXJiaWx0LmVkdS9sYXBvcC9hYjIwMTgvMjAxOC0xOV9BbWVyaWNhc0Jhcm9tZXRlcl9SZWdpb25hbF9SZXBvcnRfU3BhbmlzaF9XXzAzLjI3LjIwLnBkZikuClRoZSAyMDIxIHJvdW5kIHJlcG9ydHMgZGF0YSBvbiBleGVjdXRpdmUgY291cHMuCkZpZ3VyZSAxLjcgc2hvd3MgdGhlIHBlcmNlbnRhZ2Ugb2YgY2l0aXplbnMgdGhhdCB0b2xlcmF0ZXMgYW4gZXhlY3V0aXZlIGNvdXAgYnkgY291bnRyeS4KSW4gYm90aCBjYXNlcywgcmVzdWx0cyBpbmNsdWRlIGRlc2NyaXB0aXZlIGVzdGltYXRvcnMgYW5kIGNvbmZpZGVuY2UgaW50ZXJ2YWxzLgpUaGUgMjAxOC8xOSByb3VuZCBvZiB0aGUgQW1lcmljYXNCYXJvbWV0ZXIgcmVwb3J0cyBkYXRhIG9uIHNvY2lhbCBuZXR3b3JrcyBhbmQgcG9saXRpY2FsIGF0dGl0dWRlcy4KSW4gcGFydGljdWxhciwgRmlndXJlIDMuOSByZXBvcnRzIHRoZSBkZWdyZWUgb2Ygc2F0aXNmYWN0aW9uIHdpdGggZGVtb2NyYWN5IGJ5IHR5cGUgb2YgdXNlciBvZiBzb2NpYWwgbmV0d29ya3MuCgojIEFib3V0IHRoZSBkYXRhc2V0CgpUaGUgZGF0YSB3ZSBhcmUgZ29pbmcgdG8gdXNlIHNob3VsZCBiZSBjaXRlZCBhcyBmb2xsb3dzOiBTb3VyY2U6IEFtZXJpY2FzQmFyb21ldGVyIGJ5IHRoZSBMYXRpbiBBbWVyaWNhbiBQdWJsaWMgT3BpbmlvbiBQcm9qZWN0IChMQVBPUCksIHd3d3cuTGFwb3BTdXJ2ZXlzLm9yZy4KVGhpcyBkb2N1bWVudCBsb2FkcyBhIHRyaW1tZWQgZGF0YWJhc2UuClRoaXMgZGF0YWJhc2UgaXMgaG9zdGVkIGluIHRoZSAibWF0ZXJpYWxzX2VkdSIgcmVwb3NpdG9yeSBvZiB0aGUgTEFQT1AgYWNjb3VudCBvbiBHaXRIdWIuCkl0IGlzIHJlY29tbWVuZGVkIHRvIGNsZWFuIHRoZSBFbnZpcm9ubWVudCBiZWZvcmUgcHJvY2VlZGluZyB3aXRoIHRoaXMgc2VjdGlvbi4KClVzaW5nIHRoZSBsaWJyYXJ5IGByaW9gIGFuZCB0aGUgY29tbWFuZCBgaW1wb3J0YCwgd2UgY2FuIGltcG9ydCB0aGlzIGRhdGFiYXNlIGZyb20gdGhpcyByZXBvc2l0b3J5LgpJbiBhZGRpdGlvbiwgdGhlIGRhdGEgZnJvbSBjb3VudHJpZXMgd2l0aCBjb2RlcyBsZXNzIHRoYW4gb3IgZXF1YWwgdG8gMzUgYXJlIHNlbGVjdGVkLCB0aGF0IGlzLCB0aGUgb2JzZXJ2YXRpb25zIG9mIHRoZSBVbml0ZWQgU3RhdGVzIGFuZCBDYW5hZGEgYXJlIGVsaW1pbmF0ZWQuCgpgYGB7ciBiYXNlfQpsaWJyYXJ5KHJpbykKbGFwb3AxOCA9IGltcG9ydCgiaHR0cHM6Ly9yYXcuZ2l0aHViLmNvbS9sYXBvcC1jZW50cmFsL21hdGVyaWFsc19lZHUvbWFpbi9MQVBPUF9BQl9NZXJnZV8yMDE4X3YxLjAuc2F2IikKbGFwb3AxOCA9IHN1YnNldChsYXBvcDE4LCBwYWlzPD0zNSkKYGBgCgpXZSBhbHNvIHVwbG9hZCB0aGUgZGF0YXNldCBmb3IgdGhlIDIwMjEgcm91bmQuCgpgYGB7cn0KbGFwb3AyMSA9IGltcG9ydCgiaHR0cHM6Ly9yYXcuZ2l0aHViLmNvbS9sYXBvcC1jZW50cmFsL21hdGVyaWFsc19lZHUvbWFpbi9sYXBvcDIxLlJEYXRhIikKbGFwb3AyMSA9IHN1YnNldChsYXBvcDIxLCBwYWlzPD0zNSkKYGBgCgojIFRvbGVyYW5jZSB0byBleGVjdXRpdmUgY291cHMKCkZpZ3VyZSAxLjcgb2YgdGhlIHJlcG9ydCBUaGUgUHVsc2Ugb2YgRGVtb2NyYWN5IGZvciB0aGUgMjAyMSByb3VuZCBvZiB0aGUgQW1lcmljYXNCYXJvbWV0ZXIgc2hvd3MgdGhlIHJlc3VsdHMgb2YgdGhlIHBlcmNlbnRhZ2Ugb2YgY2l0aXplbnMgdGhhdCB0b2xlcmF0ZXMgYW4gZXhlY3V0aXZlIGNvdXAgYnkgY291bnRyeS4KVGhpcyBncmFwaCBhbHNvIGRpc3BsYXlzIHRoZSA5NSUgY29uZmlkZW5jZSBpbnRlcnZhbCBmb3IgZWFjaCBjb3VudHJ5LgoKIVtdKEZpZ3VyZTEuNy5wbmcpe3dpZHRoPSI1MjAifQoKVGhlIHZhcmlhYmxlIHVzZWQgaW4gdGhpcyBmaWd1cmUgaXMgImpjMTVhIi4KSXRzIHdvcmRpbmcgaXM6ICJEbyB5b3UgYmVsaWV2ZSB0aGF0IHdoZW4gdGhlIGNvdW50cnkgaXMgZmFjaW5nIHZlcnkgZGlmZmljdWx0IHRpbWVzLCBpdCBpcyBqdXN0aWZpYWJsZSBmb3IgdGhlIHByZXNpZGVudCBvZiB0aGUgY291bnRyeSB0byBjbG9zZSB0aGUgQ29uZ3Jlc3MgYW5kIGdvdmVybiB3aXRob3V0IENvbmdyZXNzPyIgVGhlIG9wdGlvbnMgYXJlOgoKMS4gIFllcywgaXQgaXMganVzdGlmaWVkCgoyLiAgTm8sIGl0IGlzIG5vdCBqdXN0aWZpZWQKCiMgRGVzY3JpYmluZyB0b2xlcmFuY2UgdG8gZXhlY3V0aXZlIGNvdXBzCgpUbyBjYWxjdWxhdGUgdGhlIHBlcmNlbnRhZ2Ugb2YgY2l0aXplbnMgdGhhdCBqdXN0aWZ5IG9yIHRvbGVyYXRlIGFuIGV4ZWN1dGl2ZSBjb3VwLCB3ZSBoYXZlIHRvIHJlY29kZSB0aGlzIHZhcmlhYmxlIGluIGEgd2F5IHRoYXQgdGhvc2Ugd2hvIGp1c3RpZnkgaGF2ZSBhIHZhbHVlIG9mIDEwMCBhbmQgdGhvc2Ugd2hvIGRvIG5vdCBqdXN0aWZ5IGhhdmUgYSB2YWx1ZSBvZiAwLgpJbiB0aGlzIGNhc2UsIHdlIHVzZSB0aGUgY29tbWFuZCBgcmVjb2RlYCBhbmQgd2UgdGFidWxhdGUgd2l0aCBgdGFibGVgIHRvIHZlcmlmeSB0aGUgcmVjb2RpZmljYXRpb24uCgpgYGB7cn0KbGFwb3AyMSRqYzE1YXIgPSBjYXI6OnJlY29kZShsYXBvcDIxJGpjMTVhLCAiMT0xMDA7IDI9MCIpCnRhYmxlKGxhcG9wMjEkamMxNWFyKQpgYGAKClRvIGNhbGN1bGF0ZSB0aGUgcGVyY2VudHNhZ2Ugb2YgY2l0aXplbnMgd2hvIHRvbGVyYXRlIGFuIGV4ZWN1dGl2ZSBjb3VwIHdlIGNhbiB1c2UgdGhlIGNvbW1hbmQgYHRhYmxlYCBhbmQgYHByb3AudGFibGVgLgpUaGUgbmV3IHZhcmlhYmxlICJqYzE1YXIiIGlzIGEgZHVtbXkgdmFyaWFibGUuCldpdGggdGhpcyB0eXBlIG9mIHZhcmlhYmxlLCB0aGUgbWVhbiBpcyB0aGUgcHJvcG9ydGlvbiBvZiByZXNwb25zZXMgd2l0aCAxMDAuCkl0IG1lYW5zIHRoYXQgaWYgd2UgY2FsY3VsYXRlIHRoZSBtZWFuIG9mIHRoaXMgdmFyaWFibGUsIHRoZSByZXN1bHRzIGlzIHRoZSBwZXJjZW50YWdlIGZvciBhbGwgcmVzcG9uZGVudHMuCkluIHRoaXMgc2VjdGlvbiB3ZSBwcm9jZWVkIGFzIHRoaXMgdmFyaWFibGUgaXMgbnVtZXJpYy4KSW4gc3RyaWN0IHNlbnNlLCB0aGlzIGlzIGEgY2F0ZWdvcmljYWwgbm9taW5hbCB2YXJpYWJsZS4KVGhlIGNhbGN1bGF0aW9uIG9mIHN0YW5kYXJkIGRldmlhdGlvbnMgYW5kIGNvbmZpZGVuY2UgaW50ZXJ2YWxzIGFyZSB0aGVuIHJlZmVyZW50aWFsLgoKVGhlIHJlc3VsdCBpbmRpY2F0ZXMgdGhhdCB0aGUgcGVyY2VudGFnZSBvZiBjaXRpemVucyB0aGF0IHRvbGVyYXRlcyBhbiBleGVjdXRpdmUgY291cCBpcyAyOC43JSBmb3IgdGhlIHdob2xlIHNhbXBsZS4KCmBgYHtyfQpzdW1tYXJ5KGxhcG9wMjEkamMxNWFyKQpgYGAKCiMgQ29uZmlkZW5jZSBpbnRlcnZhbHMgZm9yIHRvbGVyYW5jZSB0byBleGVjdXRpdmUgY291cHMKClRvIGNhbGN1bGF0ZSB0aGUgOTUlIGNvbmZpZGVuY2UgaW50ZXJ2YWwgb2YgdGhpcyBwZXJjZW50YWdlLCB3ZSBjYW4gdXNlIHRoZSBjb21tYW5kIGB0LnRlc3RgIG9yIHRoZSBsaWJyYXJ5IGBsc3JgIHRoYXQgaGFzIHRoZSBjb21tYW5kIGBjaU1lYW5gLgoKYGBge3J9CnQudGVzdChsYXBvcDIxJGpjMTVhcikKbGlicmFyeShsc3IpCmNpTWVhbihhcy5udW1lcmljKGxhcG9wMjEkamMxNWFyKSwgbmEucm0gPSBUKQpgYGAKCiMgVG9sZXJhbmNlIHRvIGV4ZWN1dGl2ZSBjb3VwcyBieSBjb3VudHJ5CgpGaWd1cmUgMS43IHNob3dzIHRoZSBwZXJjZW50YWdlIG9mIGNpdGl6ZW5zIHRoYXQgdG9sZXJhdGVzIGFuIGV4ZWN1dGl2ZSBjb3VwIGJ5IGNvdW50cnkgVG8gcmVwbGljYXRlIHRoaXMgcmVzdWx0cywgd2UgaGF2ZSB0byBkZWZpbmUgdGhlIHZhcmlhYmxlICJwYWlzIiBhcyBmYWN0b3IuCldlIHNhdmVkIHRoaXMgY2hhbmdlIGluIGEgbmV3IHZhcmlhYmxlICJwYWlzZXMiIHRoYXQgd2UgbGFiZWwgd2l0aCB0aGUgaW5pdGlhbHMgb2YgZWFjaCBjb3VudHJ5LgoKYGBge3J9CmxhcG9wMjEkcGFpc2VzID0gYXMuZmFjdG9yKGxhcG9wMjEkcGFpcykKbGV2ZWxzKGxhcG9wMjEkcGFpc2VzKSA8LSBjKCJNWCIsICJHVCIsICJTViIsICJITiIsICJOSSIsICJDUiIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAiUE4iLCAiQ08iLCAiRUMiLCAiQk8iLCAiUEUiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIlBZIiwgIkNMIiwgIlVZIiwgIkJSIiwgIkFSIiwgIkRPIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICJIVCIsICJKQSIsICJHVSIpCnRhYmxlKGxhcG9wMjEkcGFpc2VzKQpgYGAKClRvIGNhbGN1bGF0ZSB0aGVzZSBwZXJjZW50YWdlcyBieSBjb3VudHJ5LCB3ZSBjYW4gdXNlIHNldmVyYWwgYWx0ZXJuYXRpdmVzLgpGb3IgZXhhbXBsZSwgdGhlIGNvbW1hbmQgYHRhcHBseWAgYWxsb3dzIHRvIGNhbGN1bGF0ZSB0aGUgbWVhbiBvZiBhIHZhcmlhYmxlIGJ5IGdyb3VwcyBvZiBvdGhlciB2YXJpYWJsZS4KCmBgYHtyfQp0YXBwbHkobGFwb3AyMSRqYzE1YXIsIGxhcG9wMjEkcGFpc2VzLCBtZWFuLCBuYS5ybT1UKQpgYGAKCk90aGVyIHdheSBpcyB0byB1ZGUgdGhlIGxpYnJhcnkgYHBseXJgIGFuZCBgZHBseXJgIHRoYXQgaW5jbHVkZSB0aGUgY29tbWFuZCBgZGRwbHlgLgpUaGlzIGNvbW1hbmQgcmVxdWlyZXMgYSBkZWZpbml0aW9uIG9mIGEgZGF0YWZyYW1lICJsYXBvcDIxIiwgdGhlIGdyb3VwaW5nIHZhcmlhYmxlICJwYWlzZXMiLCBhbmQgdGhlbiB0aGUgZnVuY3Rpb25zIHRvIGNhbGN1bGF0ZSBpbiBlYWNoIGdyb3VwLCAibWVhbiIgYW5kICJzZCIuCgpgYGB7cn0KbGlicmFyeShwbHlyKQpsaWJyYXJ5KGRwbHlyKQpkZHBseShsYXBvcDIxLCAicGFpc2VzIiwgc3VtbWFyaXNlLCBtZWFuPW1lYW4oamMxNWFyLCBuYS5ybT1UKSwgc2Q9c2QoamMxNWFyLCBuYS5ybT1UKSkKYGBgCgpBcyB3ZSBvYnNlcnZlIGluIHRoZSB0YWJsZSwgdGhlcmUgaXMgbm8gZGF0YSBmb3IgQ29zdGEgUmljYSwgbm9yIEd1eWFuYS4KV2l0aCB0aGUgc3RhbmRhcmQgZGV2aWF0aW9uLCB3ZSBjYW4gY2FsY3VsYXRlIHRoZSBsb3dlciBhbmQgdXBwZXIgbGltaXRzIG9mIHRoZSBjb25maWRlbmNlIGludGVydmFsLgoKV2UgY2FuIGRvIHRoaXMgZGlyZWN0bHkgd2l0aCB0aGUgbGlicmFyeSBgUm1pc2NgLgpUaGlzIGxpYnJhcnkgaGFzIHRoZSBjb21tYW5kIGBncm91cC5DSWAgdGhhdCBjYWxjdWxhdGVzIHRoZSBtZWFuLCB0aGUgdXBwZXIgbGltaXQgYW5kIHRoZSBsb3dlciBsaW1pdCBvZiBhIHZhcmlhYmxlIGJ5IGdyb3VwcyBvZiBvdGhlciB2YXJpYWJsZS4KVGhpcyB0YWJsZSBpcyBzYXZlZCBpbiBhbiBvYmplY3QgImNvdXAiLgpUaGlzIGNvbW1hbmQgZG9lcyBub3QgaW5jbHVkZSByb3dzIG9mIGNvdW50cmllcyB3aXRoIG5vIGRhdGEsIHNvIHRoZXJlIGFyZSBubyByb3dzIGZvciBDb3N0YSBSaWNhIGFuZCBHdXlhbmEuCgpgYGB7cn0KbGlicmFyeShSbWlzYykKY291cCA9IGdyb3VwLkNJKGpjMTVhcn5wYWlzZXMsIGxhcG9wMjEpCmNvdXAKYGBgCgpXaXRoIHRoaXMgdGFibGUsIHdlIGNhbiByZXBsaWNhdGUgRmlndXJlIDEuNyB3aXRoIHRoZSBsaWJyYXJ5IGBnZ3Bsb3RgLgpJbiBhIHByZXZpb3VzIHNlY3Rpb24sIHdlIHByb2R1Y2UgYSBiYXIgZ3JhcGggYnkgY291bnRyeSwgc3BlY2lmeWluZyB2YXJpYWJsZXMgaW4gYXhpcyB3aXRoIGBhZXNgIGFuZCB1c2luZyBgZ2VvbV9iYXIo4oCmKWAuCk5vdywgd2Ugd2FudCB0byBhZGQgY29uZmlkZW5jZSBpbnRlcnZhbHMuCkZvciB0aGlzLCB3ZSBhZGQgYSBuZXcgbGF5ZXIgd2l0aCB0aGUgc3BlY2lmaWNhdGlvbiBgZ2VvbV9lcnJvcmJhcijigKYpYC4KVGhpcyBzcGVjaWZpY2F0aW9uIHJlcXVpcmVzIGEgbmV3IGBhZXNgIHdoZXJlIHdlIGhhdmUgdG8gc3BlY2lmeSBhICJ5bWluIiBhbmQgYSAieW1heCIgb2YgdGhlIGNvbmZpZGVuY2UgaW50ZXJ2YWwuClRoZSB0YWJsZSAiY291cCIgaGFzIHRoZSBpbmZvcm1hdGlvbiBmb3IgInltaW4iIGluIHRoZSBjb2x1bW4gImpjMTVhci5sb3dlciIgYW5kIHRoZSBpbmZvcm1hdGlvbiBmb3IgInltYXgiIGluIHRoZSBjb2x1bW4gImpjMTVhci51cHBlciIuCgpXZSBhbHNvIGhhdmUgb3B0aW9ucyBsaWtlIGB3aWR0aGAgdG8gc3BlY2lmeSB0aGUgd2lkdGggb2YgdGhlIHdoaXNrZXJzIG9mIHRoZSBlcnJvciBiYXJzLCBgY29sb3JgIHRvIHNwZWNpZnkgdGhlIGNvbG9yIG9mIGVycm9yIGJhcnMsIGBjZXhgIHRvIHNwZWNpZnkgdGhlIHdpZHRoIG9mIGxpbmVzIGFuZCBgbGluZXR5cGVgIHRvIHNwZWNpZnkgdGhlIHR5cGUgb2YgbGluZSwgaW4gdGhpcyBjYXNlIGRhc2hlZCBsaW5lcy4KCmBgYHtyfQpsaWJyYXJ5KGdncGxvdDIpCmZpZzEuNyA9IGdncGxvdChjb3VwLCBhZXMoeD1yZW9yZGVyKHBhaXNlcywgLWpjMTVhci5tZWFuKSwgeT1qYzE1YXIubWVhbikpKwogIGdlb21fYmFyKHdpZHRoPTAuNSwgZmlsbD0iZGFya3NsYXRlZ3JheTMiLCBjb2xvdXI9IiM2OWIzYTIiLCBzdGF0PSJpZGVudGl0eSIpKwogIGdlb21fZXJyb3JiYXIoYWVzKHltaW49amMxNWFyLmxvd2VyLCB5bWF4PWpjMTVhci51cHBlciksIHdpZHRoPTAuNCwgCiAgICAgICAgICAgICAgICBjb2xvcj0iZGFya2N5YW4iLCBjZXg9MC40LCBsaW5ldHlwZT0zKSsKICBnZW9tX3RleHQoYWVzKGxhYmVsPXBhc3RlKHJvdW5kKGpjMTVhci5tZWFuLCAxKSwgIiUiKSksIHZqdXN0PS00LjQsIHNpemU9Mi41KSsKICB4bGFiKCJDb3VudHJ5IikgKyB5bGFiKCJUb2xlcmFuY2UgdG8gZXhlY3V0aXZlIGNvdXBzICglKSIpKwogIHlsaW0oMCwgNjApCmZpZzEuNwpgYGAKClRoZXNlIHJlc3VsdHMsIGhvd2V2ZXIsIGFyZSBub3QgZXF1YWwgdG8gdGhvc2UgcHJlc2VudGVkIGluIEZpZ3VyZSAxLjcuClRoaXMgaXMgZHVlIHRvIHRoZSBmYWN0IHRoYXQgdGhlc2UgY2FsY3VsYXRpb25zIGRvIG5vdCBpbmNsdWRlIHN1cnZleSB3ZWlnaHRzLgpCZWxvdywgd2Ugd2lsbCBzaG93IGhvdyB0byBpbmNsdWRlIHN1cnZleSB3ZWlnaHRzIGluIGNhbGN1bGF0aW9ucyB0byByZXBsaWNhdGUgdGhpcyBmaWd1cmUuCgojIERlc2NyaWJpbmcgb2Ygc2F0aXNmYWN0aW9uIHdpdGggZGVtb2NyYWN5CgpGaWd1cmUgMy45IHByZXNlbnRzIHRoZSBwZXJjZW50YWdlIG9mIHJlc3BvbmRlbnRzIHdobyBhcmUgc2F0aXNmaWVkIHdpdGggZGVtb2NyYWN5IGJ5IHR5cGUgb2Ygc29jaWFsIG5ldHdvcmsgdXNlci4KCiFbXShGaWd1cmUzLjkuSlBHKXt3aWR0aD0iNDM2In0KClRoZSB2YXJpYWJsZSBzYXRpc2ZhY3Rpb24gd2l0aCBkZW1vY3JhY3kgaXMgY2FsbGVkICJwbjQiIGFuZCBpcyBjb2RlZCBhcyBmb2xsb3dzOgoKMS4gIFZlcnkgc2F0aXNmaWVkCjIuICBTYXRpc2ZpZWQKMy4gIERpc3NhdGlzZmllZAo0LiAgVmVyeSBkaXNzYXRpc2ZpZWQKCkZvb3Rub3RlIDIxIGluZGljYXRlcyB0aGF0ICJJbnRlcnZpZXdlZXMgd2hvIHNlbGVjdCAoMSkgb3IgKDIpIGFyZSBjb2RlZCBhcyBzYXRpc2ZpZWQgd2l0aCBkZW1vY3JhY3kuIiBUaGVyZWZvcmUsIHRoaXMgdmFyaWFibGUgaGFzIHRvIGJlIHJlY29kZWQuCkluIHRoaXMgY2FzZSwgdGhlIGNvbW1hbmQgYHJlY29kZWAgaXMgdXNlZCBhbmQgdGFidWxhdGVkLCB2aWEgYHRhYmxlYCwgdG8gdmVyaWZ5IHRoZSByZWNvZGluZy4KCmBgYHtyIHJlY29kZSwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KbGlicmFyeShjYXIpCnRhYmxlKGxhcG9wMTgkcG40KQpsYXBvcDE4JHBuNHJyID0gY2FyOjpyZWNvZGUobGFwb3AxOCRwbjQsICIxOjI9MTAwOyAzOjQ9MCIpCnRhYmxlKGxhcG9wMTgkcG40cnIpCmBgYAoKVGhlIG5ldyB2YXJpYWJsZSAicG40cnIiIGlzIGEgZHVtbXkgdmFyaWFibGUuCkluIHRoaXMgdHlwZSBvZiB2YXJpYWJsZXMsIHRoZSBtZWFuIGNvcnJlc3BvbmRzIHRvIHRoZSBwcm9wb3J0aW9uIG9mIHJlc3BvbnNlcyBvZiAxMDAuClRoYXQgaXMsIGlmIHdlIGNhbGN1bGF0ZSB0aGUgbWVhbiBvZiB0aGlzIHZhcmlhYmxlLCB3ZSBhcmUgY2FsY3VsYXRpbmcgdGhlIHBlcmNlbnRhZ2UgZm9yIGFsbCB0aGUgaW50ZXJ2aWV3ZWVzLgpJbiB0aGlzIHNlY3Rpb24gd2Ugd2lsbCB0cmVhdCB0aGlzIHZhcmlhYmxlIGFzIGlmIGl0IHdlcmUgYSBudW1lcmljIHZhcmlhYmxlLgpTdHJpY3RseSBzcGVha2luZywgaXQgaXMgYSBub21pbmFsIGNhdGVnb3JpY2FsIHZhcmlhYmxlLgpUaGUgY2FsY3VsYXRpb25zIG9mIHN0YW5kYXJkIGRldmlhdGlvbnMgYW5kIHRoZW4gb2YgY29uZmlkZW5jZSBpbnRlcnZhbHMsIHRoZXJlZm9yZSwgYXJlIHJlZmVyZW50aWFsLgoKYGBge3IgZGVzY3JpYmV9CnN1bW1hcnkobGFwb3AxOCRwbjRycikKYGBgCgpUaGVzZSByZXN1bHRzIHNob3cgYW4gYXZlcmFnZSBvZiAzOS41LCB0aGF0IGlzLCAzOS41JSBvZiB0aG9zZSBpbnRlcnZpZXdlZCBhcmUgc2F0aXNmaWVkIHdpdGggZGVtb2NyYWN5LgpXZSBjYW4gYWxzbyBjYWxjdWxhdGUgdGhlIGNvbmZpZGVuY2UgaW50ZXJ2YWwgZm9yIHRoaXMgdmFyaWFibGUgaW4gc2V2ZXJhbCB3YXlzLgpBIGZpcnN0IHdheSBpcyBieSBwZXJmb3JtaW5nIGEgb25lLXNhbXBsZSB0LXRlc3QsIHVzaW5nIHRoZSBjb21tYW5kIGB0LnRlc3RgLgpPdGhlciB3YXkgaXMgdXNpbmcgdGhlIGNvbW1hbmQgYGNpTWVhbmAgZnJvbSB0aGUgbGlicmFyeSBgbHNyYC4KCmBgYHtyIElDfQp0LnRlc3QobGFwb3AxOCRwbjRycikKbGlicmFyeShsc3IpCmNpTWVhbihsYXBvcDE4JHBuNHJyLCBuYS5ybT1UKQpgYGAKClRoZXNlIHJlc3VsdHMgaW5kaWNhdGUgdGhhdCB0aGUgOTUlIGNvbmZpZGVuY2UgaW50ZXJ2YWwgb2YgdGhlIG1lYW4gZm9yIHNhdGlzZmFjdGlvbiB3aXRoIGRlbW9jcmFjeSB2YXJpZXMgYmV0d2VlbiAzOC45JSBhbmQgNDAuMSUgLgpXZSBjb3VsZCBjaGFuZ2UgdGhpcyBkZWZhdWx0IHZhbHVlIHRvIDk5JSBjb25maWRlbmNlIGJ5IGFkZGluZyB0aGUgc3BlY2lmaWNhdGlvbiBgY29uZiA9IDAuOTlgIHRvIHRoZSBjb21tYW5kIGBjaU1lYW5gLgoKIyBTYXRpc2ZhY3Rpb24gd2l0aCBkZW1vY3JhY3kgYnkgZ3JvdXBzIG9mIGNvbnN1bXB0aW9uIG9mIGluZm9ybWF0aW9uIGluIHNvY2lhbCBuZXR3b3JrcwoKVGhlIDIwMTgvMTkgcmVwb3J0IHVzZXMgYSB2YXJpYWJsZSB0aGF0IG1lYXN1cmVzICJmcmVxdWVudCBleHBvc3VyZSB0byBwb2xpdGljYWwgaW5mb3JtYXRpb24uIiBUaGlzIHZhcmlhYmxlIGlzIGNvbnN0cnVjdGVkIGluIGEgY29tcGxleCB3YXksIGJhc2VkIG9uIHRoZSAzIHNvY2lhbCBuZXR3b3Jrcy4KSW4gdGhpcyBjYXNlIHdlIGFyZSBnb2luZyB0byBzdGFydCB3aXRoIGEgc2ltcGxlciByZWNvZGluZyB0byByZWNyZWF0ZSB0aGUgY29uZmlkZW5jZSBpbnRlcnZhbHMgb2YgdGhlIHZhcmlhYmxlICJzYXRpc2ZhY3Rpb24gd2l0aCBkZW1vY3JhY3kiIGJ5IGdyb3VwcyBvZiBjb25zdW1wdGlvbiBvZiBpbmZvcm1hdGlvbiBpbiBlYWNoIHNvY2lhbCBuZXR3b3JrLgpMYXRlciB0aGUgdmFyaWFibGUgdXNlZCBpbiB0aGUgcmVwb3J0IHdpbGwgYmUgcmVwbGljYXRlZC4KVGhlIGZyZXF1ZW5jeSBvZiBpbmZvcm1hdGlvbiBjb25zdW1wdGlvbiAodmFyaWFibGVzICJzbWVkaWEyIiBmb3IgRmFjZWJvb2ssICJzbWVkaWE1IiBmb3IgVHdpdHRlciBhbmQgInNtZWRpYTgiIGZvciBXaGF0c0FwcCkgb2YgZWFjaCBzb2NpYWwgbmV0d29yayBpcyBtZWFzdXJlZCBvbiB0aGUgZm9sbG93aW5nIHNjYWxlOgoKMS4gIERhaWx5CjIuICBBIGZldyB0aW1lcyBhIHdlZWsKMy4gIEEgZmV3IHRpbWVzIGEgbW9udGgKNC4gIEEgZmV3IHRpbWVzIGEgeWVhcgo1LiAgTmV2ZXIKCldlIGFyZSBnb2luZyB0byByZWNvZGUgdGhlc2UgdmFyaWFibGVzIGluIHN1Y2ggYSB3YXkgdGhhdCB0aG9zZSB3aG8gcmVzcG9uZCBkYWlseSBvciBhIGZldyB0aW1lcyBhIHdlZWsgd2lsbCBiZSBjbGFzc2lmaWVkIGFzICJoaWdoIHVzZSIsIHRob3NlIHdobyByZXNwb25kIGZyb20gMyB0byA0IHdpbGwgYmUgY2xhc3NpZmllZCBhcyAibG93IHVzZSIgYW5kIHRob3NlIHdobyByZXNwb25kICJuZXZlciIuCnRoZXkgd2lsbCBiZSBjbGFzc2lmaWVkIGFzICJub24tdXNlcnMiLgpBIHNpbWlsYXIgY2xhc3NpZmljYXRpb24gc2NoZW1lIGlzIHVzZWQgdG8gZGVmaW5lIHRoZSB1c2VycyBvZiB0aGUgMyBzb2NpYWwgbmV0d29ya3MuClRoZSBuZXcgcmVjb2RlZCB2YXJpYWJsZXMgYXJlIGNvbnZlcnRlZCB0byBhIGZhY3RvciBhbmQgbGFiZWxlZC4KCmBgYHtyIHJlY29kaW5nfQp0YWJsZShsYXBvcDE4JHNtZWRpYTIpCnRhYmxlKGxhcG9wMTgkc21lZGlhNSkKdGFibGUobGFwb3AxOCRzbWVkaWE4KQpsYXBvcDE4JHNtZWRpYTJyID0gY2FyOjpyZWNvZGUobGFwb3AxOCRzbWVkaWEyLCAiMToyPTE7IDM6ND0yOyA1PTMiKQpsYXBvcDE4JHNtZWRpYTVyID0gY2FyOjpyZWNvZGUobGFwb3AxOCRzbWVkaWE1LCAiMToyPTE7IDM6ND0yOyA1PTMiKQpsYXBvcDE4JHNtZWRpYThyID0gY2FyOjpyZWNvZGUobGFwb3AxOCRzbWVkaWE4LCAiMToyPTE7IDM6ND0yOyA1PTMiKQpsYXBvcDE4JHNtZWRpYTJyID0gYXMuZmFjdG9yKGxhcG9wMTgkc21lZGlhMnIpCmxhcG9wMTgkc21lZGlhNXIgPSBhcy5mYWN0b3IobGFwb3AxOCRzbWVkaWE1cikKbGFwb3AxOCRzbWVkaWE4ciA9IGFzLmZhY3RvcihsYXBvcDE4JHNtZWRpYThyKQpsZXZlbHMobGFwb3AxOCRzbWVkaWEycikgPSBjKCJIaWdoIHVzZSIsICJMb3cgdXNlIiwgIk5vbiB1c2VyIikKbGV2ZWxzKGxhcG9wMTgkc21lZGlhNXIpID0gYygiSGlnaCB1c2UiLCAiTG93IHVzZSIsICJOb24gdXNlciIpCmxldmVscyhsYXBvcDE4JHNtZWRpYThyKSA9IGMoIkhpZ2ggdXNlIiwgIkxvdyB1c2UiLCAiTm9uIHVzZXIiKQp0YWJsZShsYXBvcDE4JHNtZWRpYTJyKQp0YWJsZShsYXBvcDE4JHNtZWRpYTVyKQp0YWJsZShsYXBvcDE4JHNtZWRpYThyKQpgYGAKCldpdGggdGhlc2UgcmVjb2RlZCB2YXJpYWJsZXMsIGl0IGlzIHBvc3NpYmxlIHRvIGNhbGN1bGF0ZSB0aGUgbWVhbiAod2hpY2ggYXJlIHRoZSBwZXJjZW50YWdlcykgb2Ygc2F0aXNmYWN0aW9uIHdpdGggZGVtb2NyYWN5IGZvciBlYWNoIGdyb3VwIG9mIGluZm9ybWF0aW9uIGNvbnN1bXB0aW9uIGluIHNvY2lhbCBuZXR3b3Jrcy4KVGhpcyBjYW4gYmUgZG9uZSBpbiBtdWx0aXBsZSB3YXlzLgpJZiB5b3Ugd2FudCB0byBjb21wYXJlIHRoZSBtZWFucywgeW91IGNhbiB1c2UgdGhlIGNvbW1hbmQgYHRhcHBseWAuCgpgYGB7ciBhdmVyYWdlIGJ5IG5ldHdvcmtzfQp0YXBwbHkobGFwb3AxOCRwbjRyciwgbGFwb3AxOCRzbWVkaWEyciwgbWVhbiwgbmEucm09VCkgI0ZhY2Vib29rCnRhcHBseShsYXBvcDE4JHBuNHJyLCBsYXBvcDE4JHNtZWRpYTVyLCBtZWFuLCBuYS5ybT1UKSAjVHdpdHRlcgp0YXBwbHkobGFwb3AxOCRwbjRyciwgbGFwb3AxOCRzbWVkaWE4ciwgbWVhbiwgbmEucm09VCkgI1doYXRzYXBwCmBgYAoKT3RoZXIgb3B0aW9uIHRoYXQgY2FuIGRpc3BsYXkgYm90aCB0aGUgbWVhbiBhbmQgdGhlIHN0YW5kYXJkIGRldmlhdGlvbiBpcyB0aHJvdWdoIHRoZSBsaWJyYXJ5IGBwbHlyYCBhbmQgdGhlIGNvbW1hbmQgYGRkcGx5YC4KVGhlIGNvZGUgZm9yIEZhY2Vib29rIHdvdWxkIGJlOgoKYGBge3IgbWVkaWFwb3JyZWRlczIsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CmxpYnJhcnkocGx5cikKZGRwbHkobGFwb3AxOCwgInNtZWRpYTJyIiwgc3VtbWFyaXNlLCBtZWFuPW1lYW4ocG40cnIsIG5hLnJtPVQpLCBzZD1zZChwbjRyciwgbmEucm09VCkpCmBgYAoKSXQgaXMgaW1wb3J0YW50IHRvIG5vdGUgdGhhdCBpbiB0aGlzIGNhc2Ugd2UgaGF2ZSBub3QgaW5kaWNhdGVkIHRoYXQgaW50ZXJuYWxseSB3ZSBkbyBub3Qgd29yayB3aXRoIG1pc3NpbmcgdmFsdWVzICh1c2luZyB0aGUgc3BlY2lmaWNhdGlvbiBgZmlsdGVyKCFpcy5uYSh3YV91c2VyKSlgKSwgc28gdGhlIHRhYmxlIGFib3ZlIHByZXNlbnRzIGEgcm93IG9mIE5BLCBvYnNlcnZhdGlvbnMgd2l0aCBubyBpbmZvcm1hdGlvbiBvZiB1c2luZyBvZiB0aGUgc29jaWFsIG5ldHdvcmssIHdoZXJlIHRoZSBhdmVyYWdlIGFuZCB0aGUgc3RhbmRhcmQgZGV2aWF0aW9uIG9mIHRoZSB2YXJpYWJsZSBzYXRpc2ZhY3Rpb24gd2l0aCBkZW1vY3JhY3kgYXJlIGNhbGN1bGF0ZWQuCkZpbmFsbHksIGFuIG9wdGlvbiB0aGF0IGFsbG93cyB5b3UgdG8gZGlzcGxheSBtYW55IHN0YXRpc3RpY3MgZm9yIGVhY2ggZ3JvdXAgaXMgYGRlc2NyaWJlQnlgIGZyb20gdGhlIGxpYnJhcnkgYHBzeWNoYC4KVGhlIGNvZGUgZm9yIFR3aXR0ZXIgaXM6CgpgYGB7ciBtZWRpYXBvcnJlZGVzMywgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KbGlicmFyeShwc3ljaCkKZGVzY3JpYmVCeShsYXBvcDE4JHBuNHJyLCBncm91cD1sYXBvcDE4JHNtZWRpYTVyKQpgYGAKCkhvd2V2ZXIsIHdoYXQgaW50ZXJlc3RzIHVzIGlzIHRvIGNhbGN1bGF0ZSB0aGUgY29uZmlkZW5jZSBpbnRlcnZhbHMgZm9yIGVhY2ggZ3JvdXAuCkZpZ3VyZSAzLjkgb2YgdGhlIHJlcG9ydCBwcmVzZW50cyB0aGUgbWVhbiBvZiBzYXRpc2ZhY3Rpb24gd2l0aCBkZW1vY3JhY3ksIHNob3duIGFzIGEgcG9pbnQsIGFuZCB0aGUgY29uZmlkZW5jZSBpbnRlcnZhbHMgZm9yIGVhY2ggZ3JvdXAsIHNob3duIGFzIGEgZ3JheSBhcmVhIHdpdGggbG93ZXIgYW5kIHVwcGVyIGxpbWl0cy4KVGhlIGxpYnJhcnkgYFJtaXNjYCBhbmQgdGhlIGNvbW1hbmQgYGdyb3VwLkNJYCBjYW4gYmUgdXNlZCB0byBjYWxjdWxhdGUgdGhlIGNvbmZpZGVuY2UgaW50ZXJ2YWxzIG9mIHRoZSB2YXJpYWJsZSBzYXRpc2ZhY3Rpb24gd2l0aCBkZW1vY3JhY3kgYnkgZ3JvdXBzIG9mIGluZm9ybWF0aW9uIGNvbnN1bXB0aW9uIG9uIEZhY2Vib29rLgoKYGBge3IgaWNieWdyb3VwLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQpsaWJyYXJ5KFJtaXNjKQpncm91cC5DSShwbjRycn5zbWVkaWEyciwgbGFwb3AxOCkKYGBgCgpXaXRoIHRoZXNlIGRhdGEsIGZvciBleGFtcGxlLCB0aGUgYXZlcmFnZSBzYXRpc2ZhY3Rpb24gd2l0aCBkZW1vY3JhY3kgYW1vbmcgdGhlIGdyb3VwIHdpdGggaGlnaCB1c2Ugb2YgaW5mb3JtYXRpb24gb24gRmFjZWJvb2sgaXMgMzcuNiUuClRoZSBsb3dlciBsaW1pdCBvZiB0aGUgY29uZmlkZW5jZSBpbnRlcnZhbCBpcyAzNi43JSBhbmQgdGhlIHVwcGVyIGxpbWl0IGlzIDM4LjQlLgpXaXRoIHRoZXNlIGRhdGEsIGEgYmFyIGNoYXJ0IHNpbWlsYXIgdG8gMy45IGNvdWxkIGJlIHJlcGxpY2F0ZWQuCgojIENvbmZpZGVuY2UgSW50ZXJ2YWxzIGZvciBzYXRpc2ZhY3Rpb24gd2l0aCBkZW1vY3JhY3kgYnkgZ3JvdXBzIG9mIFR3aXR0ZXIgdXNlcnMKClRoZSBlYXNpZXN0IHdheSB0byBwbG90IGNvbmZpZGVuY2UgaW50ZXJ2YWxzIGJ5IGdyb3VwcyBpcyB0byB1c2UgdGhlIGNvbW1hbmQgYHBsb3RtZWFuc2AuCgpgYGB7ciBncmFmeGdydXAsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CmxpYnJhcnkoZ3Bsb3RzKQpwbG90bWVhbnMobGFwb3AxOCRwbjRycn5sYXBvcDE4JHNtZWRpYTVyLAogICAgICAgICAgeGxhYj0iVHlwZSBvZiBUd2l0dGVyIHVzZXIiLAogICAgICAgICAgeWxhYj0iU2F0aXNmYWN0aW9uIHdpdGggZGVtb2NyYWN5IiwKICAgICAgICAgIHlsaW09YygwLCA1MCksCiAgICAgICAgICBtZWFuLmxhYmVscz1ULCBkaWdpdHM9MSwKICAgICAgICAgIGNvbm5lY3Q9RgogICAgICAgICApCmBgYAoKVGhpcyBvcHRpb24gZGlzcGxheXMgdGhlIGNvbmZpZGVuY2UgaW50ZXJ2YWxzIGJ1dCBpcyBkaWZmaWN1bHQgaWYgeW91IHdhbnQgdG8gcGxvdCB0aGUgYmFycy4KVGhlIGxpYnJhcnkgYGdncGxvdGAgZ2l2ZXMgdXMgbW9yZSBvcHRpb25zIGFuZCBhbGxvd3MgdXMgdG8gcGxvdCBpbiBhIHNpbWlsYXIgd2F5IHRvIEZpZ3VyZSAzLjkgb2YgdGhlIHJlcG9ydC4KRm9yIHRoaXMsIGEgInR3LnVzZSIgZGF0YWZyYW1lIGlzIGZpcnN0IHNhdmVkIHdpdGggdGhlIGRhdGEgb2YgdGhlIG1lYW4gYW5kIHRoZSB1cHBlciBhbmQgbG93ZXIgbGltaXRzIG9mIGVhY2ggZ3JvdXAsIHVzaW5nIHRoZSBjb21tYW5kIGBncm91cC5DSWAuCkl0IGlzIHRoZSBkYXRhIGZyb20gdGhpcyBkYXRhZnJhbWUgdGhhdCBpcyB1c2VkIHdpdGggYGdncGxvdGAgYW5kIGEgZ3JhcGggaXMgY3JlYXRlZCB3aGljaCBpcyBzYXZlZCBpbiBhICJncmFmMSIgb2JqZWN0LgpXaXRoIHRoaXMgbGlicmFyeSwgdGhlIGxheWVyIGBnZW9tX2JhcigpYCBpcyBhZGRlZCB0byBkZWZpbmUgdGhhdCB5b3Ugd2FudCBhIGJhciBncmFwaCBvZiB0aGUgdmFyaWFibGVzIHNwZWNpZmllZCBpbiBgYWVzYC4KVGhlbiB0aGUgbGF5ZXIgYGdlb21fZXJyb3JiYXIoKWAgaXMgYWRkZWQgdG8gYWRkIHRoZSBlcnJvciBiYXJzIGFuZCB0aGVuIHRoZSBtZWFuIHZhbHVlcyB3aXRoIGBnZW9tX3RleHQoKWAuCkZpbmFsbHksIHRoZSBYIGFuZCBZIGF4aXMgYXJlIGxhYmVsZWQgd2l0aCBgeGxhYmAgYW5kIGB5bGFiYCBhbmQgdGhlIGxpbWl0cyBvZiB0aGUgWSBheGlzIGFyZSBkZWZpbmVkIHdpdGggYHlsaW1gLgoKYGBge3IgZ3JhZnhncnVwMiwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KdHcudXNlIDwtIGdyb3VwLkNJKHBuNHJyfnNtZWRpYTVyLCBsYXBvcDE4KQpsaWJyYXJ5KGdncGxvdDIpCmdyYWYxIDwtIGdncGxvdCh0dy51c2UsIGFlcyh4PXNtZWRpYTVyLCB5PXBuNHJyLm1lYW4pKSsKICBnZW9tX2Jhcih3aWR0aD0wLjUsIGZpbGw9ImRhcmtjeWFuIiwgY29sb3VyPSJibGFjayIsIHN0YXQ9ImlkZW50aXR5IikrCiAgZ2VvbV9lcnJvcmJhcihhZXMoeW1pbj1wbjRyci5sb3dlciwgeW1heD1wbjRyci51cHBlciksIHdpZHRoPTAuMikrCiAgZ2VvbV90ZXh0KGFlcyhsYWJlbD1wYXN0ZShyb3VuZChwbjRyci5tZWFuLCAxKSwgIiUiKSksIHZqdXN0PS00LjIsIHNpemU9NCkrCiAgeGxhYigiVHlwZSBvZiBUd2l0dGVyIHVzZXIiKSArIHlsYWIoIlNhdGlzZmFjdGlvbiB3aXRoIGRlbW9jcmFjeSAoJSkiKSsKICB5bGltKDAsIDUwKQpncmFmMQpgYGAKCkFjY29yZGluZyB0byB0aGVzZSByZXN1bHRzLCBzYXRpc2ZhY3Rpb24gd2l0aCBkZW1vY3JhY3kgaXMgaGlnaGVyIGluIG5vbi1Ud2l0dGVyIHVzZXJzLCBjb21wYXJlZCB0byB1c2VycywgYWx0aG91Z2ggdGhlIGRpZmZlcmVuY2VzIGFyZSBub3Qgc3RhdGlzdGljYWxseSBzaWduaWZpY2FudCBmcm9tIGEgdmlzdWFsIGNvbXBhcmlzb24gYmV0d2VlbiBjb25maWRlbmNlIGludGVydmFscy4KCiMgU2F0aXNmYWN0aW9uIHdpdGggZGVtb2NyYWN5IGJ5IGdyb3VwcyBvZiB0eXBlIG9mIHVzZXIgb2Ygc29jaWFsIG5ldHdvcmtzCgpTbyBmYXIsIGNvbmZpZGVuY2UgaW50ZXJ2YWxzIG9mIHNhdGlzZmFjdGlvbiB3aXRoIGRlbW9jcmFjeSBoYXZlIGJlZW4gY3JlYXRlZCBieSB0eXBlIG9mIFR3aXR0ZXIgdXNlci4KVGhlIHJlcG9ydCBhZ2dyZWdhdGVzIHRoZSB1c2VycyBvZiB0aGUgdGhyZWUgc29jaWFsIG5ldHdvcmtzIHRvIGlkZW50aWZ5IHRocmVlIHR5cGVzIG9mIHVzZXJzOiBoaWdoLXVzZXJzLCBsb3ctdXNlcnMsIGFuZCBub24tdXNlcnMgb2YgYW55IHNvY2lhbCBuZXR3b3JrLgpUaGUgd2F5IG9mIHJlY29kaW5nIHRoaXMgdHlwZSBvZiB1c2VyIG9mIHRocmVlIHNvY2lhbCBuZXR3b3JrcyBpcyBiYXNlZCBvbiBzZXZlcmFsIGNvbmRpdGlvbnMuCkFzIHRoZSByZXBvcnQgc2F5czogIldlIHVzZSB0aGUgc2FtZSBjb2RpbmcgYXMgaW4gdGhlIHByZXZpb3VzIHNlY3Rpb24sIHRvIGRpc3Rpbmd1aXNoIGJldHdlZW4gdGhvc2Ugd2hvIGZyZXF1ZW50bGUgdXNlIHNvY2lhbCBtZWRpYSAodGhvc2Ugd2l0aCBhY2NvdW50cyB0aGF0IHRoZXkgYWNjZXNzIGEgZmV3IHRpbWVzIGEgd2VlayBvciBkYWlseSkgYW5kIHRob3NlIHdobyBkbyBub3QgdXNlIHNvY2lhbCBuZXR3b3JrcyBmcmVxdWVudGx5ICh0aG9zZSB3aXRoIGFjY291bnRzIHRoYXQgdGhleSBhY2Nlc3MgYSBmZXcgdGltZXMgYSBtb250aCBvciBhIGZldyB0aW1lcyBhIHllYXIpLiBXZSBhbHNvIGluY2x1ZGUgbm9uLXVzZXJzOiB0aG9zZSB3aG8gZG8gbm90IGhhdmUgYW55IHNvY2lhbCBuZXR3b3JrIGFjY291bnRzICh0aG9zZSB3aG8gaW5kaWNhdGUgdGhhdCB0aGV5IGRvIG5vdCBoYXZlIGFuIGFjY291bnQgb24gRmFjZWJvb2ssIFR3aXR0ZXIgb3IgV2hhdHNhcHApIGFuZCB0aG9zZSB3aG8gaGF2ZSBhbiBhY2NvdW50LCBidXQgbmV2ZXIgdXNlIGl0IiAocC44MSkuCldlIGZpcnN0IGlkZW50aWZ5IHRob3NlIHdobyB1c2UgZWFjaCBzb2NpYWwgbmV0d29yayBhIGZldyB0aW1lcyBhIHdlZWsgb3IgZGFpbHkgYXMgMSBhbmQgaWYgdGhleSB1c2UgZWFjaCBzb2NpYWwgbmV0d29yayBhIGZldyB0aW1lcyBhIG1vbnRoIG9yIGEgZmV3IHRpbWVzIGEgeWVhciwgYXMgMC4KRm9yIHRoaXMgd2UgdXNlIHRoZSBjb21tYW5kIGBpZmVsc2VgLgpUaGVuLCB3ZSBhZGQgdGhlIHZhbHVlcyBvZiBlYWNoIHNvY2lhbCBuZXR3b3JrIGluIGEgc2luZ2xlIHZhcmlhYmxlLCB3aXRoIHZhbHVlcyBiZXR3ZWVuIDAgYW5kIDMuClRoZSBjb21tYW5kIGByb3dTdW1zYCBpcyB1c2VkLCB3aGljaCBhbGxvd3MgdGhlIGhvcml6b250YWwgc3VtIG9mIGRlZmluZWQgdmFyaWFibGVzLCBpbiB0aGlzIGNhc2UgdGhvc2UgYXQgcG9zaXRpb24gYFssIDg5OjkxXWAuCkluIHRoaXMgY29tbWFuZCwgd2UgdXNlIHRoZSBzcGVjaWZpY2F0aW9uIGBuYS5ybT1UYCBzbyB0aGF0IHRoZSBzdW0gZG9lcyBub3QgdGFrZSBtaXNzaW5nIHZhbHVlcyBpbnRvIGFjY291bnQuCgpgYGB7ciBuZXR3b3Jrc3VzZXJzfQpsYXBvcDE4JHNtMiA9IGlmZWxzZShsYXBvcDE4JHNtZWRpYTI9PTEgfCBsYXBvcDE4JHNtZWRpYTI9PTIsIDEsIDApCmxhcG9wMTgkc201ID0gaWZlbHNlKGxhcG9wMTgkc21lZGlhNT09MSB8IGxhcG9wMTgkc21lZGlhNT09MiwgMSwgMCkKbGFwb3AxOCRzbTggPSBpZmVsc2UobGFwb3AxOCRzbWVkaWE4PT0xIHwgbGFwb3AxOCRzbWVkaWE4PT0yLCAxLCAwKQpsYXBvcDE4JGFueWhpID0gcm93U3VtcyhsYXBvcDE4Wyw4OTo5MV0sIG5hLnJtPVQpCnRhYmxlKGxhcG9wMTgkYW55aGkpCmBgYAoKU3RhcnRpbmcgZnJvbSB0aGlzIHZhcmlhYmxlLCBhIHZhcmlhYmxlIGlzIGNyZWF0ZWQgdGhhdCBhZ2dyZWdhdGVzIHRoZSB0aHJlZSBzb2NpYWwgbmV0d29ya3MsIGNhbGxlZCAiaGlfbG9fbm9uIi4KRmlyc3QsIHRoaXMgdmFyaWFibGUgaXMgY3JlYXRlZCBhcyBhIHZlY3RvciBvZiBOQXMuClZhbHVlcyBvZiAxLCAyLCAzIG9yIE5BIGFyZSB0aGVuIGltcHV0ZWQgdG8gaXQsIGRlcGVuZGluZyBvbiB0aGUgdmFsdWVzIG9mICJhbnloaSIgb3IgdGhlIHZhbHVlcyBvZiB0aGUgc29jaWFsIG5ldHdvcmsgdmFyaWFibGVzLgpBIG5ldyB2YXJpYWJsZSBvZiB0eXBlIGZhY3RvciBpcyB0aGVuIGNyZWF0ZWQsIHdpdGggaWRlbnRpY2FsIHZhbHVlcyBhcyAiaGlfbG9fbm9uIiBhbmQgaXMgbGFiZWxlZC4KVGhlIGRlZmluaXRpb24gb2YgdGhlIGNvbmRpdGlvbmFsaXR5IGlzIHdvcmtlZCB0aHJvdWdoIHRoZSBzcXVhcmUgYnJhY2tldHMgYFsuLi5dYC4KSW4gdGhpcyB3YXksIHRoZSBjb25kaXRpb25zIGFyZSBkZWZpbmVkIGFzIGZvbGxvd3M6CgotICAgVGhlIHZhcmlhYmxlICJoaV9sb19ub24gaXMgZXF1YWwgdG8gMSBpZiB0aGUgdmFyaWFibGUgYW55aGkgaXMgZ3JlYXRlciB0aGFuIG9yIGVxdWFsIHRvIDEgKHVzZSBkYWlseSBvciBhIGZldyB0aW1lcyBhIHdlZWspID0gYGxhcG9wMTgkaGlfbG9fbm9uW2xhcG9wMTgkYW55aGk+PTFdID0gMWAKCi0gICBUaGUgdmFyaWFibGUgImhpX2xvX25vbiBpcyBlcXVhbCB0byAyIGlmIHRoZSB2YXJpYWJsZSBhbnloaSBpcyBlcXVhbCB0byAwICh1c2UgYSBmZXcgdGltZXMgYSB5ZWFyIG9yIG5ldmVyKSA9IGBsYXBvcDE4JGhpX2xvX25vbltsYXBvcDE4JGFueWhpPT0wXSA9IDJgCgotICAgVGhlIHZhcmlhYmxlICJoaV9sb19ub24gaXMgZXF1YWwgdG8gMyBpZiB0aGUgdmFyaWFibGVzIG9mIGFjY291bnQgaG9sZGluZyBhcmUgZXF1YWwgdG8gMiAoTm8pID0gYGxhcG9wMTgkaGlfbG9fbm9uW2xhcG9wMTgkc21lZGlhMT09MiAmIGxhcG9wMTgkc21lZGlhND09MiAmIGxhcG9wMTgkc21lZGlhNz09Ml0gPSAzYAoKVGhlIGZvbGxvd2luZyBjb2RpbmcgcnVsZXMgZm9sbG93IHRoZSBzYW1lIGxvZ2ljIG9mIGNvbWJpbmluZyBvdGhlciB2YXJpYWJsZXMgdG8gaW1wdXRlIHRoZSB2YWx1ZSAzIG9yIE5BLgoKYGBge3IgaGlsb25vbn0KbGFwb3AxOCRoaV9sb19ub24gPSBOQSAjY3JlYXRlIGEgdmVjdG9yIHdpdGggTkFzIwpsYXBvcDE4JGhpX2xvX25vbltsYXBvcDE4JGFueWhpPj0xXSA9IDEgIzEgaXMgY29kZWQgZm9yIHRob3NlIHdobyB1c2UgYSBzb2NpYWwgbmV0d29yayBkYWlseSBvciBhIGZldyB0aW1lcyBhIHdlZWsuIwpsYXBvcDE4JGhpX2xvX25vbltsYXBvcDE4JGFueWhpPT0wXSA9IDIgI1Rob3NlIHdobyB1c2UgYSBzb2NpYWwgbmV0d29yayBhIGZldyB0aW1lcyBhIG1vbnRoIGFuZCBhIHllYXIgYXJlIGNvZGVkIGFzIDIjCmxhcG9wMTgkaGlfbG9fbm9uW2xhcG9wMTgkc21lZGlhMT09MiAmIGxhcG9wMTgkc21lZGlhND09MiAmIGxhcG9wMTgkc21lZGlhNz09Ml0gPSAzICNUaG9zZSB3aG8gZG8gbm90IGhhdmUgc29jaWFsIG5ldHdvcmtzIGFyZSBjb2RlZCBhcyAzIwpsYXBvcDE4JGhpX2xvX25vbltsYXBvcDE4JHNtZWRpYTI9PTUgJiBsYXBvcDE4JHNtZWRpYTU9PTUgJiBsYXBvcDE4JHNtZWRpYTg9PTVdID0gMyAjVGhvc2Ugd2hvIG5ldmVyIHVzZSBhbnkgc29jaWFsIG5ldHdvcmsgYXJlIGNvZGVkIGFzIDMjCmxhcG9wMTgkaGlfbG9fbm9uW2xhcG9wMTgkcGFpcz09MyAmIChsYXBvcDE4JHNtZWRpYTI9PTUgfCBsYXBvcDE4JHNtZWRpYTU9PTUgfCBsYXBvcDE4JHNtZWRpYTg9PTUpXSA9IDMgI0EgcGFydGljdWxhciBjb2RlIGlzIGFwcGxpZWQgdG8gY291bnRyeSAzIwpsYXBvcDE4JGhpX2xvX25vbltsYXBvcDE4JHBhaXM9PTMgJiAobGFwb3AxOCRzbWVkaWExPT0yIHwgbGFwb3AxOCRzbWVkaWE0PT0yIHwgbGFwb3AxOCRzbWVkaWE3PT0yKV0gPSAzICNBIHBhcnRpY3VsYXIgY29kZSBpcyBhcHBsaWVkIHRvIGNvdW50cnkgMyMKCmxhcG9wMTgkaGlsb24gPSBhcy5mYWN0b3IobGFwb3AxOCRoaV9sb19ub24pCmxldmVscyhsYXBvcDE4JGhpbG9uKSA9IGMoIkhpZ2ggdXNlIiwgIkxvdyB1c2UiLCAiTm9uIHVzZXIiKQpwcm9wLnRhYmxlKHRhYmxlKGxhcG9wMTgkaGlsb24pKSoxMDAKYGBgCgpBY2NvcmRpbmcgdG8gdGhlc2UgZGF0YSwgNjQuOSUgb2YgdGhvc2UgaW50ZXJ2aWV3ZWQgcmVwb3J0IGEgaGlnaCB1c2Ugb2Ygc29jaWFsIG5ldHdvcmtzLCB3aGlsZSwgYXQgdGhlIG90aGVyIGV4dHJlbWUsIHRoZXJlIGFyZSAzMS42JSB3aG8gZG8gbm90IHVzZSBhbnkgc29jaWFsIG5ldHdvcmsuClRoZXNlIGRhdGEgZGlmZmVyIHNsaWdodGx5IGZyb20gdGhvc2UgcmVwb3J0ZWQgaW4gdGhlIEFwcGVuZGl4IHRvIHRoZSByZXBvcnQsIGF2YWlsYWJsZSBbaGVyZV0oaHR0cHM6Ly93d3cudmFuZGVyYmlsdC5lZHUvbGFwb3AvYWIyMDE4L0FwcGVuZGl4X01hdGVyaWFsX2Zvcl8yMDE4LTE5X0FtZXJpY2FzQmFyb21ldGVyX1JlcG9ydC1Db21wYXJhdGl2ZV9DaGFwdGVyc18xMC4xMy4xOS5wZGYpLCB3aGVyZSA2NS4zNCUgb2YgaGlnaCB1c2UgYW5kIDMxLjYwJSBvZiBub24tdXNlcnMgYXJlIHJlcG9ydGVkLgpUaGVzZSBkaWZmZXJlbmNlcyBtYXkgYmUgZHVlIHRvIGRpZmZlcmVuY2VzIGluIHRoZSBpbnRlcnByZXRhdGlvbiBvZiB0aGUgY29kaW5nIHJ1bGVzIGZyb20gU3RhdGEgdG8gUi4KCkluIHRoZSBzYW1lIHdheSB0aGF0IHRoZSBncmFwaCBvZiBhdmVyYWdlIHNhdGlzZmFjdGlvbiB3aXRoIGRlbW9jcmFjeSBieSB0eXBlIG9mIFR3aXR0ZXIgdXNlciB3YXMgcHJvZHVjZWQgdXNpbmcgYGdncGxvdGAsIG5vdyB0aGUgc2FtZSB3aWxsIGJlIGRvbmUgYnV0IGZvciB0aGUgdXNlcnMgb2YgdGhlIHRocmVlIHNvY2lhbCBuZXR3b3JrcywgdmFyaWFibGUgImhpbG9uIi4KCmBgYHtyIGdyYWYzLjl9CmxpYnJhcnkoUm1pc2MpCnNhdGlzLnVzZSA9IGdyb3VwLkNJKHBuNHJyfmhpbG9uLCBsYXBvcDE4KQpsaWJyYXJ5KGdncGxvdDIpCmZpZzMuOSA9IGdncGxvdChzYXRpcy51c2UsIGFlcyh4PWhpbG9uLCB5PXBuNHJyLm1lYW4pKSsKICBnZW9tX2Jhcih3aWR0aD0wLjUsIGZpbGw9ImRhcmtjeWFuIiwgY29sb3VyPSJibGFjayIsIHN0YXQ9ImlkZW50aXR5IikrCiAgZ2VvbV9lcnJvcmJhcihhZXMoeW1pbj1wbjRyci5sb3dlciwgeW1heD1wbjRyci51cHBlciksIHdpZHRoPTAuMikrCiAgZ2VvbV90ZXh0KGFlcyhsYWJlbD1wYXN0ZShyb3VuZChwbjRyci5tZWFuLCAxKSwgIiUiKSksIHZqdXN0PS0yLjUsIHNpemU9NCkrCiAgeGxhYigiVHlwZSBvZiBzb2NpYWwgbmV0d29yayB1c2VyIikgKyB5bGFiKCJTYXRpc2ZhY3Rpb24gd2l0aCBkZW1vY3JhY3kgKCUpIikrCiAgeWxpbSgwLCA1MCkKZmlnMy45CmBgYAoKVGhpcyBncmFwaCB3b3VsZCBiZSBhIHJlcGxpY2F0aW9uIG9mIHRoZSBvbmUgcHJlc2VudGVkIGluIHRoZSByZXBvcnQgKEZpZ3VyZSAzLjkgb24gcGFnZSA2MiksIHdpdGggbWlub3IgZGlmZmVyZW5jZXMgZHVlIHRvIHRoZSBlbmNvZGluZyBvZiB0aGUgcmVzdWx0aW5nIGRhdGEuCgojIFN1bW1hcnkKCkluIHRoaXMgc2VjdGlvbiB3ZSBoYXZlIHdvcmtlZCB3aXRoIGEgcmVjb2RlZCBkdW1teSB2YXJpYWJsZSAoc2F0aXNmYWN0aW9uIHdpdGggZGVtb2NyYWN5KSwgd2hpY2ggY2FuIGJlIHVzZWQgYXMgYSBudW1lcmljYWwgdmFyaWFibGUgZm9yIGNhbGN1bGF0aW5nIGNvbmZpZGVuY2UgaW50ZXJ2YWxzIG9mIHByb3BvcnRpb25zLgpXaXRoIHRoaXMgdmFyaWFibGUsIHRoZSBjb25maWRlbmNlIGludGVydmFsIG9mIHRoZSBtZWFuIGhhcyBiZWVuIGNhbGN1bGF0ZWQsIHdoaWNoIHdvdWxkIGJlIHRoYXQgb2YgdGhlIHByb3BvcnRpb24gb2YgcmVzcG9uZGVudHMgd2hvIGFyZSBzYXRpc2ZpZWQgd2l0aCBkZW1vY3JhY3kuClRoZW4sIHRoZXNlIHZhcmlhYmxlcyBoYXZlIGJlZW4gZGVzY3JpYmVkIGJ5IGdyb3VwcyBvZiBhIGZhY3RvciB2YXJpYWJsZSAoY29uc3VtcHRpb24gb2YgcG9saXRpY2FsIGluZm9ybWF0aW9uKS4KSXQgaGFzIGJlZW4gcHJlc2VudGVkIGhvdyB0byBjYWxjdWxhdGUgdGhlIGNvbmZpZGVuY2UgaW50ZXJ2YWxzIG9mIHRoZSBudW1lcmljYWwgdmFyaWFibGUgYnkgZ3JvdXBzIG9mIHRoZSBmYWN0b3IgdmFyaWFibGUuCkZpbmFsbHksIGl0IGhhcyBiZWVuIHByZXNlbnRlZCBob3cgdG8gcGxvdCB0aGUgY29uZmlkZW5jZSBpbnRlcnZhbHMgYnkgZ3JvdXBzLgoKIyBDYWxjdWxhdGlvbnMgaW5jbHVkaW5nIHN1cnZleSB3ZWlnaHRzCgpPdGhlciB3YXkgdG8gY2FsY3VsYXRlIHRoZSBjb25maWRlbmNlIGludGVydmFsLCBpbmNsdWRpbmcgdGhlIHN1cnZleSB3ZWlnaHQsIGlzIGJ5IHVzaW5nIHRoZSBsaWJyYXJ5IGBzdXJ2ZXlgIGFuZCB0aGUgY29tbWFuZCBgY29uZmludGAgYWxvbmcgd2l0aCB0aGUgbmF0aXZlIGNvbW1hbmQgYHN2eW1lYW5gLgoKYGBge3IgZGVzaWdufQpsaWJyYXJ5KHN1cnZleSkKZGVzaWduMTggPSBzdnlkZXNpZ24oaWRzID0gfnVwbSwgc3RyYXRhID0gfmVzdHJhdG9wcmksIHdlaWdodHMgPSB+d2VpZ2h0MTUwMCwgbmVzdD1UUlVFLCBkYXRhPWxhcG9wMTgpCmBgYAoKSW4gdGhlIHNhbWUgd2F5IGFzIGluIHRoZSBwcmV2aW91cyBzZWN0aW9uLCB0aGUgc2F0aXNmYWN0aW9uIHdpdGggZGVtb2NyYWN5IHZhcmlhYmxlIGNhbiBiZSBkZXNjcmliZWQgYnkgaW5jb3Jwb3JhdGluZyBzdXJ2ZXkgd2VpZ2h0cyB1c2luZyB0aGUgY29tbWFuZCBgc3Z5bWVhbmAuCgpgYGB7ciB3ZWlnaHRlZHBuNH0Kc3Z5bWVhbih+cG40cnIsIGRlc2lnbjE4LCBuYS5ybT1UKQpgYGAKClRvIGNhbGN1bGF0ZSB0aGUgY29uZmlkZW5jZSBpbnRlcnZhbCwgdGhlIGFib3ZlIGNvZGUgaGFzIHRvIGJlIG5lc3RlZCBpbnNpZGUgdGhlIGNvbW1hbmQgYGNvbmZpbnRgLgpUaGlzIGNvbW1hbmQgY2FsY3VsYXRlcyB0aGUgOTUlIGNvbmZpZGVuY2UgaW50ZXJ2YWwgYnkgZGVmYXVsdC4KWW91IGNvdWxkIGNoYW5nZSB0aGlzIGRlZmF1bHQgdmFsdWUgdG8gOTklIGNvbmZpZGVuY2UgYnkgYWRkaW5nIHRoZSBgY29uZiA9IDAuOTlgIHNwZWNpZmljYXRpb24gdG8gdGhlIGNvbW1hbmQuCgpgYGB7ciB3ZWlnaHRlZGNpfQpjb25maW50KHN2eW1lYW4ofnBuNHJyLCBkZXNpZ24xOCwgbmEucm09VCkpCmBgYAoKVGhlIG1lYW4gYW5kIGNvbmZpZGVuY2UgaW50ZXJ2YWwgb2Ygc2F0aXNmYWN0aW9uIHdpdGggZGVtb2NyYWN5IGNhbiBhbHNvIGJlIGNhbGN1bGF0ZWQgaW5jb3Jwb3JhdGluZyB0aGUgc3VydmV5IHdlaWdodCB1c2luZyB0aGUgY29tbWFuZCBgc3Z5YnlgLgpXaXRoaW4gdGhpcyBjb21tYW5kLCB0aGUgbnVtZXJpY2FsIHZhcmlhYmxlIHRvIGJlIGRlc2NyaWJlZCAoYH5wbjRycmApLCB0aGUgdmFyaWFibGUgdGhhdCBmb3JtcyB0aGUgZ3JvdXBzIChgfnNtZWRpYTVyYCksIHRoZSBzYW1wbGUgZGVzaWduIChgZGVzaWduMThgKSwgdGhlIGZ1bmN0aW9uIHRvIGJlIGNhbGN1bGF0ZWQgKCBgc3Z5bWVhbmApLCB0aGF0IGRvZXMgbm90IHRha2UgaW50byBhY2NvdW50IG1pc3NpbmcgdmFsdWVzIChgbmEucm09VGApIGFuZCB0aGUgY29uZmlkZW5jZSBpbnRlcnZhbCBvZiBlYWNoIGdyb3VwIChgdmFydHlwZT0iY2kiYCkgYXJlIGRlZmluZWQuCgpgYGB7ciB3ZWlnaHRlZGNpeGdyb3Vwc30KdHcudXNvLndlaWdodGVkIDwtIHN2eWJ5KH5wbjRyciwgfnNtZWRpYTVyLCBkZXNpZ24xOCwgc3Z5bWVhbiwgbmEucm09VCwgdmFydHlwZSA9ICJjaSIpCnR3LnVzby53ZWlnaHRlZApgYGAKClRvIGJlIGFibGUgdG8gcGxvdCwgdGhlc2UgY2FsY3VsYXRpb25zIGFyZSBzYXZlZCBpbiBhICJ0dy51c28ud2VpZ2h0ZWQiIGRhdGFmcmFtZSwgd2hpY2ggaW5jbHVkZXMgdGhlIG1lYW4gZGF0YSBmb3IgZWFjaCBncm91cCBhbmQgdGhlIGxvd2VyIGFuZCB1cHBlciBsaW1pdCBvZiB0aGUgY29uZmlkZW5jZSBpbnRlcnZhbC4KSW4gdGhlIHNhbWUgd2F5IGFzIHdpdGggZGF0YSB0aGF0IGRvZXMgbm90IGluY2x1ZGUgdGhlIHN1cnZleSBlZmZlY3QsIHRoZSBsaWJyYXJ5IGBnZ3Bsb3RgIGlzIHVzZWQgYW5kIGEgcGxvdCBpcyBjcmVhdGVkIHdoaWNoIGlzIHNhdmVkIGluIGEgImdyYWYyIiBvYmplY3QuClZlcnkgc2ltaWxhciBzcGVjaWZpY2F0aW9ucyB0byB0aGUgcHJldmlvdXMgZXhhbXBsZXMgYXJlIHVzZWQuCgpgYGB7ciB3ZWlnaHRlZGJhcnN9CmdyYWYyIDwtIGdncGxvdCh0dy51c28ud2VpZ2h0ZWQsIGFlcyh4PXNtZWRpYTVyLCB5PXBuNHJyKSkrCiAgZ2VvbV9iYXIod2lkdGg9MC41LCBmaWxsPSJkYXJrY3lhbiIsIGNvbG91cj0iYmxhY2siLCBzdGF0PSJpZGVudGl0eSIpKwogIGdlb21fZXJyb3JiYXIoYWVzKHltaW49Y2lfbCwgeW1heD1jaV91KSwgd2lkdGg9MC4yKSsKICBnZW9tX3RleHQoYWVzKGxhYmVsPXBhc3RlKHJvdW5kKHBuNHJyLCAxKSwgIiUiKSksIHZqdXN0PS00LjIsIHNpemU9NCkrCiAgeGxhYigiVHdpdHRlciB1c2VyIHR5cGUiKSArIHlsYWIoIlNhdGlzZmFjdGlvbiB3aXRoIGRlbW9jcmFjeSAoJSkiKSsKICB5bGltKDAsIDUwKQpncmFmMgpgYGAK