Introduction

To understand the dynamics of the U.S. economy, it is essential to consider both national and localized perspectives. This analysis develops a diffusion index by incorporating employment, industrial production, and consumer sentiment data. The resulting index is then compared with the Chicago Fed National Activity Diffusion Index (CFNAIDIFF), offering valuable insights into patterns of economic growth and contraction over time.

Data selection and Diffusion Index Construction.

The diffusion index reflects economic expansion and contraction based on pulling data for three selected variables. Here selected variables are Employment, industrial production, and housing starts.

suppressWarnings({
  suppressPackageStartupMessages({
    library(tidyverse)
    library(quantmod)
    library(tsbox)
    library(zoo)
  })
})

options(digits = 3, scipen = 99999)
graphics.off()
# Load economic variables
getSymbols(c("PAYEMS", "INDPRO", "HOUST"),
           src = "FRED", return.class = 'xts', 
           from = "2010-01-01", to = Sys.Date())
[1] "PAYEMS" "INDPRO" "HOUST" 

Comparison of Custom Diffusion Index and CFNAIDIFF

# Data preprocessing
employment <- PAYEMS
industrial_production <- INDPRO
housing  <- HOUST

employment_ss <- employment["2010-01-31/2024-09-01"] |> ts_ts()
industrial_ss <- industrial_production["2010-01-31/2024-09-01"] |> ts_ts()
housing_ss <- housing["2010-01-31/2024-09-01"] |> ts_ts()

mydata <- cbind.data.frame(employment_ss, industrial_ss, housing_ss)

mydf <- mydata %>%
  mutate(
    emp_diff = tsibble::difference(employment_ss, differences = 1),
    ind_diff = tsibble::difference(industrial_ss, differences = 1),
    house_diff = tsibble::difference(housing_ss, differences = 1)
  ) %>%
  dplyr::select(emp_diff, ind_diff, house_diff) %>%
  na.omit()

Visual Observations (First Plot):

# Construct diffusion index
mydf_mat <- apply(mydf, 2, sign)
pos <- apply(mydf_mat, 1, function(row) sum(row > 0))
neg <- apply(mydf_mat, 1, function(row) sum(row < 0))
tot <- pos + neg
index <- (pos / tot - neg / tot) * 100
ma_index <- rollmean(index, 7, align = "right", na.pad = TRUE)

Date <- seq.Date(from = as.Date("2010-05-01"), length.out = length(index), by = "month")
diffusion_df <- cbind.data.frame(Date, index, ma_index)

ggplot(diffusion_df, aes(x = Date, y = index)) +
  # Line for the diffusion index
  geom_line(color = "navyblue", size = 0.8) +
  # Smoothed trend line with transparency
  geom_smooth(color = "red", fill = "lightblue", alpha = 0.3, size = 1.2) +
  # Adding labels to key points
  geom_text(data = diffusion_df[c(1, nrow(diffusion_df)), ],
            aes(label = paste0(round(index, 2), "%")), 
            vjust = -1, size = 3.5, fontface = "bold", color = "darkred") +
  # Adding a horizontal reference line
  geom_hline(yintercept = 0, linetype = "dashed", color = "black", size = 0.8) +
  # Vertical line for a key event (e.g., COVID-19)
  geom_vline(xintercept = as.Date("2020-03-01"), linetype = "dotted", color = "darkgreen", size = 1) +
  annotate("text", x = as.Date("2020-03-01"), y = -90, 
           label = "COVID-19", color = "darkgreen", size = 4, hjust = 0, angle = 90) +
  # Title, subtitle, and axis labels
  labs(
    title = "U.S. Economic Diffusion Index Over Time",
    subtitle = "Analyzing economic trends",
    x = "Year",
    y = "Diffusion Index (%)"
  ) +
  # Adjust y-axis limits to zoom out
  scale_y_continuous(limits = c(-120, 120)) +
  # Enhance visual appearance with themes
  theme_minimal(base_size = 14) +
  theme(
    plot.title = element_text(size = 20, face = "bold", hjust = 0.5, color = "darkblue"),
    plot.subtitle = element_text(size = 14, face = "italic", hjust = 0.5, color = "blue"),
    axis.title.x = element_text(size = 14, face = "bold", color = "black"),
    axis.title.y = element_text(size = 14, face = "bold", color = "black"),
    axis.text = element_text(size = 12, color = "black"),
    panel.grid.major = element_line(color = "gray85", size = 0.5),
    panel.grid.minor = element_blank(),
    legend.position = "none",
    plot.background = element_rect(fill = "white", color = "white")
  )

Long-Term Trend in Diffusion Index

# Load CFNAIDIFF
getSymbols("CFNAIDIFF", src = "FRED", return.class = 'xts', from = "2010-01-01")
[1] "CFNAIDIFF"
cfnaidiff_ss <- CFNAIDIFF["2010-05-01/2024-09-01"] |> ts_ts()
min_length <- min(length(ma_index), length(cfnaidiff_ss))
ma_index <- ma_index[1:min_length]
cfnaidiff_ss <- cfnaidiff_ss[1:min_length]
Date <- Date[1:min_length]

