# 0) Packages 
library(readxl)
library(dplyr)
library(tidyr)
library(ggplot2)
library(broom)
library(stringr)
library(forcats)

# 1) File path
excel_path <- "UNO Survey Responses v4.xlsx"

# Soft Likert color palette (academic & clean)
likert_colors <- c(
  "1" = "#E8E8E8",
  "2" = "#CFE1F2",
  "3" = "#A6C8E0",
  "4" = "#6FAED9",
  "5" = "#3C8DC5"
)

likert7_colors <- c(
  "1" = "#F0F0F0",
  "2" = "#D9E6F2",
  "3" = "#BFD7EA",
  "4" = "#9EC5DF",
  "5" = "#6FAED9",
  "6" = "#4A97CF",
  "7" = "#2C7FB8"
)

eval_colors <- c(
  "Very Bad" = "#E6E6E6",
  "Bad" = "#D1E5F0",
  "Same" = "#BDBDBD",
  "Good" = "#92C5DE",
  "Very Good" = "#4393C3"
)

1 . Project Background (MDP / MRP / Research Questions)

1.1 Management Decision Problem (MDP)

UNO aims to increase its market share in Türkiye and must decide between two growth paths:

  1. Market penetration: Strengthening traditional packaged breads.
  2. Product development: Launching an international/premium bread line (e.g., brioche).

1.2 Marketing Research Problem (MRP)

This research aims to identify which strategic direction—market penetration or product development—better aligns with consumer behavior, brand perception, and current market dynamics in Türkiye.

1.3 Research Questions & Hypotheses

We focus on consumer behavior, unmet needs, trial intent, segment differences, and UNO brand equity fit. Key hypotheses include: - H1 (Penetration): Purchase frequency can increase if UNO improves freshness, pricing, and availability. - H2 (Product Development): Consumers perceive packaged breads as similar; differentiated products (brioche) may satisfy novelty needs. - H3 (Product Development): Younger/urban consumers have higher adoption potential for international-style breads. - H4 (Brand Equity): UNO is strongly linked to traditional breads, but can extend to premium through branding and packaging.

2 . Research Design & Data Sources

We use a mixed-method design: exploratory (focus group + expert interview) followed by a descriptive online survey and a conjoint-style rating experiment.

2.1 Qualitative Insights

Focus group insights highlight: - concerns about additives/shelf life, - packaging smell/material issues, - emotional connection to traditional white bread, - brioche as taste/experience (not daily health choice), - trial triggers: tasting, novelty, social media virality, “not found in bakeries”.

Expert (dietitian) interview highlights: - consumers struggle to find “clean-label + fresh” bread, - brioche is an indulgence (weekend breakfasts, guests/snacking), - core trial triggers: ingredient quality and taste, - UNO is perceived as a reliable everyday brand (more traditional).

3 . Data Import (Survey Summaries + Conjoint)

3.1 Helper function to read “Option / Count” sheets safely

read_summary_sheet <- function(path, sheet_name) {
  raw <- read_excel(path, sheet = sheet_name, col_names = FALSE)

  # find first row that looks like a header (contains "Count")
  header_row <- which(apply(raw, 1, function(x) any(str_detect(as.character(x), "^Count$"))))[1]

  # if not found, assume first row is header
  if (is.na(header_row)) header_row <- 1

  df <- raw[(header_row):nrow(raw), ]
  colnames(df) <- as.character(df[1, ])
  df <- df[-1, ] %>% as.data.frame()

  # convert Count to numeric if present
  if ("Count" %in% names(df)) {
    df$Count <- as.numeric(df$Count)
  }
  df
}

3.2 Read sheets

# Demographics (Option/Count)
ageData       <- read_summary_sheet(excel_path, "Age")
## New names:
## • `` -> `...1`
## • `` -> `...2`
incomeData    <- read_summary_sheet(excel_path, "Income")
## New names:
## • `` -> `...1`
## • `` -> `...2`
genderData    <- read_summary_sheet(excel_path, "Gender")
## New names:
## • `` -> `...1`
## • `` -> `...2`
educationData <- read_summary_sheet(excel_path, "Education")
## New names:
## • `` -> `...1`
## • `` -> `...2`
# Category behavior (Option/Count)
usageOccasion <- read_summary_sheet(excel_path, "Bread Usage Occasion")
## New names:
## • `` -> `...1`
## • `` -> `...2`
trialMotives  <- read_summary_sheet(excel_path, "Premium_Bread_Trial_Motivation")
## New names:
## • `` -> `...1`
## • `` -> `...2`
purchaseSev   <- read_summary_sheet(excel_path, "Purchase Severity")
## New names:
## • `` -> `...1`
## • `` -> `...2`
briochePurch  <- read_summary_sheet(excel_path, "Brioche Purchasing")
## New names:
## • `` -> `...1`
## • `` -> `...2`
# UNO questions (grid counts)
uno_q1 <- read_excel(excel_path, sheet = "UNO Question1")
uno_q2 <- read_excel(excel_path, sheet = "UNO Question2")
uno_q3 <- read_excel(excel_path, sheet = "UNO Question3")

# Conjoint (individual-level)
conjoint <- read_excel(excel_path, sheet = "Conjoint_Long")

4 . Sample Profile (Demographics)

4.1 Age Distribution

ggplot(ageData, aes(x = .data[[names(ageData)[1]]], y = Count)) +
  geom_col() +
  labs(title = "Age Distribution", x = "Age Range", y = "Number of Respondents") +
  theme_minimal()

Profile Summary:
The respondent profile is concentrated in the 25–54 age range with a female-majority sample. Education levels are primarily Bachelor’s and Master’s, and a substantial share of respondents fall into higher-income brackets. Overall, the sample reflects urban, economically active consumers who are relevant for evaluating premium packaged bread positioning.

4.2 Gender / Education / Income

plot_count_bar <- function(df, title, xlab) {
  ggplot(df, aes(x = .data[[names(df)[1]]], y = Count)) +
    geom_col() +
    labs(title = title, x = xlab, y = "Number of Respondents") +
    theme_minimal() +
    theme(axis.text.x = element_text(angle = 20, hjust = 1))
}

plot_count_bar(genderData,    "Gender Distribution", "Gender")

plot_count_bar(educationData, "Education Distribution", "Education")

plot_count_bar(incomeData,    "Income Distribution", "Income Range")


5 . Category Behavior Findings (Option/Count Sheets)

5.1 Bread Usage Occasion

plot_count_bar(usageOccasion, "When Do Consumers Use Packaged Bread?", "Occasion")

  • The top occasions indicate whether packaged bread is mainly used for daily convenience vs special moments.
  • Use this to connect to the focus group’s “daily habits + freshness” themes. :contentReferenceoaicite:13

5.2 Motivation to Try a New Premium Bread

plot_count_bar(trialMotives, "Top Motivations to Try Premium Packaged Bread", "Motivation")

Interpretation guide: Compare the top motivations with qualitative triggers (tasting, novelty, social media). :contentReferenceoaicite:14


## Purchase Severity (how often they buy packaged bread / category intensity)


