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
Correlation Coefficient:
The correlation between your custom Diffusion Index and the
Chicago Fed National Activity Diffusion Index (CFNAIDIFF) indicates the
extent to which the two series move together.
A strong positive correlation (close to 1) would imply that your
index is effectively capturing the same economic dynamics as
CFNAIDIFF.
For example, if the correlation is 0.8 or
higher, it suggests that your index is a good proxy for
CFNAIDIFF, reflecting similar economic trends over the analyzed
period.
# 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):
General Alignment: There are periods where the
trends of the custom Diffusion Index and CFNAIDIFF align closely. This
suggests that your methodology for constructing the index is capturing
key aspects of economic activity, particularly in times of economic
growth or decline.
Divergence Periods: At certain points, the
indices deviate from each other (e.g., the blue line moves significantly
above or below the orange line). These divergences could result from
differences in the variables included in your index versus those in
CFNAIDIFF, such as:
CFNAIDIFF uses a broader range of variables beyond employment,
industrial production, and consumer sentiment.
Your index may have specific sensitivities, such as being more
influenced by employment or housing data.
Post-September Observations:
Since CFNAIDIFF data ends in September 2024, your custom index
provides valuable insights into recent economic activity.
If your index shows a decline after September, it could indicate
a weakening economy, while stability or growth would suggest
resilience.
# 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
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