Exploring data patterns of sugar maple and red maple trees
To start off this project uses a data set that covers a reasearch
study conducted on “Maple Reproduction and Sap Flow at Harvard Forest
since 2011”. This project uses the data sets provides by the study and
can be found here https://doi.org/10.6073/pasta/7c2ddd7b75680980d84478011c5fbba9
or below in the full citation. This project will try and answer the
question “Does the non-masting red maple species exhibit muted dynamics
compared to the masting sugar maple species?”
Due to the incomplete nature of this data set, there is far too
little data to concretely say red maples exhibit muted dynamics when
compared to the sugar maple trees. Therefore, I’m going to be looking to
find the best key indicators so that if the data were more fleshed out
it would be easier to see if the red maple species exhibit muted
dynamics.
Rapp, J., E. Crone, and K. Stinson. 2023. Maple Reproduction and Sap
Flow at Harvard Forest since 2011 ver 6. Environmental Data Initiative.
https://doi.org/10.6073/pasta/7c2ddd7b75680980d84478011c5fbba9
(Accessed 2024-12-11)
This notebook uses tidyverse for graphing and general R commands as
well as for graphing and data visualizations, dplyr for data
manipulation, and modelr for creating statistical models and their
summarys.
library(tidyverse)
library(dplyr)
library(ggplot2)
library(modelr)
Below we read in each data set
library(readr)
hf285_01_maple_tap <- read_csv("C:/Users/Admin/Desktop/R stats homework/Final Project/knb-lter-hfr.285.6/hf285-01-maple-tap.csv")
hf285_02_maple_sap <- read_csv("C:/Users/Admin/Desktop/R stats homework/Final Project/knb-lter-hfr.285.6/hf285-02-maple-sap.csv")
hf285_03_maple_flower_qual <- read_csv("C:/Users/Admin/Desktop/R stats homework/Final Project/knb-lter-hfr.285.6/hf285-03-maple-flower-qual.csv")
hf285_04_maple_flower <- read_csv("C:/Users/Admin/Desktop/R stats homework/Final Project/knb-lter-hfr.285.6/hf285-04-maple-flower.csv")
hf285_05_maple_spring_branch <- read_csv("C:/Users/Admin/Desktop/R stats homework/Final Project/knb-lter-hfr.285.6/hf285-05-maple-spring-branch.csv")
hf285_06_maple_fall_branch <- read_csv("C:/Users/Admin/Desktop/R stats homework/Final Project/knb-lter-hfr.285.6/hf285-06-maple-fall-branch.csv")
hf285_07_maple_seedfilling <- read_csv("C:/Users/Admin/Desktop/R stats homework/Final Project/knb-lter-hfr.285.6/hf285-07-maple-seedfilling.csv")
hf285_08_maple_pollen_excl <- read_csv("C:/Users/Admin/Desktop/R stats homework/Final Project/knb-lter-hfr.285.6/hf285-08-maple-pollen-excl.csv")
hf285_09_maple_seed_count <- read_csv("C:/Users/Admin/Desktop/R stats homework/Final Project/knb-lter-hfr.285.6/hf285-09-maple-seed-count.csv")
hf285_10_leaf_removal <- read_csv("C:/Users/Admin/Desktop/R stats homework/Final Project/knb-lter-hfr.285.6/hf285-10-leaf-removal.csv")
hf285_11_leaf_removal_branches <- read_csv("C:/Users/Admin/Desktop/R stats homework/Final Project/knb-lter-hfr.285.6/hf285-11-leaf-removal-branches.csv")
hf285_12_leaf_seed_removal <- read_csv("C:/Users/Admin/Desktop/R stats homework/Final Project/knb-lter-hfr.285.6/hf285-12-leaf-seed-removal.csv")
hf285_13_leaf_seed_removal_branches <- read_csv("C:/Users/Admin/Desktop/R stats homework/Final Project/knb-lter-hfr.285.6/hf285-13-leaf-seed-removal-branches.csv")
hf285_14_perm_branches <- read_csv("C:/Users/Admin/Desktop/R stats homework/Final Project/knb-lter-hfr.285.6/hf285-14-perm-branches.csv")
Masting and Non-Masting
First we need to better understand our problem and learn a few key
defintions. A masting tree is a tree that produces seeds large quanities
in irregular intervals. Our sugar maple trees are masting trees and we
want to know if the red maples show muted dynamics when compared to the
sugar maples. To better understand our sugar maples we first need to see
what years were masting years for the trees. We do this by examening the
seed collection data average for the sugar maples each year of the
data.
tree_seed_data <- hf285_09_maple_seed_count %>%
filter(!is.na(total.count)) %>%
mutate(year = as.numeric(format(date, "%Y"))) %>%
group_by(tree, year) %>%
summarise(Total_Seeds = sum(total.count, na.rm = TRUE), .groups = "drop")
ggplot(tree_seed_data, aes(x = factor(year), y = tree, fill = Total_Seeds)) +
geom_tile(color = "black", linewidth = 0.5) +
scale_fill_viridis_c() +
labs(
title = "Yearly Seed Count by Tree",
x = "Year",
y = "Tree ID",
fill = "Seed Count"
)

Based on the heat map we can see a few years that stick out 2011,
2013, 2017, and 2019. These are the best indicators that show what years
we can see the masting taking place in our sugar maples.
Next below we add our masting years we found to our sap collection
and sugar content dataset for the approprate trees which we can use for
later to attept to build a model to predict masting seasons.
hf285_02_maple_sap <- hf285_02_maple_sap %>%
mutate(date = as.Date(date))
hf285_02_maple_sap <- hf285_02_maple_sap %>%
mutate(year = year(date))
hf285_02_maple_sap_masting <- hf285_02_maple_sap %>%
mutate(masting = ifelse(year %in% c(2011, 2013, 2017, 2019), "Yes", "No"))
head(hf285_02_maple_sap_masting)
Breaking down key indicators
Here if we want to look for key indicators in our sugar maples that
could predict when a masting might occur. These keye predictors could
help us better compare and undertand if our red maples are exhibiting
signs of muted dynamics. Below we graph both the sugar and red maples
average sap sugar content for years there was data collected. HF stands
for sugar maple and AR for red maple.
grouped_data <- hf285_02_maple_sap %>%
filter(!is.na(sugar)) %>%
mutate(Tree_Group = substr(tree, 1, 2)) %>%
group_by(date, Tree_Group) %>%
summarise(Average_Sugar = mean(sugar, na.rm = TRUE), .groups = "drop")
ggplot(grouped_data, aes(x = date, y = Average_Sugar, color = Tree_Group, group = Tree_Group)) +
geom_line() +
geom_point() +
labs(
title = "Average Sugar Content Over Time",
x = "Date",
y = "Average Sugar Content",
color = "Tree Group"
)

While we can see the average sugar content is much lower for the red
maple that doesn’t answer our question right away especially when the
data collected for red maples is very small with only about 4-5 years of
data collected the data simply isn’t conclusive enough to answer our
question.
Here is where can start to dig in and see if overlaying our graphs
between yealy average sugar content of the sugar maple trees (HF) and
the averge seed count of sugar maples have simlar graphs.
###Average seed count per year compared to average sugar content of
sugar maples
hf285_02_maple_sap_HF <- hf285_02_maple_sap %>%
filter(grepl("^HF", tree), !is.na(sugar))
hf285_09_maple_seed_count_HF <- hf285_09_maple_seed_count %>%
filter(grepl("^HF", tree), !is.na(total.count))
hf285_02_maple_sap_HF <- hf285_02_maple_sap_HF %>%
mutate(year = year(date))
hf285_09_maple_seed_count_HF <- hf285_09_maple_seed_count_HF %>%
mutate(year = year(date))
average_data <- hf285_02_maple_sap_HF %>%
group_by(year) %>%
summarise(average_sugar = mean(sugar, na.rm = TRUE))
average_seeds <- hf285_09_maple_seed_count_HF %>%
group_by(year) %>%
summarise(average_seeds = mean(total.count, na.rm = TRUE))
merged_avg_data <- left_join(average_data, average_seeds, by = "year")
merged_avg_data_clean <- merged_avg_data %>%
filter(!is.na(average_sugar) & !is.na(average_seeds))
sugar_content_HF <- ggplot(merged_avg_data_clean, aes(x = year, y = average_sugar)) +
geom_line(color = "blue", size = 1) +
geom_point(color = "red", size = 3) +
labs(
title = "Average Sugar Content for HF Trees by Year",
x = "Year",
y = "Average Sugar Content"
) +
theme_minimal()
seed_count_HF <- ggplot(merged_avg_data_clean, aes(x = year, y = average_seeds)) +
geom_line(color = "green", size = 1) +
geom_point(color = "orange", size = 3) +
labs(
title = "Average Seed Count for HF Trees by Year",
x = "Year",
y = "Average Seed Count"
) +
theme_minimal()
print(sugar_content_HF)

