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==