knitr::opts_chunk$set(message = FALSE, warning = FALSE)
library(tidyverse)
library(tidymodels)
library(recipes)
library(rvest)
library(stringr)
library(lubridate)
library(revgeo)
library(jsonlite)
library(httr)
library(kableExtra)
library(FinCal)
library(gridExtra)
library(grid)
Group by development regions
seda_db %>%
group_by(region) %>%
summarise(n = n())
Investments; Savings; Area
seda_db %>%
summarize(
Investment = sum(Investment, na.rm = TRUE)/1000000,
Savings = sum(Energy.Savings, na.rm = TRUE)/1000000,
Area = sum(Area, na.rm = TRUE)/1000000
)
Repayment period histogram
seda_db %>%
filter(Repayment.Per < 50) %>%
ggplot(aes(Repayment.Per)) +
geom_histogram() +
geom_vline(aes(xintercept = 10), color = "red", linetype = 1, size = 3) +
labs(y = "Projects Count") +
theme_bw()

Repayment period table view
seda_db %>%
group_by(Financing) %>%
filter(!is.na(Financing)) %>%
summarise(
Projects = n(),
Invesments = sum(Investment)/1.96,
t.CO2 = round(sum(CO2.Savings, na.rm = TRUE))
) %>%
kable(format.args = list(big.mark = " ")) %>%
kable_styling(full_width = F) %>%
row_spec(1, bold = T, color = "white", background = "red") %>%
row_spec(2, bold = T, color = "white", background = "green")
Financing |
Projects |
Invesments |
t.CO2 |
Not Bankable |
1 965 |
395 788 906 |
214 192 |
Bankable |
2 315 |
352 362 140 |
337 704 |
Grant/Fin. instrument
grant_help <- c(0.1, 0.20, 0.30, 0.40)
notb <- seda_db %>%
filter(Financing == "Not Bankable") %>%
summarise(
NotBankable_Invesments = sum(Investment)/1.96,
NotBankable_BGN.Savings = sum(BGN.Savings)/1.96
)
new_rep <- function(grant_perc, inv, saving){
inv = inv - grant_perc*inv
n.period(
r = 0.05/12,
pv = inv,
fv = 0,
pmt = -saving/12
)/12
}
tibble(
Grant.Support = percent(grant_help, accuracy = 1),
Repayment.Per = map_dbl(grant_help,
new_rep,
notb$NotBankable_Invesments,
notb$NotBankable_BGN.Savings
) %>%
round(1)
) %>%
kable() %>%
kable_styling(full_width = F) %>%
row_spec(3, bold = T, color = "white", background = "green")
Grant.Support |
Repayment.Per |
10% |
13.0 |
20% |
11.1 |
30% |
9.3 |
40% |
7.7 |
Investment ~ Saving by type
seda_db %>%
select(Building.Type1, Investment, BGN.Savings, Area, Payback) %>%
filter(Payback < 10) %>%
ggplot() +
geom_point(aes(x = BGN.Savings, y = Investment), alpha = 0.4) +
geom_smooth(method = lm, aes(x = BGN.Savings, y = Investment)) +
#geom_hline(aes(yintercept = 10), color = "red", linetype = 2) +
facet_wrap(~Building.Type1) +
scale_y_continuous(labels=function(x) format(x, big.mark = " ", scientific = FALSE)) +
scale_x_continuous(labels=function(x) format(x, big.mark = " ", scientific = TRUE)) +
labs(y = "BGN.Investment")

