
Motivating example (Brunner et al. 2022)

Brunner et al. 2022. Mol Syst Biol. 18(3): e10798. doi: 10.15252/msb.202110798
- Single cell study on 231 HeLa cells with drug induced cell cycle arrest for which over 2500 proteins where measured with MS-SCP.
- Authors report:
“The proteomes of the different cell cycle states grouped together in a principal component analysis (PCA) plot”.
“Our single‐cell data set also highlighted proteins not previously associated with the cell cycle and the G2/M transition”
Reanalysis of the results
We could reproduce the results:

Another way to look at the same plot

What happened
Confounding between acquisition batch and cell cycle arrest!!
To consult the statistician after an experiment is finished is often merely to ask him to conduct a post mortem examination. He can perhaps say what the experiment died of. – Ronald Fisher
Thinking about design before your experiment is key!!!!
Stages of an experiment

Stages
Define hypothesis
Experimental design
- Population
- Technology
- Lab protocol
- Think about sources of variation
- Choice of Design
- Experimental conditions
- Replicates
- How will we analyse the data
- How can we translate our research question in a quantity that we can measure
- Power analysis
Conduct experiment
Data Analysis
- QC
- Preprocessing & Data exploration
- Statistical inference
Optimisation of your experiment (go back to 2)
Validation
Report your results
Always good to discuss with statistician before the experiment!
Sources of variability
Experimental unit
- Animal, subject, plant, culture, cage to which the treatment is randomized
- Colony (B)
- Strain (B)
- Culture (B)
- Treatment / Condition of interest (B)
- Cage (T)
- Sex (B)
- Individual (B)
- Life style (B)
- …
Sample prep
- Organs from sacrificed animal (B)
- Single cells (B)
- Runs for Dissociation, Extraction and Digestion (T)
- Multipipet / pipeting robot (T)
- Plate (T)
- Position on plate (T)
Proteomics acquisition
- LC column (T)
- Run (T)
- Technical repeat (T)
- Labeling (T)
- Acquisition order
- …
Observational unit
- Unit on which the measurement is conducted
- Cell
- Cell bulk
- Animal
- If observational unit \(\neq\) experimental unit: pseudoreplication
Avoid confounding
- Random sampling & Randomisation
- Blocking
Random Sampling & Randomisation
Random Sampling
Random sampling is closely related to the concept of the population or the scope of the study.
Based on a sample of subjects, the researchers want to come to conclusions that hold for
- all kinds of people
- only male students
Scope of the study should be well specified before the start of the study.
Representative sample: For the statistical analysis to be valid, it is required that the subjects are selected completely at random from the population to which we want to generalize our conclusions.
Selecting completely at random from a population implies:
- all subjects in the population should have the same probability of being selected in the sample,
- the selection of a subject in the sample should be independent from the selection of the other subjects in the sample.
Randomisation
- Make sure that groups are comparable / Avoid systematic differences between groups
- Randomisation: treatments of interest are attributed at randam to the experimental units
Consequences of Random sampling & Randomisation
National Health NHanes study
- Since 1960 individuals of all ages are interviewed in their homes every year
- The health examination component of the survey is conducted in a mobile examination centre (MEC).
- We will use this large study to select random subjects from the American population.
- This will help us to understand how the results of an analysis and the conclusions vary from sample to sample.
nhanesSub <- NHANES %>%
filter(Age >= 18 & !is.na(Height)) %>%
select(c("Gender","Height"))
nhanesSub %>%
ggplot(aes(x = Height)) +
geom_histogram() +
facet_grid(Gender ~ .) +
xlab("Height (cm)")

female |
162.1 |
7.3 |
male |
175.9 |
7.5 |
- Data bell-shaped
- Allows us to summarize data with two statistics: mean and standard deviation
Unfortunately we cannot sample entire population!
We have to draw conclusions based on a small sample.
Experiment
- We can simulate an experiment on the American population by sampling from the NHANES study
- 5 males and 5 females above 18 years.
Note that the sample mean is different from that of the large experiment (“population”) we sampled from.
We test for the difference between Males and females
t.test(Height ~ Gender, samp, var.equal = TRUE)
Two Sample t-test
data: Height by Gender
t = -0.82599, df = 8, p-value = 0.4327
alternative hypothesis: true difference in means between group female and group male is not equal to 0
95 percent confidence interval:
-18.276478 8.636478
sample estimates:
mean in group female mean in group male
168.72 173.54
Repeat experiment
If we do the experiment again we select other people and we obtain different results.
Two Sample t-test
data: Height by Gender
t = -4.8876, df = 8, p-value = 0.001213
alternative hypothesis: true difference in means between group female and group male is not equal to 0
95 percent confidence interval:
-29.08282 -10.43718
sample estimates:
mean in group female mean in group male
158.04 177.80
And again
Two Sample t-test
data: Height by Gender
t = 3.1182, df = 8, p-value = 0.01427
alternative hypothesis: true difference in means between group female and group male is not equal to 0
95 percent confidence interval:
1.255452 8.384548
sample estimates:
mean in group female mean in group male
172.60 167.78
Summary
We drew at random different subjects in each sample
As a result, length measurements vary from sample to sample.
So do the estimated means and standard deviations.
Consequently, our conclusions are also uncertain and may change from sample to sample.
For the length example, samples where the effect is opposite to that in the population and where we decide that the difference is significant are rare.
\(\rightarrow\) With statistics, we control for the probability of drawing wrong conclusions.
Control of Decision Errors
We have two types of errors:
- false negatives: there is an effect but we do not pick it up
- false positives: there is no effect but we report a difference between both groups
Control of false negatives
- We repeat the experiment with 5 females and 5 males 10000 times.

$x
[1] ""
attr(,"class")
[1] "labels"

There are 7234 samples for which we return a true positive \(\rightarrow\) The power is 72.3%.
There are 2766 samples for which we cannot report a significant difference.
There are 0 for which we report a significant height difference between females and males that is positive.
The sample that we have shown where we concluded that females were larger than males was very unlikely. We had to draw 88605 samples before we were able to find such an extreme sample.
Why do we have a considerable number of samples for which we do not find a significant height difference between males and females?
Larger sample size
When we take 20 subjects in each group:

$x
[1] ""
attr(,"class")
[1] "labels"

Larger sample size:
- Larger power to pick up a real difference in the population.
- Mean is more precise

Control of false positives
Suppose that we set up an experiment with two groups that are both sampled from the females in the NHANES study
Both groups come from the same population: so no difference
We again draw repeated experiments with 5 subjects in each group.

$x
[1] ""
attr(,"class")
[1] "labels"

Only in 451 out of 10000 samples we conclude that the mean in both groups are different or in 4.5% of the samples.
With the statistical analysis we can control the number of false positive results correctly at the 5% significance level.
Larger sample size
We perform the simulations again with 20 subjects in each group.

$x
[1] ""
attr(,"class")
[1] "labels"

Only in 517 out of 10000 samples we conclude that the mean in both groups are different or in 5.2% of the samples.
So with the statistical analysis, also when taking a large sample, we correctly control the number of false positive results at 5%.
The mean difference is again more accurately estimated (fluctuating less around the real difference of 0).

Control treatment
Captopril study: SBP before and after dosign captopril.

Paired t-test
data: SBPa and SBPb
t = -8.1228, df = 14, p-value = 1.146e-06
alternative hypothesis: true mean difference is not equal to 0
95 percent confidence interval:
-23.93258 -13.93409
sample estimates:
mean difference
-18.93333
[1] 20.56511
[1] 20.00357
[1] 9.027471
pre-test/post-test experiment

Good control is nessecary
\(\rightarrow\) Placebo controlled double blind experiments
\(\rightarrow\) Injection of control animal with blank containing same solvents, etc.
Replication
Within an experiment: Enables to estimate uncertainty / biological variability
Between experiments: Any true finding should be reproducible
At which level do we have to replicate?
- Genuine replicates include all sources of variability: technical + biological
- Technical replicates are important if you assess new technologies

Francisella tularensis study Ramond et al. (2015)
- Proteome of wild type F. tularensis (WT) vs ArgP-gene deleted F. tularensis (knock-out, D8).
- Each bio-rep in technical triplicate on MS
- Illustration with 50S ribosomal proteïn L5 A0Q4J5

If we analyse original data with a t-test we act as if we would have 9 genuine repeats in each condition
Effect of interest between bio-reps so no block design
Same number of technical repeats for each genuine repeat we can first average over the techreps.
If that is not the case more complex data analysis methods have to be used, e.g. mixed models!
Caution: never average over genuine repeats/experimental units!!!
Correct analysis
lmBiorep <- lm(intensityLog2 ~ -1 + biorep, franc)
francSum <- data.frame(genotype = rep(c("D8","WT"),each=3) %>% as.factor %>% relevel("WT"), intensityLog2 = lmBiorep$coef)
francSum
t.test(intensityLog2 ~ genotype, francSum, var.equal=TRUE)
Two Sample t-test
data: intensityLog2 by genotype
t = 3.662, df = 4, p-value = 0.02154
alternative hypothesis: true difference in means between group WT and group D8 is not equal to 0
95 percent confidence interval:
0.05426166 0.39452610
sample estimates:
mean in group WT mean in group D8
27.58266 27.35826
Wrong analysis
Two Sample t-test
data: intensityLog2 by genotype
t = -4.5904, df = 16, p-value = 0.0003017
alternative hypothesis: true difference in means between group D8 and group WT is not equal to 0
95 percent confidence interval:
-0.3280223 -0.1207654
sample estimates:
mean in group D8 mean in group WT
27.35826 27.58266
- Result much more significant because we erroneously act as if we have a 9 by 9 comparison.
Simulation under \(H_0\)
- We use data to estimate variance components: technical and biological variance.
- We simulate 10000 experiments with similar design from a normal distribution under the assumption that group means are the same.
- We analyse them with both designs
Probability on a false positive when using a 5% significance level in
mean(resCorrect$pvalue < 0.05)
[1] 0.0452
mean(resWrong$pvalue < 0.05)
[1] 0.156
- We no-longer control the false positives at the \(\alpha = 5\)% level!
- We report to much false positives!
Implications of different technologies
Slide courtesy (Lisa Breckels)
Power analysis
- How many replicates do we need?
- Differs for different experimental designs
- Requires knowledge of total variability / magnitude of sources of variability
- Use literature or pilot experiment
- Can be done using simulations
Mouse example
In 2021 Choa et al. published that the cytokine Thymic stromal lymphopoietin (TSLP) induced fat loss through sebum secretion (talg). [html] [PDF]
Suppose that you would like to set up a similar study to test if cytokine interleukin 25 (IL) also has beneficial effect.
You plan to setup a study with a control group of high fat diet (HFD) fed mice and a treatment group that recieves the HFD and IL.
What sample size do you need to pick up the effect of the treatment.
How will we analyse the data of this experiment?
- Two groups: two sample t-test
\(H_0\): The average weight difference is equal to zero
\(H_1\): The average weight difference is different from zero
Power? Is design specific. For two-group comparison it depends on
- Real weight difference between the group means.
- Variability of the weight measurements
- Significance level \(\alpha\)
- Sample size in both groups
We can estimate the power if
- The assumptions of the model are met: weights are normally distributed with same variance
and we know
- Standard deviation of the weight measurements around their average mean for HFD-fed mice
- Real effect size in the population
- Sample sizes in each group
Use data from a previous experiment to get insight in mice data
- Suppose that we have access to the data of a preliminary experiment (e.g. provided by Karen Svenson via Gary Churchill and Dan Gatti and partially funded by P50 GM070683 on PH525x)

In the experiment we have data from two diets:
- Regular diet of cerial and grain based diet (Chow)
- High Fat (hf)
We can use the hf mice as input for our power analysis.
- The data of hf mice seem to be normally distributed
- The mean weight is 26.8g
- The SD of the weight is 4.1g
Effect size?
The alternative hypothesis is complex.
It includes all possible effects!
In order to do the power analysis we will have to choose a minimum effect size that we would like to detect.
Suppose that we would like to pick up a weight change of at least 10%.
delta <- abs(round(miceSum$mean[2] * .1, 1))
delta
[1] 2.7
Simulation based power analysis
We can use simulations to assess the power.
- E.g. for a 3 by 3 comparison where there is a weight difference of 3g.
- We simulate 3 observations from a normal with mean 26.8g and sd 4.1g and 3 observations from a normal with mean 29.8g and sd 4.1g.
- We perform a t-test and assess if we can conclude that there is a significant difference in the average weight between both groups based on this sample
- We repeat it many times and calculate the probability to find a significant difference.
We can repeat the same procedure for many different sample sizes…
We can also repeat that for different effect sizes

