Objective
Ben and I would like to talk over some of our results from ED, start discussing and thinking about a paper that uses the model and field results, we have started outlining a manuscript here.
Met Inputs
- dlwrf — downward long wave radiation (W m-2)
- nbdsf — near infrared beam downward solar radiation (W m-2)
- nddsf — near IR diffuse downward solar radiation (W m-2)
- vbdsf — visible beam downward solar radiation (W m-2)
- vddsf — visible diffuse downward solar radiation (W m-2)
- prate — precipitation rate (kgH2O m-2 s-1)
- pres — atmospheric pressure (Pa)
- hgt — geopotential height (m)
- ugrd — zonal wind (m s-1)
- vgrd — meridional wind (m s-1)
- sh — specific humidity (kgH2O kgAir-1)
- tmp — air temperature (K)
met_data <- as.data.table(read.csv(file.path(BASE_DIR, 'A.inputs', 'monthly_mean_met.csv')))
met_data$date <- ymd(paste(met_data$year, met_data$month, '01', sep = '/'))
long_met_data <- melt(met_data, measure.vars = c("nbdsf", "nddsf", "vbdsf", "vddsf",
"prate", "dlwrf", "pres", "hgt", "ugrd",
"vgrd", "sh", "tmp"),
variable.name = 'variable', value.name = 'value')
long_met_data <- as.data.table(long_met_data[, c("date", "variable", "value", "year")])
var_info <- data.table(variable = c('dlwrf', 'nbdsf', 'nddsf', 'vbdsf',
'vddsf', 'prate', 'pres', 'hgt',
'ugrd', 'vgrd', 'sh', 'tmp'),
description = c('downward long wave radiation',
'near infrared beam downward solar radiation',
'near IR diffuse downward solar radiation',
'visible beam downward solar radiation',
'visible diffuse downward solar radiation',
'precipitation rate',
'atmospheric pressure',
'geopotential height',
'zonal wind',
'meridional wind',
'specific humidity',
'air temperature'),
units = c('W m-2', 'W m-2', 'W m-2', 'W m-2',
'W m-2', 'kgH2O m-2 s-1', 'Pa', 'm',
'm s-1', 'm s-', 'kgH2O kgAir-1', 'K'))
long_met_data <- long_met_data[var_info, on = 'variable']
long_met_data <- long_met_data[variable != 'hgt', ] # exclude the geo spatial height on cause it doesn't
annual_data <- long_met_data[ , list('value' = mean(value), 'min' = min(value), 'max' = max(value)),
by = list(year, variable)]
ADD_BACKGROUND(plot = ggplot(data = annual_data)) +
geom_ribbon(aes(year, ymin = min, ymax = max), fill = 'grey') +
geom_line(aes(year, min), color = 'grey') +
geom_line(aes(year, max), color = 'grey') +
geom_line(aes(year, value)) +
facet_wrap('variable', scales = 'free') +
labs(y = NULL, title = 'Annual met data with annual max and min')

Control Results
The control, baseline, or 0 harvest ED results.
# Process the data to plot, the annual values.
exp_object$NPP[scn == 'harvest 0', ] %>%
.[ , value := sum(value), by = c('year', 'variable', 'unit', 'scn')] %>%
.[ , list(year, variable, unit, scn, value)] %>%
unique() ->
NPP_to_plot
exp_object$LAI[scn == 'harvest 0', ] %>%
.[ , value := sum(value), by = c('datetime', 'variable', 'unit', 'scn')] %>%
.[ , list(datetime, variable, unit, scn, value)] %>%
unique() ->
LAI_to_plot
exp_object$NEP[scn == 'harvest 0', ] %>%
.[ , value := sum(value), by = c('year', 'variable', 'unit', 'scn')] %>%
.[ , list(year, variable, unit, scn, value)] %>%
unique() ->
NEP_to_plot
exp_object$ABG[scn == 'harvest 0', ] %>%
.[ , value := sum(value), by = c('year', 'variable', 'unit', 'scn')] %>%
.[ , list(year, variable, unit, scn, value)] %>%
unique() ->
ABG_to_plot
exp_object$GPP[scn == "harvest 0", ] %>%
.[ , value := sum(value), by = c('year', 'variable', 'unit', 'scn')] %>%
.[ , list(year, variable, unit, scn, value)] %>%
unique() ->
GPP_to_plot
ADD_BACKGROUND(plot = ggplot(data = NPP_to_plot)) +
geom_line(aes(year, value), size = 1) +
THEME +
labs(title ='NPP',
x = 'Year',
y = unique(exp_object$NPP[scn == 'harvest 0', ][['unit']]), caption = NULL) ->
NPP_plot
ADD_BACKGROUND(plot = ggplot(data = LAI_to_plot)) +
geom_point(aes(datetime, value)) +
THEME +
labs(title ='LAI',
x = 'Year',
y = unique(exp_object$LAI[scn == 'harvest 0', ][['unit']]), caption = NULL, size = 0.01) ->
LAI_plot
ADD_BACKGROUND(ggplot(NEP_to_plot)) +
geom_line(aes(year, value), size = 1) +
THEME +
labs(title ='NEP',
x = 'Year',
y = unique(exp_object$NEP[scn == 'harvest 0', ][['unit']]), caption = NULL) ->
NEP_plot
ADD_BACKGROUND(ggplot(ABG_to_plot)) +
geom_line(aes(year, value), size = 1) +
THEME +
labs(title ='ABG',
x = 'Year',
y = unique(exp_object$ABG[scn == 'harvest 0', ][['unit']]), caption = NULL) ->
ABG_plot
ADD_BACKGROUND(ggplot(GPP_to_plot)) +
geom_point(aes(year, value), size = 1) +
THEME +
labs(title = 'GPP',
x = 'Year',
y = 'kg/m2/yr', caption = NULL) ->
GPP_plot
plot_grid(ABG_plot, NPP_plot, NEP_plot, LAI_plot, GPP_plot)

Experiment 1
Near bare ground runs starting in 1900 until 2030. The 0, 45, 65, 85 disturbance severity treatments are applied in late May 2018.
Above Ground Biomass
exp_object$ABG$datetime <- date(exp_object$ABG$datetime)
data <- exp_object$ABG[ , value := sum(value),
by = c("datetime", "scn", "unit", "year", "severity")]
ggplot(data = data) +
ADD_DISTURBANCE_LINE_MONTH +
geom_line(aes(datetime, value, color = severity,
group = interaction(scn, pft_name)),
size = 1.5) +
THEME +
ADD_COLORS +
labs(x = 'Year', y = unique(exp_object$ABG$unit), title = 'ABG')

GPP
GPP <- exp_object$GPP
GPP <- dplyr::bind_rows(add_disturbance_severity(list(GPP)))
GPP$datetime <- date(GPP$datetime)
GPP$PFT <- as.character(GPP$PFT)
GPP <- GPP[year %in% 2000:2030, ]
# Add the cohort labels to the data
split(GPP, interaction(GPP$datetime, GPP$severity, GPP$PFT), drop = TRUE) %>%
lapply(function(x){
x$cohort <- LETTERS[1:nrow(x)]
return(x)
}) %>%
rlist::list.rbind() ->
GPP_cohort
to_plot <- GPP_cohort[year %in% 2018:2020, ]
to_plot$value <- to_plot$value / 12
to_plot %>%
ggplot(aes(datetime, value, group = interaction(cohort, severity), color = severity)) +
ADD_DISTURBANCE_LINE_MONTH +
geom_line(size = 2) +
facet_grid(. ~ pft_name) +
THEME +
ADD_COLORS +
labs(title = 'GPP per Cohort',
y = 'kgC/m2/month',
x = 'Date')

NPP
ggplot(exp_object$NPP[year %in% 2010:2030, ]) +
ADD_DISTURBANCE_LINE_ANNUAL +
geom_line(aes(year, value, color = severity,
group = interaction(scn, pft_name)), size = 1.5) +
THEME +
coord_cartesian(xlim = c(2010, 2025)) +
labs(x = 'Year', y = unique(exp_object$NPP$unit), title = 'Annual NPP') +
ADD_COLORS

