1.
Consider the GDP information in data set called global_economy, which
is already embedded in fpp3 package (no need to upload externally)
1. Choose a random country by yourself. Then plot the GDP per capita
for this country over time? How GDP per capita has changed over time for
the series you chose? Explain briefly.
global_economy # see the data.
## # A tsibble: 15,150 x 9 [1Y]
## # Key: Country [263]
## Country Code Year GDP Growth CPI Imports Exports Population
## <fct> <fct> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 Afghanistan AFG 1960 537777811. NA NA 7.02 4.13 8996351
## 2 Afghanistan AFG 1961 548888896. NA NA 8.10 4.45 9166764
## 3 Afghanistan AFG 1962 546666678. NA NA 9.35 4.88 9345868
## 4 Afghanistan AFG 1963 751111191. NA NA 16.9 9.17 9533954
## 5 Afghanistan AFG 1964 800000044. NA NA 18.1 8.89 9731361
## 6 Afghanistan AFG 1965 1006666638. NA NA 21.4 11.3 9938414
## 7 Afghanistan AFG 1966 1399999967. NA NA 18.6 8.57 10152331
## 8 Afghanistan AFG 1967 1673333418. NA NA 14.2 6.77 10372630
## 9 Afghanistan AFG 1968 1373333367. NA NA 15.2 8.90 10604346
## 10 Afghanistan AFG 1969 1408888922. NA NA 15.0 10.1 10854428
## # ℹ 15,140 more rows
# 1.Answer:
global_economy %>%
filter(Country == "India") %>%
autoplot(GDP / Population)

#India's GDP per capita has seen significant growth over time, with some years experiencing a decline. However, the overall trend has been one of rapid growth
2.
For each of the following series, make a graph of the data. If
transforming seems appropriate, do so and describe the effect. Comment
below in answer:
2a. Use the series you chose in #1.
# 2a.Answer:
gdp <- global_economy %>%
filter(Country == "India")
#GDP Per Capita Income Plot
autoplot(gdp, GDP/Population)

#Log transformation
gdp <- gdp %>%
mutate(gdpPerCapita = GDP/Population, logGdp = log(gdpPerCapita))
#Log Transformation Plot
autoplot(gdp, logGdp)

gdp <- gdp %>%
mutate(difference = difference(logGdp))
autoplot(gdp, difference)
## Warning: Removed 1 row containing missing values or values outside the scale range
## (`geom_line()`).

#The data demonstrates an upward trend, signaling growth, while log transformation helps stabilize the values, and differencing eliminates the trends.
2b.
United States GDP from global_economy.
# 2b.Answer:
gdp <- global_economy %>%
filter(Country == "United States")
#GDP Per Capita Plot
autoplot(gdp, GDP/Population)

#Log transformation
gdp <- gdp %>%
mutate(gdpPerCapita = GDP/Population, logGdp = log(gdpPerCapita))
#Log transformation plot
autoplot(gdp, logGdp)

gdp <- gdp %>%
mutate(difference = difference(logGdp))
autoplot(gdp, difference)
## Warning: Removed 1 row containing missing values or values outside the scale range
## (`geom_line()`).

#By using the United States data, we can observe significant GDP growth, but applying a log transformation provides a clearer view of the trends.
2c.
Slaughter of Victorian “Bulls, bullocks and steers” in
aus_livestock
# 2c.Answer:
slVic <- aus_livestock %>%
filter(State == "Victoria", Animal == "Bulls, bullocks and steers")
#Plot
autoplot(slVic, Count)

#Log transformation
logSlVic <- slVic %>%
mutate(logC = log(Count))
#Plot
autoplot(logSlVic, logC)

2d.
Victorian Electricity Demand from vic_elec.
# 2d.Answer:
autoplot(vic_elec, Demand)

logVic <- vic_elec %>%
mutate(logD = log(Demand))
autoplot(logVic, logD)

2e.
Gas production from aus_production.
# 2e.Answer:
autoplot(aus_production, Gas)

logAusProd <- aus_production %>%
mutate(logG = log(Gas))
autoplot(logAusProd, logG)

3. Use the canadian_gas data (monthly Canadian gas production in
billions of cubic metres, January 1960 – February 2005).
2a. Plot the data using autoplot(), gg_subseries() , gg_season() to
look at the effect of the changing seasonality over time. Describe the
graphs in your own words. What do you see? What type pf pattern do you
observe?
# 3a.Answer:
autoplot(canadian_gas, Volume)

gg_subseries(canadian_gas, Volume)

gg_season(canadian_gas, Volume)

#The plots below clearly show a rapid increase overall, as well as on a monthly and seasonal basis.
3b.
Do an STL decomposition of the data. You will need to choose a
seasonal window to allow for the changing shape of the seasonal
component.
# 3b.Answer:
canadian_gas %>%
model(STL(Volume ~ season(window=12))) %>%
components() %>%
autoplot(Volume)

3c.
How does the seasonal shape change over time? [Hint: Try plotting the
seasonal component using gg_season().]
# 3c.Answer:
canadian_gas %>%
model(STL(Volume ~ season(window=12))) %>%
components() %>%
gg_season(Volume)

#Seasonally, we observe a decline in the summer and an increase in the winter.
3d.
produce a plausible seasonally adjusted series? What are these
numbers, plot the series.
# 3d.Answer:
canadian_gas %>%
model(STL(Volume ~ season(window = 12))) %>%
components() %>%
mutate(seasonally_adjusted = Volume - season_year) %>%
autoplot(seasonally_adjusted)

4.
For retail time series, use the below code:
# run the code
set.seed(12345678)
myseries <- aus_retail %>%
filter(`Series ID` == sample(aus_retail$`Series ID`,1))
4a.
Create a training dataset consisting of observations before 2011
myseries_train <- myseries %>%
filter(year(Month) < 2011)
4b.
Check that your data have been split appropriately by producing the
following plot.
autoplot(myseries, Turnover) +
autolayer(myseries_train, Turnover, colour = "red")

4c.
Fit a seasonal naïve model using SNAIVE() applied to your training
data (myseries_train).
#Answer:
fit <- myseries_train %>%
model(SNAIVE(Turnover))
fit
## # A mable: 1 x 3
## # Key: State, Industry [1]
## State Industry `SNAIVE(Turnover)`
## <chr> <chr> <model>
## 1 Northern Territory Clothing, footwear and personal accesso… <SNAIVE>
4d.
Check the residuals.
# 4d Answer:
# Do the residuals appear to be uncorrelated and normally distributed?
# Answ:
fit %>%
gg_tsresiduals()
## Warning: Removed 12 rows containing missing values or values outside the scale range
## (`geom_line()`).
## Warning: Removed 12 rows containing missing values or values outside the scale range
## (`geom_point()`).
## Warning: Removed 12 rows containing non-finite outside the scale range
## (`stat_bin()`).

#Yes, the residuals seem to be uncorrelated and follow a normal distribution. There is no obvious pattern, and their bell-shaped form is typical
4e.
Produce forecasts for the test data with given code below:
# 4e Answer:
fc <- fit %>%
forecast(new_data = anti_join(myseries, myseries_train))
## Joining with `by = join_by(State, Industry, `Series ID`, Month, Turnover)`
fc %>% autoplot(myseries)

Joining, by = c(“State”, “Industry”, “Series ID”, “Month”,
“Turnover”)
4f.
Compare the accuracy of your forecasts against the actual values with
given code below:
## # A tibble: 1 × 12
## State Industry .model .type ME RMSE MAE MPE MAPE MASE RMSSE ACF1
## <chr> <chr> <chr> <chr> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 Norther… Clothin… SNAIV… Trai… 0.439 1.21 0.915 5.23 12.4 1 1 0.768
fc %>% accuracy(myseries)
## # A tibble: 1 × 12
## .model State Industry .type ME RMSE MAE MPE MAPE MASE RMSSE ACF1
## <chr> <chr> <chr> <chr> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 SNAIVE(T… Nort… Clothin… Test 0.836 1.55 1.24 5.94 9.06 1.36 1.28 0.601
# 4f Answ:
fc <- fit %>%
forecast(new_data = anti_join(myseries, myseries_train, by = c("State", "Industry", "Series ID", "Month", "Turnover")))
fc %>%
autoplot(myseries)

train <- fit %>% accuracy()
test <- fc %>% accuracy(myseries)
train
## # A tibble: 1 × 12
## State Industry .model .type ME RMSE MAE MPE MAPE MASE RMSSE ACF1
## <chr> <chr> <chr> <chr> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 Norther… Clothin… SNAIV… Trai… 0.439 1.21 0.915 5.23 12.4 1 1 0.768
## # A tibble: 1 × 12
## .model State Industry .type ME RMSE MAE MPE MAPE MASE RMSSE ACF1
## <chr> <chr> <chr> <chr> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 SNAIVE(T… Nort… Clothin… Test 0.836 1.55 1.24 5.94 9.06 1.36 1.28 0.601
4g.
How sensitive are the accuracy measures to the amount of training
data used?
# 4g Answer:
#The accuracy metrics suggest that the model is sensitive to the training data, as it performs better on the training set than on the test set
5.
5a.
Create a training set for Australian takeaway food turnover
(aus_retail) by withholding the last four years as a test set.
# 5a.Answer:
aus_takeaway <- aus_retail %>%
filter(Industry == "Takeaway food services")
train_set <- aus_takeaway %>%
filter(year(Month) <= 2015)
test_set <- aus_takeaway %>%
filter(year(Month) > 2015)
5b.
Fit all the appropriate benchmark methods to the training set and
forecast the periods covered by the test set.
# 5b.Answer:
fit_benchmarks <- train_set %>%
model(
naive = NAIVE(Turnover),
snaive = SNAIVE(Turnover),
mean = MEAN(Turnover),
drift = RW(Turnover ~ drift())
)
fc_benchmarks <- fit_benchmarks %>%
forecast(data = test_set)
fc_benchmarks %>%
autoplot(aus_takeaway) +
autolayer(train_set) +
autolayer(test_set)
## Plot variable not specified, automatically selected `.vars = Turnover`
## Plot variable not specified, automatically selected `.vars = Turnover`

