Nigerian Deposit Money Banks Monthly Loan to Deposit Ratio (Jan. 2007 - April 2017) The data source is from the Central Bank of Nigeria Statistics Database

#check for seasonality
seasonplot(loan_to_deposit,main = "Season Plot: Nigerian Deposit Money Banks loan-to-Deposit Ratio ", year.labels = TRUE,col=1:20,ylab="Percentage(%)",year.labels.left=TRUE,pch=19)

Observing the graph above it does not seem there seems to have a strong seasonal observable pattern between the yearly season. Apart from 2008,2014 & 2015 all other years had the loan-to-deposit ratio drop from January to February.

#check for seasonality
plot(decompose ,main="Plot of Decomposition of Time Series - loan-to-deposit ratio")

monthplot(loan_to_deposit, ylab = "data", cex.axis = 0.8, main="Monthly plot of Data")

monthplot(decompose, choice = "seasonal", cex.axis = 0.8, main="Monthly plot of Seasonal ")

monthplot(decompose, choice = "trend", cex.axis = 0.8, main="Monthly plot of Trend")

monthplot(decompose, choice = "remainder", type = "h", cex.axis = 0.8, , main="Monthly plot of Remainder")

#check for seasonality
quarter <- (cycle(loan_to_deposit)-1 ) %/% 3
monthplot(loan_to_deposit, phase = quarter, main="Quarterly Plot: Loan-to-deposit Ratio")

The quarterly plot reveal a strong quarterly seasonality.

Determining if the Time Series is Stationary

Using the R tsdisplay method, I generated the ACF and PACF plots. The ACF plots show a gradual decrease which implies that the time series is not stationary

tsdisplay(loan_to_deposit)

Determining the Differencing Order to Make Time Series Stationary

The original data contains trends. To convert the time series to a stationary time series I made use of the R diffs method. To determine the order of difference to apply I made use of the R forecast package method ndiffs, ndiffs(loan_to_deposit) = 1
To determine the need for order of seasonality difference to apply I made use of nsdiffs, nsdiffs(loan_to_deposit) = 0
The result show that only first order differencing of the time series is required to make the series stationary

level_of_difference <- ndiffs(loan_to_deposit)
diff_data <- diff(loan_to_deposit, level_of_difference)
plot(diff_data, ylab="first order difference loans-to-deposit")

tsdisplay(diff_data, main="first order differencing of loans-to-deposit ratio time series")

The ACF above shows that there is only one autocorrelation that is outside the 95% limit.

Investigating Other time series dataset

The Nigerian Air total passengers travel time series dataset

The dataset is from the World bank website

plot.ts(nigeria,ylab="Number of Passengers per 1000", main = "Nigeria  Yearly Air Passengers 1970 - 2015 ")

Investigating Time Series Stationarity: Nigerian Air Travel Passengers

The yearly time series plot above does not contain seasonality. The plot show evidence of a trend, hence this series is not stationary
Inspecting the ACF and PACF graph and determining the order of differencing the time series also confirms this.
Required order for differencing , ndiffs(nigeria)= 1
Using the ADF test, the p value of 0.7408 also confirms that the plot is not stationary

tsdisplay(nigeria)

adf.test(nigeria)

    Augmented Dickey-Fuller Test

data:  nigeria
Dickey-Fuller = -1.5803, Lag order = 3, p-value = 0.7408
alternative hypothesis: stationary

First Order Differenced Time Series

tsdisplay(diff(nigeria), main="First Order Difference Time Series ")

adf.test(diff(nigeria))

    Augmented Dickey-Fuller Test

data:  diff(nigeria)
Dickey-Fuller = -2.4792, Lag order = 3, p-value = 0.3837
alternative hypothesis: stationary

The graph above shows the first order differenced time series. The adf.test small p value indicates that the time series is now stationary. However it would be observed that the outlier points can still be observed in the differenced time series. ###Using AUTO.ARIMA to determine the best model for the Air Travel Time series

nigeria_fit <- auto.arima(nigeria)
summary(nigeria_fit)
Series: nigeria 
ARIMA(0,1,0)                    

sigma^2 estimated as 260917:  log likelihood=-344.47
AIC=690.94   AICc=691.04   BIC=692.75

Training set error measures:
                  ME     RMSE      MAE      MPE     MAPE      MASE
