UNPKG

asmimproved-dbgmits

Version:

Provides the ability to control GDB and LLDB programmatically via GDB/MI.

293 lines (290 loc) 30.6 kB
// Copyright (c) 2015 Vadim Macagon // MIT License, see LICENSE file for full terms. "use strict"; require('source-map-support').install(); var chai = require('chai'); var chaiAsPromised = require('chai-as-promised'); var stream = require('stream'); var dbgmits = require('../lib/index'); var test_utils_1 = require('./test_utils'); chai.use(chaiAsPromised); // aliases var expect = chai.expect; var DebugSession = dbgmits.DebugSession; // the directory in which Gruntfile.js resides is also Mocha's working directory, // so any relative paths will be relative to that directory var localTargetExe = './build/Debug/test_target'; var hostExecutable = 'C:/Projects/hello-world/hello-world'; var remoteHost = '192.168.56.101'; var remotePort = 8099; /** * Creates a readable stream containing nothing but the text passed in. */ function createTextStream(text) { var textStream = new stream.Readable(); textStream.push(text, 'utf8'); textStream.push(null); return textStream; } /** * Creates a debug session but instead of spawning a debugger and connecting to it the session * is simply fed the passed in notification text, this makes it emit an event (assuming the * notification text was formatted correctly). * * @param text Notification text in MI format. * @param event The name of the event that is expected to be emitted. * @param callback Callback to invoke if the expected event was emitted. */ function emitEventForDebuggerOutput(text, event, callback) { var debugSession = new DebugSession(createTextStream(text), null); debugSession.once(event, function (data) { debugSession.end(false); callback(data); }); } describe("Debug Session", function () { describe("Basics", function () { var debugSession; before(function () { debugSession = test_utils_1.startDebugSession(); }); it("should start", function () { expect(debugSession).to.exist; }); it("should set executable to debug", function () { return debugSession.setExecutableFile(localTargetExe); }); after(function () { return debugSession.end(); }); }); describe("Events", function () { it("emits EVENT_THREAD_GROUP_ADDED", function (done) { var id = 'i1'; emitEventForDebuggerOutput("=thread-group-added,id=\"" + id + "\"\n", dbgmits.EVENT_THREAD_GROUP_ADDED, function (data) { expect(data).to.have.property('id', id); done(); }); }); it("emits EVENT_THREAD_GROUP_REMOVED", function (done) { var id = 'i1'; emitEventForDebuggerOutput("=thread-group-removed,id=\"" + id + "\"\n", dbgmits.EVENT_THREAD_GROUP_REMOVED, function (data) { expect(data).to.have.property('id', id); done(); }); }); it("emits EVENT_THREAD_GROUP_STARTED", function (done) { var id = 'i1'; var pid = '6550'; emitEventForDebuggerOutput("=thread-group-started,id=\"" + id + "\",pid=\"" + pid + "\"\n", dbgmits.EVENT_THREAD_GROUP_STARTED, function (data) { expect(data).to.have.property('id', id); expect(data).to.have.property('pid', pid); done(); }); }); it("emits EVENT_THREAD_GROUP_EXITED", function (done) { var id = 'i1'; var exitCode = '3'; emitEventForDebuggerOutput("=thread-group-exited,id=\"" + id + "\",exit-code=\"" + exitCode + "\"\n", dbgmits.EVENT_THREAD_GROUP_EXITED, function (data) { expect(data).to.have.property('id', id); expect(data).to.have.property('exitCode', exitCode); done(); }); }); it("emits EVENT_THREAD_CREATED", function (done) { var id = 1; var groupId = 'i1'; emitEventForDebuggerOutput("=thread-created,id=\"" + id + "\",group-id=\"" + groupId + "\"\n", dbgmits.EVENT_THREAD_CREATED, function (data) { expect(data).to.have.property('id', id); expect(data).to.have.property('groupId', groupId); done(); }); }); it("emits EVENT_THREAD_EXITED", function (done) { var id = 1; var groupId = 'i1'; emitEventForDebuggerOutput("=thread-exited,id=\"" + id + "\",group-id=\"" + groupId + "\"\n", dbgmits.EVENT_THREAD_EXITED, function (data) { expect(data).to.have.property('id', id); expect(data).to.have.property('groupId', groupId); done(); }); }); it("emits EVENT_THREAD_SELECTED", function (done) { var id = 1; emitEventForDebuggerOutput("=thread-selected,id=\"" + id + "\"\n", dbgmits.EVENT_THREAD_SELECTED, function (data) { expect(data).to.have.property('id', id); done(); }); }); it("emits EVENT_LIB_LOADED", function (done) { var id = '1'; var targetName = 'somelib'; var hostName = 'somelib'; var threadGroup = 'i1'; emitEventForDebuggerOutput("=library-loaded,id=\"" + id + "\",target-name=\"" + targetName + "\",host-name=\"" + hostName + "\",thread-group=\"" + threadGroup + "\"\n", dbgmits.EVENT_LIB_LOADED, function (data) { expect(data).to.have.property('id', id); expect(data).to.have.property('targetName', targetName); expect(data).to.have.property('hostName', hostName); expect(data).to.have.property('threadGroup', threadGroup); done(); }); }); it("emits EVENT_LIB_UNLOADED", function (done) { var id = '1'; var targetName = 'somelib'; var hostName = 'somelib'; var threadGroup = 'i1'; emitEventForDebuggerOutput("=library-unloaded,id=\"" + id + "\",target-name=\"" + targetName + "\",host-name=\"" + hostName + "\",thread-group=\"" + threadGroup + "\"\n", dbgmits.EVENT_LIB_UNLOADED, function (data) { expect(data).to.have.property('id', id); expect(data).to.have.property('targetName', targetName); expect(data).to.have.property('hostName', hostName); expect(data).to.have.property('threadGroup', threadGroup); done(); }); }); it("emits EVENT_DBG_CONSOLE_OUTPUT", function (done) { var testStr = 'This is a line of text.'; emitEventForDebuggerOutput('~"' + testStr + '"\n', dbgmits.EVENT_DBG_CONSOLE_OUTPUT, function (data) { expect(data).to.equal(testStr); done(); }); }); it("emits EVENT_TARGET_OUTPUT", function (done) { var testStr = 'This is some target output.'; emitEventForDebuggerOutput('@"' + testStr + '"\n', dbgmits.EVENT_TARGET_OUTPUT, function (data) { expect(data).to.equal(testStr); done(); }); }); it("emits EVENT_DBG_LOG_OUTPUT", function (done) { var testStr = 'This is some debugger log output.'; emitEventForDebuggerOutput('&"' + testStr + '"\n', dbgmits.EVENT_DBG_LOG_OUTPUT, function (data) { expect(data).to.equal(testStr); done(); }); }); it("emits EVENT_TARGET_RUNNING", function (done) { var threadId = 'all'; emitEventForDebuggerOutput('*running,thread-id="${threadId}"', dbgmits.EVENT_TARGET_RUNNING, function (threadId) { expect(threadId).to.equal(threadId); done(); }); }); it("emits EVENT_TARGET_STOPPED", function (done) { emitEventForDebuggerOutput('*stopped,reason="exited-normally"\n', dbgmits.EVENT_TARGET_STOPPED, function (notification) { expect(notification.reason).to.equal(dbgmits.TargetStopReason.ExitedNormally); done(); }); }); it("emits EVENT_BREAKPOINT_HIT", function (done) { var bkptId = 15; var threadId = 1; emitEventForDebuggerOutput(("*stopped,reason=\"breakpoint-hit\",bkptno=\"" + bkptId + "\",frame={},thread-id=\"" + threadId + "\",") + "stopped-threads=\"all\"\n", dbgmits.EVENT_BREAKPOINT_HIT, function (notification) { expect(notification.reason).to.equal(dbgmits.TargetStopReason.BreakpointHit); expect(notification.threadId).to.equal(threadId); expect(notification.stoppedThreads.length).to.equal(0); expect(notification.breakpointId).to.equal(bkptId); done(); }); }); it("emits EVENT_SIGNAL_RECEIVED", function (done) { var signalName = 'SIGSEGV'; var signalMeaning = 'Segmentation Fault'; var threadId = 1; emitEventForDebuggerOutput(("*stopped,reason=\"signal-received\",signal-name=\"" + signalName + "\",") + ("signal-meaning=\"" + signalMeaning + "\",thread-id=\"" + threadId + "\",frame={}\n"), dbgmits.EVENT_SIGNAL_RECEIVED, function (notification) { expect(notification.reason).to.equal(dbgmits.TargetStopReason.SignalReceived); expect(notification.threadId).to.equal(threadId); expect(notification.signalName).to.equal(signalName); expect(notification.signalMeaning).to.equal(signalMeaning); done(); }); }); it("emits EVENT_EXCEPTION_RECEIVED", function (done) { var msg = 'This is an exception description.'; var threadId = 1; emitEventForDebuggerOutput(("*stopped,reason=\"exception-received\",exception=\"" + msg + "\",thread-id=\"" + threadId + "\",") + "stopped-threads=\"all\"\n", dbgmits.EVENT_EXCEPTION_RECEIVED, function (notification) { expect(notification.reason).to.equal(dbgmits.TargetStopReason.ExceptionReceived); expect(notification.threadId).to.equal(threadId); expect(notification.stoppedThreads.length).to.equal(0); expect(notification.exception).to.equal(msg); done(); }); }); it("emits EVENT_BREAKPOINT_MODIFIED", function (done) { var id = 999; var breakpointType = 'breakpoint'; var address = '0x0000000000400927'; var func = 'main(int, char const**)'; var filename = '../test/break_tests_target.cpp'; var fullname = '/media/sf_dbgmits/test/break_tests_target.cpp'; var line = 47; var threadGroup = 'i1'; var hitCount = 1; var ignoreCount = 2; var enableCount = 3; var passCount = 4; var originaLocation = 'main'; var threadId = 10; var condition = 'something == true'; var what = 'nothing'; var at = address + " " + func; var evaluatedBy = 'target'; var mask = "xxxx"; emitEventForDebuggerOutput(("=breakpoint-modified,bkpt={number=\"" + id + "\",type=\"" + breakpointType + "\",disp=\"keep\",") + ("enabled=\"y\",addr=\"" + address + "\",func=\"" + func + "\",file=\"" + filename + "\",") + ("fullname=\"" + fullname + "\",line=\"" + line + "\",thread-groups=[\"" + threadGroup + "\"],") + ("times=\"" + hitCount + "\",enable=\"" + enableCount + "\",ignore=\"" + ignoreCount + "\",") + ("original-location=\"" + originaLocation + "\",pending=\"" + originaLocation + "\",") + ("thread=\"" + threadId + "\",cond=\"" + condition + "\",what=\"" + what + "\",at=\"" + at + "\",") + ("pass=\"" + passCount + "\",evaluated-by=\"" + evaluatedBy + "\",mask=\"" + mask + "\",") + "installed=\"y\"}", dbgmits.EVENT_BREAKPOINT_MODIFIED, function (e) { var bp = e.breakpoint; expect(bp).to.have.property('id', id); expect(bp).to.have.property('breakpointType', breakpointType); expect(bp).to.have.property('isTemp', false); expect(bp).to.have.property('isEnabled', true); expect(bp).to.have.property('locations').of.length(1); expect(bp).to.have.property('pending', originaLocation); expect(bp).to.have.property('threadId', threadId); expect(bp).to.have.property('condition', condition); expect(bp).to.have.property('ignoreCount', ignoreCount); expect(bp).to.have.property('enableCount', enableCount); expect(bp).to.have.property('originalLocation', originaLocation); expect(bp).to.have.property('hitCount', hitCount); expect(bp).to.have.property('what', what); expect(bp).to.have.property('passCount', passCount); expect(bp).to.have.property('evaluatedBy', evaluatedBy); expect(bp).to.have.property('mask', mask); expect(bp).to.have.property('isInstalled', true); var bploc = bp.locations[0]; expect(bploc).to.have.property('id', id.toString()); expect(bploc).to.have.property('address', address); expect(bploc).to.have.property('func', func); expect(bploc).to.have.property('filename', filename); expect(bploc).to.have.property('fullname', fullname); expect(bploc).to.have.property('line', line); expect(bploc).to.have.property('at', at); done(); }); }); }); /* describe("Remote Debugging Setup", () => { var debugSession: DebugSession; before(() => { debugSession = startDebugSession(); return debugSession.setExecutableFile(hostExecutable); }); it("should connect to remote target", () => { return debugSession.connectToRemoteTarget(remoteHost, remotePort); }); after(() => { return debugSession.end(); }); }); */ }); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYmFzaWMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi90ZXN0L2Jhc2ljLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLG1DQUFtQztBQUNuQyxnREFBZ0Q7O0FBRWhELE9BQU8sQ0FBQyxvQkFBb0IsQ0FBQyxDQUFDLE9BQU8sRUFBRSxDQUFDO0FBRXhDLElBQVksSUFBSSxXQUFNLE1BQU0sQ0FBQyxDQUFBO0FBQzdCLElBQU8sY0FBYyxXQUFXLGtCQUFrQixDQUFDLENBQUM7QUFDcEQsSUFBWSxNQUFNLFdBQU0sUUFBUSxDQUFDLENBQUE7QUFFakMsSUFBWSxPQUFPLFdBQU0sY0FBYyxDQUFDLENBQUE7QUFDeEMsMkJBQWtDLGNBQWMsQ0FBQyxDQUFBO0FBRWpELElBQUksQ0FBQyxHQUFHLENBQUMsY0FBYyxDQUFDLENBQUM7QUFFekIsVUFBVTtBQUNWLElBQUksTUFBTSxHQUFHLElBQUksQ0FBQyxNQUFNLENBQUM7QUFDekIsSUFBTyxZQUFZLEdBQUcsT0FBTyxDQUFDLFlBQVksQ0FBQztBQUUzQyxpRkFBaUY7QUFDakYsMkRBQTJEO0FBQzNELElBQUksY0FBYyxHQUFXLDJCQUEyQixDQUFDO0FBQ3pELElBQUksY0FBYyxHQUFXLHFDQUFxQyxDQUFDO0FBQ25FLElBQUksVUFBVSxHQUFXLGdCQUFnQixDQUFDO0FBQzFDLElBQUksVUFBVSxHQUFXLElBQUksQ0FBQztBQUU5Qjs7R0FFRztBQUNILDBCQUEwQixJQUFZO0lBQ3BDLElBQUksVUFBVSxHQUFHLElBQUksTUFBTSxDQUFDLFFBQVEsRUFBRSxDQUFDO0lBQ3ZDLFVBQVUsQ0FBQyxJQUFJLENBQUMsSUFBSSxFQUFFLE1BQU0sQ0FBQyxDQUFDO0lBQzlCLFVBQVUsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUM7SUFDdEIsTUFBTSxDQUFDLFVBQVUsQ0FBQztBQUNwQixDQUFDO0FBRUQ7Ozs7Ozs7O0dBUUc7QUFDSCxvQ0FBb0MsSUFBWSxFQUFFLEtBQWEsRUFBRSxRQUE2QjtJQUM1RixJQUFJLFlBQVksR0FBRyxJQUFJLFlBQVksQ0FBQyxnQkFBZ0IsQ0FBQyxJQUFJLENBQUMsRUFBRSxJQUFJLENBQUMsQ0FBQztJQUNsRSxZQUFZLENBQUMsSUFBSSxDQUFDLEtBQUssRUFBRSxVQUFDLElBQVM7UUFDakMsWUFBWSxDQUFDLEdBQUcsQ0FBQyxLQUFLLENBQUMsQ0FBQztRQUN4QixRQUFRLENBQUMsSUFBSSxDQUFDLENBQUM7SUFDakIsQ0FBQyxDQUFDLENBQUM7QUFDTCxDQUFDO0FBRUQsUUFBUSxDQUFDLGVBQWUsRUFBRTtJQUN4QixRQUFRLENBQUMsUUFBUSxFQUFFO1FBQ2pCLElBQUksWUFBMEIsQ0FBQztRQUUvQixNQUFNLENBQUM7WUFDTCxZQUFZLEdBQUcsOEJBQWlCLEVBQUUsQ0FBQztRQUNyQyxDQUFDLENBQUMsQ0FBQztRQUVILEVBQUUsQ0FBQyxjQUFjLEVBQUU7WUFDakIsTUFBTSxDQUFDLFlBQVksQ0FBQyxDQUFDLEVBQUUsQ0FBQyxLQUFLLENBQUM7UUFDaEMsQ0FBQyxDQUFDLENBQUM7UUFFSCxFQUFFLENBQUMsZ0NBQWdDLEVBQUU7WUFDbkMsTUFBTSxDQUFDLFlBQVksQ0FBQyxpQkFBaUIsQ0FBQyxjQUFjLENBQUMsQ0FBQztRQUN4RCxDQUFDLENBQUMsQ0FBQztRQUVILEtBQUssQ0FBQztZQUNKLE1BQU0sQ0FBQyxZQUFZLENBQUMsR0FBRyxFQUFFLENBQUM7UUFDNUIsQ0FBQyxDQUFDLENBQUM7SUFDTCxDQUFDLENBQUMsQ0FBQztJQUVILFFBQVEsQ0FBQyxRQUFRLEVBQUU7UUFDakIsRUFBRSxDQUFDLGdDQUFnQyxFQUFFLFVBQUMsSUFBZTtZQUNuRCxJQUFJLEVBQUUsR0FBVyxJQUFJLENBQUM7WUFDdEIsMEJBQTBCLENBQ3hCLDhCQUEyQixFQUFFLFNBQUssRUFDbEMsT0FBTyxDQUFDLHdCQUF3QixFQUNoQyxVQUFDLElBQVM7Z0JBQ1IsTUFBTSxDQUFDLElBQUksQ0FBQyxDQUFDLEVBQUUsQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLElBQUksRUFBRSxFQUFFLENBQUMsQ0FBQztnQkFDeEMsSUFBSSxFQUFFLENBQUM7WUFDVCxDQUFDLENBQ0YsQ0FBQztRQUNKLENBQUMsQ0FBQyxDQUFDO1FBRUgsRUFBRSxDQUFDLGtDQUFrQyxFQUFFLFVBQUMsSUFBZTtZQUNyRCxJQUFJLEVBQUUsR0FBVyxJQUFJLENBQUM7WUFDdEIsMEJBQTBCLENBQ3hCLGdDQUE2QixFQUFFLFNBQUssRUFDcEMsT0FBTyxDQUFDLDBCQUEwQixFQUNsQyxVQUFDLElBQVM7Z0JBQ1IsTUFBTSxDQUFDLElBQUksQ0FBQyxDQUFDLEVBQUUsQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLElBQUksRUFBRSxFQUFFLENBQUMsQ0FBQztnQkFDeEMsSUFBSSxFQUFFLENBQUM7WUFDVCxDQUFDLENBQ0YsQ0FBQztRQUNKLENBQUMsQ0FBQyxDQUFDO1FBRUgsRUFBRSxDQUFDLGtDQUFrQyxFQUFFLFVBQUMsSUFBZTtZQUNyRCxJQUFJLEVBQUUsR0FBVyxJQUFJLENBQUM7WUFDdEIsSUFBSSxHQUFHLEdBQVcsTUFBTSxDQUFDO1lBQ3pCLDBCQUEwQixDQUN4QixnQ0FBNkIsRUFBRSxpQkFBVSxHQUFHLFNBQUssRUFDakQsT0FBTyxDQUFDLDBCQUEwQixFQUNsQyxVQUFDLElBQVM7Z0JBQ1IsTUFBTSxDQUFDLElBQUksQ0FBQyxDQUFDLEVBQUUsQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLElBQUksRUFBRSxFQUFFLENBQUMsQ0FBQztnQkFDeEMsTUFBTSxDQUFDLElBQUksQ0FBQyxDQUFDLEVBQUUsQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLEtBQUssRUFBRSxHQUFHLENBQUMsQ0FBQztnQkFDMUMsSUFBSSxFQUFFLENBQUM7WUFDVCxDQUFDLENBQ0YsQ0FBQztRQUNKLENBQUMsQ0FBQyxDQUFDO1FBRUgsRUFBRSxDQUFDLGlDQUFpQyxFQUFFLFVBQUMsSUFBZTtZQUNwRCxJQUFJLEVBQUUsR0FBVyxJQUFJLENBQUM7WUFDdEIsSUFBSSxRQUFRLEdBQVcsR0FBRyxDQUFDO1lBQzNCLDBCQUEwQixDQUN4QiwrQkFBNEIsRUFBRSx1QkFBZ0IsUUFBUSxTQUFLLEVBQzNELE9BQU8sQ0FBQyx5QkFBeUIsRUFDakMsVUFBQyxJQUFTO2dCQUNSLE1BQU0sQ0FBQyxJQUFJLENBQUMsQ0FBQyxFQUFFLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxJQUFJLEVBQUUsRUFBRSxDQUFDLENBQUM7Z0JBQ3hDLE1BQU0sQ0FBQyxJQUFJLENBQUMsQ0FBQyxFQUFFLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxVQUFVLEVBQUUsUUFBUSxDQUFDLENBQUM7Z0JBQ3BELElBQUksRUFBRSxDQUFDO1lBQ1QsQ0FBQyxDQUNGLENBQUM7UUFDSixDQUFDLENBQUMsQ0FBQztRQUVILEVBQUUsQ0FBQyw0QkFBNEIsRUFBRSxVQUFDLElBQWU7WUFDL0MsSUFBTSxFQUFFLEdBQUcsQ0FBQyxDQUFDO1lBQ2IsSUFBSSxPQUFPLEdBQVcsSUFBSSxDQUFDO1lBQzNCLDBCQUEwQixDQUN4QiwwQkFBdUIsRUFBRSxzQkFBZSxPQUFPLFNBQUssRUFDcEQsT0FBTyxDQUFDLG9CQUFvQixFQUM1QixVQUFDLElBQVM7Z0JBQ1IsTUFBTSxDQUFDLElBQUksQ0FBQyxDQUFDLEVBQUUsQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLElBQUksRUFBRSxFQUFFLENBQUMsQ0FBQztnQkFDeEMsTUFBTSxDQUFDLElBQUksQ0FBQyxDQUFDLEVBQUUsQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLFNBQVMsRUFBRSxPQUFPLENBQUMsQ0FBQztnQkFDbEQsSUFBSSxFQUFFLENBQUM7WUFDVCxDQUFDLENBQ0YsQ0FBQztRQUNKLENBQUMsQ0FBQyxDQUFDO1FBRUgsRUFBRSxDQUFDLDJCQUEyQixFQUFFLFVBQUMsSUFBZTtZQUM5QyxJQUFNLEVBQUUsR0FBRyxDQUFDLENBQUM7WUFDYixJQUFJLE9BQU8sR0FBVyxJQUFJLENBQUM7WUFDM0IsMEJBQTBCLENBQ3hCLHlCQUFzQixFQUFFLHNCQUFlLE9BQU8sU0FBSyxFQUNuRCxPQUFPLENBQUMsbUJBQW1CLEVBQzNCLFVBQUMsSUFBUztnQkFDUixNQUFNLENBQUMsSUFBSSxDQUFDLENBQUMsRUFBRSxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsSUFBSSxFQUFFLEVBQUUsQ0FBQyxDQUFDO2dCQUN4QyxNQUFNLENBQUMsSUFBSSxDQUFDLENBQUMsRUFBRSxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsU0FBUyxFQUFFLE9BQU8sQ0FBQyxDQUFDO2dCQUNsRCxJQUFJLEVBQUUsQ0FBQztZQUNULENBQUMsQ0FDRixDQUFDO1FBQ0osQ0FBQyxDQUFDLENBQUM7UUFFSCxFQUFFLENBQUMsNkJBQTZCLEVBQUUsVUFBQyxJQUFlO1lBQ2hELElBQU0sRUFBRSxHQUFHLENBQUMsQ0FBQztZQUNiLDBCQUEwQixDQUN4QiwyQkFBd0IsRUFBRSxTQUFLLEVBQy9CLE9BQU8sQ0FBQyxxQkFBcUIsRUFDN0IsVUFBQyxJQUFTO2dCQUNSLE1BQU0sQ0FBQyxJQUFJLENBQUMsQ0FBQyxFQUFFLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxJQUFJLEVBQUUsRUFBRSxDQUFDLENBQUM7Z0JBQ3hDLElBQUksRUFBRSxDQUFDO1lBQ1QsQ0FBQyxDQUNGLENBQUM7UUFDSixDQUFDLENBQUMsQ0FBQztRQUVILEVBQUUsQ0FBQyx3QkFBd0IsRUFBRSxVQUFDLElBQWU7WUFDM0MsSUFBSSxFQUFFLEdBQVcsR0FBRyxDQUFDO1lBQ3JCLElBQUksVUFBVSxHQUFXLFNBQVMsQ0FBQztZQUNuQyxJQUFJLFFBQVEsR0FBVyxTQUFTLENBQUM7WUFDakMsSUFBSSxXQUFXLEdBQVcsSUFBSSxDQUFDO1lBQy9CLDBCQUEwQixDQUN4QiwwQkFBdUIsRUFBRSx5QkFBa0IsVUFBVSx1QkFBZ0IsUUFBUSwwQkFBbUIsV0FBVyxTQUFLLEVBQ2hILE9BQU8sQ0FBQyxnQkFBZ0IsRUFDeEIsVUFBQyxJQUFTO2dCQUNSLE1BQU0sQ0FBQyxJQUFJLENBQUMsQ0FBQyxFQUFFLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxJQUFJLEVBQUUsRUFBRSxDQUFDLENBQUM7Z0JBQ3hDLE1BQU0sQ0FBQyxJQUFJLENBQUMsQ0FBQyxFQUFFLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxZQUFZLEVBQUUsVUFBVSxDQUFDLENBQUM7Z0JBQ3hELE1BQU0sQ0FBQyxJQUFJLENBQUMsQ0FBQyxFQUFFLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxVQUFVLEVBQUUsUUFBUSxDQUFDLENBQUM7Z0JBQ3BELE1BQU0sQ0FBQyxJQUFJLENBQUMsQ0FBQyxFQUFFLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxhQUFhLEVBQUUsV0FBVyxDQUFDLENBQUM7Z0JBQzFELElBQUksRUFBRSxDQUFDO1lBQ1QsQ0FBQyxDQUNGLENBQUM7UUFDSixDQUFDLENBQUMsQ0FBQztRQUVILEVBQUUsQ0FBQywwQkFBMEIsRUFBRSxVQUFDLElBQWU7WUFDN0MsSUFBSSxFQUFFLEdBQVcsR0FBRyxDQUFDO1lBQ3JCLElBQUksVUFBVSxHQUFXLFNBQVMsQ0FBQztZQUNuQyxJQUFJLFFBQVEsR0FBVyxTQUFTLENBQUM7WUFDakMsSUFBSSxXQUFXLEdBQVcsSUFBSSxDQUFDO1lBQy9CLDBCQUEwQixDQUN4Qiw0QkFBeUIsRUFBRSx5QkFBa0IsVUFBVSx1QkFBZ0IsUUFBUSwwQkFBbUIsV0FBVyxTQUFLLEVBQ2xILE9BQU8sQ0FBQyxrQkFBa0IsRUFDMUIsVUFBQyxJQUFTO2dCQUNSLE1BQU0sQ0FBQyxJQUFJLENBQUMsQ0FBQyxFQUFFLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxJQUFJLEVBQUUsRUFBRSxDQUFDLENBQUM7Z0JBQ3hDLE1BQU0sQ0FBQyxJQUFJLENBQUMsQ0FBQyxFQUFFLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxZQUFZLEVBQUUsVUFBVSxDQUFDLENBQUM7Z0JBQ3hELE1BQU0sQ0FBQyxJQUFJLENBQUMsQ0FBQyxFQUFFLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxVQUFVLEVBQUUsUUFBUSxDQUFDLENBQUM7Z0JBQ3BELE1BQU0sQ0FBQyxJQUFJLENBQUMsQ0FBQyxFQUFFLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxhQUFhLEVBQUUsV0FBVyxDQUFDLENBQUM7Z0JBQzFELElBQUksRUFBRSxDQUFDO1lBQ1QsQ0FBQyxDQUNGLENBQUM7UUFDSixDQUFDLENBQUMsQ0FBQztRQUVILEVBQUUsQ0FBQyxnQ0FBZ0MsRUFBRSxVQUFDLElBQWU7WUFDbkQsSUFBSSxPQUFPLEdBQVcseUJBQXlCLENBQUM7WUFDaEQsMEJBQTBCLENBQ3hCLElBQUksR0FBRyxPQUFPLEdBQUcsS0FBSyxFQUN0QixPQUFPLENBQUMsd0JBQXdCLEVBQ2hDLFVBQUMsSUFBWTtnQkFDWCxNQUFNLENBQUMsSUFBSSxDQUFDLENBQUMsRUFBRSxDQUFDLEtBQUssQ0FBQyxPQUFPLENBQUMsQ0FBQztnQkFDL0IsSUFBSSxFQUFFLENBQUM7WUFDVCxDQUFDLENBQ0YsQ0FBQztRQUNKLENBQUMsQ0FBQyxDQUFDO1FBRUgsRUFBRSxDQUFDLDJCQUEyQixFQUFFLFVBQUMsSUFBZTtZQUM5QyxJQUFJLE9BQU8sR0FBVyw2QkFBNkIsQ0FBQztZQUNwRCwwQkFBMEIsQ0FDeEIsSUFBSSxHQUFHLE9BQU8sR0FBRyxLQUFLLEVBQ3RCLE9BQU8sQ0FBQyxtQkFBbUIsRUFDM0IsVUFBQyxJQUFZO2dCQUNYLE1BQU0sQ0FBQyxJQUFJLENBQUMsQ0FBQyxFQUFFLENBQUMsS0FBSyxDQUFDLE9BQU8sQ0FBQyxDQUFDO2dCQUMvQixJQUFJLEVBQUUsQ0FBQztZQUNULENBQUMsQ0FDRixDQUFDO1FBQ0osQ0FBQyxDQUFDLENBQUM7UUFFSCxFQUFFLENBQUMsNEJBQTRCLEVBQUUsVUFBQyxJQUFlO1lBQy9DLElBQUksT0FBTyxHQUFXLG1DQUFtQyxDQUFDO1lBQzFELDBCQUEwQixDQUN4QixJQUFJLEdBQUcsT0FBTyxHQUFHLEtBQUssRUFDdEIsT0FBTyxDQUFDLG9CQUFvQixFQUM1QixVQUFDLElBQVk7Z0JBQ1gsTUFBTSxDQUFDLElBQUksQ0FBQyxDQUFDLEVBQUUsQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUFDLENBQUM7Z0JBQy9CLElBQUksRUFBRSxDQUFDO1lBQ1QsQ0FBQyxDQUNGLENBQUM7UUFDSixDQUFDLENBQUMsQ0FBQztRQUVILEVBQUUsQ0FBQyw0QkFBNEIsRUFBRSxVQUFDLElBQWU7WUFDL0MsSUFBSSxRQUFRLEdBQVcsS0FBSyxDQUFDO1lBQzdCLDBCQUEwQixDQUN4QixrQ0FBa0MsRUFBRSxPQUFPLENBQUMsb0JBQW9CLEVBQ2hFLFVBQUMsUUFBZ0I7Z0JBQ2YsTUFBTSxDQUFDLFFBQVEsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxLQUFLLENBQUMsUUFBUSxDQUFDLENBQUM7Z0JBQ3BDLElBQUksRUFBRSxDQUFDO1lBQ1QsQ0FBQyxDQUNGLENBQUM7UUFDSixDQUFDLENBQUMsQ0FBQztRQUVILEVBQUUsQ0FBQyw0QkFBNEIsRUFBRSxVQUFDLElBQWU7WUFDL0MsMEJBQTBCLENBQ3hCLHFDQUFxQyxFQUFFLE9BQU8sQ0FBQyxvQkFBb0IsRUFDbkUsVUFBQyxZQUF5QztnQkFDeEMsTUFBTSxDQUFDLFlBQVksQ0FBQyxNQUFNLENBQUMsQ0FBQyxFQUFFLENBQUMsS0FBSyxDQUFDLE9BQU8sQ0FBQyxnQkFBZ0IsQ0FBQyxjQUFjLENBQUMsQ0FBQztnQkFDOUUsSUFBSSxFQUFFLENBQUM7WUFDVCxDQUFDLENBQ0YsQ0FBQztRQUNKLENBQUMsQ0FBQyxDQUFDO1FBRUgsRUFBRSxDQUFDLDRCQUE0QixFQUFFLFVBQUMsSUFBZTtZQUMvQyxJQUFJLE1BQU0sR0FBVyxFQUFFLENBQUM7WUFDeEIsSUFBSSxRQUFRLEdBQVcsQ0FBQyxDQUFDO1lBQ3pCLDBCQUEwQixDQUN4QixrREFBNEMsTUFBTSxnQ0FBeUIsUUFBUSxTQUFJO2dCQUN2RiwyQkFBeUIsRUFDekIsT0FBTyxDQUFDLG9CQUFvQixFQUM1QixVQUFDLFlBQXlDO2dCQUN4QyxNQUFNLENBQUMsWUFBWSxDQUFDLE1BQU0sQ0FBQyxDQUFDLEVBQUUsQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUFDLGdCQUFnQixDQUFDLGFBQWEsQ0FBQyxDQUFDO2dCQUM3RSxNQUFNLENBQUMsWUFBWSxDQUFDLFFBQVEsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxLQUFLLENBQUMsUUFBUSxDQUFDLENBQUM7Z0JBQ2pELE1BQU0sQ0FBQyxZQUFZLENBQUMsY0FBYyxDQUFDLE1BQU0sQ0FBQyxDQUFDLEVBQUUsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUM7Z0JBQ3ZELE1BQU0sQ0FBQyxZQUFZLENBQUMsWUFBWSxDQUFDLENBQUMsRUFBRSxDQUFDLEtBQUssQ0FBQyxNQUFNLENBQUMsQ0FBQztnQkFDbkQsSUFBSSxFQUFFLENBQUM7WUFDVCxDQUFDLENBQ0YsQ0FBQztRQUNKLENBQUMsQ0FBQyxDQUFDO1FBRUgsRUFBRSxDQUFDLDZCQUE2QixFQUFFLFVBQUMsSUFBZTtZQUNoRCxJQUFJLFVBQVUsR0FBVyxTQUFTLENBQUM7WUFDbkMsSUFBSSxhQUFhLEdBQVcsb0JBQW9CLENBQUM7WUFDakQsSUFBSSxRQUFRLEdBQVcsQ0FBQyxDQUFDO1lBQ3pCLDBCQUEwQixDQUN4Qix3REFBa0QsVUFBVSxTQUFJO2dCQUNoRSx1QkFBbUIsYUFBYSx1QkFBZ0IsUUFBUSxtQkFBYyxFQUN0RSxPQUFPLENBQUMscUJBQXFCLEVBQzdCLFVBQUMsWUFBMEM7Z0JBQ3pDLE1BQU0sQ0FBQyxZQUFZLENBQUMsTUFBTSxDQUFDLENBQUMsRUFBRSxDQUFDLEtBQUssQ0FBQyxPQUFPLENBQUMsZ0JBQWdCLENBQUMsY0FBYyxDQUFDLENBQUM7Z0JBQzlFLE1BQU0sQ0FBQyxZQUFZLENBQUMsUUFBUSxDQUFDLENBQUMsRUFBRSxDQUFDLEtBQUssQ0FBQyxRQUFRLENBQUMsQ0FBQztnQkFDakQsTUFBTSxDQUFDLFlBQVksQ0FBQyxVQUFVLENBQUMsQ0FBQyxFQUFFLENBQUMsS0FBSyxDQUFDLFVBQVUsQ0FBQyxDQUFDO2dCQUNyRCxNQUFNLENBQUMsWUFBWSxDQUFDLGFBQWEsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxLQUFLLENBQUMsYUFBYSxDQUFDLENBQUM7Z0JBQzNELElBQUksRUFBRSxDQUFDO1lBQ1QsQ0FBQyxDQUNGLENBQUM7UUFDSixDQUFDLENBQUMsQ0FBQztRQUVILEVBQUUsQ0FBQyxnQ0FBZ0MsRUFBRSxVQUFDLElBQWU7WUFDbkQsSUFBSSxHQUFHLEdBQVcsbUNBQW1DLENBQUM7WUFDdEQsSUFBSSxRQUFRLEdBQVcsQ0FBQyxDQUFDO1lBQ3pCLDBCQUEwQixDQUN4Qix5REFBbUQsR0FBRyx1QkFBZ0IsUUFBUSxTQUFJO2dCQUNsRiwyQkFBeUIsRUFDekIsT0FBTyxDQUFDLHdCQUF3QixFQUNoQyxVQUFDLFlBQTZDO2dCQUM1QyxNQUFNLENBQUMsWUFBWSxDQUFDLE1BQU0sQ0FBQyxDQUFDLEVBQUUsQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUFDLGdCQUFnQixDQUFDLGlCQUFpQixDQUFDLENBQUM7Z0JBQ2pGLE1BQU0sQ0FBQyxZQUFZLENBQUMsUUFBUSxDQUFDLENBQUMsRUFBRSxDQUFDLEtBQUssQ0FBQyxRQUFRLENBQUMsQ0FBQztnQkFDakQsTUFBTSxDQUFDLFlBQVksQ0FBQyxjQUFjLENBQUMsTUFBTSxDQUFDLENBQUMsRUFBRSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQztnQkFDdkQsTUFBTSxDQUFDLFlBQVksQ0FBQyxTQUFTLENBQUMsQ0FBQyxFQUFFLENBQUMsS0FBSyxDQUFDLEdBQUcsQ0FBQyxDQUFDO2dCQUM3QyxJQUFJLEVBQUUsQ0FBQztZQUNULENBQUMsQ0FDRixDQUFDO1FBQ0osQ0FBQyxDQUFDLENBQUM7UUFFSCxFQUFFLENBQUMsaUNBQWlDLEVBQUUsVUFBQyxJQUFlO1lBQ3BELElBQU0sRUFBRSxHQUFHLEdBQUcsQ0FBQztZQUNmLElBQU0sY0FBYyxHQUFHLFlBQVksQ0FBQztZQUNwQyxJQUFNLE9BQU8sR0FBRyxvQkFBb0IsQ0FBQztZQUNyQyxJQUFNLElBQUksR0FBRyx5QkFBeUIsQ0FBQztZQUN2QyxJQUFNLFFBQVEsR0FBRyxnQ0FBZ0MsQ0FBQztZQUNsRCxJQUFNLFFBQVEsR0FBRywrQ0FBK0MsQ0FBQztZQUNqRSxJQUFNLElBQUksR0FBRyxFQUFFLENBQUM7WUFDaEIsSUFBTSxXQUFXLEdBQUcsSUFBSSxDQUFDO1lBQ3pCLElBQU0sUUFBUSxHQUFHLENBQUMsQ0FBQztZQUNuQixJQUFNLFdBQVcsR0FBRyxDQUFDLENBQUM7WUFDdEIsSUFBTSxXQUFXLEdBQUcsQ0FBQyxDQUFDO1lBQ3RCLElBQU0sU0FBUyxHQUFHLENBQUMsQ0FBQztZQUNwQixJQUFNLGVBQWUsR0FBRyxNQUFNLENBQUM7WUFDL0IsSUFBTSxRQUFRLEdBQUcsRUFBRSxDQUFDO1lBQ3BCLElBQU0sU0FBUyxHQUFHLG1CQUFtQixDQUFDO1lBQ3RDLElBQU0sSUFBSSxHQUFHLFNBQVMsQ0FBQztZQUN2QixJQUFNLEVBQUUsR0FBTSxPQUFPLFNBQUksSUFBTSxDQUFDO1lBQ2hDLElBQU0sV0FBVyxHQUFHLFFBQVEsQ0FBQztZQUM3QixJQUFNLElBQUksR0FBRyxNQUFNLENBQUM7WUFFcEIsMEJBQTBCLENBQ3hCLDBDQUFzQyxFQUFFLGtCQUFXLGNBQWMsdUJBQWdCO2dCQUNqRiwyQkFBcUIsT0FBTyxrQkFBVyxJQUFJLGtCQUFXLFFBQVEsU0FBSTtnQkFDbEUsaUJBQWEsUUFBUSxrQkFBVyxJQUFJLDRCQUFxQixXQUFXLFVBQUs7Z0JBQ3pFLGNBQVUsUUFBUSxvQkFBYSxXQUFXLG9CQUFhLFdBQVcsU0FBSTtnQkFDdEUsMEJBQXNCLGVBQWUscUJBQWMsZUFBZSxTQUFJO2dCQUN0RSxlQUFXLFFBQVEsa0JBQVcsU0FBUyxrQkFBVyxJQUFJLGdCQUFTLEVBQUUsU0FBSTtnQkFDckUsYUFBUyxTQUFTLDBCQUFtQixXQUFXLGtCQUFXLElBQUksU0FBSTtnQkFDbkUsa0JBQWdCLEVBQ2hCLE9BQU8sQ0FBQyx5QkFBeUIsRUFDakMsVUFBQyxDQUFtQztnQkFDbEMsSUFBTSxFQUFFLEdBQUcsQ0FBQyxDQUFDLFVBQVUsQ0FBQztnQkFDeEIsTUFBTSxDQUFDLEVBQUUsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLElBQUksRUFBRSxFQUFFLENBQUMsQ0FBQztnQkFDdEMsTUFBTSxDQUFDLEVBQUUsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLGdCQUFnQixFQUFFLGNBQWMsQ0FBQyxDQUFDO2dCQUM5RCxNQUFNLENBQUMsRUFBRSxDQUFDLENBQUMsRUFBRSxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsUUFBUSxFQUFFLEtBQUssQ0FBQyxDQUFDO2dCQUM3QyxNQUFNLENBQUMsRUFBRSxDQUFDLENBQUMsRUFBRSxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsV0FBVyxFQUFFLElBQUksQ0FBQyxDQUFDO2dCQUMvQyxNQUFNLENBQUMsRUFBRSxDQUFDLENBQUMsRUFBRSxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsV0FBVyxDQUFDLENBQUMsRUFBRSxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQztnQkFDdEQsTUFBTSxDQUFDLEVBQUUsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLFNBQVMsRUFBRSxlQUFlLENBQUMsQ0FBQztnQkFDeEQsTUFBTSxDQUFDLEVBQUUsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLFVBQVUsRUFBRSxRQUFRLENBQUMsQ0FBQztnQkFDbEQsTUFBTSxDQUFDLEVBQUUsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLFdBQVcsRUFBRSxTQUFTLENBQUMsQ0FBQztnQkFDcEQsTUFBTSxDQUFDLEVBQUUsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLGFBQWEsRUFBRSxXQUFXLENBQUMsQ0FBQztnQkFDeEQsTUFBTSxDQUFDLEVBQUUsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLGFBQWEsRUFBRSxXQUFXLENBQUMsQ0FBQztnQkFDeEQsTUFBTSxDQUFDLEVBQUUsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLGtCQUFrQixFQUFFLGVBQWUsQ0FBQyxDQUFDO2dCQUNqRSxNQUFNLENBQUMsRUFBRSxDQUFDLENBQUMsRUFBRSxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsVUFBVSxFQUFFLFFBQVEsQ0FBQyxDQUFDO2dCQUNsRCxNQUFNLENBQUMsRUFBRSxDQUFDLENBQUMsRUFBRSxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsTUFBTSxFQUFFLElBQUksQ0FBQyxDQUFDO2dCQUMxQyxNQUFNLENBQUMsRUFBRSxDQUFDLENBQUMsRUFBRSxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsV0FBVyxFQUFFLFNBQVMsQ0FBQyxDQUFDO2dCQUNwRCxNQUFNLENBQUMsRUFBRSxDQUFDLENBQUMsRUFBRSxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsYUFBYSxFQUFFLFdBQVcsQ0FBQyxDQUFDO2dCQUN4RCxNQUFNLENBQUMsRUFBRSxDQUFDLENBQUMsRUFBRSxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsTUFBTSxFQUFFLElBQUksQ0FBQyxDQUFDO2dCQUMxQyxNQUFNLENBQUMsRUFBRSxDQUFDLENBQUMsRUFBRSxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsYUFBYSxFQUFFLElBQUksQ0FBQyxDQUFDO2dCQUVqRCxJQUFNLEtBQUssR0FBRyxFQUFFLENBQUMsU0FBUyxDQUFDLENBQUMsQ0FBQyxDQUFDO2dCQUM5QixNQUFNLENBQUMsS0FBSyxDQUFDLENBQUMsRUFBRSxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsSUFBSSxFQUFFLEVBQUUsQ0FBQyxRQUFRLEVBQUUsQ0FBQyxDQUFDO2dCQUNwRCxNQUFNLENBQUMsS0FBSyxDQUFDLENBQUMsRUFBRSxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsU0FBUyxFQUFFLE9BQU8sQ0FBQyxDQUFDO2dCQUNuRCxNQUFNLENBQUMsS0FBSyxDQUFDLENBQUMsRUFBRSxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsTUFBTSxFQUFFLElBQUksQ0FBQyxDQUFDO2dCQUM3QyxNQUFNLENBQUMsS0FBSyxDQUFDLENBQUMsRUFBRSxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsVUFBVSxFQUFFLFFBQVEsQ0FBQyxDQUFDO2dCQUNyRCxNQUFNLENBQUMsS0FBSyxDQUFDLENBQUMsRUFBRSxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsVUFBVSxFQUFFLFFBQVEsQ0FBQyxDQUFDO2dCQUNyRCxNQUFNLENBQUMsS0FBSyxDQUFDLENBQUMsRUFBRSxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsTUFBTSxFQUFFLElBQUksQ0FBQyxDQUFDO2dCQUM3QyxNQUFNLENBQUMsS0FBSyxDQUFDLENBQUMsRUFBRSxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsSUFBSSxFQUFFLEVBQUUsQ0FBQyxDQUFDO2dCQUV6QyxJQUFJLEVBQUUsQ0FBQztZQUNULENBQUMsQ0FDRixDQUFDO1FBQ0osQ0FBQyxDQUFDLENBQUM7SUFDTCxDQUFDLENBQUMsQ0FBQztJQUNMOzs7Ozs7Ozs7Ozs7Ozs7OztNQWlCRTtBQUNGLENBQUMsQ0FBQyxDQUFDIn0=