5c.
Compute the accuracy of your forecasts. Which method does best?
# 5c.Answer:
fc_benchmarks %>%
accuracy(test_set)
## # A tibble: 32 × 12
## .model State Industry .type ME RMSE MAE MPE MAPE MASE RMSSE
## <chr> <chr> <chr> <chr> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 drift Austr… Takeawa… Test 2.27 2.89 2.57 8.84 10.3 NaN NaN
## 2 drift New S… Takeawa… Test -11.1 38.1 29.8 -2.57 5.71 NaN NaN
## 3 drift North… Takeawa… Test -1.98 2.60 2.23 -11.0 12.1 NaN NaN
## 4 drift Queen… Takeawa… Test -30.7 35.3 31.3 -10.2 10.4 NaN NaN
## 5 drift South… Takeawa… Test -10.3 11.9 11.0 -11.9 12.6 NaN NaN
## 6 drift Tasma… Takeawa… Test 0.193 2.15 1.76 0.0342 6.25 NaN NaN
## 7 drift Victo… Takeawa… Test -34.8 41.8 36.7 -11.4 11.9 NaN NaN
## 8 drift Weste… Takeawa… Test 4.78 12.8 11.4 2.31 6.92 NaN NaN
## 9 mean Austr… Takeawa… Test 13.3 13.4 13.3 54.8 54.8 NaN NaN
## 10 mean New S… Takeawa… Test 320. 323. 320. 58.9 58.9 NaN NaN
## # ℹ 22 more rows
## # ℹ 1 more variable: ACF1 <dbl>
## # A fable: 768 x 6 [1M]
## # Key: State, Industry, .model [32]
## State Industry .model Month
## <chr> <chr> <chr> <mth>
## 1 Australian Capital Territory Takeaway food services naive 2016 Jan
## 2 Australian Capital Territory Takeaway food services naive 2016 Feb
## 3 Australian Capital Territory Takeaway food services naive 2016 Mar
## 4 Australian Capital Territory Takeaway food services naive 2016 Apr
## 5 Australian Capital Territory Takeaway food services naive 2016 May
## 6 Australian Capital Territory Takeaway food services naive 2016 Jun
## 7 Australian Capital Territory Takeaway food services naive 2016 Jul
## 8 Australian Capital Territory Takeaway food services naive 2016 Aug
## 9 Australian Capital Territory Takeaway food services naive 2016 Sep
## 10 Australian Capital Territory Takeaway food services naive 2016 Oct
## # ℹ 758 more rows
## # ℹ 2 more variables: Turnover <dist>, .mean <dbl>
#The Drift method performs the best, as it yields the lowest RMSE.
5d.
Do the residuals from the best method resemble white noise?
# 5d.Answer:
Drift_model <- train_set %>%
model(Drift = RW(Turnover ~ drift()))
residuals <- residuals(Drift_model) %>%
drop_na(.resid)
residual_values <- as.numeric(residuals$.resid)
acf_residuals <- ACF(residuals, .resid, lag_max = 20)
autoplot(acf_residuals)

hist(residual_values, breaks = 20)

qqnorm(residual_values)
qqline(residual_values)

6.
Using the code below, get a series (it gets a series randomly by
using sample() function):
set.seed(12345678)
myseries <- aus_retail %>%
filter(`Series ID` == sample(aus_retail$`Series ID`,1))
autoplot(myseries, Turnover)
see head of your series to check it is a tsibble data, and remove NA’s
if there is any with these commands:
## # A tsibble: 6 x 5 [1M]
## # Key: State, Industry [1]
## State Industry `Series ID` Month Turnover
## <chr> <chr> <chr> <mth> <dbl>
## 1 Northern Territory Clothing, footwear and perso… A3349767W 1988 Apr 2.3
## 2 Northern Territory Clothing, footwear and perso… A3349767W 1988 May 2.9
## 3 Northern Territory Clothing, footwear and perso… A3349767W 1988 Jun 2.6
## 4 Northern Territory Clothing, footwear and perso… A3349767W 1988 Jul 2.8
## 5 Northern Territory Clothing, footwear and perso… A3349767W 1988 Aug 2.9
## 6 Northern Territory Clothing, footwear and perso… A3349767W 1988 Sep 3
myseries = myseries %>% filter(!is.na(`Series ID`))
is_tsibble(myseries)
## [1] TRUE
6a.
What is the name of the series you randomly choose? Write it.
# 6a.Answer:
series <- unique(myseries$`Series ID`)
series
## [1] "A3349767W"
industry <- unique(myseries$Industry)
industry
## [1] "Clothing, footwear and personal accessory retailing"
6b.
Run a linear regression of Turnover on trend.(Hint: use TSLM() and
trend() functions)
# 6b.Answer:
Turnover_Trend_lr <- myseries %>%
model(TSLM(Turnover ~ trend()))
6c.
See the regression result by report() command.
# 6c.Answer:
report(Turnover_Trend_lr)
## Series: Turnover
## Model: TSLM
##
## Residuals:
## Min 1Q Median 3Q Max
## -4.0795 -1.1704 -0.1640 0.9683 7.4514
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 3.5313376 0.1983464 17.80 <2e-16 ***
## trend() 0.0307747 0.0009291 33.12 <2e-16 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 1.901 on 367 degrees of freedom
## Multiple R-squared: 0.7493, Adjusted R-squared: 0.7486
## F-statistic: 1097 on 1 and 367 DF, p-value: < 2.22e-16
6d.
By using this model, forecast it for the next 3 years. What are the
values of the next 3 years, monthly values?
# 6d.Answer:
forecast_th <- Turnover_Trend_lr %>%
forecast(h = "3 years")
forecast_th %>%
as_tibble() %>%
select(Month, .mean)
## # A tibble: 36 × 2
## Month .mean
## <mth> <dbl>
## 1 2019 Jan 14.9
## 2 2019 Feb 14.9
## 3 2019 Mar 15.0
## 4 2019 Apr 15.0
## 5 2019 May 15.0
## 6 2019 Jun 15.1
## 7 2019 Jul 15.1
## 8 2019 Aug 15.1
## 9 2019 Sep 15.2
## 10 2019 Oct 15.2
## # ℹ 26 more rows
## # A fable: 36 x 6 [1M]
## # Key: State, Industry, .model [1]
## State Industry .model Month
## <chr> <chr> <chr> <mth>
## 1 Northern Territory Clothing, footwear and personal accessory… TSLM(… 2019 Jan
## 2 Northern Territory Clothing, footwear and personal accessory… TSLM(… 2019 Feb
## 3 Northern Territory Clothing, footwear and personal accessory… TSLM(… 2019 Mar
## 4 Northern Territory Clothing, footwear and personal accessory… TSLM(… 2019 Apr
## 5 Northern Territory Clothing, footwear and personal accessory… TSLM(… 2019 May
## 6 Northern Territory Clothing, footwear and personal accessory… TSLM(… 2019 Jun
## 7 Northern Territory Clothing, footwear and personal accessory… TSLM(… 2019 Jul
## 8 Northern Territory Clothing, footwear and personal accessory… TSLM(… 2019 Aug
## 9 Northern Territory Clothing, footwear and personal accessory… TSLM(… 2019 Sep
## 10 Northern Territory Clothing, footwear and personal accessory… TSLM(… 2019 Oct
## # ℹ 26 more rows
## # ℹ 2 more variables: Turnover <dist>, .mean <dbl>
6d.
Plot the forecast values along with the original data.
# 6d.Answer:
autoplot(myseries, Turnover) +
autolayer(forecast_th, .mean, color = "blue")

6e.
Get the residuals from the model. And check the residuals to check
whether or not it satisfies the requirements for white noise error
terms.(hint: augment() and gg_tsresiduals() functions)
# 6e.Answer:
residuals <- augment(Turnover_Trend_lr)
gg_tsresiduals(Turnover_Trend_lr)

7.
Half-hourly electricity demand for Victoria, Australia is contained
in vic_elec. Extract the January 2014 electricity demand, and aggregate
this data to daily with daily total demands and maximum temperatures.
Run the code below:
jan_vic_elec <- vic_elec %>%
filter(yearmonth(Time) == yearmonth("2014 Jan")) %>%
index_by(Date = as_date(Time)) %>%
summarise(Demand = sum(Demand), Temperature = max(Temperature))
7a.
Plot the data and find the regression model for Demand with
temperature as a predictor variable. Why is there a positive
relationship?
# 7a.Answer:
library(ggplot2)
ggplot(jan_vic_elec, aes(x = Temperature, y = Demand)) +
geom_point()

demand_ml <- lm(Demand ~ Temperature, data = jan_vic_elec)
summary(demand_ml)
##
## Call:
## lm(formula = Demand ~ Temperature, data = jan_vic_elec)
##
## Residuals:
## Min 1Q Median 3Q Max
## -49978 -10219 -121 18533 35441
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 59083.9 17424.8 3.391 0.00203 **
## Temperature 6154.3 601.3 10.235 3.89e-11 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 24540 on 29 degrees of freedom
## Multiple R-squared: 0.7832, Adjusted R-squared: 0.7757
## F-statistic: 104.7 on 1 and 29 DF, p-value: 3.89e-11
7b.
Produce a residual plot. Is the model adequate? Are there any
outliers or influential observations?
# 7b.Answer:
library(broom)
## Warning: package 'broom' was built under R version 4.3.3
demand_ml <- lm(Demand ~ Temperature, data = jan_vic_elec)
residual_pl <- augment(demand_ml, data = jan_vic_elec)
ggplot(residual_pl, aes(x = Temperature, y = .resid)) +
geom_point()

7c.
Use the model to forecast the electricity demand that you would
expect for the next day if the maximum temperature was 15∘C and compare
it with the forecast if the with maximum temperature was 35∘C. Do you
believe these forecasts?
# 7c.Answer:
demand_ml <- lm(Demand ~ Temperature, data = jan_vic_elec)
next_day <- data.frame(Temperature = c(15, 35))
forecast <- predict(demand_ml, newdata = next_day)
forecast <- data.frame(
Temperature = c(15, 35),
Forecasted_Demand = forecast
)
forecast
## Temperature Forecasted_Demand
## 1 15 151398.4
## 2 35 274484.2
7d.
Do you believe these forecasts? The following R code will get you
started:
jan_vic_elec %>%
model(TSLM(Demand ~ Temperature)) %>%
forecast(
new_data(jan_vic_elec, 1) %>%
mutate(Temperature = 15)
) %>%
autoplot(jan_vic_elec)

# 7d.Answer:
jan_vic_elec %>%
model(TSLM(Demand ~ Temperature)) %>%
forecast(
new_data(jan_vic_elec, 1) %>%
mutate(Temperature = 15)
) %>%
autoplot(jan_vic_elec)

