Author

library(data.table)
library(ggfortify) #autoplot
library(forecast) #autoplot, auto.arima

National Energy Board, Canada’s Energy Future 2016: Energy Supply and Demand Projections to 2040

National Energy Board, Canada’s Energy Future 2016: Energy Supply and Demand Projections to 2040

Electricity Generation.xlsx (Ontario table) -> NEB_generation.csv

Electricity Capacity.xlsx (Ontario table) -> NEB_capacity.csv

NEB Generation Projections (GWh)

NEB_generation <- transpose(read.csv("NEB_generation.csv", header = FALSE))

NEB_generation <- NEB_generation[-1,]

colnames(NEB_generation) <- c("Year","Hydro","Wind","Biomass_and_Geothermal","Solar","Uranium","Coal","Natural_Gas","Oil")

Start year is 2005

NEB_generation$Year <- NULL

NEB_generation$Hydro <- as.numeric(NEB_generation$Hydro)

NEB_generation$Wind <- as.numeric(NEB_generation$Wind)

NEB_generation$Biomass_and_Geothermal <- as.numeric(NEB_generation$Biomass_and_Geothermal)

NEB_generation$Solar <- as.numeric(NEB_generation$Solar)

NEB_generation$Uranium <- as.numeric(NEB_generation$Uranium)

NEB_generation$Coal <- as.numeric(NEB_generation$Coal)

NEB_generation$Natural_Gas <- as.numeric(NEB_generation$Natural_Gas)

NEB_generation$Oil <- as.numeric(NEB_generation$Oil)

NEB_generation$Total <- NEB_generation$Hydro+NEB_generation$Wind+NEB_generation$Biomass_and_Geothermal+NEB_generation$Solar+NEB_generation$Uranium+NEB_generation$Coal+NEB_generation$Natural_Gas+NEB_generation$Oil
NEB_generation.ts <- ts(NEB_generation, start = 2005, frequency = 1)

ggplot2::autoplot(NEB_generation.ts, ylab="GWh", main="Ontario Annual Electricity Generation Projections")

NEB Capacity Projections (MW)

NEB_capacity <- transpose(read.csv("NEB_capacity.csv", header = FALSE))

NEB_capacity <- NEB_capacity[-1,]

colnames(NEB_capacity) <- c("Year","Petroleum1","Petroleum2","Petroleum3","Coal", "Nuclear","Biomass_and_Geothermal","Solar","Wind","Hydro")

NEB_capacity$Year <- NULL

NEB_capacity$Petroleum <- as.numeric(NEB_capacity$Petroleum1) + as.numeric(NEB_capacity$Petroleum2) + as.numeric(NEB_capacity$Petroleum3)

NEB_capacity$Petroleum1 <- NULL

NEB_capacity$Petroleum2 <- NULL

NEB_capacity$Petroleum3 <- NULL

NEB_capacity$Coal <- as.numeric(NEB_capacity$Coal)

NEB_capacity$Nuclear <- as.numeric(NEB_capacity$Nuclear)

NEB_capacity$Biomass_and_Geothermal <- as.numeric(NEB_capacity$Biomass_and_Geothermal)

NEB_capacity$Solar <- as.numeric(NEB_capacity$Solar)

NEB_capacity$Wind <- as.numeric(NEB_capacity$Wind)

NEB_capacity$Hydro <- as.numeric(NEB_capacity$Hydro)

NEB_capacity$Total <- NEB_capacity$Petroleum+NEB_capacity$Coal+NEB_capacity$Nuclear+NEB_capacity$Biomass_and_Geothermal+NEB_capacity$Solar+NEB_capacity$Wind+NEB_capacity$Hydro
NEB_capacity.ts <- ts(NEB_capacity, start = 2005, frequency = 1)

ggplot2::autoplot(NEB_capacity.ts, ylab="MW", main="Ontario Annual Electricity Capacity Projections")

Monthly Electricity Supply and Disposition Survey (MELE), Ontario (MWh)

Statistics Canada, Monthly Electricity Supply and Disposition Survey (MELE)

Electric power generation, monthly generation by type of electricity. Table: 25-10-0015-01

MELE_generation <- read.csv("2510001501-noSymbol.csv")
MELE_generation$YEAR_MONTH <- NULL

MELE_generation.ts <- ts(MELE_generation, start = 2008, frequency = 12)

ggplot2::autoplot(MELE_generation.ts, ylab="MWh", main="Ontario Monthly Electricity Generation")

MELE_generation_total.ts <- ts(MELE_generation$Total, start = 2008, frequency = 12)

plot(MELE_generation_total.ts)

MELE_generation_total.ts.components <- decompose(MELE_generation_total.ts)

forecast::autoplot(MELE_generation_total.ts.components)

MELE_generation_total.ts.arima <- auto.arima(MELE_generation_total.ts)

MELE_generation_total.ts.arima
Series: MELE_generation_total.ts 
ARIMA(1,1,1)(2,1,0)[12] 

Coefficients:
         ar1      ma1     sar1     sar2
      0.6312  -0.9083  -0.6268  -0.3358
s.e.  0.1059   0.0604   0.0879   0.0850

sigma^2 estimated as 2.994e+11:  log likelihood=-1786.41
AIC=3582.82   AICc=3583.34   BIC=3596.84
MELE_generation_total.ts.arima.forecast <- forecast(MELE_generation_total.ts.arima, level = c(95), h = 120)

