library(tidyverse)
library(forecast)
library(gridExtra)
library(Metrics)
library(tvReg)
library(tsibble)
library(fable)
library(fable.prophet)
library(hms)
library(lubridate)

Load dataset

data <- read_csv("data2.csv") %>% mutate(time=hms::as_hms(ts), day=day(ts))
Rows: 3600 Columns: 3── Column specification ─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
Delimiter: ","
dbl  (2): rate, occupancy
dttm (1): ts
ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
head(data)
tail(data)
train    <- data %>% filter(day!=25)
test     <- data %>% filter(day==25)
data.ts  <- data %>% select(ts,occupancy,rate) %>% as_tsibble(index = ts)
train.ts <- train %>% select(ts,occupancy,rate) %>% as_tsibble(index = ts)
test.ts  <- test %>% select(ts,occupancy,rate) %>% as_tsibble(index = ts)

Modeling

Time series data

y <- ts(data = train$rate, frequency = 144)
x <- ts(data = train$occupancy, frequency = 144)
autoplot(y) + xlab("") + ylab("Energy consumption (kWh)")

Linear Regression

m <- list()
m[["LM"]] <- train.ts %>% model(lm=TSLM(rate~log(occupancy)))
m[["LM"]] %>% forecast(test.ts) %>% autoplot()

ARIMA

m[["ARIMA"]] <- auto.arima(y)
summary(m[["ARIMA"]])
Series: y 
ARIMA(1,0,2)(0,1,0)[144] 

Coefficients:
         ar1      ma1      ma2
      0.9662  -0.4559  -0.1216
s.e.  0.0053   0.0184   0.0183

sigma^2 = 151.4:  log likelihood = -13011.89
AIC=26031.78   AICc=26031.79   BIC=26056.2

Training set error measures:
                    ME     RMSE      MAE        MPE    MAPE      MASE         ACF1
Training set 0.1073758 12.04051 8.923401 -0.4944098 7.43582 0.5325004 -0.002891708
m[["ARIMA"]] %>% forecast::forecast(h=144) %>% autoplot()

ARIMAX

m[["ARIMAX"]] <- auto.arima(y, xreg = x)
summary(m[["ARIMAX"]])
Series: y 
Regression with ARIMA(1,0,3)(0,1,0)[144] errors 

Coefficients:
         ar1      ma1      ma2     ma3    xreg
      0.9346  -0.4514  -0.1321  0.0278  0.0364
s.e.  0.0097   0.0197   0.0198  0.0189  0.0037

sigma^2 = 148:  log likelihood = -12973.41
AIC=25958.82   AICc=25958.85   BIC=25995.45

Training set error measures:
                    ME     RMSE      MAE        MPE     MAPE      MASE          ACF1
Training set 0.0835479 11.90231 8.856013 -0.5202593 7.365541 0.5284791 -0.0002280971
m[["ARIMAX"]] %>% forecast::forecast(h=144, xreg=test$occupancy) %>% autoplot()

Prophet Forecast

m[["Prophet"]] <- train.ts %>% model(prophet = prophet(rate ~ growth("linear") + season("day", type = "multiplicative")))

components(m[["Prophet"]]) %>% autoplot()

m[["Prophet"]] %>% forecast(test.ts) %>% autoplot()

components(m[["Prophet"]])

Prophet Forecast with covariate

m[["Prophet2"]] <- train.ts %>% model(prophet = prophet(rate ~ growth("linear") + season("day", type = "multiplicative") + occupancy))

components(m[["Prophet2"]]) %>% autoplot()

m[["Prophet2"]] %>% forecast(test.ts) %>% autoplot()

components(m[["Prophet2"]])

NNETAR

m[["NNETAR"]] <- nnetar(y, size=20, lambda="auto")
m[["NNETAR"]]
Series: y 
Model:  NNAR(17,1,20)[144] 
Call:   nnetar(y = y, size = 20, lambda = "auto")

