library('fpp3')
library('tsibble')
library('ggplot2')
library('readr')
library('zoo')
library('cowplot')
library('ggfortify')
library('gridExtra')
library('latex2exp')
library('seasonal')

Instuctions

Do exercises 3.1, 3.2, 3.3, 3.4, 3.5, 3.7, 3.8 and 3.9 from the online Hyndman book. Please include your Rpubs link along with.pdf file of your run code

3.1

i

Consider the GDP information in global_economy. Plot the GDP per capita for each country over time. Which country has the highest GDP per capita?


# global_economy

# add GDP to the Data frame
global_economy <- global_economy %>%
  mutate(GDP_per_capita = GDP / Population)

# get the max values entire row for the title
max_gdp_row <- global_economy[which.max(global_economy$GDP_per_capita), ]


global_economy %>%
  autoplot(GDP_per_capita, show.legend = FALSE) +
  labs(title = paste("GDP per capita by Country | Max GDP:", max_gdp_row$GDP_per_capita, "for", max_gdp_row$Country, " in ",max_gdp_row$Year),
       y = "$US")

NA
NA
na_cnt<-sum(is.na(global_economy%>%
        filter(Country=="Monaco")%>%
          select(GDP_per_capita)))
Adding missing grouping variables: `Year`
paste("In the date range of 1960 to 2017 Monaco has had ",na_cnt," NA's")
[1] "In the date range of 1960 to 2017 Monaco has had  11  NA's"

ii

How has this changed over time?


global_economy <- index_by(global_economy, Year)

# store only rows with max gdp
max_gdp_annual <- global_economy %>%
  slice_max(GDP_per_capita) %>%
  ungroup()

# plot by rows selected
ggplot(max_gdp_annual, aes(x = Year, y = GDP_per_capita, color = Country)) +
  geom_line() +
  labs(title = "Country with Highest GDP per Year",
       x = "Year",
       y = "GDP") +
  theme_minimal()

Looks like Luxembourg is using top in GDP making Monaco’s 2014 GDP

3.2

For each of the following series, make a graph of the data. If transforming seems appropriate, do so and describe the effect.

i

United States GDP from global_economy.

Using GDP per Capita made the most sense. It was already transformed by the above manipulations.


fig1<-global_economy%>%
  filter(Country=="United States")%>%
    autoplot()+
  labs(title = "GDP US")
Plot variable not specified, automatically selected `.vars = GDP``mutate_if()` ignored the following grouping variables:
fig2<-global_economy%>%
  filter(Country=="United States")%>%
    autoplot(GDP_per_capita)+
  labs(title = "GDP per Capita US")
`mutate_if()` ignored the following grouping variables:
plot_grid(fig1,
          fig2, nrow = 1)

ii

Slaughter of Victorian “Bulls, bullocks and steers” in aus_livestock.

The data seemed clutter. By grouping it by Quarter the visual is clearer and the initial dip is apparent.

head(aus_livestock)

fig3 <- aus_livestock %>%
  filter(Animal == "Bulls, bullocks and steers") %>%
  summarise(Count = sum(Count)) %>%
  autoplot(show.legend=FALSE)
Plot variable not specified, automatically selected `.vars = Count`
fig4 <- aus_livestock %>%
  filter(Animal == "Bulls, bullocks and steers") %>%
  mutate(Quarter = yearquarter(Month)) %>%
  index_by(Quarter) %>%
  summarise(Count = sum(Count)) %>%
  autoplot(Count, show.legend=FALSE)

plot_grid(fig3, fig4, nrow = 1)

iii

Victorian Electricity Demand from vic_elec.

This was a lot of data so dealers choice, but viewing the annual data in a weekly and monthly basis shows an initial spike the first week and month for the year.

head(vic_elec)
fig5<-vic_elec%>%
        autoplot(Demand)

fig6<-vic_elec%>%
  mutate(Week = yearweek(Time)) %>%
  index_by(Week) %>%
  summarise(Demand = sum(Demand)) %>%
  autoplot(Demand, show.legend=FALSE)

fig7<-vic_elec%>%
  mutate(Month = yearmonth(Time)) %>%
  index_by(Month) %>%
  summarise(Demand = sum(Demand)) %>%
  autoplot(Demand, show.legend=FALSE)

# fig7<-vic_elec%>%
#   mutate(Day = as.Date(Time)) %>%
#   group_by(Day) %>%
#   summarise(Demand = sum(Demand)) %>%
#   autoplot(Demand, show.legend=FALSE)

plot_grid(fig5,
          fig6,
          fig7, nrow = 2)

iv

Gas production from aus_production.


head(aus_production)
NA

I played with all methods introduced in mathematical transformations considering the high variability between the start and end of the data, in an attempt to remove variability.

Than I applied Box-Cox transformations:

