Country-level CCyB rates
download.file("https://www.esrb.europa.eu/national_policy/ccb/shared/data/esrb.ccybd_CCyB_data.xlsx", destfile = "esrb.ccybd_CCyB_data.xlsx")
trying URL 'https://www.esrb.europa.eu/national_policy/ccb/shared/data/esrb.ccybd_CCyB_data.xlsx'
downloaded 242 KB
ESRB_CCyB <- read_excel("~/Downloads/esrb.ccybd_CCyB_data.xlsx") %>%
mutate(decision_date = as.Date(`Decision on`, format = "%Y-%m-%d"),
reference_date = as.Date(`Reference date`, format = "%Y-%m-%d"),
announcement_date = as.Date(`Date of Announcement`, format = "%Y-%m-%d"),
application_date = as.Date(`Application since`, format = "%Y-%m-%d"),
CCyB_rate = as.numeric(`CCyB rate`),
credit_gdp_ratio = as.numeric(`Credit-to-GDP`),
credit_gdp_gap = as.numeric(`Credit Gap`)) %>%
select(Country, decision_date, announcement_date, application_date, reference_date, CCyB_rate, credit_gdp_ratio, credit_gdp_gap)
date_range <- ESRB_CCyB %>%
select(contains("_date")) %>%
as.matrix(ncol = 1) %>%
range() %>%
as.Date(format = "%Y-%m-%d")
ESRB_CCyB <- ESRB_CCyB %>%
group_by(Country) %>%
nest()
CCyB_over_time <- function(ccyb_df, pad_by) {
ccyb_df %>%
data.frame() %>%
pad(by = pad_by, interval = "day") %>%
tidyr::fill(CCyB_rate)
}
ESRB_CCyB <- ESRB_CCyB %>%
mutate(
CCyB_decision = data %>% map(~ CCyB_over_time(., "decision_date")),
CCyB_announcement = data %>% map(~ CCyB_over_time(., "announcement_date")),
CCyB_application= data %>% map(~ CCyB_over_time(., "application_date"))
)
chart_ann_date <- ESRB_CCyB %>%
unnest(CCyB_announcement) %>%
group_by(Country) %>%
mutate(nonzero_CCyB = sum(CCyB_rate) > 0) %>%
filter(nonzero_CCyB == TRUE) %>%
ggplot(aes(x = announcement_date, y = CCyB_rate, color = Country)) +
geom_line() +
labs(title = "CCyB rate by annoucement date",
subtitle = "European countries that have activated CCyB at some point") +
xlab("Announcement date") +
ylab("CCyB rate (%)") +
theme(legend.position = "bottom")
ggplotly(chart_ann_date)
NA
chart_app_date <- ESRB_CCyB %>%
unnest(CCyB_application) %>%
group_by(Country) %>%
mutate(nonzero_CCyB = sum(CCyB_rate) > 0) %>%
filter(nonzero_CCyB == TRUE) %>%
ggplot(aes(x = application_date, y = CCyB_rate, color = Country)) +
geom_line() +
labs(title = "CCyB rate by application date",
subtitle = "European countries that have activated CCyB at some point") +
xlab("Application date") +
ylab("CCyB rate (%)") +
geom_vline(xintercept = Sys.Date(), linetype = "twodash", color = "blue", size = 1.3) +
theme(legend.position = "bottom")
ggplotly(chart_app_date)
Oxford Coronavirus Government Response Tracker
Explanations found in the dataset’s codebook, under “E2, debt/contract relief”.
The metric below aims to capture both the duration and (roughly) the intensity of the debt/contract relief provided in each jurisdiction. It’s not the same as what we wanted (details are in the document linked above), but that’s what I found so far in an organised way.
debt_relief <- read.csv("https://github.com/OxCGRT/covid-policy-tracker/raw/master/data/timeseries/e2_debtcontractrelief.csv",
na.strings = ".")
CCyB_countries <- unique(ESRB_CCyB$Country)
debt_relief <- debt_relief %>% filter(X %in% CCyB_countries) %>% select(-X.1)
debt_relief <- tibble(Country = debt_relief$X,
Debt_relief = debt_relief %>% select(-X) %>% rowSums(na.rm = TRUE))
debt_relief_plot <- debt_relief %>%
ggplot(aes(x = reorder(Country, -Debt_relief), y = Debt_relief)) +
geom_bar(stat = "identity") +
ggtitle("Debt relief measures by country in the sample") +
ylab("Debt relief score") +
xlab(element_blank()) +
theme(axis.text.x=element_text(size = rel(0.7))) +
scale_x_discrete(labels = function(labels) {
sapply(seq_along(labels), function(i) paste0(ifelse(i %% 2 == 0, '', '\n'), labels[i]))
})
debt_relief_plot
Google Mobility
GoogleMobilityDataset <- data.table(read.csv("https://www.gstatic.com/covid19/mobility/Global_Mobility_Report.csv",
stringsAsFactors = FALSE))
european_countries <- c("AT", # Austria
"BA", # Bosnia and Hezegovina
"BE", # Belgium
"BG", # Bulgaria
"BY", # Belarus
"CH", # Switzerland
"CZ", # Czechia
"DE", # Germany
"DK", # Denmark
"EE", # Estonia
"ES", # Spain
"FI", # Finland
"FR", # France
"GB", # United Kingdom
"GE", # Georgia
"GR", # Greece
"HR", # Croatia
"HU", # Hungary
"IE", # Ireland
"IT", # Italy
"LI", # Liechtenstein
"LT", # Lithuania
"LU", # Luxembourg
"LV", # Latvia
"MD", # Moldova
"MK", # North Macedonia
"MT", # Malta
"NL", # Netherlands
"NO", # Norway
"PL", # Poland
"PT", # Portugal
"RO", # Romania
"RS", # Serbia
"RU", # Russia
"SE", # Sweden
"SI", # Slovenia
"SK", # Slovakia
"UA") # Ukraine
GoogleMobilityDataset <- GoogleMobilityDataset[country_region_code %in% european_countries & sub_region_1 == "",]
GoogleMobilityDataset[, date := as.POSIXct(paste0(date, " 00:00:00"))]
GoogleMobilityDataset <- GoogleMobilityDataset %>%
select(country_region,
date,
retail_and_recreation_percent_change_from_baseline,
grocery_and_pharmacy_percent_change_from_baseline,
parks_percent_change_from_baseline,
transit_stations_percent_change_from_baseline,
workplaces_percent_change_from_baseline,
residential_percent_change_from_baseline) %>%
group_by(country_region) %>%
nest()
GoogleMobilityDataset <- GoogleMobilityDataset %>%
mutate(data = data %>% map(~ pivot_longer(.x, !date, names_to = "mobility_category", values_to = "change_from_baseline")))
Now let’s plot the mobility graph for each country.
mobility_plot <- function(country, country_data) {
ggplot(data = country_data, aes(x = date, y = change_from_baseline, color = mobility_category)) +
geom_line() +
ggtitle(label = country) +
theme(legend.position = "bottom",
legend.text =element_text(size = rel(0.5))) +
ylab("Change from baseline (%)") +
xlab(element_blank())
}
mobility_plot(GoogleMobilityDataset$country_region[[1]],
GoogleMobilityDataset$data[[1]])
map2(GoogleMobilityDataset$country_region, GoogleMobilityDataset$data, ~ mobility_plot(.x, .y))
LS0tCnRpdGxlOiAiQ0N5QiBpbiBFdXJvcGUgKHdvcmsgaW4gcHJvZ3Jlc3MpIgpvdXRwdXQ6CiAgaHRtbF9ub3RlYm9vazogCiAgICB0b2M6IHllcwogICAgbnVtYmVyX3NlY3Rpb25zOiB5ZXMKICB3b3JkX2RvY3VtZW50OiBkZWZhdWx0CiAgaHRtbF9kb2N1bWVudDoKICAgIGRmX3ByaW50OiBwYWdlZAotLS0KCmBgYHtyIExvYWQgcGFja2FnZXMsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0UsIGluY2x1ZGU9RkFMU0V9CmxpYnJhcnkodGlkeXZlcnNlKQpsaWJyYXJ5KGRhdGEudGFibGUpCmxpYnJhcnkocmVhZHhsKQpsaWJyYXJ5KHBsb3RseSkKbGlicmFyeShwYWRyKQpgYGAKCiMgQ291bnRyeS1sZXZlbCBDQ3lCIHJhdGVzCmBgYHtyIEdldHMgQ0N5QiB0aW1lIHNlcmllcywgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KZG93bmxvYWQuZmlsZSgiaHR0cHM6Ly93d3cuZXNyYi5ldXJvcGEuZXUvbmF0aW9uYWxfcG9saWN5L2NjYi9zaGFyZWQvZGF0YS9lc3JiLmNjeWJkX0NDeUJfZGF0YS54bHN4IiwgZGVzdGZpbGUgPSAiZXNyYi5jY3liZF9DQ3lCX2RhdGEueGxzeCIpCkVTUkJfQ0N5QiA8LSByZWFkX2V4Y2VsKCJ+L0Rvd25sb2Fkcy9lc3JiLmNjeWJkX0NDeUJfZGF0YS54bHN4IikgJT4lCiAgbXV0YXRlKGRlY2lzaW9uX2RhdGUgPSBhcy5EYXRlKGBEZWNpc2lvbiBvbmAsIGZvcm1hdCA9ICIlWS0lbS0lZCIpLAogICAgICAgICByZWZlcmVuY2VfZGF0ZSA9IGFzLkRhdGUoYFJlZmVyZW5jZSBkYXRlYCwgZm9ybWF0ID0gIiVZLSVtLSVkIiksCiAgICAgICAgIGFubm91bmNlbWVudF9kYXRlID0gYXMuRGF0ZShgRGF0ZSBvZiBBbm5vdW5jZW1lbnRgLCBmb3JtYXQgPSAiJVktJW0tJWQiKSwKICAgICAgICAgYXBwbGljYXRpb25fZGF0ZSA9IGFzLkRhdGUoYEFwcGxpY2F0aW9uIHNpbmNlYCwgZm9ybWF0ID0gIiVZLSVtLSVkIiksCiAgICAgICAgIENDeUJfcmF0ZSA9IGFzLm51bWVyaWMoYENDeUIgcmF0ZWApLAogICAgICAgICBjcmVkaXRfZ2RwX3JhdGlvID0gYXMubnVtZXJpYyhgQ3JlZGl0LXRvLUdEUGApLAogICAgICAgICBjcmVkaXRfZ2RwX2dhcCA9IGFzLm51bWVyaWMoYENyZWRpdCBHYXBgKSkgJT4lIAogIHNlbGVjdChDb3VudHJ5LCBkZWNpc2lvbl9kYXRlLCBhbm5vdW5jZW1lbnRfZGF0ZSwgYXBwbGljYXRpb25fZGF0ZSwgcmVmZXJlbmNlX2RhdGUsIENDeUJfcmF0ZSwgY3JlZGl0X2dkcF9yYXRpbywgY3JlZGl0X2dkcF9nYXApCgpkYXRlX3JhbmdlIDwtIEVTUkJfQ0N5QiAlPiUKICBzZWxlY3QoY29udGFpbnMoIl9kYXRlIikpICU+JQogIGFzLm1hdHJpeChuY29sID0gMSkgJT4lCiAgcmFuZ2UoKSAlPiUKICBhcy5EYXRlKGZvcm1hdCA9ICIlWS0lbS0lZCIpCgpFU1JCX0NDeUIgPC0gRVNSQl9DQ3lCICU+JSAKICBncm91cF9ieShDb3VudHJ5KSAlPiUgCiAgbmVzdCgpCgpDQ3lCX292ZXJfdGltZSA8LSBmdW5jdGlvbihjY3liX2RmLCBwYWRfYnkpIHsKICBjY3liX2RmICU+JSAKICAgIGRhdGEuZnJhbWUoKSAlPiUgCiAgICBwYWQoYnkgPSBwYWRfYnksIGludGVydmFsID0gImRheSIpICU+JSAKICAgIHRpZHlyOjpmaWxsKENDeUJfcmF0ZSkKfQoKRVNSQl9DQ3lCIDwtIEVTUkJfQ0N5QiAlPiUgCiAgbXV0YXRlKAogICAgQ0N5Ql9kZWNpc2lvbiA9IGRhdGEgJT4lIG1hcCh+IENDeUJfb3Zlcl90aW1lKC4sICJkZWNpc2lvbl9kYXRlIikpLAogICAgQ0N5Ql9hbm5vdW5jZW1lbnQgPSBkYXRhICU+JSBtYXAofiBDQ3lCX292ZXJfdGltZSguLCAiYW5ub3VuY2VtZW50X2RhdGUiKSksCiAgICBDQ3lCX2FwcGxpY2F0aW9uPSBkYXRhICU+JSBtYXAofiBDQ3lCX292ZXJfdGltZSguLCAiYXBwbGljYXRpb25fZGF0ZSIpKQogICkKYGBgCgoKCmBgYHtyIE92ZXJ2aWV3IG9mIGNvdW50cmllcyB3aXRoIHBvc2l0aXZlIENDeUIgLSBhbm5vdW5jZW1lbnQgZGF0ZX0KY2hhcnRfYW5uX2RhdGUgPC0gRVNSQl9DQ3lCICU+JSAKICB1bm5lc3QoQ0N5Ql9hbm5vdW5jZW1lbnQpICU+JSAKICBncm91cF9ieShDb3VudHJ5KSAlPiUgCiAgbXV0YXRlKG5vbnplcm9fQ0N5QiA9IHN1bShDQ3lCX3JhdGUpID4gMCkgJT4lIAogIGZpbHRlcihub256ZXJvX0NDeUIgPT0gVFJVRSkgJT4lIAogIGdncGxvdChhZXMoeCA9IGFubm91bmNlbWVudF9kYXRlLCB5ID0gQ0N5Ql9yYXRlLCBjb2xvciA9IENvdW50cnkpKSArCiAgZ2VvbV9saW5lKCkgKwogIGxhYnModGl0bGUgPSAiQ0N5QiByYXRlIGJ5IGFubm91Y2VtZW50IGRhdGUiLAogICAgICAgc3VidGl0bGUgPSAiRXVyb3BlYW4gY291bnRyaWVzIHRoYXQgaGF2ZSBhY3RpdmF0ZWQgQ0N5QiBhdCBzb21lIHBvaW50IikgKwogIHhsYWIoIkFubm91bmNlbWVudCBkYXRlIikgKwogIHlsYWIoIkNDeUIgcmF0ZSAoJSkiKSArCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gImJvdHRvbSIpCgpnZ3Bsb3RseShjaGFydF9hbm5fZGF0ZSkKCmBgYAoKCmBgYHtyIE92ZXJ2aWV3IG9mIGNvdW50cmllcyB3aXRoIHBvc2l0aXZlIENDeUIgLSBhcHBsaWNhdGlvbiBkYXRlfQpjaGFydF9hcHBfZGF0ZSA8LSBFU1JCX0NDeUIgJT4lIAogIHVubmVzdChDQ3lCX2FwcGxpY2F0aW9uKSAlPiUgCiAgZ3JvdXBfYnkoQ291bnRyeSkgJT4lIAogIG11dGF0ZShub256ZXJvX0NDeUIgPSBzdW0oQ0N5Ql9yYXRlKSA+IDApICU+JSAKICBmaWx0ZXIobm9uemVyb19DQ3lCID09IFRSVUUpICU+JSAKICBnZ3Bsb3QoYWVzKHggPSBhcHBsaWNhdGlvbl9kYXRlLCB5ID0gQ0N5Ql9yYXRlLCBjb2xvciA9IENvdW50cnkpKSArCiAgZ2VvbV9saW5lKCkgKwogIGxhYnModGl0bGUgPSAiQ0N5QiByYXRlIGJ5IGFwcGxpY2F0aW9uIGRhdGUiLAogICAgICAgc3VidGl0bGUgPSAiRXVyb3BlYW4gY291bnRyaWVzIHRoYXQgaGF2ZSBhY3RpdmF0ZWQgQ0N5QiBhdCBzb21lIHBvaW50IikgKwogIHhsYWIoIkFwcGxpY2F0aW9uIGRhdGUiKSArCiAgeWxhYigiQ0N5QiByYXRlICglKSIpICsKICBnZW9tX3ZsaW5lKHhpbnRlcmNlcHQgPSBTeXMuRGF0ZSgpLCBsaW5ldHlwZSA9ICJ0d29kYXNoIiwgY29sb3IgPSAiYmx1ZSIsIHNpemUgPSAxLjMpICsKICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAiYm90dG9tIikKZ2dwbG90bHkoY2hhcnRfYXBwX2RhdGUpCmBgYAoKIyBPeGZvcmQgQ29yb25hdmlydXMgR292ZXJubWVudCBSZXNwb25zZSBUcmFja2VyCgpFeHBsYW5hdGlvbnMgZm91bmQgaW4gdGhlIGRhdGFzZXQncyBbY29kZWJvb2tdKGh0dHBzOi8vZ2l0aHViLmNvbS9PeENHUlQvY292aWQtcG9saWN5LXRyYWNrZXIvYmxvYi9tYXN0ZXIvZG9jdW1lbnRhdGlvbi9jb2RlYm9vay5tZCksIHVuZGVyICJFMiwgZGVidC9jb250cmFjdCByZWxpZWYiLgoKVGhlIG1ldHJpYyBiZWxvdyBhaW1zIHRvIGNhcHR1cmUgYm90aCB0aGUgZHVyYXRpb24gYW5kIChyb3VnaGx5KSB0aGUgaW50ZW5zaXR5IG9mIHRoZSBkZWJ0L2NvbnRyYWN0IHJlbGllZiBwcm92aWRlZCBpbiBlYWNoIGp1cmlzZGljdGlvbi4gSXQncyBub3QgdGhlIHNhbWUgYXMgd2hhdCB3ZSB3YW50ZWQgKGRldGFpbHMgYXJlIGluIHRoZSBkb2N1bWVudCBsaW5rZWQgYWJvdmUpLCBidXQgdGhhdCdzIHdoYXQgSSBmb3VuZCBzbyBmYXIgaW4gYW4gb3JnYW5pc2VkIHdheS4KCmBgYHtyfQpkZWJ0X3JlbGllZiA8LSByZWFkLmNzdigiaHR0cHM6Ly9naXRodWIuY29tL094Q0dSVC9jb3ZpZC1wb2xpY3ktdHJhY2tlci9yYXcvbWFzdGVyL2RhdGEvdGltZXNlcmllcy9lMl9kZWJ0Y29udHJhY3RyZWxpZWYuY3N2IiwKICAgICAgICAgICAgICAgICAgICAgICAgbmEuc3RyaW5ncyA9ICIuIikKCkNDeUJfY291bnRyaWVzIDwtIHVuaXF1ZShFU1JCX0NDeUIkQ291bnRyeSkKZGVidF9yZWxpZWYgPC0gZGVidF9yZWxpZWYgJT4lIGZpbHRlcihYICVpbiUgQ0N5Ql9jb3VudHJpZXMpICU+JSBzZWxlY3QoLVguMSkKCmRlYnRfcmVsaWVmIDwtIHRpYmJsZShDb3VudHJ5ID0gZGVidF9yZWxpZWYkWCwKICAgICAgICAgICAgICAgICAgICAgIERlYnRfcmVsaWVmID0gZGVidF9yZWxpZWYgJT4lIHNlbGVjdCgtWCkgJT4lIHJvd1N1bXMobmEucm0gPSBUUlVFKSkKCmRlYnRfcmVsaWVmX3Bsb3QgPC0gZGVidF9yZWxpZWYgJT4lIAogIGdncGxvdChhZXMoeCA9IHJlb3JkZXIoQ291bnRyeSwgLURlYnRfcmVsaWVmKSwgeSA9IERlYnRfcmVsaWVmKSkgKwogIGdlb21fYmFyKHN0YXQgPSAiaWRlbnRpdHkiKSArCiAgZ2d0aXRsZSgiRGVidCByZWxpZWYgbWVhc3VyZXMgYnkgY291bnRyeSBpbiB0aGUgc2FtcGxlIikgKwogIHlsYWIoIkRlYnQgcmVsaWVmIHNjb3JlIikgKwogIHhsYWIoZWxlbWVudF9ibGFuaygpKSArCiAgdGhlbWUoYXhpcy50ZXh0Lng9ZWxlbWVudF90ZXh0KHNpemUgPSByZWwoMC43KSkpICsKICBzY2FsZV94X2Rpc2NyZXRlKGxhYmVscyA9IGZ1bmN0aW9uKGxhYmVscykgewogICAgc2FwcGx5KHNlcV9hbG9uZyhsYWJlbHMpLCBmdW5jdGlvbihpKSBwYXN0ZTAoaWZlbHNlKGkgJSUgMiA9PSAwLCAnJywgJ1xuJyksIGxhYmVsc1tpXSkpCiAgfSkKCmRlYnRfcmVsaWVmX3Bsb3QKYGBgCgoKIyBHb29nbGUgTW9iaWxpdHkKYGBge3IgTG9hZHMgR29vZ2xlIE1vYmlsaXR5IGRhdGF9Ckdvb2dsZU1vYmlsaXR5RGF0YXNldCA8LSBkYXRhLnRhYmxlKHJlYWQuY3N2KCJodHRwczovL3d3dy5nc3RhdGljLmNvbS9jb3ZpZDE5L21vYmlsaXR5L0dsb2JhbF9Nb2JpbGl0eV9SZXBvcnQuY3N2IiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdHJpbmdzQXNGYWN0b3JzID0gRkFMU0UpKQoKZXVyb3BlYW5fY291bnRyaWVzIDwtIGMoIkFUIiwgIyBBdXN0cmlhCiAgICAgICAgICAgICAgICAgICAgICAgICJCQSIsICMgQm9zbmlhIGFuZCBIZXplZ292aW5hCiAgICAgICAgICAgICAgICAgICAgICAgICJCRSIsICMgIEJlbGdpdW0KICAgICAgICAgICAgICAgICAgICAgICAgIkJHIiwgIyBCdWxnYXJpYQogICAgICAgICAgICAgICAgICAgICAgICAiQlkiLCAjIEJlbGFydXMKICAgICAgICAgICAgICAgICAgICAgICAgIkNIIiwgIyBTd2l0emVybGFuZAogICAgICAgICAgICAgICAgICAgICAgICAiQ1oiLCAjIEN6ZWNoaWEKICAgICAgICAgICAgICAgICAgICAgICAgIkRFIiwgIyBHZXJtYW55CiAgICAgICAgICAgICAgICAgICAgICAgICJESyIsICMgRGVubWFyawogICAgICAgICAgICAgICAgICAgICAgICAiRUUiLCAjIEVzdG9uaWEKICAgICAgICAgICAgICAgICAgICAgICAgIkVTIiwgIyBTcGFpbgogICAgICAgICAgICAgICAgICAgICAgICAiRkkiLCAjIEZpbmxhbmQKICAgICAgICAgICAgICAgICAgICAgICAgIkZSIiwgIyBGcmFuY2UKICAgICAgICAgICAgICAgICAgICAgICAgIkdCIiwgIyBVbml0ZWQgS2luZ2RvbQogICAgICAgICAgICAgICAgICAgICAgICAiR0UiLCAjIEdlb3JnaWEKICAgICAgICAgICAgICAgICAgICAgICAgIkdSIiwgIyBHcmVlY2UKICAgICAgICAgICAgICAgICAgICAgICAgIkhSIiwgIyBDcm9hdGlhCiAgICAgICAgICAgICAgICAgICAgICAgICJIVSIsICMgSHVuZ2FyeQogICAgICAgICAgICAgICAgICAgICAgICAiSUUiLCAjIElyZWxhbmQKICAgICAgICAgICAgICAgICAgICAgICAgIklUIiwgIyBJdGFseQogICAgICAgICAgICAgICAgICAgICAgICAiTEkiLCAjIExpZWNodGVuc3RlaW4KICAgICAgICAgICAgICAgICAgICAgICAgIkxUIiwgIyBMaXRodWFuaWEKICAgICAgICAgICAgICAgICAgICAgICAgIkxVIiwgIyBMdXhlbWJvdXJnCiAgICAgICAgICAgICAgICAgICAgICAgICJMViIsICMgTGF0dmlhCiAgICAgICAgICAgICAgICAgICAgICAgICJNRCIsICMgTW9sZG92YQogICAgICAgICAgICAgICAgICAgICAgICAiTUsiLCAjIE5vcnRoIE1hY2Vkb25pYQogICAgICAgICAgICAgICAgICAgICAgICAiTVQiLCAjIE1hbHRhCiAgICAgICAgICAgICAgICAgICAgICAgICJOTCIsICMgTmV0aGVybGFuZHMKICAgICAgICAgICAgICAgICAgICAgICAgIk5PIiwgIyBOb3J3YXkKICAgICAgICAgICAgICAgICAgICAgICAgIlBMIiwgIyBQb2xhbmQKICAgICAgICAgICAgICAgICAgICAgICAgIlBUIiwgIyBQb3J0dWdhbAogICAgICAgICAgICAgICAgICAgICAgICAiUk8iLCAjIFJvbWFuaWEKICAgICAgICAgICAgICAgICAgICAgICAgIlJTIiwgIyBTZXJiaWEKICAgICAgICAgICAgICAgICAgICAgICAgIlJVIiwgIyBSdXNzaWEKICAgICAgICAgICAgICAgICAgICAgICAgIlNFIiwgIyBTd2VkZW4KICAgICAgICAgICAgICAgICAgICAgICAgIlNJIiwgIyBTbG92ZW5pYQogICAgICAgICAgICAgICAgICAgICAgICAiU0siLCAjIFNsb3Zha2lhCiAgICAgICAgICAgICAgICAgICAgICAgICJVQSIpICMgVWtyYWluZQpHb29nbGVNb2JpbGl0eURhdGFzZXQgPC0gR29vZ2xlTW9iaWxpdHlEYXRhc2V0W2NvdW50cnlfcmVnaW9uX2NvZGUgJWluJSBldXJvcGVhbl9jb3VudHJpZXMgJiBzdWJfcmVnaW9uXzEgPT0gIiIsXQpHb29nbGVNb2JpbGl0eURhdGFzZXRbLCBkYXRlIDo9IGFzLlBPU0lYY3QocGFzdGUwKGRhdGUsICIgMDA6MDA6MDAiKSldCkdvb2dsZU1vYmlsaXR5RGF0YXNldCA8LSBHb29nbGVNb2JpbGl0eURhdGFzZXQgJT4lIAogIHNlbGVjdChjb3VudHJ5X3JlZ2lvbiwgCiAgICAgICAgIGRhdGUsIAogICAgICAgICByZXRhaWxfYW5kX3JlY3JlYXRpb25fcGVyY2VudF9jaGFuZ2VfZnJvbV9iYXNlbGluZSwKICAgICAgICAgZ3JvY2VyeV9hbmRfcGhhcm1hY3lfcGVyY2VudF9jaGFuZ2VfZnJvbV9iYXNlbGluZSwKICAgICAgICAgcGFya3NfcGVyY2VudF9jaGFuZ2VfZnJvbV9iYXNlbGluZSwKICAgICAgICAgdHJhbnNpdF9zdGF0aW9uc19wZXJjZW50X2NoYW5nZV9mcm9tX2Jhc2VsaW5lLAogICAgICAgICB3b3JrcGxhY2VzX3BlcmNlbnRfY2hhbmdlX2Zyb21fYmFzZWxpbmUsCiAgICAgICAgIHJlc2lkZW50aWFsX3BlcmNlbnRfY2hhbmdlX2Zyb21fYmFzZWxpbmUpICU+JSAKICBncm91cF9ieShjb3VudHJ5X3JlZ2lvbikgJT4lIAogIG5lc3QoKQoKR29vZ2xlTW9iaWxpdHlEYXRhc2V0IDwtIEdvb2dsZU1vYmlsaXR5RGF0YXNldCAlPiUgCiAgbXV0YXRlKGRhdGEgPSBkYXRhICU+JSBtYXAofiBwaXZvdF9sb25nZXIoLngsICFkYXRlLCBuYW1lc190byA9ICJtb2JpbGl0eV9jYXRlZ29yeSIsIHZhbHVlc190byA9ICJjaGFuZ2VfZnJvbV9iYXNlbGluZSIpKSkKCmBgYAoKCk5vdyBsZXQncyBwbG90IHRoZSBtb2JpbGl0eSBncmFwaCBmb3IgZWFjaCBjb3VudHJ5LgoKYGBge3IgR29vZ2xlIG1vYmlsaXR5IGNvdW50cnkgcGxvdHN9Cm1vYmlsaXR5X3Bsb3QgPC0gZnVuY3Rpb24oY291bnRyeSwgY291bnRyeV9kYXRhKSB7CiAgZ2dwbG90KGRhdGEgPSBjb3VudHJ5X2RhdGEsIGFlcyh4ID0gZGF0ZSwgeSA9IGNoYW5nZV9mcm9tX2Jhc2VsaW5lLCBjb2xvciA9IG1vYmlsaXR5X2NhdGVnb3J5KSkgKwogICAgZ2VvbV9saW5lKCkgKwogICAgZ2d0aXRsZShsYWJlbCA9IGNvdW50cnkpICsKICAgIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJib3R0b20iLAogICAgbGVnZW5kLnRleHQgPWVsZW1lbnRfdGV4dChzaXplID0gcmVsKDAuNSkpKSArCiAgICB5bGFiKCJDaGFuZ2UgZnJvbSBiYXNlbGluZSAoJSkiKSArCiAgICB4bGFiKGVsZW1lbnRfYmxhbmsoKSkKfQptb2JpbGl0eV9wbG90KEdvb2dsZU1vYmlsaXR5RGF0YXNldCRjb3VudHJ5X3JlZ2lvbltbMV1dLAogICAgICAgICAgICAgIEdvb2dsZU1vYmlsaXR5RGF0YXNldCRkYXRhW1sxXV0pCm1hcDIoR29vZ2xlTW9iaWxpdHlEYXRhc2V0JGNvdW50cnlfcmVnaW9uLCBHb29nbGVNb2JpbGl0eURhdGFzZXQkZGF0YSwgfiBtb2JpbGl0eV9wbG90KC54LCAueSkpCmBgYAoKCgoK