forecast_2 <- jan_vic_elec %>%
model(TSLM(Demand ~ Temperature)) %>%
forecast(
new_data = new_data(jan_vic_elec, 1) %>%
mutate(Temperature = 15)
)
forecast_3 <- jan_vic_elec %>%
model(TSLM(Demand ~ Temperature)) %>%
forecast(
new_data = new_data(jan_vic_elec, 1) %>%
mutate(Temperature = 35)
)
autoplot(jan_vic_elec, Demand) +
autolayer(forecast_2, .mean) +
autolayer(forecast_3, .mean)
## Scale for colour_ramp is already present.
## Adding another scale for colour_ramp, which will replace the existing scale.

#I believe the forecasts show that higher temperatures drive up power demand, but other factors such as the day of the week, seasonality, and humidity also play a significant role in influencing power consumption.
7e.
Give prediction intervals for your forecasts.
# 7e.Answer:
forecast_2 <- jan_vic_elec %>%
model(TSLM(Demand ~ Temperature)) %>%
forecast(
new_data = new_data(jan_vic_elec, 1) %>%
mutate(Temperature = 15),
PI = TRUE
)
forecast_3 <- jan_vic_elec %>%
model(TSLM(Demand ~ Temperature)) %>%
forecast(
new_data = new_data(jan_vic_elec, 1) %>%
mutate(Temperature = 35),
PI = TRUE
)
autoplot(jan_vic_elec, Demand) +
autolayer(forecast_2, .mean,PI = TRUE) +
autolayer(forecast_3, .mean,PI = TRUE)
## Warning in ggdist::geom_interval(intvl_mapping, data =
## dist_qi_frame(object[single_row[["TRUE"]], : Ignoring unknown parameters: `PI`
## Warning in ggplot2::geom_point(mapping = without(mapping, "linetype"), data =
## unpack_data(object[single_row[["TRUE"]], : Ignoring unknown parameters: `PI`
## Warning in ggdist::geom_interval(intvl_mapping, data =
## dist_qi_frame(object[single_row[["TRUE"]], : Ignoring unknown parameters: `PI`
## Warning in ggplot2::geom_point(mapping = without(mapping, "linetype"), data =
## unpack_data(object[single_row[["TRUE"]], : Ignoring unknown parameters: `PI`
## Scale for colour_ramp is already present.
## Adding another scale for colour_ramp, which will replace the existing scale.

#The prediction intervals represent the expected range of demand, where wider intervals indicate greater uncertainty and narrower intervals suggest higher confidence in the forecasts.
8.
Read the shampoo data given in excel (Import Dataset as Excel)
#a. View the shampoo sales data. How many variables are there? Find how many rows and columns in the data?
library(readxl)
## Warning: package 'readxl' was built under R version 4.3.3
shampoo_2 <- read_excel("shampoo-2.xlsx")
View(shampoo_2)
nrow(shampoo_2)
## [1] 36
## [1] 2
#There are 36 rows and 2 columns in the data
#b. Is the data annual, monthly, quarterly?
#After initial analysis, we can observe that the data is monthly
#c. Convert the data into tibble , then tsibble
shampoo_data <- as_tibble(shampoo_2)
shampoo_tsibble <- shampoo_data %>%
mutate(Date = yearmonth(Month)) %>%
as_tsibble(index = Date)
shampoo_tsibble
## # A tsibble: 36 x 3 [1M]
## Month sales Date
## <dttm> <dbl> <mth>
## 1 1995-01-01 00:00:00 266 1995 Jan
## 2 1995-02-01 00:00:00 146. 1995 Feb
## 3 1995-03-01 00:00:00 183. 1995 Mar
## 4 1995-04-01 00:00:00 119. 1995 Apr
## 5 1995-05-01 00:00:00 180. 1995 May
## 6 1995-06-01 00:00:00 168. 1995 Jun
## 7 1995-07-01 00:00:00 232. 1995 Jul
## 8 1995-08-01 00:00:00 224. 1995 Aug
## 9 1995-09-01 00:00:00 193. 1995 Sep
## 10 1995-10-01 00:00:00 123. 1995 Oct
## # ℹ 26 more rows
#d. Plot the shampoo sales. What do you see from the data pattern? What does x-axis represent?
plot(shampoo_tsibble$Date, shampoo_tsibble$sales,
xlab = "Date",
ylab = "Shampoo Sales",
main = "Shampoo Sales")

autoplot(shampoo_tsibble, sales) +
labs(title = "Shampoo Sales",
y = "Shampoo Sales",
x = "Date")

# Comment here. Use plot() and autoplot().Put the name for y axis, and a title for the graph.
#e. What is the average, and median of shampoo sales. Put it on a histogram.
average <- mean(shampoo_tsibble$sales)
median <- median(shampoo_tsibble$sales)
hist(shampoo_tsibble$sales)
abline(v = average, col = "red", lwd = 2, lty = 2)
abline(v = median, col = "blue", lwd = 2, lty = 2)

#f. Get seasonal plot. What do you see/ is there any pattern, is tehre any seasonality.
gg_season(shampoo_tsibble, sales) +
labs(title = "Seasonal Plot of Shampoo Sales",
x = "Date",
y = "Shampoo Sales")

#g. Get a linear regression line with trend and dummy for each month (Hint: use trend and season in regression equation).
shampoo_ml <- shampoo_tsibble %>%
model(TSLM(sales ~ trend() + season()))
#h. Comment on each estimated coefficient of the model.Are they statistically significant at 5 % significance level?
report(shampoo_ml)
## Series: sales
## Model: TSLM
##
## Residuals:
## Min 1Q Median 3Q Max
## -129.60 -62.32 -4.84 53.76 152.72
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 113.867 55.740 2.043 0.0527 .
## trend() 11.754 1.534 7.664 8.88e-08 ***
## season()year2 -33.154 73.630 -0.450 0.6567
## season()year3 -53.808 73.678 -0.730 0.4726
## season()year4 -24.628 73.757 -0.334 0.7415
## season()year5 -56.015 73.869 -0.758 0.4560
## season()year6 -27.802 74.012 -0.376 0.7106
## season()year7 7.244 74.187 0.098 0.9231
## season()year8 -37.043 74.393 -0.498 0.6233
## season()year9 27.536 74.629 0.369 0.7155
## season()year10 -32.518 74.897 -0.434 0.6682
## season()year11 9.895 75.194 0.132 0.8964
## season()year12 -4.259 75.522 -0.056 0.9555
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 90.16 on 23 degrees of freedom
## Multiple R-squared: 0.7592, Adjusted R-squared: 0.6336
## F-statistic: 6.043 on 12 and 23 DF, p-value: 0.00011612
#i. Which month has the highest sales?
Sales_Highest <- shampoo_tsibble %>%
filter(sales == max(sales))
Sales_Highest
## # A tsibble: 1 x 3 [1M]
## Month sales Date
## <dttm> <dbl> <mth>
## 1 1997-09-01 00:00:00 682 1997 Sep
#j. Forecast it for the next year. What are the values
forecast <- shampoo_tsibble %>%
model(TSLM(sales ~ trend() + season())) %>%
forecast(h = "1 year")
forecast %>%
as_tibble() %>%
select(Date, .mean)
## # A tibble: 12 × 2
## Date .mean
## <mth> <dbl>
## 1 1998 Jan 549.
## 2 1998 Feb 527.
## 3 1998 Mar 518.
## 4 1998 Apr 559.
## 5 1998 May 540.
## 6 1998 Jun 580.
## 7 1998 Jul 627.
## 8 1998 Aug 594.
## 9 1998 Sep 670.
## 10 1998 Oct 622.
## 11 1998 Nov 676.
## 12 1998 Dec 674.
#k. Plot the forecast with original data.
autoplot(shampoo_tsibble, sales) +
autolayer(forecast, .mean, colour = "blue") +
labs(title = "Forecast for Next Year",
x = "Date",
y = "Shampoo Sales")

#l. Check if the residuals of the model is white noise.
shampoo_ml <- shampoo_tsibble %>%
model(TSLM(sales ~ trend() + season()))
residuals <- augment(shampoo_ml)
gg_tsresiduals(shampoo_ml)

