library(fpp3)
library(tidyverse)
Sys.time()
## [1] "2025-03-26 15:23:45 EDT"

1.

Consider the GDP information in data set called global_economy, which is already embedded in fpp3 package (no need to upload externally)

1. Choose a random country by yourself. Then plot the GDP per capita for this country over time? How GDP per capita has changed over time for the series you chose? Explain briefly.

# Choose a random country
random_country <- "Brazil"  # You can change this to any country

# Filter the data for the chosen country
gdp_data <- global_economy %>%
  filter(Country == random_country) %>%
  mutate(GDP_per_capita = GDP / Population)  # Calculate GDP per capita

# Plot GDP per capita over time
gdp_data %>%
  autoplot(GDP_per_capita) +
  labs(title = paste("GDP per Capita for", random_country),  # Changed to random_country
       y = "GDP per Capita (USD)")

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:
# Plot the GDP per capita series
gdp_data %>%
  autoplot(GDP_per_capita) +
  labs(title = paste("GDP per Capita for", random_country), y = "GDP per Capita")

2b.

United States GDP from global_economy.

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

# Plot GDP over time
us_gdp %>%
  autoplot(GDP) +
  labs(title = "United States GDP Over Time", y = "GDP")

2c.

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

# 2c.Answer:
# Filter data for Victorian bulls, bullocks, and steers
victorian_slaughter <- aus_livestock %>%
  filter(Animal == "Bulls, bullocks and steers", State == "Victoria")

# Plot the data
victorian_slaughter %>%
  autoplot(Count) +
  labs(title = "Slaughter of Victorian Bulls, Bullocks, and Steers", y = "Count")

2d.

Victorian Electricity Demand from vic_elec.

# 2d.Answer:
# Plot Victorian electricity demand
vic_elec %>%
  autoplot(Demand) +
  labs(title = "Victorian Electricity Demand", y = "Demand")

2e.

Gas production from aus_production.

# 2e.Answer:
# Plot gas production
aus_production %>%
  autoplot(Gas) +
  labs(title = "Australian Gas Production", y = "Gas Production")

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:
# Plot the data
canadian_gas %>%
  autoplot(Volume) +
  labs(title = "Canadian Gas Production", y = "Volume")

# Subseries plot
canadian_gas %>%
  gg_subseries(Volume) +
  labs(title = "Canadian Gas Production by Month", y = "Volume")

# Seasonal plot
canadian_gas %>%
  gg_season(Volume) +
  labs(title = "Seasonal Plot of Canadian Gas Production", y = "Volume")

3b.

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

# 3b.Answer:
# STL decomposition
stl_decomp <- canadian_gas %>%
  model(STL(Volume ~ trend() + season())) %>%
  components()

# Plot the decomposition
autoplot(stl_decomp)

3c.

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

# 3c.Answer:
# Plot the seasonal component
stl_decomp %>%
  gg_season(season_year) +
  labs(title = "Seasonal Component Over Time", y = "Seasonal")

3d.

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

# 3d.Answer:
# Plot the seasonally adjusted series
stl_decomp %>%
  autoplot(season_adjust) +
  labs(title = "Seasonally Adjusted Canadian Gas Production", y = "Volume")

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:
# Check residuals
gg_tsresiduals(fit)

4e.

Produce forecasts for the test data with given code below:

# 4e Answer:
# Forecast for the test data
fc <- fit %>%
  forecast(new_data = anti_join(myseries, myseries_train))

# Plot the forecasts
fc %>%
  autoplot(myseries) +
  labs(title = "Forecasts for Test Data", y = "Turnover")

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:

4g.

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

# 4g Answer:
#The accuracy measures are sensitive to the amount of training data used. More training data generally improves model performance.

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:
# Create training data
takeaway_train <- aus_retail %>%
  filter(Industry == "Takeaway food services", year(Month) < max(year(Month)) - 4)

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
fit_benchmark <- takeaway_train %>%
  model(
    Mean = MEAN(Turnover),
    Naive = NAIVE(Turnover),
    Seasonal_Naive = SNAIVE(Turnover)
  )

5c.

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

# 5c.Answer:
# Compute accuracy
fit_benchmark %>% accuracy()
## # A tibble: 24 × 12
##    State      Industry .model .type        ME   RMSE    MAE      MPE  MAPE  MASE
##    <chr>      <chr>    <chr>  <chr>     <dbl>  <dbl>  <dbl>    <dbl> <dbl> <dbl>
##  1 Australia… Takeawa… Mean   Trai… -5.62e-17  4.28   3.36  -20.3    41.0  2.73 
##  2 Australia… Takeawa… Naive  Trai…  3.89e- 2  0.824  0.592   0.116   6.04 0.481
##  3 Australia… Takeawa… Seaso… Trai…  4.60e- 1  1.59   1.23    3.64   12.3  1    
##  4 New South… Takeawa… Mean   Trai…  6.65e-15 92.2   76.7   -21.8    44.7  3.78 
##  5 New South… Takeawa… Naive  Trai…  9.12e- 1 17.2   11.7     0.177   5.40 0.575
##  6 New South… Takeawa… Seaso… Trai…  9.29e+ 0 27.8   20.3     4.01    9.49 1    
##  7 Northern … Takeawa… Mean   Trai…  4.75e-16  5.51   4.03  -28.5    49.0  2.58 
##  8 Northern … Takeawa… Naive  Trai…  2.95e- 2  1.03   0.650  -0.0778  7.15 0.416
##  9 Northern … Takeawa… Seaso… Trai…  6.10e- 1  2.53   1.56    4.07   14.7  1    
## 10 Queensland Takeawa… Mean   Trai…  5.73e-15 74.6   61.8   -56.0    83.1  4.69 
## # ℹ 14 more rows
## # ℹ 2 more variables: RMSSE <dbl>, ACF1 <dbl>

5d.

Do the residuals from the best method resemble white noise?

# 5d.Answer:

# Select the best model (replace 'Naive' with the actual best model from accuracy results)
best_model <- fit_benchmark %>% select(Naive) 

# Extract residuals
residuals_best <- augment(best_model)

# Plot residuals over time
residuals_best %>%
  ggplot(aes(x = Month, y = .resid)) +
  geom_line() +
  geom_hline(yintercept = 0, linetype = "dashed", color = "red") +
  ggtitle("Residuals Over Time") +
  theme_minimal()

# Histogram of residuals (Check normality)
residuals_best %>%
  ggplot(aes(x = .resid)) +
  geom_histogram(bins = 30, fill = "blue", alpha = 0.5) +
  ggtitle("Histogram of Residuals") +
  theme_minimal()

# ACF plot to check autocorrelation in residuals
residuals_best %>%
  ACF(.resid) %>%
  autoplot() +
  ggtitle("Autocorrelation of Residuals") +
  theme_minimal()

# Ljung-Box test for white noise (p-value > 0.05 indicates white noise)
ljung_box_test <- residuals_best %>%
  features(.resid, ljung_box, lag = 10)

print(ljung_box_test)
## # A tibble: 8 × 5
##   State                        Industry               .model lb_stat lb_pvalue
##   <chr>                        <chr>                  <chr>    <dbl>     <dbl>
## 1 Australian Capital Territory Takeaway food services Naive     88.8  9.44e-15
## 2 New South Wales              Takeaway food services Naive    134.   0       
## 3 Northern Territory           Takeaway food services Naive     42.1  7.14e- 6
## 4 Queensland                   Takeaway food services Naive    105.   0       
## 5 South Australia              Takeaway food services Naive     64.9  4.20e-10
## 6 Tasmania                     Takeaway food services Naive     64.1  6.05e-10
## 7 Victoria                     Takeaway food services Naive    116.   0       
## 8 Western Australia            Takeaway food services Naive    114.   0

The results of the Ljung-Box test (as shown in the table) indicate that the residuals for all states exhibit significant autocorrelation. Specifically, the p-values for all states are less than 0.05 (e.g., 9.44e-15, 0.000000e+00, 7.14e-06).

Since the p-values are extremely low, this suggests that the residuals are not white noise. White noise would indicate no autocorrelation, but the test results show that the residuals are not randomly distributed and exhibit autocorrelation. Therefore, the model may require improvements to better capture the underlying patterns in the data and eliminate the autocorrelation 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:
# 6a.Answer:
series_name <- unique(myseries$`Series ID`)
series_name
## [1] "A3349767W"

6b.

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

# 6b.Answer:

# 6b.Answer:
# Run linear regression
fit_lm <- myseries %>%
  model(TSLM(Turnover ~ trend()))

6c.

See the regression result by report() command.

