UNPKG

@launchmenu/core

Version:

An environment for visual keyboard controlled applets

204 lines 22.7 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const seededRandom_helper_1 = require("../../../../_tests/seededRandom.helper"); const TextAlterationTools_1 = require("../TextAlterationTools"); describe("TextAlterationTools", () => { describe("TextAlterationTools.mergeAlterations", () => { it("Should update the index to represent the index before the base alterations were made", () => { const combined = TextAlterationTools_1.TextAlterationTools.mergeAlterations([{ start: 10, end: 15, text: "hi" }], // - 3 chars [{ start: 20, end: 20, text: "orange" }]); expect(combined).toEqual([ { start: 10, end: 15, text: "hi" }, { start: 23, end: 23, text: "orange" }, ]); const combined2 = TextAlterationTools_1.TextAlterationTools.mergeAlterations([ { start: 2, end: 2, text: "oran" }, { start: 10, end: 15, text: "hi" }, { start: 24, end: 28, text: "hi" }, ], [{ start: 20, end: 20, text: "orange" }]); expect(combined2).toEqual([ { start: 2, end: 2, text: "oran" }, { start: 10, end: 15, text: "hi" }, { start: 19, end: 19, text: "orange" }, { start: 24, end: 28, text: "hi" }, ]); }); describe("Should merge adjacent alterations", () => { it("Should merge properly at the start", () => { const combined = TextAlterationTools_1.TextAlterationTools.mergeAlterations([{ start: 10, end: 15, text: "hi" }], // - 3 chars, partially after [{ start: 11, end: 11, text: "orange" }]); expect(combined).toEqual([{ start: 10, end: 15, text: "horangei" }]); const combined2 = TextAlterationTools_1.TextAlterationTools.mergeAlterations([ { start: 2, end: 2, text: "oran" }, { start: 10, end: 15, text: "hi" }, { start: 24, end: 28, text: "hi" }, ], [{ start: 15, end: 18, text: "orange" }]); expect(combined2).toEqual([ { start: 2, end: 2, text: "oran" }, { start: 10, end: 17, text: "horange" }, { start: 24, end: 28, text: "hi" }, ]); /* 1. __________=====_________====__ 2. __oran________hi_________hi__ 3. __oran________horange_______hi__ */ }); it("Should merge properly at the end", () => { const combined = TextAlterationTools_1.TextAlterationTools.mergeAlterations([{ start: 10, end: 15, text: "hi" }], // - 3 chars, partially after [{ start: 8, end: 11, text: "orange" }]); expect(combined).toEqual([{ start: 8, end: 15, text: "orangei" }]); const combined2 = TextAlterationTools_1.TextAlterationTools.mergeAlterations([ { start: 2, end: 2, text: "oran" }, { start: 10, end: 15, text: "hi" }, { start: 24, end: 28, text: "hi" }, ], [{ start: 8, end: 15, text: "orange" }]); expect(combined2).toEqual([ { start: 2, end: 2, text: "oran" }, { start: 4, end: 15, text: "orangei" }, { start: 24, end: 28, text: "hi" }, ]); /* 1. __________=====_________====__ 2. __oran________hi_________hi__ 3. __oran__orangei_________hi__ */ }); it("Should merge properly when replacing a whole change", () => { const combined = TextAlterationTools_1.TextAlterationTools.mergeAlterations([{ start: 10, end: 15, text: "hi" }], // - 3 chars [{ start: 8, end: 13, text: "orange" }]); expect(combined).toEqual([{ start: 8, end: 16, text: "orange" }]); const combined2 = TextAlterationTools_1.TextAlterationTools.mergeAlterations([ { start: 2, end: 2, text: "oran" }, { start: 10, end: 15, text: "hi" }, { start: 24, end: 28, text: "hi" }, ], [{ start: 8, end: 20, text: "orange" }]); expect(combined2).toEqual([ { start: 2, end: 2, text: "oran" }, { start: 4, end: 19, text: "orange" }, { start: 24, end: 28, text: "hi" }, ]); /* 1. __________=====_________====__ 2. __oran________hi_________hi__ 3. __oran__orange_____hi__ */ }); }); describe("Should deal with complex scenarios", () => { it("Should work properly with advanced alterations", () => { const inpText = "oranges are cool stuff when bought in a set of 56. That's a magical number that will allow you to not eat them all at once, cus it be a ton of oranges."; const baseAlterations = [ { start: 5, end: 8, text: "POTATOES" }, { start: 8, end: 14, text: "" }, { start: 19, end: 19, text: "BOB" }, { start: 35, end: 45, text: "TOMATO" }, ]; const alterations = [ { start: 5, end: 10, text: "" }, { start: 13, end: 20, text: "ORANGE" }, { start: 22, end: 22, text: "PURPLE" }, { start: 45, end: 48, text: "PANTS" }, ]; testAlterationMerge(inpText, baseAlterations, alterations); }); it("Should work properly with advanced alterations (Generated #663)", () => { const inpText = "nqpkfgqeaarytfdobkyezicujqbyqxjzcdlgspkfmdwmkoywuaqtlrmcdkucvduudrryoxvvgqjefdsbqzgpyovbepkqhxzayhfsiomkgtaocrgrkjqgbrbjwqpkoxhm"; const baseAlterations = [ { start: 18, end: 18, text: "QOSRB" }, ]; const alterations = [ { start: 21, end: 21, text: "RPZWBSPDQFMHMYGP" }, { start: 21, end: 33, text: "" }, ]; testAlterationMerge(inpText, baseAlterations, alterations); }); it(`Should work properly on advanced alterations (Generated tests)`, () => { for (let i = 1; i < 1e3; i++) { executeRandomAlterationMergeTest(i); } }); }); }); }); /** * Performs a test alteration merge test, for the given inputs * @param input The input text * @param baseAlterations The base alterations to merge * @param alterations The alterations to merge into the base alterations */ function testAlterationMerge(inpText, baseAlterations, alterations) { // Execute the 2 steps of alterations separately const intermediateText = TextAlterationTools_1.TextAlterationTools.performAlterations(inpText, baseAlterations); const finalText = TextAlterationTools_1.TextAlterationTools.performAlterations(intermediateText, alterations); // Combine the 2 steps, and perform them at once const combinedAlterations = TextAlterationTools_1.TextAlterationTools.mergeAlterations(baseAlterations, alterations); const finalTextMerged = TextAlterationTools_1.TextAlterationTools.performAlterations(inpText, combinedAlterations); // Check these 2 things are equal expect(finalTextMerged).toEqual(finalText); } /** * Generates a random alteration merging test * @param seed The seed to generate the test with */ function executeRandomAlterationMergeTest(seed) { const random = seededRandom_helper_1.getSeededRandom(seed); // Generate the input text const inpLength = Math.floor(30 + random() * 200); const chars = "abcdefghijklmnopqrstuvwxyz"; const inpText = new Array(inpLength) .fill(0) .map(() => chars[Math.floor(random() * chars.length)]) .join(""); // Generate the base alterations const baseAlterations = generateAlterations(inpLength, random); // Get the intermediate text representation when these changes are applied const intermediateText = TextAlterationTools_1.TextAlterationTools.performAlterations(inpText, baseAlterations); // Generate the further alterations const alterations = generateAlterations(intermediateText.length, random); // Obtain the final text const finalText = TextAlterationTools_1.TextAlterationTools.performAlterations(intermediateText, alterations); // Combine the base and further alterations const combinedAlterations = TextAlterationTools_1.TextAlterationTools.mergeAlterations(baseAlterations, alterations); const finalTextMerged = TextAlterationTools_1.TextAlterationTools.performAlterations(inpText, combinedAlterations); // Check if the direct and are indirect approach yield equivalent results const testID = `#${seed.toString()}-`; try { expect(testID + finalTextMerged).toEqual(testID + finalText); } catch (e) { e.message += `\n text: "${inpText}" \n baseAlterations: ${JSON.stringify(baseAlterations)} \n alterations: ${JSON.stringify(alterations)}`; throw e; } } /** * Generates text alterations in a given range * @param inpLength The range in which alterations are allowed * @param random The function to use to create random values * @returns The alterations */ function generateAlterations(inpLength, random) { const chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; const alterations = []; let index = 0; while (index < inpLength) { // Generate some start and end indices index += Math.floor(random() * 30); const start = index; index += random() > 0.5 ? 0 : Math.floor(random() * 15); // 50% chance of being a text insert const end = index; // Make sure the range is valid if (end < inpLength) { // Generate the replacement text, with 50% probability of being nothing const repLength = random() > 0.5 && end != start ? 0 : Math.floor(random() * 25); const text = new Array(repLength) .fill(0) .map(() => chars[Math.floor(random() * chars.length)]) .join(""); // Add the alteration alterations.push({ start, end, text }); } } return alterations; } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiVGV4dEFsdGVyYXRpb25Ub29scy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uL3NyYy90ZXh0RmllbGRzL2ludGVyYWN0aW9uL2NvbW1hbmRzL190ZXN0cy9UZXh0QWx0ZXJhdGlvblRvb2xzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7O0FBQUEsZ0ZBQXVFO0FBQ3ZFLGdFQUEyRDtBQUczRCxRQUFRLENBQUMscUJBQXFCLEVBQUUsR0FBRyxFQUFFO0lBQ2pDLFFBQVEsQ0FBQyxzQ0FBc0MsRUFBRSxHQUFHLEVBQUU7UUFDbEQsRUFBRSxDQUFDLHNGQUFzRixFQUFFLEdBQUcsRUFBRTtZQUM1RixNQUFNLFFBQVEsR0FBRyx5Q0FBbUIsQ0FBQyxnQkFBZ0IsQ0FDakQsQ0FBQyxFQUFDLEtBQUssRUFBRSxFQUFFLEVBQUUsR0FBRyxFQUFFLEVBQUUsRUFBRSxJQUFJLEVBQUUsSUFBSSxFQUFDLENBQUMsRUFBRSxZQUFZO1lBQ2hELENBQUMsRUFBQyxLQUFLLEVBQUUsRUFBRSxFQUFFLEdBQUcsRUFBRSxFQUFFLEVBQUUsSUFBSSxFQUFFLFFBQVEsRUFBQyxDQUFDLENBQ3pDLENBQUM7WUFFRixNQUFNLENBQUMsUUFBUSxDQUFDLENBQUMsT0FBTyxDQUFDO2dCQUNyQixFQUFDLEtBQUssRUFBRSxFQUFFLEVBQUUsR0FBRyxFQUFFLEVBQUUsRUFBRSxJQUFJLEVBQUUsSUFBSSxFQUFDO2dCQUNoQyxFQUFDLEtBQUssRUFBRSxFQUFFLEVBQUUsR0FBRyxFQUFFLEVBQUUsRUFBRSxJQUFJLEVBQUUsUUFBUSxFQUFDO2FBQ3ZDLENBQUMsQ0FBQztZQUVILE1BQU0sU0FBUyxHQUFHLHlDQUFtQixDQUFDLGdCQUFnQixDQUNsRDtnQkFDSSxFQUFDLEtBQUssRUFBRSxDQUFDLEVBQUUsR0FBRyxFQUFFLENBQUMsRUFBRSxJQUFJLEVBQUUsTUFBTSxFQUFDO2dCQUNoQyxFQUFDLEtBQUssRUFBRSxFQUFFLEVBQUUsR0FBRyxFQUFFLEVBQUUsRUFBRSxJQUFJLEVBQUUsSUFBSSxFQUFDO2dCQUNoQyxFQUFDLEtBQUssRUFBRSxFQUFFLEVBQUUsR0FBRyxFQUFFLEVBQUUsRUFBRSxJQUFJLEVBQUUsSUFBSSxFQUFDO2FBQ25DLEVBQ0QsQ0FBQyxFQUFDLEtBQUssRUFBRSxFQUFFLEVBQUUsR0FBRyxFQUFFLEVBQUUsRUFBRSxJQUFJLEVBQUUsUUFBUSxFQUFDLENBQUMsQ0FDekMsQ0FBQztZQUVGLE1BQU0sQ0FBQyxTQUFTLENBQUMsQ0FBQyxPQUFPLENBQUM7Z0JBQ3RCLEVBQUMsS0FBSyxFQUFFLENBQUMsRUFBRSxHQUFHLEVBQUUsQ0FBQyxFQUFFLElBQUksRUFBRSxNQUFNLEVBQUM7Z0JBQ2hDLEVBQUMsS0FBSyxFQUFFLEVBQUUsRUFBRSxHQUFHLEVBQUUsRUFBRSxFQUFFLElBQUksRUFBRSxJQUFJLEVBQUM7Z0JBQ2hDLEVBQUMsS0FBSyxFQUFFLEVBQUUsRUFBRSxHQUFHLEVBQUUsRUFBRSxFQUFFLElBQUksRUFBRSxRQUFRLEVBQUM7Z0JBQ3BDLEVBQUMsS0FBSyxFQUFFLEVBQUUsRUFBRSxHQUFHLEVBQUUsRUFBRSxFQUFFLElBQUksRUFBRSxJQUFJLEVBQUM7YUFDbkMsQ0FBQyxDQUFDO1FBQ1AsQ0FBQyxDQUFDLENBQUM7UUFDSCxRQUFRLENBQUMsbUNBQW1DLEVBQUUsR0FBRyxFQUFFO1lBQy9DLEVBQUUsQ0FBQyxvQ0FBb0MsRUFBRSxHQUFHLEVBQUU7Z0JBQzFDLE1BQU0sUUFBUSxHQUFHLHlDQUFtQixDQUFDLGdCQUFnQixDQUNqRCxDQUFDLEVBQUMsS0FBSyxFQUFFLEVBQUUsRUFBRSxHQUFHLEVBQUUsRUFBRSxFQUFFLElBQUksRUFBRSxJQUFJLEVBQUMsQ0FBQyxFQUFFLDZCQUE2QjtnQkFDakUsQ0FBQyxFQUFDLEtBQUssRUFBRSxFQUFFLEVBQUUsR0FBRyxFQUFFLEVBQUUsRUFBRSxJQUFJLEVBQUUsUUFBUSxFQUFDLENBQUMsQ0FDekMsQ0FBQztnQkFFRixNQUFNLENBQUMsUUFBUSxDQUFDLENBQUMsT0FBTyxDQUFDLENBQUMsRUFBQyxLQUFLLEVBQUUsRUFBRSxFQUFFLEdBQUcsRUFBRSxFQUFFLEVBQUUsSUFBSSxFQUFFLFVBQVUsRUFBQyxDQUFDLENBQUMsQ0FBQztnQkFFbkUsTUFBTSxTQUFTLEdBQUcseUNBQW1CLENBQUMsZ0JBQWdCLENBQ2xEO29CQUNJLEVBQUMsS0FBSyxFQUFFLENBQUMsRUFBRSxHQUFHLEVBQUUsQ0FBQyxFQUFFLElBQUksRUFBRSxNQUFNLEVBQUM7b0JBQ2hDLEVBQUMsS0FBSyxFQUFFLEVBQUUsRUFBRSxHQUFHLEVBQUUsRUFBRSxFQUFFLElBQUksRUFBRSxJQUFJLEVBQUM7b0JBQ2hDLEVBQUMsS0FBSyxFQUFFLEVBQUUsRUFBRSxHQUFHLEVBQUUsRUFBRSxFQUFFLElBQUksRUFBRSxJQUFJLEVBQUM7aUJBQ25DLEVBQ0QsQ0FBQyxFQUFDLEtBQUssRUFBRSxFQUFFLEVBQUUsR0FBRyxFQUFFLEVBQUUsRUFBRSxJQUFJLEVBQUUsUUFBUSxFQUFDLENBQUMsQ0FDekMsQ0FBQztnQkFFRixNQUFNLENBQUMsU0FBUyxDQUFDLENBQUMsT0FBTyxDQUFDO29CQUN0QixFQUFDLEtBQUssRUFBRSxDQUFDLEVBQUUsR0FBRyxFQUFFLENBQUMsRUFBRSxJQUFJLEVBQUUsTUFBTSxFQUFDO29CQUNoQyxFQUFDLEtBQUssRUFBRSxFQUFFLEVBQUUsR0FBRyxFQUFFLEVBQUUsRUFBRSxJQUFJLEVBQUUsU0FBUyxFQUFDO29CQUNyQyxFQUFDLEtBQUssRUFBRSxFQUFFLEVBQUUsR0FBRyxFQUFFLEVBQUUsRUFBRSxJQUFJLEVBQUUsSUFBSSxFQUFDO2lCQUNuQyxDQUFDLENBQUM7Z0JBRUg7Ozs7bUJBSUc7WUFDUCxDQUFDLENBQUMsQ0FBQztZQUNILEVBQUUsQ0FBQyxrQ0FBa0MsRUFBRSxHQUFHLEVBQUU7Z0JBQ3hDLE1BQU0sUUFBUSxHQUFHLHlDQUFtQixDQUFDLGdCQUFnQixDQUNqRCxDQUFDLEVBQUMsS0FBSyxFQUFFLEVBQUUsRUFBRSxHQUFHLEVBQUUsRUFBRSxFQUFFLElBQUksRUFBRSxJQUFJLEVBQUMsQ0FBQyxFQUFFLDZCQUE2QjtnQkFDakUsQ0FBQyxFQUFDLEtBQUssRUFBRSxDQUFDLEVBQUUsR0FBRyxFQUFFLEVBQUUsRUFBRSxJQUFJLEVBQUUsUUFBUSxFQUFDLENBQUMsQ0FDeEMsQ0FBQztnQkFFRixNQUFNLENBQUMsUUFBUSxDQUFDLENBQUMsT0FBTyxDQUFDLENBQUMsRUFBQyxLQUFLLEVBQUUsQ0FBQyxFQUFFLEdBQUcsRUFBRSxFQUFFLEVBQUUsSUFBSSxFQUFFLFNBQVMsRUFBQyxDQUFDLENBQUMsQ0FBQztnQkFFakUsTUFBTSxTQUFTLEdBQUcseUNBQW1CLENBQUMsZ0JBQWdCLENBQ2xEO29CQUNJLEVBQUMsS0FBSyxFQUFFLENBQUMsRUFBRSxHQUFHLEVBQUUsQ0FBQyxFQUFFLElBQUksRUFBRSxNQUFNLEVBQUM7b0JBQ2hDLEVBQUMsS0FBSyxFQUFFLEVBQUUsRUFBRSxHQUFHLEVBQUUsRUFBRSxFQUFFLElBQUksRUFBRSxJQUFJLEVBQUM7b0JBQ2hDLEVBQUMsS0FBSyxFQUFFLEVBQUUsRUFBRSxHQUFHLEVBQUUsRUFBRSxFQUFFLElBQUksRUFBRSxJQUFJLEVBQUM7aUJBQ25DLEVBQ0QsQ0FBQyxFQUFDLEtBQUssRUFBRSxDQUFDLEVBQUUsR0FBRyxFQUFFLEVBQUUsRUFBRSxJQUFJLEVBQUUsUUFBUSxFQUFDLENBQUMsQ0FDeEMsQ0FBQztnQkFFRixNQUFNLENBQUMsU0FBUyxDQUFDLENBQUMsT0FBTyxDQUFDO29CQUN0QixFQUFDLEtBQUssRUFBRSxDQUFDLEVBQUUsR0FBRyxFQUFFLENBQUMsRUFBRSxJQUFJLEVBQUUsTUFBTSxFQUFDO29CQUNoQyxFQUFDLEtBQUssRUFBRSxDQUFDLEVBQUUsR0FBRyxFQUFFLEVBQUUsRUFBRSxJQUFJLEVBQUUsU0FBUyxFQUFDO29CQUNwQyxFQUFDLEtBQUssRUFBRSxFQUFFLEVBQUUsR0FBRyxFQUFFLEVBQUUsRUFBRSxJQUFJLEVBQUUsSUFBSSxFQUFDO2lCQUNuQyxDQUFDLENBQUM7Z0JBRUg7Ozs7bUJBSUc7WUFDUCxDQUFDLENBQUMsQ0FBQztZQUNILEVBQUUsQ0FBQyxxREFBcUQsRUFBRSxHQUFHLEVBQUU7Z0JBQzNELE1BQU0sUUFBUSxHQUFHLHlDQUFtQixDQUFDLGdCQUFnQixDQUNqRCxDQUFDLEVBQUMsS0FBSyxFQUFFLEVBQUUsRUFBRSxHQUFHLEVBQUUsRUFBRSxFQUFFLElBQUksRUFBRSxJQUFJLEVBQUMsQ0FBQyxFQUFFLFlBQVk7Z0JBQ2hELENBQUMsRUFBQyxLQUFLLEVBQUUsQ0FBQyxFQUFFLEdBQUcsRUFBRSxFQUFFLEVBQUUsSUFBSSxFQUFFLFFBQVEsRUFBQyxDQUFDLENBQ3hDLENBQUM7Z0JBRUYsTUFBTSxDQUFDLFFBQVEsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxDQUFDLEVBQUMsS0FBSyxFQUFFLENBQUMsRUFBRSxHQUFHLEVBQUUsRUFBRSxFQUFFLElBQUksRUFBRSxRQUFRLEVBQUMsQ0FBQyxDQUFDLENBQUM7Z0JBRWhFLE1BQU0sU0FBUyxHQUFHLHlDQUFtQixDQUFDLGdCQUFnQixDQUNsRDtvQkFDSSxFQUFDLEtBQUssRUFBRSxDQUFDLEVBQUUsR0FBRyxFQUFFLENBQUMsRUFBRSxJQUFJLEVBQUUsTUFBTSxFQUFDO29CQUNoQyxFQUFDLEtBQUssRUFBRSxFQUFFLEVBQUUsR0FBRyxFQUFFLEVBQUUsRUFBRSxJQUFJLEVBQUUsSUFBSSxFQUFDO29CQUNoQyxFQUFDLEtBQUssRUFBRSxFQUFFLEVBQUUsR0FBRyxFQUFFLEVBQUUsRUFBRSxJQUFJLEVBQUUsSUFBSSxFQUFDO2lCQUNuQyxFQUNELENBQUMsRUFBQyxLQUFLLEVBQUUsQ0FBQyxFQUFFLEdBQUcsRUFBRSxFQUFFLEVBQUUsSUFBSSxFQUFFLFFBQVEsRUFBQyxDQUFDLENBQ3hDLENBQUM7Z0JBRUYsTUFBTSxDQUFDLFNBQVMsQ0FBQyxDQUFDLE9BQU8sQ0FBQztvQkFDdEIsRUFBQyxLQUFLLEVBQUUsQ0FBQyxFQUFFLEdBQUcsRUFBRSxDQUFDLEVBQUUsSUFBSSxFQUFFLE1BQU0sRUFBQztvQkFDaEMsRUFBQyxLQUFLLEVBQUUsQ0FBQyxFQUFFLEdBQUcsRUFBRSxFQUFFLEVBQUUsSUFBSSxFQUFFLFFBQVEsRUFBQztvQkFDbkMsRUFBQyxLQUFLLEVBQUUsRUFBRSxFQUFFLEdBQUcsRUFBRSxFQUFFLEVBQUUsSUFBSSxFQUFFLElBQUksRUFBQztpQkFDbkMsQ0FBQyxDQUFDO2dCQUVIOzs7O21CQUlHO1lBQ1AsQ0FBQyxDQUFDLENBQUM7UUFDUCxDQUFDLENBQUMsQ0FBQztRQUNILFFBQVEsQ0FBQyxvQ0FBb0MsRUFBRSxHQUFHLEVBQUU7WUFDaEQsRUFBRSxDQUFDLGdEQUFnRCxFQUFFLEdBQUcsRUFBRTtnQkFDdEQsTUFBTSxPQUFPLEdBQ1QseUpBQXlKLENBQUM7Z0JBRTlKLE1BQU0sZUFBZSxHQUFHO29CQUNwQixFQUFDLEtBQUssRUFBRSxDQUFDLEVBQUUsR0FBRyxFQUFFLENBQUMsRUFBRSxJQUFJLEVBQUUsVUFBVSxFQUFDO29CQUNwQyxFQUFDLEtBQUssRUFBRSxDQUFDLEVBQUUsR0FBRyxFQUFFLEVBQUUsRUFBRSxJQUFJLEVBQUUsRUFBRSxFQUFDO29CQUM3QixFQUFDLEtBQUssRUFBRSxFQUFFLEVBQUUsR0FBRyxFQUFFLEVBQUUsRUFBRSxJQUFJLEVBQUUsS0FBSyxFQUFDO29CQUNqQyxFQUFDLEtBQUssRUFBRSxFQUFFLEVBQUUsR0FBRyxFQUFFLEVBQUUsRUFBRSxJQUFJLEVBQUUsUUFBUSxFQUFDO2lCQUN2QyxDQUFDO2dCQUVGLE1BQU0sV0FBVyxHQUFHO29CQUNoQixFQUFDLEtBQUssRUFBRSxDQUFDLEVBQUUsR0FBRyxFQUFFLEVBQUUsRUFBRSxJQUFJLEVBQUUsRUFBRSxFQUFDO29CQUM3QixFQUFDLEtBQUssRUFBRSxFQUFFLEVBQUUsR0FBRyxFQUFFLEVBQUUsRUFBRSxJQUFJLEVBQUUsUUFBUSxFQUFDO29CQUNwQyxFQUFDLEtBQUssRUFBRSxFQUFFLEVBQUUsR0FBRyxFQUFFLEVBQUUsRUFBRSxJQUFJLEVBQUUsUUFBUSxFQUFDO29CQUNwQyxFQUFDLEtBQUssRUFBRSxFQUFFLEVBQUUsR0FBRyxFQUFFLEVBQUUsRUFBRSxJQUFJLEVBQUUsT0FBTyxFQUFDO2lCQUN0QyxDQUFDO2dCQUVGLG1CQUFtQixDQUFDLE9BQU8sRUFBRSxlQUFlLEVBQUUsV0FBVyxDQUFDLENBQUM7WUFDL0QsQ0FBQyxDQUFDLENBQUM7WUFDSCxFQUFFLENBQUMsaUVBQWlFLEVBQUUsR0FBRyxFQUFFO2dCQUN2RSxNQUFNLE9BQU8sR0FDVCxrSUFBa0ksQ0FBQztnQkFFdkksTUFBTSxlQUFlLEdBQUc7b0JBQ3BCLEVBQUMsS0FBSyxFQUFFLEVBQUUsRUFBRSxHQUFHLEVBQUUsRUFBRSxFQUFFLElBQUksRUFBRSxPQUFPLEVBQUM7aUJBUXRDLENBQUM7Z0JBRUYsTUFBTSxXQUFXLEdBQUc7b0JBQ2hCLEVBQUMsS0FBSyxFQUFFLEVBQUUsRUFBRSxHQUFHLEVBQUUsRUFBRSxFQUFFLElBQUksRUFBRSxrQkFBa0IsRUFBQztvQkFDOUMsRUFBQyxLQUFLLEVBQUUsRUFBRSxFQUFFLEdBQUcsRUFBRSxFQUFFLEVBQUUsSUFBSSxFQUFFLEVBQUUsRUFBQztpQkFlakMsQ0FBQztnQkFFRixtQkFBbUIsQ0FBQyxPQUFPLEVBQUUsZUFBZSxFQUFFLFdBQVcsQ0FBQyxDQUFDO1lBQy9ELENBQUMsQ0FBQyxDQUFDO1lBQ0gsRUFBRSxDQUFDLGdFQUFnRSxFQUFFLEdBQUcsRUFBRTtnQkFDdEUsS0FBSyxJQUFJLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxHQUFHLEdBQUcsRUFBRSxDQUFDLEVBQUUsRUFBRTtvQkFDMUIsZ0NBQWdDLENBQUMsQ0FBQyxDQUFDLENBQUM7aUJBQ3ZDO1lBQ0wsQ0FBQyxDQUFDLENBQUM7UUFDUCxDQUFDLENBQUMsQ0FBQztJQUNQLENBQUMsQ0FBQyxDQUFDO0FBQ1AsQ0FBQyxDQUFDLENBQUM7QUFFSDs7Ozs7R0FLRztBQUNILFNBQVMsbUJBQW1CLENBQ3hCLE9BQWUsRUFDZixlQUF1QyxFQUN2QyxXQUFtQztJQUVuQyxnREFBZ0Q7SUFDaEQsTUFBTSxnQkFBZ0IsR0FBRyx5Q0FBbUIsQ0FBQyxrQkFBa0IsQ0FDM0QsT0FBTyxFQUNQLGVBQWUsQ0FDbEIsQ0FBQztJQUNGLE1BQU0sU0FBUyxHQUFHLHlDQUFtQixDQUFDLGtCQUFrQixDQUNwRCxnQkFBZ0IsRUFDaEIsV0FBVyxDQUNkLENBQUM7SUFFRixnREFBZ0Q7SUFDaEQsTUFBTSxtQkFBbUIsR0FBRyx5Q0FBbUIsQ0FBQyxnQkFBZ0IsQ0FDNUQsZUFBZSxFQUNmLFdBQVcsQ0FDZCxDQUFDO0lBQ0YsTUFBTSxlQUFlLEdBQUcseUNBQW1CLENBQUMsa0JBQWtCLENBQzFELE9BQU8sRUFDUCxtQkFBbUIsQ0FDdEIsQ0FBQztJQUVGLGlDQUFpQztJQUNqQyxNQUFNLENBQUMsZUFBZSxDQUFDLENBQUMsT0FBTyxDQUFDLFNBQVMsQ0FBQyxDQUFDO0FBQy9DLENBQUM7QUFFRDs7O0dBR0c7QUFDSCxTQUFTLGdDQUFnQyxDQUFDLElBQVk7SUFDbEQsTUFBTSxNQUFNLEdBQUcscUNBQWUsQ0FBQyxJQUFJLENBQUMsQ0FBQztJQUVyQywwQkFBMEI7SUFDMUIsTUFBTSxTQUFTLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxFQUFFLEdBQUcsTUFBTSxFQUFFLEdBQUcsR0FBRyxDQUFDLENBQUM7SUFDbEQsTUFBTSxLQUFLLEdBQUcsNEJBQTRCLENBQUM7SUFDM0MsTUFBTSxPQUFPLEdBQUcsSUFBSSxLQUFLLENBQUMsU0FBUyxDQUFDO1NBQy9CLElBQUksQ0FBQyxDQUFDLENBQUM7U0FDUCxHQUFHLENBQUMsR0FBRyxFQUFFLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsTUFBTSxFQUFFLEdBQUcsS0FBSyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUM7U0FDckQsSUFBSSxDQUFDLEVBQUUsQ0FBQyxDQUFDO0lBRWQsZ0NBQWdDO0lBQ2hDLE1BQU0sZUFBZSxHQUFHLG1CQUFtQixDQUFDLFNBQVMsRUFBRSxNQUFNLENBQUMsQ0FBQztJQUUvRCwwRUFBMEU7SUFDMUUsTUFBTSxnQkFBZ0IsR0FBRyx5Q0FBbUIsQ0FBQyxrQkFBa0IsQ0FDM0QsT0FBTyxFQUNQLGVBQWUsQ0FDbEIsQ0FBQztJQUVGLG1DQUFtQztJQUNuQyxNQUFNLFdBQVcsR0FBRyxtQkFBbUIsQ0FBQyxnQkFBZ0IsQ0FBQyxNQUFNLEVBQUUsTUFBTSxDQUFDLENBQUM7SUFFekUsd0JBQXdCO0lBQ3hCLE1BQU0sU0FBUyxHQUFHLHlDQUFtQixDQUFDLGtCQUFrQixDQUNwRCxnQkFBZ0IsRUFDaEIsV0FBVyxDQUNkLENBQUM7SUFFRiwyQ0FBMkM7SUFDM0MsTUFBTSxtQkFBbUIsR0FBRyx5Q0FBbUIsQ0FBQyxnQkFBZ0IsQ0FDNUQsZUFBZSxFQUNmLFdBQVcsQ0FDZCxDQUFDO0lBQ0YsTUFBTSxlQUFlLEdBQUcseUNBQW1CLENBQUMsa0JBQWtCLENBQzFELE9BQU8sRUFDUCxtQkFBbUIsQ0FDdEIsQ0FBQztJQUVGLHlFQUF5RTtJQUN6RSxNQUFNLE1BQU0sR0FBRyxJQUFJLElBQUksQ0FBQyxRQUFRLEVBQUUsR0FBRyxDQUFDO0lBQ3RDLElBQUk7UUFDQSxNQUFNLENBQUMsTUFBTSxHQUFHLGVBQWUsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxNQUFNLEdBQUcsU0FBUyxDQUFDLENBQUM7S0FDaEU7SUFBQyxPQUFPLENBQUMsRUFBRTtRQUNSLENBQUMsQ0FBQyxPQUFPLElBQUksYUFBYSxPQUFPLHlCQUF5QixJQUFJLENBQUMsU0FBUyxDQUNwRSxlQUFlLENBQ2xCLG9CQUFvQixJQUFJLENBQUMsU0FBUyxDQUFDLFdBQVcsQ0FBQyxFQUFFLENBQUM7UUFDbkQsTUFBTSxDQUFDLENBQUM7S0FDWDtBQUNMLENBQUM7QUFFRDs7Ozs7R0FLRztBQUNILFNBQVMsbUJBQW1CLENBQ3hCLFNBQWlCLEVBQ2pCLE1BQW9CO0lBRXBCLE1BQU0sS0FBSyxHQUFHLDRCQUE0QixDQUFDO0lBRTNDLE1BQU0sV0FBVyxHQUEyQixFQUFFLENBQUM7SUFDL0MsSUFBSSxLQUFLLEdBQUcsQ0FBQyxDQUFDO0lBQ2QsT0FBTyxLQUFLLEdBQUcsU0FBUyxFQUFFO1FBQ3RCLHNDQUFzQztRQUN0QyxLQUFLLElBQUksSUFBSSxDQUFDLEtBQUssQ0FBQyxNQUFNLEVBQUUsR0FBRyxFQUFFLENBQUMsQ0FBQztRQUNuQyxNQUFNLEtBQUssR0FBRyxLQUFLLENBQUM7UUFDcEIsS0FBSyxJQUFJLE1BQU0sRUFBRSxHQUFHLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLE1BQU0sRUFBRSxHQUFHLEVBQUUsQ0FBQyxDQUFDLENBQUMsb0NBQW9DO1FBQzdGLE1BQU0sR0FBRyxHQUFHLEtBQUssQ0FBQztRQUVsQiwrQkFBK0I7UUFDL0IsSUFBSSxHQUFHLEdBQUcsU0FBUyxFQUFFO1lBQ2pCLHVFQUF1RTtZQUN2RSxNQUFNLFNBQVMsR0FDWCxNQUFNLEVBQUUsR0FBRyxHQUFHLElBQUksR0FBRyxJQUFJLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLE1BQU0sRUFBRSxHQUFHLEVBQUUsQ0FBQyxDQUFDO1lBQ25FLE1BQU0sSUFBSSxHQUFHLElBQUksS0FBSyxDQUFDLFNBQVMsQ0FBQztpQkFDNUIsSUFBSSxDQUFDLENBQUMsQ0FBQztpQkFDUCxHQUFHLENBQUMsR0FBRyxFQUFFLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsTUFBTSxFQUFFLEdBQUcsS0FBSyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUM7aUJBQ3JELElBQUksQ0FBQyxFQUFFLENBQUMsQ0FBQztZQUVkLHFCQUFxQjtZQUNyQixXQUFXLENBQUMsSUFBSSxDQUFDLEVBQUMsS0FBSyxFQUFFLEdBQUcsRUFBRSxJQUFJLEVBQUMsQ0FBQyxDQUFDO1NBQ3hDO0tBQ0o7SUFFRCxPQUFPLFdBQVcsQ0FBQztBQUN2QixDQUFDIn0=