1 Introduction

1.1 Experimental Design (1)

  • Researcher determines the population to which they wants to generalize their conclusions.
  • Financial and logistic limitations \(\rightarrow\) representative sample from population

1.2 Data analysis (2 & 3)

  • Data-Exploration en Descriptive Statistics (2): explore, visualize, summarize, gain insight, check assumptions
  • Statistical Inference (3): Generalize what we observe in the sample towards the population so that we can draw general conclusions on the biological process we study. We need statistical models to analyze the data, and, to quantify and report on variability and uncertainty.

2 Example

  • National Health and Nutrition Examination Survey (NHANES)
  • American demografic study
  • Large number of physical, demographic, nutritional, life style and health characteristics
ID Gender Height BMI_WHO DirectChol SexNumPartnLife
51624 male 164.7 30.0_plus 1.29 8
51625 male 105.4 12.0_18.5 NA NA
51630 female 168.4 30.0_plus 1.16 10
51638 male 133.1 12.0_18.5 1.34 NA
51646 male 130.6 18.5_to_24.9 1.55 NA
51647 female 166.7 25.0_to_29.9 2.12 20

3 Variables

  • We measure variables on subjects in the sample
  • A Variable is a charactistic e.g. Direct cholesterol, Age, Gender,, …
  • It varies from subject tot subject in the population and thus also within the sample as well as from sample to sample.

3.1 Types of variables

  1. Qualitative variables: a limited number of outcome categories, non-numeric.
    • nominal variables: no natural ordening, e.g. gender, blood group, eye color, …
    • ordinal variables: ordening, e.g. BMI class, smoking status (1: never smoked, 2: stopped smoking, 3: smoker)
  2. Numeric variables:
    • discrete variables: counts e.g. number of parners in life span, …
    • continuous variables: can (in theory) take each possible value between certain limits e.g. Age, Weight, BMI, fluorescence measurement in ELISA assay

    • Often dichotomised to turn it in a nominal qualitative variable \(\rightarrow\) information loss


4 Population

  • Aim of scientific study: make general statements on a process at the level of the population.
  • E.g. assess if the cholesterol level is on average different between males and females who are elder than 25.

\(\rightarrow\) assess cholesterol level in population above 25.

  • Population in statistics is a theoretical concept
    • It is in continuous evolution/change
    • Often interest to generalize conclusions to future subject \(\rightarrow\) so population cannot be entirely observed at the present.
    • Can typically be considered to be infinite.
  • Population has to be clearly defined!

Inclusion criteria are characteristics a subject/experimental unit must have to belong to the population, e.g.

  • age above 25
  • normal BMI

Exclusion criteria characteristics that the subject/experimental unit is not allowed to have to belong to the population, e.g.

  • pregnancy in study on new type of drug
  • diabetes, history of hard drugs, low health status when the aim is to delineate a range of normal values of blood pressure in a population of healthy individuals

5 Random Variables

  • Variables (e.g. direct cholesterol) vary in the population from subject to subject!

  • Variables are thus random because their value changes in the population.

  • Crucial question: How precise are the conclusions on the population based on a group of subjects in a sample!

  • We will thus observe differences from sample to sample.

  • Variability of the data plays a crucial role!


5.1 Convention

  • Use capital letters for a study characteristic (e.g. direct cholesterol) to indicate that it changes in the population without thinking about the observed value of a particular subject.

  • Variable \(X\) is a random variable and is the result of random sampling of the characteristic from the population.

  • Random variable \(X\) is thus the unknown variable that represent a measurement that we plan to collect on a random subject, but that we have not collected yet.

  • Typically a sequence of random variables \(X_1,\ldots X_n\) will be collected in the study (with n subjects or experimental units).

  • The concept of random variables is necessary to reason on how the results and conclusions change from sample to sample.

  • Random variables can be qualitative, quantitative, discrete, continuous, …


6 Describing the population

  • It is impossible to predict the value of a random variable.

  • The realised value of \(X\) is subject to random variability.

  • Suppose that we are interested in the IQ of subject. If we know how the data are distributed, we can use probability theory to calculate the probability that the IQ of a random subject of the population will be above 110.


6.1 Intermezzo probability theory

6.1.1 Discrete random variables

  • Supose that we measure a discrete random variable \(X\)

  • All possible values for the random variable \(X\) are called the sample space \(\Omega\).

    • For gender the sample space is \(\Omega=(0,1)\) with 0 (male) or 1 (female).
    • Suppose that we role a dice, then the sample space is \(\Omega=(1,2,3,4,5,6)\).
  • An event \(A\) is a subset of the sample space

    • Get an even number when rolling a dice: \(A=(2,4,6)\).
    • Can also be \(A=(1)\) one subset of the sample space.
  • Event space \(\mathcal{A}\) is the class of all possible events associated with a given experiment.

  • Two events (\(A_1\) and \(A_2\)) are multiple exclusive if they cannot occur together

    • e.g. event of the odd numbers \(A_1=(1,3,5)\) and the event of getting \(A_2=(6)\)
    • so \(A_1 \bigcap A_2=\emptyset\).
  • Probability \(P(A)\) is a function \(P: A \rightarrow [0,1]\) which satisfies

    1. \(P(A) \geq 0\) and \(P(A) \leq 1\) for each \(A \in \mathcal{A}\)
    2. \(P(\Omega)=1\)
    3. For multiple exclusive events \(A_1, A_2, \ldots A_k\) the probability \(P(A_1 \cup A_2 \ldots \cup A_k)= P(A_1) + \ldots + P(A_k)\)
  • Dice example

    • odd number \(A=(1,3,5)\): this is the union of 3 multiple exclusive events \(A_1=1\), \(A_2=5\) and \(A_3=5\) so \(P(A)=P(1)+P(3)+P(5)=1/6+1/6+1/6=0.5\)
    • \(\Omega=(1,2,3,4,5,6)\): \(P(\Omega)=1\)
  • If we draw two subjects (j and k) independently from the population then the joint probability on
    \(P(X_j,X_k)= P(X_j)P(X_j)\)


