1 Introduction

This assingment is going to look at several different options of expontential smoothing models to determine the best and final model for a time series with trend and seasonality.

2 Materials

2.1 Data Set

This assignment uses a time series data set from the United States Census Bureau. The time series is Annual Rate of New Single-Family Houses Sold. This data set only covers homes sold in the United States over the span of 744 months from January 1963 to December of 2024. However, in this assignment we will only look at the data from January 2010 and December 2024.

2.2 Data Cleaning

The original data set is going to be subsetted into a time series spanning from January 2010 to December 2024. However, since we are currently in December of 2024 the data set has not been full updated, so there are some observations that need to be removed since they are missing, after the missing variables are removed the value variable can be converted to a numeric variable.

url="https://ChloeWinters79.github.io/STA321/Data/USHomeSales.csv"
home.sales = read.csv(url, header = TRUE)
n.row = dim(home.sales)[1]
data.home.sales.0 = home.sales[(n.row-179):n.row, ]
data.home.sales = subset(data.home.sales.0, Value != "N/A")
data.home.sales$Value <- as.numeric(as.character(data.home.sales$Value))

2.3 Trend and Seasonality

This assignment does require that the time series we are working with show both trend and seasonality. To confirm that both of these are present in the time series, some graphs were printed to asses the trend and seasonality of the time series.

homesales.ts = ts(data.home.sales[,2], frequency = 12, start = c(2010, 1))
cls.homesales = decompose(homesales.ts)
par(mar=c(2,2,2,2))
plot(cls.homesales, xlab="")
Classical decomposition of additive time series

Classical decomposition of additive time series

The above graph shows the decomposition of additive time series, it shows a mostly positive increasing trend, however there does appear to be a decrease after 2020. Considering the context that 2020 was the start of the COVID-19 pandemic shut down so seeing a dip in the trend is not shocking considering the context. Additionally, we can see a seasonal pattern present in the graph, which means the time series meets the trend and seasonal requirements for this assignment.

3 Methodolgy & Analysis

For this project, we want to determine the best exponential smoothing model to use for this data set. To determine the best smoothing model we are going to compare the accuracy of several different models, SES, Holt, Holt-Winters and some additive, exponential and damped variations of Holt and Holt-Winters.

test.homes = data.home.sales$Value[166:177]
train.homes = data.home.sales$Value[1:165]
home=ts(data.home.sales$Value[1:168], start=100, frequency = 12)
fit1 = ses(home, h=12)
fit2 = holt(home, initial="optimal", h=12)             ## optimal alpha and beta
fit3 = holt(home,damped=TRUE, h=12 )                   ## additive damping
fit4 = holt(home,exponential=TRUE, damped=TRUE, h =12) ## multiplicative damp
fit5 = hw(home,h=12, seasonal="additive")              ## default h = 10
fit6 = hw(home,h=12, seasonal="multiplicative")
fit7 = hw(home,h=12, seasonal="additive",damped=TRUE)
fit8 = hw(home,h=12, seasonal="multiplicative",damped=TRUE)
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 Exp. Damped",
                            "HW Add.","HW Exp.","HW Add. Damp", "HW Exp. Damp")
kable(accuracy.table, caption = "The accuracy measures of various exponential smoothing models 
      based on the training data")
The accuracy measures of various exponential smoothing models based on the training data
ME RMSE MAE MPE MAPE MASE ACF1
SES 2.2136 48.4549 35.2626 0.0553 6.2339 0.4093 0.0004
Holt Linear -0.1598 48.4565 35.3792 -0.4352 6.2890 0.4106 0.0035
Holt Add. Damped 2.2835 48.4843 35.4168 0.0809 6.2728 0.4111 0.0011
Holt Exp. Damped 2.6742 48.4464 35.3365 0.2005 6.2397 0.4101 -0.0002
HW Add. -0.5234 48.3285 34.9578 -0.4813 6.1911 0.4057 0.0029
HW Exp. 1.1751 53.2488 37.2653 -0.2176 6.6320 0.4325 0.2248
HW Add. Damp 1.4851 48.3832 35.1746 -0.1231 6.2356 0.4082 0.0022
HW Exp. Damp 1.0625 48.5948 35.5074 -0.1541 6.2970 0.4121 0.0241

Looking at the results from the table above, it seems like the Holt-Winters additive model appears to be the most appropriate exponential smoothing model. The Holt-Winters beats out the other models in every situation except on where it gets beat out by Holt Exponential Dampened.

In addition to the accuracy table above, it is also beneficial to see a visual representation of the different exponential smoothing models options and compare them to the original serial plot.

par(mfrow=c(2,1), mar=c(3,4,3,1))
###### plot the original data
pred.id = 166:177
plot(1:165, train.homes, lwd=2,type="o", ylab="Home Sales", xlab="", 
     xlim=c(1,177), ylim=c(200, 1200), cex=0.3,
     main="Non-Seasonal Smoothing Models")
lines(pred.id, fit1$mean, col="red")
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="red", 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)
#points(fit0, col="black", pch=1)
legend("bottomright", lty=1, col=c("red","blue","purple", "navy"),pch=c(16,17,19,21),
   c("SES","Holt Linear","Holt Linear Damped", "Holt Multiplicative Damped"), 
   cex = 0.7, bty="n")
###########
plot(1:165, train.homes, lwd=2,type="o", ylab="Home Sales", xlab="", 
     xlim=c(1,177), ylim=c(200, 1200), cex=0.3,
     main="Holt-Winterd Trend and Seasonal Smoothing Models")
lines(pred.id, fit5$mean, col="red")
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="red", 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("red","blue","purple", "navy"),pch=c(16,17,19,21),
   c("HW Additive","HW Multiplicative","HW Additive Damped", "HW Multiplicative Damped"), 
   cex = 0.7, bty="n")
Case study: Comparing various exponential smoothing models.

Case study: Comparing various exponential smoothing models.

Looking at the graphs above the first depiction shows the predictive lines to almost go fully horizontal, or mainly horizontal with minimal slope. However, the second graph does show predictive lines with more of a shape and potential variation that is consistent with the information seen in the existing serial plot. The Holt-Winters Additive line is within the second graph, further cementing it as the most appropriate model.