\(w_t= \Biggl\{ \genfrac{}{}{0pt}{}{log(y_t),\ \ \ \lambda = 0}{ (sign(y_t)|y_t|^\lambda -1)/\lambda,\ \ \lambda \ne0}\)

as explained in 3.1 video for transformations

#example
# food |>
#   features(Turnover, features = guerrero())

(aus_gas_lambda<-aus_production%>%
  features(Gas, features = guerrero)%>%
   pull(lambda_guerrero))
[1] 0.1095171

fig8 <- aus_production %>%
  autoplot(Gas) +
  labs(title = "Original")

# Define fig9
fig9 <- aus_production %>%
  autoplot(log(Gas)) +
  labs(title = expression(paste("Log Gas ", lambda, "= 0")))

# Define fig10
fig10 <- aus_production %>%
  autoplot(-1/Gas) +
  labs(title = "Inverse Gas")

fig11 <- aus_production%>%
          autoplot(box_cox(Gas,aus_gas_lambda))

plot_grid(fig8 +
            labs(title = "Original"), 
          fig9 +
            labs(title = expression(paste("Log Gas ",
                                          lambda, "= 0"))), 
          fig10 +
            labs(title = expression(paste("Inverse Gas ",
                                          lambda, "= 0"))),
          fig11 +
            labs(title = expression(paste("Box-Cox ",
                                          lambda,
                                          " = 0.1095171"))),
          nrow = 2)

3.3

Why is a Box-Cox transformation unhelpful for the canadian_gas data?

as per the 3.1 Video for transformations.

A low value of \(\lambda\) can give extremely large prediction intervals and as we see in the plot below does not do much for transformation.

head(canadian_gas)
(canada_gas_lambda<-canadian_gas%>%
    features(Volume, features = guerrero)%>%
    pull(lambda_guerrero)
)
[1] 0.5767648
fig12<-canadian_gas%>%
  autoplot(Volume)

fig13<-canadian_gas%>%
  autoplot(box_cox(Volume, canada_gas_lambda))

plot_grid(fig12+labs(title = "Original"),
          fig13+labs(title = expression(paste("Box-Cox ",
                                              lambda,
                                              " =0.5767648"))))

rm(list = ls(pattern = "^fig"))

3.4

What Box-Cox transformation would you select for your retail data (from Exercise 7 in Section 2.10)?

I would rely on features=guerrero since its designed to be the best fit.

# data provided
set.seed(123)
myseries <- aus_retail |>
  filter(`Series ID` == sample(aus_retail$`Series ID`,1))
head(myseries)
(myseries_lambda <- myseries%>%
        features(Turnover,features = guerrero)%>%
          pull(lambda_guerrero))
[1] 0.2151641
fig1 <- myseries%>%
          autoplot(Turnover)

fig2 <- myseries%>%
        autoplot(box_cox(Turnover,myseries_lambda))
fig2<-fig2+ylab("Turnover")

plot_grid(fig1+labs(title = "Original"),
          fig2+labs(title = paste("Box-cox λ =",myseries_lambda)), nrow=2)

3.5

For the following series, find an appropriate Box-Cox transformation in order to stabilize the variance.

i

Tobacco from aus_production

aus_production_lambda<-aus_production%>%
  features(Tobacco,features=guerrero)%>%
  pull(lambda_guerrero)

aus_production%>%
  autoplot(box_cox(Tobacco,aus_production_lambda))+
  labs(title =paste("λ =",aus_production_lambda),ylab="" )

ii

Economy class passengers between Melbourne and Sydney from ansett

head(ansett)
ansett_lambda<-ansett%>%
  filter(Class=="Economy"& Airports=='MEL-SYD')%>%
  features(Passengers,features=guerrero)%>%
  pull(lambda_guerrero)

ansett%>%
  filter(Class=="Economy"& Airports=='MEL-SYD')%>%
  autoplot(box_cox(Passengers,ansett_lambda))+
  labs(title =paste("λ =",ansett_lambda), y=" " )

iii

Pedestrian counts at Southern Cross Station from pedestrian.

head(pedestrian)
pedestrian_lambda<-pedestrian%>%
  filter(Sensor=="Southern Cross Station")%>%
  features(Count,features=guerrero)%>%
  pull(lambda_guerrero)

pedestrian%>%
  filter(Sensor=="Southern Cross Station")%>%
  autoplot(box_cox(Count,pedestrian_lambda))+
  coord_flip()+
  labs(title =paste("λ =",pedestrian_lambda),x = "Date (hourly)",
       y="Count" )

3.7

Consider the last five years of the Gas data from aus_production.

gas <- tail(aus_production, 5*4) |> select(Gas)

head(gas)

a.

Plot the time series. Can you identify seasonal fluctuations and/or a trend-cycle?

Looks like the trend from 2006-2010 is upwards. Seasonality is the high every 3rd quarter and low every 1rst Quarter

gas%>%
  autoplot(Gas)

b.

Use classical_decomposition with type=multiplicative to calculate the trend-cycle and seasonal indices.

Ref 3.4 video

#example
# us_retail_employment |>
#   model(classical_decomposition(Employed, type = "additive")) |>
#   components()|>
#   autoplot()+xlab("Year")+
#   ggtitle("Classical additive decomposition of total US retail employment")
gas%>%
  model(classical_decomposition(Gas,type= "multiplicative"))%>%
  components()%>%
  autoplot+xlab("")

c.

Do the results support the graphical interpretation from part a?

The results show a positive trend with quarterly seasonality so yes it does.

d.

Compute and plot the seasonally adjusted data.

As shown in 3.5

#Example
# x11_dcmp |>
#   ggplot(aes(x = Month)) +
#   geom_line(aes(y = Employed, colour = "Data")) +
#   geom_line(aes(y = season_adjust,
#                 colour = "Seasonally Adjusted")) +
#   geom_line(aes(y = trend, colour = "Trend")) +
#   labs(y = "Persons (thousands)",
#        title = "Total employment in US retail") +
#   scale_colour_manual(
#     values = c("gray", "#0072B2", "#D55E00"),
#     breaks = c("Data", "Seasonally Adjusted", "Trend")
#   )

gas%>%
  model(classical_decomposition(Gas,type= "multiplicative"))%>%
  components()%>%
  ggplot(aes(x = Quarter)) +
  geom_line(aes(y = Gas, colour = "Data")) +
  geom_line(aes(y = season_adjust,
                colour = "Seasonally Adjusted")) +
  geom_line(aes(y = trend, colour = "Trend")) +
  labs(y = "Gas count in PJ",
       title = "Australian Gas Production") +
  scale_colour_manual(
    values = c("gray", "#0072B2", "#D55E00"),
    breaks = c("Data", "Seasonally Adjusted", "Trend")
  )

e.

Change one observation to be an outlier (e.g., add 300 to one observation), and recompute the seasonally adjusted data. What is the effect of the outlier?

rm(list = ls(pattern = "^fig"))
print(nrow(gas))
[1] 20
gas_begin_edit <- gas
gas_end_edit <- gas
gas_begin_edit$Gas[1] <- gas_begin_edit$Gas[10] + 300
gas_end_edit$Gas[20] <- gas_begin_edit$Gas[10] + 300

fig1<-gas_begin_edit%>%
  model(classical_decomposition(Gas,type= "multiplicative"))%>%
  components()%>%
  ggplot(aes(x = Quarter)) +
  geom_line(aes(y = Gas, colour = "Data")) +
  geom_line(aes(y = season_adjust,
                colour = "Seasonally Adjusted")) +
  geom_line(aes(y = trend, colour = "Trend")) +
  labs(y = "Gas count in PJ",
       title = "Australian Gas Production") +
  scale_colour_manual(
    values = c("gray", "#0072B2", "#D55E00"),
    breaks = c("Data", "Seasonally Adjusted", "Trend")
  )

fig2<-gas_end_edit%>%
  model(classical_decomposition(Gas,type= "multiplicative"))%>%
  components()%>%
  ggplot(aes(x = Quarter)) +
  geom_line(aes(y = Gas, colour = "Data")) +
  geom_line(aes(y = season_adjust,
                colour = "Seasonally Adjusted")) +
  geom_line(aes(y = trend, colour = "Trend")) +
  labs(y = "Gas count in PJ",
       title = "Australian Gas Production") +
  scale_colour_manual(
    values = c("gray", "#0072B2", "#D55E00"),
    breaks = c("Data", "Seasonally Adjusted", "Trend")
  )

plot_grid(fig1+labs(title = "Edit in the beginning"),
          fig2+labs(title = "Edit in the end"), nrow=2)
Warning: Removed 4 rows containing missing values (`geom_line()`).Warning: Removed 4 rows containing missing values (`geom_line()`).

It spikes the data

f.

Does it make any difference if the outlier is near the end rather than in the middle of the time series?

Just placement, but the effect is the same

3.8

Recall your retail time series data (from Exercise 7 in Section 2.10). Decompose the series using X-11. Does it reveal any outliers, or unusual features that you had not noticed previously?

As per 3.5 Methods used by official statistics agencies

#Example
# x11_dcmp <- us_retail_employment |>
#   model(x11 = X_13ARIMA_SEATS(Employed ~ x11())) |>
#   components()
# autoplot(x11_dcmp) +
#   labs(title =
#     "Decomposition of total US retail employment using X-11.")
set.seed(241)

myseries <- aus_retail %>%
  filter(`Series ID` == sample(aus_retail$`Series ID`,1))

x11_dcmp <- myseries %>%
  model(x11 = X_13ARIMA_SEATS(Turnover ~ x11())) %>%
  components()

autoplot(x11_dcmp) +
  labs(title =
    "Decomposition of total US retail employment using X-11.")

**I noted a long-term downward trend and greater volatility with the seasonal spikes

3.9

Figures 3.19 and 3.20 show the result of decomposing the number of persons in the civilian labour force in Australia each month from February 1978 to August 1995.

a.

Write about 3–5 sentences describing the results of the decomposition. Pay particular attention to the scales of the graphs in making your interpretation.

The trend is clearly a upward trend from 1978-1995, and what appears to be some seasonality. This makes sense to me as the spikes are common, with students leaving school for the holiday and summer, and seasonal work occurring throughout the year. I’m curious what caused the dip in 1992 which is a pretty clear outlier.

b.

Is the recession of 1991/1992 visible in the estimated components?

Very much. Its easily observed in the “remainder” plot.

LS0tDQp0aXRsZTogJ0RBVEEgNjI0OiBQUkVESUNUSVZFIEFOQUxZVElDUyBIVzInDQphdXRob3I6ICJHYWJyaWVsIENhbXBvcyINCmRhdGU6ICJMYXN0IGVkaXRlZCBgciBmb3JtYXQoU3lzLnRpbWUoKSwgJyVCICVkLCAlWScpYCINCm91dHB1dDoNCiAgaHRtbF9ub3RlYm9vazogZGVmYXVsdA0KICBnZW9tZXRyeTogbGVmdD0wLjVjbSxyaWdodD0wLjVjbSx0b3A9MWNtLGJvdHRvbT0yY20NCiAgaHRtbF9kb2N1bWVudDoNCiAgICBkZl9wcmludDogcGFnZWQNCiAgcGRmX2RvY3VtZW50Og0KICAgIGxhdGV4X2VuZ2luZTogeGVsYXRleA0KdXJsY29sb3I6IGJsdWUNCi0tLQ0KDQpgYGB7ciwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0NCmxpYnJhcnkoJ2ZwcDMnKQ0KbGlicmFyeSgndHNpYmJsZScpDQpsaWJyYXJ5KCdnZ3Bsb3QyJykNCmxpYnJhcnkoJ3JlYWRyJykNCmxpYnJhcnkoJ3pvbycpDQpsaWJyYXJ5KCdjb3dwbG90JykNCmxpYnJhcnkoJ2dnZm9ydGlmeScpDQpsaWJyYXJ5KCdncmlkRXh0cmEnKQ0KbGlicmFyeSgnbGF0ZXgyZXhwJykNCmxpYnJhcnkoJ3NlYXNvbmFsJykNCmBgYA0KDQoNCiMgSW5zdHVjdGlvbnMNCg0KRG8gZXhlcmNpc2VzIDMuMSwgMy4yLCAzLjMsIDMuNCwgMy41LCAzLjcsIDMuOCBhbmQgMy45IGZyb20gdGhlIG9ubGluZSBIeW5kbWFuIGJvb2suICBQbGVhc2UgaW5jbHVkZSB5b3VyIFJwdWJzIGxpbmsgYWxvbmcgd2l0aC5wZGYgZmlsZSBvZiB5b3VyIHJ1biBjb2RlDQoNCiMgMy4xDQoNCiMjIGkgDQoNCiAgQ29uc2lkZXIgdGhlIEdEUCBpbmZvcm1hdGlvbiBpbiBgZ2xvYmFsX2Vjb25vbXlgLiBQbG90IHRoZSBHRFAgcGVyIGNhcGl0YSBmb3IgZWFjaCBjb3VudHJ5IG92ZXIgdGltZS4gV2hpY2ggY291bnRyeSBoYXMgdGhlIGhpZ2hlc3QgR0RQIHBlciBjYXBpdGE/IA0KDQpgYGB7cn0NCg0KIyBnbG9iYWxfZWNvbm9teQ0KDQpgYGANCg0KDQoNCmBgYHtyLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQ0KDQojIGFkZCBHRFAgdG8gdGhlIERhdGEgZnJhbWUNCmdsb2JhbF9lY29ub215IDwtIGdsb2JhbF9lY29ub215ICU+JQ0KICBtdXRhdGUoR0RQX3Blcl9jYXBpdGEgPSBHRFAgLyBQb3B1bGF0aW9uKQ0KDQojIGdldCB0aGUgbWF4IHZhbHVlcyBlbnRpcmUgcm93IGZvciB0aGUgdGl0bGUNCm1heF9nZHBfcm93IDwtIGdsb2JhbF9lY29ub215W3doaWNoLm1heChnbG9iYWxfZWNvbm9teSRHRFBfcGVyX2NhcGl0YSksIF0NCg0KDQpnbG9iYWxfZWNvbm9teSAlPiUNCiAgYXV0b3Bsb3QoR0RQX3Blcl9jYXBpdGEsIHNob3cubGVnZW5kID0gRkFMU0UpICsNCiAgbGFicyh0aXRsZSA9IHBhc3RlKCJHRFAgcGVyIGNhcGl0YSBieSBDb3VudHJ5IHwgTWF4IEdEUDoiLCBtYXhfZ2RwX3JvdyRHRFBfcGVyX2NhcGl0YSwgImZvciIsIG1heF9nZHBfcm93JENvdW50cnksICIgaW4gIixtYXhfZ2RwX3JvdyRZZWFyKSwNCiAgICAgICB5ID0gIiRVUyIpDQoNCg0KYGBgDQoNCmBgYHtyLCB3YXJuaW5nPUZBTFNFfQ0KbmFfY250PC1zdW0oaXMubmEoZ2xvYmFsX2Vjb25vbXklPiUNCiAgICAgICAgZmlsdGVyKENvdW50cnk9PSJNb25hY28iKSU+JQ0KICAgICAgICAgIHNlbGVjdChHRFBfcGVyX2NhcGl0YSkpKQ0KDQoNCnBhc3RlKCJJbiB0aGUgZGF0ZSByYW5nZSBvZiAxOTYwIHRvIDIwMTcgTW9uYWNvIGhhcyBoYWQgIixuYV9jbnQsIiBOQSdzIikNCmBgYA0KDQojIyBpaQ0KDQpIb3cgaGFzIHRoaXMgY2hhbmdlZCBvdmVyIHRpbWU/DQoNCmBgYHtyfQ0KDQpnbG9iYWxfZWNvbm9teSA8LSBpbmRleF9ieShnbG9iYWxfZWNvbm9teSwgWWVhcikNCg0KIyBzdG9yZSBvbmx5IHJvd3Mgd2l0aCBtYXggZ2RwDQptYXhfZ2RwX2FubnVhbCA8LSBnbG9iYWxfZWNvbm9teSAlPiUNCiAgc2xpY2VfbWF4KEdEUF9wZXJfY2FwaXRhKSAlPiUNCiAgdW5ncm91cCgpDQoNCiMgcGxvdCBieSByb3dzIHNlbGVjdGVkDQpnZ3Bsb3QobWF4X2dkcF9hbm51YWwsIGFlcyh4ID0gWWVhciwgeSA9IEdEUF9wZXJfY2FwaXRhLCBjb2xvciA9IENvdW50cnkpKSArDQogIGdlb21fbGluZSgpICsNCiAgbGFicyh0aXRsZSA9ICJDb3VudHJ5IHdpdGggSGlnaGVzdCBHRFAgcGVyIFllYXIiLA0KICAgICAgIHggPSAiWWVhciIsDQogICAgICAgeSA9ICJHRFAiKSArDQogIHRoZW1lX21pbmltYWwoKQ0KYGBgDQpMb29rcyBsaWtlIEx1eGVtYm91cmcgaXMgdXNpbmcgdG9wIGluIEdEUCBtYWtpbmcgTW9uYWNvJ3MgMjAxNCBHRFAgDQoNCiMgMy4yDQoNCkZvciBlYWNoIG9mIHRoZSBmb2xsb3dpbmcgc2VyaWVzLCBtYWtlIGEgZ3JhcGggb2YgdGhlIGRhdGEuIElmIHRyYW5zZm9ybWluZyBzZWVtcyBhcHByb3ByaWF0ZSwgZG8gc28gYW5kIGRlc2NyaWJlIHRoZSBlZmZlY3QuDQoNCiMgaQ0KDQpVbml0ZWQgU3RhdGVzIGBHRFAgZnJvbSBnbG9iYWxfZWNvbm9teWAuDQoNClVzaW5nIEdEUCBwZXIgQ2FwaXRhIG1hZGUgdGhlIG1vc3Qgc2Vuc2UuIEl0IHdhcyBhbHJlYWR5IHRyYW5zZm9ybWVkIGJ5IHRoZSBhYm92ZSBtYW5pcHVsYXRpb25zLg0KDQpgYGB7cn0NCg0KZmlnMTwtZ2xvYmFsX2Vjb25vbXklPiUNCiAgZmlsdGVyKENvdW50cnk9PSJVbml0ZWQgU3RhdGVzIiklPiUNCiAgICBhdXRvcGxvdCgpKw0KICBsYWJzKHRpdGxlID0gIkdEUCBVUyIpDQoNCmZpZzI8LWdsb2JhbF9lY29ub215JT4lDQogIGZpbHRlcihDb3VudHJ5PT0iVW5pdGVkIFN0YXRlcyIpJT4lDQogICAgYXV0b3Bsb3QoR0RQX3Blcl9jYXBpdGEpKw0KICBsYWJzKHRpdGxlID0gIkdEUCBwZXIgQ2FwaXRhIFVTIikNCg0KcGxvdF9ncmlkKGZpZzEsDQogICAgICAgICAgZmlnMiwgbnJvdyA9IDEpDQoNCmBgYA0KDQoNCiMgaWkNCg0KU2xhdWdodGVyIG9mIFZpY3RvcmlhbiDigJxCdWxscywgYnVsbG9ja3MgYW5kIHN0ZWVyc+KAnSBpbiBgYXVzX2xpdmVzdG9ja2AuDQoNClRoZSBkYXRhIHNlZW1lZCBjbHV0dGVyLiBCeSBncm91cGluZyBpdCBieSBRdWFydGVyIHRoZSB2aXN1YWwgaXMgY2xlYXJlciBhbmQgdGhlIGluaXRpYWwgZGlwIGlzIGFwcGFyZW50Lg0KDQpgYGB7cn0NCmhlYWQoYXVzX2xpdmVzdG9jaykNCmBgYA0KDQoNCmBgYHtyfQ0KDQpmaWczIDwtIGF1c19saXZlc3RvY2sgJT4lDQogIGZpbHRlcihBbmltYWwgPT0gIkJ1bGxzLCBidWxsb2NrcyBhbmQgc3RlZXJzIikgJT4lDQogIHN1bW1hcmlzZShDb3VudCA9IHN1bShDb3VudCkpICU+JQ0KICBhdXRvcGxvdChzaG93LmxlZ2VuZD1GQUxTRSkNCg0KZmlnNCA8LSBhdXNfbGl2ZXN0b2NrICU+JQ0KICBmaWx0ZXIoQW5pbWFsID09ICJCdWxscywgYnVsbG9ja3MgYW5kIHN0ZWVycyIpICU+JQ0KICBtdXRhdGUoUXVhcnRlciA9IHllYXJxdWFydGVyKE1vbnRoKSkgJT4lDQogIGluZGV4X2J5KFF1YXJ0ZXIpICU+JQ0KICBzdW1tYXJpc2UoQ291bnQgPSBzdW0oQ291bnQpKSAlPiUNCiAgYXV0b3Bsb3QoQ291bnQsIHNob3cubGVnZW5kPUZBTFNFKQ0KDQpwbG90X2dyaWQoZmlnMywgZmlnNCwgbnJvdyA9IDEpDQoNCmBgYA0KDQoNCg0KIyBpaWkNCg0KVmljdG9yaWFuIEVsZWN0cmljaXR5IERlbWFuZCBmcm9tIGB2aWNfZWxlY2AuDQoNClRoaXMgd2FzIGEgbG90IG9mIGRhdGEgc28gZGVhbGVycyBjaG9pY2UsIGJ1dCB2aWV3aW5nIHRoZSBhbm51YWwgZGF0YSBpbiBhIHdlZWtseSBhbmQgbW9udGhseSBiYXNpcyBzaG93cyBhbiBpbml0aWFsIHNwaWtlIHRoZSBmaXJzdCB3ZWVrIGFuZCBtb250aCBmb3IgdGhlIHllYXIuDQoNCmBgYHtyfQ0KaGVhZCh2aWNfZWxlYykNCmBgYA0KDQpgYGB7cn0NCmZpZzU8LXZpY19lbGVjJT4lDQogICAgICAgIGF1dG9wbG90KERlbWFuZCkNCg0KZmlnNjwtdmljX2VsZWMlPiUNCiAgbXV0YXRlKFdlZWsgPSB5ZWFyd2VlayhUaW1lKSkgJT4lDQogIGluZGV4X2J5KFdlZWspICU+JQ0KICBzdW1tYXJpc2UoRGVtYW5kID0gc3VtKERlbWFuZCkpICU+JQ0KICBhdXRvcGxvdChEZW1hbmQsIHNob3cubGVnZW5kPUZBTFNFKQ0KDQpmaWc3PC12aWNfZWxlYyU+JQ0KICBtdXRhdGUoTW9udGggPSB5ZWFybW9udGgoVGltZSkpICU+JQ0KICBpbmRleF9ieShNb250aCkgJT4lDQogIHN1bW1hcmlzZShEZW1hbmQgPSBzdW0oRGVtYW5kKSkgJT4lDQogIGF1dG9wbG90KERlbWFuZCwgc2hvdy5sZWdlbmQ9RkFMU0UpDQoNCiMgZmlnNzwtdmljX2VsZWMlPiUNCiMgICBtdXRhdGUoRGF5ID0gYXMuRGF0ZShUaW1lKSkgJT4lDQojICAgZ3JvdXBfYnkoRGF5KSAlPiUNCiMgICBzdW1tYXJpc2UoRGVtYW5kID0gc3VtKERlbWFuZCkpICU+JQ0KIyAgIGF1dG9wbG90KERlbWFuZCwgc2hvdy5sZWdlbmQ9RkFMU0UpDQoNCnBsb3RfZ3JpZChmaWc1LA0KICAgICAgICAgIGZpZzYsDQogICAgICAgICAgZmlnNywgbnJvdyA9IDIpDQpgYGANCg0KDQojIGl2DQoNCkdhcyBwcm9kdWN0aW9uIGZyb20gYGF1c19wcm9kdWN0aW9uYC4NCg0KYGBge3J9DQoNCmhlYWQoYXVzX3Byb2R1Y3Rpb24pDQoNCmBgYA0KDQpJIHBsYXllZCB3aXRoIGFsbCBtZXRob2RzIGludHJvZHVjZWQgaW4gbWF0aGVtYXRpY2FsIHRyYW5zZm9ybWF0aW9ucyBjb25zaWRlcmluZyB0aGUgaGlnaCB2YXJpYWJpbGl0eSBiZXR3ZWVuIHRoZSBzdGFydCBhbmQgZW5kIG9mIHRoZSBkYXRhLCBpbiBhbiBhdHRlbXB0IHRvIHJlbW92ZSB2YXJpYWJpbGl0eS4NCg0KVGhhbiBJIGFwcGxpZWQgDQoqQm94LUNveCB0cmFuc2Zvcm1hdGlvbnM6Kg0KDQokd190PSBcQmlnZ2xceyBcZ2VuZnJhY3t9e317MHB0fXt9e2xvZyh5X3QpLFwgXCBcIFxsYW1iZGEgPSAwfXsgKHNpZ24oeV90KXx5X3R8XlxsYW1iZGEgLTEpL1xsYW1iZGEsXCBcICBcbGFtYmRhIFxuZTB9JA0KDQphcyBleHBsYWluZWQgaW4gWzMuMSB2aWRlb10oaHR0cHM6Ly95b3V0dS5iZS9WcC1MMXptc3Bzcz9zaT1Sc1BsTXRJODNEdEZJaDJWJnQ9Njg5KSBmb3IgdHJhbnNmb3JtYXRpb25zDQoNCmBgYHtyfQ0KI2V4YW1wbGUNCiMgZm9vZCB8Pg0KIyAgIGZlYXR1cmVzKFR1cm5vdmVyLCBmZWF0dXJlcyA9IGd1ZXJyZXJvKCkpDQoNCihhdXNfZ2FzX2xhbWJkYTwtYXVzX3Byb2R1Y3Rpb24lPiUNCiAgZmVhdHVyZXMoR2FzLCBmZWF0dXJlcyA9IGd1ZXJyZXJvKSU+JQ0KICAgcHVsbChsYW1iZGFfZ3VlcnJlcm8pKQ0KYGBgDQoNCmBgYHtyfQ0KDQpmaWc4IDwtIGF1c19wcm9kdWN0aW9uICU+JQ0KICBhdXRvcGxvdChHYXMpICsNCiAgbGFicyh0aXRsZSA9ICJPcmlnaW5hbCIpDQoNCiMgRGVmaW5lIGZpZzkNCmZpZzkgPC0gYXVzX3Byb2R1Y3Rpb24gJT4lDQogIGF1dG9wbG90KGxvZyhHYXMpKSArDQogIGxhYnModGl0bGUgPSBleHByZXNzaW9uKHBhc3RlKCJMb2cgR2FzICIsIGxhbWJkYSwgIj0gMCIpKSkNCg0KIyBEZWZpbmUgZmlnMTANCmZpZzEwIDwtIGF1c19wcm9kdWN0aW9uICU+JQ0KICBhdXRvcGxvdCgtMS9HYXMpICsNCiAgbGFicyh0aXRsZSA9ICJJbnZlcnNlIEdhcyIpDQoNCmZpZzExIDwtIGF1c19wcm9kdWN0aW9uJT4lDQogICAgICAgICAgYXV0b3Bsb3QoYm94X2NveChHYXMsYXVzX2dhc19sYW1iZGEpKQ0KDQpwbG90X2dyaWQoZmlnOCArDQogICAgICAgICAgICBsYWJzKHRpdGxlID0gIk9yaWdpbmFsIiksIA0KICAgICAgICAgIGZpZzkgKw0KICAgICAgICAgICAgbGFicyh0aXRsZSA9IGV4cHJlc3Npb24ocGFzdGUoIkxvZyBHYXMgIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxhbWJkYSwgIj0gMCIpKSksIA0KICAgICAgICAgIGZpZzEwICsNCiAgICAgICAgICAgIGxhYnModGl0bGUgPSBleHByZXNzaW9uKHBhc3RlKCJJbnZlcnNlIEdhcyAiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGFtYmRhLCAiPSAwIikpKSwNCiAgICAgICAgICBmaWcxMSArDQogICAgICAgICAgICBsYWJzKHRpdGxlID0gZXhwcmVzc2lvbihwYXN0ZSgiQm94LUNveCAiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGFtYmRhLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIiA9IDAuMTA5NTE3MSIpKSksDQogICAgICAgICAgbnJvdyA9IDIpDQoNCmBgYA0KDQoNCiMgMy4zDQoNCldoeSBpcyBhIEJveC1Db3ggdHJhbnNmb3JtYXRpb24gdW5oZWxwZnVsIGZvciB0aGUgYGNhbmFkaWFuX2dhc2AgZGF0YT8NCg0KYXMgcGVyIHRoZSBbMy4xIFZpZGVvXShodHRwczovL3lvdXR1LmJlL1ZwLUwxem1zcHNzP3NpPUJ0WC0yVEluZmN1S2pmYzAmdD03NDkpIGZvciB0cmFuc2Zvcm1hdGlvbnMuDQoNCkEgbG93IHZhbHVlIG9mICRcbGFtYmRhJCBjYW4gZ2l2ZSBleHRyZW1lbHkgbGFyZ2UgcHJlZGljdGlvbiBpbnRlcnZhbHMNCmFuZCBhcyB3ZSBzZWUgaW4gdGhlIHBsb3QgYmVsb3cgZG9lcyBub3QgZG8gbXVjaCBmb3IgdHJhbnNmb3JtYXRpb24uDQoNCmBgYHtyfQ0KaGVhZChjYW5hZGlhbl9nYXMpDQpgYGANCmBgYHtyfQ0KKGNhbmFkYV9nYXNfbGFtYmRhPC1jYW5hZGlhbl9nYXMlPiUNCiAgICBmZWF0dXJlcyhWb2x1bWUsIGZlYXR1cmVzID0gZ3VlcnJlcm8pJT4lDQogICAgcHVsbChsYW1iZGFfZ3VlcnJlcm8pDQopDQoNCmBgYA0KDQpgYGB7cn0NCmZpZzEyPC1jYW5hZGlhbl9nYXMlPiUNCiAgYXV0b3Bsb3QoVm9sdW1lKQ0KDQpmaWcxMzwtY2FuYWRpYW5fZ2FzJT4lDQogIGF1dG9wbG90KGJveF9jb3goVm9sdW1lLCBjYW5hZGFfZ2FzX2xhbWJkYSkpDQoNCnBsb3RfZ3JpZChmaWcxMitsYWJzKHRpdGxlID0gIk9yaWdpbmFsIiksDQogICAgICAgICAgZmlnMTMrbGFicyh0aXRsZSA9IGV4cHJlc3Npb24ocGFzdGUoIkJveC1Db3ggIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsYW1iZGEsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIiA9MC41NzY3NjQ4IikpKSkNCmBgYA0KDQpgYGB7cn0NCnJtKGxpc3QgPSBscyhwYXR0ZXJuID0gIl5maWciKSkNCmBgYA0KDQoNCiMgMy40DQoNCldoYXQgQm94LUNveCB0cmFuc2Zvcm1hdGlvbiB3b3VsZCB5b3Ugc2VsZWN0IGZvciB5b3VyIHJldGFpbCBkYXRhIChmcm9tIEV4ZXJjaXNlIDcgaW4gU2VjdGlvbiBbMi4xMF0oaHR0cHM6Ly9vdGV4dHMuY29tL2ZwcDMvZ3JhcGhpY3MtZXhlcmNpc2VzLmh0bWwjZ3JhcGhpY3MtZXhlcmNpc2VzKSk/DQoNCkkgd291bGQgcmVseSBvbiBgZmVhdHVyZXNgPWBndWVycmVyb2Agc2luY2UgaXRzIGRlc2lnbmVkIHRvIGJlIHRoZSBiZXN0IGZpdC4NCg0KYGBge3J9DQojIGRhdGEgcHJvdmlkZWQNCnNldC5zZWVkKDEyMykNCm15c2VyaWVzIDwtIGF1c19yZXRhaWwgfD4NCiAgZmlsdGVyKGBTZXJpZXMgSURgID09IHNhbXBsZShhdXNfcmV0YWlsJGBTZXJpZXMgSURgLDEpKQ0KaGVhZChteXNlcmllcykNCmBgYA0KDQpgYGB7cn0NCihteXNlcmllc19sYW1iZGEgPC0gbXlzZXJpZXMlPiUNCiAgICAgICAgZmVhdHVyZXMoVHVybm92ZXIsZmVhdHVyZXMgPSBndWVycmVybyklPiUNCiAgICAgICAgICBwdWxsKGxhbWJkYV9ndWVycmVybykpDQpgYGANCg0KYGBge3J9DQpmaWcxIDwtIG15c2VyaWVzJT4lDQogICAgICAgICAgYXV0b3Bsb3QoVHVybm92ZXIpDQoNCmZpZzIgPC0gbXlzZXJpZXMlPiUNCiAgICAgICAgYXV0b3Bsb3QoYm94X2NveChUdXJub3ZlcixteXNlcmllc19sYW1iZGEpKQ0KZmlnMjwtZmlnMit5bGFiKCJUdXJub3ZlciIpDQoNCnBsb3RfZ3JpZChmaWcxK2xhYnModGl0bGUgPSAiT3JpZ2luYWwiKSwNCiAgICAgICAgICBmaWcyK2xhYnModGl0bGUgPSBwYXN0ZSgiQm94LWNveCDOuyA9IixteXNlcmllc19sYW1iZGEpKSwgbnJvdz0yKQ0KYGBgDQoNCg0KIyAzLjUNCg0KRm9yIHRoZSBmb2xsb3dpbmcgc2VyaWVzLCBmaW5kIGFuIGFwcHJvcHJpYXRlIEJveC1Db3ggdHJhbnNmb3JtYXRpb24gaW4gb3JkZXIgdG8gc3RhYmlsaXplIHRoZSB2YXJpYW5jZS4gDQoNCiMgaQ0KDQpUb2JhY2NvIGZyb20gYGF1c19wcm9kdWN0aW9uYA0KDQpgYGB7cix3YXJuaW5nPUZBTFNFfQ0KYXVzX3Byb2R1Y3Rpb25fbGFtYmRhPC1hdXNfcHJvZHVjdGlvbiU+JQ0KICBmZWF0dXJlcyhUb2JhY2NvLGZlYXR1cmVzPWd1ZXJyZXJvKSU+JQ0KICBwdWxsKGxhbWJkYV9ndWVycmVybykNCg0KYXVzX3Byb2R1Y3Rpb24lPiUNCiAgYXV0b3Bsb3QoYm94X2NveChUb2JhY2NvLGF1c19wcm9kdWN0aW9uX2xhbWJkYSkpKw0KICBsYWJzKHRpdGxlID1wYXN0ZSgizrsgPSIsYXVzX3Byb2R1Y3Rpb25fbGFtYmRhKSx5bGFiPSIiICkNCmBgYA0KDQoNCiMgaWkgDQoNCkVjb25vbXkgY2xhc3MgcGFzc2VuZ2VycyBiZXR3ZWVuIE1lbGJvdXJuZSBhbmQgU3lkbmV5IGZyb20gYGFuc2V0dGANCg0KYGBge3J9DQpoZWFkKGFuc2V0dCkNCmBgYA0KDQoNCmBgYHtyLHdhcm5pbmc9RkFMU0V9DQphbnNldHRfbGFtYmRhPC1hbnNldHQlPiUNCiAgZmlsdGVyKENsYXNzPT0iRWNvbm9teSImIEFpcnBvcnRzPT0nTUVMLVNZRCcpJT4lDQogIGZlYXR1cmVzKFBhc3NlbmdlcnMsZmVhdHVyZXM9Z3VlcnJlcm8pJT4lDQogIHB1bGwobGFtYmRhX2d1ZXJyZXJvKQ0KDQphbnNldHQlPiUNCiAgZmlsdGVyKENsYXNzPT0iRWNvbm9teSImIEFpcnBvcnRzPT0nTUVMLVNZRCcpJT4lDQogIGF1dG9wbG90KGJveF9jb3goUGFzc2VuZ2VycyxhbnNldHRfbGFtYmRhKSkrDQogIGxhYnModGl0bGUgPXBhc3RlKCLOuyA9IixhbnNldHRfbGFtYmRhKSwgeT0iICIgKQ0KYGBgDQoNCiMgaWlpDQoNClBlZGVzdHJpYW4gY291bnRzIGF0IFNvdXRoZXJuIENyb3NzIFN0YXRpb24gZnJvbSBgcGVkZXN0cmlhbmAuDQoNCmBgYHtyfQ0KaGVhZChwZWRlc3RyaWFuKQ0KYGBgDQoNCmBgYHtyfQ0KcGVkZXN0cmlhbl9sYW1iZGE8LXBlZGVzdHJpYW4lPiUNCiAgZmlsdGVyKFNlbnNvcj09IlNvdXRoZXJuIENyb3NzIFN0YXRpb24iKSU+JQ0KICBmZWF0dXJlcyhDb3VudCxmZWF0dXJlcz1ndWVycmVybyklPiUNCiAgcHVsbChsYW1iZGFfZ3VlcnJlcm8pDQoNCnBlZGVzdHJpYW4lPiUNCiAgZmlsdGVyKFNlbnNvcj09IlNvdXRoZXJuIENyb3NzIFN0YXRpb24iKSU+JQ0KICBhdXRvcGxvdChib3hfY294KENvdW50LHBlZGVzdHJpYW5fbGFtYmRhKSkrDQogIGNvb3JkX2ZsaXAoKSsNCiAgbGFicyh0aXRsZSA9cGFzdGUoIs67ID0iLHBlZGVzdHJpYW5fbGFtYmRhKSx4ID0gIkRhdGUgKGhvdXJseSkiLA0KICAgICAgIHk9IkNvdW50IiApDQpgYGANCg0KDQojIDMuNw0KDQpDb25zaWRlciB0aGUgbGFzdCBmaXZlIHllYXJzIG9mIHRoZSBHYXMgZGF0YSBmcm9tIGBhdXNfcHJvZHVjdGlvbmAuDQoNCmBgYHtyfQ0KZ2FzIDwtIHRhaWwoYXVzX3Byb2R1Y3Rpb24sIDUqNCkgfD4gc2VsZWN0KEdhcykNCg0KaGVhZChnYXMpDQpgYGANCg0KIyBhLg0KDQpQbG90IHRoZSB0aW1lIHNlcmllcy4gQ2FuIHlvdSBpZGVudGlmeSBzZWFzb25hbCBmbHVjdHVhdGlvbnMgYW5kL29yIGEgdHJlbmQtY3ljbGU/DQoNCipMb29rcyBsaWtlIHRoZSB0cmVuZCBmcm9tIDIwMDYtMjAxMCBpcyB1cHdhcmRzLiBTZWFzb25hbGl0eSBpcyB0aGUgaGlnaCBldmVyeSAzcmQgcXVhcnRlciBhbmQgbG93IGV2ZXJ5IDFyc3QgUXVhcnRlcioNCg0KYGBge3J9DQpnYXMlPiUNCiAgYXV0b3Bsb3QoR2FzKQ0KYGBgDQoNCg0KIyBiLg0KDQpVc2UgYGNsYXNzaWNhbF9kZWNvbXBvc2l0aW9uYCB3aXRoIGB0eXBlPW11bHRpcGxpY2F0aXZlYCB0byBjYWxjdWxhdGUgdGhlIHRyZW5kLWN5Y2xlIGFuZCBzZWFzb25hbCBpbmRpY2VzLg0KDQpSZWYgWzMuNCB2aWRlb10oaHR0cHM6Ly95b3V0dS5iZS8xbGpfaEpCR2czQT9zaT1UdXBiOWFLQXRqYnBmZjAzJnQ9Mzk5KQ0KDQpgYGB7cn0NCiNleGFtcGxlDQojIHVzX3JldGFpbF9lbXBsb3ltZW50IHw+DQojICAgbW9kZWwoY2xhc3NpY2FsX2RlY29tcG9zaXRpb24oRW1wbG95ZWQsIHR5cGUgPSAiYWRkaXRpdmUiKSkgfD4NCiMgICBjb21wb25lbnRzKCl8Pg0KIyAgIGF1dG9wbG90KCkreGxhYigiWWVhciIpKw0KIyAgIGdndGl0bGUoIkNsYXNzaWNhbCBhZGRpdGl2ZSBkZWNvbXBvc2l0aW9uIG9mIHRvdGFsIFVTIHJldGFpbCBlbXBsb3ltZW50IikNCmBgYA0KDQpgYGB7ciwgd2FybmluZz1GQUxTRX0NCmdhcyU+JQ0KICBtb2RlbChjbGFzc2ljYWxfZGVjb21wb3NpdGlvbihHYXMsdHlwZT0gIm11bHRpcGxpY2F0aXZlIikpJT4lDQogIGNvbXBvbmVudHMoKSU+JQ0KICBhdXRvcGxvdCt4bGFiKCIiKQ0KYGBgDQoNCg0KIyBjLg0KDQpEbyB0aGUgcmVzdWx0cyBzdXBwb3J0IHRoZSBncmFwaGljYWwgaW50ZXJwcmV0YXRpb24gZnJvbSBwYXJ0IGE/DQoNCipUaGUgcmVzdWx0cyBzaG93IGEgcG9zaXRpdmUgdHJlbmQgd2l0aCBxdWFydGVybHkgc2Vhc29uYWxpdHkgc28geWVzIGl0IGRvZXMuKg0KDQojIGQuDQoNCkNvbXB1dGUgYW5kIHBsb3QgdGhlIHNlYXNvbmFsbHkgYWRqdXN0ZWQgZGF0YS4NCg0KQXMgc2hvd24gaW4gMy41DQoNCmBgYHtyfQ0KI0V4YW1wbGUNCiMgeDExX2RjbXAgfD4NCiMgICBnZ3Bsb3QoYWVzKHggPSBNb250aCkpICsNCiMgICBnZW9tX2xpbmUoYWVzKHkgPSBFbXBsb3llZCwgY29sb3VyID0gIkRhdGEiKSkgKw0KIyAgIGdlb21fbGluZShhZXMoeSA9IHNlYXNvbl9hZGp1c3QsDQojICAgICAgICAgICAgICAgICBjb2xvdXIgPSAiU2Vhc29uYWxseSBBZGp1c3RlZCIpKSArDQojICAgZ2VvbV9saW5lKGFlcyh5ID0gdHJlbmQsIGNvbG91ciA9ICJUcmVuZCIpKSArDQojICAgbGFicyh5ID0gIlBlcnNvbnMgKHRob3VzYW5kcykiLA0KIyAgICAgICAgdGl0bGUgPSAiVG90YWwgZW1wbG95bWVudCBpbiBVUyByZXRhaWwiKSArDQojICAgc2NhbGVfY29sb3VyX21hbnVhbCgNCiMgICAgIHZhbHVlcyA9IGMoImdyYXkiLCAiIzAwNzJCMiIsICIjRDU1RTAwIiksDQojICAgICBicmVha3MgPSBjKCJEYXRhIiwgIlNlYXNvbmFsbHkgQWRqdXN0ZWQiLCAiVHJlbmQiKQ0KIyAgICkNCg0KYGBgDQoNCmBgYHtyLCB3YXJuaW5nPUZBTFNFfQ0KDQpnYXMlPiUNCiAgbW9kZWwoY2xhc3NpY2FsX2RlY29tcG9zaXRpb24oR2FzLHR5cGU9ICJtdWx0aXBsaWNhdGl2ZSIpKSU+JQ0KICBjb21wb25lbnRzKCklPiUNCiAgZ2dwbG90KGFlcyh4ID0gUXVhcnRlcikpICsNCiAgZ2VvbV9saW5lKGFlcyh5ID0gR2FzLCBjb2xvdXIgPSAiRGF0YSIpKSArDQogIGdlb21fbGluZShhZXMoeSA9IHNlYXNvbl9hZGp1c3QsDQogICAgICAgICAgICAgICAgY29sb3VyID0gIlNlYXNvbmFsbHkgQWRqdXN0ZWQiKSkgKw0KICBnZW9tX2xpbmUoYWVzKHkgPSB0cmVuZCwgY29sb3VyID0gIlRyZW5kIikpICsNCiAgbGFicyh5ID0gIkdhcyBjb3VudCBpbiBQSiIsDQogICAgICAgdGl0bGUgPSAiQXVzdHJhbGlhbiBHYXMgUHJvZHVjdGlvbiIpICsNCiAgc2NhbGVfY29sb3VyX21hbnVhbCgNCiAgICB2YWx1ZXMgPSBjKCJncmF5IiwgIiMwMDcyQjIiLCAiI0Q1NUUwMCIpLA0KICAgIGJyZWFrcyA9IGMoIkRhdGEiLCAiU2Vhc29uYWxseSBBZGp1c3RlZCIsICJUcmVuZCIpDQogICkNCg0KYGBgDQoNCg0KIyBlLg0KDQpDaGFuZ2Ugb25lIG9ic2VydmF0aW9uIHRvIGJlIGFuIG91dGxpZXIgKGUuZy4sIGFkZCAzMDAgdG8gb25lIG9ic2VydmF0aW9uKSwgYW5kIHJlY29tcHV0ZSB0aGUgc2Vhc29uYWxseSBhZGp1c3RlZCBkYXRhLiBXaGF0IGlzIHRoZSBlZmZlY3Qgb2YgdGhlIG91dGxpZXI/DQoNCmBgYHtyfQ0Kcm0obGlzdCA9IGxzKHBhdHRlcm4gPSAiXmZpZyIpKQ0KYGBgDQoNCg0KYGBge3J9DQpwcmludChucm93KGdhcykpDQpgYGANCg0KDQpgYGB7cn0NCmdhc19iZWdpbl9lZGl0IDwtIGdhcw0KZ2FzX2VuZF9lZGl0IDwtIGdhcw0KZ2FzX2JlZ2luX2VkaXQkR2FzWzFdIDwtIGdhc19iZWdpbl9lZGl0JEdhc1sxMF0gKyAzMDANCmdhc19lbmRfZWRpdCRHYXNbMjBdIDwtIGdhc19iZWdpbl9lZGl0JEdhc1sxMF0gKyAzMDANCmBgYA0KDQpgYGB7cn0NCg0KZmlnMTwtZ2FzX2JlZ2luX2VkaXQlPiUNCiAgbW9kZWwoY2xhc3NpY2FsX2RlY29tcG9zaXRpb24oR2FzLHR5cGU9ICJtdWx0aXBsaWNhdGl2ZSIpKSU+JQ0KICBjb21wb25lbnRzKCklPiUNCiAgZ2dwbG90KGFlcyh4ID0gUXVhcnRlcikpICsNCiAgZ2VvbV9saW5lKGFlcyh5ID0gR2FzLCBjb2xvdXIgPSAiRGF0YSIpKSArDQogIGdlb21fbGluZShhZXMoeSA9IHNlYXNvbl9hZGp1c3QsDQogICAgICAgICAgICAgICAgY29sb3VyID0gIlNlYXNvbmFsbHkgQWRqdXN0ZWQiKSkgKw0KICBnZW9tX2xpbmUoYWVzKHkgPSB0cmVuZCwgY29sb3VyID0gIlRyZW5kIikpICsNCiAgbGFicyh5ID0gIkdhcyBjb3VudCBpbiBQSiIsDQogICAgICAgdGl0bGUgPSAiQXVzdHJhbGlhbiBHYXMgUHJvZHVjdGlvbiIpICsNCiAgc2NhbGVfY29sb3VyX21hbnVhbCgNCiAgICB2YWx1ZXMgPSBjKCJncmF5IiwgIiMwMDcyQjIiLCAiI0Q1NUUwMCIpLA0KICAgIGJyZWFrcyA9IGMoIkRhdGEiLCAiU2Vhc29uYWxseSBBZGp1c3RlZCIsICJUcmVuZCIpDQogICkNCg0KZmlnMjwtZ2FzX2VuZF9lZGl0JT4lDQogIG1vZGVsKGNsYXNzaWNhbF9kZWNvbXBvc2l0aW9uKEdhcyx0eXBlPSAibXVsdGlwbGljYXRpdmUiKSklPiUNCiAgY29tcG9uZW50cygpJT4lDQogIGdncGxvdChhZXMoeCA9IFF1YXJ0ZXIpKSArDQogIGdlb21fbGluZShhZXMoeSA9IEdhcywgY29sb3VyID0gIkRhdGEiKSkgKw0KICBnZW9tX2xpbmUoYWVzKHkgPSBzZWFzb25fYWRqdXN0LA0KICAgICAgICAgICAgICAgIGNvbG91ciA9ICJTZWFzb25hbGx5IEFkanVzdGVkIikpICsNCiAgZ2VvbV9saW5lKGFlcyh5ID0gdHJlbmQsIGNvbG91ciA9ICJUcmVuZCIpKSArDQogIGxhYnMoeSA9ICJHYXMgY291bnQgaW4gUEoiLA0KICAgICAgIHRpdGxlID0gIkF1c3RyYWxpYW4gR2FzIFByb2R1Y3Rpb24iKSArDQogIHNjYWxlX2NvbG91cl9tYW51YWwoDQogICAgdmFsdWVzID0gYygiZ3JheSIsICIjMDA3MkIyIiwgIiNENTVFMDAiKSwNCiAgICBicmVha3MgPSBjKCJEYXRhIiwgIlNlYXNvbmFsbHkgQWRqdXN0ZWQiLCAiVHJlbmQiKQ0KICApDQoNCnBsb3RfZ3JpZChmaWcxK2xhYnModGl0bGUgPSAiRWRpdCBpbiB0aGUgYmVnaW5uaW5nIiksDQogICAgICAgICAgZmlnMitsYWJzKHRpdGxlID0gIkVkaXQgaW4gdGhlIGVuZCIpLCBucm93PTIpDQoNCmBgYA0KDQoqSXQgc3Bpa2VzIHRoZSBkYXRhKg0KDQoNCiMgZi4NCg0KRG9lcyBpdCBtYWtlIGFueSBkaWZmZXJlbmNlIGlmIHRoZSBvdXRsaWVyIGlzIG5lYXIgdGhlIGVuZCByYXRoZXIgdGhhbiBpbiB0aGUgbWlkZGxlIG9mIHRoZSB0aW1lIHNlcmllcz8NCg0KKkp1c3QgcGxhY2VtZW50LCBidXQgdGhlIGVmZmVjdCBpcyB0aGUgc2FtZSoNCg0KIyAzLjgNCg0KUmVjYWxsIHlvdXIgcmV0YWlsIHRpbWUgc2VyaWVzIGRhdGEgKGZyb20gRXhlcmNpc2UgNyBpbiBTZWN0aW9uIDIuMTApLiBEZWNvbXBvc2UgdGhlIHNlcmllcyB1c2luZyBYLTExLiBEb2VzIGl0IHJldmVhbCBhbnkgb3V0bGllcnMsIG9yIHVudXN1YWwgZmVhdHVyZXMgdGhhdCB5b3UgaGFkIG5vdCBub3RpY2VkIHByZXZpb3VzbHk/DQoNCioqQXMgcGVyIDMuNSBNZXRob2RzIHVzZWQgYnkgb2ZmaWNpYWwgc3RhdGlzdGljcyBhZ2VuY2llcyoqDQoNCmBgYHtyfQ0KI0V4YW1wbGUNCiMgeDExX2RjbXAgPC0gdXNfcmV0YWlsX2VtcGxveW1lbnQgfD4NCiMgICBtb2RlbCh4MTEgPSBYXzEzQVJJTUFfU0VBVFMoRW1wbG95ZWQgfiB4MTEoKSkpIHw+DQojICAgY29tcG9uZW50cygpDQojIGF1dG9wbG90KHgxMV9kY21wKSArDQojICAgbGFicyh0aXRsZSA9DQojICAgICAiRGVjb21wb3NpdGlvbiBvZiB0b3RhbCBVUyByZXRhaWwgZW1wbG95bWVudCB1c2luZyBYLTExLiIpDQpgYGANCg0KDQpgYGB7cn0NCnNldC5zZWVkKDI0MSkNCg0KbXlzZXJpZXMgPC0gYXVzX3JldGFpbCAlPiUNCiAgZmlsdGVyKGBTZXJpZXMgSURgID09IHNhbXBsZShhdXNfcmV0YWlsJGBTZXJpZXMgSURgLDEpKQ0KDQp4MTFfZGNtcCA8LSBteXNlcmllcyAlPiUNCiAgbW9kZWwoeDExID0gWF8xM0FSSU1BX1NFQVRTKFR1cm5vdmVyIH4geDExKCkpKSAlPiUNCiAgY29tcG9uZW50cygpDQoNCmF1dG9wbG90KHgxMV9kY21wKSArDQogIGxhYnModGl0bGUgPQ0KICAgICJEZWNvbXBvc2l0aW9uIG9mIHRvdGFsIFVTIHJldGFpbCBlbXBsb3ltZW50IHVzaW5nIFgtMTEuIikNCmBgYA0KDQoqKkkgbm90ZWQgYSBsb25nLXRlcm0gZG93bndhcmQgdHJlbmQgYW5kIGdyZWF0ZXIgdm9sYXRpbGl0eSB3aXRoIHRoZSBzZWFzb25hbCBzcGlrZXMNCg0KIyAzLjkNCg0KRmlndXJlcyAzLjE5IGFuZCAzLjIwIHNob3cgdGhlIHJlc3VsdCBvZiBkZWNvbXBvc2luZyB0aGUgbnVtYmVyIG9mIHBlcnNvbnMgaW4gdGhlIGNpdmlsaWFuIGxhYm91ciBmb3JjZSBpbiBBdXN0cmFsaWEgZWFjaCBtb250aCBmcm9tIEZlYnJ1YXJ5IDE5NzggdG8gQXVndXN0IDE5OTUuDQoNCiFbXSguL0ltYWdlcy9JTUczXzE5LnBuZykNCg0KIVtdKC4vSW1hZ2VzL0lNRzNfMjAucG5nKQ0KDQojIGEuDQoNCldyaXRlIGFib3V0IDPigJM1IHNlbnRlbmNlcyBkZXNjcmliaW5nIHRoZSByZXN1bHRzIG9mIHRoZSBkZWNvbXBvc2l0aW9uLiBQYXkgcGFydGljdWxhciBhdHRlbnRpb24gdG8gdGhlIHNjYWxlcyBvZiB0aGUgZ3JhcGhzIGluIG1ha2luZyB5b3VyIGludGVycHJldGF0aW9uLg0KDQpUaGUgdHJlbmQgaXMgY2xlYXJseSBhIHVwd2FyZCB0cmVuZCBmcm9tIDE5NzgtMTk5NSwgYW5kIHdoYXQgYXBwZWFycyB0byBiZSBzb21lIHNlYXNvbmFsaXR5LiBUaGlzIG1ha2VzIHNlbnNlIHRvIG1lIGFzIHRoZSBzcGlrZXMgYXJlIGNvbW1vbiwgd2l0aCBzdHVkZW50cyBsZWF2aW5nIHNjaG9vbCBmb3IgdGhlIGhvbGlkYXkgYW5kIHN1bW1lciwgYW5kIHNlYXNvbmFsIHdvcmsgb2NjdXJyaW5nIHRocm91Z2hvdXQgdGhlIHllYXIuIEknbSBjdXJpb3VzIHdoYXQgY2F1c2VkIHRoZSBkaXAgaW4gMTk5MiB3aGljaCBpcyBhIHByZXR0eSBjbGVhciBvdXRsaWVyLg0KDQojIGIuDQoNCklzIHRoZSByZWNlc3Npb24gb2YgMTk5MS8xOTkyIHZpc2libGUgaW4gdGhlIGVzdGltYXRlZCBjb21wb25lbnRzPw0KDQpWZXJ5IG11Y2guIEl0cyBlYXNpbHkgb2JzZXJ2ZWQgaW4gdGhlICJyZW1haW5kZXIiIHBsb3Qu