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

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

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

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

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

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

4 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).

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

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

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

5 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
ME RMSE MAE MPE MAPE MASE ACF1
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.

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

7 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
MSE MAPE
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.

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

8.1 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
x
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.

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

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

10 References

The data set I used for my time series was found on kaggle.com. Included below is the citation of the web page where I found this data set.

YYXian. (2024, January 15). U.S. airline traffic data (2003-2023). Kaggle. https://www.kaggle.com/datasets/yyxian/u-s-airline-traffic-data?select=air%2Btraffic.csv

LS0tDQp0aXRsZTogIk1vbnRobHkgQXZlcmFnZSBBaXIgVHJhdmVsIFBhc3NlbmdlcnM6IFRpbWUgU2VyaWVzIHdpdGggRXhwb25lbnRpYWwgU21vb3RoaW5nIg0KYXV0aG9yOiAiSm9zaWUgR2FsbG9wIg0KZGF0ZTogIjIwMjQtMTItMTEiDQpvdXRwdXQ6DQogIGh0bWxfZG9jdW1lbnQ6IA0KICAgIHRvYzogeWVzDQogICAgdG9jX2RlcHRoOiA0DQogICAgdG9jX2Zsb2F0OiB5ZXMNCiAgICBmaWdfd2lkdGg6IDYNCiAgICBmaWdfY2FwdGlvbjogeWVzDQogICAgbnVtYmVyX3NlY3Rpb25zOiB5ZXMNCiAgICB0b2NfY29sbGFwc2VkOiB5ZXMNCiAgICBjb2RlX2ZvbGRpbmc6IGhpZGUNCiAgICBjb2RlX2Rvd25sb2FkOiB5ZXMNCiAgICBzbW9vdGhfc2Nyb2xsOiB5ZXMNCiAgICB0aGVtZTogbHVtZW4NCiAgd29yZF9kb2N1bWVudDogDQogICAgdG9jOiB5ZXMNCiAgICB0b2NfZGVwdGg6IDQNCiAgICBmaWdfY2FwdGlvbjogeWVzDQogICAga2VlcF9tZDogeWVzDQogIHBkZl9kb2N1bWVudDogDQogICAgdG9jOiB5ZXMNCiAgICB0b2NfZGVwdGg6IDQNCiAgICBmaWdfY2FwdGlvbjogeWVzDQogICAgbnVtYmVyX3NlY3Rpb25zOiB5ZXMNCmVkaXRvcl9vcHRpb25zOiANCiAgY2h1bmtfb3V0cHV0X3R5cGU6IGNvbnNvbGUNCi0tLQ0KDQpgYGB7PWh0bWx9DQoNCjxzdHlsZSB0eXBlPSJ0ZXh0L2NzcyI+DQoNCi8qIENhc2NhZGluZyBTdHlsZSBTaGVldHMgKENTUykgaXMgYSBzdHlsZXNoZWV0IGxhbmd1YWdlIHVzZWQgdG8gZGVzY3JpYmUgdGhlIHByZXNlbnRhdGlvbiBvZiBhIGRvY3VtZW50IHdyaXR0ZW4gaW4gSFRNTCBvciBYTUwuIGl0IGlzIGEgc2ltcGxlIG1lY2hhbmlzbSBmb3IgYWRkaW5nIHN0eWxlIChlLmcuLCBmb250cywgY29sb3JzLCBzcGFjaW5nKSB0byBXZWIgZG9jdW1lbnRzLiAqLw0KDQpoMS50aXRsZSB7ICAvKiBUaXRsZSAtIGZvbnQgc3BlY2lmaWNhdGlvbnMgb2YgdGhlIHJlcG9ydCB0aXRsZSAqLw0KICBmb250LXNpemU6IDI0cHg7DQogIGNvbG9yOiBEYXJrUmVkOw0KICB0ZXh0LWFsaWduOiBjZW50ZXI7DQogIGZvbnQtZmFtaWx5OiAiR2lsbCBTYW5zIiwgc2Fucy1zZXJpZjsNCn0NCmg0LmF1dGhvciB7IC8qIEhlYWRlciA0IC0gZm9udCBzcGVjaWZpY2F0aW9ucyBmb3IgYXV0aG9ycyAgKi8NCiAgZm9udC1zaXplOiAyMHB4Ow0KICBmb250LWZhbWlseTogc3lzdGVtLXVpOw0KICBjb2xvcjogRGFya1JlZDsNCiAgdGV4dC1hbGlnbjogY2VudGVyOw0KfQ0KaDQuZGF0ZSB7IC8qIEhlYWRlciA0IC0gZm9udCBzcGVjaWZpY2F0aW9ucyBmb3IgdGhlIGRhdGUgICovDQogIGZvbnQtc2l6ZTogMThweDsNCiAgZm9udC1mYW1pbHk6IHN5c3RlbS11aTsNCiAgY29sb3I6IERhcmtCbHVlOw0KICB0ZXh0LWFsaWduOiBjZW50ZXI7DQp9DQpoMSB7IC8qIEhlYWRlciAxIC0gZm9udCBzcGVjaWZpY2F0aW9ucyBmb3IgbGV2ZWwgMSBzZWN0aW9uIHRpdGxlICAqLw0KICAgIGZvbnQtc2l6ZTogMjJweDsNCiAgICBmb250LWZhbWlseTogIlRpbWVzIE5ldyBSb21hbiIsIFRpbWVzLCBzZXJpZjsNCiAgICBjb2xvcjogbmF2eTsNCiAgICB0ZXh0LWFsaWduOiBjZW50ZXI7DQp9DQpoMiB7IC8qIEhlYWRlciAyIC0gZm9udCBzcGVjaWZpY2F0aW9ucyBmb3IgbGV2ZWwgMiBzZWN0aW9uIHRpdGxlICovDQogICAgZm9udC1zaXplOiAyMHB4Ow0KICAgIGZvbnQtZmFtaWx5OiAiVGltZXMgTmV3IFJvbWFuIiwgVGltZXMsIHNlcmlmOw0KICAgIGNvbG9yOiBuYXZ5Ow0KICAgIHRleHQtYWxpZ246IGxlZnQ7DQp9DQoNCmgzIHsgLyogSGVhZGVyIDMgLSBmb250IHNwZWNpZmljYXRpb25zIG9mIGxldmVsIDMgc2VjdGlvbiB0aXRsZSAgKi8NCiAgICBmb250LXNpemU6IDE4cHg7DQogICAgZm9udC1mYW1pbHk6ICJUaW1lcyBOZXcgUm9tYW4iLCBUaW1lcywgc2VyaWY7DQogICAgY29sb3I6IG5hdnk7DQogICAgdGV4dC1hbGlnbjogbGVmdDsNCn0NCg0KaDQgeyAvKiBIZWFkZXIgNCAtIGZvbnQgc3BlY2lmaWNhdGlvbnMgb2YgbGV2ZWwgNCBzZWN0aW9uIHRpdGxlICAqLw0KICAgIGZvbnQtc2l6ZTogMThweDsNCiAgICBmb250LWZhbWlseTogIlRpbWVzIE5ldyBSb21hbiIsIFRpbWVzLCBzZXJpZjsNCiAgICBjb2xvcjogZGFya3JlZDsNCiAgICB0ZXh0LWFsaWduOiBsZWZ0Ow0KfQ0KDQpib2R5IHsgYmFja2dyb3VuZC1jb2xvcjp3aGl0ZTsgfQ0KDQouaGlnaGxpZ2h0bWUgeyBiYWNrZ3JvdW5kLWNvbG9yOnllbGxvdzsgfQ0KDQpwIHsgYmFja2dyb3VuZC1jb2xvcjp3aGl0ZTsgfQ0KDQo8L3N0eWxlPg0KYGBgDQpgYGB7ciBzZXR1cCwgaW5jbHVkZT1GQUxTRX0NCiMgRGV0ZWN0LCBpbnN0YWxsLCBhbmQgbG9hZCBwYWNrYWdlcyBpZiBuZWVkZWQuDQppZiAoIXJlcXVpcmUoImtuaXRyIikpIHsNCiAgIGluc3RhbGwucGFja2FnZXMoImtuaXRyIikNCiAgIGxpYnJhcnkoa25pdHIpDQp9DQppZiAoIXJlcXVpcmUoImxlYWZsZXQiKSkgew0KICAgaW5zdGFsbC5wYWNrYWdlcygibGVhZmxldCIpDQogICBsaWJyYXJ5KGxlYWZsZXQpDQp9DQppZiAoIXJlcXVpcmUoIkVudlN0YXRzIikpIHsNCiAgIGluc3RhbGwucGFja2FnZXMoIkVudlN0YXRzIikNCiAgIGxpYnJhcnkoRW52U3RhdHMpDQp9DQppZiAoIXJlcXVpcmUoIk1BU1MiKSkgew0KICAgaW5zdGFsbC5wYWNrYWdlcygiTUFTUyIpDQogICBsaWJyYXJ5KE1BU1MpDQp9DQppZiAoIXJlcXVpcmUoInBoeXRvb2xzIikpIHsNCiAgIGluc3RhbGwucGFja2FnZXMoInBoeXRvb2xzIikNCiAgIGxpYnJhcnkocGh5dG9vbHMpDQp9DQppZighcmVxdWlyZSgiZHBseXIiKSkgew0KICAgaW5zdGFsbC5wYWNrYWdlcygiZHBseXIiKQ0KICAgbGlicmFyeShkcGx5cikNCn0NCmlmKCFyZXF1aXJlKCJ0aWR5dmVyc2UiKSkgew0KICAgaW5zdGFsbC5wYWNrYWdlcygidGlkeXZlcnNlIikNCiAgIGxpYnJhcnkodGlkeXZlcnNlKQ0KfQ0KaWYoIXJlcXVpcmUoIkdHYWxseSIpKSB7DQogICBpbnN0YWxsLnBhY2thZ2VzKCJHR2FsbHkiKQ0KICAgbGlicmFyeShHR2FsbHkpDQp9DQppZiAoIXJlcXVpcmUoImJvb3QiKSkgew0KICAgaW5zdGFsbC5wYWNrYWdlcygiYm9vdCIpDQogICBsaWJyYXJ5KGJvb3QpDQp9DQppZighcmVxdWlyZSgicGFuZGVyIikpIHsNCiAgIGluc3RhbGwucGFja2FnZXMoInBhbmRlciIpDQogICBsaWJyYXJ5KHBhbmRlcikNCn0NCmlmKCFyZXF1aXJlKCJtbGJlbmNoIikpIHsNCiAgIGluc3RhbGwucGFja2FnZXMoIm1sYmVuY2giKQ0KICAgbGlicmFyeShtbGJlbmNoKQ0KfQ0KaWYoIXJlcXVpcmUoInBzeWNoIikpIHsNCiAgIGluc3RhbGwucGFja2FnZXMoInBzeWNoIikNCiAgIGxpYnJhcnkocHN5Y2gpDQp9DQppZighcmVxdWlyZSgibHVicmlkYXRlIikpIHsNCiAgIGluc3RhbGwucGFja2FnZXMoImx1YnJpZGF0ZSIpDQogICBsaWJyYXJ5KGx1YnJpZGF0ZSkNCn0NCmlmKCFyZXF1aXJlKCJHR2FsbHkiKSkgew0KICAgaW5zdGFsbC5wYWNrYWdlcygiR0dhbGx5IikNCiAgIGxpYnJhcnkoR0dhbGx5KQ0KfQ0KaWYgKCFyZXF1aXJlKCJwUk9DIikpIHsNCiAgIGluc3RhbGwucGFja2FnZXMoInBST0MiKQ0KICAgbGlicmFyeShwUk9DKQ0KfQ0KaWYgKCFyZXF1aXJlKCJmb3JlY2FzdCIpKSB7DQogICBpbnN0YWxsLnBhY2thZ2VzKCJmb3JlY2FzdCIpDQogICBsaWJyYXJ5KGZvcmVjYXN0KQ0KfQ0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KGVjaG8gPSBUUlVFLCAgDQogICAgICAgICAgICAgICAgICAgd2FybmluZyA9IEZBTFNFLCAgIA0KICAgICAgICAgICAgICAgICAgIG1lc3NhZ2UgPSBGQUxTRSwgIA0KICAgICAgICAgICAgICAgICAgIHJlc3VsdHMgPSBUUlVFLCAgDQogICAgICAgICAgICAgICAgICAgY29tbWVudCA9IE5BICAgDQogICAgICAgICAgICAgICAgICAgICAgKSAgIA0KYGBgDQoNCg0KIyBJbnRyb2R1Y3Rpb24NCg0KRm9yIHRoaXMgcHJvamVjdCwgd2Ugd2lsbCBiZSBjcmVhdGluZyBhIFRpbWUgU2VyaWVzLiBUaGlzIHRpbWUgc2VyaWVzIGxvb2tzIGF0IHRoZSBhdmVyYWdlIG51bWJlciBvZiBhaXIgdHJhdmVsIHBhc3NlbmdlcnMgb24gYWxsIFUuUy4gZmxpZ2h0cy4gVGhlIHRpbWUgc2VyaWVzIHdlIHdpbGwgbG9vayBhdCB3aWxsIGluY2x1ZGUgdGhlIG51bWJlciBvZiBwYXNzZW5nZXJzIG9uIGJvdGggZG9tZXN0aWMgYW5kIGludGVybmF0aW9uYWwgZmxpZ2h0cy4gV2Ugd2lsbCBjcmVhdGUgYSBtb250aGx5IHRpbWUgc2VyaWVzIHdoaWNoIGxvb2tzIGF0IHRoZSBhdmVyYWdlIG51bWJlciBvZiBhaXIgdHJhdmVsIHBhc3NlbmdlcnMgYnkgbW9udGguIFRoaXMgdGltZSBzZXJpZXMgZGF0YSB3YXMgY29sbGVjdGVkIGZyb20gMjAwMyB0byAyMDIzLCB3aXRoIHRoZSBmaXJzdCBvYnNlcnZhdGlvbiBpbiBKYW51YXJ5IG9mIDIwMDMsIGFuZCB0aGUgZmluYWwgb2JzZXJ2YXRpb24gaW4gU2VwdGVtYmVyIDIwMjMuDQoNCldlIHdpbGwgc3BsaXQgdGhlIHRpbWUgc2VyaWVzIGRhdGEgdXAgaW50byBhIHRyYWluaW5nIGFuZCBhIHRlc3RuZyBkYXRhIHNldC4gQW5kIHRoZW4gd2UgY3JlYXRlIHNldmVyYWwgY2FuZGlkYXRlLCBleHBvbmVudGlhbCBzbW9vdGhpbmcgbW9kZWxzIGZvciBmb3JlY2FzdGluZy4gVGhlc2Ugd2lsbCBpbmNsdWRlIGEgc2ltcGxlIGV4cG9uZW50aWFsIG1vZGVsLCBzZXZlcmFsIEhvbHQgbW9kZWxzLCBhbmQgc2V2ZXJhbCBIb2x0LVdpbnRlcidzIG1vZGVscy4gV2Ugd2lsbCBzZWUgd2hpY2ggb2YgdGhlc2UgY2FuZGlkYXRlIG1vZGVscyBwcm92aWRlcyB0aGUgYmVzdCB1dGlsaXR5IGZvciBhbiBleHBvbmVudGlhbCBzbW9vdGhpbmcgbW9kZWwgb2Ygb3VyIHRpbWUgc2VyaWVzLiBXZSB3aWxsIGRldGVybWluZSB0aGUgYmVzdCBtb2RlbCBieSBzZWVpbmcgd2hpY2ggb25lIHJlZHVjZXMgdGhlIGVycm9ycyBhbmQgcHJvdmlkZXMgdGhlIGJlc3Qgb3ZlcmFsbCBhY2N1cmFjeS4gDQoNCg0KIyMgRGF0YSBEZXNjcmlwdGlvbg0KDQpJIGZvdW5kIHRoaXMgZGF0YSBzZXQgb24ga2FnZ2xlLmNvbSBvbiB0aGUgZm9sbG93aW5nIHdlYnBhZ2U6DQpodHRwczovL3d3dy5rYWdnbGUuY29tL2RhdGFzZXRzL3l5eGlhbi91LXMtYWlybGluZS10cmFmZmljLWRhdGE/c2VsZWN0PWFpcit0cmFmZmljLmNzdg0KDQpUaGlzIGRhdGEgc2V0IGxvb2tzIGF0IHRoZSBhdmVyYWdlIG51bWJlciBvZiBhaXIgdHJhdmVsIHBhc3NlbmdlcnMgYnkgbW9udGggZnJvbSAyMDAzIHRvIDIwMjMuIFRoZSBmaXJzdCBvYnNlcnZhdGlvbiBpbiB0aGlzIGRhdGEgc2V0IHdhcyBjb2xsZWN0ZWQgaW4gSmFudWFyeSAyMDAzLCBhbmQgdGhlIGZpbmFsIG9ic2VydmF0aW9uIGluIHRoaXMgZGF0YSBzZXQgd2FzIGNvbGxlY3RlZCBpbiBTZXB0ZW1iZXIgMjAyMy4gVGhpcyBkYXRhIHNldCBpbmNsdWRlcyB2YXJpYWJsZXMgd2hpY2ggcmVwcmVzZW50IHRoZSB0b3RhbCBudW1iZXIgb2YgcGFzc2VuZ2VycyBvbiBib3RoIGRvbWVzdGljIGFuZCBpbnRlcm5hdGlvbmFsIGZsaWdodHMgYnkgbW9udGguIEhvd2V2ZXIsIGZvciB0aGlzIHRpbWUgc2VyaWVzLCB3ZSB3aWxsIGxvb2sgc3BlY2lmaWNhbGx5IGF0IHRoZSB2YXJpYWJsZSB3aGljaCByZXByZXNlbnRzIHRoZSB0b3RhbCBudW1iZXIgb2YgcGFzc2VuZ2VycyBvbiBhbGwgZmxpZ2h0cywgYm90aCBkb21lc3RpYyBhbmQgaW50ZXJuYXRpb25hbC4gVGhpcyBkYXRhIGlzIHJlcHJlc2VudGF0aXZlIG9mIHBhc3NlbmdlcnMgb24gYWxsIFUuUy4gZmxpZ2h0cyBieSBtb250aC4gDQoNCldlIHdpbGwgcmVhZCBpbiB0aGUgZGF0YSBzZXQgZnJvbSBHaXRodWIgYW5kIHdlIHdpbGwgY2FsbCBpdCAiZmxpZ2h0Ii4gDQoNCmBgYHtyfQ0KZmxpZ2h0IDwtIHJlYWQuY3N2KCJodHRwczovL3Jhdy5naXRodWJ1c2VyY29udGVudC5jb20vSm9zaWVHYWxsb3AvU1RBMzIxL3JlZnMvaGVhZHMvbWFpbi9kYXRhc2V0L2FpciUyMHRyYWZmaWMuY3N2IikNCmBgYA0KDQpUaGlzIGRhdGEgc2V0IGNvbnRhaW5zIG1hbnkgdmFyaWFibGVzIHJlZ2FyZGluZyBhaXIgdHJhdmVsIGluZm9ybWF0aW9uLCBidXQgZm9yIHRoaXMgdGltZSBzZXJpZXMgd2UgYXJlIGp1c3QgaW50ZXJlc3RlZCBpbiBsb29raW5nIGF0IHRoZSBudW1iZXIgb2YgdGhlIHRvdGFsIGFpciB0cmF2ZWwgcGFzc2VuZ2Vycy4gVGhpcyBpcyByZXByZXNlbnRlZCBieSB0aGUgdmFyaWFibGUgUGF4LiBXZSB3YW50IHRvIGNyZWF0ZSBhIHRpbWUgc2VyaWVzIG9mIHRoZSB0b3RhbCBhaXIgdHJhdmVsIHBhc3NlbmdlcnMgYnkgdGhlIGRhdGUsIHNvIHdlIHdpbGwgb25seSBrZWVwIHRoZSB0aW1lIHNwZWNpZmljIHZhcmlhYmxlcywgWWVhciBhbmQgTW9udGgsIGFuZCB0aGUgUGF4IHZhcmlhYmxlLiBXZSB3aWxsIGNhbGwgdGhlIG5ldyBkYXRhIHNldCB3aXRoIG9ubHkgdGhlc2Ugc3BlY2lmaWMgdmFyaWFibGVzIHdlIGFyZSBpbnRlcmVzdGVkIGluICJmbGlnaHQxIi4NCg0KYGBge3J9DQpmbGlnaHQxIDwtIGZsaWdodCAlPiUNCiAgc2VsZWN0KFllYXIsIE1vbnRoLCBQYXgpDQpgYGANCg0KTm93LCB3ZSBoYXZlIGEgbmV3IGRhdGEgc2V0LCBmbGlnaHQxLCB3aXRoIG9ubHkgdGhlIHZhcmlhYmxlcyB3ZSBhcmUgaW50ZXJlc3RlZCBpbiBmb3Igb3VyIHRpbWUgc2VyaWVzIHByb2plY3QuDQoNCg0KIyMgVmFyaWFibGVzDQoNClRoZXJlIGFyZSB0aHJlZSB2YXJpYWJsZXMgZnJvbSB0aGUgb3JpZ2luYWwgZGF0YSBzZXQgd2hpY2ggd2Ugd2lsbCBiZSBpbnRlcmVzdGVkIGluIGZvciB0aGlzIHRpbWUgc2VyaWVzIHByb2plY3QuDQoNCiogWWVhcjogVGhlIHllYXIgb2Ygd2hpY2ggdGhlIG9ic2VydmF0aW9uIGlzIGZyb20uIFRoaXMgZGF0YSBzZXQgc3BhbnMgZnJvbSAyMDAzIHRvIDIwMjMuIA0KDQoqIE1vbnRoOiBUaGUgbW9udGggb2Ygd2hpY2ggdGhlIG9ic2VydmF0aW9uIGlzIGZyb20uIEdpdmVuIGFzIGEgdHdvIGRpZ2l0IG51bWJlciByZXByZXNlbnRpbmcgdGhlIG1vbnRoLiBGb3IgZXhhbXBsZSwgMDEgcmVwcmVzZW50cyBKYW51YXJ5LCAwMiByZXByZXNlbnRzIEZlYnJ1YXJ5LCBhbmQgc28gb24uDQoNCiogUGF4OiBUaGUgdG90YWwgbnVtYmVyIG9mIGFpciB0cmF2ZWwgcGFzc2VuZ2VycyBmb3IgYSBnaXZlbiBvYnNlcnZhdGlvbnMuIFRoaXMgaW5jbHVkZXMgYWlyIHBhc3NlbmdlcnMgb24gYm90aCBkb21lc3RpYyBhbmQgaW50ZXJuYXRpb25hbCBmbGlnaHRzLiANCg0KRHVyaW5nIG91ciBleHBsb3JhdG9yeSBkYXRhIGFuYWx5c2lzLCB3ZSB3aWxsIGNyZWF0ZSBhIG5ldyB2YXJpYWJsZSBjYWxsZWQgRGF0ZSB3aGljaCB3aWxsIGNvbWJpbmUgdGhlIHllYXIgYW5kIHRoZSBtb250aCB2YXJpYWJsZXMgdG8gZ2V0IGp1c3Qgb25lLCBzaW5nbGUgdmFyaWFibGUgdG8gcmVwcmVzZW50IHRoZSBkYXRlIG9mIHdoaWNoIGFuIG9ic2VydmF0aW9uIG9jY3VycmVkLiBUaGUgZGF0ZSB2YXJpYWJsZSB3ZSB3aWxsIGNyZWF0ZSB3aWxsIGJlIGdpdmVuIGluIHRoZSBmb3JtYXQgb2YgWWVhci1Nb250aC4gDQoNCg0KDQoNCiMgRXhwbG9yYXRvcnkgRGF0YSBBbmFseXNpcw0KDQpGaXJzdCwgbGV0J3MgZW5zdXJlIHRoYXQgdGhlcmUgYXJlIG5vdCBhbnkgbWlzc2luZyB2YXJpYWJsZXMgaW4gdGhpcyBkYXRhIHNldC4gDQpgYGB7cn0NCmNvbFN1bXMoaXMubmEoZmxpZ2h0MSkpDQpgYGANCg0KQXMgd2UgY2FuIHNlZSwgdGhlcmUgYXJlIHplcm8gbWlzc2luZyB2YWx1ZXMgaW4gb3VyIGRhdGEgc2V0LCBzbyB0aGF0IG1lYW5zIHdlIGRvIG5vdCBoYXZlIHRvIHdvcnJ5IGFib3V0IGZpbGxpbmcgaW4gYW55IG1pc3Npbmcgb2JzZXJ2YXRpb25zLiBXZSBjYW4gcHJvY2VlZCB3aXRoIG91ciB0aW1lIHNlcmllcyBwcm9qZWN0LiAgDQoNCk5leHQsIHdlIHdpbGwgY29tYmluZSB0aGUgWWVhciBhbmQgTW9udGggdmFyaWFibGVzIGludG8gb25lIHZhcmlhYmxlIGNhbGxlZCBEYXRlIHdoaWNoIGlzIGdpdmVuIGFzIHllYXIgYW5kIG1vbnRoIGNvbWJpbmVkLCBpbiB0aGUgZm9ybWF0IG9mIFllYXItTW9udGguIFdlIHdpbGwgY3JlYXRlIGEgbmV3IGRhdGEgc2V0IHdpdGggdGhlIGNvbWJpbmVkIERhdGUgdmFyaWFibGUgYW5kIHdlIHdpbGwgY2FsbCB0aGlzIG5ldyBkYXRhIHNldCAiZmxpZ2h0MiIuIA0KDQpgYGB7cn0NCmZsaWdodDIgPC0gZmxpZ2h0MSAlPiUNCiAgbXV0YXRlKERhdGUgPSBwYXN0ZShZZWFyLCBzcHJpbnRmKCIlMDJkIiwgTW9udGgpLCBzZXAgPSAiLSIpKQ0KZmxpZ2h0MiA8LSBzZWxlY3QoZmxpZ2h0MiwgLTEsLTIpDQpgYGANCg0KTm93LCB3ZSBoYXZlIGEgZGF0YSBzZXQgImZsaWdodDIiIHdpdGgganVzdCB0aGUgRGF0ZSwgZ2l2ZW4gaW4gYSBZZWFyLU1vbnRoIGZvcm1hdCwgYW5kIHRoZSBQYXggdmFyaWFibGUgcmVwcmVzZW50aW5nIHRoZSB0b3RhbCBudW1iZXIgb2YgYWlyIHRyYXZlbCBwYXNzZW5nZXJzLiANCg0KT25lIHRoaW5nIEkgbm90aWNlZCBpcyB0aGF0IHRoZSBQYXggdmFyaWFibGUgaXMgaW5jb3JyZWN0bHkgZ2l2ZW4gYXMgYSBjaGFyYWN0ZXIgdmFyaWFibGUgd2hlbiBpdCBzaG91bGQgcmVhbGx5IGJlIGEgbnVtZXJpYyB2YXJpYWJsZSBzaW5jZSBpdCByZXByZXNlbnRzIHRoZSB0b3RhbCBudW1iZXIgb2YgYWlyIHRyYXZlbCBwYXNzZW5nZXJzLiBXZSB3aWxsIGNoYW5nZSB0aGUgdmFyaWFibGUgdHlwZSBvZiB0aGUgUGF4IHZhcmlhYmxlIGZyb20gYSBjaGFyYWN0ZXIgdG8gYSBudW1lcmljIHZhcmlhYmxlIGluIG9yZGVyIHRvIGZpeCB0aGlzIGlzc3VlLiBXZSB3aWxsIHJlbW92ZSB0aGUgY29tbWFzIGZyb20gdGhlIFBheCB2YXJpYWJsZSBiZWZvcmUgY29udmVydGluZyBpdCB0byBhIG51bWVyaWMgdmFyaWFibGUgdG8gYXZvaWQgYW55IHByb2JsZW1zIHdpdGggdGhlIGNvbnZlcnNpb24gb2YgdGhlIHZhcmlhYmxlIHR5cGUuDQoNCmBgYHtyfQ0KZmxpZ2h0MiRQYXggPC0gZ3N1YigiLCIsICIiLCBmbGlnaHQyJFBheCkgDQpmbGlnaHQyJFBheCA8LSBhcy5udW1lcmljKGZsaWdodDIkUGF4KQ0KYGBgDQoNCk5vdyB3ZSBoYXZlIHRoZSBwcm9wZXIgZGF0YSBzZXQgd2UgY2FuIHVzZSB0byBjcmVhdGUgdGhlIHRpbWUgc2VyaWVzLiBUaGlzIGRhdGEgc2V0IHByb3ZpZGVzIG1vbnRobHkgYXZlcmFnZXMgZm9yIHRoZSBudW1iZXIgb2YgYWlyIHRyYXZlbCBwYXNzZW5nZXJzIGZvciBhbGwgZG9tZXN0aWMgYW5kIGludGVybmF0aW9uYWwgZmxpZ2h0cy4gDQoNCg0KIyMgVGltZSBTZXJpZXMgUGxvdA0KDQpOb3csIHdlIHdpbGwgY3JlYXRlIGEgdGltZSBzZXJpZXMgb2JqZWN0IGZyb20gb3VyIGZsaWdodCBkYXRhIGFuZCBwbG90IGl0IHRvIGhlbHAgdmlzdWFsaXplIGFueSBwb3RlbnRpYWwgdHJlbmRzIHRoYXQgbWF5IGJlIG9jY3VycmluZyB3aXRoaW4gdGhpcyB0aW1lIHNlcmllcyBkYXRhIHNldC4gV2Ugd2lsbCBjYWxsIHRoaXMgdGltZSBzZXJpZXMgb2JqZWN0ICJmbGlnaHQudHMiLiBTaW5jZSB3ZSBhcmUgY3JlYXRpbmcgYSBtb250aGx5IHRpbWUgc2VyaWVzIGxvb2tpbmcgYXQgdGhlIGF2ZXJhZ2UgbnVtYmVyIG9mIGFpciB0cmF2ZWwgcGFzc2VuZ2VycyBieSBtb250aCwgb3VyIGZyZXF1ZW5jeSB3aWxsIGJlIDEyLiANCg0KYGBge3J9DQpmbGlnaHQudHMgPC0gdHMoZmxpZ2h0MiRQYXgsIHN0YXJ0ID0gYygyMDAzLCAxKSwgZnJlcXVlbmN5ID0gMTIpDQpwbG90KGZsaWdodC50cywgbWFpbiA9ICJNb250aGx5IEF2ZXJhZ2UgQWlyIFRyYXZlbCBQYXNzZW5nZXJzIGZyb20gMjAwMyB0byAyMDIzIiwgeGxhYiA9ICJZZWFyIiwgeWxhYiA9ICJBaXIgVHJhdmVsIFBhc3NlbmdlcnMiKQ0KYGBgDQoNCkxvb2tpbmcgYXQgdGhlIHRpbWUgc2VyaWVzIHBsb3QsIHdlIGNhbiBzZWUgc29tZSBub3RhYmxlIG9jY3VycmVuY2VzIHdpdGhpbiBvdXIgZGF0YS4gVGhlcmUgaXMgY2VydGFpbmx5IHNvbWUgc29ydCBvZiBzZWFzb25hbGl0eSBnb2luZyBvbiB3aXRoaW4gb3VyIHRpbWUgc2VyaWVzIHdoaWNoIGNhbiBiZSBzZWVuIGJ5IGhvdyB0aGUgcGxvdCBoYXMgYSBwYXR0ZXJuIHdoaWNoIHJlcGVhdHMgYWZ0ZXIgYSBjZXJ0YWluIGFtb3VudCBvZiB0aW1lLiBJdCBsb29rcyBsaWtlIHRoaXMgdGltZSBzZXJpZXMgbWlnaHQgaGF2ZSBhbiBhbm51YWwgc2Vhc29uYWxpdHksIHdpdGggdGhpcyByZXBldGl0aW9uIG9jY3VycmluZyBhZnRlciBhIHllYXIgaGFzIGdvbmUgYnkuIFRoaXMgd291bGQgbWFrZSBzZW5zZSB0aGF0IHRoZSBudW1iZXIgb2YgYWlyIHRyYXZlbCBwYXNzZW5nZXJzIHdvdWxkIGhhdmUgYW4gYW5udWFsIHNlYXNvbmFsaXR5LCBiZWNhdXNlIG1vcmUgcGVvcGxlIGxpa2VseSB0cmF2ZWwgZHVyaW5nIHRoZSBzdW1tZXIgbW9udGhzIGR1ZSB0byB0aGUgaWRlYWwgd2VhdGhlciBhbmQgZm9yIGZhbWlsaWVzIHRoaXMgd291bGQgbWVhbiB0aGVpciBjaGlsZHJlbiB3b3VsZCBiZSBvbiBzdW1tZXIgYnJlYWsgd2hpY2ggd291bGQgbWFrZSBoYXZpbmcgYSB2YWNhdGlvbiBkdXJpbmcgdGhlIHN1bW1lciBhbiBvcHRpbWFsIHRpbWluZy4gSXQgd291bGQgbWFrZSBzZW5zZSB0aGF0IHRoZSBudW1iZXIgb2YgYWlyIHRyYXZlbCBwYXNzZW5nZXJzIHdvdWxkIHBlYWsgZHVyaW5nIHRoZSBzdW1tZXIgbW9udGhzLCBhbmQgdGhlbiBkcm9wIGJhY2sgZG93biB1bnRpbCB0aGVyZSBpcyBhbm90aGVyIHNsaWdodCByaXNlIGFyb3VuZCB0aGUgaG9saWRheSBtb250aHMgaW4gdGhlIHdpbnRlciB0aW1lIGR1ZSB0byBwZW9wbGUgdHJhdmVsbGluZyB0byBzcGVuZCB0aGUgaG9saWRheXMgd2l0aCB0aGVpciBmYW1pbHkuIE92ZXJhbGwsIGFuIGFubnVhbCBzZWFzb25hbGl0eSB3b3VsZCBtYWtlIHNlbnNlIGZvciBhIHRpbWUgc2VyaWVzIG9uIHRoZSBudW1iZXIgb2YgYWlyIHRyYXZlbCBwYXNzZW5nZXJzLiANCg0KQW5vdGhlciBub3RhYmxlIG9jY3VycmVuY2Ugd2l0aGluIHRoaXMgdGltZSBzZXJpZXMgaXMgdGhhdCB0aGVyZSBhcHBlYXJzIHRvIGJlIGEgdHJlbmQgb2Ygc2xpZ2h0IG92ZXJhbGwgaW5jcmVhc2UgaW4gdGhlIG51bWJlciBvZiBhaXIgdHJhdmVsIHBhc3NlbmdlcnMgZnJvbSB0aGUgc3RhcnQgb2YgdGhlIHRpbWUgc2VyaWVzIHVwIHVudGlsIHRoZSBlbmQuIFRoZXJlIGlzIGFuIGVzcGVjaWFsbHkgbm90aWNlYWJsZSB0cmVuZCBvZiBvdmVyYWxsIGluY3JlYXNlIGZyb20gYXJvdW5kIDIwMTAgdXAgdW50aWwgMjAxOS4gV2UgY2FuIHNlZSB0aGF0IHRoZXJlIGlzIGFuIGluY3JlZGlibHkgbWFzc2l2ZSBkZWNyZWFzZSBpbiB0aGUgbnVtYmVyIG9mIGFpciB0cmF2ZWwgcGFzc2VuZ2VycyBhcm91bmQgMjAyMC4gVGhpcyBjYW4gYmUgYXR0cmlidXRlZCB0byB0aGUgdHJhdmVsIHJlc3RyaWN0aW9ucyB3aGljaCB3ZXJlIHB1dCBpbiBwbGFjZSBkdXJpbmcgdGhlIGVhcmx5IGRheXMgb2YgdGhlIGNvdmlkIHBhbmRlbWljLiBUaGlzIHdvdWxkIGV4cGxhaW4gd2h5IHRoZXJlIGlzIHN1Y2ggYSBkcmFzdGljIGRlY2xpbmUgaW4gdGhlIG51bWJlciBvZiBhaXIgdHJhdmVsIHBhc3NlbmdlcnMgc2VlbiBpbiB0aGUgeWVhciAyMDIwLiBBZnRlciB0aGlzIGRlY2xpbmUgaW4gMjAyMCwgd2UgY2FuIHNlZSB0aGF0IHRoZSBudW1iZXIgb2YgYWlyIHRyYXZlbCBwYXNzZW5nZXJzIGJlZ2lucyB0byBncmFkdWFsbHkgaW5jcmVhc2Ugb3ZlciB0aGUgZm9sbG93aW5nIHllYXJzLCBhbmQgaXQgYXBwZWFycyB0aGF0IHRoZSBudW1iZXJzIGF0IHRoZSBlbmQgb2YgdGhlIHRpbWUgc2VyaWVzIGluIDIwMjMgYXJlIGZhaXJseSBzaW1pbGFyIHRvIHdoYXQgdGhleSB3ZXJlIHJpZ2h0IGJlZm9yZSB0aGUgbWFqb3IgZGVjbGluZSBzZWVuIGluIDIwMjAuIA0KDQoNCg0KDQojIERhdGEgU3BsaXQNCg0KV2Ugd2lsbCBzcGxpdCBvdXIgdGltZSBzZXJpZXMgZGF0YSBpbnRvIHR3byBkYXRhIHNldHMsIG9uZSBmb3IgdHJhaW5pbmcsIGFuZCBvbmUgZm9yIHRlc3RpbmcuIFNpbmNlIHdlIGhhdmUgYSBtb250aGx5IHRpbWUgc2VyaWVzLCB3ZSB3aWxsIHVzZSB0aGUgMTIgbW9zdCByZWNlbnQgb2JzZXJ2YXRpb25zIGZvciB0aGUgdGVzdGluZyBkYXRhIHNldC4gVGhlIHJlc3Qgb2YgdGhlIG9ic2VydmF0aW9ucyB3aWxsIGJlIHVzZWQgZm9yIHRoZSB0cmFpbmluZyBkYXRhIHNldC4gV2Ugd2lsbCBhbHNvIGNyZWF0ZSBhIHRpbWUgc2VyaWVzIG9iamVjdCBmb3IganVzdCB0aGUgdHJhaW5pbmcgZGF0YSBzZXQuIFdlIHdpbGwgY2FsbCB0aGlzIHRpbWUgc2VyaWVzIG9iamVjdCAiZmxpZ2h0LnRzMSIuDQoNCmBgYHtyfQ0KdGVzdC5mbGlnaHQgPC0gZmxpZ2h0MiRQYXhbMjM4OjI0OV0NCnRyYWluLmZsaWdodCA8LSBmbGlnaHQyJFBheFsxOjIzOF0NCmZsaWdodC50czEgPC0gdHMoZmxpZ2h0MiRQYXhbMToyMzhdLCBzdGFydCA9IGMoMjAwMywgMSksIGZyZXF1ZW5jeSA9IDEyKQ0KYGBgDQoNCk5vdyB3ZSBoYXZlIHNwbGl0IG91ciB0aW1lIHNlcmllcyBkYXRhIHNldCB1cCBpbnRvIGEgdHJhaW5pbmcgYW5kIGEgdGVzdGluZyBkYXRhIHNldC4gV2Ugd2lsbCB1c2UgdGhlIHRyYWluaW5nIGRhdGEgc2V0IHRvIHRyYWluIHRoZSBzbW9vdGhpbmcgbW9kZWxzIHdlIHdpbGwgY3JlYXRlLiBXZSB3aWxsIHVzZSB0aGUgdGVzdGluZyBkYXRhIHNldCB0byBpZGVudGlmeSB3aGljaCBvZiB0aGVzZSBzbW9vdGhpbmcgbW9kZWxzIHdlIHdpbGwgY3JlYXRlIGlzIHRoZSBiZXN0IG9uZSB0byB1c2UuIFNvLCB3ZSB3aWxsIG5leHQgYmVnaW4gd2l0aCBjcmVhdGluZyB0aGVzZSBzbW9vdGhpbmcgbW9kZWxzIGFuZCB3ZSB3aWxsIHVzZSB0aGUgdHJhaW5pbmcgYW5kIHRlc3RpbmcgZGF0YSBzZXRzIHRvIGhlbHAgdXMgd2l0aCBidWlsZGluZyBlYWNoIG9mIHRoZXNlIG1vZGVscyBhbmQgdGhlbiBkZXRlcm1pbmluZyB3aGljaCBtb2RlbCBpcyB0aGUgYmVzdCBvbmUgdG8gdXNlLiANCg0KDQoNCg0KIyBTbW9vdGhpbmcgTW9kZWxzDQoNCldlIHdpbGwgbm93IGJlZ2luIHdpdGggYnVpbGRpbmcgdGhlIHNtb290aGluZyBtb2RlbHMgc28gd2UgY2FuIHVsdGltYXRlbHkgZGV0ZXJtaW5lIHdoaWNoIG9uZSBkb2VzIHRoZSBiZXN0IGFuZCB3b3VsZCBiZSB0aGUgYmVzdCB0byB1c2UuIFdlIHdpbGwgY3JlYXRlIHRocmVlIGRpZmZlcmVudCB0eXBlcyBvZiBzbW9vdGhpbmcgbW9kZWxzLiBUaGVzZSBkaWZmZXJlbnQgbW9kZWxzIHdpbGwgaW5jbHVkZSBhIHNpbXBsZSBleHBvbmVudGlhbCBzbW9vdGhpbmcgbW9kZWwsIEhvbHQgbW9kZWxzIChhZGRpdGl2ZSBhbmQgd2l0aCBhIHBvc3NpYmxlIGRhbXBlZCBwYXR0ZXJuKSwgYW5kIEhvbHQtV2ludGVyJ3MgbW9kZWxzIChhZGRpdGl2ZSBhbmQgbXVsdGlwbGljYXRpdmUgc2Vhc29uYWxpdHkgd2l0aCBhIHBvc3NpYmxlIGRhbXBlZCBwYXR0ZXJuKS4NCg0KDQojIyBTaW1wbGUgRXhwb25lbnRpYWwgU21vb3RoaW5nIE1vZGVsDQoNCkZpcnN0LCB3ZSB3aWxsIGJlZ2luIHdpdGggY3JlYXRpbmcgdGhlIHNpbXBsZSBleHBvbmVudGlhbCBzbW9vdGhpbmcgbW9kZWwuIFdlIHdpbGwgY2FsbCB0aGlzIHNpbXBsZSBleHBvbmVudGlhbCBzbW9vdGhpbmcgbW9kZWwgImZpdDEiLg0KDQpgYGB7cn0NCiMgU2ltcGxlIEV4cG9uZW50aWFsIFNtb290aGluZyBNb2RlbA0KZml0MSA8LSBzZXMoZmxpZ2h0LnRzMSwgaCA9IDEyKQ0KYGBgDQoNCk5vdyB3ZSBoYXZlIGNyZWF0ZWQgb3VyIHNpbXBsZSBleHBvbmVudGlhbCBzbW9vdGhpbmcgbW9kZWwuDQoNCg0KIyMgSG9sdCBNb2RlbHMNCg0KTmV4dCwgd2Ugd2lsbCBjcmVhdGUgdGhlIEhvbHQgbW9kZWxzLiBXZSB3aWxsIHVzZSB0aHJlZSBkaWZmZXJlbnQga2luZHMgb2YgSG9sdCBtb2RlbHMuIFRoZSBmaXJzdCBvZiBvdXIgSG9sdCBtb2RlbHMgd2lsbCBiZSBhIGxpbmVhciBIb2x0IG1vZGVsLCBhbmQgd2Ugd2lsbCBjYWxsIHRoaXMgImZpdDIiLiBPdXIgbmV4dCBIb2x0IG1vZGVsIHdpbGwgYmUgYW4gYWRkaXRpdmUgSG9sdCBtb2RlbCB3aXRoIGEgcG9zc2libGUgZGFtcGVkIHBhdHRlcm4sIGFuZCB0aGlzIHdpbGwgYmUgY2FsbGVkICJmaXQzIi4gT3VyIGxhc3QgSG9sdCBtb2RlbCB3aWxsIGJlIGFuIGV4cG9uZW50aWFsIEhvbHQgbW9kZWwgd2l0aCBhIHBvc3NpYmxlIGRhbXBlZCBwYXR0ZXJuLCBhbmQgdGhpcyB3aWxsIGJlIGNhbGxlZCAiZml0NCIuIA0KDQpgYGB7cn0NCiMgSG9sdCBMaW5lYXIgTW9kZWwNCmZpdDIgPC0gaG9sdChmbGlnaHQudHMxLCBpbml0aWFsID0gIm9wdGltYWwiLCBoID0gMTIpICAgICAgIA0KDQojIEhvbHQgQWRkaXRpdmUgTW9kZWwgd2l0aCBhIFBvc3NpYmxlIERhbXBlZCBQYXR0ZXJuIA0KZml0MyA8LSBob2x0KGZsaWdodC50czEsIGRhbXBlZCA9IFRSVUUsIGggPSAxMikgICAgICAgICAgICAgICAgICANCg0KIyBIb2x0IEV4cG9uZW50aWFsIE1vZGVsIHdpdGggYSBQb3NzaWJsZSBEYW1wZWQgUGF0dGVybg0KZml0NCA8LSBob2x0KGZsaWdodC50czEsIGV4cG9uZW50aWFsID0gVFJVRSwgZGFtcGVkID0gVFJVRSwgaCA9IDEyKSANCmBgYA0KDQpOb3cgd2UgaGF2ZSBzdWNjZXNzZnVsbHkgY3JlYXRlZCBvdXIgSG9sdCBtb2RlbHMuIA0KDQoNCiMjIEhvbHQtV2ludGVyJ3MgTW9kZWxzDQoNCkxhc3RseSwgd2Ugd2lsbCBjcmVhdGUgb3VyIEhvbHQgV2ludGVyJ3MgbW9kZWxzLiBXZSB3aWxsIHVzZSBmb3VyIGRpZmZlcmVudCBraW5kcyBvZiBIb2x0LVdpbnRlcidzIG1vZGVscy4gVGhlIGZpcnN0IG9mIHRoZXNlIHdpbGwgYmUgYSBIb2x0LVdpbnRlcidzIGFkZGl0aXZlIG1vZGVsLCBhbmQgdGhpcyB3aWxsIGJlIGNhbGxlZCAiZml0NSIuIFRoZSBuZXh0IHdpbGwgYmUgYSBIb2x0LVdpbnRlcidzIG11bHRpcGxpY2F0aXZlIG1vZGVsLCBhbmQgdGhpcyB3aWxsIGJlIGNhbGxlZCAiZml0NiIuIFRoZSBuZXh0IG9uZSBhZnRlciB3aWxsIGJlIGEgSG9sdC1XaW50ZXIncyBhZGRpdGl2ZSBtb2RlbCB3aXRoIGEgcG9zc2libGUgZGFtcGVkIHBhdHRlcm4sIGFuZCB0aGlzIHdpbGwgYmUgY2FsbGVkICJmaXQ3Ii4gVGhlIGxhc3Qgb2YgdGhlc2UgbW9kZWxzIHdpbGwgYmUgYSBIb2x0LVdpbnRlcidzIG11bHRpcGxpY2F0aXZlIG1vZGVsIHdpdGggYSBwb3NzaWJsZSBkYW1wZWQgcGF0dGVybiwgYW5kIHRoaXMgd2lsbCBiZSBjYWxsZWQgImZpdDgiLg0KDQpgYGB7cn0NCiMgSG9sdC1XaW50ZXIncyBBZGRpdGl2ZSBNb2RlbA0KZml0NSA8LSBodyhmbGlnaHQudHMxLCBoID0gMTIsIHNlYXNvbmFsID0gImFkZGl0aXZlIikgICAgIA0KDQojIEhvbHQtV2ludGVyJ3MgTXVsdGlwbGljYXRpdmUgTW9kZWwNCmZpdDYgPC0gaHcoZmxpZ2h0LnRzMSwgaCA9IDEyLCBzZWFzb25hbCA9ICJtdWx0aXBsaWNhdGl2ZSIpDQoNCiMgSG9sdC1XaW50ZXIncyBBZGRpdGl2ZSBNb2RlbCB3aXRoIGEgUG9zc2libGUgRGFtcGVkIFBhdHRlcm4NCmZpdDcgPC0gaHcoZmxpZ2h0LnRzMSwgaCA9IDEyLCBzZWFzb25hbCA9ICJhZGRpdGl2ZSIsIGRhbXBlZD1UUlVFKQ0KDQojIEhvbHQtV2ludGVyJ3MgTXVsdGlwbGljYXRpdmUgTW9kZWwgd2l0aCBhIFBvc3NpYmxlIERhbXBlZCBQYXR0ZXJuDQpmaXQ4IDwtIGh3KGZsaWdodC50czEsIGggPSAxMiwgc2Vhc29uYWwgPSAibXVsdGlwbGljYXRpdmUiLCBkYW1wZWQ9VFJVRSkNCmBgYA0KDQpOb3cgd2UgaGF2ZSBzdWNjZXNzZnVsbHkgY3JlYXRlZCBhbGwgb2Ygb3VyIEhvbHQtV2ludGVyJ3MgbW9kZWxzLiANCg0KDQoNCg0KIyBBY2N1cmFjeSBNZWFzdXJlcw0KDQpOb3cgdGhhdCB3ZSBoYXZlIGNyZWF0ZWQgdmFyaW91cyBtb2RlbHMgdG8gdHJ5IG91dCwgaW5jbHVkaW5nIGEgc2ltcGxlIGV4cG9uZW50aWFsIG1vZGVsLCBIb2x0IG1vZGVscywgYW5kIEhvbHQtV2ludGVyJ3MgbW9kZWxzLCB3ZSB3aWxsIHVzZSBhY2N1cmFjeSBtZWFzdXJlcyB0byBjb21wYXJlIGFsbCBvZiB0aGVzZSBkaWZmZXJlbnQgbW9kZWxzLiBUaGVzZSBhY2N1cmFjeSBtZWFzdXJlcyB3aWxsIGJlIGJhc2VkIHVwb24gdGhlIHRyYWluaW5nIGRhdGEgc2V0IHRoYXQgd2UgY3JlYXRlZCBmcm9tIG91ciB0aW1lIHNlcmllcyBkYXRhLiANCg0KYGBge3J9DQphY2N1cmFjeS50YWJsZSA9IHJvdW5kKHJiaW5kKGFjY3VyYWN5KGZpdDEpLCBhY2N1cmFjeShmaXQyKSwgYWNjdXJhY3koZml0MyksIGFjY3VyYWN5KGZpdDQpLCBhY2N1cmFjeShmaXQ1KSwgYWNjdXJhY3koZml0NiksIGFjY3VyYWN5KGZpdDcpLCBhY2N1cmFjeShmaXQ4KSksIDQpDQpyb3cubmFtZXMoYWNjdXJhY3kudGFibGUpPWMoIlNFUyIsIkhvbHQgTGluZWFyIiwiSG9sdCBBZGQuIERhbXBlZCIsICJIb2x0IE11bHQuIERhbXBlZCIsICJIVyBBZGQuIiwiSFcgTXVsdC4iLCJIVyBBZGQuIERhbXBlZCIsICJIVyBNdWx0LiBEYW1wZWQiKQ0KDQprYWJsZShhY2N1cmFjeS50YWJsZSwgY2FwdGlvbiA9ICJBY2NjdXJhY3kgTWVhc3VyZXMgb2YgdGhlIFZhcmlvdXMgU21vb3RoaW5nIE1vZGVscyBCYXNlZCB1cG9uIHRoZSBUcmFpbmluZyBEYXRhIFNldCIpDQpgYGANCg0KVG8gaW50ZXJwcmV0IG91ciBhY2N1cmFjeSB0YWJsZSwgd2UgaGF2ZSBzZXZlcmFsIG1lYXN1cmVzIG9mIGFjY3VyYWN5IHdlIGxvb2tlZCBhdC4gVGhlIE1FLCBvciBtZWFuIGVycm9ycywgcmVwcmVzZW50cyBob3cgZmFyIG9mZiB0aGUgcHJlZGljdGlvbnMgYXJlIGZyb20gdGhlaXIgYWN0dWFsIHZhbHVlcy4gVGhlIEhvbHQgQWRkLiBEYW1wZWQgYW5kIEhvbHQgTXVsdC4gRGFtcGVkIGhhdmUgdGhlIHNtYWxsZXN0IGFic29sdXRlIHZhbHVlIG9mIHRoZWlyIE1FLiBOZXh0LCB3ZSBoYXZlIFJNU0UsIE1BRSwgYW5kIE1BUEUsIGFsbCBvZiB3aGljaCBhIGxvd2VyIHZhbHVlIGlzIGlkZWFsIGJlY2F1c2UgaXQgaW5kaWNhdGVzIHRoZSBsZWFzdCBlcnJvcnMuIEZyb20gdGhlc2UgYWNjdXJhY3kgbWVhc3VyZW1lbnRzLCB0aGUgSFcgQWRkLiwgYW5kIHRoZSBIVy4gQWRkLiBEYW1wZWQgc3RhbmQgb3V0IGZvciBoYXZpbmcgbm90YWJseSBsb3dlciB2YWx1ZXMgdGhhbiBhbnkgb2YgdGhlIG90aGVyIG1vZGVscyBkby4gRm9yIHRoZSBNQVNFIG1lYXN1cmVtZW50LCBhIHZhbHVlIGNsb3Nlc3QgdG8gemVybyBpcyBpZGVhbC4gVGhlIEhXLiBBZGQgbW9kZWwgaGFzIHRoZSBjbG9zZXN0IE1BU0UgdG8gemVybywgbWFraW5nIHRoaXMgb25jZSBhZ2FpbiBzZWVtIGxpa2UgYSBzdHJvbmcgbW9kZWwuIExhc3RseSwgZm9yIHRoZSBBQ0YxIG1lYXN1cmVtZW50cywgYSB2YWx1ZSBjbG9zZXN0IHRvIHplcm8gaXMgaWRlYWwgZm9yIGFjY3VyYWN5LiBGcm9tIG91ciBtb2RlbHMsIHRoZSBIb2x0IExpbmVhciBtb2RlbCBoYXMgYW4gQUNGMSB0aGF0IGlzIGNsb3Nlc3QgdG8gemVyby4NCg0KT3ZlcmFsbCwgdGhlIEhvbHQtV2ludGVyJ3MgQWRkaXRpdmUgbW9kZWwgc3Rvb2Qgb3V0IGZvciBzaG93aW5nIGlkZWFsIHBlcmZvcm1hbmNlIGluIHRoZSBtb3N0IGFjY3VyYWN5IG1lYXN1cmVzIG9mIGFsbCBvZiB0aGUgbW9kZWxzLiBUaGlzIEhvbHQtV2ludGVyJ3MgQWRkaXRpdmUgbW9kZWwgaGFkIGxvdyBSTVNFLCBNQUUsIGFuZCBNQVBFLCBhcyB3ZWxsIGFzIGEgTUFTRSBjbG9zZXN0IHRvIHplcm8uIFNpbmNlIHRoZSBIb2x0LVdpbnRlcidzIEFkZGl0aXZlIG1vZGVsIHN0b29kIG91dCBpbiBtb3JlIGFjY3VyYWN5IG1lYXN1cmVtZW50cyB0aGFuIGFueSBvZiB0aGUgb3RoZXIgbW9kZWxzLCB3ZSB3aWxsIGNob29zZSB0aGlzIHNtb290aGluZyBtb2RlbCBhcyB0aGUgaWRlYWwgbW9kZWwgaW4gdGVybXMgb2YgcGVyZm9ybWFuY2UuIA0KDQoNCg0KDQojIFNlcmlhbCBQbG90IG9mIHRoZSBEYXRhDQoNCldlIHdpbGwgY3JlYXRlIGEgc2VyaWFsIHBsb3Qgb2YgdGhlIGhpc3RvcmljYWwgZGF0YSwgd2hpY2ggaXMgdGhlIGRhdGEgdGhhdCB3YXMgdXNlZCBmb3IgdGhlIHRyYWluaW5nIGRhdGEgc2V0LiBUaGlzIHdpbGwgYWxsb3cgdXMgdG8gZm9yZWNhc3QgdGhlIHZhbHVlcyBhbmQgdmlzdWFsaXplIHRoaXMgZm9yZWNhc3QuDQoNCldlIHdpbGwgY3JlYXRlIHR3byBzZXJpYWwgcGxvdHMsIG9uZSB3aWxsIGJlIGZvciB0aGUgbm9uLXNlYXNvbmFsIHNtb290aGluZyBtb2RlbHMsIHdoaWNoIHdpbGwgaW5jbHVkZSB0aGUgc2ltcGxlIGV4cG9uZW50aWFsIHNtb290aGluZyBtb2RlbCwgdGhlIEhvbHQgbGluZWFyLCB0aGUgSG9sdCBBZGRpdGl2ZSBEYW1wZWQsIGFuZCB0aGUgSG9sdCBNdWx0aXBsaWNhdGl2ZSBEYW1wZWQgbW9kZWxzLiBUaGUgb3RoZXIgc2VyaWFsIHBsb3Qgd2lsbCBiZSBmb3IgdGhlIHRyZW5kIGFuZCBzZWFzb25hbCBzbW9vdGhpbmcgbW9kZWxzLCB3aGljaCB3aWxsIGluY2x1ZGUgdGhlIEhXIEFkZGl0aXZlLCB0aGUgSFcgTXVsdGlwbGljYXRpdmUsIHRoZSBIVyBBZGRpdGl2ZSBEYW1wZWQsIGFuZCB0aGUgSFcgTXVsdGlwbGljYXRpdmUgRGFtcGVkIG1vZGVscy4gDQoNCkZpcnN0LCB3ZSB3aWxsIGNyZWF0ZSB0aGUgc2VyaWFsIHBsb3QgZm9yIHRoZSBub24tc2Vhc29uYWwgc21vb3RoaW5nIG1vZGVscy4gDQoNCmBgYHtyfQ0KcGFyKG1mcm93ID0gYygyLDEpLCBtYXIgPSBjKDMsNCwzLDEpKQ0KcHJlZC5pZCA9IDIzODoyNDkNCnBsb3QoMToyMzgsIGZsaWdodC50czEsIGx3ZCA9IDIsdHlwZSA9ICJvIiwgeWxhYiA9ICJBaXIgVHJhdmVsIFBhc3NlbmdlcnMiLCB4bGFiID0gIiIsIA0KICAgICB4bGltID0gYygxLCAyNDkpLCB5bGltPWMoMCwgODAwMDAwMDApLCBjZXggPSAwLjMsDQogICAgIG1haW4gPSAiTm9uLXNlYXNvbmFsIFNtb290aGluZyBNb2RlbHMiKQ0KbGluZXMocHJlZC5pZCwgZml0MSRtZWFuLCBjb2wgPSAicGluayIpDQpsaW5lcyhwcmVkLmlkLCBmaXQyJG1lYW4sIGNvbCA9ICJibHVlIikNCmxpbmVzKHByZWQuaWQsIGZpdDMkbWVhbiwgY29sID0gInB1cnBsZSIpDQpsaW5lcyhwcmVkLmlkLCBmaXQ0JG1lYW4sIGNvbCA9ICJuYXZ5IikNCg0KcG9pbnRzKHByZWQuaWQsIGZpdDEkbWVhbiwgcGNoID0gMTYsIGNvbCA9ICJwaW5rIiwgY2V4ID0gMC41KQ0KcG9pbnRzKHByZWQuaWQsIGZpdDIkbWVhbiwgcGNoID0gMTcsIGNvbCA9ICJibHVlIiwgY2V4ID0gMC41KQ0KcG9pbnRzKHByZWQuaWQsIGZpdDMkbWVhbiwgcGNoID0gMTksIGNvbCA9ICJwdXJwbGUiLCBjZXggPSAwLjUpDQpwb2ludHMocHJlZC5pZCwgZml0NCRtZWFuLCBwY2ggPSAyMSwgY29sID0gIm5hdnkiLCBjZXggPSAwLjUpDQoNCmxlZ2VuZCgiYm90dG9tcmlnaHQiLCBsdHkgPSAxLCBjb2wgPSBjKCJwaW5rIiwiYmx1ZSIsInB1cnBsZSIsIm5hdnkiKSwgcGNoID0gYygxNiwgMTcsIDE5LCAyMSksDQogICBjKCJTRVMiLCJIb2x0IExpbmVhciIsIkhvbHQgQWRkaXRpdmUgRGFtcGVkIiwgIkhvbHQgTXVsdGlwbGljYXRpdmUgRGFtcGVkIiksIA0KICAgY2V4ID0gMC41LCBidHkgPSAibiIpDQpgYGANCg0KV2UgY2FuIHNlZSBmcm9tIHRoZSBzZXJpYWwgcGxvdCB0aGF0IHRoaXMgdmlzdWFsaXplZCB0aGUgZm9yZWNhc3RzIGZvciB0aGUgbm9uLXNlYXNvbmFsIHNtb290aGluZyBtb2RlbHMgd2hpY2ggd2UgY3JlYXRlZC4NCg0KTmV4dCwgd2Ugd2lsbCBjcmVhdGUgdGhlIHNlcmlhbCBwbG90IGZvciB0aGUgSG9sdC1XaW50ZXIncyB0cmVuZCBhbmQgc2Vhc29uYWwgc21vb3RoaW5nIG1vZGVscy4NCg0KYGBge3J9DQpwbG90KDE6MjM4LCBmbGlnaHQudHMxLCBsd2QgPSAyLCB0eXBlID0gIm8iLCB5bGFiID0gIkFpciBUcmF2ZWwgUGFzc2VuZ2VycyIsIHhsYWIgPSAiIiwgDQogICAgIHhsaW09YygxLDI0OSksIHlsaW09YygwLCA4MDAwMDAwMCksIGNleCA9IDAuMywNCiAgICAgbWFpbj0iSG9sdC1XaW50ZXJzIFRyZW5kIGFuZCBTZWFzb25hbCBTbW9vdGhpbmcgTW9kZWxzIikNCmxpbmVzKHByZWQuaWQsIGZpdDUkbWVhbiwgY29sID0gInBpbmsiKQ0KbGluZXMocHJlZC5pZCwgZml0NiRtZWFuLCBjb2wgPSAiYmx1ZSIpDQpsaW5lcyhwcmVkLmlkLCBmaXQ3JG1lYW4sIGNvbCA9ICJwdXJwbGUiKQ0KbGluZXMocHJlZC5pZCwgZml0OCRtZWFuLCBjb2wgPSAibmF2eSIpDQoNCnBvaW50cyhwcmVkLmlkLCBmaXQ1JG1lYW4sIHBjaCA9IDE2LCBjb2wgPSAicGluayIsIGNleCA9IDAuNSkNCnBvaW50cyhwcmVkLmlkLCBmaXQ2JG1lYW4sIHBjaCA9IDE3LCBjb2wgPSAiYmx1ZSIsIGNleCA9IDAuNSkNCnBvaW50cyhwcmVkLmlkLCBmaXQ3JG1lYW4sIHBjaCA9IDE5LCBjb2wgPSAicHVycGxlIiwgY2V4ID0gMC41KQ0KcG9pbnRzKHByZWQuaWQsIGZpdDgkbWVhbiwgcGNoID0gMjEsIGNvbCA9ICJuYXZ5IiwgY2V4ID0gMC41KQ0KDQpsZWdlbmQoImJvdHRvbXJpZ2h0IiwgbHR5PTEsIGNvbCA9IGMoInBpbmsiLCJibHVlIiwicHVycGxlIiwgIm5hdnkiKSwgcGNoID0gYygxNiwgMTcsIDE5LCAyMSksDQogICBjKCJIVyBBZGRpdGl2ZSIsIkhXIE11bHRpcGxpY2F0aXZlIiwiSFcgQWRkaXRpdmUgRGFtcGVkIiwgIkhXIE11bHRpcGxpY2F0aXZlIERhbXBlZCIpLCANCiAgIGNleCA9IDAuNSwgYnR5ID0gIm4iKQ0KYGBgDQoNCldlIGNhbiBzZWUgZnJvbSB0aGlzIHNlcmlhbCBwbG90IHRoZSBmb3JlY2FzdHMgZm9yIHRoZSB0cmVuZCBhbmQgc2Vhc29uYWwgc21vb3RoaW5nIG1vZGVscy4NCg0KRnJvbSB0aGUgdHdvIHNlcmlhbCBwbG90cyB3ZSBjcmVhdGVkLCBpdCBsb29rcyBsaWtlIHRoZSBIb2x0LVdpbnRlcidzIEFkZGl0aXZlIG1vZGVsIG9uY2UgYWdhaW4gc2VlbXMgbGlrZSB0aGUgYmVzdCBvZiB0aGUgbW9kZWxzIHdlIGNyZWF0ZWQuIFRoaXMgbWF0Y2hlcyB1cCB3aXRoIHdoYXQgd2FzIGZvdW5kIGluIHRoZSBhY2N1cmFjeSB0YWJsZS4gSXQgbG9va3MgbGlrZSB0aGUgSG9sdCBXaW50ZXIncyBBZGRpdGl2ZSBNb2RlbCBwcm92aWRlcyBhIHF1YWxpdHkgZm9yZWNhc3QgaW4gdGhlIHNlcmlhbCBwbG90IGZvciB0aGUgSG9sdC1XaW50ZXIncyB0cmVuZCBhbmQgc2Vhc29uYWwgc21vb3RoaW5nIG1vZGVscy4NCg0KDQoNCg0KIyBGb3JlY2FzdGluZyB3aXRoIHRoZSBUZXN0aW5nIERhdGENCg0KTm93IHRoYXQgd2UgaGF2ZSBkZXRlcm1pbmVkIHdoaWNoIG1vZGVsIGxvb2tzIGxpa2UgdGhlIGlkZWFsIGNob2ljZSwgdGhlIEhvbHQtV2ludGVyJ3MgQWRkaXRpdmUgTW9kZWwsIHdlIHdpbGwgdXNlIHRoZSB0ZXN0aW5nIGRhdGEgc2V0IHdoaWNoIHdlIGNyZWF0ZWQgZWFybGllciB0byB2ZXJpZnkgb3VyIGJlc3QgbW9kZWwgc2VsZWN0aW9uLg0KDQpXZSBwcmV2aW91c2x5IHVzZWQgdGhlIHRyYWluaW5nIGRhdGEgc2V0IHRvIHRyYWluIHRoZSB2YXJpb3VzIHNtb290aGluZyBtb2RlbHMgd2UgbG9va2VkIGF0LiBUbyBjcmVhdGUgb3VyIHJlYWwtd29ybGQgZm9yZWNhc3QsIHdlIHdpbGwgcmVmaXQgdGhlIG1vZGVsIHVzaW5nIHRoZSB0ZXN0aW5nIGRhdGEgYXMgd2VsbC4gVGhpcyB3aWxsIGFsbG93IHVzIHRvIHZlcmlmeSBvdXIgZmluZGluZ3MgYW5kIGlmIHRoZSBtb2RlbCB3aGljaCBsb29rZWQgdG8gc2hvdyB0aGUgYmVzdCBwZXJmb3JtYW5jZSBpbiBmb3JlY2FzdGluZyB0cnVseSBsb29rcyBsaWtlIHRoZSBpZGVhbCBjaG9pY2UuDQoNCkZpcnN0LCB3ZSB3aWxsIHJlZml0IHRoZSBtb2RlbCB1c2luZyB0aGUgZW50aXJlIGRhdGEgc2V0IHRvIHVwZGF0ZSB0aGUgc21vb3RoaW5nIHBhcmFtZXRlcnMuDQoNCmBgYHtyfQ0KYWNjLmZ1biA9IGZ1bmN0aW9uKHRlc3QuZGF0YSwgbW9kLm9iail7DQogIFBFID0gMTAwKih0ZXN0LmRhdGEtbW9kLm9iaiRtZWFuKS9tb2Qub2JqJG1lYW4NCiAgTUFQRSA9IG1lYW4oYWJzKFBFKSkNCiAgRSA9IHRlc3QuZGF0YS1tb2Qub2JqJG1lYW4NCiAgTVNFID0gbWVhbihFXjIpDQogIGFjY3VyYWN5Lm1ldHJpYyA9IGMoTVNFID0gTVNFLCBNQVBFID0gTUFQRSkNCiAgYWNjdXJhY3kubWV0cmljDQp9DQpgYGANCg0KTm93LCB3ZSB3aWxsIGZpbmQgdGhlIHVwZGF0ZWQgYWNjdXJhY3kgcHJlZGljdGlvbiBtZWFzdXJlcyBmb3IgZWFjaCBvZiB0aGUgc21vb3RoaW5nIG1vZGVscyB3ZSBjcmVhdGVkLiANCg0KYGBge3J9DQpwcmVkLmFjY3VyYWN5ID0gcmJpbmQoU0VTID0gYWNjLmZ1bih0ZXN0LmRhdGEgPSB0ZXN0LmZsaWdodCwgbW9kLm9iaiA9IGZpdDEpLA0KICAgICAgICAgICAgICAgICAgICAgIEhvbHQuQWRkID0gYWNjLmZ1bih0ZXN0LmRhdGE9dGVzdC5mbGlnaHQsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtb2Qub2JqID0gZml0MiksDQogICAgICAgICAgICAgICAgICAgICAgSG9sdC5BZGQuRGFtcCA9IGFjYy5mdW4odGVzdC5kYXRhID0gdGVzdC5mbGlnaHQsICAgIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1vZC5vYmo9Zml0MyksDQogICAgICAgICAgICAgICAgICAgICAgSG9sdC5FeHAgPSBhY2MuZnVuKHRlc3QuZGF0YSA9IHRlc3QuZmxpZ2h0LCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbW9kLm9iaiA9IGZpdDQpLA0KICAgICAgICAgICAgICAgICAgICAgIEhXLkFkZCA9IGFjYy5mdW4odGVzdC5kYXRhID0gdGVzdC5mbGlnaHQsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbW9kLm9iaiA9IGZpdDUpLA0KICAgICAgICAgICAgICAgICAgICAgIEhXLkV4cCA9IGFjYy5mdW4odGVzdC5kYXRhID0gdGVzdC5mbGlnaHQsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbW9kLm9iaiA9IGZpdDYpLA0KICAgICAgICAgICAgICAgICAgICAgIEhXLkFkZC5EYW1wID0gYWNjLmZ1bih0ZXN0LmRhdGEgPSB0ZXN0LmZsaWdodCwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1vZC5vYmogPSBmaXQ3KSwNCiAgICAgICAgICAgICAgICAgICAgICBIVy5FeHAuRGFtcCA9IGFjYy5mdW4odGVzdC5kYXRhID0gdGVzdC5mbGlnaHQsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtb2Qub2JqID0gZml0OCkpDQprYWJsZShwcmVkLmFjY3VyYWN5LCBjYXB0aW9uID0gIkFjY3VyYWN5IE1lYXN1cmVzIG9mIHRoZSBWYXJpb3VzIEV4cG9uZW50aWFsIFNtb290aGluZyBNb2RlbHMgQmFzZWQgb24gdGhlIFRlc3RpbmcgRGF0YSBTZXQiKQ0KYGBgDQoNCkxvb2tpbmcgYXQgdGhlIGFjY3VyYWN5IG1lYXN1cmVzIGJhc2VkIG9uIHRoZSB0ZXN0aW5nIGRhdGEgc2V0LCB3ZSBjYW4gc2VlIHRoYXQgdGhlIEhvbHQtV2ludGVyJ3MgQWRkaXRpdmUgbW9kZWwgaGFzIGJvdGggdGhlIGxvd2VzdCBNU0UgYW5kIE1BUEUuIFRoaXMgaXMgaWRlYWwgYmVjYXVzZSB3ZSB3YW50IG91ciBtb2RlbCB0byByZWR1Y2UgdGhlIGVycm9ycyBhcyBtdWNoIGFzIHBvc3NpYmxlLiBBbHNvLCB0aGlzIG1hdGNoZXMgdXAgd2l0aCB3aGF0IHdlIGZvdW5kIGVhcmxpZXIsIGJlY2F1c2Ugb25jZSBhZ2FpbiB0aGUgSG9sdC1XaW50ZXIncyBBZGRpdGl2ZSBtb2RlbCBoYXMgdGhlIGJlc3QgcGVyZm9ybWFuY2UgaW4gdGVybXMgb2YgYWNjdXJhY3kuIFNvLCBpdCBsb29rcyBsaWtlIHRoZSBIb2x0LVdpbnRlcidzIEFkZGl0aXZlIG1vZGVsIGlzIHRoZSBpZGVhbCBjaG9pY2UsIGFuZCB0aGlzIGhhcyBiZWVuIHZlcmlmaWVkIHdpdGggdGhlIHRlc3RpbmcgZGF0YSBzZXQuIA0KDQoNCg0KDQojIEZpbmFsIE1vZGVsDQoNCkJhc2VkIHVwb24gb3VyIGZpbmRpbmdzLCBpdCBsb29rcyBsaWtlIHRoZSBIb2x0LVdpbnRlcidzIEFkZGl0aXZlIG1vZGVsIGlzIHRoZSBpZGVhbCBjaG9pY2Ugb3V0IG9mIHRoZSBtYW55IHBvc3NpYmxlIGNhbmRpZGF0ZSBtb2RlbHMgd2UgY3JlYXRlZC4gVGhpcyBtb2RlbCBzaG93ZWQgaXRzIGlkZWFsIHBlcmZvcm1hbmNlIGJ5IHJlZHVjaW5nIHRoZSBlcnJvcnMgbW9yZSBzaWduaWZpY2FudGx5IHRoYW4gYW55IG9mIHRoZSBvdGhlciBtb2RlbHMgZGlkLiBUaGlzIEhvbHQtV2ludGVyJ3MgQWRkaXRpdmUgbW9kZWwgYWxzbyBzaG93ZWQgdGhlIGJlc3QgcGVyZm9ybWFuY2UgaW4gdGVybXMgb2YgdGhlIGFjY3VyYWN5IG1lYXN1cmVzLCBiZWNhdXNlIGl0IGhhZCB0aGUgbG93ZXN0IE1TRSBhbmQgTUFQRSB2YWx1ZXMgb2Ygb3V0IGFueSBvZiB0aGUgbW9kZWxzLiBTbywgdGhlIEhvbHQtV2ludGVyJ3MgQWRkaXRpdmUgbW9kZWwgaXMgdGhlIGlkZWFsIG1vZGVsIG91dCBvZiBhbGwgdGhlIGNhbmRpZGF0ZSBtb2RlbHMgd2UgY3JlYXRlZCBhbmQgdHJpZWQgb3V0Lg0KDQoNCiMjIFNtb290aGluZyBQYXJhbWV0ZXJzDQoNCldlIHdpbGwgdGFrZSBhIGxvb2sgYXQgdGhlIHNtb290aGluZyBwYXJhbWV0ZXJzIGZvciB0aGUgSG9sdC1XaW50ZXIncyBBZGRpdGl2ZSBtb2RlbC4gDQoNCmBgYHtyfQ0KZmluYWwubW9kZWwgPC0gaHcoZmxpZ2h0LnRzMSwgaCA9IDEyLCBzZWFzb25hbCA9ICJhZGRpdGl2ZSIpDQpzbW9vdGhpbmcucGFyYW1ldGVyID0gZmluYWwubW9kZWwkbW9kZWwkcGFyWzE6M10NCmthYmxlKHNtb290aGluZy5wYXJhbWV0ZXIsIGNhcHRpb249IlRoZSBFc3RpbWF0ZWQgVmFsdWVzIG9mIHRoZSBTbW9vdGhpbmcgUGFyYW1ldGVycyBpbiB0aGUgSG9sdC1XaW50ZXJzIEFkZGl0aXZlIE1vZGVsIikNCmBgYA0KDQpUaGUgc21vb3RoaW5nIHBhcmFtZXRlcnMgZm9yIG91ciBmaW5hbCBtb2RlbCwgdGhlIEhvbHQtV2ludGVyJ3MgQWRkaXRpdmUgbW9kZWwsIGluY2x1ZGUgYW4gYWxwaGEgb2YgMC45OTk5LCBhIGJldGEgb2YgMC4wMDA0LCBhbmQgYSBnYW1tYSBvZiAwLjAwMDEuIA0KICANCg0KDQoNCiMgQ29uY2x1c2lvbg0KDQpPdmVyYWxsLCB3ZSBsb29rZWQgYXQgYSBkYXRhIHNldCB3aGljaCB3YXMgcmVwcmVzZW50YXRpdmUgb2YgdGhlIHRvdGFsIG51bWJlciBvZiBhaXIgdHJhdmVsIHBhc3NlbmdlcnMgaW4gdGhlIFUuUy4gdGhyb3VnaCBtb250aGx5IGF2ZXJhZ2VzLiBUaGlzIGRhdGEgd2FzIGNvbGxlY3RlZCBvdmVyIHRoZSBjb3Vyc2Ugb2YgdGhlIHllYXJzIGZyb20gMjAwMyB0byAyMDIzLiBXZSBjcmVhdGVkIGEgbW9udGhseSB0aW1lIHNlcmllcyB3aGljaCBzaG93ZWQgdGhlIHRyZW5kcyBhbmQgc2Vhc29uYWxpdHkgb2YgdGhlIGF2ZXJhZ2UgbnVtYmVyIG9mIGFpciB0cmF2ZWwgcGFzc2VuZ2VycyBieSBtb250aCBvdmVyIHRoZSBzcGFuIG9mIHRoaXMgMjAgeWVhciBwZXJpb2QuIA0KDQpXZSBzcGxpdCB0aGUgdGltZSBzZXJpZXMgZGF0YSB1cCBpbnRvIGEgdHJhaW5pbmcgYW5kIGEgdGVzdGluZyBkYXRhIHNldC4gQWZ0ZXIgbG9va2luZyBhdCBzZXZlcmFsIHBvdGVuZXRpYWwgc21vb3RoaW5nIG1vZGVscywgdGhlIG9uZSB3aGljaCB3YXMgZm91bmQgdG8gcHJvdmlkZSB0aGUgYmVzdCBwZXJmb3JtYW5jZSB3YXMgdGhlIEhvbHQtV2ludGVyJ3MgQWRkaXRpdmUgbW9kZWwuIFRoaXMgbW9kZWwgd2FzIHRoZSBiZXN0IGNob2ljZSBiZWNhdXNlIGl0IGRpZCB0aGUgYmVzdCBqb2Igb3V0IG9mIGRlY3JlYXNpbmcgdGhlIGVycm9ycywgYW5kIHByb3ZpZGVkIHRoZSBiZXN0IGFjY3VyYWN5IG92ZXJhbGwuIFNvLCB0aGUgSG9sdC1XaW50ZXIncyBBZGRpdGl2ZSBtb2RlbCB3YXMgdGhlIGJlc3QgY2hvaWNlIG91dCBvZiB0aGUgc2V2ZXJhbCBjYW5kaWRhdGUsIHNtb290aGluZyBtb2RlbHMgd2UgbG9va2VkIGF0LiANCg0KDQojIyBSZWNvbW1lbmRhdGlvbnMNCg0KU29tZSByZWNvbW1lbmRhdGlvbnMgSSB3b3VsZCBtYWtlIGZvciBmdXR1cmUgcHJvamVjdHMgaW5jbHVkZToNCg0KKiBDb25zaWRlciBleHBhbmRpbmcgdGhlIHRpbWUgc2VyaWVzIGRhdGEgdG8gaW5jbHVkZSB0aGUgYXZlcmFnZSBhaXIgdHJhdmVsIHBhc3NlbmdlcnMgZm9yIGFsbCBjb3VudHJpZXMsIG5vdCBqdXN0IHRoZSBVLlMuIGluIG9yZGVyIHRvIHNlZSBpZiB0aGlzIHN0aWxsIHJlc3VsdHMgaW4gdGhlIEhvbHQtV2ludGVyJ3MgQWRkaXRpdmUgbW9kZWwgYmVpbmcgdGhlIGlkZWFsIG1vZGVsIGNob2ljZSwgb3IgaWYgYW5vdGhlciBtb2RlbCBzZWVtcyB0byBwcm92aWRlIGJldHRlciBwZXJmb3JtYW5jZSBpbiB0aGlzIHNjZW5hcmlvLg0KDQoqIEZ1cnRoZXIgbG9vayBpbnRvIHRoZSBzZWFzb25hbGl0eSBpbiB0aGlzIHRpbWUgc2VyaWVzIGRhdGEgc2V0LCBzaW5jZSB0aGVyZSBkZWZpbml0ZWx5IGFwcGVhcmVkIHRvIGJlIHNlYXNvbmFsaXR5IG9jY3VycmluZyB3aXRoIG1vcmUgcGFzc2VuZ2VycyB0cmF2ZWxsaW5nIGluIGNlcnRhaW4gdGltZXMgb2YgdGhlIHllYXIsIGxpa2Ugc3VtbWVyLCB0aGFuIGR1cmluZyBvdGhlciB0aW1lcyBvZiB0aGUgeWVhciB3aGljaCBzYXcgZmV3ZXIgcGFzc2VuZ2Vycy4gDQoNCg0KDQoNCiMgUmVmZXJlbmNlcw0KDQpUaGUgZGF0YSBzZXQgSSB1c2VkIGZvciBteSB0aW1lIHNlcmllcyB3YXMgZm91bmQgb24ga2FnZ2xlLmNvbS4gSW5jbHVkZWQgYmVsb3cgaXMgdGhlIGNpdGF0aW9uIG9mIHRoZSB3ZWIgcGFnZSB3aGVyZSBJIGZvdW5kIHRoaXMgZGF0YSBzZXQuIA0KDQpZWVhpYW4uICgyMDI0LCBKYW51YXJ5IDE1KS4gVS5TLiBhaXJsaW5lIHRyYWZmaWMgZGF0YSAoMjAwMy0yMDIzKS4gS2FnZ2xlLiBodHRwczovL3d3dy5rYWdnbGUuY29tL2RhdGFzZXRzL3l5eGlhbi91LXMtYWlybGluZS10cmFmZmljLWRhdGE/c2VsZWN0PWFpciUyQnRyYWZmaWMuY3N2IA0K