1 SIR dynamics with varying parameters

In the first week, you gained first experience with coding simple models in R using the deSolve package. Last week, you went into further details about the drivers of an epidemic and the dynamics of the SIR model. This week, we are bringing this together to think more deeply about the roles of \(\beta\) and \(\gamma\).

1.0.1 Question: Imagine a disease where every person infects 1 person on average, every 2 days, and is infectious for 4 days. What are the values for \(\beta\) and \(\gamma\)?

So far, when looking at the dynamics of an epidemic, we have always plotted the number of people in each compartment. Sometimes however it is more informative to look at the proportion of the population in each compartment rather than the actual number, particularly if the population size changes over time. Although we are modelling an epidemic in a closed population with constant population size in this etivity, it is a good opportunity to practice plotting the prevalence as a proportion of the total population who are in the \(S\), \(I\) and \(R\) compartments. To do this, it is helpful to first think about which variables you need to calculate this at each timestep.

Model the epidemic with the \(\beta\) and \(\gamma\) values you calculated above, assuming introduction of a single infected person in a totally susceptible population of 1 million. Remember, if you have been saving your code somewhere, you can open that and copy-paste the SIR code you have previously developed. You might also have to try different durations to run the model for. Then plot the proportion of susceptible, infected and recovered people over time.

1.0.2 Question: What do you observe?

2 YOUR CODE GOES HERE

Now imagine an intervention is introduced to control infection, for example infected people are isolated so that they cannot spread infection. As a result, \(\beta\) drops to 0.1. Model the epidemic under this new scenario.

2.0.1 Question: What do you observe?

2.0.2 YOUR CODE GOES HERE

In your code above, vary \(\gamma\) with \(\beta\) held constant at 0.1 days\(^{-1}\). Notice that there are some values where the initial infected case fails to cause an epidemic.

2.0.3 Question: Assuming \(\beta\) equals 0.1 days\(^{-1}\), what value of \(\gamma\) do you need in order to get an epidemic? In real life, what could give rise to such a change in \(\gamma\)?

Hint: as the infection rate becomes lower, i.e. the infection spreads more slowly, you have to follow the population over a longer period to observe a visible change in the proportion infected.

You should see that different combinations of infection and recovery rates can give rise to very different infection dynamics.

2.0.4 Question: Based on your answers to the previous question, can you think of a condition involving \(\beta\) and \(\gamma\) that is necessary for an epidemic? Test this condition using your code above.

Don’t forget to check the correct answers provided in the Solutions!

3 Solution: SIR dynamics with varying parameters

We are modelling a disease where every infectious person infects 1 person on average, every 2 days, and is infectious for 4 days.

\(\beta\) = 1 person/2 days = 0.5 days\(^{-1}\)
\(\gamma\) = 1/4 = 0.25 days\(^{-1}\)

Modelling this epidemic for a duration of 100 days:

Question # LOAD THE PACKAGES:

library(deSolve)
library(reshape2)
library(ggplot2)

4 MODEL INPUTS:

# Vector storing the initial number of people in each compartment (at timestep 0)
initial_state_values <- c(S = 1000000-1,  # the whole population we are modelling is susceptible to infection
                          I = 1,          # the epidemic starts with a single infected person
                          R = 0)          # there is no prior immunity in the population

# Vector storing the parameters describing the transition rates in units of days^-1
parameters <- c(beta = 0.5,     # the infection rate, which acts on susceptibles
                gamma = 0.25)   # the rate of recovery, which acts on those infected

# TIMESTEPS:

# Vector storing the sequence of timesteps to solve the model at
times <- seq(from = 0, to = 100, by = 1)   # from 0 to 100 days in daily intervals

# SIR MODEL FUNCTION: 

# The model function takes as input arguments (in the following order): time, state and parameters
sir_model <- function(time, state, parameters) {  

    with(as.list(c(state, parameters)), {   # tell R to unpack variable names from the state and parameters inputs    
        
    # Calculating the total population size N (the sum of the number of people in each compartment)
      N <- S+I+R
      
    # Defining lambda as a function of beta and I:
      lambda <- beta * I/N
        
    # The differential equations
      dS <- -lambda * S               # people move out of (-) the S compartment at a rate lambda (force of infection)
      dI <- lambda * S - gamma * I    # people move into (+) the I compartment from S at a rate lambda, 
                                      # and move out of (-) the I compartment at a rate gamma (recovery)
      dR <- gamma * I                 # people move into (+) the R compartment from I at a rate gamma
      
    # Return the number of people in the S, I and R compartments at each timestep 
    # (in the same order as the input state variables)
    return(list(c(dS, dI, dR))) 
    })
  
}

5 MODEL OUTPUT (solving the differential equations):

# Solving the differential equations using the ode integration algorithm
output <- as.data.frame(ode(y = initial_state_values, 
                            times = times, 
                            func = sir_model,
                            parms = parameters))

# PLOTTING THE OUTPUT
output_long <- melt(as.data.frame(output), id = "time")                  # turn output dataset into long format

# Adding a column for the proportion of the population in each compartment at each timestep
# One way of calculating this is dividing the number in each compartment by the total initial population size
# We can do this in this case because our population is closed, so the population size stays the same
# at every timestep
output_long$proportion <- output_long$value/sum(initial_state_values)

# Plot this new column
ggplot(data = output_long,                                               # specify object containing data to plot
       aes(x = time, y = proportion, colour = variable, group = variable)) +  # assign columns to axes and groups
  geom_line() +                                                          # represent data as lines
  xlab("Time (days)")+                                                   # add label for x axis
  ylab("Proportion of the population") +                                 # add label for y axis
  labs(colour = "Compartment")                                           # add legend title

5.0.1 What do you observe when \(\beta\) = 0.5 and \(\gamma\) = 0.25?

An epidemic occurs, reaching a peak 56 days after introduction of the first infectious case, at which point about 15% of the population are infected. By the end of the epidemic, about 80% of the population have been infected and recovered.

Modelling a scenario where beta drops to 0.1 because an infection control measure is introduced:

# Vector storing the parameters describing the transition rates in units of days^-1
parameters <- c(beta = 0.1,      # the infection rate
                gamma = 0.25)    # the rate of recovery, which acts on those infected

# Solving the differential equations using the ode integration algorithm
output <- as.data.frame(ode(y = initial_state_values, 
                            times = times, 
                            func = sir_model,
                            parms = parameters))

# PLOTTING THE OUTPUT
output_long <- melt(as.data.frame(output), id = "time")                  # turn output dataset into long format

# Calculating the proportion in each compartment
output_long$proportion <- output_long$value/sum(initial_state_values)

ggplot(data = output_long,                                               # specify object containing data to plot
       aes(x = time, y = proportion, colour = variable, group = variable)) +  # assign columns to axes and groups
  geom_line() +                                                          # represent data as lines
  xlab("Time (days)")+                                                   # add label for x axis
  ylab("Proportion of the population") +                                 # add label for y axis
  labs(colour = "Compartment")                                           # add legend title

5.0.2 What do you observe when \(\beta\) is reduced to 0.1 instead, with \(\gamma\) remaining at 0.25?

Under this set of conditions, no epidemic occurs - the number of infected people does not increase following the introduction of a first infectious case.

5.0.3 Assuming \(\beta\) equals 0.1, what value of \(\gamma\) do you need in order to get an epidemic? In real life, what could give rise to this change in \(\gamma\)?

With \(\gamma\) around 0.09 or lower, we start to see a small epidemic if we run the model for long enough (ca. 1000 days). Different mechanisms can lead to such a decrease in the recovery rate, corresponding to an increase of the average infectious period, for example strain evolution of the infectious agent or changes in social behaviour.

5.0.4 Based on your answers to the previous question, can you think of a condition involving \(\beta\) and \(\gamma\) that is necessary for an epidemic? Test this condition using your code above.

For an epidemic to happen, the ratio \(\beta\)/\(\gamma\) has to be greater than 1. In other words, to give rise to an epidemic, infectious people have to be infectious enough (\(\beta\) has to be high enough) for long enough (\(\gamma\) has to be low enough) to pass on the pathogen - \(\beta\) has to be higher than \(\gamma\). Because of the relationship between these two parameters, a low infection rate can still lead an epidemic if infected people are infectious for long enough, as you modelled in the previous question.

6 week 2:

In the last etivity, you derived the expression for the basic reproduction number R0 in the simple SIR model: we get an epidemic only if \(\beta\)/\(\gamma\) > 1, i.e. if the average number of secondary cases caused by a single infected case in a totally susceptible population is greater than 1. As susceptibility declines over the course of the epidemic, the effective reproduction number Reff determines the shape of the epidemic curve as it reflects the amount of immunity in the population at any given time.

