UNPKG

@oaklean/profiler-core

Version:

Part of the @oaklean suite. It provides all basic functions to work with the `.oak` file format. It allows parsing the `.oak` file format as well as tools for analyzing the measurement values. It also provides all necessary capabilities required for prec

292 lines 26.3 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.SourceFileMetaData = exports.AggregatedSourceNodeMetaData = void 0; const BaseModel_1 = require("./BaseModel"); const ModelMap_1 = require("./ModelMap"); const SourceNodeMetaData_1 = require("./SourceNodeMetaData"); const SensorValues_1 = require("./SensorValues"); const SourceNodeRegex_1 = require("../constants/SourceNodeRegex"); const BufferHelper_1 = require("../helper/BufferHelper"); // Types const types_1 = require("../types"); class AggregatedSourceNodeMetaData extends BaseModel_1.BaseModel { constructor(total, max) { super(); this.total = total; this.max = max; } toBuffer() { throw new Error('ModelMap.toBuffer: not yet implemented'); } toJSON() { return { total: this.total.toJSON(), max: this.max.toJSON() }; } static join(...args) { return new AggregatedSourceNodeMetaData(SourceNodeMetaData_1.SourceNodeMetaData.sum(...args.map((x) => x.total)), SourceNodeMetaData_1.SourceNodeMetaData.max(...args.map((x) => x.max))); } static fromJSON(json) { let data; if (typeof json === 'string') { data = JSON.parse(json); } else { data = json; } return new AggregatedSourceNodeMetaData(SourceNodeMetaData_1.SourceNodeMetaData.fromJSON(data.total, undefined), SourceNodeMetaData_1.SourceNodeMetaData.fromJSON(data.max, undefined)); } } exports.AggregatedSourceNodeMetaData = AggregatedSourceNodeMetaData; class SourceFileMetaData extends BaseModel_1.BaseModel { constructor(path, pathIndex) { super(); this.path = path; this.pathIndex = pathIndex; } get containsUncommittedChanges() { if (this.pathIndex === undefined) { return false; } return this.pathIndex.containsUncommittedChanges; } set containsUncommittedChanges(v) { if (this.pathIndex !== undefined) { this.pathIndex.containsUncommittedChanges = v; } } normalize(newGlobalIndex) { const newPathIndex = this.pathIndex.insertToOtherIndex(newGlobalIndex); const newFunctions = new ModelMap_1.ModelMap('number'); for (const sourceNodeID of Array.from(this.functions.keys()).sort()) { const sourceNodeMetaData = this.functions.get(sourceNodeID); sourceNodeMetaData.normalize(newGlobalIndex); newFunctions.set(sourceNodeMetaData.id, sourceNodeMetaData); } this.pathIndex = newPathIndex; this._functions = newFunctions; } static merge(pathIndex, ...args) { if (args.length === 0) { throw new Error('SourceFileMetaData.merge: no SourceFileMetaDatas were given'); } const path = args[0].path; const containsUncommittedChanges = args.map((x) => x.containsUncommittedChanges).reduce((prevValue, currValue) => prevValue || currValue); const valuesToMerge = { functions: {} }; for (const currentSourceFileMetaData of args) { if (path !== currentSourceFileMetaData.path) { throw new Error('SourceFileMetaData.merge: all SourceFileMetaDatas should be from the same file.'); } for (const [sourceNodeID, sourceNodeMetaData] of currentSourceFileMetaData.functions) { const sourceNodeIndex = currentSourceFileMetaData.getSourceNodeIndexByID(sourceNodeID); if (sourceNodeIndex === undefined) { throw new Error('SourceFileMetaData.merge: could not resolve sourceNode from id'); } const identifier = sourceNodeIndex.identifier; if (!valuesToMerge.functions[identifier]) { valuesToMerge.functions[identifier] = []; } valuesToMerge.functions[identifier].push(sourceNodeMetaData); } } const result = new SourceFileMetaData(path, pathIndex); for (const [identifier, sourceNodeMetaDatas] of Object.entries(valuesToMerge.functions)) { const sourceNodeIndex = result.getSourceNodeIndex('upsert', identifier); const sourceNodeID = sourceNodeIndex.id; result.functions.set(sourceNodeID, SourceNodeMetaData_1.SourceNodeMetaData.merge(sourceNodeID, sourceNodeIndex, ...sourceNodeMetaDatas)); } result.containsUncommittedChanges = containsUncommittedChanges; return result; } get functions() { if (!this._functions) { this._functions = new ModelMap_1.ModelMap('number'); } return this._functions; } getSourceNodeIndexByID(id) { return this.pathIndex.moduleIndex.globalIndex.getSourceNodeIndexByID(id); } getSourceNodeIndex(indexRequestType, sourceNodeIdentifier) { return this. pathIndex.getSourceNodeIndex(indexRequestType, sourceNodeIdentifier); } removeFromIntern(filePath) { let filePaths = []; if (typeof filePath === 'string') { filePaths = [filePath]; } else { filePaths = filePath; } for (const sourceNodeMetaData of this.functions.values()) { sourceNodeMetaData.removeFromIntern(filePaths); } } validate() { for (const [sourceNodeID, sourceNodeMetaData] of this.functions.entries()) { const sourceNodeIndex = this.getSourceNodeIndexByID(sourceNodeID); if (sourceNodeIndex === undefined) { throw new Error('SourceFileMetaData.validate: could not resolve source node index'); } const identifier = sourceNodeIndex === null || sourceNodeIndex === void 0 ? void 0 : sourceNodeIndex.identifier; if (sourceNodeMetaData.type === types_1.SourceNodeMetaDataType.LangInternalSourceNode) { if (!SourceNodeRegex_1.LangInternalSourceNodeIdentifierRegex.test(identifier)) { throw new Error('SourceFileMetaData.validate: invalid LangInternalSourceNodeIdentifier_string:' + identifier + '\n' + SourceNodeRegex_1.LangInternalSourceNodeIdentifierRegexString); } } else { if (!SourceNodeRegex_1.SourceNodeIdentifierRegex.test(identifier)) { throw new Error(`SourceFileMetaData.validate: invalid sourceNodeIdentifier: ${identifier}\n` + SourceNodeRegex_1.SourceNodeIdentifierRegexString); } } sourceNodeMetaData.validate(this.path, identifier); } } toJSON() { if (process.env.NODE_ENV === 'test') { this.validate(); } return { path: this.path, functions: this.functions.toJSON() }; } static fromJSON(json, pathIndex) { let data; if (typeof json === 'string') { data = JSON.parse(json); } else { data = json; } const result = new SourceFileMetaData(data.path, pathIndex); if (data.functions) { for (const [sourceNodeID_string, nodeMetaData] of Object.entries(data.functions)) { const sourceNodeID = parseInt(sourceNodeID_string); result.functions.set(sourceNodeID, SourceNodeMetaData_1.SourceNodeMetaData.fromJSON(nodeMetaData, pathIndex.moduleIndex.globalIndex)); } } return result; } createOrGetSourceNodeMetaData(identifier, type) { const sourceNodeIndex = this.getSourceNodeIndex('upsert', identifier); const sourceNodeID = sourceNodeIndex.id; let node = this.functions.get(sourceNodeID); if (!node) { node = new SourceNodeMetaData_1.SourceNodeMetaData(type, sourceNodeID, new SensorValues_1.SensorValues({}), sourceNodeIndex); this.functions.set(sourceNodeID, node); } return node; } /** * Calculates the total SourceNodeMetaData for the SourceFile * * hits, selfTime, aggregatedTime, langInternalTime, externTime and internTime are added up * * intern self references are removed * * @returns number */ totalSourceNodeMetaData() { const listToSum = []; const intern = new ModelMap_1.ModelMap('number'); const extern = new ModelMap_1.ModelMap('number'); const langInternal = new ModelMap_1.ModelMap('number'); for (const sourceNodeMetaData of this.functions.values()) { listToSum.push(sourceNodeMetaData); for (const sourceNodeMetaDataReferences of [ sourceNodeMetaData.lang_internal, sourceNodeMetaData.intern, sourceNodeMetaData.extern ]) { for (const sourceNodeMetaDataReference of sourceNodeMetaDataReferences.values()) { const pathID = sourceNodeMetaDataReference.sourceNodeIndex.pathIndex.id; if (pathID === undefined) { throw new Error('totalSourceNodeMetaData: expected pathID'); } switch (sourceNodeMetaDataReferences) { case sourceNodeMetaData.lang_internal: { const sensorValuesOfFile = langInternal.get(pathID); langInternal.set(pathID, SensorValues_1.SensorValues.sum(sourceNodeMetaDataReference.sensorValues, ...(sensorValuesOfFile ? [sensorValuesOfFile] : []))); } break; case sourceNodeMetaData.intern: { const sensorValuesOfFile = intern.get(pathID); intern.set(pathID, SensorValues_1.SensorValues.sum(sourceNodeMetaDataReference.sensorValues, ...(sensorValuesOfFile ? [sensorValuesOfFile] : []))); } break; case sourceNodeMetaData.extern: { const sensorValuesOfFile = extern.get(pathID); extern.set(pathID, SensorValues_1.SensorValues.sum(sourceNodeMetaDataReference.sensorValues, ...(sensorValuesOfFile ? [sensorValuesOfFile] : []))); } break; } } } } if (this.pathIndex.id === undefined) { throw new Error('totalSourceNodeMetaData: expected pathIndex.id'); } const selfReference = intern.get(this.pathIndex.id); const result = SourceNodeMetaData_1.SourceNodeMetaData.sum(...listToSum); if (selfReference !== undefined) { // remove self references result.sensorValues.addToIntern(selfReference, -1); result.sensorValues.addToAggregated(selfReference, -1); // remove self references intern.delete(this.pathIndex.id); } return { sum: result, intern, extern, langInternal }; } maxSourceNodeMetaData() { return SourceNodeMetaData_1.SourceNodeMetaData.max(...this.functions.values()); } toBuffer() { const id = this.pathIndex.id; if (id === undefined) { throw new Error('SourceFileMetaData.toBuffer: expected id'); } const buffers = [ BufferHelper_1.BufferHelper.UIntToBuffer(id), this.functions.toBuffer() ]; return Buffer.concat(buffers); } static consumeFromBuffer(buffer, globalIndex) { let remainingBuffer = buffer; const { instance: pathID, remainingBuffer: newRemainingBuffer1 } = BufferHelper_1.BufferHelper.UIntFromBuffer(remainingBuffer); remainingBuffer = newRemainingBuffer1; const pathIndex = globalIndex.getPathIndexByID(pathID); if (pathIndex === undefined) { throw new Error('SourceFileMetaData.consumeFromBuffer: could not resolve pathIndex'); } const instance = new SourceFileMetaData(pathIndex.identifier, pathIndex); const consumeFromBufferWithModuleIndex = (buffer) => { return SourceNodeMetaData_1.SourceNodeMetaData.consumeFromBuffer(buffer, globalIndex); }; const { instance: functions, remainingBuffer: newRemainingBuffer2 } = ModelMap_1.ModelMap.consumeFromBuffer(remainingBuffer, 'number', consumeFromBufferWithModuleIndex); instance._functions = functions; remainingBuffer = newRemainingBuffer2; return { instance, remainingBuffer }; } } exports.SourceFileMetaData = SourceFileMetaData; //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiU291cmNlRmlsZU1ldGFEYXRhLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL21vZGVsL1NvdXJjZUZpbGVNZXRhRGF0YS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFBQSwyQ0FBdUM7QUFDdkMseUNBQXFDO0FBQ3JDLDZEQUU2QjtBQUM3QixpREFBNkM7QUFLN0Msa0VBS3FDO0FBQ3JDLHlEQUFxRDtBQUNyRCxRQUFRO0FBQ1Isb0NBWWlCO0FBRWpCLE1BQWEsNEJBQTZCLFNBQVEscUJBQVM7SUFJMUQsWUFDQyxLQUEyRCxFQUMzRCxHQUF5RDtRQUV6RCxLQUFLLEVBQUUsQ0FBQTtRQUNQLElBQUksQ0FBQyxLQUFLLEdBQUcsS0FBSyxDQUFBO1FBQ2xCLElBQUksQ0FBQyxHQUFHLEdBQUcsR0FBRyxDQUFBO0lBQ2YsQ0FBQztJQUVELFFBQVE7UUFDUCxNQUFNLElBQUksS0FBSyxDQUFDLHdDQUF3QyxDQUFDLENBQUE7SUFDMUQsQ0FBQztJQUVELE1BQU07UUFDTCxPQUFPO1lBQ04sS0FBSyxFQUFFLElBQUksQ0FBQyxLQUFLLENBQUMsTUFBTSxFQUFFO1lBQzFCLEdBQUcsRUFBRSxJQUFJLENBQUMsR0FBRyxDQUFDLE1BQU0sRUFBRTtTQUN0QixDQUFBO0lBQ0YsQ0FBQztJQUVELE1BQU0sQ0FBQyxJQUFJLENBQ1YsR0FBRyxJQUFvQztRQUV2QyxPQUFPLElBQUksNEJBQTRCLENBQ3RDLHVDQUFrQixDQUFDLEdBQUcsQ0FBQyxHQUFHLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUMsQ0FBQyxFQUNuRCx1Q0FBa0IsQ0FBQyxHQUFHLENBQUMsR0FBRyxJQUFJLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FDakQsQ0FBQTtJQUNGLENBQUM7SUFFRCxNQUFNLENBQUMsUUFBUSxDQUNkLElBQTRDO1FBRTVDLElBQUksSUFBbUMsQ0FBQTtRQUN2QyxJQUFJLE9BQU8sSUFBSSxLQUFLLFFBQVEsRUFBRSxDQUFDO1lBQzlCLElBQUksR0FBRyxJQUFJLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxDQUFBO1FBQ3hCLENBQUM7YUFBTSxDQUFDO1lBQ1AsSUFBSSxHQUFHLElBQUksQ0FBQTtRQUNaLENBQUM7UUFFRCxPQUFPLElBQUksNEJBQTRCLENBQ3RDLHVDQUFrQixDQUFDLFFBQVEsQ0FBbUMsSUFBSSxDQUFDLEtBQUssRUFBRSxTQUFTLENBQUMsRUFDcEYsdUNBQWtCLENBQUMsUUFBUSxDQUFtQyxJQUFJLENBQUMsR0FBRyxFQUFFLFNBQVMsQ0FBQyxDQUNsRixDQUFBO0lBQ0YsQ0FBQztDQUNEO0FBaERELG9FQWdEQztBQUVELE1BQWEsa0JBQW1CLFNBQVEscUJBQVM7SUFRaEQsWUFDQyxJQUFrRCxFQUNsRCxTQUFvQjtRQUVwQixLQUFLLEVBQUUsQ0FBQTtRQUNQLElBQUksQ0FBQyxJQUFJLEdBQUcsSUFBSSxDQUFBO1FBQ2hCLElBQUksQ0FBQyxTQUFTLEdBQUcsU0FBUyxDQUFBO0lBQzNCLENBQUM7SUFFRCxJQUFXLDBCQUEwQjtRQUNwQyxJQUFJLElBQUksQ0FBQyxTQUFTLEtBQUssU0FBUyxFQUFFLENBQUM7WUFDbEMsT0FBTyxLQUFLLENBQUE7UUFDYixDQUFDO1FBQ0QsT0FBTyxJQUFJLENBQUMsU0FBUyxDQUFDLDBCQUEwQixDQUFBO0lBQ2pELENBQUM7SUFFRCxJQUFXLDBCQUEwQixDQUFDLENBQVU7UUFDL0MsSUFBSSxJQUFJLENBQUMsU0FBUyxLQUFLLFNBQVMsRUFBRSxDQUFDO1lBQ2xDLElBQUksQ0FBQyxTQUFTLENBQUMsMEJBQTBCLEdBQUcsQ0FBQyxDQUFBO1FBQzlDLENBQUM7SUFDRixDQUFDO0lBRUQsU0FBUyxDQUFDLGNBQTJCO1FBQ3BDLE1BQU0sWUFBWSxHQUFHLElBQUksQ0FBQyxTQUFTLENBQUMsa0JBQWtCLENBQUMsY0FBYyxDQUFDLENBQUE7UUFDdEUsTUFBTSxZQUFZLEdBQUcsSUFBSSxtQkFBUSxDQUVzRSxRQUFRLENBQUMsQ0FBQTtRQUNoSCxLQUFLLE1BQU0sWUFBWSxJQUFJLEtBQUssQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxJQUFJLEVBQUUsQ0FBQyxDQUFDLElBQUksRUFBRSxFQUFFLENBQUM7WUFDckUsTUFBTSxrQkFBa0IsR0FBRyxJQUFJLENBQUMsU0FBUyxDQUFDLEdBQUcsQ0FBQyxZQUFZLENBQUUsQ0FBQTtZQUM1RCxrQkFBa0IsQ0FBQyxTQUFTLENBQUMsY0FBYyxDQUFDLENBQUE7WUFDNUMsWUFBWSxDQUFDLEdBQUcsQ0FBQyxrQkFBa0IsQ0FBQyxFQUFFLEVBQUUsa0JBQWtCLENBQUMsQ0FBQTtRQUM1RCxDQUFDO1FBQ0QsSUFBSSxDQUFDLFNBQVMsR0FBRyxZQUFZLENBQUE7UUFDN0IsSUFBSSxDQUFDLFVBQVUsR0FBRyxZQUFZLENBQUE7SUFDL0IsQ0FBQztJQUVELE1BQU0sQ0FBQyxLQUFLLENBQ1gsU0FBb0IsRUFDcEIsR0FBRyxJQUEwQjtRQUU3QixJQUFJLElBQUksQ0FBQyxNQUFNLEtBQUssQ0FBQyxFQUFFLENBQUM7WUFDdkIsTUFBTSxJQUFJLEtBQUssQ0FBQyw2REFBNkQsQ0FBQyxDQUFBO1FBQy9FLENBQUM7UUFFRCxNQUFNLElBQUksR0FBRyxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFBO1FBQ3pCLE1BQU0sMEJBQTBCLEdBQUcsSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQyxDQUFDLDBCQUEwQixDQUFDLENBQUMsTUFBTSxDQUN0RixDQUFDLFNBQWtCLEVBQUUsU0FBa0IsRUFBRSxFQUFFLENBQUMsU0FBUyxJQUFJLFNBQVMsQ0FDbEUsQ0FBQTtRQUVELE1BQU0sYUFBYSxHQUdmO1lBQ0gsU0FBUyxFQUFFLEVBQUU7U0FDYixDQUFBO1FBRUQsS0FBSyxNQUFNLHlCQUF5QixJQUFJLElBQUksRUFBRSxDQUFDO1lBQzlDLElBQUksSUFBSSxLQUFLLHlCQUF5QixDQUFDLElBQUksRUFBRSxDQUFDO2dCQUM3QyxNQUFNLElBQUksS0FBSyxDQUFDLGlGQUFpRixDQUFDLENBQUE7WUFDbkcsQ0FBQztZQUNELEtBQUssTUFBTSxDQUFDLFlBQVksRUFBRSxrQkFBa0IsQ0FBQyxJQUFJLHlCQUF5QixDQUFDLFNBQVMsRUFBRSxDQUFDO2dCQUN0RixNQUFNLGVBQWUsR0FBRyx5QkFBeUIsQ0FBQyxzQkFBc0IsQ0FBQyxZQUFZLENBQUMsQ0FBQTtnQkFFdEYsSUFBSSxlQUFlLEtBQUssU0FBUyxFQUFFLENBQUM7b0JBQ25DLE1BQU0sSUFBSSxLQUFLLENBQUMsZ0VBQWdFLENBQUMsQ0FBQTtnQkFDbEYsQ0FBQztnQkFDRCxNQUFNLFVBQVUsR0FBRyxlQUFlLENBQUMsVUFBeUMsQ0FBQTtnQkFFNUUsSUFBSSxDQUFDLGFBQWEsQ0FBQyxTQUFTLENBQUMsVUFBVSxDQUFDLEVBQUUsQ0FBQztvQkFDMUMsYUFBYSxDQUFDLFNBQVMsQ0FBQyxVQUFVLENBQUMsR0FBRyxFQUFFLENBQUE7Z0JBQ3pDLENBQUM7Z0JBQ0QsYUFBYSxDQUFDLFNBQVMsQ0FBQyxVQUFVLENBQUMsQ0FBQyxJQUFJLENBQUMsa0JBQWtCLENBQUMsQ0FBQTtZQUM3RCxDQUFDO1FBQ0YsQ0FBQztRQUVELE1BQU0sTUFBTSxHQUFHLElBQUksa0JBQWtCLENBQUMsSUFBSSxFQUFFLFNBQVMsQ0FBQyxDQUFBO1FBQ3RELEtBQUssTUFBTSxDQUFDLFVBQVUsRUFBRSxtQkFBbUIsQ0FBQyxJQUFJLE1BQU0sQ0FBQyxPQUFPLENBQUMsYUFBYSxDQUFDLFNBQVMsQ0FBQyxFQUFFLENBQUM7WUFDekYsTUFBTSxlQUFlLEdBQUcsTUFBTSxDQUFDLGtCQUFrQixDQUFDLFFBQVEsRUFBRSxVQUF5QyxDQUFDLENBQUE7WUFDdEcsTUFBTSxZQUFZLEdBQUcsZUFBZSxDQUFDLEVBQXlCLENBQUE7WUFFOUQsTUFBTSxDQUFDLFNBQVMsQ0FBQyxHQUFHLENBQ25CLFlBQVksRUFDWix1Q0FBa0IsQ0FBQyxLQUFLLENBQ3ZCLFlBQVksRUFDWixlQUFlLEVBQ2YsR0FBRyxtQkFBbUIsQ0FDdEIsQ0FDRCxDQUFBO1FBQ0YsQ0FBQztRQUNELE1BQU0sQ0FBQywwQkFBMEIsR0FBRywwQkFBMEIsQ0FBQTtRQUM5RCxPQUFPLE1BQU0sQ0FBQTtJQUNkLENBQUM7SUFFRCxJQUFJLFNBQVM7UUFJWixJQUFJLENBQUMsSUFBSSxDQUFDLFVBQVUsRUFBRSxDQUFDO1lBQ3RCLElBQUksQ0FBQyxVQUFVLEdBQUcsSUFBSSxtQkFBUSxDQUV5RSxRQUFRLENBQUMsQ0FBQTtRQUNqSCxDQUFDO1FBQ0QsT0FBTyxJQUFJLENBQUMsVUFBVSxDQUFBO0lBQ3ZCLENBQUM7SUFFRCxzQkFBc0IsQ0FBQyxFQUF1QjtRQUM3QyxPQUFPLElBQUksQ0FBQyxTQUFTLENBQUMsV0FBVyxDQUFDLFdBQVcsQ0FBQyxzQkFBc0IsQ0FBQyxFQUFFLENBQUMsQ0FBQTtJQUN6RSxDQUFDO0lBRUQsa0JBQWtCLENBQ2pCLGdCQUFtQixFQUNuQixvQkFBaUQ7UUFFakQsT0FBTyxJQUFJO1lBQ1YsU0FBUyxDQUFDLGtCQUFrQixDQUFJLGdCQUFnQixFQUFFLG9CQUFvQixDQUFDLENBQUE7SUFDekUsQ0FBQztJQUVELGdCQUFnQixDQUFDLFFBQW1EO1FBQ25FLElBQUksU0FBUyxHQUF5QixFQUFFLENBQUE7UUFDeEMsSUFBSSxPQUFPLFFBQVEsS0FBSyxRQUFRLEVBQUUsQ0FBQztZQUNsQyxTQUFTLEdBQUcsQ0FBQyxRQUFRLENBQUMsQ0FBQTtRQUN2QixDQUFDO2FBQU0sQ0FBQztZQUNQLFNBQVMsR0FBRyxRQUFRLENBQUE7UUFDckIsQ0FBQztRQUVELEtBQUssTUFBTSxrQkFBa0IsSUFBSSxJQUFJLENBQUMsU0FBUyxDQUFDLE1BQU0sRUFBRSxFQUFFLENBQUM7WUFDMUQsa0JBQWtCLENBQUMsZ0JBQWdCLENBQUMsU0FBUyxDQUFDLENBQUE7UUFDL0MsQ0FBQztJQUNGLENBQUM7SUFFRCxRQUFRO1FBQ1AsS0FBSyxNQUFNLENBQUMsWUFBWSxFQUFFLGtCQUFrQixDQUFDLElBQUksSUFBSSxDQUFDLFNBQVMsQ0FBQyxPQUFPLEVBQUUsRUFBRSxDQUFDO1lBQzNFLE1BQU0sZUFBZSxHQUFHLElBQUksQ0FBQyxzQkFBc0IsQ0FBQyxZQUFZLENBQUMsQ0FBQTtZQUVqRSxJQUFJLGVBQWUsS0FBSyxTQUFTLEVBQUUsQ0FBQztnQkFDbkMsTUFBTSxJQUFJLEtBQUssQ0FBQyxrRUFBa0UsQ0FBQyxDQUFBO1lBQ3BGLENBQUM7WUFFRCxNQUFNLFVBQVUsR0FBRyxlQUFlLGFBQWYsZUFBZSx1QkFBZixlQUFlLENBQUUsVUFBeUMsQ0FBQTtZQUM3RSxJQUNDLGtCQUFrQixDQUFDLElBQUksS0FBSyw4QkFBc0IsQ0FBQyxzQkFBc0IsRUFDeEUsQ0FBQztnQkFDRixJQUFJLENBQUMsdURBQXFDLENBQUMsSUFBSSxDQUFDLFVBQVUsQ0FBQyxFQUFFLENBQUM7b0JBQzdELE1BQU0sSUFBSSxLQUFLLENBQ2QsK0VBQStFOzBCQUM3RSxVQUFVLEdBQUcsSUFBSTt3QkFDbkIsNkRBQTJDLENBQzNDLENBQUE7Z0JBQ0YsQ0FBQztZQUNGLENBQUM7aUJBQU0sQ0FBQztnQkFDUCxJQUFJLENBQUMsMkNBQXlCLENBQUMsSUFBSSxDQUFDLFVBQVUsQ0FBQyxFQUFFLENBQUM7b0JBQ2pELE1BQU0sSUFBSSxLQUFLLENBQ2QsOERBQThELFVBQVUsSUFBSTt3QkFDNUUsaURBQStCLENBQy9CLENBQUE7Z0JBQ0YsQ0FBQztZQUNGLENBQUM7WUFFRCxrQkFBa0IsQ0FBQyxRQUFRLENBQzFCLElBQUksQ0FBQyxJQUFJLEVBQ1QsVUFBVSxDQUNWLENBQUE7UUFDRixDQUFDO0lBQ0YsQ0FBQztJQUVELE1BQU07UUFDTCxJQUFJLE9BQU8sQ0FBQyxHQUFHLENBQUMsUUFBUSxLQUFLLE1BQU0sRUFBRSxDQUFDO1lBQ3JDLElBQUksQ0FBQyxRQUFRLEVBQUUsQ0FBQTtRQUNoQixDQUFDO1FBQ0QsT0FBTztZQUNOLElBQUksRUFBRSxJQUFJLENBQUMsSUFBSTtZQUNmLFNBQVMsRUFBRSxJQUFJLENBQUMsU0FBUyxDQUFDLE1BQU0sRUFBRTtTQUNsQyxDQUFBO0lBQ0YsQ0FBQztJQUVELE1BQU0sQ0FBQyxRQUFRLENBQ2QsSUFBa0MsRUFDbEMsU0FBb0I7UUFFcEIsSUFBSSxJQUF5QixDQUFBO1FBQzdCLElBQUksT0FBTyxJQUFJLEtBQUssUUFBUSxFQUFFLENBQUM7WUFDOUIsSUFBSSxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLENBQUE7UUFDeEIsQ0FBQzthQUFNLENBQUM7WUFDUCxJQUFJLEdBQUcsSUFBSSxDQUFBO1FBQ1osQ0FBQztRQUNELE1BQU0sTUFBTSxHQUFHLElBQUksa0JBQWtCLENBQ3BDLElBQUksQ0FBQyxJQUFJLEVBQ1QsU0FBUyxDQUNULENBQUE7UUFDRCxJQUFJLElBQUksQ0FBQyxTQUFTLEVBQUUsQ0FBQztZQUNwQixLQUFLLE1BQU0sQ0FBQyxtQkFBbUIsRUFBRSxZQUFZLENBQUMsSUFBSSxNQUFNLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsRUFBRSxDQUFDO2dCQUNsRixNQUFNLFlBQVksR0FBRyxRQUFRLENBQUMsbUJBQW1CLENBQXdCLENBQUE7Z0JBQ3pFLE1BQU0sQ0FBQyxTQUFTLENBQUMsR0FBRyxDQUNuQixZQUFZLEVBQ1osdUNBQWtCLENBQUMsUUFBUSxDQUFDLFlBQVksRUFBRSxTQUFTLENBQUMsV0FBVyxDQUFDLFdBQVcsQ0FBQyxDQUM1RSxDQUFBO1lBQ0YsQ0FBQztRQUNGLENBQUM7UUFDRCxPQUFPLE1BQU0sQ0FBQTtJQUNkLENBQUM7SUFFRCw2QkFBNkIsQ0FHNUIsVUFBdUMsRUFDdkMsSUFBTztRQUdQLE1BQU0sZUFBZSxHQUFHLElBQUksQ0FBQyxrQkFBa0IsQ0FBQyxRQUFRLEVBQUUsVUFBVSxDQUFDLENBQUE7UUFDckUsTUFBTSxZQUFZLEdBQUcsZUFBZSxDQUFDLEVBQXlCLENBQUE7UUFFOUQsSUFBSSxJQUFJLEdBQUcsSUFBSSxDQUFDLFNBQVMsQ0FBQyxHQUFHLENBQUMsWUFBWSxDQUEwQixDQUFBO1FBQ3BFLElBQUksQ0FBQyxJQUFJLEVBQUUsQ0FBQztZQUNYLElBQUksR0FBRyxJQUFJLHVDQUFrQixDQUM1QixJQUFJLEVBQ0osWUFBNEYsRUFDNUYsSUFBSSwyQkFBWSxDQUFDLEVBQUUsQ0FBQyxFQUNwQixlQUM0RCxDQUM1RCxDQUFBO1lBQ0QsSUFBSSxDQUFDLFNBQVMsQ0FBQyxHQUFHLENBQUMsWUFBWSxFQUFFLElBQUksQ0FBQyxDQUFBO1FBQ3ZDLENBQUM7UUFDRCxPQUFPLElBQUksQ0FBQTtJQUNaLENBQUM7SUFFRDs7Ozs7Ozs7T0FRRztJQUNILHVCQUF1QjtRQU10QixNQUFNLFNBQVMsR0FHVCxFQUFFLENBQUE7UUFDUixNQUFNLE1BQU0sR0FBRyxJQUFJLG1CQUFRLENBQThCLFFBQVEsQ0FBQyxDQUFBO1FBQ2xFLE1BQU0sTUFBTSxHQUFHLElBQUksbUJBQVEsQ0FBOEIsUUFBUSxDQUFDLENBQUE7UUFDbEUsTUFBTSxZQUFZLEdBQUcsSUFBSSxtQkFBUSxDQUE4QixRQUFRLENBQUMsQ0FBQTtRQUV4RSxLQUFLLE1BQU0sa0JBQWtCLElBQUksSUFBSSxDQUFDLFNBQVMsQ0FBQyxNQUFNLEVBQUUsRUFBRSxDQUFDO1lBQzFELFNBQVMsQ0FBQyxJQUFJLENBQUMsa0JBQWtCLENBQUMsQ0FBQTtZQUNsQyxLQUFLLE1BQU0sNEJBQTRCLElBQUk7Z0JBQzFDLGtCQUFrQixDQUFDLGFBQWE7Z0JBQ2hDLGtCQUFrQixDQUFDLE1BQU07Z0JBQ3pCLGtCQUFrQixDQUFDLE1BQU07YUFDekIsRUFBRSxDQUFDO2dCQUNILEtBQUssTUFBTSwyQkFBMkIsSUFBSSw0QkFBNEIsQ0FBQyxNQUFNLEVBQUUsRUFBRSxDQUFDO29CQUNqRixNQUFNLE1BQU0sR0FBRywyQkFBMkIsQ0FBQyxlQUFlLENBQUMsU0FBUyxDQUFDLEVBQUUsQ0FBQTtvQkFFdkUsSUFBSSxNQUFNLEtBQUssU0FBUyxFQUFFLENBQUM7d0JBQzFCLE1BQU0sSUFBSSxLQUFLLENBQUMsMENBQTBDLENBQUMsQ0FBQTtvQkFDNUQsQ0FBQztvQkFDRCxRQUFRLDRCQUE0QixFQUFFLENBQUM7d0JBQ3RDLEtBQUssa0JBQWtCLENBQUMsYUFBYTs0QkFBRSxDQUFDO2dDQUN2QyxNQUFNLGtCQUFrQixHQUFHLFlBQVksQ0FBQyxHQUFHLENBQUMsTUFBTSxDQUFDLENBQUE7Z0NBQ25ELFlBQVksQ0FBQyxHQUFHLENBQUMsTUFBTSxFQUFFLDJCQUFZLENBQUMsR0FBRyxDQUN4QywyQkFBMkIsQ0FBQyxZQUFZLEVBQ3hDLEdBQUcsQ0FBQyxrQkFBa0IsQ0FBQyxDQUFDLENBQUMsQ0FBQyxrQkFBa0IsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FDbkQsQ0FBQyxDQUFBOzRCQUNILENBQUM7NEJBQUMsTUFBSzt3QkFDUCxLQUFLLGtCQUFrQixDQUFDLE1BQU07NEJBQUUsQ0FBQztnQ0FDaEMsTUFBTSxrQkFBa0IsR0FBRyxNQUFNLENBQUMsR0FBRyxDQUFDLE1BQU0sQ0FBQyxDQUFBO2dDQUM3QyxNQUFNLENBQUMsR0FBRyxDQUFDLE1BQU0sRUFBRSwyQkFBWSxDQUFDLEdBQUcsQ0FDbEMsMkJBQTJCLENBQUMsWUFBWSxFQUN4QyxHQUFHLENBQUMsa0JBQWtCLENBQUMsQ0FBQyxDQUFDLENBQUMsa0JBQWtCLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQ25ELENBQUMsQ0FBQTs0QkFDSCxDQUFDOzRCQUFDLE1BQUs7d0JBQ1AsS0FBSyxrQkFBa0IsQ0FBQyxNQUFNOzRCQUFFLENBQUM7Z0NBQ2hDLE1BQU0sa0JBQWtCLEdBQUcsTUFBTSxDQUFDLEdBQUcsQ0FBQyxNQUFNLENBQUMsQ0FBQTtnQ0FDN0MsTUFBTSxDQUFDLEdBQUcsQ0FBQyxNQUFNLEVBQUUsMkJBQVksQ0FBQyxHQUFHLENBQ2xDLDJCQUEyQixDQUFDLFlBQVksRUFDeEMsR0FBRyxDQUFDLGtCQUFrQixDQUFDLENBQUMsQ0FBQyxDQUFDLGtCQUFrQixDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUNuRCxDQUFDLENBQUE7NEJBQ0gsQ0FBQzs0QkFBQyxNQUFLO29CQUNSLENBQUM7Z0JBRUYsQ0FBQztZQUNGLENBQUM7UUFDRixDQUFDO1FBRUQsSUFBSSxJQUFJLENBQUMsU0FBUyxDQUFDLEVBQUUsS0FBSyxTQUFTLEVBQUUsQ0FBQztZQUNyQyxNQUFNLElBQUksS0FBSyxDQUFDLGdEQUFnRCxDQUFDLENBQUE7UUFDbEUsQ0FBQztRQUNELE1BQU0sYUFBYSxHQUFHLE1BQU0sQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxFQUFFLENBQUMsQ0FBQTtRQUVuRCxNQUFNLE1BQU0sR0FBRyx1Q0FBa0IsQ0FBQyxHQUFHLENBQUMsR0FBRyxTQUFTLENBQUMsQ0FBQTtRQUNuRCxJQUFJLGFBQWEsS0FBSyxTQUFTLEVBQUUsQ0FBQztZQUNqQyx5QkFBeUI7WUFDekIsTUFBTSxDQUFDLFlBQVksQ0FBQyxXQUFXLENBQUMsYUFBYSxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUE7WUFDbEQsTUFBTSxDQUFDLFlBQVksQ0FBQyxlQUFlLENBQUMsYUFBYSxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUE7WUFDdEQseUJBQXlCO1lBQ3pCLE1BQU0sQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxFQUFFLENBQUMsQ0FBQTtRQUNqQyxDQUFDO1FBR0QsT0FBTztZQUNOLEdBQUcsRUFBRSxNQUFNO1lBQ1gsTUFBTTtZQUNOLE1BQU07WUFDTixZQUFZO1NBQ1osQ0FBQTtJQUNGLENBQUM7SUFFRCxxQkFBcUI7UUFDcEIsT0FBTyx1Q0FBa0IsQ0FBQyxHQUFHLENBQUMsR0FBRyxJQUFJLENBQUMsU0FBUyxDQUFDLE1BQU0sRUFBRSxDQUFDLENBQUE7SUFDMUQsQ0FBQztJQUVELFFBQVE7UUFDUCxNQUFNLEVBQUUsR0FBRyxJQUFJLENBQUMsU0FBUyxDQUFDLEVBQUUsQ0FBQTtRQUM1QixJQUFJLEVBQUUsS0FBSyxTQUFTLEVBQUUsQ0FBQztZQUN0QixNQUFNLElBQUksS0FBSyxDQUFDLDBDQUEwQyxDQUFDLENBQUE7UUFDNUQsQ0FBQztRQUVELE1BQU0sT0FBTyxHQUFHO1lBQ2YsMkJBQVksQ0FBQyxZQUFZLENBQUMsRUFBRSxDQUFDO1lBQzdCLElBQUksQ0FBQyxTQUFTLENBQUMsUUFBUSxFQUFFO1NBQ3pCLENBQUE7UUFFRCxPQUFPLE1BQU0sQ0FBQyxNQUFNLENBQUMsT0FBTyxDQUFDLENBQUE7SUFDOUIsQ0FBQztJQUVELE1BQU0sQ0FBQyxpQkFBaUIsQ0FDdkIsTUFBYyxFQUNkLFdBQXdCO1FBRXhCLElBQUksZUFBZSxHQUFHLE1BQU0sQ0FBQTtRQUM1QixNQUFNLEVBQUUsUUFBUSxFQUFFLE1BQU0sRUFBRSxlQUFlLEVBQUUsbUJBQW1CLEVBQUUsR0FBRywyQkFBWSxDQUFDLGNBQWMsQ0FBQyxlQUFlLENBQUMsQ0FBQTtRQUMvRyxlQUFlLEdBQUcsbUJBQW1CLENBQUE7UUFFckMsTUFBTSxTQUFTLEdBQUcsV0FBVyxDQUFDLGdCQUFnQixDQUFDLE1BQXVCLENBQUMsQ0FBQTtRQUN2RSxJQUFJLFNBQVMsS0FBSyxTQUFTLEVBQUUsQ0FBQztZQUM3QixNQUFNLElBQUksS0FBSyxDQUFDLG1FQUFtRSxDQUFDLENBQUE7UUFDckYsQ0FBQztRQUNELE1BQU0sUUFBUSxHQUFHLElBQUksa0JBQWtCLENBQ3RDLFNBQVMsQ0FBQyxVQUFVLEVBQ3BCLFNBQVMsQ0FDVCxDQUFBO1FBQ0QsTUFBTSxnQ0FBZ0MsR0FBRyxDQUFDLE1BQWMsRUFBRSxFQUFFO1lBQzNELE9BQU8sdUNBQWtCLENBQUMsaUJBQWlCLENBRTFDLE1BQU0sRUFDTixXQUFXLENBQ1gsQ0FBQTtRQUNGLENBQUMsQ0FBQTtRQUVELE1BQU0sRUFBRSxRQUFRLEVBQUUsU0FBUyxFQUFFLGVBQWUsRUFBRSxtQkFBbUIsRUFBRSxHQUFHLG1CQUFRLENBQUMsaUJBQWlCLENBSS9GLGVBQWUsRUFDZixRQUFRLEVBQ1IsZ0NBQWdDLENBQ2hDLENBQUE7UUFDRCxRQUFRLENBQUMsVUFBVSxHQUFHLFNBQVMsQ0FBQTtRQUMvQixlQUFlLEdBQUcsbUJBQW1CLENBQUE7UUFFckMsT0FBTztZQUNOLFFBQVE7WUFDUixlQUFlO1NBQ2YsQ0FBQTtJQUNGLENBQUM7Q0FDRDtBQTFYRCxnREEwWEMifQ==