Introduction
This problem is a typical econometric modeling situation. The Phillips Curve says that inflation and unemployment move
in opposite directions. It was the basis for the Fed fighting
unemployment by allowing a bit of inflation.
Actually in recent years especially since 2008 this theory is
somewhat discredited, though the Trump administration seems to believe
it. Few economists believe the link is that close anymore.
The Problem
The Phillips curve and modified Phillips curve relating inflation and
unemployment are presented in Example 6.6 in the book.
I’d read that first. Now we can examine Example 6.7, which presents some
data to test for the Phillips curve.
We quote from the book:
As an illustration of the modified Phillips curve, we present in
Table 6.5 data on inflation as measured by year-to-year percentage in
the Consumer Price Index (CPI) and the unemployment rate for the period
1960–2006. The unemployment rate represents the civilian unemployment
rate. From these data we obtained the change in the inflation rate \((\pi_t − \pi_{t−1})\) and plotted it
against the civilian unemployment rate; we are using the CPI as a
measure of inflation. The resulting graph appears in Figure 6.9.
As expected, the relation between the change in inflation rate and
the unemployment rate is negative—– a low unemployment rate leads to an
increase in the inflation rate and therefore an acceleration of the
price level, hence the name accelerationist Phillips curve. Looking at
Figure 6.9, it is not obvious whether a linear (straight line)
regression model or a reciprocal model fits the data; there may be a
curvilinear relationship between the two variables. We present below
regressions based on both the models. However, keep in mind that for the
reciprocal model the intercept term is expected to be negative and the
slope positive, as noted in footnote 20.
Linear model:
\[(\pi_t − \pi_{t−1}) = 3.7844 − 0.6385
UN_t \qquad\qquad(6.7.5)\]
\[t = (4.1912) (−4.2756) \qquad R^2 =
0.2935\]
Reciprocal model:
\[(\pi_t − pi_{t−1}) = −3.0684 + 17.2077
(1/UN_t) \qquad\qquad(6.7.6)\]
\[t = (−3.1635) (3.2886) \qquad R^2 =
0.1973\]
All the estimated coefficients in both the models are individually
statistically significant, all the p values being lower than the 0.005
level.
We are supposed to use the data in Table 6.5 to create these
regressions and determine their quality.
Packages
We load the standard packages for the MBAD637 course.
library(tidyverse) # used to manipulate data and plot
library(ggfortify) # some extra ggplot functions
library(GGally) # pairs ggplot and other options
library(skimr) # nice summaries
library(broom) # neat model summary
library(gt) # nice displays of printed data
library(patchwork) # arranging graphs
library(car) # useful tools for regression analysis
library(yardstick) # for model performance metrics
library(ggResidpanel) # residual plots
library(mbadtools) # custom packages for this course; install from github
Data
We use the Import Datasets button to import from Table 6.5,
being sure to copy the code generated for the import.
library(readxl)
Table_6_5 <- read_excel("~/stfrancis/MBAD637 Business Forecasting and Econometrics/GP Data Sets/Table 6_5.xls",
skip = 2)
New names:
View(Table_6_5)
Looking at the View()
tab for the file, we see that the
data are actually in two halves, side by side. We have to put the right
half below the left half. The column names are a bit funky too.
Examine Data
Let’s do some basic examination of the data.
Table_6_5
glimpse(Table_6_5)
Rows: 24
Columns: 7
$ Year...1 <chr> "1960", "1961", "1962", "1963", "1964", "1965", "1966…
$ INFLRATE...2 <dbl> 1.718213, 1.013514, 1.003344, 1.324503, 1.307190, 1.6…
$ UNRATE...3 <dbl> 5.5, 6.7, 5.5, 5.7, 5.2, 4.5, 3.8, 3.8, 3.6, 3.5, 4.9…
$ ...4 <lgl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
$ Year...5 <chr> "1984", "1985", "1986", "1987", "1988", "1989", "1990…
$ INFLRATE...6 <dbl> 4.317269, 3.561116, 1.858736, 3.649635, 4.137324, 4.8…
$ UNRATE...7 <dbl> 7.5, 7.2, 7.0, 6.2, 5.5, 5.3, 5.6, 6.8, 7.5, 6.9, 6.1…
By looking at the end of the file we see that in the right half there
is a row of NAs at the end. Since there are 24 rows in this data frame,
there must be 47 actual years of data. So there is some wrangling to do
to make a new data frame just as we like it.
Data Wrangling
We will make a new data frame phillips
by moving in
parts of the data from Table_6_5
.
We will make a temporary data frame phillips_1
with the
left half of the data and phillips_2
with the right half.
Because of the weird column names, we will also fix those as we go. And
we will make Year a numeric variable.
phillips_1 = Table_6_5 %>%
select(1:3)
names(phillips_1) = c("Year", "INFLRATE", "UNRATE")
glimpse(phillips_1)
Rows: 24
Columns: 3
$ Year <chr> "1960", "1961", "1962", "1963", "1964", "1965", "1966", "…
$ INFLRATE <dbl> 1.718213, 1.013514, 1.003344, 1.324503, 1.307190, 1.61290…
$ UNRATE <dbl> 5.5, 6.7, 5.5, 5.7, 5.2, 4.5, 3.8, 3.8, 3.6, 3.5, 4.9, 5.…
phillips_2 = Table_6_5 %>%
select(5:7)
names(phillips_2)=c("Year", "INFLRATE", "UNRATE")
glimpse(phillips_2)
Rows: 24
Columns: 3
$ Year <chr> "1984", "1985", "1986", "1987", "1988", "1989", "1990", "…
$ INFLRATE <dbl> 4.317269, 3.561116, 1.858736, 3.649635, 4.137324, 4.81825…
$ UNRATE <dbl> 7.5, 7.2, 7.0, 6.2, 5.5, 5.3, 5.6, 6.8, 7.5, 6.9, 6.1, 5.…
This looks good.
Now we make our desired data frame by putting phillips_1
on top of phillips_2
, using tidyverse
tools.
Then we remove any NAs. And we make Year a numeric column.
phillips = bind_rows(phillips_1, phillips_2) %>%
na.omit %>%
mutate(Year=as.numeric(Year))
glimpse(phillips)
Rows: 47
Columns: 3
$ Year <dbl> 1960, 1961, 1962, 1963, 1964, 1965, 1966, 1967, 1968, 196…
$ INFLRATE <dbl> 1.718213, 1.013514, 1.003344, 1.324503, 1.307190, 1.61290…
$ UNRATE <dbl> 5.5, 6.7, 5.5, 5.7, 5.2, 4.5, 3.8, 3.8, 3.6, 3.5, 4.9, 5.…
I think we’ve got it!!
Now the research problem specifies that the models have as target not
INFLRATE, but the change in inflation rate from the previous year. Let’s
add a column to phillips
that calculates the change in the
INFLRATE
column over the past year. Observe we need to put
an NA at the start of the column, because there isn’t anything to take a
difference from.
phillips = phillips %>%
mutate(INFLCHANGE=c(NA,diff(phillips$INFLRATE)) )
glimpse(phillips)
Rows: 47
Columns: 4
$ Year <dbl> 1960, 1961, 1962, 1963, 1964, 1965, 1966, 1967, 1968, 1…
$ INFLRATE <dbl> 1.718213, 1.013514, 1.003344, 1.324503, 1.307190, 1.612…
$ UNRATE <dbl> 5.5, 6.7, 5.5, 5.7, 5.2, 4.5, 3.8, 3.8, 3.6, 3.5, 4.9, …
$ INFLCHANGE <dbl> NA, -0.70469954, -0.01016903, 0.32115883, -0.01731377, …
Now we have the difference each year from the last. We can check that
by trying the first few:
d=c()
for (i in 1:6) d[i] = phillips$INFLRATE[i+1] - phillips$INFLRATE[i]
d
[1] -0.70469954 -0.01016903 0.32115883 -0.01731377 0.30571368 1.24423963
The differences match what are in the INFLCHANGE column.
Data Description
Looking at the data we have
phillips %>% glimpse
Rows: 47
Columns: 4
$ Year <dbl> 1960, 1961, 1962, 1963, 1964, 1965, 1966, 1967, 1968, 1…
$ INFLRATE <dbl> 1.718213, 1.013514, 1.003344, 1.324503, 1.307190, 1.612…
$ UNRATE <dbl> 5.5, 6.7, 5.5, 5.7, 5.2, 4.5, 3.8, 3.8, 3.6, 3.5, 4.9, …
$ INFLCHANGE <dbl> NA, -0.70469954, -0.01016903, 0.32115883, -0.01731377, …
phillips %>% skim
── Data Summary ────────────────────────
Values
Name Piped data
Number of rows 47
Number of columns 4
_______________________
Column type frequency:
numeric 4
________________________
Group variables None
The only NA is the first INFLCHANGE observation, since we have
nothing to subtract from it.
We could throw in an estimate for the first entry, like the mean or
median of the differences, or we could just leave it and see if it
messes us up and fix it then. Hint: in R, it won’t matter for linear
models.
Visualizing Data
A pairs plot is a quick way to see relations between the columns.
phillips %>% ggpairs(progress = FALSE)