Remember that in a simple homogenous SIR model, Reff is directly related to the proportion of the population that is susceptible: \[\begin{align} R_{eff} = R_{0} \frac{S}{N} \end{align}\]

In this etivity, your task is to model an epidemic and study the connection between the behaviour of Reff and the epidemic curve. Like in the previous etivities, we are looking at a closed fully susceptible population, into which a single infected person is introduced. The rest is up to you! Use your previously developed SIR code and chose your combination of parameters so that R0 > 1. Solve the differential equations, and use the output to calculate Reff at each timestep. Then, generate 2 plots for comparison: one of the proportion of susceptible, infected and recovered individuals over time, and one of the effective reproduction number over time.

Comparing the changes over time is easiest if you can align the Reff plot directly below the SIR proportion plot. To achieve this, include the code for the 2 plots right after each other in the same cell, and move the legend of the proportion plot to the bottom using the theme command. Use help(theme) or search the internet to find out how!

7 Solution: Simulating the effective reproduction number Reff

# LOAD THE PACKAGES:
library(deSolve)
library(reshape2)
library(ggplot2)

# MODEL INPUTS:

# Vector storing the initial number of people in each compartment (at timestep 0)
initial_state_values <- c(S = 1000000-1,   # the whole population we are modelling is susceptible to infection
                          I = 1,           # the epidemic starts with a single infected person
                          R = 0)           # there is no prior immunity in the population

# Vector storing the parameters describing the transition rates in units of days^-1
parameters <- c(beta = 0.4,      # the infection rate, which acts on susceptibles
                gamma = 0.1)     # the rate of recovery, which acts on those infected

# TIMESTEPS:

# Vector storing the sequence of timesteps to solve the model at
times <- seq(from = 0, to = 100, by = 1)   # from 0 to 100 days in daily intervals

# SIR MODEL FUNCTION: 

# The model function takes as input arguments (in the following order): time, state and parameters
sir_model <- function(time, state, parameters) {  

    with(as.list(c(state, parameters)), {  # tell R to unpack variable names from the state and parameters inputs    
        
    # Calculating the total population size N (the sum of the number of people in each compartment)
      N <- S+I+R
      
    # Defining lambda as a function of beta and I:
      lambda <- beta * I/N
        
    # The differential equations
      dS <- -lambda * S               # people move out of (-) the S compartment at a rate lambda (force of infection)
      dI <- lambda * S - gamma * I    # people move into (+) the I compartment from S at a rate lambda, 
                                      # and move out of (-) the I compartment at a rate gamma (recovery)
      dR <- gamma * I                 # people move into (+) the R compartment from I at a rate gamma
      
    # Return the number of people in the S, I and R compartments at each timestep 
    # (in the same order as the input state variables)
    return(list(c(dS, dI, dR))) 
    })
  
}

# MODEL OUTPUT (solving the differential equations):

# Solving the differential equations using the ode integration algorithm
output <- as.data.frame(ode(y = initial_state_values, 
                            times = times, 
                            func = sir_model,
                            parms = parameters))

Generating 2 plots:

output_long <- melt(as.data.frame(output), id = "time")                  # turn output dataset into long format

# Calculating the proportion in each compartment as a column in the long-format output
output_long$proportion <- output_long$value/sum(initial_state_values)

# Plot the proportion of people in the S, I and R compartments over time
ggplot(data = output_long,                                               # specify object containing data to plot
       aes(x = time, y = proportion, colour = variable, group = variable)) +  # assign columns to axes and groups
  geom_line() +                                                          # represent data as lines
  xlab("Time (days)")+                                                   # add label for x axis
  ylab("Proportion of the population") +                                 # add label for y axis
  labs(colour = "Compartment",                                           # add legend title  
       title = "Proportion susceptible, infected and recovered over time") +                                                               
  theme(legend.position = "bottom")                                      # move legend to the bottom of the plot

# Calculating the effective reproduction number in a new column
output$reff <- parameters["beta"]/parameters["gamma"] *                  # R0 = beta/gamma
                output$S/(output$S+output$I+output$R)                    # multiply R0 by the proportion susceptible
                                                                         # at each timestep/for each row
# In this calculation, the total population size (output$S+output$I+output$R) is calculated for each timestep
# so this approach would also be appropriate if the population size varies over time

# Plot Reff
ggplot(data = output,                                                    # specify object containing data to plot
       aes(x = time, y = reff)) +                                        # assign columns to axes and groups
  geom_line() +                                                          # represent data as lines
  xlab("Time (days)")+                                                   # add label for x axis
  ylab("Reff") +                                                         # add label for y axis
  labs(title = "Effective reproduction number over time")                # add plot title

7.0.1 How does Reff vary over the course of the epidemic? What do you notice about the connection between the change in Reff and the epidemic curve over time? In particular, in relation to Reff, when does the epidemic peak and start to decline?

The effective reproduction number is highest when everyone is susceptible: at the beginning, Reff = R0. At this point in our example, every infected cases causes an average of 4 secondary infections. Over the course of the epidemic, Reff declines in proportion to susceptibility.

The peak of the epidemic happens when Reff goes down to 1 (in the example here, after 50 days). As Reff decreases further below 1, the epidemic prevalence goes into decline. This is exactly what you would expect, given your understanding of the meaning of Reff: once the epidemic reaches the point where every infected case cannot cause at least one more infected case (that is, when Reff < 1), the epidemic cannot sustain itself and comes to an end.

