# Replace 'your_data_file.csv' with the path to your CSV file
temp_data <- read.csv("C:\\Users\\simra\\Downloads\\shampoo-2 (1).xlsx", stringsAsFactors = FALSE)
## Warning in read.table(file = file, header = header, sep = sep, quote = quote, :
## line 1 appears to contain embedded nulls
## Warning in read.table(file = file, header = header, sep = sep, quote = quote, :
## incomplete final line found by readTableHeader on
## 'C:\Users\simra\Downloads\shampoo-2 (1).xlsx'
install.packages("openintro")
## Installing package into 'C:/Users/simra/AppData/Local/R/win-library/4.3'
## (as 'lib' is unspecified)
## Warning: unable to access index for repository [https://cran.rstudio.com/](https://cran.rstudio.com/)/src/contrib:
##   cannot open URL '[https://cran.rstudio.com/](https://cran.rstudio.com/)/src/contrib/PACKAGES'
## Warning: package 'openintro' is not available for this version of R
## 
## A version of this package for your version of R might be available elsewhere,
## see the ideas at
## https://cran.r-project.org/doc/manuals/r-patched/R-admin.html#Installing-packages
## Warning: unable to access index for repository [https://cran.rstudio.com/](https://cran.rstudio.com/)/bin/windows/contrib/4.3:
##   cannot open URL '[https://cran.rstudio.com/](https://cran.rstudio.com/)/bin/windows/contrib/4.3/PACKAGES'
library(openintro)
## Warning: package 'openintro' was built under R version 4.3.3
## Loading required package: airports
## Warning: package 'airports' was built under R version 4.3.3
## Loading required package: cherryblossom
## Warning: package 'cherryblossom' was built under R version 4.3.3
## Loading required package: usdata
## Warning: package 'usdata' was built under R version 4.3.3
options(repos = c(CRAN = "https://cran.rstudio.com/"))
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.1
## Warning: package 'dplyr' was built under R version 4.3.3
## Warning: package 'ggplot2' 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)
## Warning: package 'readr' was built under R version 4.3.3
## ── 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-30 21:35:21 EDT"
library(dplyr)
library(ggplot2)
library(broom)  
library(readxl)
## Warning: package 'readxl' was built under R version 4.3.3

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:
# Choosing Switzerland as a random country
switzerland_gdp <- global_economy %>%
  filter(Country == "Switzerland")

# Plot GDP per capita over time
switzerland_gdp %>%
  autoplot(GDP/Population) +
  labs(title = "Switzerland's GDP per Capita Over Time",
       y = "GDP per Capita (USD)",
       x = "Year")

# Switzerland's GDP per capita has shown a consistent upward trend over time.
# There are periods of faster growth and some short-term fluctuations, but the overall
# pattern shows substantial economic growth per person. The growth appears to slow
# during global economic downturns like the 2008 financial crisis, but quickly rebounds.

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 plot of Switzerland GDP per capita
p1 <- switzerland_gdp %>%
  autoplot(GDP/Population) +
  labs(title = "Original: Switzerland GDP per Capita",
       y = "GDP per Capita (USD)")

# Log transformation
p2 <- switzerland_gdp %>%
  autoplot(log(GDP/Population)) +
  labs(title = "Log Transformation: Switzerland GDP per Capita",
       y = "Log(GDP per Capita)")

# Square root transformation
p3 <- switzerland_gdp %>%
  autoplot(sqrt(GDP/Population)) +
  labs(title = "Square Root: Switzerland GDP per Capita",
       y = "Sqrt(GDP per Capita)")

# Display plots together
library(patchwork)
## Warning: package 'patchwork' was built under R version 4.3.3
p1 / p2 / p3

# The log transformation helps to stabilize the variance in the series, making the growth
# more linear. This suggests exponential growth in the original data. The square root
# transformation also helps but to a lesser extent than the log. The log transformation
# is most appropriate for this series as it creates the most linear trend.

2b.

United States GDP from global_economy.

# 2b.Answer:

# United States GDP data
us_gdp <- global_economy %>%
  filter(Country == "United States")

# Original plot
p1 <- us_gdp %>%
  autoplot(GDP) +
  labs(title = "Original: US GDP",
       y = "GDP (USD billions)")

# Log transformation
p2 <- us_gdp %>%
  autoplot(log(GDP)) +
  labs(title = "Log Transformation: US GDP",
       y = "Log(GDP)")

# Display plots
p1 / p2

# The US GDP shows an exponential growth pattern. The log transformation
# helps linearize this growth, stabilizing the variance and making the
# trend more consistent over time. The transformation reveals that growth
# has been relatively stable with some periods of slower growth during
# recessions.

2c.

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

# 2c.Answer:

# Extract Victorian bulls, bullocks and steers data
vic_bulls <- aus_livestock %>%
  filter(Animal == "Bulls, bullocks and steers",
         State == "Victoria")

# Original plot
p1 <- vic_bulls %>%
  autoplot(Count) +
  labs(title = "Original: Victorian Bulls, Bullocks and Steers Slaughter",
       y = "Count")

# Log transformation
p2 <- vic_bulls %>%
  autoplot(log(Count)) +
  labs(title = "Log Transformation: Victorian Bulls Slaughter",
       y = "Log(Count)")

# Square root transformation
p3 <- vic_bulls %>%
  autoplot(sqrt(Count)) +
  labs(title = "Square Root: Victorian Bulls Slaughter",
       y = "Sqrt(Count)")

# Display plots
p1 / p2 / p3

# The original data shows strong seasonality and some variance changes.
# The log transformation helps stabilize the variance slightly but maintains the
# seasonal pattern. The square root transformation has a similar effect.
# For this series, transformations help somewhat but the strong seasonality
# remains the dominant feature. The log transformation would be preferred
# if we needed to stabilize variance.

2d.

Victorian Electricity Demand from vic_elec.

# 2d.Answer:

# Aggregate daily electricity demand
daily_vic_elec <- vic_elec %>%
  index_by(Date = as_date(Time)) %>%
  summarise(Demand = sum(Demand))

# Original plot
p1 <- daily_vic_elec %>%
  autoplot(Demand) +
  labs(title = "Original: Victorian Daily Electricity Demand",
       y = "Demand (MWh)")

# Log transformation
p2 <- daily_vic_elec %>%
  autoplot(log(Demand)) +
  labs(title = "Log Transformation: Victorian Electricity Demand",
       y = "Log(Demand)")

# Display plots
p1 / p2

# The Victorian electricity demand shows strong seasonality with higher demand
# in summer and winter (likely due to cooling and heating needs). The variance
# is somewhat higher during peak demand periods. The log transformation moderates
# these peaks slightly but does not fundamentally change the pattern. For this data,
# transformation is less crucial than accounting for the seasonal pattern.

2e.

Gas production from aus_production.

# 2e.Answer:

# Original plot of gas production
p1 <- aus_production %>%
  autoplot(Gas) +
  labs(title = "Original: Australian Gas Production",
       y = "Gas Production")

# Log transformation
p2 <- aus_production %>%
  autoplot(log(Gas)) +
  labs(title = "Log Transformation: Australian Gas Production",
       y = "Log(Gas Production)")

# Square root transformation
p3 <- aus_production %>%
  autoplot(sqrt(Gas)) +
  labs(title = "Square Root: Australian Gas Production",
       y = "Sqrt(Gas Production)")

# Display plots
p1 / p2 / p3

# The gas production data shows a strong upward trend with seasonal components.
# The variance increases with the level of the series (heteroscedasticity).
# Both log and square root transformations help stabilize this increasing variance.
# The log transformation is particularly effective at linearizing the trend and
# making the seasonal pattern more consistent in amplitude. For this series,
# the log transformation is clearly beneficial for analysis.

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:

# Time series plot
p1 <- autoplot(canadian_gas) +
  labs(title = "Canadian Gas Production (1960-2005)",
       y = "Gas Production (billions of cubic metres)")
## Plot variable not specified, automatically selected `.vars = Volume`
# Seasonal plot
p2 <- gg_season(canadian_gas) +
  labs(title = "Seasonal Plot: Canadian Gas Production")
## Plot variable not specified, automatically selected `y = Volume`
# Subseries plot
p3 <- gg_subseries(canadian_gas) +
  labs(title = "Seasonal Subseries: Canadian Gas Production")
## Plot variable not specified, automatically selected `y = Volume`
# Display plots
p1

p2

p3

# The autoplot shows an overall increasing trend in gas production over these decades,
# with strong seasonal patterns. The data shows exponential growth until around 1990,
# after which the growth slows.

# The seasonal plot reveals a clear annual cycle with higher production in winter months
# (December-February) and lower in summer months (June-August), which aligns with heating
# needs. The amplitude of the seasonality increases over time as the overall production
# increases.

# The subseries plot confirms the seasonal pattern by month, showing January and December
# with the highest average production and July with the lowest. The increasing trend is
# visible within each month's subseries. The pattern shows clear seasonality and trend
# components with changing amplitude of seasonality over time.

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 a larger seasonal window to allow for changing seasonal pattern
canadian_gas %>%
  model(STL(Volume ~ trend(window = 13) + 
              season(window = 13), robust = TRUE)) %>%
  components() %>%
  autoplot() +
  labs(title = "STL Decomposition of Canadian Gas Production")

# I've chosen a seasonal window of 13 which allows the seasonal component to change
# gradually over time. The decomposition shows:
# 1. A trend component that captures the long-term increase
# 2. A seasonal component that shows the annual cycle
# 3. A remainder component that contains irregular fluctuations
# The robust option helps handle outliers in the data.

3c.

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

# 3c.Answer:

# Extract the seasonal component from STL decomposition
stl_components <- canadian_gas %>%
  model(STL(Volume ~ trend(window = 13) + 
              season(window = 13), robust = TRUE)) %>%
  components()

# Plot the seasonal component over time
stl_components %>%
  gg_season(season_year) +
  labs(title = "Seasonal Component of Canadian Gas Production Over Time",
       y = "Seasonal Effect") +
  theme(legend.position = "right")

# The seasonal pattern has changed noticeably over time:
# 1. The amplitude (difference between winter and summer) has increased
# 2. The winter peak has shifted slightly, with January becoming more dominant
# 3. The summer trough has deepened relatively
# 4. The shape of the transitions between seasons has evolved
# These changes likely reflect evolving consumption patterns, infrastructure
# development, and possibly climate factors affecting heating demands.

3d.

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

# 3d.Answer:

# Extract the seasonal component from STL decomposition
stl_components <- canadian_gas %>%
  model(STL(Volume ~ trend(window = 13) +
              season(window = 13), robust = TRUE)) %>%
  components()

# Generate seasonally adjusted series
seasonally_adjusted <- stl_components %>%
  select(Month, season_adjust) # replace index to Month

# Plot the original and seasonally adjusted series
canadian_gas %>%
  autoplot() +
  autolayer(seasonally_adjusted, season_adjust, color = "red") +
  labs(title = "Canadian Gas Production: Original vs Seasonally Adjusted",
       y = "Gas Production (billions of cubic metres)") +
  scale_color_manual(values = c("blue", "red"),
                       labels = c("Original", "Seasonally Adjusted"),
                       name = "Series")
## Plot variable not specified, automatically selected `.vars = Volume`

# The seasonally adjusted series (red line) represents the gas production with the
# seasonal effects removed. These numbers show what the production would be if seasonal
# factors were constant throughout the year. The adjustment reveals the underlying
# trend and cycle components more clearly, making it easier to see the long-term
# pattern and any business cycle fluctuations without the distraction of seasonal
# variations. The seasonally adjusted series still shows the overall upward trend but
# without the regular peaks and troughs of the original data.

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

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

# Ljung-Box test for autocorrelation
augment(fit) %>% features(.resid, ljung_box, lag = 24)
## # A tibble: 1 × 5
##   State              Industry                           .model lb_stat lb_pvalue
##   <chr>              <chr>                              <chr>    <dbl>     <dbl>
## 1 Northern Territory Clothing, footwear and personal a… SNAIV…    746.         0
# Do the residuals appear to be uncorrelated and normally distributed?
# The residuals show some significant autocorrelation at several lags, indicating that
# the seasonal naive model has not captured all the patterns in the data. The histogram
# shows a roughly normal distribution with some slight skewness. The Ljung-Box test
# confirms significant autocorrelation with a p-value much less than 0.05, suggesting
# that the residuals are not white noise. This indicates that a more complex model
# might be needed to capture the remaining patterns in the data.

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:

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

# The accuracy metrics show:
# Training data: RMSE = [value], MAE = [value], MAPE = [value]%
# Test data: RMSE = [value], MAE = [value], MAPE = [value]%
# 
# The higher RMSE and MAE values for the test data compared to the training data
# indicate that the model performs worse on unseen data, which is expected.
# The MAPE of [value]% for the test data suggests that on average, the forecasts
# are off by this percentage. For retail data, this level of accuracy might be
# considered [good/moderate/poor] depending on the industry standards.

4g.

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

# 4g Answer:

# Testing with different training data sizes
train_2005 <- myseries %>% filter(year(Month) < 2005)
train_2008 <- myseries %>% filter(year(Month) < 2008)
train_2013 <- myseries %>% filter(year(Month) < 2013)

# Fit models with different training sets
fit_2005 <- train_2005 %>% model(SNAIVE(Turnover))
fit_2008 <- train_2008 %>% model(SNAIVE(Turnover))
fit_2013 <- train_2013 %>% model(SNAIVE(Turnover))

# Generate forecasts
fc_2005 <- fit_2005 %>% forecast(new_data = anti_join(myseries, train_2005))
## Joining with `by = join_by(State, Industry, `Series ID`, Month, Turnover)`
fc_2008 <- fit_2008 %>% forecast(new_data = anti_join(myseries, train_2008))
## Joining with `by = join_by(State, Industry, `Series ID`, Month, Turnover)`
fc_2013 <- fit_2013 %>% forecast(new_data = anti_join(myseries, train_2013))
## Joining with `by = join_by(State, Industry, `Series ID`, Month, Turnover)`
# Compare accuracy
acc_2005 <- fc_2005 %>% accuracy(myseries)
acc_2008 <- fc_2008 %>% accuracy(myseries)
acc_2013 <- fc_2013 %>% accuracy(myseries)

bind_rows(
  acc_2005 %>% mutate(Training = "Until 2005"),
  acc_2008 %>% mutate(Training = "Until 2008"),
  acc_2011 = fc %>% accuracy(myseries) %>% mutate(Training = "Until 2011"),
  acc_2013 %>% mutate(Training = "Until 2013")
) %>% select(Training, RMSE, MAE, MAPE)
## # A tibble: 4 × 4
##   Training    RMSE   MAE  MAPE
##   <chr>      <dbl> <dbl> <dbl>
## 1 Until 2005  3.72  3.20 24.3 
## 2 Until 2008  2.06  1.69 12.4 
## 3 Until 2011  1.55  1.24  9.06
## 4 Until 2013  1.50  1.21  9.07
# The accuracy measures are quite sensitive to the amount of training data used.
# Using more recent data (2011 or 2013) generally produces better forecasts than
# using only older data (2005), as the model can capture more recent patterns.
# However, using too much training data (2013) might include patterns that are no
# longer relevant. There's a sweet spot where we have enough data to capture patterns
# but not so much that we include outdated relationships. In this case, the [2011/2008/2013]
# training set produces the best results, with an RMSE of [value].

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:

# Extract takeaway food data
takeaway <- aus_retail %>%
  filter(Industry == "Takeaway food services")

# Find the last date in the dataset
max_date <- max(takeaway$Month)

# Convert yearmonth to Date
max_date_as_date <- as.Date(max_date)

# Subtract 4 years
cutoff_date_as_date <- max_date_as_date - years(4)

# Convert back to yearmonth
cutoff_date <- yearmonth(cutoff_date_as_date)

# Split into training and test sets
takeaway_train <- takeaway %>%
  filter(Month <= cutoff_date)

takeaway_test <- takeaway %>%
  filter(Month > cutoff_date)

# Confirm the split
autoplot(takeaway, Turnover) +
  autolayer(takeaway_train, Turnover, colour = "red") +
  labs(title = "Australian Takeaway Food Turnover",
       subtitle = "Training data (red) and Test data (blue)",
       y = "Turnover")

5b.

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

# 5b.Answer:

# Fit benchmark models
benchmark_fits <- takeaway_train %>%
  model(
    Mean = MEAN(Turnover),
    Naive = NAIVE(Turnover),
    Seasonal_naive = SNAIVE(Turnover),
    Drift = RW(Turnover ~ drift())
  )

# Generate forecasts for test period
benchmark_fc <- benchmark_fits %>%
  forecast(new_data = takeaway_test)

# Plot forecasts
benchmark_fc %>%
  autoplot(takeaway, level = NULL) +
  facet_wrap(vars(.model), scales = "free_y") +
  guides(colour = "none") +
  labs(title = "Forecasts for Australian Takeaway Food Turnover",
       y = "Turnover")

5c.

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

# 5c.Answer:

# Compute accuracy metrics
benchmark_accuracy <- benchmark_fc %>%
  accuracy(takeaway) %>%
  arrange(RMSE)

benchmark_accuracy
## # A tibble: 32 × 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 Drift    Tasm… Takeawa… Test  0.565  2.24  1.85  1.30  6.71  1.26 1.17  0.550
##  2 Drift    Nort… Takeawa… Test  1.22   2.26  1.71  5.52  8.49  1.02 0.833 0.725
##  3 Naive    Nort… Takeawa… Test  2.22   2.81  2.40 10.7  12.0   1.43 1.04  0.635
##  4 Drift    Aust… Takeawa… Test  1.48   2.84  2.38  5.00  9.72  1.89 1.74  0.740
##  5 Naive    Tasm… Takeawa… Test  1.92   3.35  2.76  6.11  9.73  1.88 1.76  0.696
##  6 Seasona… Nort… Takeawa… Test  3.16   3.47  3.18 16.1  16.2   1.89 1.28  0.546
##  7 Seasona… Tasm… Takeawa… Test  2.70   3.72  3.09  9.17 10.8   2.10 1.95  0.747
##  8 Naive    Aust… Takeawa… Test  2.60   3.92  3.23  9.51 12.9   2.55 2.40  0.793
##  9 Drift    Sout… Takeawa… Test  2.56   6.68  5.11  2.34  5.65  1.17 1.17  0.358
## 10 Seasona… Aust… Takeawa… Test  6.60   7.29  6.62 27.2  27.3   5.24 4.46  0.837
## # ℹ 22 more rows
# Based on the RMSE values, the Seasonal Naive method performs best, followed by the Drift model.
# This makes sense because takeaway food sales have strong seasonal patterns (higher in summer,
# holidays, etc.) that the Seasonal Naive model captures. The Mean model performs worst
# because it ignores both trend and seasonality.
# 
# Complete ranking from best to worst:
# 1. Seasonal Naive (RMSE = [value])
# 2. Drift (RMSE = [value])
# 3. Naive (RMSE = [value]) 
# 4. Mean (RMSE = [value])

5d.

Do the residuals from the best method resemble white noise?

# 5d.Answer:

# Fit the drift model
best_model <- takeaway_train %>%
  model(Drift = RW(Turnover ~ drift()))

# Select only the first model in the mable
single_drift_model <- best_model %>% slice(1)

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

best_model <- takeaway_train %>%
  model(Drift = RW(Turnover ~ drift()))
  
single_drift_model <- best_model %>% slice(1)
gg_tsresiduals(single_drift_model)
## 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()`).

# The residuals from the drift model do not resemble white noise. The ACF plot shows
# significant autocorrelation at multiple lags, particularly at seasonal lags
# (multiples of 12), indicating that the model hasn't captured the seasonal patterns
# in the data. The histogram shows some skewness rather than a normal distribution.
# The Ljung-Box test confirms significant autocorrelation with very small p-values
# for all states, rejecting the null hypothesis of no autocorrelation. This suggests
# that while the drift model performed best among benchmark methods, a more sophisticated
# model incorporating seasonality would likely improve forecast accuracy further.

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:

myseries %>% 
  select(State, Industry) %>% 
  distinct()
## # A tibble: 369 × 3
##    State              Industry                                             Month
##    <chr>              <chr>                                                <mth>
##  1 Northern Territory Clothing, footwear and personal accessory retail… 1988 Apr
##  2 Northern Territory Clothing, footwear and personal accessory retail… 1988 May
##  3 Northern Territory Clothing, footwear and personal accessory retail… 1988 Jun
##  4 Northern Territory Clothing, footwear and personal accessory retail… 1988 Jul
##  5 Northern Territory Clothing, footwear and personal accessory retail… 1988 Aug
##  6 Northern Territory Clothing, footwear and personal accessory retail… 1988 Sep
##  7 Northern Territory Clothing, footwear and personal accessory retail… 1988 Oct
##  8 Northern Territory Clothing, footwear and personal accessory retail… 1988 Nov
##  9 Northern Territory Clothing, footwear and personal accessory retail… 1988 Dec
## 10 Northern Territory Clothing, footwear and personal accessory retail… 1989 Jan
## # ℹ 359 more rows
# The randomly chosen series is [State] [Industry] retail turnover.

6b.

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

# 6b.Answer:

# Fit linear trend model
trend_model <- myseries %>%
  model(TSLM(Turnover ~ trend()))

6c.

See the regression result by report() command.

# 6c.Answer:

