1 Quiz 3 Positioning

In Quiz 3, my goal is to extend our team’s Mini Project 2 analysis by selecting additional unanswered questions from each section of the provided question list. I provide evidence from the Walmart dataset using one simple visual, summary table, or model output per question, and then interpret what it means for the CEO.

1.1 Selected Questions (one from each section)

  • Descriptive & Exploratory: Q9 – How do macro variables vary across time?
  • Simple Linear Regression: Q13 – Does unemployment negatively affect weekly sales?
  • Multiple Linear Regression: Q30 – Where does multicollinearity appear?
  • Event Analysis: Q35 – Do sales spike before holidays?
  • Interaction Effects: Q44 – Does unemployment dampen holiday sales boosts?
  • Store-Level Heterogeneity & Fixed Effects: Q53 – How much variation is explained by store identity alone?
  • K-Means Clustering: Q67 – Are clusters stable across different k values?
  • Cluster-Based Regression: Q72 – Are holidays more effective in some clusters than others?
  • Prediction & Managerial Use: Q82 – How accurate are predictions with and without holiday variables?
  • Strategic & Marketing Interpretation: Q91 – What does analytics suggest about national vs local strategies?

2 Data Loading & Preparation

# ------------------------------------------------------------
# 1.1 Load data from Excel
# ------------------------------------------------------------

walmart_raw <- read_excel("WalmartData.xlsx")

# Quick check of columns & types
glimpse(walmart_raw)
## Rows: 6,435
## Columns: 8
## $ Store        <chr> "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1…
## $ Date         <chr> "05-02-2010", "12-02-2010", "19-02-2010", "26-02-2010", "…
## $ Weekly_Sales <chr> "1643690.9", "1641957.44", "1611968.17", "1409727.59", "1…
## $ Holiday_Flag <chr> "0", "1", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0…
## $ Temperature  <chr> "42.31", "38.51", "39.93", "46.63", "46.5", "57.79", "54.…
## $ Fuel_Price   <chr> "2.572", "2.548", "2.514", "2.561", "2.625", "2.667", "2.…
## $ CPI          <chr> "211.0963582", "211.2421698", "211.2891429", "211.3196429…
## $ Unemployment <chr> "8.106", "8.106", "8.106", "8.106", "8.106", "8.106", "8.…
# ------------------------------------------------------------
# 1.2 Clean and prepare (very important for correct analysis)
# ------------------------------------------------------------

walmart <- walmart_raw %>%
  mutate(
    # Convert Date to a proper date format.
    # If your Date is already a date, this will keep it as date.
    Date = as.Date(Date),

    # Convert key numeric variables to numeric (avoids "character" errors in sum/lm)
    Weekly_Sales = as.numeric(Weekly_Sales),
    Temperature  = as.numeric(Temperature),
    Fuel_Price   = as.numeric(Fuel_Price),
    CPI          = as.numeric(CPI),
    Unemployment = as.numeric(Unemployment),

    # Holiday flag should be 0/1 numeric
    Holiday_Flag = as.integer(Holiday_Flag),

    # Create time variables for later analysis
    Year  = year(Date),
    Month = month(Date, label = TRUE, abbr = TRUE)
  )

# Missing values check (simple and beginner-friendly)
missing_summary <- walmart %>%
  summarise(across(everything(), ~ sum(is.na(.))))

missing_summary

Interpretation (Data Prep):
This step ensures that numeric operations and regression models work correctly (e.g., sum() and lm() require numeric variables). Creating Year and Month supports trend/seasonality controls in later steps. Without these checks, results may reflect data type issues rather than business reality.


3 Descriptive & Exploratory (Q9)

3.1 Q9: How do macro variables (CPI, unemployment, temperature) vary across time?

# ------------------------------------------------------------
# Aggregate weekly macro variables over time (monthly average)
# ------------------------------------------------------------

macro_monthly <- walmart %>%
  mutate(MonthStart = floor_date(Date, unit = "month")) %>%
  group_by(MonthStart) %>%
  summarise(
    CPI_avg = mean(CPI, na.rm = TRUE),
    Unemp_avg = mean(Unemployment, na.rm = TRUE),
    Temp_avg = mean(Temperature, na.rm = TRUE),
    .groups = "drop"
  )

# Reshape to long format for easier plotting
macro_long <- macro_monthly %>%
  pivot_longer(cols = c(CPI_avg, Unemp_avg, Temp_avg),
               names_to = "MacroVar",
               values_to = "Value")

ggplot(macro_long, aes(x = MonthStart, y = Value)) +
  geom_line(alpha = 0.8) +
  facet_wrap(~ MacroVar, scales = "free_y", ncol = 1) +
  labs(
    title = "Macro Variables Over Time (Monthly Averages)",
    x = "Month",
    y = "Value"
  )

Interpretation (Q9):
Macro variables change over time and can shift the baseline conditions for sales. This matters because a CEO might incorrectly attribute sales changes to holidays or store performance when some variation is actually driven by inflation (CPI) or economic pressure (unemployment). This also supports why macro controls are important in regression.


4 Simple Linear Regression (Q13)

4.1 Q13: Does unemployment rate negatively affect weekly sales?

# ------------------------------------------------------------
# Simple regression: Weekly_Sales explained only by Unemployment
# ------------------------------------------------------------

m_simple_unemp <- lm(Weekly_Sales ~ Unemployment, data = walmart)

summary(m_simple_unemp)
## 
## Call:
## lm(formula = Weekly_Sales ~ Unemployment, data = walmart)
## 
## Residuals:
##     Min      1Q  Median      3Q     Max 
## -844415 -481049  -69658  369648 2794876 
## 
## Coefficients:
##              Estimate Std. Error t value Pr(>|t|)    
## (Intercept)   1302485      30645  42.503   <2e-16 ***
## Unemployment   -31944       3730  -8.564   <2e-16 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 561200 on 6433 degrees of freedom
## Multiple R-squared:  0.01127,    Adjusted R-squared:  0.01112 
## F-statistic: 73.35 on 1 and 6433 DF,  p-value: < 2.2e-16
# ------------------------------------------------------------
# Visualize the relationship (scatter + fitted line)
# ------------------------------------------------------------

ggplot(walmart, aes(x = Unemployment, y = Weekly_Sales)) +
  geom_point(alpha = 0.15) +
  geom_smooth(method = "lm", se = TRUE) +
  scale_y_continuous(labels = comma) +
  labs(
    title = "Simple Relationship: Weekly Sales vs Unemployment",
    x = "Unemployment Rate",
    y = "Weekly Sales"
  )

Interpretation (Q13):
This model checks whether unemployment alone is associated with weekly sales. Even if the coefficient is statistically significant, the key managerial question is whether the relationship is strong enough to matter (look at the slope direction and R-squared). This also sets up why we later need multiple regression controls.


5 Multiple Linear Regression (Q30)

5.1 Q30: Where does multicollinearity appear?

# ------------------------------------------------------------
# Multicollinearity means predictors move together (correlation).
# High correlation can make coefficients unstable.
# ------------------------------------------------------------

predictors <- walmart %>%
  select(Temperature, Fuel_Price, CPI, Unemployment) %>%
  drop_na()

cor_matrix <- cor(predictors)

cor_matrix
##              Temperature  Fuel_Price        CPI Unemployment
## Temperature    1.0000000  0.14498181  0.1768877   0.10115786
## Fuel_Price     0.1449818  1.00000000 -0.1706418  -0.03468374
## CPI            0.1768877 -0.17064180  1.0000000  -0.30202006
## Unemployment   0.1011579 -0.03468374 -0.3020201   1.00000000
# ------------------------------------------------------------
# Simple correlation heatmap (beginner-friendly)
# ------------------------------------------------------------

cor_df <- as.data.frame(as.table(cor_matrix)) %>%
  rename(Var1 = Var1, Var2 = Var2, Correlation = Freq)

ggplot(cor_df, aes(x = Var1, y = Var2, fill = Correlation)) +
  geom_tile() +
  geom_text(aes(label = round(Correlation, 2)), size = 3) +
  labs(
    title = "Correlation Among Macro Predictors (Multicollinearity Check)",
    x = "",
    y = ""
  ) +
  theme(axis.text.x = element_text(angle = 45, hjust = 1))

Interpretation (Q30):
If CPI and unemployment (or fuel price) are strongly correlated, coefficient estimates in a multiple regression can become unstable or change signs. For managerial use, this means we should interpret “which variable matters most” with caution when predictors overlap in information.


6 Event Analysis (Q35)

6.1 Q35: Do sales spike before holidays?

# ------------------------------------------------------------
# Create a "pre-holiday week" indicator:
# PreHoliday = 1 if next week is a holiday
# ------------------------------------------------------------