LS0tDQp0aXRsZTogIlcyIFNJUiBkeW5hbWljIHdpdGggdmFyeSBwYXJhbWV0dGVycyINCmF1dGhvcjogIkJpbmggVGhhbmcgVHJhbiINCmRhdGU6ICI1LzE4LzIwMjAiDQpvdXRwdXQ6DQogIGh0bWxfZG9jdW1lbnQ6DQogICAgY29kZV9kb3dubG9hZDogeWVzDQogICAgY29kZV9mb2xkaW5nOiBoaWRlDQogICAgbnVtYmVyX3NlY3Rpb25zOiB5ZXMNCiAgICB0aGVtZTogam91cm5hbA0KICAgIHRvYzogeWVzDQogICAgdG9jX2Zsb2F0OiB5ZXMNCiAgd29yZF9kb2N1bWVudDoNCiAgICB0b2M6IHllcw0KLS0tDQoNCg0KIyBTSVIgZHluYW1pY3Mgd2l0aCB2YXJ5aW5nIHBhcmFtZXRlcnMNCg0KSW4gdGhlIGZpcnN0IHdlZWssIHlvdSBnYWluZWQgZmlyc3QgZXhwZXJpZW5jZSB3aXRoIGNvZGluZyBzaW1wbGUgbW9kZWxzIGluIFIgdXNpbmcgdGhlIGRlU29sdmUgcGFja2FnZS4gTGFzdCB3ZWVrLCB5b3Ugd2VudCBpbnRvIGZ1cnRoZXIgZGV0YWlscyBhYm91dCB0aGUgZHJpdmVycyBvZiBhbiBlcGlkZW1pYyBhbmQgdGhlIGR5bmFtaWNzIG9mIHRoZSBTSVIgbW9kZWwuIFRoaXMgd2Vlaywgd2UgYXJlIGJyaW5naW5nIHRoaXMgdG9nZXRoZXIgdG8gdGhpbmsgbW9yZSBkZWVwbHkgYWJvdXQgdGhlIHJvbGVzIG9mICRcYmV0YSQgYW5kICRcZ2FtbWEkLg0KDQojIyMgUXVlc3Rpb246IEltYWdpbmUgYSBkaXNlYXNlIHdoZXJlIGV2ZXJ5IHBlcnNvbiBpbmZlY3RzIDEgcGVyc29uIG9uIGF2ZXJhZ2UsIGV2ZXJ5IDIgZGF5cywgYW5kIGlzIGluZmVjdGlvdXMgZm9yIDQgZGF5cy4gV2hhdCBhcmUgdGhlIHZhbHVlcyBmb3IgJFxiZXRhJCBhbmQgJFxnYW1tYSQ/DQoNClNvIGZhciwgd2hlbiBsb29raW5nIGF0IHRoZSBkeW5hbWljcyBvZiBhbiBlcGlkZW1pYywgd2UgaGF2ZSBhbHdheXMgcGxvdHRlZCB0aGUgbnVtYmVyIG9mIHBlb3BsZSBpbiBlYWNoIGNvbXBhcnRtZW50LiBTb21ldGltZXMgaG93ZXZlciBpdCBpcyBtb3JlIGluZm9ybWF0aXZlIHRvIGxvb2sgYXQgdGhlIHByb3BvcnRpb24gb2YgdGhlIHBvcHVsYXRpb24gaW4gZWFjaCBjb21wYXJ0bWVudCByYXRoZXIgdGhhbiB0aGUgYWN0dWFsIG51bWJlciwgcGFydGljdWxhcmx5IGlmIHRoZSBwb3B1bGF0aW9uIHNpemUgY2hhbmdlcyBvdmVyIHRpbWUuIEFsdGhvdWdoIHdlIGFyZSBtb2RlbGxpbmcgYW4gZXBpZGVtaWMgaW4gYSBjbG9zZWQgcG9wdWxhdGlvbiB3aXRoIGNvbnN0YW50IHBvcHVsYXRpb24gc2l6ZSBpbiB0aGlzIGV0aXZpdHksIGl0IGlzIGEgZ29vZCBvcHBvcnR1bml0eSB0byBwcmFjdGljZSBwbG90dGluZyB0aGUgcHJldmFsZW5jZSBhcyBhIHByb3BvcnRpb24gb2YgdGhlIHRvdGFsIHBvcHVsYXRpb24gd2hvIGFyZSBpbiB0aGUgJFMkLCAkSSQgYW5kICRSJCBjb21wYXJ0bWVudHMuIFRvIGRvIHRoaXMsIGl0IGlzIGhlbHBmdWwgdG8gZmlyc3QgdGhpbmsgYWJvdXQgd2hpY2ggdmFyaWFibGVzIHlvdSBuZWVkIHRvIGNhbGN1bGF0ZSB0aGlzIGF0IGVhY2ggdGltZXN0ZXAuDQoNCk1vZGVsIHRoZSBlcGlkZW1pYyB3aXRoIHRoZSAkXGJldGEkIGFuZCAkXGdhbW1hJCB2YWx1ZXMgeW91IGNhbGN1bGF0ZWQgYWJvdmUsIGFzc3VtaW5nIGludHJvZHVjdGlvbiBvZiBhIHNpbmdsZSBpbmZlY3RlZCBwZXJzb24gaW4gYSB0b3RhbGx5IHN1c2NlcHRpYmxlIHBvcHVsYXRpb24gb2YgMSBtaWxsaW9uLiBSZW1lbWJlciwgaWYgeW91IGhhdmUgYmVlbiBzYXZpbmcgeW91ciBjb2RlIHNvbWV3aGVyZSwgeW91IGNhbiBvcGVuIHRoYXQgYW5kIGNvcHktcGFzdGUgdGhlIFNJUiBjb2RlIHlvdSBoYXZlIHByZXZpb3VzbHkgZGV2ZWxvcGVkLiBZb3UgbWlnaHQgYWxzbyBoYXZlIHRvIHRyeSBkaWZmZXJlbnQgZHVyYXRpb25zIHRvIHJ1biB0aGUgbW9kZWwgZm9yLiBUaGVuIHBsb3QgdGhlIHByb3BvcnRpb24gb2Ygc3VzY2VwdGlibGUsIGluZmVjdGVkIGFuZCByZWNvdmVyZWQgcGVvcGxlIG92ZXIgdGltZS4NCg0KIyMjIFF1ZXN0aW9uOiBXaGF0IGRvIHlvdSBvYnNlcnZlPw0KDQoNCg0KIyBZT1VSIENPREUgR09FUyBIRVJFICMjIw0KDQoNCk5vdyBpbWFnaW5lIGFuIGludGVydmVudGlvbiBpcyBpbnRyb2R1Y2VkIHRvIGNvbnRyb2wgaW5mZWN0aW9uLCBmb3IgZXhhbXBsZSBpbmZlY3RlZCBwZW9wbGUgYXJlIGlzb2xhdGVkIHNvIHRoYXQgdGhleSBjYW5ub3Qgc3ByZWFkIGluZmVjdGlvbi4gQXMgYSByZXN1bHQsICRcYmV0YSQgZHJvcHMgdG8gMC4xLiBNb2RlbCB0aGUgZXBpZGVtaWMgdW5kZXIgdGhpcyBuZXcgc2NlbmFyaW8uIA0KDQojIyMgUXVlc3Rpb246IFdoYXQgZG8geW91IG9ic2VydmU/DQoNCg0KIyMjIFlPVVIgQ09ERSBHT0VTIEhFUkUgIyMjDQoNCg0KSW4geW91ciBjb2RlIGFib3ZlLCB2YXJ5ICRcZ2FtbWEkIHdpdGggJFxiZXRhJCBoZWxkIGNvbnN0YW50IGF0IDAuMSBkYXlzJF57LTF9JC4gTm90aWNlIHRoYXQgdGhlcmUgYXJlIHNvbWUgdmFsdWVzIHdoZXJlIHRoZSBpbml0aWFsIGluZmVjdGVkIGNhc2UgZmFpbHMgdG8gY2F1c2UgYW4gZXBpZGVtaWMuDQoNCiMjIyBRdWVzdGlvbjogQXNzdW1pbmcgJFxiZXRhJCBlcXVhbHMgMC4xIGRheXMkXnstMX0kLCB3aGF0IHZhbHVlIG9mICRcZ2FtbWEkIGRvIHlvdSBuZWVkIGluIG9yZGVyIHRvIGdldCBhbiBlcGlkZW1pYz8gSW4gcmVhbCBsaWZlLCB3aGF0IGNvdWxkIGdpdmUgcmlzZSB0byBzdWNoIGEgY2hhbmdlIGluICRcZ2FtbWEkPw0KKkhpbnQ6IGFzIHRoZSBpbmZlY3Rpb24gcmF0ZSBiZWNvbWVzIGxvd2VyLCBpLmUuIHRoZSBpbmZlY3Rpb24gc3ByZWFkcyBtb3JlIHNsb3dseSwgeW91IGhhdmUgdG8gZm9sbG93IHRoZSBwb3B1bGF0aW9uIG92ZXIgYSBsb25nZXIgcGVyaW9kIHRvIG9ic2VydmUgYSB2aXNpYmxlIGNoYW5nZSBpbiB0aGUgcHJvcG9ydGlvbiBpbmZlY3RlZC4qDQoNCllvdSBzaG91bGQgc2VlIHRoYXQgZGlmZmVyZW50IGNvbWJpbmF0aW9ucyBvZiBpbmZlY3Rpb24gYW5kIHJlY292ZXJ5IHJhdGVzIGNhbiBnaXZlIHJpc2UgdG8gdmVyeSBkaWZmZXJlbnQgaW5mZWN0aW9uIGR5bmFtaWNzLiANCg0KIyMjIFF1ZXN0aW9uOiBCYXNlZCBvbiB5b3VyIGFuc3dlcnMgdG8gdGhlIHByZXZpb3VzIHF1ZXN0aW9uLCBjYW4geW91IHRoaW5rIG9mIGEgY29uZGl0aW9uIGludm9sdmluZyAkXGJldGEkIGFuZCAkXGdhbW1hJCB0aGF0IGlzIG5lY2Vzc2FyeSBmb3IgYW4gZXBpZGVtaWM/IFRlc3QgdGhpcyBjb25kaXRpb24gdXNpbmcgeW91ciBjb2RlIGFib3ZlLg0KDQoqKkRvbid0IGZvcmdldCB0byBjaGVjayB0aGUgY29ycmVjdCBhbnN3ZXJzIHByb3ZpZGVkIGluIHRoZSBTb2x1dGlvbnMhKioNCg0KDQoNCg0KIyBTb2x1dGlvbjogU0lSIGR5bmFtaWNzIHdpdGggdmFyeWluZyBwYXJhbWV0ZXJzDQoNCldlIGFyZSBtb2RlbGxpbmcgYSBkaXNlYXNlIHdoZXJlIGV2ZXJ5IGluZmVjdGlvdXMgcGVyc29uIGluZmVjdHMgMSBwZXJzb24gb24gYXZlcmFnZSwgZXZlcnkgMiBkYXlzLCBhbmQgaXMgaW5mZWN0aW91cyBmb3IgNCBkYXlzLiAgIA0KDQokXGJldGEkID0gMSBwZXJzb24vMiBkYXlzID0gMC41IGRheXMkXnstMX0kICANCiRcZ2FtbWEkID0gMS80ID0gMC4yNSBkYXlzJF57LTF9JA0KDQoqKk1vZGVsbGluZyB0aGlzIGVwaWRlbWljIGZvciBhIGR1cmF0aW9uIG9mIDEwMCBkYXlzOioqDQoNClF1ZXN0aW9uDQojIExPQUQgVEhFIFBBQ0tBR0VTOg0KYGBge3J9DQoNCmxpYnJhcnkoZGVTb2x2ZSkNCmxpYnJhcnkocmVzaGFwZTIpDQpsaWJyYXJ5KGdncGxvdDIpDQpgYGANCg0KIyBNT0RFTCBJTlBVVFM6DQoNCmBgYHtSfQ0KDQoNCiMgVmVjdG9yIHN0b3JpbmcgdGhlIGluaXRpYWwgbnVtYmVyIG9mIHBlb3BsZSBpbiBlYWNoIGNvbXBhcnRtZW50IChhdCB0aW1lc3RlcCAwKQ0KaW5pdGlhbF9zdGF0ZV92YWx1ZXMgPC0gYyhTID0gMTAwMDAwMC0xLCAgIyB0aGUgd2hvbGUgcG9wdWxhdGlvbiB3ZSBhcmUgbW9kZWxsaW5nIGlzIHN1c2NlcHRpYmxlIHRvIGluZmVjdGlvbg0KICAgICAgICAgICAgICAgICAgICAgICAgICBJID0gMSwgICAgICAgICAgIyB0aGUgZXBpZGVtaWMgc3RhcnRzIHdpdGggYSBzaW5nbGUgaW5mZWN0ZWQgcGVyc29uDQogICAgICAgICAgICAgICAgICAgICAgICAgIFIgPSAwKSAgICAgICAgICAjIHRoZXJlIGlzIG5vIHByaW9yIGltbXVuaXR5IGluIHRoZSBwb3B1bGF0aW9uDQoNCiMgVmVjdG9yIHN0b3JpbmcgdGhlIHBhcmFtZXRlcnMgZGVzY3JpYmluZyB0aGUgdHJhbnNpdGlvbiByYXRlcyBpbiB1bml0cyBvZiBkYXlzXi0xDQpwYXJhbWV0ZXJzIDwtIGMoYmV0YSA9IDAuNSwgICAgICMgdGhlIGluZmVjdGlvbiByYXRlLCB3aGljaCBhY3RzIG9uIHN1c2NlcHRpYmxlcw0KICAgICAgICAgICAgICAgIGdhbW1hID0gMC4yNSkgICAjIHRoZSByYXRlIG9mIHJlY292ZXJ5LCB3aGljaCBhY3RzIG9uIHRob3NlIGluZmVjdGVkDQoNCiMgVElNRVNURVBTOg0KDQojIFZlY3RvciBzdG9yaW5nIHRoZSBzZXF1ZW5jZSBvZiB0aW1lc3RlcHMgdG8gc29sdmUgdGhlIG1vZGVsIGF0DQp0aW1lcyA8LSBzZXEoZnJvbSA9IDAsIHRvID0gMTAwLCBieSA9IDEpICAgIyBmcm9tIDAgdG8gMTAwIGRheXMgaW4gZGFpbHkgaW50ZXJ2YWxzDQoNCiMgU0lSIE1PREVMIEZVTkNUSU9OOiANCg0KIyBUaGUgbW9kZWwgZnVuY3Rpb24gdGFrZXMgYXMgaW5wdXQgYXJndW1lbnRzIChpbiB0aGUgZm9sbG93aW5nIG9yZGVyKTogdGltZSwgc3RhdGUgYW5kIHBhcmFtZXRlcnMNCnNpcl9tb2RlbCA8LSBmdW5jdGlvbih0aW1lLCBzdGF0ZSwgcGFyYW1ldGVycykgeyAgDQoNCiAgICB3aXRoKGFzLmxpc3QoYyhzdGF0ZSwgcGFyYW1ldGVycykpLCB7ICAgIyB0ZWxsIFIgdG8gdW5wYWNrIHZhcmlhYmxlIG5hbWVzIGZyb20gdGhlIHN0YXRlIGFuZCBwYXJhbWV0ZXJzIGlucHV0cyAgICANCiAgICAgICAgDQogICAgIyBDYWxjdWxhdGluZyB0aGUgdG90YWwgcG9wdWxhdGlvbiBzaXplIE4gKHRoZSBzdW0gb2YgdGhlIG51bWJlciBvZiBwZW9wbGUgaW4gZWFjaCBjb21wYXJ0bWVudCkNCiAgICAgIE4gPC0gUytJK1INCiAgICAgIA0KICAgICMgRGVmaW5pbmcgbGFtYmRhIGFzIGEgZnVuY3Rpb24gb2YgYmV0YSBhbmQgSToNCiAgICAgIGxhbWJkYSA8LSBiZXRhICogSS9ODQogICAgICAgIA0KICAgICMgVGhlIGRpZmZlcmVudGlhbCBlcXVhdGlvbnMNCiAgICAgIGRTIDwtIC1sYW1iZGEgKiBTICAgICAgICAgICAgICAgIyBwZW9wbGUgbW92ZSBvdXQgb2YgKC0pIHRoZSBTIGNvbXBhcnRtZW50IGF0IGEgcmF0ZSBsYW1iZGEgKGZvcmNlIG9mIGluZmVjdGlvbikNCiAgICAgIGRJIDwtIGxhbWJkYSAqIFMgLSBnYW1tYSAqIEkgICAgIyBwZW9wbGUgbW92ZSBpbnRvICgrKSB0aGUgSSBjb21wYXJ0bWVudCBmcm9tIFMgYXQgYSByYXRlIGxhbWJkYSwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICMgYW5kIG1vdmUgb3V0IG9mICgtKSB0aGUgSSBjb21wYXJ0bWVudCBhdCBhIHJhdGUgZ2FtbWEgKHJlY292ZXJ5KQ0KICAgICAgZFIgPC0gZ2FtbWEgKiBJICAgICAgICAgICAgICAgICAjIHBlb3BsZSBtb3ZlIGludG8gKCspIHRoZSBSIGNvbXBhcnRtZW50IGZyb20gSSBhdCBhIHJhdGUgZ2FtbWENCiAgICAgIA0KICAgICMgUmV0dXJuIHRoZSBudW1iZXIgb2YgcGVvcGxlIGluIHRoZSBTLCBJIGFuZCBSIGNvbXBhcnRtZW50cyBhdCBlYWNoIHRpbWVzdGVwIA0KICAgICMgKGluIHRoZSBzYW1lIG9yZGVyIGFzIHRoZSBpbnB1dCBzdGF0ZSB2YXJpYWJsZXMpDQogICAgcmV0dXJuKGxpc3QoYyhkUywgZEksIGRSKSkpIA0KICAgIH0pDQogIA0KfQ0KDQoNCmBgYA0KDQojIE1PREVMIE9VVFBVVCAoc29sdmluZyB0aGUgZGlmZmVyZW50aWFsIGVxdWF0aW9ucyk6DQoNCmBgYHtyfQ0KDQoNCiMgU29sdmluZyB0aGUgZGlmZmVyZW50aWFsIGVxdWF0aW9ucyB1c2luZyB0aGUgb2RlIGludGVncmF0aW9uIGFsZ29yaXRobQ0Kb3V0cHV0IDwtIGFzLmRhdGEuZnJhbWUob2RlKHkgPSBpbml0aWFsX3N0YXRlX3ZhbHVlcywgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgdGltZXMgPSB0aW1lcywgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgZnVuYyA9IHNpcl9tb2RlbCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwYXJtcyA9IHBhcmFtZXRlcnMpKQ0KDQojIFBMT1RUSU5HIFRIRSBPVVRQVVQNCm91dHB1dF9sb25nIDwtIG1lbHQoYXMuZGF0YS5mcmFtZShvdXRwdXQpLCBpZCA9ICJ0aW1lIikgICAgICAgICAgICAgICAgICAjIHR1cm4gb3V0cHV0IGRhdGFzZXQgaW50byBsb25nIGZvcm1hdA0KDQojIEFkZGluZyBhIGNvbHVtbiBmb3IgdGhlIHByb3BvcnRpb24gb2YgdGhlIHBvcHVsYXRpb24gaW4gZWFjaCBjb21wYXJ0bWVudCBhdCBlYWNoIHRpbWVzdGVwDQojIE9uZSB3YXkgb2YgY2FsY3VsYXRpbmcgdGhpcyBpcyBkaXZpZGluZyB0aGUgbnVtYmVyIGluIGVhY2ggY29tcGFydG1lbnQgYnkgdGhlIHRvdGFsIGluaXRpYWwgcG9wdWxhdGlvbiBzaXplDQojIFdlIGNhbiBkbyB0aGlzIGluIHRoaXMgY2FzZSBiZWNhdXNlIG91ciBwb3B1bGF0aW9uIGlzIGNsb3NlZCwgc28gdGhlIHBvcHVsYXRpb24gc2l6ZSBzdGF5cyB0aGUgc2FtZQ0KIyBhdCBldmVyeSB0aW1lc3RlcA0Kb3V0cHV0X2xvbmckcHJvcG9ydGlvbiA8LSBvdXRwdXRfbG9uZyR2YWx1ZS9zdW0oaW5pdGlhbF9zdGF0ZV92YWx1ZXMpDQoNCiMgUGxvdCB0aGlzIG5ldyBjb2x1bW4NCmdncGxvdChkYXRhID0gb3V0cHV0X2xvbmcsICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjIHNwZWNpZnkgb2JqZWN0IGNvbnRhaW5pbmcgZGF0YSB0byBwbG90DQogICAgICAgYWVzKHggPSB0aW1lLCB5ID0gcHJvcG9ydGlvbiwgY29sb3VyID0gdmFyaWFibGUsIGdyb3VwID0gdmFyaWFibGUpKSArICAjIGFzc2lnbiBjb2x1bW5zIHRvIGF4ZXMgYW5kIGdyb3Vwcw0KICBnZW9tX2xpbmUoKSArICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICMgcmVwcmVzZW50IGRhdGEgYXMgbGluZXMNCiAgeGxhYigiVGltZSAoZGF5cykiKSsgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjIGFkZCBsYWJlbCBmb3IgeCBheGlzDQogIHlsYWIoIlByb3BvcnRpb24gb2YgdGhlIHBvcHVsYXRpb24iKSArICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIyBhZGQgbGFiZWwgZm9yIHkgYXhpcw0KICBsYWJzKGNvbG91ciA9ICJDb21wYXJ0bWVudCIpICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICMgYWRkIGxlZ2VuZCB0aXRsZQ0KYGBgDQoNCg0KIyMjIFdoYXQgZG8geW91IG9ic2VydmUgd2hlbiAkXGJldGEkID0gMC41IGFuZCAkXGdhbW1hJCA9IDAuMjU/DQoNCkFuIGVwaWRlbWljIG9jY3VycywgcmVhY2hpbmcgYSBwZWFrIDU2IGRheXMgYWZ0ZXIgaW50cm9kdWN0aW9uIG9mIHRoZSBmaXJzdCBpbmZlY3Rpb3VzIGNhc2UsIGF0IHdoaWNoIHBvaW50IGFib3V0IDE1JSBvZiB0aGUgcG9wdWxhdGlvbiBhcmUgaW5mZWN0ZWQuIEJ5IHRoZSBlbmQgb2YgdGhlIGVwaWRlbWljLCBhYm91dCA4MCUgb2YgdGhlIHBvcHVsYXRpb24gaGF2ZSBiZWVuIGluZmVjdGVkIGFuZCByZWNvdmVyZWQuDQoNCioqTW9kZWxsaW5nIGEgc2NlbmFyaW8gd2hlcmUgKmJldGEqIGRyb3BzIHRvIDAuMSBiZWNhdXNlIGFuIGluZmVjdGlvbiBjb250cm9sIG1lYXN1cmUgaXMgaW50cm9kdWNlZDoqKg0KDQoNCmBgYHtSfQ0KIyBWZWN0b3Igc3RvcmluZyB0aGUgcGFyYW1ldGVycyBkZXNjcmliaW5nIHRoZSB0cmFuc2l0aW9uIHJhdGVzIGluIHVuaXRzIG9mIGRheXNeLTENCnBhcmFtZXRlcnMgPC0gYyhiZXRhID0gMC4xLCAgICAgICMgdGhlIGluZmVjdGlvbiByYXRlDQogICAgICAgICAgICAgICAgZ2FtbWEgPSAwLjI1KSAgICAjIHRoZSByYXRlIG9mIHJlY292ZXJ5LCB3aGljaCBhY3RzIG9uIHRob3NlIGluZmVjdGVkDQoNCiMgU29sdmluZyB0aGUgZGlmZmVyZW50aWFsIGVxdWF0aW9ucyB1c2luZyB0aGUgb2RlIGludGVncmF0aW9uIGFsZ29yaXRobQ0Kb3V0cHV0IDwtIGFzLmRhdGEuZnJhbWUob2RlKHkgPSBpbml0aWFsX3N0YXRlX3ZhbHVlcywgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgdGltZXMgPSB0aW1lcywgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgZnVuYyA9IHNpcl9tb2RlbCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwYXJtcyA9IHBhcmFtZXRlcnMpKQ0KDQojIFBMT1RUSU5HIFRIRSBPVVRQVVQNCm91dHB1dF9sb25nIDwtIG1lbHQoYXMuZGF0YS5mcmFtZShvdXRwdXQpLCBpZCA9ICJ0aW1lIikgICAgICAgICAgICAgICAgICAjIHR1cm4gb3V0cHV0IGRhdGFzZXQgaW50byBsb25nIGZvcm1hdA0KDQojIENhbGN1bGF0aW5nIHRoZSBwcm9wb3J0aW9uIGluIGVhY2ggY29tcGFydG1lbnQNCm91dHB1dF9sb25nJHByb3BvcnRpb24gPC0gb3V0cHV0X2xvbmckdmFsdWUvc3VtKGluaXRpYWxfc3RhdGVfdmFsdWVzKQ0KDQpnZ3Bsb3QoZGF0YSA9IG91dHB1dF9sb25nLCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIyBzcGVjaWZ5IG9iamVjdCBjb250YWluaW5nIGRhdGEgdG8gcGxvdA0KICAgICAgIGFlcyh4ID0gdGltZSwgeSA9IHByb3BvcnRpb24sIGNvbG91ciA9IHZhcmlhYmxlLCBncm91cCA9IHZhcmlhYmxlKSkgKyAgIyBhc3NpZ24gY29sdW1ucyB0byBheGVzIGFuZCBncm91cHMNCiAgZ2VvbV9saW5lKCkgKyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjIHJlcHJlc2VudCBkYXRhIGFzIGxpbmVzDQogIHhsYWIoIlRpbWUgKGRheXMpIikrICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIyBhZGQgbGFiZWwgZm9yIHggYXhpcw0KICB5bGFiKCJQcm9wb3J0aW9uIG9mIHRoZSBwb3B1bGF0aW9uIikgKyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICMgYWRkIGxhYmVsIGZvciB5IGF4aXMNCiAgbGFicyhjb2xvdXIgPSAiQ29tcGFydG1lbnQiKSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjIGFkZCBsZWdlbmQgdGl0bGUNCmBgYA0KDQoNCg0KDQojIyMgV2hhdCBkbyB5b3Ugb2JzZXJ2ZSB3aGVuICRcYmV0YSQgaXMgcmVkdWNlZCB0byAwLjEgaW5zdGVhZCwgd2l0aCAkXGdhbW1hJCByZW1haW5pbmcgYXQgMC4yNT8NCg0KVW5kZXIgdGhpcyBzZXQgb2YgY29uZGl0aW9ucywgbm8gZXBpZGVtaWMgb2NjdXJzIC0gdGhlIG51bWJlciBvZiBpbmZlY3RlZCBwZW9wbGUgZG9lcyBub3QgaW5jcmVhc2UgZm9sbG93aW5nIHRoZSBpbnRyb2R1Y3Rpb24gb2YgYSBmaXJzdCBpbmZlY3Rpb3VzIGNhc2UuDQoNCiMjIyBBc3N1bWluZyAkXGJldGEkIGVxdWFscyAwLjEsIHdoYXQgdmFsdWUgb2YgJFxnYW1tYSQgZG8geW91IG5lZWQgaW4gb3JkZXIgdG8gZ2V0IGFuIGVwaWRlbWljPyBJbiByZWFsIGxpZmUsIHdoYXQgY291bGQgZ2l2ZSByaXNlIHRvIHRoaXMgY2hhbmdlIGluICRcZ2FtbWEkPw0KDQpXaXRoICRcZ2FtbWEkIGFyb3VuZCAwLjA5IG9yIGxvd2VyLCB3ZSBzdGFydCB0byBzZWUgYSBzbWFsbCBlcGlkZW1pYyBpZiB3ZSBydW4gdGhlIG1vZGVsIGZvciBsb25nIGVub3VnaCAoY2EuIDEwMDAgZGF5cykuIERpZmZlcmVudCBtZWNoYW5pc21zIGNhbiBsZWFkIHRvIHN1Y2ggYSBkZWNyZWFzZSBpbiB0aGUgcmVjb3ZlcnkgcmF0ZSwgY29ycmVzcG9uZGluZyB0byBhbiBpbmNyZWFzZSBvZiB0aGUgYXZlcmFnZSBpbmZlY3Rpb3VzIHBlcmlvZCwgZm9yIGV4YW1wbGUgc3RyYWluIGV2b2x1dGlvbiBvZiB0aGUgaW5mZWN0aW91cyBhZ2VudCBvciBjaGFuZ2VzIGluIHNvY2lhbCBiZWhhdmlvdXIuDQoNCiMjIyBCYXNlZCBvbiB5b3VyIGFuc3dlcnMgdG8gdGhlIHByZXZpb3VzIHF1ZXN0aW9uLCBjYW4geW91IHRoaW5rIG9mIGEgY29uZGl0aW9uIGludm9sdmluZyAkXGJldGEkIGFuZCAkXGdhbW1hJCB0aGF0IGlzIG5lY2Vzc2FyeSBmb3IgYW4gZXBpZGVtaWM/IFRlc3QgdGhpcyBjb25kaXRpb24gdXNpbmcgeW91ciBjb2RlIGFib3ZlLiANCg0KRm9yIGFuIGVwaWRlbWljIHRvIGhhcHBlbiwgdGhlIHJhdGlvICRcYmV0YSQvJFxnYW1tYSQgaGFzIHRvIGJlIGdyZWF0ZXIgdGhhbiAxLiBJbiBvdGhlciB3b3JkcywgdG8gZ2l2ZSByaXNlIHRvIGFuIGVwaWRlbWljLCBpbmZlY3Rpb3VzIHBlb3BsZSBoYXZlIHRvIGJlICoqaW5mZWN0aW91cyBlbm91Z2gqKiAoJFxiZXRhJCBoYXMgdG8gYmUgaGlnaCBlbm91Z2gpIGZvciAqKmxvbmcgZW5vdWdoKiogKCRcZ2FtbWEkIGhhcyB0byBiZSBsb3cgZW5vdWdoKSB0byBwYXNzIG9uIHRoZSBwYXRob2dlbiAtICRcYmV0YSQgaGFzIHRvIGJlIGhpZ2hlciB0aGFuICRcZ2FtbWEkLiBCZWNhdXNlIG9mIHRoZSByZWxhdGlvbnNoaXAgYmV0d2VlbiB0aGVzZSB0d28gcGFyYW1ldGVycywgYSBsb3cgaW5mZWN0aW9uIHJhdGUgY2FuIHN0aWxsIGxlYWQgYW4gZXBpZGVtaWMgaWYgaW5mZWN0ZWQgcGVvcGxlIGFyZSBpbmZlY3Rpb3VzIGZvciBsb25nIGVub3VnaCwgYXMgeW91IG1vZGVsbGVkIGluIHRoZSBwcmV2aW91cyBxdWVzdGlvbi4NCg0KDQpgYGB7Un0NCg0KYGBgDQoNCg0KDQojIHdlZWsgMjogDQoNCg0KSW4gdGhlIGxhc3QgZXRpdml0eSwgeW91IGRlcml2ZWQgdGhlIGV4cHJlc3Npb24gZm9yIHRoZSBiYXNpYyByZXByb2R1Y3Rpb24gbnVtYmVyIFI8c3ViPjA8L3N1Yj4gaW4gdGhlIHNpbXBsZSBTSVIgbW9kZWw6IHdlIGdldCBhbiBlcGlkZW1pYyBvbmx5IGlmICRcYmV0YSQvJFxnYW1tYSQgPiAxLCBpLmUuIGlmIHRoZSBhdmVyYWdlIG51bWJlciBvZiBzZWNvbmRhcnkgY2FzZXMgY2F1c2VkIGJ5IGEgc2luZ2xlIGluZmVjdGVkIGNhc2UgaW4gYSB0b3RhbGx5IHN1c2NlcHRpYmxlIHBvcHVsYXRpb24gaXMgZ3JlYXRlciB0aGFuIDEuIEFzIHN1c2NlcHRpYmlsaXR5IGRlY2xpbmVzIG92ZXIgdGhlIGNvdXJzZSBvZiB0aGUgZXBpZGVtaWMsIHRoZSBlZmZlY3RpdmUgcmVwcm9kdWN0aW9uIG51bWJlciBSPHN1Yj5lZmY8L3N1Yj4gZGV0ZXJtaW5lcyB0aGUgc2hhcGUgb2YgdGhlIGVwaWRlbWljIGN1cnZlIGFzIGl0IHJlZmxlY3RzIHRoZSBhbW91bnQgb2YgaW1tdW5pdHkgaW4gdGhlIHBvcHVsYXRpb24gYXQgYW55IGdpdmVuIHRpbWUuDQoNClJlbWVtYmVyIHRoYXQgaW4gYSBzaW1wbGUgaG9tb2dlbm91cyBTSVIgbW9kZWwsIFI8c3ViPmVmZjwvc3ViPiBpcyBkaXJlY3RseSByZWxhdGVkIHRvIHRoZSBwcm9wb3J0aW9uIG9mIHRoZSBwb3B1bGF0aW9uIHRoYXQgaXMgc3VzY2VwdGlibGU6DQpcYmVnaW57YWxpZ259DQpSX3tlZmZ9ID0gUl97MH0gXGZyYWN7U317Tn0NClxlbmR7YWxpZ259DQoNCkluIHRoaXMgZXRpdml0eSwgeW91ciB0YXNrIGlzIHRvIG1vZGVsIGFuIGVwaWRlbWljIGFuZCBzdHVkeSB0aGUgY29ubmVjdGlvbiBiZXR3ZWVuIHRoZSBiZWhhdmlvdXIgb2YgUjxzdWI+ZWZmPC9zdWI+IGFuZCB0aGUgZXBpZGVtaWMgY3VydmUuIExpa2UgaW4gdGhlIHByZXZpb3VzIGV0aXZpdGllcywgd2UgYXJlIGxvb2tpbmcgYXQgYSBjbG9zZWQgZnVsbHkgc3VzY2VwdGlibGUgcG9wdWxhdGlvbiwgaW50byB3aGljaCBhIHNpbmdsZSBpbmZlY3RlZCBwZXJzb24gaXMgaW50cm9kdWNlZC4gVGhlIHJlc3QgaXMgdXAgdG8geW91ISBVc2UgeW91ciBwcmV2aW91c2x5IGRldmVsb3BlZCBTSVIgY29kZSBhbmQgY2hvc2UgeW91ciBjb21iaW5hdGlvbiBvZiBwYXJhbWV0ZXJzIHNvIHRoYXQgUjxzdWI+MDwvc3ViPiA+IDEuIFNvbHZlIHRoZSBkaWZmZXJlbnRpYWwgZXF1YXRpb25zLCBhbmQgdXNlIHRoZSBvdXRwdXQgdG8gY2FsY3VsYXRlIFI8c3ViPmVmZjwvc3ViPiBhdCBlYWNoIHRpbWVzdGVwLiBUaGVuLCBnZW5lcmF0ZSAyIHBsb3RzIGZvciBjb21wYXJpc29uOiBvbmUgb2YgdGhlIHByb3BvcnRpb24gb2Ygc3VzY2VwdGlibGUsIGluZmVjdGVkIGFuZCByZWNvdmVyZWQgaW5kaXZpZHVhbHMgb3ZlciB0aW1lLCBhbmQgb25lIG9mIHRoZSBlZmZlY3RpdmUgcmVwcm9kdWN0aW9uIG51bWJlciBvdmVyIHRpbWUuIA0KDQpDb21wYXJpbmcgdGhlIGNoYW5nZXMgb3ZlciB0aW1lIGlzIGVhc2llc3QgaWYgeW91IGNhbiBhbGlnbiB0aGUgUjxzdWI+ZWZmPC9zdWI+IHBsb3QgZGlyZWN0bHkgYmVsb3cgdGhlIFNJUiBwcm9wb3J0aW9uIHBsb3QuIFRvIGFjaGlldmUgdGhpcywgaW5jbHVkZSB0aGUgY29kZSBmb3IgdGhlIDIgcGxvdHMgcmlnaHQgYWZ0ZXIgZWFjaCBvdGhlciBpbiB0aGUgc2FtZSBjZWxsLCBhbmQgbW92ZSB0aGUgbGVnZW5kIG9mIHRoZSBwcm9wb3J0aW9uIHBsb3QgdG8gdGhlIGJvdHRvbSB1c2luZyB0aGUgdGhlbWUgY29tbWFuZC4gVXNlIGhlbHAodGhlbWUpIG9yIHNlYXJjaCB0aGUgaW50ZXJuZXQgdG8gZmluZCBvdXQgaG93IQ0KDQojIFNvbHV0aW9uOiBTaW11bGF0aW5nIHRoZSBlZmZlY3RpdmUgcmVwcm9kdWN0aW9uIG51bWJlciBSPHN1Yj5lZmY8L3N1Yj4NCg0KYGBge3J9DQojIExPQUQgVEhFIFBBQ0tBR0VTOg0KbGlicmFyeShkZVNvbHZlKQ0KbGlicmFyeShyZXNoYXBlMikNCmxpYnJhcnkoZ2dwbG90MikNCg0KIyBNT0RFTCBJTlBVVFM6DQoNCiMgVmVjdG9yIHN0b3JpbmcgdGhlIGluaXRpYWwgbnVtYmVyIG9mIHBlb3BsZSBpbiBlYWNoIGNvbXBhcnRtZW50IChhdCB0aW1lc3RlcCAwKQ0KaW5pdGlhbF9zdGF0ZV92YWx1ZXMgPC0gYyhTID0gMTAwMDAwMC0xLCAgICMgdGhlIHdob2xlIHBvcHVsYXRpb24gd2UgYXJlIG1vZGVsbGluZyBpcyBzdXNjZXB0aWJsZSB0byBpbmZlY3Rpb24NCiAgICAgICAgICAgICAgICAgICAgICAgICAgSSA9IDEsICAgICAgICAgICAjIHRoZSBlcGlkZW1pYyBzdGFydHMgd2l0aCBhIHNpbmdsZSBpbmZlY3RlZCBwZXJzb24NCiAgICAgICAgICAgICAgICAgICAgICAgICAgUiA9IDApICAgICAgICAgICAjIHRoZXJlIGlzIG5vIHByaW9yIGltbXVuaXR5IGluIHRoZSBwb3B1bGF0aW9uDQoNCiMgVmVjdG9yIHN0b3JpbmcgdGhlIHBhcmFtZXRlcnMgZGVzY3JpYmluZyB0aGUgdHJhbnNpdGlvbiByYXRlcyBpbiB1bml0cyBvZiBkYXlzXi0xDQpwYXJhbWV0ZXJzIDwtIGMoYmV0YSA9IDAuNCwgICAgICAjIHRoZSBpbmZlY3Rpb24gcmF0ZSwgd2hpY2ggYWN0cyBvbiBzdXNjZXB0aWJsZXMNCiAgICAgICAgICAgICAgICBnYW1tYSA9IDAuMSkgICAgICMgdGhlIHJhdGUgb2YgcmVjb3ZlcnksIHdoaWNoIGFjdHMgb24gdGhvc2UgaW5mZWN0ZWQNCg0KIyBUSU1FU1RFUFM6DQoNCiMgVmVjdG9yIHN0b3JpbmcgdGhlIHNlcXVlbmNlIG9mIHRpbWVzdGVwcyB0byBzb2x2ZSB0aGUgbW9kZWwgYXQNCnRpbWVzIDwtIHNlcShmcm9tID0gMCwgdG8gPSAxMDAsIGJ5ID0gMSkgICAjIGZyb20gMCB0byAxMDAgZGF5cyBpbiBkYWlseSBpbnRlcnZhbHMNCg0KIyBTSVIgTU9ERUwgRlVOQ1RJT046IA0KDQojIFRoZSBtb2RlbCBmdW5jdGlvbiB0YWtlcyBhcyBpbnB1dCBhcmd1bWVudHMgKGluIHRoZSBmb2xsb3dpbmcgb3JkZXIpOiB0aW1lLCBzdGF0ZSBhbmQgcGFyYW1ldGVycw0Kc2lyX21vZGVsIDwtIGZ1bmN0aW9uKHRpbWUsIHN0YXRlLCBwYXJhbWV0ZXJzKSB7ICANCg0KICAgIHdpdGgoYXMubGlzdChjKHN0YXRlLCBwYXJhbWV0ZXJzKSksIHsgICMgdGVsbCBSIHRvIHVucGFjayB2YXJpYWJsZSBuYW1lcyBmcm9tIHRoZSBzdGF0ZSBhbmQgcGFyYW1ldGVycyBpbnB1dHMgICAgDQogICAgICAgIA0KICAgICMgQ2FsY3VsYXRpbmcgdGhlIHRvdGFsIHBvcHVsYXRpb24gc2l6ZSBOICh0aGUgc3VtIG9mIHRoZSBudW1iZXIgb2YgcGVvcGxlIGluIGVhY2ggY29tcGFydG1lbnQpDQogICAgICBOIDwtIFMrSStSDQogICAgICANCiAgICAjIERlZmluaW5nIGxhbWJkYSBhcyBhIGZ1bmN0aW9uIG9mIGJldGEgYW5kIEk6DQogICAgICBsYW1iZGEgPC0gYmV0YSAqIEkvTg0KICAgICAgICANCiAgICAjIFRoZSBkaWZmZXJlbnRpYWwgZXF1YXRpb25zDQogICAgICBkUyA8LSAtbGFtYmRhICogUyAgICAgICAgICAgICAgICMgcGVvcGxlIG1vdmUgb3V0IG9mICgtKSB0aGUgUyBjb21wYXJ0bWVudCBhdCBhIHJhdGUgbGFtYmRhIChmb3JjZSBvZiBpbmZlY3Rpb24pDQogICAgICBkSSA8LSBsYW1iZGEgKiBTIC0gZ2FtbWEgKiBJICAgICMgcGVvcGxlIG1vdmUgaW50byAoKykgdGhlIEkgY29tcGFydG1lbnQgZnJvbSBTIGF0IGEgcmF0ZSBsYW1iZGEsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjIGFuZCBtb3ZlIG91dCBvZiAoLSkgdGhlIEkgY29tcGFydG1lbnQgYXQgYSByYXRlIGdhbW1hIChyZWNvdmVyeSkNCiAgICAgIGRSIDwtIGdhbW1hICogSSAgICAgICAgICAgICAgICAgIyBwZW9wbGUgbW92ZSBpbnRvICgrKSB0aGUgUiBjb21wYXJ0bWVudCBmcm9tIEkgYXQgYSByYXRlIGdhbW1hDQogICAgICANCiAgICAjIFJldHVybiB0aGUgbnVtYmVyIG9mIHBlb3BsZSBpbiB0aGUgUywgSSBhbmQgUiBjb21wYXJ0bWVudHMgYXQgZWFjaCB0aW1lc3RlcCANCiAgICAjIChpbiB0aGUgc2FtZSBvcmRlciBhcyB0aGUgaW5wdXQgc3RhdGUgdmFyaWFibGVzKQ0KICAgIHJldHVybihsaXN0KGMoZFMsIGRJLCBkUikpKSANCiAgICB9KQ0KICANCn0NCg0KIyBNT0RFTCBPVVRQVVQgKHNvbHZpbmcgdGhlIGRpZmZlcmVudGlhbCBlcXVhdGlvbnMpOg0KDQojIFNvbHZpbmcgdGhlIGRpZmZlcmVudGlhbCBlcXVhdGlvbnMgdXNpbmcgdGhlIG9kZSBpbnRlZ3JhdGlvbiBhbGdvcml0aG0NCm91dHB1dCA8LSBhcy5kYXRhLmZyYW1lKG9kZSh5ID0gaW5pdGlhbF9zdGF0ZV92YWx1ZXMsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRpbWVzID0gdGltZXMsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZ1bmMgPSBzaXJfbW9kZWwsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgcGFybXMgPSBwYXJhbWV0ZXJzKSkNCmBgYA0KDQoNCkdlbmVyYXRpbmcgMiBwbG90czoNCmBgYHtyfQ0Kb3V0cHV0X2xvbmcgPC0gbWVsdChhcy5kYXRhLmZyYW1lKG91dHB1dCksIGlkID0gInRpbWUiKSAgICAgICAgICAgICAgICAgICMgdHVybiBvdXRwdXQgZGF0YXNldCBpbnRvIGxvbmcgZm9ybWF0DQoNCiMgQ2FsY3VsYXRpbmcgdGhlIHByb3BvcnRpb24gaW4gZWFjaCBjb21wYXJ0bWVudCBhcyBhIGNvbHVtbiBpbiB0aGUgbG9uZy1mb3JtYXQgb3V0cHV0DQpvdXRwdXRfbG9uZyRwcm9wb3J0aW9uIDwtIG91dHB1dF9sb25nJHZhbHVlL3N1bShpbml0aWFsX3N0YXRlX3ZhbHVlcykNCg0KIyBQbG90IHRoZSBwcm9wb3J0aW9uIG9mIHBlb3BsZSBpbiB0aGUgUywgSSBhbmQgUiBjb21wYXJ0bWVudHMgb3ZlciB0aW1lDQpnZ3Bsb3QoZGF0YSA9IG91dHB1dF9sb25nLCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIyBzcGVjaWZ5IG9iamVjdCBjb250YWluaW5nIGRhdGEgdG8gcGxvdA0KICAgICAgIGFlcyh4ID0gdGltZSwgeSA9IHByb3BvcnRpb24sIGNvbG91ciA9IHZhcmlhYmxlLCBncm91cCA9IHZhcmlhYmxlKSkgKyAgIyBhc3NpZ24gY29sdW1ucyB0byBheGVzIGFuZCBncm91cHMNCiAgZ2VvbV9saW5lKCkgKyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjIHJlcHJlc2VudCBkYXRhIGFzIGxpbmVzDQogIHhsYWIoIlRpbWUgKGRheXMpIikrICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIyBhZGQgbGFiZWwgZm9yIHggYXhpcw0KICB5bGFiKCJQcm9wb3J0aW9uIG9mIHRoZSBwb3B1bGF0aW9uIikgKyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICMgYWRkIGxhYmVsIGZvciB5IGF4aXMNCiAgbGFicyhjb2xvdXIgPSAiQ29tcGFydG1lbnQiLCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjIGFkZCBsZWdlbmQgdGl0bGUgIA0KICAgICAgIHRpdGxlID0gIlByb3BvcnRpb24gc3VzY2VwdGlibGUsIGluZmVjdGVkIGFuZCByZWNvdmVyZWQgb3ZlciB0aW1lIikgKyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIA0KICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAiYm90dG9tIikgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICMgbW92ZSBsZWdlbmQgdG8gdGhlIGJvdHRvbSBvZiB0aGUgcGxvdA0KDQojIENhbGN1bGF0aW5nIHRoZSBlZmZlY3RpdmUgcmVwcm9kdWN0aW9uIG51bWJlciBpbiBhIG5ldyBjb2x1bW4NCm91dHB1dCRyZWZmIDwtIHBhcmFtZXRlcnNbImJldGEiXS9wYXJhbWV0ZXJzWyJnYW1tYSJdICogICAgICAgICAgICAgICAgICAjIFIwID0gYmV0YS9nYW1tYQ0KICAgICAgICAgICAgICAgIG91dHB1dCRTLyhvdXRwdXQkUytvdXRwdXQkSStvdXRwdXQkUikgICAgICAgICAgICAgICAgICAgICMgbXVsdGlwbHkgUjAgYnkgdGhlIHByb3BvcnRpb24gc3VzY2VwdGlibGUNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjIGF0IGVhY2ggdGltZXN0ZXAvZm9yIGVhY2ggcm93DQojIEluIHRoaXMgY2FsY3VsYXRpb24sIHRoZSB0b3RhbCBwb3B1bGF0aW9uIHNpemUgKG91dHB1dCRTK291dHB1dCRJK291dHB1dCRSKSBpcyBjYWxjdWxhdGVkIGZvciBlYWNoIHRpbWVzdGVwDQojIHNvIHRoaXMgYXBwcm9hY2ggd291bGQgYWxzbyBiZSBhcHByb3ByaWF0ZSBpZiB0aGUgcG9wdWxhdGlvbiBzaXplIHZhcmllcyBvdmVyIHRpbWUNCg0KIyBQbG90IFJlZmYNCmdncGxvdChkYXRhID0gb3V0cHV0LCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjIHNwZWNpZnkgb2JqZWN0IGNvbnRhaW5pbmcgZGF0YSB0byBwbG90DQogICAgICAgYWVzKHggPSB0aW1lLCB5ID0gcmVmZikpICsgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIyBhc3NpZ24gY29sdW1ucyB0byBheGVzIGFuZCBncm91cHMNCiAgZ2VvbV9saW5lKCkgKyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjIHJlcHJlc2VudCBkYXRhIGFzIGxpbmVzDQogIHhsYWIoIlRpbWUgKGRheXMpIikrICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIyBhZGQgbGFiZWwgZm9yIHggYXhpcw0KICB5bGFiKCJSZWZmIikgKyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICMgYWRkIGxhYmVsIGZvciB5IGF4aXMNCiAgbGFicyh0aXRsZSA9ICJFZmZlY3RpdmUgcmVwcm9kdWN0aW9uIG51bWJlciBvdmVyIHRpbWUiKSAgICAgICAgICAgICAgICAjIGFkZCBwbG90IHRpdGxlDQpgYGANCg0KDQojIyMgSG93IGRvZXMgUjxzdWI+ZWZmPC9zdWI+IHZhcnkgb3ZlciB0aGUgY291cnNlIG9mIHRoZSBlcGlkZW1pYz8gV2hhdCBkbyB5b3Ugbm90aWNlIGFib3V0IHRoZSBjb25uZWN0aW9uIGJldHdlZW4gdGhlIGNoYW5nZSBpbiBSPHN1Yj5lZmY8L3N1Yj4gYW5kIHRoZSBlcGlkZW1pYyBjdXJ2ZSBvdmVyIHRpbWU/IEluIHBhcnRpY3VsYXIsIGluIHJlbGF0aW9uIHRvIFI8c3ViPmVmZjwvc3ViPiwgd2hlbiBkb2VzIHRoZSBlcGlkZW1pYyBwZWFrIGFuZCBzdGFydCB0byBkZWNsaW5lPw0KDQoNClRoZSBlZmZlY3RpdmUgcmVwcm9kdWN0aW9uIG51bWJlciBpcyBoaWdoZXN0IHdoZW4gZXZlcnlvbmUgaXMgc3VzY2VwdGlibGU6IGF0IHRoZSBiZWdpbm5pbmcsIFI8c3ViPmVmZjwvc3ViPiA9IFI8c3ViPjA8L3N1Yj4uIEF0IHRoaXMgcG9pbnQgaW4gb3VyIGV4YW1wbGUsIGV2ZXJ5IGluZmVjdGVkIGNhc2VzIGNhdXNlcyBhbiBhdmVyYWdlIG9mIDQgc2Vjb25kYXJ5IGluZmVjdGlvbnMuIE92ZXIgdGhlIGNvdXJzZSBvZiB0aGUgZXBpZGVtaWMsIFI8c3ViPmVmZjwvc3ViPiBkZWNsaW5lcyBpbiBwcm9wb3J0aW9uIHRvIHN1c2NlcHRpYmlsaXR5LiANCg0KVGhlIHBlYWsgb2YgdGhlIGVwaWRlbWljIGhhcHBlbnMgd2hlbiBSPHN1Yj5lZmY8L3N1Yj4gZ29lcyBkb3duIHRvIDEgKGluIHRoZSBleGFtcGxlIGhlcmUsIGFmdGVyIDUwIGRheXMpLiBBcyBSPHN1Yj5lZmY8L3N1Yj4gZGVjcmVhc2VzIGZ1cnRoZXIgYmVsb3cgMSwgdGhlIGVwaWRlbWljIHByZXZhbGVuY2UgZ29lcyBpbnRvIGRlY2xpbmUuIFRoaXMgaXMgZXhhY3RseSB3aGF0IHlvdSB3b3VsZCBleHBlY3QsIGdpdmVuIHlvdXIgdW5kZXJzdGFuZGluZyBvZiB0aGUgbWVhbmluZyBvZiBSPHN1Yj5lZmY8L3N1Yj46IG9uY2UgdGhlIGVwaWRlbWljIHJlYWNoZXMgdGhlIHBvaW50IHdoZXJlIGV2ZXJ5IGluZmVjdGVkIGNhc2UgY2Fubm90IGNhdXNlIGF0IGxlYXN0IG9uZSBtb3JlIGluZmVjdGVkIGNhc2UgKHRoYXQgaXMsIHdoZW4gUjxzdWI+ZWZmPC9zdWI+IDwgMSksIHRoZSBlcGlkZW1pYyBjYW5ub3Qgc3VzdGFpbiBpdHNlbGYgYW5kIGNvbWVzIHRvIGFuIGVuZC4NCg0KDQo=