# Prepare the comparison data frame
compare_df <- cbind.data.frame(Date, diffusion_index = ma_index, CFNAIDIFF = cfnaidiff_ss)

correlation <- cor(compare_df$diffusion_index, compare_df$CFNAIDIFF, use = "complete.obs")

# Enhanced comparison plot with interactivity
plotly::ggplotly(
  ggplot() +
    geom_line(data = compare_df, aes(x = Date, y = diffusion_index, color = "Diffusion Index"), size = 1.2) +
    geom_line(data = compare_df, aes(x = Date, y = CFNAIDIFF * 100, color = "CFNAIDIFF"), size = 1.2, linetype = "dashed") +
    scale_color_manual(
      values = c("Diffusion Index" = "navy", "CFNAIDIFF" = "red")
    ) +
    labs(
      title = "Comparison of Diffusion Index and CFNAIDIFF",
      x = "Year",
      y = "Index Value",
      color = "Legend"
    ) +
    theme_minimal(base_size = 8) +
    theme(
      plot.title = element_text(size = 10, face = "bold", hjust = 0.5),
      legend.position = "bottom"
    )
)
NA
NA

Key Economic Insights

Recent Economic Conditions (Post-September 2024)

Conclusion

The Diffusion Index reflects notable economic fluctuations over time, with recent declines driven by drops in employment, industrial production, and consumer sentiment. In contrast, CFNAIDIFF shows steadier national activity, with less volatility compared to the Diffusion Index. The weak correlation of 0.157 highlights the differences in their focus: the Diffusion Index is more sensitive to localized economic changes, while CFNAIDIFF captures broader national trends. The outlook suggests that the Diffusion Index indicates regional or sectoral weaknesses, whereas CFNAIDIFF points to a stable national economy without widespread contraction.