Training set 66.3181 505.2179 267.8018 1.934564 20.54023 0.9782746
                  ACF1
Training set 0.1964641

Using ETS(SES) to determine the best model for the Air Travel Time series

nigeria_fit_ses <- ses(nigeria, initial = "simple")
summary(nigeria_fit_ses)

Forecast method: Simple exponential smoothing

Model Information:
 

Call:
 ses(x = nigeria, initial = "simple") 

  Smoothing parameters:
    alpha = 1 

  Initial states:
    l = 173 

  sigma:  505.2179
Error measures:
                   ME     RMSE      MAE     MPE     MAPE      MASE
Training set 66.31434 505.2179 267.7981 1.93239 20.53805 0.9782609
                  ACF1
Training set 0.1964642

Forecasts:
     Point Forecast    Lo 80    Hi 80      Lo 95    Hi 95
2016        3223.46 2575.997 3870.923 2233.25090 4213.669
2017        3223.46 2307.809 4139.110 1823.09295 4623.827
2018        3223.46 2102.021 4344.898 1508.36769 4938.552
2019        3223.46 1928.534 4518.385 1243.04202 5203.878
2020        3223.46 1775.689 4671.231 1009.28542 5437.634
2021        3223.46 1637.506 4809.413  797.95329 5648.966
2022        3223.46 1510.434 4936.485  603.61334 5843.306
2023        3223.46 1392.158 5054.761  422.72613 6024.193
2024        3223.46 1281.071 5165.848  252.83315 6194.086
2025        3223.46 1176.003 5270.917   92.14437 6354.775
plot(nigeria, main= "ARIMA (0,1,0) & SES (alpha=1) Model Plot",ylab="Number of Passengers per 1000")
lines(fitted(nigeria_fit), col="red")
lines(fitted(nigeria_fit_ses), col="blue")
legend("topleft",lty=1, col=c("black","blue","red"), 
       c("Data","ARIMA Model","SES Model"),cex=0.80)

In the plot above the SES model is not noticable because it returns the same value as ARIMA(0,1,0) model.

Comparing the ARIMA and SES Models Fit Values

#Comparing ARIMA and SES models fit values
arima_model<- window(fitted(nigeria_fit),1970,1990)
ses_model<- window(fitted(nigeria_fit_ses),1970,1990)
ts.union(arima_model,ses_model)
Time Series:
Start = 1970 
End = 1990 
Frequency = 1 
     arima_model ses_model
1970     172.827     173.0
1971     173.000     173.0
1972     227.100     227.1
1973     286.800     286.8
1974     314.100     314.1
1975     430.300     430.3
1976     590.400     590.4
1977     800.800     800.8
1978    1093.900    1093.9
1979    1441.000    1441.0
1980    1581.300    1581.3
1981    1938.500    1938.5
1982    2300.200    2300.2
1983    2138.400    2138.4
1984    2221.300    2221.3
1985    1945.900    1945.9
1986    2575.000    2575.0
1987    2134.000    2134.0
1988    1614.400    1614.4
1989     995.000     995.0
1990     848.900     848.9
#last 15 values
arima_model2<- window(fitted(nigeria_fit),2000,2015)
ses_model2<- window(fitted(nigeria_fit_ses),2000,2015)
ts.union(arima_model2,ses_model2)
Time Series:
Start = 2000 
End = 2015 
Frequency = 1 
     arima_model2 ses_model2
2000      419.700    419.700
2001      507.396    507.396
2002      519.453    519.453
2003      520.278    520.278
2004      520.263    520.263
2005      540.461    540.461
2006      747.648    747.648
2007     1307.541   1307.541
2008     1363.435   1363.435
2009     1460.900   1460.900
2010     1365.343   1365.343
2011     4197.375   4197.375
2012     4793.913   4793.913
2013     4716.148   4716.148
2014     4209.624   4209.624
2015     3857.424   3857.424

Investigating the Model Residuals and Outlier impact

nigeria_outliers <-tso(nigeria,types=c("AO","LS","TC","IO"))
plot(residuals(nigeria_fit), main="ARIMA(0,1,0) & SES (alpha = 1) residuals", col="blue", ylab="Residual: Number of Passengers per 1000")
lines(residuals(nigeria_fit_ses), col="red")
legend("topleft",lty=1, col=c("blue","red"), 
       c("ARIMA Residual","SES Residual"),cex=0.80)

