library(fpp3)
## Warning: package 'fpp3' was built under R version 4.3.3
## Registered S3 method overwritten by 'tsibble':
##   method               from 
##   as_tibble.grouped_df dplyr
## ── Attaching packages ──────────────────────────────────────────── fpp3 1.0.1 ──
## ✔ tibble      3.2.1     ✔ tsibble     1.1.6
## ✔ dplyr       1.1.4     ✔ tsibbledata 0.4.1
## ✔ tidyr       1.3.1     ✔ feasts      0.4.1
## ✔ lubridate   1.9.3     ✔ fable       0.4.1
## ✔ ggplot2     3.5.0
## Warning: package 'tidyr' was built under R version 4.3.3
## Warning: package 'tsibble' was built under R version 4.3.3
## Warning: package 'tsibbledata' was built under R version 4.3.3
## Warning: package 'feasts' was built under R version 4.3.3
## Warning: package 'fabletools' was built under R version 4.3.3
## Warning: package 'fable' was built under R version 4.3.3
## ── Conflicts ───────────────────────────────────────────────── fpp3_conflicts ──
## ✖ lubridate::date()    masks base::date()
## ✖ dplyr::filter()      masks stats::filter()
## ✖ tsibble::intersect() masks base::intersect()
## ✖ tsibble::interval()  masks lubridate::interval()
## ✖ dplyr::lag()         masks stats::lag()
## ✖ tsibble::setdiff()   masks base::setdiff()
## ✖ tsibble::union()     masks base::union()
library(tidyverse)
## ── Attaching core tidyverse packages ──────────────────────── tidyverse 2.0.0 ──
## ✔ forcats 1.0.0     ✔ readr   2.1.5
## ✔ purrr   1.0.2     ✔ stringr 1.5.1
## ── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
## ✖ dplyr::filter()     masks stats::filter()
## ✖ tsibble::interval() masks lubridate::interval()
## ✖ dplyr::lag()        masks stats::lag()
## ℹ Use the conflicted package (<http://conflicted.r-lib.org/>) to force all conflicts to become errors
Sys.time()
## [1] "2025-03-23 15:08:02 EDT"

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
library(fpp3)

# View the structure of the dataset
glimpse(global_economy)
## Rows: 15,150
## Columns: 9
## Key: Country [263]
## $ Country    <fct> "Afghanistan", "Afghanistan", "Afghanistan", "Afghanistan",…
## $ Code       <fct> AFG, AFG, AFG, AFG, AFG, AFG, AFG, AFG, AFG, AFG, AFG, AFG,…
## $ Year       <dbl> 1960, 1961, 1962, 1963, 1964, 1965, 1966, 1967, 1968, 1969,…
## $ GDP        <dbl> 537777811, 548888896, 546666678, 751111191, 800000044, 1006…
## $ Growth     <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,…
## $ CPI        <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,…
## $ Imports    <dbl> 7.024793, 8.097166, 9.349593, 16.863910, 18.055555, 21.4128…
## $ Exports    <dbl> 4.132233, 4.453443, 4.878051, 9.171601, 8.888893, 11.258279…
## $ Population <dbl> 8996351, 9166764, 9345868, 9533954, 9731361, 9938414, 10152…
# Choose a random country, e.g., "India"
india_gdp <- global_economy %>% 
  filter(Country == "India")

# Create a GDP per capita variable
india_gdp <- india_gdp %>%
  mutate(GDP_per_capita = GDP / Population)

# Plot GDP per capita over time
india_gdp %>%
  autoplot(GDP_per_capita) +
  labs(title = "India: GDP per Capita Over Time",
       y = "GDP per Capita (USD)", x = "Year")

# 1.Answer:

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:
# Original GDP per capita plot
india_gdp %>%
  autoplot(GDP_per_capita) +
  labs(title = "India: GDP per Capita (Original)", 
       y = "GDP per Capita", x = "Year")

# Apply log transformation
india_gdp %>%
  mutate(log_GDP_per_capita = log(GDP_per_capita)) %>%
  autoplot(log_GDP_per_capita) +
  labs(title = "India: Log of GDP per Capita", 
       y = "Log(GDP per Capita)", x = "Year")

2b.

United States GDP from global_economy.

# 2b.Answer:
# Filter for United States
us_gdp <- global_economy %>%
  filter(Country == "United States")

# Plot original GDP
us_gdp %>%
  autoplot(GDP) +
  labs(title = "United States: GDP (Original)", 
       y = "GDP (in Billions USD)", x = "Year")

# Apply log transformation to GDP
us_gdp %>%
  mutate
## # A tsibble: 58 x 9 [1Y]
## # Key:       Country [1]
##    Country       Code   Year         GDP Growth   CPI Imports Exports Population
##    <fct>         <fct> <dbl>       <dbl>  <dbl> <dbl>   <dbl>   <dbl>      <dbl>
##  1 United States USA    1960     5.43e11  NA     13.6    4.20    4.97  180671000
##  2 United States USA    1961     5.63e11   2.30  13.7    4.03    4.90  183691000
##  3 United States USA    1962     6.05e11   6.10  13.9    4.13    4.81  186538000
##  4 United States USA    1963     6.39e11   4.40  14.0    4.09    4.87  189242000
##  5 United States USA    1964     6.86e11   5.80  14.2    4.10    5.10  191889000
##  6 United States USA    1965     7.44e11   6.40  14.4    4.24    4.99  194303000
##  7 United States USA    1966     8.15e11   6.50  14.9    4.55    5.02  196560000
##  8 United States USA    1967     8.62e11   2.50  15.3    4.63    5.05  198712000
##  9 United States USA    1968     9.42e11   4.80  16.0    4.94    5.08  200706000
## 10 United States USA    1969     1.02e12   3.10  16.8    4.95    5.09  202677000
## # ℹ 48 more rows

2c.

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

# 2c.Answer:
# Load aus_livestock data
library(fpp3)

# Filter for "Bulls, bullocks and steers" in Victoria
vic_cattle <- aus_livestock %>%
  filter(Animal == "Bulls, bullocks and steers", 
         State == "Victoria")

# Plot the original series
vic_cattle %>%
  autoplot(Count) +
  labs(title = "Slaughter of Bulls, Bullocks and Steers in Victoria",
       y = "Count", x = "Year")

# Apply log transformation
vic_cattle %>%
  mutate(log_Count = log(Count)) %>%
  autoplot(log_Count) +
  labs(title = "Log of Slaughter Count in Victoria",
       y = "Log(Count)", x = "Year")

2d.

Victorian Electricity Demand from vic_elec.

# 2d.Answer:
# Load vic_elec data
library(fpp3)

# Plot the original electricity demand
vic_elec %>%
  autoplot(Demand) +
  labs(title = "Victorian Electricity Demand (Original)",
       y = "Demand (MW)", x = "Time")

# Apply log transformation to Demand
vic_elec %>%
  mutate(log_Demand = log(Demand)) %>%
  autoplot(log_Demand) +
  labs(title = "Log of Victorian Electricity Demand",
       y = "Log(Demand)", x = "Time")

2e.

Gas production from aus_production.

# 2e.Answer:
# Load aus_production data
library(fpp3)

# Filter for Gas production
gas_data <- aus_production %>%
  select(Quarter, Gas)

# Plot the original Gas production
gas_data %>%
  autoplot(Gas) +
  labs(title = "Australian Gas Production (Original)", 
       y = "Gas (Terajoules)", x = "Year")

# Apply log transformation
gas_data %>%
  mutate(log_Gas = log(Gas)) %>%
  autoplot(log_Gas) +
  labs(title = "Log of Australian Gas Production", 
       y = "Log(Gas)", x = "Year")

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:
# Load fpp3 package
library(fpp3)

# View the structure of the data
glimpse(canadian_gas)
## Rows: 542
## Columns: 2
## $ Month  <mth> 1960 Jan, 1960 Feb, 1960 Mar, 1960 Apr, 1960 May, 1960 Jun, 196…
## $ Volume <dbl> 1.4306, 1.3059, 1.4022, 1.1699, 1.1161, 1.0113, 0.9660, 0.9773,…
# Plot the time series
autoplot(canadian_gas) +
  labs(title = "Canadian Monthly Gas Production", 
       y = "Billions of Cubic Metres", x = "Year")
## Plot variable not specified, automatically selected `.vars = Volume`

# Seasonal plot to check seasonality each year
gg_season(canadian_gas) +
  labs(title = "Seasonal Plot: Canadian Gas Production",
       y = "Billions of Cubic Metres")
## Plot variable not specified, automatically selected `y = Volume`

# Subseries plot to see seasonality within months across years
gg_subseries(canadian_gas) +
  labs(title = "Subseries Plot: Canadian Gas Production",
       y = "Billions of Cubic Metres")
## Plot variable not specified, automatically selected `y = Volume`

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:
# STL decomposition with adaptive seasonal window
library(fpp3)

# STL decomposition using the correct column names
canadian_gas %>%
  model(
    STL(Volume ~ season(window = "periodic"))
  ) %>%
  components() %>%
  autoplot() +
  labs(title = "STL Decomposition of Canadian Gas Production",
       y = "Billions of Cubic Metres")

3c.

How does the seasonal shape change over time? [Hint: Try plotting the seasonal component using gg_season().]

# 3c.Answer:
# Perform STL decomposition with adaptive window to capture changing seasonality
# Perform STL decomposition with a numeric seasonal window (e.g., 13 months)
decomp <- canadian_gas %>%
  model(
    STL(Volume ~ season(window = 13))  # 13 gives flexibility for changing shape
  ) %>%
  components()

# Plot the seasonal component to see how it changes over time
decomp %>%
  autoplot(season_year) +
  labs(title = "Seasonal Component Over Time: Canadian Gas Production",
       y = "Seasonal Effect", x = "Month")

3d.

produce a plausible seasonally adjusted series? What are these numbers, plot the series.

# 3d.Answer:
# Perform STL decomposition with flexible seasonal window
decomp <- canadian_gas %>%
  model(
    STL(Volume ~ season(window = 13))
  ) %>%
  components()

# View the seasonally adjusted series
decomp %>%
  select(Month, season_adjust) %>%
  print(n = 10)  # Show first 10 rows
## # A tsibble: 542 x 2 [1M]
##       Month season_adjust
##       <mth>         <dbl>
##  1 1960 Jan         0.878
##  2 1960 Feb         1.09 
##  3 1960 Mar         1.07 
##  4 1960 Apr         1.15 
##  5 1960 May         1.24 
##  6 1960 Jun         1.40 
##  7 1960 Jul         1.40 
##  8 1960 Aug         1.34 
##  9 1960 Sep         1.39 
## 10 1960 Oct         1.33 
## # ℹ 532 more rows
# Plot seasonally adjusted series
decomp %>%
  autoplot(season_adjust) +
  labs(title = "Seasonally Adjusted Canadian Gas Production",
       y = "Seasonally Adjusted Volume (Billions of Cubic Metres)",
       x = "Year")

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))
# View the selected time series
glimpse(myseries)
## Rows: 369
## Columns: 5
## Key: State, Industry [1]
## $ State       <chr> "Northern Territory", "Northern Territory", "Northern Terr…
## $ Industry    <chr> "Clothing, footwear and personal accessory retailing", "Cl…
## $ `Series ID` <chr> "A3349767W", "A3349767W", "A3349767W", "A3349767W", "A3349…
## $ Month       <mth> 1988 Apr, 1988 May, 1988 Jun, 1988 Jul, 1988 Aug, 1988 Sep…
## $ Turnover    <dbl> 2.3, 2.9, 2.6, 2.8, 2.9, 3.0, 3.1, 3.0, 4.2, 2.7, 2.5, 2.4…
# Plot the retail series
myseries %>%
  autoplot(Turnover) +
  labs(title = "Randomly Selected Australian Retail Time Series",
       y = "Turnover (Million AUD)", x = "Year")

4a.

Create a training dataset consisting of observations before 2011

myseries_train <- myseries %>%
  filter(year(Month) < 2011)
