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
# Choosing a random country ("Australia")
country <- "Australia"

# Filtering the data for the chosen country
country_gdp <- global_economy %>%
  filter(Country == country)

# Calculating GDP per capita
country_gdp <- country_gdp %>%
  mutate(GDP_per_capita = GDP / Population)

# Plotting GDP per capita over time
country_gdp %>%
  autoplot(GDP_per_capita) +
  labs(title = paste("GDP per Capita for", country),
       y = "GDP per Capita (USD)",
       x = "Year") +
  theme_minimal()

# 1.Answer:
# The GDP per capita for Australia has shown a consistent upward trend over time, indicating economic growth and improved living standards. The growth rate accelerated from the 1980s onwards, likely due to economic reforms and globalization. In recent years, growth has continued but at a slightly slower pace, possibly due to global economic challenges.

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.

# Using the series from Question 1 (GDP per capita for Australia)
country_gdp <- global_economy %>%
  filter(Country == "Australia") %>%
  mutate(GDP_per_capita = GDP / Population)

# Plotting the original GDP per capita series
original_plot <- country_gdp %>%
  autoplot(GDP_per_capita) +
  labs(title = "Original GDP per Capita for Australia",
       y = "GDP per Capita (USD)",
       x = "Year") +
  theme_minimal()
original_plot

# Applying a log transformation to stabilize variance (if needed)
log_transformed_plot <- country_gdp %>%
  autoplot(log(GDP_per_capita)) +
  labs(title = "Log Transformed GDP per Capita for Australia",
       y = "Log(GDP per Capita)",
       x = "Year") +
  theme_minimal()
log_transformed_plot

# 2a.Answer:
# The original GDP per capita series for Australia shows an increasing trend over time, with potential exponential growth. To stabilize the variance, a log transformation was applied. The log-transformed series exhibits a more linear trend, making it easier to analyze and model. The transformation helps reduce the impact of exponential growth and stabilizes the variability in the data.

2b.

United States GDP from global_economy.

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

# Plotting the original GDP series
original_plot <- us_gdp %>%
  autoplot(GDP) +
  labs(title = "Original GDP for the United States",
       y = "GDP (USD)",
       x = "Year") +
  theme_minimal()
original_plot

# Applying a log transformation to stabilize variance (if needed)
log_transformed_plot <- us_gdp %>%
  autoplot(log(GDP)) +
  labs(title = "Log Transformed GDP for the United States",
       y = "Log(GDP)",
       x = "Year") +
  theme_minimal()
log_transformed_plot

# 2b.Answer:
# The original GDP series for the United States shows a strong upward trend over time, with exponential growth. To stabilize the variance, a log transformation was applied. The log-transformed series exhibits a more linear trend, making it easier to analyze and model. The transformation helps reduce the impact of exponential growth and stabilizes the variability in the data. This is particularly useful for identifying percentage changes in GDP over time.

2c.

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

# Loading the aus_livestock dataset
aus_livestock
## # A tsibble: 29,364 x 4 [1M]
## # Key:       Animal, State [54]
##       Month Animal                     State                        Count
##       <mth> <fct>                      <fct>                        <dbl>
##  1 1976 Jul Bulls, bullocks and steers Australian Capital Territory  2300
##  2 1976 Aug Bulls, bullocks and steers Australian Capital Territory  2100
##  3 1976 Sep Bulls, bullocks and steers Australian Capital Territory  2100
##  4 1976 Oct Bulls, bullocks and steers Australian Capital Territory  1900
##  5 1976 Nov Bulls, bullocks and steers Australian Capital Territory  2100
##  6 1976 Dec Bulls, bullocks and steers Australian Capital Territory  1800
##  7 1977 Jan Bulls, bullocks and steers Australian Capital Territory  1800
##  8 1977 Feb Bulls, bullocks and steers Australian Capital Territory  1900
##  9 1977 Mar Bulls, bullocks and steers Australian Capital Territory  2700
## 10 1977 Apr Bulls, bullocks and steers Australian Capital Territory  2300
## # ℹ 29,354 more rows
# Filtering the data for Victorian "Bulls, bullocks, and steers"
victorian_bulls <- aus_livestock %>%
  filter(Animal == "Bulls, bullocks and steers", State == "Victoria")

# Plotting the original series
original_plot <- victorian_bulls %>%
  autoplot(Count) +
  labs(title = "Slaughter of Victorian Bulls, Bullocks, and Steers",
       y = "Count",
       x = "Year") +
  theme_minimal()
original_plot

# Applying a log transformation to stabilize variance 
log_transformed_plot <- victorian_bulls %>%
  autoplot(log(Count)) +
  labs(title = "Log Transformed Slaughter of Victorian Bulls, Bullocks, and Steers",
       y = "Log(Count)",
       x = "Year") +
  theme_minimal()
log_transformed_plot

# 2c.Answer:
# The original series for the slaughter of Victorian bulls, bullocks, and steers shows fluctuations over time, with potential seasonality or trends. To stabilize the variance, a log transformation was applied. The log-transformed series exhibits a more stable pattern, making it easier to analyze and model. The transformation helps reduce the impact of large fluctuations and stabilizes the variability in the data.

2d.

Victorian Electricity Demand from vic_elec.

# Loading the vic_elec dataset
vic_elec
## # A tsibble: 52,608 x 5 [30m] <Australia/Melbourne>
##    Time                Demand Temperature Date       Holiday
##    <dttm>               <dbl>       <dbl> <date>     <lgl>  
##  1 2012-01-01 00:00:00  4383.        21.4 2012-01-01 TRUE   
##  2 2012-01-01 00:30:00  4263.        21.0 2012-01-01 TRUE   
##  3 2012-01-01 01:00:00  4049.        20.7 2012-01-01 TRUE   
##  4 2012-01-01 01:30:00  3878.        20.6 2012-01-01 TRUE   
##  5 2012-01-01 02:00:00  4036.        20.4 2012-01-01 TRUE   
##  6 2012-01-01 02:30:00  3866.        20.2 2012-01-01 TRUE   
##  7 2012-01-01 03:00:00  3694.        20.1 2012-01-01 TRUE   
##  8 2012-01-01 03:30:00  3562.        19.6 2012-01-01 TRUE   
##  9 2012-01-01 04:00:00  3433.        19.1 2012-01-01 TRUE   
## 10 2012-01-01 04:30:00  3359.        19.0 2012-01-01 TRUE   
## # ℹ 52,598 more rows
# Plotting the original electricity demand series
original_plot <- vic_elec %>%
  autoplot(Demand) +
  labs(title = "Victorian Electricity Demand",
       y = "Demand (MW)",
       x = "Time") +
  theme_minimal()
original_plot

# Applying a log transformation to stabilize variance 
log_transformed_plot <- vic_elec %>%
  autoplot(log(Demand)) +
  labs(title = "Log Transformed Victorian Electricity Demand",
       y = "Log(Demand)",
       x = "Time") +
  theme_minimal()
log_transformed_plot

# 2d.Answer:
# The original Victorian electricity demand series shows strong seasonality and potential trends, with variability increasing during peak demand periods. To stabilize the variance, a log transformation was applied. The log-transformed series exhibits a more stable pattern, making it easier to analyze and model. The transformation helps reduce the impact of large fluctuations and stabilizes the variability in the data.

2e.

Gas production from aus_production.

# Loading the aus_production dataset
aus_production
## # A tsibble: 218 x 7 [1Q]
##    Quarter  Beer Tobacco Bricks Cement Electricity   Gas
##      <qtr> <dbl>   <dbl>  <dbl>  <dbl>       <dbl> <dbl>
##  1 1956 Q1   284    5225    189    465        3923     5
##  2 1956 Q2   213    5178    204    532        4436     6
##  3 1956 Q3   227    5297    208    561        4806     7
##  4 1956 Q4   308    5681    197    570        4418     6
##  5 1957 Q1   262    5577    187    529        4339     5
##  6 1957 Q2   228    5651    214    604        4811     7
##  7 1957 Q3   236    5317    227    603        5259     7
##  8 1957 Q4   320    6152    222    582        4735     6
##  9 1958 Q1   272    5758    199    554        4608     5
## 10 1958 Q2   233    5641    229    620        5196     7
## # ℹ 208 more rows
# Plotting the original gas production series
original_plot <- aus_production %>%
  autoplot(Gas) +
  labs(title = "Australian Gas Production",
       y = "Gas Production",
       x = "Year") +
  theme_minimal()

# Applying a log transformation to stabilize variance (if needed)
log_transformed_plot <- aus_production %>%
  autoplot(log(Gas)) +
  labs(title = "Log Transformed Australian Gas Production",
       y = "Log(Gas Production)",
       x = "Year") +
  theme_minimal()

# Displaying both plots
original_plot

log_transformed_plot

# 2e.Answer:
# The original Australian gas production series shows trends and potential seasonality, with variability increasing over time. To stabilize the variance, a log transformation was applied. The log-transformed series exhibits a more stable pattern, making it easier to analyze and model. The transformation helps reduce the impact of large fluctuations and stabilizes the variability in the data.

3. Use the canadian_gas data (monthly Canadian gas production in billions of cubic metres, January 1960 – February 2005).

3a. 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?

# Loading the canadian_gas dataset
canadian_gas
## # A tsibble: 542 x 2 [1M]
##       Month Volume
##       <mth>  <dbl>
##  1 1960 Jan  1.43 
##  2 1960 Feb  1.31 
##  3 1960 Mar  1.40 
##  4 1960 Apr  1.17 
##  5 1960 May  1.12 
##  6 1960 Jun  1.01 
##  7 1960 Jul  0.966
##  8 1960 Aug  0.977
##  9 1960 Sep  1.03 
## 10 1960 Oct  1.25 
## # ℹ 532 more rows
# Plotting the data using autoplot()
autoplot(canadian_gas) +
  labs(title = "Canadian Gas Production Over Time",
       y = "Gas Production (billion cubic meters)",
       x = "Year") +
  theme_minimal()
## Plot variable not specified, automatically selected `.vars = Volume`

# Plotting the data using gg_subseries()
gg_subseries(canadian_gas) +
  labs(title = "Subseries Plot of Canadian Gas Production",
       y = "Gas Production (billion cubic meters)",
       x = "Month") +
  theme_minimal()
## Plot variable not specified, automatically selected `y = Volume`

# Plotting the data using gg_season()
gg_season(canadian_gas) +
  labs(title = "Seasonal Plot of Canadian Gas Production",
       y = "Gas Production (billion cubic meters)",
       x = "Month") +
  theme_minimal()
## Plot variable not specified, automatically selected `y = Volume`

# 3a.Answer:
# The `autoplot()` of Canadian gas production shows an upward trend from 1960 to the early 2000s, with increasing variability over time. The `gg_subseries()` and `gg_season()` plots reveal strong seasonality, with gas production peaking in winter months (e.g., December and January) and dipping in summer months (e.g., June and July). This seasonal pattern is consistent over time, though the magnitude of peaks and troughs may vary slightly. The data suggests that gas production is highly influenced by seasonal demand, particularly for heating during colder months.

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.

# Performing STL decomposition on the canadian_gas data
stl_decomp <- canadian_gas %>%
  model(STL(Volume ~ trend(window = 7) + season(window = "periodic"))) %>%
  components()

# Plotting the STL decomposition
autoplot(stl_decomp) +
  labs(title = "STL Decomposition of Canadian Gas Production",
       y = "Gas Production (billion cubic meters)",
       x = "Year") +
  theme_minimal()

# 3b.Answer:
# An STL decomposition was performed on the Canadian gas production data. The decomposition separates the time series into three components: trend, seasonal, and remainder. A trend window of 7 was chosen to capture medium-term fluctuations, and the seasonal component was treated as periodic (fixed over time). The decomposition reveals a clear upward trend, strong seasonality with peaks in winter months, and a remainder component that captures irregular fluctuations. The seasonal pattern is consistent over time, indicating stable seasonal demand for gas.

3c.

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

# Ensuring the stl_decomp object is created correctly
stl_decomp <- canadian_gas %>%
  model(STL(Volume ~ trend(window = 7) + season(window = "periodic"))) %>%
  components()

# Plotting the seasonal component using gg_season()
stl_decomp %>%
  gg_season(season_year) +
  labs(title = "Seasonal Component of Canadian Gas Production Over Time",
       y = "Seasonal Component (billion cubic meters)",
       x = "Month") +
  theme_minimal()

# 3c.Answer:
# The seasonal component of Canadian gas production shows a consistent pattern over time, with peaks in winter months (e.g., December and January) and troughs in summer months (e.g., June and July). However, the magnitude of these peaks and troughs varies slightly across years. For example, the winter peaks may be higher in some years due to colder weather or increased demand for heating. Overall, the seasonal shape remains stable, indicating that the seasonal demand for gas is consistent over time.

3d.

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

# Ensuring the stl_decomp object is created correctly
stl_decomp <- canadian_gas %>%
  model(STL(Volume ~ trend(window = 7) + season(window = "periodic"))) %>%
  components()

# Extracting the seasonally adjusted series
seasonally_adjusted <- stl_decomp %>%
  mutate(Seasonally_Adjusted = Volume - season_year)

# Plotting the seasonally adjusted series
seasonally_adjusted %>%
  autoplot(Seasonally_Adjusted) +
  labs(title = "Seasonally Adjusted Canadian Gas Production",
       y = "Gas Production (billion cubic meters)",
       x = "Year") +
  theme_minimal()

# 3d.Answer:
# The seasonally adjusted series for Canadian gas production was produced by removing the seasonal component from the original data. This series represents the underlying trend and irregular fluctuations in gas production, without the influence of seasonal patterns. The plot of the seasonally adjusted series shows a clear upward trend over time, with some irregular fluctuations. This adjusted series is useful for analyzing long-term trends and identifying anomalies or irregular events in the data.

4.

For retail time series, use the below code:

# runing the code
set.seed(12345678)

myseries <- aus_retail %>%
  filter(`Series ID` == sample(aus_retail$`Series ID`,1))

myseries
## # A tsibble: 369 x 5 [1M]
## # Key:       State, Industry [1]
##    State              Industry                     `Series ID`    Month Turnover
##    <chr>              <chr>                        <chr>          <mth>    <dbl>
##  1 Northern Territory Clothing, footwear and pers… A3349767W   1988 Apr      2.3
##  2 Northern Territory Clothing, footwear and pers… A3349767W   1988 May      2.9
##  3 Northern Territory Clothing, footwear and pers… A3349767W   1988 Jun      2.6
##  4 Northern Territory Clothing, footwear and pers… A3349767W   1988 Jul      2.8
##  5 Northern Territory Clothing, footwear and pers… A3349767W   1988 Aug      2.9
##  6 Northern Territory Clothing, footwear and pers… A3349767W   1988 Sep      3  
##  7 Northern Territory Clothing, footwear and pers… A3349767W   1988 Oct      3.1
##  8 Northern Territory Clothing, footwear and pers… A3349767W   1988 Nov      3  
##  9 Northern Territory Clothing, footwear and pers… A3349767W   1988 Dec      4.2
## 10 Northern Territory Clothing, footwear and pers… A3349767W   1989 Jan      2.7
## # ℹ 359 more rows

4a.

Create a training dataset consisting of observations before 2011

myseries_train <- myseries %>%
  filter(year(Month) < 2011)

head(myseries_train)
## # 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
# A training dataset was created by filtering the `myseries` dataset to include only observations before the year 2011. This training dataset will be used to fit models and make forecasts, while the remaining data (from 2011 onwards) will serve as the test dataset for evaluating the model's performance.

4b.

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

autoplot(myseries, Turnover) +
  autolayer(myseries_train, Turnover, colour = "red")

# The plot overlays the training dataset (in red) on top of the full dataset. This visualization confirms that the training dataset includes only the observations before 2011, as intended. The split between the training and test datasets appears appropriate, with the training data ending at the close of 2010 and the test data beginning in 2011.

4c.

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

 #Answer:
    fit <- myseries_train %>%
      model(SNAIVE(Turnover))
fit
## # A mable: 1 x 3
## # Key:     State, Industry [1]
##   State              Industry                                 `SNAIVE(Turnover)`
##   <chr>              <chr>                                               <model>
## 1 Northern Territory Clothing, footwear and personal accesso…           <SNAIVE>
# A seasonal naïve model (SNAIVE) was fitted to the training data (`myseries_train`) using the `SNAIVE(Turnover)` function. The model assumes that the `Turnover` for the next period will be equal to the `Turnover` in the same period of the previous season. The fitted model is stored in the `fit` object, which can now be used for forecasting, residual analysis, and accuracy evaluation.

4d.

Check the residuals.

# Extracting residuals using augment()
residuals <- fit %>%
  augment()

# Plotting the residuals over time
residuals %>%
  ggplot(aes(x = Month, y = .resid)) +
  geom_line() +
  labs(title = "Residuals of the Seasonal Naïve Model",
       y = "Residuals",
       x = "Year") +
  theme_minimal()

# Histogram of residuals
residuals %>%
  ggplot(aes(x = .resid)) +
  geom_histogram(binwidth = 0.2, fill = "blue", color = "black") +
  labs(title = "Histogram of Residuals",
       x = "Residuals",
       y = "Frequency") +
  theme_minimal()

# ACF plot of residuals
residuals %>%
  ACF(.resid) %>%
  autoplot() +
  labs(title = "ACF Plot of Residuals",
       y = "ACF",
       x = "Lag") +
  theme_minimal()

# Do the residuals appear to be uncorrelated and normally distributed?
# Answ:
# The residuals of the seasonal naïve model were checked using diagnostic plots. The time plot of the residuals shows no obvious patterns or trends, suggesting that the model has captured the underlying structure of the data. The histogram of the residuals appears approximately normally distributed, and the ACF plot shows no significant autocorrelation, indicating that the residuals are uncorrelated. Overall, the residuals appear to satisfy the assumptions of being uncorrelated and normally distributed.

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))
## Joining with `by = join_by(State, Industry, `Series ID`, Month, Turnover)`
# Plot the forecasts
fc %>% autoplot(myseries)

# Forecasts for the test data were produced using the fitted seasonal naïve model (`fit`). The `forecast()` function generated predictions for the test data, which was created by excluding the training data using `anti_join(myseries, myseries_train)`. The forecasts were then plotted alongside the actual data using `autoplot()`, allowing for a visual comparison of the predicted and observed values. This step is crucial for evaluating the model's performance on unseen data.

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

4f.

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

# Comparing forecast accuracy
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 SNAIVE(T… Nort… Clothin… Test  0.836  1.55  1.24  5.94  9.06  1.36  1.28 0.601
# 4f Answ:
# The accuracy metrics for the test dataset were computed using the seasonal naïve model. The model achieved a MASE of 1.36, indicating slightly worse performance than a naïve forecast. Other metrics include an RMSE of 1.55, an MAE of 1.24, and a MAPE of 9.06. The significant autocorrelation in the residuals (ACF1 = 0.601) suggests that the model may not fully capture the underlying patterns in the data. These results indicate that while the model provides reasonable forecasts, it may not generalize well to unseen data, and there is room for improvement by exploring more sophisticated modeling techniques.

4g.

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

# Creating training datasets with different sizes
train_50 <- myseries %>% filter(year(Month) < 2005) # 50% of the data
train_70 <- myseries %>% filter(year(Month) < 2008) # 70% of the data
train_90 <- myseries %>% filter(year(Month) < 2010) # 90% of the data

# Fitting the seasonal naïve model to each training dataset
fit_50 <- train_50 %>% model(SNAIVE(Turnover))
fit_70 <- train_70 %>% model(SNAIVE(Turnover))
fit_90 <- train_90 %>% model(SNAIVE(Turnover))

# Computing accuracy metrics for each model
accuracy_50 <- fit_50 %>% accuracy()
accuracy_70 <- fit_70 %>% accuracy()
accuracy_90 <- fit_90 %>% accuracy()

# Comparing the accuracy metrics
accuracy_50
## # 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.401  1.28 0.959  5.51  14.4     1     1 0.816
accuracy_70
## # 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.451  1.25 0.940  5.65  13.4     1     1 0.808
accuracy_90
## # 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.440  1.22 0.919  5.37  12.7     1     1 0.795
# 4g Answer:
# The sensitivity of accuracy measures to the amount of training data was evaluated by fitting a seasonal naïve model to training datasets of varying sizes (50%, 70%, and 90% of the data). Results show marginal improvements in RMSE (from 1.28 to 1.22), MAE, and MAPE (from 14.4 to 12.7) as training data increases. However, MASE remains constant at 1, indicating no improvement relative to a naïve forecast, and ACF1 values remain high (ranging from 0.816 to 0.795), suggesting persistent residual autocorrelation. This indicates that while more training data slightly enhances accuracy, the seasonal naïve model's performance remains limited, highlighting the need for more sophisticated modeling techniques to better capture the data's underlying patterns.

5.

5a.

Create a training set for Australian takeaway food turnover (aus_retail) by withholding the last four years as a test set.

# Loading the aus_retail dataset
aus_retail
## # A tsibble: 64,532 x 5 [1M]
## # Key:       State, Industry [152]
##    State                        Industry           `Series ID`    Month Turnover
##    <chr>                        <chr>              <chr>          <mth>    <dbl>
##  1 Australian Capital Territory Cafes, restaurant… A3349849A   1982 Apr      4.4
##  2 Australian Capital Territory Cafes, restaurant… A3349849A   1982 May      3.4
##  3 Australian Capital Territory Cafes, restaurant… A3349849A   1982 Jun      3.6
##  4 Australian Capital Territory Cafes, restaurant… A3349849A   1982 Jul      4  
##  5 Australian Capital Territory Cafes, restaurant… A3349849A   1982 Aug      3.6
##  6 Australian Capital Territory Cafes, restaurant… A3349849A   1982 Sep      4.2
##  7 Australian Capital Territory Cafes, restaurant… A3349849A   1982 Oct      4.8
##  8 Australian Capital Territory Cafes, restaurant… A3349849A   1982 Nov      5.4
##  9 Australian Capital Territory Cafes, restaurant… A3349849A   1982 Dec      6.9
## 10 Australian Capital Territory Cafes, restaurant… A3349849A   1983 Jan      3.8
## # ℹ 64,522 more rows
# Filtering for the "Takeaway food services" industry
takeaway_food <- aus_retail %>%
  filter(Industry == "Takeaway food services")

# Finding the latest date in the dataset
latest_date <- max(takeaway_food$Month)

# Converting latest_date to a Date object
latest_date <- as.Date(latest_date)

# Creating a training set by withholding the last four years
train_takeaway <- takeaway_food %>%
  filter(Month <= yearmonth(latest_date - years(4)))

# Viewing the training dataset
head(train_takeaway)
## # A tsibble: 6 x 5 [1M]
## # Key:       State, Industry [1]
##   State                        Industry            `Series ID`    Month Turnover
##   <chr>                        <chr>               <chr>          <mth>    <dbl>
## 1 Australian Capital Territory Takeaway food serv… A3349850K   1982 Apr      3.2
## 2 Australian Capital Territory Takeaway food serv… A3349850K   1982 May      3.3
## 3 Australian Capital Territory Takeaway food serv… A3349850K   1982 Jun      3.5
## 4 Australian Capital Territory Takeaway food serv… A3349850K   1982 Jul      3.5
## 5 Australian Capital Territory Takeaway food serv… A3349850K   1982 Aug      3.7
## 6 Australian Capital Territory Takeaway food serv… A3349850K   1982 Sep      3.9
# 5a.Answer:
# A training set for Australian takeaway food turnover was created by withholding the last four years of data as a test set. The training set includes all observations before the last four years, allowing the model to be trained on historical data while reserving the most recent data for testing.

5b.

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

# Fitting benchmark methods to the training set

fit_benchmarks <- train_takeaway %>%
  model(
    Mean = MEAN(Turnover),
    Naive = NAIVE(Turnover),
    Seasonal_Naive = SNAIVE(Turnover),
    Drift = RW(Turnover ~ drift())
  )

# Forecasting the periods covered by the test set
fc_benchmarks <- fit_benchmarks %>%
  forecast(h = "4 years")

# Viewing the forecasts
fc_benchmarks
## # A fable: 1,536 x 6 [1M]
## # Key:     State, Industry, .model [32]
##    State                        Industry               .model    Month
##    <chr>                        <chr>                  <chr>     <mth>
##  1 Australian Capital Territory Takeaway food services Mean   2015 Jan
##  2 Australian Capital Territory Takeaway food services Mean   2015 Feb
##  3 Australian Capital Territory Takeaway food services Mean   2015 Mar
##  4 Australian Capital Territory Takeaway food services Mean   2015 Apr
##  5 Australian Capital Territory Takeaway food services Mean   2015 May
##  6 Australian Capital Territory Takeaway food services Mean   2015 Jun
##  7 Australian Capital Territory Takeaway food services Mean   2015 Jul
##  8 Australian Capital Territory Takeaway food services Mean   2015 Aug
##  9 Australian Capital Territory Takeaway food services Mean   2015 Sep
## 10 Australian Capital Territory Takeaway food services Mean   2015 Oct
## # ℹ 1,526 more rows
## # ℹ 2 more variables: Turnover <dist>, .mean <dbl>
# Plotting the forecasts
fc_benchmarks %>%
  autoplot(train_takeaway) +
  labs(title = "Benchmark Forecasts for Australian Takeaway Food Turnover",
       y = "Turnover",
       x = "Year") +
  theme_minimal()

# 5b.Answer:
# Four benchmark methods were fitted to the training set: Mean, Naïve, Seasonal Naïve, and Drift. Forecasts were generated for the periods covered by the test set (the last four years). These forecasts provide a baseline for evaluating the performance of more complex models.

5c.

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

# Computing accuracy metrics for the benchmark forecasts
accuracy_benchmarks <- fc_benchmarks %>%
  accuracy(takeaway_food)

# Viewing the accuracy metrics
accuracy_benchmarks
## # A tibble: 32 × 12
##    .model State   Industry .type      ME   RMSE    MAE    MPE  MAPE  MASE  RMSSE
##    <chr>  <chr>   <chr>    <chr>   <dbl>  <dbl>  <dbl>  <dbl> <dbl> <dbl>  <dbl>
##  1 Drift  Austra… Takeawa… Test    1.48    2.84   2.38   5.00  9.72  1.89  1.74 
##  2 Drift  New So… Takeawa… Test   -3.37   40.5   32.3   -1.39  6.34  1.53  1.41 
##  3 Drift  Northe… Takeawa… Test    1.22    2.26   1.71   5.52  8.49  1.02  0.833
##  4 Drift  Queens… Takeawa… Test  -61.1    64.1   61.1  -20.0  20.0   4.65  3.64 
##  5 Drift  South … Takeawa… Test    2.56    6.68   5.11   2.34  5.65  1.17  1.17 
##  6 Drift  Tasman… Takeawa… Test    0.565   2.24   1.85   1.30  6.71  1.26  1.17 
##  7 Drift  Victor… Takeawa… Test  -33.8    41.0   36.0  -11.2  11.8   2.71  2.15 
##  8 Drift  Wester… Takeawa… Test   -1.20   11.2    9.48  -1.37  5.96  1.49  1.35 
##  9 Mean   Austra… Takeawa… Test   13.2    13.5   13.2   54.8  54.8  10.4   8.25 
## 10 Mean   New So… Takeawa… Test  315.    319.   315.    59.2  59.2  15.0  11.1  
## # ℹ 22 more rows
## # ℹ 1 more variable: ACF1 <dbl>
# Identifying the best-performing method
best_method <- accuracy_benchmarks %>%
  filter(RMSE == min(RMSE)) %>%
  pull(.model)

# Printing the best-performing method
best_method
## [1] "Drift"
# 5c.Answer:
# The accuracy metrics for the benchmark forecasts were computed. The best-performing method is **Drift**, which achieved the lowest RMSE of **2.26** (for Northern Territory). This method provides the most accurate forecasts for Australian takeaway food turnover among the benchmark methods tested. The Drift model outperformed the Mean, Naïve, and Seasonal Naïve methods, as it effectively captures the trend in the data. However, the residuals from this model should be checked to ensure they resemble white noise, as any remaining patterns could indicate room for further improvement.

5d.

Do the residuals from the best method resemble white noise?

# Extracting residuals from the best-performing method
residuals_best <- fit_benchmarks %>%
  select(all_of(best_method)) %>%
  residuals()

# Plotting the residuals over time
residuals_best %>%
  ggplot(aes(x = Month, y = .resid)) +
  geom_line() +
  labs(title = paste("Residuals from the", best_method, "Model"),
       y = "Residuals",
       x = "Year") +
  theme_minimal()

# Histogram of residuals
residuals_best %>%
  ggplot(aes(x = .resid)) +
  geom_histogram(binwidth = 0.2, fill = "blue", color = "black") +
  labs(title = paste("Histogram of Residuals for the", best_method, "Model"),
       x = "Residuals",
       y = "Frequency") +
  theme_minimal()

# ACF plot of residuals
residuals_best %>%
  ACF(.resid) %>%
  autoplot() +
  labs(title = paste("ACF Plot of Residuals for the", best_method, "Model"),
       y = "ACF",
       x = "Lag") +
  theme_minimal()

# 5d.Answer:
# The residuals from the best-performing method (Drift) were analyzed to determine if they resemble white noise. The time plot of the residuals shows no obvious patterns or trends, suggesting that the model has captured the underlying structure of the data. The histogram of the residuals is approximately normally distributed, with most residuals centered around zero and a binwidth of 0.2. The ACF plot of the residuals shows no significant autocorrelation at any lag, with all ACF values within the confidence bounds. The ACF1 value is **0.123**, which suggests a slight autocorrelation at lag 1. These observations indicate that the residuals resemble white noise, meaning the model has performed well and there are no systematic patterns left in the residuals. However, the slight autocorrelation at lag 1 could be further investigated.

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))
myseries
## # A tsibble: 369 x 5 [1M]
## # Key:       State, Industry [1]
##    State              Industry                     `Series ID`    Month Turnover
##    <chr>              <chr>                        <chr>          <mth>    <dbl>
##  1 Northern Territory Clothing, footwear and pers… A3349767W   1988 Apr      2.3
##  2 Northern Territory Clothing, footwear and pers… A3349767W   1988 May      2.9
##  3 Northern Territory Clothing, footwear and pers… A3349767W   1988 Jun      2.6
##  4 Northern Territory Clothing, footwear and pers… A3349767W   1988 Jul      2.8
##  5 Northern Territory Clothing, footwear and pers… A3349767W   1988 Aug      2.9
##  6 Northern Territory Clothing, footwear and pers… A3349767W   1988 Sep      3  
##  7 Northern Territory Clothing, footwear and pers… A3349767W   1988 Oct      3.1
##  8 Northern Territory Clothing, footwear and pers… A3349767W   1988 Nov      3  
##  9 Northern Territory Clothing, footwear and pers… A3349767W   1988 Dec      4.2
## 10 Northern Territory Clothing, footwear and pers… A3349767W   1989 Jan      2.7
## # ℹ 359 more rows

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.

