Basic usage

Creating a Hector core

library(hector)
library(ggplot2)
library(ggthemes)
inifile <- system.file('input/hector_rcp45.ini', package='hector', mustWork=TRUE)
hcore <- newcore(inifile, suppresslogging=TRUE, name='RCP45')
print(hcore)
Hector core:    RCP45
Start date: 1745
End date:   2300
Current date:   1745
Input file: /Users/link593/Library/R/3.3/library/hector/input/hector_rcp45.ini

Running Hector

run(hcore, 2100)
Hector core:    RCP45
Start date: 1745
End date:   2300
Current date:   2100
Input file: /Users/link593/Library/R/3.3/library/hector/input/hector_rcp45.ini

Geting data

hdata <- fetchvars(hcore, 1990:2100, c(ATMOSPHERIC_CO2(), GLOBAL_TEMP(), RF_TOTAL()))
ggplot(data=hdata, aes(x=year, y=value)) + geom_line(col="darkgrey", size=1.1) + facet_wrap(~variable, scales='free_y') + 
    theme_solarized(light = TRUE)

The core and the date are mandatory. The list of variables is optional. If you don’t specify it, a default set is fetched. You can change that default by setting the hector.default.fetchvars option. There is also an optional scenario argument that sets the value of the scenario column. If you don’t supply it, the name of the hector core is used.

Cleanup

Hector cores will automatically be cleaned up when they are garbage collected, but you can shut them down manually if you wish.

shutdown(hcore)
Hector core (INACTIVE)

Multiple Hector cores

Cores are separate from one another and can be run independently.

inifile45 <- system.file('input/hector_rcp45.ini', package='hector', mustWork=TRUE)
inifile85 <- system.file('input/hector_rcp85.ini', package='hector', mustWork=TRUE)
hcore45 <- newcore(inifile45, suppresslogging=TRUE, name='RCP45')
hcore85 <- newcore(inifile85, suppresslogging=TRUE, name='RCP85')
invisible(run(hcore45, 2100))
getdate(hcore45)
[1] 2100
getdate(hcore85)
[1] 1745

The results from several runs can easily be put together for comparison.

invisible(run(hcore85, 2100))
hdata45 <- fetchvars(hcore45, 1990:2100)                  # default vars
hdata85 <- fetchvars(hcore85, 1990:2100)
hdata <- rbind(hdata45, hdata85)
ggplot(data=hdata, aes(x=year, y=value, color=scenario)) + geom_line() + 
    facet_wrap(~variable, scales='free_y') + 
    theme_solarized(light = TRUE)

Intermediate usage

Reset a core to an earlier date

reset(hcore85)
Hector core:    RCP85
Start date: 1745
End date:   2300
Current date:   1745
Input file: /Users/link593/Library/R/3.3/library/hector/input/hector_rcp85.ini

Rerunning it should produce the same values.

invisible(run(hcore85, 2100))
hdata85_new <- fetchvars(hcore85, 1990:2100)
all.equal(hdata85, hdata85_new)
[1] TRUE

Set a custom emissions pathway

ffi85 <- fetchvars(hcore85, 2000:2100, FFI_EMISSIONS())
invisible(reset(hcore85))                               # Without a year specified, resets to the beginning
ffinew <- ffi85$value * 0.5
setvar(hcore85, ffi85$year, FFI_EMISSIONS(), ffinew, as.character(ffi85$units[1]))
invisible(run(hcore85, 2100))
hdata_lo <- fetchvars(hcore85, 1990:2100, scenario='Low_Emiss')
hdata <- rbind(hdata45, hdata85, hdata_lo)
ggplot(data=hdata, aes(x=year, y=value, color=scenario)) + geom_line() + 
    facet_wrap(~variable, scales='free_y') + 
    theme_solarized(light = TRUE)

The hector core remembers changes like this, so we’ll shut it down so we don’t accidentally use it again.

shutdown(hcore85)
Hector core (INACTIVE)

Changing model parameters