#m. By using the regression model, forecast the 1 year ahead, and then check the accuracy of the forecast. What is MSE, RMSE values?
forecast <- shampoo_tsibble %>%
model(TSLM(sales ~ trend() + season())) %>%
forecast(h = "1 year")
forecast %>%
as_tibble() %>%
select(Date, .mean)
## # A tibble: 12 × 2
## Date .mean
## <mth> <dbl>
## 1 1998 Jan 549.
## 2 1998 Feb 527.
## 3 1998 Mar 518.
## 4 1998 Apr 559.
## 5 1998 May 540.
## 6 1998 Jun 580.
## 7 1998 Jul 627.
## 8 1998 Aug 594.
## 9 1998 Sep 670.
## 10 1998 Oct 622.
## 11 1998 Nov 676.
## 12 1998 Dec 674.
## # A fable: 12 x 4 [1M]
## # Key: .model [1]
## .model Date
## <chr> <mth>
## 1 TSLM(sales ~ trend() + season()) 1998 Jan
## 2 TSLM(sales ~ trend() + season()) 1998 Feb
## 3 TSLM(sales ~ trend() + season()) 1998 Mar
## 4 TSLM(sales ~ trend() + season()) 1998 Apr
## 5 TSLM(sales ~ trend() + season()) 1998 May
## 6 TSLM(sales ~ trend() + season()) 1998 Jun
## 7 TSLM(sales ~ trend() + season()) 1998 Jul
## 8 TSLM(sales ~ trend() + season()) 1998 Aug
## 9 TSLM(sales ~ trend() + season()) 1998 Sep
## 10 TSLM(sales ~ trend() + season()) 1998 Oct
## 11 TSLM(sales ~ trend() + season()) 1998 Nov
## 12 TSLM(sales ~ trend() + season()) 1998 Dec
## # ℹ 2 more variables: sales <dist>, .mean <dbl>
LS0tDQp0aXRsZTogIkVDT04gNjYzNSAtIEVYQU0gSSBTcHJpbmcgMjAyNSAiDQphdXRob3I6IE5hZ2EgS2Fsa2kgTWFub2hhciBLYW50aW1haGFudGksIG5rYW50NEB1bmgubmV3aGF2ZW4uZWR1DQpkYXRlOiAiYHIgU3lzLkRhdGUoKWAiDQpvdXRwdXQ6IG9wZW5pbnRybzo6bGFiX3JlcG9ydA0KICANCi0tLQ0KDQpgYGB7ciBzZXR1cCwgaW5jbHVkZT1GQUxTRX0NCmtuaXRyOjpvcHRzX2NodW5rJHNldChlY2hvID0gVFJVRSkNCmxpYnJhcnkoZnBwMykNCmxpYnJhcnkodGlkeXZlcnNlKQ0KU3lzLnRpbWUoKQ0KDQpgYGANCg0KDQpgYGB7cn0NCg0KYGBgDQoNCiMjIyAxLgkNCkNvbnNpZGVyIHRoZSBHRFAgaW5mb3JtYXRpb24gaW4gZGF0YSBzZXQgY2FsbGVkIGdsb2JhbF9lY29ub215LCB3aGljaCBpcyBhbHJlYWR5IGVtYmVkZGVkIGluIGZwcDMgcGFja2FnZSAobm8gbmVlZCB0byB1cGxvYWQgZXh0ZXJuYWxseSkgDQoNCiMjIyAxLglDaG9vc2UgYSByYW5kb20gY291bnRyeSBieSB5b3Vyc2VsZi4gVGhlbiBwbG90IHRoZSBHRFAgcGVyIGNhcGl0YSBmb3IgdGhpcyBjb3VudHJ5IG92ZXIgdGltZT8gSG93IEdEUCBwZXIgY2FwaXRhIGhhcyBjaGFuZ2VkIG92ZXIgdGltZSBmb3IgdGhlIHNlcmllcyB5b3UgY2hvc2U/IEV4cGxhaW4gYnJpZWZseS4NCg0KYGBge3J9DQpnbG9iYWxfZWNvbm9teSAjIHNlZSB0aGUgZGF0YS4NCg0KDQojIDEuQW5zd2VyOg0KDQpnbG9iYWxfZWNvbm9teSAlPiUNCiAgZmlsdGVyKENvdW50cnkgPT0gIkluZGlhIikgJT4lDQogIGF1dG9wbG90KEdEUCAvIFBvcHVsYXRpb24pDQoNCiNJbmRpYSdzIEdEUCBwZXIgY2FwaXRhIGhhcyBzZWVuIHNpZ25pZmljYW50IGdyb3d0aCBvdmVyIHRpbWUsIHdpdGggc29tZSB5ZWFycyBleHBlcmllbmNpbmcgYSBkZWNsaW5lLiBIb3dldmVyLCB0aGUgb3ZlcmFsbCB0cmVuZCBoYXMgYmVlbiBvbmUgb2YgcmFwaWQgZ3Jvd3RoDQoNCg0KYGBgDQoNCiMjIyAyLgkNCkZvciBlYWNoIG9mIHRoZSBmb2xsb3dpbmcgc2VyaWVzLCBtYWtlIGEgZ3JhcGggb2YgdGhlIGRhdGEuIElmIHRyYW5zZm9ybWluZyBzZWVtcyBhcHByb3ByaWF0ZSwgZG8gc28gYW5kIGRlc2NyaWJlIHRoZSBlZmZlY3QuIENvbW1lbnQgYmVsb3cgaW4gYW5zd2VyOg0KDQojIyMgMmEuIFVzZSB0aGUgc2VyaWVzIHlvdSBjaG9zZSBpbiAjMS4NCmBgYHtyfQ0KDQojIDJhLkFuc3dlcjoNCmdkcCA8LSBnbG9iYWxfZWNvbm9teSAlPiUNCiAgZmlsdGVyKENvdW50cnkgPT0gIkluZGlhIikNCg0KI0dEUCBQZXIgQ2FwaXRhIEluY29tZSBQbG90DQphdXRvcGxvdChnZHAsIEdEUC9Qb3B1bGF0aW9uKQ0KDQojTG9nIHRyYW5zZm9ybWF0aW9uDQpnZHAgPC0gZ2RwICU+JQ0KICBtdXRhdGUoZ2RwUGVyQ2FwaXRhID0gR0RQL1BvcHVsYXRpb24sIGxvZ0dkcCA9IGxvZyhnZHBQZXJDYXBpdGEpKQ0KDQojTG9nIFRyYW5zZm9ybWF0aW9uIFBsb3QNCmF1dG9wbG90KGdkcCwgbG9nR2RwKQ0KDQpnZHAgPC0gZ2RwICU+JQ0KICBtdXRhdGUoZGlmZmVyZW5jZSA9IGRpZmZlcmVuY2UobG9nR2RwKSkNCg0KYXV0b3Bsb3QoZ2RwLCBkaWZmZXJlbmNlKQ0KDQojVGhlIGRhdGEgZGVtb25zdHJhdGVzIGFuIHVwd2FyZCB0cmVuZCwgc2lnbmFsaW5nIGdyb3d0aCwgd2hpbGUgbG9nIHRyYW5zZm9ybWF0aW9uIGhlbHBzIHN0YWJpbGl6ZSB0aGUgdmFsdWVzLCBhbmQgZGlmZmVyZW5jaW5nIGVsaW1pbmF0ZXMgdGhlIHRyZW5kcy4NCmBgYA0KDQojIyMgMmIuCQ0KVW5pdGVkIFN0YXRlcyBHRFAgZnJvbSBnbG9iYWxfZWNvbm9teS4NCmBgYHtyfQ0KDQoNCiMgMmIuQW5zd2VyOg0KZ2RwIDwtIGdsb2JhbF9lY29ub215ICU+JQ0KICBmaWx0ZXIoQ291bnRyeSA9PSAiVW5pdGVkIFN0YXRlcyIpDQoNCiNHRFAgUGVyIENhcGl0YSBQbG90DQphdXRvcGxvdChnZHAsIEdEUC9Qb3B1bGF0aW9uKQ0KDQojTG9nIHRyYW5zZm9ybWF0aW9uDQpnZHAgPC0gZ2RwICU+JQ0KICBtdXRhdGUoZ2RwUGVyQ2FwaXRhID0gR0RQL1BvcHVsYXRpb24sIGxvZ0dkcCA9IGxvZyhnZHBQZXJDYXBpdGEpKQ0KDQojTG9nIHRyYW5zZm9ybWF0aW9uIHBsb3QNCmF1dG9wbG90KGdkcCwgbG9nR2RwKQ0KDQpnZHAgPC0gZ2RwICU+JQ0KICBtdXRhdGUoZGlmZmVyZW5jZSA9IGRpZmZlcmVuY2UobG9nR2RwKSkNCg0KYXV0b3Bsb3QoZ2RwLCBkaWZmZXJlbmNlKQ0KDQojQnkgdXNpbmcgdGhlIFVuaXRlZCBTdGF0ZXMgZGF0YSwgd2UgY2FuIG9ic2VydmUgc2lnbmlmaWNhbnQgR0RQIGdyb3d0aCwgYnV0IGFwcGx5aW5nIGEgbG9nIHRyYW5zZm9ybWF0aW9uIHByb3ZpZGVzIGEgY2xlYXJlciB2aWV3IG9mIHRoZSB0cmVuZHMuDQoNCmBgYA0KDQojIyMgMmMuCQ0KU2xhdWdodGVyIG9mIFZpY3RvcmlhbiDigJxCdWxscywgYnVsbG9ja3MgYW5kIHN0ZWVyc+KAnSBpbiBhdXNfbGl2ZXN0b2NrDQpgYGB7cn0NCg0KIyAyYy5BbnN3ZXI6DQpzbFZpYyA8LSBhdXNfbGl2ZXN0b2NrICU+JQ0KICBmaWx0ZXIoU3RhdGUgPT0gIlZpY3RvcmlhIiwgQW5pbWFsID09ICJCdWxscywgYnVsbG9ja3MgYW5kIHN0ZWVycyIpDQoNCiNQbG90DQphdXRvcGxvdChzbFZpYywgQ291bnQpDQoNCiNMb2cgdHJhbnNmb3JtYXRpb24NCmxvZ1NsVmljIDwtIHNsVmljICU+JQ0KICBtdXRhdGUobG9nQyA9IGxvZyhDb3VudCkpDQoNCiNQbG90IA0KYXV0b3Bsb3QobG9nU2xWaWMsIGxvZ0MpDQoNCmBgYA0KDQojIyMgMmQuDQpWaWN0b3JpYW4gRWxlY3RyaWNpdHkgRGVtYW5kIGZyb20gdmljX2VsZWMuDQpgYGB7cn0NCg0KDQojIDJkLkFuc3dlcjoNCmF1dG9wbG90KHZpY19lbGVjLCBEZW1hbmQpDQoNCmxvZ1ZpYyA8LSB2aWNfZWxlYyAlPiUNCiAgbXV0YXRlKGxvZ0QgPSBsb2coRGVtYW5kKSkNCg0KYXV0b3Bsb3QobG9nVmljLCBsb2dEKQ0KDQoNCg0KYGBgDQoNCiMjIyAyZS4JDQpHYXMgcHJvZHVjdGlvbiBmcm9tIGF1c19wcm9kdWN0aW9uLg0KYGBge3J9DQoNCg0KIyAyZS5BbnN3ZXI6DQphdXRvcGxvdChhdXNfcHJvZHVjdGlvbiwgR2FzKQ0KDQpsb2dBdXNQcm9kIDwtIGF1c19wcm9kdWN0aW9uICU+JQ0KICBtdXRhdGUobG9nRyA9IGxvZyhHYXMpKQ0KDQphdXRvcGxvdChsb2dBdXNQcm9kLCBsb2dHKQ0KDQpgYGANCg0KIyMjIDMuCVVzZSB0aGUgY2FuYWRpYW5fZ2FzIGRhdGEgKG1vbnRobHkgQ2FuYWRpYW4gZ2FzIHByb2R1Y3Rpb24gaW4gYmlsbGlvbnMgb2YgY3ViaWMgbWV0cmVzLCBKYW51YXJ5IDE5NjAg4oCTIEZlYnJ1YXJ5IDIwMDUpLg0KIyMjIyAyYS4JUGxvdCB0aGUgZGF0YSB1c2luZyBhdXRvcGxvdCgpLCBnZ19zdWJzZXJpZXMoKSAsIGdnX3NlYXNvbigpIHRvIGxvb2sgYXQgdGhlIGVmZmVjdCBvZiB0aGUgY2hhbmdpbmcgc2Vhc29uYWxpdHkgb3ZlciB0aW1lLiBEZXNjcmliZSB0aGUgZ3JhcGhzIGluIHlvdXIgb3duIHdvcmRzLiBXaGF0IGRvIHlvdSBzZWU/IFdoYXQgdHlwZSBwZiBwYXR0ZXJuIGRvIHlvdSBvYnNlcnZlPw0KDQpgYGB7cn0NCg0KDQojIDNhLkFuc3dlcjoNCmF1dG9wbG90KGNhbmFkaWFuX2dhcywgVm9sdW1lKQ0KDQpnZ19zdWJzZXJpZXMoY2FuYWRpYW5fZ2FzLCBWb2x1bWUpDQoNCmdnX3NlYXNvbihjYW5hZGlhbl9nYXMsIFZvbHVtZSkNCg0KI1RoZSBwbG90cyBiZWxvdyBjbGVhcmx5IHNob3cgYSByYXBpZCBpbmNyZWFzZSBvdmVyYWxsLCBhcyB3ZWxsIGFzIG9uIGEgbW9udGhseSBhbmQgc2Vhc29uYWwgYmFzaXMuDQoNCg0KDQoNCg0KYGBgDQoNCiMjIyAzYi4NCkRvIGFuIFNUTCBkZWNvbXBvc2l0aW9uIG9mIHRoZSBkYXRhLiBZb3Ugd2lsbCBuZWVkIHRvIGNob29zZSBhIHNlYXNvbmFsIHdpbmRvdyB0byBhbGxvdyBmb3IgdGhlIGNoYW5naW5nIHNoYXBlIG9mIHRoZSBzZWFzb25hbCBjb21wb25lbnQuDQoNCmBgYHtyfQ0KDQojIDNiLkFuc3dlcjoNCg0KY2FuYWRpYW5fZ2FzICU+JQ0KICBtb2RlbChTVEwoVm9sdW1lIH4gc2Vhc29uKHdpbmRvdz0xMikpKSAlPiUNCiAgY29tcG9uZW50cygpICU+JQ0KICBhdXRvcGxvdChWb2x1bWUpDQoNCmBgYA0KDQojIyMgM2MuDQpIb3cgZG9lcyB0aGUgc2Vhc29uYWwgc2hhcGUgY2hhbmdlIG92ZXIgdGltZT8gW0hpbnQ6IFRyeSBwbG90dGluZyB0aGUgc2Vhc29uYWwgY29tcG9uZW50IHVzaW5nIGdnX3NlYXNvbigpLl0NCmBgYHtyfQ0KDQoNCiMgM2MuQW5zd2VyOg0KY2FuYWRpYW5fZ2FzICU+JQ0KICBtb2RlbChTVEwoVm9sdW1lIH4gc2Vhc29uKHdpbmRvdz0xMikpKSAlPiUNCiAgY29tcG9uZW50cygpICU+JQ0KICBnZ19zZWFzb24oVm9sdW1lKQ0KDQojU2Vhc29uYWxseSwgd2Ugb2JzZXJ2ZSBhIGRlY2xpbmUgaW4gdGhlIHN1bW1lciBhbmQgYW4gaW5jcmVhc2UgaW4gdGhlIHdpbnRlci4NCg0KDQoNCmBgYA0KDQojIyMgM2QuCQ0KcHJvZHVjZSBhIHBsYXVzaWJsZSBzZWFzb25hbGx5IGFkanVzdGVkIHNlcmllcz8gV2hhdCBhcmUgdGhlc2UgbnVtYmVycywgcGxvdCB0aGUgc2VyaWVzLg0KYGBge3J9DQoNCiMgM2QuQW5zd2VyOg0KDQpjYW5hZGlhbl9nYXMgJT4lDQogIG1vZGVsKFNUTChWb2x1bWUgfiBzZWFzb24od2luZG93ID0gMTIpKSkgJT4lDQogIGNvbXBvbmVudHMoKSAlPiUNCiAgbXV0YXRlKHNlYXNvbmFsbHlfYWRqdXN0ZWQgPSBWb2x1bWUgLSBzZWFzb25feWVhcikgJT4lDQogIGF1dG9wbG90KHNlYXNvbmFsbHlfYWRqdXN0ZWQpDQoNCmBgYA0KDQojIyMgNC4NCkZvciByZXRhaWwgdGltZSBzZXJpZXMsIHVzZSB0aGUgYmVsb3cgY29kZToNCg0KYGBge3J9DQojIHJ1biB0aGUgY29kZQ0Kc2V0LnNlZWQoMTIzNDU2NzgpDQoNCm15c2VyaWVzIDwtIGF1c19yZXRhaWwgJT4lDQogIGZpbHRlcihgU2VyaWVzIElEYCA9PSBzYW1wbGUoYXVzX3JldGFpbCRgU2VyaWVzIElEYCwxKSkNCg0KDQpgYGANCg0KIyMjIyA0YS4gDQpDcmVhdGUgYSB0cmFpbmluZyBkYXRhc2V0IGNvbnNpc3Rpbmcgb2Ygb2JzZXJ2YXRpb25zIGJlZm9yZSAyMDExIA0KDQpgYGB7cn0NCm15c2VyaWVzX3RyYWluIDwtIG15c2VyaWVzICU+JQ0KICBmaWx0ZXIoeWVhcihNb250aCkgPCAyMDExKQ0KDQoNCmBgYA0KDQojIyMjIDRiLgkNCkNoZWNrIHRoYXQgeW91ciBkYXRhIGhhdmUgYmVlbiBzcGxpdCBhcHByb3ByaWF0ZWx5IGJ5IHByb2R1Y2luZyB0aGUgZm9sbG93aW5nIHBsb3QuDQoNCmBgYHtyfQ0KYXV0b3Bsb3QobXlzZXJpZXMsIFR1cm5vdmVyKSArDQogIGF1dG9sYXllcihteXNlcmllc190cmFpbiwgVHVybm92ZXIsIGNvbG91ciA9ICJyZWQiKQ0KYGBgDQoNCiMjIyMgNGMuCQ0KRml0IGEgc2Vhc29uYWwgbmHDr3ZlIG1vZGVsIHVzaW5nIFNOQUlWRSgpIGFwcGxpZWQgdG8geW91ciB0cmFpbmluZyBkYXRhIChteXNlcmllc190cmFpbikuDQpgYGB7cn0NCiAjQW5zd2VyOg0KICAgIGZpdCA8LSBteXNlcmllc190cmFpbiAlPiUNCiAgICAgIG1vZGVsKFNOQUlWRShUdXJub3ZlcikpDQpmaXQNCmBgYA0KDQoNCiMjIyMgNGQuDQpDaGVjayB0aGUgcmVzaWR1YWxzLg0KYGBge3J9DQoNCiMgNGQgQW5zd2VyOg0KDQojIERvIHRoZSByZXNpZHVhbHMgYXBwZWFyIHRvIGJlIHVuY29ycmVsYXRlZCBhbmQgbm9ybWFsbHkgZGlzdHJpYnV0ZWQ/DQojIEFuc3c6DQpmaXQgJT4lDQogIGdnX3RzcmVzaWR1YWxzKCkNCg0KI1llcywgdGhlIHJlc2lkdWFscyBzZWVtIHRvIGJlIHVuY29ycmVsYXRlZCBhbmQgZm9sbG93IGEgbm9ybWFsIGRpc3RyaWJ1dGlvbi4gVGhlcmUgaXMgbm8gb2J2aW91cyBwYXR0ZXJuLCBhbmQgdGhlaXIgYmVsbC1zaGFwZWQgZm9ybSBpcyB0eXBpY2FsDQpgYGANCg0KIyMjIyA0ZS4NClByb2R1Y2UgZm9yZWNhc3RzIGZvciB0aGUgdGVzdCBkYXRhIHdpdGggZ2l2ZW4gY29kZSBiZWxvdzoNCg0KYGBge3J9DQojIDRlIEFuc3dlcjoNCmZjIDwtIGZpdCAlPiUgIA0KZm9yZWNhc3QobmV3X2RhdGEgPSBhbnRpX2pvaW4obXlzZXJpZXMsIG15c2VyaWVzX3RyYWluKSkNCmZjICU+JSBhdXRvcGxvdChteXNlcmllcykNCg0KYGBgDQoNCkpvaW5pbmcsIGJ5ID0gYygiU3RhdGUiLCAiSW5kdXN0cnkiLCAiU2VyaWVzIElEIiwgIk1vbnRoIiwgIlR1cm5vdmVyIikNCg0KIyMjIyA0Zi4JDQpDb21wYXJlIHRoZSBhY2N1cmFjeSBvZiB5b3VyIGZvcmVjYXN0cyBhZ2FpbnN0IHRoZSBhY3R1YWwgdmFsdWVzIHdpdGggZ2l2ZW4gY29kZSBiZWxvdzoNCmBgYHtyfQ0KZml0ICU+JSBhY2N1cmFjeSgpDQpmYyAlPiUgYWNjdXJhY3kobXlzZXJpZXMpDQojIDRmIEFuc3c6DQpmYyA8LSBmaXQgJT4lICANCiAgZm9yZWNhc3QobmV3X2RhdGEgPSBhbnRpX2pvaW4obXlzZXJpZXMsIG15c2VyaWVzX3RyYWluLCBieSA9IGMoIlN0YXRlIiwgIkluZHVzdHJ5IiwgIlNlcmllcyBJRCIsICJNb250aCIsICJUdXJub3ZlciIpKSkNCg0KZmMgJT4lIA0KICBhdXRvcGxvdChteXNlcmllcykNCg0KdHJhaW4gPC0gZml0ICU+JSBhY2N1cmFjeSgpDQoNCnRlc3QgPC0gZmMgJT4lIGFjY3VyYWN5KG15c2VyaWVzKQ0KDQp0cmFpbg0KDQp0ZXN0DQoNCmBgYA0KDQojIyMjIDRnLg0KSG93IHNlbnNpdGl2ZSBhcmUgdGhlIGFjY3VyYWN5IG1lYXN1cmVzIHRvIHRoZSBhbW91bnQgb2YgdHJhaW5pbmcgZGF0YSB1c2VkPw0KYGBge3J9DQoNCiMgNGcgQW5zd2VyOg0KI1RoZSBhY2N1cmFjeSBtZXRyaWNzIHN1Z2dlc3QgdGhhdCB0aGUgbW9kZWwgaXMgc2Vuc2l0aXZlIHRvIHRoZSB0cmFpbmluZyBkYXRhLCBhcyBpdCBwZXJmb3JtcyBiZXR0ZXIgb24gdGhlIHRyYWluaW5nIHNldCB0aGFuIG9uIHRoZSB0ZXN0IHNldA0KYGBgDQoNCiMjIyA1LgkNCiMjIyMgNWEuCQ0KQ3JlYXRlIGEgdHJhaW5pbmcgc2V0IGZvciBBdXN0cmFsaWFuIHRha2Vhd2F5IGZvb2QgdHVybm92ZXIgKGF1c19yZXRhaWwpIGJ5IHdpdGhob2xkaW5nIHRoZSBsYXN0IGZvdXIgeWVhcnMgYXMgYSB0ZXN0IHNldC4gDQpgYGB7cn0NCg0KDQojIDVhLkFuc3dlcjoNCmF1c190YWtlYXdheSA8LSBhdXNfcmV0YWlsICU+JQ0KICBmaWx0ZXIoSW5kdXN0cnkgPT0gIlRha2Vhd2F5IGZvb2Qgc2VydmljZXMiKQ0KDQp0cmFpbl9zZXQgPC0gYXVzX3Rha2Vhd2F5ICU+JQ0KICBmaWx0ZXIoeWVhcihNb250aCkgPD0gMjAxNSkNCg0KdGVzdF9zZXQgPC0gYXVzX3Rha2Vhd2F5ICU+JQ0KICBmaWx0ZXIoeWVhcihNb250aCkgPiAyMDE1KQ0KDQpgYGANCg0KIyMjIyA1Yi4JDQpGaXQgYWxsIHRoZSBhcHByb3ByaWF0ZSBiZW5jaG1hcmsgbWV0aG9kcyB0byB0aGUgICB0cmFpbmluZyBzZXQgYW5kIGZvcmVjYXN0IHRoZSBwZXJpb2RzIGNvdmVyZWQgYnkgdGhlIHRlc3Qgc2V0Lg0KYGBge3J9DQoNCg0KIyA1Yi5BbnN3ZXI6DQpmaXRfYmVuY2htYXJrcyA8LSB0cmFpbl9zZXQgJT4lDQogIG1vZGVsKA0KICAgIG5haXZlID0gTkFJVkUoVHVybm92ZXIpLA0KICAgIHNuYWl2ZSA9IFNOQUlWRShUdXJub3ZlciksDQogICAgbWVhbiA9IE1FQU4oVHVybm92ZXIpLA0KICAgIGRyaWZ0ID0gUlcoVHVybm92ZXIgfiBkcmlmdCgpKQ0KICApDQoNCmZjX2JlbmNobWFya3MgPC0gZml0X2JlbmNobWFya3MgJT4lDQogIGZvcmVjYXN0KGRhdGEgPSB0ZXN0X3NldCkNCg0KZmNfYmVuY2htYXJrcyAlPiUNCiAgYXV0b3Bsb3QoYXVzX3Rha2Vhd2F5KSArDQogIGF1dG9sYXllcih0cmFpbl9zZXQpICsNCiAgYXV0b2xheWVyKHRlc3Rfc2V0KQ0KDQoNCmBgYA0KDQojIyMjIDVjLgkNCkNvbXB1dGUgdGhlIGFjY3VyYWN5IG9mIHlvdXIgZm9yZWNhc3RzLiBXaGljaCBtZXRob2QgZG9lcyBiZXN0Pw0KYGBge3J9DQoNCg0KIyA1Yy5BbnN3ZXI6DQpmY19iZW5jaG1hcmtzICU+JQ0KICBhY2N1cmFjeSh0ZXN0X3NldCkNCg0KZmNfYmVuY2htYXJrcw0KDQojVGhlIERyaWZ0IG1ldGhvZCBwZXJmb3JtcyB0aGUgYmVzdCwgYXMgaXQgeWllbGRzIHRoZSBsb3dlc3QgUk1TRS4NCg0KDQpgYGANCg0KIyMjIyA1ZC4NCkRvIHRoZSByZXNpZHVhbHMgZnJvbSB0aGUgYmVzdCBtZXRob2QgcmVzZW1ibGUgd2hpdGUgbm9pc2U/DQpgYGB7cn0NCg0KIyA1ZC5BbnN3ZXI6DQpEcmlmdF9tb2RlbCA8LSB0cmFpbl9zZXQgJT4lDQogIG1vZGVsKERyaWZ0ID0gUlcoVHVybm92ZXIgfiBkcmlmdCgpKSkNCg0KcmVzaWR1YWxzIDwtIHJlc2lkdWFscyhEcmlmdF9tb2RlbCkgJT4lDQogIGRyb3BfbmEoLnJlc2lkKQ0KDQpyZXNpZHVhbF92YWx1ZXMgPC0gYXMubnVtZXJpYyhyZXNpZHVhbHMkLnJlc2lkKQ0KDQphY2ZfcmVzaWR1YWxzIDwtIEFDRihyZXNpZHVhbHMsIC5yZXNpZCwgbGFnX21heCA9IDIwKQ0KYXV0b3Bsb3QoYWNmX3Jlc2lkdWFscykgDQoNCmhpc3QocmVzaWR1YWxfdmFsdWVzLCBicmVha3MgPSAyMCkNCg0KcXFub3JtKHJlc2lkdWFsX3ZhbHVlcykNCnFxbGluZShyZXNpZHVhbF92YWx1ZXMpDQoNCmBgYA0KDQojIyMgNi4JDQpVc2luZyB0aGUgY29kZSBiZWxvdywgZ2V0IGEgc2VyaWVzIChpdCBnZXRzIGEgc2VyaWVzIHJhbmRvbWx5IGJ5IHVzaW5nIHNhbXBsZSgpIGZ1bmN0aW9uKToNCmBgYHtyfQ0Kc2V0LnNlZWQoMTIzNDU2NzgpDQpteXNlcmllcyA8LSBhdXNfcmV0YWlsICU+JQ0KICBmaWx0ZXIoYFNlcmllcyBJRGAgPT0gc2FtcGxlKGF1c19yZXRhaWwkYFNlcmllcyBJRGAsMSkpDQphdXRvcGxvdChteXNlcmllcywgVHVybm92ZXIpDQpgYGANCnNlZSBoZWFkIG9mIHlvdXIgc2VyaWVzIHRvIGNoZWNrIGl0IGlzIGEgdHNpYmJsZSBkYXRhLCBhbmQgcmVtb3ZlIE5B4oCZcyBpZiB0aGVyZSBpcyBhbnkgd2l0aCB0aGVzZSBjb21tYW5kczoNCg0KYGBge3J9DQpoZWFkKG15c2VyaWVzKQ0KbXlzZXJpZXMgPSAgbXlzZXJpZXMgJT4lIGZpbHRlcighaXMubmEoYFNlcmllcyBJRGApKQ0KaXNfdHNpYmJsZShteXNlcmllcykNCmBgYA0KDQojIyMjIDZhLg0KV2hhdCBpcyB0aGUgbmFtZSBvZiB0aGUgc2VyaWVzIHlvdSByYW5kb21seSBjaG9vc2U/IFdyaXRlIGl0Lg0KYGBge3J9DQoNCiMgNmEuQW5zd2VyOg0Kc2VyaWVzIDwtIHVuaXF1ZShteXNlcmllcyRgU2VyaWVzIElEYCkNCnNlcmllcw0KDQppbmR1c3RyeSA8LSB1bmlxdWUobXlzZXJpZXMkSW5kdXN0cnkpDQppbmR1c3RyeQ0KDQoNCmBgYA0KDQojIyMjIDZiLiANClJ1biBhIGxpbmVhciByZWdyZXNzaW9uIG9mIFR1cm5vdmVyIG9uIHRyZW5kLihIaW50OiB1c2UgVFNMTSgpIGFuZCB0cmVuZCgpIGZ1bmN0aW9ucykNCmBgYHtyfQ0KIyA2Yi5BbnN3ZXI6DQpUdXJub3Zlcl9UcmVuZF9sciA8LSBteXNlcmllcyAlPiUNCiAgbW9kZWwoVFNMTShUdXJub3ZlciB+IHRyZW5kKCkpKQ0KDQpgYGANCg0KIyMjIyA2Yy4gDQpTZWUgdGhlIHJlZ3Jlc3Npb24gcmVzdWx0IGJ5IHJlcG9ydCgpIGNvbW1hbmQuDQpgYGB7cn0NCiMgNmMuQW5zd2VyOg0KcmVwb3J0KFR1cm5vdmVyX1RyZW5kX2xyKQ0KDQoNCmBgYA0KDQoNCiMjIyMgNmQuCQ0KQnkgdXNpbmcgdGhpcyBtb2RlbCwgZm9yZWNhc3QgaXQgZm9yIHRoZSBuZXh0IDMgeWVhcnMuIFdoYXQgYXJlIHRoZSB2YWx1ZXMgb2YgdGhlIG5leHQgMyB5ZWFycywgbW9udGhseSB2YWx1ZXM/DQpgYGB7cn0NCg0KIyA2ZC5BbnN3ZXI6DQpmb3JlY2FzdF90aCA8LSBUdXJub3Zlcl9UcmVuZF9sciAlPiUNCiAgZm9yZWNhc3QoaCA9ICIzIHllYXJzIikNCg0KZm9yZWNhc3RfdGggJT4lDQogIGFzX3RpYmJsZSgpICU+JQ0KICBzZWxlY3QoTW9udGgsIC5tZWFuKQ0KDQpmb3JlY2FzdF90aA0KYGBgDQoNCiMjIyMgNmQuCQ0KUGxvdCB0aGUgZm9yZWNhc3QgdmFsdWVzIGFsb25nIHdpdGggdGhlIG9yaWdpbmFsIGRhdGEuDQpgYGB7cn0NCg0KIyA2ZC5BbnN3ZXI6DQphdXRvcGxvdChteXNlcmllcywgVHVybm92ZXIpICsNCiAgYXV0b2xheWVyKGZvcmVjYXN0X3RoLCAubWVhbiwgY29sb3IgPSAiYmx1ZSIpDQoNCmBgYA0KDQojIyMjIDZlLgkNCkdldCB0aGUgcmVzaWR1YWxzIGZyb20gdGhlIG1vZGVsLiBBbmQgY2hlY2sgdGhlIHJlc2lkdWFscyB0byBjaGVjayB3aGV0aGVyIG9yIG5vdCBpdCBzYXRpc2ZpZXMgdGhlIHJlcXVpcmVtZW50cyBmb3Igd2hpdGUgbm9pc2UgZXJyb3IgdGVybXMuKGhpbnQ6IGF1Z21lbnQoKSBhbmQgZ2dfdHNyZXNpZHVhbHMoKSBmdW5jdGlvbnMpDQoNCmBgYHtyfQ0KDQojIDZlLkFuc3dlcjoNCnJlc2lkdWFscyA8LSBhdWdtZW50KFR1cm5vdmVyX1RyZW5kX2xyKQ0KDQpnZ190c3Jlc2lkdWFscyhUdXJub3Zlcl9UcmVuZF9scikNCg0KDQpgYGANCg0KDQojIyMgNy4gDQpIYWxmLWhvdXJseSBlbGVjdHJpY2l0eSBkZW1hbmQgZm9yIFZpY3RvcmlhLCBBdXN0cmFsaWEgaXMgY29udGFpbmVkIGluIHZpY19lbGVjLiBFeHRyYWN0IHRoZSBKYW51YXJ5IDIwMTQgZWxlY3RyaWNpdHkgZGVtYW5kLCBhbmQgYWdncmVnYXRlIHRoaXMgZGF0YSB0byBkYWlseSB3aXRoICBkYWlseSB0b3RhbCBkZW1hbmRzIGFuZCBtYXhpbXVtIHRlbXBlcmF0dXJlcy4gUnVuIHRoZSBjb2RlIGJlbG93Og0KDQpgYGB7cn0NCmphbl92aWNfZWxlYyA8LSB2aWNfZWxlYyAlPiUNCiAgZmlsdGVyKHllYXJtb250aChUaW1lKSA9PSB5ZWFybW9udGgoIjIwMTQgSmFuIikpICU+JQ0KICBpbmRleF9ieShEYXRlID0gYXNfZGF0ZShUaW1lKSkgJT4lDQogIHN1bW1hcmlzZShEZW1hbmQgPSBzdW0oRGVtYW5kKSwgVGVtcGVyYXR1cmUgPSBtYXgoVGVtcGVyYXR1cmUpKQ0KDQpgYGANCg0KIyMjIyA3YS4gDQpQbG90IHRoZSBkYXRhIGFuZCBmaW5kIHRoZSByZWdyZXNzaW9uIG1vZGVsIGZvciBEZW1hbmQgd2l0aCB0ZW1wZXJhdHVyZSBhcyBhIHByZWRpY3RvciB2YXJpYWJsZS4gV2h5IGlzIHRoZXJlIGEgcG9zaXRpdmUgcmVsYXRpb25zaGlwPw0KYGBge3J9DQoNCiMgN2EuQW5zd2VyOg0KbGlicmFyeShnZ3Bsb3QyKQ0KDQpnZ3Bsb3QoamFuX3ZpY19lbGVjLCBhZXMoeCA9IFRlbXBlcmF0dXJlLCB5ID0gRGVtYW5kKSkgKw0KICBnZW9tX3BvaW50KCkgDQoNCmRlbWFuZF9tbCA8LSBsbShEZW1hbmQgfiBUZW1wZXJhdHVyZSwgZGF0YSA9IGphbl92aWNfZWxlYykNCg0Kc3VtbWFyeShkZW1hbmRfbWwpDQpgYGANCg0KIyMjIyA3Yi4gDQpQcm9kdWNlIGEgcmVzaWR1YWwgcGxvdC4gSXMgdGhlIG1vZGVsIGFkZXF1YXRlPyBBcmUgdGhlcmUgYW55IG91dGxpZXJzIG9yIGluZmx1ZW50aWFsIG9ic2VydmF0aW9ucz8NCg0KYGBge3J9DQoNCiMgN2IuQW5zd2VyOg0KbGlicmFyeShicm9vbSkNCg0KZGVtYW5kX21sIDwtIGxtKERlbWFuZCB+IFRlbXBlcmF0dXJlLCBkYXRhID0gamFuX3ZpY19lbGVjKQ0KDQpyZXNpZHVhbF9wbCA8LSBhdWdtZW50KGRlbWFuZF9tbCwgZGF0YSA9IGphbl92aWNfZWxlYykNCg0KZ2dwbG90KHJlc2lkdWFsX3BsLCBhZXMoeCA9IFRlbXBlcmF0dXJlLCB5ID0gLnJlc2lkKSkgKw0KICBnZW9tX3BvaW50KCkgDQoNCmBgYA0KDQojIyMjIDdjLg0KVXNlIHRoZSBtb2RlbCB0byBmb3JlY2FzdCB0aGUgZWxlY3RyaWNpdHkgZGVtYW5kIHRoYXQgeW91IHdvdWxkIGV4cGVjdCBmb3IgdGhlIG5leHQgZGF5IGlmIHRoZSBtYXhpbXVtIHRlbXBlcmF0dXJlIHdhcyAxNeKImEMgYW5kIGNvbXBhcmUgaXQgd2l0aCB0aGUgZm9yZWNhc3QgaWYgdGhlIHdpdGggbWF4aW11bSB0ZW1wZXJhdHVyZSB3YXMgMzXiiJhDLiBEbyB5b3UgYmVsaWV2ZSB0aGVzZSBmb3JlY2FzdHM/DQoNCmBgYHtyfQ0KDQoNCg0KIyA3Yy5BbnN3ZXI6DQpkZW1hbmRfbWwgPC0gbG0oRGVtYW5kIH4gVGVtcGVyYXR1cmUsIGRhdGEgPSBqYW5fdmljX2VsZWMpDQoNCm5leHRfZGF5IDwtIGRhdGEuZnJhbWUoVGVtcGVyYXR1cmUgPSBjKDE1LCAzNSkpDQoNCmZvcmVjYXN0IDwtIHByZWRpY3QoZGVtYW5kX21sLCBuZXdkYXRhID0gbmV4dF9kYXkpDQoNCmZvcmVjYXN0IDwtIGRhdGEuZnJhbWUoDQogIFRlbXBlcmF0dXJlID0gYygxNSwgMzUpLA0KICBGb3JlY2FzdGVkX0RlbWFuZCA9IGZvcmVjYXN0DQopDQoNCmZvcmVjYXN0DQpgYGANCg0KIyMjIyA3ZC4NCkRvIHlvdSBiZWxpZXZlIHRoZXNlIGZvcmVjYXN0cz8gVGhlIGZvbGxvd2luZyBSIGNvZGUgd2lsbCBnZXQgeW91IHN0YXJ0ZWQ6DQpgYGB7cn0NCiBqYW5fdmljX2VsZWMgJT4lDQogIG1vZGVsKFRTTE0oRGVtYW5kIH4gVGVtcGVyYXR1cmUpKSAlPiUNCiAgZm9yZWNhc3QoDQogICAgbmV3X2RhdGEoamFuX3ZpY19lbGVjLCAxKSAlPiUNCiAgICAgIG11dGF0ZShUZW1wZXJhdHVyZSA9IDE1KQ0KICApICU+JQ0KICBhdXRvcGxvdChqYW5fdmljX2VsZWMpDQoNCiAgDQpgYGANCiAgDQpgYGB7cn0NCg0KIyA3ZC5BbnN3ZXI6DQpqYW5fdmljX2VsZWMgJT4lDQogIG1vZGVsKFRTTE0oRGVtYW5kIH4gVGVtcGVyYXR1cmUpKSAlPiUNCiAgZm9yZWNhc3QoDQogICAgbmV3X2RhdGEoamFuX3ZpY19lbGVjLCAxKSAlPiUNCiAgICAgIG11dGF0ZShUZW1wZXJhdHVyZSA9IDE1KQ0KICApICU+JQ0KICBhdXRvcGxvdChqYW5fdmljX2VsZWMpDQoNCmZvcmVjYXN0XzIgPC0gamFuX3ZpY19lbGVjICU+JQ0KICBtb2RlbChUU0xNKERlbWFuZCB+IFRlbXBlcmF0dXJlKSkgJT4lDQogIGZvcmVjYXN0KA0KICAgIG5ld19kYXRhID0gbmV3X2RhdGEoamFuX3ZpY19lbGVjLCAxKSAlPiUNCiAgICAgIG11dGF0ZShUZW1wZXJhdHVyZSA9IDE1KQ0KICApDQoNCmZvcmVjYXN0XzMgPC0gamFuX3ZpY19lbGVjICU+JQ0KICBtb2RlbChUU0xNKERlbWFuZCB+IFRlbXBlcmF0dXJlKSkgJT4lDQogIGZvcmVjYXN0KA0KICAgIG5ld19kYXRhID0gbmV3X2RhdGEoamFuX3ZpY19lbGVjLCAxKSAlPiUNCiAgICAgIG11dGF0ZShUZW1wZXJhdHVyZSA9IDM1KQ0KICApDQoNCmF1dG9wbG90KGphbl92aWNfZWxlYywgRGVtYW5kKSArDQogIGF1dG9sYXllcihmb3JlY2FzdF8yLCAubWVhbikgKw0KICBhdXRvbGF5ZXIoZm9yZWNhc3RfMywgLm1lYW4pIA0KDQoNCiNJIGJlbGlldmUgdGhlIGZvcmVjYXN0cyBzaG93IHRoYXQgaGlnaGVyIHRlbXBlcmF0dXJlcyBkcml2ZSB1cCBwb3dlciBkZW1hbmQsIGJ1dCBvdGhlciBmYWN0b3JzIHN1Y2ggYXMgdGhlIGRheSBvZiB0aGUgd2Vlaywgc2Vhc29uYWxpdHksIGFuZCBodW1pZGl0eSBhbHNvIHBsYXkgYSBzaWduaWZpY2FudCByb2xlIGluIGluZmx1ZW5jaW5nIHBvd2VyIGNvbnN1bXB0aW9uLg0KYGBgDQogDQojIyMjIDdlLiANCkdpdmUgcHJlZGljdGlvbiBpbnRlcnZhbHMgZm9yIHlvdXIgZm9yZWNhc3RzLg0KDQpgYGB7cn0NCg0KDQojIDdlLkFuc3dlcjoNCmZvcmVjYXN0XzIgPC0gamFuX3ZpY19lbGVjICU+JQ0KICBtb2RlbChUU0xNKERlbWFuZCB+IFRlbXBlcmF0dXJlKSkgJT4lDQogIGZvcmVjYXN0KA0KICAgIG5ld19kYXRhID0gbmV3X2RhdGEoamFuX3ZpY19lbGVjLCAxKSAlPiUNCiAgICAgIG11dGF0ZShUZW1wZXJhdHVyZSA9IDE1KSwNCiAgICBQSSA9IFRSVUUNCiAgKQ0KDQpmb3JlY2FzdF8zIDwtIGphbl92aWNfZWxlYyAlPiUNCiAgbW9kZWwoVFNMTShEZW1hbmQgfiBUZW1wZXJhdHVyZSkpICU+JQ0KICBmb3JlY2FzdCgNCiAgICBuZXdfZGF0YSA9IG5ld19kYXRhKGphbl92aWNfZWxlYywgMSkgJT4lDQogICAgICBtdXRhdGUoVGVtcGVyYXR1cmUgPSAzNSksDQogICAgUEkgPSBUUlVFDQogICkNCg0KYXV0b3Bsb3QoamFuX3ZpY19lbGVjLCBEZW1hbmQpICsNCiAgYXV0b2xheWVyKGZvcmVjYXN0XzIsIC5tZWFuLFBJID0gVFJVRSkgKw0KICBhdXRvbGF5ZXIoZm9yZWNhc3RfMywgLm1lYW4sUEkgPSBUUlVFKQ0KDQoNCiNUaGUgcHJlZGljdGlvbiBpbnRlcnZhbHMgcmVwcmVzZW50IHRoZSBleHBlY3RlZCByYW5nZSBvZiBkZW1hbmQsIHdoZXJlIHdpZGVyIGludGVydmFscyBpbmRpY2F0ZSBncmVhdGVyIHVuY2VydGFpbnR5IGFuZCBuYXJyb3dlciBpbnRlcnZhbHMgc3VnZ2VzdCBoaWdoZXIgY29uZmlkZW5jZSBpbiB0aGUgZm9yZWNhc3RzLg0KYGBgDQoNCg0KIyMjIDguDQpSZWFkIHRoZSBzaGFtcG9vIGRhdGEgZ2l2ZW4gaW4gZXhjZWwgKEltcG9ydCBEYXRhc2V0IGFzIEV4Y2VsKQ0KICANCmBgYHtyfQ0KI2EuCVZpZXcgdGhlIHNoYW1wb28gc2FsZXMgZGF0YS4gSG93IG1hbnkgdmFyaWFibGVzIGFyZSB0aGVyZT8gRmluZCBob3cgbWFueSByb3dzIGFuZCBjb2x1bW5zIGluIHRoZSBkYXRhPw0KbGlicmFyeShyZWFkeGwpDQpzaGFtcG9vXzIgPC0gcmVhZF9leGNlbCgic2hhbXBvby0yLnhsc3giKQ0KVmlldyhzaGFtcG9vXzIpDQpucm93KHNoYW1wb29fMikNCm5jb2woc2hhbXBvb18yKQ0KI1RoZXJlIGFyZSAzNiByb3dzIGFuZCAyIGNvbHVtbnMgaW4gdGhlIGRhdGENCiAgDQoNCiNiLglJcyB0aGUgZGF0YSBhbm51YWwsIG1vbnRobHksIHF1YXJ0ZXJseT8NCiNBZnRlciBpbml0aWFsIGFuYWx5c2lzLCB3ZSBjYW4gb2JzZXJ2ZSB0aGF0IHRoZSBkYXRhIGlzIG1vbnRobHkNCiAgDQojYy4JQ29udmVydCB0aGUgZGF0YSBpbnRvIHRpYmJsZSAsIHRoZW4gdHNpYmJsZSANCnNoYW1wb29fZGF0YSA8LSBhc190aWJibGUoc2hhbXBvb18yKQ0KDQpzaGFtcG9vX3RzaWJibGUgPC0gc2hhbXBvb19kYXRhICU+JQ0KICBtdXRhdGUoRGF0ZSA9IHllYXJtb250aChNb250aCkpICU+JQ0KICBhc190c2liYmxlKGluZGV4ID0gRGF0ZSkNCg0Kc2hhbXBvb190c2liYmxlDQogIA0KI2QuCVBsb3QgdGhlIHNoYW1wb28gc2FsZXMuIFdoYXQgZG8geW91IHNlZSBmcm9tIHRoZSBkYXRhIHBhdHRlcm4/IFdoYXQgZG9lcyB4LWF4aXMgcmVwcmVzZW50PyANCnBsb3Qoc2hhbXBvb190c2liYmxlJERhdGUsIHNoYW1wb29fdHNpYmJsZSRzYWxlcywgDQogICAgIHhsYWIgPSAiRGF0ZSIsIA0KICAgICB5bGFiID0gIlNoYW1wb28gU2FsZXMiLCANCiAgICAgbWFpbiA9ICJTaGFtcG9vIFNhbGVzIikNCg0KYXV0b3Bsb3Qoc2hhbXBvb190c2liYmxlLCBzYWxlcykgKw0KICBsYWJzKHRpdGxlID0gIlNoYW1wb28gU2FsZXMiLA0KICAgICAgIHkgPSAiU2hhbXBvbyBTYWxlcyIsDQogICAgICAgeCA9ICJEYXRlIikNCg0KIyBDb21tZW50IGhlcmUuIFVzZSBwbG90KCkgYW5kIGF1dG9wbG90KCkuUHV0IHRoZSBuYW1lIGZvciB5IGF4aXMsIGFuZCBhIHRpdGxlIGZvciB0aGUgZ3JhcGguDQogIA0KI2UuCVdoYXQgaXMgdGhlIGF2ZXJhZ2UsIGFuZCBtZWRpYW4gb2Ygc2hhbXBvbyBzYWxlcy4gUHV0IGl0IG9uIGEgaGlzdG9ncmFtLg0KYXZlcmFnZSA8LSBtZWFuKHNoYW1wb29fdHNpYmJsZSRzYWxlcykNCg0KbWVkaWFuIDwtIG1lZGlhbihzaGFtcG9vX3RzaWJibGUkc2FsZXMpDQoNCmhpc3Qoc2hhbXBvb190c2liYmxlJHNhbGVzKQ0KDQphYmxpbmUodiA9IGF2ZXJhZ2UsIGNvbCA9ICJyZWQiLCBsd2QgPSAyLCBsdHkgPSAyKQ0KYWJsaW5lKHYgPSBtZWRpYW4sIGNvbCA9ICJibHVlIiwgbHdkID0gMiwgbHR5ID0gMikNCiAgDQojZi4JR2V0IHNlYXNvbmFsIHBsb3QuIFdoYXQgZG8geW91IHNlZS8gaXMgdGhlcmUgYW55IHBhdHRlcm4sIGlzIHRlaHJlIGFueSBzZWFzb25hbGl0eS4NCg0KZ2dfc2Vhc29uKHNoYW1wb29fdHNpYmJsZSwgc2FsZXMpICsNCiAgbGFicyh0aXRsZSA9ICJTZWFzb25hbCBQbG90IG9mIFNoYW1wb28gU2FsZXMiLA0KICAgICAgIHggPSAiRGF0ZSIsDQogICAgICAgeSA9ICJTaGFtcG9vIFNhbGVzIikNCg0KI2cuCUdldCBhIGxpbmVhciByZWdyZXNzaW9uIGxpbmUgd2l0aCB0cmVuZCBhbmQgZHVtbXkgZm9yIGVhY2ggbW9udGggKEhpbnQ6IHVzZSB0cmVuZCBhbmQgc2Vhc29uIGluIHJlZ3Jlc3Npb24gZXF1YXRpb24pLg0Kc2hhbXBvb19tbCA8LSBzaGFtcG9vX3RzaWJibGUgJT4lDQogIG1vZGVsKFRTTE0oc2FsZXMgfiB0cmVuZCgpICsgc2Vhc29uKCkpKQ0KICANCiNoLglDb21tZW50IG9uIGVhY2ggZXN0aW1hdGVkIGNvZWZmaWNpZW50IG9mIHRoZSBtb2RlbC5BcmUgdGhleSBzdGF0aXN0aWNhbGx5IHNpZ25pZmljYW50IGF0IDUgJSBzaWduaWZpY2FuY2UgbGV2ZWw/DQpyZXBvcnQoc2hhbXBvb19tbCkNCiAgDQojaS4JV2hpY2ggbW9udGggaGFzIHRoZSBoaWdoZXN0IHNhbGVzPw0KU2FsZXNfSGlnaGVzdCA8LSBzaGFtcG9vX3RzaWJibGUgJT4lDQogIGZpbHRlcihzYWxlcyA9PSBtYXgoc2FsZXMpKQ0KDQpTYWxlc19IaWdoZXN0DQogIA0KI2ouCUZvcmVjYXN0IGl0IGZvciB0aGUgbmV4dCB5ZWFyLiBXaGF0IGFyZSB0aGUgdmFsdWVzDQoNCmZvcmVjYXN0IDwtIHNoYW1wb29fdHNpYmJsZSAlPiUNCiAgbW9kZWwoVFNMTShzYWxlcyB+IHRyZW5kKCkgKyBzZWFzb24oKSkpICU+JQ0KICBmb3JlY2FzdChoID0gIjEgeWVhciIpDQoNCmZvcmVjYXN0ICU+JQ0KICBhc190aWJibGUoKSAlPiUNCiAgc2VsZWN0KERhdGUsIC5tZWFuKQ0KICANCiNrLglQbG90IHRoZSBmb3JlY2FzdCB3aXRoIG9yaWdpbmFsIGRhdGEuDQphdXRvcGxvdChzaGFtcG9vX3RzaWJibGUsIHNhbGVzKSArDQogIGF1dG9sYXllcihmb3JlY2FzdCwgLm1lYW4sIGNvbG91ciA9ICJibHVlIikgKw0KICBsYWJzKHRpdGxlID0gIkZvcmVjYXN0IGZvciBOZXh0IFllYXIiLA0KICAgICAgIHggPSAiRGF0ZSIsDQogICAgICAgeSA9ICJTaGFtcG9vIFNhbGVzIikNCiAgDQojbC4JQ2hlY2sgaWYgdGhlIHJlc2lkdWFscyBvZiB0aGUgbW9kZWwgaXMgd2hpdGUgbm9pc2UuDQpzaGFtcG9vX21sIDwtIHNoYW1wb29fdHNpYmJsZSAlPiUNCiAgbW9kZWwoVFNMTShzYWxlcyB+IHRyZW5kKCkgKyBzZWFzb24oKSkpDQoNCnJlc2lkdWFscyA8LSBhdWdtZW50KHNoYW1wb29fbWwpDQoNCmdnX3RzcmVzaWR1YWxzKHNoYW1wb29fbWwpDQogIA0KI20uCUJ5IHVzaW5nIHRoZSByZWdyZXNzaW9uIG1vZGVsLCBmb3JlY2FzdCB0aGUgMSB5ZWFyIGFoZWFkLCBhbmQgdGhlbiBjaGVjayB0aGUgYWNjdXJhY3kgb2YgdGhlIGZvcmVjYXN0LiBXaGF0IGlzIE1TRSwgUk1TRSB2YWx1ZXM/DQpmb3JlY2FzdCA8LSBzaGFtcG9vX3RzaWJibGUgJT4lDQogIG1vZGVsKFRTTE0oc2FsZXMgfiB0cmVuZCgpICsgc2Vhc29uKCkpKSAlPiUNCiAgZm9yZWNhc3QoaCA9ICIxIHllYXIiKQ0KDQpmb3JlY2FzdCAlPiUNCiAgYXNfdGliYmxlKCkgJT4lDQogIHNlbGVjdChEYXRlLCAubWVhbikNCg0KZm9yZWNhc3QNCiAgDQoNCmBgYA0KICAgIA0K