Creative Commons License

1 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”

1.1 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!!!!

2 Stages of an experiment

2.1 Stages

  1. Define hypothesis

  2. Experimental design

    • 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
  3. Conduct experiment

  4. Data Analysis

    • QC
    • Preprocessing & Data exploration
    • Statistical inference
  5. Optimisation of your experiment (go back to 2)

  6. Validation

  7. Report your results

Always good to discuss with statistician before the experiment!

3 Sources of variability

3.1 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)

3.2 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)

3.3 Proteomics acquisition

  • LC column (T)
  • Run (T)
  • Technical repeat (T)
  • Labeling (T)
  • Acquisition order

3.4 Observational unit

  • Unit on which the measurement is conducted
  • Cell
  • Cell bulk
  • Animal
  • If observational unit \(\neq\) experimental unit: pseudoreplication

3.5 Avoid confounding

  • Random sampling & Randomisation
  • Blocking

4 Random Sampling & Randomisation

4.1 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.

4.2 Randomisation

  • Make sure that groups are comparable / Avoid systematic differences between groups
  • Randomisation: treatments of interest are attributed at randam to the experimental units

4.3 Consequences of Random sampling & Randomisation

  • The sample is thus supposed to be representative for the population, but still it is random.

  • What does this imply?

4.3.1 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)")

Gender mean sd
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.

4.3.2 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 

4.3.3 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 

4.3.4 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 

4.4 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.

5 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

5.1 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 \(\righarrow\) 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?

5.1.1 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

5.2 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.

5.2.1 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).

6 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 
sd(captopril$SBPb)
[1] 20.56511
sd(captopril$SBPa)
[1] 20.00357
sd(captopril$deltaSBP)
[1] 9.027471

pre-test/post-test experiment

  • Advantage?
  • Problem?

Good control is nessecary

\(\rightarrow\) Placebo controlled double blind experiments
\(\rightarrow\) Injection of control animal with blank containing same solvents, etc.

7 Replication

Within an experiment: Enables to estimate uncertainty / biological variability

  • Replication is essential for quantifying the noise

  • Noise: biological and technical in nature

Between experiments: Any true finding should be reproducible

7.1 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

7.2 Pseudoreplication

  • Samples are not independent e.g.

    • Same batch of reagents
    • Same 96-well plate
    • Leaves from the same plant
    • Cells from the same plate
    • Mice in the same cage or from the same litter
    • Spatially/chronally clustered together (wells on plate, all trt A measured before trt B)
  • Try to avoid pseudo-replication: samples are not independent

    • Contain less info than genuine replicates
    • If analysed as if they were independent \(\rightarrow\) increased number of false positives
    • If not possible e.g. in a multi-subject single cell context, pseudo-replication typically occurs and has to be accounted in the analysis!
    • Consult statistician

7.3 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!!!

7.3.1 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 

7.3.2 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.

7.3.3 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

  • correct analysis:
mean(resCorrect$pvalue < 0.05)
[1] 0.0452
  • wrong analysis:
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!

7.4 How many genuine replicates?

  • For experimental studies: look at randomisation of treatment
  • Double blind study with 20 sputum positive patients randomized to treatment or placebo
  • Mouse study (10 mice)

  • Mouse study (30 mice)

  • Mouse study (10 mice)

8 Blocking

  • Isolate known sources of variability from the experiment
  • One of the most powerful concepts of experimental design
  • Nature methods: Points of significance - Blocking

https://www.nature.com/articles/nmeth.3005.pdf

8.1 Example

9 Implications of different technologies

Slide courtesy (Lisa Breckels)

10 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

10.1 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.

10.2 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

10.3 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

10.3.1 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

