Science/Health/Data Science Module

Topic 7B: Big Data II (\(p\)-value adjustments)


Welcome to the seventh computer lab for the Science, Health Science and Data Science modules.

In this computer lab we will look at methods for adjusting \(p\)-values obtained when conducting multiple inferences.

This computer lab introduces some biology terminology. Therefore, it is recommended that you read over section 2 of the Foundational Biology for Analyses of Biological Data supplement. The material in this supplement provides all the background information you will need.

By the end of this lab, you should understand how to adjust \(p\)-values to counteract the effects of conducting multiple tests simultaneously. Let’s get started!

1 Introduction

By now, you should be familiar with the concept of a hypothesis test. You should also feel comfortable conducting a statistical test that involves computing a \(p\)-value to compare a null hypothesis against an alternative hypothesis.

A simple example would be an independent samples \(t\)-test to assess the difference in the mean value of a variable between two groups.

In many situations however, we may be interested in performing a hypothesis test on multiple features simultaneously. For example, in analyses of biological data, it is now common for thousands (or hundreds of thousands) of features to be simultaneously tested against a null hypothesis (where the expectation is that a number of features will be statistically significant).

Unfortunately, when we conduct multiple tests, the probability of obtaining a false positive (aka Type I error) will increase, meaning that the original significance level of \(\alpha\) designated for a single test does not hold.

Type I error probability example

As a simple example, suppose that we set \(\alpha = 0.05\) for a single test. Therefore, the probability of not observing a Type I error for this test is \(1-\alpha = 0.95\).

So far, so good.

However, if we use this level of significance and carry out 10 tests, then the probability of not observing a Type I error in any of these 10 tests becomes \((1 - \alpha)^{10} \approx 0.6\).

In other words, by carrying out multiple testing, our probability of observing at least one Type I error has increased from \(5\%\) to \(40\%\)! As the number of tests increases, this error rate will continue to rise.

2 Adjusting \(p\)-values

Fortunately, there are several statistical methods we can use to adjust \(p\)-values obtained from performing multiple tests. We have already come across one such adjustment in the Topic 7 Readings: the Tukey adjustment, which was used to carry out post-hoc tests after carrying out a One-way ANOVA.

In this computer lab, we will learn about other types of adjustments which may be more appropriate in different settings. Most of these adjustments can be applied using the built-in R function p.adjust. Let’s take a look.

2.1

Suppose that we have compared gene expression levels between two groups of individuals (cases and controls) for 10 key genes of interest. As a result, we have obtained a set of 10 \(p\)-values (one for each gene). These \(p\)-values are presented below:

\(0.0003, 0.0085, 0.001, 0.0001, 0.045, 0.62, 0.009, 0.18, 0.92, 0.02.\)

Store these values in a vector called base_p_values in R.

2.2

Recall that we say a gene is differentially expressed if it exhibits a large change in expression between two groups (e.g. between cases and controls).

If we assessed the \(p\)-values above, how many genes would we find to have statistically significant differential expression between the cases and controls, based on an \(\alpha\) value of \(0.05\)?

2.3

A simple way to adjust our initial \(p\)-values is to multiply each \(p\)-value by the overall number of \(p\)-values we have (with any resultant values over 1 scaled back to 1). This is known as the Bonferroni correction method.

Run the R code below to conduct this adjustment:

p.adjust(base_p_values, method = "bonferroni")

2.4

Assessing the adjusted \(p\)-values, how many of the genes remain statistically significantly differentially expressed, at the \(\alpha = 0.05\) level of significance?

2.5

As you will have noticed, the Bonferroni correction is quite conservative, and in practice can often lead to rejecting true positives (especially when dealing with larger numbers of tests). This is because the adjustment method focuses on controlling the probability of making one or more Type I errors when conducting multiple tests. This probability is known as the family-wise error rate (FWER).

The p.adjust function contains options for several other methods which focus on controlling the FWER.

Compare and contrast your results, using the R code below as a guide:

# Here we use the `holm` method to compute the number of significant results
sum(p.adjust(base_p_values, method = "holm") < .05)

3 False Discovery Rate

A more flexible and more powerful alternative to controlling the FWER is to control the False Discovery Rate (FDR) when conducting multiple tests. When dealing with Big Data, using the FDR is generally preferred over more conservative adjustments such as Bonferonni correction. FDR control is also typically favoured over FWER control in biological studies involving Big Data1.

The FDR can be defined as the expected proportion of errors (i.e. false discoveries) among the rejected hypotheses2. Controlling the FDR helps to reduce false positives, but also helps minimise false negatives.

3.1

We can apply FDR correction to \(p\)-values using the R function p.adjust - just specify the method fdr.

Try this now, on our base_p_values vector of \(p\)-values.

3.2

Compare your FDR results from 3.1 to your Bonferroni correction results in 2.3. What do you notice?

4 SARS-CoV-2 Study \(p\)-values

To conclude this computer lab, let’s take a look at a real-world application of \(p\)-value adjustment, in the context of biological data.

For this example, we will consider a subset of SARS-CoV-2 (Coronavirus) gene expression profiling data, from a study by Lee et al. (2022). Information on the study can be found here and the full data set is publicly available on the NCBI Gene Expression Omnibus website3.

The study considered the VIC and B.1.1.7 (Alpha) strains of SARS-CoV-2, which have different replication and transmission characteristics. Samples were taken of human cells at several time points following infection with either of these two strains. Gene expression differences were then assessed, and \(p\)-values were computed for each gene, with a small \(p\)-value suggesting the gene was statistically significantly differentially expressed at that time point, between the two strains.

4.1

The data we will assess is stored in the file SARS_data_subset.csv which is available on the LMS. The table below provides an example of some recorded values for the different variables (the column names) in this data set. Don’t worry about all these names just yet - we will discuss them as we work through this question.

gene_name gene_biotype log2FoldChange.Alpha_8h_vs_VIC_8h pvalue.Alpha_8h_vs_VIC_8h
MTND2P28 unprocessed_pseudogene 0.2355462 0.2222321
LINC01128 lncRNA 0.0289815 0.7729915
NOC2L protein_coding -0.0154409 0.8024931
PLEKHN1 protein_coding 0.0922164 0.4848935

4.2

Download the file SARS_data_subset.csv from LMS now.

Save the SARS_data_subset.csv file in your working directory, then read the SARS_data_subset.csv file into RStudio, and store it in an object called sars_data.

Hint: Recall that you can use the function read.csv to load a .csv file into RStudio.

4.3

The \(p\)-values stored in the sars_data.csv file were computed for gene expression comparisons between the VIC and Alpha strains at 8 hours post-infection.

Run the R code below to determine the number of genes that are considered statistically significantly differentially expressed between the two strains at the 8 hour post-infection mark, for an \(\alpha = 0.05\) level of significance.

