In the previous two labs you were able to measure water and air quality in a laboratory setting. We will now use some of the data collected from those experiments to make inferences about the burden of disease associated with varying levels of water and air quality.

For the first part of this lab, you will attempt to answer a simple question: how would the burden of disease be different for the United States if drinking water quality was similar to what we tested in the Willamette River? To answer this question, you will need to break it down into several sub-questions, including:

  1. What is the current burden of disease associated with drinking water illnesses in the United States?

  2. How would the burden of disease change based on the quality of water that we tested for the water quality lab?

    1. How many people would be affected by the reduced drinking water quality?

    2. How much water do these people drink on average each day?

    3. How many bacteria would they be ingesting, and how many of them would get sick as a result of ingesting more pathogens?

    4. What would be the total health impact, expressed in disability adjusted life years (DALYs)?

In other words, you will be conducting a quantitative microbial risk assessment (QMRA) to estimate the increased burden of disease associated with reduced drinking-water quality. We recommend that you use the following resources to aid in your investigation:

  1. Havelaar, A.H., & Melse, J.M. (2003) Quantifying public health risk in the WHO Guidelines for drinking-water quality: A burden of disease approach. National Institute for Public Health and the Environment of the Netherlands
  2. FAO & WHO. (2003) Hazard characterization for pathogens in food and water: Guidelines.
  3. Brown, J., & Clasen, T. (2012). High Adherence Is Necessary to Realize Health Gains from Water Quality Interventions. PLoS ONE, 7(5), e36735. http://doi.org/10.1371/journal.pone.0036735
    • A description of a QRMA model used to estimate the level of adherence necessary to significantly increase DALYs using different levels of contamination and water treatment efficacies.

1. Current Burden of Disease

To determine the current burden of disease from unsafe water, you’ll want to check out the Global Burden of Disease (GBD) Visualization at the Institute of Health Metrics and Evaluation (IHME): https://vizhub.healthdata.org/gbd-compare/.

Select the second icon on the left-hand side (“Risks by Cause”), select level four on the slider, and select “United States” for location. Then select “Diarrhea/LRI/other” on the right-hand side. Find “Unsafe water” in the rankings. What are the total number of DALYs, the percent of total DALYs, and the DALY rate (number of DALYs per 100,000)?

Now navigate to the arrow diagram showing the risks for each cause and make sure that level four is still selected on the slider and United States is selected for location. Download this data using the Download button on the top right and determine where diarrheal diseases ranked for the United States in 2016.

Now do the same thing (determine the total DALYs, the percent of total DALYs, the DALY rate, and the cause ranking) for Sub-Saharan Africa in 2016.

Screenshot of IHME Visualization Dashboard

Screenshot of IHME Visualization Dashboard

2a. Population

What was the population of the United States in 2016?

library(MonteCarlo)
library(data.table)

population = 0

2b. Water Consumption

How much water do people drink on average per day? Should the amount of water consumed be averaged or simulated? What are the benefits of conducting a simulation versus a single estimate based on average values?

If you’re not familiar with generating random numbers or writing a function in R, here’s an example to simulate the approximate number of liters that a person could drink each day in a year. See if you can generate a data table that randomly samples the amount of water 100,000 people would drink in a year. Hint: you might try the function replicate.

# function to randomly selected between 1, 2, and 5 liters of water per person per day
generate_water = function(n=1) {
  sample(c(1,2,5),n,replace = TRUE)
}
generate_water(365)
  [1] 1 1 2 2 2 2 1 1 5 5 1 5 2 5 1 2 1 1 5 1 1 1 5 1 1 5 2 1 1 1 1 5 5 1 2 2 5 2 1 5 2 5 2 2 1
 [46] 2 2 2 5 5 1 5 5 5 1 5 5 5 1 1 1 2 5 5 1 1 1 1 5 2 2 2 1 2 1 1 1 1 5 2 1 2 5 2 5 5 1 1 2 1
 [91] 5 2 1 1 5 1 2 2 1 2 1 2 5 2 1 1 1 2 1 1 2 2 1 2 2 1 5 2 5 5 1 1 5 1 1 2 1 5 2 1 1 1 1 1 2
[136] 2 2 1 1 1 5 5 5 1 2 5 5 1 1 1 2 1 2 5 2 5 1 1 2 5 2 2 5 2 1 5 1 1 5 5 5 1 1 1 2 2 5 2 1 1
[181] 5 2 2 2 2 2 5 2 2 2 2 1 5 2 2 1 2 5 2 5 1 2 2 1 5 1 5 2 1 1 5 1 2 5 2 5 5 2 1 1 2 1 2 1 1
[226] 2 2 1 2 1 2 1 5 5 5 2 5 5 2 2 2 5 5 2 2 2 2 2 2 1 5 5 2 2 2 2 1 2 5 1 2 5 5 1 2 5 2 2 1 5
[271] 5 2 2 2 5 5 1 2 5 2 1 1 2 5 1 2 5 1 1 1 1 2 1 2 2 5 5 2 5 1 5 1 2 1 5 2 5 1 5 2 5 2 1 5 2
[316] 2 5 5 1 1 1 1 1 2 1 5 1 2 5 1 5 2 1 5 1 2 5 1 2 1 1 2 5 2 1 1 2 5 5 1 2 2 2 1 1 5 1 5 5 2
[361] 2 5 5 2 1
# generate a data table (or data frame or matrix) with 365 columns and 100,000 rows with randomly sample amounts of water for each entry

2c. Dose-Response

How many organisms would people be ingesting on average per liter of water? What is the probability of infection for the number of microbes ingested? What is the probability of illness given infection?

Here are two different ways to randomly select the number of organisms present in a liter of water: one samples from a log-normal distribution and the other samples from an empirical distribution based on water quality testing. Make sure that you can justify which one that you use, as well as the parameters used (e.g., the mean for the log-normal distribution). How do your two data tables compare?

# generate number of organisms consumed empirically (based on log-normal distribution)
organisms_lnorm <- function(n = 1,mean = 1) {
  
  rlnorm(n, meanlog = mean, sdlog = mean)
}
# generate number of organisms consumed empirically (based on E. coli water testing)
organisms_empirical <- function(n = 1) {
 
  sample(c(14,75,9,18,14,22,8,14,6,12,26,6,1,2,8,4),n,replace = TRUE) * 10
}
# now create two new data tables with the number of organisms per liter for 100,000 people for both distributions

You now have two data tables that represent the number of organisms 100,000 people would ingest in each liter of water for a year. Pick the one that you think is more accurate. Now you need to determine each person’s daily dose of organisms, their probability of infection, and their probability of illness given infection.

# number of microbes ingested per day
dose = dt_water * dt_lnorm
# probabiliy density function for campylobacter infection
beta_poisson = function(dose, alpha = 0.145, n50 = 896) {
  
  1 - ( 1 + (dose / n50) * ( 2^(1/alpha) - 1 ) )^(-alpha)
}
# generate probability of daily infection (beta-poisson function)
p_inf <- beta_poisson(dose)
  
# generate probability of illness given infection (0.3 for campylobacter)
p_illness_inf = 0.3
p_illness <- p_inf * p_illness_inf

2d. Health Impact

