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)

Load and transform //a bit

seda_db <- read_rds("data_v2\\seda-db.rds") %>%
        mutate (
                Repayment.Per = n.period(r = 0.05/12, pv = Investment, fv = 0, pmt = -BGN.Savings/12)/12
        ) %>%
        mutate(
                Financing = if_else(Repayment.Per > 10, "Bankable", "Not Bankable")
        ) %>%
        mutate(Financing = as_factor(Financing)) %>%
        mutate(Rating = as_factor(Rating)) %>%
        mutate(Potential.Rating = as_factor(Potential.Rating)) %>%
        mutate(Area.Class = case_when(
                Area < 1000 ~ "less than 1 000",
                Area >= 1000 && Area < 5000 ~ "between 1 000 and 5 000",
                Area >=5000 ~ "more than 5 000"
        )
        ) %>%
        mutate(Building.Type1 = case_when(
                Building.Type1 == "Детско заведение (градини и ясли)" ~ "Kindergarten",
                Building.Type1 == "Образователни (училища, колежи и университети)" ~ "Educational",
                Building.Type1 == "Сгради за административно обслужване" ~ "Administrative",
                Building.Type1 == "Транспорт (гари, пристанища и летища)" ~ "Transport",
                Building.Type1 == "Библиотеки и читалища" ~ "Libraries",
                Building.Type1 == "Магазини за продажба на дребно иедро (супермаркети и молове)" ~ "Supermarkets",
                Building.Type1 == "Спортни зали и съоръжения" ~ "Sports",
                Building.Type1 == "Хотели и ресторанти" ~ "Hotels and restaurants",
                Building.Type1 == "Здравеопазване (болници, поликлиники и др.)" ~ "Hospitals",
                Building.Type1 == "Театри,кина,опери,худож.галерии" ~ "Cinemas",
                Building.Type1 == "Жилищна - етажна собственост (блок и/или кооперация) с ниско, средно и високо застрояване" ~ "Residential",
                Building.Type1 == "Други, вкл. старч. домове, за сираци и изоставени деца, общ-тия, автосервизи" ~ "Other",
                Building.Type1 == "Производствена сграда" ~ "Industry",
                Building.Type1 == "Еднофамилни къщи" ~ "Houses",
                Building.Type1 == "Сграда  обследвана от физ. лице" ~ "Self-audited"
        )
        ) %>%
        mutate(
                Area.Class = as_factor(Area.Class),
                Building.Type1 = as_factor(Building.Type1)
        ) %>%
        mutate(
                Financing = if_else(Repayment.Per < 10, "Bankable", "Not Bankable")
        ) %>%
        mutate(Financing = as_factor(Financing))

seda_db        

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=