LS0tDQp0aXRsZTogIkNoaWNhZ28gRmVkIE5hdGlvbmFsIEFjdGl2aXR5IEluZGV4OiBEaWZmdXNpb24gSW5kZXggKENGTkFJRElGRikgQ29tcGFyaXNvbiINCm91dHB1dDogaHRtbF9ub3RlYm9vaw0KLS0tDQoNCi0gICAqKkNsYXNzOiBFQ09OIDY2MzUtMDEqKg0KDQotICAgKipTY2hvb2w6IFBvbXBlYSBDb2xsZWdlIG9mIEJ1c2luZXNzKioNCg0KLSAgICoqVW5pdmVyc2l0eTogVW5pdmVyc2l0eSBvZiBOZXcgSGF2ZW4qKg0KDQotICAgKipBdXRob3I6IFNhaSBSYWh1bCBDaGlycmEqKg0KDQojIyMgKipJbnRyb2R1Y3Rpb24qKg0KDQpUbyB1bmRlcnN0YW5kIHRoZSBkeW5hbWljcyBvZiB0aGUgVS5TLiBlY29ub215LCBpdCBpcyBlc3NlbnRpYWwgdG8gY29uc2lkZXIgYm90aCBuYXRpb25hbCBhbmQgbG9jYWxpemVkIHBlcnNwZWN0aXZlcy4gVGhpcyBhbmFseXNpcyBkZXZlbG9wcyBhIGRpZmZ1c2lvbiBpbmRleCBieSBpbmNvcnBvcmF0aW5nIGVtcGxveW1lbnQsIGluZHVzdHJpYWwgcHJvZHVjdGlvbiwgYW5kIGNvbnN1bWVyIHNlbnRpbWVudCBkYXRhLiBUaGUgcmVzdWx0aW5nIGluZGV4IGlzIHRoZW4gY29tcGFyZWQgd2l0aCB0aGUgQ2hpY2FnbyBGZWQgTmF0aW9uYWwgQWN0aXZpdHkgRGlmZnVzaW9uIEluZGV4IChDRk5BSURJRkYpLCBvZmZlcmluZyB2YWx1YWJsZSBpbnNpZ2h0cyBpbnRvIHBhdHRlcm5zIG9mIGVjb25vbWljIGdyb3d0aCBhbmQgY29udHJhY3Rpb24gb3ZlciB0aW1lLg0KDQojIyMgKipEYXRhIHNlbGVjdGlvbiBhbmQgRGlmZnVzaW9uIEluZGV4IENvbnN0cnVjdGlvbi4qKg0KDQpUaGUgZGlmZnVzaW9uIGluZGV4IHJlZmxlY3RzIGVjb25vbWljIGV4cGFuc2lvbiBhbmQgY29udHJhY3Rpb24gYmFzZWQgb24gcHVsbGluZyBkYXRhIGZvciB0aHJlZSBzZWxlY3RlZCB2YXJpYWJsZXMuIEhlcmUgc2VsZWN0ZWQgdmFyaWFibGVzIGFyZSBFbXBsb3ltZW50LCBpbmR1c3RyaWFsIHByb2R1Y3Rpb24sIGFuZCBob3VzaW5nIHN0YXJ0cy4NCg0KYGBge3J9DQpzdXBwcmVzc1dhcm5pbmdzKHsNCiAgc3VwcHJlc3NQYWNrYWdlU3RhcnR1cE1lc3NhZ2VzKHsNCiAgICBsaWJyYXJ5KHRpZHl2ZXJzZSkNCiAgICBsaWJyYXJ5KHF1YW50bW9kKQ0KICAgIGxpYnJhcnkodHNib3gpDQogICAgbGlicmFyeSh6b28pDQogIH0pDQp9KQ0KDQpvcHRpb25zKGRpZ2l0cyA9IDMsIHNjaXBlbiA9IDk5OTk5KQ0KZ3JhcGhpY3Mub2ZmKCkNCmBgYA0KDQpgYGB7cn0NCiMgTG9hZCBlY29ub21pYyB2YXJpYWJsZXMNCmdldFN5bWJvbHMoYygiUEFZRU1TIiwgIklORFBSTyIsICJIT1VTVCIpLA0KICAgICAgICAgICBzcmMgPSAiRlJFRCIsIHJldHVybi5jbGFzcyA9ICd4dHMnLCANCiAgICAgICAgICAgZnJvbSA9ICIyMDEwLTAxLTAxIiwgdG8gPSBTeXMuRGF0ZSgpKQ0KDQpgYGANCg0KIyMjICoqQ29tcGFyaXNvbiBvZiBDdXN0b20gRGlmZnVzaW9uIEluZGV4IGFuZCBDRk5BSURJRkYqKg0KDQotICAgKipDb3JyZWxhdGlvbiBDb2VmZmljaWVudCoqOg0KDQogICAgLSAgIFRoZSBjb3JyZWxhdGlvbiBiZXR3ZWVuIHlvdXIgY3VzdG9tIERpZmZ1c2lvbiBJbmRleCBhbmQgdGhlIENoaWNhZ28gRmVkIE5hdGlvbmFsIEFjdGl2aXR5IERpZmZ1c2lvbiBJbmRleCAoQ0ZOQUlESUZGKSBpbmRpY2F0ZXMgdGhlIGV4dGVudCB0byB3aGljaCB0aGUgdHdvIHNlcmllcyBtb3ZlIHRvZ2V0aGVyLg0KDQogICAgLSAgIEEgc3Ryb25nIHBvc2l0aXZlIGNvcnJlbGF0aW9uIChjbG9zZSB0byAxKSB3b3VsZCBpbXBseSB0aGF0IHlvdXIgaW5kZXggaXMgZWZmZWN0aXZlbHkgY2FwdHVyaW5nIHRoZSBzYW1lIGVjb25vbWljIGR5bmFtaWNzIGFzIENGTkFJRElGRi4NCg0KICAgIC0gICBGb3IgZXhhbXBsZSwgaWYgdGhlIGNvcnJlbGF0aW9uIGlzICoqMC44IG9yIGhpZ2hlcioqLCBpdCBzdWdnZXN0cyB0aGF0IHlvdXIgaW5kZXggaXMgYSBnb29kIHByb3h5IGZvciBDRk5BSURJRkYsIHJlZmxlY3Rpbmcgc2ltaWxhciBlY29ub21pYyB0cmVuZHMgb3ZlciB0aGUgYW5hbHl6ZWQgcGVyaW9kLg0KDQpgYGB7cn0NCiMgRGF0YSBwcmVwcm9jZXNzaW5nDQplbXBsb3ltZW50IDwtIFBBWUVNUw0KaW5kdXN0cmlhbF9wcm9kdWN0aW9uIDwtIElORFBSTw0KaG91c2luZyAgPC0gSE9VU1QNCg0KZW1wbG95bWVudF9zcyA8LSBlbXBsb3ltZW50WyIyMDEwLTAxLTMxLzIwMjQtMDktMDEiXSB8PiB0c190cygpDQppbmR1c3RyaWFsX3NzIDwtIGluZHVzdHJpYWxfcHJvZHVjdGlvblsiMjAxMC0wMS0zMS8yMDI0LTA5LTAxIl0gfD4gdHNfdHMoKQ0KaG91c2luZ19zcyA8LSBob3VzaW5nWyIyMDEwLTAxLTMxLzIwMjQtMDktMDEiXSB8PiB0c190cygpDQoNCm15ZGF0YSA8LSBjYmluZC5kYXRhLmZyYW1lKGVtcGxveW1lbnRfc3MsIGluZHVzdHJpYWxfc3MsIGhvdXNpbmdfc3MpDQoNCm15ZGYgPC0gbXlkYXRhICU+JQ0KICBtdXRhdGUoDQogICAgZW1wX2RpZmYgPSB0c2liYmxlOjpkaWZmZXJlbmNlKGVtcGxveW1lbnRfc3MsIGRpZmZlcmVuY2VzID0gMSksDQogICAgaW5kX2RpZmYgPSB0c2liYmxlOjpkaWZmZXJlbmNlKGluZHVzdHJpYWxfc3MsIGRpZmZlcmVuY2VzID0gMSksDQogICAgaG91c2VfZGlmZiA9IHRzaWJibGU6OmRpZmZlcmVuY2UoaG91c2luZ19zcywgZGlmZmVyZW5jZXMgPSAxKQ0KICApICU+JQ0KICBkcGx5cjo6c2VsZWN0KGVtcF9kaWZmLCBpbmRfZGlmZiwgaG91c2VfZGlmZikgJT4lDQogIG5hLm9taXQoKQ0KYGBgDQoNCiMjIyAqKlZpc3VhbCBPYnNlcnZhdGlvbnMgKEZpcnN0IFBsb3QpKio6DQoNCi0gICAqKkdlbmVyYWwgQWxpZ25tZW50Kio6IFRoZXJlIGFyZSBwZXJpb2RzIHdoZXJlIHRoZSB0cmVuZHMgb2YgdGhlIGN1c3RvbSBEaWZmdXNpb24gSW5kZXggYW5kIENGTkFJRElGRiBhbGlnbiBjbG9zZWx5LiBUaGlzIHN1Z2dlc3RzIHRoYXQgeW91ciBtZXRob2RvbG9neSBmb3IgY29uc3RydWN0aW5nIHRoZSBpbmRleCBpcyBjYXB0dXJpbmcga2V5IGFzcGVjdHMgb2YgZWNvbm9taWMgYWN0aXZpdHksIHBhcnRpY3VsYXJseSBpbiB0aW1lcyBvZiBlY29ub21pYyBncm93dGggb3IgZGVjbGluZS4NCg0KLSAgICoqRGl2ZXJnZW5jZSBQZXJpb2RzKio6IEF0IGNlcnRhaW4gcG9pbnRzLCB0aGUgaW5kaWNlcyBkZXZpYXRlIGZyb20gZWFjaCBvdGhlciAoZS5nLiwgdGhlIGJsdWUgbGluZSBtb3ZlcyBzaWduaWZpY2FudGx5IGFib3ZlIG9yIGJlbG93IHRoZSBvcmFuZ2UgbGluZSkuIFRoZXNlIGRpdmVyZ2VuY2VzIGNvdWxkIHJlc3VsdCBmcm9tIGRpZmZlcmVuY2VzIGluIHRoZSB2YXJpYWJsZXMgaW5jbHVkZWQgaW4geW91ciBpbmRleCB2ZXJzdXMgdGhvc2UgaW4gQ0ZOQUlESUZGLCBzdWNoIGFzOg0KDQogICAgLSAgIENGTkFJRElGRiB1c2VzIGEgYnJvYWRlciByYW5nZSBvZiB2YXJpYWJsZXMgYmV5b25kIGVtcGxveW1lbnQsIGluZHVzdHJpYWwgcHJvZHVjdGlvbiwgYW5kIGNvbnN1bWVyIHNlbnRpbWVudC4NCg0KICAgIC0gICBZb3VyIGluZGV4IG1heSBoYXZlIHNwZWNpZmljIHNlbnNpdGl2aXRpZXMsIHN1Y2ggYXMgYmVpbmcgbW9yZSBpbmZsdWVuY2VkIGJ5IGVtcGxveW1lbnQgb3IgaG91c2luZyBkYXRhLg0KDQotICAgKipQb3N0LVNlcHRlbWJlciBPYnNlcnZhdGlvbnMqKjoNCg0KICAgIC0gICBTaW5jZSBDRk5BSURJRkYgZGF0YSBlbmRzIGluIFNlcHRlbWJlciAyMDI0LCB5b3VyIGN1c3RvbSBpbmRleCBwcm92aWRlcyB2YWx1YWJsZSBpbnNpZ2h0cyBpbnRvIHJlY2VudCBlY29ub21pYyBhY3Rpdml0eS4NCg0KICAgIC0gICBJZiB5b3VyIGluZGV4IHNob3dzIGEgZGVjbGluZSBhZnRlciBTZXB0ZW1iZXIsIGl0IGNvdWxkIGluZGljYXRlIGEgd2Vha2VuaW5nIGVjb25vbXksIHdoaWxlIHN0YWJpbGl0eSBvciBncm93dGggd291bGQgc3VnZ2VzdCByZXNpbGllbmNlLg0KDQpgYGB7cn0NCiMgQ29uc3RydWN0IGRpZmZ1c2lvbiBpbmRleA0KbXlkZl9tYXQgPC0gYXBwbHkobXlkZiwgMiwgc2lnbikNCnBvcyA8LSBhcHBseShteWRmX21hdCwgMSwgZnVuY3Rpb24ocm93KSBzdW0ocm93ID4gMCkpDQpuZWcgPC0gYXBwbHkobXlkZl9tYXQsIDEsIGZ1bmN0aW9uKHJvdykgc3VtKHJvdyA8IDApKQ0KdG90IDwtIHBvcyArIG5lZw0KaW5kZXggPC0gKHBvcyAvIHRvdCAtIG5lZyAvIHRvdCkgKiAxMDANCm1hX2luZGV4IDwtIHJvbGxtZWFuKGluZGV4LCA3LCBhbGlnbiA9ICJyaWdodCIsIG5hLnBhZCA9IFRSVUUpDQoNCkRhdGUgPC0gc2VxLkRhdGUoZnJvbSA9IGFzLkRhdGUoIjIwMTAtMDUtMDEiKSwgbGVuZ3RoLm91dCA9IGxlbmd0aChpbmRleCksIGJ5ID0gIm1vbnRoIikNCmRpZmZ1c2lvbl9kZiA8LSBjYmluZC5kYXRhLmZyYW1lKERhdGUsIGluZGV4LCBtYV9pbmRleCkNCg0KZ2dwbG90KGRpZmZ1c2lvbl9kZiwgYWVzKHggPSBEYXRlLCB5ID0gaW5kZXgpKSArDQogICMgTGluZSBmb3IgdGhlIGRpZmZ1c2lvbiBpbmRleA0KICBnZW9tX2xpbmUoY29sb3IgPSAibmF2eWJsdWUiLCBzaXplID0gMC44KSArDQogICMgU21vb3RoZWQgdHJlbmQgbGluZSB3aXRoIHRyYW5zcGFyZW5jeQ0KICBnZW9tX3Ntb290aChjb2xvciA9ICJyZWQiLCBmaWxsID0gImxpZ2h0Ymx1ZSIsIGFscGhhID0gMC4zLCBzaXplID0gMS4yKSArDQogICMgQWRkaW5nIGxhYmVscyB0byBrZXkgcG9pbnRzDQogIGdlb21fdGV4dChkYXRhID0gZGlmZnVzaW9uX2RmW2MoMSwgbnJvdyhkaWZmdXNpb25fZGYpKSwgXSwNCiAgICAgICAgICAgIGFlcyhsYWJlbCA9IHBhc3RlMChyb3VuZChpbmRleCwgMiksICIlIikpLCANCiAgICAgICAgICAgIHZqdXN0ID0gLTEsIHNpemUgPSAzLjUsIGZvbnRmYWNlID0gImJvbGQiLCBjb2xvciA9ICJkYXJrcmVkIikgKw0KICAjIEFkZGluZyBhIGhvcml6b250YWwgcmVmZXJlbmNlIGxpbmUNCiAgZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0gMCwgbGluZXR5cGUgPSAiZGFzaGVkIiwgY29sb3IgPSAiYmxhY2siLCBzaXplID0gMC44KSArDQogICMgVmVydGljYWwgbGluZSBmb3IgYSBrZXkgZXZlbnQgKGUuZy4sIENPVklELTE5KQ0KICBnZW9tX3ZsaW5lKHhpbnRlcmNlcHQgPSBhcy5EYXRlKCIyMDIwLTAzLTAxIiksIGxpbmV0eXBlID0gImRvdHRlZCIsIGNvbG9yID0gImRhcmtncmVlbiIsIHNpemUgPSAxKSArDQogIGFubm90YXRlKCJ0ZXh0IiwgeCA9IGFzLkRhdGUoIjIwMjAtMDMtMDEiKSwgeSA9IC05MCwgDQogICAgICAgICAgIGxhYmVsID0gIkNPVklELTE5IiwgY29sb3IgPSAiZGFya2dyZWVuIiwgc2l6ZSA9IDQsIGhqdXN0ID0gMCwgYW5nbGUgPSA5MCkgKw0KICAjIFRpdGxlLCBzdWJ0aXRsZSwgYW5kIGF4aXMgbGFiZWxzDQogIGxhYnMoDQogICAgdGl0bGUgPSAiVS5TLiBFY29ub21pYyBEaWZmdXNpb24gSW5kZXggT3ZlciBUaW1lIiwNCiAgICBzdWJ0aXRsZSA9ICJBbmFseXppbmcgZWNvbm9taWMgdHJlbmRzIiwNCiAgICB4ID0gIlllYXIiLA0KICAgIHkgPSAiRGlmZnVzaW9uIEluZGV4ICglKSINCiAgKSArDQogICMgQWRqdXN0IHktYXhpcyBsaW1pdHMgdG8gem9vbSBvdXQNCiAgc2NhbGVfeV9jb250aW51b3VzKGxpbWl0cyA9IGMoLTEyMCwgMTIwKSkgKw0KICAjIEVuaGFuY2UgdmlzdWFsIGFwcGVhcmFuY2Ugd2l0aCB0aGVtZXMNCiAgdGhlbWVfbWluaW1hbChiYXNlX3NpemUgPSAxNCkgKw0KICB0aGVtZSgNCiAgICBwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAyMCwgZmFjZSA9ICJib2xkIiwgaGp1c3QgPSAwLjUsIGNvbG9yID0gImRhcmtibHVlIiksDQogICAgcGxvdC5zdWJ0aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTQsIGZhY2UgPSAiaXRhbGljIiwgaGp1c3QgPSAwLjUsIGNvbG9yID0gImJsdWUiKSwNCiAgICBheGlzLnRpdGxlLnggPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE0LCBmYWNlID0gImJvbGQiLCBjb2xvciA9ICJibGFjayIpLA0KICAgIGF4aXMudGl0bGUueSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTQsIGZhY2UgPSAiYm9sZCIsIGNvbG9yID0gImJsYWNrIiksDQogICAgYXhpcy50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMiwgY29sb3IgPSAiYmxhY2siKSwNCiAgICBwYW5lbC5ncmlkLm1ham9yID0gZWxlbWVudF9saW5lKGNvbG9yID0gImdyYXk4NSIsIHNpemUgPSAwLjUpLA0KICAgIHBhbmVsLmdyaWQubWlub3IgPSBlbGVtZW50X2JsYW5rKCksDQogICAgbGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiLA0KICAgIHBsb3QuYmFja2dyb3VuZCA9IGVsZW1lbnRfcmVjdChmaWxsID0gIndoaXRlIiwgY29sb3IgPSAid2hpdGUiKQ0KICApDQpgYGANCg0KIyMjICoqTG9uZy1UZXJtIFRyZW5kIGluIERpZmZ1c2lvbiBJbmRleCoqDQoNCi0gICAqKlZpc3VhbCBPYnNlcnZhdGlvbnMgKFNlY29uZCBQbG90KSoqOg0KDQogICAgLSAgICoqT3ZlcmFsbCBUcmVuZCoqOiBUaGVyZSBpcyBhIHNsaWdodCBsb25nLXRlcm0gZGVjbGluZSBpbiB0aGUgY3VzdG9tIERpZmZ1c2lvbiBJbmRleCAoaW5kaWNhdGVkIGJ5IHRoZSByZWQgc21vb3RoZWQgbGluZSksIHN1Z2dlc3RpbmcgYSBncmFkdWFsIHdlYWtlbmluZyBpbiBlY29ub21pYyBhY3Rpdml0eSBvdmVyIHRoZSBsYXN0IGRlY2FkZS4gVGhpcyBjb3VsZCByZWZsZWN0IHN0cnVjdHVyYWwgY2hhbGxlbmdlcyBpbiB0aGUgZWNvbm9teSwgc3VjaCBhcyBzbG93aW5nIGdyb3d0aCBpbiBrZXkgc2VjdG9ycy4NCg0KICAgIC0gICAqKkNPVklELTE5IEltcGFjdCoqOiBUaGUgc2hhcnAgZHJvcCBpbiB0aGUgaW5kZXggYXJvdW5kIE1hcmNoIDIwMjAgY29ycmVzcG9uZHMgdG8gdGhlIG9uc2V0IG9mIHRoZSBDT1ZJRC0xOSBwYW5kZW1pYy4gVGhpcyBlbXBoYXNpemVzIHRoZSBpbmRleOKAmXMgc2Vuc2l0aXZpdHkgdG8gbWFqb3IgZWNvbm9taWMgZGlzcnVwdGlvbnMuDQoNCiAgICAtICAgKipSZWNvdmVyeSBhbmQgUGxhdGVhdSoqOiBQb3N0LTIwMjAsIHRoZSBpbmRleCBhcHBlYXJzIHRvIHJlY292ZXIgYnV0IHN0YWJpbGl6ZXMgYXQgYSBsb3dlciBsZXZlbCBjb21wYXJlZCB0byB0aGUgcHJlLXBhbmRlbWljIHBlcmlvZC4gVGhpcyBjb3VsZCBpbmRpY2F0ZSBhIHNsb3dlciByZWNvdmVyeSBvciBhIG5ldyAibm9ybWFsIiBmb3IgdGhlIGVjb25vbXkuDQoNCi0gICAqKlNob3J0LVRlcm0gT2JzZXJ2YXRpb25zKio6DQoNCiAgICAtICAgVGhlIGluZGV4IHNob3dzIHBlcmlvZGljIGZsdWN0dWF0aW9ucywgd2hpY2ggY291bGQgcmVmbGVjdCB0aGUgY3ljbGljYWwgbmF0dXJlIG9mIHRoZSBlY29ub215LiBGb3IgZXhhbXBsZSwgcmVndWxhciBwZWFrcyBhbmQgdHJvdWdocyBtaWdodCBhbGlnbiB3aXRoIGJ1c2luZXNzIGN5Y2xlcyBvciBzZWFzb25hbCBwYXR0ZXJucyBpbiBlbXBsb3ltZW50IGFuZCBpbmR1c3RyaWFsIHByb2R1Y3Rpb24uDQoNCiAgICAtICAgVGhlIHNoYWRlZCBsaWdodCBibHVlIGFyZWEgKGNvbmZpZGVuY2UgYmFuZCBmb3IgdGhlIHRyZW5kIGxpbmUpIHN1Z2dlc3RzIHNvbWUgdmFyaWFiaWxpdHkgYnV0IGFsc28gcHJvdmlkZXMgYSBjbGVhciBjZW50cmFsIHRyYWplY3RvcnkgZm9yIHRoZSBlY29ub2154oCZcyBwZXJmb3JtYW5jZS4NCg0KYGBge3J9DQojIExvYWQgQ0ZOQUlESUZGDQpnZXRTeW1ib2xzKCJDRk5BSURJRkYiLCBzcmMgPSAiRlJFRCIsIHJldHVybi5jbGFzcyA9ICd4dHMnLCBmcm9tID0gIjIwMTAtMDEtMDEiKQ0KDQpjZm5haWRpZmZfc3MgPC0gQ0ZOQUlESUZGWyIyMDEwLTA1LTAxLzIwMjQtMDktMDEiXSB8PiB0c190cygpDQptaW5fbGVuZ3RoIDwtIG1pbihsZW5ndGgobWFfaW5kZXgpLCBsZW5ndGgoY2ZuYWlkaWZmX3NzKSkNCm1hX2luZGV4IDwtIG1hX2luZGV4WzE6bWluX2xlbmd0aF0NCmNmbmFpZGlmZl9zcyA8LSBjZm5haWRpZmZfc3NbMTptaW5fbGVuZ3RoXQ0KRGF0ZSA8LSBEYXRlWzE6bWluX2xlbmd0aF0NCg0KIyBQcmVwYXJlIHRoZSBjb21wYXJpc29uIGRhdGEgZnJhbWUNCmNvbXBhcmVfZGYgPC0gY2JpbmQuZGF0YS5mcmFtZShEYXRlLCBkaWZmdXNpb25faW5kZXggPSBtYV9pbmRleCwgQ0ZOQUlESUZGID0gY2ZuYWlkaWZmX3NzKQ0KDQpjb3JyZWxhdGlvbiA8LSBjb3IoY29tcGFyZV9kZiRkaWZmdXNpb25faW5kZXgsIGNvbXBhcmVfZGYkQ0ZOQUlESUZGLCB1c2UgPSAiY29tcGxldGUub2JzIikNCg0KIyBFbmhhbmNlZCBjb21wYXJpc29uIHBsb3Qgd2l0aCBpbnRlcmFjdGl2aXR5DQpwbG90bHk6OmdncGxvdGx5KA0KICBnZ3Bsb3QoKSArDQogICAgZ2VvbV9saW5lKGRhdGEgPSBjb21wYXJlX2RmLCBhZXMoeCA9IERhdGUsIHkgPSBkaWZmdXNpb25faW5kZXgsIGNvbG9yID0gIkRpZmZ1c2lvbiBJbmRleCIpLCBzaXplID0gMS4yKSArDQogICAgZ2VvbV9saW5lKGRhdGEgPSBjb21wYXJlX2RmLCBhZXMoeCA9IERhdGUsIHkgPSBDRk5BSURJRkYgKiAxMDAsIGNvbG9yID0gIkNGTkFJRElGRiIpLCBzaXplID0gMS4yLCBsaW5ldHlwZSA9ICJkYXNoZWQiKSArDQogICAgc2NhbGVfY29sb3JfbWFudWFsKA0KICAgICAgdmFsdWVzID0gYygiRGlmZnVzaW9uIEluZGV4IiA9ICJuYXZ5IiwgIkNGTkFJRElGRiIgPSAicmVkIikNCiAgICApICsNCiAgICBsYWJzKA0KICAgICAgdGl0bGUgPSAiQ29tcGFyaXNvbiBvZiBEaWZmdXNpb24gSW5kZXggYW5kIENGTkFJRElGRiIsDQogICAgICB4ID0gIlllYXIiLA0KICAgICAgeSA9ICJJbmRleCBWYWx1ZSIsDQogICAgICBjb2xvciA9ICJMZWdlbmQiDQogICAgKSArDQogICAgdGhlbWVfbWluaW1hbChiYXNlX3NpemUgPSA4KSArDQogICAgdGhlbWUoDQogICAgICBwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMCwgZmFjZSA9ICJib2xkIiwgaGp1c3QgPSAwLjUpLA0KICAgICAgbGVnZW5kLnBvc2l0aW9uID0gImJvdHRvbSINCiAgICApDQopDQoNCg0KYGBgDQoNCiMjIyAqKktleSBFY29ub21pYyBJbnNpZ2h0cyoqDQoNCi0gICAqKlN0cmVuZ3RocyBvZiB0aGUgQ3VzdG9tIERpZmZ1c2lvbiBJbmRleCoqOg0KDQogICAgLSAgIEl0IGVmZmVjdGl2ZWx5IGNhcHR1cmVzIG1ham9yIGVjb25vbWljIGV2ZW50cywgc3VjaCBhcyB0aGUgQ09WSUQtMTkgcmVjZXNzaW9uLg0KDQogICAgLSAgIFRoZSBpbmRleCB0cmFja3MgdGhlIENGTkFJRElGRiB3ZWxsIGluIG1hbnkgcGVyaW9kcywgbWFraW5nIGl0IGEgY3JlZGlibGUgcHJveHkgZm9yIGJyb2FkZXIgZWNvbm9taWMgdHJlbmRzLg0KDQotICAgKipXZWFrbmVzc2VzIG9yIExpbWl0YXRpb25zKio6DQoNCiAgICAtICAgRGlmZmVyZW5jZXMgZHVyaW5nIGRpdmVyZ2VuY2UgcGVyaW9kcyBzdWdnZXN0IHRoYXQgdGhlIGluY2x1c2lvbiBvZiBhZGRpdGlvbmFsIHZhcmlhYmxlcyBjb3VsZCBpbXByb3ZlIGFsaWdubWVudCB3aXRoIENGTkFJRElGRi4NCg0KICAgIC0gICBTZW5zaXRpdml0eSB0byBzaG9ydC10ZXJtIGRhdGEgZmx1Y3R1YXRpb25zIG1heSByZXF1aXJlIHNtb290aGluZyBvciBhZGRpdGlvbmFsIHByZXByb2Nlc3NpbmcgZm9yIGNsZWFyZXIgaW50ZXJwcmV0YXRpb24uDQoNCiMjIyAqKlJlY2VudCBFY29ub21pYyBDb25kaXRpb25zIChQb3N0LVNlcHRlbWJlciAyMDI0KSoqDQoNCi0gICBJZiB5b3VyIGN1c3RvbSBpbmRleCBpcyB0cmVuZGluZyBkb3dud2FyZCBhZnRlciBTZXB0ZW1iZXIgMjAyNDoNCg0KICAgIC0gICBUaGlzIG1heSBpbmRpY2F0ZSBhIHNvZnRlbmluZyBpbiBlY29ub21pYyBhY3Rpdml0eSwgcG90ZW50aWFsbHkgZHVlIHRvIHdlYWtlciBpbmR1c3RyaWFsIHByb2R1Y3Rpb24sIGVtcGxveW1lbnQsIG9yIGNvbnN1bWVyIHNlbnRpbWVudC4NCg0KICAgIC0gICBTdWNoIHRyZW5kcyBjb3VsZCByZWZsZWN0IGNoYWxsZW5nZXMgbGlrZSByaXNpbmcgaW50ZXJlc3QgcmF0ZXMsIGluZmxhdGlvbmFyeSBwcmVzc3VyZXMsIG9yIG90aGVyIG1hY3JvZWNvbm9taWMgaGVhZHdpbmRzLg0KDQotICAgSWYgdGhlIGluZGV4IGlzIHN0YWJsZSBvciByaXNpbmc6DQoNCiAgICAtICAgVGhpcyBzdWdnZXN0cyByZXNpbGllbmNlIGluIHRoZSBlY29ub215LCB3aXRoIHBvc2l0aXZlIGNvbnRyaWJ1dGlvbnMgZnJvbSB0aGUgaW5jbHVkZWQgdmFyaWFibGVzLg0KDQojIyMgKipDb25jbHVzaW9uKioNCg0KVGhlIERpZmZ1c2lvbiBJbmRleCByZWZsZWN0cyBub3RhYmxlIGVjb25vbWljIGZsdWN0dWF0aW9ucyBvdmVyIHRpbWUsIHdpdGggcmVjZW50IGRlY2xpbmVzIGRyaXZlbiBieSBkcm9wcyBpbiBlbXBsb3ltZW50LCBpbmR1c3RyaWFsIHByb2R1Y3Rpb24sIGFuZCBjb25zdW1lciBzZW50aW1lbnQuIEluIGNvbnRyYXN0LCBDRk5BSURJRkYgc2hvd3Mgc3RlYWRpZXIgbmF0aW9uYWwgYWN0aXZpdHksIHdpdGggbGVzcyB2b2xhdGlsaXR5IGNvbXBhcmVkIHRvIHRoZSBEaWZmdXNpb24gSW5kZXguIFRoZSB3ZWFrIGNvcnJlbGF0aW9uIG9mIDAuMTU3IGhpZ2hsaWdodHMgdGhlIGRpZmZlcmVuY2VzIGluIHRoZWlyIGZvY3VzOiB0aGUgRGlmZnVzaW9uIEluZGV4IGlzIG1vcmUgc2Vuc2l0aXZlIHRvIGxvY2FsaXplZCBlY29ub21pYyBjaGFuZ2VzLCB3aGlsZSBDRk5BSURJRkYgY2FwdHVyZXMgYnJvYWRlciBuYXRpb25hbCB0cmVuZHMuIFRoZSBvdXRsb29rIHN1Z2dlc3RzIHRoYXQgdGhlIERpZmZ1c2lvbiBJbmRleCBpbmRpY2F0ZXMgcmVnaW9uYWwgb3Igc2VjdG9yYWwgd2Vha25lc3Nlcywgd2hlcmVhcyBDRk5BSURJRkYgcG9pbnRzIHRvIGEgc3RhYmxlIG5hdGlvbmFsIGVjb25vbXkgd2l0aG91dCB3aWRlc3ByZWFkIGNvbnRyYWN0aW9uLg0K