Introduction
For this project, we will be creating a Time Series. This time series
looks at the average number of air travel passengers on all U.S.
flights. The time series we will look at will include the number of
passengers on both domestic and international flights. We will create a
monthly time series which looks at the average number of air travel
passengers by month. This time series data was collected from 2003 to
2023, with the first observation in January of 2003, and the final
observation in September 2023.
We will split the time series data up into a training and a testng
data set. And then we create several candidate, exponential smoothing
models for forecasting. These will include a simple exponential model,
several Holt models, and several Holt-Winter’s models. We will see which
of these candidate models provides the best utility for an exponential
smoothing model of our time series. We will determine the best model by
seeing which one reduces the errors and provides the best overall
accuracy.
Data Description
I found this data set on kaggle.com on the following webpage: https://www.kaggle.com/datasets/yyxian/u-s-airline-traffic-data?select=air+traffic.csv
This data set looks at the average number of air travel passengers by
month from 2003 to 2023. The first observation in this data set was
collected in January 2003, and the final observation in this data set
was collected in September 2023. This data set includes variables which
represent the total number of passengers on both domestic and
international flights by month. However, for this time series, we will
look specifically at the variable which represents the total number of
passengers on all flights, both domestic and international. This data is
representative of passengers on all U.S. flights by month.
We will read in the data set from Github and we will call it
“flight”.
flight <- read.csv("https://raw.githubusercontent.com/JosieGallop/STA321/refs/heads/main/dataset/air%20traffic.csv")
This data set contains many variables regarding air travel
information, but for this time series we are just interested in looking
at the number of the total air travel passengers. This is represented by
the variable Pax. We want to create a time series of the total air
travel passengers by the date, so we will only keep the time specific
variables, Year and Month, and the Pax variable. We will call the new
data set with only these specific variables we are interested in
“flight1”.
flight1 <- flight %>%
select(Year, Month, Pax)
Now, we have a new data set, flight1, with only the variables we are
interested in for our time series project.
Variables
There are three variables from the original data set which we will be
interested in for this time series project.
Year: The year of which the observation is from. This data set
spans from 2003 to 2023.
Month: The month of which the observation is from. Given as a two
digit number representing the month. For example, 01 represents January,
02 represents February, and so on.
Pax: The total number of air travel passengers for a given
observations. This includes air passengers on both domestic and
international flights.
During our exploratory data analysis, we will create a new variable
called Date which will combine the year and the month variables to get
just one, single variable to represent the date of which an observation
occurred. The date variable we will create will be given in the format
of Year-Month.
Exploratory Data
Analysis
First, let’s ensure that there are not any missing variables in this
data set.
colSums(is.na(flight1))
Year Month Pax
0 0 0
As we can see, there are zero missing values in our data set, so that
means we do not have to worry about filling in any missing observations.
We can proceed with our time series project.
Next, we will combine the Year and Month variables into one variable
called Date which is given as year and month combined, in the format of
Year-Month. We will create a new data set with the combined Date
variable and we will call this new data set “flight2”.
flight2 <- flight1 %>%
mutate(Date = paste(Year, sprintf("%02d", Month), sep = "-"))
flight2 <- select(flight2, -1,-2)
Now, we have a data set “flight2” with just the Date, given in a
Year-Month format, and the Pax variable representing the total number of
air travel passengers.
One thing I noticed is that the Pax variable is incorrectly given as
a character variable when it should really be a numeric variable since
it represents the total number of air travel passengers. We will change
the variable type of the Pax variable from a character to a numeric
variable in order to fix this issue. We will remove the commas from the
Pax variable before converting it to a numeric variable to avoid any
problems with the conversion of the variable type.
flight2$Pax <- gsub(",", "", flight2$Pax)
flight2$Pax <- as.numeric(flight2$Pax)
Now we have the proper data set we can use to create the time series.
This data set provides monthly averages for the number of air travel
passengers for all domestic and international flights.
Time Series Plot
Now, we will create a time series object from our flight data and
plot it to help visualize any potential trends that may be occurring
within this time series data set. We will call this time series object
“flight.ts”. Since we are creating a monthly time series looking at the
average number of air travel passengers by month, our frequency will be
12.
flight.ts <- ts(flight2$Pax, start = c(2003, 1), frequency = 12)
plot(flight.ts, main = "Monthly Average Air Travel Passengers from 2003 to 2023", xlab = "Year", ylab = "Air Travel Passengers")

Looking at the time series plot, we can see some notable occurrences
within our data. There is certainly some sort of seasonality going on
within our time series which can be seen by how the plot has a pattern
which repeats after a certain amount of time. It looks like this time
series might have an annual seasonality, with this repetition occurring
after a year has gone by. This would make sense that the number of air
travel passengers would have an annual seasonality, because more people
likely travel during the summer months due to the ideal weather and for
families this would mean their children would be on summer break which
would make having a vacation during the summer an optimal timing. It
would make sense that the number of air travel passengers would peak
during the summer months, and then drop back down until there is another
slight rise around the holiday months in the winter time due to people
travelling to spend the holidays with their family. Overall, an annual
seasonality would make sense for a time series on the number of air
travel passengers.
Another notable occurrence within this time series is that there
appears to be a trend of slight overall increase in the number of air
travel passengers from the start of the time series up until the end.
There is an especially noticeable trend of overall increase from around
2010 up until 2019. We can see that there is an incredibly massive
decrease in the number of air travel passengers around 2020. This can be
attributed to the travel restrictions which were put in place during the
early days of the covid pandemic. This would explain why there is such a
drastic decline in the number of air travel passengers seen in the year
2020. After this decline in 2020, we can see that the number of air
travel passengers begins to gradually increase over the following years,
and it appears that the numbers at the end of the time series in 2023
are fairly similar to what they were right before the major decline seen
in 2020.
Data Split
We will split our time series data into two data sets, one for
training, and one for testing. Since we have a monthly time series, we
will use the 12 most recent observations for the testing data set. The
rest of the observations will be used for the training data set. We will
also create a time series object for just the training data set. We will
call this time series object “flight.ts1”.
test.flight <- flight2$Pax[238:249]
train.flight <- flight2$Pax[1:238]
flight.ts1 <- ts(flight2$Pax[1:238], start = c(2003, 1), frequency = 12)
Now we have split our time series data set up into a training and a
testing data set. We will use the training data set to train the
smoothing models we will create. We will use the testing data set to
identify which of these smoothing models we will create is the best one
to use. So, we will next begin with creating these smoothing models and
we will use the training and testing data sets to help us with building
each of these models and then determining which model is the best one to
use.
Smoothing Models
We will now begin with building the smoothing models so we can
ultimately determine which one does the best and would be the best to
use. We will create three different types of smoothing models. These
different models will include a simple exponential smoothing model, Holt
models (additive and with a possible damped pattern), and Holt-Winter’s
models (additive and multiplicative seasonality with a possible damped
pattern).
Simple Exponential
Smoothing Model
First, we will begin with creating the simple exponential smoothing
model. We will call this simple exponential smoothing model “fit1”.
# Simple Exponential Smoothing Model
fit1 <- ses(flight.ts1, h = 12)
Now we have created our simple exponential smoothing model.
Holt Models
Next, we will create the Holt models. We will use three different
kinds of Holt models. The first of our Holt models will be a linear Holt
model, and we will call this “fit2”. Our next Holt model will be an
additive Holt model with a possible damped pattern, and this will be
called “fit3”. Our last Holt model will be an exponential Holt model
with a possible damped pattern, and this will be called “fit4”.
# Holt Linear Model
fit2 <- holt(flight.ts1, initial = "optimal", h = 12)
# Holt Additive Model with a Possible Damped Pattern
fit3 <- holt(flight.ts1, damped = TRUE, h = 12)
# Holt Exponential Model with a Possible Damped Pattern
fit4 <- holt(flight.ts1, exponential = TRUE, damped = TRUE, h = 12)
Now we have successfully created our Holt models.
Holt-Winter’s
Models
Lastly, we will create our Holt Winter’s models. We will use four
different kinds of Holt-Winter’s models. The first of these will be a
Holt-Winter’s additive model, and this will be called “fit5”. The next
will be a Holt-Winter’s multiplicative model, and this will be called
“fit6”. The next one after will be a Holt-Winter’s additive model with a
possible damped pattern, and this will be called “fit7”. The last of
these models will be a Holt-Winter’s multiplicative model with a
possible damped pattern, and this will be called “fit8”.
# Holt-Winter's Additive Model
fit5 <- hw(flight.ts1, h = 12, seasonal = "additive")
# Holt-Winter's Multiplicative Model
fit6 <- hw(flight.ts1, h = 12, seasonal = "multiplicative")
# Holt-Winter's Additive Model with a Possible Damped Pattern
fit7 <- hw(flight.ts1, h = 12, seasonal = "additive", damped=TRUE)
# Holt-Winter's Multiplicative Model with a Possible Damped Pattern
fit8 <- hw(flight.ts1, h = 12, seasonal = "multiplicative", damped=TRUE)
Now we have successfully created all of our Holt-Winter’s models.
Accuracy Measures
Now that we have created various models to try out, including a
simple exponential model, Holt models, and Holt-Winter’s models, we will
use accuracy measures to compare all of these different models. These
accuracy measures will be based upon the training data set that we
created from our time series data.
accuracy.table = round(rbind(accuracy(fit1), accuracy(fit2), accuracy(fit3), accuracy(fit4), accuracy(fit5), accuracy(fit6), accuracy(fit7), accuracy(fit8)), 4)
row.names(accuracy.table)=c("SES","Holt Linear","Holt Add. Damped", "Holt Mult. Damped", "HW Add.","HW Mult.","HW Add. Damped", "HW Mult. Damped")
kable(accuracy.table, caption = "Acccuracy Measures of the Various Smoothing Models Based upon the Training Data Set")
Acccuracy Measures of the Various Smoothing Models Based upon
the Training Data Set
SES |
102859.87 |
6626499 |
4795473 |
-5.1086 |
13.3855 |
0.6550 |
0.0043 |
Holt Linear |
-485232.07 |
6653815 |
4823863 |
-6.0574 |
13.4850 |
0.6589 |
-0.0019 |
Holt Add. Damped |
62009.49 |
6614114 |
4775792 |
-5.1840 |
13.3544 |
0.6523 |
0.0042 |
Holt Mult. Damped |
65535.10 |
6619923 |
4833567 |
-4.9977 |
13.3576 |
0.6602 |
-0.0276 |
HW Add. |
-240230.44 |
3914979 |
1755071 |
-4.4331 |
7.6521 |
0.2397 |
0.3594 |
HW Mult. |
-326797.03 |
4516990 |
2044228 |
-5.4066 |
8.9673 |
0.2792 |
0.3666 |
HW Add. Damped |
70386.74 |
3885667 |
1765809 |
-3.5371 |
7.6123 |
0.2412 |
0.3325 |
HW Mult. Damped |
70002.38 |
4144943 |
1769723 |
-3.9989 |
8.0597 |
0.2417 |
0.3616 |
To interpret our accuracy table, we have several measures of accuracy
we looked at. The ME, or mean errors, represents how far off the
predictions are from their actual values. The Holt Add. Damped and Holt
Mult. Damped have the smallest absolute value of their ME. Next, we have
RMSE, MAE, and MAPE, all of which a lower value is ideal because it
indicates the least errors. From these accuracy measurements, the HW
Add., and the HW. Add. Damped stand out for having notably lower values
than any of the other models do. For the MASE measurement, a value
closest to zero is ideal. The HW. Add model has the closest MASE to
zero, making this once again seem like a strong model. Lastly, for the
ACF1 measurements, a value closest to zero is ideal for accuracy. From
our models, the Holt Linear model has an ACF1 that is closest to
zero.
Overall, the Holt-Winter’s Additive model stood out for showing ideal
performance in the most accuracy measures of all of the models. This
Holt-Winter’s Additive model had low RMSE, MAE, and MAPE, as well as a
MASE closest to zero. Since the Holt-Winter’s Additive model stood out
in more accuracy measurements than any of the other models, we will
choose this smoothing model as the ideal model in terms of
performance.
Serial Plot of the
Data
We will create a serial plot of the historical data, which is the
data that was used for the training data set. This will allow us to
forecast the values and visualize this forecast.
We will create two serial plots, one will be for the non-seasonal
smoothing models, which will include the simple exponential smoothing
model, the Holt linear, the Holt Additive Damped, and the Holt
Multiplicative Damped models. The other serial plot will be for the
trend and seasonal smoothing models, which will include the HW Additive,
the HW Multiplicative, the HW Additive Damped, and the HW Multiplicative
Damped models.
First, we will create the serial plot for the non-seasonal smoothing
models.
par(mfrow = c(2,1), mar = c(3,4,3,1))
pred.id = 238:249
plot(1:238, flight.ts1, lwd = 2,type = "o", ylab = "Air Travel Passengers", xlab = "",
xlim = c(1, 249), ylim=c(0, 80000000), cex = 0.3,
main = "Non-seasonal Smoothing Models")
lines(pred.id, fit1$mean, col = "pink")
lines(pred.id, fit2$mean, col = "blue")
lines(pred.id, fit3$mean, col = "purple")
lines(pred.id, fit4$mean, col = "navy")
points(pred.id, fit1$mean, pch = 16, col = "pink", cex = 0.5)
points(pred.id, fit2$mean, pch = 17, col = "blue", cex = 0.5)
points(pred.id, fit3$mean, pch = 19, col = "purple", cex = 0.5)
points(pred.id, fit4$mean, pch = 21, col = "navy", cex = 0.5)
legend("bottomright", lty = 1, col = c("pink","blue","purple","navy"), pch = c(16, 17, 19, 21),
c("SES","Holt Linear","Holt Additive Damped", "Holt Multiplicative Damped"),
cex = 0.5, bty = "n")

