Exports EDA

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)
library(readr)
library(lmtest)
library(sandwich)
library(car)
library(dplyr)
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"
mexico_map <- ne_states(country = "mexico", returnclass = "sf")

setdiff(panel_data$state, mexico_map$name)
## [1] "Ciudad de Mexico" "Mexico"           "Michoacan"        "Nuevo Leon"      
## [5] "Queretaro"        "San Luis Potosi"  "Yucatan"
panel_full$state <- dplyr::recode(panel_full$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_full %>%
  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, real_public_investment_pc) %>%
  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.

Model Designs

Main Differences between cross – sectional regression analysis,

• Type of data used o Cross-sectional: Analyzes many individuals (people, firms, countries, etc.) at a single point in time. o Time series: Analyzes one individual or variable over a period of time. o Panel data: Combines both; analyzes multiple individuals across multiple time periods.

• Dimension of analysis o Cross-sectional: Has only an individual dimension (N). o Time series: Has only a time dimension (T). o Panel data: Has both an individual dimension (N) and a time dimension (T) simultaneously.

• Type of variability captured o Cross-sectional: Compares differences between individuals. o Time series: Examines changes over time. o Panel data: Allows analysis of both differences between individuals and changes over time simultaneously.

• Common statistical issues o Cross-sectional: May suffer from heteroskedasticity. o Time series: May suffer from autocorrelation and non-stationarity problems. o Panel data: May involve fixed or random effects, as well as autocorrelation and heteroskedasticity.

• Analytical capacity and depth o Cross-sectional: Simpler, but does not capture time dynamics. o Time series: Allows analysis of trends and cycles over time. o Panel data: More comprehensive because it better controls for individual heterogeneity and improves estimator precision.

Models

We defined a panel data model where real exports depend on industrial specialization, salaries, population density, and public investment per capita.

model_formula <- real_exports ~ lq_secondary +
                                  average_daily_salary + pop_density + real_public_investment_pc

We estimated a pooled model that ignores differences between states and years. Most variables were significant, and the model explained about 62 percent of exports variation.

pooling <- plm(model_formula, data = panel_data, model = "pooling")
summary(pooling)
## Pooling Model
## 
## Call:
## plm(formula = model_formula, data = panel_data, model = "pooling")
## 
## Balanced Panel: n = 32, T = 9, N = 288
## 
## Residuals:
##      Min.   1st Qu.    Median      Mean   3rd Qu.      Max. 
## -4.80e+08 -1.11e+08  4.19e+06  0.00e+00  1.09e+08  4.42e+08 
## 
## Coefficients:
##                              Estimate  Std. Error  t-value  Pr(>|t|)    
## (Intercept)               -1004258854    83563782 -12.0179 < 2.2e-16 ***
## lq_secondary                455153589    28339329  16.0608 < 2.2e-16 ***
## average_daily_salary          2449813      259179   9.4522 < 2.2e-16 ***
## pop_density                    -49737       11526  -4.3153 2.205e-05 ***
## real_public_investment_pc      -37243       25461  -1.4627    0.1447    
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Total Sum of Squares:    2.2278e+19
## Residual Sum of Squares: 8.3902e+18
## R-Squared:      0.62339
## Adj. R-Squared: 0.61807
## F-statistic: 117.11 on 4 and 283 DF, p-value: < 2.22e-16

This model controls for differences between states. The variables were not statistically significant, and the explanatory power was very low.

fe_ind <- plm(model_formula, data = panel_data, model = "within", effect = "individual")
summary(fe_ind)
## Oneway (individual) effect Within Model
## 
## Call:
## plm(formula = model_formula, data = panel_data, effect = "individual", 
##     model = "within")
## 
## Balanced Panel: n = 32, T = 9, N = 288
## 
## Residuals:
##      Min.   1st Qu.    Median      Mean   3rd Qu.      Max. 
## -1.20e+08 -1.12e+07 -7.81e+04  0.00e+00  8.88e+06  1.51e+08 
## 
## Coefficients:
##                             Estimate Std. Error t-value Pr(>|t|)
## lq_secondary              25034558.1 29583697.1  0.8462   0.3982
## average_daily_salary        -17708.3   116039.2 -0.1526   0.8788
## pop_density                 -21049.3   271104.2 -0.0776   0.9382
## real_public_investment_pc     7340.4     6973.5  1.0526   0.2935
## 
## Total Sum of Squares:    3.0639e+17
## Residual Sum of Squares: 3.0385e+17
## R-Squared:      0.0082919
## Adj. R-Squared: -0.12945
## F-statistic: 0.526758 on 4 and 252 DF, p-value: 0.71616

This model controls for differences between years. Most variables were significant, and this model had the highest R-squared.

fe_time <- plm(model_formula, data = panel_data, model = "within", effect = "time")
summary(fe_time)
## Oneway (time) effect Within Model
## 
## Call:
## plm(formula = model_formula, data = panel_data, effect = "time", 
##     model = "within")
## 
## Balanced Panel: n = 32, T = 9, N = 288
## 
## Residuals:
##      Min.   1st Qu.    Median      Mean   3rd Qu.      Max. 
## -3.85e+08 -9.29e+07  1.67e+06  0.00e+00  1.12e+08  4.15e+08 
## 
## Coefficients:
##                            Estimate Std. Error t-value  Pr(>|t|)    
## lq_secondary              435521531   27192797 16.0161 < 2.2e-16 ***
## average_daily_salary        3233824     280159 11.5428 < 2.2e-16 ***
## pop_density                  -63991      11248 -5.6889 3.268e-08 ***
## real_public_investment_pc    -76084      25687 -2.9620  0.003324 ** 
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Total Sum of Squares:    2.2211e+19
## Residual Sum of Squares: 7.3903e+18
## R-Squared:      0.66727
## Adj. R-Squared: 0.65275
## F-statistic: 137.876 on 4 and 275 DF, p-value: < 2.22e-16

This model controls for both state and year effects. Only one variable was weakly significant, and the model had low explanatory power.

fe_tw <- plm(model_formula, data = panel_data, model = "within", effect = "twoways")
summary(fe_tw)
## Twoways effects Within Model
## 
## Call:
## plm(formula = model_formula, data = panel_data, effect = "twoways", 
##     model = "within")
## 
## Balanced Panel: n = 32, T = 9, N = 288
## 
## Residuals:
##      Min.   1st Qu.    Median      Mean   3rd Qu.      Max. 
## -1.04e+08 -1.43e+07 -1.69e+06  0.00e+00  1.59e+07  1.29e+08 
## 
## Coefficients:
##                             Estimate Std. Error t-value Pr(>|t|)  
## lq_secondary              13539301.8 26702971.7  0.5070  0.61259  
## average_daily_salary        -28770.2   229440.3 -0.1254  0.90032  
## pop_density                -286037.4   252623.3 -1.1323  0.25863  
## real_public_investment_pc    13038.5     6598.8  1.9759  0.04929 *
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Total Sum of Squares:    2.3933e+17
## Residual Sum of Squares: 2.3375e+17
## R-Squared:      0.023305
## Adj. R-Squared: -0.14882
## F-statistic: 1.4555 on 4 and 244 DF, p-value: 0.21642

This model assumes that state differences are not related to the independent variables. Only one variable was significant, and the fit was weaker than the time fixed effects model.

re <- plm(model_formula, data = panel_data, model = "random")
summary(re)
## Oneway (individual) effect Random Effect Model 
##    (Swamy-Arora's transformation)
## 
## Call:
## plm(formula = model_formula, data = panel_data, model = "random")
## 
## Balanced Panel: n = 32, T = 9, N = 288
## 
## Effects:
##                     var   std.dev share
## idiosyncratic 1.206e+15 3.472e+07 0.044
## individual    2.602e+16 1.613e+08 0.956
## theta: 0.9284
## 
## Residuals:
##      Min.   1st Qu.    Median      Mean   3rd Qu.      Max. 
## -80456012 -18157289  -7849908         0  10480115 203393118 
## 
## Coefficients:
##                              Estimate  Std. Error z-value Pr(>|z|)   
## (Intercept)               139354203.5  56498460.8  2.4665 0.013644 * 
## lq_secondary               86780057.3  30093475.3  2.8837 0.003931 **
## average_daily_salary          31246.0    116089.7  0.2692 0.787811   
## pop_density                  -28431.3     29383.7 -0.9676 0.333251   
## real_public_investment_pc      7097.1      7531.2  0.9424 0.346009   
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Total Sum of Squares:    4.1893e+17
## Residual Sum of Squares: 4.0313e+17
## R-Squared:      0.037702
## Adj. R-Squared: 0.024101
## Chisq: 11.0878 on 4 DF, p-value: 0.025595

We tested whether fixed effects are necessary. The results showed that both state and time effects are important.

pFtest(fe_ind, pooling)
## 
##  F test for individual effects
## 
## data:  model_formula
## F = 216.34, df1 = 31, df2 = 252, p-value < 2.2e-16
## alternative hypothesis: significant effects
pFtest(fe_time, pooling)
## 
##  F test for time effects
## 
## data:  model_formula
## F = 4.6511, df1 = 8, df2 = 275, p-value = 2.384e-05
## alternative hypothesis: significant effects
pFtest(fe_tw, pooling)
## 
##  F test for twoways effects
## 
## data:  model_formula
## F = 218.31, df1 = 39, df2 = 244, p-value < 2.2e-16
## alternative hypothesis: significant effects

The Hausman test compared fixed and random effects. The result suggested that fixed effects are more appropriate.

phtest(fe_time, re)
## 
##  Hausman Test
## 
## data:  model_formula
## chisq = 729.9, df = 4, p-value < 2.2e-16
## alternative hypothesis: one model is inconsistent

We checked for multicollinearity. All VIF values were low, so there is no serious multicollinearity problem.

vif(lm(model_formula, data = panel_data))
##              lq_secondary      average_daily_salary               pop_density 
##                  1.112735                  1.398501                  1.460673 
## real_public_investment_pc 
##                  1.054705

We found heteroskedasticity and serial correlation in the errors. This means we should use robust standard errors.

bptest(fe_time)
## 
##  studentized Breusch-Pagan test
## 
## data:  fe_time
## BP = 108.78, df = 4, p-value < 2.2e-16
pbgtest(fe_time)
## 
##  Breusch-Godfrey/Wooldridge test for serial correlation in panel models
## 
## data:  model_formula
## chisq = 187.28, df = 9, p-value < 2.2e-16
## alternative hypothesis: serial correlation in idiosyncratic errors

We re-estimated the time fixed effects model using robust standard errors to correct for heteroskedasticity and serial correlation. After this correction, lq_secondary, average_daily_salary, and pop_density remained statistically significant. However, real_public_investment_pc was not statistically significant. This confirms that the main results are still strong even after using robust errors.

coeftest(fe_time, vcov = vcovHC(fe_time, method = "arellano", type = "HC1"))
## 
## t test of coefficients:
## 
##                            Estimate Std. Error t value  Pr(>|t|)    
## lq_secondary              435521531  100305923  4.3419 1.987e-05 ***
## average_daily_salary        3233824     906833  3.5661 0.0004273 ***
## pop_density                  -63991      22148 -2.8892 0.0041691 ** 
## real_public_investment_pc    -76084      52580 -1.4470 0.1490316    
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1

Results

library(plm)

