A Fundamental problem of names

Before we begin our discussion of multi-level data, we must first clarify some semantics. The models we are going to be describing and using in this and the following lesson go by a variety of different names, depending on the disciplinary tradition you may come from. To clarify, these models all follow common forms, but names may be vary.

Three names that are commonly used for these models are:

  • Mixed effects models
  • Hierarchical models
  • Random effects models

We will see later why these names are important in specific contexts, but for now, it is sufficient to say that these are all the same model, and they all refer to the same suite of models, but different disciplines/authors/applications have managed to confuse us all.

Some perspectives in Multi-level Modeling

Following from previous lessons, within spatial demography, there are many different types of perspectives that are used when asking questions. Regardless of the specific disciplinary tradition that you may come from, all of these perspectives attempt to situate humans within some contextual level that is assumed to either influence or be influenced by their actions and behaviors.

Following the lessons within this course, we have discussed how various measures of context matter for human health and economic activities, and these are all very valid when considering the use of multi-level models.

In general, a multi-level framework for any analysis will be interested in asking questions about outcomes that are clustered by either space or time or some other linking characteristic, such as cohort of birth or period of life.

The processes that affect an outcome within a multi-level framework are thought to be operating at both the individual level (person level) and at some other structural level of existence. These structural levels can be defined in a variety of ways, but again, following what we have covered previously, the structural levels commonly addressed in spatial demography are those of the household, neighborhood, social network, residential location, or other locational definition. The processes operating at these levels are also believed to be causal to some degree, meaning that they are thought to cause the outcome, or at least we can construct an argument about how these processes could cause the outcome.

Finally, any multilevel perspective has at its core an interest in describing the variation within the population that is attributable to the differences between these contextual, or structural levels. Moreover, the interest in the variation between these contexts presents something that is worth knowing about and addressing beyond simply focusing on the individual.

Multi-level data structure

Most statistical models assume that the data we put into them are independent of one another, meaning the individual responses in sample that is represented by the data are not related to one another in some fashion. Things that can violate this assumption, as we have seen already in this course, are spatial closeness, or, as it often is in multi-level data, neighborhood or place-base co-residence. By co-residence, we simply mean that people live in the same area, however that is defined.

As we have already discussed in this course, according to Tobler’s law, things that are close together are more alike than things that are far apart. So, if two or more people are sampled from a given neighborhood, or place, they may be at least correlated with one another because they share a similar residential location.

In most population-based surveys, people are sampled in a non-random fashion, despite what we learn in our introductory statistics books. This is because it can be much more cost effective to capture a population sample within a small area. These areas may be called clusters or primary sampling units, and you may have seen these terms before in other analyses you have done. Many surveys identify these clusters within their data code books, so that you can use this information in statistical analyses you may do. Often these clusters are nested within other areas known as strata which represent a larger subdivision of space or some sort of administrative area. For example, a school district may serve as a sample stratum, and the schools within it may serve as primary sampling units, or clusters. This would represent a two-stage sample design, with the districts representing the first stage of sampling and the schools being the second stage. We could have a third stage where classrooms are sampled within schools, for instance. A popular longitudinal survey, the Early Childhood Longitudinal Survey - Kindergarten cohort, 1998 and 2011 follow this type of sampling strategy.

When doing any analysis of data that are sampled in this kind of nested fashion, we must be careful, because the observations at any of these levels could be correlated. This leads to dependence among the observations within the given levels, and typically, the lower the level of sampling, the more similar the observations. You can think that children within the same classroom may be more similar to one another than children in the same school district, for example.

Here’s a picture of the process of stratified sampling, with a simple 1 stage design. In this example, there are several possible neighborhoods that could be sampled, but some are not sampled (dotted lines) and some are sampled (solid lines). These could represent strata or clusters, because in a 1 stage design, the two are synonymous.

Within each neighborhood there are people, and some of them are sampled (circles) and some are not sampled (X’s).

Multistage Sampling

If we were to look at the data represented by this type of sampling method, it would look like the example below. We have 12 people nested within three neighborhoods. Each is measured for the outcome variable (Y) and three presumed predictor variables (X1, X2 and X3). We see that these values are unique to each individual, they each have their own individual level data.

Also present is a neighborhood-level variable, Z1, which is the same within neighborhood, but differs across neighborhoods. A real example of this may be the poverty rate, which is measured for areas, and people within the same area will all have the same value for that variable

Multilevel Data

This is actually a really good example of what we have been talking about: people within areas sharing characteristics. In this case everyone in a given neighborhood all have the same level of neighborhood poverty, so they are similar in that regard, but are different in their own characteristics (the X’s for example).

In multi-level analyses, we are typically interested in how both the individual person-level variables and the neighborhood level variables combine to explain the outcome. In the next part of the lesson, we will review various types of research propositions we may be interested in, which use combinations of these available variables.

Multi-level propositions

When we have a research statement that involves individuals within some context, this is called a multi-level proposition. In this sense, we are interested in questions that relate variables at different levels, the person and the place, the micro and the macro.

Types of multi-level propositions

In a multilevel proposition, variables are present at two different levels, and we are potentially interested in the relationship between both the micro and macro level association with our outcome, y.

Again, referring to our data structure from the previous part of this lesson, we could create a graphical representation of these data, with the outcome, Y and the predictor X measured at the individual level, and the contextual variable Z measured at the neighborhood level.

Multi-level data

In the graphs the follow, we will describe types of questions that could be asked using various combinations of this information.

Individual level proposition

If we are concerned with how individual-level factors affect each person’s outcome, then we are stating an individual level, or micro, proposition. In this type of analysis, we have Y and X, both measured on our individual level units. An example of this would be that we think a persons health is affected by their level of education.

Micro-level proposition

Macro level proposition

We can also have purely macro-level propositions, where we have an outcome Y measured at an aggregate level unit, such as a neighborhood or MSA, such as we have seen before in previous lessons. We also have predictors measured at the aggregate unit, Z and we are interested in how Z affects Y. This is referred to as an ecological study because we observe no within area variation, only between areas. While this type of study is common in spatial demography, the trend is moving away from such analyses as better multi-level data become available. An example of this would be where we are interested to see if higher poverty rates at the MSA level are associated with higher rates of mortality at the MSA level.

Macro-level proposition

Multi-level propositions

In most circumstances when we do a multi-level analysis, we use information in the form of predictors measured at both the micro and macro levels of analysis, in order to understand an outcome at the individual level. These types of analysis represent true multi-level analyses. An example of a multi-level research question would be “For individuals with the a given level of education, does living in an high poverty area lead to poor health”. When we have these types of statements, we are generally looking for a net effect of Z after considering the effect of X.

Multi-level proposition

These are highly informative modelling strategies because we are considering the effects of both individual and neighborhood level variables on an individual level outcome.

Cross-level interactions

The final proposition we will discuss is the cross-level interaction. This is where we ask a question that demands we interact the neighborhood and individual-level predictors. In a sense, this puts the individual level directly within context by considering the interaction. When we use language to describe this type of association, we must stress the conditioning of the individual level effect on the contextual level effect. A cross-level interaction question could be stated as: “Individuals with low levels of education, and who live in areas with high poverty, have higher risk of death.” The important part of the statement is the and, where we stress in our research statement that the individual level characteristic is directly interacted with the neighborhood level variable.

Cross-level proposition

In the section that follows, we will describe the structure of multi-level regression models, emphasizing the various forms that we have covered in this section.

Multi-level statistical models

The multi-level model can be used for any form of outcome variable; continuous, dichotomous, count, right skewed, categorical. Many times the model is presented as an extension to the regular linear regression model, however this is not as useful for much of social science. It is more common in demography and sociology to be analyzing survey data that consist mostly of counts or yes/no question response. Taking this into consideration, we will discuss the multi-level model from the perspective of the generalized linear model, such as we used for logistic or Poisson regression, as to avoid strict reliance on an assumed continuous outcome. We do this because once we are comfortable with the idea that you can link the mean of any outcome to a linear model through the general linear model framework, this can be extended to any distribution.

Using this framework, we will refer to the class of models that we are describing as Generalized Linear Mixed Models, or GLMMs.

In this section we will begin our discussion of the multi-level regression model with the first model most people learn in statistics, the Analysis of Variance (ANOVA). Why the ANOVA? Because the basic multilevel model is a direct analog of the ANOVA model.

If you remember, the ANOVA was the model that was used to compare the means of several groups, or for just two groups. The general form of this is:

\[E(y_j) = \mu + u_{j}\]

or, the mean of the \(j^{th}\) group is a combination of the overall mean of the sample, \(\mu\) and a term \(u_j\) that measures how the mean of the \(j^{th}\) group differs from the overall sample mean, or perhaps from the mean of a pre-arranged reference group. When the number of groups is small, say 3 to 5, the ANOVA model is very efficient, meaning that you are estimating a few parameters in order to estimate the means of each group. These are said to be fixed effects in the model, as they are estimated relative to the mean of a predefined group.

However, in many multi-level modeling analyses, we may have dozens or hundreds of groups. An example would be if we had people nested within counties, even if we only have people in 10% of counties, we would still have over 300 groups in the data. In this setting you would estimate 300 parameters, which sounds like a lot, and it is. Moreover, when the number of groups is small, we generally choose of the groups to be the reference group and compare the means of the other groups to it. When we have a large number of groups, doing this with reference to any one particular group may not be so logical: Why pick the one you choose? Why not another?

It is in this situation where the multi-level model has a distinct advantage. Instead of estimating a single parameter for every group, the multi-level model estimates the overall mean \(\mu\), and then models the group-specific deviations as a set of Normally distributed random variables, with a mean of 0, since the overall mean is estimated by \(\mu\), and a variance of \(\sigma^2_u\). This is considered to be a random effect term in the model. Contrast this to the ANOVA model where al the group means are “fixed”. When using this type of model, we can still measure the means of all the groups, and we are doing so with fewer parameters, technically only two, the overall mean, \(\mu\) and the variance in \(u_j\), \(\sigma^2_u\), although that is a matter of debate in the literature on the subject.

Of course, in social research, the ANOVA model is generally only a first step, and we are often much more interested in controlling for various other factors, so assuming that the ANOVA or the multi-level analog is the kind of model that will be used in a research setting is not very realistic.

So, we can add lots of other terms in the model, and if we use the ANOVA as a basis, we have a model like:

\[E(y_j) = \mu + u_j +\sum_k \beta_k x_k\]

Where the \(\beta\)’s are regression coefficients for other individual level variables in the model, and the x’s are the other predictors, besides the group variable.

Again, if we have a small number of groups, the \(u_j\) will only be a few parameters, and if we have lots of groups then the \(u_j\) will be lots of parameters. In this type of situation, if we adopt a random effect model, then this would be considered a mixed effects model where we have some effects in the model that are considered fixed, the \(\beta_k\)’s and a random effect term for the group means, \(u_j\).

In many presentations of the multi-level model, you may see the equation above written where the \(u_j\) term is absorbed into the intercept term. This would be written as two stages, and in terms of the intercept parameter, \(\beta_0\):

\[y_{ij} = \beta_{0j} +\sum_k \beta_k x_{kij}\] \[\beta_{0j} = \beta_0 + u_j\]

When interpreting this model, the \(u_j\) terms are referred to as a the random intercepts in the model. In model output, these are rarely shown directly, since there can be many of them. What is shown is the variance in these random terms, \(\sigma^2_u\), and it reported by all software that fits these models.

Components of variation in the multi-level model

When using the multi-level model, we are often concerned with how much variation is accounted for within and between our groups, or neighborhoods. Different types of outcome variables, and different outcome distribution allow imply different sources of variation within the model. For example, if we were to assume our outcome was Normally distrusted, then the model above would be written as:

\[y_{ij} = \beta_{0j} +\sum_k \beta_k x_{kij} + e_i\]

Where we have the \(e_i\) term, as in the ordinary least squares model, which measures the individual level variation not accounted for by the model parameters, or the residual. In this model specification, this \(e_i\) term has it’s own variance, \(\sigma^2_e\), or the residual variance. There is a second variance term, as shown in the previous section, that measures the variation between our higher-level units, \(\sigma^2_u\), or the between group variance.

This implies that the total variation, \(\sigma^2_y\) in the outcome, for a model assuming a Normal distribution for the outcome comes from two sources, the between group variance and the person-level variance:

\[\sigma^2_y = \sigma^2_e +\sigma^2_u\]

In multi-level models, a quantity called the Intraclass correlation coefficient, or ICC is commonly calculated using these variance components. The ICC is considered a measure of correlation within higher level units. In other words, it measures the degree of similarity between two randomly selected respondents within a given, randomly selected neighborhood. An example of this would be, if we wanted to know how similar you were to one of your neighbors in your neighborhood, on average. As a general rule, the larger the between-group variance, the greater the ICC.

\[\text{ICC} = \frac{\sigma^2_u}{\sigma^2_e +\sigma^2_u}\]

The ICC is bound between 0 and 1, with higher values implying greater similarity within our higher level units. For example and ICC of .5 (which is large for an ICC) would imply that you and a randomly selected one of your neighbors in your neighborhood would be pretty strongly correlated, while an ICC of .01, would imply a very low degree of similarity between you and your neighbors.

If you are doing a multi-level logistic regression model the variance terms are different. Since the binomial distribution, assumed by the logistic regression model, only has one parameter, and the variance and mean of the distribution are strongly related, the multi-level logistic model has a different individual-level variance term, that is actually a constant. In the binomial model, the ICC is:

\[\text{ICC} = \frac{\sigma^2_u}{\frac{\pi^2}{3} +\sigma^2_u}\]

The term \(\frac{\pi^2}{3}\) is the variance in the logistic distribution, implied by the model, and is a constant (Austin and Merlo, 2017).

If a Poisson multi-level model is used, then the individual level variance is actually 1, and the ICC is:

\[\text{ICC} = \frac{\sigma^2_u}{1 +\sigma^2_u}\] The individual level variance is 1 in the Poisson model, owing to the assumption of that model that the mean and variance of the distribution are the same.

Practical rules of thumb for choosing models

There are differences between these classic ANOVA model and the linear mixed model. As a rule, you use the fixed-effects models when:

  • You know that each group is regarded as unique, and you want to draw conclusions on each of these specific groups, and you also know all the groups a priori e.g. sex or race

  • If the groups can be considered as a sample from some (real or hypothetical) population of groups, such as our MSA example, and you want to draw conclusions about this population of groups, then the random effects model is appropriate.

WHY? because if you have a LARGE number of groups, say \(n_j\) > 10, then the odds that you are really interested in all possible difference in the means is probably pretty low, and the model has lots of parameters that you do not really care about.

Multi-level data sources

Before we move forward into actually seeing how to use R to estimate multi-level models, we must state a caveat. Not all questions that you may come up with involve multi-level propositions, nor do all types of data necessarily have the required elements to do a traditional multi-level analysis, from a spatial demographic perspective, or the data necessary to do a place-focused type of model may only be available in restricted-use versions of publicly available data.

Some examples of public-use data with place-based higher level units identified are:

  • ECLS-K 1998 and 2011 (School identifier)
  • BRFSS many years (pre 2014 MSA identifier, post 2014, MSA identifier)
  • ACS microdata (PUMA, MSA, State)
  • Demographic and Health Survey, many countries, many years (Region, GPS coordinate for sampling units)

While many other data sources also allow for the types of models we are describing here, these are widely used.

Other data sources that do not allow for place-based multi-level models in their public use data, but do allow for it in the restricted use data are:

  • National Health and Nutrition Examination Survey (NHANES)
  • National Health Interview Survey (NHIS)
  • National Longitudinal Study of Adolescent to Adult Health (AddHealth)
  • Panel Study of Income Dynamics (PSID)
  • National Longitudinal Study of Youth (NLSY)

Using R to estimate multi-level models

In R there are several libraries that can be used to estimate multi-level models. The lme4 library provides a current and continuously developed framework for estimating the types of models we are considering, with options for several different distributions for handling continuous, discrete and count outcomes.

The primary function, depending on how your outcome is measured, will either be lmer() for Normally distributed outcomes, or glmer() for count and binary outcomes. Syntax for the general models are very similar to other R functions for regression we have seen in this course.

For example, if our outcome is binary (0/1), and is called y and we have one individual level predictor, x_1, and our grouping variable is called place, and our dataset is called mydata, then our model would look like this:

glmer(y ~ x_1 + (1|place), data=mydata, family=binomial)

The syntax (1|place) tells R that we want to consider a random intercept term for each place in the data. The 1 indicates that we are specifying a constant for each place, just like in a regular regression model, the intercept is estimated by the computer generating a vector of 1’s as the first element in the design matrix.

In the next section, we will use R to analyze an outcome from the 2016 Behavioral Risk Factor Surveillance System SMART MMSA(BRFSS) data.

The BRFSS data are a nationally representative phone survey designed to measure national and local trends in many health outcomes and morbidities, and the use of health resources. The BRFSS has been collected annually since 1984. The SMART data file, is a subset of the larger BRFSS data file, which identifies the metropolitan statistical area where each survey respondent lives.

#load brfss
library(car)
library(stargazer)
library(survey)
library(sjPlot)
library(ggplot2)
library(pander)
library(knitr)
library(tidycensus)
library(dplyr)
load(url("https://github.com/coreysparks/data/blob/master/brfss_2017.Rdata?raw=true"))

set.seed(12345)
#samps<-sample(1:nrow(brfss_17), size = 40000, replace=F)
#brfss_17<-brfss_17[samps,]
#The names in the data are very ugly, so I make them less ugly
nams<-names(brfss_17)
#we see some names are lower case, some are upper and some have a little _ in the first position. This is a nightmare.

newnames<-gsub(pattern = "_",
               replacement =  "",
               x =  nams)

names(brfss_17)<-tolower(newnames)

Recode variables

#sex
brfss_17$male<-ifelse(brfss_17$sex==1, 1, 0)

#BMI
brfss_17$bmi<-ifelse(is.na(brfss_17$bmi5)==T, NA, brfss_17$bmi5/100)

#Healthy days
brfss_17$healthdays<-Recode(brfss_17$physhlth, recodes = "88=0; 77=NA; 99=NA")

#Healthy mental health days
brfss_17$healthmdays<-Recode(brfss_17$menthlth, recodes = "88=0; 77=NA; 99=NA")

brfss_17$badhealth<-Recode(brfss_17$genhlth, recodes="4:5=1; 1:3=0; else=NA")
#race/ethnicity
brfss_17$black<-Recode(brfss_17$racegr3, recodes="2=1; 9=NA; else=0")
brfss_17$white<-Recode(brfss_17$racegr3, recodes="1=1; 9=NA; else=0")
brfss_17$other<-Recode(brfss_17$racegr3, recodes="3:4=1; 9=NA; else=0")
brfss_17$hispanic<-Recode(brfss_17$racegr3, recodes="5=1; 9=NA; else=0")