# Check date range of training data
range(myseries_train$Month)
## <yearmonth[2]>
## [1] "1988 Apr" "2010 Dec"
# Plot the training data
myseries_train %>%
  autoplot(Turnover) +
  labs(title = "Training Data: Retail Turnover (Before 2011)",
       y = "Turnover (Million AUD)", x = "Year")

4b.

Check that your data have been split appropriately by producing the following plot.

autoplot(myseries, Turnover) +
  autolayer(myseries_train, Turnover, colour = "red") +
  labs(title = "Retail Turnover: Full Series vs Training Data",
       y = "Turnover (Million AUD)", x = "Year") +
  guides(colour = guide_legend(title = "Series")) +
  scale_color_manual(values = c("black", "red"),
                     labels = c("Full Series", "Training Data"))

4c.

Fit a seasonal naïve model using SNAIVE() applied to your training data (myseries_train).

 #Answer:

# Fit the seasonal naïve model
fit <- myseries_train %>%
  model(SNAIVE(Turnover))

# View the model summary
report(fit)
## Series: Turnover 
## Model: SNAIVE 
## 
## sigma^2: 1.2856

4d.

Check the residuals.

# 4d Answer:

# Do the residuals appear to be uncorrelated and normally distributed?
# Answ:
#Time Plot: The residuals appear to fluctuate randomly around zero with no obvious patterns — a good sign.
#ACF Plot: If most spikes are within the blue bounds, residuals are uncorrelated, suggesting the model has captured seasonality effectively.
#Histogram / Density Plot: If roughly bell-shaped and centered at zero, residuals are approximately normally distributed.
#Yes, the residuals appear to be uncorrelated and roughly normally distributed, which suggests the seasonal naïve model provides a reasonable fit.

# Check residuals
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()`).

4e.

Produce forecasts for the test data with given code below:

# 4e Answer:


# Forecast using the fitted SNAIVE model on the test set (post-2010)
fc <- fit %>%  
  forecast(new_data = anti_join(myseries, myseries_train))
## Joining with `by = join_by(State, Industry, `Series ID`, Month, Turnover)`
# Plot forecasts along with the full series
fc %>%
  autoplot(myseries) +
  labs(title = "SNaïve Forecast vs Actual Retail Turnover",
       y = "Turnover (Million AUD)", x = "Year")

Joining, by = c(“State”, “Industry”, “Series ID”, “Month”, “Turnover”)

4f.

Compare the accuracy of your forecasts against the actual values with given code below:

# 4f Answ:
# In-sample (training) accuracy
fit %>% accuracy()
## # 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
# Out-of-sample (test set) forecast accuracy
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
#Interpretation:
#The first output (fit %>% accuracy()) shows how well the model fits the training data
#The second output (fc %>% accuracy(myseries)) shows how well the model predicts the test data (from 2011 onward).
#The out-of-sample errors (from fc) are generally larger than in-sample errors, which is expected. The SNaïve model captures the seasonal pattern but does not adjust for trend or other dynamics — so while simple, it serves as a benchmark model.

4g.

How sensitive are the accuracy measures to the amount of training data used?

# 4g Answer:
# Try a shorter training period (e.g., before 2006 instead of 2011)
short_train <- myseries %>% filter(year(Month) < 2006)

# Refit the SNaïve model
short_fit <- short_train %>% model(SNAIVE(Turnover))

# Forecast using reduced training set
short_fc <- short_fit %>% forecast(new_data = myseries %>% filter(year(Month) >= 2006))

# Compare accuracy
short_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   3.49  3.86  3.49  26.6  26.6  3.79  3.09 0.529
#The accuracy measures are sensitive to the amount of training data:
#Less training data may not fully capture the seasonal pattern or trend, especially in time series with evolving behavior.
#Using more training data generally improves forecast accuracy because the model has a better understanding of recurring seasonal shapes and long-term changes.
#However, if the older data is outdated or not representative of current patterns, too much training data can sometimes reduce accuracy.
#Forecast accuracy typically improves with enough recent training data to capture relevant patterns, but overly long history may introduce outdated behavior. The ideal training window balances data quantity with relevance.

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:
takeaway <- aus_retail %>%
 filter(Industry == "Takeaway food services") %>%
 summarise(Turnover = sum(Turnover))
train <- takeaway %>%
 filter(year(Month) <= 2014)
tail(train)
## # A tsibble: 6 x 2 [1M]
##      Month Turnover
##      <mth>    <dbl>
## 1 2014 Jul    1328.
## 2 2014 Aug    1335.
## 3 2014 Sep    1338.
## 4 2014 Oct    1390.
## 5 2014 Nov    1391.
## 6 2014 Dec    1494.

5b.

Fit all the appropriate benchmark methods to the training set and forecast the periods covered by the test set.

# 5b.Answer:

fit <- train %>%
 model(
 naive = NAIVE(Turnover),
 drift = RW(Turnover ~ drift()),
 mean = MEAN(Turnover),
 snaive = SNAIVE(Turnover)
 )
# Forecast 4 yrs horizon of all models estimated above
fc <- fit %>% forecast(h = "4 years")

5c.

Compute the accuracy of your forecasts. Which method does best?

# 5c.Answer:
fc %>%
 accuracy(takeaway) %>%
 arrange(MASE)
## # A tibble: 4 × 10
##   .model .type    ME  RMSE   MAE   MPE  MAPE  MASE RMSSE  ACF1
##   <chr>  <chr> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 naive  Test  -12.4  119.  96.4 -1.49  6.66  2.30  2.25 0.613
## 2 drift  Test  -93.7  130. 108.  -6.82  7.67  2.58  2.46 0.403
## 3 snaive Test  177.   192. 177.  11.7  11.7   4.22  3.64 0.902
## 4 mean   Test  829.   838. 829.  55.7  55.7  19.8  15.8  0.613

5d.

Do the residuals from the best method resemble white noise?

# 5d.Answer:
fit %>%
 select(naive) %>%
 gg_tsresiduals()
## Warning: Removed 1 row containing missing values or values outside the scale range
## (`geom_line()`).
## Warning: Removed 1 row containing missing values or values outside the scale range
## (`geom_point()`).
## Warning: Removed 1 row containing non-finite outside the scale range
## (`stat_bin()`).

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))

see head of your series to check it is a tsibble data, and remove NA’s if there is any with these commands:

head(myseries)
## # 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`))

6a.

What is the name of the series you randomly choose? Write it.

# 6a.Answer:
# It is A3349767W

6b.

Run a linear regression of Turnover on trend.(Hint: use TSLM() and trend() functions)

# 6b.Answer:
fit = myseries %>% model(TSLM(Turnover~ trend()))

6c.

See the regression result by report() command.

# 6c.Answer:

report(fit)
## 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:
fit %>% forecast(h=36)
## # 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:
fit %>% forecast(h=36 )%>% autoplot(myseries)

# When use autoplot() and use the name of the original series in the autoplot function as autoplot(myseries) , 
#then it plots forecasts with the orginal together. No need to use autolayer() command.
# If you use autoplot() without the original series name, it only plots the forecasted values:
fit %>% forecast(h=36 )%>% autoplot()

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:
fit %>% gg_tsresiduals()

# not normally distributed, and has autocorrelation. so it is not white noise!
# augment() gives the fitted and residuals. It is saved as .fitted and .resid

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:
jan_vic_elec %>%
 ggplot(aes(x = Temperature, y = Demand)) +
 geom_point()

 fit <- jan_vic_elec %>%
 model(TSLM(Demand ~ Temperature))
 fit %>% report()
## Series: Demand 
## Model: TSLM 
## 
## Residuals:
##      Min       1Q   Median       3Q      Max 
## -49978.2 -10218.9   -121.3  18533.2  35440.6 
## 
## 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.8897e-11
## Series: Demand
## Model: TSLM
##
## Residuals:
## Min 1Q Median 3Q Max
## -49978.2 -10218.9 -121.3 18533.2 35440.6
##
## 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.8897e-11
#It is clear that a positive relationship exists for this data. It is largely driven by days with high temperatur that is resulting in more electricity being demanded (presumably to keep things cool).

7b.

Produce a residual plot. Is the model adequate? Are there any outliers or influential observations?

# 7b.Answer:
fit %>% gg_tsresiduals()

#The residuals in this portion of the data indicate that the model may be missing a trend. #However, when viewed over a longer time period, this doesn’t appear to be a genuine pattern. #The high variability in some points also suggests the presence of outliers.

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:
library(fpp3)

# Step 1: Aggregate to daily data for Jan 2014
jan_vic_elec <- vic_elec %>%
  filter(yearmonth(Time) == yearmonth("2014 Jan")) %>%
  index_by(Date = as_date(Time)) %>%
  summarise(
    Demand = sum(Demand),
    Temperature = max(Temperature)
  )

# Step 2: Fit linear regression model
fit <- jan_vic_elec %>%
  model(tslm_model = TSLM(Demand ~ Temperature))

# Step 3: Create two future (non-overlapping) dates
next_day <- bind_rows(
  new_data(jan_vic_elec, 1) %>% mutate(Temperature = 15, Scenario = "Cold Day"),
  new_data(jan_vic_elec, 1) %>% mutate(Temperature = 35, Scenario = "Hot Day") %>%
    mutate(Date = Date + 1)  # shift 1 day forward to avoid duplicate index
)

# Step 4: Forecast using model
fc <- forecast(fit, new_data = next_day)

# Step 5: Plot results with forecasted points
autoplot(jan_vic_elec, Demand) +
  geom_point(data = fc, aes(x = Date, y = .mean, color = Scenario), size = 3) +
  labs(title = "Forecast: Electricity Demand on Cold vs Hot Days",
       y = "Daily Demand (MW)", x = "Date") +
  scale_color_manual(values = c("Cold Day" = "blue", "Hot Day" = "red"))

fc %>% as_tibble() %>% select(Scenario, Temperature, .mean)
## # A tibble: 2 × 3
##   Scenario Temperature   .mean
##   <chr>          <dbl>   <dbl>
## 1 Cold Day          15 151398.
## 2 Hot Day           35 274484.
#Using the linear regression model Demand ~ Temperature, I forecasted electricity demand for two hypothetical next-day scenarios:

#Cold Day (15°C)

#Hot Day (35°C)

#The model predicts higher electricity demand on the hot day, which is consistent with real-world behavior in summer — when air conditioning usage increases sharply with temperature.

#Do I believe these forecasts?
#yes, they are reasonable. The model reflects a clear and logical pattern: hotter temperatures lead to higher demand. However, the model is based only on January 2014, so for more reliable forecasting, it would be better to train the model on a larger and more varied dataset.

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)

#yes, they are reasonable. The model reflects a clear and logical pattern: hotter temperatures lead to higher demand. However, the model is based only on January 2014, so for more reliable forecasting, it would be better to train the model on a larger and more varied dataset.

7e.

Give prediction intervals for your forecasts.

# 7e.Answer:
fc %>%
 hilo(95) %>%
 select(-.model)
## # A tsibble: 2 x 6 [1D]
##   Date                   Demand
##   <date>                 <dist>
## 1 2014-02-01 N(151398, 6.8e+08)
## 2 2014-02-02 N(274484, 6.4e+08)
## # ℹ 4 more variables: .mean <dbl>, Temperature <dbl>, Scenario <chr>,
## #   `95%` <hilo>

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)
setwd("C:/Users/pooja/OneDrive/Desktop/RAssignment2")
shampoo <- read_excel("shampoo-2.xlsx")
#View(shampoo)
#b. Is the data annual, monthly, quarterly?
 str(shampoo) #data frame
## tibble [36 × 2] (S3: tbl_df/tbl/data.frame)
##  $ Month: POSIXct[1:36], format: "1995-01-01" "1995-02-01" ...
##  $ sales: num [1:36] 266 146 183 119 180 ...
#b. Is the data annual, monthly, quarterly?
 
 str(shampoo)
## tibble [36 × 2] (S3: tbl_df/tbl/data.frame)
##  $ Month: POSIXct[1:36], format: "1995-01-01" "1995-02-01" ...
##  $ sales: num [1:36] 266 146 183 119 180 ...
#c. Convert the data into tibble , then tsibble 
mydata = shampoo %>%
 mutate(MONTHLY = yearmonth(Month)) %>% as_tsibble(index = MONTHLY) %>% select(-Month)