# First, we select only the values in the 
# `pvalue.Alpha_8h_vs_VIC_8h` column that are less than 0.05
sars_data_8h_base <- sars_data[sars_data$pvalue.Alpha_8h_vs_VIC_8h < 0.05,]
# Then we assess the number of rows remaining - each row represents a gene
nrow(sars_data_8h_base)

4.4

Use the p.adjust function to perform FDR correction on the pvalue.Alpha_8h_vs_VIC_8h \(p\)-values, just like you did in 3.1. Store your results in a new column in the sars_data object.

You can use the R code below as a starting point - just fill in the missing ...’s.

sars_data$fdr_adjusted_pvalue_8h <- ...

Note that the $fdr_adjusted_pvalue_8h part of the code above instructs R to add a new column called fdr_adjusted_pvalue_8h to the sars_data object, with the values you specify in the ... part added as the column values.

4.5

Determine the number of genes at the 8 hour post-infection mark that are, according to your FDR results, statistically significantly differentially expressed for an FDR level of \(0.05\). Compare this with your initial results.

Hint: Use the R code in 4.3 as a guide.

4.6 Volcano Plots

In addition to the statistical significance of the gene expression differences, we are also interested in biological significance.

Notice in the sars_data file that there is a column labelled log2FoldChange.Alpha_8h_vs_VIC_8h. The values recorded in this column denote the log ratio of the change in gene expression status between the two strains, for each gene. If there is no difference in the gene expression status, the ratio would be 1, e.g.: \[\frac{4.2 \text{ for VIC strain}}{4.2 \text{ for Alpha strain}} = 1\text{, with }\log_2(1) = 0.\]

So log2FoldChange.Alpha_8h_vs_VIC_8h values close to or equal to 0 suggest there is no biologically significant change in gene expression between the two strains. In contrast, values far from 0 suggest there is a biologically significant change.

In gene expression analyses, a Volcano plot can be used to highlight genes which are statistically and biologically significant (these genes are probably the most important to consider in further detail).

Run the R code below to create two volcano plots for our modified sars_data file. As you can see, the volcano plot is a bit like a scatter plot.

plot(sars_data$log2FoldChange.Alpha_8h_vs_VIC_8h, 
     -log10(sars_data$pvalue.Alpha_8h_vs_VIC_8h), 
     main = "Volcano Plot for SARS-CoV-2 
     VIC and Alpha strains
     8h post-infection, using initial p-values",
     xlab = "log FC", ylab = "-log10(pval)",
     cex = 0.5, col = as.numeric(sars_data$pvalue.Alpha_8h_vs_VIC_8h <= 0.05) + 1)

plot(sars_data$log2FoldChange.Alpha_8h_vs_VIC_8h, 
     -log10(sars_data$fdr_adjusted_pvalue_8h), 
     main = "Volcano Plot for SARS-CoV-2 
     VIC and Alpha strains
     8h post-infection, using FDR-corrected p-values",
     xlab = "log FC", ylab = "-log10(pval)",
     cex = 0.5, col = as.numeric(sars_data$fdr_adjusted_pvalue_8h <= 0.05) + 1)

4.7

Each point in the volcano plots represents a gene. In the first plot, genes with small \(p\)-values are coloured red. In the second plot, genes with small FDR-corrected \(p\)-values are coloured red. All other genes are coloured black.

What differences do you observe between the two plots? Do you think the FDR correction has been beneficial?


Great job, that’s everything for today.

If you have any questions about Assessments, please ask for help.


References

Benjamini, Y., and Y. Hochberg. 1995. “Controlling the False Discovery Rate: A Practical and Powerful Approach to Multiple Testing.” J. R. Statist. Soc. B 57 (1): 289–300.
Lee, J. Y., P. A. C. Wing, D. S. Gala, M. Noerenberg, A. I. Järvelin, J. Titlow, X. Zhuang, et al. 2022. “Absolute Quantitation of Individual SARS-CoV-2 RNA Molecules Provides a New Paradigm for Infection Dynamics and Variant Differences.” Elife 11: e74153. https://doi.org/10.7554/eLife.74153.
Storey, J. D., and R. Tibshirani. 2003. “Statistical Significance for Genomewide Studies.” PNAS 100 (16): 9440–45.


These notes have been prepared by Rupert Kuveke and Amanda Shaker. The copyright for the material in these notes resides with the authors named above, with the Department of Mathematical and Physical Sciences and with La Trobe University. Copyright in this work is vested in La Trobe University including all La Trobe University branding and naming. Unless otherwise stated, material within this work is licensed under a Creative Commons Attribution-Non Commercial-Non Derivatives License BY-NC-ND.


  1. See e.g. Storey and Tibshirani (2003).↩︎

  2. See Benjamini and Hochberg (1995).↩︎

  3. Series GSE184932.↩︎