6.1.1.1 Probability mass function

  • The probability mass function for a random variable \(X\) describes the probability of each possible value of the sample space.

  • Example: Gender is a binary variable (0:male, 1:female) and binary variables are Bernoulli distributed. 50.8% of the subjects of the American population are female and 49.2% are male. Let \(\pi\) be the probability on a female \(\pi=0.508\). so \[ X\sim \left \{ \begin{array}{lcl} P(X=0) &=& 1-\pi\\ P(X=1) &=& \pi \end{array} \right . \]

    data.frame(X=c(0,1),prob=c(0.492,0.508)) %>%
      ggplot(aes(x=X,xend=X,y=0,yend=prob)) +
      geom_segment() +
      ylab("Probability")

Random variable \(X\) follows an Bernoulli distribution \(B(\pi)\) with parameter \(\pi=0.508\), \[B(\pi)= \pi^x(1-\pi)^{(x-1)}\]


6.1.1.2 Cumulative distribution function

  • The cumulative distribution function is the function F(x) that calculates the probability to observe a random variable X for which \(X\leq x\): \[ F(x) = \sum\limits_{\forall X\leq x} P(x)\]

  • Gender example \(F(0)=1-\pi\) and F(1)=P(X=0) + P(X=1)=1

    data.frame(X=c(0,1),cumprob=c(0.492,1)) %>%
      ggplot(aes(x=X,xend=X,y=0,yend=cumprob)) +
      geom_segment() +
      ylab("F(x)")

  • Dice:

    data.frame(X=1:6,cumprob=cumsum(rep(1/6,6))) %>%
      ggplot(aes(x=X,xend=X,y=rep(0,6),yend=cumprob)) +
      geom_segment() +
      ylab("F(x)")


6.1.1.3 Mean

The mean or the expected value \(E[X]\) of a discrete random variable is given by

\[E[X]=\sum\limits_{x\in\Omega} x P(X=x)\]

  • Gender example

    • \(E[X]= 0 \times (1-\pi) + 1 \times \pi = \pi\)
    • The mean equals \(E[X]=0.508\).
  • Dice example: $ E[X]= 1 1/6 + 2 1/6 + + 6 1/6 = $ 3.5


6.1.1.4 Variance

The variance is a measure for the variability of a random variable and is given by

\[E[(X-E[X])^2]=\sum\limits_{x\in\Omega} (x-E[X])^2 P(X=x)\]

  • Gender example \[\begin{eqnarray} E[(X-E[X])^2]&=&(0-\pi)^2\times (1-\pi)+(1-\pi)^2 \times \pi\\ &=& \pi^2 (1-\pi) + (1-\pi)^2 \pi\\ &=&\pi (1-\pi)(\pi+1-\pi)\\ &=&\pi(1-\pi) \end{eqnarray}\]

6.1.2 Continuous random variable

  • The density function \(f(x)\) describes how likely it is to observe a particular value of random variable X when we sample a random subject from the population.

  • Many biological characteristics are approximatively normally distributed (upon transformation) \[f(x) = \frac{1}{\sqrt{2\pi\sigma^2}} e^{-\frac{(x-\mu)^2}{2\sigma^2}}\]

  • This is denoted in shorthand as \(f(x) = N(\mu,\sigma^2)\)

  • The IQ in the population is known to follow a normal distribution with mean \(\mu=100\) and standard deviation \(\sigma=15\).
    \[IQ \sim N(100,15^2)\]

  • R we can use the dnorm function to calculate the density of particular values of X=x.

  • The arguments of dnorm are mean (\(\mu\)) and sd (standard deviation \(\sigma\)).

par(mar=c(5, 4, 4, 2) + 0.1, mai=c(1.02,0.82,0.82,0.42))
grid <- seq(40,160,.1)
plot(grid,dnorm(grid,mean=100,sd=15),
     xlab="IQ",
     col=2,ylab="Densiteit",type="l",lwd=2,cex.lab=1.5,cex.axis=1.5)

  • Within certain limits, continuous variables can take all possible values so the sample space \(\Omega\) is infinitely large.

6.1.2.1 Cumulative distribution

  • Again the cumulative distribution \(F(X)=P(X\leq x)\).

  • Because X is continuous we will calculate this probability using an integral \[F(x)=\int \limits_{-\infty}^x f(x) dx\]

  • Note that \(f(x)=0\) if x does not belong to the sample space.

  • We can calculate \(F(x)\) for a normally distributed random variable using the pnorm function again with arguments mean and sd.

plot(grid,pnorm(grid,mean=100,sd=15),type="l",xlab="IQ",ylab="Probability")

So the probability that the IQ of a random subject is below 80 can be obtained by

pnorm(80,mean=100,sd=15)
[1] 0.09121122

  • For the largest possible value of \(X\) we integrate over the entire sample space \(\Omega\) so \[\int \limits_{x \in \Omega} f(x) dx=1\]

  • So the area under the density function equals 1!


6.1.2.2 Mean and Variance.

  • The mean or the expected value \(E[X]\) of a continuous random variable is given by

\[\int \limits_{x \in \Omega} x f(x) dx\]

  • For the normal distribution \[\int \limits_{-\infty}^{+\infty} x f(x) dx = \mu\]

  • The variance \(E[(X-E[X])^2]\) is given by

\[\int \limits_{x \in \Omega} (x-E[X])^2 f(x) dx\]

  • For the normal distribution we get

\[\int \limits_{-\infty}^{+\infty} (x-\mu)^2 f(x) dx = \sigma^2\]

  • It is often difficult to interpret the variance because it is not in the same unit as the random variable and the mean. We therefore often use the standard deviation

\[SD=\sqrt{E[(X-E[X])^2]}\]

The SD for a normal distribution, \(\sigma\) has the nice interpretation that approximately 68% of the population has a value for the characteristic X within the interval of one standard deviation (\(\sigma\)) around the mean:

\[P(\mu-\sigma < X < \mu + \sigma) \approx 0.68\]

  • For normally distributed random variables approximately 95% of the subjects in the population have a value that lays in two standard deviations (\(2 \sigma\)) of the mean

\[P[\mu - 2 \sigma < X < \mu + 2 \sigma]\approx 0.95\]


  • In R cumulative distribution can be calculated with the function rnorm. This function has arguments q the quantile, the mean and the standard deviation.

  • If you want help you can always type:

?pnorm
  • What is the probability that a random subject in the population will have an IQ below 90?
pnorm(q=90,mean=100,sd=15)
[1] 0.2524925
  • What is the probability that a random subject in the population will have an IQ below 110?

  • What is the probability that a random subject in the population will have an IQ between 90 and 110?


6.2 Standardization

  • Normal data are often standardized.

\[z=\frac{x-\mu}{\sigma}\]

  • Upon standardization the data follow a standard normal distribution with mean \(\mu=0\) and variance \(\sigma^2=1\): \[z \sim N(0,1)\]

We can use the qnorm function to calculate the quantile \(z_{2.5\%}\) and \(z_{97.5\%}\) corresponding to \(F(z_{2.5\%})=0.025\) and \(F(z_{97.5\%})=0.975\), respectively.

qnorm(0.025)
[1] -1.959964
qnorm(0.975)
[1] 1.959964

This indeed indicates that about 97.5%-2.5%=95% of a standard normal random variable falls within the interval [-2,2], or within 2 times the standard deviation (\(\sigma=1\)) from the mean (\(\mu=0\)).


7 Sample

  • In real studies we typically do not know the distribution in the population.

  • Due to financial and logistic reasons we can almost never study the entire population.

  • The population parameters (e.g. mean IQ, variance of IQ) can therefore not be obtained without error.

  • Only as small subset of the population can be studied: the sample
  • Sample according to a structured design: select subject completely at random from the population so that every subject has an equal probability to end up in the sample \(\rightarrow\) Representative sample.

  • The sample \(x_1, x_2, . . . , x_{n}\) can be considered to be \(n\) realisations of the same random variable \(X\), for subjects \(i = 1,2,...,n\).

  • The distribution in the population is unknown and has to be estimated.

  • If we can assume that the studied characteristic follows a particular distribution (e.g. a normal distribution \(N(\mu,\sigma^2)\) then we only have to estimate the population parameters (e.g \(\mu\) and \(\sigma^2\)) based on the sample.

  • We refer to them as estimates and denote them by \(\hat \mu\) and \(\hat \sigma^2\).


7.1 NHANES example

  • Gender in the population
  • Select \(n=10000\) subjects at random from the American population.
  • Once the random individuals are sampled from the population we have observed \(n\) realisations of the random variable \(X\).

  • Convention: Observed values \(\rightarrow\) are denoted with a small letter \(x\).

  • \(x\) is a particular value measured/observed in a conducted experiment and no longer an unknown variable.

7.2 In summary

  • Unknown values of the studied population characteristic for 1 to \(n\) subjects in a sample are random variables: \(X_1, \ldots, X_n\)
  • We have to reason on this in order to understand how the observations, estimates and conclusions of a study can change from sample to sample.
  • In a sample we observe the realised outcomes \(x_1, x_2, \dots, x_n\): e.g. the observed genders or the observed direct cholesterol levels of the subjects in the sample.

8 Gender Example

library(NHANES)
NHANES %>% ggplot(aes(x=Gender)) + geom_bar()

  • Gender is a binary variable.
  • It thus follows a Bernoulli distibution.
  • The parameter of a Bernoulli distribution is the mean \(\pi\).
  • We can estimate \(\pi\) based on the sample using the sample mean \(\bar x = \sum\limits_{i=1}^n x_i\)
  • Note, that the sample mean is also a random variable! It also varies from sample to sample!
NHANES$Gender %>% head
[1] male   male   male   male   female male  
Levels: female male
  • Note, that Gender is a factor and that the females are the reference class (first class).
  • R by default uses the level which comes first in the alfabet as the reference class.
  • We can recode the Gender using a 0 and 1 coding.
  • When we use the as.numeric() function the factor Gender is transformed in a numeric value. It has two values 1 or 2. 1 stands for the first level (females) and 2 for the second level males. If we subtract 1 from it we have a 0 and 1 encoding (0 for females and 1 for males).
NHANES<-NHANES %>% mutate(gender=as.numeric(Gender)-1)
mean(NHANES$gender)
[1] 0.498
  • Note, that due to the encoding the sample mean is an estimate for the fraction of males in the population.

  • Always be careful with the encoding!


9 Direct cholesterol example

9.1 Empirical distribution

  • We can estimate the direct cholesterol distribution of females using a histogram
NHANES %>% filter(Gender=="female") %>% 
ggplot(aes(x=DirectChol)) + 
geom_histogram()

  • Note, that the distribution is skewed with a tail to the right.

  • We can estimate the cumulative distribution function using the empirical cumulative distribution function.
    • Every observation in the sample is observed once.
    • So the empirical distribution of the sample is a discrete distribution with probability of 1/n on every observation.
    • The empirical cumulative distribution function then becomes \[ECDF(x) = \sum\limits_{x_i \leq x} \frac{1}{n} = \frac{\# (x_i \leq x)}{n}\]
fem <- NHANES %>% filter(Gender=="female"&!is.na(DirectChol))
fem %>% 
ggplot(aes(x=DirectChol)) + 
stat_ecdf()

- We also illustrate this for a sample with sample size 10
set.seed(1)
fem10<- NHANES %>% filter(Gender=="female"&!is.na(DirectChol)) %>% sample_n(size=10) 
fem10 %>% ggplot(aes(x=DirectChol)) + 
stat_ecdf()


9.2 Normal approximation

  • In the introduction we have seen that the log transformed direct cholesterol levels had a nice bell shape.
  fem %>% ggplot(aes(x=DirectChol%>%log2))+
  geom_histogram(aes(y=..density.., fill=..count..)) +
  xlab("Direct Cholesterol (log2)") +
  stat_function(fun=dnorm,color="red",args=list(mean=mean(fem$DirectChol%>%log2), sd=sd(fem$DirectChol%>%log2)))

  • We can now approximate the distribution of log2 transformed direct cholesterol levels using a normal distribution.

  • We only have to estimate two parameters: the mean and the variance. We can do this based on the sample mean (\(\bar x\)) and sample variance (\(s^2\)) or sample standard deviation (\(s\)).

xBar<-mean(fem$DirectChol%>%log2)
sdBar<-sd(fem$DirectChol%>%log2)
xBar
[1] 0.5142563
sdBar
[1] 0.394117
  • We can do the same thing for the small sample with 10 women.
  fem10 %>% ggplot(aes(x=DirectChol%>%log2))+
  geom_histogram(aes(y=..density.., fill=..count..),bins=10) +
  xlab("Direct Cholesterol (log2)") +
  stat_function(fun=dnorm,color="red",args=list(mean=mean(fem10$DirectChol%>%log2), sd=sd(fem10$DirectChol%>%log2))) +
  xlim(-2,2)

xBar10<-mean(fem10$DirectChol%>%log2)
sdBar10<-sd(fem10$DirectChol%>%log2)
xBar10
[1] 0.5093291
sdBar10
[1] 0.3393851

9.3 Reference intervals

  • Normal values for the cholesterol levels in the population can be calculated using a reference interval. Typically a 95% reference interval is used, so that 95% of the subjects in the population are expected to have a value for the characteristic that falls into the reference interval.

  • We can do this based on the empirical distribution using the quantile function. We need to calculate the quantiles \(\hat{F}(x_{2.5\%})=0.025\) and \(\hat{F}(x_{97.5\%})=0.975\) so that 95% of the values are located in the interval [x_{2.5%},x_{97.5%}] .

  • Large sample

quantile(fem$DirectChol,prob=c(0.025,0.975))
 2.5% 97.5% 
 0.85  2.43 
  • So based on the large sample, we estimate that 95% of the females in the population have a direct cholesterol level in the interval [0.85, 2.43].

  • Small sample

quantile(fem10$DirectChol,prob=c(0.025,0.975))
   2.5%   97.5% 
1.05050 2.25675 
  • Note, that this estimate is very crude. In the small sample, We do not have enough observations to have a good approximation of the extreme quantiles.

9.3.1 Normal approximation

  • We can use the function qnorm to calculate quantiles from the normal distribution.

  • We also know that a 95% reference interval is located rougly in two standard deviations around the mean.

  • We will have to use the function 2^ to transform the result back to the direct cholesterol domain.

  • Large sample

qnorm(0.025,mean=xBar,sd=sdBar) %>% .^2
[1] 0.06666668
qnorm(0.975,mean=xBar,sd=sdBar) %>% .^2
[1] 1.655626
2^(xBar - 2 * sdBar)
[1] 0.8270361
2^(xBar + 2 * sdBar)
[1] 2.466543
  • Small sample
qnorm(0.025,mean=xBar10,sd=sdBar10) %>% .^2
[1] 0.0242903
qnorm(0.975,mean=xBar10,sd=sdBar10) %>% .^2
[1] 1.379477
2^(xBar10 - 2 * sdBar10)
[1] 0.8891871
2^(xBar10 + 2 * sdBar10)
[1] 2.278523

9.4 Conclusions

  • For the large sample, the empirical distribution (quantile function) and the normal approximation gives us approximately the same result.

  • For the small sample, however, the normal approximation works much better than the one based on the empirical distribution.

    • This is because we are looking at extreme quantiles 2.5% and 97.5%.
    • Indeed, we have very few observations at our disposal in the small sample to estimate these quantiles directly from the observations.
    • With the normal approximation we can use all the data to estimate the mean and the variance. So if the normal assumption holds, we get better estimates for these extreme quantiles.

10 Statistics

  • Formula will be used to estimate the parameters of a distribution in the population based on the sample. We call these statistics or estimators.

  • The numeric result obtained by evaluating these formula are also called statistics or estimates.

  • Researcher want to known the unknown parameters from the population and will thus estimate them using the statistics observed or calculated based on the sample

  • Because we calculate the statistics based on the observations in the sample, they will also vary from sample to sample and are random variables and we denote them with capital letters (e.g. \(\bar X\) for the sample mean and \(S^2\) for the sample variance).

  • So when we analyse data, we have to reason on how the statistics of interest will vary from sample to sample.

  • When the statistics refer to a numeric value realised in a particular sample, we will use a small letter: \(\bar x\) and \(s^2\).


11 Convention

  • Population parameters are fixed but unknown and we will denote them with \(\rightarrow\) Greek symbols.

  • Statistics that we use to estimate unknown parameters based on the sample are denoted with letters are with a hat.

  • e.g. for normal distribution

Population Sample
\(\mu\) \(\bar X\) or \(\hat \mu\)
\(\sigma^2\) \(S^2\) or \(\hat \sigma\)

LS0tCnRpdGxlOiAiMi4gQmFzaWMgQ29uY2VwdHMiCmF1dGhvcjogIkxpZXZlbiBDbGVtZW50IgpkYXRlOiAic3RhdE9taWNzLCBHaGVudCBVbml2ZXJzaXR5IChodHRwczovL3N0YXRvbWljcy5naXRodWIuaW8pIgpvdXRwdXQ6CiAgICBodG1sX2RvY3VtZW50OgogICAgICBjb2RlX2Rvd25sb2FkOiB0cnVlCiAgICAgIHRoZW1lOiBjb3NtbwogICAgICB0b2M6IHRydWUKICAgICAgdG9jX2Zsb2F0OiB0cnVlCiAgICAgIGhpZ2hsaWdodDogdGFuZ28KICAgICAgbnVtYmVyX3NlY3Rpb25zOiB0cnVlCi0tLQoKIyBJbnRyb2R1Y3Rpb24KYGBge3Igc2V0dXAsIGluY2x1ZGU9RkFMU0V9CmtuaXRyOjpvcHRzX2NodW5rJHNldChpbmNsdWRlID0gVFJVRSwgY29tbWVudCA9IE5BLCBlY2hvID0gVFJVRSwKICAgICAgICAgICAgICAgICAgICAgIG1lc3NhZ2UgPSBGQUxTRSwgd2FybmluZyA9IEZBTFNFKQpsaWJyYXJ5KHRpZHl2ZXJzZSkKbGlicmFyeShOSEFORVMpCmBgYAoKYGBge3IgcG9wMlNhbXAyUG9wLCBvdXQud2lkdGg9JzgwJScsZmlnLmFzcD0uOCwgZmlnLmFsaWduPSdjZW50ZXInLGVjaG89RkFMU0V9CmlmICgicGkiJWluJWxzKCkpIHJtKCJwaSIpCmtvcHZvZXRlcjwtZnVuY3Rpb24oeCx5LGFuZ2xlPTAsbD0uMixjZXguZG90PS41LHBjaD0xOSxjb2w9ImJsYWNrIikKewphbmdsZT1hbmdsZS8xODAqcGkKcG9pbnRzKHgseSxjZXg9Y2V4LmRvdCxwY2g9cGNoLGNvbD1jb2wpCmxpbmVzKGMoeCx4K2wqY29zKC1waS8yK2FuZ2xlKSksYyh5LHkrbCpzaW4oLXBpLzIrYW5nbGUpKSxjb2w9Y29sKQpsaW5lcyhjKHgrbC8yKmNvcygtcGkvMithbmdsZSkseCtsLzIqY29zKC1waS8yK2FuZ2xlKStsLzQqY29zKGFuZ2xlKSksYyh5K2wvMipzaW4oLXBpLzIrYW5nbGUpLHkrbC8yKnNpbigtcGkvMithbmdsZSkrbC80KnNpbihhbmdsZSkpLGNvbD1jb2wpCmxpbmVzKGMoeCtsLzIqY29zKC1waS8yK2FuZ2xlKSx4K2wvMipjb3MoLXBpLzIrYW5nbGUpK2wvNCpjb3MocGkrYW5nbGUpKSxjKHkrbC8yKnNpbigtcGkvMithbmdsZSkseStsLzIqc2luKC1waS8yK2FuZ2xlKStsLzQqc2luKHBpK2FuZ2xlKSksY29sPWNvbCkKbGluZXMoYyh4K2wqY29zKC1waS8yK2FuZ2xlKSx4K2wqY29zKC1waS8yK2FuZ2xlKStsLzIqY29zKC1waS8yK3BpLzQrYW5nbGUpKSxjKHkrbCpzaW4oLXBpLzIrYW5nbGUpLHkrbCpzaW4oLXBpLzIrYW5nbGUpK2wvMipzaW4oLXBpLzIrcGkvNCthbmdsZSkpLGNvbD1jb2wpCmxpbmVzKGMoeCtsKmNvcygtcGkvMithbmdsZSkseCtsKmNvcygtcGkvMithbmdsZSkrbC8yKmNvcygtcGkvMi1waS80K2FuZ2xlKSksYyh5K2wqc2luKC1waS8yK2FuZ2xlKSx5K2wqc2luKC1waS8yK2FuZ2xlKStsLzIqc2luKC1waS8yLXBpLzQrYW5nbGUpKSxjb2w9Y29sKQp9CgpwYXIobWFyPWMoMCwwLDAsMCksbWFpPWMoMCwwLDAsMCkpCnBsb3QoMCwwLHhsYWI9IiIseWxhYj0iIix4bGltPWMoMCwxMCkseWxpbT1jKDAsMTApLGNvbD0wLHhheHQ9Im5vbmUiLHlheHQ9Im5vbmUiLGF4ZXM9RkFMU0UpCnJlY3QoMCw2LDEwLDEwLGJvcmRlcj0icmVkIixsd2Q9MikKdGV4dCguNSw4LCJwb3B1bGF0aW9uIixzcnQ9OTAsY29sPSJyZWQiLGNleD0yKQpzeW1ib2xzICgzLCA4LCBjaXJjbGVzPTEuNSwgY29sPSJyZWQiLGFkZD1UUlVFLGZnPSJyZWQiLGluY2hlcz1GQUxTRSxsd2Q9MikKc2V0LnNlZWQoMzMwKQpncmlkPXNlcSgwLDEuMywuMDEpCgpmb3IgKGkgaW4gMTo1MCkKewoJYW5nbGUxPXJ1bmlmKG49MSxtaW49MCxtYXg9MzYwKQoJYW5nbGUyPXJ1bmlmKG49MSxtaW49MCxtYXg9MzYwKQoJcmFkaXVzPXNhbXBsZShncmlkLHByb2I9Z3JpZF4yKnBpL3N1bShncmlkXjIqcGkpLHNpemU9MSkKCWtvcHZvZXRlcigzK3JhZGl1cypjb3MoYW5nbGUxLzE4MCpwaSksOCtyYWRpdXMqc2luKGFuZ2xlMS8xODAqcGkpLGFuZ2xlPWFuZ2xlMikKfQp0ZXh0KDcuNSw4LCJDaG9sZXN0ZXJvbCBpbiBwb3B1bGF0aW9uIixjb2w9InJlZCIsY2V4PTEuMikKCnJlY3QoMCwwLDEwLDQsYm9yZGVyPSJibHVlIixsd2Q9MikKdGV4dCguNSwyLCJzYW1wbGUiLHNydD05MCxjb2w9ImJsdWUiLGNleD0yKQpzeW1ib2xzICgzLCAyLCBjaXJjbGVzPTEuNSwgY29sPSJyZWQiLGFkZD1UUlVFLGZnPSJibHVlIixpbmNoZXM9RkFMU0UsbHdkPTIpCmZvciAoaSBpbiAwOjIpCglmb3IgKGogaW4gMDo0KQp7CgoJa29wdm9ldGVyKDIuMStqKigzLjktMi4xKS80LDEuMStpKQp9CnRleHQoNy41LDIsIkNob2xlc3Rlcm9sIGluIHNhbXBsZSIsY29sPSJibHVlIixjZXg9MS4yKQoKYXJyb3dzKDMsNS45LDMsNC4xLGNvbD0iYmxhY2siLGx3ZD0zKQphcnJvd3MoNyw0LjEsNyw1LjksY29sPSJibGFjayIsbHdkPTMpCnRleHQoMS41LDUsIkVYUC4gREVTSUdOICgxKSIsY29sPSJibGFjayIsY2V4PTEuMikKdGV4dCg4LjUsNSwiRVNUSU1BVElPTiAmXG5JTkZFUkVOQ0UgKDMpIixjb2w9ImJsYWNrIixjZXg9MS4yKQp0ZXh0KDcuNSwuNSwiREFUQSBFWFBMT1JBVElPTiAmXG5ERVNDUklQVElWRSBTVEFUSVNUSUNTICgyKSIsY29sPSJibGFjayIsY2V4PTEuMikKYGBgCgoKIyMgRXhwZXJpbWVudGFsIERlc2lnbiAoMSkKICAgLSBSZXNlYXJjaGVyIGRldGVybWluZXMgdGhlICoqcG9wdWxhdGlvbioqIHRvIHdoaWNoIHRoZXkgd2FudHMgdG8gZ2VuZXJhbGl6ZSB0aGVpciBjb25jbHVzaW9ucy4KICAgLSBGaW5hbmNpYWwgYW5kIGxvZ2lzdGljIGxpbWl0YXRpb25zICRccmlnaHRhcnJvdyQgKipyZXByZXNlbnRhdGl2ZSBzYW1wbGUqKiBmcm9tIHBvcHVsYXRpb24KICAgCiMjIERhdGEgYW5hbHlzaXMgKDIgJiAzKQogICAtICoqRGF0YS1FeHBsb3JhdGlvbiBlbiBEZXNjcmlwdGl2ZSBTdGF0aXN0aWNzICgyKSoqOiBleHBsb3JlLCB2aXN1YWxpemUsIHN1bW1hcml6ZSwgZ2FpbiBpbnNpZ2h0LCBjaGVjayBhc3N1bXB0aW9ucwogICAtICoqU3RhdGlzdGljYWwgSW5mZXJlbmNlICgzKSoqOiBHZW5lcmFsaXplIHdoYXQgd2Ugb2JzZXJ2ZSBpbiB0aGUgc2FtcGxlIHRvd2FyZHMgdGhlIHBvcHVsYXRpb24gc28gdGhhdCB3ZSBjYW4gZHJhdyBnZW5lcmFsIGNvbmNsdXNpb25zIG9uIHRoZSBiaW9sb2dpY2FsIHByb2Nlc3Mgd2Ugc3R1ZHkuIFdlIG5lZWQgc3RhdGlzdGljYWwgbW9kZWxzIHRvIGFuYWx5emUgdGhlIGRhdGEsIGFuZCwgdG8gcXVhbnRpZnkgYW5kIHJlcG9ydCBvbiB2YXJpYWJpbGl0eSBhbmQgdW5jZXJ0YWludHkuICAKICAgCi0tLQoKIyBFeGFtcGxlCgotIE5hdGlvbmFsIEhlYWx0aCBhbmQgTnV0cml0aW9uIEV4YW1pbmF0aW9uIFN1cnZleSAoTkhBTkVTKQotIEFtZXJpY2FuIGRlbW9ncmFmaWMgc3R1ZHkKLSBMYXJnZSBudW1iZXIgb2YgcGh5c2ljYWwsIGRlbW9ncmFwaGljLCBudXRyaXRpb25hbCwgbGlmZSBzdHlsZSBhbmQgaGVhbHRoIGNoYXJhY3RlcmlzdGljcyAKCmBgYHtyIG5oYW5lcywgdGlkeT1GQUxTRSxlY2hvPUZBTFNFfQpsaWJyYXJ5KE5IQU5FUykKa25pdHI6OmthYmxlKCAgTkhBTkVTW2MoMSw0LDUsNiw3LDgpLGMoMSwzLDIwLDIzLDM0LDcyKV0KLGZvcm1hdCA9ICJtYXJrZG93biIpCmBgYAoKLS0tCgojIFZhcmlhYmxlcwoKLSBXZSBtZWFzdXJlICp2YXJpYWJsZXMqIG9uIHN1YmplY3RzIGluIHRoZSBzYW1wbGUKLSBBIFZhcmlhYmxlIGlzIGEgY2hhcmFjdGlzdGljIGUuZy4gRGlyZWN0IGNob2xlc3Rlcm9sLCBBZ2UsIEdlbmRlciwsIC4uLgotIEl0IHZhcmllcyBmcm9tIHN1YmplY3QgdG90IHN1YmplY3QgaW4gdGhlIHBvcHVsYXRpb24gYW5kIHRodXMgYWxzbyB3aXRoaW4gdGhlIHNhbXBsZSBhcyB3ZWxsIGFzIGZyb20gc2FtcGxlIHRvIHNhbXBsZS4KCgojIyAqVHlwZXMqIG9mIHZhcmlhYmxlcwoKMS4gKlF1YWxpdGF0aXZlIHZhcmlhYmxlcyo6IGEgbGltaXRlZCBudW1iZXIgb2Ygb3V0Y29tZSBjYXRlZ29yaWVzLCBub24tbnVtZXJpYy4gCgktICAqbm9taW5hbCB2YXJpYWJsZXMqOiBubyBuYXR1cmFsIG9yZGVuaW5nLCBlLmcuIGdlbmRlciwgYmxvb2QgZ3JvdXAsIGV5ZSBjb2xvciwgLi4uIAoJLSAgKm9yZGluYWwgdmFyaWFibGVzKjogb3JkZW5pbmcsIGUuZy4gQk1JIGNsYXNzLCBzbW9raW5nIHN0YXR1cyAoMTogbmV2ZXIgc21va2VkLCAyOiBzdG9wcGVkIHNtb2tpbmcsIDM6IHNtb2tlcikKCjIuICpOdW1lcmljIHZhcmlhYmxlcyo6CiAgIAktICpkaXNjcmV0ZSB2YXJpYWJsZXMqOiBjb3VudHMgZS5nLiBudW1iZXIgb2YgcGFybmVycyBpbiBsaWZlIHNwYW4sIC4uLgoJLSAqY29udGludW91cyB2YXJpYWJsZXMqOiBjYW4gKGluIHRoZW9yeSkgdGFrZSBlYWNoIHBvc3NpYmxlIHZhbHVlIGJldHdlZW4gY2VydGFpbiBsaW1pdHMgZS5nLiBBZ2UsIFdlaWdodCwgQk1JLCBmbHVvcmVzY2VuY2UgbWVhc3VyZW1lbnQgaW4gRUxJU0EgYXNzYXkgCgkKCS0gT2Z0ZW4gZGljaG90b21pc2VkIHRvIHR1cm4gaXQgaW4gYSBub21pbmFsIHF1YWxpdGF0aXZlIHZhcmlhYmxlICRccmlnaHRhcnJvdyQgaW5mb3JtYXRpb24gbG9zcwoKLS0tCgojIFBvcHVsYXRpb24KCi0gQWltIG9mIHNjaWVudGlmaWMgc3R1ZHk6IG1ha2UgZ2VuZXJhbCBzdGF0ZW1lbnRzIG9uIGEgcHJvY2VzcyBhdCB0aGUgbGV2ZWwgb2YgdGhlIHBvcHVsYXRpb24uIAotIEUuZy4gYXNzZXNzIGlmIHRoZSBjaG9sZXN0ZXJvbCBsZXZlbCBpcyBvbiBhdmVyYWdlIGRpZmZlcmVudCBiZXR3ZWVuIG1hbGVzIGFuZCBmZW1hbGVzIHdobyBhcmUgZWxkZXIgdGhhbiAyNS4KCiRccmlnaHRhcnJvdyQgYXNzZXNzIGNob2xlc3Rlcm9sIGxldmVsIGluIHBvcHVsYXRpb24gYWJvdmUgMjUuCgotIFBvcHVsYXRpb24gaW4gc3RhdGlzdGljcyBpcyBhIHRoZW9yZXRpY2FsIGNvbmNlcHQKCSAgLSBJdCBpcyBpbiBjb250aW51b3VzIGV2b2x1dGlvbi9jaGFuZ2UKCSAgLSBPZnRlbiBpbnRlcmVzdCB0byBnZW5lcmFsaXplIGNvbmNsdXNpb25zIHRvIGZ1dHVyZSBzdWJqZWN0ICRccmlnaHRhcnJvdyQgc28gcG9wdWxhdGlvbiBjYW5ub3QgYmUgZW50aXJlbHkgb2JzZXJ2ZWQgYXQgdGhlIHByZXNlbnQuIAogIAktIENhbiB0eXBpY2FsbHkgYmUgY29uc2lkZXJlZCB0byBiZSBpbmZpbml0ZS4gCgotIFBvcHVsYXRpb24gaGFzIHRvIGJlIGNsZWFybHkgZGVmaW5lZCEgCgoqSW5jbHVzaW9uIGNyaXRlcmlhKiBhcmUgY2hhcmFjdGVyaXN0aWNzIGEgc3ViamVjdC9leHBlcmltZW50YWwgdW5pdCBtdXN0IGhhdmUgdG8gYmVsb25nIHRvIHRoZSBwb3B1bGF0aW9uLCBlLmcuCgotIGFnZSBhYm92ZSAyNQotIG5vcm1hbCBCTUkKLSAuLi4KCipFeGNsdXNpb24gY3JpdGVyaWEqIGNoYXJhY3RlcmlzdGljcyB0aGF0IHRoZSBzdWJqZWN0L2V4cGVyaW1lbnRhbCB1bml0IGlzIG5vdCBhbGxvd2VkIHRvIGhhdmUgdG8gYmVsb25nIHRvIHRoZSBwb3B1bGF0aW9uLCBlLmcuIAoKLSBwcmVnbmFuY3kgaW4gc3R1ZHkgb24gbmV3IHR5cGUgb2YgZHJ1ZwotIGRpYWJldGVzLCBoaXN0b3J5IG9mIGhhcmQgZHJ1Z3MsIGxvdyBoZWFsdGggc3RhdHVzIHdoZW4gdGhlIGFpbSBpcyB0byBkZWxpbmVhdGUgYSByYW5nZSBvZiBub3JtYWwgdmFsdWVzIG9mIGJsb29kIHByZXNzdXJlIGluIGEgcG9wdWxhdGlvbiBvZiBoZWFsdGh5IGluZGl2aWR1YWxzCi0gLi4uCgotLS0KCiMgUmFuZG9tIFZhcmlhYmxlcwoKLSBWYXJpYWJsZXMgKGUuZy4gZGlyZWN0IGNob2xlc3Rlcm9sKSB2YXJ5IGluIHRoZSBwb3B1bGF0aW9uIGZyb20gc3ViamVjdCB0byBzdWJqZWN0IQoKLSBWYXJpYWJsZXMgYXJlIHRodXMgKnJhbmRvbSogYmVjYXVzZSB0aGVpciB2YWx1ZSBjaGFuZ2VzIGluIHRoZSBwb3B1bGF0aW9uLiAKCi0gKipDcnVjaWFsIHF1ZXN0aW9uKio6IEhvdyBwcmVjaXNlIGFyZSB0aGUgY29uY2x1c2lvbnMgb24gdGhlIHBvcHVsYXRpb24gYmFzZWQgb24gYSBncm91cCBvZiBzdWJqZWN0cyBpbiBhIHNhbXBsZSEgCgotIFdlIHdpbGwgdGh1cyBvYnNlcnZlIGRpZmZlcmVuY2VzIGZyb20gc2FtcGxlIHRvIHNhbXBsZS4KCi0gVmFyaWFiaWxpdHkgb2YgdGhlIGRhdGEgcGxheXMgYSBjcnVjaWFsIHJvbGUhICAKCi0tLQoKIyMgQ29udmVudGlvbgoKLSBVc2UgY2FwaXRhbCBsZXR0ZXJzIGZvciBhIHN0dWR5IGNoYXJhY3RlcmlzdGljIChlLmcuIGRpcmVjdCBjaG9sZXN0ZXJvbCkgdG8gaW5kaWNhdGUgdGhhdCBpdCBjaGFuZ2VzIGluIHRoZSBwb3B1bGF0aW9uIHdpdGhvdXQgdGhpbmtpbmcgYWJvdXQgdGhlIG9ic2VydmVkIHZhbHVlIG9mIGEgcGFydGljdWxhciBzdWJqZWN0LgoKLSBWYXJpYWJsZSAkWCQgaXMgYSAqcmFuZG9tIHZhcmlhYmxlKiBhbmQgaXMgdGhlIHJlc3VsdCBvZiAqcmFuZG9tIHNhbXBsaW5nKiBvZiB0aGUgY2hhcmFjdGVyaXN0aWMgZnJvbSB0aGUgcG9wdWxhdGlvbi4gCgotICBSYW5kb20gdmFyaWFibGUgJFgkIGlzIHRodXMgdGhlIHVua25vd24gdmFyaWFibGUgdGhhdCByZXByZXNlbnQgYSBtZWFzdXJlbWVudCB0aGF0IHdlIHBsYW4gdG8gY29sbGVjdCBvbiBhIHJhbmRvbSBzdWJqZWN0LCBidXQgdGhhdCB3ZSBoYXZlIG5vdCBjb2xsZWN0ZWQgeWV0LiAKCi0gVHlwaWNhbGx5IGEgc2VxdWVuY2Ugb2YgcmFuZG9tIHZhcmlhYmxlcyAkWF8xLFxsZG90cyBYX24kIHdpbGwgYmUgY29sbGVjdGVkIGluIHRoZSBzdHVkeSAod2l0aCBuIHN1YmplY3RzIG9yIGV4cGVyaW1lbnRhbCB1bml0cykuIAoKLSBUaGUgY29uY2VwdCBvZiByYW5kb20gdmFyaWFibGVzIGlzIG5lY2Vzc2FyeSB0byByZWFzb24gb24gaG93IHRoZSByZXN1bHRzIGFuZCBjb25jbHVzaW9ucyBjaGFuZ2UgZnJvbSBzYW1wbGUgdG8gc2FtcGxlLiAKCi0gUmFuZG9tIHZhcmlhYmxlcyBjYW4gYmUgcXVhbGl0YXRpdmUsIHF1YW50aXRhdGl2ZSwgZGlzY3JldGUsIGNvbnRpbnVvdXMsIC4uLiAKCi0tLQoKIyBEZXNjcmliaW5nIHRoZSBwb3B1bGF0aW9uIAoKLSBJdCBpcyBpbXBvc3NpYmxlIHRvIHByZWRpY3QgdGhlIHZhbHVlIG9mIGEgcmFuZG9tIHZhcmlhYmxlLgoKLSBUaGUgcmVhbGlzZWQgdmFsdWUgb2YgJFgkIGlzIHN1YmplY3QgdG8gcmFuZG9tIHZhcmlhYmlsaXR5LgoKLSBTdXBwb3NlIHRoYXQgd2UgYXJlIGludGVyZXN0ZWQgaW4gdGhlIElRIG9mIHN1YmplY3QuIElmIHdlIGtub3cgaG93IHRoZSBkYXRhIGFyZSBkaXN0cmlidXRlZCwgd2UgY2FuIHVzZSBwcm9iYWJpbGl0eSB0aGVvcnkgdG8gY2FsY3VsYXRlIHRoZSBwcm9iYWJpbGl0eSB0aGF0IHRoZSBJUSBvZiBhIHJhbmRvbSBzdWJqZWN0IG9mIHRoZSBwb3B1bGF0aW9uIHdpbGwgYmUgYWJvdmUgMTEwLiAgCgotLS0KCiMjSW50ZXJtZXp6byBwcm9iYWJpbGl0eSB0aGVvcnkKCiMjIyBEaXNjcmV0ZSByYW5kb20gdmFyaWFibGVzCgotIFN1cG9zZSB0aGF0IHdlIG1lYXN1cmUgYSBkaXNjcmV0ZSByYW5kb20gdmFyaWFibGUgJFgkCgotIEFsbCBwb3NzaWJsZSB2YWx1ZXMgZm9yIHRoZSByYW5kb20gdmFyaWFibGUgJFgkIGFyZSBjYWxsZWQgdGhlIHNhbXBsZSBzcGFjZSAkXE9tZWdhJC4KCiAgICAtIEZvciBnZW5kZXIgdGhlIHNhbXBsZSBzcGFjZSBpcyAkXE9tZWdhPSgwLDEpJCB3aXRoIDAgKG1hbGUpIG9yIDEgKGZlbWFsZSkuIAogICAgLSBTdXBwb3NlIHRoYXQgd2Ugcm9sZSBhIGRpY2UsIHRoZW4gdGhlIHNhbXBsZSBzcGFjZSBpcyAkXE9tZWdhPSgxLDIsMyw0LDUsNikkLiAKCi0gQW4gZXZlbnQgJEEkICBpcyBhIHN1YnNldCBvZiB0aGUgc2FtcGxlIHNwYWNlIAogICAgICAKICAgICAgLSBHZXQgYW4gZXZlbiBudW1iZXIgd2hlbiByb2xsaW5nIGEgZGljZTogJEE9KDIsNCw2KSQuCiAgICAgIC0gQ2FuIGFsc28gYmUgJEE9KDEpJCBvbmUgIHN1YnNldCBvZiB0aGUgc2FtcGxlIHNwYWNlLiAKCi0gRXZlbnQgc3BhY2UgJFxtYXRoY2Fse0F9JCBpcyB0aGUgY2xhc3Mgb2YgYWxsIHBvc3NpYmxlIGV2ZW50cyBhc3NvY2lhdGVkIHdpdGggYSBnaXZlbiBleHBlcmltZW50LgoKLSBUd28gZXZlbnRzICgkQV8xJCBhbmQgJEFfMiQpIGFyZSBtdWx0aXBsZSBleGNsdXNpdmUgaWYgdGhleSBjYW5ub3Qgb2NjdXIgdG9nZXRoZXIKCiAgICAtIGUuZy4gZXZlbnQgb2YgdGhlIG9kZCBudW1iZXJzICRBXzE9KDEsMyw1KSQgYW5kIHRoZSBldmVudCBvZiBnZXR0aW5nICRBXzI9KDYpJAogICAgLSBzbyAkQV8xIFxiaWdjYXAgQV8yPVxlbXB0eXNldCQuCgotIFByb2JhYmlsaXR5ICRQKEEpJCAgaXMgYSBmdW5jdGlvbiAkUDogQSBccmlnaHRhcnJvdyBbMCwxXSQgd2hpY2ggc2F0aXNmaWVzCiAgICAKICAgIDEuICRQKEEpIFxnZXEgMCQgYW5kICRQKEEpIFxsZXEgMSQgZm9yIGVhY2ggJEEgXGluIFxtYXRoY2Fse0F9JAogICAgMi4gJFAoXE9tZWdhKT0xJAogICAgMy4gRm9yIG11bHRpcGxlIGV4Y2x1c2l2ZSBldmVudHMgJEFfMSwgQV8yLCBcbGRvdHMgQV9rJCB0aGUgcHJvYmFiaWxpdHkgJFAoQV8xIFxjdXAgQV8yIFxsZG90cyBcY3VwIEFfayk9IFAoQV8xKSArIFxsZG90cyArIFAoQV9rKSQgCgotIERpY2UgZXhhbXBsZQoKICAgIC0gb2RkIG51bWJlciAkQT0oMSwzLDUpJDogdGhpcyBpcyB0aGUgdW5pb24gb2YgMyBtdWx0aXBsZSBleGNsdXNpdmUgZXZlbnRzICRBXzE9MSQsICRBXzI9NSQgYW5kICRBXzM9NSQgc28KICAgICRQKEEpPVAoMSkrUCgzKStQKDUpPTEvNisxLzYrMS82PTAuNSQKICAgIC0gJFxPbWVnYT0oMSwyLDMsNCw1LDYpJDogJFAoXE9tZWdhKT0xJAogICAgCi0gSWYgd2UgZHJhdyB0d28gc3ViamVjdHMgKGogYW5kIGspIGluZGVwZW5kZW50bHkgZnJvbSB0aGUgcG9wdWxhdGlvbiB0aGVuIHRoZSBqb2ludCBwcm9iYWJpbGl0eSBvbiAgCiRQKFhfaixYX2spPSBQKFhfailQKFhfaikkCgotLS0KCiMjIyMgUHJvYmFiaWxpdHkgbWFzcyBmdW5jdGlvbiAKCi0gVGhlIHByb2JhYmlsaXR5IG1hc3MgZnVuY3Rpb24gZm9yIGEgcmFuZG9tIHZhcmlhYmxlICRYJCBkZXNjcmliZXMgdGhlIHByb2JhYmlsaXR5IG9mIGVhY2ggcG9zc2libGUgdmFsdWUgb2YgdGhlIHNhbXBsZSBzcGFjZS4KCi0gRXhhbXBsZTogR2VuZGVyIGlzIGEgYmluYXJ5IHZhcmlhYmxlICgwOm1hbGUsIDE6ZmVtYWxlKSBhbmQgYmluYXJ5IHZhcmlhYmxlcyBhcmUgQmVybm91bGxpIGRpc3RyaWJ1dGVkLiA1MC44JSBvZiB0aGUgc3ViamVjdHMgb2YgdGhlIEFtZXJpY2FuIHBvcHVsYXRpb24gYXJlIGZlbWFsZSBhbmQgNDkuMiUgYXJlIG1hbGUuIExldCAkXHBpJCBiZSB0aGUgcHJvYmFiaWxpdHkgb24gYSBmZW1hbGUgJFxwaT0wLjUwOCQuIAogICAgc28gCiAgICAkJCBYXHNpbSBcbGVmdCBceyAKICAgIFxiZWdpbnthcnJheX17bGNsfQogICAgUChYPTApICY9JiAxLVxwaVxcCiAgICBQKFg9MSkgJj0mIFxwaQogICAgXGVuZHthcnJheX0gXHJpZ2h0IC4gJCQKICAgIAogICAgYGBge3J9CiAgICBkYXRhLmZyYW1lKFg9YygwLDEpLHByb2I9YygwLjQ5MiwwLjUwOCkpICU+JQogICAgICBnZ3Bsb3QoYWVzKHg9WCx4ZW5kPVgseT0wLHllbmQ9cHJvYikpICsKICAgICAgZ2VvbV9zZWdtZW50KCkgKwogICAgICB5bGFiKCJQcm9iYWJpbGl0eSIpCiAgICBgYGAKICAgIApSYW5kb20gdmFyaWFibGUgJFgkIGZvbGxvd3MgYW4gQmVybm91bGxpIGRpc3RyaWJ1dGlvbiAkQihccGkpJCB3aXRoIHBhcmFtZXRlciAkXHBpPTAuNTA4JCwgCiAgICAkJEIoXHBpKT0gXHBpXngoMS1ccGkpXnsoeC0xKX0kJAoKLS0tCgojIyMjIEN1bXVsYXRpdmUgZGlzdHJpYnV0aW9uIGZ1bmN0aW9uCgotIFRoZSBjdW11bGF0aXZlIGRpc3RyaWJ1dGlvbiBmdW5jdGlvbiBpcyB0aGUgZnVuY3Rpb24gRih4KSB0aGF0IGNhbGN1bGF0ZXMgdGhlIHByb2JhYmlsaXR5IHRvIG9ic2VydmUgYSByYW5kb20gdmFyaWFibGUgWCBmb3Igd2hpY2ggJFhcbGVxIHgkOiAKJCQgRih4KSA9IFxzdW1cbGltaXRzX3tcZm9yYWxsIFhcbGVxIHh9IFAoeCkkJAoKLSBHZW5kZXIgZXhhbXBsZSAkRigwKT0xLVxwaSQgYW5kIEYoMSk9UChYPTApICsgUChYPTEpPTEKCiAgICBgYGB7cn0KICAgIGRhdGEuZnJhbWUoWD1jKDAsMSksY3VtcHJvYj1jKDAuNDkyLDEpKSAlPiUKICAgICAgZ2dwbG90KGFlcyh4PVgseGVuZD1YLHk9MCx5ZW5kPWN1bXByb2IpKSArCiAgICAgIGdlb21fc2VnbWVudCgpICsKICAgICAgeWxhYigiRih4KSIpCiAgICBgYGAKCi0gRGljZTogCgogICAgYGBge3J9CiAgICBkYXRhLmZyYW1lKFg9MTo2LGN1bXByb2I9Y3Vtc3VtKHJlcCgxLzYsNikpKSAlPiUKICAgICAgZ2dwbG90KGFlcyh4PVgseGVuZD1YLHk9cmVwKDAsNikseWVuZD1jdW1wcm9iKSkgKwogICAgICBnZW9tX3NlZ21lbnQoKSArCiAgICAgIHlsYWIoIkYoeCkiKQogICAgYGBgCgotLS0KCiMjIyMgTWVhbgoKVGhlIG1lYW4gb3IgdGhlIGV4cGVjdGVkIHZhbHVlICRFW1hdJCBvZiBhIGRpc2NyZXRlIHJhbmRvbSB2YXJpYWJsZSBpcyBnaXZlbiBieQoKJCRFW1hdPVxzdW1cbGltaXRzX3t4XGluXE9tZWdhfSB4IFAoWD14KSQkCgotIEdlbmRlciBleGFtcGxlCiAgICAKICAgIC0gJEVbWF09IDAgXHRpbWVzICgxLVxwaSkgKyAxIFx0aW1lcyBccGkgPSBccGkkCiAgICAtIFRoZSBtZWFuIGVxdWFscyAkRVtYXT0wLjUwOCQuCgotIERpY2UgZXhhbXBsZTogCiQgRVtYXT0gMSBcdGltZXMgMS82ICsgMiBcdGltZXMgMS82ICsgXGxkb3RzICsgNiBcdGltZXMgMS82ID0gJCBgciBzdW0oMTo2KS82YAoKLS0tCgojIyMjIFZhcmlhbmNlCgpUaGUgdmFyaWFuY2UgaXMgYSBtZWFzdXJlIGZvciB0aGUgdmFyaWFiaWxpdHkgb2YgYSByYW5kb20gdmFyaWFibGUgYW5kICBpcyBnaXZlbiBieQoKJCRFWyhYLUVbWF0pXjJdPVxzdW1cbGltaXRzX3t4XGluXE9tZWdhfSAoeC1FW1hdKV4yIFAoWD14KSQkCgotIEdlbmRlciBleGFtcGxlCiAgICBcYmVnaW57ZXFuYXJyYXl9CiAgICBFWyhYLUVbWF0pXjJdJj0mKDAtXHBpKV4yXHRpbWVzICgxLVxwaSkrKDEtXHBpKV4yIFx0aW1lcyBccGlcXAogICAgJj0mIFxwaV4yICgxLVxwaSkgKyAoMS1ccGkpXjIgXHBpXFwKICAgICY9JlxwaSAoMS1ccGkpKFxwaSsxLVxwaSlcXAogICAgJj0mXHBpKDEtXHBpKQogICAgXGVuZHtlcW5hcnJheX0KCi0tLQoKIyMjIENvbnRpbnVvdXMgcmFuZG9tIHZhcmlhYmxlIAoKCi0gVGhlIGRlbnNpdHkgZnVuY3Rpb24gJGYoeCkkIGRlc2NyaWJlcyBob3cgbGlrZWx5IGl0IGlzIHRvIG9ic2VydmUgYSBwYXJ0aWN1bGFyIHZhbHVlIG9mIHJhbmRvbSB2YXJpYWJsZSBYIHdoZW4gd2Ugc2FtcGxlIGEgcmFuZG9tIHN1YmplY3QgZnJvbSB0aGUgcG9wdWxhdGlvbi4gCgotIE1hbnkgYmlvbG9naWNhbCBjaGFyYWN0ZXJpc3RpY3MgYXJlIGFwcHJveGltYXRpdmVseSBub3JtYWxseSBkaXN0cmlidXRlZCAodXBvbiB0cmFuc2Zvcm1hdGlvbikgCiAgICAkJGYoeCkgPSBcZnJhY3sxfXtcc3FydHsyXHBpXHNpZ21hXjJ9fSBlXnstXGZyYWN7KHgtXG11KV4yfXsyXHNpZ21hXjJ9fSQkCgotIFRoaXMgaXMgZGVub3RlZCBpbiBzaG9ydGhhbmQgYXMgJGYoeCkgPSBOKFxtdSxcc2lnbWFeMikkCgotIFRoZSBJUSBpbiB0aGUgcG9wdWxhdGlvbiBpcyBrbm93biB0byBmb2xsb3cgYSBub3JtYWwgZGlzdHJpYnV0aW9uIHdpdGggbWVhbiAkXG11PTEwMCQgYW5kIHN0YW5kYXJkIGRldmlhdGlvbiAkXHNpZ21hPTE1JC4gIAokJElRIFxzaW0gTigxMDAsMTVeMikkJAogICAgCgotIFIgd2UgY2FuIHVzZSB0aGUgZG5vcm0gZnVuY3Rpb24gdG8gY2FsY3VsYXRlIHRoZSBkZW5zaXR5IG9mIHBhcnRpY3VsYXIgdmFsdWVzIG9mIFg9eC4KCi0gVGhlIGFyZ3VtZW50cyBvZiBgZG5vcm1gIGFyZSBgbWVhbmAgKCRcbXUkKSBhbmQgYHNkYCAoc3RhbmRhcmQgZGV2aWF0aW9uICRcc2lnbWEkKS4gCgpgYGB7ciBJUSwgZmlnLmFsaWduPSdjZW50ZXInfQpwYXIobWFyPWMoNSwgNCwgNCwgMikgKyAwLjEsIG1haT1jKDEuMDIsMC44MiwwLjgyLDAuNDIpKQpncmlkIDwtIHNlcSg0MCwxNjAsLjEpCnBsb3QoZ3JpZCxkbm9ybShncmlkLG1lYW49MTAwLHNkPTE1KSwKICAgICB4bGFiPSJJUSIsCiAgICAgY29sPTIseWxhYj0iRGVuc2l0ZWl0Iix0eXBlPSJsIixsd2Q9MixjZXgubGFiPTEuNSxjZXguYXhpcz0xLjUpCmBgYAoKLSBXaXRoaW4gY2VydGFpbiBsaW1pdHMsIGNvbnRpbnVvdXMgdmFyaWFibGVzIGNhbiB0YWtlIGFsbCBwb3NzaWJsZSB2YWx1ZXMgc28gdGhlIHNhbXBsZSBzcGFjZSAkXE9tZWdhJCBpcyBpbmZpbml0ZWx5IGxhcmdlLiAKCi0tLQoKIyMjI0N1bXVsYXRpdmUgZGlzdHJpYnV0aW9uCgotIEFnYWluIHRoZSBjdW11bGF0aXZlIGRpc3RyaWJ1dGlvbiAkRihYKT1QKFhcbGVxIHgpJC4KCi0gQmVjYXVzZSBYIGlzIGNvbnRpbnVvdXMgd2Ugd2lsbCBjYWxjdWxhdGUgdGhpcyBwcm9iYWJpbGl0eSB1c2luZyBhbiBpbnRlZ3JhbAokJEYoeCk9XGludCBcbGltaXRzX3stXGluZnR5fV54IGYoeCkgZHgkJAoKLSBOb3RlIHRoYXQgJGYoeCk9MCQgaWYgeCBkb2VzIG5vdCBiZWxvbmcgdG8gdGhlIHNhbXBsZSBzcGFjZS4gCgotIFdlIGNhbiBjYWxjdWxhdGUgJEYoeCkkIGZvciBhIG5vcm1hbGx5IGRpc3RyaWJ1dGVkIHJhbmRvbSB2YXJpYWJsZSB1c2luZyB0aGUgYHBub3JtYCBmdW5jdGlvbiBhZ2FpbiB3aXRoIGFyZ3VtZW50cyBgbWVhbmAgYW5kIGBzZGAuIAoKYGBge3J9CnBsb3QoZ3JpZCxwbm9ybShncmlkLG1lYW49MTAwLHNkPTE1KSx0eXBlPSJsIix4bGFiPSJJUSIseWxhYj0iUHJvYmFiaWxpdHkiKQpgYGAKClNvIHRoZSBwcm9iYWJpbGl0eSB0aGF0IHRoZSBJUSBvZiBhIHJhbmRvbSBzdWJqZWN0IGlzIGJlbG93IDgwIGNhbiBiZSBvYnRhaW5lZCBieQoKYGBge3J9CnBub3JtKDgwLG1lYW49MTAwLHNkPTE1KQpgYGAKCmBgYHtyIGZpZy5hbGlnbj0nY2VudGVyJyxlY2hvPUZBTFNFfQpncmlkMjwtc2VxKDQwLDgwLC4wMSkKcGxvdChncmlkLGRub3JtKGdyaWQsbWVhbj0xMDAsc2Q9MTUpLAogICAgIHhsYWI9IklRIiwKICAgICBjb2w9Mix5bGFiPSJEZW5zaXRlaXQiLHR5cGU9ImwiLGx3ZD0yLGNleC5sYWI9MS41LGNleC5heGlzPTEuNSkKcG9seWdvbih4PWMoZ3JpZDIsODAsNDApLHk9Yyhkbm9ybShncmlkMiwxMDAsMTUpLDAsMCksY29sPTIsYm9yZGVyPTIpCnRleHQoODAsZG5vcm0oODAsbWVhbj0xMDAsc2Q9MTUpLHBhc3RlMCgiUChYIDwgODApID0gIixyb3VuZChwbm9ybSg4MCwxMDAsMTUpKjEwMCwxKSwiJSIpLGNvbD0yLGNleD0xLjUscG9zPTQpCmBgYAoKYGBge3IgZmlnLmFsaWduPSdjZW50ZXInLGVjaG89RkFMU0V9CnBsb3QoZ3JpZCxwbm9ybShncmlkLG1lYW49MTAwLHNkPTE1KSx0eXBlPSJsIix4bGFiPSJJUSIseWxhYj0iUHJvYmFiaWxpdHkiLGx3ZD0yLGNvbD0yKQpsaW5lcyhjKDgwLDgwLDgwLDApLGMoMCxyZXAocG5vcm0oODAsMTAwLDE1KSwzKSksbHR5PTIpCmBgYAoKLSBGb3IgdGhlIGxhcmdlc3QgcG9zc2libGUgdmFsdWUgb2YgJFgkIHdlIGludGVncmF0ZSBvdmVyIHRoZSBlbnRpcmUgc2FtcGxlIHNwYWNlICRcT21lZ2EkIHNvIAokJFxpbnQgXGxpbWl0c197eCBcaW4gXE9tZWdhfSBmKHgpIGR4PTEkJAoKLSBTbyB0aGUgYXJlYSB1bmRlciB0aGUgZGVuc2l0eSBmdW5jdGlvbiBlcXVhbHMgMSEgCgotLS0KCiMjIyMgTWVhbiBhbmQgVmFyaWFuY2UuIAoKLSBUaGUgbWVhbiBvciB0aGUgZXhwZWN0ZWQgdmFsdWUgJEVbWF0kIG9mIGEgY29udGludW91cyByYW5kb20gdmFyaWFibGUgaXMgZ2l2ZW4gYnkgCgokJFxpbnQgXGxpbWl0c197eCBcaW4gXE9tZWdhfSB4IGYoeCkgZHgkJCAKCi0gRm9yIHRoZSBub3JtYWwgZGlzdHJpYnV0aW9uIAokJFxpbnQgXGxpbWl0c197LVxpbmZ0eX1eeytcaW5mdHl9IHggZih4KSBkeCA9IFxtdSQkCgotIFRoZSB2YXJpYW5jZSAkRVsoWC1FW1hdKV4yXSQgaXMgZ2l2ZW4gYnkgCgokJFxpbnQgXGxpbWl0c197eCBcaW4gXE9tZWdhfSAoeC1FW1hdKV4yIGYoeCkgZHgkJCAKCi0gRm9yIHRoZSBub3JtYWwgZGlzdHJpYnV0aW9uIHdlIGdldCAKCiQkXGludCBcbGltaXRzX3stXGluZnR5fV57K1xpbmZ0eX0gKHgtXG11KV4yIGYoeCkgZHggPSBcc2lnbWFeMiQkCgotIEl0IGlzIG9mdGVuIGRpZmZpY3VsdCB0byBpbnRlcnByZXQgdGhlIHZhcmlhbmNlIGJlY2F1c2UgaXQgaXMgbm90IGluIHRoZSBzYW1lIHVuaXQgYXMgdGhlIHJhbmRvbSB2YXJpYWJsZSBhbmQgdGhlIG1lYW4uIApXZSB0aGVyZWZvcmUgb2Z0ZW4gdXNlIHRoZSBzdGFuZGFyZCBkZXZpYXRpb24KCiQkU0Q9XHNxcnR7RVsoWC1FW1hdKV4yXX0kJAoKClRoZSBTRCBmb3IgYSBub3JtYWwgZGlzdHJpYnV0aW9uLCAkXHNpZ21hJCBoYXMgdGhlIG5pY2UgaW50ZXJwcmV0YXRpb24gdGhhdCBhcHByb3hpbWF0ZWx5IDY4JSBvZiB0aGUgcG9wdWxhdGlvbiBoYXMgYSB2YWx1ZSBmb3IgdGhlIGNoYXJhY3RlcmlzdGljIFggd2l0aGluIHRoZSBpbnRlcnZhbCBvZiBvbmUgc3RhbmRhcmQgZGV2aWF0aW9uICgkXHNpZ21hJCkgYXJvdW5kIHRoZSBtZWFuOiAKCiQkUChcbXUtXHNpZ21hIDwgWCA8IFxtdSArIFxzaWdtYSkgXGFwcHJveCAwLjY4JCQKCgpgYGB7ciBmaWcuYWxpZ249J2NlbnRlcicsZWNobz1GQUxTRX0KZ3JpZDI8LXNlcSg4NSwxMTUsLjAxKQpwbG90KGdyaWQsZG5vcm0oZ3JpZCxtZWFuPTEwMCxzZD0xNSksCiAgICAgeGxhYj0iSVEiLAogICAgIGNvbD0yLHlsYWI9IkRlbnNpdGVpdCIsdHlwZT0ibCIsbHdkPTIsY2V4LmxhYj0xLjUsY2V4LmF4aXM9MS41KQpwb2x5Z29uKHg9YyhncmlkMiwxMTUsODUpLHk9Yyhkbm9ybShncmlkMiwxMDAsMTUpLDAsMCksY29sPSJncmV5Iixib3JkZXI9ImdyZXkiKQp0ZXh0KDExNSxkbm9ybSgxMTUsbWVhbj0xMDAsc2Q9MTUpLHBhc3RlMCgiUCg4NTxYPDExNSkgPSAiLHJvdW5kKChwbm9ybSgxMTUsMTAwLDE1KS1wbm9ybSg4NSwxMDAsMTUpKSoxMDAsMSksIiUiKSxjb2w9MixjZXg9MS4zLHBvcz00KQphYmxpbmUodj0xMDApCnRleHQoNCwwLGV4cHJlc3Npb24obXUpKQpsaW5lcyhjKDg1LDExNSkscmVwKGRub3JtKDExNSwxMDAsMTUpLDIpKQp0ZXh0KDEwNy41LGRub3JtKDExNC41LDEwMCwxNSksZXhwcmVzc2lvbihzaWdtYSkpCnRleHQoMTAwLTE1LzIsZG5vcm0oMTE0LjUsMTAwLDE1KSxleHByZXNzaW9uKHNpZ21hKSkKYGBgCgotIEZvciBub3JtYWxseSBkaXN0cmlidXRlZCByYW5kb20gdmFyaWFibGVzIGFwcHJveGltYXRlbHkgOTUlIG9mIHRoZSBzdWJqZWN0cyBpbiB0aGUgcG9wdWxhdGlvbiBoYXZlIGEgdmFsdWUgdGhhdCBsYXlzIGluIHR3byBzdGFuZGFyZCBkZXZpYXRpb25zICgkMiBcc2lnbWEkKSBvZiB0aGUgbWVhbgoKJCRQW1xtdSAtIDIgXHNpZ21hIDwgWCA8IFxtdSArIDIgXHNpZ21hXVxhcHByb3ggMC45NSQkCmBgYHtyIGZpZy5hbGlnbj0nY2VudGVyJyxlY2hvPUZBTFNFfQpncmlkMjwtc2VxKDcwLDEzMCwuMDEpCnBsb3QoZ3JpZCxkbm9ybShncmlkLG1lYW49MTAwLHNkPTE1KSwKICAgICB4bGFiPSJJUSIsCiAgICAgY29sPTIseWxhYj0iRGVuc2l0ZWl0Iix0eXBlPSJsIixsd2Q9MixjZXgubGFiPTEuNSxjZXguYXhpcz0xLjUpCnBvbHlnb24oeD1jKGdyaWQyLDEzMCw3MCkseT1jKGRub3JtKGdyaWQyLDEwMCwxNSksMCwwKSxjb2w9ImdyZXkiLGJvcmRlcj0iZ3JleSIpCnRleHQoMTE1LGRub3JtKDExNSxtZWFuPTEwMCxzZD0xNSkscGFzdGUwKCJQKDg1PFg8MTE1KSA9ICIscm91bmQoKHBub3JtKDEzMCwxMDAsMTUpLXBub3JtKDcwLDEwMCwxNSkpKjEwMCwxKSwiJSIpLGNvbD0yLGNleD0xLjMscG9zPTQpCmFibGluZSh2PTEwMCkKdGV4dCg0LDAsZXhwcmVzc2lvbihtdSkpCmxpbmVzKGMoNzAsMTMwKSxyZXAoZG5vcm0oMTMwLDEwMCwxNSksMikpCnRleHQoMTE1LGRub3JtKDEyOCwxMDAsMTUpLGV4cHJlc3Npb24oc2lnbWEpKQp0ZXh0KDg1LGRub3JtKDEyOCwxMDAsMTUpLGV4cHJlc3Npb24oc2lnbWEpKQpgYGAKCi0tLQoKLSBJbiBSIGN1bXVsYXRpdmUgZGlzdHJpYnV0aW9uIGNhbiBiZSBjYWxjdWxhdGVkIHdpdGggdGhlIGZ1bmN0aW9uIHJub3JtLiBUaGlzIGZ1bmN0aW9uIGhhcyBhcmd1bWVudHMgcSB0aGUgcXVhbnRpbGUsIHRoZSBtZWFuIGFuZCB0aGUgc3RhbmRhcmQgZGV2aWF0aW9uLgoKLSBJZiB5b3Ugd2FudCBoZWxwIHlvdSBjYW4gYWx3YXlzIHR5cGU6CgpgYGB7cn0KP3Bub3JtCmBgYAoKLSBXaGF0IGlzIHRoZSBwcm9iYWJpbGl0eSB0aGF0IGEgcmFuZG9tIHN1YmplY3QgaW4gdGhlIHBvcHVsYXRpb24gd2lsbCBoYXZlIGFuIElRIGJlbG93IDkwPwoKYGBge3J9CnBub3JtKHE9OTAsbWVhbj0xMDAsc2Q9MTUpCmBgYAoKLSBXaGF0IGlzIHRoZSBwcm9iYWJpbGl0eSB0aGF0IGEgcmFuZG9tIHN1YmplY3QgaW4gdGhlIHBvcHVsYXRpb24gd2lsbCBoYXZlIGFuIElRIGJlbG93IDExMD8KCi0gV2hhdCBpcyB0aGUgcHJvYmFiaWxpdHkgdGhhdCBhIHJhbmRvbSBzdWJqZWN0IGluIHRoZSBwb3B1bGF0aW9uIHdpbGwgaGF2ZSBhbiBJUSBiZXR3ZWVuIDkwIGFuZCAxMTA/CgotLS0KCiMjIFN0YW5kYXJkaXphdGlvbgoKLSBOb3JtYWwgZGF0YSBhcmUgb2Z0ZW4gc3RhbmRhcmRpemVkLiAKCiQkej1cZnJhY3t4LVxtdX17XHNpZ21hfSQkCgotIFVwb24gc3RhbmRhcmRpemF0aW9uIHRoZSBkYXRhIGZvbGxvdyBhIHN0YW5kYXJkIG5vcm1hbCBkaXN0cmlidXRpb24gd2l0aCBtZWFuICRcbXU9MCQgYW5kIHZhcmlhbmNlICRcc2lnbWFeMj0xJDoKJCR6IFxzaW0gTigwLDEpJCQKCldlIGNhbiB1c2UgdGhlIHFub3JtIGZ1bmN0aW9uIHRvIGNhbGN1bGF0ZSB0aGUgcXVhbnRpbGUgJHpfezIuNVwlfSQgYW5kICR6X3s5Ny41XCV9JCBjb3JyZXNwb25kaW5nIHRvICRGKHpfezIuNVwlfSk9MC4wMjUkIGFuZCAkRih6X3s5Ny41XCV9KT0wLjk3NSQsIHJlc3BlY3RpdmVseS4gCgpgYGB7cn0KcW5vcm0oMC4wMjUpCnFub3JtKDAuOTc1KQoKYGBgCgpUaGlzIGluZGVlZCAgaW5kaWNhdGVzIHRoYXQgYWJvdXQgOTcuNSUtMi41JT05NSUgb2YgYSBzdGFuZGFyZCBub3JtYWwgcmFuZG9tIHZhcmlhYmxlIGZhbGxzIHdpdGhpbiB0aGUgaW50ZXJ2YWwgWy0yLDJdLCBvciB3aXRoaW4gMiB0aW1lcyB0aGUgc3RhbmRhcmQgZGV2aWF0aW9uICgkXHNpZ21hPTEkKSBmcm9tIHRoZSBtZWFuICgkXG11PTAkKS4KCi0tLQoKIyBTYW1wbGUKCi0gSW4gcmVhbCBzdHVkaWVzIHdlIHR5cGljYWxseSBkbyBub3Qga25vdyB0aGUgZGlzdHJpYnV0aW9uIGluIHRoZSBwb3B1bGF0aW9uLgoKLSBEdWUgdG8gZmluYW5jaWFsIGFuZCBsb2dpc3RpYyByZWFzb25zIHdlIGNhbiBhbG1vc3QgbmV2ZXIgc3R1ZHkgdGhlIGVudGlyZSBwb3B1bGF0aW9uLgoKLSBUaGUgcG9wdWxhdGlvbiBwYXJhbWV0ZXJzIChlLmcuIG1lYW4gSVEsIHZhcmlhbmNlIG9mIElRKSAgY2FuIHRoZXJlZm9yZSBub3QgYmUgb2J0YWluZWQgd2l0aG91dCBlcnJvci4KCi0gT25seSBhcyBzbWFsbCBzdWJzZXQgb2YgdGhlIHBvcHVsYXRpb24gY2FuIGJlIHN0dWRpZWQ6IHRoZSAqc2FtcGxlKiAKLSBTYW1wbGUgYWNjb3JkaW5nIHRvIGEgc3RydWN0dXJlZCBkZXNpZ246IHNlbGVjdCAqKnN1YmplY3QgY29tcGxldGVseSBhdCByYW5kb20gZnJvbSB0aGUgcG9wdWxhdGlvbioqIHNvIHRoYXQgZXZlcnkgc3ViamVjdCBoYXMgYW4gZXF1YWwgcHJvYmFiaWxpdHkgdG8gZW5kIHVwIGluIHRoZSBzYW1wbGUgJFxyaWdodGFycm93JCAqKlJlcHJlc2VudGF0aXZlIHNhbXBsZSoqLgoKLSBUaGUgc2FtcGxlICR4XzEsIHhfMiwgLiAuIC4gLCB4X3tufSQgY2FuIGJlIGNvbnNpZGVyZWQgdG8gYmUgJG4kIHJlYWxpc2F0aW9ucyBvZiB0aGUgc2FtZSByYW5kb20gdmFyaWFibGUgJFgkLCBmb3Igc3ViamVjdHMgJGkgPSAxLDIsLi4uLG4kLgoKLSBUaGUgZGlzdHJpYnV0aW9uIGluIHRoZSBwb3B1bGF0aW9uIGlzIHVua25vd24gYW5kIGhhcyB0byBiZSBlc3RpbWF0ZWQuIAoKLSBJZiB3ZSBjYW4gYXNzdW1lIHRoYXQgdGhlIHN0dWRpZWQgY2hhcmFjdGVyaXN0aWMgZm9sbG93cyBhIHBhcnRpY3VsYXIgZGlzdHJpYnV0aW9uIChlLmcuIGEgbm9ybWFsIGRpc3RyaWJ1dGlvbiAkTihcbXUsXHNpZ21hXjIpJCB0aGVuIHdlIG9ubHkgaGF2ZSB0byBlc3RpbWF0ZSB0aGUgcG9wdWxhdGlvbiBwYXJhbWV0ZXJzIChlLmcgJFxtdSQgYW5kICRcc2lnbWFeMiQpIGJhc2VkIG9uIHRoZSBzYW1wbGUuIAoKLSBXZSByZWZlciB0byB0aGVtIGFzIGVzdGltYXRlcyBhbmQgZGVub3RlIHRoZW0gYnkgJFxoYXQgXG11JCBhbmQgJFxoYXQgXHNpZ21hXjIkLgoKLS0tCgojIyBOSEFORVMgZXhhbXBsZQoKLSBHZW5kZXIgaW4gdGhlIHBvcHVsYXRpb24KLSBTZWxlY3QgJG49MTAwMDAkIHN1YmplY3RzIGF0IHJhbmRvbSBmcm9tIHRoZSBBbWVyaWNhbiBwb3B1bGF0aW9uLgotIE9uY2UgdGhlIHJhbmRvbSBpbmRpdmlkdWFscyBhcmUgc2FtcGxlZCBmcm9tIHRoZSBwb3B1bGF0aW9uIHdlIGhhdmUgb2JzZXJ2ZWQgJG4kIHJlYWxpc2F0aW9ucyBvZiB0aGUgcmFuZG9tIHZhcmlhYmxlICRYJC4gCgotICpDb252ZW50aW9uKjogT2JzZXJ2ZWQgdmFsdWVzICRccmlnaHRhcnJvdyQgYXJlIGRlbm90ZWQgd2l0aCBhIHNtYWxsIGxldHRlciAkeCQuCgotICR4JCBpcyBhIHBhcnRpY3VsYXIgdmFsdWUgbWVhc3VyZWQvb2JzZXJ2ZWQgaW4gYSBjb25kdWN0ZWQgZXhwZXJpbWVudCBhbmQgbm8gbG9uZ2VyIGFuIHVua25vd24gdmFyaWFibGUuCgojIyBJbiBzdW1tYXJ5ICAKCiAgLSBVbmtub3duIHZhbHVlcyBvZiB0aGUgc3R1ZGllZCBwb3B1bGF0aW9uIGNoYXJhY3RlcmlzdGljIGZvciAxIHRvICRuJCBzdWJqZWN0cyBpbiBhIHNhbXBsZSBhcmUgcmFuZG9tIHZhcmlhYmxlczogJFhfMSwgXGxkb3RzLCBYX24kIAogIC0gV2UgaGF2ZSB0byByZWFzb24gb24gdGhpcyBpbiBvcmRlciB0byB1bmRlcnN0YW5kIGhvdyB0aGUgb2JzZXJ2YXRpb25zLCBlc3RpbWF0ZXMgYW5kIGNvbmNsdXNpb25zIG9mIGEgc3R1ZHkgY2FuIGNoYW5nZSBmcm9tIHNhbXBsZSB0byBzYW1wbGUuIAogIC0gSW4gYSBzYW1wbGUgd2Ugb2JzZXJ2ZSB0aGUgcmVhbGlzZWQgb3V0Y29tZXMgJHhfMSwgeF8yLCBcZG90cywgeF9uJDogZS5nLiB0aGUgb2JzZXJ2ZWQgZ2VuZGVycyBvciB0aGUgb2JzZXJ2ZWQgZGlyZWN0IGNob2xlc3Rlcm9sIGxldmVscyBvZiB0aGUgc3ViamVjdHMgaW4gdGhlIHNhbXBsZS4gCgotLS0KCiMgR2VuZGVyIEV4YW1wbGUKCmBgYHtyfQpsaWJyYXJ5KE5IQU5FUykKTkhBTkVTICU+JSBnZ3Bsb3QoYWVzKHg9R2VuZGVyKSkgKyBnZW9tX2JhcigpCmBgYAoKLSBHZW5kZXIgaXMgYSBiaW5hcnkgdmFyaWFibGUuIAotIEl0IHRodXMgZm9sbG93cyBhIEJlcm5vdWxsaSBkaXN0aWJ1dGlvbi4gCi0gVGhlIHBhcmFtZXRlciBvZiBhIEJlcm5vdWxsaSBkaXN0cmlidXRpb24gaXMgdGhlIG1lYW4gJFxwaSQuIAotIFdlIGNhbiBlc3RpbWF0ZSAkXHBpJCBiYXNlZCBvbiB0aGUgc2FtcGxlIHVzaW5nIHRoZSBzYW1wbGUgbWVhbiAkXGJhciB4ID0gXHN1bVxsaW1pdHNfe2k9MX1ebiB4X2kkIAotIE5vdGUsIHRoYXQgdGhlIHNhbXBsZSBtZWFuIGlzIGFsc28gYSByYW5kb20gdmFyaWFibGUhIEl0IGFsc28gdmFyaWVzIGZyb20gc2FtcGxlIHRvIHNhbXBsZSEKCmBgYHtyfQpOSEFORVMkR2VuZGVyICU+JSBoZWFkCmBgYAoKLSBOb3RlLCB0aGF0IEdlbmRlciBpcyBhIGZhY3RvciBhbmQgdGhhdCB0aGUgZmVtYWxlcyBhcmUgdGhlIHJlZmVyZW5jZSBjbGFzcyAoZmlyc3QgY2xhc3MpLiAKLSBSIGJ5IGRlZmF1bHQgdXNlcyB0aGUgbGV2ZWwgd2hpY2ggY29tZXMgZmlyc3QgaW4gdGhlIGFsZmFiZXQgYXMgdGhlIHJlZmVyZW5jZSBjbGFzcy4gCi0gV2UgY2FuIHJlY29kZSB0aGUgR2VuZGVyIHVzaW5nIGEgMCBhbmQgMSBjb2RpbmcuIAotIFdoZW4gd2UgdXNlIHRoZSBhcy5udW1lcmljKCkgZnVuY3Rpb24gdGhlIGZhY3RvciBHZW5kZXIgaXMgdHJhbnNmb3JtZWQgaW4gYSBudW1lcmljIHZhbHVlLiBJdCBoYXMgdHdvIHZhbHVlcyAxIG9yIDIuIDEgc3RhbmRzIGZvciB0aGUgZmlyc3QgbGV2ZWwgKGZlbWFsZXMpIGFuZCAyIGZvciB0aGUgc2Vjb25kIGxldmVsIG1hbGVzLiBJZiB3ZSBzdWJ0cmFjdCAxIGZyb20gaXQgd2UgaGF2ZSBhIDAgYW5kIDEgZW5jb2RpbmcgKDAgZm9yIGZlbWFsZXMgYW5kIDEgZm9yIG1hbGVzKS4KCmBgYHtyfQpOSEFORVM8LU5IQU5FUyAlPiUgbXV0YXRlKGdlbmRlcj1hcy5udW1lcmljKEdlbmRlciktMSkKbWVhbihOSEFORVMkZ2VuZGVyKQpgYGAKCi0gTm90ZSwgdGhhdCBkdWUgdG8gdGhlIGVuY29kaW5nIHRoZSBzYW1wbGUgbWVhbiBpcyBhbiBlc3RpbWF0ZSBmb3IgdGhlIGZyYWN0aW9uIG9mIG1hbGVzIGluIHRoZSBwb3B1bGF0aW9uLiAKCi0gQWx3YXlzIGJlIGNhcmVmdWwgd2l0aCB0aGUgZW5jb2RpbmchCgotLS0KCiMgRGlyZWN0IGNob2xlc3Rlcm9sIGV4YW1wbGUKCiMjIEVtcGlyaWNhbCBkaXN0cmlidXRpb24KCi0gV2UgY2FuIGVzdGltYXRlIHRoZSBkaXJlY3QgY2hvbGVzdGVyb2wgZGlzdHJpYnV0aW9uIG9mIGZlbWFsZXMgdXNpbmcgYSBoaXN0b2dyYW0gCgpgYGB7cn0KTkhBTkVTICU+JSBmaWx0ZXIoR2VuZGVyPT0iZmVtYWxlIikgJT4lIApnZ3Bsb3QoYWVzKHg9RGlyZWN0Q2hvbCkpICsgCmdlb21faGlzdG9ncmFtKCkKYGBgCgotIE5vdGUsIHRoYXQgdGhlIGRpc3RyaWJ1dGlvbiBpcyBza2V3ZWQgd2l0aCBhIHRhaWwgdG8gdGhlIHJpZ2h0LiAKCi0gV2UgY2FuIGVzdGltYXRlIHRoZSBjdW11bGF0aXZlIGRpc3RyaWJ1dGlvbiBmdW5jdGlvbiB1c2luZyB0aGUgZW1waXJpY2FsIGN1bXVsYXRpdmUgZGlzdHJpYnV0aW9uIGZ1bmN0aW9uLiAKICAgIC0gRXZlcnkgb2JzZXJ2YXRpb24gaW4gdGhlIHNhbXBsZSBpcyBvYnNlcnZlZCBvbmNlLgogICAgLSBTbyB0aGUgZW1waXJpY2FsIGRpc3RyaWJ1dGlvbiBvZiB0aGUgc2FtcGxlIGlzIGEgZGlzY3JldGUgZGlzdHJpYnV0aW9uIHdpdGggcHJvYmFiaWxpdHkgb2YgMS9uIG9uIGV2ZXJ5IG9ic2VydmF0aW9uLiAKICAgIC0gVGhlIGVtcGlyaWNhbCBjdW11bGF0aXZlIGRpc3RyaWJ1dGlvbiBmdW5jdGlvbiB0aGVuIGJlY29tZXMgCiAgICAkJEVDREYoeCkgPSBcc3VtXGxpbWl0c197eF9pIFxsZXEgeH0gXGZyYWN7MX17bn0gPSBcZnJhY3tcIyAoeF9pIFxsZXEgeCl9e259JCQKICAgIApgYGB7cn0KZmVtIDwtIE5IQU5FUyAlPiUgZmlsdGVyKEdlbmRlcj09ImZlbWFsZSImIWlzLm5hKERpcmVjdENob2wpKQpmZW0gJT4lIApnZ3Bsb3QoYWVzKHg9RGlyZWN0Q2hvbCkpICsgCnN0YXRfZWNkZigpCmBgYAoKICAgIC0gV2UgYWxzbyBpbGx1c3RyYXRlIHRoaXMgZm9yIGEgc2FtcGxlIHdpdGggc2FtcGxlIHNpemUgMTAKICAgIApgYGB7cn0Kc2V0LnNlZWQoMSkKZmVtMTA8LSBOSEFORVMgJT4lIGZpbHRlcihHZW5kZXI9PSJmZW1hbGUiJiFpcy5uYShEaXJlY3RDaG9sKSkgJT4lIHNhbXBsZV9uKHNpemU9MTApIApmZW0xMCAlPiUgZ2dwbG90KGFlcyh4PURpcmVjdENob2wpKSArIApzdGF0X2VjZGYoKQpgYGAKCi0tLQoKIyMgTm9ybWFsIGFwcHJveGltYXRpb24KCi0gSW4gdGhlIGludHJvZHVjdGlvbiB3ZSBoYXZlIHNlZW4gdGhhdCB0aGUgbG9nIHRyYW5zZm9ybWVkIGRpcmVjdCBjaG9sZXN0ZXJvbCBsZXZlbHMgaGFkIGEgbmljZSBiZWxsIHNoYXBlLiAKCmBgYHtyfQogIGZlbSAlPiUgZ2dwbG90KGFlcyh4PURpcmVjdENob2wlPiVsb2cyKSkrCiAgZ2VvbV9oaXN0b2dyYW0oYWVzKHk9Li5kZW5zaXR5Li4sIGZpbGw9Li5jb3VudC4uKSkgKwogIHhsYWIoIkRpcmVjdCBDaG9sZXN0ZXJvbCAobG9nMikiKSArCiAgc3RhdF9mdW5jdGlvbihmdW49ZG5vcm0sY29sb3I9InJlZCIsYXJncz1saXN0KG1lYW49bWVhbihmZW0kRGlyZWN0Q2hvbCU+JWxvZzIpLCBzZD1zZChmZW0kRGlyZWN0Q2hvbCU+JWxvZzIpKSkKYGBgCgotIFdlIGNhbiBub3cgYXBwcm94aW1hdGUgdGhlIGRpc3RyaWJ1dGlvbiBvZiBsb2cyIHRyYW5zZm9ybWVkIGRpcmVjdCBjaG9sZXN0ZXJvbCBsZXZlbHMgdXNpbmcgYSBub3JtYWwgZGlzdHJpYnV0aW9uLiAKCi0gV2Ugb25seSBoYXZlIHRvIGVzdGltYXRlIHR3byBwYXJhbWV0ZXJzOiB0aGUgbWVhbiBhbmQgdGhlIHZhcmlhbmNlLiBXZSBjYW4gZG8gdGhpcyBiYXNlZCBvbiB0aGUgc2FtcGxlIG1lYW4gKCRcYmFyIHgkKSBhbmQgc2FtcGxlIHZhcmlhbmNlICgkc14yJCkgb3Igc2FtcGxlIHN0YW5kYXJkIGRldmlhdGlvbiAoJHMkKS4gCgoKYGBge3J9CnhCYXI8LW1lYW4oZmVtJERpcmVjdENob2wlPiVsb2cyKQpzZEJhcjwtc2QoZmVtJERpcmVjdENob2wlPiVsb2cyKQp4QmFyCnNkQmFyCmBgYAoKCi0gV2UgY2FuIGRvIHRoZSBzYW1lIHRoaW5nIGZvciB0aGUgc21hbGwgc2FtcGxlIHdpdGggMTAgd29tZW4uCgpgYGB7cn0KICBmZW0xMCAlPiUgZ2dwbG90KGFlcyh4PURpcmVjdENob2wlPiVsb2cyKSkrCiAgZ2VvbV9oaXN0b2dyYW0oYWVzKHk9Li5kZW5zaXR5Li4sIGZpbGw9Li5jb3VudC4uKSxiaW5zPTEwKSArCiAgeGxhYigiRGlyZWN0IENob2xlc3Rlcm9sIChsb2cyKSIpICsKICBzdGF0X2Z1bmN0aW9uKGZ1bj1kbm9ybSxjb2xvcj0icmVkIixhcmdzPWxpc3QobWVhbj1tZWFuKGZlbTEwJERpcmVjdENob2wlPiVsb2cyKSwgc2Q9c2QoZmVtMTAkRGlyZWN0Q2hvbCU+JWxvZzIpKSkgKwogIHhsaW0oLTIsMikKYGBgCgoKYGBge3J9CnhCYXIxMDwtbWVhbihmZW0xMCREaXJlY3RDaG9sJT4lbG9nMikKc2RCYXIxMDwtc2QoZmVtMTAkRGlyZWN0Q2hvbCU+JWxvZzIpCnhCYXIxMApzZEJhcjEwCmBgYAoKLS0tCgojIyBSZWZlcmVuY2UgaW50ZXJ2YWxzCgotIE5vcm1hbCB2YWx1ZXMgZm9yIHRoZSBjaG9sZXN0ZXJvbCBsZXZlbHMgaW4gdGhlIHBvcHVsYXRpb24gY2FuIGJlIGNhbGN1bGF0ZWQgdXNpbmcgYSByZWZlcmVuY2UgaW50ZXJ2YWwuIFR5cGljYWxseSBhIDk1JSByZWZlcmVuY2UgaW50ZXJ2YWwgaXMgdXNlZCwgc28gdGhhdCA5NSUgb2YgdGhlIHN1YmplY3RzIGluIHRoZSBwb3B1bGF0aW9uIGFyZSBleHBlY3RlZCB0byBoYXZlIGEgdmFsdWUgZm9yIHRoZSBjaGFyYWN0ZXJpc3RpYyB0aGF0IGZhbGxzIGludG8gdGhlIHJlZmVyZW5jZSBpbnRlcnZhbC4gCgotIFdlIGNhbiBkbyB0aGlzIGJhc2VkIG9uIHRoZSBlbXBpcmljYWwgZGlzdHJpYnV0aW9uIHVzaW5nIHRoZSBxdWFudGlsZSBmdW5jdGlvbi4gV2UgbmVlZCB0byBjYWxjdWxhdGUgdGhlIHF1YW50aWxlcyAkXGhhdHtGfSh4X3syLjVcJX0pPTAuMDI1JCBhbmQgJFxoYXR7Rn0oeF97OTcuNVwlfSk9MC45NzUkIHNvIHRoYXQgOTUlIG9mIHRoZSB2YWx1ZXMgYXJlIGxvY2F0ZWQgaW4gdGhlIGludGVydmFsIFt4X3syLjUlfSx4X3s5Ny41JX1dIC4gCgotIExhcmdlIHNhbXBsZQoKYGBge3J9CnF1YW50aWxlKGZlbSREaXJlY3RDaG9sLHByb2I9YygwLjAyNSwwLjk3NSkpCmBgYAoKLSBTbyBiYXNlZCBvbiB0aGUgbGFyZ2Ugc2FtcGxlLCB3ZSBlc3RpbWF0ZSB0aGF0IDk1JSBvZiB0aGUgZmVtYWxlcyBpbiB0aGUgcG9wdWxhdGlvbiBoYXZlIGEgZGlyZWN0IGNob2xlc3Rlcm9sIGxldmVsIGluIHRoZSBpbnRlcnZhbCBbYHIgcXVhbnRpbGUoZmVtJERpcmVjdENob2wscHJvYj1jKDAuMDI1LDAuOTc1KSlgXS4gCgotIFNtYWxsIHNhbXBsZQoKYGBge3J9CnF1YW50aWxlKGZlbTEwJERpcmVjdENob2wscHJvYj1jKDAuMDI1LDAuOTc1KSkKYGBgIAogICAgCi0gTm90ZSwgdGhhdCB0aGlzIGVzdGltYXRlIGlzIHZlcnkgY3J1ZGUuIEluIHRoZSBzbWFsbCBzYW1wbGUsICBXZSBkbyBub3QgaGF2ZSBlbm91Z2ggb2JzZXJ2YXRpb25zIHRvIGhhdmUgYSBnb29kIGFwcHJveGltYXRpb24gb2YgdGhlIGV4dHJlbWUgcXVhbnRpbGVzLiAKICAgIAojIyMgTm9ybWFsIGFwcHJveGltYXRpb24KCi0gV2UgY2FuIHVzZSB0aGUgZnVuY3Rpb24gcW5vcm0gdG8gY2FsY3VsYXRlIHF1YW50aWxlcyBmcm9tIHRoZSBub3JtYWwgZGlzdHJpYnV0aW9uLiAKCi0gV2UgYWxzbyBrbm93IHRoYXQgYSA5NSUgcmVmZXJlbmNlIGludGVydmFsIGlzIGxvY2F0ZWQgcm91Z2x5IGluIHR3byBzdGFuZGFyZCBkZXZpYXRpb25zIGFyb3VuZCB0aGUgbWVhbi4gCgotIFdlIHdpbGwgaGF2ZSB0byB1c2UgdGhlIGZ1bmN0aW9uIGAyXmAgdG8gdHJhbnNmb3JtIHRoZSByZXN1bHQgYmFjayB0byB0aGUgZGlyZWN0IGNob2xlc3Rlcm9sIGRvbWFpbi4gCgotIExhcmdlIHNhbXBsZQpgYGB7cn0KcW5vcm0oMC4wMjUsbWVhbj14QmFyLHNkPXNkQmFyKSAlPiUgLl4yCnFub3JtKDAuOTc1LG1lYW49eEJhcixzZD1zZEJhcikgJT4lIC5eMgoyXih4QmFyIC0gMiAqIHNkQmFyKQoyXih4QmFyICsgMiAqIHNkQmFyKQpgYGAKICAgICAgICAKLSBTbWFsbCBzYW1wbGUKYGBge3J9CnFub3JtKDAuMDI1LG1lYW49eEJhcjEwLHNkPXNkQmFyMTApICU+JSAuXjIKcW5vcm0oMC45NzUsbWVhbj14QmFyMTAsc2Q9c2RCYXIxMCkgJT4lIC5eMgoyXih4QmFyMTAgLSAyICogc2RCYXIxMCkKMl4oeEJhcjEwICsgMiAqIHNkQmFyMTApCmBgYAoKLS0tCgojIyBDb25jbHVzaW9ucyAKCi0gRm9yIHRoZSBsYXJnZSBzYW1wbGUsIHRoZSBlbXBpcmljYWwgZGlzdHJpYnV0aW9uIChxdWFudGlsZSBmdW5jdGlvbikgYW5kIHRoZSBub3JtYWwgYXBwcm94aW1hdGlvbiBnaXZlcyB1cyBhcHByb3hpbWF0ZWx5IHRoZSBzYW1lIHJlc3VsdC4KCi0gRm9yIHRoZSBzbWFsbCBzYW1wbGUsIGhvd2V2ZXIsIHRoZSBub3JtYWwgYXBwcm94aW1hdGlvbiB3b3JrcyBtdWNoIGJldHRlciB0aGFuIHRoZSBvbmUgYmFzZWQgb24gdGhlIGVtcGlyaWNhbCBkaXN0cmlidXRpb24uIAoKICAgIC0gVGhpcyBpcyBiZWNhdXNlIHdlIGFyZSBsb29raW5nIGF0IGV4dHJlbWUgcXVhbnRpbGVzIDIuNSUgYW5kIDk3LjUlLiAKICAgIC0gSW5kZWVkLCB3ZSBoYXZlIHZlcnkgZmV3IG9ic2VydmF0aW9ucyBhdCBvdXIgZGlzcG9zYWwgaW4gdGhlIHNtYWxsIHNhbXBsZSB0byBlc3RpbWF0ZSB0aGVzZSBxdWFudGlsZXMgZGlyZWN0bHkgZnJvbSB0aGUgb2JzZXJ2YXRpb25zLgogICAgLSBXaXRoIHRoZSBub3JtYWwgYXBwcm94aW1hdGlvbiB3ZSBjYW4gdXNlIGFsbCB0aGUgZGF0YSB0byBlc3RpbWF0ZSB0aGUgbWVhbiBhbmQgdGhlIHZhcmlhbmNlLiBTbyBpZiB0aGUgbm9ybWFsIGFzc3VtcHRpb24gaG9sZHMsIHdlIGdldCBiZXR0ZXIgZXN0aW1hdGVzIGZvciB0aGVzZSBleHRyZW1lIHF1YW50aWxlcy4gCgotLS0KCiMgU3RhdGlzdGljcwoKLSBGb3JtdWxhIHdpbGwgYmUgdXNlZCB0byBlc3RpbWF0ZSB0aGUgcGFyYW1ldGVycyBvZiBhIGRpc3RyaWJ1dGlvbiBpbiB0aGUgcG9wdWxhdGlvbiBiYXNlZCBvbiB0aGUgc2FtcGxlLiBXZSBjYWxsIHRoZXNlIHN0YXRpc3RpY3Mgb3IgZXN0aW1hdG9ycy4gCgotIFRoZSBudW1lcmljIHJlc3VsdCBvYnRhaW5lZCBieSBldmFsdWF0aW5nIHRoZXNlIGZvcm11bGEgYXJlIGFsc28gY2FsbGVkIHN0YXRpc3RpY3Mgb3IgZXN0aW1hdGVzLiAKCi0gUmVzZWFyY2hlciB3YW50IHRvIGtub3duIHRoZSB1bmtub3duIHBhcmFtZXRlcnMgZnJvbSB0aGUgcG9wdWxhdGlvbiBhbmQgd2lsbCB0aHVzIGVzdGltYXRlIHRoZW0gdXNpbmcgdGhlIHN0YXRpc3RpY3Mgb2JzZXJ2ZWQgb3IgY2FsY3VsYXRlZCBiYXNlZCBvbiB0aGUgc2FtcGxlIAoKLSBCZWNhdXNlIHdlIGNhbGN1bGF0ZSB0aGUgc3RhdGlzdGljcyBiYXNlZCBvbiB0aGUgb2JzZXJ2YXRpb25zIGluIHRoZSBzYW1wbGUsIHRoZXkgd2lsbCBhbHNvIHZhcnkgZnJvbSBzYW1wbGUgdG8gc2FtcGxlIGFuZCBhcmUgcmFuZG9tIHZhcmlhYmxlcyBhbmQgd2UgZGVub3RlIHRoZW0gd2l0aCBjYXBpdGFsIGxldHRlcnMgKGUuZy4gJFxiYXIgWCQgZm9yIHRoZSBzYW1wbGUgbWVhbiBhbmQgJFNeMiQgZm9yIHRoZSBzYW1wbGUgdmFyaWFuY2UpLiAKCi0gU28gd2hlbiB3ZSBhbmFseXNlIGRhdGEsIHdlIGhhdmUgdG8gcmVhc29uIG9uIGhvdyB0aGUgc3RhdGlzdGljcyBvZiBpbnRlcmVzdCB3aWxsIHZhcnkgZnJvbSBzYW1wbGUgdG8gc2FtcGxlLiAKCi0gV2hlbiB0aGUgc3RhdGlzdGljcyByZWZlciB0byBhIG51bWVyaWMgdmFsdWUgcmVhbGlzZWQgaW4gYSBwYXJ0aWN1bGFyIHNhbXBsZSwgd2Ugd2lsbCB1c2UgYSBzbWFsbCBsZXR0ZXI6ICRcYmFyIHgkIGFuZCAkc14yJC4KCi0tLQoKIyBDb252ZW50aW9uCgotICoqUG9wdWxhdGlvbiBwYXJhbWV0ZXJzKiogIGFyZSBmaXhlZCBidXQgdW5rbm93biBhbmQgd2Ugd2lsbCBkZW5vdGUgdGhlbSB3aXRoICRccmlnaHRhcnJvdyQgKipHcmVlayBzeW1ib2xzKiouCgotICoqU3RhdGlzdGljcyoqIHRoYXQgd2UgdXNlIHRvIGVzdGltYXRlIHVua25vd24gcGFyYW1ldGVycyBiYXNlZCBvbiB0aGUgc2FtcGxlIGFyZSBkZW5vdGVkIHdpdGggKipsZXR0ZXJzKiogYXJlIHdpdGggYSBoYXQuIAoKLSBlLmcuIGZvciBub3JtYWwgZGlzdHJpYnV0aW9uCgp8IFBvcHVsYXRpb24gfCBTYW1wbGV8CnwgOi0tLTogfCA6LS0tOiB8CnwgJFxtdSQgfCAkXGJhciBYJCBvciAkXGhhdCBcbXUkIHwKfCAkXHNpZ21hXjIkIHwgJFNeMiQgb3IgJFxoYXQgXHNpZ21hJHwKICAgICAgICAKICAgICAgCgotLS0KCiMgW0hvbWVdKGh0dHBzOi8vZ3RwYi5naXRodWIuaW8vUFNMUzIwLykgey19CiAgICAKICAgIAo=