Today we will start investigating size-spectrum dynamics. We will start by looking at the size spectrum of a single species.
Size-spectrum dynamics is like traffic
The best way to think about size-spectrum dynamics is to think of traffic on a highway, except that instead of cars travelling along the road we have fish growing along the size axis, all the way from their egg size to their asymptotic size. Occasionally a car may turn off the highway, or a fish may die. Fish can only enter the highway at the start: their egg size.
For traffic, you would be interested in modelling the traffic density. From the traffic density we can obtain the number of cars in a section of road by multiplying the density there by the length of the section. So the traffic density has units of cars per meter. For fish populations, we will be interested in modelling fish density. The number of fish in a size class is obtained by multiplying the density in that size class by the width of the size class. So the fish density has units of fish per gram.
High traffic density arises in sections of the road where the traffic velocity decreases. Such a decrease can lead to traffic jams. Low traffic density arises in sections where the velocity increases, as familiar when emerging on the other side of a traffic jam. Traffic jams are self-reinforcing phenomena: if there is a decrease in speed somewhere then the density of cars increases which causes a further decrease in speed, leading to an even higher density, and so on.
Similarly, high fish density arises in size classes where the growth rate decreases. A pronounced decrease in growth rate can lead to pronounced peaks in the fish density, similar to a traffic jam. Of course fish density is also controlled by the death rate, with a high death rate leading to a decreased fish density.
To precise, what leads to an increase of fish density is if the rate at which fish grow into the size class is larger than the rate at which they either grow out of the size class or die while they are in the size class. Thus size-spectrum dynamics is the result of the interplay between the death rate and the changes in the growth rate. For the mathematically minded, this interplay is expressed by the partial differential equation \[\frac{\partial}{\partial t}N(w,t) =
-\frac{\partial}{\partial w}\big(N(w,t)g(w,t)\big)
- \mu(w,t)\] where \(N(w,t)\) is the fish density at size \(w\) and time \(t\), \(g(w,t)\) is the growth rate of an individual of size \(w\) at time \(t\) and \(\mu(w,t)\) is its death rate. There is no need for you to understand the mathematical notation.
Size-spectrum dynamics is like the traffic on a highway where cars can leave the highway (fish can die) at any point, but they can only join the highway at its beginning (fish start out at the egg size). To model the size spectrum we therefore also have to describe the rate \(R(t)\) at which eggs are entering the size spectrum, i.e., the rate at which mature fish reproduce.
We will be discussing in detail today what determines the death rate \(\mu(w,t)\), the growth rate \(g(w,t)\) and the rate of reproduction \(R(t)\).
Why study size-spectrum dynamics?
The study of traffic dynamics has had real practical benefits. For example, at least on motorways in Europe, when there is a danger of a traffic jam developing, automatic speed restrictions are imposed at a certain distance in front of the developing slow-moving traffic. For motorists who have not thought about traffic flow, these speed restrictions in places where there is no obvious reason for them are very annoying. However they do indeed avoid the formation of the traffic jam.
Of course we can not directly tell fish to obey limits to their growth rates. However we do have influence on their size-spectrum dynamics through fishing policy. For example if some species experiences stunted growth, like for example the Herring in the Baltic Sea, we could resolve that by reducing their numbers (which increases their growth rate because of reduced competition for food) or by reducing fishing on their prey.
The size-spectrum dynamics in a multi-species ecosystem is extremely complex. We can understand very simplified cases analytically, but in general we need to use numerical simulation to understand the consequences of various interventions.
The mizer package can simulate the size-specrum dynamics. Given the model parameters that enter into the expression of the growth rate, the death rate and the reproductive rate, and an initial fish size spectrum, it simulates the changes in the size spectrum over time according to the above equations.
Of particular interest is the steady state of the size spectrum, where the effects of the death rate and the changes in the growth rate exactly balance in such a way that the size spectrum stays constant over time. We will be looking both at the steady state and at time-varying size spectra today.
Our emphasis will be on understanding the dynamics. We do not just want to learn how to run simulations but we want to use the simulations to develop an intuition for how fish populations behave. We therefore start with very simple models first.
A first example
Let us start by looking at an example. Start RStudio as discussed yesterday and load the following packages:
library(mizer)
library(tidyverse)
library(plotly)
Mizer collects all the parameters describing a size-spectrum model into one object of class MizerParams. You do not need to set up this object by hand but instead there are several wrapper functions in mizer that create the object for you for various types of models, and also many functions for changing specific parameters in a model. We will use the newSheldonParams() function to set up a model describing a single fish species living in a Sheldon power-law community. You already discussed yesterday the fact that Sheldon discovered that the community spectrum is approximately described by a power law.
The newSheldonParams() function has many arguments that allow you to specify parameters for the fish species as well as for the community, but all these arguments have default values, so we can simply call the function without specifying those arguments. We will only specify the Sheldon exponent of the background community
params <- newSheldonParams(lambda = 2.05)
The search volume exponent q has been set to 0.8 so as to lead to the desired community exponent lambda = 2.05.
You can ignore the message that the function prints for now. It will make sense once we have discussed predation later. The function returns a MizerParams object and we have assigned that to the variable params. We will be explaining more about this model as we go along.
Steady state spectrum
The params object also contains an initial size spectrum that is close to the steady state of the model. The steady state is the state where in each size class the inflow of individuals through growth exactly balances the outflow of individuals through growth and death. If we start close to the steady state then usually if we simulate the size-spectrum dynamics for a while the system will evolve closer and closer to the steady state.
To get to the steady state we use the steady() function. The result of that function is again a MizerParams object but now with an initial size spectrum that has evolved to be very close to the steady state.
params <- steady(params)
Steady state was reached before 7.5 years.
We can plot the size spectrum with the plotSpectra() function.
plotSpectra(params, power = 0)

The power = 0 argument to the plotSpectra() function specifies that we want to plot the number density, rather than for example the biomass density.
The green line represents the number density of the background community as a function of size. The reason it is labelled as “Plankton” in the plot legend is just because in most models the background spectrum represents the plankton. In our model however it represents the entire marine community in which our foreground species finds itself. The green line is a straight line with slope -2.05. Thus the abundance density is proportional to \(w^{-2.05}\).
The other line represents the number density of our single species, which by default is just named unimaginatively “1”. We see that it is a straight line initially, but then has a bump before declining rapidly at large sizes. We will discuss in a short while what causes that shape.
The initial slope of the species number density is negative, which means that there are fewer larger fish than smaller fish. That is of course obvious: some fish die while they are growing up, so there are fewer fish in larger size classes.
Exercise 1
Now it is time for you to do the first exercise to use the commands you have just learned about. For this purpose you should now open the R notebook file “exercises_single-species_size-spectrum_dynamics” and read it up to the place where it shows the first exercise. Then you put your R code for the exercise straight into the code chunks in that notebook and evaluate them there. When you are satisfied with your solution, come back to this document and continue reading.
Numbers
While the plotSpectra() function gives us a plot of the number density, it would be nice if we could get at the actual numbers. The number density of the steady state is stored in the params object in the initial_n slot. This is accessed as follows:
n <- params@initial_n
As you can see in the “Environment” pane in RStudio, n is a matrix with 1 row and 251 columns. The one row corresponds to the one species. In a multispecies model there would be one row for each species, holding the number density for that species. The 251 columns are for the number densities in each of the 251 size classes. In fact, n is a named array, i.e., each row and each column has names. These we can extract with the dimnames() function.
dimnames(n)
$sp
[1] "1"
$w
[1] "0.001" "0.00105" "0.0011" "0.00115" "0.0012" "0.00126" "0.00132"
[8] "0.00138" "0.00145" "0.00151" "0.00158" "0.00166" "0.00174" "0.00182"
[15] "0.00191" "0.002" "0.00209" "0.00219" "0.00229" "0.0024" "0.00251"
[22] "0.00263" "0.00275" "0.00288" "0.00302" "0.00316" "0.00331" "0.00347"
[29] "0.00363" "0.0038" "0.00398" "0.00417" "0.00437" "0.00457" "0.00479"
[36] "0.00501" "0.00525" "0.0055" "0.00575" "0.00603" "0.00631" "0.00661"
[43] "0.00692" "0.00724" "0.00759" "0.00794" "0.00832" "0.00871" "0.00912"
[50] "0.00955" "0.01" "0.0105" "0.011" "0.0115" "0.012" "0.0126"
[57] "0.0132" "0.0138" "0.0145" "0.0151" "0.0158" "0.0166" "0.0174"
[64] "0.0182" "0.0191" "0.02" "0.0209" "0.0219" "0.0229" "0.024"
[71] "0.0251" "0.0263" "0.0275" "0.0288" "0.0302" "0.0316" "0.0331"
[78] "0.0347" "0.0363" "0.038" "0.0398" "0.0417" "0.0437" "0.0457"
[85] "0.0479" "0.0501" "0.0525" "0.055" "0.0575" "0.0603" "0.0631"
[92] "0.0661" "0.0692" "0.0724" "0.0759" "0.0794" "0.0832" "0.0871"
[99] "0.0912" "0.0955" "0.1" "0.105" "0.11" "0.115" "0.12"
[106] "0.126" "0.132" "0.138" "0.145" "0.151" "0.158" "0.166"
[113] "0.174" "0.182" "0.191" "0.2" "0.209" "0.219" "0.229"
[120] "0.24" "0.251" "0.263" "0.275" "0.288" "0.302" "0.316"
[127] "0.331" "0.347" "0.363" "0.38" "0.398" "0.417" "0.437"
[134] "0.457" "0.479" "0.501" "0.525" "0.55" "0.575" "0.603"
[141] "0.631" "0.661" "0.692" "0.724" "0.759" "0.794" "0.832"
[148] "0.871" "0.912" "0.955" "1" "1.05" "1.1" "1.15"
[155] "1.2" "1.26" "1.32" "1.38" "1.45" "1.51" "1.58"
[162] "1.66" "1.74" "1.82" "1.91" "2" "2.09" "2.19"
[169] "2.29" "2.4" "2.51" "2.63" "2.75" "2.88" "3.02"
[176] "3.16" "3.31" "3.47" "3.63" "3.8" "3.98" "4.17"
[183] "4.37" "4.57" "4.79" "5.01" "5.25" "5.5" "5.75"
[190] "6.03" "6.31" "6.61" "6.92" "7.24" "7.59" "7.94"
[197] "8.32" "8.71" "9.12" "9.55" "10" "10.5" "11"
[204] "11.5" "12" "12.6" "13.2" "13.8" "14.5" "15.1"
[211] "15.8" "16.6" "17.4" "18.2" "19.1" "20" "20.9"
[218] "21.9" "22.9" "24" "25.1" "26.3" "27.5" "28.8"
[225] "30.2" "31.6" "33.1" "34.7" "36.3" "38" "39.8"
[232] "41.7" "43.7" "45.7" "47.9" "50.1" "52.5" "55"
[239] "57.5" "60.3" "63.1" "66.1" "69.2" "72.4" "75.9"
[246] "79.4" "83.2" "87.1" "91.2" "95.5" "100"
The names of the columns are the weight in grams at the start of each size class. Notice how R displays long vectors by breaking them across many lines and starting each line with a number in brackets. That number is the index of the first value in that row. So for example we see that the 151st size bracket starts at 1 gram. The number density in the size class between 1 gram and 1.05 grams is
n[1, 151]
[1] 0.0001868972
It is important to realise that this is not the number of fish in the size class, but the number density. To get the number of fish we have to multiply the number by the width of the size class. Conveniently those widths are also stored in the params object, in the dw slot. So the number of fish in the 151st size class is
(n * params@dw)[1, 151]
[1] 8.808192e-06
You may be surprised at the small number if you interpret it as the number of fish between 1 gram and 1.05 gram in the entire ocean. However it looks more reasonable if it is the average number per square meter of sea. For more of a discussion of this issue of workinv with numbers per area, numbers per volume or numbers for the entire system see https://sizespectrum.org/mizer/dev/reference/setParams.html#units-in-mizer
Exercise 2
Go back to your exercise notebook for this tutorial and answer exercise 2 before reading on.
Biomass spectra
Without the power argument (or with power = 1 which is the default) the plotSpectra() function plots the biomass density as a function of size.
plotSpectra(params)

Now the green line representing the biomass density of the background has a slope of -1.05.
The initial slope of the species biomass density is negative, meaning that the biomass density decreases with size. This means that even though the individual fish of course gain biomass as they grow up, there is so much death among the larvae and juvenile fish that the total biomass of any cohort nevertheless decreases as it grows up. We will explain the reason for this later when we discuss predation mortality.
We can also plot the Sheldon spectrum, i.e., the biomass density as a function of the log weight instead of the weight, by supplying the argument power = 2 to plotSpectra().
plotSpectra(params, power = 2)

This now shows an approximately constant biomass density as a function of log size (the slope of the green line is -0.05). The biomass density of the species as a function of log size initially increases. So if binned in logarithmically-sized bins the biomass in each bin will initially increase, until it starts decreasing close to the maximum size of the species.
It may have been a bit confusing that we displayed the same size spectrum in three different ways. But it is important to be aware of this because in the literature you will see all different conventions being used, so if you see a plot of a size spectrum you always need to ask yourself exactly which density is being shown.
We can obtain the biomass density in a size class from the number density by multiplying the number density by the weight of the individuals in the size class. Of course there is a bit of error here because not all fish in the size class have the same weight, but with the small size classes that we use in mizer, the error is not too important. So we calculate
biomass_density <- n * params@w
The total biomass in each size class we obtain by multiplying the biomass density in each size class by the width of each size class
biomass <- biomass_density * params@dw
For example the biomass of fish between 1 gram and 1.05 grams is
biomass[151]
[1] 8.808192e-06
Next we will discuss the shape of the species size-spectrum in more detail.
Allometric rates
The first striking feature of the species size-spectrum, in all its representations, is that for small fish (larvae and juveniles) it is given by a straight line. This due to the allometric scaling of the physiological rates. The other striking feature is the bulge at around maturity size, which we will discuss in the section on reproduction.
First of all, as Mariella already mentioned yesterday, the metabolic rate, i.e., the rate at which an organism expends energy on its basic metabolic needs, scales as a power of the organisms’s body size, and the power is about \(p = 3/4\).
Because this energy needs to be supplied by consumption of food, it is natural to assume that also the consumption rate scales allometrically with a power of 3/4. When the consumption is greater than the metabolic cost then the excess leads to growth. Hence the growth rate too scales allometrically with power \(p = 3/4\).
Finally, the death rate of organisms tends to scale allometrically with a power of \(p - 1 = 3/4 - 1 = -1/4\). The death rate experienced by larger individuals is smaller than that of small individuals. Again this is confirmed by many observations.
It is a result of the mathematics that if the growth and death rates scale allometrically with exponents \(p\) and \(1-p\) respectively, for some metabolic exponent \(p\), that the number density at steady state is also a power law, i.e., a straight line on the log-log plot.
Let us check that in our model the physiological rates are indeed power laws, at least for the small sizes. We can get the growth rate with the getEGrowth() function. We assign the result to a variable that we name growth_rate.
growth_rate <- getEGrowth(params)
You can again see in the “Environment” pane that this is a matrix with one row for the one species and 251 columns for the 251 size classes. So for example the growth rate at size 1 gram is
growth_rate[1, 151]
[1] 8.40452
(because we had seen that the 151st size class starts at 1 gram). This is the per-capita growth rate, measured in grams per year.
We would like to make a log-log plot of the growth rate against size to check that it gives a straight line. We will use ggplot() for that purpose. As you saw already yesterday, ggplot() likes to work with data frames instead of named matrices, so we first convert the matrix into a data frame with the melt() function.
growth_rate_frame <- melt(growth_rate)
You can see in the “£nvironment” pane that the new variable that we called growth_rate_frame is a data frame with 251 observations of 3 variables. The 251 observations correspond to the 251 size classes. The 3 variables are called
names(growth_rate_frame)
[1] "sp" "w" "value"
They are the species sp, the size w, and the value which contains the growth_rate. This data frame we can pass to ggplot(), using techniques you already learned yesterday.
p <- ggplot(growth_rate_frame) +
geom_line(aes(x = w, y = value)) +
scale_x_log10() +
scale_y_log10() +
labs(x = "Weight [g]",
y = "Growth rate [g/year]")
p

Note how we linked the x axis to the w variable and the y axis to the value variable.
We see that at least up to a size of a few grams the line is straight. Let’s isolate the growth rate for those smaller sizes
g_small_fish <- filter(growth_rate_frame, w <= 10)
and fit a linear model
lm(log(g_small_fish$value) ~ log(g_small_fish$w))
Call:
lm(formula = log(g_small_fish$value) ~ log(g_small_fish$w))
Coefficients:
(Intercept) log(g_small_fish$w)
2.129 0.750
The slope of the line is indeed 0.75 = 3/4. In fact, the above shows that for juveniles \[\log(g(w)) = 2.129 + \frac34 \log(w)\] and thus \[g(w) = g_0\ w^p = 2.129\ w^{3/4}.\]
Of course in a real model, the growth rate would not so exactly follow a power law, due to variations in the growth rate due to variations in food availability, for example.
Exercise 3
Now over to you. Do exercise 3 in the exercise notebook. Use the methods you have just seen to make a log-log plot of the mortality rate. You can get the mortality rate with the getMort() function. Then fit a linear model and thus determine that the mortality rate is \[\mu(w) = \mu_0\ w^{p-1} = 1.909\ w^{-1/4}.\]
Slope of juvenile spectrum
We have seen that for juvenile fish the growth rate and the death rate are both power laws with exponents \(p=3/4\) and \(p-1=-1/4\) respectively and then by solving a differential equation we can derive that the juvenile spectum also follows a power law: \[N(w) = N_0\ w^{-\mu_0/g_0 - p}\]
I can’t do the maths with you (and you probably don’t want me to anyway), but we can check this claim numerically. Let’s look at the spectrum up to 10 grams. By now we know how to do this. We first convert the number density matrix n into a dataframe and then filter out all observations that do not have \(w\leq 10\). The resulting data frame we pass to ggplot() and ask it to plot a line on log-log axes.
nf <- melt(n) %>%
filter(w <= 10)
ggplot(nf) +
geom_line(aes(x = w, y = value)) +
scale_x_log10() +
scale_y_log10() +
labs(x = "Weight [g]",
y = "Number density [1/g]")