str(mydata)
## tbl_ts [36 × 2] (S3: tbl_ts/tbl_df/tbl/data.frame)
##  $ sales  : num [1:36] 266 146 183 119 180 ...
##  $ MONTHLY: mth [1:36] 1995 Jan, 1995 Feb, 1995 Mar, 1995 Apr, 1995 May, 1995 Jun,...
##  - attr(*, "key")= tibble [1 × 1] (S3: tbl_df/tbl/data.frame)
##   ..$ .rows: list<int> [1:1] 
##   .. ..$ : int [1:36] 1 2 3 4 5 6 7 8 9 10 ...
##   .. ..@ ptype: int(0) 
##  - attr(*, "index")= chr "MONTHLY"
##   ..- attr(*, "ordered")= logi TRUE
##  - attr(*, "index2")= chr "MONTHLY"
##  - attr(*, "interval")= interval [1:1] 1M
##   ..@ .regular: logi TRUE
mydata
## # A tsibble: 36 x 2 [1M]
##    sales  MONTHLY
##    <dbl>    <mth>
##  1  266  1995 Jan
##  2  146. 1995 Feb
##  3  183. 1995 Mar
##  4  119. 1995 Apr
##  5  180. 1995 May
##  6  168. 1995 Jun
##  7  232. 1995 Jul
##  8  224. 1995 Aug
##  9  193. 1995 Sep
## 10  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$sales, type ="l")

mydata %>%
 autoplot(sales) +
 labs(title = "Monthly Shampoo Sales", y= "in $")

# 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.
meanSales = mean(shampoo$sales)
meanSales
## [1] 312.6
hist(shampoo$sales)

mydata %>%
 ggplot(aes(x=sales)) +
 geom_histogram(bin=10)
## Warning in geom_histogram(bin = 10): Ignoring unknown parameters: `bin`
## `stat_bin()` using `bins = 30`. Pick better value with `binwidth`.

#f. Get seasonal plot. What do you see/ is there any pattern, is tehre any seasonality.
mydata %>% gg_season(sales) # yes, there is a trend. 1997 is higher than 1996 and than 1995.

mydata %>% gg_subseries(sales) # it looks like there is monthly effect. it is higher injul-december interval.

#g. Get a linear regression line with trend and dummy for each month (Hint: use trend and season in regression equation).
fit = mydata %>% model(TSLM(sales ~ trend() + season()))
  
#h. Comment on each estimated coefficient of the model.Are they statistically significant at 5 % significance level?
report(fit)
## 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?
# december and november.

  
#j. Forecast it for the next year. What are the values
 forecasts = fit %>% forecast(h=12)
forecasts
## # A fable: 12 x 4 [1M]
## # Key:     .model [1]
##    .model                            MONTHLY
##    <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>
#k. Plot the forecast with original data.
fit %>% forecast(h=12) %>% autoplot(mydata)

forecasts %>% autoplot(mydata)

#l. Check if the residuals of the model is white noise.

fit %>% gg_tsresiduals

# it is autocorrelation at 1 lag.
 ### Answ: not white noise.
  
#m. By using the regression model, forecast the 1 year ahead, and then check the accuracy of the forecast. What is MSE, RMSE values?