walmart_event <- walmart %>%
  arrange(Store, Date) %>%
  group_by(Store) %>%
  mutate(
    NextWeekHoliday = lead(Holiday_Flag, 1),
    PreHoliday = ifelse(NextWeekHoliday == 1 & Holiday_Flag == 0, 1, 0)
  ) %>%
  ungroup()

# Compare average sales: normal vs pre-holiday vs holiday
event_summary <- walmart_event %>%
  mutate(
    EventType = case_when(
      Holiday_Flag == 1 ~ "Holiday Week",
      PreHoliday == 1 ~ "Pre-Holiday Week",
      TRUE ~ "Regular Week"
    )
  ) %>%
  group_by(EventType) %>%
  summarise(
    avg_sales = mean(Weekly_Sales, na.rm = TRUE),
    .groups = "drop"
  )

event_summary
ggplot(event_summary, aes(x = EventType, y = avg_sales)) +
  geom_col(alpha = 0.85) +
  scale_y_continuous(labels = comma) +
  labs(
    title = "Do Sales Increase Before Holidays?",
    x = "",
    y = "Average Weekly Sales"
  )

Interpretation (Q35):
If pre-holiday weeks show higher average sales than regular weeks, it suggests customers may start shopping earlier (anticipation effect). This insight complements MP2 by adding timing nuance (not only holiday week vs non-holiday week).


7 Interaction Effects (Q44)

7.1 Q44: Does unemployment dampen holiday sales boosts?

# ------------------------------------------------------------
# Interaction model: Holiday effect depends on unemployment
# Weekly_Sales ~ Holiday_Flag + Unemployment + Holiday_Flag:Unemployment
# ------------------------------------------------------------

m_interaction <- lm(
  Weekly_Sales ~ Holiday_Flag * Unemployment + Year + Month,
  data = walmart
)

summary(m_interaction)
## 
## Call:
## lm(formula = Weekly_Sales ~ Holiday_Flag * Unemployment + Year + 
##     Month, data = walmart)
## 
## Residuals:
##      Min       1Q   Median       3Q      Max 
## -1099850  -463296   -64648   371480  2571810 
## 
## Coefficients:
##                            Estimate Std. Error t value Pr(>|t|)    
## (Intercept)               1333159.9    34011.8  39.197  < 2e-16 ***
## Holiday_Flag                40215.4   120718.9   0.333 0.739045    
## Unemployment               -33319.0     3838.2  -8.681  < 2e-16 ***
## Year                        -1158.9      796.0  -1.456 0.145447    
## Month.L                    183599.0    26487.4   6.932 4.57e-12 ***
## Month.Q                     93819.1    26426.6   3.550 0.000388 ***
## Month.C                    184981.2    25142.9   7.357 2.11e-13 ***
## Month^4                     52091.9    25251.4   2.063 0.039160 *  
## Month^5                     42413.2    25513.0   1.662 0.096478 .  
## Month^6                    -73365.7    25047.8  -2.929 0.003412 ** 
## Month^7                    -15437.2    24259.0  -0.636 0.524573    
## Month^8                    -31571.0    23982.7  -1.316 0.188085    
## Month^9                      1600.1    23101.4   0.069 0.944782    
## Month^10                     6872.5    23350.0   0.294 0.768520    
## Month^11                    29112.3    22903.4   1.271 0.203742    
## Holiday_Flag:Unemployment    -745.7    14485.6  -0.051 0.958944    
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 556000 on 6419 degrees of freedom
## Multiple R-squared:  0.03155,    Adjusted R-squared:  0.02929 
## F-statistic: 13.94 on 15 and 6419 DF,  p-value: < 2.2e-16

Interpretation (Q44):
The interaction term tests whether holiday lift is smaller when unemployment is higher. If the interaction coefficient is negative, it suggests that economic stress can reduce holiday-driven spending, which is a CEO-relevant risk insight.


8 Store Fixed Effects Thinking (Q53)

8.1 Q53: How much of sales variation is explained by store identity alone?

# ------------------------------------------------------------
# Store-only model: Weekly_Sales explained by Store factor
# This tells us how much variation is "store identity" (baseline differences).
# ------------------------------------------------------------

m_store_only <- lm(Weekly_Sales ~ factor(Store), data = walmart)

summary(m_store_only)$r.squared
## [1] 0.9174154

Interpretation (Q53):
A high R-squared here would mean that store identity alone explains a large share of sales variation (store baselines differ a lot). This strengthens the argument for store-specific strategies and supports why segmentation can be valuable.


9 K-Means Clustering (Q67)

9.1 Q67: Are clusters stable across different k values?

# ------------------------------------------------------------
# Build store-level features (simple version)
# ------------------------------------------------------------

store_features <- walmart %>%
  group_by(Store) %>%
  summarise(
    avg_sales = mean(Weekly_Sales, na.rm = TRUE),
    cv_sales = sd(Weekly_Sales, na.rm = TRUE) / mean(Weekly_Sales, na.rm = TRUE),
    holiday_mean = mean(Weekly_Sales[Holiday_Flag == 1], na.rm = TRUE),
    nonholiday_mean = mean(Weekly_Sales[Holiday_Flag == 0], na.rm = TRUE),
    holiday_lift_pct = (holiday_mean - nonholiday_mean) / nonholiday_mean * 100,
    .groups = "drop"
  ) %>%
  mutate(holiday_lift_pct = ifelse(is.finite(holiday_lift_pct), holiday_lift_pct, NA_real_)) %>%
  drop_na()

# Scale for k-means
X <- store_features %>%
  select(avg_sales, cv_sales, holiday_lift_pct) %>%
  scale()

set.seed(123)

# Run k-means for different k values and compare cluster sizes (stability proxy)
cluster_sizes <- map_dfr(2:6, function(k){
  km <- kmeans(X, centers = k, nstart = 25)
  tibble(k = k, cluster = factor(km$cluster)) %>%
    count(k, cluster, name = "n_stores")
})

cluster_sizes
ggplot(cluster_sizes, aes(x = cluster, y = n_stores)) +
  geom_col(alpha = 0.85) +
  facet_wrap(~ k, scales = "free_x") +
  labs(
    title = "Cluster Size Patterns Across Different k (Stability Check)",
    x = "Cluster label",
    y = "Number of stores"
  )

Interpretation (Q67):
If cluster sizes become extreme (e.g., one tiny cluster) as k changes, segmentation may be less stable. If patterns remain reasonable across k values, that suggests the segmentation structure is more robust.


10 Cluster-Based Regression (Q72)

10.1 Q72: Are holidays more effective in some clusters than others?

# ------------------------------------------------------------
# Choose a k (use k=3 for a simple, interpretable structure)
# ------------------------------------------------------------
set.seed(123)
k <- 3
km3 <- kmeans(X, centers = k, nstart = 25)

store_clustered <- store_features %>%
  mutate(Segment = factor(km3$cluster)) %>%
  select(Store, Segment)

# Merge segment labels back to the full weekly dataset
walmart_seg <- walmart %>%
  inner_join(store_clustered, by = "Store")

# Fit the same model by segment: Weekly_Sales ~ Holiday_Flag + controls
seg_models <- walmart_seg %>%
  group_by(Segment) %>%
  do(
    tidy(lm(Weekly_Sales ~ Holiday_Flag + Year + Month, data = .))
  ) %>%
  ungroup()

# Keep only the Holiday_Flag coefficient for comparison
holiday_by_segment <- seg_models %>%
  filter(term == "Holiday_Flag") %>%
  select(Segment, estimate, std.error, p.value)

holiday_by_segment
ggplot(holiday_by_segment, aes(x = Segment, y = estimate)) +
  geom_col(alpha = 0.85) +
  scale_y_continuous(labels = comma) +
  labs(
    title = "Estimated Holiday Effect by Store Segment (with time controls)",
    x = "Segment",
    y = "Holiday coefficient (sales units)"
  )

Interpretation (Q72):
If holiday coefficients differ across segments, it means holiday promotions are not equally effective everywhere. This directly supports differentiated strategy: focus holiday operational complexity where the segment response is strongest.


11 Prediction & Managerial Use (Q82)

11.1 Q82: How accurate are predictions with and without holiday variables?

# ------------------------------------------------------------
# Simple train/test split (beginner-friendly)
# We predict Weekly_Sales and compare RMSE with vs without Holiday_Flag
# ------------------------------------------------------------

set.seed(123)
n <- nrow(walmart)
test_idx <- sample(1:n, size = round(0.2 * n))  # 20% test

train <- walmart[-test_idx, ]
test  <- walmart[test_idx, ]

# Model A: without holiday
m_no_holiday <- lm(Weekly_Sales ~ Year + Month + CPI + Unemployment + Fuel_Price + Temperature, data = train)