Estimating: Type > Rating > Area and sorting
estim <- seda_db %>%
filter(
!is.na(Investment) | !is.na(BGN.Savings)
) %>%
group_by(Building.Type1, Rating, Area.Class) %>%
nest(Investment, BGN.Savings) %>%
mutate(
fit = map(data, ~lm(BGN.Savings ~ Investment, data = .x)),
tidied = map(fit, tidy)
) %>%
unnest(tidied) %>%
filter(
p.value < 0.05,
term == "Investment"
) %>%
arrange(
desc(estimate)
)
gems <- estim %>%
select(-std.error, -term, -statistic, -p.value) %>%
mutate(Value = "gem") %>%
mutate(Estimate = round(estimate, 3)) %>%
select(-estimate) %>%
head(5)
dregs <- estim %>%
select(-std.error, -term, -statistic, -p.value) %>%
mutate(Value = "dregs") %>%
mutate(Estimate = round(estimate, 3)) %>%
select(-estimate) %>%
tail(5)
bind_rows(gems, dregs) %>%
kable() %>%
kable_styling(full_width = F) %>%
row_spec(1:5, bold = T, color = "white", background = "gold") %>%
row_spec(6:10, bold = T, color = "white", background = "grey")
Building.Type1 |
Rating |
Area.Class |
Value |
Estimate |
Libraries |
D |
less than 1 000 |
gem |
0.425 |
Supermarkets |
D |
between 1 000 and 5 000 |
gem |
0.369 |
Libraries |
G |
between 1 000 and 5 000 |
gem |
0.356 |
Cinemas |
F |
between 1 000 and 5 000 |
gem |
0.334 |
Hospitals |
G |
less than 1 000 |
gem |
0.310 |
Libraries |
D |
between 1 000 and 5 000 |
dregs |
0.070 |
Educational |
G |
less than 1 000 |
dregs |
0.066 |
Sports |
F |
between 1 000 and 5 000 |
dregs |
0.064 |
Residential |
F |
less than 1 000 |
dregs |
0.063 |
Residential |
D |
less than 1 000 |
dregs |
0.055 |
LS0tDQp0aXRsZTogIkNlcnRpZmllZCBidWlsZGluZ3MgQkcgTWFya2V0IC0gRURBIg0Kb3V0cHV0OiBodG1sX25vdGVib29rDQotLS0NCg0KYGBge3Igc2V0dXB9DQprbml0cjo6b3B0c19jaHVuayRzZXQobWVzc2FnZSA9IEZBTFNFLCB3YXJuaW5nID0gRkFMU0UpDQpsaWJyYXJ5KHRpZHl2ZXJzZSkNCmxpYnJhcnkodGlkeW1vZGVscykNCmxpYnJhcnkocmVjaXBlcykNCmxpYnJhcnkocnZlc3QpDQpsaWJyYXJ5KHN0cmluZ3IpDQpsaWJyYXJ5KGx1YnJpZGF0ZSkNCmxpYnJhcnkocmV2Z2VvKQ0KbGlicmFyeShqc29ubGl0ZSkNCmxpYnJhcnkoaHR0cikNCmxpYnJhcnkoa2FibGVFeHRyYSkNCmxpYnJhcnkoRmluQ2FsKQ0KbGlicmFyeShncmlkRXh0cmEpDQpsaWJyYXJ5KGdyaWQpDQpgYGANCg0KIyBMb2FkIGFuZCB0cmFuc2Zvcm0gLy9hIGJpdA0KDQpgYGB7cn0NCnNlZGFfZGIgPC0gcmVhZF9yZHMoImRhdGFfdjJcXHNlZGEtZGIucmRzIikgJT4lDQogICAgICAgIG11dGF0ZSAoDQogICAgICAgICAgICAgICAgUmVwYXltZW50LlBlciA9IG4ucGVyaW9kKHIgPSAwLjA1LzEyLCBwdiA9IEludmVzdG1lbnQsIGZ2ID0gMCwgcG10ID0gLUJHTi5TYXZpbmdzLzEyKS8xMg0KICAgICAgICApICU+JQ0KICAgICAgICBtdXRhdGUoDQogICAgICAgICAgICAgICAgRmluYW5jaW5nID0gaWZfZWxzZShSZXBheW1lbnQuUGVyID4gMTAsICJCYW5rYWJsZSIsICJOb3QgQmFua2FibGUiKQ0KICAgICAgICApICU+JQ0KICAgICAgICBtdXRhdGUoRmluYW5jaW5nID0gYXNfZmFjdG9yKEZpbmFuY2luZykpICU+JQ0KICAgICAgICBtdXRhdGUoUmF0aW5nID0gYXNfZmFjdG9yKFJhdGluZykpICU+JQ0KICAgICAgICBtdXRhdGUoUG90ZW50aWFsLlJhdGluZyA9IGFzX2ZhY3RvcihQb3RlbnRpYWwuUmF0aW5nKSkgJT4lDQogICAgICAgIG11dGF0ZShBcmVhLkNsYXNzID0gY2FzZV93aGVuKA0KICAgICAgICAgICAgICAgIEFyZWEgPCAxMDAwIH4gImxlc3MgdGhhbiAxIDAwMCIsDQogICAgICAgICAgICAgICAgQXJlYSA+PSAxMDAwICYmIEFyZWEgPCA1MDAwIH4gImJldHdlZW4gMSAwMDAgYW5kIDUgMDAwIiwNCiAgICAgICAgICAgICAgICBBcmVhID49NTAwMCB+ICJtb3JlIHRoYW4gNSAwMDAiDQogICAgICAgICkNCiAgICAgICAgKSAlPiUNCiAgICAgICAgbXV0YXRlKEJ1aWxkaW5nLlR5cGUxID0gY2FzZV93aGVuKA0KICAgICAgICAgICAgICAgIEJ1aWxkaW5nLlR5cGUxID09ICLQlNC10YLRgdC60L4g0LfQsNCy0LXQtNC10L3QuNC1ICjQs9GA0LDQtNC40L3QuCDQuCDRj9GB0LvQuCkiIH4gIktpbmRlcmdhcnRlbiIsDQogICAgICAgICAgICAgICAgQnVpbGRpbmcuVHlwZTEgPT0gItCe0LHRgNCw0LfQvtCy0LDRgtC10LvQvdC4ICjRg9GH0LjQu9C40YnQsCwg0LrQvtC70LXQttC4INC4INGD0L3QuNCy0LXRgNGB0LjRgtC10YLQuCkiIH4gIkVkdWNhdGlvbmFsIiwNCiAgICAgICAgICAgICAgICBCdWlsZGluZy5UeXBlMSA9PSAi0KHQs9GA0LDQtNC4INC30LAg0LDQtNC80LjQvdC40YHRgtGA0LDRgtC40LLQvdC+INC+0LHRgdC70YPQttCy0LDQvdC1IiB+ICJBZG1pbmlzdHJhdGl2ZSIsDQogICAgICAgICAgICAgICAgQnVpbGRpbmcuVHlwZTEgPT0gItCi0YDQsNC90YHQv9C+0YDRgiAo0LPQsNGA0LgsINC/0YDQuNGB0YLQsNC90LjRidCwINC4INC70LXRgtC40YnQsCkiIH4gIlRyYW5zcG9ydCIsDQogICAgICAgICAgICAgICAgQnVpbGRpbmcuVHlwZTEgPT0gItCR0LjQsdC70LjQvtGC0LXQutC4INC4INGH0LjRgtCw0LvQuNGJ0LAiIH4gIkxpYnJhcmllcyIsDQogICAgICAgICAgICAgICAgQnVpbGRpbmcuVHlwZTEgPT0gItCc0LDQs9Cw0LfQuNC90Lgg0LfQsCDQv9GA0L7QtNCw0LbQsdCwINC90LAg0LTRgNC10LHQvdC+INC40LXQtNGA0L4gKNGB0YPQv9C10YDQvNCw0YDQutC10YLQuCDQuCDQvNC+0LvQvtCy0LUpIiB+ICJTdXBlcm1hcmtldHMiLA0KICAgICAgICAgICAgICAgIEJ1aWxkaW5nLlR5cGUxID09ICLQodC/0L7RgNGC0L3QuCDQt9Cw0LvQuCDQuCDRgdGK0L7RgNGK0LbQtdC90LjRjyIgfiAiU3BvcnRzIiwNCiAgICAgICAgICAgICAgICBCdWlsZGluZy5UeXBlMSA9PSAi0KXQvtGC0LXQu9C4INC4INGA0LXRgdGC0L7RgNCw0L3RgtC4IiB+ICJIb3RlbHMgYW5kIHJlc3RhdXJhbnRzIiwNCiAgICAgICAgICAgICAgICBCdWlsZGluZy5UeXBlMSA9PSAi0JfQtNGA0LDQstC10L7Qv9Cw0LfQstCw0L3QtSAo0LHQvtC70L3QuNGG0LgsINC/0L7Qu9C40LrQu9C40L3QuNC60Lgg0Lgg0LTRgC4pIiB+ICJIb3NwaXRhbHMiLA0KICAgICAgICAgICAgICAgIEJ1aWxkaW5nLlR5cGUxID09ICLQotC10LDRgtGA0Lgs0LrQuNC90LAs0L7Qv9C10YDQuCzRhdGD0LTQvtC2LtCz0LDQu9C10YDQuNC4IiB+ICJDaW5lbWFzIiwNCiAgICAgICAgICAgICAgICBCdWlsZGluZy5UeXBlMSA9PSAi0JbQuNC70LjRidC90LAgLSDQtdGC0LDQttC90LAg0YHQvtCx0YHRgtCy0LXQvdC+0YHRgiAo0LHQu9C+0Log0Lgv0LjQu9C4INC60L7QvtC/0LXRgNCw0YbQuNGPKSDRgSDQvdC40YHQutC+LCDRgdGA0LXQtNC90L4g0Lgg0LLQuNGB0L7QutC+INC30LDRgdGC0YDQvtGP0LLQsNC90LUiIH4gIlJlc2lkZW50aWFsIiwNCiAgICAgICAgICAgICAgICBCdWlsZGluZy5UeXBlMSA9PSAi0JTRgNGD0LPQuCwg0LLQutC7LiDRgdGC0LDRgNGHLiDQtNC+0LzQvtCy0LUsINC30LAg0YHQuNGA0LDRhtC4INC4INC40LfQvtGB0YLQsNCy0LXQvdC4INC00LXRhtCwLCDQvtCx0Ykt0YLQuNGPLCDQsNCy0YLQvtGB0LXRgNCy0LjQt9C4IiB+ICJPdGhlciIsDQogICAgICAgICAgICAgICAgQnVpbGRpbmcuVHlwZTEgPT0gItCf0YDQvtC40LfQstC+0LTRgdGC0LLQtdC90LAg0YHQs9GA0LDQtNCwIiB+ICJJbmR1c3RyeSIsDQogICAgICAgICAgICAgICAgQnVpbGRpbmcuVHlwZTEgPT0gItCV0LTQvdC+0YTQsNC80LjQu9C90Lgg0LrRitGJ0LgiIH4gIkhvdXNlcyIsDQogICAgICAgICAgICAgICAgQnVpbGRpbmcuVHlwZTEgPT0gItCh0LPRgNCw0LTQsCAg0L7QsdGB0LvQtdC00LLQsNC90LAg0L7RgiDRhNC40LcuINC70LjRhtC1IiB+ICJTZWxmLWF1ZGl0ZWQiDQogICAgICAgICkNCiAgICAgICAgKSAlPiUNCiAgICAgICAgbXV0YXRlKA0KICAgICAgICAgICAgICAgIEFyZWEuQ2xhc3MgPSBhc19mYWN0b3IoQXJlYS5DbGFzcyksDQogICAgICAgICAgICAgICAgQnVpbGRpbmcuVHlwZTEgPSBhc19mYWN0b3IoQnVpbGRpbmcuVHlwZTEpDQogICAgICAgICkgJT4lDQogICAgICAgIG11dGF0ZSgNCiAgICAgICAgICAgICAgICBGaW5hbmNpbmcgPSBpZl9lbHNlKFJlcGF5bWVudC5QZXIgPCAxMCwgIkJhbmthYmxlIiwgIk5vdCBCYW5rYWJsZSIpDQogICAgICAgICkgJT4lDQogICAgICAgIG11dGF0ZShGaW5hbmNpbmcgPSBhc19mYWN0b3IoRmluYW5jaW5nKSkNCg0Kc2VkYV9kYiAgICAgICAgDQpgYGANCg0KIyBHcm91cCBieSBkZXZlbG9wbWVudCByZWdpb25zDQoNCmBgYHtyfQ0Kc2VkYV9kYiAlPiUNCiAgICAgICAgZ3JvdXBfYnkocmVnaW9uKSAlPiUNCiAgICAgICAgc3VtbWFyaXNlKG4gPSBuKCkpDQpgYGANCg0KIyBJbnZlc3RtZW50czsgU2F2aW5nczsgQXJlYQ0KDQpgYGB7cn0NCnNlZGFfZGIgJT4lDQogICAgICAgIHN1bW1hcml6ZSgNCiAgICAgICAgICAgICAgICBJbnZlc3RtZW50ID0gc3VtKEludmVzdG1lbnQsIG5hLnJtID0gVFJVRSkvMTAwMDAwMCwNCiAgICAgICAgICAgICAgICBTYXZpbmdzID0gc3VtKEVuZXJneS5TYXZpbmdzLCBuYS5ybSA9IFRSVUUpLzEwMDAwMDAsDQogICAgICAgICAgICAgICAgQXJlYSA9IHN1bShBcmVhLCBuYS5ybSA9IFRSVUUpLzEwMDAwMDANCiAgICAgICAgKQ0KYGBgDQoNCiMgUmVwYXltZW50IHBlcmlvZCBoaXN0b2dyYW0NCg0KYGBge3IgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0NCnNlZGFfZGIgJT4lDQogICAgICAgIGZpbHRlcihSZXBheW1lbnQuUGVyIDwgNTApICU+JQ0KICAgICAgICBnZ3Bsb3QoYWVzKFJlcGF5bWVudC5QZXIpKSArDQogICAgICAgIGdlb21faGlzdG9ncmFtKCkgKw0KICAgICAgICBnZW9tX3ZsaW5lKGFlcyh4aW50ZXJjZXB0ID0gMTApLCBjb2xvciA9ICJyZWQiLCBsaW5ldHlwZSA9IDEsIHNpemUgPSAzKSArIA0KICAgICAgICBsYWJzKHkgPSAiUHJvamVjdHMgQ291bnQiKSArIA0KICAgICAgICB0aGVtZV9idygpDQpgYGANCg0KIyBSZXBheW1lbnQgcGVyaW9kIHRhYmxlIHZpZXcgDQoNCmBgYHtyIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9DQpzZWRhX2RiICU+JQ0KICAgICAgICBncm91cF9ieShGaW5hbmNpbmcpICU+JQ0KICAgICAgICBmaWx0ZXIoIWlzLm5hKEZpbmFuY2luZykpICU+JQ0KICAgICAgICBzdW1tYXJpc2UoDQogICAgICAgICAgICAgICAgUHJvamVjdHMgPSBuKCksDQogICAgICAgICAgICAgICAgSW52ZXNtZW50cyA9IHN1bShJbnZlc3RtZW50KS8xLjk2LA0KICAgICAgICAgICAgICAgIHQuQ08yID0gcm91bmQoc3VtKENPMi5TYXZpbmdzLCBuYS5ybSA9IFRSVUUpKQ0KICAgICAgICApICU+JQ0KICAgICAgICBrYWJsZShmb3JtYXQuYXJncyA9IGxpc3QoYmlnLm1hcmsgPSAiICIpKSAlPiUNCiAgICAgICAga2FibGVfc3R5bGluZyhmdWxsX3dpZHRoID0gRikgJT4lDQogICAgICAgIHJvd19zcGVjKDEsIGJvbGQgPSBULCBjb2xvciA9ICJ3aGl0ZSIsIGJhY2tncm91bmQgPSAicmVkIikgJT4lDQogICAgICAgIHJvd19zcGVjKDIsIGJvbGQgPSBULCBjb2xvciA9ICJ3aGl0ZSIsIGJhY2tncm91bmQgPSAiZ3JlZW4iKQ0KYGBgDQoNCiMgR3JhbnQvRmluLiBpbnN0cnVtZW50DQoNCmBgYHtyfQ0KZ3JhbnRfaGVscCA8LSBjKDAuMSwgMC4yMCwgMC4zMCwgMC40MCkNCg0Kbm90YiA8LSBzZWRhX2RiICU+JQ0KICAgICAgICBmaWx0ZXIoRmluYW5jaW5nID09ICJOb3QgQmFua2FibGUiKSAlPiUNCiAgICAgICAgc3VtbWFyaXNlKA0KICAgICAgICAgICAgICAgIE5vdEJhbmthYmxlX0ludmVzbWVudHMgPSBzdW0oSW52ZXN0bWVudCkvMS45NiwNCiAgICAgICAgICAgICAgICBOb3RCYW5rYWJsZV9CR04uU2F2aW5ncyA9IHN1bShCR04uU2F2aW5ncykvMS45Ng0KICAgICAgICApDQoNCm5ld19yZXAgPC0gZnVuY3Rpb24oZ3JhbnRfcGVyYywgaW52LCBzYXZpbmcpew0KICAgICAgICBpbnYgPSBpbnYgLSBncmFudF9wZXJjKmludg0KICAgICAgICBuLnBlcmlvZCgNCiAgICAgICAgICAgICAgICByID0gMC4wNS8xMiwgDQogICAgICAgICAgICAgICAgcHYgPSBpbnYsIA0KICAgICAgICAgICAgICAgIGZ2ID0gMCwgDQogICAgICAgICAgICAgICAgcG10ID0gLXNhdmluZy8xMg0KICAgICAgICApLzEyDQp9DQoNCnRpYmJsZSgNCiAgICAgICAgR3JhbnQuU3VwcG9ydCA9IHBlcmNlbnQoZ3JhbnRfaGVscCwgYWNjdXJhY3kgPSAxKSwNCiAgICAgICAgUmVwYXltZW50LlBlciA9IG1hcF9kYmwoZ3JhbnRfaGVscCwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5ld19yZXAsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5vdGIkTm90QmFua2FibGVfSW52ZXNtZW50cywgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5vdGIkTm90QmFua2FibGVfQkdOLlNhdmluZ3MNCiAgICAgICAgKSAlPiUNCiAgICAgICAgICAgICAgICByb3VuZCgxKQ0KKSAlPiUNCiAgICAgICAga2FibGUoKSAlPiUNCiAgICAgICAga2FibGVfc3R5bGluZyhmdWxsX3dpZHRoID0gRikgJT4lDQogICAgICAgIHJvd19zcGVjKDMsIGJvbGQgPSBULCBjb2xvciA9ICJ3aGl0ZSIsIGJhY2tncm91bmQgPSAiZ3JlZW4iKQ0KYGBgDQoNCiMjIEludmVzdG1lbnQgfiBTYXZpbmcgYnkgdHlwZQ0KDQpgYGB7cn0NCnNlZGFfZGIgJT4lDQogICAgICAgIHNlbGVjdChCdWlsZGluZy5UeXBlMSwgSW52ZXN0bWVudCwgQkdOLlNhdmluZ3MsIEFyZWEsIFBheWJhY2spICU+JQ0KICAgICAgICBmaWx0ZXIoUGF5YmFjayA8IDEwKSAlPiUNCiAgICAgICAgDQogICAgICAgIGdncGxvdCgpICsNCiAgICAgICAgZ2VvbV9wb2ludChhZXMoeCA9IEJHTi5TYXZpbmdzLCB5ID0gSW52ZXN0bWVudCksIGFscGhhID0gMC40KSArDQogICAgICAgIGdlb21fc21vb3RoKG1ldGhvZCA9IGxtLCBhZXMoeCA9IEJHTi5TYXZpbmdzLCB5ID0gSW52ZXN0bWVudCkpICsNCiAgICAgICAgI2dlb21faGxpbmUoYWVzKHlpbnRlcmNlcHQgPSAxMCksIGNvbG9yID0gInJlZCIsIGxpbmV0eXBlID0gMikgKw0KICAgICAgICBmYWNldF93cmFwKH5CdWlsZGluZy5UeXBlMSkgKw0KICAgICAgICBzY2FsZV95X2NvbnRpbnVvdXMobGFiZWxzPWZ1bmN0aW9uKHgpIGZvcm1hdCh4LCBiaWcubWFyayA9ICIgIiwgc2NpZW50aWZpYyA9IEZBTFNFKSkgKw0KICAgICAgICBzY2FsZV94X2NvbnRpbnVvdXMobGFiZWxzPWZ1bmN0aW9uKHgpIGZvcm1hdCh4LCBiaWcubWFyayA9ICIgIiwgc2NpZW50aWZpYyA9IFRSVUUpKSArDQogICAgICAgIGxhYnMoeSA9ICJCR04uSW52ZXN0bWVudCIpDQpgYGANCg0KIyBFc3RpbWF0aW5nOiBUeXBlID4gUmF0aW5nID4gQXJlYSBhbmQgc29ydGluZyANCg0KYGBge3J9DQplc3RpbSA8LSBzZWRhX2RiICU+JQ0KICAgICAgICBmaWx0ZXIoDQogICAgICAgICAgICAgICAgIWlzLm5hKEludmVzdG1lbnQpIHwgIWlzLm5hKEJHTi5TYXZpbmdzKQ0KICAgICAgICApICU+JQ0KICAgICAgICBncm91cF9ieShCdWlsZGluZy5UeXBlMSwgUmF0aW5nLCBBcmVhLkNsYXNzKSAlPiUNCiAgICAgICAgbmVzdChJbnZlc3RtZW50LCBCR04uU2F2aW5ncykgJT4lDQogICAgICAgIG11dGF0ZSgNCiAgICAgICAgICAgICAgICBmaXQgPSBtYXAoZGF0YSwgfmxtKEJHTi5TYXZpbmdzIH4gSW52ZXN0bWVudCwgZGF0YSA9IC54KSksDQogICAgICAgICAgICAgICAgdGlkaWVkID0gbWFwKGZpdCwgdGlkeSkNCiAgICAgICAgKSAlPiUgDQogICAgICAgIHVubmVzdCh0aWRpZWQpICU+JQ0KICAgICAgICBmaWx0ZXIoDQogICAgICAgICAgICAgICAgcC52YWx1ZSA8IDAuMDUsDQogICAgICAgICAgICAgICAgdGVybSA9PSAiSW52ZXN0bWVudCINCiAgICAgICAgKSAlPiUNCiAgICAgICAgYXJyYW5nZSgNCiAgICAgICAgICAgICAgICBkZXNjKGVzdGltYXRlKQ0KICAgICAgICApDQoNCmdlbXMgPC0gZXN0aW0gJT4lDQogICAgICAgIHNlbGVjdCgtc3RkLmVycm9yLCAtdGVybSwgLXN0YXRpc3RpYywgLXAudmFsdWUpICU+JQ0KICAgICAgICBtdXRhdGUoVmFsdWUgPSAiZ2VtIikgJT4lDQogICAgICAgIG11dGF0ZShFc3RpbWF0ZSA9IHJvdW5kKGVzdGltYXRlLCAzKSkgJT4lDQogICAgICAgIHNlbGVjdCgtZXN0aW1hdGUpICU+JQ0KICAgICAgICBoZWFkKDUpDQoNCg0KZHJlZ3MgPC0gZXN0aW0gJT4lDQogICAgICAgIHNlbGVjdCgtc3RkLmVycm9yLCAtdGVybSwgLXN0YXRpc3RpYywgLXAudmFsdWUpICU+JQ0KICAgICAgICBtdXRhdGUoVmFsdWUgPSAiZHJlZ3MiKSAlPiUNCiAgICAgICAgbXV0YXRlKEVzdGltYXRlID0gcm91bmQoZXN0aW1hdGUsIDMpKSAlPiUNCiAgICAgICAgc2VsZWN0KC1lc3RpbWF0ZSkgJT4lDQogICAgICAgIHRhaWwoNSkNCg0KYmluZF9yb3dzKGdlbXMsIGRyZWdzKSAlPiUNCiAgICAgICAga2FibGUoKSAlPiUNCiAgICAgICAga2FibGVfc3R5bGluZyhmdWxsX3dpZHRoID0gRikgJT4lDQogICAgICAgIHJvd19zcGVjKDE6NSwgYm9sZCA9IFQsIGNvbG9yID0gIndoaXRlIiwgYmFja2dyb3VuZCA9ICJnb2xkIikgJT4lDQogICAgICAgIHJvd19zcGVjKDY6MTAsIGJvbGQgPSBULCBjb2xvciA9ICJ3aGl0ZSIsIGJhY2tncm91bmQgPSAiZ3JleSIpDQpgYGANCg0KDQo=