forecast::autoplot(MELE_generation_total.ts.arima.forecast)

IESO

Independent Electricity System Operator (IESO), Data Directory

Hourly Generator Energy Output and Capability Report

Hourly Generator Energy Output and Capability Report

The Hourly Generator Energy Output and Capability Report presents the energy output and capability for generating facilities in the IESO-administered energy market with a maximum output capability of 20 MW or more.

http://reports.ieso.ca/docrefs/helpfile/GenOutputCapability_h4.pdf

Output is the actual energy production of the unit or facility. The hourly output is the facility’s five-minute outputs averaged over an hour.

Capability is the maximum potential output of the unit or facility under current conditions, which includes maximum unit derates and outages for that hour. In this report, Capability is provided for nuclear, hydro, gas, and biofuel generation (excluding wind and solar).

GOC-2010.xlsx - GOC-2019-Jan-April.xlsx -> IESO_output_2010.csv, IESO_capability_2010.csv - IESO_output_2019.csv, IESO_capability_2019.csv

observation for each hour, 2010 to April 2019

Robert J Hyman, Seasonal periods. forecast::msts

IESO_output_2010 <- fread("IESO_output_2010.csv")

IESO_output_2010$DATE <- NULL

IESO_output_2010$HOUR <- NULL

IESO_output_2010$TOTAL <- rowSums(IESO_output_2010, na.rm=TRUE)

IESO_output_2010 <- IESO_output_2010[,.(TOTAL)]
IESO_output_2011 <- fread("IESO_output_2011.csv")

IESO_output_2011$DATE <- NULL

IESO_output_2011$HOUR <- NULL

IESO_output_2011$TOTAL <- rowSums(IESO_output_2011, na.rm=TRUE)

IESO_output_2011 <- IESO_output_2011[,.(TOTAL)]
IESO_output_2012 <- fread("IESO_output_2012.csv")

IESO_output_2012$DATE <- NULL

IESO_output_2012$HOUR <- NULL

IESO_output_2012$TOTAL <- rowSums(IESO_output_2012, na.rm=TRUE)

IESO_output_2012 <- IESO_output_2012[,.(TOTAL)]

IESO_output_2012.ts <- msts(IESO_output_2012$TOTAL, seasonal.periods = c(24, 24*365.25), start=2012)
forecast::autoplot(IESO_output_2012.ts)

2012 Outliers

which(IESO_output_2012$TOTAL==0)
[1] 3947 7834

3947: DATE 13-Jun-12, HOUR 11

7834: DATE 22-Nov-12, HOUR 10

IESO_output_2012$TOTAL[3947]
[1] 0
IESO_output_2012$TOTAL[7834]
[1] 0
IESO_output_2012$TOTAL[3947] <- IESO_output_2012$TOTAL[3946]

IESO_output_2012$TOTAL[7834] <- IESO_output_2012$TOTAL[7833]

IESO_output_2012.ts <- msts(IESO_output_2012$TOTAL, seasonal.periods = c(24, 24*365.25), start=2012)

autoplot(IESO_output_2012.ts)

IESO_output_2013 <- fread("IESO_output_2013.csv")

IESO_output_2013$DATE <- NULL

IESO_output_2013$HOUR <- NULL

IESO_output_2013$TOTAL <- rowSums(IESO_output_2013, na.rm=TRUE)

IESO_output_2013 <- IESO_output_2013[,.(TOTAL)]
IESO_output_2014 <- fread("IESO_output_2014.csv")

IESO_output_2014$DATE <- NULL

IESO_output_2014$HOUR <- NULL

IESO_output_2014$TOTAL <- rowSums(IESO_output_2014, na.rm=TRUE)

IESO_output_2014 <- IESO_output_2014[,.(TOTAL)]
IESO_output_2015 <- fread("IESO_output_2015.csv")

IESO_output_2015 <- IESO_output_2015[,.(TOTAL)]
IESO_output_2016 <- fread("IESO_output_2016.csv")

IESO_output_2016 <- IESO_output_2016[,.(TOTAL)]

IESO_output_2016.ts <- msts(IESO_output_2015$TOTAL, seasonal.periods = c(24, 24*365.25), start=2016)
forecast::autoplot(IESO_output_2016.ts)

2016 Outliers

Autoregressive replacement of outlier values

for (t in which(IESO_output_2016$TOTAL<4000)){
  IESO_output_2016$TOTAL[t] <- IESO_output_2016$TOTAL[t-1] 
}
IESO_output_2017 <- fread("IESO_output_2017.csv")

IESO_output_2017 <- IESO_output_2017[,.(TOTAL)]
IESO_output_2018 <- fread("IESO_output_2018.csv")

IESO_output_2018 <- IESO_output_2018[,.(TOTAL)]
IESO_output_2019 <- fread("IESO_output_2019.csv")

IESO_output_2019$DATE <- NULL

IESO_output_2019$HOUR <- NULL

IESO_output_2019$TOTAL <- rowSums(IESO_output_2019, na.rm=TRUE)

IESO_output_2019 <- IESO_output_2019[,.(TOTAL)]
IESO_output_2010_to_2019 <- do.call("rbind",list(IESO_output_2010,IESO_output_2011,IESO_output_2012,
                                           IESO_output_2013, IESO_output_2014, IESO_output_2015,
                                           IESO_output_2016, IESO_output_2017, IESO_output_2018,
                                           IESO_output_2019))