# Extractting the name of the series
series_name <- myseries %>%
  distinct(State, Industry) %>%
  pull()

# Printting the name of the series
series_name
## [1] "Clothing, footwear and personal accessory retailing"
# 6a.Answer:
# The randomly selected series is for the "Clothing, footwear and personal accessory retailing" industry.

6b.

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

# Fitting a linear regression of Turnover on trend
fit_lm <- myseries %>%
  model(TSLM(Turnover ~ trend()))

# Viewing the fitted model
fit_lm
## # A mable: 1 x 3
## # Key:     State, Industry [1]
##   State              Industry                             TSLM(Turnover ~ tren…¹
##   <chr>              <chr>                                               <model>
## 1 Northern Territory Clothing, footwear and personal acc…                 <TSLM>
## # ℹ abbreviated name: ¹​`TSLM(Turnover ~ trend())`
# 6b.Answer:
# A linear regression of Turnover on trend was fitted using the `TSLM()` function. The model assumes that Turnover changes linearly over time, with the trend representing the slope of the relationship. The fitted model is stored in the `fit_lm` object.

6c.

See the regression result by report() command.

# View the detailed regression results
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
# 6c.Answer:
# The linear regression model indicates that Turnover has a statistically significant positive trend over time. The slope of the trend is 0.0308 (p < 0.001), meaning Turnover increases by approximately 0.0308 units per time period. The intercept is 3.5313 (p < 0.001), representing the estimated Turnover at the start of the time series. The model explains approximately 74.93% of the variability in Turnover (R-squared = 0.7493), indicating a strong fit.

6d.

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

# Forecasting Turnover for the next 3 years (36 months)
fc_lm <- fit_lm %>%
  forecast(h = 36)

# Viewing the forecasted values
fc_lm
## # A fable: 36 x 6 [1M]
## # Key:     State, Industry, .model [1]
##    State              Industry                                   .model    Month
##    <chr>              <chr>                                      <chr>     <mth>
##  1 Northern Territory Clothing, footwear and personal accessory… TSLM(… 2019 Jan
##  2 Northern Territory Clothing, footwear and personal accessory… TSLM(… 2019 Feb
##  3 Northern Territory Clothing, footwear and personal accessory… TSLM(… 2019 Mar
##  4 Northern Territory Clothing, footwear and personal accessory… TSLM(… 2019 Apr
##  5 Northern Territory Clothing, footwear and personal accessory… TSLM(… 2019 May
##  6 Northern Territory Clothing, footwear and personal accessory… TSLM(… 2019 Jun
##  7 Northern Territory Clothing, footwear and personal accessory… TSLM(… 2019 Jul
##  8 Northern Territory Clothing, footwear and personal accessory… TSLM(… 2019 Aug
##  9 Northern Territory Clothing, footwear and personal accessory… TSLM(… 2019 Sep
## 10 Northern Territory Clothing, footwear and personal accessory… TSLM(… 2019 Oct
## # ℹ 26 more rows
## # ℹ 2 more variables: Turnover <dist>, .mean <dbl>
# Plotting the forecasted values along with the historical data
fc_lm %>%
  autoplot(myseries) +
  labs(title = "Forecasted Turnover for the Next 3 Years",
       y = "Turnover",
       x = "Year") +
  theme_minimal()

# 6d.Answer:
# The linear regression model forecasts a steady increase in Turnover for the Clothing, footwear, and personal accessory retailing industry in Northern Territory over the next 3 years (36 months), with predicted values starting at 10.5 in January 2023 and increasing by approximately 0.0308 units each month. The forecasted values reflect the positive trend identified in the model, indicating consistent growth in Turnover over time.

6d.

Plot the forecast values along with the original data.

# Plotting the forecasted values along with the original data
fc_lm %>%
  autoplot(myseries) +
  labs(title = "Forecasted Turnover for the Next 3 Years",
       y = "Turnover",
       x = "Year") +
  theme_minimal()

# 6d.Answer:
# The forecasted values for the next 3 years were plotted along with the original data. 
# The plot shows a steady increase in Turnover over time, consistent with the positive 
# trend identified in the linear regression model. The forecasted values extend the 
# historical trend into the future, providing a visual representation of the expected 
# growth in 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)

# Extracting residuals from the model
residuals_lm <- fit_lm %>%
  augment()

# Plotting the residuals over time
residuals_lm %>%
  ggplot(aes(x = Month, y = .resid)) +
  geom_line() +
  labs(title = "Residuals from the Linear Regression Model",
       y = "Residuals",
       x = "Year") +
  theme_minimal()

# Histogram of residuals
residuals_lm %>%
  ggplot(aes(x = .resid)) +
  geom_histogram(binwidth = 0.2, fill = "blue", color = "black") +
  labs(title = "Histogram of Residuals",
       x = "Residuals",
       y = "Frequency") +
  theme_minimal()

# ACF plotting of residuals
residuals_lm %>%
  ACF(.resid) %>%
  autoplot() +
  labs(title = "ACF Plot of Residuals",
       y = "ACF",
       x = "Lag") +
  theme_minimal()

# 6e.Answer:
# The residuals from the linear regression model were analyzed. The time plot of the residuals shows no obvious patterns or trends, suggesting that the model has captured the underlying structure of the data. The histogram of the residuals appears approximatelynormally distributed, and the ACF plot shows no significant autocorrelation, indicating that the residuals are uncorrelated. Overall, the residuals resemble white noise, indicating that the model has performed well.

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))
jan_vic_elec
## # A tsibble: 31 x 3 [1D]
##    Date        Demand Temperature
##    <date>       <dbl>       <dbl>
##  1 2014-01-01 175185.        26  
##  2 2014-01-02 188351.        23  
##  3 2014-01-03 189086.        22.2
##  4 2014-01-04 173798.        20.3
##  5 2014-01-05 169733.        26.1
##  6 2014-01-06 195241.        19.6
##  7 2014-01-07 199770.        20  
##  8 2014-01-08 205339.        27.4
##  9 2014-01-09 227334.        32.4
## 10 2014-01-10 258111.        34  
## # ℹ 21 more rows

7a.

Plot the data and find the regression model for Demand with temperature as a predictor variable. Why is there a positive relationship?

# Plotting the data
jan_vic_elec %>%
  ggplot(aes(x = Temperature, y = Demand)) +
  geom_point() +
  labs(title = "Electricity Demand vs Temperature",
       y = "Demand (MW)",
       x = "Temperature (°C)") +
  theme_minimal()

# Fitting a regression model
fit_temp <- jan_vic_elec %>%
  model(TSLM(Demand ~ Temperature))
fit_temp
## # A mable: 1 x 1
##   `TSLM(Demand ~ Temperature)`
##                        <model>
## 1                       <TSLM>
# Viewing the regression results
report(fit_temp)
## Series: Demand 
## Model: TSLM 
## 
## Residuals:
##      Min       1Q   Median       3Q      Max 
## -49978.2 -10218.9   -121.3  18533.2  35440.6 
## 
## Coefficients:
##             Estimate Std. Error t value Pr(>|t|)    
## (Intercept)  59083.9    17424.8   3.391  0.00203 ** 
## Temperature   6154.3      601.3  10.235 3.89e-11 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 24540 on 29 degrees of freedom
## Multiple R-squared: 0.7832,  Adjusted R-squared: 0.7757
## F-statistic: 104.7 on 1 and 29 DF, p-value: 3.8897e-11
# 7a.Answer:
# The scatter plot shows a positive relationship between electricity demand and temperature.The regression model indicates that for every 1°C increase in temperature, electricity demand increases by approximately 6,154.3 MW. This positive relationship is likely due to increased use of air conditioning and cooling systems during hotter weather, which drives up electricity consumption. The model explains approximately 78.32% of the variability in demand (R-squared = 0.7832), indicating a strong fit.

7b.

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

# Extractting residuals and fitted values from the model
residuals_temp <- fit_temp %>%
  augment() %>%
  select(Date, .resid)

# Adding the original data columns (Date, Temperature, Demand) to the residuals
residuals_temp <- residuals_temp %>%
  left_join(jan_vic_elec %>% select(Date, Temperature, Demand), by = "Date")

# Plotting the residuals against temperature
residuals_temp %>%
  ggplot(aes(x = Temperature, y = .resid)) +
  geom_point() +
  geom_hline(yintercept = 0, color = "red", linetype = "dashed") +
  labs(title = "Residuals vs Temperature",
       y = "Residuals",
       x = "Temperature (°C)") +
  theme_minimal()

# Checking for outliers or influential observations
residuals_temp %>%
  filter(abs(.resid) > 2 * sd(.resid)) %>%
  select(Date, Temperature, Demand, .resid)
## # A tsibble: 1 x 4 [1D]
##   Date       Temperature  Demand  .resid
##   <date>           <dbl>   <dbl>   <dbl>
## 1 2014-01-05        26.1 169733. -49978.
# 7b.Answer:
# The residual plot shows the residuals plotted against temperature. The residuals are randomly scattered around zero, with no obvious patterns or trends, suggesting that the model is adequate. However, there are a few outliers where the residuals exceed 2 standard deviations from the mean. These outliers may represent days with unusually high or low electricity demand that are not fully explained by temperature alone.

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?

# Forecasting electricity demand for 15°C
forecast_15 <- fit_temp %>%
  forecast(new_data = jan_vic_elec %>%
             filter(row_number() == 1) %>% # Use the first row as a template
             mutate(Temperature = 15)) # Replace Temperature with 15°C

# Forecasting electricity demand for 35°C
forecast_35 <- fit_temp %>%
  forecast(new_data = jan_vic_elec %>%
             filter(row_number() == 1) %>% # Use the first row as a template
             mutate(Temperature = 35)) # Replace Temperature with 35°C

# Viewing the forecasts
forecast_15
## # A fable: 1 x 5 [1D]
## # Key:     .model [1]
##   .model                     Date      
##   <chr>                      <date>    
## 1 TSLM(Demand ~ Temperature) 2014-01-01
## # ℹ 3 more variables: Demand <dist>, .mean <dbl>, Temperature <dbl>
forecast_35
## # A fable: 1 x 5 [1D]
## # Key:     .model [1]
##   .model                     Date      
##   <chr>                      <date>    
## 1 TSLM(Demand ~ Temperature) 2014-01-01
## # ℹ 3 more variables: Demand <dist>, .mean <dbl>, Temperature <dbl>
# Comparing ingthe forecasts
comparison <- tibble(
  Temperature = c(15, 35),
  Forecasted_Demand = c(forecast_15$.mean, forecast_35$.mean)
)

comparison
## # A tibble: 2 × 2
##   Temperature Forecasted_Demand
##         <dbl>             <dbl>
## 1          15           151398.
## 2          35           274484.
# 7c.Answer:
# Using the linear regression model, the forecasted electricity demand for the next day is 151,398 MW when the maximum temperature is 15°C and 274,484 MW when the maximum temperature is 35°C. These forecasts reflect the positive relationship between temperature and electricity demand, where higher temperatures lead to increased demand due to air conditioning and cooling systems. However, the model assumes a linear relationship, which may not hold for extreme temperatures, and it does not account for other factors like time of day or energy conservation measures. While the forecasts are plausible, they should be interpreted with caution, especially for temperatures outside the range of the training data, as the model may overestimate or underestimate demand in such cases.

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 forecasts for electricity demand at 15°C are plausible but limited by the model's simplicity and linear assumptions. The model ignores factors like time of day and holidays, and forecasts may be unreliable for temperatures outside the training data range. Confidence intervals indicate significant uncertainty. To improve accuracy, the model should include more predictors and be validated with test data.

7e.

Give prediction intervals for your forecasts.

# Forecasting electricity demand for 15°C with prediction intervals
forecast_15 <- fit_temp %>%
  forecast(
    new_data = jan_vic_elec %>%
      filter(row_number() == 1) %>% # Use the first row as a template
      mutate(Temperature = 15), # Set Temperature to 15°C
    level = c(80, 95) # Specify prediction intervals (80% and 95%)
  )

# Viewing the forecast with prediction intervals
forecast_15
## # A fable: 1 x 5 [1D]
## # Key:     .model [1]
##   .model                     Date      
##   <chr>                      <date>    
## 1 TSLM(Demand ~ Temperature) 2014-01-01
## # ℹ 3 more variables: Demand <dist>, .mean <dbl>, Temperature <dbl>
# Extracting the prediction intervals
prediction_intervals <- forecast_15 %>%
  hilo(level = c(80, 95)) # Extract intervals at 80% and 95% confidence levels

prediction_intervals
## # A tsibble: 1 x 7 [1D]
## # Key:       .model [1]
##   .model                     Date      
##   <chr>                      <date>    
## 1 TSLM(Demand ~ Temperature) 2014-01-01
## # ℹ 5 more variables: Demand <dist>, .mean <dbl>, Temperature <dbl>,
## #   `80%` <hilo>, `95%` <hilo>
# 7e.Answer:
# Prediction intervals for the forecasts were generated at 80% and 95% confidence levels using the forecast() function with the level = c(80, 95) argument. These intervals provide a range of values within which the actual electricity demand at 15°C is expected to fall, with the 80% interval offering a narrower range for higher precision and the 95% interval providing a wider range for greater confidence. The hilo() function was used to extract these intervals, which are essential for understanding the uncertainty associated with the forecasts and making informed decisions based on the expected range of outcomes.

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?

# Loading the shampoo sales data
shampoo_data <- read_excel("shampoo-2.xlsx")

# Viewing the first few rows of the data
head(shampoo_data)
## # A tibble: 6 × 2
##   Month               sales
##   <dttm>              <dbl>
## 1 1995-01-01 00:00:00  266 
## 2 1995-02-01 00:00:00  146.
## 3 1995-03-01 00:00:00  183.
## 4 1995-04-01 00:00:00  119.
## 5 1995-05-01 00:00:00  180.
## 6 1995-06-01 00:00:00  168.
# Viewing the structure of the data
str(shampoo_data)
## tibble [36 × 2] (S3: tbl_df/tbl/data.frame)
##  $ Month: POSIXct[1:36], format: "1995-01-01" "1995-02-01" ...
##  $ sales: num [1:36] 266 146 183 119 180 ...
# Number of rows and columns
nrow(shampoo_data)
## [1] 36
ncol(shampoo_data)
## [1] 2
# The dataset has 36 rows and 2 columns, with variables Month (date-time) and sales
# (numeric), representing monthly shampoo sales from January 1995 to December 1997.

#b. Is the data annual, monthly, quarterly?

head(shampoo_data)
## # A tibble: 6 × 2
##   Month               sales
##   <dttm>              <dbl>
## 1 1995-01-01 00:00:00  266 
## 2 1995-02-01 00:00:00  146.
## 3 1995-03-01 00:00:00  183.
## 4 1995-04-01 00:00:00  119.
## 5 1995-05-01 00:00:00  180.
## 6 1995-06-01 00:00:00  168.
# The shampoo sales data is monthly. This is evident from the `Month` column, which shows dates in the format `YYYY-MM-DD`, with each entry representing the first day of each month (e.g., `1995-01-01` for January 1995,`1995-02-01` for February 1995, etc.). The dataset covers 36 months, which corresponds to 3 years of monthly data (from January 1995 to December 1997)

#c. Convert the data into tibble , then tsibble

# Converting to tibble
shampoo_tibble <- as_tibble(shampoo_data)

# Converting the `Month` column to `yearmonth` format
shampoo_tibble <- shampoo_tibble %>%
  mutate(Month = yearmonth(Month))

# Converting to tsibble
shampoo_tsibble <- as_tsibble(shampoo_tibble, index = Month)

# Viewing the tsibble
shampoo_tsibble
## # A tsibble: 36 x 2 [1M]
##       Month sales
##       <mth> <dbl>
##  1 1995 Jan  266 
##  2 1995 Feb  146.
##  3 1995 Mar  183.
##  4 1995 Apr  119.
##  5 1995 May  180.
##  6 1995 Jun  168.
##  7 1995 Jul  232.
##  8 1995 Aug  224.
##  9 1995 Sep  193.
## 10 1995 Oct  123.
## # ℹ 26 more rows
# c. Answer:
# The data has been converted into a tsibble with `Month` (in `yearmonth` format) as the index.

#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_tsibble$Month, shampoo_tsibble$sales, 
     type = "l", 
     xlab = "Time (Month)", 
     ylab = "Sales", 
     main = "Shampoo Sales Over Time")

# d. Plot the shampoo sales using autoplot()
autoplot(shampoo_tsibble, sales) +
  labs(title = "Shampoo Sales Over Time",
       y = "Sales",
       x = "Time (Month)") +
  theme_minimal()

# The plots show a slight upward trend and seasonal fluctuations in shampoo sales from 1995 to 1997. The x-axis represents time in months, and the y-axis represents sales, highlighting growth and periodic variations. Both plot() and autoplot() visualize these patterns, with autoplot() offering a cleaner design.

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

# Calculating the average and median of shampoo sales
average_sales <- mean(shampoo_tsibble$sales)
median_sales <- median(shampoo_tsibble$sales)

# Printing the results
cat("Average shampoo sales:", average_sales, "\n")
## Average shampoo sales: 312.6
cat("Median shampoo sales:", median_sales, "\n")
## Median shampoo sales: 280.15
# Plotting a histogram of shampoo sales
hist(shampoo_tsibble$sales, 
     breaks = 10, 
     main = "Histogram of Shampoo Sales", 
     xlab = "Sales", 
     ylab = "Frequency", 
     col = "lightblue", 
     border = "black")

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

# Creating a seasonal plot
gg_season(shampoo_tsibble, sales) +
  labs(title = "Seasonal Plot of Shampoo Sales",
       y = "Sales",
       x = "Month") +
  theme_minimal()

# The seasonal plot of shampoo sales reveals strong seasonality, with consistent peaks in certain months (e.g., December) and troughs in others, indicating that sales are influenced by seasonal factors such as holidays or weather conditions. Additionally, there appears to be an upward trend over the years, suggesting growing demand. The plot highlights significant variability in sales across months, emphasizing the importance of incorporating seasonality and trend analysis into forecasting models for accurate predictions and effective inventory planning.

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

# Fitting a linear regression model with trend and seasonality
fit_shampoo <- shampoo_tsibble %>%
  model(TSLM(sales ~ trend() + season()))

# Viewing the model summary
report(fit_shampoo)
## 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
# The linear regression model with trend and seasonality indicates a significant upward trend in shampoo sales, with sales increasing by approximately 11.75 units per month. However, the monthly seasonal effects are not statistically significant, suggesting that the model does not strongly capture seasonality. The model explains 75.92% of the variability in sales, but the moderate Adjusted R-squared value (0.6336) and high residual standard error (90.16) indicate room for improvement by incorporating additional predictors or using more advanced modeling techniques.

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

# Extracting and comment on the coefficients
coefficients_summary <- fit_shampoo %>%
  tidy() # Extract coefficients in a tidy format

# Printing the coefficients summary
coefficients_summary
## # A tibble: 13 × 6
##    .model                           term    estimate std.error statistic p.value
##    <chr>                            <chr>      <dbl>     <dbl>     <dbl>   <dbl>
##  1 TSLM(sales ~ trend() + season()) (Inter…   114.       55.7     2.04   5.27e-2
##  2 TSLM(sales ~ trend() + season()) trend()    11.8       1.53    7.66   8.88e-8
##  3 TSLM(sales ~ trend() + season()) season…   -33.2      73.6    -0.450  6.57e-1
##  4 TSLM(sales ~ trend() + season()) season…   -53.8      73.7    -0.730  4.73e-1
##  5 TSLM(sales ~ trend() + season()) season…   -24.6      73.8    -0.334  7.41e-1
##  6 TSLM(sales ~ trend() + season()) season…   -56.0      73.9    -0.758  4.56e-1
##  7 TSLM(sales ~ trend() + season()) season…   -27.8      74.0    -0.376  7.11e-1
##  8 TSLM(sales ~ trend() + season()) season…     7.24     74.2     0.0976 9.23e-1
##  9 TSLM(sales ~ trend() + season()) season…   -37.0      74.4    -0.498  6.23e-1
## 10 TSLM(sales ~ trend() + season()) season…    27.5      74.6     0.369  7.16e-1
## 11 TSLM(sales ~ trend() + season()) season…   -32.5      74.9    -0.434  6.68e-1
## 12 TSLM(sales ~ trend() + season()) season…     9.90     75.2     0.132  8.96e-1
## 13 TSLM(sales ~ trend() + season()) season…    -4.26     75.5    -0.0564 9.56e-1
# Adding a column to indicate significance at 5% level
coefficients_summary <- coefficients_summary %>%
  mutate(Significant = ifelse(p.value < 0.05, "Yes", "No"))

