library(tidyverse)
library(lubridate)
library(forecast)
library(tseries)
library(knitr)
library(htmltools)

knitr::opts_chunk$set(
  message = FALSE,
  warning = FALSE,
  fig.align = "center",
  fig.width = 9.5,
  fig.height = 5.2
)

plot_theme <- theme_minimal(base_size = 13) +
  theme(
    plot.title = element_text(face = "bold", size = 16, color = "#1d3557"),
    plot.subtitle = element_text(size = 11, color = "#6c7a89"),
    panel.grid.minor = element_blank(),
    panel.grid.major = element_line(color = "#e6edf5"),
    axis.title = element_text(color = "#334e68"),
    axis.text = element_text(color = "#4b6478")
  )

1. Introduction

This project analyses monthly Google search interest for Bitcoin as a time series. The aim is to investigate whether public interest in Bitcoin contains enough structure to support short-term forecasting.

Bitcoin search interest is not likely to behave like a stable economic or demographic series. Public attention can change quickly when Bitcoin appears in the news, when prices rise or fall sharply, or when cryptocurrency becomes part of wider market discussion. Because of this, the project is not only about producing a forecast, but also about testing how reliable that forecast is.

The analysis uses decomposition, stationarity testing, benchmark models, ETS models and SARIMA models. Models are compared using a train-test split, so the final judgement is based on performance on unseen data rather than visual fit.

Project focus: The main question is whether Bitcoin search interest behaves like a forecastable time series, or whether it is too event-driven for classical models to predict reliably.

2. Data

The dataset contains monthly Bitcoin search interest values. The values are relative Google Trends scores, so they do not represent exact search volumes. A higher value means Bitcoin had higher search interest during that month.

Code: load the Bitcoin search interest dataset
bitcoin_raw <- read.csv("BitcoinTimeSeries.csv")

The original columns are renamed to make the analysis easier to read. The date column is also converted into a proper date format so that R can treat it as a monthly time series.

Code: clean the date column and prepare the search interest series
bitcoin <- bitcoin_raw %>%
  rename(
    date = Time,
    value = Bitcoin
  )

bitcoin$date <- as.Date(bitcoin$date, format = "%d/%m/%Y")

bitcoin <- bitcoin %>%
  filter(!is.na(date), !is.na(value)) %>%
  arrange(date)

start_date <- min(bitcoin$date)
end_date <- max(bitcoin$date)
n_obs <- nrow(bitcoin)
min_value <- min(bitcoin$value)
max_value <- max(bitcoin$value)

After cleaning, the dataset runs from 2015-01-01 to 2026-01-01, with 133 monthly observations. Search interest ranges from 2 to 100.

The data is monthly, so it is converted into a time series object with frequency 12. This tells R that the data has 12 observations per year.

Code: convert the cleaned data into a monthly time series object
btc_ts <- ts(
  bitcoin$value,
  frequency = 12,
  start = c(year(min(bitcoin$date)), month(min(bitcoin$date)))
)

ts_frequency <- frequency(btc_ts)
ts_observations <- length(btc_ts)
ts_start <- paste(start(btc_ts), collapse = "-")
ts_end <- paste(end(btc_ts), collapse = "-")
Frequency
12
Observations
133
Start
2015-1
End
2026-1

3. Exploratory analysis

The first step is to inspect the overall shape of the series.

Code: plot monthly Bitcoin search interest over time
ggplot(bitcoin, aes(x = date, y = value)) +
  geom_line(linewidth = 0.8, colour = "#1d3557") +
  labs(
    title = "Bitcoin search interest over time",
    subtitle = "Monthly relative Google Trends score",
    x = "Date",
    y = "Search interest"
  ) +
  plot_theme +
  theme(axis.text.x = element_text(angle = 45, hjust = 1))

The plot shows that search interest is not stable over time. There are several sharp spikes, which is expected for Bitcoin because public attention often increases suddenly around price movements, news events or wider market discussion.

Code: calculate summary statistics for the search interest series
summary_stats <- bitcoin %>%
  summarise(
    observations = n(),
    mean_value = round(mean(value), 2),
    median_value = round(median(value), 2),
    sd_value = round(sd(value), 2),
    minimum_value = min(value),
    maximum_value = max(value)
  )

obs_value <- summary_stats$observations
mean_value <- summary_stats$mean_value
median_value <- summary_stats$median_value
sd_value <- summary_stats$sd_value
minimum_value <- summary_stats$minimum_value
maximum_value <- summary_stats$maximum_value
Observations
133
Mean
20.48
Median
18
Standard deviation
15.5
Minimum
2
Maximum
100

The gap between the median and the maximum suggests that the series is not evenly spread around a typical level. Instead, there are occasional periods where search interest becomes much higher than usual.

Initial observation: Bitcoin search interest appears volatile and spike-driven. A model that assumes a smooth stable pattern is unlikely to be enough by itself.

4. Decomposition

STL decomposition separates the series into trend, seasonal and remainder components. This helps show whether the movement in the series is mainly long-term trend, repeated seasonality or irregular shocks.

Code: decompose the series into trend, seasonality and remainder
decomp <- stl(btc_ts, s.window = "periodic")
plot(decomp)

The trend component shows longer-term movement in Bitcoin interest. The seasonal component shows repeated monthly effects. The remainder shows irregular movements that are not explained by the trend or seasonality.

For this dataset, the remainder is important because Bitcoin search interest is strongly affected by events. This means that even if there is some trend or seasonality, sudden shocks can still dominate the series.

Method note: Decomposition is not a forecasting model by itself. It is used to understand the structure of the series before fitting models.

5. Stationarity

ARIMA-type models usually work better when the series is stationary. A stationary series has statistical properties that are reasonably stable over time. The original plot suggests that Bitcoin search interest may not be stationary, so the Augmented Dickey-Fuller test is used.

Code: run ADF stationarity tests before and after differencing
adf_original <- adf.test(btc_ts)

diff_btc <- diff(btc_ts)
adf_differenced <- adf.test(diff_btc)

adf_table <- data.frame(
  Series = c("Original series", "Differenced series"),
  `ADF statistic` = c(
    round(as.numeric(adf_original$statistic), 4),
    round(as.numeric(adf_differenced$statistic), 4)
  ),
  `p-value` = c(
    round(adf_original$p.value, 4),
    round(adf_differenced$p.value, 4)
  )
)

kable(adf_table, caption = "ADF stationarity tests")
ADF stationarity tests
Series ADF.statistic p.value
Original series -3.3118 0.0723
Differenced series -6.0517 0.0100

A lower p-value gives stronger evidence against a unit root. The differenced series is included because differencing is a common way to reduce changes in level and make a series more suitable for ARIMA modelling.

Code: plot the differenced series
autoplot(diff_btc) +
  labs(
    title = "Differenced Bitcoin search interest",
    x = "Time",
    y = "Change in search interest"
  ) +
  plot_theme

Modelling point: Differencing changes the problem slightly. Instead of only modelling the level of search interest, the model also focuses on how search interest changes from one month to the next.

6. Autocorrelation

The ACF and PACF plots help assess whether past values are related to current values. This matters because time series models rely on the idea that the past contains information about the future.

Code: plot ACF and PACF for the differenced series
acf(diff_btc, main = "ACF of differenced series")

pacf(diff_btc, main = "PACF of differenced series")

The ACF shows correlation with previous lags, while the PACF shows the correlation at each lag after accounting for shorter lags. These plots are not used to manually choose the final model, but they are useful as a check before using automatic ARIMA selection.

7. Train-test split

To avoid judging models only on how well they fit the past, the final 12 observations are held back as a test set.

Code: split the series into training and test sets
n <- length(btc_ts)

train <- window(btc_ts, end = time(btc_ts)[n - 12])
test <- window(btc_ts, start = time(btc_ts)[n - 11])

train_obs <- length(train)
test_obs <- length(test)
Training set
121
Test set
12

Why this matters: A train-test split gives a more honest comparison. A model can fit historical data well but still perform badly on future observations.

8. Benchmark models

Before fitting ETS and SARIMA models, simple benchmark models are used. These are important because a more complicated model is not automatically better. It should improve on simple alternatives.

The mean forecast is a simple long-term average. The naive forecast assumes the latest observation is the best guide to the near future. The seasonal naive forecast tests whether the same month in the previous year is useful for prediction.

Code: fit mean, naive and seasonal naive benchmark forecasts
mean_fit <- meanf(train, h = length(test))
naive_fit <- naive(train, h = length(test))
snaive_fit <- snaive(train, h = length(test))

benchmark_table <- data.frame(
  Model = c("Mean forecast", "Naive forecast", "Seasonal naive forecast"),
  Idea = c(
    "Future values are forecast using the training-set average.",
    "Future values are forecast using the most recent observation.",
    "Future values repeat the value from the same month in the previous year."
  )
)

kable(benchmark_table, caption = "Benchmark models")
Benchmark models
Model Idea
Mean forecast Future values are forecast using the training-set average.
Naive forecast Future values are forecast using the most recent observation.
Seasonal naive forecast Future values repeat the value from the same month in the previous year.
Code: plot benchmark forecasts over the test horizon
autoplot(mean_fit) +
  labs(title = "Mean forecast", x = "Time", y = "Search interest") +
  plot_theme

autoplot(naive_fit) +
  labs(title = "Naive forecast", x = "Time", y = "Search interest") +
  plot_theme

autoplot(snaive_fit) +
  labs(title = "Seasonal naive forecast", x = "Time", y = "Search interest") +
  plot_theme

Benchmark purpose: If ETS or SARIMA cannot beat these simple models on unseen data, then the extra complexity is not adding much value.

9. ETS model

ETS model: ETS stands for Error, Trend and Seasonality. It is based on exponential smoothing, meaning it gives more weight to recent observations while still using the history of the series.

ETS models are useful when the level, trend or seasonal pattern of a series changes over time. In this project, ETS is worth testing because Bitcoin search interest does not appear stable across the full period.

Code: fit the ETS model and generate forecasts
ets_fit <- ets(train)
ets_forecast <- forecast(ets_fit, h = length(test))
Code: create a clean ETS model summary table
ets_table <- data.frame(
  Model = as.character(ets_fit$method),
  AIC = round(ets_fit$aic, 2),
  AICc = round(ets_fit$aicc, 2),
  BIC = round(ets_fit$bic, 2)
)

kable(ets_table, caption = "ETS model summary")
ETS model summary
Model AIC AICc BIC
ETS(M,A,M) 939.71 945.65 987.24
Code: plot ETS forecast against the test period
autoplot(ets_forecast) +
  labs(
    title = "ETS forecast",
    subtitle = "Forecast over the 12-month test period",
    x = "Time",
    y = "Search interest"
  ) +
  plot_theme

The forecast line gives the model’s central estimate. The shaded intervals show uncertainty. Wider intervals mean the model is less confident about future values.

10. SARIMA model

SARIMA model: SARIMA is a seasonal version of ARIMA, which stands for AutoRegressive Integrated Moving Average.

The autoregressive part uses past values of the series. The integrated part means the model can difference the series to handle non-stationarity. The moving-average part uses past forecast errors. The seasonal part allows the model to capture patterns that repeat every 12 months.

Code: fit the SARIMA model and generate forecasts
arima_fit <- auto.arima(train, seasonal = TRUE)
arima_forecast <- forecast(arima_fit, h = length(test))
Code: create a clean SARIMA model summary table
sarima_table <- data.frame(
  Model = as.character(arima_fit),
  AIC = round(AIC(arima_fit), 2),
  AICc = round(arima_fit$aicc, 2),
  BIC = round(BIC(arima_fit), 2)
)

kable(sarima_table, caption = "SARIMA model summary")
SARIMA model summary
Model AIC AICc BIC
ARIMA(0,1,0) 884.52 884.55 887.3
Code: plot SARIMA forecast against the test period
autoplot(arima_forecast) +
  labs(
    title = "SARIMA forecast",
    subtitle = "Forecast over the 12-month test period",
    x = "Time",
    y = "Search interest"
  ) +
  plot_theme

A SARIMA model written as ARIMA(p,d,q)(P,D,Q)[12] means that p, d and q are the non-seasonal terms, while P, D and Q are the seasonal terms. The [12] appears because the data is monthly.

11. Forecast comparison

The models are compared on the test set using RMSE, MAE and MAPE.

RMSE penalises large errors more heavily. MAE gives the average absolute error. MAPE expresses the error as a percentage.

Code: calculate out-of-sample accuracy for all models
mean_accuracy <- accuracy(mean_fit, test)
naive_accuracy <- accuracy(naive_fit, test)
snaive_accuracy <- accuracy(snaive_fit, test)
ets_accuracy <- accuracy(ets_forecast, test)
arima_accuracy <- accuracy(arima_forecast, test)

accuracy_table <- rbind(
  Mean = mean_accuracy[2, c("RMSE", "MAE", "MAPE")],
  Naive = naive_accuracy[2, c("RMSE", "MAE", "MAPE")],
  Seasonal_Naive = snaive_accuracy[2, c("RMSE", "MAE", "MAPE")],
  ETS = ets_accuracy[2, c("RMSE", "MAE", "MAPE")],
  SARIMA = arima_accuracy[2, c("RMSE", "MAE", "MAPE")]
)