hcore85_lo_ecs <- newcore(inifile85, suppresslogging=TRUE, name='RCP85_low_ecs')
setvar(hcore85_lo_ecs, NA, ECS(), 2.5, 'degC')
reset(hcore85_lo_ecs)
Hector core:    RCP85_low_ecs
Start date: 1745
End date:   2300
Current date:   1745
Input file: /Users/link593/Library/R/3.3/library/hector/input/hector_rcp85.ini
run(hcore85_lo_ecs, 2100)
Hector core:    RCP85_low_ecs
Start date: 1745
End date:   2300
Current date:   2100
Input file: /Users/link593/Library/R/3.3/library/hector/input/hector_rcp85.ini
hdata85_low_ecs <- fetchvars(hcore85_lo_ecs, 1990:2100)
hdata <- rbind(hdata45, hdata85, hdata85_low_ecs)
ggplot(data=hdata, aes(x=year, y=value, color=scenario)) + geom_line() + 
    facet_wrap(~variable, scales='free_y') + 
    theme_solarized(light = TRUE)

Caution: You must reset a hector core to the beginning of the simulation (i.e., with no year argument) after changing a model parameter. This reruns the initialization and spinup, both of which are needed for Hector to use the new parameters correctly.

Advanced usage

When combined with other R packages Hector can be very powerful. Here’s an example where we search for an emissions pathway the produces a specified (constant) atmospheric methane concentration. Note: If you use Hector in an algorithm that will run the model many times, you will probably want to turn off the logging using the suppresslogging argument to newcore.

hector_inifile <- file.path(system.file('input', package='hector'), 'hector_rcp60.ini')
hcore_solv <- newcore(hector_inifile, suppresslogging=TRUE)
run(hcore_solv, 1999)
Hector core:    unnamed hector core
Start date: 1745
End date:   2300
Current date:   1999
Input file: /Users/link593/Library/R/3.3/library/hector/input/hector_rcp60.ini

We will need a target function for our solver.
Caution: a function created this way will not be thread safe because the hector core stores persistent data in its internal data structures. If you try to use something like this in a parallel algorithm, you will have to find a way for each thread to have its own private hector core.

mktargfun <- function(targlevel, hcore) {
    function(emiss){
        setvar(hcore, 2000:2100, EMISSIONS_CH4(), emiss, "Tg CH4")
        reset(hcore, 1999)
        run(hcore, 2100)
        hout <- fetchvars(hcore, 2000:2100, ATMOSPHERIC_CH4())
        ## return the difference between the target and the actual
        hout$value - targlevel
    }
}
f <- mktargfun(1820, hcore_solv)
initguess <- rep(300.0, times=101)  # 2000:2001 includes both endpoints
slv <- nleqslv::nleqslv(initguess, f, method="Broyden")
ch4emiss <- slv$x
pltdata <- data.frame(year=2000:2100, ch4_emiss=ch4emiss)
ggplot(data=pltdata, aes(x=year, y=ch4_emiss)) + geom_line(col="darkgrey", size=1.25) + 
    theme_solarized(light = TRUE)

reset(hcore_solv, 1999)
Hector core:    unnamed hector core
Start date: 1745
End date:   2300
Current date:   1999
Input file: /Users/link593/Library/R/3.3/library/hector/input/hector_rcp60.ini
setvar(hcore_solv, 2000:2100, EMISSIONS_CH4(), ch4emiss, "Tg CH4")
run(hcore_solv, 2100)
Hector core:    unnamed hector core
Start date: 1745
End date:   2300
Current date:   2100
Input file: /Users/link593/Library/R/3.3/library/hector/input/hector_rcp60.ini
ch4conc <- fetchvars(hcore_solv, 2000:2100, ATMOSPHERIC_CH4())
ggplot(data=ch4conc, aes(x=year, y=value)) + geom_line(col='darkgrey', size=1.25) + theme_solarized(light=TRUE) + ylim(1800,1830)