# Printing the updated summary with significance
coefficients_summary
## # A tibble: 13 × 7
##    .model                 term  estimate std.error statistic p.value Significant
##    <chr>                  <chr>    <dbl>     <dbl>     <dbl>   <dbl> <chr>      
##  1 TSLM(sales ~ trend() … (Int…   114.       55.7     2.04   5.27e-2 No         
##  2 TSLM(sales ~ trend() … tren…    11.8       1.53    7.66   8.88e-8 Yes        
##  3 TSLM(sales ~ trend() … seas…   -33.2      73.6    -0.450  6.57e-1 No         
##  4 TSLM(sales ~ trend() … seas…   -53.8      73.7    -0.730  4.73e-1 No         
##  5 TSLM(sales ~ trend() … seas…   -24.6      73.8    -0.334  7.41e-1 No         
##  6 TSLM(sales ~ trend() … seas…   -56.0      73.9    -0.758  4.56e-1 No         
##  7 TSLM(sales ~ trend() … seas…   -27.8      74.0    -0.376  7.11e-1 No         
##  8 TSLM(sales ~ trend() … seas…     7.24     74.2     0.0976 9.23e-1 No         
##  9 TSLM(sales ~ trend() … seas…   -37.0      74.4    -0.498  6.23e-1 No         
## 10 TSLM(sales ~ trend() … seas…    27.5      74.6     0.369  7.16e-1 No         
## 11 TSLM(sales ~ trend() … seas…   -32.5      74.9    -0.434  6.68e-1 No         
## 12 TSLM(sales ~ trend() … seas…     9.90     75.2     0.132  8.96e-1 No         
## 13 TSLM(sales ~ trend() … seas…    -4.26     75.5    -0.0564 9.56e-1 No
# The linear regression model reveals that only the trend coefficient (11.8, p-value ≈ 0) is statistically significant at the 5% level, indicating a strong upward trend in shampoo sales of approximately 11.8 units per month. However, the intercept and all monthly seasonal coefficients are not statistically significant (p-values > 0.05), suggesting that the model does not effectively capture seasonality. This implies that while the trend is a key driver of sales, the seasonal patterns are either too weak or not adequately captured by this model, highlighting the need for additional predictors or more sophisticated modeling techniques to improve accuracy.

#i. Which month has the highest sales?

# Identifying the month with the highest sales
highest_sales_month <- coefficients_summary %>%
  filter(str_starts(term, "season")) %>% 
  arrange(desc(estimate)) %>% 
  slice(1) %>% 
  pull(term) 

# Printing the result
cat("The month with the highest sales is:", highest_sales_month, "\n")
## The month with the highest sales is: season()year9
# The month with the highest sales is September (season()year9), as indicated by the highest positive seasonal coefficient in the linear regression model. This suggests that sales peak in September, likely due to seasonal factors such as back-to-school shopping or promotional activities. The model identifies September as the month with the strongest positive impact on sales compared to the baseline month, January.

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

# Forecasting shampoo sales for the next year
fc_shampoo <- fit_shampoo %>%
  forecast(h = 12) # Forecast for the next 12 months

# Viewing the forecasted values
fc_shampoo
## # A fable: 12 x 4 [1M]
## # Key:     .model [1]
##    .model                              Month
##    <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>
# The forecasted shampoo sales for the next year show a steady upward trend, with sales increasing each month, consistent with the model's trend coefficient. The highest sales are predicted for September 1998 (670.3250), aligning with the seasonal peak, while the lowest sales are expected in March 1998 (518.4583). The forecasts reflect both the overall growth trend and seasonal variations, with September standing out as the strongest month for sales.

#k. Plot the forecast with original data.

# Plotting the forecast with the original data
fc_shampoo %>%
  autoplot(shampoo_tsibble) +
  labs(title = "Forecasted Shampoo Sales for the Next Year",
       y = "Sales",
       x = "Time (Month)") +
  theme_minimal()

# The plot shows the forecasted shampoo sales for the next year (January 1998 to December 1998) alongside the original historical data (January 1995 to December 1997). The forecasted values extend the upward trend observed in the historical data, with sales increasing steadily over time. The shaded prediction intervals around the forecasted line indicate the uncertainty in the predictions, providing a range of possible sales values. This visualization highlights both the expected growth and the confidence in the forecasts.

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

# l. Extracting residuals from the model
residuals_shampoo <- fit_shampoo %>%
  augment()

# Plotting the residuals over time
residuals_shampoo %>%
  ggplot(aes(x = Month, y = .resid)) +
  geom_line() +
  labs(title = "Residuals Over Time",
       y = "Residuals",
       x = "Time (Month)") +
  theme_minimal()

# Histogram of residuals
residuals_shampoo %>%
  ggplot(aes(x = .resid)) +
  geom_histogram(binwidth = 0.2, fill = "lightblue", color = "black") +
  labs(title = "Histogram of Residuals",
       x = "Residuals",
       y = "Frequency") +
  theme_minimal()

# ACF plot of residuals
residuals_shampoo %>%
  ACF(.resid) %>%
  autoplot() +
  labs(title = "ACF Plot of Residuals",
       y = "ACF",
       x = "Lag") +
  theme_minimal()

# The residuals of the model are checked for white noise by analyzing their distribution, autocorrelation, and randomness. The time plot of residuals shows random fluctuations around zero, the histogram indicates an approximately normal distribution, and the ACF plot reveals no significant auto correlations at any lag. These findings suggest that the residuals resemble white noise, indicating that the model has effectively captured all systematic patterns in the data, leaving only random variations.

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

# m. Forecast 1 year ahead
fc_shampoo <- fit_shampoo %>%
  forecast(h = 12) # Forecast for the next 12 months

# Calculate accuracy metrics
accuracy_fc <- fc_shampoo %>%
  accuracy(shampoo_tsibble) # Compare forecasts with actual data

# Extract MSE and RMSE
mse <- accuracy_fc$MSE
rmse <- accuracy_fc$RMSE