That confirms what we had seen earlier, that for fish less than 10 grams the number density is a power law. To determine the exponent of the power law we need the slope of that straight line in the log-log plot, and the easiest way to do that is to fit a linear model to the log variables:
lm(log(nf$value) ~ log(nf$w))
Call:
lm(formula = log(nf$value) ~ log(nf$w))
Coefficients:
(Intercept) log(nf$w)
-8.585 -1.556
The mathematics claimed that the exponent should be \(-\mu_0 / g_0 - p\). We have already observed that \(\mu_0 = 1.909\) and \(g_0 = 2.129\) so we get
-1.909 / 2.129 - 3/4
[1] -1.646665
That is not quite the result of the linear model fit, but that is the nature of numerical calculations: one gets discretisation errors and rounding errors.
Reproduction
Now that we understand the shape of the size spectrum for the juvenile fish, let us try to understand the bulge that follows. The increase of abundance that we see at around the maturity size of our species is due to a drop in growth rate at that size. This in turn is due to the fact that the mature fish invests some of its energy income into reproduction.
The proportion of the available energy that is invested into reproduction is stored in the psi slot of the params object. As so many of the other quantities in mizer, it is a matrix with one row for each species and once column for each size class. So we can plot it by melting the matrix into a data frame and then using this in ggplot().
ggplot(melt(params@psi)) +
geom_line(aes(x = w, y = value))

How was this maturity curve specified? There are four species parameters involved: * the maturity size w_mat at which 50% of the individuals are mature. * the size w_mat25 at wich 25% of the individuals are mature. * the asymptotic size w_inf at which an organism invests 100% of its income into reproduction and thus growth is zero. * an exponent m that determines how the proportion that an individual invests into reproduction scales with its size.
Such species parameters are contained in the species_params slot of the params object.
params@species_params
As you can see, there are a lot of other species parameters, some of which we will talk about later. For now let’s just select the 4 parameters we are interested in.
select(params@species_params, w_mat, w_mat25, w_inf, m)
Effect of change in maturity curve
Let us investigate what happens when we change the maturity curve. Let’s assume the maturity size is actually 40 grams and the size at which 25% of individuals is mature is 30 grams. Let us change the values in the species_params data frame. But first we make a copy of the params object so that we can keep the old version around unchanged.
params_changed_maturity <- params
In this copy we now change the species paramters
params_changed_maturity@species_params$w_mat <- 40
params_changed_maturity@species_params$w_mat25 <- 30
select(params_changed_maturity@species_params, w_mat, w_mat25, w_inf, m)
This has not yet changed the params@psi slot in the params object yet. For that we need to call the setReproduction() function.
params_changed_maturity <- setReproduction(params_changed_maturity)
Now the maturity curve has changed, which we can verify by plotting it
ggplot(melt(params_changed_maturity@psi)) +
geom_line(aes(x = w, y = value))

At this point let’s take a little break and learn how to draw two curves in the same graph. How can we see the old maturity curve and the new maturity curve in the same plot? First we create the data frames we would need for the separate plots
psif <- melt(params@psi)
psif_changed_maturity <- melt(params_changed_maturity@psi)
Then we add an extra column to each dataframe describing it
psif$type = "original"
psif_changed_maturity$type = "changed"
Then we bind the two data frames together
psif_combined <- rbind(psif, psif_changed_maturity)
and send that combined data frame to ggplot()
ggplot(psif_combined) +
geom_line(aes(x = w, y = value, colour = type))

This change in the maturity curve of course implies a change in the growth rates.
Exercise 4
Make a plot showing the growth rates of the original model and of the model with the changed maturity curve.
Next let us look how the steady state spectrum has changed. We first need to run the changed model to steady state
params_changed_maturity <- steady(params_changed_maturity)
Steady state was reached before 15 years.
We use the same technique as above to plot the steady-state spectra of both models on top of each other.
nf <- melt(params@initial_n)
nf_changed_maturity <- melt(params_changed_maturity@initial_n)
nf$type <- "original"
nf_changed_maturity$type <- "changed"
nf_combined <- rbind(nf, nf_changed_maturity)
ggplot(nf_combined) +
geom_line(aes(x = w, y = value, colour = type)) +
scale_x_log10() +
scale_y_log10() +
labs(x = "Weight [g]",
y = "Number density [1/g]")

As expected, the bump happens later due to the larger maturity size and it is less pronounced, because the maturity curve is less steep.
Reproductive efficiency
So what happens with the energy that is invested into reproduction? It leads to spawning and thus the influx of new individuals at the egg size. This conversion of energy invested into reproduction into egg biomass is inefficient. Firstly much energy is spent on things like migration to spawning grounds, rather than on production of gonadic mass. Secondly, only a small proportion of eggs that are produced are viable and hatch into larvae.
In fact, in order for the population to be at steady state, the reproductive efficiency has to have a particular value. If it were higher, the population would increase, if it was lower, the population would decrease with time. The steady() function has set the reproductive efficiency to just the right value and has stored it in the erepro species parameter.
params@species_params$erepro
[1] 0.205755
The model with the changed maturity curve leads to a different rate of investment into reproduction and thus needs a slightly different reproductive efficiency to remain at steady state:
params_changed_maturity@species_params$erepro
[1] 0.1935936
This is the reproductive efficiency at steady state. When the population deviates from the steady state, for example due to a change in fishing, the reproductive efficiency can be set to change according to a Beverton-Holt stock-recruitment curve. We will discuss this again later.
Effect of decreased prey availability
The energy income for a fish comes from predation on its prey. If there is less prey, the fish consumes less and thus its growth rate will decrease. Let us investigate this by artificially removing some prey.
Below we decrease the community spectrum by a factor of 10 in the size range from 1mg to 10mg. We again create a new parameter object to be able to keep the old one around
params_starved <- params
size_range <- params@w_full > 10^-3 & params@w_full < 10^-2
params_starved@initial_n_pp[size_range] <- params@initial_n_pp[size_range] / 10
plotSpectra(params_starved)

That is of course quite a dramatic intervention, and so should allow us to clearly see its effect on the steady-state size distribution of our species.
params_starved <- steady(params_starved)
Steady state was reached before 15 years.
plotSpectra(params_starved, power = 2)

As expected, the lack of food and the resulting slow-down in growth leads to a traffic jam: a peak in the biomass density. This slow-down occurs at a size that is about a factor of 100 larger than the size at which food is reduced. Why this is we will discuss in the next section. But first investigate what happens when the prey abundance is increased instead of decreased.
Exercise 5
Plot the steady state biomass density in our model when the community abundance is increased by a factor of 10 in the size range from 1mg to 10mg.
Predation
It is now time to discuss the important issue of predation. It is through predation that the fish obtains the energy it needs to maintain its metabolism, to grow and to invest in reproduction. So it is important how we model this predation.
The easiest case in which to understand predation is to imagine a filter feeding fish, swimming around with its mouth open. Clearly the amount of food it takes in is determined by four things:
- the density of prey in the water,
- how much volume of water the fish is able to filter, which will depend on how fast it swims as well as on its gape size.
- what part of this prey the fish is able to filter out of the water, which will be limited by its gape size and by how fine its gill rakers are,
- how fast it can digest the food. If it can filter the prey faster than it can digest, it will have to start letting prey go uneaten.
For a more active hunter the situation will be similar. The rate at which it predates will depend on four things:
- the density of prey in the water
- the volume of water that the fish patrols and in which it will be able to seek out its prey. This may depend on things like radius of vision.
- which of this detected prey the fish is able to catch, which will depend on its mouth size but also on its agility and skill as well as on the defensive mechanisms of the prey.
- how fast it can digest the food.
Of these four factors, we have of course already been discussing the density of prey. In the next section we will discuss the ability to filter out or catch prey of particular sizes, which we model via the predation kernel. In the section after that we will discuss the search volume and then in the following section the maximum consumption rate.
The predation kernel
Fish will be particularly good at catching prey in a specific range of sizes, smaller than themselves. This is encoded in the size-spectrum model by the predation kernel. Let us take a look at the predation kernel in our model. We can obtain it with the function getPredKernel().
pred_kernel <- getPredKernel(params)
This is a large three-dimensional array (predator species x predator size x prey size). We extract the kernel of a predator of size 10g (using that we remember that this is in size class 201)
pred_kernel_10 <- pred_kernel[, 201, , drop = FALSE]
The drop = FALSE option is there to prevent R from dropping any of the array dimensions. We can now plot this as usual
ggplot(melt(pred_kernel_10)) +
geom_line(aes(x = w_prey, y = value)) +
scale_x_log10()

We see that the predator of size 10g likes to feed on prey that is about a factor 100 smaller than itself, but also feeds on other sizes, just with reduced preference. The preferred predator/prey size ratio is determined by the species parameter beta and the width of the feeding kernel, i.e., how fussy the predator is regarding their prey size, is determined by the species parameter sigma. In our model these have the values
select(params@species_params, beta, sigma)
Let us change the preferred predator/prey mass ratio from 100 to 1000. As usual, we first create a copy of the parameter object before making changes. After changing the species parameters we have to call setPredKernel() to actually change the predation kernel in the model. Then, after changing the predation kernel, we have to determine the new steady state with steady(). Finally we plot the resulting spectrum.
params_pk <- params
params_pk@species_params$beta <- 1000
params_pk <- setPredKernel(params_pk)
Let’s make a plot to see that the predation kernel has indeed changed.
getPredKernel(params_pk)[, 201, , drop = FALSE] %>%
melt() %>%
ggplot() +
geom_line(aes(x = w_prey, y = value)) +
scale_x_log10()

If we now again reduce the prey in the size range from 1mg to 10mg as before, we now expect this to produce a peak in the biomass spectrum somewhere between 1g and 10g. Let’s check.
params_pk@initial_n_pp <- params_starved@initial_n_pp
params_pk <- steady(params_pk)
Steady state was reached before 15 years.
plotSpectra(params_pk, power = 2)

Yes, as expected.
For details of how beta and sigma parametrise the predation kernel, see https://sizespectrum.org/mizer/dev/reference/lognormal_pred_kernel.html#details. For information on how to change the predation kernel, see https://sizespectrum.org/mizer/dev/reference/setPredKernel.html#setting-predation-kernel
It is very important not to confuse the prey preference with the diet. Just because a predator might prefer to feed on prey of a particular size if it had free choice does not mean that it actually feeds predominantly on such prey. The actual diet of the fish depends also on the availability of prey. Because smaller prey are more abundant, the realised predator/prey mass ratio in the diet will be smaller than the preferred predator/prey mass ratio. This is particularly important when estimating the predation kernel from stomach data.
Exercise 6
This exercise gives you a different set of predation kernel parameters to investigate.
Search volume
Next we consider the factor that models the volume of water a filter feeder is able to filter in a certain amount of time, or the volume of water a forage fish is able to patrol in a certain amount of time. This is difficult to model fron first principles, although people have tried to argue in terms of swimming speeds of fish. We will simply assume that this search volume rate is also an allometric rate. Let \(\gamma(w)\) denote this rate for a predator of size \(w\). The we assume that \[\gamma(w) = \gamma_0\ w^q\] for some exponent \(q\). We know that a fish needs to consume prey at a rate that scales with its body size to the power p, with p about 3/4. We also know that the prey density will be approximately described by the Sheldon power law, i.e., that \(N(w) = N_0\ w^{-\lambda}\) with \(\lambda\). A bit of maths then says that \[q = 2 - \lambda + n\] This explains the message you got when you created the params object with a certain choice of \(\lambda\): mizer chose the search volume exponent automtically according to this formula. In the real world evolution will have made sure that the fish will have developed a feeding strategy that allows it to cover its metabolic costs, and thus leads to that search volume exponent of \(q\). Clearly filter feeders have taken a very different route to this than forage fish, but the result is the same.
Let us see what effect changing the coefficient \(\gamma_0\) in the search volume rate has. Its current value in our model is
params@species_params$gamma
[1] 3692.436
We change that with setSearchVolume() and find the new steady state.
params_new_gamma <- params
params_new_gamma@species_params$gamma <- 2000
params_new_gamma <- setSearchVolume(params_new_gamma) %>%
steady()
Steady state was reached before 15 years.
We can see the effect in the growth curve of our species. In the original model it looks as follows:
plotGrowthCurves(params, species = "1")

In the modified model it looks like
plotGrowthCurves(params_new_gamma, species = "1")

Exercise 7
What effect will this change in growth rate have on the slope of the juvenile spectrum? Will it be steeper or shallower? Make the plot of the spectrum to see.
Feeding level
A predator will have a maximum intake rate. It will simple not be able to utilise food at a faster rate than its maximum intake rate. Of course in practice it will not feed at the maximum intake rate because of limited availability of prey. We describe this by the feeding level which is the proportion of its maximum intake rate at which the predator is actually taking in prey.
In our simple model this feeding level is constant.
plotFeedingLevel(params)

In the model with the reduced search volume the feeding level will be lower
plotFeedingLevel(params_new_gamma)

Our model is taking an allometric form for the maximum intake rate \(h(w)\) as a function of predator size \(w\): \(h(w) = h\ w^n\). The current value of the coefficient \(h\) is
params@species_params$h
[1] 51.6855
We can change the maximum intake rate with setIntakeMax().
Mortality
Death from predation
Of course growth of the predator is only one aspect of predation. The other is the death of the prey. Growth and mortality are coupled. Increased growth of one class of individuals will necessitate increased death of another. There is no free lunch.
Once we have specified the predation parameters, these parameters determine both the growth of predators but also the mortality rate of prey. So we don’t have to introduce new paramters in this section.
Background mortality
In addition to mortality caused by predation from other fish, there will be some mortality from other causes. This could be predation from animals that we have not included in our model, like sea birds or mamals, or it could be death from old age (senescent death) or disease. Mizer allows setting of background death with setBMort().
Fishing mortality
The cause of mortality that is most under our control is mortality from fishing. You can see how fishing is set up in mizer at https://sizespectrum.org/mizer/dev/reference/setFishing.html#setting-fishing. Here we only look at a simple example: we introduce fishing on our species only for fish above 30 grams. All fish greater than 30 grams will be exposed to the same fishing mortality. We call this kind of fishing selectivity “knife_edge” selectivity. Mizer can deal with more general selectivity curves, like sigmoidal or doubly sigmoidal.
params_fishing <- params
params_fishing@species_params$sel_func <- "knife_edge"
params_fishing@species_params$knife_edge_size <- 30
params_fishing <- setFishing(params_fishing)
We now need to specify the fishing effort and can then find and plot the steady state
params_fishing@initial_effort <- 1
params_fishing <- steady(params_fishing)
Steady state was reached before 15 years.
plotSpectra(params_fishing, power = 2)

