UNPKG

@push.rocks/smartdata

Version:

An advanced library for NoSQL data organization and manipulation using TypeScript with support for MongoDB, data validation, collections, and custom data types.

314 lines 28.6 kB
var __esDecorate = (this && this.__esDecorate) || function (ctor, descriptorIn, decorators, contextIn, initializers, extraInitializers) { function accept(f) { if (f !== void 0 && typeof f !== "function") throw new TypeError("Function expected"); return f; } var kind = contextIn.kind, key = kind === "getter" ? "get" : kind === "setter" ? "set" : "value"; var target = !descriptorIn && ctor ? contextIn["static"] ? ctor : ctor.prototype : null; var descriptor = descriptorIn || (target ? Object.getOwnPropertyDescriptor(target, contextIn.name) : {}); var _, done = false; for (var i = decorators.length - 1; i >= 0; i--) { var context = {}; for (var p in contextIn) context[p] = p === "access" ? {} : contextIn[p]; for (var p in contextIn.access) context.access[p] = contextIn.access[p]; context.addInitializer = function (f) { if (done) throw new TypeError("Cannot add initializers after decoration has completed"); extraInitializers.push(accept(f || null)); }; var result = (0, decorators[i])(kind === "accessor" ? { get: descriptor.get, set: descriptor.set } : descriptor[key], context); if (kind === "accessor") { if (result === void 0) continue; if (result === null || typeof result !== "object") throw new TypeError("Object expected"); if (_ = accept(result.get)) descriptor.get = _; if (_ = accept(result.set)) descriptor.set = _; if (_ = accept(result.init)) initializers.unshift(_); } else if (_ = accept(result)) { if (kind === "field") initializers.unshift(_); else descriptor[key] = _; } } if (target) Object.defineProperty(target, contextIn.name, descriptor); done = true; }; var __runInitializers = (this && this.__runInitializers) || function (thisArg, initializers, value) { var useValue = arguments.length > 2; for (var i = 0; i < initializers.length; i++) { value = useValue ? initializers[i].call(thisArg, value) : initializers[i].call(thisArg); } return useValue ? value : void 0; }; import * as plugins from './plugins.js'; import { SmartdataDb } from './classes.db.js'; import { managed, setDefaultManagerForDoc } from './classes.collection.js'; import { SmartDataDbDoc, svDb, unI } from './classes.doc.js'; import { SmartdataDbWatcher } from './classes.watcher.js'; import { logger } from './logging.js'; let DistributedClass = (() => { let _classDecorators = [managed()]; let _classDescriptor; let _classExtraInitializers = []; let _classThis; let _classSuper = SmartDataDbDoc; let _id_decorators; let _id_initializers = []; let _id_extraInitializers = []; let _data_decorators; let _data_initializers = []; let _data_extraInitializers = []; var DistributedClass = class extends _classSuper { static { _classThis = this; } static { const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(_classSuper[Symbol.metadata] ?? null) : void 0; _id_decorators = [unI()]; _data_decorators = [svDb()]; __esDecorate(null, null, _id_decorators, { kind: "field", name: "id", static: false, private: false, access: { has: obj => "id" in obj, get: obj => obj.id, set: (obj, value) => { obj.id = value; } }, metadata: _metadata }, _id_initializers, _id_extraInitializers); __esDecorate(null, null, _data_decorators, { kind: "field", name: "data", static: false, private: false, access: { has: obj => "data" in obj, get: obj => obj.data, set: (obj, value) => { obj.data = value; } }, metadata: _metadata }, _data_initializers, _data_extraInitializers); __esDecorate(null, _classDescriptor = { value: _classThis }, _classDecorators, { kind: "class", name: _classThis.name, metadata: _metadata }, null, _classExtraInitializers); DistributedClass = _classThis = _classDescriptor.value; if (_metadata) Object.defineProperty(_classThis, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata }); __runInitializers(_classThis, _classExtraInitializers); } // INSTANCE id = __runInitializers(this, _id_initializers, void 0); data = (__runInitializers(this, _id_extraInitializers), __runInitializers(this, _data_initializers, void 0)); constructor() { super(...arguments); __runInitializers(this, _data_extraInitializers); } }; return DistributedClass = _classThis; })(); export { DistributedClass }; /** * This file implements a distributed coordinator according to the @pushrocks/taskbuffer standard. * you should not set up this yourself. Instead, there is a factory on the SmartdataDb class * that will take care of setting this up. */ export class SmartdataDistributedCoordinator extends plugins.taskbuffer.distributedCoordination .AbstractDistributedCoordinator { readyPromise; db; asyncExecutionStack = new plugins.lik.AsyncExecutionStack(); ownInstance; distributedWatcher; constructor(dbArg) { super(); this.db = dbArg; setDefaultManagerForDoc(this, DistributedClass); this.readyPromise = this.db.statusConnectedDeferred.promise; } // smartdata specific stuff async start() { await this.init(); } async stop() { await this.asyncExecutionStack.getExclusiveExecutionSlot(async () => { if (this.distributedWatcher) { await this.distributedWatcher.close(); } if (this.ownInstance?.data.elected) { this.ownInstance.data.elected = false; } if (this.ownInstance?.data.status === 'stopped') { logger.log('warn', `stopping a distributed instance that has not been started yet.`); } this.ownInstance.data.status = 'stopped'; await this.ownInstance.save(); logger.log('info', `stopped ${this.ownInstance.id}`); }); } id = plugins.smartunique.uni('distributedInstance'); startHeartbeat = async () => { while (this.ownInstance.data.status !== 'stopped') { await this.sendHeartbeat(); await plugins.smartdelay.delayForRandom(5000, 10000); } }; async sendHeartbeat() { await this.asyncExecutionStack.getExclusiveExecutionSlot(async () => { if (this.ownInstance.data.status === 'stopped') { logger.log('debug', `aborted sending heartbeat because status is stopped`); return; } await this.ownInstance.updateFromDb(); this.ownInstance.data.lastUpdated = Date.now(); await this.ownInstance.save(); logger.log('debug', `sent heartbeat for ${this.ownInstance.id}`); const allInstances = DistributedClass.getInstances({}); }); if (this.ownInstance.data.status === 'stopped') { logger.log('info', `aborted sending heartbeat because status is stopped`); return; } const eligibleLeader = await this.getEligibleLeader(); // not awaiting here because we don't want to block the heartbeat this.asyncExecutionStack.getExclusiveExecutionSlot(async () => { if (!eligibleLeader && this.ownInstance.data.status === 'settled') { this.checkAndMaybeLead(); } }); } async init() { await this.readyPromise; if (!this.ownInstance) { await this.asyncExecutionStack.getExclusiveExecutionSlot(async () => { this.ownInstance = new DistributedClass(); this.ownInstance.id = this.id; this.ownInstance.data = { elected: false, lastUpdated: Date.now(), status: 'initializing', taskRequests: [], taskRequestResults: [], }; await this.ownInstance.save(); }); } else { logger.log('warn', `distributed instance already initialized`); } // lets enable the heartbeat this.startHeartbeat(); // lets do a leader check await this.checkAndMaybeLead(); return this.ownInstance; } async getEligibleLeader() { return this.asyncExecutionStack.getExclusiveExecutionSlot(async () => { const allInstances = await DistributedClass.getInstances({}); let leaders = allInstances.filter((instanceArg) => instanceArg.data.elected === true); const eligibleLeader = leaders.find((leader) => leader.data.lastUpdated >= Date.now() - plugins.smarttime.getMilliSecondsFromUnits({ seconds: 20 })); return eligibleLeader; }); } // --> leader election async checkAndMaybeLead() { await this.asyncExecutionStack.getExclusiveExecutionSlot(async () => { this.ownInstance.data.status = 'initializing'; await this.ownInstance.save(); }); if (await this.getEligibleLeader()) { await this.asyncExecutionStack.getExclusiveExecutionSlot(async () => { await this.ownInstance.updateFromDb(); this.ownInstance.data.status = 'settled'; await this.ownInstance.save(); logger.log('info', `${this.ownInstance.id} settled as follower`); }); return; } else if ((await DistributedClass.getInstances({})).find((instanceArg) => { return instanceArg.data.status === 'bidding' && instanceArg.data.biddingStartTime <= Date.now() - 4000 && instanceArg.data.biddingStartTime >= Date.now() - 30000; })) { logger.log('info', 'too late to the bidding party... waiting for next round.'); return; } else { await this.asyncExecutionStack.getExclusiveExecutionSlot(async () => { await this.ownInstance.updateFromDb(); this.ownInstance.data.status = 'bidding'; this.ownInstance.data.biddingStartTime = Date.now(); this.ownInstance.data.biddingShortcode = plugins.smartunique.shortId(); await this.ownInstance.save(); logger.log('info', 'bidding code stored.'); }); logger.log('info', `bidding for leadership...`); await plugins.smartdelay.delayFor(plugins.smarttime.getMilliSecondsFromUnits({ seconds: 5 })); await this.asyncExecutionStack.getExclusiveExecutionSlot(async () => { let biddingInstances = await DistributedClass.getInstances({}); biddingInstances = biddingInstances.filter((instanceArg) => instanceArg.data.status === 'bidding' && instanceArg.data.lastUpdated >= Date.now() - plugins.smarttime.getMilliSecondsFromUnits({ seconds: 10 })); logger.log('info', `found ${biddingInstances.length} bidding instances...`); this.ownInstance.data.elected = true; for (const biddingInstance of biddingInstances) { if (biddingInstance.data.biddingShortcode < this.ownInstance.data.biddingShortcode) { this.ownInstance.data.elected = false; } } await plugins.smartdelay.delayFor(5000); logger.log('info', `settling with status elected = ${this.ownInstance.data.elected}`); this.ownInstance.data.status = 'settled'; await this.ownInstance.save(); }); if (this.ownInstance.data.elected) { this.leadFunction(); } } } /** * when it has been determined * that this instance is leading * the leading is implemented here */ async leadFunction() { this.distributedWatcher = await DistributedClass.watch({}); const currentTaskRequests = []; this.distributedWatcher.changeSubject.subscribe({ next: async (distributedDoc) => { if (!distributedDoc) { logger.log('info', `registered deletion of instance...`); return; } logger.log('info', distributedDoc); logger.log('info', `registered change for ${distributedDoc.id}`); distributedDoc; }, }); while (this.ownInstance.data.status !== 'stopped' && this.ownInstance.data.elected) { const allInstances = await DistributedClass.getInstances({}); for (const instance of allInstances) { if (instance.data.status === 'stopped') { await instance.delete(); } } await plugins.smartdelay.delayFor(10000); } } // abstract implemented methods async fireDistributedTaskRequest(taskRequestArg) { await this.asyncExecutionStack.getExclusiveExecutionSlot(async () => { if (!this.ownInstance) { logger.log('error', 'instance need to be started first...'); return; } await this.ownInstance.updateFromDb(); this.ownInstance.data.taskRequests.push(taskRequestArg); await this.ownInstance.save(); }); await plugins.smartdelay.delayFor(10000); const result = await this.asyncExecutionStack.getExclusiveExecutionSlot(async () => { await this.ownInstance.updateFromDb(); const taskRequestResult = this.ownInstance.data.taskRequestResults.find((resultItem) => { return resultItem.requestResponseId === taskRequestArg.requestResponseId; }); return taskRequestResult; }); if (!result) { logger.log('warn', 'no result found for task request...'); return null; } return result; } async updateDistributedTaskRequest(infoBasisArg) { await this.asyncExecutionStack.getExclusiveExecutionSlot(async () => { const existingInfoBasis = this.ownInstance.data.taskRequests.find((infoBasisItem) => { return (infoBasisItem.taskName === infoBasisArg.taskName && infoBasisItem.taskExecutionTime === infoBasisArg.taskExecutionTime); }); if (!existingInfoBasis) { logger.log('warn', 'trying to update a non existing task request... aborting!'); return; } Object.assign(existingInfoBasis, infoBasisArg); await this.ownInstance.save(); plugins.smartdelay.delayFor(60000).then(() => { this.asyncExecutionStack.getExclusiveExecutionSlot(async () => { const indexToRemove = this.ownInstance.data.taskRequests.indexOf(existingInfoBasis); if (indexToRemove >= 0) { this.ownInstance.data.taskRequests.splice(indexToRemove, 1); await this.ownInstance.save(); } }); }); }); } } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xhc3Nlcy5kaXN0cmlidXRlZGNvb3JkaW5hdG9yLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vdHMvY2xhc3Nlcy5kaXN0cmlidXRlZGNvb3JkaW5hdG9yLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFBQSxPQUFPLEtBQUssT0FBTyxNQUFNLGNBQWMsQ0FBQztBQUN4QyxPQUFPLEVBQUUsV0FBVyxFQUFFLE1BQU0saUJBQWlCLENBQUM7QUFDOUMsT0FBTyxFQUFFLE9BQU8sRUFBRSx1QkFBdUIsRUFBRSxNQUFNLHlCQUF5QixDQUFDO0FBQzNFLE9BQU8sRUFBRSxjQUFjLEVBQUUsSUFBSSxFQUFFLEdBQUcsRUFBRSxNQUFNLGtCQUFrQixDQUFDO0FBQzdELE9BQU8sRUFBRSxrQkFBa0IsRUFBRSxNQUFNLHNCQUFzQixDQUFDO0FBQzFELE9BQU8sRUFBRSxNQUFNLEVBQUUsTUFBTSxjQUFjLENBQUM7SUFHekIsZ0JBQWdCOzRCQUQ1QixPQUFPLEVBQUU7Ozs7c0JBQzRCLGNBQWM7Ozs7Ozs7Z0NBQXRCLFNBQVEsV0FBa0Q7Ozs7OEJBRXJGLEdBQUcsRUFBRTtnQ0FHTCxJQUFJLEVBQUU7WUFGUCx3SkFBTyxFQUFFLDZCQUFGLEVBQUUsK0VBQVU7WUFHbkIsOEpBQU8sSUFBSSw2QkFBSixJQUFJLG1GQWVUO1lBckJKLDZLQXNCQzs7O1lBdEJZLHVEQUFnQjs7UUFDM0IsV0FBVztRQUVKLEVBQUUscURBQVU7UUFHWixJQUFJLHlHQWVUOzs7Ozs7OztTQXJCUyxnQkFBZ0I7QUF3QjdCOzs7O0dBSUc7QUFDSCxNQUFNLE9BQU8sK0JBQWdDLFNBQVEsT0FBTyxDQUFDLFVBQVUsQ0FBQyx1QkFBdUI7S0FDNUYsOEJBQThCO0lBQ3hCLFlBQVksQ0FBZTtJQUMzQixFQUFFLENBQWM7SUFDZixtQkFBbUIsR0FBRyxJQUFJLE9BQU8sQ0FBQyxHQUFHLENBQUMsbUJBQW1CLEVBQUUsQ0FBQztJQUM3RCxXQUFXLENBQW9CO0lBQy9CLGtCQUFrQixDQUF3QztJQUVqRSxZQUFZLEtBQWtCO1FBQzVCLEtBQUssRUFBRSxDQUFDO1FBQ1IsSUFBSSxDQUFDLEVBQUUsR0FBRyxLQUFLLENBQUM7UUFDaEIsdUJBQXVCLENBQUMsSUFBSSxFQUFFLGdCQUFnQixDQUFDLENBQUM7UUFDaEQsSUFBSSxDQUFDLFlBQVksR0FBRyxJQUFJLENBQUMsRUFBRSxDQUFDLHVCQUF1QixDQUFDLE9BQU8sQ0FBQztJQUM5RCxDQUFDO0lBRUQsMkJBQTJCO0lBQ3BCLEtBQUssQ0FBQyxLQUFLO1FBQ2hCLE1BQU0sSUFBSSxDQUFDLElBQUksRUFBRSxDQUFDO0lBQ3BCLENBQUM7SUFFTSxLQUFLLENBQUMsSUFBSTtRQUNmLE1BQU0sSUFBSSxDQUFDLG1CQUFtQixDQUFDLHlCQUF5QixDQUFDLEtBQUssSUFBSSxFQUFFO1lBQ2xFLElBQUksSUFBSSxDQUFDLGtCQUFrQixFQUFFLENBQUM7Z0JBQzVCLE1BQU0sSUFBSSxDQUFDLGtCQUFrQixDQUFDLEtBQUssRUFBRSxDQUFDO1lBQ3hDLENBQUM7WUFDRCxJQUFJLElBQUksQ0FBQyxXQUFXLEVBQUUsSUFBSSxDQUFDLE9BQU8sRUFBRSxDQUFDO2dCQUNuQyxJQUFJLENBQUMsV0FBVyxDQUFDLElBQUksQ0FBQyxPQUFPLEdBQUcsS0FBSyxDQUFDO1lBQ3hDLENBQUM7WUFDRCxJQUFJLElBQUksQ0FBQyxXQUFXLEVBQUUsSUFBSSxDQUFDLE1BQU0sS0FBSyxTQUFTLEVBQUUsQ0FBQztnQkFDaEQsTUFBTSxDQUFDLEdBQUcsQ0FBQyxNQUFNLEVBQUUsZ0VBQWdFLENBQUMsQ0FBQztZQUN2RixDQUFDO1lBQ0QsSUFBSSxDQUFDLFdBQVcsQ0FBQyxJQUFJLENBQUMsTUFBTSxHQUFHLFNBQVMsQ0FBQztZQUN6QyxNQUFNLElBQUksQ0FBQyxXQUFXLENBQUMsSUFBSSxFQUFFLENBQUM7WUFDOUIsTUFBTSxDQUFDLEdBQUcsQ0FBQyxNQUFNLEVBQUUsV0FBVyxJQUFJLENBQUMsV0FBVyxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUM7UUFDdkQsQ0FBQyxDQUFDLENBQUM7SUFDTCxDQUFDO0lBRU0sRUFBRSxHQUFHLE9BQU8sQ0FBQyxXQUFXLENBQUMsR0FBRyxDQUFDLHFCQUFxQixDQUFDLENBQUM7SUFFbkQsY0FBYyxHQUFHLEtBQUssSUFBSSxFQUFFO1FBQ2xDLE9BQU8sSUFBSSxDQUFDLFdBQVcsQ0FBQyxJQUFJLENBQUMsTUFBTSxLQUFLLFNBQVMsRUFBRSxDQUFDO1lBQ2xELE1BQU0sSUFBSSxDQUFDLGFBQWEsRUFBRSxDQUFDO1lBQzNCLE1BQU0sT0FBTyxDQUFDLFVBQVUsQ0FBQyxjQUFjLENBQUMsSUFBSSxFQUFFLEtBQUssQ0FBQyxDQUFDO1FBQ3ZELENBQUM7SUFDSCxDQUFDLENBQUM7SUFFSyxLQUFLLENBQUMsYUFBYTtRQUN4QixNQUFNLElBQUksQ0FBQyxtQkFBbUIsQ0FBQyx5QkFBeUIsQ0FBQyxLQUFLLElBQUksRUFBRTtZQUNsRSxJQUFJLElBQUksQ0FBQyxXQUFXLENBQUMsSUFBSSxDQUFDLE1BQU0sS0FBSyxTQUFTLEVBQUUsQ0FBQztnQkFDL0MsTUFBTSxDQUFDLEdBQUcsQ0FBQyxPQUFPLEVBQUUscURBQXFELENBQUMsQ0FBQztnQkFDM0UsT0FBTztZQUNULENBQUM7WUFDRCxNQUFNLElBQUksQ0FBQyxXQUFXLENBQUMsWUFBWSxFQUFFLENBQUM7WUFDdEMsSUFBSSxDQUFDLFdBQVcsQ0FBQyxJQUFJLENBQUMsV0FBVyxHQUFHLElBQUksQ0FBQyxHQUFHLEVBQUUsQ0FBQztZQUMvQyxNQUFNLElBQUksQ0FBQyxXQUFXLENBQUMsSUFBSSxFQUFFLENBQUM7WUFDOUIsTUFBTSxDQUFDLEdBQUcsQ0FBQyxPQUFPLEVBQUUsc0JBQXNCLElBQUksQ0FBQyxXQUFXLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQztZQUNqRSxNQUFNLFlBQVksR0FBRyxnQkFBZ0IsQ0FBQyxZQUFZLENBQUMsRUFBRSxDQUFDLENBQUM7UUFDekQsQ0FBQyxDQUFDLENBQUM7UUFDSCxJQUFJLElBQUksQ0FBQyxXQUFXLENBQUMsSUFBSSxDQUFDLE1BQU0sS0FBSyxTQUFTLEVBQUUsQ0FBQztZQUMvQyxNQUFNLENBQUMsR0FBRyxDQUFDLE1BQU0sRUFBRSxxREFBcUQsQ0FBQyxDQUFDO1lBQzFFLE9BQU87UUFDVCxDQUFDO1FBQ0QsTUFBTSxjQUFjLEdBQUcsTUFBTSxJQUFJLENBQUMsaUJBQWlCLEVBQUUsQ0FBQztRQUN0RCxpRUFBaUU7UUFDakUsSUFBSSxDQUFDLG1CQUFtQixDQUFDLHlCQUF5QixDQUFDLEtBQUssSUFBSSxFQUFFO1lBQzVELElBQUksQ0FBQyxjQUFjLElBQUksSUFBSSxDQUFDLFdBQVcsQ0FBQyxJQUFJLENBQUMsTUFBTSxLQUFLLFNBQVMsRUFBRSxDQUFDO2dCQUNsRSxJQUFJLENBQUMsaUJBQWlCLEVBQUUsQ0FBQztZQUMzQixDQUFDO1FBQ0gsQ0FBQyxDQUFDLENBQUM7SUFDTCxDQUFDO0lBQ08sS0FBSyxDQUFDLElBQUk7UUFDaEIsTUFBTSxJQUFJLENBQUMsWUFBWSxDQUFDO1FBQ3hCLElBQUksQ0FBQyxJQUFJLENBQUMsV0FBVyxFQUFFLENBQUM7WUFDdEIsTUFBTSxJQUFJLENBQUMsbUJBQW1CLENBQUMseUJBQXlCLENBQUMsS0FBSyxJQUFJLEVBQUU7Z0JBQ2xFLElBQUksQ0FBQyxXQUFXLEdBQUcsSUFBSSxnQkFBZ0IsRUFBRSxDQUFDO2dCQUMxQyxJQUFJLENBQUMsV0FBVyxDQUFDLEVBQUUsR0FBRyxJQUFJLENBQUMsRUFBRSxDQUFDO2dCQUM5QixJQUFJLENBQUMsV0FBVyxDQUFDLElBQUksR0FBRztvQkFDdEIsT0FBTyxFQUFFLEtBQUs7b0JBQ2QsV0FBVyxFQUFFLElBQUksQ0FBQyxHQUFHLEVBQUU7b0JBQ3ZCLE1BQU0sRUFBRSxjQUFjO29CQUN0QixZQUFZLEVBQUUsRUFBRTtvQkFDaEIsa0JBQWtCLEVBQUUsRUFBRTtpQkFDdkIsQ0FBQztnQkFDRixNQUFNLElBQUksQ0FBQyxXQUFXLENBQUMsSUFBSSxFQUFFLENBQUM7WUFDaEMsQ0FBQyxDQUFDLENBQUM7UUFDTCxDQUFDO2FBQU0sQ0FBQztZQUNOLE1BQU0sQ0FBQyxHQUFHLENBQUMsTUFBTSxFQUFFLDBDQUEwQyxDQUFDLENBQUM7UUFDakUsQ0FBQztRQUVELDRCQUE0QjtRQUM1QixJQUFJLENBQUMsY0FBYyxFQUFFLENBQUM7UUFFdEIseUJBQXlCO1FBQ3pCLE1BQU0sSUFBSSxDQUFDLGlCQUFpQixFQUFFLENBQUM7UUFFL0IsT0FBTyxJQUFJLENBQUMsV0FBVyxDQUFDO0lBQzFCLENBQUM7SUFFTSxLQUFLLENBQUMsaUJBQWlCO1FBQzVCLE9BQU8sSUFBSSxDQUFDLG1CQUFtQixDQUFDLHlCQUF5QixDQUFDLEtBQUssSUFBSSxFQUFFO1lBQ25FLE1BQU0sWUFBWSxHQUFHLE1BQU0sZ0JBQWdCLENBQUMsWUFBWSxDQUFDLEVBQUUsQ0FBQyxDQUFDO1lBQzdELElBQUksT0FBTyxHQUFHLFlBQVksQ0FBQyxNQUFNLENBQUMsQ0FBQyxXQUFXLEVBQUUsRUFBRSxDQUFDLFdBQVcsQ0FBQyxJQUFJLENBQUMsT0FBTyxLQUFLLElBQUksQ0FBQyxDQUFDO1lBQ3RGLE1BQU0sY0FBYyxHQUFHLE9BQU8sQ0FBQyxJQUFJLENBQ2pDLENBQUMsTUFBTSxFQUFFLEVBQUUsQ0FDVCxNQUFNLENBQUMsSUFBSSxDQUFDLFdBQVc7Z0JBQ3ZCLElBQUksQ0FBQyxHQUFHLEVBQUUsR0FBRyxPQUFPLENBQUMsU0FBUyxDQUFDLHdCQUF3QixDQUFDLEVBQUUsT0FBTyxFQUFFLEVBQUUsRUFBRSxDQUFDLENBQzNFLENBQUM7WUFDRixPQUFPLGNBQWMsQ0FBQztRQUN4QixDQUFDLENBQUMsQ0FBQztJQUNMLENBQUM7SUFFRCxzQkFBc0I7SUFDZixLQUFLLENBQUMsaUJBQWlCO1FBQzVCLE1BQU0sSUFBSSxDQUFDLG1CQUFtQixDQUFDLHlCQUF5QixDQUFDLEtBQUssSUFBSSxFQUFFO1lBQ2xFLElBQUksQ0FBQyxXQUFXLENBQUMsSUFBSSxDQUFDLE1BQU0sR0FBRyxjQUFjLENBQUM7WUFDOUMsTUFBTSxJQUFJLENBQUMsV0FBVyxDQUFDLElBQUksRUFBRSxDQUFDO1FBQ2hDLENBQUMsQ0FBQyxDQUFDO1FBQ0gsSUFBSSxNQUFNLElBQUksQ0FBQyxpQkFBaUIsRUFBRSxFQUFFLENBQUM7WUFDbkMsTUFBTSxJQUFJLENBQUMsbUJBQW1CLENBQUMseUJBQXlCLENBQUMsS0FBSyxJQUFJLEVBQUU7Z0JBQ2xFLE1BQU0sSUFBSSxDQUFDLFdBQVcsQ0FBQyxZQUFZLEVBQUUsQ0FBQztnQkFDdEMsSUFBSSxDQUFDLFdBQVcsQ0FBQyxJQUFJLENBQUMsTUFBTSxHQUFHLFNBQVMsQ0FBQztnQkFDekMsTUFBTSxJQUFJLENBQUMsV0FBVyxDQUFDLElBQUksRUFBRSxDQUFDO2dCQUM5QixNQUFNLENBQUMsR0FBRyxDQUFDLE1BQU0sRUFBRSxHQUFHLElBQUksQ0FBQyxXQUFXLENBQUMsRUFBRSxzQkFBc0IsQ0FBQyxDQUFDO1lBQ25FLENBQUMsQ0FBQyxDQUFDO1lBQ0gsT0FBTztRQUNULENBQUM7YUFBTSxJQUNMLENBQUMsTUFBTSxnQkFBZ0IsQ0FBQyxZQUFZLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsQ0FBQyxXQUFXLEVBQUUsRUFBRTtZQUM3RCxPQUFPLFdBQVcsQ0FBQyxJQUFJLENBQUMsTUFBTSxLQUFLLFNBQVM7Z0JBQzFDLFdBQVcsQ0FBQyxJQUFJLENBQUMsZ0JBQWlCLElBQUksSUFBSSxDQUFDLEdBQUcsRUFBRSxHQUFHLElBQUk7Z0JBQ3ZELFdBQVcsQ0FBQyxJQUFJLENBQUMsZ0JBQWlCLElBQUksSUFBSSxDQUFDLEdBQUcsRUFBRSxHQUFHLEtBQUssQ0FBQztRQUM3RCxDQUFDLENBQUMsRUFDRixDQUFDO1lBQ0QsTUFBTSxDQUFDLEdBQUcsQ0FBQyxNQUFNLEVBQUUsMERBQTBELENBQUMsQ0FBQztZQUMvRSxPQUFPO1FBQ1QsQ0FBQzthQUFNLENBQUM7WUFDTixNQUFNLElBQUksQ0FBQyxtQkFBbUIsQ0FBQyx5QkFBeUIsQ0FBQyxLQUFLLElBQUksRUFBRTtnQkFDbEUsTUFBTSxJQUFJLENBQUMsV0FBVyxDQUFDLFlBQVksRUFBRSxDQUFDO2dCQUN0QyxJQUFJLENBQUMsV0FBVyxDQUFDLElBQUksQ0FBQyxNQUFNLEdBQUcsU0FBUyxDQUFDO2dCQUN6QyxJQUFJLENBQUMsV0FBVyxDQUFDLElBQUksQ0FBQyxnQkFBZ0IsR0FBRyxJQUFJLENBQUMsR0FBRyxFQUFFLENBQUM7Z0JBQ3BELElBQUksQ0FBQyxXQUFXLENBQUMsSUFBSSxDQUFDLGdCQUFnQixHQUFHLE9BQU8sQ0FBQyxXQUFXLENBQUMsT0FBTyxFQUFFLENBQUM7Z0JBQ3ZFLE1BQU0sSUFBSSxDQUFDLFdBQVcsQ0FBQyxJQUFJLEVBQUUsQ0FBQztnQkFDOUIsTUFBTSxDQUFDLEdBQUcsQ0FBQyxNQUFNLEVBQUUsc0JBQXNCLENBQUMsQ0FBQztZQUM3QyxDQUFDLENBQUMsQ0FBQztZQUNILE1BQU0sQ0FBQyxHQUFHLENBQUMsTUFBTSxFQUFFLDJCQUEyQixDQUFDLENBQUM7WUFDaEQsTUFBTSxPQUFPLENBQUMsVUFBVSxDQUFDLFFBQVEsQ0FBQyxPQUFPLENBQUMsU0FBUyxDQUFDLHdCQUF3QixDQUFDLEVBQUUsT0FBTyxFQUFFLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQztZQUM5RixNQUFNLElBQUksQ0FBQyxtQkFBbUIsQ0FBQyx5QkFBeUIsQ0FBQyxLQUFLLElBQUksRUFBRTtnQkFDbEUsSUFBSSxnQkFBZ0IsR0FBRyxNQUFNLGdCQUFnQixDQUFDLFlBQVksQ0FBQyxFQUFFLENBQUMsQ0FBQztnQkFDL0QsZ0JBQWdCLEdBQUcsZ0JBQWdCLENBQUMsTUFBTSxDQUN4QyxDQUFDLFdBQVcsRUFBRSxFQUFFLENBQ2QsV0FBVyxDQUFDLElBQUksQ0FBQyxNQUFNLEtBQUssU0FBUztvQkFDckMsV0FBVyxDQUFDLElBQUksQ0FBQyxXQUFXO3dCQUMxQixJQUFJLENBQUMsR0FBRyxFQUFFLEdBQUcsT0FBTyxDQUFDLFNBQVMsQ0FBQyx3QkFBd0IsQ0FBQyxFQUFFLE9BQU8sRUFBRSxFQUFFLEVBQUUsQ0FBQyxDQUM3RSxDQUFDO2dCQUNGLE1BQU0sQ0FBQyxHQUFHLENBQUMsTUFBTSxFQUFFLFNBQVMsZ0JBQWdCLENBQUMsTUFBTSx1QkFBdUIsQ0FBQyxDQUFDO2dCQUM1RSxJQUFJLENBQUMsV0FBVyxDQUFDLElBQUksQ0FBQyxPQUFPLEdBQUcsSUFBSSxDQUFDO2dCQUNyQyxLQUFLLE1BQU0sZUFBZSxJQUFJLGdCQUFnQixFQUFFLENBQUM7b0JBQy9DLElBQUksZUFBZSxDQUFDLElBQUksQ0FBQyxnQkFBaUIsR0FBRyxJQUFJLENBQUMsV0FBVyxDQUFDLElBQUksQ0FBQyxnQkFBaUIsRUFBRSxDQUFDO3dCQUNyRixJQUFJLENBQUMsV0FBVyxDQUFDLElBQUksQ0FBQyxPQUFPLEdBQUcsS0FBSyxDQUFDO29CQUN4QyxDQUFDO2dCQUNILENBQUM7Z0JBQ0QsTUFBTSxPQUFPLENBQUMsVUFBVSxDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUMsQ0FBQztnQkFDeEMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxNQUFNLEVBQUUsa0NBQWtDLElBQUksQ0FBQyxXQUFXLENBQUMsSUFBSSxDQUFDLE9BQU8sRUFBRSxDQUFDLENBQUM7Z0JBQ3RGLElBQUksQ0FBQyxXQUFXLENBQUMsSUFBSSxDQUFDLE1BQU0sR0FBRyxTQUFTLENBQUM7Z0JBQ3pDLE1BQU0sSUFBSSxDQUFDLFdBQVcsQ0FBQyxJQUFJLEVBQUUsQ0FBQztZQUNoQyxDQUFDLENBQUMsQ0FBQztZQUNILElBQUksSUFBSSxDQUFDLFdBQVcsQ0FBQyxJQUFJLENBQUMsT0FBTyxFQUFFLENBQUM7Z0JBQ2xDLElBQUksQ0FBQyxZQUFZLEVBQUUsQ0FBQztZQUN0QixDQUFDO1FBQ0gsQ0FBQztJQUNILENBQUM7SUFFRDs7OztPQUlHO0lBQ0ksS0FBSyxDQUFDLFlBQVk7UUFDdkIsSUFBSSxDQUFDLGtCQUFrQixHQUFHLE1BQU0sZ0JBQWdCLENBQUMsS0FBSyxDQUFDLEVBQUUsQ0FBQyxDQUFDO1FBRTNELE1BQU0sbUJBQW1CLEdBUXBCLEVBQUUsQ0FBQztRQUVSLElBQUksQ0FBQyxrQkFBa0IsQ0FBQyxhQUFhLENBQUMsU0FBUyxDQUFDO1lBQzlDLElBQUksRUFBRSxLQUFLLEVBQUUsY0FBYyxFQUFFLEVBQUU7Z0JBQzdCLElBQUksQ0FBQyxjQUFjLEVBQUUsQ0FBQztvQkFDcEIsTUFBTSxDQUFDLEdBQUcsQ0FBQyxNQUFNLEVBQUUsb0NBQW9DLENBQUMsQ0FBQztvQkFDekQsT0FBTztnQkFDVCxDQUFDO2dCQUNELE1BQU0sQ0FBQyxHQUFHLENBQUMsTUFBTSxFQUFFLGNBQWMsQ0FBQyxDQUFDO2dCQUNuQyxNQUFNLENBQUMsR0FBRyxDQUFDLE1BQU0sRUFBRSx5QkFBeUIsY0FBYyxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUM7Z0JBQ2pFLGNBQWMsQ0FBQztZQUNqQixDQUFDO1NBQ0YsQ0FBQyxDQUFDO1FBRUgsT0FBTyxJQUFJLENBQUMsV0FBVyxDQUFDLElBQUksQ0FBQyxNQUFNLEtBQUssU0FBUyxJQUFJLElBQUksQ0FBQyxXQUFXLENBQUMsSUFBSSxDQUFDLE9BQU8sRUFBRSxDQUFDO1lBQ25GLE1BQU0sWUFBWSxHQUFHLE1BQU0sZ0JBQWdCLENBQUMsWUFBWSxDQUFDLEVBQUUsQ0FBQyxDQUFDO1lBQzdELEtBQUssTUFBTSxRQUFRLElBQUksWUFBWSxFQUFFLENBQUM7Z0JBQ3BDLElBQUksUUFBUSxDQUFDLElBQUksQ0FBQyxNQUFNLEtBQUssU0FBUyxFQUFFLENBQUM7b0JBQ3ZDLE1BQU0sUUFBUSxDQUFDLE1BQU0sRUFBRSxDQUFDO2dCQUMxQixDQUFDO1lBQ0gsQ0FBQztZQUNELE1BQU0sT0FBTyxDQUFDLFVBQVUsQ0FBQyxRQUFRLENBQUMsS0FBSyxDQUFDLENBQUM7UUFDM0MsQ0FBQztJQUNILENBQUM7SUFFRCwrQkFBK0I7SUFDeEIsS0FBSyxDQUFDLDBCQUEwQixDQUNyQyxjQUFrRjtRQUVsRixNQUFNLElBQUksQ0FBQyxtQkFBbUIsQ0FBQyx5QkFBeUIsQ0FBQyxLQUFLLElBQUksRUFBRTtZQUNsRSxJQUFJLENBQUMsSUFBSSxDQUFDLFdBQVcsRUFBRSxDQUFDO2dCQUN0QixNQUFNLENBQUMsR0FBRyxDQUFDLE9BQU8sRUFBRSxzQ0FBc0MsQ0FBQyxDQUFDO2dCQUM1RCxPQUFPO1lBQ1QsQ0FBQztZQUNELE1BQU0sSUFBSSxDQUFDLFdBQVcsQ0FBQyxZQUFZLEVBQUUsQ0FBQztZQUN0QyxJQUFJLENBQUMsV0FBVyxDQUFDLElBQUksQ0FBQyxZQUFZLENBQUMsSUFBSSxDQUFDLGNBQWMsQ0FBQyxDQUFDO1lBQ3hELE1BQU0sSUFBSSxDQUFDLFdBQVcsQ0FBQyxJQUFJLEVBQUUsQ0FBQztRQUNoQyxDQUFDLENBQUMsQ0FBQztRQUNILE1BQU0sT0FBTyxDQUFDLFVBQVUsQ0FBQyxRQUFRLENBQUMsS0FBSyxDQUFDLENBQUM7UUFDekMsTUFBTSxNQUFNLEdBQUcsTUFBTSxJQUFJLENBQUMsbUJBQW1CLENBQUMseUJBQXlCLENBQUMsS0FBSyxJQUFJLEVBQUU7WUFDakYsTUFBTSxJQUFJLENBQUMsV0FBVyxDQUFDLFlBQVksRUFBRSxDQUFDO1lBQ3RDLE1BQU0saUJBQWlCLEdBQUcsSUFBSSxDQUFDLFdBQVcsQ0FBQyxJQUFJLENBQUMsa0JBQWtCLENBQUMsSUFBSSxDQUFDLENBQUMsVUFBVSxFQUFFLEVBQUU7Z0JBQ3JGLE9BQU8sVUFBVSxDQUFDLGlCQUFpQixLQUFLLGNBQWMsQ0FBQyxpQkFBaUIsQ0FBQztZQUMzRSxDQUFDLENBQUMsQ0FBQztZQUNILE9BQU8saUJBQWlCLENBQUM7UUFDM0IsQ0FBQyxDQUFDLENBQUM7UUFDSCxJQUFJLENBQUMsTUFBTSxFQUFFLENBQUM7WUFDWixNQUFNLENBQUMsR0FBRyxDQUFDLE1BQU0sRUFBRSxxQ0FBcUMsQ0FBQyxDQUFDO1lBQzFELE9BQU8sSUFBVyxDQUFDO1FBQ3JCLENBQUM7UUFDRCxPQUFPLE1BQU0sQ0FBQztJQUNoQixDQUFDO0lBRU0sS0FBSyxDQUFDLDRCQUE0QixDQUN2QyxZQUFnRjtRQUVoRixNQUFNLElBQUksQ0FBQyxtQkFBbUIsQ0FBQyx5QkFBeUIsQ0FBQyxLQUFLLElBQUksRUFBRTtZQUNsRSxNQUFNLGlCQUFpQixHQUFHLElBQUksQ0FBQyxXQUFXLENBQUMsSUFBSSxDQUFDLFlBQVksQ0FBQyxJQUFJLENBQUMsQ0FBQyxhQUFhLEVBQUUsRUFBRTtnQkFDbEYsT0FBTyxDQUNMLGFBQWEsQ0FBQyxRQUFRLEtBQUssWUFBWSxDQUFDLFFBQVE7b0JBQ2hELGFBQWEsQ0FBQyxpQkFBaUIsS0FBSyxZQUFZLENBQUMsaUJBQWlCLENBQ25FLENBQUM7WUFDSixDQUFDLENBQUMsQ0FBQztZQUNILElBQUksQ0FBQyxpQkFBaUIsRUFBRSxDQUFDO2dCQUN2QixNQUFNLENBQUMsR0FBRyxDQUFDLE1BQU0sRUFBRSwyREFBMkQsQ0FBQyxDQUFDO2dCQUNoRixPQUFPO1lBQ1QsQ0FBQztZQUNELE1BQU0sQ0FBQyxNQUFNLENBQUMsaUJBQWlCLEVBQUUsWUFBWSxDQUFDLENBQUM7WUFDL0MsTUFBTSxJQUFJLENBQUMsV0FBVyxDQUFDLElBQUksRUFBRSxDQUFDO1lBQzlCLE9BQU8sQ0FBQyxVQUFVLENBQUMsUUFBUSxDQUFDLEtBQUssQ0FBQyxDQUFDLElBQUksQ0FBQyxHQUFHLEVBQUU7Z0JBQzNDLElBQUksQ0FBQyxtQkFBbUIsQ0FBQyx5QkFBeUIsQ0FBQyxLQUFLLElBQUksRUFBRTtvQkFDNUQsTUFBTSxhQUFhLEdBQUcsSUFBSSxDQUFDLFdBQVcsQ0FBQyxJQUFJLENBQUMsWUFBWSxDQUFDLE9BQU8sQ0FBQyxpQkFBaUIsQ0FBQyxDQUFDO29CQUNwRixJQUFJLGFBQWEsSUFBSSxDQUFDLEVBQUUsQ0FBQzt3QkFDdkIsSUFBSSxDQUFDLFdBQVcsQ0FBQyxJQUFJLENBQUMsWUFBWSxDQUFDLE1BQU0sQ0FBQyxhQUFhLEVBQUUsQ0FBQyxDQUFDLENBQUM7d0JBQzVELE1BQU0sSUFBSSxDQUFDLFdBQVcsQ0FBQyxJQUFJLEVBQUUsQ0FBQztvQkFDaEMsQ0FBQztnQkFDSCxDQUFDLENBQUMsQ0FBQztZQUNMLENBQUMsQ0FBQyxDQUFDO1FBQ0wsQ0FBQyxDQUFDLENBQUM7SUFDTCxDQUFDO0NBQ0YifQ==