accuracy(fit)
## # A tibble: 1 × 10
##   .model             .type        ME  RMSE   MAE   MPE  MAPE  MASE RMSSE    ACF1
##   <chr>              <chr>     <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>   <dbl>
## 1 TSLM(sales ~ tren… Trai… -5.53e-15  72.1  59.6 -4.55  23.1 0.388 0.378 -0.0363
LS0tDQp0aXRsZTogIkVDT04gNjYzNSAtIEVYQU0gSSBTcHJpbmcgMjAyNSAiDQphdXRob3I6IFBvb2phIERpbGlwIFRhbGlrb3RpICBhbmQgcHRhbGlAdW5oLm5ld2hhdmVuLmVkdSANCmRhdGU6ICJgciBTeXMuRGF0ZSgpYCINCm91dHB1dDogb3BlbmludHJvOjpsYWJfcmVwb3J0DQogIA0KLS0tDQoNCmBgYHtyIHNldHVwLCBpbmNsdWRlPUZBTFNFfQ0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KGVjaG8gPSBUUlVFKQ0KDQpgYGANCg0KDQpgYGB7cn0NCmxpYnJhcnkoZnBwMykNCmxpYnJhcnkodGlkeXZlcnNlKQ0KU3lzLnRpbWUoKQ0KYGBgDQoNCiMjIyAxLgkNCkNvbnNpZGVyIHRoZSBHRFAgaW5mb3JtYXRpb24gaW4gZGF0YSBzZXQgY2FsbGVkIGdsb2JhbF9lY29ub215LCB3aGljaCBpcyBhbHJlYWR5IGVtYmVkZGVkIGluIGZwcDMgcGFja2FnZSAobm8gbmVlZCB0byB1cGxvYWQgZXh0ZXJuYWxseSkgDQoNCiMjIyAxLglDaG9vc2UgYSByYW5kb20gY291bnRyeSBieSB5b3Vyc2VsZi4gVGhlbiBwbG90IHRoZSBHRFAgcGVyIGNhcGl0YSBmb3IgdGhpcyBjb3VudHJ5IG92ZXIgdGltZT8gSG93IEdEUCBwZXIgY2FwaXRhIGhhcyBjaGFuZ2VkIG92ZXIgdGltZSBmb3IgdGhlIHNlcmllcyB5b3UgY2hvc2U/IEV4cGxhaW4gYnJpZWZseS4NCg0KYGBge3J9DQpnbG9iYWxfZWNvbm9teSAjIHNlZSB0aGUgZGF0YS4NCg0KbGlicmFyeShmcHAzKQ0KDQojIFZpZXcgdGhlIHN0cnVjdHVyZSBvZiB0aGUgZGF0YXNldA0KZ2xpbXBzZShnbG9iYWxfZWNvbm9teSkNCg0KIyBDaG9vc2UgYSByYW5kb20gY291bnRyeSwgZS5nLiwgIkluZGlhIg0KaW5kaWFfZ2RwIDwtIGdsb2JhbF9lY29ub215ICU+JSANCiAgZmlsdGVyKENvdW50cnkgPT0gIkluZGlhIikNCg0KIyBDcmVhdGUgYSBHRFAgcGVyIGNhcGl0YSB2YXJpYWJsZQ0KaW5kaWFfZ2RwIDwtIGluZGlhX2dkcCAlPiUNCiAgbXV0YXRlKEdEUF9wZXJfY2FwaXRhID0gR0RQIC8gUG9wdWxhdGlvbikNCg0KIyBQbG90IEdEUCBwZXIgY2FwaXRhIG92ZXIgdGltZQ0KaW5kaWFfZ2RwICU+JQ0KICBhdXRvcGxvdChHRFBfcGVyX2NhcGl0YSkgKw0KICBsYWJzKHRpdGxlID0gIkluZGlhOiBHRFAgcGVyIENhcGl0YSBPdmVyIFRpbWUiLA0KICAgICAgIHkgPSAiR0RQIHBlciBDYXBpdGEgKFVTRCkiLCB4ID0gIlllYXIiKQ0KDQojIDEuQW5zd2VyOg0KDQpgYGANCg0KIyMjIDIuCQ0KRm9yIGVhY2ggb2YgdGhlIGZvbGxvd2luZyBzZXJpZXMsIG1ha2UgYSBncmFwaCBvZiB0aGUgZGF0YS4gSWYgdHJhbnNmb3JtaW5nIHNlZW1zIGFwcHJvcHJpYXRlLCBkbyBzbyBhbmQgZGVzY3JpYmUgdGhlIGVmZmVjdC4gQ29tbWVudCBiZWxvdyBpbiBhbnN3ZXI6DQoNCiMjIyAyYS4gVXNlIHRoZSBzZXJpZXMgeW91IGNob3NlIGluICMxLg0KYGBge3J9DQoNCiMgMmEuQW5zd2VyOg0KIyBPcmlnaW5hbCBHRFAgcGVyIGNhcGl0YSBwbG90DQppbmRpYV9nZHAgJT4lDQogIGF1dG9wbG90KEdEUF9wZXJfY2FwaXRhKSArDQogIGxhYnModGl0bGUgPSAiSW5kaWE6IEdEUCBwZXIgQ2FwaXRhIChPcmlnaW5hbCkiLCANCiAgICAgICB5ID0gIkdEUCBwZXIgQ2FwaXRhIiwgeCA9ICJZZWFyIikNCg0KIyBBcHBseSBsb2cgdHJhbnNmb3JtYXRpb24NCmluZGlhX2dkcCAlPiUNCiAgbXV0YXRlKGxvZ19HRFBfcGVyX2NhcGl0YSA9IGxvZyhHRFBfcGVyX2NhcGl0YSkpICU+JQ0KICBhdXRvcGxvdChsb2dfR0RQX3Blcl9jYXBpdGEpICsNCiAgbGFicyh0aXRsZSA9ICJJbmRpYTogTG9nIG9mIEdEUCBwZXIgQ2FwaXRhIiwgDQogICAgICAgeSA9ICJMb2coR0RQIHBlciBDYXBpdGEpIiwgeCA9ICJZZWFyIikNCg0KYGBgDQoNCiMjIyAyYi4JDQpVbml0ZWQgU3RhdGVzIEdEUCBmcm9tIGdsb2JhbF9lY29ub215Lg0KYGBge3J9DQoNCg0KIyAyYi5BbnN3ZXI6DQojIEZpbHRlciBmb3IgVW5pdGVkIFN0YXRlcw0KdXNfZ2RwIDwtIGdsb2JhbF9lY29ub215ICU+JQ0KICBmaWx0ZXIoQ291bnRyeSA9PSAiVW5pdGVkIFN0YXRlcyIpDQoNCiMgUGxvdCBvcmlnaW5hbCBHRFANCnVzX2dkcCAlPiUNCiAgYXV0b3Bsb3QoR0RQKSArDQogIGxhYnModGl0bGUgPSAiVW5pdGVkIFN0YXRlczogR0RQIChPcmlnaW5hbCkiLCANCiAgICAgICB5ID0gIkdEUCAoaW4gQmlsbGlvbnMgVVNEKSIsIHggPSAiWWVhciIpDQoNCiMgQXBwbHkgbG9nIHRyYW5zZm9ybWF0aW9uIHRvIEdEUA0KdXNfZ2RwICU+JQ0KICBtdXRhdGUNCg0KDQpgYGANCg0KIyMjIDJjLgkNClNsYXVnaHRlciBvZiBWaWN0b3JpYW4g4oCcQnVsbHMsIGJ1bGxvY2tzIGFuZCBzdGVlcnPigJ0gaW4gYXVzX2xpdmVzdG9jaw0KYGBge3J9DQoNCiMgMmMuQW5zd2VyOg0KIyBMb2FkIGF1c19saXZlc3RvY2sgZGF0YQ0KbGlicmFyeShmcHAzKQ0KDQojIEZpbHRlciBmb3IgIkJ1bGxzLCBidWxsb2NrcyBhbmQgc3RlZXJzIiBpbiBWaWN0b3JpYQ0KdmljX2NhdHRsZSA8LSBhdXNfbGl2ZXN0b2NrICU+JQ0KICBmaWx0ZXIoQW5pbWFsID09ICJCdWxscywgYnVsbG9ja3MgYW5kIHN0ZWVycyIsIA0KICAgICAgICAgU3RhdGUgPT0gIlZpY3RvcmlhIikNCg0KIyBQbG90IHRoZSBvcmlnaW5hbCBzZXJpZXMNCnZpY19jYXR0bGUgJT4lDQogIGF1dG9wbG90KENvdW50KSArDQogIGxhYnModGl0bGUgPSAiU2xhdWdodGVyIG9mIEJ1bGxzLCBCdWxsb2NrcyBhbmQgU3RlZXJzIGluIFZpY3RvcmlhIiwNCiAgICAgICB5ID0gIkNvdW50IiwgeCA9ICJZZWFyIikNCg0KIyBBcHBseSBsb2cgdHJhbnNmb3JtYXRpb24NCnZpY19jYXR0bGUgJT4lDQogIG11dGF0ZShsb2dfQ291bnQgPSBsb2coQ291bnQpKSAlPiUNCiAgYXV0b3Bsb3QobG9nX0NvdW50KSArDQogIGxhYnModGl0bGUgPSAiTG9nIG9mIFNsYXVnaHRlciBDb3VudCBpbiBWaWN0b3JpYSIsDQogICAgICAgeSA9ICJMb2coQ291bnQpIiwgeCA9ICJZZWFyIikNCg0KDQpgYGANCg0KIyMjIDJkLg0KVmljdG9yaWFuIEVsZWN0cmljaXR5IERlbWFuZCBmcm9tIHZpY19lbGVjLg0KYGBge3J9DQoNCg0KIyAyZC5BbnN3ZXI6DQojIExvYWQgdmljX2VsZWMgZGF0YQ0KbGlicmFyeShmcHAzKQ0KDQojIFBsb3QgdGhlIG9yaWdpbmFsIGVsZWN0cmljaXR5IGRlbWFuZA0KdmljX2VsZWMgJT4lDQogIGF1dG9wbG90KERlbWFuZCkgKw0KICBsYWJzKHRpdGxlID0gIlZpY3RvcmlhbiBFbGVjdHJpY2l0eSBEZW1hbmQgKE9yaWdpbmFsKSIsDQogICAgICAgeSA9ICJEZW1hbmQgKE1XKSIsIHggPSAiVGltZSIpDQoNCiMgQXBwbHkgbG9nIHRyYW5zZm9ybWF0aW9uIHRvIERlbWFuZA0KdmljX2VsZWMgJT4lDQogIG11dGF0ZShsb2dfRGVtYW5kID0gbG9nKERlbWFuZCkpICU+JQ0KICBhdXRvcGxvdChsb2dfRGVtYW5kKSArDQogIGxhYnModGl0bGUgPSAiTG9nIG9mIFZpY3RvcmlhbiBFbGVjdHJpY2l0eSBEZW1hbmQiLA0KICAgICAgIHkgPSAiTG9nKERlbWFuZCkiLCB4ID0gIlRpbWUiKQ0KDQoNCmBgYA0KDQojIyMgMmUuCQ0KR2FzIHByb2R1Y3Rpb24gZnJvbSBhdXNfcHJvZHVjdGlvbi4NCmBgYHtyfQ0KDQoNCiMgMmUuQW5zd2VyOg0KIyBMb2FkIGF1c19wcm9kdWN0aW9uIGRhdGENCmxpYnJhcnkoZnBwMykNCg0KIyBGaWx0ZXIgZm9yIEdhcyBwcm9kdWN0aW9uDQpnYXNfZGF0YSA8LSBhdXNfcHJvZHVjdGlvbiAlPiUNCiAgc2VsZWN0KFF1YXJ0ZXIsIEdhcykNCg0KIyBQbG90IHRoZSBvcmlnaW5hbCBHYXMgcHJvZHVjdGlvbg0KZ2FzX2RhdGEgJT4lDQogIGF1dG9wbG90KEdhcykgKw0KICBsYWJzKHRpdGxlID0gIkF1c3RyYWxpYW4gR2FzIFByb2R1Y3Rpb24gKE9yaWdpbmFsKSIsIA0KICAgICAgIHkgPSAiR2FzIChUZXJham91bGVzKSIsIHggPSAiWWVhciIpDQoNCiMgQXBwbHkgbG9nIHRyYW5zZm9ybWF0aW9uDQpnYXNfZGF0YSAlPiUNCiAgbXV0YXRlKGxvZ19HYXMgPSBsb2coR2FzKSkgJT4lDQogIGF1dG9wbG90KGxvZ19HYXMpICsNCiAgbGFicyh0aXRsZSA9ICJMb2cgb2YgQXVzdHJhbGlhbiBHYXMgUHJvZHVjdGlvbiIsIA0KICAgICAgIHkgPSAiTG9nKEdhcykiLCB4ID0gIlllYXIiKQ0KDQoNCmBgYA0KDQojIyMgMy4JVXNlIHRoZSBjYW5hZGlhbl9nYXMgZGF0YSAobW9udGhseSBDYW5hZGlhbiBnYXMgcHJvZHVjdGlvbiBpbiBiaWxsaW9ucyBvZiBjdWJpYyBtZXRyZXMsIEphbnVhcnkgMTk2MCDigJMgRmVicnVhcnkgMjAwNSkuDQojIyMjIDJhLglQbG90IHRoZSBkYXRhIHVzaW5nIGF1dG9wbG90KCksIGdnX3N1YnNlcmllcygpICwgZ2dfc2Vhc29uKCkgdG8gbG9vayBhdCB0aGUgZWZmZWN0IG9mIHRoZSBjaGFuZ2luZyBzZWFzb25hbGl0eSBvdmVyIHRpbWUuIERlc2NyaWJlIHRoZSBncmFwaHMgaW4geW91ciBvd24gd29yZHMuIFdoYXQgZG8geW91IHNlZT8gV2hhdCB0eXBlIHBmIHBhdHRlcm4gZG8geW91IG9ic2VydmU/DQoNCmBgYHtyfQ0KDQoNCiMgM2EuQW5zd2VyOg0KIyBMb2FkIGZwcDMgcGFja2FnZQ0KbGlicmFyeShmcHAzKQ0KDQojIFZpZXcgdGhlIHN0cnVjdHVyZSBvZiB0aGUgZGF0YQ0KZ2xpbXBzZShjYW5hZGlhbl9nYXMpDQoNCiMgUGxvdCB0aGUgdGltZSBzZXJpZXMNCmF1dG9wbG90KGNhbmFkaWFuX2dhcykgKw0KICBsYWJzKHRpdGxlID0gIkNhbmFkaWFuIE1vbnRobHkgR2FzIFByb2R1Y3Rpb24iLCANCiAgICAgICB5ID0gIkJpbGxpb25zIG9mIEN1YmljIE1ldHJlcyIsIHggPSAiWWVhciIpDQoNCiMgU2Vhc29uYWwgcGxvdCB0byBjaGVjayBzZWFzb25hbGl0eSBlYWNoIHllYXINCmdnX3NlYXNvbihjYW5hZGlhbl9nYXMpICsNCiAgbGFicyh0aXRsZSA9ICJTZWFzb25hbCBQbG90OiBDYW5hZGlhbiBHYXMgUHJvZHVjdGlvbiIsDQogICAgICAgeSA9ICJCaWxsaW9ucyBvZiBDdWJpYyBNZXRyZXMiKQ0KDQojIFN1YnNlcmllcyBwbG90IHRvIHNlZSBzZWFzb25hbGl0eSB3aXRoaW4gbW9udGhzIGFjcm9zcyB5ZWFycw0KZ2dfc3Vic2VyaWVzKGNhbmFkaWFuX2dhcykgKw0KICBsYWJzKHRpdGxlID0gIlN1YnNlcmllcyBQbG90OiBDYW5hZGlhbiBHYXMgUHJvZHVjdGlvbiIsDQogICAgICAgeSA9ICJCaWxsaW9ucyBvZiBDdWJpYyBNZXRyZXMiKQ0KDQoNCmBgYA0KDQojIyMgM2IuDQpEbyBhbiBTVEwgZGVjb21wb3NpdGlvbiBvZiB0aGUgZGF0YS4gWW91IHdpbGwgbmVlZCB0byBjaG9vc2UgYSBzZWFzb25hbCB3aW5kb3cgdG8gYWxsb3cgZm9yIHRoZSBjaGFuZ2luZyBzaGFwZSBvZiB0aGUgc2Vhc29uYWwgY29tcG9uZW50Lg0KDQpgYGB7cn0NCg0KIyAzYi5BbnN3ZXI6DQojIFNUTCBkZWNvbXBvc2l0aW9uIHdpdGggYWRhcHRpdmUgc2Vhc29uYWwgd2luZG93DQpsaWJyYXJ5KGZwcDMpDQoNCiMgU1RMIGRlY29tcG9zaXRpb24gdXNpbmcgdGhlIGNvcnJlY3QgY29sdW1uIG5hbWVzDQpjYW5hZGlhbl9nYXMgJT4lDQogIG1vZGVsKA0KICAgIFNUTChWb2x1bWUgfiBzZWFzb24od2luZG93ID0gInBlcmlvZGljIikpDQogICkgJT4lDQogIGNvbXBvbmVudHMoKSAlPiUNCiAgYXV0b3Bsb3QoKSArDQogIGxhYnModGl0bGUgPSAiU1RMIERlY29tcG9zaXRpb24gb2YgQ2FuYWRpYW4gR2FzIFByb2R1Y3Rpb24iLA0KICAgICAgIHkgPSAiQmlsbGlvbnMgb2YgQ3ViaWMgTWV0cmVzIikNCg0KYGBgDQoNCiMjIyAzYy4NCkhvdyBkb2VzIHRoZSBzZWFzb25hbCBzaGFwZSBjaGFuZ2Ugb3ZlciB0aW1lPyBbSGludDogVHJ5IHBsb3R0aW5nIHRoZSBzZWFzb25hbCBjb21wb25lbnQgdXNpbmcgZ2dfc2Vhc29uKCkuXQ0KYGBge3J9DQoNCg0KIyAzYy5BbnN3ZXI6DQojIFBlcmZvcm0gU1RMIGRlY29tcG9zaXRpb24gd2l0aCBhZGFwdGl2ZSB3aW5kb3cgdG8gY2FwdHVyZSBjaGFuZ2luZyBzZWFzb25hbGl0eQ0KIyBQZXJmb3JtIFNUTCBkZWNvbXBvc2l0aW9uIHdpdGggYSBudW1lcmljIHNlYXNvbmFsIHdpbmRvdyAoZS5nLiwgMTMgbW9udGhzKQ0KZGVjb21wIDwtIGNhbmFkaWFuX2dhcyAlPiUNCiAgbW9kZWwoDQogICAgU1RMKFZvbHVtZSB+IHNlYXNvbih3aW5kb3cgPSAxMykpICAjIDEzIGdpdmVzIGZsZXhpYmlsaXR5IGZvciBjaGFuZ2luZyBzaGFwZQ0KICApICU+JQ0KICBjb21wb25lbnRzKCkNCg0KIyBQbG90IHRoZSBzZWFzb25hbCBjb21wb25lbnQgdG8gc2VlIGhvdyBpdCBjaGFuZ2VzIG92ZXIgdGltZQ0KZGVjb21wICU+JQ0KICBhdXRvcGxvdChzZWFzb25feWVhcikgKw0KICBsYWJzKHRpdGxlID0gIlNlYXNvbmFsIENvbXBvbmVudCBPdmVyIFRpbWU6IENhbmFkaWFuIEdhcyBQcm9kdWN0aW9uIiwNCiAgICAgICB5ID0gIlNlYXNvbmFsIEVmZmVjdCIsIHggPSAiTW9udGgiKQ0KDQoNCmBgYA0KDQojIyMgM2QuCQ0KcHJvZHVjZSBhIHBsYXVzaWJsZSBzZWFzb25hbGx5IGFkanVzdGVkIHNlcmllcz8gV2hhdCBhcmUgdGhlc2UgbnVtYmVycywgcGxvdCB0aGUgc2VyaWVzLg0KYGBge3J9DQoNCiMgM2QuQW5zd2VyOg0KIyBQZXJmb3JtIFNUTCBkZWNvbXBvc2l0aW9uIHdpdGggZmxleGlibGUgc2Vhc29uYWwgd2luZG93DQpkZWNvbXAgPC0gY2FuYWRpYW5fZ2FzICU+JQ0KICBtb2RlbCgNCiAgICBTVEwoVm9sdW1lIH4gc2Vhc29uKHdpbmRvdyA9IDEzKSkNCiAgKSAlPiUNCiAgY29tcG9uZW50cygpDQoNCiMgVmlldyB0aGUgc2Vhc29uYWxseSBhZGp1c3RlZCBzZXJpZXMNCmRlY29tcCAlPiUNCiAgc2VsZWN0KE1vbnRoLCBzZWFzb25fYWRqdXN0KSAlPiUNCiAgcHJpbnQobiA9IDEwKSAgIyBTaG93IGZpcnN0IDEwIHJvd3MNCg0KIyBQbG90IHNlYXNvbmFsbHkgYWRqdXN0ZWQgc2VyaWVzDQpkZWNvbXAgJT4lDQogIGF1dG9wbG90KHNlYXNvbl9hZGp1c3QpICsNCiAgbGFicyh0aXRsZSA9ICJTZWFzb25hbGx5IEFkanVzdGVkIENhbmFkaWFuIEdhcyBQcm9kdWN0aW9uIiwNCiAgICAgICB5ID0gIlNlYXNvbmFsbHkgQWRqdXN0ZWQgVm9sdW1lIChCaWxsaW9ucyBvZiBDdWJpYyBNZXRyZXMpIiwNCiAgICAgICB4ID0gIlllYXIiKQ0KDQoNCmBgYA0KDQojIyMgNC4NCkZvciByZXRhaWwgdGltZSBzZXJpZXMsIHVzZSB0aGUgYmVsb3cgY29kZToNCg0KYGBge3J9DQojIHJ1biB0aGUgY29kZQ0Kc2V0LnNlZWQoMTIzNDU2NzgpDQoNCm15c2VyaWVzIDwtIGF1c19yZXRhaWwgJT4lDQogIGZpbHRlcihgU2VyaWVzIElEYCA9PSBzYW1wbGUoYXVzX3JldGFpbCRgU2VyaWVzIElEYCwxKSkNCiMgVmlldyB0aGUgc2VsZWN0ZWQgdGltZSBzZXJpZXMNCmdsaW1wc2UobXlzZXJpZXMpDQoNCiMgUGxvdCB0aGUgcmV0YWlsIHNlcmllcw0KbXlzZXJpZXMgJT4lDQogIGF1dG9wbG90KFR1cm5vdmVyKSArDQogIGxhYnModGl0bGUgPSAiUmFuZG9tbHkgU2VsZWN0ZWQgQXVzdHJhbGlhbiBSZXRhaWwgVGltZSBTZXJpZXMiLA0KICAgICAgIHkgPSAiVHVybm92ZXIgKE1pbGxpb24gQVVEKSIsIHggPSAiWWVhciIpDQoNCmBgYA0KDQojIyMjIDRhLiANCkNyZWF0ZSBhIHRyYWluaW5nIGRhdGFzZXQgY29uc2lzdGluZyBvZiBvYnNlcnZhdGlvbnMgYmVmb3JlIDIwMTEgDQoNCmBgYHtyfQ0KbXlzZXJpZXNfdHJhaW4gPC0gbXlzZXJpZXMgJT4lDQogIGZpbHRlcih5ZWFyKE1vbnRoKSA8IDIwMTEpDQojIENoZWNrIGRhdGUgcmFuZ2Ugb2YgdHJhaW5pbmcgZGF0YQ0KcmFuZ2UobXlzZXJpZXNfdHJhaW4kTW9udGgpDQoNCiMgUGxvdCB0aGUgdHJhaW5pbmcgZGF0YQ0KbXlzZXJpZXNfdHJhaW4gJT4lDQogIGF1dG9wbG90KFR1cm5vdmVyKSArDQogIGxhYnModGl0bGUgPSAiVHJhaW5pbmcgRGF0YTogUmV0YWlsIFR1cm5vdmVyIChCZWZvcmUgMjAxMSkiLA0KICAgICAgIHkgPSAiVHVybm92ZXIgKE1pbGxpb24gQVVEKSIsIHggPSAiWWVhciIpDQoNCg0KYGBgDQoNCiMjIyMgNGIuCQ0KQ2hlY2sgdGhhdCB5b3VyIGRhdGEgaGF2ZSBiZWVuIHNwbGl0IGFwcHJvcHJpYXRlbHkgYnkgcHJvZHVjaW5nIHRoZSBmb2xsb3dpbmcgcGxvdC4NCg0KYGBge3J9DQoNCmF1dG9wbG90KG15c2VyaWVzLCBUdXJub3ZlcikgKw0KICBhdXRvbGF5ZXIobXlzZXJpZXNfdHJhaW4sIFR1cm5vdmVyLCBjb2xvdXIgPSAicmVkIikgKw0KICBsYWJzKHRpdGxlID0gIlJldGFpbCBUdXJub3ZlcjogRnVsbCBTZXJpZXMgdnMgVHJhaW5pbmcgRGF0YSIsDQogICAgICAgeSA9ICJUdXJub3ZlciAoTWlsbGlvbiBBVUQpIiwgeCA9ICJZZWFyIikgKw0KICBndWlkZXMoY29sb3VyID0gZ3VpZGVfbGVnZW5kKHRpdGxlID0gIlNlcmllcyIpKSArDQogIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSBjKCJibGFjayIsICJyZWQiKSwNCiAgICAgICAgICAgICAgICAgICAgIGxhYmVscyA9IGMoIkZ1bGwgU2VyaWVzIiwgIlRyYWluaW5nIERhdGEiKSkNCg0KYGBgDQoNCiMjIyMgNGMuCQ0KRml0IGEgc2Vhc29uYWwgbmHDr3ZlIG1vZGVsIHVzaW5nIFNOQUlWRSgpIGFwcGxpZWQgdG8geW91ciB0cmFpbmluZyBkYXRhIChteXNlcmllc190cmFpbikuDQpgYGB7cn0NCiAjQW5zd2VyOg0KDQojIEZpdCB0aGUgc2Vhc29uYWwgbmHDr3ZlIG1vZGVsDQpmaXQgPC0gbXlzZXJpZXNfdHJhaW4gJT4lDQogIG1vZGVsKFNOQUlWRShUdXJub3ZlcikpDQoNCiMgVmlldyB0aGUgbW9kZWwgc3VtbWFyeQ0KcmVwb3J0KGZpdCkNCg0KYGBgDQoNCg0KIyMjIyA0ZC4NCkNoZWNrIHRoZSByZXNpZHVhbHMuDQpgYGB7cn0NCg0KIyA0ZCBBbnN3ZXI6DQoNCiMgRG8gdGhlIHJlc2lkdWFscyBhcHBlYXIgdG8gYmUgdW5jb3JyZWxhdGVkIGFuZCBub3JtYWxseSBkaXN0cmlidXRlZD8NCiMgQW5zdzoNCiNUaW1lIFBsb3Q6IFRoZSByZXNpZHVhbHMgYXBwZWFyIHRvIGZsdWN0dWF0ZSByYW5kb21seSBhcm91bmQgemVybyB3aXRoIG5vIG9idmlvdXMgcGF0dGVybnMg4oCUIGEgZ29vZCBzaWduLg0KI0FDRiBQbG90OiBJZiBtb3N0IHNwaWtlcyBhcmUgd2l0aGluIHRoZSBibHVlIGJvdW5kcywgcmVzaWR1YWxzIGFyZSB1bmNvcnJlbGF0ZWQsIHN1Z2dlc3RpbmcgdGhlIG1vZGVsIGhhcyBjYXB0dXJlZCBzZWFzb25hbGl0eSBlZmZlY3RpdmVseS4NCiNIaXN0b2dyYW0gLyBEZW5zaXR5IFBsb3Q6IElmIHJvdWdobHkgYmVsbC1zaGFwZWQgYW5kIGNlbnRlcmVkIGF0IHplcm8sIHJlc2lkdWFscyBhcmUgYXBwcm94aW1hdGVseSBub3JtYWxseSBkaXN0cmlidXRlZC4NCiNZZXMsIHRoZSByZXNpZHVhbHMgYXBwZWFyIHRvIGJlIHVuY29ycmVsYXRlZCBhbmQgcm91Z2hseSBub3JtYWxseSBkaXN0cmlidXRlZCwgd2hpY2ggc3VnZ2VzdHMgdGhlIHNlYXNvbmFsIG5hw692ZSBtb2RlbCBwcm92aWRlcyBhIHJlYXNvbmFibGUgZml0Lg0KDQojIENoZWNrIHJlc2lkdWFscw0KZml0ICU+JSBnZ190c3Jlc2lkdWFscygpDQoNCmBgYA0KDQojIyMjIDRlLg0KUHJvZHVjZSBmb3JlY2FzdHMgZm9yIHRoZSB0ZXN0IGRhdGEgd2l0aCBnaXZlbiBjb2RlIGJlbG93Og0KDQpgYGB7cn0NCiMgNGUgQW5zd2VyOg0KDQoNCiMgRm9yZWNhc3QgdXNpbmcgdGhlIGZpdHRlZCBTTkFJVkUgbW9kZWwgb24gdGhlIHRlc3Qgc2V0IChwb3N0LTIwMTApDQpmYyA8LSBmaXQgJT4lICANCiAgZm9yZWNhc3QobmV3X2RhdGEgPSBhbnRpX2pvaW4obXlzZXJpZXMsIG15c2VyaWVzX3RyYWluKSkNCg0KIyBQbG90IGZvcmVjYXN0cyBhbG9uZyB3aXRoIHRoZSBmdWxsIHNlcmllcw0KZmMgJT4lDQogIGF1dG9wbG90KG15c2VyaWVzKSArDQogIGxhYnModGl0bGUgPSAiU05hw692ZSBGb3JlY2FzdCB2cyBBY3R1YWwgUmV0YWlsIFR1cm5vdmVyIiwNCiAgICAgICB5ID0gIlR1cm5vdmVyIChNaWxsaW9uIEFVRCkiLCB4ID0gIlllYXIiKQ0KDQoNCg0KYGBgDQoNCkpvaW5pbmcsIGJ5ID0gYygiU3RhdGUiLCAiSW5kdXN0cnkiLCAiU2VyaWVzIElEIiwgIk1vbnRoIiwgIlR1cm5vdmVyIikNCg0KIyMjIyA0Zi4JDQpDb21wYXJlIHRoZSBhY2N1cmFjeSBvZiB5b3VyIGZvcmVjYXN0cyBhZ2FpbnN0IHRoZSBhY3R1YWwgdmFsdWVzIHdpdGggZ2l2ZW4gY29kZSBiZWxvdzoNCmBgYHtyfQ0KIyA0ZiBBbnN3Og0KIyBJbi1zYW1wbGUgKHRyYWluaW5nKSBhY2N1cmFjeQ0KZml0ICU+JSBhY2N1cmFjeSgpDQoNCiMgT3V0LW9mLXNhbXBsZSAodGVzdCBzZXQpIGZvcmVjYXN0IGFjY3VyYWN5DQpmYyAlPiUgYWNjdXJhY3kobXlzZXJpZXMpDQojSW50ZXJwcmV0YXRpb246DQojVGhlIGZpcnN0IG91dHB1dCAoZml0ICU+JSBhY2N1cmFjeSgpKSBzaG93cyBob3cgd2VsbCB0aGUgbW9kZWwgZml0cyB0aGUgdHJhaW5pbmcgZGF0YQ0KI1RoZSBzZWNvbmQgb3V0cHV0IChmYyAlPiUgYWNjdXJhY3kobXlzZXJpZXMpKSBzaG93cyBob3cgd2VsbCB0aGUgbW9kZWwgcHJlZGljdHMgdGhlIHRlc3QgZGF0YSAoZnJvbSAyMDExIG9ud2FyZCkuDQojVGhlIG91dC1vZi1zYW1wbGUgZXJyb3JzIChmcm9tIGZjKSBhcmUgZ2VuZXJhbGx5IGxhcmdlciB0aGFuIGluLXNhbXBsZSBlcnJvcnMsIHdoaWNoIGlzIGV4cGVjdGVkLiBUaGUgU05hw692ZSBtb2RlbCBjYXB0dXJlcyB0aGUgc2Vhc29uYWwgcGF0dGVybiBidXQgZG9lcyBub3QgYWRqdXN0IGZvciB0cmVuZCBvciBvdGhlciBkeW5hbWljcyDigJQgc28gd2hpbGUgc2ltcGxlLCBpdCBzZXJ2ZXMgYXMgYSBiZW5jaG1hcmsgbW9kZWwuDQoNCg0KYGBgDQoNCiMjIyMgNGcuDQpIb3cgc2Vuc2l0aXZlIGFyZSB0aGUgYWNjdXJhY3kgbWVhc3VyZXMgdG8gdGhlIGFtb3VudCBvZiB0cmFpbmluZyBkYXRhIHVzZWQ/DQpgYGB7cn0NCg0KIyA0ZyBBbnN3ZXI6DQojIFRyeSBhIHNob3J0ZXIgdHJhaW5pbmcgcGVyaW9kIChlLmcuLCBiZWZvcmUgMjAwNiBpbnN0ZWFkIG9mIDIwMTEpDQpzaG9ydF90cmFpbiA8LSBteXNlcmllcyAlPiUgZmlsdGVyKHllYXIoTW9udGgpIDwgMjAwNikNCg0KIyBSZWZpdCB0aGUgU05hw692ZSBtb2RlbA0Kc2hvcnRfZml0IDwtIHNob3J0X3RyYWluICU+JSBtb2RlbChTTkFJVkUoVHVybm92ZXIpKQ0KDQojIEZvcmVjYXN0IHVzaW5nIHJlZHVjZWQgdHJhaW5pbmcgc2V0DQpzaG9ydF9mYyA8LSBzaG9ydF9maXQgJT4lIGZvcmVjYXN0KG5ld19kYXRhID0gbXlzZXJpZXMgJT4lIGZpbHRlcih5ZWFyKE1vbnRoKSA+PSAyMDA2KSkNCg0KIyBDb21wYXJlIGFjY3VyYWN5DQpzaG9ydF9mYyAlPiUgYWNjdXJhY3kobXlzZXJpZXMpDQoNCiNUaGUgYWNjdXJhY3kgbWVhc3VyZXMgYXJlIHNlbnNpdGl2ZSB0byB0aGUgYW1vdW50IG9mIHRyYWluaW5nIGRhdGE6DQojTGVzcyB0cmFpbmluZyBkYXRhIG1heSBub3QgZnVsbHkgY2FwdHVyZSB0aGUgc2Vhc29uYWwgcGF0dGVybiBvciB0cmVuZCwgZXNwZWNpYWxseSBpbiB0aW1lIHNlcmllcyB3aXRoIGV2b2x2aW5nIGJlaGF2aW9yLg0KI1VzaW5nIG1vcmUgdHJhaW5pbmcgZGF0YSBnZW5lcmFsbHkgaW1wcm92ZXMgZm9yZWNhc3QgYWNjdXJhY3kgYmVjYXVzZSB0aGUgbW9kZWwgaGFzIGEgYmV0dGVyIHVuZGVyc3RhbmRpbmcgb2YgcmVjdXJyaW5nIHNlYXNvbmFsIHNoYXBlcyBhbmQgbG9uZy10ZXJtIGNoYW5nZXMuDQojSG93ZXZlciwgaWYgdGhlIG9sZGVyIGRhdGEgaXMgb3V0ZGF0ZWQgb3Igbm90IHJlcHJlc2VudGF0aXZlIG9mIGN1cnJlbnQgcGF0dGVybnMsIHRvbyBtdWNoIHRyYWluaW5nIGRhdGEgY2FuIHNvbWV0aW1lcyByZWR1Y2UgYWNjdXJhY3kuDQojRm9yZWNhc3QgYWNjdXJhY3kgdHlwaWNhbGx5IGltcHJvdmVzIHdpdGggZW5vdWdoIHJlY2VudCB0cmFpbmluZyBkYXRhIHRvIGNhcHR1cmUgcmVsZXZhbnQgcGF0dGVybnMsIGJ1dCBvdmVybHkgbG9uZyBoaXN0b3J5IG1heSBpbnRyb2R1Y2Ugb3V0ZGF0ZWQgYmVoYXZpb3IuIFRoZSBpZGVhbCB0cmFpbmluZyB3aW5kb3cgYmFsYW5jZXMgZGF0YSBxdWFudGl0eSB3aXRoIHJlbGV2YW5jZS4NCg0KDQpgYGANCg0KIyMjIDUuCQ0KIyMjIyA1YS4JDQpDcmVhdGUgYSB0cmFpbmluZyBzZXQgZm9yIEF1c3RyYWxpYW4gdGFrZWF3YXkgZm9vZCB0dXJub3ZlciAoYXVzX3JldGFpbCkgYnkgd2l0aGhvbGRpbmcgdGhlIGxhc3QgZm91ciB5ZWFycyBhcyBhIHRlc3Qgc2V0LiANCmBgYHtyfQ0KDQoNCiMgNWEuQW5zd2VyOg0KdGFrZWF3YXkgPC0gYXVzX3JldGFpbCAlPiUNCiBmaWx0ZXIoSW5kdXN0cnkgPT0gIlRha2Vhd2F5IGZvb2Qgc2VydmljZXMiKSAlPiUNCiBzdW1tYXJpc2UoVHVybm92ZXIgPSBzdW0oVHVybm92ZXIpKQ0KdHJhaW4gPC0gdGFrZWF3YXkgJT4lDQogZmlsdGVyKHllYXIoTW9udGgpIDw9IDIwMTQpDQp0YWlsKHRyYWluKQ0KYGBgDQoNCiMjIyMgNWIuCQ0KRml0IGFsbCB0aGUgYXBwcm9wcmlhdGUgYmVuY2htYXJrIG1ldGhvZHMgdG8gdGhlICAgdHJhaW5pbmcgc2V0IGFuZCBmb3JlY2FzdCB0aGUgcGVyaW9kcyBjb3ZlcmVkIGJ5IHRoZSB0ZXN0IHNldC4NCmBgYHtyfQ0KDQoNCiMgNWIuQW5zd2VyOg0KDQpmaXQgPC0gdHJhaW4gJT4lDQogbW9kZWwoDQogbmFpdmUgPSBOQUlWRShUdXJub3ZlciksDQogZHJpZnQgPSBSVyhUdXJub3ZlciB+IGRyaWZ0KCkpLA0KIG1lYW4gPSBNRUFOKFR1cm5vdmVyKSwNCiBzbmFpdmUgPSBTTkFJVkUoVHVybm92ZXIpDQogKQ0KIyBGb3JlY2FzdCA0IHlycyBob3Jpem9uIG9mIGFsbCBtb2RlbHMgZXN0aW1hdGVkIGFib3ZlDQpmYyA8LSBmaXQgJT4lIGZvcmVjYXN0KGggPSAiNCB5ZWFycyIpDQoNCmBgYA0KDQojIyMjIDVjLgkNCkNvbXB1dGUgdGhlIGFjY3VyYWN5IG9mIHlvdXIgZm9yZWNhc3RzLiBXaGljaCBtZXRob2QgZG9lcyBiZXN0Pw0KYGBge3J9DQoNCg0KIyA1Yy5BbnN3ZXI6DQpmYyAlPiUNCiBhY2N1cmFjeSh0YWtlYXdheSkgJT4lDQogYXJyYW5nZShNQVNFKQ0KDQoNCmBgYA0KDQojIyMjIDVkLg0KRG8gdGhlIHJlc2lkdWFscyBmcm9tIHRoZSBiZXN0IG1ldGhvZCByZXNlbWJsZSB3aGl0ZSBub2lzZT8NCmBgYHtyfQ0KDQojIDVkLkFuc3dlcjoNCmZpdCAlPiUNCiBzZWxlY3QobmFpdmUpICU+JQ0KIGdnX3RzcmVzaWR1YWxzKCkNCg0KDQpgYGANCg0KIyMjIDYuCQ0KVXNpbmcgdGhlIGNvZGUgYmVsb3csIGdldCBhIHNlcmllcyAoaXQgZ2V0cyBhIHNlcmllcyByYW5kb21seSBieSB1c2luZyBzYW1wbGUoKSBmdW5jdGlvbik6DQpgYGB7cn0NCnNldC5zZWVkKDEyMzQ1Njc4KQ0KbXlzZXJpZXMgPC0gYXVzX3JldGFpbCAlPiUNCiAgZmlsdGVyKGBTZXJpZXMgSURgID09IHNhbXBsZShhdXNfcmV0YWlsJGBTZXJpZXMgSURgLDEpKQ0KYGBgDQpzZWUgaGVhZCBvZiB5b3VyIHNlcmllcyB0byBjaGVjayBpdCBpcyBhIHRzaWJibGUgZGF0YSwgYW5kIHJlbW92ZSBOQeKAmXMgaWYgdGhlcmUgaXMgYW55IHdpdGggdGhlc2UgY29tbWFuZHM6DQoNCmBgYHtyfQ0KaGVhZChteXNlcmllcykNCm15c2VyaWVzID0gIG15c2VyaWVzICU+JSBmaWx0ZXIoIWlzLm5hKGBTZXJpZXMgSURgKSkNCmBgYA0KDQojIyMjIDZhLg0KV2hhdCBpcyB0aGUgbmFtZSBvZiB0aGUgc2VyaWVzIHlvdSByYW5kb21seSBjaG9vc2U/IFdyaXRlIGl0Lg0KYGBge3J9DQoNCiMgNmEuQW5zd2VyOg0KIyBJdCBpcyBBMzM0OTc2N1cNCg0KYGBgDQoNCiMjIyMgNmIuIA0KUnVuIGEgbGluZWFyIHJlZ3Jlc3Npb24gb2YgVHVybm92ZXIgb24gdHJlbmQuKEhpbnQ6IHVzZSBUU0xNKCkgYW5kIHRyZW5kKCkgZnVuY3Rpb25zKQ0KYGBge3J9DQojIDZiLkFuc3dlcjoNCmZpdCA9IG15c2VyaWVzICU+JSBtb2RlbChUU0xNKFR1cm5vdmVyfiB0cmVuZCgpKSkNCg0KYGBgDQoNCiMjIyMgNmMuIA0KU2VlIHRoZSByZWdyZXNzaW9uIHJlc3VsdCBieSByZXBvcnQoKSBjb21tYW5kLg0KYGBge3J9DQojIDZjLkFuc3dlcjoNCg0KcmVwb3J0KGZpdCkNCmBgYA0KDQoNCiMjIyMgNmQuCQ0KQnkgdXNpbmcgdGhpcyBtb2RlbCwgZm9yZWNhc3QgaXQgZm9yIHRoZSBuZXh0IDMgeWVhcnMuIFdoYXQgYXJlIHRoZSB2YWx1ZXMgb2YgdGhlIG5leHQgMyB5ZWFycywgbW9udGhseSB2YWx1ZXM/DQpgYGB7cn0NCg0KIyA2ZC5BbnN3ZXI6DQpmaXQgJT4lIGZvcmVjYXN0KGg9MzYpDQoNCmBgYA0KDQojIyMjIDZkLgkNClBsb3QgdGhlIGZvcmVjYXN0IHZhbHVlcyBhbG9uZyB3aXRoIHRoZSBvcmlnaW5hbCBkYXRhLg0KYGBge3J9DQoNCiMgNmQuQW5zd2VyOg0KZml0ICU+JSBmb3JlY2FzdChoPTM2ICklPiUgYXV0b3Bsb3QobXlzZXJpZXMpDQoNCiMgV2hlbiB1c2UgYXV0b3Bsb3QoKSBhbmQgdXNlIHRoZSBuYW1lIG9mIHRoZSBvcmlnaW5hbCBzZXJpZXMgaW4gdGhlIGF1dG9wbG90IGZ1bmN0aW9uIGFzIGF1dG9wbG90KG15c2VyaWVzKSAsIA0KI3RoZW4gaXQgcGxvdHMgZm9yZWNhc3RzIHdpdGggdGhlIG9yZ2luYWwgdG9nZXRoZXIuIE5vIG5lZWQgdG8gdXNlIGF1dG9sYXllcigpIGNvbW1hbmQuDQojIElmIHlvdSB1c2UgYXV0b3Bsb3QoKSB3aXRob3V0IHRoZSBvcmlnaW5hbCBzZXJpZXMgbmFtZSwgaXQgb25seSBwbG90cyB0aGUgZm9yZWNhc3RlZCB2YWx1ZXM6DQpmaXQgJT4lIGZvcmVjYXN0KGg9MzYgKSU+JSBhdXRvcGxvdCgpDQpgYGANCg0KIyMjIyA2ZS4JDQpHZXQgdGhlIHJlc2lkdWFscyBmcm9tIHRoZSBtb2RlbC4gQW5kIGNoZWNrIHRoZSByZXNpZHVhbHMgdG8gY2hlY2sgd2hldGhlciBvciBub3QgaXQgc2F0aXNmaWVzIHRoZSByZXF1aXJlbWVudHMgZm9yIHdoaXRlIG5vaXNlIGVycm9yIHRlcm1zLihoaW50OiBhdWdtZW50KCkgYW5kIGdnX3RzcmVzaWR1YWxzKCkgZnVuY3Rpb25zKQ0KDQpgYGB7cn0NCg0KIyA2ZS5BbnN3ZXI6DQpmaXQgJT4lIGdnX3RzcmVzaWR1YWxzKCkNCiMgbm90IG5vcm1hbGx5IGRpc3RyaWJ1dGVkLCBhbmQgaGFzIGF1dG9jb3JyZWxhdGlvbi4gc28gaXQgaXMgbm90IHdoaXRlIG5vaXNlIQ0KIyBhdWdtZW50KCkgZ2l2ZXMgdGhlIGZpdHRlZCBhbmQgcmVzaWR1YWxzLiBJdCBpcyBzYXZlZCBhcyAuZml0dGVkIGFuZCAucmVzaWQNCg0KYGBgDQoNCg0KIyMjIDcuIA0KSGFsZi1ob3VybHkgZWxlY3RyaWNpdHkgZGVtYW5kIGZvciBWaWN0b3JpYSwgQXVzdHJhbGlhIGlzIGNvbnRhaW5lZCBpbiB2aWNfZWxlYy4gRXh0cmFjdCB0aGUgSmFudWFyeSAyMDE0IGVsZWN0cmljaXR5IGRlbWFuZCwgYW5kIGFnZ3JlZ2F0ZSB0aGlzIGRhdGEgdG8gZGFpbHkgd2l0aCAgZGFpbHkgdG90YWwgZGVtYW5kcyBhbmQgbWF4aW11bSB0ZW1wZXJhdHVyZXMuIFJ1biB0aGUgY29kZSBiZWxvdzoNCg0KYGBge3J9DQpqYW5fdmljX2VsZWMgPC0gdmljX2VsZWMgJT4lDQogIGZpbHRlcih5ZWFybW9udGgoVGltZSkgPT0geWVhcm1vbnRoKCIyMDE0IEphbiIpKSAlPiUNCiAgaW5kZXhfYnkoRGF0ZSA9IGFzX2RhdGUoVGltZSkpICU+JQ0KICBzdW1tYXJpc2UoRGVtYW5kID0gc3VtKERlbWFuZCksIFRlbXBlcmF0dXJlID0gbWF4KFRlbXBlcmF0dXJlKSkNCg0KYGBgDQoNCiMjIyMgN2EuIA0KUGxvdCB0aGUgZGF0YSBhbmQgZmluZCB0aGUgcmVncmVzc2lvbiBtb2RlbCBmb3IgRGVtYW5kIHdpdGggdGVtcGVyYXR1cmUgYXMgYSBwcmVkaWN0b3IgdmFyaWFibGUuIFdoeSBpcyB0aGVyZSBhIHBvc2l0aXZlIHJlbGF0aW9uc2hpcD8NCmBgYHtyfQ0KDQojIDdhLkFuc3dlcjoNCmphbl92aWNfZWxlYyAlPiUNCiBnZ3Bsb3QoYWVzKHggPSBUZW1wZXJhdHVyZSwgeSA9IERlbWFuZCkpICsNCiBnZW9tX3BvaW50KCkNCiBmaXQgPC0gamFuX3ZpY19lbGVjICU+JQ0KIG1vZGVsKFRTTE0oRGVtYW5kIH4gVGVtcGVyYXR1cmUpKQ0KIGZpdCAlPiUgcmVwb3J0KCkNCiMjIFNlcmllczogRGVtYW5kDQojIyBNb2RlbDogVFNMTQ0KIyMNCiMjIFJlc2lkdWFsczoNCiMjIE1pbiAxUSBNZWRpYW4gM1EgTWF4DQojIyAtNDk5NzguMiAtMTAyMTguOSAtMTIxLjMgMTg1MzMuMiAzNTQ0MC42DQojIw0KIyMgQ29lZmZpY2llbnRzOg0KIyMgRXN0aW1hdGUgU3RkLiBFcnJvciB0IHZhbHVlIFByKD58dHwpDQojIyAoSW50ZXJjZXB0KSA1OTA4My45IDE3NDI0LjggMy4zOTEgMC4wMDIwMyAqKg0KIyMgVGVtcGVyYXR1cmUgNjE1NC4zIDYwMS4zIDEwLjIzNSAzLjg5ZS0xMSAqKioNCiMjIC0tLQ0KIyMgU2lnbmlmLiBjb2RlczogMCAnKioqJyAwLjAwMSAnKionIDAuMDEgJyonIDAuMDUgJy4nIDAuMSAnICcgMQ0KIyMNCiMjIFJlc2lkdWFsIHN0YW5kYXJkIGVycm9yOiAyNDU0MCBvbiAyOSBkZWdyZWVzIG9mIGZyZWVkb20NCiMjIE11bHRpcGxlIFItc3F1YXJlZDogMC43ODMyLCBBZGp1c3RlZCBSLXNxdWFyZWQ6IDAuNzc1Nw0KIyMgRi1zdGF0aXN0aWM6IDEwNC43IG9uIDEgYW5kIDI5IERGLCBwLXZhbHVlOiAzLjg4OTdlLTExDQojSXQgaXMgY2xlYXIgdGhhdCBhIHBvc2l0aXZlIHJlbGF0aW9uc2hpcCBleGlzdHMgZm9yIHRoaXMgZGF0YS4gSXQgaXMgbGFyZ2VseSBkcml2ZW4gYnkgZGF5cyB3aXRoIGhpZ2ggdGVtcGVyYXR1ciB0aGF0IGlzIHJlc3VsdGluZyBpbiBtb3JlIGVsZWN0cmljaXR5IGJlaW5nIGRlbWFuZGVkIChwcmVzdW1hYmx5IHRvIGtlZXAgdGhpbmdzIGNvb2wpLg0KYGBgDQoNCiMjIyMgN2IuIA0KUHJvZHVjZSBhIHJlc2lkdWFsIHBsb3QuIElzIHRoZSBtb2RlbCBhZGVxdWF0ZT8gQXJlIHRoZXJlIGFueSBvdXRsaWVycyBvciBpbmZsdWVudGlhbCBvYnNlcnZhdGlvbnM/DQoNCmBgYHtyfQ0KDQojIDdiLkFuc3dlcjoNCmZpdCAlPiUgZ2dfdHNyZXNpZHVhbHMoKQ0KI1RoZSByZXNpZHVhbHMgaW4gdGhpcyBwb3J0aW9uIG9mIHRoZSBkYXRhIGluZGljYXRlIHRoYXQgdGhlIG1vZGVsIG1heSBiZSBtaXNzaW5nIGEgdHJlbmQuICNIb3dldmVyLCB3aGVuIHZpZXdlZCBvdmVyIGEgbG9uZ2VyIHRpbWUgcGVyaW9kLCB0aGlzIGRvZXNu4oCZdCBhcHBlYXIgdG8gYmUgYSBnZW51aW5lIHBhdHRlcm4uICNUaGUgaGlnaCB2YXJpYWJpbGl0eSBpbiBzb21lIHBvaW50cyBhbHNvIHN1Z2dlc3RzIHRoZSBwcmVzZW5jZSBvZiBvdXRsaWVycy4NCg0KYGBgDQoNCiMjIyMgN2MuDQpVc2UgdGhlIG1vZGVsIHRvIGZvcmVjYXN0IHRoZSBlbGVjdHJpY2l0eSBkZW1hbmQgdGhhdCB5b3Ugd291bGQgZXhwZWN0IGZvciB0aGUgbmV4dCBkYXkgaWYgdGhlIG1heGltdW0gdGVtcGVyYXR1cmUgd2FzIDE14oiYQyBhbmQgY29tcGFyZSBpdCB3aXRoIHRoZSBmb3JlY2FzdCBpZiB0aGUgd2l0aCBtYXhpbXVtIHRlbXBlcmF0dXJlIHdhcyAzNeKImEMuIERvIHlvdSBiZWxpZXZlIHRoZXNlIGZvcmVjYXN0cz8NCg0KYGBge3J9DQoNCiMgN2MuQW5zd2VyOg0KbGlicmFyeShmcHAzKQ0KDQojIFN0ZXAgMTogQWdncmVnYXRlIHRvIGRhaWx5IGRhdGEgZm9yIEphbiAyMDE0DQpqYW5fdmljX2VsZWMgPC0gdmljX2VsZWMgJT4lDQogIGZpbHRlcih5ZWFybW9udGgoVGltZSkgPT0geWVhcm1vbnRoKCIyMDE0IEphbiIpKSAlPiUNCiAgaW5kZXhfYnkoRGF0ZSA9IGFzX2RhdGUoVGltZSkpICU+JQ0KICBzdW1tYXJpc2UoDQogICAgRGVtYW5kID0gc3VtKERlbWFuZCksDQogICAgVGVtcGVyYXR1cmUgPSBtYXgoVGVtcGVyYXR1cmUpDQogICkNCg0KIyBTdGVwIDI6IEZpdCBsaW5lYXIgcmVncmVzc2lvbiBtb2RlbA0KZml0IDwtIGphbl92aWNfZWxlYyAlPiUNCiAgbW9kZWwodHNsbV9tb2RlbCA9IFRTTE0oRGVtYW5kIH4gVGVtcGVyYXR1cmUpKQ0KDQojIFN0ZXAgMzogQ3JlYXRlIHR3byBmdXR1cmUgKG5vbi1vdmVybGFwcGluZykgZGF0ZXMNCm5leHRfZGF5IDwtIGJpbmRfcm93cygNCiAgbmV3X2RhdGEoamFuX3ZpY19lbGVjLCAxKSAlPiUgbXV0YXRlKFRlbXBlcmF0dXJlID0gMTUsIFNjZW5hcmlvID0gIkNvbGQgRGF5IiksDQogIG5ld19kYXRhKGphbl92aWNfZWxlYywgMSkgJT4lIG11dGF0ZShUZW1wZXJhdHVyZSA9IDM1LCBTY2VuYXJpbyA9ICJIb3QgRGF5IikgJT4lDQogICAgbXV0YXRlKERhdGUgPSBEYXRlICsgMSkgICMgc2hpZnQgMSBkYXkgZm9yd2FyZCB0byBhdm9pZCBkdXBsaWNhdGUgaW5kZXgNCikNCg0KIyBTdGVwIDQ6IEZvcmVjYXN0IHVzaW5nIG1vZGVsDQpmYyA8LSBmb3JlY2FzdChmaXQsIG5ld19kYXRhID0gbmV4dF9kYXkpDQoNCiMgU3RlcCA1OiBQbG90IHJlc3VsdHMgd2l0aCBmb3JlY2FzdGVkIHBvaW50cw0KYXV0b3Bsb3QoamFuX3ZpY19lbGVjLCBEZW1hbmQpICsNCiAgZ2VvbV9wb2ludChkYXRhID0gZmMsIGFlcyh4ID0gRGF0ZSwgeSA9IC5tZWFuLCBjb2xvciA9IFNjZW5hcmlvKSwgc2l6ZSA9IDMpICsNCiAgbGFicyh0aXRsZSA9ICJGb3JlY2FzdDogRWxlY3RyaWNpdHkgRGVtYW5kIG9uIENvbGQgdnMgSG90IERheXMiLA0KICAgICAgIHkgPSAiRGFpbHkgRGVtYW5kIChNVykiLCB4ID0gIkRhdGUiKSArDQogIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSBjKCJDb2xkIERheSIgPSAiYmx1ZSIsICJIb3QgRGF5IiA9ICJyZWQiKSkNCmZjICU+JSBhc190aWJibGUoKSAlPiUgc2VsZWN0KFNjZW5hcmlvLCBUZW1wZXJhdHVyZSwgLm1lYW4pDQoNCg0KI1VzaW5nIHRoZSBsaW5lYXIgcmVncmVzc2lvbiBtb2RlbCBEZW1hbmQgfiBUZW1wZXJhdHVyZSwgSSBmb3JlY2FzdGVkIGVsZWN0cmljaXR5IGRlbWFuZCBmb3IgdHdvIGh5cG90aGV0aWNhbCBuZXh0LWRheSBzY2VuYXJpb3M6DQoNCiNDb2xkIERheSAoMTXCsEMpDQoNCiNIb3QgRGF5ICgzNcKwQykNCg0KI1RoZSBtb2RlbCBwcmVkaWN0cyBoaWdoZXIgZWxlY3RyaWNpdHkgZGVtYW5kIG9uIHRoZSBob3QgZGF5LCB3aGljaCBpcyBjb25zaXN0ZW50IHdpdGggcmVhbC13b3JsZCBiZWhhdmlvciBpbiBzdW1tZXIg4oCUIHdoZW4gYWlyIGNvbmRpdGlvbmluZyB1c2FnZSBpbmNyZWFzZXMgc2hhcnBseSB3aXRoIHRlbXBlcmF0dXJlLg0KDQojRG8gSSBiZWxpZXZlIHRoZXNlIGZvcmVjYXN0cz8NCiN5ZXMsIHRoZXkgYXJlIHJlYXNvbmFibGUuIFRoZSBtb2RlbCByZWZsZWN0cyBhIGNsZWFyIGFuZCBsb2dpY2FsIHBhdHRlcm46IGhvdHRlciB0ZW1wZXJhdHVyZXMgbGVhZCB0byBoaWdoZXIgZGVtYW5kLiBIb3dldmVyLCB0aGUgbW9kZWwgaXMgYmFzZWQgb25seSBvbiBKYW51YXJ5IDIwMTQsIHNvIGZvciBtb3JlIHJlbGlhYmxlIGZvcmVjYXN0aW5nLCBpdCB3b3VsZCBiZSBiZXR0ZXIgdG8gdHJhaW4gdGhlIG1vZGVsIG9uIGEgbGFyZ2VyIGFuZCBtb3JlIHZhcmllZCBkYXRhc2V0Lg0KYGBgDQoNCiMjIyMgN2QuDQpEbyB5b3UgYmVsaWV2ZSB0aGVzZSBmb3JlY2FzdHM/IFRoZSBmb2xsb3dpbmcgUiBjb2RlIHdpbGwgZ2V0IHlvdSBzdGFydGVkOg0KYGBge3J9DQogamFuX3ZpY19lbGVjICU+JQ0KICBtb2RlbChUU0xNKERlbWFuZCB+IFRlbXBlcmF0dXJlKSkgJT4lDQogIGZvcmVjYXN0KA0KICAgIG5ld19kYXRhKGphbl92aWNfZWxlYywgMSkgJT4lDQogICAgICBtdXRhdGUoVGVtcGVyYXR1cmUgPSAxNSkNCiAgKSAlPiUNCiAgYXV0b3Bsb3QoamFuX3ZpY19lbGVjKQ0KDQojeWVzLCB0aGV5IGFyZSByZWFzb25hYmxlLiBUaGUgbW9kZWwgcmVmbGVjdHMgYSBjbGVhciBhbmQgbG9naWNhbCBwYXR0ZXJuOiBob3R0ZXIgdGVtcGVyYXR1cmVzIGxlYWQgdG8gaGlnaGVyIGRlbWFuZC4gSG93ZXZlciwgdGhlIG1vZGVsIGlzIGJhc2VkIG9ubHkgb24gSmFudWFyeSAyMDE0LCBzbyBmb3IgbW9yZSByZWxpYWJsZSBmb3JlY2FzdGluZywgaXQgd291bGQgYmUgYmV0dGVyIHRvIHRyYWluIHRoZSBtb2RlbCBvbiBhIGxhcmdlciBhbmQgbW9yZSB2YXJpZWQgZGF0YXNldC4NCmBgYA0KDQogDQojIyMjIDdlLiANCkdpdmUgcHJlZGljdGlvbiBpbnRlcnZhbHMgZm9yIHlvdXIgZm9yZWNhc3RzLg0KDQpgYGB7cn0NCg0KIyA3ZS5BbnN3ZXI6DQpmYyAlPiUNCiBoaWxvKDk1KSAlPiUNCiBzZWxlY3QoLS5tb2RlbCkNCmBgYA0KDQoNCiMjIyA4Lg0KUmVhZCB0aGUgc2hhbXBvbyBkYXRhIGdpdmVuIGluIGV4Y2VsIChJbXBvcnQgRGF0YXNldCBhcyBFeGNlbCkNCiAgDQpgYGB7cn0NCiNhLglWaWV3IHRoZSBzaGFtcG9vIHNhbGVzIGRhdGEuIEhvdyBtYW55IHZhcmlhYmxlcyBhcmUgdGhlcmU/IEZpbmQgaG93IG1hbnkgcm93cyBhbmQgY29sdW1ucyBpbiB0aGUgZGF0YT8NCmxpYnJhcnkocmVhZHhsKQ0Kc2V0d2QoIkM6L1VzZXJzL3Bvb2phL09uZURyaXZlL0Rlc2t0b3AvUkFzc2lnbm1lbnQyIikNCnNoYW1wb28gPC0gcmVhZF9leGNlbCgic2hhbXBvby0yLnhsc3giKQ0KI1ZpZXcoc2hhbXBvbykNCiNiLiBJcyB0aGUgZGF0YSBhbm51YWwsIG1vbnRobHksIHF1YXJ0ZXJseT8NCiBzdHIoc2hhbXBvbykgI2RhdGEgZnJhbWUNCiAgDQoNCiNiLglJcyB0aGUgZGF0YSBhbm51YWwsIG1vbnRobHksIHF1YXJ0ZXJseT8NCiANCiBzdHIoc2hhbXBvbykNCiAgDQojYy4JQ29udmVydCB0aGUgZGF0YSBpbnRvIHRpYmJsZSAsIHRoZW4gdHNpYmJsZSANCm15ZGF0YSA9IHNoYW1wb28gJT4lDQogbXV0YXRlKE1PTlRITFkgPSB5ZWFybW9udGgoTW9udGgpKSAlPiUgYXNfdHNpYmJsZShpbmRleCA9IE1PTlRITFkpICU+JSBzZWxlY3QoLU1vbnRoKQ0Kc3RyKG15ZGF0YSkNCm15ZGF0YQ0KDQogIA0KI2QuCVBsb3QgdGhlIHNoYW1wb28gc2FsZXMuIFdoYXQgZG8geW91IHNlZSBmcm9tIHRoZSBkYXRhIHBhdHRlcm4/IFdoYXQgZG9lcyB4LWF4aXMgcmVwcmVzZW50PyANCnBsb3Qoc2hhbXBvbyRzYWxlcywgdHlwZSA9ImwiKQ0KbXlkYXRhICU+JQ0KIGF1dG9wbG90KHNhbGVzKSArDQogbGFicyh0aXRsZSA9ICJNb250aGx5IFNoYW1wb28gU2FsZXMiLCB5PSAiaW4gJCIpDQoNCiMgQ29tbWVudCBoZXJlLiBVc2UgcGxvdCgpIGFuZCBhdXRvcGxvdCgpLlB1dCB0aGUgbmFtZSBmb3IgeSBheGlzLCBhbmQgYSB0aXRsZSBmb3IgdGhlIGdyYXBoLg0KICANCiNlLglXaGF0IGlzIHRoZSBhdmVyYWdlLCBhbmQgbWVkaWFuIG9mIHNoYW1wb28gc2FsZXMuIFB1dCBpdCBvbiBhIGhpc3RvZ3JhbS4NCm1lYW5TYWxlcyA9IG1lYW4oc2hhbXBvbyRzYWxlcykNCm1lYW5TYWxlcw0KaGlzdChzaGFtcG9vJHNhbGVzKQ0KbXlkYXRhICU+JQ0KIGdncGxvdChhZXMoeD1zYWxlcykpICsNCiBnZW9tX2hpc3RvZ3JhbShiaW49MTApDQogIA0KI2YuCUdldCBzZWFzb25hbCBwbG90LiBXaGF0IGRvIHlvdSBzZWUvIGlzIHRoZXJlIGFueSBwYXR0ZXJuLCBpcyB0ZWhyZSBhbnkgc2Vhc29uYWxpdHkuDQpteWRhdGEgJT4lIGdnX3NlYXNvbihzYWxlcykgIyB5ZXMsIHRoZXJlIGlzIGEgdHJlbmQuIDE5OTcgaXMgaGlnaGVyIHRoYW4gMTk5NiBhbmQgdGhhbiAxOTk1Lg0KbXlkYXRhICU+JSBnZ19zdWJzZXJpZXMoc2FsZXMpICMgaXQgbG9va3MgbGlrZSB0aGVyZSBpcyBtb250aGx5IGVmZmVjdC4gaXQgaXMgaGlnaGVyIGluanVsLWRlY2VtYmVyIGludGVydmFsLg0KICANCiNnLglHZXQgYSBsaW5lYXIgcmVncmVzc2lvbiBsaW5lIHdpdGggdHJlbmQgYW5kIGR1bW15IGZvciBlYWNoIG1vbnRoIChIaW50OiB1c2UgdHJlbmQgYW5kIHNlYXNvbiBpbiByZWdyZXNzaW9uIGVxdWF0aW9uKS4NCmZpdCA9IG15ZGF0YSAlPiUgbW9kZWwoVFNMTShzYWxlcyB+IHRyZW5kKCkgKyBzZWFzb24oKSkpDQogIA0KI2guCUNvbW1lbnQgb24gZWFjaCBlc3RpbWF0ZWQgY29lZmZpY2llbnQgb2YgdGhlIG1vZGVsLkFyZSB0aGV5IHN0YXRpc3RpY2FsbHkgc2lnbmlmaWNhbnQgYXQgNSAlIHNpZ25pZmljYW5jZSBsZXZlbD8NCnJlcG9ydChmaXQpDQoNCiAgDQojaS4JV2hpY2ggbW9udGggaGFzIHRoZSBoaWdoZXN0IHNhbGVzPw0KIyBkZWNlbWJlciBhbmQgbm92ZW1iZXIuDQoNCiAgDQojai4JRm9yZWNhc3QgaXQgZm9yIHRoZSBuZXh0IHllYXIuIFdoYXQgYXJlIHRoZSB2YWx1ZXMNCiBmb3JlY2FzdHMgPSBmaXQgJT4lIGZvcmVjYXN0KGg9MTIpDQpmb3JlY2FzdHMNCiAgDQojay4JUGxvdCB0aGUgZm9yZWNhc3Qgd2l0aCBvcmlnaW5hbCBkYXRhLg0KZml0ICU+JSBmb3JlY2FzdChoPTEyKSAlPiUgYXV0b3Bsb3QobXlkYXRhKQ0KZm9yZWNhc3RzICU+JSBhdXRvcGxvdChteWRhdGEpDQogIA0KI2wuCUNoZWNrIGlmIHRoZSByZXNpZHVhbHMgb2YgdGhlIG1vZGVsIGlzIHdoaXRlIG5vaXNlLg0KDQpmaXQgJT4lIGdnX3RzcmVzaWR1YWxzDQojIGl0IGlzIGF1dG9jb3JyZWxhdGlvbiBhdCAxIGxhZy4NCiAjIyMgQW5zdzogbm90IHdoaXRlIG5vaXNlLg0KICANCiNtLglCeSB1c2luZyB0aGUgcmVncmVzc2lvbiBtb2RlbCwgZm9yZWNhc3QgdGhlIDEgeWVhciBhaGVhZCwgYW5kIHRoZW4gY2hlY2sgdGhlIGFjY3VyYWN5IG9mIHRoZSBmb3JlY2FzdC4gV2hhdCBpcyBNU0UsIFJNU0UgdmFsdWVzPw0KDQphY2N1cmFjeShmaXQpDQoNCmBgYA0KICAgIA0K