Mexico’s exports performance

Mexico exports characteristics

• Mexico’s exports grew strongly between 2015 and 2025, almost doubling in total value. This shows how important international trade is for the Mexican economy.

• Around 90% of exports come from manufactured goods, especially automotive, electronics, and machinery. Mexico is highly specialized in industrial production.

• More than 80% of exports go to the United States. This means Mexico depends heavily on the U.S. market and regional supply chains.

• Even with challenges such as COVID-19 and the renegotiation of NAFTA into USMCA, exports recovered quickly and continued growing.

Contribution of Panel Data Analysis to Understanding Export Performance

• Panel data combines information across states or sectors and across time. This helps us see differences between regions and how exports change each year.

• It allows us to control for characteristics that do not change over time, such as geography or industrial structure. This makes the analysis more accurate.

• Panel models help separate long-term structural factors from short-term shocks, such as temporary tariff changes.

Use of Panel Data for Short‑Term Export Prediction

• We can use past export trends from different states or sectors to estimate what could happen in the next 1–2 years.

• It is possible to include variables like exchange rate, U.S. economic growth, or tariff changes to simulate different scenarios.

• Predictions can be made at the state or sector level, not only for the whole country. This gives more specific and useful results.

Role of Business Intelligence and Predictive Analytics for Identifying Vulnerability During USMCA Negotiations

• Business Intelligence tools can measure how much each state or sector depends on exports to the U.S. This helps identify which ones are more exposed to tariff changes.

• Predictive models can estimate how sensitive exports are to new trade rules. With this, we can classify states or industries by level of risk.

• Dashboards and visual tools allow decision makers to monitor export performance before and after policy changes.

• Machine learning techniques can group states or sectors with similar export structures. This helps identify patterns of vulnerability during trade negotiations.

Exports Data Analysis

Data Cleaning and Transforming

library(readxl)
library(tidyverse)
library(plm)
library(sf)
library(rnaturalearth)
library(dplyr)
library(ggplot2)
library(reshape2)
df_expo <- read_excel("C:/Users/Osval/Downloads/inegi_exports_dataset.xlsx", sheet = "exports")
df_ts <- read_excel("C:/Users/Osval/Downloads/inegi_exports_dataset.xlsx", sheet = "ts_exports")
df_data <- read_excel("C:/Users/Osval/Downloads/inegi_exports_dataset.xlsx", sheet = "data")
df_fdi <- read_excel("C:/Users/Osval/Downloads/inegi_exports_dataset.xlsx", sheet = "fdi")

• The original datasets were cleaned and transformed. Export variables were converted from wide format to long format so each row represents one state in one specific year.

df_expolong <- df_expo %>%
  pivot_longer(
    cols = starts_with("real_exports_"),
    names_to = "year",
    names_prefix = "real_exports_",
    values_to = "real_exports"
  )

df_fdilong <- df_fdi %>%
  pivot_longer(
    cols = starts_with("fdi_"),
    names_to = "year",
    names_prefix = "fdi_",
    values_to = "fdi"
  )

• We verified that there were no duplicated observations by state and year before merging the datasets.

df_expolong %>% count(state, year, region) %>% filter(n > 1)
## # A tibble: 0 × 4
## # ℹ 4 variables: state <chr>, year <chr>, region <chr>, n <int>
df_data %>% count(state, year) %>% filter(n > 1)
## # A tibble: 0 × 3
## # ℹ 3 variables: state <chr>, year <dbl>, n <int>
df_fdilong %>% count(state, year, region) %>% filter(n > 1)
## # A tibble: 0 × 4
## # ℹ 4 variables: state <chr>, year <chr>, region <chr>, n <int>

• Different datasets (exports, FDI, macroeconomic variables, and state characteristics) were merged using state and year as key variables.

df_expolong$year <- as.numeric(df_expolong$year)
df_fdilong$year <- as.numeric(df_fdilong$year)
df_data$year <- as.numeric(df_data$year)
panel_full <- df_expolong %>%
  left_join(df_fdilong, by = c("state", "year", "region")) %>%
  left_join(df_data, by = c("state", "year"))

• Missing values were replaced using the average value by state in order to maintain a balanced panel structure.

panel_full <- panel_full %>%
  group_by(state) %>%
  mutate(
    across(
      where(is.numeric), 
      ~ ifelse(is.na(.), mean(., na.rm = TRUE), .)
    )
  ) %>%
  ungroup()

• A panel dataset was created using state and year as indexes, allowing analysis across time and across regions.

panel_data <- pdata.frame(panel_full,
                          index = c("state", "year"))

Exploratory Data Analysis – EDA

Descriptive Statistics

regional_avg <- panel_full %>%
  group_by(region) %>%
  summarise(
    avg_exports = mean(real_exports, na.rm = TRUE),
    avg_fdi = mean(fdi, na.rm = TRUE),
    avg_exchange_rate = mean(exchange_rate, na.rm = TRUE),
    avg_college = mean(college_education, na.rm = TRUE),
    .groups = "drop"
  )
ggplot(regional_avg, aes(x = region, y = avg_exports)) +
  geom_col() +
  labs(title = "Average Exports by Region",
       x = "Region",
       y = "Average Real Exports") +
  theme_minimal()

ggplot(regional_avg, aes(x = region, y = avg_fdi)) +
  geom_col() +
  labs(title = "Average FDI by Region",
       x = "Region",
       y = "Average FDI") +
  theme_minimal()

ggplot(regional_avg, aes(x = region, y = avg_college)) +
  geom_col() +
  labs(title = "Average College Education by Region",
       x = "Region",
       y = "Average College Education") +
  theme_minimal()

ggplot(panel_full, aes(x = real_exports)) +
  geom_histogram(bins = 30) +
  labs(title = "Distribution of Real Exports",
       x = "Real Exports",
       y = "Frequency") +
  theme_minimal()

ggplot(panel_full, aes(x = fdi)) +
  geom_histogram(bins = 30) +
  labs(title = "Distribution of FDI",
       x = "FDI",
       y = "Frequency") +
  theme_minimal()

ggplot(panel_full, aes(x = college_education)) +
  geom_histogram(bins = 30) +
  labs(title = "Distribution of College Education",
       x = "College Education",
       y = "Frequency") +
  theme_minimal()

Statistics of Dispersion

ggplot(panel_full, aes(x = region, y = real_exports)) +
  geom_boxplot() +
  labs(title = "Exports Distribution Across Regions",
       x = "Region",
       y = "Real Exports") +
  theme_minimal()

ggplot(panel_full, aes(x = region, y = fdi)) +
  geom_boxplot() +
  labs(title = "FDI Distribution Across Regions",
       x = "Region",
       y = "FDI") +
  theme_minimal()

ggplot(panel_full, aes(x = region, y = lq_primary)) +
  geom_boxplot() +
  labs(title = "College Education Across Regions",
       x = "Region",
       y = "College Education") +
  theme_minimal()

ggplot(panel_full, aes(x = region, y = lq_secondary)) +
  geom_boxplot() +
  labs(title = "College Education Across Regions",
       x = "Region",
       y = "College Education") +
  theme_minimal()

Visualization across Time

exports_time <- panel_full %>%
  group_by(year) %>%
  summarise(total_exports = sum(real_exports, na.rm = TRUE))

ggplot(exports_time, aes(x = year, y = total_exports)) +
  geom_line(size = 1) +
  labs(title = "Total Exports Inflows in Mexico",
       x = "Year",
       y = "Total Real Exports") +
  theme_minimal()
## 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.

• Total exports show a clear upward trend over the period. There is a temporary decline around the COVID-19 period, but exports recover quickly and continue growing.

exports_region <- panel_full %>%
  group_by(region, year) %>%
  summarise(total_exports = sum(real_exports, na.rm = TRUE),
            .groups = "drop")

ggplot(exports_region, aes(x = year, y = total_exports, color = region)) +
  geom_line(linewidth = 1) +
  labs(title = "Total Exports Inflows by Region",
       x = "Year",
       y = "Total Real Exports",
       color = "Region") +
  theme_minimal()

• Northern regions show higher export levels compared to southern regions.

• The gap between regions remains persistent over time, which suggests structural differences in industrial development.

macro_time <- panel_full %>%
  group_by(year) %>%
  summarise(
    total_exports = sum(real_exports, na.rm = TRUE),
    avg_exchange_rate = mean(exchange_rate, na.rm = TRUE),
    .groups = "drop"
  )