``` r
purchaseSev <- purchaseSev %>%
  mutate(pct = round(100 * Count / sum(Count), 1)) %>%
  arrange(desc(Count))

purchaseSev
purchaseSev %>%
  mutate(Purchase_Severity = fct_reorder(Purchase_Severity, Count)) %>%
  ggplot(aes(x = Purchase_Severity, y = Count)) +
  geom_col() +
  geom_text(aes(label = paste0(pct, "%")), vjust = -0.3, size = 3) +
  labs(
    title = "Purchase Severity (Category Engagement)",
    x = "Purchase Frequency / Severity",
    y = "Number of Respondents"
  ) +
  theme_minimal() +
  theme(axis.text.x = element_text(angle = 20, hjust = 1))

Interpretation:
The purchase severity distribution indicates the overall intensity of packaged bread consumption in our sample. This is important because it frames whether demand is driven by daily routines (supporting market penetration) or whether premium and specialty products would remain niche (supporting a more targeted product development strategy).

5.3 International Bread Usage Purpose (Brioche/Baguette)

briochePurch <- briochePurch %>%
  mutate(pct = round(100 * Count / sum(Count), 1)) %>%
  arrange(desc(Count))

briochePurch
briochePurch %>%
  mutate(International_Bread_Usage_Purpose =
           fct_reorder(International_Bread_Usage_Purpose, Count)) %>%
  ggplot(aes(x = International_Bread_Usage_Purpose, y = Count)) +
  geom_col() +
  geom_text(aes(label = paste0(pct, "%")), vjust = -0.3, size = 3) +
  labs(
    title = "Why Consumers Eat International Breads (Brioche/Baguette)",
    x = "Usage Purpose",
    y = "Number of Respondents"
  ) +
  theme_minimal() +
  theme(axis.text.x = element_text(angle = 20, hjust = 1))

Interpretation:
International breads (e.g., brioche/baguette) are consumed mainly for specific occasions rather than as a daily staple. This aligns with our qualitative findings that brioche is often seen as an indulgent or “special moment” product (e.g., weekend breakfasts, guests, snacking), suggesting that a premium/international line would likely be an adjacent growth opportunity rather than a replacement for core daily breads.

6 . UNO Question 1 — Brand Perceptions (1–5 scale)

6.1 Plot (faceted bar charts)

q1_item <- names(uno_q1)[1]   # first column = statement name (e.g., High_Quality)

uno_q1_long <- uno_q1 %>%
  pivot_longer(cols = where(is.numeric),
               names_to = "Scale",
               values_to = "Count") %>%
  mutate(Scale = as.factor(Scale))

ggplot(uno_q1_long, aes(x = Scale, y = Count, fill = Scale)) +
  geom_col(width = 0.7) +
  facet_wrap(~ UNO_Agreement_Level, scales = "free_y") +
  scale_fill_manual(values = likert_colors) +
  labs(
    title = "UNO Brand Perceptions (1 = Low, 5 = High)",
    x = "Agreement Level",
    y = "Number of Respondents"
  ) +
  theme_minimal(base_size = 11) +
  theme(
    legend.position = "bottom",
    strip.text = element_text(face = "bold"),
    plot.title = element_text(face = "bold")
  )

6.2 “Top-box” summary (simple, very useful)

q1_topbox <- uno_q1_long %>%
  group_by(.data[[q1_item]]) %>%
  summarise(
    total = sum(Count, na.rm=TRUE),
    topbox_4_5 = sum(Count[Scale %in% c("4","5")], na.rm=TRUE),
    topbox_pct = round(100 * topbox_4_5 / total, 1),
    .groups = "drop"
  ) %>%
  arrange(desc(topbox_pct))

q1_topbox

UNO Brand Perceptions (Q1) — Key Insights

  • Strongest association: New Product Success (55.4%)
  • Solid core strengths: Reliable Everyday (45.8%), Value for Money (42.2%), Healthy Trust (41.0%)
  • Weaker perceptions: Premium Brand (32.5%), Attractive Packaging (31.3%)

Overall, respondents believe that UNO can successfully develop new products and perceive it as a reliable everyday brand offering reasonable value and health-related trust. However, premium brand perception and packaging attractiveness are relatively weaker. This suggests that while UNO has the credibility to launch a premium line, premium cues—particularly packaging design and positioning—must be strengthened to justify higher pricing.

7 . UNO Question 2 — Action Likelihood for Premium Bread (1–7 scale)

q2_item <- names(uno_q2)[1]

uno_q2_long <- uno_q2 %>%
  pivot_longer(
    cols = where(is.numeric),
    names_to = "Scale",
    values_to = "Count"
  ) %>%
  mutate(Scale = as.factor(Scale))

ggplot(uno_q2_long, aes(x = Scale, y = Count, fill = Scale)) +
  geom_col(width = 0.7) +
  facet_wrap(as.formula(paste("~", q2_item)), scales = "free_y") +
  scale_fill_manual(values = likert7_colors) +
  labs(
    title = "Likelihood of Actions if UNO Launches Premium Bread (1 = Low, 7 = High)",
    x = "Likelihood Level",
    y = "Number of Respondents"
  ) +
  theme_minimal(base_size = 11) +
  theme(legend.position = "bottom")

7.1 Top-box for 7-point (6–7)

q2_topbox <- uno_q2_long %>%
  group_by(.data[[q2_item]]) %>%
  summarise(
    total = sum(Count, na.rm=TRUE),
    topbox_6_7 = sum(Count[Scale %in% c("6","7")], na.rm=TRUE),
    topbox_pct = round(100 * topbox_6_7 / total, 1),
    .groups = "drop"
  ) %>%
  arrange(desc(topbox_pct))

q2_topbox

Behavioral intentions (Q2) — funnel interpretation:
The strongest intention is trying UNO’s premium bread at least once, indicating high trial potential. In contrast, willingness to pay a premium price is more moderate and purchase-on-promotion appears important, suggesting price sensitivity. Following product announcements online is low, implying that awareness-building may work better through in-store visibility, packaging, and sampling rather than relying on consumers actively tracking updates online.

Managerial Interpretation (Q2)

Trial intention for a premium UNO bread is high, indicating strong curiosity and openness among consumers. However, willingness to pay a higher price is more moderate, and buying on promotion appears important. This suggests that premium adoption will depend on clear value communication and controlled pricing rather than purely brand-driven willingness to pay.

8 . UNO Question 3 — Comparative UNO Ratings (Very Bad → Very Good)

q3_item <- names(uno_q3)[1]  # attribute name column (Taste, Freshness, etc.)

uno_q3_long <- uno_q3 %>%
  pivot_longer(cols = -all_of(q3_item),
               names_to = "Evaluation",
               values_to = "Count") %>%
  mutate(Evaluation = factor(Evaluation, levels = c("Very Bad","Bad","Same","Good","Very Good")))

ggplot(uno_q3_long, aes(x = Evaluation, y = Count, fill = Evaluation)) +
  geom_col(width = 0.7) +
  facet_wrap(~ Comparative_UNO_Ratings, scales = "free_y") +
  scale_fill_manual(values = eval_colors) +
  labs(
    title = "UNO vs Other Bread Brands (Comparative Evaluation)",
    x = "Evaluation",
    y = "Number of Respondents"
  ) +
  theme_minimal(base_size = 11) +
  theme(
    legend.position = "bottom",
    strip.text = element_text(face = "bold"),
    plot.title = element_text(face = "bold")
  )

Comparative Evaluation of UNO vs Other Bread Brands This section evaluates how UNO performs relative to other packaged bread brands across key attributes such as taste, freshness, price, packaging, healthiness, availability, innovativeness, and premium feel. Overall, UNO performs strongly on core functional attributes. Taste and availability receive a high concentration of “Good” and “Very Good” ratings, indicating that consumers perceive UNO as competitive or superior to other brands in everyday consumption contexts. Healthiness also shows a favorable distribution, supporting earlier qualitative insights that position UNO as a reliable and trusted option for daily bread needs. In contrast, attributes related to premium positioning—particularly premium feel and innovativeness—show a more mixed distribution, with many respondents selecting “Same” rather than “Good” or “Very Good.” This suggests that while UNO is not perceived as weak in these dimensions, it is not yet clearly differentiated as a premium or highly innovative brand compared to alternatives.

These results reinforce the interpretation that UNO’s current brand strength lies in functional performance and reliability rather than symbolic or premium differentiation. Consequently, any premium bread extension would need to rely on stronger innovation signals, packaging design, and product storytelling to shift consumer perceptions beyond parity with existing brands.

9 . Conjoint Regression (Individual-Level Model)

# Ensure categorical fields are treated as factors
conjoint <- conjoint %>%
  mutate(
    Bread_Type   = as.factor(Bread_Type),
    Slice_Type   = as.factor(Slice_Type),
    Package_Type = as.factor(Package_Type),
    Price        = as.factor(Price)
  )

rating_model <- lm(Rating ~ Bread_Type + Slice_Type + Price + Package_Type, data = conjoint)
summary(rating_model)
## 
## Call:
## lm(formula = Rating ~ Bread_Type + Slice_Type + Price + Package_Type, 
##     data = conjoint)
## 
## Residuals:
##     Min      1Q  Median      3Q     Max 
## -3.3940 -1.4284 -0.2546  1.3089  4.8860 
## 
## Coefficients:
##                         Estimate Std. Error t value Pr(>|t|)    
## (Intercept)              4.10782    0.17067  24.069  < 2e-16 ***
## Bread_TypeTraditional   -0.01912    0.12146  -0.157  0.87496    
## Bread_TypeWhole grain    0.38851    0.12146   3.199  0.00141 ** 
## Slice_TypeThick         -0.29523    0.12207  -2.419  0.01570 *  
## Slice_TypeThin          -0.37151    0.12740  -2.916  0.00360 ** 
## Price150 TL             -0.78767    0.15431  -5.105 3.74e-07 ***
## Price25 TL              -0.10233    0.17102  -0.598  0.54969    
## Price35 TL              -0.17494    0.14914  -1.173  0.24098    
## Price50 TL              -0.35000    0.15710  -2.228  0.02604 *  
## Package_TypePlastic Bag -0.89179    0.10087  -8.841  < 2e-16 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 1.876 on 1484 degrees of freedom
## Multiple R-squared:  0.08997,    Adjusted R-squared:  0.08446 
## F-statistic:  16.3 on 9 and 1484 DF,  p-value: < 2.2e-16

Conjoint Regression Results

A rating-based conjoint regression was estimated to examine how different product attributes influence overall bread ratings. The model is statistically significant (F-test p < 0.001), indicating that the included attributes collectively explain variation in consumer preferences. While the R-squared value is modest, this is expected in consumer preference data and does not limit the interpretability of relative attribute effects.

The regression results reveal clear differences in how consumers evaluate product attributes:

  • Bread Type: Whole grain bread has a positive and statistically significant effect on ratings, indicating a strong preference for healthier or more natural bread options. Traditional bread does not significantly increase ratings relative to the reference category.

  • Slice Type: Both thick and thin slice options negatively affect ratings. This suggests that consumers prefer a standard slice thickness and penalize deviations from it.

  • Price: Higher prices reduce ratings, particularly at the extreme level (150 TL), which has a strong negative effect. Lower price increases show weaker and mostly insignificant effects, suggesting some tolerance at moderate price levels.

  • Package Type: Plastic packaging has the strongest negative impact on ratings. This highlights packaging as a critical driver of preference and suggests that plastic is perceived as inconsistent with quality or premium positioning.

9.1 Coefficient plot (easy to understand for presentation)

coef_df <- tidy(rating_model) %>% filter(term != "(Intercept)")

ggplot(coef_df, aes(x = estimate, y = reorder(term, estimate))) +
  geom_point(size = 3) +
  geom_errorbarh(aes(xmin = estimate - 1.96*std.error, xmax = estimate + 1.96*std.error), height = 0.2) +
  geom_vline(xintercept = 0, linetype = "dashed") +
  labs(title = "Conjoint Regression: Effect of Attributes on Rating",
       x = "Estimated impact on Rating", y = "Attribute level") +
  theme_minimal()
## Warning: `geom_errorbarh()` was deprecated in ggplot2 4.0.0.
## ℹ Please use the `orientation` argument of `geom_errorbar()` instead.
## This warning is displayed once every 8 hours.
## Call `lifecycle::last_lifecycle_warnings()` to see where this warning was
## generated.
## `height` was translated to `width`.

Overall, packaging and price emerge as the most influential attributes in shaping consumer ratings, followed by bread type. Slice type plays a secondary role and appears to function as a hygiene factor rather than a differentiator.

10 . Hypothesis Evaluation

H1 (Market Penetration):
Supported. UNO is perceived as reliable, accessible, and competitive in taste and healthiness. These attributes support continued penetration in the core packaged bread market.

H2 (Product Development – Differentiation):
Partially supported. Consumers show strong willingness to try a premium UNO bread, but premium perceptions are not yet well established. Differentiation would require clear innovation and packaging cues.

H3 (Premium Adoption Potential):
Partially supported. While trial intent is high, sustained behaviors such as weekly purchase and willingness to pay a higher price are more moderate, suggesting selective rather than mass adoption.

H4 (Brand Stretch to Premium):
Conditionally supported. UNO has strong brand credibility, but premium positioning is weaker. A premium extension is feasible if supported by distinctive packaging, health-oriented positioning, and controlled pricing.

11 . Managerial Recommendation (Decision: Traditional vs Brioche)

Based on the combined qualitative insights, survey findings, and conjoint regression results, we recommend a focused product development strategy rather than a broad repositioning of the core UNO portfolio.

UNO should introduce a premium or international-style bread line as a complementary offering, targeting specific consumption occasions such as special breakfasts, guests, or indulgent snacking. The success of this extension will depend heavily on non-plastic, premium packaging, clear health or quality cues, and a pricing strategy that remains within acceptable thresholds.

At the same time, UNO should continue strengthening its core packaged bread business by reinforcing trust, freshness, and availability—attributes where the brand already performs strongly.

LS0tCnRpdGxlOiAiRGF0YSBJbnNpZ2h0cyBmb3IgTWFya2V0aW5nIChNaU04MTApIC0gR3JvdXA0IgpzdWJ0aXRsZTogIlVOTyBCcmVhZCBDb25zdW1lciBTdXJ2ZXkgJiBDb25qb2ludCBBbmFseXNpcyBSZXN1bHRzIgphdXRob3I6ICJHcm91cCA0IgpkYXRlOiAiYHIgZm9ybWF0KFN5cy5EYXRlKCksICclQiAlZCwgJVknKWAiCm91dHB1dDoKICBodG1sX2RvY3VtZW50OgogICAgdGhlbWU6IGZsYXRseQogICAgaGlnaGxpZ2h0OiBweWdtZW50cwogICAgdG9jOiB0cnVlCiAgICB0b2NfZGVwdGg6IDMKICAgIHRvY19mbG9hdDoKICAgICAgY29sbGFwc2VkOiB0cnVlCiAgICAgIHNtb290aF9zY3JvbGw6IHRydWUKICAgIG51bWJlcl9zZWN0aW9uczogdHJ1ZQogICAgY29kZV9mb2xkaW5nOiBzaG93CiAgICBjb2RlX2Rvd25sb2FkOiB0cnVlCiAgICBkZl9wcmludDogcGFnZWQKICAgIHNlbGZfY29udGFpbmVkOiB0cnVlCiAgICBtYXRoamF4OiBkZWZhdWx0Ci0tLQoKYGBge3Igc2V0dXAsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CiMgMCkgUGFja2FnZXMgCmxpYnJhcnkocmVhZHhsKQpsaWJyYXJ5KGRwbHlyKQpsaWJyYXJ5KHRpZHlyKQpsaWJyYXJ5KGdncGxvdDIpCmxpYnJhcnkoYnJvb20pCmxpYnJhcnkoc3RyaW5ncikKbGlicmFyeShmb3JjYXRzKQoKIyAxKSBGaWxlIHBhdGgKZXhjZWxfcGF0aCA8LSAiVU5PIFN1cnZleSBSZXNwb25zZXMgdjQueGxzeCIKCiMgU29mdCBMaWtlcnQgY29sb3IgcGFsZXR0ZSAoYWNhZGVtaWMgJiBjbGVhbikKbGlrZXJ0X2NvbG9ycyA8LSBjKAogICIxIiA9ICIjRThFOEU4IiwKICAiMiIgPSAiI0NGRTFGMiIsCiAgIjMiID0gIiNBNkM4RTAiLAogICI0IiA9ICIjNkZBRUQ5IiwKICAiNSIgPSAiIzNDOERDNSIKKQoKbGlrZXJ0N19jb2xvcnMgPC0gYygKICAiMSIgPSAiI0YwRjBGMCIsCiAgIjIiID0gIiNEOUU2RjIiLAogICIzIiA9ICIjQkZEN0VBIiwKICAiNCIgPSAiIzlFQzVERiIsCiAgIjUiID0gIiM2RkFFRDkiLAogICI2IiA9ICIjNEE5N0NGIiwKICAiNyIgPSAiIzJDN0ZCOCIKKQoKZXZhbF9jb2xvcnMgPC0gYygKICAiVmVyeSBCYWQiID0gIiNFNkU2RTYiLAogICJCYWQiID0gIiNEMUU1RjAiLAogICJTYW1lIiA9ICIjQkRCREJEIiwKICAiR29vZCIgPSAiIzkyQzVERSIsCiAgIlZlcnkgR29vZCIgPSAiIzQzOTNDMyIKKQoKCgpgYGAKCi0tLQoKIyAuIFByb2plY3QgQmFja2dyb3VuZCAoTURQIC8gTVJQIC8gUmVzZWFyY2ggUXVlc3Rpb25zKQoKIyMgTWFuYWdlbWVudCBEZWNpc2lvbiBQcm9ibGVtIChNRFApCgpVTk8gYWltcyB0byBpbmNyZWFzZSBpdHMgbWFya2V0IHNoYXJlIGluIFTDvHJraXllIGFuZCBtdXN0IGRlY2lkZSBiZXR3ZWVuIHR3byBncm93dGggcGF0aHM6Cgo8b2w+CiAgPGxpPjxzdHJvbmc+TWFya2V0IHBlbmV0cmF0aW9uOjwvc3Ryb25nPiBTdHJlbmd0aGVuaW5nIHRyYWRpdGlvbmFsIHBhY2thZ2VkIGJyZWFkcy48L2xpPgogIDxsaT48c3Ryb25nPlByb2R1Y3QgZGV2ZWxvcG1lbnQ6PC9zdHJvbmc+IExhdW5jaGluZyBhbiBpbnRlcm5hdGlvbmFsL3ByZW1pdW0gYnJlYWQgbGluZSAoZS5nLiwgYnJpb2NoZSkuPC9saT4KPC9vbD4KCgojIyBNYXJrZXRpbmcgUmVzZWFyY2ggUHJvYmxlbSAoTVJQKQoKVGhpcyByZXNlYXJjaCBhaW1zIHRvIGlkZW50aWZ5IHdoaWNoIHN0cmF0ZWdpYyBkaXJlY3Rpb27igJRtYXJrZXQgcGVuZXRyYXRpb24gb3IgcHJvZHVjdCBkZXZlbG9wbWVudOKAlGJldHRlciBhbGlnbnMgd2l0aCBjb25zdW1lciBiZWhhdmlvciwgYnJhbmQgcGVyY2VwdGlvbiwgYW5kIGN1cnJlbnQgbWFya2V0IGR5bmFtaWNzIGluIFTDvHJraXllLgoKIyMgUmVzZWFyY2ggUXVlc3Rpb25zICYgSHlwb3RoZXNlcwoKV2UgZm9jdXMgb24gY29uc3VtZXIgYmVoYXZpb3IsIHVubWV0IG5lZWRzLCB0cmlhbCBpbnRlbnQsIHNlZ21lbnQgZGlmZmVyZW5jZXMsIGFuZCBVTk8gYnJhbmQgZXF1aXR5IGZpdC4KS2V5IGh5cG90aGVzZXMgaW5jbHVkZToKLSBIMSAoUGVuZXRyYXRpb24pOiBQdXJjaGFzZSBmcmVxdWVuY3kgY2FuIGluY3JlYXNlIGlmIFVOTyBpbXByb3ZlcyBmcmVzaG5lc3MsIHByaWNpbmcsIGFuZCBhdmFpbGFiaWxpdHkuCi0gSDIgKFByb2R1Y3QgRGV2ZWxvcG1lbnQpOiBDb25zdW1lcnMgcGVyY2VpdmUgcGFja2FnZWQgYnJlYWRzIGFzIHNpbWlsYXI7IGRpZmZlcmVudGlhdGVkIHByb2R1Y3RzIChicmlvY2hlKSBtYXkgc2F0aXNmeSBub3ZlbHR5IG5lZWRzLgotIEgzIChQcm9kdWN0IERldmVsb3BtZW50KTogWW91bmdlci91cmJhbiBjb25zdW1lcnMgaGF2ZSBoaWdoZXIgYWRvcHRpb24gcG90ZW50aWFsIGZvciBpbnRlcm5hdGlvbmFsLXN0eWxlIGJyZWFkcy4KLSBINCAoQnJhbmQgRXF1aXR5KTogVU5PIGlzIHN0cm9uZ2x5IGxpbmtlZCB0byB0cmFkaXRpb25hbCBicmVhZHMsIGJ1dCBjYW4gZXh0ZW5kIHRvIHByZW1pdW0gdGhyb3VnaCBicmFuZGluZyBhbmQgcGFja2FnaW5nLgoKIyAuIFJlc2VhcmNoIERlc2lnbiAmIERhdGEgU291cmNlcwoKV2UgdXNlIGEgbWl4ZWQtbWV0aG9kIGRlc2lnbjogZXhwbG9yYXRvcnkgKGZvY3VzIGdyb3VwICsgZXhwZXJ0IGludGVydmlldykgZm9sbG93ZWQgYnkgYSBkZXNjcmlwdGl2ZSBvbmxpbmUgc3VydmV5IGFuZCBhIGNvbmpvaW50LXN0eWxlIHJhdGluZyBleHBlcmltZW50LgoKIyMgUXVhbGl0YXRpdmUgSW5zaWdodHMKCkZvY3VzIGdyb3VwIGluc2lnaHRzIGhpZ2hsaWdodDoKLSBjb25jZXJucyBhYm91dCBhZGRpdGl2ZXMvc2hlbGYgbGlmZSwKLSBwYWNrYWdpbmcgc21lbGwvbWF0ZXJpYWwgaXNzdWVzLAotIGVtb3Rpb25hbCBjb25uZWN0aW9uIHRvIHRyYWRpdGlvbmFsIHdoaXRlIGJyZWFkLAotIGJyaW9jaGUgYXMgdGFzdGUvZXhwZXJpZW5jZSAobm90IGRhaWx5IGhlYWx0aCBjaG9pY2UpLAotIHRyaWFsIHRyaWdnZXJzOiB0YXN0aW5nLCBub3ZlbHR5LCBzb2NpYWwgbWVkaWEgdmlyYWxpdHksIOKAnG5vdCBmb3VuZCBpbiBiYWtlcmllc+KAnS4KCkV4cGVydCAoZGlldGl0aWFuKSBpbnRlcnZpZXcgaGlnaGxpZ2h0czoKLSBjb25zdW1lcnMgc3RydWdnbGUgdG8gZmluZCDigJxjbGVhbi1sYWJlbCArIGZyZXNo4oCdIGJyZWFkLAotIGJyaW9jaGUgaXMgYW4gaW5kdWxnZW5jZSAod2Vla2VuZCBicmVha2Zhc3RzLCBndWVzdHMvc25hY2tpbmcpLAotIGNvcmUgdHJpYWwgdHJpZ2dlcnM6IGluZ3JlZGllbnQgcXVhbGl0eSBhbmQgdGFzdGUsCi0gVU5PIGlzIHBlcmNlaXZlZCBhcyBhIHJlbGlhYmxlIGV2ZXJ5ZGF5IGJyYW5kIChtb3JlIHRyYWRpdGlvbmFsKS4KCiMgLiBEYXRhIEltcG9ydCAoU3VydmV5IFN1bW1hcmllcyArIENvbmpvaW50KQoKIyMgSGVscGVyIGZ1bmN0aW9uIHRvIHJlYWQg4oCcT3B0aW9uIC8gQ291bnTigJ0gc2hlZXRzIHNhZmVseQoKYGBge3IgaGVscGVyLXJlYWQtc3VtbWFyeX0KcmVhZF9zdW1tYXJ5X3NoZWV0IDwtIGZ1bmN0aW9uKHBhdGgsIHNoZWV0X25hbWUpIHsKICByYXcgPC0gcmVhZF9leGNlbChwYXRoLCBzaGVldCA9IHNoZWV0X25hbWUsIGNvbF9uYW1lcyA9IEZBTFNFKQoKICAjIGZpbmQgZmlyc3Qgcm93IHRoYXQgbG9va3MgbGlrZSBhIGhlYWRlciAoY29udGFpbnMgIkNvdW50IikKICBoZWFkZXJfcm93IDwtIHdoaWNoKGFwcGx5KHJhdywgMSwgZnVuY3Rpb24oeCkgYW55KHN0cl9kZXRlY3QoYXMuY2hhcmFjdGVyKHgpLCAiXkNvdW50JCIpKSkpWzFdCgogICMgaWYgbm90IGZvdW5kLCBhc3N1bWUgZmlyc3Qgcm93IGlzIGhlYWRlcgogIGlmIChpcy5uYShoZWFkZXJfcm93KSkgaGVhZGVyX3JvdyA8LSAxCgogIGRmIDwtIHJhd1soaGVhZGVyX3Jvdyk6bnJvdyhyYXcpLCBdCiAgY29sbmFtZXMoZGYpIDwtIGFzLmNoYXJhY3RlcihkZlsxLCBdKQogIGRmIDwtIGRmWy0xLCBdICU+JSBhcy5kYXRhLmZyYW1lKCkKCiAgIyBjb252ZXJ0IENvdW50IHRvIG51bWVyaWMgaWYgcHJlc2VudAogIGlmICgiQ291bnQiICVpbiUgbmFtZXMoZGYpKSB7CiAgICBkZiRDb3VudCA8LSBhcy5udW1lcmljKGRmJENvdW50KQogIH0KICBkZgp9CmBgYAoKCiMjIFJlYWQgc2hlZXRzCgoKYGBge3IgcmVhZC1kYXRhfQojIERlbW9ncmFwaGljcyAoT3B0aW9uL0NvdW50KQphZ2VEYXRhICAgICAgIDwtIHJlYWRfc3VtbWFyeV9zaGVldChleGNlbF9wYXRoLCAiQWdlIikKaW5jb21lRGF0YSAgICA8LSByZWFkX3N1bW1hcnlfc2hlZXQoZXhjZWxfcGF0aCwgIkluY29tZSIpCmdlbmRlckRhdGEgICAgPC0gcmVhZF9zdW1tYXJ5X3NoZWV0KGV4Y2VsX3BhdGgsICJHZW5kZXIiKQplZHVjYXRpb25EYXRhIDwtIHJlYWRfc3VtbWFyeV9zaGVldChleGNlbF9wYXRoLCAiRWR1Y2F0aW9uIikKCiMgQ2F0ZWdvcnkgYmVoYXZpb3IgKE9wdGlvbi9Db3VudCkKdXNhZ2VPY2Nhc2lvbiA8LSByZWFkX3N1bW1hcnlfc2hlZXQoZXhjZWxfcGF0aCwgIkJyZWFkIFVzYWdlIE9jY2FzaW9uIikKdHJpYWxNb3RpdmVzICA8LSByZWFkX3N1bW1hcnlfc2hlZXQoZXhjZWxfcGF0aCwgIlByZW1pdW1fQnJlYWRfVHJpYWxfTW90aXZhdGlvbiIpCnB1cmNoYXNlU2V2ICAgPC0gcmVhZF9zdW1tYXJ5X3NoZWV0KGV4Y2VsX3BhdGgsICJQdXJjaGFzZSBTZXZlcml0eSIpCmJyaW9jaGVQdXJjaCAgPC0gcmVhZF9zdW1tYXJ5X3NoZWV0KGV4Y2VsX3BhdGgsICJCcmlvY2hlIFB1cmNoYXNpbmciKQoKIyBVTk8gcXVlc3Rpb25zIChncmlkIGNvdW50cykKdW5vX3ExIDwtIHJlYWRfZXhjZWwoZXhjZWxfcGF0aCwgc2hlZXQgPSAiVU5PIFF1ZXN0aW9uMSIpCnVub19xMiA8LSByZWFkX2V4Y2VsKGV4Y2VsX3BhdGgsIHNoZWV0ID0gIlVOTyBRdWVzdGlvbjIiKQp1bm9fcTMgPC0gcmVhZF9leGNlbChleGNlbF9wYXRoLCBzaGVldCA9ICJVTk8gUXVlc3Rpb24zIikKCiMgQ29uam9pbnQgKGluZGl2aWR1YWwtbGV2ZWwpCmNvbmpvaW50IDwtIHJlYWRfZXhjZWwoZXhjZWxfcGF0aCwgc2hlZXQgPSAiQ29uam9pbnRfTG9uZyIpCgpgYGAKCgotLS0KCiMgLiBTYW1wbGUgUHJvZmlsZSAoRGVtb2dyYXBoaWNzKQoKIyMgQWdlIERpc3RyaWJ1dGlvbgoKYGBge3IgcGxvdC1hZ2V9CmdncGxvdChhZ2VEYXRhLCBhZXMoeCA9IC5kYXRhW1tuYW1lcyhhZ2VEYXRhKVsxXV1dLCB5ID0gQ291bnQpKSArCiAgZ2VvbV9jb2woKSArCiAgbGFicyh0aXRsZSA9ICJBZ2UgRGlzdHJpYnV0aW9uIiwgeCA9ICJBZ2UgUmFuZ2UiLCB5ID0gIk51bWJlciBvZiBSZXNwb25kZW50cyIpICsKICB0aGVtZV9taW5pbWFsKCkKCmBgYAoKCj4qKlByb2ZpbGUgU3VtbWFyeToqKiAgClRoZSByZXNwb25kZW50IHByb2ZpbGUgaXMgY29uY2VudHJhdGVkIGluIHRoZSAyNeKAkzU0IGFnZSByYW5nZSB3aXRoIGEgZmVtYWxlLW1ham9yaXR5IHNhbXBsZS4gRWR1Y2F0aW9uIGxldmVscyBhcmUgcHJpbWFyaWx5IEJhY2hlbG9y4oCZcyBhbmQgTWFzdGVy4oCZcywgYW5kIGEgc3Vic3RhbnRpYWwgc2hhcmUgb2YgcmVzcG9uZGVudHMgZmFsbCBpbnRvIGhpZ2hlci1pbmNvbWUgYnJhY2tldHMuIE92ZXJhbGwsIHRoZSBzYW1wbGUgcmVmbGVjdHMgdXJiYW4sIGVjb25vbWljYWxseSBhY3RpdmUgY29uc3VtZXJzIHdobyBhcmUgcmVsZXZhbnQgZm9yIGV2YWx1YXRpbmcgcHJlbWl1bSBwYWNrYWdlZCBicmVhZCBwb3NpdGlvbmluZy4KCgojIyBHZW5kZXIgLyBFZHVjYXRpb24gLyBJbmNvbWUKCmBgYHtyIHBsb3QtZGVtb2dyYXBoaWNzfQpwbG90X2NvdW50X2JhciA8LSBmdW5jdGlvbihkZiwgdGl0bGUsIHhsYWIpIHsKICBnZ3Bsb3QoZGYsIGFlcyh4ID0gLmRhdGFbW25hbWVzKGRmKVsxXV1dLCB5ID0gQ291bnQpKSArCiAgICBnZW9tX2NvbCgpICsKICAgIGxhYnModGl0bGUgPSB0aXRsZSwgeCA9IHhsYWIsIHkgPSAiTnVtYmVyIG9mIFJlc3BvbmRlbnRzIikgKwogICAgdGhlbWVfbWluaW1hbCgpICsKICAgIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gMjAsIGhqdXN0ID0gMSkpCn0KCnBsb3RfY291bnRfYmFyKGdlbmRlckRhdGEsICAgICJHZW5kZXIgRGlzdHJpYnV0aW9uIiwgIkdlbmRlciIpCnBsb3RfY291bnRfYmFyKGVkdWNhdGlvbkRhdGEsICJFZHVjYXRpb24gRGlzdHJpYnV0aW9uIiwgIkVkdWNhdGlvbiIpCnBsb3RfY291bnRfYmFyKGluY29tZURhdGEsICAgICJJbmNvbWUgRGlzdHJpYnV0aW9uIiwgIkluY29tZSBSYW5nZSIpCgpgYGAKCgotLS0KCiMgLiBDYXRlZ29yeSBCZWhhdmlvciBGaW5kaW5ncyAoT3B0aW9uL0NvdW50IFNoZWV0cykKCiMjIEJyZWFkIFVzYWdlIE9jY2FzaW9uCgoKYGBge3IgcGxvdC11c2FnZS1vY2Nhc2lvbn0KcGxvdF9jb3VudF9iYXIodXNhZ2VPY2Nhc2lvbiwgIldoZW4gRG8gQ29uc3VtZXJzIFVzZSBQYWNrYWdlZCBCcmVhZD8iLCAiT2NjYXNpb24iKQoKYGBgCgo+Ci0gVGhlIHRvcCBvY2Nhc2lvbnMgaW5kaWNhdGUgd2hldGhlciBwYWNrYWdlZCBicmVhZCBpcyBtYWlubHkgdXNlZCBmb3IgKipkYWlseSBjb252ZW5pZW5jZSoqIHZzICoqc3BlY2lhbCBtb21lbnRzKiouCi0gVXNlIHRoaXMgdG8gY29ubmVjdCB0byB0aGUgZm9jdXMgZ3JvdXDigJlzIOKAnGRhaWx5IGhhYml0cyArIGZyZXNobmVzc+KAnSB0aGVtZXMuIDpjb250ZW50UmVmZXJlbmNlW29haWNpdGU6MTNde2luZGV4PTEzfQoKCiMjIE1vdGl2YXRpb24gdG8gVHJ5IGEgTmV3IFByZW1pdW0gQnJlYWQKCmBgYHtyIHBsb3QtdHJpYWwtbW90aXZlc30KcGxvdF9jb3VudF9iYXIodHJpYWxNb3RpdmVzLCAiVG9wIE1vdGl2YXRpb25zIHRvIFRyeSBQcmVtaXVtIFBhY2thZ2VkIEJyZWFkIiwgIk1vdGl2YXRpb24iKQpgYGAKCj4qKkludGVycHJldGF0aW9uIGd1aWRlOioqCkNvbXBhcmUgdGhlIHRvcCBtb3RpdmF0aW9ucyB3aXRoIHF1YWxpdGF0aXZlIHRyaWdnZXJzICh0YXN0aW5nLCBub3ZlbHR5LCBzb2NpYWwgbWVkaWEpLiA6Y29udGVudFJlZmVyZW5jZVtvYWljaXRlOjE0XXtpbmRleD0xNH0KYGBgCgojIyBQdXJjaGFzZSBTZXZlcml0eSAoaG93IG9mdGVuIHRoZXkgYnV5IHBhY2thZ2VkIGJyZWFkIC8gY2F0ZWdvcnkgaW50ZW5zaXR5KQoKYGBge3IgcHVyY2hhc2Utc2V2ZXJpdHktdGFibGUsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CnB1cmNoYXNlU2V2IDwtIHB1cmNoYXNlU2V2ICU+JQogIG11dGF0ZShwY3QgPSByb3VuZCgxMDAgKiBDb3VudCAvIHN1bShDb3VudCksIDEpKSAlPiUKICBhcnJhbmdlKGRlc2MoQ291bnQpKQoKcHVyY2hhc2VTZXYKYGBgCgoKCmBgYHtyIHB1cmNoYXNlLXNldmVyaXR5LXBsb3QsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CnB1cmNoYXNlU2V2ICU+JQogIG11dGF0ZShQdXJjaGFzZV9TZXZlcml0eSA9IGZjdF9yZW9yZGVyKFB1cmNoYXNlX1NldmVyaXR5LCBDb3VudCkpICU+JQogIGdncGxvdChhZXMoeCA9IFB1cmNoYXNlX1NldmVyaXR5LCB5ID0gQ291bnQpKSArCiAgZ2VvbV9jb2woKSArCiAgZ2VvbV90ZXh0KGFlcyhsYWJlbCA9IHBhc3RlMChwY3QsICIlIikpLCB2anVzdCA9IC0wLjMsIHNpemUgPSAzKSArCiAgbGFicygKICAgIHRpdGxlID0gIlB1cmNoYXNlIFNldmVyaXR5IChDYXRlZ29yeSBFbmdhZ2VtZW50KSIsCiAgICB4ID0gIlB1cmNoYXNlIEZyZXF1ZW5jeSAvIFNldmVyaXR5IiwKICAgIHkgPSAiTnVtYmVyIG9mIFJlc3BvbmRlbnRzIgogICkgKwogIHRoZW1lX21pbmltYWwoKSArCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSAyMCwgaGp1c3QgPSAxKSkKYGBgCgo+KipJbnRlcnByZXRhdGlvbjogKiogIApUaGUgcHVyY2hhc2Ugc2V2ZXJpdHkgZGlzdHJpYnV0aW9uIGluZGljYXRlcyB0aGUgb3ZlcmFsbCBpbnRlbnNpdHkgb2YgcGFja2FnZWQgYnJlYWQgY29uc3VtcHRpb24gaW4gb3VyIHNhbXBsZS4gVGhpcyBpcyBpbXBvcnRhbnQgYmVjYXVzZSBpdCBmcmFtZXMgd2hldGhlciBkZW1hbmQgaXMgZHJpdmVuIGJ5IGRhaWx5IHJvdXRpbmVzIChzdXBwb3J0aW5nIG1hcmtldCBwZW5ldHJhdGlvbikgb3Igd2hldGhlciBwcmVtaXVtIGFuZCBzcGVjaWFsdHkgcHJvZHVjdHMgd291bGQgcmVtYWluIG5pY2hlIChzdXBwb3J0aW5nIGEgbW9yZSB0YXJnZXRlZCBwcm9kdWN0IGRldmVsb3BtZW50IHN0cmF0ZWd5KS4KCgojIyBJbnRlcm5hdGlvbmFsIEJyZWFkIFVzYWdlIFB1cnBvc2UgKEJyaW9jaGUvQmFndWV0dGUpCgpgYGB7ciBpbnRsLWJyZWFkLXB1cnBvc2UtdGFibGUsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CmJyaW9jaGVQdXJjaCA8LSBicmlvY2hlUHVyY2ggJT4lCiAgbXV0YXRlKHBjdCA9IHJvdW5kKDEwMCAqIENvdW50IC8gc3VtKENvdW50KSwgMSkpICU+JQogIGFycmFuZ2UoZGVzYyhDb3VudCkpCgpicmlvY2hlUHVyY2gKYGBgCgoKCmBgYHtyIGludGwtYnJlYWQtcHVycG9zZS1wbG90LCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQpicmlvY2hlUHVyY2ggJT4lCiAgbXV0YXRlKEludGVybmF0aW9uYWxfQnJlYWRfVXNhZ2VfUHVycG9zZSA9CiAgICAgICAgICAgZmN0X3Jlb3JkZXIoSW50ZXJuYXRpb25hbF9CcmVhZF9Vc2FnZV9QdXJwb3NlLCBDb3VudCkpICU+JQogIGdncGxvdChhZXMoeCA9IEludGVybmF0aW9uYWxfQnJlYWRfVXNhZ2VfUHVycG9zZSwgeSA9IENvdW50KSkgKwogIGdlb21fY29sKCkgKwogIGdlb21fdGV4dChhZXMobGFiZWwgPSBwYXN0ZTAocGN0LCAiJSIpKSwgdmp1c3QgPSAtMC4zLCBzaXplID0gMykgKwogIGxhYnMoCiAgICB0aXRsZSA9ICJXaHkgQ29uc3VtZXJzIEVhdCBJbnRlcm5hdGlvbmFsIEJyZWFkcyAoQnJpb2NoZS9CYWd1ZXR0ZSkiLAogICAgeCA9ICJVc2FnZSBQdXJwb3NlIiwKICAgIHkgPSAiTnVtYmVyIG9mIFJlc3BvbmRlbnRzIgogICkgKwogIHRoZW1lX21pbmltYWwoKSArCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSAyMCwgaGp1c3QgPSAxKSkKYGBgCgoKPioqSW50ZXJwcmV0YXRpb246KiogIApJbnRlcm5hdGlvbmFsIGJyZWFkcyAoZS5nLiwgYnJpb2NoZS9iYWd1ZXR0ZSkgYXJlIGNvbnN1bWVkIG1haW5seSBmb3Igc3BlY2lmaWMgb2NjYXNpb25zIHJhdGhlciB0aGFuIGFzIGEgZGFpbHkgc3RhcGxlLiBUaGlzIGFsaWducyB3aXRoIG91ciBxdWFsaXRhdGl2ZSBmaW5kaW5ncyB0aGF0IGJyaW9jaGUgaXMgb2Z0ZW4gc2VlbiBhcyBhbiBpbmR1bGdlbnQgb3Ig4oCcc3BlY2lhbCBtb21lbnTigJ0gcHJvZHVjdCAoZS5nLiwgd2Vla2VuZCBicmVha2Zhc3RzLCBndWVzdHMsIHNuYWNraW5nKSwgc3VnZ2VzdGluZyB0aGF0IGEgcHJlbWl1bS9pbnRlcm5hdGlvbmFsIGxpbmUgd291bGQgbGlrZWx5IGJlIGFuICphZGphY2VudCogZ3Jvd3RoIG9wcG9ydHVuaXR5IHJhdGhlciB0aGFuIGEgcmVwbGFjZW1lbnQgZm9yIGNvcmUgZGFpbHkgYnJlYWRzLgoKIyAuIFVOTyBRdWVzdGlvbiAxIOKAlCBCcmFuZCBQZXJjZXB0aW9ucyAoMeKAkzUgc2NhbGUpCgojIyBQbG90IChmYWNldGVkIGJhciBjaGFydHMpCgpgYGB7ciB1bm8tcTEtcGxvdH0KcTFfaXRlbSA8LSBuYW1lcyh1bm9fcTEpWzFdICAgIyBmaXJzdCBjb2x1bW4gPSBzdGF0ZW1lbnQgbmFtZSAoZS5nLiwgSGlnaF9RdWFsaXR5KQoKdW5vX3ExX2xvbmcgPC0gdW5vX3ExICU+JQogIHBpdm90X2xvbmdlcihjb2xzID0gd2hlcmUoaXMubnVtZXJpYyksCiAgICAgICAgICAgICAgIG5hbWVzX3RvID0gIlNjYWxlIiwKICAgICAgICAgICAgICAgdmFsdWVzX3RvID0gIkNvdW50IikgJT4lCiAgbXV0YXRlKFNjYWxlID0gYXMuZmFjdG9yKFNjYWxlKSkKCmdncGxvdCh1bm9fcTFfbG9uZywgYWVzKHggPSBTY2FsZSwgeSA9IENvdW50LCBmaWxsID0gU2NhbGUpKSArCiAgZ2VvbV9jb2wod2lkdGggPSAwLjcpICsKICBmYWNldF93cmFwKH4gVU5PX0FncmVlbWVudF9MZXZlbCwgc2NhbGVzID0gImZyZWVfeSIpICsKICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBsaWtlcnRfY29sb3JzKSArCiAgbGFicygKICAgIHRpdGxlID0gIlVOTyBCcmFuZCBQZXJjZXB0aW9ucyAoMSA9IExvdywgNSA9IEhpZ2gpIiwKICAgIHggPSAiQWdyZWVtZW50IExldmVsIiwKICAgIHkgPSAiTnVtYmVyIG9mIFJlc3BvbmRlbnRzIgogICkgKwogIHRoZW1lX21pbmltYWwoYmFzZV9zaXplID0gMTEpICsKICB0aGVtZSgKICAgIGxlZ2VuZC5wb3NpdGlvbiA9ICJib3R0b20iLAogICAgc3RyaXAudGV4dCA9IGVsZW1lbnRfdGV4dChmYWNlID0gImJvbGQiKSwKICAgIHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoZmFjZSA9ICJib2xkIikKICApCmBgYAoKCiMjIOKAnFRvcC1ib3jigJ0gc3VtbWFyeSAoc2ltcGxlLCB2ZXJ5IHVzZWZ1bCkKCgpgYGB7ciB1bm8tcTEtdG9wYm94fQpxMV90b3Bib3ggPC0gdW5vX3ExX2xvbmcgJT4lCiAgZ3JvdXBfYnkoLmRhdGFbW3ExX2l0ZW1dXSkgJT4lCiAgc3VtbWFyaXNlKAogICAgdG90YWwgPSBzdW0oQ291bnQsIG5hLnJtPVRSVUUpLAogICAgdG9wYm94XzRfNSA9IHN1bShDb3VudFtTY2FsZSAlaW4lIGMoIjQiLCI1IildLCBuYS5ybT1UUlVFKSwKICAgIHRvcGJveF9wY3QgPSByb3VuZCgxMDAgKiB0b3Bib3hfNF81IC8gdG90YWwsIDEpLAogICAgLmdyb3VwcyA9ICJkcm9wIgogICkgJT4lCiAgYXJyYW5nZShkZXNjKHRvcGJveF9wY3QpKQoKcTFfdG9wYm94CgpgYGAKCjxkaXYgY2xhc3M9Im5vdGUtYm94Ij4KPHNwYW4gY2xhc3M9Im5vdGUtdGl0bGUiPlVOTyBCcmFuZCBQZXJjZXB0aW9ucyAoUTEpIOKAlCBLZXkgSW5zaWdodHM8L3NwYW4+Cgo8dWw+CiAgPGxpPjxzdHJvbmc+U3Ryb25nZXN0IGFzc29jaWF0aW9uOjwvc3Ryb25nPiBOZXcgUHJvZHVjdCBTdWNjZXNzICg1NS40JSk8L2xpPgogIDxsaT48c3Ryb25nPlNvbGlkIGNvcmUgc3RyZW5ndGhzOjwvc3Ryb25nPiBSZWxpYWJsZSBFdmVyeWRheSAoNDUuOCUpLCBWYWx1ZSBmb3IgTW9uZXkgKDQyLjIlKSwgSGVhbHRoeSBUcnVzdCAoNDEuMCUpPC9saT4KICA8bGk+PHN0cm9uZz5XZWFrZXIgcGVyY2VwdGlvbnM6PC9zdHJvbmc+IFByZW1pdW0gQnJhbmQgKDMyLjUlKSwgQXR0cmFjdGl2ZSBQYWNrYWdpbmcgKDMxLjMlKTwvbGk+CjwvdWw+CgpPdmVyYWxsLCByZXNwb25kZW50cyBiZWxpZXZlIHRoYXQgVU5PIGNhbiBzdWNjZXNzZnVsbHkgZGV2ZWxvcCBuZXcgcHJvZHVjdHMgYW5kIHBlcmNlaXZlIGl0IGFzIGEgcmVsaWFibGUgZXZlcnlkYXkgYnJhbmQgb2ZmZXJpbmcgcmVhc29uYWJsZSB2YWx1ZSBhbmQgaGVhbHRoLXJlbGF0ZWQgdHJ1c3QuIEhvd2V2ZXIsIHByZW1pdW0gYnJhbmQgcGVyY2VwdGlvbiBhbmQgcGFja2FnaW5nIGF0dHJhY3RpdmVuZXNzIGFyZSByZWxhdGl2ZWx5IHdlYWtlci4gVGhpcyBzdWdnZXN0cyB0aGF0IHdoaWxlIFVOTyBoYXMgdGhlIGNyZWRpYmlsaXR5IHRvIGxhdW5jaCBhIHByZW1pdW0gbGluZSwgcHJlbWl1bSBjdWVz4oCUcGFydGljdWxhcmx5IHBhY2thZ2luZyBkZXNpZ24gYW5kIHBvc2l0aW9uaW5n4oCUbXVzdCBiZSBzdHJlbmd0aGVuZWQgdG8ganVzdGlmeSBoaWdoZXIgcHJpY2luZy4KPC9kaXY+CgoKIyAuIFVOTyBRdWVzdGlvbiAyIOKAlCBBY3Rpb24gTGlrZWxpaG9vZCBmb3IgUHJlbWl1bSBCcmVhZCAoMeKAkzcgc2NhbGUpCgpgYGB7ciB1bm8tcTItcGxvdH0KcTJfaXRlbSA8LSBuYW1lcyh1bm9fcTIpWzFdCgp1bm9fcTJfbG9uZyA8LSB1bm9fcTIgJT4lCiAgcGl2b3RfbG9uZ2VyKAogICAgY29scyA9IHdoZXJlKGlzLm51bWVyaWMpLAogICAgbmFtZXNfdG8gPSAiU2NhbGUiLAogICAgdmFsdWVzX3RvID0gIkNvdW50IgogICkgJT4lCiAgbXV0YXRlKFNjYWxlID0gYXMuZmFjdG9yKFNjYWxlKSkKCmdncGxvdCh1bm9fcTJfbG9uZywgYWVzKHggPSBTY2FsZSwgeSA9IENvdW50LCBmaWxsID0gU2NhbGUpKSArCiAgZ2VvbV9jb2wod2lkdGggPSAwLjcpICsKICBmYWNldF93cmFwKGFzLmZvcm11bGEocGFzdGUoIn4iLCBxMl9pdGVtKSksIHNjYWxlcyA9ICJmcmVlX3kiKSArCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gbGlrZXJ0N19jb2xvcnMpICsKICBsYWJzKAogICAgdGl0bGUgPSAiTGlrZWxpaG9vZCBvZiBBY3Rpb25zIGlmIFVOTyBMYXVuY2hlcyBQcmVtaXVtIEJyZWFkICgxID0gTG93LCA3ID0gSGlnaCkiLAogICAgeCA9ICJMaWtlbGlob29kIExldmVsIiwKICAgIHkgPSAiTnVtYmVyIG9mIFJlc3BvbmRlbnRzIgogICkgKwogIHRoZW1lX21pbmltYWwoYmFzZV9zaXplID0gMTEpICsKICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAiYm90dG9tIikKCgoKYGBgCgoKIyMgVG9wLWJveCBmb3IgNy1wb2ludCAoNuKAkzcpCgoKYGBge3IgdW5vLXEyLXRvcGJveH0KcTJfdG9wYm94IDwtIHVub19xMl9sb25nICU+JQogIGdyb3VwX2J5KC5kYXRhW1txMl9pdGVtXV0pICU+JQogIHN1bW1hcmlzZSgKICAgIHRvdGFsID0gc3VtKENvdW50LCBuYS5ybT1UUlVFKSwKICAgIHRvcGJveF82XzcgPSBzdW0oQ291bnRbU2NhbGUgJWluJSBjKCI2IiwiNyIpXSwgbmEucm09VFJVRSksCiAgICB0b3Bib3hfcGN0ID0gcm91bmQoMTAwICogdG9wYm94XzZfNyAvIHRvdGFsLCAxKSwKICAgIC5ncm91cHMgPSAiZHJvcCIKICApICU+JQogIGFycmFuZ2UoZGVzYyh0b3Bib3hfcGN0KSkKCnEyX3RvcGJveAoKYGBgCgo+KipCZWhhdmlvcmFsIGludGVudGlvbnMgKFEyKSDigJQgZnVubmVsIGludGVycHJldGF0aW9uOioqICAKVGhlIHN0cm9uZ2VzdCBpbnRlbnRpb24gaXMgdHJ5aW5nIFVOT+KAmXMgcHJlbWl1bSBicmVhZCBhdCBsZWFzdCBvbmNlLCBpbmRpY2F0aW5nIGhpZ2ggdHJpYWwgcG90ZW50aWFsLiBJbiBjb250cmFzdCwgd2lsbGluZ25lc3MgdG8gcGF5IGEgcHJlbWl1bSBwcmljZSBpcyBtb3JlIG1vZGVyYXRlIGFuZCBwdXJjaGFzZS1vbi1wcm9tb3Rpb24gYXBwZWFycyBpbXBvcnRhbnQsIHN1Z2dlc3RpbmcgcHJpY2Ugc2Vuc2l0aXZpdHkuIEZvbGxvd2luZyBwcm9kdWN0IGFubm91bmNlbWVudHMgb25saW5lIGlzIGxvdywgaW1wbHlpbmcgdGhhdCBhd2FyZW5lc3MtYnVpbGRpbmcgbWF5IHdvcmsgYmV0dGVyIHRocm91Z2ggaW4tc3RvcmUgdmlzaWJpbGl0eSwgcGFja2FnaW5nLCBhbmQgc2FtcGxpbmcgcmF0aGVyIHRoYW4gcmVseWluZyBvbiBjb25zdW1lcnMgYWN0aXZlbHkgdHJhY2tpbmcgdXBkYXRlcyBvbmxpbmUuCgoKPGRpdiBjbGFzcz0ibm90ZS1ib3giPgo8c3BhbiBjbGFzcz0ibm90ZS10aXRsZSI+TWFuYWdlcmlhbCBJbnRlcnByZXRhdGlvbiAoUTIpPC9zcGFuPjxicj4KClRyaWFsIGludGVudGlvbiBmb3IgYSBwcmVtaXVtIFVOTyBicmVhZCBpcyBoaWdoLCBpbmRpY2F0aW5nIHN0cm9uZyBjdXJpb3NpdHkgYW5kIG9wZW5uZXNzIGFtb25nIGNvbnN1bWVycy4gSG93ZXZlciwgd2lsbGluZ25lc3MgdG8gcGF5IGEgaGlnaGVyIHByaWNlIGlzIG1vcmUgbW9kZXJhdGUsIGFuZCBidXlpbmcgb24gcHJvbW90aW9uIGFwcGVhcnMgaW1wb3J0YW50LiBUaGlzIHN1Z2dlc3RzIHRoYXQgcHJlbWl1bSBhZG9wdGlvbiB3aWxsIGRlcGVuZCBvbiBjbGVhciB2YWx1ZSBjb21tdW5pY2F0aW9uIGFuZCBjb250cm9sbGVkIHByaWNpbmcgcmF0aGVyIHRoYW4gcHVyZWx5IGJyYW5kLWRyaXZlbiB3aWxsaW5nbmVzcyB0byBwYXkuCjwvZGl2PgoKCiMgLiBVTk8gUXVlc3Rpb24gMyDigJQgQ29tcGFyYXRpdmUgVU5PIFJhdGluZ3MgKFZlcnkgQmFkIOKGkiBWZXJ5IEdvb2QpCgpgYGB7ciB1bm8tcTMtcGxvdH0KcTNfaXRlbSA8LSBuYW1lcyh1bm9fcTMpWzFdICAjIGF0dHJpYnV0ZSBuYW1lIGNvbHVtbiAoVGFzdGUsIEZyZXNobmVzcywgZXRjLikKCnVub19xM19sb25nIDwtIHVub19xMyAlPiUKICBwaXZvdF9sb25nZXIoY29scyA9IC1hbGxfb2YocTNfaXRlbSksCiAgICAgICAgICAgICAgIG5hbWVzX3RvID0gIkV2YWx1YXRpb24iLAogICAgICAgICAgICAgICB2YWx1ZXNfdG8gPSAiQ291bnQiKSAlPiUKICBtdXRhdGUoRXZhbHVhdGlvbiA9IGZhY3RvcihFdmFsdWF0aW9uLCBsZXZlbHMgPSBjKCJWZXJ5IEJhZCIsIkJhZCIsIlNhbWUiLCJHb29kIiwiVmVyeSBHb29kIikpKQoKZ2dwbG90KHVub19xM19sb25nLCBhZXMoeCA9IEV2YWx1YXRpb24sIHkgPSBDb3VudCwgZmlsbCA9IEV2YWx1YXRpb24pKSArCiAgZ2VvbV9jb2wod2lkdGggPSAwLjcpICsKICBmYWNldF93cmFwKH4gQ29tcGFyYXRpdmVfVU5PX1JhdGluZ3MsIHNjYWxlcyA9ICJmcmVlX3kiKSArCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gZXZhbF9jb2xvcnMpICsKICBsYWJzKAogICAgdGl0bGUgPSAiVU5PIHZzIE90aGVyIEJyZWFkIEJyYW5kcyAoQ29tcGFyYXRpdmUgRXZhbHVhdGlvbikiLAogICAgeCA9ICJFdmFsdWF0aW9uIiwKICAgIHkgPSAiTnVtYmVyIG9mIFJlc3BvbmRlbnRzIgogICkgKwogIHRoZW1lX21pbmltYWwoYmFzZV9zaXplID0gMTEpICsKICB0aGVtZSgKICAgIGxlZ2VuZC5wb3NpdGlvbiA9ICJib3R0b20iLAogICAgc3RyaXAudGV4dCA9IGVsZW1lbnRfdGV4dChmYWNlID0gImJvbGQiKSwKICAgIHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoZmFjZSA9ICJib2xkIikKICApCgoKYGBgCgo+KipDb21wYXJhdGl2ZSBFdmFsdWF0aW9uIG9mIFVOTyB2cyBPdGhlciBCcmVhZCBCcmFuZHMqKgpUaGlzIHNlY3Rpb24gZXZhbHVhdGVzIGhvdyBVTk8gcGVyZm9ybXMgcmVsYXRpdmUgdG8gb3RoZXIgcGFja2FnZWQgYnJlYWQgYnJhbmRzIGFjcm9zcyBrZXkgYXR0cmlidXRlcyBzdWNoIGFzIHRhc3RlLCBmcmVzaG5lc3MsIHByaWNlLCBwYWNrYWdpbmcsIGhlYWx0aGluZXNzLCBhdmFpbGFiaWxpdHksIGlubm92YXRpdmVuZXNzLCBhbmQgcHJlbWl1bSBmZWVsLgpPdmVyYWxsLCBVTk8gcGVyZm9ybXMgc3Ryb25nbHkgb24gY29yZSBmdW5jdGlvbmFsIGF0dHJpYnV0ZXMuIFRhc3RlIGFuZCBhdmFpbGFiaWxpdHkgcmVjZWl2ZSBhIGhpZ2ggY29uY2VudHJhdGlvbiBvZiDigJxHb29k4oCdIGFuZCDigJxWZXJ5IEdvb2TigJ0gcmF0aW5ncywgaW5kaWNhdGluZyB0aGF0IGNvbnN1bWVycyBwZXJjZWl2ZSBVTk8gYXMgY29tcGV0aXRpdmUgb3Igc3VwZXJpb3IgdG8gb3RoZXIgYnJhbmRzIGluIGV2ZXJ5ZGF5IGNvbnN1bXB0aW9uIGNvbnRleHRzLiBIZWFsdGhpbmVzcyBhbHNvIHNob3dzIGEgZmF2b3JhYmxlIGRpc3RyaWJ1dGlvbiwgc3VwcG9ydGluZyBlYXJsaWVyIHF1YWxpdGF0aXZlIGluc2lnaHRzIHRoYXQgcG9zaXRpb24gVU5PIGFzIGEgcmVsaWFibGUgYW5kIHRydXN0ZWQgb3B0aW9uIGZvciBkYWlseSBicmVhZCBuZWVkcy4KSW4gY29udHJhc3QsIGF0dHJpYnV0ZXMgcmVsYXRlZCB0byBwcmVtaXVtIHBvc2l0aW9uaW5n4oCUcGFydGljdWxhcmx5IHByZW1pdW0gZmVlbCBhbmQgaW5ub3ZhdGl2ZW5lc3PigJRzaG93IGEgbW9yZSBtaXhlZCBkaXN0cmlidXRpb24sIHdpdGggbWFueSByZXNwb25kZW50cyBzZWxlY3Rpbmcg4oCcU2FtZeKAnSByYXRoZXIgdGhhbiDigJxHb29k4oCdIG9yIOKAnFZlcnkgR29vZC7igJ0gVGhpcyBzdWdnZXN0cyB0aGF0IHdoaWxlIFVOTyBpcyBub3QgcGVyY2VpdmVkIGFzIHdlYWsgaW4gdGhlc2UgZGltZW5zaW9ucywgaXQgaXMgbm90IHlldCBjbGVhcmx5IGRpZmZlcmVudGlhdGVkIGFzIGEgcHJlbWl1bSBvciBoaWdobHkgaW5ub3ZhdGl2ZSBicmFuZCBjb21wYXJlZCB0byBhbHRlcm5hdGl2ZXMuCgo+VGhlc2UgcmVzdWx0cyByZWluZm9yY2UgdGhlIGludGVycHJldGF0aW9uIHRoYXQgVU5P4oCZcyBjdXJyZW50IGJyYW5kIHN0cmVuZ3RoIGxpZXMgaW4gZnVuY3Rpb25hbCBwZXJmb3JtYW5jZSBhbmQgcmVsaWFiaWxpdHkgcmF0aGVyIHRoYW4gc3ltYm9saWMgb3IgcHJlbWl1bSBkaWZmZXJlbnRpYXRpb24uIENvbnNlcXVlbnRseSwgYW55IHByZW1pdW0gYnJlYWQgZXh0ZW5zaW9uIHdvdWxkIG5lZWQgdG8gcmVseSBvbiBzdHJvbmdlciBpbm5vdmF0aW9uIHNpZ25hbHMsIHBhY2thZ2luZyBkZXNpZ24sIGFuZCBwcm9kdWN0IHN0b3J5dGVsbGluZyB0byBzaGlmdCBjb25zdW1lciBwZXJjZXB0aW9ucyBiZXlvbmQgcGFyaXR5IHdpdGggZXhpc3RpbmcgYnJhbmRzLgoKCiMgLiBDb25qb2ludCBSZWdyZXNzaW9uIChJbmRpdmlkdWFsLUxldmVsIE1vZGVsKQoKYGBge3IgY29uam9pbnQtbW9kZWx9CiMgRW5zdXJlIGNhdGVnb3JpY2FsIGZpZWxkcyBhcmUgdHJlYXRlZCBhcyBmYWN0b3JzCmNvbmpvaW50IDwtIGNvbmpvaW50ICU+JQogIG11dGF0ZSgKICAgIEJyZWFkX1R5cGUgICA9IGFzLmZhY3RvcihCcmVhZF9UeXBlKSwKICAgIFNsaWNlX1R5cGUgICA9IGFzLmZhY3RvcihTbGljZV9UeXBlKSwKICAgIFBhY2thZ2VfVHlwZSA9IGFzLmZhY3RvcihQYWNrYWdlX1R5cGUpLAogICAgUHJpY2UgICAgICAgID0gYXMuZmFjdG9yKFByaWNlKQogICkKCnJhdGluZ19tb2RlbCA8LSBsbShSYXRpbmcgfiBCcmVhZF9UeXBlICsgU2xpY2VfVHlwZSArIFByaWNlICsgUGFja2FnZV9UeXBlLCBkYXRhID0gY29uam9pbnQpCnN1bW1hcnkocmF0aW5nX21vZGVsKQoKYGBgCgo+KipDb25qb2ludCBSZWdyZXNzaW9uIFJlc3VsdHMqKgoKPkEgcmF0aW5nLWJhc2VkIGNvbmpvaW50IHJlZ3Jlc3Npb24gd2FzIGVzdGltYXRlZCB0byBleGFtaW5lIGhvdyBkaWZmZXJlbnQgcHJvZHVjdCBhdHRyaWJ1dGVzIGluZmx1ZW5jZSBvdmVyYWxsIGJyZWFkIHJhdGluZ3MuIFRoZSBtb2RlbCBpcyBzdGF0aXN0aWNhbGx5IHNpZ25pZmljYW50IChGLXRlc3QgcCA8IDAuMDAxKSwgaW5kaWNhdGluZyB0aGF0IHRoZSBpbmNsdWRlZCBhdHRyaWJ1dGVzIGNvbGxlY3RpdmVseSBleHBsYWluIHZhcmlhdGlvbiBpbiBjb25zdW1lciBwcmVmZXJlbmNlcy4gV2hpbGUgdGhlIFItc3F1YXJlZCB2YWx1ZSBpcyBtb2Rlc3QsIHRoaXMgaXMgZXhwZWN0ZWQgaW4gY29uc3VtZXIgcHJlZmVyZW5jZSBkYXRhIGFuZCBkb2VzIG5vdCBsaW1pdCB0aGUgaW50ZXJwcmV0YWJpbGl0eSBvZiByZWxhdGl2ZSBhdHRyaWJ1dGUgZWZmZWN0cy4KCioqVGhlIHJlZ3Jlc3Npb24gcmVzdWx0cyByZXZlYWwgY2xlYXIgZGlmZmVyZW5jZXMgaW4gaG93IGNvbnN1bWVycyBldmFsdWF0ZSBwcm9kdWN0IGF0dHJpYnV0ZXM6KioKCi0gKipCcmVhZCBUeXBlOioqIFdob2xlIGdyYWluIGJyZWFkIGhhcyBhIHBvc2l0aXZlIGFuZCBzdGF0aXN0aWNhbGx5IHNpZ25pZmljYW50IGVmZmVjdCBvbiByYXRpbmdzLCBpbmRpY2F0aW5nIGEgc3Ryb25nIHByZWZlcmVuY2UgZm9yIGhlYWx0aGllciBvciBtb3JlIG5hdHVyYWwgYnJlYWQgb3B0aW9ucy4gVHJhZGl0aW9uYWwgYnJlYWQgZG9lcyBub3Qgc2lnbmlmaWNhbnRseSBpbmNyZWFzZSByYXRpbmdzIHJlbGF0aXZlIHRvIHRoZSByZWZlcmVuY2UgY2F0ZWdvcnkuCgotICoqU2xpY2UgVHlwZToqKiBCb3RoIHRoaWNrIGFuZCB0aGluIHNsaWNlIG9wdGlvbnMgbmVnYXRpdmVseSBhZmZlY3QgcmF0aW5ncy4gVGhpcyBzdWdnZXN0cyB0aGF0IGNvbnN1bWVycyBwcmVmZXIgYSBzdGFuZGFyZCBzbGljZSB0aGlja25lc3MgYW5kIHBlbmFsaXplIGRldmlhdGlvbnMgZnJvbSBpdC4KCi0gKipQcmljZToqKiBIaWdoZXIgcHJpY2VzIHJlZHVjZSByYXRpbmdzLCBwYXJ0aWN1bGFybHkgYXQgdGhlIGV4dHJlbWUgbGV2ZWwgKDE1MCBUTCksIHdoaWNoIGhhcyBhIHN0cm9uZyBuZWdhdGl2ZSBlZmZlY3QuIExvd2VyIHByaWNlIGluY3JlYXNlcyBzaG93IHdlYWtlciBhbmQgbW9zdGx5IGluc2lnbmlmaWNhbnQgZWZmZWN0cywgc3VnZ2VzdGluZyBzb21lIHRvbGVyYW5jZSBhdCBtb2RlcmF0ZSBwcmljZSBsZXZlbHMuCgotICoqUGFja2FnZSBUeXBlOioqIFBsYXN0aWMgcGFja2FnaW5nIGhhcyB0aGUgc3Ryb25nZXN0IG5lZ2F0aXZlIGltcGFjdCBvbiByYXRpbmdzLiBUaGlzIGhpZ2hsaWdodHMgcGFja2FnaW5nIGFzIGEgY3JpdGljYWwgZHJpdmVyIG9mIHByZWZlcmVuY2UgYW5kIHN1Z2dlc3RzIHRoYXQgcGxhc3RpYyBpcyBwZXJjZWl2ZWQgYXMgaW5jb25zaXN0ZW50IHdpdGggcXVhbGl0eSBvciBwcmVtaXVtIHBvc2l0aW9uaW5nLgoKCgojIyBDb2VmZmljaWVudCBwbG90IChlYXN5IHRvIHVuZGVyc3RhbmQgZm9yIHByZXNlbnRhdGlvbikKCgpgYGB7ciBjb25qb2ludC1jb2VmLXBsb3R9CmNvZWZfZGYgPC0gdGlkeShyYXRpbmdfbW9kZWwpICU+JSBmaWx0ZXIodGVybSAhPSAiKEludGVyY2VwdCkiKQoKZ2dwbG90KGNvZWZfZGYsIGFlcyh4ID0gZXN0aW1hdGUsIHkgPSByZW9yZGVyKHRlcm0sIGVzdGltYXRlKSkpICsKICBnZW9tX3BvaW50KHNpemUgPSAzKSArCiAgZ2VvbV9lcnJvcmJhcmgoYWVzKHhtaW4gPSBlc3RpbWF0ZSAtIDEuOTYqc3RkLmVycm9yLCB4bWF4ID0gZXN0aW1hdGUgKyAxLjk2KnN0ZC5lcnJvciksIGhlaWdodCA9IDAuMikgKwogIGdlb21fdmxpbmUoeGludGVyY2VwdCA9IDAsIGxpbmV0eXBlID0gImRhc2hlZCIpICsKICBsYWJzKHRpdGxlID0gIkNvbmpvaW50IFJlZ3Jlc3Npb246IEVmZmVjdCBvZiBBdHRyaWJ1dGVzIG9uIFJhdGluZyIsCiAgICAgICB4ID0gIkVzdGltYXRlZCBpbXBhY3Qgb24gUmF0aW5nIiwgeSA9ICJBdHRyaWJ1dGUgbGV2ZWwiKSArCiAgdGhlbWVfbWluaW1hbCgpCgpgYGAKCj5PdmVyYWxsLCBwYWNrYWdpbmcgYW5kIHByaWNlIGVtZXJnZSBhcyB0aGUgbW9zdCBpbmZsdWVudGlhbCBhdHRyaWJ1dGVzIGluIHNoYXBpbmcgY29uc3VtZXIgcmF0aW5ncywgZm9sbG93ZWQgYnkgYnJlYWQgdHlwZS4gU2xpY2UgdHlwZSBwbGF5cyBhIHNlY29uZGFyeSByb2xlIGFuZCBhcHBlYXJzIHRvIGZ1bmN0aW9uIGFzIGEgaHlnaWVuZSBmYWN0b3IgcmF0aGVyIHRoYW4gYSBkaWZmZXJlbnRpYXRvci4KCgojIC4gSHlwb3RoZXNpcyBFdmFsdWF0aW9uCgoqKkgxIChNYXJrZXQgUGVuZXRyYXRpb24pOioqICAKU3VwcG9ydGVkLiBVTk8gaXMgcGVyY2VpdmVkIGFzIHJlbGlhYmxlLCBhY2Nlc3NpYmxlLCBhbmQgY29tcGV0aXRpdmUgaW4gdGFzdGUgYW5kIGhlYWx0aGluZXNzLiBUaGVzZSBhdHRyaWJ1dGVzIHN1cHBvcnQgY29udGludWVkIHBlbmV0cmF0aW9uIGluIHRoZSBjb3JlIHBhY2thZ2VkIGJyZWFkIG1hcmtldC4KCioqSDIgKFByb2R1Y3QgRGV2ZWxvcG1lbnQg4oCTIERpZmZlcmVudGlhdGlvbik6KiogIApQYXJ0aWFsbHkgc3VwcG9ydGVkLiBDb25zdW1lcnMgc2hvdyBzdHJvbmcgd2lsbGluZ25lc3MgdG8gdHJ5IGEgcHJlbWl1bSBVTk8gYnJlYWQsIGJ1dCBwcmVtaXVtIHBlcmNlcHRpb25zIGFyZSBub3QgeWV0IHdlbGwgZXN0YWJsaXNoZWQuIERpZmZlcmVudGlhdGlvbiB3b3VsZCByZXF1aXJlIGNsZWFyIGlubm92YXRpb24gYW5kIHBhY2thZ2luZyBjdWVzLgoKKipIMyAoUHJlbWl1bSBBZG9wdGlvbiBQb3RlbnRpYWwpOioqICAKUGFydGlhbGx5IHN1cHBvcnRlZC4gV2hpbGUgdHJpYWwgaW50ZW50IGlzIGhpZ2gsIHN1c3RhaW5lZCBiZWhhdmlvcnMgc3VjaCBhcyB3ZWVrbHkgcHVyY2hhc2UgYW5kIHdpbGxpbmduZXNzIHRvIHBheSBhIGhpZ2hlciBwcmljZSBhcmUgbW9yZSBtb2RlcmF0ZSwgc3VnZ2VzdGluZyBzZWxlY3RpdmUgcmF0aGVyIHRoYW4gbWFzcyBhZG9wdGlvbi4KCioqSDQgKEJyYW5kIFN0cmV0Y2ggdG8gUHJlbWl1bSk6KiogIApDb25kaXRpb25hbGx5IHN1cHBvcnRlZC4gVU5PIGhhcyBzdHJvbmcgYnJhbmQgY3JlZGliaWxpdHksIGJ1dCBwcmVtaXVtIHBvc2l0aW9uaW5nIGlzIHdlYWtlci4gQSBwcmVtaXVtIGV4dGVuc2lvbiBpcyBmZWFzaWJsZSBpZiBzdXBwb3J0ZWQgYnkgZGlzdGluY3RpdmUgcGFja2FnaW5nLCBoZWFsdGgtb3JpZW50ZWQgcG9zaXRpb25pbmcsIGFuZCBjb250cm9sbGVkIHByaWNpbmcuCgoKCiMgLiBNYW5hZ2VyaWFsIFJlY29tbWVuZGF0aW9uIChEZWNpc2lvbjogVHJhZGl0aW9uYWwgdnMgQnJpb2NoZSkKCkJhc2VkIG9uIHRoZSBjb21iaW5lZCBxdWFsaXRhdGl2ZSBpbnNpZ2h0cywgc3VydmV5IGZpbmRpbmdzLCBhbmQgY29uam9pbnQgcmVncmVzc2lvbiByZXN1bHRzLCB3ZSByZWNvbW1lbmQgYSBmb2N1c2VkIHByb2R1Y3QgZGV2ZWxvcG1lbnQgc3RyYXRlZ3kgcmF0aGVyIHRoYW4gYSBicm9hZCByZXBvc2l0aW9uaW5nIG9mIHRoZSBjb3JlIFVOTyBwb3J0Zm9saW8uCgpVTk8gc2hvdWxkIGludHJvZHVjZSBhIHByZW1pdW0gb3IgaW50ZXJuYXRpb25hbC1zdHlsZSBicmVhZCBsaW5lIGFzIGEgY29tcGxlbWVudGFyeSBvZmZlcmluZywgdGFyZ2V0aW5nIHNwZWNpZmljIGNvbnN1bXB0aW9uIG9jY2FzaW9ucyBzdWNoIGFzIHNwZWNpYWwgYnJlYWtmYXN0cywgZ3Vlc3RzLCBvciBpbmR1bGdlbnQgc25hY2tpbmcuIFRoZSBzdWNjZXNzIG9mIHRoaXMgZXh0ZW5zaW9uIHdpbGwgZGVwZW5kIGhlYXZpbHkgb24gbm9uLXBsYXN0aWMsIHByZW1pdW0gcGFja2FnaW5nLCBjbGVhciBoZWFsdGggb3IgcXVhbGl0eSBjdWVzLCBhbmQgYSBwcmljaW5nIHN0cmF0ZWd5IHRoYXQgcmVtYWlucyB3aXRoaW4gYWNjZXB0YWJsZSB0aHJlc2hvbGRzLgoKQXQgdGhlIHNhbWUgdGltZSwgVU5PIHNob3VsZCBjb250aW51ZSBzdHJlbmd0aGVuaW5nIGl0cyBjb3JlIHBhY2thZ2VkIGJyZWFkIGJ1c2luZXNzIGJ5IHJlaW5mb3JjaW5nIHRydXN0LCBmcmVzaG5lc3MsIGFuZCBhdmFpbGFiaWxpdHnigJRhdHRyaWJ1dGVzIHdoZXJlIHRoZSBicmFuZCBhbHJlYWR5IHBlcmZvcm1zIHN0cm9uZ2x5LgoKCg==