#ploting the outliers
plot(nigeria_outliers)

Box Plot to Verify Outliers

boxplot(nigeria, main="Box Plot of Nigeria  Yearly Air Passengers 1970 - 2015  ")

Reviewing the outlier plot and model residual plot, it would be observed that the outliers had poor model representation compared to other data points in the time series. SES and ARIMA model for this time series returned the same value.

LS0tDQp0aXRsZTogIkludmVzdGlnYXRpbmcgVGltZSBTZXJpZXMgU3RhdGlvbmFyaXR5Ig0KYXV0aG9yOiAiQWRlYmF5byBBZGVyaWJpZ2JlIg0Kb3V0cHV0Og0KICBodG1sX25vdGVib29rOiBkZWZhdWx0DQogIGh0bWxfZG9jdW1lbnQ6IGRlZmF1bHQNCiAgZ2l0aHViX2RvY3VtZW50OiBkZWZhdWx0DQogIHBkZl9kb2N1bWVudDogZGVmYXVsdA0KICB3b3JkX2RvY3VtZW50OiBkZWZhdWx0DQogIHRvYzogeWVzDQotLS0NCg0KDQoNCg0KYGBge3IgIGluY2x1ZGU9RkFMU0V9DQpsaWJyYXJ5KCJmb3JlY2FzdCIpDQpsaWJyYXJ5KCJmcHAiKQ0KDQpgYGANCg0KDQpgYGB7ciwgaW5jbHVkZT1GQUxTRX0NCiNkYXRhIHNvdXJjZQ0KZG1iX2RhdGEgPC0gcmVhZC5jc3YoIkRNQl9kYXRhLmNzdiIpDQoNCiNjb252ZXJ0IGRhdGEgdG8gdGltZSBzZXJpZXMNCnRzX2RhdGEgPC0gdHMoZG1iX2RhdGFbLCgzOjUpXSxmcmVxdWVuY3k9MTIsc3RhcnQ9YygyMDA3LDEpKQ0KDQojbG9hbl90b19kZXBvc2l0DQpsb2FuX3RvX2RlcG9zaXQgPC0gdHNfZGF0YVssMV0NCg0KZGVjb21wb3NlIDwtIHN0bChsb2FuX3RvX2RlcG9zaXQsIHMud2luZG93PTEyKQ0KYGBgDQogIA0KICAgIA0KDQpOaWdlcmlhbiBEZXBvc2l0IE1vbmV5IEJhbmtzIE1vbnRobHkgTG9hbiB0byBEZXBvc2l0IFJhdGlvIChKYW4uIDIwMDcgLSBBcHJpbCAyMDE3KSANClRoZSBkYXRhIHNvdXJjZSBpcyBmcm9tIHRoZSBbQ2VudHJhbCBCYW5rIG9mIE5pZ2VyaWEgU3RhdGlzdGljcyAgRGF0YWJhc2VdKGh0dHA6Ly9zdGF0aXN0aWNzLmNibi5nb3YubmcvY2JuLW9ubGluZXN0YXRzL0RhdGFCcm93c2VyLmFzcHgpDQoNCmBgYHtyICBlY2hvPUZBTFNFfQ0KI3BhcihjZXguYXhpcz0xLjUsIGNleC5sYWI9MS41KQ0KdHMucGxvdChsb2FuX3RvX2RlcG9zaXQseGxhYj0iWWVhciIseWxhYj0iTG9hbnMtdG8tRGVwb3NpdCBSYXRpbyIsbWFpbj0iTW9udGhseSBMb2FuLXRvLURlcG9zaXQgUmF0aW8gIFxuZm9yIE5pZ2VyaWEgRGVwb3NpdCBNb25leSBCYW5rcyBKYW4uIDIwMDcgLSBBcHIuIDIwMTciKQ0KbGluZXMoZGVjb21wb3NlJHRpbWUuc2VyaWVzWywyXSxjb2w9InJlZCIseWxhYj0iVHJlbmQiKQ0KbGVnZW5kKCJib3R0b21yaWdodCIsYygiZGF0YSIsInRyZW5kIiksY29sPWMoImJsYWNrIiwicmVkIiksbHR5PWMoMSwxKSkNCmBgYA0KDQpgYGB7ciwgfQ0KI2NoZWNrIGZvciBzZWFzb25hbGl0eQ0Kc2Vhc29ucGxvdChsb2FuX3RvX2RlcG9zaXQsbWFpbiA9ICJTZWFzb24gUGxvdDogTmlnZXJpYW4gRGVwb3NpdCBNb25leSBCYW5rcyBsb2FuLXRvLURlcG9zaXQgUmF0aW8gIiwgeWVhci5sYWJlbHMgPSBUUlVFLGNvbD0xOjIwLHlsYWI9IlBlcmNlbnRhZ2UoJSkiLHllYXIubGFiZWxzLmxlZnQ9VFJVRSxwY2g9MTkpDQoNCmBgYA0KT2JzZXJ2aW5nIHRoZSBncmFwaCBhYm92ZSBpdCBkb2VzIG5vdCBzZWVtIHRoZXJlIHNlZW1zIHRvIGhhdmUgYSBzdHJvbmcgc2Vhc29uYWwgb2JzZXJ2YWJsZSBwYXR0ZXJuIGJldHdlZW4gdGhlIHllYXJseSBzZWFzb24uIEFwYXJ0IGZyb20gMjAwOCwyMDE0ICYgMjAxNSBhbGwgb3RoZXIgeWVhcnMgaGFkIHRoZSBsb2FuLXRvLWRlcG9zaXQgcmF0aW8gZHJvcCBmcm9tIEphbnVhcnkgdG8gRmVicnVhcnkuDQoNCmBgYHtyLCB9DQojY2hlY2sgZm9yIHNlYXNvbmFsaXR5DQpwbG90KGRlY29tcG9zZSAsbWFpbj0iUGxvdCBvZiBEZWNvbXBvc2l0aW9uIG9mIFRpbWUgU2VyaWVzIC0gbG9hbi10by1kZXBvc2l0IHJhdGlvIikNCg0KYGBgDQoNCmBgYHtyLCB9DQptb250aHBsb3QobG9hbl90b19kZXBvc2l0LCB5bGFiID0gImRhdGEiLCBjZXguYXhpcyA9IDAuOCwgbWFpbj0iTW9udGhseSBwbG90IG9mIERhdGEiKQ0KbW9udGhwbG90KGRlY29tcG9zZSwgY2hvaWNlID0gInNlYXNvbmFsIiwgY2V4LmF4aXMgPSAwLjgsIG1haW49Ik1vbnRobHkgcGxvdCBvZiBTZWFzb25hbCAiKQ0KbW9udGhwbG90KGRlY29tcG9zZSwgY2hvaWNlID0gInRyZW5kIiwgY2V4LmF4aXMgPSAwLjgsIG1haW49Ik1vbnRobHkgcGxvdCBvZiBUcmVuZCIpDQptb250aHBsb3QoZGVjb21wb3NlLCBjaG9pY2UgPSAicmVtYWluZGVyIiwgdHlwZSA9ICJoIiwgY2V4LmF4aXMgPSAwLjgsICwgbWFpbj0iTW9udGhseSBwbG90IG9mIFJlbWFpbmRlciIpDQpgYGANCg0KYGBge3IsIH0NCiNjaGVjayBmb3Igc2Vhc29uYWxpdHkNCnF1YXJ0ZXIgPC0gKGN5Y2xlKGxvYW5fdG9fZGVwb3NpdCktMSApICUvJSAzDQptb250aHBsb3QobG9hbl90b19kZXBvc2l0LCBwaGFzZSA9IHF1YXJ0ZXIsIG1haW49IlF1YXJ0ZXJseSBQbG90OiBMb2FuLXRvLWRlcG9zaXQgUmF0aW8iKQ0KYGBgDQpUaGUgcXVhcnRlcmx5IHBsb3QgcmV2ZWFsIGEgc3Ryb25nIHF1YXJ0ZXJseSBzZWFzb25hbGl0eS4NCg0KDQojIyNEZXRlcm1pbmluZyBpZiB0aGUgVGltZSBTZXJpZXMgaXMgU3RhdGlvbmFyeQ0KDQpVc2luZyB0aGUgUiAqKnRzZGlzcGxheSoqIG1ldGhvZCwgSSBnZW5lcmF0ZWQgdGhlIEFDRiBhbmQgUEFDRiBwbG90cy4gVGhlIEFDRiBwbG90cyBzaG93IGEgZ3JhZHVhbCBkZWNyZWFzZSB3aGljaCBpbXBsaWVzIHRoYXQgdGhlIHRpbWUgc2VyaWVzIGlzIG5vdCBzdGF0aW9uYXJ5DQoNCg0KYGBge3IgfQ0KdHNkaXNwbGF5KGxvYW5fdG9fZGVwb3NpdCkNCmBgYA0KDQoNCiMjI0RldGVybWluaW5nIHRoZSBEaWZmZXJlbmNpbmcgT3JkZXIgdG8gTWFrZSBUaW1lIFNlcmllcyBTdGF0aW9uYXJ5DQoNCg0KVGhlIG9yaWdpbmFsIGRhdGEgY29udGFpbnMgdHJlbmRzLiBUbyBjb252ZXJ0IHRoZSB0aW1lIHNlcmllcyB0byBhIHN0YXRpb25hcnkgdGltZSBzZXJpZXMgSSBtYWRlIHVzZSBvZiB0aGUgIFIgICoqZGlmZnMqKiAgbWV0aG9kLiANClRvIGRldGVybWluZSB0aGUgb3JkZXIgb2YgZGlmZmVyZW5jZSB0byBhcHBseSBJIG1hZGUgIHVzZSBvZiB0aGUgUiBmb3JlY2FzdCBwYWNrYWdlIG1ldGhvZCBuZGlmZnMsIG5kaWZmcyhsb2FuX3RvX2RlcG9zaXQpID0gYHIgbmRpZmZzKGxvYW5fdG9fZGVwb3NpdCkgYCAgDQpUbyBkZXRlcm1pbmUgdGhlIG5lZWQgZm9yIG9yZGVyIG9mIHNlYXNvbmFsaXR5IGRpZmZlcmVuY2UgdG8gYXBwbHkgSSBtYWRlIHVzZSBvZiBuc2RpZmZzLCBuc2RpZmZzKGxvYW5fdG9fZGVwb3NpdCkgPSBgciBuc2RpZmZzKGxvYW5fdG9fZGVwb3NpdCkgYCAgDQpUaGUgcmVzdWx0IHNob3cgdGhhdCBvbmx5IGZpcnN0IG9yZGVyIGRpZmZlcmVuY2luZyBvZiB0aGUgdGltZSBzZXJpZXMgaXMgcmVxdWlyZWQgdG8gbWFrZSB0aGUgc2VyaWVzIHN0YXRpb25hcnkNCg0KDQpgYGB7ciB9DQpsZXZlbF9vZl9kaWZmZXJlbmNlIDwtIG5kaWZmcyhsb2FuX3RvX2RlcG9zaXQpDQpkaWZmX2RhdGEgPC0gZGlmZihsb2FuX3RvX2RlcG9zaXQsIGxldmVsX29mX2RpZmZlcmVuY2UpDQoNCnBsb3QoZGlmZl9kYXRhLCB5bGFiPSJmaXJzdCBvcmRlciBkaWZmZXJlbmNlIGxvYW5zLXRvLWRlcG9zaXQiKQ0KdHNkaXNwbGF5KGRpZmZfZGF0YSwgbWFpbj0iZmlyc3Qgb3JkZXIgZGlmZmVyZW5jaW5nIG9mIGxvYW5zLXRvLWRlcG9zaXQgcmF0aW8gdGltZSBzZXJpZXMiKQ0KDQpgYGANCg0KVGhlIEFDRiBhYm92ZSBzaG93cyB0aGF0IHRoZXJlIGlzIG9ubHkgb25lIGF1dG9jb3JyZWxhdGlvbiB0aGF0IGlzIG91dHNpZGUgdGhlIDk1JSBsaW1pdC4NCg0KDQojIyNJbnZlc3RpZ2F0aW5nIE90aGVyIHRpbWUgc2VyaWVzIGRhdGFzZXQNCiMjIyMgVGhlIE5pZ2VyaWFuIEFpciB0b3RhbCBwYXNzZW5nZXJzIHRyYXZlbCB0aW1lIHNlcmllcyBkYXRhc2V0ICANClRoZSBkYXRhc2V0ICBpcyBmcm9tIHRoZSAgW1dvcmxkIGJhbmsgd2Vic2l0ZV0oaHR0cDovL2RhdGEud29ybGRiYW5rLm9yZy9pbmRpY2F0b3IvSVMuQUlSLlBTR1IpDQoNCmBgYHtyLCBpbmNsdWRlPUZBTFNFfQ0KDQphaXJfdHJhdmVsIDwtIHJlYWQuY3N2KCJBUElfSVMuQUlSLlBTR1JfRFMyX2VuX2Nzdl92Mi9BUElfSVMuQUlSLlBTR1JfRFMyX2VuX2Nzdl92Mi5DU1YiLCBoZWFkZXIgPSBUUlVFLHNraXAgPSA0LGNvbW1lbnQuY2hhcj0iIikNCg0KaGVhZChhaXJfdHJhdmVsLDUpDQoNCmxpYnJhcnkodGlkeXIpDQpsaWJyYXJ5KGRwbHlyKQ0KbGlicmFyeShzdHJpbmdyKQ0KbGlicmFyeSh0c291dGxpZXJzKQ0KDQphaXJfdHJhdmVsX2RmIDwtIGFzLmRhdGEuZnJhbWUoYWlyX3RyYXZlbCkNCg0KZ2hhbmFfbmlnZXJpYSA8LSBmaWx0ZXIoYWlyX3RyYXZlbF9kZiwgQ291bnRyeS5OYW1lID09Ik5pZ2VyaWEiIHwgQ291bnRyeS5OYW1lPT0iR2hhbmEiKQ0KDQpnaGFuYV9uaWdlcmlhX3RoaW4gPC0gZ2F0aGVyKGdoYW5hX25pZ2VyaWEsInllYXIiLCJuIiw1OjYyKQ0KDQpjbGVhbl9kYXRhIDwtIHNlbGVjdChnaGFuYV9uaWdlcmlhX3RoaW4sQ291bnRyeS5Db2RlLHllYXIsbikNCmNsZWFuX2RhdGEkeWVhciA8LSBzdHJfc3ViKGNsZWFuX2RhdGEkeWVhciwyKQ0KDQpjbGVhbl9kYXRhIDwtIGZpbHRlcihjbGVhbl9kYXRhLCB5ZWFyPj0xOTcwICYgeWVhcjwyMDE2KSAlPiUgc3ByZWFkKENvdW50cnkuQ29kZSxuKSU+JSANCiAgICAgICAgICAgIG11dGF0ZShHSEE9R0hBLzEwMDAsTkdBPU5HQS8xMDAwICkNCg0KDQoNCnRzX2NsZWFuX2RhdGEgPC0gdHMoY2xlYW5fZGF0YVssYygiR0hBIiwiTkdBIildLCBlbmQ9MjAxNSwgZnJlcXVlbmN5PTEpDQoNCm5pZ2VyaWEgPC0gdHNfY2xlYW5fZGF0YVssMl0NCmBgYA0KDQpgYGB7cn0NCnBsb3QudHMobmlnZXJpYSx5bGFiPSJOdW1iZXIgb2YgUGFzc2VuZ2VycyBwZXIgMTAwMCIsIG1haW4gPSAiTmlnZXJpYSAgWWVhcmx5IEFpciBQYXNzZW5nZXJzIDE5NzAgLSAyMDE1ICIpDQpgYGANCg0KIyMjSW52ZXN0aWdhdGluZyBUaW1lIFNlcmllcyBTdGF0aW9uYXJpdHk6IE5pZ2VyaWFuIEFpciBUcmF2ZWwgUGFzc2VuZ2Vycw0KVGhlIHllYXJseSAgdGltZSBzZXJpZXMgcGxvdCBhYm92ZSBkb2VzIG5vdCBjb250YWluIHNlYXNvbmFsaXR5LiBUaGUgcGxvdCBzaG93IGV2aWRlbmNlIG9mIGEgdHJlbmQsIGhlbmNlIHRoaXMgc2VyaWVzIGlzIG5vdCBzdGF0aW9uYXJ5ICANCkluc3BlY3RpbmcgdGhlIEFDRiBhbmQgUEFDRiBncmFwaCBhbmQgZGV0ZXJtaW5pbmcgdGhlIG9yZGVyIG9mIGRpZmZlcmVuY2luZyB0aGUgdGltZSBzZXJpZXMgYWxzbyBjb25maXJtcyB0aGlzLiAgDQpSZXF1aXJlZCBvcmRlciBmb3IgZGlmZmVyZW5jaW5nICwgbmRpZmZzKG5pZ2VyaWEpPSBgciBuZGlmZnMobmlnZXJpYSkgYCAgDQpVc2luZyB0aGUgQURGIHRlc3QsIHRoZSBwIHZhbHVlIG9mIDAuNzQwOCBhbHNvIGNvbmZpcm1zIHRoYXQgdGhlIHBsb3QgaXMgbm90IHN0YXRpb25hcnkNCg0KYGBge3J9DQp0c2Rpc3BsYXkobmlnZXJpYSkNCmFkZi50ZXN0KG5pZ2VyaWEpDQpgYGANCg0KRmlyc3QgT3JkZXIgRGlmZmVyZW5jZWQgVGltZSBTZXJpZXMgDQpgYGB7cn0NCnRzZGlzcGxheShkaWZmKG5pZ2VyaWEpLCBtYWluPSJGaXJzdCBPcmRlciBEaWZmZXJlbmNlIFRpbWUgU2VyaWVzICIpDQphZGYudGVzdChkaWZmKG5pZ2VyaWEpKQ0KYGBgDQpUaGUgZ3JhcGggYWJvdmUgc2hvd3MgdGhlIGZpcnN0IG9yZGVyIGRpZmZlcmVuY2VkIHRpbWUgc2VyaWVzLiAgVGhlIGFkZi50ZXN0IHNtYWxsIHAgdmFsdWUgaW5kaWNhdGVzIHRoYXQgdGhlIHRpbWUgc2VyaWVzIGlzIG5vdyBzdGF0aW9uYXJ5LiAgSG93ZXZlciBpdCB3b3VsZCBiZSBvYnNlcnZlZCB0aGF0IHRoZSBvdXRsaWVyIHBvaW50cyBjYW4gc3RpbGwgYmUgb2JzZXJ2ZWQgaW4gdGhlIGRpZmZlcmVuY2VkIHRpbWUgc2VyaWVzLg0KIyMjVXNpbmcgQVVUTy5BUklNQSB0byBkZXRlcm1pbmUgdGhlIGJlc3QgbW9kZWwgZm9yIHRoZSBBaXIgVHJhdmVsIFRpbWUgc2VyaWVzDQpgYGB7ciwgfQ0KbmlnZXJpYV9maXQgPC0gYXV0by5hcmltYShuaWdlcmlhKQ0KDQpzdW1tYXJ5KG5pZ2VyaWFfZml0KQ0KDQoNCmBgYA0KDQojIyNVc2luZyBFVFMoU0VTKSB0byBkZXRlcm1pbmUgdGhlIGJlc3QgbW9kZWwgZm9yIHRoZSBBaXIgVHJhdmVsIFRpbWUgc2VyaWVzDQpgYGB7ciwgfQ0KbmlnZXJpYV9maXRfc2VzIDwtIHNlcyhuaWdlcmlhLCBpbml0aWFsID0gInNpbXBsZSIpDQoNCnN1bW1hcnkobmlnZXJpYV9maXRfc2VzKQ0KYGBgDQpgYGB7cn0NCnBsb3QobmlnZXJpYSwgbWFpbj0gIkFSSU1BICgwLDEsMCkgJiBTRVMgKGFscGhhPTEpIE1vZGVsIFBsb3QiLHlsYWI9Ik51bWJlciBvZiBQYXNzZW5nZXJzIHBlciAxMDAwIikNCmxpbmVzKGZpdHRlZChuaWdlcmlhX2ZpdCksIGNvbD0icmVkIikNCmxpbmVzKGZpdHRlZChuaWdlcmlhX2ZpdF9zZXMpLCBjb2w9ImJsdWUiKQ0KbGVnZW5kKCJ0b3BsZWZ0IixsdHk9MSwgY29sPWMoImJsYWNrIiwiYmx1ZSIsInJlZCIpLCANCiAgICAgICBjKCJEYXRhIiwiQVJJTUEgTW9kZWwiLCJTRVMgTW9kZWwiKSxjZXg9MC44MCkNCg0KYGBgDQpJbiB0aGUgcGxvdCBhYm92ZSB0aGUgU0VTIG1vZGVsIGlzIG5vdCBub3RpY2FibGUgYmVjYXVzZSBpdCByZXR1cm5zIHRoZSBzYW1lIHZhbHVlIGFzIEFSSU1BKDAsMSwwKSBtb2RlbC4gICAgDQoNCiMjIyNDb21wYXJpbmcgdGhlIEFSSU1BIGFuZCBTRVMgTW9kZWxzIEZpdCBWYWx1ZXMNCmBgYHtyfQ0KI0NvbXBhcmluZyBBUklNQSBhbmQgU0VTIG1vZGVscyBmaXQgdmFsdWVzDQphcmltYV9tb2RlbDwtIHdpbmRvdyhmaXR0ZWQobmlnZXJpYV9maXQpLDE5NzAsMTk5MCkNCnNlc19tb2RlbDwtIHdpbmRvdyhmaXR0ZWQobmlnZXJpYV9maXRfc2VzKSwxOTcwLDE5OTApDQp0cy51bmlvbihhcmltYV9tb2RlbCxzZXNfbW9kZWwpDQoNCiNsYXN0IDE1IHZhbHVlcw0KYXJpbWFfbW9kZWwyPC0gd2luZG93KGZpdHRlZChuaWdlcmlhX2ZpdCksMjAwMCwyMDE1KQ0Kc2VzX21vZGVsMjwtIHdpbmRvdyhmaXR0ZWQobmlnZXJpYV9maXRfc2VzKSwyMDAwLDIwMTUpDQp0cy51bmlvbihhcmltYV9tb2RlbDIsc2VzX21vZGVsMikNCmBgYA0KDQogICAgDQojIyMjSW52ZXN0aWdhdGluZyB0aGUgTW9kZWwgUmVzaWR1YWxzIGFuZCBPdXRsaWVyIGltcGFjdCAgDQoNCmBgYHtyLCB9DQoNCm5pZ2VyaWFfb3V0bGllcnMgPC10c28obmlnZXJpYSx0eXBlcz1jKCJBTyIsIkxTIiwiVEMiLCJJTyIpKQ0KDQpwbG90KHJlc2lkdWFscyhuaWdlcmlhX2ZpdCksIG1haW49IkFSSU1BKDAsMSwwKSAmIFNFUyAoYWxwaGEgPSAxKSByZXNpZHVhbHMiLCBjb2w9ImJsdWUiLCB5bGFiPSJSZXNpZHVhbDogTnVtYmVyIG9mIFBhc3NlbmdlcnMgcGVyIDEwMDAiKQ0KbGluZXMocmVzaWR1YWxzKG5pZ2VyaWFfZml0X3NlcyksIGNvbD0icmVkIikNCmxlZ2VuZCgidG9wbGVmdCIsbHR5PTEsIGNvbD1jKCJibHVlIiwicmVkIiksIA0KICAgICAgIGMoIkFSSU1BIFJlc2lkdWFsIiwiU0VTIFJlc2lkdWFsIiksY2V4PTAuODApDQoNCiNwbG90aW5nIHRoZSBvdXRsaWVycw0KcGxvdChuaWdlcmlhX291dGxpZXJzKQ0KDQpgYGANCg0KIyMjIEJveCBQbG90IHRvIFZlcmlmeSBPdXRsaWVycw0KYGBge3J9DQpib3hwbG90KG5pZ2VyaWEsIG1haW49IkJveCBQbG90IG9mIE5pZ2VyaWEgIFllYXJseSBBaXIgUGFzc2VuZ2VycyAxOTcwIC0gMjAxNSAgIikNCmBgYA0KDQpSZXZpZXdpbmcgdGhlIG91dGxpZXIgcGxvdCBhbmQgbW9kZWwgcmVzaWR1YWwgcGxvdCwgaXQgd291bGQgYmUgb2JzZXJ2ZWQgdGhhdCB0aGUgb3V0bGllcnMgaGFkIHBvb3IgbW9kZWwgcmVwcmVzZW50YXRpb24gY29tcGFyZWQgdG8gb3RoZXIgZGF0YSBwb2ludHMgaW4gdGhlIHRpbWUgc2VyaWVzLiBTRVMgYW5kIEFSSU1BIG1vZGVsIGZvciB0aGlzIHRpbWUgc2VyaWVzIHJldHVybmVkIHRoZSBzYW1lIHZhbHVlLg==