IESO_output_2010_to_2019.ts <- msts(IESO_output_2010_to_2019$TOTAL, seasonal.periods = c(24, 168, 8766), start=2010)
forecast::autoplot(IESO_output_2010_to_2019.ts)

IESO_output_2010_to_2019.ts.components <- mstl(IESO_output_2010_to_2019.ts)

forecast::autoplot(IESO_output_2010_to_2019.ts.components)

IESO_output_2010_to_2019.24.ts <- IESO_output_2010_to_2019.ts.components[, "Seasonal24"]

IESO_output_2010_to_2019.168.ts <- IESO_output_2010_to_2019.ts.components[, "Seasonal168"]

IESO_output_2010_to_2019.8766.ts <- IESO_output_2010_to_2019.ts.components[, "Seasonal8766"]

autoplot(subset(IESO_output_2010_to_2019.24.ts, end = 24*7*4))

autoplot(subset(IESO_output_2010_to_2019.168.ts, end = 24*7*4))

autoplot(subset(IESO_output_2010_to_2019.8766.ts, end = 24*7*52))

Realtime Constrained Totals Report (Ontario and Market Demand)

http://reports.ieso.ca/docrefs/helpfile/RealtimeConstTotals_h2.pdf

TOTAL ENERGY: Total energy dispatched into the IESO-controlled grid, calculated as Ontario generation plus imports

TOTAL LOSS: Total losses in the IESO-controlled grid, calculated by the load flow

TOTAL LOAD: Total system load, calculated as Total Energy - Total Loss

TOTAL DISP LOAD: Total MW withdrawn from the IESO-controlled grid by dispatchable load, where the value represents the system-wide amount of dispatchable load that was dispatched down. For example, if the load is bidding 100 MW and gets dispatched down to 90 MW, then the Total Disp Load quantity is 10 MW

ONTARIO DEMAND: Total Ontario electricity demand, calculated as:

Total Energy + Total Generation Without Offers - Total Exports + Total Off Market +/- Over/Under Generation

Hourly Demand Report

PUB_Demand_2002.csv - PUB_Demand_2019.csv (to July)

Demand_2010 <- fread("PUB_Demand_2010.csv")

Demand_2010 <- Demand_2010[,.(DEMAND = `Market Demand`)]
Demand_2011 <- fread("PUB_Demand_2011.csv")

Demand_2011 <- Demand_2011[,.(DEMAND = `Market Demand`)]
Demand_2012 <- fread("PUB_Demand_2012.csv")

Demand_2012 <- Demand_2012[,.(DEMAND = `Market Demand`)]
Demand_2013 <- fread("PUB_Demand_2013.csv")

Demand_2013 <- Demand_2013[,.(DEMAND = `Market Demand`)]
Demand_2014 <- fread("PUB_Demand_2014.csv")

Demand_2014 <- Demand_2014[,.(DEMAND = `Market Demand`)]
Demand_2015 <- fread("PUB_Demand_2015.csv")

Demand_2015 <- Demand_2015[,.(DEMAND = `Market Demand`)]
Demand_2016 <- fread("PUB_Demand_2016.csv")

Demand_2016 <- Demand_2016[,.(DEMAND = `Market Demand`)]
Demand_2017 <- fread("PUB_Demand_2017.csv")

Demand_2017 <- Demand_2017[,.(DEMAND = `Market Demand`)]
Demand_2018 <- fread("PUB_Demand_2018.csv")

Demand_2018 <- Demand_2018[,.(DEMAND = `Market Demand`)]
Demand_2019 <- fread("PUB_Demand_2019.csv")

Demand_2019 <- Demand_2019[,.(DEMAND = `Market Demand`)]
Demand_2010_to_2019 <- do.call("rbind",list(Demand_2010,Demand_2011,Demand_2012,
                                           Demand_2013, Demand_2014, Demand_2015,
                                           Demand_2016, Demand_2017, Demand_2018,
                                           Demand_2019))
Demand_2010_to_2019.ts <- msts(Demand_2010_to_2019$DEMAND, seasonal.periods = c(24, 168, 8766), start=2010)
Demand_2010_to_2019.ts.components <- mstl(Demand_2010_to_2019.ts)

forecast::autoplot(Demand_2010_to_2019.ts.components)

attributes(Demand_2010_to_2019.ts.components)
$dim
[1] 83496     6

$dimnames
$dimnames[[1]]
NULL

$dimnames[[2]]
[1] "Data"         "Trend"        "Seasonal24"   "Seasonal168"  "Seasonal8766" "Remainder"   


$tsp
[1] 2010.000 2019.525 8766.000

$class
[1] "mstl" "mts"  "msts" "ts"  

$seasonal.periods
[1]   24  168 8766
Demand_2010_to_2019.24.ts <- Demand_2010_to_2019.ts.components[, "Seasonal24"]

Demand_2010_to_2019.168.ts <- Demand_2010_to_2019.ts.components[, "Seasonal168"]

Demand_2010_to_2019.8766.ts <- Demand_2010_to_2019.ts.components[, "Seasonal8766"]