Outlook
The fish species we have studied had unlimited food and constant mortality. That of course is very unrealistic. In reality, food will become scarce when the fish population increases too much. Also the number of predators will grow. This will lead to interesting and important non-linear effects that we will study in the next tutorial notebook.
LS0tCnRpdGxlOiAiU2luZ2xlLXNwZWNpZXMgc2l6ZS1zcGVjdHJ1bSBkeW5hbWljcyIKYXV0aG9yOiAiR3VzdGF2IERlbGl1cyIKb3V0cHV0OiAKICBodG1sX25vdGVib29rOgogICAgdG9jOiBUUlVFCi0tLQoKVG9kYXkgd2Ugd2lsbCBzdGFydCBpbnZlc3RpZ2F0aW5nIHNpemUtc3BlY3RydW0gZHluYW1pY3MuIFdlIHdpbGwgc3RhcnQgYnkKbG9va2luZyBhdCB0aGUgc2l6ZSBzcGVjdHJ1bSBvZiBhIHNpbmdsZSBzcGVjaWVzLgoKIyBTaXplLXNwZWN0cnVtIGR5bmFtaWNzIGlzIGxpa2UgdHJhZmZpYwoKVGhlIGJlc3Qgd2F5IHRvIHRoaW5rIGFib3V0IHNpemUtc3BlY3RydW0gZHluYW1pY3MgaXMgdG8gdGhpbmsgb2YgdHJhZmZpYwpvbiBhIGhpZ2h3YXksIGV4Y2VwdCB0aGF0IGluc3RlYWQgb2YgY2FycyB0cmF2ZWxsaW5nIGFsb25nIHRoZSByb2FkCndlIGhhdmUgZmlzaCBncm93aW5nIGFsb25nIHRoZSBzaXplIGF4aXMsIGFsbCB0aGUgd2F5IGZyb20gdGhlaXIgZWdnIHNpemUKdG8gdGhlaXIgYXN5bXB0b3RpYyBzaXplLiBPY2Nhc2lvbmFsbHkgYSBjYXIgbWF5IHR1cm4gb2ZmIHRoZSBoaWdod2F5LCBvcgphIGZpc2ggbWF5IGRpZS4gRmlzaCBjYW4gb25seSBlbnRlciB0aGUgaGlnaHdheSBhdCB0aGUgc3RhcnQ6IHRoZWlyIGVnZyBzaXplLgoKRm9yIHRyYWZmaWMsIHlvdSB3b3VsZCBiZSBpbnRlcmVzdGVkIGluIG1vZGVsbGluZyB0aGUgdHJhZmZpYyBkZW5zaXR5LiAKRnJvbSB0aGUgdHJhZmZpYyBkZW5zaXR5IHdlIGNhbiBvYnRhaW4gdGhlIG51bWJlciBvZiBjYXJzIGluIGEgc2VjdGlvbiBvZgpyb2FkIGJ5IG11bHRpcGx5aW5nIHRoZSBkZW5zaXR5IHRoZXJlIGJ5IHRoZSBsZW5ndGggb2YgdGhlIHNlY3Rpb24uIFNvIHRoZQp0cmFmZmljIGRlbnNpdHkgaGFzIHVuaXRzIG9mIGNhcnMgcGVyIG1ldGVyLiBGb3IgZmlzaCBwb3B1bGF0aW9ucywgd2UKd2lsbCBiZSBpbnRlcmVzdGVkIGluIG1vZGVsbGluZyBmaXNoIGRlbnNpdHkuIFRoZSBudW1iZXIgb2YgZmlzaCBpbiBhIHNpemUKY2xhc3MgaXMgb2J0YWluZWQgYnkgbXVsdGlwbHlpbmcgdGhlIGRlbnNpdHkgaW4gdGhhdCBzaXplIGNsYXNzIGJ5IHRoZSAKd2lkdGggb2YgdGhlIHNpemUgY2xhc3MuIFNvIHRoZSBmaXNoIGRlbnNpdHkgaGFzIHVuaXRzIG9mIGZpc2ggcGVyIGdyYW0uCgpIaWdoIHRyYWZmaWMgZGVuc2l0eSBhcmlzZXMgaW4gc2VjdGlvbnMgb2YgdGhlIHJvYWQgd2hlcmUgdGhlIHRyYWZmaWMKdmVsb2NpdHkgZGVjcmVhc2VzLiBTdWNoIGEgZGVjcmVhc2UgY2FuIGxlYWQgdG8gdHJhZmZpYyBqYW1zLiBMb3cKdHJhZmZpYyBkZW5zaXR5IGFyaXNlcyBpbiBzZWN0aW9ucyB3aGVyZSB0aGUgdmVsb2NpdHkgaW5jcmVhc2VzLCBhcyAKZmFtaWxpYXIgd2hlbiBlbWVyZ2luZyBvbiB0aGUgb3RoZXIgc2lkZSBvZiBhIHRyYWZmaWMgamFtLiBUcmFmZmljIGphbXMKYXJlIHNlbGYtcmVpbmZvcmNpbmcgcGhlbm9tZW5hOiBpZiB0aGVyZSBpcyBhIGRlY3JlYXNlIGluIHNwZWVkIHNvbWV3aGVyZQp0aGVuIHRoZSBkZW5zaXR5IG9mIGNhcnMgaW5jcmVhc2VzIHdoaWNoIGNhdXNlcyBhIGZ1cnRoZXIgZGVjcmVhc2UgaW4gc3BlZWQsCmxlYWRpbmcgdG8gYW4gZXZlbiBoaWdoZXIgZGVuc2l0eSwgYW5kIHNvIG9uLiAKClNpbWlsYXJseSwgaGlnaCBmaXNoIGRlbnNpdHkgYXJpc2VzIGluIHNpemUgY2xhc3NlcyB3aGVyZSB0aGUgZ3Jvd3RoIHJhdGUgZGVjcmVhc2VzLgpBIHByb25vdW5jZWQgZGVjcmVhc2UgaW4gZ3Jvd3RoIHJhdGUgY2FuIGxlYWQgdG8gcHJvbm91bmNlZCBwZWFrcyBpbiB0aGUgCmZpc2ggZGVuc2l0eSwgc2ltaWxhciB0byBhIHRyYWZmaWMgamFtLiBPZiBjb3Vyc2UgZmlzaCBkZW5zaXR5IGlzIGFsc28KY29udHJvbGxlZCBieSB0aGUgZGVhdGggcmF0ZSwgd2l0aCBhIGhpZ2ggZGVhdGggcmF0ZSBsZWFkaW5nIHRvIGEgZGVjcmVhc2VkCmZpc2ggZGVuc2l0eS4gCgpUbyBwcmVjaXNlLCB3aGF0IGxlYWRzIHRvIGFuIGluY3JlYXNlIG9mIGZpc2ggZGVuc2l0eSBpcyBpZiB0aGUgcmF0ZSBhdAp3aGljaCBmaXNoIGdyb3cgaW50byB0aGUgc2l6ZSBjbGFzcyBpcyBsYXJnZXIgdGhhbiB0aGUgcmF0ZSBhdCB3aGljaCB0aGV5CmVpdGhlciBncm93IG91dCBvZiB0aGUgc2l6ZSBjbGFzcyBvciBkaWUgd2hpbGUgdGhleSBhcmUgaW4gdGhlIHNpemUgY2xhc3MuClRodXMgc2l6ZS1zcGVjdHJ1bSBkeW5hbWljcyBpcyB0aGUgcmVzdWx0IG9mIHRoZSBpbnRlcnBsYXkgYmV0d2Vlbgp0aGUgZGVhdGggcmF0ZSBhbmQgdGhlIGNoYW5nZXMgaW4gdGhlIGdyb3d0aCByYXRlLiBGb3IgdGhlIG1hdGhlbWF0aWNhbGx5Cm1pbmRlZCwgdGhpcyBpbnRlcnBsYXkgaXMgZXhwcmVzc2VkIGJ5IHRoZSBwYXJ0aWFsIGRpZmZlcmVudGlhbCBlcXVhdGlvbgokJFxmcmFje1xwYXJ0aWFsfXtccGFydGlhbCB0fU4odyx0KSA9IAotXGZyYWN7XHBhcnRpYWx9e1xwYXJ0aWFsIHd9XGJpZyhOKHcsdClnKHcsdClcYmlnKQotIFxtdSh3LHQpJCQKd2hlcmUgJE4odyx0KSQgaXMgdGhlIGZpc2ggZGVuc2l0eSBhdCBzaXplICR3JCBhbmQgdGltZSAkdCQsIAokZyh3LHQpJCBpcyB0aGUgZ3Jvd3RoIHJhdGUgb2YgYW4gaW5kaXZpZHVhbCBvZiBzaXplICR3JCBhdCB0aW1lICR0JCBhbmQKJFxtdSh3LHQpJCBpcyBpdHMgZGVhdGggcmF0ZS4gVGhlcmUgaXMgbm8gbmVlZCBmb3IgeW91IHRvIHVuZGVyc3RhbmQgdGhlCm1hdGhlbWF0aWNhbCBub3RhdGlvbi4gCgpTaXplLXNwZWN0cnVtIGR5bmFtaWNzIGlzIGxpa2UgdGhlIHRyYWZmaWMgb24gYSBoaWdod2F5IHdoZXJlIGNhcnMgY2FuIGxlYXZlIHRoZQpoaWdod2F5IChmaXNoIGNhbiBkaWUpIGF0IGFueSBwb2ludCwgYnV0IHRoZXkgY2FuIG9ubHkgam9pbiB0aGUgaGlnaHdheSBhdCBpdHMKYmVnaW5uaW5nIChmaXNoIHN0YXJ0IG91dCBhdCB0aGUgZWdnIHNpemUpLiBUbyBtb2RlbCB0aGUgc2l6ZSBzcGVjdHJ1bSB3ZQp0aGVyZWZvcmUgYWxzbyBoYXZlIHRvIGRlc2NyaWJlIHRoZSByYXRlICRSKHQpJCBhdCB3aGljaCBlZ2dzIGFyZSBlbnRlcmluZyB0aGUKc2l6ZSBzcGVjdHJ1bSwgaS5lLiwgdGhlIHJhdGUgYXQgd2hpY2ggbWF0dXJlIGZpc2ggcmVwcm9kdWNlLiAKCldlIHdpbGwgYmUgZGlzY3Vzc2luZyBpbiBkZXRhaWwgdG9kYXkgd2hhdCBkZXRlcm1pbmVzIHRoZSBkZWF0aCByYXRlICRcbXUodyx0KSQsCnRoZSBncm93dGggcmF0ZSAkZyh3LHQpJCBhbmQgdGhlIHJhdGUgb2YgcmVwcm9kdWN0aW9uICRSKHQpJC4KCgojIFdoeSBzdHVkeSBzaXplLXNwZWN0cnVtIGR5bmFtaWNzPwoKVGhlIHN0dWR5IG9mIHRyYWZmaWMgZHluYW1pY3MgaGFzIGhhZCByZWFsIHByYWN0aWNhbCBiZW5lZml0cy4gRm9yIGV4YW1wbGUsIGF0CmxlYXN0IG9uIG1vdG9yd2F5cyBpbiBFdXJvcGUsIHdoZW4gdGhlcmUgaXMgYSBkYW5nZXIgb2YgYSB0cmFmZmljIGphbQpkZXZlbG9waW5nLCBhdXRvbWF0aWMgc3BlZWQgcmVzdHJpY3Rpb25zIGFyZSBpbXBvc2VkIGF0IGEgY2VydGFpbiBkaXN0YW5jZSBpbgpmcm9udCBvZiB0aGUgZGV2ZWxvcGluZyBzbG93LW1vdmluZyB0cmFmZmljLiBGb3IgbW90b3Jpc3RzIHdobyBoYXZlCm5vdCB0aG91Z2h0IGFib3V0IHRyYWZmaWMgZmxvdywgdGhlc2Ugc3BlZWQgcmVzdHJpY3Rpb25zIGluIHBsYWNlcyB3aGVyZSB0aGVyZQppcyBubyBvYnZpb3VzIHJlYXNvbiBmb3IgdGhlbSBhcmUgdmVyeSBhbm5veWluZy4gSG93ZXZlciB0aGV5IGRvIGluZGVlZCBhdm9pZAp0aGUgZm9ybWF0aW9uIG9mIHRoZSB0cmFmZmljIGphbS4KCk9mIGNvdXJzZSB3ZSBjYW4gbm90IGRpcmVjdGx5IHRlbGwgZmlzaCB0byBvYmV5IGxpbWl0cyB0byB0aGVpciBncm93dGggcmF0ZXMuCkhvd2V2ZXIgd2UgZG8gaGF2ZSBpbmZsdWVuY2Ugb24gdGhlaXIgc2l6ZS1zcGVjdHJ1bSBkeW5hbWljcyB0aHJvdWdoIGZpc2hpbmcKcG9saWN5LiBGb3IgZXhhbXBsZSBpZiBzb21lIHNwZWNpZXMgZXhwZXJpZW5jZXMgc3R1bnRlZCBncm93dGgsIGxpa2UgZm9yIApleGFtcGxlIHRoZSBIZXJyaW5nIGluIHRoZSBCYWx0aWMgU2VhLCB3ZSBjb3VsZCByZXNvbHZlIHRoYXQgYnkgcmVkdWNpbmcgdGhlaXIKbnVtYmVycyAod2hpY2ggaW5jcmVhc2VzIHRoZWlyIGdyb3d0aCByYXRlIGJlY2F1c2Ugb2YgcmVkdWNlZCBjb21wZXRpdGlvbiBmb3IKZm9vZCkgb3IgYnkgcmVkdWNpbmcgZmlzaGluZyBvbiB0aGVpciBwcmV5LgoKVGhlIHNpemUtc3BlY3RydW0gZHluYW1pY3MgaW4gYSBtdWx0aS1zcGVjaWVzIGVjb3N5c3RlbSBpcyBleHRyZW1lbHkgY29tcGxleC4gV2UKY2FuIHVuZGVyc3RhbmQgdmVyeSBzaW1wbGlmaWVkIGNhc2VzIGFuYWx5dGljYWxseSwgYnV0IGluIGdlbmVyYWwgd2UgbmVlZCB0byB1c2UKbnVtZXJpY2FsIHNpbXVsYXRpb24gdG8gdW5kZXJzdGFuZCB0aGUgY29uc2VxdWVuY2VzIG9mIHZhcmlvdXMgaW50ZXJ2ZW50aW9ucy4KClRoZSBtaXplciBwYWNrYWdlIGNhbiBzaW11bGF0ZSB0aGUgc2l6ZS1zcGVjcnVtIGR5bmFtaWNzLiBHaXZlbiB0aGUgbW9kZWwKcGFyYW1ldGVycyB0aGF0IGVudGVyIGludG8gdGhlIGV4cHJlc3Npb24gb2YgdGhlIGdyb3d0aCByYXRlLCB0aGUgZGVhdGggcmF0ZSBhbmQKdGhlIHJlcHJvZHVjdGl2ZSByYXRlLCBhbmQgYW4gaW5pdGlhbCBmaXNoIHNpemUgc3BlY3RydW0sIGl0IHNpbXVsYXRlcyB0aGUKY2hhbmdlcyBpbiB0aGUgc2l6ZSBzcGVjdHJ1bSBvdmVyIHRpbWUgYWNjb3JkaW5nIHRvIHRoZSBhYm92ZSBlcXVhdGlvbnMuCgpPZiBwYXJ0aWN1bGFyIGludGVyZXN0IGlzIHRoZSBzdGVhZHkgc3RhdGUgb2YgdGhlIHNpemUgc3BlY3RydW0sIHdoZXJlIHRoZQplZmZlY3RzIG9mIHRoZSBkZWF0aCByYXRlIGFuZCB0aGUgY2hhbmdlcyBpbiB0aGUgZ3Jvd3RoIHJhdGUgZXhhY3RseQpiYWxhbmNlIGluIHN1Y2ggYSB3YXkgdGhhdCB0aGUgc2l6ZSBzcGVjdHJ1bSBzdGF5cyBjb25zdGFudCBvdmVyIHRpbWUuIFdlCndpbGwgYmUgbG9va2luZyBib3RoIGF0IHRoZSBzdGVhZHkgc3RhdGUgYW5kIGF0IHRpbWUtdmFyeWluZyBzaXplIHNwZWN0cmEKdG9kYXkuCgpPdXIgZW1waGFzaXMgd2lsbCBiZSBvbiB1bmRlcnN0YW5kaW5nIHRoZSBkeW5hbWljcy4gV2UgZG8gbm90IGp1c3Qgd2FudCB0byAKbGVhcm4gaG93IHRvIHJ1biBzaW11bGF0aW9ucyBidXQgd2Ugd2FudCB0byB1c2UgdGhlIHNpbXVsYXRpb25zIHRvIGRldmVsb3AgYW4KaW50dWl0aW9uIGZvciBob3cgZmlzaCBwb3B1bGF0aW9ucyBiZWhhdmUuIFdlIHRoZXJlZm9yZSBzdGFydCB3aXRoIHZlcnkgc2ltcGxlCm1vZGVscyBmaXJzdC4KCiMgQSBmaXJzdCBleGFtcGxlCgpMZXQgdXMgc3RhcnQgYnkgbG9va2luZyBhdCBhbiBleGFtcGxlLiBTdGFydCBSU3R1ZGlvIGFzIGRpc2N1c3NlZCB5ZXN0ZXJkYXkKYW5kIGxvYWQgdGhlIGZvbGxvd2luZyBwYWNrYWdlczoKYGBge3IgbWVzc2FnZT1GQUxTRX0KbGlicmFyeShtaXplcikKbGlicmFyeSh0aWR5dmVyc2UpCmxpYnJhcnkocGxvdGx5KQpgYGAKCk1pemVyIGNvbGxlY3RzIGFsbCB0aGUgcGFyYW1ldGVycyBkZXNjcmliaW5nIGEgc2l6ZS1zcGVjdHJ1bSBtb2RlbCBpbnRvIG9uZQpvYmplY3Qgb2YgY2xhc3MgYE1pemVyUGFyYW1zYC4gWW91IGRvIG5vdCBuZWVkIHRvIHNldCB1cCB0aGlzIG9iamVjdCBieSBoYW5kIGJ1dAppbnN0ZWFkIHRoZXJlIGFyZSBzZXZlcmFsIHdyYXBwZXIgZnVuY3Rpb25zIGluIG1pemVyIHRoYXQgY3JlYXRlIHRoZSBvYmplY3QgZm9yCnlvdSBmb3IgdmFyaW91cyB0eXBlcyBvZiBtb2RlbHMsIGFuZCBhbHNvIG1hbnkgZnVuY3Rpb25zIGZvciBjaGFuZ2luZyBzcGVjaWZpYwpwYXJhbWV0ZXJzIGluIGEgbW9kZWwuIFdlIHdpbGwgdXNlIHRoZSBgbmV3U2hlbGRvblBhcmFtcygpYCBmdW5jdGlvbiB0byBzZXQgdXAgYQptb2RlbCBkZXNjcmliaW5nIGEgc2luZ2xlIGZpc2ggc3BlY2llcyBsaXZpbmcgaW4gYSBTaGVsZG9uIHBvd2VyLWxhdyBjb21tdW5pdHkuCllvdSBhbHJlYWR5IGRpc2N1c3NlZCB5ZXN0ZXJkYXkgdGhlIGZhY3QgdGhhdCBTaGVsZG9uIGRpc2NvdmVyZWQgdGhhdCB0aGUKY29tbXVuaXR5IHNwZWN0cnVtIGlzIGFwcHJveGltYXRlbHkgZGVzY3JpYmVkIGJ5IGEgcG93ZXIgbGF3LgoKVGhlIGBuZXdTaGVsZG9uUGFyYW1zKClgIGZ1bmN0aW9uIGhhcyBtYW55IGFyZ3VtZW50cyB0aGF0IGFsbG93IHlvdSB0byBzcGVjaWZ5CnBhcmFtZXRlcnMgZm9yIHRoZSBmaXNoIHNwZWNpZXMgYXMgd2VsbCBhcyBmb3IgdGhlIGNvbW11bml0eSwgYnV0IGFsbCB0aGVzZQphcmd1bWVudHMgaGF2ZSBkZWZhdWx0IHZhbHVlcywgc28gd2UgY2FuIHNpbXBseSBjYWxsIHRoZSBmdW5jdGlvbiB3aXRob3V0CnNwZWNpZnlpbmcgdGhvc2UgYXJndW1lbnRzLiBXZSB3aWxsIG9ubHkgc3BlY2lmeSB0aGUgU2hlbGRvbiBleHBvbmVudCBvZgp0aGUgYmFja2dyb3VuZCBjb21tdW5pdHkKYGBge3J9CnBhcmFtcyA8LSBuZXdTaGVsZG9uUGFyYW1zKGxhbWJkYSA9IDIuMDUpCmBgYApZb3UgY2FuIGlnbm9yZSB0aGUgbWVzc2FnZSB0aGF0IHRoZSBmdW5jdGlvbiBwcmludHMgZm9yIG5vdy4gSXQgd2lsbCBtYWtlIHNlbnNlCm9uY2Ugd2UgaGF2ZSBkaXNjdXNzZWQgcHJlZGF0aW9uIGxhdGVyLiBUaGUgZnVuY3Rpb24gcmV0dXJucyBhIGBNaXplclBhcmFtc2AKb2JqZWN0IGFuZCB3ZSBoYXZlIGFzc2lnbmVkIHRoYXQgdG8gdGhlIHZhcmlhYmxlIGBwYXJhbXNgLiBXZSB3aWxsIGJlCmV4cGxhaW5pbmcgbW9yZSBhYm91dCB0aGlzIG1vZGVsIGFzIHdlIGdvIGFsb25nLiAKCiMgU3RlYWR5IHN0YXRlIHNwZWN0cnVtCgpUaGUgYHBhcmFtc2Agb2JqZWN0IGFsc28gY29udGFpbnMgYW4gaW5pdGlhbCBzaXplIHNwZWN0cnVtIHRoYXQgaXMgY2xvc2UgdG8KdGhlIHN0ZWFkeSBzdGF0ZSBvZiB0aGUgbW9kZWwuIFRoZSBzdGVhZHkgc3RhdGUgaXMgdGhlIHN0YXRlIHdoZXJlIGluIGVhY2gKc2l6ZSBjbGFzcyB0aGUgaW5mbG93IG9mIGluZGl2aWR1YWxzIHRocm91Z2ggZ3Jvd3RoIGV4YWN0bHkgYmFsYW5jZXMgdGhlCm91dGZsb3cgb2YgaW5kaXZpZHVhbHMgdGhyb3VnaCBncm93dGggYW5kIGRlYXRoLiBJZiB3ZSBzdGFydCBjbG9zZSB0byB0aGUKc3RlYWR5IHN0YXRlIHRoZW4gdXN1YWxseSBpZiB3ZSBzaW11bGF0ZSB0aGUgc2l6ZS1zcGVjdHJ1bSBkeW5hbWljcyBmb3IgYQp3aGlsZSB0aGUgc3lzdGVtIHdpbGwgZXZvbHZlIGNsb3NlciBhbmQgY2xvc2VyIHRvIHRoZSBzdGVhZHkgc3RhdGUuCgpUbyBnZXQgdG8gdGhlIHN0ZWFkeSBzdGF0ZSB3ZSB1c2UgdGhlIGBzdGVhZHkoKWAgZnVuY3Rpb24uIFRoZSByZXN1bHQgb2YgdGhhdApmdW5jdGlvbiBpcyBhZ2FpbiBhIE1pemVyUGFyYW1zIG9iamVjdCBidXQgbm93IHdpdGggYW4gaW5pdGlhbCBzaXplIHNwZWN0cnVtCnRoYXQgaGFzIGV2b2x2ZWQgdG8gYmUgdmVyeSBjbG9zZSB0byB0aGUgc3RlYWR5IHN0YXRlLgpgYGB7cn0KcGFyYW1zIDwtIHN0ZWFkeShwYXJhbXMpCmBgYAoKV2UgY2FuIHBsb3QgdGhlIHNpemUgc3BlY3RydW0gd2l0aCB0aGUgYHBsb3RTcGVjdHJhKClgIGZ1bmN0aW9uLgpgYGB7cn0KcGxvdFNwZWN0cmEocGFyYW1zLCBwb3dlciA9IDApCmBgYAoKVGhlIGBwb3dlciA9IDBgIGFyZ3VtZW50IHRvIHRoZSBgcGxvdFNwZWN0cmEoKWAgZnVuY3Rpb24gc3BlY2lmaWVzIHRoYXQgd2Ugd2FudAp0byBwbG90IHRoZSBudW1iZXIgZGVuc2l0eSwgcmF0aGVyIHRoYW4gZm9yIGV4YW1wbGUgdGhlIGJpb21hc3MgZGVuc2l0eS4KClRoZSBncmVlbiBsaW5lIHJlcHJlc2VudHMgdGhlIG51bWJlciBkZW5zaXR5IG9mIHRoZSBiYWNrZ3JvdW5kIGNvbW11bml0eSBhcyBhCmZ1bmN0aW9uIG9mIHNpemUuIFRoZSByZWFzb24gaXQgaXMgbGFiZWxsZWQgYXMgIlBsYW5rdG9uIiBpbiB0aGUgcGxvdCBsZWdlbmQgaXMKanVzdCBiZWNhdXNlIGluIG1vc3QgbW9kZWxzIHRoZSBiYWNrZ3JvdW5kIHNwZWN0cnVtIHJlcHJlc2VudHMgdGhlIHBsYW5rdG9uLiBJbgpvdXIgbW9kZWwgaG93ZXZlciBpdCByZXByZXNlbnRzIHRoZSBlbnRpcmUgbWFyaW5lIGNvbW11bml0eSBpbiB3aGljaCBvdXIKZm9yZWdyb3VuZCBzcGVjaWVzIGZpbmRzIGl0c2VsZi4gVGhlIGdyZWVuIGxpbmUgaXMgYSBzdHJhaWdodCBsaW5lIHdpdGggc2xvcGUKLTIuMDUuIFRodXMgdGhlIGFidW5kYW5jZSBkZW5zaXR5IGlzIHByb3BvcnRpb25hbCB0byAkd157LTIuMDV9JC4KClRoZSBvdGhlciBsaW5lIHJlcHJlc2VudHMgdGhlIG51bWJlciBkZW5zaXR5IG9mIG91ciBzaW5nbGUgc3BlY2llcywgd2hpY2ggYnkKZGVmYXVsdCBpcyBqdXN0IG5hbWVkIHVuaW1hZ2luYXRpdmVseSAiMSIuIFdlIHNlZSB0aGF0IGl0IGlzIGEgc3RyYWlnaHQgbGluZQppbml0aWFsbHksIGJ1dCB0aGVuIGhhcyBhIGJ1bXAgYmVmb3JlIGRlY2xpbmluZyByYXBpZGx5IGF0IGxhcmdlIHNpemVzLiBXZSB3aWxsCmRpc2N1c3MgaW4gYSBzaG9ydCB3aGlsZSB3aGF0IGNhdXNlcyB0aGF0IHNoYXBlLgoKVGhlIGluaXRpYWwgc2xvcGUgb2YgdGhlIHNwZWNpZXMgbnVtYmVyIGRlbnNpdHkgaXMgbmVnYXRpdmUsIHdoaWNoIG1lYW5zIHRoYXQKdGhlcmUgYXJlIGZld2VyIGxhcmdlciBmaXNoIHRoYW4gc21hbGxlciBmaXNoLiBUaGF0IGlzIG9mIGNvdXJzZSBvYnZpb3VzOgpzb21lIGZpc2ggZGllIHdoaWxlIHRoZXkgYXJlIGdyb3dpbmcgdXAsIHNvIHRoZXJlIGFyZSBmZXdlciBmaXNoIGluIGxhcmdlcgpzaXplIGNsYXNzZXMuIAoKIyMgRXhlcmNpc2UgMQpOb3cgaXQgaXMgdGltZSBmb3IgeW91IHRvIGRvIHRoZSBmaXJzdCBleGVyY2lzZSB0byB1c2UgdGhlIGNvbW1hbmRzIHlvdSBoYXZlCmp1c3QgbGVhcm5lZCBhYm91dC4gRm9yIHRoaXMgcHVycG9zZSB5b3Ugc2hvdWxkIG5vdyBvcGVuIHRoZSBSIG5vdGVib29rIGZpbGUKImV4ZXJjaXNlc19zaW5nbGUtc3BlY2llc19zaXplLXNwZWN0cnVtX2R5bmFtaWNzIiBhbmQgcmVhZCBpdCB1cCB0byB0aGUKcGxhY2Ugd2hlcmUgaXQgc2hvd3MgdGhlIGZpcnN0IGV4ZXJjaXNlLiBUaGVuIHlvdSBwdXQgeW91ciBSIGNvZGUgZm9yIHRoZQpleGVyY2lzZSBzdHJhaWdodCBpbnRvIHRoZSBjb2RlIGNodW5rcyBpbiB0aGF0IG5vdGVib29rIGFuZCBldmFsdWF0ZSB0aGVtCnRoZXJlLiBXaGVuIHlvdSBhcmUgc2F0aXNmaWVkIHdpdGggeW91ciBzb2x1dGlvbiwgY29tZSBiYWNrIHRvIHRoaXMgZG9jdW1lbnQKYW5kIGNvbnRpbnVlIHJlYWRpbmcuCgojIE51bWJlcnMKCldoaWxlIHRoZSBgcGxvdFNwZWN0cmEoKWAgZnVuY3Rpb24gZ2l2ZXMgdXMgYSBwbG90IG9mIHRoZSBudW1iZXIgZGVuc2l0eSwgaXQKd291bGQgYmUgbmljZSBpZiB3ZSBjb3VsZCBnZXQgYXQgdGhlIGFjdHVhbCBudW1iZXJzLiBUaGUgbnVtYmVyIGRlbnNpdHkgb2YgdGhlCnN0ZWFkeSBzdGF0ZSBpcyBzdG9yZWQgaW4gdGhlIGBwYXJhbXNgIG9iamVjdCBpbiB0aGUgYGluaXRpYWxfbmAgc2xvdC4gVGhpcyBpcwphY2Nlc3NlZCBhcyBmb2xsb3dzOgpgYGB7cn0KbiA8LSBwYXJhbXNAaW5pdGlhbF9uCmBgYAoKQXMgeW91IGNhbiBzZWUgaW4gdGhlICJFbnZpcm9ubWVudCIgcGFuZSBpbiBSU3R1ZGlvLCBgbmAgaXMgYSAgbWF0cml4IHdpdGggMSByb3cKYW5kIDI1MSBjb2x1bW5zLiBUaGUgb25lIHJvdyBjb3JyZXNwb25kcyB0byB0aGUgb25lIHNwZWNpZXMuIEluIGEgbXVsdGlzcGVjaWVzCm1vZGVsIHRoZXJlIHdvdWxkIGJlIG9uZSByb3cgZm9yIGVhY2ggc3BlY2llcywgaG9sZGluZyB0aGUgbnVtYmVyIGRlbnNpdHkgZm9yCnRoYXQgc3BlY2llcy4gVGhlIDI1MSBjb2x1bW5zIGFyZSBmb3IgdGhlIG51bWJlciBkZW5zaXRpZXMgaW4gZWFjaCBvZiB0aGUgMjUxCnNpemUgY2xhc3Nlcy4gSW4gZmFjdCwgYG5gIGlzIGEgbmFtZWQgYXJyYXksIGkuZS4sIGVhY2ggcm93IGFuZCBlYWNoIGNvbHVtbiBoYXMKbmFtZXMuIFRoZXNlIHdlIGNhbiBleHRyYWN0IHdpdGggdGhlIGBkaW1uYW1lcygpYCBmdW5jdGlvbi4KYGBge3J9CmRpbW5hbWVzKG4pCmBgYAoKVGhlIG5hbWVzIG9mIHRoZSBjb2x1bW5zIGFyZSB0aGUgd2VpZ2h0IGluIGdyYW1zIGF0IHRoZSBzdGFydCBvZiBlYWNoIHNpemUKY2xhc3MuIE5vdGljZSBob3cgUiBkaXNwbGF5cyBsb25nIHZlY3RvcnMgYnkgYnJlYWtpbmcgdGhlbSBhY3Jvc3MgbWFueSBsaW5lcyBhbmQKc3RhcnRpbmcgZWFjaCBsaW5lIHdpdGggYSBudW1iZXIgaW4gYnJhY2tldHMuIFRoYXQgbnVtYmVyIGlzIHRoZSBpbmRleCBvZiB0aGUKZmlyc3QgdmFsdWUgaW4gdGhhdCByb3cuIFNvIGZvciBleGFtcGxlIHdlIHNlZSB0aGF0IHRoZSAxNTFzdCBzaXplIGJyYWNrZXQKc3RhcnRzIGF0IDEgZ3JhbS4gVGhlIG51bWJlciBkZW5zaXR5IGluIHRoZSBzaXplIGNsYXNzIGJldHdlZW4gMSBncmFtIGFuZCAxLjA1CmdyYW1zIGlzCmBgYHtyfQpuWzEsIDE1MV0KYGBgCgpJdCBpcyBpbXBvcnRhbnQgdG8gcmVhbGlzZSB0aGF0IHRoaXMgaXMgbm90IHRoZSBudW1iZXIgb2YgZmlzaCBpbiB0aGUgc2l6ZQpjbGFzcywgYnV0IHRoZSBudW1iZXIgZGVuc2l0eS4gVG8gZ2V0IHRoZSBudW1iZXIgb2YgZmlzaCB3ZSBoYXZlIHRvIG11bHRpcGx5IHRoZQpudW1iZXIgYnkgdGhlIHdpZHRoIG9mIHRoZSBzaXplIGNsYXNzLiBDb252ZW5pZW50bHkgdGhvc2Ugd2lkdGhzIGFyZSBhbHNvIHN0b3JlZAppbiB0aGUgYHBhcmFtc2Agb2JqZWN0LCBpbiB0aGUgYGR3YCBzbG90LiBTbyB0aGUgbnVtYmVyIG9mIGZpc2ggaW4gdGhlIDE1MXN0CnNpemUgY2xhc3MgaXMKYGBge3J9CihuICogcGFyYW1zQGR3KVsxLCAxNTFdCmBgYAoKWW91IG1heSBiZSBzdXJwcmlzZWQgYXQgdGhlIHNtYWxsIG51bWJlciBpZiB5b3UgaW50ZXJwcmV0IGl0IGFzIHRoZSBudW1iZXIgb2YKZmlzaCBiZXR3ZWVuIDEgZ3JhbSBhbmQgMS4wNSBncmFtIGluIHRoZSBlbnRpcmUgb2NlYW4uIEhvd2V2ZXIgaXQgbG9va3MgbW9yZQpyZWFzb25hYmxlIGlmIGl0IGlzIHRoZSBhdmVyYWdlIG51bWJlciBwZXIgc3F1YXJlIG1ldGVyIG9mIHNlYS4gRm9yIG1vcmUgb2YKYSBkaXNjdXNzaW9uIG9mIHRoaXMgaXNzdWUgb2Ygd29ya2ludiB3aXRoIG51bWJlcnMgcGVyIGFyZWEsCm51bWJlcnMgcGVyIHZvbHVtZSBvciBudW1iZXJzIGZvciB0aGUgZW50aXJlIHN5c3RlbSBzZWUKaHR0cHM6Ly9zaXplc3BlY3RydW0ub3JnL21pemVyL2Rldi9yZWZlcmVuY2Uvc2V0UGFyYW1zLmh0bWwjdW5pdHMtaW4tbWl6ZXIKCiMjIEV4ZXJjaXNlIDIKR28gYmFjayB0byB5b3VyIGV4ZXJjaXNlIG5vdGVib29rIGZvciB0aGlzCnR1dG9yaWFsIGFuZCBhbnN3ZXIgZXhlcmNpc2UgMiBiZWZvcmUgcmVhZGluZyBvbi4KCiMgQmlvbWFzcyBzcGVjdHJhCgpXaXRob3V0IHRoZSBgcG93ZXJgIGFyZ3VtZW50IChvciB3aXRoIGBwb3dlciA9IDFgIHdoaWNoIGlzIHRoZSBkZWZhdWx0KSB0aGUKYHBsb3RTcGVjdHJhKClgIGZ1bmN0aW9uIHBsb3RzIHRoZSBiaW9tYXNzIGRlbnNpdHkgYXMgYSBmdW5jdGlvbiBvZiBzaXplLgpgYGB7cn0KcGxvdFNwZWN0cmEocGFyYW1zKQpgYGAKCk5vdyB0aGUgZ3JlZW4gbGluZSByZXByZXNlbnRpbmcgdGhlIGJpb21hc3MgZGVuc2l0eSBvZiB0aGUgYmFja2dyb3VuZCBoYXMgYSAKc2xvcGUgb2YgLTEuMDUuCgpUaGUgaW5pdGlhbCBzbG9wZSBvZiB0aGUgc3BlY2llcyBiaW9tYXNzIGRlbnNpdHkgaXMgbmVnYXRpdmUsIG1lYW5pbmcgdGhhdCB0aGUKYmlvbWFzcyBkZW5zaXR5IGRlY3JlYXNlcyB3aXRoIHNpemUuIFRoaXMgbWVhbnMgdGhhdCBldmVuIHRob3VnaCB0aGUgaW5kaXZpZHVhbApmaXNoIG9mIGNvdXJzZSBnYWluIGJpb21hc3MgYXMgdGhleSBncm93IHVwLCB0aGVyZSBpcyBzbyBtdWNoIGRlYXRoIGFtb25nIHRoZQpsYXJ2YWUgYW5kIGp1dmVuaWxlIGZpc2ggdGhhdCB0aGUgdG90YWwgYmlvbWFzcyBvZiBhbnkgY29ob3J0IG5ldmVydGhlbGVzcwpkZWNyZWFzZXMgYXMgaXQgZ3Jvd3MgdXAuIFdlIHdpbGwgZXhwbGFpbiB0aGUgcmVhc29uIGZvciB0aGlzIGxhdGVyIHdoZW4gd2UKZGlzY3VzcyBwcmVkYXRpb24gbW9ydGFsaXR5LgoKV2UgY2FuIGFsc28gcGxvdCB0aGUgU2hlbGRvbiBzcGVjdHJ1bSwgaS5lLiwgdGhlIGJpb21hc3MgZGVuc2l0eSBhcyBhIGZ1bmN0aW9uCm9mIHRoZSBsb2cgd2VpZ2h0IGluc3RlYWQgb2YgdGhlIHdlaWdodCwgYnkgc3VwcGx5aW5nIHRoZSBhcmd1bWVudApgcG93ZXIgPSAyYCB0byBgcGxvdFNwZWN0cmEoKWAuCmBgYHtyfQpwbG90U3BlY3RyYShwYXJhbXMsIHBvd2VyID0gMikKYGBgCgpUaGlzIG5vdyBzaG93cyBhbiBhcHByb3hpbWF0ZWx5IGNvbnN0YW50IGJpb21hc3MgZGVuc2l0eSBhcyBhIGZ1bmN0aW9uIG9mIGxvZwpzaXplICh0aGUgc2xvcGUgb2YgdGhlIGdyZWVuIGxpbmUgaXMgLTAuMDUpLiBUaGUgYmlvbWFzcyBkZW5zaXR5IG9mIHRoZSBzcGVjaWVzCmFzIGEgZnVuY3Rpb24gb2YgbG9nIHNpemUgaW5pdGlhbGx5IGluY3JlYXNlcy4gU28gaWYgYmlubmVkIGluCmxvZ2FyaXRobWljYWxseS1zaXplZCBiaW5zIHRoZSBiaW9tYXNzIGluIGVhY2ggYmluIHdpbGwgaW5pdGlhbGx5IGluY3JlYXNlLAp1bnRpbCBpdCBzdGFydHMgZGVjcmVhc2luZyBjbG9zZSB0byB0aGUgbWF4aW11bSBzaXplIG9mIHRoZSBzcGVjaWVzLgoKSXQgbWF5IGhhdmUgYmVlbiBhIGJpdCBjb25mdXNpbmcgdGhhdCB3ZSBkaXNwbGF5ZWQgdGhlIHNhbWUgc2l6ZSBzcGVjdHJ1bSBpbgp0aHJlZSBkaWZmZXJlbnQgd2F5cy4gQnV0IGl0IGlzIGltcG9ydGFudCB0byBiZSBhd2FyZSBvZiB0aGlzIGJlY2F1c2UgaW4gdGhlCmxpdGVyYXR1cmUgeW91IHdpbGwgc2VlIGFsbCBkaWZmZXJlbnQgY29udmVudGlvbnMgYmVpbmcgdXNlZCwgc28gaWYgeW91IHNlZSBhCnBsb3Qgb2YgYSBzaXplIHNwZWN0cnVtIHlvdSBhbHdheXMgbmVlZCB0byBhc2sgeW91cnNlbGYgZXhhY3RseSB3aGljaCBkZW5zaXR5CmlzIGJlaW5nIHNob3duLgoKV2UgY2FuIG9idGFpbiB0aGUgYmlvbWFzcyBkZW5zaXR5IGluIGEgc2l6ZSBjbGFzcyBmcm9tIHRoZSBudW1iZXIgZGVuc2l0eSBieQptdWx0aXBseWluZyB0aGUgbnVtYmVyIGRlbnNpdHkgYnkgdGhlIHdlaWdodCBvZiB0aGUgaW5kaXZpZHVhbHMgaW4gdGhlIHNpemUKY2xhc3MuIE9mIGNvdXJzZSB0aGVyZSBpcyBhIGJpdCBvZiBlcnJvciBoZXJlIGJlY2F1c2Ugbm90IGFsbCBmaXNoIGluIHRoZSAKc2l6ZSBjbGFzcyBoYXZlIHRoZSBzYW1lIHdlaWdodCwgYnV0IHdpdGggdGhlIHNtYWxsIHNpemUgY2xhc3NlcyB0aGF0IHdlIHVzZQppbiBtaXplciwgdGhlIGVycm9yIGlzIG5vdCB0b28gaW1wb3J0YW50LiBTbyB3ZSBjYWxjdWxhdGUKYGBge3J9CmJpb21hc3NfZGVuc2l0eSA8LSBuICogcGFyYW1zQHcKYGBgCgpUaGUgdG90YWwgYmlvbWFzcyBpbiBlYWNoIHNpemUgY2xhc3Mgd2Ugb2J0YWluIGJ5IG11bHRpcGx5aW5nIHRoZSBiaW9tYXNzCmRlbnNpdHkgaW4gZWFjaCBzaXplIGNsYXNzIGJ5IHRoZSB3aWR0aCBvZiBlYWNoIHNpemUgY2xhc3MKYGBge3J9CmJpb21hc3MgPC0gYmlvbWFzc19kZW5zaXR5ICogcGFyYW1zQGR3CmBgYAoKRm9yIGV4YW1wbGUgdGhlIGJpb21hc3Mgb2YgZmlzaCBiZXR3ZWVuIDEgZ3JhbSBhbmQgMS4wNSBncmFtcyBpcwpgYGB7cn0KYmlvbWFzc1sxNTFdCmBgYAoKTmV4dCB3ZSB3aWxsIGRpc2N1c3MgdGhlIHNoYXBlIG9mIHRoZSBzcGVjaWVzIHNpemUtc3BlY3RydW0gaW4gbW9yZSBkZXRhaWwuCgojIEFsbG9tZXRyaWMgcmF0ZXMKClRoZSBmaXJzdCBzdHJpa2luZyBmZWF0dXJlIG9mIHRoZSBzcGVjaWVzIHNpemUtc3BlY3RydW0sIGluIGFsbCBpdHMKcmVwcmVzZW50YXRpb25zLCBpcyB0aGF0IGZvciBzbWFsbCBmaXNoIChsYXJ2YWUgYW5kIGp1dmVuaWxlcykgaXQgaXMgZ2l2ZW4gYnkgYQpzdHJhaWdodCBsaW5lLiBUaGlzIGR1ZSB0byB0aGUgYWxsb21ldHJpYyBzY2FsaW5nIG9mIHRoZSBwaHlzaW9sb2dpY2FsIHJhdGVzLgpUaGUgb3RoZXIgc3RyaWtpbmcgZmVhdHVyZSBpcyB0aGUgYnVsZ2UgYXQgYXJvdW5kIG1hdHVyaXR5IHNpemUsIHdoaWNoIHdlCndpbGwgZGlzY3VzcyBpbiB0aGUgc2VjdGlvbiBvbiByZXByb2R1Y3Rpb24uCgpGaXJzdCBvZiBhbGwsIGFzIE1hcmllbGxhIGFscmVhZHkgbWVudGlvbmVkIHllc3RlcmRheSwgdGhlIG1ldGFib2xpYyByYXRlLCBpLmUuLAp0aGUgcmF0ZSBhdCB3aGljaCBhbiBvcmdhbmlzbSBleHBlbmRzIGVuZXJneSBvbiBpdHMgYmFzaWMgbWV0YWJvbGljIG5lZWRzLApzY2FsZXMgYXMgYSBwb3dlciBvZiB0aGUgb3JnYW5pc21zJ3MgYm9keSBzaXplLCBhbmQgdGhlIHBvd2VyIGlzIGFib3V0ICRwID0KMy80JC4KCkJlY2F1c2UgdGhpcyBlbmVyZ3kgbmVlZHMgdG8gYmUgc3VwcGxpZWQgYnkgY29uc3VtcHRpb24gb2YgZm9vZCwgaXQgaXMgbmF0dXJhbAp0byBhc3N1bWUgdGhhdCBhbHNvIHRoZSBjb25zdW1wdGlvbiByYXRlIHNjYWxlcyBhbGxvbWV0cmljYWxseSB3aXRoIGEgcG93ZXIgb2YKMy80LiBXaGVuIHRoZSBjb25zdW1wdGlvbiBpcyBncmVhdGVyIHRoYW4gdGhlIG1ldGFib2xpYyBjb3N0IHRoZW4gdGhlIGV4Y2VzcwpsZWFkcyB0byBncm93dGguIEhlbmNlIHRoZSBncm93dGggcmF0ZSB0b28gc2NhbGVzIGFsbG9tZXRyaWNhbGx5IHdpdGggcG93ZXIgCiRwID0gMy80JC4KCkZpbmFsbHksIHRoZSBkZWF0aCByYXRlIG9mIG9yZ2FuaXNtcyB0ZW5kcyB0byBzY2FsZSBhbGxvbWV0cmljYWxseSB3aXRoIGEgcG93ZXIKb2YgJHAgLSAxID0gMy80IC0gMSA9IC0xLzQkLiBUaGUgZGVhdGggcmF0ZSBleHBlcmllbmNlZCBieSBsYXJnZXIgaW5kaXZpZHVhbHMgaXMKc21hbGxlciB0aGFuIHRoYXQgb2Ygc21hbGwgaW5kaXZpZHVhbHMuIEFnYWluIHRoaXMgaXMgY29uZmlybWVkIGJ5IG1hbnkKb2JzZXJ2YXRpb25zLgoKSXQgaXMgYSByZXN1bHQgb2YgdGhlIG1hdGhlbWF0aWNzIHRoYXQgaWYgdGhlIGdyb3d0aCBhbmQgZGVhdGggcmF0ZXMgc2NhbGUKYWxsb21ldHJpY2FsbHkgd2l0aCBleHBvbmVudHMgJHAkIGFuZCAkMS1wJCByZXNwZWN0aXZlbHksIGZvciBzb21lIG1ldGFib2xpYwpleHBvbmVudCAkcCQsIHRoYXQgdGhlIG51bWJlciBkZW5zaXR5IGF0IHN0ZWFkeSBzdGF0ZSBpcyBhbHNvIGEgcG93ZXIgbGF3LCBpLmUuLAphIHN0cmFpZ2h0IGxpbmUgb24gdGhlIGxvZy1sb2cgcGxvdC4KCkxldCB1cyBjaGVjayB0aGF0IGluIG91ciBtb2RlbCB0aGUgcGh5c2lvbG9naWNhbCByYXRlcyBhcmUgaW5kZWVkIHBvd2VyIGxhd3MsCmF0IGxlYXN0IGZvciB0aGUgc21hbGwgc2l6ZXMuIFdlIGNhbiBnZXQgdGhlIGdyb3d0aCByYXRlIHdpdGggdGhlIGBnZXRFR3Jvd3RoKClgCmZ1bmN0aW9uLiBXZSBhc3NpZ24gdGhlIHJlc3VsdCB0byBhIHZhcmlhYmxlIHRoYXQgd2UgbmFtZSBgZ3Jvd3RoX3JhdGVgLgpgYGB7cn0KZ3Jvd3RoX3JhdGUgPC0gZ2V0RUdyb3d0aChwYXJhbXMpCmBgYAoKWW91IGNhbiBhZ2FpbiBzZWUgaW4gdGhlICJFbnZpcm9ubWVudCIgcGFuZSB0aGF0IHRoaXMgaXMgYSBtYXRyaXggd2l0aCBvbmUgcm93CmZvciB0aGUgb25lIHNwZWNpZXMgYW5kIDI1MSBjb2x1bW5zIGZvciB0aGUgMjUxIHNpemUgY2xhc3Nlcy4gU28gZm9yIGV4YW1wbGUgCnRoZSBncm93dGggcmF0ZSBhdCBzaXplIDEgZ3JhbSBpcwpgYGB7cn0KZ3Jvd3RoX3JhdGVbMSwgMTUxXQpgYGAKKGJlY2F1c2Ugd2UgaGFkIHNlZW4gdGhhdCB0aGUgMTUxc3Qgc2l6ZSBjbGFzcyBzdGFydHMgYXQgMSBncmFtKS4gVGhpcyBpcyB0aGUKcGVyLWNhcGl0YSBncm93dGggcmF0ZSwgbWVhc3VyZWQgaW4gZ3JhbXMgcGVyIHllYXIuIAoKV2Ugd291bGQgbGlrZSB0byBtYWtlIGEgbG9nLWxvZyBwbG90IG9mIHRoZSBncm93dGggcmF0ZSBhZ2FpbnN0IHNpemUgdG8gY2hlY2sKdGhhdCBpdCBnaXZlcyBhIHN0cmFpZ2h0IGxpbmUuIFdlIHdpbGwgdXNlIGBnZ3Bsb3QoKWAgZm9yIHRoYXQgcHVycG9zZS4gQXMgeW91CnNhdyBhbHJlYWR5IHllc3RlcmRheSwgYGdncGxvdCgpYCBsaWtlcyB0byB3b3JrIHdpdGggZGF0YSBmcmFtZXMgaW5zdGVhZCBvZgpuYW1lZCBtYXRyaWNlcywgc28gd2UgZmlyc3QgY29udmVydCB0aGUgbWF0cml4IGludG8gYSBkYXRhIGZyYW1lIHdpdGggdGhlCmBtZWx0KClgIGZ1bmN0aW9uLgpgYGB7cn0KZ3Jvd3RoX3JhdGVfZnJhbWUgPC0gbWVsdChncm93dGhfcmF0ZSkKYGBgCgpZb3UgY2FuIHNlZSBpbiB0aGUgIsKjbnZpcm9ubWVudCIgcGFuZSB0aGF0IHRoZSBuZXcgdmFyaWFibGUgdGhhdCB3ZSBjYWxsZWQKYGdyb3d0aF9yYXRlX2ZyYW1lYCBpcyBhIGRhdGEgZnJhbWUgd2l0aCAyNTEgb2JzZXJ2YXRpb25zIG9mIDMgdmFyaWFibGVzLiBUaGUKMjUxIG9ic2VydmF0aW9ucyBjb3JyZXNwb25kIHRvIHRoZSAyNTEgc2l6ZSBjbGFzc2VzLiBUaGUgMyB2YXJpYWJsZXMgYXJlIGNhbGxlZApgYGB7cn0KbmFtZXMoZ3Jvd3RoX3JhdGVfZnJhbWUpCmBgYAoKVGhleSBhcmUgdGhlIHNwZWNpZXMgYHNwYCwgdGhlIHNpemUgYHdgLCBhbmQgdGhlIGB2YWx1ZWAgd2hpY2ggY29udGFpbnMgdGhlCmdyb3d0aF9yYXRlLiBUaGlzIGRhdGEgZnJhbWUgd2UgY2FuIHBhc3MgdG8gYGdncGxvdCgpYCwgdXNpbmcgdGVjaG5pcXVlcyB5b3UKYWxyZWFkeSBsZWFybmVkIHllc3RlcmRheS4KYGBge3J9CnAgPC0gZ2dwbG90KGdyb3d0aF9yYXRlX2ZyYW1lKSArCiAgICBnZW9tX2xpbmUoYWVzKHggPSB3LCB5ID0gdmFsdWUpKSArCiAgICBzY2FsZV94X2xvZzEwKCkgKwogICAgc2NhbGVfeV9sb2cxMCgpICsKICAgIGxhYnMoeCA9ICJXZWlnaHQgW2ddIiwKICAgICAgICAgeSA9ICJHcm93dGggcmF0ZSBbZy95ZWFyXSIpCnAKYGBgCk5vdGUgaG93IHdlIGxpbmtlZCB0aGUgeCBheGlzIHRvIHRoZSBgd2AgdmFyaWFibGUgYW5kIHRoZSB5IGF4aXMgdG8gdGhlIGB2YWx1ZWAKdmFyaWFibGUuCgpXZSBzZWUgdGhhdCBhdCBsZWFzdCB1cCB0byBhIHNpemUgb2YgYSBmZXcgZ3JhbXMgdGhlIGxpbmUgaXMgc3RyYWlnaHQuIExldCdzIGlzb2xhdGUgdGhlIGdyb3d0aCByYXRlIGZvciB0aG9zZSBzbWFsbGVyIHNpemVzCmBgYHtyfQpnX3NtYWxsX2Zpc2ggPC0gZmlsdGVyKGdyb3d0aF9yYXRlX2ZyYW1lLCB3IDw9IDEwKQpgYGAKYW5kIGZpdCBhIGxpbmVhciBtb2RlbApgYGB7cn0KbG0obG9nKGdfc21hbGxfZmlzaCR2YWx1ZSkgfiBsb2coZ19zbWFsbF9maXNoJHcpKQpgYGAKClRoZSBzbG9wZSBvZiB0aGUgbGluZSBpcyBpbmRlZWQgMC43NSA9IDMvNC4gSW4gZmFjdCwgdGhlIGFib3ZlIHNob3dzIHRoYXQgZm9yIGp1dmVuaWxlcwokJFxsb2coZyh3KSkgPSAyLjEyOSArIFxmcmFjMzQgXGxvZyh3KSQkCmFuZCB0aHVzCiQkZyh3KSA9IGdfMFwgd15wID0gMi4xMjlcICB3XnszLzR9LiQkCgpPZiBjb3Vyc2UgaW4gYSByZWFsIG1vZGVsLCB0aGUgZ3Jvd3RoIHJhdGUgd291bGQgbm90IHNvIGV4YWN0bHkgZm9sbG93IGEgcG93ZXIKbGF3LCBkdWUgdG8gdmFyaWF0aW9ucyBpbiB0aGUgZ3Jvd3RoIHJhdGUgZHVlIHRvIHZhcmlhdGlvbnMgaW4gZm9vZAphdmFpbGFiaWxpdHksIGZvciBleGFtcGxlLgoKIyMgRXhlcmNpc2UgMwpOb3cgb3ZlciB0byB5b3UuIERvIGV4ZXJjaXNlIDMgaW4gdGhlIGV4ZXJjaXNlIG5vdGVib29rLiBVc2UgdGhlIG1ldGhvZHMgeW91CmhhdmUganVzdCBzZWVuIHRvIG1ha2UgYSBsb2ctbG9nIHBsb3Qgb2YgdGhlIG1vcnRhbGl0eSByYXRlLiBZb3UgY2FuIGdldCB0aGUKbW9ydGFsaXR5IHJhdGUgd2l0aCB0aGUgYGdldE1vcnQoKWAgZnVuY3Rpb24uIFRoZW4gZml0IGEgbGluZWFyIG1vZGVsIGFuZCB0aHVzCmRldGVybWluZSB0aGF0IHRoZSBtb3J0YWxpdHkgcmF0ZSBpcwokJFxtdSh3KSA9IFxtdV8wXCB3XntwLTF9ID0gMS45MDlcIHdeey0xLzR9LiQkCgoKIyBTbG9wZSBvZiBqdXZlbmlsZSBzcGVjdHJ1bQoKV2UgaGF2ZSBzZWVuIHRoYXQgZm9yIGp1dmVuaWxlIGZpc2ggdGhlIGdyb3d0aCByYXRlIGFuZCB0aGUgZGVhdGggcmF0ZSBhcmUgYm90aApwb3dlciBsYXdzIHdpdGggZXhwb25lbnRzICRwPTMvNCQgYW5kICRwLTE9LTEvNCQgcmVzcGVjdGl2ZWx5IGFuZCB0aGVuIGJ5CnNvbHZpbmcgYSBkaWZmZXJlbnRpYWwgZXF1YXRpb24gd2UgY2FuIGRlcml2ZSB0aGF0IHRoZSBqdXZlbmlsZSBzcGVjdHVtIGFsc28KZm9sbG93cyBhIHBvd2VyIGxhdzoKJCROKHcpID0gTl8wXCB3XnstXG11XzAvZ18wIC0gcH0kJAoKSSBjYW4ndCBkbyB0aGUgbWF0aHMgd2l0aCB5b3UgKGFuZCB5b3UgcHJvYmFibHkgZG9uJ3Qgd2FudCBtZSB0byBhbnl3YXkpLCBidXQKd2UgY2FuIGNoZWNrIHRoaXMgY2xhaW0gbnVtZXJpY2FsbHkuIExldCdzIGxvb2sgYXQgdGhlIHNwZWN0cnVtIHVwIHRvIAoxMCBncmFtcy4gQnkgbm93IHdlIGtub3cgaG93IHRvIGRvIHRoaXMuIFdlIGZpcnN0IGNvbnZlcnQgdGhlIG51bWJlciBkZW5zaXR5Cm1hdHJpeCBgbmAgaW50byBhIGRhdGFmcmFtZSBhbmQgdGhlbiBmaWx0ZXIgb3V0IGFsbCBvYnNlcnZhdGlvbnMgdGhhdCBkbyBub3QKaGF2ZSAkd1xsZXEgMTAkLiBUaGUgcmVzdWx0aW5nIGRhdGEgZnJhbWUgd2UgcGFzcyB0byBgZ2dwbG90KClgIGFuZCBhc2sgaXQKdG8gcGxvdCBhIGxpbmUgb24gbG9nLWxvZyBheGVzLgpgYGB7cn0KbmYgPC0gbWVsdChuKSAlPiUgCiAgZmlsdGVyKHcgPD0gMTApCgpnZ3Bsb3QobmYpICsKICBnZW9tX2xpbmUoYWVzKHggPSB3LCB5ID0gdmFsdWUpKSArCiAgc2NhbGVfeF9sb2cxMCgpICsKICBzY2FsZV95X2xvZzEwKCkgKwogIGxhYnMoeCA9ICJXZWlnaHQgW2ddIiwKICAgICAgIHkgPSAiTnVtYmVyIGRlbnNpdHkgWzEvZ10iKQpgYGAKClRoYXQgY29uZmlybXMgd2hhdCB3ZSBoYWQgc2VlbiBlYXJsaWVyLCB0aGF0IGZvciBmaXNoIGxlc3MgdGhhbiAxMCBncmFtcwp0aGUgbnVtYmVyIGRlbnNpdHkgaXMgYSBwb3dlciBsYXcuIFRvIGRldGVybWluZSB0aGUgZXhwb25lbnQgb2YgdGhlIHBvd2VyCmxhdyB3ZSBuZWVkIHRoZSBzbG9wZSBvZiB0aGF0IHN0cmFpZ2h0IGxpbmUgaW4gdGhlIGxvZy1sb2cgcGxvdCwgYW5kIHRoZQplYXNpZXN0IHdheSB0byBkbyB0aGF0IGlzIHRvIGZpdCBhIGxpbmVhciBtb2RlbCB0byB0aGUgbG9nIHZhcmlhYmxlczoKYGBge3J9CmxtKGxvZyhuZiR2YWx1ZSkgfiBsb2cobmYkdykpCmBgYAoKVGhlIG1hdGhlbWF0aWNzIGNsYWltZWQgdGhhdCB0aGUgZXhwb25lbnQgc2hvdWxkIGJlICQtXG11XzAgLyBnXzAgLSBwJC4gV2UKaGF2ZSBhbHJlYWR5IG9ic2VydmVkIHRoYXQgJFxtdV8wID0gMS45MDkkIGFuZCAkZ18wID0gMi4xMjkkIHNvIHdlIGdldApgYGB7cn0KLTEuOTA5IC8gMi4xMjkgLSAzLzQKYGBgCgpUaGF0IGlzIG5vdCBxdWl0ZSB0aGUgcmVzdWx0IG9mIHRoZSBsaW5lYXIgbW9kZWwgZml0LCBidXQgdGhhdCBpcyB0aGUgbmF0dXJlCm9mIG51bWVyaWNhbCBjYWxjdWxhdGlvbnM6IG9uZSBnZXRzIGRpc2NyZXRpc2F0aW9uIGVycm9ycyBhbmQgcm91bmRpbmcgZXJyb3JzLgoKCiMgUmVwcm9kdWN0aW9uCgpOb3cgdGhhdCB3ZSB1bmRlcnN0YW5kIHRoZSBzaGFwZSBvZiB0aGUgc2l6ZSBzcGVjdHJ1bSBmb3IgdGhlIGp1dmVuaWxlIGZpc2gsCmxldCB1cyB0cnkgdG8gdW5kZXJzdGFuZCB0aGUgYnVsZ2UgdGhhdCBmb2xsb3dzLiBUaGUgaW5jcmVhc2Ugb2YgYWJ1bmRhbmNlIHRoYXQKd2Ugc2VlIGF0IGFyb3VuZCB0aGUgbWF0dXJpdHkgc2l6ZSBvZiBvdXIgc3BlY2llcyBpcyBkdWUgdG8gYSBkcm9wIGluIGdyb3d0aApyYXRlIGF0IHRoYXQgc2l6ZS4gVGhpcyBpbiB0dXJuIGlzIGR1ZSB0byB0aGUgZmFjdCB0aGF0IHRoZSBtYXR1cmUgZmlzaCAKaW52ZXN0cyBzb21lIG9mIGl0cyBlbmVyZ3kgaW5jb21lIGludG8gcmVwcm9kdWN0aW9uLiAKClRoZSBwcm9wb3J0aW9uIG9mIHRoZSBhdmFpbGFibGUgZW5lcmd5IHRoYXQgaXMgaW52ZXN0ZWQgaW50byByZXByb2R1Y3Rpb24gaXMKc3RvcmVkIGluIHRoZSBgcHNpYCBzbG90IG9mIHRoZSBgcGFyYW1zYCBvYmplY3QuIEFzIHNvIG1hbnkgb2YgdGhlIG90aGVyCnF1YW50aXRpZXMgaW4gbWl6ZXIsIGl0IGlzIGEgbWF0cml4IHdpdGggb25lIHJvdyBmb3IgZWFjaCBzcGVjaWVzIGFuZCBvbmNlCmNvbHVtbiBmb3IgZWFjaCBzaXplIGNsYXNzLiBTbyB3ZSBjYW4gcGxvdCBpdCBieSBtZWx0aW5nIHRoZSBtYXRyaXggaW50byBhIGRhdGEKZnJhbWUgYW5kIHRoZW4gdXNpbmcgdGhpcyBpbiBgZ2dwbG90KClgLgpgYGB7cn0KZ2dwbG90KG1lbHQocGFyYW1zQHBzaSkpICsKICBnZW9tX2xpbmUoYWVzKHggPSB3LCB5ID0gdmFsdWUpKQpgYGAKCkhvdyB3YXMgdGhpcyBtYXR1cml0eSBjdXJ2ZSBzcGVjaWZpZWQ/IFRoZXJlIGFyZSBmb3VyIHNwZWNpZXMgcGFyYW1ldGVycwppbnZvbHZlZDoKKiB0aGUgbWF0dXJpdHkgc2l6ZSBgd19tYXRgIGF0IHdoaWNoIDUwJSBvZiB0aGUgaW5kaXZpZHVhbHMgYXJlIG1hdHVyZS4KKiB0aGUgc2l6ZSBgd19tYXQyNWAgYXQgd2ljaCAyNSUgb2YgdGhlIGluZGl2aWR1YWxzIGFyZSBtYXR1cmUuCiogdGhlIGFzeW1wdG90aWMgc2l6ZSBgd19pbmZgIGF0IHdoaWNoIGFuIG9yZ2FuaXNtIGludmVzdHMgMTAwJSBvZiBpdHMgaW5jb21lCmludG8gcmVwcm9kdWN0aW9uIGFuZCB0aHVzIGdyb3d0aCBpcyB6ZXJvLgoqIGFuIGV4cG9uZW50IGBtYCB0aGF0IGRldGVybWluZXMgaG93IHRoZSBwcm9wb3J0aW9uIHRoYXQgYW4gaW5kaXZpZHVhbAppbnZlc3RzIGludG8gcmVwcm9kdWN0aW9uIHNjYWxlcyB3aXRoIGl0cyBzaXplLgoKU3VjaCBzcGVjaWVzIHBhcmFtZXRlcnMgYXJlIGNvbnRhaW5lZCBpbiB0aGUgYHNwZWNpZXNfcGFyYW1zYCBzbG90IG9mIHRoZQpgcGFyYW1zYCBvYmplY3QuCmBgYHtyfQpwYXJhbXNAc3BlY2llc19wYXJhbXMKYGBgCgpBcyB5b3UgY2FuIHNlZSwgdGhlcmUgYXJlIGEgbG90IG9mIG90aGVyIHNwZWNpZXMgcGFyYW1ldGVycywgc29tZSBvZiB3aGljaCB3ZQp3aWxsIHRhbGsgYWJvdXQgbGF0ZXIuIEZvciBub3cgbGV0J3MganVzdCBzZWxlY3QgdGhlIDQgcGFyYW1ldGVycyB3ZSBhcmUKaW50ZXJlc3RlZCBpbi4KYGBge3J9CnNlbGVjdChwYXJhbXNAc3BlY2llc19wYXJhbXMsIHdfbWF0LCB3X21hdDI1LCB3X2luZiwgbSkKYGBgCgoKIyMgRWZmZWN0IG9mIGNoYW5nZSBpbiBtYXR1cml0eSBjdXJ2ZQpMZXQgdXMgaW52ZXN0aWdhdGUgd2hhdCBoYXBwZW5zIHdoZW4gd2UgY2hhbmdlIHRoZSBtYXR1cml0eSBjdXJ2ZS4gTGV0J3MgYXNzdW1lCnRoZSBtYXR1cml0eSBzaXplIGlzIGFjdHVhbGx5IDQwIGdyYW1zIGFuZCB0aGUgc2l6ZSBhdCB3aGljaCAyNSUgb2YgaW5kaXZpZHVhbHMgaXMgbWF0dXJlIGlzIDMwIGdyYW1zLiBMZXQgdXMgY2hhbmdlIHRoZSB2YWx1ZXMgaW4gdGhlCmBzcGVjaWVzX3BhcmFtc2AgZGF0YSBmcmFtZS4gQnV0IGZpcnN0IHdlIG1ha2UgYSBjb3B5IG9mIHRoZSBwYXJhbXMgb2JqZWN0IApzbyB0aGF0IHdlIGNhbiBrZWVwIHRoZSBvbGQgdmVyc2lvbiBhcm91bmQgdW5jaGFuZ2VkLgpgYGB7cn0KcGFyYW1zX2NoYW5nZWRfbWF0dXJpdHkgPC0gcGFyYW1zCmBgYAoKSW4gdGhpcyBjb3B5IHdlIG5vdyBjaGFuZ2UgdGhlIHNwZWNpZXMgcGFyYW10ZXJzCmBgYHtyfQpwYXJhbXNfY2hhbmdlZF9tYXR1cml0eUBzcGVjaWVzX3BhcmFtcyR3X21hdCA8LSA0MApwYXJhbXNfY2hhbmdlZF9tYXR1cml0eUBzcGVjaWVzX3BhcmFtcyR3X21hdDI1IDwtIDMwCnNlbGVjdChwYXJhbXNfY2hhbmdlZF9tYXR1cml0eUBzcGVjaWVzX3BhcmFtcywgd19tYXQsIHdfbWF0MjUsIHdfaW5mLCBtKQpgYGAKClRoaXMgaGFzIG5vdCB5ZXQgY2hhbmdlZCB0aGUgYHBhcmFtc0Bwc2lgIHNsb3QgaW4gdGhlIGBwYXJhbXNgIG9iamVjdCB5ZXQuIEZvcgp0aGF0IHdlIG5lZWQgdG8gY2FsbCB0aGUgYHNldFJlcHJvZHVjdGlvbigpYCBmdW5jdGlvbi4KYGBge3J9CnBhcmFtc19jaGFuZ2VkX21hdHVyaXR5IDwtIHNldFJlcHJvZHVjdGlvbihwYXJhbXNfY2hhbmdlZF9tYXR1cml0eSkKYGBgCgpOb3cgdGhlIG1hdHVyaXR5IGN1cnZlIGhhcyBjaGFuZ2VkLCB3aGljaCB3ZSBjYW4gdmVyaWZ5IGJ5IHBsb3R0aW5nIGl0CmBgYHtyfQpnZ3Bsb3QobWVsdChwYXJhbXNfY2hhbmdlZF9tYXR1cml0eUBwc2kpKSArCiAgZ2VvbV9saW5lKGFlcyh4ID0gdywgeSA9IHZhbHVlKSkKYGBgCgpBdCB0aGlzIHBvaW50IGxldCdzIHRha2UgYSBsaXR0bGUgYnJlYWsgYW5kIGxlYXJuIGhvdyB0byBkcmF3IHR3byBjdXJ2ZXMgaW4KdGhlIHNhbWUgZ3JhcGguIEhvdyBjYW4gd2Ugc2VlIHRoZSBvbGQgbWF0dXJpdHkgY3VydmUgYW5kIHRoZSBuZXcgbWF0dXJpdHkKY3VydmUgaW4gdGhlIHNhbWUgcGxvdD8gRmlyc3Qgd2UgY3JlYXRlIHRoZSBkYXRhIGZyYW1lcyB3ZSB3b3VsZCBuZWVkIGZvcgp0aGUgc2VwYXJhdGUgcGxvdHMKYGBge3J9CnBzaWYgPC0gbWVsdChwYXJhbXNAcHNpKQpwc2lmX2NoYW5nZWRfbWF0dXJpdHkgPC0gbWVsdChwYXJhbXNfY2hhbmdlZF9tYXR1cml0eUBwc2kpCmBgYApUaGVuIHdlIGFkZCBhbiBleHRyYSBjb2x1bW4gdG8gZWFjaCBkYXRhZnJhbWUgZGVzY3JpYmluZyBpdApgYGB7cn0KcHNpZiR0eXBlID0gIm9yaWdpbmFsIgpwc2lmX2NoYW5nZWRfbWF0dXJpdHkkdHlwZSA9ICJjaGFuZ2VkIgpgYGAKVGhlbiB3ZSBiaW5kIHRoZSB0d28gZGF0YSBmcmFtZXMgdG9nZXRoZXIKYGBge3J9CnBzaWZfY29tYmluZWQgPC0gcmJpbmQocHNpZiwgcHNpZl9jaGFuZ2VkX21hdHVyaXR5KQpgYGAKYW5kIHNlbmQgdGhhdCBjb21iaW5lZCBkYXRhIGZyYW1lIHRvIGBnZ3Bsb3QoKWAKYGBge3J9CmdncGxvdChwc2lmX2NvbWJpbmVkKSArCiAgZ2VvbV9saW5lKGFlcyh4ID0gdywgeSA9IHZhbHVlLCBjb2xvdXIgPSB0eXBlKSkKYGBgCgpUaGlzIGNoYW5nZSBpbiB0aGUgbWF0dXJpdHkgY3VydmUgb2YgY291cnNlIGltcGxpZXMgYSBjaGFuZ2UgaW4gdGhlIGdyb3d0aApyYXRlcy4KCiMjIEV4ZXJjaXNlIDQKTWFrZSBhIHBsb3Qgc2hvd2luZyB0aGUgZ3Jvd3RoIHJhdGVzIG9mIHRoZSBvcmlnaW5hbCBtb2RlbCBhbmQgb2YgdGhlIG1vZGVsCndpdGggdGhlIGNoYW5nZWQgbWF0dXJpdHkgY3VydmUuCgoKTmV4dCBsZXQgdXMgbG9vayBob3cgdGhlIHN0ZWFkeSBzdGF0ZSBzcGVjdHJ1bSBoYXMgY2hhbmdlZC4gV2UgZmlyc3QgbmVlZCB0bwpydW4gdGhlIGNoYW5nZWQgbW9kZWwgdG8gc3RlYWR5IHN0YXRlCmBgYHtyfQpwYXJhbXNfY2hhbmdlZF9tYXR1cml0eSA8LSBzdGVhZHkocGFyYW1zX2NoYW5nZWRfbWF0dXJpdHkpCmBgYAoKV2UgdXNlIHRoZSBzYW1lIHRlY2huaXF1ZSBhcyBhYm92ZSB0byBwbG90IHRoZSBzdGVhZHktc3RhdGUgc3BlY3RyYSBvZiBib3RoCm1vZGVscyBvbiB0b3Agb2YgZWFjaCBvdGhlci4KYGBge3J9Cm5mIDwtIG1lbHQocGFyYW1zQGluaXRpYWxfbikKbmZfY2hhbmdlZF9tYXR1cml0eSA8LSBtZWx0KHBhcmFtc19jaGFuZ2VkX21hdHVyaXR5QGluaXRpYWxfbikKbmYkdHlwZSA8LSAib3JpZ2luYWwiCm5mX2NoYW5nZWRfbWF0dXJpdHkkdHlwZSA8LSAiY2hhbmdlZCIKbmZfY29tYmluZWQgPC0gcmJpbmQobmYsIG5mX2NoYW5nZWRfbWF0dXJpdHkpCmdncGxvdChuZl9jb21iaW5lZCkgKwogIGdlb21fbGluZShhZXMoeCA9IHcsIHkgPSB2YWx1ZSwgY29sb3VyID0gdHlwZSkpICsKICBzY2FsZV94X2xvZzEwKCkgKwogIHNjYWxlX3lfbG9nMTAoKSArCiAgbGFicyh4ID0gIldlaWdodCBbZ10iLAogICAgICAgeSA9ICJOdW1iZXIgZGVuc2l0eSBbMS9nXSIpCmBgYAoKQXMgZXhwZWN0ZWQsIHRoZSBidW1wIGhhcHBlbnMgbGF0ZXIgZHVlIHRvIHRoZSBsYXJnZXIgbWF0dXJpdHkgc2l6ZSBhbmQgaXQgaXMKbGVzcyBwcm9ub3VuY2VkLCBiZWNhdXNlIHRoZSBtYXR1cml0eSBjdXJ2ZSBpcyBsZXNzIHN0ZWVwLgoKCiMjIFJlcHJvZHVjdGl2ZSBlZmZpY2llbmN5CgpTbyB3aGF0IGhhcHBlbnMgd2l0aCB0aGUgZW5lcmd5IHRoYXQgaXMgaW52ZXN0ZWQgaW50byByZXByb2R1Y3Rpb24/IEl0IGxlYWRzCnRvIHNwYXduaW5nIGFuZCB0aHVzIHRoZSBpbmZsdXggb2YgbmV3IGluZGl2aWR1YWxzIGF0IHRoZSBlZ2cgc2l6ZS4gVGhpcwpjb252ZXJzaW9uIG9mIGVuZXJneSBpbnZlc3RlZCBpbnRvIHJlcHJvZHVjdGlvbiBpbnRvIGVnZyBiaW9tYXNzIGlzIAppbmVmZmljaWVudC4gRmlyc3RseSBtdWNoIGVuZXJneSBpcyBzcGVudCBvbiB0aGluZ3MgbGlrZSBtaWdyYXRpb24gdG8Kc3Bhd25pbmcgZ3JvdW5kcywgcmF0aGVyIHRoYW4gb24gcHJvZHVjdGlvbiBvZiBnb25hZGljIG1hc3MuIFNlY29uZGx5LCBvbmx5CmEgc21hbGwgcHJvcG9ydGlvbiBvZiBlZ2dzIHRoYXQgYXJlIHByb2R1Y2VkIGFyZSB2aWFibGUgYW5kIGhhdGNoIGludG8gbGFydmFlLgoKSW4gZmFjdCwgaW4gb3JkZXIgZm9yIHRoZSBwb3B1bGF0aW9uIHRvIGJlIGF0IHN0ZWFkeSBzdGF0ZSwgdGhlIHJlcHJvZHVjdGl2ZQplZmZpY2llbmN5IGhhcyB0byBoYXZlIGEgcGFydGljdWxhciB2YWx1ZS4gSWYgaXQgd2VyZSBoaWdoZXIsIHRoZSBwb3B1bGF0aW9uCndvdWxkIGluY3JlYXNlLCBpZiBpdCB3YXMgbG93ZXIsIHRoZSBwb3B1bGF0aW9uIHdvdWxkIGRlY3JlYXNlIHdpdGggdGltZS4gVGhlCmBzdGVhZHkoKWAgZnVuY3Rpb24gaGFzIHNldCB0aGUgcmVwcm9kdWN0aXZlIGVmZmljaWVuY3kgdG8ganVzdCB0aGUgcmlnaHQgdmFsdWUKYW5kIGhhcyBzdG9yZWQgaXQgaW4gdGhlIGBlcmVwcm9gIHNwZWNpZXMgcGFyYW1ldGVyLgpgYGB7cn0KcGFyYW1zQHNwZWNpZXNfcGFyYW1zJGVyZXBybwpgYGAKClRoZSBtb2RlbCB3aXRoIHRoZSBjaGFuZ2VkIG1hdHVyaXR5IGN1cnZlIGxlYWRzIHRvIGEgZGlmZmVyZW50IHJhdGUgb2YgCmludmVzdG1lbnQgaW50byByZXByb2R1Y3Rpb24gYW5kIHRodXMgbmVlZHMgYSBzbGlnaHRseSBkaWZmZXJlbnQgcmVwcm9kdWN0aXZlCmVmZmljaWVuY3kgdG8gcmVtYWluIGF0IHN0ZWFkeSBzdGF0ZToKYGBge3J9CnBhcmFtc19jaGFuZ2VkX21hdHVyaXR5QHNwZWNpZXNfcGFyYW1zJGVyZXBybwpgYGAKClRoaXMgaXMgdGhlIHJlcHJvZHVjdGl2ZSBlZmZpY2llbmN5IGF0IHN0ZWFkeSBzdGF0ZS4gV2hlbiB0aGUgcG9wdWxhdGlvbiAKZGV2aWF0ZXMgZnJvbSB0aGUgc3RlYWR5IHN0YXRlLCBmb3IgZXhhbXBsZSBkdWUgdG8gYSBjaGFuZ2UgaW4gZmlzaGluZywgdGhlCnJlcHJvZHVjdGl2ZSBlZmZpY2llbmN5IGNhbiBiZSBzZXQgdG8gY2hhbmdlIGFjY29yZGluZyB0byBhIEJldmVydG9uLUhvbHQKc3RvY2stcmVjcnVpdG1lbnQgY3VydmUuIFdlIHdpbGwgZGlzY3VzcyB0aGlzIGFnYWluIGxhdGVyLgoKCiMgRWZmZWN0IG9mIGRlY3JlYXNlZCBwcmV5IGF2YWlsYWJpbGl0eQoKVGhlIGVuZXJneSBpbmNvbWUgZm9yIGEgZmlzaCBjb21lcyBmcm9tIHByZWRhdGlvbiBvbiBpdHMgcHJleS4gSWYgdGhlcmUgaXMKbGVzcyBwcmV5LCB0aGUgZmlzaCBjb25zdW1lcyBsZXNzIGFuZCB0aHVzIGl0cyBncm93dGggcmF0ZSB3aWxsIGRlY3JlYXNlLgpMZXQgdXMgaW52ZXN0aWdhdGUgdGhpcyBieSBhcnRpZmljaWFsbHkgcmVtb3Zpbmcgc29tZSBwcmV5LgoKQmVsb3cgd2UgZGVjcmVhc2UgdGhlIGNvbW11bml0eSBzcGVjdHJ1bSBieSBhIGZhY3RvciBvZiAxMCBpbiB0aGUgc2l6ZSByYW5nZQpmcm9tIDFtZyB0byAxMG1nLiBXZSBhZ2FpbiBjcmVhdGUgYSBuZXcgcGFyYW1ldGVyIG9iamVjdCB0byBiZSBhYmxlIHRvIGtlZXAKdGhlIG9sZCBvbmUgYXJvdW5kCmBgYHtyfQpwYXJhbXNfc3RhcnZlZCA8LSBwYXJhbXMKc2l6ZV9yYW5nZSA8LSBwYXJhbXNAd19mdWxsID4gMTBeLTMgJiBwYXJhbXNAd19mdWxsIDwgMTBeLTIKcGFyYW1zX3N0YXJ2ZWRAaW5pdGlhbF9uX3BwW3NpemVfcmFuZ2VdIDwtIHBhcmFtc0Bpbml0aWFsX25fcHBbc2l6ZV9yYW5nZV0gLyAxMApwbG90U3BlY3RyYShwYXJhbXNfc3RhcnZlZCkKYGBgCgpUaGF0IGlzIG9mIGNvdXJzZSBxdWl0ZSBhIGRyYW1hdGljIGludGVydmVudGlvbiwgYW5kIHNvIHNob3VsZCBhbGxvdyB1cyB0byAKY2xlYXJseSBzZWUgaXRzIGVmZmVjdCBvbiB0aGUgc3RlYWR5LXN0YXRlIHNpemUgZGlzdHJpYnV0aW9uIG9mIG91ciBzcGVjaWVzLgpgYGB7cn0KcGFyYW1zX3N0YXJ2ZWQgPC0gc3RlYWR5KHBhcmFtc19zdGFydmVkKQpgYGAKYGBge3J9CnBsb3RTcGVjdHJhKHBhcmFtc19zdGFydmVkLCBwb3dlciA9IDIpCmBgYAoKQXMgZXhwZWN0ZWQsIHRoZSBsYWNrIG9mIGZvb2QgYW5kIHRoZSByZXN1bHRpbmcgc2xvdy1kb3duIGluIGdyb3d0aCBsZWFkcyB0bwphIHRyYWZmaWMgamFtOiBhIHBlYWsgaW4gdGhlIGJpb21hc3MgZGVuc2l0eS4gVGhpcyBzbG93LWRvd24gb2NjdXJzIGF0IGEKc2l6ZSB0aGF0IGlzIGFib3V0IGEgZmFjdG9yIG9mIDEwMCBsYXJnZXIgdGhhbiB0aGUgc2l6ZSBhdCB3aGljaCBmb29kIGlzCnJlZHVjZWQuIFdoeSB0aGlzIGlzIHdlIHdpbGwgZGlzY3VzcyBpbiB0aGUgbmV4dCBzZWN0aW9uLiBCdXQgZmlyc3QgCmludmVzdGlnYXRlIHdoYXQgaGFwcGVucyB3aGVuIHRoZSBwcmV5IGFidW5kYW5jZSBpcyBpbmNyZWFzZWQgaW5zdGVhZCBvZgpkZWNyZWFzZWQuCgojIyBFeGVyY2lzZSA1ClBsb3QgdGhlIHN0ZWFkeSBzdGF0ZSBiaW9tYXNzIGRlbnNpdHkgaW4gb3VyIG1vZGVsIHdoZW4gdGhlIGNvbW11bml0eQphYnVuZGFuY2UgaXMgaW5jcmVhc2VkIGJ5IGEgZmFjdG9yIG9mIDEwIGluIHRoZSBzaXplIHJhbmdlIGZyb20gMW1nIHRvIDEwbWcuCgojIFByZWRhdGlvbgoKSXQgaXMgbm93IHRpbWUgdG8gZGlzY3VzcyB0aGUgaW1wb3J0YW50IGlzc3VlIG9mIHByZWRhdGlvbi4gSXQgaXMgdGhyb3VnaApwcmVkYXRpb24gdGhhdCB0aGUgZmlzaCBvYnRhaW5zIHRoZSBlbmVyZ3kgaXQgbmVlZHMgdG8gbWFpbnRhaW4gaXRzIG1ldGFib2xpc20sCnRvIGdyb3cgYW5kIHRvIGludmVzdCBpbiByZXByb2R1Y3Rpb24uIFNvIGl0IGlzIGltcG9ydGFudCBob3cgd2UgbW9kZWwgdGhpcwpwcmVkYXRpb24uCgpUaGUgZWFzaWVzdCBjYXNlIGluIHdoaWNoIHRvIHVuZGVyc3RhbmQgcHJlZGF0aW9uIGlzCnRvIGltYWdpbmUgYSBmaWx0ZXIgZmVlZGluZyBmaXNoLCBzd2ltbWluZyBhcm91bmQgd2l0aCBpdHMgbW91dGggb3Blbi4gCkNsZWFybHkgdGhlIGFtb3VudCBvZiBmb29kIGl0IHRha2VzIGluIGlzIGRldGVybWluZWQgYnkgZm91ciB0aGluZ3M6CgoqIHRoZSBkZW5zaXR5IG9mIHByZXkgaW4gdGhlIHdhdGVyLAoqIGhvdyBtdWNoIHZvbHVtZSBvZiB3YXRlciB0aGUgZmlzaCBpcyBhYmxlIHRvIGZpbHRlciwgd2hpY2ggd2lsbCBkZXBlbmQgb24KaG93IGZhc3QgaXQgc3dpbXMgYXMgd2VsbCBhcyBvbiBpdHMgZ2FwZSBzaXplLgoqIHdoYXQgcGFydCBvZiB0aGlzIHByZXkgdGhlIGZpc2ggaXMgYWJsZSB0byBmaWx0ZXIgb3V0IG9mIHRoZSB3YXRlciwgd2hpY2ggCndpbGwgYmUgbGltaXRlZCBieSBpdHMgZ2FwZSBzaXplIGFuZCBieSBob3cgZmluZSBpdHMgZ2lsbCByYWtlcnMgYXJlLAoqIGhvdyBmYXN0IGl0IGNhbiBkaWdlc3QgdGhlIGZvb2QuIElmIGl0IGNhbiBmaWx0ZXIgdGhlIHByZXkgZmFzdGVyIHRoYW4KaXQgY2FuIGRpZ2VzdCwgaXQgd2lsbCBoYXZlIHRvIHN0YXJ0IGxldHRpbmcgcHJleSBnbyB1bmVhdGVuLgoKRm9yIGEgbW9yZSBhY3RpdmUgaHVudGVyIHRoZSBzaXR1YXRpb24gd2lsbCBiZSBzaW1pbGFyLiBUaGUgcmF0ZSBhdCB3aGljaAppdCBwcmVkYXRlcyB3aWxsIGRlcGVuZCBvbiBmb3VyIHRoaW5nczoKCiogdGhlIGRlbnNpdHkgb2YgcHJleSBpbiB0aGUgd2F0ZXIKKiB0aGUgdm9sdW1lIG9mIHdhdGVyIHRoYXQgdGhlIGZpc2ggcGF0cm9scyBhbmQgaW4gd2hpY2ggaXQgd2lsbCBiZSBhYmxlIHRvIApzZWVrIG91dCBpdHMgcHJleS4gVGhpcyBtYXkgZGVwZW5kIG9uIHRoaW5ncyBsaWtlIHJhZGl1cyBvZiB2aXNpb24uCiogd2hpY2ggb2YgdGhpcyBkZXRlY3RlZCBwcmV5IHRoZSBmaXNoIGlzIGFibGUgdG8gY2F0Y2gsIHdoaWNoIHdpbGwgZGVwZW5kIG9uIGl0cyBtb3V0aApzaXplIGJ1dCBhbHNvIG9uIGl0cyBhZ2lsaXR5IGFuZCBza2lsbCBhcyB3ZWxsIGFzIG9uIHRoZSBkZWZlbnNpdmUgbWVjaGFuaXNtcwpvZiB0aGUgcHJleS4KKiBob3cgZmFzdCBpdCBjYW4gZGlnZXN0IHRoZSBmb29kLgoKT2YgdGhlc2UgZm91ciBmYWN0b3JzLCB3ZSBoYXZlIG9mIGNvdXJzZSBhbHJlYWR5IGJlZW4gZGlzY3Vzc2luZyB0aGUgZGVuc2l0eSBvZiBwcmV5LiBJbiB0aGUgbmV4dCBzZWN0aW9uIHdlIHdpbGwgZGlzY3VzcyB0aGUgYWJpbGl0eSB0byBmaWx0ZXIgb3V0IG9yIGNhdGNoIHByZXkgb2YKcGFydGljdWxhciBzaXplcywgd2hpY2ggd2UgbW9kZWwgdmlhIHRoZSBwcmVkYXRpb24ga2VybmVsLiBJbiB0aGUgc2VjdGlvbiBhZnRlcgp0aGF0IHdlIHdpbGwgZGlzY3VzcyB0aGUgc2VhcmNoIHZvbHVtZSBhbmQgdGhlbiBpbiB0aGUgZm9sbG93aW5nIHNlY3Rpb24gdGhlCm1heGltdW0gY29uc3VtcHRpb24gcmF0ZS4KCgojIyBUaGUgcHJlZGF0aW9uIGtlcm5lbAoKRmlzaCB3aWxsIGJlIHBhcnRpY3VsYXJseSBnb29kIGF0IGNhdGNoaW5nIHByZXkgaW4gYSBzcGVjaWZpYyByYW5nZSBvZiBzaXplcywgc21hbGxlciB0aGFuIAp0aGVtc2VsdmVzLgpUaGlzIGlzIGVuY29kZWQgaW4gdGhlIHNpemUtc3BlY3RydW0gbW9kZWwgYnkgdGhlIHByZWRhdGlvbiBrZXJuZWwuIExldCB1cwp0YWtlIGEgbG9vayBhdCB0aGUgcHJlZGF0aW9uIGtlcm5lbCBpbiBvdXIgbW9kZWwuIFdlIGNhbiBvYnRhaW4gaXQgd2l0aCB0aGUKZnVuY3Rpb24gYGdldFByZWRLZXJuZWwoKWAuCmBgYHtyfQpwcmVkX2tlcm5lbCA8LSBnZXRQcmVkS2VybmVsKHBhcmFtcykKYGBgCgpUaGlzIGlzIGEgbGFyZ2UgdGhyZWUtZGltZW5zaW9uYWwgYXJyYXkgKHByZWRhdG9yIHNwZWNpZXMgeCBwcmVkYXRvciBzaXplIHggcHJleSBzaXplKS4gV2UgZXh0cmFjdCB0aGUga2VybmVsIG9mIGEgcHJlZGF0b3Igb2Ygc2l6ZSAxMGcgKHVzaW5nIHRoYXQgd2UgCnJlbWVtYmVyIHRoYXQgdGhpcyBpcyBpbiBzaXplIGNsYXNzIDIwMSkKYGBge3J9CnByZWRfa2VybmVsXzEwIDwtIHByZWRfa2VybmVsWywgMjAxLCAsIGRyb3AgPSBGQUxTRV0KYGBgClRoZSBgZHJvcCA9IEZBTFNFYCBvcHRpb24gaXMgdGhlcmUgdG8gcHJldmVudCBSIGZyb20gZHJvcHBpbmcgYW55IG9mIHRoZQphcnJheSBkaW1lbnNpb25zLiBXZSBjYW4gbm93IHBsb3QgdGhpcyBhcyB1c3VhbApgYGB7cn0KZ2dwbG90KG1lbHQocHJlZF9rZXJuZWxfMTApKSArCiAgZ2VvbV9saW5lKGFlcyh4ID0gd19wcmV5LCB5ID0gdmFsdWUpKSArCiAgc2NhbGVfeF9sb2cxMCgpCmBgYAogCiBXZSBzZWUgdGhhdCB0aGUgcHJlZGF0b3Igb2Ygc2l6ZSAxMGcgbGlrZXMgdG8gZmVlZCBvbiBwcmV5IHRoYXQgaXMgYWJvdXQKIGEgZmFjdG9yIDEwMCBzbWFsbGVyIHRoYW4gaXRzZWxmLCBidXQgYWxzbyBmZWVkcyBvbiBvdGhlciBzaXplcywganVzdCB3aXRoCiByZWR1Y2VkIHByZWZlcmVuY2UuIFRoZSBwcmVmZXJyZWQgcHJlZGF0b3IvcHJleSBzaXplIHJhdGlvIGlzIGRldGVybWluZWQgYnkKIHRoZSBzcGVjaWVzIHBhcmFtZXRlciBgYmV0YWAgYW5kIHRoZSB3aWR0aCBvZiB0aGUgZmVlZGluZyBrZXJuZWwsIGkuZS4sIGhvdwogZnVzc3kgdGhlIHByZWRhdG9yIGlzIHJlZ2FyZGluZyB0aGVpciBwcmV5IHNpemUsIGlzIGRldGVybWluZWQgYnkgdGhlCiBzcGVjaWVzIHBhcmFtZXRlciBgc2lnbWFgLiBJbiBvdXIgbW9kZWwgdGhlc2UgaGF2ZSB0aGUgdmFsdWVzCmBgYHtyfQpzZWxlY3QocGFyYW1zQHNwZWNpZXNfcGFyYW1zLCBiZXRhLCBzaWdtYSkKYGBgCgpMZXQgdXMgY2hhbmdlIHRoZSBwcmVmZXJyZWQgcHJlZGF0b3IvcHJleSBtYXNzIHJhdGlvIGZyb20gMTAwIHRvIDEwMDAuCkFzIHVzdWFsLCB3ZSBmaXJzdCBjcmVhdGUgYSBjb3B5IG9mIHRoZSBwYXJhbWV0ZXIgb2JqZWN0IGJlZm9yZSBtYWtpbmcgY2hhbmdlcy4KQWZ0ZXIgY2hhbmdpbmcgdGhlIHNwZWNpZXMgcGFyYW1ldGVycyB3ZSBoYXZlIHRvIGNhbGwgYHNldFByZWRLZXJuZWwoKWAgdG8gCmFjdHVhbGx5IGNoYW5nZSB0aGUgcHJlZGF0aW9uIGtlcm5lbCBpbiB0aGUgbW9kZWwuIFRoZW4sIGFmdGVyIGNoYW5naW5nIHRoZQpwcmVkYXRpb24ga2VybmVsLCB3ZSBoYXZlIHRvIGRldGVybWluZSB0aGUgbmV3IHN0ZWFkeSBzdGF0ZSB3aXRoIGBzdGVhZHkoKWAuCkZpbmFsbHkgd2UgcGxvdCB0aGUgcmVzdWx0aW5nIHNwZWN0cnVtLgpgYGB7cn0KcGFyYW1zX3BrIDwtIHBhcmFtcwpwYXJhbXNfcGtAc3BlY2llc19wYXJhbXMkYmV0YSA8LSAxMDAwCnBhcmFtc19wayA8LSBzZXRQcmVkS2VybmVsKHBhcmFtc19waykKYGBgCgpMZXQncyBtYWtlIGEgcGxvdCB0byBzZWUgdGhhdCB0aGUgcHJlZGF0aW9uIGtlcm5lbCBoYXMgaW5kZWVkIGNoYW5nZWQuCmBgYHtyfQpnZXRQcmVkS2VybmVsKHBhcmFtc19waylbLCAyMDEsICwgZHJvcCA9IEZBTFNFXSAlPiUgCiAgbWVsdCgpICU+JSAKICBnZ3Bsb3QoKSArCiAgZ2VvbV9saW5lKGFlcyh4ID0gd19wcmV5LCB5ID0gdmFsdWUpKSArCiAgc2NhbGVfeF9sb2cxMCgpCmBgYAoKSWYgd2Ugbm93IGFnYWluIHJlZHVjZSB0aGUgcHJleSBpbiB0aGUgc2l6ZSByYW5nZSBmcm9tIDFtZyB0byAxMG1nIGFzIGJlZm9yZSwKd2Ugbm93IGV4cGVjdCB0aGlzIHRvIHByb2R1Y2UgYSBwZWFrIGluIHRoZSBiaW9tYXNzIHNwZWN0cnVtIHNvbWV3aGVyZQpiZXR3ZWVuIDFnIGFuZCAxMGcuIExldCdzIGNoZWNrLgpgYGB7cn0KcGFyYW1zX3BrQGluaXRpYWxfbl9wcCA8LSBwYXJhbXNfc3RhcnZlZEBpbml0aWFsX25fcHAKcGFyYW1zX3BrIDwtIHN0ZWFkeShwYXJhbXNfcGspCnBsb3RTcGVjdHJhKHBhcmFtc19waywgcG93ZXIgPSAyKQpgYGAKClllcywgYXMgZXhwZWN0ZWQuCgoKRm9yIGRldGFpbHMgb2YgaG93IGBiZXRhYCBhbmQgYHNpZ21hYCBwYXJhbWV0cmlzZSB0aGUgcHJlZGF0aW9uIGtlcm5lbCwgc2VlCmh0dHBzOi8vc2l6ZXNwZWN0cnVtLm9yZy9taXplci9kZXYvcmVmZXJlbmNlL2xvZ25vcm1hbF9wcmVkX2tlcm5lbC5odG1sI2RldGFpbHMuCkZvciBpbmZvcm1hdGlvbiBvbiBob3cgdG8gY2hhbmdlIHRoZSBwcmVkYXRpb24ga2VybmVsLCBzZWUKaHR0cHM6Ly9zaXplc3BlY3RydW0ub3JnL21pemVyL2Rldi9yZWZlcmVuY2Uvc2V0UHJlZEtlcm5lbC5odG1sI3NldHRpbmctcHJlZGF0aW9uLWtlcm5lbAoKSXQgaXMgdmVyeSBpbXBvcnRhbnQgbm90IHRvIGNvbmZ1c2UgdGhlIHByZXkgcHJlZmVyZW5jZSB3aXRoIHRoZSBkaWV0LiBKdXN0CmJlY2F1c2UgYSBwcmVkYXRvciBtaWdodCBwcmVmZXIgdG8gZmVlZCBvbiBwcmV5IG9mIGEgcGFydGljdWxhciBzaXplIGlmIGl0IGhhZApmcmVlIGNob2ljZSBkb2VzIG5vdCBtZWFuIHRoYXQgaXQgYWN0dWFsbHkgZmVlZHMgcHJlZG9taW5hbnRseSBvbiBzdWNoIHByZXkuClRoZSBhY3R1YWwgZGlldCBvZiB0aGUgZmlzaCBkZXBlbmRzIGFsc28gb24gdGhlIGF2YWlsYWJpbGl0eSBvZiBwcmV5LiBCZWNhdXNlCnNtYWxsZXIgcHJleSBhcmUgbW9yZSBhYnVuZGFudCwgdGhlIHJlYWxpc2VkIHByZWRhdG9yL3ByZXkgbWFzcyByYXRpbyBpbiB0aGUKZGlldCB3aWxsIGJlIHNtYWxsZXIgdGhhbiB0aGUgcHJlZmVycmVkIHByZWRhdG9yL3ByZXkgbWFzcyByYXRpby4gVGhpcyBpcwpwYXJ0aWN1bGFybHkgaW1wb3J0YW50IHdoZW4gZXN0aW1hdGluZyB0aGUgcHJlZGF0aW9uIGtlcm5lbCBmcm9tIHN0b21hY2ggZGF0YS4KCgojIyBFeGVyY2lzZSA2ClRoaXMgZXhlcmNpc2UgZ2l2ZXMgeW91IGEgZGlmZmVyZW50IHNldCBvZiBwcmVkYXRpb24ga2VybmVsIHBhcmFtZXRlcnMgdG8KaW52ZXN0aWdhdGUuCgojIyBTZWFyY2ggdm9sdW1lCk5leHQgd2UgY29uc2lkZXIgdGhlIGZhY3RvciB0aGF0IG1vZGVscyB0aGUgdm9sdW1lIG9mIHdhdGVyIGEgZmlsdGVyIGZlZWRlcgppcyBhYmxlIHRvIGZpbHRlciBpbiBhIGNlcnRhaW4gYW1vdW50IG9mIHRpbWUsIG9yIHRoZSB2b2x1bWUgb2Ygd2F0ZXIgYSAKZm9yYWdlIGZpc2ggaXMgYWJsZSB0byBwYXRyb2wgaW4gYSBjZXJ0YWluIGFtb3VudCBvZiB0aW1lLiBUaGlzIGlzIGRpZmZpY3VsdAp0byBtb2RlbCBmcm9uIGZpcnN0IHByaW5jaXBsZXMsIGFsdGhvdWdoIHBlb3BsZSBoYXZlIHRyaWVkIHRvIGFyZ3VlIGluIHRlcm1zCm9mIHN3aW1taW5nIHNwZWVkcyBvZiBmaXNoLiBXZSB3aWxsIHNpbXBseSBhc3N1bWUgdGhhdCB0aGlzIHNlYXJjaCB2b2x1bWUgcmF0ZSBpcyBhbHNvCmFuIGFsbG9tZXRyaWMgcmF0ZS4gTGV0ICRcZ2FtbWEodykkIGRlbm90ZSB0aGlzIHJhdGUgZm9yIGEgcHJlZGF0b3Igb2Ygc2l6ZQokdyQuIFRoZSB3ZSBhc3N1bWUgdGhhdAokJFxnYW1tYSh3KSA9IFxnYW1tYV8wXCB3XnEkJApmb3Igc29tZSBleHBvbmVudCAkcSQuIApXZSBrbm93IHRoYXQgYSBmaXNoIG5lZWRzIHRvIGNvbnN1bWUgcHJleSBhdCBhIHJhdGUgdGhhdCBzY2FsZXMgd2l0aCBpdHMKYm9keSBzaXplIHRvIHRoZSBwb3dlciBwLCB3aXRoIHAgYWJvdXQgMy80LiBXZSBhbHNvIGtub3cgdGhhdCB0aGUgcHJleQpkZW5zaXR5IHdpbGwgYmUgYXBwcm94aW1hdGVseSBkZXNjcmliZWQgYnkgdGhlIFNoZWxkb24gcG93ZXIgbGF3LCBpLmUuLAp0aGF0ICROKHcpID0gTl8wXCB3XnstXGxhbWJkYX0kIHdpdGggJFxsYW1iZGEkLiBBIGJpdCBvZiBtYXRocwp0aGVuIHNheXMgdGhhdAokJHEgPSAyIC0gXGxhbWJkYSArIG4kJApUaGlzIGV4cGxhaW5zIHRoZSBtZXNzYWdlIHlvdSBnb3Qgd2hlbiB5b3UgY3JlYXRlZCB0aGUgcGFyYW1zIG9iamVjdCB3aXRoIGEKY2VydGFpbiBjaG9pY2Ugb2YgJFxsYW1iZGEkOiBtaXplciBjaG9zZSB0aGUgc2VhcmNoIHZvbHVtZSBleHBvbmVudCBhdXRvbXRpY2FsbHkKYWNjb3JkaW5nIHRvIHRoaXMgZm9ybXVsYS4gSW4gdGhlIHJlYWwgd29ybGQgZXZvbHV0aW9uIHdpbGwgaGF2ZSBtYWRlIHN1cmUgdGhhdAp0aGUgZmlzaCB3aWxsIGhhdmUgZGV2ZWxvcGVkIGEgZmVlZGluZyBzdHJhdGVneSB0aGF0IGFsbG93cyBpdCB0byBjb3ZlciBpdHMKbWV0YWJvbGljIGNvc3RzLCBhbmQgdGh1cyBsZWFkcyB0byB0aGF0IHNlYXJjaCB2b2x1bWUgZXhwb25lbnQgb2YgJHEkLiBDbGVhcmx5CmZpbHRlciBmZWVkZXJzIGhhdmUgdGFrZW4gYSB2ZXJ5IGRpZmZlcmVudCByb3V0ZSB0byB0aGlzIHRoYW4gZm9yYWdlIGZpc2gsIGJ1dAp0aGUgcmVzdWx0IGlzIHRoZSBzYW1lLgoKTGV0IHVzIHNlZSB3aGF0IGVmZmVjdCBjaGFuZ2luZyB0aGUgY29lZmZpY2llbnQgJFxnYW1tYV8wJCBpbiB0aGUgc2VhcmNoCnZvbHVtZSByYXRlIGhhcy4gSXRzIGN1cnJlbnQgdmFsdWUgaW4gb3VyIG1vZGVsIGlzCmBgYHtyfQpwYXJhbXNAc3BlY2llc19wYXJhbXMkZ2FtbWEKYGBgCldlIGNoYW5nZSB0aGF0IHdpdGggYHNldFNlYXJjaFZvbHVtZSgpYCBhbmQgZmluZCB0aGUgbmV3IHN0ZWFkeSBzdGF0ZS4KYGBge3J9CnBhcmFtc19uZXdfZ2FtbWEgPC0gcGFyYW1zCnBhcmFtc19uZXdfZ2FtbWFAc3BlY2llc19wYXJhbXMkZ2FtbWEgPC0gMjAwMApwYXJhbXNfbmV3X2dhbW1hIDwtIHNldFNlYXJjaFZvbHVtZShwYXJhbXNfbmV3X2dhbW1hKSAlPiUgCiAgc3RlYWR5KCkKYGBgCgpXZSBjYW4gc2VlIHRoZSBlZmZlY3QgaW4gdGhlIGdyb3d0aCBjdXJ2ZSBvZiBvdXIgc3BlY2llcy4gSW4gdGhlIG9yaWdpbmFsIAptb2RlbCBpdCBsb29rcyBhcyBmb2xsb3dzOgpgYGB7ciB3YXJuaW5nPUZBTFNFfQpwbG90R3Jvd3RoQ3VydmVzKHBhcmFtcywgc3BlY2llcyA9ICIxIikKYGBgCgpJbiB0aGUgbW9kaWZpZWQgbW9kZWwgaXQgbG9va3MgbGlrZQpgYGB7ciB3YXJuaW5nPUZBTFNFfQpwbG90R3Jvd3RoQ3VydmVzKHBhcmFtc19uZXdfZ2FtbWEsIHNwZWNpZXMgPSAiMSIpCmBgYAoKIyMgRXhlcmNpc2UgNwpXaGF0IGVmZmVjdCB3aWxsIHRoaXMgY2hhbmdlIGluIGdyb3d0aCByYXRlIGhhdmUgb24gdGhlIHNsb3BlIG9mIHRoZSBqdXZlbmlsZQpzcGVjdHJ1bT8gV2lsbCBpdCBiZSBzdGVlcGVyIG9yIHNoYWxsb3dlcj8gTWFrZSB0aGUgcGxvdCBvZiB0aGUgc3BlY3RydW0gdG8Kc2VlLgoKIyMgRmVlZGluZyBsZXZlbApBIHByZWRhdG9yIHdpbGwgaGF2ZSBhIG1heGltdW0gaW50YWtlIHJhdGUuIEl0IHdpbGwgc2ltcGxlIG5vdCBiZSBhYmxlIHRvIAp1dGlsaXNlIGZvb2QgYXQgYSBmYXN0ZXIgcmF0ZSB0aGFuIGl0cyBtYXhpbXVtIGludGFrZSByYXRlLiBPZiBjb3Vyc2UgaW4KcHJhY3RpY2UgaXQgd2lsbCBub3QgZmVlZCBhdCB0aGUgbWF4aW11bSBpbnRha2UgcmF0ZSBiZWNhdXNlIG9mIGxpbWl0ZWQgCmF2YWlsYWJpbGl0eSBvZiBwcmV5LiBXZSBkZXNjcmliZSB0aGlzIGJ5IHRoZSAqZmVlZGluZyBsZXZlbCogd2hpY2ggaXMgdGhlCnByb3BvcnRpb24gb2YgaXRzIG1heGltdW0gaW50YWtlIHJhdGUgYXQgd2hpY2ggdGhlIHByZWRhdG9yIGlzIGFjdHVhbGx5IHRha2luZwppbiBwcmV5LgoKSW4gb3VyIHNpbXBsZSBtb2RlbCB0aGlzIGZlZWRpbmcgbGV2ZWwgaXMgY29uc3RhbnQuCmBgYHtyfQpwbG90RmVlZGluZ0xldmVsKHBhcmFtcykKYGBgCgpJbiB0aGUgbW9kZWwgd2l0aCB0aGUgcmVkdWNlZCBzZWFyY2ggdm9sdW1lIHRoZSBmZWVkaW5nIGxldmVsIHdpbGwgYmUgbG93ZXIKYGBge3J9CnBsb3RGZWVkaW5nTGV2ZWwocGFyYW1zX25ld19nYW1tYSkKYGBgCgpPdXIgbW9kZWwgaXMgdGFraW5nIGFuIGFsbG9tZXRyaWMgZm9ybSBmb3IgdGhlIG1heGltdW0gaW50YWtlIHJhdGUgJGgodykkCmFzIGEgZnVuY3Rpb24gb2YgcHJlZGF0b3Igc2l6ZSAkdyQ6ICRoKHcpID0gaFwgd15uJC4gVGhlIGN1cnJlbnQgdmFsdWUgb2YKdGhlIGNvZWZmaWNpZW50ICRoJCBpcwpgYGB7cn0KcGFyYW1zQHNwZWNpZXNfcGFyYW1zJGgKYGBgCgpXZSBjYW4gY2hhbmdlIHRoZSBtYXhpbXVtIGludGFrZSByYXRlIHdpdGggYHNldEludGFrZU1heCgpYC4gCgojIE1vcnRhbGl0eQojIyBEZWF0aCBmcm9tIHByZWRhdGlvbgpPZiBjb3Vyc2UgZ3Jvd3RoIG9mIHRoZSBwcmVkYXRvciBpcyBvbmx5IG9uZSBhc3BlY3Qgb2YgcHJlZGF0aW9uLiBUaGUgb3RoZXIgaXMKdGhlIGRlYXRoIG9mIHRoZSBwcmV5LiBHcm93dGggYW5kIG1vcnRhbGl0eSBhcmUgY291cGxlZC4gSW5jcmVhc2VkIGdyb3d0aCBvZgpvbmUgY2xhc3Mgb2YgaW5kaXZpZHVhbHMgd2lsbCBuZWNlc3NpdGF0ZSBpbmNyZWFzZWQgZGVhdGggb2YgYW5vdGhlci4gVGhlcmUgaXMKbm8gZnJlZSBsdW5jaC4KCk9uY2Ugd2UgaGF2ZSBzcGVjaWZpZWQgdGhlIHByZWRhdGlvbiBwYXJhbWV0ZXJzLCB0aGVzZSBwYXJhbWV0ZXJzIGRldGVybWluZQpib3RoIHRoZSBncm93dGggb2YgcHJlZGF0b3JzIGJ1dCBhbHNvIHRoZSBtb3J0YWxpdHkgcmF0ZSBvZiBwcmV5LiBTbyB3ZQpkb24ndCBoYXZlIHRvIGludHJvZHVjZSBuZXcgcGFyYW10ZXJzIGluIHRoaXMgc2VjdGlvbi4KCiMjIEJhY2tncm91bmQgbW9ydGFsaXR5CkluIGFkZGl0aW9uIHRvIG1vcnRhbGl0eSBjYXVzZWQgYnkgcHJlZGF0aW9uIGZyb20gb3RoZXIgZmlzaCwgdGhlcmUgd2lsbCBiZQpzb21lIG1vcnRhbGl0eSBmcm9tIG90aGVyIGNhdXNlcy4gVGhpcyBjb3VsZCBiZSBwcmVkYXRpb24gZnJvbSBhbmltYWxzIHRoYXQgd2UKaGF2ZSBub3QgaW5jbHVkZWQgaW4gb3VyIG1vZGVsLCBsaWtlIHNlYSBiaXJkcyBvciBtYW1hbHMsIG9yIGl0IGNvdWxkIGJlIGRlYXRoCmZyb20gb2xkIGFnZSAoc2VuZXNjZW50IGRlYXRoKSBvciBkaXNlYXNlLiBNaXplciBhbGxvd3Mgc2V0dGluZyBvZgpiYWNrZ3JvdW5kIGRlYXRoIHdpdGggYHNldEJNb3J0KClgLgoKIyBGaXNoaW5nIG1vcnRhbGl0eQpUaGUgY2F1c2Ugb2YgbW9ydGFsaXR5IHRoYXQgaXMgbW9zdCB1bmRlciBvdXIgY29udHJvbCBpcyBtb3J0YWxpdHkgZnJvbSBmaXNoaW5nLgpZb3UgY2FuIHNlZSBob3cgZmlzaGluZyBpcyBzZXQgdXAgaW4gbWl6ZXIgYXQgCmh0dHBzOi8vc2l6ZXNwZWN0cnVtLm9yZy9taXplci9kZXYvcmVmZXJlbmNlL3NldEZpc2hpbmcuaHRtbCNzZXR0aW5nLWZpc2hpbmcuCkhlcmUgd2Ugb25seSBsb29rIGF0IGEgc2ltcGxlIGV4YW1wbGU6IHdlIGludHJvZHVjZSBmaXNoaW5nIG9uIG91ciBzcGVjaWVzCm9ubHkgZm9yIGZpc2ggYWJvdmUgMzAgZ3JhbXMuIEFsbCBmaXNoIGdyZWF0ZXIgdGhhbiAzMCBncmFtcyB3aWxsIGJlIGV4cG9zZWQKdG8gdGhlIHNhbWUgZmlzaGluZyBtb3J0YWxpdHkuIFdlIGNhbGwgdGhpcyBraW5kIG9mIGZpc2hpbmcKc2VsZWN0aXZpdHkgImtuaWZlX2VkZ2UiIHNlbGVjdGl2aXR5LiBNaXplciBjYW4gZGVhbCB3aXRoIG1vcmUgZ2VuZXJhbApzZWxlY3Rpdml0eSBjdXJ2ZXMsIGxpa2Ugc2lnbW9pZGFsIG9yIGRvdWJseSBzaWdtb2lkYWwuCmBgYHtyfQpwYXJhbXNfZmlzaGluZyA8LSBwYXJhbXMKcGFyYW1zX2Zpc2hpbmdAc3BlY2llc19wYXJhbXMkc2VsX2Z1bmMgPC0gImtuaWZlX2VkZ2UiCnBhcmFtc19maXNoaW5nQHNwZWNpZXNfcGFyYW1zJGtuaWZlX2VkZ2Vfc2l6ZSA8LSAzMApwYXJhbXNfZmlzaGluZyA8LSBzZXRGaXNoaW5nKHBhcmFtc19maXNoaW5nKQpgYGAKCldlIG5vdyBuZWVkIHRvIHNwZWNpZnkgdGhlIGZpc2hpbmcgZWZmb3J0IGFuZCBjYW4gdGhlbiBmaW5kIGFuZCBwbG90IHRoZQpzdGVhZHkgc3RhdGUKYGBge3J9CnBhcmFtc19maXNoaW5nQGluaXRpYWxfZWZmb3J0IDwtIDEKcGFyYW1zX2Zpc2hpbmcgPC0gc3RlYWR5KHBhcmFtc19maXNoaW5nKQpwbG90U3BlY3RyYShwYXJhbXNfZmlzaGluZywgcG93ZXIgPSAyKQpgYGAKCgojIE91dGxvb2sKClRoZSBmaXNoIHNwZWNpZXMgd2UgaGF2ZSBzdHVkaWVkIGhhZCB1bmxpbWl0ZWQgZm9vZCBhbmQgY29uc3RhbnQgbW9ydGFsaXR5LgpUaGF0IG9mIGNvdXJzZSBpcyB2ZXJ5IHVucmVhbGlzdGljLiBJbiByZWFsaXR5LCBmb29kIHdpbGwgYmVjb21lIHNjYXJjZSB3aGVuCnRoZSBmaXNoIHBvcHVsYXRpb24gaW5jcmVhc2VzIHRvbyBtdWNoLiBBbHNvIHRoZSBudW1iZXIgb2YgcHJlZGF0b3JzIHdpbGwgCmdyb3cuIFRoaXMgd2lsbCBsZWFkIHRvIGludGVyZXN0aW5nIGFuZCBpbXBvcnRhbnQgbm9uLWxpbmVhciBlZmZlY3RzIHRoYXQgd2UKd2lsbCBzdHVkeSBpbiB0aGUgbmV4dCB0dXRvcmlhbCBub3RlYm9vay4=