print(seed_count_HF)

Here we can see that while the graphs do have a similar shape the
overall patterns don’t match exactly so to better try and find our key
predictors we can use our added masting column from earlier to create a
linear model.
Building a model with our data
Below we use our added data from before to attept to predict the
sugar tree mastings based on sugar content of trees sap.
hf285_02_maple_sap_HF <- hf285_02_maple_sap_masting %>%
mutate(masting_binary = ifelse(masting == "Yes", 1, 0))
lm_model <- lm(masting_binary ~ sugar, data = hf285_02_maple_sap_HF)
summary(lm_model)
Call:
lm(formula = masting_binary ~ sugar, data = hf285_02_maple_sap_HF)
Residuals:
Min 1Q Median 3Q Max
-1.1457 -0.3395 -0.3146 0.6480 0.7228
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 0.231458 0.020481 11.301 < 2e-16 ***
sugar 0.041555 0.008005 5.191 2.14e-07 ***
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Residual standard error: 0.471 on 8011 degrees of freedom
(1009 observations deleted due to missingness)
Multiple R-squared: 0.003352, Adjusted R-squared: 0.003228
F-statistic: 26.95 on 1 and 8011 DF, p-value: 2.143e-07
Here we get to know break down our model and look at its key values.
Right off the bat we can see the sugar coef of .041555 so for every
increase in 1 unit of sugar we see a 4.15% increase in the chance of a
masting year. Next we can see that our RSE is quite high, a lower value
would be better but this does show that some variability remains
unexplained. Our R squared value of just .003352 shows that sugar alone
is not a strong predictor. Lastly we look at our p-value which shows an
incredly small 2.143e-07. So while sugar isn’t a great solo predictor
our new model is statistically significant.
With sugar content helping work towards a stronger model we can look
at other possible predictors we might have over looked. Below I have
taken thehf285_03_maple_flower_qual data set and edited the data to give
values to the flowering.intensity based on the values provided by
Harvads ranges which can be found here https://harvardforest1.fas.harvard.edu/exist/apps/datasets/showData.html?id=hf285.
Which states that data set hf285_03_maple_flower_qual gives these
ranges
“flowering.intensity: qualitative evaluation of whole-tree flowering
low: generally <1,000 flowering buds medium: generally 1,000-10,000
flowering buds high: generally >10,000 flowering buds none: no
flowering buds”
hf285_03_maple_flower_qual_edit <- hf285_03_maple_flower_qual %>%
mutate(flowering_value = case_when(
flowering.intensity == "none" ~ 0,
flowering.intensity == "low" ~ 999,
flowering.intensity == "medium" ~ 5000,
flowering.intensity == "high" ~ 10000,
TRUE ~ NA_real_
))
head(hf285_03_maple_flower_qual_edit)
While creating the numbers for each group is overreaching. The
dataset itself gives us very little to work with so attepting to put
numbers to values that Harvad offered is the best we can do to get a
better idea of our predictors.
Now that we have values for out flower intensity we can put it to a
graph and compare to our graph of mastings
average_flowering_data <- hf285_03_maple_flower_qual_edit %>%
group_by(year) %>%
summarise(average_flowering = mean(flowering_value, na.rm = TRUE))
ggplot(average_flowering_data, aes(x = factor(year), y = average_flowering)) +
geom_point(color = "blue", size = 3) +
labs(
title = "Average Flowering Intensity for the Forest Over Time",
x = "Year",
y = "Average Flowering Intensity"
) +
theme_minimal() +
theme(axis.text.x = element_text(angle = 45, hjust = 1))