class(Demand_2010_to_2019.8766.ts)
[1] "msts" "ts"  
autoplot(subset(Demand_2010_to_2019.Seasonal24.ts, end = 24*7*4))
Error in subset(Demand_2010_to_2019.Seasonal24.ts, end = 24 * 7 * 4) : 
  object 'Demand_2010_to_2019.Seasonal24.ts' not found
autoplot(subset(Demand_2010_to_2019.168.ts, end = 24*7*4))

autoplot(subset(Demand_2010_to_2019.8766.ts, end = 24*7*365))

Hourly Ontario Energy Price (HOEP)

Yearly Hourly HOEP OR Predispatch Report

PUB_PriceHOEPPredispOR_2002.csv - PUB_PriceHOEPPredispOR_2019.csv (to July)

HOEP_2010 <- fread("PUB_PriceHOEPPredispOR_2010.csv")

HOEP_2010 <- HOEP_2010[,.(HOEP)]
HOEP_2011 <- fread("PUB_PriceHOEPPredispOR_2011.csv")

HOEP_2011 <- HOEP_2011[,.(HOEP)]
HOEP_2012 <- fread("PUB_PriceHOEPPredispOR_2012.csv")

HOEP_2012 <- HOEP_2012[,.(HOEP)]
HOEP_2013 <- fread("PUB_PriceHOEPPredispOR_2013.csv")

HOEP_2013 <- HOEP_2013[,.(HOEP)]
HOEP_2014 <- fread("PUB_PriceHOEPPredispOR_2014.csv")

HOEP_2014 <- HOEP_2014[,.(HOEP)]
HOEP_2015 <- fread("PUB_PriceHOEPPredispOR_2015.csv")

HOEP_2015 <- HOEP_2015[,.(HOEP)]
HOEP_2016 <- fread("PUB_PriceHOEPPredispOR_2016.csv")

HOEP_2016 <- HOEP_2016[,.(HOEP)]
HOEP_2017 <- fread("PUB_PriceHOEPPredispOR_2017.csv")

HOEP_2017 <- HOEP_2017[,.(HOEP)]
HOEP_2018 <- fread("PUB_PriceHOEPPredispOR_2018.csv")

HOEP_2018 <- HOEP_2018[,.(HOEP)]
HOEP_2018.ts <- ts(HOEP_2018$HOEP, frequency = 24)

HOEP_2018.ts.components <- decompose(HOEP_2018.ts)

forecast::autoplot(HOEP_2018.ts.components)

autoplot(subset(HOEP_2018.ts.components$seasonal, end = 24*7*4))

HOEP_2019 <- fread("PUB_PriceHOEPPredispOR_2019.csv")

HOEP_2019 <- HOEP_2019[,.(HOEP)]
HOEP_2010_to_2019 <- do.call("rbind",list(HOEP_2010,HOEP_2011,HOEP_2012,
                                           HOEP_2013, HOEP_2014, HOEP_2015,
                                           HOEP_2016, HOEP_2017, HOEP_2018,
                                           HOEP_2019))
HOEP_2010_to_2019.ts <- msts(HOEP_2010_to_2019$HOEP, seasonal.periods = c(24, 168, 8766), start=2010)
autoplot(HOEP_2010_to_2019.ts)

HOEP_2010_to_2019.ts.components <- mstl(HOEP_2010_to_2019.ts)

forecast::autoplot(HOEP_2010_to_2019.ts.components)

HOEP_2010_to_2019.24.ts <- HOEP_2010_to_2019.ts.components[, "Seasonal24"]

HOEP_2010_to_2019.168.ts <- HOEP_2010_to_2019.ts.components[, "Seasonal168"]

HOEP_2010_to_2019.8766.ts <- HOEP_2010_to_2019.ts.components[, "Seasonal8766"]

autoplot(subset(HOEP_2010_to_2019.24.ts, end = 24*7*4))

autoplot(subset(HOEP_2010_to_2019.168.ts, end = 24*7*4))

autoplot(subset(HOEP_2010_to_2019.8766.ts, end = 24*7*52))

autoplot(subset(HOEP_2010_to_2019.ts.components[,"Seasonal24"], end = 24*7*4))

U.S. Energy Information Administration (EIA): State of New York

U.S. Energy Information Administration (EIA)

Average retail price of electricity : New York : all sectors : monthly. Cents per kWh

EIA_NY <- fread("EIA_NY.csv")
EIA_NY <- EIA_NY[nrow(EIA_NY):1,]

EIA_NY <- EIA_NY[, .(Month, Cents_per_kWh = Average_retail_price_electricity_monthly_cents_per_kWh)]

head(EIA_NY)
EIA_NY.ts <- ts(EIA_NY$Cents_per_kWh, frequency = 12, start = 2001)

EIA_NY.ts.components <- decompose(EIA_NY.ts)

forecast::autoplot(EIA_NY.ts.components)