LS0tDQp0aXRsZTogIlNUTTEwMDE6IENvbXB1dGVyIExhYiA3QiINCm91dHB1dDoNCiAgYm9va2Rvd246Omh0bWxfZG9jdW1lbnQyOiANCiAgICB0b2M6IHRydWUNCiAgICB0b2NfZmxvYXQ6IHRydWUNCiAgICBjb2RlX2Rvd25sb2FkOiB0cnVlDQogICAgdGhlbWU6IHJlYWRhYmxlDQogICAgY29kZV9mb2xkaW5nOiBzaG93DQpiaWJsaW9ncmFwaHk6IFNUTTEwMDFfRFNfQ0xfcmVmZXJlbmNlcy5iaWIgDQpsaW5rLWNpdGF0aW9uczogeWVzDQotLS0NCg0KPHN0eWxlPg0KI1RPQyB7DQogIGJhY2tncm91bmQ6IHVybCgiaHR0cHM6Ly93d3cubGF0cm9iZS5lZHUuYXUvX21lZGlhL2xhLXRyb2JlLWFwaS92NS9pbWcvbG9nby5zdmciKTsNCiAgYmFja2dyb3VuZC1zaXplOiBjb250YWluOw0KICBwYWRkaW5nLXRvcDogODBweCAhaW1wb3J0YW50Ow0KICBiYWNrZ3JvdW5kLXJlcGVhdDogbm8tcmVwZWF0Ow0KfQ0KPC9zdHlsZT4NCg0KIyMjIFNjaWVuY2UvSGVhbHRoL0RhdGEgU2NpZW5jZSBNb2R1bGUgey19DQoNCiMjIyBUb3BpYyA3QjogQmlnIERhdGEgSUkgKCRwJC12YWx1ZSBhZGp1c3RtZW50cykgey19DQoNCjxicj4NCg0KV2VsY29tZSB0byB0aGUgc2V2ZW50aCBjb21wdXRlciBsYWIgZm9yIHRoZSBTY2llbmNlLCBIZWFsdGggU2NpZW5jZSBhbmQgRGF0YSBTY2llbmNlIG1vZHVsZXMuDQoNCkluIHRoaXMgY29tcHV0ZXIgbGFiIHdlIHdpbGwgbG9vayBhdCBtZXRob2RzIGZvciBhZGp1c3RpbmcgJHAkLXZhbHVlcyBvYnRhaW5lZCB3aGVuIGNvbmR1Y3RpbmcgbXVsdGlwbGUgaW5mZXJlbmNlcy4NCg0KVGhpcyBjb21wdXRlciBsYWIgaW50cm9kdWNlcyBzb21lIGJpb2xvZ3kgdGVybWlub2xvZ3kuIFRoZXJlZm9yZSwgaXQgaXMgcmVjb21tZW5kZWQgdGhhdCB5b3UgcmVhZCBvdmVyIHNlY3Rpb24gMiBvZiB0aGUgW0ZvdW5kYXRpb25hbCBCaW9sb2d5IGZvciBBbmFseXNlcyBvZiBCaW9sb2dpY2FsIERhdGEgc3VwcGxlbWVudF0oaHR0cHM6Ly9ib29rZG93bi5vcmcvcmVoay9zdG0xMDAxX3QxX2ZvdW5kYXRpb25hbF9iaW9sb2d5X2Zvcl9hbmFseXNlc19vZl9iaW9sb2dpY2FsX2RhdGEvKS4gVGhlIG1hdGVyaWFsIGluIHRoaXMgc3VwcGxlbWVudCBwcm92aWRlcyBhbGwgdGhlIGJhY2tncm91bmQgaW5mb3JtYXRpb24geW91IHdpbGwgbmVlZC4gDQoNCkJ5IHRoZSBlbmQgb2YgdGhpcyBsYWIsIHlvdSBzaG91bGQgdW5kZXJzdGFuZCBob3cgdG8gYWRqdXN0ICRwJC12YWx1ZXMgdG8gY291bnRlcmFjdCB0aGUgZWZmZWN0cyBvZiBjb25kdWN0aW5nIG11bHRpcGxlIHRlc3RzIHNpbXVsdGFuZW91c2x5LiBMZXQncyBnZXQgc3RhcnRlZCENCg0KYGBge3IgZXZhbCA9IFQsIGluY2x1ZGUgPSBGfQ0KaW5zdGFsbC5wYWNrYWdlcyhzZXRkaWZmKCJrYWJsZUV4dHJhIiwgcm93bmFtZXMoaW5zdGFsbGVkLnBhY2thZ2VzKCkpKSkNCmxpYnJhcnkoa2FibGVFeHRyYSkNCmBgYA0KDQojIEludHJvZHVjdGlvbg0KDQpCeSBub3csIHlvdSBzaG91bGQgYmUgZmFtaWxpYXIgd2l0aCB0aGUgY29uY2VwdCBvZiBhIGh5cG90aGVzaXMgdGVzdC4gWW91IHNob3VsZCBhbHNvIGZlZWwgY29tZm9ydGFibGUgY29uZHVjdGluZyBhIHN0YXRpc3RpY2FsIHRlc3QgdGhhdCBpbnZvbHZlcyBjb21wdXRpbmcgYSAkcCQtdmFsdWUgdG8gY29tcGFyZSBhIG51bGwgaHlwb3RoZXNpcyBhZ2FpbnN0IGFuIGFsdGVybmF0aXZlIGh5cG90aGVzaXMuDQoNCipBIHNpbXBsZSBleGFtcGxlIHdvdWxkIGJlIGFuIGluZGVwZW5kZW50IHNhbXBsZXMgJHQkLXRlc3QgdG8gYXNzZXNzIHRoZSBkaWZmZXJlbmNlIGluIHRoZSBtZWFuIHZhbHVlIG9mIGEgdmFyaWFibGUgYmV0d2VlbiB0d28gZ3JvdXBzLioNCg0KSW4gbWFueSBzaXR1YXRpb25zIGhvd2V2ZXIsIHdlIG1heSBiZSBpbnRlcmVzdGVkIGluIHBlcmZvcm1pbmcgYSBoeXBvdGhlc2lzIHRlc3Qgb24gbXVsdGlwbGUgZmVhdHVyZXMgc2ltdWx0YW5lb3VzbHkuIEZvciBleGFtcGxlLCBpbiBhbmFseXNlcyBvZiBiaW9sb2dpY2FsIGRhdGEsIGl0IGlzIG5vdyBjb21tb24gZm9yIHRob3VzYW5kcyAob3IgaHVuZHJlZHMgb2YgdGhvdXNhbmRzKSBvZiBmZWF0dXJlcyB0byBiZSBzaW11bHRhbmVvdXNseSB0ZXN0ZWQgYWdhaW5zdCBhIG51bGwgaHlwb3RoZXNpcyAod2hlcmUgdGhlIGV4cGVjdGF0aW9uIGlzIHRoYXQgYSBudW1iZXIgb2YgZmVhdHVyZXMgd2lsbCBiZSBzdGF0aXN0aWNhbGx5IHNpZ25pZmljYW50KS4NCg0KVW5mb3J0dW5hdGVseSwgd2hlbiB3ZSBjb25kdWN0IG11bHRpcGxlIHRlc3RzLCB0aGUgcHJvYmFiaWxpdHkgb2Ygb2J0YWluaW5nIGEgZmFsc2UgcG9zaXRpdmUgKGFrYSAqKlR5cGUgSSBlcnJvcioqKSB3aWxsIGluY3JlYXNlLCBtZWFuaW5nIHRoYXQgdGhlIG9yaWdpbmFsIHNpZ25pZmljYW5jZSBsZXZlbCBvZiAkXGFscGhhJCBkZXNpZ25hdGVkIGZvciBhIHNpbmdsZSB0ZXN0IGRvZXMgbm90IGhvbGQuDQoNCiMjIyBUeXBlIEkgZXJyb3IgcHJvYmFiaWxpdHkgZXhhbXBsZSB7LX0NCg0KQXMgYSBzaW1wbGUgZXhhbXBsZSwgc3VwcG9zZSB0aGF0IHdlIHNldCAkXGFscGhhID0gMC4wNSQgZm9yIGEgc2luZ2xlIHRlc3QuIFRoZXJlZm9yZSwgdGhlIHByb2JhYmlsaXR5IG9mIG5vdCBvYnNlcnZpbmcgYSBUeXBlIEkgZXJyb3IgZm9yIHRoaXMgdGVzdCBpcyAkMS1cYWxwaGEgPSAwLjk1JC4gDQoNClNvIGZhciwgc28gZ29vZC4NCg0KSG93ZXZlciwgaWYgd2UgdXNlIHRoaXMgbGV2ZWwgb2Ygc2lnbmlmaWNhbmNlIGFuZCBjYXJyeSBvdXQgMTAgdGVzdHMsIHRoZW4gdGhlIHByb2JhYmlsaXR5IG9mIG5vdCBvYnNlcnZpbmcgYSBUeXBlIEkgZXJyb3IgaW4gYW55IG9mIHRoZXNlIDEwIHRlc3RzIGJlY29tZXMgJCgxIC0gXGFscGhhKV57MTB9IFxhcHByb3ggMC42JC4gDQoNCkluIG90aGVyIHdvcmRzLCBieSBjYXJyeWluZyBvdXQgbXVsdGlwbGUgdGVzdGluZywgb3VyIHByb2JhYmlsaXR5IG9mIG9ic2VydmluZyBhdCBsZWFzdCBvbmUgVHlwZSBJIGVycm9yIGhhcyBpbmNyZWFzZWQgZnJvbSAkNVwlJCB0byAkNDBcJSQhIEFzIHRoZSBudW1iZXIgb2YgdGVzdHMgaW5jcmVhc2VzLCB0aGlzIGVycm9yIHJhdGUgd2lsbCBjb250aW51ZSB0byByaXNlLg0KDQojIEFkanVzdGluZyAkcCQtdmFsdWVzDQoNCkZvcnR1bmF0ZWx5LCB0aGVyZSBhcmUgc2V2ZXJhbCBzdGF0aXN0aWNhbCBtZXRob2RzIHdlIGNhbiB1c2UgdG8gYWRqdXN0ICRwJC12YWx1ZXMgb2J0YWluZWQgZnJvbSBwZXJmb3JtaW5nIG11bHRpcGxlIHRlc3RzLg0KV2UgaGF2ZSBhbHJlYWR5IGNvbWUgYWNyb3NzIG9uZSBzdWNoIGFkanVzdG1lbnQgaW4gdGhlIFtUb3BpYyA3IFJlYWRpbmdzXShodHRwczovL2Jvb2tkb3duLm9yZy9hX3NoYWtlci9TVE0xMDAxX1RvcGljXzcvNS1wb3N0LWhvYy10ZXN0cy5odG1sKTogdGhlIFR1a2V5IGFkanVzdG1lbnQsIHdoaWNoIHdhcyB1c2VkIHRvIGNhcnJ5IG91dCBwb3N0LWhvYyB0ZXN0cyBhZnRlciBjYXJyeWluZyBvdXQgYSBPbmUtd2F5IEFOT1ZBLiANCg0KSW4gdGhpcyBjb21wdXRlciBsYWIsIHdlIHdpbGwgbGVhcm4gYWJvdXQgb3RoZXIgdHlwZXMgb2YgYWRqdXN0bWVudHMgd2hpY2ggbWF5IGJlIG1vcmUgYXBwcm9wcmlhdGUgaW4gZGlmZmVyZW50IHNldHRpbmdzLiANCk1vc3Qgb2YgdGhlc2UgYWRqdXN0bWVudHMgY2FuIGJlIGFwcGxpZWQgdXNpbmcgdGhlIGJ1aWx0LWluIFIgZnVuY3Rpb24gYHAuYWRqdXN0YC4gTGV0J3MgdGFrZSBhIGxvb2suDQoNCiMjDQoNClN1cHBvc2UgdGhhdCB3ZSBoYXZlIGNvbXBhcmVkIGdlbmUgZXhwcmVzc2lvbiBsZXZlbHMgYmV0d2VlbiB0d28gZ3JvdXBzIG9mIGluZGl2aWR1YWxzIChjYXNlcyBhbmQgY29udHJvbHMpIGZvciAxMCBrZXkgZ2VuZXMgb2YgaW50ZXJlc3QuIEFzIGEgcmVzdWx0LCB3ZSBoYXZlIG9idGFpbmVkIGEgc2V0IG9mIDEwICRwJC12YWx1ZXMgKG9uZSBmb3IgZWFjaCBnZW5lKS4gVGhlc2UgJHAkLXZhbHVlcyBhcmUgcHJlc2VudGVkIGJlbG93Og0KDQokMC4wMDAzLCAwLjAwODUsIDAuMDAxLCAwLjAwMDEsIDAuMDQ1LCAwLjYyLCAwLjAwOSwgMC4xOCwgMC45MiwgMC4wMi4kDQoNClN0b3JlIHRoZXNlIHZhbHVlcyBpbiBhIHZlY3RvciBjYWxsZWQgYGJhc2VfcF92YWx1ZXNgIGluIFIuDQoNCiMjDQoNClJlY2FsbCB0aGF0IHdlIHNheSBhIGdlbmUgaXMgZGlmZmVyZW50aWFsbHkgZXhwcmVzc2VkIGlmIGl0IGV4aGliaXRzIGEgbGFyZ2UgY2hhbmdlIGluIGV4cHJlc3Npb24gYmV0d2VlbiB0d28gZ3JvdXBzIChlLmcuIGJldHdlZW4gY2FzZXMgYW5kIGNvbnRyb2xzKS4gDQoNCklmIHdlIGFzc2Vzc2VkIHRoZSAkcCQtdmFsdWVzIGFib3ZlLCBob3cgbWFueSBnZW5lcyB3b3VsZCB3ZSBmaW5kIHRvIGhhdmUgc3RhdGlzdGljYWxseSBzaWduaWZpY2FudCBkaWZmZXJlbnRpYWwgZXhwcmVzc2lvbiBiZXR3ZWVuIHRoZSBjYXNlcyBhbmQgY29udHJvbHMsIGJhc2VkIG9uIGFuICRcYWxwaGEkIHZhbHVlIG9mICQwLjA1JD8NCg0KIyMgeyNib25mZXJyb25pfQ0KDQpBIHNpbXBsZSB3YXkgdG8gYWRqdXN0IG91ciBpbml0aWFsICRwJC12YWx1ZXMgaXMgdG8gbXVsdGlwbHkgZWFjaCAkcCQtdmFsdWUgYnkgdGhlIG92ZXJhbGwgbnVtYmVyIG9mICRwJC12YWx1ZXMgd2UgaGF2ZSAod2l0aCBhbnkgcmVzdWx0YW50IHZhbHVlcyBvdmVyIDEgc2NhbGVkIGJhY2sgdG8gMSkuIFRoaXMgaXMga25vd24gYXMgdGhlICpCb25mZXJyb25pIGNvcnJlY3Rpb24qICBtZXRob2QuDQoNClJ1biB0aGUgUiBjb2RlIGJlbG93IHRvIGNvbmR1Y3QgdGhpcyBhZGp1c3RtZW50Og0KDQpgYGB7ciBjbGFzcy5zb3VyY2UgPSAiZm9sZC1zaG93IiwgZXZhbCA9IEYsIGVjaG8gPSBULCB3YXJuaW5nID0gRiwgbWVzc2FnZSA9IEZ9DQpwLmFkanVzdChiYXNlX3BfdmFsdWVzLCBtZXRob2QgPSAiYm9uZmVycm9uaSIpDQpgYGANCg0KIyMNCg0KQXNzZXNzaW5nIHRoZSBhZGp1c3RlZCAkcCQtdmFsdWVzLCBob3cgbWFueSBvZiB0aGUgZ2VuZXMgcmVtYWluIHN0YXRpc3RpY2FsbHkgc2lnbmlmaWNhbnRseSBkaWZmZXJlbnRpYWxseSBleHByZXNzZWQsIGF0IHRoZSAkXGFscGhhID0gMC4wNSQgbGV2ZWwgb2Ygc2lnbmlmaWNhbmNlPw0KDQojIyB7I2hvbG19DQoNCkFzIHlvdSB3aWxsIGhhdmUgbm90aWNlZCwgdGhlIEJvbmZlcnJvbmkgY29ycmVjdGlvbiBpcyBxdWl0ZSBjb25zZXJ2YXRpdmUsIGFuZCBpbiBwcmFjdGljZSBjYW4gb2Z0ZW4gbGVhZCB0byByZWplY3RpbmcgdHJ1ZSBwb3NpdGl2ZXMgKGVzcGVjaWFsbHkgd2hlbiBkZWFsaW5nIHdpdGggbGFyZ2VyIG51bWJlcnMgb2YgdGVzdHMpLg0KVGhpcyBpcyBiZWNhdXNlIHRoZSBhZGp1c3RtZW50IG1ldGhvZCBmb2N1c2VzIG9uIGNvbnRyb2xsaW5nIHRoZSBwcm9iYWJpbGl0eSBvZiBtYWtpbmcgKipvbmUgb3IgbW9yZSoqIFR5cGUgSSBlcnJvcnMgd2hlbiBjb25kdWN0aW5nIG11bHRpcGxlIHRlc3RzLiBUaGlzIHByb2JhYmlsaXR5IGlzIGtub3duIGFzIHRoZSAqZmFtaWx5LXdpc2UgZXJyb3IgcmF0ZSogKEZXRVIpLg0KDQpUaGUgYHAuYWRqdXN0YCBmdW5jdGlvbiBjb250YWlucyBvcHRpb25zIGZvciBzZXZlcmFsIG90aGVyIG1ldGhvZHMgd2hpY2ggZm9jdXMgb24gY29udHJvbGxpbmcgdGhlIEZXRVIuDQoNCkNvbXBhcmUgYW5kIGNvbnRyYXN0IHlvdXIgcmVzdWx0cywgdXNpbmcgdGhlIFIgY29kZSBiZWxvdyBhcyBhIGd1aWRlOg0KDQpgYGB7ciBjbGFzcy5zb3VyY2UgPSAiZm9sZC1zaG93IiwgZXZhbCA9IEYsIGVjaG8gPSBULCB3YXJuaW5nID0gRiwgbWVzc2FnZSA9IEZ9DQojIEhlcmUgd2UgdXNlIHRoZSBgaG9sbWAgbWV0aG9kIHRvIGNvbXB1dGUgdGhlIG51bWJlciBvZiBzaWduaWZpY2FudCByZXN1bHRzDQpzdW0ocC5hZGp1c3QoYmFzZV9wX3ZhbHVlcywgbWV0aG9kID0gImhvbG0iKSA8IC4wNSkNCmBgYA0KDQojIEZhbHNlIERpc2NvdmVyeSBSYXRlDQoNCkEgbW9yZSBmbGV4aWJsZSBhbmQgbW9yZSBwb3dlcmZ1bCBhbHRlcm5hdGl2ZSB0byBjb250cm9sbGluZyB0aGUgRldFUiBpcyB0byBjb250cm9sIHRoZSAqRmFsc2UgRGlzY292ZXJ5IFJhdGUqIChGRFIpIHdoZW4gY29uZHVjdGluZyBtdWx0aXBsZSB0ZXN0cy4gV2hlbiBkZWFsaW5nIHdpdGggQmlnIERhdGEsIHVzaW5nIHRoZSBGRFIgaXMgZ2VuZXJhbGx5IHByZWZlcnJlZCBvdmVyIG1vcmUgY29uc2VydmF0aXZlIGFkanVzdG1lbnRzIHN1Y2ggYXMgQm9uZmVyb25uaSBjb3JyZWN0aW9uLiBGRFIgY29udHJvbCBpcyBhbHNvIHR5cGljYWxseSBmYXZvdXJlZCBvdmVyIEZXRVIgY29udHJvbCBpbiBiaW9sb2dpY2FsIHN0dWRpZXMgaW52b2x2aW5nIEJpZyBEYXRhXltTZWUgZS5nLiBAU3RvcmV5Ll0uDQoNClRoZSBGRFIgY2FuIGJlIGRlZmluZWQgYXMgdGhlIGV4cGVjdGVkIHByb3BvcnRpb24gb2YgZXJyb3JzIChpLmUuIGZhbHNlIGRpc2NvdmVyaWVzKSBhbW9uZyB0aGUgcmVqZWN0ZWQgaHlwb3RoZXNlc15bU2VlIEBjb250cm9sRkRSLl0uIENvbnRyb2xsaW5nIHRoZSBGRFIgaGVscHMgdG8gcmVkdWNlIGZhbHNlIHBvc2l0aXZlcywgYnV0IGFsc28gaGVscHMgbWluaW1pc2UgZmFsc2UgbmVnYXRpdmVzLiANCg0KIyMgeyNmZHJ9DQoNCldlIGNhbiBhcHBseSBGRFIgY29ycmVjdGlvbiB0byAkcCQtdmFsdWVzIHVzaW5nIHRoZSBSIGZ1bmN0aW9uIGBwLmFkanVzdGAgLSBqdXN0IHNwZWNpZnkgdGhlIG1ldGhvZCBgZmRyYC4gDQoNClRyeSB0aGlzIG5vdywgb24gb3VyIGBiYXNlX3BfdmFsdWVzYCB2ZWN0b3Igb2YgJHAkLXZhbHVlcy4NCg0KIyMNCg0KQ29tcGFyZSB5b3VyIEZEUiByZXN1bHRzIGZyb20gXEByZWYoZmRyKSB0byB5b3VyIEJvbmZlcnJvbmkgY29ycmVjdGlvbiByZXN1bHRzIGluIFxAcmVmKGJvbmZlcnJvbmkpLiBXaGF0IGRvIHlvdSBub3RpY2U/DQoNCiMgU0FSUy1Db1YtMiBTdHVkeSAkcCQtdmFsdWVzDQoNClRvIGNvbmNsdWRlIHRoaXMgY29tcHV0ZXIgbGFiLCBsZXQncyB0YWtlIGEgbG9vayBhdCBhIHJlYWwtd29ybGQgYXBwbGljYXRpb24gb2YgJHAkLXZhbHVlIGFkanVzdG1lbnQsIGluIHRoZSBjb250ZXh0IG9mIGJpb2xvZ2ljYWwgZGF0YS4gDQoNCkZvciB0aGlzIGV4YW1wbGUsIHdlIHdpbGwgY29uc2lkZXIgYSBzdWJzZXQgb2YgU0FSUy1Db1YtMiAoQ29yb25hdmlydXMpIGdlbmUgZXhwcmVzc2lvbiBwcm9maWxpbmcgZGF0YSwgZnJvbSBhIHN0dWR5IGJ5IEBzYXJzLiBJbmZvcm1hdGlvbiBvbiB0aGUgc3R1ZHkgY2FuIGJlIGZvdW5kIFtoZXJlXShodHRwczovL3d3dy5uY2JpLm5sbS5uaWguZ292L2dlby9xdWVyeS9hY2MuY2dpP2FjYz1HU0UxODQ5MzIpIGFuZCB0aGUgZnVsbCBkYXRhIHNldCBpcyBwdWJsaWNseSBhdmFpbGFibGUgb24gdGhlIE5DQkkgR2VuZSBFeHByZXNzaW9uIE9tbmlidXMgd2Vic2l0ZV5bU2VyaWVzIEdTRTE4NDkzMi5dLg0KDQpUaGUgc3R1ZHkgY29uc2lkZXJlZCB0aGUgYFZJQ2AgYW5kIEIuMS4xLjcgKGBBbHBoYWApIHN0cmFpbnMgb2YgU0FSUy1Db1YtMiwgd2hpY2ggaGF2ZSBkaWZmZXJlbnQgcmVwbGljYXRpb24gYW5kIHRyYW5zbWlzc2lvbiBjaGFyYWN0ZXJpc3RpY3MuIFNhbXBsZXMgd2VyZSB0YWtlbiBvZiBodW1hbiBjZWxscyBhdCBzZXZlcmFsIHRpbWUgcG9pbnRzIGZvbGxvd2luZyBpbmZlY3Rpb24gd2l0aCBlaXRoZXIgb2YgdGhlc2UgdHdvIHN0cmFpbnMuIEdlbmUgZXhwcmVzc2lvbiBkaWZmZXJlbmNlcyB3ZXJlIHRoZW4gYXNzZXNzZWQsIGFuZCAkcCQtdmFsdWVzIHdlcmUgY29tcHV0ZWQgZm9yIGVhY2ggZ2VuZSwgd2l0aCBhIHNtYWxsICRwJC12YWx1ZSBzdWdnZXN0aW5nIHRoZSBnZW5lIHdhcyBzdGF0aXN0aWNhbGx5IHNpZ25pZmljYW50bHkgZGlmZmVyZW50aWFsbHkgZXhwcmVzc2VkIGF0IHRoYXQgdGltZSBwb2ludCwgYmV0d2VlbiB0aGUgdHdvIHN0cmFpbnMuDQoNCiMjDQoNClRoZSBkYXRhIHdlIHdpbGwgYXNzZXNzIGlzIHN0b3JlZCBpbiB0aGUgZmlsZSBgU0FSU19kYXRhX3N1YnNldC5jc3ZgIHdoaWNoIGlzIGF2YWlsYWJsZSBvbiB0aGUgTE1TLg0KVGhlIHRhYmxlIGJlbG93IHByb3ZpZGVzIGFuIGV4YW1wbGUgb2Ygc29tZSByZWNvcmRlZCB2YWx1ZXMgZm9yIHRoZSBkaWZmZXJlbnQgdmFyaWFibGVzICh0aGUgY29sdW1uIG5hbWVzKSBpbiB0aGlzIGRhdGEgc2V0LiBEb24ndCB3b3JyeSBhYm91dCBhbGwgdGhlc2UgbmFtZXMganVzdCB5ZXQgLSB3ZSB3aWxsIGRpc2N1c3MgdGhlbSBhcyB3ZSB3b3JrIHRocm91Z2ggdGhpcyBxdWVzdGlvbi4NCg0KYGBge3IgZXZhbCA9IFQsIGVjaG8gPSBGfQ0Kc2Fyc19hbHBoYV92aWMgPC0gcmVhZC5jc3YoZmlsZSA9ICJTQVJTX2RhdGFfc3Vic2V0LmNzdiIsIGhlYWRlciA9IFQpDQprYmwoc2Fyc19hbHBoYV92aWNbYygxLDMsNSw3KSxdLCByb3cubmFtZXMgPSBGKSAlPiUNCiAga2FibGVfcGFwZXIoImhvdmVyIiwgZnVsbF93aWR0aCA9IEYpDQpgYGANCiMjDQoNCkRvd25sb2FkIHRoZSBmaWxlIGBTQVJTX2RhdGFfc3Vic2V0LmNzdmAgZnJvbSBMTVMgbm93LiANCg0KU2F2ZSB0aGUgYFNBUlNfZGF0YV9zdWJzZXQuY3N2YCBmaWxlIGluIHlvdXIgd29ya2luZyBkaXJlY3RvcnksIHRoZW4gcmVhZCB0aGUgYFNBUlNfZGF0YV9zdWJzZXQuY3N2YCBmaWxlIGludG8gUlN0dWRpbywgYW5kIHN0b3JlIGl0IGluIGFuIG9iamVjdCBjYWxsZWQgYHNhcnNfZGF0YWAuDQoNCipIaW50OiBSZWNhbGwgdGhhdCB5b3UgY2FuIHVzZSB0aGUgZnVuY3Rpb24gYHJlYWQuY3N2YCB0byBsb2FkIGEgLmNzdiBmaWxlIGludG8gUlN0dWRpby4qDQoNCiMjIHsjc3RhcnR9DQoNClRoZSAkcCQtdmFsdWVzIHN0b3JlZCBpbiB0aGUgYHNhcnNfZGF0YS5jc3ZgIGZpbGUgd2VyZSBjb21wdXRlZCBmb3IgZ2VuZSBleHByZXNzaW9uIGNvbXBhcmlzb25zIGJldHdlZW4gdGhlIGBWSUNgIGFuZCBgQWxwaGFgIHN0cmFpbnMgYXQgOCBob3VycyBwb3N0LWluZmVjdGlvbi4gDQoNClJ1biB0aGUgUiBjb2RlIGJlbG93IHRvIGRldGVybWluZSB0aGUgbnVtYmVyIG9mIGdlbmVzIHRoYXQgYXJlIGNvbnNpZGVyZWQgc3RhdGlzdGljYWxseSBzaWduaWZpY2FudGx5IGRpZmZlcmVudGlhbGx5IGV4cHJlc3NlZCBiZXR3ZWVuIHRoZSB0d28gc3RyYWlucyBhdCB0aGUgOCBob3VyIHBvc3QtaW5mZWN0aW9uIG1hcmssIGZvciBhbiAkXGFscGhhID0gMC4wNSQgbGV2ZWwgb2Ygc2lnbmlmaWNhbmNlLg0KDQpgYGB7ciBjbGFzcy5zb3VyY2UgPSAiZm9sZC1zaG93IiwgZXZhbCA9IEYsIGVjaG8gPSBULCB3YXJuaW5nID0gRiwgbWVzc2FnZSA9IEZ9DQojIEZpcnN0LCB3ZSBzZWxlY3Qgb25seSB0aGUgdmFsdWVzIGluIHRoZSANCiMgYHB2YWx1ZS5BbHBoYV84aF92c19WSUNfOGhgIGNvbHVtbiB0aGF0IGFyZSBsZXNzIHRoYW4gMC4wNQ0Kc2Fyc19kYXRhXzhoX2Jhc2UgPC0gc2Fyc19kYXRhW3NhcnNfZGF0YSRwdmFsdWUuQWxwaGFfOGhfdnNfVklDXzhoIDwgMC4wNSxdDQojIFRoZW4gd2UgYXNzZXNzIHRoZSBudW1iZXIgb2Ygcm93cyByZW1haW5pbmcgLSBlYWNoIHJvdyByZXByZXNlbnRzIGEgZ2VuZQ0KbnJvdyhzYXJzX2RhdGFfOGhfYmFzZSkNCmBgYA0KDQojIw0KDQpVc2UgdGhlIGBwLmFkanVzdGAgZnVuY3Rpb24gdG8gcGVyZm9ybSBGRFIgY29ycmVjdGlvbiBvbiB0aGUgYHB2YWx1ZS5BbHBoYV84aF92c19WSUNfOGhgICRwJC12YWx1ZXMsIGp1c3QgbGlrZSB5b3UgZGlkIGluIFxAcmVmKGZkcikuIFN0b3JlIHlvdXIgcmVzdWx0cyBpbiBhIG5ldyBjb2x1bW4gaW4gdGhlIGBzYXJzX2RhdGFgIG9iamVjdC4NCg0KWW91IGNhbiB1c2UgdGhlIFIgY29kZSBiZWxvdyBhcyBhIHN0YXJ0aW5nIHBvaW50IC0ganVzdCBmaWxsIGluIHRoZSBtaXNzaW5nIGAuLi5gJ3MuDQoNCmBgYHtyIGNsYXNzLnNvdXJjZSA9ICJmb2xkLXNob3ciLCBldmFsID0gRiwgZWNobyA9IFQsIHdhcm5pbmcgPSBGLCBtZXNzYWdlID0gRn0NCnNhcnNfZGF0YSRmZHJfYWRqdXN0ZWRfcHZhbHVlXzhoIDwtIC4uLg0KYGBgDQoNCipOb3RlIHRoYXQgdGhlIGAkZmRyX2FkanVzdGVkX3B2YWx1ZV84aGAgcGFydCBvZiB0aGUgY29kZSBhYm92ZSBpbnN0cnVjdHMgUiB0byBhZGQgYSBuZXcgY29sdW1uIGNhbGxlZCBgZmRyX2FkanVzdGVkX3B2YWx1ZV84aGAgdG8gdGhlIGBzYXJzX2RhdGFgIG9iamVjdCwgd2l0aCB0aGUgdmFsdWVzIHlvdSBzcGVjaWZ5IGluIHRoZSBgLi4uYCBwYXJ0IGFkZGVkIGFzIHRoZSBjb2x1bW4gdmFsdWVzLioNCg0KIyMgeyNlbmR9DQoNCkRldGVybWluZSB0aGUgbnVtYmVyIG9mIGdlbmVzIGF0IHRoZSA4IGhvdXIgcG9zdC1pbmZlY3Rpb24gbWFyayB0aGF0IGFyZSwgYWNjb3JkaW5nIHRvIHlvdXIgRkRSIHJlc3VsdHMsIHN0YXRpc3RpY2FsbHkgc2lnbmlmaWNhbnRseSBkaWZmZXJlbnRpYWxseSBleHByZXNzZWQgZm9yIGFuIEZEUiBsZXZlbCBvZiAkMC4wNSQuIENvbXBhcmUgdGhpcyB3aXRoIHlvdXIgaW5pdGlhbCByZXN1bHRzLg0KDQoqSGludDogVXNlIHRoZSBSIGNvZGUgaW4gXEByZWYoc3RhcnQpIGFzIGEgZ3VpZGUuKg0KDQojIyBWb2xjYW5vIFBsb3RzDQoNCkluIGFkZGl0aW9uIHRvIHRoZSAqc3RhdGlzdGljYWwgc2lnbmlmaWNhbmNlKiBvZiB0aGUgZ2VuZSBleHByZXNzaW9uIGRpZmZlcmVuY2VzLCB3ZSBhcmUgYWxzbyBpbnRlcmVzdGVkIGluICAqYmlvbG9naWNhbCBzaWduaWZpY2FuY2UqLiANCg0KTm90aWNlIGluIHRoZSBgc2Fyc19kYXRhYCBmaWxlIHRoYXQgdGhlcmUgaXMgYSBjb2x1bW4gbGFiZWxsZWQgYGxvZzJGb2xkQ2hhbmdlLkFscGhhXzhoX3ZzX1ZJQ184aGAuIFRoZSB2YWx1ZXMgcmVjb3JkZWQgaW4gdGhpcyBjb2x1bW4gZGVub3RlIHRoZSBsb2cgcmF0aW8gb2YgdGhlIGNoYW5nZSBpbiBnZW5lIGV4cHJlc3Npb24gc3RhdHVzIGJldHdlZW4gdGhlIHR3byBzdHJhaW5zLCBmb3IgZWFjaCBnZW5lLiBJZiB0aGVyZSBpcyBubyBkaWZmZXJlbmNlIGluIHRoZSBnZW5lIGV4cHJlc3Npb24gc3RhdHVzLCB0aGUgcmF0aW8gd291bGQgYmUgMSwgZS5nLjogJCRcZnJhY3s0LjIgXHRleHR7IGZvciBWSUMgc3RyYWlufX17NC4yIFx0ZXh0eyBmb3IgQWxwaGEgc3RyYWlufX0gPSAxXHRleHR7LCB3aXRoIH1cbG9nXzIoMSkgPSAwLiQkDQoNClNvIGBsb2cyRm9sZENoYW5nZS5BbHBoYV84aF92c19WSUNfOGhgIHZhbHVlcyBjbG9zZSB0byBvciBlcXVhbCB0byAwIHN1Z2dlc3QgdGhlcmUgaXMgbm8gYmlvbG9naWNhbGx5IHNpZ25pZmljYW50IGNoYW5nZSBpbiBnZW5lIGV4cHJlc3Npb24gYmV0d2VlbiB0aGUgdHdvIHN0cmFpbnMuIEluIGNvbnRyYXN0LCB2YWx1ZXMgZmFyIGZyb20gMCBzdWdnZXN0IHRoZXJlIGlzIGEgYmlvbG9naWNhbGx5IHNpZ25pZmljYW50IGNoYW5nZS4NCg0KSW4gZ2VuZSBleHByZXNzaW9uIGFuYWx5c2VzLCBhICoqVm9sY2FubyBwbG90KiogY2FuIGJlIHVzZWQgdG8gaGlnaGxpZ2h0IGdlbmVzIHdoaWNoIGFyZSBzdGF0aXN0aWNhbGx5IGFuZCBiaW9sb2dpY2FsbHkgc2lnbmlmaWNhbnQgKHRoZXNlIGdlbmVzIGFyZSBwcm9iYWJseSB0aGUgbW9zdCBpbXBvcnRhbnQgdG8gY29uc2lkZXIgaW4gZnVydGhlciBkZXRhaWwpLg0KDQpSdW4gdGhlIFIgY29kZSBiZWxvdyB0byBjcmVhdGUgdHdvIHZvbGNhbm8gcGxvdHMgZm9yIG91ciBtb2RpZmllZCBgc2Fyc19kYXRhYCBmaWxlLiBBcyB5b3UgY2FuIHNlZSwgdGhlIHZvbGNhbm8gcGxvdCBpcyBhIGJpdCBsaWtlIGEgc2NhdHRlciBwbG90Lg0KDQpgYGB7ciBjbGFzcy5zb3VyY2UgPSAiZm9sZC1zaG93IiwgZXZhbCA9IEYsIGVjaG8gPSBULCB3YXJuaW5nID0gRiwgbWVzc2FnZSA9IEZ9DQpwbG90KHNhcnNfZGF0YSRsb2cyRm9sZENoYW5nZS5BbHBoYV84aF92c19WSUNfOGgsIA0KICAgICAtbG9nMTAoc2Fyc19kYXRhJHB2YWx1ZS5BbHBoYV84aF92c19WSUNfOGgpLCANCiAgICAgbWFpbiA9ICJWb2xjYW5vIFBsb3QgZm9yIFNBUlMtQ29WLTIgDQogICAgIFZJQyBhbmQgQWxwaGEgc3RyYWlucw0KICAgICA4aCBwb3N0LWluZmVjdGlvbiwgdXNpbmcgaW5pdGlhbCBwLXZhbHVlcyIsDQogICAgIHhsYWIgPSAibG9nIEZDIiwgeWxhYiA9ICItbG9nMTAocHZhbCkiLA0KICAgICBjZXggPSAwLjUsIGNvbCA9IGFzLm51bWVyaWMoc2Fyc19kYXRhJHB2YWx1ZS5BbHBoYV84aF92c19WSUNfOGggPD0gMC4wNSkgKyAxKQ0KDQpwbG90KHNhcnNfZGF0YSRsb2cyRm9sZENoYW5nZS5BbHBoYV84aF92c19WSUNfOGgsIA0KICAgICAtbG9nMTAoc2Fyc19kYXRhJGZkcl9hZGp1c3RlZF9wdmFsdWVfOGgpLCANCiAgICAgbWFpbiA9ICJWb2xjYW5vIFBsb3QgZm9yIFNBUlMtQ29WLTIgDQogICAgIFZJQyBhbmQgQWxwaGEgc3RyYWlucw0KICAgICA4aCBwb3N0LWluZmVjdGlvbiwgdXNpbmcgRkRSLWNvcnJlY3RlZCBwLXZhbHVlcyIsDQogICAgIHhsYWIgPSAibG9nIEZDIiwgeWxhYiA9ICItbG9nMTAocHZhbCkiLA0KICAgICBjZXggPSAwLjUsIGNvbCA9IGFzLm51bWVyaWMoc2Fyc19kYXRhJGZkcl9hZGp1c3RlZF9wdmFsdWVfOGggPD0gMC4wNSkgKyAxKQ0KYGBgDQoNCiMjDQoNCkVhY2ggcG9pbnQgaW4gdGhlIHZvbGNhbm8gcGxvdHMgcmVwcmVzZW50cyBhIGdlbmUuIA0KSW4gdGhlIGZpcnN0IHBsb3QsIGdlbmVzIHdpdGggc21hbGwgJHAkLXZhbHVlcyBhcmUgY29sb3VyZWQgcmVkLg0KSW4gdGhlIHNlY29uZCBwbG90LCBnZW5lcyB3aXRoIHNtYWxsIEZEUi1jb3JyZWN0ZWQgJHAkLXZhbHVlcyBhcmUgY29sb3VyZWQgcmVkLiANCkFsbCBvdGhlciBnZW5lcyBhcmUgY29sb3VyZWQgYmxhY2suIA0KDQpXaGF0IGRpZmZlcmVuY2VzIGRvIHlvdSBvYnNlcnZlIGJldHdlZW4gdGhlIHR3byBwbG90cz8gRG8geW91IHRoaW5rIHRoZSBGRFIgY29ycmVjdGlvbiBoYXMgYmVlbiBiZW5lZmljaWFsPw0KDQo8YnI+DQoNCiMjIyMgR3JlYXQgam9iLCB0aGF0J3MgZXZlcnl0aGluZyBmb3IgdG9kYXkuICMjIyMgey19DQoNCiMjIyMgSWYgeW91IGhhdmUgYW55IHF1ZXN0aW9ucyBhYm91dCBBc3Nlc3NtZW50cywgcGxlYXNlIGFzayBmb3IgaGVscC4gIyMjIyB7LX0NCg0KPGJyPg0KDQojIFJlZmVyZW5jZXMgey0gI1JlZn0NCjxkaXYgaWQ9InJlZnMiPjwvZGl2Pg0KDQo8YnI+DQoNCjxmb250IGNvbG9yID0gImdyZXkiPg0KVGhlc2Ugbm90ZXMgaGF2ZSBiZWVuIHByZXBhcmVkIGJ5IFJ1cGVydCBLdXZla2UgYW5kIEFtYW5kYSBTaGFrZXIuIFRoZSBjb3B5cmlnaHQgZm9yIHRoZSBtYXRlcmlhbCBpbiB0aGVzZSBub3RlcyByZXNpZGVzIHdpdGggdGhlIGF1dGhvcnMgbmFtZWQgYWJvdmUsIHdpdGggdGhlIERlcGFydG1lbnQgb2YgTWF0aGVtYXRpY2FsIGFuZCBQaHlzaWNhbCBTY2llbmNlcyBhbmQgd2l0aCBMYSBUcm9iZSBVbml2ZXJzaXR5LiBDb3B5cmlnaHQgaW4gdGhpcyB3b3JrIGlzIHZlc3RlZCBpbiBMYSBUcm9iZSBVbml2ZXJzaXR5IGluY2x1ZGluZyBhbGwgTGEgVHJvYmUgVW5pdmVyc2l0eSBicmFuZGluZyBhbmQgbmFtaW5nLiBVbmxlc3Mgb3RoZXJ3aXNlIHN0YXRlZCwgbWF0ZXJpYWwgd2l0aGluIHRoaXMgd29yayBpcyBsaWNlbnNlZCB1bmRlciBhIENyZWF0aXZlIENvbW1vbnMgQXR0cmlidXRpb24tTm9uIENvbW1lcmNpYWwtTm9uIERlcml2YXRpdmVzIExpY2Vuc2UgDQo8YSBocmVmID0gImh0dHBzOi8vY3JlYXRpdmVjb21tb25zLm9yZy9saWNlbnNlcy9ieS1uYy1uZC80LjAvQ0MiIHRhcmdldD0iX2JsYW5rIj4gQlktTkMtTkQuIDwvYT4NCjwvZm9udD4=