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