Set Up
library(data.table)
library(hector)
library(dplyr)
library(tidyr)
library(ggplot2)
BASE_DIR <- here::here()
theme_set(theme_bw())
Objective
Run Hector under net vs gross CO2 emissions to determine does it
really matter?
Run Hector Gross FFI
Emissions
ini_list <- list.files(system.file("input", package = "hector"), pattern = "ini", full.names = TRUE)
lapply(ini_list, function(x){
hc <- newcore(x, name = basename(gsub(pattern = "hector_|.ini", x = x, replacement = "")))
run(hc)
original_emissions <- fetchvars(hc, dates, vars = c(FFI_EMISSIONS(), DACCS_UPTAKE()))
emiss_to_add <- c(0, 0.1, 0.5, 1, 1.5, 4)
lapply(emiss_to_add, function(val){
hc2 <- newcore(x, name = basename(gsub(pattern = "hector_|.ini", x = x, replacement = "")))
# okay I think I can only set one variable at a time which is werid cause I think I do it all at
# once other places which might be bad news fuck
split(original_emissions, original_emissions$variable) %>%
lapply(function(xx){
setvar(core = hc2,
dates = xx[["year"]],
var = unique(xx[["variable"]]),
values = xx[["value"]] + val,
unit = unique(xx[["units"]]))
reset(hc2)
})
run(hc2)
out <- fetchvars(hc2, dates = dates, vars = vars)
out$type <- paste0("gross ", val)
return(out)
}) %>%
bind_rows() ->
single_scn_different_vals
return(single_scn_different_vals)
}) %>%
bind_rows() ->
gross_emission_ffi
When the 0 value is added to the ffi emissions we essentially running
the default net emissions. For a single SSP scenario we would expect all
the results (except for daccs and ffi) to be identical.
gross_emission_ffi %>%
filter(scenario == "ssp119") %>%
ggplot(aes(year, value, color = type)) +
geom_line() +
facet_wrap("variable", scales = "free") +
labs(title = "ssp119", y = NULL, x = NULL)

gross_emission_ffi %>%
filter(scenario == "ssp585") %>%
ggplot(aes(year, value, color = type)) +
geom_line() +
facet_wrap("variable", scales = "free") +
labs(title = "ssp585", y = NULL, x = NULL)

Doubble check that the net emissions are all the same as one another,
for each SSP the net emissions shoudl be the same.
gross_emission_ffi %>%
filter(variable %in% c(FFI_EMISSIONS(), DACCS_UPTAKE())) %>%
spread(variable, value) %>%
mutate(net = ffi_emissions - daccs_uptake) %>%
select(scenario, year, type, net) ->
net_emissions
net_emissions %>%
ggplot(aes(year, net, color = scenario, linetype = type)) +
geom_line() +
labs(title = "Comparison of the net ffi emissions per test run", x = NULL, y = NULL)