models <- list(
  Pooling = pooling,
  FE_Individual = fe_ind,
  FE_TwoWays = fe_tw,
  RE = re,
  FE_Time = fe_time
)

comparison <- data.frame(
  Model = names(models),
  R2 = sapply(models, function(m) summary(m)$r.squared["rsq"]),
  Adj_R2 = sapply(models, function(m) summary(m)$r.squared["adjrsq"])
)

comparison
##                           Model          R2      Adj_R2
## Pooling.rsq             Pooling 0.623389824  0.61806671
## FE_Individual.rsq FE_Individual 0.008291903 -0.12944533
## FE_TwoWays.rsq       FE_TwoWays 0.023304595 -0.14881796
## RE.rsq                       RE 0.037702199  0.02410082
## FE_Time.rsq             FE_Time 0.667272482  0.65275346

According to the time fixed effects model with robust standard errors, the main driver of Mexico’s exports inflows is industrial specialization (lq_secondary). States with a stronger secondary sector tend to have significantly higher export levels. This suggests that manufacturing and industrial concentration play a key role in export performance.

Average daily salary is also positive and statistically significant. This may indicate that more productive and developed states, which pay higher wages, are also more competitive in international markets.

Population density has a negative and significant effect. This could suggest congestion effects or structural differences in highly populated states that reduce export performance.

Real public investment per capita was not statistically significant after using robust errors. Therefore, public investment does not appear to have a clear direct effect on export inflows in this model.

In summary, the main drivers of exports are industrial specialization and wage levels, while high population density may represent a structural challenge for export growth.

Elasticity

his is a log-log model, so the coefficients are elasticities.

Industrial specialization has an elasticity of 2.69 and is highly significant. A 1 percent increase in industrial concentration increases exports by about 2.7 percent. This is the main driver of export inflows.

Average daily salary has an elasticity of 6.74 and is also significant. Higher wages are associated with higher exports.

Population density and public investment are not statistically significant.

The model explains about 67 percent of export variation.

elasticity_formula <- log(real_exports) ~ log(lq_secondary) +
                    log(average_daily_salary) +
                    log(pop_density) +
                    log(real_public_investment_pc)
fe_time_elasticity <- plm(
  elasticity_formula,
  data = panel_data,
  model = "within",
  effect = "time"
)

summary(fe_time_elasticity)
## Oneway (time) effect Within Model
## 
## Call:
## plm(formula = elasticity_formula, data = panel_data, effect = "time", 
##     model = "within")
## 
## Balanced Panel: n = 32, T = 9, N = 288
## 
## Residuals:
##      Min.   1st Qu.    Median   3rd Qu.      Max. 
## -2.378580 -0.747761 -0.019808  0.786587  2.443928 
## 
## Coefficients:
##                                 Estimate Std. Error t-value Pr(>|t|)    
## log(lq_secondary)               2.688744   0.159687 16.8375   <2e-16 ***
## log(average_daily_salary)       6.744763   0.535786 12.5885   <2e-16 ***
## log(pop_density)               -0.048301   0.050077 -0.9645   0.3356    
## log(real_public_investment_pc)  0.013008   0.081292  0.1600   0.8730    
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Total Sum of Squares:    896.68
## Residual Sum of Squares: 296.84
## R-Squared:      0.66895
## Adj. R-Squared: 0.65451
## F-statistic: 138.925 on 4 and 275 DF, p-value: < 2.22e-16

Industrial specialization is the main driver of exports. A 1 percent increase in industrial concentration increases exports by about 2.7 percent. This shows that manufacturing strength is very important for Mexico’s export inflows.

Average daily salary also has a strong positive effect. A 1 percent increase in wages increases exports by about 6.7 percent. This suggests that more productive and developed states export more.

Population density and public investment are not statistically significant, so they do not show a clear impact on export inflows in this model.