We can see from the serial plot that this visualized the forecasts
for the non-seasonal smoothing models which we created.
Next, we will create the serial plot for the Holt-Winter’s trend and
seasonal smoothing models.
plot(1:238, flight.ts1, lwd = 2, type = "o", ylab = "Air Travel Passengers", xlab = "",
xlim=c(1,249), ylim=c(0, 80000000), cex = 0.3,
main="Holt-Winters Trend and Seasonal Smoothing Models")
lines(pred.id, fit5$mean, col = "pink")
lines(pred.id, fit6$mean, col = "blue")
lines(pred.id, fit7$mean, col = "purple")
lines(pred.id, fit8$mean, col = "navy")
points(pred.id, fit5$mean, pch = 16, col = "pink", cex = 0.5)
points(pred.id, fit6$mean, pch = 17, col = "blue", cex = 0.5)
points(pred.id, fit7$mean, pch = 19, col = "purple", cex = 0.5)
points(pred.id, fit8$mean, pch = 21, col = "navy", cex = 0.5)
legend("bottomright", lty=1, col = c("pink","blue","purple", "navy"), pch = c(16, 17, 19, 21),
c("HW Additive","HW Multiplicative","HW Additive Damped", "HW Multiplicative Damped"),
cex = 0.5, bty = "n")