The non emission inputs do look the same but now check the actual
numbers, the only non-0 values should be daccs and ffi emissions.
gross_emission_ffi %>%
spread(type, value) ->
wide_emission_ffi
wide_emission_ffi %>%
select(-scenario, -year, -variable, -units) %>%
apply(MARGIN = 1, FUN = sd) ->
sd_values
wide_emission_ffi$diff <- sd_values
wide_emission_ffi %>%
filter(diff > 1e-8) %>%
pull(variable) %>%
unique()
[1] "daccs_uptake" "ffi_emissions"
So yes the ffi & daccs net and gross emissions are the same.
Run Hector Gross LUC
Emissions
ini_list <- list.files(system.file("input", package = "hector"), pattern = "ini", full.names = TRUE)
lapply(ini_list, function(x){
hc <- newcore(x, name = basename(gsub(pattern = "hector_|.ini", x = x, replacement = "")))
run(hc)
original_emissions <- fetchvars(hc, dates, vars = c(LUC_EMISSIONS(), LUC_UPTAKE()))
emiss_to_add <- c(0, 0.1, 0.5, 1, 1.5, 4)
lapply(emiss_to_add, function(val){
hc2 <- newcore(x, name = basename(gsub(pattern = "hector_|.ini", x = x, replacement = "")))
# okay I think I can only set one variable at a time which is werid cause I think I do it all at
# once other places which might be bad news fuck
split(original_emissions, original_emissions$variable) %>%
lapply(function(xx){
setvar(core = hc2,
dates = xx[["year"]],
var = unique(xx[["variable"]]),
values = xx[["value"]] + val,
unit = unique(xx[["units"]]))
reset(hc2)
})
run(hc2)
out <- fetchvars(hc2, dates = dates, vars = vars)
out$type <- paste0("gross ", val)
return(out)
}) %>%
bind_rows() ->
single_scn_different_vals
return(single_scn_different_vals)
}) %>%
bind_rows() ->
gross_emission_luc
When the 0 value is added to the luc emissions/uptake we essentially
running the default net emissions. For a single SSP scenario we would
expect all the results (except for emissions and uptake) to be
identical.
gross_emission_luc %>%
filter(scenario == "ssp119") %>%
ggplot(aes(year, value, color = type)) +
geom_line() +
facet_wrap("variable", scales = "free") +
labs(title = "ssp119", y = NULL, x = NULL)

gross_emission_luc %>%
filter(scenario == "ssp585") %>%
ggplot(aes(year, value, color = type)) +
geom_line() +
facet_wrap("variable", scales = "free") +
labs(title = "ssp585", y = NULL, x = NULL)

Hmm the fact that the veg c pools are different from one another
checks out intellectually, but is this a problem…
Double check that the net luc emissions/uptake are consistent for a
scenario pathway. So yes the runs are set up correctly with the net luc
emissions & uptake being the same.
gross_emission_luc %>%
filter(variable %in% c(LUC_EMISSIONS(), LUC_UPTAKE())) %>%
spread(variable, value) %>%
mutate(net = luc_emissions - luc_uptake) %>%
select(scenario, year, type, net) ->
net_emissions
net_emissions %>%
ggplot(aes(year, net, color = scenario, linetype = type)) +
geom_line() +
labs(title = "Comparison of the net luc emissions per test run", x = NULL, y = NULL)

Take a look at the Hector variables the only non-0 values should be
luc emissions and uptake, howevver that is not the case.
gross_emission_luc %>%
spread(type, value) ->
wide_emission_luc
wide_emission_luc %>%
select(-scenario, -year, -variable, -units) %>%
apply(MARGIN = 1, FUN = sd) ->
sd_values
wide_emission_luc$diff <- sd_values
wide_emission_luc %>%
filter(diff > 1e-8) %>%
pull(variable) %>%
unique()
[1] "luc_emissions" "luc_uptake" "CO2_concentration" "global_tas" "NBP" "RF_tot" "veg_c"
How much of a difference does this make on NBP, [CO2] and RF?
gross_emission_luc %>%
filter(type == "gross 0") %>%
select(scenario, year, variable, og_val = value) ->
original_output
gross_emission_luc %>%
filter(type != "gross 0") %>%
right_join(original_output) %>%
mutate(percent_dif = 100 * (og_val - value)/value) ->
percent_dif_df
What is the impact (percent change)?