accuracy_table <- round(as.data.frame(accuracy_table), 3)

kable(accuracy_table, caption = "Out-of-sample forecast accuracy")
Out-of-sample forecast accuracy
RMSE MAE MAPE
Mean 8.686 7.214 24.474
Naive 7.159 6.250 26.222
Seasonal_Naive 8.963 7.333 26.027
ETS 8.103 6.521 24.443
SARIMA 7.159 6.250 26.222
Code: identify the best model using RMSE
best_model_name <- rownames(accuracy_table)[which.min(accuracy_table$RMSE)]
best_rmse <- min(accuracy_table$RMSE)
Best model by RMSE
Naive
Lowest RMSE
7.159

Model selection: The best model is selected using out-of-sample performance, not visual fit. This tests whether the model can generalise beyond the data it was trained on.

12. Residual diagnostics

A model should not leave behind obvious patterns in the residuals. If residuals still show autocorrelation, then the model has not captured all of the time series structure.

Code: run Ljung-Box residual autocorrelation tests
arima_lb <- Box.test(residuals(arima_fit), lag = 12, type = "Ljung-Box")
ets_lb <- Box.test(residuals(ets_fit), lag = 12, type = "Ljung-Box")

residual_table <- data.frame(
  Model = c("ETS", "SARIMA"),
  `Ljung-Box statistic` = c(
    round(as.numeric(ets_lb$statistic), 3),
    round(as.numeric(arima_lb$statistic), 3)
  ),
  `p-value` = c(
    round(ets_lb$p.value, 4),
    round(arima_lb$p.value, 4)
  )
)

kable(residual_table, caption = "Residual autocorrelation diagnostics")
Residual autocorrelation diagnostics
Model Ljung.Box.statistic p.value
ETS 6.705 0.8765
SARIMA 8.734 0.7255

The Ljung-Box test checks whether residual autocorrelation remains. A high p-value suggests there is no strong evidence of remaining autocorrelation. A low p-value suggests the model may still be missing some structure.

Code: plot SARIMA residual diagnostics
checkresiduals(arima_fit)

Code: plot ETS residual diagnostics
checkresiduals(ets_fit)

13. Final forecast

After comparing the models, the SARIMA model is refitted on the full dataset and used to produce a 12-month forecast. The train-test split was used for model evaluation; once that is complete, the final model can use all available observations.

Code: refit SARIMA using the full dataset and forecast 12 months ahead
final_model <- auto.arima(btc_ts, seasonal = TRUE)
final_forecast <- forecast(final_model, h = 12)
Code: create final model summary table
final_table <- data.frame(
  Model = as.character(final_model),
  AIC = round(AIC(final_model), 2),
  AICc = round(final_model$aicc, 2),
  BIC = round(BIC(final_model), 2)
)

kable(final_table, caption = "Final model fitted on full dataset")
Final model fitted on full dataset
Model AIC AICc BIC
ARIMA(0,1,0) 964.95 964.98 967.83
Code: plot the final 12-month forecast
autoplot(final_forecast) +
  labs(
    title = "Final 12-month forecast for Bitcoin search interest",
    subtitle = "SARIMA model refitted using the full dataset",
    x = "Time",
    y = "Search interest"
  ) +
  plot_theme

Forecast interpretation: This forecast should not be treated as a precise prediction. Bitcoin search interest is strongly affected by news, price movements and market sentiment. The forecast is best understood as a model-based estimate assuming future behaviour is similar to past patterns.

14. Limitations and possible extensions

There are several limitations to this project.

First, Google Trends gives relative search interest rather than the actual number of searches. Second, this is a univariate analysis, so the models only use past search interest. They do not include Bitcoin price, trading volume, market volatility, news sentiment or macroeconomic variables.

This matters because Bitcoin attention is likely driven by external factors. A large price movement or major news story could change search interest very quickly, and a model based only on past search interest may not react until after the movement has already happened.

Possible extensions include:

  • adding Bitcoin price as an external regressor;
  • testing an ARIMAX model;
  • comparing the results with Prophet;
  • using rolling-window cross-validation;
  • including news or social media sentiment;
  • modelling search interest and price together.

15. Conclusion

This project shows that Bitcoin search interest is volatile, uneven and strongly affected by spikes in public attention. The decomposition and stationarity analysis suggest that the series is not a simple stable process.

The model comparison shows why benchmarks are important. A more complicated model is only useful if it improves on simple methods when tested on unseen data. ETS and SARIMA provide more structured approaches, but their usefulness depends on whether they actually reduce forecast error on the test set.

Overall, classical time series models can capture some of the structure in Bitcoin search interest, but there are clear limits. The series is partly predictable from its own history, but it is also heavily influenced by external events. A stronger future version of this project would include explanatory variables such as Bitcoin price, trading volume and news sentiment.