LS0tDQp0aXRsZTogIk1leGljbyBFeHBvcnRzIg0KYXV0aG9yOiAiT3N2YWxkbyBMb3BleiwgT3NjYXIgQmFyY2FyY2VsLCBNYXJpZWwgR2FyemEiDQpkYXRlOiAiMjAyNi0wMi0xNiINCm91dHB1dDogDQogIGh0bWxfZG9jdW1lbnQ6DQogICAgdG9jOiBUUlVFDQogICAgdG9jX2Zsb2F0OiBUUlVFDQogICAgY29kZV9kb3dubG9hZDogVFJVRQ0KICAgIHRoZW1lOiAic3BhY2VsYWIiDQogICAgaGlnaGxpZ2h0OiAia2F0ZSINCi0tLQ0KDQpgYGB7ciBzZXR1cCwgaW5jbHVkZT1GQUxTRX0NCmtuaXRyOjpvcHRzX2NodW5rJHNldChlY2hvID0gVFJVRSkNCmBgYA0KDQojIEV4cG9ydHMgRURBDQojIyBNZXhpY28gZXhwb3J0cyBjaGFyYWN0ZXJpc3RpY3MNCuKAoiBNZXhpY2/igJlzIGV4cG9ydHMgZ3JldyBzdHJvbmdseSBiZXR3ZWVuIDIwMTUgYW5kIDIwMjUsIGFsbW9zdCBkb3VibGluZyBpbiB0b3RhbCB2YWx1ZS4gVGhpcyBzaG93cyBob3cgaW1wb3J0YW50IGludGVybmF0aW9uYWwgdHJhZGUgaXMgZm9yIHRoZSBNZXhpY2FuIGVjb25vbXkuDQoNCuKAoiBBcm91bmQgOTAlIG9mIGV4cG9ydHMgY29tZSBmcm9tIG1hbnVmYWN0dXJlZCBnb29kcywgZXNwZWNpYWxseSBhdXRvbW90aXZlLCBlbGVjdHJvbmljcywgYW5kIG1hY2hpbmVyeS4gTWV4aWNvIGlzIGhpZ2hseSBzcGVjaWFsaXplZCBpbiBpbmR1c3RyaWFsIHByb2R1Y3Rpb24uDQoNCuKAoiBNb3JlIHRoYW4gODAlIG9mIGV4cG9ydHMgZ28gdG8gdGhlIFVuaXRlZCBTdGF0ZXMuIFRoaXMgbWVhbnMgTWV4aWNvIGRlcGVuZHMgaGVhdmlseSBvbiB0aGUgVS5TLiBtYXJrZXQgYW5kIHJlZ2lvbmFsIHN1cHBseSBjaGFpbnMuDQoNCuKAoiBFdmVuIHdpdGggY2hhbGxlbmdlcyBzdWNoIGFzIENPVklELTE5IGFuZCB0aGUgcmVuZWdvdGlhdGlvbiBvZiBOQUZUQSBpbnRvIFVTTUNBLCBleHBvcnRzIHJlY292ZXJlZCBxdWlja2x5IGFuZCBjb250aW51ZWQgZ3Jvd2luZy4NCg0KIyMjIENvbnRyaWJ1dGlvbiBvZiBQYW5lbCBEYXRhIEFuYWx5c2lzIHRvIFVuZGVyc3RhbmRpbmcgRXhwb3J0IFBlcmZvcm1hbmNlDQoNCuKAoiBQYW5lbCBkYXRhIGNvbWJpbmVzIGluZm9ybWF0aW9uIGFjcm9zcyBzdGF0ZXMgb3Igc2VjdG9ycyBhbmQgYWNyb3NzIHRpbWUuIFRoaXMgaGVscHMgdXMgc2VlIGRpZmZlcmVuY2VzIGJldHdlZW4gcmVnaW9ucyBhbmQgaG93IGV4cG9ydHMgY2hhbmdlIGVhY2ggeWVhci4NCg0K4oCiIEl0IGFsbG93cyB1cyB0byBjb250cm9sIGZvciBjaGFyYWN0ZXJpc3RpY3MgdGhhdCBkbyBub3QgY2hhbmdlIG92ZXIgdGltZSwgc3VjaCBhcyBnZW9ncmFwaHkgb3IgaW5kdXN0cmlhbCBzdHJ1Y3R1cmUuIFRoaXMgbWFrZXMgdGhlIGFuYWx5c2lzIG1vcmUgYWNjdXJhdGUuDQoNCuKAoiBQYW5lbCBtb2RlbHMgaGVscCBzZXBhcmF0ZSBsb25nLXRlcm0gc3RydWN0dXJhbCBmYWN0b3JzIGZyb20gc2hvcnQtdGVybSBzaG9ja3MsIHN1Y2ggYXMgdGVtcG9yYXJ5IHRhcmlmZiBjaGFuZ2VzLg0KDQojIyMgVXNlIG9mIFBhbmVsIERhdGEgZm9yIFNob3J04oCRVGVybSBFeHBvcnQgUHJlZGljdGlvbg0KDQrigKIgV2UgY2FuIHVzZSBwYXN0IGV4cG9ydCB0cmVuZHMgZnJvbSBkaWZmZXJlbnQgc3RhdGVzIG9yIHNlY3RvcnMgdG8gZXN0aW1hdGUgd2hhdCBjb3VsZCBoYXBwZW4gaW4gdGhlIG5leHQgMeKAkzIgeWVhcnMuDQoNCuKAoiBJdCBpcyBwb3NzaWJsZSB0byBpbmNsdWRlIHZhcmlhYmxlcyBsaWtlIGV4Y2hhbmdlIHJhdGUsIFUuUy4gZWNvbm9taWMgZ3Jvd3RoLCBvciB0YXJpZmYgY2hhbmdlcyB0byBzaW11bGF0ZSBkaWZmZXJlbnQgc2NlbmFyaW9zLg0KDQrigKIgUHJlZGljdGlvbnMgY2FuIGJlIG1hZGUgYXQgdGhlIHN0YXRlIG9yIHNlY3RvciBsZXZlbCwgbm90IG9ubHkgZm9yIHRoZSB3aG9sZSBjb3VudHJ5LiBUaGlzIGdpdmVzIG1vcmUgc3BlY2lmaWMgYW5kIHVzZWZ1bCByZXN1bHRzLg0KDQojIyMgUm9sZSBvZiBCdXNpbmVzcyBJbnRlbGxpZ2VuY2UgYW5kIFByZWRpY3RpdmUgQW5hbHl0aWNzIGZvciBJZGVudGlmeWluZyBWdWxuZXJhYmlsaXR5IER1cmluZyBVU01DQSBOZWdvdGlhdGlvbnMNCg0K4oCiIEJ1c2luZXNzIEludGVsbGlnZW5jZSB0b29scyBjYW4gbWVhc3VyZSBob3cgbXVjaCBlYWNoIHN0YXRlIG9yIHNlY3RvciBkZXBlbmRzIG9uIGV4cG9ydHMgdG8gdGhlIFUuUy4gVGhpcyBoZWxwcyBpZGVudGlmeSB3aGljaCBvbmVzIGFyZSBtb3JlIGV4cG9zZWQgdG8gdGFyaWZmIGNoYW5nZXMuDQoNCuKAoiBQcmVkaWN0aXZlIG1vZGVscyBjYW4gZXN0aW1hdGUgaG93IHNlbnNpdGl2ZSBleHBvcnRzIGFyZSB0byBuZXcgdHJhZGUgcnVsZXMuIFdpdGggdGhpcywgd2UgY2FuIGNsYXNzaWZ5IHN0YXRlcyBvciBpbmR1c3RyaWVzIGJ5IGxldmVsIG9mIHJpc2suDQoNCuKAoiBEYXNoYm9hcmRzIGFuZCB2aXN1YWwgdG9vbHMgYWxsb3cgZGVjaXNpb24gbWFrZXJzIHRvIG1vbml0b3IgZXhwb3J0IHBlcmZvcm1hbmNlIGJlZm9yZSBhbmQgYWZ0ZXIgcG9saWN5IGNoYW5nZXMuDQoNCuKAoiBNYWNoaW5lIGxlYXJuaW5nIHRlY2huaXF1ZXMgY2FuIGdyb3VwIHN0YXRlcyBvciBzZWN0b3JzIHdpdGggc2ltaWxhciBleHBvcnQgc3RydWN0dXJlcy4gVGhpcyBoZWxwcyBpZGVudGlmeSBwYXR0ZXJucyBvZiB2dWxuZXJhYmlsaXR5IGR1cmluZyB0cmFkZSBuZWdvdGlhdGlvbnMuDQoNCiMjIyBFeHBvcnRzIERhdGEgQW5hbHlzaXMgDQojIyMjIERhdGEgQ2xlYW5pbmcgYW5kIFRyYW5zZm9ybWluZw0KDQpgYGB7ciwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0NCg0KbGlicmFyeShyZWFkeGwpDQpsaWJyYXJ5KHRpZHl2ZXJzZSkNCmxpYnJhcnkocGxtKQ0KbGlicmFyeShzZikNCmxpYnJhcnkocm5hdHVyYWxlYXJ0aCkNCmxpYnJhcnkoZHBseXIpDQpsaWJyYXJ5KGdncGxvdDIpDQpsaWJyYXJ5KHJlc2hhcGUyKQ0KbGlicmFyeShyZWFkcikNCmxpYnJhcnkobG10ZXN0KQ0KbGlicmFyeShzYW5kd2ljaCkNCmxpYnJhcnkoY2FyKQ0KbGlicmFyeShkcGx5cikNCg0KYGBgDQoNCg0KYGBge3J9DQpkZl9leHBvIDwtIHJlYWRfZXhjZWwoIkM6L1VzZXJzL09zdmFsL0Rvd25sb2Fkcy9pbmVnaV9leHBvcnRzX2RhdGFzZXQueGxzeCIsIHNoZWV0ID0gImV4cG9ydHMiKQ0KZGZfdHMgPC0gcmVhZF9leGNlbCgiQzovVXNlcnMvT3N2YWwvRG93bmxvYWRzL2luZWdpX2V4cG9ydHNfZGF0YXNldC54bHN4Iiwgc2hlZXQgPSAidHNfZXhwb3J0cyIpDQpkZl9kYXRhIDwtIHJlYWRfZXhjZWwoIkM6L1VzZXJzL09zdmFsL0Rvd25sb2Fkcy9pbmVnaV9leHBvcnRzX2RhdGFzZXQueGxzeCIsIHNoZWV0ID0gImRhdGEiKQ0KZGZfZmRpIDwtIHJlYWRfZXhjZWwoIkM6L1VzZXJzL09zdmFsL0Rvd25sb2Fkcy9pbmVnaV9leHBvcnRzX2RhdGFzZXQueGxzeCIsIHNoZWV0ID0gImZkaSIpDQoNCmBgYA0KDQrigKIgVGhlIG9yaWdpbmFsIGRhdGFzZXRzIHdlcmUgY2xlYW5lZCBhbmQgdHJhbnNmb3JtZWQuIEV4cG9ydCB2YXJpYWJsZXMgd2VyZSBjb252ZXJ0ZWQgZnJvbSB3aWRlIGZvcm1hdCB0byBsb25nIGZvcm1hdCBzbyBlYWNoIHJvdyByZXByZXNlbnRzIG9uZSBzdGF0ZSBpbiBvbmUgc3BlY2lmaWMgeWVhci4NCg0KYGBge3J9DQpkZl9leHBvbG9uZyA8LSBkZl9leHBvICU+JQ0KICBwaXZvdF9sb25nZXIoDQogICAgY29scyA9IHN0YXJ0c193aXRoKCJyZWFsX2V4cG9ydHNfIiksDQogICAgbmFtZXNfdG8gPSAieWVhciIsDQogICAgbmFtZXNfcHJlZml4ID0gInJlYWxfZXhwb3J0c18iLA0KICAgIHZhbHVlc190byA9ICJyZWFsX2V4cG9ydHMiDQogICkNCg0KZGZfZmRpbG9uZyA8LSBkZl9mZGkgJT4lDQogIHBpdm90X2xvbmdlcigNCiAgICBjb2xzID0gc3RhcnRzX3dpdGgoImZkaV8iKSwNCiAgICBuYW1lc190byA9ICJ5ZWFyIiwNCiAgICBuYW1lc19wcmVmaXggPSAiZmRpXyIsDQogICAgdmFsdWVzX3RvID0gImZkaSINCiAgKQ0KDQpgYGANCg0K4oCiIFdlIHZlcmlmaWVkIHRoYXQgdGhlcmUgd2VyZSBubyBkdXBsaWNhdGVkIG9ic2VydmF0aW9ucyBieSBzdGF0ZSBhbmQgeWVhciBiZWZvcmUgbWVyZ2luZyB0aGUgZGF0YXNldHMuDQoNCg0KYGBge3J9DQpkZl9leHBvbG9uZyAlPiUgY291bnQoc3RhdGUsIHllYXIsIHJlZ2lvbikgJT4lIGZpbHRlcihuID4gMSkNCmRmX2RhdGEgJT4lIGNvdW50KHN0YXRlLCB5ZWFyKSAlPiUgZmlsdGVyKG4gPiAxKQ0KZGZfZmRpbG9uZyAlPiUgY291bnQoc3RhdGUsIHllYXIsIHJlZ2lvbikgJT4lIGZpbHRlcihuID4gMSkNCg0KYGBgDQoNCuKAoiBEaWZmZXJlbnQgZGF0YXNldHMgKGV4cG9ydHMsIEZESSwgbWFjcm9lY29ub21pYyB2YXJpYWJsZXMsIGFuZCBzdGF0ZSBjaGFyYWN0ZXJpc3RpY3MpIHdlcmUgbWVyZ2VkIHVzaW5nIHN0YXRlIGFuZCB5ZWFyIGFzIGtleSB2YXJpYWJsZXMuDQoNCmBgYHtyfQ0KZGZfZXhwb2xvbmckeWVhciA8LSBhcy5udW1lcmljKGRmX2V4cG9sb25nJHllYXIpDQpkZl9mZGlsb25nJHllYXIgPC0gYXMubnVtZXJpYyhkZl9mZGlsb25nJHllYXIpDQpkZl9kYXRhJHllYXIgPC0gYXMubnVtZXJpYyhkZl9kYXRhJHllYXIpDQoNCmBgYA0KDQpgYGB7cn0NCnBhbmVsX2Z1bGwgPC0gZGZfZXhwb2xvbmcgJT4lDQogIGxlZnRfam9pbihkZl9mZGlsb25nLCBieSA9IGMoInN0YXRlIiwgInllYXIiLCAicmVnaW9uIikpICU+JQ0KICBsZWZ0X2pvaW4oZGZfZGF0YSwgYnkgPSBjKCJzdGF0ZSIsICJ5ZWFyIikpDQoNCmBgYA0KDQrigKIgTWlzc2luZyB2YWx1ZXMgd2VyZSByZXBsYWNlZCB1c2luZyB0aGUgYXZlcmFnZSB2YWx1ZSBieSBzdGF0ZSBpbiBvcmRlciB0byBtYWludGFpbiBhIGJhbGFuY2VkIHBhbmVsIHN0cnVjdHVyZS4NCg0KYGBge3J9DQpwYW5lbF9mdWxsIDwtIHBhbmVsX2Z1bGwgJT4lDQogIGdyb3VwX2J5KHN0YXRlKSAlPiUNCiAgbXV0YXRlKA0KICAgIGFjcm9zcygNCiAgICAgIHdoZXJlKGlzLm51bWVyaWMpLCANCiAgICAgIH4gaWZlbHNlKGlzLm5hKC4pLCBtZWFuKC4sIG5hLnJtID0gVFJVRSksIC4pDQogICAgKQ0KICApICU+JQ0KICB1bmdyb3VwKCkNCg0KYGBgDQoNCuKAoiBBIHBhbmVsIGRhdGFzZXQgd2FzIGNyZWF0ZWQgdXNpbmcgc3RhdGUgYW5kIHllYXIgYXMgaW5kZXhlcywgYWxsb3dpbmcgYW5hbHlzaXMgYWNyb3NzIHRpbWUgYW5kIGFjcm9zcyByZWdpb25zLg0KDQpgYGB7cn0NCnBhbmVsX2RhdGEgPC0gcGRhdGEuZnJhbWUocGFuZWxfZnVsbCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgaW5kZXggPSBjKCJzdGF0ZSIsICJ5ZWFyIikpDQpgYGANCg0KDQojIyBFeHBsb3JhdG9yeSBEYXRhIEFuYWx5c2lzIOKAkyBFREENCg0KIyMjIERlc2NyaXB0aXZlIFN0YXRpc3RpY3MNCg0KYGBge3J9DQpyZWdpb25hbF9hdmcgPC0gcGFuZWxfZnVsbCAlPiUNCiAgZ3JvdXBfYnkocmVnaW9uKSAlPiUNCiAgc3VtbWFyaXNlKA0KICAgIGF2Z19leHBvcnRzID0gbWVhbihyZWFsX2V4cG9ydHMsIG5hLnJtID0gVFJVRSksDQogICAgYXZnX2ZkaSA9IG1lYW4oZmRpLCBuYS5ybSA9IFRSVUUpLA0KICAgIGF2Z19leGNoYW5nZV9yYXRlID0gbWVhbihleGNoYW5nZV9yYXRlLCBuYS5ybSA9IFRSVUUpLA0KICAgIGF2Z19jb2xsZWdlID0gbWVhbihjb2xsZWdlX2VkdWNhdGlvbiwgbmEucm0gPSBUUlVFKSwNCiAgICAuZ3JvdXBzID0gImRyb3AiDQogICkNCmdncGxvdChyZWdpb25hbF9hdmcsIGFlcyh4ID0gcmVnaW9uLCB5ID0gYXZnX2V4cG9ydHMpKSArDQogIGdlb21fY29sKCkgKw0KICBsYWJzKHRpdGxlID0gIkF2ZXJhZ2UgRXhwb3J0cyBieSBSZWdpb24iLA0KICAgICAgIHggPSAiUmVnaW9uIiwNCiAgICAgICB5ID0gIkF2ZXJhZ2UgUmVhbCBFeHBvcnRzIikgKw0KICB0aGVtZV9taW5pbWFsKCkNCg0KYGBgDQpgYGB7cn0NCmdncGxvdChyZWdpb25hbF9hdmcsIGFlcyh4ID0gcmVnaW9uLCB5ID0gYXZnX2ZkaSkpICsNCiAgZ2VvbV9jb2woKSArDQogIGxhYnModGl0bGUgPSAiQXZlcmFnZSBGREkgYnkgUmVnaW9uIiwNCiAgICAgICB4ID0gIlJlZ2lvbiIsDQogICAgICAgeSA9ICJBdmVyYWdlIEZESSIpICsNCiAgdGhlbWVfbWluaW1hbCgpDQoNCmBgYA0KDQpgYGB7cn0NCmdncGxvdChyZWdpb25hbF9hdmcsIGFlcyh4ID0gcmVnaW9uLCB5ID0gYXZnX2NvbGxlZ2UpKSArDQogIGdlb21fY29sKCkgKw0KICBsYWJzKHRpdGxlID0gIkF2ZXJhZ2UgQ29sbGVnZSBFZHVjYXRpb24gYnkgUmVnaW9uIiwNCiAgICAgICB4ID0gIlJlZ2lvbiIsDQogICAgICAgeSA9ICJBdmVyYWdlIENvbGxlZ2UgRWR1Y2F0aW9uIikgKw0KICB0aGVtZV9taW5pbWFsKCkNCg0KYGBgDQpgYGB7cn0NCmdncGxvdChwYW5lbF9mdWxsLCBhZXMoeCA9IHJlYWxfZXhwb3J0cykpICsNCiAgZ2VvbV9oaXN0b2dyYW0oYmlucyA9IDMwKSArDQogIGxhYnModGl0bGUgPSAiRGlzdHJpYnV0aW9uIG9mIFJlYWwgRXhwb3J0cyIsDQogICAgICAgeCA9ICJSZWFsIEV4cG9ydHMiLA0KICAgICAgIHkgPSAiRnJlcXVlbmN5IikgKw0KICB0aGVtZV9taW5pbWFsKCkNCg0KYGBgDQpgYGB7cn0NCmdncGxvdChwYW5lbF9mdWxsLCBhZXMoeCA9IGZkaSkpICsNCiAgZ2VvbV9oaXN0b2dyYW0oYmlucyA9IDMwKSArDQogIGxhYnModGl0bGUgPSAiRGlzdHJpYnV0aW9uIG9mIEZESSIsDQogICAgICAgeCA9ICJGREkiLA0KICAgICAgIHkgPSAiRnJlcXVlbmN5IikgKw0KICB0aGVtZV9taW5pbWFsKCkNCg0KYGBgDQpgYGB7cn0NCmdncGxvdChwYW5lbF9mdWxsLCBhZXMoeCA9IGNvbGxlZ2VfZWR1Y2F0aW9uKSkgKw0KICBnZW9tX2hpc3RvZ3JhbShiaW5zID0gMzApICsNCiAgbGFicyh0aXRsZSA9ICJEaXN0cmlidXRpb24gb2YgQ29sbGVnZSBFZHVjYXRpb24iLA0KICAgICAgIHggPSAiQ29sbGVnZSBFZHVjYXRpb24iLA0KICAgICAgIHkgPSAiRnJlcXVlbmN5IikgKw0KICB0aGVtZV9taW5pbWFsKCkNCg0KYGBgDQoNCiMjIyBTdGF0aXN0aWNzIG9mIERpc3BlcnNpb24NCg0KYGBge3J9DQpnZ3Bsb3QocGFuZWxfZnVsbCwgYWVzKHggPSByZWdpb24sIHkgPSByZWFsX2V4cG9ydHMpKSArDQogIGdlb21fYm94cGxvdCgpICsNCiAgbGFicyh0aXRsZSA9ICJFeHBvcnRzIERpc3RyaWJ1dGlvbiBBY3Jvc3MgUmVnaW9ucyIsDQogICAgICAgeCA9ICJSZWdpb24iLA0KICAgICAgIHkgPSAiUmVhbCBFeHBvcnRzIikgKw0KICB0aGVtZV9taW5pbWFsKCkNCg0KYGBgDQpgYGB7cn0NCmdncGxvdChwYW5lbF9mdWxsLCBhZXMoeCA9IHJlZ2lvbiwgeSA9IGZkaSkpICsNCiAgZ2VvbV9ib3hwbG90KCkgKw0KICBsYWJzKHRpdGxlID0gIkZESSBEaXN0cmlidXRpb24gQWNyb3NzIFJlZ2lvbnMiLA0KICAgICAgIHggPSAiUmVnaW9uIiwNCiAgICAgICB5ID0gIkZESSIpICsNCiAgdGhlbWVfbWluaW1hbCgpDQoNCmBgYA0KDQpgYGB7cn0NCmdncGxvdChwYW5lbF9mdWxsLCBhZXMoeCA9IHJlZ2lvbiwgeSA9IGxxX3ByaW1hcnkpKSArDQogIGdlb21fYm94cGxvdCgpICsNCiAgbGFicyh0aXRsZSA9ICJDb2xsZWdlIEVkdWNhdGlvbiBBY3Jvc3MgUmVnaW9ucyIsDQogICAgICAgeCA9ICJSZWdpb24iLA0KICAgICAgIHkgPSAiQ29sbGVnZSBFZHVjYXRpb24iKSArDQogIHRoZW1lX21pbmltYWwoKQ0KDQpgYGANCmBgYHtyfQ0KZ2dwbG90KHBhbmVsX2Z1bGwsIGFlcyh4ID0gcmVnaW9uLCB5ID0gbHFfc2Vjb25kYXJ5KSkgKw0KICBnZW9tX2JveHBsb3QoKSArDQogIGxhYnModGl0bGUgPSAiQ29sbGVnZSBFZHVjYXRpb24gQWNyb3NzIFJlZ2lvbnMiLA0KICAgICAgIHggPSAiUmVnaW9uIiwNCiAgICAgICB5ID0gIkNvbGxlZ2UgRWR1Y2F0aW9uIikgKw0KICB0aGVtZV9taW5pbWFsKCkNCg0KYGBgDQoNCiMjIyBWaXN1YWxpemF0aW9uIGFjcm9zcyBUaW1lDQoNCg0KYGBge3J9DQpleHBvcnRzX3RpbWUgPC0gcGFuZWxfZnVsbCAlPiUNCiAgZ3JvdXBfYnkoeWVhcikgJT4lDQogIHN1bW1hcmlzZSh0b3RhbF9leHBvcnRzID0gc3VtKHJlYWxfZXhwb3J0cywgbmEucm0gPSBUUlVFKSkNCg0KZ2dwbG90KGV4cG9ydHNfdGltZSwgYWVzKHggPSB5ZWFyLCB5ID0gdG90YWxfZXhwb3J0cykpICsNCiAgZ2VvbV9saW5lKHNpemUgPSAxKSArDQogIGxhYnModGl0bGUgPSAiVG90YWwgRXhwb3J0cyBJbmZsb3dzIGluIE1leGljbyIsDQogICAgICAgeCA9ICJZZWFyIiwNCiAgICAgICB5ID0gIlRvdGFsIFJlYWwgRXhwb3J0cyIpICsNCiAgdGhlbWVfbWluaW1hbCgpDQpgYGANCuKAoiBUb3RhbCBleHBvcnRzIHNob3cgYSBjbGVhciB1cHdhcmQgdHJlbmQgb3ZlciB0aGUgcGVyaW9kLiBUaGVyZSBpcyBhIHRlbXBvcmFyeSBkZWNsaW5lIGFyb3VuZCB0aGUgQ09WSUQtMTkgcGVyaW9kLCBidXQgZXhwb3J0cyByZWNvdmVyIHF1aWNrbHkgYW5kIGNvbnRpbnVlIGdyb3dpbmcuDQoNCg0KYGBge3J9DQpleHBvcnRzX3JlZ2lvbiA8LSBwYW5lbF9mdWxsICU+JQ0KICBncm91cF9ieShyZWdpb24sIHllYXIpICU+JQ0KICBzdW1tYXJpc2UodG90YWxfZXhwb3J0cyA9IHN1bShyZWFsX2V4cG9ydHMsIG5hLnJtID0gVFJVRSksDQogICAgICAgICAgICAuZ3JvdXBzID0gImRyb3AiKQ0KDQpnZ3Bsb3QoZXhwb3J0c19yZWdpb24sIGFlcyh4ID0geWVhciwgeSA9IHRvdGFsX2V4cG9ydHMsIGNvbG9yID0gcmVnaW9uKSkgKw0KICBnZW9tX2xpbmUobGluZXdpZHRoID0gMSkgKw0KICBsYWJzKHRpdGxlID0gIlRvdGFsIEV4cG9ydHMgSW5mbG93cyBieSBSZWdpb24iLA0KICAgICAgIHggPSAiWWVhciIsDQogICAgICAgeSA9ICJUb3RhbCBSZWFsIEV4cG9ydHMiLA0KICAgICAgIGNvbG9yID0gIlJlZ2lvbiIpICsNCiAgdGhlbWVfbWluaW1hbCgpDQoNCmBgYA0K4oCiIE5vcnRoZXJuIHJlZ2lvbnMgc2hvdyBoaWdoZXIgZXhwb3J0IGxldmVscyBjb21wYXJlZCB0byBzb3V0aGVybiByZWdpb25zLg0KDQrigKIgVGhlIGdhcCBiZXR3ZWVuIHJlZ2lvbnMgcmVtYWlucyBwZXJzaXN0ZW50IG92ZXIgdGltZSwgd2hpY2ggc3VnZ2VzdHMgc3RydWN0dXJhbCBkaWZmZXJlbmNlcyBpbiBpbmR1c3RyaWFsIGRldmVsb3BtZW50Lg0KYGBge3J9DQptYWNyb190aW1lIDwtIHBhbmVsX2Z1bGwgJT4lDQogIGdyb3VwX2J5KHllYXIpICU+JQ0KICBzdW1tYXJpc2UoDQogICAgdG90YWxfZXhwb3J0cyA9IHN1bShyZWFsX2V4cG9ydHMsIG5hLnJtID0gVFJVRSksDQogICAgYXZnX2V4Y2hhbmdlX3JhdGUgPSBtZWFuKGV4Y2hhbmdlX3JhdGUsIG5hLnJtID0gVFJVRSksDQogICAgLmdyb3VwcyA9ICJkcm9wIg0KICApDQptYWNyb190aW1lIDwtIG1hY3JvX3RpbWUgJT4lDQogIG11dGF0ZSgNCiAgICBleHBvcnRzX2luZGV4ID0gdG90YWxfZXhwb3J0cyAvIG1heCh0b3RhbF9leHBvcnRzKSwNCiAgICBleGNoYW5nZV9pbmRleCA9IGF2Z19leGNoYW5nZV9yYXRlIC8gbWF4KGF2Z19leGNoYW5nZV9yYXRlKQ0KICApDQpnZ3Bsb3QobWFjcm9fdGltZSwgYWVzKHggPSB5ZWFyKSkgKw0KICBnZW9tX2xpbmUoYWVzKHkgPSBleHBvcnRzX2luZGV4LCBjb2xvciA9ICJFeHBvcnRzIiksIGxpbmV3aWR0aCA9IDEuMikgKw0KICBnZW9tX2xpbmUoYWVzKHkgPSBleGNoYW5nZV9pbmRleCwgY29sb3IgPSAiRXhjaGFuZ2UgUmF0ZSIpLCBsaW5ld2lkdGggPSAxLjIpICsNCiAgbGFicyh0aXRsZSA9ICJFeHBvcnRzIEluZmxvd3MgdnMgRXhjaGFuZ2UgUmF0ZSAoSW5kZXhlZCkiLA0KICAgICAgIHggPSAiWWVhciIsDQogICAgICAgeSA9ICJJbmRleGVkIFZhbHVlcyIsDQogICAgICAgY29sb3IgPSAiIikgKw0KICB0aGVtZV9taW5pbWFsKCkNCg0KYGBgDQrigKIgV2hlbiBjb21wYXJpbmcgaW5kZXhlZCBleHBvcnRzIGFuZCBleGNoYW5nZSByYXRlLCBib3RoIHZhcmlhYmxlcyBzaG93IHNpbWlsYXIgbW92ZW1lbnRzIGluIHNvbWUgeWVhcnMuDQoNCuKAoiBUaGlzIHN1Z2dlc3RzIHRoYXQgZXhjaGFuZ2UgcmF0ZSBmbHVjdHVhdGlvbnMgbWF5IGluZmx1ZW5jZSBleHBvcnQgcGVyZm9ybWFuY2UsIGFsdGhvdWdoIHRoZSByZWxhdGlvbnNoaXAgaXMgbm90IHBlcmZlY3RseSBsaW5lYXIuDQoNCiMjI1JlZ2lvbmFsIERpZmZlcmVuY2VzDQoNCmBgYHtyfQ0KcGFuZWxfZnVsbCA8LSBwYW5lbF9mdWxsICU+JQ0KICBtdXRhdGUoem9uZSA9IGlmZWxzZShib3JkZXJfZGlzdGFuY2UgPCA0MDAsICJOb3J0aCIsICJTb3V0aCIpKQ0KcGFuZWxfZnVsbCA8LSBwYW5lbF9mdWxsICU+JQ0KICBtdXRhdGUoem9uZSA9IGlmZWxzZShyZWdpb24gJWluJSBjKCJOb3JvZXN0ZSIsICJOb3Jlc3RlIiksIA0KICAgICAgICAgICAgICAgICAgICAgICAiTm9ydGgiLCANCiAgICAgICAgICAgICAgICAgICAgICAgIlNvdXRoIikpDQpub3J0aF9zb3V0aF9leHBvcnRzIDwtIHBhbmVsX2Z1bGwgJT4lDQogIGdyb3VwX2J5KHpvbmUpICU+JQ0KICBzdW1tYXJpc2UoYXZnX2V4cG9ydHMgPSBtZWFuKHJlYWxfZXhwb3J0cywgbmEucm0gPSBUUlVFKSwNCiAgICAgICAgICAgIC5ncm91cHMgPSAiZHJvcCIpDQpnZ3Bsb3Qobm9ydGhfc291dGhfZXhwb3J0cywgYWVzKHggPSB6b25lLCB5ID0gYXZnX2V4cG9ydHMpKSArDQogIGdlb21fYmFyKHN0YXQgPSAiaWRlbnRpdHkiKSArDQogIGxhYnModGl0bGUgPSAiQXZlcmFnZSBFeHBvcnRzIEluZmxvd3M6IE5vcnRoIHZzIFNvdXRoIiwNCiAgICAgICB4ID0gIlJlZ2lvbiIsDQogICAgICAgeSA9ICJBdmVyYWdlIFJlYWwgRXhwb3J0cyIpICsNCiAgdGhlbWVfbWluaW1hbCgpDQoNCg0KYGBgDQoNCuKAoiBTdGF0ZXMgY2xhc3NpZmllZCBhcyDigJxOb3J0aOKAnSBoYXZlIHNpZ25pZmljYW50bHkgaGlnaGVyIGF2ZXJhZ2UgZXhwb3J0cyB0aGFuIHRob3NlIGluIHRoZSDigJxTb3V0aC7igJ0NCg0K4oCiIFRoaXMgY29uZmlybXMgdGhlIGltcG9ydGFuY2Ugb2YgZ2VvZ3JhcGhpYyBwcm94aW1pdHkgdG8gdGhlIFUuUy4gYm9yZGVyIGFuZCBpbmR1c3RyaWFsIGNvbmNlbnRyYXRpbw0KDQrigKIgTm9ydGhlcm4gc3RhdGVzIHNob3cgbXVjaCBoaWdoZXIgZXhwb3J0IHZvbHVtZXMuIFNvdXRoZXJuIHN0YXRlcyBwYXJ0aWNpcGF0ZSBsZXNzIGluIGludGVybmF0aW9uYWwgdHJhZGUuDQoNCuKAoiBHZW9ncmFwaGljIHByb3hpbWl0eSB0byB0aGUgVS5TLiBib3JkZXIgaXMgYSBpbXByb3RhbnQgZmFjdG9yLiBOb3J0aGVybiBzdGF0ZXMgYmVuZWZpdCBmcm9tIGxvd2VyIHRyYW5zcG9ydGF0aW9uIGNvc3RzIGFuZCBiZXR0ZXIgYWNjZXNzIHRvIGNyb3NzLWJvcmRlciBpbmZyYXN0cnVjdHVyZS4NCg0K4oCiIEluZHVzdHJpYWwgc3RydWN0dXJlIGlzIGRpZmZlcmVudC4gTm9ydGhlcm4gc3RhdGVzIGhhdmUgaGlnaGVyIGNvbmNlbnRyYXRpb24gaW4gbWFudWZhY3R1cmluZyBhbmQgZXhwb3J0LW9yaWVudGVkIGluZHVzdHJpZXMsIHdoaWxlIHNvdXRoZXJuIHN0YXRlcyBtb3JlIG9uIHByaW1hcnkgYWN0aXZpdGllcyBvciBzZXJ2aWNlcy4NCg0K4oCiIEZvcmVpZ24gRGlyZWN0IEludmVzdG1lbnQgaXMgbW9yZSBjb25jZW50cmF0ZWQgaW4gdGhlIE5vcnRoLiBNYW55IG11bHRpbmF0aW9uYWwgZmlybXMgYXJlIGxvY2F0ZWQgaW4gbm9ydGhlcm4gc3RhdGVzIGR1ZSB0byB0aGVpciBjb25uZWN0aW9uIHdpdGggVS5TLiBtYXJrZXRzLg0KDQrigKIgSW5mcmFzdHJ1Y3R1cmUgYW5kIGNvbm5lY3Rpdml0eSBhcmUgZ2VuZXJhbGx5IHN0cm9uZ2VyIGluIG5vcnRoZXJuIHN0YXRlcywgaW5jbHVkaW5nIGhpZ2h3YXlzLCBpbmR1c3RyaWFsIHBhcmtzLCBhbmQgY3VzdG9tcyBmYWNpbGl0aWVzLCB3aGljaCBmYWNpbGl0YXRlIGludGVybmF0aW9uYWwgdHJhZGUuDQoNCmBgYHtyfQ0KbWV4aWNvX21hcCA8LSBuZV9zdGF0ZXMoY291bnRyeSA9ICJtZXhpY28iLCByZXR1cm5jbGFzcyA9ICJzZiIpDQoNCnNldGRpZmYobWV4aWNvX21hcCRuYW1lLCBwYW5lbF9kYXRhJHN0YXRlKQ0KDQoNCmBgYA0KYGBge3J9DQptZXhpY29fbWFwIDwtIG5lX3N0YXRlcyhjb3VudHJ5ID0gIm1leGljbyIsIHJldHVybmNsYXNzID0gInNmIikNCg0Kc2V0ZGlmZihwYW5lbF9kYXRhJHN0YXRlLCBtZXhpY29fbWFwJG5hbWUpDQpgYGANCg0KYGBge3J9DQoNCnBhbmVsX2Z1bGwkc3RhdGUgPC0gZHBseXI6OnJlY29kZShwYW5lbF9mdWxsJHN0YXRlLA0KICAiQ2l1ZGFkIGRlIE1leGljbyIgPSAiRGlzdHJpdG8gRmVkZXJhbCIsDQogICJNaWNob2FjYW4iID0gIk1pY2hvYWPDoW4iLA0KICAiUXVlcmV0YXJvIiA9ICJRdWVyw6l0YXJvIiwNCiAgIk1leGljbyIgPSAiTcOpeGljbyIsDQogICJTYW4gTHVpcyBQb3Rvc2kiID0gIlNhbiBMdWlzIFBvdG9zw60iLA0KICAiWXVjYXRhbiIgPSAiWXVjYXTDoW4iLA0KICAiTnVldm8gTGVvbiIgPSAiTnVldm8gTGXDs24iDQopDQoNCmBgYA0KDQrigKIgQm9yZGVyIHN0YXRlcyBzdWNoIGFzIENoaWh1YWh1YSBhbmQgb3RoZXIgbm9ydGhlcm4gc3RhdGVzIHNob3cgaGlnaGVyIGV4cG9ydCBsZXZlbHMuDQoNCmBgYHtyfQ0KYXZnX3N0YXRlX2V4cG9ydHMgPC0gcGFuZWxfZnVsbCAlPiUNCiAgZ3JvdXBfYnkoc3RhdGUpICU+JQ0KICBzdW1tYXJpc2UoYXZnX2V4cG9ydHMgPSBtZWFuKHJlYWxfZXhwb3J0cywgbmEucm0gPSBUUlVFKSwNCiAgICAgICAgICAgIC5ncm91cHMgPSAiZHJvcCIpDQptYXBfZGF0YSA8LSBtZXhpY29fbWFwICU+JQ0KICBsZWZ0X2pvaW4oYXZnX3N0YXRlX2V4cG9ydHMsIGJ5ID0gYygibmFtZSIgPSAic3RhdGUiKSkNCmdncGxvdChtYXBfZGF0YSkgKw0KICBnZW9tX3NmKGFlcyhmaWxsID0gYXZnX2V4cG9ydHMpKSArDQogIHNjYWxlX2ZpbGxfdmlyaWRpc19jKG9wdGlvbiA9ICJtYWtvIiwgbmEudmFsdWUgPSAiZ3JleTkwIikgKw0KICBsYWJzKHRpdGxlID0gIkF2ZXJhZ2UgRXhwb3J0cyBJbmZsb3dzIGJ5IE1leGljYW4gU3RhdGUiLA0KICAgICAgIGZpbGwgPSAiQXZnIEV4cG9ydHMiKSArDQogIHRoZW1lX21pbmltYWwoKQ0KDQpgYGANCg0KIyMjIENvcnJlbGF0aW9uIGFuZCBSZWxhdGlvbnNoaXBzDQoNCmBgYHtyfQ0Kc2NhbGVfZmlsbF9ncmFkaWVudDIoDQogIGxvdyA9ICJibHVlIiwNCiAgbWlkID0gIndoaXRlIiwNCiAgaGlnaCA9ICJyZWQiLA0KICBtaWRwb2ludCA9IDAsDQogIGxpbWl0cyA9IGMoLTEsIDEpDQopDQpjb3JyX2RhdGEgPC0gcGFuZWxfZGF0YSAlPiUNCiAgc2VsZWN0KHJlYWxfZXhwb3J0cywgZXhjaGFuZ2VfcmF0ZSwgcG9wX2RlbnNpdHksIGZkaSwgYm9yZGVyX2Rpc3RhbmNlLCBscV9wcmltYXJ5LGxxX3NlY29uZGFyeSxscV90ZXJ0aWFyeSwgYXZlcmFnZV9kYWlseV9zYWxhcnksIGNyaW1lX3JhdGUsIHJlYWxfcHVibGljX2ludmVzdG1lbnRfcGMpICU+JQ0KICBkcm9wX25hKCkNCg0KY29ycl9tYXRyaXggPC0gY29yKGNvcnJfZGF0YSkNCg0KY29ycl9sb25nIDwtIGFzLmRhdGEuZnJhbWUoYXMudGFibGUoY29ycl9tYXRyaXgpKQ0KDQpnZ3Bsb3QoY29ycl9sb25nLCBhZXMoVmFyMSwgVmFyMiwgZmlsbCA9IEZyZXEpKSArDQogIGdlb21fdGlsZSgpICsNCiAgc2NhbGVfZmlsbF9ncmFkaWVudDIoDQogICAgbG93ID0gImJsdWUiLA0KICAgIG1pZCA9ICJ3aGl0ZSIsDQogICAgaGlnaCA9ICJyZWQiLA0KICAgIG1pZHBvaW50ID0gMCwNCiAgICBsaW1pdHMgPSBjKC0xLCAxKQ0KICApICsNCiAgZ2VvbV90ZXh0KGFlcyhsYWJlbCA9IHJvdW5kKEZyZXEsIDIpKSwgc2l6ZSA9IDQpICsNCiAgbGFicyh0aXRsZSA9ICJDb3JyZWxhdGlvbiBNYXRyaXgiLA0KICAgICAgIHggPSAiIiwNCiAgICAgICB5ID0gIiIsDQogICAgICAgZmlsbCA9ICJDb3JyZWxhdGlvbiIpICsNCiAgdGhlbWVfbWluaW1hbCgpICsNCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA0NSwgaGp1c3QgPSAxKSkNCg0KDQpgYGANCg0K4oCiIEV4cG9ydHMgc2hvdyBwb3NpdGl2ZSBjb3JyZWxhdGlvbiB3aXRoIEZESSBhbmQgZW1wbG95bWVudCBjb25jZW50cmF0aW9uIGluIHRoZSBzZWNvbmRhcnkgc2VjdG9yLg0KDQrigKIgVGhlcmUgaXMgYSBuZWdhdGl2ZSByZWxhdGlvbnNoaXAgYmV0d2VlbiBib3JkZXIgZGlzdGFuY2UgYW5kIGV4cG9ydHMsIG1lYW5pbmcgdGhhdCBzdGF0ZXMgY2xvc2VyIHRvIHRoZSBVLlMuIHRlbmQgdG8gZXhwb3J0IG1vcmUuDQoNCuKAoiBTb21lIHNvY2lvZWNvbm9taWMgdmFyaWFibGVzIHN1Y2ggYXMgc2FsYXJ5IGFsc28gc2hvdyBwb3NpdGl2ZSBhc3NvY2lhdGlvbiB3aXRoIGV4cG9ydHMsIHN1Z2dlc3RpbmcgdGhhdCBtb3JlIGluZHVzdHJpYWxpemVkIHN0YXRlcyBoYXZlIGhpZ2hlciBpbmNvbWUgbGV2ZWxzLg0KDQpgYGB7cn0NCmdncGxvdChwYW5lbF9mdWxsLCBhZXMoeCA9IGJvcmRlcl9kaXN0YW5jZSwgeSA9IHJlYWxfZXhwb3J0cykpICsNCiAgZ2VvbV9wb2ludChhbHBoYSA9IDAuNikgKw0KICBnZW9tX3Ntb290aChtZXRob2QgPSAibG0iLCBzZSA9IFRSVUUsIGNvbG9yID0gImJsYWNrIikgKw0KICBsYWJzKHRpdGxlID0gIkV4cG9ydHMgSW5mbG93cyB2cyBCb3JkZXIgRGlzYW5jZSIsDQogICAgICAgeCA9ICJCb3JkZXIgRGlzYW5jZSIsDQogICAgICAgeSA9ICJFeHBvcnRzIikgKw0KICB0aGVtZV9taW5pbWFsKCkNCg0KYGBgDQoNCuKAoiBUaGUgcmVncmVzc2lvbiBsaW5lIHNob3dzIGEgbmVnYXRpdmUgc2xvcGUuIFN0YXRlcyBmYXJ0aGVyIGZyb20gdGhlIGJvcmRlciB0ZW5kIHRvIGhhdmUgbG93ZXIgZXhwb3J0IGxldmVscy4NCg0KYGBge3J9DQpnZ3Bsb3QocGFuZWxfZnVsbCwgYWVzKHggPSBscV9zZWNvbmRhcnksIHkgPSByZWFsX2V4cG9ydHMpKSArDQogIGdlb21fcG9pbnQoYWxwaGEgPSAwLjYpICsNCiAgZ2VvbV9zbW9vdGgobWV0aG9kID0gImxtIiwgc2UgPSBUUlVFLCBjb2xvciA9ICJibGFjayIpICsNCiAgbGFicyh0aXRsZSA9ICJFeHBvcnRzIEluZmxvd3MgdnMgRW1wbG95bWVudCBjb25jZW50cmF0aW9uIGluIHRoZSBzZWNvbmRhcnkgc2VjdG9yIiwNCiAgICAgICB4ID0gIkVtcGxveW1lbnQgY29uY2VudHJhdGlvbiBpbiB0aGUgc2Vjb25kYXJ5IHNlY3RvciIsDQogICAgICAgeSA9ICJSZWFsIEV4cG9ydHMiKSArDQogIHRoZW1lX21pbmltYWwoKQ0KDQpgYGANCuKAoiBUaGVyZSBpcyBhIHBvc2l0aXZlIHJlbGF0aW9uc2hpcC4gU3RhdGVzIHdpdGggc3Ryb25nZXIgaW5kdXN0cmlhbCBzcGVjaWFsaXphdGlvbiBleHBvcnQgbW9yZS4NCg0KYGBge3J9DQpnZ3Bsb3QocGFuZWxfZnVsbCwgYWVzKHggPSBhdmVyYWdlX2RhaWx5X3NhbGFyeSwgeSA9IHJlYWxfZXhwb3J0cykpICsNCiAgZ2VvbV9wb2ludChhbHBoYSA9IDAuNikgKw0KICBnZW9tX3Ntb290aChtZXRob2QgPSAibG0iLCBzZSA9IFRSVUUsIGNvbG9yID0gImJsYWNrIikgKw0KICBsYWJzKHRpdGxlID0gIkV4cG9ydHMgSW5mbG93cyB2cyBBdmVyYWdlIERhaWx5IFNhbGFyeSIsDQogICAgICAgeCA9ICJBdmVyYWdlIERhaWx5IFNhbGFyeSIsDQogICAgICAgeSA9ICJSZWFsIEV4cG9ydHMiKSArDQogIHRoZW1lX21pbmltYWwoKQ0KDQpgYGANCg0K4oCiIFRoZSByZWxhdGlvbnNoaXAgYXBwZWFycyBwb3NpdGl2ZSwgc3VnZ2VzdGluZyB0aGF0IGhpZ2hlciBwcm9kdWN0aXZpdHkgYW5kIGluZHVzdHJpYWxpemF0aW9uIGFyZSBsaW5rZWQgdG8gaGlnaGVyIHdhZ2VzIGFuZCBleHBvcnRzLg0KDQojIyBIeXBvdGhlc2VzIFN0YXRlbWVudHMNCg0K4oCiIEgxOiBTdGF0ZXMgd2l0aCBoaWdoZXIgZW1wbG95bWVudCBjb25jZW50cmF0aW9uIGluIHRoZSBzZWNvbmRhcnkgKGluZHVzdHJpYWwgc3BlY2lhbGl6YXRpb24pICBhbmQgdGhpcmQgKHNlcnZpY2VzKSBzZWN0b3IgaGF2ZSBzaWduaWZpY2FudGx5IGhpZ2hlciBleHBvcnQgbGV2ZWxzLg0KDQrigKIgSDI6IEJvcmRlciBkaXN0YW5jZSBoYXMgYSBuZWdhdGl2ZSBhbmQgc2lnbmlmaWNhbnQgZWZmZWN0IG9uIGV4cG9ydHMuIFN0YXRlcyBjbG9zZXIgdG8gdGhlIFUuUy4gYm9yZGVyIGV4cG9ydCBtb3JlIHRoYW4gc3RhdGVzIGxvY2F0ZWQgZmFydGhlciBhd2F5Lg0KDQrigKIgSDM6IEhpZ2hlciBsZXZlbHMgb2YgRm9yZWlnbiBEaXJlY3QgSW52ZXN0bWVudCAoRkRJKSBwb3NpdGl2ZWx5IGFmZmVjdCBleHBvcnQgcGVyZm9ybWFuY2UgYXQgdGhlIHN0YXRlIGxldmVsLg0KDQrigKIgSDQ6IFN0YXRlcyB3aXRoIGhpZ2hlciBhdmVyYWdlIHdhZ2VzLCBhcyBhIHByb3h5IGZvciBwcm9kdWN0aXZpdHkgYW5kIGluZHVzdHJpYWwgZGV2ZWxvcG1lbnQsIHNob3cgaGlnaGVyIGV4cG9ydCBwZXJmb3JtYW5jZS4NCg0KDQojIyBNYWluIEZpbmRpbmdzDQoNCuKAoiBUb3RhbCBleHBvcnRzIHNob3cgZmx1Y3R1YXRpb25zIG92ZXIgdGltZSwgd2l0aCBpbmNyZWFzZXMgYW5kIGRlY3JlYXNlcyBmcm9tIG9uZSB5ZWFyIHRvIGFub3RoZXIuDQoNCuKAoiBOb3J0aGVybiBzdGF0ZXMgY29uc2lzdGVudGx5IHNob3cgaGlnaGVyIGV4cG9ydCBsZXZlbHMgdGhhbiBzb3V0aGVybiBzdGF0ZXMuDQoNCuKAoiBUaGUgc2NhdHRlciBwbG90IG9mIGV4cG9ydHMgdmVyc3VzIGJvcmRlciBkaXN0YW5jZSBzaG93cyBhIG5lZ2F0aXZlIHJlbGF0aW9uc2hpcC4gU3RhdGVzIGNsb3NlciB0byB0aGUgVS5TLiBib3JkZXIgdGVuZCB0byBleHBvcnQgbW9yZS4NCg0K4oCiIFRoZXJlIGlzIGEgcG9zaXRpdmUgcmVsYXRpb25zaGlwIGJldHdlZW4gZXhwb3J0cyBhbmQgZW1wbG95bWVudCBjb25jZW50cmF0aW9uIGluIHRoZSBzZWNvbmRhcnkgc2VjdG9yLiBTdGF0ZXMgd2l0aCBzdHJvbmdlciBtYW51ZmFjdHVyaW5nIGxhYm9yIHRlbmQgdG8gYWNoaWV2ZSBoaWdoZXIgZXhwb3J0IGxldmVscy4NCg0K4oCiIEV4cG9ydHMgYXJlIHBvc2l0aXZlbHkgY29ycmVsYXRlZCB3aXRoIEZESSBhbmQgYXZlcmFnZSBkYWlseSBzYWxhcnkuIFRoaXMgc3VnZ2VzdHMgdGhhdCBtb3JlIGluZHVzdHJpYWxpemVkIHN0YXRlcyBwZXJmb3JtIGJldHRlciBpbiBpbnRlcm5hdGlvbmFsIHRyYWRlLg0KDQojIE1vZGVsIERlc2lnbnMNCg0KIyMgTWFpbiBEaWZmZXJlbmNlcyBiZXR3ZWVuIGNyb3NzIOKAkyBzZWN0aW9uYWwgcmVncmVzc2lvbiBhbmFseXNpcywNCg0K4oCiIFR5cGUgb2YgZGF0YSB1c2VkDQpvIENyb3NzLXNlY3Rpb25hbDogQW5hbHl6ZXMgbWFueSBpbmRpdmlkdWFscyAocGVvcGxlLCBmaXJtcywgY291bnRyaWVzLCBldGMuKSBhdCBhIHNpbmdsZSBwb2ludCBpbiB0aW1lLg0KbyBUaW1lIHNlcmllczogQW5hbHl6ZXMgb25lIGluZGl2aWR1YWwgb3IgdmFyaWFibGUgb3ZlciBhIHBlcmlvZCBvZiB0aW1lLg0KbyBQYW5lbCBkYXRhOiBDb21iaW5lcyBib3RoOyBhbmFseXplcyBtdWx0aXBsZSBpbmRpdmlkdWFscyBhY3Jvc3MgbXVsdGlwbGUgdGltZSBwZXJpb2RzLg0KDQrigKIgRGltZW5zaW9uIG9mIGFuYWx5c2lzDQpvIENyb3NzLXNlY3Rpb25hbDogSGFzIG9ubHkgYW4gaW5kaXZpZHVhbCBkaW1lbnNpb24gKE4pLg0KbyBUaW1lIHNlcmllczogSGFzIG9ubHkgYSB0aW1lIGRpbWVuc2lvbiAoVCkuDQpvIFBhbmVsIGRhdGE6IEhhcyBib3RoIGFuIGluZGl2aWR1YWwgZGltZW5zaW9uIChOKSBhbmQgYSB0aW1lIGRpbWVuc2lvbiAoVCkgc2ltdWx0YW5lb3VzbHkuDQoNCuKAoiBUeXBlIG9mIHZhcmlhYmlsaXR5IGNhcHR1cmVkDQpvIENyb3NzLXNlY3Rpb25hbDogQ29tcGFyZXMgZGlmZmVyZW5jZXMgYmV0d2VlbiBpbmRpdmlkdWFscy4NCm8gVGltZSBzZXJpZXM6IEV4YW1pbmVzIGNoYW5nZXMgb3ZlciB0aW1lLg0KbyBQYW5lbCBkYXRhOiBBbGxvd3MgYW5hbHlzaXMgb2YgYm90aCBkaWZmZXJlbmNlcyBiZXR3ZWVuIGluZGl2aWR1YWxzIGFuZCBjaGFuZ2VzIG92ZXIgdGltZSBzaW11bHRhbmVvdXNseS4NCg0K4oCiIENvbW1vbiBzdGF0aXN0aWNhbCBpc3N1ZXMNCm8gQ3Jvc3Mtc2VjdGlvbmFsOiBNYXkgc3VmZmVyIGZyb20gaGV0ZXJvc2tlZGFzdGljaXR5Lg0KbyBUaW1lIHNlcmllczogTWF5IHN1ZmZlciBmcm9tIGF1dG9jb3JyZWxhdGlvbiBhbmQgbm9uLXN0YXRpb25hcml0eSBwcm9ibGVtcy4NCm8gUGFuZWwgZGF0YTogTWF5IGludm9sdmUgZml4ZWQgb3IgcmFuZG9tIGVmZmVjdHMsIGFzIHdlbGwgYXMgYXV0b2NvcnJlbGF0aW9uIGFuZCBoZXRlcm9za2VkYXN0aWNpdHkuDQoNCuKAoiBBbmFseXRpY2FsIGNhcGFjaXR5IGFuZCBkZXB0aA0KbyBDcm9zcy1zZWN0aW9uYWw6IFNpbXBsZXIsIGJ1dCBkb2VzIG5vdCBjYXB0dXJlIHRpbWUgZHluYW1pY3MuDQpvIFRpbWUgc2VyaWVzOiBBbGxvd3MgYW5hbHlzaXMgb2YgdHJlbmRzIGFuZCBjeWNsZXMgb3ZlciB0aW1lLg0KbyBQYW5lbCBkYXRhOiBNb3JlIGNvbXByZWhlbnNpdmUgYmVjYXVzZSBpdCBiZXR0ZXIgY29udHJvbHMgZm9yIGluZGl2aWR1YWwgaGV0ZXJvZ2VuZWl0eSBhbmQgaW1wcm92ZXMgZXN0aW1hdG9yIHByZWNpc2lvbi4NCg0KIyMgTW9kZWxzDQoNCldlIGRlZmluZWQgYSBwYW5lbCBkYXRhIG1vZGVsIHdoZXJlIHJlYWwgZXhwb3J0cyBkZXBlbmQgb24gaW5kdXN0cmlhbCBzcGVjaWFsaXphdGlvbiwgc2FsYXJpZXMsIHBvcHVsYXRpb24gZGVuc2l0eSwgYW5kIHB1YmxpYyBpbnZlc3RtZW50IHBlciBjYXBpdGEuDQoNCmBgYHtyfQ0KbW9kZWxfZm9ybXVsYSA8LSByZWFsX2V4cG9ydHMgfiBscV9zZWNvbmRhcnkgKw0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGF2ZXJhZ2VfZGFpbHlfc2FsYXJ5ICsgcG9wX2RlbnNpdHkgKyByZWFsX3B1YmxpY19pbnZlc3RtZW50X3BjDQoNCmBgYA0KDQpXZSBlc3RpbWF0ZWQgYSBwb29sZWQgbW9kZWwgdGhhdCBpZ25vcmVzIGRpZmZlcmVuY2VzIGJldHdlZW4gc3RhdGVzIGFuZCB5ZWFycy4gTW9zdCB2YXJpYWJsZXMgd2VyZSBzaWduaWZpY2FudCwgYW5kIHRoZSBtb2RlbCBleHBsYWluZWQgYWJvdXQgNjIgcGVyY2VudCBvZiBleHBvcnRzIHZhcmlhdGlvbi4NCmBgYHtyfQ0KcG9vbGluZyA8LSBwbG0obW9kZWxfZm9ybXVsYSwgZGF0YSA9IHBhbmVsX2RhdGEsIG1vZGVsID0gInBvb2xpbmciKQ0Kc3VtbWFyeShwb29saW5nKQ0KYGBgDQpUaGlzIG1vZGVsIGNvbnRyb2xzIGZvciBkaWZmZXJlbmNlcyBiZXR3ZWVuIHN0YXRlcy4gVGhlIHZhcmlhYmxlcyB3ZXJlIG5vdCBzdGF0aXN0aWNhbGx5IHNpZ25pZmljYW50LCBhbmQgdGhlIGV4cGxhbmF0b3J5IHBvd2VyIHdhcyB2ZXJ5IGxvdy4NCg0KYGBge3J9DQpmZV9pbmQgPC0gcGxtKG1vZGVsX2Zvcm11bGEsIGRhdGEgPSBwYW5lbF9kYXRhLCBtb2RlbCA9ICJ3aXRoaW4iLCBlZmZlY3QgPSAiaW5kaXZpZHVhbCIpDQpzdW1tYXJ5KGZlX2luZCkNCmBgYA0KVGhpcyBtb2RlbCBjb250cm9scyBmb3IgZGlmZmVyZW5jZXMgYmV0d2VlbiB5ZWFycy4gTW9zdCB2YXJpYWJsZXMgd2VyZSBzaWduaWZpY2FudCwgYW5kIHRoaXMgbW9kZWwgaGFkIHRoZSBoaWdoZXN0IFItc3F1YXJlZC4NCg0KYGBge3J9DQpmZV90aW1lIDwtIHBsbShtb2RlbF9mb3JtdWxhLCBkYXRhID0gcGFuZWxfZGF0YSwgbW9kZWwgPSAid2l0aGluIiwgZWZmZWN0ID0gInRpbWUiKQ0Kc3VtbWFyeShmZV90aW1lKQ0KYGBgDQpUaGlzIG1vZGVsIGNvbnRyb2xzIGZvciBib3RoIHN0YXRlIGFuZCB5ZWFyIGVmZmVjdHMuIE9ubHkgb25lIHZhcmlhYmxlIHdhcyB3ZWFrbHkgc2lnbmlmaWNhbnQsIGFuZCB0aGUgbW9kZWwgaGFkIGxvdyBleHBsYW5hdG9yeSBwb3dlci4NCg0KYGBge3J9DQpmZV90dyA8LSBwbG0obW9kZWxfZm9ybXVsYSwgZGF0YSA9IHBhbmVsX2RhdGEsIG1vZGVsID0gIndpdGhpbiIsIGVmZmVjdCA9ICJ0d293YXlzIikNCnN1bW1hcnkoZmVfdHcpDQpgYGANClRoaXMgbW9kZWwgYXNzdW1lcyB0aGF0IHN0YXRlIGRpZmZlcmVuY2VzIGFyZSBub3QgcmVsYXRlZCB0byB0aGUgaW5kZXBlbmRlbnQgdmFyaWFibGVzLiBPbmx5IG9uZSB2YXJpYWJsZSB3YXMgc2lnbmlmaWNhbnQsIGFuZCB0aGUgZml0IHdhcyB3ZWFrZXIgdGhhbiB0aGUgdGltZSBmaXhlZCBlZmZlY3RzIG1vZGVsLg0KDQpgYGB7cn0NCnJlIDwtIHBsbShtb2RlbF9mb3JtdWxhLCBkYXRhID0gcGFuZWxfZGF0YSwgbW9kZWwgPSAicmFuZG9tIikNCnN1bW1hcnkocmUpDQpgYGANCldlIHRlc3RlZCB3aGV0aGVyIGZpeGVkIGVmZmVjdHMgYXJlIG5lY2Vzc2FyeS4gVGhlIHJlc3VsdHMgc2hvd2VkIHRoYXQgYm90aCBzdGF0ZSBhbmQgdGltZSBlZmZlY3RzIGFyZSBpbXBvcnRhbnQuDQoNCmBgYHtyfQ0KcEZ0ZXN0KGZlX2luZCwgcG9vbGluZykNCnBGdGVzdChmZV90aW1lLCBwb29saW5nKQ0KcEZ0ZXN0KGZlX3R3LCBwb29saW5nKQ0KYGBgDQpUaGUgSGF1c21hbiB0ZXN0IGNvbXBhcmVkIGZpeGVkIGFuZCByYW5kb20gZWZmZWN0cy4gVGhlIHJlc3VsdCBzdWdnZXN0ZWQgdGhhdCBmaXhlZCBlZmZlY3RzIGFyZSBtb3JlIGFwcHJvcHJpYXRlLg0KDQpgYGB7cn0NCnBodGVzdChmZV90aW1lLCByZSkNCmBgYA0KV2UgY2hlY2tlZCBmb3IgbXVsdGljb2xsaW5lYXJpdHkuIEFsbCBWSUYgdmFsdWVzIHdlcmUgbG93LCBzbyB0aGVyZSBpcyBubyBzZXJpb3VzIG11bHRpY29sbGluZWFyaXR5IHByb2JsZW0uDQoNCmBgYHtyfQ0KdmlmKGxtKG1vZGVsX2Zvcm11bGEsIGRhdGEgPSBwYW5lbF9kYXRhKSkNCmBgYA0KV2UgZm91bmQgaGV0ZXJvc2tlZGFzdGljaXR5IGFuZCBzZXJpYWwgY29ycmVsYXRpb24gaW4gdGhlIGVycm9ycy4gVGhpcyBtZWFucyB3ZSBzaG91bGQgdXNlIHJvYnVzdCBzdGFuZGFyZCBlcnJvcnMuDQoNCmBgYHtyfQ0KYnB0ZXN0KGZlX3RpbWUpDQpgYGANCg0KYGBge3J9DQpwYmd0ZXN0KGZlX3RpbWUpDQpgYGANCldlIHJlLWVzdGltYXRlZCB0aGUgdGltZSBmaXhlZCBlZmZlY3RzIG1vZGVsIHVzaW5nIHJvYnVzdCBzdGFuZGFyZCBlcnJvcnMgdG8gY29ycmVjdCBmb3IgaGV0ZXJvc2tlZGFzdGljaXR5IGFuZCBzZXJpYWwgY29ycmVsYXRpb24uIEFmdGVyIHRoaXMgY29ycmVjdGlvbiwgbHFfc2Vjb25kYXJ5LCBhdmVyYWdlX2RhaWx5X3NhbGFyeSwgYW5kIHBvcF9kZW5zaXR5IHJlbWFpbmVkIHN0YXRpc3RpY2FsbHkgc2lnbmlmaWNhbnQuIEhvd2V2ZXIsIHJlYWxfcHVibGljX2ludmVzdG1lbnRfcGMgd2FzIG5vdCBzdGF0aXN0aWNhbGx5IHNpZ25pZmljYW50LiBUaGlzIGNvbmZpcm1zIHRoYXQgdGhlIG1haW4gcmVzdWx0cyBhcmUgc3RpbGwgc3Ryb25nIGV2ZW4gYWZ0ZXIgdXNpbmcgcm9idXN0IGVycm9ycy4NCg0KYGBge3J9DQpjb2VmdGVzdChmZV90aW1lLCB2Y292ID0gdmNvdkhDKGZlX3RpbWUsIG1ldGhvZCA9ICJhcmVsbGFubyIsIHR5cGUgPSAiSEMxIikpDQpgYGANCg0KIyMjIFJlc3VsdHMNCg0KYGBge3J9DQpsaWJyYXJ5KHBsbSkNCg0KbW9kZWxzIDwtIGxpc3QoDQogIFBvb2xpbmcgPSBwb29saW5nLA0KICBGRV9JbmRpdmlkdWFsID0gZmVfaW5kLA0KICBGRV9Ud29XYXlzID0gZmVfdHcsDQogIFJFID0gcmUsDQogIEZFX1RpbWUgPSBmZV90aW1lDQopDQoNCmNvbXBhcmlzb24gPC0gZGF0YS5mcmFtZSgNCiAgTW9kZWwgPSBuYW1lcyhtb2RlbHMpLA0KICBSMiA9IHNhcHBseShtb2RlbHMsIGZ1bmN0aW9uKG0pIHN1bW1hcnkobSkkci5zcXVhcmVkWyJyc3EiXSksDQogIEFkal9SMiA9IHNhcHBseShtb2RlbHMsIGZ1bmN0aW9uKG0pIHN1bW1hcnkobSkkci5zcXVhcmVkWyJhZGpyc3EiXSkNCikNCg0KY29tcGFyaXNvbg0KYGBgDQoNCkFjY29yZGluZyB0byB0aGUgdGltZSBmaXhlZCBlZmZlY3RzIG1vZGVsIHdpdGggcm9idXN0IHN0YW5kYXJkIGVycm9ycywgdGhlIG1haW4gZHJpdmVyIG9mIE1leGljb+KAmXMgZXhwb3J0cyBpbmZsb3dzIGlzIGluZHVzdHJpYWwgc3BlY2lhbGl6YXRpb24gKGxxX3NlY29uZGFyeSkuIFN0YXRlcyB3aXRoIGEgc3Ryb25nZXIgc2Vjb25kYXJ5IHNlY3RvciB0ZW5kIHRvIGhhdmUgc2lnbmlmaWNhbnRseSBoaWdoZXIgZXhwb3J0IGxldmVscy4gVGhpcyBzdWdnZXN0cyB0aGF0IG1hbnVmYWN0dXJpbmcgYW5kIGluZHVzdHJpYWwgY29uY2VudHJhdGlvbiBwbGF5IGEga2V5IHJvbGUgaW4gZXhwb3J0IHBlcmZvcm1hbmNlLg0KDQpBdmVyYWdlIGRhaWx5IHNhbGFyeSBpcyBhbHNvIHBvc2l0aXZlIGFuZCBzdGF0aXN0aWNhbGx5IHNpZ25pZmljYW50LiBUaGlzIG1heSBpbmRpY2F0ZSB0aGF0IG1vcmUgcHJvZHVjdGl2ZSBhbmQgZGV2ZWxvcGVkIHN0YXRlcywgd2hpY2ggcGF5IGhpZ2hlciB3YWdlcywgYXJlIGFsc28gbW9yZSBjb21wZXRpdGl2ZSBpbiBpbnRlcm5hdGlvbmFsIG1hcmtldHMuDQoNClBvcHVsYXRpb24gZGVuc2l0eSBoYXMgYSBuZWdhdGl2ZSBhbmQgc2lnbmlmaWNhbnQgZWZmZWN0LiBUaGlzIGNvdWxkIHN1Z2dlc3QgY29uZ2VzdGlvbiBlZmZlY3RzIG9yIHN0cnVjdHVyYWwgZGlmZmVyZW5jZXMgaW4gaGlnaGx5IHBvcHVsYXRlZCBzdGF0ZXMgdGhhdCByZWR1Y2UgZXhwb3J0IHBlcmZvcm1hbmNlLg0KDQpSZWFsIHB1YmxpYyBpbnZlc3RtZW50IHBlciBjYXBpdGEgd2FzIG5vdCBzdGF0aXN0aWNhbGx5IHNpZ25pZmljYW50IGFmdGVyIHVzaW5nIHJvYnVzdCBlcnJvcnMuIFRoZXJlZm9yZSwgcHVibGljIGludmVzdG1lbnQgZG9lcyBub3QgYXBwZWFyIHRvIGhhdmUgYSBjbGVhciBkaXJlY3QgZWZmZWN0IG9uIGV4cG9ydCBpbmZsb3dzIGluIHRoaXMgbW9kZWwuDQoNCkluIHN1bW1hcnksIHRoZSBtYWluIGRyaXZlcnMgb2YgZXhwb3J0cyBhcmUgaW5kdXN0cmlhbCBzcGVjaWFsaXphdGlvbiBhbmQgd2FnZSBsZXZlbHMsIHdoaWxlIGhpZ2ggcG9wdWxhdGlvbiBkZW5zaXR5IG1heSByZXByZXNlbnQgYSBzdHJ1Y3R1cmFsIGNoYWxsZW5nZSBmb3IgZXhwb3J0IGdyb3d0aC4NCg0KIyMjIEVsYXN0aWNpdHkNCg0KaGlzIGlzIGEgbG9nLWxvZyBtb2RlbCwgc28gdGhlIGNvZWZmaWNpZW50cyBhcmUgZWxhc3RpY2l0aWVzLg0KDQpJbmR1c3RyaWFsIHNwZWNpYWxpemF0aW9uIGhhcyBhbiBlbGFzdGljaXR5IG9mIDIuNjkgYW5kIGlzIGhpZ2hseSBzaWduaWZpY2FudC4gQSAxIHBlcmNlbnQgaW5jcmVhc2UgaW4gaW5kdXN0cmlhbCBjb25jZW50cmF0aW9uIGluY3JlYXNlcyBleHBvcnRzIGJ5IGFib3V0IDIuNyBwZXJjZW50LiBUaGlzIGlzIHRoZSBtYWluIGRyaXZlciBvZiBleHBvcnQgaW5mbG93cy4NCg0KQXZlcmFnZSBkYWlseSBzYWxhcnkgaGFzIGFuIGVsYXN0aWNpdHkgb2YgNi43NCBhbmQgaXMgYWxzbyBzaWduaWZpY2FudC4gSGlnaGVyIHdhZ2VzIGFyZSBhc3NvY2lhdGVkIHdpdGggaGlnaGVyIGV4cG9ydHMuDQoNClBvcHVsYXRpb24gZGVuc2l0eSBhbmQgcHVibGljIGludmVzdG1lbnQgYXJlIG5vdCBzdGF0aXN0aWNhbGx5IHNpZ25pZmljYW50Lg0KDQpUaGUgbW9kZWwgZXhwbGFpbnMgYWJvdXQgNjcgcGVyY2VudCBvZiBleHBvcnQgdmFyaWF0aW9uLg0KDQpgYGB7cn0NCmVsYXN0aWNpdHlfZm9ybXVsYSA8LSBsb2cocmVhbF9leHBvcnRzKSB+IGxvZyhscV9zZWNvbmRhcnkpICsNCiAgICAgICAgICAgICAgICAgICAgbG9nKGF2ZXJhZ2VfZGFpbHlfc2FsYXJ5KSArDQogICAgICAgICAgICAgICAgICAgIGxvZyhwb3BfZGVuc2l0eSkgKw0KICAgICAgICAgICAgICAgICAgICBsb2cocmVhbF9wdWJsaWNfaW52ZXN0bWVudF9wYykNCmBgYA0KDQpgYGB7cn0NCmZlX3RpbWVfZWxhc3RpY2l0eSA8LSBwbG0oDQogIGVsYXN0aWNpdHlfZm9ybXVsYSwNCiAgZGF0YSA9IHBhbmVsX2RhdGEsDQogIG1vZGVsID0gIndpdGhpbiIsDQogIGVmZmVjdCA9ICJ0aW1lIg0KKQ0KDQpzdW1tYXJ5KGZlX3RpbWVfZWxhc3RpY2l0eSkNCmBgYA0KSW5kdXN0cmlhbCBzcGVjaWFsaXphdGlvbiBpcyB0aGUgbWFpbiBkcml2ZXIgb2YgZXhwb3J0cy4gQSAxIHBlcmNlbnQgaW5jcmVhc2UgaW4gaW5kdXN0cmlhbCBjb25jZW50cmF0aW9uIGluY3JlYXNlcyBleHBvcnRzIGJ5IGFib3V0IDIuNyBwZXJjZW50LiBUaGlzIHNob3dzIHRoYXQgbWFudWZhY3R1cmluZyBzdHJlbmd0aCBpcyB2ZXJ5IGltcG9ydGFudCBmb3IgTWV4aWNv4oCZcyBleHBvcnQgaW5mbG93cy4NCg0KQXZlcmFnZSBkYWlseSBzYWxhcnkgYWxzbyBoYXMgYSBzdHJvbmcgcG9zaXRpdmUgZWZmZWN0LiBBIDEgcGVyY2VudCBpbmNyZWFzZSBpbiB3YWdlcyBpbmNyZWFzZXMgZXhwb3J0cyBieSBhYm91dCA2LjcgcGVyY2VudC4gVGhpcyBzdWdnZXN0cyB0aGF0IG1vcmUgcHJvZHVjdGl2ZSBhbmQgZGV2ZWxvcGVkIHN0YXRlcyBleHBvcnQgbW9yZS4NCg0KUG9wdWxhdGlvbiBkZW5zaXR5IGFuZCBwdWJsaWMgaW52ZXN0bWVudCBhcmUgbm90IHN0YXRpc3RpY2FsbHkgc2lnbmlmaWNhbnQsIHNvIHRoZXkgZG8gbm90IHNob3cgYSBjbGVhciBpbXBhY3Qgb24gZXhwb3J0IGluZmxvd3MgaW4gdGhpcyBtb2RlbC4NCg==