You should have a large matrix with the risk of daily infection due to ingesting different amounts of campylobacter bacteria over the course of one year for 100,000 individuals. Now we will use the disease burden associated with campylobacteriosis (try saying that five times really fast) to calculate the total number of disability adjusted life years associated with increased exposure to campylobacter bacteria. To do this you have to make assumptions (that can be justified) about the proportion of the population that is susceptible to infection and the disease burden associated with campylobacteriosis.


# percent of the population susceptible to infection (campylobacter)
susceptible = 1.00

# disease burden per case (campylobacter)
db_case = 4.6e-3

# generate DALYs per year
DALYs_year = p_illness * db_case * susceptible
  
# generate total DALYs per 100,000
DALYs_total <- sum(DALYs_year)

DALYs_total

Simulation of Disease Burden

Now you have the total disease burden associated with increased exposure to campylobacter. However, there are two problems. First, we assumed that a person could have campylobacteriosis every day, whereas in reality infections and illnesses have average durations that are baked into the disease burden per case estimates. Second, we made assumptions about the number of campylobacter bacteria present in each liter of water when in reality we’re not sure how many bacteria might be present. Also, for some illnesses the disease burden per case isn’t a fixed number. As a result, we need to re-run the experiment with multiple repetitions to generate a confidence interval for our DALY estimates.