h0 <- as.data.table(h0_object$df_cohort[[1]])[ ,list(datetime, MMEAN_NPP_CO, PFT, DBH, NPLANT)]
h45 <- as.data.table(h45_object$df_cohort[[1]])[ ,list(datetime, MMEAN_NPP_CO, PFT, DBH, NPLANT)]
h65 <- as.data.table(h65_object$df_cohort[[1]])[ ,list(datetime, MMEAN_NPP_CO, PFT, DBH, NPLANT)]
h85 <- as.data.table(h85_object$df_cohort[[1]])[ ,list(datetime, MMEAN_NPP_CO, PFT, DBH, NPLANT)]
h0$severity <- '0'
h45$severity <- '45'
h65$severity <- '65'
h85$severity <- '85'
NPP <- rbind(h0, h45, h65, h85)
# Convert the NPP units from per plant to unit area
NPP$value <- NPP$MMEAN_NPP_CO * NPP$NPLANT
NPP$unit <- unique(exp_object$NPP$unit)
NPP <- NPP[, c("datetime", "PFT", "severity", "value", 'unit')]
NPP$year <- lubridate::year(NPP$datetime)
NPP$datetime <- date(NPP$datetime)
monthly_NPP <- NPP
NPP_monthly <- monthly_NPP[, value := sum(value), by = c("datetime", "severity", "unit", "year")]
NPP_monthly$value <- NPP_monthly$value / 12
NPP_monthly %>%
.[year %in% 2018:2020] %>%
ggplot(aes(datetime, value, color = severity)) +
ADD_DISTURBANCE_LINE_MONTH +
ADD_COLORS +
geom_line(size = 1.5) +
THEME +
labs(title = 'Monthly NPP', y = 'kgC/m2/month', x = 'Time')

NEP
exp_object$NEP %>%
dplyr::filter(year >= 2010 & year <= 2021) %>%
ggplot() +
geom_vline(xintercept = 2019, color = 'grey', size = 1.5) +
geom_line(aes(year, value, color = severity), size = 1.5) +
THEME +
ADD_COLORS +
labs(x = 'Year', y = unique(exp_object$NEP$unit), title = 'Annual NEP')

h0 <- as.data.table(h0_object$df_scalar[[1]])[ ,list(datetime, MMEAN_NEP_PY)]
h45 <- as.data.table(h45_object$df_scalar[[1]])[ ,list(datetime, MMEAN_NEP_PY)]
h65 <- as.data.table(h65_object$df_scalar[[1]])[ ,list(datetime, MMEAN_NEP_PY)]
h85 <- as.data.table(h85_object$df_scalar[[1]])[ ,list(datetime, MMEAN_NEP_PY)]
h0$severity <- '0'
h45$severity <- '45'
h65$severity <- '65'
h85$severity <- '85'
NEP <- rbind(h0, h45, h65, h85)
NEP$unit <- unique(exp_object$NEP$unit)
NEP <- NEP[, c("datetime", "severity", "value" = "MMEAN_NEP_PY")]
names(NEP) <- c("datetime", "severity", "value")
NEP$year <- lubridate::year(NEP$datetime)
NEP$datetime <- date(NEP$datetime)
NEP %>%
dplyr::filter(year >= 2018 & year <= 2020) %>%
dplyr::mutate(value = value / 12,
units = 'kg/m2/month') %>%
ggplot() +
ADD_DISTURBANCE_LINE_MONTH +
geom_line(aes(datetime, value, color = severity), size = 1.5) +
THEME +
ADD_COLORS +
labs(x = 'Year', y ='kg/m2/month', title = 'Monthly NEP')

Heterotrophic Respiration
h0 <- as.data.table(h0_object$df_scalar[[1]])[ ,list(datetime, MMEAN_RH_PY)]
h45 <- as.data.table(h45_object$df_scalar[[1]])[ ,list(datetime, MMEAN_RH_PY)]
h65 <- as.data.table(h65_object$df_scalar[[1]])[ ,list(datetime, MMEAN_RH_PY)]
h85 <- as.data.table(h85_object$df_scalar[[1]])[ ,list(datetime, MMEAN_RH_PY)]
h0$severity <- '0'
h45$severity <- '45'
h65$severity <- '65'
h85$severity <- '85'
RH <- rbind(h0, h45, h65, h85)
RH$datetime <- as_date(RH$datetime )
units <- 'kg/m2/month'
RH$MMEAN_RH_PY <- RH$MMEAN_RH_PY / 12
RH[datetime >= ymd('2018-06-01') & datetime <= ymd('2021-01-01'), ] %>%
ggplot(aes(datetime, MMEAN_RH_PY, color = severity)) +
ADD_DISTURBANCE_LINE_MONTH +
geom_line(size = 1.5) +
THEME +
labs(title = 'Monthly Heterotrophic Respiration',
y = units,
x = 'Date Time') +
ADD_COLORS

LAI
exp_object$LAI$year <- year(exp_object$LAI$datetime)
exp_object$LAI %>%
dplyr::filter(year >= 2018 & year <= 2020) %>%
dplyr::filter(pft_name == 'Temperate broadleaf, early successional') %>%
ggplot() +
ADD_DISTURBANCE_LINE_MONTH +
geom_line(aes(datetime, value, color = severity), size = 1.5) +
ADD_COLORS +
THEME +
labs(x = 'Year', y = unique(exp_object$LAI$unit), title = 'Monthly LAI') +
facet_wrap('pft_name', ncol = 1)

Carbon Cycling Resistance
Carbon Cycling Resistance
\[r = \ln \left( {\frac{{F_{{\text{dist}}} }}{{F_{{\text{cont}}} }}} \right)\] Equation 1 from Gough 2020.
exp_object$NPP[year %in% 2018:2030, ] %>%
.[, list(pft_name, year, variable, unit, value, severity)] %>%
# Make the table wide by disturbance severity treatment.
dcast(data = ., pft_name + year + variable + unit ~ severity) %>%
# Now gather all of the distubrance treatments into a single column so that the
# control values are recorded in their own column.
melt(data = ., id.vars = c("pft_name", "year", "variable", "unit", "0"),
measure.vars = c('45', '65', '85'), variable.name = 'severity',
value.name = 'treatment_value') %>%
# Rename the columns
.[ , list(pft_name, year, variable, unit, control = `0`, severity, dist = treatment_value)] %>%
# Now calculate r
.[ , r := log(dist/control)] ->
NPP_r
NPP_r %>%
ggplot(aes(year, r, color = severity)) +
geom_line(size = 1.5) +
ADD_COLORS +
THEME +
labs(title = 'NPP Resistance Values',
y = expression('r'[npp]),
x = 'Year')