We can see from this serial plot the forecasts for the trend and
seasonal smoothing models.
From the two serial plots we created, it looks like the Holt-Winter’s
Additive model once again seems like the best of the models we created.
This matches up with what was found in the accuracy table. It looks like
the Holt Winter’s Additive Model provides a quality forecast in the
serial plot for the Holt-Winter’s trend and seasonal smoothing
models.
Forecasting with the
Testing Data
Now that we have determined which model looks like the ideal choice,
the Holt-Winter’s Additive Model, we will use the testing data set which
we created earlier to verify our best model selection.
We previously used the training data set to train the various
smoothing models we looked at. To create our real-world forecast, we
will refit the model using the testing data as well. This will allow us
to verify our findings and if the model which looked to show the best
performance in forecasting truly looks like the ideal choice.
First, we will refit the model using the entire data set to update
the smoothing parameters.
acc.fun = function(test.data, mod.obj){
PE = 100*(test.data-mod.obj$mean)/mod.obj$mean
MAPE = mean(abs(PE))
E = test.data-mod.obj$mean
MSE = mean(E^2)
accuracy.metric = c(MSE = MSE, MAPE = MAPE)
accuracy.metric
}
Now, we will find the updated accuracy prediction measures for each
of the smoothing models we created.
pred.accuracy = rbind(SES = acc.fun(test.data = test.flight, mod.obj = fit1),
Holt.Add = acc.fun(test.data=test.flight,
mod.obj = fit2),
Holt.Add.Damp = acc.fun(test.data = test.flight,
mod.obj=fit3),
Holt.Exp = acc.fun(test.data = test.flight,
mod.obj = fit4),
HW.Add = acc.fun(test.data = test.flight,
mod.obj = fit5),
HW.Exp = acc.fun(test.data = test.flight,
mod.obj = fit6),
HW.Add.Damp = acc.fun(test.data = test.flight,
mod.obj = fit7),
HW.Exp.Damp = acc.fun(test.data = test.flight,
mod.obj = fit8))
kable(pred.accuracy, caption = "Accuracy Measures of the Various Exponential Smoothing Models Based on the Testing Data Set")
Accuracy Measures of the Various Exponential Smoothing Models
Based on the Testing Data Set
SES |
4.496124e+13 |
7.346870 |
Holt.Add |
3.748179e+13 |
6.273833 |
Holt.Add.Damp |
4.493119e+13 |
7.343571 |
Holt.Exp |
4.454601e+13 |
7.246437 |
HW.Add |
3.049452e+13 |
5.195657 |
HW.Exp |
4.372064e+13 |
7.284188 |
HW.Add.Damp |
3.366352e+13 |
5.255700 |
HW.Exp.Damp |
3.954300e+13 |
5.948060 |
Looking at the accuracy measures based on the testing data set, we
can see that the Holt-Winter’s Additive model has both the lowest MSE
and MAPE. This is ideal because we want our model to reduce the errors
as much as possible. Also, this matches up with what we found earlier,
because once again the Holt-Winter’s Additive model has the best
performance in terms of accuracy. So, it looks like the Holt-Winter’s
Additive model is the ideal choice, and this has been verified with the
testing data set.
Final Model
Based upon our findings, it looks like the Holt-Winter’s Additive
model is the ideal choice out of the many possible candidate models we
created. This model showed its ideal performance by reducing the errors
more significantly than any of the other models did. This Holt-Winter’s
Additive model also showed the best performance in terms of the accuracy
measures, because it had the lowest MSE and MAPE values of out any of
the models. So, the Holt-Winter’s Additive model is the ideal model out
of all the candidate models we created and tried out.
Smoothing
Parameters
We will take a look at the smoothing parameters for the Holt-Winter’s
Additive model.
final.model <- hw(flight.ts1, h = 12, seasonal = "additive")
smoothing.parameter = final.model$model$par[1:3]
kable(smoothing.parameter, caption="The Estimated Values of the Smoothing Parameters in the Holt-Winters Additive Model")
The Estimated Values of the Smoothing Parameters in the
Holt-Winters Additive Model
alpha |
0.9998907 |
beta |
0.0003555 |
gamma |
0.0001081 |
The smoothing parameters for our final model, the Holt-Winter’s
Additive model, include an alpha of 0.9999, a beta of 0.0004, and a
gamma of 0.0001.
Conclusion
Overall, we looked at a data set which was representative of the
total number of air travel passengers in the U.S. through monthly
averages. This data was collected over the course of the years from 2003
to 2023. We created a monthly time series which showed the trends and
seasonality of the average number of air travel passengers by month over
the span of this 20 year period.
We split the time series data up into a training and a testing data
set. After looking at several potenetial smoothing models, the one which
was found to provide the best performance was the Holt-Winter’s Additive
model. This model was the best choice because it did the best job out of
decreasing the errors, and provided the best accuracy overall. So, the
Holt-Winter’s Additive model was the best choice out of the several
candidate, smoothing models we looked at.
Recommendations
Some recommendations I would make for future projects include:
Consider expanding the time series data to include the average
air travel passengers for all countries, not just the U.S. in order to
see if this still results in the Holt-Winter’s Additive model being the
ideal model choice, or if another model seems to provide better
performance in this scenario.
Further look into the seasonality in this time series data set,
since there definitely appeared to be seasonality occurring with more
passengers travelling in certain times of the year, like summer, than
during other times of the year which saw fewer passengers.
LS0tDQp0aXRsZTogIk1vbnRobHkgQXZlcmFnZSBBaXIgVHJhdmVsIFBhc3NlbmdlcnM6IFRpbWUgU2VyaWVzIHdpdGggRXhwb25lbnRpYWwgU21vb3RoaW5nIg0KYXV0aG9yOiAiSm9zaWUgR2FsbG9wIg0KZGF0ZTogIjIwMjQtMTItMTEiDQpvdXRwdXQ6DQogIGh0bWxfZG9jdW1lbnQ6IA0KICAgIHRvYzogeWVzDQogICAgdG9jX2RlcHRoOiA0DQogICAgdG9jX2Zsb2F0OiB5ZXMNCiAgICBmaWdfd2lkdGg6IDYNCiAgICBmaWdfY2FwdGlvbjogeWVzDQogICAgbnVtYmVyX3NlY3Rpb25zOiB5ZXMNCiAgICB0b2NfY29sbGFwc2VkOiB5ZXMNCiAgICBjb2RlX2ZvbGRpbmc6IGhpZGUNCiAgICBjb2RlX2Rvd25sb2FkOiB5ZXMNCiAgICBzbW9vdGhfc2Nyb2xsOiB5ZXMNCiAgICB0aGVtZTogbHVtZW4NCiAgd29yZF9kb2N1bWVudDogDQogICAgdG9jOiB5ZXMNCiAgICB0b2NfZGVwdGg6IDQNCiAgICBmaWdfY2FwdGlvbjogeWVzDQogICAga2VlcF9tZDogeWVzDQogIHBkZl9kb2N1bWVudDogDQogICAgdG9jOiB5ZXMNCiAgICB0b2NfZGVwdGg6IDQNCiAgICBmaWdfY2FwdGlvbjogeWVzDQogICAgbnVtYmVyX3NlY3Rpb25zOiB5ZXMNCmVkaXRvcl9vcHRpb25zOiANCiAgY2h1bmtfb3V0cHV0X3R5cGU6IGNvbnNvbGUNCi0tLQ0KDQpgYGB7PWh0bWx9DQoNCjxzdHlsZSB0eXBlPSJ0ZXh0L2NzcyI+DQoNCi8qIENhc2NhZGluZyBTdHlsZSBTaGVldHMgKENTUykgaXMgYSBzdHlsZXNoZWV0IGxhbmd1YWdlIHVzZWQgdG8gZGVzY3JpYmUgdGhlIHByZXNlbnRhdGlvbiBvZiBhIGRvY3VtZW50IHdyaXR0ZW4gaW4gSFRNTCBvciBYTUwuIGl0IGlzIGEgc2ltcGxlIG1lY2hhbmlzbSBmb3IgYWRkaW5nIHN0eWxlIChlLmcuLCBmb250cywgY29sb3JzLCBzcGFjaW5nKSB0byBXZWIgZG9jdW1lbnRzLiAqLw0KDQpoMS50aXRsZSB7ICAvKiBUaXRsZSAtIGZvbnQgc3BlY2lmaWNhdGlvbnMgb2YgdGhlIHJlcG9ydCB0aXRsZSAqLw0KICBmb250LXNpemU6IDI0cHg7DQogIGNvbG9yOiBEYXJrUmVkOw0KICB0ZXh0LWFsaWduOiBjZW50ZXI7DQogIGZvbnQtZmFtaWx5OiAiR2lsbCBTYW5zIiwgc2Fucy1zZXJpZjsNCn0NCmg0LmF1dGhvciB7IC8qIEhlYWRlciA0IC0gZm9udCBzcGVjaWZpY2F0aW9ucyBmb3IgYXV0aG9ycyAgKi8NCiAgZm9udC1zaXplOiAyMHB4Ow0KICBmb250LWZhbWlseTogc3lzdGVtLXVpOw0KICBjb2xvcjogRGFya1JlZDsNCiAgdGV4dC1hbGlnbjogY2VudGVyOw0KfQ0KaDQuZGF0ZSB7IC8qIEhlYWRlciA0IC0gZm9udCBzcGVjaWZpY2F0aW9ucyBmb3IgdGhlIGRhdGUgICovDQogIGZvbnQtc2l6ZTogMThweDsNCiAgZm9udC1mYW1pbHk6IHN5c3RlbS11aTsNCiAgY29sb3I6IERhcmtCbHVlOw0KICB0ZXh0LWFsaWduOiBjZW50ZXI7DQp9DQpoMSB7IC8qIEhlYWRlciAxIC0gZm9udCBzcGVjaWZpY2F0aW9ucyBmb3IgbGV2ZWwgMSBzZWN0aW9uIHRpdGxlICAqLw0KICAgIGZvbnQtc2l6ZTogMjJweDsNCiAgICBmb250LWZhbWlseTogIlRpbWVzIE5ldyBSb21hbiIsIFRpbWVzLCBzZXJpZjsNCiAgICBjb2xvcjogbmF2eTsNCiAgICB0ZXh0LWFsaWduOiBjZW50ZXI7DQp9DQpoMiB7IC8qIEhlYWRlciAyIC0gZm9udCBzcGVjaWZpY2F0aW9ucyBmb3IgbGV2ZWwgMiBzZWN0aW9uIHRpdGxlICovDQogICAgZm9udC1zaXplOiAyMHB4Ow0KICAgIGZvbnQtZmFtaWx5OiAiVGltZXMgTmV3IFJvbWFuIiwgVGltZXMsIHNlcmlmOw0KICAgIGNvbG9yOiBuYXZ5Ow0KICAgIHRleHQtYWxpZ246IGxlZnQ7DQp9DQoNCmgzIHsgLyogSGVhZGVyIDMgLSBmb250IHNwZWNpZmljYXRpb25zIG9mIGxldmVsIDMgc2VjdGlvbiB0aXRsZSAgKi8NCiAgICBmb250LXNpemU6IDE4cHg7DQogICAgZm9udC1mYW1pbHk6ICJUaW1lcyBOZXcgUm9tYW4iLCBUaW1lcywgc2VyaWY7DQogICAgY29sb3I6IG5hdnk7DQogICAgdGV4dC1hbGlnbjogbGVmdDsNCn0NCg0KaDQgeyAvKiBIZWFkZXIgNCAtIGZvbnQgc3BlY2lmaWNhdGlvbnMgb2YgbGV2ZWwgNCBzZWN0aW9uIHRpdGxlICAqLw0KICAgIGZvbnQtc2l6ZTogMThweDsNCiAgICBmb250LWZhbWlseTogIlRpbWVzIE5ldyBSb21hbiIsIFRpbWVzLCBzZXJpZjsNCiAgICBjb2xvcjogZGFya3JlZDsNCiAgICB0ZXh0LWFsaWduOiBsZWZ0Ow0KfQ0KDQpib2R5IHsgYmFja2dyb3VuZC1jb2xvcjp3aGl0ZTsgfQ0KDQouaGlnaGxpZ2h0bWUgeyBiYWNrZ3JvdW5kLWNvbG9yOnllbGxvdzsgfQ0KDQpwIHsgYmFja2dyb3VuZC1jb2xvcjp3aGl0ZTsgfQ0KDQo8L3N0eWxlPg0KYGBgDQpgYGB7ciBzZXR1cCwgaW5jbHVkZT1GQUxTRX0NCiMgRGV0ZWN0LCBpbnN0YWxsLCBhbmQgbG9hZCBwYWNrYWdlcyBpZiBuZWVkZWQuDQppZiAoIXJlcXVpcmUoImtuaXRyIikpIHsNCiAgIGluc3RhbGwucGFja2FnZXMoImtuaXRyIikNCiAgIGxpYnJhcnkoa25pdHIpDQp9DQppZiAoIXJlcXVpcmUoImxlYWZsZXQiKSkgew0KICAgaW5zdGFsbC5wYWNrYWdlcygibGVhZmxldCIpDQogICBsaWJyYXJ5KGxlYWZsZXQpDQp9DQppZiAoIXJlcXVpcmUoIkVudlN0YXRzIikpIHsNCiAgIGluc3RhbGwucGFja2FnZXMoIkVudlN0YXRzIikNCiAgIGxpYnJhcnkoRW52U3RhdHMpDQp9DQppZiAoIXJlcXVpcmUoIk1BU1MiKSkgew0KICAgaW5zdGFsbC5wYWNrYWdlcygiTUFTUyIpDQogICBsaWJyYXJ5KE1BU1MpDQp9DQppZiAoIXJlcXVpcmUoInBoeXRvb2xzIikpIHsNCiAgIGluc3RhbGwucGFja2FnZXMoInBoeXRvb2xzIikNCiAgIGxpYnJhcnkocGh5dG9vbHMpDQp9DQppZighcmVxdWlyZSgiZHBseXIiKSkgew0KICAgaW5zdGFsbC5wYWNrYWdlcygiZHBseXIiKQ0KICAgbGlicmFyeShkcGx5cikNCn0NCmlmKCFyZXF1aXJlKCJ0aWR5dmVyc2UiKSkgew0KICAgaW5zdGFsbC5wYWNrYWdlcygidGlkeXZlcnNlIikNCiAgIGxpYnJhcnkodGlkeXZlcnNlKQ0KfQ0KaWYoIXJlcXVpcmUoIkdHYWxseSIpKSB7DQogICBpbnN0YWxsLnBhY2thZ2VzKCJHR2FsbHkiKQ0KICAgbGlicmFyeShHR2FsbHkpDQp9DQppZiAoIXJlcXVpcmUoImJvb3QiKSkgew0KICAgaW5zdGFsbC5wYWNrYWdlcygiYm9vdCIpDQogICBsaWJyYXJ5KGJvb3QpDQp9DQppZighcmVxdWlyZSgicGFuZGVyIikpIHsNCiAgIGluc3RhbGwucGFja2FnZXMoInBhbmRlciIpDQogICBsaWJyYXJ5KHBhbmRlcikNCn0NCmlmKCFyZXF1aXJlKCJtbGJlbmNoIikpIHsNCiAgIGluc3RhbGwucGFja2FnZXMoIm1sYmVuY2giKQ0KICAgbGlicmFyeShtbGJlbmNoKQ0KfQ0KaWYoIXJlcXVpcmUoInBzeWNoIikpIHsNCiAgIGluc3RhbGwucGFja2FnZXMoInBzeWNoIikNCiAgIGxpYnJhcnkocHN5Y2gpDQp9DQppZighcmVxdWlyZSgibHVicmlkYXRlIikpIHsNCiAgIGluc3RhbGwucGFja2FnZXMoImx1YnJpZGF0ZSIpDQogICBsaWJyYXJ5KGx1YnJpZGF0ZSkNCn0NCmlmKCFyZXF1aXJlKCJHR2FsbHkiKSkgew0KICAgaW5zdGFsbC5wYWNrYWdlcygiR0dhbGx5IikNCiAgIGxpYnJhcnkoR0dhbGx5KQ0KfQ0KaWYgKCFyZXF1aXJlKCJwUk9DIikpIHsNCiAgIGluc3RhbGwucGFja2FnZXMoInBST0MiKQ0KICAgbGlicmFyeShwUk9DKQ0KfQ0KaWYgKCFyZXF1aXJlKCJmb3JlY2FzdCIpKSB7DQogICBpbnN0YWxsLnBhY2thZ2VzKCJmb3JlY2FzdCIpDQogICBsaWJyYXJ5KGZvcmVjYXN0KQ0KfQ0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KGVjaG8gPSBUUlVFLCAgDQogICAgICAgICAgICAgICAgICAgd2FybmluZyA9IEZBTFNFLCAgIA0KICAgICAgICAgICAgICAgICAgIG1lc3NhZ2UgPSBGQUxTRSwgIA0KICAgICAgICAgICAgICAgICAgIHJlc3VsdHMgPSBUUlVFLCAgDQogICAgICAgICAgICAgICAgICAgY29tbWVudCA9IE5BICAgDQogICAgICAgICAgICAgICAgICAgICAgKSAgIA0KYGBgDQoNCg0KIyBJbnRyb2R1Y3Rpb24NCg0KRm9yIHRoaXMgcHJvamVjdCwgd2Ugd2lsbCBiZSBjcmVhdGluZyBhIFRpbWUgU2VyaWVzLiBUaGlzIHRpbWUgc2VyaWVzIGxvb2tzIGF0IHRoZSBhdmVyYWdlIG51bWJlciBvZiBhaXIgdHJhdmVsIHBhc3NlbmdlcnMgb24gYWxsIFUuUy4gZmxpZ2h0cy4gVGhlIHRpbWUgc2VyaWVzIHdlIHdpbGwgbG9vayBhdCB3aWxsIGluY2x1ZGUgdGhlIG51bWJlciBvZiBwYXNzZW5nZXJzIG9uIGJvdGggZG9tZXN0aWMgYW5kIGludGVybmF0aW9uYWwgZmxpZ2h0cy4gV2Ugd2lsbCBjcmVhdGUgYSBtb250aGx5IHRpbWUgc2VyaWVzIHdoaWNoIGxvb2tzIGF0IHRoZSBhdmVyYWdlIG51bWJlciBvZiBhaXIgdHJhdmVsIHBhc3NlbmdlcnMgYnkgbW9udGguIFRoaXMgdGltZSBzZXJpZXMgZGF0YSB3YXMgY29sbGVjdGVkIGZyb20gMjAwMyB0byAyMDIzLCB3aXRoIHRoZSBmaXJzdCBvYnNlcnZhdGlvbiBpbiBKYW51YXJ5IG9mIDIwMDMsIGFuZCB0aGUgZmluYWwgb2JzZXJ2YXRpb24gaW4gU2VwdGVtYmVyIDIwMjMuDQoNCldlIHdpbGwgc3BsaXQgdGhlIHRpbWUgc2VyaWVzIGRhdGEgdXAgaW50byBhIHRyYWluaW5nIGFuZCBhIHRlc3RuZyBkYXRhIHNldC4gQW5kIHRoZW4gd2UgY3JlYXRlIHNldmVyYWwgY2FuZGlkYXRlLCBleHBvbmVudGlhbCBzbW9vdGhpbmcgbW9kZWxzIGZvciBmb3JlY2FzdGluZy4gVGhlc2Ugd2lsbCBpbmNsdWRlIGEgc2ltcGxlIGV4cG9uZW50aWFsIG1vZGVsLCBzZXZlcmFsIEhvbHQgbW9kZWxzLCBhbmQgc2V2ZXJhbCBIb2x0LVdpbnRlcidzIG1vZGVscy4gV2Ugd2lsbCBzZWUgd2hpY2ggb2YgdGhlc2UgY2FuZGlkYXRlIG1vZGVscyBwcm92aWRlcyB0aGUgYmVzdCB1dGlsaXR5IGZvciBhbiBleHBvbmVudGlhbCBzbW9vdGhpbmcgbW9kZWwgb2Ygb3VyIHRpbWUgc2VyaWVzLiBXZSB3aWxsIGRldGVybWluZSB0aGUgYmVzdCBtb2RlbCBieSBzZWVpbmcgd2hpY2ggb25lIHJlZHVjZXMgdGhlIGVycm9ycyBhbmQgcHJvdmlkZXMgdGhlIGJlc3Qgb3ZlcmFsbCBhY2N1cmFjeS4gDQoNCg0KIyMgRGF0YSBEZXNjcmlwdGlvbg0KDQpJIGZvdW5kIHRoaXMgZGF0YSBzZXQgb24ga2FnZ2xlLmNvbSBvbiB0aGUgZm9sbG93aW5nIHdlYnBhZ2U6DQpodHRwczovL3d3dy5rYWdnbGUuY29tL2RhdGFzZXRzL3l5eGlhbi91LXMtYWlybGluZS10cmFmZmljLWRhdGE/c2VsZWN0PWFpcit0cmFmZmljLmNzdg0KDQpUaGlzIGRhdGEgc2V0IGxvb2tzIGF0IHRoZSBhdmVyYWdlIG51bWJlciBvZiBhaXIgdHJhdmVsIHBhc3NlbmdlcnMgYnkgbW9udGggZnJvbSAyMDAzIHRvIDIwMjMuIFRoZSBmaXJzdCBvYnNlcnZhdGlvbiBpbiB0aGlzIGRhdGEgc2V0IHdhcyBjb2xsZWN0ZWQgaW4gSmFudWFyeSAyMDAzLCBhbmQgdGhlIGZpbmFsIG9ic2VydmF0aW9uIGluIHRoaXMgZGF0YSBzZXQgd2FzIGNvbGxlY3RlZCBpbiBTZXB0ZW1iZXIgMjAyMy4gVGhpcyBkYXRhIHNldCBpbmNsdWRlcyB2YXJpYWJsZXMgd2hpY2ggcmVwcmVzZW50IHRoZSB0b3RhbCBudW1iZXIgb2YgcGFzc2VuZ2VycyBvbiBib3RoIGRvbWVzdGljIGFuZCBpbnRlcm5hdGlvbmFsIGZsaWdodHMgYnkgbW9udGguIEhvd2V2ZXIsIGZvciB0aGlzIHRpbWUgc2VyaWVzLCB3ZSB3aWxsIGxvb2sgc3BlY2lmaWNhbGx5IGF0IHRoZSB2YXJpYWJsZSB3aGljaCByZXByZXNlbnRzIHRoZSB0b3RhbCBudW1iZXIgb2YgcGFzc2VuZ2VycyBvbiBhbGwgZmxpZ2h0cywgYm90aCBkb21lc3RpYyBhbmQgaW50ZXJuYXRpb25hbC4gVGhpcyBkYXRhIGlzIHJlcHJlc2VudGF0aXZlIG9mIHBhc3NlbmdlcnMgb24gYWxsIFUuUy4gZmxpZ2h0cyBieSBtb250aC4gDQoNCldlIHdpbGwgcmVhZCBpbiB0aGUgZGF0YSBzZXQgZnJvbSBHaXRodWIgYW5kIHdlIHdpbGwgY2FsbCBpdCAiZmxpZ2h0Ii4gDQoNCmBgYHtyfQ0KZmxpZ2h0IDwtIHJlYWQuY3N2KCJodHRwczovL3Jhdy5naXRodWJ1c2VyY29udGVudC5jb20vSm9zaWVHYWxsb3AvU1RBMzIxL3JlZnMvaGVhZHMvbWFpbi9kYXRhc2V0L2FpciUyMHRyYWZmaWMuY3N2IikNCmBgYA0KDQpUaGlzIGRhdGEgc2V0IGNvbnRhaW5zIG1hbnkgdmFyaWFibGVzIHJlZ2FyZGluZyBhaXIgdHJhdmVsIGluZm9ybWF0aW9uLCBidXQgZm9yIHRoaXMgdGltZSBzZXJpZXMgd2UgYXJlIGp1c3QgaW50ZXJlc3RlZCBpbiBsb29raW5nIGF0IHRoZSBudW1iZXIgb2YgdGhlIHRvdGFsIGFpciB0cmF2ZWwgcGFzc2VuZ2Vycy4gVGhpcyBpcyByZXByZXNlbnRlZCBieSB0aGUgdmFyaWFibGUgUGF4LiBXZSB3YW50IHRvIGNyZWF0ZSBhIHRpbWUgc2VyaWVzIG9mIHRoZSB0b3RhbCBhaXIgdHJhdmVsIHBhc3NlbmdlcnMgYnkgdGhlIGRhdGUsIHNvIHdlIHdpbGwgb25seSBrZWVwIHRoZSB0aW1lIHNwZWNpZmljIHZhcmlhYmxlcywgWWVhciBhbmQgTW9udGgsIGFuZCB0aGUgUGF4IHZhcmlhYmxlLiBXZSB3aWxsIGNhbGwgdGhlIG5ldyBkYXRhIHNldCB3aXRoIG9ubHkgdGhlc2Ugc3BlY2lmaWMgdmFyaWFibGVzIHdlIGFyZSBpbnRlcmVzdGVkIGluICJmbGlnaHQxIi4NCg0KYGBge3J9DQpmbGlnaHQxIDwtIGZsaWdodCAlPiUNCiAgc2VsZWN0KFllYXIsIE1vbnRoLCBQYXgpDQpgYGANCg0KTm93LCB3ZSBoYXZlIGEgbmV3IGRhdGEgc2V0LCBmbGlnaHQxLCB3aXRoIG9ubHkgdGhlIHZhcmlhYmxlcyB3ZSBhcmUgaW50ZXJlc3RlZCBpbiBmb3Igb3VyIHRpbWUgc2VyaWVzIHByb2plY3QuDQoNCg0KIyMgVmFyaWFibGVzDQoNClRoZXJlIGFyZSB0aHJlZSB2YXJpYWJsZXMgZnJvbSB0aGUgb3JpZ2luYWwgZGF0YSBzZXQgd2hpY2ggd2Ugd2lsbCBiZSBpbnRlcmVzdGVkIGluIGZvciB0aGlzIHRpbWUgc2VyaWVzIHByb2plY3QuDQoNCiogWWVhcjogVGhlIHllYXIgb2Ygd2hpY2ggdGhlIG9ic2VydmF0aW9uIGlzIGZyb20uIFRoaXMgZGF0YSBzZXQgc3BhbnMgZnJvbSAyMDAzIHRvIDIwMjMuIA0KDQoqIE1vbnRoOiBUaGUgbW9udGggb2Ygd2hpY2ggdGhlIG9ic2VydmF0aW9uIGlzIGZyb20uIEdpdmVuIGFzIGEgdHdvIGRpZ2l0IG51bWJlciByZXByZXNlbnRpbmcgdGhlIG1vbnRoLiBGb3IgZXhhbXBsZSwgMDEgcmVwcmVzZW50cyBKYW51YXJ5LCAwMiByZXByZXNlbnRzIEZlYnJ1YXJ5LCBhbmQgc28gb24uDQoNCiogUGF4OiBUaGUgdG90YWwgbnVtYmVyIG9mIGFpciB0cmF2ZWwgcGFzc2VuZ2VycyBmb3IgYSBnaXZlbiBvYnNlcnZhdGlvbnMuIFRoaXMgaW5jbHVkZXMgYWlyIHBhc3NlbmdlcnMgb24gYm90aCBkb21lc3RpYyBhbmQgaW50ZXJuYXRpb25hbCBmbGlnaHRzLiANCg0KRHVyaW5nIG91ciBleHBsb3JhdG9yeSBkYXRhIGFuYWx5c2lzLCB3ZSB3aWxsIGNyZWF0ZSBhIG5ldyB2YXJpYWJsZSBjYWxsZWQgRGF0ZSB3aGljaCB3aWxsIGNvbWJpbmUgdGhlIHllYXIgYW5kIHRoZSBtb250aCB2YXJpYWJsZXMgdG8gZ2V0IGp1c3Qgb25lLCBzaW5nbGUgdmFyaWFibGUgdG8gcmVwcmVzZW50IHRoZSBkYXRlIG9mIHdoaWNoIGFuIG9ic2VydmF0aW9uIG9jY3VycmVkLiBUaGUgZGF0ZSB2YXJpYWJsZSB3ZSB3aWxsIGNyZWF0ZSB3aWxsIGJlIGdpdmVuIGluIHRoZSBmb3JtYXQgb2YgWWVhci1Nb250aC4gDQoNCg0KDQoNCiMgRXhwbG9yYXRvcnkgRGF0YSBBbmFseXNpcw0KDQpGaXJzdCwgbGV0J3MgZW5zdXJlIHRoYXQgdGhlcmUgYXJlIG5vdCBhbnkgbWlzc2luZyB2YXJpYWJsZXMgaW4gdGhpcyBkYXRhIHNldC4gDQpgYGB7cn0NCmNvbFN1bXMoaXMubmEoZmxpZ2h0MSkpDQpgYGANCg0KQXMgd2UgY2FuIHNlZSwgdGhlcmUgYXJlIHplcm8gbWlzc2luZyB2YWx1ZXMgaW4gb3VyIGRhdGEgc2V0LCBzbyB0aGF0IG1lYW5zIHdlIGRvIG5vdCBoYXZlIHRvIHdvcnJ5IGFib3V0IGZpbGxpbmcgaW4gYW55IG1pc3Npbmcgb2JzZXJ2YXRpb25zLiBXZSBjYW4gcHJvY2VlZCB3aXRoIG91ciB0aW1lIHNlcmllcyBwcm9qZWN0LiAgDQoNCk5leHQsIHdlIHdpbGwgY29tYmluZSB0aGUgWWVhciBhbmQgTW9udGggdmFyaWFibGVzIGludG8gb25lIHZhcmlhYmxlIGNhbGxlZCBEYXRlIHdoaWNoIGlzIGdpdmVuIGFzIHllYXIgYW5kIG1vbnRoIGNvbWJpbmVkLCBpbiB0aGUgZm9ybWF0IG9mIFllYXItTW9udGguIFdlIHdpbGwgY3JlYXRlIGEgbmV3IGRhdGEgc2V0IHdpdGggdGhlIGNvbWJpbmVkIERhdGUgdmFyaWFibGUgYW5kIHdlIHdpbGwgY2FsbCB0aGlzIG5ldyBkYXRhIHNldCAiZmxpZ2h0MiIuIA0KDQpgYGB7cn0NCmZsaWdodDIgPC0gZmxpZ2h0MSAlPiUNCiAgbXV0YXRlKERhdGUgPSBwYXN0ZShZZWFyLCBzcHJpbnRmKCIlMDJkIiwgTW9udGgpLCBzZXAgPSAiLSIpKQ0KZmxpZ2h0MiA8LSBzZWxlY3QoZmxpZ2h0MiwgLTEsLTIpDQpgYGANCg0KTm93LCB3ZSBoYXZlIGEgZGF0YSBzZXQgImZsaWdodDIiIHdpdGgganVzdCB0aGUgRGF0ZSwgZ2l2ZW4gaW4gYSBZZWFyLU1vbnRoIGZvcm1hdCwgYW5kIHRoZSBQYXggdmFyaWFibGUgcmVwcmVzZW50aW5nIHRoZSB0b3RhbCBudW1iZXIgb2YgYWlyIHRyYXZlbCBwYXNzZW5nZXJzLiANCg0KT25lIHRoaW5nIEkgbm90aWNlZCBpcyB0aGF0IHRoZSBQYXggdmFyaWFibGUgaXMgaW5jb3JyZWN0bHkgZ2l2ZW4gYXMgYSBjaGFyYWN0ZXIgdmFyaWFibGUgd2hlbiBpdCBzaG91bGQgcmVhbGx5IGJlIGEgbnVtZXJpYyB2YXJpYWJsZSBzaW5jZSBpdCByZXByZXNlbnRzIHRoZSB0b3RhbCBudW1iZXIgb2YgYWlyIHRyYXZlbCBwYXNzZW5nZXJzLiBXZSB3aWxsIGNoYW5nZSB0aGUgdmFyaWFibGUgdHlwZSBvZiB0aGUgUGF4IHZhcmlhYmxlIGZyb20gYSBjaGFyYWN0ZXIgdG8gYSBudW1lcmljIHZhcmlhYmxlIGluIG9yZGVyIHRvIGZpeCB0aGlzIGlzc3VlLiBXZSB3aWxsIHJlbW92ZSB0aGUgY29tbWFzIGZyb20gdGhlIFBheCB2YXJpYWJsZSBiZWZvcmUgY29udmVydGluZyBpdCB0byBhIG51bWVyaWMgdmFyaWFibGUgdG8gYXZvaWQgYW55IHByb2JsZW1zIHdpdGggdGhlIGNvbnZlcnNpb24gb2YgdGhlIHZhcmlhYmxlIHR5cGUuDQoNCmBgYHtyfQ0KZmxpZ2h0MiRQYXggPC0gZ3N1YigiLCIsICIiLCBmbGlnaHQyJFBheCkgDQpmbGlnaHQyJFBheCA8LSBhcy5udW1lcmljKGZsaWdodDIkUGF4KQ0KYGBgDQoNCk5vdyB3ZSBoYXZlIHRoZSBwcm9wZXIgZGF0YSBzZXQgd2UgY2FuIHVzZSB0byBjcmVhdGUgdGhlIHRpbWUgc2VyaWVzLiBUaGlzIGRhdGEgc2V0IHByb3ZpZGVzIG1vbnRobHkgYXZlcmFnZXMgZm9yIHRoZSBudW1iZXIgb2YgYWlyIHRyYXZlbCBwYXNzZW5nZXJzIGZvciBhbGwgZG9tZXN0aWMgYW5kIGludGVybmF0aW9uYWwgZmxpZ2h0cy4gDQoNCg0KIyMgVGltZSBTZXJpZXMgUGxvdA0KDQpOb3csIHdlIHdpbGwgY3JlYXRlIGEgdGltZSBzZXJpZXMgb2JqZWN0IGZyb20gb3VyIGZsaWdodCBkYXRhIGFuZCBwbG90IGl0IHRvIGhlbHAgdmlzdWFsaXplIGFueSBwb3RlbnRpYWwgdHJlbmRzIHRoYXQgbWF5IGJlIG9jY3VycmluZyB3aXRoaW4gdGhpcyB0aW1lIHNlcmllcyBkYXRhIHNldC4gV2Ugd2lsbCBjYWxsIHRoaXMgdGltZSBzZXJpZXMgb2JqZWN0ICJmbGlnaHQudHMiLiBTaW5jZSB3ZSBhcmUgY3JlYXRpbmcgYSBtb250aGx5IHRpbWUgc2VyaWVzIGxvb2tpbmcgYXQgdGhlIGF2ZXJhZ2UgbnVtYmVyIG9mIGFpciB0cmF2ZWwgcGFzc2VuZ2VycyBieSBtb250aCwgb3VyIGZyZXF1ZW5jeSB3aWxsIGJlIDEyLiANCg0KYGBge3J9DQpmbGlnaHQudHMgPC0gdHMoZmxpZ2h0MiRQYXgsIHN0YXJ0ID0gYygyMDAzLCAxKSwgZnJlcXVlbmN5ID0gMTIpDQpwbG90KGZsaWdodC50cywgbWFpbiA9ICJNb250aGx5IEF2ZXJhZ2UgQWlyIFRyYXZlbCBQYXNzZW5nZXJzIGZyb20gMjAwMyB0byAyMDIzIiwgeGxhYiA9ICJZZWFyIiwgeWxhYiA9ICJBaXIgVHJhdmVsIFBhc3NlbmdlcnMiKQ0KYGBgDQoNCkxvb2tpbmcgYXQgdGhlIHRpbWUgc2VyaWVzIHBsb3QsIHdlIGNhbiBzZWUgc29tZSBub3RhYmxlIG9jY3VycmVuY2VzIHdpdGhpbiBvdXIgZGF0YS4gVGhlcmUgaXMgY2VydGFpbmx5IHNvbWUgc29ydCBvZiBzZWFzb25hbGl0eSBnb2luZyBvbiB3aXRoaW4gb3VyIHRpbWUgc2VyaWVzIHdoaWNoIGNhbiBiZSBzZWVuIGJ5IGhvdyB0aGUgcGxvdCBoYXMgYSBwYXR0ZXJuIHdoaWNoIHJlcGVhdHMgYWZ0ZXIgYSBjZXJ0YWluIGFtb3VudCBvZiB0aW1lLiBJdCBsb29rcyBsaWtlIHRoaXMgdGltZSBzZXJpZXMgbWlnaHQgaGF2ZSBhbiBhbm51YWwgc2Vhc29uYWxpdHksIHdpdGggdGhpcyByZXBldGl0aW9uIG9jY3VycmluZyBhZnRlciBhIHllYXIgaGFzIGdvbmUgYnkuIFRoaXMgd291bGQgbWFrZSBzZW5zZSB0aGF0IHRoZSBudW1iZXIgb2YgYWlyIHRyYXZlbCBwYXNzZW5nZXJzIHdvdWxkIGhhdmUgYW4gYW5udWFsIHNlYXNvbmFsaXR5LCBiZWNhdXNlIG1vcmUgcGVvcGxlIGxpa2VseSB0cmF2ZWwgZHVyaW5nIHRoZSBzdW1tZXIgbW9udGhzIGR1ZSB0byB0aGUgaWRlYWwgd2VhdGhlciBhbmQgZm9yIGZhbWlsaWVzIHRoaXMgd291bGQgbWVhbiB0aGVpciBjaGlsZHJlbiB3b3VsZCBiZSBvbiBzdW1tZXIgYnJlYWsgd2hpY2ggd291bGQgbWFrZSBoYXZpbmcgYSB2YWNhdGlvbiBkdXJpbmcgdGhlIHN1bW1lciBhbiBvcHRpbWFsIHRpbWluZy4gSXQgd291bGQgbWFrZSBzZW5zZSB0aGF0IHRoZSBudW1iZXIgb2YgYWlyIHRyYXZlbCBwYXNzZW5nZXJzIHdvdWxkIHBlYWsgZHVyaW5nIHRoZSBzdW1tZXIgbW9udGhzLCBhbmQgdGhlbiBkcm9wIGJhY2sgZG93biB1bnRpbCB0aGVyZSBpcyBhbm90aGVyIHNsaWdodCByaXNlIGFyb3VuZCB0aGUgaG9saWRheSBtb250aHMgaW4gdGhlIHdpbnRlciB0aW1lIGR1ZSB0byBwZW9wbGUgdHJhdmVsbGluZyB0byBzcGVuZCB0aGUgaG9saWRheXMgd2l0aCB0aGVpciBmYW1pbHkuIE92ZXJhbGwsIGFuIGFubnVhbCBzZWFzb25hbGl0eSB3b3VsZCBtYWtlIHNlbnNlIGZvciBhIHRpbWUgc2VyaWVzIG9uIHRoZSBudW1iZXIgb2YgYWlyIHRyYXZlbCBwYXNzZW5nZXJzLiANCg0KQW5vdGhlciBub3RhYmxlIG9jY3VycmVuY2Ugd2l0aGluIHRoaXMgdGltZSBzZXJpZXMgaXMgdGhhdCB0aGVyZSBhcHBlYXJzIHRvIGJlIGEgdHJlbmQgb2Ygc2xpZ2h0IG92ZXJhbGwgaW5jcmVhc2UgaW4gdGhlIG51bWJlciBvZiBhaXIgdHJhdmVsIHBhc3NlbmdlcnMgZnJvbSB0aGUgc3RhcnQgb2YgdGhlIHRpbWUgc2VyaWVzIHVwIHVudGlsIHRoZSBlbmQuIFRoZXJlIGlzIGFuIGVzcGVjaWFsbHkgbm90aWNlYWJsZSB0cmVuZCBvZiBvdmVyYWxsIGluY3JlYXNlIGZyb20gYXJvdW5kIDIwMTAgdXAgdW50aWwgMjAxOS4gV2UgY2FuIHNlZSB0aGF0IHRoZXJlIGlzIGFuIGluY3JlZGlibHkgbWFzc2l2ZSBkZWNyZWFzZSBpbiB0aGUgbnVtYmVyIG9mIGFpciB0cmF2ZWwgcGFzc2VuZ2VycyBhcm91bmQgMjAyMC4gVGhpcyBjYW4gYmUgYXR0cmlidXRlZCB0byB0aGUgdHJhdmVsIHJlc3RyaWN0aW9ucyB3aGljaCB3ZXJlIHB1dCBpbiBwbGFjZSBkdXJpbmcgdGhlIGVhcmx5IGRheXMgb2YgdGhlIGNvdmlkIHBhbmRlbWljLiBUaGlzIHdvdWxkIGV4cGxhaW4gd2h5IHRoZXJlIGlzIHN1Y2ggYSBkcmFzdGljIGRlY2xpbmUgaW4gdGhlIG51bWJlciBvZiBhaXIgdHJhdmVsIHBhc3NlbmdlcnMgc2VlbiBpbiB0aGUgeWVhciAyMDIwLiBBZnRlciB0aGlzIGRlY2xpbmUgaW4gMjAyMCwgd2UgY2FuIHNlZSB0aGF0IHRoZSBudW1iZXIgb2YgYWlyIHRyYXZlbCBwYXNzZW5nZXJzIGJlZ2lucyB0byBncmFkdWFsbHkgaW5jcmVhc2Ugb3ZlciB0aGUgZm9sbG93aW5nIHllYXJzLCBhbmQgaXQgYXBwZWFycyB0aGF0IHRoZSBudW1iZXJzIGF0IHRoZSBlbmQgb2YgdGhlIHRpbWUgc2VyaWVzIGluIDIwMjMgYXJlIGZhaXJseSBzaW1pbGFyIHRvIHdoYXQgdGhleSB3ZXJlIHJpZ2h0IGJlZm9yZSB0aGUgbWFqb3IgZGVjbGluZSBzZWVuIGluIDIwMjAuIA0KDQoNCg0KDQojIERhdGEgU3BsaXQNCg0KV2Ugd2lsbCBzcGxpdCBvdXIgdGltZSBzZXJpZXMgZGF0YSBpbnRvIHR3byBkYXRhIHNldHMsIG9uZSBmb3IgdHJhaW5pbmcsIGFuZCBvbmUgZm9yIHRlc3RpbmcuIFNpbmNlIHdlIGhhdmUgYSBtb250aGx5IHRpbWUgc2VyaWVzLCB3ZSB3aWxsIHVzZSB0aGUgMTIgbW9zdCByZWNlbnQgb2JzZXJ2YXRpb25zIGZvciB0aGUgdGVzdGluZyBkYXRhIHNldC4gVGhlIHJlc3Qgb2YgdGhlIG9ic2VydmF0aW9ucyB3aWxsIGJlIHVzZWQgZm9yIHRoZSB0cmFpbmluZyBkYXRhIHNldC4gV2Ugd2lsbCBhbHNvIGNyZWF0ZSBhIHRpbWUgc2VyaWVzIG9iamVjdCBmb3IganVzdCB0aGUgdHJhaW5pbmcgZGF0YSBzZXQuIFdlIHdpbGwgY2FsbCB0aGlzIHRpbWUgc2VyaWVzIG9iamVjdCAiZmxpZ2h0LnRzMSIuDQoNCmBgYHtyfQ0KdGVzdC5mbGlnaHQgPC0gZmxpZ2h0MiRQYXhbMjM4OjI0OV0NCnRyYWluLmZsaWdodCA8LSBmbGlnaHQyJFBheFsxOjIzOF0NCmZsaWdodC50czEgPC0gdHMoZmxpZ2h0MiRQYXhbMToyMzhdLCBzdGFydCA9IGMoMjAwMywgMSksIGZyZXF1ZW5jeSA9IDEyKQ0KYGBgDQoNCk5vdyB3ZSBoYXZlIHNwbGl0IG91ciB0aW1lIHNlcmllcyBkYXRhIHNldCB1cCBpbnRvIGEgdHJhaW5pbmcgYW5kIGEgdGVzdGluZyBkYXRhIHNldC4gV2Ugd2lsbCB1c2UgdGhlIHRyYWluaW5nIGRhdGEgc2V0IHRvIHRyYWluIHRoZSBzbW9vdGhpbmcgbW9kZWxzIHdlIHdpbGwgY3JlYXRlLiBXZSB3aWxsIHVzZSB0aGUgdGVzdGluZyBkYXRhIHNldCB0byBpZGVudGlmeSB3aGljaCBvZiB0aGVzZSBzbW9vdGhpbmcgbW9kZWxzIHdlIHdpbGwgY3JlYXRlIGlzIHRoZSBiZXN0IG9uZSB0byB1c2UuIFNvLCB3ZSB3aWxsIG5leHQgYmVnaW4gd2l0aCBjcmVhdGluZyB0aGVzZSBzbW9vdGhpbmcgbW9kZWxzIGFuZCB3ZSB3aWxsIHVzZSB0aGUgdHJhaW5pbmcgYW5kIHRlc3RpbmcgZGF0YSBzZXRzIHRvIGhlbHAgdXMgd2l0aCBidWlsZGluZyBlYWNoIG9mIHRoZXNlIG1vZGVscyBhbmQgdGhlbiBkZXRlcm1pbmluZyB3aGljaCBtb2RlbCBpcyB0aGUgYmVzdCBvbmUgdG8gdXNlLiANCg0KDQoNCg0KIyBTbW9vdGhpbmcgTW9kZWxzDQoNCldlIHdpbGwgbm93IGJlZ2luIHdpdGggYnVpbGRpbmcgdGhlIHNtb290aGluZyBtb2RlbHMgc28gd2UgY2FuIHVsdGltYXRlbHkgZGV0ZXJtaW5lIHdoaWNoIG9uZSBkb2VzIHRoZSBiZXN0IGFuZCB3b3VsZCBiZSB0aGUgYmVzdCB0byB1c2UuIFdlIHdpbGwgY3JlYXRlIHRocmVlIGRpZmZlcmVudCB0eXBlcyBvZiBzbW9vdGhpbmcgbW9kZWxzLiBUaGVzZSBkaWZmZXJlbnQgbW9kZWxzIHdpbGwgaW5jbHVkZSBhIHNpbXBsZSBleHBvbmVudGlhbCBzbW9vdGhpbmcgbW9kZWwsIEhvbHQgbW9kZWxzIChhZGRpdGl2ZSBhbmQgd2l0aCBhIHBvc3NpYmxlIGRhbXBlZCBwYXR0ZXJuKSwgYW5kIEhvbHQtV2ludGVyJ3MgbW9kZWxzIChhZGRpdGl2ZSBhbmQgbXVsdGlwbGljYXRpdmUgc2Vhc29uYWxpdHkgd2l0aCBhIHBvc3NpYmxlIGRhbXBlZCBwYXR0ZXJuKS4NCg0KDQojIyBTaW1wbGUgRXhwb25lbnRpYWwgU21vb3RoaW5nIE1vZGVsDQoNCkZpcnN0LCB3ZSB3aWxsIGJlZ2luIHdpdGggY3JlYXRpbmcgdGhlIHNpbXBsZSBleHBvbmVudGlhbCBzbW9vdGhpbmcgbW9kZWwuIFdlIHdpbGwgY2FsbCB0aGlzIHNpbXBsZSBleHBvbmVudGlhbCBzbW9vdGhpbmcgbW9kZWwgImZpdDEiLg0KDQpgYGB7cn0NCiMgU2ltcGxlIEV4cG9uZW50aWFsIFNtb290aGluZyBNb2RlbA0KZml0MSA8LSBzZXMoZmxpZ2h0LnRzMSwgaCA9IDEyKQ0KYGBgDQoNCk5vdyB3ZSBoYXZlIGNyZWF0ZWQgb3VyIHNpbXBsZSBleHBvbmVudGlhbCBzbW9vdGhpbmcgbW9kZWwuDQoNCg0KIyMgSG9sdCBNb2RlbHMNCg0KTmV4dCwgd2Ugd2lsbCBjcmVhdGUgdGhlIEhvbHQgbW9kZWxzLiBXZSB3aWxsIHVzZSB0aHJlZSBkaWZmZXJlbnQga2luZHMgb2YgSG9sdCBtb2RlbHMuIFRoZSBmaXJzdCBvZiBvdXIgSG9sdCBtb2RlbHMgd2lsbCBiZSBhIGxpbmVhciBIb2x0IG1vZGVsLCBhbmQgd2Ugd2lsbCBjYWxsIHRoaXMgImZpdDIiLiBPdXIgbmV4dCBIb2x0IG1vZGVsIHdpbGwgYmUgYW4gYWRkaXRpdmUgSG9sdCBtb2RlbCB3aXRoIGEgcG9zc2libGUgZGFtcGVkIHBhdHRlcm4sIGFuZCB0aGlzIHdpbGwgYmUgY2FsbGVkICJmaXQzIi4gT3VyIGxhc3QgSG9sdCBtb2RlbCB3aWxsIGJlIGFuIGV4cG9uZW50aWFsIEhvbHQgbW9kZWwgd2l0aCBhIHBvc3NpYmxlIGRhbXBlZCBwYXR0ZXJuLCBhbmQgdGhpcyB3aWxsIGJlIGNhbGxlZCAiZml0NCIuIA0KDQpgYGB7cn0NCiMgSG9sdCBMaW5lYXIgTW9kZWwNCmZpdDIgPC0gaG9sdChmbGlnaHQudHMxLCBpbml0aWFsID0gIm9wdGltYWwiLCBoID0gMTIpICAgICAgIA0KDQojIEhvbHQgQWRkaXRpdmUgTW9kZWwgd2l0aCBhIFBvc3NpYmxlIERhbXBlZCBQYXR0ZXJuIA0KZml0MyA8LSBob2x0KGZsaWdodC50czEsIGRhbXBlZCA9IFRSVUUsIGggPSAxMikgICAgICAgICAgICAgICAgICANCg0KIyBIb2x0IEV4cG9uZW50aWFsIE1vZGVsIHdpdGggYSBQb3NzaWJsZSBEYW1wZWQgUGF0dGVybg0KZml0NCA8LSBob2x0KGZsaWdodC50czEsIGV4cG9uZW50aWFsID0gVFJVRSwgZGFtcGVkID0gVFJVRSwgaCA9IDEyKSANCmBgYA0KDQpOb3cgd2UgaGF2ZSBzdWNjZXNzZnVsbHkgY3JlYXRlZCBvdXIgSG9sdCBtb2RlbHMuIA0KDQoNCiMjIEhvbHQtV2ludGVyJ3MgTW9kZWxzDQoNCkxhc3RseSwgd2Ugd2lsbCBjcmVhdGUgb3VyIEhvbHQgV2ludGVyJ3MgbW9kZWxzLiBXZSB3aWxsIHVzZSBmb3VyIGRpZmZlcmVudCBraW5kcyBvZiBIb2x0LVdpbnRlcidzIG1vZGVscy4gVGhlIGZpcnN0IG9mIHRoZXNlIHdpbGwgYmUgYSBIb2x0LVdpbnRlcidzIGFkZGl0aXZlIG1vZGVsLCBhbmQgdGhpcyB3aWxsIGJlIGNhbGxlZCAiZml0NSIuIFRoZSBuZXh0IHdpbGwgYmUgYSBIb2x0LVdpbnRlcidzIG11bHRpcGxpY2F0aXZlIG1vZGVsLCBhbmQgdGhpcyB3aWxsIGJlIGNhbGxlZCAiZml0NiIuIFRoZSBuZXh0IG9uZSBhZnRlciB3aWxsIGJlIGEgSG9sdC1XaW50ZXIncyBhZGRpdGl2ZSBtb2RlbCB3aXRoIGEgcG9zc2libGUgZGFtcGVkIHBhdHRlcm4sIGFuZCB0aGlzIHdpbGwgYmUgY2FsbGVkICJmaXQ3Ii4gVGhlIGxhc3Qgb2YgdGhlc2UgbW9kZWxzIHdpbGwgYmUgYSBIb2x0LVdpbnRlcidzIG11bHRpcGxpY2F0aXZlIG1vZGVsIHdpdGggYSBwb3NzaWJsZSBkYW1wZWQgcGF0dGVybiwgYW5kIHRoaXMgd2lsbCBiZSBjYWxsZWQgImZpdDgiLg0KDQpgYGB7cn0NCiMgSG9sdC1XaW50ZXIncyBBZGRpdGl2ZSBNb2RlbA0KZml0NSA8LSBodyhmbGlnaHQudHMxLCBoID0gMTIsIHNlYXNvbmFsID0gImFkZGl0aXZlIikgICAgIA0KDQojIEhvbHQtV2ludGVyJ3MgTXVsdGlwbGljYXRpdmUgTW9kZWwNCmZpdDYgPC0gaHcoZmxpZ2h0LnRzMSwgaCA9IDEyLCBzZWFzb25hbCA9ICJtdWx0aXBsaWNhdGl2ZSIpDQoNCiMgSG9sdC1XaW50ZXIncyBBZGRpdGl2ZSBNb2RlbCB3aXRoIGEgUG9zc2libGUgRGFtcGVkIFBhdHRlcm4NCmZpdDcgPC0gaHcoZmxpZ2h0LnRzMSwgaCA9IDEyLCBzZWFzb25hbCA9ICJhZGRpdGl2ZSIsIGRhbXBlZD1UUlVFKQ0KDQojIEhvbHQtV2ludGVyJ3MgTXVsdGlwbGljYXRpdmUgTW9kZWwgd2l0aCBhIFBvc3NpYmxlIERhbXBlZCBQYXR0ZXJuDQpmaXQ4IDwtIGh3KGZsaWdodC50czEsIGggPSAxMiwgc2Vhc29uYWwgPSAibXVsdGlwbGljYXRpdmUiLCBkYW1wZWQ9VFJVRSkNCmBgYA0KDQpOb3cgd2UgaGF2ZSBzdWNjZXNzZnVsbHkgY3JlYXRlZCBhbGwgb2Ygb3VyIEhvbHQtV2ludGVyJ3MgbW9kZWxzLiANCg0KDQoNCg0KIyBBY2N1cmFjeSBNZWFzdXJlcw0KDQpOb3cgdGhhdCB3ZSBoYXZlIGNyZWF0ZWQgdmFyaW91cyBtb2RlbHMgdG8gdHJ5IG91dCwgaW5jbHVkaW5nIGEgc2ltcGxlIGV4cG9uZW50aWFsIG1vZGVsLCBIb2x0IG1vZGVscywgYW5kIEhvbHQtV2ludGVyJ3MgbW9kZWxzLCB3ZSB3aWxsIHVzZSBhY2N1cmFjeSBtZWFzdXJlcyB0byBjb21wYXJlIGFsbCBvZiB0aGVzZSBkaWZmZXJlbnQgbW9kZWxzLiBUaGVzZSBhY2N1cmFjeSBtZWFzdXJlcyB3aWxsIGJlIGJhc2VkIHVwb24gdGhlIHRyYWluaW5nIGRhdGEgc2V0IHRoYXQgd2UgY3JlYXRlZCBmcm9tIG91ciB0aW1lIHNlcmllcyBkYXRhLiANCg0KYGBge3J9DQphY2N1cmFjeS50YWJsZSA9IHJvdW5kKHJiaW5kKGFjY3VyYWN5KGZpdDEpLCBhY2N1cmFjeShmaXQyKSwgYWNjdXJhY3koZml0MyksIGFjY3VyYWN5KGZpdDQpLCBhY2N1cmFjeShmaXQ1KSwgYWNjdXJhY3koZml0NiksIGFjY3VyYWN5KGZpdDcpLCBhY2N1cmFjeShmaXQ4KSksIDQpDQpyb3cubmFtZXMoYWNjdXJhY3kudGFibGUpPWMoIlNFUyIsIkhvbHQgTGluZWFyIiwiSG9sdCBBZGQuIERhbXBlZCIsICJIb2x0IE11bHQuIERhbXBlZCIsICJIVyBBZGQuIiwiSFcgTXVsdC4iLCJIVyBBZGQuIERhbXBlZCIsICJIVyBNdWx0LiBEYW1wZWQiKQ0KDQprYWJsZShhY2N1cmFjeS50YWJsZSwgY2FwdGlvbiA9ICJBY2NjdXJhY3kgTWVhc3VyZXMgb2YgdGhlIFZhcmlvdXMgU21vb3RoaW5nIE1vZGVscyBCYXNlZCB1cG9uIHRoZSBUcmFpbmluZyBEYXRhIFNldCIpDQpgYGANCg0KVG8gaW50ZXJwcmV0IG91ciBhY2N1cmFjeSB0YWJsZSwgd2UgaGF2ZSBzZXZlcmFsIG1lYXN1cmVzIG9mIGFjY3VyYWN5IHdlIGxvb2tlZCBhdC4gVGhlIE1FLCBvciBtZWFuIGVycm9ycywgcmVwcmVzZW50cyBob3cgZmFyIG9mZiB0aGUgcHJlZGljdGlvbnMgYXJlIGZyb20gdGhlaXIgYWN0dWFsIHZhbHVlcy4gVGhlIEhvbHQgQWRkLiBEYW1wZWQgYW5kIEhvbHQgTXVsdC4gRGFtcGVkIGhhdmUgdGhlIHNtYWxsZXN0IGFic29sdXRlIHZhbHVlIG9mIHRoZWlyIE1FLiBOZXh0LCB3ZSBoYXZlIFJNU0UsIE1BRSwgYW5kIE1BUEUsIGFsbCBvZiB3aGljaCBhIGxvd2VyIHZhbHVlIGlzIGlkZWFsIGJlY2F1c2UgaXQgaW5kaWNhdGVzIHRoZSBsZWFzdCBlcnJvcnMuIEZyb20gdGhlc2UgYWNjdXJhY3kgbWVhc3VyZW1lbnRzLCB0aGUgSFcgQWRkLiwgYW5kIHRoZSBIVy4gQWRkLiBEYW1wZWQgc3RhbmQgb3V0IGZvciBoYXZpbmcgbm90YWJseSBsb3dlciB2YWx1ZXMgdGhhbiBhbnkgb2YgdGhlIG90aGVyIG1vZGVscyBkby4gRm9yIHRoZSBNQVNFIG1lYXN1cmVtZW50LCBhIHZhbHVlIGNsb3Nlc3QgdG8gemVybyBpcyBpZGVhbC4gVGhlIEhXLiBBZGQgbW9kZWwgaGFzIHRoZSBjbG9zZXN0IE1BU0UgdG8gemVybywgbWFraW5nIHRoaXMgb25jZSBhZ2FpbiBzZWVtIGxpa2UgYSBzdHJvbmcgbW9kZWwuIExhc3RseSwgZm9yIHRoZSBBQ0YxIG1lYXN1cmVtZW50cywgYSB2YWx1ZSBjbG9zZXN0IHRvIHplcm8gaXMgaWRlYWwgZm9yIGFjY3VyYWN5LiBGcm9tIG91ciBtb2RlbHMsIHRoZSBIb2x0IExpbmVhciBtb2RlbCBoYXMgYW4gQUNGMSB0aGF0IGlzIGNsb3Nlc3QgdG8gemVyby4NCg0KT3ZlcmFsbCwgdGhlIEhvbHQtV2ludGVyJ3MgQWRkaXRpdmUgbW9kZWwgc3Rvb2Qgb3V0IGZvciBzaG93aW5nIGlkZWFsIHBlcmZvcm1hbmNlIGluIHRoZSBtb3N0IGFjY3VyYWN5IG1lYXN1cmVzIG9mIGFsbCBvZiB0aGUgbW9kZWxzLiBUaGlzIEhvbHQtV2ludGVyJ3MgQWRkaXRpdmUgbW9kZWwgaGFkIGxvdyBSTVNFLCBNQUUsIGFuZCBNQVBFLCBhcyB3ZWxsIGFzIGEgTUFTRSBjbG9zZXN0IHRvIHplcm8uIFNpbmNlIHRoZSBIb2x0LVdpbnRlcidzIEFkZGl0aXZlIG1vZGVsIHN0b29kIG91dCBpbiBtb3JlIGFjY3VyYWN5IG1lYXN1cmVtZW50cyB0aGFuIGFueSBvZiB0aGUgb3RoZXIgbW9kZWxzLCB3ZSB3aWxsIGNob29zZSB0aGlzIHNtb290aGluZyBtb2RlbCBhcyB0aGUgaWRlYWwgbW9kZWwgaW4gdGVybXMgb2YgcGVyZm9ybWFuY2UuIA0KDQoNCg0KDQojIFNlcmlhbCBQbG90IG9mIHRoZSBEYXRhDQoNCldlIHdpbGwgY3JlYXRlIGEgc2VyaWFsIHBsb3Qgb2YgdGhlIGhpc3RvcmljYWwgZGF0YSwgd2hpY2ggaXMgdGhlIGRhdGEgdGhhdCB3YXMgdXNlZCBmb3IgdGhlIHRyYWluaW5nIGRhdGEgc2V0LiBUaGlzIHdpbGwgYWxsb3cgdXMgdG8gZm9yZWNhc3QgdGhlIHZhbHVlcyBhbmQgdmlzdWFsaXplIHRoaXMgZm9yZWNhc3QuDQoNCldlIHdpbGwgY3JlYXRlIHR3byBzZXJpYWwgcGxvdHMsIG9uZSB3aWxsIGJlIGZvciB0aGUgbm9uLXNlYXNvbmFsIHNtb290aGluZyBtb2RlbHMsIHdoaWNoIHdpbGwgaW5jbHVkZSB0aGUgc2ltcGxlIGV4cG9uZW50aWFsIHNtb290aGluZyBtb2RlbCwgdGhlIEhvbHQgbGluZWFyLCB0aGUgSG9sdCBBZGRpdGl2ZSBEYW1wZWQsIGFuZCB0aGUgSG9sdCBNdWx0aXBsaWNhdGl2ZSBEYW1wZWQgbW9kZWxzLiBUaGUgb3RoZXIgc2VyaWFsIHBsb3Qgd2lsbCBiZSBmb3IgdGhlIHRyZW5kIGFuZCBzZWFzb25hbCBzbW9vdGhpbmcgbW9kZWxzLCB3aGljaCB3aWxsIGluY2x1ZGUgdGhlIEhXIEFkZGl0aXZlLCB0aGUgSFcgTXVsdGlwbGljYXRpdmUsIHRoZSBIVyBBZGRpdGl2ZSBEYW1wZWQsIGFuZCB0aGUgSFcgTXVsdGlwbGljYXRpdmUgRGFtcGVkIG1vZGVscy4gDQoNCkZpcnN0LCB3ZSB3aWxsIGNyZWF0ZSB0aGUgc2VyaWFsIHBsb3QgZm9yIHRoZSBub24tc2Vhc29uYWwgc21vb3RoaW5nIG1vZGVscy4gDQoNCmBgYHtyfQ0KcGFyKG1mcm93ID0gYygyLDEpLCBtYXIgPSBjKDMsNCwzLDEpKQ0KcHJlZC5pZCA9IDIzODoyNDkNCnBsb3QoMToyMzgsIGZsaWdodC50czEsIGx3ZCA9IDIsdHlwZSA9ICJvIiwgeWxhYiA9ICJBaXIgVHJhdmVsIFBhc3NlbmdlcnMiLCB4bGFiID0gIiIsIA0KICAgICB4bGltID0gYygxLCAyNDkpLCB5bGltPWMoMCwgODAwMDAwMDApLCBjZXggPSAwLjMsDQogICAgIG1haW4gPSAiTm9uLXNlYXNvbmFsIFNtb290aGluZyBNb2RlbHMiKQ0KbGluZXMocHJlZC5pZCwgZml0MSRtZWFuLCBjb2wgPSAicGluayIpDQpsaW5lcyhwcmVkLmlkLCBmaXQyJG1lYW4sIGNvbCA9ICJibHVlIikNCmxpbmVzKHByZWQuaWQsIGZpdDMkbWVhbiwgY29sID0gInB1cnBsZSIpDQpsaW5lcyhwcmVkLmlkLCBmaXQ0JG1lYW4sIGNvbCA9ICJuYXZ5IikNCg0KcG9pbnRzKHByZWQuaWQsIGZpdDEkbWVhbiwgcGNoID0gMTYsIGNvbCA9ICJwaW5rIiwgY2V4ID0gMC41KQ0KcG9pbnRzKHByZWQuaWQsIGZpdDIkbWVhbiwgcGNoID0gMTcsIGNvbCA9ICJibHVlIiwgY2V4ID0gMC41KQ0KcG9pbnRzKHByZWQuaWQsIGZpdDMkbWVhbiwgcGNoID0gMTksIGNvbCA9ICJwdXJwbGUiLCBjZXggPSAwLjUpDQpwb2ludHMocHJlZC5pZCwgZml0NCRtZWFuLCBwY2ggPSAyMSwgY29sID0gIm5hdnkiLCBjZXggPSAwLjUpDQoNCmxlZ2VuZCgiYm90dG9tcmlnaHQiLCBsdHkgPSAxLCBjb2wgPSBjKCJwaW5rIiwiYmx1ZSIsInB1cnBsZSIsIm5hdnkiKSwgcGNoID0gYygxNiwgMTcsIDE5LCAyMSksDQogICBjKCJTRVMiLCJIb2x0IExpbmVhciIsIkhvbHQgQWRkaXRpdmUgRGFtcGVkIiwgIkhvbHQgTXVsdGlwbGljYXRpdmUgRGFtcGVkIiksIA0KICAgY2V4ID0gMC41LCBidHkgPSAibiIpDQpgYGANCg0KV2UgY2FuIHNlZSBmcm9tIHRoZSBzZXJpYWwgcGxvdCB0aGF0IHRoaXMgdmlzdWFsaXplZCB0aGUgZm9yZWNhc3RzIGZvciB0aGUgbm9uLXNlYXNvbmFsIHNtb290aGluZyBtb2RlbHMgd2hpY2ggd2UgY3JlYXRlZC4NCg0KTmV4dCwgd2Ugd2lsbCBjcmVhdGUgdGhlIHNlcmlhbCBwbG90IGZvciB0aGUgSG9sdC1XaW50ZXIncyB0cmVuZCBhbmQgc2Vhc29uYWwgc21vb3RoaW5nIG1vZGVscy4NCg0KYGBge3J9DQpwbG90KDE6MjM4LCBmbGlnaHQudHMxLCBsd2QgPSAyLCB0eXBlID0gIm8iLCB5bGFiID0gIkFpciBUcmF2ZWwgUGFzc2VuZ2VycyIsIHhsYWIgPSAiIiwgDQogICAgIHhsaW09YygxLDI0OSksIHlsaW09YygwLCA4MDAwMDAwMCksIGNleCA9IDAuMywNCiAgICAgbWFpbj0iSG9sdC1XaW50ZXJzIFRyZW5kIGFuZCBTZWFzb25hbCBTbW9vdGhpbmcgTW9kZWxzIikNCmxpbmVzKHByZWQuaWQsIGZpdDUkbWVhbiwgY29sID0gInBpbmsiKQ0KbGluZXMocHJlZC5pZCwgZml0NiRtZWFuLCBjb2wgPSAiYmx1ZSIpDQpsaW5lcyhwcmVkLmlkLCBmaXQ3JG1lYW4sIGNvbCA9ICJwdXJwbGUiKQ0KbGluZXMocHJlZC5pZCwgZml0OCRtZWFuLCBjb2wgPSAibmF2eSIpDQoNCnBvaW50cyhwcmVkLmlkLCBmaXQ1JG1lYW4sIHBjaCA9IDE2LCBjb2wgPSAicGluayIsIGNleCA9IDAuNSkNCnBvaW50cyhwcmVkLmlkLCBmaXQ2JG1lYW4sIHBjaCA9IDE3LCBjb2wgPSAiYmx1ZSIsIGNleCA9IDAuNSkNCnBvaW50cyhwcmVkLmlkLCBmaXQ3JG1lYW4sIHBjaCA9IDE5LCBjb2wgPSAicHVycGxlIiwgY2V4ID0gMC41KQ0KcG9pbnRzKHByZWQuaWQsIGZpdDgkbWVhbiwgcGNoID0gMjEsIGNvbCA9ICJuYXZ5IiwgY2V4ID0gMC41KQ0KDQpsZWdlbmQoImJvdHRvbXJpZ2h0IiwgbHR5PTEsIGNvbCA9IGMoInBpbmsiLCJibHVlIiwicHVycGxlIiwgIm5hdnkiKSwgcGNoID0gYygxNiwgMTcsIDE5LCAyMSksDQogICBjKCJIVyBBZGRpdGl2ZSIsIkhXIE11bHRpcGxpY2F0aXZlIiwiSFcgQWRkaXRpdmUgRGFtcGVkIiwgIkhXIE11bHRpcGxpY2F0aXZlIERhbXBlZCIpLCANCiAgIGNleCA9IDAuNSwgYnR5ID0gIm4iKQ0KYGBgDQoNCldlIGNhbiBzZWUgZnJvbSB0aGlzIHNlcmlhbCBwbG90IHRoZSBmb3JlY2FzdHMgZm9yIHRoZSB0cmVuZCBhbmQgc2Vhc29uYWwgc21vb3RoaW5nIG1vZGVscy4NCg0KRnJvbSB0aGUgdHdvIHNlcmlhbCBwbG90cyB3ZSBjcmVhdGVkLCBpdCBsb29rcyBsaWtlIHRoZSBIb2x0LVdpbnRlcidzIEFkZGl0aXZlIG1vZGVsIG9uY2UgYWdhaW4gc2VlbXMgbGlrZSB0aGUgYmVzdCBvZiB0aGUgbW9kZWxzIHdlIGNyZWF0ZWQuIFRoaXMgbWF0Y2hlcyB1cCB3aXRoIHdoYXQgd2FzIGZvdW5kIGluIHRoZSBhY2N1cmFjeSB0YWJsZS4gSXQgbG9va3MgbGlrZSB0aGUgSG9sdCBXaW50ZXIncyBBZGRpdGl2ZSBNb2RlbCBwcm92aWRlcyBhIHF1YWxpdHkgZm9yZWNhc3QgaW4gdGhlIHNlcmlhbCBwbG90IGZvciB0aGUgSG9sdC1XaW50ZXIncyB0cmVuZCBhbmQgc2Vhc29uYWwgc21vb3RoaW5nIG1vZGVscy4NCg0KDQoNCg0KIyBGb3JlY2FzdGluZyB3aXRoIHRoZSBUZXN0aW5nIERhdGENCg0KTm93IHRoYXQgd2UgaGF2ZSBkZXRlcm1pbmVkIHdoaWNoIG1vZGVsIGxvb2tzIGxpa2UgdGhlIGlkZWFsIGNob2ljZSwgdGhlIEhvbHQtV2ludGVyJ3MgQWRkaXRpdmUgTW9kZWwsIHdlIHdpbGwgdXNlIHRoZSB0ZXN0aW5nIGRhdGEgc2V0IHdoaWNoIHdlIGNyZWF0ZWQgZWFybGllciB0byB2ZXJpZnkgb3VyIGJlc3QgbW9kZWwgc2VsZWN0aW9uLg0KDQpXZSBwcmV2aW91c2x5IHVzZWQgdGhlIHRyYWluaW5nIGRhdGEgc2V0IHRvIHRyYWluIHRoZSB2YXJpb3VzIHNtb290aGluZyBtb2RlbHMgd2UgbG9va2VkIGF0LiBUbyBjcmVhdGUgb3VyIHJlYWwtd29ybGQgZm9yZWNhc3QsIHdlIHdpbGwgcmVmaXQgdGhlIG1vZGVsIHVzaW5nIHRoZSB0ZXN0aW5nIGRhdGEgYXMgd2VsbC4gVGhpcyB3aWxsIGFsbG93IHVzIHRvIHZlcmlmeSBvdXIgZmluZGluZ3MgYW5kIGlmIHRoZSBtb2RlbCB3aGljaCBsb29rZWQgdG8gc2hvdyB0aGUgYmVzdCBwZXJmb3JtYW5jZSBpbiBmb3JlY2FzdGluZyB0cnVseSBsb29rcyBsaWtlIHRoZSBpZGVhbCBjaG9pY2UuDQoNCkZpcnN0LCB3ZSB3aWxsIHJlZml0IHRoZSBtb2RlbCB1c2luZyB0aGUgZW50aXJlIGRhdGEgc2V0IHRvIHVwZGF0ZSB0aGUgc21vb3RoaW5nIHBhcmFtZXRlcnMuDQoNCmBgYHtyfQ0KYWNjLmZ1biA9IGZ1bmN0aW9uKHRlc3QuZGF0YSwgbW9kLm9iail7DQogIFBFID0gMTAwKih0ZXN0LmRhdGEtbW9kLm9iaiRtZWFuKS9tb2Qub2JqJG1lYW4NCiAgTUFQRSA9IG1lYW4oYWJzKFBFKSkNCiAgRSA9IHRlc3QuZGF0YS1tb2Qub2JqJG1lYW4NCiAgTVNFID0gbWVhbihFXjIpDQogIGFjY3VyYWN5Lm1ldHJpYyA9IGMoTVNFID0gTVNFLCBNQVBFID0gTUFQRSkNCiAgYWNjdXJhY3kubWV0cmljDQp9DQpgYGANCg0KTm93LCB3ZSB3aWxsIGZpbmQgdGhlIHVwZGF0ZWQgYWNjdXJhY3kgcHJlZGljdGlvbiBtZWFzdXJlcyBmb3IgZWFjaCBvZiB0aGUgc21vb3RoaW5nIG1vZGVscyB3ZSBjcmVhdGVkLiANCg0KYGBge3J9DQpwcmVkLmFjY3VyYWN5ID0gcmJpbmQoU0VTID0gYWNjLmZ1bih0ZXN0LmRhdGEgPSB0ZXN0LmZsaWdodCwgbW9kLm9iaiA9IGZpdDEpLA0KICAgICAgICAgICAgICAgICAgICAgIEhvbHQuQWRkID0gYWNjLmZ1bih0ZXN0LmRhdGE9dGVzdC5mbGlnaHQsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtb2Qub2JqID0gZml0MiksDQogICAgICAgICAgICAgICAgICAgICAgSG9sdC5BZGQuRGFtcCA9IGFjYy5mdW4odGVzdC5kYXRhID0gdGVzdC5mbGlnaHQsICAgIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1vZC5vYmo9Zml0MyksDQogICAgICAgICAgICAgICAgICAgICAgSG9sdC5FeHAgPSBhY2MuZnVuKHRlc3QuZGF0YSA9IHRlc3QuZmxpZ2h0LCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbW9kLm9iaiA9IGZpdDQpLA0KICAgICAgICAgICAgICAgICAgICAgIEhXLkFkZCA9IGFjYy5mdW4odGVzdC5kYXRhID0gdGVzdC5mbGlnaHQsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbW9kLm9iaiA9IGZpdDUpLA0KICAgICAgICAgICAgICAgICAgICAgIEhXLkV4cCA9IGFjYy5mdW4odGVzdC5kYXRhID0gdGVzdC5mbGlnaHQsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbW9kLm9iaiA9IGZpdDYpLA0KICAgICAgICAgICAgICAgICAgICAgIEhXLkFkZC5EYW1wID0gYWNjLmZ1bih0ZXN0LmRhdGEgPSB0ZXN0LmZsaWdodCwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1vZC5vYmogPSBmaXQ3KSwNCiAgICAgICAgICAgICAgICAgICAgICBIVy5FeHAuRGFtcCA9IGFjYy5mdW4odGVzdC5kYXRhID0gdGVzdC5mbGlnaHQsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtb2Qub2JqID0gZml0OCkpDQprYWJsZShwcmVkLmFjY3VyYWN5LCBjYXB0aW9uID0gIkFjY3VyYWN5IE1lYXN1cmVzIG9mIHRoZSBWYXJpb3VzIEV4cG9uZW50aWFsIFNtb290aGluZyBNb2RlbHMgQmFzZWQgb24gdGhlIFRlc3RpbmcgRGF0YSBTZXQiKQ0KYGBgDQoNCkxvb2tpbmcgYXQgdGhlIGFjY3VyYWN5IG1lYXN1cmVzIGJhc2VkIG9uIHRoZSB0ZXN0aW5nIGRhdGEgc2V0LCB3ZSBjYW4gc2VlIHRoYXQgdGhlIEhvbHQtV2ludGVyJ3MgQWRkaXRpdmUgbW9kZWwgaGFzIGJvdGggdGhlIGxvd2VzdCBNU0UgYW5kIE1BUEUuIFRoaXMgaXMgaWRlYWwgYmVjYXVzZSB3ZSB3YW50IG91ciBtb2RlbCB0byByZWR1Y2UgdGhlIGVycm9ycyBhcyBtdWNoIGFzIHBvc3NpYmxlLiBBbHNvLCB0aGlzIG1hdGNoZXMgdXAgd2l0aCB3aGF0IHdlIGZvdW5kIGVhcmxpZXIsIGJlY2F1c2Ugb25jZSBhZ2FpbiB0aGUgSG9sdC1XaW50ZXIncyBBZGRpdGl2ZSBtb2RlbCBoYXMgdGhlIGJlc3QgcGVyZm9ybWFuY2UgaW4gdGVybXMgb2YgYWNjdXJhY3kuIFNvLCBpdCBsb29rcyBsaWtlIHRoZSBIb2x0LVdpbnRlcidzIEFkZGl0aXZlIG1vZGVsIGlzIHRoZSBpZGVhbCBjaG9pY2UsIGFuZCB0aGlzIGhhcyBiZWVuIHZlcmlmaWVkIHdpdGggdGhlIHRlc3RpbmcgZGF0YSBzZXQuIA0KDQoNCg0KDQojIEZpbmFsIE1vZGVsDQoNCkJhc2VkIHVwb24gb3VyIGZpbmRpbmdzLCBpdCBsb29rcyBsaWtlIHRoZSBIb2x0LVdpbnRlcidzIEFkZGl0aXZlIG1vZGVsIGlzIHRoZSBpZGVhbCBjaG9pY2Ugb3V0IG9mIHRoZSBtYW55IHBvc3NpYmxlIGNhbmRpZGF0ZSBtb2RlbHMgd2UgY3JlYXRlZC4gVGhpcyBtb2RlbCBzaG93ZWQgaXRzIGlkZWFsIHBlcmZvcm1hbmNlIGJ5IHJlZHVjaW5nIHRoZSBlcnJvcnMgbW9yZSBzaWduaWZpY2FudGx5IHRoYW4gYW55IG9mIHRoZSBvdGhlciBtb2RlbHMgZGlkLiBUaGlzIEhvbHQtV2ludGVyJ3MgQWRkaXRpdmUgbW9kZWwgYWxzbyBzaG93ZWQgdGhlIGJlc3QgcGVyZm9ybWFuY2UgaW4gdGVybXMgb2YgdGhlIGFjY3VyYWN5IG1lYXN1cmVzLCBiZWNhdXNlIGl0IGhhZCB0aGUgbG93ZXN0IE1TRSBhbmQgTUFQRSB2YWx1ZXMgb2Ygb3V0IGFueSBvZiB0aGUgbW9kZWxzLiBTbywgdGhlIEhvbHQtV2ludGVyJ3MgQWRkaXRpdmUgbW9kZWwgaXMgdGhlIGlkZWFsIG1vZGVsIG91dCBvZiBhbGwgdGhlIGNhbmRpZGF0ZSBtb2RlbHMgd2UgY3JlYXRlZCBhbmQgdHJpZWQgb3V0Lg0KDQoNCiMjIFNtb290aGluZyBQYXJhbWV0ZXJzDQoNCldlIHdpbGwgdGFrZSBhIGxvb2sgYXQgdGhlIHNtb290aGluZyBwYXJhbWV0ZXJzIGZvciB0aGUgSG9sdC1XaW50ZXIncyBBZGRpdGl2ZSBtb2RlbC4gDQoNCmBgYHtyfQ0KZmluYWwubW9kZWwgPC0gaHcoZmxpZ2h0LnRzMSwgaCA9IDEyLCBzZWFzb25hbCA9ICJhZGRpdGl2ZSIpDQpzbW9vdGhpbmcucGFyYW1ldGVyID0gZmluYWwubW9kZWwkbW9kZWwkcGFyWzE6M10NCmthYmxlKHNtb290aGluZy5wYXJhbWV0ZXIsIGNhcHRpb249IlRoZSBFc3RpbWF0ZWQgVmFsdWVzIG9mIHRoZSBTbW9vdGhpbmcgUGFyYW1ldGVycyBpbiB0aGUgSG9sdC1XaW50ZXJzIEFkZGl0aXZlIE1vZGVsIikNCmBgYA0KDQpUaGUgc21vb3RoaW5nIHBhcmFtZXRlcnMgZm9yIG91ciBmaW5hbCBtb2RlbCwgdGhlIEhvbHQtV2ludGVyJ3MgQWRkaXRpdmUgbW9kZWwsIGluY2x1ZGUgYW4gYWxwaGEgb2YgMC45OTk5LCBhIGJldGEgb2YgMC4wMDA0LCBhbmQgYSBnYW1tYSBvZiAwLjAwMDEuIA0KICANCg0KDQoNCiMgQ29uY2x1c2lvbg0KDQpPdmVyYWxsLCB3ZSBsb29rZWQgYXQgYSBkYXRhIHNldCB3aGljaCB3YXMgcmVwcmVzZW50YXRpdmUgb2YgdGhlIHRvdGFsIG51bWJlciBvZiBhaXIgdHJhdmVsIHBhc3NlbmdlcnMgaW4gdGhlIFUuUy4gdGhyb3VnaCBtb250aGx5IGF2ZXJhZ2VzLiBUaGlzIGRhdGEgd2FzIGNvbGxlY3RlZCBvdmVyIHRoZSBjb3Vyc2Ugb2YgdGhlIHllYXJzIGZyb20gMjAwMyB0byAyMDIzLiBXZSBjcmVhdGVkIGEgbW9udGhseSB0aW1lIHNlcmllcyB3aGljaCBzaG93ZWQgdGhlIHRyZW5kcyBhbmQgc2Vhc29uYWxpdHkgb2YgdGhlIGF2ZXJhZ2UgbnVtYmVyIG9mIGFpciB0cmF2ZWwgcGFzc2VuZ2VycyBieSBtb250aCBvdmVyIHRoZSBzcGFuIG9mIHRoaXMgMjAgeWVhciBwZXJpb2QuIA0KDQpXZSBzcGxpdCB0aGUgdGltZSBzZXJpZXMgZGF0YSB1cCBpbnRvIGEgdHJhaW5pbmcgYW5kIGEgdGVzdGluZyBkYXRhIHNldC4gQWZ0ZXIgbG9va2luZyBhdCBzZXZlcmFsIHBvdGVuZXRpYWwgc21vb3RoaW5nIG1vZGVscywgdGhlIG9uZSB3aGljaCB3YXMgZm91bmQgdG8gcHJvdmlkZSB0aGUgYmVzdCBwZXJmb3JtYW5jZSB3YXMgdGhlIEhvbHQtV2ludGVyJ3MgQWRkaXRpdmUgbW9kZWwuIFRoaXMgbW9kZWwgd2FzIHRoZSBiZXN0IGNob2ljZSBiZWNhdXNlIGl0IGRpZCB0aGUgYmVzdCBqb2Igb3V0IG9mIGRlY3JlYXNpbmcgdGhlIGVycm9ycywgYW5kIHByb3ZpZGVkIHRoZSBiZXN0IGFjY3VyYWN5IG92ZXJhbGwuIFNvLCB0aGUgSG9sdC1XaW50ZXIncyBBZGRpdGl2ZSBtb2RlbCB3YXMgdGhlIGJlc3QgY2hvaWNlIG91dCBvZiB0aGUgc2V2ZXJhbCBjYW5kaWRhdGUsIHNtb290aGluZyBtb2RlbHMgd2UgbG9va2VkIGF0LiANCg0KDQojIyBSZWNvbW1lbmRhdGlvbnMNCg0KU29tZSByZWNvbW1lbmRhdGlvbnMgSSB3b3VsZCBtYWtlIGZvciBmdXR1cmUgcHJvamVjdHMgaW5jbHVkZToNCg0KKiBDb25zaWRlciBleHBhbmRpbmcgdGhlIHRpbWUgc2VyaWVzIGRhdGEgdG8gaW5jbHVkZSB0aGUgYXZlcmFnZSBhaXIgdHJhdmVsIHBhc3NlbmdlcnMgZm9yIGFsbCBjb3VudHJpZXMsIG5vdCBqdXN0IHRoZSBVLlMuIGluIG9yZGVyIHRvIHNlZSBpZiB0aGlzIHN0aWxsIHJlc3VsdHMgaW4gdGhlIEhvbHQtV2ludGVyJ3MgQWRkaXRpdmUgbW9kZWwgYmVpbmcgdGhlIGlkZWFsIG1vZGVsIGNob2ljZSwgb3IgaWYgYW5vdGhlciBtb2RlbCBzZWVtcyB0byBwcm92aWRlIGJldHRlciBwZXJmb3JtYW5jZSBpbiB0aGlzIHNjZW5hcmlvLg0KDQoqIEZ1cnRoZXIgbG9vayBpbnRvIHRoZSBzZWFzb25hbGl0eSBpbiB0aGlzIHRpbWUgc2VyaWVzIGRhdGEgc2V0LCBzaW5jZSB0aGVyZSBkZWZpbml0ZWx5IGFwcGVhcmVkIHRvIGJlIHNlYXNvbmFsaXR5IG9jY3VycmluZyB3aXRoIG1vcmUgcGFzc2VuZ2VycyB0cmF2ZWxsaW5nIGluIGNlcnRhaW4gdGltZXMgb2YgdGhlIHllYXIsIGxpa2Ugc3VtbWVyLCB0aGFuIGR1cmluZyBvdGhlciB0aW1lcyBvZiB0aGUgeWVhciB3aGljaCBzYXcgZmV3ZXIgcGFzc2VuZ2Vycy4gDQoNCg0KDQoNCiMgUmVmZXJlbmNlcw0KDQpUaGUgZGF0YSBzZXQgSSB1c2VkIGZvciBteSB0aW1lIHNlcmllcyB3YXMgZm91bmQgb24ga2FnZ2xlLmNvbS4gSW5jbHVkZWQgYmVsb3cgaXMgdGhlIGNpdGF0aW9uIG9mIHRoZSB3ZWIgcGFnZSB3aGVyZSBJIGZvdW5kIHRoaXMgZGF0YSBzZXQuIA0KDQpZWVhpYW4uICgyMDI0LCBKYW51YXJ5IDE1KS4gVS5TLiBhaXJsaW5lIHRyYWZmaWMgZGF0YSAoMjAwMy0yMDIzKS4gS2FnZ2xlLiBodHRwczovL3d3dy5rYWdnbGUuY29tL2RhdGFzZXRzL3l5eGlhbi91LXMtYWlybGluZS10cmFmZmljLWRhdGE/c2VsZWN0PWFpciUyQnRyYWZmaWMuY3N2IA0K