library(fpp3)
library(tidyverse)
Sys.time()
## [1] "2025-01-11 20:16:58 EST"

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:

gdp_India <- global_economy %>%
  filter(Country == "India") %>%
  mutate(GDP_per_capita = GDP / Population) %>%
  select(Year, GDP_per_capita)


autoplot(gdp_India, GDP_per_capita) +
  labs(title = "India's GDP per Capita Shows Gradual Growth from 1960s to 2000s,\n with Rapid Increase in Recent Years.",
       x = "Year",
       y = "GDP per Capita (USD)") +
  geom_smooth(method = "lm", se = FALSE, color = "Green", linetype = "dashed") +
  theme_minimal()
## `geom_smooth()` using formula = 'y ~ x'

#The GDP per capita in India has generally increased over time, with steady growth from the 1960s until a sharp acceleration in the early 2000s. This recent rapid rise highlights significant economic progress, likely driven by structural reforms and technological advancements.

2.

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

2a. Use the series you chose in #1.

# 2a.Answer:

gdp_India <- gdp_India%>%
  mutate(Log_GDP_per_capita = log(GDP_per_capita))

autoplot(gdp_India, Log_GDP_per_capita) +
  labs(title = "The log-transformed GDP per capita for India shows a consistent upward\n trend over time, indicating steady economic growth with\n reduced variability in recent years.",
       x = "Year",
       y = "Log of GDP per Capita") +
    geom_smooth(method = "lm", se = FALSE, color = "green", linetype = "dashed") +
  theme_minimal()
## `geom_smooth()` using formula = 'y ~ x'

2b.

United States GDP from global_economy.

# 2b.Answer:

gdp_us <- global_economy %>%
  filter(Country == "United States") %>%
  select(Year, GDP)

# # Plotting US GDP over time
autoplot(gdp_us, GDP) +
  labs(title = "U.S. GDP Demonstrates a Strong Upward Trend, Growing from Approximately $5 Trillion\n in the 1960s to Over $20 Trillion by 2020, Reflecting Steady Economic Growth\n Throughout the Decades.",
       x = "Year",
       y = "GDP (USD)") +
    geom_smooth(method = "lm", se = FALSE, color = "green", linetype = "dashed") +
  theme_minimal()
## `geom_smooth()` using formula = 'y ~ x'

# The graph illustrates a consistent increase in U.S. GDP over time, showcasing steady economic growth, with an accelerating trend observed in recent decades.

2c.

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

# 2c.Answer:

victorian_cattle <- aus_livestock %>%
  filter(State == "Victoria", Animal == "Bulls, bullocks and steers")

# Plotting the number of slaughters over time
autoplot(victorian_cattle, Count) +
  labs(title = "
The Slaughter of Bulls, Bullocks, and Steers in Victoria Decreased from Over\n 125,000 in the 1980s to Approximately 50,000 in Recent Years.",
       x = "Year",
       y = "Count") +
    geom_smooth(method = "lm", se = FALSE, color = "green", linetype = "dashed") +
  theme_minimal()
## `geom_smooth()` using formula = 'y ~ x'

# The number of bulls, bullocks, and steers slaughtered in Victoria has decreased from over 125,000 in the 1980s to about 50,000 in recent years.

2d.

Victorian Electricity Demand from vic_elec.

# 2d.Answer:

vic_elec_monthly <- vic_elec %>%
  index_by(Month = ~ yearmonth(.)) %>%
  summarise(Demand = mean(Demand, na.rm = TRUE))


autoplot(vic_elec_monthly, Demand) +
  labs(title = "Victorian Electricity Demand Exhibits Seasonal Peaks in Summer,\nDemonstrating a Distinct Seasonal Trend.",
       x = "Date",
       y = "Electricity Demand (MW)") +
  theme_minimal()

#The monthly average electricity demand in Victoria reveals a distinct seasonal trend, with peaks generally occurring during the summer months, likely reflecting increased demand for cooling.

2e.

Gas production from aus_production.

# 2e.Answer:

gas_production <- aus_production %>%
  select(Quarter, Gas)


autoplot(gas_production, Gas) +
  labs(title = "Australian Gas Production Increased from Approximately 0 to Over 250 Petajoules,\nExhibiting Significant Seasonal Peaks Throughout the Period.",
       x = "Year",
       y = "Gas Production (in petajoules)") +
    geom_smooth(method = "lm", se = FALSE, color = "green", linetype = "dashed") +
  theme_minimal()
## `geom_smooth()` using formula = 'y ~ x'

#Australian gas production demonstrates a consistent upward trend with notable seasonal variations, indicating both steady growth and regular peak demands likely influenced by seasonal consumption patterns.

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:

# General time series plot
autoplot(canadian_gas) +
  labs(title = "Canadian Monthly Gas Production(1960–2005)",
       x = "Year",
       y = "Gas Production (Billions of Cubic Metres)") +
  theme_minimal()
## Plot variable not specified, automatically selected `.vars = Volume`

# The time series plot shows a general upward trend in Canadian gas production from 1960 to 2005, with visible seasonal variations. These fluctuations become more prominent in recent years as production levels increase.

# Monthly Breakdown of Gas Production
gg_subseries(canadian_gas, Volume) +
  labs(title = "Monthly Trends in Canadian Gas Production",
       y = "Gas Production (Billions of Cubic Metres)") +
  theme_minimal()

# The monthly subseries plot reveals higher production levels in winter months, such as January and February, likely due to higher demand for heating. Production levels are lower in summer months, indicating a regular seasonal pattern.

# Seasonal Variation in Gas Production Over Time
gg_season(canadian_gas, Volume) +
  labs(title = "Seasonal Pattern in Canadian Gas Production",
       y = "Gas Production (Billions of Cubic Metres)") +
  theme_minimal()

# The seasonal plot highlights a consistent pattern, with production peaking in colder months and decreasing in warmer months. The amplitude of these seasonal changes increases over time, reflecting a growing variation in production as overall levels rise.

3b.

Do an STL decomposition of the data. You will need to choose a seasonal window to allow for the changing shape of the seasonal component.

# 3b.Answer:

canadian_gas_stl <- canadian_gas %>%
  model(STL(Volume ~ season(window = "periodic")))

# Plotting Decomposition Components
components(canadian_gas_stl) %>%
  autoplot() +
  labs(title = "STL Decomposition of Monthly Gas Production in Canada",
       x = "Year") +
  theme_minimal()

#  The STL decomposition shows a strong and growing seasonal pattern in Canadian gas production, with peaks in winter reflecting higher demand. This confirms the seasonal trends observed earlier. The remainder component reveals any irregularities or unexpected changes in production, potentially due to external factors or anomalies.

3c.

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

# 3c.Answer:

# Performing STL decomposition with a periodic seasonal window
canadian_gas_stl <- canadian_gas %>%
  model(STL_decomp = STL(Volume ~ season(window = "periodic")))

# Extracting components from the STL decomposition
seasonal_component <- canadian_gas_stl %>%
  components() %>%
  as_tsibble() %>%
  select(Month, season_adjust)

gg_season(seasonal_component, season_adjust) +
  labs(title = "Evolution of the Seasonal Pattern in Canadian Gas Production",
       y = "Seasonal Component (Billions of Cubic Metres)") +
  theme_minimal()

# The seasonal component shows peak production during winter months, with the amplitude of these peaks increasing over time. This trend suggests a rising demand for gas in winter as production levels grow.

3d.

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

# 3d.Answer:

# Perform STL decomposition with a periodic seasonal window
canadian_gas_stl <- canadian_gas %>%
  model(STL_decomp = STL(Volume ~ season(window = "periodic")))

# Generate the seasonally adjusted series by removing seasonal components
canadian_gas_seasonally_adjusted <- components(canadian_gas_stl) %>%
  mutate(Seasonally_Adjusted = Volume - season_year) %>%
  select(Month, Seasonally_Adjusted)

# Visualize the seasonally adjusted series
autoplot(canadian_gas_seasonally_adjusted, Seasonally_Adjusted) +
  labs(title = "Trend in Seasonally Adjusted Canadian Gas Production",
       x = "Year",
       y = "Gas Production (Billions of Cubic Metres)") +
    geom_smooth(method = "lm", se = FALSE, color = "green", linetype = "dashed") +
  theme_minimal()
## `geom_smooth()` using formula = 'y ~ x'

# The seasonally adjusted series reveals a clear upward trend in Canadian gas production from the 1960s to the early 2000s, highlighting consistent growth in production independent of seasonal fluctuations.

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:

fit %>% gg_tsresiduals()

# Do the residuals appear to be uncorrelated and normally distributed?
# Answ: The residuals display an approximately normal distribution, forming a bell-shaped curve centered around zero, suggesting they may be normally distributed.

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:

fc <- forecast(fit)
autoplot(fc, myseries)