LS0tDQp0aXRsZTogIk9udGFyaW8gRWxlY3RyaWNpdHkgR2VuZXJhdGlvbiwgRGVtYW5kLCBhbmQgUHJpY2UgVGltZXNlcmllcyINCm91dHB1dDogDQogIGh0bWxfbm90ZWJvb2s6IA0KICAgIHRvYzogeWVzDQotLS0NCg0KIyBBdXRob3INCg0KKiBKb3JkYW4gQmVsbA0KKiBKdWx5IDIzLCAyMDE5DQoqIDxodHRwczovL2pvcmRhbmJlbGwyMzU3LmdpdGh1Yi5pby9JRVNPLm5iLmh0bWw+DQoNCmBgYHtyfQ0KbGlicmFyeShkYXRhLnRhYmxlKQ0KbGlicmFyeShnZ2ZvcnRpZnkpICNhdXRvcGxvdA0KbGlicmFyeShmb3JlY2FzdCkgI2F1dG9wbG90LCBhdXRvLmFyaW1hDQpgYGANCg0KIyBOYXRpb25hbCBFbmVyZ3kgQm9hcmQsIENhbmFkYSdzIEVuZXJneSBGdXR1cmUgMjAxNjogRW5lcmd5IFN1cHBseSBhbmQgRGVtYW5kIFByb2plY3Rpb25zIHRvIDIwNDANCg0KTmF0aW9uYWwgRW5lcmd5IEJvYXJkLCBbQ2FuYWRh4oCZcyBFbmVyZ3kgRnV0dXJlIDIwMTY6IEVuZXJneSBTdXBwbHkgYW5kIERlbWFuZCBQcm9qZWN0aW9ucyB0byAyMDQwXShodHRwczovL2FwcHMubmViLW9uZS5nYy5jYS9mdHJwcG5kYzQvZGZsdC5hc3B4P0dvQ1RlbXBsYXRlQ3VsdHVyZT1lbi1DQSkNCg0KRWxlY3RyaWNpdHkgR2VuZXJhdGlvbi54bHN4IChPbnRhcmlvIHRhYmxlKSAtPiBORUJfZ2VuZXJhdGlvbi5jc3YNCg0KRWxlY3RyaWNpdHkgQ2FwYWNpdHkueGxzeCAoT250YXJpbyB0YWJsZSkgLT4gTkVCX2NhcGFjaXR5LmNzdg0KDQojIyBORUIgR2VuZXJhdGlvbiBQcm9qZWN0aW9ucyAoR1doKQ0KDQpgYGB7cn0NCk5FQl9nZW5lcmF0aW9uIDwtIHRyYW5zcG9zZShyZWFkLmNzdigiTkVCX2dlbmVyYXRpb24uY3N2IiwgaGVhZGVyID0gRkFMU0UpKQ0KDQpORUJfZ2VuZXJhdGlvbiA8LSBORUJfZ2VuZXJhdGlvblstMSxdDQoNCmNvbG5hbWVzKE5FQl9nZW5lcmF0aW9uKSA8LSBjKCJZZWFyIiwiSHlkcm8iLCJXaW5kIiwiQmlvbWFzc19hbmRfR2VvdGhlcm1hbCIsIlNvbGFyIiwiVXJhbml1bSIsIkNvYWwiLCJOYXR1cmFsX0dhcyIsIk9pbCIpDQpgYGANCg0KU3RhcnQgeWVhciBpcyAyMDA1DQoNCmBgYHtyfQ0KTkVCX2dlbmVyYXRpb24kWWVhciA8LSBOVUxMDQoNCk5FQl9nZW5lcmF0aW9uJEh5ZHJvIDwtIGFzLm51bWVyaWMoTkVCX2dlbmVyYXRpb24kSHlkcm8pDQoNCk5FQl9nZW5lcmF0aW9uJFdpbmQgPC0gYXMubnVtZXJpYyhORUJfZ2VuZXJhdGlvbiRXaW5kKQ0KDQpORUJfZ2VuZXJhdGlvbiRCaW9tYXNzX2FuZF9HZW90aGVybWFsIDwtIGFzLm51bWVyaWMoTkVCX2dlbmVyYXRpb24kQmlvbWFzc19hbmRfR2VvdGhlcm1hbCkNCg0KTkVCX2dlbmVyYXRpb24kU29sYXIgPC0gYXMubnVtZXJpYyhORUJfZ2VuZXJhdGlvbiRTb2xhcikNCg0KTkVCX2dlbmVyYXRpb24kVXJhbml1bSA8LSBhcy5udW1lcmljKE5FQl9nZW5lcmF0aW9uJFVyYW5pdW0pDQoNCk5FQl9nZW5lcmF0aW9uJENvYWwgPC0gYXMubnVtZXJpYyhORUJfZ2VuZXJhdGlvbiRDb2FsKQ0KDQpORUJfZ2VuZXJhdGlvbiROYXR1cmFsX0dhcyA8LSBhcy5udW1lcmljKE5FQl9nZW5lcmF0aW9uJE5hdHVyYWxfR2FzKQ0KDQpORUJfZ2VuZXJhdGlvbiRPaWwgPC0gYXMubnVtZXJpYyhORUJfZ2VuZXJhdGlvbiRPaWwpDQoNCk5FQl9nZW5lcmF0aW9uJFRvdGFsIDwtIE5FQl9nZW5lcmF0aW9uJEh5ZHJvK05FQl9nZW5lcmF0aW9uJFdpbmQrTkVCX2dlbmVyYXRpb24kQmlvbWFzc19hbmRfR2VvdGhlcm1hbCtORUJfZ2VuZXJhdGlvbiRTb2xhcitORUJfZ2VuZXJhdGlvbiRVcmFuaXVtK05FQl9nZW5lcmF0aW9uJENvYWwrTkVCX2dlbmVyYXRpb24kTmF0dXJhbF9HYXMrTkVCX2dlbmVyYXRpb24kT2lsDQpgYGANCg0KYGBge3J9DQpORUJfZ2VuZXJhdGlvbi50cyA8LSB0cyhORUJfZ2VuZXJhdGlvbiwgc3RhcnQgPSAyMDA1LCBmcmVxdWVuY3kgPSAxKQ0KDQpnZ3Bsb3QyOjphdXRvcGxvdChORUJfZ2VuZXJhdGlvbi50cywgeWxhYj0iR1doIiwgbWFpbj0iT250YXJpbyBBbm51YWwgRWxlY3RyaWNpdHkgR2VuZXJhdGlvbiBQcm9qZWN0aW9ucyIpDQpgYGANCg0KIyMgTkVCIENhcGFjaXR5IFByb2plY3Rpb25zIChNVykNCg0KYGBge3J9DQpORUJfY2FwYWNpdHkgPC0gdHJhbnNwb3NlKHJlYWQuY3N2KCJORUJfY2FwYWNpdHkuY3N2IiwgaGVhZGVyID0gRkFMU0UpKQ0KDQpORUJfY2FwYWNpdHkgPC0gTkVCX2NhcGFjaXR5Wy0xLF0NCg0KY29sbmFtZXMoTkVCX2NhcGFjaXR5KSA8LSBjKCJZZWFyIiwiUGV0cm9sZXVtMSIsIlBldHJvbGV1bTIiLCJQZXRyb2xldW0zIiwiQ29hbCIsICJOdWNsZWFyIiwiQmlvbWFzc19hbmRfR2VvdGhlcm1hbCIsIlNvbGFyIiwiV2luZCIsIkh5ZHJvIikNCg0KTkVCX2NhcGFjaXR5JFllYXIgPC0gTlVMTA0KDQpORUJfY2FwYWNpdHkkUGV0cm9sZXVtIDwtIGFzLm51bWVyaWMoTkVCX2NhcGFjaXR5JFBldHJvbGV1bTEpICsgYXMubnVtZXJpYyhORUJfY2FwYWNpdHkkUGV0cm9sZXVtMikgKyBhcy5udW1lcmljKE5FQl9jYXBhY2l0eSRQZXRyb2xldW0zKQ0KDQpORUJfY2FwYWNpdHkkUGV0cm9sZXVtMSA8LSBOVUxMDQoNCk5FQl9jYXBhY2l0eSRQZXRyb2xldW0yIDwtIE5VTEwNCg0KTkVCX2NhcGFjaXR5JFBldHJvbGV1bTMgPC0gTlVMTA0KDQpORUJfY2FwYWNpdHkkQ29hbCA8LSBhcy5udW1lcmljKE5FQl9jYXBhY2l0eSRDb2FsKQ0KDQpORUJfY2FwYWNpdHkkTnVjbGVhciA8LSBhcy5udW1lcmljKE5FQl9jYXBhY2l0eSROdWNsZWFyKQ0KDQpORUJfY2FwYWNpdHkkQmlvbWFzc19hbmRfR2VvdGhlcm1hbCA8LSBhcy5udW1lcmljKE5FQl9jYXBhY2l0eSRCaW9tYXNzX2FuZF9HZW90aGVybWFsKQ0KDQpORUJfY2FwYWNpdHkkU29sYXIgPC0gYXMubnVtZXJpYyhORUJfY2FwYWNpdHkkU29sYXIpDQoNCk5FQl9jYXBhY2l0eSRXaW5kIDwtIGFzLm51bWVyaWMoTkVCX2NhcGFjaXR5JFdpbmQpDQoNCk5FQl9jYXBhY2l0eSRIeWRybyA8LSBhcy5udW1lcmljKE5FQl9jYXBhY2l0eSRIeWRybykNCg0KTkVCX2NhcGFjaXR5JFRvdGFsIDwtIE5FQl9jYXBhY2l0eSRQZXRyb2xldW0rTkVCX2NhcGFjaXR5JENvYWwrTkVCX2NhcGFjaXR5JE51Y2xlYXIrTkVCX2NhcGFjaXR5JEJpb21hc3NfYW5kX0dlb3RoZXJtYWwrTkVCX2NhcGFjaXR5JFNvbGFyK05FQl9jYXBhY2l0eSRXaW5kK05FQl9jYXBhY2l0eSRIeWRybw0KYGBgDQoNCmBgYHtyfQ0KTkVCX2NhcGFjaXR5LnRzIDwtIHRzKE5FQl9jYXBhY2l0eSwgc3RhcnQgPSAyMDA1LCBmcmVxdWVuY3kgPSAxKQ0KDQpnZ3Bsb3QyOjphdXRvcGxvdChORUJfY2FwYWNpdHkudHMsIHlsYWI9Ik1XIiwgbWFpbj0iT250YXJpbyBBbm51YWwgRWxlY3RyaWNpdHkgQ2FwYWNpdHkgUHJvamVjdGlvbnMiKQ0KYGBgDQoNCiMgTW9udGhseSBFbGVjdHJpY2l0eSBTdXBwbHkgYW5kIERpc3Bvc2l0aW9uIFN1cnZleSAoTUVMRSksIE9udGFyaW8gKE1XaCkNCg0KU3RhdGlzdGljcyBDYW5hZGEsIE1vbnRobHkgRWxlY3RyaWNpdHkgU3VwcGx5IGFuZCBEaXNwb3NpdGlvbiBTdXJ2ZXkgKE1FTEUpDQoNCkVsZWN0cmljIHBvd2VyIGdlbmVyYXRpb24sIG1vbnRobHkgZ2VuZXJhdGlvbiBieSB0eXBlIG9mIGVsZWN0cmljaXR5LiBbVGFibGU6IDI1LTEwLTAwMTUtMDFdKGh0dHBzOi8vd3d3MTUwLnN0YXRjYW4uZ2MuY2EvdDEvdGJsMS9lbi9jdiFyZWNyZWF0ZS5hY3Rpb24/cGlkPTI1MTAwMDE1MDEmc2VsZWN0ZWROb2RlSWRzPTFENywzRDIsM0QzLDNENCwzRDUsM0Q2LDNENywzRDgsM0Q5LDNEMTAsM0QxMSZjaGVja2VkTGV2ZWxzPTFEMSwyRDEmcmVmUGVyaW9kcz0yMDA4MDEwMSwyMDE5MDMwMSZkaW1lbnNpb25MYXlvdXRzPWxheW91dDMsbGF5b3V0MyxsYXlvdXQyLGxheW91dDMmdmVjdG9yRGlzcGxheT1mYWxzZSkNCg0KYGBge3J9DQpNRUxFX2dlbmVyYXRpb24gPC0gcmVhZC5jc3YoIjI1MTAwMDE1MDEtbm9TeW1ib2wuY3N2IikNCmBgYA0KDQpgYGB7cn0NCk1FTEVfZ2VuZXJhdGlvbiRZRUFSX01PTlRIIDwtIE5VTEwNCg0KTUVMRV9nZW5lcmF0aW9uLnRzIDwtIHRzKE1FTEVfZ2VuZXJhdGlvbiwgc3RhcnQgPSAyMDA4LCBmcmVxdWVuY3kgPSAxMikNCg0KZ2dwbG90Mjo6YXV0b3Bsb3QoTUVMRV9nZW5lcmF0aW9uLnRzLCB5bGFiPSJNV2giLCBtYWluPSJPbnRhcmlvIE1vbnRobHkgRWxlY3RyaWNpdHkgR2VuZXJhdGlvbiIpDQpgYGANCg0KYGBge3J9DQpNRUxFX2dlbmVyYXRpb25fdG90YWwudHMgPC0gdHMoTUVMRV9nZW5lcmF0aW9uJFRvdGFsLCBzdGFydCA9IDIwMDgsIGZyZXF1ZW5jeSA9IDEyKQ0KDQpwbG90KE1FTEVfZ2VuZXJhdGlvbl90b3RhbC50cykNCmBgYA0KDQpgYGB7cn0NCk1FTEVfZ2VuZXJhdGlvbl90b3RhbC50cy5jb21wb25lbnRzIDwtIGRlY29tcG9zZShNRUxFX2dlbmVyYXRpb25fdG90YWwudHMpDQoNCmZvcmVjYXN0OjphdXRvcGxvdChNRUxFX2dlbmVyYXRpb25fdG90YWwudHMuY29tcG9uZW50cykNCmBgYA0KDQpgYGB7cn0NCk1FTEVfZ2VuZXJhdGlvbl90b3RhbC50cy5hcmltYSA8LSBhdXRvLmFyaW1hKE1FTEVfZ2VuZXJhdGlvbl90b3RhbC50cykNCg0KTUVMRV9nZW5lcmF0aW9uX3RvdGFsLnRzLmFyaW1hDQpgYGANCg0KYGBge3J9DQpNRUxFX2dlbmVyYXRpb25fdG90YWwudHMuYXJpbWEuZm9yZWNhc3QgPC0gZm9yZWNhc3QoTUVMRV9nZW5lcmF0aW9uX3RvdGFsLnRzLmFyaW1hLCBsZXZlbCA9IGMoOTUpLCBoID0gMTIwKQ0KDQpmb3JlY2FzdDo6YXV0b3Bsb3QoTUVMRV9nZW5lcmF0aW9uX3RvdGFsLnRzLmFyaW1hLmZvcmVjYXN0KQ0KYGBgDQoNCiMgSUVTTw0KDQpJbmRlcGVuZGVudCBFbGVjdHJpY2l0eSBTeXN0ZW0gT3BlcmF0b3IgKElFU08pLCBbRGF0YSBEaXJlY3RvcnldKGh0dHA6Ly9pZXNvLmNhL2VuL1Bvd2VyLURhdGEvRGF0YS1EaXJlY3RvcnkpDQoNCiMjIEhvdXJseSBHZW5lcmF0b3IgRW5lcmd5IE91dHB1dCBhbmQgQ2FwYWJpbGl0eSBSZXBvcnQNCg0KSG91cmx5IEdlbmVyYXRvciBFbmVyZ3kgT3V0cHV0IGFuZCBDYXBhYmlsaXR5IFJlcG9ydA0KDQo+IFRoZSBIb3VybHkgR2VuZXJhdG9yIEVuZXJneSBPdXRwdXQgYW5kIENhcGFiaWxpdHkgUmVwb3J0IHByZXNlbnRzIHRoZSBlbmVyZ3kgb3V0cHV0IGFuZCBjYXBhYmlsaXR5IGZvciBnZW5lcmF0aW5nIGZhY2lsaXRpZXMgaW4gdGhlIElFU08tYWRtaW5pc3RlcmVkIGVuZXJneSBtYXJrZXQgd2l0aCBhIG1heGltdW0gb3V0cHV0IGNhcGFiaWxpdHkgb2YgMjAgTVcgb3IgbW9yZS4NCg0KPGh0dHA6Ly9yZXBvcnRzLmllc28uY2EvZG9jcmVmcy9oZWxwZmlsZS9HZW5PdXRwdXRDYXBhYmlsaXR5X2g0LnBkZj4NCg0KPiAqKk91dHB1dCoqIGlzIHRoZSBhY3R1YWwgZW5lcmd5IHByb2R1Y3Rpb24gb2YgdGhlIHVuaXQgb3IgZmFjaWxpdHkuIFRoZSBob3VybHkgb3V0cHV0IGlzIHRoZSBmYWNpbGl0eeKAmXMgZml2ZS1taW51dGUNCm91dHB1dHMgYXZlcmFnZWQgb3ZlciBhbiBob3VyLiANCj4NCj4gKipDYXBhYmlsaXR5KiogaXMgdGhlIG1heGltdW0gcG90ZW50aWFsIG91dHB1dCBvZiB0aGUgdW5pdCBvciBmYWNpbGl0eSB1bmRlciBjdXJyZW50IGNvbmRpdGlvbnMsIHdoaWNoIGluY2x1ZGVzDQptYXhpbXVtIHVuaXQgZGVyYXRlcyBhbmQgb3V0YWdlcyBmb3IgdGhhdCBob3VyLiBJbiB0aGlzIHJlcG9ydCwgQ2FwYWJpbGl0eSBpcyBwcm92aWRlZCBmb3IgbnVjbGVhciwgaHlkcm8sIGdhcywNCmFuZCBiaW9mdWVsIGdlbmVyYXRpb24gKGV4Y2x1ZGluZyB3aW5kIGFuZCBzb2xhcikuIA0KDQpHT0MtMjAxMC54bHN4IC0gR09DLTIwMTktSmFuLUFwcmlsLnhsc3ggLT4gSUVTT19vdXRwdXRfMjAxMC5jc3YsIElFU09fY2FwYWJpbGl0eV8yMDEwLmNzdiAtDQpJRVNPX291dHB1dF8yMDE5LmNzdiwgSUVTT19jYXBhYmlsaXR5XzIwMTkuY3N2DQoNCm9ic2VydmF0aW9uIGZvciBlYWNoIGhvdXIsIDIwMTAgdG8gQXByaWwgMjAxOQ0KDQpSb2JlcnQgSiBIeW1hbiwgW1NlYXNvbmFsIHBlcmlvZHNdKGh0dHBzOi8vcm9iamh5bmRtYW4uY29tL2h5bmRzaWdodC9zZWFzb25hbC1wZXJpb2RzLykuDQpbZm9yZWNhc3Q6Om1zdHNdKGh0dHBzOi8vd3d3LnJkb2N1bWVudGF0aW9uLm9yZy9wYWNrYWdlcy9mb3JlY2FzdC92ZXJzaW9ucy84LjcvdG9waWNzL21zdHMpDQoNCmBgYHtyfQ0KSUVTT19vdXRwdXRfMjAxMCA8LSBmcmVhZCgiSUVTT19vdXRwdXRfMjAxMC5jc3YiKQ0KDQpJRVNPX291dHB1dF8yMDEwJERBVEUgPC0gTlVMTA0KDQpJRVNPX291dHB1dF8yMDEwJEhPVVIgPC0gTlVMTA0KDQpJRVNPX291dHB1dF8yMDEwJFRPVEFMIDwtIHJvd1N1bXMoSUVTT19vdXRwdXRfMjAxMCwgbmEucm09VFJVRSkNCg0KSUVTT19vdXRwdXRfMjAxMCA8LSBJRVNPX291dHB1dF8yMDEwWywuKFRPVEFMKV0NCmBgYA0KDQpgYGB7cn0NCklFU09fb3V0cHV0XzIwMTEgPC0gZnJlYWQoIklFU09fb3V0cHV0XzIwMTEuY3N2IikNCg0KSUVTT19vdXRwdXRfMjAxMSREQVRFIDwtIE5VTEwNCg0KSUVTT19vdXRwdXRfMjAxMSRIT1VSIDwtIE5VTEwNCg0KSUVTT19vdXRwdXRfMjAxMSRUT1RBTCA8LSByb3dTdW1zKElFU09fb3V0cHV0XzIwMTEsIG5hLnJtPVRSVUUpDQoNCklFU09fb3V0cHV0XzIwMTEgPC0gSUVTT19vdXRwdXRfMjAxMVssLihUT1RBTCldDQpgYGANCg0KYGBge3J9DQpJRVNPX291dHB1dF8yMDEyIDwtIGZyZWFkKCJJRVNPX291dHB1dF8yMDEyLmNzdiIpDQoNCklFU09fb3V0cHV0XzIwMTIkREFURSA8LSBOVUxMDQoNCklFU09fb3V0cHV0XzIwMTIkSE9VUiA8LSBOVUxMDQoNCklFU09fb3V0cHV0XzIwMTIkVE9UQUwgPC0gc