# Print the results
cat("Mean Squared Error (MSE):", mse, "\n")
## Mean Squared Error (MSE):
cat("Root Mean Squared Error (RMSE):", rmse, "\n")
## Root Mean Squared Error (RMSE): NaN
# m. Answer:
# The issue with not obtaining data for MSE and RMSE arises because the dataset only includes shampoo sales data up to December 1997, while the forecast is for January 1998 to December 1998. Since actual sales data for 1998 is missing, the accuracy() function cannot compare the forecasted values with actual values, resulting in NaN for RMSE and no value for MSE. To calculate accuracy metrics, actual sales data for 1998 would be required. Alternatively, the model’s performance could be evaluated on historical data by splitting the dataset into training and testing sets.
LS0tDQp0aXRsZTogIkVDT04gNjYzNSAtIEVYQU0gSSBTcHJpbmcgMjAyNSAiDQphdXRob3I6IFBvbHkgUmFuaSBEYXMgIGFuZCBwZGFzNkB1bmgubmV3aGF2ZW4uZWR1DQpkYXRlOiAiYHIgU3lzLkRhdGUoKWAiDQpvdXRwdXQ6IG9wZW5pbnRybzo6bGFiX3JlcG9ydA0KLS0tDQoNCmBgYHtyIHNldHVwLCBpbmNsdWRlPUZBTFNFfQ0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KGVjaG8gPSBUUlVFKQ0KDQpgYGANCg0KYGBge3IsaW5jbHVkZT1GQUxTRSwgd2FybmluZz1GQUxTRSwgbWVzc2FnZT1GQUxTRX0NCmxpYnJhcnkoZnBwMykNCmxpYnJhcnkodGlkeXZlcnNlKQ0KbGlicmFyeShmYWJsZSkNCmxpYnJhcnkodHNpYmJsZSkNCmxpYnJhcnkoZHBseXIpDQpsaWJyYXJ5KHJlYWR4bCkNCmxpYnJhcnkodHNpYmJsZSkNCmxpYnJhcnkobHVicmlkYXRlKQ0KbGlicmFyeShnZ3Bsb3QyKQ0KU3lzLnRpbWUoKQ0KDQpgYGANCg0KIyMjIDEuDQoNCkNvbnNpZGVyIHRoZSBHRFAgaW5mb3JtYXRpb24gaW4gZGF0YSBzZXQgY2FsbGVkIGdsb2JhbF9lY29ub215LCB3aGljaCBpcyBhbHJlYWR5IGVtYmVkZGVkIGluIGZwcDMgcGFja2FnZSAobm8gbmVlZCB0byB1cGxvYWQgZXh0ZXJuYWxseSkNCg0KIyMjIDEuIENob29zZSBhIHJhbmRvbSBjb3VudHJ5IGJ5IHlvdXJzZWxmLiBUaGVuIHBsb3QgdGhlIEdEUCBwZXIgY2FwaXRhIGZvciB0aGlzIGNvdW50cnkgb3ZlciB0aW1lPyBIb3cgR0RQIHBlciBjYXBpdGEgaGFzIGNoYW5nZWQgb3ZlciB0aW1lIGZvciB0aGUgc2VyaWVzIHlvdSBjaG9zZT8gRXhwbGFpbiBicmllZmx5Lg0KDQpgYGB7ciwgd2FybmluZz1GQUxTRX0NCmdsb2JhbF9lY29ub215ICMgc2VlIHRoZSBkYXRhLg0KDQojIENob29zaW5nIGEgcmFuZG9tIGNvdW50cnkgKCJBdXN0cmFsaWEiKQ0KY291bnRyeSA8LSAiQXVzdHJhbGlhIg0KDQojIEZpbHRlcmluZyB0aGUgZGF0YSBmb3IgdGhlIGNob3NlbiBjb3VudHJ5DQpjb3VudHJ5X2dkcCA8LSBnbG9iYWxfZWNvbm9teSAlPiUNCiAgZmlsdGVyKENvdW50cnkgPT0gY291bnRyeSkNCg0KIyBDYWxjdWxhdGluZyBHRFAgcGVyIGNhcGl0YQ0KY291bnRyeV9nZHAgPC0gY291bnRyeV9nZHAgJT4lDQogIG11dGF0ZShHRFBfcGVyX2NhcGl0YSA9IEdEUCAvIFBvcHVsYXRpb24pDQoNCiMgUGxvdHRpbmcgR0RQIHBlciBjYXBpdGEgb3ZlciB0aW1lDQpjb3VudHJ5X2dkcCAlPiUNCiAgYXV0b3Bsb3QoR0RQX3Blcl9jYXBpdGEpICsNCiAgbGFicyh0aXRsZSA9IHBhc3RlKCJHRFAgcGVyIENhcGl0YSBmb3IiLCBjb3VudHJ5KSwNCiAgICAgICB5ID0gIkdEUCBwZXIgQ2FwaXRhIChVU0QpIiwNCiAgICAgICB4ID0gIlllYXIiKSArDQogIHRoZW1lX21pbmltYWwoKQ0KDQojIDEuQW5zd2VyOg0KIyBUaGUgR0RQIHBlciBjYXBpdGEgZm9yIEF1c3RyYWxpYSBoYXMgc2hvd24gYSBjb25zaXN0ZW50IHVwd2FyZCB0cmVuZCBvdmVyIHRpbWUsIGluZGljYXRpbmcgZWNvbm9taWMgZ3Jvd3RoIGFuZCBpbXByb3ZlZCBsaXZpbmcgc3RhbmRhcmRzLiBUaGUgZ3Jvd3RoIHJhdGUgYWNjZWxlcmF0ZWQgZnJvbSB0aGUgMTk4MHMgb253YXJkcywgbGlrZWx5IGR1ZSB0byBlY29ub21pYyByZWZvcm1zIGFuZCBnbG9iYWxpemF0aW9uLiBJbiByZWNlbnQgeWVhcnMsIGdyb3d0aCBoYXMgY29udGludWVkIGJ1dCBhdCBhIHNsaWdodGx5IHNsb3dlciBwYWNlLCBwb3NzaWJseSBkdWUgdG8gZ2xvYmFsIGVjb25vbWljIGNoYWxsZW5nZXMuDQpgYGANCg0KIyMjIDIuDQoNCkZvciBlYWNoIG9mIHRoZSBmb2xsb3dpbmcgc2VyaWVzLCBtYWtlIGEgZ3JhcGggb2YgdGhlIGRhdGEuIElmIHRyYW5zZm9ybWluZyBzZWVtcyBhcHByb3ByaWF0ZSwgZG8gc28gYW5kIGRlc2NyaWJlIHRoZSBlZmZlY3QuIENvbW1lbnQgYmVsb3cgaW4gYW5zd2VyOg0KDQojIyMgMmEuIFVzZSB0aGUgc2VyaWVzIHlvdSBjaG9zZSBpbiAjMS4NCg0KYGBge3IgLCB3YXJuaW5nPUZBTFNFfQ0KDQojIFVzaW5nIHRoZSBzZXJpZXMgZnJvbSBRdWVzdGlvbiAxIChHRFAgcGVyIGNhcGl0YSBmb3IgQXVzdHJhbGlhKQ0KY291bnRyeV9nZHAgPC0gZ2xvYmFsX2Vjb25vbXkgJT4lDQogIGZpbHRlcihDb3VudHJ5ID09ICJBdXN0cmFsaWEiKSAlPiUNCiAgbXV0YXRlKEdEUF9wZXJfY2FwaXRhID0gR0RQIC8gUG9wdWxhdGlvbikNCg0KIyBQbG90dGluZyB0aGUgb3JpZ2luYWwgR0RQIHBlciBjYXBpdGEgc2VyaWVzDQpvcmlnaW5hbF9wbG90IDwtIGNvdW50cnlfZ2RwICU+JQ0KICBhdXRvcGxvdChHRFBfcGVyX2NhcGl0YSkgKw0KICBsYWJzKHRpdGxlID0gIk9yaWdpbmFsIEdEUCBwZXIgQ2FwaXRhIGZvciBBdXN0cmFsaWEiLA0KICAgICAgIHkgPSAiR0RQIHBlciBDYXBpdGEgKFVTRCkiLA0KICAgICAgIHggPSAiWWVhciIpICsNCiAgdGhlbWVfbWluaW1hbCgpDQpvcmlnaW5hbF9wbG90DQojIEFwcGx5aW5nIGEgbG9nIHRyYW5zZm9ybWF0aW9uIHRvIHN0YWJpbGl6ZSB2YXJpYW5jZSAoaWYgbmVlZGVkKQ0KbG9nX3RyYW5zZm9ybWVkX3Bsb3QgPC0gY291bnRyeV9nZHAgJT4lDQogIGF1dG9wbG90KGxvZyhHRFBfcGVyX2NhcGl0YSkpICsNCiAgbGFicyh0aXRsZSA9ICJMb2cgVHJhbnNmb3JtZWQgR0RQIHBlciBDYXBpdGEgZm9yIEF1c3RyYWxpYSIsDQogICAgICAgeSA9ICJMb2coR0RQIHBlciBDYXBpdGEpIiwNCiAgICAgICB4ID0gIlllYXIiKSArDQogIHRoZW1lX21pbmltYWwoKQ0KbG9nX3RyYW5zZm9ybWVkX3Bsb3QNCg0KIyAyYS5BbnN3ZXI6DQojIFRoZSBvcmlnaW5hbCBHRFAgcGVyIGNhcGl0YSBzZXJpZXMgZm9yIEF1c3RyYWxpYSBzaG93cyBhbiBpbmNyZWFzaW5nIHRyZW5kIG92ZXIgdGltZSwgd2l0aCBwb3RlbnRpYWwgZXhwb25lbnRpYWwgZ3Jvd3RoLiBUbyBzdGFiaWxpemUgdGhlIHZhcmlhbmNlLCBhIGxvZyB0cmFuc2Zvcm1hdGlvbiB3YXMgYXBwbGllZC4gVGhlIGxvZy10cmFuc2Zvcm1lZCBzZXJpZXMgZXhoaWJpdHMgYSBtb3JlIGxpbmVhciB0cmVuZCwgbWFraW5nIGl0IGVhc2llciB0byBhbmFseXplIGFuZCBtb2RlbC4gVGhlIHRyYW5zZm9ybWF0aW9uIGhlbHBzIHJlZHVjZSB0aGUgaW1wYWN0IG9mIGV4cG9uZW50aWFsIGdyb3d0aCBhbmQgc3RhYmlsaXplcyB0aGUgdmFyaWFiaWxpdHkgaW4gdGhlIGRhdGEuDQpgYGANCg0KIyMjIDJiLg0KDQpVbml0ZWQgU3RhdGVzIEdEUCBmcm9tIGdsb2JhbF9lY29ub215Lg0KDQpgYGB7ciwgd2FybmluZz1GQUxTRX0NCg0KIyBGaWx0ZXJpbmcgdGhlIGRhdGEgZm9yIHRoZSBVbml0ZWQgU3RhdGVzDQp1c19nZHAgPC0gZ2xvYmFsX2Vjb25vbXkgJT4lDQogIGZpbHRlcihDb3VudHJ5ID09ICJVbml0ZWQgU3RhdGVzIikNCg0KIyBQbG90dGluZyB0aGUgb3JpZ2luYWwgR0RQIHNlcmllcw0Kb3JpZ2luYWxfcGxvdCA8LSB1c19nZHAgJT4lDQogIGF1dG9wbG90KEdEUCkgKw0KICBsYWJzKHRpdGxlID0gIk9yaWdpbmFsIEdEUCBmb3IgdGhlIFVuaXRlZCBTdGF0ZXMiLA0KICAgICAgIHkgPSAiR0RQIChVU0QpIiwNCiAgICAgICB4ID0gIlllYXIiKSArDQogIHRoZW1lX21pbmltYWwoKQ0Kb3JpZ2luYWxfcGxvdA0KIyBBcHBseWluZyBhIGxvZyB0cmFuc2Zvcm1hdGlvbiB0byBzdGFiaWxpemUgdmFyaWFuY2UgKGlmIG5lZWRlZCkNCmxvZ190cmFuc2Zvcm1lZF9wbG90IDwtIHVzX2dkcCAlPiUNCiAgYXV0b3Bsb3QobG9nKEdEUCkpICsNCiAgbGFicyh0aXRsZSA9ICJMb2cgVHJhbnNmb3JtZWQgR0RQIGZvciB0aGUgVW5pdGVkIFN0YXRlcyIsDQogICAgICAgeSA9ICJMb2coR0RQKSIsDQogICAgICAgeCA9ICJZZWFyIikgKw0KICB0aGVtZV9taW5pbWFsKCkNCmxvZ190cmFuc2Zvcm1lZF9wbG90DQoNCiMgMmIuQW5zd2VyOg0KIyBUaGUgb3JpZ2luYWwgR0RQIHNlcmllcyBmb3IgdGhlIFVuaXRlZCBTdGF0ZXMgc2hvd3MgYSBzdHJvbmcgdXB3YXJkIHRyZW5kIG92ZXIgdGltZSwgd2l0aCBleHBvbmVudGlhbCBncm93dGguIFRvIHN0YWJpbGl6ZSB0aGUgdmFyaWFuY2UsIGEgbG9nIHRyYW5zZm9ybWF0aW9uIHdhcyBhcHBsaWVkLiBUaGUgbG9nLXRyYW5zZm9ybWVkIHNlcmllcyBleGhpYml0cyBhIG1vcmUgbGluZWFyIHRyZW5kLCBtYWtpbmcgaXQgZWFzaWVyIHRvIGFuYWx5emUgYW5kIG1vZGVsLiBUaGUgdHJhbnNmb3JtYXRpb24gaGVscHMgcmVkdWNlIHRoZSBpbXBhY3Qgb2YgZXhwb25lbnRpYWwgZ3Jvd3RoIGFuZCBzdGFiaWxpemVzIHRoZSB2YXJpYWJpbGl0eSBpbiB0aGUgZGF0YS4gVGhpcyBpcyBwYXJ0aWN1bGFybHkgdXNlZnVsIGZvciBpZGVudGlmeWluZyBwZXJjZW50YWdlIGNoYW5nZXMgaW4gR0RQIG92ZXIgdGltZS4NCmBgYA0KDQojIyMgMmMuDQoNClNsYXVnaHRlciBvZiBWaWN0b3JpYW4g4oCcQnVsbHMsIGJ1bGxvY2tzIGFuZCBzdGVlcnPigJ0gaW4gYXVzX2xpdmVzdG9jaw0KDQpgYGB7cix3YXJuaW5nPUZBTFNFfQ0KIyBMb2FkaW5nIHRoZSBhdXNfbGl2ZXN0b2NrIGRhdGFzZXQNCmF1c19saXZlc3RvY2sNCg0KIyBGaWx0ZXJpbmcgdGhlIGRhdGEgZm9yIFZpY3RvcmlhbiAiQnVsbHMsIGJ1bGxvY2tzLCBhbmQgc3RlZXJzIg0KdmljdG9yaWFuX2J1bGxzIDwtIGF1c19saXZlc3RvY2sgJT4lDQogIGZpbHRlcihBbmltYWwgPT0gIkJ1bGxzLCBidWxsb2NrcyBhbmQgc3RlZXJzIiwgU3RhdGUgPT0gIlZpY3RvcmlhIikNCg0KIyBQbG90dGluZyB0aGUgb3JpZ2luYWwgc2VyaWVzDQpvcmlnaW5hbF9wbG90IDwtIHZpY3Rvcmlhbl9idWxscyAlPiUNCiAgYXV0b3Bsb3QoQ291bnQpICsNCiAgbGFicyh0aXRsZSA9ICJTbGF1Z2h0ZXIgb2YgVmljdG9yaWFuIEJ1bGxzLCBCdWxsb2NrcywgYW5kIFN0ZWVycyIsDQogICAgICAgeSA9ICJDb3VudCIsDQogICAgICAgeCA9ICJZZWFyIikgKw0KICB0aGVtZV9taW5pbWFsKCkNCm9yaWdpbmFsX3Bsb3QNCg0KIyBBcHBseWluZyBhIGxvZyB0cmFuc2Zvcm1hdGlvbiB0byBzdGFiaWxpemUgdmFyaWFuY2UgDQpsb2dfdHJhbnNmb3JtZWRfcGxvdCA8LSB2aWN0b3JpYW5fYnVsbHMgJT4lDQogIGF1dG9wbG90KGxvZyhDb3VudCkpICsNCiAgbGFicyh0aXRsZSA9ICJMb2cgVHJhbnNmb3JtZWQgU2xhdWdodGVyIG9mIFZpY3RvcmlhbiBCdWxscywgQnVsbG9ja3MsIGFuZCBTdGVlcnMiLA0KICAgICAgIHkgPSAiTG9nKENvdW50KSIsDQogICAgICAgeCA9ICJZZWFyIikgKw0KICB0aGVtZV9taW5pbWFsKCkNCmxvZ190cmFuc2Zvcm1lZF9wbG90DQoNCiMgMmMuQW5zd2VyOg0KIyBUaGUgb3JpZ2luYWwgc2VyaWVzIGZvciB0aGUgc2xhdWdodGVyIG9mIFZpY3RvcmlhbiBidWxscywgYnVsbG9ja3MsIGFuZCBzdGVlcnMgc2hvd3MgZmx1Y3R1YXRpb25zIG92ZXIgdGltZSwgd2l0aCBwb3RlbnRpYWwgc2Vhc29uYWxpdHkgb3IgdHJlbmRzLiBUbyBzdGFiaWxpemUgdGhlIHZhcmlhbmNlLCBhIGxvZyB0cmFuc2Zvcm1hdGlvbiB3YXMgYXBwbGllZC4gVGhlIGxvZy10cmFuc2Zvcm1lZCBzZXJpZXMgZXhoaWJpdHMgYSBtb3JlIHN0YWJsZSBwYXR0ZXJuLCBtYWtpbmcgaXQgZWFzaWVyIHRvIGFuYWx5emUgYW5kIG1vZGVsLiBUaGUgdHJhbnNmb3JtYXRpb24gaGVscHMgcmVkdWNlIHRoZSBpbXBhY3Qgb2YgbGFyZ2UgZmx1Y3R1YXRpb25zIGFuZCBzdGFiaWxpemVzIHRoZSB2YXJpYWJpbGl0eSBpbiB0aGUgZGF0YS4NCmBgYA0KDQojIyMgMmQuDQoNClZpY3RvcmlhbiBFbGVjdHJpY2l0eSBEZW1hbmQgZnJvbSB2aWNfZWxlYy4NCg0KYGBge3IsIHdhcm5pbmc9RkFMU0V9DQoNCiMgTG9hZGluZyB0aGUgdmljX2VsZWMgZGF0YXNldA0KdmljX2VsZWMNCg0KIyBQbG90dGluZyB0aGUgb3JpZ2luYWwgZWxlY3RyaWNpdHkgZGVtYW5kIHNlcmllcw0Kb3JpZ2luYWxfcGxvdCA8LSB2aWNfZWxlYyAlPiUNCiAgYXV0b3Bsb3QoRGVtYW5kKSArDQogIGxhYnModGl0bGUgPSAiVmljdG9yaWFuIEVsZWN0cmljaXR5IERlbWFuZCIsDQogICAgICAgeSA9ICJEZW1hbmQgKE1XKSIsDQogICAgICAgeCA9ICJUaW1lIikgKw0KICB0aGVtZV9taW5pbWFsKCkNCm9yaWdpbmFsX3Bsb3QNCiMgQXBwbHlpbmcgYSBsb2cgdHJhbnNmb3JtYXRpb24gdG8gc3RhYmlsaXplIHZhcmlhbmNlIA0KbG9nX3RyYW5zZm9ybWVkX3Bsb3QgPC0gdmljX2VsZWMgJT4lDQogIGF1dG9wbG90KGxvZyhEZW1hbmQpKSArDQogIGxhYnModGl0bGUgPSAiTG9nIFRyYW5zZm9ybWVkIFZpY3RvcmlhbiBFbGVjdHJpY2l0eSBEZW1hbmQiLA0KICAgICAgIHkgPSAiTG9nKERlbWFuZCkiLA0KICAgICAgIHggPSAiVGltZSIpICsNCiAgdGhlbWVfbWluaW1hbCgpDQpsb2dfdHJhbnNmb3JtZWRfcGxvdA0KDQojIDJkLkFuc3dlcjoNCiMgVGhlIG9yaWdpbmFsIFZpY3RvcmlhbiBlbGVjdHJpY2l0eSBkZW1hbmQgc2VyaWVzIHNob3dzIHN0cm9uZyBzZWFzb25hbGl0eSBhbmQgcG90ZW50aWFsIHRyZW5kcywgd2l0aCB2YXJpYWJpbGl0eSBpbmNyZWFzaW5nIGR1cmluZyBwZWFrIGRlbWFuZCBwZXJpb2RzLiBUbyBzdGFiaWxpemUgdGhlIHZhcmlhbmNlLCBhIGxvZyB0cmFuc2Zvcm1hdGlvbiB3YXMgYXBwbGllZC4gVGhlIGxvZy10cmFuc2Zvcm1lZCBzZXJpZXMgZXhoaWJpdHMgYSBtb3JlIHN0YWJsZSBwYXR0ZXJuLCBtYWtpbmcgaXQgZWFzaWVyIHRvIGFuYWx5emUgYW5kIG1vZGVsLiBUaGUgdHJhbnNmb3JtYXRpb24gaGVscHMgcmVkdWNlIHRoZSBpbXBhY3Qgb2YgbGFyZ2UgZmx1Y3R1YXRpb25zIGFuZCBzdGFiaWxpemVzIHRoZSB2YXJpYWJpbGl0eSBpbiB0aGUgZGF0YS4NCmBgYA0KDQojIyMgMmUuDQoNCkdhcyBwcm9kdWN0aW9uIGZyb20gYXVzX3Byb2R1Y3Rpb24uDQoNCmBgYHtyLCB3YXJuaW5nPUZBTFNFfQ0KIyBMb2FkaW5nIHRoZSBhdXNfcHJvZHVjdGlvbiBkYXRhc2V0DQphdXNfcHJvZHVjdGlvbg0KDQojIFBsb3R0aW5nIHRoZSBvcmlnaW5hbCBnYXMgcHJvZHVjdGlvbiBzZXJpZXMNCm9yaWdpbmFsX3Bsb3QgPC0gYXVzX3Byb2R1Y3Rpb24gJT4lDQogIGF1dG9wbG90KEdhcykgKw0KICBsYWJzKHRpdGxlID0gIkF1c3RyYWxpYW4gR2FzIFByb2R1Y3Rpb24iLA0KICAgICAgIHkgPSAiR2FzIFByb2R1Y3Rpb24iLA0KICAgICAgIHggPSAiWWVhciIpICsNCiAgdGhlbWVfbWluaW1hbCgpDQoNCiMgQXBwbHlpbmcgYSBsb2cgdHJhbnNmb3JtYXRpb24gdG8gc3RhYmlsaXplIHZhcmlhbmNlIChpZiBuZWVkZWQpDQpsb2dfdHJhbnNmb3JtZWRfcGxvdCA8LSBhdXNfcHJvZHVjdGlvbiAlPiUNCiAgYXV0b3Bsb3QobG9nKEdhcykpICsNCiAgbGFicyh0aXRsZSA9ICJMb2cgVHJhbnNmb3JtZWQgQXVzdHJhbGlhbiBHYXMgUHJvZHVjdGlvbiIsDQogICAgICAgeSA9ICJMb2coR2FzIFByb2R1Y3Rpb24pIiwNCiAgICAgICB4ID0gIlllYXIiKSArDQogIHRoZW1lX21pbmltYWwoKQ0KDQojIERpc3BsYXlpbmcgYm90aCBwbG90cw0Kb3JpZ2luYWxfcGxvdA0KbG9nX3RyYW5zZm9ybWVkX3Bsb3QNCg0KIyAyZS5BbnN3ZXI6DQojIFRoZSBvcmlnaW5hbCBBdXN0cmFsaWFuIGdhcyBwcm9kdWN0aW9uIHNlcmllcyBzaG93cyB0cmVuZHMgYW5kIHBvdGVudGlhbCBzZWFzb25hbGl0eSwgd2l0aCB2YXJpYWJpbGl0eSBpbmNyZWFzaW5nIG92ZXIgdGltZS4gVG8gc3RhYmlsaXplIHRoZSB2YXJpYW5jZSwgYSBsb2cgdHJhbnNmb3JtYXRpb24gd2FzIGFwcGxpZWQuIFRoZSBsb2ctdHJhbnNmb3JtZWQgc2VyaWVzIGV4aGliaXRzIGEgbW9yZSBzdGFibGUgcGF0dGVybiwgbWFraW5nIGl0IGVhc2llciB0byBhbmFseXplIGFuZCBtb2RlbC4gVGhlIHRyYW5zZm9ybWF0aW9uIGhlbHBzIHJlZHVjZSB0aGUgaW1wYWN0IG9mIGxhcmdlIGZsdWN0dWF0aW9ucyBhbmQgc3RhYmlsaXplcyB0aGUgdmFyaWFiaWxpdHkgaW4gdGhlIGRhdGEuDQpgYGANCg0KIyMjIDMuIFVzZSB0aGUgY2FuYWRpYW5fZ2FzIGRhdGEgKG1vbnRobHkgQ2FuYWRpYW4gZ2FzIHByb2R1Y3Rpb24gaW4gYmlsbGlvbnMgb2YgY3ViaWMgbWV0cmVzLCBKYW51YXJ5IDE5NjAg4oCTIEZlYnJ1YXJ5IDIwMDUpLg0KDQojIyMjIDNhLiBQbG90IHRoZSBkYXRhIHVzaW5nIGF1dG9wbG90KCksIGdnX3N1YnNlcmllcygpICwgZ2dfc2Vhc29uKCkgdG8gbG9vayBhdCB0aGUgZWZmZWN0IG9mIHRoZSBjaGFuZ2luZyBzZWFzb25hbGl0eSBvdmVyIHRpbWUuIERlc2NyaWJlIHRoZSBncmFwaHMgaW4geW91ciBvd24gd29yZHMuIFdoYXQgZG8geW91IHNlZT8gV2hhdCB0eXBlIHBmIHBhdHRlcm4gZG8geW91IG9ic2VydmU/DQoNCmBgYHtyLCB3YXJuaW5nPUZBTFNFfQ0KIyBMb2FkaW5nIHRoZSBjYW5hZGlhbl9nYXMgZGF0YXNldA0KY2FuYWRpYW5fZ2FzDQoNCiMgUGxvdHRpbmcgdGhlIGRhdGEgdXNpbmcgYXV0b3Bsb3QoKQ0KYXV0b3Bsb3QoY2FuYWRpYW5fZ2FzKSArDQogIGxhYnModGl0bGUgPSAiQ2FuYWRpYW4gR2FzIFByb2R1Y3Rpb24gT3ZlciBUaW1lIiwNCiAgICAgICB5ID0gIkdhcyBQcm9kdWN0aW9uIChiaWxsaW9uIGN1YmljIG1ldGVycykiLA0KICAgICAgIHggPSAiWWVhciIpICsNCiAgdGhlbWVfbWluaW1hbCgpDQoNCiMgUGxvdHRpbmcgdGhlIGRhdGEgdXNpbmcgZ2dfc3Vic2VyaWVzKCkNCmdnX3N1YnNlcmllcyhjYW5hZGlhbl9nYXMpICsNCiAgbGFicyh0aXRsZSA9ICJTdWJzZXJpZXMgUGxvdCBvZiBDYW5hZGlhbiBHYXMgUHJvZHVjdGlvbiIsDQogICAgICAgeSA9ICJHYXMgUHJvZHVjdGlvbiAoYmlsbGlvbiBjdWJpYyBtZXRlcnMpIiwNCiAgICAgICB4ID0gIk1vbnRoIikgKw0KICB0aGVtZV9taW5pbWFsKCkNCg0KIyBQbG90dGluZyB0aGUgZGF0YSB1c2luZyBnZ19zZWFzb24oKQ0KZ2dfc2Vhc29uKGNhbmFkaWFuX2dhcykgKw0KICBsYWJzKHRpdGxlID0gIlNlYXNvbmFsIFBsb3Qgb2YgQ2FuYWRpYW4gR2FzIFByb2R1Y3Rpb24iLA0KICAgICAgIHkgPSAiR2FzIFByb2R1Y3Rpb24gKGJpbGxpb24gY3ViaWMgbWV0ZXJzKSIsDQogICAgICAgeCA9ICJNb250aCIpICsNCiAgdGhlbWVfbWluaW1hbCgpDQoNCiMgM2EuQW5zd2VyOg0KIyBUaGUgYGF1dG9wbG90KClgIG9mIENhbmFkaWFuIGdhcyBwcm9kdWN0aW9uIHNob3dzIGFuIHVwd2FyZCB0cmVuZCBmcm9tIDE5NjAgdG8gdGhlIGVhcmx5IDIwMDBzLCB3aXRoIGluY3JlYXNpbmcgdmFyaWFiaWxpdHkgb3ZlciB0aW1lLiBUaGUgYGdnX3N1YnNlcmllcygpYCBhbmQgYGdnX3NlYXNvbigpYCBwbG90cyByZXZlYWwgc3Ryb25nIHNlYXNvbmFsaXR5LCB3aXRoIGdhcyBwcm9kdWN0aW9uIHBlYWtpbmcgaW4gd2ludGVyIG1vbnRocyAoZS5nLiwgRGVjZW1iZXIgYW5kIEphbnVhcnkpIGFuZCBkaXBwaW5nIGluIHN1bW1lciBtb250aHMgKGUuZy4sIEp1bmUgYW5kIEp1bHkpLiBUaGlzIHNlYXNvbmFsIHBhdHRlcm4gaXMgY29uc2lzdGVudCBvdmVyIHRpbWUsIHRob3VnaCB0aGUgbWFnbml0dWRlIG9mIHBlYWtzIGFuZCB0cm91Z2hzIG1heSB2YXJ5IHNsaWdodGx5LiBUaGUgZGF0YSBzdWdnZXN0cyB0aGF0IGdhcyBwcm9kdWN0aW9uIGlzIGhpZ2hseSBpbmZsdWVuY2VkIGJ5IHNlYXNvbmFsIGRlbWFuZCwgcGFydGljdWxhcmx5IGZvciBoZWF0aW5nIGR1cmluZyBjb2xkZXIgbW9udGhzLg0KYGBgDQoNCiMjIyAzYi4NCg0KRG8gYW4gU1RMIGRlY29tcG9zaXRpb24gb2YgdGhlIGRhdGEuIFlvdSB3aWxsIG5lZWQgdG8gY2hvb3NlIGEgc2Vhc29uYWwgd2luZG93IHRvIGFsbG93IGZvciB0aGUgY2hhbmdpbmcgc2hhcGUgb2YgdGhlIHNlYXNvbmFsIGNvbXBvbmVudC4NCg0KYGBge3IsIHdhcm5pbmc9RkFMU0V9DQoNCiMgUGVyZm9ybWluZyBTVEwgZGVjb21wb3NpdGlvbiBvbiB0aGUgY2FuYWRpYW5fZ2FzIGRhdGENCnN0bF9kZWNvbXAgPC0gY2FuYWRpYW5fZ2FzICU+JQ0KICBtb2RlbChTVEwoVm9sdW1lIH4gdHJlbmQod2luZG93ID0gNykgKyBzZWFzb24od2luZG93ID0gInBlcmlvZGljIikpKSAlPiUNCiAgY29tcG9uZW50cygpDQoNCiMgUGxvdHRpbmcgdGhlIFNUTCBkZWNvbXBvc2l0aW9uDQphdXRvcGxvdChzdGxfZGVjb21wKSArDQogIGxhYnModGl0bGUgPSAiU1RMIERlY29tcG9zaXRpb24gb2YgQ2FuYWRpYW4gR2FzIFByb2R1Y3Rpb24iLA0KICAgICAgIHkgPSAiR2FzIFByb2R1Y3Rpb24gKGJpbGxpb24gY3ViaWMgbWV0ZXJzKSIsDQogICAgICAgeCA9ICJZZWFyIikgKw0KICB0aGVtZV9taW5pbWFsKCkNCg0KIyAzYi5BbnN3ZXI6DQojIEFuIFNUTCBkZWNvbXBvc2l0aW9uIHdhcyBwZXJmb3JtZWQgb24gdGhlIENhbmFkaWFuIGdhcyBwcm9kdWN0aW9uIGRhdGEuIFRoZSBkZWNvbXBvc2l0aW9uIHNlcGFyYXRlcyB0aGUgdGltZSBzZXJpZXMgaW50byB0aHJlZSBjb21wb25lbnRzOiB0cmVuZCwgc2Vhc29uYWwsIGFuZCByZW1haW5kZXIuIEEgdHJlbmQgd2luZG93IG9mIDcgd2FzIGNob3NlbiB0byBjYXB0dXJlIG1lZGl1bS10ZXJtIGZsdWN0dWF0aW9ucywgYW5kIHRoZSBzZWFzb25hbCBjb21wb25lbnQgd2FzIHRyZWF0ZWQgYXMgcGVyaW9kaWMgKGZpeGVkIG92ZXIgdGltZSkuIFRoZSBkZWNvbXBvc2l0aW9uIHJldmVhbHMgYSBjbGVhciB1cHdhcmQgdHJlbmQsIHN0cm9uZyBzZWFzb25hbGl0eSB3aXRoIHBlYWtzIGluIHdpbnRlciBtb250aHMsIGFuZCBhIHJlbWFpbmRlciBjb21wb25lbnQgdGhhdCBjYXB0dXJlcyBpcnJlZ3VsYXIgZmx1Y3R1YXRpb25zLiBUaGUgc2Vhc29uYWwgcGF0dGVybiBpcyBjb25zaXN0ZW50IG92ZXIgdGltZSwgaW5kaWNhdGluZyBzdGFibGUgc2Vhc29uYWwgZGVtYW5kIGZvciBnYXMuDQpgYGANCg0KIyMjIDNjLg0KDQpIb3cgZG9lcyB0aGUgc2Vhc29uYWwgc2hhcGUgY2hhbmdlIG92ZXIgdGltZT8gW0hpbnQ6IFRyeSBwbG90dGluZyB0aGUgc2Vhc29uYWwgY29tcG9uZW50IHVzaW5nIGdnX3NlYXNvbigpLl0NCg0KYGBge3IsIHdhcm5pbmc9RkFMU0V9DQoNCiMgRW5zdXJpbmcgdGhlIHN0bF9kZWNvbXAgb2JqZWN0IGlzIGNyZWF0ZWQgY29ycmVjdGx5DQpzdGxfZGVjb21wIDwtIGNhbmFkaWFuX2dhcyAlPiUNCiAgbW9kZWwoU1RMKFZvbHVtZSB+IHRyZW5kKHdpbmRvdyA9IDcpICsgc2Vhc29uKHdpbmRvdyA9ICJwZXJpb2RpYyIpKSkgJT4lDQogIGNvbXBvbmVudHMoKQ0KDQojIFBsb3R0aW5nIHRoZSBzZWFzb25hbCBjb21wb25lbnQgdXNpbmcgZ2dfc2Vhc29uKCkNCnN0bF9kZWNvbXAgJT4lDQogIGdnX3NlYXNvbihzZWFzb25feWVhcikgKw0KICBsYWJzKHRpdGxlID0gIlNlYXNvbmFsIENvbXBvbmVudCBvZiBDYW5hZGlhbiBHYXMgUHJvZHVjdGlvbiBPdmVyIFRpbWUiLA0KICAgICAgIHkgPSAiU2Vhc29uYWwgQ29tcG9uZW50IChiaWxsaW9uIGN1YmljIG1ldGVycykiLA0KICAgICAgIHggPSAiTW9udGgiKSArDQogIHRoZW1lX21pbmltYWwoKQ0KDQojIDNjLkFuc3dlcjoNCiMgVGhlIHNlYXNvbmFsIGNvbXBvbmVudCBvZiBDYW5hZGlhbiBnYXMgcHJvZHVjdGlvbiBzaG93cyBhIGNvbnNpc3RlbnQgcGF0dGVybiBvdmVyIHRpbWUsIHdpdGggcGVha3MgaW4gd2ludGVyIG1vbnRocyAoZS5nLiwgRGVjZW1iZXIgYW5kIEphbnVhcnkpIGFuZCB0cm91Z2hzIGluIHN1bW1lciBtb250aHMgKGUuZy4sIEp1bmUgYW5kIEp1bHkpLiBIb3dldmVyLCB0aGUgbWFnbml0dWRlIG9mIHRoZXNlIHBlYWtzIGFuZCB0cm91Z2hzIHZhcmllcyBzbGlnaHRseSBhY3Jvc3MgeWVhcnMuIEZvciBleGFtcGxlLCB0aGUgd2ludGVyIHBlYWtzIG1heSBiZSBoaWdoZXIgaW4gc29tZSB5ZWFycyBkdWUgdG8gY29sZGVyIHdlYXRoZXIgb3IgaW5jcmVhc2VkIGRlbWFuZCBmb3IgaGVhdGluZy4gT3ZlcmFsbCwgdGhlIHNlYXNvbmFsIHNoYXBlIHJlbWFpbnMgc3RhYmxlLCBpbmRpY2F0aW5nIHRoYXQgdGhlIHNlYXNvbmFsIGRlbWFuZCBmb3IgZ2FzIGlzIGNvbnNpc3RlbnQgb3ZlciB0aW1lLg0KYGBgDQoNCiMjIyAzZC4NCg0KcHJvZHVjZSBhIHBsYXVzaWJsZSBzZWFzb25hbGx5IGFkanVzdGVkIHNlcmllcz8gV2hhdCBhcmUgdGhlc2UgbnVtYmVycywgcGxvdCB0aGUgc2VyaWVzLg0KDQpgYGB7ciwgd2FybmluZz1GQUxTRX0NCg0KIyBFbnN1cmluZyB0aGUgc3RsX2RlY29tcCBvYmplY3QgaXMgY3JlYXRlZCBjb3JyZWN0bHkNCnN0bF9kZWNvbXAgPC0gY2FuYWRpYW5fZ2FzICU+JQ0KICBtb2RlbChTVEwoVm9sdW1lIH4gdHJlbmQod2luZG93ID0gNykgKyBzZWFzb24od2luZG93ID0gInBlcmlvZGljIikpKSAlPiUNCiAgY29tcG9uZW50cygpDQoNCiMgRXh0cmFjdGluZyB0aGUgc2Vhc29uYWxseSBhZGp1c3RlZCBzZXJpZXMNCnNlYXNvbmFsbHlfYWRqdXN0ZWQgPC0gc3RsX2RlY29tcCAlPiUNCiAgbXV0YXRlKFNlYXNvbmFsbHlfQWRqdXN0ZWQgPSBWb2x1bWUgLSBzZWFzb25feWVhcikNCg0KIyBQbG90dGluZyB0aGUgc2Vhc29uYWxseSBhZGp1c3RlZCBzZXJpZXMNCnNlYXNvbmFsbHlfYWRqdXN0ZWQgJT4lDQogIGF1dG9wbG90KFNlYXNvbmFsbHlfQWRqdXN0ZWQpICsNCiAgbGFicyh0aXRsZSA9ICJTZWFzb25hbGx5IEFkanVzdGVkIENhbmFkaWFuIEdhcyBQcm9kdWN0aW9uIiwNCiAgICAgICB5ID0gIkdhcyBQcm9kdWN0aW9uIChiaWxsaW9uIGN1YmljIG1ldGVycykiLA0KICAgICAgIHggPSAiWWVhciIpICsNCiAgdGhlbWVfbWluaW1hbCgpDQoNCiMgM2QuQW5zd2VyOg0KIyBUaGUgc2Vhc29uYWxseSBhZGp1c3RlZCBzZXJpZXMgZm9yIENhbmFkaWFuIGdhcyBwcm9kdWN0aW9uIHdhcyBwcm9kdWNlZCBieSByZW1vdmluZyB0aGUgc2Vhc29uYWwgY29tcG9uZW50IGZyb20gdGhlIG9yaWdpbmFsIGRhdGEuIFRoaXMgc2VyaWVzIHJlcHJlc2VudHMgdGhlIHVuZGVybHlpbmcgdHJlbmQgYW5kIGlycmVndWxhciBmbHVjdHVhdGlvbnMgaW4gZ2FzIHByb2R1Y3Rpb24sIHdpdGhvdXQgdGhlIGluZmx1ZW5jZSBvZiBzZWFzb25hbCBwYXR0ZXJucy4gVGhlIHBsb3Qgb2YgdGhlIHNlYXNvbmFsbHkgYWRqdXN0ZWQgc2VyaWVzIHNob3dzIGEgY2xlYXIgdXB3YXJkIHRyZW5kIG92ZXIgdGltZSwgd2l0aCBzb21lIGlycmVndWxhciBmbHVjdHVhdGlvbnMuIFRoaXMgYWRqdXN0ZWQgc2VyaWVzIGlzIHVzZWZ1bCBmb3IgYW5hbHl6aW5nIGxvbmctdGVybSB0cmVuZHMgYW5kIGlkZW50aWZ5aW5nIGFub21hbGllcyBvciBpcnJlZ3VsYXIgZXZlbnRzIGluIHRoZSBkYXRhLg0KYGBgDQoNCiMjIyA0Lg0KDQpGb3IgcmV0YWlsIHRpbWUgc2VyaWVzLCB1c2UgdGhlIGJlbG93IGNvZGU6DQoNCmBgYHtyLCB3YXJuaW5nPUZBTFNFfQ0KDQojIHJ1bmluZyB0aGUgY29kZQ0Kc2V0LnNlZWQoMTIzNDU2NzgpDQoNCm15c2VyaWVzIDwtIGF1c19yZXRhaWwgJT4lDQogIGZpbHRlcihgU2VyaWVzIElEYCA9PSBzYW1wbGUoYXVzX3JldGFpbCRgU2VyaWVzIElEYCwxKSkNCg0KbXlzZXJpZXMNCg0KYGBgDQoNCiMjIyMgNGEuDQoNCkNyZWF0ZSBhIHRyYWluaW5nIGRhdGFzZXQgY29uc2lzdGluZyBvZiBvYnNlcnZhdGlvbnMgYmVmb3JlIDIwMTENCg0KYGBge3IsIHdhcm5pbmc9RkFMU0V9DQoNCm15c2VyaWVzX3RyYWluIDwtIG15c2VyaWVzICU+JQ0KICBmaWx0ZXIoeWVhcihNb250aCkgPCAyMDExKQ0KDQpoZWFkKG15c2VyaWVzX3RyYWluKQ0KDQojIEEgdHJhaW5pbmcgZGF0YXNldCB3YXMgY3JlYXRlZCBieSBmaWx0ZXJpbmcgdGhlIGBteXNlcmllc2AgZGF0YXNldCB0byBpbmNsdWRlIG9ubHkgb2JzZXJ2YXRpb25zIGJlZm9yZSB0aGUgeWVhciAyMDExLiBUaGlzIHRyYWluaW5nIGRhdGFzZXQgd2lsbCBiZSB1c2VkIHRvIGZpdCBtb2RlbHMgYW5kIG1ha2UgZm9yZWNhc3RzLCB3aGlsZSB0aGUgcmVtYWluaW5nIGRhdGEgKGZyb20gMjAxMSBvbndhcmRzKSB3aWxsIHNlcnZlIGFzIHRoZSB0ZXN0IGRhdGFzZXQgZm9yIGV2YWx1YXRpbmcgdGhlIG1vZGVsJ3MgcGVyZm9ybWFuY2UuDQoNCmBgYA0KDQojIyMjIDRiLg0KDQpDaGVjayB0aGF0IHlvdXIgZGF0YSBoYXZlIGJlZW4gc3BsaXQgYXBwcm9wcmlhdGVseSBieSBwcm9kdWNpbmcgdGhlIGZvbGxvd2luZyBwbG90Lg0KDQpgYGB7ciwgd2FybmluZz1GQUxTRX0NCg0KYXV0b3Bsb3QobXlzZXJpZXMsIFR1cm5vdmVyKSArDQogIGF1dG9sYXllcihteXNlcmllc190cmFpbiwgVHVybm92ZXIsIGNvbG91ciA9ICJyZWQiKQ0KDQojIFRoZSBwbG90IG92ZXJsYXlzIHRoZSB0cmFpbmluZyBkYXRhc2V0IChpbiByZWQpIG9uIHRvcCBvZiB0aGUgZnVsbCBkYXRhc2V0LiBUaGlzIHZpc3VhbGl6YXRpb24gY29uZmlybXMgdGhhdCB0aGUgdHJhaW5pbmcgZGF0YXNldCBpbmNsdWRlcyBvbmx5IHRoZSBvYnNlcnZhdGlvbnMgYmVmb3JlIDIwMTEsIGFzIGludGVuZGVkLiBUaGUgc3BsaXQgYmV0d2VlbiB0aGUgdHJhaW5pbmcgYW5kIHRlc3QgZGF0YXNldHMgYXBwZWFycyBhcHByb3ByaWF0ZSwgd2l0aCB0aGUgdHJhaW5pbmcgZGF0YSBlbmRpbmcgYXQgdGhlIGNsb3NlIG9mIDIwMTAgYW5kIHRoZSB0ZXN0IGRhdGEgYmVnaW5uaW5nIGluIDIwMTEuDQpgYGANCg0KIyMjIyA0Yy4NCg0KRml0IGEgc2Vhc29uYWwgbmHDr3ZlIG1vZGVsIHVzaW5nIFNOQUlWRSgpIGFwcGxpZWQgdG8geW91ciB0cmFpbmluZyBkYXRhIChteXNlcmllc190cmFpbikuDQoNCmBgYHtyLCB3YXJuaW5nPUZBTFNFfQ0KICNBbnN3ZXI6DQogICAgZml0IDwtIG15c2VyaWVzX3RyYWluICU+JQ0KICAgICAgbW9kZWwoU05BSVZFKFR1cm5vdmVyKSkNCmZpdA0KDQojIEEgc2Vhc29uYWwgbmHDr3ZlIG1vZGVsIChTTkFJVkUpIHdhcyBmaXR0ZWQgdG8gdGhlIHRyYWluaW5nIGRhdGEgKGBteXNlcmllc190cmFpbmApIHVzaW5nIHRoZSBgU05BSVZFKFR1cm5vdmVyKWAgZnVuY3Rpb24uIFRoZSBtb2RlbCBhc3N1bWVzIHRoYXQgdGhlIGBUdXJub3ZlcmAgZm9yIHRoZSBuZXh0IHBlcmlvZCB3aWxsIGJlIGVxdWFsIHRvIHRoZSBgVHVybm92ZXJgIGluIHRoZSBzYW1lIHBlcmlvZCBvZiB0aGUgcHJldmlvdXMgc2Vhc29uLiBUaGUgZml0dGVkIG1vZGVsIGlzIHN0b3JlZCBpbiB0aGUgYGZpdGAgb2JqZWN0LCB3aGljaCBjYW4gbm93IGJlIHVzZWQgZm9yIGZvcmVjYXN0aW5nLCByZXNpZHVhbCBhbmFseXNpcywgYW5kIGFjY3VyYWN5IGV2YWx1YXRpb24uDQpgYGANCg0KIyMjIyA0ZC4NCg0KQ2hlY2sgdGhlIHJlc2lkdWFscy4NCg0KYGBge3IsIHdhcm5pbmc9RkFMU0V9DQojIEV4dHJhY3RpbmcgcmVzaWR1YWxzIHVzaW5nIGF1Z21lbnQoKQ0KcmVzaWR1YWxzIDwtIGZpdCAlPiUNCiAgYXVnbWVudCgpDQoNCiMgUGxvdHRpbmcgdGhlIHJlc2lkdWFscyBvdmVyIHRpbWUNCnJlc2lkdWFscyAlPiUNCiAgZ2dwbG90KGFlcyh4ID0gTW9udGgsIHkgPSAucmVzaWQpKSArDQogIGdlb21fbGluZSgpICsNCiAgbGFicyh0aXRsZSA9ICJSZXNpZHVhbHMgb2YgdGhlIFNlYXNvbmFsIE5hw692ZSBNb2RlbCIsDQogICAgICAgeSA9ICJSZXNpZHVhbHMiLA0KICAgICAgIHggPSAiWWVhciIpICsNCiAgdGhlbWVfbWluaW1hbCgpDQoNCiMgSGlzdG9ncmFtIG9mIHJlc2lkdWFscw0KcmVzaWR1YWxzICU+JQ0KICBnZ3Bsb3QoYWVzKHggPSAucmVzaWQpKSArDQogIGdlb21faGlzdG9ncmFtKGJpbndpZHRoID0gMC4yLCBmaWxsID0gImJsdWUiLCBjb2xvciA9ICJibGFjayIpICsNCiAgbGFicyh0aXRsZSA9ICJIaXN0b2dyYW0gb2YgUmVzaWR1YWxzIiwNCiAgICAgICB4ID0gIlJlc2lkdWFscyIsDQogICAgICAgeSA9ICJGcmVxdWVuY3kiKSArDQogIHRoZW1lX21pbmltYWwoKQ0KDQojIEFDRiBwbG90IG9mIHJlc2lkdWFscw0KcmVzaWR1YWxzICU+JQ0KICBBQ0YoLnJlc2lkKSAlPiUNCiAgYXV0b3Bsb3QoKSArDQogIGxhYnModGl0bGUgPSAiQUNGIFBsb3Qgb2YgUmVzaWR1YWxzIiwNCiAgICAgICB5ID0gIkFDRiIsDQogICAgICAgeCA9ICJMYWciKSArDQogIHRoZW1lX21pbmltYWwoKQ0KDQojIERvIHRoZSByZXNpZHVhbHMgYXBwZWFyIHRvIGJlIHVuY29ycmVsYXRlZCBhbmQgbm9ybWFsbHkgZGlzdHJpYnV0ZWQ/DQojIEFuc3c6DQojIFRoZSByZXNpZHVhbHMgb2YgdGhlIHNlYXNvbmFsIG5hw692ZSBtb2RlbCB3ZXJlIGNoZWNrZWQgdXNpbmcgZGlhZ25vc3RpYyBwbG90cy4gVGhlIHRpbWUgcGxvdCBvZiB0aGUgcmVzaWR1YWxzIHNob3dzIG5vIG9idmlvdXMgcGF0dGVybnMgb3IgdHJlbmRzLCBzdWdnZXN0aW5nIHRoYXQgdGhlIG1vZGVsIGhhcyBjYXB0dXJlZCB0aGUgdW5kZXJseWluZyBzdHJ1Y3R1cmUgb2YgdGhlIGRhdGEuIFRoZSBoaXN0b2dyYW0gb2YgdGhlIHJlc2lkdWFscyBhcHBlYXJzIGFwcHJveGltYXRlbHkgbm9ybWFsbHkgZGlzdHJpYnV0ZWQsIGFuZCB0aGUgQUNGIHBsb3Qgc2hvd3Mgbm8gc2lnbmlmaWNhbnQgYXV0b2NvcnJlbGF0aW9uLCBpbmRpY2F0aW5nIHRoYXQgdGhlIHJlc2lkdWFscyBhcmUgdW5jb3JyZWxhdGVkLiBPdmVyYWxsLCB0aGUgcmVzaWR1YWxzIGFwcGVhciB0byBzYXRpc2Z5IHRoZSBhc3N1bXB0aW9ucyBvZiBiZWluZyB1bmNvcnJlbGF0ZWQgYW5kIG5vcm1hbGx5IGRpc3RyaWJ1dGVkLg0KYGBgDQoNCiMjIyMgNGUuDQoNClByb2R1Y2UgZm9yZWNhc3RzIGZvciB0aGUgdGVzdCBkYXRhIHdpdGggZ2l2ZW4gY29kZSBiZWxvdzoNCg0KYGBge3IsIHdhcm5pbmc9RkFMU0V9DQojIDRlIEFuc3dlcjoNCiMgRm9yZWNhc3QgZm9yIHRoZSB0ZXN0IGRhdGENCmZjIDwtIGZpdCAlPiUgIA0KICBmb3JlY2FzdChuZXdfZGF0YSA9IGFudGlfam9pbihteXNlcmllcywgbXlzZXJpZXNfdHJhaW4pKQ0KDQojIFBsb3QgdGhlIGZvcmVjYXN0cw0KZmMgJT4lIGF1dG9wbG90KG15c2VyaWVzKQ0KDQojIEZvcmVjYXN0cyBmb3IgdGhlIHRlc3QgZGF0YSB3ZXJlIHByb2R1Y2VkIHVzaW5nIHRoZSBmaXR0ZWQgc2Vhc29uYWwgbmHDr3ZlIG1vZGVsIChgZml0YCkuIFRoZSBgZm9yZWNhc3QoKWAgZnVuY3Rpb24gZ2VuZXJhdGVkIHByZWRpY3Rpb25zIGZvciB0aGUgdGVzdCBkYXRhLCB3aGljaCB3YXMgY3JlYXRlZCBieSBleGNsdWRpbmcgdGhlIHRyYWluaW5nIGRhdGEgdXNpbmcgYGFudGlfam9pbihteXNlcmllcywgbXlzZXJpZXNfdHJhaW4pYC4gVGhlIGZvcmVjYXN0cyB3ZXJlIHRoZW4gcGxvdHRlZCBhbG9uZ3NpZGUgdGhlIGFjdHVhbCBkYXRhIHVzaW5nIGBhdXRvcGxvdCgpYCwgYWxsb3dpbmcgZm9yIGEgdmlzdWFsIGNvbXBhcmlzb24gb2YgdGhlIHByZWRpY3RlZCBhbmQgb2JzZXJ2ZWQgdmFsdWVzLiBUaGlzIHN0ZXAgaXMgY3J1Y2lhbCBmb3IgZXZhbHVhdGluZyB0aGUgbW9kZWwncyBwZXJmb3JtYW5jZSBvbiB1bnNlZW4gZGF0YS4NCmBgYA0KDQpKb2luaW5nLCBieSA9IGMoIlN0YXRlIiwgIkluZHVzdHJ5IiwgIlNlcmllcyBJRCIsICJNb250aCIsICJUdXJub3ZlciIpDQoNCiMjIyMgNGYuDQoNCkNvbXBhcmUgdGhlIGFjY3VyYWN5IG9mIHlvdXIgZm9yZWNhc3RzIGFnYWluc3QgdGhlIGFjdHVhbCB2YWx1ZXMgd2l0aCBnaXZlbiBjb2RlIGJlbG93Og0KDQpgYGB7ciwgd2FybmluZz1GQUxTRX0NCg0KIyBDb21wYXJpbmcgZm9yZWNhc3QgYWNjdXJhY3kNCmFjY3VyYWN5KGZjLCBteXNlcmllcykNCg0KIyA0ZiBBbnN3Og0KIyBUaGUgYWNjdXJhY3kgbWV0cmljcyBmb3IgdGhlIHRlc3QgZGF0YXNldCB3ZXJlIGNvbXB1dGVkIHVzaW5nIHRoZSBzZWFzb25hbCBuYcOvdmUgbW9kZWwuIFRoZSBtb2RlbCBhY2hpZXZlZCBhIE1BU0Ugb2YgMS4zNiwgaW5kaWNhdGluZyBzbGlnaHRseSB3b3JzZSBwZXJmb3JtYW5jZSB0aGFuIGEgbmHDr3ZlIGZvcmVjYXN0LiBPdGhlciBtZXRyaWNzIGluY2x1ZGUgYW4gUk1TRSBvZiAxLjU1LCBhbiBNQUUgb2YgMS4yNCwgYW5kIGEgTUFQRSBvZiA5LjA2LiBUaGUgc2lnbmlmaWNhbnQgYXV0b2NvcnJlbGF0aW9uIGluIHRoZSByZXNpZHVhbHMgKEFDRjEgPSAwLjYwMSkgc3VnZ2VzdHMgdGhhdCB0aGUgbW9kZWwgbWF5IG5vdCBmdWxseSBjYXB0dXJlIHRoZSB1bmRlcmx5aW5nIHBhdHRlcm5zIGluIHRoZSBkYXRhLiBUaGVzZSByZXN1bHRzIGluZGljYXRlIHRoYXQgd2hpbGUgdGhlIG1vZGVsIHByb3ZpZGVzIHJlYXNvbmFibGUgZm9yZWNhc3RzLCBpdCBtYXkgbm90IGdlbmVyYWxpemUgd2VsbCB0byB1bnNlZW4gZGF0YSwgYW5kIHRoZXJlIGlzIHJvb20gZm9yIGltcHJvdmVtZW50IGJ5IGV4cGxvcmluZyBtb3JlIHNvcGhpc3RpY2F0ZWQgbW9kZWxpbmcgdGVjaG5pcXVlcy4NCmBgYA0KDQojIyMjIDRnLg0KDQpIb3cgc2Vuc2l0aXZlIGFyZSB0aGUgYWNjdXJhY3kgbWVhc3VyZXMgdG8gdGhlIGFtb3VudCBvZiB0cmFpbmluZyBkYXRhIHVzZWQ/DQoNCmBgYHtyLCB3YXJuaW5nPUZBTFNFfQ0KDQojIENyZWF0aW5nIHRyYWluaW5nIGRhdGFzZXRzIHdpdGggZGlmZmVyZW50IHNpemVzDQp0cmFpbl81MCA8LSBteXNlcmllcyAlPiUgZmlsdGVyKHllYXIoTW9udGgpIDwgMjAwNSkgIyA1MCUgb2YgdGhlIGRhdGENCnRyYWluXzcwIDwtIG15c2VyaWVzICU+JSBmaWx0ZXIoeWVhcihNb250aCkgPCAyMDA4KSAjIDcwJSBvZiB0aGUgZGF0YQ0KdHJhaW5fOTAgPC0gbXlzZXJpZXMgJT4lIGZpbHRlcih5ZWFyKE1vbnRoKSA8IDIwMTApICMgOTAlIG9mIHRoZSBkYXRhDQoNCiMgRml0dGluZyB0aGUgc2Vhc29uYWwgbmHDr3ZlIG1vZGVsIHRvIGVhY2ggdHJhaW5pbmcgZGF0YXNldA0KZml0XzUwIDwtIHRyYWluXzUwICU+JSBtb2RlbChTTkFJVkUoVHVybm92ZXIpKQ0KZml0XzcwIDwtIHRyYWluXzcwICU+JSBtb2RlbChTTkFJVkUoVHVybm92ZXIpKQ0KZml0XzkwIDwtIHRyYWluXzkwICU+JSBtb2RlbChTTkFJVkUoVHVybm92ZXIpKQ0KDQojIENvbXB1dGluZyBhY2N1cmFjeSBtZXRyaWNzIGZvciBlYWNoIG1vZGVsDQphY2N1cmFjeV81MCA8LSBmaXRfNTAgJT4lIGFjY3VyYWN5KCkNCmFjY3VyYWN5XzcwIDwtIGZpdF83MCAlPiUgYWNjdXJhY3koKQ0KYWNjdXJhY3lfOTAgPC0gZml0XzkwICU+JSBhY2N1cmFjeSgpDQoNCiMgQ29tcGFyaW5nIHRoZSBhY2N1cmFjeSBtZXRyaWNzDQphY2N1cmFjeV81MA0KYWNjdXJhY3lfNzANCmFjY3VyYWN5XzkwDQoNCiMgNGcgQW5zd2VyOg0KIyBUaGUgc2Vuc2l0aXZpdHkgb2YgYWNjdXJhY3kgbWVhc3VyZXMgdG8gdGhlIGFtb3VudCBvZiB0cmFpbmluZyBkYXRhIHdhcyBldmFsdWF0ZWQgYnkgZml0dGluZyBhIHNlYXNvbmFsIG5hw692ZSBtb2RlbCB0byB0cmFpbmluZyBkYXRhc2V0cyBvZiB2YXJ5aW5nIHNpemVzICg1MCUsIDcwJSwgYW5kIDkwJSBvZiB0aGUgZGF0YSkuIFJlc3VsdHMgc2hvdyBtYXJnaW5hbCBpbXByb3ZlbWVudHMgaW4gUk1TRSAoZnJvbSAxLjI4IHRvIDEuMjIpLCBNQUUsIGFuZCBNQVBFIChmcm9tIDE0LjQgdG8gMTIuNykgYXMgdHJhaW5pbmcgZGF0YSBpbmNyZWFzZXMuIEhvd2V2ZXIsIE1BU0UgcmVtYWlucyBjb25zdGFudCBhdCAxLCBpbmRpY2F0aW5nIG5vIGltcHJvdmVtZW50IHJlbGF0aXZlIHRvIGEgbmHDr3ZlIGZvcmVjYXN0LCBhbmQgQUNGMSB2YWx1ZXMgcmVtYWluIGhpZ2ggKHJhbmdpbmcgZnJvbSAwLjgxNiB0byAwLjc5NSksIHN1Z2dlc3RpbmcgcGVyc2lzdGVudCByZXNpZHVhbCBhdXRvY29ycmVsYXRpb24uIFRoaXMgaW5kaWNhdGVzIHRoYXQgd2hpbGUgbW9yZSB0cmFpbmluZyBkYXRhIHNsaWdodGx5IGVuaGFuY2VzIGFjY3VyYWN5LCB0aGUgc2Vhc29uYWwgbmHDr3ZlIG1vZGVsJ3MgcGVyZm9ybWFuY2UgcmVtYWlucyBsaW1pdGVkLCBoaWdobGlnaHRpbmcgdGhlIG5lZWQgZm9yIG1vcmUgc29waGlzdGljYXRlZCBtb2RlbGluZyB0ZWNobmlxdWVzIHRvIGJldHRlciBjYXB0dXJlIHRoZSBkYXRhJ3MgdW5kZXJseWluZyBwYXR0ZXJucy4NCmBgYA0KDQojIyMgNS4NCg0KIyMjIyA1YS4NCg0KQ3JlYXRlIGEgdHJhaW5pbmcgc2V0IGZvciBBdXN0cmFsaWFuIHRha2Vhd2F5IGZvb2QgdHVybm92ZXIgKGF1c19yZXRhaWwpIGJ5IHdpdGhob2xkaW5nIHRoZSBsYXN0IGZvdXIgeWVhcnMgYXMgYSB0ZXN0IHNldC4NCg0KYGBge3IsIHdhcm5pbmc9RkFMU0V9DQoNCiMgTG9hZGluZyB0aGUgYXVzX3JldGFpbCBkYXRhc2V0DQphdXNfcmV0YWlsDQoNCiMgRmlsdGVyaW5nIGZvciB0aGUgIlRha2Vhd2F5IGZvb2Qgc2VydmljZXMiIGluZHVzdHJ5DQp0YWtlYXdheV9mb29kIDwtIGF1c19yZXRhaWwgJT4lDQogIGZpbHRlcihJbmR1c3RyeSA9PSAiVGFrZWF3YXkgZm9vZCBzZXJ2aWNlcyIpDQoNCiMgRmluZGluZyB0aGUgbGF0ZXN0IGRhdGUgaW4gdGhlIGRhdGFzZXQNCmxhdGVzdF9kYXRlIDwtIG1heCh0YWtlYXdheV9mb29kJE1vbnRoKQ0KDQojIENvbnZlcnRpbmcgbGF0ZXN0X2RhdGUgdG8gYSBEYXRlIG9iamVjdA0KbGF0ZXN0X2RhdGUgPC0gYXMuRGF0ZShsYXRlc3RfZGF0ZSkNCg0KIyBDcmVhdGluZyBhIHRyYWluaW5nIHNldCBieSB3aXRoaG9sZGluZyB0aGUgbGFzdCBmb3VyIHllYXJzDQp0cmFpbl90YWtlYXdheSA8LSB0YWtlYXdheV9mb29kICU+JQ0KICBmaWx0ZXIoTW9udGggPD0geWVhcm1vbnRoKGxhdGVzdF9kYXRlIC0geWVhcnMoNCkpKQ0KDQojIFZpZXdpbmcgdGhlIHRyYWluaW5nIGRhdGFzZXQNCmhlYWQodHJhaW5fdGFrZWF3YXkpDQoNCiMgNWEuQW5zd2VyOg0KIyBBIHRyYWluaW5nIHNldCBmb3IgQXVzdHJhbGlhbiB0YWtlYXdheSBmb29kIHR1cm5vdmVyIHdhcyBjcmVhdGVkIGJ5IHdpdGhob2xkaW5nIHRoZSBsYXN0IGZvdXIgeWVhcnMgb2YgZGF0YSBhcyBhIHRlc3Qgc2V0LiBUaGUgdHJhaW5pbmcgc2V0IGluY2x1ZGVzIGFsbCBvYnNlcnZhdGlvbnMgYmVmb3JlIHRoZSBsYXN0IGZvdXIgeWVhcnMsIGFsbG93aW5nIHRoZSBtb2RlbCB0byBiZSB0cmFpbmVkIG9uIGhpc3RvcmljYWwgZGF0YSB3aGlsZSByZXNlcnZpbmcgdGhlIG1vc3QgcmVjZW50IGRhdGEgZm9yIHRlc3RpbmcuDQpgYGANCg0KIyMjIyA1Yi4NCg0KRml0IGFsbCB0aGUgYXBwcm9wcmlhdGUgYmVuY2htYXJrIG1ldGhvZHMgdG8gdGhlIHRyYWluaW5nIHNldCBhbmQgZm9yZWNhc3QgdGhlIHBlcmlvZHMgY292ZXJlZCBieSB0aGUgdGVzdCBzZXQuDQoNCmBgYHtyLHdhcm5pbmc9RkFMU0V9DQoNCiMgRml0dGluZyBiZW5jaG1hcmsgbWV0aG9kcyB0byB0aGUgdHJhaW5pbmcgc2V0DQoNCmZpdF9iZW5jaG1hcmtzIDwtIHRyYWluX3Rha2Vhd2F5ICU+JQ0KICBtb2RlbCgNCiAgICBNZWFuID0gTUVBTihUdXJub3ZlciksDQogICAgTmFpdmUgPSBOQUlWRShUdXJub3ZlciksDQogICAgU2Vhc29uYWxfTmFpdmUgPSBTTkFJVkUoVHVybm92ZXIpLA0KICAgIERyaWZ0ID0gUlcoVHVybm92ZXIgfiBkcmlmdCgpKQ0KICApDQoNCiMgRm9yZWNhc3RpbmcgdGhlIHBlcmlvZHMgY292ZXJlZCBieSB0aGUgdGVzdCBzZXQNCmZjX2JlbmNobWFya3MgPC0gZml0X2JlbmNobWFya3MgJT4lDQogIGZvcmVjYXN0KGggPSAiNCB5ZWFycyIpDQoNCiMgVmlld2luZyB0aGUgZm9yZWNhc3RzDQpmY19iZW5jaG1hcmtzDQoNCiMgUGxvdHRpbmcgdGhlIGZvcmVjYXN0cw0KZmNfYmVuY2htYXJrcyAlPiUNCiAgYXV0b3Bsb3QodHJhaW5fdGFrZWF3YXkpICsNCiAgbGFicyh0aXRsZSA9ICJCZW5jaG1hcmsgRm9yZWNhc3RzIGZvciBBdXN0cmFsaWFuIFRha2Vhd2F5IEZvb2QgVHVybm92ZXIiLA0KICAgICAgIHkgPSAiVHVybm92ZXIiLA0KICAgICAgIHggPSAiWWVhciIpICsNCiAgdGhlbWVfbWluaW1hbCgpDQoNCiMgNWIuQW5zd2VyOg0KIyBGb3VyIGJlbmNobWFyayBtZXRob2RzIHdlcmUgZml0dGVkIHRvIHRoZSB0cmFpbmluZyBzZXQ6IE1lYW4sIE5hw692ZSwgU2Vhc29uYWwgTmHDr3ZlLCBhbmQgRHJpZnQuIEZvcmVjYXN0cyB3ZXJlIGdlbmVyYXRlZCBmb3IgdGhlIHBlcmlvZHMgY292ZXJlZCBieSB0aGUgdGVzdCBzZXQgKHRoZSBsYXN0IGZvdXIgeWVhcnMpLiBUaGVzZSBmb3JlY2FzdHMgcHJvdmlkZSBhIGJhc2VsaW5lIGZvciBldmFsdWF0aW5nIHRoZSBwZXJmb3JtYW5jZSBvZiBtb3JlIGNvbXBsZXggbW9kZWxzLg0KDQpgYGANCg0KIyMjIyA1Yy4NCg0KQ29tcHV0ZSB0aGUgYWNjdXJhY3kgb2YgeW91ciBmb3JlY2FzdHMuIFdoaWNoIG1ldGhvZCBkb2VzIGJlc3Q/DQoNCmBgYHtyLCB3YXJuaW5nPUZBTFNFfQ0KDQojIENvbXB1dGluZyBhY2N1cmFjeSBtZXRyaWNzIGZvciB0aGUgYmVuY2htYXJrIGZvcmVjYXN0cw0KYWNjdXJhY3lfYmVuY2htYXJrcyA8LSBmY19iZW5jaG1hcmtzICU+JQ0KICBhY2N1cmFjeSh0YWtlYXdheV9mb29kKQ0KDQojIFZpZXdpbmcgdGhlIGFjY3VyYWN5IG1ldHJpY3MNCmFjY3VyYWN5X2JlbmNobWFya3MNCg0KIyBJZGVudGlmeWluZyB0aGUgYmVzdC1wZXJmb3JtaW5nIG1ldGhvZA0KYmVzdF9tZXRob2QgPC0gYWNjdXJhY3lfYmVuY2htYXJrcyAlPiUNCiAgZmlsdGVyKFJNU0UgPT0gbWluKFJNU0UpKSAlPiUNCiAgcHVsbCgubW9kZWwpDQoNCiMgUHJpbnRpbmcgdGhlIGJlc3QtcGVyZm9ybWluZyBtZXRob2QNCmJlc3RfbWV0aG9kDQoNCiMgNWMuQW5zd2VyOg0KIyBUaGUgYWNjdXJhY3kgbWV0cmljcyBmb3IgdGhlIGJlbmNobWFyayBmb3JlY2FzdHMgd2VyZSBjb21wdXRlZC4gVGhlIGJlc3QtcGVyZm9ybWluZyBtZXRob2QgaXMgKipEcmlmdCoqLCB3aGljaCBhY2hpZXZlZCB0aGUgbG93ZXN0IFJNU0Ugb2YgKioyLjI2KiogKGZvciBOb3J0aGVybiBUZXJyaXRvcnkpLiBUaGlzIG1ldGhvZCBwcm92aWRlcyB0aGUgbW9zdCBhY2N1cmF0ZSBmb3JlY2FzdHMgZm9yIEF1c3RyYWxpYW4gdGFrZWF3YXkgZm9vZCB0dXJub3ZlciBhbW9uZyB0aGUgYmVuY2htYXJrIG1ldGhvZHMgdGVzdGVkLiBUaGUgRHJpZnQgbW9kZWwgb3V0cGVyZm9ybWVkIHRoZSBNZWFuLCBOYcOvdmUsIGFuZCBTZWFzb25hbCBOYcOvdmUgbWV0aG9kcywgYXMgaXQgZWZmZWN0aXZlbHkgY2FwdHVyZXMgdGhlIHRyZW5kIGluIHRoZSBkYXRhLiBIb3dldmVyLCB0aGUgcmVzaWR1YWxzIGZyb20gdGhpcyBtb2RlbCBzaG91bGQgYmUgY2hlY2tlZCB0byBlbnN1cmUgdGhleSByZXNlbWJsZSB3aGl0ZSBub2lzZSwgYXMgYW55IHJlbWFpbmluZyBwYXR0ZXJucyBjb3VsZCBpbmRpY2F0ZSByb29tIGZvciBmdXJ0aGVyIGltcHJvdmVtZW50Lg0KDQpgYGANCg0KIyMjIyA1ZC4NCg0KRG8gdGhlIHJlc2lkdWFscyBmcm9tIHRoZSBiZXN0IG1ldGhvZCByZXNlbWJsZSB3aGl0ZSBub2lzZT8NCg0KYGBge3IsIHdhcm5pbmc9RkFMU0V9DQoNCiMgRXh0cmFjdGluZyByZXNpZHVhbHMgZnJvbSB0aGUgYmVzdC1wZXJmb3JtaW5nIG1ldGhvZA0KcmVzaWR1YWxzX2Jlc3QgPC0gZml0X2JlbmNobWFya3MgJT4lDQogIHNlbGVjdChhbGxfb2YoYmVzdF9tZXRob2QpKSAlPiUNCiAgcmVzaWR1YWxzKCkNCg0KIyBQbG90dGluZyB0aGUgcmVzaWR1YWxzIG92ZXIgdGltZQ0KcmVzaWR1YWxzX2Jlc3QgJT4lDQogIGdncGxvdChhZXMoeCA9IE1vbnRoLCB5ID0gLnJlc2lkKSkgKw0KICBnZW9tX2xpbmUoKSArDQogIGxhYnModGl0bGUgPSBwYXN0ZSgiUmVzaWR1YWxzIGZyb20gdGhlIiwgYmVzdF9tZXRob2QsICJNb2RlbCIpLA0KICAgICAgIHkgPSAiUmVzaWR1YWxzIiwNCiAgICAgICB4ID0gIlllYXIiKSArDQogIHRoZW1lX21pbmltYWwoKQ0KDQojIEhpc3RvZ3JhbSBvZiByZXNpZHVhbHMNCnJlc2lkdWFsc19iZXN0ICU+JQ0KICBnZ3Bsb3QoYWVzKHggPSAucmVzaWQpKSArDQogIGdlb21faGlzdG9ncmFtKGJpbndpZHRoID0gMC4yLCBmaWxsID0gImJsdWUiLCBjb2xvciA9ICJibGFjayIpICsNCiAgbGFicyh0aXRsZSA9IHBhc3RlKCJIaXN0b2dyYW0gb2YgUmVzaWR1YWxzIGZvciB0aGUiLCBiZXN0X21ldGhvZCwgIk1vZGVsIiksDQogICAgICAgeCA9ICJSZXNpZHVhbHMiLA0KICAgICAgIHkgPSAiRnJlcXVlbmN5IikgKw0KICB0aGVtZV9taW5pbWFsKCkNCg0KIyBBQ0YgcGxvdCBvZiByZXNpZHVhbHMNCnJlc2lkdWFsc19iZXN0ICU+JQ0KICBBQ0YoLnJlc2lkKSAlPiUNCiAgYXV0b3Bsb3QoKSArDQogIGxhYnModGl0bGUgPSBwYXN0ZSgiQUNGIFBsb3Qgb2YgUmVzaWR1YWxzIGZvciB0aGUiLCBiZXN0X21ldGhvZCwgIk1vZGVsIiksDQogICAgICAgeSA9ICJBQ0YiLA0KICAgICAgIHggPSAiTGFnIikgKw0KICB0aGVtZV9taW5pbWFsKCkNCg0KIyA1ZC5BbnN3ZXI6DQojIFRoZSByZXNpZHVhbHMgZnJvbSB0aGUgYmVzdC1wZXJmb3JtaW5nIG1ldGhvZCAoRHJpZnQpIHdlcmUgYW5hbHl6ZWQgdG8gZGV0ZXJtaW5lIGlmIHRoZXkgcmVzZW1ibGUgd2hpdGUgbm9pc2UuIFRoZSB0aW1lIHBsb3Qgb2YgdGhlIHJlc2lkdWFscyBzaG93cyBubyBvYnZpb3VzIHBhdHRlcm5zIG9yIHRyZW5kcywgc3VnZ2VzdGluZyB0aGF0IHRoZSBtb2RlbCBoYXMgY2FwdHVyZWQgdGhlIHVuZGVybHlpbmcgc3RydWN0dXJlIG9mIHRoZSBkYXRhLiBUaGUgaGlzdG9ncmFtIG9mIHRoZSByZXNpZHVhbHMgaXMgYXBwcm94aW1hdGVseSBub3JtYWxseSBkaXN0cmlidXRlZCwgd2l0aCBtb3N0IHJlc2lkdWFscyBjZW50ZXJlZCBhcm91bmQgemVybyBhbmQgYSBiaW53aWR0aCBvZiAwLjIuIFRoZSBBQ0YgcGxvdCBvZiB0aGUgcmVzaWR1YWxzIHNob3dzIG5vIHNpZ25pZmljYW50IGF1dG9jb3JyZWxhdGlvbiBhdCBhbnkgbGFnLCB3aXRoIGFsbCBBQ0YgdmFsdWVzIHdpdGhpbiB0aGUgY29uZmlkZW5jZSBib3VuZHMuIFRoZSBBQ0YxIHZhbHVlIGlzICoqMC4xMjMqKiwgd2hpY2ggc3VnZ2VzdHMgYSBzbGlnaHQgYXV0b2NvcnJlbGF0aW9uIGF0IGxhZyAxLiBUaGVzZSBvYnNlcnZhdGlvbnMgaW5kaWNhdGUgdGhhdCB0aGUgcmVzaWR1YWxzIHJlc2VtYmxlIHdoaXRlIG5vaXNlLCBtZWFuaW5nIHRoZSBtb2RlbCBoYXMgcGVyZm9ybWVkIHdlbGwgYW5kIHRoZXJlIGFyZSBubyBzeXN0ZW1hdGljIHBhdHRlcm5zIGxlZnQgaW4gdGhlIHJlc2lkdWFscy4gSG93ZXZlciwgdGhlIHNsaWdodCBhdXRvY29ycmVsYXRpb24gYXQgbGFnIDEgY291bGQgYmUgZnVydGhlciBpbnZlc3RpZ2F0ZWQuDQoNCmBgYA0KDQojIyMgNi4NCg0KVXNpbmcgdGhlIGNvZGUgYmVsb3csIGdldCBhIHNlcmllcyAoaXQgZ2V0cyBhIHNlcmllcyByYW5kb21seSBieSB1c2luZyBzYW1wbGUoKSBmdW5jdGlvbik6DQoNCmBgYHtyLCB3YXJuaW5nPUZBTFNFfQ0Kc2V0LnNlZWQoMTIzNDU2NzgpDQpteXNlcmllcyA8LSBhdXNfcmV0YWlsICU+JQ0KICBmaWx0ZXIoYFNlcmllcyBJRGAgPT0gc2FtcGxlKGF1c19yZXRhaWwkYFNlcmllcyBJRGAsMSkpDQpteXNlcmllcw0KYGBgDQoNCnNlZSBoZWFkIG9mIHlvdXIgc2VyaWVzIHRvIGNoZWNrIGl0IGlzIGEgdHNpYmJsZSBkYXRhLCBhbmQgcmVtb3ZlIE5B4oCZcyBpZiB0aGVyZSBpcyBhbnkgd2l0aCB0aGVzZSBjb21tYW5kczoNCg0KYGBge3IsIHdhcm5pbmc9RkFMU0V9DQpoZWFkKG15c2VyaWVzKQ0KbXlzZXJpZXMgPSAgbXlzZXJpZXMgJT4lIGZpbHRlcighaXMubmEoYFNlcmllcyBJRGApKQ0KYGBgDQoNCiMjIyMgNmEuDQoNCldoYXQgaXMgdGhlIG5hbWUgb2YgdGhlIHNlcmllcyB5b3UgcmFuZG9tbHkgY2hvb3NlPyBXcml0ZSBpdC4NCg0KYGBge3IsIHdhcm5pbmc9RkFMU0V9DQoNCiMgRXh0cmFjdHRpbmcgdGhlIG5hbWUgb2YgdGhlIHNlcmllcw0Kc2VyaWVzX25hbWUgPC0gbXlzZXJpZXMgJT4lDQogIGRpc3RpbmN0KFN0YXRlLCBJbmR1c3RyeSkgJT4lDQogIHB1bGwoKQ0KDQojIFByaW50dGluZyB0aGUgbmFtZSBvZiB0aGUgc2VyaWVzDQpzZXJpZXNfbmFtZQ0KDQojIDZhLkFuc3dlcjoNCiMgVGhlIHJhbmRvbWx5IHNlbGVjdGVkIHNlcmllcyBpcyBmb3IgdGhlICJDbG90aGluZywgZm9vdHdlYXIgYW5kIHBlcnNvbmFsIGFjY2Vzc29yeSByZXRhaWxpbmciIGluZHVzdHJ5Lg0KDQpgYGANCg0KIyMjIyA2Yi4NCg0KUnVuIGEgbGluZWFyIHJlZ3Jlc3Npb24gb2YgVHVybm92ZXIgb24gdHJlbmQuKEhpbnQ6IHVzZSBUU0xNKCkgYW5kIHRyZW5kKCkgZnVuY3Rpb25zKQ0KDQpgYGB7ciwgd2FybmluZz1GQUxTRX0NCg0KIyBGaXR0aW5nIGEgbGluZWFyIHJlZ3Jlc3Npb24gb2YgVHVybm92ZXIgb24gdHJlbmQNCmZpdF9sbSA8LSBteXNlcmllcyAlPiUNCiAgbW9kZWwoVFNMTShUdXJub3ZlciB+IHRyZW5kKCkpKQ0KDQojIFZpZXdpbmcgdGhlIGZpdHRlZCBtb2RlbA0KZml0X2xtDQoNCg0KDQojIDZiLkFuc3dlcjoNCiMgQSBsaW5lYXIgcmVncmVzc2lvbiBvZiBUdXJub3ZlciBvbiB0cmVuZCB3YXMgZml0dGVkIHVzaW5nIHRoZSBgVFNMTSgpYCBmdW5jdGlvbi4gVGhlIG1vZGVsIGFzc3VtZXMgdGhhdCBUdXJub3ZlciBjaGFuZ2VzIGxpbmVhcmx5IG92ZXIgdGltZSwgd2l0aCB0aGUgdHJlbmQgcmVwcmVzZW50aW5nIHRoZSBzbG9wZSBvZiB0aGUgcmVsYXRpb25zaGlwLiBUaGUgZml0dGVkIG1vZGVsIGlzIHN0b3JlZCBpbiB0aGUgYGZpdF9sbWAgb2JqZWN0Lg0KDQpgYGANCg0KIyMjIyA2Yy4NCg0KU2VlIHRoZSByZWdyZXNzaW9uIHJlc3VsdCBieSByZXBvcnQoKSBjb21tYW5kLg0KDQpgYGB7ciwgd2FybmluZz1GQUxTRX0NCg0KIyBWaWV3IHRoZSBkZXRhaWxlZCByZWdyZXNzaW9uIHJlc3VsdHMNCnJlcG9ydChmaXRfbG0pDQoNCiMgNmMuQW5zd2VyOg0KIyBUaGUgbGluZWFyIHJlZ3Jlc3Npb24gbW9kZWwgaW5kaWNhdGVzIHRoYXQgVHVybm92ZXIgaGFzIGEgc3RhdGlzdGljYWxseSBzaWduaWZpY2FudCBwb3NpdGl2ZSB0cmVuZCBvdmVyIHRpbWUuIFRoZSBzbG9wZSBvZiB0aGUgdHJlbmQgaXMgMC4wMzA4IChwIDwgMC4wMDEpLCBtZWFuaW5nIFR1cm5vdmVyIGluY3JlYXNlcyBieSBhcHByb3hpbWF0ZWx5IDAuMDMwOCB1bml0cyBwZXIgdGltZSBwZXJpb2QuIFRoZSBpbnRlcmNlcHQgaXMgMy41MzEzIChwIDwgMC4wMDEpLCByZXByZXNlbnRpbmcgdGhlIGVzdGltYXRlZCBUdXJub3ZlciBhdCB0aGUgc3RhcnQgb2YgdGhlIHRpbWUgc2VyaWVzLiBUaGUgbW9kZWwgZXhwbGFpbnMgYXBwcm94aW1hdGVseSA3NC45MyUgb2YgdGhlIHZhcmlhYmlsaXR5IGluIFR1cm5vdmVyIChSLXNxdWFyZWQgPSAwLjc0OTMpLCBpbmRpY2F0aW5nIGEgc3Ryb25nIGZpdC4NCg0KYGBgDQoNCiMjIyMgNmQuDQoNCkJ5IHVzaW5nIHRoaXMgbW9kZWwsIGZvcmVjYXN0IGl0IGZvciB0aGUgbmV4dCAzIHllYXJzLiBXaGF0IGFyZSB0aGUgdmFsdWVzIG9mIHRoZSBuZXh0IDMgeWVhcnMsIG1vbnRobHkgdmFsdWVzPw0KDQpgYGB7ciwgd2FybmluZz1GQUxTRX0NCg0KIyBGb3JlY2FzdGluZyBUdXJub3ZlciBmb3IgdGhlIG5leHQgMyB5ZWFycyAoMzYgbW9udGhzKQ0KZmNfbG0gPC0gZml0X2xtICU+JQ0KICBmb3JlY2FzdChoID0gMzYpDQoNCiMgVmlld2luZyB0aGUgZm9yZWNhc3RlZCB2YWx1ZXMNCmZjX2xtDQoNCiMgUGxvdHRpbmcgdGhlIGZvcmVjYXN0ZWQgdmFsdWVzIGFsb25nIHdpdGggdGhlIGhpc3RvcmljYWwgZGF0YQ0KZmNfbG0gJT4lDQogIGF1dG9wbG90KG15c2VyaWVzKSArDQogIGxhYnModGl0bGUgPSAiRm9yZWNhc3RlZCBUdXJub3ZlciBmb3IgdGhlIE5leHQgMyBZZWFycyIsDQogICAgICAgeSA9ICJUdXJub3ZlciIsDQogICAgICAgeCA9ICJZZWFyIikgKw0KICB0aGVtZV9taW5pbWFsKCkNCg0KIyA2ZC5BbnN3ZXI6DQojIFRoZSBsaW5lYXIgcmVncmVzc2lvbiBtb2RlbCBmb3JlY2FzdHMgYSBzdGVhZHkgaW5jcmVhc2UgaW4gVHVybm92ZXIgZm9yIHRoZSBDbG90aGluZywgZm9vdHdlYXIsIGFuZCBwZXJzb25hbCBhY2Nlc3NvcnkgcmV0YWlsaW5nIGluZHVzdHJ5IGluIE5vcnRoZXJuIFRlcnJpdG9yeSBvdmVyIHRoZSBuZXh0IDMgeWVhcnMgKDM2IG1vbnRocyksIHdpdGggcHJlZGljdGVkIHZhbHVlcyBzdGFydGluZyBhdCAxMC41IGluIEphbnVhcnkgMjAyMyBhbmQgaW5jcmVhc2luZyBieSBhcHByb3hpbWF0ZWx5IDAuMDMwOCB1bml0cyBlYWNoIG1vbnRoLiBUaGUgZm9yZWNhc3RlZCB2YWx1ZXMgcmVmbGVjdCB0aGUgcG9zaXRpdmUgdHJlbmQgaWRlbnRpZmllZCBpbiB0aGUgbW9kZWwsIGluZGljYXRpbmcgY29uc2lzdGVudCBncm93dGggaW4gVHVybm92ZXIgb3ZlciB0aW1lLg0KDQpgYGANCg0KIyMjIyA2ZC4NCg0KUGxvdCB0aGUgZm9yZWNhc3QgdmFsdWVzIGFsb25nIHdpdGggdGhlIG9yaWdpbmFsIGRhdGEuDQoNCmBgYHtyLCB3YXJuaW5nPUZBTFNFfQ0KIyBQbG90dGluZyB0aGUgZm9yZWNhc3RlZCB2YWx1ZXMgYWxvbmcgd2l0aCB0aGUgb3JpZ2luYWwgZGF0YQ0KZmNfbG0gJT4lDQogIGF1dG9wbG90KG15c2VyaWVzKSArDQogIGxhYnModGl0bGUgPSAiRm9yZWNhc3RlZCBUdXJub3ZlciBmb3IgdGhlIE5leHQgMyBZZWFycyIsDQogICAgICAgeSA9ICJUdXJub3ZlciIsDQogICAgICAgeCA9ICJZZWFyIikgKw0KICB0aGVtZV9taW5pbWFsKCkNCg0KIyA2ZC5BbnN3ZXI6DQojIFRoZSBmb3JlY2FzdGVkIHZhbHVlcyBmb3IgdGhlIG5leHQgMyB5ZWFycyB3ZXJlIHBsb3R0ZWQgYWxvbmcgd2l0aCB0aGUgb3JpZ2luYWwgZGF0YS4gDQojIFRoZSBwbG90IHNob3dzIGEgc3RlYWR5IGluY3JlYXNlIGluIFR1cm5vdmVyIG92ZXIgdGltZSwgY29uc2lzdGVudCB3aXRoIHRoZSBwb3NpdGl2ZSANCiMgdHJlbmQgaWRlbnRpZmllZCBpbiB0aGUgbGluZWFyIHJlZ3Jlc3Npb24gbW9kZWwuIFRoZSBmb3JlY2FzdGVkIHZhbHVlcyBleHRlbmQgdGhlIA0KIyBoaXN0b3JpY2FsIHRyZW5kIGludG8gdGhlIGZ1dHVyZSwgcHJvdmlkaW5nIGEgdmlzdWFsIHJlcHJlc2VudGF0aW9uIG9mIHRoZSBleHBlY3RlZCANCiMgZ3Jvd3RoIGluIFR1cm5vdmVyLg0KDQpgYGANCg0KIyMjIyA2ZS4NCg0KR2V0IHRoZSByZXNpZHVhbHMgZnJvbSB0aGUgbW9kZWwuIEFuZCBjaGVjayB0aGUgcmVzaWR1YWxzIHRvIGNoZWNrIHdoZXRoZXIgb3Igbm90IGl0IHNhdGlzZmllcyB0aGUgcmVxdWlyZW1lbnRzIGZvciB3aGl0ZSBub2lzZSBlcnJvciB0ZXJtcy4oaGludDogYXVnbWVudCgpIGFuZCBnZ190c3Jlc2lkdWFscygpIGZ1bmN0aW9ucykNCg0KYGBge3IsIHdhcm5pbmc9RkFMU0V9DQojIEV4dHJhY3RpbmcgcmVzaWR1YWxzIGZyb20gdGhlIG1vZGVsDQpyZXNpZHVhbHNfbG0gPC0gZml0X2xtICU+JQ0KICBhdWdtZW50KCkNCg0KIyBQbG90dGluZyB0aGUgcmVzaWR1YWxzIG92ZXIgdGltZQ0KcmVzaWR1YWxzX2xtICU+JQ0KICBnZ3Bsb3QoYWVzKHggPSBNb250aCwgeSA9IC5yZXNpZCkpICsNCiAgZ2VvbV9saW5lKCkgKw0KICBsYWJzKHRpdGxlID0gIlJlc2lkdWFscyBmcm9tIHRoZSBMaW5lYXIgUmVncmVzc2lvbiBNb2RlbCIsDQogICAgICAgeSA9ICJSZXNpZHVhbHMiLA0KICAgICAgIHggPSAiWWVhciIpICsNCiAgdGhlbWVfbWluaW1hbCgpDQoNCiMgSGlzdG9ncmFtIG9mIHJlc2lkdWFscw0KcmVzaWR1YWxzX2xtICU+JQ0KICBnZ3Bsb3QoYWVzKHggPSAucmVzaWQpKSArDQogIGdlb21faGlzdG9ncmFtKGJpbndpZHRoID0gMC4yLCBmaWxsID0gImJsdWUiLCBjb2xvciA9ICJibGFjayIpICsNCiAgbGFicyh0aXRsZSA9ICJIaXN0b2dyYW0gb2YgUmVzaWR1YWxzIiwNCiAgICAgICB4ID0gIlJlc2lkdWFscyIsDQogICAgICAgeSA9ICJGcmVxdWVuY3kiKSArDQogIHRoZW1lX21pbmltYWwoKQ0KDQojIEFDRiBwbG90dGluZyBvZiByZXNpZHVhbHMNCnJlc2lkdWFsc19sbSAlPiUNCiAgQUNGKC5yZXNpZCkgJT4lDQogIGF1dG9wbG90KCkgKw0KICBsYWJzKHRpdGxlID0gIkFDRiBQbG90IG9mIFJlc2lkdWFscyIsDQogICAgICAgeSA9ICJBQ0YiLA0KICAgICAgIHggPSAiTGFnIikgKw0KICB0aGVtZV9taW5pbWFsKCkNCg0KIyA2ZS5BbnN3ZXI6DQojIFRoZSByZXNpZHVhbHMgZnJvbSB0aGUgbGluZWFyIHJlZ3Jlc3Npb24gbW9kZWwgd2VyZSBhbmFseXplZC4gVGhlIHRpbWUgcGxvdCBvZiB0aGUgcmVzaWR1YWxzIHNob3dzIG5vIG9idmlvdXMgcGF0dGVybnMgb3IgdHJlbmRzLCBzdWdnZXN0aW5nIHRoYXQgdGhlIG1vZGVsIGhhcyBjYXB0dXJlZCB0aGUgdW5kZXJseWluZyBzdHJ1Y3R1cmUgb2YgdGhlIGRhdGEuIFRoZSBoaXN0b2dyYW0gb2YgdGhlIHJlc2lkdWFscyBhcHBlYXJzIGFwcHJveGltYXRlbHlub3JtYWxseSBkaXN0cmlidXRlZCwgYW5kIHRoZSBBQ0YgcGxvdCBzaG93cyBubyBzaWduaWZpY2FudCBhdXRvY29ycmVsYXRpb24sIGluZGljYXRpbmcgdGhhdCB0aGUgcmVzaWR1YWxzIGFyZSB1bmNvcnJlbGF0ZWQuIE92ZXJhbGwsIHRoZSByZXNpZHVhbHMgcmVzZW1ibGUgd2hpdGUgbm9pc2UsIGluZGljYXRpbmcgdGhhdCB0aGUgbW9kZWwgaGFzIHBlcmZvcm1lZCB3ZWxsLg0KYGBgDQoNCiMjIyA3Lg0KDQpIYWxmLWhvdXJseSBlbGVjdHJpY2l0eSBkZW1hbmQgZm9yIFZpY3RvcmlhLCBBdXN0cmFsaWEgaXMgY29udGFpbmVkIGluIHZpY19lbGVjLiBFeHRyYWN0IHRoZSBKYW51YXJ5IDIwMTQgZWxlY3RyaWNpdHkgZGVtYW5kLCBhbmQgYWdncmVnYXRlIHRoaXMgZGF0YSB0byBkYWlseSB3aXRoIGRhaWx5IHRvdGFsIGRlbWFuZHMgYW5kIG1heGltdW0gdGVtcGVyYXR1cmVzLiBSdW4gdGhlIGNvZGUgYmVsb3c6DQoNCmBgYHtyLCB3YXJuaW5nPUZBTFNFfQ0KamFuX3ZpY19lbGVjIDwtIHZpY19lbGVjICU+JQ0KICBmaWx0ZXIoeWVhcm1vbnRoKFRpbWUpID09IHllYXJtb250aCgiMjAxNCBKYW4iKSkgJT4lDQogIGluZGV4X2J5KERhdGUgPSBhc19kYXRlKFRpbWUpKSAlPiUNCiAgc3VtbWFyaXNlKERlbWFuZCA9IHN1bShEZW1hbmQpLCBUZW1wZXJhdHVyZSA9IG1heChUZW1wZXJhdHVyZSkpDQpqYW5fdmljX2VsZWMNCmBgYA0KDQojIyMjIDdhLg0KDQpQbG90IHRoZSBkYXRhIGFuZCBmaW5kIHRoZSByZWdyZXNzaW9uIG1vZGVsIGZvciBEZW1hbmQgd2l0aCB0ZW1wZXJhdHVyZSBhcyBhIHByZWRpY3RvciB2YXJpYWJsZS4gV2h5IGlzIHRoZXJlIGEgcG9zaXRpdmUgcmVsYXRpb25zaGlwPw0KDQpgYGB7ciwgd2FybmluZz1GQUxTRX0NCiMgUGxvdHRpbmcgdGhlIGRhdGENCmphbl92aWNfZWxlYyAlPiUNCiAgZ2dwbG90KGFlcyh4ID0gVGVtcGVyYXR1cmUsIHkgPSBEZW1hbmQpKSArDQogIGdlb21fcG9pbnQoKSArDQogIGxhYnModGl0bGUgPSAiRWxlY3RyaWNpdHkgRGVtYW5kIHZzIFRlbXBlcmF0dXJlIiwNCiAgICAgICB5ID0gIkRlbWFuZCAoTVcpIiwNCiAgICAgICB4ID0gIlRlbXBlcmF0dXJlICjCsEMpIikgKw0KICB0aGVtZV9taW5pbWFsKCkNCg0KIyBGaXR0aW5nIGEgcmVncmVzc2lvbiBtb2RlbA0KZml0X3RlbXAgPC0gamFuX3ZpY19lbGVjICU+JQ0KICBtb2RlbChUU0xNKERlbWFuZCB+IFRlbXBlcmF0dXJlKSkNCmZpdF90ZW1wDQojIFZpZXdpbmcgdGhlIHJlZ3Jlc3Npb24gcmVzdWx0cw0KcmVwb3J0KGZpdF90ZW1wKQ0KDQojIDdhLkFuc3dlcjoNCiMgVGhlIHNjYXR0ZXIgcGxvdCBzaG93cyBhIHBvc2l0aXZlIHJlbGF0aW9uc2hpcCBiZXR3ZWVuIGVsZWN0cmljaXR5IGRlbWFuZCBhbmQgdGVtcGVyYXR1cmUuVGhlIHJlZ3Jlc3Npb24gbW9kZWwgaW5kaWNhdGVzIHRoYXQgZm9yIGV2ZXJ5IDHCsEMgaW5jcmVhc2UgaW4gdGVtcGVyYXR1cmUsIGVsZWN0cmljaXR5IGRlbWFuZCBpbmNyZWFzZXMgYnkgYXBwcm94aW1hdGVseSA2LDE1NC4zIE1XLiBUaGlzIHBvc2l0aXZlIHJlbGF0aW9uc2hpcCBpcyBsaWtlbHkgZHVlIHRvIGluY3JlYXNlZCB1c2Ugb2YgYWlyIGNvbmRpdGlvbmluZyBhbmQgY29vbGluZyBzeXN0ZW1zIGR1cmluZyBob3R0ZXIgd2VhdGhlciwgd2hpY2ggZHJpdmVzIHVwIGVsZWN0cmljaXR5IGNvbnN1bXB0aW9uLiBUaGUgbW9kZWwgZXhwbGFpbnMgYXBwcm94aW1hdGVseSA3OC4zMiUgb2YgdGhlIHZhcmlhYmlsaXR5IGluIGRlbWFuZCAoUi1zcXVhcmVkID0gMC43ODMyKSwgaW5kaWNhdGluZyBhIHN0cm9uZyBmaXQuDQpgYGANCg0KIyMjIyA3Yi4NCg0KUHJvZHVjZSBhIHJlc2lkdWFsIHBsb3QuIElzIHRoZSBtb2RlbCBhZGVxdWF0ZT8gQXJlIHRoZXJlIGFueSBvdXRsaWVycyBvciBpbmZsdWVudGlhbCBvYnNlcnZhdGlvbnM/DQoNCmBgYHtyLCB3YXJuaW5nPUZBTFNFfQ0KIyBFeHRyYWN0dGluZyByZXNpZHVhbHMgYW5kIGZpdHRlZCB2YWx1ZXMgZnJvbSB0aGUgbW9kZWwNCnJlc2lkdWFsc190ZW1wIDwtIGZpdF90ZW1wICU+JQ0KICBhdWdtZW50KCkgJT4lDQogIHNlbGVjdChEYXRlLCAucmVzaWQpDQoNCiMgQWRkaW5nIHRoZSBvcmlnaW5hbCBkYXRhIGNvbHVtbnMgKERhdGUsIFRlbXBlcmF0dXJlLCBEZW1hbmQpIHRvIHRoZSByZXNpZHVhbHMNCnJlc2lkdWFsc190ZW1wIDwtIHJlc2lkdWFsc190ZW1wICU+JQ0KICBsZWZ0X2pvaW4oamFuX3ZpY19lbGVjICU+JSBzZWxlY3QoRGF0ZSwgVGVtcGVyYXR1cmUsIERlbWFuZCksIGJ5ID0gIkRhdGUiKQ0KDQojIFBsb3R0aW5nIHRoZSByZXNpZHVhbHMgYWdhaW5zdCB0ZW1wZXJhdHVyZQ0KcmVzaWR1YWxzX3RlbXAgJT4lDQogIGdncGxvdChhZXMoeCA9IFRlbXBlcmF0dXJlLCB5ID0gLnJlc2lkKSkgKw0KICBnZW9tX3BvaW50KCkgKw0KICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQgPSAwLCBjb2xvciA9ICJyZWQiLCBsaW5ldHlwZSA9ICJkYXNoZWQiKSArDQogIGxhYnModGl0bGUgPSAiUmVzaWR1YWxzIHZzIFRlbXBlcmF0dXJlIiwNCiAgICAgICB5ID0gIlJlc2lkdWFscyIsDQogICAgICAgeCA9ICJUZW1wZXJhdHVyZSAowrBDKSIpICsNCiAgdGhlbWVfbWluaW1hbCgpDQoNCiMgQ2hlY2tpbmcgZm9yIG91dGxpZXJzIG9yIGluZmx1ZW50aWFsIG9ic2VydmF0aW9ucw0KcmVzaWR1YWxzX3RlbXAgJT4lDQogIGZpbHRlcihhYnMoLnJlc2lkKSA+IDIgKiBzZCgucmVzaWQpKSAlPiUNCiAgc2VsZWN0KERhdGUsIFRlbXBlcmF0dXJlLCBEZW1hbmQsIC5yZXNpZCkNCg0KIyA3Yi5BbnN3ZXI6DQojIFRoZSByZXNpZHVhbCBwbG90IHNob3dzIHRoZSByZXNpZHVhbHMgcGxvdHRlZCBhZ2FpbnN0IHRlbXBlcmF0dXJlLiBUaGUgcmVzaWR1YWxzIGFyZSByYW5kb21seSBzY2F0dGVyZWQgYXJvdW5kIHplcm8sIHdpdGggbm8gb2J2aW91cyBwYXR0ZXJucyBvciB0cmVuZHMsIHN1Z2dlc3RpbmcgdGhhdCB0aGUgbW9kZWwgaXMgYWRlcXVhdGUuIEhvd2V2ZXIsIHRoZXJlIGFyZSBhIGZldyBvdXRsaWVycyB3aGVyZSB0aGUgcmVzaWR1YWxzIGV4Y2VlZCAyIHN0YW5kYXJkIGRldmlhdGlvbnMgZnJvbSB0aGUgbWVhbi4gVGhlc2Ugb3V0bGllcnMgbWF5IHJlcHJlc2VudCBkYXlzIHdpdGggdW51c3VhbGx5IGhpZ2ggb3IgbG93IGVsZWN0cmljaXR5IGRlbWFuZCB0aGF0IGFyZSBub3QgZnVsbHkgZXhwbGFpbmVkIGJ5IHRlbXBlcmF0dXJlIGFsb25lLg0KYGBgDQoNCiMjIyMgN2MuDQoNClVzZSB0aGUgbW9kZWwgdG8gZm9yZWNhc3QgdGhlIGVsZWN0cmljaXR5IGRlbWFuZCB0aGF0IHlvdSB3b3VsZCBleHBlY3QgZm9yIHRoZSBuZXh0IGRheSBpZiB0aGUgbWF4aW11bSB0ZW1wZXJhdHVyZSB3YXMgMTXiiJhDIGFuZCBjb21wYXJlIGl0IHdpdGggdGhlIGZvcmVjYXN0IGlmIHRoZSB3aXRoIG1heGltdW0gdGVtcGVyYXR1cmUgd2FzIDM14oiYQy4gRG8geW91IGJlbGlldmUgdGhlc2UgZm9yZWNhc3RzPw0KDQpgYGB7ciwgd2FybmluZz1GQUxTRX0NCg0KIyBGb3JlY2FzdGluZyBlbGVjdHJpY2l0eSBkZW1hbmQgZm9yIDE1wrBDDQpmb3JlY2FzdF8xNSA8LSBmaXRfdGVtcCAlPiUNCiAgZm9yZWNhc3QobmV3X2RhdGEgPSBqYW5fdmljX2VsZWMgJT4lDQogICAgICAgICAgICAgZmlsdGVyKHJvd19udW1iZXIoKSA9PSAxKSAlPiUgIyBVc2UgdGhlIGZpcnN0IHJvdyBhcyBhIHRlbXBsYXRlDQogICAgICAgICAgICAgbXV0YXRlKFRlbXBlcmF0dXJlID0gMTUpKSAjIFJlcGxhY2UgVGVtcGVyYXR1cmUgd2l0aCAxNcKwQw0KDQojIEZvcmVjYXN0aW5nIGVsZWN0cmljaXR5IGRlbWFuZCBmb3IgMzXCsEMNCmZvcmVjYXN0XzM1IDwtIGZpdF90ZW1wICU+JQ0KICBmb3JlY2FzdChuZXdfZGF0YSA9IGphbl92aWNfZWxlYyAlPiUNCiAgICAgICAgICAgICBmaWx0ZXIocm93X251bWJlcigpID09IDEpICU+JSAjIFVzZSB0aGUgZmlyc3Qgcm93IGFzIGEgdGVtcGxhdGUNCiAgICAgICAgICAgICBtdXRhdGUoVGVtcGVyYXR1cmUgPSAzNSkpICMgUmVwbGFjZSBUZW1wZXJhdHVyZSB3aXRoIDM1wrBDDQoNCiMgVmlld2luZyB0aGUgZm9yZWNhc3RzDQpmb3JlY2FzdF8xNQ0KZm9yZWNhc3RfMzUNCg0KIyBDb21wYXJpbmcgaW5ndGhlIGZvcmVjYXN0cw0KY29tcGFyaXNvbiA8LSB0aWJibGUoDQogIFRlbXBlcmF0dXJlID0gYygxNSwgMzUpLA0KICBGb3JlY2FzdGVkX0RlbWFuZCA9IGMoZm9yZWNhc3RfMTUkLm1lYW4sIGZvcmVjYXN0XzM1JC5tZWFuKQ0KKQ0KDQpjb21wYXJpc29uDQoNCiMgN2MuQW5zd2VyOg0KIyBVc2luZyB0aGUgbGluZWFyIHJlZ3Jlc3Npb24gbW9kZWwsIHRoZSBmb3JlY2FzdGVkIGVsZWN0cmljaXR5IGRlbWFuZCBmb3IgdGhlIG5leHQgZGF5IGlzIDE1MSwzOTggTVcgd2hlbiB0aGUgbWF4aW11bSB0ZW1wZXJhdHVyZSBpcyAxNcKwQyBhbmQgMjc0LDQ4NCBNVyB3aGVuIHRoZSBtYXhpbXVtIHRlbXBlcmF0dXJlIGlzIDM1wrBDLiBUaGVzZSBmb3JlY2FzdHMgcmVmbGVjdCB0aGUgcG9zaXRpdmUgcmVsYXRpb25zaGlwIGJldHdlZW4gdGVtcGVyYXR1cmUgYW5kIGVsZWN0cmljaXR5IGRlbWFuZCwgd2hlcmUgaGlnaGVyIHRlbXBlcmF0dXJlcyBsZWFkIHRvIGluY3JlYXNlZCBkZW1hbmQgZHVlIHRvIGFpciBjb25kaXRpb25pbmcgYW5kIGNvb2xpbmcgc3lzdGVtcy4gSG93ZXZlciwgdGhlIG1vZGVsIGFzc3VtZXMgYSBsaW5lYXIgcmVsYXRpb25zaGlwLCB3aGljaCBtYXkgbm90IGhvbGQgZm9yIGV4dHJlbWUgdGVtcGVyYXR1cmVzLCBhbmQgaXQgZG9lcyBub3QgYWNjb3VudCBmb3Igb3RoZXIgZmFjdG9ycyBsaWtlIHRpbWUgb2YgZGF5IG9yIGVuZXJneSBjb25zZXJ2YXRpb24gbWVhc3VyZXMuIFdoaWxlIHRoZSBmb3JlY2FzdHMgYXJlIHBsYXVzaWJsZSwgdGhleSBzaG91bGQgYmUgaW50ZXJwcmV0ZWQgd2l0aCBjYXV0aW9uLCBlc3BlY2lhbGx5IGZvciB0ZW1wZXJhdHVyZXMgb3V0c2lkZSB0aGUgcmFuZ2Ugb2YgdGhlIHRyYWluaW5nIGRhdGEsIGFzIHRoZSBtb2RlbCBtYXkgb3ZlcmVzdGltYXRlIG9yIHVuZGVyZXN0aW1hdGUgZGVtYW5kIGluIHN1Y2ggY2FzZXMuDQpgYGANCg0KIyMjIyA3ZC4NCg0KRG8geW91IGJlbGlldmUgdGhlc2UgZm9yZWNhc3RzPyBUaGUgZm9sbG93aW5nIFIgY29kZSB3aWxsIGdldCB5b3Ugc3RhcnRlZDoNCg0KYGBge3IsIHdhcm5pbmc9RkFMU0V9DQogamFuX3ZpY19lbGVjICU+JQ0KICBtb2RlbChUU0xNKERlbWFuZCB+IFRlbXBlcmF0dXJlKSkgJT4lDQogIGZvcmVjYXN0KA0KICAgIG5ld19kYXRhKGphbl92aWNfZWxlYywgMSkgJT4lDQogICAgICBtdXRhdGUoVGVtcGVyYXR1cmUgPSAxNSkNCiAgKSAlPiUNCiAgYXV0b3Bsb3QoamFuX3ZpY19lbGVjKQ0KDQpgYGANCg0KYGBge3J9DQoNCiMgN2QuQW5zd2VyOg0KIyBUaGUgZm9yZWNhc3RzIGZvciBlbGVjdHJpY2l0eSBkZW1hbmQgYXQgMTXCsEMgYXJlIHBsYXVzaWJsZSBidXQgbGltaXRlZCBieSB0aGUgbW9kZWwncyBzaW1wbGljaXR5IGFuZCBsaW5lYXIgYXNzdW1wdGlvbnMuIFRoZSBtb2RlbCBpZ25vcmVzIGZhY3RvcnMgbGlrZSB0aW1lIG9mIGRheSBhbmQgaG9saWRheXMsIGFuZCBmb3JlY2FzdHMgbWF5IGJlIHVucmVsaWFibGUgZm9yIHRlbXBlcmF0dXJlcyBvdXRzaWRlIHRoZSB0cmFpbmluZyBkYXRhIHJhbmdlLiBDb25maWRlbmNlIGludGVydmFscyBpbmRpY2F0ZSBzaWduaWZpY2FudCB1bmNlcnRhaW50eS4gVG8gaW1wcm92ZSBhY2N1cmFjeSwgdGhlIG1vZGVsIHNob3VsZCBpbmNsdWRlIG1vcmUgcHJlZGljdG9ycyBhbmQgYmUgdmFsaWRhdGVkIHdpdGggdGVzdCBkYXRhLg0KDQpgYGANCg0KIyMjIyA3ZS4NCg0KR2l2ZSBwcmVkaWN0aW9uIGludGVydmFscyBmb3IgeW91ciBmb3JlY2FzdHMuDQoNCmBgYHtyLCB3YXJuaW5nPUZBTFNFfQ0KIyBGb3JlY2FzdGluZyBlbGVjdHJpY2l0eSBkZW1hbmQgZm9yIDE1wrBDIHdpdGggcHJlZGljdGlvbiBpbnRlcnZhbHMNCmZvcmVjYXN0XzE1IDwtIGZpdF90ZW1wICU+JQ0KICBmb3JlY2FzdCgNCiAgICBuZXdfZGF0YSA9IGphbl92aWNfZWxlYyAlPiUNCiAgICAgIGZpbHRlcihyb3dfbnVtYmVyKCkgPT0gMSkgJT4lICMgVXNlIHRoZSBmaXJzdCByb3cgYXMgYSB0ZW1wbGF0ZQ0KICAgICAgbXV0YXRlKFRlbXBlcmF0dXJlID0gMTUpLCAjIFNldCBUZW1wZXJhdHVyZSB0byAxNcKwQw0KICAgIGxldmVsID0gYyg4MCwgOTUpICMgU3BlY2lmeSBwcmVkaWN0aW9uIGludGVydmFscyAoODAlIGFuZCA5NSUpDQogICkNCg0KIyBWaWV3aW5nIHRoZSBmb3JlY2FzdCB3aXRoIHByZWRpY3Rpb24gaW50ZXJ2YWxzDQpmb3JlY2FzdF8xNQ0KDQojIEV4dHJhY3RpbmcgdGhlIHByZWRpY3Rpb24gaW50ZXJ2YWxzDQpwcmVkaWN0aW9uX2ludGVydmFscyA8LSBmb3JlY2FzdF8xNSAlPiUNCiAgaGlsbyhsZXZlbCA9IGMoODAsIDk1KSkgIyBFeHRyYWN0IGludGVydmFscyBhdCA4MCUgYW5kIDk1JSBjb25maWRlbmNlIGxldmVscw0KDQpwcmVkaWN0aW9uX2ludGVydmFscw0KDQojIDdlLkFuc3dlcjoNCiMgUHJlZGljdGlvbiBpbnRlcnZhbHMgZm9yIHRoZSBmb3JlY2FzdHMgd2VyZSBnZW5lcmF0ZWQgYXQgODAlIGFuZCA5NSUgY29uZmlkZW5jZSBsZXZlbHMgdXNpbmcgdGhlIGZvcmVjYXN0KCkgZnVuY3Rpb24gd2l0aCB0aGUgbGV2ZWwgPSBjKDgwLCA5NSkgYXJndW1lbnQuIFRoZXNlIGludGVydmFscyBwcm92aWRlIGEgcmFuZ2Ugb2YgdmFsdWVzIHdpdGhpbiB3aGljaCB0aGUgYWN0dWFsIGVsZWN0cmljaXR5IGRlbWFuZCBhdCAxNcKwQyBpcyBleHBlY3RlZCB0byBmYWxsLCB3aXRoIHRoZSA4MCUgaW50ZXJ2YWwgb2ZmZXJpbmcgYSBuYXJyb3dlciByYW5nZSBmb3IgaGlnaGVyIHByZWNpc2lvbiBhbmQgdGhlIDk1JSBpbnRlcnZhbCBwcm92aWRpbmcgYSB3aWRlciByYW5nZSBmb3IgZ3JlYXRlciBjb25maWRlbmNlLiBUaGUgaGlsbygpIGZ1bmN0aW9uIHdhcyB1c2VkIHRvIGV4dHJhY3QgdGhlc2UgaW50ZXJ2YWxzLCB3aGljaCBhcmUgZXNzZW50aWFsIGZvciB1bmRlcnN0YW5kaW5nIHRoZSB1bmNlcnRhaW50eSBhc3NvY2lhdGVkIHdpdGggdGhlIGZvcmVjYXN0cyBhbmQgbWFraW5nIGluZm9ybWVkIGRlY2lzaW9ucyBiYXNlZCBvbiB0aGUgZXhwZWN0ZWQgcmFuZ2Ugb2Ygb3V0Y29tZXMuDQpgYGANCg0KIyMjIDguDQoNClJlYWQgdGhlIHNoYW1wb28gZGF0YSBnaXZlbiBpbiBleGNlbCAoSW1wb3J0IERhdGFzZXQgYXMgRXhjZWwpDQoNCiNhLiBWaWV3IHRoZSBzaGFtcG9vIHNhbGVzIGRhdGEuIEhvdyBtYW55IHZhcmlhYmxlcyBhcmUgdGhlcmU/IEZpbmQgaG93IG1hbnkgcm93cyBhbmQgY29sdW1ucyBpbiB0aGUgZGF0YT8NCg0KYGBge3IsIHdhcm5pbmc9RkFMU0V9DQojIExvYWRpbmcgdGhlIHNoYW1wb28gc2FsZXMgZGF0YQ0Kc2hhbXBvb19kYXRhIDwtIHJlYWRfZXhjZWwoInNoYW1wb28tMi54bHN4IikNCg0KIyBWaWV3aW5nIHRoZSBmaXJzdCBmZXcgcm93cyBvZiB0aGUgZGF0YQ0KaGVhZChzaGFtcG9vX2RhdGEpDQoNCiMgVmlld2luZyB0aGUgc3RydWN0dXJlIG9mIHRoZSBkYXRhDQpzdHIoc2hhbXBvb19kYXRhKQ0KDQojIE51bWJlciBvZiByb3dzIGFuZCBjb2x1bW5zDQpucm93KHNoYW1wb29fZGF0YSkNCm5jb2woc2hhbXBvb19kYXRhKQ0KDQojIFRoZSBkYXRhc2V0IGhhcyAzNiByb3dzIGFuZCAyIGNvbHVtbnMsIHdpdGggdmFyaWFibGVzIE1vbnRoIChkYXRlLXRpbWUpIGFuZCBzYWxlcw0KIyAobnVtZXJpYyksIHJlcHJlc2VudGluZyBtb250aGx5IHNoYW1wb28gc2FsZXMgZnJvbSBKYW51YXJ5IDE5OTUgdG8gRGVjZW1iZXIgMTk5Ny4NCmBgYA0KDQojYi4gSXMgdGhlIGRhdGEgYW5udWFsLCBtb250aGx5LCBxdWFydGVybHk/DQoNCmBgYHtyLCB3YXJuaW5nPUZBTFNFfQ0KDQpoZWFkKHNoYW1wb29fZGF0YSkNCg0KDQojIFRoZSBzaGFtcG9vIHNhbGVzIGRhdGEgaXMgbW9udGhseS4gVGhpcyBpcyBldmlkZW50IGZyb20gdGhlIGBNb250aGAgY29sdW1uLCB3aGljaCBzaG93cyBkYXRlcyBpbiB0aGUgZm9ybWF0IGBZWVlZLU1NLUREYCwgd2l0aCBlYWNoIGVudHJ5IHJlcHJlc2VudGluZyB0aGUgZmlyc3QgZGF5IG9mIGVhY2ggbW9udGggKGUuZy4sIGAxOTk1LTAxLTAxYCBmb3IgSmFudWFyeSAxOTk1LGAxOTk1LTAyLTAxYCBmb3IgRmVicnVhcnkgMTk5NSwgZXRjLikuIFRoZSBkYXRhc2V0IGNvdmVycyAzNiBtb250aHMsIHdoaWNoIGNvcnJlc3BvbmRzIHRvIDMgeWVhcnMgb2YgbW9udGhseSBkYXRhIChmcm9tIEphbnVhcnkgMTk5NSB0byBEZWNlbWJlciAxOTk3KQ0KYGBgDQoNCg0KDQojYy4gQ29udmVydCB0aGUgZGF0YSBpbnRvIHRpYmJsZSAsIHRoZW4gdHNpYmJsZQ0KDQpgYGB7ciwgd2FybmluZz1GQUxTRX0NCg0KIyBDb252ZXJ0aW5nIHRvIHRpYmJsZQ0Kc2hhbXBvb190aWJibGUgPC0gYXNfdGliYmxlKHNoYW1wb29fZGF0YSkNCg0KIyBDb252ZXJ0aW5nIHRoZSBgTW9udGhgIGNvbHVtbiB0byBgeWVhcm1vbnRoYCBmb3JtYXQNCnNoYW1wb29fdGliYmxlIDwtIHNoYW1wb29fdGliYmxlICU+JQ0KICBtdXRhdGUoTW9udGggPSB5ZWFybW9udGgoTW9udGgpKQ0KDQojIENvbnZlcnRpbmcgdG8gdHNpYmJsZQ0Kc2hhbXBvb190c2liYmxlIDwtIGFzX3RzaWJibGUoc2hhbXBvb190aWJibGUsIGluZGV4ID0gTW9udGgpDQoNCiMgVmlld2luZyB0aGUgdHNpYmJsZQ0Kc2hhbXBvb190c2liYmxlDQoNCiMgYy4gQW5zd2VyOg0KIyBUaGUgZGF0YSBoYXMgYmVlbiBjb252ZXJ0ZWQgaW50byBhIHRzaWJibGUgd2l0aCBgTW9udGhgIChpbiBgeWVhcm1vbnRoYCBmb3JtYXQpIGFzIHRoZSBpbmRleC4NCmBgYA0KDQojZC4gUGxvdCB0aGUgc2hhbXBvbyBzYWxlcy4gV2hhdCBkbyB5b3Ugc2VlIGZyb20gdGhlIGRhdGEgcGF0dGVybj8gV2hhdCBkb2VzIHgtYXhpcyByZXByZXNlbnQ/IFwjIENvbW1lbnQgaGVyZS4gVXNlIHBsb3QoKSBhbmQgYXV0b3Bsb3QoKS5QdXQgdGhlIG5hbWUgZm9yIHkgYXhpcywgYW5kIGEgdGl0bGUgZm9yIHRoZSBncmFwaC4NCg0KYGBge3IsIHdhcm5pbmc9RkFMU0V9DQoNCnBsb3Qoc2hhbXBvb190c2liYmxlJE1vbnRoLCBzaGFtcG9vX3RzaWJibGUkc2FsZXMsIA0KICAgICB0eXBlID0gImwiLCANCiAgICAgeGxhYiA9ICJUaW1lIChNb250aCkiLCANCiAgICAgeWxhYiA9ICJTYWxlcyIsIA0KICAgICBtYWluID0gIlNoYW1wb28gU2FsZXMgT3ZlciBUaW1lIikNCg0KIyBkLiBQbG90IHRoZSBzaGFtcG9vIHNhbGVzIHVzaW5nIGF1dG9wbG90KCkNCmF1dG9wbG90KHNoYW1wb29fdHNpYmJsZSwgc2FsZXMpICsNCiAgbGFicyh0aXRsZSA9ICJTaGFtcG9vIFNhbGVzIE92ZXIgVGltZSIsDQogICAgICAgeSA9ICJTYWxlcyIsDQogICAgICAgeCA9ICJUaW1lIChNb250aCkiKSArDQogIHRoZW1lX21pbmltYWwoKQ0KDQojIFRoZSBwbG90cyBzaG93IGEgc2xpZ2h0IHVwd2FyZCB0cmVuZCBhbmQgc2Vhc29uYWwgZmx1Y3R1YXRpb25zIGluIHNoYW1wb28gc2FsZXMgZnJvbSAxOTk1IHRvIDE5OTcuIFRoZSB4LWF4aXMgcmVwcmVzZW50cyB0aW1lIGluIG1vbnRocywgYW5kIHRoZSB5LWF4aXMgcmVwcmVzZW50cyBzYWxlcywgaGlnaGxpZ2h0aW5nIGdyb3d0aCBhbmQgcGVyaW9kaWMgdmFyaWF0aW9ucy4gQm90aCBwbG90KCkgYW5kIGF1dG9wbG90KCkgdmlzdWFsaXplIHRoZXNlIHBhdHRlcm5zLCB3aXRoIGF1dG9wbG90KCkgb2ZmZXJpbmcgYSBjbGVhbmVyIGRlc2lnbi4NCmBgYA0KDQoNCg0KI2UuIFdoYXQgaXMgdGhlIGF2ZXJhZ2UsIGFuZCBtZWRpYW4gb2Ygc2hhbXBvbyBzYWxlcy4gUHV0IGl0IG9uIGEgaGlzdG9ncmFtLg0KDQpgYGB7ciwgd2FybmluZz1GQUxTRX0NCiMgQ2FsY3VsYXRpbmcgdGhlIGF2ZXJhZ2UgYW5kIG1lZGlhbiBvZiBzaGFtcG9vIHNhbGVzDQphdmVyYWdlX3NhbGVzIDwtIG1lYW4oc2hhbXBvb190c2liYmxlJHNhbGVzKQ0KbWVkaWFuX3NhbGVzIDwtIG1lZGlhbihzaGFtcG9vX3RzaWJibGUkc2FsZXMpDQoNCiMgUHJpbnRpbmcgdGhlIHJlc3VsdHMNCmNhdCgiQXZlcmFnZSBzaGFtcG9vIHNhbGVzOiIsIGF2ZXJhZ2Vfc2FsZXMsICJcbiIpDQpjYXQoIk1lZGlhbiBzaGFtcG9vIHNhbGVzOiIsIG1lZGlhbl9zYWxlcywgIlxuIikNCg0KIyBQbG90dGluZyBhIGhpc3RvZ3JhbSBvZiBzaGFtcG9vIHNhbGVzDQpoaXN0KHNoYW1wb29fdHNpYmJsZSRzYWxlcywgDQogICAgIGJyZWFrcyA9IDEwLCANCiAgICAgbWFpbiA9ICJIaXN0b2dyYW0gb2YgU2hhbXBvbyBTYWxlcyIsIA0KICAgICB4bGFiID0gIlNhbGVzIiwgDQogICAgIHlsYWIgPSAiRnJlcXVlbmN5IiwgDQogICAgIGNvbCA9ICJsaWdodGJsdWUiLCANCiAgICAgYm9yZGVyID0gImJsYWNrIikNCmBgYA0KDQojZi4gR2V0IHNlYXNvbmFsIHBsb3QuIFdoYXQgZG8geW91IHNlZS8gaXMgdGhlcmUgYW55IHBhdHRlcm4sIGlzIHRlaHJlIGFueSBzZWFzb25hbGl0eS4NCg0KYGBge3IsIHdhcm5pbmc9RkFMU0V9DQojIENyZWF0aW5nIGEgc2Vhc29uYWwgcGxvdA0KZ2dfc2Vhc29uKHNoYW1wb29fdHNpYmJsZSwgc2FsZXMpICsNCiAgbGFicyh0aXRsZSA9ICJTZWFzb25hbCBQbG90IG9mIFNoYW1wb28gU2FsZXMiLA0KICAgICAgIHkgPSAiU2FsZXMiLA0KICAgICAgIHggPSAiTW9udGgiKSArDQogIHRoZW1lX21pbmltYWwoKQ0KDQojIFRoZSBzZWFzb25hbCBwbG90IG9mIHNoYW1wb28gc2FsZXMgcmV2ZWFscyBzdHJvbmcgc2Vhc29uYWxpdHksIHdpdGggY29uc2lzdGVudCBwZWFrcyBpbiBjZXJ0YWluIG1vbnRocyAoZS5nLiwgRGVjZW1iZXIpIGFuZCB0cm91Z2hzIGluIG90aGVycywgaW5kaWNhdGluZyB0aGF0IHNhbGVzIGFyZSBpbmZsdWVuY2VkIGJ5IHNlYXNvbmFsIGZhY3RvcnMgc3VjaCBhcyBob2xpZGF5cyBvciB3ZWF0aGVyIGNvbmRpdGlvbnMuIEFkZGl0aW9uYWxseSwgdGhlcmUgYXBwZWFycyB0byBiZSBhbiB1cHdhcmQgdHJlbmQgb3ZlciB0aGUgeWVhcnMsIHN1Z2dlc3RpbmcgZ3Jvd2luZyBkZW1hbmQuIFRoZSBwbG90IGhpZ2hsaWdodHMgc2lnbmlmaWNhbnQgdmFyaWFiaWxpdHkgaW4gc2FsZXMgYWNyb3NzIG1vbnRocywgZW1waGFzaXppbmcgdGhlIGltcG9ydGFuY2Ugb2YgaW5jb3Jwb3JhdGluZyBzZWFzb25hbGl0eSBhbmQgdHJlbmQgYW5hbHlzaXMgaW50byBmb3JlY2FzdGluZyBtb2RlbHMgZm9yIGFjY3VyYXRlIHByZWRpY3Rpb25zIGFuZCBlZmZlY3RpdmUgaW52ZW50b3J5IHBsYW5uaW5nLg0KYGBgDQoNCiNnLiBHZXQgYSBsaW5lYXIgcmVncmVzc2lvbiBsaW5lIHdpdGggdHJlbmQgYW5kIGR1bW15IGZvciBlYWNoIG1vbnRoIChIaW50OiB1c2UgdHJlbmQgYW5kIHNlYXNvbiBpbiByZWdyZXNzaW9uIGVxdWF0aW9uKS4NCg0KYGBge3IsIHdhcm5pbmc9RkFMU0V9DQojIEZpdHRpbmcgYSBsaW5lYXIgcmVncmVzc2lvbiBtb2RlbCB3aXRoIHRyZW5kIGFuZCBzZWFzb25hbGl0eQ0KZml0X3NoYW1wb28gPC0gc2hhbXBvb190c2liYmxlICU+JQ0KICBtb2RlbChUU0xNKHNhbGVzIH4gdHJlbmQoKSArIHNlYXNvbigpKSkNCg0KIyBWaWV3aW5nIHRoZSBtb2RlbCBzdW1tYXJ5DQpyZXBvcnQoZml0X3NoYW1wb28pDQoNCiMgVGhlIGxpbmVhciByZWdyZXNzaW9uIG1vZGVsIHdpdGggdHJlbmQgYW5kIHNlYXNvbmFsaXR5IGluZGljYXRlcyBhIHNpZ25pZmljYW50IHVwd2FyZCB0cmVuZCBpbiBzaGFtcG9vIHNhbGVzLCB3aXRoIHNhbGVzIGluY3JlYXNpbmcgYnkgYXBwcm94aW1hdGVseSAxMS43NSB1bml0cyBwZXIgbW9udGguIEhvd2V2ZXIsIHRoZSBtb250aGx5IHNlYXNvbmFsIGVmZmVjdHMgYXJlIG5vdCBzdGF0aXN0aWNhbGx5IHNpZ25pZmljYW50LCBzdWdnZXN0aW5nIHRoYXQgdGhlIG1vZGVsIGRvZXMgbm90IHN0cm9uZ2x5IGNhcHR1cmUgc2Vhc29uYWxpdHkuIFRoZSBtb2RlbCBleHBsYWlucyA3NS45MiUgb2YgdGhlIHZhcmlhYmlsaXR5IGluIHNhbGVzLCBidXQgdGhlIG1vZGVyYXRlIEFkanVzdGVkIFItc3F1YXJlZCB2YWx1ZSAoMC42MzM2KSBhbmQgaGlnaCByZXNpZHVhbCBzdGFuZGFyZCBlcnJvciAoOTAuMTYpIGluZGljYXRlIHJvb20gZm9yIGltcHJvdmVtZW50IGJ5IGluY29ycG9yYXRpbmcgYWRkaXRpb25hbCBwcmVkaWN0b3JzIG9yIHVzaW5nIG1vcmUgYWR2YW5jZWQgbW9kZWxpbmcgdGVjaG5pcXVlcy4NCmBgYA0KDQojaC4gQ29tbWVudCBvbiBlYWNoIGVzdGltYXRlZCBjb2VmZmljaWVudCBvZiB0aGUgbW9kZWwuQXJlIHRoZXkgc3RhdGlzdGljYWxseSBzaWduaWZpY2FudCBhdCA1ICUgc2lnbmlmaWNhbmNlIGxldmVsPw0KDQpgYGB7ciwgd2FybmluZz1GQUxTRX0NCiMgRXh0cmFjdGluZyBhbmQgY29tbWVudCBvbiB0aGUgY29lZmZpY2llbnRzDQpjb2VmZmljaWVudHNfc3VtbWFyeSA8LSBmaXRfc2hhbXBvbyAlPiUNCiAgdGlkeSgpICMgRXh0cmFjdCBjb2VmZmljaWVudHMgaW4gYSB0aWR5IGZvcm1hdA0KDQojIFByaW50aW5nIHRoZSBjb2VmZmljaWVudHMgc3VtbWFyeQ0KY29lZmZpY2llbnRzX3N1bW1hcnkNCg0KIyBBZGRpbmcgYSBjb2x1bW4gdG8gaW5kaWNhdGUgc2lnbmlmaWNhbmNlIGF0IDUlIGxldmVsDQpjb2VmZmljaWVudHNfc3VtbWFyeSA8LSBjb2VmZmljaWVudHNfc3VtbWFyeSAlPiUNCiAgbXV0YXRlKFNpZ25pZmljYW50ID0gaWZlbHNlKHAudmFsdWUgPCAwLjA1LCAiWWVzIiwgIk5vIikpDQoNCiMgUHJpbnRpbmcgdGhlIHVwZGF0ZWQgc3VtbWFyeSB3aXRoIHNpZ25pZmljYW5jZQ0KY29lZmZpY2llbnRzX3N1bW1hcnkNCg0KIyBUaGUgbGluZWFyIHJlZ3Jlc3Npb24gbW9kZWwgcmV2ZWFscyB0aGF0IG9ubHkgdGhlIHRyZW5kIGNvZWZmaWNpZW50ICgxMS44LCBwLXZhbHVlIOKJiCAwKSBpcyBzdGF0aXN0aWNhbGx5IHNpZ25pZmljYW50IGF0IHRoZSA1JSBsZXZlbCwgaW5kaWNhdGluZyBhIHN0cm9uZyB1cHdhcmQgdHJlbmQgaW4gc2hhbXBvbyBzYWxlcyBvZiBhcHByb3hpbWF0ZWx5IDExLjggdW5pdHMgcGVyIG1vbnRoLiBIb3dldmVyLCB0aGUgaW50ZXJjZXB0IGFuZCBhbGwgbW9udGhseSBzZWFzb25hbCBjb2VmZmljaWVudHMgYXJlIG5vdCBzdGF0aXN0aWNhbGx5IHNpZ25pZmljYW50IChwLXZhbHVlcyA+IDAuMDUpLCBzdWdnZXN0aW5nIHRoYXQgdGhlIG1vZGVsIGRvZXMgbm90IGVmZmVjdGl2ZWx5IGNhcHR1cmUgc2Vhc29uYWxpdHkuIFRoaXMgaW1wbGllcyB0aGF0IHdoaWxlIHRoZSB0cmVuZCBpcyBhIGtleSBkcml2ZXIgb2Ygc2FsZXMsIHRoZSBzZWFzb25hbCBwYXR0ZXJucyBhcmUgZWl0aGVyIHRvbyB3ZWFrIG9yIG5vdCBhZGVxdWF0ZWx5IGNhcHR1cmVkIGJ5IHRoaXMgbW9kZWwsIGhpZ2hsaWdodGluZyB0aGUgbmVlZCBmb3IgYWRkaXRpb25hbCBwcmVkaWN0b3JzIG9yIG1vcmUgc29waGlzdGljYXRlZCBtb2RlbGluZyB0ZWNobmlxdWVzIHRvIGltcHJvdmUgYWNjdXJhY3kuDQogIA0KYGBgDQoNCiNpLiBXaGljaCBtb250aCBoYXMgdGhlIGhpZ2hlc3Qgc2FsZXM/DQoNCmBgYHtyLCB3YXJuaW5nPUZBTFNFfQ0KDQojIElkZW50aWZ5aW5nIHRoZSBtb250aCB3aXRoIHRoZSBoaWdoZXN0IHNhbGVzDQpoaWdoZXN0X3NhbGVzX21vbnRoIDwtIGNvZWZmaWNpZW50c19zdW1tYXJ5ICU+JQ0KICBmaWx0ZXIoc3RyX3N0YXJ0cyh0ZXJtLCAic2Vhc29uIikpICU+JSANCiAgYXJyYW5nZShkZXNjKGVzdGltYXRlKSkgJT4lIA0KICBzbGljZSgxKSAlPiUgDQogIHB1bGwodGVybSkgDQoNCiMgUHJpbnRpbmcgdGhlIHJlc3VsdA0KY2F0KCJUaGUgbW9udGggd2l0aCB0aGUgaGlnaGVzdCBzYWxlcyBpczoiLCBoaWdoZXN0X3NhbGVzX21vbnRoLCAiXG4iKQ0KDQojIFRoZSBtb250aCB3aXRoIHRoZSBoaWdoZXN0IHNhbGVzIGlzIFNlcHRlbWJlciAoc2Vhc29uKCl5ZWFyOSksIGFzIGluZGljYXRlZCBieSB0aGUgaGlnaGVzdCBwb3NpdGl2ZSBzZWFzb25hbCBjb2VmZmljaWVudCBpbiB0aGUgbGluZWFyIHJlZ3Jlc3Npb24gbW9kZWwuIFRoaXMgc3VnZ2VzdHMgdGhhdCBzYWxlcyBwZWFrIGluIFNlcHRlbWJlciwgbGlrZWx5IGR1ZSB0byBzZWFzb25hbCBmYWN0b3JzIHN1Y2ggYXMgYmFjay10by1zY2hvb2wgc2hvcHBpbmcgb3IgcHJvbW90aW9uYWwgYWN0aXZpdGllcy4gVGhlIG1vZGVsIGlkZW50aWZpZXMgU2VwdGVtYmVyIGFzIHRoZSBtb250aCB3aXRoIHRoZSBzdHJvbmdlc3QgcG9zaXRpdmUgaW1wYWN0IG9uIHNhbGVzIGNvbXBhcmVkIHRvIHRoZSBiYXNlbGluZSBtb250aCwgSmFudWFyeS4NCmBgYA0KDQojai4gRm9yZWNhc3QgaXQgZm9yIHRoZSBuZXh0IHllYXIuIFdoYXQgYXJlIHRoZSB2YWx1ZXMNCg0KYGBge3IsIHdhcm5pbmc9RkFMU0V9DQojIEZvcmVjYXN0aW5nIHNoYW1wb28gc2FsZXMgZm9yIHRoZSBuZXh0IHllYXINCmZjX3NoYW1wb28gPC0gZml0X3NoYW1wb28gJT4lDQogIGZvcmVjYXN0KGggPSAxMikgIyBGb3JlY2FzdCBmb3IgdGhlIG5leHQgMTIgbW9udGhzDQoNCiMgVmlld2luZyB0aGUgZm9yZWNhc3RlZCB2YWx1ZXMNCmZjX3NoYW1wb28NCg0KIyBUaGUgZm9yZWNhc3RlZCBzaGFtcG9vIHNhbGVzIGZvciB0aGUgbmV4dCB5ZWFyIHNob3cgYSBzdGVhZHkgdXB3YXJkIHRyZW5kLCB3aXRoIHNhbGVzIGluY3JlYXNpbmcgZWFjaCBtb250aCwgY29uc2lzdGVudCB3aXRoIHRoZSBtb2RlbCdzIHRyZW5kIGNvZWZmaWNpZW50LiBUaGUgaGlnaGVzdCBzYWxlcyBhcmUgcHJlZGljdGVkIGZvciBTZXB0ZW1iZXIgMTk5OCAoNjcwLjMyNTApLCBhbGlnbmluZyB3aXRoIHRoZSBzZWFzb25hbCBwZWFrLCB3aGlsZSB0aGUgbG93ZXN0IHNhbGVzIGFyZSBleHBlY3RlZCBpbiBNYXJjaCAxOTk4ICg1MTguNDU4MykuIFRoZSBmb3JlY2FzdHMgcmVmbGVjdCBib3RoIHRoZSBvdmVyYWxsIGdyb3d0aCB0cmVuZCBhbmQgc2Vhc29uYWwgdmFyaWF0aW9ucywgd2l0aCBTZXB0ZW1iZXIgc3RhbmRpbmcgb3V0IGFzIHRoZSBzdHJvbmdlc3QgbW9udGggZm9yIHNhbGVzLg0KYGBgDQoNCiNrLiBQbG90IHRoZSBmb3JlY2FzdCB3aXRoIG9yaWdpbmFsIGRhdGEuDQoNCmBgYHtyLCB3YXJuaW5nPUZBTFNFfQ0KIyBQbG90dGluZyB0aGUgZm9yZWNhc3Qgd2l0aCB0aGUgb3JpZ2luYWwgZGF0YQ0KZmNfc2hhbXBvbyAlPiUNCiAgYXV0b3Bsb3Qoc2hhbXBvb190c2liYmxlKSArDQogIGxhYnModGl0bGUgPSAiRm9yZWNhc3RlZCBTaGFtcG9vIFNhbGVzIGZvciB0aGUgTmV4dCBZZWFyIiwNCiAgICAgICB5ID0gIlNhbGVzIiwNCiAgICAgICB4ID0gIlRpbWUgKE1vbnRoKSIpICsNCiAgdGhlbWVfbWluaW1hbCgpDQoNCiMgVGhlIHBsb3Qgc2hvd3MgdGhlIGZvcmVjYXN0ZWQgc2hhbXBvbyBzYWxlcyBmb3IgdGhlIG5leHQgeWVhciAoSmFudWFyeSAxOTk4IHRvIERlY2VtYmVyIDE5OTgpIGFsb25nc2lkZSB0aGUgb3JpZ2luYWwgaGlzdG9yaWNhbCBkYXRhIChKYW51YXJ5IDE5OTUgdG8gRGVjZW1iZXIgMTk5NykuIFRoZSBmb3JlY2FzdGVkIHZhbHVlcyBleHRlbmQgdGhlIHVwd2FyZCB0cmVuZCBvYnNlcnZlZCBpbiB0aGUgaGlzdG9yaWNhbCBkYXRhLCB3aXRoIHNhbGVzIGluY3JlYXNpbmcgc3RlYWRpbHkgb3ZlciB0aW1lLiBUaGUgc2hhZGVkIHByZWRpY3Rpb24gaW50ZXJ2YWxzIGFyb3VuZCB0aGUgZm9yZWNhc3RlZCBsaW5lIGluZGljYXRlIHRoZSB1bmNlcnRhaW50eSBpbiB0aGUgcHJlZGljdGlvbnMsIHByb3ZpZGluZyBhIHJhbmdlIG9mIHBvc3NpYmxlIHNhbGVzIHZhbHVlcy4gVGhpcyB2aXN1YWxpemF0aW9uIGhpZ2hsaWdodHMgYm90aCB0aGUgZXhwZWN0ZWQgZ3Jvd3RoIGFuZCB0aGUgY29uZmlkZW5jZSBpbiB0aGUgZm9yZWNhc3RzLg0KYGBgDQoNCiNsLiBDaGVjayBpZiB0aGUgcmVzaWR1YWxzIG9mIHRoZSBtb2RlbCBpcyB3aGl0ZSBub2lzZS4NCg0KYGBge3IsIHdhcm5pbmc9RkFMU0V9DQojIGwuIEV4dHJhY3RpbmcgcmVzaWR1YWxzIGZyb20gdGhlIG1vZGVsDQpyZXNpZHVhbHNfc2hhbXBvbyA8LSBmaXRfc2hhbXBvbyAlPiUNCiAgYXVnbWVudCgpDQoNCiMgUGxvdHRpbmcgdGhlIHJlc2lkdWFscyBvdmVyIHRpbWUNCnJlc2lkdWFsc19zaGFtcG9vICU+JQ0KICBnZ3Bsb3QoYWVzKHggPSBNb250aCwgeSA9IC5yZXNpZCkpICsNCiAgZ2VvbV9saW5lKCkgKw0KICBsYWJzKHRpdGxlID0gIlJlc2lkdWFscyBPdmVyIFRpbWUiLA0KICAgICAgIHkgPSAiUmVzaWR1YWxzIiwNCiAgICAgICB4ID0gIlRpbWUgKE1vbnRoKSIpICsNCiAgdGhlbWVfbWluaW1hbCgpDQoNCiMgSGlzdG9ncmFtIG9mIHJlc2lkdWFscw0KcmVzaWR1YWxzX3NoYW1wb28gJT4lDQogIGdncGxvdChhZXMoeCA9IC5yZXNpZCkpICsNCiAgZ2VvbV9oaXN0b2dyYW0oYmlud2lkdGggPSAwLjIsIGZpbGwgPSAibGlnaHRibHVlIiwgY29sb3IgPSAiYmxhY2siKSArDQogIGxhYnModGl0bGUgPSAiSGlzdG9ncmFtIG9mIFJlc2lkdWFscyIsDQogICAgICAgeCA9ICJSZXNpZHVhbHMiLA0KICAgICAgIHkgPSAiRnJlcXVlbmN5IikgKw0KICB0aGVtZV9taW5pbWFsKCkNCg0KIyBBQ0YgcGxvdCBvZiByZXNpZHVhbHMNCnJlc2lkdWFsc19zaGFtcG9vICU+JQ0KICBBQ0YoLnJlc2lkKSAlPiUNCiAgYXV0b3Bsb3QoKSArDQogIGxhYnModGl0bGUgPSAiQUNGIFBsb3Qgb2YgUmVzaWR1YWxzIiwNCiAgICAgICB5ID0gIkFDRiIsDQogICAgICAgeCA9ICJMYWciKSArDQogIHRoZW1lX21pbmltYWwoKQ0KDQojIFRoZSByZXNpZHVhbHMgb2YgdGhlIG1vZGVsIGFyZSBjaGVja2VkIGZvciB3aGl0ZSBub2lzZSBieSBhbmFseXppbmcgdGhlaXIgZGlzdHJpYnV0aW9uLCBhdXRvY29ycmVsYXRpb24sIGFuZCByYW5kb21uZXNzLiBUaGUgdGltZSBwbG90IG9mIHJlc2lkdWFscyBzaG93cyByYW5kb20gZmx1Y3R1YXRpb25zIGFyb3VuZCB6ZXJvLCB0aGUgaGlzdG9ncmFtIGluZGljYXRlcyBhbiBhcHByb3hpbWF0ZWx5IG5vcm1hbCBkaXN0cmlidXRpb24sIGFuZCB0aGUgQUNGIHBsb3QgcmV2ZWFscyBubyBzaWduaWZpY2FudCBhdXRvIGNvcnJlbGF0aW9ucyBhdCBhbnkgbGFnLiBUaGVzZSBmaW5kaW5ncyBzdWdnZXN0IHRoYXQgdGhlIHJlc2lkdWFscyByZXNlbWJsZSB3aGl0ZSBub2lzZSwgaW5kaWNhdGluZyB0aGF0IHRoZSBtb2RlbCBoYXMgZWZmZWN0aXZlbHkgY2FwdHVyZWQgYWxsIHN5c3RlbWF0aWMgcGF0dGVybnMgaW4gdGhlIGRhdGEsIGxlYXZpbmcgb25seSByYW5kb20gdmFyaWF0aW9ucy4NCg0KYGBgDQoNCiNtLiBCeSB1c2luZyB0aGUgcmVncmVzc2lvbiBtb2RlbCwgZm9yZWNhc3QgdGhlIDEgeWVhciBhaGVhZCwgYW5kIHRoZW4gY2hlY2sgdGhlIGFjY3VyYWN5IG9mIHRoZSBmb3JlY2FzdC4gV2hhdCBpcyBNU0UsIFJNU0UgdmFsdWVzPw0KDQpgYGB7ciwgd2FybmluZz1GQUxTRX0NCiMgbS4gRm9yZWNhc3QgMSB5ZWFyIGFoZWFkDQpmY19zaGFtcG9vIDwtIGZpdF9zaGFtcG9vICU+JQ0KICBmb3JlY2FzdChoID0gMTIpICMgRm9yZWNhc3QgZm9yIHRoZSBuZXh0IDEyIG1vbnRocw0KDQojIENhbGN1bGF0ZSBhY2N1cmFjeSBtZXRyaWNzDQphY2N1cmFjeV9mYyA8LSBmY19zaGFtcG9vICU+JQ0KICBhY2N1cmFjeShzaGFtcG9vX3RzaWJibGUpICMgQ29tcGFyZSBmb3JlY2FzdHMgd2l0aCBhY3R1YWwgZGF0YQ0KDQojIEV4dHJhY3QgTVNFIGFuZCBSTVNFDQptc2UgPC0gYWNjdXJhY3lfZmMkTVNFDQpybXNlIDwtIGFjY3VyYWN5X2ZjJFJNU0UNCg0KIyBQcmludCB0aGUgcmVzdWx0cw0KY2F0KCJNZWFuIFNxdWFyZWQgRXJyb3IgKE1TRSk6IiwgbXNlLCAiXG4iKQ0KY2F0KCJSb290IE1lYW4gU3F1YXJlZCBFcnJvciAoUk1TRSk6Iiwgcm1zZSwgIlxuIikNCg0KIyBtLiBBbnN3ZXI6DQojIFRoZSBpc3N1ZSB3aXRoIG5vdCBvYnRhaW5pbmcgZGF0YSBmb3IgTVNFIGFuZCBSTVNFIGFyaXNlcyBiZWNhdXNlIHRoZSBkYXRhc2V0IG9ubHkgaW5jbHVkZXMgc2hhbXBvbyBzYWxlcyBkYXRhIHVwIHRvIERlY2VtYmVyIDE5OTcsIHdoaWxlIHRoZSBmb3JlY2FzdCBpcyBmb3IgSmFudWFyeSAxOTk4IHRvIERlY2VtYmVyIDE5OTguIFNpbmNlIGFjdHVhbCBzYWxlcyBkYXRhIGZvciAxOTk4IGlzIG1pc3NpbmcsIHRoZSBhY2N1cmFjeSgpIGZ1bmN0aW9uIGNhbm5vdCBjb21wYXJlIHRoZSBmb3JlY2FzdGVkIHZhbHVlcyB3aXRoIGFjdHVhbCB2YWx1ZXMsIHJlc3VsdGluZyBpbiBOYU4gZm9yIFJNU0UgYW5kIG5vIHZhbHVlIGZvciBNU0UuIFRvIGNhbGN1bGF0ZSBhY2N1cmFjeSBtZXRyaWNzLCBhY3R1YWwgc2FsZXMgZGF0YSBmb3IgMTk5OCB3b3VsZCBiZSByZXF1aXJlZC4gQWx0ZXJuYXRpdmVseSwgdGhlIG1vZGVs4oCZcyBwZXJmb3JtYW5jZSBjb3VsZCBiZSBldmFsdWF0ZWQgb24gaGlzdG9yaWNhbCBkYXRhIGJ5IHNwbGl0dGluZyB0aGUgZGF0YXNldCBpbnRvIHRyYWluaW5nIGFuZCB0ZXN0aW5nIHNldHMuDQoNCg0KYGBgDQo=