Is there a relation between INFLCHANGE
and
UNRATE
? It’s kind of there, and downward, as anticipated.
The correlation is around -0.54.
Because the research question poses the Linear and Reciprocal, let’s
graph the linear model INFLCHANGE~UNRATE
and the Reciprocal
model INFLCHANGE~I(1/UNRATE)
. The reciprocal formula has an
I()
function around it because we want R to interpret the
formula identically as it is written. That function stands for
Identity.
We will put the plots in a patchwork
object which shows
them side by side in two columns. The left one is Figure 6.9 in the
text.
g_linear = ggplot(phillips) +
geom_point(aes(UNRATE,INFLCHANGE), na.rm = T)
g_recip = ggplot(phillips) +
geom_point(aes(I(1/UNRATE),INFLCHANGE), na.rm=T)
# basic patchwork
g_linear + g_recip

Advanced patchwork
, and advanced
GGally::ggmatrix
methods:
list(g_linear, g_recip) %>%
wrap_plots(nrow = 1) +
plot_annotation(title = "Figure 6.9",
tag_levels=list(c("Linear","Reciprocal")))

list(g_linear, g_recip) %>%
ggmatrix(ncol=2, nrow=1,
title="Figure 6.9",
ylab="Inflation Change (%)",
xAxisLabels = c("Linear", "Reciprocal"),
showXAxisPlotLabels = TRUE
)

We can see some slight linearity in each model. The relation is
positive for 1/UNRATE, and negative for UNRATE itself.
Modeling
We estimate the Linear and Reciprocal models.
Linear Model
First we estimate the Linear Model.
fit.lin = lm(INFLCHANGE~UNRATE, data=phillips)
fit.lin %>% glance()
fit.lin %>% tidy(conf.int=T) %>% gt_add_significance()
term |
estimate |
std.error |
statistic |
p.value |
conf.low |
conf.high |
(Intercept) |
3.7844 |
0.9029 |
4.1912 |
0.0001 |
1.9647 |
5.6042 |
UNRATE |
−0.6385 |
0.1493 |
−4.2756 |
0.0001 |
−0.9394 |
−0.3375 |
The coefficient of UNRATE
in the Linear Model is -0.63,
and it is significant at better than the .005 level. The R-squared of
the Linear model is only 0.29, however, which leads us to wonder if this
regression is useful. However the F-statistic test tells us the
regression is meaningful (naturally, since there is only one driver in
the regression, and the coefficient estimate is probably not zero).
anova(fit.lin) %>% tidy %>% gt_add_significance()
term |
df |
sumsq |
meansq |
statistic |
p.value |
UNRATE |
1.0000 |
38.1475 |
38.1475 |
18.2805 |
0.0001 |
Residuals |
44.0000 |
91.8187 |
2.0868 |
NA |
NA |
The anova()
table tells us the same thing.
We are obliged to look at the residual distribution to assess any
regression. I like using ggResidpanel::resid_panel
.
Messages are turned off due to the smoother spitting out stuff.
resid_panel(fit.lin, plots=c("resid","qq","ls","hist"), smooth=T)

The QQ plot leads to some questions about whether the residuals are
normally distributed. For large quantiles of inflation they clearly are
off the dotted line. This is a problem for the regression.
The RF plot shows that the mean of residuals may be a bit below zero,
but it is pretty uniform across the fitted values. They are pretty well
scattered about zero and look random.
The SL plot shows that the standard deviation is declining rather
than being constant, but it isn’t too awful.
In short, the residual analysis is not giving us much more confidence
than the low R-squared in the statistics did. The Linear regression is
not too likely to be a good model for prediction.
Reciprocal Model
Now we estimate the Reciprocal Model using R.
fit.rec = lm(INFLCHANGE~I(1/UNRATE), data=phillips)
fit.rec %>% glance
fit.rec %>% tidy(conf.int=T) %>% gt_add_significance()
term |
estimate |
std.error |
statistic |
p.value |
conf.low |
conf.high |
(Intercept) |
−3.0684 |
0.9699 |
−3.1635 |
0.0028 |
−5.0231 |
−1.1136 |
I(1/UNRATE) |
17.2077 |
5.2325 |
3.2886 |
0.0020 |
6.6623 |
27.7530 |
The coefficient of 1/UNRATE
in the Reciprocal Model is
17.2, and it is significant at better than the .002 level.
The R-squared of the Linear model is only 0.20, however, which leads
us to wonder if this regression is useful. However the F-statistic test
tells us the regression is meaningful (naturally, since there is only
one driver in the regression, and the coefficient estimate is probably
not zero).
anova(fit.rec) %>% tidy %>% gt_add_significance()
term |
df |
sumsq |
meansq |
statistic |
p.value |
I(1/UNRATE) |
1.0000 |
25.6426 |
25.6426 |
10.8151 |
0.0020 |
Residuals |
44.0000 |
104.3237 |
2.3710 |
NA |
NA |
The anova()
table tells us the same thing.
We are obliged to look at the residual distribution to assess any
regression.
resid_panel(fit.rec, plots=c("resid","qq","ls","hist"), smooth=T)

The QQ plot leads to some questions about whether the residuals are
normally distributed. For large quantiles they clearly are off the
dotted line. This is a problem for the regression.
The RF plot shows that the mean of residuals may be a bit below zero,
and is not uniform across the fitted values. They are pretty well
scattered about zero,but don’t look random; they are wide in the middle
and narrow at the ends.
The LS plot shows that the standard deviation is declining rather
than being constant, and is way up for small fitted values.
In short, the residual analysis is giving us even less confidence
than the low R-squared in the statistics did. The Reciprocal regression
is also even less likely to be a good model for prediction.
Visualizing the models
Here we will graph the Linear and Reciprocal models on top of the
data, so we can get a picture of how well they estimate the data itself.
Of course the real question is can they be used by the Fed for instance
to estimate future inflation change from unemployment now. These models
probably would not be good choices.
We’ll grab the code for the side-by-side plots above and add layers
for the regression lines with the geom_smooth()
function.
It won’t work for the reciprocal,so we will just plot the regression
line.
gr_linear = ggplot(phillips,aes(UNRATE,INFLCHANGE)) +
geom_point(na.rm=TRUE) +
geom_text(x=8, y=5, label="Linear") +
geom_smooth(method="lm", se=T, formula='y~x', na.rm=T)
gr_recip = ggplot(phillips,aes(I(1/UNRATE),INFLCHANGE)) +
geom_point(na.rm=TRUE) +
geom_text(x=0.25, y=5, label="Reciprocal") +
geom_abline(aes(intercept=coef(fit.rec)[1],
slope=coef(fit.rec)[2]), color="red")
(gr_linear + gr_recip) +
plot_annotation(title="Linear and Reciprocal Estimates")