This assignment is also using a training data set, which will be used to identify the best model, with the assistance of the testing data set. In order to use the model for real-forecast, the model needs to be refit using the entire data to update the final working models 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
}
pred.accuracy = rbind(SES =acc.fun(test.data=test.homes, mod.obj=fit1),
                      Holt.Add =acc.fun(test.data=test.homes, mod.obj=fit2),
                      Holt.Add.Damp =acc.fun(test.data=test.homes, mod.obj=fit3),
                      Holt.Exp =acc.fun(test.data=test.homes, mod.obj=fit4),
                      HW.Add =acc.fun(test.data=test.homes, mod.obj=fit5),
                      HW.Exp =acc.fun(test.data=test.homes, mod.obj=fit6),
                      HW.Add.Damp =acc.fun(test.data=test.homes, mod.obj=fit7),
                      HW.Exp.Damp =acc.fun(test.data=test.homes, mod.obj=fit8))
kable(pred.accuracy, caption="The accuracy measures of various exponential smoothing models 
      based on the testing data")
The accuracy measures of various exponential smoothing models based on the testing data
MSE MAPE
SES 2510.071 6.258430
Holt.Add 1554.106 4.657823
Holt.Add.Damp 2512.571 6.262516
Holt.Exp 2511.084 6.260095
HW.Add 1737.009 5.053927
HW.Exp 2306.645 6.038416
HW.Add.Damp 3082.966 7.147686
HW.Exp.Damp 3664.936 8.133387

Looking at the above accuracy table, we actually see that the Holt Additive is the best of the eight smoothing models, with Holt-Winters Additive being a close second. This does come as a surprise considering the Holt-Winters Additive model has been performing better so far. Since the Holt-Winters Additive model was more often the preferred model, over Holt Additive, and since Holt-Winters is a close second here, we are going to move forward using this model. However, it is still important to acknowledge that the above accuracy table does not identify this as the number one model choice.

4 Results & Conclusions

In the previous analysis, the model was trained using the training data set in order to identify the best model for both the testing and training data sets. When using real forecast the models need to be refitted at the end of the analysis using both the training and testing data sets, combined to create the whole data set. When using the training and testing sets together the model can be refit and smoothing parameters in the final model can be updated.

homes=ts(data.home.sales$Value[1:177], start=200, frequency = 12)
final.model = hw(homes,h=12, seasonal="additive") 
smoothing.parameter = final.model$model$par[1:3]
kable(smoothing.parameter, caption="Estimated values of the smoothing parameters in
      Holt-Winters linear trend with additive seasonality")
Estimated values of the smoothing parameters in Holt-Winters linear trend with additive seasonality
x
alpha 0.8013460
beta 0.0001006
gamma 0.0001000

The estimates values for the smoothing parameter are the three updated values, alpha, beta, and gamma that are shown above. The values apply specifically to the Holt-Winters method for linear trends with additive seasonality. Taking these values into account, the real-forecasting is complete since the model was refit with updating smoothing parameters for the selected final model.

5 General Discussions

While the final smoothing model was selected and our analysis was conducted there are some drawbacks of this assignment that need to be addressed. To start, the data set itself is not perfect. Due to the COVID-19 pandemic and shut down, there is a very large spike and then subsequent drop in the new home sales. This large jump and fall is not consistent with the earlier trend and begs the question if that is where the trend would have went if the pandemic had not happened. Additionally, with this trend being so recent, it does make one question if it is having a significant impact of the models and their smoothing, and if it is skewing the results of our analysis.

Additionally, is was not expected that the when looking at the accuracy measures based just on the testing data, that Holt-Winters Additive was not the best model, and it was actually second to Holt Additive. Once the trends start to get back to normal post COVID-19 and there is more post COVID data to look at it would be beneficial to go back and rerun the analysis and see if Holt-Winters Additive still makes the most sense as the final model, or if Holt Additive seems to be the better model. However, that is analysis that we will have to wait a few several years to do.

LS0tCnRpdGxlOiAiRXhwb25lbnRpYWwgU21vb3RoaW5nIG9mIGEgVGltZSBTZXJpZXMgd2l0aCBUcmVuZCBhbmQgU2Vhc29uYWxpdHkgZm9yIE5ldyBIb21lIFNhbGVzIgphdXRob3I6ICJDaGxvw6kgV2ludGVycyIKZGF0ZTogIjIwMjQtMTItMTEiCm91dHB1dDoKICBodG1sX2RvY3VtZW50OgogICAgdG9jOiB5ZXMKICAgIHRvY19mbG9hdDogeWVzCiAgICB0b2NfZGVwdGg6IDQKICAgIGZpZ193aWR0aDogNgogICAgZmlnX2hlaWdodDogNAogICAgZmlnX2NhcHRpb246IHllcwogICAgbnVtYmVyX3NlY3Rpb25zOiB5ZXMKICAgIHRvY19jb2xsYXBzZWQ6IHllcwogICAgY29kZV9mb2xkaW5nOiBoaWRlCiAgICBjb2RlX2Rvd25sb2FkOiB5ZXMKICAgIHNtb290aF9zY3JvbGw6IHllcwogICAgdGhlbWU6IGx1bWVuCiAgcGRmX2RvY3VtZW50OiAKICAgIHRvYzogeWVzCiAgICB0b2NfZGVwdGg6IDQKICAgIGZpZ19jYXB0aW9uOiB5ZXMKICAgIG51bWJlcl9zZWN0aW9uczogeWVzCiAgd29yZF9kb2N1bWVudDoKICAgIHRvYzogeWVzCiAgICB0b2NfZGVwdGg6ICc0JwotLS0KCmBgYHs9aHRtbH0KCjxzdHlsZSB0eXBlPSJ0ZXh0L2NzcyI+CgovKiBDYXNjYWRpbmcgU3R5bGUgU2hlZXRzIChDU1MpIGlzIGEgc3R5bGVzaGVldCBsYW5ndWFnZSB1c2VkIHRvIGRlc2NyaWJlIHRoZSBwcmVzZW50YXRpb24gb2YgYSBkb2N1bWVudCB3cml0dGVuIGluIEhUTUwgb3IgWE1MLiBpdCBpcyBhIHNpbXBsZSBtZWNoYW5pc20gZm9yIGFkZGluZyBzdHlsZSAoZS5nLiwgZm9udHMsIGNvbG9ycywgc3BhY2luZykgdG8gV2ViIGRvY3VtZW50cy4gKi8KCmgxLnRpdGxlIHsgIC8qIFRpdGxlIC0gZm9udCBzcGVjaWZpY2F0aW9ucyBvZiB0aGUgcmVwb3J0IHRpdGxlICovCiAgZm9udC1zaXplOiAyNHB4OwogIGNvbG9yOiBEYXJrUmVkOwogIHRleHQtYWxpZ246IGNlbnRlcjsKICBmb250LWZhbWlseTogIkdpbGwgU2FucyIsIHNhbnMtc2VyaWY7Cn0KaDQuYXV0aG9yIHsgLyogSGVhZGVyIDQgLSBmb250IHNwZWNpZmljYXRpb25zIGZvciBhdXRob3JzICAqLwogIGZvbnQtc2l6ZTogMjBweDsKICBmb250LWZhbWlseTogc3lzdGVtLXVpOwogIGNvbG9yOiBEYXJrUmVkOwogIHRleHQtYWxpZ246IGNlbnRlcjsKfQpoNC5kYXRlIHsgLyogSGVhZGVyIDQgLSBmb250IHNwZWNpZmljYXRpb25zIGZvciB0aGUgZGF0ZSAgKi8KICBmb250LXNpemU6IDE4cHg7CiAgZm9udC1mYW1pbHk6IHN5c3RlbS11aTsKICBjb2xvcjogRGFya0JsdWU7CiAgdGV4dC1hbGlnbjogY2VudGVyOwp9CmgxIHsgLyogSGVhZGVyIDEgLSBmb250IHNwZWNpZmljYXRpb25zIGZvciBsZXZlbCAxIHNlY3Rpb24gdGl0bGUgICovCiAgICBmb250LXNpemU6IDIycHg7CiAgICBmb250LWZhbWlseTogc3lzdGVtLXVpOwogICAgY29sb3I6IG5hdnk7CiAgICB0ZXh0LWFsaWduOiBsZWZ0Owp9CmgyIHsgLyogSGVhZGVyIDIgLSBmb250IHNwZWNpZmljYXRpb25zIGZvciBsZXZlbCAyIHNlY3Rpb24gdGl0bGUgKi8KICAgIGZvbnQtc2l6ZTogMjBweDsKICAgIGZvbnQtZmFtaWx5OiAiVGltZXMgTmV3IFJvbWFuIiwgVGltZXMsIHNlcmlmOwogICAgY29sb3I6IG5hdnk7CiAgICB0ZXh0LWFsaWduOiBsZWZ0Owp9CgpoMyB7IC8qIEhlYWRlciAzIC0gZm9udCBzcGVjaWZpY2F0aW9ucyBvZiBsZXZlbCAzIHNlY3Rpb24gdGl0bGUgICovCiAgICBmb250LXNpemU6IDE4cHg7CiAgICBmb250LWZhbWlseTogIlRpbWVzIE5ldyBSb21hbiIsIFRpbWVzLCBzZXJpZjsKICAgIGNvbG9yOiBuYXZ5OwogICAgdGV4dC1hbGlnbjogbGVmdDsKfQoKaDQgeyAvKiBIZWFkZXIgNCAtIGZvbnQgc3BlY2lmaWNhdGlvbnMgb2YgbGV2ZWwgNCBzZWN0aW9uIHRpdGxlICAqLwogICAgZm9udC1zaXplOiAxOHB4OwogICAgZm9udC1mYW1pbHk6ICJUaW1lcyBOZXcgUm9tYW4iLCBUaW1lcywgc2VyaWY7CiAgICBjb2xvcjogZGFya3JlZDsKICAgIHRleHQtYWxpZ246IGxlZnQ7Cn0KCmJvZHkgeyBiYWNrZ3JvdW5kLWNvbG9yOndoaXRlOyB9CgouaGlnaGxpZ2h0bWUgeyBiYWNrZ3JvdW5kLWNvbG9yOnllbGxvdzsgfQoKcCB7IGJhY2tncm91bmQtY29sb3I6d2hpdGU7IH0KCjwvc3R5bGU+CmBgYApgYGB7ciBzZXR1cCwgaW5jbHVkZT1GQUxTRX0KCiMKIyBzcGVjaWZpY2F0aW9ucyBvZiBvdXRwdXRzIG9mIGNvZGUgaW4gY29kZSBjaHVua3MKa25pdHI6Om9wdHNfY2h1bmskc2V0KGVjaG8gPSBUUlVFLCAgICAgIAogICAgICAgICAgICAgICAgICAgICAgd2FybmluZyA9IEZBTFNFLCAgIAogICAgICAgICAgICAgICAgICAgICAgbWVzc2FnZSA9IEZBTFNFLCAgCiAgICAgICAgICAgICAgICAgICAgICByZXN1bHRzICA9IFRSVUUgICAgIAogICAgICAgICAgICAgICAgICAgICAgKSAgIAoKbGlicmFyeShrbml0cikKbGlicmFyeShwYW5kZXIpCmxpYnJhcnkobWxiZW5jaCkKbGlicmFyeShNQVNTKQpsaWJyYXJ5KGZvcmVjYXN0KQpsaWJyYXJ5KElTd1IpCmBgYAoKCiMgSW50cm9kdWN0aW9uCgpUaGlzIGFzc2luZ21lbnQgaXMgZ29pbmcgdG8gbG9vayBhdCBzZXZlcmFsIGRpZmZlcmVudCBvcHRpb25zIG9mIGV4cG9udGVudGlhbCBzbW9vdGhpbmcgbW9kZWxzIHRvIGRldGVybWluZSB0aGUgYmVzdCBhbmQgZmluYWwgbW9kZWwgZm9yIGEgdGltZSBzZXJpZXMgd2l0aCB0cmVuZCBhbmQgc2Vhc29uYWxpdHkuIAoKIyBNYXRlcmlhbHMKCiMjIERhdGEgU2V0CgpUaGlzIGFzc2lnbm1lbnQgdXNlcyBhIHRpbWUgc2VyaWVzIGRhdGEgc2V0IGZyb20gdGhlIFVuaXRlZCBTdGF0ZXMgQ2Vuc3VzIEJ1cmVhdS4gVGhlIHRpbWUgc2VyaWVzIGlzIEFubnVhbCBSYXRlIG9mIE5ldyBTaW5nbGUtRmFtaWx5IEhvdXNlcyBTb2xkLiBUaGlzIGRhdGEgc2V0IG9ubHkgY292ZXJzIGhvbWVzIHNvbGQgaW4gdGhlIFVuaXRlZCBTdGF0ZXMgb3ZlciB0aGUgc3BhbiBvZiA3NDQgbW9udGhzIGZyb20gSmFudWFyeSAxOTYzIHRvIERlY2VtYmVyIG9mIDIwMjQuIEhvd2V2ZXIsIGluIHRoaXMgYXNzaWdubWVudCB3ZSB3aWxsIG9ubHkgbG9vayBhdCB0aGUgZGF0YSBmcm9tIEphbnVhcnkgMjAxMCBhbmQgRGVjZW1iZXIgMjAyNC4KCgojIyBEYXRhIENsZWFuaW5nCgpUaGUgb3JpZ2luYWwgZGF0YSBzZXQgaXMgZ29pbmcgdG8gYmUgc3Vic2V0dGVkIGludG8gYSB0aW1lIHNlcmllcyBzcGFubmluZyBmcm9tIEphbnVhcnkgMjAxMCB0byBEZWNlbWJlciAyMDI0LiBIb3dldmVyLCBzaW5jZSB3ZSBhcmUgY3VycmVudGx5IGluIERlY2VtYmVyIG9mIDIwMjQgdGhlIGRhdGEgc2V0IGhhcyBub3QgYmVlbiBmdWxsIHVwZGF0ZWQsIHNvIHRoZXJlIGFyZSBzb21lIG9ic2VydmF0aW9ucyB0aGF0IG5lZWQgdG8gYmUgcmVtb3ZlZCBzaW5jZSB0aGV5IGFyZSBtaXNzaW5nLCBhZnRlciB0aGUgbWlzc2luZyB2YXJpYWJsZXMgYXJlIHJlbW92ZWQgdGhlIHZhbHVlIHZhcmlhYmxlIGNhbiBiZSBjb252ZXJ0ZWQgdG8gYSBudW1lcmljIHZhcmlhYmxlLiAKCmBgYHtyfQp1cmw9Imh0dHBzOi8vQ2hsb2VXaW50ZXJzNzkuZ2l0aHViLmlvL1NUQTMyMS9EYXRhL1VTSG9tZVNhbGVzLmNzdiIKaG9tZS5zYWxlcyA9IHJlYWQuY3N2KHVybCwgaGVhZGVyID0gVFJVRSkKbi5yb3cgPSBkaW0oaG9tZS5zYWxlcylbMV0KZGF0YS5ob21lLnNhbGVzLjAgPSBob21lLnNhbGVzWyhuLnJvdy0xNzkpOm4ucm93LCBdCmRhdGEuaG9tZS5zYWxlcyA9IHN1YnNldChkYXRhLmhvbWUuc2FsZXMuMCwgVmFsdWUgIT0gIk4vQSIpCmRhdGEuaG9tZS5zYWxlcyRWYWx1ZSA8LSBhcy5udW1lcmljKGFzLmNoYXJhY3RlcihkYXRhLmhvbWUuc2FsZXMkVmFsdWUpKQpgYGAKCiMjIFRyZW5kIGFuZCBTZWFzb25hbGl0eQoKVGhpcyBhc3NpZ25tZW50IGRvZXMgcmVxdWlyZSB0aGF0IHRoZSB0aW1lIHNlcmllcyB3ZSBhcmUgd29ya2luZyB3aXRoIHNob3cgYm90aCB0cmVuZCBhbmQgc2Vhc29uYWxpdHkuIFRvIGNvbmZpcm0gdGhhdCBib3RoIG9mIHRoZXNlIGFyZSBwcmVzZW50IGluIHRoZSB0aW1lIHNlcmllcywgc29tZSBncmFwaHMgd2VyZSBwcmludGVkIHRvIGFzc2VzIHRoZSB0cmVuZCBhbmQgc2Vhc29uYWxpdHkgb2YgdGhlIHRpbWUgc2VyaWVzLiAKCmBgYHtyIGZpZy5hbGlnbj0nY2VudGVyJywgZmlnLmNhcD0gIkNsYXNzaWNhbCBkZWNvbXBvc2l0aW9uIG9mIGFkZGl0aXZlIHRpbWUgc2VyaWVzIiwgZmlnLndpZHRoPTYsIGZpZy5oZWlnaHQ9NH0KaG9tZXNhbGVzLnRzID0gdHMoZGF0YS5ob21lLnNhbGVzWywyXSwgZnJlcXVlbmN5ID0gMTIsIHN0YXJ0ID0gYygyMDEwLCAxKSkKY2xzLmhvbWVzYWxlcyA9IGRlY29tcG9zZShob21lc2FsZXMudHMpCnBhcihtYXI9YygyLDIsMiwyKSkKcGxvdChjbHMuaG9tZXNhbGVzLCB4bGFiPSIiKQpgYGAKClRoZSBhYm92ZSBncmFwaCBzaG93cyB0aGUgZGVjb21wb3NpdGlvbiBvZiBhZGRpdGl2ZSB0aW1lIHNlcmllcywgaXQgc2hvd3MgYSBtb3N0bHkgcG9zaXRpdmUgaW5jcmVhc2luZyB0cmVuZCwgaG93ZXZlciB0aGVyZSBkb2VzIGFwcGVhciB0byBiZSBhIGRlY3JlYXNlIGFmdGVyIDIwMjAuIENvbnNpZGVyaW5nIHRoZSBjb250ZXh0IHRoYXQgMjAyMCB3YXMgdGhlIHN0YXJ0IG9mIHRoZSBDT1ZJRC0xOSBwYW5kZW1pYyBzaHV0IGRvd24gc28gc2VlaW5nIGEgZGlwIGluIHRoZSB0cmVuZCBpcyBub3Qgc2hvY2tpbmcgY29uc2lkZXJpbmcgdGhlIGNvbnRleHQuIEFkZGl0aW9uYWxseSwgd2UgY2FuIHNlZSBhIHNlYXNvbmFsIHBhdHRlcm4gcHJlc2VudCBpbiB0aGUgZ3JhcGgsIHdoaWNoIG1lYW5zIHRoZSB0aW1lIHNlcmllcyBtZWV0cyB0aGUgdHJlbmQgYW5kIHNlYXNvbmFsIHJlcXVpcmVtZW50cyBmb3IgdGhpcyBhc3NpZ25tZW50LiAKCiMgTWV0aG9kb2xneSAmIEFuYWx5c2lzIAoKRm9yIHRoaXMgcHJvamVjdCwgd2Ugd2FudCB0byBkZXRlcm1pbmUgdGhlIGJlc3QgZXhwb25lbnRpYWwgc21vb3RoaW5nIG1vZGVsIHRvIHVzZSBmb3IgdGhpcyBkYXRhIHNldC4gVG8gZGV0ZXJtaW5lIHRoZSBiZXN0IHNtb290aGluZyBtb2RlbCB3ZSBhcmUgZ29pbmcgdG8gY29tcGFyZSB0aGUgYWNjdXJhY3kgb2Ygc2V2ZXJhbCBkaWZmZXJlbnQgbW9kZWxzLCBTRVMsIEhvbHQsIEhvbHQtV2ludGVycyBhbmQgc29tZSBhZGRpdGl2ZSwgZXhwb25lbnRpYWwgYW5kIGRhbXBlZCB2YXJpYXRpb25zIG9mIEhvbHQgYW5kIEhvbHQtV2ludGVycy4KCmBgYHtyIGZpZy5hbGlnbj0nY2VudGVyJyxmaWcud2lkdGg9NiwgZmlnLmhlaWdodD00LjUsIGZpZy5jYXA9IkNhc2Ugc3R1ZHk6IENvbXBhcmluZyB2YXJpb3VzIGV4cG9lbnRpYWwgc21vb3RoaW5nIG1vZGVscy4ifQp0ZXN0LmhvbWVzID0gZGF0YS5ob21lLnNhbGVzJFZhbHVlWzE2NjoxNzddCnRyYWluLmhvbWVzID0gZGF0YS5ob21lLnNhbGVzJFZhbHVlWzE6MTY1XQpob21lPXRzKGRhdGEuaG9tZS5zYWxlcyRWYWx1ZVsxOjE2OF0sIHN0YXJ0PTEwMCwgZnJlcXVlbmN5ID0gMTIpCmZpdDEgPSBzZXMoaG9tZSwgaD0xMikKZml0MiA9IGhvbHQoaG9tZSwgaW5pdGlhbD0ib3B0aW1hbCIsIGg9MTIpICAgICAgICAgICAgICMjIG9wdGltYWwgYWxwaGEgYW5kIGJldGEKZml0MyA9IGhvbHQoaG9tZSxkYW1wZWQ9VFJVRSwgaD0xMiApICAgICAgICAgICAgICAgICAgICMjIGFkZGl0aXZlIGRhbXBpbmcKZml0NCA9IGhvbHQoaG9tZSxleHBvbmVudGlhbD1UUlVFLCBkYW1wZWQ9VFJVRSwgaCA9MTIpICMjIG11bHRpcGxpY2F0aXZlIGRhbXAKZml0NSA9IGh3KGhvbWUsaD0xMiwgc2Vhc29uYWw9ImFkZGl0aXZlIikgICAgICAgICAgICAgICMjIGRlZmF1bHQgaCA9IDEwCmZpdDYgPSBodyhob21lLGg9MTIsIHNlYXNvbmFsPSJtdWx0aXBsaWNhdGl2ZSIpCmZpdDcgPSBodyhob21lLGg9MTIsIHNlYXNvbmFsPSJhZGRpdGl2ZSIsZGFtcGVkPVRSVUUpCmZpdDggPSBodyhob21lLGg9MTIsIHNlYXNvbmFsPSJtdWx0aXBsaWNhdGl2ZSIsZGFtcGVkPVRSVUUpCmBgYAoKYGBge3J9CmFjY3VyYWN5LnRhYmxlID0gcm91bmQocmJpbmQoYWNjdXJhY3koZml0MSksIGFjY3VyYWN5KGZpdDIpLCBhY2N1cmFjeShmaXQzKSwgYWNjdXJhY3koZml0NCksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYWNjdXJhY3koZml0NSksIGFjY3VyYWN5KGZpdDYpLCBhY2N1cmFjeShmaXQ3KSwgYWNjdXJhY3koZml0OCkpLDQpCnJvdy5uYW1lcyhhY2N1cmFjeS50YWJsZSk9YygiU0VTIiwiSG9sdCBMaW5lYXIiLCJIb2x0IEFkZC4gRGFtcGVkIiwgIkhvbHQgRXhwLiBEYW1wZWQiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIkhXIEFkZC4iLCJIVyBFeHAuIiwiSFcgQWRkLiBEYW1wIiwgIkhXIEV4cC4gRGFtcCIpCmthYmxlKGFjY3VyYWN5LnRhYmxlLCBjYXB0aW9uID0gIlRoZSBhY2N1cmFjeSBtZWFzdXJlcyBvZiB2YXJpb3VzIGV4cG9uZW50aWFsIHNtb290aGluZyBtb2RlbHMgCiAgICAgIGJhc2VkIG9uIHRoZSB0cmFpbmluZyBkYXRhIikKYGBgCgpMb29raW5nIGF0IHRoZSByZXN1bHRzIGZyb20gdGhlIHRhYmxlIGFib3ZlLCBpdCBzZWVtcyBsaWtlIHRoZSBIb2x0LVdpbnRlcnMgYWRkaXRpdmUgbW9kZWwgYXBwZWFycyB0byBiZSB0aGUgbW9zdCBhcHByb3ByaWF0ZSBleHBvbmVudGlhbCBzbW9vdGhpbmcgbW9kZWwuIFRoZSBIb2x0LVdpbnRlcnMgYmVhdHMgb3V0IHRoZSBvdGhlciBtb2RlbHMgaW4gZXZlcnkgc2l0dWF0aW9uIGV4Y2VwdCBvbiB3aGVyZSBpdCBnZXRzIGJlYXQgb3V0IGJ5IEhvbHQgRXhwb25lbnRpYWwgRGFtcGVuZWQuIAoKSW4gYWRkaXRpb24gdG8gdGhlIGFjY3VyYWN5IHRhYmxlIGFib3ZlLCBpdCBpcyBhbHNvIGJlbmVmaWNpYWwgdG8gc2VlIGEgdmlzdWFsIHJlcHJlc2VudGF0aW9uIG9mIHRoZSBkaWZmZXJlbnQgZXhwb25lbnRpYWwgc21vb3RoaW5nIG1vZGVscyBvcHRpb25zIGFuZCBjb21wYXJlIHRoZW0gdG8gdGhlIG9yaWdpbmFsIHNlcmlhbCBwbG90LiAKCmBgYHtyIGZpZy5hbGlnbj0nY2VudGVyJyxmaWcud2lkdGg9NiwgZmlnLmhlaWdodD02LjUsIGZpZy5jYXA9IkNhc2Ugc3R1ZHk6IENvbXBhcmluZyB2YXJpb3VzIGV4cG9uZW50aWFsIHNtb290aGluZyBtb2RlbHMuIn0KcGFyKG1mcm93PWMoMiwxKSwgbWFyPWMoMyw0LDMsMSkpCiMjIyMjIyBwbG90IHRoZSBvcmlnaW5hbCBkYXRhCnByZWQuaWQgPSAxNjY6MTc3CnBsb3QoMToxNjUsIHRyYWluLmhvbWVzLCBsd2Q9Mix0eXBlPSJvIiwgeWxhYj0iSG9tZSBTYWxlcyIsIHhsYWI9IiIsIAogICAgIHhsaW09YygxLDE3NyksIHlsaW09YygyMDAsIDEyMDApLCBjZXg9MC4zLAogICAgIG1haW49Ik5vbi1TZWFzb25hbCBTbW9vdGhpbmcgTW9kZWxzIikKbGluZXMocHJlZC5pZCwgZml0MSRtZWFuLCBjb2w9InJlZCIpCmxpbmVzKHByZWQuaWQsIGZpdDIkbWVhbiwgY29sPSJibHVlIikKbGluZXMocHJlZC5pZCwgZml0MyRtZWFuLCBjb2w9InB1cnBsZSIpCmxpbmVzKHByZWQuaWQsIGZpdDQkbWVhbiwgY29sPSJuYXZ5IikKIyMKcG9pbnRzKHByZWQuaWQsIGZpdDEkbWVhbiwgcGNoPTE2LCBjb2w9InJlZCIsIGNleCA9IDAuNSkKcG9pbnRzKHByZWQuaWQsIGZpdDIkbWVhbiwgcGNoPTE3LCBjb2w9ImJsdWUiLCBjZXggPSAwLjUpCnBvaW50cyhwcmVkLmlkLCBmaXQzJG1lYW4sIHBjaD0xOSwgY29sPSJwdXJwbGUiLCBjZXggPSAwLjUpCnBvaW50cyhwcmVkLmlkLCBmaXQ0JG1lYW4sIHBjaD0yMSwgY29sPSJuYXZ5IiwgY2V4ID0gMC41KQojcG9pbnRzKGZpdDAsIGNvbD0iYmxhY2siLCBwY2g9MSkKbGVnZW5kKCJib3R0b21yaWdodCIsIGx0eT0xLCBjb2w9YygicmVkIiwiYmx1ZSIsInB1cnBsZSIsICJuYXZ5IikscGNoPWMoMTYsMTcsMTksMjEpLAogICBjKCJTRVMiLCJIb2x0IExpbmVhciIsIkhvbHQgTGluZWFyIERhbXBlZCIsICJIb2x0IE11bHRpcGxpY2F0aXZlIERhbXBlZCIpLCAKICAgY2V4ID0gMC43LCBidHk9Im4iKQojIyMjIyMjIyMjIwpwbG90KDE6MTY1LCB0cmFpbi5ob21lcywgbHdkPTIsdHlwZT0ibyIsIHlsYWI9IkhvbWUgU2FsZXMiLCB4bGFiPSIiLCAKICAgICB4bGltPWMoMSwxNzcpLCB5bGltPWMoMjAwLCAxMjAwKSwgY2V4PTAuMywKICAgICBtYWluPSJIb2x0LVdpbnRlcmQgVHJlbmQgYW5kIFNlYXNvbmFsIFNtb290aGluZyBNb2RlbHMiKQpsaW5lcyhwcmVkLmlkLCBmaXQ1JG1lYW4sIGNvbD0icmVkIikKbGluZXMocHJlZC5pZCwgZml0NiRtZWFuLCBjb2w9ImJsdWUiKQpsaW5lcyhwcmVkLmlkLCBmaXQ3JG1lYW4sIGNvbD0icHVycGxlIikKbGluZXMocHJlZC5pZCwgZml0OCRtZWFuLCBjb2w9Im5hdnkiKQojIwpwb2ludHMocHJlZC5pZCwgZml0NSRtZWFuLCBwY2g9MTYsIGNvbD0icmVkIiwgY2V4ID0gMC41KQpwb2ludHMocHJlZC5pZCwgZml0NiRtZWFuLCBwY2g9MTcsIGNvbD0iYmx1ZSIsIGNleCA9IDAuNSkKcG9pbnRzKHByZWQuaWQsIGZpdDckbWVhbiwgcGNoPTE5LCBjb2w9InB1cnBsZSIsIGNleCA9IDAuNSkKcG9pbnRzKHByZWQuaWQsIGZpdDgkbWVhbiwgcGNoPTIxLCBjb2w9Im5hdnkiLCBjZXggPSAwLjUpCiMjIwpsZWdlbmQoImJvdHRvbXJpZ2h0IiwgbHR5PTEsIGNvbD1jKCJyZWQiLCJibHVlIiwicHVycGxlIiwgIm5hdnkiKSxwY2g9YygxNiwxNywxOSwyMSksCiAgIGMoIkhXIEFkZGl0aXZlIiwiSFcgTXVsdGlwbGljYXRpdmUiLCJIVyBBZGRpdGl2ZSBEYW1wZWQiLCAiSFcgTXVsdGlwbGljYXRpdmUgRGFtcGVkIiksIAogICBjZXggPSAwLjcsIGJ0eT0ibiIpCmBgYAoKTG9va2luZyBhdCB0aGUgZ3JhcGhzIGFib3ZlIHRoZSBmaXJzdCBkZXBpY3Rpb24gc2hvd3MgdGhlIHByZWRpY3RpdmUgbGluZXMgdG8gYWxtb3N0IGdvIGZ1bGx5IGhvcml6b250YWwsIG9yIG1haW5seSBob3Jpem9udGFsIHdpdGggbWluaW1hbCBzbG9wZS4gSG93ZXZlciwgdGhlIHNlY29uZCBncmFwaCBkb2VzIHNob3cgcHJlZGljdGl2ZSBsaW5lcyB3aXRoIG1vcmUgb2YgYSBzaGFwZSBhbmQgcG90ZW50aWFsIHZhcmlhdGlvbiB0aGF0IGlzIGNvbnNpc3RlbnQgd2l0aCB0aGUgaW5mb3JtYXRpb24gc2VlbiBpbiB0aGUgZXhpc3Rpbmcgc2VyaWFsIHBsb3QuIFRoZSBIb2x0LVdpbnRlcnMgQWRkaXRpdmUgbGluZSBpcyB3aXRoaW4gdGhlIHNlY29uZCBncmFwaCwgZnVydGhlciBjZW1lbnRpbmcgaXQgYXMgdGhlIG1vc3QgYXBwcm9wcmlhdGUgbW9kZWwuIAoKVGhpcyBhc3NpZ25tZW50IGlzIGFsc28gdXNpbmcgYSB0cmFpbmluZyBkYXRhIHNldCwgd2hpY2ggd2lsbCBiZSB1c2VkIHRvIGlkZW50aWZ5IHRoZSBiZXN0IG1vZGVsLCB3aXRoIHRoZSBhc3Npc3RhbmNlIG9mIHRoZSB0ZXN0aW5nIGRhdGEgc2V0LiBJbiBvcmRlciB0byB1c2UgdGhlIG1vZGVsIGZvciByZWFsLWZvcmVjYXN0LCB0aGUgbW9kZWwgbmVlZHMgdG8gYmUgcmVmaXQgdXNpbmcgdGhlIGVudGlyZSBkYXRhIHRvIHVwZGF0ZSB0aGUgZmluYWwgd29ya2luZyBtb2RlbHMgc21vb3RoaW5nIHBhcmFtZXRlcnMuIAoKCmBgYHtyfQphY2MuZnVuID0gZnVuY3Rpb24odGVzdC5kYXRhLCBtb2Qub2JqKXsKICBQRT0xMDAqKHRlc3QuZGF0YS1tb2Qub2JqJG1lYW4pL21vZC5vYmokbWVhbgogIE1BUEUgPSBtZWFuKGFicyhQRSkpCiAgIyMjCiAgRT10ZXN0LmRhdGEtbW9kLm9iaiRtZWFuCiAgTVNFPW1lYW4oRV4yKQogICMjIwogIGFjY3VyYWN5Lm1ldHJpYz1jKE1TRT1NU0UsIE1BUEU9TUFQRSkKICBhY2N1cmFjeS5tZXRyaWMKfQpgYGAKCmBgYHtyfQpwcmVkLmFjY3VyYWN5ID0gcmJpbmQoU0VTID1hY2MuZnVuKHRlc3QuZGF0YT10ZXN0LmhvbWVzLCBtb2Qub2JqPWZpdDEpLAogICAgICAgICAgICAgICAgICAgICAgSG9sdC5BZGQgPWFjYy5mdW4odGVzdC5kYXRhPXRlc3QuaG9tZXMsIG1vZC5vYmo9Zml0MiksCiAgICAgICAgICAgICAgICAgICAgICBIb2x0LkFkZC5EYW1wID1hY2MuZnVuKHRlc3QuZGF0YT10ZXN0LmhvbWVzLCBtb2Qub2JqPWZpdDMpLAogICAgICAgICAgICAgICAgICAgICAgSG9sdC5FeHAgPWFjYy5mdW4odGVzdC5kYXRhPXRlc3QuaG9tZXMsIG1vZC5vYmo9Zml0NCksCiAgICAgICAgICAgICAgICAgICAgICBIVy5BZGQgPWFjYy5mdW4odGVzdC5kYXRhPXRlc3QuaG9tZXMsIG1vZC5vYmo9Zml0NSksCiAgICAgICAgICAgICAgICAgICAgICBIVy5FeHAgPWFjYy5mdW4odGVzdC5kYXRhPXRlc3QuaG9tZXMsIG1vZC5vYmo9Zml0NiksCiAgICAgICAgICAgICAgICAgICAgICBIVy5BZGQuRGFtcCA9YWNjLmZ1bih0ZXN0LmRhdGE9dGVzdC5ob21lcywgbW9kLm9iaj1maXQ3KSwKICAgICAgICAgICAgICAgICAgICAgIEhXLkV4cC5EYW1wID1hY2MuZnVuKHRlc3QuZGF0YT10ZXN0LmhvbWVzLCBtb2Qub2JqPWZpdDgpKQprYWJsZShwcmVkLmFjY3VyYWN5LCBjYXB0aW9uPSJUaGUgYWNjdXJhY3kgbWVhc3VyZXMgb2YgdmFyaW91cyBleHBvbmVudGlhbCBzbW9vdGhpbmcgbW9kZWxzIAogICAgICBiYXNlZCBvbiB0aGUgdGVzdGluZyBkYXRhIikKYGBgCgpMb29raW5nIGF0IHRoZSBhYm92ZSBhY2N1cmFjeSB0YWJsZSwgd2UgYWN0dWFsbHkgc2VlIHRoYXQgdGhlIEhvbHQgQWRkaXRpdmUgaXMgdGhlIGJlc3Qgb2YgdGhlIGVpZ2h0IHNtb290aGluZyBtb2RlbHMsIHdpdGggSG9sdC1XaW50ZXJzIEFkZGl0aXZlIGJlaW5nIGEgY2xvc2Ugc2Vjb25kLiBUaGlzIGRvZXMgY29tZSBhcyBhIHN1cnByaXNlIGNvbnNpZGVyaW5nIHRoZSBIb2x0LVdpbnRlcnMgQWRkaXRpdmUgbW9kZWwgaGFzIGJlZW4gcGVyZm9ybWluZyBiZXR0ZXIgc28gZmFyLiBTaW5jZSB0aGUgSG9sdC1XaW50ZXJzIEFkZGl0aXZlIG1vZGVsIHdhcyBtb3JlIG9mdGVuIHRoZSBwcmVmZXJyZWQgbW9kZWwsIG92ZXIgSG9sdCBBZGRpdGl2ZSwgYW5kIHNpbmNlIEhvbHQtV2ludGVycyBpcyBhIGNsb3NlIHNlY29uZCBoZXJlLCB3ZSBhcmUgZ29pbmcgdG8gbW92ZSBmb3J3YXJkIHVzaW5nIHRoaXMgbW9kZWwuIEhvd2V2ZXIsIGl0IGlzIHN0aWxsIGltcG9ydGFudCB0byBhY2tub3dsZWRnZSB0aGF0IHRoZSBhYm92ZSBhY2N1cmFjeSB0YWJsZSBkb2VzIG5vdCBpZGVudGlmeSB0aGlzIGFzIHRoZSBudW1iZXIgb25lIG1vZGVsIGNob2ljZS4gCgojIFJlc3VsdHMgJiBDb25jbHVzaW9ucyAKCkluIHRoZSBwcmV2aW91cyBhbmFseXNpcywgdGhlIG1vZGVsIHdhcyB0cmFpbmVkIHVzaW5nIHRoZSB0cmFpbmluZyBkYXRhIHNldCBpbiBvcmRlciB0byBpZGVudGlmeSB0aGUgYmVzdCBtb2RlbCBmb3IgYm90aCB0aGUgdGVzdGluZyBhbmQgdHJhaW5pbmcgZGF0YSBzZXRzLiBXaGVuIHVzaW5nIHJlYWwgZm9yZWNhc3QgdGhlIG1vZGVscyBuZWVkIHRvIGJlIHJlZml0dGVkIGF0IHRoZSBlbmQgb2YgdGhlIGFuYWx5c2lzIHVzaW5nIGJvdGggdGhlIHRyYWluaW5nIGFuZCB0ZXN0aW5nIGRhdGEgc2V0cywgY29tYmluZWQgdG8gY3JlYXRlIHRoZSB3aG9sZSBkYXRhIHNldC4gV2hlbiB1c2luZyB0aGUgdHJhaW5pbmcgYW5kIHRlc3Rpbmcgc2V0cyB0b2dldGhlciB0aGUgbW9kZWwgY2FuIGJlIHJlZml0IGFuZCBzbW9vdGhpbmcgcGFyYW1ldGVycyBpbiB0aGUgZmluYWwgbW9kZWwgY2FuIGJlIHVwZGF0ZWQuCgpgYGB7cn0KaG9tZXM9dHMoZGF0YS5ob21lLnNhbGVzJFZhbHVlWzE6MTc3XSwgc3RhcnQ9MjAwLCBmcmVxdWVuY3kgPSAxMikKZmluYWwubW9kZWwgPSBodyhob21lcyxoPTEyLCBzZWFzb25hbD0iYWRkaXRpdmUiKSAKc21vb3RoaW5nLnBhcmFtZXRlciA9IGZpbmFsLm1vZGVsJG1vZGVsJHBhclsxOjNdCmthYmxlKHNtb290aGluZy5wYXJhbWV0ZXIsIGNhcHRpb249IkVzdGltYXRlZCB2YWx1ZXMgb2YgdGhlIHNtb290aGluZyBwYXJhbWV0ZXJzIGluCiAgICAgIEhvbHQtV2ludGVycyBsaW5lYXIgdHJlbmQgd2l0aCBhZGRpdGl2ZSBzZWFzb25hbGl0eSIpCmBgYAoKVGhlIGVzdGltYXRlcyB2YWx1ZXMgZm9yIHRoZSBzbW9vdGhpbmcgcGFyYW1ldGVyIGFyZSB0aGUgdGhyZWUgdXBkYXRlZCB2YWx1ZXMsIGFscGhhLCBiZXRhLCBhbmQgZ2FtbWEgdGhhdCBhcmUgc2hvd24gYWJvdmUuIFRoZSB2YWx1ZXMgYXBwbHkgc3BlY2lmaWNhbGx5IHRvIHRoZSBIb2x0LVdpbnRlcnMgbWV0aG9kIGZvciBsaW5lYXIgdHJlbmRzIHdpdGggYWRkaXRpdmUgc2Vhc29uYWxpdHkuIFRha2luZyB0aGVzZSB2YWx1ZXMgaW50byBhY2NvdW50LCB0aGUgcmVhbC1mb3JlY2FzdGluZyBpcyBjb21wbGV0ZSBzaW5jZSB0aGUgbW9kZWwgd2FzIHJlZml0IHdpdGggdXBkYXRpbmcgc21vb3RoaW5nIHBhcmFtZXRlcnMgZm9yIHRoZSBzZWxlY3RlZCBmaW5hbCBtb2RlbC4gCgoKIyBHZW5lcmFsIERpc2N1c3Npb25zCgpXaGlsZSB0aGUgZmluYWwgc21vb3RoaW5nIG1vZGVsIHdhcyBzZWxlY3RlZCBhbmQgb3VyIGFuYWx5c2lzIHdhcyBjb25kdWN0ZWQgdGhlcmUgYXJlIHNvbWUgZHJhd2JhY2tzIG9mIHRoaXMgYXNzaWdubWVudCB0aGF0IG5lZWQgdG8gYmUgYWRkcmVzc2VkLiBUbyBzdGFydCwgdGhlIGRhdGEgc2V0IGl0c2VsZiBpcyBub3QgcGVyZmVjdC4gRHVlIHRvIHRoZSBDT1ZJRC0xOSBwYW5kZW1pYyBhbmQgc2h1dCBkb3duLCB0aGVyZSBpcyBhIHZlcnkgbGFyZ2Ugc3Bpa2UgYW5kIHRoZW4gc3Vic2VxdWVudCBkcm9wIGluIHRoZSBuZXcgaG9tZSBzYWxlcy4gVGhpcyBsYXJnZSBqdW1wIGFuZCBmYWxsIGlzIG5vdCBjb25zaXN0ZW50IHdpdGggdGhlIGVhcmxpZXIgdHJlbmQgYW5kIGJlZ3MgdGhlIHF1ZXN0aW9uIGlmIHRoYXQgaXMgd2hlcmUgdGhlIHRyZW5kIHdvdWxkIGhhdmUgd2VudCBpZiB0aGUgcGFuZGVtaWMgaGFkIG5vdCBoYXBwZW5lZC4gQWRkaXRpb25hbGx5LCB3aXRoIHRoaXMgdHJlbmQgYmVpbmcgc28gcmVjZW50LCBpdCBkb2VzIG1ha2Ugb25lIHF1ZXN0aW9uIGlmIGl0IGlzIGhhdmluZyBhIHNpZ25pZmljYW50IGltcGFjdCBvZiB0aGUgbW9kZWxzIGFuZCB0aGVpciBzbW9vdGhpbmcsIGFuZCBpZiBpdCBpcyBza2V3aW5nIHRoZSByZXN1bHRzIG9mIG91ciBhbmFseXNpcy4gCgpBZGRpdGlvbmFsbHksIGlzIHdhcyBub3QgZXhwZWN0ZWQgdGhhdCB0aGUgd2hlbiBsb29raW5nIGF0IHRoZSBhY2N1cmFjeSBtZWFzdXJlcyBiYXNlZCBqdXN0IG9uIHRoZSB0ZXN0aW5nIGRhdGEsIHRoYXQgSG9sdC1XaW50ZXJzIEFkZGl0aXZlIHdhcyBub3QgdGhlIGJlc3QgbW9kZWwsIGFuZCBpdCB3YXMgYWN0dWFsbHkgc2Vjb25kIHRvIEhvbHQgQWRkaXRpdmUuIE9uY2UgdGhlIHRyZW5kcyBzdGFydCB0byBnZXQgYmFjayB0byBub3JtYWwgcG9zdCBDT1ZJRC0xOSBhbmQgdGhlcmUgaXMgbW9yZSBwb3N0IENPVklEIGRhdGEgdG8gbG9vayBhdCBpdCB3b3VsZCBiZSBiZW5lZmljaWFsIHRvIGdvIGJhY2sgYW5kIHJlcnVuIHRoZSBhbmFseXNpcyBhbmQgc2VlIGlmIEhvbHQtV2ludGVycyBBZGRpdGl2ZSBzdGlsbCBtYWtlcyB0aGUgbW9zdCBzZW5zZSBhcyB0aGUgZmluYWwgbW9kZWwsIG9yIGlmIEhvbHQgQWRkaXRpdmUgc2VlbXMgdG8gYmUgdGhlIGJldHRlciBtb2RlbC4gSG93ZXZlciwgdGhhdCBpcyBhbmFseXNpcyB0aGF0IHdlIHdpbGwgaGF2ZSB0byB3YWl0IGEgZmV3IHNldmVyYWwgeWVhcnMgdG8gZG8uIAo=