10.3.2 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+CgoKVGhpbmtpbmcgYWJvdXQgZGVzaWduIGJlZm9yZSB5b3VyIGV4cGVyaW1lbnQgaXMga2V5ISEhIQoKIyBTdGFnZXMgb2YgYW4gZXhwZXJpbWVudAoKYGBge3Igb3V0LndpZHRoPSc4MCUnLGZpZy5hc3A9LjgsIGZpZy5hbGlnbj0nY2VudGVyJyxlY2hvID0gRkFMU0UsIHdhcm5pbmcgPSBGQUxTRSwgbWVzc2FnZSA9IEZBTFNFfQppZiAoInBpIiAlaW4lIGxzKCkpIHJtKCJwaSIpCmtvcHZvZXRlciA8LSBmdW5jdGlvbih4LCB5LCBhbmdsZSA9IDAsIGwgPSAuMiwgY2V4LmRvdCA9IC41LCBwY2ggPSAxOSwgY29sID0gImJsYWNrIikgewogIGFuZ2xlIDwtIGFuZ2xlIC8gMTgwICogcGkKICBwb2ludHMoeCwgeSwgY2V4ID0gY2V4LmRvdCwgcGNoID0gcGNoLCBjb2wgPSBjb2wpCiAgbGluZXMoYyh4LCB4ICsgbCAqIGNvcygtcGkgLyAyICsgYW5nbGUpKSwgYyh5LCB5ICsgbCAqIHNpbigtcGkgLyAyICsgYW5nbGUpKSwgY29sID0gY29sKQogIGxpbmVzKGMoeCArIGwgLyAyICogY29zKC1waSAvIDIgKyBhbmdsZSksIHggKyBsIC8gMiAqIGNvcygtcGkgLyAyICsgYW5nbGUpICsgbCAvIDQgKiBjb3MoYW5nbGUpKSwgYyh5ICsgbCAvIDIgKiBzaW4oLXBpIC8gMiArIGFuZ2xlKSwgeSArIGwgLyAyICogc2luKC1waSAvIDIgKyBhbmdsZSkgKyBsIC8gNCAqIHNpbihhbmdsZSkpLCBjb2wgPSBjb2wpCiAgbGluZXMoYyh4ICsgbCAvIDIgKiBjb3MoLXBpIC8gMiArIGFuZ2xlKSwgeCArIGwgLyAyICogY29zKC1waSAvIDIgKyBhbmdsZSkgKyBsIC8gNCAqIGNvcyhwaSArIGFuZ2xlKSksIGMoeSArIGwgLyAyICogc2luKC1waSAvIDIgKyBhbmdsZSksIHkgKyBsIC8gMiAqIHNpbigtcGkgLyAyICsgYW5nbGUpICsgbCAvIDQgKiBzaW4ocGkgKyBhbmdsZSkpLCBjb2wgPSBjb2wpCiAgbGluZXMoYyh4ICsgbCAqIGNvcygtcGkgLyAyICsgYW5nbGUpLCB4ICsgbCAqIGNvcygtcGkgLyAyICsgYW5nbGUpICsgbCAvIDIgKiBjb3MoLXBpIC8gMiArIHBpIC8gNCArIGFuZ2xlKSksIGMoeSArIGwgKiBzaW4oLXBpIC8gMiArIGFuZ2xlKSwgeSArIGwgKiBzaW4oLXBpIC8gMiArIGFuZ2xlKSArIGwgLyAyICogc2luKC1waSAvIDIgKyBwaSAvIDQgKyBhbmdsZSkpLCBjb2wgPSBjb2wpCiAgbGluZXMoYyh4ICsgbCAqIGNvcygtcGkgLyAyICsgYW5nbGUpLCB4ICsgbCAqIGNvcygtcGkgLyAyICsgYW5nbGUpICsgbCAvIDIgKiBjb3MoLXBpIC8gMiAtIHBpIC8gNCArIGFuZ2xlKSksIGMoeSArIGwgKiBzaW4oLXBpIC8gMiArIGFuZ2xlKSwgeSArIGwgKiBzaW4oLXBpIC8gMiArIGFuZ2xlKSArIGwgLyAyICogc2luKC1waSAvIDIgLSBwaSAvIDQgKyBhbmdsZSkpLCBjb2wgPSBjb2wpCn0KCnBhcihtYXIgPSBjKDAsIDAsIDAsIDApLCBtYWkgPSBjKDAsIDAsIDAsIDApKQpwbG90KDAsIDAsIHhsYWIgPSAiIiwgeWxhYiA9ICIiLCB4bGltID0gYygwLCAxMCksIHlsaW0gPSBjKDAsIDEwKSwgY29sID0gMCwgeGF4dCA9ICJub25lIiwgeWF4dCA9ICJub25lIiwgYXhlcyA9IEZBTFNFKQpyZWN0KDAsIDYsIDEwLCAxMCwgYm9yZGVyID0gInJlZCIsIGx3ZCA9IDIpCnRleHQoLjUsIDgsICJwb3B1bGF0aW9uIiwgc3J0ID0gOTAsIGNvbCA9ICJyZWQiLCBjZXggPSAyKQpzeW1ib2xzKDMsIDgsIGNpcmNsZXMgPSAxLjUsIGNvbCA9ICJyZWQiLCBhZGQgPSBUUlVFLCBmZyA9ICJyZWQiLCBpbmNoZXMgPSBGQUxTRSwgbHdkID0gMikKc2V0LnNlZWQoMzMwKQpncmlkIDwtIHNlcSgwLCAxLjMsIC4wMSkKCmZvciAoaSBpbiAxOjUwKQp7CiAgYW5nbGUxIDwtIHJ1bmlmKG4gPSAxLCBtaW4gPSAwLCBtYXggPSAzNjApCiAgYW5nbGUyIDwtIHJ1bmlmKG4gPSAxLCBtaW4gPSAwLCBtYXggPSAzNjApCiAgcmFkaXVzIDwtIHNhbXBsZShncmlkLCBwcm9iID0gZ3JpZF4yICogcGkgLyBzdW0oZ3JpZF4yICogcGkpLCBzaXplID0gMSkKICBrb3B2b2V0ZXIoMyArIHJhZGl1cyAqIGNvcyhhbmdsZTEgLyAxODAgKiBwaSksIDggKyByYWRpdXMgKiBzaW4oYW5nbGUxIC8gMTgwICogcGkpLCBhbmdsZSA9IGFuZ2xlMikKfQp0ZXh0KDcuNSwgOCwgIkVmZmVjdCBvZiBkcnVnIG9uIFxuIHByb3Rlb21lIGluIHBvcHVsYXRpb24iLCBjb2wgPSAicmVkIiwgY2V4ID0gMS4yKQoKcmVjdCgwLCAwLCAxMCwgNCwgYm9yZGVyID0gImJsdWUiLCBsd2QgPSAyKQp0ZXh0KC41LCAyLCAic2FtcGxlIiwgc3J0ID0gOTAsIGNvbCA9ICJibHVlIiwgY2V4ID0gMikKc3ltYm9scygzLCAyLCBjaXJjbGVzID0gMS41LCBjb2wgPSAicmVkIiwgYWRkID0gVFJVRSwgZmcgPSAiYmx1ZSIsIGluY2hlcyA9IEZBTFNFLCBsd2QgPSAyKQpmb3IgKGkgaW4gMDoxKSB7CiAgZm9yIChqIGluIDA6NCkKICB7CiAgICBrb3B2b2V0ZXIoMi4xICsgaiAqICgzLjkgLSAyLjEpIC8gNCwgMS4xICsgaSAvIDIsIGNvbCA9ICJwdXJwbGUiKQogIH0KfQpmb3IgKGkgaW4gMjozKSB7CiAgZm9yIChqIGluIDA6NCkKICB7CiAgICBrb3B2b2V0ZXIoMi4xICsgaiAqICgzLjkgLSAyLjEpIC8gNCwgMS42ICsgaSAvIDIsIGNvbCA9ICJvcmFuZ2UiKQogIH0KfQp0ZXh0KDcuNSwgMiwgIkVmZmVjdCBvZiBkcnVnIG9uIFxuIHByb3Rlb21lIGluIHNhbXBsZSIsIGNvbCA9ICJibHVlIiwgY2V4ID0gMS4yKQoKYXJyb3dzKDMsIDUuOSwgMywgNC4xLCBjb2wgPSAiYmxhY2siLCBsd2QgPSAzKQp0ZXh0KDEuNSwgNSwgIkVYUC4gREVTSUdOICgxKSIsIGNvbCA9ICJibGFjayIsIGNleCA9IDEuMikKdGV4dCg3LjUsIC41LCAiREFUQSBFWFBMT1JBVElPTiAmXG5ERVNDUklQVElWRSBTVEFUSVNUSUNTICgyKSIsIGNvbCA9ICJibGFjayIsIGNleCA9IDEuMikKYXJyb3dzKDcsIDQuMSwgNywgNS45LCBjb2wgPSAiYmxhY2siLCBsd2QgPSAzKQp0ZXh0KDguNSwgNSwgIkVTVElNQVRJT04gJlxuSU5GRVJFTkNFICgzKSIsIGNvbCA9ICJibGFjayIsIGNleCA9IDEuMikKYGBgCgojIyBTdGFnZXMgCgoxLiBEZWZpbmUgaHlwb3RoZXNpcwoyLiBFeHBlcmltZW50YWwgZGVzaWduCiAgCiAgICAtIFRlY2hub2xvZ3kKICAgIC0gTGFiIHByb3RvY29sCiAgICAtIFRoaW5rIGFib3V0IHNvdXJjZXMgb2YgdmFyaWF0aW9uIAogICAgLSBDaG9pY2Ugb2YgRGVzaWduCiAgICAtIEV4cGVyaW1lbnRhbCBjb25kaXRpb25zCiAgICAtIFJlcGxpY2F0ZXMKICAgIC0gSG93IHdpbGwgd2UgYW5hbHlzZSB0aGUgZGF0YQogICAgLSBIb3cgY2FuIHdlIHRyYW5zbGF0ZSBvdXIgcmVzZWFyY2ggcXVlc3Rpb24gaW4gYSBxdWFudGl0eSB0aGF0IHdlIGNhbiBtZWFzdXJlIAogICAgLSBQb3dlciBhbmFseXNpcwogIAozLiBDb25kdWN0IGV4cGVyaW1lbnQKNC4gRGF0YSBBbmFseXNpcwoKICAgIC0gUUMKICAgIC0gUHJlcHJvY2Vzc2luZyAmIERhdGEgZXhwbG9yYXRpb24KICAgIC0gU3RhdGlzdGljYWwgaW5mZXJlbmNlCiAgICAKNS4gT3B0aW1pc2F0aW9uIG9mIHlvdXIgZXhwZXJpbWVudCAoZ28gYmFjayB0byAyKQo2LiBWYWxpZGF0aW9uCjcuIFJlcG9ydCB5b3VyIHJlc3VsdHMKCkFsd2F5cyBnb29kIHRvIGRpc2N1c3Mgd2l0aCBzdGF0aXN0aWNpYW4gYmVmb3JlIHRoZSBleHBlcmltZW50ISAKCgojIFNvdXJjZXMgb2YgdmFyaWFiaWxpdHkgCgojIyBFeHBlcmltZW50YWwgdW5pdCAKCi0gQW5pbWFsLCBzdWJqZWN0LCBwbGFudCwgY3VsdHVyZSwgY2FnZSB0byB3aGljaCB0aGUgdHJlYXRtZW50IGlzIHJhbmRvbWl6ZWQKLSBDb2xvbnkgKEIpCi0gU3RyYWluIChCKQotIEN1bHR1cmUgKEIpCi0gVHJlYXRtZW50IC8gQ29uZGl0aW9uIG9mIGludGVyZXN0IChCKQotIENhZ2UgKFQpCi0gU2V4IChCKQotIEluZGl2aWR1YWwgKEIpCi0gTGlmZSBzdHlsZSAoQikKLSAuLi4KCgojIyBTYW1wbGUgcHJlcCAKCi0gT3JnYW5zIGZyb20gc2FjcmlmaWNlZCBhbmltYWwgKEIpCi0gU2luZ2xlIGNlbGxzIChCKQotIFJ1bnMgZm9yIERpc3NvY2lhdGlvbiwgRXh0cmFjdGlvbiBhbmQgRGlnZXN0aW9uIChUKSAKLSBNdWx0aXBpcGV0IC8gcGlwZXRpbmcgcm9ib3QgKFQpCi0gUGxhdGUgKFQpCi0gUG9zaXRpb24gb24gcGxhdGUgKFQpCgojIyBQcm90ZW9taWNzIGFjcXVpc2l0aW9uCgotIExDIGNvbHVtbiAoVCkKLSBSdW4gKFQpCi0gVGVjaG5pY2FsIHJlcGVhdCAoVCkKLSBMYWJlbGluZyAoVCkKLSBBY3F1aXNpdGlvbiBvcmRlcgotIC4uLgoKIyMgT2JzZXJ2YXRpb25hbCB1bml0CgotIFVuaXQgb24gd2hpY2ggdGhlIG1lYXN1cmVtZW50IGlzIGNvbmR1Y3RlZCAKLSBDZWxsCi0gQ2VsbCBidWxrCi0gQW5pbWFsIAotIElmIG9ic2VydmF0aW9uYWwgdW5pdCAkXG5lcSQgZXhwZXJpbWVudGFsIHVuaXQ6IHBzZXVkb3JlcGxpY2F0aW9uCgojIyBBdm9pZCBjb25mb3VuZGluZwoKLSBSYW5kb20gc2FtcGxpbmcgJiBSYW5kb21pc2F0aW9uIAotIEJsb2NraW5nCgoKIyBSYW5kb20gU2FtcGxpbmcgJiBSYW5kb21pc2F0aW9uCgojIyBSYW5kb20gU2FtcGxpbmcKCi0gUmFuZG9tIHNhbXBsaW5nIGlzIGNsb3NlbHkgcmVsYXRlZCB0byB0aGUgY29uY2VwdCBvZiB0aGUgcG9wdWxhdGlvbiBvciB0aGUgc2NvcGUgb2YgdGhlIHN0dWR5LgoKLSBCYXNlZCBvbiBhIHNhbXBsZSBvZiBzdWJqZWN0cywgdGhlIHJlc2VhcmNoZXJzIHdhbnQgdG8gY29tZSB0byBjb25jbHVzaW9ucyB0aGF0IGhvbGQgZm9yCgogICAgLSBhbGwga2luZHMgb2YgcGVvcGxlCiAgICAtIG9ubHkgbWFsZSBzdHVkZW50cwoKLSBTY29wZSBvZiB0aGUgc3R1ZHkgc2hvdWxkIGJlIHdlbGwgc3BlY2lmaWVkIGJlZm9yZSB0aGUgc3RhcnQgb2YgdGhlIHN0dWR5LgoKLSBSZXByZXNlbnRhdGl2ZSBzYW1wbGU6IEZvciB0aGUgc3RhdGlzdGljYWwgYW5hbHlzaXMgdG8gYmUgdmFsaWQsIGl0IGlzIHJlcXVpcmVkIHRoYXQgdGhlIHN1YmplY3RzIGFyZSBzZWxlY3RlZCBjb21wbGV0ZWx5IGF0IHJhbmRvbSBmcm9tIHRoZSBwb3B1bGF0aW9uIHRvIHdoaWNoIHdlIHdhbnQgdG8gZ2VuZXJhbGl6ZSBvdXIgY29uY2x1c2lvbnMuCgotIFNlbGVjdGluZyBjb21wbGV0ZWx5IGF0IHJhbmRvbSBmcm9tIGEgcG9wdWxhdGlvbiBpbXBsaWVzOgogICAgLSBhbGwgc3ViamVjdHMgaW4gdGhlIHBvcHVsYXRpb24gc2hvdWxkIGhhdmUgdGhlIHNhbWUgcHJvYmFiaWxpdHkgb2YgYmVpbmcgc2VsZWN0ZWQgaW4gdGhlIHNhbXBsZSwKICAgIC0gdGhlIHNlbGVjdGlvbiBvZiBhIHN1YmplY3QgaW4gdGhlIHNhbXBsZSBzaG91bGQgYmUgaW5kZXBlbmRlbnQgZnJvbSB0aGUgc2VsZWN0aW9uIG9mIHRoZSBvdGhlciBzdWJqZWN0cyBpbiB0aGUgc2FtcGxlLgoKIyMgUmFuZG9taXNhdGlvbiAKCi0gTWFrZSBzdXJlIHRoYXQgZ3JvdXBzIGFyZSBjb21wYXJhYmxlIC8gQXZvaWQgc3lzdGVtYXRpYyBkaWZmZXJlbmNlcyBiZXR3ZWVuIGdyb3VwcwotIFJhbmRvbWlzYXRpb246IHRyZWF0bWVudHMgb2YgaW50ZXJlc3QgYXJlIGF0dHJpYnV0ZWQgYXQgcmFuZGFtIHRvIHRoZSBleHBlcmltZW50YWwgdW5pdHMKCiMjIENvbnNlcXVlbmNlcyBvZiBSYW5kb20gc2FtcGxpbmcgJiBSYW5kb21pc2F0aW9uIAoKLSBUaGUgc2FtcGxlIGlzIHRodXMgc3VwcG9zZWQgdG8gYmUgcmVwcmVzZW50YXRpdmUgZm9yIHRoZSBwb3B1bGF0aW9uLCBidXQgc3RpbGwgaXQgaXMgcmFuZG9tLgoKLSBXaGF0IGRvZXMgdGhpcyBpbXBseT8KCgoKIyMjIE5hdGlvbmFsIEhlYWx0aCBOSGFuZXMgc3R1ZHkKCiAgLSBTaW5jZSAxOTYwIGluZGl2aWR1YWxzIG9mIGFsbCBhZ2VzIGFyZSBpbnRlcnZpZXdlZCBpbiB0aGVpciBob21lcyBldmVyeSB5ZWFyCiAgLSBUaGUgaGVhbHRoIGV4YW1pbmF0aW9uIGNvbXBvbmVudCBvZiB0aGUgc3VydmV5IGlzIGNvbmR1Y3RlZCBpbiBhIG1vYmlsZSBleGFtaW5hdGlvbiBjZW50cmUgKE1FQykuCiAgLSBXZSB3aWxsIHVzZSB0aGlzIGxhcmdlIHN0dWR5IHRvIHNlbGVjdCByYW5kb20gc3ViamVjdHMgZnJvbSB0aGUgQW1lcmljYW4gcG9wdWxhdGlvbi4KICAtIFRoaXMgd2lsbCBoZWxwIHVzIHRvIHVuZGVyc3RhbmQgaG93IHRoZSByZXN1bHRzIG9mIGFuIGFuYWx5c2lzIGFuZCB0aGUgY29uY2x1c2lvbnMgdmFyeSBmcm9tIHNhbXBsZSB0byBzYW1wbGUuCgpgYGB7cn0KbmhhbmVzU3ViIDwtIE5IQU5FUyAlPiUKICBmaWx0ZXIoQWdlID49IDE4ICYgIWlzLm5hKEhlaWdodCkpICU+JQogIHNlbGVjdChjKCJHZW5kZXIiLCJIZWlnaHQiKSkKCm5oYW5lc1N1YiAlPiUgCiAgZ2dwbG90KGFlcyh4ID0gSGVpZ2h0KSkgKwogIGdlb21faGlzdG9ncmFtKCkgKwogIGZhY2V0X2dyaWQoR2VuZGVyIH4gLikgKwogIHhsYWIoIkhlaWdodCAoY20pIikKYGBgCgpgYGB7ciBlY2hvID0gRkFMU0UsIHdhcm5pbmcgPSBGQUxTRSwgbWVzc2FnZSA9IEZBTFNFfQpIZWlnaHRTdW0gPC0gbmhhbmVzU3ViICU+JQogIGdyb3VwX2J5KEdlbmRlcikgJT4lCiAgc3VtbWFyaXplX2F0KCJIZWlnaHQiLAogICAgICAgICAgICAgICBsaXN0KG1lYW4gPSBtZWFuLAogICAgICAgICAgICAgICBzZCA9IHNkKQogICAgICAgICAgICAgICkKCmtuaXRyOjprYWJsZSgKICBIZWlnaHRTdW0gJT4lCiAgbXV0YXRlX2lmKGlzLm51bWVyaWMsIHJvdW5kLCBkaWdpdHM9MSkKICApCmBgYAoKCi0gRGF0YSBiZWxsLXNoYXBlZCAKLSBBbGxvd3MgdXMgdG8gc3VtbWFyaXplIGRhdGEgd2l0aCB0d28gc3RhdGlzdGljczogbWVhbiBhbmQgc3RhbmRhcmQgZGV2aWF0aW9uIAoKVW5mb3J0dW5hdGVseSB3ZSBjYW5ub3Qgc2FtcGxlIGVudGlyZSBwb3B1bGF0aW9uIQpXZSBoYXZlIHRvIGRyYXcgY29uY2x1c2lvbnMgYmFzZWQgb24gYSBzbWFsbCBzYW1wbGUuIAoKCgojIyMgRXhwZXJpbWVudCAKCgotIFdlIGNhbiBzaW11bGF0ZSBhbiBleHBlcmltZW50IG9uIHRoZSBBbWVyaWNhbiBwb3B1bGF0aW9uIGJ5IHNhbXBsaW5nIGZyb20gdGhlIE5IQU5FUyBzdHVkeSAKLSA1IG1hbGVzIGFuZCA1IGZlbWFsZXMgYWJvdmUgMTggeWVhcnMuIAoKCgpgYGB7ciBlY2hvID0gRkFMU0UsIHdhcm5pbmcgPSBGQUxTRSwgbWVzc2FnZSA9IEZBTFNFfQpzZXQuc2VlZCgyMDApCmZlbSA8LSBuaGFuZXNTdWIgJT4lCiAgZmlsdGVyKEdlbmRlciA9PSAiZmVtYWxlIikgJT4lCiAgc2FtcGxlX24oc2l6ZSA9IDUpCm1hbCA8LSBuaGFuZXNTdWIgJT4lCiAgZmlsdGVyKEdlbmRlciA9PSAibWFsZSIpICU+JQogIHNhbXBsZV9uKHNpemUgPSA1KQoKc2FtcCA8LSByYmluZChmZW0sIG1hbCkKCnNhbXAgJT4lCiAgZ2dwbG90KGFlcyh4ID0gR2VuZGVyLCB5ID0gSGVpZ2h0KSkgKwogIGdlb21fYm94cGxvdChvdXRsaWVyLnNoYXBlID0gTkEpICsKICBnZW9tX3BvaW50KHBvc2l0aW9uID0gImppdHRlciIpCgpzYW1wICU+JQogIGdyb3VwX2J5KEdlbmRlcikgJT4lCiAgc3VtbWFyaXplKAogICAgbWVhbiA9IG1lYW4oSGVpZ2h0LCBuYS5ybSA9IFRSVUUpLAogICAgc2QgPSBzZChIZWlnaHQsIG5hLnJtID0gVFJVRSksCiAgICBuID0gbigpCiAgKSAlPiUKICBtdXRhdGUoc2UgPSBzZCAvIHNxcnQobikpCmBgYAoKTm90ZSB0aGF0IHRoZSBzYW1wbGUgbWVhbiBpcyBkaWZmZXJlbnQgZnJvbSB0aGF0IG9mIHRoZSBsYXJnZSBleHBlcmltZW50ICgicG9wdWxhdGlvbiIpIHdlIHNhbXBsZWQgZnJvbS4KCldlIHRlc3QgZm9yIHRoZSBkaWZmZXJlbmNlIGJldHdlZW4gTWFsZXMgYW5kIGZlbWFsZXMKCmBgYHtyfQp0LnRlc3QoSGVpZ2h0IH4gR2VuZGVyLCBzYW1wLCB2YXIuZXF1YWwgPSBUUlVFKQpgYGAKCiMjIyBSZXBlYXQgZXhwZXJpbWVudCAKCklmIHdlIGRvIHRoZSBleHBlcmltZW50IGFnYWluIHdlIHNlbGVjdCBvdGhlciBwZW9wbGUgYW5kIHdlIG9idGFpbiBkaWZmZXJlbnQgcmVzdWx0cy4KCgpgYGB7ciBlY2hvID0gRkFMU0UsIHdhcm5pbmcgPSBGQUxTRSwgbWVzc2FnZSA9IEZBTFNFfQoKZmVtIDwtIG5oYW5lc1N1YiAlPiUKICBmaWx0ZXIoR2VuZGVyID09ICJmZW1hbGUiKSAlPiUKICBzYW1wbGVfbihzaXplID0gNSkKbWFsIDwtIG5oYW5lc1N1YiAlPiUKICBmaWx0ZXIoR2VuZGVyID09ICJtYWxlIikgJT4lCiAgc2FtcGxlX24oc2l6ZSA9IDUpCgpzYW1wIDwtIHJiaW5kKGZlbSwgbWFsKQoKCnNhbXAgJT4lCiAgZ2dwbG90KGFlcyh4ID0gR2VuZGVyLCB5ID0gSGVpZ2h0KSkgKwogIGdlb21fYm94cGxvdChvdXRsaWVyLnNoYXBlID0gTkEpICsKICBnZW9tX3BvaW50KHBvc2l0aW9uID0gImppdHRlciIpCgpzYW1wICU+JQogIGdyb3VwX2J5KEdlbmRlcikgJT4lCiAgc3VtbWFyaXplKAogICAgbWVhbiA9IG1lYW4oSGVpZ2h0LCBuYS5ybSA9IFRSVUUpLAogICAgc2QgPSBzZChIZWlnaHQsIG5hLnJtID0gVFJVRSksCiAgICBuID0gbigpCiAgKSAlPiUKICBtdXRhdGUoc2UgPSBzZCAvIHNxcnQobikpCgp0LnRlc3QoSGVpZ2h0IH4gR2VuZGVyLCBzYW1wLCB2YXIuZXF1YWwgPSBUUlVFKQpgYGAKCiMjIyBBbmQgYWdhaW4gCgoKYGBge3IgZWNobyA9IEZBTFNFLCB3YXJuaW5nID0gRkFMU0UsIG1lc3NhZ2UgPSBGQUxTRX0Kc2VlZCA8LSA4ODYwNQpzZXQuc2VlZChzZWVkKQpmZW0gPC0gbmhhbmVzU3ViICU+JQogIGZpbHRlcihHZW5kZXIgPT0gImZlbWFsZSIpICU+JQogIHNhbXBsZV9uKHNpemUgPSA1KQptYWwgPC0gbmhhbmVzU3ViICU+JQogIGZpbHRlcihHZW5kZXIgPT0gIm1hbGUiKSAlPiUKICBzYW1wbGVfbihzaXplID0gNSkKCnNhbXAgPC0gcmJpbmQoZmVtLCBtYWwpCgoKc2FtcCAlPiUKICBnZ3Bsb3QoYWVzKHggPSBHZW5kZXIsIHkgPSBIZWlnaHQpKSArCiAgZ2VvbV9ib3hwbG90KG91dGxpZXIuc2hhcGUgPSBOQSkgKwogIGdlb21fcG9pbnQocG9zaXRpb24gPSAiaml0dGVyIikKCnNhbXAgJT4lCiAgZ3JvdXBfYnkoR2VuZGVyKSAlPiUKICBzdW1tYXJpemUoCiAgICBtZWFuID0gbWVhbihIZWlnaHQsIG5hLnJtID0gVFJVRSksCiAgICBzZCA9IHNkKEhlaWdodCwgbmEucm0gPSBUUlVFKSwKICAgIG4gPSBuKCkKICApICU+JQogIG11dGF0ZShzZSA9IHNkIC8gc3FydChuKSkKCnQudGVzdChIZWlnaHQgfiBHZW5kZXIsIHNhbXAsIHZhci5lcXVhbCA9IFRSVUUpCmBgYAoKCiMjIFN1bW1hcnkKCi0gV2UgZHJldyBhdCByYW5kb20gZGlmZmVyZW50IHN1YmplY3RzIGluIGVhY2ggc2FtcGxlCi0gQXMgYSByZXN1bHQsIGxlbmd0aCBtZWFzdXJlbWVudHMgdmFyeSBmcm9tIHNhbXBsZSB0byBzYW1wbGUuCi0gU28gZG8gdGhlIGVzdGltYXRlZCBtZWFucyBhbmQgc3RhbmRhcmQgZGV2aWF0aW9ucy4KLSBDb25zZXF1ZW50bHksIG91ciBjb25jbHVzaW9ucyBhcmUgYWxzbyB1bmNlcnRhaW4gYW5kIG1heSBjaGFuZ2UgZnJvbSBzYW1wbGUgdG8gc2FtcGxlLgoKLSBGb3IgdGhlIGxlbmd0aCBleGFtcGxlLCBzYW1wbGVzIHdoZXJlIHRoZSBlZmZlY3QgaXMgb3Bwb3NpdGUgdG8gdGhhdCBpbiB0aGUgcG9wdWxhdGlvbiBhbmQgd2hlcmUgd2UgZGVjaWRlIHRoYXQgdGhlIGRpZmZlcmVuY2UgaXMgc2lnbmlmaWNhbnQgYXJlIHJhcmUuCgokXHJpZ2h0YXJyb3ckIFdpdGggc3RhdGlzdGljcywgd2UgY29udHJvbCBmb3IgdGhlIHByb2JhYmlsaXR5IG9mIGRyYXdpbmcgd3JvbmcgY29uY2x1c2lvbnMuCgoKIyBDb250cm9sIG9mIERlY2lzaW9uIEVycm9ycyAKCldlIGhhdmUgdHdvIHR5cGVzIG9mIGVycm9yczogCgotIGZhbHNlIG5lZ2F0aXZlczogdGhlcmUgaXMgYW4gZWZmZWN0IGJ1dCB3ZSBkbyBub3QgcGljayBpdCB1cAotIGZhbHNlIHBvc2l0aXZlczogdGhlcmUgaXMgbm8gZWZmZWN0IGJ1dCB3ZSByZXBvcnQgYSBkaWZmZXJlbmNlIGJldHdlZW4gYm90aCBncm91cHMKCiMjIENvbnRyb2wgb2YgZmFsc2UgbmVnYXRpdmVzCgoKLSBXZSByZXBlYXQgdGhlIGV4cGVyaW1lbnQgd2l0aCA1IGZlbWFsZXMgYW5kIDUgbWFsZXMgMTAwMDAgdGltZXMuIAoKYGBge3IgZWNobyA9RkFMU0V9CnNldC5zZWVkKDE1MTUyKQojIEFhbnRhbCBzaW11bGF0aWVzIGVuIHN0ZWVrcHJvZWZncm9vdHRlIHBlciBncm9lcApuU2ltIDwtIDEwMDAwCm5TYW1wIDwtIDUKCiMgV2UgZmlsdGVyZW4gZGUgZGF0YSB2b29yYWYgem9kYXQgd2UgZGl0IG5pZXQgdGVsa2VucyBvcG5pZXV3IGhvZXZlbiB0ZSBkb2VuCmZlbSA8LSBuaGFuZXNTdWIgJT4lCiAgZmlsdGVyKEdlbmRlciA9PSAiZmVtYWxlIikKCm1hbCA8LSBuaGFuZXNTdWIgJT4lCiAgZmlsdGVyKEdlbmRlciA9PSAibWFsZSIpCgojIFNpbXVsYXRpZSBzdHVkaWUKIyBPbSBzbmVsbGUgZnVuY3RpZXMgdGUga3VubmVuIGdlYnJ1aWtlbiBuZW1lbiB3ZSBlZXJzdCBuU2ltIHN0ZWVrcHJvZXZlbiBlbiBiZXJla2VuZW4gd2UgZGFhcm5hIGFsbGVzLgoKZmVtU2FtcHMgPC0gbWFsU2FtcHMgPC1tYXRyaXgoTkEsIG5yb3c9blNhbXAsIG5jb2w9blNpbSkKZm9yIChpIGluIDE6blNpbSkKewogIGZlbVNhbXBzWyxpXSA8LSBzYW1wbGUoZmVtJEhlaWdodCwgblNhbXApCiAgbWFsU2FtcHNbLGldIDwtIHNhbXBsZShtYWwkSGVpZ2h0LCBuU2FtcCkKfQoKcmVzIDwtIGRhdGEuZnJhbWUoCiAgdmVyc2NoaWw9Y29sTWVhbnMoZmVtU2FtcHMpIC0gY29sTWVhbnMobWFsU2FtcHMpLAogIFJmYXN0Ojp0dGVzdHMoZmVtU2FtcHMsIG1hbFNhbXBzKQogICkKCgpyZXMgJT4lCiAgZ2dwbG90KGFlcyh4PXZlcnNjaGlsLHk9LWxvZzEwKHB2YWx1ZSksY29sb3I9cHZhbHVlIDwgMC4wNSkpICsKICBnZW9tX3BvaW50KCkgKwogIHhsYWIoIkF2ZXJhZ2UgaGVpZ2h0IGRpZmZlcmVuY2UgKGNtKSIpICsKICB5bGFiKCJTdGF0aXN0aWNhbCBTaWduaWZpY2FuY2UgKC1sb2cxMCBwKSIpCgpmYWxzZU5lZzVCb3ggPC0gcmVzICU+JQogIGdncGxvdChhZXMoeSA9IHZlcnNjaGlsKSkgKwogIGdlb21fYm94cGxvdCgpICsKICB5bGFiKCJBdmVyYWdlIGhlaWdodCBkaWZmZXJlbmNlIChjbSkiKQogIHhsYWIoIiIpCgpmYWxzZU5lZzVCb3gKYGBgCgotIFRoZXJlIGFyZSBgciBzdW0ocmVzJHB2YWx1ZSA8IDAuMDUgJiByZXMkdmVyc2NoaWwgPCAwKWAgc2FtcGxlcyBmb3Igd2hpY2ggd2UgcmV0dXJuIGEgdHJ1ZSBwb3NpdGl2ZSAkXHJpZ2hhcnJvdyQgVGhlIHBvd2VyIGlzIGByIHJvdW5kKG1lYW4ocmVzJHB2YWx1ZSA8IDAuMDUgJiByZXMkdmVyc2NoaWwgPCAwKSoxMDAsMSlgJS4KLSBUaGVyZSBhcmUgYHIgc3VtKHJlcyRwdmFsdWUgPiAwLjA1KWAgc2FtcGxlcyBmb3Igd2hpY2ggd2UgY2Fubm90IHJlcG9ydCBhIHNpZ25pZmljYW50IGRpZmZlcmVuY2UuIAotIFRoZXJlIGFyZSBgciAgc3VtKHJlcyRwdmFsdWUgPCAwLjA1ICYgcmVzJHZlcnNjaGlsPjApYCBmb3Igd2hpY2ggd2UgcmVwb3J0IGEgc2lnbmlmaWNhbnQgaGVpZ2h0IGRpZmZlcmVuY2UgYmV0d2VlbiBmZW1hbGVzIGFuZCBtYWxlcyB0aGF0IGlzIHBvc2l0aXZlLgoKCgotIFRoZSBzYW1wbGUgdGhhdCB3ZSBoYXZlIHNob3duIHdoZXJlIHdlIGNvbmNsdWRlZCB0aGF0IGZlbWFsZXMgd2VyZSBsYXJnZXIgdGhhbiBtYWxlcyB3YXMgdmVyeSB1bmxpa2VseS4gV2UgaGFkIHRvIGRyYXcgYHIgZm9ybWF0KHNlZWQsZGlnaXRzPTUpYCBzYW1wbGVzIGJlZm9yZSB3ZSB3ZXJlIGFibGUgdG8gZmluZCBzdWNoIGFuIGV4dHJlbWUgc2FtcGxlLiAKCi0gV2h5IGRvIHdlIGhhdmUgYSBjb25zaWRlcmFibGUgbnVtYmVyIG9mIHNhbXBsZXMgZm9yIHdoaWNoIHdlIGRvIG5vdCBmaW5kIGEgc2lnbmlmaWNhbnQgaGVpZ2h0IGRpZmZlcmVuY2UgYmV0d2VlbiBtYWxlcyBhbmQgZmVtYWxlcz8gCgojIyMgTGFyZ2VyIHNhbXBsZSBzaXplIAoKV2hlbiB3ZSB0YWtlIDIwIHN1YmplY3RzIGluIGVhY2ggZ3JvdXA6IAoKYGBge3IgZWNobyA9RkFMU0V9CnNldC5zZWVkKDE1MTUyKQojIEFhbnRhbCBzaW11bGF0aWVzIGVuIHN0ZWVrcHJvZWZncm9vdHRlIHBlciBncm9lcApuU2ltIDwtIDEwMDAwCm5TYW1wIDwtIDIwCgojIFdlIGZpbHRlcmVuIGRlIGRhdGEgdm9vcmFmIHpvZGF0IHdlIGRpdCBuaWV0IHRlbGtlbnMgb3BuaWV1dyBob2V2ZW4gdGUgZG9lbgpmZW0gPC0gbmhhbmVzU3ViICU+JQogIGZpbHRlcihHZW5kZXIgPT0gImZlbWFsZSIpCgptYWwgPC0gbmhhbmVzU3ViICU+JQogIGZpbHRlcihHZW5kZXIgPT0gIm1hbGUiKQoKIyBTaW11bGF0aWUgc3R1ZGllCiMgT20gc25lbGxlIGZ1bmN0aWVzIHRlIGt1bm5lbiBnZWJydWlrZW4gbmVtZW4gd2UgZWVyc3QgblNpbSBzdGVla3Byb2V2ZW4gZW4gYmVyZWtlbmVuIHdlIGRhYXJuYSBhbGxlcy4KCmZlbVNhbXBzIDwtIG1hbFNhbXBzIDwtbWF0cml4KE5BLCBucm93PW5TYW1wLCBuY29sPW5TaW0pCmZvciAoaSBpbiAxOm5TaW0pCnsKICBmZW1TYW1wc1ssaV0gPC0gc2FtcGxlKGZlbSRIZWlnaHQsIG5TYW1wKQogIG1hbFNhbXBzWyxpXSA8LSBzYW1wbGUobWFsJEhlaWdodCwgblNhbXApCn0KCnJlcyA8LSBkYXRhLmZyYW1lKAogIHZlcnNjaGlsPWNvbE1lYW5zKGZlbVNhbXBzKSAtIGNvbE1lYW5zKG1hbFNhbXBzKSwKICBSZmFzdDo6dHRlc3RzKGZlbVNhbXBzLCBtYWxTYW1wcykKICApCgoKcmVzICU+JQogIGdncGxvdChhZXMoeD12ZXJzY2hpbCx5PS1sb2cxMChwdmFsdWUpLGNvbG9yPXB2YWx1ZSA8IDAuMDUpKSArCiAgZ2VvbV9wb2ludCgpICsKICB4bGFiKCJBdmVyYWdlIGhlaWdodCBkaWZmZXJlbmNlIChjbSkiKSArCiAgeWxhYigiU3RhdGlzdGljYWwgU2lnbmlmaWNhbmNlICgtbG9nMTAgcCkiKQoKZmFsc2VOZWcyMEJveCA8LSByZXMgJT4lCiAgZ2dwbG90KGFlcyh5ID0gdmVyc2NoaWwpKSArCiAgZ2VvbV9ib3hwbG90KCkgKwogIHlsYWIoIkF2ZXJhZ2UgaGVpZ2h0IGRpZmZlcmVuY2UgKGNtKSIpCiAgeGxhYigiIikKICAKZmFsc2VOZWcyMEJveApgYGAKCgoKTGFyZ2VyIHNhbXBsZSBzaXplOiAKCi0gTGFyZ2VyIHBvd2VyIHRvIHBpY2sgdXAgYSByZWFsIGRpZmZlcmVuY2UgaW4gdGhlIHBvcHVsYXRpb24uIAotIE1lYW4gaXMgbW9yZSBwcmVjaXNlIAoKYGBge3IgZWNobz1GQUxTRSwgd2FybmluZz1GQUxTRSwgbWVzc2FnZT1GQUxTRX0KZ3JpZC5hcnJhbmdlKGZhbHNlTmVnNUJveCArIGdndGl0bGUoIm4xID0gbjIgPSA1IikgKyB5bGltKC00MCwxMCksZmFsc2VOZWcyMEJveCArIGdndGl0bGUoIm4xID0gbjIgPSAyMCIpICsgeWxpbSgtNDAsMTApLG5yb3c9MSkKYGBgCgoKCiMjIENvbnRyb2wgb2YgZmFsc2UgcG9zaXRpdmVzCgotIFN1cHBvc2UgdGhhdCB3ZSBzZXQgdXAgYW4gZXhwZXJpbWVudCB3aXRoIHR3byBncm91cHMgdGhhdCBhcmUgYm90aCBzYW1wbGVkIGZyb20gdGhlIGZlbWFsZXMgaW4gdGhlIE5IQU5FUyBzdHVkeQotIEJvdGggZ3JvdXBzIGNvbWUgZnJvbSB0aGUgc2FtZSBwb3B1bGF0aW9uOiBzbyBubyBkaWZmZXJlbmNlCgotIFdlIGFnYWluIGRyYXcgcmVwZWF0ZWQgZXhwZXJpbWVudHMgd2l0aCA1IHN1YmplY3RzIGluIGVhY2ggZ3JvdXAuIAoKCmBgYHtyIGVjaG8gPSBGQUxTRSwgd2FybmluZyA9IEZBTFNFLCBtZXNzYWdlID0gRkFMU0V9CnNldC5zZWVkKDEzMjQpCiMgQWFudGFsIHNpbXVsYXRpZXMgZW4gc3RlZWtwcm9lZmdyb290dGUgcGVyIGdyb2VwCm5TaW0gPC0gMTAwMDAKblNhbXAgPC0gNQoKIyBXZSBmaWx0ZXJlbiBkZSBkYXRhIHZvb3JhZiB6b2RhdCB3ZSBkaXQgbmlldCB0ZWxrZW5zIG9wbmlldXcgaG9ldmVuIHRlIGRvZW4KZmVtIDwtIG5oYW5lc1N1YiAlPiUKICBmaWx0ZXIoR2VuZGVyID09ICJmZW1hbGUiKQoKIyBTaW11bGF0aWUgc3R1ZGllCiMgT20gc25lbGxlIGZ1bmN0aWVzIHRlIGt1bm5lbiBnZWJydWlrZW4gbmVtZW4gd2UgZWVyc3QgblNpbSBzdGVla3Byb2V2ZW4gZW4gYmVyZWtlbmVuIHdlIGRhYXJuYSBhbGxlcy4KCmZlbVNhbXBzIDwtIGZlbVNhbXBzMiA8LW1hdHJpeChOQSwgbnJvdz1uU2FtcCwgbmNvbD1uU2ltKQpmb3IgKGkgaW4gMTpuU2ltKQp7CiAgZmVtU2FtcHNbLGldIDwtIHNhbXBsZShmZW0kSGVpZ2h0LCBuU2FtcCkKICBmZW1TYW1wczJbLGldIDwtIHNhbXBsZShmZW0kSGVpZ2h0LCBuU2FtcCkKfQoKcmVzIDwtIGRhdGEuZnJhbWUoCiAgdmVyc2NoaWw9Y29sTWVhbnMoZmVtU2FtcHMpIC0gY29sTWVhbnMoZmVtU2FtcHMyKSwKICBSZmFzdDo6dHRlc3RzKGZlbVNhbXBzLCBmZW1TYW1wczIpCiAgKQoKCnJlcyAlPiUKICBnZ3Bsb3QoYWVzKHg9dmVyc2NoaWwseT0tbG9nMTAocHZhbHVlKSxjb2xvcj1wdmFsdWUgPCAwLjA1KSkgKwogIGdlb21fcG9pbnQoKSArCiAgeGxhYigiQXZlcmFnZSBoZWlnaHQgZGlmZmVyZW5jZSAoY20pIikgKwogIHlsYWIoIlN0YXRpc3RpY2FsIFNpZ25pZmljYW5jZSAoLWxvZzEwIHApIikKCmZhbHNlUG9zNUJveCA8LSByZXMgJT4lCiAgZ2dwbG90KGFlcyh5ID0gdmVyc2NoaWwpKSArCiAgZ2VvbV9ib3hwbG90KCkgKwogIHlsYWIoIkF2ZXJhZ2UgaGVpZ2h0IGRpZmZlcmVuY2UgKGNtKSIpCiAgeGxhYigiIikKICAKZmFsc2VQb3M1Qm94CmBgYAoKLSBPbmx5IGluIGByIHN1bShyZXMkcHZhbHVlPDAuMDUpYCBvdXQgb2YgYHIgZm9ybWF0KG5TaW0sZGlnaXRzPTUpYCBzYW1wbGVzIHdlIGNvbmNsdWRlIHRoYXQgdGhlIG1lYW4gaW4gYm90aCBncm91cHMgYXJlIGRpZmZlcmVudCBvciBpbiBgciByb3VuZChtZWFuKHJlcyRwdmFsdWU8MC4wNSkqMTAwLDEpYCUgb2YgdGhlIHNhbXBsZXMuCgotIFdpdGggdGhlIHN0YXRpc3RpY2FsIGFuYWx5c2lzIHdlIGNhbiBjb250cm9sIHRoZSBudW1iZXIgb2YgZmFsc2UgcG9zaXRpdmUgcmVzdWx0cyBjb3JyZWN0bHkgYXQgdGhlIDUlIHNpZ25pZmljYW5jZSBsZXZlbC4gCgojIyMgTGFyZ2VyIHNhbXBsZSBzaXplIAoKV2UgcGVyZm9ybSB0aGUgc2ltdWxhdGlvbnMgYWdhaW4gd2l0aCAyMCBzdWJqZWN0cyBpbiBlYWNoIGdyb3VwLiAKCgoKCmBgYHtyIGVjaG8gPSBGQUxTRSwgd2FybmluZyA9IEZBTFNFLCBtZXNzYWdlID0gRkFMU0V9CnNldC5zZWVkKDEzMjQpCiMgQWFudGFsIHNpbXVsYXRpZXMgZW4gc3RlZWtwcm9lZmdyb290dGUgcGVyIGdyb2VwCm5TaW0gPC0gMTAwMDAKblNhbXAgPC0gMjAKCiMgV2UgZmlsdGVyZW4gZGUgZGF0YSB2b29yYWYgem9kYXQgd2UgZGl0IG5pZXQgdGVsa2VucyBvcG5pZXV3IGhvZXZlbiB0ZSBkb2VuCmZlbSA8LSBuaGFuZXNTdWIgJT4lCiAgZmlsdGVyKEdlbmRlciA9PSAiZmVtYWxlIikKCiMgU2ltdWxhdGllIHN0dWRpZQojIE9tIHNuZWxsZSBmdW5jdGllcyB0ZSBrdW5uZW4gZ2VicnVpa2VuIG5lbWVuIHdlIGVlcnN0IG5TaW0gc3RlZWtwcm9ldmVuIGVuIGJlcmVrZW5lbiB3ZSBkYWFybmEgYWxsZXMuCgpmZW1TYW1wcyA8LSBmZW1TYW1wczIgPC1tYXRyaXgoTkEsIG5yb3c9blNhbXAsIG5jb2w9blNpbSkKZm9yIChpIGluIDE6blNpbSkKewogIGZlbVNhbXBzWyxpXSA8LSBzYW1wbGUoZmVtJEhlaWdodCwgblNhbXApCiAgZmVtU2FtcHMyWyxpXSA8LSBzYW1wbGUoZmVtJEhlaWdodCwgblNhbXApCn0KCnJlcyA8LSBkYXRhLmZyYW1lKAogIHZlcnNjaGlsPWNvbE1lYW5zKGZlbVNhbXBzKSAtIGNvbE1lYW5zKGZlbVNhbXBzMiksCiAgUmZhc3Q6OnR0ZXN0cyhmZW1TYW1wcywgZmVtU2FtcHMyKQogICkKCgpyZXMgJT4lCiAgZ2dwbG90KGFlcyh4PXZlcnNjaGlsLHk9LWxvZzEwKHB2YWx1ZSksY29sb3I9cHZhbHVlIDwgMC4wNSkpICsKICBnZW9tX3BvaW50KCkgKwogIHhsYWIoIkF2ZXJhZ2UgaGVpZ2h0IGRpZmZlcmVuY2UgKGNtKSIpICsKICB5bGFiKCJTdGF0aXN0aWNhbCBTaWduaWZpY2FuY2UgKC1sb2cxMCBwKSIpCgpmYWxzZVBvczIwQm94IDwtIHJlcyAlPiUKICBnZ3Bsb3QoYWVzKHkgPSB2ZXJzY2hpbCkpICsKICBnZW9tX2JveHBsb3QoKSArCiAgeWxhYigiQXZlcmFnZSBoZWlnaHQgZGlmZmVyZW5jZSAoY20pIikKICB4bGFiKCIiKQoKZmFsc2VQb3MyMEJveApgYGAKCgoKCi0gT25seSBpbiBgciBzdW0ocmVzJHB2YWx1ZTwwLjA1KWAgb3V0IG9mIGByIGZvcm1hdChuU2ltLGRpZ2l0cz01KWAgc2FtcGxlcyB3ZSBjb25jbHVkZSB0aGF0IHRoZSBtZWFuIGluIGJvdGggZ3JvdXBzIGFyZSBkaWZmZXJlbnQgb3IgaW4gYHIgcm91bmQobWVhbihyZXMkcHZhbHVlPDAuMDUpKjEwMCwxKWAlIG9mIHRoZSBzYW1wbGVzLgoKCi0gU28gd2l0aCB0aGUgc3RhdGlzdGljYWwgYW5hbHlzaXMsIGFsc28gd2hlbiB0YWtpbmcgYSBsYXJnZSBzYW1wbGUsIHdlIGNvcnJlY3RseSBjb250cm9sIHRoZSBudW1iZXIgb2YgZmFsc2UgcG9zaXRpdmUgcmVzdWx0cyBhdCA1JS4KCi0gVGhlIG1lYW4gZGlmZmVyZW5jZSBpcyBhZ2FpbiBtb3JlIGFjY3VyYXRlbHkgZXN0aW1hdGVkIChmbHVjdHVhdGluZyBsZXNzIGFyb3VuZCB0aGUgcmVhbCBkaWZmZXJlbmNlIG9mIDApLiAKCgpgYGB7ciBlY2hvPUZBTFNFLCB3YXJuaW5nPUZBTFNFLCBtZXNzYWdlPUZBTFNFfQpncmlkLmFycmFuZ2UoZmFsc2VQb3M1Qm94ICsgZ2d0aXRsZSgibjEgPSBuMiA9IDUiKSArIHlsaW0oLTIwLDIwKSxmYWxzZVBvczIwQm94ICsgZ2d0aXRsZSgibjEgPSBuMiA9IDIwIikgKyB5bGltKC0yMCwyMCksbnJvdz0xKQpgYGAKCgoKIyBDb250cm9sIHRyZWF0bWVudAoKQ2FwdG9wcmlsIHN0dWR5OiBTQlAgYmVmb3JlIGFuZCBhZnRlciBkb3NpZ24gY2FwdG9wcmlsLgoKYGBge3IgZWNobz1GQUxTRSwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KY2FwdG9wcmlsIDwtIHJlYWQudGFibGUoImh0dHBzOi8vcmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbS9zdGF0T21pY3Mvc2JjL21hc3Rlci9kYXRhL2NhcHRvcHJpbC50eHQiLGhlYWRlcj1UUlVFLHNlcD0iLCIpCmNhcHRvcHJpbFRpZHkgPC0gY2FwdG9wcmlsICU+JSBnYXRoZXIodHlwZSxicCwtaWQpCmNhcHRvMSA8LSBjYXB0b3ByaWxUaWR5ICU+JQogIGZpbHRlcih0eXBlJWluJWMoIlNCUGEiLCJTQlBiIikpICU+JQogIG11dGF0ZSh0eXBlPWZhY3Rvcih0eXBlLGxldmVscz1jKCJTQlBiIiwiU0JQYSIpKSkgJT4lCiAgZ2dwbG90KGFlcyh4PXR5cGUseT1icCkpICsKICBnZW9tX2xpbmUoYWVzKGdyb3VwID0gaWQpKSArCiAgZ2VvbV9wb2ludCgpCgpkZWx0YSA8LSBjYXB0b3ByaWwkU0JQYS1jYXB0b3ByaWwkU0JQYgpjYXB0b3ByaWwkZGVsdGFTQlAgPC0gZGVsdGEKY2FwdG8yIDwtIGNhcHRvcHJpbCAlPiUKICBnZ3Bsb3QoYWVzKHg9IlN5c3RvbGljIGJsb29kIHByZXNzdXJlIix5PWRlbHRhU0JQKSkgKwogIGdlb21fYm94cGxvdChvdXRsaWVyLnNoYXBlPU5BKSArCiAgZ2VvbV9wb2ludChwb3NpdGlvbj0iaml0dGVyIikrCiAgeWxhYigiRGlmZmVyZW5jZSAobW0gbWVyY3VyeSkiKSArCiAgeGxhYigiIikKCmdyaWQuYXJyYW5nZShjYXB0bzEsIGNhcHRvMiwgbnJvdz0xKQoKd2l0aChjYXB0b3ByaWwsIHQudGVzdCgKICAgICAgICAgICAgIFNCUGEsCiAgICAgICAgICAgICBTQlBiLAogICAgICAgICAgICAgcGFpcmVkPVRSVUUpKQoKYGBgCmBgYHtyfQpzZChjYXB0b3ByaWwkU0JQYikKc2QoY2FwdG9wcmlsJFNCUGEpCnNkKGNhcHRvcHJpbCRkZWx0YVNCUCkKYGBgCgpwcmUtdGVzdC9wb3N0LXRlc3QgZXhwZXJpbWVudAoKLSBBZHZhbnRhZ2U/Ci0gUHJvYmxlbT8KCi0tLQoKPGltZyBzcmM9Ii4vZmlndXJlcy9wbGFjZWJvLnBuZyIgd2lkdGg9IjIwJSIgc3R5bGU9ImZsb2F0OiByaWdodDsiPgoKR29vZCBjb250cm9sIGlzIG5lc3NlY2FyeSAKCiRccmlnaHRhcnJvdyQgUGxhY2VibyBjb250cm9sbGVkIGRvdWJsZSBibGluZCBleHBlcmltZW50cyAgICAgCiRccmlnaHRhcnJvdyQgSW5qZWN0aW9uIG9mIGNvbnRyb2wgYW5pbWFsIHdpdGggYmxhbmsgY29udGFpbmluZyBzYW1lIHNvbHZlbnRzLCBldGMuIAoKIyBSZXBsaWNhdGlvbgoKCldpdGhpbiBhbiBleHBlcmltZW50OiBFbmFibGVzIHRvIGVzdGltYXRlIHVuY2VydGFpbnR5IC8gYmlvbG9naWNhbCB2YXJpYWJpbGl0eQoKLSBSZXBsaWNhdGlvbiBpcyBlc3NlbnRpYWwgZm9yIHF1YW50aWZ5aW5nIHRoZSBub2lzZQoKLSBOb2lzZTogYmlvbG9naWNhbCBhbmQgdGVjaG5pY2FsIGluIG5hdHVyZQoKQmV0d2VlbiBleHBlcmltZW50czogQW55IHRydWUgZmluZGluZyBzaG91bGQgYmUgcmVwcm9kdWNpYmxlCgoKCiMjIEF0IHdoaWNoIGxldmVsIGRvIHdlIGhhdmUgdG8gcmVwbGljYXRlPyAKCi0gR2VudWluZSByZXBsaWNhdGVzIGluY2x1ZGUgYWxsIHNvdXJjZXMgb2YgdmFyaWFiaWxpdHk6IHRlY2huaWNhbCArIGJpb2xvZ2ljYWwKLSBUZWNobmljYWwgcmVwbGljYXRlcyBhcmUgaW1wb3J0YW50IGlmIHlvdSBhc3Nlc3MgbmV3IHRlY2hub2xvZ2llcwoKIVtdKC4vZmlndXJlcy9zdW1WYXJDb21wLnBuZykKCiMjIFBzZXVkb3JlcGxpY2F0aW9uCgotIFNhbXBsZXMgYXJlIG5vdCBpbmRlcGVuZGVudCBlLmcuCiAgICAKICAgIC0gU2FtZSBiYXRjaCBvZiByZWFnZW50cwogICAgLSBTYW1lIDk2LXdlbGwgcGxhdGUKICAgIC0gTGVhdmVzIGZyb20gdGhlIHNhbWUgcGxhbnQKICAgIC0gQ2VsbHMgZnJvbSB0aGUgc2FtZSBwbGF0ZQogICAgLSBNaWNlIGluIHRoZSBzYW1lIGNhZ2Ugb3IgZnJvbSB0aGUgc2FtZSBsaXR0ZXIKICAgIC0gU3BhdGlhbGx5L2Nocm9uYWxseSBjbHVzdGVyZWQgdG9nZXRoZXIgKHdlbGxzIG9uIHBsYXRlLCBhbGwgdHJ0IEEgbWVhc3VyZWQgYmVmb3JlIHRydCBCKQoKLSBUcnkgdG8gYXZvaWQgcHNldWRvLXJlcGxpY2F0aW9uOiBzYW1wbGVzIGFyZSBub3QgaW5kZXBlbmRlbnQgCgogICAgLSBDb250YWluIGxlc3MgaW5mbyB0aGFuIGdlbnVpbmUgcmVwbGljYXRlcwogICAgLSBJZiBhbmFseXNlZCBhcyBpZiB0aGV5IHdlcmUgaW5kZXBlbmRlbnQgJFxyaWdodGFycm93JCBpbmNyZWFzZWQgbnVtYmVyIG9mIGZhbHNlIHBvc2l0aXZlcwogICAgLSBJZiBub3QgcG9zc2libGUgZS5nLiBpbiBhIG11bHRpLXN1YmplY3Qgc2luZ2xlIGNlbGwgY29udGV4dCwgcHNldWRvLXJlcGxpY2F0aW9uIHR5cGljYWxseSBvY2N1cnMgYW5kIGhhcyB0byBiZSBhY2NvdW50ZWQgaW4gdGhlIGFuYWx5c2lzISAKICAgIC0gQ29uc3VsdCBzdGF0aXN0aWNpYW4KCgojIyBGcmFuY2lzZWxsYSB0dWxhcmVuc2lzIHN0dWR5IFJhbW9uZCBldCBhbC4gKDIwMTUpCgotIFByb3Rlb21lIG9mIHdpbGQgdHlwZSBGLiB0dWxhcmVuc2lzIChXVCkgdnMgQXJnUC1nZW5lIGRlbGV0ZWQgRi4gdHVsYXJlbnNpcyAoa25vY2stb3V0LCBEOCkuCi0gRWFjaCBiaW8tcmVwIGluIHRlY2huaWNhbCB0cmlwbGljYXRlIG9uIE1TCi0gSWxsdXN0cmF0aW9uIHdpdGggNTBTIHJpYm9zb21hbCBwcm90ZcOvbiBMNSBBMFE0SjUKCmBgYHtyIGVjaG8gPSBGQUxTRSwgd2FybmluZyA9IEZBTFNFLCBtZXNzYWdlID0gRkFMU0V9CmZyYW5jIDwtIHJlYWRfdHN2KCJodHRwczovL3Jhdy5naXRodWJ1c2VyY29udGVudC5jb20vc3RhdE9taWNzL1BTTFMyMS9kYXRhL2ZyYW5jaXNlbGxhQTBRNEo1LnR4dCIpCmZyYW5jICU+JSAKICBnZ3Bsb3QoYWVzKGJpb3JlcCwgaW50ZW5zaXR5TG9nMiwgY29sb3IgPSBnZW5vdHlwZSkpICsKICBnZW9tX3BvaW50KCkKYGBgCgotIElmIHdlIGFuYWx5c2Ugb3JpZ2luYWwgZGF0YSB3aXRoIGEgdC10ZXN0IHdlIGFjdCBhcyBpZiB3ZSB3b3VsZCBoYXZlIDkgZ2VudWluZSByZXBlYXRzIGluIGVhY2ggY29uZGl0aW9uIAoKLSBFZmZlY3Qgb2YgaW50ZXJlc3QgYmV0d2VlbiBiaW8tcmVwcyBzbyBubyBibG9jayBkZXNpZ24KCi0gU2FtZSBudW1iZXIgb2YgdGVjaG5pY2FsIHJlcGVhdHMgZm9yIGVhY2ggZ2VudWluZSByZXBlYXQgd2UgY2FuIGZpcnN0IGF2ZXJhZ2Ugb3ZlciB0aGUgdGVjaHJlcHMuIAoKLSBJZiB0aGF0IGlzIG5vdCB0aGUgY2FzZSBtb3JlIGNvbXBsZXggZGF0YSBhbmFseXNpcyBtZXRob2RzIGhhdmUgdG8gYmUgdXNlZCwgZS5nLiBtaXhlZCBtb2RlbHMhCgotICoqQ2F1dGlvbjogbmV2ZXIgYXZlcmFnZSBvdmVyIGdlbnVpbmUgcmVwZWF0cy9leHBlcmltZW50YWwgdW5pdHMhISEqKgoKIyMjIENvcnJlY3QgYW5hbHlzaXMgCgpgYGB7cn0KbG1CaW9yZXAgPC0gbG0oaW50ZW5zaXR5TG9nMiB+IC0xICsgYmlvcmVwLCBmcmFuYykKZnJhbmNTdW0gPC0gZGF0YS5mcmFtZShnZW5vdHlwZSA9IHJlcChjKCJEOCIsIldUIiksZWFjaD0zKSAlPiUgYXMuZmFjdG9yICU+JSByZWxldmVsKCJXVCIpLCBpbnRlbnNpdHlMb2cyID0gbG1CaW9yZXAkY29lZikKZnJhbmNTdW0KdC50ZXN0KGludGVuc2l0eUxvZzIgfiBnZW5vdHlwZSwgZnJhbmNTdW0sIHZhci5lcXVhbD1UUlVFKQpgYGAKCiMjIyBXcm9uZyBhbmFseXNpcwoKYGBge3IgZWNobyA9IEZBTFNFLCB3YXJuaW5nID0gRkFMU0UsIG1lc3NhZ2UgPSBGQUxTRX0KdC50ZXN0KGludGVuc2l0eUxvZzIgfiBnZW5vdHlwZSwgZnJhbmMsdmFyLmVxdWFsPVRSVUUpCmBgYAoKLSBSZXN1bHQgbXVjaCBtb3JlIHNpZ25pZmljYW50IGJlY2F1c2Ugd2UgZXJyb25lb3VzbHkgYWN0IGFzIGlmIHdlIGhhdmUgYSA5IGJ5IDkgY29tcGFyaXNvbi4gCgojIyMgU2ltdWxhdGlvbiB1bmRlciAkSF8wJAoKLSBXZSB1c2UgZGF0YSB0byBlc3RpbWF0ZSB2YXJpYW5jZSBjb21wb25lbnRzOiB0ZWNobmljYWwgYW5kIGJpb2xvZ2ljYWwgdmFyaWFuY2UuIAotIFdlIHNpbXVsYXRlIDEwMDAwIGV4cGVyaW1lbnRzIHdpdGggc2ltaWxhciBkZXNpZ24gZnJvbSBhIG5vcm1hbCBkaXN0cmlidXRpb24gdW5kZXIgdGhlIGFzc3VtcHRpb24gdGhhdCBncm91cCBtZWFucyBhcmUgdGhlIHNhbWUuIAotIFdlIGFuYWx5c2UgdGhlbSB3aXRoIGJvdGggZGVzaWducwoKYGBge3IgZWNobyA9IEZBTFNFLCB3YXJuaW5nID0gRkFMU0UsIG1lc3NhZ2UgPSBGQUxTRX0Kc2lnbWFXaXRoaW4gPC0gc2lnbWEobG1CaW9yZXApCmxtU3VtIDwtIGxtKGludGVuc2l0eUxvZzIgfiBnZW5vdHlwZSwgZnJhbmNTdW0pCnNpZ21hQmV0d2VlbiA8LSBzaWdtYShsbVN1bSkKeEJpb3JlcCA8LSBtb2RlbC5tYXRyaXgofi0xK2Jpb3JlcCxmcmFuYykKeFdyb25nIDwtIG1vZGVsLm1hdHJpeCh+Z2Vub3R5cGUsZnJhbmMpCgoKc2V0LnNlZWQoMjUyMykKblNpbSA8LSAxMDAwMApyZXNXcm9uZyA8LSBtYXRyaXgoTkEsblNpbSw0KSAlPiUgYXMuZGF0YS5mcmFtZQpuYW1lcyhyZXNXcm9uZykgPC0gYygiRXN0aW1hdGUiLCJTdGQuIEVycm9yIiwidCB2YWx1ZSIsInB2YWx1ZSIpCnJlc0NvcnJlY3QgPC0gcmVzV3JvbmcKZ2Vub3R5cGUgPC0gZnJhbmMkZ2Vub3R5cGUKZ2Vub3R5cGVTdW0gPC0gZnJhbmNTdW0kZ2Vub3R5cGUKYmlvcmVwIDwtIGZyYW5jJGJpb3JlcAoKZm9yIChpIGluIDE6blNpbSkKewpiaW9yZXBTaW0gPC0gcm5vcm0obmNvbCh4QmlvcmVwKSxzZD1zaWdtYUJldHdlZW4pCnlTaW0gPC0geEJpb3JlcCUqJWJpb3JlcFNpbSArIHJub3JtKG5yb3coeEJpb3JlcCksc2Q9c2lnbWFXaXRoaW4pCnlTdW0gPC0gbG0oeVNpbX5iaW9yZXApJGNvZWZmaWNpZW50CnJlc1dyb25nW2ksXSA8LSBzdW1tYXJ5KGxtKHlTaW1+Z2Vub3R5cGUpKSRjb2VmZmljaWVudFsyLF0KcmVzQ29ycmVjdFtpLF08LXN1bW1hcnkobG0oeVN1bX5nZW5vdHlwZVN1bSkpJGNvZWZmaWNpZW50WzIsXQp9CmBgYAoKUHJvYmFiaWxpdHkgb24gYSBmYWxzZSBwb3NpdGl2ZSB3aGVuIHVzaW5nIGEgNSUgc2lnbmlmaWNhbmNlIGxldmVsIGluIAoKLSBjb3JyZWN0IGFuYWx5c2lzOgpgYGB7cn0KbWVhbihyZXNDb3JyZWN0JHB2YWx1ZSA8IDAuMDUpCmBgYAoKLSB3cm9uZyBhbmFseXNpczogCgpgYGB7cn0KbWVhbihyZXNXcm9uZyRwdmFsdWUgPCAwLjA1KQpgYGAKCi0gV2Ugbm8tbG9uZ2VyIGNvbnRyb2wgdGhlIGZhbHNlIHBvc2l0aXZlcyBhdCB0aGUgJFxhbHBoYSA9IDUkJSBsZXZlbCEKLSBXZSByZXBvcnQgdG8gbXVjaCBmYWxzZSBwb3NpdGl2ZXMhIAoKIyMgSG93IG1hbnkgZ2VudWluZSByZXBsaWNhdGVzPyAKCi0gRm9yIGV4cGVyaW1lbnRhbCBzdHVkaWVzOiBsb29rIGF0IHJhbmRvbWlzYXRpb24gb2YgdHJlYXRtZW50IAotIERvdWJsZSBibGluZCBzdHVkeSB3aXRoIDIwIHNwdXR1bSBwb3NpdGl2ZSBwYXRpZW50cyByYW5kb21pemVkIHRvIHRyZWF0bWVudCBvciBwbGFjZWJvCi0gTW91c2Ugc3R1ZHkgKDEwIG1pY2UpCgohW10oLi9maWd1cmVzL21vdXNlQ2FnZS5wbmcpe3dpZHRoPTI1JX0KCi0gTW91c2Ugc3R1ZHkgKDMwIG1pY2UpCgohW10oLi9maWd1cmVzL21vdXNlQ2FnZS5wbmcpe3dpZHRoPTI1JX0hW10oLi9maWd1cmVzL21vdXNlQ2FnZS5wbmcpe3dpZHRoPTI1JX0hW10oLi9maWd1cmVzL21vdXNlQ2FnZS5wbmcpe3dpZHRoPTI1JX0gICAgCgotIE1vdXNlIHN0dWR5ICgxMCBtaWNlKQoKIVtdKC4vZmlndXJlcy9tb3VzZUNhZ2VCbG9ja2luZy5wbmcpe3dpZHRoPTI1JX0KCgojIEJsb2NraW5nIAoKLSBJc29sYXRlIGtub3duIHNvdXJjZXMgb2YgdmFyaWFiaWxpdHkgZnJvbSB0aGUgZXhwZXJpbWVudAotIE9uZSBvZiB0aGUgbW9zdCBwb3dlcmZ1bCBjb25jZXB0cyBvZiBleHBlcmltZW50YWwgZGVzaWduCi0gTmF0dXJlIG1ldGhvZHM6IFBvaW50cyBvZiBzaWduaWZpY2FuY2UgLSBCbG9ja2luZyAKCltodHRwczovL3d3dy5uYXR1cmUuY29tL2FydGljbGVzL25tZXRoLjMwMDUucGRmXShodHRwczovL3d3dy5uYXR1cmUuY29tL2FydGljbGVzL25tZXRoLjMwMDUucGRmKQoKIyMgRXhhbXBsZQoKYGBge3IgZWNobyA9IEZBTFNFLCB3YXJuaW5nID0gRkFMU0UsIG1lc3NhZ2UgPSBGQUxTRSwgb3V0LndpZHRoPSI1MCUifQprbml0cjo6aW5jbHVkZV9ncmFwaGljcygiLi9maWd1cmVzL21vdXNlVGNlbGxfUkNCX2Rlc2lnbi5wbmciKQpgYGAKCmBgYHtyIGVjaG8gPSBGQUxTRSwgd2FybmluZyA9IEZBTFNFLCBtZXNzYWdlID0gRkFMU0UsIG91dC53aWR0aD0iMTAwJSJ9CmtuaXRyOjppbmNsdWRlX2dyYXBoaWNzKCIuL2ZpZ3VyZXMvYmxvY2tpbmdNb3VzZVRtZHMucG5nIikKYGBgCgojIEltcGxpY2F0aW9ucyBvZiBkaWZmZXJlbnQgdGVjaG5vbG9naWVzCgo8aW1nIHNyYz0iLi9maWd1cmVzL2xhYmVsVnNMYWJlbEZyZWUucG5nIiB3aWR0aD0iMTAwJSI+ClNsaWRlIGNvdXJ0ZXN5IChMaXNhIEJyZWNrZWxzKQoKCgojIFBvd2VyIGFuYWx5c2lzCgotIEhvdyBtYW55IHJlcGxpY2F0ZXMgZG8gd2UgbmVlZD8gCi0gRGlmZmVycyBmb3IgZGlmZmVyZW50IGV4cGVyaW1lbnRhbCBkZXNpZ25zCi0gUmVxdWlyZXMga25vd2xlZGdlIG9mIHRvdGFsIHZhcmlhYmlsaXR5IC8gbWFnbml0dWRlIG9mIHNvdXJjZXMgb2YgdmFyaWFiaWxpdHkKLSBVc2UgbGl0ZXJhdHVyZSBvciBwaWxvdCBleHBlcmltZW50Ci0gQ2FuIGJlIGRvbmUgdXNpbmcgc2ltdWxhdGlvbnMKCiMjIE1vdXNlIGV4YW1wbGUKCi0gSW4gMjAyMSBDaG9hIGV0IGFsLiBwdWJsaXNoZWQgdGhhdCB0aGUgY3l0b2tpbmUgVGh5bWljIHN0cm9tYWwgbHltcGhvcG9pZXRpbiAoVFNMUCkgaW5kdWNlZCBmYXQgbG9zcyB0aHJvdWdoIHNlYnVtIHNlY3JldGlvbiAodGFsZykuIFtodG1sXSBbUERGXQoKLSBTdXBwb3NlIHRoYXQgeW91IHdvdWxkIGxpa2UgdG8gc2V0IHVwIGEgc2ltaWxhciBzdHVkeSB0byB0ZXN0IGlmIGN5dG9raW5lIGludGVybGV1a2luIDI1IChJTCkgYWxzbyBoYXMgYmVuZWZpY2lhbCBlZmZlY3QuCgotIFlvdSBwbGFuIHRvIHNldHVwIGEgc3R1ZHkgd2l0aCBhIGNvbnRyb2wgZ3JvdXAgb2YgaGlnaCBmYXQgZGlldCAoSEZEKSBmZWQgbWljZSBhbmQgYSB0cmVhdG1lbnQgZ3JvdXAgdGhhdCByZWNpZXZlcyB0aGUgSEZEIGFuZCBJTC4KCi0gV2hhdCBzYW1wbGUgc2l6ZSBkbyB5b3UgbmVlZCB0byBwaWNrIHVwIHRoZSBlZmZlY3Qgb2YgdGhlIHRyZWF0bWVudC4KCiMjIEhvdyB3aWxsIHdlIGFuYWx5c2UgdGhlIGRhdGEgb2YgdGhpcyBleHBlcmltZW50PwoKLSBUd28gZ3JvdXBzOiB0d28gc2FtcGxlIHQtdGVzdAoKJEhfMCQ6IFRoZSBhdmVyYWdlIHdlaWdodCBkaWZmZXJlbmNlIGlzIGVxdWFsIHRvIHplcm8gICAgCiRIXzEkOiBUaGUgYXZlcmFnZSB3ZWlnaHQgZGlmZmVyZW5jZSBpcyBkaWZmZXJlbnQgZnJvbSB6ZXJvCgpQb3dlcj8gSXMgZGVzaWduIHNwZWNpZmljLiBGb3IgdHdvLWdyb3VwIGNvbXBhcmlzb24gaXQgZGVwZW5kcyBvbiAKCi0gUmVhbCB3ZWlnaHQgZGlmZmVyZW5jZSBiZXR3ZWVuIHRoZSBncm91cCBtZWFucy4KLSBWYXJpYWJpbGl0eSBvZiB0aGUgd2VpZ2h0IG1lYXN1cmVtZW50cwotIFNpZ25pZmljYW5jZSBsZXZlbCAkXGFscGhhJAotIFNhbXBsZSBzaXplIGluIGJvdGggZ3JvdXBzCgpXZSBjYW4gZXN0aW1hdGUgdGhlIHBvd2VyIGlmCgotIFRoZSBhc3N1bXB0aW9ucyBvZiB0aGUgbW9kZWwgYXJlIG1ldDogd2VpZ2h0cyBhcmUgbm9ybWFsbHkgZGlzdHJpYnV0ZWQgd2l0aCBzYW1lIHZhcmlhbmNlCgphbmQgd2Uga25vdwoKLSBTdGFuZGFyZCBkZXZpYXRpb24gb2YgdGhlIHdlaWdodCBtZWFzdXJlbWVudHMgYXJvdW5kIHRoZWlyIGF2ZXJhZ2UgbWVhbiBmb3IgSEZELWZlZCBtaWNlCi0gUmVhbCBlZmZlY3Qgc2l6ZSBpbiB0aGUgcG9wdWxhdGlvbgotIFNhbXBsZSBzaXplcyBpbiBlYWNoIGdyb3VwIAoKIyMgVXNlIGRhdGEgZnJvbSBhIHByZXZpb3VzIGV4cGVyaW1lbnQgdG8gZ2V0IGluc2lnaHQgaW4gbWljZSBkYXRhCgotIFN1cHBvc2UgdGhhdCB3ZSBoYXZlIGFjY2VzcyB0byB0aGUgZGF0YSBvZiBhIHByZWxpbWluYXJ5IGV4cGVyaW1lbnQgKGUuZy4gcHJvdmlkZWQgYnkgS2FyZW4gU3ZlbnNvbiB2aWEgR2FyeSBDaHVyY2hpbGwgYW5kIERhbiBHYXR0aSBhbmQgcGFydGlhbGx5IGZ1bmRlZCBieSBQNTAgR00wNzA2ODMgb24gUEg1MjV4KQoKYGBge3IgZWNobyA9IEZBTFNFLCB3YXJuaW5nID0gRkFMU0UsIG1lc3NhZ2UgPSBGQUxTRX0KbWljZSA8LSByZWFkLmNzdigiaHR0cHM6Ly9yYXcuZ2l0aHVidXNlcmNvbnRlbnQuY29tL2dlbm9taWNzY2xhc3MvZGFnZGF0YS9tYXN0ZXIvaW5zdC9leHRkYXRhL2ZlbWFsZU1pY2VXZWlnaHRzLmNzdiIpCgptaWNlICU+JQogIGdncGxvdChhZXMoeCA9IERpZXQsIHkgPSBCb2R5d2VpZ2h0KSkgKwogIGdlb21fYm94cGxvdChvdXRsaWVyLnNoYXBlID0gRkFMU0UpICsKICBnZW9tX2ppdHRlcigpCgoKbWljZSAlPiUKICBnZ3Bsb3QoYWVzKHNhbXBsZSA9IEJvZHl3ZWlnaHQpKSArCiAgZ2VvbV9xcSgpICsKICBnZW9tX3FxX2xpbmUoKSArCiAgZmFjZXRfd3JhcCh+RGlldCkKCm1pY2UgPC0gbWljZSAlPiUgbXV0YXRlKERpZXQgPSBhcy5mYWN0b3IoRGlldCkpCm1pY2VTdW0gPC0gbWljZSAlPiUKICBncm91cF9ieShEaWV0KSAlPiUKICBzdW1tYXJpemUoCiAgICBtZWFuID0gbWVhbihCb2R5d2VpZ2h0LCBuYS5ybSA9IFRSVUUpLAogICAgc2QgPSBzZChCb2R5d2VpZ2h0LCBuYS5ybSA9IFRSVUUpLAogICAgbiA9IG4oKQogICkgJT4lCiAgbXV0YXRlKHNlID0gc2QgLyBzcXJ0KG4pKQptaWNlU3VtCmBgYAoKSW4gdGhlIGV4cGVyaW1lbnQgd2UgaGF2ZSBkYXRhIGZyb20gdHdvIGRpZXRzOgoKLSBSZWd1bGFyIGRpZXQgb2YgY2VyaWFsIGFuZCBncmFpbiBiYXNlZCBkaWV0IChDaG93KQotIEhpZ2ggRmF0IChoZikKCldlIGNhbiB1c2UgdGhlIGhmIG1pY2UgYXMgaW5wdXQgZm9yIG91ciBwb3dlciBhbmFseXNpcy4KCi0gVGhlIGRhdGEgb2YgaGYgbWljZSBzZWVtIHRvIGJlIG5vcm1hbGx5IGRpc3RyaWJ1dGVkCi0gVGhlIG1lYW4gd2VpZ2h0IGlzIDI2LjhnCi0gVGhlIFNEIG9mIHRoZSB3ZWlnaHQgaXMgNC4xZwoKIyMjIEVmZmVjdCBzaXplPwoKLSBUaGUgYWx0ZXJuYXRpdmUgaHlwb3RoZXNpcyBpcyBjb21wbGV4LgotIEl0IGluY2x1ZGVzIGFsbCBwb3NzaWJsZSBlZmZlY3RzIQotIEluIG9yZGVyIHRvIGRvIHRoZSBwb3dlciBhbmFseXNpcyB3ZSB3aWxsIGhhdmUgdG8gY2hvb3NlIGEgbWluaW11bSBlZmZlY3Qgc2l6ZSB0aGF0IHdlIHdvdWxkIGxpa2UgdG8gZGV0ZWN0LgoKLSBTdXBwb3NlIHRoYXQgd2Ugd291bGQgbGlrZSB0byBwaWNrIHVwIGEgd2VpZ2h0IGNoYW5nZSBvZiBhdCBsZWFzdCAxMCUuCgpgYGB7cn0KZGVsdGEgPC0gYWJzKHJvdW5kKG1pY2VTdW0kbWVhblsyXSAqIC4xLCAxKSkKZGVsdGEKYGBgCgojIyMgU2ltdWxhdGlvbiBiYXNlZCBwb3dlciBhbmFseXNpcwoKV2UgY2FuIHVzZSBzaW11bGF0aW9ucyB0byBhc3Nlc3MgdGhlIHBvd2VyLiAKCi0gRS5nLiBmb3IgYSAzIGJ5IDMgY29tcGFyaXNvbiB3aGVyZSB0aGVyZSBpcyBhIHdlaWdodCBkaWZmZXJlbmNlIG9mIDNnLiAKLSBXZSBzaW11bGF0ZSAzIG9ic2VydmF0aW9ucyBmcm9tIGEgbm9ybWFsIHdpdGggbWVhbiAyNi44ZyBhbmQgc2QgNC4xZyBhbmQgMyBvYnNlcnZhdGlvbnMgZnJvbSBhIG5vcm1hbCB3aXRoIG1lYW4gMjkuOGcgYW5kIHNkIDQuMWcuIAotIFdlIHBlcmZvcm0gYSB0LXRlc3QgYW5kIGFzc2VzcyBpZiB3ZSBjYW4gY29uY2x1ZGUgdGhhdCB0aGVyZSBpcyBhIHNpZ25pZmljYW50IGRpZmZlcmVuY2UgaW4gdGhlIGF2ZXJhZ2Ugd2VpZ2h0IGJldHdlZW4gYm90aCBncm91cHMgYmFzZWQgb24gdGhpcyBzYW1wbGUKLSBXZSByZXBlYXQgaXQgbWFueSB0aW1lcyBhbmQgY2FsY3VsYXRlIHRoZSBwcm9iYWJpbGl0eSB0byBmaW5kIGEgc2lnbmlmaWNhbnQgZGlmZmVyZW5jZS4gCgpXZSBjYW4gcmVwZWF0IHRoZSBzYW1lIHByb2NlZHVyZSBmb3IgbWFueSBkaWZmZXJlbnQgc2FtcGxlIHNpemVzLi4uIAoKCgpgYGB7ciBlY2hvID0gRkFMU0UsIHdhcm5pbmcgPSBGQUxTRSwgbWVzc2FnZSA9IEZBTFNFfQpuMSA8LSBuMiA8LSAzCgpzZCA8LSByb3VuZChtaWNlU3VtJHNkWzJdLCAxKQpwcmVkaWN0b3JEYXRhIDwtIGRhdGEuZnJhbWUoRGlldCA9IHJlcChjKCJjIiwgImhmIiksIGMobjEsIG4yKSkgJT4lIGFzLmZhY3RvcigpKQoKYWxwaGEgPC0gMC4wNQoKCnNpbUZhc3QgPC0gZnVuY3Rpb24oZm9ybSwgZGF0YSwgYmV0YXMsIHNkLCBjb250cmFzdHMsIGFscGhhID0gLjA1LCBuU2ltID0gMTAwMDApIHsKICB5U2ltIDwtIHJub3JtKG5yb3coZGF0YSkgKiBuU2ltLCBzZCA9IHNkKQogIGRpbSh5U2ltKSA8LSBjKG5yb3coZGF0YSksIG5TaW0pCiAgZGVzaWduIDwtIG1vZGVsLm1hdHJpeChmb3JtLCBkYXRhKQogIHlTaW0gPC0geVNpbSArIGMoZGVzaWduICUqJSBiZXRhcykKICB5U2ltIDwtIHQoeVNpbSkKCiAgIyMjIEZpdHRpbmcKICBmaXRBbGwgPC0gbGltbWE6OmxtRml0KHlTaW0sIGRlc2lnbikKCiAgIyMjIEluZmVyZW5jZQogIHZhclVuc2NhbGVkIDwtIGModChjb250cmFzdHMpICUqJSBmaXRBbGwkY292LmNvZWZmaWNpZW50cyAlKiUgY29udHJhc3RzKQogIGNvbnRyYXN0cyA8LSBmaXRBbGwkY29lZmZpY2llbnRzICUqJSBjb250cmFzdHMKICBzZUNvbnRyYXN0cyA8LSB2YXJVbnNjYWxlZF4uNSAqIGZpdEFsbCRzaWdtYQogIHRzdGF0cyA8LSBjb250cmFzdHMgLyBzZUNvbnRyYXN0cwogIHB2YWxzIDwtIHB0KGFicyh0c3RhdHMpLCBmaXRBbGwkZGYucmVzaWR1YWwsIGxvd2VyLnRhaWwgPSBGQUxTRSkgKiAyCiAgcmV0dXJuKG1lYW4ocHZhbHMgPCBhbHBoYSkpCn0KCm5TaW0gPC0gMjAwMDAKYjAgPC0gMApzZCA8LSByb3VuZChtaWNlU3VtJHNkWzJdLCAxKQpucyA8LSBjKDMsIDUsIDEwLCAyMCwgMjUsIDUwLCA3NSwgMTAwKQpkZWx0YXMgPC0gYygxLCAyLCAzLCA1LCAxMCkKCmNvbnRyYXN0IDwtIGxpbW1hOjptYWtlQ29udHJhc3RzKCJEaWV0aGYiLCBsZXZlbHMgPSBjKCIoSW50ZXJjZXB0KSIsICJEaWV0aGYiKSkKCnBvd2VyRmFzdCA8LSBtYXRyaXgoTkEsIG5yb3cgPSBsZW5ndGgobnMpICogbGVuZ3RoKGRlbHRhcyksIG5jb2wgPSAzKSAlPiUgYXMuZGF0YS5mcmFtZSgpCm5hbWVzKHBvd2VyRmFzdCkgPC0gYygiYjEiLCAibiIsICJwb3dlciIpCmZvcm0gPC0gfkRpZXQKCmkgPC0gMAoKZm9yIChuIGluIG5zKQp7CiAgbjEgPC0gbjIgPC0gbgoKICAjIyMgU2ltdWxhdGlvbgogIHByZWRpY3RvckRhdGEgPC0gZGF0YS5mcmFtZShEaWV0ID0gcmVwKGMoImMiLCAiaGYiKSwgYyhuMSwgbjIpKSAlPiUgYXMuZmFjdG9yKCkpCgogIGZvciAoYjEgaW4gZGVsdGFzKQogIHsKICAgIGkgPC0gaSArIDEKICAgIGJldGFzIDwtIGMoYjAsIGIxKQogICAgcG93ZXJGYXN0W2ksIF0gPC0gYyhiMSwgbiwgc2ltRmFzdChmb3JtLCBwcmVkaWN0b3JEYXRhLCBiZXRhcywgc2QsIGNvbnRyYXN0cyA9IGNvbnRyYXN0LCBhbHBoYSA9IGFscGhhLCBuU2ltID0gblNpbSkpCiAgfQp9Cgpwb3dlckZhc3RbcG93ZXJGYXN0JGIxPT0zLDI6M10KYGBgCgpXZSBjYW4gYWxzbyByZXBlYXQgdGhhdCBmb3IgZGlmZmVyZW50IGVmZmVjdCBzaXplcyAKCmBgYHtyIGVjaG8gPSBGQUxTRSwgd2FybmluZyA9IEZBTFNFLCBtZXNzYWdlID0gRkFMU0V9CnBvd2VyRmFzdCRkZWx0YSA8LSBhcy5mYWN0b3IocG93ZXJGYXN0JGIxKQpwb3dlckZhc3QgJT4lCiAgZ2dwbG90KGFlcyh4ID0gbiwgeSA9IHBvd2VyLCBjb2wgPSBkZWx0YSkpICsKICBnZW9tX2xpbmUoKQpgYGAKCg==