1 Overview

In Q. Wang et al. (2023), we developed an end-to-end pipeline to demonstrate the role of epistasis in the genetic control of cardiac hypertrophy. This pipeline consisted of four major phases: (1) the derivation of estimates of left ventricular mass via deep learning, (2) the computational prioritization of epistatic drivers based on data from the UK Biobank (Bycroft et al. 2018), (3) functional interpretation of the hypothesized epistatic genetic loci, and (4) experimental confirmation of epistasis in cardiac transcriptome and cardiac cellular morphology.

Here, we expand upon the computational prioritization of epistatic drivers phase. In this phase, we leveraged large-scale genetic and cardiac MRI data from the UK Biobank and developed the low-signal signed iterative random forest (lo-siRF) to prioritize genetic loci and interactions between loci for downstream investigations. As lo-siRF is heavily rooted in the Predictability, Computability, and Stability (PCS) framework for veridical (trustworthy) data science (Yu and Kumbier 2020), we conducted extensive stability analyses to help minimize the impact of human judgment calls and modeling decisions on our scientific conclusions. In this supplementary PCS documentation, we will:

  1. Transparently document and justify the many human judgment calls and modeling decisions that were inevitably made throughout our statistical analysis.
  2. Provide additional exploration and insight into the main results presented in Q. Wang et al. (2023) alongside the stability analyses.

In what follows, we organize this documentation by step in the lo-siRF pipeline (see Q. Wang et al. (2023)), beginning with the choice of phenotypic data, followed by the dimension reduction step, binarization step, prediction step, and concluding with the prioritization step.

2 Choice of Phenotypic Data

In the first step of lo-siRF, we began with a careful choice of phenotypic data. This first, but often overlooked, choice is critical to the reliability and interpretation of results. If the data quality is poor, conclusions may be unreliable. If the data is far-removed from the domain problem of interest, conclusions may not be relevant. Given the importance of this choice of phenotypic data, we conducted extensive data explorations for different phenotypes in addition obtaining clinician input regarding its clinical relevance.

Initial choice of phenotype: Our overarching goal was to study the role of epistasis in cardiac hypertrophy. One important disease that is closely related to cardiac hypertrophy is hypertrophic cardiomyopathy (HCM). HCM is a common heart disease, impacting around 1 in 500 people, where the heart muscle becomes enlarged or thickened. Given the high prevalence and possible life-threatening consequences of this disease, we first set out to explore this HCM phenotype, defined as a 0-1 indicator variable of whether or not the individual was diagnosed with HCM (i.e., any ICD10 code of I42.1 or I42.2 in the UK Biobank). However, when fitting various machine learning prediction models, including L1 or L2-regularized logistic regression, random forest (RF), iterative RF (iRF), and support vector machines, using single-nucleotide variant (SNV) data from the UK Biobank (details in Q. Wang et al. (2023)) to predict HCM diagnosis, the balanced classification accuracy on the held-out validation data did not consistently exceed 50% when trained on different bootstrapped training samples. In other words, the fitted prediction models were no better than random guessing. This made us wary of any interpretations extracted from these prediction models since it is unclear whether these models are capturing any relevant phenotypic signal or simply noise. Given this incredibly weak prediction signal, we deemed that these models did not pass the prediction check (the “P” in PCS) (Yu and Kumbier 2020). For this reason, we chose not to proceed further with the HCM phenotype and did not conduct any analysis with respect to interpreting the aforementioned models for HCM.

Pivoting to a cardiac MRI-derived phenotype: We instead pivoted to an alternative phenotype for cardiac hypertrophy based upon deep-learning-enabled left ventricular (LV) structural analysis using cardiac MRIs. This choice was heavily motivated by our struggles with HCM. Specifically, when looking back at the HCM diagnosis data, we noticed that the number of HCM cases in the UK Biobank data (only 236 HCM cases out of 337,535 unrelated White British individuals) was much lower than the 1 in 500 ratio that is expected. Although the UK Biobank population is known to be healthier than the general population (Fry et al. 2017), the observed discrepancy is large, leading us to speculate about potential under-diagnosis issues with the HCM phenotype. Consequently, rather than relying on a clinician’s diagnosis which may suffer from issues such as under-diagnosis, we chose to build upon recent advances in deep-learning-enabled phenotyping (Bai et al. 2018). Doing so enables us to extract a measure of left ventricular hypertrophy, specifically, the left ventricular mass (LVM), from anyone with a cardiac MRI.

Arriving at LVMi: However, LVM is known to be heavily influenced by body weight, height, and gender (Engel, Schwartz, and Homma 2016; Mizukoshi et al. 2016). Thus, if we were to proceed solely with LVM in our analysis, we risk identifying genetic loci and interactions between loci that are primarily associated with body weight, height, and gender, rather than left ventricular hypertrophy. Indeed, if we visualize the relationship between LVM, height, and weight within each gender group (Figure 2.1), we see strong positive correlations.

This motivates the need to adjust for height and weight in order to help decouple the effects of height/weight and LVM. As done in Khurshid et al. (2023), one common way to address this is by analyzing LVM indexed by body surface area (LVMi), defined as:

\[\begin{align*} \text{LVMi} = \text{LVM } / \text{ Body surface area}, \end{align*}\] where body surface area is calculated based on height and body weight via the Du Bois formula (Du Bois and Du Bois 1916).

After normalizing by body surface area (and hence, height and weight), the associations between LVMi and height/weight are much weaker within each gender group, exhibiting correlations closer to 0 (Figure 2.1). Thus, by focusing our statistical analysis on LVMi, we lessen the possibility that the identified genetic loci and interactions between loci are only selected because of their association with body height and/or weight. Still, there are differences in LVMi between males and females, with males tending to have higher LVMi measurements. As seen later, we will account for this in the modeling stage by using gender-specific binarization thresholds to binarize the LVMi responses into the high and low LVMi groups.

Study Cohort: Before proceeding, we note that another important human judgment call within our pipeline is the choice of study cohort. Specifically, we restricted our analysis to the unrelated White British individual population with both SNV and cardiac MRI data in the UK Biobank, resulting in a cohort of 29,661 individuals. We chose to focus this analysis on the unrelated White British population, anticipating the very low-signal problem under study (e.g., due to the generally small effect sizes of common genetic variants and the high phenotypic diversity of cardiac hypertrophy). By studying a more homogeneous cohort such as the unrelated White British population, we hope to first establish a proof-of-concept foothold on the role of epistasis in cardiac hypertrophy, and we view the study and generalization to the broader population as a very crucial next step.

Pair plot, illustrating the relationships between LVM, LVMi, height, and weight within each gender group (males in green and females in orange). Density distributions are shown along the diagonal.

Figure 2.1: Pair plot, illustrating the relationships between LVM, LVMi, height, and weight within each gender group (males in green and females in orange). Density distributions are shown along the diagonal.

3 Dimension Reduction Step

Overview

Having carefully chosen the phenotypic data (i.e., the cardiac MRI-derived LVMi) under study, the next step in lo-siRF is to do dimension reduction to reduce the number of SNVs under consideration using a genome-wide association study (GWAS). This dimension reduction step is necessary to mitigate the computational and statistical challenges of searching across millions of possible SNVs (which in the case of searching for epistasis results in an even larger combinatorial explosion of possibilities).

Why GWAS? We chose to do dimension reduction by running a GWAS as it (1) has been shown to be an incredibly useful tool for better understanding the genetic basis of numerous diseases in this field (Visscher et al. 2017; Pirruccello et al. 2020; Meyer et al. 2020; Harper et al. 2021; Khurshid et al. 2023), (2) is one of the few methods that can handle an input of millions of SNVs in a computationally-tractable manner, and (3) is a common, widely-accepted preprocessing step in other related statistical genomics tasks such as fine-mapping (Schaid, Chen, and Larson 2018).

Limitations: We acknowledge, however, that using a GWAS to reduce the number of SNVs under consideration has limitations. Because a GWAS prioritizes SNVs that have strong marginal associations with the phenotype under study, we may be removing SNVs that are associated with LVMi through an epistatic interaction but not through a marginal association. Alleviating this limitation is certainly interesting and an important direction to pursue in future work. Regardless, in this current work, we use lo-siRF primarily as a way to generate recommendations for experimental validation of epistasis. We thus are most interested in generating reliable recommendations for a limited number of experiments, rather than attempting to find all possible interactions that drive the disease. Given our particular use-case for lo-siRF, we accept the limitations of using a GWAS for dimension reduction and again view this work as a reliable first step (and certainly not the last) for better understanding the role of epistasis in cardiac hypertrophy.

How was the dimension reduction performed? We performed a GWAS on the training data for the rank-based inverse normal-transformed LVMi using two algorithms, PLINK (Purcell et al. 2007) and BOLT-LMM (Loh et al. 2015). For each of the two GWAS runs, we ranked the SNVs by significance (i.e., the GWAS p-value). We then took the union of the top 1000 SNVs (without clumping) from each of the two GWAS runs and proceeded with this resulting set of 1405 SNVs for the remainder of the lo-siRF pipeline. We refer to Q. Wang et al. (2023) for the details on the PLINK and BOLT-LMM implementations and use this document instead to justify several of our human judgment calls in this dimension reduction step.

  • Why PLINK and BOLT-LMM? Since BOLT-LMM and PLINK rely on different statistical models and it is unclear a priori which model is better suited for our problem, we employed both software packages to mitigate the dependence of downstream conclusions on this arbitrary choice of model.
  • Why the rank-based inverse normal-transformed LVMi? Because the distribution of LVMi measurements is right skewed (see Figure 2.1), and the p-value computation in PLINK and BOLT-LMM rely on normality assumptions, the rank-based inverse normal-transform was taken as in Khurshid et al. (2023).
  • Why was the union taken? As mentioned previously, relying on a GWAS to do dimension reduction can be limiting since it is primarily assessing marginal associations between the SNVs and the phenotype. There are also other restrictive modeling assumptions (e.g., linearity) that may add to these limitations. Due to this concern that we may be imposing too many unnecessary restrictions in order for SNVs to pass the GWAS filter, we chose to take the union of the top SNVs from BOLT-LMM and from PLINK, rather than taking the intersection which would have made it more difficult or restrictive for SNVs to pass the GWAS filter.
  • How was the threshold chosen? We chose the threshold of 1000 SNVs per GWAS method (without clumping) as it (1) struck a balance between the amount of information loss and the computational cost of our downstream modeling and (2) yielded the highest validation prediction accuracy compared to choosing other possible thresholds (500 and 2000) with and without clumping in the prediction modeling stage. We note that this choice of the top 1000 SNVs includes all SNVs that passed the genome-wide significance level (p-value = 5E-8) as well as additional SNVs that did not pass the genome-wide significance level. In particular, taking the top 1000 SNVs corresponds to using the p-value threshold of 1.7E-5 and 6.7E-6 for PLINK and BOLT-LMM, respectively.

Organization: Under the GWAS Results Summary tab, we provide an investigation into the BOLT-LMM and PLINK GWAS results for LVM and LVMi. Under the GWAS-filtered SNVs, we explore the selected 1405 SNVs that passed the GWAS filter for the LVMi phenotype.

GWAS Results Summary

Below, we provide an overview of the genome-wide association study (GWAS) results for both the LVM and LVMi phenotypes. While LVMi is the primary phenotype of interest, we provide the LVM GWAS results for completeness. We further investigate the similarities in findings between the LVM and LVMi GWAS analyses via a stability analysis.

  • Under the BOLT-LMM and PLINK tabs:
    • We provide a brief look into the GWAS results, including the Manhattan plots for each phenotype (LVMi and LVM).
    • We also provide a table of the genomic risk loci, lead SNVs, and independent significant SNVs from each GWAS, determined using FUMA (Watanabe et al. 2017) with the default settings (i.e., maximum p-value of lead SNVs = 5E-8, maximum p-value cutoff = 0.05, \(r^2\) threshold to define independent significant SNVs = 0.6, 2nd \(r^2\) threshold to define lead SNVs = 0.1, minimum minor allele frequency = 0, maximum distance between LD blocks to merge into a locus = 250kb, using the UKB release2b 10k White British reference panel population).
    • Furthermore, we used FUMA to map SNVs to genes based on position, again with the default settings (maximum distance = 10kb), and provide this table of mapped genes below.
  • Lastly, under the Stability Analysis tab, we investigated the similarities and differences between the BOLT-LMM and PLINK results as well as between the LVM and LVMi results.

BOLT-LMM

LVMi

GWAS Manhattan plot for the LVMi phenotype using BOLT-LMM. Red dashed line indicates the genome-wide significance level (p = 5E-8).

Figure 3.1: GWAS Manhattan plot for the LVMi phenotype using BOLT-LMM. Red dashed line indicates the genome-wide significance level (p = 5E-8).

Genomic Risk Loci

Figure 3.2: List of genomic risk loci from FUMA for the LVMi BOLT-LMM GWAS. uniqID = Unique ID of SNVs consists of chr:position:allele1:allele2 where alleles are alphabetically ordered. rsID = rsID of the top lead SNV for the given genomic locus. chr = Chromosome of top lead SNV. pos = Position of top lead SNV on hg19. p = P-value of top lead SNV. start = Start position of the locus. end = End position of the locus. nGWASSNVs = Number of the GWAS-tagged candidate SNVs within the genomic locus. nIndSigSNVs = Number of the independent significant SNVs in the genomic locus. IndSigSNVs = rsID of independent significant SNVs in the genomic locus. nLeadSNVs = The number of lead SNVs in the genomic locus. LeadSNVs = rsID of lead SNVs in the genomic locus.

Lead SNVs

Figure 3.3: List of lead SNVs from FUMA for the LVMi BOLT-LMM GWAS. GenomicLocus = Index of assigned genomic locus (note: multiple independent lead SNVs can be assigned to the same genomic locus). uniqID = Unique ID of SNVs consists of chr:position:allele1:allele2 where alleles are alphabetically ordered. rsID = rsID of the SNV. chr = Chromosome. pos = Position on hg19. p = P-value from GWAS. nIndSigSNVs = Number of independent significant SNVs which are in LD of the lead SNV at \(r^2\) = 0.1. IndSigSNVs = rsID of independent significant SNVs which are in LD of the lead SNV at \(r^2\) = 0.1.

Independent Significant SNVs

Figure 3.4: List of independent significant SNVs from FUMA for the LVMi BOLT-LMM GWAS. GenomicLocus = Index of assigned genomic locus (note: multiple independent lead SNVs can be assigned to the same genomic locus). uniqID = Unique ID of SNVs consists of chr:position:allele1:allele2 where alleles are alphabetically ordered. rsID = rsID of the SNV. chr = Chromosome. pos = Position on hg19. p = P-value from GWAS. nGWASSNVs = Number of GWAS-tagged SNVs which are in LD of the independent significant SNV given \(r^2\) = 0.6.

Mapped Genes

Figure 3.5: List of mapped genes (via positional mapping) from FUMA for the LVMi BOLT-LMM GWAS. ensg = ENSG ID. symbol = Gene Symbol. chr = Chromosome. start = Starting position of the gene. end = Ending position of the gene. strand = Strand of the gene. type = Gene biotype from Ensembl. entrezID = entrez ID (if available). HUGO = HUGO (HGNC) gene symbol. pLI = pLI score (the probability of being loss-of-function intolerant) from ExAC database; the higher the score is, the more intolerant to loss-of-function mutations the gene is. ncRVIS = Non-coding residual variation intolerance score; the higher the score is, the more intolerant to non-coding variation the gene is. posMapSNVs = Number of SNVs mapped to gene based on positional mapping. posMapMaxCADD = The maximum CADD score of mapped SNVs by positional mapping. minGwasP = The minimum P-value of mapped SNVs. IndSigSNVs = rsID of the independent significant SNVs that are in LD with the mapped SNVs. GenomicLocus = Index of genomic loci where mapped SNVs are from.

LVM

GWAS Manhattan plot for the LVM phenotype using BOLT-LMM. Red dashed line indicates the genome-wide significance level (p = 5E-8).

Figure 3.6: GWAS Manhattan plot for the LVM phenotype using BOLT-LMM. Red dashed line indicates the genome-wide significance level (p = 5E-8).

Genomic Risk Loci

Figure 3.7: List of genomic risk loci from FUMA for the LVM BOLT-LMM GWAS. uniqID = Unique ID of SNVs consists of chr:position:allele1:allele2 where alleles are alphabetically ordered. rsID = rsID of the top lead SNV for the given genomic locus. chr = Chromosome of top lead SNV. pos = Position of top lead SNV on hg19. p = P-value of top lead SNV. start = Start position of the locus. end = End position of the locus. nGWASSNVs = Number of the GWAS-tagged candidate SNVs within the genomic locus. nIndSigSNVs = Number of the independent significant SNVs in the genomic locus. IndSigSNVs = rsID of independent significant SNVs in the genomic locus. nLeadSNVs = The number of lead SNVs in the genomic locus. LeadSNVs = rsID of lead SNVs in the genomic locus.

Lead SNVs

Figure 3.8: List of lead SNVs from FUMA for the LVM BOLT-LMM GWAS. GenomicLocus = Index of assigned genomic locus (note: multiple independent lead SNVs can be assigned to the same genomic locus). uniqID = Unique ID of SNVs consists of chr:position:allele1:allele2 where alleles are alphabetically ordered. rsID = rsID of the SNV. chr = Chromosome. pos = Position on hg19. p = P-value from GWAS. nIndSigSNVs = Number of independent significant SNVs which are in LD of the lead SNV at \(r^2\) = 0.1. IndSigSNVs = rsID of independent significant SNVs which are in LD of the lead SNV at \(r^2\) = 0.1.

Independent Significant SNVs

Figure 3.9: List of independent significant SNVs from FUMA for the LVM BOLT-LMM GWAS. GenomicLocus = Index of assigned genomic locus (note: multiple independent lead SNVs can be assigned to the same genomic locus). uniqID = Unique ID of SNVs consists of chr:position:allele1:allele2 where alleles are alphabetically ordered. rsID = rsID of the SNV. chr = Chromosome. pos = Position on hg19. p = P-value from GWAS. nGWASSNVs = Number of GWAS-tagged SNVs which are in LD of the independent significant SNV given \(r^2\) = 0.6.

Mapped Genes

Figure 3.10: List of mapped genes (via positional mapping) from FUMA for the LVM BOLT-LMM GWAS. ensg = ENSG ID. symbol = Gene Symbol. chr = Chromosome. start = Starting position of the gene. end = Ending position of the gene. strand = Strand of the gene. type = Gene biotype from Ensembl. entrezID = entrez ID (if available). HUGO = HUGO (HGNC) gene symbol. pLI = pLI score (the probability of being loss-of-function intolerant) from ExAC database; the higher the score is, the more intolerant to loss-of-function mutations the gene is. ncRVIS = Non-coding residual variation intolerance score; the higher the score is, the more intolerant to non-coding variation the gene is. posMapSNVs = Number of SNVs mapped to gene based on positional mapping. posMapMaxCADD = The maximum CADD score of mapped SNVs by positional mapping. minGwasP = The minimum P-value of mapped SNVs. IndSigSNVs = rsID of the independent significant SNVs that are in LD with the mapped SNVs. GenomicLocus = Index of genomic loci where mapped SNVs are from.

Stability Analysis

To further investigate the choice of GWAS method and phenotype, we conducted a deeper exploration into the similarities and differences between the BOLT-LMM and PLINK results as well as between the LVM and LVMi results in the stability analysis below. The primary goal of this stability analysis is to answer the following two questions:

  1. Are there large differences between the GWAS p-values from BOLT-LMM and PLINK?
  • Figure 3.21: For each SNV, we plot the p-value (log-transformed) obtained via BOLT-LMM (x-axis) and PLINK (y-axis) for each of the LVM (left) and LVMi (right) phenotypes. We see that the most significant GWAS hits tend to be stable, no matter the choice of algorithm, but as the strength of the association decreases, there is greater variation in the p-value between BOLT-LMM and PLINK. This is to say that there is more stability around the SNVs with the strongest associations with LVMi and less stability around the SNVs with moderate or weak associations with LVMi. Another reason for taking the union of the top 1000 SNVs from each GWAS algorithm in the lo-siRF pipeline was to allow these moderate to weak association SNVs the chance of being identified in a multivariate model (i.e., via iterative random forest).
  1. What are the FUMA GWAS findings that are stable across GWAS methods (BOLT-LMM and PLINK) and choice of phenotype (LVM and LVMi)? As advocated by the stability principle (“S” in PCS) (Yu and Kumbier 2020; Yu 2013), we view stability across these arbitrary choices as a minimum requirement for making a scientific discovery.
  • In Figure 3.22, we summarize the SNVs, identified by FUMA, to be the top lead SNVs (per genomic risk locus), lead SNVs, and/or independent significant SNVs for each GWAS method (BOLT-LMM and PLINK) and choice of phenotype (LVM and LVMi). Some takeaways here:
    • rs3045696, an intronic TTN variant, is the only stable top lead SNV, identified across all four GWAS runs.
    • Besides rs3045696, rs1873164, an intronic CCDC141 variant, is the only stable lead SNV, identified by FUMA across all four GWAS runs.
    • rs7591091 (an intronic CCDC141 variant with the highest frequency of occurrence in lo-siRF, seen later), along with rs967507, rs12622500, and rs10178003, were stably identified as independent significant SNVs by FUMA across all four GWAS runs.
    • Two other SNVs (rs62178977, rs73973171) were also identified as independent significant SNVs by FUMA using both BOLT-LMM and PLINK for the LVMi phenotype.
  • In Figure 3.23, we summarize the genes that were positionally-mapped and prioritized by FUMA across the different GWAS methods (BOLT-LMM and PLINK) and choice of phenotype (LVM and LVMi).
    • The genes that were stably mapped by FUMA across all four GWAS runs are PRKRA, DFNB59, FKBP7, PLEKHA3, TTN, and CCDC141. We note that all of these genes are located near each other on chromosome 2 within ~600kb. The start position of PRKRA is 179296141 while the end position of CCDC141 is 179914813, with all other aforementioned genes in between.
    • No other genes were identified when using both BOLT-LMM and PLINK for the LVMi phenotype.
Comparison of the BOLT-LMM and PLINK GWAS p-values for each phenotype (LVM left, LVMi right). Each point represents a SNV with its BOLT-LMM p-value on the x-axis and its PLINK p-value on the y-axis.

Figure 3.21: Comparison of the BOLT-LMM and PLINK GWAS p-values for each phenotype (LVM left, LVMi right). Each point represents a SNV with its BOLT-LMM p-value on the x-axis and its PLINK p-value on the y-axis.

Summary of annotated SNVs from FUMA across different GWAS methods (BOLT-LMM and PLINK) and across different choices of phenotype (LVMi and LVM).

Figure 3.22: Summary of annotated SNVs from FUMA across different GWAS methods (BOLT-LMM and PLINK) and across different choices of phenotype (LVMi and LVM).

Summary of mapped genes from FUMA across different GWAS methods (BOLT-LMM and PLINK) and across different choices of phenotype (LVMi and LVM).

Figure 3.23: Summary of mapped genes from FUMA across different GWAS methods (BOLT-LMM and PLINK) and across different choices of phenotype (LVMi and LVM).

GWAS-filtered SNVs

In this section, we briefly explore the selected 1405 SNVs that passed the GWAS filter for the LVMi phenotype. We make two observations that will impact how we interpret the lo-siRF fit downstream:

  • There are strong correlations within blocks of neighboring SNVs due to linkage disequilibrium (LD) (Figure 3.24). This is a large contributing factor for why we ultimately extracted feature importances from the lo-siRF fit at the level of genetic loci, rather than for each individual SNV.
  • There are large differences in the number of SNVs that passed the GWAS filter from each genetic loci (Figure 3.25). We hence must account for this in the lo-siRF locus-level importance score.

We will expand upon this locus-level importance score in a later section (see Prioritization Step).

Additional notes:

  • Given the interest in CCDC141 and TTN in our work and their close proximity to each other on chromosome 2, we point out a couple pairwise (Pearson) correlations of particular relevance:
    • \(| Cor(\text{rs7591091}, \text{ rs66733621}) | = 0.35\)
    • \(| Cor(\text{rs7591091}, \text{ rs3045696}) | = 0.34\)
    • rs7591091 is the top SNV from the CCDC141 locus in lo-siRF and is one of the top CCDC141 GWAS hits (in fact, is identified to be a stable independent significant SNV (see GWAS Results Summary tab)). rs3045696, an intronic TTN SNV, was stably identified to be a top lead SNV in the GWASes, and rs66733621 is the top SNV from the TTN locus in lo-siRF. This is to say that the correlation between the CCDC141 and TTN loci is moderate and may possibly suggest independent roles of CCDC141 and TTN in their detected interaction. A further discussion of this is provided in Q. Wang et al. (2023). [Note: we use the term top SNV from a genetic locus in lo-siRF to mean the SNV in the specified genetic locus with the highest frequency of occurrence across decision paths in the siRF fit.]

LVMi - Correlation Between GWAS-filtered SNVs

Correlation heatmap for the GWAS-filtered SNVs. We plot the magnitude of the Pearson correlation between all possible pairs of SNVs that passed the GWAS filter. Darker red indicates higher correlation between the two SNVs. SNVs along the axes are ordered according to genomic location. Loci with more than two constituent SNVs are labeled.

Figure 3.24: Correlation heatmap for the GWAS-filtered SNVs. We plot the magnitude of the Pearson correlation between all possible pairs of SNVs that passed the GWAS filter. Darker red indicates higher correlation between the two SNVs. SNVs along the axes are ordered according to genomic location. Loci with more than two constituent SNVs are labeled.

LVMi - Table of GWAS-filtered SNVs

Figure 3.25: Number of SNVs per genetic locus that passed the GWAS filter. Note: a semicolon is used to denote the intergenic region between two genes.

4 Binarization Step

Overview

In the next step of lo-siRF, we chose to binarize the (continuous) LVMi phenotype measurements into two categories: a low LVMi group and a high LVMi group before fitting the prediction models.

Why did we choose to binarize? One of our main motivating factors to pursue binarization revolved around the prediction check criteria in the PCS framework (Yu and Kumbier 2020). This predictability principle advocates for the use of prediction accuracy as a reality check. This is to say that at a minimum, models should fit the data well, as measured by prediction accuracy, before believing that the model is capturing something relevant to reality or the real-world phenomena under study. In particular, before we thought to binarize the phenotype, we first attempted to train prediction models using the GWAS-filtered SNVs to predict the original (continuous) LVMi phenotype measurements. While this seemed like the most natural next step, these prediction results illuminated an incredibly weak prediction signal, with validation \(R^2\) values hovering very close to 0 (see Prediction Results without Binarization tab). Given that an \(R^2\) value of 0 can be achieved by simply predicting the mean LVMi response, this raised the question of whether these prediction models are capturing any relevant signal in the data. Consequently, the interpretation of these models may not be an accurate representation of reality. Put differently, these models do not satisfy the prediction check criteria under the PCS framework.

Given these difficulties in accurately predicting LVMi, we turned to an alternative school of thought in order to extract reliable insights from such low-signal data. Drawing inspiration from how scientists often reduce complex problems into simplified versions, we can simplify the problem of trying to understand how SNVs are associated with everyone’s precise LVMi measurements to asking which SNVs are associated with having extremely high or extremely low LVMi measurements. In other words, we can reduce the problem of predicting (continuous) LVMi responses to predicting whether one has an extremely high LVMi or low LVMi. This binarization not only simplifies the problem conceptually, but may also help to denoise since we are only looking at the more extreme LVMi cases to gain understanding. Furthermore, the original regression problem becomes a classification problem after binarization, which can help to facilitate the interpretation of prediction performance with respect to the prediction check (e.g., it is arguably easier to reason about the practical difference between 55% and 50% balanced classification accuracy than \(R^2\) values of 0.05 and 0).

How is the binarization done? In order to binarize the LVMi responses, one must choose some threshold. We chose to binarize the response based on quantiles so that for a given threshold x, we took the top and bottom x% of LVMi values and pooled them into the high and low LVMi groups, respectively, while omitting the individuals in the middle quantile range. However, due to the gender-specific biological variation of LVMi shown earlier in the exploratory data analysis (see Choice of Phenotypic Data), we performed the binarization for males and females separately. Finally, given that this threshold is artificially introduced, we run the remainder of the lo-siRF pipeline using three different reasonable binarization thresholds (15%, 20%, 25%) that balance the amount of denoising and data lost. In the end, we will consolidate the results that were stable across all three binarization thresholds, described later.

We expand on the prediction modeling with the binarized LVMi phenotype in the next section (see Prediction Step).

Prediction Results without Binarization

Here, we present a summary of the prediction modeling results, where we use the GWAS-filtered SNVs to predict the raw LVMi phenotype measurements (i.e., without any binarization). Specifically, we measure the validation set prediction accuracy from several popular machine learning regression algorithms (kernel ridge regression, Lasso regression, ridge regression, random forest (RF), and signed iterative random forest (siRF)) across four different prediction performance metrics - the Pearson correlation, mean absolute error (MAE), R-squared, and root-mean-squared error (RMSE) between the observed LVMi response and the predicted LVMi response. We also visualize how the predicted responses differ across the different prediction models in the provided pair plots. Though RF appears to yield the best prediction performance relative to the other methods under consideration, the RF prediction performance is still very poor as both the correlation and R-squared metrics are very close to 0.

Prediction Accuracies

Figure 4.1: Summary of prediction performance on the validation set for the LVMi phenotype (without binarization) across various prediction methods and evaluation metrics.

Prediction Pair Plot

Pair plot of the predicted LVMi responses from various prediction models. Each point represents an individual in the validation set, and the coordinates represent the predicted LVMi response from two different prediction methods, which are specified by the x and y-axes labels in each subplot. Density distributions of the predicted LVMi responses are shown along the diagonal.

Figure 4.2: Pair plot of the predicted LVMi responses from various prediction models. Each point represents an individual in the validation set, and the coordinates represent the predicted LVMi response from two different prediction methods, which are specified by the x and y-axes labels in each subplot. Density distributions of the predicted LVMi responses are shown along the diagonal.

5 Prediction Step

After choosing to binarize the LVMi phenotype, we next fit various prediction models using the GWAS-filtered SNVs to predict the binarized LVMi phenotype and assess their validation prediction accuracy.

Which models were chosen and why? While there are many methods, each with their unique advantages and disadvantages, for detecting epistasis from data (e.g., see Niel et al. 2015 and references therein), we chose to focus on siRF (Kumbier et al. 2023) as our primary interaction search engine for various reasons.

  1. Unlike many methods that make linear assumptions or require pre-specification of interaction order (i.e., the number of features involved in an interaction), siRF can identify higher-order, nonlinear Boolean interactions in a computationally-tractable manner without the need to specify the interaction order of interest.
  2. Another advantage of siRF for detecting interactions is the resemblance between the localized thresholding behavior of its decision trees and the threshold (or on-off switch-like) behavior frequently observed in biomolecular interactions (Nelson, Lehninger, and Cox 2008). In other words, the form of the siRF model appears to be well-suited for the biological phenomena under study.
  3. Furthermore, the prediction accuracy of the siRF model fit can be easily assessed. As discussed previously, prediction accuracy can serve as an indicator of whether or not the model is an accurate representation of reality. This prediction check is a necessary pre-requisite for interpreting the prediction model and is especially important in low-signal regimes such as this study.
  4. siRF and its predecessor iRF have demonstrated great success in detecting reliable interactions in previous real-world studies, such as in epistasis-controlled hair color (Behr et al. 2020), obesity (Allen et al. 2022), schizophrenia (De Rosa et al. 2022), and predictive gene expression networks (Cliff et al. 2019; Walker et al. 2022).
  5. Finally, due to the weak phenotypic signal and the strong correlations between neighboring SNVs due to linkage disequilibrium (see Figure 3.24), we believed it was most appropriate to recommend interactions between genetic loci, rather than interactions betweeen individual SNVs. While it is not always clear how to perform this locus-level interaction search when the data is given at the SNV-level, we can build upon the siRF structure to aggregate feature importances across multiple SNVs using our new locus-level importance score, described in Q. Wang et al. (2023).

Though we are most interested in interpreting the siRF prediction model to identify candidate epistatic interactions, we also fit several other popular prediction models, including RF, L1-regularized logistic regression (Lasso), L2-regularized logistic regression (ridge), and support vector machines (SVM). These prediction models serve as baselines to ensure that siRF indeed fits the data well, relative to these other popular prediction models, and that siRF passes the prediction check in accordance with the PCS framework (Yu and Kumbier 2020).

Summary of prediction results: For all of the classification algorithms under investigation, we see that the validation prediction accuracy metrics, measured via classification accuracy, area under the ROC curve (AUROC), and area under the precision-recall curve (AUPRC), are all comfortably above the random-guessing baseline of 0.5 across three different binarization thresholds. This suggests that the prediction models are able to ascertain some phenotypic signal from the SNVs under study. That is, the SNVs used in the prediction models have some predictive power in differentiating those with high LVMi versus those with low LVMi. Moreover, siRF consistently yielded the highest predictive power across the various binarization thresholds and prediction metrics (with one exception being the classification accuracy for the 15% binarization threshold, where ridge is slightly better than siRF). From this, we conclude that siRF passed the prediction check and will proceed to interpret the siRF fit to recommend and prioritize interactions between genetic loci for downstream analyses and experiments.

Beyond the validation prediction accuracies, we also provide the confusion matrices, ROC and precision-recall curves, and pair plots comparing the predicted responses across methods for additional post-hoc exploration.

Prediction Accuracy Summary

Figure 5.1: Summary of prediction performance on the validation set for the binarized LVMi phenotype across various prediction methods, binarization thresholds, and evaluation metrics.

Binarization Threshold = 0.15

Confusion Tables

Figure 5.2: Confusion matrix from various prediction models for predicting the binarized LVMi phenotype (binarization threshold = 0.15).

ROC/PR Curves

Figure 5.3: ROC curve for predicting the binarized LVMi (threshold = 0.15) across various prediction methods. TPR = true positive rate; FPR = false positive rate.

Figure 5.4: Precision-recall curve for predicting the binarized LVMi (threshold = 0.15) across various prediction methods.

Prediction Pair Plot

Pair plots of the predicted binarized LVMi responses (threshold = 0.15) across various prediction methods. Each point represents an individual in the validation set, and the coordinates represent the predicted probability of having high LVMi from two different prediction methods, which are specified by the x and y-axes labels in each subplot. Density distributions of the predicted probabilities are shown along the diagonal.

Figure 5.5: Pair plots of the predicted binarized LVMi responses (threshold = 0.15) across various prediction methods. Each point represents an individual in the validation set, and the coordinates represent the predicted probability of having high LVMi from two different prediction methods, which are specified by the x and y-axes labels in each subplot. Density distributions of the predicted probabilities are shown along the diagonal.

Binarization Threshold = 0.2

Confusion Tables

Figure 5.6: Confusion matrix from various prediction models for predicting the binarized LVMi phenotype (binarization threshold = 0.2).

ROC/PR Curves

Figure 5.7: ROC curve for predicting the binarized LVMi (threshold = 0.2) across various prediction methods. TPR = true positive rate; FPR = false positive rate.

Figure 5.8: Precision-recall curve for predicting the binarized LVMi (threshold = 0.2) across various prediction methods.

Prediction Pair Plot

Pair plots of the predicted binarized LVMi responses (threshold = 0.2) across various prediction methods. Each point represents an individual in the validation set, and the coordinates represent the predicted probability of having high LVMi from two different prediction methods, which are specified by the x and y-axes labels in each subplot. Density distributions of the predicted probabilities are shown along the diagonal.

Figure 5.9: Pair plots of the predicted binarized LVMi responses (threshold = 0.2) across various prediction methods. Each point represents an individual in the validation set, and the coordinates represent the predicted probability of having high LVMi from two different prediction methods, which are specified by the x and y-axes labels in each subplot. Density distributions of the predicted probabilities are shown along the diagonal.

Binarization Threshold = 0.25

Confusion Tables

Figure 5.10: Confusion matrix from various prediction models for predicting the binarized LVMi phenotype (binarization threshold = 0.25).

ROC/PR Curves

Figure 5.11: ROC curve for predicting the binarized LVMi (threshold = 0.25) across various prediction methods. TPR = true positive rate; FPR = false positive rate.

Figure 5.12: Precision-recall curve for predicting the binarized LVMi (threshold = 0.25) across various prediction methods.

Prediction Pair Plot

Pair plots of the predicted binarized LVMi responses (threshold = 0.25) across various prediction methods. Each point represents an individual in the validation set, and the coordinates represent the predicted probability of having high LVMi from two different prediction methods, which are specified by the x and y-axes labels in each subplot. Density distributions of the predicted probabilities are shown along the diagonal.

Figure 5.13: Pair plots of the predicted binarized LVMi responses (threshold = 0.25) across various prediction methods. Each point represents an individual in the validation set, and the coordinates represent the predicted probability of having high LVMi from two different prediction methods, which are specified by the x and y-axes labels in each subplot. Density distributions of the predicted probabilities are shown along the diagonal.

6 Prioritization Step

Overview

Having passed the prediction check, we finally proceed to interpret the siRF fit in the last step of lo-siRF. In this step, we developed a novel stability-driven feature importance score to prioritize both genetic loci and interactions between genetic loci from siRF. We refer to Q. Wang et al. (2023) for the detailed description of this new importance score and here provide brief insights into the motivation and intuition behind this method.

Main idea: At a high-level, this new importance score (1) aggregates weak, unstable SNV-level importances from siRF into stronger, more stable locus-level importances and (2) can be leveraged to evaluate both the marginal importance of a genetic locus in siRF as well as the importance of higher-order interactions between genetic loci in siRF. The need for this locus-level feature importance score stems from two main reasons: the high correlation between SNVs and the weak phenotypic signal. Though the prediction models (including siRF) are all trained using SNV data, it is often very challenging to interpret the importance of an individual SNV from these models due to the high correlation between SNVs (Toloşi and Lengauer 2011; Hooker, Mentch, and Zhou 2021), which we observed in our previous exploratory data analysis (see Choice of Phenotypic Data tab). To further complicate matters, the weak phenotypic signal increases the instability of existing feature importance methods in that we see the feature rankings change drastically when using different bootstrap training samples. Given these challenges with SNV-level feature importances, it is then no surprise that siRF, out-of-the-box, does not find any stable interactions between SNVs (i.e., the siRF stability score is around 0 for all interactions between SNVs). To address these challenges, our new feature importance score leverages the correlation structure between SNVs, groups SNVs into genetic loci, and aggregates weak, unstable SNV-level importances from siRF into stronger, more stable locus-level importances.

Motivation behind new feature importance score: To better understand the motivation and construction of our new locus-level feature importance score, it can be helpful to first review the original importance score used in siRF (Kumbier et al. 2023). Briefly, in the original version of siRF, the importance of a signed interaction is based upon how stable or frequently it occurs in decisions paths across the random forest – that is, based upon the number of decision paths for which every signed feature in the signed interaction was used in at least one decision split (see Kumbier et al. (2023) for details). Following a similar logic, one natural path forward to calculate a locus-level importance from a forest that was fit on SNV data is as follows:

  1. Take the fitted forest, where each decision split used some SNV to make the split.
  2. Map each SNV used in a decision split to its corresponding genetic loci (e.g., using annotation software like ANNOVAR (K. Wang, Li, and Hakonarson 2010)).
  3. Compute the importance of a signed locus-level interaction based upon the frequency of occurrence of the interaction as before, but using the mapped genetic loci in lieu of the SNVs. That is, compute the number of decision paths for which every signed locus in the signed locus-level interaction was used in at least one decision split.

However, this frequency of occurrence measure is heavily tied to the number of SNVs that belong to each genetic locus. A genetic locus that consists of more SNVs will naturally have a higher frequency of occurrence than a genetic locus with only a few SNVs even though both genetic loci may be equally important (or unimportant). In other words, the original siRF importance score, measuring the frequency of occurrence, is not comparable across genetic loci. This bias is problematic given that we have previously seen some genetic loci may consist of only 1 SNV while other genetic loci have >50 SNVs (see GWAS-filtered SNVs tab in the Dimension Reduction Step).

Intuition behind new feature importance score: To alleviate this bias, we leverage the idea of a local feature importance score, where we compute a per-individual score that measures the importance of a locus/interaction for making the prediction of each individual. This is in contrast to a global feature importance score, which is a measure of importance for the entire group of individuals under study. While a global feature importance score gives rise to a single score for the entire population under study, we can compute a local feature importance score for each individual in the population. By computing a local feature importance score for each individual (i.e., this is the local stability importance (LSI) score from Q. Wang et al. (2023)), we can compare the importance of the locus/interaction across individuals and avoid the across-loci comparison that was problematic in the aforementioned discussion. This comparison is done via a permutation test in Q. Wang et al. (2023). Moreover, since we are comparing the local feature importances between individuals within or per loci/interaction in this permutation test, the local feature importances are all measured on the same scale and comparable, thereby mitigating the bias towards genetic loci with more SNVs.

How to aggregate SNVs: We mapped each SNV to its corresponding genetic locus using ANNOVAR (K. Wang, Li, and Hakonarson 2010) according to the hg19 refSeq Gene annotations. Given our ultimate goal of recommending/prioritizing genetic loci and interactions between loci for downstream analyses and experimental validation, we believe this choice provides an appropriate starting point to obtain actionable recommendations. However, we note that there are many alternative ways of aggregating SNVs. For example, it is possible to aggregate SNVs according to LD/haplotype blocks or to include additional gene-based or functional annotations in the aggregation scheme.

Organization: Under the SNV-level Importances tab, we provide the SNV-level feature importances from the fitted prediction algorithms (described in the Prediction Step section) for completeness. These SNV-level feature importances are very unstable across methods and across bootstrap perturbations for the reasons discussed above. We then summarize the results from the lo-siRF pipeline including the rankings of genetic loci and interaction between genetic loci using our new locus-level importance score under the Summary of lo-siRF Results tab. A final technical note on the advantages of incorporating signed information from siRF in this feature importance computation is provided under the Advantages of Signed Information tab.

SNV-level Feature Importances

Having observed that the aforementioned classification algorithms do have some predictive power to predict those with high versus low LVMi, a natural next step is to investigate which SNVs were used in these prediction models. Below, we highlight the top 100 SNVs, ranked by importance in each of the prediction models. For completeness, we provide the SNV importances for the unbinarized LVMi (regression) problem as well as the binarized LVMi (classification) problem across the three different binarization thresholds.

How is importance defined?

  • For ridge and Lasso, the importance of an SNV is defined as the magnitude of its coefficient in the prediction model.
  • For RF, the importance of an SNV is determined by the mean decrease in impurity (MDI) score.
  • For siRF, the importance of an SNV is determined by the MDI from the forest in the final iteration.
  • Due to the computational complexity, we did not compute the SNV importances from the SVM fit as there is no built-in model-based feature importance method (in R), and any permutation-based approach would be computationally expensive.

A word of caution: When interpreting these SNV importances, it is crucial to keep in mind that there are very large, strongly correlated blocks of SNVs within this data, which often renders the feature rankings unmeaningful and unstable (Toloşi and Lengauer 2011; Hooker, Mentch, and Zhou 2021). In particular, it is well-known that the MDI variable importance metric used in RF/iRF/siRF is biased against correlated features (Hooker, Mentch, and Zhou 2021). In other words, SNVs within large LD blocks tend to have artificially low MDI values. Given these idiosyncrasies, it is unsurprising that SNVs from TTN and CCDC141 – two genetic loci with many SNVs under LD – do not have high importances according to MDI. We provide these SNV importance tables only for completeness and to partially motivate the need to aggregate SNV-level importances into locus-level importances in lo-siRF.

Unbinarized (Regression)

Lasso

Figure 6.1: Lasso - Top 100 SNVs, ranked by importance, for predicting LVMi.

Ridge

Figure 6.2: Ridge - Top 100 SNVs, ranked by importance, for predicting LVMi.

RF

Figure 6.3: RF - Top 100 SNVs, ranked by importance, for predicting LVMi.

siRF

Figure 6.4: siRF - Top 100 SNVs, ranked by importance, for predicting LVMi.

Binarization Threshold = 0.15

Lasso

Figure 6.5: Lasso - Top 100 SNVs, ranked by importance, for predicting the binarized LVMi (threshold = 0.15).

Ridge

Figure 6.6: Ridge - Top 100 SNVs, ranked by importance, for predicting the binarized LVMi (threshold = 0.15).

RF

Figure 6.7: RF - Top 100 SNVs, ranked by importance, for predicting the binarized LVMi (threshold = 0.15).

siRF

Figure 6.8: siRF - Top 100 SNVs, ranked by importance, for predicting the binarized LVMi (threshold = 0.15).

Binarization Threshold = 0.2

Lasso

Figure 6.9: Lasso - Top 100 SNVs, ranked by importance, for predicting the binarized LVMi (threshold = 0.2).

Ridge

Figure 6.10: Ridge - Top 100 SNVs, ranked by importance, for predicting the binarized LVMi (threshold = 0.2).

RF

Figure 6.11: RF - Top 100 SNVs, ranked by importance, for predicting the binarized LVMi (threshold = 0.2).

siRF

Figure 6.12: siRF - Top 100 SNVs, ranked by importance, for predicting the binarized LVMi (threshold = 0.2).

Binarization Threshold = 0.25

Lasso

Figure 6.13: Lasso - Top 100 SNVs, ranked by importance, for predicting the binarized LVMi (threshold = 0.25).

Ridge

Figure 6.14: Ridge - Top 100 SNVs, ranked by importance, for predicting the binarized LVMi (threshold = 0.25).

RF

Figure 6.15: RF - Top 100 SNVs, ranked by importance, for predicting the binarized LVMi (threshold = 0.25).

siRF

Figure 6.16: siRF - Top 100 SNVs, ranked by importance, for predicting the binarized LVMi (threshold = 0.25).

Summary of lo-siRF Results

Finally, we summarize the prioritization results from the lo-siRF pipeline using our new importance score to rank genetic loci and interactions between genetic loci. In this new importance score, we (1) computed a local (i.e., on a per-individual basis) stability importance score that aggregates weak SNV-level importances into stronger locus-level importances using the siRF fit and (2) conducted a permutation test to assess whether the local stability importance scores for a given locus/interaction are different between individuals with high and low LVMi (conditioned on the rest of the fitted forest). The larger the difference in local stability importance scores between those with high versus low LVMi, the greater the importance of the locus/interaction for predicting LVMi. For details on the new importance score, we refer to Q. Wang et al. (2023).

Below, we recap the siRF prediction accuracy for predicting the binarized LVMi across the three binarization thresholds (15%, 20%, 25%) (Figure 6.17). Then, in Figure 6.18, we summarize the prioritization rankings of genetic loci and interaction between loci according to the new importance score. We provide the permutation p-values along with the permutation test statistic, that is, the difference in local feature stability scores between the high and low LVMi groups, with the standard deviation of this permutation distribution in parentheses.

Note that the permutation test was not performed for all loci/interactions (details in Q. Wang et al. (2023)). Given our primary aim of generating reliable hypotheses for follow-up experimental validation, we chose to only test loci/interactions that were predictive and stable in the siRF fit, following the PCS framework for veridical data science (Yu and Kumbier 2020). Specifically, for each binarization threshold, we only tested:

  • the top 25 loci with the highest average local stability importance scores, or in other words, those that occurred most stably/frequently (and thus likely predictive) in the siRF fit, and
  • the interactions between loci that were identified by siRF and achieved a stability score > 0.5, stability score for mean increase in precision > 0, and stability score for independence of feature selection > 0. We note that in addition to the explicit stability checks here, the requirement on the mean increase in precision serves as a predictability check, and the requirement on the independence of feature selection serves to differentiate marginal additive effects from non-additive interaction effects (see Kumbier et al. (2023) for details).

By implementing this additional predictability and stability check, we are requiring that the prioritized loci/interactions meet a higher standard, with the hope that this ultimately generates more reliable (albeit more conservative) experimental recommendations.

In addition to the provided summary of results,

  • Under the siRF Interaction Table tab, we provide the full siRF locus-level interaction table output for each binarization threshold (Figures 6.19, 6.21, and 6.23). This table includes several metrics for evaluating the stability and strength of the interaction. For details on these metrics, we refer to Kumbier et al. (2023).
    • For comparison, we also provide the analogous siRF output for interactions at the SNV level (Figures 6.20, 6.22, and 6.24). Here, we see that if we do not perform the SNV-to-locus aggregation, the stability scores for the SNV-level interactions are very close to 0. This means that the siRF-identified SNV-level interactions rarely appear when siRF is refitted using different bootstrapped training samples. As discussed previously, this instability is partially due to the correlation among SNVs and the weak phenotypic signal. This high instability also motivates the need for an alternative approach via our new importance score.
  • Under the Local Stability Importance Plots - Interactions and Local Stability Importance Plots - Loci, we provide visualizations of the density distribution of local stability importance scores between the low and high LVMi groups as well as the frequency distribution of SNVs used in the siRF fit (i.e., which SNVs occurred most frequently in the decision paths across the siRF fit).
    • In the density distribution of local stability importance scores, observable differences between the low and high LVMi groups are evidence that the genetic locus or interaction between loci is important for differentiating between individuals with high versus low LVMi. The larger the difference, the greater the importance of the locus or interaction between loci.
    • In the SNV frequency distributions, we show the frequency of occurrence for each SNV or SNV pair in the siRF fit. This is the number of decision paths for which the SNV or SNV pair appeared in the siRF fit. SNVs or SNV pairs with the highest number of occurrences in the RF decision paths (y-axis) contributed the most to the overall locus/interaction’s importance in the siRF fit.

Summary

Figure 6.17: Summary of the validation prediction performance from siRF across various LVMi binarization thresholds.

Figure 6.18: Summary of the lo-siRF permutation test results across various LVMi binarization thresholds including the test statistic (i.e., difference in local feature stability scores between the high and the low LVMi groups (SD in parentheses) and the resulting p-values. Blank cells indicate that the locus/interaction was not selected for testing for the given binarization threshold. Loci/interactions are ranked according to the mean p-value across all three binarization thresholds. Interactions between genetic loci are highlighted in blue.

siRF Interaction Table

0.15

Figure 6.19: Summary of the siRF locus-level interaction table output for the binarized LVMi phenotype (binarization threshold = 0.15). For all metrics excluding the lo-siRF mean permutation p-value, higher values indicate a stronger interaction. Details regarding these metrics in the siRF interaction table output can be found in Kumbier et al. (2018).

Figure 6.20: Summary of the siRF SNV-level interaction table output for the binarized LVMi phenotype (binarization threshold = 0.15). Stability scores for all interactions are close to 0, suggesting unreliable SNV-level interactions. Details regarding these metrics in the siRF interaction table output can be found in Kumbier et al. (2018).

0.2

Figure 6.21: Summary of the siRF locus-level interaction table output for the binarized LVMi phenotype (binarization threshold = 0.2). For all metrics excluding the lo-siRF mean permutation p-value, higher values indicate a stronger interaction. Details regarding these metrics in the siRF interaction table output can be found in Kumbier et al. (2018).

Figure 6.22: Summary of the siRF SNV-level interaction table output for the binarized LVMi phenotype (binarization threshold = 0.2). Stability scores for all interactions are close to 0, suggesting unreliable SNV-level interactions. Details regarding these metrics in the siRF interaction table output can be found in Kumbier et al. (2018).

0.25

Figure 6.23: Summary of the siRF locus-level interaction table output for the binarized LVMi phenotype (binarization threshold = 0.25). For all metrics excluding the lo-siRF mean permutation p-value, higher values indicate a stronger interaction. Details regarding these metrics in the siRF interaction table output can be found in Kumbier et al. (2018).

Figure 6.24: Summary of the siRF SNV-level interaction table output for the binarized LVMi phenotype (binarization threshold = 0.25). Stability scores for all interactions are close to 0, suggesting unreliable SNV-level interactions. Details regarding these metrics in the siRF interaction table output can be found in Kumbier et al. (2018).

Local Stability Importance Plots - Interactions

0.15

Distribution of local stability importance scores between the high and low LVMi groups (binarization threshold = 0.15) for each signed interaction between loci (specified by subplot) that passed the siRF stability filter. The permutation test p-value, assessing distributional differences between the high and low LVMi groups, is provided in the top right corner of each subplot.

Figure 6.25: Distribution of local stability importance scores between the high and low LVMi groups (binarization threshold = 0.15) for each signed interaction between loci (specified by subplot) that passed the siRF stability filter. The permutation test p-value, assessing distributional differences between the high and low LVMi groups, is provided in the top right corner of each subplot.

Figure 6.26: Frequency of occurrence of SNV-SNV combinations in the siRF fit for the binarized LVMi phenotype (binarization threshold = 0.15). SNV-SNV combinations with the highest number of occurrences in the siRF decision paths contribute the most to the overall locus-level interaction importance in the siRF fit.

0.2

Distribution of local stability importance scores between the high and low LVMi groups (binarization threshold = 0.2) for each signed interaction between loci (specified by subplot) that passed the siRF stability filter. The permutation test p-value, assessing distributional differences between the high and low LVMi groups, is provided in the top right corner of each subplot.

Figure 6.27: Distribution of local stability importance scores between the high and low LVMi groups (binarization threshold = 0.2) for each signed interaction between loci (specified by subplot) that passed the siRF stability filter. The permutation test p-value, assessing distributional differences between the high and low LVMi groups, is provided in the top right corner of each subplot.

Figure 6.28: Frequency of occurrence of SNV-SNV combinations in the siRF fit for the binarized LVMi phenotype (binarization threshold = 0.2). SNV-SNV combinations with the highest number of occurrences in the siRF decision paths contribute the most to the overall locus-level interaction importance in the siRF fit.

0.25

Distribution of local stability importance scores between the high and low LVMi groups (binarization threshold = 0.25) for each signed interaction between loci (specified by subplot) that passed the siRF stability filter. The permutation test p-value, assessing distributional differences between the high and low LVMi groups, is provided in the top right corner of each subplot.

Figure 6.29: Distribution of local stability importance scores between the high and low LVMi groups (binarization threshold = 0.25) for each signed interaction between loci (specified by subplot) that passed the siRF stability filter. The permutation test p-value, assessing distributional differences between the high and low LVMi groups, is provided in the top right corner of each subplot.

Figure 6.30: Frequency of occurrence of SNV-SNV combinations in the siRF fit for the binarized LVMi phenotype (binarization threshold = 0.25). SNV-SNV combinations with the highest number of occurrences in the siRF decision paths contribute the most to the overall locus-level interaction importance in the siRF fit.

Local Stability Importance Plots - Loci

0.15

Distribution of local stability importance scores between the high and low LVMi groups (binarization threshold = 0.15) for each signed locus (specified by subplot). Here, we show only the top 25 signed loci, ranked by their average local stability importance scores. The permutation test p-value, assessing distributional differences between the high and low LVMi groups, is provided in the top right corner of each subplot.

Figure 6.31: Distribution of local stability importance scores between the high and low LVMi groups (binarization threshold = 0.15) for each signed locus (specified by subplot). Here, we show only the top 25 signed loci, ranked by their average local stability importance scores. The permutation test p-value, assessing distributional differences between the high and low LVMi groups, is provided in the top right corner of each subplot.

Figure 6.32: Frequency of occurrence of SNVs in the siRF fit for the binarized LVMi phenotype (binarization threshold = 0.15). SNVs with the highest number of occurrences in the siRF decision paths contribute the most to the overall locus-level importance in the siRF fit. SNVs are ordered on the x-axis by genomic location.

0.2

Distribution of local stability importance scores between the high and low LVMi groups (binarization threshold = 0.2) for each signed locus (specified by subplot). Here, we show only the top 25 signed loci, ranked by their average local stability importance scores. The permutation test p-value, assessing distributional differences between the high and low LVMi groups, is provided in the top right corner of each subplot.

Figure 6.33: Distribution of local stability importance scores between the high and low LVMi groups (binarization threshold = 0.2) for each signed locus (specified by subplot). Here, we show only the top 25 signed loci, ranked by their average local stability importance scores. The permutation test p-value, assessing distributional differences between the high and low LVMi groups, is provided in the top right corner of each subplot.

Figure 6.34: Frequency of occurrence of SNVs in the siRF fit for the binarized LVMi phenotype (binarization threshold = 0.2). SNVs with the highest number of occurrences in the siRF decision paths contribute the most to the overall locus-level importance in the siRF fit. SNVs are ordered on the x-axis by genomic location.

0.25

Distribution of local stability importance scores between the high and low LVMi groups (binarization threshold = 0.25) for each signed locus (specified by subplot). Here, we show only the top 25 signed loci, ranked by their average local stability importance scores. The permutation test p-value, assessing distributional differences between the high and low LVMi groups, is provided in the top right corner of each subplot.

Figure 6.35: Distribution of local stability importance scores between the high and low LVMi groups (binarization threshold = 0.25) for each signed locus (specified by subplot). Here, we show only the top 25 signed loci, ranked by their average local stability importance scores. The permutation test p-value, assessing distributional differences between the high and low LVMi groups, is provided in the top right corner of each subplot.

Figure 6.36: Frequency of occurrence of SNVs in the siRF fit for the binarized LVMi phenotype (binarization threshold = 0.25). SNVs with the highest number of occurrences in the siRF decision paths contribute the most to the overall locus-level importance in the siRF fit. SNVs are ordered on the x-axis by genomic location.

Advantages of Signed Information

Though the signed information is not pertinent to our goal of prioritizing/recommending candidate markers for experiments, the signed information from siRF provides more granular information that can improve our interpretation of the fit. To see this, suppose that we did not keep track of the sign of the feature when splitting (i.e., that we do not keep track of whether we split on low or high values of the feature). Suppose also that we would like to measure the importance of feature \(X_1\), which was used as the first (root) split in tree \(T\). In the first step in our new importance score computation, we compute the local stability importance (LSI) score of \(X_1\) for each individual \(i\). If we do not keep track of the sign of the \(X_1\) split, then \(X_1\) appears on every individual’s decision path so that \(LSI_T(X_1, i) = 1\) for every individual \(i\). In the next step of our new importance score computation, we perform a permutation test to assess whether there is a difference in the LSI scores for individuals with high LVMi and those with low LVMi. Since \(LSI_T(X_1, i) = 1\) for every \(i\), this permutation test will return a p-value of 1. This suggests that \(X_1\) is an unimportant feature in this model. However, this is counterintuitive given that \(X_1\) was split on first in the tree and should be considered one of the most important features in this tree. By keeping track of the signed information of the splits as done in siRF, we can utilize this more granular information to mitigate the issue discussed above and improve our interpretation of the siRF fit.

Moreover, to facilitate the interpretation of this signed information, it can be beneficial to aggregate SNV features that are positively correlated (as opposed to negatively correlated) into a single locus (or group). Since the encoding of SNVs as a value taking on 0, 1, or 2 is rather arbitrary (e.g., a value of 0 can be re-encoded to take on the value of 2 by changing the reference allele), we can choose the encoding of the SNV to try to avoid strong negative correlations within a locus. More specifically, for each genetic locus which consists of SNVs \(X_1, \ldots, X_g\), we choose to “flip” the encoding of the SNV \(X_j\) (\(j = 2, \ldots, g\)) if the Pearson correlation between the observed values of \(X_j\) and \(X_1\) is below -0.15. Here, we use the term “flip” to mean the application of the function that maps 0 to 2, 1 to 1, and 2 to 0. This correlation threshold of -0.15 was chosen by visually inspecting the resulting pairwise correlations between \(X_i\) and \(X_j\) for all \(i, j = 1, \ldots, g\) and checking that these pairwise correlations are not strongly negative. However, while we focus on the lo-siRF prioritization results using this correlation threshold of -0.15, the results appear to be robust to other reasonable correlation threshold choices (e.g., -0.05, -0.25). Further analysis and improvements to this procedure are very interesting for future work.

7 Final Remarks

We reiterate that lo-siRF was originally developed as a first-stage recommendation (or hypothesis generation) tool within a broader pipeline in order to prioritize genetic loci and interactions between loci for downstream analyses and experimental validation. Importantly, the output of lo-siRF is a prioritization/ranking order, not a proper statistical test of significance. We rely on follow-up investigations and in this study rigorous gene-silencing experiments in order to validate the prioritized genetic loci and interaction between loci. With that, many of the modeling decisions and human judgment calls were made with this original use case in mind. For other use cases or problems, it is highly likely that different choices may be better suited. We also acknowledge that though many stability checks were conducted to help ensure that our conclusions are stable across different reasonable data and/or modeling perturbations, these stability checks are inevitably constrained by computational limitations, and additional stability analyses can be conducted. We hope that by documenting our modeling choices, stability analyses, and providing insights into our motivations/reasons, this may help to both clarify the limitations of our current work and to facilitate the trustworthy (veridical) use of lo-siRF (and variants thereof) in other scientific problems.

8 Bibliography

Allen, Ben, Morgan Lane, Elizabeth Anderson Steeves, and Hollie Raynor. 2022. “Using Explainable Artificial Intelligence to Discover Interactions in an Ecological Model for Obesity.” International Journal of Environmental Research and Public Health 19 (15): 9447.
Bai, Wenjia, Matthew Sinclair, Giacomo Tarroni, Ozan Oktay, Martin Rajchl, Ghislain Vaillant, Aaron M Lee, et al. 2018. “Automated Cardiovascular Magnetic Resonance Image Analysis with Fully Convolutional Networks.” Journal of Cardiovascular Magnetic Resonance 20 (1): 1–12.
Behr, Merle, Karl Kumbier, Aldo Cordova-Palomera, Matthew Aguirre, Euan Ashley, Atul J Butte, Rima Arnaout, Ben Brown, James Priest, and Bin Yu. 2020. “Learning Epistatic Polygenic Phenotypes with Boolean Interactions.” bioRxiv, 2020–11.
Bycroft, Clare, Colin Freeman, Desislava Petkova, Gavin Band, Lloyd T Elliott, Kevin Sharp, Allan Motyer, et al. 2018. “The UK Biobank Resource with Deep Phenotyping and Genomic Data.” Nature 562 (7726): 203–9.
Cliff, Ashley, Jonathon Romero, David Kainer, Angelica Walker, Anna Furches, and Daniel Jacobson. 2019. “A High-Performance Computing Implementation of Iterative Random Forest for the Creation of Predictive Expression Networks.” Genes 10 (12): 996.
De Rosa, Arianna, Andrea Fontana, Tommaso Nuzzo, Martina Garofalo, Anna Di Maio, Daniela Punzo, Massimiliano Copetti, et al. 2022. “Machine Learning Algorithm Unveils Glutamatergic Alterations in the Post-Mortem Schizophrenia Brain.” Schizophrenia 8 (1): 8.
Du Bois, Delafield, and Eugene F Du Bois. 1916. “Clinical Calorimetry: Tenth Paper a Formula to Estimate the Approximate Surface Area If Height and Weight Be Known.” Archives of Internal Medicine 17 (6_2): 863–71.
Engel, David J, Allan Schwartz, and Shunichi Homma. 2016. “Athletic Cardiac Remodeling in US Professional Basketball Players.” JAMA Cardiology 1 (1): 80–87.
Fry, Anna, Thomas J Littlejohns, Cathie Sudlow, Nicola Doherty, Ligia Adamska, Tim Sprosen, Rory Collins, and Naomi E Allen. 2017. “Comparison of Sociodemographic and Health-Related Characteristics of UK Biobank Participants with Those of the General Population.” American Journal of Epidemiology 186 (9): 1026–34.
Harper, Andrew R, Anuj Goel, Christopher Grace, Kate L Thomson, Steffen E Petersen, Xiao Xu, Adam Waring, et al. 2021. “Common Genetic Variants and Modifiable Risk Factors Underpin Hypertrophic Cardiomyopathy Susceptibility and Expressivity.” Nature Genetics 53 (2): 135–42.
Hooker, Giles, Lucas Mentch, and Siyu Zhou. 2021. “Unrestricted Permutation Forces Extrapolation: Variable Importance Requires at Least One More Model, or There Is No Free Variable Importance.” Statistics and Computing 31: 1–16.
Khurshid, Shaan, Julieta Lazarte, James P Pirruccello, Lu-Chen Weng, Seung Hoan Choi, Amelia W Hall, Xin Wang, et al. 2023. “Clinical and Genetic Associations of Deep Learning-Derived Cardiac Magnetic Resonance-Based Left Ventricular Mass.” Nature Communications 14 (1): 1558.
Kumbier, Karl, Sumanta Basu, Erwin Frise, James B Brown, Susan Celniker, and Bin Yu. 2023. “Signed Iterative Random Forests to Identify Enhancer-Associated Transcription Factor Binding.” arXiv Preprint arXiv:1810.07287.
Loh, Po-Ru, George Tucker, Brendan K Bulik-Sullivan, Bjarni J Vilhjalmsson, Hilary K Finucane, Rany M Salem, Daniel I Chasman, et al. 2015. “Efficient Bayesian Mixed-Model Analysis Increases Association Power in Large Cohorts.” Nature Genetics 47 (3): 284–90.
Meyer, Hannah V, Timothy JW Dawes, Marta Serrani, Wenjia Bai, Paweł Tokarczuk, Jiashen Cai, Antonio de Marvao, et al. 2020. “Genetic and Functional Insights into the Fractal Structure of the Heart.” Nature 584 (7822): 589–94.
Mizukoshi, Kei, Masaaki Takeuchi, Yasufumi Nagata, Karima Addetia, Roberto M Lang, Yoshihiro J Akashi, and Yutaka Otsuji. 2016. “Normal Values of Left Ventricular Mass Index Assessed by Transthoracic Three-Dimensional Echocardiography.” Journal of the American Society of Echocardiography 29 (1): 51–61.
Nelson, David L, Albert L Lehninger, and Michael M Cox. 2008. Lehninger Principles of Biochemistry. Macmillan.
Niel, Clément, Christine Sinoquet, Christian Dina, and Ghislain Rocheleau. 2015. “A Survey about Methods Dedicated to Epistasis Detection.” Frontiers in Genetics 6: 285.
Pirruccello, James P, Alexander Bick, Minxian Wang, Mark Chaffin, Samuel Friedman, Jie Yao, Xiuqing Guo, et al. 2020. “Analysis of Cardiac Magnetic Resonance Imaging in 36,000 Individuals Yields Genetic Insights into Dilated Cardiomyopathy.” Nature Communications 11 (1): 2254.
Purcell, Shaun, Benjamin Neale, Kathe Todd-Brown, Lori Thomas, Manuel AR Ferreira, David Bender, Julian Maller, et al. 2007. “PLINK: A Tool Set for Whole-Genome Association and Population-Based Linkage Analyses.” The American Journal of Human Genetics 81 (3): 559–75.
Schaid, Daniel J, Wenan Chen, and Nicholas B Larson. 2018. “From Genome-Wide Associations to Candidate Causal Variants by Statistical Fine-Mapping.” Nature Reviews Genetics 19 (8): 491–504.
Toloşi, Laura, and Thomas Lengauer. 2011. “Classification with Correlated Features: Unreliability of Feature Ranking and Solutions.” Bioinformatics 27 (14): 1986–94.
Visscher, Peter M, Naomi R Wray, Qian Zhang, Pamela Sklar, Mark I McCarthy, Matthew A Brown, and Jian Yang. 2017. “10 Years of GWAS Discovery: Biology, Function, and Translation.” The American Journal of Human Genetics 101 (1): 5–22.
Walker, Angelica M, Ashley Cliff, Jonathon Romero, Manesh B Shah, Piet Jones, Joao Gabriel Felipe Machado Gazolla, Daniel A Jacobson, and David Kainer. 2022. “Evaluating the Performance of Random Forest and Iterative Random Forest Based Methods When Applied to Gene Expression Data.” Computational and Structural Biotechnology Journal 20: 3372–86.
Wang, Kai, Mingyao Li, and Hakon Hakonarson. 2010. “ANNOVAR: Functional Annotation of Genetic Variants from High-Throughput Sequencing Data.” Nucleic Acids Research 38 (16): e164–64.
Wang, Qianru, Tiffany M Tang, Nathan Youlton, Chad S Weldy, Ana M Kenney, Omer Ronen, J Weston Hughes, et al. 2023. “Epistasis Regulates Genetic Control of Cardiac Hypertrophy.”
Watanabe, Kyoko, Erdogan Taskesen, Arjen Van Bochoven, and Danielle Posthuma. 2017. “Functional Mapping and Annotation of Genetic Associations with FUMA.” Nature Communications 8 (1): 1826.
Yu, Bin. 2013. “Stability.”
Yu, Bin, and Karl Kumbier. 2020. “Veridical Data Science.” Proceedings of the National Academy of Sciences 117 (8): 3920–29. https://doi.org/10.1073/pnas.1901326117.
LS0tCnRpdGxlOiAiUENTIGRvY3VtZW50YXRpb24gZm9yIGxvdy1zaWduYWwgc2lnbmVkIGl0ZXJhdGl2ZSByYW5kb20gZm9yZXN0cyAobG8tc2lSRikiCiMgYXV0aG9yOiAiVGlmZmFueSBNLiBUYW5nIgpkYXRlOiAiT2N0b2JlciAyOCwgMjAyMyIKYmlibGlvZ3JhcGh5OiBiaWJsaW9ncmFwaHkuYmliCmhlYWRlci1pbmNsdWRlczoKICAgIC0gXHVzZXBhY2thZ2V7ZmxvYXR9CiAgICAtIFx1c2VwYWNrYWdle2Ftc21hdGh9CiAgICAtIFx1c2VwYWNrYWdle2dlbnN5bWJ9Cm91dHB1dDoKICB2dGhlbWVzOjp2bW9kZXJuOgogICAgbnVtYmVyX3NlY3Rpb25zOiB0cnVlCnBhcmFtczoKICBldmFsOiBmYWxzZQotLS0KCgpgYGB7ciBzZXR1cCwgaW5jbHVkZT1GQUxTRX0Kb3B0aW9ucyh3aWR0aCA9IDEwMDAwKQprbml0cjo6b3B0c19jaHVuayRzZXQoCiAgZWNobyA9IEZBTFNFLAogIHdhcm5pbmcgPSBGQUxTRSwKICBtZXNzYWdlID0gRkFMU0UsCiAgY2FjaGUgPSBGQUxTRSwKICBmaWcuYWxpZ24gPSAiY2VudGVyIiwKICBmaWcucG9zID0gIkgiLAogICMgZmlnLnNob3cgPSAiaG9sZCIsCiAgZmlnLmhlaWdodCA9IDEyLAogIGZpZy53aWR0aCA9IDEwCikKCmxpYnJhcnkoa25pdHIpCmxpYnJhcnkoZm9udGF3ZXNvbWUpCmxpYnJhcnkodGlkeXZlcnNlKQpsaWJyYXJ5KGRhdGEudGFibGUpCmxpYnJhcnkocGxvdGx5KQpsaWJyYXJ5KGthYmxlRXh0cmEpCmxpYnJhcnkocGF0Y2h3b3JrKQpsaWJyYXJ5KHZ0aGVtZXMpCmxpYnJhcnkodmRvY3MpCgpzb3VyY2UoZmlsZS5wYXRoKCIuLiIsICJmdW5jdGlvbnMiLCAicGxvdC1mdW5jdGlvbnMuUiIpLCBjaGRpciA9IFQpCnNvdXJjZShmaWxlLnBhdGgoIi4uIiwgImZ1bmN0aW9ucyIsICJsb2FkLWZ1bmN0aW9ucy5SIiksIGNoZGlyID0gVCkKc291cmNlKGZpbGUucGF0aCgiLi4iLCAiZnVuY3Rpb25zIiwgImV2YWwtZnVuY3Rpb25zLlIiKSwgY2hkaXIgPSBUKQoKb3B0aW9ucyhrbml0ci5rYWJsZS5OQSA9ICdOQScsIAogICAgICAgIGRwbHlyLnN1bW1hcmlzZS5pbmZvcm0gPSBGQUxTRSkKCiMgc2Nyb2xsYWJsZSB0ZXh0IG91dHB1dApsb2NhbCh7CiAgaG9va19vdXRwdXQgPC0ga25pdHI6OmtuaXRfaG9va3MkZ2V0KCdvdXRwdXQnKQogIGtuaXRyOjprbml0X2hvb2tzJHNldChvdXRwdXQgPSBmdW5jdGlvbih4LCBvcHRpb25zKSB7CiAgICBpZiAoIWlzLm51bGwob3B0aW9ucyRtYXguaGVpZ2h0KSkgb3B0aW9ucyRhdHRyLm91dHB1dCA8LSBjKAogICAgICBvcHRpb25zJGF0dHIub3V0cHV0LAogICAgICBzcHJpbnRmKCdzdHlsZT0ibWF4LWhlaWdodDogJXM7IicsIG9wdGlvbnMkbWF4LmhlaWdodCkKICAgICkKICAgIGhvb2tfb3V0cHV0KHgsIG9wdGlvbnMpCiAgfSkKfSkKCmRpc3BsYXlfaW1hZ2UgPC0gZnVuY3Rpb24oZm5hbWUsIGNodW5rX2lkeCwgY2FwdGlvbiA9ICInJyIpIHsKICBzdWJjaHVua2lmeSgKICAgIGcgPSBrbml0cjo6aW5jbHVkZV9ncmFwaGljcyhmbmFtZSksIGkgPSBjaHVua19pZHgsIAogICAgY2FwdGlvbiA9IGNhcHRpb24sCiAgICBhZGRfY2xhc3MgPSBjKCJwYW5lbCBwYW5lbC1kZWZhdWx0IiksIAogICAgb3RoZXJfYXJncyA9ICJvdXQud2lkdGg9JzEwMCUnIgogICkKICBjaHVua19pZHggPDwtIGNodW5rX2lkeCArIDEKfQoKc3ViY2h1bmtpZnkgPC0gZnVuY3Rpb24oLi4uKSB7CiAgdnRoZW1lczo6c3ViY2h1bmtpZnkoLi4uKQogIGNhdCgiXG5cbiIpCn0KCmNodW5rX2lkeCA8LSAxCnJlc19kaXIgPC0gZmlsZS5wYXRoKCIuLiIsICJyZXN1bHRzIikKdGFiX3Jlc19kaXIgPC0gZmlsZS5wYXRoKHJlc19kaXIsICJ0YWJsZXMiKQpmaWdfcmVzX2RpciA8LSBmaWxlLnBhdGgocmVzX2RpciwgImZpZ3VyZXMiKQpwaGVub3R5cGVzIDwtIGMoIkxWTWkiID0gImlMVk0iKQpwaGVub3R5cGVzX2FsbCA8LSBjKCJMVk1pIiA9ICJpTFZNIiwgIkxWTSIgPSAiTFZNIikKYGBgCgpgYGB7Y3NzLCBlY2hvPUZBTFNFfQouYnRuLXRvb2xiYXIgewogIGRpc3BsYXk6IG5vbmU7Cn0KCi5maWd1cmUgcC5jYXB0aW9uIHsKICBmb250LXNpemU6IDkwJTsKICBwYWRkaW5nOiA4cHg7Cn0KCi5maWd1cmUgewogIGRpc3BsYXk6IGluaGVyaXQ7Cn0KCi50aC1ncm91cC1oZWFkZXIgewogIHBhZGRpbmc6IDVweCAhaW1wb3J0YW50OwogIGJvcmRlcjogbm9uZSAhaW1wb3J0YW50OwogIHRleHQtYWxpZ246IGNlbnRlcjsKfQoKLnRoLWdyb3VwLWhlYWRlcjphZnRlciB7CiAgY29udGVudDogIiI7IC8qIFRoaXMgaXMgbmVjZXNzYXJ5IGZvciB0aGUgcHNldWRvIGVsZW1lbnQgdG8gd29yay4gKi8gCiAgZGlzcGxheTogYmxvY2s7IC8qIFRoaXMgd2lsbCBwdXQgdGhlIHBzZXVkbyBlbGVtZW50IG9uIGl0cyBvd24gbGluZS4gKi8KICBtYXJnaW46IDAgYXV0bzsgLyogVGhpcyB3aWxsIGNlbnRlciB0aGUgYm9yZGVyLiAqLwogIHdpZHRoOiA5NSU7IC8qIENoYW5nZSB0aGlzIHRvIHdoYXRldmVyIHdpZHRoIHlvdSB3YW50LiAqLwogIHBhZGRpbmctdG9wOiAxNHB4OyAvKiBUaGlzIGNyZWF0ZXMgc29tZSBzcGFjZSBiZXR3ZWVuIHRoZSBlbGVtZW50IGFuZCB0aGUgYm9yZGVyLiAqLwogIGJvcmRlci1ib3R0b206IDFweCBzb2xpZCBibGFjazsgLyogVGhpcyBjcmVhdGVzIHRoZSBib3JkZXIuIFJlcGxhY2UgYmxhY2sgd2l0aCB3aGF0ZXZlciBjb2xvciB5b3Ugd2FudC4gKi8KfQoKLnRoLWdyb3VwLXN1YmhlYWRlciB7CiAgYm9yZGVyLXRvcDogbm9uZSAhaW1wb3J0YW50Owp9CgouY2l0YXRpb24gewogIGNvbG9yOiAjMDA5Njg4Owp9CgouY3NsLWVudHJ5IHsKICBtYXJnaW4tYm90dG9tOiAwLjVlbTsKfQpgYGAKCgojIE92ZXJ2aWV3IHsudGFic2V0IC50YWJzZXQtZmFkZSAudGFic2V0LXZtb2Rlcm59Cgo8ZGl2IGNsYXNzPSJwYW5lbCBwYW5lbC1kZWZhdWx0IHBhZGRlZC1wYW5lbCI+CkluIFtAd2FuZzIwMjNlcGlzdGFzaXNdKCksIHdlIGRldmVsb3BlZCBhbiBlbmQtdG8tZW5kIHBpcGVsaW5lIHRvIGRlbW9uc3RyYXRlIHRoZSByb2xlIG9mIGVwaXN0YXNpcyBpbiB0aGUgZ2VuZXRpYyBjb250cm9sIG9mIGNhcmRpYWMgaHlwZXJ0cm9waHkuIApUaGlzIHBpcGVsaW5lIGNvbnNpc3RlZCBvZiBmb3VyIG1ham9yIHBoYXNlczogCigxKSB0aGUgZGVyaXZhdGlvbiBvZiBlc3RpbWF0ZXMgb2YgbGVmdCB2ZW50cmljdWxhciBtYXNzIHZpYSBkZWVwIGxlYXJuaW5nLAooMikgdGhlIGNvbXB1dGF0aW9uYWwgcHJpb3JpdGl6YXRpb24gb2YgZXBpc3RhdGljIGRyaXZlcnMgYmFzZWQgb24gZGF0YSBmcm9tIHRoZSBVSyBCaW9iYW5rIFtAYnljcm9mdDIwMTh1a10sIAooMykgZnVuY3Rpb25hbCBpbnRlcnByZXRhdGlvbiBvZiB0aGUgaHlwb3RoZXNpemVkIGVwaXN0YXRpYyBnZW5ldGljIGxvY2ksIGFuZCAKKDQpIGV4cGVyaW1lbnRhbCBjb25maXJtYXRpb24gb2YgZXBpc3Rhc2lzIGluIGNhcmRpYWMgdHJhbnNjcmlwdG9tZSBhbmQgY2FyZGlhYyBjZWxsdWxhciBtb3JwaG9sb2d5LgoKSGVyZSwgd2UgZXhwYW5kIHVwb24gdGhlIGNvbXB1dGF0aW9uYWwgcHJpb3JpdGl6YXRpb24gb2YgZXBpc3RhdGljIGRyaXZlcnMgcGhhc2UuIApJbiB0aGlzIHBoYXNlLCB3ZSBsZXZlcmFnZWQgbGFyZ2Utc2NhbGUgZ2VuZXRpYyBhbmQgY2FyZGlhYyBNUkkgZGF0YSBmcm9tIHRoZSBVSyBCaW9iYW5rIGFuZCBkZXZlbG9wZWQgdGhlIGxvdy1zaWduYWwgc2lnbmVkIGl0ZXJhdGl2ZSByYW5kb20gZm9yZXN0IChsby1zaVJGKSB0byBwcmlvcml0aXplIGdlbmV0aWMgbG9jaSBhbmQgaW50ZXJhY3Rpb25zIGJldHdlZW4gbG9jaSBmb3IgZG93bnN0cmVhbSBpbnZlc3RpZ2F0aW9ucy4gCkFzIGxvLXNpUkYgaXMgaGVhdmlseSByb290ZWQgaW4gdGhlIFByZWRpY3RhYmlsaXR5LCBDb21wdXRhYmlsaXR5LCBhbmQgU3RhYmlsaXR5IChQQ1MpIGZyYW1ld29yayBmb3IgdmVyaWRpY2FsICh0cnVzdHdvcnRoeSkgZGF0YSBzY2llbmNlIFtAeXUyMDIwdmVyaWRpY2FsXSwgd2UgY29uZHVjdGVkIGV4dGVuc2l2ZSBzdGFiaWxpdHkgYW5hbHlzZXMgdG8gaGVscCBtaW5pbWl6ZSB0aGUgaW1wYWN0IG9mIGh1bWFuIGp1ZGdtZW50IGNhbGxzIGFuZCBtb2RlbGluZyBkZWNpc2lvbnMgb24gb3VyIHNjaWVudGlmaWMgY29uY2x1c2lvbnMuIApJbiB0aGlzIHN1cHBsZW1lbnRhcnkgUENTIGRvY3VtZW50YXRpb24sIHdlIHdpbGw6CgoxLiBUcmFuc3BhcmVudGx5IGRvY3VtZW50IGFuZCBqdXN0aWZ5IHRoZSBtYW55IGh1bWFuIGp1ZGdtZW50IGNhbGxzIGFuZCBtb2RlbGluZyBkZWNpc2lvbnMgdGhhdCB3ZXJlIGluZXZpdGFibHkgbWFkZSB0aHJvdWdob3V0IG91ciBzdGF0aXN0aWNhbCBhbmFseXNpcy4KMi4gUHJvdmlkZSBhZGRpdGlvbmFsIGV4cGxvcmF0aW9uIGFuZCBpbnNpZ2h0IGludG8gdGhlIG1haW4gcmVzdWx0cyBwcmVzZW50ZWQgaW4gW0B3YW5nMjAyM2VwaXN0YXNpc10oKSBhbG9uZ3NpZGUgdGhlIHN0YWJpbGl0eSBhbmFseXNlcy4KCkluIHdoYXQgZm9sbG93cywgd2Ugb3JnYW5pemUgdGhpcyBkb2N1bWVudGF0aW9uIGJ5IHN0ZXAgaW4gdGhlIGxvLXNpUkYgcGlwZWxpbmUgKHNlZSBbQHdhbmcyMDIzZXBpc3Rhc2lzXSgpKSwgYmVnaW5uaW5nIHdpdGggdGhlIGNob2ljZSBvZiBwaGVub3R5cGljIGRhdGEsIGZvbGxvd2VkIGJ5IHRoZSBkaW1lbnNpb24gcmVkdWN0aW9uIHN0ZXAsIGJpbmFyaXphdGlvbiBzdGVwLCBwcmVkaWN0aW9uIHN0ZXAsIGFuZCBjb25jbHVkaW5nIHdpdGggdGhlIHByaW9yaXRpemF0aW9uIHN0ZXAuCgo8L2Rpdj4KCgojIENob2ljZSBvZiBQaGVub3R5cGljIERhdGEgey50YWJzZXQgLnRhYnNldC1mYWRlIC50YWJzZXQtdm1vZGVybn0KCjxkaXYgY2xhc3M9InBhbmVsIHBhbmVsLWRlZmF1bHQgcGFkZGVkLXBhbmVsIj4KSW4gdGhlIGZpcnN0IHN0ZXAgb2YgbG8tc2lSRiwgd2UgYmVnYW4gd2l0aCBhIGNhcmVmdWwgY2hvaWNlIG9mIHBoZW5vdHlwaWMgZGF0YS4gClRoaXMgZmlyc3QsIGJ1dCBvZnRlbiBvdmVybG9va2VkLCBjaG9pY2UgaXMgY3JpdGljYWwgdG8gdGhlIHJlbGlhYmlsaXR5IGFuZCBpbnRlcnByZXRhdGlvbiBvZiByZXN1bHRzLgpJZiB0aGUgZGF0YSBxdWFsaXR5IGlzIHBvb3IsIGNvbmNsdXNpb25zIG1heSBiZSB1bnJlbGlhYmxlLiAKSWYgdGhlIGRhdGEgaXMgZmFyLXJlbW92ZWQgZnJvbSB0aGUgZG9tYWluIHByb2JsZW0gb2YgaW50ZXJlc3QsIGNvbmNsdXNpb25zIG1heSBub3QgYmUgcmVsZXZhbnQuIApHaXZlbiB0aGUgaW1wb3J0YW5jZSBvZiB0aGlzIGNob2ljZSBvZiBwaGVub3R5cGljIGRhdGEsIHdlIGNvbmR1Y3RlZCBleHRlbnNpdmUgZGF0YSBleHBsb3JhdGlvbnMgZm9yIGRpZmZlcmVudCBwaGVub3R5cGVzIGluIGFkZGl0aW9uIG9idGFpbmluZyBjbGluaWNpYW4gaW5wdXQgcmVnYXJkaW5nIGl0cyBjbGluaWNhbCByZWxldmFuY2UuCgoqKkluaXRpYWwgY2hvaWNlIG9mIHBoZW5vdHlwZToqKiAKT3VyIG92ZXJhcmNoaW5nIGdvYWwgd2FzIHRvIHN0dWR5IHRoZSByb2xlIG9mIGVwaXN0YXNpcyBpbiBjYXJkaWFjIGh5cGVydHJvcGh5LiAKT25lIGltcG9ydGFudCBkaXNlYXNlIHRoYXQgaXMgY2xvc2VseSByZWxhdGVkIHRvIGNhcmRpYWMgaHlwZXJ0cm9waHkgaXMgaHlwZXJ0cm9waGljIGNhcmRpb215b3BhdGh5IChIQ00pLiAKSENNIGlzIGEgY29tbW9uIGhlYXJ0IGRpc2Vhc2UsIGltcGFjdGluZyBhcm91bmQgMSBpbiA1MDAgcGVvcGxlLCB3aGVyZSB0aGUgaGVhcnQgbXVzY2xlIGJlY29tZXMgZW5sYXJnZWQgb3IgdGhpY2tlbmVkLiAKR2l2ZW4gdGhlIGhpZ2ggcHJldmFsZW5jZSBhbmQgcG9zc2libGUgbGlmZS10aHJlYXRlbmluZyBjb25zZXF1ZW5jZXMgb2YgdGhpcyBkaXNlYXNlLCB3ZSBmaXJzdCBzZXQgb3V0IHRvIGV4cGxvcmUgdGhpcyBIQ00gcGhlbm90eXBlLCBkZWZpbmVkIGFzIGEgMC0xIGluZGljYXRvciB2YXJpYWJsZSBvZiB3aGV0aGVyIG9yIG5vdCB0aGUgaW5kaXZpZHVhbCB3YXMgZGlhZ25vc2VkIHdpdGggSENNIChpLmUuLCBhbnkgSUNEMTAgY29kZSBvZiBJNDIuMSBvciBJNDIuMiBpbiB0aGUgVUsgQmlvYmFuaykuIApIb3dldmVyLCB3aGVuIGZpdHRpbmcgdmFyaW91cyBtYWNoaW5lIGxlYXJuaW5nIHByZWRpY3Rpb24gbW9kZWxzLCBpbmNsdWRpbmcgTDEgb3IgTDItcmVndWxhcml6ZWQgbG9naXN0aWMgcmVncmVzc2lvbiwgcmFuZG9tIGZvcmVzdCAoUkYpLCBpdGVyYXRpdmUgUkYgKGlSRiksIGFuZCBzdXBwb3J0IHZlY3RvciBtYWNoaW5lcywgdXNpbmcgc2luZ2xlLW51Y2xlb3RpZGUgdmFyaWFudCAoU05WKSBkYXRhIGZyb20gdGhlIFVLIEJpb2JhbmsgKGRldGFpbHMgaW4gW0B3YW5nMjAyM2VwaXN0YXNpc10oKSkgdG8gcHJlZGljdCBIQ00gZGlhZ25vc2lzLCB0aGUgYmFsYW5jZWQgY2xhc3NpZmljYXRpb24gYWNjdXJhY3kgb24gdGhlIGhlbGQtb3V0IHZhbGlkYXRpb24gZGF0YSBkaWQgbm90IGNvbnNpc3RlbnRseSBleGNlZWQgNTBcJSB3aGVuIHRyYWluZWQgb24gZGlmZmVyZW50IGJvb3RzdHJhcHBlZCB0cmFpbmluZyBzYW1wbGVzLiAKSW4gb3RoZXIgd29yZHMsIHRoZSBmaXR0ZWQgcHJlZGljdGlvbiBtb2RlbHMgd2VyZSBubyBiZXR0ZXIgdGhhbiByYW5kb20gZ3Vlc3NpbmcuIApUaGlzIG1hZGUgdXMgd2FyeSBvZiBhbnkgaW50ZXJwcmV0YXRpb25zIGV4dHJhY3RlZCBmcm9tIHRoZXNlIHByZWRpY3Rpb24gbW9kZWxzIHNpbmNlIGl0IGlzIHVuY2xlYXIgd2hldGhlciB0aGVzZSBtb2RlbHMgYXJlIGNhcHR1cmluZyBhbnkgcmVsZXZhbnQgcGhlbm90eXBpYyBzaWduYWwgb3Igc2ltcGx5IG5vaXNlLiAKR2l2ZW4gdGhpcyBpbmNyZWRpYmx5IHdlYWsgcHJlZGljdGlvbiBzaWduYWwsIHdlIGRlZW1lZCB0aGF0IHRoZXNlIG1vZGVscyBkaWQgbm90IHBhc3MgdGhlIHByZWRpY3Rpb24gY2hlY2sgKHRoZSAiUCIgaW4gUENTKSBbQHl1MjAyMHZlcmlkaWNhbF0uIApGb3IgdGhpcyByZWFzb24sIHdlIGNob3NlIG5vdCB0byBwcm9jZWVkIGZ1cnRoZXIgd2l0aCB0aGUgSENNIHBoZW5vdHlwZSBhbmQgZGlkIG5vdCBjb25kdWN0IGFueSBhbmFseXNpcyB3aXRoIHJlc3BlY3QgdG8gaW50ZXJwcmV0aW5nIHRoZSBhZm9yZW1lbnRpb25lZCBtb2RlbHMgZm9yIEhDTS4KCioqUGl2b3RpbmcgdG8gYSBjYXJkaWFjIE1SSS1kZXJpdmVkIHBoZW5vdHlwZToqKiAKV2UgaW5zdGVhZCBwaXZvdGVkIHRvIGFuIGFsdGVybmF0aXZlIHBoZW5vdHlwZSBmb3IgY2FyZGlhYyBoeXBlcnRyb3BoeSBiYXNlZCB1cG9uIGRlZXAtbGVhcm5pbmctZW5hYmxlZCBsZWZ0IHZlbnRyaWN1bGFyIChMVikgc3RydWN0dXJhbCBhbmFseXNpcyB1c2luZyBjYXJkaWFjIE1SSXMuIApUaGlzIGNob2ljZSB3YXMgaGVhdmlseSBtb3RpdmF0ZWQgYnkgb3VyIHN0cnVnZ2xlcyB3aXRoIEhDTS4gClNwZWNpZmljYWxseSwgd2hlbiBsb29raW5nIGJhY2sgYXQgdGhlIEhDTSBkaWFnbm9zaXMgZGF0YSwgd2Ugbm90aWNlZCB0aGF0IHRoZSBudW1iZXIgb2YgSENNIGNhc2VzIGluIHRoZSBVSyBCaW9iYW5rIGRhdGEgKG9ubHkgMjM2IEhDTSBjYXNlcyBvdXQgb2YgMzM3LDUzNSB1bnJlbGF0ZWQgV2hpdGUgQnJpdGlzaCBpbmRpdmlkdWFscykgd2FzIG11Y2ggbG93ZXIgdGhhbiB0aGUgMSBpbiA1MDAgcmF0aW8gdGhhdCBpcyBleHBlY3RlZC4gCkFsdGhvdWdoIHRoZSBVSyBCaW9iYW5rIHBvcHVsYXRpb24gaXMga25vd24gdG8gYmUgaGVhbHRoaWVyIHRoYW4gdGhlIGdlbmVyYWwgcG9wdWxhdGlvbiBbQGZyeTIwMTdjb21wYXJpc29uXSwgdGhlIG9ic2VydmVkIGRpc2NyZXBhbmN5IGlzIGxhcmdlLCBsZWFkaW5nIHVzIHRvIHNwZWN1bGF0ZSBhYm91dCBwb3RlbnRpYWwgdW5kZXItZGlhZ25vc2lzIGlzc3VlcyB3aXRoIHRoZSBIQ00gcGhlbm90eXBlLiAKQ29uc2VxdWVudGx5LCByYXRoZXIgdGhhbiByZWx5aW5nIG9uIGEgY2xpbmljaWFuJ3MgZGlhZ25vc2lzIHdoaWNoIG1heSBzdWZmZXIgZnJvbSBpc3N1ZXMgc3VjaCBhcyB1bmRlci1kaWFnbm9zaXMsIHdlIGNob3NlIHRvIGJ1aWxkIHVwb24gcmVjZW50IGFkdmFuY2VzIGluIGRlZXAtbGVhcm5pbmctZW5hYmxlZCBwaGVub3R5cGluZyBbQGJhaTIwMThhdXRvbWF0ZWRdLiAKRG9pbmcgc28gZW5hYmxlcyB1cyB0byBleHRyYWN0IGEgbWVhc3VyZSBvZiBsZWZ0IHZlbnRyaWN1bGFyIGh5cGVydHJvcGh5LCBzcGVjaWZpY2FsbHksIHRoZSBsZWZ0IHZlbnRyaWN1bGFyIG1hc3MgKExWTSksIGZyb20gYW55b25lIHdpdGggYSBjYXJkaWFjIE1SSS4gCgoqKkFycml2aW5nIGF0IExWTWk6KioKSG93ZXZlciwgTFZNIGlzIGtub3duIHRvIGJlIGhlYXZpbHkgaW5mbHVlbmNlZCBieSBib2R5IHdlaWdodCwgaGVpZ2h0LCBhbmQgZ2VuZGVyIFtAZW5nZWwyMDE2YXRobGV0aWM7IEBtaXp1a29zaGkyMDE2bm9ybWFsXS4gClRodXMsIGlmIHdlIHdlcmUgdG8gcHJvY2VlZCBzb2xlbHkgd2l0aCBMVk0gaW4gb3VyIGFuYWx5c2lzLCB3ZSByaXNrIGlkZW50aWZ5aW5nIGdlbmV0aWMgbG9jaSBhbmQgaW50ZXJhY3Rpb25zIGJldHdlZW4gbG9jaSB0aGF0IGFyZSBwcmltYXJpbHkgYXNzb2NpYXRlZCB3aXRoIGJvZHkgd2VpZ2h0LCBoZWlnaHQsIGFuZCBnZW5kZXIsIHJhdGhlciB0aGFuIGxlZnQgdmVudHJpY3VsYXIgaHlwZXJ0cm9waHkuIApJbmRlZWQsIGlmIHdlIHZpc3VhbGl6ZSB0aGUgcmVsYXRpb25zaGlwIGJldHdlZW4gTFZNLCBoZWlnaHQsIGFuZCB3ZWlnaHQgd2l0aGluIGVhY2ggZ2VuZGVyIGdyb3VwIChGaWd1cmUgXEByZWYoZmlnOnN1YmNodW5rLTEpKSwgd2Ugc2VlIHN0cm9uZyBwb3NpdGl2ZSBjb3JyZWxhdGlvbnMuIAoKVGhpcyBtb3RpdmF0ZXMgdGhlIG5lZWQgdG8gYWRqdXN0IGZvciBoZWlnaHQgYW5kIHdlaWdodCBpbiBvcmRlciB0byBoZWxwIGRlY291cGxlIHRoZSBlZmZlY3RzIG9mIGhlaWdodC93ZWlnaHQgYW5kIExWTS4gCkFzIGRvbmUgaW4gQGtodXJzaGlkMjAyM2NsaW5pY2FsLCBvbmUgY29tbW9uIHdheSB0byBhZGRyZXNzIHRoaXMgaXMgYnkgYW5hbHl6aW5nIExWTSBpbmRleGVkIGJ5IGJvZHkgc3VyZmFjZSBhcmVhIChMVk1pKSwgZGVmaW5lZCBhczoKClxiZWdpbnthbGlnbip9Clx0ZXh0e0xWTWl9ID0gXHRleHR7TFZNIH0gLyBcdGV4dHsgQm9keSBzdXJmYWNlIGFyZWF9LApcZW5ke2FsaWduKn0Kd2hlcmUgYm9keSBzdXJmYWNlIGFyZWEgaXMgY2FsY3VsYXRlZCBiYXNlZCBvbiBoZWlnaHQgYW5kIGJvZHkgd2VpZ2h0IHZpYSB0aGUgRHUgQm9pcyBmb3JtdWxhIFtAZHUxOTE2Y2xpbmljYWxdLgoKQWZ0ZXIgbm9ybWFsaXppbmcgYnkgYm9keSBzdXJmYWNlIGFyZWEgKGFuZCBoZW5jZSwgaGVpZ2h0IGFuZCB3ZWlnaHQpLCB0aGUgYXNzb2NpYXRpb25zIGJldHdlZW4gTFZNaSBhbmQgaGVpZ2h0L3dlaWdodCBhcmUgbXVjaCB3ZWFrZXIgd2l0aGluIGVhY2ggZ2VuZGVyIGdyb3VwLCBleGhpYml0aW5nIGNvcnJlbGF0aW9ucyBjbG9zZXIgdG8gMCAoRmlndXJlIFxAcmVmKGZpZzpzdWJjaHVuay0xKSkuIApUaHVzLCBieSBmb2N1c2luZyBvdXIgc3RhdGlzdGljYWwgYW5hbHlzaXMgb24gTFZNaSwgd2UgbGVzc2VuIHRoZSBwb3NzaWJpbGl0eSB0aGF0IHRoZSBpZGVudGlmaWVkIGdlbmV0aWMgbG9jaSBhbmQgaW50ZXJhY3Rpb25zIGJldHdlZW4gbG9jaSBhcmUgb25seSBzZWxlY3RlZCBiZWNhdXNlIG9mIHRoZWlyIGFzc29jaWF0aW9uIHdpdGggYm9keSBoZWlnaHQgYW5kL29yIHdlaWdodC4gClN0aWxsLCB0aGVyZSBhcmUgZGlmZmVyZW5jZXMgaW4gTFZNaSBiZXR3ZWVuIG1hbGVzIGFuZCBmZW1hbGVzLCB3aXRoIG1hbGVzIHRlbmRpbmcgdG8gaGF2ZSBoaWdoZXIgTFZNaSBtZWFzdXJlbWVudHMuIApBcyBzZWVuIGxhdGVyLCB3ZSB3aWxsIGFjY291bnQgZm9yIHRoaXMgaW4gdGhlIG1vZGVsaW5nIHN0YWdlIGJ5IHVzaW5nIGdlbmRlci1zcGVjaWZpYyBiaW5hcml6YXRpb24gdGhyZXNob2xkcyB0byBiaW5hcml6ZSB0aGUgTFZNaSByZXNwb25zZXMgaW50byB0aGUgaGlnaCBhbmQgbG93IExWTWkgZ3JvdXBzLiAKCioqU3R1ZHkgQ29ob3J0OioqIApCZWZvcmUgcHJvY2VlZGluZywgd2Ugbm90ZSB0aGF0IGFub3RoZXIgaW1wb3J0YW50IGh1bWFuIGp1ZGdtZW50IGNhbGwgd2l0aGluIG91ciBwaXBlbGluZSBpcyB0aGUgY2hvaWNlIG9mIHN0dWR5IGNvaG9ydC4gClNwZWNpZmljYWxseSwgd2UgcmVzdHJpY3RlZCBvdXIgYW5hbHlzaXMgdG8gdGhlIHVucmVsYXRlZCBXaGl0ZSBCcml0aXNoIGluZGl2aWR1YWwgcG9wdWxhdGlvbiB3aXRoIGJvdGggU05WIGFuZCBjYXJkaWFjIE1SSSBkYXRhIGluIHRoZSBVSyBCaW9iYW5rLCByZXN1bHRpbmcgaW4gYSBjb2hvcnQgb2YgMjksNjYxIGluZGl2aWR1YWxzLiAKV2UgY2hvc2UgdG8gZm9jdXMgdGhpcyBhbmFseXNpcyBvbiB0aGUgdW5yZWxhdGVkIFdoaXRlIEJyaXRpc2ggcG9wdWxhdGlvbiwgYW50aWNpcGF0aW5nIHRoZSB2ZXJ5IGxvdy1zaWduYWwgcHJvYmxlbSB1bmRlciBzdHVkeSAoZS5nLiwgZHVlIHRvIHRoZSBnZW5lcmFsbHkgc21hbGwgZWZmZWN0IHNpemVzIG9mIGNvbW1vbiBnZW5ldGljIHZhcmlhbnRzIGFuZCB0aGUgaGlnaCBwaGVub3R5cGljIGRpdmVyc2l0eSBvZiBjYXJkaWFjIGh5cGVydHJvcGh5KS4gCkJ5IHN0dWR5aW5nIGEgbW9yZSBob21vZ2VuZW91cyBjb2hvcnQgc3VjaCBhcyB0aGUgdW5yZWxhdGVkIFdoaXRlIEJyaXRpc2ggcG9wdWxhdGlvbiwgd2UgaG9wZSB0byBmaXJzdCBlc3RhYmxpc2ggYSBwcm9vZi1vZi1jb25jZXB0IGZvb3Rob2xkIG9uIHRoZSByb2xlIG9mIGVwaXN0YXNpcyBpbiBjYXJkaWFjIGh5cGVydHJvcGh5LCBhbmQgd2UgdmlldyB0aGUgc3R1ZHkgYW5kIGdlbmVyYWxpemF0aW9uIHRvIHRoZSBicm9hZGVyIHBvcHVsYXRpb24gYXMgYSB2ZXJ5IGNydWNpYWwgbmV4dCBzdGVwLgo8L2Rpdj4KCmBgYHtyIGx2bS1lZGEsIHJlc3VsdHMgPSAiYXNpcyJ9CgppZiAocGFyYW1zJGV2YWwpIHsKICBwaGVub19kYXRhIDwtIGZyZWFkKCIvb2FrL3N0YW5mb3JkL3Byb2plY3RzL3VrYmIvaW1hZ2luZ19hc2hsZXkvMjAyMDkvcmVzdWx0cy90YWJsZV92ZW50cmljdWxhcl92b2x1bWVfd2l0aF9pbmRleGluZy5jc3YiKQogIG1lcmdlX2RmIDwtIGZyZWFkKCIvb2FrL3N0YW5mb3JkL3Byb2plY3RzL3VrYmIvZ2VuZXRpY19kYXRhX2FzaGxleS92Mi9icmlkZ2luZ19maWxlXzIyMjhfdG9fMTM3MjEuY3N2IikKICBwaGVub19kYXRhIDwtIGxlZnRfam9pbih4ID0gcGhlbm9fZGF0YSwgeSA9IG1lcmdlX2RmLAogICAgICAgICAgICAgICAgICAgICAgICAgIGJ5ID0gYygiVjEiID0gImFwcDIyMjgyIikpICU+JQogICAgZmlsdGVyKCFpcy5uYShhcHAxMzcyMSkpICU+JQogICAgbXV0YXRlKEdlbmRlciA9IGlmZWxzZShsb2FkRGVtb2dyYXBoaWNzKGFwcDEzNzIxKVssICJnZW5kZXIiXSA9PSAxLAogICAgICAgICAgICAgICAgICAgICAgICAgICAiTWFsZSIsICJGZW1hbGUiKSAlPiUgYXMuZmFjdG9yKCkpICU+JQogICAgYXMuZGF0YS5mcmFtZSgpICU+JQogICAgcmVuYW1lKCJMVk1pIChnL21eMikiID0gImlMVk0gKGcvbTIpIiwKICAgICAgICAgICAiV2VpZ2h0IChrZykiID0gIndlaWdodCAoa2cpIiwKICAgICAgICAgICAiSGVpZ2h0IChjbSkiID0gImhlaWdodCAoY20pIikgJT4lCiAgICBkcGx5cjo6ZmlsdGVyKCFpcy5uYShHZW5kZXIpKQoKICBrZWVwX2NvbHMgPC0gYygiTFZNIChnKSIsICJMVk1pIChnL21eMikiLCAiV2VpZ2h0IChrZykiLCAiSGVpZ2h0IChjbSkiKQogIHBsdCA8LSBwaGVub19kYXRhICU+JSAKICAgIGRwbHlyOjpzZWxlY3QodGlkeXNlbGVjdDo6YWxsX29mKGtlZXBfY29scyksIEdlbmRlcikgJT4lCiAgICB2ZG9jczo6cGxvdF9wYWlycyhjb2x1bW5zID0ga2VlcF9jb2xzLCBjb2xvciA9IC4kR2VuZGVyLCBwb2ludF9zaXplID0gMC4xKQogIHNhdmVSRFMocGx0LCBmaWxlLnBhdGgoZmlnX3Jlc19kaXIsICJwaGVub3R5cGVfY29ycmVsYXRpb25faGVhdG1hcC5yZHMiKSkKICBnZ3NhdmUocGx0LCBmaWxlbmFtZSA9IGZpbGUucGF0aChmaWdfcmVzX2RpciwgInBoZW5vdHlwZV9jb3JyZWxhdGlvbl9oZWF0bWFwLnBuZyIpLCAKICAgICAgICAgd2lkdGggPSA4LCBoZWlnaHQgPSA2KQp9IGVsc2UgewogIGRpc3BsYXlfaW1hZ2UoCiAgICBmaWxlLnBhdGgoZmlnX3Jlc19kaXIsICJwaGVub3R5cGVfY29ycmVsYXRpb25faGVhdG1hcC5wbmciKSwgCiAgICBjaHVua19pZHggPSBjaHVua19pZHgsIAogICAgY2FwdGlvbiA9ICInUGFpciBwbG90LCBpbGx1c3RyYXRpbmcgdGhlIHJlbGF0aW9uc2hpcHMgYmV0d2VlbiBMVk0sIExWTWksIGhlaWdodCwgYW5kIHdlaWdodCB3aXRoaW4gZWFjaCBnZW5kZXIgZ3JvdXAgKG1hbGVzIGluIGdyZWVuIGFuZCBmZW1hbGVzIGluIG9yYW5nZSkuIERlbnNpdHkgZGlzdHJpYnV0aW9ucyBhcmUgc2hvd24gYWxvbmcgdGhlIGRpYWdvbmFsLiciCiAgKQp9CgpgYGAKCgojIERpbWVuc2lvbiBSZWR1Y3Rpb24gU3RlcCB7LnRhYnNldCAudGFic2V0LWZhZGUgLnRhYnNldC12bW9kZXJufQoKIyMgT3ZlcnZpZXcgey51bm51bWJlcmVkIC50YWJzZXQgLnRhYnNldC1waWxscyAudGFic2V0LWZhZGUgLnRhYnNldC1zcXVhcmV9Cgo8ZGl2IGNsYXNzPSJwYW5lbCBwYW5lbC1kZWZhdWx0IHBhZGRlZC1wYW5lbCI+CkhhdmluZyBjYXJlZnVsbHkgY2hvc2VuIHRoZSBwaGVub3R5cGljIGRhdGEgKGkuZS4sIHRoZSBjYXJkaWFjIE1SSS1kZXJpdmVkIExWTWkpIHVuZGVyIHN0dWR5LCB0aGUgbmV4dCBzdGVwIGluIGxvLXNpUkYgaXMgdG8gZG8gZGltZW5zaW9uIHJlZHVjdGlvbiB0byByZWR1Y2UgdGhlIG51bWJlciBvZiBTTlZzIHVuZGVyIGNvbnNpZGVyYXRpb24gdXNpbmcgYSBnZW5vbWUtd2lkZSBhc3NvY2lhdGlvbiBzdHVkeSAoR1dBUykuIApUaGlzIGRpbWVuc2lvbiByZWR1Y3Rpb24gc3RlcCBpcyBuZWNlc3NhcnkgdG8gbWl0aWdhdGUgdGhlIGNvbXB1dGF0aW9uYWwgYW5kIHN0YXRpc3RpY2FsIGNoYWxsZW5nZXMgb2Ygc2VhcmNoaW5nIGFjcm9zcyBtaWxsaW9ucyBvZiBwb3NzaWJsZSBTTlZzICh3aGljaCBpbiB0aGUgY2FzZSBvZiBzZWFyY2hpbmcgZm9yIGVwaXN0YXNpcyByZXN1bHRzIGluIGFuIGV2ZW4gbGFyZ2VyIGNvbWJpbmF0b3JpYWwgZXhwbG9zaW9uIG9mIHBvc3NpYmlsaXRpZXMpLgoKKipXaHkgR1dBUz8qKiAKV2UgY2hvc2UgdG8gZG8gZGltZW5zaW9uIHJlZHVjdGlvbiBieSBydW5uaW5nIGEgR1dBUyBhcyBpdCAKKDEpIGhhcyBiZWVuIHNob3duIHRvIGJlIGFuIGluY3JlZGlibHkgdXNlZnVsIHRvb2wgZm9yIGJldHRlciB1bmRlcnN0YW5kaW5nIHRoZSBnZW5ldGljIGJhc2lzIG9mIG51bWVyb3VzIGRpc2Vhc2VzIGluIHRoaXMgZmllbGQgW0B2aXNzY2hlcjIwMTcxMDsgQHBpcnJ1Y2NlbGxvMjAyMGFuYWx5c2lzOyBAbWV5ZXIyMDIwZ2VuZXRpYzsgQGhhcnBlcjIwMjFjb21tb247IEBraHVyc2hpZDIwMjNjbGluaWNhbF0sIAooMikgaXMgb25lIG9mIHRoZSBmZXcgbWV0aG9kcyB0aGF0IGNhbiBoYW5kbGUgYW4gaW5wdXQgb2YgbWlsbGlvbnMgb2YgU05WcyBpbiBhIGNvbXB1dGF0aW9uYWxseS10cmFjdGFibGUgbWFubmVyLCBhbmQgCigzKSBpcyBhIGNvbW1vbiwgd2lkZWx5LWFjY2VwdGVkIHByZXByb2Nlc3Npbmcgc3RlcCBpbiBvdGhlciByZWxhdGVkIHN0YXRpc3RpY2FsIGdlbm9taWNzIHRhc2tzIHN1Y2ggYXMgZmluZS1tYXBwaW5nIFtAc2NoYWlkMjAxOGdlbm9tZV0uCgoqKkxpbWl0YXRpb25zOioqIApXZSBhY2tub3dsZWRnZSwgaG93ZXZlciwgdGhhdCB1c2luZyBhIEdXQVMgdG8gcmVkdWNlIHRoZSBudW1iZXIgb2YgU05WcyB1bmRlciBjb25zaWRlcmF0aW9uIGhhcyBsaW1pdGF0aW9ucy4gCkJlY2F1c2UgYSBHV0FTIHByaW9yaXRpemVzIFNOVnMgdGhhdCBoYXZlIHN0cm9uZyBtYXJnaW5hbCBhc3NvY2lhdGlvbnMgd2l0aCB0aGUgcGhlbm90eXBlIHVuZGVyIHN0dWR5LCB3ZSBtYXkgYmUgcmVtb3ZpbmcgU05WcyB0aGF0IGFyZSBhc3NvY2lhdGVkIHdpdGggTFZNaSB0aHJvdWdoIGFuIGVwaXN0YXRpYyBpbnRlcmFjdGlvbiBidXQgbm90IHRocm91Z2ggYSBtYXJnaW5hbCBhc3NvY2lhdGlvbi4gCkFsbGV2aWF0aW5nIHRoaXMgbGltaXRhdGlvbiBpcyBjZXJ0YWlubHkgaW50ZXJlc3RpbmcgYW5kIGFuIGltcG9ydGFudCBkaXJlY3Rpb24gdG8gcHVyc3VlIGluIGZ1dHVyZSB3b3JrLiAKUmVnYXJkbGVzcywgaW4gdGhpcyBjdXJyZW50IHdvcmssIHdlIHVzZSBsby1zaVJGIHByaW1hcmlseSBhcyBhIHdheSB0byBnZW5lcmF0ZSByZWNvbW1lbmRhdGlvbnMgZm9yIGV4cGVyaW1lbnRhbCB2YWxpZGF0aW9uIG9mIGVwaXN0YXNpcy4gCldlIHRodXMgYXJlIG1vc3QgaW50ZXJlc3RlZCBpbiBnZW5lcmF0aW5nICpyZWxpYWJsZSogcmVjb21tZW5kYXRpb25zIGZvciBhIGxpbWl0ZWQgbnVtYmVyIG9mIGV4cGVyaW1lbnRzLCByYXRoZXIgdGhhbiBhdHRlbXB0aW5nIHRvIGZpbmQgYWxsIHBvc3NpYmxlIGludGVyYWN0aW9ucyB0aGF0IGRyaXZlIHRoZSBkaXNlYXNlLiAKR2l2ZW4gb3VyIHBhcnRpY3VsYXIgdXNlLWNhc2UgZm9yIGxvLXNpUkYsIHdlIGFjY2VwdCB0aGUgbGltaXRhdGlvbnMgb2YgdXNpbmcgYSBHV0FTIGZvciBkaW1lbnNpb24gcmVkdWN0aW9uIGFuZCBhZ2FpbiB2aWV3IHRoaXMgd29yayBhcyBhIHJlbGlhYmxlICpmaXJzdCogc3RlcCAoYW5kIGNlcnRhaW5seSBub3QgdGhlIGxhc3QpIGZvciBiZXR0ZXIgdW5kZXJzdGFuZGluZyB0aGUgcm9sZSBvZiBlcGlzdGFzaXMgaW4gY2FyZGlhYyBoeXBlcnRyb3BoeS4KCioqSG93IHdhcyB0aGUgZGltZW5zaW9uIHJlZHVjdGlvbiBwZXJmb3JtZWQ/KiogCldlIHBlcmZvcm1lZCBhIEdXQVMgb24gdGhlIHRyYWluaW5nIGRhdGEgZm9yIHRoZSByYW5rLWJhc2VkIGludmVyc2Ugbm9ybWFsLXRyYW5zZm9ybWVkIExWTWkgdXNpbmcgdHdvIGFsZ29yaXRobXMsIFBMSU5LIFtAcHVyY2VsbDIwMDdwbGlua10gYW5kIEJPTFQtTE1NIFtAbG9oMjAxNWVmZmljaWVudF0uIApGb3IgZWFjaCBvZiB0aGUgdHdvIEdXQVMgcnVucywgd2UgcmFua2VkIHRoZSBTTlZzIGJ5IHNpZ25pZmljYW5jZSAoaS5lLiwgdGhlIEdXQVMgcC12YWx1ZSkuIApXZSB0aGVuIHRvb2sgdGhlIHVuaW9uIG9mIHRoZSB0b3AgMTAwMCBTTlZzICh3aXRob3V0IGNsdW1waW5nKSBmcm9tIGVhY2ggb2YgdGhlIHR3byBHV0FTIHJ1bnMgYW5kIHByb2NlZWRlZCB3aXRoIHRoaXMgcmVzdWx0aW5nIHNldCBvZiAxNDA1IFNOVnMgZm9yIHRoZSByZW1haW5kZXIgb2YgdGhlIGxvLXNpUkYgcGlwZWxpbmUuIApXZSByZWZlciB0byBbQHdhbmcyMDIzZXBpc3Rhc2lzXSgpIGZvciB0aGUgZGV0YWlscyBvbiB0aGUgUExJTksgYW5kIEJPTFQtTE1NIGltcGxlbWVudGF0aW9ucyBhbmQgdXNlIHRoaXMgZG9jdW1lbnQgaW5zdGVhZCB0byBqdXN0aWZ5IHNldmVyYWwgb2Ygb3VyIGh1bWFuIGp1ZGdtZW50IGNhbGxzIGluIHRoaXMgZGltZW5zaW9uIHJlZHVjdGlvbiBzdGVwLgoKLSAqKldoeSBQTElOSyBhbmQgQk9MVC1MTU0/KiogU2luY2UgQk9MVC1MTU0gYW5kIFBMSU5LIHJlbHkgb24gZGlmZmVyZW50IHN0YXRpc3RpY2FsIG1vZGVscyBhbmQgaXQgaXMgdW5jbGVhciBhIHByaW9yaSB3aGljaCBtb2RlbCBpcyBiZXR0ZXIgc3VpdGVkIGZvciBvdXIgcHJvYmxlbSwgd2UgZW1wbG95ZWQgYm90aCBzb2Z0d2FyZSBwYWNrYWdlcyB0byBtaXRpZ2F0ZSB0aGUgZGVwZW5kZW5jZSBvZiBkb3duc3RyZWFtIGNvbmNsdXNpb25zIG9uIHRoaXMgYXJiaXRyYXJ5IGNob2ljZSBvZiBtb2RlbC4KLSAqKldoeSB0aGUgcmFuay1iYXNlZCBpbnZlcnNlIG5vcm1hbC10cmFuc2Zvcm1lZCBMVk1pPyoqIEJlY2F1c2UgdGhlIGRpc3RyaWJ1dGlvbiBvZiBMVk1pIG1lYXN1cmVtZW50cyBpcyByaWdodCBza2V3ZWQgKHNlZSBGaWd1cmUgXEByZWYoZmlnOnN1YmNodW5rLTEpKSwgYW5kIHRoZSBwLXZhbHVlIGNvbXB1dGF0aW9uIGluIFBMSU5LIGFuZCBCT0xULUxNTSByZWx5IG9uIG5vcm1hbGl0eSBhc3N1bXB0aW9ucywgdGhlIHJhbmstYmFzZWQgaW52ZXJzZSBub3JtYWwtdHJhbnNmb3JtIHdhcyB0YWtlbiBhcyBpbiBAa2h1cnNoaWQyMDIzY2xpbmljYWwuCi0gKipXaHkgd2FzIHRoZSB1bmlvbiB0YWtlbj8qKiBBcyBtZW50aW9uZWQgcHJldmlvdXNseSwgcmVseWluZyBvbiBhIEdXQVMgdG8gZG8gZGltZW5zaW9uIHJlZHVjdGlvbiBjYW4gYmUgbGltaXRpbmcgc2luY2UgaXQgaXMgcHJpbWFyaWx5IGFzc2Vzc2luZyBtYXJnaW5hbCBhc3NvY2lhdGlvbnMgYmV0d2VlbiB0aGUgU05WcyBhbmQgdGhlIHBoZW5vdHlwZS4gVGhlcmUgYXJlIGFsc28gb3RoZXIgcmVzdHJpY3RpdmUgbW9kZWxpbmcgYXNzdW1wdGlvbnMgKGUuZy4sIGxpbmVhcml0eSkgdGhhdCBtYXkgYWRkIHRvIHRoZXNlIGxpbWl0YXRpb25zLiBEdWUgdG8gdGhpcyBjb25jZXJuIHRoYXQgd2UgbWF5IGJlIGltcG9zaW5nIHRvbyBtYW55IHVubmVjZXNzYXJ5IHJlc3RyaWN0aW9ucyBpbiBvcmRlciBmb3IgU05WcyB0byBwYXNzIHRoZSBHV0FTIGZpbHRlciwgd2UgY2hvc2UgdG8gdGFrZSB0aGUgdW5pb24gb2YgdGhlIHRvcCBTTlZzIGZyb20gQk9MVC1MTU0gYW5kIGZyb20gUExJTkssIHJhdGhlciB0aGFuIHRha2luZyB0aGUgaW50ZXJzZWN0aW9uIHdoaWNoIHdvdWxkIGhhdmUgbWFkZSBpdCBtb3JlIGRpZmZpY3VsdCBvciByZXN0cmljdGl2ZSBmb3IgU05WcyB0byBwYXNzIHRoZSBHV0FTIGZpbHRlci4KLSAqKkhvdyB3YXMgdGhlIHRocmVzaG9sZCBjaG9zZW4/KiogV2UgY2hvc2UgdGhlIHRocmVzaG9sZCBvZiAxMDAwIFNOVnMgcGVyIEdXQVMgbWV0aG9kICh3aXRob3V0IGNsdW1waW5nKSBhcyBpdCAoMSkgc3RydWNrIGEgYmFsYW5jZSBiZXR3ZWVuIHRoZSBhbW91bnQgb2YgaW5mb3JtYXRpb24gbG9zcyBhbmQgdGhlIGNvbXB1dGF0aW9uYWwgY29zdCBvZiBvdXIgZG93bnN0cmVhbSBtb2RlbGluZyBhbmQgKDIpIHlpZWxkZWQgdGhlIGhpZ2hlc3QgdmFsaWRhdGlvbiBwcmVkaWN0aW9uIGFjY3VyYWN5IGNvbXBhcmVkIHRvIGNob29zaW5nIG90aGVyIHBvc3NpYmxlIHRocmVzaG9sZHMgKDUwMCBhbmQgMjAwMCkgd2l0aCBhbmQgd2l0aG91dCBjbHVtcGluZyBpbiB0aGUgcHJlZGljdGlvbiBtb2RlbGluZyBzdGFnZS4gV2Ugbm90ZSB0aGF0IHRoaXMgY2hvaWNlIG9mIHRoZSB0b3AgMTAwMCBTTlZzIGluY2x1ZGVzIGFsbCBTTlZzIHRoYXQgcGFzc2VkIHRoZSBnZW5vbWUtd2lkZSBzaWduaWZpY2FuY2UgbGV2ZWwgKHAtdmFsdWUgPSA1RS04KSBhcyB3ZWxsIGFzIGFkZGl0aW9uYWwgU05WcyB0aGF0IGRpZCBub3QgcGFzcyB0aGUgZ2Vub21lLXdpZGUgc2lnbmlmaWNhbmNlIGxldmVsLiBJbiBwYXJ0aWN1bGFyLCB0YWtpbmcgdGhlIHRvcCAxMDAwIFNOVnMgY29ycmVzcG9uZHMgdG8gdXNpbmcgdGhlIHAtdmFsdWUgdGhyZXNob2xkIG9mIDEuN0UtNSBhbmQgNi43RS02IGZvciBQTElOSyBhbmQgQk9MVC1MTU0sIHJlc3BlY3RpdmVseS4KCioqT3JnYW5pemF0aW9uOioqIFVuZGVyIHRoZSBgR1dBUyBSZXN1bHRzIFN1bW1hcnlgIHRhYiwgd2UgcHJvdmlkZSBhbiBpbnZlc3RpZ2F0aW9uIGludG8gdGhlIEJPTFQtTE1NIGFuZCBQTElOSyBHV0FTIHJlc3VsdHMgZm9yIExWTSBhbmQgTFZNaS4gVW5kZXIgdGhlIGBHV0FTLWZpbHRlcmVkIFNOVnNgLCB3ZSBleHBsb3JlIHRoZSBzZWxlY3RlZCAxNDA1IFNOVnMgdGhhdCBwYXNzZWQgdGhlIEdXQVMgZmlsdGVyIGZvciB0aGUgTFZNaSBwaGVub3R5cGUuCjwvZGl2PgoKIyMgR1dBUyBSZXN1bHRzIFN1bW1hcnkgey51bm51bWJlcmVkIC50YWJzZXR9Cgo8ZGl2IGNsYXNzPSJwYW5lbCBwYW5lbC1kZWZhdWx0IHBhZGRlZC1wYW5lbCI+CkJlbG93LCB3ZSBwcm92aWRlIGFuIG92ZXJ2aWV3IG9mIHRoZSBnZW5vbWUtd2lkZSBhc3NvY2lhdGlvbiBzdHVkeSAoR1dBUykgcmVzdWx0cyBmb3IgYm90aCB0aGUgTFZNIGFuZCBMVk1pIHBoZW5vdHlwZXMuIFdoaWxlIExWTWkgaXMgdGhlIHByaW1hcnkgcGhlbm90eXBlIG9mIGludGVyZXN0LCB3ZSBwcm92aWRlIHRoZSBMVk0gR1dBUyByZXN1bHRzIGZvciBjb21wbGV0ZW5lc3MuIFdlIGZ1cnRoZXIgaW52ZXN0aWdhdGUgdGhlIHNpbWlsYXJpdGllcyBpbiBmaW5kaW5ncyBiZXR3ZWVuIHRoZSBMVk0gYW5kIExWTWkgR1dBUyBhbmFseXNlcyB2aWEgYSBzdGFiaWxpdHkgYW5hbHlzaXMuIAoKLSBVbmRlciB0aGUgYEJPTFQtTE1NYCBhbmQgYFBMSU5LYCB0YWJzOgogIC0gV2UgcHJvdmlkZSBhIGJyaWVmIGxvb2sgaW50byB0aGUgR1dBUyByZXN1bHRzLCBpbmNsdWRpbmcgdGhlIE1hbmhhdHRhbiBwbG90cyBmb3IgZWFjaCBwaGVub3R5cGUgKExWTWkgYW5kIExWTSkuIAogIC0gV2UgYWxzbyBwcm92aWRlIGEgdGFibGUgb2YgdGhlIGdlbm9taWMgcmlzayBsb2NpLCBsZWFkIFNOVnMsIGFuZCBpbmRlcGVuZGVudCBzaWduaWZpY2FudCBTTlZzIGZyb20gZWFjaCBHV0FTLCBkZXRlcm1pbmVkIHVzaW5nIEZVTUEgW0B3YXRhbmFiZTIwMTdmdW5jdGlvbmFsXSB3aXRoIHRoZSBkZWZhdWx0IHNldHRpbmdzIChpLmUuLCBtYXhpbXVtIHAtdmFsdWUgb2YgbGVhZCBTTlZzID0gNUUtOCwgbWF4aW11bSBwLXZhbHVlIGN1dG9mZiA9IDAuMDUsICRyXjIkIHRocmVzaG9sZCB0byBkZWZpbmUgaW5kZXBlbmRlbnQgc2lnbmlmaWNhbnQgU05WcyA9IDAuNiwgMm5kICRyXjIkIHRocmVzaG9sZCB0byBkZWZpbmUgbGVhZCBTTlZzID0gMC4xLCBtaW5pbXVtIG1pbm9yIGFsbGVsZSBmcmVxdWVuY3kgPSAwLCBtYXhpbXVtIGRpc3RhbmNlIGJldHdlZW4gTEQgYmxvY2tzIHRvIG1lcmdlIGludG8gYSBsb2N1cyA9IDI1MGtiLCB1c2luZyB0aGUgVUtCIHJlbGVhc2UyYiAxMGsgV2hpdGUgQnJpdGlzaCByZWZlcmVuY2UgcGFuZWwgcG9wdWxhdGlvbikuCiAgLSBGdXJ0aGVybW9yZSwgd2UgdXNlZCBGVU1BIHRvIG1hcCBTTlZzIHRvIGdlbmVzIGJhc2VkIG9uIHBvc2l0aW9uLCBhZ2FpbiB3aXRoIHRoZSBkZWZhdWx0IHNldHRpbmdzIChtYXhpbXVtIGRpc3RhbmNlID0gMTBrYiksIGFuZCBwcm92aWRlIHRoaXMgdGFibGUgb2YgbWFwcGVkIGdlbmVzIGJlbG93LiAKLSBMYXN0bHksIHVuZGVyIHRoZSBgU3RhYmlsaXR5IEFuYWx5c2lzYCB0YWIsIHdlIGludmVzdGlnYXRlZCB0aGUgc2ltaWxhcml0aWVzIGFuZCBkaWZmZXJlbmNlcyBiZXR3ZWVuIHRoZSBCT0xULUxNTSBhbmQgUExJTksgcmVzdWx0cyBhcyB3ZWxsIGFzIGJldHdlZW4gdGhlIExWTSBhbmQgTFZNaSByZXN1bHRzLiAKPC9kaXY+CgpgYGB7ciBnd2FzLW1hbmhhdHRhbiwgcmVzdWx0cyA9ICJhc2lzIn0KCmd3YXNfbWV0aG9kcyA8LSBjKCJCT0xULUxNTSIsICJQbGluayIpCgpnd2FzX2hlYWRlciA8LSAiXG5cbiMjIyAlcyB7LnVubnVtYmVyZWQgLnRhYnNldCAudGFic2V0LXBpbGxzIC50YWJzZXQtZmFkZSAudGFic2V0LXNxdWFyZX0gXG5cbiIKcGhlbm90eXBlX2hlYWRlciA8LSAiXG5cbiMjIyMgJXMgey51bm51bWJlcmVkIC50YWJzZXQgLnRhYnNldC1waWxscyAudGFic2V0LWZhZGUgLnRhYnNldC1jaXJjbGV9XG5cbiIKZnVtYV9oZWFkZXIgPC0gIlxuXG4jIyMjIyAlcyB7LnVubnVtYmVyZWR9XG5cbiIKClBWQUxfVEhSIDwtIDQKCiMgcGxvdCBnd2FzIHN1bW1hcnkgcmVzdWx0cwppZiAocGFyYW1zJGV2YWwpIHsKICBnd2FzX2xzIDwtIGxpc3QoKQogIHNucHNfdGFiX2xzIDwtIGxpc3QoKQogIGdlbmVzX3RhYl9scyA8LSBsaXN0KCkKICBmb3IgKGd3YXNfbWV0aG9kIGluIGd3YXNfbWV0aG9kcykgewogICAgZ3dhc19sc1tbZ3dhc19tZXRob2RdXSA8LSBsaXN0KCkKICAgIGZvciAocGhlbm90eXBlIGluIHBoZW5vdHlwZXNfYWxsKSB7CiAgICAgICMgcmV0cmlldmUgZ3dhcyByZXN1bHRzCiAgICAgIGd3YXNfZGlyIDwtIHBhc3RlMCgiZ3dhc18iLCBzdHJfcmVwbGFjZSh0b2xvd2VyKGd3YXNfbWV0aG9kKSwgIi0iLCAiXyIpKQogICAgICBmbmFtZSA8LSBwYXN0ZTAocGhlbm90eXBlLCAiX25vcm1fYXBwMTM3MjEuc3RhdHNfYW5ub3QiKQogICAgICAjIGd3YXNfbHNbW2d3YXNfbWV0aG9kXV1bW3BoZW5vdHlwZV1dIDwtIGZyZWFkKGZpbGUucGF0aChyZXNfZGlyLCBnd2FzX2RpciwgZm5hbWUpKQogICAgICAKICAgICAgIyByZXRyaWV2ZSBhbm5vdGF0ZWQgZnVtYSBnd2FzIHJlc3VsdHMKICAgICAgcGhlbm90eXBlX25hbWUgPC0gbmFtZXMocGhlbm90eXBlc19hbGwpW3BoZW5vdHlwZXNfYWxsID09IHBoZW5vdHlwZV0KICAgICAgZ3dhc19tZXRob2RfZnN0ciA8LSBzdHJpbmdyOjpzdHJfcmVwbGFjZSh0b2xvd2VyKGd3YXNfbWV0aG9kKSwgIi0iLCAiXyIpCiAgICAgIHBoZW5vdHlwZV9mc3RyIDwtIHN0cmluZ3I6OnN0cl9yZXBsYWNlKHRvbG93ZXIocGhlbm90eXBlKSwgImlsdm0iLCAibHZtaSIpCiAgICAgIGZ1bWFfZnBhdGggPC0gZmlsZS5wYXRoKAogICAgICAgIHJlc19kaXIsICJnd2FzX2Z1bWEiLCBzcHJpbnRmKCIlc18lc19nd2FzIiwgZ3dhc19tZXRob2RfZnN0ciwgcGhlbm90eXBlX2ZzdHIpCiAgICAgICkKICAgICAgbG9jaV90YWIgPC0gZnJlYWQoZmlsZS5wYXRoKGZ1bWFfZnBhdGgsICJHZW5vbWljUmlza0xvY2kudHh0IikpICU+JQogICAgICAgIHRpYmJsZTo6YXNfdGliYmxlKCkKICAgICAgbGVhZHNucHNfdGFiIDwtIGZyZWFkKGZpbGUucGF0aChmdW1hX2ZwYXRoLCAibGVhZFNOUHMudHh0IikpICU+JQogICAgICAgIGRwbHlyOjpzZWxlY3QoLU5vKSAlPiUKICAgICAgICB0aWJibGU6OmFzX3RpYmJsZSgpCiAgICAgIGluZHNpZ3NucHNfdGFiIDwtIGZyZWFkKGZpbGUucGF0aChmdW1hX2ZwYXRoLCAiSW5kU2lnU05Qcy50eHQiKSkgJT4lCiAgICAgICAgZHBseXI6OnNlbGVjdCgtTm8pICU+JQogICAgICAgIHRpYmJsZTo6YXNfdGliYmxlKCkKICAgICAgZ2VuZXNfdGFiIDwtIGZyZWFkKGZpbGUucGF0aChmdW1hX2ZwYXRoLCAiZ2VuZXMudHh0IikpICU+JQogICAgICAgIHRpYmJsZTo6YXNfdGliYmxlKCkgJT4lCiAgICAgICAgZHBseXI6Om11dGF0ZSgKICAgICAgICAgIGBHV0FTIE1ldGhvZGAgPSAhIWd3YXNfbWV0aG9kLAogICAgICAgICAgYFBoZW5vdHlwZWAgPSAhIXBoZW5vdHlwZV9uYW1lCiAgICAgICAgKQogICAgICBzbnBzX3RhYiA8LSBpbmRzaWdzbnBzX3RhYiAlPiUKICAgICAgICBkcGx5cjo6c2VsZWN0KEdlbm9taWNMb2N1czpwb3MpICU+JQogICAgICAgIGRwbHlyOjptdXRhdGUoCiAgICAgICAgICBgVG9wIExlYWQgU05QYCA9IHB1cnJyOjptYXBfbGdsKHVuaXFJRCwgfiAueCAlaW4lIGxvY2lfdGFiJHVuaXFJRCksCiAgICAgICAgICBgTGVhZCBTTlBgID0gcHVycnI6Om1hcF9sZ2wodW5pcUlELCB+IC54ICVpbiUgbGVhZHNucHNfdGFiJHVuaXFJRCksCiAgICAgICAgICBgSW5kLiBTaWcuIFNOUGAgPSBwdXJycjo6bWFwX2xnbCh1bmlxSUQsIH4gLnggJWluJSBpbmRzaWdzbnBzX3RhYiR1bmlxSUQpLAogICAgICAgICAgYEdXQVMgTWV0aG9kYCA9ICEhZ3dhc19tZXRob2QsCiAgICAgICAgICBgUGhlbm90eXBlYCA9ICEhcGhlbm90eXBlX25hbWUKICAgICAgICApCiAgICAgIHNucHNfdGFiX2xzIDwtIGMoc25wc190YWJfbHMsIGxpc3Qoc25wc190YWIpKQogICAgICBnZW5lc190YWJfbHMgPC0gYyhnZW5lc190YWJfbHMsIGxpc3QoZ2VuZXNfdGFiKSkKICAgIH0KICB9CiAgCiAgIyBjb21wYXJlIGJvbHQtbG1tIHZzIHBsaW5rIHJlc3VsdHMKICBwbHRfZGYgPC0gbWFwMl9kZnIoZ3dhc19sc1tbIkJPTFQtTE1NIl1dLCBnd2FzX2xzW1siUGxpbmsiXV0sCiAgICAgICAgICAgICAgICAgICAgIGZ1bmN0aW9uKGJvbHQsIHBsaW5rKSB7CiAgICAgICAgICAgICAgICAgICAgICAgaW5uZXJfam9pbih4ID0gYm9sdCAlPiUKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2VsZWN0KFNOUCwgYEJPTFQtTE1NYCA9IFBfQk9MVF9MTU1fSU5GKSAlPiUKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIyBmaWx0ZXIoLWxvZzEwKGBCT0xULUxNTWApID4gUFZBTF9USFIpICU+JQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtdXRhdGUoYEJPTFQtTE1NYCA9IC1sb2cxMChgQk9MVC1MTU1gKSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB5ID0gcGxpbmsgJT4lCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNlbGVjdChTTlAsIFBsaW5rID0gUF9HTE0pICU+JQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjIGZpbHRlcigtbG9nMTAoUGxpbmspID4gUFZBTF9USFIpICU+JQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtdXRhdGUoUGxpbmsgPSAtbG9nMTAoUGxpbmspKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJ5ID0gIlNOUCIpCiAgICAgICAgICAgICAgICAgICAgIH0sIC5pZCA9ICJQaGVub3R5cGUiKSAlPiUKICAgIGRwbHlyOjptdXRhdGUoI2tlZXAgPSAoYEJPTFQtTE1NYCA+IFBWQUxfVEhSKSB8IChQbGluayA+IFBWQUxfVEhSKSwKICAgICAgICAgICAgICAgICAgUGhlbm90eXBlID0gaWZlbHNlKFBoZW5vdHlwZSA9PSAiaUxWTSIsICJMVk1pIiwgUGhlbm90eXBlKSkKICBwbHQgPC0gdmRvY3M6OnBsb3RfcG9pbnQoCiAgICBwbHRfZGYsIyAlPiUgZHBseXI6OmZpbHRlcihrZWVwKSwgCiAgICB4X3N0ciA9ICJCT0xULUxNTSIsIHlfc3RyID0gIlBsaW5rIiwgc2l6ZSA9IC4xCiAgKSArCiAgICBmYWNldF9ncmlkKH4gUGhlbm90eXBlKSArCiAgICBsYWJzKHggPSAiLWxvZzEwKEJPTFQtTE1NIFAtdmFsdWUpIiwgeSA9ICItbG9nMTAoUExJTksgUC12YWx1ZSkiKQogIHNhdmVSRFMocGx0LCBmaWxlLnBhdGgoZmlnX3Jlc19kaXIsICJnd2FzX3B2YWx1ZXNfY29tcGFyZS5yZHMiKSkKICBnZ3NhdmUocGx0LCBmaWxlbmFtZSA9IGZpbGUucGF0aChmaWdfcmVzX2RpciwgImd3YXNfcHZhbHVlc19jb21wYXJlLnBuZyIpLCAKICAgICAgICAgd2lkdGggPSA2LCBoZWlnaHQgPSAzLjUpCgogICMgc3VtbWFyaXplIGZ1bWEgZ3dhcyBTTlAgcmVzdWx0cyB1c2luZyBzdGFiaWxpdHkgYWNyb3NzIGd3YXMgcnVucwogIHNucHNfdGFiIDwtIGRwbHlyOjpiaW5kX3Jvd3Moc25wc190YWJfbHMpICU+JQogICAgdGlkeXI6OnBpdm90X3dpZGVyKAogICAgICBpZF9jb2xzID0gYyh1bmlxSUQ6cG9zKSwgCiAgICAgIG5hbWVzX2Zyb20gPSBjKGBHV0FTIE1ldGhvZGAsIGBQaGVub3R5cGVgKSwKICAgICAgdmFsdWVzX2Zyb20gPSBjKGBUb3AgTGVhZCBTTlBgLCBgTGVhZCBTTlBgLCBgSW5kLiBTaWcuIFNOUGApLCAKICAgICAgbmFtZXNfc2VwID0gIiAiLAogICAgICBuYW1lc19wcmVmaXggPSAiLSAiLAogICAgICB2YWx1ZXNfZmlsbCA9IEZBTFNFCiAgICApICU+JQogICAgZHBseXI6OnJvd3dpc2UoKSAlPiUKICAgIGRwbHlyOjptdXRhdGUoCiAgICAgIG5fY291bnRzID0gc3VtKGRwbHlyOjpjX2Fjcm9zcyh3aGVyZShpcy5sb2dpY2FsKSkpCiAgICApICU+JQogICAgZHBseXI6OmxlZnRfam9pbigKICAgICAgZ3dhc19sc1tbIkJPTFQtTE1NIl1dW1siaUxWTSJdXSAlPiUKICAgICAgICBkcGx5cjo6c2VsZWN0KHJzSUQgPSBTTlAsIGBCT0xULUxNTSBMVk1pIHAtdmFsdWVgID0gUF9CT0xUX0xNTV9JTkYpLCAKICAgICAgYnkgPSAicnNJRCIKICAgICkgJT4lCiAgICBkcGx5cjo6bGVmdF9qb2luKAogICAgICBnd2FzX2xzW1siQk9MVC1MTU0iXV1bWyJMVk0iXV0gJT4lCiAgICAgICAgZHBseXI6OnNlbGVjdChyc0lEID0gU05QLCBgQk9MVC1MTU0gTFZNIHAtdmFsdWVgID0gUF9CT0xUX0xNTV9JTkYpLCAKICAgICAgYnkgPSAicnNJRCIKICAgICkgJT4lCiAgICBkcGx5cjo6bGVmdF9qb2luKAogICAgICBnd2FzX2xzW1siUGxpbmsiXV1bWyJpTFZNIl1dICU+JQogICAgICAgIGRwbHlyOjpzZWxlY3QocnNJRCA9IFNOUCwgYFBsaW5rIExWTWkgcC12YWx1ZWAgPSBQX0dMTSksIAogICAgICBieSA9ICJyc0lEIgogICAgKSAlPiUKICAgIGRwbHlyOjpsZWZ0X2pvaW4oCiAgICAgIGd3YXNfbHNbWyJQbGluayJdXVtbIkxWTSJdXSAlPiUKICAgICAgICBkcGx5cjo6c2VsZWN0KHJzSUQgPSBTTlAsIGBQbGluayBMVk0gcC12YWx1ZWAgPSBQX0dMTSksIAogICAgICBieSA9ICJyc0lEIgogICAgKSAlPiUKICAgIGRwbHlyOjpyb3d3aXNlKCkgJT4lCiAgICBkcGx5cjo6bXV0YXRlKAogICAgICBuX3AgPSBzdW0oIWlzLm5hKGRwbHlyOjpjX2Fjcm9zcyh0aWR5c2VsZWN0Ojpjb250YWlucygicC12YWx1ZSIpKSkpLAogICAgICBhdmdfcCA9IG1lYW4oZHBseXI6OmNfYWNyb3NzKHRpZHlzZWxlY3Q6OmNvbnRhaW5zKCJwLXZhbHVlIikpLCBuYS5ybSA9IFRSVUUpCiAgICApICU+JQogICAgZHBseXI6OmFycmFuZ2UoLW5fY291bnRzLCAtbl9wLCBhdmdfcCkKICAKICBzbnBzX3RhYl9sb25nIDwtIHNucHNfdGFiICU+JQogICAgZHBseXI6OnNlbGVjdCgtdW5pcUlELCAtY2hyLCAtcG9zLCAtbl9jb3VudHMsIC1uX3AsIC1hdmdfcCwKICAgICAgICAgICAgICAgICAgLXRpZHlzZWxlY3Q6OmNvbnRhaW5zKCJwLXZhbHVlIikpICU+JQogICAgdGlkeXI6OnBpdm90X2xvbmdlcigKICAgICAgY29scyA9IGModGlkeXNlbGVjdDo6c3RhcnRzX3dpdGgoIlRvcCIpLCAKICAgICAgICAgICAgICAgdGlkeXNlbGVjdDo6c3RhcnRzX3dpdGgoIkxlYWQiKSwgCiAgICAgICAgICAgICAgIHRpZHlzZWxlY3Q6OnN0YXJ0c193aXRoKCJJbmQiKSkKICAgICkgJT4lCiAgICBkcGx5cjo6bXV0YXRlKAogICAgICBNZXRob2QgPSBzdHJpbmdyOjpzdHJfdHJpbShzdHJpbmdyOjpzdHJfZXh0cmFjdChuYW1lLCAiKD88PS0pXFxzKi4qIikpLAogICAgICBHcm91cCA9IGZhY3RvcigKICAgICAgICBzdHJpbmdyOjpzdHJfdHJpbShzdHJpbmdyOjpzdHJfZXh0cmFjdChuYW1lLCAiXlteLV0rIikpICU+JQogICAgICAgICAgc3RyaW5ncjo6c3RyX3JlcGxhY2UoIlNOUCIsICJTTlYiKSwKICAgICAgICBsZXZlbHMgPSBjKCJUb3AgTGVhZCBTTlYiLCAiTGVhZCBTTlYiLCAiSW5kLiBTaWcuIFNOViIpCiAgICAgICksCiAgICAgIHJzSUQgPSBmYWN0b3IocnNJRCwgbGV2ZWxzID0gcmV2KHNucHNfdGFiJHJzSUQpKSwKICAgICAgdmFsdWUgPSBmYWN0b3IoCiAgICAgICAgaWZlbHNlKHZhbHVlLCAiVHJ1ZSIsICJGYWxzZSIpLAogICAgICAgIGxldmVscyA9IGMoIlRydWUiLCAiRmFsc2UiKQogICAgICApCiAgICApCiAgCiAgcGx0IDwtIGdncGxvdDI6OmdncGxvdChzbnBzX3RhYl9sb25nKSArCiAgICBnZ3Bsb3QyOjphZXMoeCA9IE1ldGhvZCwgeSA9IHJzSUQsIGZpbGwgPSB2YWx1ZSkgKwogICAgZ2dwbG90Mjo6ZmFjZXRfZ3JpZCh+IEdyb3VwKSArCiAgICBnZ3Bsb3QyOjpnZW9tX3RpbGUoY29sb3IgPSAid2hpdGUiKSArCiAgICBnZ3Bsb3QyOjpzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBjKCIjMzM3YWI3IiwgImdyZXk4MCIpLCBuYS52YWx1ZSA9ICJncmV5ODAiKSArCiAgICBnZ3Bsb3QyOjpsYWJzKHggPSAiIiwgZmlsbCA9ICIiKSArCiAgICB2dGhlbWVzOjp0aGVtZV92bW9kZXJuKAogICAgICB4X3RleHRfYW5nbGUgPSBUUlVFLCBiZ19jb2xvciA9ICJ3aGl0ZSIsIGdyaWRfY29sb3IgPSAid2hpdGUiCiAgICApCiAgc2F2ZVJEUyhwbHQsIGZpbGUucGF0aChmaWdfcmVzX2RpciwgImd3YXNfZnVtYV9zbnBzX3N0YWJpbGl0eV9wbG90LnJkcyIpKQogIGdnc2F2ZShwbHQsIGZpbGVuYW1lID0gZmlsZS5wYXRoKGZpZ19yZXNfZGlyLCAiZ3dhc19mdW1hX3NucHNfc3RhYmlsaXR5X3Bsb3QucG5nIiksIAogICAgICAgICB3aWR0aCA9IDgsIGhlaWdodCA9IDYpCiAgCiAgZHQgPC0gc25wc190YWIgJT4lCiAgICBkcGx5cjo6c2VsZWN0KHVuaXFJRDpwb3MpICU+JQogICAgcHJldHR5X0RUKHJvd25hbWVzID0gRkFMU0UpCiAgc2F2ZVJEUyhkdCwgZmlsZS5wYXRoKHRhYl9yZXNfZGlyLCAiZ3dhc19mdW1hX3NucHNfc3RhYmlsaXR5X3RhYmxlLnJkcyIpKQogIAogICMgc3VtbWFyaXplIGZ1bWEgZ3dhcyBtYXBwZWQgZ2VuZSByZXN1bHRzIHVzaW5nIHN0YWJpbGl0eSBhY3Jvc3MgZ3dhcyBydW5zCiAgZ2VuZXNfdGFiIDwtIGRwbHlyOjpiaW5kX3Jvd3MoZ2VuZXNfdGFiX2xzKSAlPiUKICAgIGRwbHlyOjptdXRhdGUodmFsdWUgPSBUUlVFKSAlPiUKICAgIHRpZHlyOjpwaXZvdF93aWRlcigKICAgICAgaWRfY29scyA9IGMoZW5zZywgc3ltYm9sLCBjaHIsIHN0YXJ0LCBlbmQpLAogICAgICBuYW1lc19mcm9tID0gYyhgR1dBUyBNZXRob2RgLCBgUGhlbm90eXBlYCksCiAgICAgIHZhbHVlc19mcm9tID0gdmFsdWUsCiAgICAgIG5hbWVzX3NlcCA9ICIgIiwgCiAgICAgIHZhbHVlc19maWxsID0gRkFMU0UKICAgICkgJT4lCiAgICBkcGx5cjo6cm93d2lzZSgpICU+JQogICAgZHBseXI6Om11dGF0ZSgKICAgICAgbl9jb3VudHMgPSBzdW0oZHBseXI6OmNfYWNyb3NzKHdoZXJlKGlzLmxvZ2ljYWwpKSkKICAgICkgJT4lCiAgICBkcGx5cjo6YXJyYW5nZSgtbl9jb3VudHMpCiAgCiAgZ2VuZXNfdGFiX2xvbmcgPC0gZ2VuZXNfdGFiICU+JQogICAgZHBseXI6OnNlbGVjdCgtZW5zZywgLWNociwgLXN0YXJ0LCAtZW5kLCAtbl9jb3VudHMpICU+JQogICAgdGlkeXI6OnBpdm90X2xvbmdlcihjb2xzID0gLXN5bWJvbCkgJT4lCiAgICBkcGx5cjo6bXV0YXRlKAogICAgICBzeW1ib2wgPSBmYWN0b3Ioc3ltYm9sLCBsZXZlbHMgPSByZXYoZ2VuZXNfdGFiJHN5bWJvbCkpLAogICAgICB2YWx1ZSA9IGZhY3RvcigKICAgICAgICBpZmVsc2UodmFsdWUsICJNYXBwZWQiLCAiTm90IE1hcHBlZCIpLAogICAgICAgIGxldmVscyA9IGMoIk1hcHBlZCIsICJOb3QgTWFwcGVkIikKICAgICAgKQogICAgKQogIAogIHBsdCA8LSBnZ3Bsb3QyOjpnZ3Bsb3QoZ2VuZXNfdGFiX2xvbmcpICsKICAgIGdncGxvdDI6OmFlcyh4ID0gbmFtZSwgeSA9IHN5bWJvbCwgZmlsbCA9IHZhbHVlKSArCiAgICBnZ3Bsb3QyOjpnZW9tX3RpbGUoY29sb3IgPSAid2hpdGUiKSArCiAgICBnZ3Bsb3QyOjpzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBjKCIjMzM3YWI3IiwgImdyZXk4MCIpLCBuYS52YWx1ZSA9ICJncmV5ODAiKSArCiAgICBnZ3Bsb3QyOjpsYWJzKHggPSAiIiwgZmlsbCA9ICIiLCB5ID0gIkdlbmUgU3ltYm9sIikgKwogICAgdnRoZW1lczo6dGhlbWVfdm1vZGVybigKICAgICAgeF90ZXh0X2FuZ2xlID0gVFJVRSwgYmdfY29sb3IgPSAid2hpdGUiLCBncmlkX2NvbG9yID0gIndoaXRlIgogICAgKQogIHNhdmVSRFMocGx0LCBmaWxlLnBhdGgoZmlnX3Jlc19kaXIsICJnd2FzX2Z1bWFfZ2VuZXNfc3RhYmlsaXR5X3Bsb3QucmRzIikpCiAgZ2dzYXZlKHBsdCwgZmlsZW5hbWUgPSBmaWxlLnBhdGgoZmlnX3Jlc19kaXIsICJnd2FzX2Z1bWFfZ2VuZXNfc3RhYmlsaXR5X3Bsb3QucG5nIiksIAogICAgICAgICB3aWR0aCA9IDYsIGhlaWdodCA9IDUpCiAgCiAgZHQgPC0gZ2VuZXNfdGFiICU+JQogICAgZHBseXI6OnNlbGVjdChlbnNnOmVuZCkgJT4lCiAgICBwcmV0dHlfRFQocm93bmFtZXMgPSBGQUxTRSkKICBzYXZlUkRTKGR0LCBmaWxlLnBhdGgodGFiX3Jlc19kaXIsICJnd2FzX2Z1bWFfZ2VuZXNfc3RhYmlsaXR5X3RhYmxlLnJkcyIpKQp9IGVsc2UgewogIGZvciAoZ3dhc19tZXRob2QgaW4gZ3dhc19tZXRob2RzKSB7CiAgICBjYXQoc3ByaW50Zihnd2FzX2hlYWRlciwgdG91cHBlcihnd2FzX21ldGhvZCkpKQogICAgZm9yIChwaGVub3R5cGUgaW4gcGhlbm90eXBlc19hbGwpIHsKICAgICAgcGhlbm90eXBlX25hbWUgPC0gbmFtZXMocGhlbm90eXBlc19hbGwpW3BoZW5vdHlwZXNfYWxsID09IHBoZW5vdHlwZV0KICAgICAgZ3dhc19tZXRob2RfZnN0ciA8LSBzdHJpbmdyOjpzdHJfcmVwbGFjZSh0b2xvd2VyKGd3YXNfbWV0aG9kKSwgIi0iLCAiXyIpCiAgICAgIHBoZW5vdHlwZV9mc3RyIDwtIHN0cmluZ3I6OnN0cl9yZXBsYWNlKHRvbG93ZXIocGhlbm90eXBlKSwgImlsdm0iLCAibHZtaSIpCiAgICAgIGZwYXRoIDwtIGZpbGUucGF0aCgKICAgICAgICByZXNfZGlyLCAiZ3dhc19mdW1hIiwgc3ByaW50ZigiJXNfJXNfZ3dhcyIsIGd3YXNfbWV0aG9kX2ZzdHIsIHBoZW5vdHlwZV9mc3RyKQogICAgICApCiAgICAgIGNhdChzcHJpbnRmKHBoZW5vdHlwZV9oZWFkZXIsIHBoZW5vdHlwZV9uYW1lKSkKICAgICAgZGlzcGxheV9pbWFnZShmaWxlLnBhdGgocmVzX2RpciwgImd3YXNfZnVtYSIsIHNwcmludGYoIm1hbmhhdHRhbl8lc18lcy5wbmciLCBnd2FzX21ldGhvZF9mc3RyLCBwaGVub3R5cGVfZnN0cikpLAogICAgICAgICAgICAgICAgICAgIGNodW5rX2lkeCA9IGNodW5rX2lkeCwKICAgICAgICAgICAgICAgICAgICBjYXB0aW9uID0gc3ByaW50ZigiJ0dXQVMgTWFuaGF0dGFuIHBsb3QgZm9yIHRoZSAlcyBwaGVub3R5cGUgdXNpbmcgJXMuIFJlZCBkYXNoZWQgbGluZSBpbmRpY2F0ZXMgdGhlIGdlbm9tZS13aWRlIHNpZ25pZmljYW5jZSBsZXZlbCAocCA9IDVFLTgpLiciLCBwaGVub3R5cGVfbmFtZSwgZ3dhc19tZXRob2QpKQogICAgICAKICAgICAgY2F0KHNwcmludGYoZnVtYV9oZWFkZXIsICJHZW5vbWljIFJpc2sgTG9jaSIpKQogICAgICBkdCA8LSBmcmVhZChmaWxlLnBhdGgoZnBhdGgsICJHZW5vbWljUmlza0xvY2kudHh0IikpICU+JQogICAgICAgIGRwbHlyOjpzZWxlY3QoLW5TTlBzKSAlPiUKICAgICAgICBkcGx5cjo6cmVuYW1lKAogICAgICAgICAgbkdXQVNTTlZzID0gbkdXQVNTTlBzLCAKICAgICAgICAgIG5JbmRTaWdTTlZzID0gbkluZFNpZ1NOUHMsCiAgICAgICAgICBJbmRTaWdTTlZzID0gSW5kU2lnU05QcywKICAgICAgICAgIG5MZWFkU05WcyA9IG5MZWFkU05QcywKICAgICAgICAgIExlYWRTTlZzID0gTGVhZFNOUHMKICAgICAgICApICU+JQogICAgICAgIHByZXR0eV9EVChyb3duYW1lcyA9IEZBTFNFKQogICAgICBzdWJjaHVua2lmeShkdCwgaSA9IGNodW5rX2lkeCwKICAgICAgICAgICAgICAgICAgY2FwdGlvbiA9IHNwcmludGYoIicqKkxpc3Qgb2YgZ2Vub21pYyByaXNrIGxvY2kgZnJvbSBGVU1BIGZvciB0aGUgJXMgJXMgR1dBUy4qKiB1bmlxSUQgPSBVbmlxdWUgSUQgb2YgU05WcyBjb25zaXN0cyBvZiBjaHI6cG9zaXRpb246YWxsZWxlMTphbGxlbGUyIHdoZXJlIGFsbGVsZXMgYXJlIGFscGhhYmV0aWNhbGx5IG9yZGVyZWQuIHJzSUQgPSByc0lEIG9mIHRoZSB0b3AgbGVhZCBTTlYgZm9yIHRoZSBnaXZlbiBnZW5vbWljIGxvY3VzLiBjaHIgPSBDaHJvbW9zb21lIG9mIHRvcCBsZWFkIFNOVi4gcG9zID0gUG9zaXRpb24gb2YgdG9wIGxlYWQgU05WIG9uIGhnMTkuIHAgPSBQLXZhbHVlIG9mIHRvcCBsZWFkIFNOVi4gc3RhcnQgPSBTdGFydCBwb3NpdGlvbiBvZiB0aGUgbG9jdXMuIGVuZCA9IEVuZCBwb3NpdGlvbiBvZiB0aGUgbG9jdXMuIG5HV0FTU05WcyA9IE51bWJlciBvZiB0aGUgR1dBUy10YWdnZWQgY2FuZGlkYXRlIFNOVnMgd2l0aGluIHRoZSBnZW5vbWljIGxvY3VzLiBuSW5kU2lnU05WcyA9IE51bWJlciBvZiB0aGUgaW5kZXBlbmRlbnQgc2lnbmlmaWNhbnQgU05WcyBpbiB0aGUgZ2Vub21pYyBsb2N1cy4gSW5kU2lnU05WcyA9IHJzSUQgb2YgaW5kZXBlbmRlbnQgc2lnbmlmaWNhbnQgU05WcyBpbiB0aGUgZ2Vub21pYyBsb2N1cy4gbkxlYWRTTlZzID0gVGhlIG51bWJlciBvZiBsZWFkIFNOVnMgaW4gdGhlIGdlbm9taWMgbG9jdXMuIExlYWRTTlZzID0gcnNJRCBvZiBsZWFkIFNOVnMgaW4gdGhlIGdlbm9taWMgbG9jdXMuJyIsIHBoZW5vdHlwZV9uYW1lLCBnd2FzX21ldGhvZCkpCiAgICAgIGNodW5rX2lkeCA8LSBjaHVua19pZHggKyAxCiAgICAgIAogICAgICBjYXQoc3ByaW50ZihmdW1hX2hlYWRlciwgIkxlYWQgU05WcyIpKQogICAgICBkdCA8LSBmcmVhZChmaWxlLnBhdGgoZnBhdGgsICJsZWFkU05Qcy50eHQiKSkgJT4lCiAgICAgICAgZHBseXI6OnNlbGVjdCgtTm8pICU+JQogICAgICAgIGRwbHlyOjpyZW5hbWUoCiAgICAgICAgICBuSW5kU2lnU05WcyA9IG5JbmRTaWdTTlBzLAogICAgICAgICAgSW5kU2lnU05WcyA9IEluZFNpZ1NOUHMKICAgICAgICApICU+JQogICAgICAgIHByZXR0eV9EVChyb3duYW1lcyA9IEZBTFNFKQogICAgICBzdWJjaHVua2lmeShkdCwgaSA9IGNodW5rX2lkeCwKICAgICAgICAgICAgICAgICAgY2FwdGlvbiA9IHNwcmludGYoIicqKkxpc3Qgb2YgbGVhZCBTTlZzIGZyb20gRlVNQSBmb3IgdGhlICVzICVzIEdXQVMuKiogR2Vub21pY0xvY3VzID0gSW5kZXggb2YgYXNzaWduZWQgZ2Vub21pYyBsb2N1cyAobm90ZTogbXVsdGlwbGUgaW5kZXBlbmRlbnQgbGVhZCBTTlZzIGNhbiBiZSBhc3NpZ25lZCB0byB0aGUgc2FtZSBnZW5vbWljIGxvY3VzKS4gdW5pcUlEID0gVW5pcXVlIElEIG9mIFNOVnMgY29uc2lzdHMgb2YgY2hyOnBvc2l0aW9uOmFsbGVsZTE6YWxsZWxlMiB3aGVyZSBhbGxlbGVzIGFyZSBhbHBoYWJldGljYWxseSBvcmRlcmVkLiByc0lEID0gcnNJRCBvZiB0aGUgU05WLiBjaHIgPSBDaHJvbW9zb21lLiBwb3MgPSBQb3NpdGlvbiBvbiBoZzE5LiBwID0gUC12YWx1ZSBmcm9tIEdXQVMuIG5JbmRTaWdTTlZzID0gTnVtYmVyIG9mIGluZGVwZW5kZW50IHNpZ25pZmljYW50IFNOVnMgd2hpY2ggYXJlIGluIExEIG9mIHRoZSBsZWFkIFNOViBhdCAkcl4yJCA9IDAuMS4gSW5kU2lnU05WcyA9IHJzSUQgb2YgaW5kZXBlbmRlbnQgc2lnbmlmaWNhbnQgU05WcyB3aGljaCBhcmUgaW4gTEQgb2YgdGhlIGxlYWQgU05WIGF0ICRyXjIkID0gMC4xLiciLCBwaGVub3R5cGVfbmFtZSwgZ3dhc19tZXRob2QpKQogICAgICBjaHVua19pZHggPC0gY2h1bmtfaWR4ICsgMQogICAgICAKICAgICAgY2F0KHNwcmludGYoZnVtYV9oZWFkZXIsICJJbmRlcGVuZGVudCBTaWduaWZpY2FudCBTTlZzIikpCiAgICAgIGR0IDwtIGZyZWFkKGZpbGUucGF0aChmcGF0aCwgIkluZFNpZ1NOUHMudHh0IikpICU+JQogICAgICAgIGRwbHlyOjpzZWxlY3QoLU5vLCAtblNOUHMpICU+JQogICAgICAgIGRwbHlyOjpyZW5hbWUoCiAgICAgICAgICBuR1dBU1NOVnMgPSBuR1dBU1NOUHMKICAgICAgICApICU+JQogICAgICAgIHByZXR0eV9EVChyb3duYW1lcyA9IEZBTFNFKQogICAgICBzdWJjaHVua2lmeShkdCwgaSA9IGNodW5rX2lkeCwKICAgICAgICAgICAgICAgICAgY2FwdGlvbiA9IHNwcmludGYoIicqKkxpc3Qgb2YgaW5kZXBlbmRlbnQgc2lnbmlmaWNhbnQgU05WcyBmcm9tIEZVTUEgZm9yIHRoZSAlcyAlcyBHV0FTLioqIEdlbm9taWNMb2N1cyA9IEluZGV4IG9mIGFzc2lnbmVkIGdlbm9taWMgbG9jdXMgKG5vdGU6IG11bHRpcGxlIGluZGVwZW5kZW50IGxlYWQgU05WcyBjYW4gYmUgYXNzaWduZWQgdG8gdGhlIHNhbWUgZ2Vub21pYyBsb2N1cykuIHVuaXFJRCA9IFVuaXF1ZSBJRCBvZiBTTlZzIGNvbnNpc3RzIG9mIGNocjpwb3NpdGlvbjphbGxlbGUxOmFsbGVsZTIgd2hlcmUgYWxsZWxlcyBhcmUgYWxwaGFiZXRpY2FsbHkgb3JkZXJlZC4gcnNJRCA9IHJzSUQgb2YgdGhlIFNOVi4gY2hyID0gQ2hyb21vc29tZS4gcG9zID0gUG9zaXRpb24gb24gaGcxOS4gcCA9IFAtdmFsdWUgZnJvbSBHV0FTLiBuR1dBU1NOVnMgPSBOdW1iZXIgb2YgR1dBUy10YWdnZWQgU05WcyB3aGljaCBhcmUgaW4gTEQgb2YgdGhlIGluZGVwZW5kZW50IHNpZ25pZmljYW50IFNOViBnaXZlbiAkcl4yJCA9IDAuNi4nIiwgcGhlbm90eXBlX25hbWUsIGd3YXNfbWV0aG9kKSkKICAgICAgY2h1bmtfaWR4IDwtIGNodW5rX2lkeCArIDEKICAgICAgCiAgICAgIGNhdChzcHJpbnRmKGZ1bWFfaGVhZGVyLCAiTWFwcGVkIEdlbmVzIikpCiAgICAgIGR0IDwtIGZyZWFkKGZpbGUucGF0aChmcGF0aCwgImdlbmVzLnR4dCIpKSAlPiUKICAgICAgICBkcGx5cjo6c2VsZWN0KC10aWR5c2VsZWN0Ojphbnlfb2YoYygiY2lNYXAiLCAiY2lNYXB0cyIpKSkgJT4lCiAgICAgICAgZHBseXI6OnJlbmFtZSgKICAgICAgICAgIHBvc01hcFNOVnMgPSBwb3NNYXBTTlBzLAogICAgICAgICAgSW5kU2lnU05WcyA9IEluZFNpZ1NOUHMKICAgICAgICApICU+JQogICAgICAgIHByZXR0eV9EVChyb3duYW1lcyA9IEZBTFNFKQogICAgICBzdWJjaHVua2lmeShkdCwgaSA9IGNodW5rX2lkeCwKICAgICAgICAgICAgICAgICAgY2FwdGlvbiA9IHNwcmludGYoIicqKkxpc3Qgb2YgbWFwcGVkIGdlbmVzICh2aWEgcG9zaXRpb25hbCBtYXBwaW5nKSBmcm9tIEZVTUEgZm9yIHRoZSAlcyAlcyBHV0FTLioqIGVuc2cgPSBFTlNHIElELiBzeW1ib2wgPSBHZW5lIFN5bWJvbC4gY2hyID0gQ2hyb21vc29tZS4gc3RhcnQgPSBTdGFydGluZyBwb3NpdGlvbiBvZiB0aGUgZ2VuZS4gZW5kID0gRW5kaW5nIHBvc2l0aW9uIG9mIHRoZSBnZW5lLiBzdHJhbmQgPSBTdHJhbmQgb2YgdGhlIGdlbmUuIHR5cGUgPSBHZW5lIGJpb3R5cGUgZnJvbSBFbnNlbWJsLiBlbnRyZXpJRCA9IGVudHJleiBJRCAoaWYgYXZhaWxhYmxlKS4gSFVHTyA9IEhVR08gKEhHTkMpIGdlbmUgc3ltYm9sLiBwTEkgPSBwTEkgc2NvcmUgKHRoZSBwcm9iYWJpbGl0eSBvZiBiZWluZyBsb3NzLW9mLWZ1bmN0aW9uIGludG9sZXJhbnQpIGZyb20gRXhBQyBkYXRhYmFzZTsgdGhlIGhpZ2hlciB0aGUgc2NvcmUgaXMsIHRoZSBtb3JlIGludG9sZXJhbnQgdG8gbG9zcy1vZi1mdW5jdGlvbiBtdXRhdGlvbnMgdGhlIGdlbmUgaXMuIG5jUlZJUyA9IE5vbi1jb2RpbmcgcmVzaWR1YWwgdmFyaWF0aW9uIGludG9sZXJhbmNlIHNjb3JlOyB0aGUgaGlnaGVyIHRoZSBzY29yZSBpcywgdGhlIG1vcmUgaW50b2xlcmFudCB0byBub24tY29kaW5nIHZhcmlhdGlvbiB0aGUgZ2VuZSBpcy4gcG9zTWFwU05WcyA9IE51bWJlciBvZiBTTlZzIG1hcHBlZCB0byBnZW5lIGJhc2VkIG9uIHBvc2l0aW9uYWwgbWFwcGluZy4gcG9zTWFwTWF4Q0FERCA9IFRoZSBtYXhpbXVtIENBREQgc2NvcmUgb2YgbWFwcGVkIFNOVnMgYnkgcG9zaXRpb25hbCBtYXBwaW5nLiBtaW5Hd2FzUCA9IFRoZSBtaW5pbXVtIFAtdmFsdWUgb2YgbWFwcGVkIFNOVnMuIEluZFNpZ1NOVnMgPSByc0lEIG9mIHRoZSBpbmRlcGVuZGVudCBzaWduaWZpY2FudCBTTlZzIHRoYXQgYXJlIGluIExEIHdpdGggdGhlIG1hcHBlZCBTTlZzLiBHZW5vbWljTG9jdXMgPSBJbmRleCBvZiBnZW5vbWljIGxvY2kgd2hlcmUgbWFwcGVkIFNOVnMgYXJlIGZyb20uJyIsIHBoZW5vdHlwZV9uYW1lLCBnd2FzX21ldGhvZCkpCiAgICAgIGNodW5rX2lkeCA8LSBjaHVua19pZHggKyAxCiAgICB9CiAgfQp9CgpgYGAKCgojIyMgU3RhYmlsaXR5IEFuYWx5c2lzIHsudW5udW1iZXJlZCAudGFic2V0IC50YWJzZXQtcGlsbHMgLnRhYnNldC1mYWRlIC50YWJzZXQtY2lyY2xlfQoKPGRpdiBjbGFzcz0icGFuZWwgcGFuZWwtZGVmYXVsdCBwYWRkZWQtcGFuZWwiPgpUbyBmdXJ0aGVyIGludmVzdGlnYXRlIHRoZSBjaG9pY2Ugb2YgR1dBUyBtZXRob2QgYW5kIHBoZW5vdHlwZSwgd2UgY29uZHVjdGVkIGEgZGVlcGVyIGV4cGxvcmF0aW9uIGludG8gdGhlIHNpbWlsYXJpdGllcyBhbmQgZGlmZmVyZW5jZXMgYmV0d2VlbiB0aGUgQk9MVC1MTU0gYW5kIFBMSU5LIHJlc3VsdHMgYXMgd2VsbCBhcyBiZXR3ZWVuIHRoZSBMVk0gYW5kIExWTWkgcmVzdWx0cyBpbiB0aGUgc3RhYmlsaXR5IGFuYWx5c2lzIGJlbG93LiBUaGUgcHJpbWFyeSBnb2FsIG9mIHRoaXMgc3RhYmlsaXR5IGFuYWx5c2lzIGlzIHRvIGFuc3dlciB0aGUgZm9sbG93aW5nIHR3byBxdWVzdGlvbnM6CgoxLiAqKkFyZSB0aGVyZSBsYXJnZSBkaWZmZXJlbmNlcyBiZXR3ZWVuIHRoZSBHV0FTIHAtdmFsdWVzIGZyb20gQk9MVC1MTU0gYW5kIFBMSU5LPyoqCiAgLSBGaWd1cmUgXEByZWYoZmlnOnN1YmNodW5rLTIyKTogRm9yIGVhY2ggU05WLCB3ZSBwbG90IHRoZSBwLXZhbHVlIChsb2ctdHJhbnNmb3JtZWQpIG9idGFpbmVkIHZpYSBCT0xULUxNTSAoeC1heGlzKSBhbmQgUExJTksgKHktYXhpcykgZm9yIGVhY2ggb2YgdGhlIExWTSAobGVmdCkgYW5kIExWTWkgKHJpZ2h0KSBwaGVub3R5cGVzLiBXZSBzZWUgdGhhdCB0aGUgbW9zdCBzaWduaWZpY2FudCBHV0FTIGhpdHMgdGVuZCB0byBiZSBzdGFibGUsIG5vIG1hdHRlciB0aGUgY2hvaWNlIG9mIGFsZ29yaXRobSwgYnV0IGFzIHRoZSBzdHJlbmd0aCBvZiB0aGUgYXNzb2NpYXRpb24gZGVjcmVhc2VzLCB0aGVyZSBpcyBncmVhdGVyIHZhcmlhdGlvbiBpbiB0aGUgcC12YWx1ZSBiZXR3ZWVuIEJPTFQtTE1NIGFuZCBQTElOSy4gVGhpcyBpcyB0byBzYXkgdGhhdCB0aGVyZSBpcyBtb3JlIHN0YWJpbGl0eSBhcm91bmQgdGhlIFNOVnMgd2l0aCB0aGUgc3Ryb25nZXN0IGFzc29jaWF0aW9ucyB3aXRoIExWTWkgYW5kIGxlc3Mgc3RhYmlsaXR5IGFyb3VuZCB0aGUgU05WcyB3aXRoIG1vZGVyYXRlIG9yIHdlYWsgYXNzb2NpYXRpb25zIHdpdGggTFZNaS4gQW5vdGhlciByZWFzb24gZm9yIHRha2luZyB0aGUgdW5pb24gb2YgdGhlIHRvcCAxMDAwIFNOVnMgZnJvbSBlYWNoIEdXQVMgYWxnb3JpdGhtIGluIHRoZSBsby1zaVJGIHBpcGVsaW5lIHdhcyB0byBhbGxvdyB0aGVzZSBtb2RlcmF0ZSB0byB3ZWFrIGFzc29jaWF0aW9uIFNOVnMgdGhlIGNoYW5jZSBvZiBiZWluZyBpZGVudGlmaWVkIGluIGEgbXVsdGl2YXJpYXRlIG1vZGVsIChpLmUuLCB2aWEgaXRlcmF0aXZlIHJhbmRvbSBmb3Jlc3QpLgoKMi4gKipXaGF0IGFyZSB0aGUgRlVNQSBHV0FTIGZpbmRpbmdzIHRoYXQgYXJlIHN0YWJsZSBhY3Jvc3MgR1dBUyBtZXRob2RzIChCT0xULUxNTSBhbmQgUExJTkspIGFuZCBjaG9pY2Ugb2YgcGhlbm90eXBlIChMVk0gYW5kIExWTWkpPyoqIEFzIGFkdm9jYXRlZCBieSB0aGUgc3RhYmlsaXR5IHByaW5jaXBsZSAoIlMiIGluIFBDUykgW0B5dTIwMjB2ZXJpZGljYWw7IEB5dTIwMTNzdGFiaWxpdHldLCB3ZSB2aWV3IHN0YWJpbGl0eSBhY3Jvc3MgdGhlc2UgYXJiaXRyYXJ5IGNob2ljZXMgYXMgYSBtaW5pbXVtIHJlcXVpcmVtZW50IGZvciBtYWtpbmcgYSBzY2llbnRpZmljIGRpc2NvdmVyeS4KICAtIEluIEZpZ3VyZSBcQHJlZihmaWc6c3ViY2h1bmstMjMpLCB3ZSBzdW1tYXJpemUgdGhlIFNOVnMsIGlkZW50aWZpZWQgYnkgRlVNQSwgdG8gYmUgdGhlIHRvcCBsZWFkIFNOVnMgKHBlciBnZW5vbWljIHJpc2sgbG9jdXMpLCBsZWFkIFNOVnMsIGFuZC9vciBpbmRlcGVuZGVudCBzaWduaWZpY2FudCBTTlZzIGZvciBlYWNoIEdXQVMgbWV0aG9kIChCT0xULUxNTSBhbmQgUExJTkspIGFuZCBjaG9pY2Ugb2YgcGhlbm90eXBlIChMVk0gYW5kIExWTWkpLiBTb21lIHRha2Vhd2F5cyBoZXJlOgogICAgLSByczMwNDU2OTYsIGFuIGludHJvbmljICpUVE4qIHZhcmlhbnQsIGlzIHRoZSBvbmx5IHN0YWJsZSB0b3AgbGVhZCBTTlYsIGlkZW50aWZpZWQgYWNyb3NzIGFsbCBmb3VyIEdXQVMgcnVucy4KICAgIC0gQmVzaWRlcyByczMwNDU2OTYsIHJzMTg3MzE2NCwgYW4gaW50cm9uaWMgKkNDREMxNDEqIHZhcmlhbnQsIGlzIHRoZSBvbmx5IHN0YWJsZSBsZWFkIFNOViwgaWRlbnRpZmllZCBieSBGVU1BIGFjcm9zcyBhbGwgZm91ciBHV0FTIHJ1bnMuCiAgICAtIHJzNzU5MTA5MSAoYW4gaW50cm9uaWMgKkNDREMxNDEqIHZhcmlhbnQgd2l0aCB0aGUgaGlnaGVzdCBmcmVxdWVuY3kgb2Ygb2NjdXJyZW5jZSBpbiBsby1zaVJGLCBzZWVuIGxhdGVyKSwgYWxvbmcgd2l0aCByczk2NzUwNywgcnMxMjYyMjUwMCwgYW5kIHJzMTAxNzgwMDMsIHdlcmUgc3RhYmx5IGlkZW50aWZpZWQgYXMgaW5kZXBlbmRlbnQgc2lnbmlmaWNhbnQgU05WcyBieSBGVU1BIGFjcm9zcyBhbGwgZm91ciBHV0FTIHJ1bnMuCiAgICAtIFR3byBvdGhlciBTTlZzIChyczYyMTc4OTc3LCByczczOTczMTcxKSB3ZXJlIGFsc28gaWRlbnRpZmllZCBhcyBpbmRlcGVuZGVudCBzaWduaWZpY2FudCBTTlZzIGJ5IEZVTUEgdXNpbmcgYm90aCBCT0xULUxNTSBhbmQgUExJTksgZm9yIHRoZSBMVk1pIHBoZW5vdHlwZS4KICAtIEluIEZpZ3VyZSBcQHJlZihmaWc6c3ViY2h1bmstMjQpLCB3ZSBzdW1tYXJpemUgdGhlIGdlbmVzIHRoYXQgd2VyZSBwb3NpdGlvbmFsbHktbWFwcGVkIGFuZCBwcmlvcml0aXplZCBieSBGVU1BIGFjcm9zcyB0aGUgZGlmZmVyZW50IEdXQVMgbWV0aG9kcyAoQk9MVC1MTU0gYW5kIFBMSU5LKSBhbmQgY2hvaWNlIG9mIHBoZW5vdHlwZSAoTFZNIGFuZCBMVk1pKS4KICAgIC0gVGhlIGdlbmVzIHRoYXQgd2VyZSBzdGFibHkgbWFwcGVkIGJ5IEZVTUEgYWNyb3NzIGFsbCBmb3VyIEdXQVMgcnVucyBhcmUgKlBSS1JBKiwgKkRGTkI1OSosICpGS0JQNyosICpQTEVLSEEzKiwgKlRUTiosIGFuZCAqQ0NEQzE0MSouIFdlIG5vdGUgdGhhdCBhbGwgb2YgdGhlc2UgZ2VuZXMgYXJlIGxvY2F0ZWQgbmVhciBlYWNoIG90aGVyIG9uIGNocm9tb3NvbWUgMiB3aXRoaW4gfjYwMGtiLiBUaGUgc3RhcnQgcG9zaXRpb24gb2YgUFJLUkEgaXMgMTc5Mjk2MTQxIHdoaWxlIHRoZSBlbmQgcG9zaXRpb24gb2YgQ0NEQzE0MSBpcyAxNzk5MTQ4MTMsIHdpdGggYWxsIG90aGVyIGFmb3JlbWVudGlvbmVkIGdlbmVzIGluIGJldHdlZW4uCiAgICAtIE5vIG90aGVyIGdlbmVzIHdlcmUgaWRlbnRpZmllZCB3aGVuIHVzaW5nIGJvdGggQk9MVC1MTU0gYW5kIFBMSU5LIGZvciB0aGUgTFZNaSBwaGVub3R5cGUuCjwvZGl2PgoKYGBge3IgZ3dhcy1zdGFiaWxpdHksIHJlc3VsdHMgPSAiYXNpcyJ9ClBWQUxfVEhSIDwtIDQKCiMgcGxvdCBzdW1tYXJ5IHJlc3VsdHMKaWYgKCFwYXJhbXMkZXZhbCkgewogIGRpc3BsYXlfaW1hZ2UoZmlsZS5wYXRoKGZpZ19yZXNfZGlyLCAiZ3dhc19wdmFsdWVzX2NvbXBhcmUucG5nIiksCiAgICAgICAgICAgICAgICBjaHVua19pZHggPSBjaHVua19pZHgsCiAgICAgICAgICAgICAgICBjYXB0aW9uID0gIidDb21wYXJpc29uIG9mIHRoZSBCT0xULUxNTSBhbmQgUExJTksgR1dBUyBwLXZhbHVlcyBmb3IgZWFjaCBwaGVub3R5cGUgKExWTSBsZWZ0LCBMVk1pIHJpZ2h0KS4gRWFjaCBwb2ludCByZXByZXNlbnRzIGEgU05WIHdpdGggaXRzIEJPTFQtTE1NIHAtdmFsdWUgb24gdGhlIHgtYXhpcyBhbmQgaXRzIFBMSU5LIHAtdmFsdWUgb24gdGhlIHktYXhpcy4nIikKICAKICBkaXNwbGF5X2ltYWdlKGZpbGUucGF0aChmaWdfcmVzX2RpciwgImd3YXNfZnVtYV9zbnBzX3N0YWJpbGl0eV9wbG90LnBuZyIpLAogICAgICAgICAgICAgICAgY2h1bmtfaWR4ID0gY2h1bmtfaWR4LAogICAgICAgICAgICAgICAgY2FwdGlvbiA9ICInU3VtbWFyeSBvZiBhbm5vdGF0ZWQgU05WcyBmcm9tIEZVTUEgYWNyb3NzIGRpZmZlcmVudCBHV0FTIG1ldGhvZHMgKEJPTFQtTE1NIGFuZCBQTElOSykgYW5kIGFjcm9zcyBkaWZmZXJlbnQgY2hvaWNlcyBvZiBwaGVub3R5cGUgKExWTWkgYW5kIExWTSkuJyIpCiAgCiAgIyBkdCA8LSByZWFkUkRTKGZpbGUucGF0aCh0YWJfcmVzX2RpciwgImd3YXNfZnVtYV9zbnBzX3N0YWJpbGl0eV90YWJsZS5yZHMiKSkKICAjIHN1YmNodW5raWZ5KGR0LCBpID0gY2h1bmtfaWR4LCBjYXB0aW9uID0gIidMaXN0IG9mIGFubm90YXRlZCBTTlZzIGZyb20gRlVNQS4nIikKICAjIGNodW5rX2lkeCA8LSBjaHVua19pZHggKyAxCiAgCiAgZGlzcGxheV9pbWFnZShmaWxlLnBhdGgoZmlnX3Jlc19kaXIsICJnd2FzX2Z1bWFfZ2VuZXNfc3RhYmlsaXR5X3Bsb3QucG5nIiksCiAgICAgICAgICAgICAgICBjaHVua19pZHggPSBjaHVua19pZHgsCiAgICAgICAgICAgICAgICBjYXB0aW9uID0gIidTdW1tYXJ5IG9mIG1hcHBlZCBnZW5lcyBmcm9tIEZVTUEgYWNyb3NzIGRpZmZlcmVudCBHV0FTIG1ldGhvZHMgKEJPTFQtTE1NIGFuZCBQTElOSykgYW5kIGFjcm9zcyBkaWZmZXJlbnQgY2hvaWNlcyBvZiBwaGVub3R5cGUgKExWTWkgYW5kIExWTSkuJyIpCiAgCiAgIyBkdCA8LSByZWFkUkRTKGZpbGUucGF0aCh0YWJfcmVzX2RpciwgImd3YXNfZnVtYV9nZW5lc19zdGFiaWxpdHlfdGFibGUucmRzIikpCiAgIyBzdWJjaHVua2lmeShkdCwgaSA9IGNodW5rX2lkeCwgY2FwdGlvbiA9ICInTGlzdCBvZiBtYXBwZWQgZ2VuZXMgZnJvbSBGVU1BLiciKQogICMgY2h1bmtfaWR4IDwtIGNodW5rX2lkeCArIDEKfQoKYGBgCgojIyBHV0FTLWZpbHRlcmVkIFNOVnMgey51bm51bWJlcmVkIC50YWJzZXQgLnRhYnNldC1waWxscyAudGFic2V0LWZhZGUgLnRhYnNldC1zcXVhcmV9Cgo8ZGl2IGNsYXNzPSJwYW5lbCBwYW5lbC1kZWZhdWx0IHBhZGRlZC1wYW5lbCI+CkluIHRoaXMgc2VjdGlvbiwgd2UgYnJpZWZseSBleHBsb3JlIHRoZSBzZWxlY3RlZCAxNDA1IFNOVnMgdGhhdCBwYXNzZWQgdGhlIEdXQVMgZmlsdGVyIGZvciB0aGUgTFZNaSBwaGVub3R5cGUuIFdlIG1ha2UgdHdvIG9ic2VydmF0aW9ucyB0aGF0IHdpbGwgaW1wYWN0IGhvdyB3ZSBpbnRlcnByZXQgdGhlIGxvLXNpUkYgZml0IGRvd25zdHJlYW06CgotIFRoZXJlIGFyZSBzdHJvbmcgY29ycmVsYXRpb25zIHdpdGhpbiBibG9ja3Mgb2YgbmVpZ2hib3JpbmcgU05WcyBkdWUgdG8gbGlua2FnZSBkaXNlcXVpbGlicml1bSAoTEQpIChGaWd1cmUgXEByZWYoZmlnOnN1YmNodW5rLTI1KSkuIFRoaXMgaXMgYSBsYXJnZSBjb250cmlidXRpbmcgZmFjdG9yIGZvciB3aHkgd2UgdWx0aW1hdGVseSBleHRyYWN0ZWQgZmVhdHVyZSBpbXBvcnRhbmNlcyBmcm9tIHRoZSBsby1zaVJGIGZpdCBhdCB0aGUgbGV2ZWwgb2YgZ2VuZXRpYyBsb2NpLCByYXRoZXIgdGhhbiBmb3IgZWFjaCBpbmRpdmlkdWFsIFNOVi4KLSBUaGVyZSBhcmUgbGFyZ2UgZGlmZmVyZW5jZXMgaW4gdGhlIG51bWJlciBvZiBTTlZzIHRoYXQgcGFzc2VkIHRoZSBHV0FTIGZpbHRlciBmcm9tIGVhY2ggZ2VuZXRpYyBsb2NpIChGaWd1cmUgXEByZWYoZmlnOnN1YmNodW5rLTI2KSkuIFdlIGhlbmNlIG11c3QgYWNjb3VudCBmb3IgdGhpcyBpbiB0aGUgbG8tc2lSRiBsb2N1cy1sZXZlbCBpbXBvcnRhbmNlIHNjb3JlLiAKCldlIHdpbGwgZXhwYW5kIHVwb24gdGhpcyBsb2N1cy1sZXZlbCBpbXBvcnRhbmNlIHNjb3JlIGluIGEgbGF0ZXIgc2VjdGlvbiAoc2VlIGBQcmlvcml0aXphdGlvbiBTdGVwYCkuCgpBZGRpdGlvbmFsIG5vdGVzOgoKLSBHaXZlbiB0aGUgaW50ZXJlc3QgaW4gKkNDREMxNDEqIGFuZCAqVFROKiBpbiBvdXIgd29yayBhbmQgdGhlaXIgY2xvc2UgcHJveGltaXR5IHRvIGVhY2ggb3RoZXIgb24gY2hyb21vc29tZSAyLCB3ZSBwb2ludCBvdXQgYSBjb3VwbGUgcGFpcndpc2UgKFBlYXJzb24pIGNvcnJlbGF0aW9ucyBvZiBwYXJ0aWN1bGFyIHJlbGV2YW5jZToKICAtICR8IENvcihcdGV4dHtyczc1OTEwOTF9LCBcdGV4dHsgcnM2NjczMzYyMX0pIHwgPSAwLjM1JAogIC0gJHwgQ29yKFx0ZXh0e3JzNzU5MTA5MX0sIFx0ZXh0eyByczMwNDU2OTZ9KSB8ID0gMC4zNCQKICAtIHJzNzU5MTA5MSBpcyB0aGUgdG9wIFNOViBmcm9tIHRoZSBDQ0RDMTQxIGxvY3VzIGluIGxvLXNpUkYgYW5kIGlzIG9uZSBvZiB0aGUgdG9wIENDREMxNDEgR1dBUyBoaXRzIChpbiBmYWN0LCBpcyBpZGVudGlmaWVkIHRvIGJlIGEgc3RhYmxlIGluZGVwZW5kZW50IHNpZ25pZmljYW50IFNOViAoc2VlIGBHV0FTIFJlc3VsdHMgU3VtbWFyeWAgdGFiKSkuIHJzMzA0NTY5NiwgYW4gaW50cm9uaWMgKlRUTiogU05WLCB3YXMgc3RhYmx5IGlkZW50aWZpZWQgdG8gYmUgYSB0b3AgbGVhZCBTTlYgaW4gdGhlIEdXQVNlcywgYW5kIHJzNjY3MzM2MjEgaXMgdGhlIHRvcCBTTlYgZnJvbSB0aGUgVFROIGxvY3VzIGluIGxvLXNpUkYuIFRoaXMgaXMgdG8gc2F5IHRoYXQgdGhlIGNvcnJlbGF0aW9uIGJldHdlZW4gdGhlIENDREMxNDEgYW5kIFRUTiBsb2NpIGlzIG1vZGVyYXRlIGFuZCBtYXkgcG9zc2libHkgc3VnZ2VzdCBpbmRlcGVuZGVudCByb2xlcyBvZiBDQ0RDMTQxIGFuZCBUVE4gaW4gdGhlaXIgZGV0ZWN0ZWQgaW50ZXJhY3Rpb24uIEEgZnVydGhlciBkaXNjdXNzaW9uIG9mIHRoaXMgaXMgcHJvdmlkZWQgaW4gW0B3YW5nMjAyM2VwaXN0YXNpc10oKS4gW05vdGU6IHdlIHVzZSB0aGUgdGVybSAqdG9wIFNOViBmcm9tIGEgZ2VuZXRpYyBsb2N1cyBpbiBsby1zaVJGKiB0byBtZWFuIHRoZSBTTlYgaW4gdGhlIHNwZWNpZmllZCBnZW5ldGljIGxvY3VzIHdpdGggdGhlIGhpZ2hlc3QgZnJlcXVlbmN5IG9mIG9jY3VycmVuY2UgYWNyb3NzIGRlY2lzaW9uIHBhdGhzIGluIHRoZSBzaVJGIGZpdC5dCgo8L2Rpdj4KCmBgYHtyIGVkYS10b3Atc25wcywgcmVzdWx0cyA9ICJhc2lzIn0KCkhFQVRNQVBfSEVJR0hUIDwtIDgKCnBoZW5vdHlwZV9oZWFkZXIgPC0gIlxuXG4jIyMgJXMgey51bm51bWJlcmVkIC50YWJzZXQgLnRhYnNldC1waWxscyAudGFic2V0LWZhZGUgLnRhYnNldC1jaXJjbGV9IFxuXG4iCnN1YnNlY3Rpb25faGVhZGVyIDwtICJcblxuIyMjIyAlcyB7LnVubnVtYmVyZWR9XG5cbiIKcGhlbm90eXBlIDwtICJpTFZNIgpwaGVub3R5cGVfbmFtZSA8LSAiTFZNaSIKCmlmIChwYXJhbXMkZXZhbCkgewogICMgbG9hZCBpbiBkYXRhCiAgbnNucHMgPC0gMTAwMAogIHNucGxpc3QgPC0gImFwcDEzNzIxIgogIGJvbHRfZGlyIDwtIGZpbGUucGF0aCgiLi4iLCAicmVzdWx0cyIsICJnd2FzX2JvbHRfbG1tIikKICBwbGlua19kaXIgPC0gZmlsZS5wYXRoKCIuLiIsICJyZXN1bHRzIiwgImd3YXNfcGxpbmsiKQogIGtlZXBfc25wcyA8LSBtYXAoYyhib2x0X2RpciwgcGxpbmtfZGlyKSwKICAgICAgICAgICAgICAgICAgIGZ1bmN0aW9uKGZkaXIpIHsKICAgICAgICAgICAgICAgICAgICAgZnBhdGggPC0gZmlsZS5wYXRoKGZkaXIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwYXN0ZTAocGhlbm90eXBlLCAiX25vcm1fIiwgc25wbGlzdCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiLnN0YXRzX2Fubm90IikpCiAgICAgICAgICAgICAgICAgICAgIHNucHMgPC0gZnJlYWQoZnBhdGgpICU+JQogICAgICAgICAgICAgICAgICAgICAgIHNsaWNlKDE6bnNucHMpICU+JQogICAgICAgICAgICAgICAgICAgICAgIHB1bGwoU05QKQogICAgICAgICAgICAgICAgICAgfSkgJT4lCiAgICBwdXJycjo6cmVkdWNlKGMpICU+JQogICAgdW5pcXVlKCkKICBzbnBfZGYgPC0gbG9hZFNOUEluZm8oa2VlcF9zbnBzLCBieSA9ICJyc0lEIikKICB3cml0ZS5jc3Yoc25wX2RmICU+JQogICAgICAgICAgICAgIGRwbHlyOjpzZWxlY3QoLU5hbWUpLCAKICAgICAgICAgICAgIi4uL3Jlc3VsdHMvZ3dhc19maWx0ZXJlZF9zbnBzLmNzdiIsIHF1b3RlID0gRkFMU0UsIHJvdy5uYW1lcyA9IEZBTFNFKQoKICAjIGZyZXF1ZW5jeSB0YWJsZSBvZiBzbnBzIGluIGVhY2ggbG9jaQogIHRhYl9vdXQgPC0gc25wX2RmICU+JQogICAgZ3JvdXBfYnkoQ2hyLCBHZW5lKSAlPiUKICAgIHN1bW1hcmlzZShgU3RhcnQgUG9zLmAgPSBtaW4oUG9zKSwKICAgICAgICAgICAgICBgRW5kIFBvcy5gID0gbWF4KFBvcyksCiAgICAgICAgICAgICAgYCMgU05Qc2AgPSBuKCksCiAgICAgICAgICAgICAgYEdlbmUgRnVuY3Rpb25gID0gZGF0YS5mcmFtZSh0YWJsZShgR2VuZSBGdW5jdGlvbmApKSAlPiUKICAgICAgICAgICAgICAgIG11dGF0ZShzdHIgPSBwYXN0ZTAoR2VuZS5GdW5jdGlvbiwgIjogIiwgRnJlcSkpICU+JQogICAgICAgICAgICAgICAgcHVsbChzdHIpICU+JQogICAgICAgICAgICAgICAgcGFzdGUoY29sbGFwc2UgPSAiOyAiKSkgJT4lCiAgICBhcnJhbmdlKENociwgYFN0YXJ0IFBvcy5gKSAlPiUKICAgIHJlbmFtZSgiTG9jdXMiID0gIkdlbmUiLCAiRnVuY3Rpb24iID0gIkdlbmUgRnVuY3Rpb24iKQogIHNhdmVSRFModGFiX291dCwKICAgICAgICAgIGZpbGUucGF0aCh0YWJfcmVzX2RpciwKICAgICAgICAgICAgICAgICAgICBwYXN0ZTAocGhlbm90eXBlLCAiX2d3YXNfc25wc19mcmVxdWVuY3lfYnlfZ2VuZS5yZHMiKSkpCiAgd3JpdGUuY3N2KHRhYl9vdXQsICIuLi9yZXN1bHRzL2d3YXNfZmlsdGVyZWRfc25wc19ieV9sb2NpLmNzdiIsIHF1b3RlID0gRkFMU0UsIHJvdy5uYW1lcyA9IEZBTFNFKQoKICAjIGdldCBkYXRhIHRvIG1ha2UgY29ycmVsYXRpb24gaGVhdG1hcAogIGludmlzaWJsZShjYXB0dXJlLm91dHB1dCgKICAgIHRyYWluX2RhdGEgPC0gbG9hZERhdGEocGhlbm9fbmFtZSA9IHBoZW5vdHlwZSwgcGhlbm9fYmluYXJ5ID0gRiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgbiA9IDE1MDAwLCBuX3Rlc3QgPSAwLCBpbmNsdWRlX2RlbXMgPSBGLAogICAgICAgICAgICAgICAgICAgICAgICAgICBzbnBsaXN0ID0gc25wbGlzdCwga2VlcF9zbnBzID0ga2VlcF9zbnBzKQogICkpCiAgCiAgIyBzbnAgY29ycmVsYXRpb24gaGVhdG1hcAogIGduYW1lcyA8LSBzbnBfZGYgJT4lCiAgICBncm91cF9ieShHZW5lKSAlPiUKICAgIG11dGF0ZShHZW5lTmFtZSA9IHBhc3RlKEdlbmUsIHJzSUQsIHNlcCA9ICIsICIpKSAlPiUKICAgIHB1bGwoR2VuZU5hbWUpCiAgcGx0X2RmIDwtIHRyYWluX2RhdGEkZ2Vub190cmFpbgogIGNvbG5hbWVzKHBsdF9kZikgPC0gZ25hbWVzCiAgcGx0IDwtIHZkb2NzOjpwbG90X2Nvcl9oZWF0bWFwKFggPSBwbHRfZGYsIGFic29sdXRlX3ZhbHVlID0gVFJVRSwgY2x1c3QgPSBGQUxTRSkgKwogICAgbGFicyh4ID0gIlNOViIsIHkgPSAiU05WIiwgZmlsbCA9ICJ8Q29ycmVsYXRpb258IikgKwogICAgZ2dwbG90Mjo6c2NhbGVfZmlsbF9ncmFkaWVudChsb3cgPSAid2hpdGUiLCBoaWdoID0gInJlZCIpCiAgIyBjbGVhbiB1cCBheGVzIGxhYmVscyAtIG9ubHkgc2hvdyBnZW5lcyB3aXRoID4gMiBzbnBzCiAgZGF0YV9sb25nIDwtIHBsdCRkYXRhICU+JQogICAgbXV0YXRlKAogICAgICBHZW5lX3kgPSBmb3JjYXRzOjpmY3RfaW5vcmRlcihwdXJycjo6bWFwX2NocihzdHJpbmdyOjpzdHJfc3BsaXQoeSwgIiwgIiksIH4ueFtbMV1dKSksCiAgICAgIEdlbmVfeCA9IGZvcmNhdHM6OmZjdF9pbm9yZGVyKHB1cnJyOjptYXBfY2hyKHN0cmluZ3I6OnN0cl9zcGxpdCh4LCAiLCAiKSwgfi54W1sxXV0pKQogICAgKQogIGdlbmVfZnJlcSA8LSB0YWJsZShkYXRhX2xvbmckR2VuZV94KSAvIG1pbih0YWJsZShkYXRhX2xvbmckR2VuZV94KSkKICBpbnZpc2libGVfZ2VuZXMgPC0gbmFtZXMoZ2VuZV9mcmVxW2dlbmVfZnJlcSA8PSAyXSkKICBwbHRfYnJlYWtzIDwtIGRhdGFfbG9uZyAlPiUKICAgIGRwbHlyOjpncm91cF9ieShHZW5lX3gpICU+JQogICAgZHBseXI6Om11dGF0ZShvcmRlciA9IDE6ZHBseXI6Om4oKSAtIHJvdW5kKGRwbHlyOjpuKCkgLyAyKSwKICAgICAgICAgICAgICAgICAgR2VuZV94ID0gaWZlbHNlKEdlbmVfeCAlaW4lIGludmlzaWJsZV9nZW5lcywgIiIsIGFzLmNoYXJhY3RlcihHZW5lX3gpKSkgJT4lCiAgICBkcGx5cjo6ZmlsdGVyKG9yZGVyID09IDApICU+JQogICAgZHBseXI6OnVuZ3JvdXAoKQogIHBsdF9icmVha3MgPC0gZHBseXI6OmJpbmRfcm93cygKICAgIHBsdF9icmVha3MsCiAgICBkYXRhLmZyYW1lKEdlbmVfeCA9ICJUVE4sIHJzNjY3MzM2MjEiLCB4ID0gIlRUTiwgcnM2NjczMzYyMSIsIG9yZGVyID0gMSksCiAgICBkYXRhLmZyYW1lKEdlbmVfeCA9ICJUVE4sIHJzMzA0NTY5NiIsIHggPSAiVFROLCByczMwNDU2OTYiLCBvcmRlciA9IDEpLAogICAgZGF0YS5mcmFtZShHZW5lX3ggPSAiQ0NEQzE0MSwgcnM3NTkxMDkxIiwgeCA9ICJDQ0RDMTQxLCByczc1OTEwOTEiLCBvcmRlciA9IDEpCiAgKQogIHBsdCA8LSBwbHQgKwogICAgZ2dwbG90Mjo6c2NhbGVfeF9kaXNjcmV0ZSgKICAgICAgYnJlYWtzID0gcGx0X2JyZWFrcyR4LCBsYWJlbHMgPSBwbHRfYnJlYWtzJEdlbmVfeAogICAgKSArCiAgICBnZ3Bsb3QyOjpzY2FsZV95X2Rpc2NyZXRlKAogICAgICBicmVha3MgPSBwbHRfYnJlYWtzJHgsIGxhYmVscyA9IHBsdF9icmVha3MkR2VuZV94CiAgICApICsKICAgIGdncGxvdDI6OnRoZW1lKAogICAgICBheGlzLnRleHQueCA9IGdncGxvdDI6OmVsZW1lbnRfdGV4dChhbmdsZSA9IDkwLCBoanVzdCA9IDEsIHZqdXN0ID0gMC41LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb2xvciA9IGlmZWxzZShwbHRfYnJlYWtzJG9yZGVyLCAiY29ybmZsb3dlcmJsdWUiLCAiYmxhY2siKSksCiAgICAgIGF4aXMudGV4dC55ID0gZ2dwbG90Mjo6ZWxlbWVudF90ZXh0KGNvbG9yID0gaWZlbHNlKHBsdF9icmVha3Mkb3JkZXIsICJjb3JuZmxvd2VyYmx1ZSIsICJibGFjayIpKQogICAgKQogIHNhdmVSRFMoCiAgICBwbHQsCiAgICBmaWxlLnBhdGgoZmlnX3Jlc19kaXIsCiAgICAgICAgICAgICAgcGFzdGUwKHBoZW5vdHlwZSwgIl9nd2FzX3NucHNfY29yX2hlYXRtYXBfYnlfcG9zLnJkcyIpKQogICkKICBnZ3NhdmUocGx0LCBmaWxlbmFtZSA9IGZpbGUucGF0aChmaWdfcmVzX2RpciwgcGFzdGUwKHBoZW5vdHlwZSwgIl9nd2FzX3NucHNfY29yX2hlYXRtYXBfYnlfcG9zLnBuZyIpKSwKICAgICAgICAgd2lkdGggPSAxMiwgaGVpZ2h0ID0gMTApCiAgCn0gZWxzZSB7CiAgY2F0KHNwcmludGYocGhlbm90eXBlX2hlYWRlciwgc3ByaW50ZigiJXMgLSBDb3JyZWxhdGlvbiBCZXR3ZWVuIEdXQVMtZmlsdGVyZWQgU05WcyIsIHBoZW5vdHlwZV9uYW1lKSkpCiAgZGlzcGxheV9pbWFnZShmaWxlLnBhdGgoZmlnX3Jlc19kaXIsIHBhc3RlMChwaGVub3R5cGUsICJfZ3dhc19zbnBzX2Nvcl9oZWF0bWFwX2J5X3Bvcy5wbmciKSksCiAgICAgICAgICAgICAgICBjaHVua19pZHggPSBjaHVua19pZHgsCiAgICAgICAgICAgICAgICBjYXB0aW9uID0gIidDb3JyZWxhdGlvbiBoZWF0bWFwIGZvciB0aGUgR1dBUy1maWx0ZXJlZCBTTlZzLiBXZSBwbG90IHRoZSBtYWduaXR1ZGUgb2YgdGhlIFBlYXJzb24gY29ycmVsYXRpb24gYmV0d2VlbiBhbGwgcG9zc2libGUgcGFpcnMgb2YgU05WcyB0aGF0IHBhc3NlZCB0aGUgR1dBUyBmaWx0ZXIuIERhcmtlciByZWQgaW5kaWNhdGVzIGhpZ2hlciBjb3JyZWxhdGlvbiBiZXR3ZWVuIHRoZSB0d28gU05Wcy4gU05WcyBhbG9uZyB0aGUgYXhlcyBhcmUgb3JkZXJlZCBhY2NvcmRpbmcgdG8gZ2Vub21pYyBsb2NhdGlvbi4gTG9jaSB3aXRoIG1vcmUgdGhhbiB0d28gY29uc3RpdHVlbnQgU05WcyBhcmUgbGFiZWxlZC4nIikKICAKICBjYXQoc3ByaW50ZihwaGVub3R5cGVfaGVhZGVyLCBzcHJpbnRmKCIlcyAtIFRhYmxlIG9mIEdXQVMtZmlsdGVyZWQgU05WcyIsIHBoZW5vdHlwZV9uYW1lKSkpCiAgdGFiIDwtIHJlYWRSRFMoCiAgICBmaWxlLnBhdGgodGFiX3Jlc19kaXIsIAogICAgICAgICAgICAgIHBhc3RlMChwaGVub3R5cGUsICJfZ3dhc19zbnBzX2ZyZXF1ZW5jeV9ieV9nZW5lLnJkcyIpKQogICkgJT4lCiAgICBkcGx5cjo6c2VsZWN0KC1gU3RhcnQgUG9zLmAsIC1gRW5kIFBvcy5gKSAlPiUKICAgIGRwbHlyOjpyZW5hbWUoIkxvY3VzIiA9ICJHZW5lIiwgIiMgU05WcyIgPSAiIyBTTlBzIiwgIkZ1bmN0aW9uIiA9ICJHZW5lIEZ1bmN0aW9uIikgJT4lCiAgICBwcmV0dHlfRFQocm93bmFtZXMgPSBGQUxTRSkKICBzdWJjaHVua2lmeSh0YWIsIGkgPSBjaHVua19pZHgsIG90aGVyX2FyZ3MgPSAib3V0LndpZHRoPScxMDAlJyIsCiAgICAgICAgICAgICAgY2FwdGlvbiA9ICInTnVtYmVyIG9mIFNOVnMgcGVyIGdlbmV0aWMgbG9jdXMgdGhhdCBwYXNzZWQgdGhlIEdXQVMgZmlsdGVyLiBOb3RlOiBhIHNlbWljb2xvbiBpcyB1c2VkIHRvIGRlbm90ZSB0aGUgaW50ZXJnZW5pYyByZWdpb24gYmV0d2VlbiB0d28gZ2VuZXMuJyIpCiAgY2h1bmtfaWR4IDwtIGNodW5rX2lkeCArIDEKfQoKYGBgCgoKIyBCaW5hcml6YXRpb24gU3RlcCB7LnRhYnNldCAudGFic2V0LWZhZGUgLnRhYnNldC12bW9kZXJufQoKIyMgT3ZlcnZpZXcgey51bm51bWJlcmVkIC50YWJzZXQgLnRhYnNldC1waWxscyAudGFic2V0LWZhZGUgLnRhYnNldC1zcXVhcmV9Cgo8ZGl2IGNsYXNzPSJwYW5lbCBwYW5lbC1kZWZhdWx0IHBhZGRlZC1wYW5lbCI+CgpJbiB0aGUgbmV4dCBzdGVwIG9mIGxvLXNpUkYsIHdlIGNob3NlIHRvIGJpbmFyaXplIHRoZSAoY29udGludW91cykgTFZNaSBwaGVub3R5cGUgbWVhc3VyZW1lbnRzIGludG8gdHdvIGNhdGVnb3JpZXM6IGEgbG93IExWTWkgZ3JvdXAgYW5kIGEgaGlnaCBMVk1pIGdyb3VwIGJlZm9yZSBmaXR0aW5nIHRoZSBwcmVkaWN0aW9uIG1vZGVscy4KCioqV2h5IGRpZCB3ZSBjaG9vc2UgdG8gYmluYXJpemU/KiogT25lIG9mIG91ciBtYWluIG1vdGl2YXRpbmcgZmFjdG9ycyB0byBwdXJzdWUgYmluYXJpemF0aW9uIHJldm9sdmVkIGFyb3VuZCB0aGUgcHJlZGljdGlvbiBjaGVjayBjcml0ZXJpYSBpbiB0aGUgUENTIGZyYW1ld29yayBbQHl1MjAyMHZlcmlkaWNhbF0uIFRoaXMgcHJlZGljdGFiaWxpdHkgcHJpbmNpcGxlIGFkdm9jYXRlcyBmb3IgdGhlIHVzZSBvZiBwcmVkaWN0aW9uIGFjY3VyYWN5IGFzIGEgcmVhbGl0eSBjaGVjay4gVGhpcyBpcyB0byBzYXkgdGhhdCBhdCBhIG1pbmltdW0sIG1vZGVscyBzaG91bGQgZml0IHRoZSBkYXRhIHdlbGwsIGFzIG1lYXN1cmVkIGJ5IHByZWRpY3Rpb24gYWNjdXJhY3ksIGJlZm9yZSBiZWxpZXZpbmcgdGhhdCB0aGUgbW9kZWwgaXMgY2FwdHVyaW5nIHNvbWV0aGluZyByZWxldmFudCB0byByZWFsaXR5IG9yIHRoZSByZWFsLXdvcmxkIHBoZW5vbWVuYSB1bmRlciBzdHVkeS4gSW4gcGFydGljdWxhciwgYmVmb3JlIHdlIHRob3VnaHQgdG8gYmluYXJpemUgdGhlIHBoZW5vdHlwZSwgd2UgZmlyc3QgYXR0ZW1wdGVkIHRvIHRyYWluIHByZWRpY3Rpb24gbW9kZWxzIHVzaW5nIHRoZSBHV0FTLWZpbHRlcmVkIFNOVnMgdG8gcHJlZGljdCB0aGUgb3JpZ2luYWwgKGNvbnRpbnVvdXMpIExWTWkgcGhlbm90eXBlIG1lYXN1cmVtZW50cy4gV2hpbGUgdGhpcyBzZWVtZWQgbGlrZSB0aGUgbW9zdCBuYXR1cmFsIG5leHQgc3RlcCwgdGhlc2UgcHJlZGljdGlvbiByZXN1bHRzIGlsbHVtaW5hdGVkIGFuIGluY3JlZGlibHkgd2VhayBwcmVkaWN0aW9uIHNpZ25hbCwgd2l0aCB2YWxpZGF0aW9uICRSXjIkIHZhbHVlcyBob3ZlcmluZyB2ZXJ5IGNsb3NlIHRvIDAgKHNlZSBgUHJlZGljdGlvbiBSZXN1bHRzIHdpdGhvdXQgQmluYXJpemF0aW9uYCB0YWIpLiBHaXZlbiB0aGF0IGFuICRSXjIkIHZhbHVlIG9mIDAgY2FuIGJlIGFjaGlldmVkIGJ5IHNpbXBseSBwcmVkaWN0aW5nIHRoZSBtZWFuIExWTWkgcmVzcG9uc2UsIHRoaXMgcmFpc2VkIHRoZSBxdWVzdGlvbiBvZiB3aGV0aGVyIHRoZXNlIHByZWRpY3Rpb24gbW9kZWxzIGFyZSBjYXB0dXJpbmcgYW55IHJlbGV2YW50IHNpZ25hbCBpbiB0aGUgZGF0YS4gQ29uc2VxdWVudGx5LCB0aGUgaW50ZXJwcmV0YXRpb24gb2YgdGhlc2UgbW9kZWxzIG1heSBub3QgYmUgYW4gYWNjdXJhdGUgcmVwcmVzZW50YXRpb24gb2YgcmVhbGl0eS4gUHV0IGRpZmZlcmVudGx5LCB0aGVzZSBtb2RlbHMgZG8gbm90IHNhdGlzZnkgdGhlIHByZWRpY3Rpb24gY2hlY2sgY3JpdGVyaWEgdW5kZXIgdGhlIFBDUyBmcmFtZXdvcmsuCgpHaXZlbiB0aGVzZSBkaWZmaWN1bHRpZXMgaW4gYWNjdXJhdGVseSBwcmVkaWN0aW5nIExWTWksIHdlIHR1cm5lZCB0byBhbiBhbHRlcm5hdGl2ZSBzY2hvb2wgb2YgdGhvdWdodCBpbiBvcmRlciB0byBleHRyYWN0IHJlbGlhYmxlIGluc2lnaHRzIGZyb20gc3VjaCBsb3ctc2lnbmFsIGRhdGEuIERyYXdpbmcgaW5zcGlyYXRpb24gZnJvbSBob3cgc2NpZW50aXN0cyBvZnRlbiByZWR1Y2UgY29tcGxleCBwcm9ibGVtcyBpbnRvIHNpbXBsaWZpZWQgdmVyc2lvbnMsIHdlIGNhbiBzaW1wbGlmeSB0aGUgcHJvYmxlbSBvZiB0cnlpbmcgdG8gdW5kZXJzdGFuZCBob3cgU05WcyBhcmUgYXNzb2NpYXRlZCB3aXRoIGV2ZXJ5b25lJ3MgcHJlY2lzZSBMVk1pIG1lYXN1cmVtZW50cyB0byBhc2tpbmcgd2hpY2ggU05WcyBhcmUgYXNzb2NpYXRlZCB3aXRoIGhhdmluZyBleHRyZW1lbHkgaGlnaCBvciBleHRyZW1lbHkgbG93IExWTWkgbWVhc3VyZW1lbnRzLiBJbiBvdGhlciB3b3Jkcywgd2UgY2FuIHJlZHVjZSB0aGUgcHJvYmxlbSBvZiBwcmVkaWN0aW5nIChjb250aW51b3VzKSBMVk1pIHJlc3BvbnNlcyB0byBwcmVkaWN0aW5nIHdoZXRoZXIgb25lIGhhcyBhbiBleHRyZW1lbHkgaGlnaCBMVk1pIG9yIGxvdyBMVk1pLiBUaGlzIGJpbmFyaXphdGlvbiBub3Qgb25seSBzaW1wbGlmaWVzIHRoZSBwcm9ibGVtIGNvbmNlcHR1YWxseSwgYnV0IG1heSBhbHNvIGhlbHAgdG8gZGVub2lzZSBzaW5jZSB3ZSBhcmUgb25seSBsb29raW5nIGF0IHRoZSBtb3JlIGV4dHJlbWUgTFZNaSBjYXNlcyB0byBnYWluIHVuZGVyc3RhbmRpbmcuIEZ1cnRoZXJtb3JlLCB0aGUgb3JpZ2luYWwgcmVncmVzc2lvbiBwcm9ibGVtIGJlY29tZXMgYSBjbGFzc2lmaWNhdGlvbiBwcm9ibGVtIGFmdGVyIGJpbmFyaXphdGlvbiwgd2hpY2ggY2FuIGhlbHAgdG8gZmFjaWxpdGF0ZSB0aGUgaW50ZXJwcmV0YXRpb24gb2YgcHJlZGljdGlvbiBwZXJmb3JtYW5jZSB3aXRoIHJlc3BlY3QgdG8gdGhlIHByZWRpY3Rpb24gY2hlY2sgKGUuZy4sIGl0IGlzIGFyZ3VhYmx5IGVhc2llciB0byByZWFzb24gYWJvdXQgdGhlIHByYWN0aWNhbCBkaWZmZXJlbmNlIGJldHdlZW4gNTUlIGFuZCA1MCUgYmFsYW5jZWQgY2xhc3NpZmljYXRpb24gYWNjdXJhY3kgdGhhbiAkUl4yJCB2YWx1ZXMgb2YgMC4wNSBhbmQgMCkuCgoqKkhvdyBpcyB0aGUgYmluYXJpemF0aW9uIGRvbmU/KiogSW4gb3JkZXIgdG8gYmluYXJpemUgdGhlIExWTWkgcmVzcG9uc2VzLCBvbmUgbXVzdCBjaG9vc2Ugc29tZSB0aHJlc2hvbGQuIFdlIGNob3NlIHRvIGJpbmFyaXplIHRoZSByZXNwb25zZSBiYXNlZCBvbiBxdWFudGlsZXMgc28gdGhhdCBmb3IgYSBnaXZlbiB0aHJlc2hvbGQgKngqLCB3ZSB0b29rIHRoZSB0b3AgYW5kIGJvdHRvbSAqeCpcJSBvZiBMVk1pIHZhbHVlcyBhbmQgcG9vbGVkIHRoZW0gaW50byB0aGUgaGlnaCBhbmQgbG93IExWTWkgZ3JvdXBzLCByZXNwZWN0aXZlbHksIHdoaWxlIG9taXR0aW5nIHRoZSBpbmRpdmlkdWFscyBpbiB0aGUgbWlkZGxlIHF1YW50aWxlIHJhbmdlLiBIb3dldmVyLCBkdWUgdG8gdGhlIGdlbmRlci1zcGVjaWZpYyBiaW9sb2dpY2FsIHZhcmlhdGlvbiBvZiBMVk1pIHNob3duIGVhcmxpZXIgaW4gdGhlIGV4cGxvcmF0b3J5IGRhdGEgYW5hbHlzaXMgKHNlZSBgQ2hvaWNlIG9mIFBoZW5vdHlwaWMgRGF0YWApLCB3ZSBwZXJmb3JtZWQgdGhlIGJpbmFyaXphdGlvbiBmb3IgbWFsZXMgYW5kIGZlbWFsZXMgc2VwYXJhdGVseS4gRmluYWxseSwgZ2l2ZW4gdGhhdCB0aGlzIHRocmVzaG9sZCBpcyBhcnRpZmljaWFsbHkgaW50cm9kdWNlZCwgd2UgcnVuIHRoZSByZW1haW5kZXIgb2YgdGhlIGxvLXNpUkYgcGlwZWxpbmUgdXNpbmcgdGhyZWUgZGlmZmVyZW50IHJlYXNvbmFibGUgYmluYXJpemF0aW9uIHRocmVzaG9sZHMgKDE1XCUsIDIwXCUsIDI1XCUpIHRoYXQgYmFsYW5jZSB0aGUgYW1vdW50IG9mIGRlbm9pc2luZyBhbmQgZGF0YSBsb3N0LiBJbiB0aGUgZW5kLCB3ZSB3aWxsIGNvbnNvbGlkYXRlIHRoZSByZXN1bHRzIHRoYXQgd2VyZSBzdGFibGUgYWNyb3NzIGFsbCB0aHJlZSBiaW5hcml6YXRpb24gdGhyZXNob2xkcywgZGVzY3JpYmVkIGxhdGVyLgoKV2UgZXhwYW5kIG9uIHRoZSBwcmVkaWN0aW9uIG1vZGVsaW5nIHdpdGggdGhlIGJpbmFyaXplZCBMVk1pIHBoZW5vdHlwZSBpbiB0aGUgbmV4dCBzZWN0aW9uIChzZWUgYFByZWRpY3Rpb24gU3RlcGApLgoKPC9kaXY+CgoKIyMgUHJlZGljdGlvbiBSZXN1bHRzIHdpdGhvdXQgQmluYXJpemF0aW9uIHsudW5udW1iZXJlZCAudGFic2V0IC50YWJzZXQtcGlsbHMgLnRhYnNldC1mYWRlIC50YWJzZXQtc3F1YXJlfQoKPGRpdiBjbGFzcz0icGFuZWwgcGFuZWwtZGVmYXVsdCBwYWRkZWQtcGFuZWwiPgoKSGVyZSwgd2UgcHJlc2VudCBhIHN1bW1hcnkgb2YgdGhlIHByZWRpY3Rpb24gbW9kZWxpbmcgcmVzdWx0cywgd2hlcmUgd2UgdXNlIHRoZSBHV0FTLWZpbHRlcmVkIFNOVnMgdG8gcHJlZGljdCB0aGUgcmF3IExWTWkgcGhlbm90eXBlIG1lYXN1cmVtZW50cyAoaS5lLiwgd2l0aG91dCBhbnkgYmluYXJpemF0aW9uKS4gU3BlY2lmaWNhbGx5LCB3ZSBtZWFzdXJlIHRoZSB2YWxpZGF0aW9uIHNldCBwcmVkaWN0aW9uIGFjY3VyYWN5IGZyb20gc2V2ZXJhbCBwb3B1bGFyIG1hY2hpbmUgbGVhcm5pbmcgcmVncmVzc2lvbiBhbGdvcml0aG1zIChrZXJuZWwgcmlkZ2UgcmVncmVzc2lvbiwgTGFzc28gcmVncmVzc2lvbiwgcmlkZ2UgcmVncmVzc2lvbiwgcmFuZG9tIGZvcmVzdCAoUkYpLCBhbmQgc2lnbmVkIGl0ZXJhdGl2ZSByYW5kb20gZm9yZXN0IChzaVJGKSkgYWNyb3NzIGZvdXIgZGlmZmVyZW50IHByZWRpY3Rpb24gcGVyZm9ybWFuY2UgbWV0cmljcyAtIHRoZSBQZWFyc29uIGNvcnJlbGF0aW9uLCBtZWFuIGFic29sdXRlIGVycm9yIChNQUUpLCBSLXNxdWFyZWQsIGFuZCByb290LW1lYW4tc3F1YXJlZCBlcnJvciAoUk1TRSkgYmV0d2VlbiB0aGUgb2JzZXJ2ZWQgTFZNaSByZXNwb25zZSBhbmQgdGhlIHByZWRpY3RlZCBMVk1pIHJlc3BvbnNlLiBXZSBhbHNvIHZpc3VhbGl6ZSBob3cgdGhlIHByZWRpY3RlZCByZXNwb25zZXMgZGlmZmVyIGFjcm9zcyB0aGUgZGlmZmVyZW50IHByZWRpY3Rpb24gbW9kZWxzIGluIHRoZSBwcm92aWRlZCBwYWlyIHBsb3RzLiBUaG91Z2ggUkYgYXBwZWFycyB0byB5aWVsZCB0aGUgYmVzdCBwcmVkaWN0aW9uIHBlcmZvcm1hbmNlIHJlbGF0aXZlIHRvIHRoZSBvdGhlciBtZXRob2RzIHVuZGVyIGNvbnNpZGVyYXRpb24sIHRoZSBSRiBwcmVkaWN0aW9uIHBlcmZvcm1hbmNlIGlzIHN0aWxsIHZlcnkgcG9vciBhcyBib3RoIHRoZSBjb3JyZWxhdGlvbiBhbmQgUi1zcXVhcmVkIG1ldHJpY3MgYXJlIHZlcnkgY2xvc2UgdG8gMC4gCgo8L2Rpdj4KCmBgYHtyIHByZWQtcmVzdWx0cy1jdHMsIHJlc3VsdHMgPSAiYXNpcyJ9CgojIHBoZW5vdHlwZV9oZWFkZXIgPC0gIlxuXG4jIyMgJXMgey51bm51bWJlcmVkIC50YWJzZXQgLnRhYnNldC1waWxscyAudGFic2V0LWZhZGUgLnRhYnNldC1jaXJjbGV9IFxuXG4iCnNlY3Rpb25faGVhZGVyIDwtICJcblxuIyMjICVzIHsudW5udW1iZXJlZCAudGFic2V0IC50YWJzZXQtcGlsbHMgLnRhYnNldC1mYWRlIC50YWJzZXQtY2lyY2xlfSBcblxuIgpzdWJzZWN0aW9uX2hlYWRlciA8LSAiXG5cbiMjIyMjICVzIHsudW5udW1iZXJlZH0gXG5cbiIKCm1ldGhvZHMgPC0gYygiTGFzc28iID0gImxhc3NvIiwgIlJpZGdlIiA9ICJyaWRnZSIsICJSRiIgPSAicmYiLCAic2lSRiIgPSAiaXJmIiwgIktlcm5lbCBSaWRnZSIgPSAia2VybmVsX3JpZGdlIikKCmlmIChwYXJhbXMkZXZhbCkgewogIGZvciAocGhlbm90eXBlIGluIHBoZW5vdHlwZXMpIHsKICAgIGZwYXRoIDwtIGZpbGUucGF0aChyZXNfZGlyLCBwYXN0ZTAocGhlbm90eXBlLCAiX2d3YXNfZmlsdGVyZWRfbnNucHMxMDAwIikpCgogICAgIyByZWFkIGluIHByZWRpY3Rpb24gcmVzdWx0cyB3aXRoIGRlbW9ncmFwaGljcwogICAgbG9hZChmaWxlLnBhdGgoZnBhdGgsICJ2YWxpZGF0aW9uX3BoZW5vLlJkYXRhIikpICAjID4gcGhlbm8KICAgIHByZWRzX2RhdGEgPC0gbGlzdCgKICAgICAgeWhhdCA9IGMoCiAgICAgICAgcmVhZFJEUyhmaWxlLnBhdGgoZnBhdGgsICJ5cHJlZC5yZHMiKSksCiAgICAgICAgZnJlYWQoZmlsZS5wYXRoKGZwYXRoLCAieXByZWQuY3N2IikpCiAgICAgICksCiAgICAgIHkgPSBwaGVubywKICAgICAgZ2VuZGVyID0gaWZlbHNlKGxvYWREZW1vZ3JhcGhpY3MobmFtZXMocGhlbm8pKVssICJnZW5kZXIiXSA9PSAxLAogICAgICAgICAgICAgICAgICAgICAgIk1hbGUiLCAiRmVtYWxlIikgJT4lCiAgICAgICAgYXMuZmFjdG9yKCkKICAgICkKICAgIAogICAgcHJlZHNfZGF0YSR5aGF0IDwtIHByZWRzX2RhdGEkeWhhdFttZXRob2RzXQogICAgbmFtZXMocHJlZHNfZGF0YSR5aGF0KSA8LSBuYW1lcyhtZXRob2RzKQoKICAgICMgcHJlZGljdGlvbiBhY2N1cmFjeSB0YWJsZQogICAgbWV0cmljcyA8LSBjKCJSTVNFIiwgIlIyIiwgIk1BRSIsICJDb3JyZWxhdGlvbiIpCiAgICBldmFsX291dCA8LSBtYXBfZGZyKHByZWRzX2RhdGEkeWhhdCwKICAgICAgICAgICAgICAgICAgICAgICAgfmV2YWxQcmVkcyh5ID0gcHJlZHNfZGF0YSR5LCB5aGF0ID0gYygueCksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWV0cmljID0gbWV0cmljcyksCiAgICAgICAgICAgICAgICAgICAgICAgIC5pZCA9ICJNZXRob2QiKSAlPiUKICAgICAgc3ByZWFkKGtleSA9ICJNZXRyaWMiLCB2YWx1ZSA9ICJWYWx1ZSIpICU+JQogICAgICBkcGx5cjo6bXV0YXRlKAogICAgICAgIGRwbHlyOjphY3Jvc3MoCiAgICAgICAgICBjKENvcnJlbGF0aW9uLCBSMiksCiAgICAgICAgICB+aWZlbHNlKC54ID09IG1heCgueCksIAogICAgICAgICAgICAgICAgICBrYWJsZUV4dHJhOjpjZWxsX3NwZWMoZm9ybWF0QygueCwgZGlnaXRzID0gMywgZm9ybWF0ID0gImciLCBmbGFnID0gIiMiKSwgYm9sZCA9IFRSVUUpLCAKICAgICAgICAgICAgICAgICAgZm9ybWF0QygueCwgZGlnaXRzID0gMywgZm9ybWF0ID0gImciLCBmbGFnID0gIiMiKSkKICAgICAgICApLAogICAgICAgIGRwbHlyOjphY3Jvc3MoCiAgICAgICAgICBjKE1BRSwgUk1TRSksCiAgICAgICAgICB+aWZlbHNlKC54ID09IG1pbigueCksIAogICAgICAgICAgICAgICAgICBrYWJsZUV4dHJhOjpjZWxsX3NwZWMoZm9ybWF0QygueCwgZGlnaXRzID0gNCwgZm9ybWF0ID0gImciLCBmbGFnID0gIiMiKSwgYm9sZCA9IFRSVUUpLCAKICAgICAgICAgICAgICAgICAgZm9ybWF0QygueCwgZGlnaXRzID0gNCwgZm9ybWF0ID0gImciLCBmbGFnID0gIiMiKSkKICAgICAgICApCiAgICAgICkKICAgIHRhYiA8LSBwcmV0dHlfRFQoZXZhbF9vdXQsIGRpZ2l0cyA9IDQsIHNpZ2ZpZyA9IFRSVUUsIHJvd25hbWVzID0gRkFMU0UsCiAgICAgICAgICAgICAgICAgICAgIG5hX2Rpc3AgPSAiLS0iLCAKICAgICAgICAgICAgICAgICAgICAgb3B0aW9ucyA9IGxpc3QocGFnZUxlbmd0aCA9IG5yb3coZXZhbF9vdXQpLCBkb20gPSAidCIpKQogICAgc2F2ZVJEUyh0YWIsCiAgICAgICAgICAgIGZpbGUucGF0aCh0YWJfcmVzX2RpciwgcGFzdGUwKHBoZW5vdHlwZSwgIl9wcmVkX2FjY3VyYWN5LnJkcyIpKSkKCiAgICAjIHByZWRpY3Rpb24gcGFpciBwbG90cwogICAgcGx0X2RmIDwtIG1hcF9kZmMocHJlZHNfZGF0YSR5aGF0LCB+YygueCkpCiAgICBwbHQgPC0gcGxvdF9wYWlycyhkYXRhID0gcGx0X2RmLCBjb2x1bW5zID0gMTpuY29sKHBsdF9kZiksCiAgICAgICAgICAgICAgICAgICAgICBjb2xvciA9IHByZWRzX2RhdGEkZ2VuZGVyKQogICAgc2F2ZVJEUyhwbHQsCiAgICAgICAgICAgIGZpbGUucGF0aChmaWdfcmVzX2RpciwgcGFzdGUwKHBoZW5vdHlwZSwgIl9wcmVkX3BhaXJfcGxvdC5yZHMiKSkpCiAgfQp9IGVsc2UgewogIGZvciAocGhlbm90eXBlIGluIHBoZW5vdHlwZXMpIHsKICAgIHBoZW5vdHlwZV9uYW1lIDwtIG5hbWVzKHBoZW5vdHlwZXMpW3BoZW5vdHlwZXMgPT0gcGhlbm90eXBlXQogICAgIyBjYXQoc3ByaW50ZihwaGVub3R5cGVfaGVhZGVyLCBwaGVub3R5cGVfbmFtZSkpCiAgICAKICAgICMgcHJlZGljdGlvbiBhY2N1cmFjeSB0YWJsZQogICAgY2F0KHNwcmludGYoc2VjdGlvbl9oZWFkZXIsICJQcmVkaWN0aW9uIEFjY3VyYWNpZXMiKSkKICAgIHRhYiA8LSByZWFkUkRTKAogICAgICBmaWxlLnBhdGgodGFiX3Jlc19kaXIsIHBhc3RlMChwaGVub3R5cGUsICJfcHJlZF9hY2N1cmFjeS5yZHMiKSkKICAgICkKICAgIHN1YmNodW5raWZ5KHRhYiwgaSA9IGNodW5rX2lkeCwKICAgICAgICAgICAgICAgIGNhcHRpb24gPSBzcHJpbnRmKCInU3VtbWFyeSBvZiBwcmVkaWN0aW9uIHBlcmZvcm1hbmNlIG9uIHRoZSB2YWxpZGF0aW9uIHNldCBmb3IgdGhlICVzIHBoZW5vdHlwZSAod2l0aG91dCBiaW5hcml6YXRpb24pIGFjcm9zcyB2YXJpb3VzIHByZWRpY3Rpb24gbWV0aG9kcyBhbmQgZXZhbHVhdGlvbiBtZXRyaWNzLiciLCBwaGVub3R5cGVfbmFtZSkpCiAgICBjaHVua19pZHggPC0gY2h1bmtfaWR4ICsgMQogIAogICAgIyBwcmVkaWN0aW9uIHBhaXIgcGxvdHMKICAgIGNhdChzcHJpbnRmKHNlY3Rpb25faGVhZGVyLCAiUHJlZGljdGlvbiBQYWlyIFBsb3QiKSkKICAgIHBsdCA8LSByZWFkUkRTKAogICAgICBmaWxlLnBhdGgoZmlnX3Jlc19kaXIsCiAgICAgICAgICAgICAgICBwYXN0ZTAocGhlbm90eXBlLCAiX3ByZWRfcGFpcl9wbG90LnJkcyIpKQogICAgKQogICAgc3ViY2h1bmtpZnkocGx0LCBpID0gY2h1bmtfaWR4LCBmaWdfaGVpZ2h0ID0gcGx0JG5jb2wgKiAxLjUsCiAgICAgICAgICAgICAgICBhZGRfY2xhc3MgPSBjKCJwYW5lbCBwYW5lbC1kZWZhdWx0IiksCiAgICAgICAgICAgICAgICBvdGhlcl9hcmdzID0gIm91dC53aWR0aD0nMTAwJSciLAogICAgICAgICAgICAgICAgY2FwdGlvbiA9IHNwcmludGYoIidQYWlyIHBsb3Qgb2YgdGhlIHByZWRpY3RlZCAlcyByZXNwb25zZXMgZnJvbSB2YXJpb3VzIHByZWRpY3Rpb24gbW9kZWxzLiBFYWNoIHBvaW50IHJlcHJlc2VudHMgYW4gaW5kaXZpZHVhbCBpbiB0aGUgdmFsaWRhdGlvbiBzZXQsIGFuZCB0aGUgY29vcmRpbmF0ZXMgcmVwcmVzZW50IHRoZSBwcmVkaWN0ZWQgJXMgcmVzcG9uc2UgZnJvbSB0d28gZGlmZmVyZW50IHByZWRpY3Rpb24gbWV0aG9kcywgd2hpY2ggYXJlIHNwZWNpZmllZCBieSB0aGUgeCBhbmQgeS1heGVzIGxhYmVscyBpbiBlYWNoIHN1YnBsb3QuIERlbnNpdHkgZGlzdHJpYnV0aW9ucyBvZiB0aGUgcHJlZGljdGVkICVzIHJlc3BvbnNlcyBhcmUgc2hvd24gYWxvbmcgdGhlIGRpYWdvbmFsLiciLCBwaGVub3R5cGVfbmFtZSwgcGhlbm90eXBlX25hbWUsIHBoZW5vdHlwZV9uYW1lKSkKICAgIGNodW5rX2lkeCA8LSBjaHVua19pZHggKyAxCiAgfQp9CgpgYGAKCiMgUHJlZGljdGlvbiBTdGVwIHsudGFic2V0IC50YWJzZXQtZmFkZSAudGFic2V0LXZtb2Rlcm59Cgo8ZGl2IGNsYXNzPSJwYW5lbCBwYW5lbC1kZWZhdWx0IHBhZGRlZC1wYW5lbCI+CgpBZnRlciBjaG9vc2luZyB0byBiaW5hcml6ZSB0aGUgTFZNaSBwaGVub3R5cGUsIHdlIG5leHQgZml0IHZhcmlvdXMgcHJlZGljdGlvbiBtb2RlbHMgdXNpbmcgdGhlIEdXQVMtZmlsdGVyZWQgU05WcyB0byBwcmVkaWN0IHRoZSBiaW5hcml6ZWQgTFZNaSBwaGVub3R5cGUgYW5kIGFzc2VzcyB0aGVpciB2YWxpZGF0aW9uIHByZWRpY3Rpb24gYWNjdXJhY3kuIAoKKipXaGljaCBtb2RlbHMgd2VyZSBjaG9zZW4gYW5kIHdoeT8qKiBXaGlsZSB0aGVyZSBhcmUgbWFueSBtZXRob2RzLCBlYWNoIHdpdGggdGhlaXIgdW5pcXVlIGFkdmFudGFnZXMgYW5kIGRpc2FkdmFudGFnZXMsIGZvciBkZXRlY3RpbmcgZXBpc3Rhc2lzIGZyb20gZGF0YSBbZS5nLiwgc2VlIEBuaWVsMjAxNXN1cnZleSBhbmQgcmVmZXJlbmNlcyB0aGVyZWluXSwgd2UgY2hvc2UgdG8gZm9jdXMgb24gc2lSRiBbQGt1bWJpZXIyMDE4cmVmaW5pbmddIGFzIG91ciBwcmltYXJ5IGludGVyYWN0aW9uIHNlYXJjaCBlbmdpbmUgZm9yIHZhcmlvdXMgcmVhc29ucy4gCgoxLiBVbmxpa2UgbWFueSBtZXRob2RzIHRoYXQgbWFrZSBsaW5lYXIgYXNzdW1wdGlvbnMgb3IgcmVxdWlyZSBwcmUtc3BlY2lmaWNhdGlvbiBvZiBpbnRlcmFjdGlvbiBvcmRlciAoaS5lLiwgdGhlIG51bWJlciBvZiBmZWF0dXJlcyBpbnZvbHZlZCBpbiBhbiBpbnRlcmFjdGlvbiksIHNpUkYgY2FuIGlkZW50aWZ5ICpoaWdoZXItb3JkZXIqLCAqbm9ubGluZWFyKiBCb29sZWFuIGludGVyYWN0aW9ucyBpbiBhIGNvbXB1dGF0aW9uYWxseS10cmFjdGFibGUgbWFubmVyIHdpdGhvdXQgdGhlIG5lZWQgdG8gc3BlY2lmeSB0aGUgaW50ZXJhY3Rpb24gb3JkZXIgb2YgaW50ZXJlc3QuIAoyLiBBbm90aGVyIGFkdmFudGFnZSBvZiBzaVJGIGZvciBkZXRlY3RpbmcgaW50ZXJhY3Rpb25zIGlzIHRoZSByZXNlbWJsYW5jZSBiZXR3ZWVuIHRoZSBsb2NhbGl6ZWQgdGhyZXNob2xkaW5nIGJlaGF2aW9yIG9mIGl0cyBkZWNpc2lvbiB0cmVlcyBhbmQgdGhlIHRocmVzaG9sZCAob3Igb24tb2ZmIHN3aXRjaC1saWtlKSBiZWhhdmlvciBmcmVxdWVudGx5IG9ic2VydmVkIGluIGJpb21vbGVjdWxhciBpbnRlcmFjdGlvbnMgW0BuZWxzb24yMDA4bGVobmluZ2VyXS4gSW4gb3RoZXIgd29yZHMsIHRoZSBmb3JtIG9mIHRoZSBzaVJGIG1vZGVsIGFwcGVhcnMgdG8gYmUgd2VsbC1zdWl0ZWQgZm9yIHRoZSBiaW9sb2dpY2FsIHBoZW5vbWVuYSB1bmRlciBzdHVkeS4KMy4gRnVydGhlcm1vcmUsIHRoZSBwcmVkaWN0aW9uIGFjY3VyYWN5IG9mIHRoZSBzaVJGIG1vZGVsIGZpdCBjYW4gYmUgZWFzaWx5IGFzc2Vzc2VkLiBBcyBkaXNjdXNzZWQgcHJldmlvdXNseSwgcHJlZGljdGlvbiBhY2N1cmFjeSBjYW4gc2VydmUgYXMgYW4gaW5kaWNhdG9yIG9mIHdoZXRoZXIgb3Igbm90IHRoZSBtb2RlbCBpcyBhbiBhY2N1cmF0ZSByZXByZXNlbnRhdGlvbiBvZiByZWFsaXR5LiBUaGlzIHByZWRpY3Rpb24gY2hlY2sgaXMgYSBuZWNlc3NhcnkgcHJlLXJlcXVpc2l0ZSBmb3IgaW50ZXJwcmV0aW5nIHRoZSBwcmVkaWN0aW9uIG1vZGVsIGFuZCBpcyBlc3BlY2lhbGx5IGltcG9ydGFudCBpbiBsb3ctc2lnbmFsIHJlZ2ltZXMgc3VjaCBhcyB0aGlzIHN0dWR5Lgo0LiBzaVJGIGFuZCBpdHMgcHJlZGVjZXNzb3IgaVJGIGhhdmUgZGVtb25zdHJhdGVkIGdyZWF0IHN1Y2Nlc3MgaW4gZGV0ZWN0aW5nIHJlbGlhYmxlIGludGVyYWN0aW9ucyBpbiBwcmV2aW91cyByZWFsLXdvcmxkIHN0dWRpZXMsIHN1Y2ggYXMgaW4gZXBpc3Rhc2lzLWNvbnRyb2xsZWQgaGFpciBjb2xvciBbQGJlaHIyMDIwbGVhcm5pbmddLCBvYmVzaXR5IFtAYWxsZW4yMDIydXNpbmddLCBzY2hpem9waHJlbmlhIFtAZGUyMDIybWFjaGluZV0sIGFuZCBwcmVkaWN0aXZlIGdlbmUgZXhwcmVzc2lvbiBuZXR3b3JrcyBbQGNsaWZmMjAxOWhpZ2g7IEB3YWxrZXIyMDIyZXZhbHVhdGluZ10uCjUuIEZpbmFsbHksIGR1ZSB0byB0aGUgd2VhayBwaGVub3R5cGljIHNpZ25hbCBhbmQgdGhlIHN0cm9uZyBjb3JyZWxhdGlvbnMgYmV0d2VlbiBuZWlnaGJvcmluZyBTTlZzIGR1ZSB0byBsaW5rYWdlIGRpc2VxdWlsaWJyaXVtIChzZWUgRmlndXJlIFxAcmVmKGZpZzpzdWJjaHVuay0yNSkpLCB3ZSBiZWxpZXZlZCBpdCB3YXMgbW9zdCBhcHByb3ByaWF0ZSB0byByZWNvbW1lbmQgaW50ZXJhY3Rpb25zIGJldHdlZW4gZ2VuZXRpYyBsb2NpLCByYXRoZXIgdGhhbiBpbnRlcmFjdGlvbnMgYmV0d2VlZW4gaW5kaXZpZHVhbCBTTlZzLiBXaGlsZSBpdCBpcyBub3QgYWx3YXlzIGNsZWFyIGhvdyB0byBwZXJmb3JtIHRoaXMgbG9jdXMtbGV2ZWwgaW50ZXJhY3Rpb24gc2VhcmNoIHdoZW4gdGhlIGRhdGEgaXMgZ2l2ZW4gYXQgdGhlIFNOVi1sZXZlbCwgd2UgY2FuIGJ1aWxkIHVwb24gdGhlIHNpUkYgc3RydWN0dXJlIHRvIGFnZ3JlZ2F0ZSBmZWF0dXJlIGltcG9ydGFuY2VzIGFjcm9zcyBtdWx0aXBsZSBTTlZzIHVzaW5nIG91ciBuZXcgbG9jdXMtbGV2ZWwgaW1wb3J0YW5jZSBzY29yZSwgZGVzY3JpYmVkIGluIFtAd2FuZzIwMjNlcGlzdGFzaXNdKCkuCgpUaG91Z2ggd2UgYXJlIG1vc3QgaW50ZXJlc3RlZCBpbiBpbnRlcnByZXRpbmcgdGhlIHNpUkYgcHJlZGljdGlvbiBtb2RlbCB0byBpZGVudGlmeSBjYW5kaWRhdGUgZXBpc3RhdGljIGludGVyYWN0aW9ucywgd2UgYWxzbyBmaXQgc2V2ZXJhbCBvdGhlciBwb3B1bGFyIHByZWRpY3Rpb24gbW9kZWxzLCBpbmNsdWRpbmcgUkYsIEwxLXJlZ3VsYXJpemVkIGxvZ2lzdGljIHJlZ3Jlc3Npb24gKExhc3NvKSwgTDItcmVndWxhcml6ZWQgbG9naXN0aWMgcmVncmVzc2lvbiAocmlkZ2UpLCBhbmQgc3VwcG9ydCB2ZWN0b3IgbWFjaGluZXMgKFNWTSkuIFRoZXNlIHByZWRpY3Rpb24gbW9kZWxzIHNlcnZlIGFzIGJhc2VsaW5lcyB0byBlbnN1cmUgdGhhdCBzaVJGIGluZGVlZCBmaXRzIHRoZSBkYXRhIHdlbGwsIHJlbGF0aXZlIHRvIHRoZXNlIG90aGVyIHBvcHVsYXIgcHJlZGljdGlvbiBtb2RlbHMsIGFuZCB0aGF0IHNpUkYgcGFzc2VzIHRoZSBwcmVkaWN0aW9uIGNoZWNrIGluIGFjY29yZGFuY2Ugd2l0aCB0aGUgUENTIGZyYW1ld29yayBbQHl1MjAyMHZlcmlkaWNhbF0uCgoqKlN1bW1hcnkgb2YgcHJlZGljdGlvbiByZXN1bHRzOioqIEZvciBhbGwgb2YgdGhlIGNsYXNzaWZpY2F0aW9uIGFsZ29yaXRobXMgdW5kZXIgaW52ZXN0aWdhdGlvbiwgd2Ugc2VlIHRoYXQgdGhlIHZhbGlkYXRpb24gcHJlZGljdGlvbiBhY2N1cmFjeSBtZXRyaWNzLCBtZWFzdXJlZCB2aWEgY2xhc3NpZmljYXRpb24gYWNjdXJhY3ksIGFyZWEgdW5kZXIgdGhlIFJPQyBjdXJ2ZSAoQVVST0MpLCBhbmQgYXJlYSB1bmRlciB0aGUgcHJlY2lzaW9uLXJlY2FsbCBjdXJ2ZSAoQVVQUkMpLCBhcmUgYWxsIGNvbWZvcnRhYmx5IGFib3ZlIHRoZSByYW5kb20tZ3Vlc3NpbmcgYmFzZWxpbmUgb2YgMC41IGFjcm9zcyB0aHJlZSBkaWZmZXJlbnQgYmluYXJpemF0aW9uIHRocmVzaG9sZHMuIFRoaXMgc3VnZ2VzdHMgdGhhdCB0aGUgcHJlZGljdGlvbiBtb2RlbHMgYXJlIGFibGUgdG8gYXNjZXJ0YWluIHNvbWUgcGhlbm90eXBpYyBzaWduYWwgZnJvbSB0aGUgU05WcyB1bmRlciBzdHVkeS4gVGhhdCBpcywgdGhlIFNOVnMgdXNlZCBpbiB0aGUgcHJlZGljdGlvbiBtb2RlbHMgaGF2ZSBzb21lIHByZWRpY3RpdmUgcG93ZXIgaW4gZGlmZmVyZW50aWF0aW5nIHRob3NlIHdpdGggaGlnaCBMVk1pIHZlcnN1cyB0aG9zZSB3aXRoIGxvdyBMVk1pLiBNb3Jlb3Zlciwgc2lSRiBjb25zaXN0ZW50bHkgeWllbGRlZCB0aGUgaGlnaGVzdCBwcmVkaWN0aXZlIHBvd2VyIGFjcm9zcyB0aGUgdmFyaW91cyBiaW5hcml6YXRpb24gdGhyZXNob2xkcyBhbmQgcHJlZGljdGlvbiBtZXRyaWNzICh3aXRoIG9uZSBleGNlcHRpb24gYmVpbmcgdGhlIGNsYXNzaWZpY2F0aW9uIGFjY3VyYWN5IGZvciB0aGUgMTVcJSBiaW5hcml6YXRpb24gdGhyZXNob2xkLCB3aGVyZSByaWRnZSBpcyBzbGlnaHRseSBiZXR0ZXIgdGhhbiBzaVJGKS4gRnJvbSB0aGlzLCB3ZSBjb25jbHVkZSB0aGF0IHNpUkYgcGFzc2VkIHRoZSBwcmVkaWN0aW9uIGNoZWNrIGFuZCB3aWxsIHByb2NlZWQgdG8gaW50ZXJwcmV0IHRoZSBzaVJGIGZpdCB0byByZWNvbW1lbmQgYW5kIHByaW9yaXRpemUgaW50ZXJhY3Rpb25zIGJldHdlZW4gZ2VuZXRpYyBsb2NpIGZvciBkb3duc3RyZWFtIGFuYWx5c2VzIGFuZCBleHBlcmltZW50cy4KCkJleW9uZCB0aGUgdmFsaWRhdGlvbiBwcmVkaWN0aW9uIGFjY3VyYWNpZXMsIHdlIGFsc28gcHJvdmlkZSB0aGUgY29uZnVzaW9uIG1hdHJpY2VzLCBST0MgYW5kIHByZWNpc2lvbi1yZWNhbGwgY3VydmVzLCBhbmQgcGFpciBwbG90cyBjb21wYXJpbmcgdGhlIHByZWRpY3RlZCByZXNwb25zZXMgYWNyb3NzIG1ldGhvZHMgZm9yIGFkZGl0aW9uYWwgcG9zdC1ob2MgZXhwbG9yYXRpb24uCgo8L2Rpdj4KCmBgYHtyIHByZWQtcmVzdWx0cy1iaW5hcnksIHJlc3VsdHMgPSAiYXNpcyJ9CgojIFRPRE86IEFkZCB0ZXN0IGFjY3VyYWNpZXMKIyBwaGVub3R5cGVfaGVhZGVyIDwtICJcblxuIyMgJXMgey51bm51bWJlcmVkIC50YWJzZXQgLnRhYnNldC1waWxscyAudGFic2V0LWZhZGUgLnRhYnNldC1zcXVhcmV9IFxuXG4iCnN1bW1hcnlfaGVhZGVyIDwtICJcblxuIyMgJXMgey51bm51bWJlcmVkIC50YWJzZXQgLnRhYnNldC1waWxscyAudGFic2V0LWZhZGUgLnRhYnNldC1zcXVhcmV9XG5cbiIKdGhyX2hlYWRlciA8LSAiXG5cbiMjIEJpbmFyaXphdGlvbiBUaHJlc2hvbGQgPSAlcyB7LnVubnVtYmVyZWQgLnRhYnNldCAudGFic2V0LXBpbGxzIC50YWJzZXQtZmFkZSAudGFic2V0LXNxdWFyZX1cblxuIgpzZWN0aW9uX2hlYWRlciA8LSAiXG5cbiMjIyAlcyB7LnVubnVtYmVyZWQgLnRhYnNldCAudGFic2V0LXBpbGxzIC50YWJzZXQtZmFkZSAudGFic2V0LWNpcmNsZX0gXG5cbiIKc3Vic2VjdGlvbl9oZWFkZXIgPC0gIlxuXG4jIyMjICVzIHsudW5udW1iZXJlZH0gXG5cbiIKCm1ldGhvZHMgPC0gYygiTGFzc28iID0gImxhc3NvIiwgIlJpZGdlIiA9ICJyaWRnZSIsICJSRiIgPSAicmYiLCAic2lSRiIgPSAiaXJmIiwgIlNWTSIgPSAic3ZtIikKCkFVQ19IRUlHSFQgPC0gNQoKIyBmb3IgKHBoZW5vdHlwZSBpbiBwaGVub3R5cGVzKSB7CiMgICBmb3IgKHRociBpbiBjKDAuMTUsIDAuMiwgMC4yNSkpIHsKIyAgICAgZnBhdGggPC0gZmlsZS5wYXRoKHJlc19kaXIsIHBhc3RlMChwaGVub3R5cGUsICJfYmluYXJ5X3RociIsIHRociwKIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJfZ3dhc19maWx0ZXJlZF9uc25wczEwMDAiKSkKIyAgICAgbG9hZChmaWxlLnBhdGgoZnBhdGgsICJpcmZfaW50ZXJhY3Rpb25fZml0LlJkYXRhIikpCiMgICAgIHRyYWluX2lkcyA8LSBjKHJvd25hbWVzKG91dCRnZW5vLnRyYWluMSksIHJvd25hbWVzKG91dCRnZW5vLnRyYWluMikpCiMgICAgIHRlc3RfaWRzIDwtIHJvd25hbWVzKG91dCRnZW5vLnRlc3QpCiMgICAgIAojICAgICB5IDwtIGxvYWRQaGVubyh0cmFpbl9pZHMsICJpTFZNIikKIyAgIH0KIyB9CgppZiAocGFyYW1zJGV2YWwpIHsKICBmb3IgKHBoZW5vdHlwZSBpbiBwaGVub3R5cGVzKSB7CiAgICBldmFsX2xzIDwtIGxpc3QoKQogICAgcGhlbm90eXBlX25hbWUgPC0gbmFtZXMocGhlbm90eXBlcylbcGhlbm90eXBlcyA9PSBwaGVub3R5cGVdCiAgICBmb3IgKHRociBpbiBjKDAuMTUsIDAuMiwgMC4yNSkpIHsKICAgICAgZnBhdGggPC0gZmlsZS5wYXRoKHJlc19kaXIsIHBhc3RlMChwaGVub3R5cGUsICJfYmluYXJ5X3RociIsIHRociwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiX2d3YXNfZmlsdGVyZWRfbnNucHMxMDAwIikpCiAgICAgICMgcmVhZCBpbiBwcmVkaWN0aW9uIHJlc3VsdHMKICAgICAgbG9hZChmaWxlLnBhdGgoZnBhdGgsICJ2YWxpZGF0aW9uX3BoZW5vLlJkYXRhIikpICAjID4gcGhlbm8KICAgICAgcHJlZHNfZGF0YSA8LSBsaXN0KAogICAgICAgIHloYXQgPSBjKAogICAgICAgICAgcmVhZFJEUyhmaWxlLnBhdGgoZnBhdGgsICJ5cHJlZC5yZHMiKSksCiAgICAgICAgICBmcmVhZChmaWxlLnBhdGgoZnBhdGgsICJ5cHJlZC5jc3YiKSkKICAgICAgICApLAogICAgICAgIHkgPSBwaGVubywKICAgICAgICBHZW5kZXIgPSBpZmVsc2UobG9hZERlbW9ncmFwaGljcyhwaGVubylbLCAiZ2VuZGVyIl0gPT0gMSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIk1hbGUiLCAiRmVtYWxlIikgJT4lIGFzLmZhY3RvcigpCiAgICAgICkKICAgICAgCiAgICAgIHByZWRzX2RhdGEkeWhhdCA8LSBwcmVkc19kYXRhJHloYXRbbWV0aG9kc10KICAgICAgbmFtZXMocHJlZHNfZGF0YSR5aGF0KSA8LSBuYW1lcyhtZXRob2RzKQoKICAgICAgIyBwcmVkaWN0aW9uIGFjY3VyYWN5IHRhYmxlCiAgICAgIG1ldHJpY3MgPC0gYygiQ2xhc3MiLCAiQVVDIiwgIlBSIikKICAgICAgZXZhbF9vdXQgPC0gbWFwX2RmcihwcmVkc19kYXRhJHloYXQsCiAgICAgICAgICAgICAgICAgICAgICAgICAgfmJpbmRfcm93cygKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGV2YWxQcmVkcyh5ID0gcHJlZHNfZGF0YSR5LCB5aGF0ID0gYygueCksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWV0cmljID0gYygiQVVDIiwgIlBSIikpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgZXZhbFByZWRzKHkgPSBwcmVkc19kYXRhJHksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgeWhhdCA9IHJvdW5kKGMoLngpKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtZXRyaWMgPSBjKCJCYWxhbmNlZENsYXNzIiwgIkNsYXNzIikpCiAgICAgICAgICAgICAgICAgICAgICAgICAgKSwgLmlkID0gIk1ldGhvZCIpICU+JQogICAgICAgIHNwcmVhZChrZXkgPSAiTWV0cmljIiwgdmFsdWUgPSAiVmFsdWUiKQogICAgICBldmFsX2xzW1thcy5jaGFyYWN0ZXIodGhyKV1dIDwtIGV2YWxfb3V0CiAgICAgIAogICAgICAjIGNvbmZ1c2lvbiBtYXRyaXgKICAgICAgY29uZl9hbGwgPC0gbWFwKHByZWRzX2RhdGEkeWhhdCwKICAgICAgICAgICAgICAgICAgICAgIH5ldmFsQ29uZnVzaW9uKHkgPSBwcmVkc19kYXRhJHksIHloYXQgPSAueCkpICU+JQogICAgICAgIHB1cnJyOjpyZWR1Y2UoLiwgY2JpbmQpCiAgICAgIGNvbmZfbmFtZXMgPC0gY29sbmFtZXMoY29uZl9hbGwpICU+JQogICAgICAgIHN0cmluZ3I6OnN0cl9yZXBsYWNlKCIwIiwgIkxvdyIpICU+JQogICAgICAgIHN0cmluZ3I6OnN0cl9yZXBsYWNlKCIxIiwgIkhpZ2giKQogICAgICBjb2xuYW1lcyhjb25mX2FsbCkgPC0gcGFzdGUoY29uZl9uYW1lcywgMTpuY29sKGNvbmZfYWxsKSkKICAgICAgcm93bmFtZXMoY29uZl9hbGwpIDwtIHJvd25hbWVzKGNvbmZfYWxsKSAlPiUKICAgICAgICBzdHJpbmdyOjpzdHJfcmVwbGFjZSgiMCIsICJMb3ciKSAlPiUKICAgICAgICBzdHJpbmdyOjpzdHJfcmVwbGFjZSgiMSIsICJIaWdoIikKICAgICAgY29uZl9oZWFkZXIgPC0gYygxLCByZXAoMiwgbGVuZ3RoKHByZWRzX2RhdGEkeWhhdCkpKSAlPiUKICAgICAgICBzZXROYW1lcyhjKCIgIiwgbmFtZXMocHJlZHNfZGF0YSR5aGF0KSkpCiAgICAgIHRhYiA8LSBwcmV0dHlfRFQoY29uZl9hbGwsIHJvd25hbWVzID0gVFJVRSwgCiAgICAgICAgICAgICAgICAgICAgICAgZ3JvdXBlZF9oZWFkZXIgPSBjb25mX2hlYWRlciwgCiAgICAgICAgICAgICAgICAgICAgICAgZ3JvdXBlZF9zdWJoZWFkZXIgPSBjKCIgIiwgY29uZl9uYW1lcyksCiAgICAgICAgICAgICAgICAgICAgICAgb3B0aW9ucyA9IGxpc3QoZG9tID0gInQiLCBvcmRlcmluZyA9IEZBTFNFKSkKICAgICAgc2F2ZVJEUyh0YWIsCiAgICAgICAgICAgICAgZmlsZS5wYXRoKHRhYl9yZXNfZGlyLAogICAgICAgICAgICAgICAgICAgICAgICBwYXN0ZTAocGhlbm90eXBlLCAiX3RociIsIHRociwgIl9jb25mdXNpb25fbWF0cml4LnJkcyIpKSkKCiAgICAgICMgYXVjL3ByIHBsb3RzCiAgICAgIHJvY19scyA8LSBtYXAocHJlZHNfZGF0YSR5aGF0LAogICAgICAgICAgICAgICAgICAgIH5ldmFsQVVDKHkgPSBwcmVkc19kYXRhJHksIHloYXQgPSAueCwgbWV0cmljID0gInJvYyIpKQogICAgICBwcl9scyA8LSBtYXAocHJlZHNfZGF0YSR5aGF0LAogICAgICAgICAgICAgICAgICAgfmV2YWxBVUMoeSA9IHByZWRzX2RhdGEkeSwgeWhhdCA9IC54LCBtZXRyaWMgPSAicHIiKSkKCiAgICAgICMgZHJvcCBtb2RlbHMgd2l0aCBjb25zdGFudCBwcmVkaWN0aW9ucwogICAgICByb2NfbHMgPC0gcm9jX2xzWyFzYXBwbHkocm9jX2xzLCBpcy5udWxsKV0KICAgICAgcHJfbHMgPC0gcHJfbHNbIXNhcHBseShwcl9scywgaXMubnVsbCldCgogICAgICAjIGdldCBjdXJ2ZXMKICAgICAgcm9jX2RmIDwtIG1hcF9kZnIocm9jX2xzLAogICAgICAgICAgICAgICAgICAgICAgICB+ZGF0YS5mcmFtZSgueCRjdXJ2ZSkgJT4lCiAgICAgICAgICAgICAgICAgICAgICAgICAgbXV0YXRlKEFVQyA9IHJvdW5kKC54JGF1YywgMykpLAogICAgICAgICAgICAgICAgICAgICAgICAuaWQgPSAiTWV0aG9kIikgJT4lCiAgICAgICAgbXV0YXRlKE1ldGhvZCA9IGFzLmZhY3RvcihwYXN0ZShNZXRob2QsICIgKCIsIEFVQywgIikiLCBzZXAgPSAiIikpKQogICAgICBwcl9kZiA8LSBtYXBfZGZyKHByX2xzLAogICAgICAgICAgICAgICAgICAgICAgIH5kYXRhLmZyYW1lKC54JGN1cnZlKSAlPiUKICAgICAgICAgICAgICAgICAgICAgICAgIG11dGF0ZShBVUMgPSByb3VuZCgueCRhdWMuaW50ZWdyYWwsIDMpKSwKICAgICAgICAgICAgICAgICAgICAgICAuaWQgPSAiTWV0aG9kIikgJT4lCiAgICAgICAgbXV0YXRlKE1ldGhvZCA9IGFzLmZhY3RvcihwYXN0ZShNZXRob2QsICIgKCIsIEFVQywgIikiLCBzZXAgPSAiIikpKQoKICAgICAgIyBtYWtlIHBsb3RzCiAgICAgIHJvY19wbHQgPC0gZ2dwbG90KHJvY19kZikgKwogICAgICAgIGFlcyh4ID0gWDEsIHkgPSBYMiwgY29sb3IgPSBNZXRob2QpICsKICAgICAgICBnZW9tX2xpbmUoKSArCiAgICAgICAgbGFicyh4ID0gIkZQUiIsIHkgPSAiVFBSIikgKwogICAgICAgIHZ0aGVtZXM6OnRoZW1lX3Ztb2Rlcm4oKSArCiAgICAgICAgdnRoZW1lczo6c2NhbGVfY29sb3Jfdm1vZGVybihkaXNjcmV0ZSA9IFRSVUUpCiAgICAgIHNhdmVSRFMocm9jX3BsdCwKICAgICAgICAgICAgICBmaWxlLnBhdGgoZmlnX3Jlc19kaXIsCiAgICAgICAgICAgICAgICAgICAgICAgIHBhc3RlMChwaGVub3R5cGUsICJfdGhyIiwgdGhyLCAiX3JvYy5yZHMiKSkpCgogICAgICBwcl9wbHQgPC0gZ2dwbG90KHByX2RmKSArCiAgICAgICAgYWVzKHggPSBYMSwgeSA9IFgyLCBjb2xvciA9IE1ldGhvZCkgKwogICAgICAgIGdlb21fbGluZSgpICsKICAgICAgICBsYWJzKHggPSAiUmVjYWxsIiwgeSA9ICJQcmVjaXNpb24iKSArCiAgICAgICAgdnRoZW1lczo6dGhlbWVfdm1vZGVybigpICsKICAgICAgICB2dGhlbWVzOjpzY2FsZV9jb2xvcl92bW9kZXJuKGRpc2NyZXRlID0gVFJVRSkKICAgICAgc2F2ZVJEUyhwcl9wbHQsCiAgICAgICAgICAgICAgZmlsZS5wYXRoKGZpZ19yZXNfZGlyLAogICAgICAgICAgICAgICAgICAgICAgICBwYXN0ZTAocGhlbm90eXBlLCAiX3RociIsIHRociwgIl9wci5yZHMiKSkpCgogICAgICAjIHByZWRpY3Rpb24gcGFpciBwbG90cwogICAgICBwbHRfZGYgPC0gbWFwX2RmYyhwcmVkc19kYXRhJHloYXQsIH5jKC54KSkKICAgICAgcGx0IDwtIHBsb3RfcGFpcnMoZGF0YSA9IHBsdF9kZiwgY29sdW1ucyA9IDE6bmNvbChwbHRfZGYpKQogICAgICBzYXZlUkRTKHBsdCwKICAgICAgICAgICAgICBmaWxlLnBhdGgoZmlnX3Jlc19kaXIsCiAgICAgICAgICAgICAgICAgICAgICAgIHBhc3RlMChwaGVub3R5cGUsICJfdGhyIiwgdGhyLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIl9wcmVkX3BhaXJfcGxvdC5yZHMiKSkpCiAgICB9CiAgICAKICAgIHBoZW5vdHlwZV9uYW1lIDwtIG5hbWVzKHBoZW5vdHlwZXMpW3BoZW5vdHlwZXMgPT0gcGhlbm90eXBlXQogICAgdGFiIDwtIGRwbHlyOjpiaW5kX3Jvd3MoZXZhbF9scywgLmlkID0gIlRocmVzaG9sZCIpICU+JQogICAgICBkcGx5cjo6cmVuYW1lKCJBY2N1cmFjeSIgPSAiQ2xhc3MiLCAiQVVST0MiID0gIkFVQyIsICJBVVBSQyIgPSAiUFIiKSAlPiUKICAgICAgZHBseXI6Om11dGF0ZShUaHJlc2hvbGQgPSBwYXN0ZTAoIkJpbmFyaXphdGlvbiBUaHJlc2hvbGQgPSAiLCBUaHJlc2hvbGQpKSAlPiUKICAgICAgZHBseXI6OnNlbGVjdChUaHJlc2hvbGQsIE1ldGhvZCwgQWNjdXJhY3ksIEFVUk9DLCBBVVBSQykgJT4lCiAgICAgIGRwbHlyOjpncm91cF9ieShUaHJlc2hvbGQpICU+JQogICAgICBkcGx5cjo6bXV0YXRlKGRwbHlyOjphY3Jvc3MoYyhBY2N1cmFjeSwgQVVST0MsIEFVUFJDKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH5pZmVsc2UoLnggPT0gbWF4KC54KSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGthYmxlRXh0cmE6OmNlbGxfc3BlYygKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmb3JtYXRDKC54LCBkaWdpdHMgPSAzLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZvcm1hdCA9ICJnIiwgZmxhZyA9ICIjIiksIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJvbGQgPSBUUlVFKSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZvcm1hdEMoLngsIGRpZ2l0cyA9IDMsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9ybWF0ID0gImciLCBmbGFnID0gIiMiKSkpKSAlPiUKICAgICAgdGlkeXI6OnBpdm90X2xvbmdlcihjb2xzID0gYyhBY2N1cmFjeSwgQVVST0MsIEFVUFJDKSwgbmFtZXNfdG8gPSAiTWV0cmljIiwgdmFsdWVzX3RvID0gIlZhbHVlIikgJT4lCiAgICAgIHRpZHlyOjpwaXZvdF93aWRlcihpZF9jb2xzID0gTWV0aG9kLCBuYW1lc19mcm9tID0gYyhUaHJlc2hvbGQsIE1ldHJpYyksIHZhbHVlc19mcm9tID0gVmFsdWUpICU+JQogICAgICB2dGhlbWVzOjpwcmV0dHlfRFQoCiAgICAgICAgZGlnaXRzID0gMywgc2lnZmlnID0gRkFMU0UsIHJvd25hbWVzID0gRkFMU0UsIG5hX2Rpc3AgPSAiLS0iLAogICAgICAgIGdyb3VwZWRfaGVhZGVyID0gYygiICIgPSAxLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgIkJpbmFyaXphdGlvbiBUaHJlc2hvbGQgPSAwLjE1IiA9IDMsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICJCaW5hcml6YXRpb24gVGhyZXNob2xkID0gMC4yMCIgPSAzLAogICAgICAgICAgICAgICAgICAgICAgICAgICAiQmluYXJpemF0aW9uIFRocmVzaG9sZCA9IDAuMjUiID0gMyksIAogICAgICAgIGdyb3VwZWRfc3ViaGVhZGVyID0gYygiTWV0aG9kIiwgcmVwKGMoIkFjY3VyYWN5IiwgIkFVUk9DIiwgIkFVUFJDIiksIHRpbWVzID0gMykpLAogICAgICAgIG9wdGlvbnMgPSBsaXN0KGRvbSA9ICJ0IikKICAgICAgKQogICAgc2F2ZVJEUyh0YWIsIAogICAgICAgICAgICBmaWxlLnBhdGgodGFiX3Jlc19kaXIsIHBhc3RlMChwaGVub3R5cGUsICJfYmluYXJ5X3ByZWRfYWNjdXJhY3kucmRzIikpKQogIH0KfSBlbHNlIHsKICBmb3IgKHBoZW5vdHlwZSBpbiBwaGVub3R5cGVzKSB7CiAgICBwaGVub3R5cGVfbmFtZSA8LSBuYW1lcyhwaGVub3R5cGVzKVtwaGVub3R5cGVzID09IHBoZW5vdHlwZV0KICAgICMgY2F0KHNwcmludGYocGhlbm90eXBlX2hlYWRlciwgcGhlbm90eXBlX25hbWUpKQogICAgCiAgICAjIHN1bW1hcnkgdGFibGUgb2YgcHJlZGljdGlvbiBhY2N1cmFjaWVzCiAgICBjYXQoc3ByaW50ZihzdW1tYXJ5X2hlYWRlciwgIlByZWRpY3Rpb24gQWNjdXJhY3kgU3VtbWFyeSIpKQogICAgdGFiIDwtIHJlYWRSRFMoZmlsZS5wYXRoKHRhYl9yZXNfZGlyLCBwYXN0ZTAocGhlbm90eXBlLCAiX2JpbmFyeV9wcmVkX2FjY3VyYWN5LnJkcyIpKSkKICAgIHN1YmNodW5raWZ5KHRhYiwgaSA9IGNodW5rX2lkeCwKICAgICAgICAgICAgICAgIGNhcHRpb24gPSBzcHJpbnRmKCInU3VtbWFyeSBvZiBwcmVkaWN0aW9uIHBlcmZvcm1hbmNlIG9uIHRoZSB2YWxpZGF0aW9uIHNldCBmb3IgdGhlIGJpbmFyaXplZCAlcyBwaGVub3R5cGUgYWNyb3NzIHZhcmlvdXMgcHJlZGljdGlvbiBtZXRob2RzLCBiaW5hcml6YXRpb24gdGhyZXNob2xkcywgYW5kIGV2YWx1YXRpb24gbWV0cmljcy4nIiwgcGhlbm90eXBlX25hbWUpKQogICAgY2h1bmtfaWR4IDwtIGNodW5rX2lkeCArIDEKICAgIAogICAgZm9yICh0aHIgaW4gYygwLjE1LCAwLjIsIDAuMjUpKSB7CiAgICAgIGNhdChzcHJpbnRmKHRocl9oZWFkZXIsIHRocikpCiAgICAgIAogICAgICAjIGNvbmZ1c2lvbiBtYXRyaXgKICAgICAgY2F0KHNwcmludGYoc2VjdGlvbl9oZWFkZXIsICJDb25mdXNpb24gVGFibGVzIikpCiAgICAgIHRhYiA8LSByZWFkUkRTKGZpbGUucGF0aCh0YWJfcmVzX2RpciwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcGFzdGUwKHBoZW5vdHlwZSwgIl90aHIiLCB0aHIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiX2NvbmZ1c2lvbl9tYXRyaXgucmRzIikpKQogICAgICBzdWJjaHVua2lmeSh0YWIsIGkgPSBjaHVua19pZHgsCiAgICAgICAgICAgICAgICAgIGNhcHRpb24gPSBzcHJpbnRmKCInQ29uZnVzaW9uIG1hdHJpeCBmcm9tIHZhcmlvdXMgcHJlZGljdGlvbiBtb2RlbHMgZm9yIHByZWRpY3RpbmcgdGhlIGJpbmFyaXplZCAlcyBwaGVub3R5cGUgKGJpbmFyaXphdGlvbiB0aHJlc2hvbGQgPSAlcykuJyIsIHBoZW5vdHlwZV9uYW1lLCB0aHIpKQogICAgICBjaHVua19pZHggPC0gY2h1bmtfaWR4ICsgMQogICAgICAKICAgICAgIyBhdWMvcHIgcGxvdHMKICAgICAgY2F0KHNwcmludGYoc2VjdGlvbl9oZWFkZXIsICJST0MvUFIgQ3VydmVzIikpCiAgICAgIHBsdCA8LSByZWFkUkRTKGZpbGUucGF0aChmaWdfcmVzX2RpciwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwYXN0ZTAocGhlbm90eXBlLCAiX3RociIsIHRociwgIl9yb2MucmRzIikpKQogICAgICBzdWJjaHVua2lmeShnZ3Bsb3RseShwbHQpLCBpID0gY2h1bmtfaWR4LCBmaWdfaGVpZ2h0ID0gQVVDX0hFSUdIVCwKICAgICAgICAgICAgICAgICAgYWRkX2NsYXNzID0gYygicGFuZWwgcGFuZWwtZGVmYXVsdCBwYWRkZWQtcGFuZWwiKSwKICAgICAgICAgICAgICAgICAgb3RoZXJfYXJncyA9ICJvdXQud2lkdGg9JzEwMCUnIiwKICAgICAgICAgICAgICAgICAgY2FwdGlvbiA9IHNwcmludGYoIidST0MgY3VydmUgZm9yIHByZWRpY3RpbmcgdGhlIGJpbmFyaXplZCAlcyAodGhyZXNob2xkID0gJXMpIGFjcm9zcyB2YXJpb3VzIHByZWRpY3Rpb24gbWV0aG9kcy4gVFBSID0gdHJ1ZSBwb3NpdGl2ZSByYXRlOyBGUFIgPSBmYWxzZSBwb3NpdGl2ZSByYXRlLiciLCBwaGVub3R5cGVfbmFtZSwgdGhyKSkKICAgICAgY2h1bmtfaWR4IDwtIGNodW5rX2lkeCArIDEKICAgICAgCiAgICAgIHBsdCA8LSByZWFkUkRTKGZpbGUucGF0aChmaWdfcmVzX2RpciwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwYXN0ZTAocGhlbm90eXBlLCAiX3RociIsIHRociwgIl9wci5yZHMiKSkpCiAgICAgIHN1YmNodW5raWZ5KGdncGxvdGx5KHBsdCksIGkgPSBjaHVua19pZHgsIGZpZ19oZWlnaHQgPSBBVUNfSEVJR0hULAogICAgICAgICAgICAgICAgICBhZGRfY2xhc3MgPSBjKCJwYW5lbCBwYW5lbC1kZWZhdWx0IHBhZGRlZC1wYW5lbCIpLAogICAgICAgICAgICAgICAgICBvdGhlcl9hcmdzID0gIm91dC53aWR0aD0nMTAwJSciLAogICAgICAgICAgICAgICAgICBjYXB0aW9uID0gc3ByaW50ZigiJ1ByZWNpc2lvbi1yZWNhbGwgY3VydmUgZm9yIHByZWRpY3RpbmcgdGhlIGJpbmFyaXplZCAlcyAodGhyZXNob2xkID0gJXMpIGFjcm9zcyB2YXJpb3VzIHByZWRpY3Rpb24gbWV0aG9kcy4nIiwgcGhlbm90eXBlX25hbWUsIHRocikpCiAgICAgIGNodW5rX2lkeCA8LSBjaHVua19pZHggKyAxCiAgICAgIAogICAgICAjIHByZWRpY3Rpb24gcGFpciBwbG90cwogICAgICBjYXQoc3ByaW50ZihzZWN0aW9uX2hlYWRlciwgIlByZWRpY3Rpb24gUGFpciBQbG90IikpCiAgICAgIHBsdCA8LSByZWFkUkRTKGZpbGUucGF0aChmaWdfcmVzX2RpciwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwYXN0ZTAocGhlbm90eXBlLCAiX3RociIsIHRociwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIl9wcmVkX3BhaXJfcGxvdC5yZHMiKSkpCiAgICAgIHN1YmNodW5raWZ5KHBsdCwgaSA9IGNodW5rX2lkeCwgZmlnX2hlaWdodCA9IHBsdCRuY29sICogMS41LAogICAgICAgICAgICAgICAgICBhZGRfY2xhc3MgPSBjKCJwYW5lbCBwYW5lbC1kZWZhdWx0IiksCiAgICAgICAgICAgICAgICAgIG90aGVyX2FyZ3MgPSAib3V0LndpZHRoPScxMDAlJyIsCiAgICAgICAgICAgICAgICAgIGNhcHRpb24gPSBzcHJpbnRmKCInUGFpciBwbG90cyBvZiB0aGUgcHJlZGljdGVkIGJpbmFyaXplZCAlcyByZXNwb25zZXMgKHRocmVzaG9sZCA9ICVzKSBhY3Jvc3MgdmFyaW91cyBwcmVkaWN0aW9uIG1ldGhvZHMuIEVhY2ggcG9pbnQgcmVwcmVzZW50cyBhbiBpbmRpdmlkdWFsIGluIHRoZSB2YWxpZGF0aW9uIHNldCwgYW5kIHRoZSBjb29yZGluYXRlcyByZXByZXNlbnQgdGhlIHByZWRpY3RlZCBwcm9iYWJpbGl0eSBvZiBoYXZpbmcgaGlnaCAlcyBmcm9tIHR3byBkaWZmZXJlbnQgcHJlZGljdGlvbiBtZXRob2RzLCB3aGljaCBhcmUgc3BlY2lmaWVkIGJ5IHRoZSB4IGFuZCB5LWF4ZXMgbGFiZWxzIGluIGVhY2ggc3VicGxvdC4gRGVuc2l0eSBkaXN0cmlidXRpb25zIG9mIHRoZSBwcmVkaWN0ZWQgcHJvYmFiaWxpdGllcyBhcmUgc2hvd24gYWxvbmcgdGhlIGRpYWdvbmFsLiciLCBwaGVub3R5cGVfbmFtZSwgdGhyLCBwaGVub3R5cGVfbmFtZSkpCiAgICAgIGNodW5rX2lkeCA8LSBjaHVua19pZHggKyAxCiAgICB9CiAgfQp9CgpgYGAKCgojIFByaW9yaXRpemF0aW9uIFN0ZXAgey50YWJzZXQgLnRhYnNldC1mYWRlIC50YWJzZXQtdm1vZGVybn0KCiMjIE92ZXJ2aWV3IHsudW5udW1iZXJlZCAudGFic2V0IC50YWJzZXQtcGlsbHMgLnRhYnNldC1mYWRlIC50YWJzZXQtc3F1YXJlfQoKPGRpdiBjbGFzcz0icGFuZWwgcGFuZWwtZGVmYXVsdCBwYWRkZWQtcGFuZWwiPgpIYXZpbmcgcGFzc2VkIHRoZSBwcmVkaWN0aW9uIGNoZWNrLCB3ZSBmaW5hbGx5IHByb2NlZWQgdG8gaW50ZXJwcmV0IHRoZSBzaVJGIGZpdCBpbiB0aGUgbGFzdCBzdGVwIG9mIGxvLXNpUkYuIEluIHRoaXMgc3RlcCwgd2UgZGV2ZWxvcGVkIGEgbm92ZWwgc3RhYmlsaXR5LWRyaXZlbiBmZWF0dXJlIGltcG9ydGFuY2Ugc2NvcmUgdG8gcHJpb3JpdGl6ZSBib3RoIGdlbmV0aWMgbG9jaSBhbmQgaW50ZXJhY3Rpb25zIGJldHdlZW4gZ2VuZXRpYyBsb2NpIGZyb20gc2lSRi4gV2UgcmVmZXIgdG8gW0B3YW5nMjAyM2VwaXN0YXNpc10oKSBmb3IgdGhlIGRldGFpbGVkIGRlc2NyaXB0aW9uIG9mIHRoaXMgbmV3IGltcG9ydGFuY2Ugc2NvcmUgYW5kIGhlcmUgcHJvdmlkZSBicmllZiBpbnNpZ2h0cyBpbnRvIHRoZSBtb3RpdmF0aW9uIGFuZCBpbnR1aXRpb24gYmVoaW5kIHRoaXMgbWV0aG9kLgoKKipNYWluIGlkZWE6KiogQXQgYSBoaWdoLWxldmVsLCB0aGlzIG5ldyBpbXBvcnRhbmNlIHNjb3JlICgxKSBhZ2dyZWdhdGVzIHdlYWssIHVuc3RhYmxlIFNOVi1sZXZlbCBpbXBvcnRhbmNlcyBmcm9tIHNpUkYgaW50byBzdHJvbmdlciwgbW9yZSBzdGFibGUgbG9jdXMtbGV2ZWwgaW1wb3J0YW5jZXMgYW5kICgyKSBjYW4gYmUgbGV2ZXJhZ2VkIHRvIGV2YWx1YXRlIGJvdGggdGhlIG1hcmdpbmFsIGltcG9ydGFuY2Ugb2YgYSBnZW5ldGljIGxvY3VzIGluIHNpUkYgYXMgd2VsbCBhcyB0aGUgaW1wb3J0YW5jZSBvZiBoaWdoZXItb3JkZXIgaW50ZXJhY3Rpb25zIGJldHdlZW4gZ2VuZXRpYyBsb2NpIGluIHNpUkYuIFRoZSBuZWVkIGZvciB0aGlzIGxvY3VzLWxldmVsIGZlYXR1cmUgaW1wb3J0YW5jZSBzY29yZSBzdGVtcyBmcm9tIHR3byBtYWluIHJlYXNvbnM6IHRoZSBoaWdoIGNvcnJlbGF0aW9uIGJldHdlZW4gU05WcyBhbmQgdGhlIHdlYWsgcGhlbm90eXBpYyBzaWduYWwuIFRob3VnaCB0aGUgcHJlZGljdGlvbiBtb2RlbHMgKGluY2x1ZGluZyBzaVJGKSBhcmUgYWxsIHRyYWluZWQgdXNpbmcgU05WIGRhdGEsIGl0IGlzIG9mdGVuIHZlcnkgY2hhbGxlbmdpbmcgdG8gaW50ZXJwcmV0IHRoZSBpbXBvcnRhbmNlIG9mIGFuIGluZGl2aWR1YWwgU05WIGZyb20gdGhlc2UgbW9kZWxzIGR1ZSB0byB0aGUgaGlnaCBjb3JyZWxhdGlvbiBiZXR3ZWVuIFNOVnMgW0B0b2xvY3NpMjAxMWNsYXNzaWZpY2F0aW9uOyBAaG9va2VyMjAyMXVucmVzdHJpY3RlZF0sIHdoaWNoIHdlIG9ic2VydmVkIGluIG91ciBwcmV2aW91cyBleHBsb3JhdG9yeSBkYXRhIGFuYWx5c2lzIChzZWUgYENob2ljZSBvZiBQaGVub3R5cGljIERhdGFgIHRhYikuIFRvIGZ1cnRoZXIgY29tcGxpY2F0ZSBtYXR0ZXJzLCB0aGUgd2VhayBwaGVub3R5cGljIHNpZ25hbCBpbmNyZWFzZXMgdGhlIGluc3RhYmlsaXR5IG9mIGV4aXN0aW5nIGZlYXR1cmUgaW1wb3J0YW5jZSBtZXRob2RzIGluIHRoYXQgd2Ugc2VlIHRoZSBmZWF0dXJlIHJhbmtpbmdzIGNoYW5nZSBkcmFzdGljYWxseSB3aGVuIHVzaW5nIGRpZmZlcmVudCBib290c3RyYXAgdHJhaW5pbmcgc2FtcGxlcy4gR2l2ZW4gdGhlc2UgY2hhbGxlbmdlcyB3aXRoIFNOVi1sZXZlbCBmZWF0dXJlIGltcG9ydGFuY2VzLCBpdCBpcyB0aGVuIG5vIHN1cnByaXNlIHRoYXQgc2lSRiwgb3V0LW9mLXRoZS1ib3gsIGRvZXMgbm90IGZpbmQgYW55IHN0YWJsZSBpbnRlcmFjdGlvbnMgYmV0d2VlbiBTTlZzIChpLmUuLCB0aGUgc2lSRiBzdGFiaWxpdHkgc2NvcmUgaXMgYXJvdW5kIDAgZm9yIGFsbCBpbnRlcmFjdGlvbnMgYmV0d2VlbiBTTlZzKS4gVG8gYWRkcmVzcyB0aGVzZSBjaGFsbGVuZ2VzLCBvdXIgbmV3IGZlYXR1cmUgaW1wb3J0YW5jZSBzY29yZSBsZXZlcmFnZXMgdGhlIGNvcnJlbGF0aW9uIHN0cnVjdHVyZSBiZXR3ZWVuIFNOVnMsIGdyb3VwcyBTTlZzIGludG8gZ2VuZXRpYyBsb2NpLCBhbmQgYWdncmVnYXRlcyB3ZWFrLCB1bnN0YWJsZSBTTlYtbGV2ZWwgaW1wb3J0YW5jZXMgZnJvbSBzaVJGIGludG8gc3Ryb25nZXIsIG1vcmUgc3RhYmxlIGxvY3VzLWxldmVsIGltcG9ydGFuY2VzLgoKKipNb3RpdmF0aW9uIGJlaGluZCBuZXcgZmVhdHVyZSBpbXBvcnRhbmNlIHNjb3JlOioqIFRvIGJldHRlciB1bmRlcnN0YW5kIHRoZSBtb3RpdmF0aW9uIGFuZCBjb25zdHJ1Y3Rpb24gb2Ygb3VyIG5ldyBsb2N1cy1sZXZlbCBmZWF0dXJlIGltcG9ydGFuY2Ugc2NvcmUsIGl0IGNhbiBiZSBoZWxwZnVsIHRvIGZpcnN0IHJldmlldyB0aGUgb3JpZ2luYWwgaW1wb3J0YW5jZSBzY29yZSB1c2VkIGluIHNpUkYgW0BrdW1iaWVyMjAxOHJlZmluaW5nXS4gQnJpZWZseSwgaW4gdGhlIG9yaWdpbmFsIHZlcnNpb24gb2Ygc2lSRiwgdGhlIGltcG9ydGFuY2Ugb2YgYSBzaWduZWQgaW50ZXJhY3Rpb24gaXMgYmFzZWQgdXBvbiAqaG93IHN0YWJsZSBvciBmcmVxdWVudGx5IGl0IG9jY3VycyogaW4gZGVjaXNpb25zIHBhdGhzIGFjcm9zcyB0aGUgcmFuZG9tIGZvcmVzdCAtLSB0aGF0IGlzLCBiYXNlZCB1cG9uIHRoZSBudW1iZXIgb2YgZGVjaXNpb24gcGF0aHMgZm9yIHdoaWNoIGV2ZXJ5IHNpZ25lZCBmZWF0dXJlIGluIHRoZSBzaWduZWQgaW50ZXJhY3Rpb24gd2FzIHVzZWQgaW4gYXQgbGVhc3Qgb25lIGRlY2lzaW9uIHNwbGl0IChzZWUgQGt1bWJpZXIyMDE4cmVmaW5pbmcgZm9yIGRldGFpbHMpLiBGb2xsb3dpbmcgYSBzaW1pbGFyIGxvZ2ljLCBvbmUgbmF0dXJhbCBwYXRoIGZvcndhcmQgdG8gY2FsY3VsYXRlIGEgbG9jdXMtbGV2ZWwgaW1wb3J0YW5jZSBmcm9tIGEgZm9yZXN0IHRoYXQgd2FzIGZpdCBvbiBTTlYgZGF0YSBpcyBhcyBmb2xsb3dzOgoKMS4gVGFrZSB0aGUgZml0dGVkIGZvcmVzdCwgd2hlcmUgZWFjaCBkZWNpc2lvbiBzcGxpdCB1c2VkIHNvbWUgU05WIHRvIG1ha2UgdGhlIHNwbGl0LgoyLiBNYXAgZWFjaCBTTlYgdXNlZCBpbiBhIGRlY2lzaW9uIHNwbGl0IHRvIGl0cyBjb3JyZXNwb25kaW5nIGdlbmV0aWMgbG9jaSAoZS5nLiwgdXNpbmcgYW5ub3RhdGlvbiBzb2Z0d2FyZSBsaWtlIEFOTk9WQVIgW0B3YW5nMjAxMGFubm92YXJdKS4KMy4gQ29tcHV0ZSB0aGUgaW1wb3J0YW5jZSBvZiBhIHNpZ25lZCBsb2N1cy1sZXZlbCBpbnRlcmFjdGlvbiBiYXNlZCB1cG9uIHRoZSBmcmVxdWVuY3kgb2Ygb2NjdXJyZW5jZSBvZiB0aGUgaW50ZXJhY3Rpb24gYXMgYmVmb3JlLCBidXQgdXNpbmcgdGhlIG1hcHBlZCBnZW5ldGljIGxvY2kgaW4gbGlldSBvZiB0aGUgU05Wcy4gVGhhdCBpcywgY29tcHV0ZSB0aGUgbnVtYmVyIG9mIGRlY2lzaW9uIHBhdGhzIGZvciB3aGljaCBldmVyeSBzaWduZWQgbG9jdXMgaW4gdGhlIHNpZ25lZCBsb2N1cy1sZXZlbCBpbnRlcmFjdGlvbiB3YXMgdXNlZCBpbiBhdCBsZWFzdCBvbmUgZGVjaXNpb24gc3BsaXQuIAoKSG93ZXZlciwgdGhpcyAqZnJlcXVlbmN5IG9mIG9jY3VycmVuY2UqIG1lYXN1cmUgaXMgaGVhdmlseSB0aWVkIHRvIHRoZSBudW1iZXIgb2YgU05WcyB0aGF0IGJlbG9uZyB0byBlYWNoIGdlbmV0aWMgbG9jdXMuIEEgZ2VuZXRpYyBsb2N1cyB0aGF0IGNvbnNpc3RzIG9mIG1vcmUgU05WcyB3aWxsIG5hdHVyYWxseSBoYXZlIGEgaGlnaGVyIGZyZXF1ZW5jeSBvZiBvY2N1cnJlbmNlIHRoYW4gYSBnZW5ldGljIGxvY3VzIHdpdGggb25seSBhIGZldyBTTlZzIGV2ZW4gdGhvdWdoIGJvdGggZ2VuZXRpYyBsb2NpIG1heSBiZSBlcXVhbGx5IGltcG9ydGFudCAob3IgdW5pbXBvcnRhbnQpLiBJbiBvdGhlciB3b3JkcywgdGhlIG9yaWdpbmFsIHNpUkYgaW1wb3J0YW5jZSBzY29yZSwgbWVhc3VyaW5nIHRoZSBmcmVxdWVuY3kgb2Ygb2NjdXJyZW5jZSwgaXMgbm90IGNvbXBhcmFibGUgYWNyb3NzIGdlbmV0aWMgbG9jaS4gVGhpcyBiaWFzIGlzIHByb2JsZW1hdGljIGdpdmVuIHRoYXQgd2UgaGF2ZSBwcmV2aW91c2x5IHNlZW4gc29tZSBnZW5ldGljIGxvY2kgbWF5IGNvbnNpc3Qgb2Ygb25seSAxIFNOViB3aGlsZSBvdGhlciBnZW5ldGljIGxvY2kgaGF2ZSA+NTAgU05WcyAoc2VlIGBHV0FTLWZpbHRlcmVkIFNOVnNgIHRhYiBpbiB0aGUgRGltZW5zaW9uIFJlZHVjdGlvbiBTdGVwKS4gCgoqKkludHVpdGlvbiBiZWhpbmQgbmV3IGZlYXR1cmUgaW1wb3J0YW5jZSBzY29yZToqKiBUbyBhbGxldmlhdGUgdGhpcyBiaWFzLCB3ZSBsZXZlcmFnZSB0aGUgaWRlYSBvZiBhICpsb2NhbCogZmVhdHVyZSBpbXBvcnRhbmNlIHNjb3JlLCB3aGVyZSB3ZSBjb21wdXRlIGEgKnBlci1pbmRpdmlkdWFsKiBzY29yZSB0aGF0IG1lYXN1cmVzIHRoZSBpbXBvcnRhbmNlIG9mIGEgbG9jdXMvaW50ZXJhY3Rpb24gZm9yIG1ha2luZyB0aGUgcHJlZGljdGlvbiBvZiAqZWFjaCogaW5kaXZpZHVhbC4gVGhpcyBpcyBpbiBjb250cmFzdCB0byBhICpnbG9iYWwqIGZlYXR1cmUgaW1wb3J0YW5jZSBzY29yZSwgd2hpY2ggaXMgYSBtZWFzdXJlIG9mIGltcG9ydGFuY2UgZm9yIHRoZSBlbnRpcmUgZ3JvdXAgb2YgaW5kaXZpZHVhbHMgdW5kZXIgc3R1ZHkuIFdoaWxlIGEgZ2xvYmFsIGZlYXR1cmUgaW1wb3J0YW5jZSBzY29yZSBnaXZlcyByaXNlIHRvIGEgKnNpbmdsZSogc2NvcmUgZm9yIHRoZSBlbnRpcmUgcG9wdWxhdGlvbiB1bmRlciBzdHVkeSwgd2UgY2FuIGNvbXB1dGUgYSBsb2NhbCBmZWF0dXJlIGltcG9ydGFuY2Ugc2NvcmUgZm9yICplYWNoKiBpbmRpdmlkdWFsIGluIHRoZSBwb3B1bGF0aW9uLiBCeSBjb21wdXRpbmcgYSBsb2NhbCBmZWF0dXJlIGltcG9ydGFuY2Ugc2NvcmUgZm9yIGVhY2ggaW5kaXZpZHVhbCAoaS5lLiwgdGhpcyBpcyB0aGUgbG9jYWwgc3RhYmlsaXR5IGltcG9ydGFuY2UgKExTSSkgc2NvcmUgZnJvbSBbQHdhbmcyMDIzZXBpc3Rhc2lzXSgpKSwgd2UgY2FuIGNvbXBhcmUgdGhlIGltcG9ydGFuY2Ugb2YgdGhlIGxvY3VzL2ludGVyYWN0aW9uIGFjcm9zcyAqaW5kaXZpZHVhbHMqIGFuZCBhdm9pZCB0aGUgYWNyb3NzLSpsb2NpKiBjb21wYXJpc29uIHRoYXQgd2FzIHByb2JsZW1hdGljIGluIHRoZSBhZm9yZW1lbnRpb25lZCBkaXNjdXNzaW9uLiBUaGlzIGNvbXBhcmlzb24gaXMgZG9uZSB2aWEgYSBwZXJtdXRhdGlvbiB0ZXN0IGluIFtAd2FuZzIwMjNlcGlzdGFzaXNdKCkuIE1vcmVvdmVyLCBzaW5jZSB3ZSBhcmUgY29tcGFyaW5nIHRoZSBsb2NhbCBmZWF0dXJlIGltcG9ydGFuY2VzIGJldHdlZW4gaW5kaXZpZHVhbHMgKndpdGhpbiogb3IgKnBlciogbG9jaS9pbnRlcmFjdGlvbiBpbiB0aGlzIHBlcm11dGF0aW9uIHRlc3QsIHRoZSBsb2NhbCBmZWF0dXJlIGltcG9ydGFuY2VzIGFyZSBhbGwgbWVhc3VyZWQgb24gdGhlIHNhbWUgc2NhbGUgYW5kIGNvbXBhcmFibGUsIHRoZXJlYnkgbWl0aWdhdGluZyB0aGUgYmlhcyB0b3dhcmRzIGdlbmV0aWMgbG9jaSB3aXRoIG1vcmUgU05Wcy4KCioqSG93IHRvIGFnZ3JlZ2F0ZSBTTlZzOioqIFdlIG1hcHBlZCBlYWNoIFNOViB0byBpdHMgY29ycmVzcG9uZGluZyBnZW5ldGljIGxvY3VzIHVzaW5nIEFOTk9WQVIgW0B3YW5nMjAxMGFubm92YXJdIGFjY29yZGluZyB0byB0aGUgaGcxOSByZWZTZXEgR2VuZSBhbm5vdGF0aW9ucy4gR2l2ZW4gb3VyIHVsdGltYXRlIGdvYWwgb2YgcmVjb21tZW5kaW5nL3ByaW9yaXRpemluZyBnZW5ldGljIGxvY2kgYW5kIGludGVyYWN0aW9ucyBiZXR3ZWVuIGxvY2kgZm9yIGRvd25zdHJlYW0gYW5hbHlzZXMgYW5kIGV4cGVyaW1lbnRhbCB2YWxpZGF0aW9uLCB3ZSBiZWxpZXZlIHRoaXMgY2hvaWNlIHByb3ZpZGVzIGFuIGFwcHJvcHJpYXRlIHN0YXJ0aW5nIHBvaW50IHRvIG9idGFpbiBhY3Rpb25hYmxlIHJlY29tbWVuZGF0aW9ucy4gSG93ZXZlciwgd2Ugbm90ZSB0aGF0IHRoZXJlIGFyZSBtYW55IGFsdGVybmF0aXZlIHdheXMgb2YgYWdncmVnYXRpbmcgU05Wcy4gRm9yIGV4YW1wbGUsIGl0IGlzIHBvc3NpYmxlIHRvIGFnZ3JlZ2F0ZSBTTlZzIGFjY29yZGluZyB0byBMRC9oYXBsb3R5cGUgYmxvY2tzIG9yIHRvIGluY2x1ZGUgYWRkaXRpb25hbCBnZW5lLWJhc2VkIG9yIGZ1bmN0aW9uYWwgYW5ub3RhdGlvbnMgaW4gdGhlIGFnZ3JlZ2F0aW9uIHNjaGVtZS4KCioqT3JnYW5pemF0aW9uOioqIFVuZGVyIHRoZSBgU05WLWxldmVsIEltcG9ydGFuY2VzYCB0YWIsIHdlIHByb3ZpZGUgdGhlIFNOVi1sZXZlbCBmZWF0dXJlIGltcG9ydGFuY2VzIGZyb20gdGhlIGZpdHRlZCBwcmVkaWN0aW9uIGFsZ29yaXRobXMgKGRlc2NyaWJlZCBpbiB0aGUgYFByZWRpY3Rpb24gU3RlcGAgc2VjdGlvbikgZm9yIGNvbXBsZXRlbmVzcy4gVGhlc2UgU05WLWxldmVsIGZlYXR1cmUgaW1wb3J0YW5jZXMgYXJlIHZlcnkgdW5zdGFibGUgYWNyb3NzIG1ldGhvZHMgYW5kIGFjcm9zcyBib290c3RyYXAgcGVydHVyYmF0aW9ucyBmb3IgdGhlIHJlYXNvbnMgZGlzY3Vzc2VkIGFib3ZlLiBXZSB0aGVuIHN1bW1hcml6ZSB0aGUgcmVzdWx0cyBmcm9tIHRoZSBsby1zaVJGIHBpcGVsaW5lIGluY2x1ZGluZyB0aGUgcmFua2luZ3Mgb2YgZ2VuZXRpYyBsb2NpIGFuZCBpbnRlcmFjdGlvbiBiZXR3ZWVuIGdlbmV0aWMgbG9jaSB1c2luZyBvdXIgbmV3IGxvY3VzLWxldmVsIGltcG9ydGFuY2Ugc2NvcmUgdW5kZXIgdGhlIGBTdW1tYXJ5IG9mIGxvLXNpUkYgUmVzdWx0c2AgdGFiLiBBIGZpbmFsIHRlY2huaWNhbCBub3RlIG9uIHRoZSBhZHZhbnRhZ2VzIG9mIGluY29ycG9yYXRpbmcgc2lnbmVkIGluZm9ybWF0aW9uIGZyb20gc2lSRiBpbiB0aGlzIGZlYXR1cmUgaW1wb3J0YW5jZSBjb21wdXRhdGlvbiBpcyBwcm92aWRlZCB1bmRlciB0aGUgYEFkdmFudGFnZXMgb2YgU2lnbmVkIEluZm9ybWF0aW9uYCB0YWIuCgo8L2Rpdj4KCiMjIFNOVi1sZXZlbCBGZWF0dXJlIEltcG9ydGFuY2VzIHsudW5udW1iZXJlZCAudGFic2V0IC50YWJzZXQtcGlsbHMgLnRhYnNldC1mYWRlIC50YWJzZXQtc3F1YXJlfQoKPGRpdiBjbGFzcz0icGFuZWwgcGFuZWwtZGVmYXVsdCBwYWRkZWQtcGFuZWwiPgpIYXZpbmcgb2JzZXJ2ZWQgdGhhdCB0aGUgYWZvcmVtZW50aW9uZWQgY2xhc3NpZmljYXRpb24gYWxnb3JpdGhtcyBkbyBoYXZlIHNvbWUgcHJlZGljdGl2ZSBwb3dlciB0byBwcmVkaWN0IHRob3NlIHdpdGggaGlnaCB2ZXJzdXMgbG93IExWTWksIGEgbmF0dXJhbCBuZXh0IHN0ZXAgaXMgdG8gaW52ZXN0aWdhdGUgd2hpY2ggU05WcyB3ZXJlIHVzZWQgaW4gdGhlc2UgcHJlZGljdGlvbiBtb2RlbHMuIEJlbG93LCB3ZSBoaWdobGlnaHQgdGhlIHRvcCAxMDAgU05WcywgcmFua2VkIGJ5IGltcG9ydGFuY2UgaW4gZWFjaCBvZiB0aGUgcHJlZGljdGlvbiBtb2RlbHMuIEZvciBjb21wbGV0ZW5lc3MsIHdlIHByb3ZpZGUgdGhlIFNOViBpbXBvcnRhbmNlcyBmb3IgdGhlIHVuYmluYXJpemVkIExWTWkgKHJlZ3Jlc3Npb24pIHByb2JsZW0gYXMgd2VsbCBhcyB0aGUgYmluYXJpemVkIExWTWkgKGNsYXNzaWZpY2F0aW9uKSBwcm9ibGVtIGFjcm9zcyB0aGUgdGhyZWUgZGlmZmVyZW50IGJpbmFyaXphdGlvbiB0aHJlc2hvbGRzLgoKKipIb3cgaXMgaW1wb3J0YW5jZSBkZWZpbmVkPyoqCgotIEZvciByaWRnZSBhbmQgTGFzc28sIHRoZSBpbXBvcnRhbmNlIG9mIGFuIFNOViBpcyBkZWZpbmVkIGFzIHRoZSBtYWduaXR1ZGUgb2YgaXRzIGNvZWZmaWNpZW50IGluIHRoZSBwcmVkaWN0aW9uIG1vZGVsLgotIEZvciBSRiwgdGhlIGltcG9ydGFuY2Ugb2YgYW4gU05WIGlzIGRldGVybWluZWQgYnkgdGhlIG1lYW4gZGVjcmVhc2UgaW4gaW1wdXJpdHkgKE1ESSkgc2NvcmUuCi0gRm9yIHNpUkYsIHRoZSBpbXBvcnRhbmNlIG9mIGFuIFNOViBpcyBkZXRlcm1pbmVkIGJ5IHRoZSBNREkgZnJvbSB0aGUgZm9yZXN0IGluIHRoZSBmaW5hbCBpdGVyYXRpb24uCi0gRHVlIHRvIHRoZSBjb21wdXRhdGlvbmFsIGNvbXBsZXhpdHksIHdlIGRpZCBub3QgY29tcHV0ZSB0aGUgU05WIGltcG9ydGFuY2VzIGZyb20gdGhlIFNWTSBmaXQgYXMgdGhlcmUgaXMgbm8gYnVpbHQtaW4gbW9kZWwtYmFzZWQgZmVhdHVyZSBpbXBvcnRhbmNlIG1ldGhvZCAoaW4gUiksIGFuZCBhbnkgcGVybXV0YXRpb24tYmFzZWQgYXBwcm9hY2ggd291bGQgYmUgY29tcHV0YXRpb25hbGx5IGV4cGVuc2l2ZS4KCioqQSB3b3JkIG9mIGNhdXRpb246KiogV2hlbiBpbnRlcnByZXRpbmcgdGhlc2UgU05WIGltcG9ydGFuY2VzLCBpdCBpcyBjcnVjaWFsIHRvIGtlZXAgaW4gbWluZCB0aGF0IHRoZXJlIGFyZSB2ZXJ5IGxhcmdlLCBzdHJvbmdseSBjb3JyZWxhdGVkIGJsb2NrcyBvZiBTTlZzIHdpdGhpbiB0aGlzIGRhdGEsIHdoaWNoIG9mdGVuIHJlbmRlcnMgdGhlIGZlYXR1cmUgcmFua2luZ3MgdW5tZWFuaW5nZnVsIGFuZCB1bnN0YWJsZSBbQHRvbG9jc2kyMDExY2xhc3NpZmljYXRpb247IEBob29rZXIyMDIxdW5yZXN0cmljdGVkXS4gSW4gcGFydGljdWxhciwgaXQgaXMgd2VsbC1rbm93biB0aGF0IHRoZSBNREkgdmFyaWFibGUgaW1wb3J0YW5jZSBtZXRyaWMgdXNlZCBpbiBSRi9pUkYvc2lSRiBpcyBiaWFzZWQgYWdhaW5zdCBjb3JyZWxhdGVkIGZlYXR1cmVzIFtAaG9va2VyMjAyMXVucmVzdHJpY3RlZF0uIEluIG90aGVyIHdvcmRzLCBTTlZzIHdpdGhpbiBsYXJnZSBMRCBibG9ja3MgdGVuZCB0byBoYXZlIGFydGlmaWNpYWxseSBsb3cgTURJIHZhbHVlcy4gR2l2ZW4gdGhlc2UgaWRpb3N5bmNyYXNpZXMsIGl0IGlzIHVuc3VycHJpc2luZyB0aGF0IFNOVnMgZnJvbSBUVE4gYW5kIENDREMxNDEgLS0gdHdvIGdlbmV0aWMgbG9jaSB3aXRoIG1hbnkgU05WcyB1bmRlciBMRCAtLSBkbyBub3QgaGF2ZSBoaWdoIGltcG9ydGFuY2VzIGFjY29yZGluZyB0byBNREkuIFdlIHByb3ZpZGUgdGhlc2UgU05WIGltcG9ydGFuY2UgdGFibGVzIG9ubHkgZm9yIGNvbXBsZXRlbmVzcyBhbmQgdG8gcGFydGlhbGx5IG1vdGl2YXRlIHRoZSBuZWVkIHRvIGFnZ3JlZ2F0ZSBTTlYtbGV2ZWwgaW1wb3J0YW5jZXMgaW50byBsb2N1cy1sZXZlbCBpbXBvcnRhbmNlcyBpbiBsby1zaVJGLgoKPC9kaXY+CgoKYGBge3IgdmltcCwgcmVzdWx0cyA9ICJhc2lzIn0KCiMgcGhlbm90eXBlX2hlYWRlciA8LSAiXG5cbiMjIyAlcyB7LnVubnVtYmVyZWQgLnRhYnNldCAudGFic2V0LXBpbGxzIC50YWJzZXQtZmFkZSAudGFic2V0LWNpcmNsZX0gXG5cbiIKdGhyX2hlYWRlciA8LSAiXG5cbiMjIyAlcyB7LnVubnVtYmVyZWQgLnRhYnNldCAudGFic2V0LXBpbGxzIC50YWJzZXQtZmFkZSAudGFic2V0LWNpcmNsZX0iCm1ldGhvZF9oZWFkZXIgPC0gIlxuXG4jIyMjICVzIHsudW5udW1iZXJlZCAudGFic2V0IC50YWJzZXQtcGlsbHMgLnRhYnNldC1mYWRlIC50YWJzZXQtY2lyY2xlfSBcblxuIgpzdWJzZWN0aW9uX2hlYWRlciA8LSAiXG5cbiMjIyMjICVzIHsudW5udW1iZXJlZH1cblxuIgoKbWV0aG9kcyA8LSBjKCJMYXNzbyIgPSAibGFzc28iLCAiUmlkZ2UiID0gInJpZGdlIiwgIlJGIiA9ICJyZiIsICJzaVJGIiA9ICJpcmYiKQoKaWYgKHBhcmFtcyRldmFsKSB7CiAgc25wc19kZiA8LSBmcmVhZChmaWxlLnBhdGgocmVzX2RpciwgImFubm92YXIiLCAic25wMmdlbmVfZGYuY3N2IikpCiAgZm9yIChwaGVub3R5cGUgaW4gcGhlbm90eXBlcykgewogICAgcGhlbm90eXBlX25hbWUgPC0gbmFtZXMocGhlbm90eXBlcylbcGhlbm90eXBlcyA9PSBwaGVub3R5cGVdCiAgICBmb3IgKHRociBpbiBjKE5BLCAwLjE1LCAwLjIsIDAuMjUpKSB7CiAgICAgIGlmIChpcy5uYSh0aHIpKSB7CiAgICAgICAgZnBhdGggPC0gZmlsZS5wYXRoKHJlc19kaXIsIHBhc3RlMChwaGVub3R5cGUsICJfZ3dhc19maWx0ZXJlZF9uc25wczEwMDAiKSkKICAgICAgfSBlbHNlIHsKICAgICAgICBmcGF0aCA8LSBmaWxlLnBhdGgocmVzX2RpciwgcGFzdGUwKHBoZW5vdHlwZSwgIl9iaW5hcnlfdGhyIiwgdGhyLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIl9nd2FzX2ZpbHRlcmVkX25zbnBzMTAwMCIpKQogICAgICB9CiAgICAgIGZvciAobWV0aG9kIGluIG1ldGhvZHMpIHsKICAgICAgICB2aW1wX291dCA8LSBldmFsVmltcChyZXNfZGlyID0gZnBhdGgsIG1ldGhvZCA9IG1ldGhvZCwgc25wc19kZiA9IHNucHNfZGYpICU+JQogICAgICAgICAgZHBseXI6OmZpbHRlcighc3RyaW5ncjo6c3RyX2RldGVjdChHZW5lLCAiUENbMC05XSokIikpICU+JQogICAgICAgICAgZHBseXI6OnNsaWNlKDE6MTAwKSAlPiUKICAgICAgICAgIGRwbHlyOjptdXRhdGUoCiAgICAgICAgICAgIEFsbGVsZXMgPSBwdXJycjo6bWFwMihSZWYsIEFsdCwgfiBzb3J0KGMoLngsIC55KSkpLAogICAgICAgICAgICBBbGxlbGUxID0gcHVycnI6Om1hcF9jaHIoQWxsZWxlcywgfiAueFtbMV1dKSwKICAgICAgICAgICAgQWxsZWxlMiA9IHB1cnJyOjptYXBfY2hyKEFsbGVsZXMsIH4gLnhbWzJdXSksCiAgICAgICAgICAgIHVuaXFJRCA9IHBhc3RlKENociwgUG9zLCBBbGxlbGUxLCBBbGxlbGUyLCBzZXAgPSAiOiIpCiAgICAgICAgICApICU+JQogICAgICAgICAgZHBseXI6OnNlbGVjdCgKICAgICAgICAgICAgQ2hyLCByc0lELCBQb3MsIHVuaXFJRCwgTG9jdXMgPSBHZW5lLCBGdW5jdGlvbiA9IGBHZW5lIEZ1bmN0aW9uYCwKICAgICAgICAgICAgYEV4b25pYyBGdW5jdGlvbmAsIEltcG9ydGFuY2UKICAgICAgICAgICkKICAgICAgICBpZiAoIWlzLm51bGwodmltcF9vdXQpKSB7CiAgICAgICAgICB0YWIgPC0gcHJldHR5X0RUKHZpbXBfb3V0LCBkaWdpdHMgPSAzLCBzaWdmaWcgPSBULCBuYV9kaXNwID0gIi0tIikKICAgICAgICAgIHNhdmVSRFModGFiLAogICAgICAgICAgICAgICAgICBmaWxlLnBhdGgodGFiX3Jlc19kaXIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwYXN0ZTAocGhlbm90eXBlLCAiX3RociIsIHRociwgIl8iLCBtZXRob2QsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIl92aW1wLnJkcyIpKSkKICAgICAgICB9CiAgICAgIH0KICAgIH0KICB9Cn0gZWxzZSB7CiAgZm9yIChwaGVub3R5cGUgaW4gcGhlbm90eXBlcykgewogICAgcGhlbm90eXBlX25hbWUgPC0gbmFtZXMocGhlbm90eXBlcylbcGhlbm90eXBlcyA9PSBwaGVub3R5cGVdCiAgICAjIGNhdChzcHJpbnRmKHBoZW5vdHlwZV9oZWFkZXIsIHBoZW5vdHlwZV9uYW1lKSkKICAgIGZvciAodGhyIGluIGMoTkEsIDAuMTUsIDAuMiwgMC4yNSkpIHsKICAgICAgaWYgKGlzLm5hKHRocikpIHsKICAgICAgICBjYXQoc3ByaW50Zih0aHJfaGVhZGVyLCAiVW5iaW5hcml6ZWQgKFJlZ3Jlc3Npb24pIikpCiAgICAgICAgZnBhdGggPC0gZmlsZS5wYXRoKHJlc19kaXIsIHBhc3RlMChwaGVub3R5cGUsICJfZ3dhc19maWx0ZXJlZF9uc25wczEwMDAiKSkKICAgICAgICBwaGVub3R5cGVfc3RyIDwtIHNwcmludGYoIiVzIiwgcGhlbm90eXBlX25hbWUpCiAgICAgIH0gZWxzZSB7CiAgICAgICAgY2F0KHNwcmludGYodGhyX2hlYWRlciwgcGFzdGUwKCJCaW5hcml6YXRpb24gVGhyZXNob2xkID0gIiwgdGhyKSkpCiAgICAgICAgZnBhdGggPC0gZmlsZS5wYXRoKHJlc19kaXIsIHBhc3RlMChwaGVub3R5cGUsICJfYmluYXJ5X3RociIsIHRociwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJfZ3dhc19maWx0ZXJlZF9uc25wczEwMDAiKSkKICAgICAgICBwaGVub3R5cGVfc3RyIDwtIHNwcmludGYoInRoZSBiaW5hcml6ZWQgJXMgKHRocmVzaG9sZCA9ICVzKSIsIHBoZW5vdHlwZV9uYW1lLCB0aHIpCiAgICAgIH0KICAgICAgZm9yIChpIGluIDE6bGVuZ3RoKG1ldGhvZHMpKSB7CiAgICAgICAgbWV0aG9kIDwtIG1ldGhvZHNbW2ldXQogICAgICAgIG1ldGhvZF9uYW1lIDwtIG5hbWVzKG1ldGhvZHMpW2ldCiAgICAgICAgY2F0KHNwcmludGYobWV0aG9kX2hlYWRlciwgbWV0aG9kX25hbWUpKQogICAgICAgIHRtcF9maWxlIDwtIGZpbGUucGF0aCh0YWJfcmVzX2RpciwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcGFzdGUwKHBoZW5vdHlwZSwgIl90aHIiLCB0aHIsICJfIiwgbWV0aG9kLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJfdmltcC5yZHMiKSkKICAgICAgICBpZiAoZmlsZS5leGlzdHModG1wX2ZpbGUpKSB7CiAgICAgICAgICB0YWIgPC0gcmVhZFJEUyh0bXBfZmlsZSkKICAgICAgICAgIHN1YmNodW5raWZ5KHRhYiwgaSA9IGNodW5rX2lkeCwKICAgICAgICAgICAgICAgICAgICAgIG90aGVyX2FyZ3MgPSAib3V0LndpZHRoPScxMDAlJyIsCiAgICAgICAgICAgICAgICAgICAgICBjYXB0aW9uID0gc3ByaW50ZigiJyVzIC0gVG9wIDEwMCBTTlZzLCByYW5rZWQgYnkgaW1wb3J0YW5jZSwgZm9yIHByZWRpY3RpbmcgJXMuJyIsIG1ldGhvZF9uYW1lLCBwaGVub3R5cGVfc3RyKSkKICAgICAgICAgIGNodW5rX2lkeCA8LSBjaHVua19pZHggKyAxCiAgICAgICAgfQogICAgICB9CiAgICB9CiAgfQp9CgpgYGAKCiMjIFN1bW1hcnkgb2YgbG8tc2lSRiBSZXN1bHRzIHsudW5udW1iZXJlZCAudGFic2V0IC50YWJzZXQtcGlsbHMgLnRhYnNldC1mYWRlIC50YWJzZXQtc3F1YXJlfQoKPGRpdiBjbGFzcz0icGFuZWwgcGFuZWwtZGVmYXVsdCBwYWRkZWQtcGFuZWwiPgpGaW5hbGx5LCB3ZSBzdW1tYXJpemUgdGhlIHByaW9yaXRpemF0aW9uIHJlc3VsdHMgZnJvbSB0aGUgbG8tc2lSRiBwaXBlbGluZSB1c2luZyBvdXIgbmV3IGltcG9ydGFuY2Ugc2NvcmUgdG8gcmFuayBnZW5ldGljIGxvY2kgYW5kIGludGVyYWN0aW9ucyBiZXR3ZWVuIGdlbmV0aWMgbG9jaS4gSW4gdGhpcyBuZXcgaW1wb3J0YW5jZSBzY29yZSwgd2UgKDEpIGNvbXB1dGVkIGEgbG9jYWwgKGkuZS4sIG9uIGEgcGVyLWluZGl2aWR1YWwgYmFzaXMpIHN0YWJpbGl0eSBpbXBvcnRhbmNlIHNjb3JlIHRoYXQgYWdncmVnYXRlcyB3ZWFrIFNOVi1sZXZlbCBpbXBvcnRhbmNlcyBpbnRvIHN0cm9uZ2VyIGxvY3VzLWxldmVsIGltcG9ydGFuY2VzIHVzaW5nIHRoZSBzaVJGIGZpdCBhbmQgKDIpIGNvbmR1Y3RlZCBhIHBlcm11dGF0aW9uIHRlc3QgdG8gYXNzZXNzIHdoZXRoZXIgdGhlIGxvY2FsIHN0YWJpbGl0eSBpbXBvcnRhbmNlIHNjb3JlcyBmb3IgYSBnaXZlbiBsb2N1cy9pbnRlcmFjdGlvbiBhcmUgZGlmZmVyZW50IGJldHdlZW4gaW5kaXZpZHVhbHMgd2l0aCBoaWdoIGFuZCBsb3cgTFZNaSAoY29uZGl0aW9uZWQgb24gdGhlIHJlc3Qgb2YgdGhlIGZpdHRlZCBmb3Jlc3QpLiBUaGUgbGFyZ2VyIHRoZSBkaWZmZXJlbmNlIGluIGxvY2FsIHN0YWJpbGl0eSBpbXBvcnRhbmNlIHNjb3JlcyBiZXR3ZWVuIHRob3NlIHdpdGggaGlnaCB2ZXJzdXMgbG93IExWTWksIHRoZSBncmVhdGVyIHRoZSBpbXBvcnRhbmNlIG9mIHRoZSBsb2N1cy9pbnRlcmFjdGlvbiBmb3IgcHJlZGljdGluZyBMVk1pLiBGb3IgZGV0YWlscyBvbiB0aGUgbmV3IGltcG9ydGFuY2Ugc2NvcmUsIHdlIHJlZmVyIHRvIFtAd2FuZzIwMjNlcGlzdGFzaXNdKCkuCgpCZWxvdywgd2UgcmVjYXAgdGhlIHNpUkYgcHJlZGljdGlvbiBhY2N1cmFjeSBmb3IgcHJlZGljdGluZyB0aGUgYmluYXJpemVkIExWTWkgYWNyb3NzIHRoZSB0aHJlZSBiaW5hcml6YXRpb24gdGhyZXNob2xkcyAoMTVcJSwgMjBcJSwgMjVcJSkgKEZpZ3VyZSBcQHJlZihmaWc6c3ViY2h1bmstNTgpKS4gVGhlbiwgaW4gRmlndXJlIFxAcmVmKGZpZzpzdWJjaHVuay01OSksIHdlIHN1bW1hcml6ZSB0aGUgcHJpb3JpdGl6YXRpb24gcmFua2luZ3Mgb2YgZ2VuZXRpYyBsb2NpIGFuZCBpbnRlcmFjdGlvbiBiZXR3ZWVuIGxvY2kgYWNjb3JkaW5nIHRvIHRoZSBuZXcgaW1wb3J0YW5jZSBzY29yZS4gV2UgcHJvdmlkZSB0aGUgcGVybXV0YXRpb24gcC12YWx1ZXMgYWxvbmcgd2l0aCB0aGUgcGVybXV0YXRpb24gdGVzdCBzdGF0aXN0aWMsIHRoYXQgaXMsIHRoZSBkaWZmZXJlbmNlIGluIGxvY2FsIGZlYXR1cmUgc3RhYmlsaXR5IHNjb3JlcyBiZXR3ZWVuIHRoZSBoaWdoIGFuZCBsb3cgTFZNaSBncm91cHMsIHdpdGggdGhlIHN0YW5kYXJkIGRldmlhdGlvbiBvZiB0aGlzIHBlcm11dGF0aW9uIGRpc3RyaWJ1dGlvbiBpbiBwYXJlbnRoZXNlcy4gCgpOb3RlIHRoYXQgdGhlIHBlcm11dGF0aW9uIHRlc3Qgd2FzIG5vdCBwZXJmb3JtZWQgZm9yIGFsbCBsb2NpL2ludGVyYWN0aW9ucyAoZGV0YWlscyBpbiBbQHdhbmcyMDIzZXBpc3Rhc2lzXSgpKS4gR2l2ZW4gb3VyIHByaW1hcnkgYWltIG9mIGdlbmVyYXRpbmcgcmVsaWFibGUgaHlwb3RoZXNlcyBmb3IgZm9sbG93LXVwIGV4cGVyaW1lbnRhbCB2YWxpZGF0aW9uLCB3ZSBjaG9zZSB0byBvbmx5IHRlc3QgbG9jaS9pbnRlcmFjdGlvbnMgdGhhdCB3ZXJlICpwcmVkaWN0aXZlKiBhbmQgKnN0YWJsZSogaW4gdGhlIHNpUkYgZml0LCBmb2xsb3dpbmcgdGhlIFBDUyBmcmFtZXdvcmsgZm9yIHZlcmlkaWNhbCBkYXRhIHNjaWVuY2UgW0B5dTIwMjB2ZXJpZGljYWxdLiBTcGVjaWZpY2FsbHksIGZvciBlYWNoIGJpbmFyaXphdGlvbiB0aHJlc2hvbGQsIHdlIG9ubHkgdGVzdGVkOgoKLSB0aGUgdG9wIDI1IGxvY2kgd2l0aCB0aGUgaGlnaGVzdCBhdmVyYWdlIGxvY2FsIHN0YWJpbGl0eSBpbXBvcnRhbmNlIHNjb3Jlcywgb3IgaW4gb3RoZXIgd29yZHMsIHRob3NlIHRoYXQgb2NjdXJyZWQgbW9zdCBzdGFibHkvZnJlcXVlbnRseSAoYW5kIHRodXMgbGlrZWx5IHByZWRpY3RpdmUpIGluIHRoZSBzaVJGIGZpdCwgYW5kCi0gdGhlIGludGVyYWN0aW9ucyBiZXR3ZWVuIGxvY2kgdGhhdCB3ZXJlIGlkZW50aWZpZWQgYnkgc2lSRiBhbmQgYWNoaWV2ZWQgYSBzdGFiaWxpdHkgc2NvcmUgPiAwLjUsIHN0YWJpbGl0eSBzY29yZSBmb3IgbWVhbiBpbmNyZWFzZSBpbiBwcmVjaXNpb24gPiAwLCBhbmQgc3RhYmlsaXR5IHNjb3JlIGZvciBpbmRlcGVuZGVuY2Ugb2YgZmVhdHVyZSBzZWxlY3Rpb24gPiAwLiBXZSBub3RlIHRoYXQgaW4gYWRkaXRpb24gdG8gdGhlIGV4cGxpY2l0IHN0YWJpbGl0eSBjaGVja3MgaGVyZSwgdGhlIHJlcXVpcmVtZW50IG9uIHRoZSBtZWFuIGluY3JlYXNlIGluIHByZWNpc2lvbiBzZXJ2ZXMgYXMgYSBwcmVkaWN0YWJpbGl0eSBjaGVjaywgYW5kIHRoZSByZXF1aXJlbWVudCBvbiB0aGUgaW5kZXBlbmRlbmNlIG9mIGZlYXR1cmUgc2VsZWN0aW9uIHNlcnZlcyB0byBkaWZmZXJlbnRpYXRlIG1hcmdpbmFsIGFkZGl0aXZlIGVmZmVjdHMgZnJvbSBub24tYWRkaXRpdmUgaW50ZXJhY3Rpb24gZWZmZWN0cyAoc2VlIEBrdW1iaWVyMjAxOHJlZmluaW5nIGZvciBkZXRhaWxzKS4KCkJ5IGltcGxlbWVudGluZyB0aGlzIGFkZGl0aW9uYWwgcHJlZGljdGFiaWxpdHkgYW5kIHN0YWJpbGl0eSBjaGVjaywgd2UgYXJlIHJlcXVpcmluZyB0aGF0IHRoZSBwcmlvcml0aXplZCBsb2NpL2ludGVyYWN0aW9ucyBtZWV0IGEgaGlnaGVyIHN0YW5kYXJkLCB3aXRoIHRoZSBob3BlIHRoYXQgdGhpcyB1bHRpbWF0ZWx5IGdlbmVyYXRlcyBtb3JlIHJlbGlhYmxlIChhbGJlaXQgbW9yZSBjb25zZXJ2YXRpdmUpIGV4cGVyaW1lbnRhbCByZWNvbW1lbmRhdGlvbnMuCgpJbiBhZGRpdGlvbiB0byB0aGUgcHJvdmlkZWQgc3VtbWFyeSBvZiByZXN1bHRzLAoKLSBVbmRlciB0aGUgYHNpUkYgSW50ZXJhY3Rpb24gVGFibGVgIHRhYiwgd2UgcHJvdmlkZSB0aGUgZnVsbCBzaVJGIGxvY3VzLWxldmVsIGludGVyYWN0aW9uIHRhYmxlIG91dHB1dCBmb3IgZWFjaCBiaW5hcml6YXRpb24gdGhyZXNob2xkIChGaWd1cmVzIFxAcmVmKGZpZzpzdWJjaHVuay02MCksIFxAcmVmKGZpZzpzdWJjaHVuay02MiksIGFuZCBcQHJlZihmaWc6c3ViY2h1bmstNjQpKS4gVGhpcyB0YWJsZSBpbmNsdWRlcyBzZXZlcmFsIG1ldHJpY3MgZm9yIGV2YWx1YXRpbmcgdGhlIHN0YWJpbGl0eSBhbmQgc3RyZW5ndGggb2YgdGhlIGludGVyYWN0aW9uLiBGb3IgZGV0YWlscyBvbiB0aGVzZSBtZXRyaWNzLCB3ZSByZWZlciB0byBAa3VtYmllcjIwMThyZWZpbmluZy4KICAtIEZvciBjb21wYXJpc29uLCB3ZSBhbHNvIHByb3ZpZGUgdGhlIGFuYWxvZ291cyBzaVJGIG91dHB1dCBmb3IgaW50ZXJhY3Rpb25zIGF0IHRoZSBTTlYgbGV2ZWwgKEZpZ3VyZXMgXEByZWYoZmlnOnN1YmNodW5rLTYxKSwgXEByZWYoZmlnOnN1YmNodW5rLTYzKSwgYW5kIFxAcmVmKGZpZzpzdWJjaHVuay02NSkpLiBIZXJlLCB3ZSBzZWUgdGhhdCBpZiB3ZSBkbyBub3QgcGVyZm9ybSB0aGUgU05WLXRvLWxvY3VzIGFnZ3JlZ2F0aW9uLCB0aGUgc3RhYmlsaXR5IHNjb3JlcyBmb3IgdGhlIFNOVi1sZXZlbCBpbnRlcmFjdGlvbnMgYXJlIHZlcnkgY2xvc2UgdG8gMC4gVGhpcyBtZWFucyB0aGF0IHRoZSBzaVJGLWlkZW50aWZpZWQgU05WLWxldmVsIGludGVyYWN0aW9ucyByYXJlbHkgYXBwZWFyIHdoZW4gc2lSRiBpcyByZWZpdHRlZCB1c2luZyBkaWZmZXJlbnQgYm9vdHN0cmFwcGVkIHRyYWluaW5nIHNhbXBsZXMuIEFzIGRpc2N1c3NlZCBwcmV2aW91c2x5LCB0aGlzIGluc3RhYmlsaXR5IGlzIHBhcnRpYWxseSBkdWUgdG8gdGhlIGNvcnJlbGF0aW9uIGFtb25nIFNOVnMgYW5kIHRoZSB3ZWFrIHBoZW5vdHlwaWMgc2lnbmFsLiBUaGlzIGhpZ2ggaW5zdGFiaWxpdHkgYWxzbyBtb3RpdmF0ZXMgdGhlIG5lZWQgZm9yIGFuIGFsdGVybmF0aXZlIGFwcHJvYWNoIHZpYSBvdXIgbmV3IGltcG9ydGFuY2Ugc2NvcmUuCi0gVW5kZXIgdGhlIGBMb2NhbCBTdGFiaWxpdHkgSW1wb3J0YW5jZSBQbG90cyAtIEludGVyYWN0aW9uc2AgYW5kIGBMb2NhbCBTdGFiaWxpdHkgSW1wb3J0YW5jZSBQbG90cyAtIExvY2lgLCB3ZSBwcm92aWRlIHZpc3VhbGl6YXRpb25zIG9mIHRoZSBkZW5zaXR5IGRpc3RyaWJ1dGlvbiBvZiBsb2NhbCBzdGFiaWxpdHkgaW1wb3J0YW5jZSBzY29yZXMgYmV0d2VlbiB0aGUgbG93IGFuZCBoaWdoIExWTWkgZ3JvdXBzIGFzIHdlbGwgYXMgdGhlIGZyZXF1ZW5jeSBkaXN0cmlidXRpb24gb2YgU05WcyB1c2VkIGluIHRoZSBzaVJGIGZpdCAoaS5lLiwgd2hpY2ggU05WcyBvY2N1cnJlZCBtb3N0IGZyZXF1ZW50bHkgaW4gdGhlIGRlY2lzaW9uIHBhdGhzIGFjcm9zcyB0aGUgc2lSRiBmaXQpLgogIC0gSW4gdGhlIGRlbnNpdHkgZGlzdHJpYnV0aW9uIG9mIGxvY2FsIHN0YWJpbGl0eSBpbXBvcnRhbmNlIHNjb3Jlcywgb2JzZXJ2YWJsZSBkaWZmZXJlbmNlcyBiZXR3ZWVuIHRoZSBsb3cgYW5kIGhpZ2ggTFZNaSBncm91cHMgYXJlIGV2aWRlbmNlIHRoYXQgdGhlIGdlbmV0aWMgbG9jdXMgb3IgaW50ZXJhY3Rpb24gYmV0d2VlbiBsb2NpIGlzIGltcG9ydGFudCBmb3IgZGlmZmVyZW50aWF0aW5nIGJldHdlZW4gaW5kaXZpZHVhbHMgd2l0aCBoaWdoIHZlcnN1cyBsb3cgTFZNaS4gVGhlIGxhcmdlciB0aGUgZGlmZmVyZW5jZSwgdGhlIGdyZWF0ZXIgdGhlIGltcG9ydGFuY2Ugb2YgdGhlIGxvY3VzIG9yIGludGVyYWN0aW9uIGJldHdlZW4gbG9jaS4KICAtIEluIHRoZSBTTlYgZnJlcXVlbmN5IGRpc3RyaWJ1dGlvbnMsIHdlIHNob3cgdGhlIGZyZXF1ZW5jeSBvZiBvY2N1cnJlbmNlIGZvciBlYWNoIFNOViBvciBTTlYgcGFpciBpbiB0aGUgc2lSRiBmaXQuIFRoaXMgaXMgdGhlIG51bWJlciBvZiBkZWNpc2lvbiBwYXRocyBmb3Igd2hpY2ggdGhlIFNOViBvciBTTlYgcGFpciBhcHBlYXJlZCBpbiB0aGUgc2lSRiBmaXQuIFNOVnMgb3IgU05WIHBhaXJzIHdpdGggdGhlIGhpZ2hlc3QgbnVtYmVyIG9mIG9jY3VycmVuY2VzIGluIHRoZSBSRiBkZWNpc2lvbiBwYXRocyAoeS1heGlzKSBjb250cmlidXRlZCB0aGUgbW9zdCB0byB0aGUgb3ZlcmFsbCBsb2N1cy9pbnRlcmFjdGlvbidzIGltcG9ydGFuY2UgaW4gdGhlIHNpUkYgZml0LgoKPC9kaXY+CgoKYGBge3IgaXJmLXJlc3VsdHMsIHJlc3VsdHMgPSAiYXNpcyJ9CgojIHBoZW5vdHlwZV9oZWFkZXIgPC0gIlxuXG4jIyMgJXMgey51bm51bWJlcmVkIC50YWJzZXQgLnRhYnNldC1waWxscyAudGFic2V0LWZhZGUgLnRhYnNldC1jaXJjbGV9IFxuXG4iCnNlY3Rpb25faGVhZGVyIDwtICJcblxuIyMjICVzIHsudW5udW1iZXJlZCAudGFic2V0IC50YWJzZXQtcGlsbHMgLnRhYnNldC1mYWRlIC50YWJzZXQtY2lyY2xlfSBcblxuIgp0aHJfaGVhZGVyIDwtICJcblxuIyMjIyAlcyB7LnVubnVtYmVyZWQgLnRhYnNldCAudGFic2V0LXBpbGxzIC50YWJzZXQtZmFkZX0gXG5cbiIKIyBzdWJzZWN0aW9uX2hlYWRlciA8LSAiXG5cbiMjIyMjICVzIHsudW5udW1iZXJlZCAudGFic2V0IC50YWJzZXQtcGlsbHMgLnRhYnNldC1mYWRlIC50YWJzZXQtY2lyY2xlfSBcblxuIgojIHN1YnN1YnNlY3Rpb25faGVhZGVyIDwtICJcblxuIyMjIyMjIyAlcyB7LnVubnVtYmVyZWR9IFxuXG4iCgpESVNUX0hFSUdIVCA8LSA4CkhFQVRNQVBfSEVJR0hUIDwtIDgKRVBJX0hFSUdIVCA8LSA4CklURVIgPC0gMwpMRUZUX01BUkdJTiA8LSA1CgppZiAocGFyYW1zJGV2YWwpIHsKICBmb3IgKHBoZW5vdHlwZSBpbiBwaGVub3R5cGVzKSB7CiAgICBwcmludChwaGVub3R5cGUpCiAgICBldmFsX2xzIDwtIGxpc3QoKQogICAgaW50X3Jlc3VsdHNfbHMgPC0gbGlzdCgpCiAgICBnZW5lX3Jlc3VsdHNfbHMgPC0gbGlzdCgpCiAgICBmb3IgKHRociBpbiBjKDAuMTUsIDAuMiwgMC4yNSkpIHsKICAgICAgcHJpbnQodGhyKQogICAgICBmcGF0aCA8LSBmaWxlLnBhdGgocmVzX2RpciwgcGFzdGUwKHBoZW5vdHlwZSwgIl9iaW5hcnlfdGhyIiwgdGhyLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJfZ3dhc19maWx0ZXJlZF9uc25wczEwMDAiKSkKICAgICAgIyA+IG91dCwgeWhhdF90cjIsIHloYXRfdmEsIGlyZl9nZW5lX291dCwgc25wcy5kZiwgaXJmX3Nudl9pbnRfb3V0CiAgICAgIGxvYWQoZmlsZS5wYXRoKGZwYXRoLCAiaXJmX2ludGVyYWN0aW9uX2ZpdC5SZGF0YSIpKSAgCiAgICAgIHlfdGVzdCA8LSBpZmVsc2Uob3V0JHBoZW5vLnRlc3QgPT0gMCwgIkxvdyBMVk1pIiwgIkhpZ2ggTFZNaSIpCgogICAgICAjIHByZWRpY3Rpb24gcmVzdWx0cwogICAgICBldmFsX291dCA8LSBiaW5kX3Jvd3MoCiAgICAgICAgZXZhbFByZWRzKHkgPSBvdXQkcGhlbm8udGVzdCwgeWhhdCA9IHloYXRfdmEsIG1ldHJpYyA9IGMoIkFVQyIsICJQUiIpKSwKICAgICAgICBldmFsUHJlZHMoeSA9IG91dCRwaGVuby50ZXN0LCB5aGF0ID0gcm91bmQoeWhhdF92YSksIG1ldHJpYyA9IGMoIkNsYXNzIikpCiAgICAgICkgJT4lCiAgICAgICAgc3ByZWFkKGtleSA9ICJNZXRyaWMiLCB2YWx1ZSA9ICJWYWx1ZSIpCiAgICAgIGV2YWxfbHNbW2FzLmNoYXJhY3Rlcih0aHIpXV0gPC0gZXZhbF9vdXQKICAgIAogICAgICAjIGxvY2FsIGludGVyYWN0aW9uIHN0YWJpbGl0eSByZXN1bHRzCiAgICAgIGxvYWQoZmlsZS5wYXRoKGZwYXRoLCAibG9jYWxfaW50ZXJhY3Rpb25fc3RhYmlsaXR5X3Jlc3VsdHMuUmRhdGEiKSkKICAgICAgaW50X291dCA8LSBsaXN0KAogICAgICAgIHN0YWJfdHIyX2xzID0gaW50X3N0YWJfdHIyX2xzLAogICAgICAgIHN0YWJfdmFfbHMgPSBpbnRfc3RhYl92YV9scywKICAgICAgICB0ZXN0X2ludHNfbHMgPSB0ZXN0X2ludHNfbHMsCiAgICAgICAgcGVybV9vdXRfbHMgPSBpbnRfcGVybV9vdXRfbHMKICAgICAgKQogICAgICBpbnRfcmVzdWx0c19sc1tbYXMuY2hhcmFjdGVyKHRocildXSA8LSBpbnRfcGVybV9vdXRfbHMKICAgICAgCiAgICAgIGludF9hbGxfb3V0IDwtIGxpc3QoYFVzaW5nIGFsbCBzcGxpdHNgID0gaW50X291dCkKICAgICAgCiAgICAgIHB2YWxfaW50IDwtIG1hcF9kZnIoaW50X291dCRwZXJtX291dF9sc1tbSVRFUl1dLAogICAgICAgICAgICAgICAgICAgICAgICAgIGZ1bmN0aW9uKHgpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRhdGEuZnJhbWUocHZhbCA9IHgkcHZhbCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2hlY2submFtZXMgPSBGQUxTRSkKICAgICAgICAgICAgICAgICAgICAgICAgICB9LCAuaWQgPSAiaW50IikgJT4lCiAgICAgICAgZHBseXI6Om11dGF0ZSgKICAgICAgICAgIHB2YWxfc3RyID0gZHBseXI6OmNhc2Vfd2hlbigKICAgICAgICAgICAgcHZhbCA8IDFlLTQgfiAiPCAxMDxzdXA+LTQ8L3N1cD4iLAogICAgICAgICAgICBwdmFsIDwgMWUtMyB+ICI8IDEwPHN1cD4tMzwvc3VwPiIsCiAgICAgICAgICAgIFRSVUUgfiBzcHJpbnRmKCIlcyIsIGZvcm1hdEMocHZhbCwgZGlnaXRzID0gMywgZm9ybWF0ID0gImYiKSkKICAgICAgICAgICkKICAgICAgICApCiAgICAgIAogICAgICBzdHlsZV9uYW1lc19iYXNpYyA8LSBmdW5jdGlvbih4LCBpdGFsaWMgPSBUUlVFKSB7CiAgICAgICAgeCA8LSB4ICU+JQogICAgICAgICAgc3RyaW5ncjo6c3RyX3JlcGxhY2VfYWxsKCItXyIsICI8c3VwPiYjODIxMTs8L3N1cD4mIzgyMTE7IikgJT4lCiAgICAgICAgICBzdHJpbmdyOjpzdHJfcmVwbGFjZV9hbGwoIlxcK18iLCAiPHN1cD4rPC9zdXA+JiM4MjExOyIpICU+JQogICAgICAgICAgc3RyaW5ncjo6c3RyX3JlcGxhY2VfYWxsKCItJCIsICI8c3VwPiYjODIxMTs8L3N1cD4iKSAlPiUKICAgICAgICAgIHN0cmluZ3I6OnN0cl9yZXBsYWNlX2FsbCgiXFwrJCIsICI8c3VwPis8L3N1cD4iKSAlPiUKICAgICAgICAgIGthYmxlRXh0cmE6OmNlbGxfc3BlYyhlc2NhcGUgPSBGQUxTRSwgaXRhbGljID0gaXRhbGljKQogICAgICAgIHJldHVybih4KQogICAgICB9CgogICAgICAjIGlSRiByZXN1bHRzCiAgICAgIHRhYl9vdXQgPC0gaXJmX2dlbmVfb3V0JGludGVyYWN0aW9uW1tJVEVSXV0gJT4lCiAgICAgICAgbGVmdF9qb2luKHkgPSBwdmFsX2ludCwgYnkgPSAiaW50IikgJT4lCiAgICAgICAgZHBseXI6OmFycmFuZ2UocHZhbCkgJT4lCiAgICAgICAgZHBseXI6OnNlbGVjdCgtcHZhbCkgJT4lCiAgICAgICAgZHBseXI6OnJlbmFtZSgKICAgICAgICAgICJJbnRlcmFjdGlvbiIgPSAiaW50IiwKICAgICAgICAgICJQcmV2YWxlbmNlIiA9ICJwcmV2YWxlbmNlIiwKICAgICAgICAgICJQcmVjaXNpb24iID0gInByZWNpc2lvbiIsCiAgICAgICAgICAiQ2xhc3MgRGlmZmVyZW5jZSBpbiBQcmV2YWxlbmNlIiA9ICJjcGUiLAogICAgICAgICAgIlN0YWJpbGl0eSBvZiBDbGFzcyBEaWZmZXJlbmNlIGluIFByZXZhbGVuY2UiID0gInN0YS5jcGUiLAogICAgICAgICAgIkluZGVwZW5kZW5jZSBvZiBGZWF0dXJlIFNlbGVjdGlvbiIgPSAiZnNkIiwKICAgICAgICAgICJTdGFiaWxpdHkgb2YgSW5kZXBlbmRlbmNlIG9mIEZlYXR1cmUgU2VsZWN0aW9uIiA9ICJzdGEuZnNkIiwKICAgICAgICAgICJJbmNyZWFzZSBpbiBQcmVjaXNpb24iID0gIm1pcCIsCiAgICAgICAgICAiU3RhYmlsaXR5IG9mIEluY3JlYXNlIGluIFByZWNpc2lvbiIgPSAic3RhLm1pcCIsCiAgICAgICAgICAiU3RhYmlsaXR5IiA9ICJzdGFiaWxpdHkiLAogICAgICAgICAgImxvLXNpUkYgTWVhbiBQZXJtdXRhdGlvbiBwLXZhbHVlIiA9ICJwdmFsX3N0ciIKICAgICAgICApICU+JQogICAgICAgIGRwbHlyOjptdXRhdGUoSW50ZXJhY3Rpb24gPSBzdHlsZV9uYW1lc19iYXNpYyhJbnRlcmFjdGlvbikpCiAgICAgIHRhYiA8LSBwcmV0dHlfRFQodGFiX291dCwgZGlnaXRzID0gMywgc2lnZmlnID0gVFJVRSwgcm93bmFtZXMgPSBGQUxTRSwKICAgICAgICAgICAgICAgICAgICAgICBuYV9kaXNwID0gIi0tIikKICAgICAgc2F2ZVJEUyh0YWIsCiAgICAgICAgICAgICAgZmlsZS5wYXRoKHRhYl9yZXNfZGlyLAogICAgICAgICAgICAgICAgICAgICAgICBwYXN0ZTAocGhlbm90eXBlLCAiX3RociIsIHRociwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJfaXJmX2ludGVyYWN0aW9uX3Jlc3VsdHMucmRzIikpKQogICAgICAKICAgICAgIyBpUkYgcmVzdWx0cyAtIFNOViBsZXZlbAogICAgICB0YWJfb3V0IDwtIGlyZl9zbnZfaW50X291dCAlPiUKICAgICAgICBkcGx5cjo6bXV0YXRlKGludCA9IHN0cmluZ3I6OnN0cl9yZW1vdmVfYWxsKGludCwgIlswLTldKmNoIikpICU+JQogICAgICAgIGRwbHlyOjphcnJhbmdlKC1zdGFiaWxpdHkpICU+JQogICAgICAgIGRwbHlyOjpyZW5hbWUoCiAgICAgICAgICAiSW50ZXJhY3Rpb24iID0gImludCIsCiAgICAgICAgICAiUHJldmFsZW5jZSIgPSAicHJldmFsZW5jZSIsCiAgICAgICAgICAiUHJlY2lzaW9uIiA9ICJwcmVjaXNpb24iLAogICAgICAgICAgIkNsYXNzIERpZmZlcmVuY2UgaW4gUHJldmFsZW5jZSIgPSAiY3BlIiwKICAgICAgICAgICJTdGFiaWxpdHkgb2YgQ2xhc3MgRGlmZmVyZW5jZSBpbiBQcmV2YWxlbmNlIiA9ICJzdGEuY3BlIiwKICAgICAgICAgICJJbmRlcGVuZGVuY2Ugb2YgRmVhdHVyZSBTZWxlY3Rpb24iID0gImZzZCIsCiAgICAgICAgICAiU3RhYmlsaXR5IG9mIEluZGVwZW5kZW5jZSBvZiBGZWF0dXJlIFNlbGVjdGlvbiIgPSAic3RhLmZzZCIsCiAgICAgICAgICAiSW5jcmVhc2UgaW4gUHJlY2lzaW9uIiA9ICJtaXAiLAogICAgICAgICAgIlN0YWJpbGl0eSBvZiBJbmNyZWFzZSBpbiBQcmVjaXNpb24iID0gInN0YS5taXAiLAogICAgICAgICAgIlN0YWJpbGl0eSIgPSAic3RhYmlsaXR5IgogICAgICAgICkgJT4lCiAgICAgICAgZHBseXI6Om11dGF0ZSgKICAgICAgICAgIEludGVyYWN0aW9uID0gc3R5bGVfbmFtZXNfYmFzaWMoSW50ZXJhY3Rpb24sIGl0YWxpYyA9IEZBTFNFKQogICAgICAgICkKICAgICAgdGFiIDwtIHByZXR0eV9EVCh0YWJfb3V0LCBkaWdpdHMgPSAzLCBzaWdmaWcgPSBUUlVFLCByb3duYW1lcyA9IEZBTFNFKQogICAgICBzYXZlUkRTKHRhYiwgCiAgICAgICAgICAgICAgZmlsZS5wYXRoKHRhYl9yZXNfZGlyLCAKICAgICAgICAgICAgICAgICAgICAgICAgcGFzdGUwKHBoZW5vdHlwZSwgIl90aHIiLCB0aHIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIl9pcmZfc252X2ludGVyYWN0aW9uX3Jlc3VsdHMucmRzIikpKQogICAgICAKICAgICAgZm9yICh0eXBlIGluIG5hbWVzKGludF9hbGxfb3V0KSkgewogICAgICAgIHByaW50KHR5cGUpCiAgICAgICAgIyBoZWF0bWFwCiAgICAgICAgcGx0IDwtIHBsb3RfaGNsdXN0X2hlYXRtYXAoaW50X2FsbF9vdXRbW3R5cGVdXSRzdGFiX3ZhX2xzW1tJVEVSXV0sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgeV9ncm91cHMgPSB5X3Rlc3QsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2x1c3RfeV93aV9ncm91cCA9IEZBTFNFKSArCiAgICAgICAgICBsYWJzKHggPSAiSW50ZXJhY3Rpb24iLCB5ID0gIlBhdGllbnRzIiwKICAgICAgICAgICAgICAgZmlsbCA9ICJMb2NhbFxuU3RhYmlsaXR5XG5TY29yZSIpICsKICAgICAgICAgIHZ0aGVtZXM6OnRoZW1lX3Ztb2Rlcm4oc2l6ZV9wcmVzZXQgPSAibWVkaXVtIikgKwogICAgICAgICAgdGhlbWUoYXhpcy50ZXh0LnkgPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgICAgICAgICBheGlzLnRpY2tzLnkgPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgICAgICAgICBheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDkwLCBoanVzdCA9IDEsIHZqdXN0ID0gMC41KSkKICAgICAgICBzYXZlUkRTKHBsdCwKICAgICAgICAgICAgICAgIGZpbGUucGF0aChmaWdfcmVzX2RpciwKICAgICAgICAgICAgICAgICAgICAgICAgICBwYXN0ZTAocGhlbm90eXBlLCAiX3RociIsIHRociwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIl9pbnRfbG9jYWxfc3RhYmlsaXR5X2hlYXRtYXBfIiwgdHlwZSwgIi5yZHMiKSkpCgogICAgICAgICMgZGlzdHJpYnV0aW9uIHBsb3RzCiAgICAgICAgaW50X3B2YWxzIDwtIG1hcF9kZnIoaW50X2FsbF9vdXRbW3R5cGVdXSRwZXJtX291dF9sc1tbSVRFUl1dLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIH5kYXRhLmZyYW1lKHB2YWwgPSAueCRwdmFsKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAuaWQgPSAiaW50IikgJT4lCiAgICAgICAgICBhcnJhbmdlKHB2YWwpICU+JQogICAgICAgICAgZHBseXI6Om11dGF0ZSgKICAgICAgICAgICAgcHZhbF9zdHIgPSBkcGx5cjo6Y2FzZV93aGVuKAogICAgICAgICAgICAgIHB2YWwgPCAxZS00IH4gInAgPCAxMF4tNCIsCiAgICAgICAgICAgICAgcHZhbCA8IDFlLTMgfiAicCA8IDEwXi0zIiwKICAgICAgICAgICAgICAjIHB2YWwgPCAxZS00IH4gInAgPCAxMDxzdXA+LTQ8L3N1cD4iLAogICAgICAgICAgICAgICMgcHZhbCA8IDFlLTMgfiAicCA8IDEwPHN1cD4tMzwvc3VwPiIsCiAgICAgICAgICAgICAgVFJVRSB+IHNwcmludGYoInB+YD1gfiVzIiwgZm9ybWF0QyhwdmFsLCBkaWdpdHMgPSAzLCBmb3JtYXQgPSAiZiIpKQogICAgICAgICAgICApCiAgICAgICAgICApICU+JQogICAgICAgICAgbXV0YXRlKGludF9wdmFsID0gc3ByaW50ZigiJXMgKCVzKSIsIGludCwgcHZhbF9zdHIpKQogICAgICAgIHBsdF9kZiA8LSBpbnRfYWxsX291dFtbdHlwZV1dJHN0YWJfdmFfbHNbW0lURVJdXSAlPiUKICAgICAgICAgIGJpbmRfY29scyh5ID0geV90ZXN0KSAlPiUKICAgICAgICAgIGdhdGhlcihrZXkgPSAiaW50IiwgdmFsdWUgPSAiU3RhYmlsaXR5IiwgLXkpICU+JQogICAgICAgICAgbGVmdF9qb2luKHkgPSBpbnRfcHZhbHMsIGJ5ID0gImludCIpICU+JQogICAgICAgICAgIyBtdXRhdGUoaW50ID0gcGFzdGUwKGludCwgIiAocCA9ICIsIGZvcm1hdEMocHZhbCwgMywgZm9ybWF0ID0gImciKSwgIikiKSkgJT4lCiAgICAgICAgICBtdXRhdGUoaW50ID0gZmFjdG9yKGludCwgbGV2ZWxzID0gaW50X3B2YWxzJGludCkpCiAgICAgICAgcGx0IDwtIHBsb3RfZGVuc2l0eShkYXRhID0gcGx0X2RmLCB4X3N0ciA9ICJTdGFiaWxpdHkiLCBmaWxsX3N0ciA9ICJ5IikgKwogICAgICAgICAgZmFjZXRfd3JhcCh+IGludCwgc2NhbGVzID0gImZyZWUiLCBuY29sID0gMykgKwogICAgICAgICAgZ2dwbG90Mjo6bGFicyh4ID0gIkxvY2FsIFN0YWJpbGl0eSBJbXBvcnRhbmNlIFNjb3JlIiwgZmlsbCA9ICIiKSArCiAgICAgICAgICBnZ3Bsb3QyOjpnZW9tX3RleHQoCiAgICAgICAgICAgIGdncGxvdDI6OmFlcyh4ID0gSW5mLCB5ID0gSW5mLCBoanVzdCA9IDEuMSwgdmp1c3QgPSAxLjUsIGxhYmVsID0gcHZhbF9zdHIpLAogICAgICAgICAgICBkYXRhID0gcGx0X2RmICU+JSBkcGx5cjo6ZGlzdGluY3QoaW50LCAua2VlcF9hbGwgPSBUUlVFKSwKICAgICAgICAgICAgcGFyc2UgPSBUUlVFCiAgICAgICAgICApICsKICAgICAgICAgIGdncGxvdDI6OnRoZW1lKGF4aXMudGl0bGUgPSBnZ3Bsb3QyOjplbGVtZW50X3RleHQoc2l6ZSA9IDE0KSkKICAgICAgICBzYXZlUkRTKHBsdCwKICAgICAgICAgICAgICAgIGZpbGUucGF0aChmaWdfcmVzX2RpciwKICAgICAgICAgICAgICAgICAgICAgICAgICBwYXN0ZTAocGhlbm90eXBlLCAiX3RociIsIHRociwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIl9pbnRfbG9jYWxfc3RhYmlsaXR5X2Rpc3RfIiwgdHlwZSwgIi5yZHMiKSkpCgogICAgICAgICMgaW5kaXZpZHVhbCBzbnAgcGxvdHMKICAgICAgICBwbHQgPC0gcGxvdFJGU25wSW50RGlzdCgKICAgICAgICAgIGlyZl9nZW5lX291dCRyZi5saXN0W1tJVEVSXV0sIHNucHMuZGYsIGludF9wdmFscyRpbnQsIHByb3AgPSBUUlVFCiAgICAgICAgKSArCiAgICAgICAgICBnZ3Bsb3QyOjpsYWJzKHggPSAiU05WLVNOViBQYWlyIikKICAgICAgICBzYXZlUkRTKHBsdCwKICAgICAgICAgICAgICAgIGZpbGUucGF0aChmaWdfcmVzX2RpciwKICAgICAgICAgICAgICAgICAgICAgICAgICBwYXN0ZTAocGhlbm90eXBlLCAiX3RociIsIHRociwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIl9pbnRfbG9jYWxfc3RhYmlsaXR5X3NucF9kaXN0XyIsIHR5cGUsICIucmRzIikpKQogICAgICB9CgogICAgICAjIGxvY2FsIGZlYXR1cmUgc3RhYmlsaXR5IHJlc3VsdHMKICAgICAgbG9hZChmaWxlLnBhdGgoZnBhdGgsICJsb2NhbF9mZWF0dXJlX3N0YWJpbGl0eV9yZXN1bHRzLlJkYXRhIikpCiAgICAgIHN0YWJfb3V0IDwtIGxpc3QoCiAgICAgICAgc3RhYl90cjJfbHMgPSBzdGFiX3RyMl9scywKICAgICAgICBzdGFiX3ZhX2xzID0gc3RhYl92YV9scywKICAgICAgICB0ZXN0X2dlbmVzX2xzID0gdGVzdF9nZW5lc19scywKICAgICAgICBwZXJtX291dF9scyA9IHBlcm1fb3V0X2xzCiAgICAgICkKICAgICAgZ2VuZV9yZXN1bHRzX2xzW1thcy5jaGFyYWN0ZXIodGhyKV1dIDwtIHBlcm1fb3V0X2xzCgogICAgICBzdGFiX2FsbF9vdXQgPC0gbGlzdChgVXNpbmcgYWxsIHNwbGl0c2AgPSBzdGFiX291dCkKCiAgICAgIGZvciAodHlwZSBpbiBuYW1lcyhpbnRfYWxsX291dCkpIHsKICAgICAgICBwcmludCh0eXBlKQogICAgICAgIHN0YWJfZGYgPC0gc3RhYl9hbGxfb3V0W1t0eXBlXV0kc3RhYl92YV9sc1tbSVRFUl1dICU+JQogICAgICAgICAgc2VsZWN0KGFsbF9vZihzdGFiX2FsbF9vdXRbW3R5cGVdXSR0ZXN0X2dlbmVzX2xzW1tJVEVSXV0pKQoKICAgICAgICAjIGhlYXRtYXAKICAgICAgICBwbHQgPC0gcGxvdF9oY2x1c3RfaGVhdG1hcChzdGFiX2RmLCB5X2dyb3VwcyA9IHlfdGVzdCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjbHVzdF95X3dpX2dyb3VwID0gRkFMU0UpICsKICAgICAgICAgIGxhYnMoeCA9ICJGZWF0dXJlIiwgeSA9ICJQYXRpZW50cyIsCiAgICAgICAgICAgICAgIGZpbGwgPSAiTG9jYWxcblN0YWJpbGl0eVxuU2NvcmUiKSArCiAgICAgICAgICB2dGhlbWVzOjp0aGVtZV92bW9kZXJuKHNpemVfcHJlc2V0ID0gIm1lZGl1bSIpICsKICAgICAgICAgIHRoZW1lKGF4aXMudGV4dC55ID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgICAgICAgICAgYXhpcy50aWNrcy55ID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgICAgICAgICAgYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA5MCwgaGp1c3QgPSAxLCB2anVzdCA9IDAuNSkpCiAgICAgICAgc2F2ZVJEUyhwbHQsCiAgICAgICAgICAgICAgICBmaWxlLnBhdGgoZmlnX3Jlc19kaXIsCiAgICAgICAgICAgICAgICAgICAgcGFzdGUwKHBoZW5vdHlwZSwgIl90aHIiLCB0aHIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICJfbG9jYWxfc3RhYmlsaXR5X2hlYXRtYXBfIiwgdHlwZSwgIi5yZHMiKSkpCgogICAgICAgICMgZGlzdHJpYnV0aW9uIHBsb3RzCiAgICAgICAgZnRfcHZhbHMgPC0gbWFwX2RmcihzdGFiX2FsbF9vdXRbW3R5cGVdXSRwZXJtX291dF9sc1tbSVRFUl1dLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgfmRhdGEuZnJhbWUocHZhbCA9IC54JHB2YWwpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgLmlkID0gImZlYXR1cmUiKSAlPiUKICAgICAgICAgIGFycmFuZ2UocHZhbCkgJT4lCiAgICAgICAgICBkcGx5cjo6bXV0YXRlKAogICAgICAgICAgICBwdmFsX3N0ciA9IGRwbHlyOjpjYXNlX3doZW4oCiAgICAgICAgICAgICAgcHZhbCA8IDFlLTQgfiAicCA8IDEwXi00IiwKICAgICAgICAgICAgICBwdmFsIDwgMWUtMyB+ICJwIDwgMTBeLTMiLAogICAgICAgICAgICAgICMgcHZhbCA8IDFlLTQgfiAicCA8IDEwPHN1cD4tNDwvc3VwPiIsCiAgICAgICAgICAgICAgIyBwdmFsIDwgMWUtMyB+ICJwIDwgMTA8c3VwPi0zPC9zdXA+IiwKICAgICAgICAgICAgICBUUlVFIH4gc3ByaW50ZigicH5gPWB+JXMiLCBmb3JtYXRDKHB2YWwsIGRpZ2l0cyA9IDMsIGZvcm1hdCA9ICJmIikpCiAgICAgICAgICAgICkKICAgICAgICAgICkgJT4lCiAgICAgICAgICBtdXRhdGUoZnRfcHZhbCA9IHBhc3RlMChmZWF0dXJlLCAiIChwID0gIiwgZm9ybWF0QyhwdmFsLCAzLCBmb3JtYXQgPSAiZyIpLCAiKSIpKQogICAgICAgIHBsdF9kZiA8LSBzdGFiX2RmICU+JQogICAgICAgICAgYmluZF9jb2xzKHkgPSB5X3Rlc3QpICU+JQogICAgICAgICAgZ2F0aGVyKGtleSA9ICJmZWF0dXJlIiwgdmFsdWUgPSAiU3RhYmlsaXR5IiwgLXkpICU+JQogICAgICAgICAgbGVmdF9qb2luKHkgPSBmdF9wdmFscywgYnkgPSAiZmVhdHVyZSIpICU+JQogICAgICAgICAgIyBtdXRhdGUoZmVhdHVyZSA9IHBhc3RlMChmZWF0dXJlLCAiIChwID0gIiwgZm9ybWF0QyhwdmFsLCAzLCBmb3JtYXQgPSAiZyIpLCAiKSIpKSAlPiUKICAgICAgICAgIG11dGF0ZShmZWF0dXJlID0gZmFjdG9yKGZlYXR1cmUsIGxldmVscyA9IGZ0X3B2YWxzJGZlYXR1cmUpKQogICAgICAgIHBsdCA8LSBwbG90X2RlbnNpdHkoZGF0YSA9IHBsdF9kZiwgeF9zdHIgPSAiU3RhYmlsaXR5IiwgZmlsbF9zdHIgPSAieSIpICsKICAgICAgICAgIGZhY2V0X3dyYXAofiBmZWF0dXJlLCBzY2FsZXMgPSAiZnJlZSIsIG5jb2wgPSA0KSArCiAgICAgICAgICBnZ3Bsb3QyOjpsYWJzKHggPSAiTG9jYWwgU3RhYmlsaXR5IEltcG9ydGFuY2UgU2NvcmUiLCBmaWxsID0gIiIpICsKICAgICAgICAgIGdncGxvdDI6Omdlb21fdGV4dCgKICAgICAgICAgICAgZ2dwbG90Mjo6YWVzKHggPSBJbmYsIHkgPSBJbmYsIGhqdXN0ID0gMS4xLCB2anVzdCA9IDEuNSwgbGFiZWwgPSBwdmFsX3N0ciksCiAgICAgICAgICAgIGRhdGEgPSBwbHRfZGYgJT4lIGRwbHlyOjpkaXN0aW5jdChmZWF0dXJlLCAua2VlcF9hbGwgPSBUUlVFKSwKICAgICAgICAgICAgcGFyc2UgPSBUUlVFCiAgICAgICAgICApICsKICAgICAgICAgIGdncGxvdDI6OnRoZW1lKGF4aXMudGl0bGUgPSBnZ3Bsb3QyOjplbGVtZW50X3RleHQoc2l6ZSA9IDE0KSkKICAgICAgICBzYXZlUkRTKHBsdCwKICAgICAgICAgICAgICAgIGZpbGUucGF0aChmaWdfcmVzX2RpciwKICAgICAgICAgICAgICAgICAgICBwYXN0ZTAocGhlbm90eXBlLCAiX3RociIsIHRociwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIl9sb2NhbF9zdGFiaWxpdHlfZGlzdF8iLCB0eXBlLCAiLnJkcyIpKSkKCiAgICAgICAgIyBpbmRpdmlkdWFsIHNucCBwbG90cwogICAgICAgIHBsdCA8LSBwbG90UkZTbnBEaXN0KAogICAgICAgICAgaXJmX2dlbmVfb3V0JHJmLmxpc3RbW0lURVJdXSwgc25wcy5kZiwgZnRfcHZhbHMkZmVhdHVyZSwgcHJvcCA9IFRSVUUKICAgICAgICApICsKICAgICAgICAgIGdncGxvdDI6OmxhYnMoeCA9ICJTTlYgKE9yZGVyZWQgYnkgUG9zaXRpb24pIikKICAgICAgICBzYXZlUkRTKHBsdCwKICAgICAgICAgICAgICAgIGZpbGUucGF0aChmaWdfcmVzX2RpciwKICAgICAgICAgICAgICAgICAgICBwYXN0ZTAocGhlbm90eXBlLCAiX3RociIsIHRociwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIl9sb2NhbF9zdGFiaWxpdHlfc25wX2Rpc3RfIiwgdHlwZSwgIi5yZHMiKSkpCiAgICAgIH0KICAgIH0KICAgIAogICAgdGFiIDwtIGRwbHlyOjpiaW5kX3Jvd3MoZXZhbF9scywgLmlkID0gIkJpbmFyaXphdGlvbiBUaHJlc2hvbGQiKSAlPiUKICAgICAgZHBseXI6OnJlbmFtZSgiQWNjdXJhY3kiID0gIkNsYXNzIiwgIkFVUk9DIiA9ICJBVUMiLCAiQVVQUkMiID0gIlBSIikgJT4lCiAgICAgIGRwbHlyOjpzZWxlY3QoYEJpbmFyaXphdGlvbiBUaHJlc2hvbGRgLCBBY2N1cmFjeSwgQVVST0MsIEFVUFJDKSAlPiUKICAgICAgcHJldHR5X0RUKGRpZ2l0cyA9IDMsIHNpZ2ZpZyA9IEZBTFNFLCByb3duYW1lcyA9IEZBTFNFLCAKICAgICAgICAgICAgICAgIG9wdGlvbnMgPSBsaXN0KGRvbSA9ICJ0Iiwgb3JkZXJpbmcgPSBGQUxTRSkpCiAgICBzYXZlUkRTKHRhYiwKICAgICAgICAgICAgZmlsZS5wYXRoKHRhYl9yZXNfZGlyLAogICAgICAgICAgICAgICAgICAgICAgcGFzdGUwKHBoZW5vdHlwZSwgIl9pcmZfcHJlZGljdGlvbl9yZXN1bHRzLnJkcyIpKSkKICAgIAogICAgZ2VuZV9yZXN1bHRzX2RmIDwtIHB1cnJyOjptYXBfZGZyKAogICAgICBnZW5lX3Jlc3VsdHNfbHMsCiAgICAgIGZ1bmN0aW9uKGdlbmVfcmVzdWx0cykgewogICAgICAgIHB1cnJyOjptYXBfZGZyKAogICAgICAgICAgZ2VuZV9yZXN1bHRzW1tJVEVSXV0sCiAgICAgICAgICB+IGRhdGEuZnJhbWUoCiAgICAgICAgICAgIGBNZWFuIERpZmZlcmVuY2UgKEhpZ2ggLSBMb3cpYCA9IGZvcm1hdEMoLngkVF9vYnMsIGRpZ2l0cyA9IDIsIGZvcm1hdCA9ICJnIiksCiAgICAgICAgICAgIGBTRGAgPSBmb3JtYXRDKHNkKC54JHBlcm1fZGlzdCksIGRpZ2l0cyA9IDIsIGZvcm1hdCA9ICJnIiksCiAgICAgICAgICAgIGBwLXZhbHVlYCA9IGRwbHlyOjpjYXNlX3doZW4oCiAgICAgICAgICAgICAgLngkcHZhbCA8IDFlLTQgfiAiPCAxMDxzdXA+LTQ8L3N1cD4iLAogICAgICAgICAgICAgIC54JHB2YWwgPCAxZS0zIH4gIjwgMTA8c3VwPi0zPC9zdXA+IiwKICAgICAgICAgICAgICBUUlVFIH4gZm9ybWF0QygueCRwdmFsLCBkaWdpdHMgPSAzLCBmb3JtYXQgPSAiZiIpCiAgICAgICAgICAgICksCiAgICAgICAgICAgIHAgPSAueCRwdmFsLAogICAgICAgICAgICBjaGVjay5uYW1lcyA9IEZBTFNFCiAgICAgICAgICApLAogICAgICAgICAgLmlkID0gIkxvY3VzIC8gSW50ZXJhY3Rpb24iCiAgICAgICAgKQogICAgICB9LAogICAgICAuaWQgPSAiQmluYXJpemF0aW9uIFRocmVzaG9sZCIKICAgICkKICAgIAogICAgaW50X3Jlc3VsdHNfZGYgPC0gcHVycnI6Om1hcF9kZnIoCiAgICAgIGludF9yZXN1bHRzX2xzLAogICAgICBmdW5jdGlvbihpbnRfcmVzdWx0cykgewogICAgICAgIHB1cnJyOjptYXBfZGZyKAogICAgICAgICAgaW50X3Jlc3VsdHNbW0lURVJdXSwKICAgICAgICAgIH4gZGF0YS5mcmFtZSgKICAgICAgICAgICAgYE1lYW4gRGlmZmVyZW5jZSAoSGlnaCAtIExvdylgID0gZm9ybWF0QygueCRUX29icywgZGlnaXRzID0gMiwgZm9ybWF0ID0gImciKSwKICAgICAgICAgICAgYFNEYCA9IGZvcm1hdEMoc2QoLngkcGVybV9kaXN0KSwgZGlnaXRzID0gMiwgZm9ybWF0ID0gImciKSwKICAgICAgICAgICAgYHAtdmFsdWVgID0gZHBseXI6OmNhc2Vfd2hlbigKICAgICAgICAgICAgICAueCRwdmFsIDwgMWUtNCB+ICI8IDEwPHN1cD4tNDwvc3VwPiIsCiAgICAgICAgICAgICAgLngkcHZhbCA8IDFlLTMgfiAiPCAxMDxzdXA+LTM8L3N1cD4iLAogICAgICAgICAgICAgIFRSVUUgfiBmb3JtYXRDKC54JHB2YWwsIGRpZ2l0cyA9IDMsIGZvcm1hdCA9ICJmIikKICAgICAgICAgICAgKSwKICAgICAgICAgICAgcCA9IC54JHB2YWwsCiAgICAgICAgICAgIGNoZWNrLm5hbWVzID0gRkFMU0UKICAgICAgICAgICksCiAgICAgICAgICAuaWQgPSAiTG9jdXMgLyBJbnRlcmFjdGlvbiIKICAgICAgICApCiAgICAgIH0sCiAgICAgIC5pZCA9ICJCaW5hcml6YXRpb24gVGhyZXNob2xkIgogICAgKQogICAgCiAgICBzdHlsZV9uYW1lcyA8LSBmdW5jdGlvbih4KSB7CiAgICAgIGNvbG9yX3ZlYyA8LSBzdHJpbmdyOjpzdHJfZGV0ZWN0KHgsICJfIikKICAgICAgeCA8LSB4ICU+JQogICAgICAgIHN0cmluZ3I6OnN0cl9yZXBsYWNlX2FsbCgiLV8iLCAiPHN1cD4mIzgyMTE7PC9zdXA+JiM4MjExOyIpICU+JQogICAgICAgIHN0cmluZ3I6OnN0cl9yZXBsYWNlX2FsbCgiLSQiLCAiPHN1cD4mIzgyMTE7PC9zdXA+IikgJT4lCiAgICAgICAgc3RyaW5ncjo6c3RyX3JlcGxhY2VfYWxsKCJcXCsiLCAiPHN1cD4rPC9zdXA+IikKICAgICAgeCA8LSBkcGx5cjo6Y2FzZV93aGVuKAogICAgICAgIGNvbG9yX3ZlYyB+IGthYmxlRXh0cmE6OmNlbGxfc3BlYygKICAgICAgICAgIHgsIGNvbG9yID0gImNvcm5mbG93ZXJibHVlIiwgZXNjYXBlID0gRkFMU0UsIGl0YWxpYyA9IFRSVUUKICAgICAgICApLAogICAgICAgIFRSVUUgfiBrYWJsZUV4dHJhOjpjZWxsX3NwZWMoeCwgZXNjYXBlID0gRkFMU0UsIGl0YWxpYyA9IFRSVUUpCiAgICAgICkKICAgICAgcmV0dXJuKHgpCiAgICB9CiAgICAKICAgIGZlYXR1cmVfb3JkZXIgPC0gZHBseXI6OmJpbmRfcm93cyhnZW5lX3Jlc3VsdHNfZGYsIGludF9yZXN1bHRzX2RmKSAlPiUKICAgICAgZHBseXI6Omdyb3VwX2J5KGBMb2N1cyAvIEludGVyYWN0aW9uYCkgJT4lCiAgICAgIGRwbHlyOjpzdW1tYXJpc2UobiA9IGRwbHlyOjpuKCksCiAgICAgICAgICAgICAgICAgICAgICAgbWVhbiA9IG1lYW4ocCkpICU+JQogICAgICBkcGx5cjo6YXJyYW5nZSgtbiwgbWVhbikgJT4lCiAgICAgIGRwbHlyOjpzZWxlY3QoYExvY3VzIC8gSW50ZXJhY3Rpb25gKQogICAgCiAgICBjb2xvcl92ZWMgPC0gc3RyaW5ncjo6c3RyX2RldGVjdChmZWF0dXJlX29yZGVyJGBMb2N1cyAvIEludGVyYWN0aW9uYCwgIl8iKQogICAgCiAgICByZXN1bHRzX2RmIDwtIGRwbHlyOjpiaW5kX3Jvd3MoZ2VuZV9yZXN1bHRzX2RmLCBpbnRfcmVzdWx0c19kZikgJT4lCiAgICAgIGRwbHlyOjptdXRhdGUoCiAgICAgICAgYERpZmZlcmVuY2UgaW4gTG9jYWwgRmVhdHVyZSBTdGFiaWxpdHkgKEhpZ2ggLSBMb3cpYCA9IHNwcmludGYoIiVzICglcykiLCBgTWVhbiBEaWZmZXJlbmNlIChIaWdoIC0gTG93KWAsIFNEKQogICAgICApICU+JQogICAgICB0aWR5cjo6cGl2b3Rfd2lkZXIoaWRfY29scyA9IGBMb2N1cyAvIEludGVyYWN0aW9uYCwgCiAgICAgICAgICAgICAgICAgICAgICAgICBuYW1lc19mcm9tID0gYEJpbmFyaXphdGlvbiBUaHJlc2hvbGRgLCAKICAgICAgICAgICAgICAgICAgICAgICAgIHZhbHVlc19mcm9tID0gYyhgRGlmZmVyZW5jZSBpbiBMb2NhbCBGZWF0dXJlIFN0YWJpbGl0eSAoSGlnaCAtIExvdylgLCBgcC12YWx1ZWApLAogICAgICAgICAgICAgICAgICAgICAgICAgbmFtZXNfdmFyeSA9ICJzbG93ZXN0IikgJT4lCiAgICAgIGRwbHlyOjpsZWZ0X2pvaW4oeCA9IGZlYXR1cmVfb3JkZXIsIHkgPSAuLCBieSA9ICJMb2N1cyAvIEludGVyYWN0aW9uIikgJT4lCiAgICAgIGRwbHlyOjptdXRhdGUoCiAgICAgICAgYExvY3VzIC8gSW50ZXJhY3Rpb25gID0gc3R5bGVfbmFtZXMoYExvY3VzIC8gSW50ZXJhY3Rpb25gKQogICAgICApCiAgICByZXN1bHRzX3RhYiA8LSBwcmV0dHlfRFQoCiAgICAgIHJlc3VsdHNfZGYsIG5hX2Rpc3AgPSAiLS0iLCByb3duYW1lcyA9IEZBTFNFLAogICAgICBncm91cGVkX2hlYWRlciA9IGMoIiAiID0gMSwgIkJpbmFyaXphdGlvbiBUaHJlc2hvbGQgPSAwLjE1IiA9IDIsCiAgICAgICAgICAgICAgICAgICAgICAgICAiQmluYXJpemF0aW9uIFRocmVzaG9sZCA9IDAuMjAiID0gMiwKICAgICAgICAgICAgICAgICAgICAgICAgICJCaW5hcml6YXRpb24gVGhyZXNob2xkID0gMC4yNSIgPSAyKSwKICAgICAgZ3JvdXBlZF9zdWJoZWFkZXIgPSBzdHJpbmdyOjpzdHJfcmVtb3ZlKGNvbG5hbWVzKHJlc3VsdHNfZGYpLCAiXFxfWy4wLTldKyIpKQogICAgc2F2ZVJEUyhyZXN1bHRzX3RhYiwKICAgICAgICAgICAgZmlsZS5wYXRoKHRhYl9yZXNfZGlyLAogICAgICAgICAgICAgICAgICAgICAgcGFzdGUwKHBoZW5vdHlwZSwgIl9pcmZfcHZhbHVlc19zdW1tYXJ5LnJkcyIpKSkKCiAgfQp9IGVsc2UgewogIG1ldGhvZF90eXBlcyA8LSBjKCJVc2luZyBhbGwgc3BsaXRzIikKICB0aHJzIDwtIGMoMC4xNSwgMC4yLCAwLjI1KQogIGZvciAocGhlbm90eXBlIGluIHBoZW5vdHlwZXMpIHsKICAgIHBoZW5vdHlwZV9uYW1lIDwtIG5hbWVzKHBoZW5vdHlwZXMpW3BoZW5vdHlwZXMgPT0gcGhlbm90eXBlXQogICAgIyBjYXQoc3ByaW50ZihwaGVub3R5cGVfaGVhZGVyLCBwaGVub3R5cGVfbmFtZSkpCiAgICAKICAgIGNhdChzcHJpbnRmKHNlY3Rpb25faGVhZGVyLCAiU3VtbWFyeSIpKQogICAgdGFiIDwtIHJlYWRSRFMoZmlsZS5wYXRoKHRhYl9yZXNfZGlyLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwYXN0ZTAocGhlbm90eXBlLCAiX2lyZl9wcmVkaWN0aW9uX3Jlc3VsdHMucmRzIikpKQogICAgc3ViY2h1bmtpZnkodGFiLCBpID0gY2h1bmtfaWR4LAogICAgICAgICAgICAgICAgY2FwdGlvbiA9IHNwcmludGYoIidTdW1tYXJ5IG9mIHRoZSB2YWxpZGF0aW9uIHByZWRpY3Rpb24gcGVyZm9ybWFuY2UgZnJvbSBzaVJGIGFjcm9zcyB2YXJpb3VzICVzIGJpbmFyaXphdGlvbiB0aHJlc2hvbGRzLiciLCBwaGVub3R5cGVfbmFtZSkpCiAgICBjaHVua19pZHggPC0gY2h1bmtfaWR4ICsgMQogICAgCiAgICB0YWIgPC0gcmVhZFJEUyhmaWxlLnBhdGgodGFiX3Jlc19kaXIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBhc3RlMChwaGVub3R5cGUsICJfaXJmX3B2YWx1ZXNfc3VtbWFyeS5yZHMiKSkpCiAgICBzdWJjaHVua2lmeSh0YWIsIGkgPSBjaHVua19pZHgsCiAgICAgICAgICAgICAgICBjYXB0aW9uID0gc3ByaW50ZigiJ1N1bW1hcnkgb2YgdGhlIGxvLXNpUkYgcGVybXV0YXRpb24gdGVzdCByZXN1bHRzIGFjcm9zcyB2YXJpb3VzICVzIGJpbmFyaXphdGlvbiB0aHJlc2hvbGRzIGluY2x1ZGluZyB0aGUgdGVzdCBzdGF0aXN0aWMgKGkuZS4sIGRpZmZlcmVuY2UgaW4gbG9jYWwgZmVhdHVyZSBzdGFiaWxpdHkgc2NvcmVzIGJldHdlZW4gdGhlIGhpZ2ggYW5kIHRoZSBsb3cgJXMgZ3JvdXBzIChTRCBpbiBwYXJlbnRoZXNlcykgYW5kIHRoZSByZXN1bHRpbmcgcC12YWx1ZXMuIEJsYW5rIGNlbGxzIGluZGljYXRlIHRoYXQgdGhlIGxvY3VzL2ludGVyYWN0aW9uIHdhcyBub3Qgc2VsZWN0ZWQgZm9yIHRlc3RpbmcgZm9yIHRoZSBnaXZlbiBiaW5hcml6YXRpb24gdGhyZXNob2xkLiBMb2NpL2ludGVyYWN0aW9ucyBhcmUgcmFua2VkIGFjY29yZGluZyB0byB0aGUgbWVhbiBwLXZhbHVlIGFjcm9zcyBhbGwgdGhyZWUgYmluYXJpemF0aW9uIHRocmVzaG9sZHMuIEludGVyYWN0aW9ucyBiZXR3ZWVuIGdlbmV0aWMgbG9jaSBhcmUgaGlnaGxpZ2h0ZWQgaW4gYmx1ZS4nIiwgcGhlbm90eXBlX25hbWUsIHBoZW5vdHlwZV9uYW1lKSkKICAgIGNodW5rX2lkeCA8LSBjaHVua19pZHggKyAxCiAgICAKICAgIGNhdChzcHJpbnRmKHNlY3Rpb25faGVhZGVyLCAic2lSRiBJbnRlcmFjdGlvbiBUYWJsZSIpKQogICAgZm9yICh0aHIgaW4gdGhycykgewogICAgICBjYXQoc3ByaW50Zih0aHJfaGVhZGVyLCB0aHIpKQogICAgICB0YWIgPC0gcmVhZFJEUyhmaWxlLnBhdGgodGFiX3Jlc19kaXIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcGFzdGUwKHBoZW5vdHlwZSwgIl90aHIiLCB0aHIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJfaXJmX2ludGVyYWN0aW9uX3Jlc3VsdHMucmRzIikpKQogICAgICBzdWJjaHVua2lmeSh0YWIsIGkgPSBjaHVua19pZHgsCiAgICAgICAgICAgICAgICAgIGNhcHRpb24gPSBzcHJpbnRmKCInU3VtbWFyeSBvZiB0aGUgc2lSRiBsb2N1cy1sZXZlbCBpbnRlcmFjdGlvbiB0YWJsZSBvdXRwdXQgZm9yIHRoZSBiaW5hcml6ZWQgJXMgcGhlbm90eXBlIChiaW5hcml6YXRpb24gdGhyZXNob2xkID0gJXMpLiBGb3IgYWxsIG1ldHJpY3MgZXhjbHVkaW5nIHRoZSBsby1zaVJGIG1lYW4gcGVybXV0YXRpb24gcC12YWx1ZSwgaGlnaGVyIHZhbHVlcyBpbmRpY2F0ZSBhIHN0cm9uZ2VyIGludGVyYWN0aW9uLiBEZXRhaWxzIHJlZ2FyZGluZyB0aGVzZSBtZXRyaWNzIGluIHRoZSBzaVJGIGludGVyYWN0aW9uIHRhYmxlIG91dHB1dCBjYW4gYmUgZm91bmQgaW4gS3VtYmllciBldCBhbC4gKDIwMTgpLiciLCBwaGVub3R5cGVfbmFtZSwgdGhyKSkKICAgICAgY2h1bmtfaWR4IDwtIGNodW5rX2lkeCArIDEKICAgICAgY2F0KCJcblxuIikKICAgICAgCiAgICAgIHRhYiA8LSByZWFkUkRTKGZpbGUucGF0aCh0YWJfcmVzX2RpciwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwYXN0ZTAocGhlbm90eXBlLCAiX3RociIsIHRociwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIl9pcmZfc252X2ludGVyYWN0aW9uX3Jlc3VsdHMucmRzIikpKQogICAgICBzdWJjaHVua2lmeSh0YWIsIGkgPSBjaHVua19pZHgsCiAgICAgICAgICAgICAgICAgIGNhcHRpb24gPSBzcHJpbnRmKCInU3VtbWFyeSBvZiB0aGUgc2lSRiBTTlYtbGV2ZWwgaW50ZXJhY3Rpb24gdGFibGUgb3V0cHV0IGZvciB0aGUgYmluYXJpemVkICVzIHBoZW5vdHlwZSAoYmluYXJpemF0aW9uIHRocmVzaG9sZCA9ICVzKS4gU3RhYmlsaXR5IHNjb3JlcyBmb3IgYWxsIGludGVyYWN0aW9ucyBhcmUgY2xvc2UgdG8gMCwgc3VnZ2VzdGluZyB1bnJlbGlhYmxlIFNOVi1sZXZlbCBpbnRlcmFjdGlvbnMuIERldGFpbHMgcmVnYXJkaW5nIHRoZXNlIG1ldHJpY3MgaW4gdGhlIHNpUkYgaW50ZXJhY3Rpb24gdGFibGUgb3V0cHV0IGNhbiBiZSBmb3VuZCBpbiBLdW1iaWVyIGV0IGFsLiAoMjAxOCkuJyIsIHBoZW5vdHlwZV9uYW1lLCB0aHIpKQogICAgICBjaHVua19pZHggPC0gY2h1bmtfaWR4ICsgMQogICAgICBjYXQoIlxuXG4iKQogICAgfQogICAgCiAgICBjYXQoc3ByaW50ZihzZWN0aW9uX2hlYWRlciwgIkxvY2FsIFN0YWJpbGl0eSBJbXBvcnRhbmNlIFBsb3RzIC0gSW50ZXJhY3Rpb25zIikpCiAgICBmb3IgKHRociBpbiB0aHJzKSB7CiAgICAgIGNhdChzcHJpbnRmKHRocl9oZWFkZXIsIHRocikpCiAgICAgIGZvciAodHlwZSBpbiBtZXRob2RfdHlwZXMpIHsKICAgICAgICAjIGRpc3RyaWJ1dGlvbiBwbG90cwogICAgICAgIHBsdCA8LSByZWFkUkRTKAogICAgICAgICAgZmlsZS5wYXRoKGZpZ19yZXNfZGlyLCAKICAgICAgICAgICAgICAgICAgICBwYXN0ZTAocGhlbm90eXBlLCAiX3RociIsIHRociwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICJfaW50X2xvY2FsX3N0YWJpbGl0eV9kaXN0XyIsIHR5cGUsICIucmRzIikpCiAgICAgICAgKQogICAgICAgIG5yb3dzIDwtIGNlaWxpbmcobmxldmVscyhwbHQkZGF0YSRpbnQpIC8gMykKICAgICAgICBzdWJjaHVua2lmeShwbHQsIGkgPSBjaHVua19pZHgsIGZpZ19oZWlnaHQgPSBESVNUX0hFSUdIVCAvIDQgKiBucm93cywKICAgICAgICAgICAgICAgICAgICBhZGRfY2xhc3MgPSBjKCJwYW5lbCBwYW5lbC1kZWZhdWx0IHBhZGRlZC1wYW5lbCIpLAogICAgICAgICAgICAgICAgICAgIG90aGVyX2FyZ3MgPSAib3V0LndpZHRoPScxMDAlJyIsCiAgICAgICAgICAgICAgICAgICAgY2FwdGlvbiA9IHNwcmludGYoIidEaXN0cmlidXRpb24gb2YgbG9jYWwgc3RhYmlsaXR5IGltcG9ydGFuY2Ugc2NvcmVzIGJldHdlZW4gdGhlIGhpZ2ggYW5kIGxvdyAlcyBncm91cHMgKGJpbmFyaXphdGlvbiB0aHJlc2hvbGQgPSAlcykgZm9yIGVhY2ggc2lnbmVkIGludGVyYWN0aW9uIGJldHdlZW4gbG9jaSAoc3BlY2lmaWVkIGJ5IHN1YnBsb3QpIHRoYXQgcGFzc2VkIHRoZSBzaVJGIHN0YWJpbGl0eSBmaWx0ZXIuIFRoZSBwZXJtdXRhdGlvbiB0ZXN0IHAtdmFsdWUsIGFzc2Vzc2luZyBkaXN0cmlidXRpb25hbCBkaWZmZXJlbmNlcyBiZXR3ZWVuIHRoZSBoaWdoIGFuZCBsb3cgJXMgZ3JvdXBzLCBpcyBwcm92aWRlZCBpbiB0aGUgdG9wIHJpZ2h0IGNvcm5lciBvZiBlYWNoIHN1YnBsb3QuJyIsIHBoZW5vdHlwZV9uYW1lLCB0aHIsIHBoZW5vdHlwZV9uYW1lKSkKICAgICAgICBjaHVua19pZHggPC0gY2h1bmtfaWR4ICsgMQogICAgICAgIGNhdCgiXG5cbiIpCiAgICAgICAgCiAgICAgICAgIyBpbmRpdmlkdWFsIHNucCBwbG90cwogICAgICAgIHBsdCA8LSByZWFkUkRTKAogICAgICAgICAgZmlsZS5wYXRoKGZpZ19yZXNfZGlyLAogICAgICAgICAgICAgICAgICAgIHBhc3RlMChwaGVub3R5cGUsICJfdGhyIiwgdGhyLAogICAgICAgICAgICAgICAgICAgICAgICAgICAiX2ludF9sb2NhbF9zdGFiaWxpdHlfc25wX2Rpc3RfIiwgdHlwZSwgIi5yZHMiKSkKICAgICAgICApCiAgICAgICAgbnJvd3MgPC0gY2VpbGluZyhsZW5ndGgodW5pcXVlKHBsdCRkYXRhJEdlbmVzKSkgLyAzKQogICAgICAgIHN1YmNodW5raWZ5KGdncGxvdGx5KHBsdCksIGkgPSBjaHVua19pZHgsIGZpZ19oZWlnaHQgPSBESVNUX0hFSUdIVCAvIDQgKiBucm93cywKICAgICAgICAgICAgICAgICAgICBhZGRfY2xhc3MgPSBjKCJwYW5lbCBwYW5lbC1kZWZhdWx0IHBhZGRlZC1wYW5lbCIpLAogICAgICAgICAgICAgICAgICAgIG90aGVyX2FyZ3MgPSAib3V0LndpZHRoPScxMDAlJyIsCiAgICAgICAgICAgICAgICAgICAgY2FwdGlvbiA9IHNwcmludGYoIidGcmVxdWVuY3kgb2Ygb2NjdXJyZW5jZSBvZiBTTlYtU05WIGNvbWJpbmF0aW9ucyBpbiB0aGUgc2lSRiBmaXQgZm9yIHRoZSBiaW5hcml6ZWQgJXMgcGhlbm90eXBlIChiaW5hcml6YXRpb24gdGhyZXNob2xkID0gJXMpLiBTTlYtU05WIGNvbWJpbmF0aW9ucyB3aXRoIHRoZSBoaWdoZXN0IG51bWJlciBvZiBvY2N1cnJlbmNlcyBpbiB0aGUgc2lSRiBkZWNpc2lvbiBwYXRocyBjb250cmlidXRlIHRoZSBtb3N0IHRvIHRoZSBvdmVyYWxsIGxvY3VzLWxldmVsIGludGVyYWN0aW9uIGltcG9ydGFuY2UgaW4gdGhlIHNpUkYgZml0LiciLCBwaGVub3R5cGVfbmFtZSwgdGhyKSkKICAgICAgICBjaHVua19pZHggPC0gY2h1bmtfaWR4ICsgMQogICAgICAgIGNhdCgiXG5cbiIpCiAgICAgICAgCiAgICAgICAgIyAjIGhlYXRtYXAKICAgICAgICAjIHBsdCA8LSByZWFkUkRTKAogICAgICAgICMgICBmaWxlLnBhdGgoZmlnX3Jlc19kaXIsIAogICAgICAgICMgICAgICAgICAgICAgcGFzdGUwKHBoZW5vdHlwZSwgIl90aHIiLCB0aHIsIAogICAgICAgICMgICAgICAgICAgICAgICAgICAgICJfaW50X2xvY2FsX3N0YWJpbGl0eV9oZWF0bWFwXyIsIHR5cGUsICIucmRzIikpCiAgICAgICAgIyApCiAgICAgICAgIyBzdWJjaHVua2lmeShwbHQsIGkgPSBjaHVua19pZHgsIGZpZ19oZWlnaHQgPSBIRUFUTUFQX0hFSUdIVCwKICAgICAgICAjICAgICAgICAgICAgIGFkZF9jbGFzcyA9IGMoInBhbmVsIHBhbmVsLWRlZmF1bHQiKSwKICAgICAgICAjICAgICAgICAgICAgIG90aGVyX2FyZ3MgPSAib3V0LndpZHRoPScxMDAlJyIpCiAgICAgICAgIyBjaHVua19pZHggPC0gY2h1bmtfaWR4ICsgMQogICAgICB9CiAgICB9CiAgICAKICAgIGNhdChzcHJpbnRmKHNlY3Rpb25faGVhZGVyLCAiTG9jYWwgU3RhYmlsaXR5IEltcG9ydGFuY2UgUGxvdHMgLSBMb2NpIikpCiAgICBmb3IgKHRociBpbiB0aHJzKSB7CiAgICAgIGNhdChzcHJpbnRmKHRocl9oZWFkZXIsIHRocikpCiAgICAgIGZvciAodHlwZSBpbiBtZXRob2RfdHlwZXMpIHsKICAgICAgICAjIGRpc3RyaWJ1dGlvbiBwbG90cwogICAgICAgIHBsdCA8LSByZWFkUkRTKAogICAgICAgICAgZmlsZS5wYXRoKGZpZ19yZXNfZGlyLCAKICAgICAgICAgICAgICAgICAgICBwYXN0ZTAocGhlbm90eXBlLCAiX3RociIsIHRociwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICJfbG9jYWxfc3RhYmlsaXR5X2Rpc3RfIiwgdHlwZSwgIi5yZHMiKSkKICAgICAgICApCiAgICAgICAgbnJvd3MgPC0gY2VpbGluZyhubGV2ZWxzKHBsdCRkYXRhJGZlYXR1cmUpIC8gNCkKICAgICAgICBzdWJjaHVua2lmeShwbHQsIGkgPSBjaHVua19pZHgsIGZpZ19oZWlnaHQgPSBESVNUX0hFSUdIVCAvIDQgKiBucm93cywKICAgICAgICAgICAgICAgICAgICBhZGRfY2xhc3MgPSBjKCJwYW5lbCBwYW5lbC1kZWZhdWx0IiksCiAgICAgICAgICAgICAgICAgICAgb3RoZXJfYXJncyA9ICJvdXQud2lkdGg9JzEwMCUnIiwKICAgICAgICAgICAgICAgICAgICBjYXB0aW9uID0gc3ByaW50ZigiJ0Rpc3RyaWJ1dGlvbiBvZiBsb2NhbCBzdGFiaWxpdHkgaW1wb3J0YW5jZSBzY29yZXMgYmV0d2VlbiB0aGUgaGlnaCBhbmQgbG93ICVzIGdyb3VwcyAoYmluYXJpemF0aW9uIHRocmVzaG9sZCA9ICVzKSBmb3IgZWFjaCBzaWduZWQgbG9jdXMgKHNwZWNpZmllZCBieSBzdWJwbG90KS4gSGVyZSwgd2Ugc2hvdyBvbmx5IHRoZSB0b3AgMjUgc2lnbmVkIGxvY2ksIHJhbmtlZCBieSB0aGVpciBhdmVyYWdlIGxvY2FsIHN0YWJpbGl0eSBpbXBvcnRhbmNlIHNjb3Jlcy4gVGhlIHBlcm11dGF0aW9uIHRlc3QgcC12YWx1ZSwgYXNzZXNzaW5nIGRpc3RyaWJ1dGlvbmFsIGRpZmZlcmVuY2VzIGJldHdlZW4gdGhlIGhpZ2ggYW5kIGxvdyAlcyBncm91cHMsIGlzIHByb3ZpZGVkIGluIHRoZSB0b3AgcmlnaHQgY29ybmVyIG9mIGVhY2ggc3VicGxvdC4nIiwgcGhlbm90eXBlX25hbWUsIHRociwgcGhlbm90eXBlX25hbWUpKQogICAgICAgIGNodW5rX2lkeCA8LSBjaHVua19pZHggKyAxCiAgICAgICAgY2F0KCJcblxuIikKICAgICAgICAKICAgICAgICAjIGluZGl2aWR1YWwgc25wIHBsb3RzCiAgICAgICAgcGx0IDwtIHJlYWRSRFMoCiAgICAgICAgICBmaWxlLnBhdGgoZmlnX3Jlc19kaXIsCiAgICAgICAgICAgICAgICAgICAgcGFzdGUwKHBoZW5vdHlwZSwgIl90aHIiLCB0aHIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICJfbG9jYWxfc3RhYmlsaXR5X3NucF9kaXN0XyIsIHR5cGUsICIucmRzIikpCiAgICAgICAgKQogICAgICAgIG5yb3dzIDwtIGNlaWxpbmcobGVuZ3RoKHVuaXF1ZShwbHQkZGF0YSRHZW5lKSkgLyAzKQogICAgICAgIHN1YmNodW5raWZ5KGdncGxvdGx5KHBsdCwgdG9vbHRpcCA9IGMoInkiLCAidGV4dCIpKSwgaSA9IGNodW5rX2lkeCwgZmlnX2hlaWdodCA9IERJU1RfSEVJR0hUIC8gNCAqIG5yb3dzLAogICAgICAgICAgICAgICAgICAgIGFkZF9jbGFzcyA9IGMoInBhbmVsIHBhbmVsLWRlZmF1bHQgcGFkZGVkLXBhbmVsIiksCiAgICAgICAgICAgICAgICAgICAgb3RoZXJfYXJncyA9ICJvdXQud2lkdGg9JzEwMCUnIiwKICAgICAgICAgICAgICAgICAgICBjYXB0aW9uID0gc3ByaW50ZigiJ0ZyZXF1ZW5jeSBvZiBvY2N1cnJlbmNlIG9mIFNOVnMgaW4gdGhlIHNpUkYgZml0IGZvciB0aGUgYmluYXJpemVkICVzIHBoZW5vdHlwZSAoYmluYXJpemF0aW9uIHRocmVzaG9sZCA9ICVzKS4gU05WcyB3aXRoIHRoZSBoaWdoZXN0IG51bWJlciBvZiBvY2N1cnJlbmNlcyBpbiB0aGUgc2lSRiBkZWNpc2lvbiBwYXRocyBjb250cmlidXRlIHRoZSBtb3N0IHRvIHRoZSBvdmVyYWxsIGxvY3VzLWxldmVsIGltcG9ydGFuY2UgaW4gdGhlIHNpUkYgZml0LiBTTlZzIGFyZSBvcmRlcmVkIG9uIHRoZSB4LWF4aXMgYnkgZ2Vub21pYyBsb2NhdGlvbi4nIiwgcGhlbm90eXBlX25hbWUsIHRocikpCiAgICAgICAgY2h1bmtfaWR4IDwtIGNodW5rX2lkeCArIDEKICAgICAgICBjYXQoIlxuXG4iKQogICAgICAgIAogICAgICAgICMgIyBoZWF0bWFwCiAgICAgICAgIyBwbHQgPC0gcmVhZFJEUygKICAgICAgICAjICAgZmlsZS5wYXRoKGZpZ19yZXNfZGlyLCAKICAgICAgICAjICAgICAgICAgICAgIHBhc3RlMChwaGVub3R5cGUsICJfdGhyIiwgdGhyLCAKICAgICAgICAjICAgICAgICAgICAgICAgICAgICAiX2xvY2FsX3N0YWJpbGl0eV9oZWF0bWFwXyIsIHR5cGUsICIucmRzIikpCiAgICAgICAgIyApCiAgICAgICAgIyBzdWJjaHVua2lmeShwbHQsIGkgPSBjaHVua19pZHgsIGZpZ19oZWlnaHQgPSBIRUFUTUFQX0hFSUdIVCwKICAgICAgICAjICAgICAgICAgICAgIGFkZF9jbGFzcyA9IGMoInBhbmVsIHBhbmVsLWRlZmF1bHQiKSwKICAgICAgICAjICAgICAgICAgICAgIG90aGVyX2FyZ3MgPSAib3V0LndpZHRoPScxMDAlJyIpCiAgICAgICAgIyBjaHVua19pZHggPC0gY2h1bmtfaWR4ICsgMQogICAgICB9CiAgICB9CiAgfQp9CgpgYGAKCgojIyBBZHZhbnRhZ2VzIG9mIFNpZ25lZCBJbmZvcm1hdGlvbiB7LnVubnVtYmVyZWQgLnRhYnNldCAudGFic2V0LXBpbGxzIC50YWJzZXQtZmFkZSAudGFic2V0LXNxdWFyZX0KCjxkaXYgY2xhc3M9InBhbmVsIHBhbmVsLWRlZmF1bHQgcGFkZGVkLXBhbmVsIj4KVGhvdWdoIHRoZSBzaWduZWQgaW5mb3JtYXRpb24gaXMgbm90IHBlcnRpbmVudCB0byBvdXIgZ29hbCBvZiBwcmlvcml0aXppbmcvcmVjb21tZW5kaW5nIGNhbmRpZGF0ZSBtYXJrZXJzIGZvciBleHBlcmltZW50cywgdGhlIHNpZ25lZCBpbmZvcm1hdGlvbiBmcm9tIHNpUkYgcHJvdmlkZXMgbW9yZSBncmFudWxhciBpbmZvcm1hdGlvbiB0aGF0IGNhbiBpbXByb3ZlIG91ciBpbnRlcnByZXRhdGlvbiBvZiB0aGUgZml0LiBUbyBzZWUgdGhpcywgc3VwcG9zZSB0aGF0IHdlIGRpZCBub3Qga2VlcCB0cmFjayBvZiB0aGUgc2lnbiBvZiB0aGUgZmVhdHVyZSB3aGVuIHNwbGl0dGluZyAoaS5lLiwgdGhhdCB3ZSBkbyBub3Qga2VlcCB0cmFjayBvZiB3aGV0aGVyIHdlIHNwbGl0IG9uIGxvdyBvciBoaWdoIHZhbHVlcyBvZiB0aGUgZmVhdHVyZSkuIFN1cHBvc2UgYWxzbyB0aGF0IHdlIHdvdWxkIGxpa2UgdG8gbWVhc3VyZSB0aGUgaW1wb3J0YW5jZSBvZiBmZWF0dXJlICRYXzEkLCB3aGljaCB3YXMgdXNlZCBhcyB0aGUgZmlyc3QgKHJvb3QpIHNwbGl0IGluIHRyZWUgJFQkLiBJbiB0aGUgZmlyc3Qgc3RlcCBpbiBvdXIgbmV3IGltcG9ydGFuY2Ugc2NvcmUgY29tcHV0YXRpb24sIHdlIGNvbXB1dGUgdGhlIGxvY2FsIHN0YWJpbGl0eSBpbXBvcnRhbmNlIChMU0kpIHNjb3JlIG9mICRYXzEkIGZvciBlYWNoIGluZGl2aWR1YWwgJGkkLiBJZiB3ZSBkbyBub3Qga2VlcCB0cmFjayBvZiB0aGUgc2lnbiBvZiB0aGUgJFhfMSQgc3BsaXQsIHRoZW4gJFhfMSQgYXBwZWFycyBvbiBldmVyeSBpbmRpdmlkdWFsJ3MgZGVjaXNpb24gcGF0aCBzbyB0aGF0ICRMU0lfVChYXzEsIGkpID0gMSQgZm9yIGV2ZXJ5IGluZGl2aWR1YWwgJGkkLiBJbiB0aGUgbmV4dCBzdGVwIG9mIG91ciBuZXcgaW1wb3J0YW5jZSBzY29yZSBjb21wdXRhdGlvbiwgd2UgcGVyZm9ybSBhIHBlcm11dGF0aW9uIHRlc3QgdG8gYXNzZXNzIHdoZXRoZXIgdGhlcmUgaXMgYSBkaWZmZXJlbmNlIGluIHRoZSBMU0kgc2NvcmVzIGZvciBpbmRpdmlkdWFscyB3aXRoIGhpZ2ggTFZNaSBhbmQgdGhvc2Ugd2l0aCBsb3cgTFZNaS4gU2luY2UgJExTSV9UKFhfMSwgaSkgPSAxJCBmb3IgZXZlcnkgJGkkLCB0aGlzIHBlcm11dGF0aW9uIHRlc3Qgd2lsbCByZXR1cm4gYSBwLXZhbHVlIG9mIDEuIFRoaXMgc3VnZ2VzdHMgdGhhdCAkWF8xJCBpcyBhbiB1bmltcG9ydGFudCBmZWF0dXJlIGluIHRoaXMgbW9kZWwuIEhvd2V2ZXIsIHRoaXMgaXMgY291bnRlcmludHVpdGl2ZSBnaXZlbiB0aGF0ICRYXzEkIHdhcyBzcGxpdCBvbiBmaXJzdCBpbiB0aGUgdHJlZSBhbmQgc2hvdWxkIGJlIGNvbnNpZGVyZWQgb25lIG9mIHRoZSBtb3N0IGltcG9ydGFudCBmZWF0dXJlcyBpbiB0aGlzIHRyZWUuIEJ5IGtlZXBpbmcgdHJhY2sgb2YgdGhlIHNpZ25lZCBpbmZvcm1hdGlvbiBvZiB0aGUgc3BsaXRzIGFzIGRvbmUgaW4gc2lSRiwgd2UgY2FuIHV0aWxpemUgdGhpcyBtb3JlIGdyYW51bGFyIGluZm9ybWF0aW9uIHRvIG1pdGlnYXRlIHRoZSBpc3N1ZSBkaXNjdXNzZWQgYWJvdmUgYW5kIGltcHJvdmUgb3VyIGludGVycHJldGF0aW9uIG9mIHRoZSBzaVJGIGZpdC4KCk1vcmVvdmVyLCB0byBmYWNpbGl0YXRlIHRoZSBpbnRlcnByZXRhdGlvbiBvZiB0aGlzIHNpZ25lZCBpbmZvcm1hdGlvbiwgaXQgY2FuIGJlIGJlbmVmaWNpYWwgdG8gYWdncmVnYXRlIFNOViBmZWF0dXJlcyB0aGF0IGFyZSAqcG9zaXRpdmVseSogY29ycmVsYXRlZCAoYXMgb3Bwb3NlZCB0byBuZWdhdGl2ZWx5IGNvcnJlbGF0ZWQpIGludG8gYSBzaW5nbGUgbG9jdXMgKG9yIGdyb3VwKS4gU2luY2UgdGhlIGVuY29kaW5nIG9mIFNOVnMgYXMgYSB2YWx1ZSB0YWtpbmcgb24gMCwgMSwgb3IgMiBpcyByYXRoZXIgYXJiaXRyYXJ5IChlLmcuLCBhIHZhbHVlIG9mIDAgY2FuIGJlIHJlLWVuY29kZWQgdG8gdGFrZSBvbiB0aGUgdmFsdWUgb2YgMiBieSBjaGFuZ2luZyB0aGUgcmVmZXJlbmNlIGFsbGVsZSksIHdlIGNhbiBjaG9vc2UgdGhlIGVuY29kaW5nIG9mIHRoZSBTTlYgdG8gdHJ5IHRvIGF2b2lkIHN0cm9uZyBuZWdhdGl2ZSBjb3JyZWxhdGlvbnMgd2l0aGluIGEgbG9jdXMuIE1vcmUgc3BlY2lmaWNhbGx5LCBmb3IgZWFjaCBnZW5ldGljIGxvY3VzIHdoaWNoIGNvbnNpc3RzIG9mIFNOVnMgJFhfMSwgXGxkb3RzLCBYX2ckLCB3ZSBjaG9vc2UgdG8gImZsaXAiIHRoZSBlbmNvZGluZyBvZiB0aGUgU05WICRYX2okICgkaiA9IDIsIFxsZG90cywgZyQpIGlmIHRoZSBQZWFyc29uIGNvcnJlbGF0aW9uIGJldHdlZW4gdGhlIG9ic2VydmVkIHZhbHVlcyBvZiAkWF9qJCBhbmQgJFhfMSQgaXMgYmVsb3cgLTAuMTUuIEhlcmUsIHdlIHVzZSB0aGUgdGVybSAiZmxpcCIgdG8gbWVhbiB0aGUgYXBwbGljYXRpb24gb2YgdGhlIGZ1bmN0aW9uIHRoYXQgbWFwcyAwIHRvIDIsIDEgdG8gMSwgYW5kIDIgdG8gMC4gVGhpcyBjb3JyZWxhdGlvbiB0aHJlc2hvbGQgb2YgLTAuMTUgd2FzIGNob3NlbiBieSB2aXN1YWxseSBpbnNwZWN0aW5nIHRoZSByZXN1bHRpbmcgcGFpcndpc2UgY29ycmVsYXRpb25zIGJldHdlZW4gJFhfaSQgYW5kICRYX2okIGZvciBhbGwgJGksIGogPSAxLCBcbGRvdHMsIGckIGFuZCBjaGVja2luZyB0aGF0IHRoZXNlIHBhaXJ3aXNlIGNvcnJlbGF0aW9ucyBhcmUgbm90IHN0cm9uZ2x5IG5lZ2F0aXZlLiBIb3dldmVyLCB3aGlsZSB3ZSBmb2N1cyBvbiB0aGUgbG8tc2lSRiBwcmlvcml0aXphdGlvbiByZXN1bHRzIHVzaW5nIHRoaXMgY29ycmVsYXRpb24gdGhyZXNob2xkIG9mIC0wLjE1LCB0aGUgcmVzdWx0cyBhcHBlYXIgdG8gYmUgcm9idXN0IHRvIG90aGVyIHJlYXNvbmFibGUgY29ycmVsYXRpb24gdGhyZXNob2xkIGNob2ljZXMgKGUuZy4sIC0wLjA1LCAtMC4yNSkuIEZ1cnRoZXIgYW5hbHlzaXMgYW5kIGltcHJvdmVtZW50cyB0byB0aGlzIHByb2NlZHVyZSBhcmUgdmVyeSBpbnRlcmVzdGluZyBmb3IgZnV0dXJlIHdvcmsuCjwvZGl2PgoKCiMgRmluYWwgUmVtYXJrcwoKPGRpdiBjbGFzcz0icGFuZWwgcGFuZWwtZGVmYXVsdCBwYWRkZWQtcGFuZWwiPgpXZSByZWl0ZXJhdGUgdGhhdCBsby1zaVJGIHdhcyBvcmlnaW5hbGx5IGRldmVsb3BlZCBhcyBhIGZpcnN0LXN0YWdlIHJlY29tbWVuZGF0aW9uIChvciBoeXBvdGhlc2lzIGdlbmVyYXRpb24pIHRvb2wgd2l0aGluIGEgYnJvYWRlciBwaXBlbGluZSBpbiBvcmRlciB0byBwcmlvcml0aXplIGdlbmV0aWMgbG9jaSBhbmQgaW50ZXJhY3Rpb25zIGJldHdlZW4gbG9jaSBmb3IgZG93bnN0cmVhbSBhbmFseXNlcyBhbmQgZXhwZXJpbWVudGFsIHZhbGlkYXRpb24uIEltcG9ydGFudGx5LCB0aGUgb3V0cHV0IG9mIGxvLXNpUkYgaXMgYSBwcmlvcml0aXphdGlvbi9yYW5raW5nIG9yZGVyLCBub3QgYSBwcm9wZXIgc3RhdGlzdGljYWwgdGVzdCBvZiBzaWduaWZpY2FuY2UuIFdlIHJlbHkgb24gZm9sbG93LXVwIGludmVzdGlnYXRpb25zIGFuZCBpbiB0aGlzIHN0dWR5IHJpZ29yb3VzIGdlbmUtc2lsZW5jaW5nIGV4cGVyaW1lbnRzIGluIG9yZGVyIHRvIHZhbGlkYXRlIHRoZSBwcmlvcml0aXplZCBnZW5ldGljIGxvY2kgYW5kIGludGVyYWN0aW9uIGJldHdlZW4gbG9jaS4gV2l0aCB0aGF0LCBtYW55IG9mIHRoZSBtb2RlbGluZyBkZWNpc2lvbnMgYW5kIGh1bWFuIGp1ZGdtZW50IGNhbGxzIHdlcmUgbWFkZSB3aXRoIHRoaXMgb3JpZ2luYWwgdXNlIGNhc2UgaW4gbWluZC4gRm9yIG90aGVyIHVzZSBjYXNlcyBvciBwcm9ibGVtcywgaXQgaXMgaGlnaGx5IGxpa2VseSB0aGF0IGRpZmZlcmVudCBjaG9pY2VzIG1heSBiZSBiZXR0ZXIgc3VpdGVkLiBXZSBhbHNvIGFja25vd2xlZGdlIHRoYXQgdGhvdWdoIG1hbnkgc3RhYmlsaXR5IGNoZWNrcyB3ZXJlIGNvbmR1Y3RlZCB0byBoZWxwIGVuc3VyZSB0aGF0IG91ciBjb25jbHVzaW9ucyBhcmUgc3RhYmxlIGFjcm9zcyBkaWZmZXJlbnQgcmVhc29uYWJsZSBkYXRhIGFuZC9vciBtb2RlbGluZyBwZXJ0dXJiYXRpb25zLCB0aGVzZSBzdGFiaWxpdHkgY2hlY2tzIGFyZSBpbmV2aXRhYmx5IGNvbnN0cmFpbmVkIGJ5IGNvbXB1dGF0aW9uYWwgbGltaXRhdGlvbnMsIGFuZCBhZGRpdGlvbmFsIHN0YWJpbGl0eSBhbmFseXNlcyBjYW4gYmUgY29uZHVjdGVkLiBXZSBob3BlIHRoYXQgYnkgZG9jdW1lbnRpbmcgb3VyIG1vZGVsaW5nIGNob2ljZXMsIHN0YWJpbGl0eSBhbmFseXNlcywgYW5kIHByb3ZpZGluZyBpbnNpZ2h0cyBpbnRvIG91ciBtb3RpdmF0aW9ucy9yZWFzb25zLCB0aGlzIG1heSBoZWxwIHRvIGJvdGggY2xhcmlmeSB0aGUgbGltaXRhdGlvbnMgb2Ygb3VyIGN1cnJlbnQgd29yayBhbmQgdG8gZmFjaWxpdGF0ZSB0aGUgdHJ1c3R3b3J0aHkgKHZlcmlkaWNhbCkgdXNlIG9mIGxvLXNpUkYgKGFuZCB2YXJpYW50cyB0aGVyZW9mKSBpbiBvdGhlciBzY2llbnRpZmljIHByb2JsZW1zLgo8L2Rpdj4KCiMgQmlibGlvZ3JhcGh5Cgo8ZGl2IGNsYXNzPSJwYW5lbCBwYW5lbC1kZWZhdWx0IHBhZGRlZC1wYW5lbCI+CjxkaXYgaWQ9InJlZnMiPjwvZGl2Pgo8L2Rpdj4=