Here we can see a strong pattern though we see large spikes on our
masting years with 2011, 2013, 2017, and 2019! This is very big becuase
it matches very close to our heat map of our masting years. But just
looking similar isn’t enough, we can test this by adding on to our
linear model to see if the number of flowers is a good predictor.
Below we look to test if the number of flower is a accurate predictor
on if sugar maple trees will have a masting year. By combining it with
our sugar model from earlier.
average_flowering_data_masting <- hf285_03_maple_flower_qual_edit %>%
mutate(
masting = ifelse(year %in% c(2011, 2013, 2017, 2019), "Yes", "No"),
masting_binary = ifelse(masting == "Yes", 1, 0)
)
lm_model_flowering <- lm(masting_binary ~ flowering_value, data = average_flowering_data_masting)
summary(lm_model_flowering)
Call:
lm(formula = masting_binary ~ flowering_value, data = average_flowering_data_masting)
Residuals:
Min 1Q Median 3Q Max
-0.62634 -0.10057 -0.04222 0.37366 0.95778
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 4.222e-02 3.625e-02 1.165 0.245
flowering_value 5.841e-05 5.669e-06 10.304 <2e-16 ***
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Residual standard error: 0.3843 on 230 degrees of freedom
Multiple R-squared: 0.3158, Adjusted R-squared: 0.3129
F-statistic: 106.2 on 1 and 230 DF, p-value: < 2.2e-16
First off we can see by our average_flowering coef showing .004
average flowering is statistically significant. Second we can see our
intercept shows that for every increase by 1 flower increases the chance
of a masting year by .0001. Which on the surface doesn’t seem like much
when dealing with trees these blossoms can range from a few hundred to
well over ten thousand this can add up. Now when we look at RSE there
are improvements over the sugar model with ours being .334 which shows
us the model is a better fit. Our R squared shows .579 showing us that
about 58% of the variance in the masting binary outcome is explained by
average_flowering. Lastly our p-value shows that over all this model is
statistically significant.
view(hf285_02_maple_sap_masting)
combined_data <- left_join(
average_flowering_data_masting,
hf285_02_maple_sap_masting %>%
group_by(year) %>%
summarise(average_sugar = mean(sugar, na.rm = TRUE)),
by = "year"
)
view(average_flowering_data_masting)
combined_lm <- lm(masting_binary ~ flowering_value + average_sugar, data = combined_data)
summary(combined_lm)
Call:
lm(formula = masting_binary ~ flowering_value + average_sugar,
data = combined_data)
Residuals:
Min 1Q Median 3Q Max
-0.66676 -0.22594 -0.03772 0.34683 0.83780
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) -9.725e-01 3.400e-01 -2.860 0.00465 **
flowering_value 4.897e-05 5.899e-06 8.302 1.09e-14 ***
average_sugar 4.202e-01 1.393e-01 3.017 0.00285 **
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Residual standard error: 0.3765 on 217 degrees of freedom
(12 observations deleted due to missingness)
Multiple R-squared: 0.2951, Adjusted R-squared: 0.2886
F-statistic: 45.42 on 2 and 217 DF, p-value: < 2.2e-16
First off we can see by our average_flowering coef is incredibly
small so average flowering is highly statistically significant. Second
we can see our intercept shows that for every increase by 1 flower
increases the chance of a masting year but only by 4.897e-05. Which on
the surface doesn’t seem like much when dealing with trees these
blossoms can range from a few hundred to well over ten thousand this can
add up. Our average sugar has changed some too we now see the coef at
.002 making it a statistically significant predictor of masting. Now
when we look at RSE there are improvements over the sugar model with
ours being .376 which shows us the model is a better fit then before.
Our R squared shows .295 showing us that about 30% of the variance in
the masting binary outcome is explained by average_flowering and
average_sugar. Lastly our p-value shows that over all this model is
highly statistically significant. While our data shows that this model
is statistically significant our R squared only explains about 30% of
the variance in the model showing the model needs more data to better
predict masting seasons.
In concluion
Overall, while there is not enough data to accurately state whether
red maple species exhibit muted dynamics or not I believe that the two
best key predictor in this limited data set are sap sugar content and
the number of flowers in bloom. If the data were more complete I believe
that these two predictors could be used to better see if the red maple
trees exhibit muted dynamics when compared to the sugar maple trees but
with the current data set limitations the data is inconclusive
LS0tDQp0aXRsZTogIlIgTm90ZWJvb2siDQpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sNCkF1dGhvcjogTm9haCBTemFyZWprbw0KLS0tDQoNCiMjIyBFeHBsb3JpbmcgZGF0YSBwYXR0ZXJucyBvZiBzdWdhciBtYXBsZSBhbmQgcmVkIG1hcGxlIHRyZWVzDQoNCiBUbyBzdGFydCBvZmYgdGhpcyBwcm9qZWN0IHVzZXMgYSBkYXRhIHNldCB0aGF0IGNvdmVycyBhIHJlYXNlYXJjaCBzdHVkeSBjb25kdWN0ZWQgb24gIk1hcGxlIFJlcHJvZHVjdGlvbiBhbmQgU2FwIEZsb3cgYXQgSGFydmFyZCBGb3Jlc3Qgc2luY2UgMjAxMSIuIFRoaXMgcHJvamVjdCB1c2VzIHRoZSBkYXRhIHNldHMgcHJvdmlkZXMgYnkgdGhlIHN0dWR5IGFuZCBjYW4gYmUgZm91bmQgaGVyZSBodHRwczovL2RvaS5vcmcvMTAuNjA3My9wYXN0YS83YzJkZGQ3Yjc1NjgwOTgwZDg0NDc4MDExYzVmYmJhOSBvciBiZWxvdyBpbiB0aGUgZnVsbCBjaXRhdGlvbi4gVGhpcyBwcm9qZWN0IHdpbGwgdHJ5IGFuZCBhbnN3ZXIgdGhlIHF1ZXN0aW9uICJEb2VzIHRoZSBub24tbWFzdGluZyByZWQgbWFwbGUgc3BlY2llcyBleGhpYml0IG11dGVkIGR5bmFtaWNzIGNvbXBhcmVkIHRvIHRoZSBtYXN0aW5nIHN1Z2FyIG1hcGxlIHNwZWNpZXM/Ig0KIA0KRHVlIHRvIHRoZSBpbmNvbXBsZXRlIG5hdHVyZSBvZiB0aGlzIGRhdGEgc2V0LCB0aGVyZSBpcyBmYXIgdG9vIGxpdHRsZSBkYXRhIHRvIGNvbmNyZXRlbHkgc2F5IHJlZCBtYXBsZXMgZXhoaWJpdCBtdXRlZCBkeW5hbWljcyB3aGVuIGNvbXBhcmVkIHRvIHRoZSBzdWdhciBtYXBsZSB0cmVlcy4gVGhlcmVmb3JlLCBJJ20gZ29pbmcgdG8gYmUgbG9va2luZyB0byBmaW5kIHRoZSBiZXN0IGtleSBpbmRpY2F0b3JzIHNvIHRoYXQgaWYgdGhlIGRhdGEgd2VyZSBtb3JlIGZsZXNoZWQgb3V0IGl0IHdvdWxkIGJlIGVhc2llciB0byBzZWUgaWYgdGhlIHJlZCBtYXBsZSBzcGVjaWVzIGV4aGliaXQgbXV0ZWQgZHluYW1pY3MuIA0KDQpSYXBwLCBKLiwgRS4gQ3JvbmUsIGFuZCBLLiBTdGluc29uLiAyMDIzLiBNYXBsZSBSZXByb2R1Y3Rpb24gYW5kIFNhcCBGbG93IGF0IEhhcnZhcmQgRm9yZXN0IHNpbmNlIDIwMTEgdmVyIDYuIEVudmlyb25tZW50YWwgRGF0YSBJbml0aWF0aXZlLiBodHRwczovL2RvaS5vcmcvMTAuNjA3My9wYXN0YS83YzJkZGQ3Yjc1NjgwOTgwZDg0NDc4MDExYzVmYmJhOSAoQWNjZXNzZWQgMjAyNC0xMi0xMSkNCg0KVGhpcyBub3RlYm9vayB1c2VzIHRpZHl2ZXJzZSBmb3IgZ3JhcGhpbmcgYW5kIGdlbmVyYWwgUiBjb21tYW5kcyBhcyB3ZWxsIGFzIGZvciBncmFwaGluZyBhbmQgZGF0YSB2aXN1YWxpemF0aW9ucywgZHBseXIgZm9yIGRhdGEgbWFuaXB1bGF0aW9uLCBhbmQgbW9kZWxyIGZvciBjcmVhdGluZyBzdGF0aXN0aWNhbCBtb2RlbHMgYW5kIHRoZWlyIHN1bW1hcnlzLg0KDQoNCmBgYHtyfQ0KbGlicmFyeSh0aWR5dmVyc2UpDQpsaWJyYXJ5KGRwbHlyKQ0KbGlicmFyeShnZ3Bsb3QyKQ0KbGlicmFyeShtb2RlbHIpDQpgYGANCg0KQmVsb3cgd2UgcmVhZCBpbiBlYWNoIGRhdGEgc2V0DQpgYGB7cn0NCmxpYnJhcnkocmVhZHIpDQpoZjI4NV8wMV9tYXBsZV90YXAgPC0gcmVhZF9jc3YoIkM6L1VzZXJzL0FkbWluL0Rlc2t0b3AvUiBzdGF0cyBob21ld29yay9GaW5hbCBQcm9qZWN0L2tuYi1sdGVyLWhmci4yODUuNi9oZjI4NS0wMS1tYXBsZS10YXAuY3N2IikNCg0KDQpoZjI4NV8wMl9tYXBsZV9zYXAgPC0gcmVhZF9jc3YoIkM6L1VzZXJzL0FkbWluL0Rlc2t0b3AvUiBzdGF0cyBob21ld29yay9GaW5hbCBQcm9qZWN0L2tuYi1sdGVyLWhmci4yODUuNi9oZjI4NS0wMi1tYXBsZS1zYXAuY3N2IikNCg0KaGYyODVfMDNfbWFwbGVfZmxvd2VyX3F1YWwgPC0gcmVhZF9jc3YoIkM6L1VzZXJzL0FkbWluL0Rlc2t0b3AvUiBzdGF0cyBob21ld29yay9GaW5hbCBQcm9qZWN0L2tuYi1sdGVyLWhmci4yODUuNi9oZjI4NS0wMy1tYXBsZS1mbG93ZXItcXVhbC5jc3YiKQ0KDQpoZjI4NV8wNF9tYXBsZV9mbG93ZXIgPC0gcmVhZF9jc3YoIkM6L1VzZXJzL0FkbWluL0Rlc2t0b3AvUiBzdGF0cyBob21ld29yay9GaW5hbCBQcm9qZWN0L2tuYi1sdGVyLWhmci4yODUuNi9oZjI4NS0wNC1tYXBsZS1mbG93ZXIuY3N2IikNCg0KaGYyODVfMDVfbWFwbGVfc3ByaW5nX2JyYW5jaCA8LSByZWFkX2NzdigiQzovVXNlcnMvQWRtaW4vRGVza3RvcC9SIHN0YXRzIGhvbWV3b3JrL0ZpbmFsIFByb2plY3Qva25iLWx0ZXItaGZyLjI4NS42L2hmMjg1LTA1LW1hcGxlLXNwcmluZy1icmFuY2guY3N2IikNCg0KDQpoZjI4NV8wNl9tYXBsZV9mYWxsX2JyYW5jaCA8LSByZWFkX2NzdigiQzovVXNlcnMvQWRtaW4vRGVza3RvcC9SIHN0YXRzIGhvbWV3b3JrL0ZpbmFsIFByb2plY3Qva25iLWx0ZXItaGZyLjI4NS42L2hmMjg1LTA2LW1hcGxlLWZhbGwtYnJhbmNoLmNzdiIpDQoNCmhmMjg1XzA3X21hcGxlX3NlZWRmaWxsaW5nIDwtIHJlYWRfY3N2KCJDOi9Vc2Vycy9BZG1pbi9EZXNrdG9wL1Igc3RhdHMgaG9tZXdvcmsvRmluYWwgUHJvamVjdC9rbmItbHRlci1oZnIuMjg1LjYvaGYyODUtMDctbWFwbGUtc2VlZGZpbGxpbmcuY3N2IikNCg0KDQpoZjI4NV8wOF9tYXBsZV9wb2xsZW5fZXhjbCA8LSByZWFkX2NzdigiQzovVXNlcnMvQWRtaW4vRGVza3RvcC9SIHN0YXRzIGhvbWV3b3JrL0ZpbmFsIFByb2plY3Qva25iLWx0ZXItaGZyLjI4NS42L2hmMjg1LTA4LW1hcGxlLXBvbGxlbi1leGNsLmNzdiIpDQoNCg0KaGYyODVfMDlfbWFwbGVfc2VlZF9jb3VudCA8LSByZWFkX2NzdigiQzovVXNlcnMvQWRtaW4vRGVza3RvcC9SIHN0YXRzIGhvbWV3b3JrL0ZpbmFsIFByb2plY3Qva25iLWx0ZXItaGZyLjI4NS42L2hmMjg1LTA5LW1hcGxlLXNlZWQtY291bnQuY3N2IikNCg0KaGYyODVfMTBfbGVhZl9yZW1vdmFsIDwtIHJlYWRfY3N2KCJDOi9Vc2Vycy9BZG1pbi9EZXNrdG9wL1Igc3RhdHMgaG9tZXdvcmsvRmluYWwgUHJvamVjdC9rbmItbHRlci1oZnIuMjg1LjYvaGYyODUtMTAtbGVhZi1yZW1vdmFsLmNzdiIpDQoNCmhmMjg1XzExX2xlYWZfcmVtb3ZhbF9icmFuY2hlcyA8LSByZWFkX2NzdigiQzovVXNlcnMvQWRtaW4vRGVza3RvcC9SIHN0YXRzIGhvbWV3b3JrL0ZpbmFsIFByb2plY3Qva25iLWx0ZXItaGZyLjI4NS42L2hmMjg1LTExLWxlYWYtcmVtb3ZhbC1icmFuY2hlcy5jc3YiKQ0KDQoNCmhmMjg1XzEyX2xlYWZfc2VlZF9yZW1vdmFsIDwtIHJlYWRfY3N2KCJDOi9Vc2Vycy9BZG1pbi9EZXNrdG9wL1Igc3RhdHMgaG9tZXdvcmsvRmluYWwgUHJvamVjdC9rbmItbHRlci1oZnIuMjg1LjYvaGYyODUtMTItbGVhZi1zZWVkLXJlbW92YWwuY3N2IikNCg0KDQpoZjI4NV8xM19sZWFmX3NlZWRfcmVtb3ZhbF9icmFuY2hlcyA8LSByZWFkX2NzdigiQzovVXNlcnMvQWRtaW4vRGVza3RvcC9SIHN0YXRzIGhvbWV3b3JrL0ZpbmFsIFByb2plY3Qva25iLWx0ZXItaGZyLjI4NS42L2hmMjg1LTEzLWxlYWYtc2VlZC1yZW1vdmFsLWJyYW5jaGVzLmNzdiIpDQoNCmhmMjg1XzE0X3Blcm1fYnJhbmNoZXMgPC0gcmVhZF9jc3YoIkM6L1VzZXJzL0FkbWluL0Rlc2t0b3AvUiBzdGF0cyBob21ld29yay9GaW5hbCBQcm9qZWN0L2tuYi1sdGVyLWhmci4yODUuNi9oZjI4NS0xNC1wZXJtLWJyYW5jaGVzLmNzdiIpDQpgYGANCg0KIyMjIE1hc3RpbmcgYW5kIE5vbi1NYXN0aW5nIA0KDQpGaXJzdCB3ZSBuZWVkIHRvIGJldHRlciB1bmRlcnN0YW5kIG91ciBwcm9ibGVtIGFuZCBsZWFybiBhIGZldyBrZXkgZGVmaW50aW9ucy4gQSBtYXN0aW5nIHRyZWUgaXMgYSB0cmVlIHRoYXQgcHJvZHVjZXMgc2VlZHMgbGFyZ2UgcXVhbml0aWVzIGluIGlycmVndWxhciBpbnRlcnZhbHMuIE91ciBzdWdhciBtYXBsZSB0cmVlcyBhcmUgbWFzdGluZyB0cmVlcyBhbmQgd2Ugd2FudCB0byBrbm93IGlmIHRoZSByZWQgbWFwbGVzIHNob3cgbXV0ZWQgZHluYW1pY3Mgd2hlbiBjb21wYXJlZCB0byB0aGUgc3VnYXIgbWFwbGVzLiBUbyBiZXR0ZXIgdW5kZXJzdGFuZCBvdXIgc3VnYXIgbWFwbGVzIHdlIGZpcnN0IG5lZWQgdG8gc2VlIHdoYXQgeWVhcnMgd2VyZSBtYXN0aW5nIHllYXJzIGZvciB0aGUgdHJlZXMuIFdlIGRvIHRoaXMgYnkgZXhhbWVuaW5nIHRoZSBzZWVkIGNvbGxlY3Rpb24gZGF0YSBhdmVyYWdlIGZvciB0aGUgc3VnYXIgbWFwbGVzIGVhY2ggeWVhciBvZiB0aGUgZGF0YS4gDQoNCmBgYHtyfQ0KDQp0cmVlX3NlZWRfZGF0YSA8LSBoZjI4NV8wOV9tYXBsZV9zZWVkX2NvdW50ICU+JQ0KICBmaWx0ZXIoIWlzLm5hKHRvdGFsLmNvdW50KSkgJT4lDQogIG11dGF0ZSh5ZWFyID0gYXMubnVtZXJpYyhmb3JtYXQoZGF0ZSwgIiVZIikpKSAlPiUNCiAgZ3JvdXBfYnkodHJlZSwgeWVhcikgJT4lDQogIHN1bW1hcmlzZShUb3RhbF9TZWVkcyA9IHN1bSh0b3RhbC5jb3VudCwgbmEucm0gPSBUUlVFKSwgLmdyb3VwcyA9ICJkcm9wIikNCg0KZ2dwbG90KHRyZWVfc2VlZF9kYXRhLCBhZXMoeCA9IGZhY3Rvcih5ZWFyKSwgeSA9IHRyZWUsIGZpbGwgPSBUb3RhbF9TZWVkcykpICsNCiAgZ2VvbV90aWxlKGNvbG9yID0gImJsYWNrIiwgbGluZXdpZHRoID0gMC41KSArDQogIHNjYWxlX2ZpbGxfdmlyaWRpc19jKCkgKw0KICBsYWJzKA0KICAgIHRpdGxlID0gIlllYXJseSBTZWVkIENvdW50IGJ5IFRyZWUiLA0KICAgIHggPSAiWWVhciIsDQogICAgeSA9ICJUcmVlIElEIiwNCiAgICBmaWxsID0gIlNlZWQgQ291bnQiDQogICkNCmBgYA0KQmFzZWQgb24gdGhlIGhlYXQgbWFwIHdlIGNhbiBzZWUgYSBmZXcgeWVhcnMgdGhhdCBzdGljayBvdXQgMjAxMSwgMjAxMywgMjAxNywgYW5kIDIwMTkuIFRoZXNlIGFyZSB0aGUgYmVzdCBpbmRpY2F0b3JzIHRoYXQgc2hvdyB3aGF0IHllYXJzIHdlIGNhbiBzZWUgdGhlIG1hc3RpbmcgdGFraW5nIHBsYWNlIGluIG91ciBzdWdhciBtYXBsZXMuDQoNCg0KTmV4dCBiZWxvdyB3ZSBhZGQgb3VyIG1hc3RpbmcgeWVhcnMgd2UgZm91bmQgdG8gb3VyIHNhcCBjb2xsZWN0aW9uIGFuZCBzdWdhciBjb250ZW50IGRhdGFzZXQgZm9yIHRoZSBhcHByb3ByYXRlIHRyZWVzIHdoaWNoIHdlIGNhbiB1c2UgZm9yIGxhdGVyIHRvIGF0dGVwdCB0byBidWlsZCBhIG1vZGVsIHRvIHByZWRpY3QgbWFzdGluZyBzZWFzb25zLiANCmBgYHtyfQ0KaGYyODVfMDJfbWFwbGVfc2FwIDwtIGhmMjg1XzAyX21hcGxlX3NhcCAlPiUNCiAgbXV0YXRlKGRhdGUgPSBhcy5EYXRlKGRhdGUpKQ0KDQpoZjI4NV8wMl9tYXBsZV9zYXAgPC0gaGYyODVfMDJfbWFwbGVfc2FwICU+JQ0KICBtdXRhdGUoeWVhciA9IHllYXIoZGF0ZSkpDQoNCmhmMjg1XzAyX21hcGxlX3NhcF9tYXN0aW5nIDwtIGhmMjg1XzAyX21hcGxlX3NhcCAlPiUNCiAgbXV0YXRlKG1hc3RpbmcgPSBpZmVsc2UoeWVhciAlaW4lIGMoMjAxMSwgMjAxMywgMjAxNywgMjAxOSksICJZZXMiLCAiTm8iKSkNCg0KaGVhZChoZjI4NV8wMl9tYXBsZV9zYXBfbWFzdGluZykNCmBgYA0KIyMjIEJyZWFraW5nIGRvd24ga2V5IGluZGljYXRvcnMgDQoNCkhlcmUgaWYgd2Ugd2FudCB0byBsb29rIGZvciBrZXkgaW5kaWNhdG9ycyBpbiBvdXIgc3VnYXIgbWFwbGVzIHRoYXQgY291bGQgcHJlZGljdCB3aGVuIGEgbWFzdGluZyBtaWdodCBvY2N1ci4gVGhlc2Uga2V5ZSBwcmVkaWN0b3JzIGNvdWxkIGhlbHAgdXMgYmV0dGVyIGNvbXBhcmUgYW5kIHVuZGVydGFuZCBpZiBvdXIgcmVkIG1hcGxlcyBhcmUgZXhoaWJpdGluZyBzaWducyBvZiANCm11dGVkIGR5bmFtaWNzLiBCZWxvdyB3ZSBncmFwaCBib3RoIHRoZSBzdWdhciBhbmQgcmVkIG1hcGxlcyBhdmVyYWdlIHNhcCBzdWdhciBjb250ZW50IGZvciB5ZWFycyB0aGVyZSB3YXMgZGF0YSBjb2xsZWN0ZWQuIEhGIHN0YW5kcyBmb3Igc3VnYXIgbWFwbGUgYW5kIEFSIGZvciByZWQgbWFwbGUuDQpgYGB7cn0NCmdyb3VwZWRfZGF0YSA8LSBoZjI4NV8wMl9tYXBsZV9zYXAgJT4lDQogIGZpbHRlcighaXMubmEoc3VnYXIpKSAlPiUNCiAgbXV0YXRlKFRyZWVfR3JvdXAgPSBzdWJzdHIodHJlZSwgMSwgMikpICU+JQ0KICBncm91cF9ieShkYXRlLCBUcmVlX0dyb3VwKSAlPiUNCiAgc3VtbWFyaXNlKEF2ZXJhZ2VfU3VnYXIgPSBtZWFuKHN1Z2FyLCBuYS5ybSA9IFRSVUUpLCAuZ3JvdXBzID0gImRyb3AiKQ0KDQpnZ3Bsb3QoZ3JvdXBlZF9kYXRhLCBhZXMoeCA9IGRhdGUsIHkgPSBBdmVyYWdlX1N1Z2FyLCBjb2xvciA9IFRyZWVfR3JvdXAsIGdyb3VwID0gVHJlZV9Hcm91cCkpICsNCiAgZ2VvbV9saW5lKCkgKw0KICBnZW9tX3BvaW50KCkgKw0KICBsYWJzKA0KICAgIHRpdGxlID0gIkF2ZXJhZ2UgU3VnYXIgQ29udGVudCBPdmVyIFRpbWUiLA0KICAgIHggPSAiRGF0ZSIsDQogICAgeSA9ICJBdmVyYWdlIFN1Z2FyIENvbnRlbnQiLA0KICAgIGNvbG9yID0gIlRyZWUgR3JvdXAiDQogICkNCmBgYA0KIFdoaWxlIHdlIGNhbiBzZWUgdGhlIGF2ZXJhZ2Ugc3VnYXIgY29udGVudCBpcyBtdWNoIGxvd2VyIGZvciB0aGUgcmVkIG1hcGxlIHRoYXQgZG9lc24ndCBhbnN3ZXIgb3VyIHF1ZXN0aW9uIHJpZ2h0IGF3YXkgZXNwZWNpYWxseSB3aGVuIHRoZSBkYXRhIGNvbGxlY3RlZCBmb3IgcmVkIG1hcGxlcyBpcyB2ZXJ5IHNtYWxsIHdpdGggb25seSBhYm91dCA0LTUgeWVhcnMgb2YgZGF0YSBjb2xsZWN0ZWQgdGhlIGRhdGEgc2ltcGx5IGlzbid0IGNvbmNsdXNpdmUgZW5vdWdoIHRvIGFuc3dlciBvdXIgcXVlc3Rpb24uIA0KDQpIZXJlIGlzIHdoZXJlIGNhbiBzdGFydCB0byBkaWcgaW4gYW5kIHNlZSBpZiBvdmVybGF5aW5nIG91ciBncmFwaHMgYmV0d2VlbiB5ZWFseSBhdmVyYWdlIHN1Z2FyIGNvbnRlbnQgb2YgdGhlIHN1Z2FyIG1hcGxlIHRyZWVzIChIRikgYW5kIHRoZSBhdmVyZ2Ugc2VlZCBjb3VudCBvZiBzdWdhciBtYXBsZXMgaGF2ZSBzaW1sYXIgZ3JhcGhzLiANCg0KIyMjQXZlcmFnZSBzZWVkIGNvdW50IHBlciB5ZWFyIGNvbXBhcmVkIHRvIGF2ZXJhZ2Ugc3VnYXIgY29udGVudCBvZiBzdWdhciBtYXBsZXMgIA0KYGBge3J9DQpoZjI4NV8wMl9tYXBsZV9zYXBfSEYgPC0gaGYyODVfMDJfbWFwbGVfc2FwICU+JSANCiAgZmlsdGVyKGdyZXBsKCJeSEYiLCB0cmVlKSwgIWlzLm5hKHN1Z2FyKSkNCg0KaGYyODVfMDlfbWFwbGVfc2VlZF9jb3VudF9IRiA8LSBoZjI4NV8wOV9tYXBsZV9zZWVkX2NvdW50ICU+JQ0KICBmaWx0ZXIoZ3JlcGwoIl5IRiIsIHRyZWUpLCAhaXMubmEodG90YWwuY291bnQpKQ0KDQpoZjI4NV8wMl9tYXBsZV9zYXBfSEYgPC0gaGYyODVfMDJfbWFwbGVfc2FwX0hGICU+JSANCiAgbXV0YXRlKHllYXIgPSB5ZWFyKGRhdGUpKQ0KDQpoZjI4NV8wOV9tYXBsZV9zZWVkX2NvdW50X0hGIDwtIGhmMjg1XzA5X21hcGxlX3NlZWRfY291bnRfSEYgJT4lDQogIG11dGF0ZSh5ZWFyID0geWVhcihkYXRlKSkNCg0KYXZlcmFnZV9kYXRhIDwtIGhmMjg1XzAyX21hcGxlX3NhcF9IRiAlPiUNCiAgZ3JvdXBfYnkoeWVhcikgJT4lDQogIHN1bW1hcmlzZShhdmVyYWdlX3N1Z2FyID0gbWVhbihzdWdhciwgbmEucm0gPSBUUlVFKSkNCg0KYXZlcmFnZV9zZWVkcyA8LSBoZjI4NV8wOV9tYXBsZV9zZWVkX2NvdW50X0hGICU+JQ0KICBncm91cF9ieSh5ZWFyKSAlPiUNCiAgc3VtbWFyaXNlKGF2ZXJhZ2Vfc2VlZHMgPSBtZWFuKHRvdGFsLmNvdW50LCBuYS5ybSA9IFRSVUUpKQ0KDQptZXJnZWRfYXZnX2RhdGEgPC0gbGVmdF9qb2luKGF2ZXJhZ2VfZGF0YSwgYXZlcmFnZV9zZWVkcywgYnkgPSAieWVhciIpDQoNCm1lcmdlZF9hdmdfZGF0YV9jbGVhbiA8LSBtZXJnZWRfYXZnX2RhdGEgJT4lDQogIGZpbHRlcighaXMubmEoYXZlcmFnZV9zdWdhcikgJiAhaXMubmEoYXZlcmFnZV9zZWVkcykpDQoNCnN1Z2FyX2NvbnRlbnRfSEYgPC0gZ2dwbG90KG1lcmdlZF9hdmdfZGF0YV9jbGVhbiwgYWVzKHggPSB5ZWFyLCB5ID0gYXZlcmFnZV9zdWdhcikpICsNCiAgZ2VvbV9saW5lKGNvbG9yID0gImJsdWUiLCBzaXplID0gMSkgKw0KICBnZW9tX3BvaW50KGNvbG9yID0gInJlZCIsIHNpemUgPSAzKSArDQogIGxhYnMoDQogICAgdGl0bGUgPSAiQXZlcmFnZSBTdWdhciBDb250ZW50IGZvciBIRiBUcmVlcyBieSBZZWFyIiwNCiAgICB4ID0gIlllYXIiLA0KICAgIHkgPSAiQXZlcmFnZSBTdWdhciBDb250ZW50Ig0KICApICsNCiAgdGhlbWVfbWluaW1hbCgpDQoNCnNlZWRfY291bnRfSEYgPC0gZ2dwbG90KG1lcmdlZF9hdmdfZGF0YV9jbGVhbiwgYWVzKHggPSB5ZWFyLCB5ID0gYXZlcmFnZV9zZWVkcykpICsNCiAgZ2VvbV9saW5lKGNvbG9yID0gImdyZWVuIiwgc2l6ZSA9IDEpICsNCiAgZ2VvbV9wb2ludChjb2xvciA9ICJvcmFuZ2UiLCBzaXplID0gMykgKw0KICBsYWJzKA0KICAgIHRpdGxlID0gIkF2ZXJhZ2UgU2VlZCBDb3VudCBmb3IgSEYgVHJlZXMgYnkgWWVhciIsDQogICAgeCA9ICJZZWFyIiwNCiAgICB5ID0gIkF2ZXJhZ2UgU2VlZCBDb3VudCINCiAgKSArDQogIHRoZW1lX21pbmltYWwoKQ0KDQpwcmludChzdWdhcl9jb250ZW50X0hGKQ0KcHJpbnQoc2VlZF9jb3VudF9IRikNCmBgYA0KSGVyZSB3ZSBjYW4gc2VlIHRoYXQgd2hpbGUgdGhlIGdyYXBocyBkbyBoYXZlIGEgc2ltaWxhciBzaGFwZSB0aGUgb3ZlcmFsbCBwYXR0ZXJucyBkb24ndCBtYXRjaCBleGFjdGx5IHNvIHRvIGJldHRlciB0cnkgYW5kIGZpbmQgb3VyIGtleSBwcmVkaWN0b3JzIHdlIGNhbiB1c2Ugb3VyIGFkZGVkIG1hc3RpbmcgY29sdW1uIGZyb20gZWFybGllciB0byBjcmVhdGUgYSBsaW5lYXIgbW9kZWwuIA0KDQojIyMgQnVpbGRpbmcgYSBtb2RlbCB3aXRoIG91ciBkYXRhDQoNCkJlbG93IHdlIHVzZSBvdXIgYWRkZWQgZGF0YSBmcm9tIGJlZm9yZSB0byBhdHRlcHQgdG8gcHJlZGljdCB0aGUgc3VnYXIgdHJlZSBtYXN0aW5ncyBiYXNlZCBvbiBzdWdhciBjb250ZW50IG9mIHRyZWVzIHNhcC4gDQpgYGB7cn0NCmhmMjg1XzAyX21hcGxlX3NhcF9IRiA8LSBoZjI4NV8wMl9tYXBsZV9zYXBfbWFzdGluZyAlPiUNCiAgbXV0YXRlKG1hc3RpbmdfYmluYXJ5ID0gaWZlbHNlKG1hc3RpbmcgPT0gIlllcyIsIDEsIDApKQ0KDQpsbV9tb2RlbCA8LSBsbShtYXN0aW5nX2JpbmFyeSB+IHN1Z2FyLCBkYXRhID0gaGYyODVfMDJfbWFwbGVfc2FwX0hGKQ0KDQpzdW1tYXJ5KGxtX21vZGVsKQ0KYGBgDQpIZXJlIHdlIGdldCB0byBrbm93IGJyZWFrIGRvd24gb3VyIG1vZGVsIGFuZCBsb29rIGF0IGl0cyBrZXkgdmFsdWVzLiBSaWdodCBvZmYgdGhlIGJhdCB3ZSBjYW4gc2VlIHRoZSBzdWdhciBjb2VmIG9mIC4wNDE1NTUgc28gZm9yIGV2ZXJ5IGluY3JlYXNlIGluIDEgdW5pdCBvZiBzdWdhciB3ZSBzZWUgYSA0LjE1JSBpbmNyZWFzZSBpbiB0aGUgY2hhbmNlIG9mIGEgbWFzdGluZyB5ZWFyLiBOZXh0IHdlIGNhbiBzZWUgdGhhdCBvdXIgUlNFIGlzIHF1aXRlIGhpZ2gsIGEgbG93ZXIgdmFsdWUgd291bGQgYmUgYmV0dGVyIGJ1dCB0aGlzIGRvZXMgc2hvdyB0aGF0IHNvbWUgdmFyaWFiaWxpdHkgcmVtYWlucyB1bmV4cGxhaW5lZC4gT3VyIFIgc3F1YXJlZCB2YWx1ZSBvZiBqdXN0IC4wMDMzNTIgc2hvd3MgdGhhdCBzdWdhciBhbG9uZSBpcyBub3QgYSBzdHJvbmcgcHJlZGljdG9yLiBMYXN0bHkgd2UgbG9vayBhdCBvdXIgcC12YWx1ZSB3aGljaCBzaG93cyBhbiBpbmNyZWRseSBzbWFsbCAyLjE0M2UtMDcuIFNvIHdoaWxlIHN1Z2FyIGlzbid0IGEgZ3JlYXQgc29sbyBwcmVkaWN0b3Igb3VyIG5ldyBtb2RlbCBpcyBzdGF0aXN0aWNhbGx5IHNpZ25pZmljYW50LiANCg0KDQpXaXRoIHN1Z2FyIGNvbnRlbnQgaGVscGluZyB3b3JrIHRvd2FyZHMgYSBzdHJvbmdlciBtb2RlbCB3ZSBjYW4gbG9vayBhdCBvdGhlciBwb3NzaWJsZSBwcmVkaWN0b3JzIHdlIG1pZ2h0IGhhdmUgb3ZlciBsb29rZWQuIEJlbG93IEkgaGF2ZSB0YWtlbiB0aGVoZjI4NV8wM19tYXBsZV9mbG93ZXJfcXVhbCBkYXRhIHNldCBhbmQgZWRpdGVkIHRoZSBkYXRhIHRvIGdpdmUgdmFsdWVzIHRvIHRoZSBmbG93ZXJpbmcuaW50ZW5zaXR5IGJhc2VkIG9uIHRoZSB2YWx1ZXMgcHJvdmlkZWQgYnkgSGFydmFkcyByYW5nZXMgd2hpY2ggY2FuIGJlIGZvdW5kIGhlcmUgaHR0cHM6Ly9oYXJ2YXJkZm9yZXN0MS5mYXMuaGFydmFyZC5lZHUvZXhpc3QvYXBwcy9kYXRhc2V0cy9zaG93RGF0YS5odG1sP2lkPWhmMjg1LiBXaGljaCBzdGF0ZXMgdGhhdCBkYXRhIHNldCBoZjI4NV8wM19tYXBsZV9mbG93ZXJfcXVhbCBnaXZlcyB0aGVzZSByYW5nZXMNCg0KImZsb3dlcmluZy5pbnRlbnNpdHk6IHF1YWxpdGF0aXZlIGV2YWx1YXRpb24gb2Ygd2hvbGUtdHJlZSBmbG93ZXJpbmcNCiAgICBsb3c6IGdlbmVyYWxseSA8MSwwMDAgZmxvd2VyaW5nIGJ1ZHMNCiAgICBtZWRpdW06IGdlbmVyYWxseSAxLDAwMC0xMCwwMDAgZmxvd2VyaW5nIGJ1ZHMNCiAgICBoaWdoOiBnZW5lcmFsbHkgPjEwLDAwMCBmbG93ZXJpbmcgYnVkcw0KICAgIG5vbmU6IG5vIGZsb3dlcmluZyBidWRzIg0KDQpgYGB7cn0NCg0KaGYyODVfMDNfbWFwbGVfZmxvd2VyX3F1YWxfZWRpdCA8LSBoZjI4NV8wM19tYXBsZV9mbG93ZXJfcXVhbCAlPiUNCiAgbXV0YXRlKGZsb3dlcmluZ192YWx1ZSA9IGNhc2Vfd2hlbigNCiAgICBmbG93ZXJpbmcuaW50ZW5zaXR5ID09ICJub25lIiB+IDAsDQogICAgZmxvd2VyaW5nLmludGVuc2l0eSA9PSAibG93IiB+IDk5OSwNCiAgICBmbG93ZXJpbmcuaW50ZW5zaXR5ID09ICJtZWRpdW0iIH4gNTAwMCwNCiAgICBmbG93ZXJpbmcuaW50ZW5zaXR5ID09ICJoaWdoIiB+IDEwMDAwLA0KICAgIFRSVUUgfiBOQV9yZWFsXw0KICApKQ0KDQpoZWFkKGhmMjg1XzAzX21hcGxlX2Zsb3dlcl9xdWFsX2VkaXQpDQpgYGANCldoaWxlIGNyZWF0aW5nIHRoZSBudW1iZXJzIGZvciBlYWNoIGdyb3VwIGlzIG92ZXJyZWFjaGluZy4gVGhlIGRhdGFzZXQgaXRzZWxmIGdpdmVzIHVzIHZlcnkgbGl0dGxlIHRvIHdvcmsgd2l0aCBzbyBhdHRlcHRpbmcgdG8gcHV0IG51bWJlcnMgdG8gdmFsdWVzIHRoYXQgSGFydmFkIG9mZmVyZWQgaXMgdGhlIGJlc3Qgd2UgY2FuIGRvIHRvIGdldCBhIGJldHRlciBpZGVhIG9mIG91ciBwcmVkaWN0b3JzLg0KDQoNCk5vdyB0aGF0IHdlIGhhdmUgdmFsdWVzIGZvciBvdXQgZmxvd2VyIGludGVuc2l0eSB3ZSBjYW4gcHV0IGl0IHRvIGEgZ3JhcGggYW5kIGNvbXBhcmUgdG8gb3VyIGdyYXBoIG9mIG1hc3RpbmdzDQoNCmBgYHtyfQ0KYXZlcmFnZV9mbG93ZXJpbmdfZGF0YSA8LSBoZjI4NV8wM19tYXBsZV9mbG93ZXJfcXVhbF9lZGl0ICU+JQ0KICBncm91cF9ieSh5ZWFyKSAlPiUNCiAgc3VtbWFyaXNlKGF2ZXJhZ2VfZmxvd2VyaW5nID0gbWVhbihmbG93ZXJpbmdfdmFsdWUsIG5hLnJtID0gVFJVRSkpDQoNCg0KDQpnZ3Bsb3QoYXZlcmFnZV9mbG93ZXJpbmdfZGF0YSwgYWVzKHggPSBmYWN0b3IoeWVhciksIHkgPSBhdmVyYWdlX2Zsb3dlcmluZykpICsNCiAgZ2VvbV9wb2ludChjb2xvciA9ICJibHVlIiwgc2l6ZSA9IDMpICsNCiAgbGFicygNCiAgICB0aXRsZSA9ICJBdmVyYWdlIEZsb3dlcmluZyBJbnRlbnNpdHkgZm9yIHRoZSBGb3Jlc3QgT3ZlciBUaW1lIiwNCiAgICB4ID0gIlllYXIiLA0KICAgIHkgPSAiQXZlcmFnZSBGbG93ZXJpbmcgSW50ZW5zaXR5Ig0KICApICsNCiAgdGhlbWVfbWluaW1hbCgpICsNCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA0NSwgaGp1c3QgPSAxKSkNCmBgYA0KSGVyZSB3ZSBjYW4gc2VlIGEgc3Ryb25nIHBhdHRlcm4gdGhvdWdoIHdlIHNlZSBsYXJnZSBzcGlrZXMgb24gb3VyIG1hc3RpbmcgeWVhcnMgd2l0aCAyMDExLCAyMDEzLCAyMDE3LCBhbmQgMjAxOSEgVGhpcyBpcyB2ZXJ5IGJpZyBiZWN1YXNlIGl0IG1hdGNoZXMgdmVyeSBjbG9zZSB0byBvdXIgaGVhdCBtYXAgb2Ygb3VyIG1hc3RpbmcgeWVhcnMuIEJ1dCBqdXN0IGxvb2tpbmcgc2ltaWxhciBpc24ndCBlbm91Z2gsIHdlIGNhbiB0ZXN0IHRoaXMgYnkgYWRkaW5nIG9uIHRvIG91ciBsaW5lYXIgbW9kZWwgdG8gc2VlIGlmIHRoZSBudW1iZXIgb2YgZmxvd2VycyBpcyBhIGdvb2QgcHJlZGljdG9yLg0KDQpCZWxvdyB3ZSBsb29rIHRvIHRlc3QgaWYgdGhlIG51bWJlciBvZiBmbG93ZXIgaXMgYSBhY2N1cmF0ZSBwcmVkaWN0b3Igb24gaWYgc3VnYXIgbWFwbGUgdHJlZXMgd2lsbCBoYXZlIGEgbWFzdGluZyB5ZWFyLiBCeSBjb21iaW5pbmcgaXQgd2l0aCBvdXIgc3VnYXIgbW9kZWwgZnJvbSBlYXJsaWVyLiANCmBgYHtyfQ0KYXZlcmFnZV9mbG93ZXJpbmdfZGF0YV9tYXN0aW5nIDwtIGhmMjg1XzAzX21hcGxlX2Zsb3dlcl9xdWFsX2VkaXQgJT4lDQogIG11dGF0ZSgNCiAgICBtYXN0aW5nID0gaWZlbHNlKHllYXIgJWluJSBjKDIwMTEsIDIwMTMsIDIwMTcsIDIwMTkpLCAiWWVzIiwgIk5vIiksDQogICAgbWFzdGluZ19iaW5hcnkgPSBpZmVsc2UobWFzdGluZyA9PSAiWWVzIiwgMSwgMCkNCiAgKQ0KbG1fbW9kZWxfZmxvd2VyaW5nIDwtIGxtKG1hc3RpbmdfYmluYXJ5IH4gZmxvd2VyaW5nX3ZhbHVlLCBkYXRhID0gYXZlcmFnZV9mbG93ZXJpbmdfZGF0YV9tYXN0aW5nKQ0KDQpzdW1tYXJ5KGxtX21vZGVsX2Zsb3dlcmluZykNCmBgYA0KRmlyc3Qgb2ZmIHdlIGNhbiBzZWUgYnkgb3VyIGF2ZXJhZ2VfZmxvd2VyaW5nIGNvZWYgc2hvd2luZyAuMDA0IGF2ZXJhZ2UgZmxvd2VyaW5nIGlzIHN0YXRpc3RpY2FsbHkgc2lnbmlmaWNhbnQuIFNlY29uZCB3ZSBjYW4gc2VlIG91ciBpbnRlcmNlcHQgc2hvd3MgdGhhdCBmb3IgZXZlcnkgaW5jcmVhc2UgYnkgMSBmbG93ZXIgaW5jcmVhc2VzIHRoZSBjaGFuY2Ugb2YgYSBtYXN0aW5nIHllYXIgYnkgLjAwMDEuIFdoaWNoIG9uIHRoZSBzdXJmYWNlIGRvZXNuJ3Qgc2VlbSBsaWtlIG11Y2ggd2hlbiBkZWFsaW5nIHdpdGggdHJlZXMgdGhlc2UgYmxvc3NvbXMgY2FuIHJhbmdlIGZyb20gYSBmZXcgaHVuZHJlZCB0byB3ZWxsIG92ZXIgdGVuIHRob3VzYW5kIHRoaXMgY2FuIGFkZCB1cC4gTm93IHdoZW4gd2UgbG9vayBhdCBSU0UgdGhlcmUgYXJlIGltcHJvdmVtZW50cyBvdmVyIHRoZSBzdWdhciBtb2RlbCB3aXRoIG91cnMgYmVpbmcgLjMzNCB3aGljaCBzaG93cyB1cyB0aGUgbW9kZWwgaXMgYSBiZXR0ZXIgZml0LiBPdXIgUiBzcXVhcmVkIHNob3dzIC41Nzkgc2hvd2luZyB1cyB0aGF0IGFib3V0IDU4JSBvZiB0aGUgdmFyaWFuY2UgaW4gdGhlIG1hc3RpbmcgYmluYXJ5IG91dGNvbWUgaXMgZXhwbGFpbmVkIGJ5IGF2ZXJhZ2VfZmxvd2VyaW5nLiBMYXN0bHkgb3VyIHAtdmFsdWUgc2hvd3MgdGhhdCBvdmVyIGFsbCB0aGlzIG1vZGVsIGlzICBzdGF0aXN0aWNhbGx5IHNpZ25pZmljYW50LiANCg0KDQpgYGB7cn0NCg0KdmlldyhoZjI4NV8wMl9tYXBsZV9zYXBfbWFzdGluZykNCg0KY29tYmluZWRfZGF0YSA8LSBsZWZ0X2pvaW4oDQogIGF2ZXJhZ2VfZmxvd2VyaW5nX2RhdGFfbWFzdGluZywgDQogIGhmMjg1XzAyX21hcGxlX3NhcF9tYXN0aW5nICU+JSANCiAgICBncm91cF9ieSh5ZWFyKSAlPiUgDQogICAgc3VtbWFyaXNlKGF2ZXJhZ2Vfc3VnYXIgPSBtZWFuKHN1Z2FyLCBuYS5ybSA9IFRSVUUpKSwgDQogIGJ5ID0gInllYXIiDQopDQoNCg0KY29tYmluZWRfbG0gPC0gbG0obWFzdGluZ19iaW5hcnkgfiBmbG93ZXJpbmdfdmFsdWUgKyBhdmVyYWdlX3N1Z2FyLCBkYXRhID0gY29tYmluZWRfZGF0YSkNCg0Kc3VtbWFyeShjb21iaW5lZF9sbSkNCg0KYGBgDQpGaXJzdCBvZmYgd2UgY2FuIHNlZSBieSBvdXIgYXZlcmFnZV9mbG93ZXJpbmcgY29lZiBpcyBpbmNyZWRpYmx5IHNtYWxsIHNvIGF2ZXJhZ2UgZmxvd2VyaW5nIGlzIGhpZ2hseSBzdGF0aXN0aWNhbGx5IHNpZ25pZmljYW50LiBTZWNvbmQgd2UgY2FuIHNlZSBvdXIgaW50ZXJjZXB0IHNob3dzIHRoYXQgZm9yIGV2ZXJ5IGluY3JlYXNlIGJ5IDEgZmxvd2VyIGluY3JlYXNlcyB0aGUgY2hhbmNlIG9mIGEgbWFzdGluZyB5ZWFyIGJ1dCBvbmx5IGJ5IDQuODk3ZS0wNS4gV2hpY2ggb24gdGhlIHN1cmZhY2UgZG9lc24ndCBzZWVtIGxpa2UgbXVjaCB3aGVuIGRlYWxpbmcgd2l0aCB0cmVlcyB0aGVzZSBibG9zc29tcyBjYW4gcmFuZ2UgZnJvbSBhIGZldyBodW5kcmVkIHRvIHdlbGwgb3ZlciB0ZW4gdGhvdXNhbmQgdGhpcyBjYW4gYWRkIHVwLiBPdXIgYXZlcmFnZSBzdWdhciBoYXMgY2hhbmdlZCBzb21lIHRvbyB3ZSBub3cgc2VlIHRoZSBjb2VmIGF0IC4wMDIgbWFraW5nIGl0IGEgc3RhdGlzdGljYWxseSBzaWduaWZpY2FudCBwcmVkaWN0b3Igb2YgbWFzdGluZy4gTm93IHdoZW4gd2UgbG9vayBhdCBSU0UgdGhlcmUgYXJlIGltcHJvdmVtZW50cyBvdmVyIHRoZSBzdWdhciBtb2RlbCB3aXRoIG91cnMgYmVpbmcgLjM3NiB3aGljaCBzaG93cyB1cyB0aGUgbW9kZWwgaXMgYSBiZXR0ZXIgZml0IHRoZW4gYmVmb3JlLiBPdXIgUiBzcXVhcmVkIHNob3dzIC4yOTUgc2hvd2luZyB1cyB0aGF0IGFib3V0IDMwJSBvZiB0aGUgdmFyaWFuY2UgaW4gdGhlIG1hc3RpbmcgYmluYXJ5IG91dGNvbWUgaXMgZXhwbGFpbmVkIGJ5IGF2ZXJhZ2VfZmxvd2VyaW5nIGFuZCBhdmVyYWdlX3N1Z2FyLiBMYXN0bHkgb3VyIHAtdmFsdWUgc2hvd3MgdGhhdCBvdmVyIGFsbCB0aGlzIG1vZGVsIGlzIGhpZ2hseSBzdGF0aXN0aWNhbGx5IHNpZ25pZmljYW50LiBXaGlsZSBvdXIgZGF0YSBzaG93cyB0aGF0IHRoaXMgbW9kZWwgaXMgc3RhdGlzdGljYWxseSBzaWduaWZpY2FudCBvdXIgUiBzcXVhcmVkIG9ubHkgZXhwbGFpbnMgYWJvdXQgMzAlIG9mIHRoZSB2YXJpYW5jZSBpbiB0aGUgbW9kZWwgc2hvd2luZyB0aGUgbW9kZWwgbmVlZHMgbW9yZSBkYXRhIHRvIGJldHRlciBwcmVkaWN0IG1hc3Rpbmcgc2Vhc29ucy4gDQoNCg0KIyMjIEluIGNvbmNsdWlvbiANCk92ZXJhbGwsIHdoaWxlIHRoZXJlIGlzIG5vdCBlbm91Z2ggZGF0YSB0byBhY2N1cmF0ZWx5IHN0YXRlIHdoZXRoZXIgcmVkIG1hcGxlIHNwZWNpZXMgZXhoaWJpdCBtdXRlZCBkeW5hbWljcw0Kb3Igbm90IEkgYmVsaWV2ZSB0aGF0IHRoZSB0d28gYmVzdCBrZXkgcHJlZGljdG9yIGluIHRoaXMgbGltaXRlZCBkYXRhIHNldCBhcmUgc2FwIHN1Z2FyIGNvbnRlbnQgYW5kIHRoZSBudW1iZXIgb2YgZmxvd2VycyBpbiBibG9vbS4gSWYgdGhlIGRhdGEgd2VyZSBtb3JlIGNvbXBsZXRlIEkgYmVsaWV2ZSB0aGF0IHRoZXNlIHR3byBwcmVkaWN0b3JzIGNvdWxkIGJlIHVzZWQgdG8gYmV0dGVyIHNlZSBpZiB0aGUgcmVkIG1hcGxlIHRyZWVzIGV4aGliaXQgbXV0ZWQgZHluYW1pY3Mgd2hlbiBjb21wYXJlZCB0byB0aGUgc3VnYXIgbWFwbGUgdHJlZXMgYnV0IHdpdGggdGhlIGN1cnJlbnQgZGF0YSBzZXQgbGltaXRhdGlvbnMgdGhlIGRhdGEgaXMgaW5jb25jbHVzaXZlIA==