# Model B: with holiday
m_with_holiday <- lm(Weekly_Sales ~ Holiday_Flag + Year + Month + CPI + Unemployment + Fuel_Price + Temperature, data = train)

# Predictions
pred_A <- predict(m_no_holiday, newdata = test)
pred_B <- predict(m_with_holiday, newdata = test)

# RMSE function
rmse <- function(actual, predicted) sqrt(mean((actual - predicted)^2, na.rm = TRUE))

rmse_A <- rmse(test$Weekly_Sales, pred_A)
rmse_B <- rmse(test$Weekly_Sales, pred_B)

tibble(
  Model = c("No Holiday Variable", "With Holiday Variable"),
  RMSE  = c(rmse_A, rmse_B)
)

Interpretation (Q82):
If adding the holiday variable reduces RMSE, it improves predictive accuracy and can support inventory planning. If the improvement is very small, it suggests that time and macro factors already capture much of the predictable structure, and holiday flags add limited incremental predictive value.


12 Strategic Interpretation (Q91)

12.1 Q91: What does analytics suggest about national vs local strategies?

Evidence to reference from this report:
- Store identity explains a meaningful share of variation (fixed-effects insight).
- Segments differ in volatility and holiday responsiveness.
- Holiday coefficients differ across segments.

Interpretation (Q91):
Analytics suggests that a single national strategy is risky because stores differ significantly in baseline sales, volatility, and holiday sensitivity. A better approach is a hybrid model: maintain a national framework (e.g., core holiday calendar) but apply local differentiation using store segments. For example, holiday-heavy operational plans should focus on segments where holiday effects are consistently strong, while stable low-impact segments should focus on cost efficiency and steady inventory.


13 Conclusion

This individual Quiz 3 analysis complements Mini Project 2 by: - adding macro trend context (Q9), - showing single-variable risk (Q13), - checking multicollinearity (Q30), - adding timing nuance with pre-holiday effects (Q35), - testing an interaction mechanism (Q44), - quantifying store identity importance (Q53), - checking segmentation robustness (Q67), - comparing holiday effectiveness across segments (Q72), - and evaluating predictive value of holiday variables (Q82), which together support the CEO’s need for clearer, more targeted decisions.

