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

Load dataset

url_link = "https://gist.github.com/novrisuhermi/86d88b5d82cea37007979921c38fc207/raw/03ded2a94d48aa77dd18d37b11574801aaa62364/data2.csv"
data <- read_csv(url_link) %>% 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.001969
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.001873
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)
Warning: Using `size` aesthetic for lines was deprecated in ggplot2 3.4.0.
ℹ Please use `linewidth` instead.
This warning is displayed once every 8 hours.
Call `lifecycle::last_lifecycle_warnings()` to see where this warning was generated.

Evaluation

RMSE

sort(apply(X = prediction[,-c(1,2)], MARGIN = 2, FUN = rmse, actual = prediction$actual))
Prophet2   ARIMAX       LM    ARIMA  NNETAR2  Prophet   NNETAR 
10.58774 12.36074 12.78291 13.31192 13.82411 16.01882 21.33545 

MAPE

sort(apply(X = prediction[,-c(1,2)], MARGIN = 2, FUN = mape, actual = prediction$actual))
  Prophet2     ARIMAX      ARIMA         LM    Prophet    NNETAR2     NNETAR 
0.07253363 0.07927125 0.08764947 0.09318489 0.10055044 0.10085085 0.14022036 

sMAPE

sort(apply(X = prediction[,-c(1,2)], MARGIN = 2, FUN = smape, actual = prediction$actual))
  Prophet2     ARIMAX      ARIMA         LM    NNETAR2    Prophet     NNETAR 