brfss_17$race_eth<-Recode(brfss_17$racegr3, 
recodes="1='nhwhite'; 2='nh black'; 3='nh other';4='nh multirace'; 5='hispanic'; else=NA",
as.factor = T)
brfss_17$race_eth<-relevel(brfss_17$race_eth, ref = "nhwhite")

#insurance
brfss_17$ins<-Recode(brfss_17$hlthpln1, recodes ="7:9=NA; 1=1;2=0")

#income grouping
brfss_17$inc<-Recode(brfss_17$incomg, recodes = "9= NA;1='1_lt15k'; 2='2_15-25k';3='3_25-35k';4='4_35-50k';5='5_50kplus'", as.factor = T)
brfss_17$inc<-as.ordered(brfss_17$inc)
#education level
brfss_17$educ<-Recode(brfss_17$educa,
recodes="1:2='0Prim'; 3='1somehs'; 4='2hsgrad'; 5='3somecol'; 6='4colgrad';9=NA",
as.factor=T)
brfss_17$educ<-relevel(brfss_17$educ, ref='2hsgrad')

#employment
brfss_17$employ<-Recode(brfss_17$employ1,
recodes="1:2='employloyed'; 2:6='nilf'; 7='retired'; 8='unable'; else=NA",
as.factor=T)
brfss_17$employ<-relevel(brfss_17$employ, ref='employloyed')

#marital status
brfss_17$marst<-Recode(brfss_17$marital,
recodes="1='married'; 2='divorced'; 3='widowed'; 4='separated'; 5='nm';6='cohab'; else=NA",
as.factor=T)
brfss_17$marst<-relevel(brfss_17$marst,
                        ref='married')

#Age cut into intervals
brfss_17$agec<-cut(brfss_17$age80,
                   breaks=c(0,24,39,59,79,99))

#BMI, in the brfss_17a the bmi variable has 2 implied decimal places,
#so we must divide by 100 to get real bmi's

brfss_17$bmi<-brfss_17$bmi5/100

#smoking currently
brfss_17$smoke<-Recode(brfss_17$smoker3, 
recodes="1:2=1; 3:4=0; else=NA")
#brfss_17$smoke<-relevel(brfss_17$smoke, ref = "NeverSmoked")

brfss_17$obese<-ifelse(is.na(brfss_17$bmi)==T, NA, 
                       ifelse(brfss_17$bmi>30,1,0))

I want to see how many people we have in each MSA in the data:

#Now we will begin fitting the multilevel regression model with the msa
#that the person lives in being the higher level
head(data.frame(name=table(brfss_17$mmsaname), 
                id=unique(brfss_17$mmsa)))
#people within each msa

#How many total MSAs are in the data?
length(table(brfss_17$mmsa))
## [1] 136
#MSAs

Higher level predictors

We will often be interested in factors at both the individual AND contextual levels. To illustrate this, I will use data from the American Community Survey measured at the MSA level. Specifically, I use the DP3 table, which provides economic characteristics of places, from the 2010 5 year ACS Link.

To measure macro level variables, I will include some Census variables from the ACS 2011 5 Year estimates load in ACS data from tidycensus. The first set of variables includes information on the economic conditions of the MSA, specifically poverty and unemployment.

usacs<-get_acs(geography = "metropolitan statistical area/micropolitan statistical area", year = 2011,
                variables=c( "DP05_0001E",
                             "DP03_0062E",
                             "DP04_0003PE") ,
                summary_var = "B01001_001",
                geometry = F,
               output = "wide")
## Getting data from the 2007-2011 5-year ACS
## Using the ACS Data Profile
usacs<-usacs%>%
  mutate(totpop= DP05_0001E,
         medhhinc=DP03_0062E,
         pvacant=DP04_0003PE/100)%>%
  dplyr::select(GEOID,NAME, totpop, medhhinc, pvacant)


head(usacs)

I also have segregation measures at the MSA level that I made here, I will merge these in too.

Clean and standardize contextual data

myscale<-function(x){as.numeric(scale(x))}
usacs<-usacs %>%
  mutate_at(c( "medhhinc", "pvacant"),myscale)

merged<-usacs%>%
  filter(complete.cases(.))
head(merged)

Now, I merge the data back to the individual level data:

merged<-merge(x=brfss_17,
              y=merged,
              by.x="mmsa",
              by.y="GEOID",
              all.x=F)

Let’s see the geographic variation in these economic indicators:

library(tigris)
## To enable 
## caching of data, set `options(tigris_use_cache = TRUE)` in your R script or .Rprofile.
msa<-core_based_statistical_areas(cb=T)
msa_ec<-geo_join(msa,
                 usacs, "CBSAFP", "GEOID", how="inner")
library(RColorBrewer)
library(tmap)
## Warning: package 'tmap' was built under R version 4.0.5
tm_shape(msa_ec)+
  tm_polygons("pvacant",
              style="quantile",
              n=5,
              legend.hist = TRUE) +
   tm_layout(legend.outside = TRUE,
             title = "% Vacant Housing") 
## Warning: package 'sf' was built under R version 4.0.5
## Linking to GEOS 3.9.0, GDAL 3.2.1, PROJ 7.2.1
## Variable(s) "pvacant" contains positive and negative values, so midpoint is set to 0. Set midpoint = NA to show the full spectrum of the color palette.

## [1] "#FEE695" "#FEEC9F" "#FEF5AF" "#FFFFBF" "#40AA59"
tm_shape(msa_ec)+
  tm_polygons("medhhinc",
              style="quantile",
              n=5,
              legend.hist = TRUE) +
   tm_layout(legend.outside = TRUE,
             title = "Median Household Income") 
## Variable(s) "medhhinc" contains positive and negative values, so midpoint is set to 0. Set midpoint = NA to show the full spectrum of the color palette.

## [1] "#FDB869" "#FEE390" "#FFFFBF" "#B5DF73" "#40AA59"

Merge the MSA data to the BRFSS data

merged$bmiz<-as.numeric(scale(merged$bmi,
                              center=T,
                              scale=T))
#merged<-merged[complete.cases(merged[, c("bmiz", "race_eth", "agec", "educ", "gini")]),]
#and merge the data back to the kids data

merged<-merged%>%
  dplyr::select(bmiz, obese, mmsa, agec, educ, race_eth,smoke, healthmdays, badhealth,bmi,medhhinc,pvacant, male, mmsawt, mmsaname )%>%
  filter(complete.cases(.))


head(merged[, c("bmiz", "male", "agec", "educ","medhhinc", "pvacant", "mmsa")])
meanbmi<-mean(merged$bmi, na.rm=T)

sdbmi<-sd(merged$bmi, na.rm=T)

As a general rule, I will do a basic fixed-effects ANOVA as a precursor to doing full multi-level models, just to see if there is any variation amongst my higher level units (groups). If I do not see any variation in my higher level units, I generally will not proceed with the process of multi-level modeling.

fit.an<-lm(bmiz~as.factor(mmsa),
           merged)
anova(fit.an)

use glm() for non-normal outcomes

fit.ob<-glm(obese~as.factor(mmsa),
            family=binomial,
            merged)

anova(fit.ob, test="Chisq")

So we see significant variation in our outcomes across the higher level units.

Now we fit the hierarchical model

library(lme4)
library(lmerTest)
## Warning: package 'lmerTest' was built under R version 4.0.5
library(arm)

Basic hierarchical model for means of each MSA:

fit<-lmer(bmiz~(1|mmsa),
           data=merged)
arm::display(fit,
             detail=T)
## lmer(formula = bmiz ~ (1 | mmsa), data = merged)
##             coef.est coef.se t value
## (Intercept) 0.02     0.01    2.15   
## 
## Error terms:
##  Groups   Name        Std.Dev.
##  mmsa     (Intercept) 0.09    
##  Residual             1.00    
## ---
## number of obs: 159429, groups: mmsa, 118
## AIC = 451514, DIC = 451492.6
## deviance = 451500.3
merged$predbmi<-sdbmi*(fitted(fit))+meanbmi

head(ranef(fit)$mmsa)
dim(ranef(fit)$mmsa)
## [1] 118   1
rate<- sdbmi*(fixef(fit)+ranef(fit)$mmsa)+meanbmi
est<-data.frame(rate =rate, id=rownames(ranef(fit)$mmsa))
head(est)
msa_ec<-merge(msa_ec, est,
              by.x="CBSAFP", by.y="id")

tm_shape(msa_ec)+
  tm_polygons("X.Intercept.",
              style="quantile",
              n=5,
              legend.hist = TRUE) +
   tm_layout(legend.outside = TRUE,
             title = "Estimated BMI") 

## [1] "#FFF8C4" "#FEDE86" "#FEAA38" "#EA6E13" "#B74202"
citymeans<-aggregate(cbind(bmi, predbmi)~mmsaname,merged, mean)
head(citymeans, n=10)
plot(predbmi~bmi, citymeans)

Model with individual level predictors:

fit2<-lmer(bmiz~male+agec+educ+(1|mmsa),
           data=merged,
           na.action=na.omit)
arm::display(fit2, detail=T)
## lmer(formula = bmiz ~ male + agec + educ + (1 | mmsa), data = merged, 
##     na.action = na.omit)
##              coef.est coef.se t value
## (Intercept)   -0.40     0.01  -30.41 
## male           0.08     0.00   15.71 
## agec(24,39]    0.45     0.01   39.13 
## agec(39,59]    0.61     0.01   55.81 
## agec(59,79]    0.51     0.01   47.55 
## agec(79,99]    0.12     0.01    8.84 
## educ0Prim      0.06     0.02    3.21 
## educ1somehs    0.03     0.01    2.35 
## educ3somecol  -0.01     0.01   -1.84 
## educ4colgrad  -0.22     0.01  -34.45 
## 
## Error terms:
##  Groups   Name        Std.Dev.
##  mmsa     (Intercept) 0.08    
##  Residual             0.98    
## ---
## number of obs: 159429, groups: mmsa, 118
## AIC = 445383, DIC = 445202.6
## deviance = 445280.6

We do a likelihood ratio test to see if our individual level variables are explaining anything about out outcome:

anova(fit, fit2)
## refitting model(s) with ML (instead of REML)

They do.

We also typically would test to see if the random effect term is significant, SAS pumps out a test of this, so we do the same kind of thing in R

rand(fit2)

Which shows significant variation in average BMI across MSAs.

Some may be interested in getting the intra-class correlation coefficient. While I don’t usually pay attention to this, here it is:

library(sjstats); library(sjPlot)
## 
## Attaching package: 'sjstats'
## The following object is masked from 'package:survey':
## 
##     cv
icc(fit2)
## Warning: 'icc' is deprecated.
## Use 'performance::icc()' instead.
## See help("Deprecated")
## # Intraclass Correlation Coefficient
## 
##      Adjusted ICC: 0.006
##   Conditional ICC: 0.006
plot_model(fit,
           type = "re",
           sort.est="sort.all",
           grid=F)
## Warning: `select_vars()` was deprecated in dplyr 0.8.4.
## Please use `tidyselect::vars_select()` instead.

So less than 1% of the variance in BMI is due to difference between MSAs. That’s not much, but according to our random effect testing, it’s not, statistically speaking, 0.

Pooling of estimates

It may be informative to plot the estimated BMI’s for each MSA from the OLS and multilevel models. This section illustrates the effects of “pooling” as Gelman & Hill ch 12.

#these models are good for estimating group means better than traditional methods
#this follows the examples in chapter 12 of Gelman and Hill, I stole the code directly from them.

#complete pooling, this model fits the grand mean ONLY
fit.cp<-lm(bmi~1, merged)
display(fit.cp)
## lm(formula = bmi ~ 1, data = merged)
##             coef.est coef.se
## (Intercept) 28.11     0.02  
## ---
## n = 159429, k = 1
## residual sd = 6.26, R-Squared = 0.00
#No pooling i.e. fixed effects regression, this model fits separate means for each MSA using OLS
lm.unpooled<-lm(bmi~factor(mmsa)-1, merged)


#partial pooling, this model fits the population mean and MSA deviations using multilevel models
fit0<-lmer(bmi~1+(1|mmsa), merged)

#partial pooling with covariate
fit0.1<-lmer(bmi~medhhinc+pvacant+(1|mmsa), merged)

Plot the means of the counties

mmsas<-unique(merged$mmsa)
J<-length(unique(merged$mmsa))
ns<-as.numeric(table(brfss_17$mmsa[brfss_17$mmsa%in%mmsas]))
sample.size <- as.numeric(table(brfss_17$mmsa[brfss_17$mmsa%in%mmsas]))
sample.size.jittered <- sample.size*exp (runif (J, -.1, .1))

par (mar=c(5,5,4,2)+.1)
plot (sample.size.jittered, 
      coef(lm.unpooled), cex.lab=1.2, cex.axis=1.2,
      xlab="sample size in MSA j", ylab=expression (paste ("est. intercept, ", alpha[J], "   (no pooling)")),
      pch=20, log="x", ylim=c(25, 30), yaxt="n", xaxt="n")
axis (1, quantile(ns), cex.axis=1.1)
axis (2, seq(25, 30), cex.axis=1.1)
for (j in 1:J){
  lines (rep(sample.size.jittered[j],2),
         coef(lm.unpooled)[j] + c(-1,1)*se.coef(lm.unpooled)[j], lwd=.5)
}
abline (coef(fit.cp)[1], 0, lwd=.5)
title(main="Estimates of MSA Means from the Fixed Effect Model")

Plot MLM estimates of MSA means + se’s

par (mar=c(5,5,4,2)+.1)
a.hat.M1 <- coef(fit0)$mmsa[,1]
a.se.M1 <- se.coef(fit0)$mmsa

plot (as.numeric(ns), t(a.hat.M1), cex.lab=1.2, cex.axis=1.1,
      xlab="sample size in MSA j",
      ylab=expression (paste("est. intercept, ", alpha[j], "(multilevel model)")),
      pch=20, log="x", ylim=c(25, 30), yaxt="n", xaxt="n")
axis (1, quantile(ns), cex.axis=1.1)
axis (2, seq(25,30), cex.axis=1.1)
for (j in 1:length(unique(merged$mmsa))){
  lines (rep(as.numeric(ns)[j],2),
         as.vector(a.hat.M1[j]) + c(-1,1)*a.se.M1[j], lwd=.5, col="gray10")
}
abline (coef(fit.cp)[1], 0, lwd=.5)
title(main="Estimates of MSA Means from the MLM")

Plot MLM estimates of MSA means + se’s, model with MSA covariates

par (mar=c(5,5,4,2)+.1)
a.hat.M2 <- coef(fit0.1)$mmsa[,1]
a.se.M2 <- se.coef(fit0.1)$mmsa

plot (as.numeric(ns), t(a.hat.M2), cex.lab=1.2, cex.axis=1.1,
      xlab="sample size in MSA j",
      ylab=expression (paste("est. intercept, ", alpha[j], "(multilevel model with covariates)")),
      pch=20, log="x", ylim=c(25, 30), yaxt="n", xaxt="n")
axis (1, quantile(ns), cex.axis=1.1)
axis (2, seq(25,30), cex.axis=1.1)
for (j in 1:length(unique(merged$mmsa))){
  lines (rep(as.numeric(ns)[j],2),
         as.vector(a.hat.M2[j]) + c(-1,1)*a.se.M2[j], lwd=.5, col="gray10")
}
abline (coef(fit.cp)[1], 0, lwd=.5)
title(main="Estimates of MSA Means from the MLM with MSA predictors")

#This plot shows that as the n_j goes down, the standard error of the estimate increases
qplot(y=se.coef(lm.unpooled), x=coef(lm.unpooled), size=sqrt(ns))

#again, we see the relationship between variance and n_j
qplot(y=as.numeric(a.se.M1),x=se.coef(lm.unpooled),color=sqrt(ns))