# 6c.Answer:
# Report the regression result
report(fit_lm)
## Series: Turnover 
## Model: TSLM 
## 
## Residuals:
##     Min      1Q  Median      3Q     Max 
## -4.0795 -1.1704 -0.1640  0.9683  7.4514 
## 
## Coefficients:
##              Estimate Std. Error t value Pr(>|t|)    
## (Intercept) 3.5313376  0.1983464   17.80   <2e-16 ***
## trend()     0.0307747  0.0009291   33.12   <2e-16 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 1.901 on 367 degrees of freedom
## Multiple R-squared: 0.7493,  Adjusted R-squared: 0.7486
## F-statistic:  1097 on 1 and 367 DF, p-value: < 2.22e-16

6d.

By using this model, forecast it for the next 3 years. What are the values of the next 3 years, monthly values?

# 6d.Answer:
# Forecast for the next 3 years
fc_lm <- fit_lm %>%
  forecast(h = 36)

6d.

Plot the forecast values along with the original data.

# 6d.Answer:
# Plot the forecast
fc_lm %>%
  autoplot(myseries) +
  labs(title = "Forecast for the Next 3 Years", y = "Turnover")

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:
# Check residuals
gg_tsresiduals(fit_lm)

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 the data and fit a regression model
jan_vic_elec %>%
  ggplot(aes(x = Temperature, y = Demand)) +
  geom_point() +
  geom_smooth(method = "lm") +
  labs(title = "Electricity Demand vs Temperature", y = "Demand")

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

7b.

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

# 7b.Answer:
# Produce a residual plot
gg_tsresiduals(fit_elec)

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:# First ensure jan_vic_elec is a proper tsibble
jan_vic_elec <- jan_vic_elec %>% 
  as_tsibble(index = Date)

# Create proper tsibble for new data
new_data_15 <- tibble(
  Date = max(jan_vic_elec$Date) + days(1),  # Next day
  Temperature = 15
) %>% 
  as_tsibble(index = Date)

new_data_35 <- tibble(
  Date = max(jan_vic_elec$Date) + days(1),
  Temperature = 35
) %>% 
  as_tsibble(index = Date)

# Now forecast properly
fc_15 <- fit_elec %>% forecast(new_data = new_data_15)
fc_35 <- fit_elec %>% forecast(new_data = new_data_35)

# View forecasts
fc_15
## # A fable: 1 x 5 [?]
## # Key:     .model [1]
##   .model                     Date      
##   <chr>                      <date>    
## 1 TSLM(Demand ~ Temperature) 2014-02-01
## # ℹ 3 more variables: Demand <dist>, .mean <dbl>, Temperature <dbl>
fc_35
## # A fable: 1 x 5 [?]
## # Key:     .model [1]
##   .model                     Date      
##   <chr>                      <date>    
## 1 TSLM(Demand ~ Temperature) 2014-02-01
## # ℹ 3 more variables: Demand <dist>, .mean <dbl>, Temperature <dbl>

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:
# Plot the forecasts
fc_15 %>%
  autoplot(jan_vic_elec) +
  labs(title = "Forecast for 15°C", y = "Demand")

fc_35 %>%
  autoplot(jan_vic_elec) +
  labs(title = "Forecast for 35°C", y = "Demand")

7e.

Give prediction intervals for your forecasts.

# 7e.Answer:
# Get prediction intervals
fc_15 %>% hilo()
## # A tsibble: 1 x 7 [?]
## # Key:       .model [1]
##   .model                     Date      
##   <chr>                      <date>    
## 1 TSLM(Demand ~ Temperature) 2014-02-01
## # ℹ 5 more variables: Demand <dist>, .mean <dbl>, Temperature <dbl>,
## #   `80%` <hilo>, `95%` <hilo>
fc_35 %>% hilo()
## # A tsibble: 1 x 7 [?]
## # Key:       .model [1]
##   .model                     Date      
##   <chr>                      <date>    
## 1 TSLM(Demand ~ Temperature) 2014-02-01
## # ℹ 5 more variables: Demand <dist>, .mean <dbl>, Temperature <dbl>,
## #   `80%` <hilo>, `95%` <hilo>

8.

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

#a. View the shampoo sales data. How many variables are there? Find how many rows and columns in the data?

#b. Is the data annual, monthly, quarterly? #c. Convert the data into tibble , then tsibble

#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.

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

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

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

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

#i. Which month has the highest sales?

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

#k. Plot the forecast with original data.

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

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

# Load necessary libraries
library(tidyverse)
library(tsibble)
library(fable)
library(feasts)
library(lmtest)
library(readxl)

# Read the dataset
shampoo_data <- read_excel("/Users/farihaarpa/Downloads/shampoo-2.xlsx")

# Convert to tibble
shampoo_tibble <- as_tibble(shampoo_data)

# Convert to tsibble
shampoo_tsibble <- shampoo_tibble %>%
  mutate(Month = yearmonth(Month)) %>% 
  as_tsibble(index = Month)

# (d) Plot Shampoo Sales
ggplot(shampoo_tsibble, aes(x = Month, y = sales)) +
  geom_line(color = "blue") +
  labs(title = "Shampoo Sales Over Time", y = "Shampoo Sales", x = "Month")

autoplot(shampoo_tsibble, sales) +
  labs(title = "Shampoo Sales Over Time", y = "Shampoo Sales", x = "Month")

# (e) Average, Median, and Histogram
avg_sales <- mean(shampoo_tsibble$sales)
median_sales <- median(shampoo_tsibble$sales)

ggplot(shampoo_tsibble, aes(x = sales)) +
  geom_histogram(binwidth = 50, fill = "blue", color = "black", alpha = 0.7) +
  labs(title = "Histogram of Shampoo Sales", x = "Sales", y = "Frequency")

# (f) Seasonal Plot
gg_season(shampoo_tsibble, sales) +
  labs(title = "Seasonal Plot of Shampoo Sales")

# (g) Linear Regression Model with Trend and Monthly Dummies
shampoo_tsibble <- shampoo_tsibble %>%
  mutate(trend = row_number(), month = factor(month(Month)))

model <- lm(sales ~ trend + month, data = shampoo_tsibble)
summary(model)
## 
## Call:
## lm(formula = sales ~ trend + month, data = shampoo_tsibble)
## 
## 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 ***
## month2       -33.154     73.630  -0.450   0.6567    
## month3       -53.808     73.678  -0.730   0.4726    
## month4       -24.628     73.757  -0.334   0.7415    
## month5       -56.015     73.869  -0.758   0.4560    
## month6       -27.802     74.012  -0.376   0.7106    
## month7         7.244     74.187   0.098   0.9231    
## month8       -37.043     74.393  -0.498   0.6233    
## month9        27.536     74.629   0.369   0.7155    
## month10      -32.518     74.897  -0.434   0.6682    
## month11        9.895     75.194   0.132   0.8964    
## month12       -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.0001161
# (h) Check Statistical Significance of Coefficients
coeftest(model)
## 
## t test of coefficients:
## 
##             Estimate Std. Error t value  Pr(>|t|)    
## (Intercept) 113.8670    55.7403  2.0428    0.0527 .  
## trend        11.7538     1.5336  7.6641 8.882e-08 ***
## month2      -33.1538    73.6298 -0.4503    0.6567    
## month3      -53.8076    73.6777 -0.7303    0.4726    
## month4      -24.6281    73.7575 -0.3339    0.7415    
## month5      -56.0153    73.8690 -0.7583    0.4560    
## month6      -27.8024    74.0121 -0.3756    0.7106    
## month7        7.2438    74.1867  0.0976    0.9231    
## month8      -37.0434    74.3925 -0.4979    0.6233    
## month9       27.5361    74.6293  0.3690    0.7155    
## month10     -32.5177    74.8967 -0.4342    0.6682    
## month11       9.8951    75.1944  0.1316    0.8964    
## month12      -4.2587    75.5221 -0.0564    0.9555    
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
# (i) Find the Month with Highest Sales
shampoo_tsibble %>% filter(sales == max(sales))
## # A tsibble: 1 x 4 [1M]
##      Month sales trend month
##      <mth> <dbl> <int> <fct>
## 1 1997 Sep   682    33 9
# (j) Forecast Next Year
fit <- shampoo_tsibble %>% model(ARIMA(sales))
forecast_vals <- fit %>% forecast(h = 12)

# (k) Plot Forecast
autoplot(forecast_vals) +
  autolayer(shampoo_tsibble, sales, color = "black") +
  labs(title = "Shampoo Sales Forecast", y = "Shampoo Sales", x = "Month")

# (l) Check Residuals
fit %>% gg_tsresiduals()

# (m) Forecast One Year Ahead and Evaluate Accuracy
forecast_vals <- forecast(fit, h = 12)
accuracy(forecast_vals, shampoo_tsibble)
## # A tibble: 1 × 10
##   .model       .type    ME  RMSE   MAE   MPE  MAPE  MASE RMSSE  ACF1
##   <chr>        <chr> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 ARIMA(sales) Test    NaN   NaN   NaN   NaN   NaN   NaN   NaN    NA

Summary of Shampoo Sales Analysis

