Fish tank dataset
In this experiment, 96 fish (dojofish, goldfish and zebrafish) were placed separately in a tank with two liters of water and a certain dose (in mg) of the poison EI-43,064. The resistance of the fish against the poison was measured as the amount of minutes the fish survived after being exposed to the poison (Surv_time
, in minutes). Additionally, the weight of each fish was measured.
Goal
The research goal is to study the association between the dose of the poison that was administered to the fish and their survival time.
Load the required libraries
Import the data
poison <- read_csv("https://raw.githubusercontent.com/statOmics/PSLSData/main/poison.csv")
## Rows: 96
## Columns: 4
## $ species <dbl> 0, 2, 1, 2, 0, 0, 2, 1, 0, 1, 0, 1, 0, 0, 2, 0, 0,…
## $ Weight <dbl> 1.884359, 1.732261, 2.830895, 1.748562, 2.114166, …
## $ Dose <dbl> 1.0, 1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7, 1.8, 1.9, …
## $ Surv_time <dbl> 3.461493, 2.110417, 11.419131, 1.821191, 3.277619,…
Data tidying
We can see a couple of things in the data that can be improved:
Capitalise the fist column name. Hint: use the rename
function.
Set the Species column as a factor. Hint: use the mutate
and as.factor
functions.
Change the species factor levels from 0, 1 and 2 to Dojofish, Goldfish and Zebrafish. Hint: use the fct_recode
function inside the mutate
function.
poison <- poison %>%
rename("Species" = "species") %>%
mutate(Species = as.factor(Species)) %>%
mutate(
Species = fct_recode(Species,
Dojofish = "0", Goldfish = "1", Zebrafish = "2"
)
)
poison
Data exploration
How many fish do we have per species?
poison %>%
count(Species)
Make a suitable visualization of the association between the dose and the survival time. Additionally, add the fish species as a color to the plot.
poison %>%
ggplot(aes(x = Dose, y = Surv_time)) +
geom_point() +
stat_smooth(method = "loess") +
geom_smooth(method = "lm", col = "black") +
ylab("Survival time (min)") +
xlab("Dose (mg)") +
geom_point(aes(col = Species)) + ## not necessary, additional layer of information
scale_color_manual(values = c("red", "darkgoldenrod", "black")) +
theme_bw()
## `geom_smooth()` using formula 'y ~ x'
## `geom_smooth()` using formula 'y ~ x'
The linear regression line (black) is a good approximation of the best fitting smooth line (blue) through the data. Based on this figure, it seems realistic to suggest a linear relationship between dose and survival, where higher doses have lower survival times (as expected). However, before we start with the regression analysis we must check if all required assumptions are met.
Important note on the dataset
In this dataset, there are multiple variables that can have an effect on the survival time of the fish. The most obvious one is the dose of poison that was administered (as displayed above). However, we could also imagine that heavier fish are less prone to the poison than light fish. Additionally, one fish species may be more resistant to the poison than the other.
As such, not taking into account species into the analysis will introduce problems regarding the assumption of independence of the data. The assumption of independence entails that knowing the response value of one observation (fish) does not learn us anything about the response values for another variable. This will not be the case here; the response values (survival times) of fish of the same species will be much more alike compared to those of fish from another species.
Thus, in order to correctly analyze this data, fish species
and weight
should be taken into consideration. For now, we will “avoid” taking into account the effect of species into the analysis by only performing an analysis for the dojofish. As such, we will filter the dataset so that it only contains observations for the Dojofish.
# filter the data so it only contains dojofish
poison_dojo <- poison %>%
filter(Species == "Dojofish")
Later in the course, we will come back to this dataset and perform a analysis that allows us to assess the different research hypotheses for all fish species at once!
The second predictor variable, Weight
, still may influence our analysis; fish with higher weight are expected to be more resistant to the poison. If there would be a systematic bias in the experiment, e.g. if all lighter fish obtained a low dose of poison and heavier fish obtained a high dose of poison (so, if the dose was not correctly randomized accros the different weights), then we would not be able to correctly estimate the linear association between Dose
and survival
; indeed, this relationship would be confounded by the effect of weight.
poison_dojo %>%
ggplot(aes(x = Dose, y = Weight)) +
geom_point() +
ggtitle("Association between dose and weight") +
theme_bw() +
stat_summary(
fun = mean, geom = "point",
col = "black", size = 4, shape = 24,
fill = "red"
)
In our dataset, there seems to be no systematic bias, i.e., no clear trend in the association between Dose
and Weight
. However, we do notice that the fish weights are not perfectly uniformly distributed across the different doses; we don’t see a clear trend, but we do see some fluctuations. To check if fluctuations of the size that we observe here could happen by random change if we carefully randomise, we may use simulations where we simulate the allocation of the fish to the different doses.
##
## Attaching package: 'gridExtra'
## The following object is masked from 'package:dplyr':
##
## combine
set.seed(1351)
plots <- lapply(
1:9,
function(x) {
poison_dojo %>%
mutate(Dose = sample(Dose)) %>% # randomization
ggplot(aes(x = Dose, y = Weight)) +
geom_point() +
theme_bw() +
stat_summary(
geom = "point",
fun = "mean",
col = "black",
size = 2,
shape = 24,
fill = "red"
)
}
)
do.call(gridExtra::grid.arrange, plots)
In the above simulation, we randomly assigned the different fish to different poison doses. Even though we did this randomly, we still see that by random chance there can be fluctuations as large as the ones observed in our real dataset. As such, we may conclude that there is indeed no systematic bias, i.e., no clear trend in the association between Dose
and Weight
.
Linear regression analysis
Assumptions of linear regression
List assumptions:
- The observations are independent of each other
- Linearity between the response and predictor variable
- The residues of the model must be normally distributed
- Homoscedasticity of the data
The first assumption is met based on the experimental design. In the data exploration phase, we saw that there is no clear trend in the association between Dose
and Weight
. With respect to species, we have “avoided” taking into account the effect of species into the analysis by only performing an analysis for the dojofish.
We will check the other assumptions by first fitting the linear model and plotting the output. As such, we will get all the required diagnostic plots.
# fit a linear regression model with 'Surv_time' as response variable and
# 'Dose' as predictor variabele
model <- lm(Surv_time ~ Dose, data = poison_dojo)
## display the diagnostic plots of the model
plot(model)
We have four diagnostic plots:
- Linearity with the Residuals vs fitted plot
- predictor of predictions \(\hat\beta_0+\hat\beta_1 x\) on \(X\)-axis
- residuals on \(Y\)-as \[e_i=y_i-\hat{g}(x_i)=y_i-\hat\beta_0-\hat\beta_1\times x_i,\]
If there would be a linear relationship in the data, the residuals are expected to be scattered at random around y=0 for the entire range of predicted values. This is clearly the case: the assumption of linearity is met.
- Normal Q-Q
- QQ-plot of the residuals \(e_i\).
The residuals of the linear regression model should be normally distributed. Given the second diagnostic plot, this seems not to be the case. In stead, we observe a short left tail and a long right tail. The assumption of normal residues is not met.
- Homoscedasticity
- Square-root of the absolute value of standardized residuals in function of the fitted values
To meet the third assumption of linear regression, the variance on the Square-root of the absolute value of standardized residuals must be similar over the entire range of fitted values. The smoother in the plot helps us with looking at this; it should be nicely horizontal over the entire range of fitted values. This seems not to be the case: for larger fitted values, the variance increase slightly. The assumption of homoscedasticity is not met.
Multiple assumptions are not met, so we may not continue by performing a linear regression.
We can try to remediate these deviations by log-transforming the data. Indeed, data with heavy right tails can often be normalized by applying this strategy.
Fit a (log-)linear model by log-transforming the response.Generate diagnostic plots and assess the assumptions.
log.model <- lm(log10(Surv_time) ~ Dose, data = poison_dojo)
plot(log.model)
Arguably, there might be some deviation from normality in the left tail of the distribution. However, when we would simulate data under the normality assumption, it seems that deviations of this size may be expected when normality is met:
set.seed(1406)
nobs <- nrow(poison_dojo)
data.frame(
y = c(log.model$res, rnorm(nobs * 8, sd = sigma(log.model))),
label = rep(c("orig", paste0("sim", 1:8)), each = nobs)
) %>%
ggplot(aes(sample = y)) +
geom_qq() +
geom_qq_line() +
facet_wrap(~label)
- The independence assumption is met.
- Upon log-transformation, the linearity assumption is still met.
- Upon log-transformation, the normality assumption is also met.
- Upon log-transformation, the homoscedasticity assumption is also met.
Look at the output of the log-linear model:
##
## Call:
## lm(formula = log10(Surv_time) ~ Dose, data = poison_dojo)
##
## Residuals:
## Min 1Q Median 3Q Max
## -0.2074 -0.1145 -0.0324 0.1039 0.3268
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 0.91722 0.10423 8.800 1.33e-10 ***
## Dose -0.27282 0.06648 -4.104 0.000215 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 0.1453 on 37 degrees of freedom
## Multiple R-squared: 0.3128, Adjusted R-squared: 0.2942
## F-statistic: 16.84 on 1 and 37 DF, p-value: 0.0002146
Compute the 95% confidence interval on the model parameters:
## 2.5 % 97.5 %
## (Intercept) 0.7060342 1.1284104
## Dose -0.4075255 -0.1381159
Interpretation on the log scale
Currently, all the outcomes should be interpreted on the log-scale. Indeed, since we are now modelling the log\(_{10}\) of survival time, we don’t have direct inference on survival time.
As such, we may interpret the output as follows:
Dojofish that are exposed to a higher dose of the poison will have a \(log_{10}\) survival time that is on average 0.27 lower per gram of poison that was administered additionally (95% CI [0.71, 0.41, 1.13, 0.14]). This decrease in survival time is significant on the 5% significance level (p<0.001).
Note, that the study is an experimental study so we can conclude that there is a causal effect of the poison dose and the survival time.
The average of the log10 of survival time for fish that were given a dose of 0 mg is 0.92.
Interpretation on the original scale
The interpretation the log-scale is quite difficult. To ease the interpretation, we will backtransform the results to the original scale (time in minutes). This we can do by
10^(summary(log.model)$coefficients[, "Estimate"])
## (Intercept) Dose
## 8.2646094 0.5335551
and of their confidence intervals:
## 2.5 % 97.5 %
## (Intercept) 5.0819949 13.4403459
## Dose 0.3912681 0.7275855
Now, we can interpret the results in terms of the geometric mean:
Dojo fish that are exposed to a higher dose of the poison will have a geometric mean of the survival time that is factor 0.53 (95% CI [0.39, 0.73]) per gram of poison that they received more than fish exposed to a lower dose. This decrease is very significant on the 5% significance level (p<0.001).
The geometric mean of the survival time for fish that were given a dose of 0 mg is 8.26 minutes.
In other words, our analysis seems to suggest that fish in uncontaminated water would only survive for about 8 minutes! This seems a little bit fishy…
Note, that this interpretation is not biologically relevant and is induced because we extrapolated considerably because all fish in the experiment were exposed to poison.
## Extract slope and intercept from the model
dojo_intercept <- coef(log.model)[1]
dojo_slope <- coef(log.model)[2]
ggplot(poison_dojo, aes(Dose, log10(Surv_time))) +
geom_point() +
geom_abline(
slope = dojo_slope, intercept = dojo_intercept,
color = "steelblue", size = 1.2
)
We can see that the dose value of 0 mg does not fall within the same range as our data. The model is only valid in the range of data that we use to build the model on!
However, in most applications we will never test for the intercept term.
Conclusion
There is a very significant effect of the poison on survival of Dojofish (p< 0.001). Dojofish that are exposed to a higher dose of the poison will have a survival time that decrease on average with a factor 1.87 per gram of poison that is added (95% CI [2.56, 1.37]).
In the tutorial of multiple regression, we will revisit this exercise. More specifically, we will there study the association between dose and survival for all the species in the dataset.
LS0tCnRpdGxlOiAiRXhlcmNpc2UgNi4xOiBMaW5lYXIgcmVncmVzc2lvbiBvbiB0aGUgZmlzaCB0YW5rIGRhdGFzZXQgLSBzb2x1dGlvbiIKYXV0aG9yOiAiTGlldmVuIENsZW1lbnQsIEplcm9lbiBHaWxpcyBhbmQgTWlsYW4gTWFsZmFpdCIKZGF0ZTogInN0YXRPbWljcywgR2hlbnQgVW5pdmVyc2l0eSAoaHR0cHM6Ly9zdGF0b21pY3MuZ2l0aHViLmlvKSIKLS0tCgojIEZpc2ggdGFuayBkYXRhc2V0CgpJbiB0aGlzIGV4cGVyaW1lbnQsIDk2IGZpc2ggKGRvam9maXNoLCBnb2xkZmlzaCBhbmQgemVicmFmaXNoKQp3ZXJlIHBsYWNlZCBzZXBhcmF0ZWx5IGluIGEgdGFuayB3aXRoIHR3byBsaXRlcnMgb2Ygd2F0ZXIgYW5kCmEgY2VydGFpbiBkb3NlIChpbiBtZykgb2YgdGhlIHBvaXNvbiBFSS00MywwNjQuIFRoZSByZXNpc3RhbmNlCm9mIHRoZSBmaXNoIGFnYWluc3QgdGhlIHBvaXNvbiB3YXMgbWVhc3VyZWQgYXMgdGhlIGFtb3VudCBvZgptaW51dGVzIHRoZSBmaXNoIHN1cnZpdmVkIGFmdGVyIGJlaW5nIGV4cG9zZWQgdG8gdGhlIHBvaXNvbiAoYFN1cnZfdGltZWAsIGluCm1pbnV0ZXMpLiBBZGRpdGlvbmFsbHksIHRoZSB3ZWlnaHQgb2YgZWFjaCBmaXNoIHdhcyBtZWFzdXJlZC4KCiMgR29hbAoKVGhlIHJlc2VhcmNoIGdvYWwgaXMgdG8gc3R1ZHkgdGhlIGFzc29jaWF0aW9uIGJldHdlZW4gdGhlIGRvc2Ugb2YKdGhlIHBvaXNvbiB0aGF0IHdhcyBhZG1pbmlzdGVyZWQgdG8gdGhlIGZpc2ggYW5kIHRoZWlyCnN1cnZpdmFsIHRpbWUuCgpMb2FkIHRoZSByZXF1aXJlZCBsaWJyYXJpZXMKCmBgYHtyLCBtZXNzYWdlID0gRkFMU0V9CmxpYnJhcnkodGlkeXZlcnNlKQpgYGAKCiMgSW1wb3J0IHRoZSBkYXRhCgpgYGB7ciwgbWVzc2FnZT1GQUxTRX0KcG9pc29uIDwtIHJlYWRfY3N2KCJodHRwczovL3Jhdy5naXRodWJ1c2VyY29udGVudC5jb20vc3RhdE9taWNzL1BTTFNEYXRhL21haW4vcG9pc29uLmNzdiIpCmBgYAoKYGBge3J9CmdsaW1wc2UocG9pc29uKQpoZWFkKHBvaXNvbikKYGBgCgojIERhdGEgdGlkeWluZwoKV2UgY2FuIHNlZSBhIGNvdXBsZSBvZiB0aGluZ3MgaW4gdGhlIGRhdGEgdGhhdCBjYW4gYmUgaW1wcm92ZWQ6CgoxLiBDYXBpdGFsaXNlIHRoZSBmaXN0IGNvbHVtbiBuYW1lLiAqSGludCo6IHVzZSB0aGUgYHJlbmFtZWAgZnVuY3Rpb24uCgoyLiBTZXQgdGhlIFNwZWNpZXMgY29sdW1uIGFzIGEgZmFjdG9yLiAqSGludCo6IHVzZSB0aGUgYG11dGF0ZWAgYW5kIGBhcy5mYWN0b3JgCmZ1bmN0aW9ucy4KCjMuIENoYW5nZSB0aGUgc3BlY2llcyBmYWN0b3IgbGV2ZWxzIGZyb20gMCwgMSBhbmQgMiB0bwpEb2pvZmlzaCwgR29sZGZpc2ggYW5kIFplYnJhZmlzaC4gKkhpbnQqOiB1c2UgdGhlIGBmY3RfcmVjb2RlYCBmdW5jdGlvbiBpbnNpZGUKdGhlIGBtdXRhdGVgIGZ1bmN0aW9uLgoKYGBge3J9CnBvaXNvbiA8LSBwb2lzb24gJT4lCiAgcmVuYW1lKCJTcGVjaWVzIiA9ICJzcGVjaWVzIikgJT4lCiAgbXV0YXRlKFNwZWNpZXMgPSBhcy5mYWN0b3IoU3BlY2llcykpICU+JQogIG11dGF0ZSgKICAgIFNwZWNpZXMgPSBmY3RfcmVjb2RlKFNwZWNpZXMsCiAgICAgIERvam9maXNoID0gIjAiLCBHb2xkZmlzaCA9ICIxIiwgWmVicmFmaXNoID0gIjIiCiAgICApCiAgKQoKcG9pc29uCmBgYAoKIyBEYXRhIGV4cGxvcmF0aW9uCgpIb3cgbWFueSBmaXNoIGRvIHdlIGhhdmUgcGVyIHNwZWNpZXM/CgpgYGB7cn0KcG9pc29uICU+JQogIGNvdW50KFNwZWNpZXMpCmBgYAoKTWFrZSBhIHN1aXRhYmxlIHZpc3VhbGl6YXRpb24gb2YgdGhlIGFzc29jaWF0aW9uIGJldHdlZW4KdGhlIGRvc2UgYW5kIHRoZSBzdXJ2aXZhbCB0aW1lLiBBZGRpdGlvbmFsbHksIGFkZCB0aGUgZmlzaCBzcGVjaWVzCmFzIGEgY29sb3IgdG8gdGhlIHBsb3QuCgpgYGB7cn0KcG9pc29uICU+JQogIGdncGxvdChhZXMoeCA9IERvc2UsIHkgPSBTdXJ2X3RpbWUpKSArCiAgZ2VvbV9wb2ludCgpICsKICBzdGF0X3Ntb290aChtZXRob2QgPSAibG9lc3MiKSArCiAgZ2VvbV9zbW9vdGgobWV0aG9kID0gImxtIiwgY29sID0gImJsYWNrIikgKwogIHlsYWIoIlN1cnZpdmFsIHRpbWUgKG1pbikiKSArCiAgeGxhYigiRG9zZSAobWcpIikgKwogIGdlb21fcG9pbnQoYWVzKGNvbCA9IFNwZWNpZXMpKSArICMjIG5vdCBuZWNlc3NhcnksIGFkZGl0aW9uYWwgbGF5ZXIgb2YgaW5mb3JtYXRpb24KICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gYygicmVkIiwgImRhcmtnb2xkZW5yb2QiLCAiYmxhY2siKSkgKwogIHRoZW1lX2J3KCkKYGBgCgpUaGUgbGluZWFyIHJlZ3Jlc3Npb24gbGluZSAoYmxhY2spIGlzIGEgZ29vZCBhcHByb3hpbWF0aW9uCm9mIHRoZSBiZXN0IGZpdHRpbmcgc21vb3RoIGxpbmUgKGJsdWUpIHRocm91Z2ggdGhlIGRhdGEuCkJhc2VkIG9uIHRoaXMgZmlndXJlLCBpdCBzZWVtcyByZWFsaXN0aWMgdG8gc3VnZ2VzdCBhIGxpbmVhcgpyZWxhdGlvbnNoaXAgYmV0d2VlbiBkb3NlIGFuZCBzdXJ2aXZhbCwgd2hlcmUgaGlnaGVyIGRvc2VzCmhhdmUgbG93ZXIgc3Vydml2YWwgdGltZXMgKGFzIGV4cGVjdGVkKS4gSG93ZXZlciwgYmVmb3JlIHdlCnN0YXJ0IHdpdGggdGhlIHJlZ3Jlc3Npb24gYW5hbHlzaXMgd2UgbXVzdCBjaGVjayBpZiBhbGwgcmVxdWlyZWQKYXNzdW1wdGlvbnMgYXJlIG1ldC4KCiMgSW1wb3J0YW50IG5vdGUgb24gdGhlIGRhdGFzZXQKCkluIHRoaXMgZGF0YXNldCwgdGhlcmUgYXJlIG11bHRpcGxlIHZhcmlhYmxlcyB0aGF0IGNhbiBoYXZlIGFuIGVmZmVjdCBvbiB0aGUKc3Vydml2YWwgdGltZSBvZiB0aGUgZmlzaC4gVGhlIG1vc3Qgb2J2aW91cyBvbmUgaXMgdGhlIGRvc2Ugb2YgcG9pc29uIHRoYXQgd2FzCmFkbWluaXN0ZXJlZCAoYXMgZGlzcGxheWVkIGFib3ZlKS4gSG93ZXZlciwgd2UgY291bGQgYWxzbyBpbWFnaW5lIHRoYXQgaGVhdmllcgpmaXNoIGFyZSBsZXNzIHByb25lIHRvIHRoZSBwb2lzb24gdGhhbiBsaWdodCBmaXNoLiBBZGRpdGlvbmFsbHksIG9uZSBmaXNoCnNwZWNpZXMgbWF5IGJlIG1vcmUgcmVzaXN0YW50IHRvIHRoZSBwb2lzb24gdGhhbiB0aGUgb3RoZXIuCgpBcyBzdWNoLCBub3QgdGFraW5nIGludG8gYWNjb3VudCBzcGVjaWVzIGludG8gdGhlIGFuYWx5c2lzIHdpbGwgaW50cm9kdWNlCnByb2JsZW1zIHJlZ2FyZGluZyB0aGUgYXNzdW1wdGlvbiBvZiAqaW5kZXBlbmRlbmNlKiBvZiB0aGUgZGF0YS4gVGhlIGFzc3VtcHRpb24Kb2YgKmluZGVwZW5kZW5jZSogZW50YWlscyB0aGF0IGtub3dpbmcgdGhlIHJlc3BvbnNlIHZhbHVlIG9mIG9uZSBvYnNlcnZhdGlvbgooZmlzaCkgZG9lcyBub3QgbGVhcm4gdXMgYW55dGhpbmcgYWJvdXQgdGhlIHJlc3BvbnNlIHZhbHVlcyBmb3IgYW5vdGhlcgp2YXJpYWJsZS4gVGhpcyB3aWxsIG5vdCBiZSB0aGUgY2FzZSBoZXJlOyB0aGUgcmVzcG9uc2UgdmFsdWVzIChzdXJ2aXZhbCB0aW1lcykKb2YgZmlzaCBvZiB0aGUgc2FtZSBzcGVjaWVzIHdpbGwgYmUgbXVjaCBtb3JlIGFsaWtlIGNvbXBhcmVkIHRvIHRob3NlIG9mIGZpc2gKZnJvbSBhbm90aGVyIHNwZWNpZXMuCgpUaHVzLCBpbiBvcmRlciB0byBjb3JyZWN0bHkgYW5hbHl6ZSB0aGlzIGRhdGEsIGZpc2ggYHNwZWNpZXNgIGFuZCBgd2VpZ2h0YApzaG91bGQgYmUgdGFrZW4gaW50byBjb25zaWRlcmF0aW9uLiAqKkZvciBub3csIHdlIHdpbGwgImF2b2lkIiB0YWtpbmcgaW50byoqCioqYWNjb3VudCB0aGUgZWZmZWN0IG9mIHNwZWNpZXMgaW50byB0aGUgYW5hbHlzaXMgYnkgb25seSBwZXJmb3JtaW5nIGFuKioKKiphbmFseXNpcyBmb3IgdGhlIGRvam9maXNoKiouIEFzIHN1Y2gsIHdlIHdpbGwgZmlsdGVyIHRoZSBkYXRhc2V0IHNvIHRoYXQKaXQgb25seSBjb250YWlucyBvYnNlcnZhdGlvbnMgZm9yIHRoZSBEb2pvZmlzaC4KCmBgYHtyfQojIGZpbHRlciB0aGUgZGF0YSBzbyBpdCBvbmx5IGNvbnRhaW5zIGRvam9maXNoCnBvaXNvbl9kb2pvIDwtIHBvaXNvbiAlPiUKICBmaWx0ZXIoU3BlY2llcyA9PSAiRG9qb2Zpc2giKQpgYGAKCkxhdGVyIGluIHRoZSBjb3Vyc2UsIHdlIHdpbGwgY29tZSBiYWNrIHRvIHRoaXMgZGF0YXNldCBhbmQgcGVyZm9ybSBhIGFuYWx5c2lzCnRoYXQgYWxsb3dzIHVzIHRvIGFzc2VzcyB0aGUgZGlmZmVyZW50IHJlc2VhcmNoIGh5cG90aGVzZXMgZm9yIGFsbCBmaXNoIHNwZWNpZXMKYXQgb25jZSEKClRoZSBzZWNvbmQgcHJlZGljdG9yIHZhcmlhYmxlLCBgV2VpZ2h0YCwgc3RpbGwgbWF5IGluZmx1ZW5jZSBvdXIgYW5hbHlzaXM7IGZpc2gKd2l0aCBoaWdoZXIgd2VpZ2h0IGFyZSBleHBlY3RlZCB0byBiZSBtb3JlIHJlc2lzdGFudCB0byB0aGUgcG9pc29uLiAqKklmKiogdGhlcmUKd291bGQgYmUgYSBzeXN0ZW1hdGljIGJpYXMgaW4gdGhlIGV4cGVyaW1lbnQsIGUuZy4gaWYgYWxsIGxpZ2h0ZXIgZmlzaCBvYnRhaW5lZAphIGxvdyBkb3NlICBvZiBwb2lzb24gYW5kIGhlYXZpZXIgZmlzaCBvYnRhaW5lZCBhIGhpZ2ggZG9zZSBvZiBwb2lzb24KKHNvLCBpZiB0aGUgZG9zZSB3YXMgbm90IGNvcnJlY3RseSByYW5kb21pemVkIGFjY3JvcyB0aGUgZGlmZmVyZW50IHdlaWdodHMpLAp0aGVuIHdlIHdvdWxkIG5vdCBiZSBhYmxlIHRvIGNvcnJlY3RseSBlc3RpbWF0ZSB0aGUgbGluZWFyIGFzc29jaWF0aW9uIGJldHdlZW4KYERvc2VgIGFuZCBgc3Vydml2YWxgOyBpbmRlZWQsIHRoaXMgcmVsYXRpb25zaGlwIHdvdWxkIGJlIGNvbmZvdW5kZWQgYnkgdGhlCmVmZmVjdCBvZiB3ZWlnaHQuCgpgYGB7ciwgbWVzc2FnZT1GQUxTRX0KcG9pc29uX2Rvam8gJT4lCiAgZ2dwbG90KGFlcyh4ID0gRG9zZSwgeSA9IFdlaWdodCkpICsKICBnZW9tX3BvaW50KCkgKwogIGdndGl0bGUoIkFzc29jaWF0aW9uIGJldHdlZW4gZG9zZSBhbmQgd2VpZ2h0IikgKwogIHRoZW1lX2J3KCkgKwogIHN0YXRfc3VtbWFyeSgKICAgIGZ1biA9IG1lYW4sIGdlb20gPSAicG9pbnQiLAogICAgY29sID0gImJsYWNrIiwgc2l6ZSA9IDQsIHNoYXBlID0gMjQsCiAgICBmaWxsID0gInJlZCIKICApCmBgYAoKSW4gb3VyIGRhdGFzZXQsIHRoZXJlIHNlZW1zIHRvIGJlICoqbm8gc3lzdGVtYXRpYyBiaWFzKiosIGkuZS4sIG5vIGNsZWFyIHRyZW5kCmluIHRoZSBhc3NvY2lhdGlvbiBiZXR3ZWVuIGBEb3NlYCBhbmQgYFdlaWdodGAuIEhvd2V2ZXIsIHdlIGRvIG5vdGljZSB0aGF0IHRoZQpmaXNoIHdlaWdodHMgYXJlIG5vdCBwZXJmZWN0bHkgdW5pZm9ybWx5IGRpc3RyaWJ1dGVkIGFjcm9zcyB0aGUgZGlmZmVyZW50IGRvc2VzOwp3ZSBkb24ndCBzZWUgYSBjbGVhciB0cmVuZCwgYnV0IHdlIGRvIHNlZSBzb21lIGZsdWN0dWF0aW9ucy4gVG8gY2hlY2sgaWYKZmx1Y3R1YXRpb25zIG9mIHRoZSBzaXplIHRoYXQgd2Ugb2JzZXJ2ZSBoZXJlIGNvdWxkIGhhcHBlbiBieSByYW5kb20gY2hhbmdlIGlmCndlIGNhcmVmdWxseSByYW5kb21pc2UsIHdlIG1heSB1c2Ugc2ltdWxhdGlvbnMgd2hlcmUgd2Ugc2ltdWxhdGUgdGhlIGFsbG9jYXRpb24Kb2YgdGhlIGZpc2ggdG8gdGhlIGRpZmZlcmVudCBkb3Nlcy4KCmBgYHtyfQpsaWJyYXJ5KGdyaWRFeHRyYSkKYGBgCgpgYGB7cn0Kc2V0LnNlZWQoMTM1MSkKCnBsb3RzIDwtIGxhcHBseSgKICAxOjksCiAgZnVuY3Rpb24oeCkgewogICAgcG9pc29uX2Rvam8gJT4lCiAgICAgIG11dGF0ZShEb3NlID0gc2FtcGxlKERvc2UpKSAlPiUgIyByYW5kb21pemF0aW9uCiAgICAgIGdncGxvdChhZXMoeCA9IERvc2UsIHkgPSBXZWlnaHQpKSArCiAgICAgIGdlb21fcG9pbnQoKSArCiAgICAgIHRoZW1lX2J3KCkgKwogICAgICBzdGF0X3N1bW1hcnkoCiAgICAgICAgZ2VvbSA9ICJwb2ludCIsCiAgICAgICAgZnVuID0gIm1lYW4iLAogICAgICAgIGNvbCA9ICJibGFjayIsCiAgICAgICAgc2l6ZSA9IDIsCiAgICAgICAgc2hhcGUgPSAyNCwKICAgICAgICBmaWxsID0gInJlZCIKICAgICAgKQogIH0KKQpkby5jYWxsKGdyaWRFeHRyYTo6Z3JpZC5hcnJhbmdlLCBwbG90cykKYGBgCgpJbiB0aGUgYWJvdmUgc2ltdWxhdGlvbiwgd2UgcmFuZG9tbHkgYXNzaWduZWQgdGhlIGRpZmZlcmVudCBmaXNoIHRvIGRpZmZlcmVudApwb2lzb24gZG9zZXMuIEV2ZW4gdGhvdWdoIHdlIGRpZCB0aGlzIHJhbmRvbWx5LCB3ZSBzdGlsbCBzZWUgdGhhdCBieSByYW5kb20KY2hhbmNlIHRoZXJlIGNhbiBiZSBmbHVjdHVhdGlvbnMgYXMgbGFyZ2UgYXMgdGhlIG9uZXMgb2JzZXJ2ZWQgaW4gb3VyIHJlYWwKZGF0YXNldC4gQXMgc3VjaCwgd2UgbWF5IGNvbmNsdWRlIHRoYXQgdGhlcmUgaXMgaW5kZWVkICoqbm8gc3lzdGVtYXRpYyBiaWFzKiosCmkuZS4sIG5vIGNsZWFyIHRyZW5kIGluIHRoZSBhc3NvY2lhdGlvbiBiZXR3ZWVuIGBEb3NlYCBhbmQgYFdlaWdodGAuCgojIExpbmVhciByZWdyZXNzaW9uIGFuYWx5c2lzCgojIyBBc3N1bXB0aW9ucyBvZiBsaW5lYXIgcmVncmVzc2lvbgoKTGlzdCBhc3N1bXB0aW9uczoKCjEuIFRoZSBvYnNlcnZhdGlvbnMgYXJlIGluZGVwZW5kZW50IG9mIGVhY2ggb3RoZXIKMi4gTGluZWFyaXR5IGJldHdlZW4gdGhlIHJlc3BvbnNlIGFuZCBwcmVkaWN0b3IgdmFyaWFibGUKMy4gVGhlIHJlc2lkdWVzIG9mIHRoZSBtb2RlbCBtdXN0IGJlIG5vcm1hbGx5IGRpc3RyaWJ1dGVkCjQuIEhvbW9zY2VkYXN0aWNpdHkgb2YgdGhlIGRhdGEKClRoZSBmaXJzdCBhc3N1bXB0aW9uIGlzIG1ldCBiYXNlZCBvbiB0aGUgZXhwZXJpbWVudGFsIGRlc2lnbi4gSW4gdGhlCmRhdGEgZXhwbG9yYXRpb24gcGhhc2UsIHdlIHNhdyB0aGF0IHRoZXJlIGlzIG5vIGNsZWFyIHRyZW5kIGluIHRoZSBhc3NvY2lhdGlvbgpiZXR3ZWVuIGBEb3NlYCBhbmQgYFdlaWdodGAuIFdpdGggcmVzcGVjdCB0byBzcGVjaWVzLCB3ZSBoYXZlICJhdm9pZGVkIiB0YWtpbmcKaW50byBhY2NvdW50IHRoZSBlZmZlY3Qgb2Ygc3BlY2llcyBpbnRvIHRoZSBhbmFseXNpcyBieSBvbmx5IHBlcmZvcm1pbmcgYW4KYW5hbHlzaXMgZm9yIHRoZSBkb2pvZmlzaC4KCldlIHdpbGwgY2hlY2sgdGhlIG90aGVyIGFzc3VtcHRpb25zIGJ5IGZpcnN0IGZpdHRpbmcgdGhlIGxpbmVhcgptb2RlbCBhbmQgcGxvdHRpbmcgdGhlIG91dHB1dC4gQXMgc3VjaCwgd2Ugd2lsbCBnZXQgYWxsIHRoZQpyZXF1aXJlZCBkaWFnbm9zdGljIHBsb3RzLgoKYGBge3J9CiMgZml0IGEgbGluZWFyIHJlZ3Jlc3Npb24gbW9kZWwgd2l0aCAnU3Vydl90aW1lJyBhcyByZXNwb25zZSB2YXJpYWJsZSBhbmQKIyAnRG9zZScgYXMgcHJlZGljdG9yIHZhcmlhYmVsZQptb2RlbCA8LSBsbShTdXJ2X3RpbWUgfiBEb3NlLCBkYXRhID0gcG9pc29uX2Rvam8pCgojIyBkaXNwbGF5IHRoZSBkaWFnbm9zdGljIHBsb3RzIG9mIHRoZSBtb2RlbApwbG90KG1vZGVsKQpgYGAKCldlIGhhdmUgZm91ciBkaWFnbm9zdGljIHBsb3RzOgoKMi4gTGluZWFyaXR5IHdpdGggdGhlIFJlc2lkdWFscyB2cyBmaXR0ZWQgcGxvdAoKLSBwcmVkaWN0b3Igb2YgcHJlZGljdGlvbnMgJFxoYXRcYmV0YV8wK1xoYXRcYmV0YV8xIHgkIG9uICRYJC1heGlzCi0gKnJlc2lkdWFscyogb24gJFkkLWFzCiQkZV9pPXlfaS1caGF0e2d9KHhfaSk9eV9pLVxoYXRcYmV0YV8wLVxoYXRcYmV0YV8xXHRpbWVzIHhfaSwkJAoKSWYgdGhlcmUgd291bGQgYmUgYSBsaW5lYXIgcmVsYXRpb25zaGlwIGluIHRoZSBkYXRhLAp0aGUgcmVzaWR1YWxzIGFyZSBleHBlY3RlZCB0byBiZSBzY2F0dGVyZWQgYXQgcmFuZG9tIGFyb3VuZCB5PTAgZm9yCnRoZSBlbnRpcmUgcmFuZ2Ugb2YgcHJlZGljdGVkIHZhbHVlcy4gVGhpcyBpcyBjbGVhcmx5CnRoZSBjYXNlOiB0aGUgYXNzdW1wdGlvbiBvZiBsaW5lYXJpdHkgaXMgbWV0LgoKMy4gTm9ybWFsIFEtUQoKLSBRUS1wbG90IG9mIHRoZSByZXNpZHVhbHMgJGVfaSQuCgpUaGUgcmVzaWR1YWxzIG9mIHRoZSBsaW5lYXIgcmVncmVzc2lvbiBtb2RlbCBzaG91bGQgYmUgbm9ybWFsbHkKZGlzdHJpYnV0ZWQuIEdpdmVuIHRoZSBzZWNvbmQgZGlhZ25vc3RpYyBwbG90LCB0aGlzIHNlZW1zIG5vdAp0byBiZSB0aGUgY2FzZS4gSW4gc3RlYWQsIHdlIG9ic2VydmUgYSBzaG9ydCBsZWZ0IHRhaWwgYW5kIGEKbG9uZyByaWdodCB0YWlsLiBUaGUgYXNzdW1wdGlvbiBvZiBub3JtYWwgcmVzaWR1ZXMgaXMgKipub3QgbWV0LioqCgo0LiBIb21vc2NlZGFzdGljaXR5CgotIFNxdWFyZS1yb290IG9mIHRoZSBhYnNvbHV0ZSB2YWx1ZSBvZiBzdGFuZGFyZGl6ZWQgcmVzaWR1YWxzCmluIGZ1bmN0aW9uIG9mIHRoZSBmaXR0ZWQgdmFsdWVzCgpUbyBtZWV0IHRoZSB0aGlyZCBhc3N1bXB0aW9uIG9mIGxpbmVhciByZWdyZXNzaW9uLCB0aGUgdmFyaWFuY2UKb24gdGhlIF9TcXVhcmUtcm9vdCBvZiB0aGUgYWJzb2x1dGUgdmFsdWUgb2Ygc3RhbmRhcmRpemVkIHJlc2lkdWFsc18KbXVzdCBiZSBzaW1pbGFyIG92ZXIgdGhlIGVudGlyZSByYW5nZSBvZiBmaXR0ZWQgdmFsdWVzLiBUaGUgc21vb3RoZXIKaW4gdGhlIHBsb3QgaGVscHMgdXMgd2l0aCBsb29raW5nIGF0IHRoaXM7IGl0IHNob3VsZCBiZSBuaWNlbHkKaG9yaXpvbnRhbCBvdmVyIHRoZSBlbnRpcmUgcmFuZ2Ugb2YgZml0dGVkIHZhbHVlcy4gVGhpcyBzZWVtcyBub3QKdG8gYmUgdGhlIGNhc2U6IGZvciBsYXJnZXIgZml0dGVkIHZhbHVlcywgdGhlIHZhcmlhbmNlIGluY3JlYXNlIHNsaWdodGx5LgpUaGUgYXNzdW1wdGlvbiBvZiBob21vc2NlZGFzdGljaXR5IGlzICoqbm90IG1ldC4qKgoKTXVsdGlwbGUgYXNzdW1wdGlvbnMgYXJlIG5vdCBtZXQsIHNvIHdlIG1heSBub3QgY29udGludWUgYnkgcGVyZm9ybWluZwphIGxpbmVhciByZWdyZXNzaW9uLgoKV2UgY2FuIHRyeSB0byByZW1lZGlhdGUgdGhlc2UgZGV2aWF0aW9ucyBieSBsb2ctdHJhbnNmb3JtaW5nIHRoZSBkYXRhLiBJbmRlZWQsCmRhdGEgd2l0aCBoZWF2eSByaWdodCB0YWlscyBjYW4gb2Z0ZW4gYmUgbm9ybWFsaXplZCBieSBhcHBseWluZyB0aGlzIHN0cmF0ZWd5LgoKRml0IGEgKGxvZy0pbGluZWFyIG1vZGVsIGJ5IGxvZy10cmFuc2Zvcm1pbmcgdGhlIHJlc3BvbnNlLkdlbmVyYXRlIGRpYWdub3N0aWMKcGxvdHMgYW5kIGFzc2VzcyB0aGUgYXNzdW1wdGlvbnMuCgpgYGB7cn0KbG9nLm1vZGVsIDwtIGxtKGxvZzEwKFN1cnZfdGltZSkgfiBEb3NlLCBkYXRhID0gcG9pc29uX2Rvam8pCnBsb3QobG9nLm1vZGVsKQpgYGAKCkFyZ3VhYmx5LCB0aGVyZSBtaWdodCBiZSBzb21lIGRldmlhdGlvbiBmcm9tIG5vcm1hbGl0eSBpbiB0aGUgbGVmdCB0YWlsIG9mIHRoZQpkaXN0cmlidXRpb24uIEhvd2V2ZXIsIHdoZW4gd2Ugd291bGQgc2ltdWxhdGUgZGF0YSB1bmRlciB0aGUgbm9ybWFsaXR5CmFzc3VtcHRpb24sIGl0IHNlZW1zIHRoYXQgZGV2aWF0aW9ucyBvZiB0aGlzIHNpemUgbWF5IGJlIGV4cGVjdGVkIHdoZW4Kbm9ybWFsaXR5IGlzIG1ldDoKCmBgYHtyfQpzZXQuc2VlZCgxNDA2KQpub2JzIDwtIG5yb3cocG9pc29uX2Rvam8pCgpkYXRhLmZyYW1lKAogIHkgPSBjKGxvZy5tb2RlbCRyZXMsIHJub3JtKG5vYnMgKiA4LCBzZCA9IHNpZ21hKGxvZy5tb2RlbCkpKSwKICBsYWJlbCA9IHJlcChjKCJvcmlnIiwgcGFzdGUwKCJzaW0iLCAxOjgpKSwgZWFjaCA9IG5vYnMpCikgJT4lCiAgZ2dwbG90KGFlcyhzYW1wbGUgPSB5KSkgKwogIGdlb21fcXEoKSArCiAgZ2VvbV9xcV9saW5lKCkgKwogIGZhY2V0X3dyYXAofmxhYmVsKQpgYGAKCjEuIFRoZSBpbmRlcGVuZGVuY2UgYXNzdW1wdGlvbiBpcyBtZXQuCjIuIFVwb24gbG9nLXRyYW5zZm9ybWF0aW9uLCB0aGUgbGluZWFyaXR5IGFzc3VtcHRpb24gaXMgc3RpbGwgbWV0LgozLiBVcG9uIGxvZy10cmFuc2Zvcm1hdGlvbiwgdGhlIG5vcm1hbGl0eSBhc3N1bXB0aW9uIGlzIGFsc28gbWV0Lgo0LiBVcG9uIGxvZy10cmFuc2Zvcm1hdGlvbiwgdGhlIGhvbW9zY2VkYXN0aWNpdHkgYXNzdW1wdGlvbiBpcyBhbHNvIG1ldC4KCkxvb2sgYXQgdGhlIG91dHB1dCBvZiB0aGUgbG9nLWxpbmVhciBtb2RlbDoKCmBgYHtyfQpzdW1tYXJ5KGxvZy5tb2RlbCkKYGBgCgpDb21wdXRlIHRoZSA5NSUgY29uZmlkZW5jZSBpbnRlcnZhbCBvbiB0aGUgbW9kZWwgcGFyYW1ldGVyczoKCmBgYHtyfQpjb25maW50KGxvZy5tb2RlbCkKYGBgCgojIyBJbnRlcnByZXRhdGlvbiBvbiB0aGUgbG9nIHNjYWxlCgpDdXJyZW50bHksIGFsbCB0aGUgb3V0Y29tZXMgc2hvdWxkIGJlIGludGVycHJldGVkIG9uIHRoZSBsb2ctc2NhbGUuCkluZGVlZCwgc2luY2Ugd2UgYXJlIG5vdyBtb2RlbGxpbmcgIF90aGUgbG9nJF97MTB9JCBvZiBzdXJ2aXZhbCB0aW1lXywgd2UKZG9uJ3QgaGF2ZSBkaXJlY3QgaW5mZXJlbmNlIG9uIHN1cnZpdmFsIHRpbWUuCgpBcyBzdWNoLCB3ZSBtYXkgaW50ZXJwcmV0IHRoZSBvdXRwdXQgYXMgZm9sbG93czoKCi0gVGhlIHNsb3BlOgoKRG9qb2Zpc2ggdGhhdCBhcmUgZXhwb3NlZCB0byBhIGhpZ2hlciBkb3NlIG9mIHRoZSBwb2lzb24gd2lsbCBoYXZlIGEgJGxvZ197MTB9JApzdXJ2aXZhbCB0aW1lIHRoYXQgaXMgb24gYXZlcmFnZSBgciBsb2cubW9kZWwkY29lZlsyXSAlPiUgYWJzICU+JSByb3VuZCguLDIpYApsb3dlciBwZXIgZ3JhbSBvZiBwb2lzb24gdGhhdCB3YXMgYWRtaW5pc3RlcmVkIGFkZGl0aW9uYWxseQooOTUlIENJIFtgciBjb25maW50KGxvZy5tb2RlbCkgJT4lIGFicyAlPiUgcm91bmQoLiwyKWBdKS4gVGhpcyBkZWNyZWFzZSBpbgpzdXJ2aXZhbCB0aW1lIGlzIHNpZ25pZmljYW50IG9uIHRoZSA1JSBzaWduaWZpY2FuY2UgbGV2ZWwgKHA8MC4wMDEpLgoKTm90ZSwgdGhhdCB0aGUgc3R1ZHkgaXMgYW4gZXhwZXJpbWVudGFsIHN0dWR5IHNvIHdlIGNhbiBjb25jbHVkZSB0aGF0IHRoZXJlIGlzCmEgY2F1c2FsIGVmZmVjdCBvZiB0aGUgcG9pc29uIGRvc2UgYW5kIHRoZSBzdXJ2aXZhbCB0aW1lLgoKLSBUaGUgaW50ZXJjZXB0OgoKVGhlIGF2ZXJhZ2Ugb2YgdGhlIGxvZzEwIG9mIHN1cnZpdmFsIHRpbWUgZm9yIGZpc2ggdGhhdAp3ZXJlIGdpdmVuIGEgZG9zZSBvZiAwIG1nIGlzIGByIGxvZy5tb2RlbCRjb2VmWzFdICU+JSBhYnMgJT4lIHJvdW5kKC4sMilgLgoKIyMgSW50ZXJwcmV0YXRpb24gb24gdGhlIG9yaWdpbmFsIHNjYWxlCgpUaGUgaW50ZXJwcmV0YXRpb24gdGhlIGxvZy1zY2FsZSBpcyBxdWl0ZSBkaWZmaWN1bHQuIFRvIGVhc2UKdGhlIGludGVycHJldGF0aW9uLCB3ZSB3aWxsIGJhY2t0cmFuc2Zvcm0gdGhlIHJlc3VsdHMgdG8gdGhlIG9yaWdpbmFsCnNjYWxlICh0aW1lIGluIG1pbnV0ZXMpLiBUaGlzIHdlIGNhbiBkbyBieQoKYGBge3J9CjEwXihzdW1tYXJ5KGxvZy5tb2RlbCkkY29lZmZpY2llbnRzWywgIkVzdGltYXRlIl0pCmBgYAoKYW5kIG9mIHRoZWlyIGNvbmZpZGVuY2UgaW50ZXJ2YWxzOgoKYGBge3J9CjEwXihjb25maW50KGxvZy5tb2RlbCkpCmBgYAoKTm93LCB3ZSBjYW4gaW50ZXJwcmV0IHRoZSByZXN1bHRzIGluIHRlcm1zIG9mIHRoZSBnZW9tZXRyaWMgbWVhbjoKCi0gVGhlIHNsb3BlOgoKRG9qbyBmaXNoIHRoYXQgYXJlIGV4cG9zZWQgdG8gYSBoaWdoZXIgZG9zZSBvZiB0aGUgcG9pc29uIHdpbGwgaGF2ZSBhIGdlb21ldHJpYwptZWFuIG9mIHRoZSBzdXJ2aXZhbCB0aW1lIHRoYXQgaXMgZmFjdG9yIGByIHJvdW5kKDEwXmxvZy5tb2RlbCRjb2VmWzJdLDIpYAooOTUlIENJIFtgciByb3VuZCgxMF4oY29uZmludChsb2cubW9kZWwpWzIsXSksMilgXSkgcGVyIGdyYW0gb2YgcG9pc29uIHRoYXQgdGhleQpyZWNlaXZlZCBtb3JlIHRoYW4gZmlzaCBleHBvc2VkIHRvIGEgbG93ZXIgZG9zZS4gVGhpcyBkZWNyZWFzZSBpcyB2ZXJ5CnNpZ25pZmljYW50IG9uIHRoZSA1JSBzaWduaWZpY2FuY2UgbGV2ZWwgKHA8MC4wMDEpLgoKLSBUaGUgaW50ZXJjZXB0OgoKVGhlIGdlb21ldHJpYyBtZWFuIG9mIHRoZSBzdXJ2aXZhbCB0aW1lIGZvciBmaXNoIHRoYXQgd2VyZSBnaXZlbiBhCmRvc2Ugb2YgMCBtZyBpcyBgciByb3VuZCgxMF5sb2cubW9kZWwkY29lZlsxXSwyKWAgbWludXRlcy4KCkluIG90aGVyIHdvcmRzLCBvdXIgYW5hbHlzaXMgc2VlbXMgdG8gc3VnZ2VzdCB0aGF0IGZpc2ggaW4gdW5jb250YW1pbmF0ZWQgd2F0ZXIKd291bGQgb25seSBzdXJ2aXZlIGZvciBhYm91dCA4IG1pbnV0ZXMhIFRoaXMgc2VlbXMgYSBsaXR0bGUgYml0IF9maXNoeV8uLi4KCk5vdGUsIHRoYXQgdGhpcyBpbnRlcnByZXRhdGlvbiBpcyBub3QgYmlvbG9naWNhbGx5IHJlbGV2YW50IGFuZCBpcyBpbmR1Y2VkCmJlY2F1c2Ugd2UgZXh0cmFwb2xhdGVkIGNvbnNpZGVyYWJseSBiZWNhdXNlIGFsbCBmaXNoIGluIHRoZSBleHBlcmltZW50IHdlcmUKZXhwb3NlZCB0byBwb2lzb24uCgpgYGB7cn0KIyMgRXh0cmFjdCBzbG9wZSBhbmQgaW50ZXJjZXB0IGZyb20gdGhlIG1vZGVsCmRvam9faW50ZXJjZXB0IDwtIGNvZWYobG9nLm1vZGVsKVsxXQpkb2pvX3Nsb3BlIDwtIGNvZWYobG9nLm1vZGVsKVsyXQoKZ2dwbG90KHBvaXNvbl9kb2pvLCBhZXMoRG9zZSwgbG9nMTAoU3Vydl90aW1lKSkpICsKICBnZW9tX3BvaW50KCkgKwogIGdlb21fYWJsaW5lKAogICAgc2xvcGUgPSBkb2pvX3Nsb3BlLCBpbnRlcmNlcHQgPSBkb2pvX2ludGVyY2VwdCwKICAgIGNvbG9yID0gInN0ZWVsYmx1ZSIsIHNpemUgPSAxLjIKICApCmBgYAoKV2UgY2FuIHNlZSB0aGF0IHRoZSBkb3NlIHZhbHVlIG9mIDAgbWcgZG9lcyBub3QgZmFsbCB3aXRoaW4KdGhlIHNhbWUgcmFuZ2UgYXMgb3VyIGRhdGEuIFRoZSBtb2RlbCBpcyBvbmx5IHZhbGlkIGluIHRoZSByYW5nZSBvZgpkYXRhIHRoYXQgd2UgdXNlIHRvIGJ1aWxkIHRoZSBtb2RlbCBvbiEKCkhvd2V2ZXIsIGluIG1vc3QgYXBwbGljYXRpb25zIHdlIHdpbGwgbmV2ZXIgdGVzdCBmb3IgdGhlIGludGVyY2VwdCB0ZXJtLgoKIyBDb25jbHVzaW9uCgpUaGVyZSBpcyBhIHZlcnkgc2lnbmlmaWNhbnQgZWZmZWN0IG9mIHRoZSBwb2lzb24gb24gc3Vydml2YWwgb2YgRG9qb2Zpc2gKKHA8IDAuMDAxKS4gRG9qb2Zpc2ggdGhhdCBhcmUgZXhwb3NlZCB0byBhIGhpZ2hlciBkb3NlIG9mIHRoZSBwb2lzb24gd2lsbApoYXZlIGEgc3Vydml2YWwgdGltZSB0aGF0IGRlY3JlYXNlIG9uIGF2ZXJhZ2Ugd2l0aCBhIGZhY3RvcgpgciBsb2cubW9kZWwkY29lZlsyXSAlPiUgYWJzICU+JSAxMF4uICU+JSByb3VuZCguLDIpYCBwZXIgZ3JhbSBvZiBwb2lzb24gdGhhdAppcyBhZGRlZCAoOTUlIENJIFtgciBjb25maW50KGxvZy5tb2RlbClbMixdICU+JSBhYnMgJT4lIDEwXi4gJT4lIHJvdW5kKC4sMilgXSkuCgpJbiB0aGUgdHV0b3JpYWwgb2YgbXVsdGlwbGUgcmVncmVzc2lvbiwgd2Ugd2lsbCByZXZpc2l0IHRoaXMgZXhlcmNpc2UuCk1vcmUgc3BlY2lmaWNhbGx5LCB3ZSB3aWxsIHRoZXJlIHN0dWR5IHRoZSBhc3NvY2lhdGlvbiBiZXR3ZWVuIGRvc2UgYW5kIHN1cnZpdmFsCmZvciBhbGwgdGhlIHNwZWNpZXMgaW4gdGhlIGRhdGFzZXQuCg==