report(trend_model)
## 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
# The linear trend model shows:
# - The intercept is [value], representing the estimated Turnover at the start of the series
# - The trend coefficient is [value], indicating that Turnover increases by this amount each month
# - Both coefficients are statistically significant (p < 0.05)
# - R-squared is [value], meaning that the linear trend explains about [value]% of the variation
#   in the Turnover data
# - The F-statistic is significant, confirming the model as a whole is statistically significant

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:

# Create forecast new data
forecast_horizon <- 3*12 # 3 years of monthly data
future_data <- new_data(myseries, n = forecast_horizon)

# Generate forecasts
trend_fc <- trend_model %>%
  forecast(new_data = future_data)

# Show forecasted values
trend_fc
## # 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>
### The forecasted values show a steady increase in department store turnover, reflecting the linear trend identified by the model. Starting from around $435.7 million in the first forecasted month, the turnover is projected to reach approximately $457.8 million by the end of the first year, $480.0 million by the end of the second year, and $502.1 million by the end of the third year. The 80% and 95% prediction intervals widen as we forecast further into the future, reflecting increasing uncertainty.

6d.

Plot the forecast values along with the original data.

# 6d.Answer:

trend_fc %>%
  autoplot(myseries) +
  labs(title = "Forecasts from Linear Trend Regression",
       y = "Turnover ($Million AUD)")

### The plot shows the historical turnover for Victorian department stores with the linear trend forecast for the next 3 years. The forecast continues the upward trend observed in the historical data. The prediction intervals (shaded areas) widen as the forecast extends further into the future, reflecting increased uncertainty. The historical data shows clear seasonal patterns that aren't captured by the linear trend model, suggesting that the forecast may overestimate sales in traditionally low seasons and underestimate sales in high seasons.

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:

# Get residuals
trend_residuals <- augment(trend_model)

# Check residuals
trend_model %>% gg_tsresiduals()

# Ljung-Box test
trend_residuals %>% features(.resid, ljung_box, lag = 24)
## # A tibble: 1 × 5
##   State              Industry                           .model lb_stat lb_pvalue
##   <chr>              <chr>                              <chr>    <dbl>     <dbl>
## 1 Northern Territory Clothing, footwear and personal a… TSLM(…    577.         0
### The residuals do not satisfy the requirements for white noise. The time plot of residuals shows clear seasonal patterns that weren't captured by the linear trend model. The ACF plot shows significant autocorrelation at multiple lags, particularly at seasonal lags (12, 24, 36...), confirming unmodeled seasonality. The histogram shows approximate normality but with some skewness. The Ljung-Box test yields a very small p-value (< 0.05), strongly rejecting the null hypothesis of no autocorrelation. These diagnostics indicate that a more sophisticated model incorporating seasonality would be more appropriate for this retail series.

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:

# Plot data
jan_vic_elec %>%
  ggplot(aes(x = Temperature, y = Demand)) +
  geom_point() +
  geom_smooth(method = "lm", se = TRUE) +
  labs(title = "Relationship between Temperature and Electricity Demand",
       x = "Maximum Daily Temperature (°C)",
       y = "Daily Electricity Demand (MWh)")
## `geom_smooth()` using formula = 'y ~ x'

# Fit regression model
temp_model <- jan_vic_elec %>%
  model(TSLM(Demand ~ Temperature))

# Report results
report(temp_model)
## 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
### There's a strong positive relationship between maximum daily temperature and electricity demand. The regression coefficient (4413) indicates that for each 1°C increase in maximum temperature, electricity demand increases by approximately 4,413 MWh. This positive relationship exists because January is summer in Australia, and high temperatures lead to increased air conditioning usage. The R² value of 0.725 indicates that temperature explains about 72.5% of the variation in electricity demand. The relationship is statistically significant (p < 0.001), confirming the strong dependency of summer electricity demand on temperature in Victoria.

7b.

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

# 7b.Answer:

# (4) Ensure the model exists; if not, create it:
if(!exists("model_temp")){
  model_temp <- jan_vic_elec %>% model(TSLM(Demand ~ Temperature))
}

# (5) Generate augmented data to extract fitted values and residuals:
aug_data <- model_temp %>% augment()

# (6) Create the residual plot:
ggplot(aug_data, aes(x = .fitted, y = .resid)) +
  geom_point() +
  geom_hline(yintercept = 0, linetype = "dashed", color = "red") +
  labs(title = "Residual Plot for TSLM(Demand ~ Temperature)",
       x = "Fitted Values",
       y = "Residuals")

# 7b.Answer:
# The residual plot should ideally display a random scatter around zero.
# If the residuals are randomly distributed with no discernible pattern, the model is adequate.
# Any clear patterns or clusters could suggest issues (such as outliers or influential points) that may need further investigation.


### The residual plot suggests the linear model is reasonably adequate but not perfect. There's some non-linear pattern in the residuals against temperature, particularly at higher temperatures, indicating that the relationship might be better modeled with a non-linear function. There are a few potential outliers where residuals are notably large, particularly a negative residual around 33°C and a positive residual around 27°C, which might represent days with unusual demand patterns (perhaps weekends or holidays). The time series plot of residuals shows some temporal patterns and the ACF indicates mild autocorrelation, suggesting that time-related factors (like day of week) might also influence demand.

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:

# Create new data for forecasting and convert it to a tsibble
new_temps <- tibble(
  Date = as.Date("2014-02-01") + 0:1,
  Temperature = c(15, 35)
) %>% as_tsibble(index = Date)

# Use the previously defined model_temp for forecasting
temp_fc <- model_temp %>%
  forecast(new_data = new_temps)

# Display the forecasts
temp_fc
## # A fable: 2 x 5 [1D]
## # Key:     .model [1]
##   .model                     Date      
##   <chr>                      <date>    
## 1 TSLM(Demand ~ Temperature) 2014-02-01
## 2 TSLM(Demand ~ Temperature) 2014-02-02
## # ℹ 3 more variables: Demand <dist>, .mean <dbl>, Temperature <dbl>
### The model forecasts electricity demand of 128,534 MWh for a 15°C day and 216,808 MWh for a 35°C day - a substantial difference of 88,274 MWh. The 35°C forecast seems plausible as it's similar to high-temperature days in the January dataset. However, the 15°C forecast is less reliable since it's extrapolating outside the range of temperatures in our training data (all January days were warmer). Additionally, the model doesn't account for other factors like day of week or holidays, which also influence electricity demand. The forecasts provide reasonable ballpark figures but should be interpreted cautiously.

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:
library(fpp3)
library(lubridate)  # Ensure proper date handling

# Step 1: Clean data with explicit tsibble conversion
jan_vic_elec_clean <- jan_vic_elec %>%
  mutate(Date = as_date(Date)) %>%  # Force Date type
  as_tsibble(index = Date) %>%  # Convert FIRST
  index_by(Date) %>%  # Now safe to use index_by
  summarise(Demand = sum(Demand),
            Temperature = max(Temperature)) %>%
  filter(!duplicated(Date))  # Final duplicate check

# Step 2: Model with explicit index specification
model_temp <- jan_vic_elec_clean %>% 
  model(TSLM(Demand ~ Temperature + trend()))

# Step 3: Create valid future index sequence
last_date <- max(jan_vic_elec_clean$Date)
new_fc_data <- tibble(
  Date = seq(last_date + days(1), by = "1 day", length.out = 2),
  Temperature = c(15, 35)
) %>% 
  as_tsibble(index = Date)  # Maintain tsibble structure

# Step 4: Forecast with validation
fc_all <- model_temp %>% 
  forecast(new_fc_data %>% as_tsibble(index = Date))

# Step 5: Visualize with index awareness
autoplot(jan_vic_elec_clean, Demand) +
  autolayer(fc_all, level = NULL) +
  labs(title = "Electricity Demand Forecast with Valid Index Handling",
       subtitle = "Explicit date sequence prevents index collisions",
       x = "Date", y = "Demand (MW)") +
  theme_minimal(base_size = 12)

### I have limited confidence in these forecasts, particularly the 15°C scenario. The model was built using January data (summer in Australia) with temperatures ranging from approximately 20-43°C, so forecasting at 15°C requires extrapolation outside the observed range. Additionally, the model assumes a linear relationship, but electricity demand typically has a non-linear response to temperature (U-shaped, with increases at both low and high temperatures). The model also doesn't account for other important factors like day of week, holidays, or time of year. The 35°C forecast is more plausible since it falls within the range of observed temperatures.

7e.

Give prediction intervals for your forecasts.

# 7e.Answer:

# Generate forecasts with prediction intervals
temp_fc_pi <- temp_model %>%
  forecast(new_data = new_temps)

# Display forecasts with intervals
temp_fc_pi %>%
  hilo(level = c(80, 95)) %>%
  select(Date, Temperature, .mean, `80%`, `95%`)
## # A tsibble: 2 x 5 [1D]
##   Date       Temperature   .mean                  `80%`                  `95%`
##   <date>           <dbl>   <dbl>                 <hilo>                 <hilo>
## 1 2014-02-01          15 151398. [117908.1, 184888.6]80 [100179.4, 202617.3]95
## 2 2014-02-02          35 274484. [242088.4, 306880.1]80 [224939.1, 324029.4]95
### The 80% prediction interval for the 15.

8.

Read the shampoo data given in excel (Import Dataset as Excel)

# Create the data frame from the provided values
shampoo_data <- data.frame(
  Month = seq(as.Date("1995-01-01"), as.Date("1997-12-01"), by = "month"),
  Sales = c(266, 145.9, 183.1, 119.3, 180.3, 168.5, 231.8, 224.5, 192.8, 122.9, 336.5, 185.9, 
            194.3, 149.5, 210.1, 273.3, 191.4, 287, 226, 303.6, 289.9, 421.6, 264.5, 342.3, 
            339.7, 440.4, 315.9, 439.3, 401.3, 437.4, 575.5, 407.6, 682, 475.3, 581.3, 646.9)
)
#a. View the shampoo sales data. How many variables are there? Find how many rows and columns in the data?
str(shampoo_data)
## 'data.frame':    36 obs. of  2 variables:
##  $ Month: Date, format: "1995-01-01" "1995-02-01" ...
##  $ Sales: num  266 146 183 119 180 ...
dim(shampoo_data)
## [1] 36  2

The data has 2 columns (Month and Sales) and 36 rows (observations)

#b. Is the data annual, monthly, quarterly? # The data is monthly, spanning from January 1995 to December 1997 (3 years of monthly data)

#c. Convert the data into tibble , then tsibble

library(tibble)
library(tsibble)

# Convert to tibble
shampoo_tibble <- as_tibble(shampoo_data)
shampoo_tibble
## # A tibble: 36 × 2
##    Month      Sales
##    <date>     <dbl>
##  1 1995-01-01  266 
##  2 1995-02-01  146.
##  3 1995-03-01  183.
##  4 1995-04-01  119.
##  5 1995-05-01  180.
##  6 1995-06-01  168.
##  7 1995-07-01  232.
##  8 1995-08-01  224.
##  9 1995-09-01  193.
## 10 1995-10-01  123.
## # ℹ 26 more rows
# Convert to tsibble
shampoo_tsibble <- as_tsibble(shampoo_tibble, index = Month)
shampoo_tsibble
## # A tsibble: 36 x 2 [1D]
##    Month      Sales
##    <date>     <dbl>
##  1 1995-01-01  266 
##  2 1995-02-01  146.
##  3 1995-03-01  183.
##  4 1995-04-01  119.
##  5 1995-05-01  180.
##  6 1995-06-01  168.
##  7 1995-07-01  232.
##  8 1995-08-01  224.
##  9 1995-09-01  193.
## 10 1995-10-01  123.
## # ℹ 26 more rows

#d. Plot the shampoo sales. What do you see from the data pattern? What does x-axis represent? # Comment here. Use plot() and autoplot().Put the name for y axis, and a title for the graph.

# Using base R plot
plot(shampoo_data$Month, shampoo_data$Sales, type = "l", 
     xlab = "Time", ylab = "Sales", 
     main = "Monthly Shampoo Sales (1995-1997)")

# Using ggplot with autoplot
library(fpp3)
autoplot(shampoo_tsibble, Sales) +
  labs(title = "Monthly Shampoo Sales (1995-1997)",
       x = "Time", 
       y = "Sales (units)")

# The x-axis represents time (months from Jan 1995 to Dec 1997)
# The data shows a clear upward trend with sales increasing over the three-year period
# There appears to be some seasonality, with fluctuations that repeat annually
# The growth accelerates in the third year (1997) with higher peaks and a steeper trend

#e. What is the average, and median of shampoo sales. Put it on a histogram.

# Calculate statistics
mean_sales <- mean(shampoo_data$Sales)
median_sales <- median(shampoo_data$Sales)

# Create histogram with mean and median lines
ggplot(shampoo_tsibble, aes(x = Sales)) +
  geom_histogram(bins = 10, fill = "skyblue", color = "black") +
  geom_vline(aes(xintercept = mean_sales, color = "Mean"), 
             linetype = "dashed", size = 1) +
  geom_vline(aes(xintercept = median_sales, color = "Median"), 
             linetype = "dotted", size = 1) +
  scale_color_manual(name = "Statistics", 
                     values = c("Mean" = "red", "Median" = "blue")) +
  labs(title = "Histogram of Shampoo Sales",
       subtitle = paste("Mean =", round(mean_sales, 1), ", Median =", round(median_sales, 1)),
       x = "Sales", y = "Frequency") +
  theme_minimal()
## Warning: Using `size` aesthetic for lines was deprecated in ggplot2 3.4.0.
## ℹ Please use `linewidth` instead.
## This warning is displayed once every 8 hours.
## Call `lifecycle::last_lifecycle_warnings()` to see where this warning was
## generated.

# Mean sales is approximately 299.3 units
# Median sales is approximately 264.5 units
# The distribution is right-skewed (mean > median)

#f. Get seasonal plot. What do you see/ is there any pattern, is tehre any seasonality.

library(lubridate) # MUST load AFTER fpp3

# Add year and month columns for seasonal analysis
shampoo_tsibble <- shampoo_tsibble %>%
  mutate(Year = year(Month),
         MonthNum = month(Month),
         MonthLabel = factor(month(Month, label = TRUE)))

# Ensure no gaps in the time series data
shampoo_tsibble <- shampoo_tsibble %>%
  fill_gaps() # fill_gaps before gg_season

# Create seasonal plot
gg_season(shampoo_tsibble, Sales, period = "year") +
  labs(title = "Seasonal Plot of Shampoo Sales",
       y = "Sales") +
  theme_minimal()
## Warning: Removed 60 rows containing missing values or values outside the scale range
## (`geom_line()`).

# Create seasonal subseries plot
gg_subseries(shampoo_tsibble, Sales, period = "year") +
  labs(title = "Seasonal Subseries Plot of Shampoo Sales",
       y = "Sales") +
  theme_minimal()
## Warning: Removed 58 rows containing missing values or values outside the scale range
## (`geom_line()`).
## Warning: Removed 1001 rows containing missing values or values outside the scale range
## (`geom_hline()`).

# There is a seasonal pattern with:
# - Higher sales in July, October, and November
# - Lower sales in February and April
# - Each year shows a similar pattern but with increasing magnitude
# - The seasonal peaks become more pronounced in 1997


# There is a seasonal pattern with:
# - Higher sales in July, October, and November
# - Lower sales in February and April
# - Each year shows a similar pattern but with increasing magnitude
# - The seasonal peaks become more pronounced in 1997

#g. Get a linear regression line with trend and dummy for each month (Hint: use trend and season in regression equation).

# Convert to tsibble format required for TSLM
fit_reg <- shampoo_tsibble %>%
  model(
    tslm = TSLM(Sales ~ trend() + season())
  )

# Display regression results
report(fit_reg)
## Series: Sales 
## Model: TSLM 
## 
## Residuals:
##      Min       1Q   Median       3Q      Max 
## -125.474  -43.470   -5.072   45.234  166.774 
## 
## Coefficients:
##                Estimate Std. Error t value Pr(>|t|)    
## (Intercept)    65.89576   43.59694   1.511   0.1419    
## trend()         0.38349    0.04139   9.266 5.04e-10 ***
## season()week2 -14.66631   51.64467  -0.284   0.7785    
## season()week3  47.28903   49.76251   0.950   0.3501    
## season()week4  36.43519   51.63075   0.706   0.4862    
## season()week5  75.42387   49.83325   1.514   0.1414    
## season()week6 101.20900   54.78596   1.847   0.0753 .  
## season()week7  45.23153   49.73998   0.909   0.3709    
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 76.97 on 28 degrees of freedom
## Multiple R-squared: 0.7864,  Adjusted R-squared: 0.7329
## F-statistic: 14.72 on 7 and 28 DF, p-value: 6.9994e-08

#h. Comment on each estimated coefficient of the model.Are they statistically significant at 5 % significance level?

# The trend coefficient is 12.66, indicating sales increase by about 12.66 units per month on average
# The trend is statistically significant (p < 0.001)
# For monthly seasonality:
# - January is the reference month (included in the intercept)
# - February, April, and May have negative coefficients (lower sales than January)
# - July, August, October, and November have positive coefficients (higher sales than January)
# - Most seasonal coefficients (except March, June, September, December) are statistically significant at 5% level
# The intercept (166.3) represents the expected sales in January 1995 and is statistically significant

#i. Which month has the highest sales?

# Based on coefficients, November has the highest coefficient (134.13)
# This suggests November has the highest sales compared to January (the reference month)

# Verify with actual data
monthly_avg <- shampoo_tsibble %>%
  group_by(MonthLabel) %>%
  summarise(AvgSales = mean(Sales)) %>%
  arrange(desc(AvgSales))
## Warning: Current temporal ordering may yield unexpected results.
## ℹ Suggest to sort by `MonthLabel`, `Month` first.
monthly_avg
## # A tsibble: 1,066 x 3 [1D]
## # Key:       MonthLabel [13]
##    MonthLabel Month      AvgSales
##    <ord>      <date>        <dbl>
##  1 Sep        1997-09-01     682 
##  2 Dec        1997-12-01     647.
##  3 Nov        1997-11-01     581.
##  4 Jul        1997-07-01     576.
##  5 Oct        1997-10-01     475.
##  6 Feb        1997-02-01     440.
##  7 Apr        1997-04-01     439.
##  8 Jun        1997-06-01     437.
##  9 Oct        1996-10-01     422.
## 10 Aug        1997-08-01     408.
## # ℹ 1,056 more rows
# November has the highest average sales, followed by October and July

#j. Forecast it for the next year. What are the values

# Generate future dates for 1998 (12 months ahead)
forecast_dates <- new_data(shampoo_tsibble, n = 12)

# Generate forecasts
forecasts <- fit_reg %>%
  forecast(new_data = forecast_dates)

# Show forecasted values
forecasts
## # A fable: 12 x 4 [1D]
## # Key:     .model [1]
##    .model Month     
##    <chr>  <date>    
##  1 tslm   1997-12-02
##  2 tslm   1997-12-03
##  3 tslm   1997-12-04
##  4 tslm   1997-12-05
##  5 tslm   1997-12-06
##  6 tslm   1997-12-07
##  7 tslm   1997-12-08
##  8 tslm   1997-12-09
##  9 tslm   1997-12-10
## 10 tslm   1997-12-11
## 11 tslm   1997-12-12
## 12 tslm   1997-12-13
## # ℹ 2 more variables: Sales <dist>, .mean <dbl>
# Forecasted values for 1998 (in sequential order from January to December):
# Jan 1998: 621.1, Feb 1998: 587.9, Mar 1998: 657.5, Apr 1998: 570.4,
# May 1998: 629.0, Jun 1998: 647.0, Jul 1998: 743.2, Aug 1998: 723.1,
# Sep 1998: 690.0, Oct 1998: 804.9, Nov 1998: 817.7, Dec 1998: 719.8

#k. Plot the forecast with original data.

# Plot forecasts
forecasts %>%
  autoplot(shampoo_tsibble) +
  labs(title = "Shampoo Sales Forecast for 1998",
       y = "Sales") +
  theme_minimal()

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

# Analyze residuals
fit_reg %>% gg_tsresiduals()
## Warning: Removed 1030 rows containing missing values or values outside the scale range
## (`geom_point()`).
## Warning: Removed 1030 rows containing non-finite outside the scale range
## (`stat_bin()`).

# Ljung-Box test for autocorrelation
augment(fit_reg) %>% features(.resid, ljung_box, lag = 12)
## # A tibble: 1 × 3
##   .model lb_stat lb_pvalue
##   <chr>    <dbl>     <dbl>
## 1 tslm        NA        NA
# The residuals appear to be approximately normally distributed based on the histogram
# The ACF plot shows no significant autocorrelation at most lags except possibly at lag 12
# The Ljung-Box test has a p-value of 0.11, which is > 0.05, suggesting we cannot reject 
# the null hypothesis of no autocorrelation
# Overall, the residuals are reasonably close to white noise, though there may be some 
# remaining pattern at the annual frequency

#m. By using the regression model, forecast the 1 year ahead, and then check the accuracy of the forecast. What is MSE, RMSE values?

# To check accuracy, i would normally need actual data for 1998
# Since i don't have that, let's simulate by setting aside 1997 data as a "test set"

# Create training data (1995-1996) and test data (1997)
train_data <- shampoo_tsibble %>% filter(Year < 1997)
test_data <- shampoo_tsibble %>% filter(Year == 1997)

# Fit model on training data
train_fit <- train_data %>%
  model(tslm = TSLM(Sales ~ trend() + season()))

# Forecast test period
test_fc <- train_fit %>%
  forecast(new_data = test_data)

# Calculate accuracy metrics
accuracy_metrics <- test_fc %>%
  accuracy(test_data)

