[1] -1

Load data

Iowa COVID-19 Summary 2020-08-08

Today we had 384 new positive tests which is 9.8% (9.3% in the last week) of the tests recorded in the last 24 hours. There are 10,337 people actively sick and 2% (229) are hospitalized. 25.3% (58) of those hospitalized are in the ICU.

View Data

So, it turns out to be very difficult to find past data in the State of Iowa since they re-publish everything daily. Here are the last 6 days of data if you are interested:

tail(clean)

Data Exploration

Known Active Cases

This is a graph of the known active cases in Iowa. These people have tested positive, but have not moved on to a stage where they are not infectious. I say it that way because we know that a lot of patients with mild and moderate COVID-19 are very sick even after they are no longer infectious.

null device 
          1 

Sigh. On June 30 IDPH decided to count anyone who was still not listed as recovered after 28 days as recovered. So, let’s go back into the historic data and try to add that expectation to past recoverd data. Fortunately it is possible to download the data from the website https://coronavirus.iowa.gov/#CurrentStatus

Percent Positive Active Cases

null device 
          1 
png 
  2 

Bremer County

I started recording daily data on Bremer county on May 29, 2020. There will be problems with the recovered data since I have yet to get tables of data for the county and the definition of recovered changed on June 30. Thus, the following graph omits that data.

null device 
          1 
png 
  2 

png 
  2 

There are 97 active cases and 2 hospitalized in Bremer County today. The 7 day positivity rate is 15.5%.

Positive Tests

Logistic Model

To try to fit a logistic model to the data, we want to fit a parabola to the rate of change, but the input variable is cases or deaths and not time. This is because the logistic model comes from the differential equation \(\displaystyle{\frac{dP}{dt}= kP(1-\frac{P}{M})}\). Note that this equation as a function of \(P\) is a parabola with zeroes at \(P=0\) and \(P=M\).

clean <- clean[-c(1,10),]
with(clean, plot(positive, New.Positive, pch=16, xlab = "Positive Counts", ylab = "Rate of Change of Positive", cex.lab = 1.3, col = "blue"))

Now, it doesn’t really look quadratic, but we are not going to let that stop us from mathematics. Next, we will fit a quadratic model to the data.

clean$P2 <- as.numeric(clean$positive)^2
quadratic <-lm(New.Positive ~ positive + P2-1, data = clean)
r <- quadratic$coefficients[2]*(-1)
M <- quadratic$coefficients[1]/r
Mprint <- format(M, scientific = FALSE)
predictedcounts <- with(clean,predict(quadratic,list(positive = positive, P2 = P2)))

Let’s plot the model:

So, we have a quadratic model that looks like \(\frac{dP}{dt}\) = 0.0275512\(P^2\) + -3.923460210^{-7}\(P\) = 3.923460210^{-7}\(P(1-P/\) 70221.79\()\). This is looking pretty good. In particular, because \(M=\) 70221.79, we can estimate that 2.23% of Iowa’s population will become infected. We would like to see what that looks like for the original data. When R performs logistic modeling, it usually has binomial data and thus expects numbers that are between zero and one. We will use our estimate of \(M\) to create positive counts that are a percentage of \(M\).

non-integer #successes in a binomial glm!

Okay, that looks quite good. What will it predict for the next 28 days?

This predicts that in 14 days, Iowa will have 55813 infected people.

SIR Model

This should be more interesting and probably won’t be done for a week. The differential equations for the SIR model are:

\(\frac{dS}{dt} = -r_1SI\), \(\frac{dR}{dt} = r_2I\), \(\frac{dI}{dt} = -\frac{dS}{dt} - \frac{dR}{dt}\)

So, we may have enough data to estimate \(r_1\) and \(r_2\). We would do this using a linear model on the change of recovered to esitmate \(r_2\) and then that model and the rate of change of infecteds to estimate \(r_1\). We may have to use \(M\) from the logistic growth model to estimate \(S\).

Step 1: Estimate \(r_2\)

SIR <- with(clean, data.frame(
    dS = (-1)*diff(positive),
    dR = diff(Recovered),
    dI = diff(Still.Sick),
    dD = diff(deaths)
))
SIR <- SIR %>% mutate(
    R = clean$Recovered[-1],
    I = clean$Still.Sick[-1],
    day = clean$date[-1],
    S = M - clean$positive[-1]
    )
SIR$day = as.POSIXct(SIR$day)
SIR <- SIR[complete.cases(SIR),]

Let’s first just graph our data

qplot(day, data = SIR) + 
    stat_smooth(aes( y = S),method = "loess") + 
    stat_smooth( aes( y = I), color = "red", method = "loess") +
    stat_smooth( aes( y = R), color = "green", method = "loess") +
    theme(legend.position = "right")

(Note 5/30/2020) As of about March 15 this no longer looks like the SIR model that you would expect. We have this unexpected linear growth in \(R\) where we would expect things to be more concave down at this point. Not good.

Next, let’s see about coefficients:

dRmodel <- lm(dR ~ 0+I, data = SIR)
r2 <- dRmodel$coefficients[1]
dImodel <- lm (dS ~ 0 + S*I, data = SIR)
r1 <- dImodel$coefficients[1]

Now we plug this into the DE solver.

require(deSolve)
state <- c(S = as.numeric(1-clean$positive[25]/M), 
           I = as.numeric(clean$Still.Sick[25]/M), 
           R = as.numeric(clean$Recovered[25]/M))
times <- seq(0, nrow(clean)-24, by = 1)
parameters <- c(r1=as.numeric(r1*M),
                r2=as.numeric(r2))

# R function to calculate the value of the derivatives at each time value
    # Use the names of the variables as defined in the vectors above
SIR <- function(time, state, parameters){
      with(as.list(c(state, parameters)), {
        dS = r1*S*I
        dR = r2*I
        dI = -r1*S*I -r2*I
        return(list(c(dS, dI, dR)))
      })
}

## Integration with 'ode'
out <- ode(y = state, times = times, func = SIR, parms = parameters, method = rk4)
    
    ## Ploting
    out.df = as.data.frame(out) # required by ggplot: data object must be a data frame
    require(reshape2)
    out.m = melt(out.df, id.vars='time') # this makes plotting easier by puting all variables in a single column
    
    p <- ggplot(out.m, aes(time, value, color = variable)) + geom_point()
    #print(p)

Exponential Model

Run a linear model on the logarithm of the positive cases.

qplot(date, log(positive), data =clean) + geom_point() + geom_smooth()+
  stat_smooth(method = "lm", col = "red") 

For the model \(positive = e^{k date}\), \(k=\) 0.0399945. Estimated doubling time for positive cases is 17.3310456 days. Here is what that looks like on the original data.

Modified Exponential Model

By now there is strong evidence that the curve is flattening. We can create a new linear model that uses the more recent data to improve our model. Let’s look to see what happens if we only use data from later when we were doing more testing.

For the model \(positive = e^{k date}\), \(k=\) 0.0182274. Estimated doubling time for positive cases is 23.7213056 days. Here is what that looks like on the original data.

Deaths

Exponential Model

We will start the data when we have non-zero deaths.

For the model \(deaths = e^{k date}\), \(k=\) 7.6213089. Estimated time for deaths to double is 21.3708173 days.

Later Data

As above, let’s look at the same models, but only after we got serious about testing.

For the model \(deaths = e^{k date}\), \(k=\) 0.0238919. Estimated time for deaths to double is 29.011853 days.

New Positives

At the beginning, we were modeling the new positive data as an exponential curve. As of about the middle of May we changed to use the logistic growth curve from the Logistic Model to predict new positive tests.

As of about the middle of May, it becomes clear that the new positive data is not exponential. Which is really good news. This is when this model gets downgraded to the Alternative Modeling section.

Accuracy

As with any test, there will be false positives (people who test positive, but aren’t infected) and false negatives (people who test negative, but are infected). On May 1, it was reported by the Governor’s office:

“Governor Reynolds says the State Hygienic Lab has validated the machines used as part of the Test Iowa program. “I’m pleased to announce that the State Hygienic Lab completed the Test Iowa validation process yesterday, achieving high ratings of 95% accuracy for determining positives and 99.7% accuracy for determining negatives.”"

This is a bit hard to interpret, but I am going to assume that it means that the false positive rate is 0.3% and the false negative rate is 5%. This agrees with earlier reports of testing where the tests used to show that you are currently infected have pretty low false positive rates and higher false negative rates because it comes back positive if it finds the virus. A false negative would be that you have the virus, but the test can’t find it which isn’t out of the range of possibility. So, let’s go back to our data and calculate the numbers:

temp <- 1/(.997*.95 - (1-.995)*(1-.95))
accuracy <- clean %>% 
    mutate(
    tp = .95*positive/temp, 
    fp = (1-.993)/temp*positive, 
    tn = 0.993/temp*negative, 
    fn = (1-.95)/temp*negative) %>%
    mutate( pos = round(tp+fn, digits = 0),
            neg = round(tn+fp, digits = 0))
lastrow = length(accuracy)

Today, the state reported 13675 total positive and 134 total negative. Due to test inaccuracy, these numbers could be as much as NA positive and NA negative.

Store Predictions

This section stores predictions.

Alternative Modeling

This didn’t turn out well, but it is still here for historical perspective:

Positives Linear Model

First run a linear model on positive test results.

qplot(date, positive, data =clean) + geom_point() + geom_smooth()+
  stat_smooth(method = "lm", col = "red")

Deaths Linear Model

qplot(date, deaths, data =cdeaths, rm.na=TRUE) + geom_point() + geom_smooth()+
  stat_smooth(method = "lm", col = "red")
Ignoring unknown parameters: rm.na

model <- lm(deaths~date, data=cdeaths)
#model$coefficients

New Positives

As of about the middle of May, it becomes clear that the new positive data is not exponential. Which is really good news. This is when this model gets downgraded to the Alternative Modeling section. For the model \(new positives = e^{k date}\), \(k=\) 0.0182274. Estimated time for new positives to double is 38.0277688 days.