accuracy(fc, 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 SNAIV… Nort… Clothin… Test  -0.125 0.765   0.6 -1.14  4.59 0.656 0.631 -0.0541
# The model is quite accurate considering the RMSE Score of 1.228089

4g.

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

# 4g Answer: The accuracy measures are influenced by the quantity of training data used; with limited data, errors may increase, and metrics such as RMSE, MAE, and MAPE can become less stable.

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:

# Filter the aus_retail dataset to include only takeaway food turnover data
takeaway_data <- aus_retail %>%
  filter(Industry == "Takeaway food services") %>%
  select(-Industry)  # Drop the Industry column

#Set the cutoff date by subtracting 48 months (4 years) from the latest date in the dataset
cutoff_date <- max(takeaway_data$Month) - 48 

# Define the training set with data before the cutoff date
takeaway_train <- takeaway_data %>%
  filter(Month < cutoff_date)

# Define the test set with data from the last four years
takeaway_test <- takeaway_data %>%
  filter(Month >= cutoff_date)

#  Display the structure of the training and test sets
takeaway_train
## # A tsibble: 3,064 x 4 [1M]
## # Key:       State [8]
##    State                        `Series ID`    Month Turnover
##    <chr>                        <chr>          <mth>    <dbl>
##  1 Australian Capital Territory A3349850K   1982 Apr      3.2
##  2 Australian Capital Territory A3349850K   1982 May      3.3
##  3 Australian Capital Territory A3349850K   1982 Jun      3.5
##  4 Australian Capital Territory A3349850K   1982 Jul      3.5
##  5 Australian Capital Territory A3349850K   1982 Aug      3.7
##  6 Australian Capital Territory A3349850K   1982 Sep      3.9
##  7 Australian Capital Territory A3349850K   1982 Oct      4  
##  8 Australian Capital Territory A3349850K   1982 Nov      4.3
##  9 Australian Capital Territory A3349850K   1982 Dec      4.3
## 10 Australian Capital Territory A3349850K   1983 Jan      3.9
## # ℹ 3,054 more rows
takeaway_test
## # A tsibble: 392 x 4 [1M]
## # Key:       State [8]
##    State                        `Series ID`    Month Turnover
##    <chr>                        <chr>          <mth>    <dbl>
##  1 Australian Capital Territory A3349850K   2014 Dec     21.1
##  2 Australian Capital Territory A3349850K   2015 Jan     17.3
##  3 Australian Capital Territory A3349850K   2015 Feb     17.3
##  4 Australian Capital Territory A3349850K   2015 Mar     19.9
##  5 Australian Capital Territory A3349850K   2015 Apr     20.1
##  6 Australian Capital Territory A3349850K   2015 May     20.6
##  7 Australian Capital Territory A3349850K   2015 Jun     20.5
##  8 Australian Capital Territory A3349850K   2015 Jul     21.5
##  9 Australian Capital Territory A3349850K   2015 Aug     21.3
## 10 Australian Capital Territory A3349850K   2015 Sep     20.9
## # ℹ 382 more rows

5b.

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

# 5b.Answer:


# Fit benchmark forecasting models to the training data
fit_benchmarks <- takeaway_train %>%
  model(
    Mean = MEAN(Turnover),
    Naive = NAIVE(Turnover),
    Seasonal_Naive = SNAIVE(Turnover),
  )

#  Generate forecasts for the test period using each benchmark model
fc_benchmarks <- fit_benchmarks %>%
  forecast(new_data = takeaway_test)

# Plot benchmark forecasts alongside actual values in the test set
fc_benchmarks %>%
  autoplot(takeaway_train, level = NULL) +
  autolayer(takeaway_test, Turnover, color = "yellow", linetype = "dashed") +
  labs(title = "Australian Takeaway Food Turnover: Benchmark Model Forecasts",
       x = "Date",
       y = "Turnover (AUD)") +
  theme_minimal()

5c.

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

# 5c.Answer:

# Calculate accuracy metrics for each benchmark model against the test set
accuracy_metrics <- fc_benchmarks %>%
  accuracy(takeaway_test)

# Display the table of accuracy metrics
accuracy_metrics
## # A tibble: 24 × 11
##    .model State         .type     ME   RMSE    MAE   MPE  MAPE  MASE RMSSE  ACF1
##    <chr>  <chr>         <chr>  <dbl>  <dbl>  <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
##  1 Mean   Australian C… Test   13.1   13.5   13.1  54.8   54.8   NaN   NaN 0.819
##  2 Mean   New South Wa… Test  316.   320.   316.   59.3   59.3   NaN   NaN 0.718
##  3 Mean   Northern Ter… Test    9.70   9.85   9.70 49.9   49.9   NaN   NaN 0.689
##  4 Mean   Queensland    Test  166.   167.   166.   53.1   53.1   NaN   NaN 0.198
##  5 Mean   South Austra… Test   43.6   44.2   43.6  48.9   48.9   NaN   NaN 0.551
##  6 Mean   Tasmania      Test   13.6   13.9   13.6  49.9   49.9   NaN   NaN 0.706
##  7 Mean   Victoria      Test  171.   173.   171.   52.9   52.9   NaN   NaN 0.609
##  8 Mean   Western Aust… Test   97.2   98.3   97.2  59.5   59.5   NaN   NaN 0.791
##  9 Naive  Australian C… Test    2.64   3.94   3.22  9.74  12.8   NaN   NaN 0.819
## 10 Naive  New South Wa… Test   74.6   89.9   77.3  13.3   14.0   NaN   NaN 0.718
## # ℹ 14 more rows
# Determine the model with the best performance based on the lowest RMSE value
best_model <- accuracy_metrics %>%
  filter(RMSE == min(RMSE)) %>%
  select(.model, RMSE, MAE, MAPE)

# Output the performance metrics for the best model
best_model
## # A tibble: 1 × 4
##   .model  RMSE   MAE  MAPE
##   <chr>  <dbl> <dbl> <dbl>
## 1 Naive   2.94  2.53  12.6
# The Naive model demonstrates the highest accuracy among the benchmarks..

5d.

Do the residuals from the best method resemble white noise?

# 5d.Answer:

# Extract the optimal model based on RMSE
best_fit <- fit_benchmarks %>%
  select(!!best_model$.model)

# Compute residuals for the optimal model using the training data
residuals_best <- residuals(best_fit)

# Assess autocorrelation in the residuals
acf_residuals <- residuals_best %>%
  ACF(.resid) %>%
  autoplot() +
  labs(title = "Autocorrelation Function (ACF) of Residuals from the Optimal Model")

# Create a histogram and QQ plot to evaluate the normality of residuals
hist_residuals <- residuals_best %>%
  ggplot(aes(x = .resid)) +
  geom_histogram(aes(y = ..density..), bins = 20, fill = "yellow", color = "black") +
  geom_density(color = "red") +
  labs(title = "Residuals Histogram", x = "Residuals", y = "Density")

qq_residuals <- residuals_best %>%
  ggplot(aes(sample = .resid)) +
  stat_qq() +
  stat_qq_line() +
  labs(title = "QQ Plot of Residuals", x = "Theoretical Quantiles", y = "Sample Quantiles")

# Display the visualizations
acf_residuals

hist_residuals

qq_residuals

#  The residuals exhibit some autocorrelation, as indicated by the ACF plot, and show deviations from normality in the QQ plot. This suggests that the model may not have fully captured all underlying patterns in the data, indicating some remaining structure in the residuals.

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_name <- unique(myseries$`Series ID`)
print(myseries_name)
## [1] "A3349767W"

6b.

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

# 6b.Answer:

model <- myseries %>%
  model(Linear_Trend = TSLM(Turnover ~ trend()))

6c.

See the regression result by report() command.

# 6c.Answer:

report(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

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 a forecast for the next 3 years (36 months)
forecast_values <- model %>%
  forecast(h = 36)

# Show the forecasted values
forecast_values %>%
  as_tibble() %>%
  select(Month, .mean) %>%
  print()
## # A tibble: 36 × 2
##       Month .mean
##       <mth> <dbl>
##  1 2019 Jan  14.9
##  2 2019 Feb  14.9
##  3 2019 Mar  15.0
##  4 2019 Apr  15.0
##  5 2019 May  15.0
##  6 2019 Jun  15.1
##  7 2019 Jul  15.1
##  8 2019 Aug  15.1
##  9 2019 Sep  15.2
## 10 2019 Oct  15.2
## # ℹ 26 more rows

6d.

Plot the forecast values along with the original data.

# 6d.Answer:
# Create a forecast for the next 3 years (36 months)
forecast_values <- model %>%
  forecast(h = 36)

# Vizualize the original data and  forecasted values
autoplot(myseries, Turnover) +
  autolayer(forecast_values, .mean, series = "Forecast", PI = FALSE) +
  labs(title = "3-Year Turnover Forecast",
       x = "Month",
       y = "Turnover (AUD)") +
  theme_minimal()

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:

gg_tsresiduals(model)

#The residuals show patterns, autocorrelation at lag 12, and deviations from normality, indicating they do not resemble white noise.

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:

# Visualize the relationship between Demand and Temperature
jan_vic_elec %>%
  ggplot(aes(x = Temperature, y = Demand)) +
  geom_point() +
  geom_smooth(method = "lm", se = FALSE, color = "red") +
  labs(title = "Relationship Between Daily Electricity Demand and Temperature (January 2014)",
       x = expression("Temperature ("* degree * "C)"),
       y = "Demand (MW)") +
  theme_minimal()
## `geom_smooth()` using formula = 'y ~ x'

# Fit a linear regression model using Temperature as a predictor for Demand

model <- jan_vic_elec %>%
  model(lm_model = TSLM(Demand ~ Temperature))

# The observed positive correlation between temperature and electricity demand suggests that higher temperatures drive up demand, likely due to increased air conditioning use. This trend is especially evident on hotter days, where cooling needs lead to a direct increase in electricity consumption.

7b.

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

# 7b.Answer:
gg_tsresiduals(model)

# The model may be insufficient, as the residuals show patterns and autocorrelation, suggesting potential outliers or influential points impacting the model's accuracy.

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:

electricity_demand_15 <- jan_vic_elec %>%
  model(TSLM(Demand ~ Temperature)) %>%
  forecast(
    new_data(jan_vic_elec, 1) %>%
      mutate(Temperature = 15)
  ) %>%
  autoplot(jan_vic_elec)+labs(title=expression("Projected Electricity Demand for Next Day with Max Temperature of 15" * degree * "C"))
electricity_demand_15

#Forecast electricity demand for the next day if the maximum temperature is 35°C

electricity_demand_35 <- jan_vic_elec %>%
  model(TSLM(Demand ~ Temperature)) %>%
  forecast(
    new_data(jan_vic_elec, 1) %>%
      mutate(Temperature = 35)
  ) %>%
  autoplot(jan_vic_elec)+labs(title=expression("Projected Electricity Demand for Next Day with Max Temperature of 35" * degree * "C"))
electricity_demand_35

# These forecasts offer a general indication of demand but should be interpreted with caution.

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:
#The forecast appears inaccurate, as the average demand has never dropped below 190000.

7e.

Give prediction intervals for your forecasts.

# 7e.Answer:

# Forecast and plot electricity demand for the next day assuming a maximum temperature of 15°C
electricity_demand_15 <- jan_vic_elec %>%
  model(TSLM(Demand ~ Temperature)) %>%
  forecast(
    new_data(jan_vic_elec, 1) %>%
      mutate(Temperature = 15)
  ) %>%
  autoplot(jan_vic_elec) +
  labs(title = expression("Next-Day Electricity Demand Forecast at Max Temperature of 15" * degree * "C"),
       y = "Electricity Demand (MW)", x = "Date")

# Display the forecast plot
print(electricity_demand_15)

# Forecast and plot electricity demand for the next day assuming a maximum temperature of 35°C
electricity_demand_35 <- jan_vic_elec %>%
  model(TSLM(Demand ~ Temperature)) %>%
  forecast(
    new_data(jan_vic_elec, 1) %>%
      mutate(Temperature = 35)
  ) %>%
  autoplot(jan_vic_elec) +
  labs(title = expression("Next-Day Electricity Demand Forecast at Max Temperature of 35"* degree * "C"),
       y = "Electricity Demand (MW)", x = "Date")

# Display the forecast plot
print(electricity_demand_35)

8.

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

#a. View the shampoo sales data. How many variables are there? Find how many rows and columns in the data?
  library(readxl)
shampoo <- read_excel("~/Business Forecating/Midterm/shampoo-2.xlsx")
dim(shampoo)
## [1] 36  2
#b. Is the data annual, monthly, quarterly?
unique(shampoo$Month)
##  [1] "1995-01-01 UTC" "1995-02-01 UTC" "1995-03-01 UTC" "1995-04-01 UTC"
##  [5] "1995-05-01 UTC" "1995-06-01 UTC" "1995-07-01 UTC" "1995-08-01 UTC"
##  [9] "1995-09-01 UTC" "1995-10-01 UTC" "1995-11-01 UTC" "1995-12-01 UTC"
## [13] "1996-01-01 UTC" "1996-02-01 UTC" "1996-03-01 UTC" "1996-04-01 UTC"
## [17] "1996-05-01 UTC" "1996-06-01 UTC" "1996-07-01 UTC" "1996-08-01 UTC"
## [21] "1996-09-01 UTC" "1996-10-01 UTC" "1996-11-01 UTC" "1996-12-01 UTC"
## [25] "1997-01-01 UTC" "1997-02-01 UTC" "1997-03-01 UTC" "1997-04-01 UTC"
## [29] "1997-05-01 UTC" "1997-06-01 UTC" "1997-07-01 UTC" "1997-08-01 UTC"
## [33] "1997-09-01 UTC" "1997-10-01 UTC" "1997-11-01 UTC" "1997-12-01 UTC"
#c. Convert the data into tibble , then tsibble 
shampoo <- shampoo %>%
  mutate(monthly = yearmonth(Month)) %>%
  select(-Month) %>%
  as_tibble() %>%
  as_tsibble(index = monthly)
  
#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.

plot(shampoo$monthly, shampoo$sales, type = "l", main = "Shampoo Sales Trends Over Time", xlab = "Date", ylab = "Sales")

autoplot(shampoo, sales) + 
  labs(title = "Shampoo Sales Trends Over Time", y = "Sales", x = "Date")

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

avg_sales <- mean(shampoo$sales, na.rm = TRUE)
median_sales <- median(shampoo$sales, na.rm = TRUE)

ggplot(shampoo, aes(x = sales)) +
  geom_histogram(binwidth = 50, fill = "yellow", alpha = 0.7) +
  labs(title = "Distribution of Shampoo Sales", x = "Sales", y = "Frequency") +
  geom_vline(aes(xintercept = avg_sales), color = "red", linetype = "dashed") +
  geom_vline(aes(xintercept = median_sales), color = "blue", linetype = "dashed")

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

#g. Get a linear regression line with trend and dummy for each month (Hint: use trend and season in regression equation).
lm_model <- shampoo %>%
  model(TSLM(sales ~ trend() + season()))
report(lm_model)
## Series: sales 
## Model: TSLM 
## 
## Residuals:
##     Min      1Q  Median      3Q     Max 
## -129.60  -62.32   -4.84   53.76  152.72 
## 
## Coefficients:
##                Estimate Std. Error t value Pr(>|t|)    
## (Intercept)     113.867     55.740   2.043   0.0527 .  
## trend()          11.754      1.534   7.664 8.88e-08 ***
## season()year2   -33.154     73.630  -0.450   0.6567    
## season()year3   -53.808     73.678  -0.730   0.4726    
## season()year4   -24.628     73.757  -0.334   0.7415    
## season()year5   -56.015     73.869  -0.758   0.4560    
## season()year6   -27.802     74.012  -0.376   0.7106    
## season()year7     7.244     74.187   0.098   0.9231    
## season()year8   -37.043     74.393  -0.498   0.6233    
## season()year9    27.536     74.629   0.369   0.7155    
## season()year10  -32.518     74.897  -0.434   0.6682    
## season()year11    9.895     75.194   0.132   0.8964    
## season()year12   -4.259     75.522  -0.056   0.9555    
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 90.16 on 23 degrees of freedom
## Multiple R-squared: 0.7592,  Adjusted R-squared: 0.6336
## F-statistic: 6.043 on 12 and 23 DF, p-value: 0.00011612
#h. Comment on each estimated coefficient of the model.Are they statistically significant at 5 % significance level?

#No, the majority of them are not statistically significant at the 5% significance level.
  
#i. Which month has the highest sales?
highest_sales_month <- shampoo %>%
  filter(sales == max(sales, na.rm = TRUE)) %>%
  select(monthly, sales)
print(highest_sales_month)
## # A tsibble: 1 x 2 [1M]
##    monthly sales
##      <mth> <dbl>
## 1 1997 Sep   682
#j. Forecast it for the next year. What are the values
  
forecast_next_year <- lm_model %>%
  forecast(h = "1 year")
print(forecast_next_year)
## # A fable: 12 x 4 [1M]
## # Key:     .model [1]
##    .model                            monthly
##    <chr>                               <mth>
##  1 TSLM(sales ~ trend() + season()) 1998 Jan
##  2 TSLM(sales ~ trend() + season()) 1998 Feb
##  3 TSLM(sales ~ trend() + season()) 1998 Mar
##  4 TSLM(sales ~ trend() + season()) 1998 Apr
##  5 TSLM(sales ~ trend() + season()) 1998 May
##  6 TSLM(sales ~ trend() + season()) 1998 Jun
##  7 TSLM(sales ~ trend() + season()) 1998 Jul
##  8 TSLM(sales ~ trend() + season()) 1998 Aug
##  9 TSLM(sales ~ trend() + season()) 1998 Sep
## 10 TSLM(sales ~ trend() + season()) 1998 Oct
## 11 TSLM(sales ~ trend() + season()) 1998 Nov
## 12 TSLM(sales ~ trend() + season()) 1998 Dec
## # ℹ 2 more variables: sales <dist>, .mean <dbl>
#k. Plot the forecast with original data.

autoplot(shampoo, sales) +
  autolayer(forecast_next_year, series = "Forecast", PI = TRUE) +
  labs(title = "Shampoo Sales Forecast", y = "Sales", x = "Date")

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

gg_tsresiduals(lm_model)

#The residuals do not seem to meet the criteria for white noise, as indicated by the presence of autocorrelation and discernible patterns.
  
#m. By using the regression model, forecast the 1 year ahead, and then check the accuracy of the forecast. What is MSE, RMSE values?

# Forecast for the next 12 months (1 year ahead)
forecast_next_year <- lm_model %>%
  forecast(h = "12 months")

# show forecasted values
print(forecast_next_year)
## # A fable: 12 x 4 [1M]
## # Key:     .model [1]
##    .model                            monthly
##    <chr>                               <mth>
##  1 TSLM(sales ~ trend() + season()) 1998 Jan
##  2 TSLM(sales ~ trend() + season()) 1998 Feb
##  3 TSLM(sales ~ trend() + season()) 1998 Mar
##  4 TSLM(sales ~ trend() + season()) 1998 Apr
##  5 TSLM(sales ~ trend() + season()) 1998 May
##  6 TSLM(sales ~ trend() + season()) 1998 Jun
##  7 TSLM(sales ~ trend() + season()) 1998 Jul
##  8 TSLM(sales ~ trend() + season()) 1998 Aug
##  9 TSLM(sales ~ trend() + season()) 1998 Sep
## 10 TSLM(sales ~ trend() + season()) 1998 Oct
## 11 TSLM(sales ~ trend() + season()) 1998 Nov
## 12 TSLM(sales ~ trend() + season()) 1998 Dec
## # ℹ 2 more variables: sales <dist>, .mean <dbl>
# Plotting the forecast and the original data
autoplot(shampoo, sales) +
  autolayer(forecast_next_year, series = "Forecast", PI = TRUE) +
  labs(title = "Shampoo Sales Forecast for Next Year", y = "Sales", x = "Date")

LS0tDQp0aXRsZTogIkVYQU0gSSINCmF1dGhvcjogQWtzaGl0aGEgVmFyYWRhLCBhdmFyYTNAdW5oLm5ld2hhdmVuLmVkdQ0KZGF0ZTogImByIFN5cy5EYXRlKClgIg0Kb3V0cHV0OiBvcGVuaW50cm86OmxhYl9yZXBvcnQNCiAgDQotLS0NCg0KYGBge3Igc2V0dXAsIGluY2x1ZGU9RkFMU0V9DQprbml0cjo6b3B0c19jaHVuayRzZXQoZWNobyA9IFRSVUUsIHdhcm5pbmc9RkFMU0UsIGVycm9yID0gRkFMU0UpDQoNCmBgYA0KDQoNCmBgYHtyIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9DQpsaWJyYXJ5KGZwcDMpDQpsaWJyYXJ5KHRpZHl2ZXJzZSkNClN5cy50aW1lKCkNCmBgYA0KDQojIyMgMS4JDQpDb25zaWRlciB0aGUgR0RQIGluZm9ybWF0aW9uIGluIGRhdGEgc2V0IGNhbGxlZCBnbG9iYWxfZWNvbm9teSwgd2hpY2ggaXMgYWxyZWFkeSBlbWJlZGRlZCBpbiBmcHAzIHBhY2thZ2UgKG5vIG5lZWQgdG8gdXBsb2FkIGV4dGVybmFsbHkpIA0KDQojIyMgMS4JQ2hvb3NlIGEgcmFuZG9tIGNvdW50cnkgYnkgeW91cnNlbGYuIFRoZW4gcGxvdCB0aGUgR0RQIHBlciBjYXBpdGEgZm9yIHRoaXMgY291bnRyeSBvdmVyIHRpbWU/IEhvdyBHRFAgcGVyIGNhcGl0YSBoYXMgY2hhbmdlZCBvdmVyIHRpbWUgZm9yIHRoZSBzZXJpZXMgeW91IGNob3NlPyBFeHBsYWluIGJyaWVmbHkuDQoNCmBgYHtyfQ0KZ2xvYmFsX2Vjb25vbXkgIyBzZWUgdGhlIGRhdGEuDQoNCg0KIyAxLkFuc3dlcjoNCg0KZ2RwX0luZGlhIDwtIGdsb2JhbF9lY29ub215ICU+JQ0KICBmaWx0ZXIoQ291bnRyeSA9PSAiSW5kaWEiKSAlPiUNCiAgbXV0YXRlKEdEUF9wZXJfY2FwaXRhID0gR0RQIC8gUG9wdWxhdGlvbikgJT4lDQogIHNlbGVjdChZZWFyLCBHRFBfcGVyX2NhcGl0YSkNCg0KDQphdXRvcGxvdChnZHBfSW5kaWEsIEdEUF9wZXJfY2FwaXRhKSArDQogIGxhYnModGl0bGUgPSAiSW5kaWEncyBHRFAgcGVyIENhcGl0YSBTaG93cyBHcmFkdWFsIEdyb3d0aCBmcm9tIDE5NjBzIHRvIDIwMDBzLFxuIHdpdGggUmFwaWQgSW5jcmVhc2UgaW4gUmVjZW50IFllYXJzLiIsDQogICAgICAgeCA9ICJZZWFyIiwNCiAgICAgICB5ID0gIkdEUCBwZXIgQ2FwaXRhIChVU0QpIikgKw0KICBnZW9tX3Ntb290aChtZXRob2QgPSAibG0iLCBzZSA9IEZBTFNFLCBjb2xvciA9ICJHcmVlbiIsIGxpbmV0eXBlID0gImRhc2hlZCIpICsNCiAgdGhlbWVfbWluaW1hbCgpDQoNCiNUaGUgR0RQIHBlciBjYXBpdGEgaW4gSW5kaWEgaGFzIGdlbmVyYWxseSBpbmNyZWFzZWQgb3ZlciB0aW1lLCB3aXRoIHN0ZWFkeSBncm93dGggZnJvbSB0aGUgMTk2MHMgdW50aWwgYSBzaGFycCBhY2NlbGVyYXRpb24gaW4gdGhlIGVhcmx5IDIwMDBzLiBUaGlzIHJlY2VudCByYXBpZCByaXNlIGhpZ2hsaWdodHMgc2lnbmlmaWNhbnQgZWNvbm9taWMgcHJvZ3Jlc3MsIGxpa2VseSBkcml2ZW4gYnkgc3RydWN0dXJhbCByZWZvcm1zIGFuZCB0ZWNobm9sb2dpY2FsIGFkdmFuY2VtZW50cy4NCg0KDQpgYGANCg0KIyMjIDIuCQ0KRm9yIGVhY2ggb2YgdGhlIGZvbGxvd2luZyBzZXJpZXMsIG1ha2UgYSBncmFwaCBvZiB0aGUgZGF0YS4gSWYgdHJhbnNmb3JtaW5nIHNlZW1zIGFwcHJvcHJpYXRlLCBkbyBzbyBhbmQgZGVzY3JpYmUgdGhlIGVmZmVjdC4gQ29tbWVudCBiZWxvdyBpbiBhbnN3ZXI6DQoNCiMjIyAyYS4gVXNlIHRoZSBzZXJpZXMgeW91IGNob3NlIGluICMxLg0KYGBge3J9DQoNCiMgMmEuQW5zd2VyOg0KDQpnZHBfSW5kaWEgPC0gZ2RwX0luZGlhJT4lDQogIG11dGF0ZShMb2dfR0RQX3Blcl9jYXBpdGEgPSBsb2coR0RQX3Blcl9jYXBpdGEpKQ0KDQphdXRvcGxvdChnZHBfSW5kaWEsIExvZ19HRFBfcGVyX2NhcGl0YSkgKw0KICBsYWJzKHRpdGxlID0gIlRoZSBsb2ctdHJhbnNmb3JtZWQgR0RQIHBlciBjYXBpdGEgZm9yIEluZGlhIHNob3dzIGEgY29uc2lzdGVudCB1cHdhcmRcbiB0cmVuZCBvdmVyIHRpbWUsIGluZGljYXRpbmcgc3RlYWR5IGVjb25vbWljIGdyb3d0aCB3aXRoXG4gcmVkdWNlZCB2YXJpYWJpbGl0eSBpbiByZWNlbnQgeWVhcnMuIiwNCiAgICAgICB4ID0gIlllYXIiLA0KICAgICAgIHkgPSAiTG9nIG9mIEdEUCBwZXIgQ2FwaXRhIikgKw0KICAgIGdlb21fc21vb3RoKG1ldGhvZCA9ICJsbSIsIHNlID0gRkFMU0UsIGNvbG9yID0gImdyZWVuIiwgbGluZXR5cGUgPSAiZGFzaGVkIikgKw0KICB0aGVtZV9taW5pbWFsKCkNCg0KDQpgYGANCg0KIyMjIDJiLgkNClVuaXRlZCBTdGF0ZXMgR0RQIGZyb20gZ2xvYmFsX2Vjb25vbXkuDQpgYGB7cn0NCg0KDQojIDJiLkFuc3dlcjoNCg0KZ2RwX3VzIDwtIGdsb2JhbF9lY29ub215ICU+JQ0KICBmaWx0ZXIoQ291bnRyeSA9PSAiVW5pdGVkIFN0YXRlcyIpICU+JQ0KICBzZWxlY3QoWWVhciwgR0RQKQ0KDQojICMgUGxvdHRpbmcgVVMgR0RQIG92ZXIgdGltZQ0KYXV0b3Bsb3QoZ2RwX3VzLCBHRFApICsNCiAgbGFicyh0aXRsZSA9ICJVLlMuIEdEUCBEZW1vbnN0cmF0ZXMgYSBTdHJvbmcgVXB3YXJkIFRyZW5kLCBHcm93aW5nIGZyb20gQXBwcm94aW1hdGVseSAkNSBUcmlsbGlvblxuIGluIHRoZSAxOTYwcyB0byBPdmVyICQyMCBUcmlsbGlvbiBieSAyMDIwLCBSZWZsZWN0aW5nIFN0ZWFkeSBFY29ub21pYyBHcm93dGhcbiBUaHJvdWdob3V0IHRoZSBEZWNhZGVzLiIsDQogICAgICAgeCA9ICJZZWFyIiwNCiAgICAgICB5ID0gIkdEUCAoVVNEKSIpICsNCiAgICBnZW9tX3Ntb290aChtZXRob2QgPSAibG0iLCBzZSA9IEZBTFNFLCBjb2xvciA9ICJncmVlbiIsIGxpbmV0eXBlID0gImRhc2hlZCIpICsNCiAgdGhlbWVfbWluaW1hbCgpDQoNCiMgVGhlIGdyYXBoIGlsbHVzdHJhdGVzIGEgY29uc2lzdGVudCBpbmNyZWFzZSBpbiBVLlMuIEdEUCBvdmVyIHRpbWUsIHNob3djYXNpbmcgc3RlYWR5IGVjb25vbWljIGdyb3d0aCwgd2l0aCBhbiBhY2NlbGVyYXRpbmcgdHJlbmQgb2JzZXJ2ZWQgaW4gcmVjZW50IGRlY2FkZXMuDQoNCmBgYA0KDQojIyMgMmMuCQ0KU2xhdWdodGVyIG9mIFZpY3RvcmlhbiDigJxCdWxscywgYnVsbG9ja3MgYW5kIHN0ZWVyc+KAnSBpbiBhdXNfbGl2ZXN0b2NrDQpgYGB7cn0NCg0KIyAyYy5BbnN3ZXI6DQoNCnZpY3Rvcmlhbl9jYXR0bGUgPC0gYXVzX2xpdmVzdG9jayAlPiUNCiAgZmlsdGVyKFN0YXRlID09ICJWaWN0b3JpYSIsIEFuaW1hbCA9PSAiQnVsbHMsIGJ1bGxvY2tzIGFuZCBzdGVlcnMiKQ0KDQojIFBsb3R0aW5nIHRoZSBudW1iZXIgb2Ygc2xhdWdodGVycyBvdmVyIHRpbWUNCmF1dG9wbG90KHZpY3Rvcmlhbl9jYXR0bGUsIENvdW50KSArDQogIGxhYnModGl0bGUgPSAiDQpUaGUgU2xhdWdodGVyIG9mIEJ1bGxzLCBCdWxsb2NrcywgYW5kIFN0ZWVycyBpbiBWaWN0b3JpYSBEZWNyZWFzZWQgZnJvbSBPdmVyXG4gMTI1LDAwMCBpbiB0aGUgMTk4MHMgdG8gQXBwcm94aW1hdGVseSA1MCwwMDAgaW4gUmVjZW50IFllYXJzLiIsDQogICAgICAgeCA9ICJZZWFyIiwNCiAgICAgICB5ID0gIkNvdW50IikgKw0KICAgIGdlb21fc21vb3RoKG1ldGhvZCA9ICJsbSIsIHNlID0gRkFMU0UsIGNvbG9yID0gImdyZWVuIiwgbGluZXR5cGUgPSAiZGFzaGVkIikgKw0KICB0aGVtZV9taW5pbWFsKCkNCg0KIyBUaGUgbnVtYmVyIG9mIGJ1bGxzLCBidWxsb2NrcywgYW5kIHN0ZWVycyBzbGF1Z2h0ZXJlZCBpbiBWaWN0b3JpYSBoYXMgZGVjcmVhc2VkIGZyb20gb3ZlciAxMjUsMDAwIGluIHRoZSAxOTgwcyB0byBhYm91dCA1MCwwMDAgaW4gcmVjZW50IHllYXJzLg0KYGBgDQoNCiMjIyAyZC4NClZpY3RvcmlhbiBFbGVjdHJpY2l0eSBEZW1hbmQgZnJvbSB2aWNfZWxlYy4NCmBgYHtyfQ0KDQoNCiMgMmQuQW5zd2VyOg0KDQp2aWNfZWxlY19tb250aGx5IDwtIHZpY19lbGVjICU+JQ0KICBpbmRleF9ieShNb250aCA9IH4geWVhcm1vbnRoKC4pKSAlPiUNCiAgc3VtbWFyaXNlKERlbWFuZCA9IG1lYW4oRGVtYW5kLCBuYS5ybSA9IFRSVUUpKQ0KDQoNCmF1dG9wbG90KHZpY19lbGVjX21vbnRobHksIERlbWFuZCkgKw0KICBsYWJzKHRpdGxlID0gIlZpY3RvcmlhbiBFbGVjdHJpY2l0eSBEZW1hbmQgRXhoaWJpdHMgU2Vhc29uYWwgUGVha3MgaW4gU3VtbWVyLFxuRGVtb25zdHJhdGluZyBhIERpc3RpbmN0IFNlYXNvbmFsIFRyZW5kLiIsDQogICAgICAgeCA9ICJEYXRlIiwNCiAgICAgICB5ID0gIkVsZWN0cmljaXR5IERlbWFuZCAoTVcpIikgKw0KICB0aGVtZV9taW5pbWFsKCkNCg0KI1RoZSBtb250aGx5IGF2ZXJhZ2UgZWxlY3RyaWNpdHkgZGVtYW5kIGluIFZpY3RvcmlhIHJldmVhbHMgYSBkaXN0aW5jdCBzZWFzb25hbCB0cmVuZCwgd2l0aCBwZWFrcyBnZW5lcmFsbHkgb2NjdXJyaW5nIGR1cmluZyB0aGUgc3VtbWVyIG1vbnRocywgbGlrZWx5IHJlZmxlY3RpbmcgaW5jcmVhc2VkIGRlbWFuZCBmb3IgY29vbGluZy4NCg0KYGBgDQoNCiMjIyAyZS4JDQpHYXMgcHJvZHVjdGlvbiBmcm9tIGF1c19wcm9kdWN0aW9uLg0KYGBge3J9DQoNCg0KIyAyZS5BbnN3ZXI6DQoNCmdhc19wcm9kdWN0aW9uIDwtIGF1c19wcm9kdWN0aW9uICU+JQ0KICBzZWxlY3QoUXVhcnRlciwgR2FzKQ0KDQoNCmF1dG9wbG90KGdhc19wcm9kdWN0aW9uLCBHYXMpICsNCiAgbGFicyh0aXRsZSA9ICJBdXN0cmFsaWFuIEdhcyBQcm9kdWN0aW9uIEluY3JlYXNlZCBmcm9tIEFwcHJveGltYXRlbHkgMCB0byBPdmVyIDI1MCBQZXRham91bGVzLFxuRXhoaWJpdGluZyBTaWduaWZpY2FudCBTZWFzb25hbCBQZWFrcyBUaHJvdWdob3V0IHRoZSBQZXJpb2QuIiwNCiAgICAgICB4ID0gIlllYXIiLA0KICAgICAgIHkgPSAiR2FzIFByb2R1Y3Rpb24gKGluIHBldGFqb3VsZXMpIikgKw0KICAgIGdlb21fc21vb3RoKG1ldGhvZCA9ICJsbSIsIHNlID0gRkFMU0UsIGNvbG9yID0gImdyZWVuIiwgbGluZXR5cGUgPSAiZGFzaGVkIikgKw0KICB0aGVtZV9taW5pbWFsKCkNCg0KI0F1c3RyYWxpYW4gZ2FzIHByb2R1Y3Rpb24gZGVtb25zdHJhdGVzIGEgY29uc2lzdGVudCB1cHdhcmQgdHJlbmQgd2l0aCBub3RhYmxlIHNlYXNvbmFsIHZhcmlhdGlvbnMsIGluZGljYXRpbmcgYm90aCBzdGVhZHkgZ3Jvd3RoIGFuZCByZWd1bGFyIHBlYWsgZGVtYW5kcyBsaWtlbHkgaW5mbHVlbmNlZCBieSBzZWFzb25hbCBjb25zdW1wdGlvbiBwYXR0ZXJucy4NCg0KYGBgDQoNCiMjIyAzLglVc2UgdGhlIGNhbmFkaWFuX2dhcyBkYXRhIChtb250aGx5IENhbmFkaWFuIGdhcyBwcm9kdWN0aW9uIGluIGJpbGxpb25zIG9mIGN1YmljIG1ldHJlcywgSmFudWFyeSAxOTYwIOKAkyBGZWJydWFyeSAyMDA1KS4NCiMjIyMgMmEuCVBsb3QgdGhlIGRhdGEgdXNpbmcgYXV0b3Bsb3QoKSwgZ2dfc3Vic2VyaWVzKCkgLCBnZ19zZWFzb24oKSB0byBsb29rIGF0IHRoZSBlZmZlY3Qgb2YgdGhlIGNoYW5naW5nIHNlYXNvbmFsaXR5IG92ZXIgdGltZS4gRGVzY3JpYmUgdGhlIGdyYXBocyBpbiB5b3VyIG93biB3b3Jkcy4gV2hhdCBkbyB5b3Ugc2VlPyBXaGF0IHR5cGUgcGYgcGF0dGVybiBkbyB5b3Ugb2JzZXJ2ZT8NCg0KYGBge3Igd2FybmluZz1GQUxTRSwgZXJyb3I9RkFMU0V9DQoNCiMgM2EuQW5zd2VyOg0KDQojIEdlbmVyYWwgdGltZSBzZXJpZXMgcGxvdA0KYXV0b3Bsb3QoY2FuYWRpYW5fZ2FzKSArDQogIGxhYnModGl0bGUgPSAiQ2FuYWRpYW4gTW9udGhseSBHYXMgUHJvZHVjdGlvbigxOTYw4oCTMjAwNSkiLA0KICAgICAgIHggPSAiWWVhciIsDQogICAgICAgeSA9ICJHYXMgUHJvZHVjdGlvbiAoQmlsbGlvbnMgb2YgQ3ViaWMgTWV0cmVzKSIpICsNCiAgdGhlbWVfbWluaW1hbCgpDQoNCiMgVGhlIHRpbWUgc2VyaWVzIHBsb3Qgc2hvd3MgYSBnZW5lcmFsIHVwd2FyZCB0cmVuZCBpbiBDYW5hZGlhbiBnYXMgcHJvZHVjdGlvbiBmcm9tIDE5NjAgdG8gMjAwNSwgd2l0aCB2aXNpYmxlIHNlYXNvbmFsIHZhcmlhdGlvbnMuIFRoZXNlIGZsdWN0dWF0aW9ucyBiZWNvbWUgbW9yZSBwcm9taW5lbnQgaW4gcmVjZW50IHllYXJzIGFzIHByb2R1Y3Rpb24gbGV2ZWxzIGluY3JlYXNlLg0KDQojIE1vbnRobHkgQnJlYWtkb3duIG9mIEdhcyBQcm9kdWN0aW9uDQpnZ19zdWJzZXJpZXMoY2FuYWRpYW5fZ2FzLCBWb2x1bWUpICsNCiAgbGFicyh0aXRsZSA9ICJNb250aGx5IFRyZW5kcyBpbiBDYW5hZGlhbiBHYXMgUHJvZHVjdGlvbiIsDQogICAgICAgeSA9ICJHYXMgUHJvZHVjdGlvbiAoQmlsbGlvbnMgb2YgQ3ViaWMgTWV0cmVzKSIpICsNCiAgdGhlbWVfbWluaW1hbCgpDQoNCiMgVGhlIG1vbnRobHkgc3Vic2VyaWVzIHBsb3QgcmV2ZWFscyBoaWdoZXIgcHJvZHVjdGlvbiBsZXZlbHMgaW4gd2ludGVyIG1vbnRocywgc3VjaCBhcyBKYW51YXJ5IGFuZCBGZWJydWFyeSwgbGlrZWx5IGR1ZSB0byBoaWdoZXIgZGVtYW5kIGZvciBoZWF0aW5nLiBQcm9kdWN0aW9uIGxldmVscyBhcmUgbG93ZXIgaW4gc3VtbWVyIG1vbnRocywgaW5kaWNhdGluZyBhIHJlZ3VsYXIgc2Vhc29uYWwgcGF0dGVybi4NCg0KIyBTZWFzb25hbCBWYXJpYXRpb24gaW4gR2FzIFByb2R1Y3Rpb24gT3ZlciBUaW1lDQpnZ19zZWFzb24oY2FuYWRpYW5fZ2FzLCBWb2x1bWUpICsNCiAgbGFicyh0aXRsZSA9ICJTZWFzb25hbCBQYXR0ZXJuIGluIENhbmFkaWFuIEdhcyBQcm9kdWN0aW9uIiwNCiAgICAgICB5ID0gIkdhcyBQcm9kdWN0aW9uIChCaWxsaW9ucyBvZiBDdWJpYyBNZXRyZXMpIikgKw0KICB0aGVtZV9taW5pbWFsKCkNCg0KIyBUaGUgc2Vhc29uYWwgcGxvdCBoaWdobGlnaHRzIGEgY29uc2lzdGVudCBwYXR0ZXJuLCB3aXRoIHByb2R1Y3Rpb24gcGVha2luZyBpbiBjb2xkZXIgbW9udGhzIGFuZCBkZWNyZWFzaW5nIGluIHdhcm1lciBtb250aHMuIFRoZSBhbXBsaXR1ZGUgb2YgdGhlc2Ugc2Vhc29uYWwgY2hhbmdlcyBpbmNyZWFzZXMgb3ZlciB0aW1lLCByZWZsZWN0aW5nIGEgZ3Jvd2luZyB2YXJpYXRpb24gaW4gcHJvZHVjdGlvbiBhcyBvdmVyYWxsIGxldmVscyByaXNlLg0KDQpgYGANCg0KIyMjIDNiLg0KRG8gYW4gU1RMIGRlY29tcG9zaXRpb24gb2YgdGhlIGRhdGEuIFlvdSB3aWxsIG5lZWQgdG8gY2hvb3NlIGEgc2Vhc29uYWwgd2luZG93IHRvIGFsbG93IGZvciB0aGUgY2hhbmdpbmcgc2hhcGUgb2YgdGhlIHNlYXNvbmFsIGNvbXBvbmVudC4NCg0KYGBge3J9DQoNCiMgM2IuQW5zd2VyOg0KDQpjYW5hZGlhbl9nYXNfc3RsIDwtIGNhbmFkaWFuX2dhcyAlPiUNCiAgbW9kZWwoU1RMKFZvbHVtZSB+IHNlYXNvbih3aW5kb3cgPSAicGVyaW9kaWMiKSkpDQoNCiMgUGxvdHRpbmcgRGVjb21wb3NpdGlvbiBDb21wb25lbnRzDQpjb21wb25lbnRzKGNhbmFkaWFuX2dhc19zdGwpICU+JQ0KICBhdXRvcGxvdCgpICsNCiAgbGFicyh0aXRsZSA9ICJTVEwgRGVjb21wb3NpdGlvbiBvZiBNb250aGx5IEdhcyBQcm9kdWN0aW9uIGluIENhbmFkYSIsDQogICAgICAgeCA9ICJZZWFyIikgKw0KICB0aGVtZV9taW5pbWFsKCkNCg0KIyAgVGhlIFNUTCBkZWNvbXBvc2l0aW9uIHNob3dzIGEgc3Ryb25nIGFuZCBncm93aW5nIHNlYXNvbmFsIHBhdHRlcm4gaW4gQ2FuYWRpYW4gZ2FzIHByb2R1Y3Rpb24sIHdpdGggcGVha3MgaW4gd2ludGVyIHJlZmxlY3RpbmcgaGlnaGVyIGRlbWFuZC4gVGhpcyBjb25maXJtcyB0aGUgc2Vhc29uYWwgdHJlbmRzIG9ic2VydmVkIGVhcmxpZXIuIFRoZSByZW1haW5kZXIgY29tcG9uZW50IHJldmVhbHMgYW55IGlycmVndWxhcml0aWVzIG9yIHVuZXhwZWN0ZWQgY2hhbmdlcyBpbiBwcm9kdWN0aW9uLCBwb3RlbnRpYWxseSBkdWUgdG8gZXh0ZXJuYWwgZmFjdG9ycyBvciBhbm9tYWxpZXMuDQpgYGANCg0KIyMjIDNjLg0KSG93IGRvZXMgdGhlIHNlYXNvbmFsIHNoYXBlIGNoYW5nZSBvdmVyIHRpbWU/IFtIaW50OiBUcnkgcGxvdHRpbmcgdGhlIHNlYXNvbmFsIGNvbXBvbmVudCB1c2luZyBnZ19zZWFzb24oKS5dDQpgYGB7cn0NCg0KDQojIDNjLkFuc3dlcjoNCg0KIyBQZXJmb3JtaW5nIFNUTCBkZWNvbXBvc2l0aW9uIHdpdGggYSBwZXJpb2RpYyBzZWFzb25hbCB3aW5kb3cNCmNhbmFkaWFuX2dhc19zdGwgPC0gY2FuYWRpYW5fZ2FzICU+JQ0KICBtb2RlbChTVExfZGVjb21wID0gU1RMKFZvbHVtZSB+IHNlYXNvbih3aW5kb3cgPSAicGVyaW9kaWMiKSkpDQoNCiMgRXh0cmFjdGluZyBjb21wb25lbnRzIGZyb20gdGhlIFNUTCBkZWNvbXBvc2l0aW9uDQpzZWFzb25hbF9jb21wb25lbnQgPC0gY2FuYWRpYW5fZ2FzX3N0bCAlPiUNCiAgY29tcG9uZW50cygpICU+JQ0KICBhc190c2liYmxlKCkgJT4lDQogIHNlbGVjdChNb250aCwgc2Vhc29uX2FkanVzdCkNCg0KZ2dfc2Vhc29uKHNlYXNvbmFsX2NvbXBvbmVudCwgc2Vhc29uX2FkanVzdCkgKw0KICBsYWJzKHRpdGxlID0gIkV2b2x1dGlvbiBvZiB0aGUgU2Vhc29uYWwgUGF0dGVybiBpbiBDYW5hZGlhbiBHYXMgUHJvZHVjdGlvbiIsDQogICAgICAgeSA9ICJTZWFzb25hbCBDb21wb25lbnQgKEJpbGxpb25zIG9mIEN1YmljIE1ldHJlcykiKSArDQogIHRoZW1lX21pbmltYWwoKQ0KDQojIFRoZSBzZWFzb25hbCBjb21wb25lbnQgc2hvd3MgcGVhayBwcm9kdWN0aW9uIGR1cmluZyB3aW50ZXIgbW9udGhzLCB3aXRoIHRoZSBhbXBsaXR1ZGUgb2YgdGhlc2UgcGVha3MgaW5jcmVhc2luZyBvdmVyIHRpbWUuIFRoaXMgdHJlbmQgc3VnZ2VzdHMgYSByaXNpbmcgZGVtYW5kIGZvciBnYXMgaW4gd2ludGVyIGFzIHByb2R1Y3Rpb24gbGV2ZWxzIGdyb3cuDQpgYGANCg0KIyMjIDNkLgkNCnByb2R1Y2UgYSBwbGF1c2libGUgc2Vhc29uYWxseSBhZGp1c3RlZCBzZXJpZXM/IFdoYXQgYXJlIHRoZXNlIG51bWJlcnMsIHBsb3QgdGhlIHNlcmllcy4NCmBgYHtyfQ0KDQojIDNkLkFuc3dlcjoNCg0KIyBQZXJmb3JtIFNUTCBkZWNvbXBvc2l0aW9uIHdpdGggYSBwZXJpb2RpYyBzZWFzb25hbCB3aW5kb3cNCmNhbmFkaWFuX2dhc19zdGwgPC0gY2FuYWRpYW5fZ2FzICU+JQ0KICBtb2RlbChTVExfZGVjb21wID0gU1RMKFZvbHVtZSB+IHNlYXNvbih3aW5kb3cgPSAicGVyaW9kaWMiKSkpDQoNCiMgR2VuZXJhdGUgdGhlIHNlYXNvbmFsbHkgYWRqdXN0ZWQgc2VyaWVzIGJ5IHJlbW92aW5nIHNlYXNvbmFsIGNvbXBvbmVudHMNCmNhbmFkaWFuX2dhc19zZWFzb25hbGx5X2FkanVzdGVkIDwtIGNvbXBvbmVudHMoY2FuYWRpYW5fZ2FzX3N0bCkgJT4lDQogIG11dGF0ZShTZWFzb25hbGx5X0FkanVzdGVkID0gVm9sdW1lIC0gc2Vhc29uX3llYXIpICU+JQ0KICBzZWxlY3QoTW9udGgsIFNlYXNvbmFsbHlfQWRqdXN0ZWQpDQoNCiMgVmlzdWFsaXplIHRoZSBzZWFzb25hbGx5IGFkanVzdGVkIHNlcmllcw0KYXV0b3Bsb3QoY2FuYWRpYW5fZ2FzX3NlYXNvbmFsbHlfYWRqdXN0ZWQsIFNlYXNvbmFsbHlfQWRqdXN0ZWQpICsNCiAgbGFicyh0aXRsZSA9ICJUcmVuZCBpbiBTZWFzb25hbGx5IEFkanVzdGVkIENhbmFkaWFuIEdhcyBQcm9kdWN0aW9uIiwNCiAgICAgICB4ID0gIlllYXIiLA0KICAgICAgIHkgPSAiR2FzIFByb2R1Y3Rpb24gKEJpbGxpb25zIG9mIEN1YmljIE1ldHJlcykiKSArDQogICAgZ2VvbV9zbW9vdGgobWV0aG9kID0gImxtIiwgc2UgPSBGQUxTRSwgY29sb3IgPSAiZ3JlZW4iLCBsaW5ldHlwZSA9ICJkYXNoZWQiKSArDQogIHRoZW1lX21pbmltYWwoKQ0KDQojIFRoZSBzZWFzb25hbGx5IGFkanVzdGVkIHNlcmllcyByZXZlYWxzIGEgY2xlYXIgdXB3YXJkIHRyZW5kIGluIENhbmFkaWFuIGdhcyBwcm9kdWN0aW9uIGZyb20gdGhlIDE5NjBzIHRvIHRoZSBlYXJseSAyMDAwcywgaGlnaGxpZ2h0aW5nIGNvbnNpc3RlbnQgZ3Jvd3RoIGluIHByb2R1Y3Rpb24gaW5kZXBlbmRlbnQgb2Ygc2Vhc29uYWwgZmx1Y3R1YXRpb25zLg0KYGBgDQoNCg0KIyMjIDQuDQpGb3IgcmV0YWlsIHRpbWUgc2VyaWVzLCB1c2UgdGhlIGJlbG93IGNvZGU6DQoNCmBgYHtyfQ0KIyBydW4gdGhlIGNvZGUNCnNldC5zZWVkKDEyMzQ1Njc4KQ0KDQpteXNlcmllcyA8LSBhdXNfcmV0YWlsICU+JQ0KICBmaWx0ZXIoYFNlcmllcyBJRGAgPT0gc2FtcGxlKGF1c19yZXRhaWwkYFNlcmllcyBJRGAsMSkpDQoNCg0KYGBgDQoNCiMjIyMgNGEuIA0KQ3JlYXRlIGEgdHJhaW5pbmcgZGF0YXNldCBjb25zaXN0aW5nIG9mIG9ic2VydmF0aW9ucyBiZWZvcmUgMjAxMSANCg0KYGBge3J9DQpteXNlcmllc190cmFpbiA8LSBteXNlcmllcyAlPiUNCiAgZmlsdGVyKHllYXIoTW9udGgpIDwgMjAxMSkNCg0KDQpgYGANCg0KIyMjIyA0Yi4JDQpDaGVjayB0aGF0IHlvdXIgZGF0YSBoYXZlIGJlZW4gc3BsaXQgYXBwcm9wcmlhdGVseSBieSBwcm9kdWNpbmcgdGhlIGZvbGxvd2luZyBwbG90Lg0KDQpgYGB7cn0NCmF1dG9wbG90KG15c2VyaWVzLCBUdXJub3ZlcikgKw0KICBhdXRvbGF5ZXIobXlzZXJpZXNfdHJhaW4sIFR1cm5vdmVyLCBjb2xvdXIgPSAicmVkIikNCmBgYA0KDQojIyMjIDRjLgkNCkZpdCBhIHNlYXNvbmFsIG5hw692ZSBtb2RlbCB1c2luZyBTTkFJVkUoKSBhcHBsaWVkIHRvIHlvdXIgdHJhaW5pbmcgZGF0YSAobXlzZXJpZXNfdHJhaW4pLg0KYGBge3J9DQogI0Fuc3dlcjoNCiAgICBmaXQgPC0gbXlzZXJpZXNfdHJhaW4gJT4lDQogICAgICBtb2RlbChTTkFJVkUoVHVybm92ZXIpKQ0KYGBgDQoNCg0KIyMjIyA0ZC4NCkNoZWNrIHRoZSByZXNpZHVhbHMuDQpgYGB7cn0NCg0KIyA0ZCBBbnN3ZXI6DQoNCmZpdCAlPiUgZ2dfdHNyZXNpZHVhbHMoKQ0KDQojIERvIHRoZSByZXNpZHVhbHMgYXBwZWFyIHRvIGJlIHVuY29ycmVsYXRlZCBhbmQgbm9ybWFsbHkgZGlzdHJpYnV0ZWQ/DQojIEFuc3c6IFRoZSByZXNpZHVhbHMgZGlzcGxheSBhbiBhcHByb3hpbWF0ZWx5IG5vcm1hbCBkaXN0cmlidXRpb24sIGZvcm1pbmcgYSBiZWxsLXNoYXBlZCBjdXJ2ZSBjZW50ZXJlZCBhcm91bmQgemVybywgc3VnZ2VzdGluZyB0aGV5IG1heSBiZSBub3JtYWxseSBkaXN0cmlidXRlZC4NCmBgYA0KDQojIyMjIDRlLg0KUHJvZHVjZSBmb3JlY2FzdHMgZm9yIHRoZSB0ZXN0IGRhdGEgd2l0aCBnaXZlbiBjb2RlIGJlbG93Og0KDQpgYGB7cn0NCiMgNGUgQW5zd2VyOg0KZmMgPC0gZml0ICU+JSAgDQpmb3JlY2FzdChuZXdfZGF0YSA9IGFudGlfam9pbihteXNlcmllcywgbXlzZXJpZXNfdHJhaW4pKQ0KZmMgJT4lIGF1dG9wbG90KG15c2VyaWVzKQ0KDQpgYGANCg0KSm9pbmluZywgYnkgPSBjKCJTdGF0ZSIsICJJbmR1c3RyeSIsICJTZXJpZXMgSUQiLCAiTW9udGgiLCAiVHVybm92ZXIiKQ0KDQojIyMjIDRmLgkNCkNvbXBhcmUgdGhlIGFjY3VyYWN5IG9mIHlvdXIgZm9yZWNhc3RzIGFnYWluc3QgdGhlIGFjdHVhbCB2YWx1ZXMgd2l0aCBnaXZlbiBjb2RlIGJlbG93Og0KYGBge3J9DQpmaXQgJT4lIGFjY3VyYWN5KCkNCmZjICU+JSBhY2N1cmFjeShteXNlcmllcykNCiMgNGYgQW5zdzoNCg0KZmMgPC0gZm9yZWNhc3QoZml0KQ0KYXV0b3Bsb3QoZmMsIG15c2VyaWVzKQ0KYWNjdXJhY3koZmMsIG15c2VyaWVzKQ0KDQojIFRoZSBtb2RlbCBpcyBxdWl0ZSBhY2N1cmF0ZSBjb25zaWRlcmluZyB0aGUgUk1TRSBTY29yZSBvZiAxLjIyODA4OQ0KYGBgDQoNCiMjIyMgNGcuDQpIb3cgc2Vuc2l0aXZlIGFyZSB0aGUgYWNjdXJhY3kgbWVhc3VyZXMgdG8gdGhlIGFtb3VudCBvZiB0cmFpbmluZyBkYXRhIHVzZWQ/DQpgYGB7cn0NCg0KIyA0ZyBBbnN3ZXI6IFRoZSBhY2N1cmFjeSBtZWFzdXJlcyBhcmUgaW5mbHVlbmNlZCBieSB0aGUgcXVhbnRpdHkgb2YgdHJhaW5pbmcgZGF0YSB1c2VkOyB3aXRoIGxpbWl0ZWQgZGF0YSwgZXJyb3JzIG1heSBpbmNyZWFzZSwgYW5kIG1ldHJpY3Mgc3VjaCBhcyBSTVNFLCBNQUUsIGFuZCBNQVBFIGNhbiBiZWNvbWUgbGVzcyBzdGFibGUuDQoNCmBgYA0KDQojIyMgNS4JDQojIyMjIDVhLgkNCkNyZWF0ZSBhIHRyYWluaW5nIHNldCBmb3IgQXVzdHJhbGlhbiB0YWtlYXdheSBmb29kIHR1cm5vdmVyIChhdXNfcmV0YWlsKSBieSB3aXRoaG9sZGluZyB0aGUgbGFzdCBmb3VyIHllYXJzIGFzIGEgdGVzdCBzZXQuIA0KYGBge3J9DQoNCg0KIyA1YS5BbnN3ZXI6DQoNCiMgRmlsdGVyIHRoZSBhdXNfcmV0YWlsIGRhdGFzZXQgdG8gaW5jbHVkZSBvbmx5IHRha2Vhd2F5IGZvb2QgdHVybm92ZXIgZGF0YQ0KdGFrZWF3YXlfZGF0YSA8LSBhdXNfcmV0YWlsICU+JQ0KICBmaWx0ZXIoSW5kdXN0cnkgPT0gIlRha2Vhd2F5IGZvb2Qgc2VydmljZXMiKSAlPiUNCiAgc2VsZWN0KC1JbmR1c3RyeSkgICMgRHJvcCB0aGUgSW5kdXN0cnkgY29sdW1uDQoNCiNTZXQgdGhlIGN1dG9mZiBkYXRlIGJ5IHN1YnRyYWN0aW5nIDQ4IG1vbnRocyAoNCB5ZWFycykgZnJvbSB0aGUgbGF0ZXN0IGRhdGUgaW4gdGhlIGRhdGFzZXQNCmN1dG9mZl9kYXRlIDwtIG1heCh0YWtlYXdheV9kYXRhJE1vbnRoKSAtIDQ4IA0KDQojIERlZmluZSB0aGUgdHJhaW5pbmcgc2V0IHdpdGggZGF0YSBiZWZvcmUgdGhlIGN1dG9mZiBkYXRlDQp0YWtlYXdheV90cmFpbiA8LSB0YWtlYXdheV9kYXRhICU+JQ0KICBmaWx0ZXIoTW9udGggPCBjdXRvZmZfZGF0ZSkNCg0KIyBEZWZpbmUgdGhlIHRlc3Qgc2V0IHdpdGggZGF0YSBmcm9tIHRoZSBsYXN0IGZvdXIgeWVhcnMNCnRha2Vhd2F5X3Rlc3QgPC0gdGFrZWF3YXlfZGF0YSAlPiUNCiAgZmlsdGVyKE1vbnRoID49IGN1dG9mZl9kYXRlKQ0KDQojICBEaXNwbGF5IHRoZSBzdHJ1Y3R1cmUgb2YgdGhlIHRyYWluaW5nIGFuZCB0ZXN0IHNldHMNCnRha2Vhd2F5X3RyYWluDQp0YWtlYXdheV90ZXN0DQoNCg0KYGBgDQoNCiMjIyMgNWIuCQ0KRml0IGFsbCB0aGUgYXBwcm9wcmlhdGUgYmVuY2htYXJrIG1ldGhvZHMgdG8gdGhlICAgdHJhaW5pbmcgc2V0IGFuZCBmb3JlY2FzdCB0aGUgcGVyaW9kcyBjb3ZlcmVkIGJ5IHRoZSB0ZXN0IHNldC4NCmBgYHtyfQ0KDQojIDViLkFuc3dlcjoNCg0KDQojIEZpdCBiZW5jaG1hcmsgZm9yZWNhc3RpbmcgbW9kZWxzIHRvIHRoZSB0cmFpbmluZyBkYXRhDQpmaXRfYmVuY2htYXJrcyA8LSB0YWtlYXdheV90cmFpbiAlPiUNCiAgbW9kZWwoDQogICAgTWVhbiA9IE1FQU4oVHVybm92ZXIpLA0KICAgIE5haXZlID0gTkFJVkUoVHVybm92ZXIpLA0KICAgIFNlYXNvbmFsX05haXZlID0gU05BSVZFKFR1cm5vdmVyKSwNCiAgKQ0KDQojICBHZW5lcmF0ZSBmb3JlY2FzdHMgZm9yIHRoZSB0ZXN0IHBlcmlvZCB1c2luZyBlYWNoIGJlbmNobWFyayBtb2RlbA0KZmNfYmVuY2htYXJrcyA8LSBmaXRfYmVuY2htYXJrcyAlPiUNCiAgZm9yZWNhc3QobmV3X2RhdGEgPSB0YWtlYXdheV90ZXN0KQ0KDQojIFBsb3QgYmVuY2htYXJrIGZvcmVjYXN0cyBhbG9uZ3NpZGUgYWN0dWFsIHZhbHVlcyBpbiB0aGUgdGVzdCBzZXQNCmZjX2JlbmNobWFya3MgJT4lDQogIGF1dG9wbG90KHRha2Vhd2F5X3RyYWluLCBsZXZlbCA9IE5VTEwpICsNCiAgYXV0b2xheWVyKHRha2Vhd2F5X3Rlc3QsIFR1cm5vdmVyLCBjb2xvciA9ICJ5ZWxsb3ciLCBsaW5ldHlwZSA9ICJkYXNoZWQiKSArDQogIGxhYnModGl0bGUgPSAiQXVzdHJhbGlhbiBUYWtlYXdheSBGb29kIFR1cm5vdmVyOiBCZW5jaG1hcmsgTW9kZWwgRm9yZWNhc3RzIiwNCiAgICAgICB4ID0gIkRhdGUiLA0KICAgICAgIHkgPSAiVHVybm92ZXIgKEFVRCkiKSArDQogIHRoZW1lX21pbmltYWwoKQ0KDQpgYGANCg0KIyMjIyA1Yy4JDQpDb21wdXRlIHRoZSBhY2N1cmFjeSBvZiB5b3VyIGZvcmVjYXN0cy4gV2hpY2ggbWV0aG9kIGRvZXMgYmVzdD8NCmBgYHtyfQ0KDQoNCiMgNWMuQW5zd2VyOg0KDQojIENhbGN1bGF0ZSBhY2N1cmFjeSBtZXRyaWNzIGZvciBlYWNoIGJlbmNobWFyayBtb2RlbCBhZ2FpbnN0IHRoZSB0ZXN0IHNldA0KYWNjdXJhY3lfbWV0cmljcyA8LSBmY19iZW5jaG1hcmtzICU+JQ0KICBhY2N1cmFjeSh0YWtlYXdheV90ZXN0KQ0KDQojIERpc3BsYXkgdGhlIHRhYmxlIG9mIGFjY3VyYWN5IG1ldHJpY3MNCmFjY3VyYWN5X21ldHJpY3MNCg0KIyBEZXRlcm1pbmUgdGhlIG1vZGVsIHdpdGggdGhlIGJlc3QgcGVyZm9ybWFuY2UgYmFzZWQgb24gdGhlIGxvd2VzdCBSTVNFIHZhbHVlDQpiZXN0X21vZGVsIDwtIGFjY3VyYWN5X21ldHJpY3MgJT4lDQogIGZpbHRlcihSTVNFID09IG1pbihSTVNFKSkgJT4lDQogIHNlbGVjdCgubW9kZWwsIFJNU0UsIE1BRSwgTUFQRSkNCg0KIyBPdXRwdXQgdGhlIHBlcmZvcm1hbmNlIG1ldHJpY3MgZm9yIHRoZSBiZXN0IG1vZGVsDQpiZXN0X21vZGVsDQoNCiMgVGhlIE5haXZlIG1vZGVsIGRlbW9uc3RyYXRlcyB0aGUgaGlnaGVzdCBhY2N1cmFjeSBhbW9uZyB0aGUgYmVuY2htYXJrcy4uDQoNCmBgYA0KDQojIyMjIDVkLg0KRG8gdGhlIHJlc2lkdWFscyBmcm9tIHRoZSBiZXN0IG1ldGhvZCByZXNlbWJsZSB3aGl0ZSBub2lzZT8NCmBgYHtyfQ0KDQojIDVkLkFuc3dlcjoNCg0KIyBFeHRyYWN0IHRoZSBvcHRpbWFsIG1vZGVsIGJhc2VkIG9uIFJNU0UNCmJlc3RfZml0IDwtIGZpdF9iZW5jaG1hcmtzICU+JQ0KICBzZWxlY3QoISFiZXN0X21vZGVsJC5tb2RlbCkNCg0KIyBDb21wdXRlIHJlc2lkdWFscyBmb3IgdGhlIG9wdGltYWwgbW9kZWwgdXNpbmcgdGhlIHRyYWluaW5nIGRhdGENCnJlc2lkdWFsc19iZXN0IDwtIHJlc2lkdWFscyhiZXN0X2ZpdCkNCg0KIyBBc3Nlc3MgYXV0b2NvcnJlbGF0aW9uIGluIHRoZSByZXNpZHVhbHMNCmFjZl9yZXNpZHVhbHMgPC0gcmVzaWR1YWxzX2Jlc3QgJT4lDQogIEFDRigucmVzaWQpICU+JQ0KICBhdXRvcGxvdCgpICsNCiAgbGFicyh0aXRsZSA9ICJBdXRvY29ycmVsYXRpb24gRnVuY3Rpb24gKEFDRikgb2YgUmVzaWR1YWxzIGZyb20gdGhlIE9wdGltYWwgTW9kZWwiKQ0KDQojIENyZWF0ZSBhIGhpc3RvZ3JhbSBhbmQgUVEgcGxvdCB0byBldmFsdWF0ZSB0aGUgbm9ybWFsaXR5IG9mIHJlc2lkdWFscw0KaGlzdF9yZXNpZHVhbHMgPC0gcmVzaWR1YWxzX2Jlc3QgJT4lDQogIGdncGxvdChhZXMoeCA9IC5yZXNpZCkpICsNCiAgZ2VvbV9oaXN0b2dyYW0oYWVzKHkgPSAuLmRlbnNpdHkuLiksIGJpbnMgPSAyMCwgZmlsbCA9ICJ5ZWxsb3ciLCBjb2xvciA9ICJibGFjayIpICsNCiAgZ2VvbV9kZW5zaXR5KGNvbG9yID0gInJlZCIpICsNCiAgbGFicyh0aXRsZSA9ICJSZXNpZHVhbHMgSGlzdG9ncmFtIiwgeCA9ICJSZXNpZHVhbHMiLCB5ID0gIkRlbnNpdHkiKQ0KDQpxcV9yZXNpZHVhbHMgPC0gcmVzaWR1YWxzX2Jlc3QgJT4lDQogIGdncGxvdChhZXMoc2FtcGxlID0gLnJlc2lkKSkgKw0KICBzdGF0X3FxKCkgKw0KICBzdGF0X3FxX2xpbmUoKSArDQogIGxhYnModGl0bGUgPSAiUVEgUGxvdCBvZiBSZXNpZHVhbHMiLCB4ID0gIlRoZW9yZXRpY2FsIFF1YW50aWxlcyIsIHkgPSAiU2FtcGxlIFF1YW50aWxlcyIpDQoNCiMgRGlzcGxheSB0aGUgdmlzdWFsaXphdGlvbnMNCmFjZl9yZXNpZHVhbHMNCmhpc3RfcmVzaWR1YWxzDQpxcV9yZXNpZHVhbHMNCg0KIyAgVGhlIHJlc2lkdWFscyBleGhpYml0IHNvbWUgYXV0b2NvcnJlbGF0aW9uLCBhcyBpbmRpY2F0ZWQgYnkgdGhlIEFDRiBwbG90LCBhbmQgc2hvdyBkZXZpYXRpb25zIGZyb20gbm9ybWFsaXR5IGluIHRoZSBRUSBwbG90LiBUaGlzIHN1Z2dlc3RzIHRoYXQgdGhlIG1vZGVsIG1heSBub3QgaGF2ZSBmdWxseSBjYXB0dXJlZCBhbGwgdW5kZXJseWluZyBwYXR0ZXJucyBpbiB0aGUgZGF0YSwgaW5kaWNhdGluZyBzb21lIHJlbWFpbmluZyBzdHJ1Y3R1cmUgaW4gdGhlIHJlc2lkdWFscy4NCmBgYA0KDQoNCiMjIyA2LgkNClVzaW5nIHRoZSBjb2RlIGJlbG93LCBnZXQgYSBzZXJpZXMgKGl0IGdldHMgYSBzZXJpZXMgcmFuZG9tbHkgYnkgdXNpbmcgc2FtcGxlKCkgZnVuY3Rpb24pOg0KDQpgYGB7cn0NCnNldC5zZWVkKDEyMzQ1Njc4KQ0KbXlzZXJpZXMgPC0gYXVzX3JldGFpbCAlPiUNCiAgZmlsdGVyKGBTZXJpZXMgSURgID09IHNhbXBsZShhdXNfcmV0YWlsJGBTZXJpZXMgSURgLDEpKQ0KYGBgDQpzZWUgaGVhZCBvZiB5b3VyIHNlcmllcyB0byBjaGVjayBpdCBpcyBhIHRzaWJibGUgZGF0YSwgYW5kIHJlbW92ZSBOQeKAmXMgaWYgdGhlcmUgaXMgYW55IHdpdGggdGhlc2UgY29tbWFuZHM6DQoNCmBgYHtyfQ0KaGVhZChteXNlcmllcykNCm15c2VyaWVzID0gIG15c2VyaWVzICU+JSBmaWx0ZXIoIWlzLm5hKGBTZXJpZXMgSURgKSkNCmBgYA0KDQojIyMjIDZhLg0KV2hhdCBpcyB0aGUgbmFtZSBvZiB0aGUgc2VyaWVzIHlvdSByYW5kb21seSBjaG9vc2U/IFdyaXRlIGl0Lg0KYGBge3J9DQoNCiMgNmEuQW5zd2VyOg0KDQpteXNlcmllc19uYW1lIDwtIHVuaXF1ZShteXNlcmllcyRgU2VyaWVzIElEYCkNCnByaW50KG15c2VyaWVzX25hbWUpDQoNCg0KYGBgDQoNCiMjIyMgNmIuIA0KUnVuIGEgbGluZWFyIHJlZ3Jlc3Npb24gb2YgVHVybm92ZXIgb24gdHJlbmQuKEhpbnQ6IHVzZSBUU0xNKCkgYW5kIHRyZW5kKCkgZnVuY3Rpb25zKQ0KYGBge3J9DQojIDZiLkFuc3dlcjoNCg0KbW9kZWwgPC0gbXlzZXJpZXMgJT4lDQogIG1vZGVsKExpbmVhcl9UcmVuZCA9IFRTTE0oVHVybm92ZXIgfiB0cmVuZCgpKSkNCg0KDQoNCmBgYA0KDQojIyMjIDZjLiANClNlZSB0aGUgcmVncmVzc2lvbiByZXN1bHQgYnkgcmVwb3J0KCkgY29tbWFuZC4NCmBgYHtyfQ0KIyA2Yy5BbnN3ZXI6DQoNCnJlcG9ydChtb2RlbCkNCmBgYA0KDQoNCiMjIyMgNmQuCQ0KQnkgdXNpbmcgdGhpcyBtb2RlbCwgZm9yZWNhc3QgaXQgZm9yIHRoZSBuZXh0IDMgeWVhcnMuIFdoYXQgYXJlIHRoZSB2YWx1ZXMgb2YgdGhlIG5leHQgMyB5ZWFycywgbW9udGhseSB2YWx1ZXM/DQpgYGB7cn0NCg0KIyA2ZC5BbnN3ZXI6DQojIENyZWF0ZSBhIGZvcmVjYXN0IGZvciB0aGUgbmV4dCAzIHllYXJzICgzNiBtb250aHMpDQpmb3JlY2FzdF92YWx1ZXMgPC0gbW9kZWwgJT4lDQogIGZvcmVjYXN0KGggPSAzNikNCg0KIyBTaG93IHRoZSBmb3JlY2FzdGVkIHZhbHVlcw0KZm9yZWNhc3RfdmFsdWVzICU+JQ0KICBhc190aWJibGUoKSAlPiUNCiAgc2VsZWN0KE1vbnRoLCAubWVhbikgJT4lDQogIHByaW50KCkNCg0KDQpgYGANCg0KIyMjIyA2ZC4JDQpQbG90IHRoZSBmb3JlY2FzdCB2YWx1ZXMgYWxvbmcgd2l0aCB0aGUgb3JpZ2luYWwgZGF0YS4NCmBgYHtyfQ0KDQojIDZkLkFuc3dlcjoNCiMgQ3JlYXRlIGEgZm9yZWNhc3QgZm9yIHRoZSBuZXh0IDMgeWVhcnMgKDM2IG1vbnRocykNCmZvcmVjYXN0X3ZhbHVlcyA8LSBtb2RlbCAlPiUNCiAgZm9yZWNhc3QoaCA9IDM2KQ0KDQojIFZpenVhbGl6ZSB0aGUgb3JpZ2luYWwgZGF0YSBhbmQgIGZvcmVjYXN0ZWQgdmFsdWVzDQphdXRvcGxvdChteXNlcmllcywgVHVybm92ZXIpICsNCiAgYXV0b2xheWVyKGZvcmVjYXN0X3ZhbHVlcywgLm1lYW4sIHNlcmllcyA9ICJGb3JlY2FzdCIsIFBJID0gRkFMU0UpICsNCiAgbGFicyh0aXRsZSA9ICIzLVllYXIgVHVybm92ZXIgRm9yZWNhc3QiLA0KICAgICAgIHggPSAiTW9udGgiLA0KICAgICAgIHkgPSAiVHVybm92ZXIgKEFVRCkiKSArDQogIHRoZW1lX21pbmltYWwoKQ0KDQoNCmBgYA0KDQojIyMjIDZlLgkNCkdldCB0aGUgcmVzaWR1YWxzIGZyb20gdGhlIG1vZGVsLiBBbmQgY2hlY2sgdGhlIHJlc2lkdWFscyB0byBjaGVjayB3aGV0aGVyIG9yIG5vdCBpdCBzYXRpc2ZpZXMgdGhlIHJlcXVpcmVtZW50cyBmb3Igd2hpdGUgbm9pc2UgZXJyb3IgdGVybXMuKGhpbnQ6IGF1Z21lbnQoKSBhbmQgZ2dfdHNyZXNpZHVhbHMoKSBmdW5jdGlvbnMpDQoNCmBgYHtyfQ0KDQojIDZlLkFuc3dlcjoNCg0KZ2dfdHNyZXNpZHVhbHMobW9kZWwpDQoNCiNUaGUgcmVzaWR1YWxzIHNob3cgcGF0dGVybnMsIGF1dG9jb3JyZWxhdGlvbiBhdCBsYWcgMTIsIGFuZCBkZXZpYXRpb25zIGZyb20gbm9ybWFsaXR5LCBpbmRpY2F0aW5nIHRoZXkgZG8gbm90IHJlc2VtYmxlIHdoaXRlIG5vaXNlLg0KDQpgYGANCg0KDQojIyMgNy4gDQpIYWxmLWhvdXJseSBlbGVjdHJpY2l0eSBkZW1hbmQgZm9yIFZpY3RvcmlhLCBBdXN0cmFsaWEgaXMgY29udGFpbmVkIGluIHZpY19lbGVjLiBFeHRyYWN0IHRoZSBKYW51YXJ5IDIwMTQgZWxlY3RyaWNpdHkgZGVtYW5kLCBhbmQgYWdncmVnYXRlIHRoaXMgZGF0YSB0byBkYWlseSB3aXRoICBkYWlseSB0b3RhbCBkZW1hbmRzIGFuZCBtYXhpbXVtIHRlbXBlcmF0dXJlcy4gUnVuIHRoZSBjb2RlIGJlbG93Og0KDQpgYGB7cn0NCmphbl92aWNfZWxlYyA8LSB2aWNfZWxlYyAlPiUNCiAgZmlsdGVyKHllYXJtb250aChUaW1lKSA9PSB5ZWFybW9udGgoIjIwMTQgSmFuIikpICU+JQ0KICBpbmRleF9ieShEYXRlID0gYXNfZGF0ZShUaW1lKSkgJT4lDQogIHN1bW1hcmlzZShEZW1hbmQgPSBzdW0oRGVtYW5kKSwgVGVtcGVyYXR1cmUgPSBtYXgoVGVtcGVyYXR1cmUpKQ0KDQpgYGANCg0KIyMjIyA3YS4gDQpQbG90IHRoZSBkYXRhIGFuZCBmaW5kIHRoZSByZWdyZXNzaW9uIG1vZGVsIGZvciBEZW1hbmQgd2l0aCB0ZW1wZXJhdHVyZSBhcyBhIHByZWRpY3RvciB2YXJpYWJsZS4gV2h5IGlzIHRoZXJlIGEgcG9zaXRpdmUgcmVsYXRpb25zaGlwPw0KYGBge3J9DQoNCiMgN2EuQW5zd2VyOg0KDQojIFZpc3VhbGl6ZSB0aGUgcmVsYXRpb25zaGlwIGJldHdlZW4gRGVtYW5kIGFuZCBUZW1wZXJhdHVyZQ0KamFuX3ZpY19lbGVjICU+JQ0KICBnZ3Bsb3QoYWVzKHggPSBUZW1wZXJhdHVyZSwgeSA9IERlbWFuZCkpICsNCiAgZ2VvbV9wb2ludCgpICsNCiAgZ2VvbV9zbW9vdGgobWV0aG9kID0gImxtIiwgc2UgPSBGQUxTRSwgY29sb3IgPSAicmVkIikgKw0KICBsYWJzKHRpdGxlID0gIlJlbGF0aW9uc2hpcCBCZXR3ZWVuIERhaWx5IEVsZWN0cmljaXR5IERlbWFuZCBhbmQgVGVtcGVyYXR1cmUgKEphbnVhcnkgMjAxNCkiLA0KICAgICAgIHggPSBleHByZXNzaW9uKCJUZW1wZXJhdHVyZSAoIiogZGVncmVlICogIkMpIiksDQogICAgICAgeSA9ICJEZW1hbmQgKE1XKSIpICsNCiAgdGhlbWVfbWluaW1hbCgpDQoNCiMgRml0IGEgbGluZWFyIHJlZ3Jlc3Npb24gbW9kZWwgdXNpbmcgVGVtcGVyYXR1cmUgYXMgYSBwcmVkaWN0b3IgZm9yIERlbWFuZA0KDQptb2RlbCA8LSBqYW5fdmljX2VsZWMgJT4lDQogIG1vZGVsKGxtX21vZGVsID0gVFNMTShEZW1hbmQgfiBUZW1wZXJhdHVyZSkpDQoNCiMgVGhlIG9ic2VydmVkIHBvc2l0aXZlIGNvcnJlbGF0aW9uIGJldHdlZW4gdGVtcGVyYXR1cmUgYW5kIGVsZWN0cmljaXR5IGRlbWFuZCBzdWdnZXN0cyB0aGF0IGhpZ2hlciB0ZW1wZXJhdHVyZXMgZHJpdmUgdXAgZGVtYW5kLCBsaWtlbHkgZHVlIHRvIGluY3JlYXNlZCBhaXIgY29uZGl0aW9uaW5nIHVzZS4gVGhpcyB0cmVuZCBpcyBlc3BlY2lhbGx5IGV2aWRlbnQgb24gaG90dGVyIGRheXMsIHdoZXJlIGNvb2xpbmcgbmVlZHMgbGVhZCB0byBhIGRpcmVjdCBpbmNyZWFzZSBpbiBlbGVjdHJpY2l0eSBjb25zdW1wdGlvbi4NCg0KDQpgYGANCg0KIyMjIyA3Yi4gDQpQcm9kdWNlIGEgcmVzaWR1YWwgcGxvdC4gSXMgdGhlIG1vZGVsIGFkZXF1YXRlPyBBcmUgdGhlcmUgYW55IG91dGxpZXJzIG9yIGluZmx1ZW50aWFsIG9ic2VydmF0aW9ucz8NCg0KYGBge3J9DQoNCiMgN2IuQW5zd2VyOg0KZ2dfdHNyZXNpZHVhbHMobW9kZWwpDQoNCiMgVGhlIG1vZGVsIG1heSBiZSBpbnN1ZmZpY2llbnQsIGFzIHRoZSByZXNpZHVhbHMgc2hvdyBwYXR0ZXJucyBhbmQgYXV0b2NvcnJlbGF0aW9uLCBzdWdnZXN0aW5nIHBvdGVudGlhbCBvdXRsaWVycyBvciBpbmZsdWVudGlhbCBwb2ludHMgaW1wYWN0aW5nIHRoZSBtb2RlbCdzIGFjY3VyYWN5Lg0KDQpgYGANCg0KIyMjIyA3Yy4NClVzZSB0aGUgbW9kZWwgdG8gZm9yZWNhc3QgdGhlIGVsZWN0cmljaXR5IGRlbWFuZCB0aGF0IHlvdSB3b3VsZCBleHBlY3QgZm9yIHRoZSBuZXh0IGRheSBpZiB0aGUgbWF4aW11bSB0ZW1wZXJhdHVyZSB3YXMgMTXiiJhDIGFuZCBjb21wYXJlIGl0IHdpdGggdGhlIGZvcmVjYXN0IGlmIHRoZSB3aXRoIG1heGltdW0gdGVtcGVyYXR1cmUgd2FzIDM14oiYQy4gRG8geW91IGJlbGlldmUgdGhlc2UgZm9yZWNhc3RzPw0KDQpgYGB7cn0NCg0KIyA3Yy5BbnN3ZXI6DQoNCmVsZWN0cmljaXR5X2RlbWFuZF8xNSA8LSBqYW5fdmljX2VsZWMgJT4lDQogIG1vZGVsKFRTTE0oRGVtYW5kIH4gVGVtcGVyYXR1cmUpKSAlPiUNCiAgZm9yZWNhc3QoDQogICAgbmV3X2RhdGEoamFuX3ZpY19lbGVjLCAxKSAlPiUNCiAgICAgIG11dGF0ZShUZW1wZXJhdHVyZSA9IDE1KQ0KICApICU+JQ0KICBhdXRvcGxvdChqYW5fdmljX2VsZWMpK2xhYnModGl0bGU9ZXhwcmVzc2lvbigiUHJvamVjdGVkIEVsZWN0cmljaXR5IERlbWFuZCBmb3IgTmV4dCBEYXkgd2l0aCBNYXggVGVtcGVyYXR1cmUgb2YgMTUiICogZGVncmVlICogIkMiKSkNCmVsZWN0cmljaXR5X2RlbWFuZF8xNQ0KDQojRm9yZWNhc3QgZWxlY3RyaWNpdHkgZGVtYW5kIGZvciB0aGUgbmV4dCBkYXkgaWYgdGhlIG1heGltdW0gdGVtcGVyYXR1cmUgaXMgMzXCsEMNCg0KZWxlY3RyaWNpdHlfZGVtYW5kXzM1IDwtIGphbl92aWNfZWxlYyAlPiUNCiAgbW9kZWwoVFNMTShEZW1hbmQgfiBUZW1wZXJhdHVyZSkpICU+JQ0KICBmb3JlY2FzdCgNCiAgICBuZXdfZGF0YShqYW5fdmljX2VsZWMsIDEpICU+JQ0KICAgICAgbXV0YXRlKFRlbXBlcmF0dXJlID0gMzUpDQogICkgJT4lDQogIGF1dG9wbG90KGphbl92aWNfZWxlYykrbGFicyh0aXRsZT1leHByZXNzaW9uKCJQcm9qZWN0ZWQgRWxlY3RyaWNpdHkgRGVtYW5kIGZvciBOZXh0IERheSB3aXRoIE1heCBUZW1wZXJhdHVyZSBvZiAzNSIgKiBkZWdyZWUgKiAiQyIpKQ0KZWxlY3RyaWNpdHlfZGVtYW5kXzM1DQoNCiMgVGhlc2UgZm9yZWNhc3RzIG9mZmVyIGEgZ2VuZXJhbCBpbmRpY2F0aW9uIG9mIGRlbWFuZCBidXQgc2hvdWxkIGJlIGludGVycHJldGVkIHdpdGggY2F1dGlvbi4NCg0KYGBgDQoNCiMjIyMgN2QuDQpEbyB5b3UgYmVsaWV2ZSB0aGVzZSBmb3JlY2FzdHM/IFRoZSBmb2xsb3dpbmcgUiBjb2RlIHdpbGwgZ2V0IHlvdSBzdGFydGVkOg0KYGBge3J9DQogamFuX3ZpY19lbGVjICU+JQ0KICBtb2RlbChUU0xNKERlbWFuZCB+IFRlbXBlcmF0dXJlKSkgJT4lDQogIGZvcmVjYXN0KA0KICAgIG5ld19kYXRhKGphbl92aWNfZWxlYywgMSkgJT4lDQogICAgICBtdXRhdGUoVGVtcGVyYXR1cmUgPSAxNSkNCiAgKSAlPiUNCiAgYXV0b3Bsb3QoamFuX3ZpY19lbGVjKQ0KYGBgDQogIA0KYGBge3J9DQoNCiMgN2QuQW5zd2VyOg0KI1RoZSBmb3JlY2FzdCBhcHBlYXJzIGluYWNjdXJhdGUsIGFzIHRoZSBhdmVyYWdlIGRlbWFuZCBoYXMgbmV2ZXIgZHJvcHBlZCBiZWxvdyAxOTAwMDAuDQoNCmBgYA0KIA0KIyMjIyA3ZS4gDQpHaXZlIHByZWRpY3Rpb24gaW50ZXJ2YWxzIGZvciB5b3VyIGZvcmVjYXN0cy4NCg0KYGBge3J9DQojIDdlLkFuc3dlcjoNCg0KIyBGb3JlY2FzdCBhbmQgcGxvdCBlbGVjdHJpY2l0eSBkZW1hbmQgZm9yIHRoZSBuZXh0IGRheSBhc3N1bWluZyBhIG1heGltdW0gdGVtcGVyYXR1cmUgb2YgMTXCsEMNCmVsZWN0cmljaXR5X2RlbWFuZF8xNSA8LSBqYW5fdmljX2VsZWMgJT4lDQogIG1vZGVsKFRTTE0oRGVtYW5kIH4gVGVtcGVyYXR1cmUpKSAlPiUNCiAgZm9yZWNhc3QoDQogICAgbmV3X2RhdGEoamFuX3ZpY19lbGVjLCAxKSAlPiUNCiAgICAgIG11dGF0ZShUZW1wZXJhdHVyZSA9IDE1KQ0KICApICU+JQ0KICBhdXRvcGxvdChqYW5fdmljX2VsZWMpICsNCiAgbGFicyh0aXRsZSA9IGV4cHJlc3Npb24oIk5leHQtRGF5IEVsZWN0cmljaXR5IERlbWFuZCBGb3JlY2FzdCBhdCBNYXggVGVtcGVyYXR1cmUgb2YgMTUiICogZGVncmVlICogIkMiKSwNCiAgICAgICB5ID0gIkVsZWN0cmljaXR5IERlbWFuZCAoTVcpIiwgeCA9ICJEYXRlIikNCg0KIyBEaXNwbGF5IHRoZSBmb3JlY2FzdCBwbG90DQpwcmludChlbGVjdHJpY2l0eV9kZW1hbmRfMTUpDQoNCiMgRm9yZWNhc3QgYW5kIHBsb3QgZWxlY3RyaWNpdHkgZGVtYW5kIGZvciB0aGUgbmV4dCBkYXkgYXNzdW1pbmcgYSBtYXhpbXVtIHRlbXBlcmF0dXJlIG9mIDM1wrBDDQplbGVjdHJpY2l0eV9kZW1hbmRfMzUgPC0gamFuX3ZpY19lbGVjICU+JQ0KICBtb2RlbChUU0xNKERlbWFuZCB+IFRlbXBlcmF0dXJlKSkgJT4lDQogIGZvcmVjYXN0KA0KICAgIG5ld19kYXRhKGphbl92aWNfZWxlYywgMSkgJT4lDQogICAgICBtdXRhdGUoVGVtcGVyYXR1cmUgPSAzNSkNCiAgKSAlPiUNCiAgYXV0b3Bsb3QoamFuX3ZpY19lbGVjKSArDQogIGxhYnModGl0bGUgPSBleHByZXNzaW9uKCJOZXh0LURheSBFbGVjdHJpY2l0eSBEZW1hbmQgRm9yZWNhc3QgYXQgTWF4IFRlbXBlcmF0dXJlIG9mIDM1IiogZGVncmVlICogIkMiKSwNCiAgICAgICB5ID0gIkVsZWN0cmljaXR5IERlbWFuZCAoTVcpIiwgeCA9ICJEYXRlIikNCg0KIyBEaXNwbGF5IHRoZSBmb3JlY2FzdCBwbG90DQpwcmludChlbGVjdHJpY2l0eV9kZW1hbmRfMzUpDQoNCg0KDQpgYGANCg0KDQojIyMgOC4NClJlYWQgdGhlIHNoYW1wb28gZGF0YSBnaXZlbiBpbiBleGNlbCAoSW1wb3J0IERhdGFzZXQgYXMgRXhjZWwpDQogIA0KYGBge3J9DQojYS4JVmlldyB0aGUgc2hhbXBvbyBzYWxlcyBkYXRhLiBIb3cgbWFueSB2YXJpYWJsZXMgYXJlIHRoZXJlPyBGaW5kIGhvdyBtYW55IHJvd3MgYW5kIGNvbHVtbnMgaW4gdGhlIGRhdGE/DQogIGxpYnJhcnkocmVhZHhsKQ0Kc2hhbXBvbyA8LSByZWFkX2V4Y2VsKCJ+L0J1c2luZXNzIEZvcmVjYXRpbmcvTWlkdGVybS9zaGFtcG9vLTIueGxzeCIpDQpkaW0oc2hhbXBvbykNCg0KI2IuCUlzIHRoZSBkYXRhIGFubnVhbCwgbW9udGhseSwgcXVhcnRlcmx5Pw0KdW5pcXVlKHNoYW1wb28kTW9udGgpDQogIA0KI2MuCUNvbnZlcnQgdGhlIGRhdGEgaW50byB0aWJibGUgLCB0aGVuIHRzaWJibGUgDQpzaGFtcG9vIDwtIHNoYW1wb28gJT4lDQogIG11dGF0ZShtb250aGx5ID0geWVhcm1vbnRoKE1vbnRoKSkgJT4lDQogIHNlbGVjdCgtTW9udGgpICU+JQ0KICBhc190aWJibGUoKSAlPiUNCiAgYXNfdHNpYmJsZShpbmRleCA9IG1vbnRobHkpDQogIA0KI2QuCVBsb3QgdGhlIHNoYW1wb28gc2FsZXMuIFdoYXQgZG8geW91IHNlZSBmcm9tIHRoZSBkYXRhIHBhdHRlcm4/IFdoYXQgZG9lcyB4LWF4aXMgcmVwcmVzZW50PyANCiMgQ29tbWVudCBoZXJlLiBVc2UgcGxvdCgpIGFuZCBhdXRvcGxvdCgpLlB1dCB0aGUgbmFtZSBmb3IgeSBheGlzLCBhbmQgYSB0aXRsZSBmb3IgdGhlIGdyYXBoLg0KDQpwbG90KHNoYW1wb28kbW9udGhseSwgc2hhbXBvbyRzYWxlcywgdHlwZSA9ICJsIiwgbWFpbiA9ICJTaGFtcG9vIFNhbGVzIFRyZW5kcyBPdmVyIFRpbWUiLCB4bGFiID0gIkRhdGUiLCB5bGFiID0gIlNhbGVzIikNCg0KYXV0b3Bsb3Qoc2hhbXBvbywgc2FsZXMpICsgDQogIGxhYnModGl0bGUgPSAiU2hhbXBvbyBTYWxlcyBUcmVuZHMgT3ZlciBUaW1lIiwgeSA9ICJTYWxlcyIsIHggPSAiRGF0ZSIpDQogIA0KI2UuCVdoYXQgaXMgdGhlIGF2ZXJhZ2UsIGFuZCBtZWRpYW4gb2Ygc2hhbXBvbyBzYWxlcy4gUHV0IGl0IG9uIGEgaGlzdG9ncmFtLg0KDQphdmdfc2FsZXMgPC0gbWVhbihzaGFtcG9vJHNhbGVzLCBuYS5ybSA9IFRSVUUpDQptZWRpYW5fc2FsZXMgPC0gbWVkaWFuKHNoYW1wb28kc2FsZXMsIG5hLnJtID0gVFJVRSkNCg0KZ2dwbG90KHNoYW1wb28sIGFlcyh4ID0gc2FsZXMpKSArDQogIGdlb21faGlzdG9ncmFtKGJpbndpZHRoID0gNTAsIGZpbGwgPSAieWVsbG93IiwgYWxwaGEgPSAwLjcpICsNCiAgbGFicyh0aXRsZSA9ICJEaXN0cmlidXRpb24gb2YgU2hhbXBvbyBTYWxlcyIsIHggPSAiU2FsZXMiLCB5ID0gIkZyZXF1ZW5jeSIpICsNCiAgZ2VvbV92bGluZShhZXMoeGludGVyY2VwdCA9IGF2Z19zYWxlcyksIGNvbG9yID0gInJlZCIsIGxpbmV0eXBlID0gImRhc2hlZCIpICsNCiAgZ2VvbV92bGluZShhZXMoeGludGVyY2VwdCA9IG1lZGlhbl9zYWxlcyksIGNvbG9yID0gImJsdWUiLCBsaW5ldHlwZSA9ICJkYXNoZWQiKQ0KDQogIA0KI2YuCUdldCBzZWFzb25hbCBwbG90LiBXaGF0IGRvIHlvdSBzZWUvIGlzIHRoZXJlIGFueSBwYXR0ZXJuLCBpcyB0ZWhyZSBhbnkgc2Vhc29uYWxpdHkuDQpnZ19zZWFzb24oc2hhbXBvbywgc2FsZXMpICsNCiAgbGFicyh0aXRsZSA9ICJTZWFzb25hbCBQbG90IG9mIFNoYW1wb28gU2FsZXMiLCB5ID0gIlNhbGVzIiwgeCA9ICJNb250aCIpDQogIA0KI2cuCUdldCBhIGxpbmVhciByZWdyZXNzaW9uIGxpbmUgd2l0aCB0cmVuZCBhbmQgZHVtbXkgZm9yIGVhY2ggbW9udGggKEhpbnQ6IHVzZSB0cmVuZCBhbmQgc2Vhc29uIGluIHJlZ3Jlc3Npb24gZXF1YXRpb24pLg0KbG1fbW9kZWwgPC0gc2hhbXBvbyAlPiUNCiAgbW9kZWwoVFNMTShzYWxlcyB+IHRyZW5kKCkgKyBzZWFzb24oKSkpDQpyZXBvcnQobG1fbW9kZWwpDQogIA0KI2guCUNvbW1lbnQgb24gZWFjaCBlc3RpbWF0ZWQgY29lZmZpY2llbnQgb2YgdGhlIG1vZGVsLkFyZSB0aGV5IHN0YXRpc3RpY2FsbHkgc2lnbmlmaWNhbnQgYXQgNSAlIHNpZ25pZmljYW5jZSBsZXZlbD8NCg0KI05vLCB0aGUgbWFqb3JpdHkgb2YgdGhlbSBhcmUgbm90IHN0YXRpc3RpY2FsbHkgc2lnbmlmaWNhbnQgYXQgdGhlIDUlIHNpZ25pZmljYW5jZSBsZXZlbC4NCiAgDQojaS4JV2hpY2ggbW9udGggaGFzIHRoZSBoaWdoZXN0IHNhbGVzPw0KaGlnaGVzdF9zYWxlc19tb250aCA8LSBzaGFtcG9vICU+JQ0KICBmaWx0ZXIoc2FsZXMgPT0gbWF4KHNhbGVzLCBuYS5ybSA9IFRSVUUpKSAlPiUNCiAgc2VsZWN0KG1vbnRobHksIHNhbGVzKQ0KcHJpbnQoaGlnaGVzdF9zYWxlc19tb250aCkNCg0KICANCiNqLglGb3JlY2FzdCBpdCBmb3IgdGhlIG5leHQgeWVhci4gV2hhdCBhcmUgdGhlIHZhbHVlcw0KICANCmZvcmVjYXN0X25leHRfeWVhciA8LSBsbV9tb2RlbCAlPiUNCiAgZm9yZWNhc3QoaCA9ICIxIHllYXIiKQ0KcHJpbnQoZm9yZWNhc3RfbmV4dF95ZWFyKQ0KDQojay4JUGxvdCB0aGUgZm9yZWNhc3Qgd2l0aCBvcmlnaW5hbCBkYXRhLg0KDQphdXRvcGxvdChzaGFtcG9vLCBzYWxlcykgKw0KICBhdXRvbGF5ZXIoZm9yZWNhc3RfbmV4dF95ZWFyLCBzZXJpZXMgPSAiRm9yZWNhc3QiLCBQSSA9IFRSVUUpICsNCiAgbGFicyh0aXRsZSA9ICJTaGFtcG9vIFNhbGVzIEZvcmVjYXN0IiwgeSA9ICJTYWxlcyIsIHggPSAiRGF0ZSIpDQogIA0KI2wuCUNoZWNrIGlmIHRoZSByZXNpZHVhbHMgb2YgdGhlIG1vZGVsIGlzIHdoaXRlIG5vaXNlLg0KDQpnZ190c3Jlc2lkdWFscyhsbV9tb2RlbCkNCg0KI1RoZSByZXNpZHVhbHMgZG8gbm90IHNlZW0gdG8gbWVldCB0aGUgY3JpdGVyaWEgZm9yIHdoaXRlIG5vaXNlLCBhcyBpbmRpY2F0ZWQgYnkgdGhlIHByZXNlbmNlIG9mIGF1dG9jb3JyZWxhdGlvbiBhbmQgZGlzY2VybmlibGUgcGF0dGVybnMuDQogIA0KI20uCUJ5IHVzaW5nIHRoZSByZWdyZXNzaW9uIG1vZGVsLCBmb3JlY2FzdCB0aGUgMSB5ZWFyIGFoZWFkLCBhbmQgdGhlbiBjaGVjayB0aGUgYWNjdXJhY3kgb2YgdGhlIGZvcmVjYXN0LiBXaGF0IGlzIE1TRSwgUk1TRSB2YWx1ZXM/DQoNCiMgRm9yZWNhc3QgZm9yIHRoZSBuZXh0IDEyIG1vbnRocyAoMSB5ZWFyIGFoZWFkKQ0KZm9yZWNhc3RfbmV4dF95ZWFyIDwtIGxtX21vZGVsICU+JQ0KICBmb3JlY2FzdChoID0gIjEyIG1vbnRocyIpDQoNCiMgc2hvdyBmb3JlY2FzdGVkIHZhbHVlcw0KcHJpbnQoZm9yZWNhc3RfbmV4dF95ZWFyKQ0KDQojIFBsb3R0aW5nIHRoZSBmb3JlY2FzdCBhbmQgdGhlIG9yaWdpbmFsIGRhdGENCmF1dG9wbG90KHNoYW1wb28sIHNhbGVzKSArDQogIGF1dG9sYXllcihmb3JlY2FzdF9uZXh0X3llYXIsIHNlcmllcyA9ICJGb3JlY2FzdCIsIFBJID0gVFJVRSkgKw0KICBsYWJzKHRpdGxlID0gIlNoYW1wb28gU2FsZXMgRm9yZWNhc3QgZm9yIE5leHQgWWVhciIsIHkgPSAiU2FsZXMiLCB4ID0gIkRhdGUiKQ0KICANCg0KYGBgDQogICAgDQo=