0.07089585 0.07606659 0.08267374 0.08474103 0.09000829 0.10201565 0.13480095 
LS0tCnRpdGxlOiAiRm9yZWNhc3Rpbmcgd2l0aCBNYWNoaW5lIExlYXJuaW5nIgpvdXRwdXQ6CiAgaHRtbF9ub3RlYm9vazoKICAgIHRvYzogdHJ1ZQogICAgdG9jX2Zsb2F0OgogICAgICB0b2NfY29sbGFwc2VkOiB0cnVlCi0tLQoKYGBge3IgZWNobz1UUlVFLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQpsaWJyYXJ5KHRpZHl2ZXJzZSkKbGlicmFyeShmb3JlY2FzdCkKbGlicmFyeShncmlkRXh0cmEpCmxpYnJhcnkoTWV0cmljcykKbGlicmFyeSh0dlJlZykKbGlicmFyeSh0c2liYmxlKQpsaWJyYXJ5KGZhYmxlKQpsaWJyYXJ5KGZhYmxlLnByb3BoZXQpCmxpYnJhcnkoaG1zKQpsaWJyYXJ5KGx1YnJpZGF0ZSkKYGBgCgojIyBMb2FkIGRhdGFzZXQKCmBgYHtyfQp1cmxfbGluayA9ICJodHRwczovL2dpc3QuZ2l0aHViLmNvbS9ub3ZyaXN1aGVybWkvODZkODhiNWQ4MmNlYTM3MDA3OTc5OTIxYzM4ZmMyMDcvcmF3LzAzZGVkMmE5NGQ0OGFhNzdkZDE4ZDM3YjExNTc0ODAxYWFhNjIzNjQvZGF0YTIuY3N2IgpkYXRhIDwtIHJlYWRfY3N2KHVybF9saW5rKSAlPiUgbXV0YXRlKHRpbWU9aG1zOjphc19obXModHMpLCBkYXk9ZGF5KHRzKSkKYGBgCgoKYGBge3J9CmhlYWQoZGF0YSkKYGBgCgoKYGBge3J9CnRhaWwoZGF0YSkKYGBgCgpgYGB7cn0KdHJhaW4gICAgPC0gZGF0YSAlPiUgZmlsdGVyKGRheSE9MjUpCnRlc3QgICAgIDwtIGRhdGEgJT4lIGZpbHRlcihkYXk9PTI1KQpkYXRhLnRzICA8LSBkYXRhICU+JSBzZWxlY3QodHMsb2NjdXBhbmN5LHJhdGUpICU+JSBhc190c2liYmxlKGluZGV4ID0gdHMpCnRyYWluLnRzIDwtIHRyYWluICU+JSBzZWxlY3QodHMsb2NjdXBhbmN5LHJhdGUpICU+JSBhc190c2liYmxlKGluZGV4ID0gdHMpCnRlc3QudHMgIDwtIHRlc3QgJT4lIHNlbGVjdCh0cyxvY2N1cGFuY3kscmF0ZSkgJT4lIGFzX3RzaWJibGUoaW5kZXggPSB0cykKYGBgCgoKIyMgTW9kZWxpbmcKCiMjIyBUaW1lIHNlcmllcyBkYXRhCmBgYHtyfQp5IDwtIHRzKGRhdGEgPSB0cmFpbiRyYXRlLCBmcmVxdWVuY3kgPSAxNDQpCnggPC0gdHMoZGF0YSA9IHRyYWluJG9jY3VwYW5jeSwgZnJlcXVlbmN5ID0gMTQ0KQphdXRvcGxvdCh5KSArIHhsYWIoIiIpICsgeWxhYigiRW5lcmd5IGNvbnN1bXB0aW9uIChrV2gpIikKYGBgCgojIyMgTGluZWFyIFJlZ3Jlc3Npb24KYGBge3J9Cm0gPC0gbGlzdCgpCm1bWyJMTSJdXSA8LSB0cmFpbi50cyAlPiUgbW9kZWwobG09VFNMTShyYXRlfmxvZyhvY2N1cGFuY3kpKSkKYGBgCgoKYGBge3J9Cm1bWyJMTSJdXSAlPiUgZm9yZWNhc3QodGVzdC50cykgJT4lIGF1dG9wbG90KCkKYGBgCgoKIyMjIEFSSU1BCmBgYHtyfQptW1siQVJJTUEiXV0gPC0gYXV0by5hcmltYSh5KQpzdW1tYXJ5KG1bWyJBUklNQSJdXSkKYGBgCgpgYGB7cn0KbVtbIkFSSU1BIl1dICU+JSBmb3JlY2FzdDo6Zm9yZWNhc3QoaD0xNDQpICU+JSBhdXRvcGxvdCgpCmBgYAoKCiMjIyBBUklNQVgKYGBge3J9Cm1bWyJBUklNQVgiXV0gPC0gYXV0by5hcmltYSh5LCB4cmVnID0geCkKc3VtbWFyeShtW1siQVJJTUFYIl1dKQpgYGAKCgpgYGB7cn0KbVtbIkFSSU1BWCJdXSAlPiUgZm9yZWNhc3Q6OmZvcmVjYXN0KGg9MTQ0LCB4cmVnPXRlc3Qkb2NjdXBhbmN5KSAlPiUgYXV0b3Bsb3QoKQpgYGAKCiMjIyBQcm9waGV0IEZvcmVjYXN0IAoKYGBge3J9Cm1bWyJQcm9waGV0Il1dIDwtIHRyYWluLnRzICU+JSBtb2RlbChwcm9waGV0ID0gcHJvcGhldChyYXRlIH4gZ3Jvd3RoKCJsaW5lYXIiKSArIHNlYXNvbigiZGF5IiwgdHlwZSA9ICJtdWx0aXBsaWNhdGl2ZSIpKSkKCmNvbXBvbmVudHMobVtbIlByb3BoZXQiXV0pICU+JSBhdXRvcGxvdCgpCmBgYAoKYGBge3J9Cm1bWyJQcm9waGV0Il1dICU+JSBmb3JlY2FzdCh0ZXN0LnRzKSAlPiUgYXV0b3Bsb3QoKQpgYGAKCmBgYHtyfQpjb21wb25lbnRzKG1bWyJQcm9waGV0Il1dKQpgYGAKCgojIyMgUHJvcGhldCBGb3JlY2FzdCB3aXRoIGNvdmFyaWF0ZQoKYGBge3J9Cm1bWyJQcm9waGV0MiJdXSA8LSB0cmFpbi50cyAlPiUgbW9kZWwocHJvcGhldCA9IHByb3BoZXQocmF0ZSB+IGdyb3d0aCgibGluZWFyIikgKyBzZWFzb24oImRheSIsIHR5cGUgPSAibXVsdGlwbGljYXRpdmUiKSArIG9jY3VwYW5jeSkpCgpjb21wb25lbnRzKG1bWyJQcm9waGV0MiJdXSkgJT4lIGF1dG9wbG90KCkKYGBgCgpgYGB7cn0KbVtbIlByb3BoZXQyIl1dICU+JSBmb3JlY2FzdCh0ZXN0LnRzKSAlPiUgYXV0b3Bsb3QoKQpgYGAKCmBgYHtyfQpjb21wb25lbnRzKG1bWyJQcm9waGV0MiJdXSkKYGBgCgojIyMgTk5FVEFSIAoKYGBge3J9Cm1bWyJOTkVUQVIiXV0gPC0gbm5ldGFyKHksIHNpemU9MjAsIGxhbWJkYT0iYXV0byIpCm1bWyJOTkVUQVIiXV0KYGBgCgoKYGBge3J9Cm1bWyJOTkVUQVIiXV0gJT4lIGZvcmVjYXN0Ojpmb3JlY2FzdChoPTE0NCwgUEk9VFJVRSkgJT4lIGF1dG9wbG90KCkKYGBgCgoKIyMjIE5ORVRBUiB3aXRoIGNvdmFyaWF0ZQoKYGBge3J9Cm1bWyJOTkVUQVIyIl1dIDwtIG5uZXRhcih5LCBzaXplPTIwLCB4cmVnPXgsIGxhbWJkYT0iYXV0byIpCm1bWyJOTkVUQVIyIl1dCmBgYAoKCmBgYHtyfQptW1siTk5FVEFSMiJdXSAlPiUgZm9yZWNhc3Q6OmZvcmVjYXN0KHhyZWc9dGVzdCRvY2N1cGFuY3ksIFBJPVRSVUUpICU+JSBhdXRvcGxvdCgpCmBgYAoKCgoKIyMgRm9yZWNhc3RpbmcgYW5kIEV2YWx1YXRpb24KCiMjIyBGb3JlY2FzdGluZwpgYGB7cn0KcHJlZGljdGlvbiA8LSB0ZXN0ICU+JSBzZWxlY3QodHMsIHJhdGUpICU+JSByZW5hbWUoYWN0dWFsID0gcmF0ZSwgdGltZSA9IHRzKQpuX3Rlc3QgPC0gZGltKHByZWRpY3Rpb24pWzFdCnByZWRpY3Rpb25bJ0xNJ10gPC0gKG1bWyJMTSJdXSAlPiUgZm9yZWNhc3QodGVzdC50cykpJC5tZWFuCnByZWRpY3Rpb25bJ0FSSU1BJ10gPC0gKG1bWyJBUklNQSJdXSAlPiUgZm9yZWNhc3Q6OmZvcmVjYXN0KGg9MTQ0KSkkbWVhbgpwcmVkaWN0aW9uWydBUklNQVgnXSA8LSAobVtbIkFSSU1BWCJdXSAlPiUgZm9yZWNhc3Q6OmZvcmVjYXN0KGg9MTQ0LCB4cmVnPXRlc3Qkb2NjdXBhbmN5KSkkbWVhbgpwcmVkaWN0aW9uWydQcm9waGV0J10gPC0gKG1bWyJQcm9waGV0Il1dICU+JSBmb3JlY2FzdCh0ZXN0LnRzKSkkLm1lYW4KcHJlZGljdGlvblsnUHJvcGhldDInXSA8LSAobVtbIlByb3BoZXQyIl1dICU+JSBmb3JlY2FzdCh0ZXN0LnRzKSkkLm1lYW4KcHJlZGljdGlvblsnTk5FVEFSJ10gPC0gKG1bWyJOTkVUQVIiXV0gJT4lIGZvcmVjYXN0Ojpmb3JlY2FzdChoPTE0NCkpJG1lYW4KcHJlZGljdGlvblsnTk5FVEFSMiddIDwtIChtW1siTk5FVEFSMiJdXSAlPiUgZm9yZWNhc3Q6OmZvcmVjYXN0KHhyZWc9dGVzdCRvY2N1cGFuY3kpKSRtZWFuCmBgYAoKCmBgYHtyfQpoZWFkKHByZWRpY3Rpb24pCmBgYAoKYGBge3J9CnBsb3RGb3JlY2FzdCA8LSBmdW5jdGlvbihkYXRhKXsKICBwMSA8LSBnZ3Bsb3QoZGF0YSA9IGRhdGEpICsgCiAgICAgICAgZ2VvbV9saW5lKGNvbG9yID0gInJlZCIsIGFlcyh4ID0gdGltZSwgeSA9IGFjdHVhbCksIHNpemUgPSAwLjUsIGxpbmV0eXBlID0gMikgKwogICAgICAgIGdlb21fbGluZShjb2xvciA9ICJibGFjayIsIGFlcyh4ID0gdGltZSwgeSA9IExNKSkgKyAKICAgICAgICB4bGFiKCIiKSArIHlsYWIoIiIpICsgZ2d0aXRsZSgiTGluZWFyIE1vZGVsIikgKyBzY2FsZV94X2RhdGV0aW1lKGRhdGVfbGFiZWxzID0gIiVIOiVNIikgCgogIHAyIDwtIGdncGxvdChkYXRhID0gZGF0YSkgKyAKICAgICAgICBnZW9tX2xpbmUoY29sb3IgPSAicmVkIiwgYWVzKHggPSB0aW1lLCB5ID0gYWN0dWFsKSwgc2l6ZSA9IDAuNSwgbGluZXR5cGUgPSAyKSArCiAgICAgICAgZ2VvbV9saW5lKGNvbG9yID0gImJsYWNrIiwgYWVzKHggPSB0aW1lLCB5ID0gQVJJTUEpKSArCiAgICAgICAgeGxhYigiIikgKyB5bGFiKCIiKSArIGdndGl0bGUoIkFSSU1BIikgKyBzY2FsZV94X2RhdGV0aW1lKGRhdGVfbGFiZWxzID0gIiVIOiVNIikgCiAgCiAgcDMgPC0gZ2dwbG90KGRhdGEgPSBkYXRhKSArIAogICAgICAgIGdlb21fbGluZShjb2xvciA9ICJyZWQiLCBhZXMoeCA9IHRpbWUsIHkgPSBhY3R1YWwpLCBzaXplID0gMC41LCBsaW5ldHlwZSA9IDIpICsKICAgICAgICBnZW9tX2xpbmUoY29sb3IgPSAiYmxhY2siLCBhZXMoeCA9IHRpbWUsIHkgPSBBUklNQVgpKSArCiAgICAgICAgeGxhYigiIikgKyB5bGFiKCIiKSArIGdndGl0bGUoIkFSSU1BWCIpICsgc2NhbGVfeF9kYXRldGltZShkYXRlX2xhYmVscyA9ICIlSDolTSIpIAogIAogIHA0IDwtIGdncGxvdChkYXRhID0gZGF0YSkgKyAKICAgICAgICBnZW9tX2xpbmUoY29sb3IgPSAicmVkIiwgYWVzKHggPSB0aW1lLCB5ID0gYWN0dWFsKSwgc2l6ZSA9IDAuNSwgbGluZXR5cGUgPSAyKSArCiAgICAgICAgZ2VvbV9saW5lKGNvbG9yID0gImJsYWNrIiwgYWVzKHggPSB0aW1lLCB5ID0gUHJvcGhldCkpICsgCiAgICAgICAgeGxhYigiIikgKyB5bGFiKCIiKSArIGdndGl0bGUoIlByb3BoZXQiKSArIHNjYWxlX3hfZGF0ZXRpbWUoZGF0ZV9sYWJlbHMgPSAiJUg6JU0iKSAKICAKICBwNSA8LSBnZ3Bsb3QoZGF0YSA9IGRhdGEpICsgCiAgICAgICAgZ2VvbV9saW5lKGNvbG9yID0gInJlZCIsIGFlcyh4ID0gdGltZSwgeSA9IGFjdHVhbCksIHNpemUgPSAwLjUsIGxpbmV0eXBlID0gMikgKwogICAgICAgIGdlb21fbGluZShjb2xvciA9ICJibGFjayIsIGFlcyh4ID0gdGltZSwgeSA9IFByb3BoZXQyKSkgKyAKICAgICAgICB4bGFiKCIiKSArIHlsYWIoIiIpICsgZ2d0aXRsZSgiUHJvcGhldCB3aXRoIGNvdmFyaWF0ZSIpICsgc2NhbGVfeF9kYXRldGltZShkYXRlX2xhYmVscyA9ICIlSDolTSIpCiAgCiAgcDYgPC0gZ2dwbG90KGRhdGEgPSBkYXRhKSArIAogICAgICAgIGdlb21fbGluZShjb2xvciA9ICJyZWQiLCBhZXMoeCA9IHRpbWUsIHkgPSBhY3R1YWwpLCBzaXplID0gMC41LCBsaW5ldHlwZSA9IDIpICsKICAgICAgICBnZW9tX2xpbmUoY29sb3IgPSAiYmxhY2siLCBhZXMoeCA9IHRpbWUsIHkgPSBOTkVUQVIpKSArCiAgICAgICAgeGxhYigiIikgKyB5bGFiKCIiKSArIGdndGl0bGUoIk5OQVIiKSArIHNjYWxlX3hfZGF0ZXRpbWUoZGF0ZV9sYWJlbHMgPSAiJUg6JU0iKSAKICAKICBwNyA8LSBnZ3Bsb3QoZGF0YSA9IGRhdGEpICsgCiAgICAgICAgZ2VvbV9saW5lKGNvbG9yID0gInJlZCIsIGFlcyh4ID0gdGltZSwgeSA9IGFjdHVhbCksIHNpemUgPSAwLjUsIGxpbmV0eXBlID0gMikgKwogICAgICAgIGdlb21fbGluZShjb2xvciA9ICJibGFjayIsIGFlcyh4ID0gdGltZSwgeSA9IE5ORVRBUjIpKSArCiAgICAgICAgeGxhYigiIikgKyB5bGFiKCIiKSArIGdndGl0bGUoIk5OQVIgd2l0aCBjb3ZhcmlhdGUiKSArIHNjYWxlX3hfZGF0ZXRpbWUoZGF0ZV9sYWJlbHMgPSAiJUg6JU0iKSAKICAgCiAgICAgICAgCiAgZ3JpZC5hcnJhbmdlKHAxLHAyLHAzLHA0LHA1LHA2LHA3LG5yb3c9MykKfQpgYGAKCgoKCmBgYHtyfQpwbG90Rm9yZWNhc3QocHJlZGljdGlvbikKYGBgCgojIyMgRXZhbHVhdGlvbgoKIyMjIyBSTVNFCmBgYHtyfQpzb3J0KGFwcGx5KFggPSBwcmVkaWN0aW9uWywtYygxLDIpXSwgTUFSR0lOID0gMiwgRlVOID0gcm1zZSwgYWN0dWFsID0gcHJlZGljdGlvbiRhY3R1YWwpKQpgYGAKCiMjIyMgTUFQRQpgYGB7cn0Kc29ydChhcHBseShYID0gcHJlZGljdGlvblssLWMoMSwyKV0sIE1BUkdJTiA9IDIsIEZVTiA9IG1hcGUsIGFjdHVhbCA9IHByZWRpY3Rpb24kYWN0dWFsKSkKYGBgCgojIyMjIHNNQVBFCmBgYHtyfQpzb3J0KGFwcGx5KFggPSBwcmVkaWN0aW9uWywtYygxLDIpXSwgTUFSR0lOID0gMiwgRlVOID0gc21hcGUsIGFjdHVhbCA9IHByZWRpY3Rpb24kYWN0dWFsKSkKYGBgCgoKCg==