LS0tDQp0aXRsZTogIkNvdmlkLTE5IEFuYWx5c2lzIg0KYXV0aG9yOiAiTWFyaWFoIEJpcmdlbiINCm91dHB1dDogaHRtbF9ub3RlYm9vaw0KLS0tDQoNCmBgYHtyIGluaXRpYWxpemF0aW9uLCBlY2hvPUZBTFNFfQ0Kc3VwcHJlc3NQYWNrYWdlU3RhcnR1cE1lc3NhZ2VzKCByZXF1aXJlKGRwbHlyKSkNCnN1cHByZXNzUGFja2FnZVN0YXJ0dXBNZXNzYWdlcyggcmVxdWlyZShsdWJyaWRhdGUpKQ0Kc3VwcHJlc3NQYWNrYWdlU3RhcnR1cE1lc3NhZ2VzKCByZXF1aXJlKGdncGxvdDIpKQ0Kc3VwcHJlc3NQYWNrYWdlU3RhcnR1cE1lc3NhZ2VzKCByZXF1aXJlKHpvbykpDQpzdXBwcmVzc1BhY2thZ2VTdGFydHVwTWVzc2FnZXMoIHJlcXVpcmUoZ3NoZWV0KSkNCmBgYA0KDQpMb2FkIGRhdGENCmBgYHtyIGVjaG89RkFMU0V9DQojIHJlYWRfY2h1bmsoJ0NvdW50eURhdGEuUicpDQpgYGANCg0KYGBge3IgbG9hZCwgZWNobyA9IEZBTFNFfQ0KY292aWQxOSA8LSByZWFkLmNzdigiY292aWQxOS5jc3YiLCBzdHJpbmdzQXNGYWN0b3JzID0gRkFMU0UpDQpjb3VudHkgPC0gcmVhZC5jc3YoImNlbnN1c0NvdW50aWVzLmNzdiIsIHN0cmluZ3NBc0ZhY3RvcnMgPSBGQUxTRSkNCiMgY292aWQxOSA8LSBnY292aWQxOQ0KbmFtZXMoY292aWQxOSlbbmFtZXMoY292aWQxOSkgPT0gIsOvLi5kYXRlIl0gPC0gJ2RhdGUnDQpjb3ZpZDE5JGRhdGUgPC0gbWR5KGNvdmlkMTkkZGF0ZSkNCmNsZWFybiA8LSAhaXMubmEoY292aWQxOSRwb3NpdGl2ZSkNCmNsZWFuIDwtIGNvdmlkMTlbY2xlYXJuLF0NCmNhbGN1bGF0ZSA8LSB3aXRoKGRhdGEgPSBjbGVhbixkYXRhLmZyYW1lKA0KICBOZXcuUG9zaXRpdmUgPSBkaWZmKHBvc2l0aXZlKSwNCiAgTmV3Lk5lZ2F0aXZlID0gZGlmZihuZWdhdGl2ZSksDQogIFRvdGFsLkRhaWx5LlRlc3RzID0gZGlmZihUb3RhbC5UZXN0ZWQpLA0KICBOZXcuRGVhdGhzID0gZGlmZihkZWF0aHMpDQogICkpDQpjYWxjdWxhdGUgPC0gcmJpbmQoYyhOQSxOQSxOQSxOQSksIGNhbGN1bGF0ZSkNCmNhbGN1bGF0ZSA8LSBjYmluZChkYXRlID0gY2xlYW4kZGF0ZSwgY2FsY3VsYXRlKQ0KY2RlYXRocyA8LSBjb3ZpZDE5WyFpcy5uYShjb3ZpZDE5JGRlYXRocyksXQ0KY2xlYW4gPC0gY2xlYW4gJT4lIG11dGF0ZSgNCiAgbmVnYXRpdmUgPSBUb3RhbC5UZXN0ZWQgLSBwb3NpdGl2ZSwNCiAgUGVyY2VudC5Qb3MgPSBwb3NpdGl2ZS9Ub3RhbC5UZXN0ZWQqMTAwLA0KICBucF83ZGF5ID0gcm9sbG1lYW4oTmV3LlBvc2l0aXZlLCBrPTcsIGFsaWduID0gInJpZ2h0IiwgZmlsbCA9IE5BKSwNCiAgTmV3LlBvc2l0aXZlID0gY2FsY3VsYXRlJE5ldy5Qb3NpdGl2ZSwNCiAgTmV3Lk5lZ2F0aXZlID0gY2FsY3VsYXRlJE5ldy5OZWdhdGl2ZSwNCiAgVG90YWwuRGFpbHkuVGVzdHMgPSBjYWxjdWxhdGUkVG90YWwuRGFpbHkuVGVzdHMsDQogIE5ldy5EZWF0aHMgPSBjYWxjdWxhdGUkTmV3LkRlYXRocywNCiAgTmV3LlBlcmNlbnQuUG9zaXRpdmUgPSBOZXcuUG9zaXRpdmUvVG90YWwuRGFpbHkuVGVzdHMNCikNCmNsZWFuIDwtIGNsZWFuICU+JSBtdXRhdGUoDQogIFdlZWsuUG9zaXRpdml0eSA9IHJvbGxhcHBseShOZXcuUG9zaXRpdmUsIDcsIEZVTj1zdW0sIGZpbGwgPSBOQSksDQogIFdlZWsuVGVzdHMgPSByb2xsYXBwbHkoVG90YWwuRGFpbHkuVGVzdHMsIDcsIEZVTj1zdW0sIGZpbGwgPSBOQSksDQogIFdlZWsuUG9zaXRpdml0eS5SYXRlID0gV2Vlay5Qb3NpdGl2aXR5L1dlZWsuVGVzdHMNCiAgKQ0KY2xlYW4kd2t0b3QgPC0gc2FwcGx5KGNsZWFuJGRhdGUsZnVuY3Rpb24oeClzdW0oY2xlYW5bZGlmZnRpbWUoY2xlYW4kZGF0ZSx4LCwiZGF5cyIpICVpbiUgMDotNixdJE5ldy5Qb3NpdGl2ZSkpDQpsYXN0cm93IDwtIG5yb3coY2xlYW4pDQpjbGVhbiA8LSBjbGVhbiAlPiUgbXV0YXRlKA0KICBuZF83ZGF5ID0gcm9sbG1lYW4oZGVhdGhzLCBrPTcsIGZpbGwgPSBOQSwpLA0KICBwcF83ZGF5ID0gcm9sbG1lYW4oTmV3LlBlcmNlbnQuUG9zaXRpdmUsIGs9NywgZmlsbCA9IE5BKSkNCmBgYA0KYGBge3IsIGVjaG8gPSBGQUxTRX0NCnRvZGF5IDwtIGNsZWFuW25yb3coY2xlYW4pLF0NCmRheSA8LSB0b2RheSRkYXRlDQpuZXdfcG9zIDwtIHRvZGF5JE5ldy5Qb3NpdGl2ZQ0KcGVyY2VudF9wb3MgPC0gcm91bmQodG9kYXkkTmV3LlBlcmNlbnQuUG9zaXRpdmUqMTAwLCBkaWdpdHMgPSAxKQ0KcGVyY2VudF9wb3M3IDwtIHJvdW5kKGNsZWFuJFdlZWsuUG9zaXRpdml0eS5SYXRlW25yb3coY2xlYW4pLTRdKjEwMCwgZGlnaXRzID0gMSkNCg0KcGVyY2VudF9ob3NwaXRhbCA8LSB0b2RheSRQZXJjZW50Lkhvc3BpdGFsaXplZA0KSUNVIDwtIHRvZGF5JElDVQ0KcGVyY2VudF9JQ1UgPC0gcm91bmQodG9kYXkkSUNVL3RvZGF5JGhvc3BpdGFsaXplZCoxMDAsIGRpZ2l0cyA9IDEpDQpzaWNrIDwtIGZvcm1hdCh0b2RheSRTdGlsbC5TaWNrLCBzY2llbnRpZmljID0gRkFMU0UsIGJpZy5tYXJrPSIsIikNCklvd2FQb3AgPC0gMzE1NTA3MA0KDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyMjIyMjIyBUaGlzIHNlY3Rpb24gZG93bmxvYWRzIHRoZSBob3NwaXRhbGl6YXRpb24gZGF0YSBwZXIgY291bnR5LiBJdCB3YXMgYWRkZWQgSnVseSAyNSwgMjAyMC4NCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQpyZXF1aXJlKHBkZnRvb2xzKQ0KcmVxdWlyZSh0aWR5dmVyc2UpDQoNCiMjIyMjIyMjIFRoZSBmaWxlIG5hbWUgaXMgYmFzZWQgb24gdGhlIGRhdGUuDQpteWRhdGUgPC0gU3lzLkRhdGUoKSAtMiAgIyBHZXQgdG9kYXkncyBkYXRlIG1pbnVzIDIgZGF5cw0KIyBteXByZXR0eWRhdGUgPC0gZm9ybWF0KG15ZGF0ZSwgZm9ybWF0ID0gIiVkJUIlWSIpDQpteXByZXR0eWRhdGUgPC0gZm9ybWF0KG15ZGF0ZSwgZm9ybWF0ID0gIiVkJWIlWSIpDQojIHBkZmZpbGVuYW1lIDwtICJodHRwczovL3d3dy5ob21lbGFuZHNlY3VyaXR5Lmlvd2EuZ292L2RvY3VtZW50cy9jb3ZpZC1zaXRlL0lBX0MxOV8yM0pVTDIwMjAucGRmIg0KIyBwZGZmaWxlbmFtZSA8LSBwYXN0ZSgiaHR0cHM6Ly93d3cuaG9tZWxhbmRzZWN1cml0eS5pb3dhLmdvdi9kb2N1bWVudHMvY292aWQtc2l0ZS9JQV9DMTlfIiwNCiAgICAgICAgICAgICAgICAgICAgICMgbXlwcmV0dHlkYXRlLCAiLnBkZiIsIHNlcD0iIikNCiMgcGFzdGUoImh0dHBzOi8vaWRwaC5pb3dhLmdvdi9Qb3J0YWxzLzEvdXNlcmZpbGVzLzYxL2NvdmlkMTkvaG9zcGl0YWxpemF0aW9ucy9JQV9DMTlfIiwNCiMgICAgICAgICAgICAgICAgICAgICAgbXlwcmV0dHlkYXRlLCAiLnBkZiIsIHNlcD0iIikNCiMgcGRmZmlsZW5hbWUgPC0gcGFzdGUoIkM6XFxVc2Vyc1xcbWFyaWFoLmJpcmdlblxcRG93bmxvYWRzXFxJQV9DMTlfIiwNCiMgICAgICAgICAgICAgICAgICAgICAgbXlwcmV0dHlkYXRlLCAiLnBkZiIsIHNlcD0iIikNCiMgDQojICBkb3dubG9hZC5maWxlKHBkZmZpbGVuYW1lLCAnaG9zcF9ieV9jb3VudHkucGRmJywgbW9kZT0id2IiKQ0KIyBmaWxlLmNvcHkocGRmZmlsZW5hbWUsICdob3NwX2J5X2NvdW50eS5wZGYnKQ0KIyMjIyMjIyBUaGUgbmV4dCBwYXJ0IHR1cm5zIHRoZSBwZGYgaW50byBhIGRhdGEgdGFibGUNCg0KaG9zcF9ieV9jb3VudHkgPC0gcGRmX3RleHQoImhvc3BfYnlfY291bnR5LnBkZiIpICU+JQ0KICAgIHJlYWRyOjpyZWFkX2xpbmVzKCkgJT4lIA0KICAgIHN0cl9zcXVpc2goKQ0KaG9zcF9ieV9jb3VudHkgPC0gaG9zcF9ieV9jb3VudHlbLSgxOjQpXQ0KaG9zcF9ieV9jb3VudHkgPC0gaG9zcF9ieV9jb3VudHlbLSgzNDozNildDQpob3NwX2J5X2NvdW50eSA8LWhvc3BfYnlfY291bnR5ICU+JQ0KICAgIHN0cnNwbGl0KCIoPz0gW0EtWmEtel0pKD88PVswLTldKXwoPz0gWzAtOV0pKD88PVtBLVphLXpdKSIsIHBlcmw9VFJVRSkNCiAgICANCmhvc3BfYnlfY291bnR5X2RmIDwtIHBseXI6OmxkcGx5KGhvc3BfYnlfY291bnR5KQ0KdGVtcDEgPC0gaG9zcF9ieV9jb3VudHlfZGZbLDE6Ml0NCnRlbXAyIDwtIGhvc3BfYnlfY291bnR5X2RmWywzOjRdDQp0ZW1wMyA8LSBob3NwX2J5X2NvdW50eV9kZlssNTo2XQ0KY29sbmFtZXModGVtcDIpIDwtIG5hbWVzKHRlbXAxKQ0KY29sbmFtZXModGVtcDMpIDwtIG5hbWVzKHRlbXAxKQ0KaG9zcF9ieV9jb3VudHkgPC0gcmJpbmQodGVtcDEsIHRlbXAyLCB0ZW1wMykNCmNvbG5hbWVzKGhvc3BfYnlfY291bnR5KSA8LSBjKCJDb3VudHkiLCAiSG9zcGl0YWxpemVkIikNCmhvc3BfYnlfY291bnR5IDwtaG9zcF9ieV9jb3VudHkgJT4lDQogICAgbXV0YXRlKEhvc3BpdGFsaXplZCA9IGFzLm51bWVyaWMoSG9zcGl0YWxpemVkKSkNCnJtKHRlbXAxLCB0ZW1wMiwgdGVtcDMsIGhvc3BfYnlfY291bnR5X2RmKQ0Kcm93bmFtZXMoaG9zcF9ieV9jb3VudHkpIDwtIGhvc3BfYnlfY291bnR5WywxXQ0KYGBgDQojIElvd2EgQ09WSUQtMTkgU3VtbWFyeSBgciBkYXlgDQoNClRvZGF5IHdlIGhhZCBgciBuZXdfcG9zYCBuZXcgcG9zaXRpdmUgdGVzdHMgd2hpY2ggaXMgYHIgcGVyY2VudF9wb3NgJSAoYHIgcGVyY2VudF9wb3M3YCUgaW4gdGhlIGxhc3Qgd2Vlaykgb2YgdGhlIHRlc3RzIHJlY29yZGVkIGluIHRoZSBsYXN0IDI0IGhvdXJzLiBUaGVyZSBhcmUgYHIgc2lja2AgcGVvcGxlIGFjdGl2ZWx5IHNpY2sgYW5kIGByIHBlcmNlbnRfaG9zcGl0YWxgIChgciB0b2RheSRob3NwaXRhbGl6ZWRgKSBhcmUgaG9zcGl0YWxpemVkLiBgciBwZXJjZW50X0lDVWAlIChgciBJQ1VgKSBvZiB0aG9zZSBob3NwaXRhbGl6ZWQgYXJlIGluIHRoZSBJQ1UuIA0KDQojIyBWaWV3IERhdGENClNvLCBpdCB0dXJucyBvdXQgdG8gYmUgdmVyeSBkaWZmaWN1bHQgdG8gZmluZCBwYXN0IGRhdGEgaW4gdGhlIFN0YXRlIG9mIElvd2Egc2luY2UgdGhleSByZS1wdWJsaXNoIGV2ZXJ5dGhpbmcgZGFpbHkuICBIZXJlIGFyZSB0aGUgbGFzdCA2IGRheXMgb2YgZGF0YSBpZiB5b3UgYXJlIGludGVyZXN0ZWQ6DQpgYGB7cn0NCnRhaWwoY2xlYW4pDQpgYGANCg0KIyBEYXRhIEV4cGxvcmF0aW9uDQoNCiMjIEtub3duIEFjdGl2ZSBDYXNlcw0KVGhpcyBpcyBhIGdyYXBoIG9mIHRoZSBrbm93biBhY3RpdmUgY2FzZXMgaW4gSW93YS4gVGhlc2UgcGVvcGxlIGhhdmUgdGVzdGVkIHBvc2l0aXZlLCBidXQgaGF2ZSBub3QgbW92ZWQgb24gdG8gYSBzdGFnZSB3aGVyZSB0aGV5IGFyZSBub3QgaW5mZWN0aW91cy4gSSBzYXkgaXQgdGhhdCB3YXkgYmVjYXVzZSB3ZSBrbm93IHRoYXQgYSBsb3Qgb2YgcGF0aWVudHMgd2l0aCBtaWxkIGFuZCBtb2RlcmF0ZSBDT1ZJRC0xOSBhcmUgdmVyeSBzaWNrIGV2ZW4gYWZ0ZXIgdGhleSBhcmUgbm8gbG9uZ2VyIGluZmVjdGlvdXMuDQoNCmBgYHtyLCBlY2hvPUZBTFNFfQ0KcGFjdGl2ZSA8LSBxcGxvdChkYXRlLCBTdGlsbC5TaWNrLCBkYXRhID0gY2xlYW5bLSgxOjIzKSxdLCBnZW9tID0gYygicG9pbnQiLCAic21vb3RoIikpICsNCiAgZ2d0aXRsZSgiS25vd24gQWN0aXZlIENPVklELTE5IENhc2VzIGluIElvd2EiKQ0KcG5nKHBhc3RlKGRheSwicGFjdGl2ZS5wbmciKSkNCnBhY3RpdmUNCmRldi5vZmYoKQ0KcGFjdGl2ZQ0KYGBgDQpTaWdoLiBPbiBKdW5lIDMwIElEUEggZGVjaWRlZCB0byBjb3VudCBhbnlvbmUgd2hvIHdhcyBzdGlsbCBub3QgbGlzdGVkIGFzIHJlY292ZXJlZCBhZnRlciAyOCBkYXlzIGFzIHJlY292ZXJlZC4gU28sIGxldCdzIGdvIGJhY2sgaW50byB0aGUgaGlzdG9yaWMgZGF0YSBhbmQgdHJ5IHRvIGFkZCB0aGF0IGV4cGVjdGF0aW9uIHRvIHBhc3QgcmVjb3ZlcmQgZGF0YS4gRm9ydHVuYXRlbHkgaXQgaXMgcG9zc2libGUgdG8gZG93bmxvYWQgdGhlIGRhdGEgZnJvbSB0aGUgd2Vic2l0ZSBodHRwczovL2Nvcm9uYXZpcnVzLmlvd2EuZ292LyNDdXJyZW50U3RhdHVzIA0KDQojIyBQZXJjZW50IFBvc2l0aXZlIEFjdGl2ZSBDYXNlcw0KYGBge3IsZWNobz1GYWxzZX0NCg0KcHBvc2l0aXZlIDwtcXBsb3QoZGF0ZSwgTmV3LlBlcmNlbnQuUG9zaXRpdmUsIGRhdGEgPSBjbGVhblstKDE6NyksXSwgZ2VvbSA9IGMoInBvaW50IiwgInNtb290aCIpKSArIHlsYWIoIkZyYWN0aW9uIFBvc2l0aXZlIikgKw0KZ2d0aXRsZSgiRnJhY3Rpb24gb2YgUG9zaXRpdmUgQ09WSUQtMTkgVGVzdHMgaW4gSW93YSIpDQpwbmcocGFzdGUoZGF5LCJwcG9zaXRpdmUucG5nIikpDQpwcG9zaXRpdmUNCmRldi5vZmYoKQ0KcHBvc2l0aXZlDQoNCnA3cG9zaXRpdmUgPC1xcGxvdChkYXRlLCBXZWVrLlBvc2l0aXZpdHkuUmF0ZSwgZGF0YSA9IGNsZWFuWy0oMToyMCksXSwgZ2VvbSA9IGMoInBvaW50IiwgInNtb290aCIpKSArIHlsYWIoIkZyYWN0aW9uIFBvc2l0aXZlIikgKw0KZ2d0aXRsZSgiNyBkYXkgYXZlcmFnZSBvZiBGcmFjdGlvbiBvZiBQb3NpdGl2ZSBDT1ZJRC0xOSBUZXN0cyBpbiBJb3dhIikNCnBuZyhwYXN0ZShkYXksInA3cG9zaXRpdmUucG5nIikpDQoNCnA3cG9zaXRpdmUNCmRldi5vZmYoKQ0KcDdwb3NpdGl2ZQ0KYGBgDQoNCg0KIyMgQnJlbWVyIENvdW50eQ0KSSBzdGFydGVkIHJlY29yZGluZyBkYWlseSBkYXRhIG9uIEJyZW1lciBjb3VudHkgb24gTWF5IDI5LCAyMDIwLiBUaGVyZSB3aWxsIGJlIHByb2JsZW1zIHdpdGggdGhlIHJlY292ZXJlZCBkYXRhIHNpbmNlIEkgaGF2ZSB5ZXQgdG8gZ2V0IHRhYmxlcyBvZiBkYXRhIGZvciB0aGUgY291bnR5IGFuZCB0aGUgZGVmaW5pdGlvbiBvZiByZWNvdmVyZWQgY2hhbmdlZCBvbiBKdW5lIDMwLiBUaHVzLCB0aGUgZm9sbG93aW5nIGdyYXBoIG9taXRzIHRoYXQgZGF0YS4NCmBgYHtyLCBlY2hvPUZBTFNFfQ0KU3RhdGVfQXZlcmFnZV9BY3RpdmUgPC0gdG9kYXkkU3RpbGwuU2ljay9Jb3dhUG9wKjEwMDAwMA0KQnJlbWVyX1BvcHVsYXRpb24gPC0gY291bnR5W2NvdW50eSRDT1VOVFk9PSJCcmVtZXIiLF1bLDNdDQpCdXRsZXJfUG9wdWxhdGlvbiA8LSBjb3VudHlbY291bnR5JFNUQVRFPT0iSW93YSImY291bnR5JENPVU5UWT09IkJ1dGxlciIsXVssM10NCkJsYWNrSGF3a19Qb3B1bGF0aW9uIDwtIGNvdW50eVtjb3VudHkkU1RBVEU9PSJJb3dhIiZjb3VudHkkQ09VTlRZPT0iQmxhY2sgSGF3ayIsXVssM10NCnBCcmVtZXIgPC1xcGxvdChkYXRlLA0KICAgICAgICAgICAgICAgICMgQnJlbWVyLlNTL0JyZW1lcl9Qb3B1bGF0aW9uKjEwMDAwMCwNCiAgICAgICAgICAgICAgICBCcmVtZXIuU1MsDQogICAgICAgICAgICAgICAgZGF0YSA9IGNsZWFuWy0oMTo3MSksXSwgZ2VvbSA9IGMoInBvaW50IiwgInNtb290aCIpKSArDQogIGdndGl0bGUoDQogICAgIyAiS25vd24gQWN0aXZlIENPVklELTE5IENhc2VzIGluIEJyZW1lciBDb3VudHkgUGVyIDEwMCwwMDAgUGVvcGxlIikNCiAgICAiS25vd24gQWN0aXZlIENPVklELTE5IENhc2VzIGluIEJyZW1lciBDb3VudHkiKQ0KIyArICBnZW9tX2hsaW5lKGFlcyh5aW50ZXJjZXB0PVN0YXRlX0F2ZXJhZ2VfQWN0aXZlKQ0KcEJ1dGxlciA8LXFwbG90KGRhdGUsDQogICAgICAgICAgICAgICAgI0J1dGxlci5TUy9CdXRsZXJfUG9wdWxhdGlvbioxMDAwMDAsDQogICAgICAgICAgICAgICAgQnV0bGVyLlNTLA0KICAgICAgICAgICAgICAgIGRhdGEgPSBjbGVhblstKDE6MTE2KSxdLCBnZW9tID0gYygicG9pbnQiLCAic21vb3RoIikpICsNCiAgZ2d0aXRsZSgiS25vd24gQWN0aXZlIENPVklELTE5IENhc2VzIGluIEJ1dGxlciBDb3VudHkiKQ0KI2dndGl0bGUoIktub3duIEFjdGl2ZSBDT1ZJRC0xOSBDYXNlcyBpbiBCdXRsZXIgQ291bnR5IFBlciAxMDAsMDAwIFBlb3BsZSIpDQojKyAgZ2VvbV9obGluZShhZXMoeWludGVyY2VwdD1TdGF0ZV9BdmVyYWdlX0FjdGl2ZSkNCnBuZyhwYXN0ZShkYXksInBCdXRsZXIucG5nIikpDQpwQnV0bGVyDQpkZXYub2ZmKCkNCnBCdXRsZXINCnBCbGFja0hhd2sgPC1xcGxvdChkYXRlLA0KICAgICAgICAgICAgICBCbGFja0hhd2suU1MsIA0KICAgICAgICAgICAgICAjQmxhY2tIYXdrLlNTL0JsYWNrSGF3a19Qb3B1bGF0aW9uKjEwMDAwMCwNCiAgICAgICAgICAgICAgZGF0YSA9IGNsZWFuWy0oMToxMTYpLF0sIGdlb20gPSBjKCJwb2ludCIsICJzbW9vdGgiKSkgKw0KICBnZ3RpdGxlKCJLbm93biBBY3RpdmUgQ09WSUQtMTkgQ2FzZXMgaW4gQmxhY2sgSGF3ayBDb3VudHkiKQ0KI2dndGl0bGUoIktub3duIEFjdGl2ZSBDT1ZJRC0xOSBDYXNlcyBpbiBCbGFjayBIYXdrIENvdW50eSBQZXIgMTAwLDAwMCBQZW9wbGUiKQ0KIysgIGdlb21faGxpbmUoYWVzKHlpbnRlcmNlcHQ9U3RhdGVfQXZlcmFnZV9BY3RpdmUpDQpwbmcocGFzdGUoZGF5LCJwQmxhY2tIYXdrLnBuZyIpKQ0KcEJsYWNrSGF3aw0KZGV2Lm9mZigpDQpwQmxhY2tIYXdrDQoNCnBuZyhwYXN0ZShkYXksInBCcmVtZXIucG5nIikpDQpwQnJlbWVyDQpkZXYub2ZmKCkNCnBCcmVtZXINCg0KZGF5N3Bvcy5CcmVtZXIgPC0gcm91bmQoDQogIEJyZW1lckRhdGEkRGF5Ny5QZXJjW25yb3coQnJlbWVyRGF0YSldKjEwMCwgZGlnaXRzPTEpDQpgYGANClRoZXJlIGFyZSBgciBjbGVhbiRCcmVtZXIuU1NbbnJvdyhjbGVhbildYCBhY3RpdmUgY2FzZXMgYW5kIGByIGhvc3BfYnlfY291bnR5WyJCcmVtZXIiLF1bWzJdXWAgaG9zcGl0YWxpemVkIGluIEJyZW1lciBDb3VudHkgdG9kYXkuIFRoZSA3IGRheSBwb3NpdGl2aXR5IHJhdGUgaXMgYHIgZGF5N3Bvcy5CcmVtZXJgJS4NCg0KYHIgaG9zcF9ieV9jb3VudHlbYygiQnJlbWVyIiwgIkJ1dGxlciIsICJCbGFjayBIYXdrIiksXVsyXWANCg0KIyMgUG9zaXRpdmUgVGVzdHMNCg0KIyMjIExvZ2lzdGljIE1vZGVsDQpUbyB0cnkgdG8gZml0IGEgbG9naXN0aWMgbW9kZWwgdG8gdGhlIGRhdGEsIHdlIHdhbnQgdG8gZml0IGEgcGFyYWJvbGEgdG8gdGhlIHJhdGUgb2YgY2hhbmdlLCBidXQgdGhlIGlucHV0IHZhcmlhYmxlIGlzIGNhc2VzIG9yIGRlYXRocyBhbmQgbm90IHRpbWUuICBUaGlzIGlzIGJlY2F1c2UgdGhlIGxvZ2lzdGljIG1vZGVsIGNvbWVzIGZyb20gdGhlIGRpZmZlcmVudGlhbCBlcXVhdGlvbiAkXGRpc3BsYXlzdHlsZXtcZnJhY3tkUH17ZHR9PSBrUCgxLVxmcmFje1B9e019KX0kLiAgTm90ZSB0aGF0IHRoaXMgZXF1YXRpb24gYXMgYSBmdW5jdGlvbiBvZiAkUCQgaXMgYSBwYXJhYm9sYSB3aXRoIHplcm9lcyBhdCAkUD0wJCBhbmQgJFA9TSQuDQpgYGB7cn0NCmNsZWFuIDwtIGNsZWFuWy1jKDEsMTApLF0NCndpdGgoY2xlYW4sIHBsb3QocG9zaXRpdmUsIE5ldy5Qb3NpdGl2ZSwgcGNoPTE2LCB4bGFiID0gIlBvc2l0aXZlIENvdW50cyIsIHlsYWIgPSAiUmF0ZSBvZiBDaGFuZ2Ugb2YgUG9zaXRpdmUiLCBjZXgubGFiID0gMS4zLCBjb2wgPSAiYmx1ZSIpKQ0KYGBgDQpOb3csIGl0IGRvZXNuJ3QgcmVhbGx5IGxvb2sgcXVhZHJhdGljLCBidXQgd2UgYXJlIG5vdCBnb2luZyB0byBsZXQgdGhhdCBzdG9wIHVzIGZyb20gbWF0aGVtYXRpY3MuIE5leHQsIHdlIHdpbGwgZml0IGEgcXVhZHJhdGljIG1vZGVsIHRvIHRoZSBkYXRhLg0KYGBge3J9DQpjbGVhbiRQMiA8LSBhcy5udW1lcmljKGNsZWFuJHBvc2l0aXZlKV4yDQpxdWFkcmF0aWMgPC1sbShOZXcuUG9zaXRpdmUgfiBwb3NpdGl2ZSArIFAyLTEsIGRhdGEgPSBjbGVhbikNCnIgPC0gcXVhZHJhdGljJGNvZWZmaWNpZW50c1syXSooLTEpDQpNIDwtIHF1YWRyYXRpYyRjb2VmZmljaWVudHNbMV0vcg0KTXByaW50IDwtIGZvcm1hdChNLCBzY2llbnRpZmljID0gRkFMU0UpDQpwcmVkaWN0ZWRjb3VudHMgPC0gd2l0aChjbGVhbixwcmVkaWN0KHF1YWRyYXRpYyxsaXN0KHBvc2l0aXZlID0gcG9zaXRpdmUsIFAyID0gUDIpKSkNCmBgYA0KTGV0J3MgcGxvdCB0aGUgbW9kZWw6DQpgYGB7cn0NCndpdGgoY2xlYW4sIHBsb3QocG9zaXRpdmUsIE5ldy5Qb3NpdGl2ZSwgcGNoPTE2LCB4bGFiID0gIlBvc2l0aXZlIENvdW50cyIsIHlsYWIgPSAiUmF0ZSBvZiBDaGFuZ2Ugb2YgUG9zaXRpdmUiLCBjZXgubGFiID0gMS4zLCBjb2wgPSAiYmx1ZSIpKQ0Kd2l0aChjbGVhbixsaW5lcyhwb3NpdGl2ZSwgcHJlZGljdGVkY291bnRzLCBjb2wgPSAiZGFya2dyZWVuIiwgbHdkID0gMykpDQpJb3dhUGVyY2VudCA8LSByb3VuZChNL0lvd2FQb3AqMTAwLCBkaWdpdHMgPSAyKQ0KYGBgDQpTbywgd2UgaGF2ZSBhIHF1YWRyYXRpYyBtb2RlbCB0aGF0IGxvb2tzIGxpa2UgJFxmcmFje2RQfXtkdH0kID0gYHIgcXVhZHJhdGljJGNvZWZmaWNpZW50c1sxXWAkUF4yJCArIGByIHF1YWRyYXRpYyRjb2VmZmljaWVudHNbMl1gJFAkID0gYHIgcmAkUCgxLVAvJCBgciBNcHJpbnRgJCkkLiBUaGlzIGlzIGxvb2tpbmcgcHJldHR5IGdvb2QuIEluIHBhcnRpY3VsYXIsIGJlY2F1c2UgJE09JCBgciBNcHJpbnRgLCB3ZSBjYW4gZXN0aW1hdGUgdGhhdCBgciBJb3dhUGVyY2VudGAlIG9mIElvd2EncyBwb3B1bGF0aW9uIHdpbGwgYmVjb21lIGluZmVjdGVkLiAgV2Ugd291bGQgbGlrZSB0byBzZWUgd2hhdCB0aGF0IGxvb2tzIGxpa2UgZm9yIHRoZSBvcmlnaW5hbCBkYXRhLiBXaGVuIFIgcGVyZm9ybXMgbG9naXN0aWMgbW9kZWxpbmcsIGl0IHVzdWFsbHkgaGFzIGJpbm9taWFsIGRhdGEgYW5kIHRodXMgZXhwZWN0cyBudW1iZXJzIHRoYXQgYXJlIGJldHdlZW4gemVybyBhbmQgb25lLiBXZSB3aWxsIHVzZSBvdXIgZXN0aW1hdGUgb2YgJE0kIHRvIGNyZWF0ZSBwb3NpdGl2ZSBjb3VudHMgdGhhdCBhcmUgYSBwZXJjZW50YWdlIG9mICRNJC4gDQpgYGB7ciwgZWNobyA9IEZBTFNFfQ0KbG9naXN0aWNHcm93dGh5IDwtIGZ1bmN0aW9uKGRhdGEsIE0pew0KZGF0YSRiaW5vbWlhbCA8LSBkYXRhJHBvc2l0aXZlL00NCm15bG9naXQgPC0gZ2xtKGJpbm9taWFsIH4gZGF0ZSwgZGF0YSA9IGRhdGEsIGZhbWlseSA9ICJiaW5vbWlhbCIpDQp5cHJlZGljdCA8LSBwcmVkaWN0KG15bG9naXQsIGxpc3QoZGF0ZSA9IGRhdGEkZGF0ZSksIHR5cGUgPSAicmVzcG9uc2UiKSpNDQp9DQpjbGVhbiRiaW5vbWlhbCA8LSBjbGVhbiRwb3NpdGl2ZS9NDQpteWxvZ2l0IDwtIGdsbShiaW5vbWlhbCB+IGRhdGUsIGRhdGEgPSBjbGVhbiwgZmFtaWx5ID0gImJpbm9taWFsIikNCnlwcmVkaWN0IDwtIHByZWRpY3QobXlsb2dpdCwgbGlzdChkYXRlID0gY2xlYW4kZGF0ZSksIHR5cGUgPSAicmVzcG9uc2UiKSpNDQojeXByZWRpY3QgPC0gbG9naXN0aWNHcm93dGh5KGNsZWFuLCBNKQ0KcXBsb3QoZGF0ZSwgcG9zaXRpdmUsIGRhdGEgPSBjbGVhbikgKw0KICAjc3RhdF9zbW9vdGgobWV0aG9kID0gImxtIiwgY29sID0gImdyZWVuIikgKw0KICBnZW9tX2xpbmUoYWVzKHkgPSB5cHJlZGljdCwgY29sID0gIm1vZGVsIiksIHNpemUgPSAxLjI1KSANCmBgYA0KT2theSwgdGhhdCBsb29rcyBxdWl0ZSBnb29kLiBXaGF0IHdpbGwgaXQgcHJlZGljdCBmb3IgdGhlIG5leHQgMjggZGF5cz8NCmBgYHtyLCBlY2hvPUZBTFNFfQ0KbmRhdGUgPC1zZXEoYXMuRGF0ZSgiMjAyMC0wMy0wOSIpLGFzLkRhdGUoZGF5ICsgMTQpLGJ5ID0gMSkNCiNwbGF5IDwtIGNsZWFuICU+JSBmaWx0ZXIocm93X251bWJlcigpID49IChuKCkgLSA3KSkNCnBsYXkgPC0gY2xlYW4NCnlwcmVkaWN0MiA8LSBwcmVkaWN0KG15bG9naXQsIGxpc3QoZGF0ZSA9bmRhdGUpLCB0eXBlID0gInJlc3BvbnNlIikqTQ0KZGYgPC0gZGF0YS5mcmFtZShkYXRlID0gbmRhdGUsIG1vZGVsID0geXByZWRpY3QyKQ0KZGYgPC0gbWVyZ2UoZGYsIHBsYXksIGFsbCA9IFRSVUUpDQpwcmVkaWN0MTQgPC0gZm9ybWF0KHJvdW5kKHlwcmVkaWN0MltsZW5ndGgoeXByZWRpY3QyKV0sIGRpZ2l0cyA9IDApLCBzY2llbnRpZmljID0gRkFMU0UpDQoNCm5kYXRlIDwtc2VxKGFzLkRhdGUoIjIwMjAtMDMtMDkiKSxhcy5EYXRlKGRheSArIDI4KSxieSA9IDEpDQp5cHJlZGljdDMgPC0gcHJlZGljdChteWxvZ2l0LCBsaXN0KGRhdGUgPW5kYXRlKSwgdHlwZSA9ICJyZXNwb25zZSIpKk0NCmRmMiA8LSBkYXRhLmZyYW1lKGRhdGUgPSBuZGF0ZSwgbW9kZWwgPSB5cHJlZGljdDMpDQpkZjIgPC0gbWVyZ2UoZGYyLCBwbGF5LCBhbGwgPSBUUlVFKQ0KcXBsb3QoZGF0ZSwgbW9kZWwsIHlsYWIgPSAiUG9zaXRpdmUgQ2FzZXMiLCBkYXRhID0gZGYyLCBnZW9tID0gInNtb290aCIpICsgDQogICNnZW9tX2xpbmUoc2l6ZSA9IDEuMjUsIGNvbG9yID0gInJlZCIpICsNCiAgZ2VvbV9wb2ludChhZXMoeT1wb3NpdGl2ZSksIHNoYXBlID0gOCkgKyB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAncmlnaHQnKQ0KYGBgDQoNClRoaXMgcHJlZGljdHMgdGhhdCBpbiAxNCBkYXlzLCBJb3dhIHdpbGwgaGF2ZSBgciBwcmVkaWN0MTRgIGluZmVjdGVkIHBlb3BsZS4NCg0KIyMgU0lSIE1vZGVsDQpUaGlzIHNob3VsZCBiZSBtb3JlIGludGVyZXN0aW5nIGFuZCBwcm9iYWJseSB3b24ndCBiZSBkb25lIGZvciBhIHdlZWsuIFRoZSBkaWZmZXJlbnRpYWwgZXF1YXRpb25zIGZvciB0aGUgU0lSIG1vZGVsIGFyZToNCg0KPiAkXGZyYWN7ZFN9e2R0fSA9IC1yXzFTSSQsDQogJFxmcmFje2RSfXtkdH0gPSByXzJJJCwgDQogJFxmcmFje2RJfXtkdH0gPSAtXGZyYWN7ZFN9e2R0fSAtIFxmcmFje2RSfXtkdH0kDQoNClNvLCB3ZSBtYXkgaGF2ZSBlbm91Z2ggZGF0YSB0byBlc3RpbWF0ZSAkcl8xJCBhbmQgJHJfMiQuIFdlIHdvdWxkIGRvIHRoaXMgdXNpbmcgYSBsaW5lYXIgbW9kZWwgb24gdGhlIGNoYW5nZSBvZiByZWNvdmVyZWQgdG8gZXNpdG1hdGUgJHJfMiQgYW5kIHRoZW4gdGhhdCBtb2RlbCBhbmQgdGhlIHJhdGUgb2YgY2hhbmdlIG9mIGluZmVjdGVkcyB0byBlc3RpbWF0ZSAkcl8xJC4gV2UgbWF5IGhhdmUgdG8gdXNlICRNJCBmcm9tIHRoZSBsb2dpc3RpYyBncm93dGggbW9kZWwgdG8gZXN0aW1hdGUgJFMkLg0KDQojIyMgU3RlcCAxOiBFc3RpbWF0ZSAkcl8yJA0KYGBge3J9DQpTSVIgPC0gd2l0aChjbGVhbiwgZGF0YS5mcmFtZSgNCiAgICBkUyA9ICgtMSkqZGlmZihwb3NpdGl2ZSksDQogICAgZFIgPSBkaWZmKFJlY292ZXJlZCksDQogICAgZEkgPSBkaWZmKFN0aWxsLlNpY2spLA0KICAgIGREID0gZGlmZihkZWF0aHMpDQopKQ0KU0lSIDwtIFNJUiAlPiUgbXV0YXRlKA0KICAgIFIgPSBjbGVhbiRSZWNvdmVyZWRbLTFdLA0KICAgIEkgPSBjbGVhbiRTdGlsbC5TaWNrWy0xXSwNCiAgICBkYXkgPSBjbGVhbiRkYXRlWy0xXSwNCiAgICBTID0gTSAtIGNsZWFuJHBvc2l0aXZlWy0xXQ0KICAgICkNClNJUiRkYXkgPSBhcy5QT1NJWGN0KFNJUiRkYXkpDQpTSVIgPC0gU0lSW2NvbXBsZXRlLmNhc2VzKFNJUiksXQ0KYGBgDQpMZXQncyBmaXJzdCBqdXN0IGdyYXBoIG91ciBkYXRhDQpgYGB7cn0NCnFwbG90KGRheSwgZGF0YSA9IFNJUikgKyANCiAgICBzdGF0X3Ntb290aChhZXMoIHkgPSBTKSxtZXRob2QgPSAibG9lc3MiKSArIA0KICAgIHN0YXRfc21vb3RoKCBhZXMoIHkgPSBJKSwgY29sb3IgPSAicmVkIiwgbWV0aG9kID0gImxvZXNzIikgKw0KICAgIHN0YXRfc21vb3RoKCBhZXMoIHkgPSBSKSwgY29sb3IgPSAiZ3JlZW4iLCBtZXRob2QgPSAibG9lc3MiKSArDQogICAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gInJpZ2h0IikNCmBgYA0KKE5vdGUgNS8zMC8yMDIwKSBBcyBvZiBhYm91dCBNYXJjaCAxNSB0aGlzIG5vIGxvbmdlciBsb29rcyBsaWtlIHRoZSBTSVIgbW9kZWwgdGhhdCB5b3Ugd291bGQgZXhwZWN0LiBXZSBoYXZlIHRoaXMgdW5leHBlY3RlZCBsaW5lYXIgZ3Jvd3RoIGluICRSJCB3aGVyZSB3ZSB3b3VsZCBleHBlY3QgdGhpbmdzIHRvIGJlIG1vcmUgY29uY2F2ZSBkb3duIGF0IHRoaXMgcG9pbnQuIE5vdCBnb29kLg0KDQpOZXh0LCBsZXQncyBzZWUgYWJvdXQgY29lZmZpY2llbnRzOg0KYGBge3J9DQpkUm1vZGVsIDwtIGxtKGRSIH4gMCtJLCBkYXRhID0gU0lSKQ0KcjIgPC0gZFJtb2RlbCRjb2VmZmljaWVudHNbMV0NCmRJbW9kZWwgPC0gbG0gKGRTIH4gMCArIFMqSSwgZGF0YSA9IFNJUikNCnIxIDwtIGRJbW9kZWwkY29lZmZpY2llbnRzWzFdDQpgYGANCg0KTm93IHdlIHBsdWcgdGhpcyBpbnRvIHRoZSBERSBzb2x2ZXIuDQpgYGB7cn0NCnJlcXVpcmUoZGVTb2x2ZSkNCnN0YXRlIDwtIGMoUyA9IGFzLm51bWVyaWMoMS1jbGVhbiRwb3NpdGl2ZVsyNV0vTSksIA0KICAgICAgICAgICBJID0gYXMubnVtZXJpYyhjbGVhbiRTdGlsbC5TaWNrWzI1XS9NKSwgDQogICAgICAgICAgIFIgPSBhcy5udW1lcmljKGNsZWFuJFJlY292ZXJlZFsyNV0vTSkpDQp0aW1lcyA8LSBzZXEoMCwgbnJvdyhjbGVhbiktMjQsIGJ5ID0gMSkNCnBhcmFtZXRlcnMgPC0gYyhyMT1hcy5udW1lcmljKHIxKk0pLA0KICAgICAgICAgICAgICAgIHIyPWFzLm51bWVyaWMocjIpKQ0KDQojIFIgZnVuY3Rpb24gdG8gY2FsY3VsYXRlIHRoZSB2YWx1ZSBvZiB0aGUgZGVyaXZhdGl2ZXMgYXQgZWFjaCB0aW1lIHZhbHVlDQogICAgIyBVc2UgdGhlIG5hbWVzIG9mIHRoZSB2YXJpYWJsZXMgYXMgZGVmaW5lZCBpbiB0aGUgdmVjdG9ycyBhYm92ZQ0KU0lSIDwtIGZ1bmN0aW9uKHRpbWUsIHN0YXRlLCBwYXJhbWV0ZXJzKXsNCiAgICAgIHdpdGgoYXMubGlzdChjKHN0YXRlLCBwYXJhbWV0ZXJzKSksIHsNCiAgICAgICAgZFMgPSByMSpTKkkNCiAgICAgICAgZFIgPSByMipJDQogICAgICAgIGRJID0gLXIxKlMqSSAtcjIqSQ0KICAgICAgICByZXR1cm4obGlzdChjKGRTLCBkSSwgZFIpKSkNCiAgICAgIH0pDQp9DQoNCiMjIEludGVncmF0aW9uIHdpdGggJ29kZScNCm91dCA8LSBvZGUoeSA9IHN0YXRlLCB0aW1lcyA9IHRpbWVzLCBmdW5jID0gU0lSLCBwYXJtcyA9IHBhcmFtZXRlcnMsIG1ldGhvZCA9IHJrNCkNCiAgICANCiAgICAjIyBQbG90aW5nDQogICAgb3V0LmRmID0gYXMuZGF0YS5mcmFtZShvdXQpICMgcmVxdWlyZWQgYnkgZ2dwbG90OiBkYXRhIG9iamVjdCBtdXN0IGJlIGEgZGF0YSBmcmFtZQ0KICAgIHJlcXVpcmUocmVzaGFwZTIpDQogICAgb3V0Lm0gPSBtZWx0KG91dC5kZiwgaWQudmFycz0ndGltZScpICMgdGhpcyBtYWtlcyBwbG90dGluZyBlYXNpZXIgYnkgcHV0aW5nIGFsbCB2YXJpYWJsZXMgaW4gYSBzaW5nbGUgY29sdW1uDQogICAgDQogICAgcCA8LSBnZ3Bsb3Qob3V0Lm0sIGFlcyh0aW1lLCB2YWx1ZSwgY29sb3IgPSB2YXJpYWJsZSkpICsgZ2VvbV9wb2ludCgpDQogICAgI3ByaW50KHApDQpgYGANCg0KIyMjIEV4cG9uZW50aWFsIE1vZGVsDQpSdW4gYSBsaW5lYXIgbW9kZWwgb24gdGhlIGxvZ2FyaXRobSBvZiB0aGUgcG9zaXRpdmUgY2FzZXMuDQpgYGB7ciBsb2cgbW9kZWwsIGVycm9yPUZBTFNFfQ0KcXBsb3QoZGF0ZSwgbG9nKHBvc2l0aXZlKSwgZGF0YSA9Y2xlYW4pICsgZ2VvbV9wb2ludCgpICsgZ2VvbV9zbW9vdGgoKSsNCiAgc3RhdF9zbW9vdGgobWV0aG9kID0gImxtIiwgY29sID0gInJlZCIpIA0KYGBgDQoNCmBgYHtyLCBlY2hvID0gRkFMU0V9DQptb2RlbDAgPC0gbG0obG9nKHBvc2l0aXZlKX5kYXRlLCBkYXRhPWNsZWFuKQ0KI21vZGVsMCRjb2VmZmljaWVudHNbMl0NCnBvc2l0aXZlX2RvdWJsaW5nX3RpbWUgPC0gbG9nKDIpL21vZGVsMCRjb2VmZmljaWVudHNbMl0NCiNwb3NpdGl2ZV9kb3VibGluZ190aW1lDQpgYGANCkZvciB0aGUgbW9kZWwgJHBvc2l0aXZlID0gZV57ayBkYXRlfSQsICRrPSQgYHIgbW9kZWwwJGNvZWZmaWNpZW50c1syXWAuIA0KRXN0aW1hdGVkIGRvdWJsaW5nIHRpbWUgZm9yIHBvc2l0aXZlIGNhc2VzIGlzIGByIHBvc2l0aXZlX2RvdWJsaW5nX3RpbWVgIGRheXMuICBIZXJlIGlzIHdoYXQgdGhhdCBsb29rcyBsaWtlIG9uIHRoZSBvcmlnaW5hbCBkYXRhLg0KYGBge3IsIGVjaG8gPSBGQUxTRX0NCnggPSBhcy5udW1lcmljKGNsZWFuJGRhdGUpDQp5ID0gZXhwKG1vZGVsMCRjb2VmZmljaWVudHNbMV0rIG1vZGVsMCRjb2VmZmljaWVudHNbMl0gKngpDQpBID0gZGF0YS5mcmFtZShkYXRlID0gY2xlYW4kZGF0ZSwgcG9zaXRpdmUgPSBjbGVhbiRwb3NpdGl2ZSwgeSA9IHkpDQoNCmdncGxvdChBLCBhZXMoZGF0ZSwgeSA9IHZhbHVlLCBjb2xvciA9IHZhcmlhYmxlKSkgKyANCiAgICBnZW9tX3BvaW50KGFlcyh5ID0gcG9zaXRpdmUsIGNvbCA9ICJwb3NpdGl2ZSIpKSArICAgICBnZW9tX2xpbmUoYWVzKHkgPSB5LCBjb2wgPSAibW9kZWwiKSkgDQoNCmBgYA0KDQojIyMgTW9kaWZpZWQgRXhwb25lbnRpYWwgTW9kZWwNCkJ5IG5vdyB0aGVyZSBpcyBzdHJvbmcgZXZpZGVuY2UgdGhhdCB0aGUgY3VydmUgaXMgZmxhdHRlbmluZy4gV2UgY2FuIGNyZWF0ZSBhIG5ldyBsaW5lYXIgbW9kZWwgdGhhdCB1c2VzIHRoZSBtb3JlIHJlY2VudCBkYXRhIHRvIGltcHJvdmUgb3VyIG1vZGVsLiBMZXQncyBsb29rIHRvIHNlZSB3aGF0IGhhcHBlbnMgaWYgd2Ugb25seSB1c2UgZGF0YSBmcm9tIGxhdGVyIHdoZW4gd2Ugd2VyZSBkb2luZyBtb3JlIHRlc3RpbmcuDQpgYGB7ciwgZWNobyA9IEZBTFNFfQ0KbGF0ZWRhdGEgPC0gY2xlYW5bLSgxOjEwKSxdDQptb2RlbDQgPC0gbG0obG9nKHBvc2l0aXZlKX5kYXRlLCBkYXRhPWxhdGVkYXRhKQ0KcG9zaXRpdmVfZG91YmxpbmdfdGltZTIgPC0gbG9nKDIpL21vZGVsNCRjb2VmZmljaWVudHNbMl0NCnFwbG90KGRhdGUsIGxvZyhwb3NpdGl2ZSksIGRhdGEgPWxhdGVkYXRhKSArIGdlb21fcG9pbnQoKSArIGdlb21fc21vb3RoKCkrDQogIHN0YXRfc21vb3RoKG1ldGhvZCA9ICJsbSIsIGNvbCA9ICJwdXJwbGUiKSANCmBgYA0KRm9yIHRoZSBtb2RlbCAkcG9zaXRpdmUgPSBlXntrIGRhdGV9JCwgJGs9JCBgciBtb2RlbDQkY29lZmZpY2llbnRzWzJdYC4gDQpFc3RpbWF0ZWQgZG91YmxpbmcgdGltZSBmb3IgcG9zaXRpdmUgY2FzZXMgaXMgYHIgcG9zaXRpdmVfZG91YmxpbmdfdGltZTJgIGRheXMuICBIZXJlIGlzIHdoYXQgdGhhdCBsb29rcyBsaWtlIG9uIHRoZSBvcmlnaW5hbCBkYXRhLg0KYGBge3IsIGVjaG8gPSBGQUxTRX0NCnggPSBhcy5udW1lcmljKGxhdGVkYXRhJGRhdGUpDQp5ID0gZXhwKG1vZGVsNCRjb2VmZmljaWVudHNbMV0rIG1vZGVsNCRjb2VmZmljaWVudHNbMl0gKngpDQpBID0gZGF0YS5mcmFtZShkYXRlID0gbGF0ZWRhdGEkZGF0ZSwgcG9zaXRpdmUgPSBsYXRlZGF0YSRwb3NpdGl2ZSwgeSA9IHkpDQpnZ3Bsb3QoQSwgYWVzKGRhdGUsIHkgPSB2YWx1ZSwgY29sb3IgPSB2YXJpYWJsZSkpICsgDQogICAgZ2VvbV9wb2ludChhZXMoeSA9IHBvc2l0aXZlLCBjb2wgPSAicG9zaXRpdmUiKSkgKyAgICAgZ2VvbV9saW5lKGFlcyh5ID0geSwgY29sID0gIm1vZGVsIikpIA0KYGBgDQoNCiMjIERlYXRocw0KDQoNCiMjIyBFeHBvbmVudGlhbCBNb2RlbA0KV2Ugd2lsbCBzdGFydCB0aGUgZGF0YSB3aGVuIHdlIGhhdmUgbm9uLXplcm8gZGVhdGhzLg0KYGBge3IsIGVjaG8gPSBGQUxTRX0NCnplcm9kZWF0aHMgPC0gY2RlYXRocyRkZWF0aHMgPT0gMA0KY2RlYXRocyA8LSBjZGVhdGhzWyF6ZXJvZGVhdGhzLF0NCmBgYA0KDQpgYGB7ciwgZWNobyA9IEZBTFNFfQ0KcXBsb3QoZGF0ZSwgbG9nKGRlYXRocyksIGRhdGEgPWNkZWF0aHMpICsgZ2VvbV9wb2ludCgpICsgZ2VvbV9zbW9vdGgoKSsNCiAgc3RhdF9zbW9vdGgobWV0aG9kID0gImxtIiwgY29sID0gInJlZCIpDQpgYGANCg0KYGBge3IsIGVjaG8gPSBGQUxTRX0NCm1vZGVsIDwtIGxtKGxvZyhkZWF0aHMpfmRhdGUsIGRhdGE9Y2RlYXRocykNCiNtb2RlbCRjb2VmZmljaWVudHNbMl0NCmRlYXRoX2RvdWJsaW5nX3RpbWUgPC0gbG9nKDIpL21vZGVsJGNvZWZmaWNpZW50c1syXQ0KI2RlYXRoX2RvdWJsaW5nX3RpbWUNCmBgYA0KRm9yIHRoZSBtb2RlbCAkZGVhdGhzID0gZV57ayBkYXRlfSQsICRrPSQgYHIgbW9kZWwkY29lZmZpY2llbnRzWzJdYC4gDQpFc3RpbWF0ZWQgdGltZSBmb3IgZGVhdGhzIHRvIGRvdWJsZSBpcyBgciBkZWF0aF9kb3VibGluZ190aW1lYCBkYXlzLg0KDQojIyMgTGF0ZXIgRGF0YQ0KQXMgYWJvdmUsIGxldCdzIGxvb2sgYXQgdGhlIHNhbWUgbW9kZWxzLCBidXQgb25seSBhZnRlciB3ZSBnb3Qgc2VyaW91cyBhYm91dCB0ZXN0aW5nLg0KDQpgYGB7ciAsIGVjaG8gPSBGQUxTRX0NCmxhdGVkYXRhMiA8LSBsYXRlZGF0YVstKDE6OCksXQ0KcXBsb3QoZGF0ZSwgbG9nKGRlYXRocyksIGRhdGEgPWxhdGVkYXRhMikgKyBnZW9tX3BvaW50KCkgKyBnZW9tX3Ntb290aCgpKw0KICBzdGF0X3Ntb290aChtZXRob2QgPSAibG0iLCBjb2wgPSAicmVkIikNCmBgYA0KDQpgYGB7ciwgZWNobyA9IEZBTFNFfQ0KbW9kZWw1IDwtIGxtKGxvZyhkZWF0aHMpfmRhdGUsIGRhdGE9bGF0ZWRhdGEyKQ0KI21vZGVsJGNvZWZmaWNpZW50c1syXQ0KZGVhdGhfZG91YmxpbmdfdGltZTIgPC0gbG9nKDIpL21vZGVsNSRjb2VmZmljaWVudHNbMl0NCiNkZWF0aF9kb3VibGluZ190aW1lDQpgYGANCkZvciB0aGUgbW9kZWwgJGRlYXRocyA9IGVee2sgZGF0ZX0kLCAkaz0kIGByIG1vZGVsNSRjb2VmZmljaWVudHNbMl1gLiANCkVzdGltYXRlZCB0aW1lIGZvciBkZWF0aHMgdG8gZG91YmxlIGlzIGByIGRlYXRoX2RvdWJsaW5nX3RpbWUyYCBkYXlzLg0KDQpgYGB7ciwgZWNobyA9IEZBTFNFfQ0KeCA9IGFzLm51bWVyaWMobGF0ZWRhdGEyJGRhdGUpDQp5ID0gZXhwKG1vZGVsNSRjb2VmZmljaWVudHNbMV0rIG1vZGVsNSRjb2VmZmljaWVudHNbMl0gKngpDQpCID0gZGF0YS5mcmFtZShkYXRlID0gbGF0ZWRhdGEyJGRhdGUsIGRlYXRocyA9IGxhdGVkYXRhMiRkZWF0aHMsIHkgPSB5KQ0KZ2dwbG90KEIsIGFlcyhkYXRlLCB5ID0gdmFsdWUsIGNvbG9yID0gdmFyaWFibGUpKSArIA0KICAgIGdlb21fcG9pbnQoYWVzKHkgPSBkZWF0aHMsIGNvbCA9ICJkZWF0aHMiKSkgKyAgICAgZ2VvbV9saW5lKGFlcyh5ID0geSwgY29sID0gIm1vZGVsIikpIA0KYGBgDQoNCiMjIE5ldyBQb3NpdGl2ZXMNCg0KQXQgdGhlIGJlZ2lubmluZywgd2Ugd2VyZSBtb2RlbGluZyB0aGUgbmV3IHBvc2l0aXZlIGRhdGEgYXMgYW4gZXhwb25lbnRpYWwgY3VydmUuIEFzIG9mIGFib3V0IHRoZSBtaWRkbGUgb2YgTWF5IHdlIGNoYW5nZWQgdG8gdXNlIHRoZSBsb2dpc3RpYyBncm93dGggY3VydmUgZnJvbSB0aGUgTG9naXN0aWMgTW9kZWwgdG8gcHJlZGljdCBuZXcgcG9zaXRpdmUgdGVzdHMuDQpgYGB7ciwgZWNobyA9IEZBTFNFfQ0KbnBQcmVkaWN0IDwtIGRpZmYoeXByZWRpY3QyLDEsMSkNCnRlbXBsZW5ndGggPC0gbGVuZ3RoKGNsZWFuJE5ldy5Qb3NpdGl2ZSkNCm5wUHJlZGljdCA8LSBucFByZWRpY3RbMTp0ZW1wbGVuZ3RoXQ0KcXBsb3QoZGF0ZSwgTmV3LlBvc2l0aXZlLCBkYXRhID0gY2xlYW4sIGdlb20gPSBjKCJwb2ludCIsICJzbW9vdGgiKSkgKw0KICAjc3RhdF9zbW9vdGgobWV0aG9kID0gImxtIiwgY29sID0gImdyZWVuIikgKw0KICBnZW9tX2xpbmUoYWVzKHkgPSBucFByZWRpY3QsIGNvbCA9ICJtb2RlbCIpKSArIA0KICBnZW9tX2xpbmUoYWVzKHk9bnBfN2RheSwgY29sID0gIjcgZGF5IGF2ZXJhZ2UiKSwgc2l6ZSA9IDEuMjUpDQogIA0KYGBgDQoNCkFzIG9mIGFib3V0IHRoZSBtaWRkbGUgb2YgTWF5LCBpdCBiZWNvbWVzIGNsZWFyIHRoYXQgdGhlIG5ldyBwb3NpdGl2ZSBkYXRhIGlzIG5vdCBleHBvbmVudGlhbC4gV2hpY2ggaXMgcmVhbGx5IGdvb2QgbmV3cy4gVGhpcyBpcyB3aGVuIHRoaXMgbW9kZWwgZ2V0cyBkb3duZ3JhZGVkIHRvIHRoZSBBbHRlcm5hdGl2ZSBNb2RlbGluZyBzZWN0aW9uLg0KDQojIEFjY3VyYWN5DQpBcyB3aXRoIGFueSB0ZXN0LCB0aGVyZSB3aWxsIGJlIGZhbHNlIHBvc2l0aXZlcyAocGVvcGxlIHdobyB0ZXN0IHBvc2l0aXZlLCBidXQgYXJlbid0IGluZmVjdGVkKSBhbmQgZmFsc2UgbmVnYXRpdmVzIChwZW9wbGUgd2hvIHRlc3QgbmVnYXRpdmUsIGJ1dCBhcmUgaW5mZWN0ZWQpLiBPbiBNYXkgMSwgaXQgd2FzIHJlcG9ydGVkIGJ5IHRoZSBHb3Zlcm5vcidzIG9mZmljZTogDQoNCiJHb3Zlcm5vciBSZXlub2xkcyBzYXlzIHRoZSBTdGF0ZSBIeWdpZW5pYyBMYWIgaGFzIHZhbGlkYXRlZCB0aGUgbWFjaGluZXMgdXNlZCBhcyBwYXJ0IG9mIHRoZSBUZXN0IElvd2EgcHJvZ3JhbS4gIOKAnEnigJltIHBsZWFzZWQgdG8gYW5ub3VuY2UgdGhhdCB0aGUgU3RhdGUgSHlnaWVuaWMgTGFiIGNvbXBsZXRlZCB0aGUgVGVzdCBJb3dhIHZhbGlkYXRpb24gcHJvY2VzcyB5ZXN0ZXJkYXksIGFjaGlldmluZyBoaWdoIHJhdGluZ3Mgb2YgOTUlIGFjY3VyYWN5IGZvciBkZXRlcm1pbmluZyBwb3NpdGl2ZXMgYW5kIDk5LjclIGFjY3VyYWN5IGZvciBkZXRlcm1pbmluZyBuZWdhdGl2ZXMu4oCdIg0KDQpUaGlzIGlzIGEgYml0IGhhcmQgdG8gaW50ZXJwcmV0LCBidXQgSSBhbSBnb2luZyB0byBhc3N1bWUgdGhhdCBpdCBtZWFucyB0aGF0IHRoZSBmYWxzZSBwb3NpdGl2ZSByYXRlIGlzIDAuMyUgYW5kIHRoZSBmYWxzZSBuZWdhdGl2ZSByYXRlIGlzIDUlLiBUaGlzIGFncmVlcyB3aXRoIGVhcmxpZXIgcmVwb3J0cyBvZiB0ZXN0aW5nIHdoZXJlIHRoZSB0ZXN0cyB1c2VkIHRvIHNob3cgdGhhdCB5b3UgYXJlIGN1cnJlbnRseSBpbmZlY3RlZCBoYXZlIHByZXR0eSBsb3cgZmFsc2UgcG9zaXRpdmUgcmF0ZXMgYW5kIGhpZ2hlciBmYWxzZSBuZWdhdGl2ZSByYXRlcyBiZWNhdXNlIGl0IGNvbWVzIGJhY2sgcG9zaXRpdmUgaWYgaXQgZmluZHMgdGhlIHZpcnVzLiBBIGZhbHNlIG5lZ2F0aXZlIHdvdWxkIGJlIHRoYXQgeW91IGhhdmUgdGhlIHZpcnVzLCBidXQgdGhlIHRlc3QgY2FuJ3QgZmluZCBpdCB3aGljaCBpc24ndCBvdXQgb2YgdGhlIHJhbmdlIG9mIHBvc3NpYmlsaXR5LiAgU28sIGxldCdzIGdvIGJhY2sgdG8gb3VyIGRhdGEgYW5kIGNhbGN1bGF0ZSB0aGUgbnVtYmVyczogDQpgYGB7cn0NCnRlbXAgPC0gMS8oLjk5NyouOTUgLSAoMS0uOTk1KSooMS0uOTUpKQ0KYWNjdXJhY3kgPC0gY2xlYW4gJT4lIA0KICAgIG11dGF0ZSgNCiAgICB0cCA9IC45NSpwb3NpdGl2ZS90ZW1wLCANCiAgICBmcCA9ICgxLS45OTMpL3RlbXAqcG9zaXRpdmUsIA0KICAgIHRuID0gMC45OTMvdGVtcCpuZWdhdGl2ZSwgDQogICAgZm4gPSAoMS0uOTUpL3RlbXAqbmVnYXRpdmUpICU+JQ0KICAgIG11dGF0ZSggcG9zID0gcm91bmQodHArZm4sIGRpZ2l0cyA9IDApLA0KICAgICAgICAgICAgbmVnID0gcm91bmQodG4rZnAsIGRpZ2l0cyA9IDApKQ0KbGFzdHJvdyA9IGxlbmd0aChhY2N1cmFjeSkNCmBgYA0KVG9kYXksIHRoZSBzdGF0ZSByZXBvcnRlZCBgciBhY2N1cmFjeVtsYXN0cm93LCAzXWAgdG90YWwgcG9zaXRpdmUgYW5kIGByIGFjY3VyYWN5W2xhc3Ryb3csIDldYCB0b3RhbCBuZWdhdGl2ZS4gRHVlIHRvIHRlc3QgaW5hY2N1cmFjeSwgdGhlc2UgbnVtYmVycyBjb3VsZCBiZSBhcyBtdWNoIGFzIGByIGZvcm1hdChhY2N1cmFjeVtsYXN0cm93LCAyNl0sIHNjaWVudGlmaWMgPSBGKWAgcG9zaXRpdmUgYW5kIGByIGZvcm1hdChhY2N1cmFjeVtsYXN0cm93LCAyN10sIHNjaWVudGlmaWMgPSBGKWAgbmVnYXRpdmUuDQoNCiMgU3RvcmUgUHJlZGljdGlvbnMNClRoaXMgc2VjdGlvbiBzdG9yZXMgcHJlZGljdGlvbnMuDQpgYGB7ciwgZWNobz1GQUxTRX0NCnByZWRpY3Rpb25zIDwtIGFzLmRhdGEuZnJhbWUocmVhZC5jc3YoIlByZWRpY3Rpb25zLmNzdiIpKQ0KcHJlZGljdGlvbnMgPC0gcHJlZGljdGlvbnNbLC0xXQ0KcHJlZGljdGlvbnMkZGF0ZSA8LSBhcy5EYXRlKHByZWRpY3Rpb25zJGRhdGUpDQpsaXN0IDwtIGRhdGEuZnJhbWUoZGF0ZSA9IGRheSwgDQogICAgICAgICAgUG9zaXRpdmVEb3VibGluZyA9IHBvc2l0aXZlX2RvdWJsaW5nX3RpbWUsIA0KICAgICAgICAgIGxhdGVQb3NpdGl2ZURvdWJsaW5nID0gcG9zaXRpdmVfZG91YmxpbmdfdGltZTIsIA0KICAgICAgICAgIERlYXRoRG91YmxpbmcgPSBkZWF0aF9kb3VibGluZ190aW1lLCANCiAgICAgICAgICBMYXRlRGVhdGhEb3VibGluZyA9IGRlYXRoX2RvdWJsaW5nX3RpbWUyLCANCiAgICAgICAgICBOZXdQb3NpdGl2ZURvdWJsaW5nID0gbnBfZG91YmxpbmdfdGltZSwNCiAgICAgICAgICBMb2dpc3RpY1IgPSByLCANCiAgICAgICAgICBMb2dpc3RpY00gPSBNLCANCiAgICAgICAgICBGb3VydGVlbkRheVByZWRpY3Rpb24gPSBwcmVkaWN0MTQNCiAgICAgICAgICApDQpsaXN0JGRhdGUgPC0gYXMuRGF0ZShsaXN0JGRhdGUpDQpyb3duYW1lcyhsaXN0KSA8LSBjKCkNCmlmKGFzLmNoYXJhY3RlcihwcmVkaWN0aW9uc1tucm93KHByZWRpY3Rpb25zKSwxXSkhPSBkYXkpew0KICBwcmVkaWN0aW9ucyA9IHJiaW5kKHByZWRpY3Rpb25zLCBsaXN0KQ0KfQ0KaG9zcGl0YWwgPC0gYXMuZGF0YS5mcmFtZShyZWFkLmNzdigiQ291bnR5SG9zcGl0aWxpemF0aW9ucy5jc3YiKSkNCmhvc3BpdGFsIDwtIGhvc3BpdGFsWywtMV0NCmhfY291bnR5IDwtICB0KGhvc3BfYnlfY291bnR5WywyXSkNCg0KY29sbmFtZXMoaF9jb3VudHkpIDwtICBob3NwX2J5X2NvdW50eVssMV0NCmhfY291bnR5IDwtIGNiaW5kKGRhdGUgPSBjKGFzLmNoYXJhY3RlcihkYXkpKSwgaF9jb3VudHkpDQpjb2xuYW1lcyhoX2NvdW50eSkgPC0gY29sbmFtZXMoaG9zcGl0YWwpDQpyb3duYW1lcyhoX2NvdW50eSkgPC0gYXMuY2hhcmFjdGVyKGRheSkNCmlmKGFzLmNoYXJhY3Rlcihob3NwaXRhbFtucm93KGhvc3BpdGFsKSwxXSkhPSBkYXkpeyBob3NwaXRhbCA8LSByYmluZChob3NwaXRhbCwgaF9jb3VudHkpfQ0KDQp3cml0ZS5jc3YoaG9zcGl0YWwsICJDb3VudHlIb3NwaXRpbGl6YXRpb25zLmNzdiIpDQp3cml0ZS5jc3YocHJlZGljdGlvbnMsICJQcmVkaWN0aW9ucy5jc3YiKQ0Kd3JpdGUuY3N2KGNsZWFuLCAiQ2xlYW5EYXRhLmNzdiIpDQpgYGANCg0KDQojIyBBbHRlcm5hdGl2ZSBNb2RlbGluZw0KVGhpcyBkaWRuJ3QgdHVybiBvdXQgd2VsbCwgYnV0IGl0IGlzIHN0aWxsIGhlcmUgZm9yIGhpc3RvcmljYWwgcGVyc3BlY3RpdmU6DQoNCiMjIyBQb3NpdGl2ZXMgTGluZWFyIE1vZGVsDQoNCkZpcnN0IHJ1biBhIGxpbmVhciBtb2RlbCBvbiBwb3NpdGl2ZSB0ZXN0IHJlc3VsdHMuDQpgYGB7ciwgZXJyb3I9RkFMU0V9DQpxcGxvdChkYXRlLCBwb3NpdGl2ZSwgZGF0YSA9Y2xlYW4pICsgZ2VvbV9wb2ludCgpICsgZ2VvbV9zbW9vdGgoKSsNCiAgc3RhdF9zbW9vdGgobWV0aG9kID0gImxtIiwgY29sID0gInJlZCIpDQpgYGANCg0KIyMjIERlYXRocyBMaW5lYXIgTW9kZWwNCg0KYGBge3IgbGluZWFyIG1vZGVsfQ0KcXBsb3QoZGF0ZSwgZGVhdGhzLCBkYXRhID1jZGVhdGhzLCBybS5uYT1UUlVFKSArIGdlb21fcG9pbnQoKSArIGdlb21fc21vb3RoKCkrDQogIHN0YXRfc21vb3RoKG1ldGhvZCA9ICJsbSIsIGNvbCA9ICJyZWQiKQ0KbW9kZWwgPC0gbG0oZGVhdGhzfmRhdGUsIGRhdGE9Y2RlYXRocykNCiNtb2RlbCRjb2VmZmljaWVudHMNCmBgYA0KDQojIyBOZXcgUG9zaXRpdmVzDQpgYGB7ciwgZWNobyA9IEZBTFNFfQ0KbW9kZWw0IDwtIGxtKGxvZyhOZXcuUG9zaXRpdmUpIH4gZGF0ZSwgZGF0YSA9IGNsZWFuKQ0KcHJlZCA8LSBwcmVkaWN0KG1vZGVsNCwgbmV3ZGF0YSA9IGRhdGEuZnJhbWUoZGF0ZSA9Y2xlYW4kZGF0ZSkpDQpucF9kb3VibGluZ190aW1lIDwtIGxvZygyKS9tb2RlbDQkY29lZmZpY2llbnRzWzJdDQpxcGxvdChkYXRlLCBOZXcuUG9zaXRpdmUsIGRhdGEgPSBjbGVhbiwgZ2VvbSA9IGMoInBvaW50IiwgInNtb290aCIpKSArDQogICNzdGF0X3Ntb290aChtZXRob2QgPSAibG0iLCBjb2wgPSAiZ3JlZW4iKSArDQogIGdlb21fbGluZShhZXMoeSA9IGV4cChwcmVkKSwgY29sID0gIm1vZGVsIikpICsgDQogIGdlb21fbGluZShhZXMoeT1ucF83ZGF5LCBjb2wgPSAiNyBkYXkgYXZlcmFnZSIpLCBzaXplID0gMS4yNSkNCiAgDQpgYGANCg0KQXMgb2YgYWJvdXQgdGhlIG1pZGRsZSBvZiBNYXksIGl0IGJlY29tZXMgY2xlYXIgdGhhdCB0aGUgbmV3IHBvc2l0aXZlIGRhdGEgaXMgbm90IGV4cG9uZW50aWFsLiBXaGljaCBpcyByZWFsbHkgZ29vZCBuZXdzLiBUaGlzIGlzIHdoZW4gdGhpcyBtb2RlbCBnZXRzIGRvd25ncmFkZWQgdG8gdGhlIEFsdGVybmF0aXZlIE1vZGVsaW5nIHNlY3Rpb24uDQpGb3IgdGhlIG1vZGVsICRuZXcgcG9zaXRpdmVzID0gZV57ayBkYXRlfSQsICRrPSQgYHIgbW9kZWw0JGNvZWZmaWNpZW50c1syXWAuIA0KRXN0aW1hdGVkIHRpbWUgZm9yIG5ldyBwb3NpdGl2ZXMgdG8gZG91YmxlIGlzIGByIG5wX2RvdWJsaW5nX3RpbWVgIGRheXMuDQoNCg==