macro_time <- macro_time %>%
  mutate(
    exports_index = total_exports / max(total_exports),
    exchange_index = avg_exchange_rate / max(avg_exchange_rate)
  )
ggplot(macro_time, aes(x = year)) +
  geom_line(aes(y = exports_index, color = "Exports"), linewidth = 1.2) +
  geom_line(aes(y = exchange_index, color = "Exchange Rate"), linewidth = 1.2) +
  labs(title = "Exports Inflows vs Exchange Rate (Indexed)",
       x = "Year",
       y = "Indexed Values",
       color = "") +
  theme_minimal()

• When comparing indexed exports and exchange rate, both variables show similar movements in some years.

• This suggests that exchange rate fluctuations may influence export performance, although the relationship is not perfectly linear.

###Regional Differences

panel_full <- panel_full %>%
  mutate(zone = ifelse(border_distance < 400, "North", "South"))
panel_full <- panel_full %>%
  mutate(zone = ifelse(region %in% c("Noroeste", "Noreste"), 
                       "North", 
                       "South"))
north_south_exports <- panel_full %>%
  group_by(zone) %>%
  summarise(avg_exports = mean(real_exports, na.rm = TRUE),
            .groups = "drop")
ggplot(north_south_exports, aes(x = zone, y = avg_exports)) +
  geom_bar(stat = "identity") +
  labs(title = "Average Exports Inflows: North vs South",
       x = "Region",
       y = "Average Real Exports") +
  theme_minimal()

• States classified as “North” have significantly higher average exports than those in the “South.”

• This confirms the importance of geographic proximity to the U.S. border and industrial concentratio

• Northern states show much higher export volumes. Southern states participate less in international trade.

• Geographic proximity to the U.S. border is a improtant factor. Northern states benefit from lower transportation costs and better access to cross-border infrastructure.

• Industrial structure is different. Northern states have higher concentration in manufacturing and export-oriented industries, while southern states more on primary activities or services.

• Foreign Direct Investment is more concentrated in the North. Many multinational firms are located in northern states due to their connection with U.S. markets.

• Infrastructure and connectivity are generally stronger in northern states, including highways, industrial parks, and customs facilities, which facilitate international trade.

mexico_map <- ne_states(country = "mexico", returnclass = "sf")

setdiff(mexico_map$name, panel_data$state)
## [1] "Nuevo León"       "Yucatán"          "Michoacán"        NA                
## [5] "México"           "Querétaro"        "San Luis Potosí"  "Distrito Federal"
panel_data$state <- recode(panel_data$state,
  "Ciudad de Mexico" = "Distrito Federal",
  "Michoacan" = "Michoacán",
  "Queretaro" = "Querétaro",
  "Mexico" = "México",
  "San Luis Potosi" = "San Luis Potosí",
  "Yucatan" = "Yucatán",
  "Nuevo Leon" = "Nuevo León"
)

• Border states such as Chihuahua and other northern states show higher export levels.

avg_state_exports <- panel_data %>%
  group_by(state) %>%
  summarise(avg_exports = mean(real_exports, na.rm = TRUE),
            .groups = "drop")
map_data <- mexico_map %>%
  left_join(avg_state_exports, by = c("name" = "state"))
ggplot(map_data) +
  geom_sf(aes(fill = avg_exports)) +
  scale_fill_viridis_c(option = "mako", na.value = "grey90") +
  labs(title = "Average Exports Inflows by Mexican State",
       fill = "Avg Exports") +
  theme_minimal()

Correlation and Relationships

scale_fill_gradient2(
  low = "blue",
  mid = "white",
  high = "red",
  midpoint = 0,
  limits = c(-1, 1)
)
## <ScaleContinuous>
##  Range:  
##  Limits:   -1 --    1
corr_data <- panel_data %>%
  select(real_exports, exchange_rate, pop_density, fdi, border_distance, lq_primary,lq_secondary,lq_tertiary, average_daily_salary, crime_rate) %>%
  drop_na()

corr_matrix <- cor(corr_data)

corr_long <- as.data.frame(as.table(corr_matrix))

ggplot(corr_long, aes(Var1, Var2, fill = Freq)) +
  geom_tile() +
  scale_fill_gradient2(
    low = "blue",
    mid = "white",
    high = "red",
    midpoint = 0,
    limits = c(-1, 1)
  ) +
  geom_text(aes(label = round(Freq, 2)), size = 4) +
  labs(title = "Correlation Matrix",
       x = "",
       y = "",
       fill = "Correlation") +
  theme_minimal() +
  theme(axis.text.x = element_text(angle = 45, hjust = 1))

• Exports show positive correlation with FDI and employment concentration in the secondary sector.

• There is a negative relationship between border distance and exports, meaning that states closer to the U.S. tend to export more.

• Some socioeconomic variables such as salary also show positive association with exports, suggesting that more industrialized states have higher income levels.

ggplot(panel_full, aes(x = border_distance, y = real_exports)) +
  geom_point(alpha = 0.6) +
  geom_smooth(method = "lm", se = TRUE, color = "black") +
  labs(title = "Exports Inflows vs Border Disance",
       x = "Border Disance",
       y = "Exports") +
  theme_minimal()
## `geom_smooth()` using formula = 'y ~ x'

• The regression line shows a negative slope. States farther from the border tend to have lower export levels.

ggplot(panel_full, aes(x = lq_secondary, y = real_exports)) +
  geom_point(alpha = 0.6) +
  geom_smooth(method = "lm", se = TRUE, color = "black") +
  labs(title = "Exports Inflows vs Employment concentration in the secondary sector",
       x = "Employment concentration in the secondary sector",
       y = "Real Exports") +
  theme_minimal()
## `geom_smooth()` using formula = 'y ~ x'

• There is a positive relationship. States with stronger industrial specialization export more.

ggplot(panel_full, aes(x = average_daily_salary, y = real_exports)) +
  geom_point(alpha = 0.6) +
  geom_smooth(method = "lm", se = TRUE, color = "black") +
  labs(title = "Exports Inflows vs Average Daily Salary",
       x = "Average Daily Salary",
       y = "Real Exports") +
  theme_minimal()
## `geom_smooth()` using formula = 'y ~ x'

• The relationship appears positive, suggesting that higher productivity and industrialization are linked to higher wages and exports.

#Hypotheses Statements

• H1: States with higher employment concentration in the secondary (industrial specialization) and third (services) sector have significantly higher export levels.

• H2: Border distance has a negative and significant effect on exports. States closer to the U.S. border export more than states located farther away.

• H3: Higher levels of Foreign Direct Investment (FDI) positively affect export performance at the state level.

• H4: States with higher average wages, as a proxy for productivity and industrial development, show higher export performance.

#Main Findings

• Total exports show fluctuations over time, with increases and decreases from one year to another.

• Northern states consistently show higher export levels than southern states.

• The scatter plot of exports versus border distance shows a negative relationship. States closer to the U.S. border tend to export more.

• There is a positive relationship between exports and employment concentration in the secondary sector. States with stronger manufacturing labor tend to achieve higher export levels.

• Exports are positively correlated with FDI and average daily salary. This suggests that more industrialized states perform better in international trade.