LS0tDQp0aXRsZTogIkRFTSA1MjgzLzcyODMgLSBNdWx0aS1sZXZlbCBNb2RlbHMgRXhhbXBsZSAxIg0KYXV0aG9yOiAiQ29yZXkgU3BhcmtzLCBQaEQiDQpkYXRlOiAiYHIgZm9ybWF0KFN5cy50aW1lKCksICclZCAlQiwgJVknKWAiDQpvdXRwdXQ6DQogICBodG1sX2RvY3VtZW50Og0KICAgIGRmX3ByaW50OiBwYWdlZA0KICAgIGZpZ19oZWlnaHQ6IDcNCiAgICBmaWdfd2lkdGg6IDcNCiAgICB0b2M6IHllcw0KICAgIHRvY19mbG9hdDogeWVzDQogICAgY29kZV9kb3dubG9hZDogdHJ1ZQ0KLS0tDQoNCg0KIyMgQSBGdW5kYW1lbnRhbCBwcm9ibGVtIG9mIG5hbWVzIA0KDQpCZWZvcmUgd2UgYmVnaW4gb3VyIGRpc2N1c3Npb24gb2YgbXVsdGktbGV2ZWwgZGF0YSwgd2UgbXVzdCBmaXJzdCBjbGFyaWZ5IHNvbWUgc2VtYW50aWNzLiBUaGUgbW9kZWxzIHdlIGFyZSBnb2luZyB0byBiZSBkZXNjcmliaW5nIGFuZCB1c2luZyBpbiB0aGlzIGFuZCB0aGUgZm9sbG93aW5nIGxlc3NvbiBnbyBieSBhIHZhcmlldHkgb2YgZGlmZmVyZW50IG5hbWVzLCBkZXBlbmRpbmcgb24gdGhlIGRpc2NpcGxpbmFyeSB0cmFkaXRpb24geW91IG1heSBjb21lIGZyb20uIFRvIGNsYXJpZnksIHRoZXNlIG1vZGVscyBhbGwgZm9sbG93IGNvbW1vbiBmb3JtcywgYnV0IG5hbWVzIG1heSBiZSB2YXJ5LiANCg0KVGhyZWUgbmFtZXMgdGhhdCBhcmUgY29tbW9ubHkgdXNlZCBmb3IgdGhlc2UgbW9kZWxzIGFyZToNCg0KLSBNaXhlZCBlZmZlY3RzIG1vZGVscw0KLSBIaWVyYXJjaGljYWwgbW9kZWxzDQotIFJhbmRvbSBlZmZlY3RzIG1vZGVscw0KDQpXZSB3aWxsIHNlZSBsYXRlciB3aHkgdGhlc2UgbmFtZXMgYXJlIGltcG9ydGFudCBpbiBzcGVjaWZpYyBjb250ZXh0cywgYnV0IGZvciBub3csIGl0IGlzIHN1ZmZpY2llbnQgdG8gc2F5IHRoYXQgdGhlc2UgYXJlIGFsbCB0aGUgc2FtZSBtb2RlbCwgYW5kIHRoZXkgYWxsIHJlZmVyIHRvIHRoZSBzYW1lIHN1aXRlIG9mIG1vZGVscywgYnV0IGRpZmZlcmVudCBkaXNjaXBsaW5lcy9hdXRob3JzL2FwcGxpY2F0aW9ucyBoYXZlIG1hbmFnZWQgdG8gY29uZnVzZSB1cyBhbGwuDQoNCg0KDQojIyBTb21lIHBlcnNwZWN0aXZlcyBpbiBNdWx0aS1sZXZlbCBNb2RlbGluZyANCg0KRm9sbG93aW5nIGZyb20gcHJldmlvdXMgbGVzc29ucywgd2l0aGluIHNwYXRpYWwgZGVtb2dyYXBoeSwgdGhlcmUgYXJlIG1hbnkgZGlmZmVyZW50IHR5cGVzIG9mIHBlcnNwZWN0aXZlcyB0aGF0IGFyZSB1c2VkIHdoZW4gYXNraW5nIHF1ZXN0aW9ucy4gUmVnYXJkbGVzcyBvZiB0aGUgc3BlY2lmaWMgZGlzY2lwbGluYXJ5IHRyYWRpdGlvbiB0aGF0IHlvdSBtYXkgY29tZSBmcm9tLCBhbGwgb2YgdGhlc2UgcGVyc3BlY3RpdmVzIGF0dGVtcHQgdG8gc2l0dWF0ZSBodW1hbnMgd2l0aGluIHNvbWUgY29udGV4dHVhbCBsZXZlbCB0aGF0IGlzIGFzc3VtZWQgdG8gZWl0aGVyIGluZmx1ZW5jZSBvciBiZSBpbmZsdWVuY2VkIGJ5IHRoZWlyIGFjdGlvbnMgYW5kIGJlaGF2aW9ycy4NCg0KRm9sbG93aW5nIHRoZSBsZXNzb25zIHdpdGhpbiB0aGlzIGNvdXJzZSwgd2UgaGF2ZSBkaXNjdXNzZWQgaG93IHZhcmlvdXMgbWVhc3VyZXMgb2YgY29udGV4dCBtYXR0ZXIgZm9yIGh1bWFuIGhlYWx0aCBhbmQgZWNvbm9taWMgYWN0aXZpdGllcywgYW5kIHRoZXNlIGFyZSBhbGwgdmVyeSB2YWxpZCB3aGVuIGNvbnNpZGVyaW5nIHRoZSB1c2Ugb2YgbXVsdGktbGV2ZWwgbW9kZWxzLiANCg0KSW4gZ2VuZXJhbCwgYSBtdWx0aS1sZXZlbCBmcmFtZXdvcmsgZm9yIGFueSBhbmFseXNpcyB3aWxsIGJlIGludGVyZXN0ZWQgaW4gYXNraW5nIHF1ZXN0aW9ucyBhYm91dCBvdXRjb21lcyB0aGF0IGFyZSBjbHVzdGVyZWQgYnkgZWl0aGVyIHNwYWNlIG9yIHRpbWUgb3Igc29tZSBvdGhlciBsaW5raW5nIGNoYXJhY3RlcmlzdGljLCBzdWNoIGFzIGNvaG9ydCBvZiBiaXJ0aCBvciBwZXJpb2Qgb2YgbGlmZS4gDQoNClRoZSBwcm9jZXNzZXMgdGhhdCBhZmZlY3QgYW4gb3V0Y29tZSB3aXRoaW4gYSBtdWx0aS1sZXZlbCBmcmFtZXdvcmsgYXJlIHRob3VnaHQgdG8gYmUgb3BlcmF0aW5nIGF0IGJvdGggdGhlIGluZGl2aWR1YWwgbGV2ZWwgKHBlcnNvbiBsZXZlbCkgYW5kIGF0IHNvbWUgb3RoZXIgc3RydWN0dXJhbCBsZXZlbCBvZiBleGlzdGVuY2UuIFRoZXNlIHN0cnVjdHVyYWwgbGV2ZWxzIGNhbiBiZSBkZWZpbmVkIGluIGEgdmFyaWV0eSBvZiB3YXlzLCBidXQgYWdhaW4sIGZvbGxvd2luZyB3aGF0IHdlIGhhdmUgY292ZXJlZCBwcmV2aW91c2x5LCB0aGUgc3RydWN0dXJhbCBsZXZlbHMgY29tbW9ubHkgYWRkcmVzc2VkIGluIHNwYXRpYWwgZGVtb2dyYXBoeSBhcmUgdGhvc2Ugb2YgdGhlIGhvdXNlaG9sZCwgbmVpZ2hib3Job29kLCBzb2NpYWwgbmV0d29yaywgcmVzaWRlbnRpYWwgbG9jYXRpb24sIG9yIG90aGVyIGxvY2F0aW9uYWwgZGVmaW5pdGlvbi4gVGhlIHByb2Nlc3NlcyBvcGVyYXRpbmcgYXQgdGhlc2UgbGV2ZWxzIGFyZSBhbHNvIGJlbGlldmVkIHRvIGJlIGNhdXNhbCB0byBzb21lIGRlZ3JlZSwgbWVhbmluZyB0aGF0IHRoZXkgYXJlIHRob3VnaHQgdG8gY2F1c2UgdGhlIG91dGNvbWUsIG9yIGF0IGxlYXN0IHdlIGNhbiBjb25zdHJ1Y3QgYW4gYXJndW1lbnQgYWJvdXQgaG93IHRoZXNlIHByb2Nlc3NlcyAqKl9jb3VsZF8qKiBjYXVzZSB0aGUgb3V0Y29tZS4gDQoNCkZpbmFsbHksIGFueSBtdWx0aWxldmVsIHBlcnNwZWN0aXZlIGhhcyBhdCBpdHMgY29yZSBhbiBpbnRlcmVzdCBpbiBkZXNjcmliaW5nIHRoZSB2YXJpYXRpb24gd2l0aGluIHRoZSBwb3B1bGF0aW9uIHRoYXQgaXMgYXR0cmlidXRhYmxlIHRvIHRoZSBkaWZmZXJlbmNlcyBiZXR3ZWVuIHRoZXNlIGNvbnRleHR1YWwsIG9yIHN0cnVjdHVyYWwgbGV2ZWxzLiBNb3Jlb3ZlciwgdGhlIGludGVyZXN0IGluIHRoZSB2YXJpYXRpb24gYmV0d2VlbiB0aGVzZSBjb250ZXh0cyBwcmVzZW50cyBzb21ldGhpbmcgdGhhdCBpcyB3b3J0aCBrbm93aW5nIGFib3V0IGFuZCBhZGRyZXNzaW5nIGJleW9uZCBzaW1wbHkgZm9jdXNpbmcgb24gdGhlIGluZGl2aWR1YWwuDQoNCg0KIyMgTXVsdGktbGV2ZWwgZGF0YSBzdHJ1Y3R1cmUgDQoNCk1vc3Qgc3RhdGlzdGljYWwgbW9kZWxzIGFzc3VtZSB0aGF0IHRoZSBkYXRhIHdlIHB1dCBpbnRvIHRoZW0gYXJlIGluZGVwZW5kZW50IG9mIG9uZSBhbm90aGVyLCBtZWFuaW5nIHRoZSBpbmRpdmlkdWFsIHJlc3BvbnNlcyBpbiBzYW1wbGUgdGhhdCBpcyByZXByZXNlbnRlZCBieSB0aGUgZGF0YSBhcmUgbm90IHJlbGF0ZWQgdG8gb25lIGFub3RoZXIgaW4gc29tZSBmYXNoaW9uLiBUaGluZ3MgdGhhdCBjYW4gdmlvbGF0ZSB0aGlzIGFzc3VtcHRpb24sIGFzIHdlIGhhdmUgc2VlbiBhbHJlYWR5IGluIHRoaXMgY291cnNlLCBhcmUgc3BhdGlhbCBjbG9zZW5lc3MsIG9yLCBhcyBpdCBvZnRlbiBpcyBpbiBtdWx0aS1sZXZlbCBkYXRhLCBuZWlnaGJvcmhvb2Qgb3IgcGxhY2UtYmFzZSBjby1yZXNpZGVuY2UuIEJ5IGNvLXJlc2lkZW5jZSwgd2Ugc2ltcGx5IG1lYW4gdGhhdCBwZW9wbGUgbGl2ZSBpbiB0aGUgc2FtZSBhcmVhLCBob3dldmVyIHRoYXQgaXMgZGVmaW5lZC4gDQoNCkFzIHdlIGhhdmUgYWxyZWFkeSBkaXNjdXNzZWQgaW4gdGhpcyBjb3Vyc2UsIGFjY29yZGluZyB0byBUb2JsZXIncyBsYXcsIHRoaW5ncyB0aGF0IGFyZSBjbG9zZSB0b2dldGhlciBhcmUgbW9yZSBhbGlrZSB0aGFuIHRoaW5ncyB0aGF0IGFyZSBmYXIgYXBhcnQuIFNvLCBpZiB0d28gb3IgbW9yZSBwZW9wbGUgYXJlIHNhbXBsZWQgZnJvbSBhIGdpdmVuIG5laWdoYm9yaG9vZCwgb3IgcGxhY2UsIHRoZXkgbWF5IGJlIGF0IGxlYXN0IGNvcnJlbGF0ZWQgd2l0aCBvbmUgYW5vdGhlciBiZWNhdXNlIHRoZXkgc2hhcmUgYSBzaW1pbGFyIHJlc2lkZW50aWFsIGxvY2F0aW9uLiANCg0KSW4gbW9zdCBwb3B1bGF0aW9uLWJhc2VkIHN1cnZleXMsIHBlb3BsZSBhcmUgc2FtcGxlZCBpbiBhIG5vbi1yYW5kb20gZmFzaGlvbiwgZGVzcGl0ZSB3aGF0IHdlIGxlYXJuIGluIG91ciBpbnRyb2R1Y3Rvcnkgc3RhdGlzdGljcyBib29rcy4gVGhpcyBpcyBiZWNhdXNlIGl0IGNhbiBiZSBtdWNoIG1vcmUgY29zdCBlZmZlY3RpdmUgdG8gY2FwdHVyZSBhIHBvcHVsYXRpb24gc2FtcGxlIHdpdGhpbiBhIHNtYWxsIGFyZWEuIFRoZXNlIGFyZWFzIG1heSBiZSBjYWxsZWQgKipfY2x1c3RlcnNfKiogb3IgKipfcHJpbWFyeSBzYW1wbGluZyB1bml0c18qKiwgYW5kIHlvdSBtYXkgaGF2ZSBzZWVuIHRoZXNlIHRlcm1zIGJlZm9yZSBpbiBvdGhlciBhbmFseXNlcyB5b3UgaGF2ZSBkb25lLiBNYW55IHN1cnZleXMgaWRlbnRpZnkgdGhlc2UgY2x1c3RlcnMgd2l0aGluIHRoZWlyIGRhdGEgY29kZSBib29rcywgc28gdGhhdCB5b3UgY2FuIHVzZSB0aGlzIGluZm9ybWF0aW9uIGluIHN0YXRpc3RpY2FsIGFuYWx5c2VzIHlvdSBtYXkgZG8uIE9mdGVuIHRoZXNlIGNsdXN0ZXJzIGFyZSBuZXN0ZWQgd2l0aGluIG90aGVyIGFyZWFzIGtub3duIGFzICoqX3N0cmF0YV8qKiB3aGljaCByZXByZXNlbnQgYSBsYXJnZXIgc3ViZGl2aXNpb24gb2Ygc3BhY2Ugb3Igc29tZSBzb3J0IG9mIGFkbWluaXN0cmF0aXZlIGFyZWEuIEZvciBleGFtcGxlLCBhIHNjaG9vbCBkaXN0cmljdCBtYXkgc2VydmUgYXMgYSBzYW1wbGUgc3RyYXR1bSwgYW5kIHRoZSBzY2hvb2xzIHdpdGhpbiBpdCBtYXkgc2VydmUgYXMgcHJpbWFyeSBzYW1wbGluZyB1bml0cywgb3IgY2x1c3RlcnMuIFRoaXMgd291bGQgcmVwcmVzZW50IGEgKipfdHdvLXN0YWdlXyoqIHNhbXBsZSBkZXNpZ24sIHdpdGggdGhlIGRpc3RyaWN0cyByZXByZXNlbnRpbmcgdGhlIGZpcnN0IHN0YWdlIG9mIHNhbXBsaW5nIGFuZCB0aGUgc2Nob29scyBiZWluZyB0aGUgc2Vjb25kIHN0YWdlLiBXZSBjb3VsZCBoYXZlIGEgdGhpcmQgc3RhZ2Ugd2hlcmUgY2xhc3Nyb29tcyBhcmUgc2FtcGxlZCB3aXRoaW4gc2Nob29scywgZm9yIGluc3RhbmNlLiBBIHBvcHVsYXIgbG9uZ2l0dWRpbmFsIHN1cnZleSwgdGhlIFtFYXJseSBDaGlsZGhvb2QgTG9uZ2l0dWRpbmFsIFN1cnZleSAtIEtpbmRlcmdhcnRlbiBjb2hvcnQsIDE5OTggYW5kIDIwMTFdKGh0dHBzOi8vbmNlcy5lZC5nb3YvZWNscy8pIGZvbGxvdyB0aGlzIHR5cGUgb2Ygc2FtcGxpbmcgc3RyYXRlZ3kuIA0KDQpXaGVuIGRvaW5nIGFueSBhbmFseXNpcyBvZiBkYXRhIHRoYXQgYXJlIHNhbXBsZWQgaW4gdGhpcyBraW5kIG9mIG5lc3RlZCBmYXNoaW9uLCB3ZSBtdXN0IGJlIGNhcmVmdWwsIGJlY2F1c2UgdGhlIG9ic2VydmF0aW9ucyBhdCBhbnkgb2YgdGhlc2UgbGV2ZWxzIGNvdWxkIGJlIGNvcnJlbGF0ZWQuIFRoaXMgbGVhZHMgdG8gZGVwZW5kZW5jZSBhbW9uZyB0aGUgb2JzZXJ2YXRpb25zIHdpdGhpbiB0aGUgZ2l2ZW4gbGV2ZWxzLCBhbmQgdHlwaWNhbGx5LCB0aGUgbG93ZXIgdGhlIGxldmVsIG9mIHNhbXBsaW5nLCB0aGUgbW9yZSBzaW1pbGFyIHRoZSBvYnNlcnZhdGlvbnMuIFlvdSBjYW4gdGhpbmsgdGhhdCBjaGlsZHJlbiB3aXRoaW4gdGhlIHNhbWUgY2xhc3Nyb29tIG1heSBiZSBtb3JlIHNpbWlsYXIgdG8gb25lIGFub3RoZXIgdGhhbiBjaGlsZHJlbiBpbiB0aGUgc2FtZSBzY2hvb2wgZGlzdHJpY3QsIGZvciBleGFtcGxlLiANCg0KSGVyZSdzIGEgcGljdHVyZSBvZiB0aGUgcHJvY2VzcyBvZiBzdHJhdGlmaWVkIHNhbXBsaW5nLCB3aXRoIGEgc2ltcGxlIDEgc3RhZ2UgZGVzaWduLiBJbiB0aGlzIGV4YW1wbGUsIHRoZXJlIGFyZSBzZXZlcmFsIHBvc3NpYmxlIG5laWdoYm9yaG9vZHMgdGhhdCBjb3VsZCBiZSBzYW1wbGVkLCBidXQgc29tZSBhcmUgbm90IHNhbXBsZWQgKGRvdHRlZCBsaW5lcykgYW5kIHNvbWUgYXJlIHNhbXBsZWQgKHNvbGlkIGxpbmVzKS4gVGhlc2UgY291bGQgcmVwcmVzZW50IHN0cmF0YSBvciBjbHVzdGVycywgYmVjYXVzZSBpbiBhIDEgc3RhZ2UgZGVzaWduLCB0aGUgdHdvIGFyZSBzeW5vbnltb3VzLiANCg0KV2l0aGluIGVhY2ggbmVpZ2hib3Job29kIHRoZXJlIGFyZSBwZW9wbGUsIGFuZCBzb21lIG9mIHRoZW0gYXJlIHNhbXBsZWQgKGNpcmNsZXMpIGFuZCBzb21lIGFyZSBub3Qgc2FtcGxlZCAoWCdzKS4gDQoNCiFbTXVsdGlzdGFnZSBTYW1wbGluZ10oTUxkYXRhLnBuZykNCg0KSWYgd2Ugd2VyZSB0byBsb29rIGF0IHRoZSBkYXRhIHJlcHJlc2VudGVkIGJ5IHRoaXMgdHlwZSBvZiBzYW1wbGluZyBtZXRob2QsIGl0IHdvdWxkIGxvb2sgbGlrZSB0aGUgZXhhbXBsZSBiZWxvdy4gV2UgaGF2ZSAxMiBwZW9wbGUgbmVzdGVkIHdpdGhpbiB0aHJlZSBuZWlnaGJvcmhvb2RzLiBFYWNoIGlzIG1lYXN1cmVkIGZvciB0aGUgb3V0Y29tZSB2YXJpYWJsZSAoWSkgYW5kIHRocmVlIHByZXN1bWVkIHByZWRpY3RvciB2YXJpYWJsZXMgKFgxLCBYMiBhbmQgWDMpLiBXZSBzZWUgdGhhdCB0aGVzZSB2YWx1ZXMgYXJlIHVuaXF1ZSB0byBlYWNoIGluZGl2aWR1YWwsIHRoZXkgZWFjaCBoYXZlIHRoZWlyIG93biBpbmRpdmlkdWFsIGxldmVsIGRhdGEuIA0KDQpBbHNvIHByZXNlbnQgaXMgYSBuZWlnaGJvcmhvb2QtbGV2ZWwgdmFyaWFibGUsIFoxLCB3aGljaCBpcyB0aGUgc2FtZSB3aXRoaW4gbmVpZ2hib3Job29kLCBidXQgZGlmZmVycyBhY3Jvc3MgbmVpZ2hib3Job29kcy4gQSByZWFsIGV4YW1wbGUgb2YgdGhpcyBtYXkgYmUgdGhlIHBvdmVydHkgcmF0ZSwgd2hpY2ggaXMgbWVhc3VyZWQgZm9yIGFyZWFzLCBhbmQgcGVvcGxlIHdpdGhpbiB0aGUgc2FtZSBhcmVhIHdpbGwgYWxsIGhhdmUgdGhlIHNhbWUgdmFsdWUgZm9yIHRoYXQgdmFyaWFibGUNCg0KIVtNdWx0aWxldmVsIERhdGFdKG1sZGF0YXRhYmxlLnBuZykNCg0KVGhpcyBpcyBhY3R1YWxseSBhIHJlYWxseSBnb29kIGV4YW1wbGUgb2Ygd2hhdCB3ZSBoYXZlIGJlZW4gdGFsa2luZyBhYm91dDogcGVvcGxlIHdpdGhpbiBhcmVhcyBzaGFyaW5nIGNoYXJhY3RlcmlzdGljcy4gSW4gdGhpcyBjYXNlIGV2ZXJ5b25lIGluIGEgZ2l2ZW4gbmVpZ2hib3Job29kIGFsbCBoYXZlIHRoZSBzYW1lIGxldmVsIG9mIG5laWdoYm9yaG9vZCBwb3ZlcnR5LCBzbyB0aGV5IGFyZSBzaW1pbGFyIGluIHRoYXQgcmVnYXJkLCBidXQgYXJlIGRpZmZlcmVudCBpbiB0aGVpciBvd24gY2hhcmFjdGVyaXN0aWNzICh0aGUgWCdzIGZvciBleGFtcGxlKS4gDQoNCkluIG11bHRpLWxldmVsIGFuYWx5c2VzLCB3ZSBhcmUgdHlwaWNhbGx5IGludGVyZXN0ZWQgaW4gaG93IGJvdGggdGhlIGluZGl2aWR1YWwgcGVyc29uLWxldmVsIHZhcmlhYmxlcyBhbmQgdGhlIG5laWdoYm9yaG9vZCBsZXZlbCB2YXJpYWJsZXMgY29tYmluZSB0byBleHBsYWluIHRoZSBvdXRjb21lLiBJbiB0aGUgbmV4dCBwYXJ0IG9mIHRoZSBsZXNzb24sIHdlIHdpbGwgcmV2aWV3IHZhcmlvdXMgdHlwZXMgb2YgcmVzZWFyY2ggcHJvcG9zaXRpb25zIHdlIG1heSBiZSBpbnRlcmVzdGVkIGluLCB3aGljaCB1c2UgY29tYmluYXRpb25zIG9mIHRoZXNlIGF2YWlsYWJsZSB2YXJpYWJsZXMuIA0KDQoNCiMjIE11bHRpLWxldmVsIHByb3Bvc2l0aW9ucyANCg0KV2hlbiB3ZSBoYXZlIGEgcmVzZWFyY2ggc3RhdGVtZW50IHRoYXQgaW52b2x2ZXMgaW5kaXZpZHVhbHMgd2l0aGluIHNvbWUgY29udGV4dCwgdGhpcyBpcyBjYWxsZWQgYSBtdWx0aS1sZXZlbCBwcm9wb3NpdGlvbi4gSW4gdGhpcyBzZW5zZSwgd2UgYXJlIGludGVyZXN0ZWQgaW4gcXVlc3Rpb25zIHRoYXQgcmVsYXRlIHZhcmlhYmxlcyBhdCBkaWZmZXJlbnQgbGV2ZWxzLCB0aGUgcGVyc29uIGFuZCB0aGUgcGxhY2UsIHRoZSBtaWNybyBhbmQgdGhlIG1hY3JvLiANCg0KIyMjIFR5cGVzIG9mIG11bHRpLWxldmVsIHByb3Bvc2l0aW9ucw0KDQpJbiBhIG11bHRpbGV2ZWwgcHJvcG9zaXRpb24sIHZhcmlhYmxlcyBhcmUgcHJlc2VudCBhdCB0d28gZGlmZmVyZW50IGxldmVscywgYW5kIHdlIGFyZSBwb3RlbnRpYWxseSBpbnRlcmVzdGVkIGluIHRoZSByZWxhdGlvbnNoaXAgYmV0d2VlbiBib3RoIHRoZSBtaWNybyBhbmQgbWFjcm8gbGV2ZWwgYXNzb2NpYXRpb24gd2l0aCBvdXIgb3V0Y29tZSwgeS4NCg0KQWdhaW4sIHJlZmVycmluZyB0byBvdXIgZGF0YSBzdHJ1Y3R1cmUgZnJvbSB0aGUgcHJldmlvdXMgcGFydCBvZiB0aGlzIGxlc3Nvbiwgd2UgY291bGQgY3JlYXRlIGEgZ3JhcGhpY2FsIHJlcHJlc2VudGF0aW9uIG9mIHRoZXNlIGRhdGEsIHdpdGggdGhlIG91dGNvbWUsICpZKiBhbmQgdGhlIHByZWRpY3RvciAqWCogbWVhc3VyZWQgYXQgdGhlIGluZGl2aWR1YWwgbGV2ZWwsIGFuZCB0aGUgY29udGV4dHVhbCB2YXJpYWJsZSAqWiogbWVhc3VyZWQgYXQgdGhlIG5laWdoYm9yaG9vZCBsZXZlbC4gDQoNCiFbTXVsdGktbGV2ZWwgZGF0YV0oYmFzaWNfbWxfZGF0LnBuZykgIA0KDQoNCkluIHRoZSBncmFwaHMgdGhlIGZvbGxvdywgd2Ugd2lsbCBkZXNjcmliZSB0eXBlcyBvZiBxdWVzdGlvbnMgdGhhdCBjb3VsZCBiZSBhc2tlZCB1c2luZyB2YXJpb3VzIGNvbWJpbmF0aW9ucyBvZiB0aGlzIGluZm9ybWF0aW9uLiANCg0KIyMjIEluZGl2aWR1YWwgbGV2ZWwgcHJvcG9zaXRpb24NCklmIHdlIGFyZSBjb25jZXJuZWQgd2l0aCBob3cgaW5kaXZpZHVhbC1sZXZlbCBmYWN0b3JzIGFmZmVjdCBlYWNoIHBlcnNvbidzIG91dGNvbWUsIHRoZW4gd2UgYXJlIHN0YXRpbmcgYW4gaW5kaXZpZHVhbCBsZXZlbCwgb3IgbWljcm8sIHByb3Bvc2l0aW9uLiBJbiB0aGlzIHR5cGUgb2YgYW5hbHlzaXMsIHdlIGhhdmUgKlkqIGFuZCAqWCosIGJvdGggbWVhc3VyZWQgb24gb3VyIGluZGl2aWR1YWwgbGV2ZWwgdW5pdHMuIEFuIGV4YW1wbGUgb2YgdGhpcyB3b3VsZCBiZSB0aGF0IHdlIHRoaW5rIGEgcGVyc29ucyBoZWFsdGggaXMgYWZmZWN0ZWQgYnkgdGhlaXIgbGV2ZWwgb2YgZWR1Y2F0aW9uLiANCg0KIVtNaWNyby1sZXZlbCBwcm9wb3NpdGlvbl0oaW5kaS5wbmcpDQoNCiMjIE1hY3JvIGxldmVsIHByb3Bvc2l0aW9uDQpXZSBjYW4gYWxzbyBoYXZlIHB1cmVseSBtYWNyby1sZXZlbCBwcm9wb3NpdGlvbnMsIHdoZXJlIHdlIGhhdmUgYW4gb3V0Y29tZSAqWSogbWVhc3VyZWQgYXQgYW4gYWdncmVnYXRlIGxldmVsIHVuaXQsIHN1Y2ggYXMgYSBuZWlnaGJvcmhvb2Qgb3IgTVNBLCBzdWNoIGFzIHdlIGhhdmUgc2VlbiBiZWZvcmUgaW4gcHJldmlvdXMgbGVzc29ucy4gV2UgYWxzbyBoYXZlIHByZWRpY3RvcnMgbWVhc3VyZWQgYXQgdGhlIGFnZ3JlZ2F0ZSB1bml0LCAqWiogYW5kIHdlIGFyZSBpbnRlcmVzdGVkIGluIGhvdyAqWiogYWZmZWN0cyAqWSouIFRoaXMgaXMgcmVmZXJyZWQgdG8gYXMgYW4gKipfZWNvbG9naWNhbCBzdHVkeV8qKiBiZWNhdXNlIHdlIG9ic2VydmUgbm8gd2l0aGluIGFyZWEgdmFyaWF0aW9uLCBvbmx5IGJldHdlZW4gYXJlYXMuIFdoaWxlIHRoaXMgdHlwZSBvZiBzdHVkeSBpcyBjb21tb24gaW4gc3BhdGlhbCBkZW1vZ3JhcGh5LCB0aGUgdHJlbmQgaXMgbW92aW5nIGF3YXkgZnJvbSBzdWNoIGFuYWx5c2VzIGFzIGJldHRlciBtdWx0aS1sZXZlbCBkYXRhIGJlY29tZSBhdmFpbGFibGUuIEFuIGV4YW1wbGUgb2YgdGhpcyB3b3VsZCBiZSB3aGVyZSB3ZSBhcmUgaW50ZXJlc3RlZCB0byBzZWUgaWYgaGlnaGVyIHBvdmVydHkgcmF0ZXMgYXQgdGhlIE1TQSBsZXZlbCBhcmUgYXNzb2NpYXRlZCB3aXRoIGhpZ2hlciByYXRlcyBvZiBtb3J0YWxpdHkgYXQgdGhlIE1TQSBsZXZlbC4gDQoNCiFbTWFjcm8tbGV2ZWwgcHJvcG9zaXRpb25dKG1hY3JvLnBuZykNCg0KIyMjIE11bHRpLWxldmVsIHByb3Bvc2l0aW9ucw0KSW4gbW9zdCBjaXJjdW1zdGFuY2VzIHdoZW4gd2UgZG8gYSBtdWx0aS1sZXZlbCBhbmFseXNpcywgd2UgdXNlIGluZm9ybWF0aW9uIGluIHRoZSBmb3JtIG9mIHByZWRpY3RvcnMgbWVhc3VyZWQgYXQgYm90aCB0aGUgbWljcm8gYW5kIG1hY3JvIGxldmVscyBvZiBhbmFseXNpcywgaW4gb3JkZXIgdG8gdW5kZXJzdGFuZCBhbiBvdXRjb21lIGF0IHRoZSBpbmRpdmlkdWFsIGxldmVsLiBUaGVzZSB0eXBlcyBvZiBhbmFseXNpcyByZXByZXNlbnQgdHJ1ZSAqKl9tdWx0aS1sZXZlbF8qKiBhbmFseXNlcy4gQW4gZXhhbXBsZSBvZiBhIG11bHRpLWxldmVsIHJlc2VhcmNoIHF1ZXN0aW9uIHdvdWxkIGJlICJGb3IgaW5kaXZpZHVhbHMgd2l0aCB0aGUgYSBnaXZlbiBsZXZlbCBvZiBlZHVjYXRpb24sIGRvZXMgbGl2aW5nIGluIGFuIGhpZ2ggcG92ZXJ0eSBhcmVhIGxlYWQgdG8gcG9vciBoZWFsdGgiLiBXaGVuIHdlIGhhdmUgdGhlc2UgdHlwZXMgb2Ygc3RhdGVtZW50cywgd2UgYXJlIGdlbmVyYWxseSBsb29raW5nIGZvciBhICpuZXQqIGVmZmVjdCBvZiAqWiogYWZ0ZXIgY29uc2lkZXJpbmcgdGhlIGVmZmVjdCBvZiAqWCouIA0KDQohW011bHRpLWxldmVsIHByb3Bvc2l0aW9uXShtbC5wbmcpDQoNClRoZXNlIGFyZSBoaWdobHkgaW5mb3JtYXRpdmUgbW9kZWxsaW5nIHN0cmF0ZWdpZXMgYmVjYXVzZSB3ZSBhcmUgY29uc2lkZXJpbmcgdGhlIGVmZmVjdHMgb2YgYm90aCBpbmRpdmlkdWFsIGFuZCBuZWlnaGJvcmhvb2QgbGV2ZWwgdmFyaWFibGVzIG9uIGFuIGluZGl2aWR1YWwgbGV2ZWwgb3V0Y29tZS4gDQoNCiMjIyBDcm9zcy1sZXZlbCBpbnRlcmFjdGlvbnMgDQpUaGUgZmluYWwgcHJvcG9zaXRpb24gd2Ugd2lsbCBkaXNjdXNzIGlzIHRoZSAqKl9jcm9zcy1sZXZlbCBpbnRlcmFjdGlvbl8qKi4gVGhpcyBpcyB3aGVyZSB3ZSBhc2sgYSBxdWVzdGlvbiB0aGF0IGRlbWFuZHMgd2UgaW50ZXJhY3QgdGhlIG5laWdoYm9yaG9vZCBhbmQgaW5kaXZpZHVhbC1sZXZlbCBwcmVkaWN0b3JzLiBJbiBhIHNlbnNlLCB0aGlzIHB1dHMgdGhlIGluZGl2aWR1YWwgbGV2ZWwgZGlyZWN0bHkgd2l0aGluIGNvbnRleHQgYnkgY29uc2lkZXJpbmcgdGhlIGludGVyYWN0aW9uLiBXaGVuIHdlIHVzZSBsYW5ndWFnZSB0byBkZXNjcmliZSB0aGlzIHR5cGUgb2YgYXNzb2NpYXRpb24sIHdlIG11c3Qgc3RyZXNzIHRoZSBjb25kaXRpb25pbmcgb2YgdGhlIGluZGl2aWR1YWwgbGV2ZWwgZWZmZWN0IG9uIHRoZSBjb250ZXh0dWFsIGxldmVsIGVmZmVjdC4gQSBjcm9zcy1sZXZlbCBpbnRlcmFjdGlvbiBxdWVzdGlvbiBjb3VsZCBiZSBzdGF0ZWQgYXM6ICJJbmRpdmlkdWFscyB3aXRoIGxvdyBsZXZlbHMgb2YgZWR1Y2F0aW9uLCAqYW5kKiB3aG8gbGl2ZSBpbiBhcmVhcyB3aXRoIGhpZ2ggcG92ZXJ0eSwgaGF2ZSBoaWdoZXIgcmlzayBvZiBkZWF0aC4iIFRoZSBpbXBvcnRhbnQgcGFydCBvZiB0aGUgc3RhdGVtZW50IGlzIHRoZSAqYW5kKiwgd2hlcmUgd2Ugc3RyZXNzIGluIG91ciByZXNlYXJjaCBzdGF0ZW1lbnQgdGhhdCB0aGUgaW5kaXZpZHVhbCBsZXZlbCBjaGFyYWN0ZXJpc3RpYyBpcyBkaXJlY3RseSBpbnRlcmFjdGVkIHdpdGggdGhlIG5laWdoYm9yaG9vZCBsZXZlbCB2YXJpYWJsZS4gIA0KDQohW0Nyb3NzLWxldmVsIHByb3Bvc2l0aW9uXShjbGkucG5nKQ0KDQpJbiB0aGUgc2VjdGlvbiB0aGF0IGZvbGxvd3MsIHdlIHdpbGwgZGVzY3JpYmUgdGhlIHN0cnVjdHVyZSBvZiBtdWx0aS1sZXZlbCByZWdyZXNzaW9uIG1vZGVscywgZW1waGFzaXppbmcgdGhlIHZhcmlvdXMgZm9ybXMgdGhhdCB3ZSBoYXZlIGNvdmVyZWQgaW4gdGhpcyBzZWN0aW9uLg0KDQoNCiMjIE11bHRpLWxldmVsIHN0YXRpc3RpY2FsIG1vZGVscyANCg0KVGhlIG11bHRpLWxldmVsIG1vZGVsIGNhbiBiZSB1c2VkIGZvciBhbnkgZm9ybSBvZiBvdXRjb21lIHZhcmlhYmxlOyBjb250aW51b3VzLCBkaWNob3RvbW91cywgY291bnQsIHJpZ2h0IHNrZXdlZCwgY2F0ZWdvcmljYWwuIE1hbnkgdGltZXMgdGhlIG1vZGVsIGlzIHByZXNlbnRlZCBhcyBhbiBleHRlbnNpb24gdG8gdGhlIHJlZ3VsYXIgbGluZWFyIHJlZ3Jlc3Npb24gbW9kZWwsIGhvd2V2ZXIgdGhpcyBpcyBub3QgYXMgdXNlZnVsIGZvciBtdWNoIG9mIHNvY2lhbCBzY2llbmNlLiBJdCBpcyBtb3JlIGNvbW1vbiBpbiBkZW1vZ3JhcGh5IGFuZCBzb2Npb2xvZ3kgdG8gYmUgYW5hbHl6aW5nIHN1cnZleSBkYXRhIHRoYXQgY29uc2lzdCBtb3N0bHkgb2YgY291bnRzIG9yIHllcy9ubyBxdWVzdGlvbiByZXNwb25zZS4gVGFraW5nIHRoaXMgaW50byBjb25zaWRlcmF0aW9uLCB3ZSB3aWxsIGRpc2N1c3MgdGhlIG11bHRpLWxldmVsIG1vZGVsIGZyb20gdGhlIHBlcnNwZWN0aXZlIG9mIHRoZSBnZW5lcmFsaXplZCBsaW5lYXIgbW9kZWwsIHN1Y2ggYXMgd2UgdXNlZCBmb3IgbG9naXN0aWMgb3IgUG9pc3NvbiByZWdyZXNzaW9uLCBhcyB0byBhdm9pZCBzdHJpY3QgcmVsaWFuY2Ugb24gYW4gYXNzdW1lZCBjb250aW51b3VzIG91dGNvbWUuIFdlIGRvIHRoaXMgYmVjYXVzZSBvbmNlIHdlIGFyZSBjb21mb3J0YWJsZSB3aXRoIHRoZSBpZGVhIHRoYXQgeW91IGNhbiBsaW5rIHRoZSBtZWFuIG9mIGFueSBvdXRjb21lIHRvIGEgbGluZWFyIG1vZGVsIHRocm91Z2ggdGhlIGdlbmVyYWwgbGluZWFyIG1vZGVsIGZyYW1ld29yaywgdGhpcyBjYW4gYmUgZXh0ZW5kZWQgdG8gYW55IGRpc3RyaWJ1dGlvbi4gDQoNClVzaW5nIHRoaXMgZnJhbWV3b3JrLCB3ZSB3aWxsIHJlZmVyIHRvIHRoZSBjbGFzcyBvZiBtb2RlbHMgdGhhdCB3ZSBhcmUgZGVzY3JpYmluZyBhcyAqKl9HZW5lcmFsaXplZCBMaW5lYXIgTWl4ZWQgTW9kZWxzXyoqLCBvciBHTE1Ncy4gDQoNCkluIHRoaXMgc2VjdGlvbiB3ZSB3aWxsIGJlZ2luIG91ciBkaXNjdXNzaW9uIG9mIHRoZSBtdWx0aS1sZXZlbCByZWdyZXNzaW9uIG1vZGVsIHdpdGggdGhlIGZpcnN0IG1vZGVsIG1vc3QgcGVvcGxlIGxlYXJuIGluIHN0YXRpc3RpY3MsIHRoZSBBbmFseXNpcyBvZiBWYXJpYW5jZSAoQU5PVkEpLiBXaHkgdGhlIEFOT1ZBPyBCZWNhdXNlIHRoZSBiYXNpYyBtdWx0aWxldmVsIG1vZGVsIGlzIGEgZGlyZWN0IGFuYWxvZyBvZiB0aGUgQU5PVkEgbW9kZWwuIA0KDQpJZiB5b3UgcmVtZW1iZXIsIHRoZSBBTk9WQSB3YXMgdGhlIG1vZGVsIHRoYXQgd2FzIHVzZWQgdG8gY29tcGFyZSB0aGUgbWVhbnMgb2Ygc2V2ZXJhbCBncm91cHMsIG9yIGZvciBqdXN0IHR3byBncm91cHMuIFRoZSBnZW5lcmFsIGZvcm0gb2YgdGhpcyBpczoNCg0KJCRFKHlfaikgPSBcbXUgKyB1X3tqfSQkDQoNCm9yLCB0aGUgbWVhbiBvZiB0aGUgJGpee3RofSQgZ3JvdXAgaXMgYSBjb21iaW5hdGlvbiBvZiB0aGUgb3ZlcmFsbCBtZWFuIG9mIHRoZSBzYW1wbGUsICRcbXUkIGFuZCBhIHRlcm0gJHVfaiQgdGhhdCBtZWFzdXJlcyBob3cgdGhlIG1lYW4gb2YgdGhlICRqXnt0aH0kIGdyb3VwIGRpZmZlcnMgZnJvbSB0aGUgb3ZlcmFsbCBzYW1wbGUgbWVhbiwgb3IgcGVyaGFwcyBmcm9tIHRoZSBtZWFuIG9mIGEgcHJlLWFycmFuZ2VkIHJlZmVyZW5jZSBncm91cC4gV2hlbiB0aGUgbnVtYmVyIG9mIGdyb3VwcyBpcyBzbWFsbCwgc2F5IDMgdG8gNSwgdGhlIEFOT1ZBIG1vZGVsIGlzIHZlcnkgZWZmaWNpZW50LCBtZWFuaW5nIHRoYXQgeW91IGFyZSBlc3RpbWF0aW5nIGEgZmV3IHBhcmFtZXRlcnMgaW4gb3JkZXIgdG8gZXN0aW1hdGUgdGhlIG1lYW5zIG9mIGVhY2ggZ3JvdXAuIFRoZXNlIGFyZSBzYWlkIHRvIGJlICoqX2ZpeGVkIGVmZmVjdHNfKiogaW4gdGhlIG1vZGVsLCBhcyB0aGV5IGFyZSBlc3RpbWF0ZWQgcmVsYXRpdmUgdG8gdGhlIG1lYW4gb2YgYSBwcmVkZWZpbmVkIGdyb3VwLiANCg0KDQpIb3dldmVyLCBpbiBtYW55IG11bHRpLWxldmVsIG1vZGVsaW5nIGFuYWx5c2VzLCB3ZSBtYXkgaGF2ZSBkb3plbnMgb3IgaHVuZHJlZHMgb2YgZ3JvdXBzLiBBbiBleGFtcGxlIHdvdWxkIGJlIGlmIHdlIGhhZCBwZW9wbGUgbmVzdGVkIHdpdGhpbiBjb3VudGllcywgZXZlbiBpZiB3ZSBvbmx5IGhhdmUgcGVvcGxlIGluIDEwJSBvZiBjb3VudGllcywgd2Ugd291bGQgc3RpbGwgaGF2ZSBvdmVyIDMwMCBncm91cHMgaW4gdGhlIGRhdGEuIEluIHRoaXMgc2V0dGluZyB5b3Ugd291bGQgZXN0aW1hdGUgMzAwIHBhcmFtZXRlcnMsIHdoaWNoIHNvdW5kcyBsaWtlIGEgbG90LCBhbmQgaXQgaXMuIE1vcmVvdmVyLCB3aGVuIHRoZSBudW1iZXIgb2YgZ3JvdXBzIGlzIHNtYWxsLCB3ZSBnZW5lcmFsbHkgY2hvb3NlIG9mIHRoZSBncm91cHMgdG8gYmUgdGhlIHJlZmVyZW5jZSBncm91cCBhbmQgY29tcGFyZSB0aGUgbWVhbnMgb2YgdGhlIG90aGVyIGdyb3VwcyB0byBpdC4gV2hlbiB3ZSBoYXZlIGEgbGFyZ2UgbnVtYmVyIG9mIGdyb3VwcywgZG9pbmcgdGhpcyB3aXRoIHJlZmVyZW5jZSB0byBhbnkgb25lIHBhcnRpY3VsYXIgZ3JvdXAgbWF5IG5vdCBiZSBzbyBsb2dpY2FsOiBXaHkgcGljayB0aGUgb25lIHlvdSBjaG9vc2U/IFdoeSBub3QgYW5vdGhlcj8NCg0KSXQgaXMgaW4gdGhpcyBzaXR1YXRpb24gd2hlcmUgdGhlIG11bHRpLWxldmVsIG1vZGVsIGhhcyBhIGRpc3RpbmN0IGFkdmFudGFnZS4gSW5zdGVhZCBvZiBlc3RpbWF0aW5nIGEgc2luZ2xlIHBhcmFtZXRlciBmb3IgZXZlcnkgZ3JvdXAsIHRoZSBtdWx0aS1sZXZlbCBtb2RlbCBlc3RpbWF0ZXMgdGhlIG92ZXJhbGwgbWVhbiAkXG11JCwgYW5kIHRoZW4gbW9kZWxzIHRoZSBncm91cC1zcGVjaWZpYyBkZXZpYXRpb25zIGFzIGEgc2V0IG9mIE5vcm1hbGx5IGRpc3RyaWJ1dGVkIHJhbmRvbSB2YXJpYWJsZXMsIHdpdGggYSBtZWFuIG9mIDAsIHNpbmNlIHRoZSBvdmVyYWxsIG1lYW4gaXMgZXN0aW1hdGVkIGJ5ICRcbXUkLCBhbmQgYSB2YXJpYW5jZSBvZiAkXHNpZ21hXjJfdSQuIFRoaXMgaXMgY29uc2lkZXJlZCB0byBiZSBhICoqX3JhbmRvbSBlZmZlY3QgdGVybV8qKiBpbiB0aGUgbW9kZWwuIENvbnRyYXN0IHRoaXMgdG8gdGhlIEFOT1ZBIG1vZGVsIHdoZXJlIGFsIHRoZSBncm91cCBtZWFucyBhcmUgImZpeGVkIi4gV2hlbiB1c2luZyB0aGlzIHR5cGUgb2YgbW9kZWwsIHdlIGNhbiBzdGlsbCBtZWFzdXJlIHRoZSBtZWFucyBvZiBhbGwgdGhlIGdyb3VwcywgYW5kIHdlIGFyZSBkb2luZyBzbyB3aXRoIGZld2VyIHBhcmFtZXRlcnMsIHRlY2huaWNhbGx5IG9ubHkgdHdvLCB0aGUgb3ZlcmFsbCBtZWFuLCAkXG11JCBhbmQgdGhlIHZhcmlhbmNlIGluICR1X2okLCAkXHNpZ21hXjJfdSQsIGFsdGhvdWdoIHRoYXQgaXMgYSBtYXR0ZXIgb2YgZGViYXRlIGluIHRoZSBsaXRlcmF0dXJlIG9uIHRoZSBzdWJqZWN0LiAgDQoNCk9mIGNvdXJzZSwgaW4gc29jaWFsIHJlc2VhcmNoLCB0aGUgQU5PVkEgbW9kZWwgaXMgZ2VuZXJhbGx5IG9ubHkgYSBmaXJzdCBzdGVwLCBhbmQgd2UgYXJlIG9mdGVuIG11Y2ggbW9yZSBpbnRlcmVzdGVkIGluIGNvbnRyb2xsaW5nIGZvciB2YXJpb3VzIG90aGVyIGZhY3RvcnMsIHNvIGFzc3VtaW5nIHRoYXQgdGhlIEFOT1ZBIG9yIHRoZSBtdWx0aS1sZXZlbCBhbmFsb2cgaXMgdGhlIGtpbmQgb2YgbW9kZWwgdGhhdCB3aWxsIGJlIHVzZWQgaW4gYSByZXNlYXJjaCBzZXR0aW5nIGlzIG5vdCB2ZXJ5IHJlYWxpc3RpYy4gDQoNClNvLCB3ZSBjYW4gYWRkIGxvdHMgb2Ygb3RoZXIgdGVybXMgaW4gdGhlIG1vZGVsLCBhbmQgaWYgd2UgdXNlIHRoZSBBTk9WQSBhcyBhIGJhc2lzLCB3ZSBoYXZlIGEgbW9kZWwgbGlrZToNCg0KJCRFKHlfaikgPSBcbXUgKyB1X2ogK1xzdW1fayBcYmV0YV9rIHhfayQkDQoNCldoZXJlIHRoZSAkXGJldGEkJ3MgYXJlIHJlZ3Jlc3Npb24gY29lZmZpY2llbnRzIGZvciBvdGhlciBpbmRpdmlkdWFsIGxldmVsIHZhcmlhYmxlcyBpbiB0aGUgbW9kZWwsIGFuZCB0aGUgKngqJ3MgYXJlIHRoZSBvdGhlciBwcmVkaWN0b3JzLCBiZXNpZGVzIHRoZSBncm91cCB2YXJpYWJsZS4gDQoNCkFnYWluLCBpZiB3ZSBoYXZlIGEgc21hbGwgbnVtYmVyIG9mIGdyb3VwcywgdGhlICR1X2okIHdpbGwgb25seSBiZSBhIGZldyBwYXJhbWV0ZXJzLCBhbmQgaWYgd2UgaGF2ZSBsb3RzIG9mIGdyb3VwcyB0aGVuIHRoZSAkdV9qJCB3aWxsIGJlIGxvdHMgb2YgcGFyYW1ldGVycy4gSW4gdGhpcyB0eXBlIG9mIHNpdHVhdGlvbiwgaWYgd2UgYWRvcHQgYSByYW5kb20gZWZmZWN0IG1vZGVsLCB0aGVuIHRoaXMgd291bGQgYmUgY29uc2lkZXJlZCBhICoqX21peGVkIGVmZmVjdHMgbW9kZWxfKiogd2hlcmUgd2UgaGF2ZSBzb21lIGVmZmVjdHMgaW4gdGhlIG1vZGVsIHRoYXQgYXJlIGNvbnNpZGVyZWQgZml4ZWQsIHRoZSAkXGJldGFfayQncyBhbmQgYSByYW5kb20gZWZmZWN0IHRlcm0gZm9yIHRoZSBncm91cCBtZWFucywgJHVfaiQuIA0KDQpJbiBtYW55IHByZXNlbnRhdGlvbnMgb2YgdGhlIG11bHRpLWxldmVsIG1vZGVsLCB5b3UgbWF5IHNlZSB0aGUgZXF1YXRpb24gYWJvdmUgd3JpdHRlbiB3aGVyZSB0aGUgJHVfaiQgdGVybSBpcyBhYnNvcmJlZCBpbnRvIHRoZSBpbnRlcmNlcHQgdGVybS4gVGhpcyB3b3VsZCBiZSB3cml0dGVuIGFzIHR3byBzdGFnZXMsIGFuZCBpbiB0ZXJtcyBvZiB0aGUgaW50ZXJjZXB0IHBhcmFtZXRlciwgJFxiZXRhXzAkOg0KDQokJHlfe2lqfSA9IFxiZXRhX3swan0gK1xzdW1fayBcYmV0YV9rIHhfe2tpan0kJA0KJCRcYmV0YV97MGp9ID0gXGJldGFfMCArIHVfaiQkDQoNCldoZW4gaW50ZXJwcmV0aW5nIHRoaXMgbW9kZWwsIHRoZSAkdV9qJCB0ZXJtcyBhcmUgcmVmZXJyZWQgdG8gYXMgYSB0aGUgKipfcmFuZG9tIGludGVyY2VwdHNfKiogaW4gdGhlIG1vZGVsLiBJbiBtb2RlbCBvdXRwdXQsIHRoZXNlIGFyZSByYXJlbHkgc2hvd24gZGlyZWN0bHksIHNpbmNlIHRoZXJlIGNhbiBiZSBtYW55IG9mIHRoZW0uIFdoYXQgKmlzKiBzaG93biBpcyB0aGUgdmFyaWFuY2UgaW4gdGhlc2UgcmFuZG9tIHRlcm1zLCAkXHNpZ21hXjJfdSQsIGFuZCBpdCByZXBvcnRlZCBieSBhbGwgc29mdHdhcmUgdGhhdCBmaXRzIHRoZXNlIG1vZGVscy4gDQoNCg0KIyMgQ29tcG9uZW50cyBvZiB2YXJpYXRpb24gaW4gdGhlIG11bHRpLWxldmVsIG1vZGVsIA0KV2hlbiB1c2luZyB0aGUgbXVsdGktbGV2ZWwgbW9kZWwsIHdlIGFyZSBvZnRlbiBjb25jZXJuZWQgd2l0aCBob3cgbXVjaCB2YXJpYXRpb24gaXMgYWNjb3VudGVkIGZvciB3aXRoaW4gYW5kIGJldHdlZW4gb3VyIGdyb3Vwcywgb3IgbmVpZ2hib3Job29kcy4gRGlmZmVyZW50IHR5cGVzIG9mIG91dGNvbWUgdmFyaWFibGVzLCBhbmQgZGlmZmVyZW50IG91dGNvbWUgZGlzdHJpYnV0aW9uIGFsbG93IGltcGx5IGRpZmZlcmVudCBzb3VyY2VzIG9mIHZhcmlhdGlvbiB3aXRoaW4gdGhlIG1vZGVsLiBGb3IgZXhhbXBsZSwgaWYgd2Ugd2VyZSB0byBhc3N1bWUgb3VyIG91dGNvbWUgd2FzIE5vcm1hbGx5IGRpc3RydXN0ZWQsIHRoZW4gdGhlIG1vZGVsIGFib3ZlIHdvdWxkIGJlIHdyaXR0ZW4gYXM6DQoNCiQkeV97aWp9ID0gXGJldGFfezBqfSArXHN1bV9rIFxiZXRhX2sgeF97a2lqfSArIGVfaSQkDQoNCldoZXJlIHdlIGhhdmUgdGhlICRlX2kkIHRlcm0sIGFzIGluIHRoZSBvcmRpbmFyeSBsZWFzdCBzcXVhcmVzIG1vZGVsLCB3aGljaCBtZWFzdXJlcyB0aGUgaW5kaXZpZHVhbCBsZXZlbCB2YXJpYXRpb24gbm90IGFjY291bnRlZCBmb3IgYnkgdGhlIG1vZGVsIHBhcmFtZXRlcnMsIG9yIHRoZSByZXNpZHVhbC4gSW4gdGhpcyBtb2RlbCBzcGVjaWZpY2F0aW9uLCB0aGlzICRlX2kkIHRlcm0gaGFzIGl0J3Mgb3duIHZhcmlhbmNlLCAkXHNpZ21hXjJfZSQsIG9yIHRoZSByZXNpZHVhbCB2YXJpYW5jZS4gVGhlcmUgaXMgYSBzZWNvbmQgdmFyaWFuY2UgdGVybSwgYXMgc2hvd24gaW4gdGhlIHByZXZpb3VzIHNlY3Rpb24sIHRoYXQgbWVhc3VyZXMgdGhlIHZhcmlhdGlvbiBiZXR3ZWVuIG91ciBoaWdoZXItbGV2ZWwgdW5pdHMsICRcc2lnbWFeMl91JCwgb3IgdGhlIGJldHdlZW4gZ3JvdXAgdmFyaWFuY2UuIA0KDQpUaGlzIGltcGxpZXMgdGhhdCB0aGUgdG90YWwgdmFyaWF0aW9uLCAkXHNpZ21hXjJfeSQgaW4gdGhlIG91dGNvbWUsIGZvciBhIG1vZGVsIGFzc3VtaW5nIGEgTm9ybWFsIGRpc3RyaWJ1dGlvbiBmb3IgdGhlIG91dGNvbWUgY29tZXMgZnJvbSB0d28gc291cmNlcywgdGhlIGJldHdlZW4gZ3JvdXAgdmFyaWFuY2UgYW5kIHRoZSBwZXJzb24tbGV2ZWwgdmFyaWFuY2U6DQoNCiQkXHNpZ21hXjJfeSA9IFxzaWdtYV4yX2UgK1xzaWdtYV4yX3UkJA0KDQpJbiBtdWx0aS1sZXZlbCBtb2RlbHMsIGEgcXVhbnRpdHkgY2FsbGVkIHRoZSAqKl9JbnRyYWNsYXNzIGNvcnJlbGF0aW9uIGNvZWZmaWNpZW50XyoqLCBvciBJQ0MgaXMgY29tbW9ubHkgY2FsY3VsYXRlZCB1c2luZyB0aGVzZSB2YXJpYW5jZSBjb21wb25lbnRzLiBUaGUgSUNDIGlzIGNvbnNpZGVyZWQgYSBtZWFzdXJlIG9mIGNvcnJlbGF0aW9uIHdpdGhpbiBoaWdoZXIgbGV2ZWwgdW5pdHMuIEluIG90aGVyIHdvcmRzLCBpdCBtZWFzdXJlcyB0aGUgZGVncmVlIG9mIHNpbWlsYXJpdHkgYmV0d2VlbiB0d28gcmFuZG9tbHkgc2VsZWN0ZWQgcmVzcG9uZGVudHMgd2l0aGluIGEgZ2l2ZW4sIHJhbmRvbWx5IHNlbGVjdGVkIG5laWdoYm9yaG9vZC4gQW4gZXhhbXBsZSBvZiB0aGlzIHdvdWxkIGJlLCBpZiB3ZSB3YW50ZWQgdG8ga25vdyBob3cgc2ltaWxhciB5b3Ugd2VyZSB0byBvbmUgb2YgeW91ciBuZWlnaGJvcnMgaW4geW91ciBuZWlnaGJvcmhvb2QsIG9uIGF2ZXJhZ2UuIEFzIGEgZ2VuZXJhbCBydWxlLCB0aGUgbGFyZ2VyIHRoZSBiZXR3ZWVuLWdyb3VwIHZhcmlhbmNlLCB0aGUgZ3JlYXRlciB0aGUgSUNDLiANCg0KJCRcdGV4dHtJQ0N9ID0gXGZyYWN7XHNpZ21hXjJfdX17XHNpZ21hXjJfZSArXHNpZ21hXjJfdX0kJA0KDQpUaGUgSUNDIGlzIGJvdW5kIGJldHdlZW4gMCBhbmQgMSwgd2l0aCBoaWdoZXIgdmFsdWVzIGltcGx5aW5nIGdyZWF0ZXIgc2ltaWxhcml0eSB3aXRoaW4gb3VyIGhpZ2hlciBsZXZlbCB1bml0cy4gRm9yIGV4YW1wbGUgYW5kIElDQyBvZiAuNSAod2hpY2ggaXMgbGFyZ2UgZm9yIGFuIElDQykgd291bGQgaW1wbHkgdGhhdCB5b3UgYW5kIGEgcmFuZG9tbHkgc2VsZWN0ZWQgb25lIG9mIHlvdXIgbmVpZ2hib3JzIGluIHlvdXIgbmVpZ2hib3Job29kIHdvdWxkIGJlIHByZXR0eSBzdHJvbmdseSBjb3JyZWxhdGVkLCB3aGlsZSBhbiBJQ0Mgb2YgLjAxLCB3b3VsZCBpbXBseSBhIHZlcnkgbG93IGRlZ3JlZSBvZiBzaW1pbGFyaXR5IGJldHdlZW4geW91IGFuZCB5b3VyIG5laWdoYm9ycy4gDQoNCklmIHlvdSBhcmUgZG9pbmcgYSBtdWx0aS1sZXZlbCBsb2dpc3RpYyByZWdyZXNzaW9uIG1vZGVsIHRoZSB2YXJpYW5jZSB0ZXJtcyBhcmUgZGlmZmVyZW50LiBTaW5jZSB0aGUgYmlub21pYWwgZGlzdHJpYnV0aW9uLCBhc3N1bWVkIGJ5IHRoZSBsb2dpc3RpYyByZWdyZXNzaW9uIG1vZGVsLCBvbmx5IGhhcyBvbmUgcGFyYW1ldGVyLCBhbmQgdGhlIHZhcmlhbmNlIGFuZCBtZWFuIG9mIHRoZSBkaXN0cmlidXRpb24gYXJlIHN0cm9uZ2x5IHJlbGF0ZWQsIHRoZSBtdWx0aS1sZXZlbCBsb2dpc3RpYyBtb2RlbCBoYXMgYSBkaWZmZXJlbnQgaW5kaXZpZHVhbC1sZXZlbCB2YXJpYW5jZSB0ZXJtLCB0aGF0IGlzIGFjdHVhbGx5IGEgY29uc3RhbnQuIEluIHRoZSBiaW5vbWlhbCBtb2RlbCwgdGhlIElDQyBpczoNCg0KJCRcdGV4dHtJQ0N9ID0gXGZyYWN7XHNpZ21hXjJfdX17XGZyYWN7XHBpXjJ9ezN9ICtcc2lnbWFeMl91fSQkDQoNClRoZSB0ZXJtICRcZnJhY3tccGleMn17M30kIGlzIHRoZSB2YXJpYW5jZSBpbiB0aGUgbG9naXN0aWMgZGlzdHJpYnV0aW9uLCBpbXBsaWVkIGJ5IHRoZSBtb2RlbCwgYW5kIGlzIGEgY29uc3RhbnQgKEF1c3RpbiBhbmQgTWVybG8sIDIwMTcpLiANCg0KSWYgYSBQb2lzc29uIG11bHRpLWxldmVsIG1vZGVsIGlzIHVzZWQsIHRoZW4gdGhlIGluZGl2aWR1YWwgbGV2ZWwgdmFyaWFuY2UgaXMgYWN0dWFsbHkgMSwgYW5kIHRoZSBJQ0MgaXM6DQoNCiQkXHRleHR7SUNDfSA9IFxmcmFje1xzaWdtYV4yX3V9ezEgK1xzaWdtYV4yX3V9JCQNClRoZSBpbmRpdmlkdWFsIGxldmVsIHZhcmlhbmNlIGlzIDEgaW4gdGhlIFBvaXNzb24gbW9kZWwsIG93aW5nIHRvIHRoZSBhc3N1bXB0aW9uIG9mIHRoYXQgbW9kZWwgdGhhdCB0aGUgbWVhbiBhbmQgdmFyaWFuY2Ugb2YgdGhlIGRpc3RyaWJ1dGlvbiBhcmUgdGhlIHNhbWUuIA0KDQoNCiMjIFByYWN0aWNhbCBydWxlcyBvZiB0aHVtYiBmb3IgY2hvb3NpbmcgbW9kZWxzIA0KDQpUaGVyZSBhcmUgZGlmZmVyZW5jZXMgYmV0d2VlbiB0aGVzZSBjbGFzc2ljIEFOT1ZBIG1vZGVsIGFuZCB0aGUgbGluZWFyIG1peGVkIG1vZGVsLiAgQXMgYSBydWxlLCB5b3UgdXNlIHRoZSBmaXhlZC1lZmZlY3RzIG1vZGVscyB3aGVuOg0KDQotIFlvdSBrbm93IHRoYXQgZWFjaCBncm91cCBpcyByZWdhcmRlZCBhcyB1bmlxdWUsIGFuZCB5b3Ugd2FudCB0byBkcmF3IGNvbmNsdXNpb25zIG9uIGVhY2ggb2YgdGhlc2Ugc3BlY2lmaWMgZ3JvdXBzLCBhbmQgeW91IGFsc28ga25vdyBhbGwgdGhlIGdyb3VwcyBhIHByaW9yaSBlLmcuIHNleCBvciByYWNlDQoNCi0gSWYgdGhlIGdyb3VwcyBjYW4gYmUgY29uc2lkZXJlZCBhcyBhIHNhbXBsZSBmcm9tIHNvbWUgKHJlYWwgb3IgaHlwb3RoZXRpY2FsKSBwb3B1bGF0aW9uIG9mIGdyb3Vwcywgc3VjaCBhcyBvdXIgTVNBIGV4YW1wbGUsIGFuZCB5b3Ugd2FudCB0byBkcmF3IGNvbmNsdXNpb25zIGFib3V0IHRoaXMgcG9wdWxhdGlvbiBvZiBncm91cHMsIHRoZW4gdGhlIHJhbmRvbSBlZmZlY3RzIG1vZGVsIGlzIGFwcHJvcHJpYXRlLg0KICAgIA0KKldIWT8qICBiZWNhdXNlIGlmIHlvdSBoYXZlIGEgKkxBUkdFKiBudW1iZXIgb2YgZ3JvdXBzLCBzYXkgJG5faiQgPiAxMCwgdGhlbiB0aGUgb2RkcyB0aGF0IHlvdSBhcmUgcmVhbGx5IGludGVyZXN0ZWQgaW4gYWxsIHBvc3NpYmxlIGRpZmZlcmVuY2UgaW4gdGhlIG1lYW5zIGlzIHByb2JhYmx5IHByZXR0eSBsb3csIGFuZCB0aGUgbW9kZWwgaGFzIGxvdHMgb2YgcGFyYW1ldGVycyB0aGF0IHlvdSBkbyBub3QgcmVhbGx5IGNhcmUgYWJvdXQuIA0KIA0KIyMgTXVsdGktbGV2ZWwgZGF0YSBzb3VyY2VzIA0KQmVmb3JlIHdlIG1vdmUgZm9yd2FyZCBpbnRvIGFjdHVhbGx5IHNlZWluZyBob3cgdG8gdXNlIFIgdG8gZXN0aW1hdGUgbXVsdGktbGV2ZWwgbW9kZWxzLCB3ZSBtdXN0IHN0YXRlIGEgY2F2ZWF0LiBOb3QgYWxsIHF1ZXN0aW9ucyB0aGF0IHlvdSBtYXkgY29tZSB1cCB3aXRoIGludm9sdmUgbXVsdGktbGV2ZWwgcHJvcG9zaXRpb25zLCBub3IgZG8gYWxsIHR5cGVzIG9mIGRhdGEgbmVjZXNzYXJpbHkgaGF2ZSB0aGUgcmVxdWlyZWQgZWxlbWVudHMgdG8gZG8gYSB0cmFkaXRpb25hbCBtdWx0aS1sZXZlbCBhbmFseXNpcywgZnJvbSBhIHNwYXRpYWwgZGVtb2dyYXBoaWMgcGVyc3BlY3RpdmUsIG9yIHRoZSBkYXRhIG5lY2Vzc2FyeSB0byBkbyBhIHBsYWNlLWZvY3VzZWQgdHlwZSBvZiBtb2RlbCBtYXkgb25seSBiZSBhdmFpbGFibGUgaW4gcmVzdHJpY3RlZC11c2UgdmVyc2lvbnMgb2YgcHVibGljbHkgYXZhaWxhYmxlIGRhdGEuIA0KDQpTb21lIGV4YW1wbGVzIG9mIHB1YmxpYy11c2UgZGF0YSB3aXRoIHBsYWNlLWJhc2VkIGhpZ2hlciBsZXZlbCB1bml0cyBpZGVudGlmaWVkIGFyZToNCg0KLSBFQ0xTLUsgMTk5OCBhbmQgMjAxMSAoU2Nob29sIGlkZW50aWZpZXIpDQotIEJSRlNTIG1hbnkgeWVhcnMgKHByZSAyMDE0IE1TQSBpZGVudGlmaWVyLCBwb3N0IDIwMTQsIE1TQSBpZGVudGlmaWVyKQ0KLSBBQ1MgbWljcm9kYXRhIChQVU1BLCBNU0EsIFN0YXRlKQ0KLSBEZW1vZ3JhcGhpYyBhbmQgSGVhbHRoIFN1cnZleSwgbWFueSBjb3VudHJpZXMsIG1hbnkgeWVhcnMgKFJlZ2lvbiwgR1BTIGNvb3JkaW5hdGUgZm9yIHNhbXBsaW5nIHVuaXRzKQ0KDQpXaGlsZSBtYW55IG90aGVyIGRhdGEgc291cmNlcyBhbHNvIGFsbG93IGZvciB0aGUgdHlwZXMgb2YgbW9kZWxzIHdlIGFyZSBkZXNjcmliaW5nIGhlcmUsIHRoZXNlIGFyZSB3aWRlbHkgdXNlZC4NCg0KT3RoZXIgZGF0YSBzb3VyY2VzIHRoYXQgZG8gbm90IGFsbG93IGZvciBwbGFjZS1iYXNlZCBtdWx0aS1sZXZlbCBtb2RlbHMgaW4gdGhlaXIgcHVibGljIHVzZSBkYXRhLCBidXQgZG8gYWxsb3cgZm9yIGl0IGluIHRoZSByZXN0cmljdGVkIHVzZSBkYXRhIGFyZToNCg0KLSBOYXRpb25hbCBIZWFsdGggYW5kIE51dHJpdGlvbiBFeGFtaW5hdGlvbiBTdXJ2ZXkgKE5IQU5FUykNCi0gTmF0aW9uYWwgSGVhbHRoIEludGVydmlldyBTdXJ2ZXkgKE5ISVMpDQotIE5hdGlvbmFsIExvbmdpdHVkaW5hbCBTdHVkeSBvZiBBZG9sZXNjZW50IHRvIEFkdWx0IEhlYWx0aCAoQWRkSGVhbHRoKQ0KLSBQYW5lbCBTdHVkeSBvZiBJbmNvbWUgRHluYW1pY3MgKFBTSUQpDQotIE5hdGlvbmFsIExvbmdpdHVkaW5hbCBTdHVkeSBvZiBZb3V0aCAoTkxTWSkNCg0KDQojIyBVc2luZyBSIHRvIGVzdGltYXRlIG11bHRpLWxldmVsIG1vZGVscyANCg0KSW4gUiB0aGVyZSAgYXJlIHNldmVyYWwgbGlicmFyaWVzIHRoYXQgY2FuIGJlIHVzZWQgdG8gZXN0aW1hdGUgbXVsdGktbGV2ZWwgbW9kZWxzLiBUaGUgYGxtZTRgIGxpYnJhcnkgcHJvdmlkZXMgYSBjdXJyZW50IGFuZCBjb250aW51b3VzbHkgZGV2ZWxvcGVkIGZyYW1ld29yayBmb3IgZXN0aW1hdGluZyB0aGUgdHlwZXMgb2YgbW9kZWxzIHdlIGFyZSBjb25zaWRlcmluZywgd2l0aCBvcHRpb25zIGZvciBzZXZlcmFsIGRpZmZlcmVudCBkaXN0cmlidXRpb25zIGZvciBoYW5kbGluZyBjb250aW51b3VzLCBkaXNjcmV0ZSBhbmQgY291bnQgb3V0Y29tZXMuIA0KDQpUaGUgcHJpbWFyeSBmdW5jdGlvbiwgZGVwZW5kaW5nIG9uIGhvdyB5b3VyIG91dGNvbWUgaXMgbWVhc3VyZWQsIHdpbGwgZWl0aGVyIGJlIGBsbWVyKClgIGZvciBOb3JtYWxseSBkaXN0cmlidXRlZCBvdXRjb21lcywgb3IgYGdsbWVyKClgIGZvciBjb3VudCBhbmQgYmluYXJ5IG91dGNvbWVzLiBTeW50YXggZm9yIHRoZSBnZW5lcmFsIG1vZGVscyBhcmUgdmVyeSBzaW1pbGFyIHRvIG90aGVyIFIgZnVuY3Rpb25zIGZvciByZWdyZXNzaW9uIHdlIGhhdmUgc2VlbiBpbiB0aGlzIGNvdXJzZS4gDQoNCkZvciBleGFtcGxlLCBpZiBvdXIgb3V0Y29tZSBpcyBiaW5hcnkgKDAvMSksIGFuZCBpcyBjYWxsZWQgYHlgIGFuZCB3ZSBoYXZlIG9uZSBpbmRpdmlkdWFsIGxldmVsIHByZWRpY3RvciwgYHhfMWAsIGFuZCBvdXIgZ3JvdXBpbmcgdmFyaWFibGUgaXMgY2FsbGVkIGBwbGFjZWAsIGFuZCBvdXIgZGF0YXNldCBpcyBjYWxsZWQgYG15ZGF0YWAsIHRoZW4gb3VyIG1vZGVsIHdvdWxkIGxvb2sgbGlrZSB0aGlzOg0KDQpgZ2xtZXIoeSB+IHhfMSArICgxfHBsYWNlKSwgZGF0YT1teWRhdGEsIGZhbWlseT1iaW5vbWlhbClgDQoNClRoZSBzeW50YXggYCgxfHBsYWNlKWAgdGVsbHMgUiB0aGF0IHdlIHdhbnQgdG8gY29uc2lkZXIgYSByYW5kb20gaW50ZXJjZXB0IHRlcm0gZm9yIGVhY2ggcGxhY2UgaW4gdGhlIGRhdGEuIFRoZSBgMWAgaW5kaWNhdGVzIHRoYXQgd2UgYXJlIHNwZWNpZnlpbmcgYSBjb25zdGFudCBmb3IgZWFjaCBwbGFjZSwganVzdCBsaWtlIGluIGEgcmVndWxhciByZWdyZXNzaW9uIG1vZGVsLCB0aGUgaW50ZXJjZXB0IGlzIGVzdGltYXRlZCBieSB0aGUgY29tcHV0ZXIgZ2VuZXJhdGluZyBhIHZlY3RvciBvZiAxJ3MgYXMgdGhlIGZpcnN0IGVsZW1lbnQgaW4gdGhlIGRlc2lnbiBtYXRyaXguIA0KDQpJbiB0aGUgbmV4dCBzZWN0aW9uLCB3ZSB3aWxsIHVzZSBSIHRvIGFuYWx5emUgYW4gb3V0Y29tZSBmcm9tIHRoZSAyMDE2IFtCZWhhdmlvcmFsIFJpc2sgRmFjdG9yIFN1cnZlaWxsYW5jZSBTeXN0ZW0gU01BUlQgTU1TQV0oaHR0cHM6Ly93d3cuY2RjLmdvdi9icmZzcy9zbWFydC9zbWFydF8yMDE2Lmh0bWwpKEJSRlNTKSBkYXRhLiANCg0KVGhlIEJSRlNTIGRhdGEgYXJlIGEgbmF0aW9uYWxseSByZXByZXNlbnRhdGl2ZSBwaG9uZSBzdXJ2ZXkgZGVzaWduZWQgdG8gbWVhc3VyZSBuYXRpb25hbCBhbmQgbG9jYWwgdHJlbmRzIGluIG1hbnkgaGVhbHRoIG91dGNvbWVzIGFuZCBtb3JiaWRpdGllcywgYW5kIHRoZSB1c2Ugb2YgaGVhbHRoIHJlc291cmNlcy4gVGhlIEJSRlNTIGhhcyBiZWVuIGNvbGxlY3RlZCBhbm51YWxseSBzaW5jZSAxOTg0LiBUaGUgU01BUlQgZGF0YSBmaWxlLCBpcyBhIHN1YnNldCBvZiB0aGUgbGFyZ2VyIEJSRlNTIGRhdGEgZmlsZSwgd2hpY2ggaWRlbnRpZmllcyB0aGUgbWV0cm9wb2xpdGFuIHN0YXRpc3RpY2FsIGFyZWEgd2hlcmUgZWFjaCBzdXJ2ZXkgcmVzcG9uZGVudCBsaXZlcy4gIA0KDQoNCg0KYGBge3IgbG9hZCBkYXRhJnJlY29kZSwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0NCiNsb2FkIGJyZnNzDQpsaWJyYXJ5KGNhcikNCmxpYnJhcnkoc3RhcmdhemVyKQ0KbGlicmFyeShzdXJ2ZXkpDQpsaWJyYXJ5KHNqUGxvdCkNCmxpYnJhcnkoZ2dwbG90MikNCmxpYnJhcnkocGFuZGVyKQ0KbGlicmFyeShrbml0cikNCmxpYnJhcnkodGlkeWNlbnN1cykNCmxpYnJhcnkoZHBseXIpDQpgYGANCg0KDQpgYGB7cn0NCmxvYWQodXJsKCJodHRwczovL2dpdGh1Yi5jb20vY29yZXlzcGFya3MvZGF0YS9ibG9iL21hc3Rlci9icmZzc18yMDE3LlJkYXRhP3Jhdz10cnVlIikpDQoNCnNldC5zZWVkKDEyMzQ1KQ0KI3NhbXBzPC1zYW1wbGUoMTpucm93KGJyZnNzXzE3KSwgc2l6ZSA9IDQwMDAwLCByZXBsYWNlPUYpDQojYnJmc3NfMTc8LWJyZnNzXzE3W3NhbXBzLF0NCiNUaGUgbmFtZXMgaW4gdGhlIGRhdGEgYXJlIHZlcnkgdWdseSwgc28gSSBtYWtlIHRoZW0gbGVzcyB1Z2x5DQpuYW1zPC1uYW1lcyhicmZzc18xNykNCiN3ZSBzZWUgc29tZSBuYW1lcyBhcmUgbG93ZXIgY2FzZSwgc29tZSBhcmUgdXBwZXIgYW5kIHNvbWUgaGF2ZSBhIGxpdHRsZSBfIGluIHRoZSBmaXJzdCBwb3NpdGlvbi4gVGhpcyBpcyBhIG5pZ2h0bWFyZS4NCg0KbmV3bmFtZXM8LWdzdWIocGF0dGVybiA9ICJfIiwNCiAgICAgICAgICAgICAgIHJlcGxhY2VtZW50ID0gICIiLA0KICAgICAgICAgICAgICAgeCA9ICBuYW1zKQ0KDQpuYW1lcyhicmZzc18xNyk8LXRvbG93ZXIobmV3bmFtZXMpDQoNCmBgYA0KDQojIyMgUmVjb2RlIHZhcmlhYmxlcw0KYGBge3J9DQojc2V4DQpicmZzc18xNyRtYWxlPC1pZmVsc2UoYnJmc3NfMTckc2V4PT0xLCAxLCAwKQ0KDQojQk1JDQpicmZzc18xNyRibWk8LWlmZWxzZShpcy5uYShicmZzc18xNyRibWk1KT09VCwgTkEsIGJyZnNzXzE3JGJtaTUvMTAwKQ0KDQojSGVhbHRoeSBkYXlzDQpicmZzc18xNyRoZWFsdGhkYXlzPC1SZWNvZGUoYnJmc3NfMTckcGh5c2hsdGgsIHJlY29kZXMgPSAiODg9MDsgNzc9TkE7IDk5PU5BIikNCg0KI0hlYWx0aHkgbWVudGFsIGhlYWx0aCBkYXlzDQpicmZzc18xNyRoZWFsdGhtZGF5czwtUmVjb2RlKGJyZnNzXzE3JG1lbnRobHRoLCByZWNvZGVzID0gIjg4PTA7IDc3PU5BOyA5OT1OQSIpDQoNCmJyZnNzXzE3JGJhZGhlYWx0aDwtUmVjb2RlKGJyZnNzXzE3JGdlbmhsdGgsIHJlY29kZXM9IjQ6NT0xOyAxOjM9MDsgZWxzZT1OQSIpDQojcmFjZS9ldGhuaWNpdHkNCmJyZnNzXzE3JGJsYWNrPC1SZWNvZGUoYnJmc3NfMTckcmFjZWdyMywgcmVjb2Rlcz0iMj0xOyA5PU5BOyBlbHNlPTAiKQ0KYnJmc3NfMTckd2hpdGU8LVJlY29kZShicmZzc18xNyRyYWNlZ3IzLCByZWNvZGVzPSIxPTE7IDk9TkE7IGVsc2U9MCIpDQpicmZzc18xNyRvdGhlcjwtUmVjb2RlKGJyZnNzXzE3JHJhY2VncjMsIHJlY29kZXM9IjM6ND0xOyA5PU5BOyBlbHNlPTAiKQ0KYnJmc3NfMTckaGlzcGFuaWM8LVJlY29kZShicmZzc18xNyRyYWNlZ3IzLCByZWNvZGVzPSI1PTE7IDk9TkE7IGVsc2U9MCIpDQoNCmJyZnNzXzE3JHJhY2VfZXRoPC1SZWNvZGUoYnJmc3NfMTckcmFjZWdyMywgDQpyZWNvZGVzPSIxPSduaHdoaXRlJzsgMj0nbmggYmxhY2snOyAzPSduaCBvdGhlcic7ND0nbmggbXVsdGlyYWNlJzsgNT0naGlzcGFuaWMnOyBlbHNlPU5BIiwNCmFzLmZhY3RvciA9IFQpDQpicmZzc18xNyRyYWNlX2V0aDwtcmVsZXZlbChicmZzc18xNyRyYWNlX2V0aCwgcmVmID0gIm5od2hpdGUiKQ0KDQojaW5zdXJhbmNlDQpicmZzc18xNyRpbnM8LVJlY29kZShicmZzc18xNyRobHRocGxuMSwgcmVjb2RlcyA9Ijc6OT1OQTsgMT0xOzI9MCIpDQoNCiNpbmNvbWUgZ3JvdXBpbmcNCmJyZnNzXzE3JGluYzwtUmVjb2RlKGJyZnNzXzE3JGluY29tZywgcmVjb2RlcyA9ICI5PSBOQTsxPScxX2x0MTVrJzsgMj0nMl8xNS0yNWsnOzM9JzNfMjUtMzVrJzs0PSc0XzM1LTUwayc7NT0nNV81MGtwbHVzJyIsIGFzLmZhY3RvciA9IFQpDQpicmZzc18xNyRpbmM8LWFzLm9yZGVyZWQoYnJmc3NfMTckaW5jKQ0KI2VkdWNhdGlvbiBsZXZlbA0KYnJmc3NfMTckZWR1YzwtUmVjb2RlKGJyZnNzXzE3JGVkdWNhLA0KcmVjb2Rlcz0iMToyPScwUHJpbSc7IDM9JzFzb21laHMnOyA0PScyaHNncmFkJzsgNT0nM3NvbWVjb2wnOyA2PSc0Y29sZ3JhZCc7OT1OQSIsDQphcy5mYWN0b3I9VCkNCmJyZnNzXzE3JGVkdWM8LXJlbGV2ZWwoYnJmc3NfMTckZWR1YywgcmVmPScyaHNncmFkJykNCg0KI2VtcGxveW1lbnQNCmJyZnNzXzE3JGVtcGxveTwtUmVjb2RlKGJyZnNzXzE3JGVtcGxveTEsDQpyZWNvZGVzPSIxOjI9J2VtcGxveWxveWVkJzsgMjo2PSduaWxmJzsgNz0ncmV0aXJlZCc7IDg9J3VuYWJsZSc7IGVsc2U9TkEiLA0KYXMuZmFjdG9yPVQpDQpicmZzc18xNyRlbXBsb3k8LXJlbGV2ZWwoYnJmc3NfMTckZW1wbG95LCByZWY9J2VtcGxveWxveWVkJykNCg0KI21hcml0YWwgc3RhdHVzDQpicmZzc18xNyRtYXJzdDwtUmVjb2RlKGJyZnNzXzE3JG1hcml0YWwsDQpyZWNvZGVzPSIxPSdtYXJyaWVkJzsgMj0nZGl2b3JjZWQnOyAzPSd3aWRvd2VkJzsgND0nc2VwYXJhdGVkJzsgNT0nbm0nOzY9J2NvaGFiJzsgZWxzZT1OQSIsDQphcy5mYWN0b3I9VCkNCmJyZnNzXzE3JG1hcnN0PC1yZWxldmVsKGJyZnNzXzE3JG1hcnN0LA0KICAgICAgICAgICAgICAgICAgICAgICAgcmVmPSdtYXJyaWVkJykNCg0KI0FnZSBjdXQgaW50byBpbnRlcnZhbHMNCmJyZnNzXzE3JGFnZWM8LWN1dChicmZzc18xNyRhZ2U4MCwNCiAgICAgICAgICAgICAgICAgICBicmVha3M9YygwLDI0LDM5LDU5LDc5LDk5KSkNCg0KI0JNSSwgaW4gdGhlIGJyZnNzXzE3YSB0aGUgYm1pIHZhcmlhYmxlIGhhcyAyIGltcGxpZWQgZGVjaW1hbCBwbGFjZXMsDQojc28gd2UgbXVzdCBkaXZpZGUgYnkgMTAwIHRvIGdldCByZWFsIGJtaSdzDQoNCmJyZnNzXzE3JGJtaTwtYnJmc3NfMTckYm1pNS8xMDANCg0KI3Ntb2tpbmcgY3VycmVudGx5DQpicmZzc18xNyRzbW9rZTwtUmVjb2RlKGJyZnNzXzE3JHNtb2tlcjMsIA0KcmVjb2Rlcz0iMToyPTE7IDM6ND0wOyBlbHNlPU5BIikNCiNicmZzc18xNyRzbW9rZTwtcmVsZXZlbChicmZzc18xNyRzbW9rZSwgcmVmID0gIk5ldmVyU21va2VkIikNCg0KYnJmc3NfMTckb2Jlc2U8LWlmZWxzZShpcy5uYShicmZzc18xNyRibWkpPT1ULCBOQSwgDQogICAgICAgICAgICAgICAgICAgICAgIGlmZWxzZShicmZzc18xNyRibWk+MzAsMSwwKSkNCg0KYGBgDQoNCkkgd2FudCB0byBzZWUgaG93IG1hbnkgcGVvcGxlIHdlIGhhdmUgaW4gZWFjaCBNU0EgaW4gdGhlIGRhdGE6DQoNCmBgYHtyfQ0KDQojTm93IHdlIHdpbGwgYmVnaW4gZml0dGluZyB0aGUgbXVsdGlsZXZlbCByZWdyZXNzaW9uIG1vZGVsIHdpdGggdGhlIG1zYQ0KI3RoYXQgdGhlIHBlcnNvbiBsaXZlcyBpbiBiZWluZyB0aGUgaGlnaGVyIGxldmVsDQpoZWFkKGRhdGEuZnJhbWUobmFtZT10YWJsZShicmZzc18xNyRtbXNhbmFtZSksIA0KICAgICAgICAgICAgICAgIGlkPXVuaXF1ZShicmZzc18xNyRtbXNhKSkpDQojcGVvcGxlIHdpdGhpbiBlYWNoIG1zYQ0KDQojSG93IG1hbnkgdG90YWwgTVNBcyBhcmUgaW4gdGhlIGRhdGE/DQpsZW5ndGgodGFibGUoYnJmc3NfMTckbW1zYSkpDQojTVNBcw0KYGBgDQoNCg0KIyMjIEhpZ2hlciBsZXZlbCBwcmVkaWN0b3JzDQpXZSB3aWxsIG9mdGVuIGJlIGludGVyZXN0ZWQgaW4gZmFjdG9ycyBhdCBib3RoIHRoZSBpbmRpdmlkdWFsICpBTkQqIGNvbnRleHR1YWwgbGV2ZWxzLiBUbyBpbGx1c3RyYXRlIHRoaXMsIEkgd2lsbCB1c2UgZGF0YSBmcm9tIHRoZSBBbWVyaWNhbiBDb21tdW5pdHkgU3VydmV5IG1lYXN1cmVkIGF0IHRoZSBNU0EgbGV2ZWwuIFNwZWNpZmljYWxseSwgSSB1c2UgdGhlIERQMyB0YWJsZSwgd2hpY2ggcHJvdmlkZXMgZWNvbm9taWMgY2hhcmFjdGVyaXN0aWNzIG9mIHBsYWNlcywgZnJvbSB0aGUgMjAxMCA1IHllYXIgQUNTIFtMaW5rXShodHRwOi8vd3d3LmNlbnN1cy5nb3YvYWNzL3d3dy9kYXRhX2RvY3VtZW50YXRpb24vc3BlY2lhbF9kYXRhX3JlbGVhc2UvKS4NCg0KVG8gbWVhc3VyZSBtYWNybyBsZXZlbCB2YXJpYWJsZXMsIEkgd2lsbCBpbmNsdWRlIHNvbWUgQ2Vuc3VzIHZhcmlhYmxlcyBmcm9tIHRoZSBBQ1MgMjAxMSA1IFllYXIgZXN0aW1hdGVzIGxvYWQgaW4gQUNTIGRhdGEgZnJvbSAqKl90aWR5Y2Vuc3VzXyoqLg0KVGhlIGZpcnN0IHNldCBvZiB2YXJpYWJsZXMgaW5jbHVkZXMgaW5mb3JtYXRpb24gb24gdGhlIGVjb25vbWljIGNvbmRpdGlvbnMgb2YgdGhlIE1TQSwgc3BlY2lmaWNhbGx5IHBvdmVydHkgYW5kIHVuZW1wbG95bWVudC4NCmBgYHtyfQ0KdXNhY3M8LWdldF9hY3MoZ2VvZ3JhcGh5ID0gIm1ldHJvcG9saXRhbiBzdGF0aXN0aWNhbCBhcmVhL21pY3JvcG9saXRhbiBzdGF0aXN0aWNhbCBhcmVhIiwgeWVhciA9IDIwMTEsDQogICAgICAgICAgICAgICAgdmFyaWFibGVzPWMoICJEUDA1XzAwMDFFIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkRQMDNfMDA2MkUiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiRFAwNF8wMDAzUEUiKSAsDQogICAgICAgICAgICAgICAgc3VtbWFyeV92YXIgPSAiQjAxMDAxXzAwMSIsDQogICAgICAgICAgICAgICAgZ2VvbWV0cnkgPSBGLA0KICAgICAgICAgICAgICAgb3V0cHV0ID0gIndpZGUiKQ0KDQp1c2FjczwtdXNhY3MlPiUNCiAgbXV0YXRlKHRvdHBvcD0gRFAwNV8wMDAxRSwNCiAgICAgICAgIG1lZGhoaW5jPURQMDNfMDA2MkUsDQogICAgICAgICBwdmFjYW50PURQMDRfMDAwM1BFLzEwMCklPiUNCiAgZHBseXI6OnNlbGVjdChHRU9JRCxOQU1FLCB0b3Rwb3AsIG1lZGhoaW5jLCBwdmFjYW50KQ0KDQoNCmhlYWQodXNhY3MpDQpgYGANCg0KSSBhbHNvIGhhdmUgc2VncmVnYXRpb24gbWVhc3VyZXMgYXQgdGhlIE1TQSBsZXZlbCB0aGF0IEkgbWFkZSBbaGVyZV0oaHR0cDovL3JwdWJzLmNvbS9jb3JleV9zcGFya3MvMTE2MDMyKSwgSSB3aWxsIG1lcmdlIHRoZXNlIGluIHRvby4NCg0KDQojIyMgQ2xlYW4gYW5kIHN0YW5kYXJkaXplIGNvbnRleHR1YWwgZGF0YQ0KYGBge3J9DQpteXNjYWxlPC1mdW5jdGlvbih4KXthcy5udW1lcmljKHNjYWxlKHgpKX0NCnVzYWNzPC11c2FjcyAlPiUNCiAgbXV0YXRlX2F0KGMoICJtZWRoaGluYyIsICJwdmFjYW50IiksbXlzY2FsZSkNCg0KbWVyZ2VkPC11c2FjcyU+JQ0KICBmaWx0ZXIoY29tcGxldGUuY2FzZXMoLikpDQpoZWFkKG1lcmdlZCkNCmBgYA0KDQpOb3csIEkgbWVyZ2UgdGhlIGRhdGEgYmFjayB0byB0aGUgaW5kaXZpZHVhbCBsZXZlbCBkYXRhOg0KYGBge3J9DQptZXJnZWQ8LW1lcmdlKHg9YnJmc3NfMTcsDQogICAgICAgICAgICAgIHk9bWVyZ2VkLA0KICAgICAgICAgICAgICBieS54PSJtbXNhIiwNCiAgICAgICAgICAgICAgYnkueT0iR0VPSUQiLA0KICAgICAgICAgICAgICBhbGwueD1GKQ0KDQpgYGANCg0KTGV0J3Mgc2VlIHRoZSBnZW9ncmFwaGljIHZhcmlhdGlvbiBpbiB0aGVzZSBlY29ub21pYyBpbmRpY2F0b3JzOg0KYGBge3IsIHJlc3VsdHM9J2hpZGUnfQ0KbGlicmFyeSh0aWdyaXMpDQptc2E8LWNvcmVfYmFzZWRfc3RhdGlzdGljYWxfYXJlYXMoY2I9VCkNCm1zYV9lYzwtZ2VvX2pvaW4obXNhLA0KICAgICAgICAgICAgICAgICB1c2FjcywgIkNCU0FGUCIsICJHRU9JRCIsIGhvdz0iaW5uZXIiKQ0KDQpgYGANCg0KYGBge3J9DQpsaWJyYXJ5KFJDb2xvckJyZXdlcikNCmxpYnJhcnkodG1hcCkNCnRtX3NoYXBlKG1zYV9lYykrDQogIHRtX3BvbHlnb25zKCJwdmFjYW50IiwNCiAgICAgICAgICAgICAgc3R5bGU9InF1YW50aWxlIiwNCiAgICAgICAgICAgICAgbj01LA0KICAgICAgICAgICAgICBsZWdlbmQuaGlzdCA9IFRSVUUpICsNCiAgIHRtX2xheW91dChsZWdlbmQub3V0c2lkZSA9IFRSVUUsDQogICAgICAgICAgICAgdGl0bGUgPSAiJSBWYWNhbnQgSG91c2luZyIpIA0KDQoNCnRtX3NoYXBlKG1zYV9lYykrDQogIHRtX3BvbHlnb25zKCJtZWRoaGluYyIsDQogICAgICAgICAgICAgIHN0eWxlPSJxdWFudGlsZSIsDQogICAgICAgICAgICAgIG49NSwNCiAgICAgICAgICAgICAgbGVnZW5kLmhpc3QgPSBUUlVFKSArDQogICB0bV9sYXlvdXQobGVnZW5kLm91dHNpZGUgPSBUUlVFLA0KICAgICAgICAgICAgIHRpdGxlID0gIk1lZGlhbiBIb3VzZWhvbGQgSW5jb21lIikgDQoNCg0KDQpgYGANCg0KTWVyZ2UgdGhlIE1TQSBkYXRhIHRvIHRoZSBCUkZTUyBkYXRhDQoNCmBgYHtyIG1lcmdlZH0NCg0KbWVyZ2VkJGJtaXo8LWFzLm51bWVyaWMoc2NhbGUobWVyZ2VkJGJtaSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNlbnRlcj1ULA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2NhbGU9VCkpDQojbWVyZ2VkPC1tZXJnZWRbY29tcGxldGUuY2FzZXMobWVyZ2VkWywgYygiYm1peiIsICJyYWNlX2V0aCIsICJhZ2VjIiwgImVkdWMiLCAiZ2luaSIpXSksXQ0KI2FuZCBtZXJnZSB0aGUgZGF0YSBiYWNrIHRvIHRoZSBraWRzIGRhdGENCg0KbWVyZ2VkPC1tZXJnZWQlPiUNCiAgZHBseXI6OnNlbGVjdChibWl6LCBvYmVzZSwgbW1zYSwgYWdlYywgZWR1YywgcmFjZV9ldGgsc21va2UsIGhlYWx0aG1kYXlzLCBiYWRoZWFsdGgsYm1pLG1lZGhoaW5jLHB2YWNhbnQsIG1hbGUsIG1tc2F3dCwgbW1zYW5hbWUgKSU+JQ0KICBmaWx0ZXIoY29tcGxldGUuY2FzZXMoLikpDQoNCg0KaGVhZChtZXJnZWRbLCBjKCJibWl6IiwgIm1hbGUiLCAiYWdlYyIsICJlZHVjIiwibWVkaGhpbmMiLCAicHZhY2FudCIsICJtbXNhIildKQ0KDQptZWFuYm1pPC1tZWFuKG1lcmdlZCRibWksIG5hLnJtPVQpDQoNCnNkYm1pPC1zZChtZXJnZWQkYm1pLCBuYS5ybT1UKQ0KDQoNCmBgYA0KDQpBcyBhIGdlbmVyYWwgcnVsZSwgSSB3aWxsIGRvIGEgYmFzaWMgZml4ZWQtZWZmZWN0cyBBTk9WQSBhcyBhIHByZWN1cnNvciB0byBkb2luZyBmdWxsIG11bHRpLWxldmVsIG1vZGVscywganVzdCB0byBzZWUgaWYgdGhlcmUgaXMgYW55IHZhcmlhdGlvbiBhbW9uZ3N0IG15IGhpZ2hlciBsZXZlbCB1bml0cyAoZ3JvdXBzKS4gSWYgSSBkbyBub3Qgc2VlIGFueSB2YXJpYXRpb24gaW4gbXkgaGlnaGVyIGxldmVsIHVuaXRzLCBJIGdlbmVyYWxseSB3aWxsIG5vdCBwcm9jZWVkIHdpdGggdGhlIHByb2Nlc3Mgb2YgbXVsdGktbGV2ZWwgbW9kZWxpbmcuDQoNCmBgYHtyIGFub3ZhLG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9DQpmaXQuYW48LWxtKGJtaXp+YXMuZmFjdG9yKG1tc2EpLA0KICAgICAgICAgICBtZXJnZWQpDQphbm92YShmaXQuYW4pDQpgYGANCg0KDQojIyMgdXNlIGdsbSgpIGZvciBub24tbm9ybWFsIG91dGNvbWVzDQpgYGB7cn0NCmZpdC5vYjwtZ2xtKG9iZXNlfmFzLmZhY3RvcihtbXNhKSwNCiAgICAgICAgICAgIGZhbWlseT1iaW5vbWlhbCwNCiAgICAgICAgICAgIG1lcmdlZCkNCg0KYW5vdmEoZml0Lm9iLCB0ZXN0PSJDaGlzcSIpDQpgYGANClNvIHdlIHNlZSBzaWduaWZpY2FudCB2YXJpYXRpb24gaW4gb3VyIG91dGNvbWVzIGFjcm9zcyB0aGUgaGlnaGVyIGxldmVsIHVuaXRzLg0KDQpOb3cgd2UgZml0IHRoZSBoaWVyYXJjaGljYWwgbW9kZWwNCmBgYHtyLCBtZXNzYWdlPUZBTFNFfQ0KbGlicmFyeShsbWU0KQ0KbGlicmFyeShsbWVyVGVzdCkNCmxpYnJhcnkoYXJtKQ0KYGBgDQoNCkJhc2ljIGhpZXJhcmNoaWNhbCBtb2RlbCBmb3IgbWVhbnMgb2YgZWFjaCBNU0E6DQoNCmBgYHtyfQ0KDQpmaXQ8LWxtZXIoYm1pen4oMXxtbXNhKSwNCiAgICAgICAgICAgZGF0YT1tZXJnZWQpDQphcm06OmRpc3BsYXkoZml0LA0KICAgICAgICAgICAgIGRldGFpbD1UKQ0KDQpgYGANCg0KYGBge3J9DQptZXJnZWQkcHJlZGJtaTwtc2RibWkqKGZpdHRlZChmaXQpKSttZWFuYm1pDQoNCmhlYWQocmFuZWYoZml0KSRtbXNhKQ0KDQpkaW0ocmFuZWYoZml0KSRtbXNhKQ0KDQpyYXRlPC0gc2RibWkqKGZpeGVmKGZpdCkrcmFuZWYoZml0KSRtbXNhKSttZWFuYm1pDQplc3Q8LWRhdGEuZnJhbWUocmF0ZSA9cmF0ZSwgaWQ9cm93bmFtZXMocmFuZWYoZml0KSRtbXNhKSkNCmhlYWQoZXN0KQ0KDQpgYGANCg0KDQpgYGB7cn0NCm1zYV9lYzwtbWVyZ2UobXNhX2VjLCBlc3QsDQogICAgICAgICAgICAgIGJ5Lng9IkNCU0FGUCIsIGJ5Lnk9ImlkIikNCg0KdG1fc2hhcGUobXNhX2VjKSsNCiAgdG1fcG9seWdvbnMoIlguSW50ZXJjZXB0LiIsDQogICAgICAgICAgICAgIHN0eWxlPSJxdWFudGlsZSIsDQogICAgICAgICAgICAgIG49NSwNCiAgICAgICAgICAgICAgbGVnZW5kLmhpc3QgPSBUUlVFKSArDQogICB0bV9sYXlvdXQobGVnZW5kLm91dHNpZGUgPSBUUlVFLA0KICAgICAgICAgICAgIHRpdGxlID0gIkVzdGltYXRlZCBCTUkiKSANCg0KYGBgDQoNCmBgYHtyfQ0KDQpjaXR5bWVhbnM8LWFnZ3JlZ2F0ZShjYmluZChibWksIHByZWRibWkpfm1tc2FuYW1lLG1lcmdlZCwgbWVhbikNCmhlYWQoY2l0eW1lYW5zLCBuPTEwKQ0KDQpwbG90KHByZWRibWl+Ym1pLCBjaXR5bWVhbnMpDQpgYGANCg0KTW9kZWwgd2l0aCBpbmRpdmlkdWFsIGxldmVsIHByZWRpY3RvcnM6DQoNCmBgYHtyfQ0KZml0MjwtbG1lcihibWl6fm1hbGUrYWdlYytlZHVjKygxfG1tc2EpLA0KICAgICAgICAgICBkYXRhPW1lcmdlZCwNCiAgICAgICAgICAgbmEuYWN0aW9uPW5hLm9taXQpDQphcm06OmRpc3BsYXkoZml0MiwgZGV0YWlsPVQpDQoNCmBgYA0KDQpXZSBkbyBhIGxpa2VsaWhvb2QgcmF0aW8gdGVzdCB0byBzZWUgaWYgb3VyIGluZGl2aWR1YWwgbGV2ZWwgdmFyaWFibGVzIGFyZSBleHBsYWluaW5nIGFueXRoaW5nIGFib3V0IG91dCBvdXRjb21lOg0KDQpgYGB7cn0NCmFub3ZhKGZpdCwgZml0MikNCg0KYGBgDQoNClRoZXkgZG8uDQoNCg0KV2UgYWxzbyB0eXBpY2FsbHkgd291bGQgdGVzdCB0byBzZWUgaWYgdGhlIHJhbmRvbSBlZmZlY3QgdGVybSBpcyBzaWduaWZpY2FudCwgU0FTIHB1bXBzIG91dCBhIHRlc3Qgb2YgdGhpcywgc28gd2UgZG8gdGhlIHNhbWUga2luZCBvZiB0aGluZyBpbiBSDQpgYGB7cn0NCg0KcmFuZChmaXQyKQ0KDQpgYGANCg0KV2hpY2ggc2hvd3Mgc2lnbmlmaWNhbnQgdmFyaWF0aW9uIGluIGF2ZXJhZ2UgQk1JIGFjcm9zcyBNU0FzLg0KDQoNClNvbWUgbWF5IGJlIGludGVyZXN0ZWQgaW4gZ2V0dGluZyB0aGUgaW50cmEtY2xhc3MgY29ycmVsYXRpb24gY29lZmZpY2llbnQuIFdoaWxlIEkgZG9uJ3QgdXN1YWxseSBwYXkgYXR0ZW50aW9uIHRvIHRoaXMsIGhlcmUgaXQgaXM6DQpgYGB7ciBJQ0N9DQpsaWJyYXJ5KHNqc3RhdHMpOyBsaWJyYXJ5KHNqUGxvdCkNCmljYyhmaXQyKQ0KcGxvdF9tb2RlbChmaXQsDQogICAgICAgICAgIHR5cGUgPSAicmUiLA0KICAgICAgICAgICBzb3J0LmVzdD0ic29ydC5hbGwiLA0KICAgICAgICAgICBncmlkPUYpDQpgYGANCg0KU28gbGVzcyB0aGFuIDElIG9mIHRoZSB2YXJpYW5jZSBpbiBCTUkgaXMgZHVlIHRvIGRpZmZlcmVuY2UgYmV0d2VlbiBNU0FzLiBUaGF0J3Mgbm90IG11Y2gsIGJ1dCBhY2NvcmRpbmcgdG8gb3VyIHJhbmRvbSBlZmZlY3QgdGVzdGluZywgaXQncyBub3QsIHN0YXRpc3RpY2FsbHkgc3BlYWtpbmcsIDAuDQoNCiMjIyBQb29saW5nIG9mIGVzdGltYXRlcw0KSXQgbWF5IGJlIGluZm9ybWF0aXZlIHRvIHBsb3QgdGhlIGVzdGltYXRlZCBCTUkncyBmb3IgZWFjaCBNU0EgZnJvbSB0aGUgT0xTIGFuZCBtdWx0aWxldmVsIG1vZGVscy4gVGhpcyBzZWN0aW9uIGlsbHVzdHJhdGVzIHRoZSBlZmZlY3RzIG9mICJwb29saW5nIiBhcyBHZWxtYW4gJiBIaWxsIGNoIDEyLiANCg0KYGBge3J9DQojdGhlc2UgbW9kZWxzIGFyZSBnb29kIGZvciBlc3RpbWF0aW5nIGdyb3VwIG1lYW5zIGJldHRlciB0aGFuIHRyYWRpdGlvbmFsIG1ldGhvZHMNCiN0aGlzIGZvbGxvd3MgdGhlIGV4YW1wbGVzIGluIGNoYXB0ZXIgMTIgb2YgR2VsbWFuIGFuZCBIaWxsLCBJIHN0b2xlIHRoZSBjb2RlIGRpcmVjdGx5IGZyb20gdGhlbS4NCg0KI2NvbXBsZXRlIHBvb2xpbmcsIHRoaXMgbW9kZWwgZml0cyB0aGUgZ3JhbmQgbWVhbiBPTkxZDQpmaXQuY3A8LWxtKGJtaX4xLCBtZXJnZWQpDQpkaXNwbGF5KGZpdC5jcCkNCg0KDQojTm8gcG9vbGluZyBpLmUuIGZpeGVkIGVmZmVjdHMgcmVncmVzc2lvbiwgdGhpcyBtb2RlbCBmaXRzIHNlcGFyYXRlIG1lYW5zIGZvciBlYWNoIE1TQSB1c2luZyBPTFMNCmxtLnVucG9vbGVkPC1sbShibWl+ZmFjdG9yKG1tc2EpLTEsIG1lcmdlZCkNCg0KDQojcGFydGlhbCBwb29saW5nLCB0aGlzIG1vZGVsIGZpdHMgdGhlIHBvcHVsYXRpb24gbWVhbiBhbmQgTVNBIGRldmlhdGlvbnMgdXNpbmcgbXVsdGlsZXZlbCBtb2RlbHMNCmZpdDA8LWxtZXIoYm1pfjErKDF8bW1zYSksIG1lcmdlZCkNCg0KI3BhcnRpYWwgcG9vbGluZyB3aXRoIGNvdmFyaWF0ZQ0KZml0MC4xPC1sbWVyKGJtaX5tZWRoaGluYytwdmFjYW50KygxfG1tc2EpLCBtZXJnZWQpDQoNCmBgYA0KDQojIyMgUGxvdCB0aGUgbWVhbnMgb2YgdGhlIGNvdW50aWVzDQpgYGB7cn0NCm1tc2FzPC11bmlxdWUobWVyZ2VkJG1tc2EpDQpKPC1sZW5ndGgodW5pcXVlKG1lcmdlZCRtbXNhKSkNCm5zPC1hcy5udW1lcmljKHRhYmxlKGJyZnNzXzE3JG1tc2FbYnJmc3NfMTckbW1zYSVpbiVtbXNhc10pKQ0Kc2FtcGxlLnNpemUgPC0gYXMubnVtZXJpYyh0YWJsZShicmZzc18xNyRtbXNhW2JyZnNzXzE3JG1tc2ElaW4lbW1zYXNdKSkNCnNhbXBsZS5zaXplLmppdHRlcmVkIDwtIHNhbXBsZS5zaXplKmV4cCAocnVuaWYgKEosIC0uMSwgLjEpKQ0KDQpwYXIgKG1hcj1jKDUsNSw0LDIpKy4xKQ0KcGxvdCAoc2FtcGxlLnNpemUuaml0dGVyZWQsIA0KICAgICAgY29lZihsbS51bnBvb2xlZCksIGNleC5sYWI9MS4yLCBjZXguYXhpcz0xLjIsDQogICAgICB4bGFiPSJzYW1wbGUgc2l6ZSBpbiBNU0EgaiIsIHlsYWI9ZXhwcmVzc2lvbiAocGFzdGUgKCJlc3QuIGludGVyY2VwdCwgIiwgYWxwaGFbSl0sICIgICAobm8gcG9vbGluZykiKSksDQogICAgICBwY2g9MjAsIGxvZz0ieCIsIHlsaW09YygyNSwgMzApLCB5YXh0PSJuIiwgeGF4dD0ibiIpDQpheGlzICgxLCBxdWFudGlsZShucyksIGNleC5heGlzPTEuMSkNCmF4aXMgKDIsIHNlcSgyNSwgMzApLCBjZXguYXhpcz0xLjEpDQpmb3IgKGogaW4gMTpKKXsNCiAgbGluZXMgKHJlcChzYW1wbGUuc2l6ZS5qaXR0ZXJlZFtqXSwyKSwNCiAgICAgICAgIGNvZWYobG0udW5wb29sZWQpW2pdICsgYygtMSwxKSpzZS5jb2VmKGxtLnVucG9vbGVkKVtqXSwgbHdkPS41KQ0KfQ0KYWJsaW5lIChjb2VmKGZpdC5jcClbMV0sIDAsIGx3ZD0uNSkNCnRpdGxlKG1haW49IkVzdGltYXRlcyBvZiBNU0EgTWVhbnMgZnJvbSB0aGUgRml4ZWQgRWZmZWN0IE1vZGVsIikNCg0KYGBgDQoNCg0KDQoNCiMjIyBQbG90IE1MTSBlc3RpbWF0ZXMgb2YgTVNBIG1lYW5zICsgc2Uncw0KDQpgYGB7cn0NCg0KcGFyIChtYXI9Yyg1LDUsNCwyKSsuMSkNCmEuaGF0Lk0xIDwtIGNvZWYoZml0MCkkbW1zYVssMV0NCmEuc2UuTTEgPC0gc2UuY29lZihmaXQwKSRtbXNhDQoNCnBsb3QgKGFzLm51bWVyaWMobnMpLCB0KGEuaGF0Lk0xKSwgY2V4LmxhYj0xLjIsIGNleC5heGlzPTEuMSwNCiAgICAgIHhsYWI9InNhbXBsZSBzaXplIGluIE1TQSBqIiwNCiAgICAgIHlsYWI9ZXhwcmVzc2lvbiAocGFzdGUoImVzdC4gaW50ZXJjZXB0LCAiLCBhbHBoYVtqXSwgIihtdWx0aWxldmVsIG1vZGVsKSIpKSwNCiAgICAgIHBjaD0yMCwgbG9nPSJ4IiwgeWxpbT1jKDI1LCAzMCksIHlheHQ9Im4iLCB4YXh0PSJuIikNCmF4aXMgKDEsIHF1YW50aWxlKG5zKSwgY2V4LmF4aXM9MS4xKQ0KYXhpcyAoMiwgc2VxKDI1LDMwKSwgY2V4LmF4aXM9MS4xKQ0KZm9yIChqIGluIDE6bGVuZ3RoKHVuaXF1ZShtZXJnZWQkbW1zYSkpKXsNCiAgbGluZXMgKHJlcChhcy5udW1lcmljKG5zKVtqXSwyKSwNCiAgICAgICAgIGFzLnZlY3RvcihhLmhhdC5NMVtqXSkgKyBjKC0xLDEpKmEuc2UuTTFbal0sIGx3ZD0uNSwgY29sPSJncmF5MTAiKQ0KfQ0KYWJsaW5lIChjb2VmKGZpdC5jcClbMV0sIDAsIGx3ZD0uNSkNCnRpdGxlKG1haW49IkVzdGltYXRlcyBvZiBNU0EgTWVhbnMgZnJvbSB0aGUgTUxNIikNCg0KYGBgDQoNCiMjIyBQbG90IE1MTSBlc3RpbWF0ZXMgb2YgTVNBIG1lYW5zICsgc2UncywgbW9kZWwgd2l0aCBNU0EgY292YXJpYXRlcw0KYGBge3J9DQoNCnBhciAobWFyPWMoNSw1LDQsMikrLjEpDQphLmhhdC5NMiA8LSBjb2VmKGZpdDAuMSkkbW1zYVssMV0NCmEuc2UuTTIgPC0gc2UuY29lZihmaXQwLjEpJG1tc2ENCg0KcGxvdCAoYXMubnVtZXJpYyhucyksIHQoYS5oYXQuTTIpLCBjZXgubGFiPTEuMiwgY2V4LmF4aXM9MS4xLA0KICAgICAgeGxhYj0ic2FtcGxlIHNpemUgaW4gTVNBIGoiLA0KICAgICAgeWxhYj1leHByZXNzaW9uIChwYXN0ZSgiZXN0LiBpbnRlcmNlcHQsICIsIGFscGhhW2pdLCAiKG11bHRpbGV2ZWwgbW9kZWwgd2l0aCBjb3ZhcmlhdGVzKSIpKSwNCiAgICAgIHBjaD0yMCwgbG9nPSJ4IiwgeWxpbT1jKDI1LCAzMCksIHlheHQ9Im4iLCB4YXh0PSJuIikNCmF4aXMgKDEsIHF1YW50aWxlKG5zKSwgY2V4LmF4aXM9MS4xKQ0KYXhpcyAoMiwgc2VxKDI1LDMwKSwgY2V4LmF4aXM9MS4xKQ0KZm9yIChqIGluIDE6bGVuZ3RoKHVuaXF1ZShtZXJnZWQkbW1zYSkpKXsNCiAgbGluZXMgKHJlcChhcy5udW1lcmljKG5zKVtqXSwyKSwNCiAgICAgICAgIGFzLnZlY3RvcihhLmhhdC5NMltqXSkgKyBjKC0xLDEpKmEuc2UuTTJbal0sIGx3ZD0uNSwgY29sPSJncmF5MTAiKQ0KfQ0KYWJsaW5lIChjb2VmKGZpdC5jcClbMV0sIDAsIGx3ZD0uNSkNCnRpdGxlKG1haW49IkVzdGltYXRlcyBvZiBNU0EgTWVhbnMgZnJvbSB0aGUgTUxNIHdpdGggTVNBIHByZWRpY3RvcnMiKQ0KDQojVGhpcyBwbG90IHNob3dzIHRoYXQgYXMgdGhlIG5faiBnb2VzIGRvd24sIHRoZSBzdGFuZGFyZCBlcnJvciBvZiB0aGUgZXN0aW1hdGUgaW5jcmVhc2VzDQpxcGxvdCh5PXNlLmNvZWYobG0udW5wb29sZWQpLCB4PWNvZWYobG0udW5wb29sZWQpLCBzaXplPXNxcnQobnMpKQ0KDQojYWdhaW4sIHdlIHNlZSB0aGUgcmVsYXRpb25zaGlwIGJldHdlZW4gdmFyaWFuY2UgYW5kIG5fag0KcXBsb3QoeT1hcy5udW1lcmljKGEuc2UuTTEpLHg9c2UuY29lZihsbS51bnBvb2xlZCksY29sb3I9c3FydChucykpDQoNCg0KYGBgDQo=