LS0tCnRpdGxlOiAiRXhwZXJpbWVudGFsIERlc2lnbiIKYXV0aG9yOiAiTGlldmVuIENsZW1lbnQiCmRhdGU6ICJbc3RhdE9taWNzXShodHRwczovL3N0YXRvbWljcy5naXRodWIuaW8pLCBHaGVudCBVbml2ZXJzaXR5IgpvdXRwdXQ6CiAgICBwZGZfZG9jdW1lbnQ6CiAgICAgIHRvYzogdHJ1ZQogICAgICBudW1iZXJfc2VjdGlvbnM6IHRydWUKICAgIGh0bWxfZG9jdW1lbnQ6CiAgICAgIGNvZGVfZG93bmxvYWQ6IHRydWUKICAgICAgdGhlbWU6IGZsYXRseQogICAgICB0b2M6IHRydWUKICAgICAgdG9jX2Zsb2F0OiB0cnVlCiAgICAgIGhpZ2hsaWdodDogdGFuZ28KICAgICAgbnVtYmVyX3NlY3Rpb25zOiB0cnVlCmxpbmtjb2xvcjogYmx1ZQp1cmxjb2xvcjogYmx1ZQpjaXRlY29sb3I6IGJsdWUKYmlibGlvZ3JhcGh5OiBtc3Fyb2IyLmJpYgogICAgICAKLS0tCgoKYGBge3Igc2V0dXAsIGluY2x1ZGU9RkFMU0UsIGNhY2hlPUZBTFNFfQprbml0cjo6b3B0c19jaHVuayRzZXQoCiAgaW5jbHVkZSA9IFRSVUUsIGNvbW1lbnQgPSBOQSwgZWNobyA9IFRSVUUsCiAgbWVzc2FnZSA9IEZBTFNFLCB3YXJuaW5nID0gRkFMU0UsIGNhY2hlID0gVFJVRQopCmxpYnJhcnkodGlkeXZlcnNlKQppZighcmVxdWlyZU5hbWVzcGFjZSgiTkhBTkVTIiwgcXVpZXRseSA9IFRSVUUpKSB7aW5zdGFsbC5wYWNrYWdlcygiTkhBTkVTIil9CmxpYnJhcnkoUmZhc3QpCmxpYnJhcnkoTkhBTkVTKQpsaWJyYXJ5KGdyaWRFeHRyYSkKYGBgCgo8YSByZWw9ImxpY2Vuc2UiIGhyZWY9Imh0dHBzOi8vY3JlYXRpdmVjb21tb25zLm9yZy9saWNlbnNlcy9ieS1uYy1zYS80LjAiPjxpbWcgYWx0PSJDcmVhdGl2ZSBDb21tb25zIExpY2Vuc2UiIHN0eWxlPSJib3JkZXItd2lkdGg6MCIgc3JjPSJodHRwczovL2kuY3JlYXRpdmVjb21tb25zLm9yZy9sL2J5LW5jLXNhLzQuMC84OHgzMS5wbmciIC8+PC9hPgoKIyBNb3RpdmF0aW5nIGV4YW1wbGUgKEJydW5uZXIgZXQgYWwuIDIwMjIpIAoKPGltZyBzcmM9Ii4vZmlndXJlcy9icnVubmVyMjAyMm1haW5GaWcuanBnIiB3aWR0aD0iMTAwJSI+CgpCcnVubmVyIGV0IGFsLiAyMDIyLiBNb2wgU3lzdCBCaW9sLiAxOCgzKTogZTEwNzk4LiBkb2k6IDEwLjE1MjUyL21zYi4yMDIxMTA3OTgKCi0gU2luZ2xlIGNlbGwgc3R1ZHkgb24gMjMxIEhlTGEgY2VsbHMgd2l0aCBkcnVnIGluZHVjZWQgY2VsbCBjeWNsZSBhcnJlc3QgZm9yIHdoaWNoIG92ZXIgMjUwMCBwcm90ZWlucyB3aGVyZSBtZWFzdXJlZCB3aXRoIE1TLVNDUC4gCi0gQXV0aG9ycyByZXBvcnQ6ICAKCiJUaGUgcHJvdGVvbWVzIG9mIHRoZSBkaWZmZXJlbnQgY2VsbCBjeWNsZSBzdGF0ZXMgZ3JvdXBlZCB0b2dldGhlciBpbiBhIHByaW5jaXBhbCBjb21wb25lbnQgYW5hbHlzaXMgKFBDQSkgcGxvdCIuIAoKIk91ciBzaW5nbGXigJBjZWxsIGRhdGEgc2V0IGFsc28gaGlnaGxpZ2h0ZWQgcHJvdGVpbnMgbm90IHByZXZpb3VzbHkgYXNzb2NpYXRlZCB3aXRoIHRoZSBjZWxsIGN5Y2xlIGFuZCB0aGUgRzIvTSB0cmFuc2l0aW9uIgoKIyMgUmVhbmFseXNpcyBvZiB0aGUgcmVzdWx0cwoKV2UgY291bGQgcmVwcm9kdWNlIHRoZSByZXN1bHRzOiAKCjxpbWcgc3JjPSIuL2ZpZ3VyZXMvYnJ1bm5lclBDQUNlbGxDeWNsZS5wbmciIHdpZHRoPSIxMDAlIj4KCkFub3RoZXIgd2F5IHRvIGxvb2sgYXQgdGhlIHNhbWUgcGxvdAoKPGltZyBzcmM9Ii4vZmlndXJlcy9icnVubmVyUENBQmF0Y2gucG5nIiB3aWR0aD0iMTAwJSI+Cgo8ZGV0YWlscz48c3VtbWFyeT4gV2hhdCBoYXBwZW5lZCA8L3N1bW1hcnk+PHA+CgpDb25mb3VuZGluZyBiZXR3ZWVuIGFjcXVpc2l0aW9uIGJhdGNoIGFuZCBjZWxsIGN5Y2xlIGFycmVzdCEhCgpUbyBjb25zdWx0IHRoZSBzdGF0aXN0aWNpYW4gYWZ0ZXIgYW4gZXhwZXJpbWVudCBpcyBmaW5pc2hlZCBpcyBvZnRlbiBtZXJlbHkgdG8gYXNrIGhpbSB0byBjb25kdWN0IGEgcG9zdCBtb3J0ZW0gZXhhbWluYXRpb24uIEhlIGNhbiBwZXJoYXBzIHNheSB3aGF0IHRoZSBleHBlcmltZW50IGRpZWQgb2YuIC0tIFJvbmFsZCBGaXNoZXIKCjwvcD48L2RldGFpbHM+CgoKVGhpbmtpbmcgYWJvdXQgZGVzaWduIGJlZm9yZSB5b3VyIGV4cGVyaW1lbnQgaXMga2V5ISEhIQoKIyBTdGFnZXMgb2YgYW4gZXhwZXJpbWVudAoKYGBge3Igb3V0LndpZHRoPSc4MCUnLGZpZy5hc3A9LjgsIGZpZy5hbGlnbj0nY2VudGVyJyxlY2hvID0gRkFMU0UsIHdhcm5pbmcgPSBGQUxTRSwgbWVzc2FnZSA9IEZBTFNFfQppZiAoInBpIiAlaW4lIGxzKCkpIHJtKCJwaSIpCmtvcHZvZXRlciA8LSBmdW5jdGlvbih4LCB5LCBhbmdsZSA9IDAsIGwgPSAuMiwgY2V4LmRvdCA9IC41LCBwY2ggPSAxOSwgY29sID0gImJsYWNrIikgewogIGFuZ2xlIDwtIGFuZ2xlIC8gMTgwICogcGkKICBwb2ludHMoeCwgeSwgY2V4ID0gY2V4LmRvdCwgcGNoID0gcGNoLCBjb2wgPSBjb2wpCiAgbGluZXMoYyh4LCB4ICsgbCAqIGNvcygtcGkgLyAyICsgYW5nbGUpKSwgYyh5LCB5ICsgbCAqIHNpbigtcGkgLyAyICsgYW5nbGUpKSwgY29sID0gY29sKQogIGxpbmVzKGMoeCArIGwgLyAyICogY29zKC1waSAvIDIgKyBhbmdsZSksIHggKyBsIC8gMiAqIGNvcygtcGkgLyAyICsgYW5nbGUpICsgbCAvIDQgKiBjb3MoYW5nbGUpKSwgYyh5ICsgbCAvIDIgKiBzaW4oLXBpIC8gMiArIGFuZ2xlKSwgeSArIGwgLyAyICogc2luKC1waSAvIDIgKyBhbmdsZSkgKyBsIC8gNCAqIHNpbihhbmdsZSkpLCBjb2wgPSBjb2wpCiAgbGluZXMoYyh4ICsgbCAvIDIgKiBjb3MoLXBpIC8gMiArIGFuZ2xlKSwgeCArIGwgLyAyICogY29zKC1waSAvIDIgKyBhbmdsZSkgKyBsIC8gNCAqIGNvcyhwaSArIGFuZ2xlKSksIGMoeSArIGwgLyAyICogc2luKC1waSAvIDIgKyBhbmdsZSksIHkgKyBsIC8gMiAqIHNpbigtcGkgLyAyICsgYW5nbGUpICsgbCAvIDQgKiBzaW4ocGkgKyBhbmdsZSkpLCBjb2wgPSBjb2wpCiAgbGluZXMoYyh4ICsgbCAqIGNvcygtcGkgLyAyICsgYW5nbGUpLCB4ICsgbCAqIGNvcygtcGkgLyAyICsgYW5nbGUpICsgbCAvIDIgKiBjb3MoLXBpIC8gMiArIHBpIC8gNCArIGFuZ2xlKSksIGMoeSArIGwgKiBzaW4oLXBpIC8gMiArIGFuZ2xlKSwgeSArIGwgKiBzaW4oLXBpIC8gMiArIGFuZ2xlKSArIGwgLyAyICogc2luKC1waSAvIDIgKyBwaSAvIDQgKyBhbmdsZSkpLCBjb2wgPSBjb2wpCiAgbGluZXMoYyh4ICsgbCAqIGNvcygtcGkgLyAyICsgYW5nbGUpLCB4ICsgbCAqIGNvcygtcGkgLyAyICsgYW5nbGUpICsgbCAvIDIgKiBjb3MoLXBpIC8gMiAtIHBpIC8gNCArIGFuZ2xlKSksIGMoeSArIGwgKiBzaW4oLXBpIC8gMiArIGFuZ2xlKSwgeSArIGwgKiBzaW4oLXBpIC8gMiArIGFuZ2xlKSArIGwgLyAyICogc2luKC1waSAvIDIgLSBwaSAvIDQgKyBhbmdsZSkpLCBjb2wgPSBjb2wpCn0KCnBhcihtYXIgPSBjKDAsIDAsIDAsIDApLCBtYWkgPSBjKDAsIDAsIDAsIDApKQpwbG90KDAsIDAsIHhsYWIgPSAiIiwgeWxhYiA9ICIiLCB4bGltID0gYygwLCAxMCksIHlsaW0gPSBjKDAsIDEwKSwgY29sID0gMCwgeGF4dCA9ICJub25lIiwgeWF4dCA9ICJub25lIiwgYXhlcyA9IEZBTFNFKQpyZWN0KDAsIDYsIDEwLCAxMCwgYm9yZGVyID0gInJlZCIsIGx3ZCA9IDIpCnRleHQoLjUsIDgsICJwb3B1bGF0aW9uIiwgc3J0ID0gOTAsIGNvbCA9ICJyZWQiLCBjZXggPSAyKQpzeW1ib2xzKDMsIDgsIGNpcmNsZXMgPSAxLjUsIGNvbCA9ICJyZWQiLCBhZGQgPSBUUlVFLCBmZyA9ICJyZWQiLCBpbmNoZXMgPSBGQUxTRSwgbHdkID0gMikKc2V0LnNlZWQoMzMwKQpncmlkIDwtIHNlcSgwLCAxLjMsIC4wMSkKCmZvciAoaSBpbiAxOjUwKQp7CiAgYW5nbGUxIDwtIHJ1bmlmKG4gPSAxLCBtaW4gPSAwLCBtYXggPSAzNjApCiAgYW5nbGUyIDwtIHJ1bmlmKG4gPSAxLCBtaW4gPSAwLCBtYXggPSAzNjApCiAgcmFkaXVzIDwtIHNhbXBsZShncmlkLCBwcm9iID0gZ3JpZF4yICogcGkgLyBzdW0oZ3JpZF4yICogcGkpLCBzaXplID0gMSkKICBrb3B2b2V0ZXIoMyArIHJhZGl1cyAqIGNvcyhhbmdsZTEgLyAxODAgKiBwaSksIDggKyByYWRpdXMgKiBzaW4oYW5nbGUxIC8gMTgwICogcGkpLCBhbmdsZSA9IGFuZ2xlMikKfQp0ZXh0KDcuNSwgOCwgIkVmZmVjdCBvZiBkcnVnIG9uIFxuIHByb3Rlb21lIGluIHBvcHVsYXRpb24iLCBjb2wgPSAicmVkIiwgY2V4ID0gMS4yKQoKcmVjdCgwLCAwLCAxMCwgNCwgYm9yZGVyID0gImJsdWUiLCBsd2QgPSAyKQp0ZXh0KC41LCAyLCAic2FtcGxlIiwgc3J0ID0gOTAsIGNvbCA9ICJibHVlIiwgY2V4ID0gMikKc3ltYm9scygzLCAyLCBjaXJjbGVzID0gMS41LCBjb2wgPSAicmVkIiwgYWRkID0gVFJVRSwgZmcgPSAiYmx1ZSIsIGluY2hlcyA9IEZBTFNFLCBsd2QgPSAyKQpmb3IgKGkgaW4gMDoxKSB7CiAgZm9yIChqIGluIDA6NCkKICB7CiAgICBrb3B2b2V0ZXIoMi4xICsgaiAqICgzLjkgLSAyLjEpIC8gNCwgMS4xICsgaSAvIDIsIGNvbCA9ICJwdXJwbGUiKQogIH0KfQpmb3IgKGkgaW4gMjozKSB7CiAgZm9yIChqIGluIDA6NCkKICB7CiAgICBrb3B2b2V0ZXIoMi4xICsgaiAqICgzLjkgLSAyLjEpIC8gNCwgMS42ICsgaSAvIDIsIGNvbCA9ICJvcmFuZ2UiKQogIH0KfQp0ZXh0KDcuNSwgMiwgIkVmZmVjdCBvZiBkcnVnIG9uIFxuIHByb3Rlb21lIGluIHNhbXBsZSIsIGNvbCA9ICJibHVlIiwgY2V4ID0gMS4yKQoKYXJyb3dzKDMsIDUuOSwgMywgNC4xLCBjb2wgPSAiYmxhY2siLCBsd2QgPSAzKQp0ZXh0KDEuNSwgNSwgIkVYUC4gREVTSUdOICgxKSIsIGNvbCA9ICJibGFjayIsIGNleCA9IDEuMikKdGV4dCg3LjUsIC41LCAiREFUQSBFWFBMT1JBVElPTiAmXG5ERVNDUklQVElWRSBTVEFUSVNUSUNTICgyKSIsIGNvbCA9ICJibGFjayIsIGNleCA9IDEuMikKYXJyb3dzKDcsIDQuMSwgNywgNS45LCBjb2wgPSAiYmxhY2siLCBsd2QgPSAzKQp0ZXh0KDguNSwgNSwgIkVTVElNQVRJT04gJlxuSU5GRVJFTkNFICgzKSIsIGNvbCA9ICJibGFjayIsIGNleCA9IDEuMikKYGBgCgojIyBTdGFnZXMgCgoxLiBEZWZpbmUgaHlwb3RoZXNpcwoyLiBFeHBlcmltZW50YWwgZGVzaWduCiAgCiAgICAtIFBvcHVsYXRpb24KICAgIC0gVGVjaG5vbG9neQogICAgLSBMYWIgcHJvdG9jb2wKICAgIC0gVGhpbmsgYWJvdXQgc291cmNlcyBvZiB2YXJpYXRpb24gCiAgICAtIENob2ljZSBvZiBEZXNpZ24KICAgIC0gRXhwZXJpbWVudGFsIGNvbmRpdGlvbnMKICAgIC0gUmVwbGljYXRlcwogICAgLSBIb3cgd2lsbCB3ZSBhbmFseXNlIHRoZSBkYXRhCiAgICAtIEhvdyBjYW4gd2UgdHJhbnNsYXRlIG91ciByZXNlYXJjaCBxdWVzdGlvbiBpbiBhIHF1YW50aXR5IHRoYXQgd2UgY2FuIG1lYXN1cmUgCiAgICAtIFBvd2VyIGFuYWx5c2lzCiAgCjMuIENvbmR1Y3QgZXhwZXJpbWVudAo0LiBEYXRhIEFuYWx5c2lzCgogICAgLSBRQwogICAgLSBQcmVwcm9jZXNzaW5nICYgRGF0YSBleHBsb3JhdGlvbgogICAgLSBTdGF0aXN0aWNhbCBpbmZlcmVuY2UKICAgIAo1LiBPcHRpbWlzYXRpb24gb2YgeW91ciBleHBlcmltZW50IChnbyBiYWNrIHRvIDIpCjYuIFZhbGlkYXRpb24KNy4gUmVwb3J0IHlvdXIgcmVzdWx0cwoKQWx3YXlzIGdvb2QgdG8gZGlzY3VzcyB3aXRoIHN0YXRpc3RpY2lhbiBiZWZvcmUgdGhlIGV4cGVyaW1lbnQhIAoKCiMgU291cmNlcyBvZiB2YXJpYWJpbGl0eSAKCiMjIEV4cGVyaW1lbnRhbCB1bml0IAoKLSBBbmltYWwsIHN1YmplY3QsIHBsYW50LCBjdWx0dXJlLCBjYWdlIHRvIHdoaWNoIHRoZSB0cmVhdG1lbnQgaXMgcmFuZG9taXplZAotIENvbG9ueSAoQikKLSBTdHJhaW4gKEIpCi0gQ3VsdHVyZSAoQikKLSBUcmVhdG1lbnQgLyBDb25kaXRpb24gb2YgaW50ZXJlc3QgKEIpCi0gQ2FnZSAoVCkKLSBTZXggKEIpCi0gSW5kaXZpZHVhbCAoQikKLSBMaWZlIHN0eWxlIChCKQotIC4uLgoKCiMjIFNhbXBsZSBwcmVwIAoKLSBPcmdhbnMgZnJvbSBzYWNyaWZpY2VkIGFuaW1hbCAoQikKLSBTaW5nbGUgY2VsbHMgKEIpCi0gUnVucyBmb3IgRGlzc29jaWF0aW9uLCBFeHRyYWN0aW9uIGFuZCBEaWdlc3Rpb24gKFQpIAotIE11bHRpcGlwZXQgLyBwaXBldGluZyByb2JvdCAoVCkKLSBQbGF0ZSAoVCkKLSBQb3NpdGlvbiBvbiBwbGF0ZSAoVCkKCiMjIFByb3Rlb21pY3MgYWNxdWlzaXRpb24KCi0gTEMgY29sdW1uIChUKQotIFJ1biAoVCkKLSBUZWNobmljYWwgcmVwZWF0IChUKQotIExhYmVsaW5nIChUKQotIEFjcXVpc2l0aW9uIG9yZGVyCi0gLi4uCgojIyBPYnNlcnZhdGlvbmFsIHVuaXQKCi0gVW5pdCBvbiB3aGljaCB0aGUgbWVhc3VyZW1lbnQgaXMgY29uZHVjdGVkIAotIENlbGwKLSBDZWxsIGJ1bGsKLSBBbmltYWwgCi0gSWYgb2JzZXJ2YXRpb25hbCB1bml0ICRcbmVxJCBleHBlcmltZW50YWwgdW5pdDogcHNldWRvcmVwbGljYXRpb24KCiMjIEF2b2lkIGNvbmZvdW5kaW5nCgotIFJhbmRvbSBzYW1wbGluZyAmIFJhbmRvbWlzYXRpb24gCi0gQmxvY2tpbmcKCgojIFJhbmRvbSBTYW1wbGluZyAmIFJhbmRvbWlzYXRpb24KCiMjIFJhbmRvbSBTYW1wbGluZwoKLSBSYW5kb20gc2FtcGxpbmcgaXMgY2xvc2VseSByZWxhdGVkIHRvIHRoZSBjb25jZXB0IG9mIHRoZSBwb3B1bGF0aW9uIG9yIHRoZSBzY29wZSBvZiB0aGUgc3R1ZHkuCgotIEJhc2VkIG9uIGEgc2FtcGxlIG9mIHN1YmplY3RzLCB0aGUgcmVzZWFyY2hlcnMgd2FudCB0byBjb21lIHRvIGNvbmNsdXNpb25zIHRoYXQgaG9sZCBmb3IKCiAgICAtIGFsbCBraW5kcyBvZiBwZW9wbGUKICAgIC0gb25seSBtYWxlIHN0dWRlbnRzCgotIFNjb3BlIG9mIHRoZSBzdHVkeSBzaG91bGQgYmUgd2VsbCBzcGVjaWZpZWQgYmVmb3JlIHRoZSBzdGFydCBvZiB0aGUgc3R1ZHkuCgotIFJlcHJlc2VudGF0aXZlIHNhbXBsZTogRm9yIHRoZSBzdGF0aXN0aWNhbCBhbmFseXNpcyB0byBiZSB2YWxpZCwgaXQgaXMgcmVxdWlyZWQgdGhhdCB0aGUgc3ViamVjdHMgYXJlIHNlbGVjdGVkIGNvbXBsZXRlbHkgYXQgcmFuZG9tIGZyb20gdGhlIHBvcHVsYXRpb24gdG8gd2hpY2ggd2Ugd2FudCB0byBnZW5lcmFsaXplIG91ciBjb25jbHVzaW9ucy4KCi0gU2VsZWN0aW5nIGNvbXBsZXRlbHkgYXQgcmFuZG9tIGZyb20gYSBwb3B1bGF0aW9uIGltcGxpZXM6CiAgICAtIGFsbCBzdWJqZWN0cyBpbiB0aGUgcG9wdWxhdGlvbiBzaG91bGQgaGF2ZSB0aGUgc2FtZSBwcm9iYWJpbGl0eSBvZiBiZWluZyBzZWxlY3RlZCBpbiB0aGUgc2FtcGxlLAogICAgLSB0aGUgc2VsZWN0aW9uIG9mIGEgc3ViamVjdCBpbiB0aGUgc2FtcGxlIHNob3VsZCBiZSBpbmRlcGVuZGVudCBmcm9tIHRoZSBzZWxlY3Rpb24gb2YgdGhlIG90aGVyIHN1YmplY3RzIGluIHRoZSBzYW1wbGUuCgojIyBSYW5kb21pc2F0aW9uIAoKLSBNYWtlIHN1cmUgdGhhdCBncm91cHMgYXJlIGNvbXBhcmFibGUgLyBBdm9pZCBzeXN0ZW1hdGljIGRpZmZlcmVuY2VzIGJldHdlZW4gZ3JvdXBzCi0gUmFuZG9taXNhdGlvbjogdHJlYXRtZW50cyBvZiBpbnRlcmVzdCBhcmUgYXR0cmlidXRlZCBhdCByYW5kYW0gdG8gdGhlIGV4cGVyaW1lbnRhbCB1bml0cwoKIyMgQ29uc2VxdWVuY2VzIG9mIFJhbmRvbSBzYW1wbGluZyAmIFJhbmRvbWlzYXRpb24gCgotIFRoZSBzYW1wbGUgaXMgdGh1cyBzdXBwb3NlZCB0byBiZSByZXByZXNlbnRhdGl2ZSBmb3IgdGhlIHBvcHVsYXRpb24sIGJ1dCBzdGlsbCBpdCBpcyByYW5kb20uCgotIFdoYXQgZG9lcyB0aGlzIGltcGx5PwoKCgojIyMgTmF0aW9uYWwgSGVhbHRoIE5IYW5lcyBzdHVkeQoKICAtIFNpbmNlIDE5NjAgaW5kaXZpZHVhbHMgb2YgYWxsIGFnZXMgYXJlIGludGVydmlld2VkIGluIHRoZWlyIGhvbWVzIGV2ZXJ5IHllYXIKICAtIFRoZSBoZWFsdGggZXhhbWluYXRpb24gY29tcG9uZW50IG9mIHRoZSBzdXJ2ZXkgaXMgY29uZHVjdGVkIGluIGEgbW9iaWxlIGV4YW1pbmF0aW9uIGNlbnRyZSAoTUVDKS4KICAtIFdlIHdpbGwgdXNlIHRoaXMgbGFyZ2Ugc3R1ZHkgdG8gc2VsZWN0IHJhbmRvbSBzdWJqZWN0cyBmcm9tIHRoZSBBbWVyaWNhbiBwb3B1bGF0aW9uLgogIC0gVGhpcyB3aWxsIGhlbHAgdXMgdG8gdW5kZXJzdGFuZCBob3cgdGhlIHJlc3VsdHMgb2YgYW4gYW5hbHlzaXMgYW5kIHRoZSBjb25jbHVzaW9ucyB2YXJ5IGZyb20gc2FtcGxlIHRvIHNhbXBsZS4KCmBgYHtyfQpuaGFuZXNTdWIgPC0gTkhBTkVTICU+JQogIGZpbHRlcihBZ2UgPj0gMTggJiAhaXMubmEoSGVpZ2h0KSkgJT4lCiAgc2VsZWN0KGMoIkdlbmRlciIsIkhlaWdodCIpKQoKbmhhbmVzU3ViICU+JSAKICBnZ3Bsb3QoYWVzKHggPSBIZWlnaHQpKSArCiAgZ2VvbV9oaXN0b2dyYW0oKSArCiAgZmFjZXRfZ3JpZChHZW5kZXIgfiAuKSArCiAgeGxhYigiSGVpZ2h0IChjbSkiKQpgYGAKCmBgYHtyIGVjaG8gPSBGQUxTRSwgd2FybmluZyA9IEZBTFNFLCBtZXNzYWdlID0gRkFMU0V9CkhlaWdodFN1bSA8LSBuaGFuZXNTdWIgJT4lCiAgZ3JvdXBfYnkoR2VuZGVyKSAlPiUKICBzdW1tYXJpemVfYXQoIkhlaWdodCIsCiAgICAgICAgICAgICAgIGxpc3QobWVhbiA9IG1lYW4sCiAgICAgICAgICAgICAgIHNkID0gc2QpCiAgICAgICAgICAgICAgKQoKa25pdHI6OmthYmxlKAogIEhlaWdodFN1bSAlPiUKICBtdXRhdGVfaWYoaXMubnVtZXJpYywgcm91bmQsIGRpZ2l0cz0xKQogICkKYGBgCgoKLSBEYXRhIGJlbGwtc2hhcGVkIAotIEFsbG93cyB1cyB0byBzdW1tYXJpemUgZGF0YSB3aXRoIHR3byBzdGF0aXN0aWNzOiBtZWFuIGFuZCBzdGFuZGFyZCBkZXZpYXRpb24gCgpVbmZvcnR1bmF0ZWx5IHdlIGNhbm5vdCBzYW1wbGUgZW50aXJlIHBvcHVsYXRpb24hCldlIGhhdmUgdG8gZHJhdyBjb25jbHVzaW9ucyBiYXNlZCBvbiBhIHNtYWxsIHNhbXBsZS4gCgoKCiMjIyBFeHBlcmltZW50IAoKCi0gV2UgY2FuIHNpbXVsYXRlIGFuIGV4cGVyaW1lbnQgb24gdGhlIEFtZXJpY2FuIHBvcHVsYXRpb24gYnkgc2FtcGxpbmcgZnJvbSB0aGUgTkhBTkVTIHN0dWR5IAotIDUgbWFsZXMgYW5kIDUgZmVtYWxlcyBhYm92ZSAxOCB5ZWFycy4gCgoKCmBgYHtyIGVjaG8gPSBGQUxTRSwgd2FybmluZyA9IEZBTFNFLCBtZXNzYWdlID0gRkFMU0V9CnNldC5zZWVkKDIwMCkKZmVtIDwtIG5oYW5lc1N1YiAlPiUKICBmaWx0ZXIoR2VuZGVyID09ICJmZW1hbGUiKSAlPiUKICBzYW1wbGVfbihzaXplID0gNSkKbWFsIDwtIG5oYW5lc1N1YiAlPiUKICBmaWx0ZXIoR2VuZGVyID09ICJtYWxlIikgJT4lCiAgc2FtcGxlX24oc2l6ZSA9IDUpCgpzYW1wIDwtIHJiaW5kKGZlbSwgbWFsKQoKc2FtcCAlPiUKICBnZ3Bsb3QoYWVzKHggPSBHZW5kZXIsIHkgPSBIZWlnaHQpKSArCiAgZ2VvbV9ib3hwbG90KG91dGxpZXIuc2hhcGUgPSBOQSkgKwogIGdlb21fcG9pbnQocG9zaXRpb24gPSAiaml0dGVyIikKCnNhbXAgJT4lCiAgZ3JvdXBfYnkoR2VuZGVyKSAlPiUKICBzdW1tYXJpemUoCiAgICBtZWFuID0gbWVhbihIZWlnaHQsIG5hLnJtID0gVFJVRSksCiAgICBzZCA9IHNkKEhlaWdodCwgbmEucm0gPSBUUlVFKSwKICAgIG4gPSBuKCkKICApICU+JQogIG11dGF0ZShzZSA9IHNkIC8gc3FydChuKSkKYGBgCgpOb3RlIHRoYXQgdGhlIHNhbXBsZSBtZWFuIGlzIGRpZmZlcmVudCBmcm9tIHRoYXQgb2YgdGhlIGxhcmdlIGV4cGVyaW1lbnQgKCJwb3B1bGF0aW9uIikgd2Ugc2FtcGxlZCBmcm9tLgoKV2UgdGVzdCBmb3IgdGhlIGRpZmZlcmVuY2UgYmV0d2VlbiBNYWxlcyBhbmQgZmVtYWxlcwoKYGBge3J9CnQudGVzdChIZWlnaHQgfiBHZW5kZXIsIHNhbXAsIHZhci5lcXVhbCA9IFRSVUUpCmBgYAoKIyMjIFJlcGVhdCBleHBlcmltZW50IAoKSWYgd2UgZG8gdGhlIGV4cGVyaW1lbnQgYWdhaW4gd2Ugc2VsZWN0IG90aGVyIHBlb3BsZSBhbmQgd2Ugb2J0YWluIGRpZmZlcmVudCByZXN1bHRzLgoKCmBgYHtyIGVjaG8gPSBGQUxTRSwgd2FybmluZyA9IEZBTFNFLCBtZXNzYWdlID0gRkFMU0V9CgpmZW0gPC0gbmhhbmVzU3ViICU+JQogIGZpbHRlcihHZW5kZXIgPT0gImZlbWFsZSIpICU+JQogIHNhbXBsZV9uKHNpemUgPSA1KQptYWwgPC0gbmhhbmVzU3ViICU+JQogIGZpbHRlcihHZW5kZXIgPT0gIm1hbGUiKSAlPiUKICBzYW1wbGVfbihzaXplID0gNSkKCnNhbXAgPC0gcmJpbmQoZmVtLCBtYWwpCgoKc2FtcCAlPiUKICBnZ3Bsb3QoYWVzKHggPSBHZW5kZXIsIHkgPSBIZWlnaHQpKSArCiAgZ2VvbV9ib3hwbG90KG91dGxpZXIuc2hhcGUgPSBOQSkgKwogIGdlb21fcG9pbnQocG9zaXRpb24gPSAiaml0dGVyIikKCnNhbXAgJT4lCiAgZ3JvdXBfYnkoR2VuZGVyKSAlPiUKICBzdW1tYXJpemUoCiAgICBtZWFuID0gbWVhbihIZWlnaHQsIG5hLnJtID0gVFJVRSksCiAgICBzZCA9IHNkKEhlaWdodCwgbmEucm0gPSBUUlVFKSwKICAgIG4gPSBuKCkKICApICU+JQogIG11dGF0ZShzZSA9IHNkIC8gc3FydChuKSkKCnQudGVzdChIZWlnaHQgfiBHZW5kZXIsIHNhbXAsIHZhci5lcXVhbCA9IFRSVUUpCmBgYAoKIyMjIEFuZCBhZ2FpbiAKCgpgYGB7ciBlY2hvID0gRkFMU0UsIHdhcm5pbmcgPSBGQUxTRSwgbWVzc2FnZSA9IEZBTFNFfQpzZWVkIDwtIDg4NjA1CnNldC5zZWVkKHNlZWQpCmZlbSA8LSBuaGFuZXNTdWIgJT4lCiAgZmlsdGVyKEdlbmRlciA9PSAiZmVtYWxlIikgJT4lCiAgc2FtcGxlX24oc2l6ZSA9IDUpCm1hbCA8LSBuaGFuZXNTdWIgJT4lCiAgZmlsdGVyKEdlbmRlciA9PSAibWFsZSIpICU+JQogIHNhbXBsZV9uKHNpemUgPSA1KQoKc2FtcCA8LSByYmluZChmZW0sIG1hbCkKCgpzYW1wICU+JQogIGdncGxvdChhZXMoeCA9IEdlbmRlciwgeSA9IEhlaWdodCkpICsKICBnZW9tX2JveHBsb3Qob3V0bGllci5zaGFwZSA9IE5BKSArCiAgZ2VvbV9wb2ludChwb3NpdGlvbiA9ICJqaXR0ZXIiKQoKc2FtcCAlPiUKICBncm91cF9ieShHZW5kZXIpICU+JQogIHN1bW1hcml6ZSgKICAgIG1lYW4gPSBtZWFuKEhlaWdodCwgbmEucm0gPSBUUlVFKSwKICAgIHNkID0gc2QoSGVpZ2h0LCBuYS5ybSA9IFRSVUUpLAogICAgbiA9IG4oKQogICkgJT4lCiAgbXV0YXRlKHNlID0gc2QgLyBzcXJ0KG4pKQoKdC50ZXN0KEhlaWdodCB+IEdlbmRlciwgc2FtcCwgdmFyLmVxdWFsID0gVFJVRSkKYGBgCgoKIyMgU3VtbWFyeQoKLSBXZSBkcmV3IGF0IHJhbmRvbSBkaWZmZXJlbnQgc3ViamVjdHMgaW4gZWFjaCBzYW1wbGUKLSBBcyBhIHJlc3VsdCwgbGVuZ3RoIG1lYXN1cmVtZW50cyB2YXJ5IGZyb20gc2FtcGxlIHRvIHNhbXBsZS4KLSBTbyBkbyB0aGUgZXN0aW1hdGVkIG1lYW5zIGFuZCBzdGFuZGFyZCBkZXZpYXRpb25zLgotIENvbnNlcXVlbnRseSwgb3VyIGNvbmNsdXNpb25zIGFyZSBhbHNvIHVuY2VydGFpbiBhbmQgbWF5IGNoYW5nZSBmcm9tIHNhbXBsZSB0byBzYW1wbGUuCgotIEZvciB0aGUgbGVuZ3RoIGV4YW1wbGUsIHNhbXBsZXMgd2hlcmUgdGhlIGVmZmVjdCBpcyBvcHBvc2l0ZSB0byB0aGF0IGluIHRoZSBwb3B1bGF0aW9uIGFuZCB3aGVyZSB3ZSBkZWNpZGUgdGhhdCB0aGUgZGlmZmVyZW5jZSBpcyBzaWduaWZpY2FudCBhcmUgcmFyZS4KCiRccmlnaHRhcnJvdyQgV2l0aCBzdGF0aXN0aWNzLCB3ZSBjb250cm9sIGZvciB0aGUgcHJvYmFiaWxpdHkgb2YgZHJhd2luZyB3cm9uZyBjb25jbHVzaW9ucy4KCgojIENvbnRyb2wgb2YgRGVjaXNpb24gRXJyb3JzIAoKV2UgaGF2ZSB0d28gdHlwZXMgb2YgZXJyb3JzOiAKCi0gZmFsc2UgbmVnYXRpdmVzOiB0aGVyZSBpcyBhbiBlZmZlY3QgYnV0IHdlIGRvIG5vdCBwaWNrIGl0IHVwCi0gZmFsc2UgcG9zaXRpdmVzOiB0aGVyZSBpcyBubyBlZmZlY3QgYnV0IHdlIHJlcG9ydCBhIGRpZmZlcmVuY2UgYmV0d2VlbiBib3RoIGdyb3VwcwoKIyMgQ29udHJvbCBvZiBmYWxzZSBuZWdhdGl2ZXMKCgotIFdlIHJlcGVhdCB0aGUgZXhwZXJpbWVudCB3aXRoIDUgZmVtYWxlcyBhbmQgNSBtYWxlcyAxMDAwMCB0aW1lcy4gCgpgYGB7ciBlY2hvID1GQUxTRX0Kc2V0LnNlZWQoMTUxNTIpCiMgQWFudGFsIHNpbXVsYXRpZXMgZW4gc3RlZWtwcm9lZmdyb290dGUgcGVyIGdyb2VwCm5TaW0gPC0gMTAwMDAKblNhbXAgPC0gNQoKIyBXZSBmaWx0ZXJlbiBkZSBkYXRhIHZvb3JhZiB6b2RhdCB3ZSBkaXQgbmlldCB0ZWxrZW5zIG9wbmlldXcgaG9ldmVuIHRlIGRvZW4KZmVtIDwtIG5oYW5lc1N1YiAlPiUKICBmaWx0ZXIoR2VuZGVyID09ICJmZW1hbGUiKQoKbWFsIDwtIG5oYW5lc1N1YiAlPiUKICBmaWx0ZXIoR2VuZGVyID09ICJtYWxlIikKCiMgU2ltdWxhdGllIHN0dWRpZQojIE9tIHNuZWxsZSBmdW5jdGllcyB0ZSBrdW5uZW4gZ2VicnVpa2VuIG5lbWVuIHdlIGVlcnN0IG5TaW0gc3RlZWtwcm9ldmVuIGVuIGJlcmVrZW5lbiB3ZSBkYWFybmEgYWxsZXMuCgpmZW1TYW1wcyA8LSBtYWxTYW1wcyA8LW1hdHJpeChOQSwgbnJvdz1uU2FtcCwgbmNvbD1uU2ltKQpmb3IgKGkgaW4gMTpuU2ltKQp7CiAgZmVtU2FtcHNbLGldIDwtIHNhbXBsZShmZW0kSGVpZ2h0LCBuU2FtcCkKICBtYWxTYW1wc1ssaV0gPC0gc2FtcGxlKG1hbCRIZWlnaHQsIG5TYW1wKQp9CgpyZXMgPC0gZGF0YS5mcmFtZSgKICB2ZXJzY2hpbD1jb2xNZWFucyhmZW1TYW1wcykgLSBjb2xNZWFucyhtYWxTYW1wcyksCiAgUmZhc3Q6OnR0ZXN0cyhmZW1TYW1wcywgbWFsU2FtcHMpCiAgKQoKCnJlcyAlPiUKICBnZ3Bsb3QoYWVzKHg9dmVyc2NoaWwseT0tbG9nMTAocHZhbHVlKSxjb2xvcj1wdmFsdWUgPCAwLjA1KSkgKwogIGdlb21fcG9pbnQoKSArCiAgeGxhYigiQXZlcmFnZSBoZWlnaHQgZGlmZmVyZW5jZSAoY20pIikgKwogIHlsYWIoIlN0YXRpc3RpY2FsIFNpZ25pZmljYW5jZSAoLWxvZzEwIHApIikKCmZhbHNlTmVnNUJveCA8LSByZXMgJT4lCiAgZ2dwbG90KGFlcyh5ID0gdmVyc2NoaWwpKSArCiAgZ2VvbV9ib3hwbG90KCkgKwogIHlsYWIoIkF2ZXJhZ2UgaGVpZ2h0IGRpZmZlcmVuY2UgKGNtKSIpCiAgeGxhYigiIikKCmZhbHNlTmVnNUJveApgYGAKCi0gVGhlcmUgYXJlIGByIHN1bShyZXMkcHZhbHVlIDwgMC4wNSAmIHJlcyR2ZXJzY2hpbCA8IDApYCBzYW1wbGVzIGZvciB3aGljaCB3ZSByZXR1cm4gYSB0cnVlIHBvc2l0aXZlICRccmlnaHRhcnJvdyQgVGhlIHBvd2VyIGlzIGByIHJvdW5kKG1lYW4ocmVzJHB2YWx1ZSA8IDAuMDUgJiByZXMkdmVyc2NoaWwgPCAwKSoxMDAsMSlgJS4KLSBUaGVyZSBhcmUgYHIgc3VtKHJlcyRwdmFsdWUgPiAwLjA1KWAgc2FtcGxlcyBmb3Igd2hpY2ggd2UgY2Fubm90IHJlcG9ydCBhIHNpZ25pZmljYW50IGRpZmZlcmVuY2UuIAotIFRoZXJlIGFyZSBgciAgc3VtKHJlcyRwdmFsdWUgPCAwLjA1ICYgcmVzJHZlcnNjaGlsPjApYCBmb3Igd2hpY2ggd2UgcmVwb3J0IGEgc2lnbmlmaWNhbnQgaGVpZ2h0IGRpZmZlcmVuY2UgYmV0d2VlbiBmZW1hbGVzIGFuZCBtYWxlcyB0aGF0IGlzIHBvc2l0aXZlLgoKCgotIFRoZSBzYW1wbGUgdGhhdCB3ZSBoYXZlIHNob3duIHdoZXJlIHdlIGNvbmNsdWRlZCB0aGF0IGZlbWFsZXMgd2VyZSBsYXJnZXIgdGhhbiBtYWxlcyB3YXMgdmVyeSB1bmxpa2VseS4gV2UgaGFkIHRvIGRyYXcgYHIgZm9ybWF0KHNlZWQsZGlnaXRzPTUpYCBzYW1wbGVzIGJlZm9yZSB3ZSB3ZXJlIGFibGUgdG8gZmluZCBzdWNoIGFuIGV4dHJlbWUgc2FtcGxlLiAKCi0gV2h5IGRvIHdlIGhhdmUgYSBjb25zaWRlcmFibGUgbnVtYmVyIG9mIHNhbXBsZXMgZm9yIHdoaWNoIHdlIGRvIG5vdCBmaW5kIGEgc2lnbmlmaWNhbnQgaGVpZ2h0IGRpZmZlcmVuY2UgYmV0d2VlbiBtYWxlcyBhbmQgZmVtYWxlcz8gCgojIyMgTGFyZ2VyIHNhbXBsZSBzaXplIAoKV2hlbiB3ZSB0YWtlIDIwIHN1YmplY3RzIGluIGVhY2ggZ3JvdXA6IAoKYGBge3IgZWNobyA9RkFMU0V9CnNldC5zZWVkKDE1MTUyKQojIEFhbnRhbCBzaW11bGF0aWVzIGVuIHN0ZWVrcHJvZWZncm9vdHRlIHBlciBncm9lcApuU2ltIDwtIDEwMDAwCm5TYW1wIDwtIDIwCgojIFdlIGZpbHRlcmVuIGRlIGRhdGEgdm9vcmFmIHpvZGF0IHdlIGRpdCBuaWV0IHRlbGtlbnMgb3BuaWV1dyBob2V2ZW4gdGUgZG9lbgpmZW0gPC0gbmhhbmVzU3ViICU+JQogIGZpbHRlcihHZW5kZXIgPT0gImZlbWFsZSIpCgptYWwgPC0gbmhhbmVzU3ViICU+JQogIGZpbHRlcihHZW5kZXIgPT0gIm1hbGUiKQoKIyBTaW11bGF0aWUgc3R1ZGllCiMgT20gc25lbGxlIGZ1bmN0aWVzIHRlIGt1bm5lbiBnZWJydWlrZW4gbmVtZW4gd2UgZWVyc3QgblNpbSBzdGVla3Byb2V2ZW4gZW4gYmVyZWtlbmVuIHdlIGRhYXJuYSBhbGxlcy4KCmZlbVNhbXBzIDwtIG1hbFNhbXBzIDwtbWF0cml4KE5BLCBucm93PW5TYW1wLCBuY29sPW5TaW0pCmZvciAoaSBpbiAxOm5TaW0pCnsKICBmZW1TYW1wc1ssaV0gPC0gc2FtcGxlKGZlbSRIZWlnaHQsIG5TYW1wKQogIG1hbFNhbXBzWyxpXSA8LSBzYW1wbGUobWFsJEhlaWdodCwgblNhbXApCn0KCnJlcyA8LSBkYXRhLmZyYW1lKAogIHZlcnNjaGlsPWNvbE1lYW5zKGZlbVNhbXBzKSAtIGNvbE1lYW5zKG1hbFNhbXBzKSwKICBSZmFzdDo6dHRlc3RzKGZlbVNhbXBzLCBtYWxTYW1wcykKICApCgoKcmVzICU+JQogIGdncGxvdChhZXMoeD12ZXJzY2hpbCx5PS1sb2cxMChwdmFsdWUpLGNvbG9yPXB2YWx1ZSA8IDAuMDUpKSArCiAgZ2VvbV9wb2ludCgpICsKICB4bGFiKCJBdmVyYWdlIGhlaWdodCBkaWZmZXJlbmNlIChjbSkiKSArCiAgeWxhYigiU3RhdGlzdGljYWwgU2lnbmlmaWNhbmNlICgtbG9nMTAgcCkiKQoKZmFsc2VOZWcyMEJveCA8LSByZXMgJT4lCiAgZ2dwbG90KGFlcyh5ID0gdmVyc2NoaWwpKSArCiAgZ2VvbV9ib3hwbG90KCkgKwogIHlsYWIoIkF2ZXJhZ2UgaGVpZ2h0IGRpZmZlcmVuY2UgKGNtKSIpCiAgeGxhYigiIikKICAKZmFsc2VOZWcyMEJveApgYGAKCgoKTGFyZ2VyIHNhbXBsZSBzaXplOiAKCi0gTGFyZ2VyIHBvd2VyIHRvIHBpY2sgdXAgYSByZWFsIGRpZmZlcmVuY2UgaW4gdGhlIHBvcHVsYXRpb24uIAotIE1lYW4gaXMgbW9yZSBwcmVjaXNlIAoKYGBge3IgZWNobz1GQUxTRSwgd2FybmluZz1GQUxTRSwgbWVzc2FnZT1GQUxTRX0KZ3JpZC5hcnJhbmdlKGZhbHNlTmVnNUJveCArIGdndGl0bGUoIm4xID0gbjIgPSA1IikgKyB5bGltKC00MCwxMCksZmFsc2VOZWcyMEJveCArIGdndGl0bGUoIm4xID0gbjIgPSAyMCIpICsgeWxpbSgtNDAsMTApLG5yb3c9MSkKYGBgCgoKCiMjIENvbnRyb2wgb2YgZmFsc2UgcG9zaXRpdmVzCgotIFN1cHBvc2UgdGhhdCB3ZSBzZXQgdXAgYW4gZXhwZXJpbWVudCB3aXRoIHR3byBncm91cHMgdGhhdCBhcmUgYm90aCBzYW1wbGVkIGZyb20gdGhlIGZlbWFsZXMgaW4gdGhlIE5IQU5FUyBzdHVkeQotIEJvdGggZ3JvdXBzIGNvbWUgZnJvbSB0aGUgc2FtZSBwb3B1bGF0aW9uOiBzbyBubyBkaWZmZXJlbmNlCgotIFdlIGFnYWluIGRyYXcgcmVwZWF0ZWQgZXhwZXJpbWVudHMgd2l0aCA1IHN1YmplY3RzIGluIGVhY2ggZ3JvdXAuIAoKCmBgYHtyIGVjaG8gPSBGQUxTRSwgd2FybmluZyA9IEZBTFNFLCBtZXNzYWdlID0gRkFMU0V9CnNldC5zZWVkKDEzMjQpCiMgQWFudGFsIHNpbXVsYXRpZXMgZW4gc3RlZWtwcm9lZmdyb290dGUgcGVyIGdyb2VwCm5TaW0gPC0gMTAwMDAKblNhbXAgPC0gNQoKIyBXZSBmaWx0ZXJlbiBkZSBkYXRhIHZvb3JhZiB6b2RhdCB3ZSBkaXQgbmlldCB0ZWxrZW5zIG9wbmlldXcgaG9ldmVuIHRlIGRvZW4KZmVtIDwtIG5oYW5lc1N1YiAlPiUKICBmaWx0ZXIoR2VuZGVyID09ICJmZW1hbGUiKQoKIyBTaW11bGF0aWUgc3R1ZGllCiMgT20gc25lbGxlIGZ1bmN0aWVzIHRlIGt1bm5lbiBnZWJydWlrZW4gbmVtZW4gd2UgZWVyc3QgblNpbSBzdGVla3Byb2V2ZW4gZW4gYmVyZWtlbmVuIHdlIGRhYXJuYSBhbGxlcy4KCmZlbVNhbXBzIDwtIGZlbVNhbXBzMiA8LW1hdHJpeChOQSwgbnJvdz1uU2FtcCwgbmNvbD1uU2ltKQpmb3IgKGkgaW4gMTpuU2ltKQp7CiAgZmVtU2FtcHNbLGldIDwtIHNhbXBsZShmZW0kSGVpZ2h0LCBuU2FtcCkKICBmZW1TYW1wczJbLGldIDwtIHNhbXBsZShmZW0kSGVpZ2h0LCBuU2FtcCkKfQoKcmVzIDwtIGRhdGEuZnJhbWUoCiAgdmVyc2NoaWw9Y29sTWVhbnMoZmVtU2FtcHMpIC0gY29sTWVhbnMoZmVtU2FtcHMyKSwKICBSZmFzdDo6dHRlc3RzKGZlbVNhbXBzLCBmZW1TYW1wczIpCiAgKQoKCnJlcyAlPiUKICBnZ3Bsb3QoYWVzKHg9dmVyc2NoaWwseT0tbG9nMTAocHZhbHVlKSxjb2xvcj1wdmFsdWUgPCAwLjA1KSkgKwogIGdlb21fcG9pbnQoKSArCiAgeGxhYigiQXZlcmFnZSBoZWlnaHQgZGlmZmVyZW5jZSAoY20pIikgKwogIHlsYWIoIlN0YXRpc3RpY2FsIFNpZ25pZmljYW5jZSAoLWxvZzEwIHApIikKCmZhbHNlUG9zNUJveCA8LSByZXMgJT4lCiAgZ2dwbG90KGFlcyh5ID0gdmVyc2NoaWwpKSArCiAgZ2VvbV9ib3hwbG90KCkgKwogIHlsYWIoIkF2ZXJhZ2UgaGVpZ2h0IGRpZmZlcmVuY2UgKGNtKSIpCiAgeGxhYigiIikKICAKZmFsc2VQb3M1Qm94CmBgYAoKLSBPbmx5IGluIGByIHN1bShyZXMkcHZhbHVlPDAuMDUpYCBvdXQgb2YgYHIgZm9ybWF0KG5TaW0sZGlnaXRzPTUpYCBzYW1wbGVzIHdlIGNvbmNsdWRlIHRoYXQgdGhlIG1lYW4gaW4gYm90aCBncm91cHMgYXJlIGRpZmZlcmVudCBvciBpbiBgciByb3VuZChtZWFuKHJlcyRwdmFsdWU8MC4wNSkqMTAwLDEpYCUgb2YgdGhlIHNhbXBsZXMuCgotIFdpdGggdGhlIHN0YXRpc3RpY2FsIGFuYWx5c2lzIHdlIGNhbiBjb250cm9sIHRoZSBudW1iZXIgb2YgZmFsc2UgcG9zaXRpdmUgcmVzdWx0cyBjb3JyZWN0bHkgYXQgdGhlIDUlIHNpZ25pZmljYW5jZSBsZXZlbC4gCgojIyMgTGFyZ2VyIHNhbXBsZSBzaXplIAoKV2UgcGVyZm9ybSB0aGUgc2ltdWxhdGlvbnMgYWdhaW4gd2l0aCAyMCBzdWJqZWN0cyBpbiBlYWNoIGdyb3VwLiAKCgoKCmBgYHtyIGVjaG8gPSBGQUxTRSwgd2FybmluZyA9IEZBTFNFLCBtZXNzYWdlID0gRkFMU0V9CnNldC5zZWVkKDEzMjQpCiMgQWFudGFsIHNpbXVsYXRpZXMgZW4gc3RlZWtwcm9lZmdyb290dGUgcGVyIGdyb2VwCm5TaW0gPC0gMTAwMDAKblNhbXAgPC0gMjAKCiMgV2UgZmlsdGVyZW4gZGUgZGF0YSB2b29yYWYgem9kYXQgd2UgZGl0IG5pZXQgdGVsa2VucyBvcG5pZXV3IGhvZXZlbiB0ZSBkb2VuCmZlbSA8LSBuaGFuZXNTdWIgJT4lCiAgZmlsdGVyKEdlbmRlciA9PSAiZmVtYWxlIikKCiMgU2ltdWxhdGllIHN0dWRpZQojIE9tIHNuZWxsZSBmdW5jdGllcyB0ZSBrdW5uZW4gZ2VicnVpa2VuIG5lbWVuIHdlIGVlcnN0IG5TaW0gc3RlZWtwcm9ldmVuIGVuIGJlcmVrZW5lbiB3ZSBkYWFybmEgYWxsZXMuCgpmZW1TYW1wcyA8LSBmZW1TYW1wczIgPC1tYXRyaXgoTkEsIG5yb3c9blNhbXAsIG5jb2w9blNpbSkKZm9yIChpIGluIDE6blNpbSkKewogIGZlbVNhbXBzWyxpXSA8LSBzYW1wbGUoZmVtJEhlaWdodCwgblNhbXApCiAgZmVtU2FtcHMyWyxpXSA8LSBzYW1wbGUoZmVtJEhlaWdodCwgblNhbXApCn0KCnJlcyA8LSBkYXRhLmZyYW1lKAogIHZlcnNjaGlsPWNvbE1lYW5zKGZlbVNhbXBzKSAtIGNvbE1lYW5zKGZlbVNhbXBzMiksCiAgUmZhc3Q6OnR0ZXN0cyhmZW1TYW1wcywgZmVtU2FtcHMyKQogICkKCgpyZXMgJT4lCiAgZ2dwbG90KGFlcyh4PXZlcnNjaGlsLHk9LWxvZzEwKHB2YWx1ZSksY29sb3I9cHZhbHVlIDwgMC4wNSkpICsKICBnZW9tX3BvaW50KCkgKwogIHhsYWIoIkF2ZXJhZ2UgaGVpZ2h0IGRpZmZlcmVuY2UgKGNtKSIpICsKICB5bGFiKCJTdGF0aXN0aWNhbCBTaWduaWZpY2FuY2UgKC1sb2cxMCBwKSIpCgpmYWxzZVBvczIwQm94IDwtIHJlcyAlPiUKICBnZ3Bsb3QoYWVzKHkgPSB2ZXJzY2hpbCkpICsKICBnZW9tX2JveHBsb3QoKSArCiAgeWxhYigiQXZlcmFnZSBoZWlnaHQgZGlmZmVyZW5jZSAoY20pIikKICB4bGFiKCIiKQoKZmFsc2VQb3MyMEJveApgYGAKCgoKCi0gT25seSBpbiBgciBzdW0ocmVzJHB2YWx1ZTwwLjA1KWAgb3V0IG9mIGByIGZvcm1hdChuU2ltLGRpZ2l0cz01KWAgc2FtcGxlcyB3ZSBjb25jbHVkZSB0aGF0IHRoZSBtZWFuIGluIGJvdGggZ3JvdXBzIGFyZSBkaWZmZXJlbnQgb3IgaW4gYHIgcm91bmQobWVhbihyZXMkcHZhbHVlPDAuMDUpKjEwMCwxKWAlIG9mIHRoZSBzYW1wbGVzLgoKCi0gU28gd2l0aCB0aGUgc3RhdGlzdGljYWwgYW5hbHlzaXMsIGFsc28gd2hlbiB0YWtpbmcgYSBsYXJnZSBzYW1wbGUsIHdlIGNvcnJlY3RseSBjb250cm9sIHRoZSBudW1iZXIgb2YgZmFsc2UgcG9zaXRpdmUgcmVzdWx0cyBhdCA1JS4KCi0gVGhlIG1lYW4gZGlmZmVyZW5jZSBpcyBhZ2FpbiBtb3JlIGFjY3VyYXRlbHkgZXN0aW1hdGVkIChmbHVjdHVhdGluZyBsZXNzIGFyb3VuZCB0aGUgcmVhbCBkaWZmZXJlbmNlIG9mIDApLiAKCgpgYGB7ciBlY2hvPUZBTFNFLCB3YXJuaW5nPUZBTFNFLCBtZXNzYWdlPUZBTFNFfQpncmlkLmFycmFuZ2UoZmFsc2VQb3M1Qm94ICsgZ2d0aXRsZSgibjEgPSBuMiA9IDUiKSArIHlsaW0oLTIwLDIwKSxmYWxzZVBvczIwQm94ICsgZ2d0aXRsZSgibjEgPSBuMiA9IDIwIikgKyB5bGltKC0yMCwyMCksbnJvdz0xKQpgYGAKCgoKIyBDb250cm9sIHRyZWF0bWVudAoKQ2FwdG9wcmlsIHN0dWR5OiBTQlAgYmVmb3JlIGFuZCBhZnRlciBkb3NpZ24gY2FwdG9wcmlsLgoKYGBge3IgZWNobz1GQUxTRSwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KY2FwdG9wcmlsIDwtIHJlYWQudGFibGUoImh0dHBzOi8vcmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbS9zdGF0T21pY3Mvc2JjL21hc3Rlci9kYXRhL2NhcHRvcHJpbC50eHQiLGhlYWRlcj1UUlVFLHNlcD0iLCIpCmNhcHRvcHJpbFRpZHkgPC0gY2FwdG9wcmlsICU+JSBnYXRoZXIodHlwZSxicCwtaWQpCmNhcHRvMSA8LSBjYXB0b3ByaWxUaWR5ICU+JQogIGZpbHRlcih0eXBlJWluJWMoIlNCUGEiLCJTQlBiIikpICU+JQogIG11dGF0ZSh0eXBlPWZhY3Rvcih0eXBlLGxldmVscz1jKCJTQlBiIiwiU0JQYSIpKSkgJT4lCiAgZ2dwbG90KGFlcyh4PXR5cGUseT1icCkpICsKICBnZW9tX2xpbmUoYWVzKGdyb3VwID0gaWQpKSArCiAgZ2VvbV9wb2ludCgpCgpkZWx0YSA8LSBjYXB0b3ByaWwkU0JQYS1jYXB0b3ByaWwkU0JQYgpjYXB0b3ByaWwkZGVsdGFTQlAgPC0gZGVsdGEKY2FwdG8yIDwtIGNhcHRvcHJpbCAlPiUKICBnZ3Bsb3QoYWVzKHg9IlN5c3RvbGljIGJsb29kIHByZXNzdXJlIix5PWRlbHRhU0JQKSkgKwogIGdlb21fYm94cGxvdChvdXRsaWVyLnNoYXBlPU5BKSArCiAgZ2VvbV9wb2ludChwb3NpdGlvbj0iaml0dGVyIikrCiAgeWxhYigiRGlmZmVyZW5jZSAobW0gbWVyY3VyeSkiKSArCiAgeGxhYigiIikKCmdyaWQuYXJyYW5nZShjYXB0bzEsIGNhcHRvMiwgbnJvdz0xKQoKd2l0aChjYXB0b3ByaWwsIHQudGVzdCgKICAgICAgICAgICAgIFNCUGEsCiAgICAgICAgICAgICBTQlBiLAogICAgICAgICAgICAgcGFpcmVkPVRSVUUpKQoKYGBgCmBgYHtyfQpzZChjYXB0b3ByaWwkU0JQYikKc2QoY2FwdG9wcmlsJFNCUGEpCnNkKGNhcHRvcHJpbCRkZWx0YVNCUCkKYGBgCgpwcmUtdGVzdC9wb3N0LXRlc3QgZXhwZXJpbWVudAoKLSBBZHZhbnRhZ2U/Ci0gUHJvYmxlbT8KCi0tLQoKPGltZyBzcmM9Ii4vZmlndXJlcy9wbGFjZWJvLnBuZyIgd2lkdGg9IjIwJSIgc3R5bGU9ImZsb2F0OiByaWdodDsiPgoKR29vZCBjb250cm9sIGlzIG5lc3NlY2FyeSAKCiRccmlnaHRhcnJvdyQgUGxhY2VibyBjb250cm9sbGVkIGRvdWJsZSBibGluZCBleHBlcmltZW50cyAgICAgCiRccmlnaHRhcnJvdyQgSW5qZWN0aW9uIG9mIGNvbnRyb2wgYW5pbWFsIHdpdGggYmxhbmsgY29udGFpbmluZyBzYW1lIHNvbHZlbnRzLCBldGMuIAoKIyBSZXBsaWNhdGlvbgoKCldpdGhpbiBhbiBleHBlcmltZW50OiBFbmFibGVzIHRvIGVzdGltYXRlIHVuY2VydGFpbnR5IC8gYmlvbG9naWNhbCB2YXJpYWJpbGl0eQoKLSBSZXBsaWNhdGlvbiBpcyBlc3NlbnRpYWwgZm9yIHF1YW50aWZ5aW5nIHRoZSBub2lzZQoKLSBOb2lzZTogYmlvbG9naWNhbCBhbmQgdGVjaG5pY2FsIGluIG5hdHVyZQoKQmV0d2VlbiBleHBlcmltZW50czogQW55IHRydWUgZmluZGluZyBzaG91bGQgYmUgcmVwcm9kdWNpYmxlCgoKCiMjIEF0IHdoaWNoIGxldmVsIGRvIHdlIGhhdmUgdG8gcmVwbGljYXRlPyAKCi0gR2VudWluZSByZXBsaWNhdGVzIGluY2x1ZGUgYWxsIHNvdXJjZXMgb2YgdmFyaWFiaWxpdHk6IHRlY2huaWNhbCArIGJpb2xvZ2ljYWwKLSBUZWNobmljYWwgcmVwbGljYXRlcyBhcmUgaW1wb3J0YW50IGlmIHlvdSBhc3Nlc3MgbmV3IHRlY2hub2xvZ2llcwoKIVtdKC4vZmlndXJlcy9zdW1WYXJDb21wLnBuZykKCiMjIFBzZXVkb3JlcGxpY2F0aW9uCgotIFNhbXBsZXMgYXJlIG5vdCBpbmRlcGVuZGVudCBlLmcuCiAgICAKICAgIC0gU2FtZSBiYXRjaCBvZiByZWFnZW50cwogICAgLSBTYW1lIDk2LXdlbGwgcGxhdGUKICAgIC0gTGVhdmVzIGZyb20gdGhlIHNhbWUgcGxhbnQKICAgIC0gQ2VsbHMgZnJvbSB0aGUgc2FtZSBwbGF0ZQogICAgLSBNaWNlIGluIHRoZSBzYW1lIGNhZ2Ugb3IgZnJvbSB0aGUgc2FtZSBsaXR0ZXIKICAgIC0gU3BhdGlhbGx5L2Nocm9uYWxseSBjbHVzdGVyZWQgdG9nZXRoZXIgKHdlbGxzIG9uIHBsYXRlLCBhbGwgdHJ0IEEgbWVhc3VyZWQgYmVmb3JlIHRydCBCKQoKLSBUcnkgdG8gYXZvaWQgcHNldWRvLXJlcGxpY2F0aW9uOiBzYW1wbGVzIGFyZSBub3QgaW5kZXBlbmRlbnQgCgogICAgLSBDb250YWluIGxlc3MgaW5mbyB0aGFuIGdlbnVpbmUgcmVwbGljYXRlcwogICAgLSBJZiBhbmFseXNlZCBhcyBpZiB0aGV5IHdlcmUgaW5kZXBlbmRlbnQgJFxyaWdodGFycm93JCBpbmNyZWFzZWQgbnVtYmVyIG9mIGZhbHNlIHBvc2l0aXZlcwogICAgLSBJZiBub3QgcG9zc2libGUgZS5nLiBpbiBhIG11bHRpLXN1YmplY3Qgc2luZ2xlIGNlbGwgY29udGV4dCwgcHNldWRvLXJlcGxpY2F0aW9uIHR5cGljYWxseSBvY2N1cnMgYW5kIGhhcyB0byBiZSBhY2NvdW50ZWQgaW4gdGhlIGFuYWx5c2lzISAKICAgIC0gQ29uc3VsdCBzdGF0aXN0aWNpYW4KCgojIyBGcmFuY2lzZWxsYSB0dWxhcmVuc2lzIHN0dWR5IFJhbW9uZCBldCBhbC4gKDIwMTUpCgotIFByb3Rlb21lIG9mIHdpbGQgdHlwZSBGLiB0dWxhcmVuc2lzIChXVCkgdnMgQXJnUC1nZW5lIGRlbGV0ZWQgRi4gdHVsYXJlbnNpcyAoa25vY2stb3V0LCBEOCkuCi0gRWFjaCBiaW8tcmVwIGluIHRlY2huaWNhbCB0cmlwbGljYXRlIG9uIE1TCi0gSWxsdXN0cmF0aW9uIHdpdGggNTBTIHJpYm9zb21hbCBwcm90ZcOvbiBMNSBBMFE0SjUKCmBgYHtyIGVjaG8gPSBGQUxTRSwgd2FybmluZyA9IEZBTFNFLCBtZXNzYWdlID0gRkFMU0V9CmZyYW5jIDwtIHJlYWRfdHN2KCJodHRwczovL3Jhdy5naXRodWJ1c2VyY29udGVudC5jb20vc3RhdE9taWNzL1BTTFMyMS9kYXRhL2ZyYW5jaXNlbGxhQTBRNEo1LnR4dCIpCmZyYW5jICU+JSAKICBnZ3Bsb3QoYWVzKGJpb3JlcCwgaW50ZW5zaXR5TG9nMiwgY29sb3IgPSBnZW5vdHlwZSkpICsKICBnZW9tX3BvaW50KCkKYGBgCgotIElmIHdlIGFuYWx5c2Ugb3JpZ2luYWwgZGF0YSB3aXRoIGEgdC10ZXN0IHdlIGFjdCBhcyBpZiB3ZSB3b3VsZCBoYXZlIDkgZ2VudWluZSByZXBlYXRzIGluIGVhY2ggY29uZGl0aW9uIAoKLSBFZmZlY3Qgb2YgaW50ZXJlc3QgYmV0d2VlbiBiaW8tcmVwcyBzbyBubyBibG9jayBkZXNpZ24KCi0gU2FtZSBudW1iZXIgb2YgdGVjaG5pY2FsIHJlcGVhdHMgZm9yIGVhY2ggZ2VudWluZSByZXBlYXQgd2UgY2FuIGZpcnN0IGF2ZXJhZ2Ugb3ZlciB0aGUgdGVjaHJlcHMuIAoKLSBJZiB0aGF0IGlzIG5vdCB0aGUgY2FzZSBtb3JlIGNvbXBsZXggZGF0YSBhbmFseXNpcyBtZXRob2RzIGhhdmUgdG8gYmUgdXNlZCwgZS5nLiBtaXhlZCBtb2RlbHMhCgotICoqQ2F1dGlvbjogbmV2ZXIgYXZlcmFnZSBvdmVyIGdlbnVpbmUgcmVwZWF0cy9leHBlcmltZW50YWwgdW5pdHMhISEqKgoKIyMjIENvcnJlY3QgYW5hbHlzaXMgCgpgYGB7cn0KbG1CaW9yZXAgPC0gbG0oaW50ZW5zaXR5TG9nMiB+IC0xICsgYmlvcmVwLCBmcmFuYykKZnJhbmNTdW0gPC0gZGF0YS5mcmFtZShnZW5vdHlwZSA9IHJlcChjKCJEOCIsIldUIiksZWFjaD0zKSAlPiUgYXMuZmFjdG9yICU+JSByZWxldmVsKCJXVCIpLCBpbnRlbnNpdHlMb2cyID0gbG1CaW9yZXAkY29lZikKZnJhbmNTdW0KdC50ZXN0KGludGVuc2l0eUxvZzIgfiBnZW5vdHlwZSwgZnJhbmNTdW0sIHZhci5lcXVhbD1UUlVFKQpgYGAKCiMjIyBXcm9uZyBhbmFseXNpcwoKYGBge3IgZWNobyA9IEZBTFNFLCB3YXJuaW5nID0gRkFMU0UsIG1lc3NhZ2UgPSBGQUxTRX0KdC50ZXN0KGludGVuc2l0eUxvZzIgfiBnZW5vdHlwZSwgZnJhbmMsdmFyLmVxdWFsPVRSVUUpCmBgYAoKLSBSZXN1bHQgbXVjaCBtb3JlIHNpZ25pZmljYW50IGJlY2F1c2Ugd2UgZXJyb25lb3VzbHkgYWN0IGFzIGlmIHdlIGhhdmUgYSA5IGJ5IDkgY29tcGFyaXNvbi4gCgojIyMgU2ltdWxhdGlvbiB1bmRlciAkSF8wJAoKLSBXZSB1c2UgZGF0YSB0byBlc3RpbWF0ZSB2YXJpYW5jZSBjb21wb25lbnRzOiB0ZWNobmljYWwgYW5kIGJpb2xvZ2ljYWwgdmFyaWFuY2UuIAotIFdlIHNpbXVsYXRlIDEwMDAwIGV4cGVyaW1lbnRzIHdpdGggc2ltaWxhciBkZXNpZ24gZnJvbSBhIG5vcm1hbCBkaXN0cmlidXRpb24gdW5kZXIgdGhlIGFzc3VtcHRpb24gdGhhdCBncm91cCBtZWFucyBhcmUgdGhlIHNhbWUuIAotIFdlIGFuYWx5c2UgdGhlbSB3aXRoIGJvdGggZGVzaWducwoKYGBge3IgZWNobyA9IEZBTFNFLCB3YXJuaW5nID0gRkFMU0UsIG1lc3NhZ2UgPSBGQUxTRX0Kc2lnbWFXaXRoaW4gPC0gc2lnbWEobG1CaW9yZXApCmxtU3VtIDwtIGxtKGludGVuc2l0eUxvZzIgfiBnZW5vdHlwZSwgZnJhbmNTdW0pCnNpZ21hQmV0d2VlbiA8LSBzaWdtYShsbVN1bSkKeEJpb3JlcCA8LSBtb2RlbC5tYXRyaXgofi0xK2Jpb3JlcCxmcmFuYykKeFdyb25nIDwtIG1vZGVsLm1hdHJpeCh+Z2Vub3R5cGUsZnJhbmMpCgoKc2V0LnNlZWQoMjUyMykKblNpbSA8LSAxMDAwMApyZXNXcm9uZyA8LSBtYXRyaXgoTkEsblNpbSw0KSAlPiUgYXMuZGF0YS5mcmFtZQpuYW1lcyhyZXNXcm9uZykgPC0gYygiRXN0aW1hdGUiLCJTdGQuIEVycm9yIiwidCB2YWx1ZSIsInB2YWx1ZSIpCnJlc0NvcnJlY3QgPC0gcmVzV3JvbmcKZ2Vub3R5cGUgPC0gZnJhbmMkZ2Vub3R5cGUKZ2Vub3R5cGVTdW0gPC0gZnJhbmNTdW0kZ2Vub3R5cGUKYmlvcmVwIDwtIGZyYW5jJGJpb3JlcAoKZm9yIChpIGluIDE6blNpbSkKewpiaW9yZXBTaW0gPC0gcm5vcm0obmNvbCh4QmlvcmVwKSxzZD1zaWdtYUJldHdlZW4pCnlTaW0gPC0geEJpb3JlcCUqJWJpb3JlcFNpbSArIHJub3JtKG5yb3coeEJpb3JlcCksc2Q9c2lnbWFXaXRoaW4pCnlTdW0gPC0gbG0oeVNpbX5iaW9yZXApJGNvZWZmaWNpZW50CnJlc1dyb25nW2ksXSA8LSBzdW1tYXJ5KGxtKHlTaW1+Z2Vub3R5cGUpKSRjb2VmZmljaWVudFsyLF0KcmVzQ29ycmVjdFtpLF08LXN1bW1hcnkobG0oeVN1bX5nZW5vdHlwZVN1bSkpJGNvZWZmaWNpZW50WzIsXQp9CmBgYAoKUHJvYmFiaWxpdHkgb24gYSBmYWxzZSBwb3NpdGl2ZSB3aGVuIHVzaW5nIGEgNSUgc2lnbmlmaWNhbmNlIGxldmVsIGluIAoKLSBjb3JyZWN0IGFuYWx5c2lzOgpgYGB7cn0KbWVhbihyZXNDb3JyZWN0JHB2YWx1ZSA8IDAuMDUpCmBgYAoKLSB3cm9uZyBhbmFseXNpczogCgpgYGB7cn0KbWVhbihyZXNXcm9uZyRwdmFsdWUgPCAwLjA1KQpgYGAKCi0gV2Ugbm8tbG9uZ2VyIGNvbnRyb2wgdGhlIGZhbHNlIHBvc2l0aXZlcyBhdCB0aGUgJFxhbHBoYSA9IDUkJSBsZXZlbCEKLSBXZSByZXBvcnQgdG8gbXVjaCBmYWxzZSBwb3NpdGl2ZXMhIAoKIyMgSG93IG1hbnkgZ2VudWluZSByZXBsaWNhdGVzPyAKCi0gRm9yIGV4cGVyaW1lbnRhbCBzdHVkaWVzOiBsb29rIGF0IHJhbmRvbWlzYXRpb24gb2YgdHJlYXRtZW50IAotIERvdWJsZSBibGluZCBzdHVkeSB3aXRoIDIwIHNwdXR1bSBwb3NpdGl2ZSBwYXRpZW50cyByYW5kb21pemVkIHRvIHRyZWF0bWVudCBvciBwbGFjZWJvCi0gTW91c2Ugc3R1ZHkgKDEwIG1pY2UpCgohW10oLi9maWd1cmVzL21vdXNlQ2FnZS5wbmcpe3dpZHRoPTI1JX0KCi0gTW91c2Ugc3R1ZHkgKDMwIG1pY2UpCgohW10oLi9maWd1cmVzL21vdXNlQ2FnZS5wbmcpe3dpZHRoPTI1JX0hW10oLi9maWd1cmVzL21vdXNlQ2FnZS5wbmcpe3dpZHRoPTI1JX0hW10oLi9maWd1cmVzL21vdXNlQ2FnZS5wbmcpe3dpZHRoPTI1JX0gICAgCgotIE1vdXNlIHN0dWR5ICgxMCBtaWNlKQoKIVtdKC4vZmlndXJlcy9tb3VzZUNhZ2VCbG9ja2luZy5wbmcpe3dpZHRoPTI1JX0KCgojIEJsb2NraW5nIAoKLSBJc29sYXRlIGtub3duIHNvdXJjZXMgb2YgdmFyaWFiaWxpdHkgZnJvbSB0aGUgZXhwZXJpbWVudAotIE9uZSBvZiB0aGUgbW9zdCBwb3dlcmZ1bCBjb25jZXB0cyBvZiBleHBlcmltZW50YWwgZGVzaWduCi0gTmF0dXJlIG1ldGhvZHM6IFBvaW50cyBvZiBzaWduaWZpY2FuY2UgLSBCbG9ja2luZyAKCltodHRwczovL3d3dy5uYXR1cmUuY29tL2FydGljbGVzL25tZXRoLjMwMDUucGRmXShodHRwczovL3d3dy5uYXR1cmUuY29tL2FydGljbGVzL25tZXRoLjMwMDUucGRmKQoKIyMgRXhhbXBsZQoKYGBge3IgZWNobyA9IEZBTFNFLCB3YXJuaW5nID0gRkFMU0UsIG1lc3NhZ2UgPSBGQUxTRSwgb3V0LndpZHRoPSI1MCUifQprbml0cjo6aW5jbHVkZV9ncmFwaGljcygiLi9maWd1cmVzL21vdXNlVGNlbGxfUkNCX2Rlc2lnbi5wbmciKQpgYGAKCmBgYHtyIGVjaG8gPSBGQUxTRSwgd2FybmluZyA9IEZBTFNFLCBtZXNzYWdlID0gRkFMU0UsIG91dC53aWR0aD0iMTAwJSJ9CmtuaXRyOjppbmNsdWRlX2dyYXBoaWNzKCIuL2ZpZ3VyZXMvYmxvY2tpbmdNb3VzZVRtZHMucG5nIikKYGBgCgojIEltcGxpY2F0aW9ucyBvZiBkaWZmZXJlbnQgdGVjaG5vbG9naWVzCgo8aW1nIHNyYz0iLi9maWd1cmVzL2xhYmVsVnNMYWJlbEZyZWUucG5nIiB3aWR0aD0iMTAwJSI+ClNsaWRlIGNvdXJ0ZXN5IChMaXNhIEJyZWNrZWxzKQoKCgojIFBvd2VyIGFuYWx5c2lzCgotIEhvdyBtYW55IHJlcGxpY2F0ZXMgZG8gd2UgbmVlZD8gCi0gRGlmZmVycyBmb3IgZGlmZmVyZW50IGV4cGVyaW1lbnRhbCBkZXNpZ25zCi0gUmVxdWlyZXMga25vd2xlZGdlIG9mIHRvdGFsIHZhcmlhYmlsaXR5IC8gbWFnbml0dWRlIG9mIHNvdXJjZXMgb2YgdmFyaWFiaWxpdHkKLSBVc2UgbGl0ZXJhdHVyZSBvciBwaWxvdCBleHBlcmltZW50Ci0gQ2FuIGJlIGRvbmUgdXNpbmcgc2ltdWxhdGlvbnMKCiMjIE1vdXNlIGV4YW1wbGUKCi0gSW4gMjAyMSBDaG9hIGV0IGFsLiBwdWJsaXNoZWQgdGhhdCB0aGUgY3l0b2tpbmUgVGh5bWljIHN0cm9tYWwgbHltcGhvcG9pZXRpbiAoVFNMUCkgaW5kdWNlZCBmYXQgbG9zcyB0aHJvdWdoIHNlYnVtIHNlY3JldGlvbiAodGFsZykuIFtbaHRtbF0oaHR0cHM6Ly93d3cuc2NpZW5jZS5vcmcvZG9pL2Z1bGwvMTAuMTEyNi9zY2llbmNlLmFiZDI4OTMpXSBbW1BERl0oaHR0cHM6Ly93d3cuc2NpZW5jZS5vcmcvZG9pL3BkZi8xMC4xMTI2L3NjaWVuY2UuYWJkMjg5MyldCgoKLSBTdXBwb3NlIHRoYXQgeW91IHdvdWxkIGxpa2UgdG8gc2V0IHVwIGEgc2ltaWxhciBzdHVkeSB0byB0ZXN0IGlmIGN5dG9raW5lIGludGVybGV1a2luIDI1IChJTCkgYWxzbyBoYXMgYmVuZWZpY2lhbCBlZmZlY3QuCgotIFlvdSBwbGFuIHRvIHNldHVwIGEgc3R1ZHkgd2l0aCBhIGNvbnRyb2wgZ3JvdXAgb2YgaGlnaCBmYXQgZGlldCAoSEZEKSBmZWQgbWljZSBhbmQgYSB0cmVhdG1lbnQgZ3JvdXAgdGhhdCByZWNpZXZlcyB0aGUgSEZEIGFuZCBJTC4KCi0gV2hhdCBzYW1wbGUgc2l6ZSBkbyB5b3UgbmVlZCB0byBwaWNrIHVwIHRoZSBlZmZlY3Qgb2YgdGhlIHRyZWF0bWVudC4KCiMjIEhvdyB3aWxsIHdlIGFuYWx5c2UgdGhlIGRhdGEgb2YgdGhpcyBleHBlcmltZW50PwoKLSBUd28gZ3JvdXBzOiB0d28gc2FtcGxlIHQtdGVzdAoKJEhfMCQ6IFRoZSBhdmVyYWdlIHdlaWdodCBkaWZmZXJlbmNlIGlzIGVxdWFsIHRvIHplcm8gICAgCiRIXzEkOiBUaGUgYXZlcmFnZSB3ZWlnaHQgZGlmZmVyZW5jZSBpcyBkaWZmZXJlbnQgZnJvbSB6ZXJvCgpQb3dlcj8gSXMgZGVzaWduIHNwZWNpZmljLiBGb3IgdHdvLWdyb3VwIGNvbXBhcmlzb24gaXQgZGVwZW5kcyBvbiAKCi0gUmVhbCB3ZWlnaHQgZGlmZmVyZW5jZSBiZXR3ZWVuIHRoZSBncm91cCBtZWFucy4KLSBWYXJpYWJpbGl0eSBvZiB0aGUgd2VpZ2h0IG1lYXN1cmVtZW50cwotIFNpZ25pZmljYW5jZSBsZXZlbCAkXGFscGhhJAotIFNhbXBsZSBzaXplIGluIGJvdGggZ3JvdXBzCgpXZSBjYW4gZXN0aW1hdGUgdGhlIHBvd2VyIGlmCgotIFRoZSBhc3N1bXB0aW9ucyBvZiB0aGUgbW9kZWwgYXJlIG1ldDogd2VpZ2h0cyBhcmUgbm9ybWFsbHkgZGlzdHJpYnV0ZWQgd2l0aCBzYW1lIHZhcmlhbmNlCgphbmQgd2Uga25vdwoKLSBTdGFuZGFyZCBkZXZpYXRpb24gb2YgdGhlIHdlaWdodCBtZWFzdXJlbWVudHMgYXJvdW5kIHRoZWlyIGF2ZXJhZ2UgbWVhbiBmb3IgSEZELWZlZCBtaWNlCi0gUmVhbCBlZmZlY3Qgc2l6ZSBpbiB0aGUgcG9wdWxhdGlvbgotIFNhbXBsZSBzaXplcyBpbiBlYWNoIGdyb3VwIAoKIyMgVXNlIGRhdGEgZnJvbSBhIHByZXZpb3VzIGV4cGVyaW1lbnQgdG8gZ2V0IGluc2lnaHQgaW4gbWljZSBkYXRhCgotIFN1cHBvc2UgdGhhdCB3ZSBoYXZlIGFjY2VzcyB0byB0aGUgZGF0YSBvZiBhIHByZWxpbWluYXJ5IGV4cGVyaW1lbnQgKGUuZy4gcHJvdmlkZWQgYnkgS2FyZW4gU3ZlbnNvbiB2aWEgR2FyeSBDaHVyY2hpbGwgYW5kIERhbiBHYXR0aSBhbmQgcGFydGlhbGx5IGZ1bmRlZCBieSBQNTAgR00wNzA2ODMgb24gUEg1MjV4KQoKYGBge3IgZWNobyA9IEZBTFNFLCB3YXJuaW5nID0gRkFMU0UsIG1lc3NhZ2UgPSBGQUxTRX0KbWljZSA8LSByZWFkLmNzdigiaHR0cHM6Ly9yYXcuZ2l0aHVidXNlcmNvbnRlbnQuY29tL2dlbm9taWNzY2xhc3MvZGFnZGF0YS9tYXN0ZXIvaW5zdC9leHRkYXRhL2ZlbWFsZU1pY2VXZWlnaHRzLmNzdiIpCgptaWNlICU+JQogIGdncGxvdChhZXMoeCA9IERpZXQsIHkgPSBCb2R5d2VpZ2h0KSkgKwogIGdlb21fYm94cGxvdChvdXRsaWVyLnNoYXBlID0gRkFMU0UpICsKICBnZW9tX2ppdHRlcigpCgoKbWljZSAlPiUKICBnZ3Bsb3QoYWVzKHNhbXBsZSA9IEJvZHl3ZWlnaHQpKSArCiAgZ2VvbV9xcSgpICsKICBnZW9tX3FxX2xpbmUoKSArCiAgZmFjZXRfd3JhcCh+RGlldCkKCm1pY2UgPC0gbWljZSAlPiUgbXV0YXRlKERpZXQgPSBhcy5mYWN0b3IoRGlldCkpCm1pY2VTdW0gPC0gbWljZSAlPiUKICBncm91cF9ieShEaWV0KSAlPiUKICBzdW1tYXJpemUoCiAgICBtZWFuID0gbWVhbihCb2R5d2VpZ2h0LCBuYS5ybSA9IFRSVUUpLAogICAgc2QgPSBzZChCb2R5d2VpZ2h0LCBuYS5ybSA9IFRSVUUpLAogICAgbiA9IG4oKQogICkgJT4lCiAgbXV0YXRlKHNlID0gc2QgLyBzcXJ0KG4pKQptaWNlU3VtCmBgYAoKSW4gdGhlIGV4cGVyaW1lbnQgd2UgaGF2ZSBkYXRhIGZyb20gdHdvIGRpZXRzOgoKLSBSZWd1bGFyIGRpZXQgb2YgY2VyaWFsIGFuZCBncmFpbiBiYXNlZCBkaWV0IChDaG93KQotIEhpZ2ggRmF0IChoZikKCldlIGNhbiB1c2UgdGhlIGhmIG1pY2UgYXMgaW5wdXQgZm9yIG91ciBwb3dlciBhbmFseXNpcy4KCi0gVGhlIGRhdGEgb2YgaGYgbWljZSBzZWVtIHRvIGJlIG5vcm1hbGx5IGRpc3RyaWJ1dGVkCi0gVGhlIG1lYW4gd2VpZ2h0IGlzIDI2LjhnCi0gVGhlIFNEIG9mIHRoZSB3ZWlnaHQgaXMgNC4xZwoKIyMjIEVmZmVjdCBzaXplPwoKLSBUaGUgYWx0ZXJuYXRpdmUgaHlwb3RoZXNpcyBpcyBjb21wbGV4LgotIEl0IGluY2x1ZGVzIGFsbCBwb3NzaWJsZSBlZmZlY3RzIQotIEluIG9yZGVyIHRvIGRvIHRoZSBwb3dlciBhbmFseXNpcyB3ZSB3aWxsIGhhdmUgdG8gY2hvb3NlIGEgbWluaW11bSBlZmZlY3Qgc2l6ZSB0aGF0IHdlIHdvdWxkIGxpa2UgdG8gZGV0ZWN0LgoKLSBTdXBwb3NlIHRoYXQgd2Ugd291bGQgbGlrZSB0byBwaWNrIHVwIGEgd2VpZ2h0IGNoYW5nZSBvZiBhdCBsZWFzdCAxMCUuCgpgYGB7cn0KZGVsdGEgPC0gYWJzKHJvdW5kKG1pY2VTdW0kbWVhblsyXSAqIC4xLCAxKSkKZGVsdGEKYGBgCgojIyMgU2ltdWxhdGlvbiBiYXNlZCBwb3dlciBhbmFseXNpcwoKV2UgY2FuIHVzZSBzaW11bGF0aW9ucyB0byBhc3Nlc3MgdGhlIHBvd2VyLiAKCi0gRS5nLiBmb3IgYSAzIGJ5IDMgY29tcGFyaXNvbiB3aGVyZSB0aGVyZSBpcyBhIHdlaWdodCBkaWZmZXJlbmNlIG9mIDNnLiAKLSBXZSBzaW11bGF0ZSAzIG9ic2VydmF0aW9ucyBmcm9tIGEgbm9ybWFsIHdpdGggbWVhbiAyNi44ZyBhbmQgc2QgNC4xZyBhbmQgMyBvYnNlcnZhdGlvbnMgZnJvbSBhIG5vcm1hbCB3aXRoIG1lYW4gMjkuOGcgYW5kIHNkIDQuMWcuIAotIFdlIHBlcmZvcm0gYSB0LXRlc3QgYW5kIGFzc2VzcyBpZiB3ZSBjYW4gY29uY2x1ZGUgdGhhdCB0aGVyZSBpcyBhIHNpZ25pZmljYW50IGRpZmZlcmVuY2UgaW4gdGhlIGF2ZXJhZ2Ugd2VpZ2h0IGJldHdlZW4gYm90aCBncm91cHMgYmFzZWQgb24gdGhpcyBzYW1wbGUKLSBXZSByZXBlYXQgaXQgbWFueSB0aW1lcyBhbmQgY2FsY3VsYXRlIHRoZSBwcm9iYWJpbGl0eSB0byBmaW5kIGEgc2lnbmlmaWNhbnQgZGlmZmVyZW5jZS4gCgpXZSBjYW4gcmVwZWF0IHRoZSBzYW1lIHByb2NlZHVyZSBmb3IgbWFueSBkaWZmZXJlbnQgc2FtcGxlIHNpemVzLi4uIAoKCgpgYGB7ciBlY2hvID0gRkFMU0UsIHdhcm5pbmcgPSBGQUxTRSwgbWVzc2FnZSA9IEZBTFNFfQpuMSA8LSBuMiA8LSAzCgpzZCA8LSByb3VuZChtaWNlU3VtJHNkWzJdLCAxKQpwcmVkaWN0b3JEYXRhIDwtIGRhdGEuZnJhbWUoRGlldCA9IHJlcChjKCJjIiwgImhmIiksIGMobjEsIG4yKSkgJT4lIGFzLmZhY3RvcigpKQoKYWxwaGEgPC0gMC4wNQoKCnNpbUZhc3QgPC0gZnVuY3Rpb24oZm9ybSwgZGF0YSwgYmV0YXMsIHNkLCBjb250cmFzdHMsIGFscGhhID0gLjA1LCBuU2ltID0gMTAwMDApIHsKICB5U2ltIDwtIHJub3JtKG5yb3coZGF0YSkgKiBuU2ltLCBzZCA9IHNkKQogIGRpbSh5U2ltKSA8LSBjKG5yb3coZGF0YSksIG5TaW0pCiAgZGVzaWduIDwtIG1vZGVsLm1hdHJpeChmb3JtLCBkYXRhKQogIHlTaW0gPC0geVNpbSArIGMoZGVzaWduICUqJSBiZXRhcykKICB5U2ltIDwtIHQoeVNpbSkKCiAgIyMjIEZpdHRpbmcKICBmaXRBbGwgPC0gbGltbWE6OmxtRml0KHlTaW0sIGRlc2lnbikKCiAgIyMjIEluZmVyZW5jZQogIHZhclVuc2NhbGVkIDwtIGModChjb250cmFzdHMpICUqJSBmaXRBbGwkY292LmNvZWZmaWNpZW50cyAlKiUgY29udHJhc3RzKQogIGNvbnRyYXN0cyA8LSBmaXRBbGwkY29lZmZpY2llbnRzICUqJSBjb250cmFzdHMKICBzZUNvbnRyYXN0cyA8LSB2YXJVbnNjYWxlZF4uNSAqIGZpdEFsbCRzaWdtYQogIHRzdGF0cyA8LSBjb250cmFzdHMgLyBzZUNvbnRyYXN0cwogIHB2YWxzIDwtIHB0KGFicyh0c3RhdHMpLCBmaXRBbGwkZGYucmVzaWR1YWwsIGxvd2VyLnRhaWwgPSBGQUxTRSkgKiAyCiAgcmV0dXJuKG1lYW4ocHZhbHMgPCBhbHBoYSkpCn0KCm5TaW0gPC0gMjAwMDAKYjAgPC0gMApzZCA8LSByb3VuZChtaWNlU3VtJHNkWzJdLCAxKQpucyA8LSBjKDMsIDUsIDEwLCAyMCwgMjUsIDUwLCA3NSwgMTAwKQpkZWx0YXMgPC0gYygxLCAyLCAzLCA1LCAxMCkKCmNvbnRyYXN0IDwtIGxpbW1hOjptYWtlQ29udHJhc3RzKCJEaWV0aGYiLCBsZXZlbHMgPSBjKCIoSW50ZXJjZXB0KSIsICJEaWV0aGYiKSkKCnBvd2VyRmFzdCA8LSBtYXRyaXgoTkEsIG5yb3cgPSBsZW5ndGgobnMpICogbGVuZ3RoKGRlbHRhcyksIG5jb2wgPSAzKSAlPiUgYXMuZGF0YS5mcmFtZSgpCm5hbWVzKHBvd2VyRmFzdCkgPC0gYygiYjEiLCAibiIsICJwb3dlciIpCmZvcm0gPC0gfkRpZXQKCmkgPC0gMAoKZm9yIChuIGluIG5zKQp7CiAgbjEgPC0gbjIgPC0gbgoKICAjIyMgU2ltdWxhdGlvbgogIHByZWRpY3RvckRhdGEgPC0gZGF0YS5mcmFtZShEaWV0ID0gcmVwKGMoImMiLCAiaGYiKSwgYyhuMSwgbjIpKSAlPiUgYXMuZmFjdG9yKCkpCgogIGZvciAoYjEgaW4gZGVsdGFzKQogIHsKICAgIGkgPC0gaSArIDEKICAgIGJldGFzIDwtIGMoYjAsIGIxKQogICAgcG93ZXJGYXN0W2ksIF0gPC0gYyhiMSwgbiwgc2ltRmFzdChmb3JtLCBwcmVkaWN0b3JEYXRhLCBiZXRhcywgc2QsIGNvbnRyYXN0cyA9IGNvbnRyYXN0LCBhbHBoYSA9IGFscGhhLCBuU2ltID0gblNpbSkpCiAgfQp9Cgpwb3dlckZhc3RbcG93ZXJGYXN0JGIxPT0zLDI6M10KYGBgCgpXZSBjYW4gYWxzbyByZXBlYXQgdGhhdCBmb3IgZGlmZmVyZW50IGVmZmVjdCBzaXplcyAKCmBgYHtyIGVjaG8gPSBGQUxTRSwgd2FybmluZyA9IEZBTFNFLCBtZXNzYWdlID0gRkFMU0V9CnBvd2VyRmFzdCRkZWx0YSA8LSBhcy5mYWN0b3IocG93ZXJGYXN0JGIxKQpwb3dlckZhc3QgJT4lCiAgZ2dwbG90KGFlcyh4ID0gbiwgeSA9IHBvd2VyLCBjb2wgPSBkZWx0YSkpICsKICBnZW9tX2xpbmUoKQpgYGAKCg==