LS0tDQp0aXRsZTogIk1leGljbyBFeHBvcnRzIg0KYXV0aG9yOiAiT3N2YWxkbyBMb3BleiwgT3NjYXIgQmFyY2FyY2VsLCBNYXJpZWwiDQpkYXRlOiAiMjAyNi0wMi0xNiINCm91dHB1dDogDQogIGh0bWxfZG9jdW1lbnQ6DQogICAgdG9jOiBUUlVFDQogICAgdG9jX2Zsb2F0OiBUUlVFDQogICAgY29kZV9kb3dubG9hZDogVFJVRQ0KICAgIHRoZW1lOiAic3BhY2VsYWIiDQogICAgaGlnaGxpZ2h0OiAia2F0ZSINCi0tLQ0KDQpgYGB7ciBzZXR1cCwgaW5jbHVkZT1GQUxTRX0NCmtuaXRyOjpvcHRzX2NodW5rJHNldChlY2hvID0gVFJVRSkNCmBgYA0KDQoNCiMgTWV4aWNv4oCZcyBleHBvcnRzIHBlcmZvcm1hbmNlDQoNCiMjIE1leGljbyBleHBvcnRzIGNoYXJhY3RlcmlzdGljcw0K4oCiIE1leGljb+KAmXMgZXhwb3J0cyBncmV3IHN0cm9uZ2x5IGJldHdlZW4gMjAxNSBhbmQgMjAyNSwgYWxtb3N0IGRvdWJsaW5nIGluIHRvdGFsIHZhbHVlLiBUaGlzIHNob3dzIGhvdyBpbXBvcnRhbnQgaW50ZXJuYXRpb25hbCB0cmFkZSBpcyBmb3IgdGhlIE1leGljYW4gZWNvbm9teS4NCg0K4oCiIEFyb3VuZCA5MCUgb2YgZXhwb3J0cyBjb21lIGZyb20gbWFudWZhY3R1cmVkIGdvb2RzLCBlc3BlY2lhbGx5IGF1dG9tb3RpdmUsIGVsZWN0cm9uaWNzLCBhbmQgbWFjaGluZXJ5LiBNZXhpY28gaXMgaGlnaGx5IHNwZWNpYWxpemVkIGluIGluZHVzdHJpYWwgcHJvZHVjdGlvbi4NCg0K4oCiIE1vcmUgdGhhbiA4MCUgb2YgZXhwb3J0cyBnbyB0byB0aGUgVW5pdGVkIFN0YXRlcy4gVGhpcyBtZWFucyBNZXhpY28gZGVwZW5kcyBoZWF2aWx5IG9uIHRoZSBVLlMuIG1hcmtldCBhbmQgcmVnaW9uYWwgc3VwcGx5IGNoYWlucy4NCg0K4oCiIEV2ZW4gd2l0aCBjaGFsbGVuZ2VzIHN1Y2ggYXMgQ09WSUQtMTkgYW5kIHRoZSByZW5lZ290aWF0aW9uIG9mIE5BRlRBIGludG8gVVNNQ0EsIGV4cG9ydHMgcmVjb3ZlcmVkIHF1aWNrbHkgYW5kIGNvbnRpbnVlZCBncm93aW5nLg0KDQojIyBDb250cmlidXRpb24gb2YgUGFuZWwgRGF0YSBBbmFseXNpcyB0byBVbmRlcnN0YW5kaW5nIEV4cG9ydCBQZXJmb3JtYW5jZQ0KDQrigKIgUGFuZWwgZGF0YSBjb21iaW5lcyBpbmZvcm1hdGlvbiBhY3Jvc3Mgc3RhdGVzIG9yIHNlY3RvcnMgYW5kIGFjcm9zcyB0aW1lLiBUaGlzIGhlbHBzIHVzIHNlZSBkaWZmZXJlbmNlcyBiZXR3ZWVuIHJlZ2lvbnMgYW5kIGhvdyBleHBvcnRzIGNoYW5nZSBlYWNoIHllYXIuDQoNCuKAoiBJdCBhbGxvd3MgdXMgdG8gY29udHJvbCBmb3IgY2hhcmFjdGVyaXN0aWNzIHRoYXQgZG8gbm90IGNoYW5nZSBvdmVyIHRpbWUsIHN1Y2ggYXMgZ2VvZ3JhcGh5IG9yIGluZHVzdHJpYWwgc3RydWN0dXJlLiBUaGlzIG1ha2VzIHRoZSBhbmFseXNpcyBtb3JlIGFjY3VyYXRlLg0KDQrigKIgUGFuZWwgbW9kZWxzIGhlbHAgc2VwYXJhdGUgbG9uZy10ZXJtIHN0cnVjdHVyYWwgZmFjdG9ycyBmcm9tIHNob3J0LXRlcm0gc2hvY2tzLCBzdWNoIGFzIHRlbXBvcmFyeSB0YXJpZmYgY2hhbmdlcy4NCg0KIyMgVXNlIG9mIFBhbmVsIERhdGEgZm9yIFNob3J04oCRVGVybSBFeHBvcnQgUHJlZGljdGlvbg0KDQrigKIgV2UgY2FuIHVzZSBwYXN0IGV4cG9ydCB0cmVuZHMgZnJvbSBkaWZmZXJlbnQgc3RhdGVzIG9yIHNlY3RvcnMgdG8gZXN0aW1hdGUgd2hhdCBjb3VsZCBoYXBwZW4gaW4gdGhlIG5leHQgMeKAkzIgeWVhcnMuDQoNCuKAoiBJdCBpcyBwb3NzaWJsZSB0byBpbmNsdWRlIHZhcmlhYmxlcyBsaWtlIGV4Y2hhbmdlIHJhdGUsIFUuUy4gZWNvbm9taWMgZ3Jvd3RoLCBvciB0YXJpZmYgY2hhbmdlcyB0byBzaW11bGF0ZSBkaWZmZXJlbnQgc2NlbmFyaW9zLg0KDQrigKIgUHJlZGljdGlvbnMgY2FuIGJlIG1hZGUgYXQgdGhlIHN0YXRlIG9yIHNlY3RvciBsZXZlbCwgbm90IG9ubHkgZm9yIHRoZSB3aG9sZSBjb3VudHJ5LiBUaGlzIGdpdmVzIG1vcmUgc3BlY2lmaWMgYW5kIHVzZWZ1bCByZXN1bHRzLg0KDQojIyBSb2xlIG9mIEJ1c2luZXNzIEludGVsbGlnZW5jZSBhbmQgUHJlZGljdGl2ZSBBbmFseXRpY3MgZm9yIElkZW50aWZ5aW5nIFZ1bG5lcmFiaWxpdHkgRHVyaW5nIFVTTUNBIE5lZ290aWF0aW9ucw0KDQrigKIgQnVzaW5lc3MgSW50ZWxsaWdlbmNlIHRvb2xzIGNhbiBtZWFzdXJlIGhvdyBtdWNoIGVhY2ggc3RhdGUgb3Igc2VjdG9yIGRlcGVuZHMgb24gZXhwb3J0cyB0byB0aGUgVS5TLiBUaGlzIGhlbHBzIGlkZW50aWZ5IHdoaWNoIG9uZXMgYXJlIG1vcmUgZXhwb3NlZCB0byB0YXJpZmYgY2hhbmdlcy4NCg0K4oCiIFByZWRpY3RpdmUgbW9kZWxzIGNhbiBlc3RpbWF0ZSBob3cgc2Vuc2l0aXZlIGV4cG9ydHMgYXJlIHRvIG5ldyB0cmFkZSBydWxlcy4gV2l0aCB0aGlzLCB3ZSBjYW4gY2xhc3NpZnkgc3RhdGVzIG9yIGluZHVzdHJpZXMgYnkgbGV2ZWwgb2Ygcmlzay4NCg0K4oCiIERhc2hib2FyZHMgYW5kIHZpc3VhbCB0b29scyBhbGxvdyBkZWNpc2lvbiBtYWtlcnMgdG8gbW9uaXRvciBleHBvcnQgcGVyZm9ybWFuY2UgYmVmb3JlIGFuZCBhZnRlciBwb2xpY3kgY2hhbmdlcy4NCg0K4oCiIE1hY2hpbmUgbGVhcm5pbmcgdGVjaG5pcXVlcyBjYW4gZ3JvdXAgc3RhdGVzIG9yIHNlY3RvcnMgd2l0aCBzaW1pbGFyIGV4cG9ydCBzdHJ1Y3R1cmVzLiBUaGlzIGhlbHBzIGlkZW50aWZ5IHBhdHRlcm5zIG9mIHZ1bG5lcmFiaWxpdHkgZHVyaW5nIHRyYWRlIG5lZ290aWF0aW9ucy4NCg0KIyBFeHBvcnRzIERhdGEgQW5hbHlzaXMgDQojIyBEYXRhIENsZWFuaW5nIGFuZCBUcmFuc2Zvcm1pbmcNCg0KYGBge3IsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9DQoNCmxpYnJhcnkocmVhZHhsKQ0KbGlicmFyeSh0aWR5dmVyc2UpDQpsaWJyYXJ5KHBsbSkNCmxpYnJhcnkoc2YpDQpsaWJyYXJ5KHJuYXR1cmFsZWFydGgpDQpsaWJyYXJ5KGRwbHlyKQ0KbGlicmFyeShnZ3Bsb3QyKQ0KbGlicmFyeShyZXNoYXBlMikNCg0KYGBgDQoNCg0KYGBge3J9DQpkZl9leHBvIDwtIHJlYWRfZXhjZWwoIkM6L1VzZXJzL09zdmFsL0Rvd25sb2Fkcy9pbmVnaV9leHBvcnRzX2RhdGFzZXQueGxzeCIsIHNoZWV0ID0gImV4cG9ydHMiKQ0KZGZfdHMgPC0gcmVhZF9leGNlbCgiQzovVXNlcnMvT3N2YWwvRG93bmxvYWRzL2luZWdpX2V4cG9ydHNfZGF0YXNldC54bHN4Iiwgc2hlZXQgPSAidHNfZXhwb3J0cyIpDQpkZl9kYXRhIDwtIHJlYWRfZXhjZWwoIkM6L1VzZXJzL09zdmFsL0Rvd25sb2Fkcy9pbmVnaV9leHBvcnRzX2RhdGFzZXQueGxzeCIsIHNoZWV0ID0gImRhdGEiKQ0KZGZfZmRpIDwtIHJlYWRfZXhjZWwoIkM6L1VzZXJzL09zdmFsL0Rvd25sb2Fkcy9pbmVnaV9leHBvcnRzX2RhdGFzZXQueGxzeCIsIHNoZWV0ID0gImZkaSIpDQoNCmBgYA0KDQrigKIgVGhlIG9yaWdpbmFsIGRhdGFzZXRzIHdlcmUgY2xlYW5lZCBhbmQgdHJhbnNmb3JtZWQuIEV4cG9ydCB2YXJpYWJsZXMgd2VyZSBjb252ZXJ0ZWQgZnJvbSB3aWRlIGZvcm1hdCB0byBsb25nIGZvcm1hdCBzbyBlYWNoIHJvdyByZXByZXNlbnRzIG9uZSBzdGF0ZSBpbiBvbmUgc3BlY2lmaWMgeWVhci4NCg0KYGBge3J9DQpkZl9leHBvbG9uZyA8LSBkZl9leHBvICU+JQ0KICBwaXZvdF9sb25nZXIoDQogICAgY29scyA9IHN0YXJ0c193aXRoKCJyZWFsX2V4cG9ydHNfIiksDQogICAgbmFtZXNfdG8gPSAieWVhciIsDQogICAgbmFtZXNfcHJlZml4ID0gInJlYWxfZXhwb3J0c18iLA0KICAgIHZhbHVlc190byA9ICJyZWFsX2V4cG9ydHMiDQogICkNCg0KZGZfZmRpbG9uZyA8LSBkZl9mZGkgJT4lDQogIHBpdm90X2xvbmdlcigNCiAgICBjb2xzID0gc3RhcnRzX3dpdGgoImZkaV8iKSwNCiAgICBuYW1lc190byA9ICJ5ZWFyIiwNCiAgICBuYW1lc19wcmVmaXggPSAiZmRpXyIsDQogICAgdmFsdWVzX3RvID0gImZkaSINCiAgKQ0KDQpgYGANCg0K4oCiIFdlIHZlcmlmaWVkIHRoYXQgdGhlcmUgd2VyZSBubyBkdXBsaWNhdGVkIG9ic2VydmF0aW9ucyBieSBzdGF0ZSBhbmQgeWVhciBiZWZvcmUgbWVyZ2luZyB0aGUgZGF0YXNldHMuDQoNCg0KYGBge3J9DQpkZl9leHBvbG9uZyAlPiUgY291bnQoc3RhdGUsIHllYXIsIHJlZ2lvbikgJT4lIGZpbHRlcihuID4gMSkNCmRmX2RhdGEgJT4lIGNvdW50KHN0YXRlLCB5ZWFyKSAlPiUgZmlsdGVyKG4gPiAxKQ0KZGZfZmRpbG9uZyAlPiUgY291bnQoc3RhdGUsIHllYXIsIHJlZ2lvbikgJT4lIGZpbHRlcihuID4gMSkNCg0KYGBgDQoNCuKAoiBEaWZmZXJlbnQgZGF0YXNldHMgKGV4cG9ydHMsIEZESSwgbWFjcm9lY29ub21pYyB2YXJpYWJsZXMsIGFuZCBzdGF0ZSBjaGFyYWN0ZXJpc3RpY3MpIHdlcmUgbWVyZ2VkIHVzaW5nIHN0YXRlIGFuZCB5ZWFyIGFzIGtleSB2YXJpYWJsZXMuDQoNCmBgYHtyfQ0KZGZfZXhwb2xvbmckeWVhciA8LSBhcy5udW1lcmljKGRmX2V4cG9sb25nJHllYXIpDQpkZl9mZGlsb25nJHllYXIgPC0gYXMubnVtZXJpYyhkZl9mZGlsb25nJHllYXIpDQpkZl9kYXRhJHllYXIgPC0gYXMubnVtZXJpYyhkZl9kYXRhJHllYXIpDQoNCmBgYA0KDQpgYGB7cn0NCnBhbmVsX2Z1bGwgPC0gZGZfZXhwb2xvbmcgJT4lDQogIGxlZnRfam9pbihkZl9mZGlsb25nLCBieSA9IGMoInN0YXRlIiwgInllYXIiLCAicmVnaW9uIikpICU+JQ0KICBsZWZ0X2pvaW4oZGZfZGF0YSwgYnkgPSBjKCJzdGF0ZSIsICJ5ZWFyIikpDQoNCmBgYA0KDQrigKIgTWlzc2luZyB2YWx1ZXMgd2VyZSByZXBsYWNlZCB1c2luZyB0aGUgYXZlcmFnZSB2YWx1ZSBieSBzdGF0ZSBpbiBvcmRlciB0byBtYWludGFpbiBhIGJhbGFuY2VkIHBhbmVsIHN0cnVjdHVyZS4NCg0KYGBge3J9DQpwYW5lbF9mdWxsIDwtIHBhbmVsX2Z1bGwgJT4lDQogIGdyb3VwX2J5KHN0YXRlKSAlPiUNCiAgbXV0YXRlKA0KICAgIGFjcm9zcygNCiAgICAgIHdoZXJlKGlzLm51bWVyaWMpLCANCiAgICAgIH4gaWZlbHNlKGlzLm5hKC4pLCBtZWFuKC4sIG5hLnJtID0gVFJVRSksIC4pDQogICAgKQ0KICApICU+JQ0KICB1bmdyb3VwKCkNCg0KYGBgDQoNCuKAoiBBIHBhbmVsIGRhdGFzZXQgd2FzIGNyZWF0ZWQgdXNpbmcgc3RhdGUgYW5kIHllYXIgYXMgaW5kZXhlcywgYWxsb3dpbmcgYW5hbHlzaXMgYWNyb3NzIHRpbWUgYW5kIGFjcm9zcyByZWdpb25zLg0KDQpgYGB7cn0NCnBhbmVsX2RhdGEgPC0gcGRhdGEuZnJhbWUocGFuZWxfZnVsbCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgaW5kZXggPSBjKCJzdGF0ZSIsICJ5ZWFyIikpDQpgYGANCg0KDQojIyBFeHBsb3JhdG9yeSBEYXRhIEFuYWx5c2lzIOKAkyBFREENCg0KIyMjIERlc2NyaXB0aXZlIFN0YXRpc3RpY3MNCg0KYGBge3J9DQpyZWdpb25hbF9hdmcgPC0gcGFuZWxfZnVsbCAlPiUNCiAgZ3JvdXBfYnkocmVnaW9uKSAlPiUNCiAgc3VtbWFyaXNlKA0KICAgIGF2Z19leHBvcnRzID0gbWVhbihyZWFsX2V4cG9ydHMsIG5hLnJtID0gVFJVRSksDQogICAgYXZnX2ZkaSA9IG1lYW4oZmRpLCBuYS5ybSA9IFRSVUUpLA0KICAgIGF2Z19leGNoYW5nZV9yYXRlID0gbWVhbihleGNoYW5nZV9yYXRlLCBuYS5ybSA9IFRSVUUpLA0KICAgIGF2Z19jb2xsZWdlID0gbWVhbihjb2xsZWdlX2VkdWNhdGlvbiwgbmEucm0gPSBUUlVFKSwNCiAgICAuZ3JvdXBzID0gImRyb3AiDQogICkNCmdncGxvdChyZWdpb25hbF9hdmcsIGFlcyh4ID0gcmVnaW9uLCB5ID0gYXZnX2V4cG9ydHMpKSArDQogIGdlb21fY29sKCkgKw0KICBsYWJzKHRpdGxlID0gIkF2ZXJhZ2UgRXhwb3J0cyBieSBSZWdpb24iLA0KICAgICAgIHggPSAiUmVnaW9uIiwNCiAgICAgICB5ID0gIkF2ZXJhZ2UgUmVhbCBFeHBvcnRzIikgKw0KICB0aGVtZV9taW5pbWFsKCkNCg0KYGBgDQpgYGB7cn0NCmdncGxvdChyZWdpb25hbF9hdmcsIGFlcyh4ID0gcmVnaW9uLCB5ID0gYXZnX2ZkaSkpICsNCiAgZ2VvbV9jb2woKSArDQogIGxhYnModGl0bGUgPSAiQXZlcmFnZSBGREkgYnkgUmVnaW9uIiwNCiAgICAgICB4ID0gIlJlZ2lvbiIsDQogICAgICAgeSA9ICJBdmVyYWdlIEZESSIpICsNCiAgdGhlbWVfbWluaW1hbCgpDQoNCmBgYA0KDQpgYGB7cn0NCmdncGxvdChyZWdpb25hbF9hdmcsIGFlcyh4ID0gcmVnaW9uLCB5ID0gYXZnX2NvbGxlZ2UpKSArDQogIGdlb21fY29sKCkgKw0KICBsYWJzKHRpdGxlID0gIkF2ZXJhZ2UgQ29sbGVnZSBFZHVjYXRpb24gYnkgUmVnaW9uIiwNCiAgICAgICB4ID0gIlJlZ2lvbiIsDQogICAgICAgeSA9ICJBdmVyYWdlIENvbGxlZ2UgRWR1Y2F0aW9uIikgKw0KICB0aGVtZV9taW5pbWFsKCkNCg0KYGBgDQpgYGB7cn0NCmdncGxvdChwYW5lbF9mdWxsLCBhZXMoeCA9IHJlYWxfZXhwb3J0cykpICsNCiAgZ2VvbV9oaXN0b2dyYW0oYmlucyA9IDMwKSArDQogIGxhYnModGl0bGUgPSAiRGlzdHJpYnV0aW9uIG9mIFJlYWwgRXhwb3J0cyIsDQogICAgICAgeCA9ICJSZWFsIEV4cG9ydHMiLA0KICAgICAgIHkgPSAiRnJlcXVlbmN5IikgKw0KICB0aGVtZV9taW5pbWFsKCkNCg0KYGBgDQpgYGB7cn0NCmdncGxvdChwYW5lbF9mdWxsLCBhZXMoeCA9IGZkaSkpICsNCiAgZ2VvbV9oaXN0b2dyYW0oYmlucyA9IDMwKSArDQogIGxhYnModGl0bGUgPSAiRGlzdHJpYnV0aW9uIG9mIEZESSIsDQogICAgICAgeCA9ICJGREkiLA0KICAgICAgIHkgPSAiRnJlcXVlbmN5IikgKw0KICB0aGVtZV9taW5pbWFsKCkNCg0KYGBgDQpgYGB7cn0NCmdncGxvdChwYW5lbF9mdWxsLCBhZXMoeCA9IGNvbGxlZ2VfZWR1Y2F0aW9uKSkgKw0KICBnZW9tX2hpc3RvZ3JhbShiaW5zID0gMzApICsNCiAgbGFicyh0aXRsZSA9ICJEaXN0cmlidXRpb24gb2YgQ29sbGVnZSBFZHVjYXRpb24iLA0KICAgICAgIHggPSAiQ29sbGVnZSBFZHVjYXRpb24iLA0KICAgICAgIHkgPSAiRnJlcXVlbmN5IikgKw0KICB0aGVtZV9taW5pbWFsKCkNCg0KYGBgDQoNCiMjIyBTdGF0aXN0aWNzIG9mIERpc3BlcnNpb24NCg0KYGBge3J9DQpnZ3Bsb3QocGFuZWxfZnVsbCwgYWVzKHggPSByZWdpb24sIHkgPSByZWFsX2V4cG9ydHMpKSArDQogIGdlb21fYm94cGxvdCgpICsNCiAgbGFicyh0aXRsZSA9ICJFeHBvcnRzIERpc3RyaWJ1dGlvbiBBY3Jvc3MgUmVnaW9ucyIsDQogICAgICAgeCA9ICJSZWdpb24iLA0KICAgICAgIHkgPSAiUmVhbCBFeHBvcnRzIikgKw0KICB0aGVtZV9taW5pbWFsKCkNCg0KYGBgDQpgYGB7cn0NCmdncGxvdChwYW5lbF9mdWxsLCBhZXMoeCA9IHJlZ2lvbiwgeSA9IGZkaSkpICsNCiAgZ2VvbV9ib3hwbG90KCkgKw0KICBsYWJzKHRpdGxlID0gIkZESSBEaXN0cmlidXRpb24gQWNyb3NzIFJlZ2lvbnMiLA0KICAgICAgIHggPSAiUmVnaW9uIiwNCiAgICAgICB5ID0gIkZESSIpICsNCiAgdGhlbWVfbWluaW1hbCgpDQoNCmBgYA0KDQpgYGB7cn0NCmdncGxvdChwYW5lbF9mdWxsLCBhZXMoeCA9IHJlZ2lvbiwgeSA9IGxxX3ByaW1hcnkpKSArDQogIGdlb21fYm94cGxvdCgpICsNCiAgbGFicyh0aXRsZSA9ICJDb2xsZWdlIEVkdWNhdGlvbiBBY3Jvc3MgUmVnaW9ucyIsDQogICAgICAgeCA9ICJSZWdpb24iLA0KICAgICAgIHkgPSAiQ29sbGVnZSBFZHVjYXRpb24iKSArDQogIHRoZW1lX21pbmltYWwoKQ0KDQpgYGANCmBgYHtyfQ0KZ2dwbG90KHBhbmVsX2Z1bGwsIGFlcyh4ID0gcmVnaW9uLCB5ID0gbHFfc2Vjb25kYXJ5KSkgKw0KICBnZW9tX2JveHBsb3QoKSArDQogIGxhYnModGl0bGUgPSAiQ29sbGVnZSBFZHVjYXRpb24gQWNyb3NzIFJlZ2lvbnMiLA0KICAgICAgIHggPSAiUmVnaW9uIiwNCiAgICAgICB5ID0gIkNvbGxlZ2UgRWR1Y2F0aW9uIikgKw0KICB0aGVtZV9taW5pbWFsKCkNCg0KYGBgDQoNCiMjIyBWaXN1YWxpemF0aW9uIGFjcm9zcyBUaW1lDQoNCg0KYGBge3J9DQpleHBvcnRzX3RpbWUgPC0gcGFuZWxfZnVsbCAlPiUNCiAgZ3JvdXBfYnkoeWVhcikgJT4lDQogIHN1bW1hcmlzZSh0b3RhbF9leHBvcnRzID0gc3VtKHJlYWxfZXhwb3J0cywgbmEucm0gPSBUUlVFKSkNCg0KZ2dwbG90KGV4cG9ydHNfdGltZSwgYWVzKHggPSB5ZWFyLCB5ID0gdG90YWxfZXhwb3J0cykpICsNCiAgZ2VvbV9saW5lKHNpemUgPSAxKSArDQogIGxhYnModGl0bGUgPSAiVG90YWwgRXhwb3J0cyBJbmZsb3dzIGluIE1leGljbyIsDQogICAgICAgeCA9ICJZZWFyIiwNCiAgICAgICB5ID0gIlRvdGFsIFJlYWwgRXhwb3J0cyIpICsNCiAgdGhlbWVfbWluaW1hbCgpDQpgYGANCuKAoiBUb3RhbCBleHBvcnRzIHNob3cgYSBjbGVhciB1cHdhcmQgdHJlbmQgb3ZlciB0aGUgcGVyaW9kLiBUaGVyZSBpcyBhIHRlbXBvcmFyeSBkZWNsaW5lIGFyb3VuZCB0aGUgQ09WSUQtMTkgcGVyaW9kLCBidXQgZXhwb3J0cyByZWNvdmVyIHF1aWNrbHkgYW5kIGNvbnRpbnVlIGdyb3dpbmcuDQoNCg0KYGBge3J9DQpleHBvcnRzX3JlZ2lvbiA8LSBwYW5lbF9mdWxsICU+JQ0KICBncm91cF9ieShyZWdpb24sIHllYXIpICU+JQ0KICBzdW1tYXJpc2UodG90YWxfZXhwb3J0cyA9IHN1bShyZWFsX2V4cG9ydHMsIG5hLnJtID0gVFJVRSksDQogICAgICAgICAgICAuZ3JvdXBzID0gImRyb3AiKQ0KDQpnZ3Bsb3QoZXhwb3J0c19yZWdpb24sIGFlcyh4ID0geWVhciwgeSA9IHRvdGFsX2V4cG9ydHMsIGNvbG9yID0gcmVnaW9uKSkgKw0KICBnZW9tX2xpbmUobGluZXdpZHRoID0gMSkgKw0KICBsYWJzKHRpdGxlID0gIlRvdGFsIEV4cG9ydHMgSW5mbG93cyBieSBSZWdpb24iLA0KICAgICAgIHggPSAiWWVhciIsDQogICAgICAgeSA9ICJUb3RhbCBSZWFsIEV4cG9ydHMiLA0KICAgICAgIGNvbG9yID0gIlJlZ2lvbiIpICsNCiAgdGhlbWVfbWluaW1hbCgpDQoNCmBgYA0K4oCiIE5vcnRoZXJuIHJlZ2lvbnMgc2hvdyBoaWdoZXIgZXhwb3J0IGxldmVscyBjb21wYXJlZCB0byBzb3V0aGVybiByZWdpb25zLg0KDQrigKIgVGhlIGdhcCBiZXR3ZWVuIHJlZ2lvbnMgcmVtYWlucyBwZXJzaXN0ZW50IG92ZXIgdGltZSwgd2hpY2ggc3VnZ2VzdHMgc3RydWN0dXJhbCBkaWZmZXJlbmNlcyBpbiBpbmR1c3RyaWFsIGRldmVsb3BtZW50Lg0KYGBge3J9DQptYWNyb190aW1lIDwtIHBhbmVsX2Z1bGwgJT4lDQogIGdyb3VwX2J5KHllYXIpICU+JQ0KICBzdW1tYXJpc2UoDQogICAgdG90YWxfZXhwb3J0cyA9IHN1bShyZWFsX2V4cG9ydHMsIG5hLnJtID0gVFJVRSksDQogICAgYXZnX2V4Y2hhbmdlX3JhdGUgPSBtZWFuKGV4Y2hhbmdlX3JhdGUsIG5hLnJtID0gVFJVRSksDQogICAgLmdyb3VwcyA9ICJkcm9wIg0KICApDQptYWNyb190aW1lIDwtIG1hY3JvX3RpbWUgJT4lDQogIG11dGF0ZSgNCiAgICBleHBvcnRzX2luZGV4ID0gdG90YWxfZXhwb3J0cyAvIG1heCh0b3RhbF9leHBvcnRzKSwNCiAgICBleGNoYW5nZV9pbmRleCA9IGF2Z19leGNoYW5nZV9yYXRlIC8gbWF4KGF2Z19leGNoYW5nZV9yYXRlKQ0KICApDQpnZ3Bsb3QobWFjcm9fdGltZSwgYWVzKHggPSB5ZWFyKSkgKw0KICBnZW9tX2xpbmUoYWVzKHkgPSBleHBvcnRzX2luZGV4LCBjb2xvciA9ICJFeHBvcnRzIiksIGxpbmV3aWR0aCA9IDEuMikgKw0KICBnZW9tX2xpbmUoYWVzKHkgPSBleGNoYW5nZV9pbmRleCwgY29sb3IgPSAiRXhjaGFuZ2UgUmF0ZSIpLCBsaW5ld2lkdGggPSAxLjIpICsNCiAgbGFicyh0aXRsZSA9ICJFeHBvcnRzIEluZmxvd3MgdnMgRXhjaGFuZ2UgUmF0ZSAoSW5kZXhlZCkiLA0KICAgICAgIHggPSAiWWVhciIsDQogICAgICAgeSA9ICJJbmRleGVkIFZhbHVlcyIsDQogICAgICAgY29sb3IgPSAiIikgKw0KICB0aGVtZV9taW5pbWFsKCkNCg0KYGBgDQrigKIgV2hlbiBjb21wYXJpbmcgaW5kZXhlZCBleHBvcnRzIGFuZCBleGNoYW5nZSByYXRlLCBib3RoIHZhcmlhYmxlcyBzaG93IHNpbWlsYXIgbW92ZW1lbnRzIGluIHNvbWUgeWVhcnMuDQoNCuKAoiBUaGlzIHN1Z2dlc3RzIHRoYXQgZXhjaGFuZ2UgcmF0ZSBmbHVjdHVhdGlvbnMgbWF5IGluZmx1ZW5jZSBleHBvcnQgcGVyZm9ybWFuY2UsIGFsdGhvdWdoIHRoZSByZWxhdGlvbnNoaXAgaXMgbm90IHBlcmZlY3RseSBsaW5lYXIuDQoNCiMjI1JlZ2lvbmFsIERpZmZlcmVuY2VzDQoNCmBgYHtyfQ0KcGFuZWxfZnVsbCA8LSBwYW5lbF9mdWxsICU+JQ0KICBtdXRhdGUoem9uZSA9IGlmZWxzZShib3JkZXJfZGlzdGFuY2UgPCA0MDAsICJOb3J0aCIsICJTb3V0aCIpKQ0KcGFuZWxfZnVsbCA8LSBwYW5lbF9mdWxsICU+JQ0KICBtdXRhdGUoem9uZSA9IGlmZWxzZShyZWdpb24gJWluJSBjKCJOb3JvZXN0ZSIsICJOb3Jlc3RlIiksIA0KICAgICAgICAgICAgICAgICAgICAgICAiTm9ydGgiLCANCiAgICAgICAgICAgICAgICAgICAgICAgIlNvdXRoIikpDQpub3J0aF9zb3V0aF9leHBvcnRzIDwtIHBhbmVsX2Z1bGwgJT4lDQogIGdyb3VwX2J5KHpvbmUpICU+JQ0KICBzdW1tYXJpc2UoYXZnX2V4cG9ydHMgPSBtZWFuKHJlYWxfZXhwb3J0cywgbmEucm0gPSBUUlVFKSwNCiAgICAgICAgICAgIC5ncm91cHMgPSAiZHJvcCIpDQpnZ3Bsb3Qobm9ydGhfc291dGhfZXhwb3J0cywgYWVzKHggPSB6b25lLCB5ID0gYXZnX2V4cG9ydHMpKSArDQogIGdlb21fYmFyKHN0YXQgPSAiaWRlbnRpdHkiKSArDQogIGxhYnModGl0bGUgPSAiQXZlcmFnZSBFeHBvcnRzIEluZmxvd3M6IE5vcnRoIHZzIFNvdXRoIiwNCiAgICAgICB4ID0gIlJlZ2lvbiIsDQogICAgICAgeSA9ICJBdmVyYWdlIFJlYWwgRXhwb3J0cyIpICsNCiAgdGhlbWVfbWluaW1hbCgpDQoNCg0KYGBgDQoNCuKAoiBTdGF0ZXMgY2xhc3NpZmllZCBhcyDigJxOb3J0aOKAnSBoYXZlIHNpZ25pZmljYW50bHkgaGlnaGVyIGF2ZXJhZ2UgZXhwb3J0cyB0aGFuIHRob3NlIGluIHRoZSDigJxTb3V0aC7igJ0NCg0K4oCiIFRoaXMgY29uZmlybXMgdGhlIGltcG9ydGFuY2Ugb2YgZ2VvZ3JhcGhpYyBwcm94aW1pdHkgdG8gdGhlIFUuUy4gYm9yZGVyIGFuZCBpbmR1c3RyaWFsIGNvbmNlbnRyYXRpbw0KDQrigKIgTm9ydGhlcm4gc3RhdGVzIHNob3cgbXVjaCBoaWdoZXIgZXhwb3J0IHZvbHVtZXMuIFNvdXRoZXJuIHN0YXRlcyBwYXJ0aWNpcGF0ZSBsZXNzIGluIGludGVybmF0aW9uYWwgdHJhZGUuDQoNCuKAoiBHZW9ncmFwaGljIHByb3hpbWl0eSB0byB0aGUgVS5TLiBib3JkZXIgaXMgYSBpbXByb3RhbnQgZmFjdG9yLiBOb3J0aGVybiBzdGF0ZXMgYmVuZWZpdCBmcm9tIGxvd2VyIHRyYW5zcG9ydGF0aW9uIGNvc3RzIGFuZCBiZXR0ZXIgYWNjZXNzIHRvIGNyb3NzLWJvcmRlciBpbmZyYXN0cnVjdHVyZS4NCg0K4oCiIEluZHVzdHJpYWwgc3RydWN0dXJlIGlzIGRpZmZlcmVudC4gTm9ydGhlcm4gc3RhdGVzIGhhdmUgaGlnaGVyIGNvbmNlbnRyYXRpb24gaW4gbWFudWZhY3R1cmluZyBhbmQgZXhwb3J0LW9yaWVudGVkIGluZHVzdHJpZXMsIHdoaWxlIHNvdXRoZXJuIHN0YXRlcyBtb3JlIG9uIHByaW1hcnkgYWN0aXZpdGllcyBvciBzZXJ2aWNlcy4NCg0K4oCiIEZvcmVpZ24gRGlyZWN0IEludmVzdG1lbnQgaXMgbW9yZSBjb25jZW50cmF0ZWQgaW4gdGhlIE5vcnRoLiBNYW55IG11bHRpbmF0aW9uYWwgZmlybXMgYXJlIGxvY2F0ZWQgaW4gbm9ydGhlcm4gc3RhdGVzIGR1ZSB0byB0aGVpciBjb25uZWN0aW9uIHdpdGggVS5TLiBtYXJrZXRzLg0KDQrigKIgSW5mcmFzdHJ1Y3R1cmUgYW5kIGNvbm5lY3Rpdml0eSBhcmUgZ2VuZXJhbGx5IHN0cm9uZ2VyIGluIG5vcnRoZXJuIHN0YXRlcywgaW5jbHVkaW5nIGhpZ2h3YXlzLCBpbmR1c3RyaWFsIHBhcmtzLCBhbmQgY3VzdG9tcyBmYWNpbGl0aWVzLCB3aGljaCBmYWNpbGl0YXRlIGludGVybmF0aW9uYWwgdHJhZGUuDQoNCmBgYHtyfQ0KbWV4aWNvX21hcCA8LSBuZV9zdGF0ZXMoY291bnRyeSA9ICJtZXhpY28iLCByZXR1cm5jbGFzcyA9ICJzZiIpDQoNCnNldGRpZmYobWV4aWNvX21hcCRuYW1lLCBwYW5lbF9kYXRhJHN0YXRlKQ0KDQoNCmBgYA0KYGBge3J9DQpwYW5lbF9kYXRhJHN0YXRlIDwtIHJlY29kZShwYW5lbF9kYXRhJHN0YXRlLA0KICAiQ2l1ZGFkIGRlIE1leGljbyIgPSAiRGlzdHJpdG8gRmVkZXJhbCIsDQogICJNaWNob2FjYW4iID0gIk1pY2hvYWPDoW4iLA0KICAiUXVlcmV0YXJvIiA9ICJRdWVyw6l0YXJvIiwNCiAgIk1leGljbyIgPSAiTcOpeGljbyIsDQogICJTYW4gTHVpcyBQb3Rvc2kiID0gIlNhbiBMdWlzIFBvdG9zw60iLA0KICAiWXVjYXRhbiIgPSAiWXVjYXTDoW4iLA0KICAiTnVldm8gTGVvbiIgPSAiTnVldm8gTGXDs24iDQopDQoNCmBgYA0KDQrigKIgQm9yZGVyIHN0YXRlcyBzdWNoIGFzIENoaWh1YWh1YSBhbmQgb3RoZXIgbm9ydGhlcm4gc3RhdGVzIHNob3cgaGlnaGVyIGV4cG9ydCBsZXZlbHMuDQoNCmBgYHtyfQ0KYXZnX3N0YXRlX2V4cG9ydHMgPC0gcGFuZWxfZGF0YSAlPiUNCiAgZ3JvdXBfYnkoc3RhdGUpICU+JQ0KICBzdW1tYXJpc2UoYXZnX2V4cG9ydHMgPSBtZWFuKHJlYWxfZXhwb3J0cywgbmEucm0gPSBUUlVFKSwNCiAgICAgICAgICAgIC5ncm91cHMgPSAiZHJvcCIpDQptYXBfZGF0YSA8LSBtZXhpY29fbWFwICU+JQ0KICBsZWZ0X2pvaW4oYXZnX3N0YXRlX2V4cG9ydHMsIGJ5ID0gYygibmFtZSIgPSAic3RhdGUiKSkNCmdncGxvdChtYXBfZGF0YSkgKw0KICBnZW9tX3NmKGFlcyhmaWxsID0gYXZnX2V4cG9ydHMpKSArDQogIHNjYWxlX2ZpbGxfdmlyaWRpc19jKG9wdGlvbiA9ICJtYWtvIiwgbmEudmFsdWUgPSAiZ3JleTkwIikgKw0KICBsYWJzKHRpdGxlID0gIkF2ZXJhZ2UgRXhwb3J0cyBJbmZsb3dzIGJ5IE1leGljYW4gU3RhdGUiLA0KICAgICAgIGZpbGwgPSAiQXZnIEV4cG9ydHMiKSArDQogIHRoZW1lX21pbmltYWwoKQ0KDQpgYGANCg0KIyMjIENvcnJlbGF0aW9uIGFuZCBSZWxhdGlvbnNoaXBzDQoNCmBgYHtyfQ0Kc2NhbGVfZmlsbF9ncmFkaWVudDIoDQogIGxvdyA9ICJibHVlIiwNCiAgbWlkID0gIndoaXRlIiwNCiAgaGlnaCA9ICJyZWQiLA0KICBtaWRwb2ludCA9IDAsDQogIGxpbWl0cyA9IGMoLTEsIDEpDQopDQpjb3JyX2RhdGEgPC0gcGFuZWxfZGF0YSAlPiUNCiAgc2VsZWN0KHJlYWxfZXhwb3J0cywgZXhjaGFuZ2VfcmF0ZSwgcG9wX2RlbnNpdHksIGZkaSwgYm9yZGVyX2Rpc3RhbmNlLCBscV9wcmltYXJ5LGxxX3NlY29uZGFyeSxscV90ZXJ0aWFyeSwgYXZlcmFnZV9kYWlseV9zYWxhcnksIGNyaW1lX3JhdGUpICU+JQ0KICBkcm9wX25hKCkNCg0KY29ycl9tYXRyaXggPC0gY29yKGNvcnJfZGF0YSkNCg0KY29ycl9sb25nIDwtIGFzLmRhdGEuZnJhbWUoYXMudGFibGUoY29ycl9tYXRyaXgpKQ0KDQpnZ3Bsb3QoY29ycl9sb25nLCBhZXMoVmFyMSwgVmFyMiwgZmlsbCA9IEZyZXEpKSArDQogIGdlb21fdGlsZSgpICsNCiAgc2NhbGVfZmlsbF9ncmFkaWVudDIoDQogICAgbG93ID0gImJsdWUiLA0KICAgIG1pZCA9ICJ3aGl0ZSIsDQogICAgaGlnaCA9ICJyZWQiLA0KICAgIG1pZHBvaW50ID0gMCwNCiAgICBsaW1pdHMgPSBjKC0xLCAxKQ0KICApICsNCiAgZ2VvbV90ZXh0KGFlcyhsYWJlbCA9IHJvdW5kKEZyZXEsIDIpKSwgc2l6ZSA9IDQpICsNCiAgbGFicyh0aXRsZSA9ICJDb3JyZWxhdGlvbiBNYXRyaXgiLA0KICAgICAgIHggPSAiIiwNCiAgICAgICB5ID0gIiIsDQogICAgICAgZmlsbCA9ICJDb3JyZWxhdGlvbiIpICsNCiAgdGhlbWVfbWluaW1hbCgpICsNCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA0NSwgaGp1c3QgPSAxKSkNCg0KDQpgYGANCg0K4oCiIEV4cG9ydHMgc2hvdyBwb3NpdGl2ZSBjb3JyZWxhdGlvbiB3aXRoIEZESSBhbmQgZW1wbG95bWVudCBjb25jZW50cmF0aW9uIGluIHRoZSBzZWNvbmRhcnkgc2VjdG9yLg0KDQrigKIgVGhlcmUgaXMgYSBuZWdhdGl2ZSByZWxhdGlvbnNoaXAgYmV0d2VlbiBib3JkZXIgZGlzdGFuY2UgYW5kIGV4cG9ydHMsIG1lYW5pbmcgdGhhdCBzdGF0ZXMgY2xvc2VyIHRvIHRoZSBVLlMuIHRlbmQgdG8gZXhwb3J0IG1vcmUuDQoNCuKAoiBTb21lIHNvY2lvZWNvbm9taWMgdmFyaWFibGVzIHN1Y2ggYXMgc2FsYXJ5IGFsc28gc2hvdyBwb3NpdGl2ZSBhc3NvY2lhdGlvbiB3aXRoIGV4cG9ydHMsIHN1Z2dlc3RpbmcgdGhhdCBtb3JlIGluZHVzdHJpYWxpemVkIHN0YXRlcyBoYXZlIGhpZ2hlciBpbmNvbWUgbGV2ZWxzLg0KDQpgYGB7cn0NCmdncGxvdChwYW5lbF9mdWxsLCBhZXMoeCA9IGJvcmRlcl9kaXN0YW5jZSwgeSA9IHJlYWxfZXhwb3J0cykpICsNCiAgZ2VvbV9wb2ludChhbHBoYSA9IDAuNikgKw0KICBnZW9tX3Ntb290aChtZXRob2QgPSAibG0iLCBzZSA9IFRSVUUsIGNvbG9yID0gImJsYWNrIikgKw0KICBsYWJzKHRpdGxlID0gIkV4cG9ydHMgSW5mbG93cyB2cyBCb3JkZXIgRGlzYW5jZSIsDQogICAgICAgeCA9ICJCb3JkZXIgRGlzYW5jZSIsDQogICAgICAgeSA9ICJFeHBvcnRzIikgKw0KICB0aGVtZV9taW5pbWFsKCkNCg0KYGBgDQoNCuKAoiBUaGUgcmVncmVzc2lvbiBsaW5lIHNob3dzIGEgbmVnYXRpdmUgc2xvcGUuIFN0YXRlcyBmYXJ0aGVyIGZyb20gdGhlIGJvcmRlciB0ZW5kIHRvIGhhdmUgbG93ZXIgZXhwb3J0IGxldmVscy4NCg0KYGBge3J9DQpnZ3Bsb3QocGFuZWxfZnVsbCwgYWVzKHggPSBscV9zZWNvbmRhcnksIHkgPSByZWFsX2V4cG9ydHMpKSArDQogIGdlb21fcG9pbnQoYWxwaGEgPSAwLjYpICsNCiAgZ2VvbV9zbW9vdGgobWV0aG9kID0gImxtIiwgc2UgPSBUUlVFLCBjb2xvciA9ICJibGFjayIpICsNCiAgbGFicyh0aXRsZSA9ICJFeHBvcnRzIEluZmxvd3MgdnMgRW1wbG95bWVudCBjb25jZW50cmF0aW9uIGluIHRoZSBzZWNvbmRhcnkgc2VjdG9yIiwNCiAgICAgICB4ID0gIkVtcGxveW1lbnQgY29uY2VudHJhdGlvbiBpbiB0aGUgc2Vjb25kYXJ5IHNlY3RvciIsDQogICAgICAgeSA9ICJSZWFsIEV4cG9ydHMiKSArDQogIHRoZW1lX21pbmltYWwoKQ0KDQpgYGANCuKAoiBUaGVyZSBpcyBhIHBvc2l0aXZlIHJlbGF0aW9uc2hpcC4gU3RhdGVzIHdpdGggc3Ryb25nZXIgaW5kdXN0cmlhbCBzcGVjaWFsaXphdGlvbiBleHBvcnQgbW9yZS4NCg0KYGBge3J9DQpnZ3Bsb3QocGFuZWxfZnVsbCwgYWVzKHggPSBhdmVyYWdlX2RhaWx5X3NhbGFyeSwgeSA9IHJlYWxfZXhwb3J0cykpICsNCiAgZ2VvbV9wb2ludChhbHBoYSA9IDAuNikgKw0KICBnZW9tX3Ntb290aChtZXRob2QgPSAibG0iLCBzZSA9IFRSVUUsIGNvbG9yID0gImJsYWNrIikgKw0KICBsYWJzKHRpdGxlID0gIkV4cG9ydHMgSW5mbG93cyB2cyBBdmVyYWdlIERhaWx5IFNhbGFyeSIsDQogICAgICAgeCA9ICJBdmVyYWdlIERhaWx5IFNhbGFyeSIsDQogICAgICAgeSA9ICJSZWFsIEV4cG9ydHMiKSArDQogIHRoZW1lX21pbmltYWwoKQ0KDQpgYGANCg0K4oCiIFRoZSByZWxhdGlvbnNoaXAgYXBwZWFycyBwb3NpdGl2ZSwgc3VnZ2VzdGluZyB0aGF0IGhpZ2hlciBwcm9kdWN0aXZpdHkgYW5kIGluZHVzdHJpYWxpemF0aW9uIGFyZSBsaW5rZWQgdG8gaGlnaGVyIHdhZ2VzIGFuZCBleHBvcnRzLg0KDQojSHlwb3RoZXNlcyBTdGF0ZW1lbnRzDQoNCuKAoiBIMTogU3RhdGVzIHdpdGggaGlnaGVyIGVtcGxveW1lbnQgY29uY2VudHJhdGlvbiBpbiB0aGUgc2Vjb25kYXJ5IChpbmR1c3RyaWFsIHNwZWNpYWxpemF0aW9uKSAgYW5kIHRoaXJkIChzZXJ2aWNlcykgc2VjdG9yIGhhdmUgc2lnbmlmaWNhbnRseSBoaWdoZXIgZXhwb3J0IGxldmVscy4NCg0K4oCiIEgyOiBCb3JkZXIgZGlzdGFuY2UgaGFzIGEgbmVnYXRpdmUgYW5kIHNpZ25pZmljYW50IGVmZmVjdCBvbiBleHBvcnRzLiBTdGF0ZXMgY2xvc2VyIHRvIHRoZSBVLlMuIGJvcmRlciBleHBvcnQgbW9yZSB0aGFuIHN0YXRlcyBsb2NhdGVkIGZhcnRoZXIgYXdheS4NCg0K4oCiIEgzOiBIaWdoZXIgbGV2ZWxzIG9mIEZvcmVpZ24gRGlyZWN0IEludmVzdG1lbnQgKEZESSkgcG9zaXRpdmVseSBhZmZlY3QgZXhwb3J0IHBlcmZvcm1hbmNlIGF0IHRoZSBzdGF0ZSBsZXZlbC4NCg0K4oCiIEg0OiBTdGF0ZXMgd2l0aCBoaWdoZXIgYXZlcmFnZSB3YWdlcywgYXMgYSBwcm94eSBmb3IgcHJvZHVjdGl2aXR5IGFuZCBpbmR1c3RyaWFsIGRldmVsb3BtZW50LCBzaG93IGhpZ2hlciBleHBvcnQgcGVyZm9ybWFuY2UuDQoNCg0KI01haW4gRmluZGluZ3MNCg0K4oCiIFRvdGFsIGV4cG9ydHMgc2hvdyBmbHVjdHVhdGlvbnMgb3ZlciB0aW1lLCB3aXRoIGluY3JlYXNlcyBhbmQgZGVjcmVhc2VzIGZyb20gb25lIHllYXIgdG8gYW5vdGhlci4NCg0K4oCiIE5vcnRoZXJuIHN0YXRlcyBjb25zaXN0ZW50bHkgc2hvdyBoaWdoZXIgZXhwb3J0IGxldmVscyB0aGFuIHNvdXRoZXJuIHN0YXRlcy4NCg0K4oCiIFRoZSBzY2F0dGVyIHBsb3Qgb2YgZXhwb3J0cyB2ZXJzdXMgYm9yZGVyIGRpc3RhbmNlIHNob3dzIGEgbmVnYXRpdmUgcmVsYXRpb25zaGlwLiBTdGF0ZXMgY2xvc2VyIHRvIHRoZSBVLlMuIGJvcmRlciB0ZW5kIHRvIGV4cG9ydCBtb3JlLg0KDQrigKIgVGhlcmUgaXMgYSBwb3NpdGl2ZSByZWxhdGlvbnNoaXAgYmV0d2VlbiBleHBvcnRzIGFuZCBlbXBsb3ltZW50IGNvbmNlbnRyYXRpb24gaW4gdGhlIHNlY29uZGFyeSBzZWN0b3IuIFN0YXRlcyB3aXRoIHN0cm9uZ2VyIG1hbnVmYWN0dXJpbmcgbGFib3IgdGVuZCB0byBhY2hpZXZlIGhpZ2hlciBleHBvcnQgbGV2ZWxzLg0KDQrigKIgRXhwb3J0cyBhcmUgcG9zaXRpdmVseSBjb3JyZWxhdGVkIHdpdGggRkRJIGFuZCBhdmVyYWdlIGRhaWx5IHNhbGFyeS4gVGhpcyBzdWdnZXN0cyB0aGF0IG1vcmUgaW5kdXN0cmlhbGl6ZWQgc3RhdGVzIHBlcmZvcm0gYmV0dGVyIGluIGludGVybmF0aW9uYWwgdHJhZGUuDQoNCg0K