So it looks like it is about a 2% change in global temperature and
[CO2] which eh it may or may not matter.
LS0tCnRpdGxlOiAiR3Jvc3MgdnMgTmV0IENPMiBlbWlzc2lvbnMiCm91dHB1dDoKICBodG1sX25vdGVib29rOgogICAgdG9jOiB5ZXMKICAgIHRvY19kZXB0aDogJzQnCiAgICB0b2NfZmxvYXQ6IHllcwogICAgbnVtYmVyX3NlY3Rpb25zOiB0cnVlCmRhdGU6ICJgciBmb3JtYXQoU3lzLnRpbWUoKSwgJyVkICVCLCAlWScpYCIKLS0tCgojIFNldCBVcCAKYGBge3Igc2V0dXAsIGluY2x1ZGU9RkFMU0V9CmtuaXRyOjpvcHRzX2NodW5rJHNldChlY2hvID0gVFJVRSwgZXJyb3IgPSBGQUxTRSwgbWVzc2FnZSA9IEZBTFNFKQojIHNlZSBodHRwczovL2Jvb2tkb3duLm9yZy95aWh1aS9ybWFya2Rvd24tY29va2Jvb2svIGZvciBtb3JlIGluZm8gb24gbWFya2Rvd25zCmBgYAoKYGBge3J9CmxpYnJhcnkoZGF0YS50YWJsZSkKbGlicmFyeShoZWN0b3IpCmxpYnJhcnkoZHBseXIpCmxpYnJhcnkodGlkeXIpCmxpYnJhcnkoZ2dwbG90MikKCkJBU0VfRElSIDwtIGhlcmU6OmhlcmUoKQoKdGhlbWVfc2V0KHRoZW1lX2J3KCkpCmBgYAoKIyMgT2JqZWN0aXZlIAoKUnVuIEhlY3RvciB1bmRlciBuZXQgdnMgZ3Jvc3MgQ08yIGVtaXNzaW9ucyB0byBkZXRlcm1pbmUgZG9lcyBpdCByZWFsbHkgbWF0dGVyPyAKCgojIFJ1biBIZWN0b3IgR3Jvc3MgRkZJIEVtaXNzaW9ucwoKYGBgYHtyfQppbmlfbGlzdCA8LSBsaXN0LmZpbGVzKHN5c3RlbS5maWxlKCJpbnB1dCIsIHBhY2thZ2UgPSAiaGVjdG9yIiksIHBhdHRlcm4gPSAiaW5pIiwgZnVsbC5uYW1lcyA9IFRSVUUpCgpsYXBwbHkoaW5pX2xpc3QsIGZ1bmN0aW9uKHgpewogIGhjIDwtIG5ld2NvcmUoeCwgbmFtZSA9IGJhc2VuYW1lKGdzdWIocGF0dGVybiA9ICJoZWN0b3JffC5pbmkiLCB4ID0geCwgcmVwbGFjZW1lbnQgPSAiIikpKQogIHJ1bihoYykKICAKICBvcmlnaW5hbF9lbWlzc2lvbnMgPC0gZmV0Y2h2YXJzKGhjLCBkYXRlcywgdmFycyA9IGMoRkZJX0VNSVNTSU9OUygpLCBEQUNDU19VUFRBS0UoKSkpCiAgCiAgZW1pc3NfdG9fYWRkIDwtIGMoMCwgMC4xLCAwLjUsIDEsIDEuNSwgNCkKICAKICBsYXBwbHkoZW1pc3NfdG9fYWRkLCBmdW5jdGlvbih2YWwpewogICAgaGMyIDwtIG5ld2NvcmUoeCwgbmFtZSA9IGJhc2VuYW1lKGdzdWIocGF0dGVybiA9ICJoZWN0b3JffC5pbmkiLCB4ID0geCwgcmVwbGFjZW1lbnQgPSAiIikpKQogICAgCiAgICAjIG9rYXkgSSB0aGluayBJIGNhbiBvbmx5IHNldCBvbmUgdmFyaWFibGUgYXQgYSB0aW1lIHdoaWNoIGlzIHdlcmlkIGNhdXNlIEkgdGhpbmsgSSBkbyBpdCBhbGwgYXQgCiAgICAjIG9uY2Ugb3RoZXIgcGxhY2VzIHdoaWNoIG1pZ2h0IGJlIGJhZCBuZXdzIGZ1Y2sgCiAgICBzcGxpdChvcmlnaW5hbF9lbWlzc2lvbnMsIG9yaWdpbmFsX2VtaXNzaW9ucyR2YXJpYWJsZSkgJT4lIAogICAgICBsYXBwbHkoZnVuY3Rpb24oeHgpewogICAgICAgIHNldHZhcihjb3JlID0gaGMyLCAKICAgICAgICAgICAgICAgZGF0ZXMgPSB4eFtbInllYXIiXV0sCiAgICAgICAgICAgICAgIHZhciAgPSB1bmlxdWUoeHhbWyJ2YXJpYWJsZSJdXSksIAogICAgICAgICAgICAgICB2YWx1ZXMgPSB4eFtbInZhbHVlIl1dICsgdmFsLCAKICAgICAgICAgICAgICAgdW5pdCA9ICB1bmlxdWUoeHhbWyJ1bml0cyJdXSkpCiAgICAgICAgcmVzZXQoaGMyKQogICAgICB9KQogICAgCiAgICBydW4oaGMyKQogICAgCiAgICBvdXQgPC0gZmV0Y2h2YXJzKGhjMiwgZGF0ZXMgPSBkYXRlcywgdmFycyA9IHZhcnMpCiAgICBvdXQkdHlwZSA8LSBwYXN0ZTAoImdyb3NzICIsIHZhbCkKICAgIHJldHVybihvdXQpCiAgfSkgJT4lICAKICAgIGJpbmRfcm93cygpIC0+IAogICAgc2luZ2xlX3Njbl9kaWZmZXJlbnRfdmFscwogIAogIHJldHVybihzaW5nbGVfc2NuX2RpZmZlcmVudF92YWxzKQogIAp9KSAlPiUgCiAgYmluZF9yb3dzKCkgLT4gCiAgZ3Jvc3NfZW1pc3Npb25fZmZpCgpgYGBgCgpXaGVuIHRoZSAwIHZhbHVlIGlzIGFkZGVkIHRvIHRoZSBmZmkgZW1pc3Npb25zIHdlIGVzc2VudGlhbGx5IHJ1bm5pbmcgdGhlIGRlZmF1bHQgbmV0IGVtaXNzaW9ucy4gRm9yIGEgc2luZ2xlIFNTUCBzY2VuYXJpbyB3ZSB3b3VsZCBleHBlY3QgYWxsIHRoZSByZXN1bHRzIChleGNlcHQgZm9yIGRhY2NzIGFuZCBmZmkpIHRvIGJlIGlkZW50aWNhbC4gCgpgYGB7cn0KZ3Jvc3NfZW1pc3Npb25fZmZpICU+JSAKICBmaWx0ZXIoc2NlbmFyaW8gPT0gInNzcDExOSIpICU+JSAKICBnZ3Bsb3QoYWVzKHllYXIsIHZhbHVlLCBjb2xvciA9IHR5cGUpKSArIAogIGdlb21fbGluZSgpICsKICBmYWNldF93cmFwKCJ2YXJpYWJsZSIsIHNjYWxlcyA9ICJmcmVlIikgKyAKICBsYWJzKHRpdGxlID0gInNzcDExOSIsIHkgPSBOVUxMLCB4ID0gTlVMTCkKYGBgCgpgYGB7cn0KZ3Jvc3NfZW1pc3Npb25fZmZpICU+JSAKICBmaWx0ZXIoc2NlbmFyaW8gPT0gInNzcDU4NSIpICU+JSAKICBnZ3Bsb3QoYWVzKHllYXIsIHZhbHVlLCBjb2xvciA9IHR5cGUpKSArIAogIGdlb21fbGluZSgpICsKICBmYWNldF93cmFwKCJ2YXJpYWJsZSIsIHNjYWxlcyA9ICJmcmVlIikgKyAKICBsYWJzKHRpdGxlID0gInNzcDU4NSIsIHkgPSBOVUxMLCB4ID0gTlVMTCkKYGBgCgpEb3ViYmxlIGNoZWNrIHRoYXQgdGhlIG5ldCBlbWlzc2lvbnMgYXJlIGFsbCB0aGUgc2FtZSBhcyBvbmUgYW5vdGhlciwgZm9yIGVhY2ggU1NQIHRoZSBuZXQgZW1pc3Npb25zIHNob3VkbCBiZSB0aGUgc2FtZS4gCgpgYGB7cn0KZ3Jvc3NfZW1pc3Npb25fZmZpICU+JQogIGZpbHRlcih2YXJpYWJsZSAlaW4lIGMoRkZJX0VNSVNTSU9OUygpLCBEQUNDU19VUFRBS0UoKSkpICU+JSAKICBzcHJlYWQodmFyaWFibGUsIHZhbHVlKSAlPiUgCiAgbXV0YXRlKG5ldCA9IGZmaV9lbWlzc2lvbnMgLSBkYWNjc191cHRha2UpICU+JSAKICBzZWxlY3Qoc2NlbmFyaW8sIHllYXIsIHR5cGUsIG5ldCkgLT4gCiAgbmV0X2VtaXNzaW9ucyAKCm5ldF9lbWlzc2lvbnMgJT4lIAogIGdncGxvdChhZXMoeWVhciwgbmV0LCBjb2xvciA9IHNjZW5hcmlvLCBsaW5ldHlwZSA9IHR5cGUpKSArIAogIGdlb21fbGluZSgpICsgCiAgbGFicyh0aXRsZSA9ICJDb21wYXJpc29uIG9mIHRoZSBuZXQgZmZpIGVtaXNzaW9ucyBwZXIgdGVzdCBydW4iLCB4ID0gTlVMTCwgeSA9IE5VTEwpCmBgYAoKClRoZSBub24gZW1pc3Npb24gaW5wdXRzIGRvIGxvb2sgdGhlIHNhbWUgYnV0IG5vdyBjaGVjayB0aGUgYWN0dWFsIG51bWJlcnMsIHRoZSBvbmx5IG5vbi0wIHZhbHVlcyBzaG91bGQgYmUgZGFjY3MgYW5kIGZmaSBlbWlzc2lvbnMuIAoKYGBge3J9Cmdyb3NzX2VtaXNzaW9uX2ZmaSAlPiUKICBzcHJlYWQodHlwZSwgdmFsdWUpIC0+IAogIHdpZGVfZW1pc3Npb25fZmZpCgp3aWRlX2VtaXNzaW9uX2ZmaSAlPiUgCiAgc2VsZWN0KC1zY2VuYXJpbywgLXllYXIsIC12YXJpYWJsZSwgLXVuaXRzKSAlPiUgCiAgYXBwbHkoTUFSR0lOID0gMSwgRlVOID0gc2QpIC0+IAogIHNkX3ZhbHVlcwoKd2lkZV9lbWlzc2lvbl9mZmkkZGlmZiA8LSBzZF92YWx1ZXMKCndpZGVfZW1pc3Npb25fZmZpICU+JSAKICBmaWx0ZXIoZGlmZiA+IDFlLTgpICU+JSAKICBwdWxsKHZhcmlhYmxlKSAlPiUgCiAgdW5pcXVlKCkKYGBgCgoKU28geWVzIHRoZSBmZmkgJiBkYWNjcyBuZXQgYW5kIGdyb3NzIGVtaXNzaW9ucyBhcmUgdGhlIHNhbWUuICAKCgoKIyBSdW4gSGVjdG9yIEdyb3NzIExVQyBFbWlzc2lvbnMKCgpgYGBge3J9CmluaV9saXN0IDwtIGxpc3QuZmlsZXMoc3lzdGVtLmZpbGUoImlucHV0IiwgcGFja2FnZSA9ICJoZWN0b3IiKSwgcGF0dGVybiA9ICJpbmkiLCBmdWxsLm5hbWVzID0gVFJVRSkKCmxhcHBseShpbmlfbGlzdCwgZnVuY3Rpb24oeCl7CiAgaGMgPC0gbmV3Y29yZSh4LCBuYW1lID0gYmFzZW5hbWUoZ3N1YihwYXR0ZXJuID0gImhlY3Rvcl98LmluaSIsIHggPSB4LCByZXBsYWNlbWVudCA9ICIiKSkpCiAgcnVuKGhjKQogIAogIG9yaWdpbmFsX2VtaXNzaW9ucyA8LSBmZXRjaHZhcnMoaGMsIGRhdGVzLCB2YXJzID0gYyhMVUNfRU1JU1NJT05TKCksIExVQ19VUFRBS0UoKSkpCiAgCiAgZW1pc3NfdG9fYWRkIDwtIGMoMCwgMC4xLCAwLjUsIDEsIDEuNSwgNCkKICAKICBsYXBwbHkoZW1pc3NfdG9fYWRkLCBmdW5jdGlvbih2YWwpewogICAgaGMyIDwtIG5ld2NvcmUoeCwgbmFtZSA9IGJhc2VuYW1lKGdzdWIocGF0dGVybiA9ICJoZWN0b3JffC5pbmkiLCB4ID0geCwgcmVwbGFjZW1lbnQgPSAiIikpKQogICAgCiAgICAjIG9rYXkgSSB0aGluayBJIGNhbiBvbmx5IHNldCBvbmUgdmFyaWFibGUgYXQgYSB0aW1lIHdoaWNoIGlzIHdlcmlkIGNhdXNlIEkgdGhpbmsgSSBkbyBpdCBhbGwgYXQgCiAgICAjIG9uY2Ugb3RoZXIgcGxhY2VzIHdoaWNoIG1pZ2h0IGJlIGJhZCBuZXdzIGZ1Y2sgCiAgICBzcGxpdChvcmlnaW5hbF9lbWlzc2lvbnMsIG9yaWdpbmFsX2VtaXNzaW9ucyR2YXJpYWJsZSkgJT4lIAogICAgICBsYXBwbHkoZnVuY3Rpb24oeHgpewogICAgICAgIHNldHZhcihjb3JlID0gaGMyLCAKICAgICAgICAgICAgICAgZGF0ZXMgPSB4eFtbInllYXIiXV0sCiAgICAgICAgICAgICAgIHZhciAgPSB1bmlxdWUoeHhbWyJ2YXJpYWJsZSJdXSksIAogICAgICAgICAgICAgICB2YWx1ZXMgPSB4eFtbInZhbHVlIl1dICsgdmFsLCAKICAgICAgICAgICAgICAgdW5pdCA9ICB1bmlxdWUoeHhbWyJ1bml0cyJdXSkpCiAgICAgICAgcmVzZXQoaGMyKQogICAgICB9KQogICAgCiAgICBydW4oaGMyKQogICAgCiAgICBvdXQgPC0gZmV0Y2h2YXJzKGhjMiwgZGF0ZXMgPSBkYXRlcywgdmFycyA9IHZhcnMpCiAgICBvdXQkdHlwZSA8LSBwYXN0ZTAoImdyb3NzICIsIHZhbCkKICAgIHJldHVybihvdXQpCiAgfSkgJT4lICAKICAgIGJpbmRfcm93cygpIC0+IAogICAgc2luZ2xlX3Njbl9kaWZmZXJlbnRfdmFscwogIAogIHJldHVybihzaW5nbGVfc2NuX2RpZmZlcmVudF92YWxzKQogIAp9KSAlPiUgCiAgYmluZF9yb3dzKCkgLT4gCiAgZ3Jvc3NfZW1pc3Npb25fbHVjCgpgYGBgCgoKV2hlbiB0aGUgMCB2YWx1ZSBpcyBhZGRlZCB0byB0aGUgbHVjIGVtaXNzaW9ucy91cHRha2Ugd2UgZXNzZW50aWFsbHkgcnVubmluZyB0aGUgZGVmYXVsdCBuZXQgZW1pc3Npb25zLiBGb3IgYSBzaW5nbGUgU1NQIHNjZW5hcmlvIHdlIHdvdWxkIGV4cGVjdCBhbGwgdGhlIHJlc3VsdHMgKGV4Y2VwdCBmb3IgZW1pc3Npb25zIGFuZCB1cHRha2UpIHRvIGJlIGlkZW50aWNhbC4gCgpgYGB7cn0KZ3Jvc3NfZW1pc3Npb25fbHVjICU+JSAKICBmaWx0ZXIoc2NlbmFyaW8gPT0gInNzcDExOSIpICU+JSAKICBnZ3Bsb3QoYWVzKHllYXIsIHZhbHVlLCBjb2xvciA9IHR5cGUpKSArIAogIGdlb21fbGluZSgpICsKICBmYWNldF93cmFwKCJ2YXJpYWJsZSIsIHNjYWxlcyA9ICJmcmVlIikgKyAKICBsYWJzKHRpdGxlID0gInNzcDExOSIsIHkgPSBOVUxMLCB4ID0gTlVMTCkKYGBgCgpgYGB7cn0KZ3Jvc3NfZW1pc3Npb25fbHVjICU+JSAKICBmaWx0ZXIoc2NlbmFyaW8gPT0gInNzcDU4NSIpICU+JSAKICBnZ3Bsb3QoYWVzKHllYXIsIHZhbHVlLCBjb2xvciA9IHR5cGUpKSArIAogIGdlb21fbGluZSgpICsKICBmYWNldF93cmFwKCJ2YXJpYWJsZSIsIHNjYWxlcyA9ICJmcmVlIikgKyAKICBsYWJzKHRpdGxlID0gInNzcDU4NSIsIHkgPSBOVUxMLCB4ID0gTlVMTCkKYGBgCgpIbW0gdGhlIGZhY3QgdGhhdCB0aGUgdmVnIGMgcG9vbHMgYXJlIGRpZmZlcmVudCBmcm9tIG9uZSBhbm90aGVyIGNoZWNrcyBvdXQgaW50ZWxsZWN0dWFsbHksIGJ1dCBpcyB0aGlzIGEgcHJvYmxlbS4uLiAKCgoKRG91YmxlIGNoZWNrIHRoYXQgdGhlIG5ldCBsdWMgZW1pc3Npb25zL3VwdGFrZSBhcmUgY29uc2lzdGVudCBmb3IgYSBzY2VuYXJpbyBwYXRod2F5LiBTbyB5ZXMgdGhlIHJ1bnMgYXJlIHNldCB1cCBjb3JyZWN0bHkgd2l0aCB0aGUgbmV0IGx1YyBlbWlzc2lvbnMgJiB1cHRha2UgYmVpbmcgdGhlIHNhbWUuIAoKYGBge3J9Cmdyb3NzX2VtaXNzaW9uX2x1YyAlPiUKICBmaWx0ZXIodmFyaWFibGUgJWluJSBjKExVQ19FTUlTU0lPTlMoKSwgTFVDX1VQVEFLRSgpKSkgJT4lIAogIHNwcmVhZCh2YXJpYWJsZSwgdmFsdWUpICU+JSAKICBtdXRhdGUobmV0ID0gbHVjX2VtaXNzaW9ucyAtIGx1Y191cHRha2UpICU+JSAKICBzZWxlY3Qoc2NlbmFyaW8sIHllYXIsIHR5cGUsIG5ldCkgLT4gCiAgbmV0X2VtaXNzaW9ucyAKCm5ldF9lbWlzc2lvbnMgJT4lIAogIGdncGxvdChhZXMoeWVhciwgbmV0LCBjb2xvciA9IHNjZW5hcmlvLCBsaW5ldHlwZSA9IHR5cGUpKSArIAogIGdlb21fbGluZSgpICsgCiAgbGFicyh0aXRsZSA9ICJDb21wYXJpc29uIG9mIHRoZSBuZXQgbHVjIGVtaXNzaW9ucyBwZXIgdGVzdCBydW4iLCB4ID0gTlVMTCwgeSA9IE5VTEwpCmBgYAoKVGFrZSBhIGxvb2sgYXQgdGhlIEhlY3RvciB2YXJpYWJsZXMgdGhlIG9ubHkgbm9uLTAgdmFsdWVzIHNob3VsZCBiZSBsdWMgZW1pc3Npb25zIGFuZCB1cHRha2UsIGhvd2V2dmVyIHRoYXQgaXMgbm90IHRoZSBjYXNlLiAKCmBgYHtyfQpncm9zc19lbWlzc2lvbl9sdWMgJT4lCiAgc3ByZWFkKHR5cGUsIHZhbHVlKSAtPiAKICB3aWRlX2VtaXNzaW9uX2x1YwoKd2lkZV9lbWlzc2lvbl9sdWMgJT4lIAogIHNlbGVjdCgtc2NlbmFyaW8sIC15ZWFyLCAtdmFyaWFibGUsIC11bml0cykgJT4lIAogIGFwcGx5KE1BUkdJTiA9IDEsIEZVTiA9IHNkKSAtPiAKICBzZF92YWx1ZXMKCndpZGVfZW1pc3Npb25fbHVjJGRpZmYgPC0gc2RfdmFsdWVzCgp3aWRlX2VtaXNzaW9uX2x1YyAlPiUgCiAgZmlsdGVyKGRpZmYgPiAxZS04KSAlPiUgCiAgcHVsbCh2YXJpYWJsZSkgJT4lIAogIHVuaXF1ZSgpCmBgYAoKSG93IG11Y2ggb2YgYSBkaWZmZXJlbmNlIGRvZXMgdGhpcyBtYWtlIG9uIE5CUCwgW0NPMl0gYW5kIFJGPyAKCgpgYGB7cn0KCmdyb3NzX2VtaXNzaW9uX2x1YyAlPiUgCiAgZmlsdGVyKHR5cGUgPT0gImdyb3NzIDAiKSAlPiUgCiAgc2VsZWN0KHNjZW5hcmlvLCB5ZWFyLCB2YXJpYWJsZSwgb2dfdmFsID0gdmFsdWUpIC0+IAogIG9yaWdpbmFsX291dHB1dAoKZ3Jvc3NfZW1pc3Npb25fbHVjICU+JSAKICBmaWx0ZXIodHlwZSAhPSAiZ3Jvc3MgMCIpICU+JQogIHJpZ2h0X2pvaW4ob3JpZ2luYWxfb3V0cHV0KSAlPiUgCiAgbXV0YXRlKHBlcmNlbnRfZGlmID0gMTAwICogKG9nX3ZhbCAtIHZhbHVlKS92YWx1ZSkgLT4gCiAgcGVyY2VudF9kaWZfZGYKYGBgCgoKV2hhdCBpcyB0aGUgaW1wYWN0IChwZXJjZW50IGNoYW5nZSk/CgpgYGB7cn0KcGVyY2VudF9kaWZfZGYgJT4lIAogIGZpbHRlcih2YXJpYWJsZSAlaW4lIGMoQ09OQ0VOVFJBVElPTlNfQ08yKCksIEdMT0JBTF9UQVMoKSwgTkJQKCkpKSAlPiUgCiAgZmlsdGVyKGFicyhwZXJjZW50X2RpZikgPCA1MCkgJT4lIAogIGZpbHRlcih5ZWFyID4gMjAyMCkgJT4lIAogIGdncGxvdChhZXMoeWVhciwgcGVyY2VudF9kaWYsIGNvbG9yID0gc2NlbmFyaW8pKSArIAogIGdlb21fcG9pbnQoKSArCiAgZmFjZXRfd3JhcCgidmFyaWFibGUiLCBzY2FsZXMgPSAiZnJlZSIpICsgCiAgbGFicyh5ID0gIiUgZGlmZmVyZW5jZSBmcm9tIG9yaWdpbmFsIG5ldCBlbWlzc2lvbnMgcGF0aHdheSIpIApgYGAKClNvIGl0IGxvb2tzIGxpa2UgaXQgaXMgYWJvdXQgYSAyJSBjaGFuZ2UgaW4gZ2xvYmFsIHRlbXBlcmF0dXJlIGFuZCBbQ08yXSB3aGljaCBlaCBpdCBtYXkgb3IgbWF5IG5vdCBtYXR0ZXIuIAo=