Average of 20 networks, each of which is
a 18-20-1 network with 401 weights
options were - linear output units 

sigma^2 estimated as 0.001965
m[["NNETAR"]] %>% forecast::forecast(h=144, PI=TRUE) %>% autoplot()

NNETAR with covariate

m[["NNETAR2"]] <- nnetar(y, size=20, xreg=x, lambda="auto")
m[["NNETAR2"]]
Series: y 
Model:  NNAR(17,1,20)[144] 
Call:   nnetar(y = y, size = 20, xreg = x, lambda = "auto")

Average of 20 networks, each of which is
a 19-20-1 network with 421 weights
options were - linear output units 

sigma^2 estimated as 0.001891
m[["NNETAR2"]] %>% forecast::forecast(xreg=test$occupancy, PI=TRUE) %>% autoplot()

Forecasting and Evaluation

Forecasting

prediction <- test %>% select(ts, rate) %>% rename(actual = rate, time = ts)
n_test <- dim(prediction)[1]
prediction['LM'] <- (m[["LM"]] %>% forecast(test.ts))$.mean
prediction['ARIMA'] <- (m[["ARIMA"]] %>% forecast::forecast(h=144))$mean
prediction['ARIMAX'] <- (m[["ARIMAX"]] %>% forecast::forecast(h=144, xreg=test$occupancy))$mean
prediction['Prophet'] <- (m[["Prophet"]] %>% forecast(test.ts))$.mean
prediction['Prophet2'] <- (m[["Prophet2"]] %>% forecast(test.ts))$.mean
prediction['NNETAR'] <- (m[["NNETAR"]] %>% forecast::forecast(h=144))$mean
prediction['NNETAR2'] <- (m[["NNETAR2"]] %>% forecast::forecast(xreg=test$occupancy))$mean
head(prediction)
plotForecast <- function(data){
  p1 <- ggplot(data = data) + 
        geom_line(color = "red", aes(x = time, y = actual), size = 0.5, linetype = 2) +
        geom_line(color = "black", aes(x = time, y = LM)) + 
        xlab("") + ylab("") + ggtitle("Linear Model") + scale_x_datetime(date_labels = "%H:%M") 

  p2 <- ggplot(data = data) + 
        geom_line(color = "red", aes(x = time, y = actual), size = 0.5, linetype = 2) +
        geom_line(color = "black", aes(x = time, y = ARIMA)) +
        xlab("") + ylab("") + ggtitle("ARIMA") + scale_x_datetime(date_labels = "%H:%M") 
  
  p3 <- ggplot(data = data) + 
        geom_line(color = "red", aes(x = time, y = actual), size = 0.5, linetype = 2) +
        geom_line(color = "black", aes(x = time, y = ARIMAX)) +
        xlab("") + ylab("") + ggtitle("ARIMAX") + scale_x_datetime(date_labels = "%H:%M") 
  
  p4 <- ggplot(data = data) + 
        geom_line(color = "red", aes(x = time, y = actual), size = 0.5, linetype = 2) +
        geom_line(color = "black", aes(x = time, y = Prophet)) + 
        xlab("") + ylab("") + ggtitle("Prophet") + scale_x_datetime(date_labels = "%H:%M") 
  
  p5 <- ggplot(data = data) + 
        geom_line(color = "red", aes(x = time, y = actual), size = 0.5, linetype = 2) +
        geom_line(color = "black", aes(x = time, y = Prophet2)) + 
        xlab("") + ylab("") + ggtitle("Prophet with covariate") + scale_x_datetime(date_labels = "%H:%M")
  
  p6 <- ggplot(data = data) + 
        geom_line(color = "red", aes(x = time, y = actual), size = 0.5, linetype = 2) +
        geom_line(color = "black", aes(x = time, y = NNETAR)) +
        xlab("") + ylab("") + ggtitle("NNAR") + scale_x_datetime(date_labels = "%H:%M") 
  
  p7 <- ggplot(data = data) + 
        geom_line(color = "red", aes(x = time, y = actual), size = 0.5, linetype = 2) +
        geom_line(color = "black", aes(x = time, y = NNETAR2)) +
        xlab("") + ylab("") + ggtitle("NNAR with covariate") + scale_x_datetime(date_labels = "%H:%M") 
   
        
  grid.arrange(p1,p2,p3,p4,p5,p6,p7,nrow=3)
}
plotForecast(prediction)