In order to simulate the disease burden associated with increased exposure to pathogens, we will conduct a Monte Carlo simulation. I’ve opted to use the MonteCarlo package (https://www.r-bloggers.com/introducing-the-montecarlo-package/), but you can feel free to use another method as you wish.

I am going to include the code for campylobacter below. Your responsibility is to understand what I’m doing below and then run simulations for rotavirus, shiga-toxin producing E. coli STEC 0157, and cryptosporidium based on parameters and methodologies you can find in the literature. Also, because we’re running multiple iterations, the simulation is modified to more closely approximate the methodology used in Brown & Clasen (cited above).

Following the instructions from the R Bloggers website, I will create the disease_burden function to calculate the total DALYs for 100,000 people (though slightly different from how we did it up above). I then specify the parameters I want to vary in the simulation. In this case I will vary the mean from the log-normal distribution that we’re using to generate random numbers of pathogens.

Campylobacter, Rotavirus, and E. Coli


# function to calculate disease burden
disease_burden = function(people, meanlog, alpha, n50, p_illness_inf, susceptible, db_case){
  
  # generate water consumed
  water_consumed <- sample(c(1,2,5),people,replace = TRUE)
  
  # generate number of organism consumed from log-normal distribution
  number_of_organisms <- rlnorm(people, meanlog = meanlog)
  
  # generate daily dose
  dose <- water_consumed * number_of_organisms
  
  # generate probability of daily infection (beta-poisson function)
  p_inf <- 1 - ( 1 + (dose / n50) * ( 2^(1/alpha) - 1 ) )^(-alpha)
  
  # generate probability of illness
  p_illness <- p_inf * p_illness_inf
  
  # generate yearly infection risk
  p_year = 1 - (1 - p_illness)^365
  
  # generate DALYs per year
  DALYs_year = p_year * db_case * susceptible
  
  # generate total DALYs per 100,000
  DALYs_total <- sum(DALYs_year)
  
  # returns value for MonteCarlo function
  return(list("DALYs"=DALYs_total))
  
}

# parameter list for campylobacter
param_campylobacter <- list("people" = 100000,
                            "meanlog" = c(1, 0.1, 0.01, 0.001, 0.0001),
                            "alpha" = 0.145,
                            "n50" = 896,
                            "p_illness_inf" = 0.3,
                            "susceptible" = 1.00,
                            "db_case" = 4.6e-3)

# function to run the simulation
campylobacter <- MonteCarlo(func=disease_burden, nrep=1000, param_list = param_campylobacter)

# summary of results
summary(campylobacter$results$DALYs)



# parameter list for rotavirus (fill this in)


# parameter list for E. coli (fill this in)




# function to run the simulation
rotavirus <- MonteCarlo(func=disease_burden, nrep=1000, param_list = param_rotavirus)

# summary of results
summary(rotavirus$results$DALYs)

# function to run the simulation
ecoli <- MonteCarlo(func=disease_burden, nrep=1000, param_list = param_ecoli)

# summary of results
summary(ecoli$results$DALYs)

Cryptosporidium

Why is cryptosporidium being modeled in its own section?


disease_burden_crypto = function(people, meanlog, infectivity, p_illness_inf, susceptible, db_case){

  # fill this in
  
}

# parameter list for cryptosporidium (fill this in)


# function to run the simulation
crypto <- MonteCarlo(func=disease_burden_crypto, nrep=1000, param_list = param_crypto)

# summary of results
summary(crypto$results$DALYs)

You should now have estimates of the total DALYs due to infections from campylobacter, rotavirus, shiga-toxin producing E. coli STEC 0157, and cryptosporidium. How do these estimates compare with the first DALY estimates from 2a. through 2d. above? What different assumptions were made, and how did that affect the outcome?

Lab Assignment

You will need to compose a formal lab report (that includes part one and part two) not exceeding five pages (excluding appendices). This can be submitted as an R Notebook (PDF version of the main report less than 5 pages) or as a PDF. You will need to include a brief introduction, a methods section, results, discussion, and a brief conclusion. See the syllabus and grading rubric for more a more detailed description.

In particular, you should address the following questions:

  1. How does the newly calculated disease burden compare to the previous disease burden? How does it compare with other causes of disease burden in the United States (https://vizhub.healthdata.org/gbd-compare/)? How about in Low SDI countries?

  2. Simulations require a lot of assumptions. Comment on which assumptions felt dubious (or that you weren’t able to justify from the literature) and which assumptions most significantly influenced your results. How much faith do you have in your results?

  3. Why is it important to conduct a Monte Carlo simulation instead of just using average values?

  4. Is disease burden per case the same for all locations? How would that assumption affect the outcome of this experiment?

The final report will be need to be submitted on D2L through Dropbox by 3pm on Tuesday, March 13th.

LS0tDQp0aXRsZTogIkRpc2Vhc2UgQnVyZGVuOiBQYXJ0IEkiDQpvdXRwdXQ6IA0KICAgaHRtbF9ub3RlYm9vazoNCiAgICAgdG9jOiB5ZXMNCiAgICAgdG9jX2Zsb2F0OiB5ZXMNCiAgICAgdGhlbWU6IHNpbXBsZXgNCi0tLQ0KDQpJbiB0aGUgcHJldmlvdXMgdHdvIGxhYnMgeW91IHdlcmUgYWJsZSB0byBtZWFzdXJlIHdhdGVyIGFuZCBhaXIgcXVhbGl0eSBpbiBhIGxhYm9yYXRvcnkgc2V0dGluZy4gV2Ugd2lsbCBub3cgdXNlIHNvbWUgb2YgdGhlIGRhdGEgY29sbGVjdGVkIGZyb20gdGhvc2UgZXhwZXJpbWVudHMgdG8gbWFrZSBpbmZlcmVuY2VzIGFib3V0IHRoZSBidXJkZW4gb2YgZGlzZWFzZSBhc3NvY2lhdGVkIHdpdGggdmFyeWluZyBsZXZlbHMgb2Ygd2F0ZXIgYW5kIGFpciBxdWFsaXR5Lg0KDQpGb3IgdGhlIGZpcnN0IHBhcnQgb2YgdGhpcyBsYWIsIHlvdSB3aWxsIGF0dGVtcHQgdG8gYW5zd2VyIGEgc2ltcGxlIHF1ZXN0aW9uOiAqKmhvdyB3b3VsZCB0aGUgYnVyZGVuIG9mIGRpc2Vhc2UgYmUgZGlmZmVyZW50IGZvciB0aGUgVW5pdGVkIFN0YXRlcyBpZiBkcmlua2luZyB3YXRlciBxdWFsaXR5IHdhcyBzaW1pbGFyIHRvIHdoYXQgd2UgdGVzdGVkIGluIHRoZSBXaWxsYW1ldHRlIFJpdmVyPyoqIFRvIGFuc3dlciB0aGlzIHF1ZXN0aW9uLCB5b3Ugd2lsbCBuZWVkIHRvIGJyZWFrIGl0IGRvd24gaW50byBzZXZlcmFsIHN1Yi1xdWVzdGlvbnMsIGluY2x1ZGluZzoNCg0KMS4gV2hhdCBpcyB0aGUgY3VycmVudCBidXJkZW4gb2YgZGlzZWFzZSBhc3NvY2lhdGVkIHdpdGggZHJpbmtpbmcgd2F0ZXIgaWxsbmVzc2VzIGluIHRoZSBVbml0ZWQgU3RhdGVzPw0KDQoyLiBIb3cgd291bGQgdGhlIGJ1cmRlbiBvZiBkaXNlYXNlIGNoYW5nZSBiYXNlZCBvbiB0aGUgcXVhbGl0eSBvZiB3YXRlciB0aGF0IHdlIHRlc3RlZCBmb3IgdGhlIHdhdGVyIHF1YWxpdHkgbGFiPw0KDQogICAgYS4gSG93IG1hbnkgcGVvcGxlIHdvdWxkIGJlIGFmZmVjdGVkIGJ5IHRoZSByZWR1Y2VkIGRyaW5raW5nIHdhdGVyIHF1YWxpdHk/DQogICAgDQogICAgYi4gSG93IG11Y2ggd2F0ZXIgZG8gdGhlc2UgcGVvcGxlIGRyaW5rIG9uIGF2ZXJhZ2UgZWFjaCBkYXk/DQogICAgDQogICAgYy4gSG93IG1hbnkgYmFjdGVyaWEgd291bGQgdGhleSBiZSBpbmdlc3RpbmcsIGFuZCBob3cgbWFueSBvZiB0aGVtIHdvdWxkIGdldCBzaWNrIGFzIGEgcmVzdWx0IG9mIGluZ2VzdGluZyBtb3JlIHBhdGhvZ2Vucz8NCiAgICANCiAgICBkLiBXaGF0IHdvdWxkIGJlIHRoZSB0b3RhbCBoZWFsdGggaW1wYWN0LCBleHByZXNzZWQgaW4gZGlzYWJpbGl0eSBhZGp1c3RlZCBsaWZlIHllYXJzIChEQUxZcyk/DQogICAgDQpJbiBvdGhlciB3b3JkcywgeW91IHdpbGwgYmUgY29uZHVjdGluZyBhIHF1YW50aXRhdGl2ZSBtaWNyb2JpYWwgcmlzayBhc3Nlc3NtZW50IChRTVJBKSB0byBlc3RpbWF0ZSB0aGUgaW5jcmVhc2VkIGJ1cmRlbiBvZiBkaXNlYXNlIGFzc29jaWF0ZWQgd2l0aCByZWR1Y2VkIGRyaW5raW5nLXdhdGVyIHF1YWxpdHkuIFdlIHJlY29tbWVuZCB0aGF0IHlvdSB1c2UgdGhlIGZvbGxvd2luZyByZXNvdXJjZXMgdG8gYWlkIGluIHlvdXIgaW52ZXN0aWdhdGlvbjoNCg0KMS4gSGF2ZWxhYXIsIEEuSC4sICYgTWVsc2UsIEouTS4gKDIwMDMpICpRdWFudGlmeWluZyBwdWJsaWMgaGVhbHRoIHJpc2sgaW4gdGhlIFdITyBHdWlkZWxpbmVzIGZvciBkcmlua2luZy13YXRlciBxdWFsaXR5OiBBIGJ1cmRlbiBvZiBkaXNlYXNlIGFwcHJvYWNoLiogTmF0aW9uYWwgSW5zdGl0dXRlIGZvciBQdWJsaWMgSGVhbHRoIGFuZCB0aGUgRW52aXJvbm1lbnQgb2YgdGhlIE5ldGhlcmxhbmRzDQogICAgLSBBIGRpc2N1c3Npb24gcGFwZXIgb24gdGhlIGNvbmNlcHRzIGFuZCBtZXRob2RvbG9neSBvZiBkaXNhYmlsaXR5LWFkanVzdGVkIGxpZmUgeWVhcnMgKERBTFlzKQ0KYXMgYSBjb21tb24gcHVibGljIGhlYWx0aCBtZXRyaWMgYW5kIGl0cyB1c2VmdWxuZXNzIGZvciBkcmlua2luZy13YXRlciBxdWFsaXR5Lg0KaHR0cDovL3d3dy53aG8uaW50L3dhdGVyX3Nhbml0YXRpb25faGVhbHRoL3B1YmxpY2F0aW9ucy9xdWFudGlmeWluZ2hlYWx0aHJpc2tzL2VuLw0KDQoyLiBGQU8gJiBXSE8uICgyMDAzKSAqSGF6YXJkIGNoYXJhY3Rlcml6YXRpb24gZm9yIHBhdGhvZ2VucyBpbiBmb29kIGFuZCB3YXRlcjogR3VpZGVsaW5lcy4qDQogICAgLSBBIHByYWN0aWNhbCBmcmFtZXdvcmsgYW5kIHN0cnVjdHVyZWQgYXBwcm9hY2ggZm9yIHRoZSBjaGFyYWN0ZXJpemF0aW9uIG9mIG1pY3JvYmlhbCBoYXphcmRzDQppbiBmb29kIGFuZCB3YXRlciwgdG8gYXNzaXN0IGdvdmVybm1lbnRhbCBhbmQgcmVzZWFyY2ggc2NpZW50aXN0cy4NCmh0dHA6Ly93d3cud2hvLmludC93YXRlcl9zYW5pdGF0aW9uX2hlYWx0aC9wdWJsaWNhdGlvbnMvaGF6YXJkLWNoYXJhY3Rlcml6YXRpb24tZm9ycGF0aG9nZW5zLw0KZW4vDQoNCjMuIEJyb3duLCBKLiwgJiBDbGFzZW4sIFQuICgyMDEyKS4gKkhpZ2ggQWRoZXJlbmNlIElzIE5lY2Vzc2FyeSB0byBSZWFsaXplIEhlYWx0aCBHYWlucyBmcm9tIFdhdGVyIFF1YWxpdHkgSW50ZXJ2ZW50aW9ucy4qIFBMb1MgT05FLCA3KDUpLCBlMzY3MzUuIGh0dHA6Ly9kb2kub3JnLzEwLjEzNzEvam91cm5hbC5wb25lLjAwMzY3MzUNCiAgICAtIEEgZGVzY3JpcHRpb24gb2YgYSBRUk1BIG1vZGVsIHVzZWQgdG8gZXN0aW1hdGUgdGhlIGxldmVsIG9mIGFkaGVyZW5jZSBuZWNlc3NhcnkgdG8gc2lnbmlmaWNhbnRseSBpbmNyZWFzZSBEQUxZcyB1c2luZyBkaWZmZXJlbnQgbGV2ZWxzIG9mIGNvbnRhbWluYXRpb24gYW5kIHdhdGVyIHRyZWF0bWVudCBlZmZpY2FjaWVzLg0KDQojIDEuIEN1cnJlbnQgQnVyZGVuIG9mIERpc2Vhc2UNCg0KVG8gZGV0ZXJtaW5lIHRoZSBjdXJyZW50IGJ1cmRlbiBvZiBkaXNlYXNlIGZyb20gdW5zYWZlIHdhdGVyLCB5b3UnbGwgd2FudCB0byBjaGVjayBvdXQgdGhlIEdsb2JhbCBCdXJkZW4gb2YgRGlzZWFzZSAoR0JEKSBWaXN1YWxpemF0aW9uIGF0IHRoZSBJbnN0aXR1dGUgb2YgSGVhbHRoIE1ldHJpY3MgYW5kIEV2YWx1YXRpb24gKElITUUpOiBodHRwczovL3Zpemh1Yi5oZWFsdGhkYXRhLm9yZy9nYmQtY29tcGFyZS8uDQoNClNlbGVjdCB0aGUgc2Vjb25kIGljb24gb24gdGhlIGxlZnQtaGFuZCBzaWRlICgiUmlza3MgYnkgQ2F1c2UiKSwgc2VsZWN0IGxldmVsIGZvdXIgb24gdGhlIHNsaWRlciwgYW5kIHNlbGVjdCAiVW5pdGVkIFN0YXRlcyIgZm9yIGxvY2F0aW9uLiBUaGVuIHNlbGVjdCAiRGlhcnJoZWEvTFJJL290aGVyIiBvbiB0aGUgcmlnaHQtaGFuZCBzaWRlLiBGaW5kICJVbnNhZmUgd2F0ZXIiIGluIHRoZSByYW5raW5ncy4gV2hhdCBhcmUgdGhlIHRvdGFsIG51bWJlciBvZiBEQUxZcywgdGhlIHBlcmNlbnQgb2YgdG90YWwgREFMWXMsIGFuZCB0aGUgREFMWSByYXRlIChudW1iZXIgb2YgREFMWXMgcGVyIDEwMCwwMDApPyANCg0KTm93IG5hdmlnYXRlIHRvIHRoZSBhcnJvdyBkaWFncmFtIHNob3dpbmcgdGhlIHJpc2tzIGZvciBlYWNoIGNhdXNlIGFuZCBtYWtlIHN1cmUgdGhhdCBsZXZlbCBmb3VyIGlzIHN0aWxsIHNlbGVjdGVkIG9uIHRoZSBzbGlkZXIgYW5kIFVuaXRlZCBTdGF0ZXMgaXMgc2VsZWN0ZWQgZm9yIGxvY2F0aW9uLiBEb3dubG9hZCB0aGlzIGRhdGEgdXNpbmcgdGhlIERvd25sb2FkIGJ1dHRvbiBvbiB0aGUgdG9wIHJpZ2h0IGFuZCBkZXRlcm1pbmUgd2hlcmUgZGlhcnJoZWFsIGRpc2Vhc2VzIHJhbmtlZCBmb3IgdGhlIFVuaXRlZCBTdGF0ZXMgaW4gMjAxNi4NCg0KTm93IGRvIHRoZSBzYW1lIHRoaW5nIChkZXRlcm1pbmUgdGhlIHRvdGFsIERBTFlzLCB0aGUgcGVyY2VudCBvZiB0b3RhbCBEQUxZcywgdGhlIERBTFkgcmF0ZSwgYW5kIHRoZSBjYXVzZSByYW5raW5nKSBmb3IgU3ViLVNhaGFyYW4gQWZyaWNhIGluIDIwMTYuDQoNCiFbU2NyZWVuc2hvdCBvZiBJSE1FIFZpc3VhbGl6YXRpb24gRGFzaGJvYXJkXShEaXNlYXNlQnVyZGVuX0xJLmpwZykNCg0KIyAyYS4gUG9wdWxhdGlvbg0KDQpXaGF0IHdhcyB0aGUgcG9wdWxhdGlvbiBvZiB0aGUgVW5pdGVkIFN0YXRlcyBpbiAyMDE2Pw0KDQpgYGB7cn0NCmxpYnJhcnkoTW9udGVDYXJsbykNCmxpYnJhcnkoZGF0YS50YWJsZSkNCg0KcG9wdWxhdGlvbiA9IDANCg0KYGBgDQoNCiMgMmIuIFdhdGVyIENvbnN1bXB0aW9uDQoNCkhvdyBtdWNoIHdhdGVyIGRvIHBlb3BsZSBkcmluayBvbiBhdmVyYWdlIHBlciBkYXk/IFNob3VsZCB0aGUgYW1vdW50IG9mIHdhdGVyIGNvbnN1bWVkIGJlIGF2ZXJhZ2VkIG9yIHNpbXVsYXRlZD8gV2hhdCBhcmUgdGhlIGJlbmVmaXRzIG9mIGNvbmR1Y3RpbmcgYSBzaW11bGF0aW9uIHZlcnN1cyBhIHNpbmdsZSBlc3RpbWF0ZSBiYXNlZCBvbiBhdmVyYWdlIHZhbHVlcz8NCg0KSWYgeW91J3JlIG5vdCBmYW1pbGlhciB3aXRoIGdlbmVyYXRpbmcgcmFuZG9tIG51bWJlcnMgb3Igd3JpdGluZyBhIGZ1bmN0aW9uIGluIFIsIGhlcmUncyBhbiBleGFtcGxlIHRvIHNpbXVsYXRlIHRoZSBhcHByb3hpbWF0ZSBudW1iZXIgb2YgbGl0ZXJzIHRoYXQgYSBwZXJzb24gY291bGQgZHJpbmsgZWFjaCBkYXkgaW4gYSB5ZWFyLiBTZWUgaWYgeW91IGNhbiBnZW5lcmF0ZSBhIGRhdGEgdGFibGUgdGhhdCByYW5kb21seSBzYW1wbGVzIHRoZSBhbW91bnQgb2Ygd2F0ZXIgMTAwLDAwMCBwZW9wbGUgd291bGQgZHJpbmsgaW4gYSB5ZWFyLiBIaW50OiB5b3UgbWlnaHQgdHJ5IHRoZSBmdW5jdGlvbiByZXBsaWNhdGUuDQoNCmBgYHtyfQ0KDQojIGZ1bmN0aW9uIHRvIHJhbmRvbWx5IHNlbGVjdGVkIGJldHdlZW4gMSwgMiwgYW5kIDUgbGl0ZXJzIG9mIHdhdGVyIHBlciBwZXJzb24gcGVyIGRheQ0KZ2VuZXJhdGVfd2F0ZXIgPSBmdW5jdGlvbihuPTEpIHsNCiAgc2FtcGxlKGMoMSwyLDUpLG4scmVwbGFjZSA9IFRSVUUpDQp9DQoNCmdlbmVyYXRlX3dhdGVyKDM2NSkNCg0KIyBnZW5lcmF0ZSBhIGRhdGEgdGFibGUgKG9yIGRhdGEgZnJhbWUgb3IgbWF0cml4KSB3aXRoIDM2NSBjb2x1bW5zIGFuZCAxMDAsMDAwIHJvd3Mgd2l0aCByYW5kb21seSBzYW1wbGUgYW1vdW50cyBvZiB3YXRlciBmb3IgZWFjaCBlbnRyeQ0KDQpgYGANCg0KIyAyYy4gRG9zZS1SZXNwb25zZQ0KDQpIb3cgbWFueSBvcmdhbmlzbXMgd291bGQgcGVvcGxlIGJlIGluZ2VzdGluZyBvbiBhdmVyYWdlIHBlciBsaXRlciBvZiB3YXRlcj8gV2hhdCBpcyB0aGUgcHJvYmFiaWxpdHkgb2YgaW5mZWN0aW9uIGZvciB0aGUgbnVtYmVyIG9mIG1pY3JvYmVzIGluZ2VzdGVkPyBXaGF0IGlzIHRoZSBwcm9iYWJpbGl0eSBvZiBpbGxuZXNzIGdpdmVuIGluZmVjdGlvbj8NCg0KSGVyZSBhcmUgdHdvIGRpZmZlcmVudCB3YXlzIHRvIHJhbmRvbWx5IHNlbGVjdCB0aGUgbnVtYmVyIG9mIG9yZ2FuaXNtcyBwcmVzZW50IGluIGEgbGl0ZXIgb2Ygd2F0ZXI6IG9uZSBzYW1wbGVzIGZyb20gYSBsb2ctbm9ybWFsIGRpc3RyaWJ1dGlvbiBhbmQgdGhlIG90aGVyIHNhbXBsZXMgZnJvbSBhbiBlbXBpcmljYWwgZGlzdHJpYnV0aW9uIGJhc2VkIG9uIHdhdGVyIHF1YWxpdHkgdGVzdGluZy4gTWFrZSBzdXJlIHRoYXQgeW91IGNhbiBqdXN0aWZ5IHdoaWNoIG9uZSB0aGF0IHlvdSB1c2UsIGFzIHdlbGwgYXMgdGhlIHBhcmFtZXRlcnMgdXNlZCAoZS5nLiwgdGhlIG1lYW4gZm9yIHRoZSBsb2ctbm9ybWFsIGRpc3RyaWJ1dGlvbikuIEhvdyBkbyB5b3VyIHR3byBkYXRhIHRhYmxlcyBjb21wYXJlPw0KDQpgYGB7cn0NCg0KIyBnZW5lcmF0ZSBudW1iZXIgb2Ygb3JnYW5pc21zIGNvbnN1bWVkIGVtcGlyaWNhbGx5IChiYXNlZCBvbiBsb2ctbm9ybWFsIGRpc3RyaWJ1dGlvbikNCm9yZ2FuaXNtc19sbm9ybSA8LSBmdW5jdGlvbihuID0gMSxtZWFuID0gMSkgew0KICANCiAgcmxub3JtKG4sIG1lYW5sb2cgPSBtZWFuLCBzZGxvZyA9IG1lYW4pDQp9DQoNCiMgZ2VuZXJhdGUgbnVtYmVyIG9mIG9yZ2FuaXNtcyBjb25zdW1lZCBlbXBpcmljYWxseSAoYmFzZWQgb24gRS4gY29saSB3YXRlciB0ZXN0aW5nKQ0Kb3JnYW5pc21zX2VtcGlyaWNhbCA8LSBmdW5jdGlvbihuID0gMSkgew0KIA0KICBzYW1wbGUoYygxNCw3NSw5LDE4LDE0LDIyLDgsMTQsNiwxMiwyNiw2LDEsMiw4LDQpLG4scmVwbGFjZSA9IFRSVUUpICogMTANCn0NCg0KIyBub3cgY3JlYXRlIHR3byBuZXcgZGF0YSB0YWJsZXMgd2l0aCB0aGUgbnVtYmVyIG9mIG9yZ2FuaXNtcyBwZXIgbGl0ZXIgZm9yIDEwMCwwMDAgcGVvcGxlIGZvciBib3RoIGRpc3RyaWJ1dGlvbnMNCg0KDQpgYGANCg0KWW91IG5vdyBoYXZlIHR3byBkYXRhIHRhYmxlcyB0aGF0IHJlcHJlc2VudCB0aGUgbnVtYmVyIG9mIG9yZ2FuaXNtcyAxMDAsMDAwIHBlb3BsZSB3b3VsZCBpbmdlc3QgaW4gZWFjaCBsaXRlciBvZiB3YXRlciBmb3IgYSB5ZWFyLiBQaWNrIHRoZSBvbmUgdGhhdCB5b3UgdGhpbmsgaXMgbW9yZSBhY2N1cmF0ZS4gTm93IHlvdSBuZWVkIHRvIGRldGVybWluZSBlYWNoIHBlcnNvbidzIGRhaWx5IGRvc2Ugb2Ygb3JnYW5pc21zLCB0aGVpciBwcm9iYWJpbGl0eSBvZiBpbmZlY3Rpb24sIGFuZCB0aGVpciBwcm9iYWJpbGl0eSBvZiBpbGxuZXNzIGdpdmVuIGluZmVjdGlvbi4NCg0KYGBge3J9DQoNCiMgbnVtYmVyIG9mIG1pY3JvYmVzIGluZ2VzdGVkIHBlciBkYXkNCmRvc2UgPSBkdF93YXRlciAqIGR0X2xub3JtDQoNCiMgcHJvYmFiaWxpeSBkZW5zaXR5IGZ1bmN0aW9uIGZvciBjYW1weWxvYmFjdGVyIGluZmVjdGlvbg0KYmV0YV9wb2lzc29uID0gZnVuY3Rpb24oZG9zZSwgYWxwaGEgPSAwLjE0NSwgbjUwID0gODk2KSB7DQogIA0KICAxIC0gKCAxICsgKGRvc2UgLyBuNTApICogKCAyXigxL2FscGhhKSAtIDEgKSApXigtYWxwaGEpDQp9DQoNCiMgZ2VuZXJhdGUgcHJvYmFiaWxpdHkgb2YgZGFpbHkgaW5mZWN0aW9uIChiZXRhLXBvaXNzb24gZnVuY3Rpb24pDQpwX2luZiA8LSBiZXRhX3BvaXNzb24oZG9zZSkNCiAgDQojIGdlbmVyYXRlIHByb2JhYmlsaXR5IG9mIGlsbG5lc3MgZ2l2ZW4gaW5mZWN0aW9uICgwLjMgZm9yIGNhbXB5bG9iYWN0ZXIpDQpwX2lsbG5lc3NfaW5mID0gMC4zDQpwX2lsbG5lc3MgPC0gcF9pbmYgKiBwX2lsbG5lc3NfaW5mDQoNCmBgYA0KDQojIDJkLiBIZWFsdGggSW1wYWN0DQoNCllvdSBzaG91bGQgaGF2ZSBhIGxhcmdlIG1hdHJpeCB3aXRoIHRoZSByaXNrIG9mIGRhaWx5IGluZmVjdGlvbiBkdWUgdG8gaW5nZXN0aW5nIGRpZmZlcmVudCBhbW91bnRzIG9mIGNhbXB5bG9iYWN0ZXIgYmFjdGVyaWEgb3ZlciB0aGUgY291cnNlIG9mIG9uZSB5ZWFyIGZvciAxMDAsMDAwIGluZGl2aWR1YWxzLiBOb3cgd2Ugd2lsbCB1c2UgdGhlIGRpc2Vhc2UgYnVyZGVuIGFzc29jaWF0ZWQgd2l0aCBjYW1weWxvYmFjdGVyaW9zaXMgKHRyeSBzYXlpbmcgdGhhdCBmaXZlIHRpbWVzIHJlYWxseSBmYXN0KSB0byBjYWxjdWxhdGUgdGhlIHRvdGFsIG51bWJlciBvZiBkaXNhYmlsaXR5IGFkanVzdGVkIGxpZmUgeWVhcnMgYXNzb2NpYXRlZCB3aXRoIGluY3JlYXNlZCBleHBvc3VyZSB0byBjYW1weWxvYmFjdGVyIGJhY3RlcmlhLiBUbyBkbyB0aGlzIHlvdSBoYXZlIHRvIG1ha2UgYXNzdW1wdGlvbnMgKHRoYXQgY2FuIGJlIGp1c3RpZmllZCkgYWJvdXQgdGhlIHByb3BvcnRpb24gb2YgdGhlIHBvcHVsYXRpb24gdGhhdCBpcyBzdXNjZXB0aWJsZSB0byBpbmZlY3Rpb24gYW5kIHRoZSBkaXNlYXNlIGJ1cmRlbiBhc3NvY2lhdGVkIHdpdGggY2FtcHlsb2JhY3Rlcmlvc2lzLg0KICAgIA0KYGBge3J9DQoNCiMgcGVyY2VudCBvZiB0aGUgcG9wdWxhdGlvbiBzdXNjZXB0aWJsZSB0byBpbmZlY3Rpb24gKGNhbXB5bG9iYWN0ZXIpDQpzdXNjZXB0aWJsZSA9IDEuMDANCg0KIyBkaXNlYXNlIGJ1cmRlbiBwZXIgY2FzZSAoY2FtcHlsb2JhY3RlcikNCmRiX2Nhc2UgPSA0LjZlLTMNCg0KIyBnZW5lcmF0ZSBEQUxZcyBwZXIgeWVhcg0KREFMWXNfeWVhciA9IHBfaWxsbmVzcyAqIGRiX2Nhc2UgKiBzdXNjZXB0aWJsZQ0KICANCiMgZ2VuZXJhdGUgdG90YWwgREFMWXMgcGVyIDEwMCwwMDANCkRBTFlzX3RvdGFsIDwtIHN1bShEQUxZc195ZWFyKQ0KDQpEQUxZc190b3RhbA0KDQpgYGANCg0KIyBTaW11bGF0aW9uIG9mIERpc2Vhc2UgQnVyZGVuDQoNCk5vdyB5b3UgaGF2ZSB0aGUgdG90YWwgZGlzZWFzZSBidXJkZW4gYXNzb2NpYXRlZCB3aXRoIGluY3JlYXNlZCBleHBvc3VyZSB0byBjYW1weWxvYmFjdGVyLiBIb3dldmVyLCB0aGVyZSBhcmUgdHdvIHByb2JsZW1zLiBGaXJzdCwgd2UgYXNzdW1lZCB0aGF0IGEgcGVyc29uIGNvdWxkIGhhdmUgY2FtcHlsb2JhY3Rlcmlvc2lzIGV2ZXJ5IGRheSwgd2hlcmVhcyBpbiByZWFsaXR5IGluZmVjdGlvbnMgYW5kIGlsbG5lc3NlcyBoYXZlIGF2ZXJhZ2UgZHVyYXRpb25zIHRoYXQgYXJlIGJha2VkIGludG8gdGhlIGRpc2Vhc2UgYnVyZGVuIHBlciBjYXNlIGVzdGltYXRlcy4gU2Vjb25kLCB3ZSBtYWRlIGFzc3VtcHRpb25zIGFib3V0IHRoZSBudW1iZXIgb2YgY2FtcHlsb2JhY3RlciBiYWN0ZXJpYSBwcmVzZW50IGluIGVhY2ggbGl0ZXIgb2Ygd2F0ZXIgd2hlbiBpbiByZWFsaXR5IHdlJ3JlIG5vdCBzdXJlIGhvdyBtYW55IGJhY3RlcmlhIG1pZ2h0IGJlIHByZXNlbnQuIEFsc28sIGZvciBzb21lIGlsbG5lc3NlcyB0aGUgZGlzZWFzZSBidXJkZW4gcGVyIGNhc2UgaXNuJ3QgYSBmaXhlZCBudW1iZXIuIEFzIGEgcmVzdWx0LCB3ZSBuZWVkIHRvIHJlLXJ1biB0aGUgZXhwZXJpbWVudCB3aXRoIG11bHRpcGxlIHJlcGV0aXRpb25zIHRvIGdlbmVyYXRlIGEgY29uZmlkZW5jZSBpbnRlcnZhbCBmb3Igb3VyIERBTFkgZXN0aW1hdGVzLg0KDQpJbiBvcmRlciB0byBzaW11bGF0ZSB0aGUgZGlzZWFzZSBidXJkZW4gYXNzb2NpYXRlZCB3aXRoIGluY3JlYXNlZCBleHBvc3VyZSB0byBwYXRob2dlbnMsIHdlIHdpbGwgY29uZHVjdCBhIE1vbnRlIENhcmxvIHNpbXVsYXRpb24uIEkndmUgb3B0ZWQgdG8gdXNlIHRoZSBNb250ZUNhcmxvIHBhY2thZ2UgKGh0dHBzOi8vd3d3LnItYmxvZ2dlcnMuY29tL2ludHJvZHVjaW5nLXRoZS1tb250ZWNhcmxvLXBhY2thZ2UvKSwgYnV0IHlvdSBjYW4gZmVlbCBmcmVlIHRvIHVzZSBhbm90aGVyIG1ldGhvZCBhcyB5b3Ugd2lzaC4NCg0KSSBhbSBnb2luZyB0byBpbmNsdWRlIHRoZSBjb2RlIGZvciBjYW1weWxvYmFjdGVyIGJlbG93LiBZb3VyIHJlc3BvbnNpYmlsaXR5IGlzIHRvIHVuZGVyc3RhbmQgd2hhdCBJJ20gZG9pbmcgYmVsb3cgYW5kIHRoZW4gcnVuIHNpbXVsYXRpb25zIGZvciByb3RhdmlydXMsIHNoaWdhLXRveGluIHByb2R1Y2luZyBFLiBjb2xpIFNURUMgMDE1NywgYW5kIGNyeXB0b3Nwb3JpZGl1bSBiYXNlZCBvbiBwYXJhbWV0ZXJzIGFuZCBtZXRob2RvbG9naWVzIHlvdSBjYW4gZmluZCBpbiB0aGUgbGl0ZXJhdHVyZS4gQWxzbywgYmVjYXVzZSB3ZSdyZSBydW5uaW5nIG11bHRpcGxlIGl0ZXJhdGlvbnMsIHRoZSBzaW11bGF0aW9uIGlzIG1vZGlmaWVkIHRvIG1vcmUgY2xvc2VseSBhcHByb3hpbWF0ZSB0aGUgbWV0aG9kb2xvZ3kgdXNlZCBpbiBCcm93biAmIENsYXNlbiAoY2l0ZWQgYWJvdmUpLg0KDQpGb2xsb3dpbmcgdGhlIGluc3RydWN0aW9ucyBmcm9tIHRoZSBSIEJsb2dnZXJzIHdlYnNpdGUsIEkgd2lsbCBjcmVhdGUgdGhlIGRpc2Vhc2VfYnVyZGVuIGZ1bmN0aW9uIHRvIGNhbGN1bGF0ZSB0aGUgdG90YWwgREFMWXMgZm9yIDEwMCwwMDAgcGVvcGxlICh0aG91Z2ggc2xpZ2h0bHkgZGlmZmVyZW50IGZyb20gaG93IHdlIGRpZCBpdCB1cCBhYm92ZSkuIEkgdGhlbiBzcGVjaWZ5IHRoZSBwYXJhbWV0ZXJzIEkgd2FudCB0byB2YXJ5IGluIHRoZSBzaW11bGF0aW9uLiBJbiB0aGlzIGNhc2UgSSB3aWxsIHZhcnkgdGhlIG1lYW4gZnJvbSB0aGUgbG9nLW5vcm1hbCBkaXN0cmlidXRpb24gdGhhdCB3ZSdyZSB1c2luZyB0byBnZW5lcmF0ZSByYW5kb20gbnVtYmVycyBvZiBwYXRob2dlbnMuDQoNCiMjIENhbXB5bG9iYWN0ZXIsIFJvdGF2aXJ1cywgYW5kIEUuIENvbGkNCg0KYGBge3J9DQoNCiMgZnVuY3Rpb24gdG8gY2FsY3VsYXRlIGRpc2Vhc2UgYnVyZGVuDQpkaXNlYXNlX2J1cmRlbiA9IGZ1bmN0aW9uKHBlb3BsZSwgbWVhbmxvZywgYWxwaGEsIG41MCwgcF9pbGxuZXNzX2luZiwgc3VzY2VwdGlibGUsIGRiX2Nhc2Upew0KICANCiAgIyBnZW5lcmF0ZSB3YXRlciBjb25zdW1lZA0KICB3YXRlcl9jb25zdW1lZCA8LSBzYW1wbGUoYygxLDIsNSkscGVvcGxlLHJlcGxhY2UgPSBUUlVFKQ0KICANCiAgIyBnZW5lcmF0ZSBudW1iZXIgb2Ygb3JnYW5pc20gY29uc3VtZWQgZnJvbSBsb2ctbm9ybWFsIGRpc3RyaWJ1dGlvbg0KICBudW1iZXJfb2Zfb3JnYW5pc21zIDwtIHJsbm9ybShwZW9wbGUsIG1lYW5sb2cgPSBtZWFubG9nKQ0KICANCiAgIyBnZW5lcmF0ZSBkYWlseSBkb3NlDQogIGRvc2UgPC0gd2F0ZXJfY29uc3VtZWQgKiBudW1iZXJfb2Zfb3JnYW5pc21zDQogIA0KICAjIGdlbmVyYXRlIHByb2JhYmlsaXR5IG9mIGRhaWx5IGluZmVjdGlvbiAoYmV0YS1wb2lzc29uIGZ1bmN0aW9uKQ0KICBwX2luZiA8LSAxIC0gKCAxICsgKGRvc2UgLyBuNTApICogKCAyXigxL2FscGhhKSAtIDEgKSApXigtYWxwaGEpDQogIA0KICAjIGdlbmVyYXRlIHByb2JhYmlsaXR5IG9mIGlsbG5lc3MNCiAgcF9pbGxuZXNzIDwtIHBfaW5mICogcF9pbGxuZXNzX2luZg0KICANCiAgIyBnZW5lcmF0ZSB5ZWFybHkgaW5mZWN0aW9uIHJpc2sNCiAgcF95ZWFyID0gMSAtICgxIC0gcF9pbGxuZXNzKV4zNjUNCiAgDQogICMgZ2VuZXJhdGUgREFMWXMgcGVyIHllYXINCiAgREFMWXNfeWVhciA9IHBfeWVhciAqIGRiX2Nhc2UgKiBzdXNjZXB0aWJsZQ0KICANCiAgIyBnZW5lcmF0ZSB0b3RhbCBEQUxZcyBwZXIgMTAwLDAwMA0KICBEQUxZc190b3RhbCA8LSBzdW0oREFMWXNfeWVhcikNCiAgDQogICMgcmV0dXJucyB2YWx1ZSBmb3IgTW9udGVDYXJsbyBmdW5jdGlvbg0KICByZXR1cm4obGlzdCgiREFMWXMiPURBTFlzX3RvdGFsKSkNCiAgDQp9DQoNCiMgcGFyYW1ldGVyIGxpc3QgZm9yIGNhbXB5bG9iYWN0ZXINCnBhcmFtX2NhbXB5bG9iYWN0ZXIgPC0gbGlzdCgicGVvcGxlIiA9IDEwMDAwMCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAibWVhbmxvZyIgPSBjKDEsIDAuMSwgMC4wMSwgMC4wMDEsIDAuMDAwMSksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgImFscGhhIiA9IDAuMTQ1LA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICJuNTAiID0gODk2LA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICJwX2lsbG5lc3NfaW5mIiA9IDAuMywNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAic3VzY2VwdGlibGUiID0gMS4wMCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAiZGJfY2FzZSIgPSA0LjZlLTMpDQoNCiMgZnVuY3Rpb24gdG8gcnVuIHRoZSBzaW11bGF0aW9uDQpjYW1weWxvYmFjdGVyIDwtIE1vbnRlQ2FybG8oZnVuYz1kaXNlYXNlX2J1cmRlbiwgbnJlcD0xMDAwLCBwYXJhbV9saXN0ID0gcGFyYW1fY2FtcHlsb2JhY3RlcikNCg0KIyBzdW1tYXJ5IG9mIHJlc3VsdHMNCnN1bW1hcnkoY2FtcHlsb2JhY3RlciRyZXN1bHRzJERBTFlzKQ0KDQoNCg0KIyBwYXJhbWV0ZXIgbGlzdCBmb3Igcm90YXZpcnVzIChmaWxsIHRoaXMgaW4pDQoNCg0KIyBwYXJhbWV0ZXIgbGlzdCBmb3IgRS4gY29saSAoZmlsbCB0aGlzIGluKQ0KDQoNCg0KDQojIGZ1bmN0aW9uIHRvIHJ1biB0aGUgc2ltdWxhdGlvbg0Kcm90YXZpcnVzIDwtIE1vbnRlQ2FybG8oZnVuYz1kaXNlYXNlX2J1cmRlbiwgbnJlcD0xMDAwLCBwYXJhbV9saXN0ID0gcGFyYW1fcm90YXZpcnVzKQ0KDQojIHN1bW1hcnkgb2YgcmVzdWx0cw0Kc3VtbWFyeShyb3RhdmlydXMkcmVzdWx0cyREQUxZcykNCg0KIyBmdW5jdGlvbiB0byBydW4gdGhlIHNpbXVsYXRpb24NCmVjb2xpIDwtIE1vbnRlQ2FybG8oZnVuYz1kaXNlYXNlX2J1cmRlbiwgbnJlcD0xMDAwLCBwYXJhbV9saXN0ID0gcGFyYW1fZWNvbGkpDQoNCiMgc3VtbWFyeSBvZiByZXN1bHRzDQpzdW1tYXJ5KGVjb2xpJHJlc3VsdHMkREFMWXMpDQoNCmBgYA0KDQojIyBDcnlwdG9zcG9yaWRpdW0NCg0KV2h5IGlzIGNyeXB0b3Nwb3JpZGl1bSBiZWluZyBtb2RlbGVkIGluIGl0cyBvd24gc2VjdGlvbj8NCg0KYGBge3J9DQoNCmRpc2Vhc2VfYnVyZGVuX2NyeXB0byA9IGZ1bmN0aW9uKHBlb3BsZSwgbWVhbmxvZywgaW5mZWN0aXZpdHksIHBfaWxsbmVzc19pbmYsIHN1c2NlcHRpYmxlLCBkYl9jYXNlKXsNCg0KICAjIGZpbGwgdGhpcyBpbg0KICANCn0NCg0KIyBwYXJhbWV0ZXIgbGlzdCBmb3IgY3J5cHRvc3BvcmlkaXVtIChmaWxsIHRoaXMgaW4pDQoNCg0KIyBmdW5jdGlvbiB0byBydW4gdGhlIHNpbXVsYXRpb24NCmNyeXB0byA8LSBNb250ZUNhcmxvKGZ1bmM9ZGlzZWFzZV9idXJkZW5fY3J5cHRvLCBucmVwPTEwMDAsIHBhcmFtX2xpc3QgPSBwYXJhbV9jcnlwdG8pDQoNCiMgc3VtbWFyeSBvZiByZXN1bHRzDQpzdW1tYXJ5KGNyeXB0byRyZXN1bHRzJERBTFlzKQ0KDQpgYGANCg0KWW91IHNob3VsZCBub3cgaGF2ZSBlc3RpbWF0ZXMgb2YgdGhlIHRvdGFsIERBTFlzIGR1ZSB0byBpbmZlY3Rpb25zIGZyb20gY2FtcHlsb2JhY3Rlciwgcm90YXZpcnVzLCBzaGlnYS10b3hpbiBwcm9kdWNpbmcgRS4gY29saSBTVEVDIDAxNTcsIGFuZCBjcnlwdG9zcG9yaWRpdW0uIEhvdyBkbyB0aGVzZSBlc3RpbWF0ZXMgY29tcGFyZSB3aXRoIHRoZSBmaXJzdCBEQUxZIGVzdGltYXRlcyBmcm9tIDJhLiB0aHJvdWdoIDJkLiBhYm92ZT8gV2hhdCBkaWZmZXJlbnQgYXNzdW1wdGlvbnMgd2VyZSBtYWRlLCBhbmQgaG93IGRpZCB0aGF0IGFmZmVjdCB0aGUgb3V0Y29tZT8NCg0KIyBMYWIgQXNzaWdubWVudA0KDQpZb3Ugd2lsbCBuZWVkIHRvIGNvbXBvc2UgYSBmb3JtYWwgbGFiIHJlcG9ydCAodGhhdCBpbmNsdWRlcyBwYXJ0IG9uZSBhbmQgcGFydCB0d28pIG5vdCBleGNlZWRpbmcgZml2ZSBwYWdlcyAoZXhjbHVkaW5nIGFwcGVuZGljZXMpLiBUaGlzIGNhbiBiZSBzdWJtaXR0ZWQgYXMgYW4gUiBOb3RlYm9vayAoUERGIHZlcnNpb24gb2YgdGhlIG1haW4gcmVwb3J0IGxlc3MgdGhhbiA1IHBhZ2VzKSBvciBhcyBhIFBERi4gWW91IHdpbGwgbmVlZCB0byBpbmNsdWRlIGEgYnJpZWYgaW50cm9kdWN0aW9uLCBhIG1ldGhvZHMgc2VjdGlvbiwgcmVzdWx0cywgZGlzY3Vzc2lvbiwgYW5kIGEgYnJpZWYgY29uY2x1c2lvbi4gU2VlIHRoZSBzeWxsYWJ1cyBhbmQgZ3JhZGluZyBydWJyaWMgZm9yIG1vcmUgYSBtb3JlIGRldGFpbGVkIGRlc2NyaXB0aW9uLg0KDQpJbiBwYXJ0aWN1bGFyLCB5b3Ugc2hvdWxkIGFkZHJlc3MgdGhlIGZvbGxvd2luZyBxdWVzdGlvbnM6DQoNCjEuIEhvdyBkb2VzIHRoZSBuZXdseSBjYWxjdWxhdGVkIGRpc2Vhc2UgYnVyZGVuIGNvbXBhcmUgdG8gdGhlIHByZXZpb3VzIGRpc2Vhc2UgYnVyZGVuPyBIb3cgZG9lcyBpdCBjb21wYXJlIHdpdGggb3RoZXIgY2F1c2VzIG9mIGRpc2Vhc2UgYnVyZGVuIGluIHRoZSBVbml0ZWQgU3RhdGVzIChodHRwczovL3Zpemh1Yi5oZWFsdGhkYXRhLm9yZy9nYmQtY29tcGFyZS8pPyBIb3cgYWJvdXQgaW4gTG93IFNESSBjb3VudHJpZXM/DQoNCjIuIFNpbXVsYXRpb25zIHJlcXVpcmUgYSBsb3Qgb2YgYXNzdW1wdGlvbnMuIENvbW1lbnQgb24gd2hpY2ggYXNzdW1wdGlvbnMgZmVsdCBkdWJpb3VzIChvciB0aGF0IHlvdSB3ZXJlbid0IGFibGUgdG8ganVzdGlmeSBmcm9tIHRoZSBsaXRlcmF0dXJlKSBhbmQgd2hpY2ggYXNzdW1wdGlvbnMgbW9zdCBzaWduaWZpY2FudGx5IGluZmx1ZW5jZWQgeW91ciByZXN1bHRzLiBIb3cgbXVjaCBmYWl0aCBkbyB5b3UgaGF2ZSBpbiB5b3VyIHJlc3VsdHM/DQoNCjMuIFdoeSBpcyBpdCBpbXBvcnRhbnQgdG8gY29uZHVjdCBhIE1vbnRlIENhcmxvIHNpbXVsYXRpb24gaW5zdGVhZCBvZiBqdXN0IHVzaW5nIGF2ZXJhZ2UgdmFsdWVzPw0KDQo0LiBJcyBkaXNlYXNlIGJ1cmRlbiBwZXIgY2FzZSB0aGUgc2FtZSBmb3IgYWxsIGxvY2F0aW9ucz8gSG93IHdvdWxkIHRoYXQgYXNzdW1wdGlvbiBhZmZlY3QgdGhlIG91dGNvbWUgb2YgdGhpcyBleHBlcmltZW50Pw0KDQpUaGUgZmluYWwgcmVwb3J0IHdpbGwgYmUgbmVlZCB0byBiZSBzdWJtaXR0ZWQgb24gRDJMIHRocm91Z2ggRHJvcGJveCBieSAzcG0gb24gVHVlc2RheSwgTWFyY2ggMTN0aC4NCg==