Many of the data points are outside the confidence bands for mean
estimates, signifying pretty poor forecasting ability.
Another way to look at the fit is to use yvp plots: we present them
side by side with patchwork
.
P = list(
resid_panel(fit.rec, plots=c("yvp"), smooth=T),
resid_panel(fit.lin, plots=c("yvp"), smooth=T)
)
P %>% wrap_plots(ncol=2) +
plot_annotation(subtitle = "Linear and Reciprocal responses")

P %>% ggmatrix(nrow=2, ncol=1,
xAxisLabels = c("Linear","Reciprocal"))

These both show a lot of noise in the predictions; high accuracy
would place the dots close to the blue line.
Conclusion
We looked at a Linear and a Reciprocal model of possible Phillips
Curves. Neither was found to be very good for forecasting future
inflation rate change for present unemployment.
This is in line with current critiques of the Phillips Curve as a
policy tool for the Fed.
LS0tDQp0aXRsZTogIkV4YW1wbGUgNl83IFBoaWxsaXBzIEN1cnZlIg0KYXV0aG9yOiAiQnJ1Y2UgSGFydG1hbiINCmRhdGU6ICJGZWJydWFyeSAyMSwgMjAyNCINCm91dHB1dDogICANCiAgaHRtbF9ub3RlYm9vazoNCiAgICB0b2M6IFRSVUUNCiAgICB0b2NfZmxvYXQ6IFRSVUUNCiAgICB0aGVtZTogdW5pdGVkDQphYnN0cmFjdDogfA0KICBXZSBkaXNjdXNzIHNldmVyYWwgZm9ybXMgb2YgdGhlIFBoaWxsaXBzIGN1cnZlIHdoaWNoIHJlbGF0ZXMgaW5mbGF0aW9uIHRvIHVuZW1wbG95bWVudC4gDQotLS0NCg0KIyBJbnRyb2R1Y3Rpb24NClRoaXMgcHJvYmxlbSBpcyBhIHR5cGljYWwgZWNvbm9tZXRyaWMgbW9kZWxpbmcgc2l0dWF0aW9uLiBUaGUgW1BoaWxsaXBzIEN1cnZlXSgjcjIpIHNheXMgdGhhdCBpbmZsYXRpb24gYW5kIHVuZW1wbG95bWVudCBtb3ZlIGluIG9wcG9zaXRlIGRpcmVjdGlvbnMuIEl0IHdhcyB0aGUgYmFzaXMgZm9yIHRoZSBGZWQgZmlnaHRpbmcgdW5lbXBsb3ltZW50IGJ5IGFsbG93aW5nIGEgYml0IG9mIGluZmxhdGlvbi4NCg0KQWN0dWFsbHkgaW4gcmVjZW50IHllYXJzIGVzcGVjaWFsbHkgc2luY2UgMjAwOCB0aGlzIHRoZW9yeSBpcyBzb21ld2hhdA0KZGlzY3JlZGl0ZWQsIHRob3VnaCB0aGUgVHJ1bXAgYWRtaW5pc3RyYXRpb24gc2VlbXMgdG8gYmVsaWV2ZSBpdC4gRmV3DQplY29ub21pc3RzIGJlbGlldmUgdGhlIGxpbmsgaXMgdGhhdCBjbG9zZSBhbnltb3JlLiANCg0KIyBUaGUgUHJvYmxlbQ0KVGhlIFBoaWxsaXBzIGN1cnZlIGFuZCBtb2RpZmllZCBQaGlsbGlwcyBjdXJ2ZSByZWxhdGluZyBpbmZsYXRpb24gYW5kIHVuZW1wbG95bWVudCBhcmUgcHJlc2VudGVkIGluIEV4YW1wbGUgNi42IGluIFt0aGUgYm9va10oI3IxKS4gSSdkIHJlYWQgdGhhdCBmaXJzdC4gIE5vdyB3ZSBjYW4gZXhhbWluZSBFeGFtcGxlIDYuNywgd2hpY2ggcHJlc2VudHMgc29tZSBkYXRhIHRvIHRlc3QgZm9yIHRoZSBQaGlsbGlwcyBjdXJ2ZS4gDQoNCldlIHF1b3RlIGZyb20gdGhlIGJvb2s6DQoNCj5BcyBhbiBpbGx1c3RyYXRpb24gb2YgdGhlIG1vZGlmaWVkIFBoaWxsaXBzIGN1cnZlLCB3ZSBwcmVzZW50IGluIFRhYmxlIDYuNSBkYXRhIG9uIGluZmxhdGlvbg0KYXMgbWVhc3VyZWQgYnkgeWVhci10by15ZWFyIHBlcmNlbnRhZ2UgaW4gdGhlIENvbnN1bWVyIFByaWNlIEluZGV4IChDUEkpIGFuZA0KdGhlIHVuZW1wbG95bWVudCByYXRlIGZvciB0aGUgcGVyaW9kIDE5NjDigJMyMDA2LiBUaGUgdW5lbXBsb3ltZW50IHJhdGUgcmVwcmVzZW50cw0KdGhlIGNpdmlsaWFuIHVuZW1wbG95bWVudCByYXRlLiBGcm9tIHRoZXNlIGRhdGEgd2Ugb2J0YWluZWQgdGhlIGNoYW5nZSBpbiB0aGUgaW5mbGF0aW9uDQpyYXRlICQoXHBpX3Qg4oiSIFxwaV97dOKIkjF9KSQgYW5kIHBsb3R0ZWQgaXQgYWdhaW5zdCB0aGUgY2l2aWxpYW4gdW5lbXBsb3ltZW50IHJhdGU7IHdlIGFyZSB1c2luZyB0aGUgQ1BJDQphcyBhIG1lYXN1cmUgb2YgaW5mbGF0aW9uLiBUaGUgcmVzdWx0aW5nIGdyYXBoIGFwcGVhcnMgaW4gRmlndXJlIDYuOS4NCg0KPkFzIGV4cGVjdGVkLCB0aGUgcmVsYXRpb24gYmV0d2VlbiB0aGUgY2hhbmdlIGluIGluZmxhdGlvbiByYXRlIGFuZCB0aGUgdW5lbXBsb3ltZW50DQpyYXRlIGlzIG5lZ2F0aXZl4oCULS0gYSBsb3cgdW5lbXBsb3ltZW50IHJhdGUgbGVhZHMgdG8gYW4gaW5jcmVhc2UgaW4gdGhlIGluZmxhdGlvbiByYXRlIGFuZA0KdGhlcmVmb3JlIGFuIGFjY2VsZXJhdGlvbiBvZiB0aGUgcHJpY2UgbGV2ZWwsIGhlbmNlIHRoZSBuYW1lIGFjY2VsZXJhdGlvbmlzdCBQaGlsbGlwcyBjdXJ2ZS4NCkxvb2tpbmcgYXQgRmlndXJlIDYuOSwgaXQgaXMgbm90IG9idmlvdXMgd2hldGhlciBhIGxpbmVhciAoc3RyYWlnaHQgbGluZSkgcmVncmVzc2lvbiBtb2RlbA0Kb3IgYSByZWNpcHJvY2FsIG1vZGVsIGZpdHMgdGhlIGRhdGE7IHRoZXJlIG1heSBiZSBhIGN1cnZpbGluZWFyIHJlbGF0aW9uc2hpcCBiZXR3ZWVuIHRoZQ0KdHdvIHZhcmlhYmxlcy4gV2UgcHJlc2VudCBiZWxvdyByZWdyZXNzaW9ucyBiYXNlZCBvbiBib3RoIHRoZSBtb2RlbHMuIEhvd2V2ZXIsIGtlZXAgaW4NCm1pbmQgdGhhdCBmb3IgdGhlIHJlY2lwcm9jYWwgbW9kZWwgdGhlIGludGVyY2VwdCB0ZXJtIGlzIGV4cGVjdGVkIHRvIGJlIG5lZ2F0aXZlIGFuZCB0aGUNCnNsb3BlIHBvc2l0aXZlLCBhcyBub3RlZCBpbiBmb290bm90ZSAyMC4NCg0KPkxpbmVhciBtb2RlbDogDQoNCiQkKFxwaV90IOKIkiBccGlfe3TiiJIxfSkgPSAzLjc4NDQg4oiSIDAuNjM4NSBVTl90ICBccXF1YWRccXF1YWQoNi43LjUpJCQNCg0KJCR0ID0gKDQuMTkxMikgKOKIkjQuMjc1NikgXHFxdWFkIFJeMiA9IDAuMjkzNSQkDQoNCj5SZWNpcHJvY2FsIG1vZGVsOg0KDQogICQkKFxwaV90IOKIkiBwaV97dOKIkjF9KSA9IOKIkjMuMDY4NCArIDE3LjIwNzcgKDEvVU5fdCkgIFxxcXVhZFxxcXVhZCg2LjcuNikkJA0KDQogJCR0ID0gKOKIkjMuMTYzNSkgKDMuMjg4NikgXHFxdWFkIFJeMiA9IDAuMTk3MyQkDQoNCj5BbGwgdGhlIGVzdGltYXRlZCBjb2VmZmljaWVudHMgaW4gYm90aCB0aGUgbW9kZWxzIGFyZSBpbmRpdmlkdWFsbHkgc3RhdGlzdGljYWxseSBzaWduaWZpY2FudCwgYWxsIHRoZSBwIHZhbHVlcyBiZWluZyBsb3dlciB0aGFuIHRoZSAwLjAwNSBsZXZlbC4NCg0KV2UgYXJlIHN1cHBvc2VkIHRvIHVzZSB0aGUgZGF0YSBpbiBUYWJsZSA2LjUgdG8gY3JlYXRlIHRoZXNlIHJlZ3Jlc3Npb25zIGFuZCBkZXRlcm1pbmUgdGhlaXIgcXVhbGl0eS4NCg0KIyBQYWNrYWdlcw0KV2UgbG9hZCB0aGUgc3RhbmRhcmQgcGFja2FnZXMgZm9yIHRoZSBNQkFENjM3IGNvdXJzZS4NCmBgYHtyfQ0KbGlicmFyeSh0aWR5dmVyc2UpICMgdXNlZCB0byBtYW5pcHVsYXRlIGRhdGEgYW5kIHBsb3QNCmxpYnJhcnkoZ2dmb3J0aWZ5KSAjIHNvbWUgZXh0cmEgZ2dwbG90IGZ1bmN0aW9ucw0KbGlicmFyeShHR2FsbHkpICMgcGFpcnMgZ2dwbG90IGFuZCBvdGhlciBvcHRpb25zDQpsaWJyYXJ5KHNraW1yKSAjIG5pY2Ugc3VtbWFyaWVzDQpsaWJyYXJ5KGJyb29tKSAjIG5lYXQgbW9kZWwgc3VtbWFyeQ0KbGlicmFyeShndCkgIyBuaWNlIGRpc3BsYXlzIG9mIHByaW50ZWQgZGF0YQ0KbGlicmFyeShwYXRjaHdvcmspICMgYXJyYW5naW5nIGdyYXBocw0KbGlicmFyeShjYXIpICMgdXNlZnVsIHRvb2xzIGZvciByZWdyZXNzaW9uIGFuYWx5c2lzDQpsaWJyYXJ5KHlhcmRzdGljaykgIyBmb3IgbW9kZWwgcGVyZm9ybWFuY2UgbWV0cmljcw0KbGlicmFyeShnZ1Jlc2lkcGFuZWwpICMgcmVzaWR1YWwgcGxvdHMNCmxpYnJhcnkobWJhZHRvb2xzKSAjIGN1c3RvbSBwYWNrYWdlcyBmb3IgdGhpcyBjb3Vyc2U7IGluc3RhbGwgZnJvbSBnaXRodWINCmBgYA0KDQojIERhdGENCg0KV2UgdXNlIHRoZSAqSW1wb3J0IERhdGFzZXRzKiBidXR0b24gdG8gaW1wb3J0IGZyb20gVGFibGUgNi41LCBiZWluZyBzdXJlIHRvIGNvcHkgdGhlIGNvZGUgZ2VuZXJhdGVkIGZvciB0aGUgaW1wb3J0Lg0KDQpgYGB7cn0NCmxpYnJhcnkocmVhZHhsKQ0KVGFibGVfNl81IDwtIHJlYWRfZXhjZWwoIn4vc3RmcmFuY2lzL01CQUQ2MzcgQnVzaW5lc3MgRm9yZWNhc3RpbmcgYW5kIEVjb25vbWV0cmljcy9HUCBEYXRhIFNldHMvVGFibGUgNl81LnhscyIsIA0KICAgIHNraXAgPSAyKQ0KVmlldyhUYWJsZV82XzUpDQpgYGANCg0KTG9va2luZyBhdCB0aGUgYFZpZXcoKWAgdGFiIGZvciB0aGUgZmlsZSwgd2Ugc2VlIHRoYXQgdGhlIGRhdGEgYXJlIGFjdHVhbGx5IGluIHR3byBoYWx2ZXMsIHNpZGUgYnkgc2lkZS4gV2UgaGF2ZSB0byBwdXQgdGhlIHJpZ2h0IGhhbGYgYmVsb3cgdGhlIGxlZnQgaGFsZi4gVGhlIGNvbHVtbiBuYW1lcyBhcmUgYSBiaXQgZnVua3kgdG9vLiAgDQoNCiMgRXhhbWluZSBEYXRhDQpMZXQncyBkbyBzb21lIGJhc2ljIGV4YW1pbmF0aW9uIG9mIHRoZSBkYXRhLg0KDQpgYGB7cn0NClRhYmxlXzZfNQ0KZ2xpbXBzZShUYWJsZV82XzUpDQpgYGANCg0KQnkgbG9va2luZyBhdCB0aGUgZW5kIG9mIHRoZSBmaWxlIHdlIHNlZSB0aGF0IGluIHRoZSByaWdodCBoYWxmIHRoZXJlIGlzIGEgcm93IG9mIE5BcyBhdCB0aGUgZW5kLiBTaW5jZSB0aGVyZSBhcmUgMjQgcm93cyBpbiB0aGlzIGRhdGEgZnJhbWUsIHRoZXJlIG11c3QgYmUgNDcgYWN0dWFsIHllYXJzIG9mIGRhdGEuIFNvIHRoZXJlIGlzIHNvbWUgd3JhbmdsaW5nIHRvIGRvIHRvIG1ha2UgYSBuZXcgZGF0YSBmcmFtZSBqdXN0IGFzIHdlIGxpa2UgaXQuIA0KDQojIERhdGEgV3JhbmdsaW5nDQoNCldlIHdpbGwgbWFrZSBhIG5ldyBkYXRhIGZyYW1lIGBwaGlsbGlwc2AgYnkgbW92aW5nIGluIHBhcnRzIG9mIHRoZSBkYXRhIGZyb20gYFRhYmxlXzZfNWAuDQoNCldlIHdpbGwgbWFrZSBhIHRlbXBvcmFyeSBkYXRhIGZyYW1lIGBwaGlsbGlwc18xYCB3aXRoIHRoZSBsZWZ0IGhhbGYgb2YgdGhlIGRhdGEgYW5kIGBwaGlsbGlwc18yYCB3aXRoIHRoZSByaWdodCBoYWxmLiBCZWNhdXNlIG9mIHRoZSB3ZWlyZCBjb2x1bW4gbmFtZXMsIHdlIHdpbGwgYWxzbyBmaXggdGhvc2UgYXMgd2UgZ28uIEFuZCB3ZSB3aWxsIG1ha2UgWWVhciBhIG51bWVyaWMgdmFyaWFibGUuDQoNCmBgYHtyfQ0KcGhpbGxpcHNfMSA9IFRhYmxlXzZfNSAlPiUgDQogIHNlbGVjdCgxOjMpIA0KbmFtZXMocGhpbGxpcHNfMSkgPSBjKCJZZWFyIiwgIklORkxSQVRFIiwgIlVOUkFURSIpDQpnbGltcHNlKHBoaWxsaXBzXzEpDQoNCnBoaWxsaXBzXzIgPSBUYWJsZV82XzUgJT4lDQogIHNlbGVjdCg1OjcpDQpuYW1lcyhwaGlsbGlwc18yKT1jKCJZZWFyIiwgIklORkxSQVRFIiwgIlVOUkFURSIpDQpnbGltcHNlKHBoaWxsaXBzXzIpDQpgYGANCg0KVGhpcyBsb29rcyBnb29kLg0KDQpOb3cgd2UgbWFrZSBvdXIgZGVzaXJlZCBkYXRhIGZyYW1lIGJ5IHB1dHRpbmcgYHBoaWxsaXBzXzFgIG9uIHRvcCBvZiBgcGhpbGxpcHNfMmAsIHVzaW5nIGB0aWR5dmVyc2VgIHRvb2xzLiBUaGVuIHdlIHJlbW92ZSBhbnkgTkFzLiBBbmQgd2UgbWFrZSBZZWFyIGEgbnVtZXJpYyBjb2x1bW4uDQoNCmBgYHtyfQ0KcGhpbGxpcHMgPSBiaW5kX3Jvd3MocGhpbGxpcHNfMSwgcGhpbGxpcHNfMikgJT4lIA0KICBuYS5vbWl0ICU+JSANCiAgbXV0YXRlKFllYXI9YXMubnVtZXJpYyhZZWFyKSkNCmdsaW1wc2UocGhpbGxpcHMpDQpgYGANCg0KSSB0aGluayB3ZSd2ZSBnb3QgaXQhIQ0KDQpOb3cgdGhlIHJlc2VhcmNoIHByb2JsZW0gc3BlY2lmaWVzIHRoYXQgdGhlIG1vZGVscyBoYXZlIGFzIHRhcmdldCBub3QgSU5GTFJBVEUsIGJ1dCB0aGUgY2hhbmdlIGluIGluZmxhdGlvbiByYXRlIGZyb20gdGhlIHByZXZpb3VzIHllYXIuIExldCdzIGFkZCBhIGNvbHVtbiB0byBgcGhpbGxpcHNgIHRoYXQgY2FsY3VsYXRlcyB0aGUgY2hhbmdlIGluIHRoZSBgSU5GTFJBVEVgIGNvbHVtbiBvdmVyIHRoZSBwYXN0IHllYXIuIE9ic2VydmUgd2UgbmVlZCB0byBwdXQgYW4gTkEgYXQgdGhlIHN0YXJ0IG9mIHRoZSBjb2x1bW4sIGJlY2F1c2UgdGhlcmUgaXNuJ3QgYW55dGhpbmcgdG8gdGFrZSBhIGRpZmZlcmVuY2UgZnJvbS4NCg0KYGBge3J9DQpwaGlsbGlwcyA9IHBoaWxsaXBzICU+JSANCiAgbXV0YXRlKElORkxDSEFOR0U9YyhOQSxkaWZmKHBoaWxsaXBzJElORkxSQVRFKSkgKQ0KZ2xpbXBzZShwaGlsbGlwcykNCmBgYA0KDQpOb3cgd2UgaGF2ZSB0aGUgZGlmZmVyZW5jZSBlYWNoIHllYXIgZnJvbSB0aGUgbGFzdC4gV2UgY2FuIGNoZWNrIHRoYXQgYnkgdHJ5aW5nIHRoZSBmaXJzdCBmZXc6DQpgYGB7cn0NCmQ9YygpDQpmb3IgKGkgaW4gMTo2KSBkW2ldID0gcGhpbGxpcHMkSU5GTFJBVEVbaSsxXSAtIHBoaWxsaXBzJElORkxSQVRFW2ldDQpkDQpgYGANClRoZSBkaWZmZXJlbmNlcyBtYXRjaCB3aGF0IGFyZSBpbiB0aGUgSU5GTENIQU5HRSBjb2x1bW4uDQoNCiMgRGF0YSBEZXNjcmlwdGlvbg0KDQpMb29raW5nIGF0IHRoZSBkYXRhIHdlIGhhdmUNCg0KYGBge3J9DQpwaGlsbGlwcyAlPiUgZ2xpbXBzZQ0KcGhpbGxpcHMgJT4lIHNraW0NCmBgYA0KDQpUaGUgb25seSBOQSBpcyB0aGUgZmlyc3QgSU5GTENIQU5HRSBvYnNlcnZhdGlvbiwgc2luY2Ugd2UgaGF2ZSBub3RoaW5nIHRvIHN1YnRyYWN0IGZyb20gaXQuIA0KDQpXZSBjb3VsZCB0aHJvdyBpbiBhbiBlc3RpbWF0ZSBmb3IgdGhlIGZpcnN0IGVudHJ5LCBsaWtlIHRoZSBtZWFuIG9yIG1lZGlhbiBvZiB0aGUgZGlmZmVyZW5jZXMsIG9yIHdlIGNvdWxkIGp1c3QgbGVhdmUgaXQgYW5kIHNlZSBpZiBpdCBtZXNzZXMgdXMgdXAgYW5kIGZpeCBpdCB0aGVuLiBIaW50OiBpbiBSLCBpdCB3b24ndCBtYXR0ZXIgZm9yIGxpbmVhciBtb2RlbHMuDQoNCiMgVmlzdWFsaXppbmcgRGF0YQ0KDQpBIHBhaXJzIHBsb3QgaXMgYSBxdWljayB3YXkgdG8gc2VlIHJlbGF0aW9ucyBiZXR3ZWVuIHRoZSBjb2x1bW5zLg0KDQpgYGB7cn0NCnBoaWxsaXBzICU+JSBnZ3BhaXJzKHByb2dyZXNzID0gRkFMU0UpDQpgYGANCg0KSXMgdGhlcmUgYSByZWxhdGlvbiBiZXR3ZWVuIGBJTkZMQ0hBTkdFYCBhbmQgYFVOUkFURWA/IEl0J3Mga2luZCBvZiB0aGVyZSwgYW5kIGRvd253YXJkLCBhcyBhbnRpY2lwYXRlZC4gVGhlIGNvcnJlbGF0aW9uIGlzIGFyb3VuZCAtMC41NC4NCg0KQmVjYXVzZSB0aGUgcmVzZWFyY2ggcXVlc3Rpb24gcG9zZXMgdGhlIExpbmVhciBhbmQgUmVjaXByb2NhbCwgbGV0J3MgZ3JhcGggdGhlIGxpbmVhciBtb2RlbCBgSU5GTENIQU5HRX5VTlJBVEVgIGFuZCB0aGUgUmVjaXByb2NhbCBtb2RlbCBgSU5GTENIQU5HRX5JKDEvVU5SQVRFKWAuIFRoZSByZWNpcHJvY2FsIGZvcm11bGEgaGFzIGFuIGBJKClgIGZ1bmN0aW9uIGFyb3VuZCBpdCBiZWNhdXNlIHdlIHdhbnQgUiB0byBpbnRlcnByZXQgdGhlIGZvcm11bGEgaWRlbnRpY2FsbHkgYXMgaXQgaXMgd3JpdHRlbi4gVGhhdCBmdW5jdGlvbiBzdGFuZHMgZm9yIElkZW50aXR5Lg0KDQpXZSB3aWxsIHB1dCB0aGUgcGxvdHMgaW4gYSBgcGF0Y2h3b3JrYCBvYmplY3Qgd2hpY2ggc2hvd3MgdGhlbSBzaWRlIGJ5IHNpZGUgaW4gdHdvIGNvbHVtbnMuIFRoZSBsZWZ0IG9uZSBpcyBGaWd1cmUgNi45IGluIHRoZSB0ZXh0Lg0KDQpgYGB7ciB3YXJuaW5nPUZBTFNFfQ0KZ19saW5lYXIgPSBnZ3Bsb3QocGhpbGxpcHMpICsNCiAgZ2VvbV9wb2ludChhZXMoVU5SQVRFLElORkxDSEFOR0UpLCBuYS5ybSA9IFQpDQpnX3JlY2lwID0gZ2dwbG90KHBoaWxsaXBzKSArDQogIGdlb21fcG9pbnQoYWVzKEkoMS9VTlJBVEUpLElORkxDSEFOR0UpLCBuYS5ybT1UKQ0KDQojIGJhc2ljIHBhdGNod29yaw0KZ19saW5lYXIgKyBnX3JlY2lwDQpgYGANCg0KQWR2YW5jZWQgYHBhdGNod29ya2AsIGFuZCBhZHZhbmNlZCBgR0dhbGx5OjpnZ21hdHJpeGAgbWV0aG9kczoNCmBgYHtyfQ0KbGlzdChnX2xpbmVhciwgZ19yZWNpcCkgJT4lIA0KICB3cmFwX3Bsb3RzKG5yb3cgPSAxKSArDQogICAgcGxvdF9hbm5vdGF0aW9uKHRpdGxlID0gIkZpZ3VyZSA2LjkiLA0KICAgICAgICAgICAgICAgICAgICB0YWdfbGV2ZWxzPWxpc3QoYygiTGluZWFyIiwiUmVjaXByb2NhbCIpKSkNCg0KbGlzdChnX2xpbmVhciwgZ19yZWNpcCkgJT4lIA0KICBnZ21hdHJpeChuY29sPTIsIG5yb3c9MSwNCiAgICAgICAgICAgdGl0bGU9IkZpZ3VyZSA2LjkiLA0KICAgICAgICAgICB5bGFiPSJJbmZsYXRpb24gQ2hhbmdlICglKSIsDQogICAgICAgICAgIHhBeGlzTGFiZWxzID0gYygiTGluZWFyIiwgIlJlY2lwcm9jYWwiKSwNCiAgICAgICAgICAgc2hvd1hBeGlzUGxvdExhYmVscyA9IFRSVUUNCiAgKQ0KYGBgDQpXZSBjYW4gc2VlIHNvbWUgc2xpZ2h0IGxpbmVhcml0eSBpbiBlYWNoIG1vZGVsLiBUaGUgcmVsYXRpb24gaXMgcG9zaXRpdmUgZm9yIDEvVU5SQVRFLCBhbmQgbmVnYXRpdmUgZm9yIFVOUkFURSBpdHNlbGYuDQoNCiMgTW9kZWxpbmcNCldlIGVzdGltYXRlIHRoZSBMaW5lYXIgYW5kIFJlY2lwcm9jYWwgbW9kZWxzLg0KDQojIyBMaW5lYXIgTW9kZWwNCg0KRmlyc3Qgd2UgZXN0aW1hdGUgdGhlIExpbmVhciBNb2RlbC4NCg0KYGBge3J9DQpmaXQubGluID0gbG0oSU5GTENIQU5HRX5VTlJBVEUsIGRhdGE9cGhpbGxpcHMpDQpmaXQubGluICU+JSBnbGFuY2UoKSANCmZpdC5saW4gJT4lIHRpZHkoY29uZi5pbnQ9VCkgJT4lIGd0X2FkZF9zaWduaWZpY2FuY2UoKQ0KYGBgDQoNClRoZSBjb2VmZmljaWVudCBvZiBgVU5SQVRFYCBpbiB0aGUgTGluZWFyIE1vZGVsIGlzIC0wLjYzLCBhbmQgaXQgaXMgc2lnbmlmaWNhbnQgYXQgYmV0dGVyIHRoYW4gdGhlIC4wMDUgbGV2ZWwuIFRoZSBSLXNxdWFyZWQgb2YgdGhlIExpbmVhciBtb2RlbCBpcyBvbmx5IDAuMjksIGhvd2V2ZXIsIHdoaWNoIGxlYWRzIHVzIHRvIHdvbmRlciBpZiB0aGlzIHJlZ3Jlc3Npb24gaXMgdXNlZnVsLiBIb3dldmVyIHRoZSBGLXN0YXRpc3RpYyB0ZXN0IHRlbGxzIHVzIHRoZSByZWdyZXNzaW9uIGlzIG1lYW5pbmdmdWwgKG5hdHVyYWxseSwgc2luY2UgdGhlcmUgaXMgb25seSBvbmUgZHJpdmVyIGluIHRoZSByZWdyZXNzaW9uLCBhbmQgdGhlIGNvZWZmaWNpZW50IGVzdGltYXRlIGlzIHByb2JhYmx5IG5vdCB6ZXJvKS4NCg0KYGBge3J9DQphbm92YShmaXQubGluKSAlPiUgdGlkeSAlPiUgZ3RfYWRkX3NpZ25pZmljYW5jZSgpDQpgYGANClRoZSBgYW5vdmEoKWAgdGFibGUgdGVsbHMgdXMgdGhlIHNhbWUgdGhpbmcuDQoNCldlIGFyZSBvYmxpZ2VkIHRvIGxvb2sgYXQgdGhlIHJlc2lkdWFsIGRpc3RyaWJ1dGlvbiB0byBhc3Nlc3MgYW55IHJlZ3Jlc3Npb24uIEkgbGlrZSB1c2luZyBgZ2dSZXNpZHBhbmVsOjpyZXNpZF9wYW5lbGAuIE1lc3NhZ2VzIGFyZSB0dXJuZWQgb2ZmIGR1ZSB0byB0aGUgc21vb3RoZXIgc3BpdHRpbmcgb3V0IHN0dWZmLg0KDQpgYGB7ciBtZXNzYWdlPUZBTFNFfQ0KcmVzaWRfcGFuZWwoZml0LmxpbiwgcGxvdHM9YygicmVzaWQiLCJxcSIsImxzIiwiaGlzdCIpLCBzbW9vdGg9VCkNCmBgYA0KDQpUaGUgUVEgcGxvdCBsZWFkcyB0byBzb21lIHF1ZXN0aW9ucyBhYm91dCB3aGV0aGVyIHRoZSByZXNpZHVhbHMgYXJlIG5vcm1hbGx5IGRpc3RyaWJ1dGVkLiBGb3IgbGFyZ2UgcXVhbnRpbGVzIG9mIGluZmxhdGlvbiB0aGV5IGNsZWFybHkgYXJlIG9mZiB0aGUgZG90dGVkIGxpbmUuICBUaGlzIGlzIGEgcHJvYmxlbSBmb3IgdGhlIHJlZ3Jlc3Npb24uDQoNClRoZSBSRiBwbG90IHNob3dzIHRoYXQgdGhlIG1lYW4gb2YgcmVzaWR1YWxzIG1heSBiZSBhIGJpdCBiZWxvdyB6ZXJvLCBidXQgaXQgaXMgcHJldHR5IHVuaWZvcm0gYWNyb3NzIHRoZSBmaXR0ZWQgdmFsdWVzLiBUaGV5IGFyZSBwcmV0dHkgd2VsbCBzY2F0dGVyZWQgYWJvdXQgemVybyBhbmQgbG9vayByYW5kb20uICANCg0KVGhlIFNMIHBsb3Qgc2hvd3MgdGhhdCB0aGUgc3RhbmRhcmQgZGV2aWF0aW9uIGlzIGRlY2xpbmluZyByYXRoZXIgdGhhbiBiZWluZyBjb25zdGFudCwgYnV0IGl0IGlzbid0IHRvbyBhd2Z1bC4NCg0KSW4gc2hvcnQsIHRoZSByZXNpZHVhbCBhbmFseXNpcyBpcyBub3QgZ2l2aW5nIHVzIG11Y2ggbW9yZSBjb25maWRlbmNlIHRoYW4gdGhlIGxvdyBSLXNxdWFyZWQgaW4gdGhlIHN0YXRpc3RpY3MgZGlkLiBUaGUgTGluZWFyIHJlZ3Jlc3Npb24gaXMgbm90IHRvbyBsaWtlbHkgdG8gYmUgYSBnb29kIG1vZGVsIGZvciBwcmVkaWN0aW9uLg0KDQojIyBSZWNpcHJvY2FsIE1vZGVsDQoNCk5vdyB3ZSBlc3RpbWF0ZSB0aGUgUmVjaXByb2NhbCBNb2RlbCB1c2luZyBSLg0KDQpgYGB7cn0NCmZpdC5yZWMgPSBsbShJTkZMQ0hBTkdFfkkoMS9VTlJBVEUpLCBkYXRhPXBoaWxsaXBzKQ0KZml0LnJlYyAlPiUgZ2xhbmNlDQpmaXQucmVjICU+JSB0aWR5KGNvbmYuaW50PVQpICU+JSBndF9hZGRfc2lnbmlmaWNhbmNlKCkNCmBgYA0KDQpUaGUgY29lZmZpY2llbnQgb2YgYDEvVU5SQVRFYCBpbiB0aGUgUmVjaXByb2NhbCBNb2RlbCBpcyAxNy4yLCBhbmQgaXQgaXMgc2lnbmlmaWNhbnQgYXQgYmV0dGVyIHRoYW4gdGhlIC4wMDIgbGV2ZWwuIA0KDQpUaGUgUi1zcXVhcmVkIG9mIHRoZSBMaW5lYXIgbW9kZWwgaXMgb25seSAwLjIwLCBob3dldmVyLCB3aGljaCBsZWFkcyB1cyB0byB3b25kZXIgaWYgdGhpcyByZWdyZXNzaW9uIGlzIHVzZWZ1bC4gSG93ZXZlciB0aGUgRi1zdGF0aXN0aWMgdGVzdCB0ZWxscyB1cyB0aGUgcmVncmVzc2lvbiBpcyBtZWFuaW5nZnVsIChuYXR1cmFsbHksIHNpbmNlIHRoZXJlIGlzIG9ubHkgb25lIGRyaXZlciBpbiB0aGUgcmVncmVzc2lvbiwgYW5kIHRoZSBjb2VmZmljaWVudCBlc3RpbWF0ZSBpcyBwcm9iYWJseSBub3QgemVybykuDQoNCmBgYHtyfQ0KYW5vdmEoZml0LnJlYykgJT4lIHRpZHkgJT4lIGd0X2FkZF9zaWduaWZpY2FuY2UoKQ0KYGBgDQpUaGUgYGFub3ZhKClgIHRhYmxlIHRlbGxzIHVzIHRoZSBzYW1lIHRoaW5nLg0KDQpXZSBhcmUgb2JsaWdlZCB0byBsb29rIGF0IHRoZSByZXNpZHVhbCBkaXN0cmlidXRpb24gdG8gYXNzZXNzIGFueSByZWdyZXNzaW9uLg0KDQpgYGB7ciBtZXNzYWdlPUZBTFNFfQ0KcmVzaWRfcGFuZWwoZml0LnJlYywgcGxvdHM9YygicmVzaWQiLCJxcSIsImxzIiwiaGlzdCIpLCBzbW9vdGg9VCkNCmBgYA0KDQpUaGUgUVEgcGxvdCBsZWFkcyB0byBzb21lIHF1ZXN0aW9ucyBhYm91dCB3aGV0aGVyIHRoZSByZXNpZHVhbHMgYXJlIG5vcm1hbGx5IGRpc3RyaWJ1dGVkLiBGb3IgbGFyZ2UgcXVhbnRpbGVzIHRoZXkgY2xlYXJseSBhcmUgb2ZmIHRoZSBkb3R0ZWQgbGluZS4gIFRoaXMgaXMgYSBwcm9ibGVtIGZvciB0aGUgcmVncmVzc2lvbi4gIA0KDQpUaGUgUkYgcGxvdCBzaG93cyB0aGF0IHRoZSBtZWFuIG9mIHJlc2lkdWFscyBtYXkgYmUgYSBiaXQgYmVsb3cgemVybywgYW5kIGlzIG5vdCB1bmlmb3JtIGFjcm9zcyB0aGUgZml0dGVkIHZhbHVlcy4gVGhleSBhcmUgcHJldHR5IHdlbGwgc2NhdHRlcmVkIGFib3V0IHplcm8sYnV0IGRvbid0IGxvb2sgcmFuZG9tOyB0aGV5IGFyZSB3aWRlIGluIHRoZSBtaWRkbGUgYW5kIG5hcnJvdyBhdCB0aGUgZW5kcy4gIA0KDQpUaGUgTFMgcGxvdCBzaG93cyB0aGF0IHRoZSBzdGFuZGFyZCBkZXZpYXRpb24gaXMgZGVjbGluaW5nIHJhdGhlciB0aGFuIGJlaW5nIGNvbnN0YW50LCBhbmQgaXMgd2F5IHVwIGZvciBzbWFsbCBmaXR0ZWQgdmFsdWVzLg0KDQpJbiBzaG9ydCwgdGhlIHJlc2lkdWFsIGFuYWx5c2lzIGlzIGdpdmluZyB1cyBldmVuIGxlc3MgY29uZmlkZW5jZSB0aGFuIHRoZSBsb3cgUi1zcXVhcmVkIGluIHRoZSBzdGF0aXN0aWNzIGRpZC4gVGhlIFJlY2lwcm9jYWwgcmVncmVzc2lvbiBpcyBhbHNvIGV2ZW4gbGVzcyBsaWtlbHkgdG8gYmUgYSBnb29kIG1vZGVsIGZvciBwcmVkaWN0aW9uLg0KDQojIFZpc3VhbGl6aW5nIHRoZSBtb2RlbHMNCg0KSGVyZSB3ZSB3aWxsIGdyYXBoIHRoZSBMaW5lYXIgYW5kIFJlY2lwcm9jYWwgbW9kZWxzIG9uIHRvcCBvZiB0aGUgZGF0YSwgc28gd2UgY2FuIGdldCBhIHBpY3R1cmUgb2YgaG93IHdlbGwgdGhleSBlc3RpbWF0ZSB0aGUgZGF0YSBpdHNlbGYuIE9mIGNvdXJzZSB0aGUgcmVhbCBxdWVzdGlvbiBpcyBjYW4gdGhleSBiZSB1c2VkIGJ5IHRoZSBGZWQgZm9yIGluc3RhbmNlIHRvIGVzdGltYXRlIGZ1dHVyZSBpbmZsYXRpb24gY2hhbmdlIGZyb20gdW5lbXBsb3ltZW50IG5vdy4gVGhlc2UgbW9kZWxzIHByb2JhYmx5IHdvdWxkIG5vdCBiZSBnb29kIGNob2ljZXMuDQoNCldlJ2xsIGdyYWIgdGhlIGNvZGUgZm9yIHRoZSBzaWRlLWJ5LXNpZGUgcGxvdHMgYWJvdmUgYW5kIGFkZCBsYXllcnMgZm9yIHRoZSByZWdyZXNzaW9uIGxpbmVzIHdpdGggdGhlIGBnZW9tX3Ntb290aCgpYCBmdW5jdGlvbi4gSXQgd29uJ3Qgd29yayBmb3IgdGhlIHJlY2lwcm9jYWwsc28gd2Ugd2lsbCBqdXN0IHBsb3QgdGhlIHJlZ3Jlc3Npb24gbGluZS4NCg0KYGBge3Igd2FybmluZz1GQUxTRX0NCmdyX2xpbmVhciA9IGdncGxvdChwaGlsbGlwcyxhZXMoVU5SQVRFLElORkxDSEFOR0UpKSArDQogIGdlb21fcG9pbnQobmEucm09VFJVRSkgKw0KICBnZW9tX3RleHQoeD04LCB5PTUsIGxhYmVsPSJMaW5lYXIiKSArDQogIGdlb21fc21vb3RoKG1ldGhvZD0ibG0iLCBzZT1ULCBmb3JtdWxhPSd5fngnLCBuYS5ybT1UKQ0KDQpncl9yZWNpcCA9IGdncGxvdChwaGlsbGlwcyxhZXMoSSgxL1VOUkFURSksSU5GTENIQU5HRSkpICsNCiAgZ2VvbV9wb2ludChuYS5ybT1UUlVFKSArDQogIGdlb21fdGV4dCh4PTAuMjUsIHk9NSwgbGFiZWw9IlJlY2lwcm9jYWwiKSArDQogIGdlb21fYWJsaW5lKGFlcyhpbnRlcmNlcHQ9Y29lZihmaXQucmVjKVsxXSwNCiAgICAgICAgICAgICAgICAgIHNsb3BlPWNvZWYoZml0LnJlYylbMl0pLCBjb2xvcj0icmVkIikgDQoNCihncl9saW5lYXIgKyBncl9yZWNpcCkgKyANCiAgcGxvdF9hbm5vdGF0aW9uKHRpdGxlPSJMaW5lYXIgYW5kIFJlY2lwcm9jYWwgRXN0aW1hdGVzIikNCmBgYA0KDQpNYW55IG9mIHRoZSBkYXRhIHBvaW50cyBhcmUgb3V0c2lkZSB0aGUgY29uZmlkZW5jZSBiYW5kcyBmb3IgbWVhbiBlc3RpbWF0ZXMsIHNpZ25pZnlpbmcgcHJldHR5IHBvb3IgZm9yZWNhc3RpbmcgYWJpbGl0eS4NCg0KQW5vdGhlciB3YXkgdG8gbG9vayBhdCB0aGUgZml0IGlzIHRvIHVzZSB5dnAgcGxvdHM6IHdlIHByZXNlbnQgdGhlbSBzaWRlIGJ5IHNpZGUgd2l0aCBgcGF0Y2h3b3JrYC4NCmBgYHtyIG1lc3NhZ2U9RkFMU0V9DQpQID0gbGlzdCgNCiAgcmVzaWRfcGFuZWwoZml0LnJlYywgcGxvdHM9YygieXZwIiksIHNtb290aD1UKSwNCiAgcmVzaWRfcGFuZWwoZml0LmxpbiwgcGxvdHM9YygieXZwIiksIHNtb290aD1UKQ0KICAgICAgICApIA0KUCAlPiUgd3JhcF9wbG90cyhuY29sPTIpICsgDQogIHBsb3RfYW5ub3RhdGlvbihzdWJ0aXRsZSA9ICJMaW5lYXIgYW5kIFJlY2lwcm9jYWwgcmVzcG9uc2VzIikNClAgJT4lIGdnbWF0cml4KG5yb3c9MiwgbmNvbD0xLA0KICAgICAgICAgICAgICAgeEF4aXNMYWJlbHMgPSBjKCJMaW5lYXIiLCJSZWNpcHJvY2FsIikpDQpgYGANCg0KVGhlc2UgYm90aCBzaG93IGEgbG90IG9mIG5vaXNlIGluIHRoZSBwcmVkaWN0aW9uczsgaGlnaCBhY2N1cmFjeSB3b3VsZCBwbGFjZSB0aGUgZG90cyBjbG9zZSB0byB0aGUgYmx1ZSBsaW5lLg0KDQojIENvbmNsdXNpb24NCg0KV2UgbG9va2VkIGF0IGEgTGluZWFyIGFuZCBhIFJlY2lwcm9jYWwgbW9kZWwgb2YgcG9zc2libGUgUGhpbGxpcHMgQ3VydmVzLiAgTmVpdGhlciB3YXMgZm91bmQgdG8gYmUgdmVyeSBnb29kIGZvciBmb3JlY2FzdGluZyBmdXR1cmUgaW5mbGF0aW9uIHJhdGUgY2hhbmdlIGZvciBwcmVzZW50IHVuZW1wbG95bWVudC4NCg0KVGhpcyBpcyBpbiBsaW5lIHdpdGggY3VycmVudCBjcml0aXF1ZXMgb2YgdGhlIFBoaWxsaXBzIEN1cnZlIGFzIGEgcG9saWN5IHRvb2wgZm9yIHRoZSBGZWQuDQoNCiMgUmVmZXJlbmNlcw0KOjo6eyNyMX0NCjEuIEd1amFyYXRpLCBELk4uIGFuZCBQb3J0ZXIsIEQuQy4gKDIwMDkpIEJhc2ljIEVjb25vbWV0cmljcy4gNXRoIEVkaXRpb24sIDIwMDkuIE5ldyBZb3JrLCBNY0dyYXctSGlsbCBJcndpbi4gQ2hhcHRlciA2LCBFeGFtcGxlIDYuNywgcGFnZSAxNzAuIChodHRwczovL2xlYXJuLnN0ZnJhbmNpcy5lZHUvY291cnNlcy8xMTg5NDM2L21vZHVsZXMvaXRlbXMvMTMzMzI2MzQpDQo6OjoNCg0KOjo6eyNyMn0NCjIuIFdpa2lwZWRpYSAoMjAyNCkgUGhpbGxpcHMgQ3VydmUuIChodHRwczovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9QaGlsbGlwc19jdXJ2ZSkNCjo6Og0KDQo=