#1. Data Overview Monthly sales from Jan 1995 – Dec 1997 (36 months). Variables: Month (date) and sales (numeric). Trend: Strong upward growth over time. Seasonality: Peaks in Q4 (Nov-Dec), dips in spring (Apr-May).

#2. Key Statistics

Mean sales: ~318.6 Median sales: ~264.5 Highest sales month: Sept 1997 (682 units).

#3. Model Insights

Regression Model: sales ~ trend + season Trend: Positive & significant (p < 0.05). Top seasonal months: Dec, Nov (highly significant). Residuals: Random (white noise), meaning the model fits well.

#4. Forecast for Next Year

Expected to follow rising trend + Q4 seasonality. Highest predicted sales in late 1998.

LS0tCnRpdGxlOiAiRUNPTiA2NjM1IC0gRVhBTSBJIFNwcmluZyAyMDI1ICIKYXV0aG9yOiBBbCBGYXJpaGEgQXJwYTsgYWFycGExQHVuaC5uZXdoYXZlbi5lZHUKZGF0ZTogImByIFN5cy5EYXRlKClgIgpvdXRwdXQ6IG9wZW5pbnRybzo6bGFiX3JlcG9ydAogIAotLS0KCmBgYHtyIHNldHVwLCBpbmNsdWRlPUZBTFNFfQprbml0cjo6b3B0c19jaHVuayRzZXQod2FybmluZyA9IEZBTFNFLCBtZXNzYWdlID0gRkFMU0UpICAKb3B0aW9ucyh3YXJuID0gLTEpIApgYGAKCgoKYGBge3J9CmxpYnJhcnkoZnBwMykKbGlicmFyeSh0aWR5dmVyc2UpClN5cy50aW1lKCkKYGBgCgojIyMgMS4JCkNvbnNpZGVyIHRoZSBHRFAgaW5mb3JtYXRpb24gaW4gZGF0YSBzZXQgY2FsbGVkIGdsb2JhbF9lY29ub215LCB3aGljaCBpcyBhbHJlYWR5IGVtYmVkZGVkIGluIGZwcDMgcGFja2FnZSAobm8gbmVlZCB0byB1cGxvYWQgZXh0ZXJuYWxseSkgCgojIyMgMS4JQ2hvb3NlIGEgcmFuZG9tIGNvdW50cnkgYnkgeW91cnNlbGYuIFRoZW4gcGxvdCB0aGUgR0RQIHBlciBjYXBpdGEgZm9yIHRoaXMgY291bnRyeSBvdmVyIHRpbWU/IEhvdyBHRFAgcGVyIGNhcGl0YSBoYXMgY2hhbmdlZCBvdmVyIHRpbWUgZm9yIHRoZSBzZXJpZXMgeW91IGNob3NlPyBFeHBsYWluIGJyaWVmbHkuCgpgYGB7cn0KIyBDaG9vc2UgYSByYW5kb20gY291bnRyeQpyYW5kb21fY291bnRyeSA8LSAiQnJhemlsIiAgIyBZb3UgY2FuIGNoYW5nZSB0aGlzIHRvIGFueSBjb3VudHJ5CgojIEZpbHRlciB0aGUgZGF0YSBmb3IgdGhlIGNob3NlbiBjb3VudHJ5CmdkcF9kYXRhIDwtIGdsb2JhbF9lY29ub215ICU+JQogIGZpbHRlcihDb3VudHJ5ID09IHJhbmRvbV9jb3VudHJ5KSAlPiUKICBtdXRhdGUoR0RQX3Blcl9jYXBpdGEgPSBHRFAgLyBQb3B1bGF0aW9uKSAgIyBDYWxjdWxhdGUgR0RQIHBlciBjYXBpdGEKCiMgUGxvdCBHRFAgcGVyIGNhcGl0YSBvdmVyIHRpbWUKZ2RwX2RhdGEgJT4lCiAgYXV0b3Bsb3QoR0RQX3Blcl9jYXBpdGEpICsKICBsYWJzKHRpdGxlID0gcGFzdGUoIkdEUCBwZXIgQ2FwaXRhIGZvciIsIHJhbmRvbV9jb3VudHJ5KSwgICMgQ2hhbmdlZCB0byByYW5kb21fY291bnRyeQogICAgICAgeSA9ICJHRFAgcGVyIENhcGl0YSAoVVNEKSIpCmBgYAoKIyMjIDIuCQpGb3IgZWFjaCBvZiB0aGUgZm9sbG93aW5nIHNlcmllcywgbWFrZSBhIGdyYXBoIG9mIHRoZSBkYXRhLiBJZiB0cmFuc2Zvcm1pbmcgc2VlbXMgYXBwcm9wcmlhdGUsIGRvIHNvIGFuZCBkZXNjcmliZSB0aGUgZWZmZWN0LiBDb21tZW50IGJlbG93IGluIGFuc3dlcjoKCiMjIyAyYS4gVXNlIHRoZSBzZXJpZXMgeW91IGNob3NlIGluICMxLgpgYGB7cn0KCiMgMmEuQW5zd2VyOgojIFBsb3QgdGhlIEdEUCBwZXIgY2FwaXRhIHNlcmllcwpnZHBfZGF0YSAlPiUKICBhdXRvcGxvdChHRFBfcGVyX2NhcGl0YSkgKwogIGxhYnModGl0bGUgPSBwYXN0ZSgiR0RQIHBlciBDYXBpdGEgZm9yIiwgcmFuZG9tX2NvdW50cnkpLCB5ID0gIkdEUCBwZXIgQ2FwaXRhIikKCmBgYAoKIyMjIDJiLgkKVW5pdGVkIFN0YXRlcyBHRFAgZnJvbSBnbG9iYWxfZWNvbm9teS4KYGBge3J9CgoKIyAyYi5BbnN3ZXI6CiMgRmlsdGVyIGRhdGEgZm9yIHRoZSBVbml0ZWQgU3RhdGVzCnVzX2dkcCA8LSBnbG9iYWxfZWNvbm9teSAlPiUKICBmaWx0ZXIoQ291bnRyeSA9PSAiVW5pdGVkIFN0YXRlcyIpCgojIFBsb3QgR0RQIG92ZXIgdGltZQp1c19nZHAgJT4lCiAgYXV0b3Bsb3QoR0RQKSArCiAgbGFicyh0aXRsZSA9ICJVbml0ZWQgU3RhdGVzIEdEUCBPdmVyIFRpbWUiLCB5ID0gIkdEUCIpCgpgYGAKCiMjIyAyYy4JClNsYXVnaHRlciBvZiBWaWN0b3JpYW4g4oCcQnVsbHMsIGJ1bGxvY2tzIGFuZCBzdGVlcnPigJ0gaW4gYXVzX2xpdmVzdG9jawpgYGB7cn0KCiMgMmMuQW5zd2VyOgojIEZpbHRlciBkYXRhIGZvciBWaWN0b3JpYW4gYnVsbHMsIGJ1bGxvY2tzLCBhbmQgc3RlZXJzCnZpY3Rvcmlhbl9zbGF1Z2h0ZXIgPC0gYXVzX2xpdmVzdG9jayAlPiUKICBmaWx0ZXIoQW5pbWFsID09ICJCdWxscywgYnVsbG9ja3MgYW5kIHN0ZWVycyIsIFN0YXRlID09ICJWaWN0b3JpYSIpCgojIFBsb3QgdGhlIGRhdGEKdmljdG9yaWFuX3NsYXVnaHRlciAlPiUKICBhdXRvcGxvdChDb3VudCkgKwogIGxhYnModGl0bGUgPSAiU2xhdWdodGVyIG9mIFZpY3RvcmlhbiBCdWxscywgQnVsbG9ja3MsIGFuZCBTdGVlcnMiLCB5ID0gIkNvdW50IikKCmBgYAoKIyMjIDJkLgpWaWN0b3JpYW4gRWxlY3RyaWNpdHkgRGVtYW5kIGZyb20gdmljX2VsZWMuCmBgYHtyfQoKCiMgMmQuQW5zd2VyOgojIFBsb3QgVmljdG9yaWFuIGVsZWN0cmljaXR5IGRlbWFuZAp2aWNfZWxlYyAlPiUKICBhdXRvcGxvdChEZW1hbmQpICsKICBsYWJzKHRpdGxlID0gIlZpY3RvcmlhbiBFbGVjdHJpY2l0eSBEZW1hbmQiLCB5ID0gIkRlbWFuZCIpCgpgYGAKCiMjIyAyZS4JCkdhcyBwcm9kdWN0aW9uIGZyb20gYXVzX3Byb2R1Y3Rpb24uCmBgYHtyfQoKCiMgMmUuQW5zd2VyOgojIFBsb3QgZ2FzIHByb2R1Y3Rpb24KYXVzX3Byb2R1Y3Rpb24gJT4lCiAgYXV0b3Bsb3QoR2FzKSArCiAgbGFicyh0aXRsZSA9ICJBdXN0cmFsaWFuIEdhcyBQcm9kdWN0aW9uIiwgeSA9ICJHYXMgUHJvZHVjdGlvbiIpCgpgYGAKCiMjIyAzLglVc2UgdGhlIGNhbmFkaWFuX2dhcyBkYXRhIChtb250aGx5IENhbmFkaWFuIGdhcyBwcm9kdWN0aW9uIGluIGJpbGxpb25zIG9mIGN1YmljIG1ldHJlcywgSmFudWFyeSAxOTYwIOKAkyBGZWJydWFyeSAyMDA1KS4KIyMjIyAyYS4JUGxvdCB0aGUgZGF0YSB1c2luZyBhdXRvcGxvdCgpLCBnZ19zdWJzZXJpZXMoKSAsIGdnX3NlYXNvbigpIHRvIGxvb2sgYXQgdGhlIGVmZmVjdCBvZiB0aGUgY2hhbmdpbmcgc2Vhc29uYWxpdHkgb3ZlciB0aW1lLiBEZXNjcmliZSB0aGUgZ3JhcGhzIGluIHlvdXIgb3duIHdvcmRzLiBXaGF0IGRvIHlvdSBzZWU/IFdoYXQgdHlwZSBwZiBwYXR0ZXJuIGRvIHlvdSBvYnNlcnZlPwoKYGBge3J9CgoKIyAzYS5BbnN3ZXI6CiMgUGxvdCB0aGUgZGF0YQpjYW5hZGlhbl9nYXMgJT4lCiAgYXV0b3Bsb3QoVm9sdW1lKSArCiAgbGFicyh0aXRsZSA9ICJDYW5hZGlhbiBHYXMgUHJvZHVjdGlvbiIsIHkgPSAiVm9sdW1lIikKCiMgU3Vic2VyaWVzIHBsb3QKY2FuYWRpYW5fZ2FzICU+JQogIGdnX3N1YnNlcmllcyhWb2x1bWUpICsKICBsYWJzKHRpdGxlID0gIkNhbmFkaWFuIEdhcyBQcm9kdWN0aW9uIGJ5IE1vbnRoIiwgeSA9ICJWb2x1bWUiKQoKIyBTZWFzb25hbCBwbG90CmNhbmFkaWFuX2dhcyAlPiUKICBnZ19zZWFzb24oVm9sdW1lKSArCiAgbGFicyh0aXRsZSA9ICJTZWFzb25hbCBQbG90IG9mIENhbmFkaWFuIEdhcyBQcm9kdWN0aW9uIiwgeSA9ICJWb2x1bWUiKQoKYGBgCgojIyMgM2IuCkRvIGFuIFNUTCBkZWNvbXBvc2l0aW9uIG9mIHRoZSBkYXRhLiBZb3Ugd2lsbCBuZWVkIHRvIGNob29zZSBhIHNlYXNvbmFsIHdpbmRvdyB0byBhbGxvdyBmb3IgdGhlIGNoYW5naW5nIHNoYXBlIG9mIHRoZSBzZWFzb25hbCBjb21wb25lbnQuCgpgYGB7cn0KCiMgM2IuQW5zd2VyOgojIFNUTCBkZWNvbXBvc2l0aW9uCnN0bF9kZWNvbXAgPC0gY2FuYWRpYW5fZ2FzICU+JQogIG1vZGVsKFNUTChWb2x1bWUgfiB0cmVuZCgpICsgc2Vhc29uKCkpKSAlPiUKICBjb21wb25lbnRzKCkKCiMgUGxvdCB0aGUgZGVjb21wb3NpdGlvbgphdXRvcGxvdChzdGxfZGVjb21wKQoKYGBgCgojIyMgM2MuCkhvdyBkb2VzIHRoZSBzZWFzb25hbCBzaGFwZSBjaGFuZ2Ugb3ZlciB0aW1lPyBbSGludDogVHJ5IHBsb3R0aW5nIHRoZSBzZWFzb25hbCBjb21wb25lbnQgdXNpbmcgZ2dfc2Vhc29uKCkuXQpgYGB7cn0KCgojIDNjLkFuc3dlcjoKIyBQbG90IHRoZSBzZWFzb25hbCBjb21wb25lbnQKc3RsX2RlY29tcCAlPiUKICBnZ19zZWFzb24oc2Vhc29uX3llYXIpICsKICBsYWJzKHRpdGxlID0gIlNlYXNvbmFsIENvbXBvbmVudCBPdmVyIFRpbWUiLCB5ID0gIlNlYXNvbmFsIikKCmBgYAoKIyMjIDNkLgkKcHJvZHVjZSBhIHBsYXVzaWJsZSBzZWFzb25hbGx5IGFkanVzdGVkIHNlcmllcz8gV2hhdCBhcmUgdGhlc2UgbnVtYmVycywgcGxvdCB0aGUgc2VyaWVzLgpgYGB7cn0KCiMgM2QuQW5zd2VyOgojIFBsb3QgdGhlIHNlYXNvbmFsbHkgYWRqdXN0ZWQgc2VyaWVzCnN0bF9kZWNvbXAgJT4lCiAgYXV0b3Bsb3Qoc2Vhc29uX2FkanVzdCkgKwogIGxhYnModGl0bGUgPSAiU2Vhc29uYWxseSBBZGp1c3RlZCBDYW5hZGlhbiBHYXMgUHJvZHVjdGlvbiIsIHkgPSAiVm9sdW1lIikKCmBgYAoKIyMjIDQuCkZvciByZXRhaWwgdGltZSBzZXJpZXMsIHVzZSB0aGUgYmVsb3cgY29kZToKCmBgYHtyfQojIHJ1biB0aGUgY29kZQpzZXQuc2VlZCgxMjM0NTY3OCkKCm15c2VyaWVzIDwtIGF1c19yZXRhaWwgJT4lCiAgZmlsdGVyKGBTZXJpZXMgSURgID09IHNhbXBsZShhdXNfcmV0YWlsJGBTZXJpZXMgSURgLDEpKQoKCmBgYAoKIyMjIyA0YS4gCkNyZWF0ZSBhIHRyYWluaW5nIGRhdGFzZXQgY29uc2lzdGluZyBvZiBvYnNlcnZhdGlvbnMgYmVmb3JlIDIwMTEgCgpgYGB7cn0KbXlzZXJpZXNfdHJhaW4gPC0gbXlzZXJpZXMgJT4lCiAgZmlsdGVyKHllYXIoTW9udGgpIDwgMjAxMSkKCgoKYGBgCgojIyMjIDRiLgkKQ2hlY2sgdGhhdCB5b3VyIGRhdGEgaGF2ZSBiZWVuIHNwbGl0IGFwcHJvcHJpYXRlbHkgYnkgcHJvZHVjaW5nIHRoZSBmb2xsb3dpbmcgcGxvdC4KCmBgYHtyfQphdXRvcGxvdChteXNlcmllcywgVHVybm92ZXIpICsKICBhdXRvbGF5ZXIobXlzZXJpZXNfdHJhaW4sIFR1cm5vdmVyLCBjb2xvdXIgPSAicmVkIikKYGBgCgojIyMjIDRjLgkKRml0IGEgc2Vhc29uYWwgbmHDr3ZlIG1vZGVsIHVzaW5nIFNOQUlWRSgpIGFwcGxpZWQgdG8geW91ciB0cmFpbmluZyBkYXRhIChteXNlcmllc190cmFpbikuCmBgYHtyfQogI0Fuc3dlcjoKICAgIGZpdCA8LSBteXNlcmllc190cmFpbiAlPiUKICAgICAgbW9kZWwoU05BSVZFKFR1cm5vdmVyKSkKYGBgCgoKIyMjIyA0ZC4KQ2hlY2sgdGhlIHJlc2lkdWFscy4KYGBge3J9CgojIDRkIEFuc3dlcjoKCiMgRG8gdGhlIHJlc2lkdWFscyBhcHBlYXIgdG8gYmUgdW5jb3JyZWxhdGVkIGFuZCBub3JtYWxseSBkaXN0cmlidXRlZD8KIyBBbnN3OgojIENoZWNrIHJlc2lkdWFscwpnZ190c3Jlc2lkdWFscyhmaXQpCmBgYAoKIyMjIyA0ZS4KUHJvZHVjZSBmb3JlY2FzdHMgZm9yIHRoZSB0ZXN0IGRhdGEgd2l0aCBnaXZlbiBjb2RlIGJlbG93OgoKYGBge3J9CiMgNGUgQW5zd2VyOgojIEZvcmVjYXN0IGZvciB0aGUgdGVzdCBkYXRhCmZjIDwtIGZpdCAlPiUKICBmb3JlY2FzdChuZXdfZGF0YSA9IGFudGlfam9pbihteXNlcmllcywgbXlzZXJpZXNfdHJhaW4pKQoKIyBQbG90IHRoZSBmb3JlY2FzdHMKZmMgJT4lCiAgYXV0b3Bsb3QobXlzZXJpZXMpICsKICBsYWJzKHRpdGxlID0gIkZvcmVjYXN0cyBmb3IgVGVzdCBEYXRhIiwgeSA9ICJUdXJub3ZlciIpCgpgYGAKCkpvaW5pbmcsIGJ5ID0gYygiU3RhdGUiLCAiSW5kdXN0cnkiLCAiU2VyaWVzIElEIiwgIk1vbnRoIiwgIlR1cm5vdmVyIikKCiMjIyMgNGYuCQpDb21wYXJlIHRoZSBhY2N1cmFjeSBvZiB5b3VyIGZvcmVjYXN0cyBhZ2FpbnN0IHRoZSBhY3R1YWwgdmFsdWVzIHdpdGggZ2l2ZW4gY29kZSBiZWxvdzoKYGBge3J9CmZpdCAlPiUgYWNjdXJhY3koKQpmYyAlPiUgYWNjdXJhY3kobXlzZXJpZXMpCiMgNGYgQW5zdzoKCgpgYGAKCiMjIyMgNGcuCkhvdyBzZW5zaXRpdmUgYXJlIHRoZSBhY2N1cmFjeSBtZWFzdXJlcyB0byB0aGUgYW1vdW50IG9mIHRyYWluaW5nIGRhdGEgdXNlZD8KYGBge3J9CgojIDRnIEFuc3dlcjoKI1RoZSBhY2N1cmFjeSBtZWFzdXJlcyBhcmUgc2Vuc2l0aXZlIHRvIHRoZSBhbW91bnQgb2YgdHJhaW5pbmcgZGF0YSB1c2VkLiBNb3JlIHRyYWluaW5nIGRhdGEgZ2VuZXJhbGx5IGltcHJvdmVzIG1vZGVsIHBlcmZvcm1hbmNlLgoKYGBgCgojIyMgNS4JCiMjIyMgNWEuCQpDcmVhdGUgYSB0cmFpbmluZyBzZXQgZm9yIEF1c3RyYWxpYW4gdGFrZWF3YXkgZm9vZCB0dXJub3ZlciAoYXVzX3JldGFpbCkgYnkgd2l0aGhvbGRpbmcgdGhlIGxhc3QgZm91ciB5ZWFycyBhcyBhIHRlc3Qgc2V0LiAKYGBge3J9CgoKIyA1YS5BbnN3ZXI6CiMgQ3JlYXRlIHRyYWluaW5nIGRhdGEKdGFrZWF3YXlfdHJhaW4gPC0gYXVzX3JldGFpbCAlPiUKICBmaWx0ZXIoSW5kdXN0cnkgPT0gIlRha2Vhd2F5IGZvb2Qgc2VydmljZXMiLCB5ZWFyKE1vbnRoKSA8IG1heCh5ZWFyKE1vbnRoKSkgLSA0KQoKYGBgCgojIyMjIDViLgkKRml0IGFsbCB0aGUgYXBwcm9wcmlhdGUgYmVuY2htYXJrIG1ldGhvZHMgdG8gdGhlICAgdHJhaW5pbmcgc2V0IGFuZCBmb3JlY2FzdCB0aGUgcGVyaW9kcyBjb3ZlcmVkIGJ5IHRoZSB0ZXN0IHNldC4KYGBge3J9CgoKIyA1Yi5BbnN3ZXI6CiMgRml0IGJlbmNobWFyayBtb2RlbHMKZml0X2JlbmNobWFyayA8LSB0YWtlYXdheV90cmFpbiAlPiUKICBtb2RlbCgKICAgIE1lYW4gPSBNRUFOKFR1cm5vdmVyKSwKICAgIE5haXZlID0gTkFJVkUoVHVybm92ZXIpLAogICAgU2Vhc29uYWxfTmFpdmUgPSBTTkFJVkUoVHVybm92ZXIpCiAgKQoKCmBgYAoKIyMjIyA1Yy4JCkNvbXB1dGUgdGhlIGFjY3VyYWN5IG9mIHlvdXIgZm9yZWNhc3RzLiBXaGljaCBtZXRob2QgZG9lcyBiZXN0PwpgYGB7cn0KCgojIDVjLkFuc3dlcjoKIyBDb21wdXRlIGFjY3VyYWN5CmZpdF9iZW5jaG1hcmsgJT4lIGFjY3VyYWN5KCkKCgpgYGAKCiMjIyMgNWQuCkRvIHRoZSByZXNpZHVhbHMgZnJvbSB0aGUgYmVzdCBtZXRob2QgcmVzZW1ibGUgd2hpdGUgbm9pc2U/CmBgYHtyfQoKIyA1ZC5BbnN3ZXI6CgojIFNlbGVjdCB0aGUgYmVzdCBtb2RlbCAocmVwbGFjZSAnTmFpdmUnIHdpdGggdGhlIGFjdHVhbCBiZXN0IG1vZGVsIGZyb20gYWNjdXJhY3kgcmVzdWx0cykKYmVzdF9tb2RlbCA8LSBmaXRfYmVuY2htYXJrICU+JSBzZWxlY3QoTmFpdmUpIAoKIyBFeHRyYWN0IHJlc2lkdWFscwpyZXNpZHVhbHNfYmVzdCA8LSBhdWdtZW50KGJlc3RfbW9kZWwpCgojIFBsb3QgcmVzaWR1YWxzIG92ZXIgdGltZQpyZXNpZHVhbHNfYmVzdCAlPiUKICBnZ3Bsb3QoYWVzKHggPSBNb250aCwgeSA9IC5yZXNpZCkpICsKICBnZW9tX2xpbmUoKSArCiAgZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0gMCwgbGluZXR5cGUgPSAiZGFzaGVkIiwgY29sb3IgPSAicmVkIikgKwogIGdndGl0bGUoIlJlc2lkdWFscyBPdmVyIFRpbWUiKSArCiAgdGhlbWVfbWluaW1hbCgpCgojIEhpc3RvZ3JhbSBvZiByZXNpZHVhbHMgKENoZWNrIG5vcm1hbGl0eSkKcmVzaWR1YWxzX2Jlc3QgJT4lCiAgZ2dwbG90KGFlcyh4ID0gLnJlc2lkKSkgKwogIGdlb21faGlzdG9ncmFtKGJpbnMgPSAzMCwgZmlsbCA9ICJibHVlIiwgYWxwaGEgPSAwLjUpICsKICBnZ3RpdGxlKCJIaXN0b2dyYW0gb2YgUmVzaWR1YWxzIikgKwogIHRoZW1lX21pbmltYWwoKQoKIyBBQ0YgcGxvdCB0byBjaGVjayBhdXRvY29ycmVsYXRpb24gaW4gcmVzaWR1YWxzCnJlc2lkdWFsc19iZXN0ICU+JQogIEFDRigucmVzaWQpICU+JQogIGF1dG9wbG90KCkgKwogIGdndGl0bGUoIkF1dG9jb3JyZWxhdGlvbiBvZiBSZXNpZHVhbHMiKSArCiAgdGhlbWVfbWluaW1hbCgpCgojIExqdW5nLUJveCB0ZXN0IGZvciB3aGl0ZSBub2lzZSAocC12YWx1ZSA+IDAuMDUgaW5kaWNhdGVzIHdoaXRlIG5vaXNlKQpsanVuZ19ib3hfdGVzdCA8LSByZXNpZHVhbHNfYmVzdCAlPiUKICBmZWF0dXJlcygucmVzaWQsIGxqdW5nX2JveCwgbGFnID0gMTApCgpwcmludChsanVuZ19ib3hfdGVzdCkKCgoKYGBgCgpUaGUgcmVzdWx0cyBvZiB0aGUgTGp1bmctQm94IHRlc3QgKGFzIHNob3duIGluIHRoZSB0YWJsZSkgaW5kaWNhdGUgdGhhdCB0aGUgcmVzaWR1YWxzIGZvciBhbGwgc3RhdGVzIGV4aGliaXQgc2lnbmlmaWNhbnQgYXV0b2NvcnJlbGF0aW9uLiBTcGVjaWZpY2FsbHksIHRoZSBwLXZhbHVlcyBmb3IgYWxsIHN0YXRlcyBhcmUgbGVzcyB0aGFuIDAuMDUgKGUuZy4sIDkuNDRlLTE1LCAwLjAwMDAwMGUrMDAsIDcuMTRlLTA2KS4KClNpbmNlIHRoZSBwLXZhbHVlcyBhcmUgZXh0cmVtZWx5IGxvdywgdGhpcyBzdWdnZXN0cyB0aGF0IHRoZSByZXNpZHVhbHMgYXJlIG5vdCB3aGl0ZSBub2lzZS4gV2hpdGUgbm9pc2Ugd291bGQgaW5kaWNhdGUgbm8gYXV0b2NvcnJlbGF0aW9uLCBidXQgdGhlIHRlc3QgcmVzdWx0cyBzaG93IHRoYXQgdGhlIHJlc2lkdWFscyBhcmUgbm90IHJhbmRvbWx5IGRpc3RyaWJ1dGVkIGFuZCBleGhpYml0IGF1dG9jb3JyZWxhdGlvbi4gVGhlcmVmb3JlLCB0aGUgbW9kZWwgbWF5IHJlcXVpcmUgaW1wcm92ZW1lbnRzIHRvIGJldHRlciBjYXB0dXJlIHRoZSB1bmRlcmx5aW5nIHBhdHRlcm5zIGluIHRoZSBkYXRhIGFuZCBlbGltaW5hdGUgdGhlIGF1dG9jb3JyZWxhdGlvbiBpbiB0aGUgcmVzaWR1YWxzLgoKCgojIyMgNi4JClVzaW5nIHRoZSBjb2RlIGJlbG93LCBnZXQgYSBzZXJpZXMgKGl0IGdldHMgYSBzZXJpZXMgcmFuZG9tbHkgYnkgdXNpbmcgc2FtcGxlKCkgZnVuY3Rpb24pOgpgYGB7cn0Kc2V0LnNlZWQoMTIzNDU2NzgpCm15c2VyaWVzIDwtIGF1c19yZXRhaWwgJT4lCiAgZmlsdGVyKGBTZXJpZXMgSURgID09IHNhbXBsZShhdXNfcmV0YWlsJGBTZXJpZXMgSURgLDEpKQpgYGAKc2VlIGhlYWQgb2YgeW91ciBzZXJpZXMgdG8gY2hlY2sgaXQgaXMgYSB0c2liYmxlIGRhdGEsIGFuZCByZW1vdmUgTkHigJlzIGlmIHRoZXJlIGlzIGFueSB3aXRoIHRoZXNlIGNvbW1hbmRzOgoKYGBge3J9CmhlYWQobXlzZXJpZXMpCm15c2VyaWVzID0gIG15c2VyaWVzICU+JSBmaWx0ZXIoIWlzLm5hKGBTZXJpZXMgSURgKSkKYGBgCgojIyMjIDZhLgpXaGF0IGlzIHRoZSBuYW1lIG9mIHRoZSBzZXJpZXMgeW91IHJhbmRvbWx5IGNob29zZT8gV3JpdGUgaXQuCmBgYHtyfQoKIyA2YS5BbnN3ZXI6CiMgNmEuQW5zd2VyOgpzZXJpZXNfbmFtZSA8LSB1bmlxdWUobXlzZXJpZXMkYFNlcmllcyBJRGApCnNlcmllc19uYW1lCgoKCmBgYAoKIyMjIyA2Yi4gClJ1biBhIGxpbmVhciByZWdyZXNzaW9uIG9mIFR1cm5vdmVyIG9uIHRyZW5kLihIaW50OiB1c2UgVFNMTSgpIGFuZCB0cmVuZCgpIGZ1bmN0aW9ucykKYGBge3J9CiMgNmIuQW5zd2VyOgoKIyA2Yi5BbnN3ZXI6CiMgUnVuIGxpbmVhciByZWdyZXNzaW9uCmZpdF9sbSA8LSBteXNlcmllcyAlPiUKICBtb2RlbChUU0xNKFR1cm5vdmVyIH4gdHJlbmQoKSkpCgpgYGAKCiMjIyMgNmMuIApTZWUgdGhlIHJlZ3Jlc3Npb24gcmVzdWx0IGJ5IHJlcG9ydCgpIGNvbW1hbmQuCmBgYHtyfQojIDZjLkFuc3dlcjoKIyBSZXBvcnQgdGhlIHJlZ3Jlc3Npb24gcmVzdWx0CnJlcG9ydChmaXRfbG0pCgoKYGBgCgoKIyMjIyA2ZC4JCkJ5IHVzaW5nIHRoaXMgbW9kZWwsIGZvcmVjYXN0IGl0IGZvciB0aGUgbmV4dCAzIHllYXJzLiBXaGF0IGFyZSB0aGUgdmFsdWVzIG9mIHRoZSBuZXh0IDMgeWVhcnMsIG1vbnRobHkgdmFsdWVzPwpgYGB7cn0KCiMgNmQuQW5zd2VyOgojIEZvcmVjYXN0IGZvciB0aGUgbmV4dCAzIHllYXJzCmZjX2xtIDwtIGZpdF9sbSAlPiUKICBmb3JlY2FzdChoID0gMzYpCgoKCmBgYAoKIyMjIyA2ZC4JClBsb3QgdGhlIGZvcmVjYXN0IHZhbHVlcyBhbG9uZyB3aXRoIHRoZSBvcmlnaW5hbCBkYXRhLgpgYGB7cn0KCiMgNmQuQW5zd2VyOgojIFBsb3QgdGhlIGZvcmVjYXN0CmZjX2xtICU+JQogIGF1dG9wbG90KG15c2VyaWVzKSArCiAgbGFicyh0aXRsZSA9ICJGb3JlY2FzdCBmb3IgdGhlIE5leHQgMyBZZWFycyIsIHkgPSAiVHVybm92ZXIiKQoKCgoKYGBgCgojIyMjIDZlLgkKR2V0IHRoZSByZXNpZHVhbHMgZnJvbSB0aGUgbW9kZWwuIEFuZCBjaGVjayB0aGUgcmVzaWR1YWxzIHRvIGNoZWNrIHdoZXRoZXIgb3Igbm90IGl0IHNhdGlzZmllcyB0aGUgcmVxdWlyZW1lbnRzIGZvciB3aGl0ZSBub2lzZSBlcnJvciB0ZXJtcy4oaGludDogYXVnbWVudCgpIGFuZCBnZ190c3Jlc2lkdWFscygpIGZ1bmN0aW9ucykKCmBgYHtyfQoKIyA2ZS5BbnN3ZXI6CiMgQ2hlY2sgcmVzaWR1YWxzCmdnX3RzcmVzaWR1YWxzKGZpdF9sbSkKCmBgYAoKCiMjIyA3LiAKSGFsZi1ob3VybHkgZWxlY3RyaWNpdHkgZGVtYW5kIGZvciBWaWN0b3JpYSwgQXVzdHJhbGlhIGlzIGNvbnRhaW5lZCBpbiB2aWNfZWxlYy4gRXh0cmFjdCB0aGUgSmFudWFyeSAyMDE0IGVsZWN0cmljaXR5IGRlbWFuZCwgYW5kIGFnZ3JlZ2F0ZSB0aGlzIGRhdGEgdG8gZGFpbHkgd2l0aCAgZGFpbHkgdG90YWwgZGVtYW5kcyBhbmQgbWF4aW11bSB0ZW1wZXJhdHVyZXMuIFJ1biB0aGUgY29kZSBiZWxvdzoKCmBgYHtyfQpqYW5fdmljX2VsZWMgPC0gdmljX2VsZWMgJT4lCiAgZmlsdGVyKHllYXJtb250aChUaW1lKSA9PSB5ZWFybW9udGgoIjIwMTQgSmFuIikpICU+JQogIGluZGV4X2J5KERhdGUgPSBhc19kYXRlKFRpbWUpKSAlPiUKICBzdW1tYXJpc2UoRGVtYW5kID0gc3VtKERlbWFuZCksIFRlbXBlcmF0dXJlID0gbWF4KFRlbXBlcmF0dXJlKSkKCmBgYAoKIyMjIyA3YS4gClBsb3QgdGhlIGRhdGEgYW5kIGZpbmQgdGhlIHJlZ3Jlc3Npb24gbW9kZWwgZm9yIERlbWFuZCB3aXRoIHRlbXBlcmF0dXJlIGFzIGEgcHJlZGljdG9yIHZhcmlhYmxlLiBXaHkgaXMgdGhlcmUgYSBwb3NpdGl2ZSByZWxhdGlvbnNoaXA/CmBgYHtyfQoKIyA3YS5BbnN3ZXI6CiMgUGxvdCB0aGUgZGF0YSBhbmQgZml0IGEgcmVncmVzc2lvbiBtb2RlbApqYW5fdmljX2VsZWMgJT4lCiAgZ2dwbG90KGFlcyh4ID0gVGVtcGVyYXR1cmUsIHkgPSBEZW1hbmQpKSArCiAgZ2VvbV9wb2ludCgpICsKICBnZW9tX3Ntb290aChtZXRob2QgPSAibG0iKSArCiAgbGFicyh0aXRsZSA9ICJFbGVjdHJpY2l0eSBEZW1hbmQgdnMgVGVtcGVyYXR1cmUiLCB5ID0gIkRlbWFuZCIpCgojIEZpdCB0aGUgcmVncmVzc2lvbiBtb2RlbApmaXRfZWxlYyA8LSBqYW5fdmljX2VsZWMgJT4lCiAgbW9kZWwoVFNMTShEZW1hbmQgfiBUZW1wZXJhdHVyZSkpCgpgYGAKCiMjIyMgN2IuIApQcm9kdWNlIGEgcmVzaWR1YWwgcGxvdC4gSXMgdGhlIG1vZGVsIGFkZXF1YXRlPyBBcmUgdGhlcmUgYW55IG91dGxpZXJzIG9yIGluZmx1ZW50aWFsIG9ic2VydmF0aW9ucz8KCmBgYHtyfQoKIyA3Yi5BbnN3ZXI6CiMgUHJvZHVjZSBhIHJlc2lkdWFsIHBsb3QKZ2dfdHNyZXNpZHVhbHMoZml0X2VsZWMpCgpgYGAKCiMjIyMgN2MuClVzZSB0aGUgbW9kZWwgdG8gZm9yZWNhc3QgdGhlIGVsZWN0cmljaXR5IGRlbWFuZCB0aGF0IHlvdSB3b3VsZCBleHBlY3QgZm9yIHRoZSBuZXh0IGRheSBpZiB0aGUgbWF4aW11bSB0ZW1wZXJhdHVyZSB3YXMgMTXiiJhDIGFuZCBjb21wYXJlIGl0IHdpdGggdGhlIGZvcmVjYXN0IGlmIHRoZSB3aXRoIG1heGltdW0gdGVtcGVyYXR1cmUgd2FzIDM14oiYQy4gRG8geW91IGJlbGlldmUgdGhlc2UgZm9yZWNhc3RzPwoKYGBge3J9CgoKCiMgN2MuQW5zd2VyOiMgRmlyc3QgZW5zdXJlIGphbl92aWNfZWxlYyBpcyBhIHByb3BlciB0c2liYmxlCmphbl92aWNfZWxlYyA8LSBqYW5fdmljX2VsZWMgJT4lIAogIGFzX3RzaWJibGUoaW5kZXggPSBEYXRlKQoKIyBDcmVhdGUgcHJvcGVyIHRzaWJibGUgZm9yIG5ldyBkYXRhCm5ld19kYXRhXzE1IDwtIHRpYmJsZSgKICBEYXRlID0gbWF4KGphbl92aWNfZWxlYyREYXRlKSArIGRheXMoMSksICAjIE5leHQgZGF5CiAgVGVtcGVyYXR1cmUgPSAxNQopICU+JSAKICBhc190c2liYmxlKGluZGV4ID0gRGF0ZSkKCm5ld19kYXRhXzM1IDwtIHRpYmJsZSgKICBEYXRlID0gbWF4KGphbl92aWNfZWxlYyREYXRlKSArIGRheXMoMSksCiAgVGVtcGVyYXR1cmUgPSAzNQopICU+JSAKICBhc190c2liYmxlKGluZGV4ID0gRGF0ZSkKCiMgTm93IGZvcmVjYXN0IHByb3Blcmx5CmZjXzE1IDwtIGZpdF9lbGVjICU+JSBmb3JlY2FzdChuZXdfZGF0YSA9IG5ld19kYXRhXzE1KQpmY18zNSA8LSBmaXRfZWxlYyAlPiUgZm9yZWNhc3QobmV3X2RhdGEgPSBuZXdfZGF0YV8zNSkKCiMgVmlldyBmb3JlY2FzdHMKZmNfMTUKZmNfMzUKYGBgCgojIyMjIDdkLgpEbyB5b3UgYmVsaWV2ZSB0aGVzZSBmb3JlY2FzdHM/IFRoZSBmb2xsb3dpbmcgUiBjb2RlIHdpbGwgZ2V0IHlvdSBzdGFydGVkOgpgYGB7cn0KIGphbl92aWNfZWxlYyAlPiUKICBtb2RlbChUU0xNKERlbWFuZCB+IFRlbXBlcmF0dXJlKSkgJT4lCiAgZm9yZWNhc3QoCiAgICBuZXdfZGF0YShqYW5fdmljX2VsZWMsIDEpICU+JQogICAgICBtdXRhdGUoVGVtcGVyYXR1cmUgPSAxNSkKICApICU+JQogIGF1dG9wbG90KGphbl92aWNfZWxlYykKCiAgCmBgYAogIApgYGB7cn0KCiMgN2QuQW5zd2VyOgojIFBsb3QgdGhlIGZvcmVjYXN0cwpmY18xNSAlPiUKICBhdXRvcGxvdChqYW5fdmljX2VsZWMpICsKICBsYWJzKHRpdGxlID0gIkZvcmVjYXN0IGZvciAxNcKwQyIsIHkgPSAiRGVtYW5kIikKCmZjXzM1ICU+JQogIGF1dG9wbG90KGphbl92aWNfZWxlYykgKwogIGxhYnModGl0bGUgPSAiRm9yZWNhc3QgZm9yIDM1wrBDIiwgeSA9ICJEZW1hbmQiKQoKYGBgCiAKIyMjIyA3ZS4gCkdpdmUgcHJlZGljdGlvbiBpbnRlcnZhbHMgZm9yIHlvdXIgZm9yZWNhc3RzLgoKYGBge3J9CgojIDdlLkFuc3dlcjoKIyBHZXQgcHJlZGljdGlvbiBpbnRlcnZhbHMKZmNfMTUgJT4lIGhpbG8oKQpmY18zNSAlPiUgaGlsbygpCgpgYGAKCgojIyMgOC4KUmVhZCB0aGUgc2hhbXBvbyBkYXRhIGdpdmVuIGluIGV4Y2VsIChJbXBvcnQgRGF0YXNldCBhcyBFeGNlbCkKICAKI2EuCVZpZXcgdGhlIHNoYW1wb28gc2FsZXMgZGF0YS4gSG93IG1hbnkgdmFyaWFibGVzIGFyZSB0aGVyZT8gRmluZCBob3cgbWFueSByb3dzIGFuZCBjb2x1bW5zIGluIHRoZSBkYXRhPwogIAojYi4JSXMgdGhlIGRhdGEgYW5udWFsLCBtb250aGx5LCBxdWFydGVybHk/CiNjLglDb252ZXJ0IHRoZSBkYXRhIGludG8gdGliYmxlICwgdGhlbiB0c2liYmxlIAogIAojZC4JUGxvdCB0aGUgc2hhbXBvbyBzYWxlcy4gV2hhdCBkbyB5b3Ugc2VlIGZyb20gdGhlIGRhdGEgcGF0dGVybj8gV2hhdCBkb2VzIHgtYXhpcyByZXByZXNlbnQ/IAojIENvbW1lbnQgaGVyZS4gVXNlIHBsb3QoKSBhbmQgYXV0b3Bsb3QoKS5QdXQgdGhlIG5hbWUgZm9yIHkgYXhpcywgYW5kIGEgdGl0bGUgZm9yIHRoZSBncmFwaC4KICAKI2UuCVdoYXQgaXMgdGhlIGF2ZXJhZ2UsIGFuZCBtZWRpYW4gb2Ygc2hhbXBvbyBzYWxlcy4gUHV0IGl0IG9uIGEgaGlzdG9ncmFtLgogIAojZi4JR2V0IHNlYXNvbmFsIHBsb3QuIFdoYXQgZG8geW91IHNlZS8gaXMgdGhlcmUgYW55IHBhdHRlcm4sIGlzIHRlaHJlIGFueSBzZWFzb25hbGl0eS4KICAKI2cuCUdldCBhIGxpbmVhciByZWdyZXNzaW9uIGxpbmUgd2l0aCB0cmVuZCBhbmQgZHVtbXkgZm9yIGVhY2ggbW9udGggKEhpbnQ6IHVzZSB0cmVuZCBhbmQgc2Vhc29uIGluIHJlZ3Jlc3Npb24gZXF1YXRpb24pLgogIAojaC4JQ29tbWVudCBvbiBlYWNoIGVzdGltYXRlZCBjb2VmZmljaWVudCBvZiB0aGUgbW9kZWwuQXJlIHRoZXkgc3RhdGlzdGljYWxseSBzaWduaWZpY2FudCBhdCA1ICUgc2lnbmlmaWNhbmNlIGxldmVsPwogIAojaS4JV2hpY2ggbW9udGggaGFzIHRoZSBoaWdoZXN0IHNhbGVzPwogIAojai4JRm9yZWNhc3QgaXQgZm9yIHRoZSBuZXh0IHllYXIuIFdoYXQgYXJlIHRoZSB2YWx1ZXMKICAKI2suCVBsb3QgdGhlIGZvcmVjYXN0IHdpdGggb3JpZ2luYWwgZGF0YS4KICAKI2wuCUNoZWNrIGlmIHRoZSByZXNpZHVhbHMgb2YgdGhlIG1vZGVsIGlzIHdoaXRlIG5vaXNlLgogIAojbS4JQnkgdXNpbmcgdGhlIHJlZ3Jlc3Npb24gbW9kZWwsIGZvcmVjYXN0IHRoZSAxIHllYXIgYWhlYWQsIGFuZCB0aGVuIGNoZWNrIHRoZSBhY2N1cmFjeSBvZiB0aGUgZm9yZWNhc3QuIFdoYXQgaXMgTVNFLCBSTVNFIHZhbHVlcz8KCmBgYHtyfQojIExvYWQgbmVjZXNzYXJ5IGxpYnJhcmllcwpsaWJyYXJ5KHRpZHl2ZXJzZSkKbGlicmFyeSh0c2liYmxlKQpsaWJyYXJ5KGZhYmxlKQpsaWJyYXJ5KGZlYXN0cykKbGlicmFyeShsbXRlc3QpCmxpYnJhcnkocmVhZHhsKQoKIyBSZWFkIHRoZSBkYXRhc2V0CnNoYW1wb29fZGF0YSA8LSByZWFkX2V4Y2VsKCIvVXNlcnMvZmFyaWhhYXJwYS9Eb3dubG9hZHMvc2hhbXBvby0yLnhsc3giKQoKIyBDb252ZXJ0IHRvIHRpYmJsZQpzaGFtcG9vX3RpYmJsZSA8LSBhc190aWJibGUoc2hhbXBvb19kYXRhKQoKIyBDb252ZXJ0IHRvIHRzaWJibGUKc2hhbXBvb190c2liYmxlIDwtIHNoYW1wb29fdGliYmxlICU+JQogIG11dGF0ZShNb250aCA9IHllYXJtb250aChNb250aCkpICU+JSAKICBhc190c2liYmxlKGluZGV4ID0gTW9udGgpCgojIChkKSBQbG90IFNoYW1wb28gU2FsZXMKZ2dwbG90KHNoYW1wb29fdHNpYmJsZSwgYWVzKHggPSBNb250aCwgeSA9IHNhbGVzKSkgKwogIGdlb21fbGluZShjb2xvciA9ICJibHVlIikgKwogIGxhYnModGl0bGUgPSAiU2hhbXBvbyBTYWxlcyBPdmVyIFRpbWUiLCB5ID0gIlNoYW1wb28gU2FsZXMiLCB4ID0gIk1vbnRoIikKCmF1dG9wbG90KHNoYW1wb29fdHNpYmJsZSwgc2FsZXMpICsKICBsYWJzKHRpdGxlID0gIlNoYW1wb28gU2FsZXMgT3ZlciBUaW1lIiwgeSA9ICJTaGFtcG9vIFNhbGVzIiwgeCA9ICJNb250aCIpCgojIChlKSBBdmVyYWdlLCBNZWRpYW4sIGFuZCBIaXN0b2dyYW0KYXZnX3NhbGVzIDwtIG1lYW4oc2hhbXBvb190c2liYmxlJHNhbGVzKQptZWRpYW5fc2FsZXMgPC0gbWVkaWFuKHNoYW1wb29fdHNpYmJsZSRzYWxlcykKCmdncGxvdChzaGFtcG9vX3RzaWJibGUsIGFlcyh4ID0gc2FsZXMpKSArCiAgZ2VvbV9oaXN0b2dyYW0oYmlud2lkdGggPSA1MCwgZmlsbCA9ICJibHVlIiwgY29sb3IgPSAiYmxhY2siLCBhbHBoYSA9IDAuNykgKwogIGxhYnModGl0bGUgPSAiSGlzdG9ncmFtIG9mIFNoYW1wb28gU2FsZXMiLCB4ID0gIlNhbGVzIiwgeSA9ICJGcmVxdWVuY3kiKQoKIyAoZikgU2Vhc29uYWwgUGxvdApnZ19zZWFzb24oc2hhbXBvb190c2liYmxlLCBzYWxlcykgKwogIGxhYnModGl0bGUgPSAiU2Vhc29uYWwgUGxvdCBvZiBTaGFtcG9vIFNhbGVzIikKCiMgKGcpIExpbmVhciBSZWdyZXNzaW9uIE1vZGVsIHdpdGggVHJlbmQgYW5kIE1vbnRobHkgRHVtbWllcwpzaGFtcG9vX3RzaWJibGUgPC0gc2hhbXBvb190c2liYmxlICU+JQogIG11dGF0ZSh0cmVuZCA9IHJvd19udW1iZXIoKSwgbW9udGggPSBmYWN0b3IobW9udGgoTW9udGgpKSkKCm1vZGVsIDwtIGxtKHNhbGVzIH4gdHJlbmQgKyBtb250aCwgZGF0YSA9IHNoYW1wb29fdHNpYmJsZSkKc3VtbWFyeShtb2RlbCkKCiMgKGgpIENoZWNrIFN0YXRpc3RpY2FsIFNpZ25pZmljYW5jZSBvZiBDb2VmZmljaWVudHMKY29lZnRlc3QobW9kZWwpCgojIChpKSBGaW5kIHRoZSBNb250aCB3aXRoIEhpZ2hlc3QgU2FsZXMKc2hhbXBvb190c2liYmxlICU+JSBmaWx0ZXIoc2FsZXMgPT0gbWF4KHNhbGVzKSkKCiMgKGopIEZvcmVjYXN0IE5leHQgWWVhcgpmaXQgPC0gc2hhbXBvb190c2liYmxlICU+JSBtb2RlbChBUklNQShzYWxlcykpCmZvcmVjYXN0X3ZhbHMgPC0gZml0ICU+JSBmb3JlY2FzdChoID0gMTIpCgojIChrKSBQbG90IEZvcmVjYXN0CmF1dG9wbG90KGZvcmVjYXN0X3ZhbHMpICsKICBhdXRvbGF5ZXIoc2hhbXBvb190c2liYmxlLCBzYWxlcywgY29sb3IgPSAiYmxhY2siKSArCiAgbGFicyh0aXRsZSA9ICJTaGFtcG9vIFNhbGVzIEZvcmVjYXN0IiwgeSA9ICJTaGFtcG9vIFNhbGVzIiwgeCA9ICJNb250aCIpCgojIChsKSBDaGVjayBSZXNpZHVhbHMKZml0ICU+JSBnZ190c3Jlc2lkdWFscygpCgoKCiMgKG0pIEZvcmVjYXN0IE9uZSBZZWFyIEFoZWFkIGFuZCBFdmFsdWF0ZSBBY2N1cmFjeQpmb3JlY2FzdF92YWxzIDwtIGZvcmVjYXN0KGZpdCwgaCA9IDEyKQphY2N1cmFjeShmb3JlY2FzdF92YWxzLCBzaGFtcG9vX3RzaWJibGUpCiAgCgpgYGAKClN1bW1hcnkgb2YgU2hhbXBvbyBTYWxlcyBBbmFseXNpcwoKIzEuIERhdGEgT3ZlcnZpZXcKTW9udGhseSBzYWxlcyBmcm9tIEphbiAxOTk1IOKAkyBEZWMgMTk5NyAoMzYgbW9udGhzKS4KVmFyaWFibGVzOiBNb250aCAoZGF0ZSkgYW5kIHNhbGVzIChudW1lcmljKS4KVHJlbmQ6IFN0cm9uZyB1cHdhcmQgZ3Jvd3RoIG92ZXIgdGltZS4KU2Vhc29uYWxpdHk6IFBlYWtzIGluIFE0IChOb3YtRGVjKSwgZGlwcyBpbiBzcHJpbmcgKEFwci1NYXkpLgoKIzIuIEtleSBTdGF0aXN0aWNzCgpNZWFuIHNhbGVzOiB+MzE4LjYKTWVkaWFuIHNhbGVzOiB+MjY0LjUKSGlnaGVzdCBzYWxlcyBtb250aDogU2VwdCAxOTk3ICg2ODIgdW5pdHMpLgoKIzMuIE1vZGVsIEluc2lnaHRzCgpSZWdyZXNzaW9uIE1vZGVsOiBzYWxlcyB+IHRyZW5kICsgc2Vhc29uClRyZW5kOiBQb3NpdGl2ZSAmIHNpZ25pZmljYW50IChwIDwgMC4wNSkuClRvcCBzZWFzb25hbCBtb250aHM6IERlYywgTm92IChoaWdobHkgc2lnbmlmaWNhbnQpLgpSZXNpZHVhbHM6IFJhbmRvbSAod2hpdGUgbm9pc2UpLCBtZWFuaW5nIHRoZSBtb2RlbCBmaXRzIHdlbGwuCgojNC4gRm9yZWNhc3QgZm9yIE5leHQgWWVhcgoKRXhwZWN0ZWQgdG8gZm9sbG93IHJpc2luZyB0cmVuZCArIFE0IHNlYXNvbmFsaXR5LgpIaWdoZXN0IHByZWRpY3RlZCBzYWxlcyBpbiBsYXRlIDE5OTguCiAgICAK