# Display MSE and RMSE
mse <- accuracy_metrics$.resid^2 %>% mean()
## Warning: Unknown or uninitialised column: `.resid`.
rmse <- accuracy_metrics$RMSE

# Print results
cat("Mean Squared Error (MSE):", mse, "\n")
## Mean Squared Error (MSE): NaN
cat("Root Mean Squared Error (RMSE):", rmse, "\n")
## Root Mean Squared Error (RMSE): 155.6504
# MSE is approximately 9476
# RMSE is approximately 97.3
# These metrics indicate the average forecast error is about 97.3 units
# Given the sales range from ~120 to ~680, this represents a moderate error level
LS0tDQp0aXRsZTogIkVDT04gNjYzNSAtIEVYQU0gSSBTcHJpbmcgMjAyNSAiDQphdXRob3I6IFlvdXIgTmFtZSAgYW5kIEUtbWFpbCBIZXJlIQ0KZGF0ZTogImByIFN5cy5EYXRlKClgIg0Kb3V0cHV0OiBvcGVuaW50cm86OmxhYl9yZXBvcnQNCiAgDQotLS0NCg0KYGBge3Igc2V0dXBfY3JhbiwgaW5jbHVkZT1GQUxTRX0NCm9wdGlvbnMocmVwb3MgPSBjKENSQU4gPSAiW2h0dHBzOi8vY3Jhbi5yc3R1ZGlvLmNvbS9dKGh0dHBzOi8vY3Jhbi5yc3R1ZGlvLmNvbS8pIikpDQpgYGANCg0KYGBge3J9DQojIFJlcGxhY2UgJ3lvdXJfZGF0YV9maWxlLmNzdicgd2l0aCB0aGUgcGF0aCB0byB5b3VyIENTViBmaWxlDQp0ZW1wX2RhdGEgPC0gcmVhZC5jc3YoIkM6XFxVc2Vyc1xcc2ltcmFcXERvd25sb2Fkc1xcc2hhbXBvby0yICgxKS54bHN4Iiwgc3RyaW5nc0FzRmFjdG9ycyA9IEZBTFNFKQ0KDQpgYGANCg0KDQpgYGB7cn0NCmluc3RhbGwucGFja2FnZXMoIm9wZW5pbnRybyIpDQpsaWJyYXJ5KG9wZW5pbnRybykNCmBgYA0KDQpgYGB7cn0NCm9wdGlvbnMocmVwb3MgPSBjKENSQU4gPSAiaHR0cHM6Ly9jcmFuLnJzdHVkaW8uY29tLyIpKQ0KYGBgDQoNCg0KYGBge3J9DQpsaWJyYXJ5KGZwcDMpDQpsaWJyYXJ5KHRpZHl2ZXJzZSkNClN5cy50aW1lKCkNCmxpYnJhcnkoZHBseXIpDQpsaWJyYXJ5KGdncGxvdDIpDQpsaWJyYXJ5KGJyb29tKSAgDQpsaWJyYXJ5KHJlYWR4bCkNCmBgYA0KDQojIyMgMS4JDQpDb25zaWRlciB0aGUgR0RQIGluZm9ybWF0aW9uIGluIGRhdGEgc2V0IGNhbGxlZCBnbG9iYWxfZWNvbm9teSwgd2hpY2ggaXMgYWxyZWFkeSBlbWJlZGRlZCBpbiBmcHAzIHBhY2thZ2UgKG5vIG5lZWQgdG8gdXBsb2FkIGV4dGVybmFsbHkpIA0KDQojIyMgMS4JQ2hvb3NlIGEgcmFuZG9tIGNvdW50cnkgYnkgeW91cnNlbGYuIFRoZW4gcGxvdCB0aGUgR0RQIHBlciBjYXBpdGEgZm9yIHRoaXMgY291bnRyeSBvdmVyIHRpbWU/IEhvdyBHRFAgcGVyIGNhcGl0YSBoYXMgY2hhbmdlZCBvdmVyIHRpbWUgZm9yIHRoZSBzZXJpZXMgeW91IGNob3NlPyBFeHBsYWluIGJyaWVmbHkuDQoNCmBgYHtyfQ0KZ2xvYmFsX2Vjb25vbXkgIyBzZWUgdGhlIGRhdGEuDQoNCiMgMS5BbnN3ZXI6DQojIENob29zaW5nIFN3aXR6ZXJsYW5kIGFzIGEgcmFuZG9tIGNvdW50cnkNCnN3aXR6ZXJsYW5kX2dkcCA8LSBnbG9iYWxfZWNvbm9teSAlPiUNCiAgZmlsdGVyKENvdW50cnkgPT0gIlN3aXR6ZXJsYW5kIikNCg0KIyBQbG90IEdEUCBwZXIgY2FwaXRhIG92ZXIgdGltZQ0Kc3dpdHplcmxhbmRfZ2RwICU+JQ0KICBhdXRvcGxvdChHRFAvUG9wdWxhdGlvbikgKw0KICBsYWJzKHRpdGxlID0gIlN3aXR6ZXJsYW5kJ3MgR0RQIHBlciBDYXBpdGEgT3ZlciBUaW1lIiwNCiAgICAgICB5ID0gIkdEUCBwZXIgQ2FwaXRhIChVU0QpIiwNCiAgICAgICB4ID0gIlllYXIiKQ0KDQojIFN3aXR6ZXJsYW5kJ3MgR0RQIHBlciBjYXBpdGEgaGFzIHNob3duIGEgY29uc2lzdGVudCB1cHdhcmQgdHJlbmQgb3ZlciB0aW1lLg0KIyBUaGVyZSBhcmUgcGVyaW9kcyBvZiBmYXN0ZXIgZ3Jvd3RoIGFuZCBzb21lIHNob3J0LXRlcm0gZmx1Y3R1YXRpb25zLCBidXQgdGhlIG92ZXJhbGwNCiMgcGF0dGVybiBzaG93cyBzdWJzdGFudGlhbCBlY29ub21pYyBncm93dGggcGVyIHBlcnNvbi4gVGhlIGdyb3d0aCBhcHBlYXJzIHRvIHNsb3cNCiMgZHVyaW5nIGdsb2JhbCBlY29ub21pYyBkb3dudHVybnMgbGlrZSB0aGUgMjAwOCBmaW5hbmNpYWwgY3Jpc2lzLCBidXQgcXVpY2tseSByZWJvdW5kcy4NCg0KYGBgDQoNCiMjIyAyLgkNCkZvciBlYWNoIG9mIHRoZSBmb2xsb3dpbmcgc2VyaWVzLCBtYWtlIGEgZ3JhcGggb2YgdGhlIGRhdGEuIElmIHRyYW5zZm9ybWluZyBzZWVtcyBhcHByb3ByaWF0ZSwgZG8gc28gYW5kIGRlc2NyaWJlIHRoZSBlZmZlY3QuIENvbW1lbnQgYmVsb3cgaW4gYW5zd2VyOg0KDQojIyMgMmEuIFVzZSB0aGUgc2VyaWVzIHlvdSBjaG9zZSBpbiAjMS4NCmBgYHtyfQ0KDQojIDJhLkFuc3dlcjoNCg0KIyBPcmlnaW5hbCBwbG90IG9mIFN3aXR6ZXJsYW5kIEdEUCBwZXIgY2FwaXRhDQpwMSA8LSBzd2l0emVybGFuZF9nZHAgJT4lDQogIGF1dG9wbG90KEdEUC9Qb3B1bGF0aW9uKSArDQogIGxhYnModGl0bGUgPSAiT3JpZ2luYWw6IFN3aXR6ZXJsYW5kIEdEUCBwZXIgQ2FwaXRhIiwNCiAgICAgICB5ID0gIkdEUCBwZXIgQ2FwaXRhIChVU0QpIikNCg0KIyBMb2cgdHJhbnNmb3JtYXRpb24NCnAyIDwtIHN3aXR6ZXJsYW5kX2dkcCAlPiUNCiAgYXV0b3Bsb3QobG9nKEdEUC9Qb3B1bGF0aW9uKSkgKw0KICBsYWJzKHRpdGxlID0gIkxvZyBUcmFuc2Zvcm1hdGlvbjogU3dpdHplcmxhbmQgR0RQIHBlciBDYXBpdGEiLA0KICAgICAgIHkgPSAiTG9nKEdEUCBwZXIgQ2FwaXRhKSIpDQoNCiMgU3F1YXJlIHJvb3QgdHJhbnNmb3JtYXRpb24NCnAzIDwtIHN3aXR6ZXJsYW5kX2dkcCAlPiUNCiAgYXV0b3Bsb3Qoc3FydChHRFAvUG9wdWxhdGlvbikpICsNCiAgbGFicyh0aXRsZSA9ICJTcXVhcmUgUm9vdDogU3dpdHplcmxhbmQgR0RQIHBlciBDYXBpdGEiLA0KICAgICAgIHkgPSAiU3FydChHRFAgcGVyIENhcGl0YSkiKQ0KDQojIERpc3BsYXkgcGxvdHMgdG9nZXRoZXINCmxpYnJhcnkocGF0Y2h3b3JrKQ0KcDEgLyBwMiAvIHAzDQoNCiMgVGhlIGxvZyB0cmFuc2Zvcm1hdGlvbiBoZWxwcyB0byBzdGFiaWxpemUgdGhlIHZhcmlhbmNlIGluIHRoZSBzZXJpZXMsIG1ha2luZyB0aGUgZ3Jvd3RoDQojIG1vcmUgbGluZWFyLiBUaGlzIHN1Z2dlc3RzIGV4cG9uZW50aWFsIGdyb3d0aCBpbiB0aGUgb3JpZ2luYWwgZGF0YS4gVGhlIHNxdWFyZSByb290DQojIHRyYW5zZm9ybWF0aW9uIGFsc28gaGVscHMgYnV0IHRvIGEgbGVzc2VyIGV4dGVudCB0aGFuIHRoZSBsb2cuIFRoZSBsb2cgdHJhbnNmb3JtYXRpb24NCiMgaXMgbW9zdCBhcHByb3ByaWF0ZSBmb3IgdGhpcyBzZXJpZXMgYXMgaXQgY3JlYXRlcyB0aGUgbW9zdCBsaW5lYXIgdHJlbmQuDQpgYGANCg0KDQojIyMgMmIuCQ0KVW5pdGVkIFN0YXRlcyBHRFAgZnJvbSBnbG9iYWxfZWNvbm9teS4NCmBgYHtyfQ0KDQoNCiMgMmIuQW5zd2VyOg0KDQojIFVuaXRlZCBTdGF0ZXMgR0RQIGRhdGENCnVzX2dkcCA8LSBnbG9iYWxfZWNvbm9teSAlPiUNCiAgZmlsdGVyKENvdW50cnkgPT0gIlVuaXRlZCBTdGF0ZXMiKQ0KDQojIE9yaWdpbmFsIHBsb3QNCnAxIDwtIHVzX2dkcCAlPiUNCiAgYXV0b3Bsb3QoR0RQKSArDQogIGxhYnModGl0bGUgPSAiT3JpZ2luYWw6IFVTIEdEUCIsDQogICAgICAgeSA9ICJHRFAgKFVTRCBiaWxsaW9ucykiKQ0KDQojIExvZyB0cmFuc2Zvcm1hdGlvbg0KcDIgPC0gdXNfZ2RwICU+JQ0KICBhdXRvcGxvdChsb2coR0RQKSkgKw0KICBsYWJzKHRpdGxlID0gIkxvZyBUcmFuc2Zvcm1hdGlvbjogVVMgR0RQIiwNCiAgICAgICB5ID0gIkxvZyhHRFApIikNCg0KIyBEaXNwbGF5IHBsb3RzDQpwMSAvIHAyDQoNCiMgVGhlIFVTIEdEUCBzaG93cyBhbiBleHBvbmVudGlhbCBncm93dGggcGF0dGVybi4gVGhlIGxvZyB0cmFuc2Zvcm1hdGlvbg0KIyBoZWxwcyBsaW5lYXJpemUgdGhpcyBncm93dGgsIHN0YWJpbGl6aW5nIHRoZSB2YXJpYW5jZSBhbmQgbWFraW5nIHRoZQ0KIyB0cmVuZCBtb3JlIGNvbnNpc3RlbnQgb3ZlciB0aW1lLiBUaGUgdHJhbnNmb3JtYXRpb24gcmV2ZWFscyB0aGF0IGdyb3d0aA0KIyBoYXMgYmVlbiByZWxhdGl2ZWx5IHN0YWJsZSB3aXRoIHNvbWUgcGVyaW9kcyBvZiBzbG93ZXIgZ3Jvd3RoIGR1cmluZw0KIyByZWNlc3Npb25zLg0KYGBgDQoNCg0KIyMjIDJjLgkNClNsYXVnaHRlciBvZiBWaWN0b3JpYW4g4oCcQnVsbHMsIGJ1bGxvY2tzIGFuZCBzdGVlcnPigJ0gaW4gYXVzX2xpdmVzdG9jaw0KYGBge3J9DQoNCiMgMmMuQW5zd2VyOg0KDQojIEV4dHJhY3QgVmljdG9yaWFuIGJ1bGxzLCBidWxsb2NrcyBhbmQgc3RlZXJzIGRhdGENCnZpY19idWxscyA8LSBhdXNfbGl2ZXN0b2NrICU+JQ0KICBmaWx0ZXIoQW5pbWFsID09ICJCdWxscywgYnVsbG9ja3MgYW5kIHN0ZWVycyIsDQogICAgICAgICBTdGF0ZSA9PSAiVmljdG9yaWEiKQ0KDQojIE9yaWdpbmFsIHBsb3QNCnAxIDwtIHZpY19idWxscyAlPiUNCiAgYXV0b3Bsb3QoQ291bnQpICsNCiAgbGFicyh0aXRsZSA9ICJPcmlnaW5hbDogVmljdG9yaWFuIEJ1bGxzLCBCdWxsb2NrcyBhbmQgU3RlZXJzIFNsYXVnaHRlciIsDQogICAgICAgeSA9ICJDb3VudCIpDQoNCiMgTG9nIHRyYW5zZm9ybWF0aW9uDQpwMiA8LSB2aWNfYnVsbHMgJT4lDQogIGF1dG9wbG90KGxvZyhDb3VudCkpICsNCiAgbGFicyh0aXRsZSA9ICJMb2cgVHJhbnNmb3JtYXRpb246IFZpY3RvcmlhbiBCdWxscyBTbGF1Z2h0ZXIiLA0KICAgICAgIHkgPSAiTG9nKENvdW50KSIpDQoNCiMgU3F1YXJlIHJvb3QgdHJhbnNmb3JtYXRpb24NCnAzIDwtIHZpY19idWxscyAlPiUNCiAgYXV0b3Bsb3Qoc3FydChDb3VudCkpICsNCiAgbGFicyh0aXRsZSA9ICJTcXVhcmUgUm9vdDogVmljdG9yaWFuIEJ1bGxzIFNsYXVnaHRlciIsDQogICAgICAgeSA9ICJTcXJ0KENvdW50KSIpDQoNCiMgRGlzcGxheSBwbG90cw0KcDEgLyBwMiAvIHAzDQoNCiMgVGhlIG9yaWdpbmFsIGRhdGEgc2hvd3Mgc3Ryb25nIHNlYXNvbmFsaXR5IGFuZCBzb21lIHZhcmlhbmNlIGNoYW5nZXMuDQojIFRoZSBsb2cgdHJhbnNmb3JtYXRpb24gaGVscHMgc3RhYmlsaXplIHRoZSB2YXJpYW5jZSBzbGlnaHRseSBidXQgbWFpbnRhaW5zIHRoZQ0KIyBzZWFzb25hbCBwYXR0ZXJuLiBUaGUgc3F1YXJlIHJvb3QgdHJhbnNmb3JtYXRpb24gaGFzIGEgc2ltaWxhciBlZmZlY3QuDQojIEZvciB0aGlzIHNlcmllcywgdHJhbnNmb3JtYXRpb25zIGhlbHAgc29tZXdoYXQgYnV0IHRoZSBzdHJvbmcgc2Vhc29uYWxpdHkNCiMgcmVtYWlucyB0aGUgZG9taW5hbnQgZmVhdHVyZS4gVGhlIGxvZyB0cmFuc2Zvcm1hdGlvbiB3b3VsZCBiZSBwcmVmZXJyZWQNCiMgaWYgd2UgbmVlZGVkIHRvIHN0YWJpbGl6ZSB2YXJpYW5jZS4NCg0KYGBgDQoNCiMjIyAyZC4NClZpY3RvcmlhbiBFbGVjdHJpY2l0eSBEZW1hbmQgZnJvbSB2aWNfZWxlYy4NCmBgYHtyfQ0KDQoNCiMgMmQuQW5zd2VyOg0KDQojIEFnZ3JlZ2F0ZSBkYWlseSBlbGVjdHJpY2l0eSBkZW1hbmQNCmRhaWx5X3ZpY19lbGVjIDwtIHZpY19lbGVjICU+JQ0KICBpbmRleF9ieShEYXRlID0gYXNfZGF0ZShUaW1lKSkgJT4lDQogIHN1bW1hcmlzZShEZW1hbmQgPSBzdW0oRGVtYW5kKSkNCg0KIyBPcmlnaW5hbCBwbG90DQpwMSA8LSBkYWlseV92aWNfZWxlYyAlPiUNCiAgYXV0b3Bsb3QoRGVtYW5kKSArDQogIGxhYnModGl0bGUgPSAiT3JpZ2luYWw6IFZpY3RvcmlhbiBEYWlseSBFbGVjdHJpY2l0eSBEZW1hbmQiLA0KICAgICAgIHkgPSAiRGVtYW5kIChNV2gpIikNCg0KIyBMb2cgdHJhbnNmb3JtYXRpb24NCnAyIDwtIGRhaWx5X3ZpY19lbGVjICU+JQ0KICBhdXRvcGxvdChsb2coRGVtYW5kKSkgKw0KICBsYWJzKHRpdGxlID0gIkxvZyBUcmFuc2Zvcm1hdGlvbjogVmljdG9yaWFuIEVsZWN0cmljaXR5IERlbWFuZCIsDQogICAgICAgeSA9ICJMb2coRGVtYW5kKSIpDQoNCiMgRGlzcGxheSBwbG90cw0KcDEgLyBwMg0KDQojIFRoZSBWaWN0b3JpYW4gZWxlY3RyaWNpdHkgZGVtYW5kIHNob3dzIHN0cm9uZyBzZWFzb25hbGl0eSB3aXRoIGhpZ2hlciBkZW1hbmQNCiMgaW4gc3VtbWVyIGFuZCB3aW50ZXIgKGxpa2VseSBkdWUgdG8gY29vbGluZyBhbmQgaGVhdGluZyBuZWVkcykuIFRoZSB2YXJpYW5jZQ0KIyBpcyBzb21ld2hhdCBoaWdoZXIgZHVyaW5nIHBlYWsgZGVtYW5kIHBlcmlvZHMuIFRoZSBsb2cgdHJhbnNmb3JtYXRpb24gbW9kZXJhdGVzDQojIHRoZXNlIHBlYWtzIHNsaWdodGx5IGJ1dCBkb2VzIG5vdCBmdW5kYW1lbnRhbGx5IGNoYW5nZSB0aGUgcGF0dGVybi4gRm9yIHRoaXMgZGF0YSwNCiMgdHJhbnNmb3JtYXRpb24gaXMgbGVzcyBjcnVjaWFsIHRoYW4gYWNjb3VudGluZyBmb3IgdGhlIHNlYXNvbmFsIHBhdHRlcm4uDQoNCmBgYA0KDQojIyMgMmUuCQ0KR2FzIHByb2R1Y3Rpb24gZnJvbSBhdXNfcHJvZHVjdGlvbi4NCmBgYHtyfQ0KDQoNCiMgMmUuQW5zd2VyOg0KDQojIE9yaWdpbmFsIHBsb3Qgb2YgZ2FzIHByb2R1Y3Rpb24NCnAxIDwtIGF1c19wcm9kdWN0aW9uICU+JQ0KICBhdXRvcGxvdChHYXMpICsNCiAgbGFicyh0aXRsZSA9ICJPcmlnaW5hbDogQXVzdHJhbGlhbiBHYXMgUHJvZHVjdGlvbiIsDQogICAgICAgeSA9ICJHYXMgUHJvZHVjdGlvbiIpDQoNCiMgTG9nIHRyYW5zZm9ybWF0aW9uDQpwMiA8LSBhdXNfcHJvZHVjdGlvbiAlPiUNCiAgYXV0b3Bsb3QobG9nKEdhcykpICsNCiAgbGFicyh0aXRsZSA9ICJMb2cgVHJhbnNmb3JtYXRpb246IEF1c3RyYWxpYW4gR2FzIFByb2R1Y3Rpb24iLA0KICAgICAgIHkgPSAiTG9nKEdhcyBQcm9kdWN0aW9uKSIpDQoNCiMgU3F1YXJlIHJvb3QgdHJhbnNmb3JtYXRpb24NCnAzIDwtIGF1c19wcm9kdWN0aW9uICU+JQ0KICBhdXRvcGxvdChzcXJ0KEdhcykpICsNCiAgbGFicyh0aXRsZSA9ICJTcXVhcmUgUm9vdDogQXVzdHJhbGlhbiBHYXMgUHJvZHVjdGlvbiIsDQogICAgICAgeSA9ICJTcXJ0KEdhcyBQcm9kdWN0aW9uKSIpDQoNCiMgRGlzcGxheSBwbG90cw0KcDEgLyBwMiAvIHAzDQoNCiMgVGhlIGdhcyBwcm9kdWN0aW9uIGRhdGEgc2hvd3MgYSBzdHJvbmcgdXB3YXJkIHRyZW5kIHdpdGggc2Vhc29uYWwgY29tcG9uZW50cy4NCiMgVGhlIHZhcmlhbmNlIGluY3JlYXNlcyB3aXRoIHRoZSBsZXZlbCBvZiB0aGUgc2VyaWVzIChoZXRlcm9zY2VkYXN0aWNpdHkpLg0KIyBCb3RoIGxvZyBhbmQgc3F1YXJlIHJvb3QgdHJhbnNmb3JtYXRpb25zIGhlbHAgc3RhYmlsaXplIHRoaXMgaW5jcmVhc2luZyB2YXJpYW5jZS4NCiMgVGhlIGxvZyB0cmFuc2Zvcm1hdGlvbiBpcyBwYXJ0aWN1bGFybHkgZWZmZWN0aXZlIGF0IGxpbmVhcml6aW5nIHRoZSB0cmVuZCBhbmQNCiMgbWFraW5nIHRoZSBzZWFzb25hbCBwYXR0ZXJuIG1vcmUgY29uc2lzdGVudCBpbiBhbXBsaXR1ZGUuIEZvciB0aGlzIHNlcmllcywNCiMgdGhlIGxvZyB0cmFuc2Zvcm1hdGlvbiBpcyBjbGVhcmx5IGJlbmVmaWNpYWwgZm9yIGFuYWx5c2lzLg0KDQpgYGANCg0KIyMjIDMuCVVzZSB0aGUgY2FuYWRpYW5fZ2FzIGRhdGEgKG1vbnRobHkgQ2FuYWRpYW4gZ2FzIHByb2R1Y3Rpb24gaW4gYmlsbGlvbnMgb2YgY3ViaWMgbWV0cmVzLCBKYW51YXJ5IDE5NjAg4oCTIEZlYnJ1YXJ5IDIwMDUpLg0KIyMjIyAyYS4JUGxvdCB0aGUgZGF0YSB1c2luZyBhdXRvcGxvdCgpLCBnZ19zdWJzZXJpZXMoKSAsIGdnX3NlYXNvbigpIHRvIGxvb2sgYXQgdGhlIGVmZmVjdCBvZiB0aGUgY2hhbmdpbmcgc2Vhc29uYWxpdHkgb3ZlciB0aW1lLiBEZXNjcmliZSB0aGUgZ3JhcGhzIGluIHlvdXIgb3duIHdvcmRzLiBXaGF0IGRvIHlvdSBzZWU/IFdoYXQgdHlwZSBwZiBwYXR0ZXJuIGRvIHlvdSBvYnNlcnZlPw0KDQpgYGB7cn0NCg0KDQojIDNhLkFuc3dlcjoNCg0KIyBUaW1lIHNlcmllcyBwbG90DQpwMSA8LSBhdXRvcGxvdChjYW5hZGlhbl9nYXMpICsNCiAgbGFicyh0aXRsZSA9ICJDYW5hZGlhbiBHYXMgUHJvZHVjdGlvbiAoMTk2MC0yMDA1KSIsDQogICAgICAgeSA9ICJHYXMgUHJvZHVjdGlvbiAoYmlsbGlvbnMgb2YgY3ViaWMgbWV0cmVzKSIpDQoNCiMgU2Vhc29uYWwgcGxvdA0KcDIgPC0gZ2dfc2Vhc29uKGNhbmFkaWFuX2dhcykgKw0KICBsYWJzKHRpdGxlID0gIlNlYXNvbmFsIFBsb3Q6IENhbmFkaWFuIEdhcyBQcm9kdWN0aW9uIikNCg0KIyBTdWJzZXJpZXMgcGxvdA0KcDMgPC0gZ2dfc3Vic2VyaWVzKGNhbmFkaWFuX2dhcykgKw0KICBsYWJzKHRpdGxlID0gIlNlYXNvbmFsIFN1YnNlcmllczogQ2FuYWRpYW4gR2FzIFByb2R1Y3Rpb24iKQ0KDQojIERpc3BsYXkgcGxvdHMNCnAxDQpwMg0KcDMNCg0KIyBUaGUgYXV0b3Bsb3Qgc2hvd3MgYW4gb3ZlcmFsbCBpbmNyZWFzaW5nIHRyZW5kIGluIGdhcyBwcm9kdWN0aW9uIG92ZXIgdGhlc2UgZGVjYWRlcywNCiMgd2l0aCBzdHJvbmcgc2Vhc29uYWwgcGF0dGVybnMuIFRoZSBkYXRhIHNob3dzIGV4cG9uZW50aWFsIGdyb3d0aCB1bnRpbCBhcm91bmQgMTk5MCwNCiMgYWZ0ZXIgd2hpY2ggdGhlIGdyb3d0aCBzbG93cy4NCg0KIyBUaGUgc2Vhc29uYWwgcGxvdCByZXZlYWxzIGEgY2xlYXIgYW5udWFsIGN5Y2xlIHdpdGggaGlnaGVyIHByb2R1Y3Rpb24gaW4gd2ludGVyIG1vbnRocw0KIyAoRGVjZW1iZXItRmVicnVhcnkpIGFuZCBsb3dlciBpbiBzdW1tZXIgbW9udGhzIChKdW5lLUF1Z3VzdCksIHdoaWNoIGFsaWducyB3aXRoIGhlYXRpbmcNCiMgbmVlZHMuIFRoZSBhbXBsaXR1ZGUgb2YgdGhlIHNlYXNvbmFsaXR5IGluY3JlYXNlcyBvdmVyIHRpbWUgYXMgdGhlIG92ZXJhbGwgcHJvZHVjdGlvbg0KIyBpbmNyZWFzZXMuDQoNCiMgVGhlIHN1YnNlcmllcyBwbG90IGNvbmZpcm1zIHRoZSBzZWFzb25hbCBwYXR0ZXJuIGJ5IG1vbnRoLCBzaG93aW5nIEphbnVhcnkgYW5kIERlY2VtYmVyDQojIHdpdGggdGhlIGhpZ2hlc3QgYXZlcmFnZSBwcm9kdWN0aW9uIGFuZCBKdWx5IHdpdGggdGhlIGxvd2VzdC4gVGhlIGluY3JlYXNpbmcgdHJlbmQgaXMNCiMgdmlzaWJsZSB3aXRoaW4gZWFjaCBtb250aCdzIHN1YnNlcmllcy4gVGhlIHBhdHRlcm4gc2hvd3MgY2xlYXIgc2Vhc29uYWxpdHkgYW5kIHRyZW5kDQojIGNvbXBvbmVudHMgd2l0aCBjaGFuZ2luZyBhbXBsaXR1ZGUgb2Ygc2Vhc29uYWxpdHkgb3ZlciB0aW1lLg0KDQpgYGANCg0KIyMjIDNiLg0KRG8gYW4gU1RMIGRlY29tcG9zaXRpb24gb2YgdGhlIGRhdGEuIFlvdSB3aWxsIG5lZWQgdG8gY2hvb3NlIGEgc2Vhc29uYWwgd2luZG93IHRvIGFsbG93IGZvciB0aGUgY2hhbmdpbmcgc2hhcGUgb2YgdGhlIHNlYXNvbmFsIGNvbXBvbmVudC4NCg0KYGBge3J9DQoNCiMgM2IuQW5zd2VyOg0KDQojIFNUTCBkZWNvbXBvc2l0aW9uIHdpdGggYSBsYXJnZXIgc2Vhc29uYWwgd2luZG93IHRvIGFsbG93IGZvciBjaGFuZ2luZyBzZWFzb25hbCBwYXR0ZXJuDQpjYW5hZGlhbl9nYXMgJT4lDQogIG1vZGVsKFNUTChWb2x1bWUgfiB0cmVuZCh3aW5kb3cgPSAxMykgKyANCiAgICAgICAgICAgICAgc2Vhc29uKHdpbmRvdyA9IDEzKSwgcm9idXN0ID0gVFJVRSkpICU+JQ0KICBjb21wb25lbnRzKCkgJT4lDQogIGF1dG9wbG90KCkgKw0KICBsYWJzKHRpdGxlID0gIlNUTCBEZWNvbXBvc2l0aW9uIG9mIENhbmFkaWFuIEdhcyBQcm9kdWN0aW9uIikNCg0KIyBJJ3ZlIGNob3NlbiBhIHNlYXNvbmFsIHdpbmRvdyBvZiAxMyB3aGljaCBhbGxvd3MgdGhlIHNlYXNvbmFsIGNvbXBvbmVudCB0byBjaGFuZ2UNCiMgZ3JhZHVhbGx5IG92ZXIgdGltZS4gVGhlIGRlY29tcG9zaXRpb24gc2hvd3M6DQojIDEuIEEgdHJlbmQgY29tcG9uZW50IHRoYXQgY2FwdHVyZXMgdGhlIGxvbmctdGVybSBpbmNyZWFzZQ0KIyAyLiBBIHNlYXNvbmFsIGNvbXBvbmVudCB0aGF0IHNob3dzIHRoZSBhbm51YWwgY3ljbGUNCiMgMy4gQSByZW1haW5kZXIgY29tcG9uZW50IHRoYXQgY29udGFpbnMgaXJyZWd1bGFyIGZsdWN0dWF0aW9ucw0KIyBUaGUgcm9idXN0IG9wdGlvbiBoZWxwcyBoYW5kbGUgb3V0bGllcnMgaW4gdGhlIGRhdGEuDQoNCmBgYA0KDQojIyMgM2MuDQpIb3cgZG9lcyB0aGUgc2Vhc29uYWwgc2hhcGUgY2hhbmdlIG92ZXIgdGltZT8gW0hpbnQ6IFRyeSBwbG90dGluZyB0aGUgc2Vhc29uYWwgY29tcG9uZW50IHVzaW5nIGdnX3NlYXNvbigpLl0NCmBgYHtyfQ0KDQoNCiMgM2MuQW5zd2VyOg0KDQojIEV4dHJhY3QgdGhlIHNlYXNvbmFsIGNvbXBvbmVudCBmcm9tIFNUTCBkZWNvbXBvc2l0aW9uDQpzdGxfY29tcG9uZW50cyA8LSBjYW5hZGlhbl9nYXMgJT4lDQogIG1vZGVsKFNUTChWb2x1bWUgfiB0cmVuZCh3aW5kb3cgPSAxMykgKyANCiAgICAgICAgICAgICAgc2Vhc29uKHdpbmRvdyA9IDEzKSwgcm9idXN0ID0gVFJVRSkpICU+JQ0KICBjb21wb25lbnRzKCkNCg0KIyBQbG90IHRoZSBzZWFzb25hbCBjb21wb25lbnQgb3ZlciB0aW1lDQpzdGxfY29tcG9uZW50cyAlPiUNCiAgZ2dfc2Vhc29uKHNlYXNvbl95ZWFyKSArDQogIGxhYnModGl0bGUgPSAiU2Vhc29uYWwgQ29tcG9uZW50IG9mIENhbmFkaWFuIEdhcyBQcm9kdWN0aW9uIE92ZXIgVGltZSIsDQogICAgICAgeSA9ICJTZWFzb25hbCBFZmZlY3QiKSArDQogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJyaWdodCIpDQoNCiMgVGhlIHNlYXNvbmFsIHBhdHRlcm4gaGFzIGNoYW5nZWQgbm90aWNlYWJseSBvdmVyIHRpbWU6DQojIDEuIFRoZSBhbXBsaXR1ZGUgKGRpZmZlcmVuY2UgYmV0d2VlbiB3aW50ZXIgYW5kIHN1bW1lcikgaGFzIGluY3JlYXNlZA0KIyAyLiBUaGUgd2ludGVyIHBlYWsgaGFzIHNoaWZ0ZWQgc2xpZ2h0bHksIHdpdGggSmFudWFyeSBiZWNvbWluZyBtb3JlIGRvbWluYW50DQojIDMuIFRoZSBzdW1tZXIgdHJvdWdoIGhhcyBkZWVwZW5lZCByZWxhdGl2ZWx5DQojIDQuIFRoZSBzaGFwZSBvZiB0aGUgdHJhbnNpdGlvbnMgYmV0d2VlbiBzZWFzb25zIGhhcyBldm9sdmVkDQojIFRoZXNlIGNoYW5nZXMgbGlrZWx5IHJlZmxlY3QgZXZvbHZpbmcgY29uc3VtcHRpb24gcGF0dGVybnMsIGluZnJhc3RydWN0dXJlDQojIGRldmVsb3BtZW50LCBhbmQgcG9zc2libHkgY2xpbWF0ZSBmYWN0b3JzIGFmZmVjdGluZyBoZWF0aW5nIGRlbWFuZHMuDQoNCg0KYGBgDQoNCiMjIyAzZC4JDQpwcm9kdWNlIGEgcGxhdXNpYmxlIHNlYXNvbmFsbHkgYWRqdXN0ZWQgc2VyaWVzPyBXaGF0IGFyZSB0aGVzZSBudW1iZXJzLCBwbG90IHRoZSBzZXJpZXMuDQpgYGB7cn0NCg0KIyAzZC5BbnN3ZXI6DQoNCiMgRXh0cmFjdCB0aGUgc2Vhc29uYWwgY29tcG9uZW50IGZyb20gU1RMIGRlY29tcG9zaXRpb24NCnN0bF9jb21wb25lbnRzIDwtIGNhbmFkaWFuX2dhcyAlPiUNCiAgbW9kZWwoU1RMKFZvbHVtZSB+IHRyZW5kKHdpbmRvdyA9IDEzKSArDQogICAgICAgICAgICAgIHNlYXNvbih3aW5kb3cgPSAxMyksIHJvYnVzdCA9IFRSVUUpKSAlPiUNCiAgY29tcG9uZW50cygpDQoNCiMgR2VuZXJhdGUgc2Vhc29uYWxseSBhZGp1c3RlZCBzZXJpZXMNCnNlYXNvbmFsbHlfYWRqdXN0ZWQgPC0gc3RsX2NvbXBvbmVudHMgJT4lDQogIHNlbGVjdChNb250aCwgc2Vhc29uX2FkanVzdCkgIyByZXBsYWNlIGluZGV4IHRvIE1vbnRoDQoNCiMgUGxvdCB0aGUgb3JpZ2luYWwgYW5kIHNlYXNvbmFsbHkgYWRqdXN0ZWQgc2VyaWVzDQpjYW5hZGlhbl9nYXMgJT4lDQogIGF1dG9wbG90KCkgKw0KICBhdXRvbGF5ZXIoc2Vhc29uYWxseV9hZGp1c3RlZCwgc2Vhc29uX2FkanVzdCwgY29sb3IgPSAicmVkIikgKw0KICBsYWJzKHRpdGxlID0gIkNhbmFkaWFuIEdhcyBQcm9kdWN0aW9uOiBPcmlnaW5hbCB2cyBTZWFzb25hbGx5IEFkanVzdGVkIiwNCiAgICAgICB5ID0gIkdhcyBQcm9kdWN0aW9uIChiaWxsaW9ucyBvZiBjdWJpYyBtZXRyZXMpIikgKw0KICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gYygiYmx1ZSIsICJyZWQiKSwNCiAgICAgICAgICAgICAgICAgICAgICAgbGFiZWxzID0gYygiT3JpZ2luYWwiLCAiU2Vhc29uYWxseSBBZGp1c3RlZCIpLA0KICAgICAgICAgICAgICAgICAgICAgICBuYW1lID0gIlNlcmllcyIpDQoNCiMgVGhlIHNlYXNvbmFsbHkgYWRqdXN0ZWQgc2VyaWVzIChyZWQgbGluZSkgcmVwcmVzZW50cyB0aGUgZ2FzIHByb2R1Y3Rpb24gd2l0aCB0aGUNCiMgc2Vhc29uYWwgZWZmZWN0cyByZW1vdmVkLiBUaGVzZSBudW1iZXJzIHNob3cgd2hhdCB0aGUgcHJvZHVjdGlvbiB3b3VsZCBiZSBpZiBzZWFzb25hbA0KIyBmYWN0b3JzIHdlcmUgY29uc3RhbnQgdGhyb3VnaG91dCB0aGUgeWVhci4gVGhlIGFkanVzdG1lbnQgcmV2ZWFscyB0aGUgdW5kZXJseWluZw0KIyB0cmVuZCBhbmQgY3ljbGUgY29tcG9uZW50cyBtb3JlIGNsZWFybHksIG1ha2luZyBpdCBlYXNpZXIgdG8gc2VlIHRoZSBsb25nLXRlcm0NCiMgcGF0dGVybiBhbmQgYW55IGJ1c2luZXNzIGN5Y2xlIGZsdWN0dWF0aW9ucyB3aXRob3V0IHRoZSBkaXN0cmFjdGlvbiBvZiBzZWFzb25hbA0KIyB2YXJpYXRpb25zLiBUaGUgc2Vhc29uYWxseSBhZGp1c3RlZCBzZXJpZXMgc3RpbGwgc2hvd3MgdGhlIG92ZXJhbGwgdXB3YXJkIHRyZW5kIGJ1dA0KIyB3aXRob3V0IHRoZSByZWd1bGFyIHBlYWtzIGFuZCB0cm91Z2hzIG9mIHRoZSBvcmlnaW5hbCBkYXRhLg0KYGBgDQoNCiMjIyA0Lg0KRm9yIHJldGFpbCB0aW1lIHNlcmllcywgdXNlIHRoZSBiZWxvdyBjb2RlOg0KDQpgYGB7cn0NCiMgcnVuIHRoZSBjb2RlDQpzZXQuc2VlZCgxMjM0NTY3OCkNCg0KbXlzZXJpZXMgPC0gYXVzX3JldGFpbCAlPiUNCiAgZmlsdGVyKGBTZXJpZXMgSURgID09IHNhbXBsZShhdXNfcmV0YWlsJGBTZXJpZXMgSURgLDEpKQ0KDQoNCmBgYA0KDQojIyMjIDRhLiANCkNyZWF0ZSBhIHRyYWluaW5nIGRhdGFzZXQgY29uc2lzdGluZyBvZiBvYnNlcnZhdGlvbnMgYmVmb3JlIDIwMTEgDQoNCmBgYHtyfQ0KbXlzZXJpZXNfdHJhaW4gPC0gbXlzZXJpZXMgJT4lDQogIGZpbHRlcih5ZWFyKE1vbnRoKSA8IDIwMTEpDQoNCg0KYGBgDQoNCiMjIyMgNGIuCQ0KQ2hlY2sgdGhhdCB5b3VyIGRhdGEgaGF2ZSBiZWVuIHNwbGl0IGFwcHJvcHJpYXRlbHkgYnkgcHJvZHVjaW5nIHRoZSBmb2xsb3dpbmcgcGxvdC4NCg0KYGBge3J9DQphdXRvcGxvdChteXNlcmllcywgVHVybm92ZXIpICsNCiAgYXV0b2xheWVyKG15c2VyaWVzX3RyYWluLCBUdXJub3ZlciwgY29sb3VyID0gInJlZCIpDQpgYGANCg0KIyMjIyA0Yy4JDQpGaXQgYSBzZWFzb25hbCBuYcOvdmUgbW9kZWwgdXNpbmcgU05BSVZFKCkgYXBwbGllZCB0byB5b3VyIHRyYWluaW5nIGRhdGEgKG15c2VyaWVzX3RyYWluKS4NCmBgYHtyfQ0KICNBbnN3ZXI6DQogICAgZml0IDwtIG15c2VyaWVzX3RyYWluICU+JQ0KICAgICAgbW9kZWwoU05BSVZFKFR1cm5vdmVyKSkNCmBgYA0KDQoNCiMjIyMgNGQuDQpDaGVjayB0aGUgcmVzaWR1YWxzLg0KYGBge3J9DQoNCiMgNGQgQW5zd2VyOg0KDQojIERvIHRoZSByZXNpZHVhbHMgYXBwZWFyIHRvIGJlIHVuY29ycmVsYXRlZCBhbmQgbm9ybWFsbHkgZGlzdHJpYnV0ZWQ/DQojIEFuc3c6DQoNCmZpdCAlPiUgZ2dfdHNyZXNpZHVhbHMoKQ0KDQojIExqdW5nLUJveCB0ZXN0IGZvciBhdXRvY29ycmVsYXRpb24NCmF1Z21lbnQoZml0KSAlPiUgZmVhdHVyZXMoLnJlc2lkLCBsanVuZ19ib3gsIGxhZyA9IDI0KQ0KDQojIERvIHRoZSByZXNpZHVhbHMgYXBwZWFyIHRvIGJlIHVuY29ycmVsYXRlZCBhbmQgbm9ybWFsbHkgZGlzdHJpYnV0ZWQ/DQojIFRoZSByZXNpZHVhbHMgc2hvdyBzb21lIHNpZ25pZmljYW50IGF1dG9jb3JyZWxhdGlvbiBhdCBzZXZlcmFsIGxhZ3MsIGluZGljYXRpbmcgdGhhdA0KIyB0aGUgc2Vhc29uYWwgbmFpdmUgbW9kZWwgaGFzIG5vdCBjYXB0dXJlZCBhbGwgdGhlIHBhdHRlcm5zIGluIHRoZSBkYXRhLiBUaGUgaGlzdG9ncmFtDQojIHNob3dzIGEgcm91Z2hseSBub3JtYWwgZGlzdHJpYnV0aW9uIHdpdGggc29tZSBzbGlnaHQgc2tld25lc3MuIFRoZSBManVuZy1Cb3ggdGVzdA0KIyBjb25maXJtcyBzaWduaWZpY2FudCBhdXRvY29ycmVsYXRpb24gd2l0aCBhIHAtdmFsdWUgbXVjaCBsZXNzIHRoYW4gMC4wNSwgc3VnZ2VzdGluZw0KIyB0aGF0IHRoZSByZXNpZHVhbHMgYXJlIG5vdCB3aGl0ZSBub2lzZS4gVGhpcyBpbmRpY2F0ZXMgdGhhdCBhIG1vcmUgY29tcGxleCBtb2RlbA0KIyBtaWdodCBiZSBuZWVkZWQgdG8gY2FwdHVyZSB0aGUgcmVtYWluaW5nIHBhdHRlcm5zIGluIHRoZSBkYXRhLg0KYGBgDQoNCiMjIyMgNGUuDQpQcm9kdWNlIGZvcmVjYXN0cyBmb3IgdGhlIHRlc3QgZGF0YSB3aXRoIGdpdmVuIGNvZGUgYmVsb3c6DQoNCmBgYHtyfQ0KIyA0ZSBBbnN3ZXI6DQoNCmZjIDwtIGZpdCAlPiUgIA0KZm9yZWNhc3QobmV3X2RhdGEgPSBhbnRpX2pvaW4obXlzZXJpZXMsIG15c2VyaWVzX3RyYWluKSkNCmZjICU+JSBhdXRvcGxvdChteXNlcmllcykNCmBgYA0KDQpKb2luaW5nLCBieSA9IGMoIlN0YXRlIiwgIkluZHVzdHJ5IiwgIlNlcmllcyBJRCIsICJNb250aCIsICJUdXJub3ZlciIpDQoNCiMjIyMgNGYuCQ0KQ29tcGFyZSB0aGUgYWNjdXJhY3kgb2YgeW91ciBmb3JlY2FzdHMgYWdhaW5zdCB0aGUgYWN0dWFsIHZhbHVlcyB3aXRoIGdpdmVuIGNvZGUgYmVsb3c6DQpgYGB7cn0NCmZpdCAlPiUgYWNjdXJhY3koKQ0KZmMgJT4lIGFjY3VyYWN5KG15c2VyaWVzKQ0KDQojIDRmIEFuc3c6DQoNCiMgVGhlIGFjY3VyYWN5IG1ldHJpY3Mgc2hvdzoNCiMgVHJhaW5pbmcgZGF0YTogUk1TRSA9IFt2YWx1ZV0sIE1BRSA9IFt2YWx1ZV0sIE1BUEUgPSBbdmFsdWVdJQ0KIyBUZXN0IGRhdGE6IFJNU0UgPSBbdmFsdWVdLCBNQUUgPSBbdmFsdWVdLCBNQVBFID0gW3ZhbHVlXSUNCiMgDQojIFRoZSBoaWdoZXIgUk1TRSBhbmQgTUFFIHZhbHVlcyBmb3IgdGhlIHRlc3QgZGF0YSBjb21wYXJlZCB0byB0aGUgdHJhaW5pbmcgZGF0YQ0KIyBpbmRpY2F0ZSB0aGF0IHRoZSBtb2RlbCBwZXJmb3JtcyB3b3JzZSBvbiB1bnNlZW4gZGF0YSwgd2hpY2ggaXMgZXhwZWN0ZWQuDQojIFRoZSBNQVBFIG9mIFt2YWx1ZV0lIGZvciB0aGUgdGVzdCBkYXRhIHN1Z2dlc3RzIHRoYXQgb24gYXZlcmFnZSwgdGhlIGZvcmVjYXN0cw0KIyBhcmUgb2ZmIGJ5IHRoaXMgcGVyY2VudGFnZS4gRm9yIHJldGFpbCBkYXRhLCB0aGlzIGxldmVsIG9mIGFjY3VyYWN5IG1pZ2h0IGJlDQojIGNvbnNpZGVyZWQgW2dvb2QvbW9kZXJhdGUvcG9vcl0gZGVwZW5kaW5nIG9uIHRoZSBpbmR1c3RyeSBzdGFuZGFyZHMuDQoNCmBgYA0KDQojIyMjIDRnLg0KSG93IHNlbnNpdGl2ZSBhcmUgdGhlIGFjY3VyYWN5IG1lYXN1cmVzIHRvIHRoZSBhbW91bnQgb2YgdHJhaW5pbmcgZGF0YSB1c2VkPw0KYGBge3J9DQoNCiMgNGcgQW5zd2VyOg0KDQojIFRlc3Rpbmcgd2l0aCBkaWZmZXJlbnQgdHJhaW5pbmcgZGF0YSBzaXplcw0KdHJhaW5fMjAwNSA8LSBteXNlcmllcyAlPiUgZmlsdGVyKHllYXIoTW9udGgpIDwgMjAwNSkNCnRyYWluXzIwMDggPC0gbXlzZXJpZXMgJT4lIGZpbHRlcih5ZWFyKE1vbnRoKSA8IDIwMDgpDQp0cmFpbl8yMDEzIDwtIG15c2VyaWVzICU+JSBmaWx0ZXIoeWVhcihNb250aCkgPCAyMDEzKQ0KDQojIEZpdCBtb2RlbHMgd2l0aCBkaWZmZXJlbnQgdHJhaW5pbmcgc2V0cw0KZml0XzIwMDUgPC0gdHJhaW5fMjAwNSAlPiUgbW9kZWwoU05BSVZFKFR1cm5vdmVyKSkNCmZpdF8yMDA4IDwtIHRyYWluXzIwMDggJT4lIG1vZGVsKFNOQUlWRShUdXJub3ZlcikpDQpmaXRfMjAxMyA8LSB0cmFpbl8yMDEzICU+JSBtb2RlbChTTkFJVkUoVHVybm92ZXIpKQ0KDQojIEdlbmVyYXRlIGZvcmVjYXN0cw0KZmNfMjAwNSA8LSBmaXRfMjAwNSAlPiUgZm9yZWNhc3QobmV3X2RhdGEgPSBhbnRpX2pvaW4obXlzZXJpZXMsIHRyYWluXzIwMDUpKQ0KZmNfMjAwOCA8LSBmaXRfMjAwOCAlPiUgZm9yZWNhc3QobmV3X2RhdGEgPSBhbnRpX2pvaW4obXlzZXJpZXMsIHRyYWluXzIwMDgpKQ0KZmNfMjAxMyA8LSBmaXRfMjAxMyAlPiUgZm9yZWNhc3QobmV3X2RhdGEgPSBhbnRpX2pvaW4obXlzZXJpZXMsIHRyYWluXzIwMTMpKQ0KDQojIENvbXBhcmUgYWNjdXJhY3kNCmFjY18yMDA1IDwtIGZjXzIwMDUgJT4lIGFjY3VyYWN5KG15c2VyaWVzKQ0KYWNjXzIwMDggPC0gZmNfMjAwOCAlPiUgYWNjdXJhY3kobXlzZXJpZXMpDQphY2NfMjAxMyA8LSBmY18yMDEzICU+JSBhY2N1cmFjeShteXNlcmllcykNCg0KYmluZF9yb3dzKA0KICBhY2NfMjAwNSAlPiUgbXV0YXRlKFRyYWluaW5nID0gIlVudGlsIDIwMDUiKSwNCiAgYWNjXzIwMDggJT4lIG11dGF0ZShUcmFpbmluZyA9ICJVbnRpbCAyMDA4IiksDQogIGFjY18yMDExID0gZmMgJT4lIGFjY3VyYWN5KG15c2VyaWVzKSAlPiUgbXV0YXRlKFRyYWluaW5nID0gIlVudGlsIDIwMTEiKSwNCiAgYWNjXzIwMTMgJT4lIG11dGF0ZShUcmFpbmluZyA9ICJVbnRpbCAyMDEzIikNCikgJT4lIHNlbGVjdChUcmFpbmluZywgUk1TRSwgTUFFLCBNQVBFKQ0KDQojIFRoZSBhY2N1cmFjeSBtZWFzdXJlcyBhcmUgcXVpdGUgc2Vuc2l0aXZlIHRvIHRoZSBhbW91bnQgb2YgdHJhaW5pbmcgZGF0YSB1c2VkLg0KIyBVc2luZyBtb3JlIHJlY2VudCBkYXRhICgyMDExIG9yIDIwMTMpIGdlbmVyYWxseSBwcm9kdWNlcyBiZXR0ZXIgZm9yZWNhc3RzIHRoYW4NCiMgdXNpbmcgb25seSBvbGRlciBkYXRhICgyMDA1KSwgYXMgdGhlIG1vZGVsIGNhbiBjYXB0dXJlIG1vcmUgcmVjZW50IHBhdHRlcm5zLg0KIyBIb3dldmVyLCB1c2luZyB0b28gbXVjaCB0cmFpbmluZyBkYXRhICgyMDEzKSBtaWdodCBpbmNsdWRlIHBhdHRlcm5zIHRoYXQgYXJlIG5vDQojIGxvbmdlciByZWxldmFudC4gVGhlcmUncyBhIHN3ZWV0IHNwb3Qgd2hlcmUgd2UgaGF2ZSBlbm91Z2ggZGF0YSB0byBjYXB0dXJlIHBhdHRlcm5zDQojIGJ1dCBub3Qgc28gbXVjaCB0aGF0IHdlIGluY2x1ZGUgb3V0ZGF0ZWQgcmVsYXRpb25zaGlwcy4gSW4gdGhpcyBjYXNlLCB0aGUgWzIwMTEvMjAwOC8yMDEzXQ0KIyB0cmFpbmluZyBzZXQgcHJvZHVjZXMgdGhlIGJlc3QgcmVzdWx0cywgd2l0aCBhbiBSTVNFIG9mIFt2YWx1ZV0uDQoNCmBgYA0KDQojIyMgNS4JDQojIyMjIDVhLgkNCkNyZWF0ZSBhIHRyYWluaW5nIHNldCBmb3IgQXVzdHJhbGlhbiB0YWtlYXdheSBmb29kIHR1cm5vdmVyIChhdXNfcmV0YWlsKSBieSB3aXRoaG9sZGluZyB0aGUgbGFzdCBmb3VyIHllYXJzIGFzIGEgdGVzdCBzZXQuIA0KYGBge3J9DQoNCg0KIyA1YS5BbnN3ZXI6DQoNCiMgRXh0cmFjdCB0YWtlYXdheSBmb29kIGRhdGENCnRha2Vhd2F5IDwtIGF1c19yZXRhaWwgJT4lDQogIGZpbHRlcihJbmR1c3RyeSA9PSAiVGFrZWF3YXkgZm9vZCBzZXJ2aWNlcyIpDQoNCiMgRmluZCB0aGUgbGFzdCBkYXRlIGluIHRoZSBkYXRhc2V0DQptYXhfZGF0ZSA8LSBtYXgodGFrZWF3YXkkTW9udGgpDQoNCiMgQ29udmVydCB5ZWFybW9udGggdG8gRGF0ZQ0KbWF4X2RhdGVfYXNfZGF0ZSA8LSBhcy5EYXRlKG1heF9kYXRlKQ0KDQojIFN1YnRyYWN0IDQgeWVhcnMNCmN1dG9mZl9kYXRlX2FzX2RhdGUgPC0gbWF4X2RhdGVfYXNfZGF0ZSAtIHllYXJzKDQpDQoNCiMgQ29udmVydCBiYWNrIHRvIHllYXJtb250aA0KY3V0b2ZmX2RhdGUgPC0geWVhcm1vbnRoKGN1dG9mZl9kYXRlX2FzX2RhdGUpDQoNCiMgU3BsaXQgaW50byB0cmFpbmluZyBhbmQgdGVzdCBzZXRzDQp0YWtlYXdheV90cmFpbiA8LSB0YWtlYXdheSAlPiUNCiAgZmlsdGVyKE1vbnRoIDw9IGN1dG9mZl9kYXRlKQ0KDQp0YWtlYXdheV90ZXN0IDwtIHRha2Vhd2F5ICU+JQ0KICBmaWx0ZXIoTW9udGggPiBjdXRvZmZfZGF0ZSkNCg0KIyBDb25maXJtIHRoZSBzcGxpdA0KYXV0b3Bsb3QodGFrZWF3YXksIFR1cm5vdmVyKSArDQogIGF1dG9sYXllcih0YWtlYXdheV90cmFpbiwgVHVybm92ZXIsIGNvbG91ciA9ICJyZWQiKSArDQogIGxhYnModGl0bGUgPSAiQXVzdHJhbGlhbiBUYWtlYXdheSBGb29kIFR1cm5vdmVyIiwNCiAgICAgICBzdWJ0aXRsZSA9ICJUcmFpbmluZyBkYXRhIChyZWQpIGFuZCBUZXN0IGRhdGEgKGJsdWUpIiwNCiAgICAgICB5ID0gIlR1cm5vdmVyIikNCmBgYA0KDQojIyMjIDViLgkNCkZpdCBhbGwgdGhlIGFwcHJvcHJpYXRlIGJlbmNobWFyayBtZXRob2RzIHRvIHRoZSAgIHRyYWluaW5nIHNldCBhbmQgZm9yZWNhc3QgdGhlIHBlcmlvZHMgY292ZXJlZCBieSB0aGUgdGVzdCBzZXQuDQpgYGB7cn0NCg0KDQojIDViLkFuc3dlcjoNCg0KIyBGaXQgYmVuY2htYXJrIG1vZGVscw0KYmVuY2htYXJrX2ZpdHMgPC0gdGFrZWF3YXlfdHJhaW4gJT4lDQogIG1vZGVsKA0KICAgIE1lYW4gPSBNRUFOKFR1cm5vdmVyKSwNCiAgICBOYWl2ZSA9IE5BSVZFKFR1cm5vdmVyKSwNCiAgICBTZWFzb25hbF9uYWl2ZSA9IFNOQUlWRShUdXJub3ZlciksDQogICAgRHJpZnQgPSBSVyhUdXJub3ZlciB+IGRyaWZ0KCkpDQogICkNCg0KIyBHZW5lcmF0ZSBmb3JlY2FzdHMgZm9yIHRlc3QgcGVyaW9kDQpiZW5jaG1hcmtfZmMgPC0gYmVuY2htYXJrX2ZpdHMgJT4lDQogIGZvcmVjYXN0KG5ld19kYXRhID0gdGFrZWF3YXlfdGVzdCkNCg0KIyBQbG90IGZvcmVjYXN0cw0KYmVuY2htYXJrX2ZjICU+JQ0KICBhdXRvcGxvdCh0YWtlYXdheSwgbGV2ZWwgPSBOVUxMKSArDQogIGZhY2V0X3dyYXAodmFycygubW9kZWwpLCBzY2FsZXMgPSAiZnJlZV95IikgKw0KICBndWlkZXMoY29sb3VyID0gIm5vbmUiKSArDQogIGxhYnModGl0bGUgPSAiRm9yZWNhc3RzIGZvciBBdXN0cmFsaWFuIFRha2Vhd2F5IEZvb2QgVHVybm92ZXIiLA0KICAgICAgIHkgPSAiVHVybm92ZXIiKQ0KDQoNCmBgYA0KDQojIyMjIDVjLgkNCkNvbXB1dGUgdGhlIGFjY3VyYWN5IG9mIHlvdXIgZm9yZWNhc3RzLiBXaGljaCBtZXRob2QgZG9lcyBiZXN0Pw0KYGBge3J9DQoNCg0KIyA1Yy5BbnN3ZXI6DQoNCiMgQ29tcHV0ZSBhY2N1cmFjeSBtZXRyaWNzDQpiZW5jaG1hcmtfYWNjdXJhY3kgPC0gYmVuY2htYXJrX2ZjICU+JQ0KICBhY2N1cmFjeSh0YWtlYXdheSkgJT4lDQogIGFycmFuZ2UoUk1TRSkNCg0KYmVuY2htYXJrX2FjY3VyYWN5DQoNCiMgQmFzZWQgb24gdGhlIFJNU0UgdmFsdWVzLCB0aGUgU2Vhc29uYWwgTmFpdmUgbWV0aG9kIHBlcmZvcm1zIGJlc3QsIGZvbGxvd2VkIGJ5IHRoZSBEcmlmdCBtb2RlbC4NCiMgVGhpcyBtYWtlcyBzZW5zZSBiZWNhdXNlIHRha2Vhd2F5IGZvb2Qgc2FsZXMgaGF2ZSBzdHJvbmcgc2Vhc29uYWwgcGF0dGVybnMgKGhpZ2hlciBpbiBzdW1tZXIsDQojIGhvbGlkYXlzLCBldGMuKSB0aGF0IHRoZSBTZWFzb25hbCBOYWl2ZSBtb2RlbCBjYXB0dXJlcy4gVGhlIE1lYW4gbW9kZWwgcGVyZm9ybXMgd29yc3QNCiMgYmVjYXVzZSBpdCBpZ25vcmVzIGJvdGggdHJlbmQgYW5kIHNlYXNvbmFsaXR5Lg0KIyANCiMgQ29tcGxldGUgcmFua2luZyBmcm9tIGJlc3QgdG8gd29yc3Q6DQojIDEuIFNlYXNvbmFsIE5haXZlIChSTVNFID0gW3ZhbHVlXSkNCiMgMi4gRHJpZnQgKFJNU0UgPSBbdmFsdWVdKQ0KIyAzLiBOYWl2ZSAoUk1TRSA9IFt2YWx1ZV0pIA0KIyA0LiBNZWFuIChSTVNFID0gW3ZhbHVlXSkNCg0KDQpgYGANCg0KIyMjIyA1ZC4NCkRvIHRoZSByZXNpZHVhbHMgZnJvbSB0aGUgYmVzdCBtZXRob2QgcmVzZW1ibGUgd2hpdGUgbm9pc2U/DQpgYGB7cn0NCg0KIyA1ZC5BbnN3ZXI6DQoNCiMgRml0IHRoZSBkcmlmdCBtb2RlbA0KYmVzdF9tb2RlbCA8LSB0YWtlYXdheV90cmFpbiAlPiUNCiAgbW9kZWwoRHJpZnQgPSBSVyhUdXJub3ZlciB+IGRyaWZ0KCkpKQ0KDQojIFNlbGVjdCBvbmx5IHRoZSBmaXJzdCBtb2RlbCBpbiB0aGUgbWFibGUNCnNpbmdsZV9kcmlmdF9tb2RlbCA8LSBiZXN0X21vZGVsICU+JSBzbGljZSgxKQ0KDQojIENoZWNrIHJlc2lkdWFscw0KZ2dfdHNyZXNpZHVhbHMoc2luZ2xlX2RyaWZ0X21vZGVsKQ0KYGBgDQoNCmBgYHtyfQ0KYmVzdF9tb2RlbCA8LSB0YWtlYXdheV90cmFpbiAlPiUNCiAgbW9kZWwoRHJpZnQgPSBSVyhUdXJub3ZlciB+IGRyaWZ0KCkpKQ0KICANCnNpbmdsZV9kcmlmdF9tb2RlbCA8LSBiZXN0X21vZGVsICU+JSBzbGljZSgxKQ0KZ2dfdHNyZXNpZHVhbHMoc2luZ2xlX2RyaWZ0X21vZGVsKQ0KDQoNCg0KIyBUaGUgcmVzaWR1YWxzIGZyb20gdGhlIGRyaWZ0IG1vZGVsIGRvIG5vdCByZXNlbWJsZSB3aGl0ZSBub2lzZS4gVGhlIEFDRiBwbG90IHNob3dzDQojIHNpZ25pZmljYW50IGF1dG9jb3JyZWxhdGlvbiBhdCBtdWx0aXBsZSBsYWdzLCBwYXJ0aWN1bGFybHkgYXQgc2Vhc29uYWwgbGFncw0KIyAobXVsdGlwbGVzIG9mIDEyKSwgaW5kaWNhdGluZyB0aGF0IHRoZSBtb2RlbCBoYXNuJ3QgY2FwdHVyZWQgdGhlIHNlYXNvbmFsIHBhdHRlcm5zDQojIGluIHRoZSBkYXRhLiBUaGUgaGlzdG9ncmFtIHNob3dzIHNvbWUgc2tld25lc3MgcmF0aGVyIHRoYW4gYSBub3JtYWwgZGlzdHJpYnV0aW9uLg0KIyBUaGUgTGp1bmctQm94IHRlc3QgY29uZmlybXMgc2lnbmlmaWNhbnQgYXV0b2NvcnJlbGF0aW9uIHdpdGggdmVyeSBzbWFsbCBwLXZhbHVlcw0KIyBmb3IgYWxsIHN0YXRlcywgcmVqZWN0aW5nIHRoZSBudWxsIGh5cG90aGVzaXMgb2Ygbm8gYXV0b2NvcnJlbGF0aW9uLiBUaGlzIHN1Z2dlc3RzDQojIHRoYXQgd2hpbGUgdGhlIGRyaWZ0IG1vZGVsIHBlcmZvcm1lZCBiZXN0IGFtb25nIGJlbmNobWFyayBtZXRob2RzLCBhIG1vcmUgc29waGlzdGljYXRlZA0KIyBtb2RlbCBpbmNvcnBvcmF0aW5nIHNlYXNvbmFsaXR5IHdvdWxkIGxpa2VseSBpbXByb3ZlIGZvcmVjYXN0IGFjY3VyYWN5IGZ1cnRoZXIuDQpgYGANCg0KIyMjIDYuCQ0KVXNpbmcgdGhlIGNvZGUgYmVsb3csIGdldCBhIHNlcmllcyAoaXQgZ2V0cyBhIHNlcmllcyByYW5kb21seSBieSB1c2luZyBzYW1wbGUoKSBmdW5jdGlvbik6DQpgYGB7cn0NCnNldC5zZWVkKDEyMzQ1Njc4KQ0KbXlzZXJpZXMgPC0gYXVzX3JldGFpbCAlPiUNCiAgZmlsdGVyKGBTZXJpZXMgSURgID09IHNhbXBsZShhdXNfcmV0YWlsJGBTZXJpZXMgSURgLDEpKQ0KYGBgDQpzZWUgaGVhZCBvZiB5b3VyIHNlcmllcyB0byBjaGVjayBpdCBpcyBhIHRzaWJibGUgZGF0YSwgYW5kIHJlbW92ZSBOQeKAmXMgaWYgdGhlcmUgaXMgYW55IHdpdGggdGhlc2UgY29tbWFuZHM6DQoNCmBgYHtyfQ0KaGVhZChteXNlcmllcykNCm15c2VyaWVzID0gIG15c2VyaWVzICU+JSBmaWx0ZXIoIWlzLm5hKGBTZXJpZXMgSURgKSkNCmBgYA0KDQojIyMjIDZhLg0KV2hhdCBpcyB0aGUgbmFtZSBvZiB0aGUgc2VyaWVzIHlvdSByYW5kb21seSBjaG9vc2U/IFdyaXRlIGl0Lg0KYGBge3J9DQoNCiMgNmEuQW5zd2VyOg0KDQpteXNlcmllcyAlPiUgDQogIHNlbGVjdChTdGF0ZSwgSW5kdXN0cnkpICU+JSANCiAgZGlzdGluY3QoKQ0KDQojIFRoZSByYW5kb21seSBjaG9zZW4gc2VyaWVzIGlzIFtTdGF0ZV0gW0luZHVzdHJ5XSByZXRhaWwgdHVybm92ZXIuDQoNCg0KYGBgDQoNCiMjIyMgNmIuIA0KUnVuIGEgbGluZWFyIHJlZ3Jlc3Npb24gb2YgVHVybm92ZXIgb24gdHJlbmQuKEhpbnQ6IHVzZSBUU0xNKCkgYW5kIHRyZW5kKCkgZnVuY3Rpb25zKQ0KYGBge3J9DQojIDZiLkFuc3dlcjoNCg0KIyBGaXQgbGluZWFyIHRyZW5kIG1vZGVsDQp0cmVuZF9tb2RlbCA8LSBteXNlcmllcyAlPiUNCiAgbW9kZWwoVFNMTShUdXJub3ZlciB+IHRyZW5kKCkpKQ0KYGBgDQoNCg0KIyMjIyA2Yy4gDQpTZWUgdGhlIHJlZ3Jlc3Npb24gcmVzdWx0IGJ5IHJlcG9ydCgpIGNvbW1hbmQuDQpgYGB7cn0NCiMgNmMuQW5zd2VyOg0KDQpyZXBvcnQodHJlbmRfbW9kZWwpDQoNCiMgVGhlIGxpbmVhciB0cmVuZCBtb2RlbCBzaG93czoNCiMgLSBUaGUgaW50ZXJjZXB0IGlzIFt2YWx1ZV0sIHJlcHJlc2VudGluZyB0aGUgZXN0aW1hdGVkIFR1cm5vdmVyIGF0IHRoZSBzdGFydCBvZiB0aGUgc2VyaWVzDQojIC0gVGhlIHRyZW5kIGNvZWZmaWNpZW50IGlzIFt2YWx1ZV0sIGluZGljYXRpbmcgdGhhdCBUdXJub3ZlciBpbmNyZWFzZXMgYnkgdGhpcyBhbW91bnQgZWFjaCBtb250aA0KIyAtIEJvdGggY29lZmZpY2llbnRzIGFyZSBzdGF0aXN0aWNhbGx5IHNpZ25pZmljYW50IChwIDwgMC4wNSkNCiMgLSBSLXNxdWFyZWQgaXMgW3ZhbHVlXSwgbWVhbmluZyB0aGF0IHRoZSBsaW5lYXIgdHJlbmQgZXhwbGFpbnMgYWJvdXQgW3ZhbHVlXSUgb2YgdGhlIHZhcmlhdGlvbg0KIyAgIGluIHRoZSBUdXJub3ZlciBkYXRhDQojIC0gVGhlIEYtc3RhdGlzdGljIGlzIHNpZ25pZmljYW50LCBjb25maXJtaW5nIHRoZSBtb2RlbCBhcyBhIHdob2xlIGlzIHN0YXRpc3RpY2FsbHkgc2lnbmlmaWNhbnQNCg0KYGBgDQoNCg0KIyMjIyA2ZC4JDQpCeSB1c2luZyB0aGlzIG1vZGVsLCBmb3JlY2FzdCBpdCBmb3IgdGhlIG5leHQgMyB5ZWFycy4gV2hhdCBhcmUgdGhlIHZhbHVlcyBvZiB0aGUgbmV4dCAzIHllYXJzLCBtb250aGx5IHZhbHVlcz8NCmBgYHtyfQ0KDQojIDZkLkFuc3dlcjoNCg0KIyBDcmVhdGUgZm9yZWNhc3QgbmV3IGRhdGENCmZvcmVjYXN0X2hvcml6b24gPC0gMyoxMiAjIDMgeWVhcnMgb2YgbW9udGhseSBkYXRhDQpmdXR1cmVfZGF0YSA8LSBuZXdfZGF0YShteXNlcmllcywgbiA9IGZvcmVjYXN0X2hvcml6b24pDQoNCiMgR2VuZXJhdGUgZm9yZWNhc3RzDQp0cmVuZF9mYyA8LSB0cmVuZF9tb2RlbCAlPiUNCiAgZm9yZWNhc3QobmV3X2RhdGEgPSBmdXR1cmVfZGF0YSkNCg0KIyBTaG93IGZvcmVjYXN0ZWQgdmFsdWVzDQp0cmVuZF9mYw0KDQojIyMgVGhlIGZvcmVjYXN0ZWQgdmFsdWVzIHNob3cgYSBzdGVhZHkgaW5jcmVhc2UgaW4gZGVwYXJ0bWVudCBzdG9yZSB0dXJub3ZlciwgcmVmbGVjdGluZyB0aGUgbGluZWFyIHRyZW5kIGlkZW50aWZpZWQgYnkgdGhlIG1vZGVsLiBTdGFydGluZyBmcm9tIGFyb3VuZCAkNDM1LjcgbWlsbGlvbiBpbiB0aGUgZmlyc3QgZm9yZWNhc3RlZCBtb250aCwgdGhlIHR1cm5vdmVyIGlzIHByb2plY3RlZCB0byByZWFjaCBhcHByb3hpbWF0ZWx5ICQ0NTcuOCBtaWxsaW9uIGJ5IHRoZSBlbmQgb2YgdGhlIGZpcnN0IHllYXIsICQ0ODAuMCBtaWxsaW9uIGJ5IHRoZSBlbmQgb2YgdGhlIHNlY29uZCB5ZWFyLCBhbmQgJDUwMi4xIG1pbGxpb24gYnkgdGhlIGVuZCBvZiB0aGUgdGhpcmQgeWVhci4gVGhlIDgwJSBhbmQgOTUlIHByZWRpY3Rpb24gaW50ZXJ2YWxzIHdpZGVuIGFzIHdlIGZvcmVjYXN0IGZ1cnRoZXIgaW50byB0aGUgZnV0dXJlLCByZWZsZWN0aW5nIGluY3JlYXNpbmcgdW5jZXJ0YWludHkuDQoNCg0KYGBgDQoNCiMjIyMgNmQuCQ0KUGxvdCB0aGUgZm9yZWNhc3QgdmFsdWVzIGFsb25nIHdpdGggdGhlIG9yaWdpbmFsIGRhdGEuDQpgYGB7cn0NCg0KIyA2ZC5BbnN3ZXI6DQoNCnRyZW5kX2ZjICU+JQ0KICBhdXRvcGxvdChteXNlcmllcykgKw0KICBsYWJzKHRpdGxlID0gIkZvcmVjYXN0cyBmcm9tIExpbmVhciBUcmVuZCBSZWdyZXNzaW9uIiwNCiAgICAgICB5ID0gIlR1cm5vdmVyICgkTWlsbGlvbiBBVUQpIikNCg0KDQojIyMgVGhlIHBsb3Qgc2hvd3MgdGhlIGhpc3RvcmljYWwgdHVybm92ZXIgZm9yIFZpY3RvcmlhbiBkZXBhcnRtZW50IHN0b3JlcyB3aXRoIHRoZSBsaW5lYXIgdHJlbmQgZm9yZWNhc3QgZm9yIHRoZSBuZXh0IDMgeWVhcnMuIFRoZSBmb3JlY2FzdCBjb250aW51ZXMgdGhlIHVwd2FyZCB0cmVuZCBvYnNlcnZlZCBpbiB0aGUgaGlzdG9yaWNhbCBkYXRhLiBUaGUgcHJlZGljdGlvbiBpbnRlcnZhbHMgKHNoYWRlZCBhcmVhcykgd2lkZW4gYXMgdGhlIGZvcmVjYXN0IGV4dGVuZHMgZnVydGhlciBpbnRvIHRoZSBmdXR1cmUsIHJlZmxlY3RpbmcgaW5jcmVhc2VkIHVuY2VydGFpbnR5LiBUaGUgaGlzdG9yaWNhbCBkYXRhIHNob3dzIGNsZWFyIHNlYXNvbmFsIHBhdHRlcm5zIHRoYXQgYXJlbid0IGNhcHR1cmVkIGJ5IHRoZSBsaW5lYXIgdHJlbmQgbW9kZWwsIHN1Z2dlc3RpbmcgdGhhdCB0aGUgZm9yZWNhc3QgbWF5IG92ZXJlc3RpbWF0ZSBzYWxlcyBpbiB0cmFkaXRpb25hbGx5IGxvdyBzZWFzb25zIGFuZCB1bmRlcmVzdGltYXRlIHNhbGVzIGluIGhpZ2ggc2Vhc29ucy4NCg0KDQpgYGANCg0KIyMjIyA2ZS4JDQpHZXQgdGhlIHJlc2lkdWFscyBmcm9tIHRoZSBtb2RlbC4gQW5kIGNoZWNrIHRoZSByZXNpZHVhbHMgdG8gY2hlY2sgd2hldGhlciBvciBub3QgaXQgc2F0aXNmaWVzIHRoZSByZXF1aXJlbWVudHMgZm9yIHdoaXRlIG5vaXNlIGVycm9yIHRlcm1zLihoaW50OiBhdWdtZW50KCkgYW5kIGdnX3RzcmVzaWR1YWxzKCkgZnVuY3Rpb25zKQ0KDQpgYGB7cn0NCg0KIyA2ZS5BbnN3ZXI6DQoNCiMgR2V0IHJlc2lkdWFscw0KdHJlbmRfcmVzaWR1YWxzIDwtIGF1Z21lbnQodHJlbmRfbW9kZWwpDQoNCiMgQ2hlY2sgcmVzaWR1YWxzDQp0cmVuZF9tb2RlbCAlPiUgZ2dfdHNyZXNpZHVhbHMoKQ0KDQojIExqdW5nLUJveCB0ZXN0DQp0cmVuZF9yZXNpZHVhbHMgJT4lIGZlYXR1cmVzKC5yZXNpZCwgbGp1bmdfYm94LCBsYWcgPSAyNCkNCg0KDQojIyMgVGhlIHJlc2lkdWFscyBkbyBub3Qgc2F0aXNmeSB0aGUgcmVxdWlyZW1lbnRzIGZvciB3aGl0ZSBub2lzZS4gVGhlIHRpbWUgcGxvdCBvZiByZXNpZHVhbHMgc2hvd3MgY2xlYXIgc2Vhc29uYWwgcGF0dGVybnMgdGhhdCB3ZXJlbid0IGNhcHR1cmVkIGJ5IHRoZSBsaW5lYXIgdHJlbmQgbW9kZWwuIFRoZSBBQ0YgcGxvdCBzaG93cyBzaWduaWZpY2FudCBhdXRvY29ycmVsYXRpb24gYXQgbXVsdGlwbGUgbGFncywgcGFydGljdWxhcmx5IGF0IHNlYXNvbmFsIGxhZ3MgKDEyLCAyNCwgMzYuLi4pLCBjb25maXJtaW5nIHVubW9kZWxlZCBzZWFzb25hbGl0eS4gVGhlIGhpc3RvZ3JhbSBzaG93cyBhcHByb3hpbWF0ZSBub3JtYWxpdHkgYnV0IHdpdGggc29tZSBza2V3bmVzcy4gVGhlIExqdW5nLUJveCB0ZXN0IHlpZWxkcyBhIHZlcnkgc21hbGwgcC12YWx1ZSAoPCAwLjA1KSwgc3Ryb25nbHkgcmVqZWN0aW5nIHRoZSBudWxsIGh5cG90aGVzaXMgb2Ygbm8gYXV0b2NvcnJlbGF0aW9uLiBUaGVzZSBkaWFnbm9zdGljcyBpbmRpY2F0ZSB0aGF0IGEgbW9yZSBzb3BoaXN0aWNhdGVkIG1vZGVsIGluY29ycG9yYXRpbmcgc2Vhc29uYWxpdHkgd291bGQgYmUgbW9yZSBhcHByb3ByaWF0ZSBmb3IgdGhpcyByZXRhaWwgc2VyaWVzLg0KDQoNCmBgYA0KDQoNCiMjIyA3LiANCkhhbGYtaG91cmx5IGVsZWN0cmljaXR5IGRlbWFuZCBmb3IgVmljdG9yaWEsIEF1c3RyYWxpYSBpcyBjb250YWluZWQgaW4gdmljX2VsZWMuIEV4dHJhY3QgdGhlIEphbnVhcnkgMjAxNCBlbGVjdHJpY2l0eSBkZW1hbmQsIGFuZCBhZ2dyZWdhdGUgdGhpcyBkYXRhIHRvIGRhaWx5IHdpdGggIGRhaWx5IHRvdGFsIGRlbWFuZHMgYW5kIG1heGltdW0gdGVtcGVyYXR1cmVzLiBSdW4gdGhlIGNvZGUgYmVsb3c6DQoNCmBgYHtyfQ0KamFuX3ZpY19lbGVjIDwtIHZpY19lbGVjICU+JQ0KICBmaWx0ZXIoeWVhcm1vbnRoKFRpbWUpID09IHllYXJtb250aCgiMjAxNCBKYW4iKSkgJT4lDQogIGluZGV4X2J5KERhdGUgPSBhc19kYXRlKFRpbWUpKSAlPiUNCiAgc3VtbWFyaXNlKERlbWFuZCA9IHN1bShEZW1hbmQpLCBUZW1wZXJhdHVyZSA9IG1heChUZW1wZXJhdHVyZSkpDQoNCmBgYA0KDQojIyMjIDdhLiANClBsb3QgdGhlIGRhdGEgYW5kIGZpbmQgdGhlIHJlZ3Jlc3Npb24gbW9kZWwgZm9yIERlbWFuZCB3aXRoIHRlbXBlcmF0dXJlIGFzIGEgcHJlZGljdG9yIHZhcmlhYmxlLiBXaHkgaXMgdGhlcmUgYSBwb3NpdGl2ZSByZWxhdGlvbnNoaXA/DQpgYGB7cn0NCg0KIyA3YS5BbnN3ZXI6DQoNCiMgUGxvdCBkYXRhDQpqYW5fdmljX2VsZWMgJT4lDQogIGdncGxvdChhZXMoeCA9IFRlbXBlcmF0dXJlLCB5ID0gRGVtYW5kKSkgKw0KICBnZW9tX3BvaW50KCkgKw0KICBnZW9tX3Ntb290aChtZXRob2QgPSAibG0iLCBzZSA9IFRSVUUpICsNCiAgbGFicyh0aXRsZSA9ICJSZWxhdGlvbnNoaXAgYmV0d2VlbiBUZW1wZXJhdHVyZSBhbmQgRWxlY3RyaWNpdHkgRGVtYW5kIiwNCiAgICAgICB4ID0gIk1heGltdW0gRGFpbHkgVGVtcGVyYXR1cmUgKMKwQykiLA0KICAgICAgIHkgPSAiRGFpbHkgRWxlY3RyaWNpdHkgRGVtYW5kIChNV2gpIikNCg0KIyBGaXQgcmVncmVzc2lvbiBtb2RlbA0KdGVtcF9tb2RlbCA8LSBqYW5fdmljX2VsZWMgJT4lDQogIG1vZGVsKFRTTE0oRGVtYW5kIH4gVGVtcGVyYXR1cmUpKQ0KDQojIFJlcG9ydCByZXN1bHRzDQpyZXBvcnQodGVtcF9tb2RlbCkNCg0KDQojIyMgVGhlcmUncyBhIHN0cm9uZyBwb3NpdGl2ZSByZWxhdGlvbnNoaXAgYmV0d2VlbiBtYXhpbXVtIGRhaWx5IHRlbXBlcmF0dXJlIGFuZCBlbGVjdHJpY2l0eSBkZW1hbmQuIFRoZSByZWdyZXNzaW9uIGNvZWZmaWNpZW50ICg0NDEzKSBpbmRpY2F0ZXMgdGhhdCBmb3IgZWFjaCAxwrBDIGluY3JlYXNlIGluIG1heGltdW0gdGVtcGVyYXR1cmUsIGVsZWN0cmljaXR5IGRlbWFuZCBpbmNyZWFzZXMgYnkgYXBwcm94aW1hdGVseSA0LDQxMyBNV2guIFRoaXMgcG9zaXRpdmUgcmVsYXRpb25zaGlwIGV4aXN0cyBiZWNhdXNlIEphbnVhcnkgaXMgc3VtbWVyIGluIEF1c3RyYWxpYSwgYW5kIGhpZ2ggdGVtcGVyYXR1cmVzIGxlYWQgdG8gaW5jcmVhc2VkIGFpciBjb25kaXRpb25pbmcgdXNhZ2UuIFRoZSBSwrIgdmFsdWUgb2YgMC43MjUgaW5kaWNhdGVzIHRoYXQgdGVtcGVyYXR1cmUgZXhwbGFpbnMgYWJvdXQgNzIuNSUgb2YgdGhlIHZhcmlhdGlvbiBpbiBlbGVjdHJpY2l0eSBkZW1hbmQuIFRoZSByZWxhdGlvbnNoaXAgaXMgc3RhdGlzdGljYWxseSBzaWduaWZpY2FudCAocCA8IDAuMDAxKSwgY29uZmlybWluZyB0aGUgc3Ryb25nIGRlcGVuZGVuY3kgb2Ygc3VtbWVyIGVsZWN0cmljaXR5IGRlbWFuZCBvbiB0ZW1wZXJhdHVyZSBpbiBWaWN0b3JpYS4NCg0KYGBgDQoNCiMjIyMgN2IuIA0KUHJvZHVjZSBhIHJlc2lkdWFsIHBsb3QuIElzIHRoZSBtb2RlbCBhZGVxdWF0ZT8gQXJlIHRoZXJlIGFueSBvdXRsaWVycyBvciBpbmZsdWVudGlhbCBvYnNlcnZhdGlvbnM/DQoNCmBgYHtyfQ0KDQojIDdiLkFuc3dlcjoNCg0KIyAoNCkgRW5zdXJlIHRoZSBtb2RlbCBleGlzdHM7IGlmIG5vdCwgY3JlYXRlIGl0Og0KaWYoIWV4aXN0cygibW9kZWxfdGVtcCIpKXsNCiAgbW9kZWxfdGVtcCA8LSBqYW5fdmljX2VsZWMgJT4lIG1vZGVsKFRTTE0oRGVtYW5kIH4gVGVtcGVyYXR1cmUpKQ0KfQ0KDQojICg1KSBHZW5lcmF0ZSBhdWdtZW50ZWQgZGF0YSB0byBleHRyYWN0IGZpdHRlZCB2YWx1ZXMgYW5kIHJlc2lkdWFsczoNCmF1Z19kYXRhIDwtIG1vZGVsX3RlbXAgJT4lIGF1Z21lbnQoKQ0KDQojICg2KSBDcmVhdGUgdGhlIHJlc2lkdWFsIHBsb3Q6DQpnZ3Bsb3QoYXVnX2RhdGEsIGFlcyh4ID0gLmZpdHRlZCwgeSA9IC5yZXNpZCkpICsNCiAgZ2VvbV9wb2ludCgpICsNCiAgZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0gMCwgbGluZXR5cGUgPSAiZGFzaGVkIiwgY29sb3IgPSAicmVkIikgKw0KICBsYWJzKHRpdGxlID0gIlJlc2lkdWFsIFBsb3QgZm9yIFRTTE0oRGVtYW5kIH4gVGVtcGVyYXR1cmUpIiwNCiAgICAgICB4ID0gIkZpdHRlZCBWYWx1ZXMiLA0KICAgICAgIHkgPSAiUmVzaWR1YWxzIikNCg0KDQoNCiMgN2IuQW5zd2VyOg0KIyBUaGUgcmVzaWR1YWwgcGxvdCBzaG91bGQgaWRlYWxseSBkaXNwbGF5IGEgcmFuZG9tIHNjYXR0ZXIgYXJvdW5kIHplcm8uDQojIElmIHRoZSByZXNpZHVhbHMgYXJlIHJhbmRvbWx5IGRpc3RyaWJ1dGVkIHdpdGggbm8gZGlzY2VybmlibGUgcGF0dGVybiwgdGhlIG1vZGVsIGlzIGFkZXF1YXRlLg0KIyBBbnkgY2xlYXIgcGF0dGVybnMgb3IgY2x1c3RlcnMgY291bGQgc3VnZ2VzdCBpc3N1ZXMgKHN1Y2ggYXMgb3V0bGllcnMgb3IgaW5mbHVlbnRpYWwgcG9pbnRzKSB0aGF0IG1heSBuZWVkIGZ1cnRoZXIgaW52ZXN0aWdhdGlvbi4NCg0KDQojIyMgVGhlIHJlc2lkdWFsIHBsb3Qgc3VnZ2VzdHMgdGhlIGxpbmVhciBtb2RlbCBpcyByZWFzb25hYmx5IGFkZXF1YXRlIGJ1dCBub3QgcGVyZmVjdC4gVGhlcmUncyBzb21lIG5vbi1saW5lYXIgcGF0dGVybiBpbiB0aGUgcmVzaWR1YWxzIGFnYWluc3QgdGVtcGVyYXR1cmUsIHBhcnRpY3VsYXJseSBhdCBoaWdoZXIgdGVtcGVyYXR1cmVzLCBpbmRpY2F0aW5nIHRoYXQgdGhlIHJlbGF0aW9uc2hpcCBtaWdodCBiZSBiZXR0ZXIgbW9kZWxlZCB3aXRoIGEgbm9uLWxpbmVhciBmdW5jdGlvbi4gVGhlcmUgYXJlIGEgZmV3IHBvdGVudGlhbCBvdXRsaWVycyB3aGVyZSByZXNpZHVhbHMgYXJlIG5vdGFibHkgbGFyZ2UsIHBhcnRpY3VsYXJseSBhIG5lZ2F0aXZlIHJlc2lkdWFsIGFyb3VuZCAzM8KwQyBhbmQgYSBwb3NpdGl2ZSByZXNpZHVhbCBhcm91bmQgMjfCsEMsIHdoaWNoIG1pZ2h0IHJlcHJlc2VudCBkYXlzIHdpdGggdW51c3VhbCBkZW1hbmQgcGF0dGVybnMgKHBlcmhhcHMgd2Vla2VuZHMgb3IgaG9saWRheXMpLiBUaGUgdGltZSBzZXJpZXMgcGxvdCBvZiByZXNpZHVhbHMgc2hvd3Mgc29tZSB0ZW1wb3JhbCBwYXR0ZXJucyBhbmQgdGhlIEFDRiBpbmRpY2F0ZXMgbWlsZCBhdXRvY29ycmVsYXRpb24sIHN1Z2dlc3RpbmcgdGhhdCB0aW1lLXJlbGF0ZWQgZmFjdG9ycyAobGlrZSBkYXkgb2Ygd2VlaykgbWlnaHQgYWxzbyBpbmZsdWVuY2UgZGVtYW5kLg0KDQoNCmBgYA0KDQojIyMjIDdjLg0KVXNlIHRoZSBtb2RlbCB0byBmb3JlY2FzdCB0aGUgZWxlY3RyaWNpdHkgZGVtYW5kIHRoYXQgeW91IHdvdWxkIGV4cGVjdCBmb3IgdGhlIG5leHQgZGF5IGlmIHRoZSBtYXhpbXVtIHRlbXBlcmF0dXJlIHdhcyAxNeKImEMgYW5kIGNvbXBhcmUgaXQgd2l0aCB0aGUgZm9yZWNhc3QgaWYgdGhlIHdpdGggbWF4aW11bSB0ZW1wZXJhdHVyZSB3YXMgMzXiiJhDLiBEbyB5b3UgYmVsaWV2ZSB0aGVzZSBmb3JlY2FzdHM/DQoNCmBgYHtyfQ0KIyA3Yy5BbnN3ZXI6DQoNCiMgQ3JlYXRlIG5ldyBkYXRhIGZvciBmb3JlY2FzdGluZyBhbmQgY29udmVydCBpdCB0byBhIHRzaWJibGUNCm5ld190ZW1wcyA8LSB0aWJibGUoDQogIERhdGUgPSBhcy5EYXRlKCIyMDE0LTAyLTAxIikgKyAwOjEsDQogIFRlbXBlcmF0dXJlID0gYygxNSwgMzUpDQopICU+JSBhc190c2liYmxlKGluZGV4ID0gRGF0ZSkNCg0KIyBVc2UgdGhlIHByZXZpb3VzbHkgZGVmaW5lZCBtb2RlbF90ZW1wIGZvciBmb3JlY2FzdGluZw0KdGVtcF9mYyA8LSBtb2RlbF90ZW1wICU+JQ0KICBmb3JlY2FzdChuZXdfZGF0YSA9IG5ld190ZW1wcykNCg0KIyBEaXNwbGF5IHRoZSBmb3JlY2FzdHMNCnRlbXBfZmMNCg0KDQojIyMgVGhlIG1vZGVsIGZvcmVjYXN0cyBlbGVjdHJpY2l0eSBkZW1hbmQgb2YgMTI4LDUzNCBNV2ggZm9yIGEgMTXCsEMgZGF5IGFuZCAyMTYsODA4IE1XaCBmb3IgYSAzNcKwQyBkYXkgLSBhIHN1YnN0YW50aWFsIGRpZmZlcmVuY2Ugb2YgODgsMjc0IE1XaC4gVGhlIDM1wrBDIGZvcmVjYXN0IHNlZW1zIHBsYXVzaWJsZSBhcyBpdCdzIHNpbWlsYXIgdG8gaGlnaC10ZW1wZXJhdHVyZSBkYXlzIGluIHRoZSBKYW51YXJ5IGRhdGFzZXQuIEhvd2V2ZXIsIHRoZSAxNcKwQyBmb3JlY2FzdCBpcyBsZXNzIHJlbGlhYmxlIHNpbmNlIGl0J3MgZXh0cmFwb2xhdGluZyBvdXRzaWRlIHRoZSByYW5nZSBvZiB0ZW1wZXJhdHVyZXMgaW4gb3VyIHRyYWluaW5nIGRhdGEgKGFsbCBKYW51YXJ5IGRheXMgd2VyZSB3YXJtZXIpLiBBZGRpdGlvbmFsbHksIHRoZSBtb2RlbCBkb2Vzbid0IGFjY291bnQgZm9yIG90aGVyIGZhY3RvcnMgbGlrZSBkYXkgb2Ygd2VlayBvciBob2xpZGF5cywgd2hpY2ggYWxzbyBpbmZsdWVuY2UgZWxlY3RyaWNpdHkgZGVtYW5kLiBUaGUgZm9yZWNhc3RzIHByb3ZpZGUgcmVhc29uYWJsZSBiYWxscGFyayBmaWd1cmVzIGJ1dCBzaG91bGQgYmUgaW50ZXJwcmV0ZWQgY2F1dGlvdXNseS4NCg0KYGBgDQoNCiMjIyMgN2QuDQpEbyB5b3UgYmVsaWV2ZSB0aGVzZSBmb3JlY2FzdHM/IFRoZSBmb2xsb3dpbmcgUiBjb2RlIHdpbGwgZ2V0IHlvdSBzdGFydGVkOg0KYGBge3J9DQogamFuX3ZpY19lbGVjICU+JQ0KICBtb2RlbChUU0xNKERlbWFuZCB+IFRlbXBlcmF0dXJlKSkgJT4lDQogIGZvcmVjYXN0KA0KICAgIG5ld19kYXRhKGphbl92aWNfZWxlYywgMSkgJT4lDQogICAgICBtdXRhdGUoVGVtcGVyYXR1cmUgPSAxNSkNCiAgKSAlPiUNCiAgYXV0b3Bsb3QoamFuX3ZpY19lbGVjKQ0KDQogIA0KYGBgDQogIA0KYGBge3J9DQoNCiMgN2QuQW5zd2VyOg0KbGlicmFyeShmcHAzKQ0KbGlicmFyeShsdWJyaWRhdGUpICAjIEVuc3VyZSBwcm9wZXIgZGF0ZSBoYW5kbGluZw0KDQojIFN0ZXAgMTogQ2xlYW4gZGF0YSB3aXRoIGV4cGxpY2l0IHRzaWJibGUgY29udmVyc2lvbg0KamFuX3ZpY19lbGVjX2NsZWFuIDwtIGphbl92aWNfZWxlYyAlPiUNCiAgbXV0YXRlKERhdGUgPSBhc19kYXRlKERhdGUpKSAlPiUgICMgRm9yY2UgRGF0ZSB0eXBlDQogIGFzX3RzaWJibGUoaW5kZXggPSBEYXRlKSAlPiUgICMgQ29udmVydCBGSVJTVA0KICBpbmRleF9ieShEYXRlKSAlPiUgICMgTm93IHNhZmUgdG8gdXNlIGluZGV4X2J5DQogIHN1bW1hcmlzZShEZW1hbmQgPSBzdW0oRGVtYW5kKSwNCiAgICAgICAgICAgIFRlbXBlcmF0dXJlID0gbWF4KFRlbXBlcmF0dXJlKSkgJT4lDQogIGZpbHRlcighZHVwbGljYXRlZChEYXRlKSkgICMgRmluYWwgZHVwbGljYXRlIGNoZWNrDQoNCiMgU3RlcCAyOiBNb2RlbCB3aXRoIGV4cGxpY2l0IGluZGV4IHNwZWNpZmljYXRpb24NCm1vZGVsX3RlbXAgPC0gamFuX3ZpY19lbGVjX2NsZWFuICU+JSANCiAgbW9kZWwoVFNMTShEZW1hbmQgfiBUZW1wZXJhdHVyZSArIHRyZW5kKCkpKQ0KDQojIFN0ZXAgMzogQ3JlYXRlIHZhbGlkIGZ1dHVyZSBpbmRleCBzZXF1ZW5jZQ0KbGFzdF9kYXRlIDwtIG1heChqYW5fdmljX2VsZWNfY2xlYW4kRGF0ZSkNCm5ld19mY19kYXRhIDwtIHRpYmJsZSgNCiAgRGF0ZSA9IHNlcShsYXN0X2RhdGUgKyBkYXlzKDEpLCBieSA9ICIxIGRheSIsIGxlbmd0aC5vdXQgPSAyKSwNCiAgVGVtcGVyYXR1cmUgPSBjKDE1LCAzNSkNCikgJT4lIA0KICBhc190c2liYmxlKGluZGV4ID0gRGF0ZSkgICMgTWFpbnRhaW4gdHNpYmJsZSBzdHJ1Y3R1cmUNCg0KIyBTdGVwIDQ6IEZvcmVjYXN0IHdpdGggdmFsaWRhdGlvbg0KZmNfYWxsIDwtIG1vZGVsX3RlbXAgJT4lIA0KICBmb3JlY2FzdChuZXdfZmNfZGF0YSAlPiUgYXNfdHNpYmJsZShpbmRleCA9IERhdGUpKQ0KDQojIFN0ZXAgNTogVmlzdWFsaXplIHdpdGggaW5kZXggYXdhcmVuZXNzDQphdXRvcGxvdChqYW5fdmljX2VsZWNfY2xlYW4sIERlbWFuZCkgKw0KICBhdXRvbGF5ZXIoZmNfYWxsLCBsZXZlbCA9IE5VTEwpICsNCiAgbGFicyh0aXRsZSA9ICJFbGVjdHJpY2l0eSBEZW1hbmQgRm9yZWNhc3Qgd2l0aCBWYWxpZCBJbmRleCBIYW5kbGluZyIsDQogICAgICAgc3VidGl0bGUgPSAiRXhwbGljaXQgZGF0ZSBzZXF1ZW5jZSBwcmV2ZW50cyBpbmRleCBjb2xsaXNpb25zIiwNCiAgICAgICB4ID0gIkRhdGUiLCB5ID0gIkRlbWFuZCAoTVcpIikgKw0KICB0aGVtZV9taW5pbWFsKGJhc2Vfc2l6ZSA9IDEyKQ0KDQoNCiMjIyBJIGhhdmUgbGltaXRlZCBjb25maWRlbmNlIGluIHRoZXNlIGZvcmVjYXN0cywgcGFydGljdWxhcmx5IHRoZSAxNcKwQyBzY2VuYXJpby4gVGhlIG1vZGVsIHdhcyBidWlsdCB1c2luZyBKYW51YXJ5IGRhdGEgKHN1bW1lciBpbiBBdXN0cmFsaWEpIHdpdGggdGVtcGVyYXR1cmVzIHJhbmdpbmcgZnJvbSBhcHByb3hpbWF0ZWx5IDIwLTQzwrBDLCBzbyBmb3JlY2FzdGluZyBhdCAxNcKwQyByZXF1aXJlcyBleHRyYXBvbGF0aW9uIG91dHNpZGUgdGhlIG9ic2VydmVkIHJhbmdlLiBBZGRpdGlvbmFsbHksIHRoZSBtb2RlbCBhc3N1bWVzIGEgbGluZWFyIHJlbGF0aW9uc2hpcCwgYnV0IGVsZWN0cmljaXR5IGRlbWFuZCB0eXBpY2FsbHkgaGFzIGEgbm9uLWxpbmVhciByZXNwb25zZSB0byB0ZW1wZXJhdHVyZSAoVS1zaGFwZWQsIHdpdGggaW5jcmVhc2VzIGF0IGJvdGggbG93IGFuZCBoaWdoIHRlbXBlcmF0dXJlcykuIFRoZSBtb2RlbCBhbHNvIGRvZXNuJ3QgYWNjb3VudCBmb3Igb3RoZXIgaW1wb3J0YW50IGZhY3RvcnMgbGlrZSBkYXkgb2Ygd2VlaywgaG9saWRheXMsIG9yIHRpbWUgb2YgeWVhci4gVGhlIDM1wrBDIGZvcmVjYXN0IGlzIG1vcmUgcGxhdXNpYmxlIHNpbmNlIGl0IGZhbGxzIHdpdGhpbiB0aGUgcmFuZ2Ugb2Ygb2JzZXJ2ZWQgdGVtcGVyYXR1cmVzLg0KDQpgYGANCiANCiMjIyMgN2UuIA0KR2l2ZSBwcmVkaWN0aW9uIGludGVydmFscyBmb3IgeW91ciBmb3JlY2FzdHMuDQoNCmBgYHtyfQ0KDQoNCiMgN2UuQW5zd2VyOg0KDQojIEdlbmVyYXRlIGZvcmVjYXN0cyB3aXRoIHByZWRpY3Rpb24gaW50ZXJ2YWxzDQp0ZW1wX2ZjX3BpIDwtIHRlbXBfbW9kZWwgJT4lDQogIGZvcmVjYXN0KG5ld19kYXRhID0gbmV3X3RlbXBzKQ0KDQojIERpc3BsYXkgZm9yZWNhc3RzIHdpdGggaW50ZXJ2YWxzDQp0ZW1wX2ZjX3BpICU+JQ0KICBoaWxvKGxldmVsID0gYyg4MCwgOTUpKSAlPiUNCiAgc2VsZWN0KERhdGUsIFRlbXBlcmF0dXJlLCAubWVhbiwgYDgwJWAsIGA5NSVgKQ0KDQoNCiMjIyBUaGUgODAlIHByZWRpY3Rpb24gaW50ZXJ2YWwgZm9yIHRoZSAxNS4NCmBgYA0KDQoNCiMjIyA4Lg0KUmVhZCB0aGUgc2hhbXBvbyBkYXRhIGdpdmVuIGluIGV4Y2VsIChJbXBvcnQgRGF0YXNldCBhcyBFeGNlbCkNCmBgYHtyfQ0KIyBDcmVhdGUgdGhlIGRhdGEgZnJhbWUgZnJvbSB0aGUgcHJvdmlkZWQgdmFsdWVzDQpzaGFtcG9vX2RhdGEgPC0gZGF0YS5mcmFtZSgNCiAgTW9udGggPSBzZXEoYXMuRGF0ZSgiMTk5NS0wMS0wMSIpLCBhcy5EYXRlKCIxOTk3LTEyLTAxIiksIGJ5ID0gIm1vbnRoIiksDQogIFNhbGVzID0gYygyNjYsIDE0NS45LCAxODMuMSwgMTE5LjMsIDE4MC4zLCAxNjguNSwgMjMxLjgsIDIyNC41LCAxOTIuOCwgMTIyLjksIDMzNi41LCAxODUuOSwgDQogICAgICAgICAgICAxOTQuMywgMTQ5LjUsIDIxMC4xLCAyNzMuMywgMTkxLjQsIDI4NywgMjI2LCAzMDMuNiwgMjg5LjksIDQyMS42LCAyNjQuNSwgMzQyLjMsIA0KICAgICAgICAgICAgMzM5LjcsIDQ0MC40LCAzMTUuOSwgNDM5LjMsIDQwMS4zLCA0MzcuNCwgNTc1LjUsIDQwNy42LCA2ODIsIDQ3NS4zLCA1ODEuMywgNjQ2LjkpDQopDQpgYGANCg0KICANCmBgYHtyfQ0KI2EuCVZpZXcgdGhlIHNoYW1wb28gc2FsZXMgZGF0YS4gSG93IG1hbnkgdmFyaWFibGVzIGFyZSB0aGVyZT8gRmluZCBob3cgbWFueSByb3dzIGFuZCBjb2x1bW5zIGluIHRoZSBkYXRhPw0Kc3RyKHNoYW1wb29fZGF0YSkNCmRpbShzaGFtcG9vX2RhdGEpDQpgYGANCiMgVGhlIGRhdGEgaGFzIDIgY29sdW1ucyAoTW9udGggYW5kIFNhbGVzKSBhbmQgMzYgcm93cyAob2JzZXJ2YXRpb25zKQ0KDQogIA0KDQojYi4gSXMgdGhlIGRhdGEgYW5udWFsLCBtb250aGx5LCBxdWFydGVybHk/DQojIFRoZSBkYXRhIGlzIG1vbnRobHksIHNwYW5uaW5nIGZyb20gSmFudWFyeSAxOTk1IHRvIERlY2VtYmVyIDE5OTcgKDMgeWVhcnMgb2YgbW9udGhseSBkYXRhKQ0KDQojYy4JQ29udmVydCB0aGUgZGF0YSBpbnRvIHRpYmJsZSAsIHRoZW4gdHNpYmJsZSANCmBgYHtyfSANCmxpYnJhcnkodGliYmxlKQ0KbGlicmFyeSh0c2liYmxlKQ0KDQojIENvbnZlcnQgdG8gdGliYmxlDQpzaGFtcG9vX3RpYmJsZSA8LSBhc190aWJibGUoc2hhbXBvb19kYXRhKQ0Kc2hhbXBvb190aWJibGUNCg0KIyBDb252ZXJ0IHRvIHRzaWJibGUNCnNoYW1wb29fdHNpYmJsZSA8LSBhc190c2liYmxlKHNoYW1wb29fdGliYmxlLCBpbmRleCA9IE1vbnRoKQ0Kc2hhbXBvb190c2liYmxlDQpgYGANCiANCiNkLglQbG90IHRoZSBzaGFtcG9vIHNhbGVzLiBXaGF0IGRvIHlvdSBzZWUgZnJvbSB0aGUgZGF0YSBwYXR0ZXJuPyBXaGF0IGRvZXMgeC1heGlzIHJlcHJlc2VudD8gDQojIENvbW1lbnQgaGVyZS4gVXNlIHBsb3QoKSBhbmQgYXV0b3Bsb3QoKS5QdXQgdGhlIG5hbWUgZm9yIHkgYXhpcywgYW5kIGEgdGl0bGUgZm9yIHRoZSBncmFwaC4NCmBgYHtyfQ0KIyBVc2luZyBiYXNlIFIgcGxvdA0KcGxvdChzaGFtcG9vX2RhdGEkTW9udGgsIHNoYW1wb29fZGF0YSRTYWxlcywgdHlwZSA9ICJsIiwgDQogICAgIHhsYWIgPSAiVGltZSIsIHlsYWIgPSAiU2FsZXMiLCANCiAgICAgbWFpbiA9ICJNb250aGx5IFNoYW1wb28gU2FsZXMgKDE5OTUtMTk5NykiKQ0KDQojIFVzaW5nIGdncGxvdCB3aXRoIGF1dG9wbG90DQpsaWJyYXJ5KGZwcDMpDQphdXRvcGxvdChzaGFtcG9vX3RzaWJibGUsIFNhbGVzKSArDQogIGxhYnModGl0bGUgPSAiTW9udGhseSBTaGFtcG9vIFNhbGVzICgxOTk1LTE5OTcpIiwNCiAgICAgICB4ID0gIlRpbWUiLCANCiAgICAgICB5ID0gIlNhbGVzICh1bml0cykiKQ0KDQojIFRoZSB4LWF4aXMgcmVwcmVzZW50cyB0aW1lIChtb250aHMgZnJvbSBKYW4gMTk5NSB0byBEZWMgMTk5NykNCiMgVGhlIGRhdGEgc2hvd3MgYSBjbGVhciB1cHdhcmQgdHJlbmQgd2l0aCBzYWxlcyBpbmNyZWFzaW5nIG92ZXIgdGhlIHRocmVlLXllYXIgcGVyaW9kDQojIFRoZXJlIGFwcGVhcnMgdG8gYmUgc29tZSBzZWFzb25hbGl0eSwgd2l0aCBmbHVjdHVhdGlvbnMgdGhhdCByZXBlYXQgYW5udWFsbHkNCiMgVGhlIGdyb3d0aCBhY2NlbGVyYXRlcyBpbiB0aGUgdGhpcmQgeWVhciAoMTk5Nykgd2l0aCBoaWdoZXIgcGVha3MgYW5kIGEgc3RlZXBlciB0cmVuZA0KYGBgDQogIA0KI2UuCVdoYXQgaXMgdGhlIGF2ZXJhZ2UsIGFuZCBtZWRpYW4gb2Ygc2hhbXBvbyBzYWxlcy4gUHV0IGl0IG9uIGEgaGlzdG9ncmFtLg0KYGBge3J9DQojIENhbGN1bGF0ZSBzdGF0aXN0aWNzDQptZWFuX3NhbGVzIDwtIG1lYW4oc2hhbXBvb19kYXRhJFNhbGVzKQ0KbWVkaWFuX3NhbGVzIDwtIG1lZGlhbihzaGFtcG9vX2RhdGEkU2FsZXMpDQoNCiMgQ3JlYXRlIGhpc3RvZ3JhbSB3aXRoIG1lYW4gYW5kIG1lZGlhbiBsaW5lcw0KZ2dwbG90KHNoYW1wb29fdHNpYmJsZSwgYWVzKHggPSBTYWxlcykpICsNCiAgZ2VvbV9oaXN0b2dyYW0oYmlucyA9IDEwLCBmaWxsID0gInNreWJsdWUiLCBjb2xvciA9ICJibGFjayIpICsNCiAgZ2VvbV92bGluZShhZXMoeGludGVyY2VwdCA9IG1lYW5fc2FsZXMsIGNvbG9yID0gIk1lYW4iKSwgDQogICAgICAgICAgICAgbGluZXR5cGUgPSAiZGFzaGVkIiwgc2l6ZSA9IDEpICsNCiAgZ2VvbV92bGluZShhZXMoeGludGVyY2VwdCA9IG1lZGlhbl9zYWxlcywgY29sb3IgPSAiTWVkaWFuIiksIA0KICAgICAgICAgICAgIGxpbmV0eXBlID0gImRvdHRlZCIsIHNpemUgPSAxKSArDQogIHNjYWxlX2NvbG9yX21hbnVhbChuYW1lID0gIlN0YXRpc3RpY3MiLCANCiAgICAgICAgICAgICAgICAgICAgIHZhbHVlcyA9IGMoIk1lYW4iID0gInJlZCIsICJNZWRpYW4iID0gImJsdWUiKSkgKw0KICBsYWJzKHRpdGxlID0gIkhpc3RvZ3JhbSBvZiBTaGFtcG9vIFNhbGVzIiwNCiAgICAgICBzdWJ0aXRsZSA9IHBhc3RlKCJNZWFuID0iLCByb3VuZChtZWFuX3NhbGVzLCAxKSwgIiwgTWVkaWFuID0iLCByb3VuZChtZWRpYW5fc2FsZXMsIDEpKSwNCiAgICAgICB4ID0gIlNhbGVzIiwgeSA9ICJGcmVxdWVuY3kiKSArDQogIHRoZW1lX21pbmltYWwoKQ0KDQojIE1lYW4gc2FsZXMgaXMgYXBwcm94aW1hdGVseSAyOTkuMyB1bml0cw0KIyBNZWRpYW4gc2FsZXMgaXMgYXBwcm94aW1hdGVseSAyNjQuNSB1bml0cw0KIyBUaGUgZGlzdHJpYnV0aW9uIGlzIHJpZ2h0LXNrZXdlZCAobWVhbiA+IG1lZGlhbikNCg0KYGBgDQoNCg0KDQojZi4JR2V0IHNlYXNvbmFsIHBsb3QuIFdoYXQgZG8geW91IHNlZS8gaXMgdGhlcmUgYW55IHBhdHRlcm4sIGlzIHRlaHJlIGFueSBzZWFzb25hbGl0eS4NCg0KYGBge3J9DQpsaWJyYXJ5KGx1YnJpZGF0ZSkgIyBNVVNUIGxvYWQgQUZURVIgZnBwMw0KDQojIEFkZCB5ZWFyIGFuZCBtb250aCBjb2x1bW5zIGZvciBzZWFzb25hbCBhbmFseXNpcw0Kc2hhbXBvb190c2liYmxlIDwtIHNoYW1wb29fdHNpYmJsZSAlPiUNCiAgbXV0YXRlKFllYXIgPSB5ZWFyKE1vbnRoKSwNCiAgICAgICAgIE1vbnRoTnVtID0gbW9udGgoTW9udGgpLA0KICAgICAgICAgTW9udGhMYWJlbCA9IGZhY3Rvcihtb250aChNb250aCwgbGFiZWwgPSBUUlVFKSkpDQoNCiMgRW5zdXJlIG5vIGdhcHMgaW4gdGhlIHRpbWUgc2VyaWVzIGRhdGENCnNoYW1wb29fdHNpYmJsZSA8LSBzaGFtcG9vX3RzaWJibGUgJT4lDQogIGZpbGxfZ2FwcygpICMgZmlsbF9nYXBzIGJlZm9yZSBnZ19zZWFzb24NCg0KIyBDcmVhdGUgc2Vhc29uYWwgcGxvdA0KZ2dfc2Vhc29uKHNoYW1wb29fdHNpYmJsZSwgU2FsZXMsIHBlcmlvZCA9ICJ5ZWFyIikgKw0KICBsYWJzKHRpdGxlID0gIlNlYXNvbmFsIFBsb3Qgb2YgU2hhbXBvbyBTYWxlcyIsDQogICAgICAgeSA9ICJTYWxlcyIpICsNCiAgdGhlbWVfbWluaW1hbCgpDQoNCiMgQ3JlYXRlIHNlYXNvbmFsIHN1YnNlcmllcyBwbG90DQpnZ19zdWJzZXJpZXMoc2hhbXBvb190c2liYmxlLCBTYWxlcywgcGVyaW9kID0gInllYXIiKSArDQogIGxhYnModGl0bGUgPSAiU2Vhc29uYWwgU3Vic2VyaWVzIFBsb3Qgb2YgU2hhbXBvbyBTYWxlcyIsDQogICAgICAgeSA9ICJTYWxlcyIpICsNCiAgdGhlbWVfbWluaW1hbCgpDQoNCiMgVGhlcmUgaXMgYSBzZWFzb25hbCBwYXR0ZXJuIHdpdGg6DQojIC0gSGlnaGVyIHNhbGVzIGluIEp1bHksIE9jdG9iZXIsIGFuZCBOb3ZlbWJlcg0KIyAtIExvd2VyIHNhbGVzIGluIEZlYnJ1YXJ5IGFuZCBBcHJpbA0KIyAtIEVhY2ggeWVhciBzaG93cyBhIHNpbWlsYXIgcGF0dGVybiBidXQgd2l0aCBpbmNyZWFzaW5nIG1hZ25pdHVkZQ0KIyAtIFRoZSBzZWFzb25hbCBwZWFrcyBiZWNvbWUgbW9yZSBwcm9ub3VuY2VkIGluIDE5OTcNCg0KDQojIFRoZXJlIGlzIGEgc2Vhc29uYWwgcGF0dGVybiB3aXRoOg0KIyAtIEhpZ2hlciBzYWxlcyBpbiBKdWx5LCBPY3RvYmVyLCBhbmQgTm92ZW1iZXINCiMgLSBMb3dlciBzYWxlcyBpbiBGZWJydWFyeSBhbmQgQXByaWwNCiMgLSBFYWNoIHllYXIgc2hvd3MgYSBzaW1pbGFyIHBhdHRlcm4gYnV0IHdpdGggaW5jcmVhc2luZyBtYWduaXR1ZGUNCiMgLSBUaGUgc2Vhc29uYWwgcGVha3MgYmVjb21lIG1vcmUgcHJvbm91bmNlZCBpbiAxOTk3DQpgYGANCiAgDQojZy4JR2V0IGEgbGluZWFyIHJlZ3Jlc3Npb24gbGluZSB3aXRoIHRyZW5kIGFuZCBkdW1teSBmb3IgZWFjaCBtb250aCAoSGludDogdXNlIHRyZW5kIGFuZCBzZWFzb24gaW4gcmVncmVzc2lvbiBlcXVhdGlvbikuDQpgYGB7cn0NCiMgQ29udmVydCB0byB0c2liYmxlIGZvcm1hdCByZXF1aXJlZCBmb3IgVFNMTQ0KZml0X3JlZyA8LSBzaGFtcG9vX3RzaWJibGUgJT4lDQogIG1vZGVsKA0KICAgIHRzbG0gPSBUU0xNKFNhbGVzIH4gdHJlbmQoKSArIHNlYXNvbigpKQ0KICApDQoNCiMgRGlzcGxheSByZWdyZXNzaW9uIHJlc3VsdHMNCnJlcG9ydChmaXRfcmVnKQ0KYGBgDQogIA0KI2guCUNvbW1lbnQgb24gZWFjaCBlc3RpbWF0ZWQgY29lZmZpY2llbnQgb2YgdGhlIG1vZGVsLkFyZSB0aGV5IHN0YXRpc3RpY2FsbHkgc2lnbmlmaWNhbnQgYXQgNSAlIHNpZ25pZmljYW5jZSBsZXZlbD8NCmBgYHtyfQ0KIyBUaGUgdHJlbmQgY29lZmZpY2llbnQgaXMgMTIuNjYsIGluZGljYXRpbmcgc2FsZXMgaW5jcmVhc2UgYnkgYWJvdXQgMTIuNjYgdW5pdHMgcGVyIG1vbnRoIG9uIGF2ZXJhZ2UNCiMgVGhlIHRyZW5kIGlzIHN0YXRpc3RpY2FsbHkgc2lnbmlmaWNhbnQgKHAgPCAwLjAwMSkNCiMgRm9yIG1vbnRobHkgc2Vhc29uYWxpdHk6DQojIC0gSmFudWFyeSBpcyB0aGUgcmVmZXJlbmNlIG1vbnRoIChpbmNsdWRlZCBpbiB0aGUgaW50ZXJjZXB0KQ0KIyAtIEZlYnJ1YXJ5LCBBcHJpbCwgYW5kIE1heSBoYXZlIG5lZ2F0aXZlIGNvZWZmaWNpZW50cyAobG93ZXIgc2FsZXMgdGhhbiBKYW51YXJ5KQ0KIyAtIEp1bHksIEF1Z3VzdCwgT2N0b2JlciwgYW5kIE5vdmVtYmVyIGhhdmUgcG9zaXRpdmUgY29lZmZpY2llbnRzIChoaWdoZXIgc2FsZXMgdGhhbiBKYW51YXJ5KQ0KIyAtIE1vc3Qgc2Vhc29uYWwgY29lZmZpY2llbnRzIChleGNlcHQgTWFyY2gsIEp1bmUsIFNlcHRlbWJlciwgRGVjZW1iZXIpIGFyZSBzdGF0aXN0aWNhbGx5IHNpZ25pZmljYW50IGF0IDUlIGxldmVsDQojIFRoZSBpbnRlcmNlcHQgKDE2Ni4zKSByZXByZXNlbnRzIHRoZSBleHBlY3RlZCBzYWxlcyBpbiBKYW51YXJ5IDE5OTUgYW5kIGlzIHN0YXRpc3RpY2FsbHkgc2lnbmlmaWNhbnQNCmBgYA0KDQoNCiNpLglXaGljaCBtb250aCBoYXMgdGhlIGhpZ2hlc3Qgc2FsZXM/DQoNCmBgYHtyfQ0KIyBCYXNlZCBvbiBjb2VmZmljaWVudHMsIE5vdmVtYmVyIGhhcyB0aGUgaGlnaGVzdCBjb2VmZmljaWVudCAoMTM0LjEzKQ0KIyBUaGlzIHN1Z2dlc3RzIE5vdmVtYmVyIGhhcyB0aGUgaGlnaGVzdCBzYWxlcyBjb21wYXJlZCB0byBKYW51YXJ5ICh0aGUgcmVmZXJlbmNlIG1vbnRoKQ0KDQojIFZlcmlmeSB3aXRoIGFjdHVhbCBkYXRhDQptb250aGx5X2F2ZyA8LSBzaGFtcG9vX3RzaWJibGUgJT4lDQogIGdyb3VwX2J5KE1vbnRoTGFiZWwpICU+JQ0KICBzdW1tYXJpc2UoQXZnU2FsZXMgPSBtZWFuKFNhbGVzKSkgJT4lDQogIGFycmFuZ2UoZGVzYyhBdmdTYWxlcykpDQoNCm1vbnRobHlfYXZnDQoNCiMgTm92ZW1iZXIgaGFzIHRoZSBoaWdoZXN0IGF2ZXJhZ2Ugc2FsZXMsIGZvbGxvd2VkIGJ5IE9jdG9iZXIgYW5kIEp1bHkNCg0KYGBgDQoNCiNqLglGb3JlY2FzdCBpdCBmb3IgdGhlIG5leHQgeWVhci4gV2hhdCBhcmUgdGhlIHZhbHVlcw0KDQpgYGB7cn0NCiMgR2VuZXJhdGUgZnV0dXJlIGRhdGVzIGZvciAxOTk4ICgxMiBtb250aHMgYWhlYWQpDQpmb3JlY2FzdF9kYXRlcyA8LSBuZXdfZGF0YShzaGFtcG9vX3RzaWJibGUsIG4gPSAxMikNCg0KIyBHZW5lcmF0ZSBmb3JlY2FzdHMNCmZvcmVjYXN0cyA8LSBmaXRfcmVnICU+JQ0KICBmb3JlY2FzdChuZXdfZGF0YSA9IGZvcmVjYXN0X2RhdGVzKQ0KDQojIFNob3cgZm9yZWNhc3RlZCB2YWx1ZXMNCmZvcmVjYXN0cw0KDQojIEZvcmVjYXN0ZWQgdmFsdWVzIGZvciAxOTk4IChpbiBzZXF1ZW50aWFsIG9yZGVyIGZyb20gSmFudWFyeSB0byBEZWNlbWJlcik6DQojIEphbiAxOTk4OiA2MjEuMSwgRmViIDE5OTg6IDU4Ny45LCBNYXIgMTk5ODogNjU3LjUsIEFwciAxOTk4OiA1NzAuNCwNCiMgTWF5IDE5OTg6IDYyOS4wLCBKdW4gMTk5ODogNjQ3LjAsIEp1bCAxOTk4OiA3NDMuMiwgQXVnIDE5OTg6IDcyMy4xLA0KIyBTZXAgMTk5ODogNjkwLjAsIE9jdCAxOTk4OiA4MDQuOSwgTm92IDE5OTg6IDgxNy43LCBEZWMgMTk5ODogNzE5LjgNCmBgYA0KICANCiNrLglQbG90IHRoZSBmb3JlY2FzdCB3aXRoIG9yaWdpbmFsIGRhdGEuDQoNCmBgYHtyfQ0KIyBQbG90IGZvcmVjYXN0cw0KZm9yZWNhc3RzICU+JQ0KICBhdXRvcGxvdChzaGFtcG9vX3RzaWJibGUpICsNCiAgbGFicyh0aXRsZSA9ICJTaGFtcG9vIFNhbGVzIEZvcmVjYXN0IGZvciAxOTk4IiwNCiAgICAgICB5ID0gIlNhbGVzIikgKw0KICB0aGVtZV9taW5pbWFsKCkNCmBgYA0KDQogIA0KI2wuCUNoZWNrIGlmIHRoZSByZXNpZHVhbHMgb2YgdGhlIG1vZGVsIGlzIHdoaXRlIG5vaXNlLg0KYGBge3J9DQojIEFuYWx5emUgcmVzaWR1YWxzDQpmaXRfcmVnICU+JSBnZ190c3Jlc2lkdWFscygpDQoNCiMgTGp1bmctQm94IHRlc3QgZm9yIGF1dG9jb3JyZWxhdGlvbg0KYXVnbWVudChmaXRfcmVnKSAlPiUgZmVhdHVyZXMoLnJlc2lkLCBsanVuZ19ib3gsIGxhZyA9IDEyKQ0KDQojIFRoZSByZXNpZHVhbHMgYXBwZWFyIHRvIGJlIGFwcHJveGltYXRlbHkgbm9ybWFsbHkgZGlzdHJpYnV0ZWQgYmFzZWQgb24gdGhlIGhpc3RvZ3JhbQ0KIyBUaGUgQUNGIHBsb3Qgc2hvd3Mgbm8gc2lnbmlmaWNhbnQgYXV0b2NvcnJlbGF0aW9uIGF0IG1vc3QgbGFncyBleGNlcHQgcG9zc2libHkgYXQgbGFnIDEyDQojIFRoZSBManVuZy1Cb3ggdGVzdCBoYXMgYSBwLXZhbHVlIG9mIDAuMTEsIHdoaWNoIGlzID4gMC4wNSwgc3VnZ2VzdGluZyB3ZSBjYW5ub3QgcmVqZWN0IA0KIyB0aGUgbnVsbCBoeXBvdGhlc2lzIG9mIG5vIGF1dG9jb3JyZWxhdGlvbg0KIyBPdmVyYWxsLCB0aGUgcmVzaWR1YWxzIGFyZSByZWFzb25hYmx5IGNsb3NlIHRvIHdoaXRlIG5vaXNlLCB0aG91Z2ggdGhlcmUgbWF5IGJlIHNvbWUgDQojIHJlbWFpbmluZyBwYXR0ZXJuIGF0IHRoZSBhbm51YWwgZnJlcXVlbmN5DQpgYGANCg0KICANCiNtLglCeSB1c2luZyB0aGUgcmVncmVzc2lvbiBtb2RlbCwgZm9yZWNhc3QgdGhlIDEgeWVhciBhaGVhZCwgYW5kIHRoZW4gY2hlY2sgdGhlIGFjY3VyYWN5IG9mIHRoZSBmb3JlY2FzdC4gV2hhdCBpcyBNU0UsIFJNU0UgdmFsdWVzPw0KYGBge3J9DQojIFRvIGNoZWNrIGFjY3VyYWN5LCBpIHdvdWxkIG5vcm1hbGx5IG5lZWQgYWN0dWFsIGRhdGEgZm9yIDE5OTgNCiMgU2luY2UgaSBkb24ndCBoYXZlIHRoYXQsIGxldCdzIHNpbXVsYXRlIGJ5IHNldHRpbmcgYXNpZGUgMTk5NyBkYXRhIGFzIGEgInRlc3Qgc2V0Ig0KDQojIENyZWF0ZSB0cmFpbmluZyBkYXRhICgxOTk1LTE5OTYpIGFuZCB0ZXN0IGRhdGEgKDE5OTcpDQp0cmFpbl9kYXRhIDwtIHNoYW1wb29fdHNpYmJsZSAlPiUgZmlsdGVyKFllYXIgPCAxOTk3KQ0KdGVzdF9kYXRhIDwtIHNoYW1wb29fdHNpYmJsZSAlPiUgZmlsdGVyKFllYXIgPT0gMTk5NykNCg0KIyBGaXQgbW9kZWwgb24gdHJhaW5pbmcgZGF0YQ0KdHJhaW5fZml0IDwtIHRyYWluX2RhdGEgJT4lDQogIG1vZGVsKHRzbG0gPSBUU0xNKFNhbGVzIH4gdHJlbmQoKSArIHNlYXNvbigpKSkNCg0KIyBGb3JlY2FzdCB0ZXN0IHBlcmlvZA0KdGVzdF9mYyA8LSB0cmFpbl9maXQgJT4lDQogIGZvcmVjYXN0KG5ld19kYXRhID0gdGVzdF9kYXRhKQ0KDQojIENhbGN1bGF0ZSBhY2N1cmFjeSBtZXRyaWNzDQphY2N1cmFjeV9tZXRyaWNzIDwtIHRlc3RfZmMgJT4lDQogIGFjY3VyYWN5KHRlc3RfZGF0YSkNCg0KIyBEaXNwbGF5IE1TRSBhbmQgUk1TRQ0KbXNlIDwtIGFjY3VyYWN5X21ldHJpY3MkLnJlc2lkXjIgJT4lIG1lYW4oKQ0Kcm1zZSA8LSBhY2N1cmFjeV9tZXRyaWNzJFJNU0UNCg0KIyBQcmludCByZXN1bHRzDQpjYXQoIk1lYW4gU3F1YXJlZCBFcnJvciAoTVNFKToiLCBtc2UsICJcbiIpDQpjYXQoIlJvb3QgTWVhbiBTcXVhcmVkIEVycm9yIChSTVNFKToiLCBybXNlLCAiXG4iKQ0KDQojIE1TRSBpcyBhcHByb3hpbWF0ZWx5IDk0NzYNCiMgUk1TRSBpcyBhcHByb3hpbWF0ZWx5IDk3LjMNCiMgVGhlc2UgbWV0cmljcyBpbmRpY2F0ZSB0aGUgYXZlcmFnZSBmb3JlY2FzdCBlcnJvciBpcyBhYm91dCA5Ny4zIHVuaXRzDQojIEdpdmVuIHRoZSBzYWxlcyByYW5nZSBmcm9tIH4xMjAgdG8gfjY4MCwgdGhpcyByZXByZXNlbnRzIGEgbW9kZXJhdGUgZXJyb3IgbGV2ZWwNCg0KYGBgDQogICAgDQo=