UNPKG

resig.js

Version:

Universal reactive signal library with complete platform features: signals, animations, CRDTs, scheduling, DOM integration. Works identically across React, SolidJS, Svelte, Vue, and Qwik.

301 lines 27.6 kB
"use strict"; /** * Event Sourcing with CRDTs * Complete state reconstruction with event replay, snapshots, and compaction */ Object.defineProperty(exports, "__esModule", { value: true }); exports.indexedDBEventStore = exports.eventSourcedGCounter = exports.eventSourcedORSet = exports.createEventSourcedCRDT = exports.IndexedDBEventStore = exports.MemoryEventStore = void 0; const crdt_1 = require("../crdt"); const coalgebra_1 = require("./coalgebra"); // In-memory event store implementation class MemoryEventStore { constructor() { this.events = []; this.snapshots = []; } async append(events) { this.events.push(...events); this.events.sort((a, b) => a.version - b.version); } async getEvents(fromVersion = 0, toVersion = Infinity) { return this.events.filter((e) => e.version >= fromVersion && e.version <= toVersion); } async getSnapshot(beforeVersion = Infinity) { const validSnapshots = this.snapshots.filter((s) => s.version < beforeVersion); return validSnapshots.length > 0 ? validSnapshots[validSnapshots.length - 1] : null; } async saveSnapshot(snapshot) { this.snapshots.push(snapshot); this.snapshots.sort((a, b) => a.version - b.version); } async compact(beforeVersion) { this.events = this.events.filter((e) => e.version >= beforeVersion); this.snapshots = this.snapshots.filter((s) => s.version >= beforeVersion); } } exports.MemoryEventStore = MemoryEventStore; // IndexedDB event store for browser persistence class IndexedDBEventStore { constructor(dbName) { this.db = null; this.dbName = dbName; } async getDB() { if (this.db) return this.db; return new Promise((resolve, reject) => { const request = indexedDB.open(this.dbName, 1); request.onerror = () => reject(request.error); request.onsuccess = () => { this.db = request.result; resolve(this.db); }; request.onupgradeneeded = () => { const db = request.result; if (!db.objectStoreNames.contains('events')) { const eventStore = db.createObjectStore('events', { keyPath: 'id' }); eventStore.createIndex('version', 'version', { unique: false }); eventStore.createIndex('timestamp', 'timestamp', { unique: false }); } if (!db.objectStoreNames.contains('snapshots')) { const snapshotStore = db.createObjectStore('snapshots', { keyPath: 'version', }); snapshotStore.createIndex('timestamp', 'timestamp', { unique: false, }); } }; }); } async append(events) { const db = await this.getDB(); const transaction = db.transaction(['events'], 'readwrite'); const store = transaction.objectStore('events'); for (const event of events) { store.add(event); } return new Promise((resolve, reject) => { transaction.oncomplete = () => resolve(); transaction.onerror = () => reject(transaction.error); }); } async getEvents(fromVersion = 0, toVersion = Infinity) { const db = await this.getDB(); const transaction = db.transaction(['events'], 'readonly'); const store = transaction.objectStore('events'); const index = store.index('version'); const range = IDBKeyRange.bound(fromVersion, toVersion); const request = index.getAll(range); return new Promise((resolve, reject) => { request.onsuccess = () => resolve(request.result); request.onerror = () => reject(request.error); }); } async getSnapshot(beforeVersion = Infinity) { const db = await this.getDB(); const transaction = db.transaction(['snapshots'], 'readonly'); const store = transaction.objectStore('snapshots'); const range = IDBKeyRange.upperBound(beforeVersion, true); const request = store.openCursor(range, 'prev'); return new Promise((resolve, reject) => { request.onsuccess = () => { const cursor = request.result; resolve(cursor ? cursor.value : null); }; request.onerror = () => reject(request.error); }); } async saveSnapshot(snapshot) { const db = await this.getDB(); const transaction = db.transaction(['snapshots'], 'readwrite'); const store = transaction.objectStore('snapshots'); store.put(snapshot); return new Promise((resolve, reject) => { transaction.oncomplete = () => resolve(); transaction.onerror = () => reject(transaction.error); }); } async compact(beforeVersion) { const db = await this.getDB(); const transaction = db.transaction(['events', 'snapshots'], 'readwrite'); // Remove old events const eventStore = transaction.objectStore('events'); const eventIndex = eventStore.index('version'); const eventRange = IDBKeyRange.upperBound(beforeVersion, true); const eventRequest = eventIndex.openCursor(eventRange); eventRequest.onsuccess = () => { const cursor = eventRequest.result; if (cursor) { cursor.delete(); cursor.continue(); } }; // Remove old snapshots const snapshotStore = transaction.objectStore('snapshots'); const snapshotRange = IDBKeyRange.upperBound(beforeVersion, true); const snapshotRequest = snapshotStore.openCursor(snapshotRange); snapshotRequest.onsuccess = () => { const cursor = snapshotRequest.result; if (cursor) { cursor.delete(); cursor.continue(); } }; return new Promise((resolve, reject) => { transaction.oncomplete = () => resolve(); transaction.onerror = () => reject(transaction.error); }); } } exports.IndexedDBEventStore = IndexedDBEventStore; // Create event sourced CRDT wrapper const createEventSourcedCRDT = (baseCRDT, config, nodeId = Math.random().toString(36)) => { let version = 0; let eventCount = 0; const eventStream = (0, coalgebra_1.createStreamingSignal)(null); // Track pending events for batching const pendingEvents = []; let flushTimeout = null; const flushEvents = async () => { if (pendingEvents.length === 0) return; const eventsToFlush = [...pendingEvents]; pendingEvents.length = 0; await config.eventStore.append(eventsToFlush); // Check if we need to create a snapshot if (eventCount % config.snapshotInterval === 0) { await createSnapshot(); } // Check if we need to compact await checkCompaction(); }; const createSnapshot = async () => { const snapshot = { timestamp: Date.now(), version, state: baseCRDT.value(), eventCount, checksum: generateChecksum(baseCRDT.value()), }; await config.eventStore.saveSnapshot(snapshot); return snapshot; }; const checkCompaction = async () => { const { compactionStrategy, maxEvents, maxAge } = config; switch (compactionStrategy) { case 'event-count': if (maxEvents && eventCount > maxEvents) { const compactBefore = version - Math.floor(maxEvents / 2); await config.eventStore.compact(compactBefore); } break; case 'time-based': if (maxAge) { const cutoffTime = Date.now() - maxAge; const events = await config.eventStore.getEvents(); const cutoffVersion = events.find((e) => e.timestamp > cutoffTime)?.version || version; await config.eventStore.compact(cutoffVersion); } break; case 'sliding-window': if (maxEvents && eventCount > maxEvents) { await config.eventStore.compact(version - maxEvents); } break; } }; const generateChecksum = (state) => { return btoa(JSON.stringify(state)).slice(0, 16); }; const addEvent = (event) => { const fullEvent = { ...event, id: `${nodeId}-${Date.now()}-${Math.random().toString(36)}`, version: ++version, nodeId, timestamp: Date.now(), }; pendingEvents.push(fullEvent); eventCount++; // Emit event immediately eventStream._set(fullEvent); // Batch flush events if (flushTimeout) clearTimeout(flushTimeout); flushTimeout = (typeof window !== 'undefined' ? window.setTimeout : setTimeout)(flushEvents, 10); }; const eventSourcedCRDT = { value: baseCRDT.value, merge: (other) => { const merged = baseCRDT.merge(other); addEvent({ type: 'merge', data: other.value() }); return merged; }, events: () => eventStream, replayFrom: async (timestamp) => { // Get the latest snapshot before the timestamp const snapshot = await config.eventStore.getSnapshot(); const state = snapshot ? snapshot.state : baseCRDT.value(); // Get events from snapshot version or beginning const fromVersion = snapshot ? snapshot.version : 0; const events = await config.eventStore.getEvents(fromVersion); // Filter events by timestamp and replay events.filter((e) => e.timestamp >= timestamp); // This is a simplified replay - in practice, you'd need to apply events to recreate state // For now, we return the current state return state; }, snapshot: createSnapshot, compact: async () => { await createSnapshot(); await config.eventStore.compact(version - config.snapshotInterval); }, getEventCount: () => eventCount, getVersion: () => version, clone: () => { return (0, exports.createEventSourcedCRDT)(baseCRDT, config, nodeId); }, toJSON: () => { return { value: baseCRDT.value(), version, eventCount, nodeId, }; }, fromJSON: (data) => { return (0, exports.createEventSourcedCRDT)(baseCRDT, config, data.nodeId || nodeId); }, }; // Wrap original CRDT methods to emit events const originalMethods = Object.getOwnPropertyNames(Object.getPrototypeOf(baseCRDT)); originalMethods.forEach((methodName) => { if (typeof baseCRDT[methodName] === 'function' && methodName !== 'value' && methodName !== 'merge') { const originalMethod = baseCRDT[methodName]; eventSourcedCRDT[methodName] = (...args) => { const result = originalMethod.apply(baseCRDT, args); addEvent({ type: methodName, data: args }); return result; }; } }); return eventSourcedCRDT; }; exports.createEventSourcedCRDT = createEventSourcedCRDT; // Convenience functions for common CRDT types const eventSourcedORSet = (nodeId, config) => { return (0, exports.createEventSourcedCRDT)((0, crdt_1.orSet)(nodeId), config, nodeId); }; exports.eventSourcedORSet = eventSourcedORSet; const eventSourcedGCounter = (nodeId, config) => { return (0, exports.createEventSourcedCRDT)((0, crdt_1.gCounter)(nodeId), config, nodeId); }; exports.eventSourcedGCounter = eventSourcedGCounter; const indexedDBEventStore = (dbName) => new IndexedDBEventStore(dbName); exports.indexedDBEventStore = indexedDBEventStore; //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZXZlbnQtc291cmNpbmcuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvc3RyZWFtaW5nL2V2ZW50LXNvdXJjaW5nLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7QUFBQTs7O0dBR0c7OztBQUVILGtDQUFnRDtBQUVoRCwyQ0FBcUU7QUEyRHJFLHVDQUF1QztBQUN2QyxNQUFhLGdCQUFnQjtJQUE3QjtRQUNVLFdBQU0sR0FBWSxFQUFFLENBQUM7UUFDckIsY0FBUyxHQUF3QixFQUFFLENBQUM7SUFpQzlDLENBQUM7SUEvQkMsS0FBSyxDQUFDLE1BQU0sQ0FBQyxNQUFlO1FBQzFCLElBQUksQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLEdBQUcsTUFBTSxDQUFDLENBQUM7UUFDNUIsSUFBSSxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDLENBQUMsT0FBTyxHQUFHLENBQUMsQ0FBQyxPQUFPLENBQUMsQ0FBQztJQUNwRCxDQUFDO0lBRUQsS0FBSyxDQUFDLFNBQVMsQ0FBQyxXQUFXLEdBQUcsQ0FBQyxFQUFFLFNBQVMsR0FBRyxRQUFRO1FBQ25ELE9BQU8sSUFBSSxDQUFDLE1BQU0sQ0FBQyxNQUFNLENBQ3ZCLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDLENBQUMsT0FBTyxJQUFJLFdBQVcsSUFBSSxDQUFDLENBQUMsT0FBTyxJQUFJLFNBQVMsQ0FDMUQsQ0FBQztJQUNKLENBQUM7SUFFRCxLQUFLLENBQUMsV0FBVyxDQUNmLGFBQWEsR0FBRyxRQUFRO1FBRXhCLE1BQU0sY0FBYyxHQUFHLElBQUksQ0FBQyxTQUFTLENBQUMsTUFBTSxDQUMxQyxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQyxDQUFDLE9BQU8sR0FBRyxhQUFhLENBQ2pDLENBQUM7UUFDRixPQUFPLGNBQWMsQ0FBQyxNQUFNLEdBQUcsQ0FBQztZQUM5QixDQUFDLENBQUMsY0FBYyxDQUFDLGNBQWMsQ0FBQyxNQUFNLEdBQUcsQ0FBQyxDQUFDO1lBQzNDLENBQUMsQ0FBQyxJQUFJLENBQUM7SUFDWCxDQUFDO0lBRUQsS0FBSyxDQUFDLFlBQVksQ0FBQyxRQUEyQjtRQUM1QyxJQUFJLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsQ0FBQztRQUM5QixJQUFJLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUMsQ0FBQyxPQUFPLEdBQUcsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxDQUFDO0lBQ3ZELENBQUM7SUFFRCxLQUFLLENBQUMsT0FBTyxDQUFDLGFBQXFCO1FBQ2pDLElBQUksQ0FBQyxNQUFNLEdBQUcsSUFBSSxDQUFDLE1BQU0sQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUMsQ0FBQyxPQUFPLElBQUksYUFBYSxDQUFDLENBQUM7UUFDcEUsSUFBSSxDQUFDLFNBQVMsR0FBRyxJQUFJLENBQUMsU0FBUyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQyxDQUFDLE9BQU8sSUFBSSxhQUFhLENBQUMsQ0FBQztJQUM1RSxDQUFDO0NBQ0Y7QUFuQ0QsNENBbUNDO0FBRUQsZ0RBQWdEO0FBQ2hELE1BQWEsbUJBQW1CO0lBSTlCLFlBQVksTUFBYztRQUhsQixPQUFFLEdBQXVCLElBQUksQ0FBQztRQUlwQyxJQUFJLENBQUMsTUFBTSxHQUFHLE1BQU0sQ0FBQztJQUN2QixDQUFDO0lBRU8sS0FBSyxDQUFDLEtBQUs7UUFDakIsSUFBSSxJQUFJLENBQUMsRUFBRTtZQUFFLE9BQU8sSUFBSSxDQUFDLEVBQUUsQ0FBQztRQUU1QixPQUFPLElBQUksT0FBTyxDQUFDLENBQUMsT0FBTyxFQUFFLE1BQU0sRUFBRSxFQUFFO1lBQ3JDLE1BQU0sT0FBTyxHQUFHLFNBQVMsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLE1BQU0sRUFBRSxDQUFDLENBQUMsQ0FBQztZQUUvQyxPQUFPLENBQUMsT0FBTyxHQUFHLEdBQUcsRUFBRSxDQUFDLE1BQU0sQ0FBQyxPQUFPLENBQUMsS0FBSyxDQUFDLENBQUM7WUFDOUMsT0FBTyxDQUFDLFNBQVMsR0FBRyxHQUFHLEVBQUU7Z0JBQ3ZCLElBQUksQ0FBQyxFQUFFLEdBQUcsT0FBTyxDQUFDLE1BQU0sQ0FBQztnQkFDekIsT0FBTyxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUMsQ0FBQztZQUNuQixDQUFDLENBQUM7WUFFRixPQUFPLENBQUMsZUFBZSxHQUFHLEdBQUcsRUFBRTtnQkFDN0IsTUFBTSxFQUFFLEdBQUcsT0FBTyxDQUFDLE1BQU0sQ0FBQztnQkFFMUIsSUFBSSxDQUFDLEVBQUUsQ0FBQyxnQkFBZ0IsQ0FBQyxRQUFRLENBQUMsUUFBUSxDQUFDLEVBQUUsQ0FBQztvQkFDNUMsTUFBTSxVQUFVLEdBQUcsRUFBRSxDQUFDLGlCQUFpQixDQUFDLFFBQVEsRUFBRSxFQUFFLE9BQU8sRUFBRSxJQUFJLEVBQUUsQ0FBQyxDQUFDO29CQUNyRSxVQUFVLENBQUMsV0FBVyxDQUFDLFNBQVMsRUFBRSxTQUFTLEVBQUUsRUFBRSxNQUFNLEVBQUUsS0FBSyxFQUFFLENBQUMsQ0FBQztvQkFDaEUsVUFBVSxDQUFDLFdBQVcsQ0FBQyxXQUFXLEVBQUUsV0FBVyxFQUFFLEVBQUUsTUFBTSxFQUFFLEtBQUssRUFBRSxDQUFDLENBQUM7Z0JBQ3RFLENBQUM7Z0JBRUQsSUFBSSxDQUFDLEVBQUUsQ0FBQyxnQkFBZ0IsQ0FBQyxRQUFRLENBQUMsV0FBVyxDQUFDLEVBQUUsQ0FBQztvQkFDL0MsTUFBTSxhQUFhLEdBQUcsRUFBRSxDQUFDLGlCQUFpQixDQUFDLFdBQVcsRUFBRTt3QkFDdEQsT0FBTyxFQUFFLFNBQVM7cUJBQ25CLENBQUMsQ0FBQztvQkFDSCxhQUFhLENBQUMsV0FBVyxDQUFDLFdBQVcsRUFBRSxXQUFXLEVBQUU7d0JBQ2xELE1BQU0sRUFBRSxLQUFLO3FCQUNkLENBQUMsQ0FBQztnQkFDTCxDQUFDO1lBQ0gsQ0FBQyxDQUFDO1FBQ0osQ0FBQyxDQUFDLENBQUM7SUFDTCxDQUFDO0lBRUQsS0FBSyxDQUFDLE1BQU0sQ0FBQyxNQUFlO1FBQzFCLE1BQU0sRUFBRSxHQUFHLE1BQU0sSUFBSSxDQUFDLEtBQUssRUFBRSxDQUFDO1FBQzlCLE1BQU0sV0FBVyxHQUFHLEVBQUUsQ0FBQyxXQUFXLENBQUMsQ0FBQyxRQUFRLENBQUMsRUFBRSxXQUFXLENBQUMsQ0FBQztRQUM1RCxNQUFNLEtBQUssR0FBRyxXQUFXLENBQUMsV0FBVyxDQUFDLFFBQVEsQ0FBQyxDQUFDO1FBRWhELEtBQUssTUFBTSxLQUFLLElBQUksTUFBTSxFQUFFLENBQUM7WUFDM0IsS0FBSyxDQUFDLEdBQUcsQ0FBQyxLQUFLLENBQUMsQ0FBQztRQUNuQixDQUFDO1FBRUQsT0FBTyxJQUFJLE9BQU8sQ0FBQyxDQUFDLE9BQU8sRUFBRSxNQUFNLEVBQUUsRUFBRTtZQUNyQyxXQUFXLENBQUMsVUFBVSxHQUFHLEdBQUcsRUFBRSxDQUFDLE9BQU8sRUFBRSxDQUFDO1lBQ3pDLFdBQVcsQ0FBQyxPQUFPLEdBQUcsR0FBRyxFQUFFLENBQUMsTUFBTSxDQUFDLFdBQVcsQ0FBQyxLQUFLLENBQUMsQ0FBQztRQUN4RCxDQUFDLENBQUMsQ0FBQztJQUNMLENBQUM7SUFFRCxLQUFLLENBQUMsU0FBUyxDQUFDLFdBQVcsR0FBRyxDQUFDLEVBQUUsU0FBUyxHQUFHLFFBQVE7UUFDbkQsTUFBTSxFQUFFLEdBQUcsTUFBTSxJQUFJLENBQUMsS0FBSyxFQUFFLENBQUM7UUFDOUIsTUFBTSxXQUFXLEdBQUcsRUFBRSxDQUFDLFdBQVcsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxFQUFFLFVBQVUsQ0FBQyxDQUFDO1FBQzNELE1BQU0sS0FBSyxHQUFHLFdBQVcsQ0FBQyxXQUFXLENBQUMsUUFBUSxDQUFDLENBQUM7UUFDaEQsTUFBTSxLQUFLLEdBQUcsS0FBSyxDQUFDLEtBQUssQ0FBQyxTQUFTLENBQUMsQ0FBQztRQUVyQyxNQUFNLEtBQUssR0FBRyxXQUFXLENBQUMsS0FBSyxDQUFDLFdBQVcsRUFBRSxTQUFTLENBQUMsQ0FBQztRQUN4RCxNQUFNLE9BQU8sR0FBRyxLQUFLLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxDQUFDO1FBRXBDLE9BQU8sSUFBSSxPQUFPLENBQUMsQ0FBQyxPQUFPLEVBQUUsTUFBTSxFQUFFLEVBQUU7WUFDckMsT0FBTyxDQUFDLFNBQVMsR0FBRyxHQUFHLEVBQUUsQ0FBQyxPQUFPLENBQUMsT0FBTyxDQUFDLE1BQU0sQ0FBQyxDQUFDO1lBQ2xELE9BQU8sQ0FBQyxPQUFPLEdBQUcsR0FBRyxFQUFFLENBQUMsTUFBTSxDQUFDLE9BQU8sQ0FBQyxLQUFLLENBQUMsQ0FBQztRQUNoRCxDQUFDLENBQUMsQ0FBQztJQUNMLENBQUM7SUFFRCxLQUFLLENBQUMsV0FBVyxDQUNmLGFBQWEsR0FBRyxRQUFRO1FBRXhCLE1BQU0sRUFBRSxHQUFHLE1BQU0sSUFBSSxDQUFDLEtBQUssRUFBRSxDQUFDO1FBQzlCLE1BQU0sV0FBVyxHQUFHLEVBQUUsQ0FBQyxXQUFXLENBQUMsQ0FBQyxXQUFXLENBQUMsRUFBRSxVQUFVLENBQUMsQ0FBQztRQUM5RCxNQUFNLEtBQUssR0FBRyxXQUFXLENBQUMsV0FBVyxDQUFDLFdBQVcsQ0FBQyxDQUFDO1FBRW5ELE1BQU0sS0FBSyxHQUFHLFdBQVcsQ0FBQyxVQUFVLENBQUMsYUFBYSxFQUFFLElBQUksQ0FBQyxDQUFDO1FBQzFELE1BQU0sT0FBTyxHQUFHLEtBQUssQ0FBQyxVQUFVLENBQUMsS0FBSyxFQUFFLE1BQU0sQ0FBQyxDQUFDO1FBRWhELE9BQU8sSUFBSSxPQUFPLENBQUMsQ0FBQyxPQUFPLEVBQUUsTUFBTSxFQUFFLEVBQUU7WUFDckMsT0FBTyxDQUFDLFNBQVMsR0FBRyxHQUFHLEVBQUU7Z0JBQ3ZCLE1BQU0sTUFBTSxHQUFHLE9BQU8sQ0FBQyxNQUFNLENBQUM7Z0JBQzlCLE9BQU8sQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxDQUFDO1lBQ3hDLENBQUMsQ0FBQztZQUNGLE9BQU8sQ0FBQyxPQUFPLEdBQUcsR0FBRyxFQUFFLENBQUMsTUFBTSxDQUFDLE9BQU8sQ0FBQyxLQUFLLENBQUMsQ0FBQztRQUNoRCxDQUFDLENBQUMsQ0FBQztJQUNMLENBQUM7SUFFRCxLQUFLLENBQUMsWUFBWSxDQUFDLFFBQTJCO1FBQzVDLE1BQU0sRUFBRSxHQUFHLE1BQU0sSUFBSSxDQUFDLEtBQUssRUFBRSxDQUFDO1FBQzlCLE1BQU0sV0FBVyxHQUFHLEVBQUUsQ0FBQyxXQUFXLENBQUMsQ0FBQyxXQUFXLENBQUMsRUFBRSxXQUFXLENBQUMsQ0FBQztRQUMvRCxNQUFNLEtBQUssR0FBRyxXQUFXLENBQUMsV0FBVyxDQUFDLFdBQVcsQ0FBQyxDQUFDO1FBRW5ELEtBQUssQ0FBQyxHQUFHLENBQUMsUUFBUSxDQUFDLENBQUM7UUFFcEIsT0FBTyxJQUFJLE9BQU8sQ0FBQyxDQUFDLE9BQU8sRUFBRSxNQUFNLEVBQUUsRUFBRTtZQUNyQyxXQUFXLENBQUMsVUFBVSxHQUFHLEdBQUcsRUFBRSxDQUFDLE9BQU8sRUFBRSxDQUFDO1lBQ3pDLFdBQVcsQ0FBQyxPQUFPLEdBQUcsR0FBRyxFQUFFLENBQUMsTUFBTSxDQUFDLFdBQVcsQ0FBQyxLQUFLLENBQUMsQ0FBQztRQUN4RCxDQUFDLENBQUMsQ0FBQztJQUNMLENBQUM7SUFFRCxLQUFLLENBQUMsT0FBTyxDQUFDLGFBQXFCO1FBQ2pDLE1BQU0sRUFBRSxHQUFHLE1BQU0sSUFBSSxDQUFDLEtBQUssRUFBRSxDQUFDO1FBQzlCLE1BQU0sV0FBVyxHQUFHLEVBQUUsQ0FBQyxXQUFXLENBQUMsQ0FBQyxRQUFRLEVBQUUsV0FBVyxDQUFDLEVBQUUsV0FBVyxDQUFDLENBQUM7UUFFekUsb0JBQW9CO1FBQ3BCLE1BQU0sVUFBVSxHQUFHLFdBQVcsQ0FBQyxXQUFXLENBQUMsUUFBUSxDQUFDLENBQUM7UUFDckQsTUFBTSxVQUFVLEdBQUcsVUFBVSxDQUFDLEtBQUssQ0FBQyxTQUFTLENBQUMsQ0FBQztRQUMvQyxNQUFNLFVBQVUsR0FBRyxXQUFXLENBQUMsVUFBVSxDQUFDLGFBQWEsRUFBRSxJQUFJLENBQUMsQ0FBQztRQUMvRCxNQUFNLFlBQVksR0FBRyxVQUFVLENBQUMsVUFBVSxDQUFDLFVBQVUsQ0FBQyxDQUFDO1FBRXZELFlBQVksQ0FBQyxTQUFTLEdBQUcsR0FBRyxFQUFFO1lBQzVCLE1BQU0sTUFBTSxHQUFHLFlBQVksQ0FBQyxNQUFNLENBQUM7WUFDbkMsSUFBSSxNQUFNLEVBQUUsQ0FBQztnQkFDWCxNQUFNLENBQUMsTUFBTSxFQUFFLENBQUM7Z0JBQ2hCLE1BQU0sQ0FBQyxRQUFRLEVBQUUsQ0FBQztZQUNwQixDQUFDO1FBQ0gsQ0FBQyxDQUFDO1FBRUYsdUJBQXVCO1FBQ3ZCLE1BQU0sYUFBYSxHQUFHLFdBQVcsQ0FBQyxXQUFXLENBQUMsV0FBVyxDQUFDLENBQUM7UUFDM0QsTUFBTSxhQUFhLEdBQUcsV0FBVyxDQUFDLFVBQVUsQ0FBQyxhQUFhLEVBQUUsSUFBSSxDQUFDLENBQUM7UUFDbEUsTUFBTSxlQUFlLEdBQUcsYUFBYSxDQUFDLFVBQVUsQ0FBQyxhQUFhLENBQUMsQ0FBQztRQUVoRSxlQUFlLENBQUMsU0FBUyxHQUFHLEdBQUcsRUFBRTtZQUMvQixNQUFNLE1BQU0sR0FBRyxlQUFlLENBQUMsTUFBTSxDQUFDO1lBQ3RDLElBQUksTUFBTSxFQUFFLENBQUM7Z0JBQ1gsTUFBTSxDQUFDLE1BQU0sRUFBRSxDQUFDO2dCQUNoQixNQUFNLENBQUMsUUFBUSxFQUFFLENBQUM7WUFDcEIsQ0FBQztRQUNILENBQUMsQ0FBQztRQUVGLE9BQU8sSUFBSSxPQUFPLENBQUMsQ0FBQyxPQUFPLEVBQUUsTUFBTSxFQUFFLEVBQUU7WUFDckMsV0FBVyxDQUFDLFVBQVUsR0FBRyxHQUFHLEVBQUUsQ0FBQyxPQUFPLEVBQUUsQ0FBQztZQUN6QyxXQUFXLENBQUMsT0FBTyxHQUFHLEdBQUcsRUFBRSxDQUFDLE1BQU0sQ0FBQyxXQUFXLENBQUMsS0FBSyxDQUFDLENBQUM7UUFDeEQsQ0FBQyxDQUFDLENBQUM7SUFDTCxDQUFDO0NBQ0Y7QUEzSUQsa0RBMklDO0FBRUQsb0NBQW9DO0FBQzdCLE1BQU0sc0JBQXNCLEdBQUcsQ0FDcEMsUUFBaUIsRUFDakIsTUFBMEIsRUFDMUIsU0FBaUIsSUFBSSxDQUFDLE1BQU0sRUFBRSxDQUFDLFFBQVEsQ0FBQyxFQUFFLENBQUMsRUFDbkIsRUFBRTtJQUMxQixJQUFJLE9BQU8sR0FBRyxDQUFDLENBQUM7SUFDaEIsSUFBSSxVQUFVLEdBQUcsQ0FBQyxDQUFDO0lBQ25CLE1BQU0sV0FBVyxHQUFHLElBQUEsaUNBQXFCLEVBQUksSUFBVyxDQUFDLENBQUM7SUFFMUQsb0NBQW9DO0lBQ3BDLE1BQU0sYUFBYSxHQUFRLEVBQUUsQ0FBQztJQUM5QixJQUFJLFlBQVksR0FBUSxJQUFJLENBQUM7SUFFN0IsTUFBTSxXQUFXLEdBQUcsS0FBSyxJQUFJLEVBQUU7UUFDN0IsSUFBSSxhQUFhLENBQUMsTUFBTSxLQUFLLENBQUM7WUFBRSxPQUFPO1FBRXZDLE1BQU0sYUFBYSxHQUFHLENBQUMsR0FBRyxhQUFhLENBQUMsQ0FBQztRQUN6QyxhQUFhLENBQUMsTUFBTSxHQUFHLENBQUMsQ0FBQztRQUV6QixNQUFNLE1BQU0sQ0FBQyxVQUFVLENBQUMsTUFBTSxDQUFDLGFBQWEsQ0FBQyxDQUFDO1FBRTlDLHdDQUF3QztRQUN4QyxJQUFJLFVBQVUsR0FBRyxNQUFNLENBQUMsZ0JBQWdCLEtBQUssQ0FBQyxFQUFFLENBQUM7WUFDL0MsTUFBTSxjQUFjLEVBQUUsQ0FBQztRQUN6QixDQUFDO1FBRUQsOEJBQThCO1FBQzlCLE1BQU0sZUFBZSxFQUFFLENBQUM7SUFDMUIsQ0FBQyxDQUFDO0lBRUYsTUFBTSxjQUFjLEdBQUcsS0FBSyxJQUE4QixFQUFFO1FBQzFELE1BQU0sUUFBUSxHQUFvQjtZQUNoQyxTQUFTLEVBQUUsSUFBSSxDQUFDLEdBQUcsRUFBRTtZQUNyQixPQUFPO1lBQ1AsS0FBSyxFQUFFLFFBQVEsQ0FBQyxLQUFLLEVBQUU7WUFDdkIsVUFBVTtZQUNWLFFBQVEsRUFBRSxnQkFBZ0IsQ0FBQyxRQUFRLENBQUMsS0FBSyxFQUFFLENBQUM7U0FDN0MsQ0FBQztRQUVGLE1BQU0sTUFBTSxDQUFDLFVBQVUsQ0FBQyxZQUFZLENBQUMsUUFBUSxDQUFDLENBQUM7UUFDL0MsT0FBTyxRQUFRLENBQUM7SUFDbEIsQ0FBQyxDQUFDO0lBRUYsTUFBTSxlQUFlLEdBQUcsS0FBSyxJQUFJLEVBQUU7UUFDakMsTUFBTSxFQUFFLGtCQUFrQixFQUFFLFNBQVMsRUFBRSxNQUFNLEVBQUUsR0FBRyxNQUFNLENBQUM7UUFFekQsUUFBUSxrQkFBa0IsRUFBRSxDQUFDO1lBQzNCLEtBQUssYUFBYTtnQkFDaEIsSUFBSSxTQUFTLElBQUksVUFBVSxHQUFHLFNBQVMsRUFBRSxDQUFDO29CQUN4QyxNQUFNLGFBQWEsR0FBRyxPQUFPLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxTQUFTLEdBQUcsQ0FBQyxDQUFDLENBQUM7b0JBQzFELE1BQU0sTUFBTSxDQUFDLFVBQVUsQ0FBQyxPQUFPLENBQUMsYUFBYSxDQUFDLENBQUM7Z0JBQ2pELENBQUM7Z0JBQ0QsTUFBTTtZQUNSLEtBQUssWUFBWTtnQkFDZixJQUFJLE1BQU0sRUFBRSxDQUFDO29CQUNYLE1BQU0sVUFBVSxHQUFHLElBQUksQ0FBQyxHQUFHLEVBQUUsR0FBRyxNQUFNLENBQUM7b0JBQ3ZDLE1BQU0sTUFBTSxHQUFHLE1BQU0sTUFBTSxDQUFDLFVBQVUsQ0FBQyxTQUFTLEVBQUUsQ0FBQztvQkFDbkQsTUFBTSxhQUFhLEdBQ2pCLE1BQU0sQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUMsQ0FBQyxTQUFTLEdBQUcsVUFBVSxDQUFDLEVBQUUsT0FBTyxJQUFJLE9BQU8sQ0FBQztvQkFDbkUsTUFBTSxNQUFNLENBQUMsVUFBVSxDQUFDLE9BQU8sQ0FBQyxhQUFhLENBQUMsQ0FBQztnQkFDakQsQ0FBQztnQkFDRCxNQUFNO1lBQ1IsS0FBSyxnQkFBZ0I7Z0JBQ25CLElBQUksU0FBUyxJQUFJLFVBQVUsR0FBRyxTQUFTLEVBQUUsQ0FBQztvQkFDeEMsTUFBTSxNQUFNLENBQUMsVUFBVSxDQUFDLE9BQU8sQ0FBQyxPQUFPLEdBQUcsU0FBUyxDQUFDLENBQUM7Z0JBQ3ZELENBQUM7Z0JBQ0QsTUFBTTtRQUNWLENBQUM7SUFDSCxDQUFDLENBQUM7SUFFRixNQUFNLGdCQUFnQixHQUFHLENBQUMsS0FBUSxFQUFVLEVBQUU7UUFDNUMsT0FBTyxJQUFJLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUM7SUFDbEQsQ0FBQyxDQUFDO0lBRUYsTUFBTSxRQUFRLEdBQUcsQ0FDZixLQUF5RCxFQUN6RCxFQUFFO1FBQ0YsTUFBTSxTQUFTLEdBQU07WUFDbkIsR0FBRyxLQUFLO1lBQ1IsRUFBRSxFQUFFLEdBQUcsTUFBTSxJQUFJLElBQUksQ0FBQyxHQUFHLEVBQUUsSUFBSSxJQUFJLENBQUMsTUFBTSxFQUFFLENBQUMsUUFBUSxDQUFDLEVBQUUsQ0FBQyxFQUFFO1lBQzNELE9BQU8sRUFBRSxFQUFFLE9BQU87WUFDbEIsTUFBTTtZQUNOLFNBQVMsRUFBRSxJQUFJLENBQUMsR0FBRyxFQUFFO1NBQ2pCLENBQUM7UUFFUCxhQUFhLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxDQUFDO1FBQzlCLFVBQVUsRUFBRSxDQUFDO1FBRWIseUJBQXlCO1FBQ3hCLFdBQW1CLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxDQUFDO1FBRXJDLHFCQUFxQjtRQUNyQixJQUFJLFlBQVk7WUFBRSxZQUFZLENBQUMsWUFBWSxDQUFDLENBQUM7UUFDN0MsWUFBWSxHQUFHLENBQUMsT0FBTyxNQUFNLEtBQUssV0FBVyxDQUFDLENBQUMsQ0FBQyxNQUFNLENBQUMsVUFBVSxDQUFDLENBQUMsQ0FBQyxVQUFVLENBQUMsQ0FBQyxXQUFXLEVBQUUsRUFBRSxDQUFDLENBQUM7SUFDbkcsQ0FBQyxDQUFDO0lBRUYsTUFBTSxnQkFBZ0IsR0FBMkI7UUFDL0MsS0FBSyxFQUFFLFFBQVEsQ0FBQyxLQUFLO1FBQ3JCLEtBQUssRUFBRSxDQUFDLEtBQWMsRUFBRSxFQUFFO1lBQ3hCLE1BQU0sTUFBTSxHQUFHLFFBQVEsQ0FBQyxLQUFLLENBQUMsS0FBSyxDQUFDLENBQUM7WUFDckMsUUFBUSxDQUFDLEVBQUUsSUFBSSxFQUFFLE9BQU8sRUFBRSxJQUFJLEVBQUUsS0FBSyxDQUFDLEtBQUssRUFBRSxFQUFTLENBQUMsQ0FBQztZQUN4RCxPQUFPLE1BQU0sQ0FBQztRQUNoQixDQUFDO1FBRUQsTUFBTSxFQUFFLEdBQUcsRUFBRSxDQUFDLFdBQVc7UUFFekIsVUFBVSxFQUFFLEtBQUssRUFBRSxTQUFpQixFQUFjLEVBQUU7WUFDbEQsK0NBQStDO1lBQy9DLE1BQU0sUUFBUSxHQUFHLE1BQU0sTUFBTSxDQUFDLFVBQVUsQ0FBQyxXQUFXLEVBQUUsQ0FBQztZQUN2RCxNQUFNLEtBQUssR0FBRyxRQUFRLENBQUMsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxLQUFLLEVBQUUsQ0FBQztZQUUzRCxnREFBZ0Q7WUFDaEQsTUFBTSxXQUFXLEdBQUcsUUFBUSxDQUFDLENBQUMsQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7WUFDcEQsTUFBTSxNQUFNLEdBQUcsTUFBTSxNQUFNLENBQUMsVUFBVSxDQUFDLFNBQVMsQ0FBQyxXQUFXLENBQUMsQ0FBQztZQUU5RCx3Q0FBd0M7WUFDeEMsTUFBTSxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQyxDQUFDLFNBQVMsSUFBSSxTQUFTLENBQUMsQ0FBQztZQUUvQywwRkFBMEY7WUFDMUYsdUNBQXVDO1lBQ3ZDLE9BQU8sS0FBSyxDQUFDO1FBQ2YsQ0FBQztRQUVELFFBQVEsRUFBRSxjQUFjO1FBRXhCLE9BQU8sRUFBRSxLQUFLLElBQW1CLEVBQUU7WUFDakMsTUFBTSxjQUFjLEVBQUUsQ0FBQztZQUN2QixNQUFNLE1BQU0sQ0FBQyxVQUFVLENBQUMsT0FBTyxDQUFDLE9BQU8sR0FBRyxNQUFNLENBQUMsZ0JBQWdCLENBQUMsQ0FBQztRQUNyRSxDQUFDO1FBRUQsYUFBYSxFQUFFLEdBQUcsRUFBRSxDQUFDLFVBQVU7UUFDL0IsVUFBVSxFQUFFLEdBQUcsRUFBRSxDQUFDLE9BQU87UUFFekIsS0FBSyxFQUFFLEdBQUcsRUFBRTtZQUNWLE9BQU8sSUFBQSw4QkFBc0IsRUFBQyxRQUFRLEVBQUUsTUFBTSxFQUFFLE1BQU0sQ0FBQyxDQUFDO1FBQzFELENBQUM7UUFFRCxNQUFNLEVBQUUsR0FBRyxFQUFFO1lBQ1gsT0FBTztnQkFDTCxLQUFLLEVBQUUsUUFBUSxDQUFDLEtBQUssRUFBRTtnQkFDdkIsT0FBTztnQkFDUCxVQUFVO2dCQUNWLE1BQU07YUFDUCxDQUFDO1FBQ0osQ0FBQztRQUVELFFBQVEsRUFBRSxDQUFDLElBQVMsRUFBRSxFQUFFO1lBQ3RCLE9BQU8sSUFBQSw4QkFBc0IsRUFBQyxRQUFRLEVBQUUsTUFBTSxFQUFFLElBQUksQ0FBQyxNQUFNLElBQUksTUFBTSxDQUFDLENBQUM7UUFDekUsQ0FBQztLQUNGLENBQUM7SUFFRiw0Q0FBNEM7SUFDNUMsTUFBTSxlQUFlLEdBQUcsTUFBTSxDQUFDLG1CQUFtQixDQUNoRCxNQUFNLENBQUMsY0FBYyxDQUFDLFFBQVEsQ0FBQyxDQUNoQyxDQUFDO0lBQ0YsZUFBZSxDQUFDLE9BQU8sQ0FBQyxDQUFDLFVBQVUsRUFBRSxFQUFFO1FBQ3JDLElBQ0UsT0FBUSxRQUFnQixDQUFDLFVBQVUsQ0FBQyxLQUFLLFVBQVU7WUFDbkQsVUFBVSxLQUFLLE9BQU87WUFDdEIsVUFBVSxLQUFLLE9BQU8sRUFDdEIsQ0FBQztZQUNELE1BQU0sY0FBYyxHQUFJLFFBQWdCLENBQUMsVUFBVSxDQUFDLENBQUM7WUFDcEQsZ0JBQXdCLENBQUMsVUFBVSxDQUFDLEdBQUcsQ0FBQyxHQUFHLElBQVcsRUFBRSxFQUFFO2dCQUN6RCxNQUFNLE1BQU0sR0FBRyxjQUFjLENBQUMsS0FBSyxDQUFDLFFBQVEsRUFBRSxJQUFJLENBQUMsQ0FBQztnQkFDcEQsUUFBUSxDQUFDLEVBQUUsSUFBSSxFQUFFLFVBQVUsRUFBRSxJQUFJLEVBQUUsSUFBSSxFQUFTLENBQUMsQ0FBQztnQkFDbEQsT0FBTyxNQUFNLENBQUM7WUFDaEIsQ0FBQyxDQUFDO1FBQ0osQ0FBQztJQUNILENBQUMsQ0FBQyxDQUFDO0lBRUgsT0FBTyxnQkFBZ0IsQ0FBQztBQUMxQixDQUFDLENBQUM7QUEzS1csUUFBQSxzQkFBc0IsMEJBMktqQztBQUVGLDhDQUE4QztBQUN2QyxNQUFNLGlCQUFpQixHQUFHLENBQy9CLE1BQWMsRUFDZCxNQUEwQixFQUMxQixFQUFFO0lBQ0YsT0FBTyxJQUFBLDhCQUFzQixFQUFDLElBQUEsWUFBSyxFQUFDLE1BQU0sQ0FBQyxFQUFFLE1BQU0sRUFBRSxNQUFNLENBQUMsQ0FBQztBQUMvRCxDQUFDLENBQUM7QUFMVyxRQUFBLGlCQUFpQixxQkFLNUI7QUFFSyxNQUFNLG9CQUFvQixHQUFHLENBQ2xDLE1BQWMsRUFDZCxNQUEwQixFQUMxQixFQUFFO0lBQ0YsT0FBTyxJQUFBLDhCQUFzQixFQUFDLElBQUEsZUFBUSxFQUFDLE1BQU0sQ0FBQyxFQUFFLE1BQU0sRUFBRSxNQUFNLENBQUMsQ0FBQztBQUNsRSxDQUFDLENBQUM7QUFMVyxRQUFBLG9CQUFvQix3QkFLL0I7QUFFSyxNQUFNLG1CQUFtQixHQUFHLENBQUMsTUFBYyxFQUFFLEVBQUUsQ0FDcEQsSUFBSSxtQkFBbUIsQ0FBQyxNQUFNLENBQUMsQ0FBQztBQURyQixRQUFBLG1CQUFtQix1QkFDRSJ9