LS0tCnRpdGxlOiAiTWlNODExIOKAkyBRdWl6IDM6IEV4dGVuZGluZyBNaW5pIFByb2plY3QgMiIKYXV0aG9yOiAiR8O8bMWfYWggw4dhbMSxxZ9rYW4iCm91dHB1dDoKICBodG1sX2RvY3VtZW50OgogICAgdGhlbWU6IGZsYXRseQogICAgaGlnaGxpZ2h0OiBweWdtZW50cwogICAgdG9jOiB0cnVlCiAgICB0b2NfZGVwdGg6IDMKICAgIHRvY19mbG9hdDoKICAgICAgY29sbGFwc2VkOiB0cnVlCiAgICAgIHNtb290aF9zY3JvbGw6IHRydWUKICAgIG51bWJlcl9zZWN0aW9uczogdHJ1ZQogICAgY29kZV9mb2xkaW5nOiBzaG93CiAgICBjb2RlX2Rvd25sb2FkOiB0cnVlCiAgICBkZl9wcmludDogcGFnZWQKICAgIHNlbGZfY29udGFpbmVkOiB0cnVlCiAgICBtYXRoamF4OiBkZWZhdWx0Ci0tLQoKYGBge3Igc2V0dXAsIGluY2x1ZGU9RkFMU0V9CiMgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCiMgU0VUVVAgKHJ1bnMgb25jZSkKIyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KCiMgU2hvdyBjb2RlICsgb3V0cHV0IGluIEhUTUwKa25pdHI6Om9wdHNfY2h1bmskc2V0KAogIGVjaG8gPSBUUlVFLCAgICAgICAgIyBzaG93IGNvZGUKICBtZXNzYWdlID0gRkFMU0UsICAgICMgaGlkZSBwYWNrYWdlIG1lc3NhZ2VzCiAgd2FybmluZyA9IEZBTFNFICAgICAjIGhpZGUgd2FybmluZ3MgdG8ga2VlcCBIVE1MIGNsZWFuCikKCiMgTG9hZCBwYWNrYWdlcyAoaW5zdGFsbCBmaXJzdCBpZiBuZWVkZWQpCmxpYnJhcnkodGlkeXZlcnNlKSAgICMgZHBseXIgKyBnZ3Bsb3QyICsgbWFueSBoZWxwZXJzCmxpYnJhcnkobHVicmlkYXRlKSAgICMgZWFzeSBkYXRlIGhhbmRsaW5nCmxpYnJhcnkocmVhZHhsKSAgICAgICMgcmVhZCBFeGNlbCBmaWxlcwpsaWJyYXJ5KGJyb29tKSAgICAgICAjIHRpZHkgcmVncmVzc2lvbiBvdXRwdXRzCmxpYnJhcnkoc2NhbGVzKSAgICAgICMgbmljZXIgYXhpcyBsYWJlbHMgKGNvbW1hIGZvcm1hdHRpbmcpCgpgYGAKCiMgUXVpeiAzIFBvc2l0aW9uaW5nIAoKSW4gUXVpeiAzLCBteSBnb2FsIGlzIHRvICoqZXh0ZW5kKiogb3VyIHRlYW3igJlzIE1pbmkgUHJvamVjdCAyIGFuYWx5c2lzIGJ5IHNlbGVjdGluZyAqKmFkZGl0aW9uYWwgdW5hbnN3ZXJlZCBxdWVzdGlvbnMqKiBmcm9tIGVhY2ggc2VjdGlvbiBvZiB0aGUgcHJvdmlkZWQgcXVlc3Rpb24gbGlzdC4gSSBwcm92aWRlIGV2aWRlbmNlIGZyb20gdGhlIFdhbG1hcnQgZGF0YXNldCB1c2luZyAqKm9uZSBzaW1wbGUgdmlzdWFsLCBzdW1tYXJ5IHRhYmxlLCBvciBtb2RlbCBvdXRwdXQgcGVyIHF1ZXN0aW9uKiosIGFuZCB0aGVuIGludGVycHJldCB3aGF0IGl0IG1lYW5zIGZvciB0aGUgQ0VPLiAKCiMjIFNlbGVjdGVkIFF1ZXN0aW9ucyAob25lIGZyb20gZWFjaCBzZWN0aW9uKQoKCi0gKipEZXNjcmlwdGl2ZSAmIEV4cGxvcmF0b3J5OioqIFE5IOKAkyBIb3cgZG8gbWFjcm8gdmFyaWFibGVzIHZhcnkgYWNyb3NzIHRpbWU/Ci0gKipTaW1wbGUgTGluZWFyIFJlZ3Jlc3Npb246KiogUTEzIOKAkyBEb2VzIHVuZW1wbG95bWVudCBuZWdhdGl2ZWx5IGFmZmVjdCB3ZWVrbHkgc2FsZXM/Ci0gKipNdWx0aXBsZSBMaW5lYXIgUmVncmVzc2lvbjoqKiBRMzAg4oCTIFdoZXJlIGRvZXMgbXVsdGljb2xsaW5lYXJpdHkgYXBwZWFyPwotICoqRXZlbnQgQW5hbHlzaXM6KiogUTM1IOKAkyBEbyBzYWxlcyBzcGlrZSAqKmJlZm9yZSoqIGhvbGlkYXlzPwotICoqSW50ZXJhY3Rpb24gRWZmZWN0czoqKiBRNDQg4oCTIERvZXMgdW5lbXBsb3ltZW50IGRhbXBlbiBob2xpZGF5IHNhbGVzIGJvb3N0cz8KLSAqKlN0b3JlLUxldmVsIEhldGVyb2dlbmVpdHkgJiBGaXhlZCBFZmZlY3RzOioqIFE1MyDigJMgSG93IG11Y2ggdmFyaWF0aW9uIGlzIGV4cGxhaW5lZCBieSBzdG9yZSBpZGVudGl0eSBhbG9uZT8KLSAqKkstTWVhbnMgQ2x1c3RlcmluZzoqKiBRNjcg4oCTIEFyZSBjbHVzdGVycyBzdGFibGUgYWNyb3NzIGRpZmZlcmVudCBrIHZhbHVlcz8KLSAqKkNsdXN0ZXItQmFzZWQgUmVncmVzc2lvbjoqKiBRNzIg4oCTIEFyZSBob2xpZGF5cyBtb3JlIGVmZmVjdGl2ZSBpbiBzb21lIGNsdXN0ZXJzIHRoYW4gb3RoZXJzPwotICoqUHJlZGljdGlvbiAmIE1hbmFnZXJpYWwgVXNlOioqIFE4MiDigJMgSG93IGFjY3VyYXRlIGFyZSBwcmVkaWN0aW9ucyB3aXRoIGFuZCB3aXRob3V0IGhvbGlkYXkgdmFyaWFibGVzPwotICoqU3RyYXRlZ2ljICYgTWFya2V0aW5nIEludGVycHJldGF0aW9uOioqIFE5MSDigJMgV2hhdCBkb2VzIGFuYWx5dGljcyBzdWdnZXN0IGFib3V0IG5hdGlvbmFsIHZzIGxvY2FsIHN0cmF0ZWdpZXM/CgotLS0KCiMgRGF0YSBMb2FkaW5nICYgUHJlcGFyYXRpb24gCgoKYGBge3IgZGF0YS1sb2FkfQojIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQojIDEuMSBMb2FkIGRhdGEgZnJvbSBFeGNlbAojIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQoKd2FsbWFydF9yYXcgPC0gcmVhZF9leGNlbCgiV2FsbWFydERhdGEueGxzeCIpCgojIFF1aWNrIGNoZWNrIG9mIGNvbHVtbnMgJiB0eXBlcwpnbGltcHNlKHdhbG1hcnRfcmF3KQpgYGAKCmBgYHtyIGRhdGEtY2xlYW59CiMgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCiMgMS4yIENsZWFuIGFuZCBwcmVwYXJlICh2ZXJ5IGltcG9ydGFudCBmb3IgY29ycmVjdCBhbmFseXNpcykKIyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KCndhbG1hcnQgPC0gd2FsbWFydF9yYXcgJT4lCiAgbXV0YXRlKAogICAgIyBDb252ZXJ0IERhdGUgdG8gYSBwcm9wZXIgZGF0ZSBmb3JtYXQuCiAgICAjIElmIHlvdXIgRGF0ZSBpcyBhbHJlYWR5IGEgZGF0ZSwgdGhpcyB3aWxsIGtlZXAgaXQgYXMgZGF0ZS4KICAgIERhdGUgPSBhcy5EYXRlKERhdGUpLAoKICAgICMgQ29udmVydCBrZXkgbnVtZXJpYyB2YXJpYWJsZXMgdG8gbnVtZXJpYyAoYXZvaWRzICJjaGFyYWN0ZXIiIGVycm9ycyBpbiBzdW0vbG0pCiAgICBXZWVrbHlfU2FsZXMgPSBhcy5udW1lcmljKFdlZWtseV9TYWxlcyksCiAgICBUZW1wZXJhdHVyZSAgPSBhcy5udW1lcmljKFRlbXBlcmF0dXJlKSwKICAgIEZ1ZWxfUHJpY2UgICA9IGFzLm51bWVyaWMoRnVlbF9QcmljZSksCiAgICBDUEkgICAgICAgICAgPSBhcy5udW1lcmljKENQSSksCiAgICBVbmVtcGxveW1lbnQgPSBhcy5udW1lcmljKFVuZW1wbG95bWVudCksCgogICAgIyBIb2xpZGF5IGZsYWcgc2hvdWxkIGJlIDAvMSBudW1lcmljCiAgICBIb2xpZGF5X0ZsYWcgPSBhcy5pbnRlZ2VyKEhvbGlkYXlfRmxhZyksCgogICAgIyBDcmVhdGUgdGltZSB2YXJpYWJsZXMgZm9yIGxhdGVyIGFuYWx5c2lzCiAgICBZZWFyICA9IHllYXIoRGF0ZSksCiAgICBNb250aCA9IG1vbnRoKERhdGUsIGxhYmVsID0gVFJVRSwgYWJiciA9IFRSVUUpCiAgKQoKIyBNaXNzaW5nIHZhbHVlcyBjaGVjayAoc2ltcGxlIGFuZCBiZWdpbm5lci1mcmllbmRseSkKbWlzc2luZ19zdW1tYXJ5IDwtIHdhbG1hcnQgJT4lCiAgc3VtbWFyaXNlKGFjcm9zcyhldmVyeXRoaW5nKCksIH4gc3VtKGlzLm5hKC4pKSkpCgptaXNzaW5nX3N1bW1hcnkKYGBgCgoKKipJbnRlcnByZXRhdGlvbiAoRGF0YSBQcmVwKToqKiAgClRoaXMgc3RlcCBlbnN1cmVzIHRoYXQgbnVtZXJpYyBvcGVyYXRpb25zIGFuZCByZWdyZXNzaW9uIG1vZGVscyB3b3JrIGNvcnJlY3RseSAoZS5nLiwgYHN1bSgpYCBhbmQgYGxtKClgIHJlcXVpcmUgbnVtZXJpYyB2YXJpYWJsZXMpLiBDcmVhdGluZyBgWWVhcmAgYW5kIGBNb250aGAgc3VwcG9ydHMgdHJlbmQvc2Vhc29uYWxpdHkgY29udHJvbHMgaW4gbGF0ZXIgc3RlcHMuIFdpdGhvdXQgdGhlc2UgY2hlY2tzLCByZXN1bHRzIG1heSByZWZsZWN0IGRhdGEgdHlwZSBpc3N1ZXMgcmF0aGVyIHRoYW4gYnVzaW5lc3MgcmVhbGl0eS4KCi0tLQoKIyBEZXNjcmlwdGl2ZSAmIEV4cGxvcmF0b3J5IChROSkKIyMgUTk6IEhvdyBkbyBtYWNybyB2YXJpYWJsZXMgKENQSSwgdW5lbXBsb3ltZW50LCB0ZW1wZXJhdHVyZSkgdmFyeSBhY3Jvc3MgdGltZT8KCgpgYGB7ciBxOS1tYWNyby10aW1lfQojIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQojIEFnZ3JlZ2F0ZSB3ZWVrbHkgbWFjcm8gdmFyaWFibGVzIG92ZXIgdGltZSAobW9udGhseSBhdmVyYWdlKQojIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQoKbWFjcm9fbW9udGhseSA8LSB3YWxtYXJ0ICU+JQogIG11dGF0ZShNb250aFN0YXJ0ID0gZmxvb3JfZGF0ZShEYXRlLCB1bml0ID0gIm1vbnRoIikpICU+JQogIGdyb3VwX2J5KE1vbnRoU3RhcnQpICU+JQogIHN1bW1hcmlzZSgKICAgIENQSV9hdmcgPSBtZWFuKENQSSwgbmEucm0gPSBUUlVFKSwKICAgIFVuZW1wX2F2ZyA9IG1lYW4oVW5lbXBsb3ltZW50LCBuYS5ybSA9IFRSVUUpLAogICAgVGVtcF9hdmcgPSBtZWFuKFRlbXBlcmF0dXJlLCBuYS5ybSA9IFRSVUUpLAogICAgLmdyb3VwcyA9ICJkcm9wIgogICkKCiMgUmVzaGFwZSB0byBsb25nIGZvcm1hdCBmb3IgZWFzaWVyIHBsb3R0aW5nCm1hY3JvX2xvbmcgPC0gbWFjcm9fbW9udGhseSAlPiUKICBwaXZvdF9sb25nZXIoY29scyA9IGMoQ1BJX2F2ZywgVW5lbXBfYXZnLCBUZW1wX2F2ZyksCiAgICAgICAgICAgICAgIG5hbWVzX3RvID0gIk1hY3JvVmFyIiwKICAgICAgICAgICAgICAgdmFsdWVzX3RvID0gIlZhbHVlIikKCmdncGxvdChtYWNyb19sb25nLCBhZXMoeCA9IE1vbnRoU3RhcnQsIHkgPSBWYWx1ZSkpICsKICBnZW9tX2xpbmUoYWxwaGEgPSAwLjgpICsKICBmYWNldF93cmFwKH4gTWFjcm9WYXIsIHNjYWxlcyA9ICJmcmVlX3kiLCBuY29sID0gMSkgKwogIGxhYnMoCiAgICB0aXRsZSA9ICJNYWNybyBWYXJpYWJsZXMgT3ZlciBUaW1lIChNb250aGx5IEF2ZXJhZ2VzKSIsCiAgICB4ID0gIk1vbnRoIiwKICAgIHkgPSAiVmFsdWUiCiAgKQoKYGBgCgoKKipJbnRlcnByZXRhdGlvbiAoUTkpOioqICAKTWFjcm8gdmFyaWFibGVzIGNoYW5nZSBvdmVyIHRpbWUgYW5kIGNhbiBzaGlmdCB0aGUgYmFzZWxpbmUgY29uZGl0aW9ucyBmb3Igc2FsZXMuIFRoaXMgbWF0dGVycyBiZWNhdXNlIGEgQ0VPIG1pZ2h0IGluY29ycmVjdGx5IGF0dHJpYnV0ZSBzYWxlcyBjaGFuZ2VzIHRvIGhvbGlkYXlzIG9yIHN0b3JlIHBlcmZvcm1hbmNlIHdoZW4gc29tZSB2YXJpYXRpb24gaXMgYWN0dWFsbHkgZHJpdmVuIGJ5IGluZmxhdGlvbiAoQ1BJKSBvciBlY29ub21pYyBwcmVzc3VyZSAodW5lbXBsb3ltZW50KS4gVGhpcyBhbHNvIHN1cHBvcnRzIHdoeSBtYWNybyBjb250cm9scyBhcmUgaW1wb3J0YW50IGluIHJlZ3Jlc3Npb24uCgotLS0KCiMgU2ltcGxlIExpbmVhciBSZWdyZXNzaW9uIChRMTMpCgojIyBRMTM6IERvZXMgdW5lbXBsb3ltZW50IHJhdGUgbmVnYXRpdmVseSBhZmZlY3Qgd2Vla2x5IHNhbGVzPwoKYGBge3IgcTEzLXNpbXBsZS1yZWd9CiMgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCiMgU2ltcGxlIHJlZ3Jlc3Npb246IFdlZWtseV9TYWxlcyBleHBsYWluZWQgb25seSBieSBVbmVtcGxveW1lbnQKIyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KCm1fc2ltcGxlX3VuZW1wIDwtIGxtKFdlZWtseV9TYWxlcyB+IFVuZW1wbG95bWVudCwgZGF0YSA9IHdhbG1hcnQpCgpzdW1tYXJ5KG1fc2ltcGxlX3VuZW1wKQpgYGAKCgoKYGBge3IgcTEzLXBsb3R9CiMgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCiMgVmlzdWFsaXplIHRoZSByZWxhdGlvbnNoaXAgKHNjYXR0ZXIgKyBmaXR0ZWQgbGluZSkKIyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KCmdncGxvdCh3YWxtYXJ0LCBhZXMoeCA9IFVuZW1wbG95bWVudCwgeSA9IFdlZWtseV9TYWxlcykpICsKICBnZW9tX3BvaW50KGFscGhhID0gMC4xNSkgKwogIGdlb21fc21vb3RoKG1ldGhvZCA9ICJsbSIsIHNlID0gVFJVRSkgKwogIHNjYWxlX3lfY29udGludW91cyhsYWJlbHMgPSBjb21tYSkgKwogIGxhYnMoCiAgICB0aXRsZSA9ICJTaW1wbGUgUmVsYXRpb25zaGlwOiBXZWVrbHkgU2FsZXMgdnMgVW5lbXBsb3ltZW50IiwKICAgIHggPSAiVW5lbXBsb3ltZW50IFJhdGUiLAogICAgeSA9ICJXZWVrbHkgU2FsZXMiCiAgKQpgYGAKCioqSW50ZXJwcmV0YXRpb24gKFExMyk6KiogIApUaGlzIG1vZGVsIGNoZWNrcyB3aGV0aGVyIHVuZW1wbG95bWVudCBhbG9uZSBpcyBhc3NvY2lhdGVkIHdpdGggd2Vla2x5IHNhbGVzLiBFdmVuIGlmIHRoZSBjb2VmZmljaWVudCBpcyBzdGF0aXN0aWNhbGx5IHNpZ25pZmljYW50LCB0aGUga2V5IG1hbmFnZXJpYWwgcXVlc3Rpb24gaXMgd2hldGhlciB0aGUgcmVsYXRpb25zaGlwIGlzIHN0cm9uZyBlbm91Z2ggdG8gbWF0dGVyIChsb29rIGF0IHRoZSBzbG9wZSBkaXJlY3Rpb24gYW5kIFItc3F1YXJlZCkuIFRoaXMgYWxzbyBzZXRzIHVwIHdoeSB3ZSBsYXRlciBuZWVkIG11bHRpcGxlIHJlZ3Jlc3Npb24gY29udHJvbHMuCgotLS0KCgojIE11bHRpcGxlIExpbmVhciBSZWdyZXNzaW9uIChRMzApCiMjIFEzMDogV2hlcmUgZG9lcyBtdWx0aWNvbGxpbmVhcml0eSBhcHBlYXI/CgoKYGBge3IgcTMwLW11bHRpY29sbGluZWFyaXR5fQojIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQojIE11bHRpY29sbGluZWFyaXR5IG1lYW5zIHByZWRpY3RvcnMgbW92ZSB0b2dldGhlciAoY29ycmVsYXRpb24pLgojIEhpZ2ggY29ycmVsYXRpb24gY2FuIG1ha2UgY29lZmZpY2llbnRzIHVuc3RhYmxlLgojIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQoKcHJlZGljdG9ycyA8LSB3YWxtYXJ0ICU+JQogIHNlbGVjdChUZW1wZXJhdHVyZSwgRnVlbF9QcmljZSwgQ1BJLCBVbmVtcGxveW1lbnQpICU+JQogIGRyb3BfbmEoKQoKY29yX21hdHJpeCA8LSBjb3IocHJlZGljdG9ycykKCmNvcl9tYXRyaXgKYGBgCgoKCmBgYHtyIHEzMC1pbnRlcnByZXQtY29yfQojIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQojIFNpbXBsZSBjb3JyZWxhdGlvbiBoZWF0bWFwIChiZWdpbm5lci1mcmllbmRseSkKIyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KCmNvcl9kZiA8LSBhcy5kYXRhLmZyYW1lKGFzLnRhYmxlKGNvcl9tYXRyaXgpKSAlPiUKICByZW5hbWUoVmFyMSA9IFZhcjEsIFZhcjIgPSBWYXIyLCBDb3JyZWxhdGlvbiA9IEZyZXEpCgpnZ3Bsb3QoY29yX2RmLCBhZXMoeCA9IFZhcjEsIHkgPSBWYXIyLCBmaWxsID0gQ29ycmVsYXRpb24pKSArCiAgZ2VvbV90aWxlKCkgKwogIGdlb21fdGV4dChhZXMobGFiZWwgPSByb3VuZChDb3JyZWxhdGlvbiwgMikpLCBzaXplID0gMykgKwogIGxhYnMoCiAgICB0aXRsZSA9ICJDb3JyZWxhdGlvbiBBbW9uZyBNYWNybyBQcmVkaWN0b3JzIChNdWx0aWNvbGxpbmVhcml0eSBDaGVjaykiLAogICAgeCA9ICIiLAogICAgeSA9ICIiCiAgKSArCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA0NSwgaGp1c3QgPSAxKSkKYGBgCgoKKipJbnRlcnByZXRhdGlvbiAoUTMwKToqKiAgCklmIENQSSBhbmQgdW5lbXBsb3ltZW50IChvciBmdWVsIHByaWNlKSBhcmUgc3Ryb25nbHkgY29ycmVsYXRlZCwgY29lZmZpY2llbnQgZXN0aW1hdGVzIGluIGEgbXVsdGlwbGUgcmVncmVzc2lvbiBjYW4gYmVjb21lIHVuc3RhYmxlIG9yIGNoYW5nZSBzaWducy4gRm9yIG1hbmFnZXJpYWwgdXNlLCB0aGlzIG1lYW5zIHdlIHNob3VsZCBpbnRlcnByZXQg4oCcd2hpY2ggdmFyaWFibGUgbWF0dGVycyBtb3N04oCdIHdpdGggY2F1dGlvbiB3aGVuIHByZWRpY3RvcnMgb3ZlcmxhcCBpbiBpbmZvcm1hdGlvbi4KCi0tLQoKIyBFdmVudCBBbmFseXNpcyAoUTM1KQojIyBRMzU6IERvIHNhbGVzIHNwaWtlIGJlZm9yZSBob2xpZGF5cz8KCgpgYGB7ciBxMzUtcHJlaG9saWRheX0KIyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KIyBDcmVhdGUgYSAicHJlLWhvbGlkYXkgd2VlayIgaW5kaWNhdG9yOgojIFByZUhvbGlkYXkgPSAxIGlmIG5leHQgd2VlayBpcyBhIGhvbGlkYXkKIyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KCndhbG1hcnRfZXZlbnQgPC0gd2FsbWFydCAlPiUKICBhcnJhbmdlKFN0b3JlLCBEYXRlKSAlPiUKICBncm91cF9ieShTdG9yZSkgJT4lCiAgbXV0YXRlKAogICAgTmV4dFdlZWtIb2xpZGF5ID0gbGVhZChIb2xpZGF5X0ZsYWcsIDEpLAogICAgUHJlSG9saWRheSA9IGlmZWxzZShOZXh0V2Vla0hvbGlkYXkgPT0gMSAmIEhvbGlkYXlfRmxhZyA9PSAwLCAxLCAwKQogICkgJT4lCiAgdW5ncm91cCgpCgojIENvbXBhcmUgYXZlcmFnZSBzYWxlczogbm9ybWFsIHZzIHByZS1ob2xpZGF5IHZzIGhvbGlkYXkKZXZlbnRfc3VtbWFyeSA8LSB3YWxtYXJ0X2V2ZW50ICU+JQogIG11dGF0ZSgKICAgIEV2ZW50VHlwZSA9IGNhc2Vfd2hlbigKICAgICAgSG9saWRheV9GbGFnID09IDEgfiAiSG9saWRheSBXZWVrIiwKICAgICAgUHJlSG9saWRheSA9PSAxIH4gIlByZS1Ib2xpZGF5IFdlZWsiLAogICAgICBUUlVFIH4gIlJlZ3VsYXIgV2VlayIKICAgICkKICApICU+JQogIGdyb3VwX2J5KEV2ZW50VHlwZSkgJT4lCiAgc3VtbWFyaXNlKAogICAgYXZnX3NhbGVzID0gbWVhbihXZWVrbHlfU2FsZXMsIG5hLnJtID0gVFJVRSksCiAgICAuZ3JvdXBzID0gImRyb3AiCiAgKQoKZXZlbnRfc3VtbWFyeQoKYGBgCgpgYGB7ciBxMzUtcGxvdH0KZ2dwbG90KGV2ZW50X3N1bW1hcnksIGFlcyh4ID0gRXZlbnRUeXBlLCB5ID0gYXZnX3NhbGVzKSkgKwogIGdlb21fY29sKGFscGhhID0gMC44NSkgKwogIHNjYWxlX3lfY29udGludW91cyhsYWJlbHMgPSBjb21tYSkgKwogIGxhYnMoCiAgICB0aXRsZSA9ICJEbyBTYWxlcyBJbmNyZWFzZSBCZWZvcmUgSG9saWRheXM/IiwKICAgIHggPSAiIiwKICAgIHkgPSAiQXZlcmFnZSBXZWVrbHkgU2FsZXMiCiAgKQpgYGAKCgoqKkludGVycHJldGF0aW9uIChRMzUpOioqICAKSWYgcHJlLWhvbGlkYXkgd2Vla3Mgc2hvdyBoaWdoZXIgYXZlcmFnZSBzYWxlcyB0aGFuIHJlZ3VsYXIgd2Vla3MsIGl0IHN1Z2dlc3RzIGN1c3RvbWVycyBtYXkgc3RhcnQgc2hvcHBpbmcgZWFybGllciAoYW50aWNpcGF0aW9uIGVmZmVjdCkuIFRoaXMgaW5zaWdodCBjb21wbGVtZW50cyBNUDIgYnkgYWRkaW5nICoqdGltaW5nIG51YW5jZSoqIChub3Qgb25seSBob2xpZGF5IHdlZWsgdnMgbm9uLWhvbGlkYXkgd2VlaykuCgotLS0KCiMgSW50ZXJhY3Rpb24gRWZmZWN0cyAoUTQ0KQojIyBRNDQ6IERvZXMgdW5lbXBsb3ltZW50IGRhbXBlbiBob2xpZGF5IHNhbGVzIGJvb3N0cz8KCgpgYGB7ciBxNDQtaW50ZXJhY3Rpb259CiMgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCiMgSW50ZXJhY3Rpb24gbW9kZWw6IEhvbGlkYXkgZWZmZWN0IGRlcGVuZHMgb24gdW5lbXBsb3ltZW50CiMgV2Vla2x5X1NhbGVzIH4gSG9saWRheV9GbGFnICsgVW5lbXBsb3ltZW50ICsgSG9saWRheV9GbGFnOlVuZW1wbG95bWVudAojIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQoKbV9pbnRlcmFjdGlvbiA8LSBsbSgKICBXZWVrbHlfU2FsZXMgfiBIb2xpZGF5X0ZsYWcgKiBVbmVtcGxveW1lbnQgKyBZZWFyICsgTW9udGgsCiAgZGF0YSA9IHdhbG1hcnQKKQoKc3VtbWFyeShtX2ludGVyYWN0aW9uKQoKCmBgYAoKKipJbnRlcnByZXRhdGlvbiAoUTQ0KToqKiAgClRoZSBpbnRlcmFjdGlvbiB0ZXJtIHRlc3RzIHdoZXRoZXIgaG9saWRheSBsaWZ0IGlzIHNtYWxsZXIgd2hlbiB1bmVtcGxveW1lbnQgaXMgaGlnaGVyLiBJZiB0aGUgaW50ZXJhY3Rpb24gY29lZmZpY2llbnQgaXMgbmVnYXRpdmUsIGl0IHN1Z2dlc3RzIHRoYXQgZWNvbm9taWMgc3RyZXNzIGNhbiByZWR1Y2UgaG9saWRheS1kcml2ZW4gc3BlbmRpbmcsIHdoaWNoIGlzIGEgQ0VPLXJlbGV2YW50IHJpc2sgaW5zaWdodC4KCi0tLQoKIyBTdG9yZSBGaXhlZCBFZmZlY3RzIFRoaW5raW5nIChRNTMpCiMjIFE1MzogSG93IG11Y2ggb2Ygc2FsZXMgdmFyaWF0aW9uIGlzIGV4cGxhaW5lZCBieSBzdG9yZSBpZGVudGl0eSBhbG9uZT8KCgpgYGB7ciBxNTMtc3RvcmUtaWRlbnRpdHl9CiMgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCiMgU3RvcmUtb25seSBtb2RlbDogV2Vla2x5X1NhbGVzIGV4cGxhaW5lZCBieSBTdG9yZSBmYWN0b3IKIyBUaGlzIHRlbGxzIHVzIGhvdyBtdWNoIHZhcmlhdGlvbiBpcyAic3RvcmUgaWRlbnRpdHkiIChiYXNlbGluZSBkaWZmZXJlbmNlcykuCiMgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCgptX3N0b3JlX29ubHkgPC0gbG0oV2Vla2x5X1NhbGVzIH4gZmFjdG9yKFN0b3JlKSwgZGF0YSA9IHdhbG1hcnQpCgpzdW1tYXJ5KG1fc3RvcmVfb25seSkkci5zcXVhcmVkCmBgYAoKCioqSW50ZXJwcmV0YXRpb24gKFE1Myk6KiogIApBIGhpZ2ggUi1zcXVhcmVkIGhlcmUgd291bGQgbWVhbiB0aGF0IHN0b3JlIGlkZW50aXR5IGFsb25lIGV4cGxhaW5zIGEgbGFyZ2Ugc2hhcmUgb2Ygc2FsZXMgdmFyaWF0aW9uIChzdG9yZSBiYXNlbGluZXMgZGlmZmVyIGEgbG90KS4gVGhpcyBzdHJlbmd0aGVucyB0aGUgYXJndW1lbnQgZm9yIHN0b3JlLXNwZWNpZmljIHN0cmF0ZWdpZXMgYW5kIHN1cHBvcnRzIHdoeSBzZWdtZW50YXRpb24gY2FuIGJlIHZhbHVhYmxlLgoKLS0tCgojIEstTWVhbnMgQ2x1c3RlcmluZyAoUTY3KQojIyBRNjc6IEFyZSBjbHVzdGVycyBzdGFibGUgYWNyb3NzIGRpZmZlcmVudCBrIHZhbHVlcz8KCgpgYGB7ciBxNjctY2x1c3Rlci1zdGFiaWxpdHl9CiMgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCiMgQnVpbGQgc3RvcmUtbGV2ZWwgZmVhdHVyZXMgKHNpbXBsZSB2ZXJzaW9uKQojIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQoKc3RvcmVfZmVhdHVyZXMgPC0gd2FsbWFydCAlPiUKICBncm91cF9ieShTdG9yZSkgJT4lCiAgc3VtbWFyaXNlKAogICAgYXZnX3NhbGVzID0gbWVhbihXZWVrbHlfU2FsZXMsIG5hLnJtID0gVFJVRSksCiAgICBjdl9zYWxlcyA9IHNkKFdlZWtseV9TYWxlcywgbmEucm0gPSBUUlVFKSAvIG1lYW4oV2Vla2x5X1NhbGVzLCBuYS5ybSA9IFRSVUUpLAogICAgaG9saWRheV9tZWFuID0gbWVhbihXZWVrbHlfU2FsZXNbSG9saWRheV9GbGFnID09IDFdLCBuYS5ybSA9IFRSVUUpLAogICAgbm9uaG9saWRheV9tZWFuID0gbWVhbihXZWVrbHlfU2FsZXNbSG9saWRheV9GbGFnID09IDBdLCBuYS5ybSA9IFRSVUUpLAogICAgaG9saWRheV9saWZ0X3BjdCA9IChob2xpZGF5X21lYW4gLSBub25ob2xpZGF5X21lYW4pIC8gbm9uaG9saWRheV9tZWFuICogMTAwLAogICAgLmdyb3VwcyA9ICJkcm9wIgogICkgJT4lCiAgbXV0YXRlKGhvbGlkYXlfbGlmdF9wY3QgPSBpZmVsc2UoaXMuZmluaXRlKGhvbGlkYXlfbGlmdF9wY3QpLCBob2xpZGF5X2xpZnRfcGN0LCBOQV9yZWFsXykpICU+JQogIGRyb3BfbmEoKQoKIyBTY2FsZSBmb3Igay1tZWFucwpYIDwtIHN0b3JlX2ZlYXR1cmVzICU+JQogIHNlbGVjdChhdmdfc2FsZXMsIGN2X3NhbGVzLCBob2xpZGF5X2xpZnRfcGN0KSAlPiUKICBzY2FsZSgpCgpzZXQuc2VlZCgxMjMpCgojIFJ1biBrLW1lYW5zIGZvciBkaWZmZXJlbnQgayB2YWx1ZXMgYW5kIGNvbXBhcmUgY2x1c3RlciBzaXplcyAoc3RhYmlsaXR5IHByb3h5KQpjbHVzdGVyX3NpemVzIDwtIG1hcF9kZnIoMjo2LCBmdW5jdGlvbihrKXsKICBrbSA8LSBrbWVhbnMoWCwgY2VudGVycyA9IGssIG5zdGFydCA9IDI1KQogIHRpYmJsZShrID0gaywgY2x1c3RlciA9IGZhY3RvcihrbSRjbHVzdGVyKSkgJT4lCiAgICBjb3VudChrLCBjbHVzdGVyLCBuYW1lID0gIm5fc3RvcmVzIikKfSkKCmNsdXN0ZXJfc2l6ZXMKYGBgCgoKCmBgYHtyIHE2Ny1wbG90fQpnZ3Bsb3QoY2x1c3Rlcl9zaXplcywgYWVzKHggPSBjbHVzdGVyLCB5ID0gbl9zdG9yZXMpKSArCiAgZ2VvbV9jb2woYWxwaGEgPSAwLjg1KSArCiAgZmFjZXRfd3JhcCh+IGssIHNjYWxlcyA9ICJmcmVlX3giKSArCiAgbGFicygKICAgIHRpdGxlID0gIkNsdXN0ZXIgU2l6ZSBQYXR0ZXJucyBBY3Jvc3MgRGlmZmVyZW50IGsgKFN0YWJpbGl0eSBDaGVjaykiLAogICAgeCA9ICJDbHVzdGVyIGxhYmVsIiwKICAgIHkgPSAiTnVtYmVyIG9mIHN0b3JlcyIKICApCmBgYAoKCioqSW50ZXJwcmV0YXRpb24gKFE2Nyk6KiogIApJZiBjbHVzdGVyIHNpemVzIGJlY29tZSBleHRyZW1lIChlLmcuLCBvbmUgdGlueSBjbHVzdGVyKSBhcyBrIGNoYW5nZXMsIHNlZ21lbnRhdGlvbiBtYXkgYmUgbGVzcyBzdGFibGUuIElmIHBhdHRlcm5zIHJlbWFpbiByZWFzb25hYmxlIGFjcm9zcyBrIHZhbHVlcywgdGhhdCBzdWdnZXN0cyB0aGUgc2VnbWVudGF0aW9uIHN0cnVjdHVyZSBpcyBtb3JlIHJvYnVzdC4KCi0tLQoKIyBDbHVzdGVyLUJhc2VkIFJlZ3Jlc3Npb24gKFE3MikKIyMgUTcyOiBBcmUgaG9saWRheXMgbW9yZSBlZmZlY3RpdmUgaW4gc29tZSBjbHVzdGVycyB0aGFuIG90aGVycz8KCgpgYGB7ciBxNzItY2x1c3Rlci1yZWdyZXNzaW9ufQojIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQojIENob29zZSBhIGsgKHVzZSBrPTMgZm9yIGEgc2ltcGxlLCBpbnRlcnByZXRhYmxlIHN0cnVjdHVyZSkKIyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0Kc2V0LnNlZWQoMTIzKQprIDwtIDMKa20zIDwtIGttZWFucyhYLCBjZW50ZXJzID0gaywgbnN0YXJ0ID0gMjUpCgpzdG9yZV9jbHVzdGVyZWQgPC0gc3RvcmVfZmVhdHVyZXMgJT4lCiAgbXV0YXRlKFNlZ21lbnQgPSBmYWN0b3Ioa20zJGNsdXN0ZXIpKSAlPiUKICBzZWxlY3QoU3RvcmUsIFNlZ21lbnQpCgojIE1lcmdlIHNlZ21lbnQgbGFiZWxzIGJhY2sgdG8gdGhlIGZ1bGwgd2Vla2x5IGRhdGFzZXQKd2FsbWFydF9zZWcgPC0gd2FsbWFydCAlPiUKICBpbm5lcl9qb2luKHN0b3JlX2NsdXN0ZXJlZCwgYnkgPSAiU3RvcmUiKQoKIyBGaXQgdGhlIHNhbWUgbW9kZWwgYnkgc2VnbWVudDogV2Vla2x5X1NhbGVzIH4gSG9saWRheV9GbGFnICsgY29udHJvbHMKc2VnX21vZGVscyA8LSB3YWxtYXJ0X3NlZyAlPiUKICBncm91cF9ieShTZWdtZW50KSAlPiUKICBkbygKICAgIHRpZHkobG0oV2Vla2x5X1NhbGVzIH4gSG9saWRheV9GbGFnICsgWWVhciArIE1vbnRoLCBkYXRhID0gLikpCiAgKSAlPiUKICB1bmdyb3VwKCkKCiMgS2VlcCBvbmx5IHRoZSBIb2xpZGF5X0ZsYWcgY29lZmZpY2llbnQgZm9yIGNvbXBhcmlzb24KaG9saWRheV9ieV9zZWdtZW50IDwtIHNlZ19tb2RlbHMgJT4lCiAgZmlsdGVyKHRlcm0gPT0gIkhvbGlkYXlfRmxhZyIpICU+JQogIHNlbGVjdChTZWdtZW50LCBlc3RpbWF0ZSwgc3RkLmVycm9yLCBwLnZhbHVlKQoKaG9saWRheV9ieV9zZWdtZW50CmBgYAoKCgpgYGB7ciBxNzItcGxvdH0KZ2dwbG90KGhvbGlkYXlfYnlfc2VnbWVudCwgYWVzKHggPSBTZWdtZW50LCB5ID0gZXN0aW1hdGUpKSArCiAgZ2VvbV9jb2woYWxwaGEgPSAwLjg1KSArCiAgc2NhbGVfeV9jb250aW51b3VzKGxhYmVscyA9IGNvbW1hKSArCiAgbGFicygKICAgIHRpdGxlID0gIkVzdGltYXRlZCBIb2xpZGF5IEVmZmVjdCBieSBTdG9yZSBTZWdtZW50ICh3aXRoIHRpbWUgY29udHJvbHMpIiwKICAgIHggPSAiU2VnbWVudCIsCiAgICB5ID0gIkhvbGlkYXkgY29lZmZpY2llbnQgKHNhbGVzIHVuaXRzKSIKICApCmBgYAoKCioqSW50ZXJwcmV0YXRpb24gKFE3Mik6KiogIApJZiBob2xpZGF5IGNvZWZmaWNpZW50cyBkaWZmZXIgYWNyb3NzIHNlZ21lbnRzLCBpdCBtZWFucyBob2xpZGF5IHByb21vdGlvbnMgYXJlIG5vdCBlcXVhbGx5IGVmZmVjdGl2ZSBldmVyeXdoZXJlLiBUaGlzIGRpcmVjdGx5IHN1cHBvcnRzIGRpZmZlcmVudGlhdGVkIHN0cmF0ZWd5OiBmb2N1cyBob2xpZGF5IG9wZXJhdGlvbmFsIGNvbXBsZXhpdHkgd2hlcmUgdGhlIHNlZ21lbnQgcmVzcG9uc2UgaXMgc3Ryb25nZXN0LgoKLS0tCgojIFByZWRpY3Rpb24gJiBNYW5hZ2VyaWFsIFVzZSAoUTgyKQojIyBRODI6IEhvdyBhY2N1cmF0ZSBhcmUgcHJlZGljdGlvbnMgd2l0aCBhbmQgd2l0aG91dCBob2xpZGF5IHZhcmlhYmxlcz8KCgpgYGB7ciBxODItcHJlZGljdGlvbn0KIyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KIyBTaW1wbGUgdHJhaW4vdGVzdCBzcGxpdCAoYmVnaW5uZXItZnJpZW5kbHkpCiMgV2UgcHJlZGljdCBXZWVrbHlfU2FsZXMgYW5kIGNvbXBhcmUgUk1TRSB3aXRoIHZzIHdpdGhvdXQgSG9saWRheV9GbGFnCiMgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCgpzZXQuc2VlZCgxMjMpCm4gPC0gbnJvdyh3YWxtYXJ0KQp0ZXN0X2lkeCA8LSBzYW1wbGUoMTpuLCBzaXplID0gcm91bmQoMC4yICogbikpICAjIDIwJSB0ZXN0Cgp0cmFpbiA8LSB3YWxtYXJ0Wy10ZXN0X2lkeCwgXQp0ZXN0ICA8LSB3YWxtYXJ0W3Rlc3RfaWR4LCBdCgojIE1vZGVsIEE6IHdpdGhvdXQgaG9saWRheQptX25vX2hvbGlkYXkgPC0gbG0oV2Vla2x5X1NhbGVzIH4gWWVhciArIE1vbnRoICsgQ1BJICsgVW5lbXBsb3ltZW50ICsgRnVlbF9QcmljZSArIFRlbXBlcmF0dXJlLCBkYXRhID0gdHJhaW4pCgojIE1vZGVsIEI6IHdpdGggaG9saWRheQptX3dpdGhfaG9saWRheSA8LSBsbShXZWVrbHlfU2FsZXMgfiBIb2xpZGF5X0ZsYWcgKyBZZWFyICsgTW9udGggKyBDUEkgKyBVbmVtcGxveW1lbnQgKyBGdWVsX1ByaWNlICsgVGVtcGVyYXR1cmUsIGRhdGEgPSB0cmFpbikKCiMgUHJlZGljdGlvbnMKcHJlZF9BIDwtIHByZWRpY3QobV9ub19ob2xpZGF5LCBuZXdkYXRhID0gdGVzdCkKcHJlZF9CIDwtIHByZWRpY3QobV93aXRoX2hvbGlkYXksIG5ld2RhdGEgPSB0ZXN0KQoKIyBSTVNFIGZ1bmN0aW9uCnJtc2UgPC0gZnVuY3Rpb24oYWN0dWFsLCBwcmVkaWN0ZWQpIHNxcnQobWVhbigoYWN0dWFsIC0gcHJlZGljdGVkKV4yLCBuYS5ybSA9IFRSVUUpKQoKcm1zZV9BIDwtIHJtc2UodGVzdCRXZWVrbHlfU2FsZXMsIHByZWRfQSkKcm1zZV9CIDwtIHJtc2UodGVzdCRXZWVrbHlfU2FsZXMsIHByZWRfQikKCnRpYmJsZSgKICBNb2RlbCA9IGMoIk5vIEhvbGlkYXkgVmFyaWFibGUiLCAiV2l0aCBIb2xpZGF5IFZhcmlhYmxlIiksCiAgUk1TRSAgPSBjKHJtc2VfQSwgcm1zZV9CKQopCmBgYAoKCioqSW50ZXJwcmV0YXRpb24gKFE4Mik6KiogIApJZiBhZGRpbmcgdGhlIGhvbGlkYXkgdmFyaWFibGUgcmVkdWNlcyBSTVNFLCBpdCBpbXByb3ZlcyBwcmVkaWN0aXZlIGFjY3VyYWN5IGFuZCBjYW4gc3VwcG9ydCBpbnZlbnRvcnkgcGxhbm5pbmcuIElmIHRoZSBpbXByb3ZlbWVudCBpcyB2ZXJ5IHNtYWxsLCBpdCBzdWdnZXN0cyB0aGF0IHRpbWUgYW5kIG1hY3JvIGZhY3RvcnMgYWxyZWFkeSBjYXB0dXJlIG11Y2ggb2YgdGhlIHByZWRpY3RhYmxlIHN0cnVjdHVyZSwgYW5kIGhvbGlkYXkgZmxhZ3MgYWRkIGxpbWl0ZWQgaW5jcmVtZW50YWwgcHJlZGljdGl2ZSB2YWx1ZS4KCi0tLQoKIyBTdHJhdGVnaWMgSW50ZXJwcmV0YXRpb24gKFE5MSkKIyMgUTkxOiBXaGF0IGRvZXMgYW5hbHl0aWNzIHN1Z2dlc3QgYWJvdXQgbmF0aW9uYWwgdnMgbG9jYWwgc3RyYXRlZ2llcz8KCioqRXZpZGVuY2UgdG8gcmVmZXJlbmNlIGZyb20gdGhpcyByZXBvcnQ6KiogIAotIFN0b3JlIGlkZW50aXR5IGV4cGxhaW5zIGEgbWVhbmluZ2Z1bCBzaGFyZSBvZiB2YXJpYXRpb24gKGZpeGVkLWVmZmVjdHMgaW5zaWdodCkuICAKLSBTZWdtZW50cyBkaWZmZXIgaW4gdm9sYXRpbGl0eSBhbmQgaG9saWRheSByZXNwb25zaXZlbmVzcy4gIAotIEhvbGlkYXkgY29lZmZpY2llbnRzIGRpZmZlciBhY3Jvc3Mgc2VnbWVudHMuCgoqKkludGVycHJldGF0aW9uIChROTEpOioqICAKQW5hbHl0aWNzIHN1Z2dlc3RzIHRoYXQgYSBzaW5nbGUgbmF0aW9uYWwgc3RyYXRlZ3kgaXMgcmlza3kgYmVjYXVzZSBzdG9yZXMgZGlmZmVyIHNpZ25pZmljYW50bHkgaW4gYmFzZWxpbmUgc2FsZXMsIHZvbGF0aWxpdHksIGFuZCBob2xpZGF5IHNlbnNpdGl2aXR5LiBBIGJldHRlciBhcHByb2FjaCBpcyBhIGh5YnJpZCBtb2RlbDogbWFpbnRhaW4gYSBuYXRpb25hbCBmcmFtZXdvcmsgKGUuZy4sIGNvcmUgaG9saWRheSBjYWxlbmRhcikgYnV0IGFwcGx5IGxvY2FsIGRpZmZlcmVudGlhdGlvbiB1c2luZyBzdG9yZSBzZWdtZW50cy4gRm9yIGV4YW1wbGUsIGhvbGlkYXktaGVhdnkgb3BlcmF0aW9uYWwgcGxhbnMgc2hvdWxkIGZvY3VzIG9uIHNlZ21lbnRzIHdoZXJlIGhvbGlkYXkgZWZmZWN0cyBhcmUgY29uc2lzdGVudGx5IHN0cm9uZywgd2hpbGUgc3RhYmxlIGxvdy1pbXBhY3Qgc2VnbWVudHMgc2hvdWxkIGZvY3VzIG9uIGNvc3QgZWZmaWNpZW5jeSBhbmQgc3RlYWR5IGludmVudG9yeS4KCi0tLQoKIyBDb25jbHVzaW9uIAoKVGhpcyBpbmRpdmlkdWFsIFF1aXogMyBhbmFseXNpcyBjb21wbGVtZW50cyBNaW5pIFByb2plY3QgMiBieToKLSBhZGRpbmcgbWFjcm8gdHJlbmQgY29udGV4dCAoUTkpLAotIHNob3dpbmcgc2luZ2xlLXZhcmlhYmxlIHJpc2sgKFExMyksCi0gY2hlY2tpbmcgbXVsdGljb2xsaW5lYXJpdHkgKFEzMCksCi0gYWRkaW5nIHRpbWluZyBudWFuY2Ugd2l0aCBwcmUtaG9saWRheSBlZmZlY3RzIChRMzUpLAotIHRlc3RpbmcgYW4gaW50ZXJhY3Rpb24gbWVjaGFuaXNtIChRNDQpLAotIHF1YW50aWZ5aW5nIHN0b3JlIGlkZW50aXR5IGltcG9ydGFuY2UgKFE1MyksCi0gY2hlY2tpbmcgc2VnbWVudGF0aW9uIHJvYnVzdG5lc3MgKFE2NyksCi0gY29tcGFyaW5nIGhvbGlkYXkgZWZmZWN0aXZlbmVzcyBhY3Jvc3Mgc2VnbWVudHMgKFE3MiksCi0gYW5kIGV2YWx1YXRpbmcgcHJlZGljdGl2ZSB2YWx1ZSBvZiBob2xpZGF5IHZhcmlhYmxlcyAoUTgyKSwKd2hpY2ggdG9nZXRoZXIgc3VwcG9ydCB0aGUgQ0VP4oCZcyBuZWVkIGZvciBjbGVhcmVyLCBtb3JlIHRhcmdldGVkIGRlY2lzaW9ucy4gCgo=