This document includes descriptive plots of the relationship between hours and wages over time in the U.S. in the past 4 decades using data from CPS-ORG and CPS-ASEC surveys.

Patterns for the Literature Costa (2000): while the elasticity between hours per day and houely wages was negative in the end of the 19th centiry and in 1973, by 1991 it became positive.

Mantovani (2024, not published):

knitr::include_graphics("/Users/tamary/Dropbox/WFH/Empirical work/pictures/mantovani.png")

CPS-ORG from IPUMS

1982-2024; ages 25-65; more than 10 hours per week; non self-employed workers.

Variables used:

ipums_org <- fread("~/Dropbox/WFH/Empirical work/Data/IPUMS CPS ORG/ipums_org.csv")
|--------------------------------------------------|
|==================================================|
# Initial cleanup and variable construction
ipums_org <- ipums_org %>%
  filter(AGE >= 25, AGE <= 65) %>%
  filter(UHRSWORK1 > 10 & UHRSWORK1 < 100) %>%
  filter(CLASSWKR >= 20 & CLASSWKR != 99)


# Use cut to create the bins
bin_breaks <- c(seq(10, 80, by = 5))
bin_labels <- c("10-14","15-19","20-24","25-29","30-34", "35-39", "40-44", "45-49", "50-54", "55-59", "60-64", "65-69", "70-74", "75-79", "80+")

ipums_org <- ipums_org %>%
  mutate(AGE2 = AGE * AGE,
         HOURWAGE_computed = EARNWEEK / UHRSWORK1,  
         ln_hrwage = log(HOURWAGE_computed),
         bin = as.factor(cut(UHRSWORK1, breaks = c(bin_breaks, Inf), right = FALSE,
                             labels = NULL)),
         salaried = PAIDHOUR == 1)

Below I replicate a plot from Bick et. al. (QJE 2022) to assure data cleaning is correct. This plot includes both the distribution of hours worked and the coefficients of log wages on a set of bins of hours for men, controlling for education, marital status, union status, race as well as year and month fixed effect for the years 1995-2007.

bick_et_al_data <- ipums_org %>%
  filter(YEAR >= 1995 & YEAR <= 2007) %>%
  filter(SEX == 1) %>%
  filter(MULTJOB == 1) # not multijobbed
  