LS0tCnRpdGxlOiAiUiBJbnRlcmZhY2UgZm9yIEhlY3RvciIKb3V0cHV0OiBodG1sX25vdGVib29rCi0tLQoKIyMgQmFzaWMgdXNhZ2UKCiMjIyBDcmVhdGluZyBhIEhlY3RvciBjb3JlCgpgYGB7cn0KbGlicmFyeShoZWN0b3IpCmxpYnJhcnkoZ2dwbG90MikKbGlicmFyeShnZ3RoZW1lcykKaW5pZmlsZSA8LSBzeXN0ZW0uZmlsZSgnaW5wdXQvaGVjdG9yX3JjcDQ1LmluaScsIHBhY2thZ2U9J2hlY3RvcicsIG11c3RXb3JrPVRSVUUpCmhjb3JlIDwtIG5ld2NvcmUoaW5pZmlsZSwgc3VwcHJlc3Nsb2dnaW5nPVRSVUUsIG5hbWU9J1JDUDQ1JykKcHJpbnQoaGNvcmUpCmBgYAoKIyMjIFJ1bm5pbmcgSGVjdG9yCgpgYGB7cn0KcnVuKGhjb3JlLCAyMTAwKQpgYGAKCiMjIyBHZXRpbmcgZGF0YQoKYGBge3J9CmhkYXRhIDwtIGZldGNodmFycyhoY29yZSwgMTk5MDoyMTAwLCBjKEFUTU9TUEhFUklDX0NPMigpLCBHTE9CQUxfVEVNUCgpLCBSRl9UT1RBTCgpKSkKZ2dwbG90KGRhdGE9aGRhdGEsIGFlcyh4PXllYXIsIHk9dmFsdWUpKSArIGdlb21fbGluZShjb2w9ImRhcmtncmV5Iiwgc2l6ZT0xLjEpICsgZmFjZXRfd3JhcCh+dmFyaWFibGUsIHNjYWxlcz0nZnJlZV95JykgKyAKICAgIHRoZW1lX3NvbGFyaXplZChsaWdodCA9IFRSVUUpCmBgYApUaGUgY29yZSBhbmQgdGhlIGRhdGUgYXJlIG1hbmRhdG9yeS4gIFRoZSBsaXN0IG9mIHZhcmlhYmxlcyBpcyBvcHRpb25hbC4gIElmIHlvdSBkb24ndCBzcGVjaWZ5IGl0LCBhIGRlZmF1bHQgc2V0CmlzIGZldGNoZWQuICBZb3UgY2FuIGNoYW5nZSB0aGF0IGRlZmF1bHQgYnkgc2V0dGluZyB0aGUgYGhlY3Rvci5kZWZhdWx0LmZldGNodmFyc2Agb3B0aW9uLiAgVGhlcmUgaXMgYWxzbyBhbiBvcHRpb25hbApgc2NlbmFyaW9gIGFyZ3VtZW50IHRoYXQgc2V0cyB0aGUgdmFsdWUgb2YgdGhlIHNjZW5hcmlvIGNvbHVtbi4gIElmIHlvdSBkb24ndCBzdXBwbHkgaXQsIHRoZSBuYW1lIG9mIHRoZSBoZWN0b3IKY29yZSBpcyB1c2VkLgoKIyMjIENsZWFudXAKCkhlY3RvciBjb3JlcyB3aWxsIGF1dG9tYXRpY2FsbHkgYmUgY2xlYW5lZCB1cCB3aGVuIHRoZXkgYXJlIGdhcmJhZ2UgY29sbGVjdGVkLCBidXQgeW91IGNhbiBzaHV0IHRoZW0gZG93biBtYW51YWxseQppZiB5b3Ugd2lzaC4KYGBge3J9CnNodXRkb3duKGhjb3JlKQpgYGAKCiMjIyBNdWx0aXBsZSBIZWN0b3IgY29yZXMKCkNvcmVzIGFyZSBzZXBhcmF0ZSBmcm9tIG9uZSBhbm90aGVyIGFuZCBjYW4gYmUgcnVuIGluZGVwZW5kZW50bHkuCmBgYHtyfQppbmlmaWxlNDUgPC0gc3lzdGVtLmZpbGUoJ2lucHV0L2hlY3Rvcl9yY3A0NS5pbmknLCBwYWNrYWdlPSdoZWN0b3InLCBtdXN0V29yaz1UUlVFKQppbmlmaWxlODUgPC0gc3lzdGVtLmZpbGUoJ2lucHV0L2hlY3Rvcl9yY3A4NS5pbmknLCBwYWNrYWdlPSdoZWN0b3InLCBtdXN0V29yaz1UUlVFKQpoY29yZTQ1IDwtIG5ld2NvcmUoaW5pZmlsZTQ1LCBzdXBwcmVzc2xvZ2dpbmc9VFJVRSwgbmFtZT0nUkNQNDUnKQpoY29yZTg1IDwtIG5ld2NvcmUoaW5pZmlsZTg1LCBzdXBwcmVzc2xvZ2dpbmc9VFJVRSwgbmFtZT0nUkNQODUnKQoKaW52aXNpYmxlKHJ1bihoY29yZTQ1LCAyMTAwKSkKZ2V0ZGF0ZShoY29yZTQ1KQpnZXRkYXRlKGhjb3JlODUpCmBgYAoKVGhlIHJlc3VsdHMgZnJvbSBzZXZlcmFsIHJ1bnMgY2FuIGVhc2lseSBiZSBwdXQgdG9nZXRoZXIgZm9yIGNvbXBhcmlzb24uCmBgYHtyfQppbnZpc2libGUocnVuKGhjb3JlODUsIDIxMDApKQpoZGF0YTQ1IDwtIGZldGNodmFycyhoY29yZTQ1LCAxOTkwOjIxMDApICAgICAgICAgICAgICAgICAgIyBkZWZhdWx0IHZhcnMKaGRhdGE4NSA8LSBmZXRjaHZhcnMoaGNvcmU4NSwgMTk5MDoyMTAwKQpoZGF0YSA8LSByYmluZChoZGF0YTQ1LCBoZGF0YTg1KQpnZ3Bsb3QoZGF0YT1oZGF0YSwgYWVzKHg9eWVhciwgeT12YWx1ZSwgY29sb3I9c2NlbmFyaW8pKSArIGdlb21fbGluZSgpICsgCiAgICBmYWNldF93cmFwKH52YXJpYWJsZSwgc2NhbGVzPSdmcmVlX3knKSArIAogICAgdGhlbWVfc29sYXJpemVkKGxpZ2h0ID0gVFJVRSkKYGBgCgojIyBJbnRlcm1lZGlhdGUgdXNhZ2UKCiMjIyBSZXNldCBhIGNvcmUgdG8gYW4gZWFybGllciBkYXRlCgpgYGB7cn0KcmVzZXQoaGNvcmU4NSkKYGBgClJlcnVubmluZyBpdCBzaG91bGQgcHJvZHVjZSB0aGUgc2FtZSB2YWx1ZXMuCmBgYHtyfQppbnZpc2libGUocnVuKGhjb3JlODUsIDIxMDApKQpoZGF0YTg1X25ldyA8LSBmZXRjaHZhcnMoaGNvcmU4NSwgMTk5MDoyMTAwKQphbGwuZXF1YWwoaGRhdGE4NSwgaGRhdGE4NV9uZXcpCmBgYAoKIyMjIFNldCBhIGN1c3RvbSBlbWlzc2lvbnMgcGF0aHdheQoKYGBge3J9CmZmaTg1IDwtIGZldGNodmFycyhoY29yZTg1LCAyMDAwOjIxMDAsIEZGSV9FTUlTU0lPTlMoKSkKaW52aXNpYmxlKHJlc2V0KGhjb3JlODUpKSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjIFdpdGhvdXQgYSB5ZWFyIHNwZWNpZmllZCwgcmVzZXRzIHRvIHRoZSBiZWdpbm5pbmcKZmZpbmV3IDwtIGZmaTg1JHZhbHVlICogMC41CnNldHZhcihoY29yZTg1LCBmZmk4NSR5ZWFyLCBGRklfRU1JU1NJT05TKCksIGZmaW5ldywgYXMuY2hhcmFjdGVyKGZmaTg1JHVuaXRzWzFdKSkKaW52aXNpYmxlKHJ1bihoY29yZTg1LCAyMTAwKSkKaGRhdGFfbG8gPC0gZmV0Y2h2YXJzKGhjb3JlODUsIDE5OTA6MjEwMCwgc2NlbmFyaW89J0xvd19FbWlzcycpCmhkYXRhIDwtIHJiaW5kKGhkYXRhNDUsIGhkYXRhODUsIGhkYXRhX2xvKQpnZ3Bsb3QoZGF0YT1oZGF0YSwgYWVzKHg9eWVhciwgeT12YWx1ZSwgY29sb3I9c2NlbmFyaW8pKSArIGdlb21fbGluZSgpICsgCiAgICBmYWNldF93cmFwKH52YXJpYWJsZSwgc2NhbGVzPSdmcmVlX3knKSArIAogICAgdGhlbWVfc29sYXJpemVkKGxpZ2h0ID0gVFJVRSkKYGBgCgpUaGUgaGVjdG9yIGNvcmUgcmVtZW1iZXJzIGNoYW5nZXMgbGlrZSB0aGlzLCBzbyB3ZSdsbCBzaHV0IGl0IGRvd24gc28gd2UgZG9uJ3QgYWNjaWRlbnRhbGx5IHVzZSBpdCBhZ2Fpbi4gIApgYGB7cn0Kc2h1dGRvd24oaGNvcmU4NSkKYGBgCgojIyMgQ2hhbmdpbmcgbW9kZWwgcGFyYW1ldGVycwoKYGBge3J9Cmhjb3JlODVfbG9fZWNzIDwtIG5ld2NvcmUoaW5pZmlsZTg1LCBzdXBwcmVzc2xvZ2dpbmc9VFJVRSwgbmFtZT0nUkNQODVfbG93X2VjcycpCnNldHZhcihoY29yZTg1X2xvX2VjcywgTkEsIEVDUygpLCAyLjUsICdkZWdDJykKcmVzZXQoaGNvcmU4NV9sb19lY3MpCnJ1bihoY29yZTg1X2xvX2VjcywgMjEwMCkKaGRhdGE4NV9sb3dfZWNzIDwtIGZldGNodmFycyhoY29yZTg1X2xvX2VjcywgMTk5MDoyMTAwKQpoZGF0YSA8LSByYmluZChoZGF0YTQ1LCBoZGF0YTg1LCBoZGF0YTg1X2xvd19lY3MpCmdncGxvdChkYXRhPWhkYXRhLCBhZXMoeD15ZWFyLCB5PXZhbHVlLCBjb2xvcj1zY2VuYXJpbykpICsgZ2VvbV9saW5lKCkgKyAKICAgIGZhY2V0X3dyYXAofnZhcmlhYmxlLCBzY2FsZXM9J2ZyZWVfeScpICsgCiAgICB0aGVtZV9zb2xhcml6ZWQobGlnaHQgPSBUUlVFKQpgYGAKKipDYXV0aW9uKio6IFlvdSBtdXN0IGByZXNldGAgYSBoZWN0b3IgY29yZSB0byB0aGUgYmVnaW5uaW5nIG9mIHRoZSBzaW11bGF0aW9uIChpLmUuLCB3aXRoIG5vIGB5ZWFyYCBhcmd1bWVudCkgCmFmdGVyIGNoYW5naW5nIGEgbW9kZWwgcGFyYW1ldGVyLiAgVGhpcyByZXJ1bnMgdGhlIGluaXRpYWxpemF0aW9uIGFuZCBzcGludXAsIGJvdGggb2Ygd2hpY2ggYXJlIG5lZWRlZCBmb3IKSGVjdG9yIHRvIHVzZSB0aGUgbmV3IHBhcmFtZXRlcnMgY29ycmVjdGx5LgoKIyMgQWR2YW5jZWQgdXNhZ2UKCldoZW4gY29tYmluZWQgd2l0aCBvdGhlciBSIHBhY2thZ2VzIEhlY3RvciBjYW4gYmUgdmVyeSBwb3dlcmZ1bC4gIEhlcmUncyBhbiBleGFtcGxlIHdoZXJlIHdlIHNlYXJjaCBmb3IgYW4gCmVtaXNzaW9ucyBwYXRod2F5IHRoZSBwcm9kdWNlcyBhIHNwZWNpZmllZCAoY29uc3RhbnQpIGF0bW9zcGhlcmljIG1ldGhhbmUgY29uY2VudHJhdGlvbi4KKipOb3RlKio6IElmIHlvdSB1c2UgSGVjdG9yIGluIGFuIGFsZ29yaXRobSB0aGF0IHdpbGwgcnVuIHRoZSBtb2RlbCBtYW55IHRpbWVzLCB5b3Ugd2lsbCBwcm9iYWJseSB3YW50IHRvIAp0dXJuIG9mZiB0aGUgbG9nZ2luZyB1c2luZyB0aGUgYHN1cHByZXNzbG9nZ2luZ2AgYXJndW1lbnQgdG8gYG5ld2NvcmVgLgoKYGBge3J9CmhlY3Rvcl9pbmlmaWxlIDwtIGZpbGUucGF0aChzeXN0ZW0uZmlsZSgnaW5wdXQnLCBwYWNrYWdlPSdoZWN0b3InKSwgJ2hlY3Rvcl9yY3A2MC5pbmknKQpoY29yZV9zb2x2IDwtIG5ld2NvcmUoaGVjdG9yX2luaWZpbGUsIHN1cHByZXNzbG9nZ2luZz1UUlVFKQpydW4oaGNvcmVfc29sdiwgMTk5OSkKYGBgCgpXZSB3aWxsIG5lZWQgYSB0YXJnZXQgZnVuY3Rpb24gZm9yIG91ciBzb2x2ZXIuICAKKipDYXV0aW9uKio6IGEgZnVuY3Rpb24gY3JlYXRlZCB0aGlzIHdheSB3aWxsIG5vdCBiZSB0aHJlYWQgc2FmZSBiZWNhdXNlIHRoZSBoZWN0b3IgY29yZSBzdG9yZXMgcGVyc2lzdGVudApkYXRhIGluIGl0cyBpbnRlcm5hbCBkYXRhIHN0cnVjdHVyZXMuICBJZiB5b3UgdHJ5IHRvIHVzZSBzb21ldGhpbmcgbGlrZSB0aGlzIGluIGEgcGFyYWxsZWwgYWxnb3JpdGhtLCB5b3Ugd2lsbApoYXZlIHRvIGZpbmQgYSB3YXkgZm9yIGVhY2ggdGhyZWFkIHRvIGhhdmUgaXRzIG93biBwcml2YXRlIGhlY3RvciBjb3JlLiAgCgpgYGB7cn0KbWt0YXJnZnVuIDwtIGZ1bmN0aW9uKHRhcmdsZXZlbCwgaGNvcmUpIHsKICAgIGZ1bmN0aW9uKGVtaXNzKXsKICAgICAgICBzZXR2YXIoaGNvcmUsIDIwMDA6MjEwMCwgRU1JU1NJT05TX0NINCgpLCBlbWlzcywgIlRnIENINCIpCiAgICAgICAgcmVzZXQoaGNvcmUsIDE5OTkpCiAgICAgICAgcnVuKGhjb3JlLCAyMTAwKQogICAgICAgIGhvdXQgPC0gZmV0Y2h2YXJzKGhjb3JlLCAyMDAwOjIxMDAsIEFUTU9TUEhFUklDX0NINCgpKQogICAgICAgICMjIHJldHVybiB0aGUgZGlmZmVyZW5jZSBiZXR3ZWVuIHRoZSB0YXJnZXQgYW5kIHRoZSBhY3R1YWwKICAgICAgICBob3V0JHZhbHVlIC0gdGFyZ2xldmVsCiAgICB9Cn0KZiA8LSBta3RhcmdmdW4oMTgyMCwgaGNvcmVfc29sdikKYGBgCgpgYGB7cn0KaW5pdGd1ZXNzIDwtIHJlcCgzMDAuMCwgdGltZXM9MTAxKSAgIyAyMDAwOjIwMDEgaW5jbHVkZXMgYm90aCBlbmRwb2ludHMKc2x2IDwtIG5sZXFzbHY6Om5sZXFzbHYoaW5pdGd1ZXNzLCBmLCBtZXRob2Q9IkJyb3lkZW4iKQpjaDRlbWlzcyA8LSBzbHYkeApwbHRkYXRhIDwtIGRhdGEuZnJhbWUoeWVhcj0yMDAwOjIxMDAsIGNoNF9lbWlzcz1jaDRlbWlzcykKZ2dwbG90KGRhdGE9cGx0ZGF0YSwgYWVzKHg9eWVhciwgeT1jaDRfZW1pc3MpKSArIGdlb21fbGluZShjb2w9ImRhcmtncmV5Iiwgc2l6ZT0xLjI1KSArIAogICAgdGhlbWVfc29sYXJpemVkKGxpZ2h0ID0gVFJVRSkKYGBgCgpgYGB7cn0KcmVzZXQoaGNvcmVfc29sdiwgMTk5OSkKc2V0dmFyKGhjb3JlX3NvbHYsIDIwMDA6MjEwMCwgRU1JU1NJT05TX0NINCgpLCBjaDRlbWlzcywgIlRnIENINCIpCnJ1bihoY29yZV9zb2x2LCAyMTAwKQpjaDRjb25jIDwtIGZldGNodmFycyhoY29yZV9zb2x2LCAyMDAwOjIxMDAsIEFUTU9TUEhFUklDX0NINCgpKQpnZ3Bsb3QoZGF0YT1jaDRjb25jLCBhZXMoeD15ZWFyLCB5PXZhbHVlKSkgKyBnZW9tX2xpbmUoY29sPSdkYXJrZ3JleScsIHNpemU9MS4yNSkgKyB0aGVtZV9zb2xhcml6ZWQobGlnaHQ9VFJVRSkgKyB5bGltKDE4MDAsMTgzMCkKYGBgCgo=