Evaluation

RMSE

sort(apply(X = prediction[,-c(1,2)], MARGIN = 2, FUN = rmse, actual = prediction$actual))
Prophet2   ARIMAX       LM  NNETAR2    ARIMA  Prophet   NNETAR 
10.56564 12.36074 12.78291 13.30685 13.31192 16.04740 18.39696 

MAPE

sort(apply(X = prediction[,-c(1,2)], MARGIN = 2, FUN = mape, actual = prediction$actual))
  Prophet2     ARIMAX      ARIMA         LM    NNETAR2    Prophet     NNETAR 
0.07242431 0.07927125 0.08764947 0.09318489 0.09632072 0.10086697 0.12760569 

sMAPE

sort(apply(X = prediction[,-c(1,2)], MARGIN = 2, FUN = smape, actual = prediction$actual))
  Prophet2     ARIMAX      ARIMA         LM    NNETAR2    Prophet     NNETAR 
0.07083304 0.07606659 0.08267374 0.08474103 0.08623185 0.10229192 0.11784685 
LS0tCnRpdGxlOiAiTWFjaGluZSBMZWFybmluZyBGb3JlY2FzdGluZyIKb3V0cHV0OgogIGh0bWxfbm90ZWJvb2s6CiAgICB0b2M6IHRydWUKICAgIHRvY19mbG9hdDoKICAgICAgdG9jX2NvbGxhcHNlZDogdHJ1ZQotLS0KCmBgYHtyIGVjaG89VFJVRSwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KbGlicmFyeSh0aWR5dmVyc2UpCmxpYnJhcnkoZm9yZWNhc3QpCmxpYnJhcnkoZ3JpZEV4dHJhKQpsaWJyYXJ5KE1ldHJpY3MpCmxpYnJhcnkodHZSZWcpCmxpYnJhcnkodHNpYmJsZSkKbGlicmFyeShmYWJsZSkKbGlicmFyeShmYWJsZS5wcm9waGV0KQpsaWJyYXJ5KGhtcykKbGlicmFyeShsdWJyaWRhdGUpCmBgYAoKIyMgTG9hZCBkYXRhc2V0CgpgYGB7cn0KZGF0YSA8LSByZWFkX2NzdigiZGF0YTIuY3N2IikgJT4lIG11dGF0ZSh0aW1lPWhtczo6YXNfaG1zKHRzKSwgZGF5PWRheSh0cykpCmBgYAoKCmBgYHtyfQpoZWFkKGRhdGEpCmBgYAoKCmBgYHtyfQp0YWlsKGRhdGEpCmBgYAoKYGBge3J9CnRyYWluICAgIDwtIGRhdGEgJT4lIGZpbHRlcihkYXkhPTI1KQp0ZXN0ICAgICA8LSBkYXRhICU+JSBmaWx0ZXIoZGF5PT0yNSkKZGF0YS50cyAgPC0gZGF0YSAlPiUgc2VsZWN0KHRzLG9jY3VwYW5jeSxyYXRlKSAlPiUgYXNfdHNpYmJsZShpbmRleCA9IHRzKQp0cmFpbi50cyA8LSB0cmFpbiAlPiUgc2VsZWN0KHRzLG9jY3VwYW5jeSxyYXRlKSAlPiUgYXNfdHNpYmJsZShpbmRleCA9IHRzKQp0ZXN0LnRzICA8LSB0ZXN0ICU+JSBzZWxlY3QodHMsb2NjdXBhbmN5LHJhdGUpICU+JSBhc190c2liYmxlKGluZGV4ID0gdHMpCmBgYAoKCiMjIE1vZGVsaW5nCgojIyMgVGltZSBzZXJpZXMgZGF0YQpgYGB7cn0KeSA8LSB0cyhkYXRhID0gdHJhaW4kcmF0ZSwgZnJlcXVlbmN5ID0gMTQ0KQp4IDwtIHRzKGRhdGEgPSB0cmFpbiRvY2N1cGFuY3ksIGZyZXF1ZW5jeSA9IDE0NCkKYXV0b3Bsb3QoeSkgKyB4bGFiKCIiKSArIHlsYWIoIkVuZXJneSBjb25zdW1wdGlvbiAoa1doKSIpCmBgYAoKIyMjIExpbmVhciBSZWdyZXNzaW9uCmBgYHtyfQptIDwtIGxpc3QoKQptW1siTE0iXV0gPC0gdHJhaW4udHMgJT4lIG1vZGVsKGxtPVRTTE0ocmF0ZX5sb2cob2NjdXBhbmN5KSkpCmBgYAoKCmBgYHtyfQptW1siTE0iXV0gJT4lIGZvcmVjYXN0KHRlc3QudHMpICU+JSBhdXRvcGxvdCgpCmBgYAoKCiMjIyBBUklNQQpgYGB7cn0KbVtbIkFSSU1BIl1dIDwtIGF1dG8uYXJpbWEoeSkKc3VtbWFyeShtW1siQVJJTUEiXV0pCmBgYAoKYGBge3J9Cm1bWyJBUklNQSJdXSAlPiUgZm9yZWNhc3Q6OmZvcmVjYXN0KGg9MTQ0KSAlPiUgYXV0b3Bsb3QoKQpgYGAKCgojIyMgQVJJTUFYCmBgYHtyfQptW1siQVJJTUFYIl1dIDwtIGF1dG8uYXJpbWEoeSwgeHJlZyA9IHgpCnN1bW1hcnkobVtbIkFSSU1BWCJdXSkKYGBgCgoKYGBge3J9Cm1bWyJBUklNQVgiXV0gJT4lIGZvcmVjYXN0Ojpmb3JlY2FzdChoPTE0NCwgeHJlZz10ZXN0JG9jY3VwYW5jeSkgJT4lIGF1dG9wbG90KCkKYGBgCgojIyMgUHJvcGhldCBGb3JlY2FzdCAKCmBgYHtyfQptW1siUHJvcGhldCJdXSA8LSB0cmFpbi50cyAlPiUgbW9kZWwocHJvcGhldCA9IHByb3BoZXQocmF0ZSB+IGdyb3d0aCgibGluZWFyIikgKyBzZWFzb24oImRheSIsIHR5cGUgPSAibXVsdGlwbGljYXRpdmUiKSkpCgpjb21wb25lbnRzKG1bWyJQcm9waGV0Il1dKSAlPiUgYXV0b3Bsb3QoKQpgYGAKCmBgYHtyfQptW1siUHJvcGhldCJdXSAlPiUgZm9yZWNhc3QodGVzdC50cykgJT4lIGF1dG9wbG90KCkKYGBgCgpgYGB7cn0KY29tcG9uZW50cyhtW1siUHJvcGhldCJdXSkKYGBgCgoKIyMjIFByb3BoZXQgRm9yZWNhc3Qgd2l0aCBjb3ZhcmlhdGUKCmBgYHtyfQptW1siUHJvcGhldDIiXV0gPC0gdHJhaW4udHMgJT4lIG1vZGVsKHByb3BoZXQgPSBwcm9waGV0KHJhdGUgfiBncm93dGgoImxpbmVhciIpICsgc2Vhc29uKCJkYXkiLCB0eXBlID0gIm11bHRpcGxpY2F0aXZlIikgKyBvY2N1cGFuY3kpKQoKY29tcG9uZW50cyhtW1siUHJvcGhldDIiXV0pICU+JSBhdXRvcGxvdCgpCmBgYAoKYGBge3J9Cm1bWyJQcm9waGV0MiJdXSAlPiUgZm9yZWNhc3QodGVzdC50cykgJT4lIGF1dG9wbG90KCkKYGBgCgpgYGB7cn0KY29tcG9uZW50cyhtW1siUHJvcGhldDIiXV0pCmBgYAoKIyMjIE5ORVRBUiAKCmBgYHtyfQptW1siTk5FVEFSIl1dIDwtIG5uZXRhcih5LCBzaXplPTIwLCBsYW1iZGE9ImF1dG8iKQptW1siTk5FVEFSIl1dCmBgYAoKCmBgYHtyfQptW1siTk5FVEFSIl1dICU+JSBmb3JlY2FzdDo6Zm9yZWNhc3QoaD0xNDQsIFBJPVRSVUUpICU+JSBhdXRvcGxvdCgpCmBgYAoKCiMjIyBOTkVUQVIgd2l0aCBjb3ZhcmlhdGUKCmBgYHtyfQptW1siTk5FVEFSMiJdXSA8LSBubmV0YXIoeSwgc2l6ZT0yMCwgeHJlZz14LCBsYW1iZGE9ImF1dG8iKQptW1siTk5FVEFSMiJdXQpgYGAKCgpgYGB7cn0KbVtbIk5ORVRBUjIiXV0gJT4lIGZvcmVjYXN0Ojpmb3JlY2FzdCh4cmVnPXRlc3Qkb2NjdXBhbmN5LCBQST1UUlVFKSAlPiUgYXV0b3Bsb3QoKQpgYGAKCgoKCiMjIEZvcmVjYXN0aW5nIGFuZCBFdmFsdWF0aW9uCgojIyMgRm9yZWNhc3RpbmcKYGBge3J9CnByZWRpY3Rpb24gPC0gdGVzdCAlPiUgc2VsZWN0KHRzLCByYXRlKSAlPiUgcmVuYW1lKGFjdHVhbCA9IHJhdGUsIHRpbWUgPSB0cykKbl90ZXN0IDwtIGRpbShwcmVkaWN0aW9uKVsxXQpwcmVkaWN0aW9uWydMTSddIDwtIChtW1siTE0iXV0gJT4lIGZvcmVjYXN0KHRlc3QudHMpKSQubWVhbgpwcmVkaWN0aW9uWydBUklNQSddIDwtIChtW1siQVJJTUEiXV0gJT4lIGZvcmVjYXN0Ojpmb3JlY2FzdChoPTE0NCkpJG1lYW4KcHJlZGljdGlvblsnQVJJTUFYJ10gPC0gKG1bWyJBUklNQVgiXV0gJT4lIGZvcmVjYXN0Ojpmb3JlY2FzdChoPTE0NCwgeHJlZz10ZXN0JG9jY3VwYW5jeSkpJG1lYW4KcHJlZGljdGlvblsnUHJvcGhldCddIDwtIChtW1siUHJvcGhldCJdXSAlPiUgZm9yZWNhc3QodGVzdC50cykpJC5tZWFuCnByZWRpY3Rpb25bJ1Byb3BoZXQyJ10gPC0gKG1bWyJQcm9waGV0MiJdXSAlPiUgZm9yZWNhc3QodGVzdC50cykpJC5tZWFuCnByZWRpY3Rpb25bJ05ORVRBUiddIDwtIChtW1siTk5FVEFSIl1dICU+JSBmb3JlY2FzdDo6Zm9yZWNhc3QoaD0xNDQpKSRtZWFuCnByZWRpY3Rpb25bJ05ORVRBUjInXSA8LSAobVtbIk5ORVRBUjIiXV0gJT4lIGZvcmVjYXN0Ojpmb3JlY2FzdCh4cmVnPXRlc3Qkb2NjdXBhbmN5KSkkbWVhbgpgYGAKCgpgYGB7cn0KaGVhZChwcmVkaWN0aW9uKQpgYGAKCmBgYHtyfQpwbG90Rm9yZWNhc3QgPC0gZnVuY3Rpb24oZGF0YSl7CiAgcDEgPC0gZ2dwbG90KGRhdGEgPSBkYXRhKSArIAogICAgICAgIGdlb21fbGluZShjb2xvciA9ICJyZWQiLCBhZXMoeCA9IHRpbWUsIHkgPSBhY3R1YWwpLCBzaXplID0gMC41LCBsaW5ldHlwZSA9IDIpICsKICAgICAgICBnZW9tX2xpbmUoY29sb3IgPSAiYmxhY2siLCBhZXMoeCA9IHRpbWUsIHkgPSBMTSkpICsgCiAgICAgICAgeGxhYigiIikgKyB5bGFiKCIiKSArIGdndGl0bGUoIkxpbmVhciBNb2RlbCIpICsgc2NhbGVfeF9kYXRldGltZShkYXRlX2xhYmVscyA9ICIlSDolTSIpIAoKICBwMiA8LSBnZ3Bsb3QoZGF0YSA9IGRhdGEpICsgCiAgICAgICAgZ2VvbV9saW5lKGNvbG9yID0gInJlZCIsIGFlcyh4ID0gdGltZSwgeSA9IGFjdHVhbCksIHNpemUgPSAwLjUsIGxpbmV0eXBlID0gMikgKwogICAgICAgIGdlb21fbGluZShjb2xvciA9ICJibGFjayIsIGFlcyh4ID0gdGltZSwgeSA9IEFSSU1BKSkgKwogICAgICAgIHhsYWIoIiIpICsgeWxhYigiIikgKyBnZ3RpdGxlKCJBUklNQSIpICsgc2NhbGVfeF9kYXRldGltZShkYXRlX2xhYmVscyA9ICIlSDolTSIpIAogIAogIHAzIDwtIGdncGxvdChkYXRhID0gZGF0YSkgKyAKICAgICAgICBnZW9tX2xpbmUoY29sb3IgPSAicmVkIiwgYWVzKHggPSB0aW1lLCB5ID0gYWN0dWFsKSwgc2l6ZSA9IDAuNSwgbGluZXR5cGUgPSAyKSArCiAgICAgICAgZ2VvbV9saW5lKGNvbG9yID0gImJsYWNrIiwgYWVzKHggPSB0aW1lLCB5ID0gQVJJTUFYKSkgKwogICAgICAgIHhsYWIoIiIpICsgeWxhYigiIikgKyBnZ3RpdGxlKCJBUklNQVgiKSArIHNjYWxlX3hfZGF0ZXRpbWUoZGF0ZV9sYWJlbHMgPSAiJUg6JU0iKSAKICAKICBwNCA8LSBnZ3Bsb3QoZGF0YSA9IGRhdGEpICsgCiAgICAgICAgZ2VvbV9saW5lKGNvbG9yID0gInJlZCIsIGFlcyh4ID0gdGltZSwgeSA9IGFjdHVhbCksIHNpemUgPSAwLjUsIGxpbmV0eXBlID0gMikgKwogICAgICAgIGdlb21fbGluZShjb2xvciA9ICJibGFjayIsIGFlcyh4ID0gdGltZSwgeSA9IFByb3BoZXQpKSArIAogICAgICAgIHhsYWIoIiIpICsgeWxhYigiIikgKyBnZ3RpdGxlKCJQcm9waGV0IikgKyBzY2FsZV94X2RhdGV0aW1lKGRhdGVfbGFiZWxzID0gIiVIOiVNIikgCiAgCiAgcDUgPC0gZ2dwbG90KGRhdGEgPSBkYXRhKSArIAogICAgICAgIGdlb21fbGluZShjb2xvciA9ICJyZWQiLCBhZXMoeCA9IHRpbWUsIHkgPSBhY3R1YWwpLCBzaXplID0gMC41LCBsaW5ldHlwZSA9IDIpICsKICAgICAgICBnZW9tX2xpbmUoY29sb3IgPSAiYmxhY2siLCBhZXMoeCA9IHRpbWUsIHkgPSBQcm9waGV0MikpICsgCiAgICAgICAgeGxhYigiIikgKyB5bGFiKCIiKSArIGdndGl0bGUoIlByb3BoZXQgd2l0aCBjb3ZhcmlhdGUiKSArIHNjYWxlX3hfZGF0ZXRpbWUoZGF0ZV9sYWJlbHMgPSAiJUg6JU0iKQogIAogIHA2IDwtIGdncGxvdChkYXRhID0gZGF0YSkgKyAKICAgICAgICBnZW9tX2xpbmUoY29sb3IgPSAicmVkIiwgYWVzKHggPSB0aW1lLCB5ID0gYWN0dWFsKSwgc2l6ZSA9IDAuNSwgbGluZXR5cGUgPSAyKSArCiAgICAgICAgZ2VvbV9saW5lKGNvbG9yID0gImJsYWNrIiwgYWVzKHggPSB0aW1lLCB5ID0gTk5FVEFSKSkgKwogICAgICAgIHhsYWIoIiIpICsgeWxhYigiIikgKyBnZ3RpdGxlKCJOTkFSIikgKyBzY2FsZV94X2RhdGV0aW1lKGRhdGVfbGFiZWxzID0gIiVIOiVNIikgCiAgCiAgcDcgPC0gZ2dwbG90KGRhdGEgPSBkYXRhKSArIAogICAgICAgIGdlb21fbGluZShjb2xvciA9ICJyZWQiLCBhZXMoeCA9IHRpbWUsIHkgPSBhY3R1YWwpLCBzaXplID0gMC41LCBsaW5ldHlwZSA9IDIpICsKICAgICAgICBnZW9tX2xpbmUoY29sb3IgPSAiYmxhY2siLCBhZXMoeCA9IHRpbWUsIHkgPSBOTkVUQVIyKSkgKwogICAgICAgIHhsYWIoIiIpICsgeWxhYigiIikgKyBnZ3RpdGxlKCJOTkFSIHdpdGggY292YXJpYXRlIikgKyBzY2FsZV94X2RhdGV0aW1lKGRhdGVfbGFiZWxzID0gIiVIOiVNIikgCiAgIAogICAgICAgIAogIGdyaWQuYXJyYW5nZShwMSxwMixwMyxwNCxwNSxwNixwNyxucm93PTMpCn0KYGBgCgoKCgpgYGB7cn0KcGxvdEZvcmVjYXN0KHByZWRpY3Rpb24pCmBgYAoKIyMjIEV2YWx1YXRpb24KCiMjIyMgUk1TRQpgYGB7cn0Kc29ydChhcHBseShYID0gcHJlZGljdGlvblssLWMoMSwyKV0sIE1BUkdJTiA9IDIsIEZVTiA9IHJtc2UsIGFjdHVhbCA9IHByZWRpY3Rpb24kYWN0dWFsKSkKYGBgCgojIyMjIE1BUEUKYGBge3J9CnNvcnQoYXBwbHkoWCA9IHByZWRpY3Rpb25bLC1jKDEsMildLCBNQVJHSU4gPSAyLCBGVU4gPSBtYXBlLCBhY3R1YWwgPSBwcmVkaWN0aW9uJGFjdHVhbCkpCmBgYAoKIyMjIyBzTUFQRQpgYGB7cn0Kc29ydChhcHBseShYID0gcHJlZGljdGlvblssLWMoMSwyKV0sIE1BUkdJTiA9IDIsIEZVTiA9IHNtYXBlLCBhY3R1YWwgPSBwcmVkaWN0aW9uJGFjdHVhbCkpCmBgYAoKCgo=