LS0tCnRpdGxlOiAiRm9yZWNhc3RpbmcgQml0Y29pbiBTZWFyY2ggSW50ZXJlc3QiCmF1dGhvcjogIlpheWFuIEFmemFsIgpkYXRlOiAiYHIgZm9ybWF0KFN5cy5EYXRlKCksICclQiAlWScpYCIKb3V0cHV0OgogIGh0bWxfZG9jdW1lbnQ6CiAgICB0b2M6IHRydWUKICAgIHRvY19mbG9hdDogdHJ1ZQogICAgdG9jX2RlcHRoOiAyCiAgICB0aGVtZTogbHVtZW4KICAgIGhpZ2hsaWdodDogdGV4dG1hdGUKICAgIGNvZGVfZm9sZGluZzogaGlkZQogICAgY29kZV9kb3dubG9hZDogdHJ1ZQogICAgZGZfcHJpbnQ6IHBhZ2VkCi0tLQoKPHN0eWxlPgpib2R5IHsKICBmb250LWZhbWlseTogLWFwcGxlLXN5c3RlbSwgQmxpbmtNYWNTeXN0ZW1Gb250LCAiU2Vnb2UgVUkiLCBSb2JvdG8sIEFyaWFsLCBzYW5zLXNlcmlmOwogIGZvbnQtc2l6ZTogMTZweDsKICBsaW5lLWhlaWdodDogMS42NTsKICBjb2xvcjogIzIzMzE0MjsKICBiYWNrZ3JvdW5kOiBsaW5lYXItZ3JhZGllbnQoMTgwZGVnLCAjZjZmYmZmIDAlLCAjZmZmZmZmIDI2MHB4KTsKfQoKLm1haW4tY29udGFpbmVyIHsKICBtYXgtd2lkdGg6IDEwMjBweDsKICBtYXJnaW4tbGVmdDogYXV0bzsKICBtYXJnaW4tcmlnaHQ6IGF1dG87CiAgYmFja2dyb3VuZDogI2ZmZmZmZjsKICBwYWRkaW5nOiAzOHB4IDQ4cHg7CiAgYm9yZGVyLXJhZGl1czogMTZweDsKICBib3gtc2hhZG93OiAwIDhweCAyOHB4IHJnYmEoNDUsIDg3LCAxMjIsIDAuMTApOwp9CgpoMS50aXRsZSB7CiAgZm9udC1zaXplOiA0MHB4OwogIGZvbnQtd2VpZ2h0OiA4MDA7CiAgY29sb3I6ICMxZDM1NTc7CiAgbWFyZ2luLXRvcDogMTVweDsKICBtYXJnaW4tYm90dG9tOiA4cHg7CiAgbGV0dGVyLXNwYWNpbmc6IC0wLjRweDsKfQoKLmF1dGhvciwgLmRhdGUgewogIGNvbG9yOiAjNmM3YTg5OwogIGZvbnQtc2l6ZTogMTVweDsKfQoKaDEgewogIGZvbnQtc2l6ZTogMjdweDsKICBmb250LXdlaWdodDogNzUwOwogIGNvbG9yOiAjMWQzNTU3OwogIG1hcmdpbi10b3A6IDQ4cHg7CiAgcGFkZGluZy1ib3R0b206IDhweDsKICBib3JkZXItYm90dG9tOiAzcHggc29saWQgI2RiZWFmZTsKfQoKaDIgewogIGZvbnQtc2l6ZTogMjFweDsKICBmb250LXdlaWdodDogNzAwOwogIGNvbG9yOiAjMjc0Yzc3OwogIG1hcmdpbi10b3A6IDM0cHg7Cn0KCmgzIHsKICBmb250LXNpemU6IDE4cHg7CiAgZm9udC13ZWlnaHQ6IDcwMDsKICBjb2xvcjogIzMzNGU2ODsKfQoKcCB7CiAgbWFyZ2luLWJvdHRvbTogMTVweDsKfQoKdWwgewogIG1hcmdpbi1ib3R0b206IDE4cHg7Cn0KCi8qIFN0YW5kYXJkIHRhYmxlcyAqLwp0YWJsZSB7CiAgd2lkdGg6IDEwMCU7CiAgbWFyZ2luLXRvcDogMThweDsKICBtYXJnaW4tYm90dG9tOiAyNnB4OwogIGJvcmRlci1jb2xsYXBzZTogY29sbGFwc2U7CiAgZm9udC1zaXplOiAxNC41cHg7CiAgYmFja2dyb3VuZDogI2ZmZmZmZjsKfQoKY2FwdGlvbiB7CiAgY2FwdGlvbi1zaWRlOiB0b3A7CiAgdGV4dC1hbGlnbjogbGVmdDsKICBjb2xvcjogIzI3NGM3NzsKICBmb250LXdlaWdodDogNzAwOwogIG1hcmdpbi1ib3R0b206IDhweDsKfQoKdGggewogIGJhY2tncm91bmQtY29sb3I6ICNlYWY0ZmY7CiAgY29sb3I6ICMxZDM1NTc7CiAgZm9udC13ZWlnaHQ6IDcwMDsKICBib3JkZXItYm90dG9tOiAxcHggc29saWQgI2JmZDdlZDsKfQoKdGQsIHRoIHsKICBwYWRkaW5nOiA5cHggMTFweDsKICBib3JkZXItYm90dG9tOiAxcHggc29saWQgI2U2ZWRmNTsKfQoKLyogQ2xlYW5lciB0YWJsZSB3cmFwcGVyICovCi5jbGVhbi10YWJsZSB7CiAgbWFyZ2luOiAyMnB4IDAgMzBweCAwOwogIGJvcmRlcjogMXB4IHNvbGlkICNkYmVhZmU7CiAgYm9yZGVyLXJhZGl1czogMTJweDsKICBvdmVyZmxvdzogaGlkZGVuOwogIGJveC1zaGFkb3c6IDAgNHB4IDE0cHggcmdiYSg0NSwgODcsIDEyMiwgMC4wNik7Cn0KCi5jbGVhbi10YWJsZSB0YWJsZSB7CiAgbWFyZ2luOiAwOwp9CgouY2xlYW4tdGFibGUgY2FwdGlvbiB7CiAgcGFkZGluZzogMTJweCAxNHB4OwogIGJhY2tncm91bmQ6ICNmNWZhZmY7CiAgbWFyZ2luLWJvdHRvbTogMDsKfQoKLmNsZWFuLXRhYmxlIHRoIHsKICBiYWNrZ3JvdW5kOiAjZWFmNGZmOwp9CgovKiBNZXRyaWMgY2FyZHMgKi8KLm1ldHJpYy1ncmlkIHsKICBkaXNwbGF5OiBncmlkOwogIGdyaWQtdGVtcGxhdGUtY29sdW1uczogcmVwZWF0KGF1dG8tZml0LCBtaW5tYXgoMTYwcHgsIDFmcikpOwogIGdhcDogMTRweDsKICBtYXJnaW46IDIycHggMCAyOHB4IDA7Cn0KCi5tZXRyaWMtY2FyZCB7CiAgYmFja2dyb3VuZDogI2ZmZmZmZjsKICBib3JkZXI6IDFweCBzb2xpZCAjZGJlYWZlOwogIGJvcmRlci1yYWRpdXM6IDEycHg7CiAgcGFkZGluZzogMTZweCAxOHB4OwogIGJveC1zaGFkb3c6IDAgNHB4IDE0cHggcmdiYSg0NSwgODcsIDEyMiwgMC4wNyk7Cn0KCi5tZXRyaWMtbGFiZWwgewogIGNvbG9yOiAjNmM3YTg5OwogIGZvbnQtc2l6ZTogMTNweDsKICBmb250LXdlaWdodDogNzAwOwogIHRleHQtdHJhbnNmb3JtOiB1cHBlcmNhc2U7CiAgbGV0dGVyLXNwYWNpbmc6IDAuM3B4OwogIG1hcmdpbi1ib3R0b206IDZweDsKfQoKLm1ldHJpYy12YWx1ZSB7CiAgY29sb3I6ICMxZDM1NTc7CiAgZm9udC1zaXplOiAyNHB4OwogIGZvbnQtd2VpZ2h0OiA4MDA7Cn0KCi8qIENvZGUgKi8KcHJlIHsKICBiYWNrZ3JvdW5kLWNvbG9yOiAjZjhmYmZmOwogIGJvcmRlcjogMXB4IHNvbGlkICNkYmVhZmU7CiAgYm9yZGVyLXJhZGl1czogOHB4Owp9Cgpjb2RlIHsKICBjb2xvcjogIzFkMzU1NzsKICBiYWNrZ3JvdW5kLWNvbG9yOiAjZWVmNmZmOwogIGJvcmRlci1yYWRpdXM6IDRweDsKfQoKLmJ0biB7CiAgYm9yZGVyLXJhZGl1czogOTk5cHggIWltcG9ydGFudDsKICBib3JkZXI6IDFweCBzb2xpZCAjYmZkN2VkICFpbXBvcnRhbnQ7CiAgYmFja2dyb3VuZDogI2VhZjRmZiAhaW1wb3J0YW50OwogIGNvbG9yOiAjMWQzNTU3ICFpbXBvcnRhbnQ7CiAgZm9udC13ZWlnaHQ6IDYwMCAhaW1wb3J0YW50OwogIHBhZGRpbmc6IDVweCAxNHB4ICFpbXBvcnRhbnQ7CiAgYm94LXNoYWRvdzogbm9uZSAhaW1wb3J0YW50Owp9CgouYnRuOmhvdmVyIHsKICBiYWNrZ3JvdW5kOiAjZGJlYWZlICFpbXBvcnRhbnQ7CiAgY29sb3I6ICMwZjJhNDMgIWltcG9ydGFudDsKfQoKYnV0dG9uLmNvZGUtZm9sZGluZy1idG4sCmJ1dHRvbltkYXRhLXRvZ2dsZT0iY29sbGFwc2UiXSB7CiAgYm9yZGVyLXJhZGl1czogOTk5cHggIWltcG9ydGFudDsKICBiYWNrZ3JvdW5kOiAjZWFmNGZmICFpbXBvcnRhbnQ7CiAgY29sb3I6ICMxZDM1NTcgIWltcG9ydGFudDsKICBib3JkZXI6IDFweCBzb2xpZCAjYmZkN2VkICFpbXBvcnRhbnQ7CiAgZm9udC13ZWlnaHQ6IDYwMCAhaW1wb3J0YW50Owp9CgouY29kZS1sYWJlbCB7CiAgZm9udC1zaXplOiAxMy41cHg7CiAgZm9udC13ZWlnaHQ6IDY1MDsKICBjb2xvcjogIzQ2NjI3ZjsKICBiYWNrZ3JvdW5kOiAjZjRmOWZmOwogIGJvcmRlcjogMXB4IHNvbGlkICNkYmVhZmU7CiAgYm9yZGVyLWxlZnQ6IDRweCBzb2xpZCAjNWRhZGUyOwogIHBhZGRpbmc6IDhweCAxMnB4OwogIGJvcmRlci1yYWRpdXM6IDhweDsKICBtYXJnaW4tdG9wOiAxOHB4OwogIG1hcmdpbi1ib3R0b206IDhweDsKfQoKLyogUGxvdHMgKi8KaW1nIHsKICBib3JkZXItcmFkaXVzOiA4cHg7CiAgbWFyZ2luLXRvcDogOHB4OwogIG1hcmdpbi1ib3R0b206IDEycHg7Cn0KCi8qIFRhYmxlIG9mIGNvbnRlbnRzICovCi50b2NpZnkgewogIGJvcmRlcjogMXB4IHNvbGlkICNkYmVhZmU7CiAgYm9yZGVyLXJhZGl1czogMTBweDsKICBiYWNrZ3JvdW5kOiAjZmZmZmZmOwp9CgoudG9jaWZ5IC5hY3RpdmUgewogIGJhY2tncm91bmQtY29sb3I6ICNkYmVhZmUgIWltcG9ydGFudDsKICBjb2xvcjogIzFkMzU1NyAhaW1wb3J0YW50OwogIGZvbnQtd2VpZ2h0OiA3MDA7Cn0KCi8qIENhbGxvdXQgYm94ZXMgKi8KLnRha2Vhd2F5IHsKICBiYWNrZ3JvdW5kOiAjZjVmYWZmOwogIGJvcmRlcjogMXB4IHNvbGlkICNkYmVhZmU7CiAgYm9yZGVyLWxlZnQ6IDVweCBzb2xpZCAjNWRhZGUyOwogIHBhZGRpbmc6IDE1cHggMThweDsKICBtYXJnaW46IDIycHggMDsKICBib3JkZXItcmFkaXVzOiAxMHB4Owp9CgoubWV0aG9kIHsKICBiYWNrZ3JvdW5kOiAjZjhmYmY4OwogIGJvcmRlcjogMXB4IHNvbGlkICNkOGVhZDg7CiAgYm9yZGVyLWxlZnQ6IDVweCBzb2xpZCAjNmFiZjY5OwogIHBhZGRpbmc6IDE1cHggMThweDsKICBtYXJnaW46IDIycHggMDsKICBib3JkZXItcmFkaXVzOiAxMHB4Owp9CgouY2F1dGlvbiB7CiAgYmFja2dyb3VuZDogI2ZmZmFmMDsKICBib3JkZXI6IDFweCBzb2xpZCAjZmRlN2JkOwogIGJvcmRlci1sZWZ0OiA1cHggc29saWQgI2Y0Yjg2MDsKICBwYWRkaW5nOiAxNXB4IDE4cHg7CiAgbWFyZ2luOiAyMnB4IDA7CiAgYm9yZGVyLXJhZGl1czogMTBweDsKfQoKLm1vZGVsLWJveCB7CiAgYmFja2dyb3VuZDogI2ZhZjVmZjsKICBib3JkZXI6IDFweCBzb2xpZCAjZWFkY2ZmOwogIGJvcmRlci1sZWZ0OiA1cHggc29saWQgIzliNWRlNTsKICBwYWRkaW5nOiAxNXB4IDE4cHg7CiAgbWFyZ2luOiAyMnB4IDA7CiAgYm9yZGVyLXJhZGl1czogMTBweDsKfQo8L3N0eWxlPgoKYGBge3Igc2V0dXAsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CmxpYnJhcnkodGlkeXZlcnNlKQpsaWJyYXJ5KGx1YnJpZGF0ZSkKbGlicmFyeShmb3JlY2FzdCkKbGlicmFyeSh0c2VyaWVzKQpsaWJyYXJ5KGtuaXRyKQpsaWJyYXJ5KGh0bWx0b29scykKCmtuaXRyOjpvcHRzX2NodW5rJHNldCgKICBtZXNzYWdlID0gRkFMU0UsCiAgd2FybmluZyA9IEZBTFNFLAogIGZpZy5hbGlnbiA9ICJjZW50ZXIiLAogIGZpZy53aWR0aCA9IDkuNSwKICBmaWcuaGVpZ2h0ID0gNS4yCikKCnBsb3RfdGhlbWUgPC0gdGhlbWVfbWluaW1hbChiYXNlX3NpemUgPSAxMykgKwogIHRoZW1lKAogICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChmYWNlID0gImJvbGQiLCBzaXplID0gMTYsIGNvbG9yID0gIiMxZDM1NTciKSwKICAgIHBsb3Quc3VidGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDExLCBjb2xvciA9ICIjNmM3YTg5IiksCiAgICBwYW5lbC5ncmlkLm1pbm9yID0gZWxlbWVudF9ibGFuaygpLAogICAgcGFuZWwuZ3JpZC5tYWpvciA9IGVsZW1lbnRfbGluZShjb2xvciA9ICIjZTZlZGY1IiksCiAgICBheGlzLnRpdGxlID0gZWxlbWVudF90ZXh0KGNvbG9yID0gIiMzMzRlNjgiKSwKICAgIGF4aXMudGV4dCA9IGVsZW1lbnRfdGV4dChjb2xvciA9ICIjNGI2NDc4IikKICApCmBgYAoKIyAxLiBJbnRyb2R1Y3Rpb24KClRoaXMgcHJvamVjdCBhbmFseXNlcyBtb250aGx5IEdvb2dsZSBzZWFyY2ggaW50ZXJlc3QgZm9yIEJpdGNvaW4gYXMgYSB0aW1lIHNlcmllcy4gVGhlIGFpbSBpcyB0byBpbnZlc3RpZ2F0ZSB3aGV0aGVyIHB1YmxpYyBpbnRlcmVzdCBpbiBCaXRjb2luIGNvbnRhaW5zIGVub3VnaCBzdHJ1Y3R1cmUgdG8gc3VwcG9ydCBzaG9ydC10ZXJtIGZvcmVjYXN0aW5nLgoKQml0Y29pbiBzZWFyY2ggaW50ZXJlc3QgaXMgbm90IGxpa2VseSB0byBiZWhhdmUgbGlrZSBhIHN0YWJsZSBlY29ub21pYyBvciBkZW1vZ3JhcGhpYyBzZXJpZXMuIFB1YmxpYyBhdHRlbnRpb24gY2FuIGNoYW5nZSBxdWlja2x5IHdoZW4gQml0Y29pbiBhcHBlYXJzIGluIHRoZSBuZXdzLCB3aGVuIHByaWNlcyByaXNlIG9yIGZhbGwgc2hhcnBseSwgb3Igd2hlbiBjcnlwdG9jdXJyZW5jeSBiZWNvbWVzIHBhcnQgb2Ygd2lkZXIgbWFya2V0IGRpc2N1c3Npb24uIEJlY2F1c2Ugb2YgdGhpcywgdGhlIHByb2plY3QgaXMgbm90IG9ubHkgYWJvdXQgcHJvZHVjaW5nIGEgZm9yZWNhc3QsIGJ1dCBhbHNvIGFib3V0IHRlc3RpbmcgaG93IHJlbGlhYmxlIHRoYXQgZm9yZWNhc3QgaXMuCgpUaGUgYW5hbHlzaXMgdXNlcyBkZWNvbXBvc2l0aW9uLCBzdGF0aW9uYXJpdHkgdGVzdGluZywgYmVuY2htYXJrIG1vZGVscywgRVRTIG1vZGVscyBhbmQgU0FSSU1BIG1vZGVscy4gTW9kZWxzIGFyZSBjb21wYXJlZCB1c2luZyBhIHRyYWluLXRlc3Qgc3BsaXQsIHNvIHRoZSBmaW5hbCBqdWRnZW1lbnQgaXMgYmFzZWQgb24gcGVyZm9ybWFuY2Ugb24gdW5zZWVuIGRhdGEgcmF0aGVyIHRoYW4gdmlzdWFsIGZpdC4KCjxkaXYgY2xhc3M9InRha2Vhd2F5Ij4KPHN0cm9uZz5Qcm9qZWN0IGZvY3VzOjwvc3Ryb25nPiBUaGUgbWFpbiBxdWVzdGlvbiBpcyB3aGV0aGVyIEJpdGNvaW4gc2VhcmNoIGludGVyZXN0IGJlaGF2ZXMgbGlrZSBhIGZvcmVjYXN0YWJsZSB0aW1lIHNlcmllcywgb3Igd2hldGhlciBpdCBpcyB0b28gZXZlbnQtZHJpdmVuIGZvciBjbGFzc2ljYWwgbW9kZWxzIHRvIHByZWRpY3QgcmVsaWFibHkuCjwvZGl2PgoKIyAyLiBEYXRhCgpUaGUgZGF0YXNldCBjb250YWlucyBtb250aGx5IEJpdGNvaW4gc2VhcmNoIGludGVyZXN0IHZhbHVlcy4gVGhlIHZhbHVlcyBhcmUgcmVsYXRpdmUgR29vZ2xlIFRyZW5kcyBzY29yZXMsIHNvIHRoZXkgZG8gbm90IHJlcHJlc2VudCBleGFjdCBzZWFyY2ggdm9sdW1lcy4gQSBoaWdoZXIgdmFsdWUgbWVhbnMgQml0Y29pbiBoYWQgaGlnaGVyIHNlYXJjaCBpbnRlcmVzdCBkdXJpbmcgdGhhdCBtb250aC4KCjxkaXYgY2xhc3M9ImNvZGUtbGFiZWwiPkNvZGU6IGxvYWQgdGhlIEJpdGNvaW4gc2VhcmNoIGludGVyZXN0IGRhdGFzZXQ8L2Rpdj4KCmBgYHtyIGRhdGEtbG9hZGluZywgcmVzdWx0cz0naGlkZSd9CmJpdGNvaW5fcmF3IDwtIHJlYWQuY3N2KCJCaXRjb2luVGltZVNlcmllcy5jc3YiKQpgYGAKClRoZSBvcmlnaW5hbCBjb2x1bW5zIGFyZSByZW5hbWVkIHRvIG1ha2UgdGhlIGFuYWx5c2lzIGVhc2llciB0byByZWFkLiBUaGUgZGF0ZSBjb2x1bW4gaXMgYWxzbyBjb252ZXJ0ZWQgaW50byBhIHByb3BlciBkYXRlIGZvcm1hdCBzbyB0aGF0IFIgY2FuIHRyZWF0IGl0IGFzIGEgbW9udGhseSB0aW1lIHNlcmllcy4KCjxkaXYgY2xhc3M9ImNvZGUtbGFiZWwiPkNvZGU6IGNsZWFuIHRoZSBkYXRlIGNvbHVtbiBhbmQgcHJlcGFyZSB0aGUgc2VhcmNoIGludGVyZXN0IHNlcmllczwvZGl2PgoKYGBge3IgZGF0YS1jbGVhbmluZywgcmVzdWx0cz0naGlkZSd9CmJpdGNvaW4gPC0gYml0Y29pbl9yYXcgJT4lCiAgcmVuYW1lKAogICAgZGF0ZSA9IFRpbWUsCiAgICB2YWx1ZSA9IEJpdGNvaW4KICApCgpiaXRjb2luJGRhdGUgPC0gYXMuRGF0ZShiaXRjb2luJGRhdGUsIGZvcm1hdCA9ICIlZC8lbS8lWSIpCgpiaXRjb2luIDwtIGJpdGNvaW4gJT4lCiAgZmlsdGVyKCFpcy5uYShkYXRlKSwgIWlzLm5hKHZhbHVlKSkgJT4lCiAgYXJyYW5nZShkYXRlKQoKc3RhcnRfZGF0ZSA8LSBtaW4oYml0Y29pbiRkYXRlKQplbmRfZGF0ZSA8LSBtYXgoYml0Y29pbiRkYXRlKQpuX29icyA8LSBucm93KGJpdGNvaW4pCm1pbl92YWx1ZSA8LSBtaW4oYml0Y29pbiR2YWx1ZSkKbWF4X3ZhbHVlIDwtIG1heChiaXRjb2luJHZhbHVlKQpgYGAKCkFmdGVyIGNsZWFuaW5nLCB0aGUgZGF0YXNldCBydW5zIGZyb20gYHIgc3RhcnRfZGF0ZWAgdG8gYHIgZW5kX2RhdGVgLCB3aXRoIGByIG5fb2JzYCBtb250aGx5IG9ic2VydmF0aW9ucy4gU2VhcmNoIGludGVyZXN0IHJhbmdlcyBmcm9tIGByIG1pbl92YWx1ZWAgdG8gYHIgbWF4X3ZhbHVlYC4KClRoZSBkYXRhIGlzIG1vbnRobHksIHNvIGl0IGlzIGNvbnZlcnRlZCBpbnRvIGEgdGltZSBzZXJpZXMgb2JqZWN0IHdpdGggZnJlcXVlbmN5IDEyLiBUaGlzIHRlbGxzIFIgdGhhdCB0aGUgZGF0YSBoYXMgMTIgb2JzZXJ2YXRpb25zIHBlciB5ZWFyLgoKPGRpdiBjbGFzcz0iY29kZS1sYWJlbCI+Q29kZTogY29udmVydCB0aGUgY2xlYW5lZCBkYXRhIGludG8gYSBtb250aGx5IHRpbWUgc2VyaWVzIG9iamVjdDwvZGl2PgoKYGBge3IgdGltZS1zZXJpZXMtb2JqZWN0LCByZXN1bHRzPSdoaWRlJ30KYnRjX3RzIDwtIHRzKAogIGJpdGNvaW4kdmFsdWUsCiAgZnJlcXVlbmN5ID0gMTIsCiAgc3RhcnQgPSBjKHllYXIobWluKGJpdGNvaW4kZGF0ZSkpLCBtb250aChtaW4oYml0Y29pbiRkYXRlKSkpCikKCnRzX2ZyZXF1ZW5jeSA8LSBmcmVxdWVuY3koYnRjX3RzKQp0c19vYnNlcnZhdGlvbnMgPC0gbGVuZ3RoKGJ0Y190cykKdHNfc3RhcnQgPC0gcGFzdGUoc3RhcnQoYnRjX3RzKSwgY29sbGFwc2UgPSAiLSIpCnRzX2VuZCA8LSBwYXN0ZShlbmQoYnRjX3RzKSwgY29sbGFwc2UgPSAiLSIpCmBgYAoKYGBge3IgdGltZS1zZXJpZXMtY2FyZHMsIGVjaG89RkFMU0UsIHJlc3VsdHM9J2FzaXMnfQpIVE1MKHBhc3RlMCgKICAnPGRpdiBjbGFzcz0ibWV0cmljLWdyaWQiPicsCiAgICAnPGRpdiBjbGFzcz0ibWV0cmljLWNhcmQiPicsCiAgICAgICc8ZGl2IGNsYXNzPSJtZXRyaWMtbGFiZWwiPkZyZXF1ZW5jeTwvZGl2PicsCiAgICAgICc8ZGl2IGNsYXNzPSJtZXRyaWMtdmFsdWUiPicsIHRzX2ZyZXF1ZW5jeSwgJzwvZGl2PicsCiAgICAnPC9kaXY+JywKICAgICc8ZGl2IGNsYXNzPSJtZXRyaWMtY2FyZCI+JywKICAgICAgJzxkaXYgY2xhc3M9Im1ldHJpYy1sYWJlbCI+T2JzZXJ2YXRpb25zPC9kaXY+JywKICAgICAgJzxkaXYgY2xhc3M9Im1ldHJpYy12YWx1ZSI+JywgdHNfb2JzZXJ2YXRpb25zLCAnPC9kaXY+JywKICAgICc8L2Rpdj4nLAogICAgJzxkaXYgY2xhc3M9Im1ldHJpYy1jYXJkIj4nLAogICAgICAnPGRpdiBjbGFzcz0ibWV0cmljLWxhYmVsIj5TdGFydDwvZGl2PicsCiAgICAgICc8ZGl2IGNsYXNzPSJtZXRyaWMtdmFsdWUiPicsIHRzX3N0YXJ0LCAnPC9kaXY+JywKICAgICc8L2Rpdj4nLAogICAgJzxkaXYgY2xhc3M9Im1ldHJpYy1jYXJkIj4nLAogICAgICAnPGRpdiBjbGFzcz0ibWV0cmljLWxhYmVsIj5FbmQ8L2Rpdj4nLAogICAgICAnPGRpdiBjbGFzcz0ibWV0cmljLXZhbHVlIj4nLCB0c19lbmQsICc8L2Rpdj4nLAogICAgJzwvZGl2PicsCiAgJzwvZGl2PicKKSkKYGBgCgojIDMuIEV4cGxvcmF0b3J5IGFuYWx5c2lzCgpUaGUgZmlyc3Qgc3RlcCBpcyB0byBpbnNwZWN0IHRoZSBvdmVyYWxsIHNoYXBlIG9mIHRoZSBzZXJpZXMuCgo8ZGl2IGNsYXNzPSJjb2RlLWxhYmVsIj5Db2RlOiBwbG90IG1vbnRobHkgQml0Y29pbiBzZWFyY2ggaW50ZXJlc3Qgb3ZlciB0aW1lPC9kaXY+CgpgYGB7ciBleHBsb3JhdG9yeS1wbG90fQpnZ3Bsb3QoYml0Y29pbiwgYWVzKHggPSBkYXRlLCB5ID0gdmFsdWUpKSArCiAgZ2VvbV9saW5lKGxpbmV3aWR0aCA9IDAuOCwgY29sb3VyID0gIiMxZDM1NTciKSArCiAgbGFicygKICAgIHRpdGxlID0gIkJpdGNvaW4gc2VhcmNoIGludGVyZXN0IG92ZXIgdGltZSIsCiAgICBzdWJ0aXRsZSA9ICJNb250aGx5IHJlbGF0aXZlIEdvb2dsZSBUcmVuZHMgc2NvcmUiLAogICAgeCA9ICJEYXRlIiwKICAgIHkgPSAiU2VhcmNoIGludGVyZXN0IgogICkgKwogIHBsb3RfdGhlbWUgKwogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gNDUsIGhqdXN0ID0gMSkpCmBgYAoKVGhlIHBsb3Qgc2hvd3MgdGhhdCBzZWFyY2ggaW50ZXJlc3QgaXMgbm90IHN0YWJsZSBvdmVyIHRpbWUuIFRoZXJlIGFyZSBzZXZlcmFsIHNoYXJwIHNwaWtlcywgd2hpY2ggaXMgZXhwZWN0ZWQgZm9yIEJpdGNvaW4gYmVjYXVzZSBwdWJsaWMgYXR0ZW50aW9uIG9mdGVuIGluY3JlYXNlcyBzdWRkZW5seSBhcm91bmQgcHJpY2UgbW92ZW1lbnRzLCBuZXdzIGV2ZW50cyBvciB3aWRlciBtYXJrZXQgZGlzY3Vzc2lvbi4KCjxkaXYgY2xhc3M9ImNvZGUtbGFiZWwiPkNvZGU6IGNhbGN1bGF0ZSBzdW1tYXJ5IHN0YXRpc3RpY3MgZm9yIHRoZSBzZWFyY2ggaW50ZXJlc3Qgc2VyaWVzPC9kaXY+CgpgYGB7ciBzdW1tYXJ5LXN0YXRpc3RpY3MsIHJlc3VsdHM9J2hpZGUnfQpzdW1tYXJ5X3N0YXRzIDwtIGJpdGNvaW4gJT4lCiAgc3VtbWFyaXNlKAogICAgb2JzZXJ2YXRpb25zID0gbigpLAogICAgbWVhbl92YWx1ZSA9IHJvdW5kKG1lYW4odmFsdWUpLCAyKSwKICAgIG1lZGlhbl92YWx1ZSA9IHJvdW5kKG1lZGlhbih2YWx1ZSksIDIpLAogICAgc2RfdmFsdWUgPSByb3VuZChzZCh2YWx1ZSksIDIpLAogICAgbWluaW11bV92YWx1ZSA9IG1pbih2YWx1ZSksCiAgICBtYXhpbXVtX3ZhbHVlID0gbWF4KHZhbHVlKQogICkKCm9ic192YWx1ZSA8LSBzdW1tYXJ5X3N0YXRzJG9ic2VydmF0aW9ucwptZWFuX3ZhbHVlIDwtIHN1bW1hcnlfc3RhdHMkbWVhbl92YWx1ZQptZWRpYW5fdmFsdWUgPC0gc3VtbWFyeV9zdGF0cyRtZWRpYW5fdmFsdWUKc2RfdmFsdWUgPC0gc3VtbWFyeV9zdGF0cyRzZF92YWx1ZQptaW5pbXVtX3ZhbHVlIDwtIHN1bW1hcnlfc3RhdHMkbWluaW11bV92YWx1ZQptYXhpbXVtX3ZhbHVlIDwtIHN1bW1hcnlfc3RhdHMkbWF4aW11bV92YWx1ZQpgYGAKCmBgYHtyIHN1bW1hcnktc3RhdGlzdGljcy1jYXJkcywgZWNobz1GQUxTRSwgcmVzdWx0cz0nYXNpcyd9CkhUTUwocGFzdGUwKAogICc8ZGl2IGNsYXNzPSJtZXRyaWMtZ3JpZCI+JywKICAgICc8ZGl2IGNsYXNzPSJtZXRyaWMtY2FyZCI+JywKICAgICAgJzxkaXYgY2xhc3M9Im1ldHJpYy1sYWJlbCI+T2JzZXJ2YXRpb25zPC9kaXY+JywKICAgICAgJzxkaXYgY2xhc3M9Im1ldHJpYy12YWx1ZSI+Jywgb2JzX3ZhbHVlLCAnPC9kaXY+JywKICAgICc8L2Rpdj4nLAogICAgJzxkaXYgY2xhc3M9Im1ldHJpYy1jYXJkIj4nLAogICAgICAnPGRpdiBjbGFzcz0ibWV0cmljLWxhYmVsIj5NZWFuPC9kaXY+JywKICAgICAgJzxkaXYgY2xhc3M9Im1ldHJpYy12YWx1ZSI+JywgbWVhbl92YWx1ZSwgJzwvZGl2PicsCiAgICAnPC9kaXY+JywKICAgICc8ZGl2IGNsYXNzPSJtZXRyaWMtY2FyZCI+JywKICAgICAgJzxkaXYgY2xhc3M9Im1ldHJpYy1sYWJlbCI+TWVkaWFuPC9kaXY+JywKICAgICAgJzxkaXYgY2xhc3M9Im1ldHJpYy12YWx1ZSI+JywgbWVkaWFuX3ZhbHVlLCAnPC9kaXY+JywKICAgICc8L2Rpdj4nLAogICAgJzxkaXYgY2xhc3M9Im1ldHJpYy1jYXJkIj4nLAogICAgICAnPGRpdiBjbGFzcz0ibWV0cmljLWxhYmVsIj5TdGFuZGFyZCBkZXZpYXRpb248L2Rpdj4nLAogICAgICAnPGRpdiBjbGFzcz0ibWV0cmljLXZhbHVlIj4nLCBzZF92YWx1ZSwgJzwvZGl2PicsCiAgICAnPC9kaXY+JywKICAgICc8ZGl2IGNsYXNzPSJtZXRyaWMtY2FyZCI+JywKICAgICAgJzxkaXYgY2xhc3M9Im1ldHJpYy1sYWJlbCI+TWluaW11bTwvZGl2PicsCiAgICAgICc8ZGl2IGNsYXNzPSJtZXRyaWMtdmFsdWUiPicsIG1pbmltdW1fdmFsdWUsICc8L2Rpdj4nLAogICAgJzwvZGl2PicsCiAgICAnPGRpdiBjbGFzcz0ibWV0cmljLWNhcmQiPicsCiAgICAgICc8ZGl2IGNsYXNzPSJtZXRyaWMtbGFiZWwiPk1heGltdW08L2Rpdj4nLAogICAgICAnPGRpdiBjbGFzcz0ibWV0cmljLXZhbHVlIj4nLCBtYXhpbXVtX3ZhbHVlLCAnPC9kaXY+JywKICAgICc8L2Rpdj4nLAogICc8L2Rpdj4nCikpCmBgYAoKVGhlIGdhcCBiZXR3ZWVuIHRoZSBtZWRpYW4gYW5kIHRoZSBtYXhpbXVtIHN1Z2dlc3RzIHRoYXQgdGhlIHNlcmllcyBpcyBub3QgZXZlbmx5IHNwcmVhZCBhcm91bmQgYSB0eXBpY2FsIGxldmVsLiBJbnN0ZWFkLCB0aGVyZSBhcmUgb2NjYXNpb25hbCBwZXJpb2RzIHdoZXJlIHNlYXJjaCBpbnRlcmVzdCBiZWNvbWVzIG11Y2ggaGlnaGVyIHRoYW4gdXN1YWwuCgo8ZGl2IGNsYXNzPSJ0YWtlYXdheSI+CjxzdHJvbmc+SW5pdGlhbCBvYnNlcnZhdGlvbjo8L3N0cm9uZz4gQml0Y29pbiBzZWFyY2ggaW50ZXJlc3QgYXBwZWFycyB2b2xhdGlsZSBhbmQgc3Bpa2UtZHJpdmVuLiBBIG1vZGVsIHRoYXQgYXNzdW1lcyBhIHNtb290aCBzdGFibGUgcGF0dGVybiBpcyB1bmxpa2VseSB0byBiZSBlbm91Z2ggYnkgaXRzZWxmLgo8L2Rpdj4KCiMgNC4gRGVjb21wb3NpdGlvbgoKU1RMIGRlY29tcG9zaXRpb24gc2VwYXJhdGVzIHRoZSBzZXJpZXMgaW50byB0cmVuZCwgc2Vhc29uYWwgYW5kIHJlbWFpbmRlciBjb21wb25lbnRzLiBUaGlzIGhlbHBzIHNob3cgd2hldGhlciB0aGUgbW92ZW1lbnQgaW4gdGhlIHNlcmllcyBpcyBtYWlubHkgbG9uZy10ZXJtIHRyZW5kLCByZXBlYXRlZCBzZWFzb25hbGl0eSBvciBpcnJlZ3VsYXIgc2hvY2tzLgoKPGRpdiBjbGFzcz0iY29kZS1sYWJlbCI+Q29kZTogZGVjb21wb3NlIHRoZSBzZXJpZXMgaW50byB0cmVuZCwgc2Vhc29uYWxpdHkgYW5kIHJlbWFpbmRlcjwvZGl2PgoKYGBge3IgZGVjb21wb3NpdGlvbiwgZmlnLmhlaWdodD03fQpkZWNvbXAgPC0gc3RsKGJ0Y190cywgcy53aW5kb3cgPSAicGVyaW9kaWMiKQpwbG90KGRlY29tcCkKYGBgCgpUaGUgdHJlbmQgY29tcG9uZW50IHNob3dzIGxvbmdlci10ZXJtIG1vdmVtZW50IGluIEJpdGNvaW4gaW50ZXJlc3QuIFRoZSBzZWFzb25hbCBjb21wb25lbnQgc2hvd3MgcmVwZWF0ZWQgbW9udGhseSBlZmZlY3RzLiBUaGUgcmVtYWluZGVyIHNob3dzIGlycmVndWxhciBtb3ZlbWVudHMgdGhhdCBhcmUgbm90IGV4cGxhaW5lZCBieSB0aGUgdHJlbmQgb3Igc2Vhc29uYWxpdHkuCgpGb3IgdGhpcyBkYXRhc2V0LCB0aGUgcmVtYWluZGVyIGlzIGltcG9ydGFudCBiZWNhdXNlIEJpdGNvaW4gc2VhcmNoIGludGVyZXN0IGlzIHN0cm9uZ2x5IGFmZmVjdGVkIGJ5IGV2ZW50cy4gVGhpcyBtZWFucyB0aGF0IGV2ZW4gaWYgdGhlcmUgaXMgc29tZSB0cmVuZCBvciBzZWFzb25hbGl0eSwgc3VkZGVuIHNob2NrcyBjYW4gc3RpbGwgZG9taW5hdGUgdGhlIHNlcmllcy4KCjxkaXYgY2xhc3M9Im1ldGhvZCI+CjxzdHJvbmc+TWV0aG9kIG5vdGU6PC9zdHJvbmc+IERlY29tcG9zaXRpb24gaXMgbm90IGEgZm9yZWNhc3RpbmcgbW9kZWwgYnkgaXRzZWxmLiBJdCBpcyB1c2VkIHRvIHVuZGVyc3RhbmQgdGhlIHN0cnVjdHVyZSBvZiB0aGUgc2VyaWVzIGJlZm9yZSBmaXR0aW5nIG1vZGVscy4KPC9kaXY+CgojIDUuIFN0YXRpb25hcml0eQoKQVJJTUEtdHlwZSBtb2RlbHMgdXN1YWxseSB3b3JrIGJldHRlciB3aGVuIHRoZSBzZXJpZXMgaXMgc3RhdGlvbmFyeS4gQSBzdGF0aW9uYXJ5IHNlcmllcyBoYXMgc3RhdGlzdGljYWwgcHJvcGVydGllcyB0aGF0IGFyZSByZWFzb25hYmx5IHN0YWJsZSBvdmVyIHRpbWUuIFRoZSBvcmlnaW5hbCBwbG90IHN1Z2dlc3RzIHRoYXQgQml0Y29pbiBzZWFyY2ggaW50ZXJlc3QgbWF5IG5vdCBiZSBzdGF0aW9uYXJ5LCBzbyB0aGUgQXVnbWVudGVkIERpY2tleS1GdWxsZXIgdGVzdCBpcyB1c2VkLgoKPGRpdiBjbGFzcz0iY29kZS1sYWJlbCI+Q29kZTogcnVuIEFERiBzdGF0aW9uYXJpdHkgdGVzdHMgYmVmb3JlIGFuZCBhZnRlciBkaWZmZXJlbmNpbmc8L2Rpdj4KCjxkaXYgY2xhc3M9ImNsZWFuLXRhYmxlIj4KCmBgYHtyIGFkZi10ZXN0c30KYWRmX29yaWdpbmFsIDwtIGFkZi50ZXN0KGJ0Y190cykKCmRpZmZfYnRjIDwtIGRpZmYoYnRjX3RzKQphZGZfZGlmZmVyZW5jZWQgPC0gYWRmLnRlc3QoZGlmZl9idGMpCgphZGZfdGFibGUgPC0gZGF0YS5mcmFtZSgKICBTZXJpZXMgPSBjKCJPcmlnaW5hbCBzZXJpZXMiLCAiRGlmZmVyZW5jZWQgc2VyaWVzIiksCiAgYEFERiBzdGF0aXN0aWNgID0gYygKICAgIHJvdW5kKGFzLm51bWVyaWMoYWRmX29yaWdpbmFsJHN0YXRpc3RpYyksIDQpLAogICAgcm91bmQoYXMubnVtZXJpYyhhZGZfZGlmZmVyZW5jZWQkc3RhdGlzdGljKSwgNCkKICApLAogIGBwLXZhbHVlYCA9IGMoCiAgICByb3VuZChhZGZfb3JpZ2luYWwkcC52YWx1ZSwgNCksCiAgICByb3VuZChhZGZfZGlmZmVyZW5jZWQkcC52YWx1ZSwgNCkKICApCikKCmthYmxlKGFkZl90YWJsZSwgY2FwdGlvbiA9ICJBREYgc3RhdGlvbmFyaXR5IHRlc3RzIikKYGBgCgo8L2Rpdj4KCkEgbG93ZXIgcC12YWx1ZSBnaXZlcyBzdHJvbmdlciBldmlkZW5jZSBhZ2FpbnN0IGEgdW5pdCByb290LiBUaGUgZGlmZmVyZW5jZWQgc2VyaWVzIGlzIGluY2x1ZGVkIGJlY2F1c2UgZGlmZmVyZW5jaW5nIGlzIGEgY29tbW9uIHdheSB0byByZWR1Y2UgY2hhbmdlcyBpbiBsZXZlbCBhbmQgbWFrZSBhIHNlcmllcyBtb3JlIHN1aXRhYmxlIGZvciBBUklNQSBtb2RlbGxpbmcuCgo8ZGl2IGNsYXNzPSJjb2RlLWxhYmVsIj5Db2RlOiBwbG90IHRoZSBkaWZmZXJlbmNlZCBzZXJpZXM8L2Rpdj4KCmBgYHtyIGRpZmZlcmVuY2VkLXBsb3R9CmF1dG9wbG90KGRpZmZfYnRjKSArCiAgbGFicygKICAgIHRpdGxlID0gIkRpZmZlcmVuY2VkIEJpdGNvaW4gc2VhcmNoIGludGVyZXN0IiwKICAgIHggPSAiVGltZSIsCiAgICB5ID0gIkNoYW5nZSBpbiBzZWFyY2ggaW50ZXJlc3QiCiAgKSArCiAgcGxvdF90aGVtZQpgYGAKCjxkaXYgY2xhc3M9Im1ldGhvZCI+CjxzdHJvbmc+TW9kZWxsaW5nIHBvaW50Ojwvc3Ryb25nPiBEaWZmZXJlbmNpbmcgY2hhbmdlcyB0aGUgcHJvYmxlbSBzbGlnaHRseS4gSW5zdGVhZCBvZiBvbmx5IG1vZGVsbGluZyB0aGUgbGV2ZWwgb2Ygc2VhcmNoIGludGVyZXN0LCB0aGUgbW9kZWwgYWxzbyBmb2N1c2VzIG9uIGhvdyBzZWFyY2ggaW50ZXJlc3QgY2hhbmdlcyBmcm9tIG9uZSBtb250aCB0byB0aGUgbmV4dC4KPC9kaXY+CgojIDYuIEF1dG9jb3JyZWxhdGlvbgoKVGhlIEFDRiBhbmQgUEFDRiBwbG90cyBoZWxwIGFzc2VzcyB3aGV0aGVyIHBhc3QgdmFsdWVzIGFyZSByZWxhdGVkIHRvIGN1cnJlbnQgdmFsdWVzLiBUaGlzIG1hdHRlcnMgYmVjYXVzZSB0aW1lIHNlcmllcyBtb2RlbHMgcmVseSBvbiB0aGUgaWRlYSB0aGF0IHRoZSBwYXN0IGNvbnRhaW5zIGluZm9ybWF0aW9uIGFib3V0IHRoZSBmdXR1cmUuCgo8ZGl2IGNsYXNzPSJjb2RlLWxhYmVsIj5Db2RlOiBwbG90IEFDRiBhbmQgUEFDRiBmb3IgdGhlIGRpZmZlcmVuY2VkIHNlcmllczwvZGl2PgoKYGBge3IgYWNmLXBhY2Z9CmFjZihkaWZmX2J0YywgbWFpbiA9ICJBQ0Ygb2YgZGlmZmVyZW5jZWQgc2VyaWVzIikKcGFjZihkaWZmX2J0YywgbWFpbiA9ICJQQUNGIG9mIGRpZmZlcmVuY2VkIHNlcmllcyIpCmBgYAoKVGhlIEFDRiBzaG93cyBjb3JyZWxhdGlvbiB3aXRoIHByZXZpb3VzIGxhZ3MsIHdoaWxlIHRoZSBQQUNGIHNob3dzIHRoZSBjb3JyZWxhdGlvbiBhdCBlYWNoIGxhZyBhZnRlciBhY2NvdW50aW5nIGZvciBzaG9ydGVyIGxhZ3MuIFRoZXNlIHBsb3RzIGFyZSBub3QgdXNlZCB0byBtYW51YWxseSBjaG9vc2UgdGhlIGZpbmFsIG1vZGVsLCBidXQgdGhleSBhcmUgdXNlZnVsIGFzIGEgY2hlY2sgYmVmb3JlIHVzaW5nIGF1dG9tYXRpYyBBUklNQSBzZWxlY3Rpb24uCgojIDcuIFRyYWluLXRlc3Qgc3BsaXQKClRvIGF2b2lkIGp1ZGdpbmcgbW9kZWxzIG9ubHkgb24gaG93IHdlbGwgdGhleSBmaXQgdGhlIHBhc3QsIHRoZSBmaW5hbCAxMiBvYnNlcnZhdGlvbnMgYXJlIGhlbGQgYmFjayBhcyBhIHRlc3Qgc2V0LgoKPGRpdiBjbGFzcz0iY29kZS1sYWJlbCI+Q29kZTogc3BsaXQgdGhlIHNlcmllcyBpbnRvIHRyYWluaW5nIGFuZCB0ZXN0IHNldHM8L2Rpdj4KCmBgYHtyIHRyYWluLXRlc3Qtc3BsaXQsIHJlc3VsdHM9J2hpZGUnfQpuIDwtIGxlbmd0aChidGNfdHMpCgp0cmFpbiA8LSB3aW5kb3coYnRjX3RzLCBlbmQgPSB0aW1lKGJ0Y190cylbbiAtIDEyXSkKdGVzdCA8LSB3aW5kb3coYnRjX3RzLCBzdGFydCA9IHRpbWUoYnRjX3RzKVtuIC0gMTFdKQoKdHJhaW5fb2JzIDwtIGxlbmd0aCh0cmFpbikKdGVzdF9vYnMgPC0gbGVuZ3RoKHRlc3QpCmBgYAoKYGBge3IgdHJhaW4tdGVzdC1jYXJkcywgZWNobz1GQUxTRSwgcmVzdWx0cz0nYXNpcyd9CkhUTUwocGFzdGUwKAogICc8ZGl2IGNsYXNzPSJtZXRyaWMtZ3JpZCI+JywKICAgICc8ZGl2IGNsYXNzPSJtZXRyaWMtY2FyZCI+JywKICAgICAgJzxkaXYgY2xhc3M9Im1ldHJpYy1sYWJlbCI+VHJhaW5pbmcgc2V0PC9kaXY+JywKICAgICAgJzxkaXYgY2xhc3M9Im1ldHJpYy12YWx1ZSI+JywgdHJhaW5fb2JzLCAnPC9kaXY+JywKICAgICc8L2Rpdj4nLAogICAgJzxkaXYgY2xhc3M9Im1ldHJpYy1jYXJkIj4nLAogICAgICAnPGRpdiBjbGFzcz0ibWV0cmljLWxhYmVsIj5UZXN0IHNldDwvZGl2PicsCiAgICAgICc8ZGl2IGNsYXNzPSJtZXRyaWMtdmFsdWUiPicsIHRlc3Rfb2JzLCAnPC9kaXY+JywKICAgICc8L2Rpdj4nLAogICc8L2Rpdj4nCikpCmBgYAoKPGRpdiBjbGFzcz0ibWV0aG9kIj4KPHN0cm9uZz5XaHkgdGhpcyBtYXR0ZXJzOjwvc3Ryb25nPiBBIHRyYWluLXRlc3Qgc3BsaXQgZ2l2ZXMgYSBtb3JlIGhvbmVzdCBjb21wYXJpc29uLiBBIG1vZGVsIGNhbiBmaXQgaGlzdG9yaWNhbCBkYXRhIHdlbGwgYnV0IHN0aWxsIHBlcmZvcm0gYmFkbHkgb24gZnV0dXJlIG9ic2VydmF0aW9ucy4KPC9kaXY+CgojIDguIEJlbmNobWFyayBtb2RlbHMKCkJlZm9yZSBmaXR0aW5nIEVUUyBhbmQgU0FSSU1BIG1vZGVscywgc2ltcGxlIGJlbmNobWFyayBtb2RlbHMgYXJlIHVzZWQuIFRoZXNlIGFyZSBpbXBvcnRhbnQgYmVjYXVzZSBhIG1vcmUgY29tcGxpY2F0ZWQgbW9kZWwgaXMgbm90IGF1dG9tYXRpY2FsbHkgYmV0dGVyLiBJdCBzaG91bGQgaW1wcm92ZSBvbiBzaW1wbGUgYWx0ZXJuYXRpdmVzLgoKVGhlIG1lYW4gZm9yZWNhc3QgaXMgYSBzaW1wbGUgbG9uZy10ZXJtIGF2ZXJhZ2UuIFRoZSBuYWl2ZSBmb3JlY2FzdCBhc3N1bWVzIHRoZSBsYXRlc3Qgb2JzZXJ2YXRpb24gaXMgdGhlIGJlc3QgZ3VpZGUgdG8gdGhlIG5lYXIgZnV0dXJlLiBUaGUgc2Vhc29uYWwgbmFpdmUgZm9yZWNhc3QgdGVzdHMgd2hldGhlciB0aGUgc2FtZSBtb250aCBpbiB0aGUgcHJldmlvdXMgeWVhciBpcyB1c2VmdWwgZm9yIHByZWRpY3Rpb24uCgo8ZGl2IGNsYXNzPSJjb2RlLWxhYmVsIj5Db2RlOiBmaXQgbWVhbiwgbmFpdmUgYW5kIHNlYXNvbmFsIG5haXZlIGJlbmNobWFyayBmb3JlY2FzdHM8L2Rpdj4KCjxkaXYgY2xhc3M9ImNsZWFuLXRhYmxlIj4KCmBgYHtyIGJlbmNobWFyay1tb2RlbHN9Cm1lYW5fZml0IDwtIG1lYW5mKHRyYWluLCBoID0gbGVuZ3RoKHRlc3QpKQpuYWl2ZV9maXQgPC0gbmFpdmUodHJhaW4sIGggPSBsZW5ndGgodGVzdCkpCnNuYWl2ZV9maXQgPC0gc25haXZlKHRyYWluLCBoID0gbGVuZ3RoKHRlc3QpKQoKYmVuY2htYXJrX3RhYmxlIDwtIGRhdGEuZnJhbWUoCiAgTW9kZWwgPSBjKCJNZWFuIGZvcmVjYXN0IiwgIk5haXZlIGZvcmVjYXN0IiwgIlNlYXNvbmFsIG5haXZlIGZvcmVjYXN0IiksCiAgSWRlYSA9IGMoCiAgICAiRnV0dXJlIHZhbHVlcyBhcmUgZm9yZWNhc3QgdXNpbmcgdGhlIHRyYWluaW5nLXNldCBhdmVyYWdlLiIsCiAgICAiRnV0dXJlIHZhbHVlcyBhcmUgZm9yZWNhc3QgdXNpbmcgdGhlIG1vc3QgcmVjZW50IG9ic2VydmF0aW9uLiIsCiAgICAiRnV0dXJlIHZhbHVlcyByZXBlYXQgdGhlIHZhbHVlIGZyb20gdGhlIHNhbWUgbW9udGggaW4gdGhlIHByZXZpb3VzIHllYXIuIgogICkKKQoKa2FibGUoYmVuY2htYXJrX3RhYmxlLCBjYXB0aW9uID0gIkJlbmNobWFyayBtb2RlbHMiKQpgYGAKCjwvZGl2PgoKPGRpdiBjbGFzcz0iY29kZS1sYWJlbCI+Q29kZTogcGxvdCBiZW5jaG1hcmsgZm9yZWNhc3RzIG92ZXIgdGhlIHRlc3QgaG9yaXpvbjwvZGl2PgoKYGBge3IgYmVuY2htYXJrLXBsb3RzfQphdXRvcGxvdChtZWFuX2ZpdCkgKwogIGxhYnModGl0bGUgPSAiTWVhbiBmb3JlY2FzdCIsIHggPSAiVGltZSIsIHkgPSAiU2VhcmNoIGludGVyZXN0IikgKwogIHBsb3RfdGhlbWUKCmF1dG9wbG90KG5haXZlX2ZpdCkgKwogIGxhYnModGl0bGUgPSAiTmFpdmUgZm9yZWNhc3QiLCB4ID0gIlRpbWUiLCB5ID0gIlNlYXJjaCBpbnRlcmVzdCIpICsKICBwbG90X3RoZW1lCgphdXRvcGxvdChzbmFpdmVfZml0KSArCiAgbGFicyh0aXRsZSA9ICJTZWFzb25hbCBuYWl2ZSBmb3JlY2FzdCIsIHggPSAiVGltZSIsIHkgPSAiU2VhcmNoIGludGVyZXN0IikgKwogIHBsb3RfdGhlbWUKYGBgCgo8ZGl2IGNsYXNzPSJ0YWtlYXdheSI+CjxzdHJvbmc+QmVuY2htYXJrIHB1cnBvc2U6PC9zdHJvbmc+IElmIEVUUyBvciBTQVJJTUEgY2Fubm90IGJlYXQgdGhlc2Ugc2ltcGxlIG1vZGVscyBvbiB1bnNlZW4gZGF0YSwgdGhlbiB0aGUgZXh0cmEgY29tcGxleGl0eSBpcyBub3QgYWRkaW5nIG11Y2ggdmFsdWUuCjwvZGl2PgoKIyA5LiBFVFMgbW9kZWwKCjxkaXYgY2xhc3M9Im1vZGVsLWJveCI+CjxzdHJvbmc+RVRTIG1vZGVsOjwvc3Ryb25nPiBFVFMgc3RhbmRzIGZvciBFcnJvciwgVHJlbmQgYW5kIFNlYXNvbmFsaXR5LiBJdCBpcyBiYXNlZCBvbiBleHBvbmVudGlhbCBzbW9vdGhpbmcsIG1lYW5pbmcgaXQgZ2l2ZXMgbW9yZSB3ZWlnaHQgdG8gcmVjZW50IG9ic2VydmF0aW9ucyB3aGlsZSBzdGlsbCB1c2luZyB0aGUgaGlzdG9yeSBvZiB0aGUgc2VyaWVzLgo8L2Rpdj4KCkVUUyBtb2RlbHMgYXJlIHVzZWZ1bCB3aGVuIHRoZSBsZXZlbCwgdHJlbmQgb3Igc2Vhc29uYWwgcGF0dGVybiBvZiBhIHNlcmllcyBjaGFuZ2VzIG92ZXIgdGltZS4gSW4gdGhpcyBwcm9qZWN0LCBFVFMgaXMgd29ydGggdGVzdGluZyBiZWNhdXNlIEJpdGNvaW4gc2VhcmNoIGludGVyZXN0IGRvZXMgbm90IGFwcGVhciBzdGFibGUgYWNyb3NzIHRoZSBmdWxsIHBlcmlvZC4KCjxkaXYgY2xhc3M9ImNvZGUtbGFiZWwiPkNvZGU6IGZpdCB0aGUgRVRTIG1vZGVsIGFuZCBnZW5lcmF0ZSBmb3JlY2FzdHM8L2Rpdj4KCmBgYHtyIGV0cy1tb2RlbCwgcmVzdWx0cz0naGlkZSd9CmV0c19maXQgPC0gZXRzKHRyYWluKQpldHNfZm9yZWNhc3QgPC0gZm9yZWNhc3QoZXRzX2ZpdCwgaCA9IGxlbmd0aCh0ZXN0KSkKYGBgCgo8ZGl2IGNsYXNzPSJjb2RlLWxhYmVsIj5Db2RlOiBjcmVhdGUgYSBjbGVhbiBFVFMgbW9kZWwgc3VtbWFyeSB0YWJsZTwvZGl2PgoKPGRpdiBjbGFzcz0iY2xlYW4tdGFibGUiPgoKYGBge3IgZXRzLW1vZGVsLXRhYmxlfQpldHNfdGFibGUgPC0gZGF0YS5mcmFtZSgKICBNb2RlbCA9IGFzLmNoYXJhY3RlcihldHNfZml0JG1ldGhvZCksCiAgQUlDID0gcm91bmQoZXRzX2ZpdCRhaWMsIDIpLAogIEFJQ2MgPSByb3VuZChldHNfZml0JGFpY2MsIDIpLAogIEJJQyA9IHJvdW5kKGV0c19maXQkYmljLCAyKQopCgprYWJsZShldHNfdGFibGUsIGNhcHRpb24gPSAiRVRTIG1vZGVsIHN1bW1hcnkiKQpgYGAKCjwvZGl2PgoKPGRpdiBjbGFzcz0iY29kZS1sYWJlbCI+Q29kZTogcGxvdCBFVFMgZm9yZWNhc3QgYWdhaW5zdCB0aGUgdGVzdCBwZXJpb2Q8L2Rpdj4KCmBgYHtyIGV0cy1wbG90fQphdXRvcGxvdChldHNfZm9yZWNhc3QpICsKICBsYWJzKAogICAgdGl0bGUgPSAiRVRTIGZvcmVjYXN0IiwKICAgIHN1YnRpdGxlID0gIkZvcmVjYXN0IG92ZXIgdGhlIDEyLW1vbnRoIHRlc3QgcGVyaW9kIiwKICAgIHggPSAiVGltZSIsCiAgICB5ID0gIlNlYXJjaCBpbnRlcmVzdCIKICApICsKICBwbG90X3RoZW1lCmBgYAoKVGhlIGZvcmVjYXN0IGxpbmUgZ2l2ZXMgdGhlIG1vZGVsJ3MgY2VudHJhbCBlc3RpbWF0ZS4gVGhlIHNoYWRlZCBpbnRlcnZhbHMgc2hvdyB1bmNlcnRhaW50eS4gV2lkZXIgaW50ZXJ2YWxzIG1lYW4gdGhlIG1vZGVsIGlzIGxlc3MgY29uZmlkZW50IGFib3V0IGZ1dHVyZSB2YWx1ZXMuCgojIDEwLiBTQVJJTUEgbW9kZWwKCjxkaXYgY2xhc3M9Im1vZGVsLWJveCI+CjxzdHJvbmc+U0FSSU1BIG1vZGVsOjwvc3Ryb25nPiBTQVJJTUEgaXMgYSBzZWFzb25hbCB2ZXJzaW9uIG9mIEFSSU1BLCB3aGljaCBzdGFuZHMgZm9yIEF1dG9SZWdyZXNzaXZlIEludGVncmF0ZWQgTW92aW5nIEF2ZXJhZ2UuCjwvZGl2PgoKVGhlIGF1dG9yZWdyZXNzaXZlIHBhcnQgdXNlcyBwYXN0IHZhbHVlcyBvZiB0aGUgc2VyaWVzLiBUaGUgaW50ZWdyYXRlZCBwYXJ0IG1lYW5zIHRoZSBtb2RlbCBjYW4gZGlmZmVyZW5jZSB0aGUgc2VyaWVzIHRvIGhhbmRsZSBub24tc3RhdGlvbmFyaXR5LiBUaGUgbW92aW5nLWF2ZXJhZ2UgcGFydCB1c2VzIHBhc3QgZm9yZWNhc3QgZXJyb3JzLiBUaGUgc2Vhc29uYWwgcGFydCBhbGxvd3MgdGhlIG1vZGVsIHRvIGNhcHR1cmUgcGF0dGVybnMgdGhhdCByZXBlYXQgZXZlcnkgMTIgbW9udGhzLgoKPGRpdiBjbGFzcz0iY29kZS1sYWJlbCI+Q29kZTogZml0IHRoZSBTQVJJTUEgbW9kZWwgYW5kIGdlbmVyYXRlIGZvcmVjYXN0czwvZGl2PgoKYGBge3Igc2FyaW1hLW1vZGVsLCByZXN1bHRzPSdoaWRlJ30KYXJpbWFfZml0IDwtIGF1dG8uYXJpbWEodHJhaW4sIHNlYXNvbmFsID0gVFJVRSkKYXJpbWFfZm9yZWNhc3QgPC0gZm9yZWNhc3QoYXJpbWFfZml0LCBoID0gbGVuZ3RoKHRlc3QpKQpgYGAKCjxkaXYgY2xhc3M9ImNvZGUtbGFiZWwiPkNvZGU6IGNyZWF0ZSBhIGNsZWFuIFNBUklNQSBtb2RlbCBzdW1tYXJ5IHRhYmxlPC9kaXY+Cgo8ZGl2IGNsYXNzPSJjbGVhbi10YWJsZSI+CgpgYGB7ciBzYXJpbWEtbW9kZWwtdGFibGV9CnNhcmltYV90YWJsZSA8LSBkYXRhLmZyYW1lKAogIE1vZGVsID0gYXMuY2hhcmFjdGVyKGFyaW1hX2ZpdCksCiAgQUlDID0gcm91bmQoQUlDKGFyaW1hX2ZpdCksIDIpLAogIEFJQ2MgPSByb3VuZChhcmltYV9maXQkYWljYywgMiksCiAgQklDID0gcm91bmQoQklDKGFyaW1hX2ZpdCksIDIpCikKCmthYmxlKHNhcmltYV90YWJsZSwgY2FwdGlvbiA9ICJTQVJJTUEgbW9kZWwgc3VtbWFyeSIpCmBgYAoKPC9kaXY+Cgo8ZGl2IGNsYXNzPSJjb2RlLWxhYmVsIj5Db2RlOiBwbG90IFNBUklNQSBmb3JlY2FzdCBhZ2FpbnN0IHRoZSB0ZXN0IHBlcmlvZDwvZGl2PgoKYGBge3Igc2FyaW1hLXBsb3R9CmF1dG9wbG90KGFyaW1hX2ZvcmVjYXN0KSArCiAgbGFicygKICAgIHRpdGxlID0gIlNBUklNQSBmb3JlY2FzdCIsCiAgICBzdWJ0aXRsZSA9ICJGb3JlY2FzdCBvdmVyIHRoZSAxMi1tb250aCB0ZXN0IHBlcmlvZCIsCiAgICB4ID0gIlRpbWUiLAogICAgeSA9ICJTZWFyY2ggaW50ZXJlc3QiCiAgKSArCiAgcGxvdF90aGVtZQpgYGAKCkEgU0FSSU1BIG1vZGVsIHdyaXR0ZW4gYXMgYEFSSU1BKHAsZCxxKShQLEQsUSlbMTJdYCBtZWFucyB0aGF0IGBwYCwgYGRgIGFuZCBgcWAgYXJlIHRoZSBub24tc2Vhc29uYWwgdGVybXMsIHdoaWxlIGBQYCwgYERgIGFuZCBgUWAgYXJlIHRoZSBzZWFzb25hbCB0ZXJtcy4gVGhlIGBbMTJdYCBhcHBlYXJzIGJlY2F1c2UgdGhlIGRhdGEgaXMgbW9udGhseS4KCiMgMTEuIEZvcmVjYXN0IGNvbXBhcmlzb24KClRoZSBtb2RlbHMgYXJlIGNvbXBhcmVkIG9uIHRoZSB0ZXN0IHNldCB1c2luZyBSTVNFLCBNQUUgYW5kIE1BUEUuCgpSTVNFIHBlbmFsaXNlcyBsYXJnZSBlcnJvcnMgbW9yZSBoZWF2aWx5LiBNQUUgZ2l2ZXMgdGhlIGF2ZXJhZ2UgYWJzb2x1dGUgZXJyb3IuIE1BUEUgZXhwcmVzc2VzIHRoZSBlcnJvciBhcyBhIHBlcmNlbnRhZ2UuCgo8ZGl2IGNsYXNzPSJjb2RlLWxhYmVsIj5Db2RlOiBjYWxjdWxhdGUgb3V0LW9mLXNhbXBsZSBhY2N1cmFjeSBmb3IgYWxsIG1vZGVsczwvZGl2PgoKPGRpdiBjbGFzcz0iY2xlYW4tdGFibGUiPgoKYGBge3IgYWNjdXJhY3ktdGFibGV9Cm1lYW5fYWNjdXJhY3kgPC0gYWNjdXJhY3kobWVhbl9maXQsIHRlc3QpCm5haXZlX2FjY3VyYWN5IDwtIGFjY3VyYWN5KG5haXZlX2ZpdCwgdGVzdCkKc25haXZlX2FjY3VyYWN5IDwtIGFjY3VyYWN5KHNuYWl2ZV9maXQsIHRlc3QpCmV0c19hY2N1cmFjeSA8LSBhY2N1cmFjeShldHNfZm9yZWNhc3QsIHRlc3QpCmFyaW1hX2FjY3VyYWN5IDwtIGFjY3VyYWN5KGFyaW1hX2ZvcmVjYXN0LCB0ZXN0KQoKYWNjdXJhY3lfdGFibGUgPC0gcmJpbmQoCiAgTWVhbiA9IG1lYW5fYWNjdXJhY3lbMiwgYygiUk1TRSIsICJNQUUiLCAiTUFQRSIpXSwKICBOYWl2ZSA9IG5haXZlX2FjY3VyYWN5WzIsIGMoIlJNU0UiLCAiTUFFIiwgIk1BUEUiKV0sCiAgU2Vhc29uYWxfTmFpdmUgPSBzbmFpdmVfYWNjdXJhY3lbMiwgYygiUk1TRSIsICJNQUUiLCAiTUFQRSIpXSwKICBFVFMgPSBldHNfYWNjdXJhY3lbMiwgYygiUk1TRSIsICJNQUUiLCAiTUFQRSIpXSwKICBTQVJJTUEgPSBhcmltYV9hY2N1cmFjeVsyLCBjKCJSTVNFIiwgIk1BRSIsICJNQVBFIildCikKCmFjY3VyYWN5X3RhYmxlIDwtIHJvdW5kKGFzLmRhdGEuZnJhbWUoYWNjdXJhY3lfdGFibGUpLCAzKQoKa2FibGUoYWNjdXJhY3lfdGFibGUsIGNhcHRpb24gPSAiT3V0LW9mLXNhbXBsZSBmb3JlY2FzdCBhY2N1cmFjeSIpCmBgYAoKPC9kaXY+Cgo8ZGl2IGNsYXNzPSJjb2RlLWxhYmVsIj5Db2RlOiBpZGVudGlmeSB0aGUgYmVzdCBtb2RlbCB1c2luZyBSTVNFPC9kaXY+CgpgYGB7ciBiZXN0LW1vZGVsLXNlbGVjdGlvbiwgcmVzdWx0cz0naGlkZSd9CmJlc3RfbW9kZWxfbmFtZSA8LSByb3duYW1lcyhhY2N1cmFjeV90YWJsZSlbd2hpY2gubWluKGFjY3VyYWN5X3RhYmxlJFJNU0UpXQpiZXN0X3Jtc2UgPC0gbWluKGFjY3VyYWN5X3RhYmxlJFJNU0UpCmBgYAoKYGBge3IgYmVzdC1tb2RlbC1jYXJkcywgZWNobz1GQUxTRSwgcmVzdWx0cz0nYXNpcyd9CkhUTUwocGFzdGUwKAogICc8ZGl2IGNsYXNzPSJtZXRyaWMtZ3JpZCI+JywKICAgICc8ZGl2IGNsYXNzPSJtZXRyaWMtY2FyZCI+JywKICAgICAgJzxkaXYgY2xhc3M9Im1ldHJpYy1sYWJlbCI+QmVzdCBtb2RlbCBieSBSTVNFPC9kaXY+JywKICAgICAgJzxkaXYgY2xhc3M9Im1ldHJpYy12YWx1ZSI+JywgYmVzdF9tb2RlbF9uYW1lLCAnPC9kaXY+JywKICAgICc8L2Rpdj4nLAogICAgJzxkaXYgY2xhc3M9Im1ldHJpYy1jYXJkIj4nLAogICAgICAnPGRpdiBjbGFzcz0ibWV0cmljLWxhYmVsIj5Mb3dlc3QgUk1TRTwvZGl2PicsCiAgICAgICc8ZGl2IGNsYXNzPSJtZXRyaWMtdmFsdWUiPicsIGJlc3Rfcm1zZSwgJzwvZGl2PicsCiAgICAnPC9kaXY+JywKICAnPC9kaXY+JwopKQpgYGAKCjxkaXYgY2xhc3M9InRha2Vhd2F5Ij4KPHN0cm9uZz5Nb2RlbCBzZWxlY3Rpb246PC9zdHJvbmc+IFRoZSBiZXN0IG1vZGVsIGlzIHNlbGVjdGVkIHVzaW5nIG91dC1vZi1zYW1wbGUgcGVyZm9ybWFuY2UsIG5vdCB2aXN1YWwgZml0LiBUaGlzIHRlc3RzIHdoZXRoZXIgdGhlIG1vZGVsIGNhbiBnZW5lcmFsaXNlIGJleW9uZCB0aGUgZGF0YSBpdCB3YXMgdHJhaW5lZCBvbi4KPC9kaXY+CgojIDEyLiBSZXNpZHVhbCBkaWFnbm9zdGljcwoKQSBtb2RlbCBzaG91bGQgbm90IGxlYXZlIGJlaGluZCBvYnZpb3VzIHBhdHRlcm5zIGluIHRoZSByZXNpZHVhbHMuIElmIHJlc2lkdWFscyBzdGlsbCBzaG93IGF1dG9jb3JyZWxhdGlvbiwgdGhlbiB0aGUgbW9kZWwgaGFzIG5vdCBjYXB0dXJlZCBhbGwgb2YgdGhlIHRpbWUgc2VyaWVzIHN0cnVjdHVyZS4KCjxkaXYgY2xhc3M9ImNvZGUtbGFiZWwiPkNvZGU6IHJ1biBManVuZy1Cb3ggcmVzaWR1YWwgYXV0b2NvcnJlbGF0aW9uIHRlc3RzPC9kaXY+Cgo8ZGl2IGNsYXNzPSJjbGVhbi10YWJsZSI+CgpgYGB7ciByZXNpZHVhbC10ZXN0cy10YWJsZX0KYXJpbWFfbGIgPC0gQm94LnRlc3QocmVzaWR1YWxzKGFyaW1hX2ZpdCksIGxhZyA9IDEyLCB0eXBlID0gIkxqdW5nLUJveCIpCmV0c19sYiA8LSBCb3gudGVzdChyZXNpZHVhbHMoZXRzX2ZpdCksIGxhZyA9IDEyLCB0eXBlID0gIkxqdW5nLUJveCIpCgpyZXNpZHVhbF90YWJsZSA8LSBkYXRhLmZyYW1lKAogIE1vZGVsID0gYygiRVRTIiwgIlNBUklNQSIpLAogIGBManVuZy1Cb3ggc3RhdGlzdGljYCA9IGMoCiAgICByb3VuZChhcy5udW1lcmljKGV0c19sYiRzdGF0aXN0aWMpLCAzKSwKICAgIHJvdW5kKGFzLm51bWVyaWMoYXJpbWFfbGIkc3RhdGlzdGljKSwgMykKICApLAogIGBwLXZhbHVlYCA9IGMoCiAgICByb3VuZChldHNfbGIkcC52YWx1ZSwgNCksCiAgICByb3VuZChhcmltYV9sYiRwLnZhbHVlLCA0KQogICkKKQoKa2FibGUocmVzaWR1YWxfdGFibGUsIGNhcHRpb24gPSAiUmVzaWR1YWwgYXV0b2NvcnJlbGF0aW9uIGRpYWdub3N0aWNzIikKYGBgCgo8L2Rpdj4KClRoZSBManVuZy1Cb3ggdGVzdCBjaGVja3Mgd2hldGhlciByZXNpZHVhbCBhdXRvY29ycmVsYXRpb24gcmVtYWlucy4gQSBoaWdoIHAtdmFsdWUgc3VnZ2VzdHMgdGhlcmUgaXMgbm8gc3Ryb25nIGV2aWRlbmNlIG9mIHJlbWFpbmluZyBhdXRvY29ycmVsYXRpb24uIEEgbG93IHAtdmFsdWUgc3VnZ2VzdHMgdGhlIG1vZGVsIG1heSBzdGlsbCBiZSBtaXNzaW5nIHNvbWUgc3RydWN0dXJlLgoKPGRpdiBjbGFzcz0iY29kZS1sYWJlbCI+Q29kZTogcGxvdCBTQVJJTUEgcmVzaWR1YWwgZGlhZ25vc3RpY3M8L2Rpdj4KCmBgYHtyIHJlc2lkdWFsLWRpYWdub3N0aWNzLWFyaW1hLCBmaWcuaGVpZ2h0PTYuNSwgcmVzdWx0cz0naGlkZSd9CmNoZWNrcmVzaWR1YWxzKGFyaW1hX2ZpdCkKYGBgCgo8ZGl2IGNsYXNzPSJjb2RlLWxhYmVsIj5Db2RlOiBwbG90IEVUUyByZXNpZHVhbCBkaWFnbm9zdGljczwvZGl2PgoKYGBge3IgcmVzaWR1YWwtZGlhZ25vc3RpY3MtZXRzLCBmaWcuaGVpZ2h0PTYuNSwgcmVzdWx0cz0naGlkZSd9CmNoZWNrcmVzaWR1YWxzKGV0c19maXQpCmBgYAoKIyAxMy4gRmluYWwgZm9yZWNhc3QKCkFmdGVyIGNvbXBhcmluZyB0aGUgbW9kZWxzLCB0aGUgU0FSSU1BIG1vZGVsIGlzIHJlZml0dGVkIG9uIHRoZSBmdWxsIGRhdGFzZXQgYW5kIHVzZWQgdG8gcHJvZHVjZSBhIDEyLW1vbnRoIGZvcmVjYXN0LiBUaGUgdHJhaW4tdGVzdCBzcGxpdCB3YXMgdXNlZCBmb3IgbW9kZWwgZXZhbHVhdGlvbjsgb25jZSB0aGF0IGlzIGNvbXBsZXRlLCB0aGUgZmluYWwgbW9kZWwgY2FuIHVzZSBhbGwgYXZhaWxhYmxlIG9ic2VydmF0aW9ucy4KCjxkaXYgY2xhc3M9ImNvZGUtbGFiZWwiPkNvZGU6IHJlZml0IFNBUklNQSB1c2luZyB0aGUgZnVsbCBkYXRhc2V0IGFuZCBmb3JlY2FzdCAxMiBtb250aHMgYWhlYWQ8L2Rpdj4KCmBgYHtyIGZpbmFsLW1vZGVsLCByZXN1bHRzPSdoaWRlJ30KZmluYWxfbW9kZWwgPC0gYXV0by5hcmltYShidGNfdHMsIHNlYXNvbmFsID0gVFJVRSkKZmluYWxfZm9yZWNhc3QgPC0gZm9yZWNhc3QoZmluYWxfbW9kZWwsIGggPSAxMikKYGBgCgo8ZGl2IGNsYXNzPSJjb2RlLWxhYmVsIj5Db2RlOiBjcmVhdGUgZmluYWwgbW9kZWwgc3VtbWFyeSB0YWJsZTwvZGl2PgoKPGRpdiBjbGFzcz0iY2xlYW4tdGFibGUiPgoKYGBge3IgZmluYWwtbW9kZWwtdGFibGV9CmZpbmFsX3RhYmxlIDwtIGRhdGEuZnJhbWUoCiAgTW9kZWwgPSBhcy5jaGFyYWN0ZXIoZmluYWxfbW9kZWwpLAogIEFJQyA9IHJvdW5kKEFJQyhmaW5hbF9tb2RlbCksIDIpLAogIEFJQ2MgPSByb3VuZChmaW5hbF9tb2RlbCRhaWNjLCAyKSwKICBCSUMgPSByb3VuZChCSUMoZmluYWxfbW9kZWwpLCAyKQopCgprYWJsZShmaW5hbF90YWJsZSwgY2FwdGlvbiA9ICJGaW5hbCBtb2RlbCBmaXR0ZWQgb24gZnVsbCBkYXRhc2V0IikKYGBgCgo8L2Rpdj4KCjxkaXYgY2xhc3M9ImNvZGUtbGFiZWwiPkNvZGU6IHBsb3QgdGhlIGZpbmFsIDEyLW1vbnRoIGZvcmVjYXN0PC9kaXY+CgpgYGB7ciBmaW5hbC1mb3JlY2FzdC1wbG90fQphdXRvcGxvdChmaW5hbF9mb3JlY2FzdCkgKwogIGxhYnMoCiAgICB0aXRsZSA9ICJGaW5hbCAxMi1tb250aCBmb3JlY2FzdCBmb3IgQml0Y29pbiBzZWFyY2ggaW50ZXJlc3QiLAogICAgc3VidGl0bGUgPSAiU0FSSU1BIG1vZGVsIHJlZml0dGVkIHVzaW5nIHRoZSBmdWxsIGRhdGFzZXQiLAogICAgeCA9ICJUaW1lIiwKICAgIHkgPSAiU2VhcmNoIGludGVyZXN0IgogICkgKwogIHBsb3RfdGhlbWUKYGBgCgo8ZGl2IGNsYXNzPSJjYXV0aW9uIj4KPHN0cm9uZz5Gb3JlY2FzdCBpbnRlcnByZXRhdGlvbjo8L3N0cm9uZz4gVGhpcyBmb3JlY2FzdCBzaG91bGQgbm90IGJlIHRyZWF0ZWQgYXMgYSBwcmVjaXNlIHByZWRpY3Rpb24uIEJpdGNvaW4gc2VhcmNoIGludGVyZXN0IGlzIHN0cm9uZ2x5IGFmZmVjdGVkIGJ5IG5ld3MsIHByaWNlIG1vdmVtZW50cyBhbmQgbWFya2V0IHNlbnRpbWVudC4gVGhlIGZvcmVjYXN0IGlzIGJlc3QgdW5kZXJzdG9vZCBhcyBhIG1vZGVsLWJhc2VkIGVzdGltYXRlIGFzc3VtaW5nIGZ1dHVyZSBiZWhhdmlvdXIgaXMgc2ltaWxhciB0byBwYXN0IHBhdHRlcm5zLgo8L2Rpdj4KCiMgMTQuIExpbWl0YXRpb25zIGFuZCBwb3NzaWJsZSBleHRlbnNpb25zCgpUaGVyZSBhcmUgc2V2ZXJhbCBsaW1pdGF0aW9ucyB0byB0aGlzIHByb2plY3QuCgpGaXJzdCwgR29vZ2xlIFRyZW5kcyBnaXZlcyByZWxhdGl2ZSBzZWFyY2ggaW50ZXJlc3QgcmF0aGVyIHRoYW4gdGhlIGFjdHVhbCBudW1iZXIgb2Ygc2VhcmNoZXMuIFNlY29uZCwgdGhpcyBpcyBhIHVuaXZhcmlhdGUgYW5hbHlzaXMsIHNvIHRoZSBtb2RlbHMgb25seSB1c2UgcGFzdCBzZWFyY2ggaW50ZXJlc3QuIFRoZXkgZG8gbm90IGluY2x1ZGUgQml0Y29pbiBwcmljZSwgdHJhZGluZyB2b2x1bWUsIG1hcmtldCB2b2xhdGlsaXR5LCBuZXdzIHNlbnRpbWVudCBvciBtYWNyb2Vjb25vbWljIHZhcmlhYmxlcy4KClRoaXMgbWF0dGVycyBiZWNhdXNlIEJpdGNvaW4gYXR0ZW50aW9uIGlzIGxpa2VseSBkcml2ZW4gYnkgZXh0ZXJuYWwgZmFjdG9ycy4gQSBsYXJnZSBwcmljZSBtb3ZlbWVudCBvciBtYWpvciBuZXdzIHN0b3J5IGNvdWxkIGNoYW5nZSBzZWFyY2ggaW50ZXJlc3QgdmVyeSBxdWlja2x5LCBhbmQgYSBtb2RlbCBiYXNlZCBvbmx5IG9uIHBhc3Qgc2VhcmNoIGludGVyZXN0IG1heSBub3QgcmVhY3QgdW50aWwgYWZ0ZXIgdGhlIG1vdmVtZW50IGhhcyBhbHJlYWR5IGhhcHBlbmVkLgoKUG9zc2libGUgZXh0ZW5zaW9ucyBpbmNsdWRlOgoKLSBhZGRpbmcgQml0Y29pbiBwcmljZSBhcyBhbiBleHRlcm5hbCByZWdyZXNzb3I7Ci0gdGVzdGluZyBhbiBBUklNQVggbW9kZWw7Ci0gY29tcGFyaW5nIHRoZSByZXN1bHRzIHdpdGggUHJvcGhldDsKLSB1c2luZyByb2xsaW5nLXdpbmRvdyBjcm9zcy12YWxpZGF0aW9uOwotIGluY2x1ZGluZyBuZXdzIG9yIHNvY2lhbCBtZWRpYSBzZW50aW1lbnQ7Ci0gbW9kZWxsaW5nIHNlYXJjaCBpbnRlcmVzdCBhbmQgcHJpY2UgdG9nZXRoZXIuCgojIDE1LiBDb25jbHVzaW9uCgpUaGlzIHByb2plY3Qgc2hvd3MgdGhhdCBCaXRjb2luIHNlYXJjaCBpbnRlcmVzdCBpcyB2b2xhdGlsZSwgdW5ldmVuIGFuZCBzdHJvbmdseSBhZmZlY3RlZCBieSBzcGlrZXMgaW4gcHVibGljIGF0dGVudGlvbi4gVGhlIGRlY29tcG9zaXRpb24gYW5kIHN0YXRpb25hcml0eSBhbmFseXNpcyBzdWdnZXN0IHRoYXQgdGhlIHNlcmllcyBpcyBub3QgYSBzaW1wbGUgc3RhYmxlIHByb2Nlc3MuCgpUaGUgbW9kZWwgY29tcGFyaXNvbiBzaG93cyB3aHkgYmVuY2htYXJrcyBhcmUgaW1wb3J0YW50LiBBIG1vcmUgY29tcGxpY2F0ZWQgbW9kZWwgaXMgb25seSB1c2VmdWwgaWYgaXQgaW1wcm92ZXMgb24gc2ltcGxlIG1ldGhvZHMgd2hlbiB0ZXN0ZWQgb24gdW5zZWVuIGRhdGEuIEVUUyBhbmQgU0FSSU1BIHByb3ZpZGUgbW9yZSBzdHJ1Y3R1cmVkIGFwcHJvYWNoZXMsIGJ1dCB0aGVpciB1c2VmdWxuZXNzIGRlcGVuZHMgb24gd2hldGhlciB0aGV5IGFjdHVhbGx5IHJlZHVjZSBmb3JlY2FzdCBlcnJvciBvbiB0aGUgdGVzdCBzZXQuCgpPdmVyYWxsLCBjbGFzc2ljYWwgdGltZSBzZXJpZXMgbW9kZWxzIGNhbiBjYXB0dXJlIHNvbWUgb2YgdGhlIHN0cnVjdHVyZSBpbiBCaXRjb2luIHNlYXJjaCBpbnRlcmVzdCwgYnV0IHRoZXJlIGFyZSBjbGVhciBsaW1pdHMuIFRoZSBzZXJpZXMgaXMgcGFydGx5IHByZWRpY3RhYmxlIGZyb20gaXRzIG93biBoaXN0b3J5LCBidXQgaXQgaXMgYWxzbyBoZWF2aWx5IGluZmx1ZW5jZWQgYnkgZXh0ZXJuYWwgZXZlbnRzLiBBIHN0cm9uZ2VyIGZ1dHVyZSB2ZXJzaW9uIG9mIHRoaXMgcHJvamVjdCB3b3VsZCBpbmNsdWRlIGV4cGxhbmF0b3J5IHZhcmlhYmxlcyBzdWNoIGFzIEJpdGNvaW4gcHJpY2UsIHRyYWRpbmcgdm9sdW1lIGFuZCBuZXdzIHNlbnRpbWVudC4=