formula_bins <- as.formula("ln_hrwage ~ bin + AGE + AGE2 + 
                            factor(MARST) + factor(EDUC) + 
                            factor(RACE) + factor(YEAR) + factor(MONTH) + UNION - 1") 

combined(bick_et_al_data, weight_var = "EARNWT", title = NULL, filename = NULL, bin_var = "bin", formula = formula_bins, plot = TRUE)

Now I look at a aggregate trends in hours worked over time. First, while women have consistently increased their working hours, men’s working hours have decreased slighlty.

summary_by_year_sex <- ipums_org %>% 
  group_by(YEAR, SEX) %>% 
  summarise(mean_hours = weighted.mean(UHRSWORK1, EARNWT),
            share_less_40 = weighted.mean(UHRSWORK1 < 40, EARNWT),
            share_exacctly_40 = weighted.mean(UHRSWORK1 == 40, EARNWT),
            share_above_40 = weighted.mean(UHRSWORK1 > 40, EARNWT), .groups = "drop")

summary_by_year_sex %>%
  ggplot(aes(x = YEAR, y = mean_hours, color = factor(SEX))) +
  geom_point(size = 0.5) +                # Adjust point size
  geom_line(size = 0.5) +                 # Adjust line thickness
  scale_color_brewer(palette = "Set2",  # Nicer colors
                     labels = c("Male", "Female")) + 
  labs(title = "Mean Hours Worked Over Time",
       x = "Year",
       y = "Mean Hours Worked",
       color = "Sex") +                # Update legend title
  theme_minimal()                      # Clean theme
Warning: Using `size` aesthetic for lines was deprecated in ggplot2 3.4.0.
ℹ Please use `linewidth` instead.
This warning is displayed once every 8 hours.
Call `lifecycle::last_lifecycle_warnings()` to see where this warning was generated.

plot_dist_40(ipums_org, UHRSWORK1, EARNWT, "all Workers, CPS-ORG")

plot_dist_40(ipums_org %>% filter(SEX == 1), UHRSWORK1, EARNWT, "Men, CPS-ORG")

plot_dist_40(ipums_org %>% filter(SEX == 2), UHRSWORK1, EARNWT, "Women, CPS-ORG")

Now I look at how this changed across weekly earnings deciles:

ipums_org <- add_weighted_decile_by_year(ipums_org, "EARNWEEK", "EARNWT", "YEAR")

for (i in 1:10){
  plot_dist_40(ipums_org %>% filter(EARNWEEK_decile == i),UHRSWORK1, EARNWT, paste0("all Workers, ",i,"th decile"))
}

Below, I plot the mean of hours worked by decile: - There seems to be something weird about data from 2023-2024 - The Menotovani fact (D1 going down, D10 going down) does not replicate

plot_v1_mean_by_v2_decile_over_v3(ipums_org, "UHRSWORK1", "EARNWEEK", "YEAR", "EARNWT",
                                  color_lab = "EARNWEEK Decile",
                                  caption = "Source: CPS-ORG IPUMS")
[1] "UHRSWORK1 mean by EARNWEEK deciles, All Observations"

plot_v1_mean_by_v2_decile_over_v3(ipums_org, "UHRSWORK1", "HOURWAGE_computed", "YEAR", "EARNWT",
                                  caption = "Source: CPS-ORG IPUMS")
[1] "UHRSWORK1 mean by HOURWAGE_computed deciles, All Observations"

plot_v1_mean_by_v2_decile_over_v3(ipums_org, "UHRSWORK1", "HOURWAGE_computed", "YEAR", "EARNWT",
                                  filter_expr = salaried == 1,
                                  caption = "Source: CPS-ORG IPUMS")
[1] "UHRSWORK1 mean by HOURWAGE_computed deciles, salaried == 1"

plot_v1_mean_by_v2_decile_over_v3(ipums_org, "UHRSWORK1", "HOURWAGE_computed", "YEAR", "EARNWT",
                                  filter_expr = salaried == 1,
                                  caption = "Source: CPS-ORG IPUMS", deciles_to_plot = c(1,5,10))
[1] "UHRSWORK1 mean by HOURWAGE_computed deciles, salaried == 1"

plot_v1_mean_by_v2_decile_over_v3(ipums_org, "UHRSWORK1", "HOURWAGE_computed", "YEAR", "EARNWT",
                                  filter_expr = salaried == 0,
                                  caption = "Source: CPS-ORG IPUMS")
[1] "UHRSWORK1 mean by HOURWAGE_computed deciles, salaried == 0"

plot_v1_mean_by_v2_decile_over_v3(ipums_org, "UHRSWORK1", "HOURWAGE", "YEAR", "EARNWT",
                                  filter_expr = salaried == 0,
                                  caption = "Source: CPS-ORG IPUMS")
[1] "UHRSWORK1 mean by HOURWAGE deciles, salaried == 0"

hourly_workers <- bick_et_al_data %>% filter(salaried == 0) %>% filter(!is.na(HOURWAGE))
cor(hourly_workers$HOURWAGE_computed, hourly_workers$HOURWAGE)
[1] 0.5235918

CPS-MORG from CEPR

I also tried to replicate the Mantovani plot from CEPR CPS-MORG data that he states he used but the results are very weird. I am not sure which variables he used.

ORG <- fread(paste0(dir,"/data/CEPR/cepr_data.csv"))
# Understanding the data
ORG <- ORG %>%
  mutate(hourly_worker = !is.na(wage1),
         salaried_worker = !is.na(wage2))

ORG <- ORG %>% filter(!is.na(uhourse))

ORG <- ORG %>% mutate(log_wage3 = log(wage3),
                      log_uhoursw = log(uhourse), age_sq = age*age)
# a <- feols(log_uhoursw ~ log_wage3, data = ORG %>% filter(wage3> 0, uhourse >0), weights = ~fnlwgt, fsplit = ~year)
plot_uhourse_mean_by_wage3_decile_over_year_CPSORG <- function(filter_expr){
  plot_v1_mean_by_v2_decile_over_v3(ORG, "uhourse", "wage3", "year", "fnlwgt",
                                  filter_expr = !!enquo(filter_expr),
                                  caption = "Source: CPS-ORG",
                                  )
}

plot_uhourse_mean_by_wage3_decile_over_year_CPSORG(uhourse > 35)
[1] "uhourse mean by wage3 deciles, uhourse > 35"

plot_uhourse_mean_by_wage3_decile_over_year_CPSORG(uhourse > 35 & salaried_worker == 1)
[1] "uhourse mean by wage3 deciles, uhourse > 35 & salaried_worker == 1"

plot_uhourse_mean_by_wage3_decile_over_year_CPSORG(uhourse > 35 & hourly_worker == 1)
[1] "uhourse mean by wage3 deciles, uhourse > 35 & hourly_worker == 1"

plot_uhourse_mean_by_wage3_decile_over_year_CPSORG(uhourse > 10)
[1] "uhourse mean by wage3 deciles, uhourse > 10"

plot_uhourse_mean_by_wage3_decile_over_year_CPSORG(uhourse > 10 & salaried_worker == 1)
[1] "uhourse mean by wage3 deciles, uhourse > 10 & salaried_worker == 1"

plot_uhourse_mean_by_wage3_decile_over_year_CPSORG(uhourse > 10 & hourly_worker == 1)
[1] "uhourse mean by wage3 deciles, uhourse > 10 & hourly_worker == 1"

Note that abrupt changes in the topcode occurred in 1989 and 1998, I am not sure what happened in 1994.

ASEC

I conducted a similar analysis for ASEC data, for the years 1962-2024, workers of ages 25-65. ASEC asks respondents both regarding actual hours worked last week and on usual hour worked last year. Income is documented only at an annual basis - for the previous calander year.

This document first plots patterns with annual income and then uses an estimate of hourly wages constructed by dividing the annual income by (# weeks per year X # hours per week.)

n = 3696401

asec <- fread(paste0(dir,"/data/CPS_long_term/ASEC/ASEC_62_24.csv"))

asec <- asec %>%
  filter(AGE >= 25 & AGE <= 65,
         INCWAGE > 0,
         INCWAGE != 99999998, # missing
         INCWAGE != 99999999)  # NIU 

asec_worked_LY <- asec %>% filter(UHRSWORKLY != 999)
asec_worked_LW <- asec %>% filter(AHRSWORKT != 999)
summary_by_year_sex_asec <- asec_worked_LY %>% 
  group_by(YEAR, SEX) %>% 
  summarise(mean_hours = weighted.mean(UHRSWORKLY, ASECWT),
            share_less_40 = weighted.mean(UHRSWORKLY < 40, ASECWT),
            share_exacctly_40 = weighted.mean(UHRSWORKLY == 40, ASECWT),
            share_above_40 = weighted.mean(UHRSWORKLY > 40, ASECWT), .groups = "drop")

summary_by_year_sex_asec %>%
  ggplot(aes(x = YEAR, y = mean_hours, color = factor(SEX))) +
  geom_point(size = 0.5) +                # Adjust point size
  geom_line(size = 0.5) +                 # Adjust line thickness
  scale_color_brewer(palette = "Set2",  # Nicer colors
                     labels = c("Male", "Female")) + 
  labs(title = "Mean Hours Worked Last Year Over Time, ASEC",
       x = "Year",
       y = "Mean Hours Worked",
       color = "Sex") +                # Update legend title
  theme_minimal()                      # Clean theme

NA
NA
plot_dist_40(asec_worked_LY, UHRSWORKLY, ASECWT, "all Workers, ASEC")

plot_dist_40(asec_worked_LY %>% filter(SEX == 1), UHRSWORKLY, ASECWT, "Men, ASEC")

plot_dist_40(asec_worked_LY %>% filter(SEX == 2), UHRSWORKLY, ASECWT, "Women, ASEC")

plot_v1_mean_by_v2_decile_over_v3(asec_worked_LY, "UHRSWORKLY", "INCWAGE", "YEAR", "ASECWT",
                                  title = "Usual Hours Worked Last Year over Annual Income, all Workers",
                                  caption = "Source: ASEC 1976-2024")

plot_v1_mean_by_v2_decile_over_v3(asec_worked_LY, "UHRSWORKLY", "INCWAGE", "YEAR", "ASECWT",
                                  deciles_to_plot = c(1, 5, 10), 
                                  title = "Usual Hours Worked Last Year over Annual Income, all Workers",
                                  caption = "Source: ASEC 1976-2024")

Now, limit attention to workers that worked 50-52 weeks per week

asec_worked_LY_full <- asec_worked_LY %>% filter(WKSWORK2 == 6) 
plot_v1_mean_by_v2_decile_over_v3(asec_worked_LY_full, "UHRSWORKLY", "INCWAGE", "YEAR", "ASECWT",
                                  title = "Usual Hours Worked Last Year over Annual Income, 50-52 weeks worked last year",
                                  caption = "Source: ASEC 1976-2024")

plot_v1_mean_by_v2_decile_over_v3(asec_worked_LY_full, "UHRSWORKLY", "INCWAGE", "YEAR", "ASECWT",
                                  deciles_to_plot = c(1, 5, 10), 
                                  title = "Usual Hours Worked Last Year over Annual Income, 50-52 weeks worked last year",
                                  caption = "Source: ASEC 1976-2024")

plot_v1_mean_by_v2_decile_over_v3(asec_worked_LY_full %>% mutate(h_wage_usual = INCWAGE / 51 / UHRSWORKLY),
                                  "UHRSWORKLY", "h_wage_usual", "YEAR", "ASECWT",
                                  title = "Usual Hours Worked Last Year by Computed Hourly Wage, 50-52 weeks worked last year",
                                  caption = "Source: ASEC. Note: computed hourly wage = annual income / 51 / usual hours worked last year")

plot_v1_mean_by_v2_decile_over_v3(asec_worked_LY_full %>% mutate(h_wage_usual = INCWAGE / 51 / UHRSWORKLY),
                                  "UHRSWORKLY", "h_wage_usual", "YEAR", "ASECWT",
                                  deciles_to_plot = c(1, 5, 10), 
                                  title = "Usual Hours Worked Last Year by Computed Hourly Wage, 50-52 weeks worked last year",
                                  caption = "Source: ASEC. Note: computed hourly wage = annual income / 51 / usual hours worked last year")

Now, Limit attention to workers with more than 40 hours worked on usual weeks

plot_v1_mean_by_v2_decile_over_v3(asec_worked_LY %>% filter(WKSWORK2 == 6) %>% filter(UHRSWORKLY >= 40),
                                  "UHRSWORKLY", "INCWAGE", "YEAR", "ASECWT",
                                  title = "Usual Hours Worked Last Year over Annual Income,\n50-52 weeks worked last year, >= 40h per usual week",
                                  caption = "Source: ASEC 1976-2024")

plot_v1_mean_by_v2_decile_over_v3(asec_worked_LY %>% filter(WKSWORK2 == 6) %>% filter(UHRSWORKLY >= 40),
                                  "UHRSWORKLY", "INCWAGE", "YEAR", "ASECWT",
                                  deciles_to_plot = c(1, 5, 10), 
                                  title = "Usual Hours Worked Last Year over Annual Income,\n50-52 weeks worked last year, >= 40h per usual week",
                                  caption = "Source: ASEC 1976-2024")

plot_v1_mean_by_v2_decile_over_v3(asec_worked_LY %>% filter(WKSWORK2 == 6) %>% filter(UHRSWORKLY >= 40) %>% mutate(h_wage_usual = INCWAGE / 51 / UHRSWORKLY),
                                  "UHRSWORKLY", "h_wage_usual", "YEAR", "ASECWT",
                                  title = "Usual Hours Worked Last Year by Computed Hourly Wage,\n50-52 weeks worked last year, >= 40 hours per usual week",
                                  caption = "Source: ASEC. Note: computed hourly wage = annual income / 51 / usual hours worked last year")

plot_v1_mean_by_v2_decile_over_v3(asec_worked_LY %>% filter(WKSWORK2 == 6) %>% filter(UHRSWORKLY >= 40) %>% mutate(h_wage_usual = INCWAGE / 51 / UHRSWORKLY),
                                  "UHRSWORKLY", "h_wage_usual", "YEAR", "ASECWT",
                                  deciles_to_plot = c(1, 5, 10), 
                                  title = "Usual Hours Worked Last Year by Computed Hourly Wage,\n50-52 weeks worked last year,  >= than 40 hours per usual week",
                                  caption = "Source: ASEC. Note: computed hourly wage = annual income / 51 / usual hours worked last year")

plot_v1_mean_by_v2_decile_over_v3(asec_worked_LY %>% filter(WKSWORK2 == 6) %>% filter(UHRSWORKLY >= 35) %>% mutate(h_wage_usual = INCWAGE / 51 / UHRSWORKLY),
                                  "UHRSWORKLY", "h_wage_usual", "YEAR", "ASECWT",
                                  title = "Usual Hours Worked Last Year by Computed Hourly Wage,\n50-52 weeks worked last year, >= 35 hours per usual week",
                                  caption = "Source: ASEC. Note: computed hourly wage = annual income / 51 / usual hours worked last year")

plot_v1_mean_by_v2_decile_over_v3(asec_worked_LY %>% filter(WKSWORK2 == 6) %>% filter(UHRSWORKLY >= 35) %>% mutate(h_wage_usual = INCWAGE / 51 / UHRSWORKLY),
                                  "UHRSWORKLY", "h_wage_usual", "YEAR", "ASECWT",
                                  deciles_to_plot = c(1, 5, 10), 
                                  title = "Usual Hours Worked Last Year by Computed Hourly Wage,\n50-52 weeks worked last year, >= 35 hours per usual week",
                                  caption = "Source: ASEC. Note: computed hourly wage = annual income / 51 / usual hours worked last year")

plot_v1_mean_by_v2_decile_over_v3(asec_worked_LY %>% filter(WKSWORK2 == 6, UHRSWORKLY >= 40, SEX == 1) %>% mutate(h_wage_usual = INCWAGE / 51 / UHRSWORKLY),
                                  "UHRSWORKLY", "h_wage_usual", "YEAR", "ASECWT",
                                  title = "Usual Hours Worked Last Year by Computed Hourly Wage, Men\n50-52 weeks worked last year, >= 40 hours per usual week",
                                  caption = "Source: ASEC. Note: computed hourly wage = annual income / 51 / usual hours worked last year")

plot_v1_mean_by_v2_decile_over_v3(asec_worked_LY %>% filter(WKSWORK2 == 6, UHRSWORKLY >= 40, SEX == 1) %>% mutate(h_wage_usual = INCWAGE / 51 / UHRSWORKLY),
                                  "UHRSWORKLY", "h_wage_usual", "YEAR", "ASECWT",
                                  deciles_to_plot = c(1, 5, 10), 
                                  title = "Usual Hours Worked Last Year by Computed Hourly Wage, Men\n50-52 weeks worked last year,  >= than 40 hours per usual week",
                                  caption = "Source: ASEC. Note: computed hourly wage = annual income / 51 / usual hours worked last year")

plot_v1_mean_by_v2_decile_over_v3(asec_worked_LY %>% filter(WKSWORK2 == 6, UHRSWORKLY >= 40, SEX == 2) %>% mutate(h_wage_usual = INCWAGE / 51 / UHRSWORKLY),
                                  "UHRSWORKLY", "h_wage_usual", "YEAR", "ASECWT",
                                  title = "Usual Hours Worked Last Year by Computed Hourly Wage, Women\n50-52 weeks worked last year, >= 40 hours per usual week",
                                  caption = "Source: ASEC. Note: computed hourly wage = annual income / 51 / usual hours worked last year")

plot_v1_mean_by_v2_decile_over_v3(asec_worked_LY %>% filter(WKSWORK2 == 6, UHRSWORKLY >= 40, SEX == 2) %>% mutate(h_wage_usual = INCWAGE / 51 / UHRSWORKLY),
                                  "UHRSWORKLY", "h_wage_usual", "YEAR", "ASECWT",
                                  deciles_to_plot = c(1, 5, 10), 
                                  title = "Usual Hours Worked Last Year by Computed Hourly Wage, Women\n50-52 weeks worked last year,  >= than 40 hours per usual week",
                                  caption = "Source: ASEC. Note: computed hourly wage = annual income / 51 / usual hours worked last year")

Within-Between Variance Decomposition - To be completed

# Within - between variance decomposition

summary_decomp_df <- ipums_org %>%
  filter(!is.na(UHRSWORK1)) %>%
  group_by(YEAR) %>%
  mutate(year_total = n()) %>%  # Add total count for each year
  group_by(YEAR, OCC2010) %>%
  summarise(variance = var(UHRSWORK1),
            mean = mean(UHRSWORK1),
            n = n(),
            share = n() / unique(year_total), .groups = "drop")

var_decomposition_df <- data.frame(YEAR = unique(summary_decomp_df$YEAR))

for (i in (1:nrow(var_decomposition_df))){
  year <- var_decomposition_df[i,"YEAR"]
  
  mean_all <- mean(ipums_org %>% filter(YEAR == year) %>% pull(UHRSWORK1))
  summary_decomp_df_year <- summary_decomp_df %>% filter(YEAR == year)
  
  var_within_occ_vec <- summary_decomp_df_year %>% pull(variance) 
  mean_within_occ_vec <- summary_decomp_df_year %>% pull(mean)
  share_occ_vec <- summary_decomp_df_year %>% pull(share)
  
  var_decomposition_df[i,"within_var"] <- sum(var_within_occ_vec * share_occ_vec)
  var_decomposition_df[i,"between_var"] <- sum(share_occ_vec * (mean_within_occ_vec - mean_all) ^ 2)
  
  var_decomposition_df[i,"total_var_computed_as_sum"] <-  var_decomposition_df[i,"within_var"] + var_decomposition_df[i,"between_var"] 
  var_decomposition_df[i,"total_var_computed_as_normal"] <- var(ipums_org %>% filter(YEAR == year) %>% pull(UHRSWORK1))
  
}



within_var <- sum(occ_year_within_var_vector * occ_year_share_vector)
between_var <- sum(share_vector * (mean_vector - mean_all) ^ 2)
total_var_decomposed_calc <- within_var+between_var

var(ipums_org$UHRSWORK1)
LS0tCnRpdGxlOiAiRG9jdW1lbnRpbmcgUGF0dGVybnMgaW4gSG91cnMgV29ya2VkIG92ZXIgVGltZSIKb3V0cHV0OiBodG1sX25vdGVib29rCi0tLQoKVGhpcyBkb2N1bWVudCBpbmNsdWRlcyBkZXNjcmlwdGl2ZSBwbG90cyBvZiB0aGUgcmVsYXRpb25zaGlwIGJldHdlZW4gaG91cnMgYW5kIHdhZ2VzIG92ZXIgdGltZSBpbiB0aGUgVS5TLiBpbiB0aGUgcGFzdCA0IGRlY2FkZXMgdXNpbmcgZGF0YSBmcm9tIENQUy1PUkcgYW5kIENQUy1BU0VDIHN1cnZleXMuIAoKCioqUGF0dGVybnMgZm9yIHRoZSBMaXRlcmF0dXJlKioKQ29zdGEgKDIwMDApOiB3aGlsZSB0aGUgZWxhc3RpY2l0eSBiZXR3ZWVuIGhvdXJzIHBlciBkYXkgYW5kIGhvdWVseSB3YWdlcyB3YXMgbmVnYXRpdmUgaW4gdGhlIGVuZCBvZiB0aGUgMTl0aCBjZW50aXJ5IGFuZCBpbiAxOTczLCBieSAxOTkxIGl0IGJlY2FtZSBwb3NpdGl2ZS4gCgpNYW50b3ZhbmkgKDIwMjQsIG5vdCBwdWJsaXNoZWQpOgoKYGBge3J9CmtuaXRyOjppbmNsdWRlX2dyYXBoaWNzKCIvVXNlcnMvdGFtYXJ5L0Ryb3Bib3gvV0ZIL0VtcGlyaWNhbCB3b3JrL3BpY3R1cmVzL21hbnRvdmFuaS5wbmciKQpgYGAKCgpgYGB7ciwgZWNobyA9IEZBTFNFLCBtZXNzYWdlID0gRkFMU0UsIHdhcm5pbmcgPSBGQUxTRSwgcmVzdWx0cz0naGlkZSd9CiMgU2V0IHVwCmxpYnJhcnkodGlkeXZlcnNlKQpsaWJyYXJ5KGRhdGEudGFibGUpCmxpYnJhcnkoc3RhcmdhemVyKQpsaWJyYXJ5KGZpeGVzdCkKbGlicmFyeShocmJydGhlbWVzKQpsaWJyYXJ5KHN1cnZleSkKCmRpciA8LSAifi9Ecm9wYm94L1dGSC9FbXBpcmljYWwgd29yayIKc291cmNlKHBhc3RlMChkaXIsIi9TY3JpcHRzL3RyZW5kc19lbmdpbmUuUiIpKQpzb3VyY2UocGFzdGUwKGRpciwiL1NjcmlwdHMvZ2VuZXJhbF9lbmdpbmUuUiIpKQoKYGBgCgojIENQUy1PUkcgZnJvbSBJUFVNUwoxOTgyLTIwMjQ7IGFnZXMgMjUtNjU7IG1vcmUgdGhhbiAxMCBob3VycyBwZXIgd2Vlazsgbm9uIHNlbGYtZW1wbG95ZWQgd29ya2Vycy4KClZhcmlhYmxlcyB1c2VkOgoKLSBVSFJTV09SSzEgLSBob3VycyB3b3JrZWQgaW4gbWFpbiBqb2IuIChBZnRlciAxOTk1IHRoZSBzdXJ2ZXkgZXhwbGljaXRseSBkaXN0aW5ndWlzaGVzIGJldHdlZW4gbWFpbiBqb2IgYW5kIG90aGVyIGpvYnM7IGJlZm9yZSAxOTk1IC0gdGhlcmUgaXMgbm8gZGlzdGluY3Rpb24uIFRoZSBzaGFyZSBvZiB3b3JrZXJzIHdpdGggbXVsdGlwbGUgam9icyBpcyA1JSkKLSBFQVJOV0VFSyAtIHVzdWFsIHdlZWtseSBlYXJuaW5ncyAKLSBIT1VSV0FHRSAtIGhvdXJseSB3YWdlIGZvciB3b3JrZXJzIHdobyBhcmUgcGFpZCBieSB0aGUgaG91cgotIEhPVVJXQUdFX2NvbXB1dGVkID0gRUFSTldFRUsgLyBVSFJTV09SSzEKKiBIT1VSV0FHRSBpcyBub3QgZXF1YWwgdG8gSE9VUldBR0VfY29tcHV0ZWQgaW4gbWFueSBjYXNlcy4gCm4gPSA1LjVNLiAKCmBgYHtyIHVwbG9hZCBPUkd9CmlwdW1zX29yZyA8LSBmcmVhZCgifi9Ecm9wYm94L1dGSC9FbXBpcmljYWwgd29yay9EYXRhL0lQVU1TIENQUyBPUkcvaXB1bXNfb3JnLmNzdiIpCgpgYGAKCmBgYHtyfQojIEluaXRpYWwgY2xlYW51cCBhbmQgdmFyaWFibGUgY29uc3RydWN0aW9uCmlwdW1zX29yZyA8LSBpcHVtc19vcmcgJT4lCiAgZmlsdGVyKEFHRSA+PSAyNSwgQUdFIDw9IDY1KSAlPiUKICBmaWx0ZXIoVUhSU1dPUksxID4gMTAgJiBVSFJTV09SSzEgPCAxMDApICU+JQogIGZpbHRlcihDTEFTU1dLUiA+PSAyMCAmIENMQVNTV0tSICE9IDk5KQoKCiMgVXNlIGN1dCB0byBjcmVhdGUgdGhlIGJpbnMKYmluX2JyZWFrcyA8LSBjKHNlcSgxMCwgODAsIGJ5ID0gNSkpCmJpbl9sYWJlbHMgPC0gYygiMTAtMTQiLCIxNS0xOSIsIjIwLTI0IiwiMjUtMjkiLCIzMC0zNCIsICIzNS0zOSIsICI0MC00NCIsICI0NS00OSIsICI1MC01NCIsICI1NS01OSIsICI2MC02NCIsICI2NS02OSIsICI3MC03NCIsICI3NS03OSIsICI4MCsiKQoKaXB1bXNfb3JnIDwtIGlwdW1zX29yZyAlPiUKICBtdXRhdGUoQUdFMiA9IEFHRSAqIEFHRSwKICAgICAgICAgSE9VUldBR0VfY29tcHV0ZWQgPSBFQVJOV0VFSyAvIFVIUlNXT1JLMSwgIAogICAgICAgICBsbl9ocndhZ2UgPSBsb2coSE9VUldBR0VfY29tcHV0ZWQpLAogICAgICAgICBiaW4gPSBhcy5mYWN0b3IoY3V0KFVIUlNXT1JLMSwgYnJlYWtzID0gYyhiaW5fYnJlYWtzLCBJbmYpLCByaWdodCA9IEZBTFNFLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxhYmVscyA9IE5VTEwpKSwKICAgICAgICAgc2FsYXJpZWQgPSBQQUlESE9VUiA9PSAxKQpgYGAKCkJlbG93IEkgcmVwbGljYXRlIGEgcGxvdCBmcm9tIEJpY2sgZXQuIGFsLiAoUUpFIDIwMjIpIHRvIGFzc3VyZSBkYXRhIGNsZWFuaW5nIGlzIGNvcnJlY3QuIFRoaXMgcGxvdCBpbmNsdWRlcyBib3RoIHRoZSBkaXN0cmlidXRpb24gb2YgaG91cnMgd29ya2VkIGFuZCB0aGUgY29lZmZpY2llbnRzIG9mIGxvZyB3YWdlcyBvbiBhIHNldCBvZiBiaW5zIG9mIGhvdXJzIGZvciBtZW4sIGNvbnRyb2xsaW5nIGZvciBlZHVjYXRpb24sIG1hcml0YWwgc3RhdHVzLCB1bmlvbiBzdGF0dXMsIHJhY2UgYXMgd2VsbCBhcyB5ZWFyIGFuZCBtb250aCBmaXhlZCBlZmZlY3QgZm9yIHRoZSB5ZWFycyAxOTk1LTIwMDcuIApgYGB7cn0KYmlja19ldF9hbF9kYXRhIDwtIGlwdW1zX29yZyAlPiUKICBmaWx0ZXIoWUVBUiA+PSAxOTk1ICYgWUVBUiA8PSAyMDA3KSAlPiUKICBmaWx0ZXIoU0VYID09IDEpICU+JQogIGZpbHRlcihNVUxUSk9CID09IDEpICMgbm90IG11bHRpam9iYmVkCiAgCmZvcm11bGFfYmlucyA8LSBhcy5mb3JtdWxhKCJsbl9ocndhZ2UgfiBiaW4gKyBBR0UgKyBBR0UyICsgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBmYWN0b3IoTUFSU1QpICsgZmFjdG9yKEVEVUMpICsgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBmYWN0b3IoUkFDRSkgKyBmYWN0b3IoWUVBUikgKyBmYWN0b3IoTU9OVEgpICsgVU5JT04gLSAxIikgCgpjb21iaW5lZChiaWNrX2V0X2FsX2RhdGEsIHdlaWdodF92YXIgPSAiRUFSTldUIiwgdGl0bGUgPSBOVUxMLCBmaWxlbmFtZSA9IE5VTEwsIGJpbl92YXIgPSAiYmluIiwgZm9ybXVsYSA9IGZvcm11bGFfYmlucywgcGxvdCA9IFRSVUUpCgpgYGAKCk5vdyBJIGxvb2sgYXQgYSBhZ2dyZWdhdGUgdHJlbmRzIGluIGhvdXJzIHdvcmtlZCBvdmVyIHRpbWUuIEZpcnN0LCB3aGlsZSB3b21lbiBoYXZlIGNvbnNpc3RlbnRseSBpbmNyZWFzZWQgdGhlaXIgd29ya2luZyBob3VycywgbWVuJ3Mgd29ya2luZyBob3VycyBoYXZlIGRlY3JlYXNlZCBzbGlnaGx0eS4KYGBge3J9CnN1bW1hcnlfYnlfeWVhcl9zZXggPC0gaXB1bXNfb3JnICU+JSAKICBncm91cF9ieShZRUFSLCBTRVgpICU+JSAKICBzdW1tYXJpc2UobWVhbl9ob3VycyA9IHdlaWdodGVkLm1lYW4oVUhSU1dPUksxLCBFQVJOV1QpLAogICAgICAgICAgICBzaGFyZV9sZXNzXzQwID0gd2VpZ2h0ZWQubWVhbihVSFJTV09SSzEgPCA0MCwgRUFSTldUKSwKICAgICAgICAgICAgc2hhcmVfZXhhY2N0bHlfNDAgPSB3ZWlnaHRlZC5tZWFuKFVIUlNXT1JLMSA9PSA0MCwgRUFSTldUKSwKICAgICAgICAgICAgc2hhcmVfYWJvdmVfNDAgPSB3ZWlnaHRlZC5tZWFuKFVIUlNXT1JLMSA+IDQwLCBFQVJOV1QpLCAuZ3JvdXBzID0gImRyb3AiKQoKc3VtbWFyeV9ieV95ZWFyX3NleCAlPiUKICBnZ3Bsb3QoYWVzKHggPSBZRUFSLCB5ID0gbWVhbl9ob3VycywgY29sb3IgPSBmYWN0b3IoU0VYKSkpICsKICBnZW9tX3BvaW50KHNpemUgPSAwLjUpICsgICAgICAgICAgICAgICAgIyBBZGp1c3QgcG9pbnQgc2l6ZQogIGdlb21fbGluZShzaXplID0gMC41KSArICAgICAgICAgICAgICAgICAjIEFkanVzdCBsaW5lIHRoaWNrbmVzcwogIHNjYWxlX2NvbG9yX2JyZXdlcihwYWxldHRlID0gIlNldDIiLCAgIyBOaWNlciBjb2xvcnMKICAgICAgICAgICAgICAgICAgICAgbGFiZWxzID0gYygiTWFsZSIsICJGZW1hbGUiKSkgKyAKICBsYWJzKHRpdGxlID0gIk1lYW4gSG91cnMgV29ya2VkIE92ZXIgVGltZSIsCiAgICAgICB4ID0gIlllYXIiLAogICAgICAgeSA9ICJNZWFuIEhvdXJzIFdvcmtlZCIsCiAgICAgICBjb2xvciA9ICJTZXgiKSArICAgICAgICAgICAgICAgICMgVXBkYXRlIGxlZ2VuZCB0aXRsZQogIHRoZW1lX21pbmltYWwoKSAgICAgICAgICAgICAgICAgICAgICAjIENsZWFuIHRoZW1lCgoKYGBgCmBgYHtyfQpwbG90X2Rpc3RfNDAoaXB1bXNfb3JnLCBVSFJTV09SSzEsIEVBUk5XVCwgImFsbCBXb3JrZXJzLCBDUFMtT1JHIikKcGxvdF9kaXN0XzQwKGlwdW1zX29yZyAlPiUgZmlsdGVyKFNFWCA9PSAxKSwgVUhSU1dPUksxLCBFQVJOV1QsICJNZW4sIENQUy1PUkciKQpwbG90X2Rpc3RfNDAoaXB1bXNfb3JnICU+JSBmaWx0ZXIoU0VYID09IDIpLCBVSFJTV09SSzEsIEVBUk5XVCwgIldvbWVuLCBDUFMtT1JHIikKCmBgYApOb3cgSSBsb29rIGF0IGhvdyB0aGlzIGNoYW5nZWQgYWNyb3NzIHdlZWtseSBlYXJuaW5ncyBkZWNpbGVzOiAKCmBgYHtyfQppcHVtc19vcmcgPC0gYWRkX3dlaWdodGVkX2RlY2lsZV9ieV95ZWFyKGlwdW1zX29yZywgIkVBUk5XRUVLIiwgIkVBUk5XVCIsICJZRUFSIikKCmZvciAoaSBpbiAxOjEwKXsKICBwbG90X2Rpc3RfNDAoaXB1bXNfb3JnICU+JSBmaWx0ZXIoRUFSTldFRUtfZGVjaWxlID09IGkpLFVIUlNXT1JLMSwgRUFSTldULCBwYXN0ZTAoImFsbCBXb3JrZXJzLCAiLGksInRoIGRlY2lsZSIpKQp9CmBgYApCZWxvdywgSSBwbG90IHRoZSBtZWFuIG9mIGhvdXJzIHdvcmtlZCBieSBkZWNpbGU6IAotIFRoZXJlIHNlZW1zIHRvIGJlIHNvbWV0aGluZyB3ZWlyZCBhYm91dCBkYXRhIGZyb20gMjAyMy0yMDI0Ci0gVGhlIE1lbm90b3ZhbmkgZmFjdCAoRDEgZ29pbmcgZG93biwgRDEwIGdvaW5nIGRvd24pIGRvZXMgbm90IHJlcGxpY2F0ZQoKYGBge3J9CnBsb3RfdjFfbWVhbl9ieV92Ml9kZWNpbGVfb3Zlcl92MyhpcHVtc19vcmcsICJVSFJTV09SSzEiLCAiRUFSTldFRUsiLCAiWUVBUiIsICJFQVJOV1QiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29sb3JfbGFiID0gIkVBUk5XRUVLIERlY2lsZSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXB0aW9uID0gIlNvdXJjZTogQ1BTLU9SRyBJUFVNUyIpCgpwbG90X3YxX21lYW5fYnlfdjJfZGVjaWxlX292ZXJfdjMoaXB1bXNfb3JnLCAiVUhSU1dPUksxIiwgIkhPVVJXQUdFX2NvbXB1dGVkIiwgIllFQVIiLCAiRUFSTldUIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhcHRpb24gPSAiU291cmNlOiBDUFMtT1JHIElQVU1TIikKCnBsb3RfdjFfbWVhbl9ieV92Ml9kZWNpbGVfb3Zlcl92MyhpcHVtc19vcmcsICJVSFJTV09SSzEiLCAiSE9VUldBR0VfY29tcHV0ZWQiLCAiWUVBUiIsICJFQVJOV1QiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmlsdGVyX2V4cHIgPSBzYWxhcmllZCA9PSAxLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FwdGlvbiA9ICJTb3VyY2U6IENQUy1PUkcgSVBVTVMiKQoKcGxvdF92MV9tZWFuX2J5X3YyX2RlY2lsZV9vdmVyX3YzKGlwdW1zX29yZywgIlVIUlNXT1JLMSIsICJIT1VSV0FHRV9jb21wdXRlZCIsICJZRUFSIiwgIkVBUk5XVCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmaWx0ZXJfZXhwciA9IHNhbGFyaWVkID09IDEsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXB0aW9uID0gIlNvdXJjZTogQ1BTLU9SRyBJUFVNUyIsIGRlY2lsZXNfdG9fcGxvdCA9IGMoMSw1LDEwKSkKCnBsb3RfdjFfbWVhbl9ieV92Ml9kZWNpbGVfb3Zlcl92MyhpcHVtc19vcmcsICJVSFJTV09SSzEiLCAiSE9VUldBR0VfY29tcHV0ZWQiLCAiWUVBUiIsICJFQVJOV1QiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmlsdGVyX2V4cHIgPSBzYWxhcmllZCA9PSAwLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FwdGlvbiA9ICJTb3VyY2U6IENQUy1PUkcgSVBVTVMiKQoKcGxvdF92MV9tZWFuX2J5X3YyX2RlY2lsZV9vdmVyX3YzKGlwdW1zX29yZywgIlVIUlNXT1JLMSIsICJIT1VSV0FHRSIsICJZRUFSIiwgIkVBUk5XVCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmaWx0ZXJfZXhwciA9IHNhbGFyaWVkID09IDAsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXB0aW9uID0gIlNvdXJjZTogQ1BTLU9SRyBJUFVNUyIpCgpob3VybHlfd29ya2VycyA8LSBiaWNrX2V0X2FsX2RhdGEgJT4lIGZpbHRlcihzYWxhcmllZCA9PSAwKSAlPiUgZmlsdGVyKCFpcy5uYShIT1VSV0FHRSkpCmNvcihob3VybHlfd29ya2VycyRIT1VSV0FHRV9jb21wdXRlZCwgaG91cmx5X3dvcmtlcnMkSE9VUldBR0UpCmBgYAoKCgojIENQUy1NT1JHIGZyb20gQ0VQUgoKSSBhbHNvIHRyaWVkIHRvIHJlcGxpY2F0ZSB0aGUgTWFudG92YW5pIHBsb3QgZnJvbSBDRVBSIENQUy1NT1JHIGRhdGEgdGhhdCBoZSBzdGF0ZXMgaGUgdXNlZCBidXQgdGhlIHJlc3VsdHMgYXJlIHZlcnkgd2VpcmQuIEkgYW0gbm90IHN1cmUgd2hpY2ggdmFyaWFibGVzIGhlIHVzZWQuIApgYGB7cn0KT1JHIDwtIGZyZWFkKHBhc3RlMChkaXIsIi9kYXRhL0NFUFIvY2Vwcl9kYXRhLmNzdiIpKQojIFVuZGVyc3RhbmRpbmcgdGhlIGRhdGEKT1JHIDwtIE9SRyAlPiUKICBtdXRhdGUoaG91cmx5X3dvcmtlciA9ICFpcy5uYSh3YWdlMSksCiAgICAgICAgIHNhbGFyaWVkX3dvcmtlciA9ICFpcy5uYSh3YWdlMikpCgpPUkcgPC0gT1JHICU+JSBmaWx0ZXIoIWlzLm5hKHVob3Vyc2UpKQoKT1JHIDwtIE9SRyAlPiUgbXV0YXRlKGxvZ193YWdlMyA9IGxvZyh3YWdlMyksCiAgICAgICAgICAgICAgICAgICAgICBsb2dfdWhvdXJzdyA9IGxvZyh1aG91cnNlKSwgYWdlX3NxID0gYWdlKmFnZSkKIyBhIDwtIGZlb2xzKGxvZ191aG91cnN3IH4gbG9nX3dhZ2UzLCBkYXRhID0gT1JHICU+JSBmaWx0ZXIod2FnZTM+IDAsIHVob3Vyc2UgPjApLCB3ZWlnaHRzID0gfmZubHdndCwgZnNwbGl0ID0gfnllYXIpCgpgYGAKCgpgYGB7cn0KcGxvdF91aG91cnNlX21lYW5fYnlfd2FnZTNfZGVjaWxlX292ZXJfeWVhcl9DUFNPUkcgPC0gZnVuY3Rpb24oZmlsdGVyX2V4cHIpewogIHBsb3RfdjFfbWVhbl9ieV92Ml9kZWNpbGVfb3Zlcl92MyhPUkcsICJ1aG91cnNlIiwgIndhZ2UzIiwgInllYXIiLCAiZm5sd2d0IiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZpbHRlcl9leHByID0gISFlbnF1byhmaWx0ZXJfZXhwciksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXB0aW9uID0gIlNvdXJjZTogQ1BTLU9SRyIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApCn0KCnBsb3RfdWhvdXJzZV9tZWFuX2J5X3dhZ2UzX2RlY2lsZV9vdmVyX3llYXJfQ1BTT1JHKHVob3Vyc2UgPiAzNSkKcGxvdF91aG91cnNlX21lYW5fYnlfd2FnZTNfZGVjaWxlX292ZXJfeWVhcl9DUFNPUkcodWhvdXJzZSA+IDM1ICYgc2FsYXJpZWRfd29ya2VyID09IDEpCnBsb3RfdWhvdXJzZV9tZWFuX2J5X3dhZ2UzX2RlY2lsZV9vdmVyX3llYXJfQ1BTT1JHKHVob3Vyc2UgPiAzNSAmIGhvdXJseV93b3JrZXIgPT0gMSkKcGxvdF91aG91cnNlX21lYW5fYnlfd2FnZTNfZGVjaWxlX292ZXJfeWVhcl9DUFNPUkcodWhvdXJzZSA+IDEwKQpwbG90X3Vob3Vyc2VfbWVhbl9ieV93YWdlM19kZWNpbGVfb3Zlcl95ZWFyX0NQU09SRyh1aG91cnNlID4gMTAgJiBzYWxhcmllZF93b3JrZXIgPT0gMSkKcGxvdF91aG91cnNlX21lYW5fYnlfd2FnZTNfZGVjaWxlX292ZXJfeWVhcl9DUFNPUkcodWhvdXJzZSA+IDEwICYgaG91cmx5X3dvcmtlciA9PSAxKQoKCmBgYApOb3RlIHRoYXQgYWJydXB0IGNoYW5nZXMgaW4gdGhlIHRvcGNvZGUgb2NjdXJyZWQgaW4gMTk4OSBhbmQgMTk5OCwgSSBhbSBub3Qgc3VyZSB3aGF0IGhhcHBlbmVkIGluIDE5OTQuCgoKIyMgQVNFQwpJIGNvbmR1Y3RlZCBhIHNpbWlsYXIgYW5hbHlzaXMgZm9yIEFTRUMgZGF0YSwgZm9yIHRoZSB5ZWFycyAxOTYyLTIwMjQsIHdvcmtlcnMgb2YgYWdlcyAyNS02NS4KQVNFQyBhc2tzIHJlc3BvbmRlbnRzIGJvdGggcmVnYXJkaW5nIGFjdHVhbCBob3VycyB3b3JrZWQgbGFzdCB3ZWVrIGFuZCBvbiB1c3VhbCBob3VyIHdvcmtlZCBsYXN0IHllYXIuIApJbmNvbWUgaXMgZG9jdW1lbnRlZCBvbmx5IGF0IGFuIGFubnVhbCBiYXNpcyAtIGZvciB0aGUgcHJldmlvdXMgY2FsYW5kZXIgeWVhci4KClRoaXMgZG9jdW1lbnQgZmlyc3QgcGxvdHMgcGF0dGVybnMgd2l0aCBhbm51YWwgaW5jb21lIGFuZCB0aGVuIHVzZXMgYW4gZXN0aW1hdGUgb2YgaG91cmx5IHdhZ2VzIGNvbnN0cnVjdGVkIGJ5IGRpdmlkaW5nIHRoZSBhbm51YWwgaW5jb21lIGJ5ICgjIHdlZWtzIHBlciB5ZWFyIFggIyBob3VycyBwZXIgd2Vlay4pIAoKbiA9IDM2OTY0MDEKYGBge3J9CmFzZWMgPC0gZnJlYWQocGFzdGUwKGRpciwiL2RhdGEvQ1BTX2xvbmdfdGVybS9BU0VDL0FTRUNfNjJfMjQuY3N2IikpCgphc2VjIDwtIGFzZWMgJT4lCiAgZmlsdGVyKEFHRSA+PSAyNSAmIEFHRSA8PSA2NSwKICAgICAgICAgSU5DV0FHRSA+IDAsCiAgICAgICAgIElOQ1dBR0UgIT0gOTk5OTk5OTgsICMgbWlzc2luZwogICAgICAgICBJTkNXQUdFICE9IDk5OTk5OTk5KSAgIyBOSVUgCgphc2VjX3dvcmtlZF9MWSA8LSBhc2VjICU+JSBmaWx0ZXIoVUhSU1dPUktMWSAhPSA5OTkpCmFzZWNfd29ya2VkX0xXIDwtIGFzZWMgJT4lIGZpbHRlcihBSFJTV09SS1QgIT0gOTk5KQpgYGAKCmBgYHtyfQpzdW1tYXJ5X2J5X3llYXJfc2V4X2FzZWMgPC0gYXNlY193b3JrZWRfTFkgJT4lIAogIGdyb3VwX2J5KFlFQVIsIFNFWCkgJT4lIAogIHN1bW1hcmlzZShtZWFuX2hvdXJzID0gd2VpZ2h0ZWQubWVhbihVSFJTV09SS0xZLCBBU0VDV1QpLAogICAgICAgICAgICBzaGFyZV9sZXNzXzQwID0gd2VpZ2h0ZWQubWVhbihVSFJTV09SS0xZIDwgNDAsIEFTRUNXVCksCiAgICAgICAgICAgIHNoYXJlX2V4YWNjdGx5XzQwID0gd2VpZ2h0ZWQubWVhbihVSFJTV09SS0xZID09IDQwLCBBU0VDV1QpLAogICAgICAgICAgICBzaGFyZV9hYm92ZV80MCA9IHdlaWdodGVkLm1lYW4oVUhSU1dPUktMWSA+IDQwLCBBU0VDV1QpLCAuZ3JvdXBzID0gImRyb3AiKQoKc3VtbWFyeV9ieV95ZWFyX3NleF9hc2VjICU+JQogIGdncGxvdChhZXMoeCA9IFlFQVIsIHkgPSBtZWFuX2hvdXJzLCBjb2xvciA9IGZhY3RvcihTRVgpKSkgKwogIGdlb21fcG9pbnQoc2l6ZSA9IDAuNSkgKyAgICAgICAgICAgICAgICAjIEFkanVzdCBwb2ludCBzaXplCiAgZ2VvbV9saW5lKHNpemUgPSAwLjUpICsgICAgICAgICAgICAgICAgICMgQWRqdXN0IGxpbmUgdGhpY2tuZXNzCiAgc2NhbGVfY29sb3JfYnJld2VyKHBhbGV0dGUgPSAiU2V0MiIsICAjIE5pY2VyIGNvbG9ycwogICAgICAgICAgICAgICAgICAgICBsYWJlbHMgPSBjKCJNYWxlIiwgIkZlbWFsZSIpKSArIAogIGxhYnModGl0bGUgPSAiTWVhbiBIb3VycyBXb3JrZWQgTGFzdCBZZWFyIE92ZXIgVGltZSwgQVNFQyIsCiAgICAgICB4ID0gIlllYXIiLAogICAgICAgeSA9ICJNZWFuIEhvdXJzIFdvcmtlZCIsCiAgICAgICBjb2xvciA9ICJTZXgiKSArICAgICAgICAgICAgICAgICMgVXBkYXRlIGxlZ2VuZCB0aXRsZQogIHRoZW1lX21pbmltYWwoKSAgICAgICAgICAgICAgICAgICAgICAjIENsZWFuIHRoZW1lCgoKYGBgCmBgYHtyfQpwbG90X2Rpc3RfNDAoYXNlY193b3JrZWRfTFksIFVIUlNXT1JLTFksIEFTRUNXVCwgImFsbCBXb3JrZXJzLCBBU0VDIikKcGxvdF9kaXN0XzQwKGFzZWNfd29ya2VkX0xZICU+JSBmaWx0ZXIoU0VYID09IDEpLCBVSFJTV09SS0xZLCBBU0VDV1QsICJNZW4sIEFTRUMiKQpwbG90X2Rpc3RfNDAoYXNlY193b3JrZWRfTFkgJT4lIGZpbHRlcihTRVggPT0gMiksIFVIUlNXT1JLTFksIEFTRUNXVCwgIldvbWVuLCBBU0VDIikKCmBgYApgYGB7cn0KcGxvdF92MV9tZWFuX2J5X3YyX2RlY2lsZV9vdmVyX3YzKGFzZWNfd29ya2VkX0xZLCAiVUhSU1dPUktMWSIsICJJTkNXQUdFIiwgIllFQVIiLCAiQVNFQ1dUIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRpdGxlID0gIlVzdWFsIEhvdXJzIFdvcmtlZCBMYXN0IFllYXIgb3ZlciBBbm51YWwgSW5jb21lLCBhbGwgV29ya2VycyIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXB0aW9uID0gIlNvdXJjZTogQVNFQyAxOTc2LTIwMjQiKQpwbG90X3YxX21lYW5fYnlfdjJfZGVjaWxlX292ZXJfdjMoYXNlY193b3JrZWRfTFksICJVSFJTV09SS0xZIiwgIklOQ1dBR0UiLCAiWUVBUiIsICJBU0VDV1QiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGVjaWxlc190b19wbG90ID0gYygxLCA1LCAxMCksIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGl0bGUgPSAiVXN1YWwgSG91cnMgV29ya2VkIExhc3QgWWVhciBvdmVyIEFubnVhbCBJbmNvbWUsIGFsbCBXb3JrZXJzIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhcHRpb24gPSAiU291cmNlOiBBU0VDIDE5NzYtMjAyNCIpCgpgYGAKYGBge3IsIGVjaG8gPSBGQUxTRSwgbWVzc2FnZSA9IEZBTFNFLCB3YXJuaW5nID0gRkFMU0UsIHJlc3VsdHM9J2hpZGUnfQpwbG90X3YxX21lYW5fYnlfdjJfZGVjaWxlX292ZXJfdjMoYXNlY193b3JrZWRfTFcsICJBSFJTV09SS1QiLCAiSU5DV0FHRSIsICJZRUFSIiwgIkFTRUNXVCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aXRsZSA9ICJIb3VycyBXb3JrZWQgTGFzdCBXZWVrIG92ZXIgQW5udWFsIEluY29tZSwgYWxsIFdvcmtlcnMiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FwdGlvbiA9ICJTb3VyY2U6IEFTRUMiKQpwbG90X3YxX21lYW5fYnlfdjJfZGVjaWxlX292ZXJfdjMoYXNlY193b3JrZWRfTFcsICJBSFJTV09SS1QiLCAiSU5DV0FHRSIsICJZRUFSIiwgIkFTRUNXVCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkZWNpbGVzX3RvX3Bsb3QgPSBjKDEsIDUsIDEwKSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aXRsZSA9ICJIb3VycyBXb3JrZWQgTGFzdCBXZWVrIG92ZXIgQW5udWFsIEluY29tZSwgYWxsIFdvcmtlcnMiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FwdGlvbiA9ICJTb3VyY2U6IEFTRUMiKQoKCgpgYGAKTm93LCBsaW1pdCBhdHRlbnRpb24gdG8gd29ya2VycyB0aGF0IHdvcmtlZCA1MC01MiB3ZWVrcyBwZXIgd2VlawoKYGBge3J9CmFzZWNfd29ya2VkX0xZX2Z1bGwgPC0gYXNlY193b3JrZWRfTFkgJT4lIGZpbHRlcihXS1NXT1JLMiA9PSA2KSAKcGxvdF92MV9tZWFuX2J5X3YyX2RlY2lsZV9vdmVyX3YzKGFzZWNfd29ya2VkX0xZX2Z1bGwsICJVSFJTV09SS0xZIiwgIklOQ1dBR0UiLCAiWUVBUiIsICJBU0VDV1QiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGl0bGUgPSAiVXN1YWwgSG91cnMgV29ya2VkIExhc3QgWWVhciBvdmVyIEFubnVhbCBJbmNvbWUsIDUwLTUyIHdlZWtzIHdvcmtlZCBsYXN0IHllYXIiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FwdGlvbiA9ICJTb3VyY2U6IEFTRUMgMTk3Ni0yMDI0IikKcGxvdF92MV9tZWFuX2J5X3YyX2RlY2lsZV9vdmVyX3YzKGFzZWNfd29ya2VkX0xZX2Z1bGwsICJVSFJTV09SS0xZIiwgIklOQ1dBR0UiLCAiWUVBUiIsICJBU0VDV1QiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGVjaWxlc190b19wbG90ID0gYygxLCA1LCAxMCksIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGl0bGUgPSAiVXN1YWwgSG91cnMgV29ya2VkIExhc3QgWWVhciBvdmVyIEFubnVhbCBJbmNvbWUsIDUwLTUyIHdlZWtzIHdvcmtlZCBsYXN0IHllYXIiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FwdGlvbiA9ICJTb3VyY2U6IEFTRUMgMTk3Ni0yMDI0IikKYGBgCmBgYHtyfQpwbG90X3YxX21lYW5fYnlfdjJfZGVjaWxlX292ZXJfdjMoYXNlY193b3JrZWRfTFlfZnVsbCAlPiUgbXV0YXRlKGhfd2FnZV91c3VhbCA9IElOQ1dBR0UgLyA1MSAvIFVIUlNXT1JLTFkpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIlVIUlNXT1JLTFkiLCAiaF93YWdlX3VzdWFsIiwgIllFQVIiLCAiQVNFQ1dUIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRpdGxlID0gIlVzdWFsIEhvdXJzIFdvcmtlZCBMYXN0IFllYXIgYnkgQ29tcHV0ZWQgSG91cmx5IFdhZ2UsIDUwLTUyIHdlZWtzIHdvcmtlZCBsYXN0IHllYXIiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FwdGlvbiA9ICJTb3VyY2U6IEFTRUMuIE5vdGU6IGNvbXB1dGVkIGhvdXJseSB3YWdlID0gYW5udWFsIGluY29tZSAvIDUxIC8gdXN1YWwgaG91cnMgd29ya2VkIGxhc3QgeWVhciIpCnBsb3RfdjFfbWVhbl9ieV92Ml9kZWNpbGVfb3Zlcl92Myhhc2VjX3dvcmtlZF9MWV9mdWxsICU+JSBtdXRhdGUoaF93YWdlX3VzdWFsID0gSU5DV0FHRSAvIDUxIC8gVUhSU1dPUktMWSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiVUhSU1dPUktMWSIsICJoX3dhZ2VfdXN1YWwiLCAiWUVBUiIsICJBU0VDV1QiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGVjaWxlc190b19wbG90ID0gYygxLCA1LCAxMCksIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGl0bGUgPSAiVXN1YWwgSG91cnMgV29ya2VkIExhc3QgWWVhciBieSBDb21wdXRlZCBIb3VybHkgV2FnZSwgNTAtNTIgd2Vla3Mgd29ya2VkIGxhc3QgeWVhciIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXB0aW9uID0gIlNvdXJjZTogQVNFQy4gTm90ZTogY29tcHV0ZWQgaG91cmx5IHdhZ2UgPSBhbm51YWwgaW5jb21lIC8gNTEgLyB1c3VhbCBob3VycyB3b3JrZWQgbGFzdCB5ZWFyIikKYGBgCk5vdywgTGltaXQgYXR0ZW50aW9uIHRvIHdvcmtlcnMgd2l0aCBtb3JlIHRoYW4gNDAgaG91cnMgd29ya2VkIG9uIHVzdWFsIHdlZWtzCgpgYGB7cn0KcGxvdF92MV9tZWFuX2J5X3YyX2RlY2lsZV9vdmVyX3YzKGFzZWNfd29ya2VkX0xZICU+JSBmaWx0ZXIoV0tTV09SSzIgPT0gNikgJT4lIGZpbHRlcihVSFJTV09SS0xZID49IDQwKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJVSFJTV09SS0xZIiwgIklOQ1dBR0UiLCAiWUVBUiIsICJBU0VDV1QiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGl0bGUgPSAiVXN1YWwgSG91cnMgV29ya2VkIExhc3QgWWVhciBvdmVyIEFubnVhbCBJbmNvbWUsXG41MC01MiB3ZWVrcyB3b3JrZWQgbGFzdCB5ZWFyLCA+PSA0MGggcGVyIHVzdWFsIHdlZWsiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FwdGlvbiA9ICJTb3VyY2U6IEFTRUMgMTk3Ni0yMDI0IikKcGxvdF92MV9tZWFuX2J5X3YyX2RlY2lsZV9vdmVyX3YzKGFzZWNfd29ya2VkX0xZICU+JSBmaWx0ZXIoV0tTV09SSzIgPT0gNikgJT4lIGZpbHRlcihVSFJTV09SS0xZID49IDQwKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJVSFJTV09SS0xZIiwgIklOQ1dBR0UiLCAiWUVBUiIsICJBU0VDV1QiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGVjaWxlc190b19wbG90ID0gYygxLCA1LCAxMCksIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGl0bGUgPSAiVXN1YWwgSG91cnMgV29ya2VkIExhc3QgWWVhciBvdmVyIEFubnVhbCBJbmNvbWUsXG41MC01MiB3ZWVrcyB3b3JrZWQgbGFzdCB5ZWFyLCA+PSA0MGggcGVyIHVzdWFsIHdlZWsiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FwdGlvbiA9ICJTb3VyY2U6IEFTRUMgMTk3Ni0yMDI0IikKYGBgCgoKYGBge3J9CnBsb3RfdjFfbWVhbl9ieV92Ml9kZWNpbGVfb3Zlcl92Myhhc2VjX3dvcmtlZF9MWSAlPiUgZmlsdGVyKFdLU1dPUksyID09IDYpICU+JSBmaWx0ZXIoVUhSU1dPUktMWSA+PSA0MCkgJT4lIG11dGF0ZShoX3dhZ2VfdXN1YWwgPSBJTkNXQUdFIC8gNTEgLyBVSFJTV09SS0xZKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJVSFJTV09SS0xZIiwgImhfd2FnZV91c3VhbCIsICJZRUFSIiwgIkFTRUNXVCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aXRsZSA9ICJVc3VhbCBIb3VycyBXb3JrZWQgTGFzdCBZZWFyIGJ5IENvbXB1dGVkIEhvdXJseSBXYWdlLFxuNTAtNTIgd2Vla3Mgd29ya2VkIGxhc3QgeWVhciwgPj0gNDAgaG91cnMgcGVyIHVzdWFsIHdlZWsiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FwdGlvbiA9ICJTb3VyY2U6IEFTRUMuIE5vdGU6IGNvbXB1dGVkIGhvdXJseSB3YWdlID0gYW5udWFsIGluY29tZSAvIDUxIC8gdXN1YWwgaG91cnMgd29ya2VkIGxhc3QgeWVhciIpCnBsb3RfdjFfbWVhbl9ieV92Ml9kZWNpbGVfb3Zlcl92Myhhc2VjX3dvcmtlZF9MWSAlPiUgZmlsdGVyKFdLU1dPUksyID09IDYpICU+JSBmaWx0ZXIoVUhSU1dPUktMWSA+PSA0MCkgJT4lIG11dGF0ZShoX3dhZ2VfdXN1YWwgPSBJTkNXQUdFIC8gNTEgLyBVSFJTV09SS0xZKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJVSFJTV09SS0xZIiwgImhfd2FnZV91c3VhbCIsICJZRUFSIiwgIkFTRUNXVCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkZWNpbGVzX3RvX3Bsb3QgPSBjKDEsIDUsIDEwKSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aXRsZSA9ICJVc3VhbCBIb3VycyBXb3JrZWQgTGFzdCBZZWFyIGJ5IENvbXB1dGVkIEhvdXJseSBXYWdlLFxuNTAtNTIgd2Vla3Mgd29ya2VkIGxhc3QgeWVhciwgID49IHRoYW4gNDAgaG91cnMgcGVyIHVzdWFsIHdlZWsiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FwdGlvbiA9ICJTb3VyY2U6IEFTRUMuIE5vdGU6IGNvbXB1dGVkIGhvdXJseSB3YWdlID0gYW5udWFsIGluY29tZSAvIDUxIC8gdXN1YWwgaG91cnMgd29ya2VkIGxhc3QgeWVhciIpCmBgYApgYGB7cn0KcGxvdF92MV9tZWFuX2J5X3YyX2RlY2lsZV9vdmVyX3YzKGFzZWNfd29ya2VkX0xZICU+JSBmaWx0ZXIoV0tTV09SSzIgPT0gNikgJT4lIGZpbHRlcihVSFJTV09SS0xZID49IDM1KSAlPiUgbXV0YXRlKGhfd2FnZV91c3VhbCA9IElOQ1dBR0UgLyA1MSAvIFVIUlNXT1JLTFkpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIlVIUlNXT1JLTFkiLCAiaF93YWdlX3VzdWFsIiwgIllFQVIiLCAiQVNFQ1dUIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRpdGxlID0gIlVzdWFsIEhvdXJzIFdvcmtlZCBMYXN0IFllYXIgYnkgQ29tcHV0ZWQgSG91cmx5IFdhZ2UsXG41MC01MiB3ZWVrcyB3b3JrZWQgbGFzdCB5ZWFyLCA+PSAzNSBob3VycyBwZXIgdXN1YWwgd2VlayIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXB0aW9uID0gIlNvdXJjZTogQVNFQy4gTm90ZTogY29tcHV0ZWQgaG91cmx5IHdhZ2UgPSBhbm51YWwgaW5jb21lIC8gNTEgLyB1c3VhbCBob3VycyB3b3JrZWQgbGFzdCB5ZWFyIikKcGxvdF92MV9tZWFuX2J5X3YyX2RlY2lsZV9vdmVyX3YzKGFzZWNfd29ya2VkX0xZICU+JSBmaWx0ZXIoV0tTV09SSzIgPT0gNikgJT4lIGZpbHRlcihVSFJTV09SS0xZID49IDM1KSAlPiUgbXV0YXRlKGhfd2FnZV91c3VhbCA9IElOQ1dBR0UgLyA1MSAvIFVIUlNXT1JLTFkpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIlVIUlNXT1JLTFkiLCAiaF93YWdlX3VzdWFsIiwgIllFQVIiLCAiQVNFQ1dUIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRlY2lsZXNfdG9fcGxvdCA9IGMoMSwgNSwgMTApLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRpdGxlID0gIlVzdWFsIEhvdXJzIFdvcmtlZCBMYXN0IFllYXIgYnkgQ29tcHV0ZWQgSG91cmx5IFdhZ2UsXG41MC01MiB3ZWVrcyB3b3JrZWQgbGFzdCB5ZWFyLCA+PSAzNSBob3VycyBwZXIgdXN1YWwgd2VlayIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXB0aW9uID0gIlNvdXJjZTogQVNFQy4gTm90ZTogY29tcHV0ZWQgaG91cmx5IHdhZ2UgPSBhbm51YWwgaW5jb21lIC8gNTEgLyB1c3VhbCBob3VycyB3b3JrZWQgbGFzdCB5ZWFyIikKYGBgCgoKYGBge3J9CnBsb3RfdjFfbWVhbl9ieV92Ml9kZWNpbGVfb3Zlcl92Myhhc2VjX3dvcmtlZF9MWSAlPiUgZmlsdGVyKFdLU1dPUksyID09IDYsIFVIUlNXT1JLTFkgPj0gNDAsIFNFWCA9PSAxKSAlPiUgbXV0YXRlKGhfd2FnZV91c3VhbCA9IElOQ1dBR0UgLyA1MSAvIFVIUlNXT1JLTFkpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIlVIUlNXT1JLTFkiLCAiaF93YWdlX3VzdWFsIiwgIllFQVIiLCAiQVNFQ1dUIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRpdGxlID0gIlVzdWFsIEhvdXJzIFdvcmtlZCBMYXN0IFllYXIgYnkgQ29tcHV0ZWQgSG91cmx5IFdhZ2UsIE1lblxuNTAtNTIgd2Vla3Mgd29ya2VkIGxhc3QgeWVhciwgPj0gNDAgaG91cnMgcGVyIHVzdWFsIHdlZWsiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FwdGlvbiA9ICJTb3VyY2U6IEFTRUMuIE5vdGU6IGNvbXB1dGVkIGhvdXJseSB3YWdlID0gYW5udWFsIGluY29tZSAvIDUxIC8gdXN1YWwgaG91cnMgd29ya2VkIGxhc3QgeWVhciIpCnBsb3RfdjFfbWVhbl9ieV92Ml9kZWNpbGVfb3Zlcl92Myhhc2VjX3dvcmtlZF9MWSAlPiUgZmlsdGVyKFdLU1dPUksyID09IDYsIFVIUlNXT1JLTFkgPj0gNDAsIFNFWCA9PSAxKSAlPiUgbXV0YXRlKGhfd2FnZV91c3VhbCA9IElOQ1dBR0UgLyA1MSAvIFVIUlNXT1JLTFkpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIlVIUlNXT1JLTFkiLCAiaF93YWdlX3VzdWFsIiwgIllFQVIiLCAiQVNFQ1dUIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRlY2lsZXNfdG9fcGxvdCA9IGMoMSwgNSwgMTApLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRpdGxlID0gIlVzdWFsIEhvdXJzIFdvcmtlZCBMYXN0IFllYXIgYnkgQ29tcHV0ZWQgSG91cmx5IFdhZ2UsIE1lblxuNTAtNTIgd2Vla3Mgd29ya2VkIGxhc3QgeWVhciwgID49IHRoYW4gNDAgaG91cnMgcGVyIHVzdWFsIHdlZWsiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FwdGlvbiA9ICJTb3VyY2U6IEFTRUMuIE5vdGU6IGNvbXB1dGVkIGhvdXJseSB3YWdlID0gYW5udWFsIGluY29tZSAvIDUxIC8gdXN1YWwgaG91cnMgd29ya2VkIGxhc3QgeWVhciIpCmBgYAoKCmBgYHtyfQpwbG90X3YxX21lYW5fYnlfdjJfZGVjaWxlX292ZXJfdjMoYXNlY193b3JrZWRfTFkgJT4lIGZpbHRlcihXS1NXT1JLMiA9PSA2LCBVSFJTV09SS0xZID49IDQwLCBTRVggPT0gMikgJT4lIG11dGF0ZShoX3dhZ2VfdXN1YWwgPSBJTkNXQUdFIC8gNTEgLyBVSFJTV09SS0xZKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJVSFJTV09SS0xZIiwgImhfd2FnZV91c3VhbCIsICJZRUFSIiwgIkFTRUNXVCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aXRsZSA9ICJVc3VhbCBIb3VycyBXb3JrZWQgTGFzdCBZZWFyIGJ5IENvbXB1dGVkIEhvdXJseSBXYWdlLCBXb21lblxuNTAtNTIgd2Vla3Mgd29ya2VkIGxhc3QgeWVhciwgPj0gNDAgaG91cnMgcGVyIHVzdWFsIHdlZWsiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FwdGlvbiA9ICJTb3VyY2U6IEFTRUMuIE5vdGU6IGNvbXB1dGVkIGhvdXJseSB3YWdlID0gYW5udWFsIGluY29tZSAvIDUxIC8gdXN1YWwgaG91cnMgd29ya2VkIGxhc3QgeWVhciIpCnBsb3RfdjFfbWVhbl9ieV92Ml9kZWNpbGVfb3Zlcl92Myhhc2VjX3dvcmtlZF9MWSAlPiUgZmlsdGVyKFdLU1dPUksyID09IDYsIFVIUlNXT1JLTFkgPj0gNDAsIFNFWCA9PSAyKSAlPiUgbXV0YXRlKGhfd2FnZV91c3VhbCA9IElOQ1dBR0UgLyA1MSAvIFVIUlNXT1JLTFkpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIlVIUlNXT1JLTFkiLCAiaF93YWdlX3VzdWFsIiwgIllFQVIiLCAiQVNFQ1dUIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRlY2lsZXNfdG9fcGxvdCA9IGMoMSwgNSwgMTApLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRpdGxlID0gIlVzdWFsIEhvdXJzIFdvcmtlZCBMYXN0IFllYXIgYnkgQ29tcHV0ZWQgSG91cmx5IFdhZ2UsIFdvbWVuXG41MC01MiB3ZWVrcyB3b3JrZWQgbGFzdCB5ZWFyLCAgPj0gdGhhbiA0MCBob3VycyBwZXIgdXN1YWwgd2VlayIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXB0aW9uID0gIlNvdXJjZTogQVNFQy4gTm90ZTogY29tcHV0ZWQgaG91cmx5IHdhZ2UgPSBhbm51YWwgaW5jb21lIC8gNTEgLyB1c3VhbCBob3VycyB3b3JrZWQgbGFzdCB5ZWFyIikKCmBgYAoKCldpdGhpbi1CZXR3ZWVuIFZhcmlhbmNlIERlY29tcG9zaXRpb24gLSBUbyBiZSBjb21wbGV0ZWQKCmBgYHtyfQojIFdpdGhpbiAtIGJldHdlZW4gdmFyaWFuY2UgZGVjb21wb3NpdGlvbgoKc3VtbWFyeV9kZWNvbXBfZGYgPC0gaXB1bXNfb3JnICU+JQogIGZpbHRlcighaXMubmEoVUhSU1dPUksxKSkgJT4lCiAgZ3JvdXBfYnkoWUVBUikgJT4lCiAgbXV0YXRlKHllYXJfdG90YWwgPSBuKCkpICU+JSAgIyBBZGQgdG90YWwgY291bnQgZm9yIGVhY2ggeWVhcgogIGdyb3VwX2J5KFlFQVIsIE9DQzIwMTApICU+JQogIHN1bW1hcmlzZSh2YXJpYW5jZSA9IHZhcihVSFJTV09SSzEpLAogICAgICAgICAgICBtZWFuID0gbWVhbihVSFJTV09SSzEpLAogICAgICAgICAgICBuID0gbigpLAogICAgICAgICAgICBzaGFyZSA9IG4oKSAvIHVuaXF1ZSh5ZWFyX3RvdGFsKSwgLmdyb3VwcyA9ICJkcm9wIikKCnZhcl9kZWNvbXBvc2l0aW9uX2RmIDwtIGRhdGEuZnJhbWUoWUVBUiA9IHVuaXF1ZShzdW1tYXJ5X2RlY29tcF9kZiRZRUFSKSkKCmZvciAoaSBpbiAoMTpucm93KHZhcl9kZWNvbXBvc2l0aW9uX2RmKSkpewogIHllYXIgPC0gdmFyX2RlY29tcG9zaXRpb25fZGZbaSwiWUVBUiJdCiAgCiAgbWVhbl9hbGwgPC0gbWVhbihpcHVtc19vcmcgJT4lIGZpbHRlcihZRUFSID09IHllYXIpICU+JSBwdWxsKFVIUlNXT1JLMSkpCiAgc3VtbWFyeV9kZWNvbXBfZGZfeWVhciA8LSBzdW1tYXJ5X2RlY29tcF9kZiAlPiUgZmlsdGVyKFlFQVIgPT0geWVhcikKICAKICB2YXJfd2l0aGluX29jY192ZWMgPC0gc3VtbWFyeV9kZWNvbXBfZGZfeWVhciAlPiUgcHVsbCh2YXJpYW5jZSkgCiAgbWVhbl93aXRoaW5fb2NjX3ZlYyA8LSBzdW1tYXJ5X2RlY29tcF9kZl95ZWFyICU+JSBwdWxsKG1lYW4pCiAgc2hhcmVfb2NjX3ZlYyA8LSBzdW1tYXJ5X2RlY29tcF9kZl95ZWFyICU+JSBwdWxsKHNoYXJlKQogIAogIHZhcl9kZWNvbXBvc2l0aW9uX2RmW2ksIndpdGhpbl92YXIiXSA8LSBzdW0odmFyX3dpdGhpbl9vY2NfdmVjICogc2hhcmVfb2NjX3ZlYykKICB2YXJfZGVjb21wb3NpdGlvbl9kZltpLCJiZXR3ZWVuX3ZhciJdIDwtIHN1bShzaGFyZV9vY2NfdmVjICogKG1lYW5fd2l0aGluX29jY192ZWMgLSBtZWFuX2FsbCkgXiAyKQogIAogIHZhcl9kZWNvbXBvc2l0aW9uX2RmW2ksInRvdGFsX3Zhcl9jb21wdXRlZF9hc19zdW0iXSA8LSAgdmFyX2RlY29tcG9zaXRpb25fZGZbaSwid2l0aGluX3ZhciJdICsgdmFyX2RlY29tcG9zaXRpb25fZGZbaSwiYmV0d2Vlbl92YXIiXSAKICB2YXJfZGVjb21wb3NpdGlvbl9kZltpLCJ0b3RhbF92YXJfY29tcHV0ZWRfYXNfbm9ybWFsIl0gPC0gdmFyKGlwdW1zX29yZyAlPiUgZmlsdGVyKFlFQVIgPT0geWVhcikgJT4lIHB1bGwoVUhSU1dPUksxKSkKICAKfQoKCgp3aXRoaW5fdmFyIDwtIHN1bShvY2NfeWVhcl93aXRoaW5fdmFyX3ZlY3RvciAqIG9jY195ZWFyX3NoYXJlX3ZlY3RvcikKYmV0d2Vlbl92YXIgPC0gc3VtKHNoYXJlX3ZlY3RvciAqIChtZWFuX3ZlY3RvciAtIG1lYW5fYWxsKSBeIDIpCnRvdGFsX3Zhcl9kZWNvbXBvc2VkX2NhbGMgPC0gd2l0aGluX3ZhcitiZXR3ZWVuX3ZhcgoKdmFyKGlwdW1zX29yZyRVSFJTV09SSzEpCgpgYGAK