LS0tCnRpdGxlOiAiMjAyMC8xMi8wOCBGb1JURSBFRCBEaXN0dXJiYW5jZSBNZWV0aW5nIDEiCmF1dGhvcjogIkthbHluIERvcmhlaW0iCmRhdGU6ICJgciBmb3JtYXQoU3lzLnRpbWUoKSwgJyVkICVCLCAlWScpYCIKb3V0cHV0OiAKICBodG1sX25vdGVib29rOiAKICAgIHRvYzogdHJ1ZQogICAgdG9jX2Zsb2F0OgogICAgICB0b2NfY29sbGFwc2VkOiB0cnVlCiAgICB0b2NfZGVwdGg6IDMKLS0tCgoKIyBPYmplY3RpdmUgIAoKQmVuIGFuZCBJIHdvdWxkIGxpa2UgdG8gdGFsayBvdmVyIHNvbWUgb2Ygb3VyIHJlc3VsdHMgZnJvbSBFRCwgc3RhcnQgZGlzY3Vzc2luZyBhbmQgdGhpbmtpbmcgYWJvdXQgYSBwYXBlciB0aGF0IHVzZXMgdGhlIG1vZGVsIGFuZCBmaWVsZCByZXN1bHRzLCB3ZSBoYXZlIHN0YXJ0ZWQgb3V0bGluaW5nIGEgbWFudXNjcmlwdCBbaGVyZV0oaHR0cHM6Ly9kb2NzLmdvb2dsZS5jb20vZG9jdW1lbnQvZC8xQm12b0FXdlJNZ3hLU1lRMEQzczBRNFc0UDNXWEZucksxVzZ5MGtMQmtSYy9lZGl0KS4KCgpgYGB7ciBzZXR1cCwgaW5jbHVkZT1GQUxTRSwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KIyBUaGUgZGVmYXVsdHMgZm9yIHRoZSBjaHVua3MKa25pdHI6Om9wdHNfY2h1bmskc2V0KGVjaG8gPSBUUlVFLCBmaWcud2lkdGggPSA2LCBmaWcuaGVpZ2h0ID0gNikKCiMgTG9hZCB0aGUgcmVxdWlyZWQgbGlicyAKbGlicmFyeShnZ3Bsb3QyKQpsaWJyYXJ5KG1hZ3JpdHRyKQpsaWJyYXJ5KGRhdGEudGFibGUpCmxpYnJhcnkoY293cGxvdCkKbGlicmFyeShsdWJyaWRhdGUpCmxpYnJhcnkocHVycnIpCmxpYnJhcnkoZm9ydGVkYXRhKQoKQkFTRV9ESVIgPC0gaGVyZTo6aGVyZSgpClRIRU1FICAgIDwtIHRoZW1lX2J3KGJhc2Vfc2l6ZSA9IDIwKQoKQUxQSEEgPC0gMC4wNQoKIyBGdW5jdGlvbiB0aGF0IGFkZHMgdGhlIGNvbG9yZWQgYmFja2dyb3VuZCB0byBhIHBsb3QgdGhhdCB1c2VzIG1vbnRobHkgZGF0YS4gCiMgQXJncwojICAgcGxvdDogYSBnZ3Bsb3Qgb2JqZWN0IGNvbnRhaW5pbmcgbW9udGhseSBkYXRhIAojIFJldHVybnM6IGEgZ2dwbG90IG9iamVjdCB3aXRoIHRoZSBjb2xvciBjb2RlZCBiYWNrZ3JvdW5kCk1PTlRITFlfQkFDS0dST1VORCA8LSBmdW5jdGlvbihwbG90KXsKICAKICAjIFRoZSBkaWZmZXJlbnQgYmFja2dyb3VuZCBjb2xvcnMgZGVwZW5kaW5nIG9uIHdoYXQgbWV0ZXJvbG9naWNhbCBkYXRhIGlzIGJlaW5nIHVzZWQuIAogIEJDS19HUk5EMSA8LSAnI2RjZmZjYycKICBCQ0tfR1JORDIgPC0gJyM5ZmRmY2QnCiAgQkNLX0dSTkQzIDwtICcjYmFhYmRhJwogIAogIHBsb3QgKyAKICAgIGdlb21fcmVjdChhZXMoeG1pbj15bWQoJzE5MDAtMDEtMDEnKSwgeG1heCA9IHltZCgnMTk3OS0xMi0wMScpLAogICAgICAgICAgICAgICAgICB5bWluID0gLUluZiwgeW1heCA9IEluZiksIGZpbGwgPSBCQ0tfR1JORDEsIGFscGhhID0gQUxQSEEpICsKICAgIGdlb21fcmVjdChhZXMoeG1pbj15bWQoJzE5ODAtMDEtMDEnKSwgeG1heCA9IHltZCgnMjAxNS0xMi0wMScpLAogICAgICAgICAgICAgICAgICB5bWluID0gLUluZiwgeW1heCA9IEluZiksIGZpbGwgPSBCQ0tfR1JORDIsIGFscGhhID0gQUxQSEEpICsKICAgIGdlb21fcmVjdChhZXMoeG1pbj15bWQoJzIwMTYtMDEtMDEnKSwgeG1heCA9IHltZCgnMjAyOS0wMS0wMScpLAogICAgICAgICAgICAgICAgICB5bWluID0gLUluZiwgeW1heCA9IEluZiksIGZpbGwgPSBCQ0tfR1JORDMsIGFscGhhID0gQUxQSEEpICsgCiAgICBsYWJzKGNhcHRpb24gPSAnY29sb3JlZCBiYWNrZ3JvdW5kOiBsb29wZWQgb3ZlciAxOTc5IC0gMTk3OCwgb2JzLiAxOTc5IC0gMjAxNiwgYXZnIDIwMDggLSAyMDE4JykgCn0KCiMgRnVuY3Rpb24gdGhhdCBhZGRzIHRoZSBjb2xvcmVkIGJhY2tncm91bmQgdG8gYSBwbG90IHRoYXQgdXNlcyBhbm51YWwgZGF0YS4gCiMgQXJncwojICAgcGxvdDogYSBnZ3Bsb3Qgb2JqZWN0IGNvbnRhaW5pbmcgbW9udGhseSBkYXRhIAojIFJldHVybnM6IGEgZ2dwbG90IG9iamVjdCB3aXRoIHRoZSBjb2xvciBjb2RlZCBiYWNrZ3JvdW5kCkFOTlVBTF9CQUNLR1JPVU5EIDwtIGZ1bmN0aW9uKHBsb3QpewogIAogICAgIyBUaGUgZGlmZmVyZW50IGJhY2tncm91bmQgY29sb3JzIGRlcGVuZGluZyBvbiB3aGF0IG1ldGVyb2xvZ2ljYWwgZGF0YSBpcyBiZWluZyB1c2VkLiAKICBCQ0tfR1JORDEgPC0gJyNkY2ZmY2MnCiAgQkNLX0dSTkQyIDwtICcjOWZkZmNkJwogIEJDS19HUk5EMyA8LSAnI2JhYWJkYScKICAKICBwbG90ICsgCiAgICBnZW9tX3JlY3QoYWVzKHhtaW49MTkwMCwgeG1heCA9IDE5NzksCiAgICAgICAgICAgICAgICAgIHltaW4gPSAtSW5mLCB5bWF4ID0gSW5mKSwgZmlsbCA9IEJDS19HUk5EMSwgYWxwaGEgPSBBTFBIQSkgKwogICAgZ2VvbV9yZWN0KGFlcyh4bWluPTE5NzksIHhtYXggPSAyMDE1LAogICAgICAgICAgICAgICAgICB5bWluID0gLUluZiwgeW1heCA9IEluZiksIGZpbGwgPSBCQ0tfR1JORDIsIGFscGhhID0gQUxQSEEpICsKICAgIGdlb21fcmVjdChhZXMoeG1pbj0yMDE1LCB4bWF4ID0gMjAyOSwKICAgICAgICAgICAgICAgICAgeW1pbiA9IC1JbmYsIHltYXggPSBJbmYpLCBmaWxsID0gQkNLX0dSTkQzLCBhbHBoYSA9IEFMUEhBKSArIAogICAgbGFicyhjYXB0aW9uID0gJ2NvbG9yZWQgYmFja2dyb3VuZDogbG9vcGVkIG92ZXIgMTk3OSAtIDE5NzgsIG9icy4gMTk3OSAtIDIwMTYsIGF2ZyAyMDA4IC0gMjAxOCcpCn0KCiMgRnVuY3Rpb24gdGhhdCBhZGRzIGEgY29sb3IgY29kZGVkIGJhY2tncm91bmQgYmFzZWQKIyBBcmdzOgojICAgcGxvdDogYSBnZ3Bsb3Qgb2JqZWN0IG9mIG1vbnRobHkgb3IgYW5udWFsIG1ldCBkYXRhIAojIFJldHVybnM6IGEgZ2dwbG90IG9iamVjdCB3aXRoIHRoZSBjb2xvciBjb2RlZCBiYWNrZ3JvdW5kCkFERF9CQUNLR1JPVU5EIDwtIGZ1bmN0aW9uKHBsb3QpewogIAogIGlmKGFueShjKCdkYXRlJywgJ2RhdGV0aW1lJykgJWluJSBuYW1lcyhwbG90JGRhdGEpKSl7CiAgICBwIDwtIE1PTlRITFlfQkFDS0dST1VORChwbG90KQogIH0gZWxzZSBpZiAoJ3llYXInICVpbiUgbmFtZXMocGxvdCRkYXRhKSl7CiAgICBwIDwtIEFOTlVBTF9CQUNLR1JPVU5EKHBsb3QpCiAgfQogIHJldHVybihwKQp9CgojIEFkZCBhIGxpbmUgdG8gaW5kaWNhdGUgd2hlbiB0aGUgZGlzdHVyYmFuY2UgdGFrZXMgcGxhY2UKQUREX0RJU1RVUkJBTkNFX0xJTkVfTU9OVEggIDwtIGdlb21fdmxpbmUoeGludGVyY2VwdCA9IGRhdGUoJzIwMTktMDUtMDEnKSwgY29sb3IgPSAnZ3JleScsIHNpemUgPSAyKQpBRERfRElTVFVSQkFOQ0VfTElORV9BTk5VQUwgPC0gZ2VvbV92bGluZSh4aW50ZXJjZXB0ID0gMjAxOSwgY29sb3IgPSAnZ3JleScsIHNpemUgPSAyKQoKIyBBZGQgdGhlIHRyZWF0bWVudCBjb2xvcnMgYmFzZWQgb24gdGhlIGNvbG9yIHBhbGxhdGUgZnJvbSBmb3J0ZWRhdGEKRElTVFVSQkFOQ0VfQ09MT1JTIDwtIGMoIjAiID0gIiMwMDAwMDAiLCAiNDUiID0gIiMwMDlFNzMiLCAiNjUiID0gIiMwMDcyQjIiLCAiODUiID0gIiNENTVFMDAiKQpBRERfQ09MT1JTIDwtIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSBESVNUVVJCQU5DRV9DT0xPUlMpIAoKCiMgSW1wb3J0IHRoZSBFRCByZXN1bHRzIAojIE5vdGUgdGhhdCB0aGlzIGlzIHRoZSBvYmplY3QgY3JlYXRlZCB3aXRoIHRoZSBkcmFrZSBmcmFtZSB3b3JrLCAKIyB0aGVyZSBzaG91bGQgYmUgc29tZSBiZXR0ZXIgd2F5IHRvIHRyaWdnZXIgdGhpcy4KZXhwX29iamVjdCA8LSByZWFkUkRTKGZpbGUucGF0aChCQVNFX0RJUiwgJ0VELW91dHB1dHMnLCAiZXhwLTEucmRzIikpCmV4cF9vYmplY3QgPC0gbWFwKGV4cF9vYmplY3QsIGZ1bmN0aW9uKHgpeyB4W3llYXIgPCAyMDMwLCBdIH0pIAoKIyBVcGRhdGUgdGhlIGRhdGEgZm9yIHdpdGggdGhlIGRpc3R1cmJhbmNlIHNldmVyaXR5CmFkZF9kaXN0dXJiYW5jZV9zZXZlcml0eSA8LSBmdW5jdGlvbihsaXN0KXsKICB5IDwtIG1hcChsaXN0LCBmdW5jdGlvbih4KXsKICAgIHhbZGF0YS50YWJsZShzY24gPSBjKCJoYXJ2ZXN0IDAiLCAiaGFydmVzdCA0NSIsICJoYXJ2ZXN0IDY1IiwgImhhcnZlc3QgODUiKSwgCiAgICAgICAgICAgICAgICAgc2V2ZXJpdHkgPSBjKCIwIiwgIjQ1IiwgIjY1IiwgIjg1IikpLCBvbiA9ICdzY24nXSAKICB9KQogIHJldHVybih5KQp9CgpleHBfb2JqZWN0IDwtIGFkZF9kaXN0dXJiYW5jZV9zZXZlcml0eShleHBfb2JqZWN0KQoKCgojICBSZWFkIGluIHRoZSBvYmplY3RzIGluY2FzZSB3ZSB3YW50IHRvIHdvcmsgd2l0aCBkYXRhIHRoYXQgaGFzIGJlZW4gYWRkZWQgdG8gdGhlIGRyYWtlIGRhdGEgcHJvY2Vzc2luZyBwaXBlbGluZS4gCmgwX29iamVjdCAgPC0gcmVhZFJEUyhmaWxlLnBhdGgoQkFTRV9ESVIsICdFRC1vdXRwdXRzJywgJ2V4cC0xJywgJ2hhcnZlc3RfMF9hYm92ZS5yZHMnKSkKaDQ1X29iamVjdCA8LSByZWFkUkRTKGZpbGUucGF0aChCQVNFX0RJUiwgJ0VELW91dHB1dHMnLCAnZXhwLTEnLCAnaGFydmVzdF80NV9hYm92ZS5yZHMnKSkKaDY1X29iamVjdCA8LSByZWFkUkRTKGZpbGUucGF0aChCQVNFX0RJUiwgJ0VELW91dHB1dHMnLCAnZXhwLTEnLCAnaGFydmVzdF82NV9hYm92ZS5yZHMnKSkKaDg1X29iamVjdCA8LSByZWFkUkRTKGZpbGUucGF0aChCQVNFX0RJUiwgJ0VELW91dHB1dHMnLCAnZXhwLTEnLCAnaGFydmVzdF84NV9hYm92ZS5yZHMnKSkKYGBgCgoKCiMgTWV0IElucHV0cyAKCj4gCiogZGx3cmYg4oCUIGRvd253YXJkIGxvbmcgd2F2ZSByYWRpYXRpb24gKFcgbS0yKQoqIG5iZHNmIOKAlCBuZWFyIGluZnJhcmVkIGJlYW0gZG93bndhcmQgc29sYXIgcmFkaWF0aW9uIChXIG0tMikKKiBuZGRzZiDigJQgbmVhciBJUiBkaWZmdXNlIGRvd253YXJkIHNvbGFyIHJhZGlhdGlvbiAoVyBtLTIpCiogdmJkc2Yg4oCUIHZpc2libGUgYmVhbSBkb3dud2FyZCBzb2xhciByYWRpYXRpb24gKFcgbS0yKQoqIHZkZHNmIOKAlCB2aXNpYmxlIGRpZmZ1c2UgZG93bndhcmQgc29sYXIgcmFkaWF0aW9uIChXIG0tMikKKiBwcmF0ZSDigJQgcHJlY2lwaXRhdGlvbiByYXRlIChrZ0gyTyBtLTIgcy0xKQoqIHByZXMg4oCUIGF0bW9zcGhlcmljIHByZXNzdXJlIChQYSkKKiBoZ3Qg4oCUIGdlb3BvdGVudGlhbCBoZWlnaHQgKG0pCiogdWdyZCDigJQgem9uYWwgd2luZCAobSBzLTEpCiogdmdyZCDigJQgbWVyaWRpb25hbCB3aW5kIChtIHMtMSkKKiBzaCDigJQgc3BlY2lmaWMgaHVtaWRpdHkgKGtnSDJPIGtnQWlyLTEpCiogdG1wIOKAlCBhaXIgdGVtcGVyYXR1cmUgKEspCgpgYGB7ciwgZmlnLndpZHRoID0gMTIsIGZpZy5oZWlnaHQgPSA2LCB3YXJuaW5nPUZBTFNFfQptZXRfZGF0YSA8LSBhcy5kYXRhLnRhYmxlKHJlYWQuY3N2KGZpbGUucGF0aChCQVNFX0RJUiwgJ0EuaW5wdXRzJywgJ21vbnRobHlfbWVhbl9tZXQuY3N2JykpKQptZXRfZGF0YSRkYXRlIDwtIHltZChwYXN0ZShtZXRfZGF0YSR5ZWFyLCBtZXRfZGF0YSRtb250aCwgJzAxJywgc2VwID0gJy8nKSkKCmxvbmdfbWV0X2RhdGEgPC0gbWVsdChtZXRfZGF0YSwgbWVhc3VyZS52YXJzID0gYygibmJkc2YiLCAibmRkc2YiLCAidmJkc2YiLCAidmRkc2YiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgInByYXRlIiwgImRsd3JmIiwgInByZXMiLCAiaGd0IiwgInVncmQiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJ2Z3JkIiwgInNoIiwgInRtcCIpLAogICAgICAgICAgICAgICAgICAgICAgdmFyaWFibGUubmFtZSA9ICd2YXJpYWJsZScsIHZhbHVlLm5hbWUgPSAndmFsdWUnKQpsb25nX21ldF9kYXRhIDwtIGFzLmRhdGEudGFibGUobG9uZ19tZXRfZGF0YVssIGMoImRhdGUiLCAidmFyaWFibGUiLCAidmFsdWUiLCAieWVhciIpXSkKCnZhcl9pbmZvIDwtIGRhdGEudGFibGUodmFyaWFibGUgPSBjKCdkbHdyZicsICduYmRzZicsICduZGRzZicsICd2YmRzZicsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICd2ZGRzZicsICdwcmF0ZScsICdwcmVzJywgJ2hndCcsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAndWdyZCcsICd2Z3JkJywgJ3NoJywgJ3RtcCcpLCAKICAgICAgICAgICAgICAgICAgICAgICBkZXNjcmlwdGlvbiA9IGMoJ2Rvd253YXJkIGxvbmcgd2F2ZSByYWRpYXRpb24nLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJ25lYXIgaW5mcmFyZWQgYmVhbSBkb3dud2FyZCBzb2xhciByYWRpYXRpb24nLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJ25lYXIgSVIgZGlmZnVzZSBkb3dud2FyZCBzb2xhciByYWRpYXRpb24nLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJ3Zpc2libGUgYmVhbSBkb3dud2FyZCBzb2xhciByYWRpYXRpb24nLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAndmlzaWJsZSBkaWZmdXNlIGRvd253YXJkIHNvbGFyIHJhZGlhdGlvbicsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAncHJlY2lwaXRhdGlvbiByYXRlJywgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICdhdG1vc3BoZXJpYyBwcmVzc3VyZScsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnZ2VvcG90ZW50aWFsIGhlaWdodCcsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnem9uYWwgd2luZCcsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICdtZXJpZGlvbmFsIHdpbmQnLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJ3NwZWNpZmljIGh1bWlkaXR5JywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJ2FpciB0ZW1wZXJhdHVyZScpLCAgCiAgICAgICAgICAgICAgICAgICAgICAgdW5pdHMgPSBjKCdXIG0tMicsICdXIG0tMicsICdXIG0tMicsICdXIG0tMicsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICdXIG0tMicsICdrZ0gyTyBtLTIgcy0xJywgJ1BhJywgJ20nLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnbSBzLTEnLCAnbSBzLScsICdrZ0gyTyBrZ0Fpci0xJywgJ0snKSkKbG9uZ19tZXRfZGF0YSA8LSBsb25nX21ldF9kYXRhW3Zhcl9pbmZvLCBvbiA9ICd2YXJpYWJsZSddCmxvbmdfbWV0X2RhdGEgPC0gbG9uZ19tZXRfZGF0YVt2YXJpYWJsZSAhPSAnaGd0JywgXSAjIGV4Y2x1ZGUgdGhlIGdlbyBzcGF0aWFsIGhlaWdodCBvbiBjYXVzZSBpdCBkb2Vzbid0IApgYGAKCgpgYGB7cn0KYW5udWFsX2RhdGEgPC0gbG9uZ19tZXRfZGF0YVsgLCBsaXN0KCd2YWx1ZScgPSBtZWFuKHZhbHVlKSwgJ21pbicgPSBtaW4odmFsdWUpLCAnbWF4JyA9IG1heCh2YWx1ZSkpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBieSA9IGxpc3QoeWVhciwgdmFyaWFibGUpXQoKQUREX0JBQ0tHUk9VTkQocGxvdCA9IGdncGxvdChkYXRhID0gYW5udWFsX2RhdGEpKSArCiAgZ2VvbV9yaWJib24oYWVzKHllYXIsIHltaW4gPSBtaW4sIHltYXggPSBtYXgpLCBmaWxsID0gJ2dyZXknKSArIAogIGdlb21fbGluZShhZXMoeWVhciwgbWluKSwgY29sb3IgPSAnZ3JleScpICsgCiAgZ2VvbV9saW5lKGFlcyh5ZWFyLCBtYXgpLCBjb2xvciA9ICdncmV5JykgKyAKICBnZW9tX2xpbmUoYWVzKHllYXIsIHZhbHVlKSkgKwogIGZhY2V0X3dyYXAoJ3ZhcmlhYmxlJywgc2NhbGVzID0gJ2ZyZWUnKSArIAogIGxhYnMoeSA9IE5VTEwsIHRpdGxlID0gJ0FubnVhbCBtZXQgZGF0YSB3aXRoIGFubnVhbCBtYXggYW5kIG1pbicpCmBgYAoKCgoKIyBDb250cm9sIFJlc3VsdHMKClRoZSBjb250cm9sLCBiYXNlbGluZSwgb3IgMCBoYXJ2ZXN0IEVEIHJlc3VsdHMuIAoKYGBge3IsIGZpZy53aWR0aD04LCBmaWcuaGVpZ2h0PTZ9CiMgUHJvY2VzcyB0aGUgZGF0YSB0byBwbG90LCB0aGUgYW5udWFsIHZhbHVlcy4gCmV4cF9vYmplY3QkTlBQW3NjbiA9PSAnaGFydmVzdCAwJywgXSAlPiUgIAogICAgLlsgICwgdmFsdWUgOj0gc3VtKHZhbHVlKSwgYnkgPSBjKCd5ZWFyJywgJ3ZhcmlhYmxlJywgJ3VuaXQnLCAnc2NuJyldICU+JSAKICAgIC5bICwgbGlzdCh5ZWFyLCB2YXJpYWJsZSwgdW5pdCwgc2NuLCB2YWx1ZSldICU+JSAKICB1bmlxdWUoKSAtPiAKICBOUFBfdG9fcGxvdAoKZXhwX29iamVjdCRMQUlbc2NuID09ICdoYXJ2ZXN0IDAnLCBdICU+JQogIC5bICAsIHZhbHVlIDo9IHN1bSh2YWx1ZSksIGJ5ID0gYygnZGF0ZXRpbWUnLCAndmFyaWFibGUnLCAndW5pdCcsICdzY24nKV0gJT4lIAogIC5bICwgbGlzdChkYXRldGltZSwgdmFyaWFibGUsIHVuaXQsIHNjbiwgdmFsdWUpXSAlPiUgIAogIHVuaXF1ZSgpIC0+IAogIExBSV90b19wbG90CgpleHBfb2JqZWN0JE5FUFtzY24gPT0gJ2hhcnZlc3QgMCcsIF0gJT4lICAKICAuWyAgLCB2YWx1ZSA6PSBzdW0odmFsdWUpLCBieSA9IGMoJ3llYXInLCAndmFyaWFibGUnLCAndW5pdCcsICdzY24nKV0gJT4lIAogIC5bICwgbGlzdCh5ZWFyLCB2YXJpYWJsZSwgdW5pdCwgc2NuLCB2YWx1ZSldICU+JSAgCiAgdW5pcXVlKCkgLT4gCiAgTkVQX3RvX3Bsb3QKCmV4cF9vYmplY3QkQUJHW3NjbiA9PSAnaGFydmVzdCAwJywgXSAlPiUgIAogIC5bICAsIHZhbHVlIDo9IHN1bSh2YWx1ZSksIGJ5ID0gYygneWVhcicsICd2YXJpYWJsZScsICd1bml0JywgJ3NjbicpXSAlPiUgCiAgLlsgLCBsaXN0KHllYXIsIHZhcmlhYmxlLCB1bml0LCBzY24sIHZhbHVlKV0gJT4lICAKICB1bmlxdWUoKSAtPiAKICBBQkdfdG9fcGxvdAoKZXhwX29iamVjdCRHUFBbc2NuID09ICJoYXJ2ZXN0IDAiLCBdICU+JSAgCiAgLlsgICwgdmFsdWUgOj0gc3VtKHZhbHVlKSwgYnkgPSBjKCd5ZWFyJywgJ3ZhcmlhYmxlJywgJ3VuaXQnLCAnc2NuJyldICU+JSAKICAuWyAsIGxpc3QoeWVhciwgdmFyaWFibGUsIHVuaXQsIHNjbiwgdmFsdWUpXSAlPiUgIAogIHVuaXF1ZSgpIC0+IAogIEdQUF90b19wbG90CgoKQUREX0JBQ0tHUk9VTkQocGxvdCA9IGdncGxvdChkYXRhID0gTlBQX3RvX3Bsb3QpKSArIAogIGdlb21fbGluZShhZXMoeWVhciwgdmFsdWUpLCBzaXplID0gMSkgKwogIFRIRU1FICsKICBsYWJzKHRpdGxlID0nTlBQJywKICAgICAgIHggPSAnWWVhcicsIAogICAgICAgeSA9IHVuaXF1ZShleHBfb2JqZWN0JE5QUFtzY24gPT0gJ2hhcnZlc3QgMCcsIF1bWyd1bml0J11dKSwgY2FwdGlvbiA9IE5VTEwpIC0+IAogIE5QUF9wbG90CgpBRERfQkFDS0dST1VORChwbG90ID0gZ2dwbG90KGRhdGEgPSBMQUlfdG9fcGxvdCkpICsgCiAgZ2VvbV9wb2ludChhZXMoZGF0ZXRpbWUsIHZhbHVlKSkgKyAKICBUSEVNRSArIAogIGxhYnModGl0bGUgPSdMQUknLAogICAgICAgeCA9ICdZZWFyJywgCiAgICAgICB5ID0gdW5pcXVlKGV4cF9vYmplY3QkTEFJW3NjbiA9PSAnaGFydmVzdCAwJywgXVtbJ3VuaXQnXV0pLCBjYXB0aW9uID0gTlVMTCwgc2l6ZSA9IDAuMDEpIC0+IAogIExBSV9wbG90CgpBRERfQkFDS0dST1VORChnZ3Bsb3QoTkVQX3RvX3Bsb3QpKSArIAogIGdlb21fbGluZShhZXMoeWVhciwgdmFsdWUpLCBzaXplID0gMSkgKwogIFRIRU1FICsgCiAgbGFicyh0aXRsZSA9J05FUCcsCiAgICAgICB4ID0gJ1llYXInLCAKICAgICAgIHkgPSB1bmlxdWUoZXhwX29iamVjdCRORVBbc2NuID09ICdoYXJ2ZXN0IDAnLCBdW1sndW5pdCddXSksIGNhcHRpb24gPSBOVUxMKSAtPiAKICBORVBfcGxvdAoKQUREX0JBQ0tHUk9VTkQoZ2dwbG90KEFCR190b19wbG90KSkgKyAKICBnZW9tX2xpbmUoYWVzKHllYXIsIHZhbHVlKSwgc2l6ZSA9IDEpICsgCiAgVEhFTUUgKyAKICBsYWJzKHRpdGxlID0nQUJHJywKICAgICAgIHggPSAnWWVhcicsIAogICAgICAgeSA9IHVuaXF1ZShleHBfb2JqZWN0JEFCR1tzY24gPT0gJ2hhcnZlc3QgMCcsIF1bWyd1bml0J11dKSwgY2FwdGlvbiA9IE5VTEwpIC0+IAogIEFCR19wbG90CgpBRERfQkFDS0dST1VORChnZ3Bsb3QoR1BQX3RvX3Bsb3QpKSArIAogIGdlb21fcG9pbnQoYWVzKHllYXIsIHZhbHVlKSwgc2l6ZSA9IDEpICsgCiAgVEhFTUUgKyAKICBsYWJzKHRpdGxlID0gJ0dQUCcsIAogICAgICAgeCA9ICdZZWFyJywgCiAgICAgICB5ID0gJ2tnL20yL3lyJywgY2FwdGlvbiA9IE5VTEwpIC0+IAogIEdQUF9wbG90CgpwbG90X2dyaWQoQUJHX3Bsb3QsIE5QUF9wbG90LCBORVBfcGxvdCwgTEFJX3Bsb3QsIEdQUF9wbG90KQoKYGBgCgoKCiMgRXhwZXJpbWVudCAxIAoKTmVhciBiYXJlIGdyb3VuZCBydW5zIHN0YXJ0aW5nIGluIDE5MDAgdW50aWwgMjAzMC4gVGhlIDAsIDQ1LCA2NSwgODUgZGlzdHVyYmFuY2Ugc2V2ZXJpdHkgdHJlYXRtZW50cyBhcmUgYXBwbGllZCBpbiBsYXRlIE1heSAyMDE4LgoKIyMgQWJvdmUgR3JvdW5kIEJpb21hc3MKCmBgYHtyLCBmaWcud2lkdGggPSAxMiwgZmlnLmhlaWdodCA9IDZ9CmV4cF9vYmplY3QkQUJHJGRhdGV0aW1lIDwtIGRhdGUoZXhwX29iamVjdCRBQkckZGF0ZXRpbWUpCmRhdGEgPC0gZXhwX29iamVjdCRBQkdbICAsIHZhbHVlIDo9IHN1bSh2YWx1ZSksIAogICAgICAgICAgICAgICAgICAgICAgICAgYnkgPSBjKCJkYXRldGltZSIsICJzY24iLCAidW5pdCIsICJ5ZWFyIiwgInNldmVyaXR5IildIApnZ3Bsb3QoZGF0YSA9IGRhdGEpICsgCiAgQUREX0RJU1RVUkJBTkNFX0xJTkVfTU9OVEggKyAKICBnZW9tX2xpbmUoYWVzKGRhdGV0aW1lLCB2YWx1ZSwgY29sb3IgPSBzZXZlcml0eSwgCiAgICAgICAgICAgICAgICBncm91cCA9IGludGVyYWN0aW9uKHNjbiwgcGZ0X25hbWUpKSwKICAgICAgICAgICAgc2l6ZSA9IDEuNSkgKyAKICBUSEVNRSArIAogIEFERF9DT0xPUlMgKyAKICBsYWJzKHggPSAnWWVhcicsIHkgPSB1bmlxdWUoZXhwX29iamVjdCRBQkckdW5pdCksIHRpdGxlID0gJ0FCRycpIApgYGAKCgojIyBHUFAgCgpgYGB7cn0KR1BQIDwtIGV4cF9vYmplY3QkR1BQCkdQUCA8LSBkcGx5cjo6YmluZF9yb3dzKGFkZF9kaXN0dXJiYW5jZV9zZXZlcml0eShsaXN0KEdQUCkpKQpHUFAkZGF0ZXRpbWUgPC0gZGF0ZShHUFAkZGF0ZXRpbWUpCkdQUCRQRlQgPC0gYXMuY2hhcmFjdGVyKEdQUCRQRlQpCkdQUCA8LSBHUFBbeWVhciAlaW4lIDIwMDA6MjAzMCwgXSAKCgojIEFkZCB0aGUgY29ob3J0IGxhYmVscyB0byB0aGUgZGF0YQpzcGxpdChHUFAsIGludGVyYWN0aW9uKEdQUCRkYXRldGltZSwgR1BQJHNldmVyaXR5LCBHUFAkUEZUKSwgZHJvcCA9IFRSVUUpICU+JSAKICBsYXBwbHkoZnVuY3Rpb24oeCl7CiAgICAKICAgIHgkY29ob3J0IDwtIExFVFRFUlNbMTpucm93KHgpXQogICAgcmV0dXJuKHgpCiAgICAKICB9KSAlPiUgIAogIHJsaXN0OjpsaXN0LnJiaW5kKCkgLT4gCiAgR1BQX2NvaG9ydAoKCnRvX3Bsb3QgPC0gR1BQX2NvaG9ydFt5ZWFyICVpbiUgMjAxODoyMDIwLCBdIAp0b19wbG90JHZhbHVlIDwtIHRvX3Bsb3QkdmFsdWUgLyAxMgp0b19wbG90ICU+JSAgCiAgZ2dwbG90KGFlcyhkYXRldGltZSwgdmFsdWUsIGdyb3VwID0gaW50ZXJhY3Rpb24oY29ob3J0LCBzZXZlcml0eSksIGNvbG9yID0gc2V2ZXJpdHkpKSArIAogIEFERF9ESVNUVVJCQU5DRV9MSU5FX01PTlRIICsKICBnZW9tX2xpbmUoc2l6ZSA9IDIpICsgCiAgZmFjZXRfZ3JpZCguIH4gcGZ0X25hbWUpICsgCiAgVEhFTUUgKyAKICBBRERfQ09MT1JTICsgCiAgbGFicyh0aXRsZSA9ICdHUFAgcGVyIENvaG9ydCcsIAogICAgICAgeSA9ICdrZ0MvbTIvbW9udGgnLCAKICAgICAgIHggPSAnRGF0ZScpCmBgYAoKIyMgTlBQIAoKYGBge3J9CmdncGxvdChleHBfb2JqZWN0JE5QUFt5ZWFyICVpbiUgMjAxMDoyMDMwLCBdKSArCiAgQUREX0RJU1RVUkJBTkNFX0xJTkVfQU5OVUFMICsKICBnZW9tX2xpbmUoYWVzKHllYXIsIHZhbHVlLCBjb2xvciA9IHNldmVyaXR5LCAKICAgICAgICAgICAgICAgIGdyb3VwID0gaW50ZXJhY3Rpb24oc2NuLCBwZnRfbmFtZSkpLCBzaXplID0gMS41KSArIAogIFRIRU1FICsgCiAgY29vcmRfY2FydGVzaWFuKHhsaW0gPSBjKDIwMTAsIDIwMjUpKSArIAogIGxhYnMoeCA9ICdZZWFyJywgeSA9IHVuaXF1ZShleHBfb2JqZWN0JE5QUCR1bml0KSwgdGl0bGUgPSAnQW5udWFsIE5QUCcpICsgCiAgQUREX0NPTE9SUwpgYGAKCmBgYHtyfQpoMCA8LSBhcy5kYXRhLnRhYmxlKGgwX29iamVjdCRkZl9jb2hvcnRbWzFdXSlbICAsbGlzdChkYXRldGltZSwgTU1FQU5fTlBQX0NPLCBQRlQsIERCSCwgTlBMQU5UKV0KaDQ1IDwtIGFzLmRhdGEudGFibGUoaDQ1X29iamVjdCRkZl9jb2hvcnRbWzFdXSlbICAsbGlzdChkYXRldGltZSwgTU1FQU5fTlBQX0NPLCBQRlQsIERCSCwgTlBMQU5UKV0KaDY1IDwtIGFzLmRhdGEudGFibGUoaDY1X29iamVjdCRkZl9jb2hvcnRbWzFdXSlbICAsbGlzdChkYXRldGltZSwgTU1FQU5fTlBQX0NPLCBQRlQsIERCSCwgTlBMQU5UKV0KaDg1IDwtIGFzLmRhdGEudGFibGUoaDg1X29iamVjdCRkZl9jb2hvcnRbWzFdXSlbICAsbGlzdChkYXRldGltZSwgTU1FQU5fTlBQX0NPLCBQRlQsIERCSCwgTlBMQU5UKV0KCmgwJHNldmVyaXR5ICA8LSAnMCcKaDQ1JHNldmVyaXR5IDwtICc0NScKaDY1JHNldmVyaXR5IDwtICc2NScKaDg1JHNldmVyaXR5IDwtICc4NScKCk5QUCA8LSByYmluZChoMCwgaDQ1LCBoNjUsIGg4NSkKIyBDb252ZXJ0IHRoZSBOUFAgdW5pdHMgZnJvbSBwZXIgcGxhbnQgdG8gdW5pdCBhcmVhCk5QUCR2YWx1ZSA8LSBOUFAkTU1FQU5fTlBQX0NPICogTlBQJE5QTEFOVApOUFAkdW5pdCAgPC0gdW5pcXVlKGV4cF9vYmplY3QkTlBQJHVuaXQpCk5QUCA8LSBOUFBbLCBjKCJkYXRldGltZSIsICJQRlQiLCAic2V2ZXJpdHkiLCAidmFsdWUiLCAndW5pdCcpXQpOUFAkeWVhciA8LSBsdWJyaWRhdGU6OnllYXIoTlBQJGRhdGV0aW1lKQpOUFAkZGF0ZXRpbWUgPC0gZGF0ZShOUFAkZGF0ZXRpbWUpCm1vbnRobHlfTlBQIDwtIE5QUAoKTlBQX21vbnRobHkgPC0gbW9udGhseV9OUFBbLCB2YWx1ZSA6PSBzdW0odmFsdWUpLCBieSA9IGMoImRhdGV0aW1lIiwgInNldmVyaXR5IiwgInVuaXQiLCAieWVhciIpXQpOUFBfbW9udGhseSR2YWx1ZSA8LSBOUFBfbW9udGhseSR2YWx1ZSAvIDEyCgpOUFBfbW9udGhseSAlPiUgCiAgLlt5ZWFyICVpbiUgMjAxODoyMDIwXSAlPiUgIAogIGdncGxvdChhZXMoZGF0ZXRpbWUsIHZhbHVlLCBjb2xvciA9IHNldmVyaXR5KSkgKyAKICBBRERfRElTVFVSQkFOQ0VfTElORV9NT05USCArCiAgQUREX0NPTE9SUyArCiAgZ2VvbV9saW5lKHNpemUgPSAxLjUpICsgCiAgVEhFTUUgKyAKICBsYWJzKHRpdGxlID0gJ01vbnRobHkgTlBQJywgeSA9ICdrZ0MvbTIvbW9udGgnLCB4ID0gJ1RpbWUnKSAKYGBgCgojIyBORVAgCgpgYGB7cn0KZXhwX29iamVjdCRORVAgJT4lIAogIGRwbHlyOjpmaWx0ZXIoeWVhciA+PSAyMDEwICYgeWVhciA8PSAyMDIxKSAlPiUgCiAgZ2dwbG90KCkgKyAKICBnZW9tX3ZsaW5lKHhpbnRlcmNlcHQgPSAyMDE5LCBjb2xvciA9ICdncmV5Jywgc2l6ZSA9IDEuNSkgKyAKICBnZW9tX2xpbmUoYWVzKHllYXIsIHZhbHVlLCBjb2xvciA9IHNldmVyaXR5KSwgc2l6ZSA9IDEuNSkgKyAKICBUSEVNRSArIAogIEFERF9DT0xPUlMgKwogIGxhYnMoeCA9ICdZZWFyJywgeSA9IHVuaXF1ZShleHBfb2JqZWN0JE5FUCR1bml0KSwgdGl0bGUgPSAnQW5udWFsIE5FUCcpCmBgYAoKYGBge3J9CmgwIDwtIGFzLmRhdGEudGFibGUoaDBfb2JqZWN0JGRmX3NjYWxhcltbMV1dKVsgLGxpc3QoZGF0ZXRpbWUsIE1NRUFOX05FUF9QWSldCmg0NSA8LSBhcy5kYXRhLnRhYmxlKGg0NV9vYmplY3QkZGZfc2NhbGFyW1sxXV0pWyAsbGlzdChkYXRldGltZSwgTU1FQU5fTkVQX1BZKV0KaDY1IDwtIGFzLmRhdGEudGFibGUoaDY1X29iamVjdCRkZl9zY2FsYXJbWzFdXSlbICxsaXN0KGRhdGV0aW1lLCBNTUVBTl9ORVBfUFkpXQpoODUgPC0gYXMuZGF0YS50YWJsZShoODVfb2JqZWN0JGRmX3NjYWxhcltbMV1dKVsgLGxpc3QoZGF0ZXRpbWUsIE1NRUFOX05FUF9QWSldCgpoMCRzZXZlcml0eSAgPC0gJzAnCmg0NSRzZXZlcml0eSA8LSAnNDUnCmg2NSRzZXZlcml0eSA8LSAnNjUnCmg4NSRzZXZlcml0eSA8LSAnODUnCgpORVAgPC0gcmJpbmQoaDAsIGg0NSwgaDY1LCBoODUpCk5FUCR1bml0ICA8LSB1bmlxdWUoZXhwX29iamVjdCRORVAkdW5pdCkKTkVQIDwtIE5FUFssIGMoImRhdGV0aW1lIiwgInNldmVyaXR5IiwgInZhbHVlIiA9ICJNTUVBTl9ORVBfUFkiKV0KbmFtZXMoTkVQKSA8LSBjKCJkYXRldGltZSIsICJzZXZlcml0eSIsICJ2YWx1ZSIpCk5FUCR5ZWFyIDwtIGx1YnJpZGF0ZTo6eWVhcihORVAkZGF0ZXRpbWUpCk5FUCRkYXRldGltZSA8LSBkYXRlKE5FUCRkYXRldGltZSkKCk5FUCAlPiUgCiAgZHBseXI6OmZpbHRlcih5ZWFyID49IDIwMTggJiB5ZWFyIDw9IDIwMjApICU+JSAKICBkcGx5cjo6bXV0YXRlKHZhbHVlID0gdmFsdWUgLyAxMiwgCiAgICAgICAgICAgICAgICB1bml0cyA9ICdrZy9tMi9tb250aCcpICU+JSAKICBnZ3Bsb3QoKSArIAogIEFERF9ESVNUVVJCQU5DRV9MSU5FX01PTlRIICsgCiAgZ2VvbV9saW5lKGFlcyhkYXRldGltZSwgdmFsdWUsIGNvbG9yID0gc2V2ZXJpdHkpLCBzaXplID0gMS41KSArIAogIFRIRU1FICsgCiAgQUREX0NPTE9SUyArCiAgbGFicyh4ID0gJ1llYXInLCB5ID0na2cvbTIvbW9udGgnLCB0aXRsZSA9ICdNb250aGx5IE5FUCcpCgpgYGAKCiMjIEhldGVyb3Ryb3BoaWMgUmVzcGlyYXRpb24KCmBgYHtyfQpoMCA8LSBhcy5kYXRhLnRhYmxlKGgwX29iamVjdCRkZl9zY2FsYXJbWzFdXSlbICAsbGlzdChkYXRldGltZSwgTU1FQU5fUkhfUFkpXQpoNDUgPC0gYXMuZGF0YS50YWJsZShoNDVfb2JqZWN0JGRmX3NjYWxhcltbMV1dKVsgICxsaXN0KGRhdGV0aW1lLCBNTUVBTl9SSF9QWSldCmg2NSA8LSBhcy5kYXRhLnRhYmxlKGg2NV9vYmplY3QkZGZfc2NhbGFyW1sxXV0pWyAgLGxpc3QoZGF0ZXRpbWUsIE1NRUFOX1JIX1BZKV0KaDg1IDwtIGFzLmRhdGEudGFibGUoaDg1X29iamVjdCRkZl9zY2FsYXJbWzFdXSlbICAsbGlzdChkYXRldGltZSwgTU1FQU5fUkhfUFkpXQoKaDAkc2V2ZXJpdHkgIDwtICcwJwpoNDUkc2V2ZXJpdHkgPC0gJzQ1JwpoNjUkc2V2ZXJpdHkgPC0gJzY1JwpoODUkc2V2ZXJpdHkgPC0gJzg1JwoKUkggICAgPC0gcmJpbmQoaDAsIGg0NSwgaDY1LCBoODUpClJIJGRhdGV0aW1lIDwtIGFzX2RhdGUoUkgkZGF0ZXRpbWUgKQp1bml0cyA8LSAna2cvbTIvbW9udGgnClJIJE1NRUFOX1JIX1BZIDwtIFJIJE1NRUFOX1JIX1BZIC8gMTIKClJIW2RhdGV0aW1lID49IHltZCgnMjAxOC0wNi0wMScpICYgZGF0ZXRpbWUgPD0geW1kKCcyMDIxLTAxLTAxJyksIF0gJT4lIApnZ3Bsb3QoYWVzKGRhdGV0aW1lLCBNTUVBTl9SSF9QWSwgY29sb3IgPSBzZXZlcml0eSkpICsgCiAgQUREX0RJU1RVUkJBTkNFX0xJTkVfTU9OVEggKwogIGdlb21fbGluZShzaXplID0gMS41KSArIAogIFRIRU1FICsgCiAgbGFicyh0aXRsZSA9ICdNb250aGx5IEhldGVyb3Ryb3BoaWMgUmVzcGlyYXRpb24nLCAKICAgICAgIHkgPSB1bml0cywKICAgICAgIHggPSAnRGF0ZSBUaW1lJykgKyAKICBBRERfQ09MT1JTCmBgYAoKCiMjIExBSSAKCgpgYGB7cn0KCmV4cF9vYmplY3QkTEFJJHllYXIgPC0geWVhcihleHBfb2JqZWN0JExBSSRkYXRldGltZSkKZXhwX29iamVjdCRMQUkgJT4lIAogIGRwbHlyOjpmaWx0ZXIoeWVhciA+PSAyMDE4ICYgeWVhciA8PSAyMDIwKSAlPiUgCiAgZHBseXI6OmZpbHRlcihwZnRfbmFtZSA9PSAnVGVtcGVyYXRlIGJyb2FkbGVhZiwgZWFybHkgc3VjY2Vzc2lvbmFsJykgJT4lIAogIGdncGxvdCgpICsgCiAgQUREX0RJU1RVUkJBTkNFX0xJTkVfTU9OVEggKyAKICBnZW9tX2xpbmUoYWVzKGRhdGV0aW1lLCB2YWx1ZSwgY29sb3IgPSBzZXZlcml0eSksIHNpemUgPSAxLjUpICsgCiAgQUREX0NPTE9SUyArCiAgVEhFTUUgKyAKICBsYWJzKHggPSAnWWVhcicsIHkgPSB1bmlxdWUoZXhwX29iamVjdCRMQUkkdW5pdCksIHRpdGxlID0gJ01vbnRobHkgTEFJJykgKyAKICBmYWNldF93cmFwKCdwZnRfbmFtZScsIG5jb2wgPSAxKQpgYGAKCgojIyBDYXJib24gQ3ljbGluZyBSZXNpc3RhbmNlCgpDYXJib24gQ3ljbGluZyBSZXNpc3RhbmNlCgokJHIgPSBcbG4gXGxlZnQoIHtcZnJhY3t7Rl97e1x0ZXh0e2Rpc3R9fX0gfX17e0Zfe3tcdGV4dHtjb250fX19IH19fSBccmlnaHQpJCQgRXF1YXRpb24gMSBmcm9tIEdvdWdoIDIwMjAuIAoKYGBge3J9CgpleHBfb2JqZWN0JE5QUFt5ZWFyICVpbiUgMjAxODoyMDMwLCBdICU+JSAgCiAgLlssIGxpc3QocGZ0X25hbWUsIHllYXIsIHZhcmlhYmxlLCB1bml0LCB2YWx1ZSwgc2V2ZXJpdHkpXSAlPiUgCiAgIyBNYWtlIHRoZSB0YWJsZSB3aWRlIGJ5IGRpc3R1cmJhbmNlIHNldmVyaXR5IHRyZWF0bWVudC4gCiAgZGNhc3QoZGF0YSA9IC4sIHBmdF9uYW1lICsgeWVhciArIHZhcmlhYmxlICsgdW5pdCB+IHNldmVyaXR5KSAlPiUKICAjIE5vdyBnYXRoZXIgYWxsIG9mIHRoZSBkaXN0dWJyYW5jZSB0cmVhdG1lbnRzIGludG8gYSBzaW5nbGUgY29sdW1uIHNvIHRoYXQgdGhlIAogICMgY29udHJvbCB2YWx1ZXMgYXJlIHJlY29yZGVkIGluIHRoZWlyIG93biBjb2x1bW4uIAogIG1lbHQoZGF0YSA9IC4sIGlkLnZhcnMgPSBjKCJwZnRfbmFtZSIsICJ5ZWFyIiwgInZhcmlhYmxlIiwgInVuaXQiLCAiMCIpLCAKICAgICAgIG1lYXN1cmUudmFycyA9IGMoJzQ1JywgJzY1JywgJzg1JyksIHZhcmlhYmxlLm5hbWUgPSAnc2V2ZXJpdHknLCAKICAgICAgIHZhbHVlLm5hbWUgPSAndHJlYXRtZW50X3ZhbHVlJykgJT4lICAKICAjIFJlbmFtZSB0aGUgY29sdW1ucyAKICAuWyAsIGxpc3QocGZ0X25hbWUsIHllYXIsIHZhcmlhYmxlLCB1bml0LCBjb250cm9sID0gYDBgLCBzZXZlcml0eSwgZGlzdCA9IHRyZWF0bWVudF92YWx1ZSldICU+JSAKICAjIE5vdyBjYWxjdWxhdGUgciAKICAuWyAsIHIgOj0gbG9nKGRpc3QvY29udHJvbCldIC0+IAogIE5QUF9yCiAgCk5QUF9yICU+JSAgIApnZ3Bsb3QoYWVzKHllYXIsIHIsIGNvbG9yID0gc2V2ZXJpdHkpKSArIAogIGdlb21fbGluZShzaXplID0gMS41KSArIAogIEFERF9DT0xPUlMgKyAKICBUSEVNRSArIAogIGxhYnModGl0bGUgPSAnTlBQIFJlc2lzdGFuY2UgVmFsdWVzJywgCiAgICAgICB5ID0gZXhwcmVzc2lvbigncidbbnBwXSksIAogICAgICAgeCA9ICdZZWFyJykKYGBgCg==