diff --git a/.Dockerfile b/.Dockerfile index aba8a16..b01c0b8 100644 --- a/.Dockerfile +++ b/.Dockerfile @@ -30,7 +30,7 @@ RUN mkdir -p /home/appuser/logs COPY static ./static COPY templates ./templates COPY tests ./tests -COPY xi_web_api ./xi_web_api +COPY xiview_server ./xiview_server COPY .env . COPY default.database.ini . COPY logging.ini . diff --git a/.env b/.env index 221c6d1..d81ef52 100644 --- a/.env +++ b/.env @@ -1,3 +1,3 @@ PYTHONHASHSEED=0 -FLASK_APP="xi_web_api/pride_loader.py" +FLASK_APP="xiview_server/pride_loader.py" XI2XIVIEWLOADER_SETTINGS=config \ No newline at end of file diff --git a/logging.ini b/logging.ini index 603757a..e3c27b0 100644 --- a/logging.ini +++ b/logging.ini @@ -15,7 +15,12 @@ handlers=fileHandler, console_handler class=FileHandler level=DEBUG formatter=simpleFormatter -args=('logs/xi_web_api.log',) +args=('logs/xiview_server.log',) + +[handler_console_handler] +class = StreamHandler +formatter = simpleFormatter +args = (sys.stdout,) [handler_console_handler] class = StreamHandler diff --git a/setup.cfg b/setup.cfg index fbe0f97..9894735 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,7 +1,7 @@ [tool:pytest] pep8maxlinelength = 100 flake8-max-line-length = 100 -#addopts = --cov=xi_web_api --cov-report html --cov-branch --cov-fail-under=90 --flake8 +#addopts = --cov=xiview_server --cov-report html --cov-branch --cov-fail-under=90 --flake8 [flake8] ignore = F403,E226,F405,W503 diff --git a/static/network.html b/static/network.html index 4883812..7376e1b 100644 --- a/static/network.html +++ b/static/network.html @@ -165,8 +165,8 @@ // diff --git a/static/pride.css b/static/pride.css index bca8b36..f3e9756 100644 --- a/static/pride.css +++ b/static/pride.css @@ -92,4 +92,8 @@ #xiNetButtonBar > span.layoutLabel.noBreak.sectionDividerLeft { border-left: 0; +} + +#helpDropdownPlaceholder > div > ul > li:nth-child(1) { + display: none !important; } \ No newline at end of file diff --git a/static/xiview.js b/static/xiview.js index c29bbf0..cdb8ef4 100644 --- a/static/xiview.js +++ b/static/xiview.js @@ -1,243777 +1,2 @@ -(function webpackUniversalModuleDefinition(root, factory) { - if(typeof exports === 'object' && typeof module === 'object') - module.exports = factory(); - else if(typeof define === 'function' && define.amd) - define([], factory); - else if(typeof exports === 'object') - exports["xiview"] = factory(); - else - root["xiview"] = factory(); -})(self, () => { -return /******/ (() => { // webpackBootstrap -/******/ var __webpack_modules__ = ({ - -/***/ "./CLMS-model/src/crosslink.js": -/*!*************************************!*\ - !*** ./CLMS-model/src/crosslink.js ***! - \*************************************/ -/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { - -"use strict"; -__webpack_require__.r(__webpack_exports__); -/* harmony export */ __webpack_require__.d(__webpack_exports__, { -/* harmony export */ Crosslink: () => (/* binding */ Crosslink) -/* harmony export */ }); -class Crosslink { - constructor(id, fromProtein, fromResidue, toProtein, toResidue) { - this.id = id; - this.matches_pp = []; - this.filteredMatches_pp = []; - - this.fromProtein = fromProtein; - this.fromResidue = fromResidue; - this.toProtein = toProtein; - this.toResidue = toResidue; - } - - isDecoyLink() { - return (this.fromProtein.is_decoy === true || - (this.toProtein && this.toProtein.is_decoy === true)); - } - - isSelfLink() { - return this.fromProtein && this.toProtein && this.fromProtein.targetProteinID === this.toProtein.targetProteinID; // mjg - } - - isLinearLink() { - return this.matches_pp[0].match.isNotCrosslinked(); - } - - isMonoLink() { - return this.matches_pp[0].match.isMonoLink(); - } - - getMeta(metaField) { - if (arguments.length === 0) { - return this.meta; - } - return this.meta ? this.meta[metaField] : undefined; - } - - setMeta(metaField, value) { - if (arguments.length === 2) { - this.meta = this.meta || {}; - this.meta[metaField] = value; - } - } -} - - -/***/ }), - -/***/ "./CLMS-model/src/old-load-spectrum.js": -/*!*********************************************!*\ - !*** ./CLMS-model/src/old-load-spectrum.js ***! - \*********************************************/ -/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { - -"use strict"; -__webpack_require__.r(__webpack_exports__); -/* harmony export */ __webpack_require__.d(__webpack_exports__, { -/* harmony export */ oldLoadSpectrum: () => (/* binding */ oldLoadSpectrum) -/* harmony export */ }); -/* harmony import */ var d3__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! d3 */ "./node_modules/d3/d3.js"); -/* harmony import */ var d3__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(d3__WEBPACK_IMPORTED_MODULE_0__); - - -const oldLoadSpectrum = function (match, randId) { - if (match.spectrum && match.spectrum.pks) { - const formatted_data = {}; - - formatted_data.sequence1 = match.matchedPeptides[0].seq_mods; - formatted_data.linkPos1 = match.linkPos1 - 1; - if (match.matchedPeptides[1]) { - formatted_data.sequence2 = match.matchedPeptides[1].seq_mods; - formatted_data.linkPos2 = match.linkPos2 - 1; - } - formatted_data.crossLinkerModMass = match.crosslinkerModMass(); - formatted_data.modifications = window.compositeModelInst.get("clmsModel").get("modifications"); - formatted_data.precursorCharge = match.precursorCharge; - formatted_data.fragmentTolerance = match.fragmentTolerance(); - //formatted_data.customConfig = CLMSUI.compositeModelInst.get("clmsModel").get("searches").get(match.searchId).customsettings.split('\n'); - - const ions = match.ionTypes(); - formatted_data.ionTypes = ions.map(function (ion) { - return ion.type.replace("Ion", ""); - }).join(";"); - formatted_data.precursorMZ = match.expMZ(); - formatted_data.requestID = match.id; - - console.log("loadSpectrum match:" + match.id); - - d3__WEBPACK_IMPORTED_MODULE_0___default().json("./php/peakList.php?upload=" + match.searchId + "-" + randId + "&spid=" + match.spectrumId, function (error, json) { - if (error) { - console.log("error getting peak list", json); - } else { - d3__WEBPACK_IMPORTED_MODULE_0___default().select("#range-error").text(""); - - - console.log(json); - const peakArray = []; - const peakCount = json.mz.length; - for (let i = 0; i < peakCount; i++) { - peakArray.push([json.mz[i], json.intensity[i]]); - } - - formatted_data.peakList = peakArray; //JSON.parse(text).map(function(p){ return [p.mz, p.intensity]; }); - console.log(formatted_data); - window.xiSPEC.setData(formatted_data); - } - }); - } -}; - - -/***/ }), - -/***/ "./CLMS-model/src/pride-load-spectrum.js": -/*!***********************************************!*\ - !*** ./CLMS-model/src/pride-load-spectrum.js ***! - \***********************************************/ -/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { - -"use strict"; -__webpack_require__.r(__webpack_exports__); -/* harmony export */ __webpack_require__.d(__webpack_exports__, { -/* harmony export */ prideLoadSpectrum: () => (/* binding */ prideLoadSpectrum) -/* harmony export */ }); -/* harmony import */ var d3__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! d3 */ "./node_modules/d3/d3.js"); -/* harmony import */ var d3__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(d3__WEBPACK_IMPORTED_MODULE_0__); - - -const prideLoadSpectrum = function (match, randId) { - // if (match.spectrum && match.spectrum.pks) { - const formatted_data = {}; - - const modMap = new Map(); - function createModSequence(peptide) { - let seqMods = ""; - const pepLen = peptide.base_seq.length; - for (let i = 0; i < pepLen; i++) { - seqMods += peptide.base_seq[i]; - if (peptide.mod_pos.indexOf(i) !== -1){ - const modIndex = peptide.mod_pos.indexOf(i); - const modName = "(" + peptide.mod_masses[modIndex] + ")"; - seqMods += modName; - if (!modMap.has(modName)) { - modMap.set(modName, peptide.mod_masses[modIndex]); - } - } - } - - return seqMods; - } - - console.log(createModSequence(match.matchedPeptides[0])); - - formatted_data.sequence1 = createModSequence(match.matchedPeptides[0]); - formatted_data.linkPos1 = match.linkPos1 - 1; - if (match.matchedPeptides[1]) { - formatted_data.sequence2 = createModSequence(match.matchedPeptides[1]); - formatted_data.linkPos2 = match.linkPos2 - 1; - } - formatted_data.crossLinkerModMass = match.crosslinkerModMass(); - - const modifications = []; - modMap.forEach(function (value, key) { - modifications.push({id: key, mass: value, aminoAcids: ["*"]}); - }); - - formatted_data.modifications = modifications; - formatted_data.precursorCharge = match.precursorCharge; - formatted_data.fragmentTolerance = match.fragmentTolerance(); - - const ions = match.ionTypes(); - formatted_data.ionTypes = ions.map(function (ion) { - return ion.type.replace("Ion", ""); - }).join(";"); - formatted_data.precursorMZ = match.expMZ(); - formatted_data.requestID = match.id; - - console.log("prideLoadSpectrum match:" + match.id); - - d3__WEBPACK_IMPORTED_MODULE_0___default().json("./get_peaklist?id=" + match.spectrumId + "&sd_ref=" + match.identification.sd_ref + "&upload_id=" + match.searchId, function (error, json) { - if (error) { - console.log("error getting peak list", json); - } else { - d3__WEBPACK_IMPORTED_MODULE_0___default().select("#range-error").text(""); - - - console.log(json); - const peakArray = []; - const peakCount = json.mz.length; - for (let i = 0; i < peakCount; i++) { - peakArray.push([json.mz[i], json.intensity[i]]); - } - - formatted_data.peakList = peakArray; //JSON.parse(text).map(function(p){ return [p.mz, p.intensity]; }); - console.log(formatted_data); - window.compositeModelInst.get("xispec_wrapper").setData(formatted_data); - } - }); - // } -}; - - -/***/ }), - -/***/ "./CLMS-model/src/search-results-model.js": -/*!************************************************!*\ - !*** ./CLMS-model/src/search-results-model.js ***! - \************************************************/ -/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { - -"use strict"; -__webpack_require__.r(__webpack_exports__); -/* harmony export */ __webpack_require__.d(__webpack_exports__, { -/* harmony export */ SearchResultsModel: () => (/* binding */ SearchResultsModel) -/* harmony export */ }); -/* harmony import */ var d3__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! d3 */ "./node_modules/d3/d3.js"); -/* harmony import */ var d3__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(d3__WEBPACK_IMPORTED_MODULE_0__); -/* harmony import */ var backbone__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! backbone */ "./node_modules/backbone/backbone.js"); -/* harmony import */ var backbone__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(backbone__WEBPACK_IMPORTED_MODULE_1__); -/* harmony import */ var _spectrum_match_pride_spectrum_match__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./spectrum-match/pride-spectrum-match */ "./CLMS-model/src/spectrum-match/pride-spectrum-match.js"); -/* harmony import */ var _spectrum_match_xi2_spectrum_match__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./spectrum-match/xi2-spectrum-match */ "./CLMS-model/src/spectrum-match/xi2-spectrum-match.js"); -/* harmony import */ var _spectrum_match_old_spectrum_match__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./spectrum-match/old-spectrum-match */ "./CLMS-model/src/spectrum-match/old-spectrum-match.js"); - - - - - - -//import {Peptide} from "./peptide"; - -class SearchResultsModel extends backbone__WEBPACK_IMPORTED_MODULE_1__.Model { - - constructor(attributes, options) { - super(attributes, options); - } - - //http://stackoverflow.com/questions/19835163/backbone-model-collection-property-not-empty-on-new-model-creation - defaults() { - return { - participants: new Map(), //map - matches: [], - crosslinks: new Map(), //map - scoreExtent: null, - searches: new Map(), - decoysPresent: false, - ambiguousPresent: false, - unvalidatedPresent: false, - crosslinksPresent: false, - linearsPresent: false, // TODO - scoreSets: new Set(), - selectedScoreSet: null - }; - } - - //our SpectrumMatches are constructed from the rawMatches and peptides arrays in this json - parseJSON(json) { - if (json) { - const self = this; - this.set("sid", json.sid); - if (this.get("serverFlavour") === "PRIDE") { - //modifications - // short term hack - index mod names by accession - const modificationNames = new Map(); - // for (let mod of json.modifications){ - // modificationNames.set(mod.accession, mod.mod_name); - // } - this.set("modificationNames", modificationNames); - this.set("primaryScore", {score_name:"Match Score"}); - } else if (this.get("serverFlavour") === "XI2") { - this.set("decoysPresent", true); - this.set("primaryScore", json.primary_score); - } else if (this.get("serverFlavour") === "XIVIEW.ORG") { - this.set("primaryScore", {score_name:"Match Score"}); - //modifications - var modifications = []; - var modCount = json.modifications.length; - for (var m = 0; m < modCount; m++) { - var mod = json.modifications[m]; - modifications.push({ - aminoAcids: mod.residues.split(""), - id: mod.mod_name, - mass: mod.mass - }); - } - this.set("modifications", modifications); - } - - //search meta data - const searches = new Map(); - for (let propertyName in json.searches) { - const search = json.searches[propertyName]; - searches.set(propertyName, search); - } - this.set("searches", searches); - - const getResiduesFromEnzymeDescription = function (regexMatch, residueSet) { - if (regexMatch && regexMatch.length > 1) { - const resArray = regexMatch[1].split(","); - const resCount = resArray.length; - for (let r = 0; r < resCount; r++) { - residueSet.add({ - aa: resArray[r], - postConstraint: regexMatch[2] ? regexMatch[2].split(",") : null - }); - } - } - }; - - //enzyme specificity - // TODO _ seems like theres a duplication problem here if multiple searches are aggregated - - //eliminate duplication first - // const enzymeDescriptions = new Set(); - // for (let search of searches.values()) { - // for (let enzyme of search.enzymes) { - // enzymeDescriptions.add(enzyme.description); - // } - // } - // - // const postAaSet = new Set(); - // const aaConstrainedCTermSet = new Set(); - // const aaConstrainedNTermSet = new Set(); - // - // for (let enzymeDescription of enzymeDescriptions) { - // const postAARegex = /PostAAConstrainedDigestion:DIGESTED:(.*?);ConstrainingAminoAcids:(.*?);/g; - // const postAAMatch = postAARegex.exec(enzymeDescription); - // getResiduesFromEnzymeDescription(postAAMatch, postAaSet); - // - // const cTermRegex = /CTERMDIGEST:(.*?);/g; - // const ctMatch = cTermRegex.exec(enzymeDescription); - // getResiduesFromEnzymeDescription(ctMatch, aaConstrainedCTermSet); - // - // const nTermRegex = /NTERMDIGEST:(.*?);/g; - // const ntMatch = nTermRegex.exec(enzymeDescription); - // getResiduesFromEnzymeDescription(ntMatch, aaConstrainedNTermSet); - // } - // - // const addEnzymeSpecificityResidues = function (residueSet, type) { - // const resArray = Array.from(residueSet.values()); - // const resCount = resArray.length; - // for (let r = 0; r < resCount; r++) { - // enzymeSpecificity.push({ - // aa: resArray[r].aa, - // type: type, - // postConstraint: resArray[r].postConstraint - // }); - // } - // }; - - const enzymeSpecificity = []; - // addEnzymeSpecificityResidues(postAaSet, "DIGESTIBLE"); //"Post AA constrained"); - // addEnzymeSpecificityResidues(aaConstrainedCTermSet, "DIGESTIBLE"); // "AA constrained c-term"); - // addEnzymeSpecificityResidues(aaConstrainedNTermSet, "DIGESTIBLE"); // "AA constrained n-term"); - this.set("enzymeSpecificity", enzymeSpecificity); - - //crosslink specificity - /*var linkableResSet = new Set(); - for (var s = 0; s < searchCount; s++) { - var search = searchArray[s]; - var crosslinkers = search.crosslinkers || []; - var crosslinkerCount = crosslinkers.length; - for (var cl = 0; cl < crosslinkerCount; cl++) { - var crosslinkerDescription = crosslinkers[cl].description; - var linkedAARegex = /LINKEDAMINOACIDS:(.*?)(?:;|$)/g; - var result = null; - while ((result = linkedAARegex.exec(crosslinkerDescription)) !== null) { - var resArray = result[1].split(','); - var resCount = resArray.length; - for (var r = 0; r < resCount; r++) { - var resRegex = /([A-Z])(.*)?/ - var resMatch = resRegex.exec(resArray[r]); - if (resMatch) { - linkableResSet.add(resMatch[1]); - } - } - } - } - } - this.set("crosslinkerSpecificity", CLMS.arrayFromMapValues(linkableResSet));*/ - - const linkableResSets = {}; - for (let search of searches.values()) { - const crosslinkers = search.crosslinkers || []; - - crosslinkers.forEach(function (crosslinker) { - const crosslinkerDescription = crosslinker.description; - const crosslinkerName = crosslinker.name; - const linkedAARegex = /LINKEDAMINOACIDS:(.*?)(?:;|$)/g; // capture both sets if > 1 set - // //console.log("cld", crosslinkerDescription); - let resSet = linkableResSets[crosslinkerName]; - - if (!resSet) { - resSet = { - searches: new Set(), - linkables: [], - name: crosslinkerName, - id: +crosslinker.id - }; - linkableResSets[crosslinkerName] = resSet; - } - resSet.searches.add(search.id); - - let result = null; - let i = 0; - while ((result = linkedAARegex.exec(crosslinkerDescription)) !== null) { - if (!resSet.linkables[i]) { - resSet.linkables[i] = new Set(); - } - - const resArray = result[1].split(","); - resArray.forEach(function (res) { - const resRegex = /(cterm|nterm|[A-Z])(.*)?/i; - const resMatch = resRegex.exec(res); - if (resMatch) { - resSet.linkables[i].add(resMatch[1].toUpperCase()); - } - }); - i++; - } - - if (i === 0) { - resSet.linkables.push(new Set(["*"])); // in case non-covalent - } - - resSet.heterobi = resSet.heterobi || (i > 1); - }); - } - - //console.log("CROSS", linkableResSets); - this.set("crosslinkerSpecificity", linkableResSets); - - //saved config should end up including filter settings not just xiNET layout - this.set("xiNETLayout", json.xiNETLayout); - const spectrumSources = new Map(); - if (this.get("serverFlavour") === "XI2") { - //spectrum sources - let specSource; - for (let propertyName in json.spectrumSources) { - specSource = json.spectrumSources[propertyName]; - spectrumSources.set(+specSource.id, specSource.name); - } - - //peak list files - const peakListFiles = new Map(); - let plFile; - for (let propertyName in json.peakListFiles) { - plFile = json.peakListFiles[propertyName]; - peakListFiles.set(+plFile.id, plFile.name); - } - this.set("peakListFiles", peakListFiles); - } else if (this.get("serverFlavour") === "XIVIEW.ORG") { - //spectrum sources - var specSource; - var specCount = json.spectra.length; - for (var sp = 0; sp < specCount; sp++) { - specSource = json.spectra[sp]; - spectrumSources.set(specSource.up_id + "_" + specSource.id, specSource); - } - } - this.set("spectrumSources", spectrumSources); - - const participants = this.get("participants"); - const peptides = new Map(); - if (this.get("serverFlavour") === "PRIDE") { - if (!this.isAggregatedData()) { - if (json.proteins) { - for (let participant of json.proteins) { - this.initProtein(participant, json); - participants.set(participant.id, participant); - } - } - //peptides - if (json.peptides) { - for (let peptide of json.peptides) { - SearchResultsModel.commonRegexes.notUpperCase.lastIndex = 0; - peptide.sequence = peptide.base_seq;//seq_mods.replace(SearchResultsModel.commonRegexes.notUpperCase, ""); - peptides.set(peptide.u_id + "_" + peptide.id, peptide); // concat upload_id and peptide.id - for (var p = 0; p < peptide.prt.length; p++) { - if (peptide.is_decoy[p]) { - const protein = participants.get(peptide.prt[p]); - if (!protein) { - console.error("Protein not found for peptide (not aggregated data)", peptide, peptide.prt[p]); - } - protein.is_decoy = true; - this.set("decoysPresent", true); - } - } - } - } - } else { - var tempParticipants = new Map(); - if (json.proteins) { - for (let participant of json.proteins) { - this.initProtein(participant, json); - tempParticipants.set(participant.id, participant); - } - } - //peptides - if (json.peptides) { - for (let peptide of json.peptides) { - SearchResultsModel.commonRegexes.notUpperCase.lastIndex = 0; - peptide.sequence = peptide.seq_mods.replace(SearchResultsModel.commonRegexes.notUpperCase, ""); - peptides.set(peptide.u_id + "_" + peptide.id, peptide); // concat upload_id and peptide.id - - for (var p = 0; p < peptide.prt.length; p++) { - const protein = tempParticipants.get(peptide.prt[p]); - if (!protein) { - console.error("Protein not found for peptide (aggregated data)", peptide, peptide.prt[p]); - } - if (peptide.is_decoy[p]) { - const decoyId = "DECOY_" + protein.accession; - protein.is_decoy = true; - protein.id = decoyId; - // how to get prot acc after id has been changed? - peptide.prt[p] = decoyId; - this.set("decoysPresent", true); - } else { - // fix ids for target in aggregated data - protein.id = protein.accession; - peptide.prt[p] = protein.accession; - - } - - } - } - } - - for (let participant of tempParticipants.values()) { - participants.set(participant.id, participant); - } - - } - } else if (this.get("serverFlavour") === "XI2") { - - if (json.proteins) { - for (let protein of json.proteins) { - this.initProtein(protein); - participants.set(protein.id, protein); - } - } - - //peptides - if (json.peptides) { - const peptideArray = json.peptides; - const pepCount = peptideArray.length; - let peptide; - for (let pep = 0; pep < pepCount; pep++) { - SearchResultsModel.commonRegexes.notUpperCase.lastIndex = 0; - peptide = peptideArray[pep]; - peptide.sequence = peptide.seq_mods.replace(SearchResultsModel.commonRegexes.notUpperCase, ""); - peptides.set(peptide.search_id + "_" + peptide.id, peptide); - } - } - - } else if (this.get("serverFlavour") === "XIVIEW.ORG") { - var tempParticipants = new Map(); - - if (json.proteins) { - for (let participant of json.proteins) { - this.initProtein(participant, json); - tempParticipants.set(participant.id, participant); - } - } - //peptides - if (json.peptides) { - for (let peptide of json.peptides) { - - SearchResultsModel.commonRegexes.notUpperCase.lastIndex = 0; - peptide.sequence = peptide.seq_mods.replace(SearchResultsModel.commonRegexes.notUpperCase, ""); - peptides.set(peptide.u_id + "_" + peptide.id, peptide); // concat upload_id and peptide.id - - for (var p = 0; p < peptide.prt.length; p++) { - const protein = tempParticipants.get(peptide.prt[p]); - if (!protein) { - console.error("Protein not found for peptide (aggregated data)", peptide, peptide.prt[p]); - } - if (peptide.is_decoy[p]) { - const decoyId = "DECOY_" + protein.accession; - protein.is_decoy = true; - protein.id = decoyId; - // how to get prot acc after id has been changed? - peptide.prt[p] = decoyId; - this.set("decoysPresent", true); - } else { - // fix ids for target in aggregated data - protein.id = protein.accession; - peptide.prt[p] = protein.accession; - - } - - } - } - } - - for (let participant of tempParticipants.values()) { - participants.set(participant.id, participant); - } - } - - this.initDecoyLookup(); - - const crosslinks = this.get("crosslinks"); - - let minScore = undefined; - let maxScore = undefined; - - // moved from modelUtils 05/08/19 - // Connect searches to proteins, and add the protein set as a property of a search in the clmsModel, MJG 17/05/17 - var searchMap = this.getProteinSearchMap(json.peptides, json.matches); - this.get("searches").forEach(function (value, key) { - value.participantIDSet = searchMap[key]; - }); - - if (json.matches) { - var matches = this.get("matches"); - - var l = json.matches.length; - for (var i = 0; i < l; i++) { - let match; - if (this.get("serverFlavour") === "PRIDE") { - match = new _spectrum_match_pride_spectrum_match__WEBPACK_IMPORTED_MODULE_2__.PrideSpectrumMatch(this, participants, crosslinks, peptides, json.matches[i]); - } else if (this.get("serverFlavour") === "XI2") { - match = new _spectrum_match_xi2_spectrum_match__WEBPACK_IMPORTED_MODULE_3__.Xi2SpectrumMatch(this, participants, crosslinks, peptides, json.matches[i]); - } else if (this.get("serverFlavour") === "XIVIEW.ORG") { - match = new _spectrum_match_old_spectrum_match__WEBPACK_IMPORTED_MODULE_4__.OldSpectrumMatch(this, participants, crosslinks, peptides, json.matches[i]); - } - matches.push(match); - - if (maxScore === undefined || match.score() > maxScore) { - maxScore = match.score(); - } else if (minScore === undefined || match.score() < minScore) { - minScore = match.score(); - } - } - } - - console.log("score sets:", this.get("scoreSets")); - - this.set("minScore", minScore); - this.set("maxScore", maxScore); - - const participantArray = Array.from(participants.values()); - // only count real participants towards participant count (which is used as cut-off further on) - const targetParticipantArray = participantArray.filter(function (p) { - return !p.is_decoy; - }); - - for (let participant of targetParticipantArray) { - participant.uniprot = json.interactors ? json.interactors[participant.accession.split("-")[0]] : null; - } - - window.vent.trigger("uniprotDataParsed", self); - } - - } - - // Connect searches to proteins - getProteinSearchMap(peptideArray, rawMatchArray) { - const pepMap = d3__WEBPACK_IMPORTED_MODULE_0__.map(peptideArray, function (peptide) { - return peptide.id; - }); - const searchMap = {}; - rawMatchArray = rawMatchArray || []; - rawMatchArray.forEach(function (rawMatch) { - const peptideIDs = rawMatch.pi ? rawMatch.pi : [rawMatch.pi1, rawMatch.pi2]; - peptideIDs.forEach(function (pepID) { - if (pepID) { - const prots = pepMap.get(pepID).prt; - let searchToProts = searchMap[rawMatch.primaryDataSetId]; - if (!searchToProts) { - const newSet = d3__WEBPACK_IMPORTED_MODULE_0__.set(); - searchMap[rawMatch.primaryDataSetId] = newSet; - searchToProts = newSet; - } - prots.forEach(function (prot) { - searchToProts.add(prot); - }); - } - }); - }); - return searchMap; - } - - //adds some attributes we want to protein object - initProtein(protObj, json) { - if (!protObj.crosslinks) { - protObj.crosslinks = []; - } - // check serverFlavour - if (this.get("serverFlavour") === "PRIDE") { - protObj.is_decoy = false; - } - else if (this.get("serverFlavour") === "XIVIEW.ORG") { - protObj.is_decoy = false; - var accCheck = protObj.accession.match(SearchResultsModel.commonRegexes.uniprotAccession); - if (protObj.seq_mods) { - SearchResultsModel.commonRegexes.notUpperCase.lastIndex = 0; - protObj.sequence = protObj.seq_mods.replace(SearchResultsModel.commonRegexes.notUpperCase, ""); - } else if (accCheck != null && json.interactors[protObj.accession]) { - protObj.sequence = json.interactors[protObj.accession].sequence; - } else { - protObj.sequence = ""; - } - } - protObj.size = protObj.sequence.length; - - protObj.form = 0; - - if ((!protObj.name || protObj.name.trim() === '{"","protein description"}') && protObj.accession){ - protObj.name = protObj.accession; - } - protObj.getMeta = function (metaField) { - if (arguments.length === 0) { - return this.meta; - } - return this.meta ? this.meta[metaField] : undefined; - }.bind(protObj); - - protObj.setMeta = function (metaField, value) { - if (arguments.length === 2) { - this.meta = this.meta || {}; - this.meta[metaField] = value; - } - }.bind(protObj); - } - - getDigestibleResiduesAsFeatures(participant) { - const digestibleResiduesAsFeatures = []; - - const sequence = participant.sequence; - const seqLength = sequence.length; - const specificity = this.get("enzymeSpecificity"); - - const specifCount = specificity.length; - for (let i = 0; i < specifCount; i++) { - const spec = specificity[i]; - for (let s = 0; s < seqLength; s++) { - if (sequence[s] === spec.aa) { - if (!spec.postConstraint || !sequence[s + 1] || spec.postConstraint.indexOf(sequence[s + 1]) === -1) { - digestibleResiduesAsFeatures.push({ - begin: s + 1, - end: s + 1, - name: "DIGESTIBLE", - protID: participant.id, - id: participant.id + " " + spec.type + (s + 1), - category: "AA", - type: "DIGESTIBLE" - }); - } - } - } - } - //console.log("sp:", specificity, "df:", digestibleResiduesAsFeatures); - return digestibleResiduesAsFeatures; - } - - getCrosslinkableResiduesAsFeatures(participant, reactiveGroup) { - const crosslinkableResiduesAsFeatures = []; - - const sequence = participant.sequence; - const seqLength = sequence.length; - const linkedResSets = this.get("crosslinkerSpecificity"); - - const temp = d3__WEBPACK_IMPORTED_MODULE_0__.values(linkedResSets); - for (let cl = 0; cl < temp.length; cl++) { - // resSet = {searches: new Set(), linkables: [], name: crosslinkerName}; - const crosslinkerLinkedResSet = temp[cl]; - const linkables = crosslinkerLinkedResSet.linkables; - - //for (var l = 0 ; l < linkables.length; l++) { - if (linkables[reactiveGroup - 1]) { - const linkableSet = linkables[reactiveGroup - 1]; - const linkableArr = []; - linkableSet.forEach(v => linkableArr.push(v)); - const specifCount = linkableArr.length; - for (let i = 0; i < specifCount; i++) { - const spec = linkableArr[i]; - for (let s = 0; s < seqLength; s++) { - if (sequence[s] === spec) { - crosslinkableResiduesAsFeatures.push({ - begin: s + 1, - end: s + 1, - name: "CROSSLINKABLE-" + reactiveGroup, - protID: participant.id, - id: participant.id + " Crosslinkable residue" + (s + 1) + "[group " + reactiveGroup + "]", - category: "AA", - type: "CROSSLINKABLE-" + reactiveGroup - }); - } - } - } - } - } - - console.log("reactiveGroup:", reactiveGroup, "sp:", linkedResSets, "clf:", crosslinkableResiduesAsFeatures); - return crosslinkableResiduesAsFeatures; - } - - initDecoyLookup(prefixes) { - // Make map of reverse/random decoy proteins to real proteins - prefixes = prefixes || ["REV_", "RAN_", "DECOY_", "DECOY:", "reverse_", "REV", "RAN"]; - const prots = Array.from(this.get("participants").values()); - const nameMap = d3__WEBPACK_IMPORTED_MODULE_0__.map(); - const accessionMap = d3__WEBPACK_IMPORTED_MODULE_0__.map(); - prots.forEach(function (prot) { - nameMap.set(prot.name, prot.id); - accessionMap.set(prot.accession, prot.id); - prot.targetProteinID = prot.id; // this gets overwritten for decoys in next bit, mjg - }); - - const decoys = prots.filter(function (p) { - return p.is_decoy; - }); - decoys.forEach(function (decoyProt) { - prefixes.forEach(function (pre) { - const targetProtIDByName = nameMap.get(decoyProt.name.substring(pre.length)); - if (decoyProt.accession) { - const targetProtIDByAccession = accessionMap.get(decoyProt.accession.substring(pre.length)); - if (targetProtIDByAccession) { - decoyProt.targetProteinID = targetProtIDByAccession; // mjg - } - } else if (targetProtIDByName) { - decoyProt.targetProteinID = targetProtIDByName; // mjg - } - }); - }); - - this.targetProteinCount = prots.length - decoys.length; - } - - isAggregatedData() { - return this.get("searches").size > 1; - } - - getSearchRandomId(match) { - const searchId = match.searchId; - const searchMap = this.get("searches"); - const searchData = searchMap.get(searchId); - return searchData.random_id; - } -} - -SearchResultsModel.attributeOptions = - [ - { - linkFunc: function (link) { - return [link.filteredMatches_pp.length]; - }, - unfilteredLinkFunc: function (link) { - return [link.matches_pp.length]; - }, - id: "MatchCount", - label: "Crosslink Match Count", - decimalPlaces: 0 - }, - { - linkFunc: function (link) { - return link.filteredMatches_pp.map(function (m) { - return m.match.score(); - }); - }, - unfilteredLinkFunc: function (link) { - return link.matches_pp.map(function (m) { - return m.match.score(); - }); - }, - id: "Score", - label: "Match Score", - decimalPlaces: 2, - matchLevel: true - }, - { - linkFunc: function (link) { - const scores = link.filteredMatches_pp.map(function (m) { - return m.match.score(); - }); - return [Math.max.apply(Math, scores)]; - }, - unfilteredLinkFunc: function (link) { - const scores = link.matches_pp.map(function (m) { - return m.match.score(); - }); - return [Math.max.apply(Math, scores)]; - }, - id: "Highest Score", - label: "Highest Match Score per Crosslink", - decimalPlaces: 2, - matchLevel: false - }, - { - linkFunc: function (link) { - return link.filteredMatches_pp.map(function (m) { - return m.match.precursorMZ; - }); - }, - unfilteredLinkFunc: function (link) { - return link.matches_pp.map(function (m) { - return m.match.precursorMZ; - }); - }, - id: "MZ", - label: "Match Precursor m/z", - decimalPlaces: 4, - matchLevel: true - }, - { - linkFunc: function (link) { - return link.filteredMatches_pp.map(function (m) { - return m.match.precursorCharge; - }); - }, - unfilteredLinkFunc: function (link) { - return link.matches_pp.map(function (m) { - return m.match.precursorCharge; - }); - }, - id: "Charge", - label: "Match Precursor Charge (z)", - decimalPlaces: 0, - matchLevel: true - }, - { - linkFunc: function (link) { - return link.filteredMatches_pp.map(function (m) { - return m.match.calcMass(); - }); - }, - unfilteredLinkFunc: function (link) { - return link.matches_pp.map(function (m) { - return m.match.calcMass(); - }); - }, - id: "CalcMass", - label: "Match Calculated Mass (m)", - decimalPlaces: 4, - matchLevel: true - }, - { - linkFunc: function (link) { - return link.filteredMatches_pp.map(function (m) { - return m.match.massError(); - }); - }, - unfilteredLinkFunc: function (link) { - return link.matches_pp.map(function (m) { - return m.match.massError(); - }); - }, - id: "MassError", - label: "Match Mass Error", - decimalPlaces: 4, - matchLevel: true - }, - { - linkFunc: function (link) { - return link.filteredMatches_pp.map(function (m) { - return m.match.missingPeaks(); - }); - }, - unfilteredLinkFunc: function (link) { - return link.matches_pp.map(function (m) { - return m.match.missingPeaks(); - }); - }, - id: "MissingPeaks", - label: "Missing Peaks", - decimalPlaces: 0, - matchLevel: true - }, - { - linkFunc: function (link) { - return link.filteredMatches_pp.map(function (m) { - return Math.min(m.pepPos[0].length, m.pepPos[1].length); - }); - }, - unfilteredLinkFunc: function (link) { - return link.matches_pp.map(function (m) { - return Math.min(m.pepPos[0].length, m.pepPos[1].length); - }); - }, - id: "SmallPeptideLen", - label: "Match Smaller Peptide Length (AA)", - decimalPlaces: 0, - matchLevel: true - }, - { - linkFunc: function (link) { - return link.filteredMatches_pp.map(function (m) { - const p = m.match.precursor_intensity; - return isNaN(p) ? undefined : p; - }); - }, - unfilteredLinkFunc: function (link) { - return link.matches_pp.map(function (m) { - const p = m.match.precursor_intensity; - return isNaN(p) ? undefined : p; - }); - }, - id: "PrecursorIntensity", - label: "Match Precursor Intensity", - decimalPlaces: 0, - matchLevel: true, - valueFormat: d3__WEBPACK_IMPORTED_MODULE_0__.format(".1e"), - logAxis: true, - logStart: 1000 - }, - { - linkFunc: function (link) { - return link.filteredMatches_pp.map(function (m) { - return m.match.elution_time_start; - }); - }, - unfilteredLinkFunc: function (link) { - return link.matches_pp.map(function (m) { - return m.match.elution_time_start; - }); - }, - id: "ElutionTimeStart", - label: "Elution Time Start", - decimalPlaces: 2, - matchLevel: true - }, - { - linkFunc: function (link) { - return link.filteredMatches_pp.map(function (m) { - return m.match.elution_time_end; - }); - }, - unfilteredLinkFunc: function (link) { - return link.matches_pp.map(function (m) { - return m.match.elution_time_end; - }); - }, - id: "ElutionTimeEnd", - label: "Elution Time End", - decimalPlaces: 2, - matchLevel: true - }, - { - //watch out for the 'this' reference - linkFunc: function (link) { - //return link.isLinearLink() ? [] : [this.model.getSingleCrosslinkDistance(link, null, null, option)]; - return link.isLinearLink() ? [] : [link.getMeta("distance")]; - }, - unfilteredLinkFunc: function (link) { - //return link.isLinearLink() ? [] : [this.model.getSingleCrosslinkDistance(link, null, null, option)]; - return link.isLinearLink() ? [] : [link.getMeta("distance")]; - }, - id: "Distance", - label: "Crosslink Cα-Cα Distance (Å)", - decimalPlaces: 2, - maxVal: 90, - }, - { - linkFunc: function (link) { - return link.filteredMatches_pp.map(function (m) { - return m.match.experimentalMissedCleavageCount(); - }); - }, - unfilteredLinkFunc: function (link) { - return link.matches_pp.map(function (m) { - return m.match.experimentalMissedCleavageCount(); - }); - }, - id: "ExpMissedCleavages", - label: "Experimental Max. Missed Cleavages", - decimalPlaces: 0, - matchLevel: true - }, - { - linkFunc: function (link) { - return link.filteredMatches_pp.map(function (m) { - return m.match.searchMissedCleavageCount(); - }); - }, - unfilteredLinkFunc: function (link) { - return link.matches_pp.map(function (m) { - return m.match.searchMissedCleavageCount(); - }); - }, - id: "SearchMissedCleavages", - label: "Search Max. Missed Cleavages", - decimalPlaces: 0, - matchLevel: true - }, - { - linkFunc: function (link) { - return link.filteredMatches_pp.map(function (m) { - return m.match.modificationCount(); - }); - }, - unfilteredLinkFunc: function (link) { - return link.matches_pp.map(function (m) { - return m.match.modificationCount(); - }); - }, - id: "ModificationCount", - label: "Modification Count", - decimalPlaces: 0, - matchLevel: true - }, - ]; - -SearchResultsModel.commonRegexes = { - uniprotAccession: /[OPQ][0-9][A-Z0-9]{3}[0-9]|[A-NR-Z][0-9]([A-Z][A-Z0-9]{2}[0-9]){1,2}/, - notUpperCase: /[^A-Z]/g, - decoyNames: /(REV_)|(RAN_)|(DECOY_)|(DECOY:)|(reverse_)/, -}; - - -/***/ }), - -/***/ "./CLMS-model/src/spectrum-match/old-spectrum-match.js": -/*!*************************************************************!*\ - !*** ./CLMS-model/src/spectrum-match/old-spectrum-match.js ***! - \*************************************************************/ -/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { - -"use strict"; -__webpack_require__.r(__webpack_exports__); -/* harmony export */ __webpack_require__.d(__webpack_exports__, { -/* harmony export */ OldSpectrumMatch: () => (/* binding */ OldSpectrumMatch) -/* harmony export */ }); -/* harmony import */ var _crosslink__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../crosslink */ "./CLMS-model/src/crosslink.js"); - - -class OldSpectrumMatch { - constructor(containingModel, participants, crosslinks, peptides, identification) { - - this.containingModel = containingModel; //containing BB model - this.spectrumId = +identification.sp; - this.searchId = identification.si.toString(); - this.primaryDataSetId = this.si; - this.precursor_intensity = null; - this.id = this.searchId + "_" + identification.id; - this.precursorMZ = +identification.e_mz; // experimental MZ, accessor for this att is called expMZ() - this.calc_mz = +identification.c_mz; - - this._scores = identification.sc; - var scoreSets = Object.keys(this._scores); - var scoreSetCount = scoreSets.length; - for (var s = 0; s < scoreSetCount; s++) { - var scoreSet = scoreSets[s]; - this.containingModel.get("scoreSets").add(scoreSet); - } - - this.passThreshold = (identification.pass == "t"); - if (identification.ions) { - var ionTypes = identification.ions.split(";"); - var ionTypeCount = ionTypes.length; - var ions = []; - for (var it = 0; it < ionTypeCount; it++) { - var ionType = ionTypes[it]; - ions.push({"type": (ionType.charAt(0).toUpperCase() + ionType.slice(1) + "Ion")}); - } - this.ions = ions; - } - - this.spectrum = this.containingModel.get("spectrumSources").get(this.searchId + "_" + this.spectrumId); - if (this.spectrum) { - this.scanNumber = +this.spectrum.sn; - } - - this.precursorCharge = +identification.pc_c; - // if (this.precursorCharge == -1) { //dodgy? - // this.precursorCharge = undefined; - // } - - this.matchedPeptides = []; - this.matchedPeptides[0] = peptides.get(this.searchId + "_" + identification.pi1); - if (!this.matchedPeptides[0]) { - alert("peptide error (missing peptide evidence?) for:" + identification.pi1); - } else { - if (this.matchedPeptides[0].is_decoy.indexOf("1") != -1) { - this.is_decoy = true; - this.containingModel.set("decoysPresent", true); - } - } - // following will be inadequate for trimeric and higher order cross-links - if (identification.pi2) { - this.matchedPeptides[1] = peptides.get(this.searchId + "_" + identification.pi2); - if (!this.matchedPeptides[1]) { - alert("peptide error (missing peptide evidence?) for:" + +identification.pi2); - } else if (this.matchedPeptides[1].is_decoy.indexOf("1") != -1) { - this.is_decoy = true; - this.containingModel.set("decoysPresent", true); - } - } - //if the match is ambiguous it will relate to many crosslinks - this.crosslinks = []; - this.linkPos1 = +this.matchedPeptides[0].linkSite; - if (this.matchedPeptides[1]) { - this.linkPos2 = this.matchedPeptides[1].linkSite; - } - - if (this.linkPos1 == -1) { - //its a linear - this.containingModel.set("linearsPresent", true); - for (var i = 0; i < this.matchedPeptides[0].prt.length; i++) { - p1ID = this.matchedPeptides[0].prt[i]; - this.associateWithLink(participants, crosslinks, p1ID); - } - if (this.matchedPeptides[1]) { - for (var i = 0; i < this.matchedPeptides[1].prt.length; i++) { - p1ID = this.matchedPeptides[1].prt[i]; - this.associateWithLink(participants, crosslinks, p1ID); - } - } - return; - } - - this.couldBelongToBetweenLink = false; - this.couldBelongToSelfLink = false; - - var self = this; - - // the protein IDs and residue numers we eventually want to get:- - var p1ID, p2ID, res1, res2; - //used along the way:- - var iProt, jProt; - - //loop to produce all alternative linkage site combinations - //(position1 count * position2 count alternative) - if (this.matchedPeptides[1]) { - for (var i = 0; i < this.matchedPeptides[0].pos.length; i++) { - for (var j = 0; j < this.matchedPeptides[1].pos.length; j++) { - - if (i > 0 || j > 0) { - this.containingModel.set("ambiguousPresent", true); - } - - //some files are not puting in duplicate protein ids in ambig links - //in this case use last one - // if (i < this.matchedPeptides[0].prt.length) { - p1ID = this.matchedPeptides[0].prt[i]; - // } else { - // p1ID = this.matchedPeptides[0].prt[this.matchedPeptides[0].prt.length - 1]; - // } - // if (j < this.matchedPeptides[1].prt.length) { - p2ID = this.matchedPeptides[1].prt[j]; - // } else { - // p2ID = this.matchedPeptides[1].prt[this.matchedPeptides[1].prt.length - 1]; - // } - - // * residue numbering starts at 1 * - res1 = +this.matchedPeptides[0].pos[i] - 1 + this.linkPos1; - res2 = +this.matchedPeptides[1].pos[j] - 1 + this.linkPos2; - - this.associateWithLink(participants, crosslinks, p1ID, p2ID, res1, res2, this.matchedPeptides[0].pos[i] - 0, this.matchedPeptides[0].sequence.length, this.matchedPeptides[1].pos[j], this.matchedPeptides[1].sequence.length); - } - } - } else { - for (var i = 0; i < this.matchedPeptides[0].pos.length; i++) { - if (i > 0) { - this.containingModel.set("ambiguousPresent", true); - } - p1ID = this.matchedPeptides[0].prt[i]; - // * residue numbering starts at 1 * - res1 = +this.matchedPeptides[0].pos[i] - 1 + this.linkPos1; - this.associateWithLink(participants, crosslinks, p1ID, null, res1, null, this.matchedPeptides[0].pos[i] - 0, this.matchedPeptides[0].sequence.length, null, null); - } - } - //identify homodimers: if peptides overlap its a homodimer - this.confirmedHomomultimer = false; - this.overlap = []; - if (this.isAmbig() == false && p1ID == p2ID) { //todo: fix potential problem here regarding ambiguous homo-multimer link - - if (this.matchedPeptides[0].sequence && this.matchedPeptides[1].sequence) { - - var pep1length = this.matchedPeptides[0].sequence.length; - var pep2length = this.matchedPeptides[1].sequence.length; - var pep1_start = +this.matchedPeptides[0].pos[0]; - var pep2_start = +this.matchedPeptides[1].pos[0]; - var pep1_end = pep1_start + (pep1length - 1); - var pep2_end = pep2_start + (pep2length - 1); - if (pep1_start >= pep2_start && pep1_start <= pep2_end) { - this.confirmedHomomultimer = true; - this.overlap[0] = pep1_start - 1; - if (pep1_end < pep2_end) { - this.overlap[1] = pep1_end; - } else { - this.overlap[1] = pep2_end; - } - } else if (pep2_start >= pep1_start && pep2_start <= pep1_end) { - this.confirmedHomomultimer = true; - this.overlap[0] = pep2_start - 1; - if (pep2_end < pep1_end) { - this.overlap[1] = pep2_end; - } else { - this.overlap[1] = pep1_end; - } - } - } else if (res1 === res2) { - this.confirmedHomomultimer = true; - this.overlap[0] = res1 - 1; - this.overlap[1] = res2; - } - } - } - - associateWithLink(proteins, crosslinks, p1ID, p2ID, res1, res2, //following params may be null :- - pep1_start, pep1_length, pep2_start, pep2_length) { - - // we don't want two different ID's, e.g. one thats "33-66" and one thats "66-33" - //following puts lower protein_ID first in link_ID - - //todo: this end swapping thing, its a possible source of confusion - - let fromProt, toProt; - - if (!p2ID || p2ID == "" || p2ID == "-" || p2ID == "n/a") { //its a linear peptide (no crosslinker of any product type)) - this.containingModel.set("linearsPresent", true); - fromProt = proteins.get(p1ID); - if (!fromProt) { - alert("FAIL: not protein with ID " + p1ID); - } - } else if (p1ID <= p2ID) { - fromProt = proteins.get(p1ID); - toProt = proteins.get(p2ID); - if (!fromProt) { - alert("FAIL: not protein with ID " + p1ID); - } - if (!toProt) { - alert("FAIL: not protein with ID " + p2ID); - } - } else { - fromProt = proteins.get(p2ID); - toProt = proteins.get(p1ID); - if (!fromProt) { - alert("FAIL: not protein with ID " + p2ID); - } - if (!toProt) { - alert("FAIL: not protein with ID " + p1ID); - } - } - - if (fromProt && toProt && fromProt.targetProteinID === toProt.targetProteinID) { - this.couldBelongToSelfLink = true; - } else if (!this.isMonoLink()) { - this.couldBelongToBetweenLink = true; - } - - // again, order id string by prot id or by residue if self-link - let endsReversedInResLinkId = false; - let crosslinkID; - if (this.isNotCrosslinked()) { - crosslinkID = p1ID + "_linears"; - } else if (p1ID === p2ID || p2ID === null) { - if ((res1 - 0) < (res2 - 0) || res2 === null) { - crosslinkID = p1ID + "_" + res1 + "-" + p2ID + "_" + res2; - } else { - crosslinkID = p2ID + "_" + res2 + "-" + p1ID + "_" + res1; - endsReversedInResLinkId = true; - } - } else if (p1ID < p2ID) { - crosslinkID = p1ID + "_" + res1 + "-" + p2ID + "_" + res2; - } else { - crosslinkID = p2ID + "_" + res2 + "-" + p1ID + "_" + res1; - endsReversedInResLinkId = true; - } - - //get or create residue link - let resLink = crosslinks.get(crosslinkID); - if (typeof resLink == "undefined") { - //to and from proteins were already swapped over above - - //WATCH OUT - residues need to be in correct order - if (!p2ID) { - resLink = new _crosslink__WEBPACK_IMPORTED_MODULE_0__.Crosslink(crosslinkID, fromProt, - res1, null, null, this.containingModel); - } else if (p1ID === p2ID) { - if ((res1 - 0) < (res2 - 0)) { - resLink = new _crosslink__WEBPACK_IMPORTED_MODULE_0__.Crosslink(crosslinkID, fromProt, res1, toProt, res2, this.containingModel); - } else { - resLink = new _crosslink__WEBPACK_IMPORTED_MODULE_0__.Crosslink(crosslinkID, fromProt, res2, toProt, res1, this.containingModel); - } - } else if (p1ID === fromProt.id) { - resLink = new _crosslink__WEBPACK_IMPORTED_MODULE_0__.Crosslink(crosslinkID, fromProt, res1, toProt, res2, this.containingModel); - } else { - //WATCH OUT - residues need to be in correct oprder - resLink = new _crosslink__WEBPACK_IMPORTED_MODULE_0__.Crosslink(crosslinkID, fromProt, res2, toProt, res1, this.containingModel); - } - crosslinks.set(crosslinkID, resLink); - - fromProt.crosslinks.push(resLink); - if (toProt && (toProt !== fromProt)) { - toProt.crosslinks.push(resLink); - } - } - - const peptidePositions = []; - if (endsReversedInResLinkId === false) { - peptidePositions.push({ - start: pep1_start, - length: pep1_length - }); - peptidePositions.push({ - start: pep2_start, - length: pep2_length - }); - } else { - peptidePositions.push({ - start: pep2_start, - length: pep2_length - }); - peptidePositions.push({ - start: pep1_start, - length: pep1_length - }); - } - resLink.matches_pp.push({ - match: this, - pepPos: peptidePositions - }); - this.crosslinks.push(resLink); - } - - isAmbig() { - return this.matchedPeptides[0].pos.length > 1 || - (this.matchedPeptides[1] && this.matchedPeptides[1].pos.length > 1); - } - - isDecoy() { - if (this.is_decoy) { - return this.is_decoy; - } else { - //its from csv not database, for simplicity lets just look at first crosslink //todo - look at again - return this.crosslinks[0].isDecoyLink(); - } - } - - isNotCrosslinked() { - return this.linkPos1 === -1; - } - - isMonoLink() { - return this.linkPos1 !== -1 && (this.matchedPeptides.length === 1 || this.linkPos2 == -1 || this.matchedPeptides[1].pos[0] == -1); - } - - runName() { - if (this.spectrum) { - return this.spectrum.file; - } - } - - peakListFileName() { - if (this.spectrum) { - return this.spectrum.file; - } - } - - group() { - var group = this.containingModel.get("searches").get(this.searchId).group; - return group; - } - - expMZ() { - return this.precursorMZ; - } - - - expMass() { - return this.precursorMZ * this.precursorCharge - (this.precursorCharge * OldSpectrumMatch.protonMass); - } - - calcMZ() { - return this.calc_mz;// (this.calc_mass + (this.precursorCharge * SpectrumMatch.protonMass)) / this.precursorCharge; - } - - calcMass() { - return (this.precursorCharge * this.calc_mz) - (this.precursorCharge * OldSpectrumMatch.protonMass); //this.calc_mass; - } - - massError() { - return ((this.expMass() - this.calcMass()) / this.calcMass()) * 1000000; - } - - missingPeaks() { - const errorMZ = this.expMZ() - this.calcMZ(); - const errorM = errorMZ * this.precursorCharge; - //how many peaks assumed missing/miss-assigned - return Math.round(errorM / OldSpectrumMatch.C13_MASS_DIFFERENCE); - } - - ionTypes() { - return this.ions; - } - - ionTypesString() { - return JSON.stringify(this.ionTypes()); - } - - crosslinkerModMass() { - var clModMass = +this.matchedPeptides[0].clModMass; - if (this.matchedPeptides[1]) { - clModMass = clModMass + (+this.matchedPeptides[1].clModMass); - } - return clModMass; - } - - fragmentTolerance() { - if (this.spectrum) { - var fragTolArr = this.spectrum.ft.split(" "); - return { - "tolerance": fragTolArr[0], - "unit": fragTolArr[1] - }; - } - } - - fragmentToleranceString() { - var fragTol = this.fragmentTolerance(); - if (fragTol) { - return fragTol.tolerance + " " + fragTol.unit; - } - } - - score() { - //return this._scores.score; - var scoreSets = this.containingModel.get("scoreSets"); - //if (scoreSets.size == 1) { - var scoreSet = scoreSets.keys().next().value; - var s = this._scores[scoreSet]; - //console.log("!", s); - return s; - //} - } - - modificationCount() { - function peptideModCount(peptide) { - let count = 0; - const sequence = peptide.seq_mods; - const pepLen = sequence.length; - for (let i = 0; i < pepLen - 1; i++) { - const a = sequence[i]; - const b = sequence[i + 1]; - if ((a >= "A" && a <= "Z") && (b < "A" || b > "Z")) count++; - } - return count; - } - - const modCount1 = peptideModCount(this.matchedPeptides[0]); - if (this.matchedPeptides[1]) { - const modCount2 = peptideModCount(this.matchedPeptides[1]); - if (modCount2 > modCount1) { - return modCount2; - } - } - return modCount1; - } -} - -OldSpectrumMatch.protonMass = 1.007276466879; -OldSpectrumMatch.C13_MASS_DIFFERENCE = 1.0033548; - - -/***/ }), - -/***/ "./CLMS-model/src/spectrum-match/pride-spectrum-match.js": -/*!***************************************************************!*\ - !*** ./CLMS-model/src/spectrum-match/pride-spectrum-match.js ***! - \***************************************************************/ -/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { - -"use strict"; -__webpack_require__.r(__webpack_exports__); -/* harmony export */ __webpack_require__.d(__webpack_exports__, { -/* harmony export */ PrideSpectrumMatch: () => (/* binding */ PrideSpectrumMatch) -/* harmony export */ }); -/* harmony import */ var _crosslink__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../crosslink */ "./CLMS-model/src/crosslink.js"); -/* harmony import */ var _spectrum_match__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./spectrum-match */ "./CLMS-model/src/spectrum-match/spectrum-match.js"); - - - -class PrideSpectrumMatch extends _spectrum_match__WEBPACK_IMPORTED_MODULE_1__.SpectrumMatch{ - constructor(containingModel, participants, crosslinks, peptides, identification) { - super(); - this.containingModel = containingModel; //containing BB model - this.identification = identification; - this.primaryDataSetId = identification.si; - this.precursor_intensity = null; - this.spectrumId = identification.sp; - this.searchId = identification.si.toString(); - this.id = this.searchId + "_" + identification.id; - this.precursorMZ = +identification.pc_mz; // experimental MZ, accessor for this att is called expMZ() - this.calc_mz = +identification.c_mz; - this._scores = identification.sc; - var scoreSets = Object.keys(this._scores); - var scoreSetCount = scoreSets.length; - for (var s = 0; s < scoreSetCount; s++) { - var scoreSet = scoreSets[s]; - this.containingModel.get("scoreSets").add(scoreSet); - } - - this.passThreshold = !!identification.pass; - if (identification.ions) { - var ionTypes = identification.ions.split(";"); - var ionTypeCount = ionTypes.length; - var ions = []; - for (var it = 0; it < ionTypeCount; it++) { - var ionType = ionTypes[it]; - ions.push({"type": (ionType.charAt(0).toUpperCase() + ionType.slice(1) + "Ion")}); - } - this.ions = ions; - } else { - this.ions = [{type:"bIon"}, {type:"yIon"}]; - } - - this.spectrum = this.containingModel.get("spectrumSources").get(this.searchId + "_" + this.spectrumId); - - this.precursorCharge = +identification.pc_c; - if (this.precursorCharge === -1) { - this.precursorCharge = undefined; - } - - this.matchedPeptides = []; - this.matchedPeptides[0] = peptides.get(this.searchId + "_" + identification.pi1); - if (!this.matchedPeptides[0]) { - alert("peptide error (missing peptide evidence?) for:" + identification.pi1); - } else { - if (this.matchedPeptides[0].is_decoy.indexOf("1") != -1) { - this.is_decoy = true; - this.containingModel.set("decoysPresent", true); - } - } - // following will be inadequate for trimeric and higher order cross-links - if (identification.pi2) { - this.matchedPeptides[1] = peptides.get(this.searchId + "_" + identification.pi2); - if (!this.matchedPeptides[1]) { - alert("peptide error (missing peptide evidence?) for:" + +identification.pi2); - } else if (this.matchedPeptides[1].is_decoy.indexOf("1") != -1) { - this.is_decoy = true; - this.containingModel.set("decoysPresent", true); - } - } - //if the match is ambiguous it will relate to many crosslinks - this.crosslinks = []; - this.linkPos1 = +this.matchedPeptides[0].linkSite; - if (this.matchedPeptides[1]) { - this.linkPos2 = this.matchedPeptides[1].linkSite; - } - - // the protein IDs and residue numers we eventually want to get:- - let p1ID, p2ID, res1, res2; - - if (this.isNotCrosslinked()) { - //its a linear - this.containingModel.set("linearsPresent", true); - for (let i = 0; i < this.matchedPeptides[0].prt.length; i++) { - p1ID = this.matchedPeptides[0].prt[i]; - this.associateWithLink(participants, crosslinks, p1ID); - } - if (this.matchedPeptides[1]) { - for (let i = 0; i < this.matchedPeptides[1].prt.length; i++) { - p1ID = this.matchedPeptides[1].prt[i]; - this.associateWithLink(participants, crosslinks, p1ID); - } - } - return; - } - - this.couldBelongToBetweenLink = false; - this.couldBelongToSelfLink = false; - - //loop to produce all alternative linkage site combinations - //(position1 count * position2 count alternative) - for (let i = 0; i < this.matchedPeptides[0].pos.length; i++) { - for (let j = 0; j < this.matchedPeptides[1].pos.length; j++) { - - if (i > 0 || j > 0) { - this.containingModel.set("ambiguousPresent", true); - } - - //some files (must be csv) are not puting in duplicate protein ids in ambig links - //in this case use last one - if (i < this.matchedPeptides[0].prt.length) { - p1ID = this.matchedPeptides[0].prt[i]; - } else { - p1ID = this.matchedPeptides[0].prt[this.matchedPeptides[0].prt.length - 1]; - } - if (j < this.matchedPeptides[1].prt.length) { - p2ID = this.matchedPeptides[1].prt[j]; - } else { - p2ID = this.matchedPeptides[1].prt[this.matchedPeptides[1].prt.length - 1]; - } - - // * residue numbering starts at 1 * - res1 = +this.matchedPeptides[0].pos[i] - 1 + this.linkPos1; - res2 = +this.matchedPeptides[1].pos[j] - 1 + this.linkPos2; - - this.associateWithLink(participants, crosslinks, p1ID, p2ID, res1, res2, this.matchedPeptides[0].pos[i] - 0, this.matchedPeptides[0].sequence.length, this.matchedPeptides[1].pos[j], this.matchedPeptides[1].sequence.length); - } - } - - //identify homodimers: if peptides overlap its a homodimer - this.confirmedHomomultimer = false; - this.overlap = []; - if (this.isAmbig() === false && p1ID === p2ID) { //todo: potential problem re ambiguous homo-multimer link (compare current behaviour to xiNET paper product type fig) - - if (this.matchedPeptides[0].sequence && this.matchedPeptides[1].sequence) { - - const pep1length = this.matchedPeptides[0].sequence.length; - const pep2length = this.matchedPeptides[1].sequence.length; - const pep1_start = +this.matchedPeptides[0].pos[0]; - const pep2_start = +this.matchedPeptides[1].pos[0]; - const pep1_end = pep1_start + (pep1length - 1); - const pep2_end = pep2_start + (pep2length - 1); - if (pep1_start >= pep2_start && pep1_start <= pep2_end) { - this.confirmedHomomultimer = true; - this.overlap[0] = pep1_start - 1; - if (pep1_end < pep2_end) { - this.overlap[1] = pep1_end; - } else { - this.overlap[1] = pep2_end; - } - } else if (pep2_start >= pep1_start && pep2_start <= pep1_end) { - this.confirmedHomomultimer = true; - this.overlap[0] = pep2_start - 1; - if (pep2_end < pep1_end) { - this.overlap[1] = pep2_end; - } else { - this.overlap[1] = pep1_end; - } - } - } else if (res1 === res2) { - this.confirmedHomomultimer = true; - this.overlap[0] = res1 - 1; - this.overlap[1] = res2; - } - } - } - - isNotCrosslinked() { - return this.linkPos1 === -1; - } - - isMonoLink() { - return this.linkPos1 !== -1 && (this.matchedPeptides.length === 1 || this.linkPos2 == -1 || this.matchedPeptides[1].pos[0] == -1); - } - - runName() { - if (this.spectrum) { - return this.spectrum.file; - } - } - - peakListFileName() { - if (this.spectrum) { - return this.spectrum.file; - } - } - - group() { - return -1; // temp - var group = this.containingModel.get("searches").get(this.searchId).group; - return group; - } - - expMZ() { - return this.precursorMZ; - } - - - expMass() { - return this.precursorMZ * this.precursorCharge - (this.precursorCharge * PrideSpectrumMatch.protonMass); - } - - calcMZ() { - return this.calc_mz;// (this.calc_mass + (this.precursorCharge * PrideSpectrumMatch.protonMass)) / this.precursorCharge; - } - - calcMass() { - return (this.precursorCharge * this.calc_mz) - (this.precursorCharge * PrideSpectrumMatch.protonMass); //this.calc_mass; - } - - missingPeaks() { - const errorMZ = this.expMZ() - this.calcMZ(); - const errorM = errorMZ * this.precursorCharge; - //how many peaks assumed missing/miss-assigned - return Math.round(errorM / PrideSpectrumMatch.C13_MASS_DIFFERENCE); - } - - massError() { - return ((this.expMass() - this.calcMass()) / this.calcMass()) * 1000000; - } - - ionTypes() { - return this.ions; - } - - ionTypesString() { - return JSON.stringify(this.ionTypes()); - } - - crosslinkerModMass() { - var clModMass = +this.matchedPeptides[0].cl_modmass; - if (this.matchedPeptides[1]) { - clModMass = clModMass + (+this.matchedPeptides[1].cl_modmass); - } - return clModMass; - } - - fragmentTolerance() { - if (this.spectrum) { - var fragTolArr = this.spectrum.ft.split(" "); - return { - "tolerance": fragTolArr[0], - "unit": fragTolArr[1] - }; - } - } - - fragmentToleranceString() { - var fragTol = this.fragmentTolerance(); - if (fragTol) { - return fragTol.tolerance + " " + fragTol.unit; - } - } - - score() { - //return this._scores.score; - var scoreSets = this.containingModel.get("scoreSets"); - //if (scoreSets.size == 1) { - var scoreSet = scoreSets.keys().next().value; - var s = this._scores[scoreSet]; - //console.log("!", s); - return s; - //} - } - - modificationCount() { - return -1; //temp - const modCount1 = this.matchedPeptides[0].mod_pos.length; - if (this.matchedPeptides[1]) { - const modCount2 = this.matchedPeptides[1].mod_pos.length; - if (modCount2 > modCount1) { - return modCount2; - } - } - return modCount1; - } - - get pepSeq1_base() { - return this.matchedPeptides[0].sequence; - } - - get pepSeq2_base() { - if (this.matchedPeptides[1]) { - return this.matchedPeptides[1].sequence; - } else { - return ""; - } - } - - get pepSeq1_mods() { - return this.pepSeq1_base; - } - - get pepSeq2_mods() { - return this.pepSeq2_base; - } - - get psmId() { - return this.identification.id; - } - - get datasetId() { - return this.searchId; - } - - get scanNumber() { - // if (this.spectrum) { - return this.spectrumId; - // } - } -} - -PrideSpectrumMatch.protonMass = 1.007276466879; -PrideSpectrumMatch.C13_MASS_DIFFERENCE = 1.0033548; - - -/***/ }), - -/***/ "./CLMS-model/src/spectrum-match/spectrum-match.js": -/*!*********************************************************!*\ - !*** ./CLMS-model/src/spectrum-match/spectrum-match.js ***! - \*********************************************************/ -/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { - -"use strict"; -__webpack_require__.r(__webpack_exports__); -/* harmony export */ __webpack_require__.d(__webpack_exports__, { -/* harmony export */ SpectrumMatch: () => (/* binding */ SpectrumMatch) -/* harmony export */ }); -/* harmony import */ var _crosslink__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../crosslink */ "./CLMS-model/src/crosslink.js"); - - -class SpectrumMatch { - - constructor() { - - } - - associateWithLink(proteins, crosslinks, p1ID, p2ID, res1, res2, //following params may be null :- - pep1_start, pep1_length, pep2_start, pep2_length) { - - // we don't want two different ID's, e.g. one that's "33-66" and one that's "66-33" - //following puts lower protein_ID first in link_ID - - //todo: this end swapping thing, its a possible source of confusion - - let fromProt, toProt; - - if (this.isNotCrosslinked()) {//!p2ID || p2ID === "" || p2ID === '-' || p2ID === 'n/a') { //its a linear peptide (no crosslinker of any product type)) - this.containingModel.set("linearsPresent", true); - fromProt = proteins.get(p1ID); - if (!fromProt) { - alert("FAIL: not protein with ID " + p1ID); - } - } else if (p1ID <= p2ID) { - fromProt = proteins.get(p1ID); - toProt = proteins.get(p2ID); - if (!fromProt) { - alert("FAIL: not protein with ID " + p1ID); - } - if (!toProt) { - alert("FAIL: not protein with ID " + p2ID); - } - } else { - fromProt = proteins.get(p2ID); - toProt = proteins.get(p1ID); - if (!fromProt) { - alert("FAIL: not protein with ID " + p2ID); - } - if (!toProt) { - alert("FAIL: not protein with ID " + p1ID); - } - } - - if (fromProt && toProt && fromProt.targetProteinID === toProt.targetProteinID) { - this.couldBelongToSelfLink = true; - } else if (!this.isMonoLink()) { - this.couldBelongToBetweenLink = true; - } - - // again, order id string by prot id or by residue if self-link - let endsReversedInResLinkId = false; - let crosslinkID; - if (this.isNotCrosslinked()) { - crosslinkID = p1ID + "_linears"; - } else if (p1ID === p2ID || p2ID === null) { - if ((res1 - 0) < (res2 - 0) || res2 === null) { - crosslinkID = p1ID + "_" + res1 + "-" + p2ID + "_" + res2; - } else { - crosslinkID = p2ID + "_" + res2 + "-" + p1ID + "_" + res1; - endsReversedInResLinkId = true; - } - } else if (p1ID < p2ID) { - crosslinkID = p1ID + "_" + res1 + "-" + p2ID + "_" + res2; - } else { - crosslinkID = p2ID + "_" + res2 + "-" + p1ID + "_" + res1; - endsReversedInResLinkId = true; - } - - //get or create residue link - let resLink = crosslinks.get(crosslinkID); - if (typeof resLink == "undefined") { - //to and from proteins were already swapped over above - - //WATCH OUT - residues need to be in correct order - if (this.isNotCrosslinked()) { - resLink = new _crosslink__WEBPACK_IMPORTED_MODULE_0__.Crosslink(crosslinkID, fromProt, - res1, null, null, this.containingModel); - } else if (p1ID === p2ID) { - if ((res1 - 0) < (res2 - 0)) { - resLink = new _crosslink__WEBPACK_IMPORTED_MODULE_0__.Crosslink(crosslinkID, fromProt, res1, toProt, res2, this.containingModel); - } else { - resLink = new _crosslink__WEBPACK_IMPORTED_MODULE_0__.Crosslink(crosslinkID, fromProt, res2, toProt, res1, this.containingModel); - } - } else if (p1ID === fromProt.id) { - resLink = new _crosslink__WEBPACK_IMPORTED_MODULE_0__.Crosslink(crosslinkID, fromProt, res1, toProt, res2, this.containingModel); - } else { - //WATCH OUT - residues need to be in correct oprder - resLink = new _crosslink__WEBPACK_IMPORTED_MODULE_0__.Crosslink(crosslinkID, fromProt, res2, toProt, res1, this.containingModel); - } - crosslinks.set(crosslinkID, resLink); - - fromProt.crosslinks.push(resLink); - if (toProt && (toProt !== fromProt)) { - toProt.crosslinks.push(resLink); - } - } - - const peptidePositions = []; - if (endsReversedInResLinkId === false) { - peptidePositions.push({ - start: pep1_start, - length: pep1_length - }); - peptidePositions.push({ - start: pep2_start, - length: pep2_length - }); - } else { - peptidePositions.push({ - start: pep2_start, - length: pep2_length - }); - peptidePositions.push({ - start: pep1_start, - length: pep1_length - }); - } - resLink.matches_pp.push({ - match: this, - pepPos: peptidePositions - }); - this.crosslinks.push(resLink); - } - - isAmbig() { - return this.matchedPeptides[0].pos.length > 1 || - (this.matchedPeptides[1] && this.matchedPeptides[1].pos.length > 1); - } - - isDecoy() { - if (this.is_decoy) { - return this.is_decoy; - } else { - //its from csv not database, for simplicity lets just look at first crosslink //todo - look at again - return this.crosslinks[0].isDecoyLink(); - } - } - -} - -/***/ }), - -/***/ "./CLMS-model/src/spectrum-match/xi2-spectrum-match.js": -/*!*************************************************************!*\ - !*** ./CLMS-model/src/spectrum-match/xi2-spectrum-match.js ***! - \*************************************************************/ -/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { - -"use strict"; -__webpack_require__.r(__webpack_exports__); -/* harmony export */ __webpack_require__.d(__webpack_exports__, { -/* harmony export */ Xi2SpectrumMatch: () => (/* binding */ Xi2SpectrumMatch) -/* harmony export */ }); -/* harmony import */ var _crosslink__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../crosslink */ "./CLMS-model/src/crosslink.js"); -/* harmony import */ var _spectrum_match__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./spectrum-match */ "./CLMS-model/src/spectrum-match/spectrum-match.js"); - - - -class Xi2SpectrumMatch extends _spectrum_match__WEBPACK_IMPORTED_MODULE_1__.SpectrumMatch { - constructor(containingModel, participants, crosslinks, peptides, identification) { - super(); - this.containingModel = containingModel; //containing BB model - this.identification = identification; - this.primaryDataSetId = identification.rs_id; - this.spectrumId = identification.sp; - this.searchId = identification.si.toString(); - this.id = identification.id; - this.precursorMZ = +identification.pc_mz; - this.calc_mass = +identification.cm; - this._score = +identification.sc; - - - this.resultSetId = identification.rs_id.toString(); - this.crosslinker_id = identification.cl; - - // this.scanNumber = null;//+identificationes[0].sn; - this.scanIndex = null;//+identificationes[0].sc_i; - this.precursor_intensity = +identification.pc_i; - this.elution_time_start = +identification.rt; - this.elution_time_end = null;//+identificationes[0].e_e; - - this.src = null;//+identificationes[0].src; //for looking up run name - this.plf = null;//+identificationes[0].plf; //for looking up peak list file name - //run name may have come from csv file - - this.precursorCharge = +identification.pc_c; - if (this.precursorCharge === -1) { - this.precursorCharge = undefined; - } - - this.matchedPeptides = []; - this.matchedPeptides[0] = peptides.get(this.searchId + "_" + identification.pi1); - // following will be inadequate for trimeric and higher order cross-links - if (!this.isNotCrosslinked()) { - this.matchedPeptides[1] = peptides.get(this.searchId + "_" + identification.pi2); - } - // } else { //*here - if its from a csv file use identificationes as the matchedPep array, - // //makes it easier to construct as parsing CSV - // this.matchedPeptides = identificationes; - // } - - //if the match is ambiguous it will relate to many crosslinks - this.crosslinks = []; - this.linkPos1 = +identification.s1; - // if (identification.s2) { - this.linkPos2 = +identification.s2; - // } - - // the protein IDs and residue numers we eventually want to get:- - let p1ID, p2ID, res1, res2; - - if (this.isNotCrosslinked()) { - //its a linear - this.containingModel.set("linearsPresent", true); - for (let i = 0; i < this.matchedPeptides[0].prt.length; i++) { - p1ID = this.matchedPeptides[0].prt[i]; - this.associateWithLink(participants, crosslinks, p1ID); - } - if (this.matchedPeptides[1]) { - for (let i = 0; i < this.matchedPeptides[1].prt.length; i++) { - p1ID = this.matchedPeptides[1].prt[i]; - this.associateWithLink(participants, crosslinks, p1ID); - } - } - return; - } - - this.couldBelongToBetweenLink = false; - this.couldBelongToSelfLink = false; - - //loop to produce all alternative linkage site combinations - //(position1 count * position2 count alternative) - for (let i = 0; i < this.matchedPeptides[0].pos.length; i++) { - for (let j = 0; j < this.matchedPeptides[1].pos.length; j++) { - - if (i > 0 || j > 0) { - this.containingModel.set("ambiguousPresent", true); - } - - //some files (must be csv) are not puting in duplicate protein ids in ambig links - //in this case use last one - if (i < this.matchedPeptides[0].prt.length) { - p1ID = this.matchedPeptides[0].prt[i]; - } else { - p1ID = this.matchedPeptides[0].prt[this.matchedPeptides[0].prt.length - 1]; - } - if (j < this.matchedPeptides[1].prt.length) { - p2ID = this.matchedPeptides[1].prt[j]; - } else { - p2ID = this.matchedPeptides[1].prt[this.matchedPeptides[1].prt.length - 1]; - } - - // * residue numbering starts at 1 * - res1 = +this.matchedPeptides[0].pos[i] - 1 + this.linkPos1; - res2 = +this.matchedPeptides[1].pos[j] - 1 + this.linkPos2; - - this.associateWithLink(participants, crosslinks, p1ID, p2ID, res1, res2, this.matchedPeptides[0].pos[i] - 0, this.matchedPeptides[0].sequence.length, this.matchedPeptides[1].pos[j], this.matchedPeptides[1].sequence.length); - } - } - - //identify homodimers: if peptides overlap its a homodimer - this.confirmedHomomultimer = false; - this.overlap = []; - if (this.isAmbig() === false && p1ID === p2ID) { //todo: potential problem re ambiguous homo-multimer link (compare current behaviour to xiNET paper product type fig) - - if (this.matchedPeptides[0].sequence && this.matchedPeptides[1].sequence) { - - const pep1length = this.matchedPeptides[0].sequence.length; - const pep2length = this.matchedPeptides[1].sequence.length; - const pep1_start = +this.matchedPeptides[0].pos[0]; - const pep2_start = +this.matchedPeptides[1].pos[0]; - const pep1_end = pep1_start + (pep1length - 1); - const pep2_end = pep2_start + (pep2length - 1); - if (pep1_start >= pep2_start && pep1_start <= pep2_end) { - this.confirmedHomomultimer = true; - this.overlap[0] = pep1_start - 1; - if (pep1_end < pep2_end) { - this.overlap[1] = pep1_end; - } else { - this.overlap[1] = pep2_end; - } - } else if (pep2_start >= pep1_start && pep2_start <= pep1_end) { - this.confirmedHomomultimer = true; - this.overlap[0] = pep2_start - 1; - if (pep2_end < pep1_end) { - this.overlap[1] = pep2_end; - } else { - this.overlap[1] = pep1_end; - } - } - } else if (res1 === res2) { - this.confirmedHomomultimer = true; - this.overlap[0] = res1 - 1; - this.overlap[1] = res2; - } - } - } - - isNotCrosslinked() { - return this.linkPos1 === 0; - } - - isMonoLink() { - return false; - } - - runName() { - return this.identification.run; - } - - peakListFileName() { - return this.containingModel.get("peakListFiles").get(this.plf); - } - - group() { - return this.containingModel.get("searches").get(this.datasetId).group; - } - - expMZ() { - return this.precursorMZ; - } - - expMass() { - return this.precursorMZ * this.precursorCharge - (this.precursorCharge * Xi2SpectrumMatch.protonMass); - } - - calcMZ() { - return (this.calc_mass + (this.precursorCharge * Xi2SpectrumMatch.protonMass)) / this.precursorCharge; - } - - calcMass() { - return this.calc_mass; - } - - missingPeaks() { - const errorMZ = this.expMZ() - this.calcMZ(); - const errorM = errorMZ * this.precursorCharge; - //how many peaks assumed missing/miss-assigned - return Math.round(errorM / Xi2SpectrumMatch.C13_MASS_DIFFERENCE); - } - - massError() { - //old - //return ((this.expMass() - this.calcMass()) / this.calcMass()) * 1000000; - - // new - change needed due to some other change to do with missing peaks - // what is the error in m/z - const assumedMZ = this.expMZ() - this.missingPeaks() * Xi2SpectrumMatch.C13_MASS_DIFFERENCE / this.precursorCharge; - const errorMZ = assumedMZ - this.calcMZ(); - return errorMZ / this.calcMZ() * 1000000; - } - - ionTypes() { - const search = this.containingModel.get("searches").get(this.resultSetId); - let ionTypes = []; - ionTypes = ionTypes.concat(search.s_config.fragmentation.cterm_ions); - ionTypes = ionTypes.concat(search.s_config.fragmentation.nterm_ions); - return ionTypes; - } - - ionTypesString() { - const ions = this.ionTypes(); - let returnString = ""; - for (let i = 0; i < ions.length; i++) { - let ion = ions[i];//.type; - if (ion.indexOf("Ion") > 0) { - ion = ion.substring(0, ion.indexOf("Ion")); - } - returnString = returnString + ion.toLowerCase() + ";"; - } - return returnString; - } - - crosslinkerModMass() { - const crosslinker = this.getCrossLinker(); - if (crosslinker) { - return crosslinker.mass; - } else return 0; - } - - getCrossLinker() { - // if (this.crosslinker_id === -1) { - return null; - // } - // - // const searches = this.containingModel.get("searches"); - // const search = searches.get(this.searchId); - // const crosslinkers = search.crosslinkers; - // const clCount = crosslinkers.length; - // for (let c = 0; c < clCount; c++) { - // const crosslinker = crosslinkers[c]; - // if (crosslinker.id == this.crosslinker_id) { // yes, they're different types, don't === - // return crosslinker; - // } - // } - } - - fragmentTolerance() { - const search = this.containingModel.get("searches").get(this.resultSetId); - return { - "tolerance": search.ms2tolerance, - "unit": search.ms2toleranceunits - }; - } - - fragmentToleranceString() { - const search = this.containingModel.get("searches").get(this.resultSetId); - return search.ms2tolerance + " " + search.ms2toleranceunits; - } - - score() { - return this._score; - } - - experimentalMissedCleavageCount() { - const enzymeSpecificity = this.containingModel.get("enzymeSpecificity"); - - //yes... this should prob be done with regex - // (https://github.com/Rappsilber-Laboratory/xi3-issue-tracker/issues/401#issuecomment-495158293) - - function countMissedCleavages(peptide, linkPos) { - let count = 0; - const seqMods = peptide.seq_mods; - if (seqMods) { - const pepLen = seqMods.length; - - const indexOfLinkedAA = findIndexofNthUpperCaseLetter(seqMods, linkPos); - - for (let i = 0; i < pepLen; i++) { - for (let spec of enzymeSpecificity) { - if (seqMods[i] === spec.aa) { - if (i < pepLen) { - if (seqMods[i + 1] >= "A" && seqMods[i + 1] <= "Z") { - if (i !== indexOfLinkedAA) { - let postConstrained = false; - if (spec.postConstraint) { - for (let pc of spec.postConstraint) { - if (peptide.sequence[i + 1] === pc) { - postConstrained = true; - break; - } - } - } - if (!postConstrained) { - count++; - } - } - } - } - } - } - } - } - return count; - } - - function findIndexofNthUpperCaseLetter(str, n) { // n is 1-indexed here - let i = -1; - while (n > 0 && i < str.length) { - i++; - const c = str[i]; - if (c >= "A" && c <= "Z") n--; - } - return i === str.length ? undefined : i; - } - - const mc1 = countMissedCleavages(this.matchedPeptides[0], this.linkPos1); - if (this.matchedPeptides[1]) { - const mc2 = countMissedCleavages(this.matchedPeptides[1], this.linkPos2); - return Math.max(mc1, mc2); - } - return mc1; - } - - searchMissedCleavageCount() { - const enzymeSpecificity = this.containingModel.get("enzymeSpecificity"); - - function countSearchMissedCleavages(peptide) { - let count = 0; - const sequence = peptide.sequence; - const pepLen = sequence.length; - for (let i = 0; i < pepLen; i++) { - for (let spec of enzymeSpecificity) { - if (sequence[i] === spec.aa) { - if (i < (pepLen - 1)) { - count++; - } - } - } - } - return count; - } - - const mc1 = countSearchMissedCleavages(this.matchedPeptides[0]); - if (this.matchedPeptides[1]) { - const mc2 = countSearchMissedCleavages(this.matchedPeptides[1]); - return Math.max(mc1, mc2); - } - return mc1; - } - - modificationCount() { - function peptideModCount(peptide) { - let count = 0; - const sequence = peptide.seq_mods; - const pepLen = sequence.length; - for (let i = 0; i < pepLen - 1; i++) { - const a = sequence[i]; - const b = sequence[i + 1]; - if ((a >= "A" && a <= "Z") && (b < "A" || b > "Z")) count++; - } - return count; - } - - const modCount1 = peptideModCount(this.matchedPeptides[0]); - if (this.matchedPeptides[1]) { - const modCount2 = peptideModCount(this.matchedPeptides[1]); - if (modCount2 > modCount1) { - return modCount2; - } - } - return modCount1; - } - -// this.id = identification.id; -// this.spectrumId = identification.sp_id; -// this.searchId = identification.si.toString(); -// this.resultSetId = identification.rsi.toString(); -// this.crosslinker_id = identification.cl; -// -// // this.scanNumber = null;//+identificationes[0].sn; -// this.scanIndex = null;//+identificationes[0].sc_i; -// this.precursor_intensity = null;//+identificationes[0].pc_i; -// this.elution_time_start = null;//+identificationes[0].e_s; -// this.elution_time_end = null;//+identificationes[0].e_e; -// -// this.src = null;//+identificationes[0].src; //for looking up run name -// this.plf = null;//+identificationes[0].plf; //for looking up peak list file name -// //run name may have come from csv file -// -// this.precursorCharge = +identification.pc_c; -// if (this.precursorCharge === -1) { -// this.precursorCharge = undefined; -// } -// -// this.precursorMZ = +identification.pc_mz; -// this.calc_mass = +identification.cm; -// this._score = +identification.sc; - - get passThreshold() { - return true; - } - - get pepSeq1_mods() { - return this.matchedPeptides[0].seq_mods; - } - - get pepSeq2_mods() { - if (!this.matchedPeptides[1]) return undefined; - return this.matchedPeptides[1].seq_mods; - } - - get psmId() { - return this.identification.id; - } - - get datasetId() { - return this.resultSetId; - } - - get scanNumber() { - return this.identification.sn; - } -} - -Xi2SpectrumMatch.protonMass = 1.007276466879; -Xi2SpectrumMatch.C13_MASS_DIFFERENCE = 1.0033548; - - -/***/ }), - -/***/ "./CLMS-model/src/xi2-load-spectrum.js": -/*!*********************************************!*\ - !*** ./CLMS-model/src/xi2-load-spectrum.js ***! - \*********************************************/ -/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { - -"use strict"; -__webpack_require__.r(__webpack_exports__); -/* harmony export */ __webpack_require__.d(__webpack_exports__, { -/* harmony export */ xi2LoadSpectrum: () => (/* binding */ xi2LoadSpectrum) -/* harmony export */ }); -/* harmony import */ var d3__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! d3 */ "./node_modules/d3/d3.js"); -/* harmony import */ var d3__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(d3__WEBPACK_IMPORTED_MODULE_0__); - - -const xi2LoadSpectrum = function (match) { - - const formatted_data = {}; - - formatted_data.sequence1 = match.matchedPeptides[0].seq_mods; - formatted_data.base_sequence1 = match.matchedPeptides[0].sequence; - formatted_data.mod_ids1 = match.matchedPeptides[0].mod_ids; - formatted_data.mod_pos1 = match.matchedPeptides[0].mod_pos; - formatted_data.linkPos1 = match.linkPos1 - 1; - if (match.matchedPeptides[1]) { - formatted_data.sequence2 = match.matchedPeptides[1].seq_mods; - formatted_data.base_sequence2 = match.matchedPeptides[1].sequence; - formatted_data.mod_ids2 = match.matchedPeptides[1].mod_ids; - formatted_data.mod_pos2 = match.matchedPeptides[1].mod_pos; - formatted_data.linkPos2 = match.linkPos2 - 1; - } - formatted_data.precursorCharge = match.precursorCharge; - formatted_data.config = window.compositeModelInst.get("clmsModel").get("searches").get(match.datasetId).s_config; - formatted_data.crosslinkerID = match.crosslinker_id; - formatted_data.precursorMZ = match.expMZ(); - formatted_data.requestID = match.id; - formatted_data.spectrum_title = "PSMID: " + match.id; - - console.log("xi2LoadSpectrum match:" + match.id); - - d3__WEBPACK_IMPORTED_MODULE_0___default().text(window.peakListUrl + "?uuid=" + match.spectrumId, function (error, text) { - if (error) { - console.log("error getting peak list", error); - } else { - if (text === "false") { - const xiVersion = window.compositeModelInst.get("clmsModel").get("searches").get(match.searchId).version; - const message = "Missing peak list for spectrum " + match.spectrumId + ". xiSearch v" + xiVersion; - alert(message); - // ToDo: clear (following doesn't work: window.compositeModelInst.get("xispec_wrapper").setData({}); - } else { - d3__WEBPACK_IMPORTED_MODULE_0___default().select("#range-error").text(""); - const rawPeaks = JSON.parse(text); - const intensity = rawPeaks[0]; - const mz = rawPeaks[1]; - const peakList = []; - const peakCount = intensity.length; - for (let i = 0; i < peakCount; i++){ - peakList.push([mz[i], intensity[i]]); - } - formatted_data.peakList = peakList; - console.log(formatted_data); - window.compositeModelInst.get("xispec_wrapper").setData(formatted_data); - } - } - }); - -}; - - -/***/ }), - -/***/ "./crosslink-viewer/js/views/xinet/crosslink-viewer-BB.js": -/*!****************************************************************!*\ - !*** ./crosslink-viewer/js/views/xinet/crosslink-viewer-BB.js ***! - \****************************************************************/ -/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { - -"use strict"; -__webpack_require__.r(__webpack_exports__); -/* harmony export */ __webpack_require__.d(__webpack_exports__, { -/* harmony export */ CrosslinkViewer: () => (/* binding */ CrosslinkViewer) -/* harmony export */ }); -/* harmony import */ var _css_xiNET_css__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../../css/xiNET.css */ "./crosslink-viewer/css/xiNET.css"); -/* harmony import */ var d3__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! d3 */ "./node_modules/d3/d3.js"); -/* harmony import */ var d3__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(d3__WEBPACK_IMPORTED_MODULE_1__); -/* harmony import */ var backbone__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! backbone */ "./node_modules/backbone/backbone.js"); -/* harmony import */ var backbone__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(backbone__WEBPACK_IMPORTED_MODULE_2__); -/* harmony import */ var _vendor_cola__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../../../vendor/cola */ "./crosslink-viewer/vendor/cola.js"); -/* harmony import */ var _vendor_cola__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(_vendor_cola__WEBPACK_IMPORTED_MODULE_3__); -/* harmony import */ var _xiview_js_svgexp__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../../../../xiview/js/svgexp */ "./xiview/js/svgexp.js"); -/* harmony import */ var _xiview_js_utils__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ../../../../xiview/js/utils */ "./xiview/js/utils.js"); -/* harmony import */ var _xiview_js_downloads__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ../../../../xiview/js/downloads */ "./xiview/js/downloads.js"); -/* harmony import */ var _interactor_rendered_protein__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ./interactor/rendered-protein */ "./crosslink-viewer/js/views/xinet/interactor/rendered-protein.js"); -/* harmony import */ var _link_rendered_crosslink__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ./link/rendered-crosslink */ "./crosslink-viewer/js/views/xinet/link/rendered-crosslink.js"); -/* harmony import */ var _interactor_group__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ./interactor/group */ "./crosslink-viewer/js/views/xinet/interactor/group.js"); -/* harmony import */ var _link_p_p_link__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! ./link/p_p-link */ "./crosslink-viewer/js/views/xinet/link/p_p-link.js"); -/* harmony import */ var _link_g_g_link__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! ./link/g_g-link */ "./crosslink-viewer/js/views/xinet/link/g_g-link.js"); -/* harmony import */ var _xiview_js_model_color_protein_color_model__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(/*! ../../../../xiview/js/model/color/protein-color-model */ "./xiview/js/model/color/protein-color-model.js"); - - - -// import * as _ from "underscore"; - - - - - - - - - - - - - - -class CrosslinkViewer extends (backbone__WEBPACK_IMPORTED_MODULE_2___default().View) { - - // constructor(attributes, options) { - // super(_.extend(attributes, { - // events: { - // } - // }), options); - // } - - initialize() { - // this.debug = true; - this.fixedSize = this.model.get("xinetFixedSize"); - this.cropLabels = this.model.get("xinetCropLabels"); - const self = this; - - function newCustomContextMenuSel(outerDivClass) { - const contextMenuSel = d3__WEBPACK_IMPORTED_MODULE_1__.select(self.el) - .append("div").classed("custom-menu-margin", true) - .classed(outerDivClass, true); - const menuUL = contextMenuSel.append("div").classed("custom-menu", true) - .append("ul"); - contextMenuSel.node().onmouseover = function () { - // self.contextMenuParticipant.highlighted = true; // todo - look at - change hidden proteins in model - self.model.setHighlightedProteins(self.contextMenuParticipant.proteins); - }; - contextMenuSel.node().onmouseout = function (evt) { - let e = evt.toElement || evt.relatedTarget; - do { - if (e === this) return; - if (e) e = e.parentNode; // seems like tab changing when uniprot opens can cause e to become null - } while (e); - if (self.contextMenuParticipant){ - self.model.setHighlightedProteins([]); // todo - look at - } - self.contextMenuParticipant = null; - d3__WEBPACK_IMPORTED_MODULE_1__.select(this).style("display", "none"); - }; - return menuUL; - } - - this.contextMenuUlSel = newCustomContextMenuSel("xinet-context-menu"); - //create SVG element - this.svgElement = d3__WEBPACK_IMPORTED_MODULE_1__.select(this.el).append("div").style("height", "100%").append("svg").node(); //document.createElementNS(CrosslinkViewer.svgns, "svg"); - this.svgElement.setAttribute("width", "100%"); - this.svgElement.setAttribute("height", "100%"); - this.svgElement.setAttribute("style", "pointer-events:visible"); - //add listeners - - this.svgElement.onmousedown = function (evt) { - self.mouseDown(evt); - }; - this.svgElement.onmousemove = function (evt) { - self.mouseMove(evt); - }; - this.svgElement.onmouseup = function (evt) { - self.mouseUp(evt); - }; - - this.el.oncontextmenu = function (evt) { - if (evt.preventDefault) { // necessary for addEventListener, works with traditional - evt.preventDefault(); - } - evt.returnValue = false; // necessary for attachEvent, works with traditional - return false; // works with traditional, not with attachEvent or addEventListener - }; - - const mouseWheelEvt = (/Firefox/i.test(navigator.userAgent)) ? "DOMMouseScroll" : "mousewheel"; //FF doesn't recognize mousewheel as of FF3.x - this.svgElement.addEventListener(mouseWheelEvt, function (evt) { - self.mouseWheel(evt); - }, false); - - this.lastMouseUp = new Date().getTime(); - - // various SVG groups needed - this.wrapper = document.createElementNS(CrosslinkViewer.svgns, "g"); //in effect, a hack for fact firefox doesn't support getCTM on svgElement - const identM = this.svgElement.createSVGMatrix(); - const s = "matrix(" + identM.a + "," + identM.b + "," + identM.c + "," + identM.d + "," + identM.e + "," + identM.f + ")"; - this.wrapper.setAttribute("transform", s); - this.container = document.createElementNS(CrosslinkViewer.svgns, "g"); - this.container.setAttribute("id", "container"); - this.wrapper.appendChild(this.container); - - this.groupsSVG = document.createElementNS(CrosslinkViewer.svgns, "g"); - this.groupsSVG.setAttribute("id", "groupsSVG"); - this.container.appendChild(this.groupsSVG); - - this.p_pLinksWide = document.createElementNS(CrosslinkViewer.svgns, "g"); - this.p_pLinksWide.setAttribute("id", "p_pLinksWide"); - this.container.appendChild(this.p_pLinksWide); - - this.proteinLower = document.createElementNS(CrosslinkViewer.svgns, "g"); - this.proteinLower.setAttribute("id", "proteinLower"); - this.container.appendChild(this.proteinLower); - - this.highlights = document.createElementNS(CrosslinkViewer.svgns, "g"); - this.highlights.setAttribute("class", "highlights"); //proteins also contain highlight groups - this.container.appendChild(this.highlights); - - this.res_resLinks = document.createElementNS(CrosslinkViewer.svgns, "g"); - this.res_resLinks.setAttribute("id", "res_resLinks"); - this.container.appendChild(this.res_resLinks); - - this.p_pLinks = document.createElementNS(CrosslinkViewer.svgns, "g"); - this.p_pLinks.setAttribute("id", "p_pLinks"); - this.container.appendChild(this.p_pLinks); - - this.proteinUpper = document.createElementNS(CrosslinkViewer.svgns, "g"); - this.proteinUpper.setAttribute("id", "proteinUpper"); - this.container.appendChild(this.proteinUpper); - - this.svgElement.appendChild(this.wrapper); - - // this.debugRectSel = d3.select(this.proteinUpper).append("rect").attr("stroke", "green").attr("fill", "none").style("pointer-events", "none"); - // this.debugRectSel2 = d3.select(this.proteinUpper).append("rect").attr("stroke", "blue").attr("fill", "none").style("pointer-events", "none"); - - //is a d3 selection unlike those above - this.selectionRectSel = d3__WEBPACK_IMPORTED_MODULE_1__.select(this.svgElement).append("rect") - .attr("x", 10) - .attr("y", 10) - .attr("width", 50) - .attr("height", 100) - .attr("stroke", "red") - .attr("stroke-dasharray", "4,4") - .attr("stroke-dashoffset", "32") - .style("animation", "dash 2s linear infinite") - .attr("fill", "none") - .attr("display", "none"); - - this.d3cola = _vendor_cola__WEBPACK_IMPORTED_MODULE_3__.d3adaptor() - .groupCompactness(1e-5) - .avoidOverlaps(true); - - this.dragElement = null; - this.dragStart = null; - - this.renderedProteins = new Map(); - this.renderedCrosslinks = new Map(); - this.renderedP_PLinks = new Map(); - // all xiNET.Groups in play - this.groupMap = new Map(); - this.g_gLinks = new Map(); - this.toSelect = []; // used by right click drag - this.z = 1; - this.container.setAttribute("transform", "scale(1)"); - this.state = CrosslinkViewer.STATES.MOUSE_UP; - - this.firstRender = true; - - // calculate default bar scale - let maxSeqLength = 0; - for (let participant of this.model.get("clmsModel").get("participants").values()) { - if (participant.is_decoy === false && this.renderedProteins.has(participant.id) === false) { - const newProtien = new _interactor_rendered_protein__WEBPACK_IMPORTED_MODULE_7__.RenderedProtein(participant, this); - this.renderedProteins.set(participant.id, newProtien); - - const protSize = participant.size; - if (protSize > maxSeqLength) { - maxSeqLength = protSize; - } - } - } - const width = this.svgElement.parentNode.clientWidth; - const defaultPixPerRes = ((width * 0.8) - _interactor_rendered_protein__WEBPACK_IMPORTED_MODULE_7__.RenderedProtein.LABELMAXLENGTH) / maxSeqLength; - - // https://stackoverflow.com/questions/12141150/from-list-of-integers-get-number-closest-to-a-given-value/12141511#12141511 - function takeClosest(myList, myNumber) { - const bisect = d3__WEBPACK_IMPORTED_MODULE_1__.bisector(function (d) { - return d; - }).left; - const pos = bisect(myList, myNumber); - if (pos === 0 || pos === 1) { - return myList[1]; // don't return smallest scale as default - } - if (pos === myList.length) { - return myList[myList.length - 1]; - } - return myList[pos - 1]; - } - - this.defaultBarScale = takeClosest(CrosslinkViewer.barScales, defaultPixPerRes); - - const expand = this.renderedProteins.size < 4; - for (let rp of this.renderedProteins.values()) { - //to do - should this really be here - this.proteinLower.appendChild(rp.lowerGroup); - this.proteinUpper.appendChild(rp.upperGroup); - if (!rp.stickZoom) { - rp.stickZoom = this.defaultBarScale; - } - rp.scale(); - // rp.width;// cause it to store a constant value for unexpanded width? - if (expand) { - rp.toStickNoTransition(); - } - } - - for (let crosslink of this.model.get("clmsModel").get("crosslinks").values()) { - if (!crosslink.isDecoyLink() && !crosslink.isLinearLink()) { - if (!this.renderedCrosslinks.has(crosslink.id)) { - const renderedCrossLink = new _link_rendered_crosslink__WEBPACK_IMPORTED_MODULE_8__.RenderedCrosslink(crosslink, this); - this.renderedCrosslinks.set(crosslink.id, renderedCrossLink); - const toId = crosslink.toProtein ? crosslink.toProtein.id : "null"; - const p_pId = crosslink.fromProtein.id + "-" + toId; - let p_pLink = this.renderedP_PLinks.get(p_pId); - if (typeof p_pLink == "undefined") { - p_pLink = new _link_p_p_link__WEBPACK_IMPORTED_MODULE_10__.P_PLink(p_pId, crosslink, this); - this.renderedP_PLinks.set(p_pId, p_pLink); - } - p_pLink.crosslinks.push(crosslink); - - crosslink.p_pLink = p_pLink; - } - } - } - - this.listenTo(this.model, "filteringDone", this.render); - this.listenTo(this.model, "hiddenChanged", this.hiddenProteinsChanged); - this.listenTo(this.model, "change:groups", this.groupsChanged); - this.listenTo(this.model, "change:highlights", this.highlightedLinksChanged); - this.listenTo(this.model, "change:selection", this.selectedLinksChanged); - - this.listenTo(this.model, "change:linkColourAssignment currentColourModelChanged", this.render); - this.listenTo(this.model, "change:proteinColourAssignment currentProteinColourModelChanged", this.proteinColoursUpdated); - - this.listenTo(this.model.get("annotationTypes"), "change:shown", this.setAnnotations); - this.listenTo(this.model.get("alignColl"), "bulkAlignChange", this.setAnnotations); - this.listenTo(this.model, "change:selectedProteins", this.selectedProteinsChanged); - this.listenTo(this.model, "change:highlightedProteins", this.highlightedProteinsChanged); - - this.listenTo(window.vent, "proteinMetadataUpdated", this.proteinMetadataUpdated); - - this.listenTo(window.vent, "xinetSvgDownload", this.downloadSVG); - this.listenTo(window.vent, "xinetAutoLayout", this.autoLayout); - this.listenTo(window.vent, "xinetLoadLayout", this.loadLayout); - this.listenTo(window.vent, "xinetSaveLayout", this.saveLayout); - - this.listenTo(window.vent, "collapseGroups", this.collapseGroups); - this.listenTo(window.vent, "expandGroups", this.expandGroups); - - this.listenTo(this.model, "change:xinetShowLabels", this.showLabels); - this.listenTo(this.model, "change:xinetFixedSize", this.setFixedSize); - this.listenTo(this.model, "change:xinetCropLabels", this.setCropLabels); - this.listenTo(this.model, "change:xinetThickLinks", this.render); - this.listenTo(this.model, "change:xinetPpiSteps", this.render); - - return this; - } - - expandProtein() { - d3__WEBPACK_IMPORTED_MODULE_1__.select(".xinet-context-menu").style("display", "none"); - this.contextMenuParticipant.setExpanded(true); - this.render(); - this.contextMenuParticipant = null; - } - - collapseInteractor() { - d3__WEBPACK_IMPORTED_MODULE_1__.select(".xinet-context-menu").style("display", "none"); - this.model.setHighlightedProteins([]); - this.contextMenuParticipant.setExpanded(false, this.contextMenuPoint); - // if (this.contextMenuParticipant.type === "group") { - // this.render(); - // } - //this.hiddenProteinsChanged(); //REINSTATE? - //this.render(); - this.contextMenuParticipant = null; - } - - cantCollapseGroup() { - // d3.select(".custom-menu-margin").style("display", "none"); - // d3.select(".group-custom-menu-margin").style("display", "none"); - } - - ungroup() { - d3__WEBPACK_IMPORTED_MODULE_1__.select(".xinet-context-menu").style("display", "none"); - this.model.setHighlightedProteins([]); - this.model.get("groups").delete(this.contextMenuParticipant.id); - this.model.trigger("change:groups"); - this.contextMenuParticipant = null; - } - - collapseGroups() { - for (let group of this.groupMap.values()) { - if (group.expanded === true && !group.isOverlappingGroup()) { - // group.setExpanded(false); - group.collapse(null, false); - } - } - this.hiddenProteinsChanged(); - this.render(); - } - - expandGroups() { - for (let group of this.groupMap.values()) { - if (group.expanded === false) { - // group.setExpanded(true); - group.expand(false);// todo: reanme this to expandNoTransition - } - } - this.hiddenProteinsChanged(); - this.render(); - } - - groupsChanged() { - console.log("xiNET GROUPS CHANGED"); - this.d3cola.stop(); - - // a Map with group id as key and Set of protein ids to group as value - const modelGroups = this.model.get("groups"); - - //clear out old groups -- https://stackoverflow.com/questions/9882284/looping-through-array-and-removing-items-without-breaking-for-loop - const groupIdsToRemove = []; - for (let group of this.groupMap.values()) { - if (!modelGroups.has(group.id)) { - groupIdsToRemove.push(group.id); - - group.parentGroups = new Set();//[]; //don't think necessary but just in case - group.subroups = []; - for (let rp of group.renderedParticipants) { - rp.parentGroups.delete(group); - } - - if (group.expanded) { - this.groupsSVG.removeChild(group.upperGroup); - } else { - this.proteinUpper.removeChild(group.upperGroup); - } - } - } - for (let rgId of groupIdsToRemove) { - this.groupMap.delete(rgId); - } - - for (let g of modelGroups.entries()) { - if (!this.groupMap.has(g[0])) { //if group doesn't exist - const group = new _interactor_group__WEBPACK_IMPORTED_MODULE_9__.Group(g[0], g[1], this); - group.init(); - this.groupMap.set(group.id, group); - } else { // group already exists but the proteins in it may have changed - const group = this.groupMap.get(g[0]); - group.renderedParticipants = []; - for (let pId of g[1]) { - const p = this.renderedProteins.get(pId); - if (p) { // no decoys in this.renderedProteins - group.renderedParticipants.push(this.renderedProteins.get(pId)); - } - } - } - } - this.scale();//just to update groups selection highlights - this.hiddenProteinsChanged(); - this.render(); - } - - // handle changes to manually hidden proteins, - // but also deal with stuff to do with groups / group hierarchy - // specifically subgroups could change as result of things being hidden so this is here - // (i.e. overlapping group becomes subgroup) - hiddenProteinsChanged() { - console.log("xiNET HIDDEN PROTEINS CHANGED"); - this.d3cola.stop(); - - //clear parent groups of all proteins - for (let rp of this.renderedProteins.values()) { - rp.parentGroups = new Set();//[]; - } - - // parent groups may change, so clear groups - for (let g of this.groupMap.values()) { - g.subgroups = []; // subgroups as xiNET.Groups - g.parentGroups = new Set(); - g.leaves = []; // different from g.renderedParticipants coz only contains ungrouped RenderedProteins, used by cola.js - g.groups = []; // indexes of subgroups in resulting groupArr, used by cola.js // needed? prob not coz groups already referred to by index - - for (let rp of g.renderedParticipants) { - rp.parentGroups.delete(g); // sometimes it won't have contained g as parentGroup - } - } - - //sort it by count not hidden (not manually hidden and not filtered) - const sortedGroupMap = new Map([...this.groupMap.entries()].sort((a, b) => a[1].unhiddenParticipantCount - b[1].unhiddenParticipantCount)); - - // get maximal set of possible subgroups - const groups = Array.from(sortedGroupMap.values()); - const gCount = groups.length; // contains xiNET.Groups - for (let gi = 0; gi < gCount - 1; gi++) { - const group1 = groups[gi]; - if (group1.unhiddenParticipantCount > 0) { - for (let gj = gi + 1; gj < gCount; gj++) { - const group2 = groups[gj]; - if (group1.isSubsetOf(group2)) { - group2.subgroups.push(group1); - console.log(group1.name, "is SUBSET of", group2.name); - } - } - } - } - - for (let g of groups) { - for (let rp of g.renderedParticipants) { - rp.parentGroups.add(g); - } - } - - //sort out parentGroups - for (let group1 of groups.reverse()) { - if (group1.upperGroup.parentNode) { - // z-ordering (?) - const pn = group1.upperGroup.parentNode; - pn.removeChild(group1.upperGroup); - pn.appendChild(group1.upperGroup); - } - for (let group2 of group1.subgroups) { - group2.parentGroups.add(group1); - } - } - - let manuallyHidden = 0; - for (let renderedParticipant of this.renderedProteins.values()) { - if (renderedParticipant.participant.manuallyHidden === true) { - manuallyHidden++; - } - if (renderedParticipant.inCollapsedGroup() === false) { - renderedParticipant.setHidden(renderedParticipant.participant.hidden); - } else { - renderedParticipant.setHidden(true); - } - } - - if (manuallyHidden === 0) { - d3__WEBPACK_IMPORTED_MODULE_1__.select("#hiddenProteinsMessage").style("display", "none"); - } else { - const pSel = d3__WEBPACK_IMPORTED_MODULE_1__.select("#hiddenProteinsText"); - pSel.text((manuallyHidden > 1) ? (manuallyHidden + " Hidden Proteins") : (manuallyHidden + " Hidden Protein")); - const messageSel = d3__WEBPACK_IMPORTED_MODULE_1__.select("#hiddenProteinsMessage"); - messageSel.style("display", "block"); - } - - - for (let group of groups) { - if (!group.expanded && group.isOverlappingGroup()) { - group.setExpanded(true); - } - } - for (let group of groups) { - let hasVisible = false; - for (let p of group.renderedParticipants) { - if (p.participant.hidden === false) { - hasVisible = true; - } - } - if (!hasVisible || group.inCollapsedGroup()) { - group.setHidden(true); - } else { - group.setHidden(false); - group.updateCountLabel(); - if (group.expanded) { - group.updateExpandedGroup(); - } else { - group.setPosition(group.ix, group.iy); - } - } - } - - /* - this.subgraphs = []; - - for (let interactor of this.renderedProteins.values()) { - interactor.subgraph = null; - } - for (let interactor of this.groupMap.values()) { - interactor.subgraph = null; - } - - for (let interactor of this.renderedProteins.values()) { - if (!interactor.hidden) { - interactor.getSubgraph();//adds new subgraphs to this.subgraphs - } - } - for (let interactor of this.groupMap.values()) { - if (!interactor.hidden) { - interactor.getSubgraph();//adds new subgraphs to this.subgraphs - } - } - - this.subgraphs.sort(function (a, b) { - return b.nodes.size - a.nodes.size; - }); - - - //Sort subgraphs into linear and non-linear sets - this.linearGraphs = []; - this.nonLinearGraphs = []; - for (let graph of this.subgraphs) { - // const nodes = graph.nodes.values(); - const nodeCount = graph.nodes.size; - let isLinear = true; - if (nodeCount === 1) { - isLinear = true; - } else { - var endFound = false; - for (let node of graph.nodes.values()) { - const externalLinkCount = node.countExternalLinks(); - // console.log("ELC*: " + externalLinkCount); - if (node.expanded === true) { - isLinear = false; - break; - } - if (externalLinkCount > 2) { - isLinear = false; - break; - } else if (externalLinkCount < 2) { - endFound = true; - } - } - //check not circular - if (!endFound) { - isLinear = false; - } - } - if (isLinear === true) { - this.linearGraphs.push(graph); - } else { - this.nonLinearGraphs.push(graph); - } - }*/ - - return this; - } - - render() { - console.log("xiNET RENDER"); - this.d3cola.stop(); - if (this.firstRender) { // first render - this.firstRender = false; - if (this.model.get("clmsModel").get("xiNETLayout")) { - this.loadLayout(this.model.get("clmsModel").get("xiNETLayout").layout); - } else { - this.autoLayout([]); //layout all - } - } - - for (let ppLink of this.renderedP_PLinks.values()) { - - - ppLink.hd = false; - const filteredCrossLinks = new Set(); - const filteredMatches = new Set(); - const altP_PLinks = new Set(); - for (let crosslink of ppLink.crosslinks) { - if (crosslink.filteredMatches_pp.length > 0) { - filteredCrossLinks.add(crosslink.id); - for (let m of crosslink.filteredMatches_pp) { - const match = m.match; // oh dear, this... - filteredMatches.add(match.id); - if (match.hd === true) { - ppLink.hd = true; - } - if (match.crosslinks.length > 1) { - for (let matchCrossLink of match.crosslinks) { - if (!matchCrossLink.isDecoyLink()) { - altP_PLinks.add(matchCrossLink.p_pLink.id); - } - } - } - } - } - } - ppLink.filteredMatchCount = filteredMatches.size; - ppLink.filteredCrossLinkCount = filteredCrossLinks.size; - ppLink.ambiguous = altP_PLinks.size > 1; - - if (!ppLink.renderedToProtein || // not linear - //or either end hidden - ppLink.renderedFromProtein.participant.hidden || - ppLink.renderedToProtein.participant.hidden) { - ppLink.hide(); - } else { - const fromProtInCollapsedGroup = ppLink.renderedFromProtein.inCollapsedGroup(); - const toProtInCollapsedGroup = ppLink.renderedToProtein.inCollapsedGroup(); - - // if (// or is self link in collapsed group - // (ppLink.crosslinks[0].isSelfLink() && fromProtInCollapsedGroup) || - // // or either end is expanded to bar and not in collapsed group - // (ppLink.renderedFromProtein.expanded && !fromProtInCollapsedGroup) || - // (ppLink.renderedToProtein.expanded && !toProtInCollapsedGroup) || - // (fromProtInCollapsedGroup && toProtInCollapsedGroup) - // ) { - // ppLink.hide(); - // } - // else { - if (ppLink.filteredCrossLinkCount === 0) { - ppLink.hide(); - } else { - ppLink.ambiguous = altP_PLinks.size > 1; - if (fromProtInCollapsedGroup && toProtInCollapsedGroup) { - const source = ppLink.renderedFromProtein.getRenderedInteractor(); - const target = ppLink.renderedToProtein.getRenderedInteractor(); - let ggId; - if (source.id < target.id) { - ggId = source.id + "_" + target.id; - } else { - ggId = target.id + "_" + source.id; - } - let ggLink = ppLink.controller.g_gLinks.get(ggId); - if (!ggLink) { - if (source.id < target.id) { - ggLink = new _link_g_g_link__WEBPACK_IMPORTED_MODULE_11__.G_GLink(ggId, source, target, this); - } else { - ggLink = new _link_g_g_link__WEBPACK_IMPORTED_MODULE_11__.G_GLink(ggId, target, source, this); - } - this.g_gLinks.set(ggId, ggLink); - } - ggLink.p_pLinks.set(ppLink.id, ppLink); - ppLink.hide(); - } else { - // ppLink.show(); - if (// or is self link in collapsed group - (ppLink.crosslinks[0].isSelfLink() && fromProtInCollapsedGroup) || - // or either end is expanded to bar and not in collapsed group - (ppLink.renderedFromProtein.expanded && !fromProtInCollapsedGroup) || - (ppLink.renderedToProtein.expanded && !toProtInCollapsedGroup) || - (fromProtInCollapsedGroup && toProtInCollapsedGroup) - ) { - ppLink.hide(); - } else { - ppLink.show(); - } - } - } - // } - } - } - for (let cLink of this.renderedCrosslinks.values()) { - cLink.check(); - } - const ggLinkIdsToRemove = []; - for (let ggLink of this.g_gLinks.values()) { - if ( //true - ggLink.group1.expanded === false && ggLink.group2.expanded === false - && ggLink.check() - && this.groupMap.has(ggLink.group1.id) && this.groupMap.has(ggLink.group2.id) - && !(ggLink.group1.inCollapsedGroup() || ggLink.group2.inCollapsedGroup()) - ) { - ggLink.show(); - //set line coord? - } else { - ggLinkIdsToRemove.push(ggLink.id); - ggLink.hide(); - } - } - for (let id of ggLinkIdsToRemove) { - this.g_gLinks.delete(id); - } - } - - autoLayoutGroup(group, fixedParticipants) { - console.log("xiNET AUTO LAYOUT SINGLE GROUP"); - this.d3cola.stop(); - - const linkLength = (this.renderedProteins.size < 20) ? 40 : 20; - const width = this.svgElement.parentNode.clientWidth; - const height = this.svgElement.parentNode.clientHeight; - - for (let renderedProtein of this.renderedProteins.values()) { - if (fixedParticipants.length === 0) { - delete renderedProtein.x; - delete renderedProtein.y; - delete renderedProtein.px; - delete renderedProtein.py; - } - renderedProtein.fixed = fixedParticipants.indexOf(renderedProtein.participant) !== -1; - delete renderedProtein.index; - } - for (let g of this.groupMap.values()) { - if (fixedParticipants.length === 0) { // todo - some issues here (select a collapsed group and select fixed selected) - delete g.x; - delete g.y; - delete g.px; - delete g.py; - } - delete g.index; - delete g.parent; - g.leaves = []; // clear this, it's used by cola, gets filled by auto - } - - this.d3cola.size([height - /*layoutXOffset -*/ 40, width - 40]).symmetricDiffLinkLengths(linkLength); - - const self = this; - - const links = new Map(); - const nodeSet = new Set(); - for (let crosslink of self.model.getFilteredCrossLinks()) { - // for (let graph of this.nonLinearGraphs) { - // for (let link of graph.links.values()) { - if (crosslink.toProtein) { // not linears - // if (link.crosslinks[0].isSelfLink() === false) { - const source = self.renderedProteins.get(crosslink.fromProtein.id).getRenderedInteractor(); - const target = self.renderedProteins.get(crosslink.toProtein.id).getRenderedInteractor(); - if (group.renderedParticipants.indexOf(source) !== -1 || group.renderedParticipants.indexOf(target) !== -1) { - nodeSet.add(source); - const fromId = crosslink.fromProtein.id; - const toId = crosslink.toProtein.id; - const linkId = fromId + "-" + toId; - if (!links.has(linkId)) { - const linkObj = {}; - // todo - maybe do use indexes, might avoid probs in cola - linkObj.source = source; - linkObj.target = target; - nodeSet.add(target); // bit weird doing ths here - linkObj.id = linkId; - links.set(linkId, linkObj); - } - } - } - } - - const nodeArr = Array.from(nodeSet); - const linkArr = Array.from(links.values()); - doLayout(nodeArr, linkArr); - - function doLayout(nodes, links) { - //don't know how necessary these deletions are - delete self.d3cola._lastStress; - delete self.d3cola._alpha; - delete self.d3cola._descent; - delete self.d3cola._rootGroup; - - const groups = []; - if (self.groupMap) { - for (let g of self.groupMap.values()) { - delete g.index; - if (!g.hidden && g.expanded) { - g.groups = []; - // put any rp not contained in a subgroup in group1.leaves - for (let rp of g.renderedParticipants) { - if (!rp.hidden) { - let inSubGroup = false; - for (let subgroup of g.subgroups) { - if (subgroup.contains(rp)) { - inSubGroup = true; - break; - } - } - if (!inSubGroup) { - g.leaves.push(nodes.indexOf(rp)); - } - } - } - groups.push(g); - } - } - //need to use indexes of groups - for (let g of groups) { - console.log("GROUP ", g.unhiddenParticipantCount, g.id); - for (let i = 0; i < g.subgroups.length; i++) { - console.log("\tSUBGROUP ", g.subgroups[i].unhiddenParticipantCount, g.subgroups[i].id); - if (!g.subgroups[i].hidden) { - // todo - this is where you need to sort out issue of nested subgroups... - // the problem is when the same subgroup gets added to multiple parent groups - // the following seems to be working but not convinced it's totally reliable (depends on order groups end up in?) - let isSubset = false; - for (let j = i + 1; j < g.subgroups.length; j++) { - if (g.subgroups[i].isSubsetOf(g.subgroups[j])) { - isSubset = true; - break; - } - } - if (!isSubset) { - if (g.subgroups[i].expanded) { - g.groups.push(groups.indexOf(g.subgroups[i])); - - } else { - g.leaves.push(g.subgroups[i]); - } - } - } - } - } - } - - const cmp = self.contextMenuPoint; - - self.d3cola.nodes(nodes).groups(groups).links(links).start(23, 10, 1, 0, true).on("tick", function () { //.start(23, 10, 1, 0, true) - for (let node of self.d3cola.nodes()) { - node.setPositionFromXinet((node.x * self.z) - ((width/2 * self.z)) + cmp.x, - (node.y * self.z) - ((height/2 * self.z)) + cmp.y); - // node.setPositionFromXinet((node.x * self.z) - ((cmp.x - (width/2)) * self.z), - // (node.y * self.z) - ((cmp.y - (width/2)) * self.z) + 30); - // // node.setPositionFromCola(); - node.setAllLinkCoordinates(); - } - for (let g of self.d3cola.groups()) { // todo - seems a bit of a weird way to have done this? - if (g.expanded) { - g.updateExpandedGroup(); - } - } - }); - } - } - - autoLayout(fixedParticipants) { - console.log("xiNET AUTO LAYOUT"); - this.d3cola.stop(); - if (fixedParticipants.length === 0) { - this.container.setAttribute("transform", "scale(" + 1 + ")");// translate(" + ((width / scaleFactor) - bbox.width - bbox.x) + " " + -bbox.y + ")"); - this.scale(); - } - - const linkLength = (this.renderedProteins.size < 20) ? 40 : 20; - const width = this.svgElement.parentNode.clientWidth; - const height = this.svgElement.parentNode.clientHeight; - - /* const tempGroupMap = new Map (this.groupMap); - - //Grid layout linear graphs - var column = 0, row = 0; - if (this.linearGraphs.length > 0) { - column++; - for (let graph of this.linearGraphs) { - // todo - this is a right mess, fixing can wait til i'm back from holiday - var nodes = Array.from(graph.nodes.keys()); // - var nodeCount = nodes.length; - if (nodeCount > 2) { - nodes = this.reorderedNodes(graph); - } - nodeCount = nodes.length; - for (var n = 0; n < nodeCount; n++) { - var p = this.renderedProteins.get(nodes[n]); - if (!p) { - p = this.groupMap.get(nodes[n]); - tempGroupMap.delete(nodes[n]); - } - for (let pg of p.parentGroups.values()) { - tempGroupMap.delete(pg.id); - } - var x, y; - row++; - x = this.xForColumn(column); - y = this.yForRow(row); - var lastNodeY = this.yForRow(row + ((nodeCount - 1 - n) * 2)); - let lowerBound = height; - if (column < 4) { - lowerBound = lowerBound - 100; - } - if ((lastNodeY + 20) > lowerBound) { - column++; - row = 1; - x = this.xForColumn(column); - y = this.yForRow(row); - } - // console.log("??", p.id, column, row); - p.setPosition(x, y); - p.setAllLinkCoordinates(); - } - } - } - //remember edge of gridded proteins - const layoutXOffset = this.xForColumn(column + 1);*/ - - for (let renderedProtein of this.renderedProteins.values()) { - if (fixedParticipants.length === 0) { - delete renderedProtein.x; - delete renderedProtein.y; - delete renderedProtein.px; - delete renderedProtein.py; - } - renderedProtein.fixed = fixedParticipants.indexOf(renderedProtein.participant) !== -1; - delete renderedProtein.index; - } - for (let g of this.groupMap.values()) { - if (fixedParticipants.length === 0) { // todo - some issues here (select a collapsed group and select fixed selected) - delete g.x; - delete g.y; - delete g.px; - delete g.py; - } - delete g.index; - delete g.parent; - g.leaves = []; // clear this, it's used by cola, gets filled by auto - } - - this.d3cola.size([height - /*layoutXOffset -*/ 40, width - 40]).symmetricDiffLinkLengths(linkLength); - - const self = this; - - const links = new Map(); - const nodeSet = new Set(); - for (let crosslink of self.model.getFilteredCrossLinks()) { - // for (let graph of this.nonLinearGraphs) { - // for (let link of graph.links.values()) { - if (crosslink.toProtein) { // not linears - // if (link.crosslinks[0].isSelfLink() === false) { - const source = self.renderedProteins.get(crosslink.fromProtein.id).getRenderedInteractor(); - const target = self.renderedProteins.get(crosslink.toProtein.id).getRenderedInteractor(); - nodeSet.add(source); - const fromId = crosslink.fromProtein.id; - const toId = crosslink.toProtein.id; - const linkId = fromId + "-" + toId; - if (!links.has(linkId)) { - const linkObj = {}; - // todo - maybe do use indexes, might avoid probs in cola - linkObj.source = source; - linkObj.target = target; - nodeSet.add(target); // bit weird doing ths here - linkObj.id = linkId; - links.set(linkId, linkObj); - } - } - } - // } - const nodeArr = Array.from(nodeSet); - const linkArr = Array.from(links.values()); - doLayout(nodeArr, linkArr); - - function doLayout(nodes, links) { - //don't know how necessary these deletions are - delete self.d3cola._lastStress; - delete self.d3cola._alpha; - delete self.d3cola._descent; - delete self.d3cola._rootGroup; - - const groups = []; - if (self.groupMap) { - for (let g of self.groupMap.values()) { - delete g.index; - if (!g.hidden && g.expanded) { - g.groups = []; - // put any rp not contained in a subgroup in group1.leaves - for (let rp of g.renderedParticipants) { - if (!rp.hidden) { - let inSubGroup = false; - for (let subgroup of g.subgroups) { - if (subgroup.contains(rp)) { - inSubGroup = true; - break; - } - } - if (!inSubGroup) { - g.leaves.push(nodes.indexOf(rp)); - } - } - } - groups.push(g); - } - } - //need to use indexes of groups - for (let g of groups) { - console.log("GROUP ", g.unhiddenParticipantCount, g.id); - for (let i = 0; i < g.subgroups.length; i++) { - console.log("\tSUBGROUP ", g.subgroups[i].unhiddenParticipantCount, g.subgroups[i].id); - if (!g.subgroups[i].hidden) { - // todo - this is where you need to sort out issue of nested subgroups... - // the problem is when the same subgroup gets added to multiple parent groups - // the following seems to be working but not convinced it's totally reliable (depends on order groups end up in?) - let isSubset = false; - for (let j = i + 1; j < g.subgroups.length; j++) { - if (g.subgroups[i].isSubsetOf(g.subgroups[j])) { - isSubset = true; - break; - } - } - if (!isSubset) { - if (g.subgroups[i].expanded) { - g.groups.push(groups.indexOf(g.subgroups[i])); - - } else { - g.leaves.push(g.subgroups[i]); - } - } - } - } - } - } - let participantDebugSel, groupDebugSel; - if (self.debug) { - participantDebugSel = d3__WEBPACK_IMPORTED_MODULE_1__.select(self.groupsSVG).selectAll(".node") - .data(nodes); - participantDebugSel.enter().append("rect") - .classed("node", true) - .attr({ - rx: 5, - ry: 5 - }) - .style("stroke", "red") - .style("fill", "none") - .style("pointer-events", "none"); - groupDebugSel = d3__WEBPACK_IMPORTED_MODULE_1__.select(self.groupsSVG).selectAll(".group") - .data(groups); - groupDebugSel.enter().append("rect") - .classed("group", true) - .attr({ - rx: 5, - ry: 5 - }) - .style("stroke", "blue") - .style("fill", "none") - .style("pointer-events", "none"); - groupDebugSel.exit().remove(); - participantDebugSel.exit().remove(); - } - self.d3cola.nodes(nodes).groups(groups).links(links).start(23, 10, 1, 0, true).on("tick", function () { //.start(23, 10, 1, 0, true) - // let x1 = null, y1 = null, x2 = null, y2 = null; - // for (let node of self.d3cola.nodes()) { - // if (!x1 || node.x < x1) { - // x1 = node.x; - // } - // if (!y1 || node.y < y1) { - // y1 = node.y; - // } - // if (!x2 || node.x > x2) { - // x2 = node.x; - // } - // if (!y2 || node.y > y2) { - // y2 = node.y; - // } - // } - // - // let c = 0; - // let xr = (width - /*layoutXOffset -*/ 120) / (x2 - x1); - // let yr = ((height - 60) / (y2 - y1)); - - for (let node of self.d3cola.nodes()) { - // node.setPositionFromCola((node.x * xr) - (x1 * xr) /*+ layoutXOffset*/, - // (node.y * yr) - (y1 * yr) + 30); - node.setPositionFromCola(); - node.setAllLinkCoordinates(); - } - for (let g of self.d3cola.groups()) { // todo - seems a bit of a weird way to have done this? - if (g.expanded) { - g.updateExpandedGroup(); - } - } - if (fixedParticipants.length === 0) { - self.zoomToFullExtent(); - } - - if (self.debug) { - groupDebugSel.attr({ - x: function (d) { - return d.bounds.x; - }, - y: function (d) { - return d.bounds.y; - }, - width: function (d) { - return d.bounds.width(); - }, - height: function (d) { - return d.bounds.height(); - } - }); - participantDebugSel.attr({ - x: function (d) { - return d.bounds.x; - }, - y: function (d) { - return d.bounds.y; - }, - width: function (d) { - return d.bounds.width(); - }, - height: function (d) { - return d.bounds.height(); - } - }); - } - }); - //} - } - } - - // //functions used... - // xForColumn(c) { - // const maxBlobRadius = 40; - // // var LABELMAXLENGTH = 0; - // // return (c * ((2 * maxBlobRadius) + LABELMAXLENGTH)) - maxBlobRadius; - // return c * maxBlobRadius - (maxBlobRadius / 2); - // } - // - // yForRow(r) { - // const maxBlobRadius = 50; - // return (r * maxBlobRadius) - 10; - // } - // - // reorderedNodes(linearGraph) { - // const reorderedNodes = []; - // appendNode(getStartNode(), new Set ()); - // return reorderedNodes; - // - // function getStartNode() { - // // var ns = Array.from(linearGraph.nodes.values()); - // // var count = ns.length; - // // // alert (nodeCount); - // // for (var n = 0; n < count; n++) { - // // if (ns[n].countExternalLinks() < 2) { - // // // alert("got start"); - // // return ns[n]; - // // } - // // } - // for (let node of linearGraph.nodes.values()) { - // if (node.countExternalLinks() < 2) { - // console.log("StartNode", node.id); - // return node; - // } - // } - // console.error("missed linear subgraph start"); - // return null; - // } - // - // function appendNode(currentNode, checkedNodes) { - // checkedNodes.add(currentNode.id); // yeah, wierdness, this all needs tidied up - // if (!currentNode.hidden) { - // reorderedNodes.push(currentNode.participant.id); - // } - // - // // var proteinLinksArr = Array.from(currentNode.renderedP_PLinks.values()); - // // for (var l = 0; l < proteinLinksArr.length; l++) { - // // var link = proteinLinksArr[l]; - // // if (link.isPassingFilter()) { - // // var nextNode = link.getOtherEnd(currentNode); - // // if (reorderedNodes.indexOf(nextNode.participant.id) === -1) { - // // // alert("here"); - // // appendNode(nextNode); - // // break; - // // } - // // } - // // } - // - // for (let link of currentNode.renderedP_PLinks.values()) { - // if (link.isPassingFilter()) { - // const nextNode = link.getOtherEnd(currentNode); - // if (!checkedNodes.has(nextNode.id)) { - // console.log("nextNode", nextNode.id); - // appendNode(nextNode, checkedNodes); - // break; - // } - // } - // } - // } - // } - - saveLayout(callback) { - const layout = {}; - const proteinColourModel = this.model.get("proteinColourAssignment"); - if (proteinColourModel instanceof _xiview_js_model_color_protein_color_model__WEBPACK_IMPORTED_MODULE_12__.ManualColourModel) { - layout.manualColourAssignment = JSON.stringify(Object.fromEntries(proteinColourModel.colourAssignment)); - } - layout.groups = Array.from(this.groupMap.values()); - layout.proteins = Array.from(this.renderedProteins.values()); - const myJSONText = JSON.stringify(layout, null); - console.log("SAVING", layout); - callback(myJSONText.replace(/\\u0000/gi, "")); - } - - //todo - this is becoming about config of all xiVIEw not just config of xiNET, should be moved - loadLayout(layout) { - console.log("xiNET LOAD LAYOUT", layout); - let proteinPositions, groups; - // for backwards compatibility (after groups added to layout) - if (layout.proteins) { - proteinPositions = layout.proteins; - groups = layout.groups; - } else { - proteinPositions = layout; - } - let namesChanged = false; - for (let protLayout of proteinPositions) { - const protein = this.renderedProteins.get(protLayout.id); - if (protein !== undefined) { - protein.setPositionFromXinet(protLayout["x"], protLayout["y"]); - if (typeof protLayout["rot"] !== "undefined") { - // noinspection PointlessArithmeticExpressionJS - protein.rotation = protLayout["rot"] - 0; - } - protein.ix = protLayout["x"]; - protein.iy = protLayout["y"]; - protein.newForm = protLayout["expanded"]; - if (CrosslinkViewer.barScales.indexOf(+protLayout["stickZoom"]) > -1) { - protein.stickZoom = protLayout["stickZoom"]; - } - // noinspection PointlessArithmeticExpressionJS - protein.rotation = protLayout["rot"] - 0; - protein.flipped = protLayout["flipped"]; - protein.participant.manuallyHidden = protLayout["manuallyHidden"]; - - if (protLayout["name"]) { - protein.participant.name = protLayout["name"]; - namesChanged = true; - } - - } - } - - for (let rp of this.renderedProteins.values()) { - rp.setEverything(); - } - - if (groups && typeof groups[Symbol.iterator] === "function") { - const modelGroupMap = new Map(); - for (const savedGroup of groups) { - //gonna need to check for proteins now missing from results - const presentProteins = new Set(); - - for (let pId of savedGroup.participantIds) { - if (this.renderedProteins.get(pId)) { - presentProteins.add(pId); - } - } - if (presentProteins.size === 0) { - // layoutIsDodgy = true; - // this prob happens as a result of revalidating data in lab version - console.log("! group in layout but no proteins in search:" + savedGroup.id + "; " + savedGroup.participantIds); - } else { - modelGroupMap.set(savedGroup.id, presentProteins); - } - } - this.model.set("groups", modelGroupMap); - this.model.trigger("change:groups"); - - for (const savedGroup of groups) { - const xiNetGroup = this.groupMap.get(savedGroup.id); - if (xiNetGroup && savedGroup.expanded === false) { - xiNetGroup.collapse(null, false); - xiNetGroup.setPositionFromXinet(savedGroup.x, savedGroup.y); - } - } - } - - this.model.get("filterModel").trigger("change", this.model.get("filterModel")); - - this.zoomToFullExtent(); - - if (layout.manualColourAssignment) { - window.linkColor.manualProteinColoursBB.setMap(JSON.parse(layout.manualColourAssignment)); - this.model.set("proteinColourAssignment", window.linkColor.manualProteinColoursBB); - } - - // if (layoutIsDodgy) { - // alert("Looks like something went wrong with the saved layout, if you can't see your proteins click Auto layout"); - // } - - if (namesChanged) { - // vent.trigger("proteinMetadataUpdated", {}); //ain't gonna work - for (let renderedParticipant of this.renderedProteins.values()) { - renderedParticipant.updateName(); - } - } - } - - downloadSVG() { - const svgArr = [this.svgElement]; - const svgStrings = (0,_xiview_js_svgexp__WEBPACK_IMPORTED_MODULE_4__.capture)(svgArr); - let svgXML = (0,_xiview_js_svgexp__WEBPACK_IMPORTED_MODULE_4__.makeXMLStr)(new XMLSerializer(), svgStrings[0]); - //bit of a hack - const bBox = this.svgElement.getBoundingClientRect(); - const width = Math.round(bBox.width); - const height = Math.round(bBox.height); - svgXML = svgXML.replace("width=\"100%\"", "width=\"" + width + "px\""); - svgXML = svgXML.replace("height=\"100%\"", "height=\"" + height + "px\""); - const fileName = (0,_xiview_js_utils__WEBPACK_IMPORTED_MODULE_5__.makeLegalFileName)((0,_xiview_js_utils__WEBPACK_IMPORTED_MODULE_5__.searchesToString)() + "--xiNET--" + (0,_xiview_js_utils__WEBPACK_IMPORTED_MODULE_5__.filterStateToString)()); - (0,_xiview_js_downloads__WEBPACK_IMPORTED_MODULE_6__.download)(svgXML, "application/svg", fileName + ".svg"); - } - - highlightedLinksChanged() { - for (let p_pLink of this.renderedP_PLinks.values()) { - p_pLink.showHighlight(false); - } - const highlightedCrossLinks = this.model.getMarkedCrossLinks("highlights"); - for (let renderedCrossLink of this.renderedCrosslinks.values()) { - if (highlightedCrossLinks.indexOf(renderedCrossLink.crosslink) !== -1) { - if (renderedCrossLink.renderedFromProtein.expanded || - !renderedCrossLink.renderedToProtein || renderedCrossLink.renderedToProtein.expanded) { - renderedCrossLink.showHighlight(true); - } else if (renderedCrossLink.renderedToProtein) { - const p_pLink = this.renderedP_PLinks.get( - renderedCrossLink.renderedFromProtein.participant.id + "-" + renderedCrossLink.renderedToProtein.participant.id); - p_pLink.showHighlight(true); - } - } else { - renderedCrossLink.showHighlight(false); - } - } - for (let gg of this.g_gLinks.values()) { - gg.checkHighlight(); - } - return this; - } - - selectedLinksChanged() { - for (let p_pLink of this.renderedP_PLinks.values()) { - p_pLink.setSelected(false); - } - const selectedCrossLinks = this.model.getMarkedCrossLinks("selection"); - for (let renderedCrossLink of this.renderedCrosslinks.values()) { - if (selectedCrossLinks.indexOf(renderedCrossLink.crosslink) !== -1) { - renderedCrossLink.setSelected(true); - if (renderedCrossLink.renderedToProtein) { - const p_pLink = this.renderedP_PLinks.get( - renderedCrossLink.renderedFromProtein.participant.id + "-" + renderedCrossLink.renderedToProtein.participant.id); - p_pLink.setSelected(true); - } - } else { - renderedCrossLink.setSelected(false); - } - } - for (let gg of this.g_gLinks.values()) { - gg.checkSelected(); - } - return this; - } - - selectedProteinsChanged() { - const selectedProteins = this.model.get("selectedProteins"); - for (let renderedProtein of this.renderedProteins.values()) { - if (selectedProteins.indexOf(renderedProtein.participant) === -1 ){//&& renderedProtein.isSelected === true) { - renderedProtein.selected = false; - } - } - for (let selectedProtein of selectedProteins) { - if (selectedProtein.is_decoy !== true) { - this.renderedProteins.get(selectedProtein.id).selected = true; - } - } - if (this.groupMap) { - for (let g of this.groupMap.values()) { - g.updateSelected(); - } - } - return this; - } - - highlightedProteinsChanged() { - const highlightedProteins = this.model.get("highlightedProteins"); - - for (let renderedProtein of this.renderedProteins.values()) { - if (highlightedProteins.indexOf(renderedProtein.participant) === -1){//} && renderedProtein.highlight === true) { - renderedProtein.highlighted = false; - } - } - for (let highlightedProtein of highlightedProteins) { - if (highlightedProtein.is_decoy !== true) { - const renderedProtein = this.renderedProteins.get(highlightedProtein.id); - renderedProtein.highlighted = true; - } - - } - - if (this.groupMap) { - for (let g of this.groupMap.values()) { - let someHighlighted = false, allHighlighted = true; - for (let rp of g.renderedParticipants) { - if (rp.highlighted) { - someHighlighted = true; - } else { - allHighlighted = false; - } - } - if (someHighlighted) { - g.dashed = !allHighlighted; - g.highlighted = true; - } else { - g.highlighted = false; - g.updateSelected(); - } - } - } - - return this; - } - - // updates protein names and colours - proteinMetadataUpdated() { - for (let renderedParticipant of this.renderedProteins.values()) { - renderedParticipant.updateName(); - } - this.proteinColoursUpdated(); - return this; - } - - proteinColoursUpdated() { - const proteinColourModel = window.compositeModelInst.get("proteinColourAssignment"); - for (let renderedParticipant of this.renderedProteins.values()) { - if (proteinColourModel) { - const c = proteinColourModel.getColour(renderedParticipant.participant); - d3__WEBPACK_IMPORTED_MODULE_1__.select(renderedParticipant.outline) - .attr("fill", c); - d3__WEBPACK_IMPORTED_MODULE_1__.select(renderedParticipant.background) - .attr("fill", c); - } - } - //groups also - for (let g of this.groupMap.values()) { - if (proteinColourModel && proteinColourModel instanceof _xiview_js_model_color_protein_color_model__WEBPACK_IMPORTED_MODULE_12__.ManualColourModel) { - const c = proteinColourModel.getColour(g); - g.setColour(c); - } else { - g.setColour("#CCCCCC"); - } - } - return this; - } - - showLabels() { - const show = this.model.get("xinetShowLabels"); - for (let renderedParticipant of this.renderedProteins.values()) { - renderedParticipant.showLabel(show); - } - return this; - } - - setFixedSize() { - this.fixedSize = this.model.get("xinetFixedSize"); - for (let renderedParticipant of this.renderedProteins.values()) { - renderedParticipant.resize(); - } - return this; - } - - setCropLabels() { - this.cropLabels = this.model.get("xinetCropLabels"); - for (let renderedParticipant of this.renderedProteins.values()) { - renderedParticipant.updateName(); - } - return this; - } - - zoomToFullExtent() { - const margin = 50; - const width = this.svgElement.parentNode.clientWidth - (2 * margin); - const height = this.svgElement.parentNode.clientHeight - (2 * margin); - const bbox = this.container.getBBox(); - let xr = (width / bbox.width); - let yr = (height / bbox.height); - let scaleFactor; - if (xr > yr) { - scaleFactor = yr; - } else { - scaleFactor = xr; - } - this.container.setAttribute("transform", "scale(" + scaleFactor - + ") translate(" + ((width / scaleFactor) - bbox.width - bbox.x + (margin / scaleFactor)) + " " + (-bbox.y + (margin / scaleFactor)) + ")"); - this.scale(); - } - - scale() { - this.z = this.container.getCTM().inverse().a; - if (this.z < 0) { - console.error("weird negative value for this.z"); - this.z = 1; - } - for (let prot of this.renderedProteins.values()) { - prot.setPositionFromXinet(prot.ix, prot.iy); // this rescales the protein - if (prot.expanded) - prot.setAllLinkCoordinates(); - } - for (let renderedCrossLink of this.renderedCrosslinks.values()) { - if (renderedCrossLink.shown && renderedCrossLink.crosslink.isSelfLink() === false && renderedCrossLink.crosslink.toProtein) { - renderedCrossLink.line.setAttribute("stroke-width", this.z * CrosslinkViewer.linkWidth); - renderedCrossLink.highlightLine.setAttribute("stroke-width", this.z * 10); - if (renderedCrossLink.crosslink.ambiguous === true) { - renderedCrossLink.dashedLine(true); //rescale spacing of dashes - } - } - } - for (let p_pLink of this.renderedP_PLinks.values()) { - if (p_pLink.renderedToProtein && p_pLink.renderedFromProtein !== p_pLink.renderedToProtein && - !p_pLink.renderedFromProtein.expanded && !p_pLink.renderedToProtein.expanded) { - if (p_pLink.line) { - p_pLink.line.setAttribute("stroke-width", this.z * CrosslinkViewer.linkWidth); - p_pLink.highlightLine.setAttribute("stroke-width", this.z * 10); - p_pLink.updateThickLineWidth(); - if (p_pLink.ambiguous) { - p_pLink.dashedLine(true); //rescale spacing of dashes // performance issue? - } - } - } - } - for (let gg of this.g_gLinks.values()) { - if (gg.group1 !== gg.group2) { - // if (p_pLink.line) { - gg.line.setAttribute("stroke-width", this.z * CrosslinkViewer.linkWidth); - gg.highlightLine.setAttribute("stroke-width", this.z * 10); - gg.updateThickLineWidth(); - // if (p_pLink.ambiguous) { - // p_pLink.dashedLine(true); //rescale spacing of dashes - // } - // } - } - } - for (let g of this.groupMap.values()) { - if (!g.hidden) { - g.outline.setAttribute("stroke-width", this.z * 5); - g.highlight.setAttribute("stroke-width", this.z * 5); - if (g.expanded) { - g.updateExpandedGroup(); - } else { - g.setPositionFromXinet(g.ix, g.iy); - } - g.dashed = g._dashed; // rescale dashes - } - } - } - - setAnnotations() { - for (let renderedProtein of this.renderedProteins.values()) { - renderedProtein.setPositionalFeatures(); - } - } - - setCTM(element, matrix) { - const s = "matrix(" + matrix.a + "," + matrix.b + "," + matrix.c + "," + matrix.d + "," + matrix.e + "," + matrix.f + ")"; - element.setAttribute("transform", s); - } - - mouseDown(evt) { - evt.preventDefault(); - this.d3cola.stop(); - this.dragStart = evt; - this.state = CrosslinkViewer.STATES.SELECT_PAN; - this.mouseMoved = false; - this.toSelect = []; - d3__WEBPACK_IMPORTED_MODULE_1__.select(".xinet-context-menu").style("display", "none"); - } - - // dragging/rotating/panning/selecting - mouseMove(evt) { - if (this.dragStart) { - const p = this.getEventPoint(evt); // seems to be correct, see below - const c = p.matrixTransform(this.container.getCTM().inverse()); - const ds = this.getEventPoint(this.dragStart).matrixTransform(this.container.getCTM().inverse()); - const dx = ds.x - c.x; - const dy = ds.y - c.y; - if (Math.sqrt(dx * dx + dy * dy) > (5 * this.z)) { - this.mouseMoved = true; - } - if (this.dragElement != null && evt.which !== 3) { //dragging or rotating / not right-click mouse down - //remove tooltip - this.model.get("tooltipModel").set("contents", null); - if (this.state === CrosslinkViewer.STATES.DRAGGING) { - // we are currently dragging things around - if (this.dragElement.type === "group" && this.dragElement.expanded) { - if (!this.dragElement.selected) { - const toDrag = this.dragElement.renderedParticipants; - for (let d = 0; d < toDrag.length; d++) { - const renderedProtein = toDrag[d]; - renderedProtein.setPositionFromXinet(renderedProtein.ix - dx, renderedProtein.iy - dy); - renderedProtein.setAllLinkCoordinates(); - } - for (let g of this.dragElement.subgroups) { - if (!g.expanded) { - g.setPositionFromXinet(g.ix - dx, g.iy - dy); - g.setAllLinkCoordinates(); - } - } - }else { - this.moveSelected(dx, dy); - } - this.dragElement.updateExpandedGroup(); - } else if (this.dragElement.participant || this.dragElement.type === "group"){ //collapsed group or protein - if (!this.dragElement.selected) { - this.dragElement.setPositionFromXinet(this.dragElement.ix - dx, this.dragElement.iy - dy); - this.dragElement.setAllLinkCoordinates(); - } else { - this.moveSelected(dx, dy); - } - } - this.dragStart = evt; - } else if (this.state === CrosslinkViewer.STATES.ROTATING) { - // Distance from mouse x and center of stick. - const _dx = c.x - this.dragElement.ix; - // Distance from mouse y and center of stick. - const _dy = c.y - this.dragElement.iy; - //see http://en.wikipedia.org/wiki/Atan2#Motivation - let centreToMouseAngleRads = Math.atan2(_dy, _dx); - if (this.whichRotator === 0) { - centreToMouseAngleRads = centreToMouseAngleRads + Math.PI; - } - const centreToMouseAngleDegrees = centreToMouseAngleRads * (360 / (2 * Math.PI)); - this.dragElement.setRotation(centreToMouseAngleDegrees); - this.dragElement.setAllLinkCoordinates(); - } else { //not dragging or rotating yet, maybe we should start - // don't start dragging just on a click - we need to move the mouse a bit first - if (Math.sqrt(dx * dx + dy * dy) > (5 * this.z)) { //this.mouseMoved? - this.state = CrosslinkViewer.STATES.DRAGGING; - } - } - } else if (this.state === CrosslinkViewer.STATES.SELECT_PAN) { - if (evt.which === 3) { - //SELECT - const ds = this.getEventPoint(this.dragStart).matrixTransform(this.wrapper.getCTM().inverse()); - // var dx = c.x - ds.x; - // var dy = c.y - ds.y; - - const sx = p.x - ds.x; - const sy = p.y - ds.y; - - let rectX = ds.x; - if (sx < 0) { - rectX += sx; - } - let rectY = ds.y; - if (sy < 0) { - rectY += sy; - } - - this.selectionRectSel.attr("display", "inline") - .attr("x", rectX) - .attr("y", rectY) - .attr("width", Math.abs(sx)) - .attr("height", Math.abs(sy)); - - this.toSelect = []; - - const svgRect = this.svgElement.createSVGRect(); - svgRect.x = rectX; - svgRect.y = rectY; - svgRect.width = Math.abs(sx); - svgRect.height = Math.abs(sy); - - for (let renderedParticipant of this.renderedProteins.values()) { - if (renderedParticipant.hidden !== true) { - const intersects = this.svgElement.getIntersectionList(svgRect, renderedParticipant.upperGroup); - if (intersects.length > 0) { - renderedParticipant.highlighted = true; // todo - use model - this.toSelect.push(renderedParticipant.participant); - } else { - renderedParticipant.highlighted = false; // todo - use model - } - } - - } - for (let renderedGroup of this.groupMap.values()) { - if (renderedGroup.hidden !== true && renderedGroup.expanded === false) { - const intersects = this.svgElement.getIntersectionList(svgRect, renderedGroup.upperGroup); - if (intersects.length > 0) { - renderedGroup.highlighted = true; // todo - use model? - for (let renderedParticipant of renderedGroup.renderedParticipants) { - this.toSelect.push(renderedParticipant.participant); - } - } else { - renderedGroup.highlighted = false; // todo - use model? - } - } - } - } else { - //PAN - const ds = this.getEventPoint(this.dragStart).matrixTransform(this.container.getCTM().inverse()); - const dx = c.x - ds.x; - const dy = c.y - ds.y; - this.setCTM(this.container, - this.container.getCTM() - .translate(dx, dy) - ); - this.dragStart = evt; - } - } - } - } - - moveSelected(dx, dy) { - const toDrag = this.model.get("selectedProteins"); - for (let d = 0; d < toDrag.length; d++) { - const renderedProtein = this.renderedProteins.get(toDrag[d].id); - renderedProtein.setPositionFromXinet(renderedProtein.ix - dx, renderedProtein.iy - dy); - renderedProtein.setAllLinkCoordinates(); - } - for (let g of this.groupMap.values()) { - if (!g.expanded && g.selected) { - g.setPositionFromXinet(g.ix - dx, g.iy - dy); - g.setAllLinkCoordinates(); - } - } - } - - // this ends all dragging and rotating - mouseUp(evt) { - this.preventDefaultsAndStopPropagation(evt); - //remove selection rect, may not be shown but just do this now - this.selectionRectSel.attr("display", "none"); - //eliminate some spurious mouse up events - a simple version of debouncing, but it seems to work better than for e.g. _.debounce - const time = new Date().getTime(); - if ((time - this.lastMouseUp) > 150) { - const rightClick = (evt.button === 2); - const add = evt.ctrlKey || evt.shiftKey; - const p = this.getEventPoint(evt); - const c = p.matrixTransform(this.container.getCTM().inverse()); - if (this.state === CrosslinkViewer.STATES.ROTATING) { - //round protein rotation to nearest 5 degrees (looks neater) - this.dragElement.setRotation(Math.round(this.dragElement.rotation / 5) * 5); - this.dragElement.setAllLinkCoordinates(); - } else { - if (this.dragElement) { - if (rightClick) { - if (this.mouseMoved) { // move and right click - // ADD TO SELECT POST RIGHT CLICK DRAG -- RIGHT CLICK, HAS MOVED, NO DRAG ELEMENT - this.model.setSelectedProteins(this.toSelect, add); - } - // EXPANDING / COLLAPSING -- RIGHT CLICK, NO MOVE, IS A DRAG ELEMENT - this.contextMenuParticipant = this.dragElement; - if (this.dragElement.ix || this.dragElement.type === "group") { - this.model.get("tooltipModel").set("contents", null); - this.contextMenuPoint = c; - this.showContextMenu(evt); - } - } else if (this.dragElement.participant && !this.mouseMoved) { // it's a protein - // ADD SINGLE PROTEIN TO SELECTION - LEFT CLICK, NO MOVE, IS A DRAG ELEMENT - this.model.setSelectedProteins([this.dragElement.participant], add); - } else if (this.dragElement.participant && add && this.mouseMoved) { - // alert ("add protein to group, not implemented yet"); - // get list of groups intersecting point where protein was 'dropped' - const groupsAtPoint = []; - for (let renderedGroup of this.groupMap.values()) { - if (renderedGroup.hidden !== true){ // && renderedGroup.expanded === false) { - const bbox = renderedGroup.upperGroup.getBBox(); - if (c.x > bbox.x && c.x < bbox.x + bbox.width && c.y > bbox.y && c.y < bbox.y + bbox.height) { - console.log("just dropped in" + renderedGroup.id); //to see-ee what condition my condition was in - groupsAtPoint.push(renderedGroup); - } - } - } - // if only one group, add protein to that group - if (groupsAtPoint.length === 1) { - const group = groupsAtPoint[0]; - this.model.addProteinToGroup(group.id, this.dragElement.participant.id); - } else if (groupsAtPoint.length > 1) { - // if more than one group, show a menu of groups to add to - alert("more than one group at that point, this not implemented yet. You need a menu to confirm which group(s) to add to"); - } - } else if (this.dragElement.type === "group" && !this.mouseMoved) { // was left-click on a group, no move mouse - //add all group's proteins to selection - this.model.setSelectedProteins(this.dragElement.proteins, add); - } - } else { //no drag element - if (rightClick) { - if (this.mouseMoved) { // move and right click - // ADD TO SELECT POST RIGHT CLICK DRAG -- RIGHT CLICK, HAS MOVED, NO DRAG ELEMENT - this.model.setSelectedProteins(this.toSelect, add); - } - } else if (!this.mouseMoved) { - //UNSELECT - EITHER MOUSE BUTTON, NO MOVE, NO DRAG ELEMENT - this.model.setMarkedCrossLinks("selection", [], false, add); - this.model.setSelectedProteins([]); - - } - } - } - this.dragElement = null; - this.whichRotator = -1; - this.state = CrosslinkViewer.STATES.MOUSE_UP; - this.mouseMoved = false; - } - this.lastMouseUp = time; - return false; - } - - showContextMenu(evt) { - const self = this; - const menuListSel = this.contextMenuUlSel; - menuListSel.selectAll("li").remove(); - - const renderedInteractor = this.contextMenuParticipant; - const proteinColourModel = this.model.get("proteinColourAssignment"); - - if (renderedInteractor.participant) { //protein - if (renderedInteractor.expanded) { - menuListSel.append("li").text("Collapse Protein").on("click", () => { - this.collapseInteractor(renderedInteractor); - }); - //scale buttons - const scaleButtonsListItemSel = menuListSel.append("li").text("Scale: "); - const scaleButtons = scaleButtonsListItemSel.selectAll("ul.custom-menu") - .data(CrosslinkViewer.barScales) - .enter() - .append("div") - .attr("class", "barScale") - .append("label"); - scaleButtons.append("span") - .text(function (d) { - if (d === 8) return "AA"; - else return d; - }); - scaleButtons.append("input") - // .attr ("id", function(d) { return d*100; }) - .attr("class", function (d) { - return "scaleButton scaleButton_" + (d * 100); - }) - .attr("name", "scaleButtons") - .attr("type", "radio") - .on("change", function (d) { - self.contextMenuParticipant.setStickScale(d, self.contextMenuPoint); - }); - d3__WEBPACK_IMPORTED_MODULE_1__.select(".scaleButton_" + (renderedInteractor.stickZoom * 100)).property("checked", true); - - } else { - menuListSel.append("li").text("Expand Protein").on("click", () => { - this.expandProtein(renderedInteractor); - }); - } - - menuListSel.append("li").text("Open in UniProt").on("click", () => { - window.open("https://www.uniprot.org/uniprotkb?query=" + renderedInteractor.participant.accession); - }); - - menuListSel.append("li").text("Set Protein Colour").on("click", () => { - //todo: set protein colour for all selected proteins? - this.model.chooseInteractorColor(renderedInteractor.participant.id); - d3__WEBPACK_IMPORTED_MODULE_1__.select(".xinet-context-menu").style("display", "none"); - }); - - if (proteinColourModel instanceof _xiview_js_model_color_protein_color_model__WEBPACK_IMPORTED_MODULE_12__.ManualColourModel) { - if (proteinColourModel.hasManualAssignment(renderedInteractor.participant.id)) { - menuListSel.append("li").text("Remove Protein Colour").on("click", () => { - proteinColourModel.removeManualAssignment(renderedInteractor.participant.id); - this.model.trigger("currentProteinColourModelChanged", proteinColourModel); - d3__WEBPACK_IMPORTED_MODULE_1__.select(".xinet-context-menu").style("display", "none"); - }); - } - } - - for (let pg of renderedInteractor.parentGroups) { - menuListSel.append("li").text("Remove from group " + pg.name) - .attr("data-group", pg.name).attr("data-protein", renderedInteractor.participant.id) - .node().onclick = function (evt) { //on("click", function (evt) { - const protien = evt.target.getAttribute("data-protein"); - const group = evt.target.getAttribute("data-group"); - console.log("remove protein " + protien + " from group " + group); - d3__WEBPACK_IMPORTED_MODULE_1__.select(".xinet-context-menu").style("display", "none"); - self.contextMenuParticipant.highlighted = false; - self.model.removeProteinFromGroup(group, protien); - }; - } - - } else { // group - if (renderedInteractor.expanded) { - if (renderedInteractor.isOverlappingGroup()) { - menuListSel.append("li").text("Can't collapse overlapping groups").on("click", () => { - this.cantCollapseGroup(); //does nothing - d3__WEBPACK_IMPORTED_MODULE_1__.select(".xinet-context-menu").style("display", "none"); - }); - // menuListSel.append("li").text("Enclose Overlapping Groups").on("click", () => { - // alert("enclose overlapping groups not implemented yet"); - // }); - } else { - menuListSel.append("li").text("Collapse Group").on("click", () => { - this.collapseInteractor(renderedInteractor); - }); - } - // menuListSel.append("li").text("Autolayout Group").on("click", () => { - // this.autoLayoutGroup(renderedInteractor, []); - // d3.select(".xinet-context-menu").style("display", "none"); - // }); - } else { - menuListSel.append("li").text("Expand Group").on("click", () => { - renderedInteractor.setExpanded(true, this.getEventPoint(evt)); - d3__WEBPACK_IMPORTED_MODULE_1__.select(".xinet-context-menu").style("display", "none"); - }); - } - - menuListSel.append("li").text("Ungroup").on("click", () => { - this.ungroup(renderedInteractor); - d3__WEBPACK_IMPORTED_MODULE_1__.select(".xinet-context-menu").style("display", "none"); - }); - - menuListSel.append("li").text("Set Group Colour").on("click", () => { - this.model.chooseInteractorColor(renderedInteractor.id); - d3__WEBPACK_IMPORTED_MODULE_1__.select(".xinet-context-menu").style("display", "none"); - }); - - if (proteinColourModel instanceof _xiview_js_model_color_protein_color_model__WEBPACK_IMPORTED_MODULE_12__.ManualColourModel) { - if (proteinColourModel.hasManualAssignment(renderedInteractor.id)) { - menuListSel.append("li").text("Remove Group Colour").on("click", () => { - proteinColourModel.removeManualAssignment(renderedInteractor.id); - this.model.trigger("currentProteinColourModelChanged", proteinColourModel); - d3__WEBPACK_IMPORTED_MODULE_1__.select(".xinet-context-menu").style("display", "none"); - }); - } - } - } - - //keep menu on screen - const width = this.svgElement.parentNode.clientWidth; - const height = this.svgElement.parentNode.clientHeight; - const pageX = evt.pageX; - const pageY = evt.pageY - 37; //todo: hacky, 37 is height of top bar - const menu = d3__WEBPACK_IMPORTED_MODULE_1__.select(".xinet-context-menu"); - menu.style("display", "block"); - const menuWidth = menu.node().getBoundingClientRect().width; - const menuHeight = menu.node().getBoundingClientRect().height; - console.log("menuWidth: " + menuWidth, "menuHeight: " + menuHeight); - const mouseOffset = 20; - const x = pageX + mouseOffset + menuWidth > width ? pageX - mouseOffset - menuWidth : pageX + mouseOffset; - const y = pageY + mouseOffset + menuHeight > height ? pageY - mouseOffset - menuHeight : pageY + mouseOffset; - menu.style("top", y + "px").style("left", x + "px"); - } - - mouseWheel(evt) { - this.preventDefaultsAndStopPropagation(evt); - this.d3cola.stop(); - let delta; - //see http://stackoverflow.com/questions/5527601/normalizing-mousewheel-speed-across-browsers - // noinspection JSUnresolvedVariable - if (evt.wheelDelta) { - delta = evt.wheelDelta / 3600; // Chrome/Safari - } else { - delta = evt.detail / -90; // Mozilla - } - const z = 1 + delta; - const g = this.container; - const p = this.getEventPoint(evt); - const c = p.matrixTransform(g.getCTM().inverse()); - const k = this.svgElement.createSVGMatrix().translate(c.x, c.y).scale(z).translate(-c.x, -c.y); - this.setCTM(g, g.getCTM().multiply(k)); - this.scale(); - return false; - } - - mouseOut() { //todo - // don't, causes problem's - RenderedInteractor mouseOut getting propagated? - // d3.select(".custom-menu-margin").style("display", "none"); - // d3.select(".group-custom-menu-margin").style("display", "none"); - } - - getEventPoint(evt) { - const p = this.svgElement.createSVGPoint(); - let element = this.svgElement.parentNode; - let top = 0, - left = 0; - do { - top += element.offsetTop || 0; - left += element.offsetLeft || 0; - element = element.offsetParent; - } while (element); - p.x = evt.clientX - left; //crossBrowserElementX(evt);//, this.svgElement); - p.y = evt.clientY - top; //crossBrowserElementY(evt);//, this.svgElement); - return p; - } - - //stop event propagation and defaults; only do what we ask - preventDefaultsAndStopPropagation(evt) { - if (evt.stopPropagation) - evt.stopPropagation(); - if (evt.cancelBubble != null) - evt.cancelBubble = true; - if (evt.preventDefault) - evt.preventDefault(); - } - -} - -CrosslinkViewer.removeDomElement = function (child) { - if (child && child.parentNode) { - child.parentNode.removeChild(child); - } -}; - -CrosslinkViewer.svgns = "http://www.w3.org/2000/svg"; // namespace for svg elements -CrosslinkViewer.linkWidth = 1.7; // default line width -//static values signifying Controller's status -CrosslinkViewer.STATES = { - MOUSE_UP: 0, - SELECT_PAN: 1, - DRAGGING: 2, - ROTATING: 3 -}; - -CrosslinkViewer.barScales = [0.01, 0.2, 0.5, 0.8, 1, 2, 4, 8]; - - -/***/ }), - -/***/ "./crosslink-viewer/js/views/xinet/interactor/group.js": -/*!*************************************************************!*\ - !*** ./crosslink-viewer/js/views/xinet/interactor/group.js ***! - \*************************************************************/ -/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { - -"use strict"; -__webpack_require__.r(__webpack_exports__); -/* harmony export */ __webpack_require__.d(__webpack_exports__, { -/* harmony export */ Group: () => (/* binding */ Group) -/* harmony export */ }); -/* harmony import */ var d3__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! d3 */ "./node_modules/d3/d3.js"); -/* harmony import */ var d3__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(d3__WEBPACK_IMPORTED_MODULE_0__); -/* harmony import */ var _interactor__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./interactor */ "./crosslink-viewer/js/views/xinet/interactor/interactor.js"); -/* harmony import */ var _crosslink_viewer_BB__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../crosslink-viewer-BB */ "./crosslink-viewer/js/views/xinet/crosslink-viewer-BB.js"); -/* harmony import */ var _xiview_js_make_tooltip__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../../../../../xiview/js/make-tooltip */ "./xiview/js/make-tooltip.js"); -/* harmony import */ var _rendered_protein__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./rendered-protein */ "./crosslink-viewer/js/views/xinet/interactor/rendered-protein.js"); - - - - - - -class Group extends _interactor__WEBPACK_IMPORTED_MODULE_1__.Interactor { - constructor(id, participantIds, controller) { - super(controller); - - this._id = id; - this.name = id; - - this.renderedParticipants = []; - for (let pId of participantIds) { - const p = this.controller.renderedProteins.get(pId); - if (p) { // no decoys in this.controller.renderedProteins - this.renderedParticipants.push(p); - } - } - this.parentGroups = new Set(); - this.subgroups = []; - - this.expanded = true; - this.hidden = false; - this.type = "group"; - - this.padding = 45; // used by cola.js - - this.upperGroup = document.createElementNS(_crosslink_viewer_BB__WEBPACK_IMPORTED_MODULE_2__.CrosslinkViewer.svgns, "g"); - this.upperGroup.setAttribute("class", "protein upperGroup"); - - //make highlight - this.highlight = document.createElementNS(_crosslink_viewer_BB__WEBPACK_IMPORTED_MODULE_2__.CrosslinkViewer.svgns, "rect"); - this.highlight.setAttribute("class", "highlightedProtein"); - this.highlight.setAttribute("stroke-width", "3"); - this.highlight.setAttribute("fill", "none"); - this.highlight.setAttribute("stroke-opacity", "0"); - - //create label - we will move this svg element around when expand / collapse - this.labelSVG = document.createElementNS(_crosslink_viewer_BB__WEBPACK_IMPORTED_MODULE_2__.CrosslinkViewer.svgns, "text"); - this.labelSVG.setAttribute("fill", "black"); - this.labelSVG.setAttribute("x", "0"); - this.labelSVG.setAttribute("y", "0"); - this.labelSVG.setAttribute("class", "xlv_text proteinLabel"); - this.labelSVG.setAttribute("text-decoration", "underline"); - this.labelText = this.name; - this.labelTextNode = document.createTextNode(this.labelText); - this.labelSVG.appendChild(this.labelTextNode); - - //make blob - this.outline = document.createElementNS(_crosslink_viewer_BB__WEBPACK_IMPORTED_MODULE_2__.CrosslinkViewer.svgns, "rect"); - this.outline.setAttribute("stroke", "white"); - this.outline.setAttribute("stroke-width", "3"); - this.outline.setAttribute("stroke-opacity", "1"); - this.outline.setAttribute("fill-opacity", "0.5"); - this.outline.setAttribute("fill", "#cccccc"); - - this.upperGroup.appendChild(this.outline); - this.upperGroup.appendChild(this.highlight); - this.upperGroup.appendChild(this.labelSVG); - - //need to change this if default is unexpanded - this.controller.groupsSVG.appendChild(this.upperGroup); - - const self = this; - // this.upperGroup.setAttribute('pointer-events','all'); - this.upperGroup.onmousedown = function (evt) { - self.mouseDown(evt); - }; - this.upperGroup.onmouseover = function (evt) { - self.mouseOver(evt); - }; - this.upperGroup.onmouseout = function (evt) { - self.mouseOut(evt); - }; - } - - get id () { - return this._id; - } - - set id (id){ - this._id = id; - } - - get proteins () { - const proteins = []; - for (let renderedParticipant of this.renderedParticipants) { - proteins.push(renderedParticipant.participant); - } - return proteins; - } - - get width() { - // return 60; - const approxLabelWidth = 10 * (this.labelText.length + 2); - return (approxLabelWidth > this.symbolRadius) ? approxLabelWidth : this.symbolRadius + 20; - } - - get height () { - return 60; - } - - get bBox () { - return this.upperGroup.getBBox(); - // let x1 = 0, y1 = 0, x2 = 0, y2 = 0; - // const z = this.controller.z;//, pad = 5 * z; - // - // for (let rp of this.renderedParticipants) { - // if (!rp.hidden && !this.containsInSubgroup(rp)) { - // const rpBbox = rp.bBox; - // if (!x1 || (rpBbox.x * z) + rp.ix < x1) { - // x1 = (rpBbox.x * z) + rp.ix; - // } - // if (!y1 || (rpBbox.y * z) + rp.iy < y1) { - // y1 = (rpBbox.y * z) + rp.iy; - // } - // if (!x2 || ((rpBbox.x + rpBbox.width) * z) + rp.ix > x2) { - // x2 = ((rpBbox.x + rpBbox.width) * z) + rp.ix; - // } - // if (!y2 || ((rpBbox.y + rpBbox.height) * z) + rp.iy > y2) { - // y2 = ((rpBbox.y + rpBbox.height) * z) + rp.iy; - // } - // } - // } - // - // const w = x2 - x1, h = y2 -y1; - // - // return { - // x: x1, - // y: y1, - // width: w, - // height: h - // }; - } - - //only output the info needed to reproduce the layout, used by save layout function - toJSON() { - const participantIds = []; - for (let rp of this.renderedParticipants) { - participantIds.push(rp.participant.id); - } - return { - id: this.id, - x: this.ix, - y: this.iy, - expanded: this.expanded, - participantIds: participantIds - }; - } - - get unhiddenParticipantCount () { - let count = 0; - for (let renderedParticipant of this.renderedParticipants) { - if (!renderedParticipant.participant.hidden) { - count++; - } - } - return count; - } - - get selected () { - const selectedProteins = this.controller.model.get("selectedProteins"); - for (let rp of this.renderedParticipants) { - if (selectedProteins.indexOf(rp.participant) === -1) { - return false; - } - } - return true; - } - - set selected (selected) { - super.selected = selected; - if (selected) { - this.outline.setAttribute("stroke", "none"); - } else { - this.outline.setAttribute("stroke", "white"); - } - } - - set highlighted (highlight) { - super.highlighted = highlight; - if (highlight) { - this.outline.setAttribute("stroke", "none"); - } else { - this.outline.setAttribute("stroke", "white"); - } - } - - // result depends on whats hidden - isSubsetOf(anotherGroup) { - for (let renderedParticipant of this.renderedParticipants) { - if (!renderedParticipant.participant.hidden && anotherGroup.renderedParticipants.indexOf(renderedParticipant) === -1) { - return false; - } - } - return true; - } - - contains(renderedProtein) { - for (let rp of this.renderedParticipants) { - if (rp === renderedProtein) { - return true; - } - } - return false; - } - - containsInSubgroup(renderedProtein) { - for (let subgroup of this.subgroups) { - if (subgroup.contains(renderedProtein)) { - return true; - } - } - return false; - } - - isOverlappingGroup() { - for (let renderedParticipant of this.renderedParticipants) { - if (!renderedParticipant.participant.hidden && renderedParticipant.parentGroups.size > 1) { - for (let parentGroup of renderedParticipant.parentGroups) { - if (!parentGroup.isSubsetOf(this) && !this.isSubsetOf(parentGroup)) { - return true; - } - } - } - } - for (let subgroup of this.subgroups) { - if (!subgroup.hidden && subgroup.parentGroups.size > 1) { - for (let subgroupParentGroup of subgroup.parentGroups) { - if (!subgroupParentGroup.isSubsetOf(this) && !this.isSubsetOf(subgroupParentGroup)) { - return true; - } - } - } - } - return false; - } - - init() { - this.controller.groupsSVG.appendChild(this.upperGroup); - this.setExpanded(this.expanded); - } - - mouseDown(evt) { - this.controller.d3cola.stop(); - this.controller.dragElement = this; - this.controller.dragStart = evt; - this.controller.mouseMoved = false; - return false; - } - - mouseOver(evt) { - // this.showHighlight(true); - const toHighlight = []; - for (let rp of this.renderedParticipants) { - toHighlight.push(rp.participant); - } - this.controller.model.setHighlightedProteins(toHighlight); - //call in super? - const p = this.controller.getEventPoint(evt); - this.controller.model.get("tooltipModel") - .set("header", _xiview_js_make_tooltip__WEBPACK_IMPORTED_MODULE_3__.makeTooltipTitle.complex(this)) - .set("contents", _xiview_js_make_tooltip__WEBPACK_IMPORTED_MODULE_3__.makeTooltipContents.complex(this)) - .set("location", { - pageX: p.x, - pageY: p.y - }); - } - - // mouseOut(evt) { - // this.highlighted = false; - // Interactor.prototype.mouseOut.call(this, evt); - // } - - getAverageParticipantPosition() { - let xSum = 0, - ySum = 0; - const rpCount = this.renderedParticipants.length; - for (let rp of this.renderedParticipants) { - xSum += rp.ix; - ySum += rp.iy; - } - return [xSum / rpCount, ySum / rpCount]; - } - - /* leave this.x and this.y as they were set by cola, - calculate centre of interactor's glyph, - call setPosition with those - */ - setPositionFromCola() { - this.px = this.x; - this.py = this.y; - // let xOffset = 0; - // if (!this.hidden) { // todo - hacky - // xOffset = (this.width / 20); // - (this.getBlobRadius()) + 5) - // // if (this.expanded) { - // // xOffset = xOffset + (this.participant.size / 2 * this.stickZoom ); - // // } - // } - this.setPosition(this.x /*- xOffset*/, this.y); - } - - /* calculate top left of interactor's glyph, - set this.x and this.y as cola would have them, - call setPosition with same params this received - */ - setPositionFromXinet(ix, iy) { - this.px = this.x; - this.py = this.y; - let xOffset = 0; - if (!this.hidden) { // todo - hacky - xOffset = (this.width / 2); // - (this.getBlobRadius()) + 5) - // if (this.expanded) { - // xOffset = xOffset + (this.participant.size / 2 * this.stickZoom ); - // } - } - this.x = ix - xOffset; - this.y = iy; - this.setPosition(ix, iy); - } - - //also setting size of collapsed group symbol; scaling line widths, corner radii - setPosition(ix, iy) { //todo - array for coordinate param? - if (!this.expanded) { - this.ix = ix; - this.iy = iy; - const symbolWidth = 20; - const x = this.ix - (symbolWidth * this.controller.z); - const y = this.iy - (symbolWidth * this.controller.z); - const scaledWidth = 2 * (symbolWidth * this.controller.z); - const cornerRadii = 5 * this.controller.z; - - const updateOutline = function (svgElement) { - if (!x){ - console.log("!x"); - } - - svgElement.setAttribute("x", x); - svgElement.setAttribute("y", y); - svgElement.setAttribute("width", scaledWidth); - svgElement.setAttribute("height", scaledWidth); - svgElement.setAttribute("rx", cornerRadii); - svgElement.setAttribute("ry", cornerRadii); - }; - - updateOutline(this.outline); - // noinspection JSCheckFunctionSignatures - this.outline.setAttribute("stroke-width", 3 * this.controller.z); - - updateOutline(this.highlight); - this.highlight.setAttribute("stroke-width", 9 * this.controller.z); - - this.labelSVG.setAttribute("transform", "translate(" + this.ix + " " + this.iy + ")" + - " scale(" + (this.controller.z) + ")"); - - for (let group of this.parentGroups) { - if (group.expanded && !this.hidden) { - group.updateExpandedGroup(); - } - } - for (let ggLink of this.controller.g_gLinks.values()) { - ggLink.setLineCoordinates(); - } - if (this.selfLink != null) { - if (typeof this.selfLink.thickLine !== "undefined") { - this.selfLink.thickLine.setAttribute("transform", "translate(" + this.ix + - " " + this.iy + ")" + " scale(" + (this.controller.z) + ")"); - } - this.selfLink.line.setAttribute("transform", "translate(" + this.ix + - " " + this.iy + ")" + " scale(" + (this.controller.z) + ")"); - this.selfLink.highlightLine.setAttribute("transform", "translate(" + this.ix + - " " + this.iy + ")" + " scale(" + (this.controller.z) + ")"); - } - - } else { - console.log("error - calling setPosition on unexpanded Group"); - } - } - - updateExpandedGroup() { - let x1 = 0, y1 = 0, x2 = 0, y2 = 0; - const z = this.controller.z, pad = 5 * z; - - for (let rp of this.renderedParticipants) { - if (!rp.hidden && !this.containsInSubgroup(rp)) { - const rpBbox = rp.bBox; - if (!x1 || (rpBbox.x * z) + rp.ix < x1) { - x1 = (rpBbox.x * z) + rp.ix; - } - if (!y1 || (rpBbox.y * z) + rp.iy < y1) { - y1 = (rpBbox.y * z) + rp.iy; - } - if (!x2 || ((rpBbox.x + rpBbox.width) * z) + rp.ix > x2) { - x2 = ((rpBbox.x + rpBbox.width) * z) + rp.ix; - } - if (!y2 || ((rpBbox.y + rpBbox.height) * z) + rp.iy > y2) { - y2 = ((rpBbox.y + rpBbox.height) * z) + rp.iy; - } - } - } - - for (let sg of this.subgroups) { - if (!sg.hidden) { - const sgBbox = sg.bBox; - if (!x1 || (sgBbox.x) < x1) { - x1 = (sgBbox.x); - } - if (!y1 || (sgBbox.y) < y1) { - y1 = (sgBbox.y); - } - if (!x2 || ((sgBbox.x + sgBbox.width)) > x2) { - x2 = ((sgBbox.x + sgBbox.width)); - } - if (!y2 || ((sgBbox.y + sgBbox.height)) > y2) { - y2 = ((sgBbox.y + sgBbox.height)); - } - } - } - - const updateOutline = function (svgElement) { - svgElement.setAttribute("x", x1 - pad); - svgElement.setAttribute("y", y1 - pad); - svgElement.setAttribute("width", x2 - x1 + (2 * pad)); - svgElement.setAttribute("height", y2 - y1 + (2 * pad)); - svgElement.setAttribute("rx", pad); - svgElement.setAttribute("ry", pad); - }; - - updateOutline(this.outline); - // noinspection JSCheckFunctionSignatures - this.outline.setAttribute("stroke-width", 3 * this.controller.z); - - updateOutline(this.highlight); - this.highlight.setAttribute("stroke-width", 9 * this.controller.z); - - //move label - this.labelSVG.setAttribute("transform", "translate(" + (x1 - pad) + " " + (y1 - pad) + ")" + - " scale(" + (this.controller.z) + ")"); - - for (let group of this.parentGroups) { - if (group.expanded && !this.hidden) { - group.updateExpandedGroup(); - } - } - } - - setColour(colour) { - if (colour === "#FFFFFF") colour = "#CCCCCC"; - this.outline.setAttribute("fill", colour); - } - - setHidden(bool) { // todo: make this a property? - d3__WEBPACK_IMPORTED_MODULE_0___default().select(this.upperGroup).style("display", bool ? "none" : null); - d3__WEBPACK_IMPORTED_MODULE_0___default().select(this.labelSVG).style("display", bool ? "none" : null); - this.hidden = !!bool; - } - - // updateHighlight() { - // if (this.expanded) { - // let someHighlighted = false, allHighlighted = true; - // for (let rp of this.renderedParticipants) { - // if (!rp.hidden) { - // if (rp.isHighlighted) { - // someHighlighted = true; - // } else { - // allHighlighted = false; - // } - // } - // } - // if (someHighlighted) { - // if (!allHighlighted) { - // this.dashedOutline(true); - // } else { - // this.dashedOutline(false); - // } - // this.showHighlight(true); - // } else { - // this.dashedOutline(false); - // this.showHighlight(false); - // this.updateSelected(); - // } - // } - // } - - updateSelected() { - let someSelected = false, allSelected = true; - for (let rp of this.renderedParticipants) { - if (rp.selected) { - someSelected = true; - } else { - allSelected = false; - } - } - if (someSelected) { - this.dashed = !allSelected; - this.selected = true; - } else { - this.selected = false; - } - } - - set dashed(dash) { - if (dash){// && !this._dashed) { - this.highlight.setAttribute("stroke-dasharray", (8 * this.controller.z) + ", " + (8 * this.controller.z)); - } else if (!dash){//} && this._dashed) { - this.highlight.removeAttribute("stroke-dasharray"); - } - this._dashed = !!dash; - } - - updateCountLabel() { - this.labelSVG.innerHTML = this.labelText + " ("+ this.unhiddenParticipantCount + ")"; - } - - setExpanded(expanded, svgP) { - this.controller.model.get("tooltipModel").set("contents", null); - if (this.busy !== true) { - if (this.isOverlappingGroup()) { - console.error("overlapping group", this.id); - expanded = true; - } - if (expanded) { - if (this.expanded !== expanded) { - this.expand(); - } - } else { - if (this.expanded !== expanded) { - this.collapse(svgP); - } - } - } - } - - collapse(svgP, transition = true) { - // transition = false; - if (this.isOverlappingGroup()) { - console.error("overlapping group", this.id); - this.expand(false); - return; - } - let newX, newY; - if (svgP) { - newX = svgP.x; - newY = svgP.y; - } else { - const avPos = this.getAverageParticipantPosition(); - newX = avPos[0]; - newY = avPos[1]; - } - - const originalProteinPositions = []; // will reset positions after transition - const originalCollapsedSubgroupPositions = []; // will reset positions after transition - const proteinXPositionInterpolations = []; - const proteinYPositionInterpolations = []; - const collapsedSubgroupXPositionInterpolations = []; - const collapsedSubgroupYPositionInterpolations = []; - const cubicInOut = d3__WEBPACK_IMPORTED_MODULE_0___default().ease("cubic-in-out"); - this.busy = true; - const self = this; - - if (transition) { - for (let rp of this.renderedParticipants) { - originalProteinPositions.push([rp.ix, rp.iy]); - proteinXPositionInterpolations.push(d3__WEBPACK_IMPORTED_MODULE_0___default().interpolate(rp.ix, newX)); - proteinYPositionInterpolations.push(d3__WEBPACK_IMPORTED_MODULE_0___default().interpolate(rp.iy, newY)); - } - - for (let sg of this.subgroups) { - // if (!sg.expanded) { - originalCollapsedSubgroupPositions.push([sg.ix, sg.iy]); - collapsedSubgroupXPositionInterpolations.push(d3__WEBPACK_IMPORTED_MODULE_0___default().interpolate(sg.ix, newX)); - collapsedSubgroupYPositionInterpolations.push(d3__WEBPACK_IMPORTED_MODULE_0___default().interpolate(sg.iy, newY)); - // } - } - - d3__WEBPACK_IMPORTED_MODULE_0___default().timer(function (elapsed) { - return updateCollapsing(elapsed / (_rendered_protein__WEBPACK_IMPORTED_MODULE_4__.RenderedProtein.transitionTime * 2)); - }); - - } else { - updateCollapsing(1); - } - - function updateCollapsing(interp) { - if (interp === 1) { // finished - tidy up - self.expanded = false; - self.setPositionFromXinet(newX, newY); - - for (let i = 0; i < self.renderedParticipants.length; i++) { - const rp = self.renderedParticipants[i]; - rp.setHidden(true); - if (transition){ - rp.setPositionFromXinet(originalProteinPositions[i][0], originalProteinPositions[i][1]); - } - // rp.setAllLinkCoordinates(); - } - - for (let i = 0; i < self.subgroups.length; i++) { - const sg = self.subgroups[i]; - // if (!sg.expanded) { - if (transition){ - sg.setPositionFromXinet(originalCollapsedSubgroupPositions[i][0], originalCollapsedSubgroupPositions[i][1]); - } - // } - } - self.labelSVG.setAttribute("dominant-baseline", "central"); - self.labelSVG.setAttribute("text-anchor", "middle"); - self.hideSubgroups(); - self.controller.proteinUpper.appendChild(self.upperGroup); - self.outline.setAttribute("fill-opacity", "1"); - if (transition) { - self.controller.hiddenProteinsChanged(); - self.controller.render(); - } - self.busy = false; - return true; - } else if (interp > 1 || isNaN(interp)) { - return updateCollapsing(1); - } else { - for (let i = 0; i < self.renderedParticipants.length; i++) { - const rp = self.renderedParticipants[i]; - const x = proteinXPositionInterpolations[i](cubicInOut(interp)); - const y = proteinYPositionInterpolations[i](cubicInOut(interp)); - rp.setPositionFromXinet(x, y); - rp.setAllLinkCoordinates(); - } - - for (let i = 0; i < self.subgroups.length; i++) { - const sg = self.subgroups[i]; - if (!sg.expanded) { - const x = collapsedSubgroupXPositionInterpolations[i](cubicInOut(interp)); - const y = collapsedSubgroupYPositionInterpolations[i](cubicInOut(interp)); - sg.setPositionFromXinet(x, y); - } - } - self.updateExpandedGroup(); - return false; - } - } - } - - expand(transition = true) { - // transition = false; - this.busy = true; - const self = this; - - this.expanded = true; - // if (transition) { // yucky, transition is being used to indicate whether this is one interactor collapsing or from 'Collapse All' - // this.controller.render(); - // } - - const proteinXPositionInterpolations = []; - const proteinYPositionInterpolations = []; - const collapsedSubgroupXPositionInterpolations = []; - const collapsedSubgroupYPositionInterpolations = []; - - const cubicInOut = d3__WEBPACK_IMPORTED_MODULE_0___default().ease("cubic-out"); - - // this.labelSVG.setAttribute("dominant-baseline", null); - // this.labelSVG.setAttribute("text-anchor", null); - // this.showSubgroups(); - // this.controller.groupsSVG.appendChild(this.upperGroup); - // this.outline.setAttribute("fill-opacity", "0.5"); - // - // for (let rp of this.renderedParticipants) { - // rp.setHidden(rp.participant.hidden || rp.inCollapsedGroup()); - // } - - const tl = this.controller.svgElement.createSVGPoint(); - tl.x = 0; - tl.y =0; - const br = this.controller.svgElement.createSVGPoint(); - const width = this.controller.svgElement.parentNode.clientWidth; - const height = this.controller.svgElement.parentNode.clientHeight; - br.x = width; - br.y = height; - const topLeft = tl.matrixTransform(this.controller.container.getCTM().inverse()); - const bottomRight = br.matrixTransform(this.controller.container.getCTM().inverse()); - - //bbox of the expanded group (before moving it on screen if necessary) - let bboxTL = this.controller.svgElement.createSVGPoint(); - let bboxBR = this.controller.svgElement.createSVGPoint(); - - // decide on new positions for proteins and collapsed subgroups - if (transition) { // only if transition (not if no position, i.e. from saved layout) - let ix = this.ix, iy = this.iy; - if (!ix) { // todo? um, check why this can be undefined (is it when loading from saved layout) - const pPos = this.getAverageParticipantPosition(); - ix = pPos[0]; - iy = pPos[1]; - } - - this.controller.hiddenProteinsChanged(); //needed for isOnScreen() to work - - let allOnScreen = true; - for (let rp of this.renderedParticipants) { - if (!isOnScreen(rp)) { - allOnScreen = false; - // can't break here because we need to get the bbox of the expanded group - } - } - - for (let sg of this.subgroups) { - if (!sg.expanded) { - if (!isOnScreen(sg)) { - allOnScreen = false; - // can't break here because we need to get the bbox of the expanded group - } - } - } - - if (allOnScreen) { - for (let rp of this.renderedParticipants) { - proteinXPositionInterpolations.push(d3__WEBPACK_IMPORTED_MODULE_0___default().interpolate(ix, rp.ix)); - proteinYPositionInterpolations.push(d3__WEBPACK_IMPORTED_MODULE_0___default().interpolate(iy, rp.iy)); - } - for (let sg of this.subgroups) { - // if (!sg.expanded) { - collapsedSubgroupXPositionInterpolations.push(d3__WEBPACK_IMPORTED_MODULE_0___default().interpolate(ix, sg.ix)); - collapsedSubgroupYPositionInterpolations.push(d3__WEBPACK_IMPORTED_MODULE_0___default().interpolate(iy, sg.iy)); - // } - } - } else { - // alert("not all on screen"); - console.log("not all on screen", bboxTL, bboxBR); - - - //scale? - const bboxWidth = (bboxBR.x - bboxTL.x); - const bboxHeight = bboxBR.y - bboxTL.y; - const preferredWidth = (width / 2) * this.controller.z; - const preferredHeight = (height / 2) * this.controller.z; - let xScale, yScale, scale = 1; - if (bboxWidth > (width * this.controller.z) || bboxHeight > (height * this.controller.z)) { - if (bboxWidth > preferredWidth) { - xScale = preferredWidth / bboxWidth; - } - if (bboxHeight > preferredHeight) { - yScale = preferredHeight / bboxHeight; - } - scale = Math.min(xScale, yScale); - console.log("SCALE!!", scale); - //bbox is that of the expanded group - - const bboxMidPoint = {};//= this.controller.svgElement.createSVGPoint(); - - bboxMidPoint.x = (bboxTL.x + bboxBR.x) / 2; - bboxMidPoint.y = (bboxTL.y + bboxBR.y) / 2; - - const xTrans = ix - bboxMidPoint.x; - const yTrans = iy - bboxMidPoint.y; - - for (let rp of this.renderedParticipants) { - const dx = rp.ix + xTrans - bboxMidPoint.x; - const dy = rp.iy + yTrans - bboxMidPoint.y; - // const dx = rp.ix + (ix - bboxMidPoint.x) - bboxMidPoint.x; - // = rp.ix + ix - 2 * bboxMidPoint.x; - proteinXPositionInterpolations.push(d3__WEBPACK_IMPORTED_MODULE_0___default().interpolate(ix, ix + (dx * scale))); - proteinYPositionInterpolations.push(d3__WEBPACK_IMPORTED_MODULE_0___default().interpolate(iy, iy + (dy * scale))); - } - for (let sg of this.subgroups) { - // if (!sg.expanded) { - const dx = sg.ix + xTrans - bboxMidPoint.x; - const dy = sg.iy + yTrans - bboxMidPoint.y; - - collapsedSubgroupXPositionInterpolations.push(d3__WEBPACK_IMPORTED_MODULE_0___default().interpolate(ix, ix + (dx * scale))); - collapsedSubgroupYPositionInterpolations.push(d3__WEBPACK_IMPORTED_MODULE_0___default().interpolate(iy, iy + (dy * scale))); - // } - } - } else { - //bbox is that of the expanded group - - const bboxMidPoint = {};//= this.controller.svgElement.createSVGPoint(); - - bboxMidPoint.x = (bboxTL.x + bboxBR.x) / 2; - bboxMidPoint.y = (bboxTL.y + bboxBR.y) / 2; - - const xTrans = ix - bboxMidPoint.x; - const yTrans = iy - bboxMidPoint.y; - - for (let rp of this.renderedParticipants) { - proteinXPositionInterpolations.push(d3__WEBPACK_IMPORTED_MODULE_0___default().interpolate(ix, rp.ix + xTrans)); - proteinYPositionInterpolations.push(d3__WEBPACK_IMPORTED_MODULE_0___default().interpolate(iy, rp.iy + yTrans)); - } - for (let sg of this.subgroups) { - // if (!sg.expanded) { - collapsedSubgroupXPositionInterpolations.push(d3__WEBPACK_IMPORTED_MODULE_0___default().interpolate(ix, sg.ix + xTrans)); - collapsedSubgroupYPositionInterpolations.push(d3__WEBPACK_IMPORTED_MODULE_0___default().interpolate(iy, sg.iy + yTrans)); - // } - } - } - } - - //move all prots / subgroups to - for (let rp of this.renderedParticipants) { - if (!rp.hidden){ - rp.setPositionFromXinet(ix, iy); - } - } - for (let sg of this.subgroups) { - if (!sg.hidden) { - sg.setPositionFromXinet(ix, iy); - } - } - - // this.expanded = true; - this.labelSVG.setAttribute("dominant-baseline", null); - this.labelSVG.setAttribute("text-anchor", null); - - this.showSubgroups(); - - this.controller.groupsSVG.appendChild(this.upperGroup); - this.outline.setAttribute("fill-opacity", "0.5"); - - for (let rp of this.renderedParticipants) { - rp.setHidden(rp.participant.hidden || rp.inCollapsedGroup()); - } - - if (transition) { // yucky, transition is being used to indicate whether this is one interactor collapsing or from 'Collapse All' - this.controller.render(); - } - - d3__WEBPACK_IMPORTED_MODULE_0___default().timer(function (elapsed) { - return updateExpanding(elapsed / (_rendered_protein__WEBPACK_IMPORTED_MODULE_4__.RenderedProtein.transitionTime * 2)); - }); - } else { - updateExpanding(1); - } - - function isOnScreen(interactor){ - if (!interactor.hidden) { - // console.log("TESTING", interactor); - if (!bboxTL.x || interactor.ix < bboxTL.x) { - bboxTL.x = interactor.ix; - // console.log("SETTING BBOX TL X", bboxTL.x); - } - if (!bboxTL.y || interactor.iy < bboxTL.y) { - bboxTL.y = interactor.iy; - // console.log("SETTING BBOX TL Y", bboxTL.y); - } - if (!bboxBR.x || interactor.ix > bboxBR.x) { - bboxBR.x = interactor.ix; - // console.log("SETTING BBOX BR X", bboxBR.x); - } - if (!bboxBR.y || interactor.iy > bboxBR.y) { - bboxBR.y = interactor.iy; - // console.log("SETTING BBOX BR Y", bboxBR.y); - } - } - return interactor.ix > topLeft.x && interactor.ix < bottomRight.x && interactor.iy > topLeft.y && interactor.iy < bottomRight.y; - } - - function updateExpanding(interp) { - if (interp === 1) { // finished - tidy up - self.updateExpandedGroup(); - if (transition) { // yucky, transition is being used to indicate whether this is one interactor collapsing or from 'Collapse All' - self.controller.hiddenProteinsChanged(); - self.controller.render(); - } - self.busy = false; - return true; - } else if (interp > 1 || isNaN(interp)) { - return updateExpanding(1); - } else { - for (let i = 0; i < self.renderedParticipants.length; i++) { - const rp = self.renderedParticipants[i]; - const x = proteinXPositionInterpolations[i](cubicInOut(interp)); - const y = proteinYPositionInterpolations[i](cubicInOut(interp)); - rp.setPosition(x, y); - rp.setAllLinkCoordinates(); - } - - for (let i = 0; i < self.subgroups.length; i++) { - const sg = self.subgroups[i]; - if (!sg.expanded) { - const x = collapsedSubgroupXPositionInterpolations[i](cubicInOut(interp)); - const y = collapsedSubgroupYPositionInterpolations[i](cubicInOut(interp)); - sg.setPosition(x, y); - } else { - sg.updateExpandedGroup(); - } - } - - self.updateExpandedGroup(); - return false; - } - } - } - - hideSubgroups() { - for (let subgroup of this.subgroups) { - subgroup.setHidden(true); - } - } - - showSubgroups() { - for (let subgroup of this.subgroups) { - if (!subgroup.inCollapsedGroup()) { - subgroup.setHidden(false); - } - } - } - - // update all lines (e.g after a move) - setAllLinkCoordinates() { - for (let rp of this.renderedParticipants) { - rp.setAllLinkCoordinates(); - } - } - - // addConnectedNodes (subgraph) { - // for (let p of this.renderedParticipants) { - // for (let link of p.renderedP_PLinks.values()) { - // //visible, non-self links only - // if (link.renderedFromProtein !== link.renderedToProtein && link.isPassingFilter()) { - // if (!subgraph.links.has(link.id)) { - // subgraph.links.set(link.id, link); - // let otherEnd; - // if (link.renderedFromProtein === this) { - // otherEnd = link.renderedToProtein; - // } else { - // otherEnd = link.renderedFromProtein; - // } - // // if (otherEnd !== null) { - // const renderedOtherEnd = otherEnd.getRenderedInteractor(); - // renderedOtherEnd.subgraph = subgraph; - // //if (!subgraph.nodes.has(renderedOtherEnd.id)) { - // subgraph.nodes.set(renderedOtherEnd.id, renderedOtherEnd); - // otherEnd.subgraph = subgraph; - // otherEnd.addConnectedNodes(subgraph); - // //} - // // } - // } - // } - // } - // } - // return subgraph; - // } - - // countExternalLinks () { - // // return this.renderedP_PLinks.length; - // const renderedParticipantsLinkedTo = new Set(); - // - // for (let link of this.subgraph.links.values()) { - // const rp = link.getOtherEnd(this); - // renderedParticipantsLinkedTo.add(rp); - // } - // - // - // - // // //let countExternal = 0; - // // for (let link of this.renderedP_PLinks) { - // // if (link.crosslinks[0].isSelfLink() === false) - // // { - // // if (link.isPassingFilter()) { - // // //countExternal++; - // // renderedParticipantsLinkedTo.add(link.getOtherEnd(this).getRenderedInteractor()); - // // } - // // } - // // } - // return renderedParticipantsLinkedTo.size; - // - // } -} - - -/***/ }), - -/***/ "./crosslink-viewer/js/views/xinet/interactor/interactor.js": -/*!******************************************************************!*\ - !*** ./crosslink-viewer/js/views/xinet/interactor/interactor.js ***! - \******************************************************************/ -/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { - -"use strict"; -__webpack_require__.r(__webpack_exports__); -/* harmony export */ __webpack_require__.d(__webpack_exports__, { -/* harmony export */ Interactor: () => (/* binding */ Interactor) -/* harmony export */ }); -/* harmony import */ var d3__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! d3 */ "./node_modules/d3/d3.js"); -/* harmony import */ var d3__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(d3__WEBPACK_IMPORTED_MODULE_0__); -/* harmony import */ var _trig__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../trig */ "./crosslink-viewer/js/views/xinet/trig.js"); - - - -class Interactor { - - constructor(controller) { - this.controller = controller; - this.selfLink = null; - this.parentGroups = new Set(); - - this._selected = false; - this._highlight = false; - } - - get symbolRadius() { - return 25; - } - - mouseDown(evt) { - this.controller.preventDefaultsAndStopPropagation(evt); - this.controller.d3cola.stop(); - this.controller.dragElement = this; - this.controller.dragStart = evt; - this.controller.mouseMoved = false; - return false; - } - - mouseOut() { - //this.controller.preventDefaultsAndStopPropagation(evt); // isn't stopping mouseOut in controller getting called - this.controller.model.setHighlightedProteins([]); - this.controller.model.get("tooltipModel").set("contents", null); - } - - set highlighted(show) { - if (show === true && !this._highlight) { - const d3HighSel = d3__WEBPACK_IMPORTED_MODULE_0___default().select(this.highlight); - d3HighSel - .classed("selectedProtein", false) - .classed("highlightedProtein", true) - .attr("stroke-opacity", "1"); - } else if (show === false && this._highlight) { - const d3HighSel = d3__WEBPACK_IMPORTED_MODULE_0___default().select(this.highlight); - if (!this._selected) { - d3HighSel.attr("stroke-opacity", "0"); - } - d3HighSel - .classed("selectedProtein", true) - .classed("highlightedProtein", false); - } - this._highlight = !!show; - } - - get highlighted() { - return this._highlight; - } - - set selected(select) { - const d3HighSel = d3__WEBPACK_IMPORTED_MODULE_0___default().select(this.highlight); - if (select === true && !this._selected) { - d3HighSel - .classed("selectedProtein", true) - .classed("highlightedProtein", false) - .attr("stroke-opacity", "1"); - } else if (select === false && this._selected) { - d3HighSel - .attr("stroke-opacity", "0") - .classed("selectedProtein", false) - .classed("highlightedProtein", true); - } - this._selected = !!select; - } - - get selected() { - return this._selected; - } - - getAggregateSelfLinkPath() { - const intraR = this.symbolRadius + 7; - const sectorSize = 45; - const arcStart = (0,_trig__WEBPACK_IMPORTED_MODULE_1__.trig)(intraR, 25 + sectorSize); - const arcEnd = (0,_trig__WEBPACK_IMPORTED_MODULE_1__.trig)(intraR, -25 + sectorSize); - const cp1 = (0,_trig__WEBPACK_IMPORTED_MODULE_1__.trig)(intraR, 40 + sectorSize); - const cp2 = (0,_trig__WEBPACK_IMPORTED_MODULE_1__.trig)(intraR, -40 + sectorSize); - return "M 0,0 " + - "Q " + cp1.x + "," + -cp1.y + " " + arcStart.x + "," + -arcStart.y + - " A " + intraR + " " + intraR + " 0 0 1 " + arcEnd.x + "," + -arcEnd.y + - " Q " + cp2.x + "," + -cp2.y + " 0,0"; - } - - // update all lines (e.g after a move) - setAllLinkCoordinates() { - for (let pl of this.renderedP_PLinks) { - pl.setLineCoordinates(this); - } - for (let rcl of this.renderedCrosslinks) { - rcl.setLineCoordinates(this); - } - // yes... the group-to-group links are updated separately - } - - showLabel(show) { - d3__WEBPACK_IMPORTED_MODULE_0___default().select(this.labelSVG).attr("display", show ? null : "none"); - } - - getRenderedInteractor() { - // get highest collapsed group - for (let pg of this.parentGroups.values()) { - if (!pg.expanded) { - return pg.getRenderedInteractor(); - } - } - return this; - } - - inCollapsedGroup() { - // noinspection LoopStatementThatDoesntLoopJS - for (let pg of this.parentGroups.values()) { - if (!pg.expanded) { - return true; - } - } - return false; - } - - // getSubgraph () { - // if (this.subgraph == null) { - // const subgraph = { - // nodes: new Map(), - // links: new Map() - // }; - // const thisNode = this.getRenderedInteractor(); - // subgraph.nodes.set(thisNode.id, thisNode); - // this.subgraph = this.addConnectedNodes(subgraph); - // thisNode.subgraph = subgraph; - // this.controller.subgraphs.push(subgraph); - // } - // return this.subgraph; - // } -} - - -/***/ }), - -/***/ "./crosslink-viewer/js/views/xinet/interactor/rendered-protein.js": -/*!************************************************************************!*\ - !*** ./crosslink-viewer/js/views/xinet/interactor/rendered-protein.js ***! - \************************************************************************/ -/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { - -"use strict"; -__webpack_require__.r(__webpack_exports__); -/* harmony export */ __webpack_require__.d(__webpack_exports__, { -/* harmony export */ RenderedProtein: () => (/* binding */ RenderedProtein) -/* harmony export */ }); -/* harmony import */ var underscore__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! underscore */ "./node_modules/underscore/modules/index-all.js"); -/* harmony import */ var _interactor__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./interactor */ "./crosslink-viewer/js/views/xinet/interactor/interactor.js"); -/* harmony import */ var _rotator__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./rotator */ "./crosslink-viewer/js/views/xinet/interactor/rotator.js"); -/* harmony import */ var _crosslink_viewer_BB__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../crosslink-viewer-BB */ "./crosslink-viewer/js/views/xinet/crosslink-viewer-BB.js"); -/* harmony import */ var d3__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! d3 */ "./node_modules/d3/d3.js"); -/* harmony import */ var d3__WEBPACK_IMPORTED_MODULE_4___default = /*#__PURE__*/__webpack_require__.n(d3__WEBPACK_IMPORTED_MODULE_4__); -/* harmony import */ var _xiview_js_make_tooltip__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ../../../../../xiview/js/make-tooltip */ "./xiview/js/make-tooltip.js"); -/* harmony import */ var _trig__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ../trig */ "./crosslink-viewer/js/views/xinet/trig.js"); - - - - - - - - - -class RenderedProtein extends _interactor__WEBPACK_IMPORTED_MODULE_1__.Interactor { - - constructor(participant, controller) { - super(controller); - this.participant = participant; - this.busy = false; - this.renderedP_PLinks = []; - this.renderedCrosslinks = []; - this.parentGroups = new Set(); - // layout info - this.ix = 300; - this.iy = 40; - this.rotation = 0; - this.expanded = false; - this.hidden = false; - this.isFlipped = false; - // this.isSelected = false; - // this.isHighlighted = false; - this.createElements(); - } - - createElements() { - //'rotators' - this.lowerRotator = new _rotator__WEBPACK_IMPORTED_MODULE_2__.Rotator(this, 0, this.controller); - this.upperRotator = new _rotator__WEBPACK_IMPORTED_MODULE_2__.Rotator(this, 1, this.controller); - - /* - * Lower group - * svg group for elements that appear underneath links - */ - this.lowerGroup = document.createElementNS(_crosslink_viewer_BB__WEBPACK_IMPORTED_MODULE_3__.CrosslinkViewer.svgns, "g"); - this.lowerGroup.setAttribute("class", "protein lowerGroup"); - //make highlight - this.highlight = document.createElementNS(_crosslink_viewer_BB__WEBPACK_IMPORTED_MODULE_3__.CrosslinkViewer.svgns, "rect"); - d3__WEBPACK_IMPORTED_MODULE_4___default().select(this.highlight).attr("fill-opacity", "0").attr("stroke-width", "5"); - this.lowerGroup.appendChild(this.highlight); - //make background - this.background = document.createElementNS(_crosslink_viewer_BB__WEBPACK_IMPORTED_MODULE_3__.CrosslinkViewer.svgns, "rect"); - this.lowerGroup.appendChild(this.background); - //domains in rectangle form (shown underneath links) - this.rectDomains = document.createElementNS(_crosslink_viewer_BB__WEBPACK_IMPORTED_MODULE_3__.CrosslinkViewer.svgns, "g"); - this.rectDomains.setAttribute("opacity", "0"); - this.lowerGroup.appendChild(this.rectDomains); - this.peptides = document.createElementNS(_crosslink_viewer_BB__WEBPACK_IMPORTED_MODULE_3__.CrosslinkViewer.svgns, "g"); - this.lowerGroup.appendChild(this.peptides); - - /* - * Upper group - * svg group for elements that appear above links - */ - this.upperGroup = document.createElementNS(_crosslink_viewer_BB__WEBPACK_IMPORTED_MODULE_3__.CrosslinkViewer.svgns, "g"); - this.upperGroup.setAttribute("class", "protein upperGroup"); - //svg groups for self links - this.selfLinksHighlights = document.createElementNS(_crosslink_viewer_BB__WEBPACK_IMPORTED_MODULE_3__.CrosslinkViewer.svgns, "g"); - this.selfLinks = document.createElementNS(_crosslink_viewer_BB__WEBPACK_IMPORTED_MODULE_3__.CrosslinkViewer.svgns, "g"); - this.upperGroup.appendChild(this.selfLinksHighlights); - this.upperGroup.appendChild(this.selfLinks); - - //create label - we will move this svg element around when protein form changes - this.labelSVG = document.createElementNS(_crosslink_viewer_BB__WEBPACK_IMPORTED_MODULE_3__.CrosslinkViewer.svgns, "text"); - d3__WEBPACK_IMPORTED_MODULE_4___default().select(this.labelSVG).attr("text-anchor", "middle") - .attr("dominant-baseline", "middle") - .attr("fill", this.participant.is_decoy ? "#FB8072" : "black") - .attr("x", 0) - .attr("y", 0) - .classed("protein xlv_text proteinLabel", true); - this.labelTextNode = document.createTextNode(this.participant.name); - this.updateName(); - this.labelSVG.appendChild(this.labelTextNode); - - //ticks (and animo acid letters) - this.ticks = document.createElementNS(_crosslink_viewer_BB__WEBPACK_IMPORTED_MODULE_3__.CrosslinkViewer.svgns, "g"); - - //make outline - //http://stackoverflow.com/questions/17437408/how-do-i-change-a-circle-to-a-square-using-d3 - this.outline = document.createElementNS(_crosslink_viewer_BB__WEBPACK_IMPORTED_MODULE_3__.CrosslinkViewer.svgns, "rect"); - d3__WEBPACK_IMPORTED_MODULE_4___default().select(this.outline).attr("stroke", "black") - .attr("stroke-width", "1") - .attr("fill", "#EEEEEE"); - this.upperGroup.appendChild(this.outline); - this.upperGroup.appendChild(this.ticks); - //domains as pie slices - shown on top of everything - this.circDomains = document.createElementNS(_crosslink_viewer_BB__WEBPACK_IMPORTED_MODULE_3__.CrosslinkViewer.svgns, "g"); - this.circDomains.setAttribute("opacity", "1"); - this.upperGroup.appendChild(this.circDomains); - this.upperGroup.appendChild(this.labelSVG); - - this.scaleLabels = []; - - this.toCircle(null, false); - - // events - const self = this; - this.upperGroup.onmousedown = function (evt) { - self.mouseDown(evt); - }; - this.upperGroup.onmouseover = function (evt) { - self.mouseOver(evt); - }; - this.upperGroup.onmouseout = function (evt) { - self.mouseOut(evt); - }; - - //going to use right click ourselves - this.upperGroup.oncontextmenu = function (evt) { - // if (evt.preventDefault) { - evt.preventDefault(); - // } - return false; - }; - } - - get proteins () { - return [this.participant]; - } - - get bBox () { - return this.upperGroup.getBBox(); - // return { - // x:this.ix - 30, - // y: this.iy - 30, - // width: this.width, - // height: this.height - // }; - } - - get width(){ - const approxLabelWidth = 10 * (this.labelText.length + 2); - if (!this.expanded) { - return (approxLabelWidth > this.symbolRadius)? approxLabelWidth : this.symbolRadius + 20;//this.upperGroup.getBBox().width + 10; - } else { - return (this.participant.size * this.stickZoom) + approxLabelWidth; - } - } - - get height () { - return 60; - } - - get symbolRadius() { - if (this.controller.fixedSize) { - return 12; - } else { - return Math.sqrt(this.participant.size / Math.PI) * 0.6; - } - } - - //when we get here all prot's have been created and defaultBarScale will have value - //this is called by loadLayout function - setEverything() { - this.busy = false; - if (!this.stickZoom) { - this.stickZoom = this.controller.defaultBarScale; - } - // this.showHighlight(this.isHighlighted); - // this.setSelected(this.isSelected); - this.setPositionFromXinet(this.ix, this.iy); - this.scale(); - this.setAllLinkCoordinates(); - if (this.newForm === true) { //hacky? - this.toStickNoTransition(); - } - } - - updateName() { - //choose label text - if (!this.controller.cropLabels) { - this.labelText = this.participant.name; - } else { - this.labelText = this.participant.name.split("_")[0]; - } - if (this.labelText.length > 25) { - this.labelText = this.labelText.substr(0, 16) + "..."; - } - this.labelTextNode.textContent = this.labelText; - } - - mouseOver(evt) { - this.controller.model.setHighlightedProteins([this.participant]); - if (!this.controller.dragElement) { - const p = this.controller.getEventPoint(evt); - this.controller.model.get("tooltipModel") - .set("header", _xiview_js_make_tooltip__WEBPACK_IMPORTED_MODULE_5__.makeTooltipTitle.interactor(this.participant)) - .set("contents", _xiview_js_make_tooltip__WEBPACK_IMPORTED_MODULE_5__.makeTooltipContents.interactor(this.participant)) - .set("location", { - pageX: p.x, - pageY: p.y - }); - } - } - - resize() { - if (!this.expanded) { - const r = this.symbolRadius; - d3__WEBPACK_IMPORTED_MODULE_4___default().select(this.outline) - .attr("x", -r).attr("y", -r) - .attr("width", r * 2).attr("height", r * 2) - .attr("rx", r).attr("ry", r); - d3__WEBPACK_IMPORTED_MODULE_4___default().select(this.background) - .attr("x", -r).attr("y", -r) - .attr("width", r * 2).attr("height", r * 2) - .attr("rx", r).attr("ry", r); - d3__WEBPACK_IMPORTED_MODULE_4___default().select(this.highlight) - .attr("width", (r * 2) + 5).attr("height", (r * 2) + 5) - .attr("x", -r - 2.5).attr("y", -r - 2.5) - .attr("rx", r + 2.5).attr("ry", r + 2.5); - this.labelSVG.setAttribute("transform", "translate(" + (-(r + 5)) + "," + "-5)"); - for (let ppLink of this.renderedP_PLinks) { - if (ppLink.crosslinks[0].isSelfLink() && ppLink.shown) { - ppLink.initSelfLinkSVG(); - } - } - } - } - - //only output the info needed to reproduce the layout, used by save layout function - toJSON() { - return { - id: this.participant.id, - x: this.ix, - y: this.iy, - rot: this.rotation, - expanded: this.expanded, - stickZoom: this.stickZoom, - flipped: this.isFlipped, - manuallyHidden: this.participant.manuallyHidden, - name: this.participant.name // having this here is bit of hack - }; - } - - setRotation(angle) { - this.rotation = angle % 360; - if (this.rotation < 0) { - this.rotation += 360; - } - this.upperGroup.setAttribute("transform", "translate(" + this.ix + " " + this.iy + ")" + - " scale(" + (this.controller.z) + ") " + "rotate(" + this.rotation + ")"); - this.lowerGroup.setAttribute("transform", "translate(" + this.ix + " " + this.iy + ")" + - " scale(" + (this.controller.z) + ") " + "rotate(" + this.rotation + ")"); - - const svg = this.controller.svgElement; - const transformToContainingGroup = this.labelSVG.getAttribute("transform"); - const labelTransform = d3__WEBPACK_IMPORTED_MODULE_4___default().transform(transformToContainingGroup); - const sll = this.scaleLabels.length; - if (this.rotation >= 90 && this.rotation < 270) { - const k = svg.createSVGMatrix() - .translate(Math.abs(labelTransform.translate[0]), 0) - .rotate(180, 0, 0); - this.labelSVG.transform.baseVal.initialize(svg.createSVGTransformFromMatrix(k)); - if (this.expanded) { - for (let i = 0; i < sll; i++) { - this.scaleLabels[i].setAttribute("transform", "scale(-1,1)"); - } - this.ticks.setAttribute("transform", "scale(1,-1)"); - } - } else { - const k = svg.createSVGMatrix() - .translate(-(Math.abs(labelTransform.translate[0])), 0); - this.labelSVG.transform.baseVal.initialize(svg.createSVGTransformFromMatrix(k)); - if (this.expanded) { - for (let j = 0; j < sll; j++) { - this.scaleLabels[j].setAttribute("transform", "scale(1,1)"); - } - this.ticks.setAttribute("transform", "scale(1,1)"); - } - } - } - - /* leave this.x and this.y as they were set by cola, - calculate centre of interactor's glyph, - call setPosition with those - */ - setPositionFromCola() { - this.px = this.x; - this.py = this.y; - // let xOffset = 0; - // if (!this.hidden) { // todo - hacky - // xOffset = (this.width / 2 - (this.getBlobRadius()) + 5) - // if (this.expanded) { - // xOffset = xOffset + (this.participant.size / 2 * this.stickZoom ); - // } - // } - this.setPosition(this.x /*- xOffset*/, this.y); - this.updateExpandedGroup(); - } - - /* calculate top left of interactor's glyph, - set this.x and this.y as cola would have them, - call setPosition with same params this received - */ - setPositionFromXinet(ix, iy) { - this.px = this.x; - this.py = this.y; - let xOffset = 0; - if (!this.hidden) { // todo - hacky - xOffset = (this.width / 2 - (this.symbolRadius) + 5); - // // if (this.expanded) { - // // xOffset = xOffset + (this.participant.size / 2 * this.stickZoom ); - // // } - } - this.x = ix - xOffset; - this.y = iy; - this.setPosition(ix, iy); - this.updateExpandedGroup(); - } - - // more accurately described as setting transform for top svg elements (sets scale also) - setPosition(ix, iy) { - this.ix = ix; - this.iy = iy; - if (this.expanded) { - this.upperGroup.setAttribute("transform", "translate(" + this.ix + " " + this.iy + ")" + - " scale(" + (this.controller.z) + ") " + "rotate(" + this.rotation + ")"); - this.lowerGroup.setAttribute("transform", "translate(" + this.ix + " " + this.iy + ")" + - " scale(" + (this.controller.z) + ") " + "rotate(" + this.rotation + ")"); - } else { - this.upperGroup.setAttribute("transform", "translate(" + this.ix + " " + this.iy + ")" + - " scale(" + (this.controller.z) + ") "); - this.lowerGroup.setAttribute("transform", "translate(" + this.ix + " " + this.iy + ")" + - " scale(" + (this.controller.z) + ") "); - if (this.selfLink != null) { - if (typeof this.selfLink.thickLine !== "undefined") { - this.selfLink.thickLine.setAttribute("transform", "translate(" + this.ix + - " " + this.iy + ")" + " scale(" + (this.controller.z) + ")"); - } - this.selfLink.line.setAttribute("transform", "translate(" + this.ix + - " " + this.iy + ")" + " scale(" + (this.controller.z) + ")"); - this.selfLink.highlightLine.setAttribute("transform", "translate(" + this.ix + - " " + this.iy + ")" + " scale(" + (this.controller.z) + ")"); - } - } - } - - updateExpandedGroup() { - for (let group of this.parentGroups) { - if (group.expanded && !this.hidden) { - group.updateExpandedGroup(); - } - } - } - - setStickScale(scale, svgP) { - const oldScale = this.stickZoom; - - //dist from centre - const dx = (this.ix - svgP.x); - const dy = (this.iy - svgP.y); - - // new dist from centre - const nx = dx * scale / oldScale; - const ny = dy * scale / oldScale; - - //required change - const rx = nx - dx; - let ry = ny - dy; - - if (this.rotation === 0 || this.rotation === 180) { - ry = 0; - } - - //new pos - const x = this.ix + rx; - const y = this.iy + ry; - - this.stickZoom = scale; - this.scale(); - this.setPositionFromXinet(x, y); - this.setAllLinkCoordinates(); - } - - scale() { - d3__WEBPACK_IMPORTED_MODULE_4___default().select(this.peptides).attr("transform", "scale(" + (this.stickZoom) + ", 1)"); - const protLength = (this.participant.size) * this.stickZoom; - if (this.expanded) { - const labelWidth = this.labelSVG.getBBox().width; - const labelTransform = d3__WEBPACK_IMPORTED_MODULE_4___default().transform(this.labelSVG.getAttribute("transform")); - const k = this.controller.svgElement.createSVGMatrix().rotate(labelTransform.rotate) - .translate((-(((this.participant.size / 2) * this.stickZoom) + +(labelWidth / 2) + 10)), 0); - this.labelSVG.transform.baseVal.initialize(this.controller.svgElement.createSVGTransformFromMatrix(k)); - if (this.annotations) { - for (let anno of this.annotations.values()) { - const feature = anno.feature; - anno.pieSlice.setAttribute("d", this.getAnnotationRectPath(feature)); - anno.colouredRect.setAttribute("d", this.getAnnotationRectPath(feature)); - } - } - - d3__WEBPACK_IMPORTED_MODULE_4___default().select(this.outline) - .attr("width", protLength) - .attr("x", this.getResXwithStickZoom(0.5)); - d3__WEBPACK_IMPORTED_MODULE_4___default().select(this.background) - .attr("width", protLength) - .attr("x", this.getResXwithStickZoom(0.5)); - - d3__WEBPACK_IMPORTED_MODULE_4___default().select(this.highlight) - .attr("width", protLength + 5) - .attr("x", this.getResXwithStickZoom(0.5) - 2.5); - - this.placeRotators(); - - for (let residueLink of this.renderedCrosslinks) { - if (residueLink.crosslink.isSelfLink() || residueLink.crosslink.isMonoLink()) { - const path = this.getCrossLinkPath(residueLink); - d3__WEBPACK_IMPORTED_MODULE_4___default().select(residueLink.line).attr("d", path); - d3__WEBPACK_IMPORTED_MODULE_4___default().select(residueLink.highlightLine).attr("d", path); - } - } - - this.setScaleGroup(); - this.setRotation(this.rotation); // places ticks and rotators - } - } - - placeRotators() { - //place rotators - this.lowerRotator.svg.setAttribute("transform", - "translate(" + (this.getResXwithStickZoom(0.5) - RenderedProtein.rotOffset) + " 0)"); - this.upperRotator.svg.setAttribute("transform", - "translate(" + (this.getResXwithStickZoom(this.participant.size - 0 + 0.5) + RenderedProtein.rotOffset) + " 0)"); - } - - setScaleGroup() { - d3__WEBPACK_IMPORTED_MODULE_4___default().select(this.ticks).selectAll("*").remove(); - - this.scaleLabels = []; - // const ScaleMajTick = 100; - const ScaleTicksPerLabel = 2; // varies with scale? - let tick = -1; - const lastTickX = this.getResXwithStickZoom(this.participant.size); - - for (let res = 1; res <= this.participant.size; res++) { - if (res === 1 || - ((res % 100 === 0) && (200 * this.stickZoom > RenderedProtein.minXDist)) || - ((res % 10 === 0) && (20 * this.stickZoom > RenderedProtein.minXDist)) - ) { - const tx = this.getResXwithStickZoom(res); - if (this.stickZoom >= 8 || res !== 1) { - tickAt(this, tx); - } - tick = (tick + 1) % ScaleTicksPerLabel; - // does this one get a label? - if (tick === 0) { // && tx > 20) { - if ((tx + RenderedProtein.minXDist) < lastTickX) { - scaleLabelAt(this, res, tx); - } - } - } - if (this.stickZoom >= 8 && this.participant.sequence) { - const seqLabelGroup = document.createElementNS(_crosslink_viewer_BB__WEBPACK_IMPORTED_MODULE_3__.CrosslinkViewer.svgns, "g"); - seqLabelGroup.setAttribute("transform", "translate(" + this.getResXwithStickZoom(res) + " " + 0 + ")"); - const seqLabel = document.createElementNS(_crosslink_viewer_BB__WEBPACK_IMPORTED_MODULE_3__.CrosslinkViewer.svgns, "text"); - seqLabel.setAttribute("font-family", "monospace"); - seqLabel.setAttribute("font-size", "10px"); - seqLabel.setAttribute("text-anchor", "middle"); - seqLabel.setAttribute("x", "0"); - seqLabel.setAttribute("y", "3"); - seqLabel.appendChild(document.createTextNode(this.participant.sequence[res - 1])); - seqLabelGroup.appendChild(seqLabel); - this.scaleLabels.push(seqLabel); - this.ticks.appendChild(seqLabelGroup); - } - } - scaleLabelAt(this, this.participant.size, lastTickX); - if (this.stickZoom >= 8) { - tickAt(this, lastTickX); - } - - function scaleLabelAt(self, text, tickX) { - const scaleLabelGroup = document.createElementNS(_crosslink_viewer_BB__WEBPACK_IMPORTED_MODULE_3__.CrosslinkViewer.svgns, "g"); - scaleLabelGroup.setAttribute("transform", "translate(" + tickX + " " + 0 + ")"); - const scaleLabel = document.createElementNS(_crosslink_viewer_BB__WEBPACK_IMPORTED_MODULE_3__.CrosslinkViewer.svgns, "text"); - scaleLabel.setAttribute("class", "xinetAxisLabel"); - scaleLabel.setAttribute("font-family", "monospace"); - scaleLabel.setAttribute("font-size", "14"); - scaleLabel.setAttribute("text-anchor", "middle"); - scaleLabel.setAttribute("x", "0"); - scaleLabel.setAttribute("y", (RenderedProtein.STICKHEIGHT + 4).toString()); - scaleLabel.appendChild(document.createTextNode(text)); - scaleLabelGroup.appendChild(scaleLabel); - self.scaleLabels.push(scaleLabel); - self.ticks.appendChild(scaleLabelGroup); - } - - function tickAt(self, tickX) { - const tick = document.createElementNS(_crosslink_viewer_BB__WEBPACK_IMPORTED_MODULE_3__.CrosslinkViewer.svgns, "line"); - tick.setAttribute("x1", tickX); - tick.setAttribute("y1", "5"); - tick.setAttribute("x2", tickX); - tick.setAttribute("y2", "10"); - tick.setAttribute("stroke", "black"); - self.ticks.appendChild(tick); - } - } - - toggleFlipped() { - this.isFlipped = !this.isFlipped; - if (this.isFlipped) { - this.selfLinks.setAttribute("transform", "scale (1 -1)"); - this.selfLinksHighlights.setAttribute("transform", "scale (1 -1)"); - } else { - this.selfLinks.setAttribute("transform", "scale (1 1)"); - this.selfLinksHighlights.setAttribute("transform", "scale (1 1)"); - } - } - - setHidden(bool) { - // MJG - d3__WEBPACK_IMPORTED_MODULE_4___default().select(this.upperGroup).style("display", bool ? "none" : null); - d3__WEBPACK_IMPORTED_MODULE_4___default().select(this.lowerGroup).style("display", bool ? "none" : null); - this.hidden = !!bool; - } - - setExpanded(expanded, svgP) { - this.controller.model.get("tooltipModel").set("contents", null); - if (this.busy !== true) { - if (expanded) { - if (this.expanded !== expanded) { - this.toStick(); - } - } else { - if (this.expanded !== expanded) { - this.toCircle(svgP); - } - } - } - } - - toCircle(svgP, transition = true) { - const transitionTime = transition ? RenderedProtein.transitionTime : 0; //this maybe isn't so good - - this.busy = true; - _crosslink_viewer_BB__WEBPACK_IMPORTED_MODULE_3__.CrosslinkViewer.removeDomElement(this.lowerRotator.svg); - _crosslink_viewer_BB__WEBPACK_IMPORTED_MODULE_3__.CrosslinkViewer.removeDomElement(this.upperRotator.svg); - - // const protLength = this.participant.size * this.stickZoom; - const r = this.symbolRadius; - const protColourModel = window.compositeModelInst.get("proteinColourAssignment"); - - if (transition) { - d3__WEBPACK_IMPORTED_MODULE_4___default().select(this.outline).transition() - .attr("fill-opacity", 1) - .attr("fill", protColourModel.getColour(this.participant)) - .attr("x", -r).attr("y", -r) - .attr("width", r * 2).attr("height", r * 2) - .attr("rx", r).attr("ry", r) - .duration(transitionTime); - - d3__WEBPACK_IMPORTED_MODULE_4___default().select(this.background).transition() - .attr("fill-opacity", 1) - .attr("fill", protColourModel.getColour(this.participant)) - .attr("x", -r).attr("y", -r) - .attr("width", r * 2).attr("height", r * 2) - .attr("rx", r).attr("ry", r) - .duration(transitionTime); - - d3__WEBPACK_IMPORTED_MODULE_4___default().select(this.rectDomains).transition().attr("opacity", 0) - .attr("transform", "scale(1, 1)") - .duration(transitionTime); - - d3__WEBPACK_IMPORTED_MODULE_4___default().select(this.circDomains).transition().attr("opacity", 1) - .attr("transform", "scale(1, 1)") - .duration(transitionTime); - } else { - d3__WEBPACK_IMPORTED_MODULE_4___default().select(this.outline) - .attr("fill-opacity", 1) - .attr("fill", protColourModel.getColour(this.participant)) - .attr("x", -r).attr("y", -r) - .attr("width", r * 2).attr("height", r * 2) - .attr("rx", r).attr("ry", r); - - d3__WEBPACK_IMPORTED_MODULE_4___default().select(this.background) - .attr("fill-opacity", 1) - .attr("fill", protColourModel.getColour(this.participant)) - .attr("x", -r).attr("y", -r) - .attr("width", r * 2).attr("height", r * 2) - .attr("rx", r).attr("ry", r); - - d3__WEBPACK_IMPORTED_MODULE_4___default().select(this.rectDomains).attr("opacity", 0) - .attr("transform", "scale(1, 1)"); - - d3__WEBPACK_IMPORTED_MODULE_4___default().select(this.circDomains).attr("opacity", 1) - .attr("transform", "scale(1, 1)"); - } - - - const stickZoomInterpol = d3__WEBPACK_IMPORTED_MODULE_4___default().interpolate(this.stickZoom, 0); - const rotationInterpol = d3__WEBPACK_IMPORTED_MODULE_4___default().interpolate((this.rotation > 180) ? this.rotation - 360 : this.rotation, 0); - //todo: should take current transform of label as start - const labelTransform = d3__WEBPACK_IMPORTED_MODULE_4___default().transform(this.labelSVG.getAttribute("transform")); - const labelStartPoint = labelTransform.translate[0]; //-(((this.participant.size / 2) * this.stickZoom) + 10); - const labelTranslateInterpol = d3__WEBPACK_IMPORTED_MODULE_4___default().interpolate(labelStartPoint, 0); //-(r + 5)); - - let xInterpol = null, - yInterpol = null; - if (typeof svgP !== "undefined" && svgP !== null) { - xInterpol = d3__WEBPACK_IMPORTED_MODULE_4___default().interpolate(this.ix, svgP.x); - yInterpol = d3__WEBPACK_IMPORTED_MODULE_4___default().interpolate(this.iy, svgP.y); - } - - const self = this; - if (transition) { - d3__WEBPACK_IMPORTED_MODULE_4___default().select(this.ticks).transition().attr("opacity", 0).duration(transitionTime / 4) - .each("end", - function () { - d3__WEBPACK_IMPORTED_MODULE_4___default().select(this).selectAll("*").remove(); - } - ); - d3__WEBPACK_IMPORTED_MODULE_4___default().select(this.highlight).transition() - .attr("width", (r * 2) + 5).attr("height", (r * 2) + 5) - .attr("x", -r - 2.5).attr("y", -r - 2.5) - .attr("rx", r + 2.5).attr("ry", r + 2.5) - .duration(transitionTime); - const aggSelfLinkPath = this.getAggregateSelfLinkPath(); - for (let residueLink of this.renderedCrosslinks) { - const crosslinkPath = this.getCrossLinkPath(residueLink); - const lineSel = d3__WEBPACK_IMPORTED_MODULE_4___default().select(residueLink.line); - if (residueLink.crosslink.isSelfLink()) { - lineSel.attr("d", crosslinkPath); - lineSel.transition().attr("d", aggSelfLinkPath) - .duration(transitionTime); - const highlightLineSel = d3__WEBPACK_IMPORTED_MODULE_4___default().select(residueLink.highlightLine); - highlightLineSel.attr("d", crosslinkPath); - highlightLineSel.transition().attr("d", aggSelfLinkPath) - .duration(transitionTime); - } else if (residueLink.crosslink.isMonoLink()) { - lineSel.attr("d", crosslinkPath); - lineSel.transition().attr("d", "M 0,0 L 0,0 L 0,0 L 0,0") - .duration(transitionTime); - const highlightLineSel = d3__WEBPACK_IMPORTED_MODULE_4___default().select(residueLink.highlightLine); - highlightLineSel.attr("d", crosslinkPath); - highlightLineSel.transition().attr("d", "M 0,0 L 0,0 L 0,0 L 0,0") - .duration(transitionTime); - } - } - - if (this.annotations) { - const annotArr = Array.from(this.annotations.values()); - const annotationCount = annotArr.length; - for (let a = 0; a < annotationCount; a++) { - const anno = annotArr[a], - feature = anno.feature, - pieSlice = anno.pieSlice, - rectDomain = anno.colouredRect; - if (feature.type !== RenderedProtein.disulfide) { - if (transition) { - d3__WEBPACK_IMPORTED_MODULE_4___default().select(pieSlice).transition().attr("d", this.getAnnotationPieSliceApproximatePath(feature)) - .duration(transitionTime).each("end", - function () { - for (let b = 0; b < annotationCount; b++) { - const annoB = annotArr[b]; - if (this === annoB.pieSlice) { - d3__WEBPACK_IMPORTED_MODULE_4___default().select(this).attr("d", self.getAnnotationPieSliceArcPath(annoB.feature)); - } - } - } - ); - - d3__WEBPACK_IMPORTED_MODULE_4___default().select(rectDomain).transition().attr("d", self.getAnnotationPieSliceApproximatePath(feature)) - .duration(transitionTime); - } else { - for (let b = 0; b < annotationCount; b++) { - const annoB = annotArr[b]; - if (this === annoB.pieSlice) { - d3__WEBPACK_IMPORTED_MODULE_4___default().select(this).attr("d", self.getAnnotationPieSliceArcPath(annoB.feature)); - } - } - } - } else { - d3__WEBPACK_IMPORTED_MODULE_4___default().select(pieSlice).transition().attr("d", this.getDisulfidAnnotationCircPath(feature)) - .duration(transitionTime); - d3__WEBPACK_IMPORTED_MODULE_4___default().select(rectDomain).transition().attr("d", self.getDisulfidAnnotationRectPath(feature)) - .duration(transitionTime); - } - } - } - } else { - d3__WEBPACK_IMPORTED_MODULE_4___default().select(this.ticks).selectAll("*").remove(); - d3__WEBPACK_IMPORTED_MODULE_4___default().select(this.highlight) - .attr("width", (r * 2) + 5).attr("height", (r * 2) + 5) - .attr("x", -r - 2.5).attr("y", -r - 2.5) - .attr("rx", r + 2.5).attr("ry", r + 2.5); - } - - const originalStickZoom = this.stickZoom; - const originalRotation = this.rotation; - const cubicInOut = d3__WEBPACK_IMPORTED_MODULE_4___default().ease("cubic-in-out"); - if (transition) { - d3__WEBPACK_IMPORTED_MODULE_4___default().timer(function (elapsed) { - return update(elapsed / transitionTime); - }); - } else { - update(1); - } - - function update(interp) { - const labelTransform = d3__WEBPACK_IMPORTED_MODULE_4___default().transform(self.labelSVG.getAttribute("transform")); - const k = self.controller.svgElement.createSVGMatrix().rotate(labelTransform.rotate).translate(labelTranslateInterpol(cubicInOut(interp)), 0); - if (self.labelSVG.transform) self.labelSVG.transform.baseVal.initialize(self.controller.svgElement.createSVGTransformFromMatrix(k)); - if (xInterpol !== null) { - // noinspection JSValidateTypes - self.setPositionFromXinet(xInterpol(cubicInOut(interp)), yInterpol(cubicInOut(interp))); - } - const rot = rotationInterpol(cubicInOut(interp)); - self.stickZoom = stickZoomInterpol(cubicInOut(interp)); - self.setRotation(rot); - - self.setAllLinkCoordinates(); - - if (interp === 1) { // finished - tidy up - //bring in new - self.expanded = false; - for (let rcl of self.renderedCrosslinks) { - rcl.check(); - } - for (let pl of self.renderedP_PLinks) { - pl.update(); - } - self.stickZoom = originalStickZoom; - self.rotation = originalRotation; - self.busy = false; - - // not needed coz setPosition gets called above - // if (this.complex) { - // this.complex.updateExpandedGroup(); - // } - - return true; - } else if (interp > 1 || isNaN(interp)) { - return update(1); - } else { - return false; - } - } - } - - toStick(transition = true) { - const transitionTime = transition ? RenderedProtein.transitionTime : 0; - - this.busy = true; - this.expanded = true; - - //place rotators - this.upperGroup.appendChild(this.lowerRotator.svg); - this.upperGroup.appendChild(this.upperRotator.svg); - this.placeRotators(); - - const protLength = this.participant.size * this.stickZoom; - const r = this.symbolRadius; - - const lengthInterpol = d3__WEBPACK_IMPORTED_MODULE_4___default().interpolate((2 * r), protLength); - const stickZoomInterpol = d3__WEBPACK_IMPORTED_MODULE_4___default().interpolate(0, this.stickZoom); - const rotationInterpol = d3__WEBPACK_IMPORTED_MODULE_4___default().interpolate(0, (this.rotation > 180) ? this.rotation - 360 : this.rotation); - const labelWidth = this.labelSVG.getBBox().width; - const labelTranslateInterpol = d3__WEBPACK_IMPORTED_MODULE_4___default().interpolate(0 /*-(r + 5)*/, -(((this.participant.size / 2) * this.stickZoom) + (labelWidth / 2) + 10)); - - const origStickZoom = this.stickZoom; - this.stickZoom = 0; - this.checkLinks(); - this.stickZoom = origStickZoom; - - const protColourModel = window.compositeModelInst.get("proteinColourAssignment"); - - d3__WEBPACK_IMPORTED_MODULE_4___default().select(this.circDomains).transition().attr("opacity", 0).duration(transitionTime); - d3__WEBPACK_IMPORTED_MODULE_4___default().select(this.rectDomains).transition().attr("opacity", 1).duration(transitionTime); - - d3__WEBPACK_IMPORTED_MODULE_4___default().select(this.outline).transition().attr("stroke-opacity", 1) - .attr("fill-opacity", 0) - .attr("fill", protColourModel.getColour(this.participant)) - .attr("height", RenderedProtein.STICKHEIGHT) - .attr("y", -RenderedProtein.STICKHEIGHT / 2) - .attr("rx", 0).attr("ry", 0) - .duration(transitionTime); - - d3__WEBPACK_IMPORTED_MODULE_4___default().select(this.background).transition().attr("stroke-opacity", 1) - .attr("fill", protColourModel.getColour(this.participant)) - .attr("height", RenderedProtein.STICKHEIGHT) - .attr("y", -RenderedProtein.STICKHEIGHT / 2) - .attr("rx", 0).attr("ry", 0) - .duration(transitionTime); - - d3__WEBPACK_IMPORTED_MODULE_4___default().select(this.highlight).transition() - .attr("width", protLength + 5).attr("height", RenderedProtein.STICKHEIGHT + 5) - .attr("x", this.getResXwithStickZoom(0.5) - 2.5).attr("y", (-RenderedProtein.STICKHEIGHT / 2) - 2.5) - .attr("rx", 0).attr("ry", 0) - .duration(transitionTime); - - const aggSelfLinkPath = this.getAggregateSelfLinkPath(); - for (let residueLink of this.renderedCrosslinks) { - const crosslinkPath = this.getCrossLinkPath(residueLink); - const lineSel = d3__WEBPACK_IMPORTED_MODULE_4___default().select(residueLink.line); - const highlightLineSel = d3__WEBPACK_IMPORTED_MODULE_4___default().select(residueLink.highlightLine); - if (residueLink.crosslink.isSelfLink()) { - lineSel.attr("d", aggSelfLinkPath); - lineSel.transition().attr("d", crosslinkPath) - .duration(transitionTime); - highlightLineSel.attr("d", aggSelfLinkPath); - highlightLineSel.transition().attr("d", crosslinkPath) - .duration(transitionTime); - } else if (residueLink.crosslink.isMonoLink()) { - lineSel.attr("d", "M 0,0 L 0,0 L 0,0 L 0,0"); - lineSel.transition().attr("d", crosslinkPath) - .duration(RenderedProtein.transitionTime); - highlightLineSel.attr("d", "M 0,0 L 0,0 L 0,0 L 0,0"); - highlightLineSel.transition().attr("d", crosslinkPath) - .duration(transitionTime); - } - } - - if (this.annotations) { - for (let anno of this.annotations.values()) { - const feature = anno.feature, - pieSlice = anno.pieSlice, - rectDomain = anno.colouredRect; - - if (feature.type !== RenderedProtein.disulfide) { - pieSlice.setAttribute("d", this.getAnnotationPieSliceApproximatePath(feature)); - d3__WEBPACK_IMPORTED_MODULE_4___default().select(pieSlice).transition().attr("d", this.getAnnotationRectPath(feature)) - .duration(transitionTime); - d3__WEBPACK_IMPORTED_MODULE_4___default().select(rectDomain).transition().attr("d", this.getAnnotationRectPath(feature)) - .duration(RenderedProtein.transitionTime); - } else { - d3__WEBPACK_IMPORTED_MODULE_4___default().select(pieSlice).transition().attr("d", this.getDisulfidAnnotationRectPath(feature)) - .duration(transitionTime); - d3__WEBPACK_IMPORTED_MODULE_4___default().select(rectDomain).transition().attr("d", this.getDisulfidAnnotationRectPath(feature)) - .duration(transitionTime); - - } - } - } - - const self = this; - const cubicInOut = d3__WEBPACK_IMPORTED_MODULE_4___default().ease("cubic-in-out"); - if (transition) { - d3__WEBPACK_IMPORTED_MODULE_4___default().timer(function (elapsed) { - return update(elapsed / transitionTime); - }); - } else { - update(1); - } - - //~ update(1); - - function update(interp) { - const labelTransform = d3__WEBPACK_IMPORTED_MODULE_4___default().transform(self.labelSVG.getAttribute("transform")); - const k = self.controller.svgElement.createSVGMatrix().rotate(labelTransform.rotate).translate(labelTranslateInterpol(cubicInOut(interp)), 0); - self.labelSVG.transform.baseVal.initialize(self.controller.svgElement.createSVGTransformFromMatrix(k)); - - const rot = rotationInterpol(cubicInOut(interp)); - self.setRotation(rot); - - const currentLength = lengthInterpol(cubicInOut(interp)); - d3__WEBPACK_IMPORTED_MODULE_4___default().select(self.outline).attr("width", currentLength).attr("x", -(currentLength / 2) + (0.5 * self.stickZoom)); - d3__WEBPACK_IMPORTED_MODULE_4___default().select(self.background).attr("width", currentLength).attr("x", -(currentLength / 2) + (0.5 * self.stickZoom)); - self.stickZoom = stickZoomInterpol(cubicInOut(interp)); - self.setAllLinkCoordinates(); - - for (let group of self.parentGroups) { - group.updateExpandedGroup(); - } - - if (interp === 1) { // finished - tidy up - self.busy = false; - return true; - } else if (interp > 1 || isNaN(interp)) { - return update(1); - } else { - return false; - } - } - - d3__WEBPACK_IMPORTED_MODULE_4___default().select(this.ticks).attr("opacity", 0); - this.setScaleGroup(); - d3__WEBPACK_IMPORTED_MODULE_4___default().select(this.ticks).transition().attr("opacity", 1) - .delay(transitionTime * 0.8).duration(transitionTime / 2); - } - - toStickNoTransition() { - this.toStick(false); - } - - getCrossLinkPath(renderedCrossLink) { - const x1 = this.getResXwithStickZoom(renderedCrossLink.crosslink.fromResidue); - let baseLine = 0; - if (this.stickZoom >= 8) { - baseLine = -5; - } - - // following draws little flags - if (renderedCrossLink.crosslink.isMonoLink()) { //linker modified peptide - // if (renderedCrossLink.ambig === false) { - // renderedCrossLink.line.setAttribute("fill", "red"); //xiNET.defaultSelfLinkColour.toRGB()); - // } - const p1 = [x1, 26]; - const p3 = [x1, 18]; - const p2 = (0,_trig__WEBPACK_IMPORTED_MODULE_6__.rotatePointAboutPoint)(p1, p3, 60); - baseLine = baseLine * -1; - return "M " + x1 + "," + baseLine + - " L " + p1[0] + "," + p1[1] + - " L " + p2[0] + "," + p2[1] + - " L " + p3[0] + "," + p3[1]; - } else { - - const x2 = this.getResXwithStickZoom(renderedCrossLink.crosslink.toResidue); - let height, cp1, cp2, arcStart, arcEnd, arcRadius; - arcRadius = (Math.abs(x2 - x1)) / 2; - height = -((RenderedProtein.STICKHEIGHT / 2) + 3); - if (arcRadius < 15) { - height = -28 + arcRadius; - } - - const start = [x1, baseLine]; - const end = [x2, baseLine]; - - //~ // draws a a little triangle for *truly* intraMolecular - e.g. internally linked peptides - //~ // not in use - //~ if (renderedCrossLink.intraMolecular === true){ - //~ var curveMidX = x1 + ((x2 - x1) / 2); - //~ arcStart = [ curveMidX, height - arcRadius]; - //~ arcEnd = [ curveMidX, height - arcRadius]; - //~ cp1 = [ curveMidX, height - arcRadius]; - //~ cp2 = [ curveMidX, height - arcRadius]; - - //~ } - //~ else - if (renderedCrossLink.crosslink.confirmedHomomultimer) { - const curveMidX = x1 + ((x2 - x1) / 2); - arcStart = [curveMidX, height - arcRadius]; - arcEnd = [curveMidX, height - arcRadius]; - cp1 = (0,_trig__WEBPACK_IMPORTED_MODULE_6__.rotatePointAboutPoint)([x1, height - arcRadius], start, -20); - cp2 = (0,_trig__WEBPACK_IMPORTED_MODULE_6__.rotatePointAboutPoint)([x2, height - arcRadius], end, 20); - - //flip - start[1] = start[1] * -1; - cp1[1] = cp1[1] * -1; - arcStart[1] = arcStart[1] * -1; - arcEnd[1] = arcEnd[1] * -1; - cp2[1] = cp2[1] * -1; - end[1] = end[1] * -1; - - } else { - cp1 = [x1, height]; - cp2 = [x2, baseLine]; - arcStart = [x1, height]; - arcEnd = [x2, height]; - } - - return " M " + start[0] + "," + start[1] + - " Q " + cp1[0] + "," + cp1[1] + " " + arcStart[0] + "," + arcStart[1] + - " A " + arcRadius + "," + arcRadius + " 0 0 1 " + arcEnd[0] + "," + arcEnd[1] + - " Q " + cp2[0] + "," + cp2[1] + " " + end[0] + "," + end[1]; - - } - } - - getResXwithStickZoom(r) { - return (r - (this.participant.size / 2)) * this.stickZoom; - } - - checkLinks() { - for (let p_pLink of this.renderedP_PLinks) { - //p_pLink.check(); - p_pLink.update(); - } - for (let renderedCrosslink of this.renderedCrosslinks) { - renderedCrosslink.check(); - } - } - - clearPositionalFeatures() { - this.annotations = new Map(); - if (this.circDomains) d3__WEBPACK_IMPORTED_MODULE_4___default().select(this.circDomains).selectAll("*").remove(); - if (this.rectDomains) d3__WEBPACK_IMPORTED_MODULE_4___default().select(this.rectDomains).selectAll("*").remove(); - } - - setPositionalFeatures() { - this.clearPositionalFeatures(); - const annotationTypes = this.controller.model.get("annotationTypes"); - //create new annotations - - // does all of the commented out above, and picks up user-defined annotations - let featuresShown = this.controller.model.getFilteredFeatures(this.participant); - const split = underscore__WEBPACK_IMPORTED_MODULE_0__.partition(featuresShown, function (f) { - return f.type === RenderedProtein.disulfide; - }); - const disulfidBonds = split[0]; - featuresShown = split[1]; - - if (featuresShown || disulfidBonds) { - //draw longest regions first - featuresShown.sort(function (a, b) { - return (b.end - b.begin) - (a.end - a.begin); - }); - - //~ disulfidBonds.sort(function(a, b) { - //~ return b.begin - a.begin; - //~ }); - - featuresShown = featuresShown.concat(disulfidBonds); - - const fsLen = featuresShown.length; - for (let f = 0; f < fsLen; f++) { - - const anno = featuresShown[f]; - - let convStart = anno.begin; - let convEnd = anno.end; - const alignModel = this.controller.model.get("alignColl").get(this.participant.id); - let withinAlignedRange = true; - - // mjg next 5 lines - const annotationTypeModel = annotationTypes.get(annotationTypes.modelId(anno)); - const annotationTypeModelAlignmentID = annotationTypeModel ? annotationTypeModel.get("typeAlignmentID") : undefined; - const alignmentID = anno.alignmentID || annotationTypeModelAlignmentID; // individual feature alignment ids trump feature type alignment ids (needed for multiple pdb chain alignments) - // it will be undefined for annotations/annotaion types aligned to search sequence so skips the next bit - - if ( //anno.category != "AA" // this handles not aligning certain features, todo; check for tidier way - alignmentID && alignModel) { - //var alignmentID = anno.alignmentID || "Canonical"; - const conv = alignModel.rangeToSearch(alignmentID, anno.begin, anno.end); - if (conv) { - convStart = conv[0]; - convEnd = conv[1]; - } else { - withinAlignedRange = false; // when conv returns null - } - } - //TODO: tooltip requring these to be written into feature object, seems wrong? - anno.fstart = +convStart; // + to convert to number - anno.fend = +convEnd; - - const fid = anno.category + "-" + anno.type + "-" + anno.alignmentID + "[" + convStart + " - " + convEnd + "]"; - - if (withinAlignedRange) { - const pieSlice = document.createElementNS(_crosslink_viewer_BB__WEBPACK_IMPORTED_MODULE_3__.CrosslinkViewer.svgns, "path"); - const colouredRect = document.createElementNS(_crosslink_viewer_BB__WEBPACK_IMPORTED_MODULE_3__.CrosslinkViewer.svgns, "path"); - if (anno.type !== RenderedProtein.disulfide) { - //if (anno.type != "disulfide bond") { - if (!this.expanded) { - pieSlice.setAttribute("d", this.getAnnotationPieSliceArcPath(anno)); - colouredRect.setAttribute("d", this.getAnnotationPieSliceApproximatePath(anno)); - } else { - pieSlice.setAttribute("d", this.getAnnotationRectPath(anno)); - colouredRect.setAttribute("d", this.getAnnotationRectPath(anno)); - } - pieSlice.setAttribute("stroke-width", "1"); - pieSlice.setAttribute("fill-opacity", "0.5"); - colouredRect.setAttribute("stroke-width", "1"); - colouredRect.setAttribute("fill-opacity", "0.5"); - - const c = annotationTypes.getColour(anno.category, anno.type); // domainColours(anno.category, anno.type); - pieSlice.setAttribute("fill", c); - pieSlice.setAttribute("stroke", c); - colouredRect.setAttribute("fill", c); - colouredRect.setAttribute("stroke", c); - } else { - - if (!this.expanded) { - pieSlice.setAttribute("d", this.getDisulfidAnnotationCircPath(anno)); - colouredRect.setAttribute("d", this.getDisulfidAnnotationCircPath(anno)); - } else { - pieSlice.setAttribute("d", this.getDisulfidAnnotationRectPath(anno, f)); - colouredRect.setAttribute("d", this.getDisulfidAnnotationRectPath(anno, f)); - } - pieSlice.setAttribute("stroke-width", "1"); - colouredRect.setAttribute("stroke-width", "1"); - - const c = annotationTypes.getColour(anno.category, anno.type); // domainColours(anno.category, anno.type); - pieSlice.setAttribute("fill", "none"); - pieSlice.setAttribute("stroke", c); - colouredRect.setAttribute("fill", "none"); - colouredRect.setAttribute("stroke", c); - } - - pieSlice.setAttribute("data-feature", fid); - - const self = this; - - //only needs tooltip on pie slice, its always on top even if transparent - pieSlice.onmouseover = function (evt) { - self.controller.preventDefaultsAndStopPropagation(evt); - const feature = self.annotations.get(evt.target.getAttribute("data-feature")).feature; - self.controller.model.get("tooltipModel") - //.set("header", d.id.replace("_", " ")) - .set("header", _xiview_js_make_tooltip__WEBPACK_IMPORTED_MODULE_5__.makeTooltipTitle.feature()) - .set("contents", - _xiview_js_make_tooltip__WEBPACK_IMPORTED_MODULE_5__.makeTooltipContents.feature(feature) - ) - .set("location", { - pageX: evt.pageX, - pageY: evt.pageY - }); - }; - - this.annotations.set(fid, { - feature: anno, - pieSlice: pieSlice, - colouredRect: colouredRect - }); - this.circDomains.appendChild(pieSlice); - this.rectDomains.appendChild(colouredRect); - } - } - } - } - - getAnnotationPieSliceArcPath(annotation) { - let startAngle = ((annotation.fstart - 1) / this.participant.size) * 360; - let endAngle = (annotation.fend / this.participant.size) * 360; - //just in case - if (startAngle > endAngle) { - const temp = startAngle; - startAngle = endAngle; - endAngle = temp; - } - let largeArcFlag = 0, - sweepFlag = 1; - if ((endAngle - startAngle) > 180) { //|| (endAngle - startAngle) == 0) { - largeArcFlag = 1; - } - //hacky - //actually its not clear there is better solution - - // https://stackoverflow.com/questions/5737975/circle-drawing-with-svgs-arc-path - if (annotation.fstart === 1 && annotation.fend === this.participant.size) { - startAngle = 0.1; - endAngle = 359.9; - sweepFlag = 1; - } - - const radius = this.symbolRadius - 2; - const arcStart = (0,_trig__WEBPACK_IMPORTED_MODULE_6__.trig)(radius, startAngle - 90); - const arcEnd = (0,_trig__WEBPACK_IMPORTED_MODULE_6__.trig)(radius, endAngle - 90); - return "M0,0 L" + arcStart.x + "," + arcStart.y + " A" + radius + "," + - radius + " 0 " + largeArcFlag + " " + sweepFlag + " " + arcEnd.x + "," + arcEnd.y + " Z"; - } - - getAnnotationPieSliceApproximatePath(annotation) { - //approximate pie slice - const startAngle = ((annotation.fstart - 1) / this.participant.size) * 360; - const endAngle = ((annotation.fend) / this.participant.size) * 360; - const pieRadius = this.symbolRadius - 2; - let approximatePiePath = "M 0,0"; - const stepsInArc = 5; - for (let sia = 0; sia <= RenderedProtein.stepsInArc; sia++) { - const angle = startAngle + ((endAngle - startAngle) * (sia / stepsInArc)); - const siaCoord = (0,_trig__WEBPACK_IMPORTED_MODULE_6__.trig)(pieRadius, angle - 90); - approximatePiePath += " L " + siaCoord.x + "," + siaCoord.y; - } - approximatePiePath += " L " + 0 + "," + 0; - approximatePiePath += " Z"; - return approximatePiePath; - } - - getAnnotationRectPath(annotation) { - //domain as rectangular path - const bottom = RenderedProtein.STICKHEIGHT / 2, - top = -RenderedProtein.STICKHEIGHT / 2; - const annotX = this.getResXwithStickZoom(annotation.fstart - 0.5); - const annotSize = (1 + (annotation.fend - annotation.fstart)); - const annotLength = annotSize * this.stickZoom; - let rectPath = "M " + annotX + "," + bottom; - for (let sia = 0; sia <= RenderedProtein.stepsInArc; sia++) { - const step = annotX + (annotLength * (sia / RenderedProtein.stepsInArc)); - rectPath += " L " + step + "," + top; - } - rectPath += " L " + (annotX + annotLength) + "," + bottom + - " Z"; - return rectPath; - } - - getDisulfidAnnotationRectPath(annotation/*, index*/) { - let bottom = RenderedProtein.STICKHEIGHT / 2, - top = 1.5 * bottom; - bottom = bottom - 5; - - const annotX = this.getResXwithStickZoom(annotation.fstart - 0.5); - const annotSize = (1 + (annotation.fend - annotation.fstart)); - - // const level = annotSize / 20; - top += annotSize * bottom / 30; - - - const annotLength = annotSize * this.stickZoom; - let rectPath = "M " + annotX + "," + bottom; - rectPath += " L " + annotX + "," + top; - rectPath += " L " + (annotX + annotLength) + "," + top; - rectPath += " L " + (annotX + annotLength) + "," + bottom; - return rectPath; - } - - getDisulfidAnnotationCircPath(/*annotation*/) { - return "M 0,0 L 0,0 L 0,0 L 0,0 "; - } - - get id () { - return this.participant.id; - } - - // addConnectedNodes (subgraph) { - // for (let link of this.renderedP_PLinks.values()) { - // //visible, non-self links only - // if (link.renderedFromProtein !== link.renderedToProtein && link.isPassingFilter()) { - // if (!subgraph.links.has(link.id)) { - // subgraph.links.set(link.id, link); - // let otherEnd; - // if (link.renderedFromProtein === this) { - // otherEnd = link.renderedToProtein; - // } else { - // otherEnd = link.renderedFromProtein; - // } - // // if (otherEnd !== null) { - // const renderedOtherEnd = otherEnd.getRenderedInteractor(); - // renderedOtherEnd.subgraph = subgraph; - // //if (!subgraph.nodes.has(renderedOtherEnd.id)) { - // subgraph.nodes.set(renderedOtherEnd.id, renderedOtherEnd); - // otherEnd.subgraph = subgraph; - // otherEnd.addConnectedNodes(subgraph); - // //} - // // } - // } - // } - // } - // return subgraph; - // } - // - // - // countExternalLinks () { - // // return this.renderedP_PLinks.length; - // const renderedParticipantsLinkedTo = new Set(); - // //let countExternal = 0; - // for (let link of this.renderedP_PLinks) { - // if (link.crosslinks[0].isSelfLink() === false) { - // if (link.isPassingFilter()) { - // //countExternal++; - // renderedParticipantsLinkedTo.add(link.getOtherEnd(this).getRenderedInteractor()); - // } - // } - // } - // return renderedParticipantsLinkedTo.size; - // - // } - -} - -RenderedProtein.STICKHEIGHT = 20; // height of stick in pixels -RenderedProtein.LABELMAXLENGTH = 60; // maximal width reserved for protein-labels -RenderedProtein.transitionTime = 650; -RenderedProtein.stepsInArc = 5; -RenderedProtein.rotOffset = 25 * 0.7; // see xiNET.Rotator.js -RenderedProtein.minXDist = 30; -RenderedProtein.disulfide = "disulfide bond"; - - -/***/ }), - -/***/ "./crosslink-viewer/js/views/xinet/interactor/rotator.js": -/*!***************************************************************!*\ - !*** ./crosslink-viewer/js/views/xinet/interactor/rotator.js ***! - \***************************************************************/ -/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { - -"use strict"; -__webpack_require__.r(__webpack_exports__); -/* harmony export */ __webpack_require__.d(__webpack_exports__, { -/* harmony export */ Rotator: () => (/* binding */ Rotator) -/* harmony export */ }); -/* harmony import */ var _crosslink_viewer_BB__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../crosslink-viewer-BB */ "./crosslink-viewer/js/views/xinet/crosslink-viewer-BB.js"); - - -class Rotator { - constructor(protein, upperOrLower, controller) { - const self = this; - this.controller = controller; - this.protein = protein; - this.upperOrLower = upperOrLower; - - const RADIUS = 14; - const SYMBOL_RADIUS = 20; // not really, gets scaled down - - this.svg = document.createElementNS(_crosslink_viewer_BB__WEBPACK_IMPORTED_MODULE_0__.CrosslinkViewer.svgns, "g"); - this.rotatorSymbol = document.createElementNS(_crosslink_viewer_BB__WEBPACK_IMPORTED_MODULE_0__.CrosslinkViewer.svgns, "g"); - - const rotatorCircle = document.createElementNS(_crosslink_viewer_BB__WEBPACK_IMPORTED_MODULE_0__.CrosslinkViewer.svgns, "circle"); - rotatorCircle.setAttribute("r", "" + RADIUS); - rotatorCircle.setAttribute("stroke", "none"); - rotatorCircle.setAttribute("fill", "gray"); - rotatorCircle.setAttribute("fill-opacity", "0.0"); - this.svg.appendChild(rotatorCircle); - - const symbolCircle = document.createElementNS(_crosslink_viewer_BB__WEBPACK_IMPORTED_MODULE_0__.CrosslinkViewer.svgns, "circle"); - symbolCircle.setAttribute("r", "" + SYMBOL_RADIUS); - symbolCircle.setAttribute("stroke", "black"); - symbolCircle.setAttribute("stroke-width", "1"); - symbolCircle.setAttribute("fill", "none"); - this.rotatorSymbol.appendChild(symbolCircle); - - const arrow1 = document.createElementNS(_crosslink_viewer_BB__WEBPACK_IMPORTED_MODULE_0__.CrosslinkViewer.svgns, "path"); - arrow1.setAttribute("d", "M 19.818182,-3 L 16,3.10345 L 23.636363,3.10345 L 19.818182,-3 z "); - arrow1.setAttribute("stroke", "black"); - arrow1.setAttribute("stroke-width", "1"); - arrow1.setAttribute("fill", "black"); - - this.rotatorSymbol.appendChild(arrow1); - const arrow2 = document.createElementNS(_crosslink_viewer_BB__WEBPACK_IMPORTED_MODULE_0__.CrosslinkViewer.svgns, "path"); - arrow2.setAttribute("d", "M 19.818182,-3 L 16,3.10345 L 23.636363,3.10345 L 19.818182,-3 z "); - arrow2.setAttribute("stroke", "black"); - arrow2.setAttribute("stroke-width", "1"); - arrow2.setAttribute("fill", "black"); - arrow2.setAttribute("transform", "rotate(180)"); - this.rotatorSymbol.appendChild(arrow2); - this.rotatorSymbol.setAttribute("transform", "rotate(45) scale (0.7, 0.7)"); - - this.rotatorSymbol.setAttribute("display", "none"); - - this.inner = document.createElementNS(_crosslink_viewer_BB__WEBPACK_IMPORTED_MODULE_0__.CrosslinkViewer.svgns, "g"); - this.inner.setAttribute("class", "PV_rotator"); - this.inner.appendChild(this.rotatorSymbol); - - this.svg.appendChild(this.inner); - - this.svg.onmouseover = function (evt) { - self.rotatorMouseOver(evt); - }; - this.svg.onmouseout = function (evt) { - self.rotatorMouseOut(evt); - }; - this.svg.onmousedown = function (evt) { - self.rotatorMouseDown(evt); - }; - } - - rotatorMouseOver() { - this.rotatorSymbol.setAttribute("display", "block"); - } - - rotatorMouseOut() { - this.rotatorSymbol.setAttribute("display", "none"); - } - - rotatorMouseDown() { - this.controller.state = _crosslink_viewer_BB__WEBPACK_IMPORTED_MODULE_0__.CrosslinkViewer.STATES.ROTATING; - this.controller.dragElement = this.protein; - this.controller.whichRotator = this.upperOrLower; - } -} - -/***/ }), - -/***/ "./crosslink-viewer/js/views/xinet/link/g_g-link.js": -/*!**********************************************************!*\ - !*** ./crosslink-viewer/js/views/xinet/link/g_g-link.js ***! - \**********************************************************/ -/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { - -"use strict"; -__webpack_require__.r(__webpack_exports__); -/* harmony export */ __webpack_require__.d(__webpack_exports__, { -/* harmony export */ G_GLink: () => (/* binding */ G_GLink) -/* harmony export */ }); -/* harmony import */ var underscore__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! underscore */ "./node_modules/underscore/modules/index-all.js"); -/* harmony import */ var _link__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./link */ "./crosslink-viewer/js/views/xinet/link/link.js"); -/* harmony import */ var _crosslink_viewer_BB__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../crosslink-viewer-BB */ "./crosslink-viewer/js/views/xinet/crosslink-viewer-BB.js"); -/* harmony import */ var d3__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! d3 */ "./node_modules/d3/d3.js"); -/* harmony import */ var d3__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(d3__WEBPACK_IMPORTED_MODULE_3__); - - - - - -class G_GLink extends _link__WEBPACK_IMPORTED_MODULE_1__.Link { - - constructor(id, group1, group2, crosslinkViewer) { - super(crosslinkViewer); - - this.id = id; - this.isAggregateLink = true; - - this.p_pLinks = new Map(); - this.group1 = group1; - this.group2 = group2; - } - - getCrosslinks() { - let allCrosslinks = []; - for (let pp of this.p_pLinks.values()) { - allCrosslinks = allCrosslinks.concat(pp.crosslinks); - } - return allCrosslinks; - } - - initSVG() { - if (this.group1 !== this.group2) { - this.line = document.createElementNS(_crosslink_viewer_BB__WEBPACK_IMPORTED_MODULE_2__.CrosslinkViewer.svgns, "line"); - this.highlightLine = document.createElementNS(_crosslink_viewer_BB__WEBPACK_IMPORTED_MODULE_2__.CrosslinkViewer.svgns, "line"); - this.thickLine = document.createElementNS(_crosslink_viewer_BB__WEBPACK_IMPORTED_MODULE_2__.CrosslinkViewer.svgns, "line"); - } else { - this.group1.selfLink = this; - - this.line = document.createElementNS(_crosslink_viewer_BB__WEBPACK_IMPORTED_MODULE_2__.CrosslinkViewer.svgns, "path"); - this.highlightLine = document.createElementNS(_crosslink_viewer_BB__WEBPACK_IMPORTED_MODULE_2__.CrosslinkViewer.svgns, "path"); - this.thickLine = document.createElementNS(_crosslink_viewer_BB__WEBPACK_IMPORTED_MODULE_2__.CrosslinkViewer.svgns, "path"); - - this.initSelfLinkSVG(); - } - - this.line.setAttribute("class", "link"); - this.line.setAttribute("fill", "none"); - this.line.setAttribute("stroke-width", _crosslink_viewer_BB__WEBPACK_IMPORTED_MODULE_2__.CrosslinkViewer.linkWidth); - this.line.setAttribute("stroke-linecap", "round"); - - this.highlightLine.setAttribute("class", "link highlightedLink"); - this.highlightLine.setAttribute("fill", "none"); - this.highlightLine.setAttribute("stroke-width", "10"); - this.highlightLine.setAttribute("stroke-linecap", "round"); - this.highlightLine.setAttribute("stroke-opacity", "0"); - - this.thickLine.setAttribute("class", "link"); - this.thickLine.setAttribute("fill", "none"); - this.thickLine.setAttribute("stroke", "#ddd"); - this.thickLine.setAttribute("stroke-linecap", "round"); - this.thickLine.setAttribute("stroke-linejoin", "round"); - - this.controller.p_pLinksWide.appendChild(this.thickLine); - this.controller.highlights.appendChild(this.highlightLine); - this.controller.p_pLinks.appendChild(this.line); - - //set the events for it - const self = this; - const setMouseEvents = function (svgElement) { - svgElement.onmousedown = function (evt) { - self.mouseDown(evt); - }; - svgElement.onmouseover = function (evt) { - self.mouseOver(evt); - }; - svgElement.onmouseout = function (evt) { - self.mouseOut(evt); - }; - // this.line.ontouchstart = function(evt) { - // self.touchStart(evt); - // }; - svgElement.oncontextmenu = function () { - return false; - }; - }; - setMouseEvents(this.line); - setMouseEvents(this.highlightLine); - setMouseEvents(this.thickLine); - } - - mouseOver(evt) { - const p = this.controller.getEventPoint(evt); - let allCrosslinks = []; - this.filteredCrosslinkCount = 0; - let filteredMatchCount = 0; - let ppiCount = 0; - for (let pp of this.p_pLinks.values()) { - if (pp.filteredCrossLinkCount > 0) { - allCrosslinks = allCrosslinks.concat(pp.crosslinks); - ppiCount++; - this.filteredCrosslinkCount += pp.filteredCrossLinkCount; - filteredMatchCount += pp.filteredMatchCount; - } - } - this.controller.model.setMarkedCrossLinks("highlights", allCrosslinks, true, false); - this.controller.model.get("tooltipModel") - //TODO - reuse other multiLink tooltips in CLM-UI? - .set("header", "Group to Group Links") - .set("contents", [ - ["From", this.group1.name], - ["To", this.group2.name], - ["PPI count", ppiCount], - ["Unique Linked Residue Pairs", this.filteredCrosslinkCount], - ["Matches", filteredMatchCount ? filteredMatchCount : "filter not yet applied"] - //highest score - ]) - .set("location", { - pageX: p.x, - pageY: p.y - }); - } - - // event handler for starting dragging or rotation (or flipping internal links) - mouseDown(evt) { - this.controller.d3cola.stop(); - let allCrosslinks = []; - for (let pp of this.p_pLinks.values()) { - allCrosslinks = allCrosslinks.concat(pp.crosslinks); - } - this.controller.dragElement = this; - if (evt.shiftKey || evt.ctrlKey) { - let selection = this.controller.model.get("selection"); - if (this.isSelected) { - selection = selection.filter(function (d) { - return allCrosslinks.indexOf(d) === -1; - }); - } else { - selection = selection.concat(allCrosslinks); - } - this.controller.model.setMarkedCrossLinks("selection", selection); - } else { - this.controller.model.setMarkedCrossLinks("selection", underscore__WEBPACK_IMPORTED_MODULE_0__.clone(allCrosslinks)); - } - //store start location - this.controller.dragStart = evt; - d3__WEBPACK_IMPORTED_MODULE_3___default().select(".custom-menu-margin").style("display", "none"); - d3__WEBPACK_IMPORTED_MODULE_3___default().select(".group-custom-menu-margin").style("display", "none"); - } - - /*xiNET.P_PLink.prototype.touchStart = function(evt) { - this.controller.d3cola.stop(); - this.controller.dragElement = this; - this.controller.model.setMarkedCrossLinks("selection", this.crosslinks); - //store start location - //var p = this.controller.getTouchEventPoint(evt);// oh dear, now broken - this.controller.dragStart = evt; - }*/ - - initSelfLinkSVG() { - const path = this.group1.getAggregateSelfLinkPath(); - this.line.setAttribute("d", path); - this.highlightLine.setAttribute("d", path); - this.thickLine.setAttribute("d", path); - } - - checkHighlight() { - for (let pp of this.p_pLinks.values()) { - // if (pp.filteredCrossLinkCount > 0) { ? // shouldn't be needed - if (pp.isHighlighted) { - this.showHighlight(true); - return; - } - } - this.showHighlight(false); - } - - checkSelected() { - for (let pp of this.p_pLinks.values()) { - // if (pp.filteredCrossLinkCount > 0) { ? // shouldn't be needed - if (pp.isSelected) { - this.setSelected(true); - return; - } - } - this.setSelected(false); - } - - showHighlight(show) { - if (this.shown) { - if (show) { - d3__WEBPACK_IMPORTED_MODULE_3___default().select(this.highlightLine).classed("selectedLink", false); - d3__WEBPACK_IMPORTED_MODULE_3___default().select(this.highlightLine).classed("highlightedLink", true); - this.highlightLine.setAttribute("stroke-opacity", "1"); - } else { - d3__WEBPACK_IMPORTED_MODULE_3___default().select(this.highlightLine).classed("selectedLink", true); - d3__WEBPACK_IMPORTED_MODULE_3___default().select(this.highlightLine).classed("highlightedLink", false); - if (this.isSelected === false) { - this.highlightLine.setAttribute("stroke-opacity", "0"); - } - } - } - } - - setSelected(select) { - if (this.shown) { - if (select === true) { - d3__WEBPACK_IMPORTED_MODULE_3___default().select(this.highlightLine).classed("selectedLink", true); - d3__WEBPACK_IMPORTED_MODULE_3___default().select(this.highlightLine).classed("highlightedLink", false); - this.highlightLine.setAttribute("stroke-opacity", "1"); - } else { - this.highlightLine.setAttribute("stroke-opacity", "0"); - d3__WEBPACK_IMPORTED_MODULE_3___default().select(this.highlightLine).classed("selectedLink", false); - d3__WEBPACK_IMPORTED_MODULE_3___default().select(this.highlightLine).classed("highlightedLink", true); - } - } - this.isSelected = select; - } - - check() { - for (let pp of this.p_pLinks.values()) { - if (pp.filteredCrossLinkCount > 0) { - return true; - } - } - return false; - } - - // xiNET.P_PLink.prototype.check = function () { - // // this.ambiguous = true; // todo - looks like this could be removed - // this.hd = false; - // - // const filteredCrossLinks = new Set(); - // const filteredMatches = new Set(); - // const altP_PLinks = new Set(); - // - // // this.colours.clear(); - // - // for (let crosslink of this.crosslinks) { - // - // if (crosslink.filteredMatches_pp.length > 0) { - // filteredCrossLinks.add(crosslink.id); - // // this.colours.add(window.compositeModelInst.get("linkColourAssignment").getColour(crosslink)); - // } - // - // for (let m of crosslink.filteredMatches_pp) { - // // i think there's a performance improvement to be had here - // const match = m.match; // oh dear, this... - // filteredMatches.add(match.id); - // if (match.hd === true) { - // this.hd = true; - // } - // if (match.crosslinks.length === 1) { - // // this.ambiguous = false; //yeah... whats this doing when this.ambiguous gets set later, just before end of function - // } else { - // for (let matchCrossLink of match.crosslinks) { - // if (!matchCrossLink.isDecoyLink()) { - // altP_PLinks.add(matchCrossLink.p_pLink.id); - // } - // } - // } - // } - // } - // - // this.filteredMatchCount = filteredMatches.size; - // this.filteredCrossLinkCount = filteredCrossLinks.size; - // if (this.filteredCrossLinkCount > 0) { - // this.ambiguous = altP_PLinks.size > 1; - // } - // return this.filteredCrossLinkCount; - // }; - - // xiNET.P_PLink.prototype.update = function () { - // if (!this.renderedToProtein || // todo - ok... check why this is here - // //hide if prot either end is hidden - // this.renderedFromProtein.participant.hidden || - // this.renderedToProtein.participant.hidden || - // // or either end is expanded to bar and not in collapsed group - // (this.renderedFromProtein.expanded && !this.renderedFromProtein.inCollapsedGroup()) || - // (this.renderedToProtein.expanded && !this.renderedToProtein.inCollapsedGroup()) || - // // or no matches pass filter - // this.filteredCrossLinkCount === 0 || - // // or is self link in collapsed group - // (this.crosslinks[0].isSelfLink() && this.renderedFromProtein.inCollapsedGroup())) { - // this.hide(); - // } else { - // - // // if (both ends in collapsed groups) { - // // - // // } - // // - // this.show(); - // } - // } - - show() { - //if (!this.shown) { - causing problems with load layout, TODO - look at again - if (typeof this.line === "undefined") { - this.initSVG(); - } - this.shown = true; - if (this.group1 === this.group2) { - this.thickLine.setAttribute("transform", "translate(" + - this.group1.ix + " " + this.group2.iy + ")" // possibly not neccessary - + - " scale(" + (this.controller.z) + ")"); - this.line.setAttribute("transform", "translate(" + this.group1.ix + - " " + this.group1.iy + ")" + " scale(" + (this.controller.z) + ")"); - this.highlightLine.setAttribute("transform", "translate(" + this.group1.ix + - " " + this.group1.iy + ")" + " scale(" + (this.controller.z) + ")"); - - } else { - this.line.setAttribute("stroke-width", (this.controller.z * _crosslink_viewer_BB__WEBPACK_IMPORTED_MODULE_2__.CrosslinkViewer.linkWidth).toString()); - this.highlightLine.setAttribute("stroke-width", (this.controller.z * 10).toString()); - this.setLineCoordinates(); - } - d3__WEBPACK_IMPORTED_MODULE_3___default().select(this.thickLine).style("display", null); - d3__WEBPACK_IMPORTED_MODULE_3___default().select(this.line).style("display", null); - d3__WEBPACK_IMPORTED_MODULE_3___default().select(this.highlightLine).style("display", null); - //} - - if (this.controller.model.get("xinetThickLinks") === false) { - d3__WEBPACK_IMPORTED_MODULE_3___default().select(this.thickLine).style("display", "none"); - } else { - d3__WEBPACK_IMPORTED_MODULE_3___default().select(this.thickLine).style("display", null); - this.updateThickLineWidth(); - } - - // this.dashedLine(this.ambiguous); - - this.line.setAttribute("stroke", window.compositeModelInst.get("linkColourAssignment").getColour(this)); - - this.setSelected(this.isSelected); - } - - updateThickLineWidth() { - const steps = this.controller.model.get("xinetPpiSteps"); - - let thickLineWidth; - if (this.filteredCrosslinkCount < steps[0]) { - thickLineWidth = 1; - } else if (this.filteredCrosslinkCount < steps[1]) { - thickLineWidth = 5; - } else { - thickLineWidth = 10; - } - if (this.group1 === this.group2) { - this.thickLine.setAttribute("stroke-width", thickLineWidth); - } else { - this.thickLine.setAttribute("stroke-width", (this.controller.z * thickLineWidth).toString()); - } - } - - hide() { - // if (this.shown) { - // this.shown = false; - d3__WEBPACK_IMPORTED_MODULE_3___default().select(this.thickLine).style("display", "none"); - d3__WEBPACK_IMPORTED_MODULE_3___default().select(this.highlightLine).style("display", "none"); - d3__WEBPACK_IMPORTED_MODULE_3___default().select(this.line).style("display", "none"); - // } - } - - setLineCoordinates() { - if (this.group1 !== this.group2) { - if (this.shown) { - const source = this.group1;//.getRenderedInteractor(); - const target = this.group2;//renderedToProtein.getRenderedInteractor(); - if (!source.ix || !source.iy) { - console.log("NOT"); - } - - // if (this.renderedFromProtein === participant) { - this.line.setAttribute("x1", source.ix); - this.line.setAttribute("y1", source.iy); - this.highlightLine.setAttribute("x1", source.ix); - this.highlightLine.setAttribute("y1", source.iy); - this.thickLine.setAttribute("x1", source.ix); - this.thickLine.setAttribute("y1", source.iy); - // } else if (this.renderedToProtein === participant) { - this.line.setAttribute("x2", target.ix); - this.line.setAttribute("y2", target.iy); - this.highlightLine.setAttribute("x2", target.ix); - this.highlightLine.setAttribute("y2", target.iy); - this.thickLine.setAttribute("x2", target.ix); - this.thickLine.setAttribute("y2", target.iy); - // } - } - } - } -} - -/* -xiNET.P_PLink.prototype.getOtherEnd = function(protein) { - if (this.fromProtein === protein) { - return this.toProtein; - } else { - return this.fromProtein; - } -};*/ - - -/***/ }), - -/***/ "./crosslink-viewer/js/views/xinet/link/link.js": -/*!******************************************************!*\ - !*** ./crosslink-viewer/js/views/xinet/link/link.js ***! - \******************************************************/ -/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { - -"use strict"; -__webpack_require__.r(__webpack_exports__); -/* harmony export */ __webpack_require__.d(__webpack_exports__, { -/* harmony export */ Link: () => (/* binding */ Link) -/* harmony export */ }); -class Link { - - constructor(crosslinkViewer) { - this.controller = crosslinkViewer; - this.shown = false; //used to avoid some unnecessary manipulation of DOM - this.isSelected = false; - } - - mouseOut() { - this.controller.model.setMarkedCrossLinks("highlights", []); // which pokes highlighted matches into changing too - this.controller.model.get("tooltipModel").set("contents", null); - } - - dashedLine(dash) { - if (this.shown) { - if (dash) { - if (this.renderedFromProtein === this.renderedToProtein) { - this.line.setAttribute("stroke-dasharray", (4) + ", " + (4)); - } else { - this.line.setAttribute("stroke-dasharray", (4 * this.controller.z) + ", " + (4 * this.controller.z)); - } - } else { - this.line.removeAttribute("stroke-dasharray"); - } - } - } -} - - -/***/ }), - -/***/ "./crosslink-viewer/js/views/xinet/link/p_p-link.js": -/*!**********************************************************!*\ - !*** ./crosslink-viewer/js/views/xinet/link/p_p-link.js ***! - \**********************************************************/ -/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { - -"use strict"; -__webpack_require__.r(__webpack_exports__); -/* harmony export */ __webpack_require__.d(__webpack_exports__, { -/* harmony export */ P_PLink: () => (/* binding */ P_PLink) -/* harmony export */ }); -/* harmony import */ var underscore__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! underscore */ "./node_modules/underscore/modules/index-all.js"); -/* harmony import */ var _link__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./link */ "./crosslink-viewer/js/views/xinet/link/link.js"); -/* harmony import */ var _crosslink_viewer_BB__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../crosslink-viewer-BB */ "./crosslink-viewer/js/views/xinet/crosslink-viewer-BB.js"); -/* harmony import */ var _g_g_link__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./g_g-link */ "./crosslink-viewer/js/views/xinet/link/g_g-link.js"); -/* harmony import */ var d3__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! d3 */ "./node_modules/d3/d3.js"); -/* harmony import */ var d3__WEBPACK_IMPORTED_MODULE_4___default = /*#__PURE__*/__webpack_require__.n(d3__WEBPACK_IMPORTED_MODULE_4__); - - - - - - - -class P_PLink extends _link__WEBPACK_IMPORTED_MODULE_1__.Link { - - constructor(p_pId, crosslink, crosslinkViewer) { - super(crosslinkViewer); - this.isAggregateLink = true; - this.id = p_pId; - this.crosslinks = []; - this.renderedFromProtein = this.controller.renderedProteins.get(crosslink.fromProtein.id); - this.renderedFromProtein.renderedP_PLinks.push(this); - if (crosslink.toProtein) { - this.renderedToProtein = this.controller.renderedProteins.get(crosslink.toProtein.id); - this.renderedToProtein.renderedP_PLinks.push(this); - } - } - - getCrosslinks() { - return this.crosslinks; - } - - initSVG() { - if (this.crosslinks[0].isSelfLink() === false) { - this.line = document.createElementNS(_crosslink_viewer_BB__WEBPACK_IMPORTED_MODULE_2__.CrosslinkViewer.svgns, "line"); - this.highlightLine = document.createElementNS(_crosslink_viewer_BB__WEBPACK_IMPORTED_MODULE_2__.CrosslinkViewer.svgns, "line"); - this.thickLine = document.createElementNS(_crosslink_viewer_BB__WEBPACK_IMPORTED_MODULE_2__.CrosslinkViewer.svgns, "line"); - } else { - this.renderedFromProtein.selfLink = this; - - this.line = document.createElementNS(_crosslink_viewer_BB__WEBPACK_IMPORTED_MODULE_2__.CrosslinkViewer.svgns, "path"); - this.highlightLine = document.createElementNS(_crosslink_viewer_BB__WEBPACK_IMPORTED_MODULE_2__.CrosslinkViewer.svgns, "path"); - this.thickLine = document.createElementNS(_crosslink_viewer_BB__WEBPACK_IMPORTED_MODULE_2__.CrosslinkViewer.svgns, "path"); - - this.initSelfLinkSVG(); - } - - this.line.setAttribute("class", "link"); - this.line.setAttribute("fill", "none"); - this.line.setAttribute("stroke-width", _crosslink_viewer_BB__WEBPACK_IMPORTED_MODULE_2__.CrosslinkViewer.linkWidth); - this.line.setAttribute("stroke-linecap", "round"); - - this.highlightLine.setAttribute("class", "link highlightedLink"); - this.highlightLine.setAttribute("fill", "none"); - this.highlightLine.setAttribute("stroke-width", "10"); - this.highlightLine.setAttribute("stroke-linecap", "round"); - this.highlightLine.setAttribute("stroke-opacity", "0"); - - this.thickLine.setAttribute("class", "link"); - this.thickLine.setAttribute("fill", "none"); - this.thickLine.setAttribute("stroke", "#ddd"); - this.thickLine.setAttribute("stroke-linecap", "round"); - this.thickLine.setAttribute("stroke-linejoin", "round"); - - this.controller.p_pLinksWide.appendChild(this.thickLine); - this.controller.highlights.appendChild(this.highlightLine); - this.controller.p_pLinks.appendChild(this.line); - - //set the events for it - const self = this; - const setMouseEvents = function (svgElement) { - svgElement.onmousedown = function (evt) { - self.mouseDown(evt); - }; - svgElement.onmouseover = function (evt) { - self.mouseOver(evt); - }; - svgElement.onmouseout = function (evt) { - self.mouseOut(evt); - }; - // this.line.ontouchstart = function(evt) { - // self.touchStart(evt); - // }; - svgElement.oncontextmenu = function () { - return false; - }; - }; - setMouseEvents(this.line); - setMouseEvents(this.highlightLine); - setMouseEvents(this.thickLine); - } - - mouseOver(evt) { - const p = this.controller.getEventPoint(evt); - const toHighlight = this.crosslinks.slice(0); - this.controller.model.setMarkedCrossLinks("highlights", toHighlight, true, false); - this.controller.model.get("tooltipModel") - .set("header", "Linked Protein Pair") - .set("contents", [ - ["From", this.renderedFromProtein.participant.name], - ["To", this.renderedToProtein.participant.name], - ["Unique Linked Residue Pairs", this.filteredCrossLinkCount ? this.filteredCrossLinkCount : "filter not yet applied"], - ["Matches", this.filteredMatchCount ? this.filteredMatchCount : "filter not yet applied"] - //highest score - ]) - .set("location", { - pageX: p.x, - pageY: p.y - }); - } - - // event handler for starting dragging or rotation (or flipping internal links) - mouseDown(evt) { - //stop layout - this.controller.d3cola.stop(); - - this.controller.dragElement = this; - if (evt.shiftKey || evt.ctrlKey) { - let selection = this.controller.model.get("selection"); - if (this.isSelected) { - const self = this; - selection = selection.filter(function (d) { - return self.crosslinks.indexOf(d) === -1; - }); - } else { - selection = selection.concat(this.crosslinks); - } - this.controller.model.setMarkedCrossLinks("selection", selection); - } else { - this.controller.model.setMarkedCrossLinks("selection", underscore__WEBPACK_IMPORTED_MODULE_0__.clone(this.crosslinks)); - } - - //store start location - this.controller.dragStart = evt; - - d3__WEBPACK_IMPORTED_MODULE_4___default().select(".custom-menu-margin").style("display", "none"); - d3__WEBPACK_IMPORTED_MODULE_4___default().select(".group-custom-menu-margin").style("display", "none"); - } - - /*xiNET.P_PLink.prototype.touchStart = function(evt) { - this.controller.d3cola.stop(); - this.controller.dragElement = this; - this.controller.model.setMarkedCrossLinks("selection", this.crosslinks); - //store start location - //var p = this.controller.getTouchEventPoint(evt);// oh dear, now broken - this.controller.dragStart = evt; - }*/ - - initSelfLinkSVG() { - const path = this.renderedFromProtein.getAggregateSelfLinkPath(); - this.line.setAttribute("d", path); - this.highlightLine.setAttribute("d", path); - this.thickLine.setAttribute("d", path); - } - - showHighlight(show) { - if (this.shown) { - if (show) { - d3__WEBPACK_IMPORTED_MODULE_4___default().select(this.highlightLine).classed("selectedLink", false); - d3__WEBPACK_IMPORTED_MODULE_4___default().select(this.highlightLine).classed("highlightedLink", true); - this.highlightLine.setAttribute("stroke-opacity", "1"); - } else { - d3__WEBPACK_IMPORTED_MODULE_4___default().select(this.highlightLine).classed("selectedLink", true); - d3__WEBPACK_IMPORTED_MODULE_4___default().select(this.highlightLine).classed("highlightedLink", false); - if (this.isSelected === false) { - this.highlightLine.setAttribute("stroke-opacity", "0"); - } - } - } - this.isHighlighted = show; - } - - setSelected(select) { - if (this.shown) { - if (select === true) { - d3__WEBPACK_IMPORTED_MODULE_4___default().select(this.highlightLine).classed("selectedLink", true); - d3__WEBPACK_IMPORTED_MODULE_4___default().select(this.highlightLine).classed("highlightedLink", false); - this.highlightLine.setAttribute("stroke-opacity", "1"); - } else { - this.highlightLine.setAttribute("stroke-opacity", "0"); - d3__WEBPACK_IMPORTED_MODULE_4___default().select(this.highlightLine).classed("selectedLink", false); - d3__WEBPACK_IMPORTED_MODULE_4___default().select(this.highlightLine).classed("highlightedLink", true); - } - } - this.isSelected = select; - } - - update() { - if (!this.renderedToProtein || // not linear - //or either end hidden hidden - this.renderedFromProtein.participant.hidden || - this.renderedToProtein.participant.hidden || - // or is self link in collapsed group - (this.crosslinks[0].isSelfLink() && this.renderedFromProtein.inCollapsedGroup()) || - // or either end is expanded to bar and not in collapsed group - (this.renderedFromProtein.expanded && !this.renderedFromProtein.inCollapsedGroup()) || - (this.renderedToProtein.expanded && !this.renderedToProtein.inCollapsedGroup()) // || - ) { - this.hide(); - } else { - this.hd = false; - const filteredCrossLinks = new Set(); - const filteredMatches = new Set(); - const altP_PLinks = new Set(); - - for (let crosslink of this.crosslinks) { - if (crosslink.filteredMatches_pp.length > 0) { - filteredCrossLinks.add(crosslink.id); - for (let m of crosslink.filteredMatches_pp) { - const match = m.match; // oh dear, this... - filteredMatches.add(match.id); - if (match.hd === true) { - this.hd = true; - } - if (match.crosslinks.length > 1) { - for (let matchCrossLink of match.crosslinks) { - if (!matchCrossLink.isDecoyLink()) { - altP_PLinks.add(matchCrossLink.p_pLink.id); - } - } - } - } - } - - this.filteredMatchCount = filteredMatches.size; - this.filteredCrossLinkCount = filteredCrossLinks.size; - - if (this.filteredCrossLinkCount === 0) { - this.hide(); - } else { - this.ambiguous = altP_PLinks.size > 1; - - if (this.renderedFromProtein.inCollapsedGroup() && this.renderedToProtein.inCollapsedGroup()) { - const source = this.renderedFromProtein.getRenderedInteractor(); - const target = this.renderedToProtein.getRenderedInteractor(); - let ggId; - if (source.id < target.id) { - ggId = source.id + "_" + target.id; - } else { - ggId = target.id + "_" + source.id; - } - let ggLink = this.controller.g_gLinks.get(ggId); - if (!ggLink) { - if (source.id < target.id) { - ggLink = new _g_g_link__WEBPACK_IMPORTED_MODULE_3__.G_GLink(ggId, source, target, this.controller); - } else { - ggLink = new _g_g_link__WEBPACK_IMPORTED_MODULE_3__.G_GLink(ggId, target, source, this.controller); - } - this.controller.g_gLinks.set(ggId, ggLink); - } - ggLink.p_pLinks.set(this.id, this); - this.hide(); - // ggLink.show(); - } else { - this.show(); - } - - } - } - } - } - - show() { - //if (!this.shown) { - causing problems with load layout, TODO - look at again - if (typeof this.line === "undefined") { - this.initSVG(); - } - this.shown = true; - if (this.renderedFromProtein === this.renderedToProtein) { - this.thickLine.setAttribute("transform", "translate(" + - this.renderedFromProtein.ix + " " + this.renderedFromProtein.iy + ")" // possibly not necessary - + - " scale(" + (this.controller.z) + ")"); - this.line.setAttribute("transform", "translate(" + this.renderedFromProtein.ix + - " " + this.renderedFromProtein.iy + ")" + " scale(" + (this.controller.z) + ")"); - this.highlightLine.setAttribute("transform", "translate(" + this.renderedFromProtein.ix + - " " + this.renderedFromProtein.iy + ")" + " scale(" + (this.controller.z) + ")"); - - } else { - this.line.setAttribute("stroke-width", (this.controller.z * _crosslink_viewer_BB__WEBPACK_IMPORTED_MODULE_2__.CrosslinkViewer.linkWidth).toString()); - this.highlightLine.setAttribute("stroke-width", (this.controller.z * 10).toString()); - this.setLineCoordinates(this.renderedFromProtein); - this.setLineCoordinates(this.renderedToProtein); - } - d3__WEBPACK_IMPORTED_MODULE_4___default().select(this.thickLine).style("display", null); - d3__WEBPACK_IMPORTED_MODULE_4___default().select(this.line).style("display", null); - d3__WEBPACK_IMPORTED_MODULE_4___default().select(this.highlightLine).style("display", null); - //} - - if (this.controller.model.get("xinetThickLinks") === false) { - d3__WEBPACK_IMPORTED_MODULE_4___default().select(this.thickLine).style("display", "none"); - } else { - d3__WEBPACK_IMPORTED_MODULE_4___default().select(this.thickLine).style("display", null); - this.updateThickLineWidth(); - } - - this.dashedLine(this.ambiguous); - this.line.setAttribute("stroke", window.compositeModelInst.get("linkColourAssignment").getColour(this)); - this.setSelected(this.isSelected); - } - - // isPassingFilter() { - // for (let crosslink of this.crosslinks) { - // if (crosslink.filteredMatches_pp.length > 0) { - // return true; - // } - // } - // return false; - // } - - updateThickLineWidth() { - const steps = this.controller.model.get("xinetPpiSteps"); - - let thickLineWidth; - if (this.filteredCrossLinkCount < steps[0]) { - thickLineWidth = 1; - } else if (this.filteredCrossLinkCount < steps[1]) { - thickLineWidth = 5; - } else { - thickLineWidth = 10; - } - if (this.renderedFromProtein === this.renderedToProtein) { - this.thickLine.setAttribute("stroke-width", thickLineWidth); - } else { - this.thickLine.setAttribute("stroke-width", (this.controller.z * thickLineWidth).toString()); - } - } - - hide() { - if (this.shown) { - this.shown = false; - d3__WEBPACK_IMPORTED_MODULE_4___default().select(this.thickLine).style("display", "none"); - d3__WEBPACK_IMPORTED_MODULE_4___default().select(this.highlightLine).style("display", "none"); - d3__WEBPACK_IMPORTED_MODULE_4___default().select(this.line).style("display", "none"); - } - } - - setLineCoordinates() { - if (this.renderedToProtein && this.renderedFromProtein !== this.renderedToProtein) { - if (this.shown) { - const source = this.renderedFromProtein.getRenderedInteractor(); - const target = this.renderedToProtein.getRenderedInteractor(); - if (isNaN(source.ix) || isNaN(source.iy)) { - console.log("prot coords are NaN"); - } - - // if (this.renderedFromProtein === participant) { - this.line.setAttribute("x1", source.ix); - this.line.setAttribute("y1", source.iy); - this.highlightLine.setAttribute("x1", source.ix); - this.highlightLine.setAttribute("y1", source.iy); - this.thickLine.setAttribute("x1", source.ix); - this.thickLine.setAttribute("y1", source.iy); - // } else if (this.renderedToProtein === participant) { - this.line.setAttribute("x2", target.ix); - this.line.setAttribute("y2", target.iy); - this.highlightLine.setAttribute("x2", target.ix); - this.highlightLine.setAttribute("y2", target.iy); - this.thickLine.setAttribute("x2", target.ix); - this.thickLine.setAttribute("y2", target.iy); - // } - } - } - } - - // getOtherEnd (protein) { - // if (this.renderedFromProtein === protein) { - // return this.renderedToProtein; - // } else { - // return this.renderedFromProtein; - // } - // } - // - // getFromProtein(){ - // return this.fromProtein; - // } - // - // getToProtein(){ - // return this.fromProtein; - // } -} - - -/***/ }), - -/***/ "./crosslink-viewer/js/views/xinet/link/rendered-crosslink.js": -/*!********************************************************************!*\ - !*** ./crosslink-viewer/js/views/xinet/link/rendered-crosslink.js ***! - \********************************************************************/ -/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { - -"use strict"; -__webpack_require__.r(__webpack_exports__); -/* harmony export */ __webpack_require__.d(__webpack_exports__, { -/* harmony export */ RenderedCrosslink: () => (/* binding */ RenderedCrosslink) -/* harmony export */ }); -/* harmony import */ var _link__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./link */ "./crosslink-viewer/js/views/xinet/link/link.js"); -/* harmony import */ var _crosslink_viewer_BB__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../crosslink-viewer-BB */ "./crosslink-viewer/js/views/xinet/crosslink-viewer-BB.js"); -/* harmony import */ var _interactor_rendered_protein__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../interactor/rendered-protein */ "./crosslink-viewer/js/views/xinet/interactor/rendered-protein.js"); -/* harmony import */ var d3__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! d3 */ "./node_modules/d3/d3.js"); -/* harmony import */ var d3__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(d3__WEBPACK_IMPORTED_MODULE_3__); -/* harmony import */ var _xiview_js_make_tooltip__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../../../../../xiview/js/make-tooltip */ "./xiview/js/make-tooltip.js"); -/* harmony import */ var _trig__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ../trig */ "./crosslink-viewer/js/views/xinet/trig.js"); - - - - - - - -class RenderedCrosslink extends _link__WEBPACK_IMPORTED_MODULE_0__.Link { - constructor(crosslink, crosslinkViewer) { - super(crosslinkViewer); - this.isAggregateLink = false; - this.crosslink = crosslink; - - this.renderedFromProtein = this.controller.renderedProteins.get(this.crosslink.fromProtein.id); - this.renderedFromProtein.renderedCrosslinks.push(this); - if (this.crosslink.toProtein) { - this.renderedToProtein = this.controller.renderedProteins.get(this.crosslink.toProtein.id); - this.renderedToProtein.renderedCrosslinks.push(this); - } - - this.pepSvgArr = []; - } - - initSVG() { - if (this.crosslink.isSelfLink() || this.crosslink.isMonoLink()) { - this.line = document.createElementNS(_crosslink_viewer_BB__WEBPACK_IMPORTED_MODULE_1__.CrosslinkViewer.svgns, "path"); - this.line.setAttribute("stroke-width", _crosslink_viewer_BB__WEBPACK_IMPORTED_MODULE_1__.CrosslinkViewer.linkWidth); - this.highlightLine = document.createElementNS(_crosslink_viewer_BB__WEBPACK_IMPORTED_MODULE_1__.CrosslinkViewer.svgns, "path"); - this.renderedFromProtein.selfLinksHighlights.appendChild(this.highlightLine); - this.renderedFromProtein.selfLinks.appendChild(this.line); - } else { - this.line = document.createElementNS(_crosslink_viewer_BB__WEBPACK_IMPORTED_MODULE_1__.CrosslinkViewer.svgns, "line"); - this.line.setAttribute("stroke-linecap", "round"); - this.highlightLine = document.createElementNS(_crosslink_viewer_BB__WEBPACK_IMPORTED_MODULE_1__.CrosslinkViewer.svgns, "line"); - this.highlightLine.setAttribute("stroke-linecap", "round"); - this.controller.highlights.appendChild(this.highlightLine); - this.controller.res_resLinks.appendChild(this.line); - } - this.line.setAttribute("class", "link"); - this.line.setAttribute("fill", "none"); - this.highlightLine.setAttribute("class", "link highlightedLink"); - this.highlightLine.setAttribute("fill", "none"); - //this.highlightLine.setAttribute("stroke", CLMS.xiNET.highlightColour.toRGB()); - this.highlightLine.setAttribute("stroke-width", "10"); - this.highlightLine.setAttribute("stroke-opacity", "0"); - //set the events for it - const self = this; - const setMouseEvents = function (svgElement) { - svgElement.onmousedown = function (evt) { - self.mouseDown(evt); - }; - svgElement.onmouseover = function (evt) { - self.mouseOver(evt); - }; - svgElement.onmouseout = function (evt) { - self.mouseOut(evt); - }; - // this.line.ontouchstart = function(evt) { - // self.touchStart(evt); - // }; - svgElement.oncontextmenu = function () { - return false; - }; - }; - setMouseEvents(this.line); - setMouseEvents(this.highlightLine); - } - - mouseOver(evt) { - this.controller.preventDefaultsAndStopPropagation(evt); - if (this.renderedFromProtein.busy === false && (!this.renderedToProtein || this.renderedToProtein.busy === false)) { - const p = this.controller.getEventPoint(evt); - - const toHighlight = [this.crosslink]; - - this.controller.model.setMarkedCrossLinks("highlights", toHighlight, true, false); - - this.controller.model.get("tooltipModel") - .set("header", _xiview_js_make_tooltip__WEBPACK_IMPORTED_MODULE_4__.makeTooltipTitle.link()) - .set("contents", _xiview_js_make_tooltip__WEBPACK_IMPORTED_MODULE_4__.makeTooltipContents.link(this.crosslink)) - .set("location", { - pageX: p.x, - pageY: p.y - }); - } - } - - mouseDown(evt) { - this.controller.preventDefaultsAndStopPropagation(evt); - this.controller.d3cola.stop(); - this.controller.dragElement = this; - - let rightClick = (evt.button === 2); - - if (rightClick && this.crosslink.isSelfLink()) { - this.renderedFromProtein.toggleFlipped(); - } else { - const add = evt.shiftKey || evt.ctrlKey; - this.controller.model.setMarkedCrossLinks("selection", [this.crosslink], false, add); - } - //store start location - this.controller.dragStart = evt; - - d3__WEBPACK_IMPORTED_MODULE_3___default().select(".custom-menu-margin").style("display", "none"); - d3__WEBPACK_IMPORTED_MODULE_3___default().select(".group-custom-menu-margin").style("display", "none"); - } - - /*xiNET.RenderedCrosslink.prototype.touchStart = function(evt) { - this.controller.d3cola.stop(); - this.controller.dragElement = this; - var add = evt.shiftKey || evt.ctrlKey; - this.controller.model.setMarkedCrossLinks("selection", [this.crosslink], false, add); - //store start location - //var p = this.controller.getTouchEventPoint(evt);// broke - this.controller.dragStart = evt; //this.controller.mouseToSVG(p.x, p.y); - }*/ - - // andAlternatives means highlight alternative links in case of site ambiguity, - // need to be able to switch this on and off to avoid infinite loop - showHighlight(show) { - //~ if (!this.renderedFromProtein.busy && (!this.renderedToProtein || !this.renderedToProtein.busy)) { - if (this.shown) { - if (show) { - //this.highlightLine.setAttribute("stroke", CLMS.xiNET.highlightColour.toRGB()); - d3__WEBPACK_IMPORTED_MODULE_3___default().select(this.highlightLine).classed("selectedLink", false); - d3__WEBPACK_IMPORTED_MODULE_3___default().select(this.highlightLine).classed("highlightedLink", true); - this.highlightLine.setAttribute("stroke-opacity", "0.7"); - if (this.crosslink.filteredMatches_pp[0].match.matchedPeptides[0].seq_mods) { - const fromPeptides = [], - toPeptides = []; - //this is where we need the peptide positions - const filteredMatchesAndPeptidePositions = this.crosslink.filteredMatches_pp; - const fm_ppCount = filteredMatchesAndPeptidePositions.length; - for (let fm_pp = 0; fm_pp < fm_ppCount; fm_pp++) { - const matchAndPepPos = filteredMatchesAndPeptidePositions[fm_pp]; - const match = matchAndPepPos.match; - - const fromPepStart = matchAndPepPos.pepPos[0].start - 1; - const fromPepLength = matchAndPepPos.pepPos[0].length; - const toPepStart = matchAndPepPos.pepPos[1].start - 1; - const toPepLength = matchAndPepPos.pepPos[1].length; - - fromPeptides.push([fromPepStart, fromPepLength, match.overlap[0], match.overlap[1]]); - toPeptides.push([toPepStart, toPepLength, match.overlap[0], match.overlap[1]]); - } - if (this.renderedFromProtein.expanded) { - this.showPeptides(fromPeptides, this.renderedFromProtein); - } - if (this.renderedToProtein && this.renderedToProtein.expanded) { - this.showPeptides(toPeptides, this.renderedToProtein); - } - } - } else { - d3__WEBPACK_IMPORTED_MODULE_3___default().select(this.highlightLine).classed("selectedLink", true); - d3__WEBPACK_IMPORTED_MODULE_3___default().select(this.highlightLine).classed("highlightedLink", false); - if (this.isSelected === false) { - this.highlightLine.setAttribute("stroke-opacity", "0"); - } - this.removePeptides(); - } - } - } - - showPeptides(pepBounds, renderedProtein) { - let y = -_interactor_rendered_protein__WEBPACK_IMPORTED_MODULE_2__.RenderedProtein.STICKHEIGHT / 2; - const count = pepBounds.length; - const yIncrement = _interactor_rendered_protein__WEBPACK_IMPORTED_MODULE_2__.RenderedProtein.STICKHEIGHT / count; - for (let i = 0; i < count; i++) { - const pep = pepBounds[i]; - let annoColouredRect = document.createElementNS(_crosslink_viewer_BB__WEBPACK_IMPORTED_MODULE_1__.CrosslinkViewer.svgns, "rect"); - annoColouredRect.setAttribute("class", "protein"); - - //make domain rectangles - const annoSize = pep[1] - 0.2; - let annoX = ((pep[0] + 0.6) - (renderedProtein.participant.size / 2)); - let annoLength = annoSize; - annoColouredRect.setAttribute("x", annoX.toString()); - annoColouredRect.setAttribute("y", y.toString()); - annoColouredRect.setAttribute("width", annoLength.toString()); - annoColouredRect.setAttribute("height", yIncrement.toString()); - //style 'em - d3__WEBPACK_IMPORTED_MODULE_3___default().select(annoColouredRect).classed("highlightedPeptide", true); - //annotColouredRect.setAttribute("fill-opacity", "0.7"); - renderedProtein.peptides.appendChild(annoColouredRect); - this.pepSvgArr.push(annoColouredRect); - - if (typeof pep[2] != "undefined") { //homomultimer like - annoColouredRect = document.createElementNS(_crosslink_viewer_BB__WEBPACK_IMPORTED_MODULE_1__.CrosslinkViewer.svgns, "rect"); - annoColouredRect.setAttribute("class", "protein"); - annoX = ((pep[2] + 0.5) - (renderedProtein.participant.size / 2)); - annoLength = (pep[3] - pep[2]); - annoColouredRect.setAttribute("x", annoX.toString()); - annoColouredRect.setAttribute("y", y.toString()); - annoColouredRect.setAttribute("width", annoLength.toString()); - annoColouredRect.setAttribute("height", yIncrement.toString()); - - //style 'em - d3__WEBPACK_IMPORTED_MODULE_3___default().select(annoColouredRect).classed("peptideOverlap", true); - annoColouredRect.setAttribute("fill-opacity", "0.5"); - - renderedProtein.peptides.appendChild(annoColouredRect); - this.pepSvgArr.push(annoColouredRect); - } - y += yIncrement; - } - } - - removePeptides() { - const pepSvgArrCount = this.pepSvgArr.length; - for (let p = 0; p < pepSvgArrCount; p++) { - _crosslink_viewer_BB__WEBPACK_IMPORTED_MODULE_1__.CrosslinkViewer.removeDomElement(this.pepSvgArr[p]); - } - } - - setSelected(select) { - if (this.shown) { - if (select === true) { - d3__WEBPACK_IMPORTED_MODULE_3___default().select(this.highlightLine).classed("selectedLink", true); - d3__WEBPACK_IMPORTED_MODULE_3___default().select(this.highlightLine).classed("highlightedLink", false); - this.highlightLine.setAttribute("stroke-opacity", "0.7"); - } else { - this.highlightLine.setAttribute("stroke-opacity", "0"); - d3__WEBPACK_IMPORTED_MODULE_3___default().select(this.highlightLine).classed("selectedLink", false); - d3__WEBPACK_IMPORTED_MODULE_3___default().select(this.highlightLine).classed("highlightedLink", true); - } - } - this.isSelected = select; - } - - - //used when filter changed - check() { - // neither end is a bar which isn't in a collapsed group? then hide - if ((!this.renderedFromProtein.expanded || (this.renderedFromProtein.inCollapsedGroup())) && - (this.renderedToProtein ? (!this.renderedToProtein.expanded || this.renderedToProtein.inCollapsedGroup()) : false)) { - this.hide(); - return false; - } - - // either end manually hidden? then hide - if (this.renderedFromProtein.participant.hidden === true || - (this.renderedToProtein && this.renderedToProtein.participant.hidden === true)) { - this.hide(); - return false; - } - - // no crosslinks passed filter? then hide - if (this.crosslink.filteredMatches_pp.length > 0) { - this.show(); - return true; - } else { - this.hide(); - return false; - } - } - - show() { - if (!this.shown) { - this.shown = true; - if (typeof this.line === "undefined") { - this.initSVG(); - } - if (!this.renderedToProtein) { - let path; - if (this.renderedFromProtein.expanded) { - path = this.renderedFromProtein.getCrossLinkPath(this); - } else { - path = this.crosslink.isMonoLink() ? "M 0,0 L 0,0 L 0,0 L 0,0" : this.renderedFromProtein.getAggregateSelfLinkPath(); - } - this.highlightLine.setAttribute("d", path); - this.line.setAttribute("d", path); - } else { - if (!this.crosslink.isSelfLink()) { - this.line.setAttribute("stroke-width", (this.controller.z * _crosslink_viewer_BB__WEBPACK_IMPORTED_MODULE_1__.CrosslinkViewer.linkWidth).toString()); - this.highlightLine.setAttribute("stroke-width", (this.controller.z * 10).toString()); - this.setLineCoordinates(this.renderedFromProtein); - this.setLineCoordinates(this.renderedToProtein); - } - } - d3__WEBPACK_IMPORTED_MODULE_3___default().select(this.highlightLine).style("display", null); - d3__WEBPACK_IMPORTED_MODULE_3___default().select(this.line).style("display", null); - } - - if (this.crosslink.isSelfLink() && this.renderedToProtein) { - if (this.homomultimer !== this.crosslink.confirmedHomomultimer) { - let path; - if (this.renderedFromProtein.expanded) { - path = this.renderedFromProtein.getCrossLinkPath(this); - } else { - path = this.renderedFromProtein.getAggregateSelfLinkPath(); - } - this.highlightLine.setAttribute("d", path); - this.line.setAttribute("d", path); - this.homomultimer = this.crosslink.confirmedHomomultimer; - } - } - - this.dashedLine(this.crosslink.ambiguous && this.crosslink.isMonoLink() === false); - - if (this.crosslink.isMonoLink()) { - this.line.setAttribute("fill", this.crosslink.ambiguous ? "none" : this.controller.model.get("linkColourAssignment").getColour(this.crosslink)); - } - - this.line.setAttribute("stroke", - this.controller.model.get("linkColourAssignment").getColour(this.crosslink)); - - this.setSelected(this.isSelected); - } - - hide() { - if (this.shown) { - this.shown = false; - d3__WEBPACK_IMPORTED_MODULE_3___default().select(this.highlightLine).style("display", "none"); - d3__WEBPACK_IMPORTED_MODULE_3___default().select(this.line).style("display", "none"); - this.removePeptides(); - } - } - - // there's an efficiency saving possible by passing in the renderedInteractor that's moved, - // then only need to change that end - setLineCoordinates() { - if (this.shown) { - //if not self link && not linker modified pep - if (!this.crosslink.isSelfLink() && this.crosslink.toProtein) { - let x, y; - const source = this.renderedFromProtein.getRenderedInteractor(); - const target = this.renderedToProtein.getRenderedInteractor(); - if (!source.ix || !source.iy) { - console.log("NOT"); - } - // from end - if (source.type === "group" || !source.expanded) { - x = source.ix; - y = source.iy; - } else { - const coord = this.getResidueCoordinates(this.crosslink.fromResidue, this.renderedFromProtein); - x = coord[0]; - y = coord[1]; - } - this.line.setAttribute("x1", x); - this.line.setAttribute("y1", y); - this.highlightLine.setAttribute("x1", x); - this.highlightLine.setAttribute("y1", y); - - // to end - if (target.type === "group" || !target.expanded) { - x = target.ix; - y = target.iy; - } else { - const coord = this.getResidueCoordinates(this.crosslink.toResidue, this.renderedToProtein); - x = coord[0]; - y = coord[1]; - } - this.line.setAttribute("x2", x); - this.line.setAttribute("y2", y); - this.highlightLine.setAttribute("x2", x); - this.highlightLine.setAttribute("y2", y); - - } - } - } - - //calculate the coordinates of a residue (relative to this.controller.container) - getResidueCoordinates(r, renderedInteractor) { - let x = renderedInteractor.getResXwithStickZoom(r) * this.controller.z; - let y = 0; - if (renderedInteractor.stickZoom >= 8) { //if sequence shown - const from = this.renderedFromProtein, - to = this.renderedToProtein; - const deltaX = from.ix - to.ix; - const deltaY = from.iy - to.iy; - const angleBetweenMidPoints = Math.atan2(deltaY, deltaX); - //todo: tidy up trig code so everything is always in radians? - let abmpDeg = angleBetweenMidPoints / (2 * Math.PI) * 360; - if (abmpDeg < 0) { - abmpDeg += 360; - } - - let out; //'out' is value we use to decide which side of letter the line is drawn - if (renderedInteractor === from) { - out = (abmpDeg - from.rotation); - if (out < 0) { - out += 360; - } - let fyOffset = 5; - if (out < 180) { - fyOffset = -5; - } - - y = fyOffset * this.controller.z; - } else { // renderedInteractor === to - out = (abmpDeg - to.rotation); - if (out < 0) { - out += 360; - } - let tyOffset = 5; - if (out > 180) { - tyOffset = -5; - } - y = tyOffset * this.controller.z; - } - } - - const rotated = (0,_trig__WEBPACK_IMPORTED_MODULE_5__.rotatePointAboutPoint)([x, y], [0, 0], renderedInteractor.rotation); - - x = rotated[0] + renderedInteractor.ix; - y = rotated[1] + renderedInteractor.iy; - return [x, y]; - } -} - - -/***/ }), - -/***/ "./crosslink-viewer/js/views/xinet/trig.js": -/*!*************************************************!*\ - !*** ./crosslink-viewer/js/views/xinet/trig.js ***! - \*************************************************/ -/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { - -"use strict"; -__webpack_require__.r(__webpack_exports__); -/* harmony export */ __webpack_require__.d(__webpack_exports__, { -/* harmony export */ rotatePointAboutPoint: () => (/* binding */ rotatePointAboutPoint), -/* harmony export */ trig: () => (/* binding */ trig) -/* harmony export */ }); -function trig(radius, angleDegrees) { //TODO: change theta arg to radians not degrees - //x = rx + radius * cos(theta) and y = ry + radius * sin(theta) - const radians = (angleDegrees / 360) * Math.PI * 2; - return { - x: (radius * Math.cos(radians)), - y: (radius * Math.sin(radians)) - }; -} - -function rotatePointAboutPoint(p, o, theta) { // todo: change format of p and o to be {x,y}? - theta = (theta / 360) * Math.PI * 2; //TODO: change theta arg to radians not degrees - const rx = Math.cos(theta) * (p[0] - o[0]) - Math.sin(theta) * (p[1] - o[1]) + o[0]; - const ry = Math.sin(theta) * (p[0] - o[0]) + Math.cos(theta) * (p[1] - o[1]) + o[1]; - return [rx, ry]; -} - -/***/ }), - -/***/ "./crosslink-viewer/vendor/cola.js": -/*!*****************************************!*\ - !*** ./crosslink-viewer/vendor/cola.js ***! - \*****************************************/ -/***/ ((module) => { - -(function(f){if(true){module.exports=f()}else { var g; }})(function(){var define,module,exports;return (function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c=undefined;if(!f&&c)return require(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u=undefined,i=0;i i) { - var d = D[i][j]; - if (d > 0 && d < this.minD) { - this.minD = d; - } - } - } - if (this.minD === Number.MAX_VALUE) - this.minD = 1; - i = this.k; - while (i--) { - this.g[i] = new Array(n); - this.H[i] = new Array(n); - j = n; - while (j--) { - this.H[i][j] = new Array(n); - } - this.Hd[i] = new Array(n); - this.a[i] = new Array(n); - this.b[i] = new Array(n); - this.c[i] = new Array(n); - this.d[i] = new Array(n); - this.e[i] = new Array(n); - this.ia[i] = new Array(n); - this.ib[i] = new Array(n); - this.xtmp[i] = new Array(n); - } - } - Descent.createSquareMatrix = function (n, f) { - var M = new Array(n); - for (var i = 0; i < n; ++i) { - M[i] = new Array(n); - for (var j = 0; j < n; ++j) { - M[i][j] = f(i, j); - } - } - return M; - }; - Descent.prototype.offsetDir = function () { - var _this = this; - var u = new Array(this.k); - var l = 0; - for (var i = 0; i < this.k; ++i) { - var x = u[i] = this.random.getNextBetween(0.01, 1) - 0.5; - l += x * x; - } - l = Math.sqrt(l); - return u.map(function (x) { return x *= _this.minD / l; }); - }; - Descent.prototype.computeDerivatives = function (x) { - var _this = this; - var n = this.n; - if (n < 1) - return; - var i; - var d = new Array(this.k); - var d2 = new Array(this.k); - var Huu = new Array(this.k); - var maxH = 0; - for (var u_1 = 0; u_1 < n; ++u_1) { - for (i = 0; i < this.k; ++i) - Huu[i] = this.g[i][u_1] = 0; - for (var v = 0; v < n; ++v) { - if (u_1 === v) - continue; - var maxDisplaces = n; - var distanceSquared = 0; - while (maxDisplaces--) { - distanceSquared = 0; - for (i = 0; i < this.k; ++i) { - var dx_1 = d[i] = x[i][u_1] - x[i][v]; - distanceSquared += d2[i] = dx_1 * dx_1; - } - if (distanceSquared > 1e-9) - break; - var rd = this.offsetDir(); - for (i = 0; i < this.k; ++i) - x[i][v] += rd[i]; - } - var distance = Math.sqrt(distanceSquared); - var idealDistance = this.D[u_1][v]; - var weight = this.G != null ? this.G[u_1][v] : 1; - if (weight > 1 && distance > idealDistance || !isFinite(idealDistance)) { - for (i = 0; i < this.k; ++i) - this.H[i][u_1][v] = 0; - continue; - } - if (weight > 1) { - weight = 1; - } - var idealDistSquared = idealDistance * idealDistance, gs = 2 * weight * (distance - idealDistance) / (idealDistSquared * distance), distanceCubed = distanceSquared * distance, hs = 2 * -weight / (idealDistSquared * distanceCubed); - if (!isFinite(gs)) - console.log(gs); - for (i = 0; i < this.k; ++i) { - this.g[i][u_1] += d[i] * gs; - Huu[i] -= this.H[i][u_1][v] = hs * (2 * distanceCubed + idealDistance * (d2[i] - distanceSquared)); - } - } - for (i = 0; i < this.k; ++i) - maxH = Math.max(maxH, this.H[i][u_1][u_1] = Huu[i]); - } - var r = this.snapGridSize / 2; - var g = this.snapGridSize; - var w = this.snapStrength; - var k = w / (r * r); - var numNodes = this.numGridSnapNodes; - for (var u = 0; u < numNodes; ++u) { - for (i = 0; i < this.k; ++i) { - var xiu = this.x[i][u]; - var m = xiu / g; - var f = m % 1; - var q = m - f; - var a = Math.abs(f); - var dx = (a <= 0.5) ? xiu - q * g : - (xiu > 0) ? xiu - (q + 1) * g : xiu - (q - 1) * g; - if (-r < dx && dx <= r) { - if (this.scaleSnapByMaxH) { - this.g[i][u] += maxH * k * dx; - this.H[i][u][u] += maxH * k; - } - else { - this.g[i][u] += k * dx; - this.H[i][u][u] += k; - } - } - } - } - if (!this.locks.isEmpty()) { - this.locks.apply(function (u, p) { - for (i = 0; i < _this.k; ++i) { - _this.H[i][u][u] += maxH; - _this.g[i][u] -= maxH * (p[i] - x[i][u]); - } - }); - } - }; - Descent.dotProd = function (a, b) { - var x = 0, i = a.length; - while (i--) - x += a[i] * b[i]; - return x; - }; - Descent.rightMultiply = function (m, v, r) { - var i = m.length; - while (i--) - r[i] = Descent.dotProd(m[i], v); - }; - Descent.prototype.computeStepSize = function (d) { - var numerator = 0, denominator = 0; - for (var i = 0; i < this.k; ++i) { - numerator += Descent.dotProd(this.g[i], d[i]); - Descent.rightMultiply(this.H[i], d[i], this.Hd[i]); - denominator += Descent.dotProd(d[i], this.Hd[i]); - } - if (denominator === 0 || !isFinite(denominator)) - return 0; - return 1 * numerator / denominator; - }; - Descent.prototype.reduceStress = function () { - this.computeDerivatives(this.x); - var alpha = this.computeStepSize(this.g); - for (var i = 0; i < this.k; ++i) { - this.takeDescentStep(this.x[i], this.g[i], alpha); - } - return this.computeStress(); - }; - Descent.copy = function (a, b) { - var m = a.length, n = b[0].length; - for (var i = 0; i < m; ++i) { - for (var j = 0; j < n; ++j) { - b[i][j] = a[i][j]; - } - } - }; - Descent.prototype.stepAndProject = function (x0, r, d, stepSize) { - Descent.copy(x0, r); - this.takeDescentStep(r[0], d[0], stepSize); - if (this.project) - this.project[0](x0[0], x0[1], r[0]); - this.takeDescentStep(r[1], d[1], stepSize); - if (this.project) - this.project[1](r[0], x0[1], r[1]); - for (var i = 2; i < this.k; i++) - this.takeDescentStep(r[i], d[i], stepSize); - }; - Descent.mApply = function (m, n, f) { - var i = m; - while (i-- > 0) { - var j = n; - while (j-- > 0) - f(i, j); - } - }; - Descent.prototype.matrixApply = function (f) { - Descent.mApply(this.k, this.n, f); - }; - Descent.prototype.computeNextPosition = function (x0, r) { - var _this = this; - this.computeDerivatives(x0); - var alpha = this.computeStepSize(this.g); - this.stepAndProject(x0, r, this.g, alpha); - if (this.project) { - this.matrixApply(function (i, j) { return _this.e[i][j] = x0[i][j] - r[i][j]; }); - var beta = this.computeStepSize(this.e); - beta = Math.max(0.2, Math.min(beta, 1)); - this.stepAndProject(x0, r, this.e, beta); - } - }; - Descent.prototype.run = function (iterations) { - var stress = Number.MAX_VALUE, converged = false; - while (!converged && iterations-- > 0) { - var s = this.rungeKutta(); - converged = Math.abs(stress / s - 1) < this.threshold; - stress = s; - } - return stress; - }; - Descent.prototype.rungeKutta = function () { - var _this = this; - this.computeNextPosition(this.x, this.a); - Descent.mid(this.x, this.a, this.ia); - this.computeNextPosition(this.ia, this.b); - Descent.mid(this.x, this.b, this.ib); - this.computeNextPosition(this.ib, this.c); - this.computeNextPosition(this.c, this.d); - var disp = 0; - this.matrixApply(function (i, j) { - var x = (_this.a[i][j] + 2.0 * _this.b[i][j] + 2.0 * _this.c[i][j] + _this.d[i][j]) / 6.0, d = _this.x[i][j] - x; - disp += d * d; - _this.x[i][j] = x; - }); - return disp; - }; - Descent.mid = function (a, b, m) { - Descent.mApply(a.length, a[0].length, function (i, j) { - return m[i][j] = a[i][j] + (b[i][j] - a[i][j]) / 2.0; - }); - }; - Descent.prototype.takeDescentStep = function (x, d, stepSize) { - for (var i = 0; i < this.n; ++i) { - x[i] = x[i] - stepSize * d[i]; - } - }; - Descent.prototype.computeStress = function () { - var stress = 0; - for (var u = 0, nMinus1 = this.n - 1; u < nMinus1; ++u) { - for (var v = u + 1, n = this.n; v < n; ++v) { - var l = 0; - for (var i = 0; i < this.k; ++i) { - var dx = this.x[i][u] - this.x[i][v]; - l += dx * dx; - } - l = Math.sqrt(l); - var d = this.D[u][v]; - if (!isFinite(d)) - continue; - var rl = d - l; - var d2 = d * d; - stress += rl * rl / d2; - } - } - return stress; - }; - Descent.zeroDistance = 1e-10; - return Descent; -}()); -exports.Descent = Descent; -var PseudoRandom = (function () { - function PseudoRandom(seed) { - if (seed === void 0) { seed = 1; } - this.seed = seed; - this.a = 214013; - this.c = 2531011; - this.m = 2147483648; - this.range = 32767; - } - PseudoRandom.prototype.getNext = function () { - this.seed = (this.seed * this.a + this.c) % this.m; - return (this.seed >> 16) / this.range; - }; - PseudoRandom.prototype.getNextBetween = function (min, max) { - return min + this.getNext() * (max - min); - }; - return PseudoRandom; -}()); -exports.PseudoRandom = PseudoRandom; - -},{}],8:[function(require,module,exports){ -"use strict"; -var __extends = (this && this.__extends) || (function () { - var extendStatics = function (d, b) { - extendStatics = Object.setPrototypeOf || - ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || - function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; - return extendStatics(d, b); - }; - return function (d, b) { - extendStatics(d, b); - function __() { this.constructor = d; } - d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); - }; -})(); -Object.defineProperty(exports, "__esModule", { value: true }); -var rectangle_1 = require("./rectangle"); -var Point = (function () { - function Point() { - } - return Point; -}()); -exports.Point = Point; -var LineSegment = (function () { - function LineSegment(x1, y1, x2, y2) { - this.x1 = x1; - this.y1 = y1; - this.x2 = x2; - this.y2 = y2; - } - return LineSegment; -}()); -exports.LineSegment = LineSegment; -var PolyPoint = (function (_super) { - __extends(PolyPoint, _super); - function PolyPoint() { - return _super !== null && _super.apply(this, arguments) || this; - } - return PolyPoint; -}(Point)); -exports.PolyPoint = PolyPoint; -function isLeft(P0, P1, P2) { - return (P1.x - P0.x) * (P2.y - P0.y) - (P2.x - P0.x) * (P1.y - P0.y); -} -exports.isLeft = isLeft; -function above(p, vi, vj) { - return isLeft(p, vi, vj) > 0; -} -function below(p, vi, vj) { - return isLeft(p, vi, vj) < 0; -} -function ConvexHull(S) { - var P = S.slice(0).sort(function (a, b) { return a.x !== b.x ? b.x - a.x : b.y - a.y; }); - var n = S.length, i; - var minmin = 0; - var xmin = P[0].x; - for (i = 1; i < n; ++i) { - if (P[i].x !== xmin) - break; - } - var minmax = i - 1; - var H = []; - H.push(P[minmin]); - if (minmax === n - 1) { - if (P[minmax].y !== P[minmin].y) - H.push(P[minmax]); - } - else { - var maxmin, maxmax = n - 1; - var xmax = P[n - 1].x; - for (i = n - 2; i >= 0; i--) - if (P[i].x !== xmax) - break; - maxmin = i + 1; - i = minmax; - while (++i <= maxmin) { - if (isLeft(P[minmin], P[maxmin], P[i]) >= 0 && i < maxmin) - continue; - while (H.length > 1) { - if (isLeft(H[H.length - 2], H[H.length - 1], P[i]) > 0) - break; - else - H.length -= 1; - } - if (i != minmin) - H.push(P[i]); - } - if (maxmax != maxmin) - H.push(P[maxmax]); - var bot = H.length; - i = maxmin; - while (--i >= minmax) { - if (isLeft(P[maxmax], P[minmax], P[i]) >= 0 && i > minmax) - continue; - while (H.length > bot) { - if (isLeft(H[H.length - 2], H[H.length - 1], P[i]) > 0) - break; - else - H.length -= 1; - } - if (i != minmin) - H.push(P[i]); - } - } - return H; -} -exports.ConvexHull = ConvexHull; -function clockwiseRadialSweep(p, P, f) { - P.slice(0).sort(function (a, b) { return Math.atan2(a.y - p.y, a.x - p.x) - Math.atan2(b.y - p.y, b.x - p.x); }).forEach(f); -} -exports.clockwiseRadialSweep = clockwiseRadialSweep; -function nextPolyPoint(p, ps) { - if (p.polyIndex === ps.length - 1) - return ps[0]; - return ps[p.polyIndex + 1]; -} -function prevPolyPoint(p, ps) { - if (p.polyIndex === 0) - return ps[ps.length - 1]; - return ps[p.polyIndex - 1]; -} -function tangent_PointPolyC(P, V) { - var Vclosed = V.slice(0); - Vclosed.push(V[0]); - return { rtan: Rtangent_PointPolyC(P, Vclosed), ltan: Ltangent_PointPolyC(P, Vclosed) }; -} -function Rtangent_PointPolyC(P, V) { - var n = V.length - 1; - var a, b, c; - var upA, dnC; - if (below(P, V[1], V[0]) && !above(P, V[n - 1], V[0])) - return 0; - for (a = 0, b = n;;) { - if (b - a === 1) - if (above(P, V[a], V[b])) - return a; - else - return b; - c = Math.floor((a + b) / 2); - dnC = below(P, V[c + 1], V[c]); - if (dnC && !above(P, V[c - 1], V[c])) - return c; - upA = above(P, V[a + 1], V[a]); - if (upA) { - if (dnC) - b = c; - else { - if (above(P, V[a], V[c])) - b = c; - else - a = c; - } - } - else { - if (!dnC) - a = c; - else { - if (below(P, V[a], V[c])) - b = c; - else - a = c; - } - } - } -} -function Ltangent_PointPolyC(P, V) { - var n = V.length - 1; - var a, b, c; - var dnA, dnC; - if (above(P, V[n - 1], V[0]) && !below(P, V[1], V[0])) - return 0; - for (a = 0, b = n;;) { - if (b - a === 1) - if (below(P, V[a], V[b])) - return a; - else - return b; - c = Math.floor((a + b) / 2); - dnC = below(P, V[c + 1], V[c]); - if (above(P, V[c - 1], V[c]) && !dnC) - return c; - dnA = below(P, V[a + 1], V[a]); - if (dnA) { - if (!dnC) - b = c; - else { - if (below(P, V[a], V[c])) - b = c; - else - a = c; - } - } - else { - if (dnC) - a = c; - else { - if (above(P, V[a], V[c])) - b = c; - else - a = c; - } - } - } -} -function tangent_PolyPolyC(V, W, t1, t2, cmp1, cmp2) { - var ix1, ix2; - ix1 = t1(W[0], V); - ix2 = t2(V[ix1], W); - var done = false; - while (!done) { - done = true; - while (true) { - if (ix1 === V.length - 1) - ix1 = 0; - if (cmp1(W[ix2], V[ix1], V[ix1 + 1])) - break; - ++ix1; - } - while (true) { - if (ix2 === 0) - ix2 = W.length - 1; - if (cmp2(V[ix1], W[ix2], W[ix2 - 1])) - break; - --ix2; - done = false; - } - } - return { t1: ix1, t2: ix2 }; -} -exports.tangent_PolyPolyC = tangent_PolyPolyC; -function LRtangent_PolyPolyC(V, W) { - var rl = RLtangent_PolyPolyC(W, V); - return { t1: rl.t2, t2: rl.t1 }; -} -exports.LRtangent_PolyPolyC = LRtangent_PolyPolyC; -function RLtangent_PolyPolyC(V, W) { - return tangent_PolyPolyC(V, W, Rtangent_PointPolyC, Ltangent_PointPolyC, above, below); -} -exports.RLtangent_PolyPolyC = RLtangent_PolyPolyC; -function LLtangent_PolyPolyC(V, W) { - return tangent_PolyPolyC(V, W, Ltangent_PointPolyC, Ltangent_PointPolyC, below, below); -} -exports.LLtangent_PolyPolyC = LLtangent_PolyPolyC; -function RRtangent_PolyPolyC(V, W) { - return tangent_PolyPolyC(V, W, Rtangent_PointPolyC, Rtangent_PointPolyC, above, above); -} -exports.RRtangent_PolyPolyC = RRtangent_PolyPolyC; -var BiTangent = (function () { - function BiTangent(t1, t2) { - this.t1 = t1; - this.t2 = t2; - } - return BiTangent; -}()); -exports.BiTangent = BiTangent; -var BiTangents = (function () { - function BiTangents() { - } - return BiTangents; -}()); -exports.BiTangents = BiTangents; -var TVGPoint = (function (_super) { - __extends(TVGPoint, _super); - function TVGPoint() { - return _super !== null && _super.apply(this, arguments) || this; - } - return TVGPoint; -}(Point)); -exports.TVGPoint = TVGPoint; -var VisibilityVertex = (function () { - function VisibilityVertex(id, polyid, polyvertid, p) { - this.id = id; - this.polyid = polyid; - this.polyvertid = polyvertid; - this.p = p; - p.vv = this; - } - return VisibilityVertex; -}()); -exports.VisibilityVertex = VisibilityVertex; -var VisibilityEdge = (function () { - function VisibilityEdge(source, target) { - this.source = source; - this.target = target; - } - VisibilityEdge.prototype.length = function () { - var dx = this.source.p.x - this.target.p.x; - var dy = this.source.p.y - this.target.p.y; - return Math.sqrt(dx * dx + dy * dy); - }; - return VisibilityEdge; -}()); -exports.VisibilityEdge = VisibilityEdge; -var TangentVisibilityGraph = (function () { - function TangentVisibilityGraph(P, g0) { - this.P = P; - this.V = []; - this.E = []; - if (!g0) { - var n = P.length; - for (var i = 0; i < n; i++) { - var p = P[i]; - for (var j = 0; j < p.length; ++j) { - var pj = p[j], vv = new VisibilityVertex(this.V.length, i, j, pj); - this.V.push(vv); - if (j > 0) - this.E.push(new VisibilityEdge(p[j - 1].vv, vv)); - } - if (p.length > 1) - this.E.push(new VisibilityEdge(p[0].vv, p[p.length - 1].vv)); - } - for (var i = 0; i < n - 1; i++) { - var Pi = P[i]; - for (var j = i + 1; j < n; j++) { - var Pj = P[j], t = tangents(Pi, Pj); - for (var q in t) { - var c = t[q], source = Pi[c.t1], target = Pj[c.t2]; - this.addEdgeIfVisible(source, target, i, j); - } - } - } - } - else { - this.V = g0.V.slice(0); - this.E = g0.E.slice(0); - } - } - TangentVisibilityGraph.prototype.addEdgeIfVisible = function (u, v, i1, i2) { - if (!this.intersectsPolys(new LineSegment(u.x, u.y, v.x, v.y), i1, i2)) { - this.E.push(new VisibilityEdge(u.vv, v.vv)); - } - }; - TangentVisibilityGraph.prototype.addPoint = function (p, i1) { - var n = this.P.length; - this.V.push(new VisibilityVertex(this.V.length, n, 0, p)); - for (var i = 0; i < n; ++i) { - if (i === i1) - continue; - var poly = this.P[i], t = tangent_PointPolyC(p, poly); - this.addEdgeIfVisible(p, poly[t.ltan], i1, i); - this.addEdgeIfVisible(p, poly[t.rtan], i1, i); - } - return p.vv; - }; - TangentVisibilityGraph.prototype.intersectsPolys = function (l, i1, i2) { - for (var i = 0, n = this.P.length; i < n; ++i) { - if (i != i1 && i != i2 && intersects(l, this.P[i]).length > 0) { - return true; - } - } - return false; - }; - return TangentVisibilityGraph; -}()); -exports.TangentVisibilityGraph = TangentVisibilityGraph; -function intersects(l, P) { - var ints = []; - for (var i = 1, n = P.length; i < n; ++i) { - var int = rectangle_1.Rectangle.lineIntersection(l.x1, l.y1, l.x2, l.y2, P[i - 1].x, P[i - 1].y, P[i].x, P[i].y); - if (int) - ints.push(int); - } - return ints; -} -function tangents(V, W) { - var m = V.length - 1, n = W.length - 1; - var bt = new BiTangents(); - for (var i = 0; i <= m; ++i) { - for (var j = 0; j <= n; ++j) { - var v1 = V[i == 0 ? m : i - 1]; - var v2 = V[i]; - var v3 = V[i == m ? 0 : i + 1]; - var w1 = W[j == 0 ? n : j - 1]; - var w2 = W[j]; - var w3 = W[j == n ? 0 : j + 1]; - var v1v2w2 = isLeft(v1, v2, w2); - var v2w1w2 = isLeft(v2, w1, w2); - var v2w2w3 = isLeft(v2, w2, w3); - var w1w2v2 = isLeft(w1, w2, v2); - var w2v1v2 = isLeft(w2, v1, v2); - var w2v2v3 = isLeft(w2, v2, v3); - if (v1v2w2 >= 0 && v2w1w2 >= 0 && v2w2w3 < 0 - && w1w2v2 >= 0 && w2v1v2 >= 0 && w2v2v3 < 0) { - bt.ll = new BiTangent(i, j); - } - else if (v1v2w2 <= 0 && v2w1w2 <= 0 && v2w2w3 > 0 - && w1w2v2 <= 0 && w2v1v2 <= 0 && w2v2v3 > 0) { - bt.rr = new BiTangent(i, j); - } - else if (v1v2w2 <= 0 && v2w1w2 > 0 && v2w2w3 <= 0 - && w1w2v2 >= 0 && w2v1v2 < 0 && w2v2v3 >= 0) { - bt.rl = new BiTangent(i, j); - } - else if (v1v2w2 >= 0 && v2w1w2 < 0 && v2w2w3 >= 0 - && w1w2v2 <= 0 && w2v1v2 > 0 && w2v2v3 <= 0) { - bt.lr = new BiTangent(i, j); - } - } - } - return bt; -} -exports.tangents = tangents; -function isPointInsidePoly(p, poly) { - for (var i = 1, n = poly.length; i < n; ++i) - if (below(poly[i - 1], poly[i], p)) - return false; - return true; -} -function isAnyPInQ(p, q) { - return !p.every(function (v) { return !isPointInsidePoly(v, q); }); -} -function polysOverlap(p, q) { - if (isAnyPInQ(p, q)) - return true; - if (isAnyPInQ(q, p)) - return true; - for (var i = 1, n = p.length; i < n; ++i) { - var v = p[i], u = p[i - 1]; - if (intersects(new LineSegment(u.x, u.y, v.x, v.y), q).length > 0) - return true; - } - return false; -} -exports.polysOverlap = polysOverlap; - -},{"./rectangle":17}],9:[function(require,module,exports){ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -var rectangle_1 = require("./rectangle"); -var vpsc_1 = require("./vpsc"); -var shortestpaths_1 = require("./shortestpaths"); -var NodeWrapper = (function () { - function NodeWrapper(id, rect, children) { - this.id = id; - this.rect = rect; - this.children = children; - this.leaf = typeof children === 'undefined' || children.length === 0; - } - return NodeWrapper; -}()); -exports.NodeWrapper = NodeWrapper; -var Vert = (function () { - function Vert(id, x, y, node, line) { - if (node === void 0) { node = null; } - if (line === void 0) { line = null; } - this.id = id; - this.x = x; - this.y = y; - this.node = node; - this.line = line; - } - return Vert; -}()); -exports.Vert = Vert; -var LongestCommonSubsequence = (function () { - function LongestCommonSubsequence(s, t) { - this.s = s; - this.t = t; - var mf = LongestCommonSubsequence.findMatch(s, t); - var tr = t.slice(0).reverse(); - var mr = LongestCommonSubsequence.findMatch(s, tr); - if (mf.length >= mr.length) { - this.length = mf.length; - this.si = mf.si; - this.ti = mf.ti; - this.reversed = false; - } - else { - this.length = mr.length; - this.si = mr.si; - this.ti = t.length - mr.ti - mr.length; - this.reversed = true; - } - } - LongestCommonSubsequence.findMatch = function (s, t) { - var m = s.length; - var n = t.length; - var match = { length: 0, si: -1, ti: -1 }; - var l = new Array(m); - for (var i = 0; i < m; i++) { - l[i] = new Array(n); - for (var j = 0; j < n; j++) - if (s[i] === t[j]) { - var v = l[i][j] = (i === 0 || j === 0) ? 1 : l[i - 1][j - 1] + 1; - if (v > match.length) { - match.length = v; - match.si = i - v + 1; - match.ti = j - v + 1; - } - ; - } - else - l[i][j] = 0; - } - return match; - }; - LongestCommonSubsequence.prototype.getSequence = function () { - return this.length >= 0 ? this.s.slice(this.si, this.si + this.length) : []; - }; - return LongestCommonSubsequence; -}()); -exports.LongestCommonSubsequence = LongestCommonSubsequence; -var GridRouter = (function () { - function GridRouter(originalnodes, accessor, groupPadding) { - var _this = this; - if (groupPadding === void 0) { groupPadding = 12; } - this.originalnodes = originalnodes; - this.groupPadding = groupPadding; - this.leaves = null; - this.nodes = originalnodes.map(function (v, i) { return new NodeWrapper(i, accessor.getBounds(v), accessor.getChildren(v)); }); - this.leaves = this.nodes.filter(function (v) { return v.leaf; }); - this.groups = this.nodes.filter(function (g) { return !g.leaf; }); - this.cols = this.getGridLines('x'); - this.rows = this.getGridLines('y'); - this.groups.forEach(function (v) { - return v.children.forEach(function (c) { return _this.nodes[c].parent = v; }); - }); - this.root = { children: [] }; - this.nodes.forEach(function (v) { - if (typeof v.parent === 'undefined') { - v.parent = _this.root; - _this.root.children.push(v.id); - } - v.ports = []; - }); - this.backToFront = this.nodes.slice(0); - this.backToFront.sort(function (x, y) { return _this.getDepth(x) - _this.getDepth(y); }); - var frontToBackGroups = this.backToFront.slice(0).reverse().filter(function (g) { return !g.leaf; }); - frontToBackGroups.forEach(function (v) { - var r = rectangle_1.Rectangle.empty(); - v.children.forEach(function (c) { return r = r.union(_this.nodes[c].rect); }); - v.rect = r.inflate(_this.groupPadding); - }); - var colMids = this.midPoints(this.cols.map(function (r) { return r.pos; })); - var rowMids = this.midPoints(this.rows.map(function (r) { return r.pos; })); - var rowx = colMids[0], rowX = colMids[colMids.length - 1]; - var coly = rowMids[0], colY = rowMids[rowMids.length - 1]; - var hlines = this.rows.map(function (r) { return ({ x1: rowx, x2: rowX, y1: r.pos, y2: r.pos }); }) - .concat(rowMids.map(function (m) { return ({ x1: rowx, x2: rowX, y1: m, y2: m }); })); - var vlines = this.cols.map(function (c) { return ({ x1: c.pos, x2: c.pos, y1: coly, y2: colY }); }) - .concat(colMids.map(function (m) { return ({ x1: m, x2: m, y1: coly, y2: colY }); })); - var lines = hlines.concat(vlines); - lines.forEach(function (l) { return l.verts = []; }); - this.verts = []; - this.edges = []; - hlines.forEach(function (h) { - return vlines.forEach(function (v) { - var p = new Vert(_this.verts.length, v.x1, h.y1); - h.verts.push(p); - v.verts.push(p); - _this.verts.push(p); - var i = _this.backToFront.length; - while (i-- > 0) { - var node = _this.backToFront[i], r = node.rect; - var dx = Math.abs(p.x - r.cx()), dy = Math.abs(p.y - r.cy()); - if (dx < r.width() / 2 && dy < r.height() / 2) { - p.node = node; - break; - } - } - }); - }); - lines.forEach(function (l, li) { - _this.nodes.forEach(function (v, i) { - v.rect.lineIntersections(l.x1, l.y1, l.x2, l.y2).forEach(function (intersect, j) { - var p = new Vert(_this.verts.length, intersect.x, intersect.y, v, l); - _this.verts.push(p); - l.verts.push(p); - v.ports.push(p); - }); - }); - var isHoriz = Math.abs(l.y1 - l.y2) < 0.1; - var delta = function (a, b) { return isHoriz ? b.x - a.x : b.y - a.y; }; - l.verts.sort(delta); - for (var i = 1; i < l.verts.length; i++) { - var u = l.verts[i - 1], v = l.verts[i]; - if (u.node && u.node === v.node && u.node.leaf) - continue; - _this.edges.push({ source: u.id, target: v.id, length: Math.abs(delta(u, v)) }); - } - }); - } - GridRouter.prototype.avg = function (a) { return a.reduce(function (x, y) { return x + y; }) / a.length; }; - GridRouter.prototype.getGridLines = function (axis) { - var columns = []; - var ls = this.leaves.slice(0, this.leaves.length); - while (ls.length > 0) { - var overlapping = ls.filter(function (v) { return v.rect['overlap' + axis.toUpperCase()](ls[0].rect); }); - var col = { - nodes: overlapping, - pos: this.avg(overlapping.map(function (v) { return v.rect['c' + axis](); })) - }; - columns.push(col); - col.nodes.forEach(function (v) { return ls.splice(ls.indexOf(v), 1); }); - } - columns.sort(function (a, b) { return a.pos - b.pos; }); - return columns; - }; - GridRouter.prototype.getDepth = function (v) { - var depth = 0; - while (v.parent !== this.root) { - depth++; - v = v.parent; - } - return depth; - }; - GridRouter.prototype.midPoints = function (a) { - var gap = a[1] - a[0]; - var mids = [a[0] - gap / 2]; - for (var i = 1; i < a.length; i++) { - mids.push((a[i] + a[i - 1]) / 2); - } - mids.push(a[a.length - 1] + gap / 2); - return mids; - }; - GridRouter.prototype.findLineage = function (v) { - var lineage = [v]; - do { - v = v.parent; - lineage.push(v); - } while (v !== this.root); - return lineage.reverse(); - }; - GridRouter.prototype.findAncestorPathBetween = function (a, b) { - var aa = this.findLineage(a), ba = this.findLineage(b), i = 0; - while (aa[i] === ba[i]) - i++; - return { commonAncestor: aa[i - 1], lineages: aa.slice(i).concat(ba.slice(i)) }; - }; - GridRouter.prototype.siblingObstacles = function (a, b) { - var _this = this; - var path = this.findAncestorPathBetween(a, b); - var lineageLookup = {}; - path.lineages.forEach(function (v) { return lineageLookup[v.id] = {}; }); - var obstacles = path.commonAncestor.children.filter(function (v) { return !(v in lineageLookup); }); - path.lineages - .filter(function (v) { return v.parent !== path.commonAncestor; }) - .forEach(function (v) { return obstacles = obstacles.concat(v.parent.children.filter(function (c) { return c !== v.id; })); }); - return obstacles.map(function (v) { return _this.nodes[v]; }); - }; - GridRouter.getSegmentSets = function (routes, x, y) { - var vsegments = []; - for (var ei = 0; ei < routes.length; ei++) { - var route = routes[ei]; - for (var si = 0; si < route.length; si++) { - var s = route[si]; - s.edgeid = ei; - s.i = si; - var sdx = s[1][x] - s[0][x]; - if (Math.abs(sdx) < 0.1) { - vsegments.push(s); - } - } - } - vsegments.sort(function (a, b) { return a[0][x] - b[0][x]; }); - var vsegmentsets = []; - var segmentset = null; - for (var i = 0; i < vsegments.length; i++) { - var s = vsegments[i]; - if (!segmentset || Math.abs(s[0][x] - segmentset.pos) > 0.1) { - segmentset = { pos: s[0][x], segments: [] }; - vsegmentsets.push(segmentset); - } - segmentset.segments.push(s); - } - return vsegmentsets; - }; - GridRouter.nudgeSegs = function (x, y, routes, segments, leftOf, gap) { - var n = segments.length; - if (n <= 1) - return; - var vs = segments.map(function (s) { return new vpsc_1.Variable(s[0][x]); }); - var cs = []; - for (var i = 0; i < n; i++) { - for (var j = 0; j < n; j++) { - if (i === j) - continue; - var s1 = segments[i], s2 = segments[j], e1 = s1.edgeid, e2 = s2.edgeid, lind = -1, rind = -1; - if (x == 'x') { - if (leftOf(e1, e2)) { - if (s1[0][y] < s1[1][y]) { - lind = j, rind = i; - } - else { - lind = i, rind = j; - } - } - } - else { - if (leftOf(e1, e2)) { - if (s1[0][y] < s1[1][y]) { - lind = i, rind = j; - } - else { - lind = j, rind = i; - } - } - } - if (lind >= 0) { - cs.push(new vpsc_1.Constraint(vs[lind], vs[rind], gap)); - } - } - } - var solver = new vpsc_1.Solver(vs, cs); - solver.solve(); - vs.forEach(function (v, i) { - var s = segments[i]; - var pos = v.position(); - s[0][x] = s[1][x] = pos; - var route = routes[s.edgeid]; - if (s.i > 0) - route[s.i - 1][1][x] = pos; - if (s.i < route.length - 1) - route[s.i + 1][0][x] = pos; - }); - }; - GridRouter.nudgeSegments = function (routes, x, y, leftOf, gap) { - var vsegmentsets = GridRouter.getSegmentSets(routes, x, y); - for (var i = 0; i < vsegmentsets.length; i++) { - var ss = vsegmentsets[i]; - var events = []; - for (var j = 0; j < ss.segments.length; j++) { - var s = ss.segments[j]; - events.push({ type: 0, s: s, pos: Math.min(s[0][y], s[1][y]) }); - events.push({ type: 1, s: s, pos: Math.max(s[0][y], s[1][y]) }); - } - events.sort(function (a, b) { return a.pos - b.pos + a.type - b.type; }); - var open = []; - var openCount = 0; - events.forEach(function (e) { - if (e.type === 0) { - open.push(e.s); - openCount++; - } - else { - openCount--; - } - if (openCount == 0) { - GridRouter.nudgeSegs(x, y, routes, open, leftOf, gap); - open = []; - } - }); - } - }; - GridRouter.prototype.routeEdges = function (edges, nudgeGap, source, target) { - var _this = this; - var routePaths = edges.map(function (e) { return _this.route(source(e), target(e)); }); - var order = GridRouter.orderEdges(routePaths); - var routes = routePaths.map(function (e) { return GridRouter.makeSegments(e); }); - GridRouter.nudgeSegments(routes, 'x', 'y', order, nudgeGap); - GridRouter.nudgeSegments(routes, 'y', 'x', order, nudgeGap); - GridRouter.unreverseEdges(routes, routePaths); - return routes; - }; - GridRouter.unreverseEdges = function (routes, routePaths) { - routes.forEach(function (segments, i) { - var path = routePaths[i]; - if (path.reversed) { - segments.reverse(); - segments.forEach(function (segment) { - segment.reverse(); - }); - } - }); - }; - GridRouter.angleBetween2Lines = function (line1, line2) { - var angle1 = Math.atan2(line1[0].y - line1[1].y, line1[0].x - line1[1].x); - var angle2 = Math.atan2(line2[0].y - line2[1].y, line2[0].x - line2[1].x); - var diff = angle1 - angle2; - if (diff > Math.PI || diff < -Math.PI) { - diff = angle2 - angle1; - } - return diff; - }; - GridRouter.isLeft = function (a, b, c) { - return ((b.x - a.x) * (c.y - a.y) - (b.y - a.y) * (c.x - a.x)) <= 0; - }; - GridRouter.getOrder = function (pairs) { - var outgoing = {}; - for (var i = 0; i < pairs.length; i++) { - var p = pairs[i]; - if (typeof outgoing[p.l] === 'undefined') - outgoing[p.l] = {}; - outgoing[p.l][p.r] = true; - } - return function (l, r) { return typeof outgoing[l] !== 'undefined' && outgoing[l][r]; }; - }; - GridRouter.orderEdges = function (edges) { - var edgeOrder = []; - for (var i = 0; i < edges.length - 1; i++) { - for (var j = i + 1; j < edges.length; j++) { - var e = edges[i], f = edges[j], lcs = new LongestCommonSubsequence(e, f); - var u, vi, vj; - if (lcs.length === 0) - continue; - if (lcs.reversed) { - f.reverse(); - f.reversed = true; - lcs = new LongestCommonSubsequence(e, f); - } - if ((lcs.si <= 0 || lcs.ti <= 0) && - (lcs.si + lcs.length >= e.length || lcs.ti + lcs.length >= f.length)) { - edgeOrder.push({ l: i, r: j }); - continue; - } - if (lcs.si + lcs.length >= e.length || lcs.ti + lcs.length >= f.length) { - u = e[lcs.si + 1]; - vj = e[lcs.si - 1]; - vi = f[lcs.ti - 1]; - } - else { - u = e[lcs.si + lcs.length - 2]; - vi = e[lcs.si + lcs.length]; - vj = f[lcs.ti + lcs.length]; - } - if (GridRouter.isLeft(u, vi, vj)) { - edgeOrder.push({ l: j, r: i }); - } - else { - edgeOrder.push({ l: i, r: j }); - } - } - } - return GridRouter.getOrder(edgeOrder); - }; - GridRouter.makeSegments = function (path) { - function copyPoint(p) { - return { x: p.x, y: p.y }; - } - var isStraight = function (a, b, c) { return Math.abs((b.x - a.x) * (c.y - a.y) - (b.y - a.y) * (c.x - a.x)) < 0.001; }; - var segments = []; - var a = copyPoint(path[0]); - for (var i = 1; i < path.length; i++) { - var b = copyPoint(path[i]), c = i < path.length - 1 ? path[i + 1] : null; - if (!c || !isStraight(a, b, c)) { - segments.push([a, b]); - a = b; - } - } - return segments; - }; - GridRouter.prototype.route = function (s, t) { - var _this = this; - var source = this.nodes[s], target = this.nodes[t]; - this.obstacles = this.siblingObstacles(source, target); - var obstacleLookup = {}; - this.obstacles.forEach(function (o) { return obstacleLookup[o.id] = o; }); - this.passableEdges = this.edges.filter(function (e) { - var u = _this.verts[e.source], v = _this.verts[e.target]; - return !(u.node && u.node.id in obstacleLookup - || v.node && v.node.id in obstacleLookup); - }); - for (var i = 1; i < source.ports.length; i++) { - var u = source.ports[0].id; - var v = source.ports[i].id; - this.passableEdges.push({ - source: u, - target: v, - length: 0 - }); - } - for (var i = 1; i < target.ports.length; i++) { - var u = target.ports[0].id; - var v = target.ports[i].id; - this.passableEdges.push({ - source: u, - target: v, - length: 0 - }); - } - var getSource = function (e) { return e.source; }, getTarget = function (e) { return e.target; }, getLength = function (e) { return e.length; }; - var shortestPathCalculator = new shortestpaths_1.Calculator(this.verts.length, this.passableEdges, getSource, getTarget, getLength); - var bendPenalty = function (u, v, w) { - var a = _this.verts[u], b = _this.verts[v], c = _this.verts[w]; - var dx = Math.abs(c.x - a.x), dy = Math.abs(c.y - a.y); - if (a.node === source && a.node === b.node || b.node === target && b.node === c.node) - return 0; - return dx > 1 && dy > 1 ? 1000 : 0; - }; - var shortestPath = shortestPathCalculator.PathFromNodeToNodeWithPrevCost(source.ports[0].id, target.ports[0].id, bendPenalty); - var pathPoints = shortestPath.reverse().map(function (vi) { return _this.verts[vi]; }); - pathPoints.push(this.nodes[target.id].ports[0]); - return pathPoints.filter(function (v, i) { - return !(i < pathPoints.length - 1 && pathPoints[i + 1].node === source && v.node === source - || i > 0 && v.node === target && pathPoints[i - 1].node === target); - }); - }; - GridRouter.getRoutePath = function (route, cornerradius, arrowwidth, arrowheight) { - var result = { - routepath: 'M ' + route[0][0].x + ' ' + route[0][0].y + ' ', - arrowpath: '' - }; - if (route.length > 1) { - for (var i = 0; i < route.length; i++) { - var li = route[i]; - var x = li[1].x, y = li[1].y; - var dx = x - li[0].x; - var dy = y - li[0].y; - if (i < route.length - 1) { - if (Math.abs(dx) > 0) { - x -= dx / Math.abs(dx) * cornerradius; - } - else { - y -= dy / Math.abs(dy) * cornerradius; - } - result.routepath += 'L ' + x + ' ' + y + ' '; - var l = route[i + 1]; - var x0 = l[0].x, y0 = l[0].y; - var x1 = l[1].x; - var y1 = l[1].y; - dx = x1 - x0; - dy = y1 - y0; - var angle = GridRouter.angleBetween2Lines(li, l) < 0 ? 1 : 0; - var x2, y2; - if (Math.abs(dx) > 0) { - x2 = x0 + dx / Math.abs(dx) * cornerradius; - y2 = y0; - } - else { - x2 = x0; - y2 = y0 + dy / Math.abs(dy) * cornerradius; - } - var cx = Math.abs(x2 - x); - var cy = Math.abs(y2 - y); - result.routepath += 'A ' + cx + ' ' + cy + ' 0 0 ' + angle + ' ' + x2 + ' ' + y2 + ' '; - } - else { - var arrowtip = [x, y]; - var arrowcorner1, arrowcorner2; - if (Math.abs(dx) > 0) { - x -= dx / Math.abs(dx) * arrowheight; - arrowcorner1 = [x, y + arrowwidth]; - arrowcorner2 = [x, y - arrowwidth]; - } - else { - y -= dy / Math.abs(dy) * arrowheight; - arrowcorner1 = [x + arrowwidth, y]; - arrowcorner2 = [x - arrowwidth, y]; - } - result.routepath += 'L ' + x + ' ' + y + ' '; - if (arrowheight > 0) { - result.arrowpath = 'M ' + arrowtip[0] + ' ' + arrowtip[1] + ' L ' + arrowcorner1[0] + ' ' + arrowcorner1[1] - + ' L ' + arrowcorner2[0] + ' ' + arrowcorner2[1]; - } - } - } - } - else { - var li = route[0]; - var x = li[1].x, y = li[1].y; - var dx = x - li[0].x; - var dy = y - li[0].y; - var arrowtip = [x, y]; - var arrowcorner1, arrowcorner2; - if (Math.abs(dx) > 0) { - x -= dx / Math.abs(dx) * arrowheight; - arrowcorner1 = [x, y + arrowwidth]; - arrowcorner2 = [x, y - arrowwidth]; - } - else { - y -= dy / Math.abs(dy) * arrowheight; - arrowcorner1 = [x + arrowwidth, y]; - arrowcorner2 = [x - arrowwidth, y]; - } - result.routepath += 'L ' + x + ' ' + y + ' '; - if (arrowheight > 0) { - result.arrowpath = 'M ' + arrowtip[0] + ' ' + arrowtip[1] + ' L ' + arrowcorner1[0] + ' ' + arrowcorner1[1] - + ' L ' + arrowcorner2[0] + ' ' + arrowcorner2[1]; - } - } - return result; - }; - return GridRouter; -}()); -exports.GridRouter = GridRouter; - -},{"./rectangle":17,"./shortestpaths":18,"./vpsc":19}],10:[function(require,module,exports){ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -var packingOptions = { - PADDING: 10, - GOLDEN_SECTION: (1 + Math.sqrt(5)) / 2, - FLOAT_EPSILON: 0.0001, - MAX_INERATIONS: 100 -}; -function applyPacking(graphs, w, h, node_size, desired_ratio, centerGraph) { - if (desired_ratio === void 0) { desired_ratio = 1; } - if (centerGraph === void 0) { centerGraph = true; } - var init_x = 0, init_y = 0, svg_width = w, svg_height = h, desired_ratio = typeof desired_ratio !== 'undefined' ? desired_ratio : 1, node_size = typeof node_size !== 'undefined' ? node_size : 0, real_width = 0, real_height = 0, min_width = 0, global_bottom = 0, line = []; - if (graphs.length == 0) - return; - calculate_bb(graphs); - apply(graphs, desired_ratio); - if (centerGraph) { - put_nodes_to_right_positions(graphs); - } - function calculate_bb(graphs) { - graphs.forEach(function (g) { - calculate_single_bb(g); - }); - function calculate_single_bb(graph) { - var min_x = Number.MAX_VALUE, min_y = Number.MAX_VALUE, max_x = 0, max_y = 0; - graph.array.forEach(function (v) { - var w = typeof v.width !== 'undefined' ? v.width : node_size; - var h = typeof v.height !== 'undefined' ? v.height : node_size; - w /= 2; - h /= 2; - max_x = Math.max(v.x + w, max_x); - min_x = Math.min(v.x - w, min_x); - max_y = Math.max(v.y + h, max_y); - min_y = Math.min(v.y - h, min_y); - }); - graph.width = max_x - min_x; - graph.height = max_y - min_y; - } - } - function put_nodes_to_right_positions(graphs) { - graphs.forEach(function (g) { - var center = { x: 0, y: 0 }; - g.array.forEach(function (node) { - center.x += node.x; - center.y += node.y; - }); - center.x /= g.array.length; - center.y /= g.array.length; - var corner = { x: center.x - g.width / 2, y: center.y - g.height / 2 }; - var offset = { x: g.x - corner.x + svg_width / 2 - real_width / 2, y: g.y - corner.y + svg_height / 2 - real_height / 2 }; - g.array.forEach(function (node) { - node.x += offset.x; - node.y += offset.y; - }); - }); - } - function apply(data, desired_ratio) { - var curr_best_f = Number.POSITIVE_INFINITY; - var curr_best = 0; - data.sort(function (a, b) { return b.height - a.height; }); - min_width = data.reduce(function (a, b) { - return a.width < b.width ? a.width : b.width; - }); - var left = x1 = min_width; - var right = x2 = get_entire_width(data); - var iterationCounter = 0; - var f_x1 = Number.MAX_VALUE; - var f_x2 = Number.MAX_VALUE; - var flag = -1; - var dx = Number.MAX_VALUE; - var df = Number.MAX_VALUE; - while ((dx > min_width) || df > packingOptions.FLOAT_EPSILON) { - if (flag != 1) { - var x1 = right - (right - left) / packingOptions.GOLDEN_SECTION; - var f_x1 = step(data, x1); - } - if (flag != 0) { - var x2 = left + (right - left) / packingOptions.GOLDEN_SECTION; - var f_x2 = step(data, x2); - } - dx = Math.abs(x1 - x2); - df = Math.abs(f_x1 - f_x2); - if (f_x1 < curr_best_f) { - curr_best_f = f_x1; - curr_best = x1; - } - if (f_x2 < curr_best_f) { - curr_best_f = f_x2; - curr_best = x2; - } - if (f_x1 > f_x2) { - left = x1; - x1 = x2; - f_x1 = f_x2; - flag = 1; - } - else { - right = x2; - x2 = x1; - f_x2 = f_x1; - flag = 0; - } - if (iterationCounter++ > 100) { - break; - } - } - step(data, curr_best); - } - function step(data, max_width) { - line = []; - real_width = 0; - real_height = 0; - global_bottom = init_y; - for (var i = 0; i < data.length; i++) { - var o = data[i]; - put_rect(o, max_width); - } - return Math.abs(get_real_ratio() - desired_ratio); - } - function put_rect(rect, max_width) { - var parent = undefined; - for (var i = 0; i < line.length; i++) { - if ((line[i].space_left >= rect.height) && (line[i].x + line[i].width + rect.width + packingOptions.PADDING - max_width) <= packingOptions.FLOAT_EPSILON) { - parent = line[i]; - break; - } - } - line.push(rect); - if (parent !== undefined) { - rect.x = parent.x + parent.width + packingOptions.PADDING; - rect.y = parent.bottom; - rect.space_left = rect.height; - rect.bottom = rect.y; - parent.space_left -= rect.height + packingOptions.PADDING; - parent.bottom += rect.height + packingOptions.PADDING; - } - else { - rect.y = global_bottom; - global_bottom += rect.height + packingOptions.PADDING; - rect.x = init_x; - rect.bottom = rect.y; - rect.space_left = rect.height; - } - if (rect.y + rect.height - real_height > -packingOptions.FLOAT_EPSILON) - real_height = rect.y + rect.height - init_y; - if (rect.x + rect.width - real_width > -packingOptions.FLOAT_EPSILON) - real_width = rect.x + rect.width - init_x; - } - ; - function get_entire_width(data) { - var width = 0; - data.forEach(function (d) { return width += d.width + packingOptions.PADDING; }); - return width; - } - function get_real_ratio() { - return (real_width / real_height); - } -} -exports.applyPacking = applyPacking; -function separateGraphs(nodes, links) { - var marks = {}; - var ways = {}; - var graphs = []; - var clusters = 0; - for (var i = 0; i < links.length; i++) { - var link = links[i]; - var n1 = link.source; - var n2 = link.target; - if (ways[n1.index]) - ways[n1.index].push(n2); - else - ways[n1.index] = [n2]; - if (ways[n2.index]) - ways[n2.index].push(n1); - else - ways[n2.index] = [n1]; - } - for (var i = 0; i < nodes.length; i++) { - var node = nodes[i]; - if (marks[node.index]) - continue; - explore_node(node, true); - } - function explore_node(n, is_new) { - if (marks[n.index] !== undefined) - return; - if (is_new) { - clusters++; - graphs.push({ array: [] }); - } - marks[n.index] = clusters; - graphs[clusters - 1].array.push(n); - var adjacent = ways[n.index]; - if (!adjacent) - return; - for (var j = 0; j < adjacent.length; j++) { - explore_node(adjacent[j], false); - } - } - return graphs; -} -exports.separateGraphs = separateGraphs; - -},{}],11:[function(require,module,exports){ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -var powergraph = require("./powergraph"); -var linklengths_1 = require("./linklengths"); -var descent_1 = require("./descent"); -var rectangle_1 = require("./rectangle"); -var shortestpaths_1 = require("./shortestpaths"); -var geom_1 = require("./geom"); -var handledisconnected_1 = require("./handledisconnected"); -var EventType; -(function (EventType) { - EventType[EventType["start"] = 0] = "start"; - EventType[EventType["tick"] = 1] = "tick"; - EventType[EventType["end"] = 2] = "end"; -})(EventType = exports.EventType || (exports.EventType = {})); -; -function isGroup(g) { - return typeof g.leaves !== 'undefined' || typeof g.groups !== 'undefined'; -} -var Layout = (function () { - function Layout() { - var _this = this; - this._canvasSize = [1, 1]; - this._linkDistance = 20; - this._defaultNodeSize = 10; - this._linkLengthCalculator = null; - this._linkType = null; - this._avoidOverlaps = false; - this._handleDisconnected = true; - this._running = false; - this._nodes = []; - this._groups = []; - this._rootGroup = null; - this._links = []; - this._constraints = []; - this._distanceMatrix = null; - this._descent = null; - this._directedLinkConstraints = null; - this._threshold = 0.01; - this._visibilityGraph = null; - this._groupCompactness = 1e-6; - this.event = null; - this.linkAccessor = { - getSourceIndex: Layout.getSourceIndex, - getTargetIndex: Layout.getTargetIndex, - setLength: Layout.setLinkLength, - getType: function (l) { return typeof _this._linkType === "function" ? _this._linkType(l) : 0; } - }; - } - Layout.prototype.on = function (e, listener) { - if (!this.event) - this.event = {}; - if (typeof e === 'string') { - this.event[EventType[e]] = listener; - } - else { - this.event[e] = listener; - } - return this; - }; - Layout.prototype.trigger = function (e) { - if (this.event && typeof this.event[e.type] !== 'undefined') { - this.event[e.type](e); - } - }; - Layout.prototype.kick = function () { - while (!this.tick()) - ; - }; - Layout.prototype.tick = function () { - if (this._alpha < this._threshold) { - this._running = false; - this.trigger({ type: EventType.end, alpha: this._alpha = 0, stress: this._lastStress }); - return true; - } - var n = this._nodes.length, m = this._links.length; - var o, i; - this._descent.locks.clear(); - for (i = 0; i < n; ++i) { - o = this._nodes[i]; - if (o.fixed) { - if (typeof o.px === 'undefined' || typeof o.py === 'undefined') { - o.px = o.x; - o.py = o.y; - } - var p = [o.px, o.py]; - this._descent.locks.add(i, p); - } - } - var s1 = this._descent.rungeKutta(); - if (s1 === 0) { - this._alpha = 0; - } - else if (typeof this._lastStress !== 'undefined') { - this._alpha = s1; - } - this._lastStress = s1; - this.updateNodePositions(); - this.trigger({ type: EventType.tick, alpha: this._alpha, stress: this._lastStress }); - return false; - }; - Layout.prototype.updateNodePositions = function () { - var x = this._descent.x[0], y = this._descent.x[1]; - var o, i = this._nodes.length; - while (i--) { - o = this._nodes[i]; - o.x = x[i]; - o.y = y[i]; - } - }; - Layout.prototype.nodes = function (v) { - if (!v) { - if (this._nodes.length === 0 && this._links.length > 0) { - var n = 0; - this._links.forEach(function (l) { - n = Math.max(n, l.source, l.target); - }); - this._nodes = new Array(++n); - for (var i = 0; i < n; ++i) { - this._nodes[i] = {}; - } - } - return this._nodes; - } - this._nodes = v; - return this; - }; - Layout.prototype.groups = function (x) { - var _this = this; - if (!x) - return this._groups; - this._groups = x; - this._rootGroup = {}; - this._groups.forEach(function (g) { - if (typeof g.padding === "undefined") - g.padding = 1; - if (typeof g.leaves !== "undefined") { - g.leaves.forEach(function (v, i) { - if (typeof v === 'number') - (g.leaves[i] = _this._nodes[v]).parent = g; - }); - } - if (typeof g.groups !== "undefined") { - g.groups.forEach(function (gi, i) { - if (typeof gi === 'number') - (g.groups[i] = _this._groups[gi]).parent = g; - }); - } - }); - this._rootGroup.leaves = this._nodes.filter(function (v) { return typeof v.parent === 'undefined'; }); - this._rootGroup.groups = this._groups.filter(function (g) { return typeof g.parent === 'undefined'; }); - return this; - }; - Layout.prototype.powerGraphGroups = function (f) { - var g = powergraph.getGroups(this._nodes, this._links, this.linkAccessor, this._rootGroup); - this.groups(g.groups); - f(g); - return this; - }; - Layout.prototype.avoidOverlaps = function (v) { - if (!arguments.length) - return this._avoidOverlaps; - this._avoidOverlaps = v; - return this; - }; - Layout.prototype.handleDisconnected = function (v) { - if (!arguments.length) - return this._handleDisconnected; - this._handleDisconnected = v; - return this; - }; - Layout.prototype.flowLayout = function (axis, minSeparation) { - if (!arguments.length) - axis = 'y'; - this._directedLinkConstraints = { - axis: axis, - getMinSeparation: typeof minSeparation === 'number' ? function () { return minSeparation; } : minSeparation - }; - return this; - }; - Layout.prototype.links = function (x) { - if (!arguments.length) - return this._links; - this._links = x; - return this; - }; - Layout.prototype.constraints = function (c) { - if (!arguments.length) - return this._constraints; - this._constraints = c; - return this; - }; - Layout.prototype.distanceMatrix = function (d) { - if (!arguments.length) - return this._distanceMatrix; - this._distanceMatrix = d; - return this; - }; - Layout.prototype.size = function (x) { - if (!x) - return this._canvasSize; - this._canvasSize = x; - return this; - }; - Layout.prototype.defaultNodeSize = function (x) { - if (!x) - return this._defaultNodeSize; - this._defaultNodeSize = x; - return this; - }; - Layout.prototype.groupCompactness = function (x) { - if (!x) - return this._groupCompactness; - this._groupCompactness = x; - return this; - }; - Layout.prototype.linkDistance = function (x) { - if (!x) { - return this._linkDistance; - } - this._linkDistance = typeof x === "function" ? x : +x; - this._linkLengthCalculator = null; - return this; - }; - Layout.prototype.linkType = function (f) { - this._linkType = f; - return this; - }; - Layout.prototype.convergenceThreshold = function (x) { - if (!x) - return this._threshold; - this._threshold = typeof x === "function" ? x : +x; - return this; - }; - Layout.prototype.alpha = function (x) { - if (!arguments.length) - return this._alpha; - else { - x = +x; - if (this._alpha) { - if (x > 0) - this._alpha = x; - else - this._alpha = 0; - } - else if (x > 0) { - if (!this._running) { - this._running = true; - this.trigger({ type: EventType.start, alpha: this._alpha = x }); - this.kick(); - } - } - return this; - } - }; - Layout.prototype.getLinkLength = function (link) { - return typeof this._linkDistance === "function" ? +(this._linkDistance(link)) : this._linkDistance; - }; - Layout.setLinkLength = function (link, length) { - link.length = length; - }; - Layout.prototype.getLinkType = function (link) { - return typeof this._linkType === "function" ? this._linkType(link) : 0; - }; - Layout.prototype.symmetricDiffLinkLengths = function (idealLength, w) { - var _this = this; - if (w === void 0) { w = 1; } - this.linkDistance(function (l) { return idealLength * l.length; }); - this._linkLengthCalculator = function () { return linklengths_1.symmetricDiffLinkLengths(_this._links, _this.linkAccessor, w); }; - return this; - }; - Layout.prototype.jaccardLinkLengths = function (idealLength, w) { - var _this = this; - if (w === void 0) { w = 1; } - this.linkDistance(function (l) { return idealLength * l.length; }); - this._linkLengthCalculator = function () { return linklengths_1.jaccardLinkLengths(_this._links, _this.linkAccessor, w); }; - return this; - }; - Layout.prototype.start = function (initialUnconstrainedIterations, initialUserConstraintIterations, initialAllConstraintsIterations, gridSnapIterations, keepRunning, centerGraph) { - var _this = this; - if (initialUnconstrainedIterations === void 0) { initialUnconstrainedIterations = 0; } - if (initialUserConstraintIterations === void 0) { initialUserConstraintIterations = 0; } - if (initialAllConstraintsIterations === void 0) { initialAllConstraintsIterations = 0; } - if (gridSnapIterations === void 0) { gridSnapIterations = 0; } - if (keepRunning === void 0) { keepRunning = true; } - if (centerGraph === void 0) { centerGraph = true; } - var i, j, n = this.nodes().length, N = n + 2 * this._groups.length, m = this._links.length, w = this._canvasSize[0], h = this._canvasSize[1]; - var x = new Array(N), y = new Array(N); - var G = null; - var ao = this._avoidOverlaps; - this._nodes.forEach(function (v, i) { - v.index = i; - if (typeof v.x === 'undefined') { - v.x = w / 2, v.y = h / 2; - } - x[i] = v.x, y[i] = v.y; - }); - if (this._linkLengthCalculator) - this._linkLengthCalculator(); - var distances; - if (this._distanceMatrix) { - distances = this._distanceMatrix; - } - else { - distances = (new shortestpaths_1.Calculator(N, this._links, Layout.getSourceIndex, Layout.getTargetIndex, function (l) { return _this.getLinkLength(l); })).DistanceMatrix(); - G = descent_1.Descent.createSquareMatrix(N, function () { return 2; }); - this._links.forEach(function (l) { - if (typeof l.source == "number") - l.source = _this._nodes[l.source]; - if (typeof l.target == "number") - l.target = _this._nodes[l.target]; - }); - this._links.forEach(function (e) { - var u = Layout.getSourceIndex(e), v = Layout.getTargetIndex(e); - G[u][v] = G[v][u] = e.weight || 1; - }); - } - var D = descent_1.Descent.createSquareMatrix(N, function (i, j) { - return distances[i][j]; - }); - if (this._rootGroup && typeof this._rootGroup.groups !== 'undefined') { - var i = n; - var addAttraction = function (i, j, strength, idealDistance) { - G[i][j] = G[j][i] = strength; - D[i][j] = D[j][i] = idealDistance; - }; - this._groups.forEach(function (g) { - addAttraction(i, i + 1, _this._groupCompactness, 0.1); - x[i] = 0, y[i++] = 0; - x[i] = 0, y[i++] = 0; - }); - } - else - this._rootGroup = { leaves: this._nodes, groups: [] }; - var curConstraints = this._constraints || []; - if (this._directedLinkConstraints) { - this.linkAccessor.getMinSeparation = this._directedLinkConstraints.getMinSeparation; - curConstraints = curConstraints.concat(linklengths_1.generateDirectedEdgeConstraints(n, this._links, this._directedLinkConstraints.axis, (this.linkAccessor))); - } - this.avoidOverlaps(false); - this._descent = new descent_1.Descent([x, y], D); - this._descent.locks.clear(); - for (var i = 0; i < n; ++i) { - var o = this._nodes[i]; - if (o.fixed) { - o.px = o.x; - o.py = o.y; - var p = [o.x, o.y]; - this._descent.locks.add(i, p); - } - } - this._descent.threshold = this._threshold; - this.initialLayout(initialUnconstrainedIterations, x, y); - if (curConstraints.length > 0) - this._descent.project = new rectangle_1.Projection(this._nodes, this._groups, this._rootGroup, curConstraints).projectFunctions(); - this._descent.run(initialUserConstraintIterations); - this.separateOverlappingComponents(w, h, centerGraph); - this.avoidOverlaps(ao); - if (ao) { - this._nodes.forEach(function (v, i) { v.x = x[i], v.y = y[i]; }); - this._descent.project = new rectangle_1.Projection(this._nodes, this._groups, this._rootGroup, curConstraints, true).projectFunctions(); - this._nodes.forEach(function (v, i) { x[i] = v.x, y[i] = v.y; }); - } - this._descent.G = G; - this._descent.run(initialAllConstraintsIterations); - if (gridSnapIterations) { - this._descent.snapStrength = 1000; - this._descent.snapGridSize = this._nodes[0].width; - this._descent.numGridSnapNodes = n; - this._descent.scaleSnapByMaxH = n != N; - var G0 = descent_1.Descent.createSquareMatrix(N, function (i, j) { - if (i >= n || j >= n) - return G[i][j]; - return 0; - }); - this._descent.G = G0; - this._descent.run(gridSnapIterations); - } - this.updateNodePositions(); - this.separateOverlappingComponents(w, h, centerGraph); - return keepRunning ? this.resume() : this; - }; - Layout.prototype.initialLayout = function (iterations, x, y) { - if (this._groups.length > 0 && iterations > 0) { - var n = this._nodes.length; - var edges = this._links.map(function (e) { return ({ source: e.source.index, target: e.target.index }); }); - var vs = this._nodes.map(function (v) { return ({ index: v.index }); }); - this._groups.forEach(function (g, i) { - vs.push({ index: g.index = n + i }); - }); - this._groups.forEach(function (g, i) { - if (typeof g.leaves !== 'undefined') - g.leaves.forEach(function (v) { return edges.push({ source: g.index, target: v.index }); }); - if (typeof g.groups !== 'undefined') - g.groups.forEach(function (gg) { return edges.push({ source: g.index, target: gg.index }); }); - }); - new Layout() - .size(this.size()) - .nodes(vs) - .links(edges) - .avoidOverlaps(false) - .linkDistance(this.linkDistance()) - .symmetricDiffLinkLengths(5) - .convergenceThreshold(1e-4) - .start(iterations, 0, 0, 0, false); - this._nodes.forEach(function (v) { - x[v.index] = vs[v.index].x; - y[v.index] = vs[v.index].y; - }); - } - else { - this._descent.run(iterations); - } - }; - Layout.prototype.separateOverlappingComponents = function (width, height, centerGraph) { - var _this = this; - if (centerGraph === void 0) { centerGraph = true; } - if (!this._distanceMatrix && this._handleDisconnected) { - var x_1 = this._descent.x[0], y_1 = this._descent.x[1]; - this._nodes.forEach(function (v, i) { v.x = x_1[i], v.y = y_1[i]; }); - var graphs = handledisconnected_1.separateGraphs(this._nodes, this._links); - handledisconnected_1.applyPacking(graphs, width, height, this._defaultNodeSize, (height / width), centerGraph); - this._nodes.forEach(function (v, i) { - _this._descent.x[0][i] = v.x, _this._descent.x[1][i] = v.y; - if (v.bounds) { - v.bounds.setXCentre(v.x); - v.bounds.setYCentre(v.y); - } - }); - } - }; - Layout.prototype.resume = function () { - return this.alpha(0.1); - }; - Layout.prototype.stop = function () { - return this.alpha(0); - }; - Layout.prototype.prepareEdgeRouting = function (nodeMargin) { - if (nodeMargin === void 0) { nodeMargin = 0; } - this._visibilityGraph = new geom_1.TangentVisibilityGraph(this._nodes.map(function (v) { - return v.bounds.inflate(-nodeMargin).vertices(); - })); - }; - Layout.prototype.routeEdge = function (edge, ah, draw) { - if (ah === void 0) { ah = 5; } - var lineData = []; - var vg2 = new geom_1.TangentVisibilityGraph(this._visibilityGraph.P, { V: this._visibilityGraph.V, E: this._visibilityGraph.E }), port1 = { x: edge.source.x, y: edge.source.y }, port2 = { x: edge.target.x, y: edge.target.y }, start = vg2.addPoint(port1, edge.source.index), end = vg2.addPoint(port2, edge.target.index); - vg2.addEdgeIfVisible(port1, port2, edge.source.index, edge.target.index); - if (typeof draw !== 'undefined') { - draw(vg2); - } - var sourceInd = function (e) { return e.source.id; }, targetInd = function (e) { return e.target.id; }, length = function (e) { return e.length(); }, spCalc = new shortestpaths_1.Calculator(vg2.V.length, vg2.E, sourceInd, targetInd, length), shortestPath = spCalc.PathFromNodeToNode(start.id, end.id); - if (shortestPath.length === 1 || shortestPath.length === vg2.V.length) { - var route = rectangle_1.makeEdgeBetween(edge.source.innerBounds, edge.target.innerBounds, ah); - lineData = [route.sourceIntersection, route.arrowStart]; - } - else { - var n = shortestPath.length - 2, p = vg2.V[shortestPath[n]].p, q = vg2.V[shortestPath[0]].p, lineData = [edge.source.innerBounds.rayIntersection(p.x, p.y)]; - for (var i = n; i >= 0; --i) - lineData.push(vg2.V[shortestPath[i]].p); - lineData.push(rectangle_1.makeEdgeTo(q, edge.target.innerBounds, ah)); - } - return lineData; - }; - Layout.getSourceIndex = function (e) { - return typeof e.source === 'number' ? e.source : e.source.index; - }; - Layout.getTargetIndex = function (e) { - return typeof e.target === 'number' ? e.target : e.target.index; - }; - Layout.linkId = function (e) { - return Layout.getSourceIndex(e) + "-" + Layout.getTargetIndex(e); - }; - Layout.dragStart = function (d) { - if (isGroup(d)) { - Layout.storeOffset(d, Layout.dragOrigin(d)); - } - else { - Layout.stopNode(d); - d.fixed |= 2; - } - }; - Layout.stopNode = function (v) { - v.px = v.x; - v.py = v.y; - }; - Layout.storeOffset = function (d, origin) { - if (typeof d.leaves !== 'undefined') { - d.leaves.forEach(function (v) { - v.fixed |= 2; - Layout.stopNode(v); - v._dragGroupOffsetX = v.x - origin.x; - v._dragGroupOffsetY = v.y - origin.y; - }); - } - if (typeof d.groups !== 'undefined') { - d.groups.forEach(function (g) { return Layout.storeOffset(g, origin); }); - } - }; - Layout.dragOrigin = function (d) { - if (isGroup(d)) { - return { - x: d.bounds.cx(), - y: d.bounds.cy() - }; - } - else { - return d; - } - }; - Layout.drag = function (d, position) { - if (isGroup(d)) { - if (typeof d.leaves !== 'undefined') { - d.leaves.forEach(function (v) { - d.bounds.setXCentre(position.x); - d.bounds.setYCentre(position.y); - v.px = v._dragGroupOffsetX + position.x; - v.py = v._dragGroupOffsetY + position.y; - }); - } - if (typeof d.groups !== 'undefined') { - d.groups.forEach(function (g) { return Layout.drag(g, position); }); - } - } - else { - d.px = position.x; - d.py = position.y; - } - }; - Layout.dragEnd = function (d) { - if (isGroup(d)) { - if (typeof d.leaves !== 'undefined') { - d.leaves.forEach(function (v) { - Layout.dragEnd(v); - delete v._dragGroupOffsetX; - delete v._dragGroupOffsetY; - }); - } - if (typeof d.groups !== 'undefined') { - d.groups.forEach(Layout.dragEnd); - } - } - else { - d.fixed &= ~6; - } - }; - Layout.mouseOver = function (d) { - d.fixed |= 4; - d.px = d.x, d.py = d.y; - }; - Layout.mouseOut = function (d) { - d.fixed &= ~4; - }; - return Layout; -}()); -exports.Layout = Layout; - -},{"./descent":7,"./geom":8,"./handledisconnected":10,"./linklengths":13,"./powergraph":14,"./rectangle":17,"./shortestpaths":18}],12:[function(require,module,exports){ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -var shortestpaths_1 = require("./shortestpaths"); -var descent_1 = require("./descent"); -var rectangle_1 = require("./rectangle"); -var linklengths_1 = require("./linklengths"); -var Link3D = (function () { - function Link3D(source, target) { - this.source = source; - this.target = target; - } - Link3D.prototype.actualLength = function (x) { - var _this = this; - return Math.sqrt(x.reduce(function (c, v) { - var dx = v[_this.target] - v[_this.source]; - return c + dx * dx; - }, 0)); - }; - return Link3D; -}()); -exports.Link3D = Link3D; -var Node3D = (function () { - function Node3D(x, y, z) { - if (x === void 0) { x = 0; } - if (y === void 0) { y = 0; } - if (z === void 0) { z = 0; } - this.x = x; - this.y = y; - this.z = z; - } - return Node3D; -}()); -exports.Node3D = Node3D; -var Layout3D = (function () { - function Layout3D(nodes, links, idealLinkLength) { - var _this = this; - if (idealLinkLength === void 0) { idealLinkLength = 1; } - this.nodes = nodes; - this.links = links; - this.idealLinkLength = idealLinkLength; - this.constraints = null; - this.useJaccardLinkLengths = true; - this.result = new Array(Layout3D.k); - for (var i = 0; i < Layout3D.k; ++i) { - this.result[i] = new Array(nodes.length); - } - nodes.forEach(function (v, i) { - for (var _i = 0, _a = Layout3D.dims; _i < _a.length; _i++) { - var dim = _a[_i]; - if (typeof v[dim] == 'undefined') - v[dim] = Math.random(); - } - _this.result[0][i] = v.x; - _this.result[1][i] = v.y; - _this.result[2][i] = v.z; - }); - } - ; - Layout3D.prototype.linkLength = function (l) { - return l.actualLength(this.result); - }; - Layout3D.prototype.start = function (iterations) { - var _this = this; - if (iterations === void 0) { iterations = 100; } - var n = this.nodes.length; - var linkAccessor = new LinkAccessor(); - if (this.useJaccardLinkLengths) - linklengths_1.jaccardLinkLengths(this.links, linkAccessor, 1.5); - this.links.forEach(function (e) { return e.length *= _this.idealLinkLength; }); - var distanceMatrix = (new shortestpaths_1.Calculator(n, this.links, function (e) { return e.source; }, function (e) { return e.target; }, function (e) { return e.length; })).DistanceMatrix(); - var D = descent_1.Descent.createSquareMatrix(n, function (i, j) { return distanceMatrix[i][j]; }); - var G = descent_1.Descent.createSquareMatrix(n, function () { return 2; }); - this.links.forEach(function (_a) { - var source = _a.source, target = _a.target; - return G[source][target] = G[target][source] = 1; - }); - this.descent = new descent_1.Descent(this.result, D); - this.descent.threshold = 1e-3; - this.descent.G = G; - if (this.constraints) - this.descent.project = new rectangle_1.Projection(this.nodes, null, null, this.constraints).projectFunctions(); - for (var i = 0; i < this.nodes.length; i++) { - var v = this.nodes[i]; - if (v.fixed) { - this.descent.locks.add(i, [v.x, v.y, v.z]); - } - } - this.descent.run(iterations); - return this; - }; - Layout3D.prototype.tick = function () { - this.descent.locks.clear(); - for (var i = 0; i < this.nodes.length; i++) { - var v = this.nodes[i]; - if (v.fixed) { - this.descent.locks.add(i, [v.x, v.y, v.z]); - } - } - return this.descent.rungeKutta(); - }; - Layout3D.dims = ['x', 'y', 'z']; - Layout3D.k = Layout3D.dims.length; - return Layout3D; -}()); -exports.Layout3D = Layout3D; -var LinkAccessor = (function () { - function LinkAccessor() { - } - LinkAccessor.prototype.getSourceIndex = function (e) { return e.source; }; - LinkAccessor.prototype.getTargetIndex = function (e) { return e.target; }; - LinkAccessor.prototype.getLength = function (e) { return e.length; }; - LinkAccessor.prototype.setLength = function (e, l) { e.length = l; }; - return LinkAccessor; -}()); - -},{"./descent":7,"./linklengths":13,"./rectangle":17,"./shortestpaths":18}],13:[function(require,module,exports){ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -function unionCount(a, b) { - var u = {}; - for (var i in a) - u[i] = {}; - for (var i in b) - u[i] = {}; - return Object.keys(u).length; -} -function intersectionCount(a, b) { - var n = 0; - for (var i in a) - if (typeof b[i] !== 'undefined') - ++n; - return n; -} -function getNeighbours(links, la) { - var neighbours = {}; - var addNeighbours = function (u, v) { - if (typeof neighbours[u] === 'undefined') - neighbours[u] = {}; - neighbours[u][v] = {}; - }; - links.forEach(function (e) { - var u = la.getSourceIndex(e), v = la.getTargetIndex(e); - addNeighbours(u, v); - addNeighbours(v, u); - }); - return neighbours; -} -function computeLinkLengths(links, w, f, la) { - var neighbours = getNeighbours(links, la); - links.forEach(function (l) { - var a = neighbours[la.getSourceIndex(l)]; - var b = neighbours[la.getTargetIndex(l)]; - la.setLength(l, 1 + w * f(a, b)); - }); -} -function symmetricDiffLinkLengths(links, la, w) { - if (w === void 0) { w = 1; } - computeLinkLengths(links, w, function (a, b) { return Math.sqrt(unionCount(a, b) - intersectionCount(a, b)); }, la); -} -exports.symmetricDiffLinkLengths = symmetricDiffLinkLengths; -function jaccardLinkLengths(links, la, w) { - if (w === void 0) { w = 1; } - computeLinkLengths(links, w, function (a, b) { - return Math.min(Object.keys(a).length, Object.keys(b).length) < 1.1 ? 0 : intersectionCount(a, b) / unionCount(a, b); - }, la); -} -exports.jaccardLinkLengths = jaccardLinkLengths; -function generateDirectedEdgeConstraints(n, links, axis, la) { - var components = stronglyConnectedComponents(n, links, la); - var nodes = {}; - components.forEach(function (c, i) { - return c.forEach(function (v) { return nodes[v] = i; }); - }); - var constraints = []; - links.forEach(function (l) { - var ui = la.getSourceIndex(l), vi = la.getTargetIndex(l), u = nodes[ui], v = nodes[vi]; - if (u !== v) { - constraints.push({ - axis: axis, - left: ui, - right: vi, - gap: la.getMinSeparation(l) - }); - } - }); - return constraints; -} -exports.generateDirectedEdgeConstraints = generateDirectedEdgeConstraints; -function stronglyConnectedComponents(numVertices, edges, la) { - var nodes = []; - var index = 0; - var stack = []; - var components = []; - function strongConnect(v) { - v.index = v.lowlink = index++; - stack.push(v); - v.onStack = true; - for (var _i = 0, _a = v.out; _i < _a.length; _i++) { - var w = _a[_i]; - if (typeof w.index === 'undefined') { - strongConnect(w); - v.lowlink = Math.min(v.lowlink, w.lowlink); - } - else if (w.onStack) { - v.lowlink = Math.min(v.lowlink, w.index); - } - } - if (v.lowlink === v.index) { - var component = []; - while (stack.length) { - w = stack.pop(); - w.onStack = false; - component.push(w); - if (w === v) - break; - } - components.push(component.map(function (v) { return v.id; })); - } - } - for (var i = 0; i < numVertices; i++) { - nodes.push({ id: i, out: [] }); - } - for (var _i = 0, edges_1 = edges; _i < edges_1.length; _i++) { - var e = edges_1[_i]; - var v_1 = nodes[la.getSourceIndex(e)], w = nodes[la.getTargetIndex(e)]; - v_1.out.push(w); - } - for (var _a = 0, nodes_1 = nodes; _a < nodes_1.length; _a++) { - var v = nodes_1[_a]; - if (typeof v.index === 'undefined') - strongConnect(v); - } - return components; -} -exports.stronglyConnectedComponents = stronglyConnectedComponents; - -},{}],14:[function(require,module,exports){ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -var PowerEdge = (function () { - function PowerEdge(source, target, type) { - this.source = source; - this.target = target; - this.type = type; - } - return PowerEdge; -}()); -exports.PowerEdge = PowerEdge; -var Configuration = (function () { - function Configuration(n, edges, linkAccessor, rootGroup) { - var _this = this; - this.linkAccessor = linkAccessor; - this.modules = new Array(n); - this.roots = []; - if (rootGroup) { - this.initModulesFromGroup(rootGroup); - } - else { - this.roots.push(new ModuleSet()); - for (var i = 0; i < n; ++i) - this.roots[0].add(this.modules[i] = new Module(i)); - } - this.R = edges.length; - edges.forEach(function (e) { - var s = _this.modules[linkAccessor.getSourceIndex(e)], t = _this.modules[linkAccessor.getTargetIndex(e)], type = linkAccessor.getType(e); - s.outgoing.add(type, t); - t.incoming.add(type, s); - }); - } - Configuration.prototype.initModulesFromGroup = function (group) { - var moduleSet = new ModuleSet(); - this.roots.push(moduleSet); - for (var i = 0; i < group.leaves.length; ++i) { - var node = group.leaves[i]; - var module = new Module(node.id); - this.modules[node.id] = module; - moduleSet.add(module); - } - if (group.groups) { - for (var j = 0; j < group.groups.length; ++j) { - var child = group.groups[j]; - var definition = {}; - for (var prop in child) - if (prop !== "leaves" && prop !== "groups" && child.hasOwnProperty(prop)) - definition[prop] = child[prop]; - moduleSet.add(new Module(-1 - j, new LinkSets(), new LinkSets(), this.initModulesFromGroup(child), definition)); - } - } - return moduleSet; - }; - Configuration.prototype.merge = function (a, b, k) { - if (k === void 0) { k = 0; } - var inInt = a.incoming.intersection(b.incoming), outInt = a.outgoing.intersection(b.outgoing); - var children = new ModuleSet(); - children.add(a); - children.add(b); - var m = new Module(this.modules.length, outInt, inInt, children); - this.modules.push(m); - var update = function (s, i, o) { - s.forAll(function (ms, linktype) { - ms.forAll(function (n) { - var nls = n[i]; - nls.add(linktype, m); - nls.remove(linktype, a); - nls.remove(linktype, b); - a[o].remove(linktype, n); - b[o].remove(linktype, n); - }); - }); - }; - update(outInt, "incoming", "outgoing"); - update(inInt, "outgoing", "incoming"); - this.R -= inInt.count() + outInt.count(); - this.roots[k].remove(a); - this.roots[k].remove(b); - this.roots[k].add(m); - return m; - }; - Configuration.prototype.rootMerges = function (k) { - if (k === void 0) { k = 0; } - var rs = this.roots[k].modules(); - var n = rs.length; - var merges = new Array(n * (n - 1)); - var ctr = 0; - for (var i = 0, i_ = n - 1; i < i_; ++i) { - for (var j = i + 1; j < n; ++j) { - var a = rs[i], b = rs[j]; - merges[ctr] = { id: ctr, nEdges: this.nEdges(a, b), a: a, b: b }; - ctr++; - } - } - return merges; - }; - Configuration.prototype.greedyMerge = function () { - for (var i = 0; i < this.roots.length; ++i) { - if (this.roots[i].modules().length < 2) - continue; - var ms = this.rootMerges(i).sort(function (a, b) { return a.nEdges == b.nEdges ? a.id - b.id : a.nEdges - b.nEdges; }); - var m = ms[0]; - if (m.nEdges >= this.R) - continue; - this.merge(m.a, m.b, i); - return true; - } - }; - Configuration.prototype.nEdges = function (a, b) { - var inInt = a.incoming.intersection(b.incoming), outInt = a.outgoing.intersection(b.outgoing); - return this.R - inInt.count() - outInt.count(); - }; - Configuration.prototype.getGroupHierarchy = function (retargetedEdges) { - var _this = this; - var groups = []; - var root = {}; - toGroups(this.roots[0], root, groups); - var es = this.allEdges(); - es.forEach(function (e) { - var a = _this.modules[e.source]; - var b = _this.modules[e.target]; - retargetedEdges.push(new PowerEdge(typeof a.gid === "undefined" ? e.source : groups[a.gid], typeof b.gid === "undefined" ? e.target : groups[b.gid], e.type)); - }); - return groups; - }; - Configuration.prototype.allEdges = function () { - var es = []; - Configuration.getEdges(this.roots[0], es); - return es; - }; - Configuration.getEdges = function (modules, es) { - modules.forAll(function (m) { - m.getEdges(es); - Configuration.getEdges(m.children, es); - }); - }; - return Configuration; -}()); -exports.Configuration = Configuration; -function toGroups(modules, group, groups) { - modules.forAll(function (m) { - if (m.isLeaf()) { - if (!group.leaves) - group.leaves = []; - group.leaves.push(m.id); - } - else { - var g = group; - m.gid = groups.length; - if (!m.isIsland() || m.isPredefined()) { - g = { id: m.gid }; - if (m.isPredefined()) - for (var prop in m.definition) - g[prop] = m.definition[prop]; - if (!group.groups) - group.groups = []; - group.groups.push(m.gid); - groups.push(g); - } - toGroups(m.children, g, groups); - } - }); -} -var Module = (function () { - function Module(id, outgoing, incoming, children, definition) { - if (outgoing === void 0) { outgoing = new LinkSets(); } - if (incoming === void 0) { incoming = new LinkSets(); } - if (children === void 0) { children = new ModuleSet(); } - this.id = id; - this.outgoing = outgoing; - this.incoming = incoming; - this.children = children; - this.definition = definition; - } - Module.prototype.getEdges = function (es) { - var _this = this; - this.outgoing.forAll(function (ms, edgetype) { - ms.forAll(function (target) { - es.push(new PowerEdge(_this.id, target.id, edgetype)); - }); - }); - }; - Module.prototype.isLeaf = function () { - return this.children.count() === 0; - }; - Module.prototype.isIsland = function () { - return this.outgoing.count() === 0 && this.incoming.count() === 0; - }; - Module.prototype.isPredefined = function () { - return typeof this.definition !== "undefined"; - }; - return Module; -}()); -exports.Module = Module; -function intersection(m, n) { - var i = {}; - for (var v in m) - if (v in n) - i[v] = m[v]; - return i; -} -var ModuleSet = (function () { - function ModuleSet() { - this.table = {}; - } - ModuleSet.prototype.count = function () { - return Object.keys(this.table).length; - }; - ModuleSet.prototype.intersection = function (other) { - var result = new ModuleSet(); - result.table = intersection(this.table, other.table); - return result; - }; - ModuleSet.prototype.intersectionCount = function (other) { - return this.intersection(other).count(); - }; - ModuleSet.prototype.contains = function (id) { - return id in this.table; - }; - ModuleSet.prototype.add = function (m) { - this.table[m.id] = m; - }; - ModuleSet.prototype.remove = function (m) { - delete this.table[m.id]; - }; - ModuleSet.prototype.forAll = function (f) { - for (var mid in this.table) { - f(this.table[mid]); - } - }; - ModuleSet.prototype.modules = function () { - var vs = []; - this.forAll(function (m) { - if (!m.isPredefined()) - vs.push(m); - }); - return vs; - }; - return ModuleSet; -}()); -exports.ModuleSet = ModuleSet; -var LinkSets = (function () { - function LinkSets() { - this.sets = {}; - this.n = 0; - } - LinkSets.prototype.count = function () { - return this.n; - }; - LinkSets.prototype.contains = function (id) { - var result = false; - this.forAllModules(function (m) { - if (!result && m.id == id) { - result = true; - } - }); - return result; - }; - LinkSets.prototype.add = function (linktype, m) { - var s = linktype in this.sets ? this.sets[linktype] : this.sets[linktype] = new ModuleSet(); - s.add(m); - ++this.n; - }; - LinkSets.prototype.remove = function (linktype, m) { - var ms = this.sets[linktype]; - ms.remove(m); - if (ms.count() === 0) { - delete this.sets[linktype]; - } - --this.n; - }; - LinkSets.prototype.forAll = function (f) { - for (var linktype in this.sets) { - f(this.sets[linktype], Number(linktype)); - } - }; - LinkSets.prototype.forAllModules = function (f) { - this.forAll(function (ms, lt) { return ms.forAll(f); }); - }; - LinkSets.prototype.intersection = function (other) { - var result = new LinkSets(); - this.forAll(function (ms, lt) { - if (lt in other.sets) { - var i = ms.intersection(other.sets[lt]), n = i.count(); - if (n > 0) { - result.sets[lt] = i; - result.n += n; - } - } - }); - return result; - }; - return LinkSets; -}()); -exports.LinkSets = LinkSets; -function intersectionCount(m, n) { - return Object.keys(intersection(m, n)).length; -} -function getGroups(nodes, links, la, rootGroup) { - var n = nodes.length, c = new Configuration(n, links, la, rootGroup); - while (c.greedyMerge()) - ; - var powerEdges = []; - var g = c.getGroupHierarchy(powerEdges); - powerEdges.forEach(function (e) { - var f = function (end) { - var g = e[end]; - if (typeof g == "number") - e[end] = nodes[g]; - }; - f("source"); - f("target"); - }); - return { groups: g, powerEdges: powerEdges }; -} -exports.getGroups = getGroups; - -},{}],15:[function(require,module,exports){ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -var PairingHeap = (function () { - function PairingHeap(elem) { - this.elem = elem; - this.subheaps = []; - } - PairingHeap.prototype.toString = function (selector) { - var str = "", needComma = false; - for (var i = 0; i < this.subheaps.length; ++i) { - var subheap = this.subheaps[i]; - if (!subheap.elem) { - needComma = false; - continue; - } - if (needComma) { - str = str + ","; - } - str = str + subheap.toString(selector); - needComma = true; - } - if (str !== "") { - str = "(" + str + ")"; - } - return (this.elem ? selector(this.elem) : "") + str; - }; - PairingHeap.prototype.forEach = function (f) { - if (!this.empty()) { - f(this.elem, this); - this.subheaps.forEach(function (s) { return s.forEach(f); }); - } - }; - PairingHeap.prototype.count = function () { - return this.empty() ? 0 : 1 + this.subheaps.reduce(function (n, h) { - return n + h.count(); - }, 0); - }; - PairingHeap.prototype.min = function () { - return this.elem; - }; - PairingHeap.prototype.empty = function () { - return this.elem == null; - }; - PairingHeap.prototype.contains = function (h) { - if (this === h) - return true; - for (var i = 0; i < this.subheaps.length; i++) { - if (this.subheaps[i].contains(h)) - return true; - } - return false; - }; - PairingHeap.prototype.isHeap = function (lessThan) { - var _this = this; - return this.subheaps.every(function (h) { return lessThan(_this.elem, h.elem) && h.isHeap(lessThan); }); - }; - PairingHeap.prototype.insert = function (obj, lessThan) { - return this.merge(new PairingHeap(obj), lessThan); - }; - PairingHeap.prototype.merge = function (heap2, lessThan) { - if (this.empty()) - return heap2; - else if (heap2.empty()) - return this; - else if (lessThan(this.elem, heap2.elem)) { - this.subheaps.push(heap2); - return this; - } - else { - heap2.subheaps.push(this); - return heap2; - } - }; - PairingHeap.prototype.removeMin = function (lessThan) { - if (this.empty()) - return null; - else - return this.mergePairs(lessThan); - }; - PairingHeap.prototype.mergePairs = function (lessThan) { - if (this.subheaps.length == 0) - return new PairingHeap(null); - else if (this.subheaps.length == 1) { - return this.subheaps[0]; - } - else { - var firstPair = this.subheaps.pop().merge(this.subheaps.pop(), lessThan); - var remaining = this.mergePairs(lessThan); - return firstPair.merge(remaining, lessThan); - } - }; - PairingHeap.prototype.decreaseKey = function (subheap, newValue, setHeapNode, lessThan) { - var newHeap = subheap.removeMin(lessThan); - subheap.elem = newHeap.elem; - subheap.subheaps = newHeap.subheaps; - if (setHeapNode !== null && newHeap.elem !== null) { - setHeapNode(subheap.elem, subheap); - } - var pairingNode = new PairingHeap(newValue); - if (setHeapNode !== null) { - setHeapNode(newValue, pairingNode); - } - return this.merge(pairingNode, lessThan); - }; - return PairingHeap; -}()); -exports.PairingHeap = PairingHeap; -var PriorityQueue = (function () { - function PriorityQueue(lessThan) { - this.lessThan = lessThan; - } - PriorityQueue.prototype.top = function () { - if (this.empty()) { - return null; - } - return this.root.elem; - }; - PriorityQueue.prototype.push = function () { - var args = []; - for (var _i = 0; _i < arguments.length; _i++) { - args[_i] = arguments[_i]; - } - var pairingNode; - for (var i = 0, arg; arg = args[i]; ++i) { - pairingNode = new PairingHeap(arg); - this.root = this.empty() ? - pairingNode : this.root.merge(pairingNode, this.lessThan); - } - return pairingNode; - }; - PriorityQueue.prototype.empty = function () { - return !this.root || !this.root.elem; - }; - PriorityQueue.prototype.isHeap = function () { - return this.root.isHeap(this.lessThan); - }; - PriorityQueue.prototype.forEach = function (f) { - this.root.forEach(f); - }; - PriorityQueue.prototype.pop = function () { - if (this.empty()) { - return null; - } - var obj = this.root.min(); - this.root = this.root.removeMin(this.lessThan); - return obj; - }; - PriorityQueue.prototype.reduceKey = function (heapNode, newKey, setHeapNode) { - if (setHeapNode === void 0) { setHeapNode = null; } - this.root = this.root.decreaseKey(heapNode, newKey, setHeapNode, this.lessThan); - }; - PriorityQueue.prototype.toString = function (selector) { - return this.root.toString(selector); - }; - PriorityQueue.prototype.count = function () { - return this.root.count(); - }; - return PriorityQueue; -}()); -exports.PriorityQueue = PriorityQueue; - -},{}],16:[function(require,module,exports){ -"use strict"; -var __extends = (this && this.__extends) || (function () { - var extendStatics = function (d, b) { - extendStatics = Object.setPrototypeOf || - ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || - function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; - return extendStatics(d, b); - }; - return function (d, b) { - extendStatics(d, b); - function __() { this.constructor = d; } - d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); - }; -})(); -Object.defineProperty(exports, "__esModule", { value: true }); -var TreeBase = (function () { - function TreeBase() { - this.findIter = function (data) { - var res = this._root; - var iter = this.iterator(); - while (res !== null) { - var c = this._comparator(data, res.data); - if (c === 0) { - iter._cursor = res; - return iter; - } - else { - iter._ancestors.push(res); - res = res.get_child(c > 0); - } - } - return null; - }; - } - TreeBase.prototype.clear = function () { - this._root = null; - this.size = 0; - }; - ; - TreeBase.prototype.find = function (data) { - var res = this._root; - while (res !== null) { - var c = this._comparator(data, res.data); - if (c === 0) { - return res.data; - } - else { - res = res.get_child(c > 0); - } - } - return null; - }; - ; - TreeBase.prototype.lowerBound = function (data) { - return this._bound(data, this._comparator); - }; - ; - TreeBase.prototype.upperBound = function (data) { - var cmp = this._comparator; - function reverse_cmp(a, b) { - return cmp(b, a); - } - return this._bound(data, reverse_cmp); - }; - ; - TreeBase.prototype.min = function () { - var res = this._root; - if (res === null) { - return null; - } - while (res.left !== null) { - res = res.left; - } - return res.data; - }; - ; - TreeBase.prototype.max = function () { - var res = this._root; - if (res === null) { - return null; - } - while (res.right !== null) { - res = res.right; - } - return res.data; - }; - ; - TreeBase.prototype.iterator = function () { - return new Iterator(this); - }; - ; - TreeBase.prototype.each = function (cb) { - var it = this.iterator(), data; - while ((data = it.next()) !== null) { - cb(data); - } - }; - ; - TreeBase.prototype.reach = function (cb) { - var it = this.iterator(), data; - while ((data = it.prev()) !== null) { - cb(data); - } - }; - ; - TreeBase.prototype._bound = function (data, cmp) { - var cur = this._root; - var iter = this.iterator(); - while (cur !== null) { - var c = this._comparator(data, cur.data); - if (c === 0) { - iter._cursor = cur; - return iter; - } - iter._ancestors.push(cur); - cur = cur.get_child(c > 0); - } - for (var i = iter._ancestors.length - 1; i >= 0; --i) { - cur = iter._ancestors[i]; - if (cmp(data, cur.data) > 0) { - iter._cursor = cur; - iter._ancestors.length = i; - return iter; - } - } - iter._ancestors.length = 0; - return iter; - }; - ; - return TreeBase; -}()); -exports.TreeBase = TreeBase; -var Iterator = (function () { - function Iterator(tree) { - this._tree = tree; - this._ancestors = []; - this._cursor = null; - } - Iterator.prototype.data = function () { - return this._cursor !== null ? this._cursor.data : null; - }; - ; - Iterator.prototype.next = function () { - if (this._cursor === null) { - var root = this._tree._root; - if (root !== null) { - this._minNode(root); - } - } - else { - if (this._cursor.right === null) { - var save; - do { - save = this._cursor; - if (this._ancestors.length) { - this._cursor = this._ancestors.pop(); - } - else { - this._cursor = null; - break; - } - } while (this._cursor.right === save); - } - else { - this._ancestors.push(this._cursor); - this._minNode(this._cursor.right); - } - } - return this._cursor !== null ? this._cursor.data : null; - }; - ; - Iterator.prototype.prev = function () { - if (this._cursor === null) { - var root = this._tree._root; - if (root !== null) { - this._maxNode(root); - } - } - else { - if (this._cursor.left === null) { - var save; - do { - save = this._cursor; - if (this._ancestors.length) { - this._cursor = this._ancestors.pop(); - } - else { - this._cursor = null; - break; - } - } while (this._cursor.left === save); - } - else { - this._ancestors.push(this._cursor); - this._maxNode(this._cursor.left); - } - } - return this._cursor !== null ? this._cursor.data : null; - }; - ; - Iterator.prototype._minNode = function (start) { - while (start.left !== null) { - this._ancestors.push(start); - start = start.left; - } - this._cursor = start; - }; - ; - Iterator.prototype._maxNode = function (start) { - while (start.right !== null) { - this._ancestors.push(start); - start = start.right; - } - this._cursor = start; - }; - ; - return Iterator; -}()); -exports.Iterator = Iterator; -var Node = (function () { - function Node(data) { - this.data = data; - this.left = null; - this.right = null; - this.red = true; - } - Node.prototype.get_child = function (dir) { - return dir ? this.right : this.left; - }; - ; - Node.prototype.set_child = function (dir, val) { - if (dir) { - this.right = val; - } - else { - this.left = val; - } - }; - ; - return Node; -}()); -var RBTree = (function (_super) { - __extends(RBTree, _super); - function RBTree(comparator) { - var _this = _super.call(this) || this; - _this._root = null; - _this._comparator = comparator; - _this.size = 0; - return _this; - } - RBTree.prototype.insert = function (data) { - var ret = false; - if (this._root === null) { - this._root = new Node(data); - ret = true; - this.size++; - } - else { - var head = new Node(undefined); - var dir = false; - var last = false; - var gp = null; - var ggp = head; - var p = null; - var node = this._root; - ggp.right = this._root; - while (true) { - if (node === null) { - node = new Node(data); - p.set_child(dir, node); - ret = true; - this.size++; - } - else if (RBTree.is_red(node.left) && RBTree.is_red(node.right)) { - node.red = true; - node.left.red = false; - node.right.red = false; - } - if (RBTree.is_red(node) && RBTree.is_red(p)) { - var dir2 = ggp.right === gp; - if (node === p.get_child(last)) { - ggp.set_child(dir2, RBTree.single_rotate(gp, !last)); - } - else { - ggp.set_child(dir2, RBTree.double_rotate(gp, !last)); - } - } - var cmp = this._comparator(node.data, data); - if (cmp === 0) { - break; - } - last = dir; - dir = cmp < 0; - if (gp !== null) { - ggp = gp; - } - gp = p; - p = node; - node = node.get_child(dir); - } - this._root = head.right; - } - this._root.red = false; - return ret; - }; - ; - RBTree.prototype.remove = function (data) { - if (this._root === null) { - return false; - } - var head = new Node(undefined); - var node = head; - node.right = this._root; - var p = null; - var gp = null; - var found = null; - var dir = true; - while (node.get_child(dir) !== null) { - var last = dir; - gp = p; - p = node; - node = node.get_child(dir); - var cmp = this._comparator(data, node.data); - dir = cmp > 0; - if (cmp === 0) { - found = node; - } - if (!RBTree.is_red(node) && !RBTree.is_red(node.get_child(dir))) { - if (RBTree.is_red(node.get_child(!dir))) { - var sr = RBTree.single_rotate(node, dir); - p.set_child(last, sr); - p = sr; - } - else if (!RBTree.is_red(node.get_child(!dir))) { - var sibling = p.get_child(!last); - if (sibling !== null) { - if (!RBTree.is_red(sibling.get_child(!last)) && !RBTree.is_red(sibling.get_child(last))) { - p.red = false; - sibling.red = true; - node.red = true; - } - else { - var dir2 = gp.right === p; - if (RBTree.is_red(sibling.get_child(last))) { - gp.set_child(dir2, RBTree.double_rotate(p, last)); - } - else if (RBTree.is_red(sibling.get_child(!last))) { - gp.set_child(dir2, RBTree.single_rotate(p, last)); - } - var gpc = gp.get_child(dir2); - gpc.red = true; - node.red = true; - gpc.left.red = false; - gpc.right.red = false; - } - } - } - } - } - if (found !== null) { - found.data = node.data; - p.set_child(p.right === node, node.get_child(node.left === null)); - this.size--; - } - this._root = head.right; - if (this._root !== null) { - this._root.red = false; - } - return found !== null; - }; - ; - RBTree.is_red = function (node) { - return node !== null && node.red; - }; - RBTree.single_rotate = function (root, dir) { - var save = root.get_child(!dir); - root.set_child(!dir, save.get_child(dir)); - save.set_child(dir, root); - root.red = true; - save.red = false; - return save; - }; - RBTree.double_rotate = function (root, dir) { - root.set_child(!dir, RBTree.single_rotate(root.get_child(!dir), !dir)); - return RBTree.single_rotate(root, dir); - }; - return RBTree; -}(TreeBase)); -exports.RBTree = RBTree; - -},{}],17:[function(require,module,exports){ -"use strict"; -var __extends = (this && this.__extends) || (function () { - var extendStatics = function (d, b) { - extendStatics = Object.setPrototypeOf || - ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || - function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; - return extendStatics(d, b); - }; - return function (d, b) { - extendStatics(d, b); - function __() { this.constructor = d; } - d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); - }; -})(); -Object.defineProperty(exports, "__esModule", { value: true }); -var vpsc_1 = require("./vpsc"); -var rbtree_1 = require("./rbtree"); -function computeGroupBounds(g) { - g.bounds = typeof g.leaves !== "undefined" ? - g.leaves.reduce(function (r, c) { return c.bounds.union(r); }, Rectangle.empty()) : - Rectangle.empty(); - if (typeof g.groups !== "undefined") - g.bounds = g.groups.reduce(function (r, c) { return computeGroupBounds(c).union(r); }, g.bounds); - g.bounds = g.bounds.inflate(g.padding); - return g.bounds; -} -exports.computeGroupBounds = computeGroupBounds; -var Rectangle = (function () { - function Rectangle(x, X, y, Y) { - this.x = x; - this.X = X; - this.y = y; - this.Y = Y; - } - Rectangle.empty = function () { return new Rectangle(Number.POSITIVE_INFINITY, Number.NEGATIVE_INFINITY, Number.POSITIVE_INFINITY, Number.NEGATIVE_INFINITY); }; - Rectangle.prototype.cx = function () { return (this.x + this.X) / 2; }; - Rectangle.prototype.cy = function () { return (this.y + this.Y) / 2; }; - Rectangle.prototype.overlapX = function (r) { - var ux = this.cx(), vx = r.cx(); - if (ux <= vx && r.x < this.X) - return this.X - r.x; - if (vx <= ux && this.x < r.X) - return r.X - this.x; - return 0; - }; - Rectangle.prototype.overlapY = function (r) { - var uy = this.cy(), vy = r.cy(); - if (uy <= vy && r.y < this.Y) - return this.Y - r.y; - if (vy <= uy && this.y < r.Y) - return r.Y - this.y; - return 0; - }; - Rectangle.prototype.setXCentre = function (cx) { - var dx = cx - this.cx(); - this.x += dx; - this.X += dx; - }; - Rectangle.prototype.setYCentre = function (cy) { - var dy = cy - this.cy(); - this.y += dy; - this.Y += dy; - }; - Rectangle.prototype.width = function () { - return this.X - this.x; - }; - Rectangle.prototype.height = function () { - return this.Y - this.y; - }; - Rectangle.prototype.union = function (r) { - return new Rectangle(Math.min(this.x, r.x), Math.max(this.X, r.X), Math.min(this.y, r.y), Math.max(this.Y, r.Y)); - }; - Rectangle.prototype.lineIntersections = function (x1, y1, x2, y2) { - var sides = [[this.x, this.y, this.X, this.y], - [this.X, this.y, this.X, this.Y], - [this.X, this.Y, this.x, this.Y], - [this.x, this.Y, this.x, this.y]]; - var intersections = []; - for (var i = 0; i < 4; ++i) { - var r = Rectangle.lineIntersection(x1, y1, x2, y2, sides[i][0], sides[i][1], sides[i][2], sides[i][3]); - if (r !== null) - intersections.push({ x: r.x, y: r.y }); - } - return intersections; - }; - Rectangle.prototype.rayIntersection = function (x2, y2) { - var ints = this.lineIntersections(this.cx(), this.cy(), x2, y2); - return ints.length > 0 ? ints[0] : null; - }; - Rectangle.prototype.vertices = function () { - return [ - { x: this.x, y: this.y }, - { x: this.X, y: this.y }, - { x: this.X, y: this.Y }, - { x: this.x, y: this.Y } - ]; - }; - Rectangle.lineIntersection = function (x1, y1, x2, y2, x3, y3, x4, y4) { - var dx12 = x2 - x1, dx34 = x4 - x3, dy12 = y2 - y1, dy34 = y4 - y3, denominator = dy34 * dx12 - dx34 * dy12; - if (denominator == 0) - return null; - var dx31 = x1 - x3, dy31 = y1 - y3, numa = dx34 * dy31 - dy34 * dx31, a = numa / denominator, numb = dx12 * dy31 - dy12 * dx31, b = numb / denominator; - if (a >= 0 && a <= 1 && b >= 0 && b <= 1) { - return { - x: x1 + a * dx12, - y: y1 + a * dy12 - }; - } - return null; - }; - Rectangle.prototype.inflate = function (pad) { - return new Rectangle(this.x - pad, this.X + pad, this.y - pad, this.Y + pad); - }; - return Rectangle; -}()); -exports.Rectangle = Rectangle; -function makeEdgeBetween(source, target, ah) { - var si = source.rayIntersection(target.cx(), target.cy()) || { x: source.cx(), y: source.cy() }, ti = target.rayIntersection(source.cx(), source.cy()) || { x: target.cx(), y: target.cy() }, dx = ti.x - si.x, dy = ti.y - si.y, l = Math.sqrt(dx * dx + dy * dy), al = l - ah; - return { - sourceIntersection: si, - targetIntersection: ti, - arrowStart: { x: si.x + al * dx / l, y: si.y + al * dy / l } - }; -} -exports.makeEdgeBetween = makeEdgeBetween; -function makeEdgeTo(s, target, ah) { - var ti = target.rayIntersection(s.x, s.y); - if (!ti) - ti = { x: target.cx(), y: target.cy() }; - var dx = ti.x - s.x, dy = ti.y - s.y, l = Math.sqrt(dx * dx + dy * dy); - return { x: ti.x - ah * dx / l, y: ti.y - ah * dy / l }; -} -exports.makeEdgeTo = makeEdgeTo; -var Node = (function () { - function Node(v, r, pos) { - this.v = v; - this.r = r; - this.pos = pos; - this.prev = makeRBTree(); - this.next = makeRBTree(); - } - return Node; -}()); -var Event = (function () { - function Event(isOpen, v, pos) { - this.isOpen = isOpen; - this.v = v; - this.pos = pos; - } - return Event; -}()); -function compareEvents(a, b) { - if (a.pos > b.pos) { - return 1; - } - if (a.pos < b.pos) { - return -1; - } - if (a.isOpen) { - return -1; - } - if (b.isOpen) { - return 1; - } - return 0; -} -function makeRBTree() { - return new rbtree_1.RBTree(function (a, b) { return a.pos - b.pos; }); -} -var xRect = { - getCentre: function (r) { return r.cx(); }, - getOpen: function (r) { return r.y; }, - getClose: function (r) { return r.Y; }, - getSize: function (r) { return r.width(); }, - makeRect: function (open, close, center, size) { return new Rectangle(center - size / 2, center + size / 2, open, close); }, - findNeighbours: findXNeighbours -}; -var yRect = { - getCentre: function (r) { return r.cy(); }, - getOpen: function (r) { return r.x; }, - getClose: function (r) { return r.X; }, - getSize: function (r) { return r.height(); }, - makeRect: function (open, close, center, size) { return new Rectangle(open, close, center - size / 2, center + size / 2); }, - findNeighbours: findYNeighbours -}; -function generateGroupConstraints(root, f, minSep, isContained) { - if (isContained === void 0) { isContained = false; } - var padding = root.padding, gn = typeof root.groups !== 'undefined' ? root.groups.length : 0, ln = typeof root.leaves !== 'undefined' ? root.leaves.length : 0, childConstraints = !gn ? [] - : root.groups.reduce(function (ccs, g) { return ccs.concat(generateGroupConstraints(g, f, minSep, true)); }, []), n = (isContained ? 2 : 0) + ln + gn, vs = new Array(n), rs = new Array(n), i = 0, add = function (r, v) { rs[i] = r; vs[i++] = v; }; - if (isContained) { - var b = root.bounds, c = f.getCentre(b), s = f.getSize(b) / 2, open = f.getOpen(b), close = f.getClose(b), min = c - s + padding / 2, max = c + s - padding / 2; - root.minVar.desiredPosition = min; - add(f.makeRect(open, close, min, padding), root.minVar); - root.maxVar.desiredPosition = max; - add(f.makeRect(open, close, max, padding), root.maxVar); - } - if (ln) - root.leaves.forEach(function (l) { return add(l.bounds, l.variable); }); - if (gn) - root.groups.forEach(function (g) { - var b = g.bounds; - add(f.makeRect(f.getOpen(b), f.getClose(b), f.getCentre(b), f.getSize(b)), g.minVar); - }); - var cs = generateConstraints(rs, vs, f, minSep); - if (gn) { - vs.forEach(function (v) { v.cOut = [], v.cIn = []; }); - cs.forEach(function (c) { c.left.cOut.push(c), c.right.cIn.push(c); }); - root.groups.forEach(function (g) { - var gapAdjustment = (g.padding - f.getSize(g.bounds)) / 2; - g.minVar.cIn.forEach(function (c) { return c.gap += gapAdjustment; }); - g.minVar.cOut.forEach(function (c) { c.left = g.maxVar; c.gap += gapAdjustment; }); - }); - } - return childConstraints.concat(cs); -} -function generateConstraints(rs, vars, rect, minSep) { - var i, n = rs.length; - var N = 2 * n; - console.assert(vars.length >= n); - var events = new Array(N); - for (i = 0; i < n; ++i) { - var r = rs[i]; - var v = new Node(vars[i], r, rect.getCentre(r)); - events[i] = new Event(true, v, rect.getOpen(r)); - events[i + n] = new Event(false, v, rect.getClose(r)); - } - events.sort(compareEvents); - var cs = new Array(); - var scanline = makeRBTree(); - for (i = 0; i < N; ++i) { - var e = events[i]; - var v = e.v; - if (e.isOpen) { - scanline.insert(v); - rect.findNeighbours(v, scanline); - } - else { - scanline.remove(v); - var makeConstraint = function (l, r) { - var sep = (rect.getSize(l.r) + rect.getSize(r.r)) / 2 + minSep; - cs.push(new vpsc_1.Constraint(l.v, r.v, sep)); - }; - var visitNeighbours = function (forward, reverse, mkcon) { - var u, it = v[forward].iterator(); - while ((u = it[forward]()) !== null) { - mkcon(u, v); - u[reverse].remove(v); - } - }; - visitNeighbours("prev", "next", function (u, v) { return makeConstraint(u, v); }); - visitNeighbours("next", "prev", function (u, v) { return makeConstraint(v, u); }); - } - } - console.assert(scanline.size === 0); - return cs; -} -function findXNeighbours(v, scanline) { - var f = function (forward, reverse) { - var it = scanline.findIter(v); - var u; - while ((u = it[forward]()) !== null) { - var uovervX = u.r.overlapX(v.r); - if (uovervX <= 0 || uovervX <= u.r.overlapY(v.r)) { - v[forward].insert(u); - u[reverse].insert(v); - } - if (uovervX <= 0) { - break; - } - } - }; - f("next", "prev"); - f("prev", "next"); -} -function findYNeighbours(v, scanline) { - var f = function (forward, reverse) { - var u = scanline.findIter(v)[forward](); - if (u !== null && u.r.overlapX(v.r) > 0) { - v[forward].insert(u); - u[reverse].insert(v); - } - }; - f("next", "prev"); - f("prev", "next"); -} -function generateXConstraints(rs, vars) { - return generateConstraints(rs, vars, xRect, 1e-6); -} -exports.generateXConstraints = generateXConstraints; -function generateYConstraints(rs, vars) { - return generateConstraints(rs, vars, yRect, 1e-6); -} -exports.generateYConstraints = generateYConstraints; -function generateXGroupConstraints(root) { - return generateGroupConstraints(root, xRect, 1e-6); -} -exports.generateXGroupConstraints = generateXGroupConstraints; -function generateYGroupConstraints(root) { - return generateGroupConstraints(root, yRect, 1e-6); -} -exports.generateYGroupConstraints = generateYGroupConstraints; -function removeOverlaps(rs) { - var vs = rs.map(function (r) { return new vpsc_1.Variable(r.cx()); }); - var cs = generateXConstraints(rs, vs); - var solver = new vpsc_1.Solver(vs, cs); - solver.solve(); - vs.forEach(function (v, i) { return rs[i].setXCentre(v.position()); }); - vs = rs.map(function (r) { return new vpsc_1.Variable(r.cy()); }); - cs = generateYConstraints(rs, vs); - solver = new vpsc_1.Solver(vs, cs); - solver.solve(); - vs.forEach(function (v, i) { return rs[i].setYCentre(v.position()); }); -} -exports.removeOverlaps = removeOverlaps; -var IndexedVariable = (function (_super) { - __extends(IndexedVariable, _super); - function IndexedVariable(index, w) { - var _this = _super.call(this, 0, w) || this; - _this.index = index; - return _this; - } - return IndexedVariable; -}(vpsc_1.Variable)); -exports.IndexedVariable = IndexedVariable; -var Projection = (function () { - function Projection(nodes, groups, rootGroup, constraints, avoidOverlaps) { - var _this = this; - if (rootGroup === void 0) { rootGroup = null; } - if (constraints === void 0) { constraints = null; } - if (avoidOverlaps === void 0) { avoidOverlaps = false; } - this.nodes = nodes; - this.groups = groups; - this.rootGroup = rootGroup; - this.avoidOverlaps = avoidOverlaps; - this.variables = nodes.map(function (v, i) { - return v.variable = new IndexedVariable(i, 1); - }); - if (constraints) - this.createConstraints(constraints); - if (avoidOverlaps && rootGroup && typeof rootGroup.groups !== 'undefined') { - nodes.forEach(function (v) { - if (!v.width || !v.height) { - v.bounds = new Rectangle(v.x, v.x, v.y, v.y); - return; - } - var w2 = v.width / 2, h2 = v.height / 2; - v.bounds = new Rectangle(v.x - w2, v.x + w2, v.y - h2, v.y + h2); - }); - computeGroupBounds(rootGroup); - var i = nodes.length; - groups.forEach(function (g) { - _this.variables[i] = g.minVar = new IndexedVariable(i++, typeof g.stiffness !== "undefined" ? g.stiffness : 0.01); - _this.variables[i] = g.maxVar = new IndexedVariable(i++, typeof g.stiffness !== "undefined" ? g.stiffness : 0.01); - }); - } - } - Projection.prototype.createSeparation = function (c) { - return new vpsc_1.Constraint(this.nodes[c.left].variable, this.nodes[c.right].variable, c.gap, typeof c.equality !== "undefined" ? c.equality : false); - }; - Projection.prototype.makeFeasible = function (c) { - var _this = this; - if (!this.avoidOverlaps) - return; - var axis = 'x', dim = 'width'; - if (c.axis === 'x') - axis = 'y', dim = 'height'; - var vs = c.offsets.map(function (o) { return _this.nodes[o.node]; }).sort(function (a, b) { return a[axis] - b[axis]; }); - var p = null; - vs.forEach(function (v) { - if (p) { - var nextPos = p[axis] + p[dim]; - if (nextPos > v[axis]) { - v[axis] = nextPos; - } - } - p = v; - }); - }; - Projection.prototype.createAlignment = function (c) { - var _this = this; - var u = this.nodes[c.offsets[0].node].variable; - this.makeFeasible(c); - var cs = c.axis === 'x' ? this.xConstraints : this.yConstraints; - c.offsets.slice(1).forEach(function (o) { - var v = _this.nodes[o.node].variable; - cs.push(new vpsc_1.Constraint(u, v, o.offset, true)); - }); - }; - Projection.prototype.createConstraints = function (constraints) { - var _this = this; - var isSep = function (c) { return typeof c.type === 'undefined' || c.type === 'separation'; }; - this.xConstraints = constraints - .filter(function (c) { return c.axis === "x" && isSep(c); }) - .map(function (c) { return _this.createSeparation(c); }); - this.yConstraints = constraints - .filter(function (c) { return c.axis === "y" && isSep(c); }) - .map(function (c) { return _this.createSeparation(c); }); - constraints - .filter(function (c) { return c.type === 'alignment'; }) - .forEach(function (c) { return _this.createAlignment(c); }); - }; - Projection.prototype.setupVariablesAndBounds = function (x0, y0, desired, getDesired) { - this.nodes.forEach(function (v, i) { - if (v.fixed) { - v.variable.weight = v.fixedWeight ? v.fixedWeight : 1000; - desired[i] = getDesired(v); - } - else { - v.variable.weight = 1; - } - var w = (v.width || 0) / 2, h = (v.height || 0) / 2; - var ix = x0[i], iy = y0[i]; - v.bounds = new Rectangle(ix - w, ix + w, iy - h, iy + h); - }); - }; - Projection.prototype.xProject = function (x0, y0, x) { - if (!this.rootGroup && !(this.avoidOverlaps || this.xConstraints)) - return; - this.project(x0, y0, x0, x, function (v) { return v.px; }, this.xConstraints, generateXGroupConstraints, function (v) { return v.bounds.setXCentre(x[v.variable.index] = v.variable.position()); }, function (g) { - var xmin = x[g.minVar.index] = g.minVar.position(); - var xmax = x[g.maxVar.index] = g.maxVar.position(); - var p2 = g.padding / 2; - g.bounds.x = xmin - p2; - g.bounds.X = xmax + p2; - }); - }; - Projection.prototype.yProject = function (x0, y0, y) { - if (!this.rootGroup && !this.yConstraints) - return; - this.project(x0, y0, y0, y, function (v) { return v.py; }, this.yConstraints, generateYGroupConstraints, function (v) { return v.bounds.setYCentre(y[v.variable.index] = v.variable.position()); }, function (g) { - var ymin = y[g.minVar.index] = g.minVar.position(); - var ymax = y[g.maxVar.index] = g.maxVar.position(); - var p2 = g.padding / 2; - g.bounds.y = ymin - p2; - ; - g.bounds.Y = ymax + p2; - }); - }; - Projection.prototype.projectFunctions = function () { - var _this = this; - return [ - function (x0, y0, x) { return _this.xProject(x0, y0, x); }, - function (x0, y0, y) { return _this.yProject(x0, y0, y); } - ]; - }; - Projection.prototype.project = function (x0, y0, start, desired, getDesired, cs, generateConstraints, updateNodeBounds, updateGroupBounds) { - this.setupVariablesAndBounds(x0, y0, desired, getDesired); - if (this.rootGroup && this.avoidOverlaps) { - computeGroupBounds(this.rootGroup); - cs = cs.concat(generateConstraints(this.rootGroup)); - } - this.solve(this.variables, cs, start, desired); - this.nodes.forEach(updateNodeBounds); - if (this.rootGroup && this.avoidOverlaps) { - this.groups.forEach(updateGroupBounds); - computeGroupBounds(this.rootGroup); - } - }; - Projection.prototype.solve = function (vs, cs, starting, desired) { - var solver = new vpsc_1.Solver(vs, cs); - solver.setStartingPositions(starting); - solver.setDesiredPositions(desired); - solver.solve(); - }; - return Projection; -}()); -exports.Projection = Projection; - -},{"./rbtree":16,"./vpsc":19}],18:[function(require,module,exports){ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -var pqueue_1 = require("./pqueue"); -var Neighbour = (function () { - function Neighbour(id, distance) { - this.id = id; - this.distance = distance; - } - return Neighbour; -}()); -var Node = (function () { - function Node(id) { - this.id = id; - this.neighbours = []; - } - return Node; -}()); -var QueueEntry = (function () { - function QueueEntry(node, prev, d) { - this.node = node; - this.prev = prev; - this.d = d; - } - return QueueEntry; -}()); -var Calculator = (function () { - function Calculator(n, es, getSourceIndex, getTargetIndex, getLength) { - this.n = n; - this.es = es; - this.neighbours = new Array(this.n); - var i = this.n; - while (i--) - this.neighbours[i] = new Node(i); - i = this.es.length; - while (i--) { - var e = this.es[i]; - var u = getSourceIndex(e), v = getTargetIndex(e); - var d = getLength(e); - this.neighbours[u].neighbours.push(new Neighbour(v, d)); - this.neighbours[v].neighbours.push(new Neighbour(u, d)); - } - } - Calculator.prototype.DistanceMatrix = function () { - var D = new Array(this.n); - for (var i = 0; i < this.n; ++i) { - D[i] = this.dijkstraNeighbours(i); - } - return D; - }; - Calculator.prototype.DistancesFromNode = function (start) { - return this.dijkstraNeighbours(start); - }; - Calculator.prototype.PathFromNodeToNode = function (start, end) { - return this.dijkstraNeighbours(start, end); - }; - Calculator.prototype.PathFromNodeToNodeWithPrevCost = function (start, end, prevCost) { - var q = new pqueue_1.PriorityQueue(function (a, b) { return a.d <= b.d; }), u = this.neighbours[start], qu = new QueueEntry(u, null, 0), visitedFrom = {}; - q.push(qu); - while (!q.empty()) { - qu = q.pop(); - u = qu.node; - if (u.id === end) { - break; - } - var i = u.neighbours.length; - while (i--) { - var neighbour = u.neighbours[i], v = this.neighbours[neighbour.id]; - if (qu.prev && v.id === qu.prev.node.id) - continue; - var viduid = v.id + ',' + u.id; - if (viduid in visitedFrom && visitedFrom[viduid] <= qu.d) - continue; - var cc = qu.prev ? prevCost(qu.prev.node.id, u.id, v.id) : 0, t = qu.d + neighbour.distance + cc; - visitedFrom[viduid] = t; - q.push(new QueueEntry(v, qu, t)); - } - } - var path = []; - while (qu.prev) { - qu = qu.prev; - path.push(qu.node.id); - } - return path; - }; - Calculator.prototype.dijkstraNeighbours = function (start, dest) { - if (dest === void 0) { dest = -1; } - var q = new pqueue_1.PriorityQueue(function (a, b) { return a.d <= b.d; }), i = this.neighbours.length, d = new Array(i); - while (i--) { - var node = this.neighbours[i]; - node.d = i === start ? 0 : Number.POSITIVE_INFINITY; - node.q = q.push(node); - } - while (!q.empty()) { - var u = q.pop(); - d[u.id] = u.d; - if (u.id === dest) { - var path = []; - var v = u; - while (typeof v.prev !== 'undefined') { - path.push(v.prev.id); - v = v.prev; - } - return path; - } - i = u.neighbours.length; - while (i--) { - var neighbour = u.neighbours[i]; - var v = this.neighbours[neighbour.id]; - var t = u.d + neighbour.distance; - if (u.d !== Number.MAX_VALUE && v.d > t) { - v.d = t; - v.prev = u; - q.reduceKey(v.q, v, function (e, q) { return e.q = q; }); - } - } - } - return d; - }; - return Calculator; -}()); -exports.Calculator = Calculator; - -},{"./pqueue":15}],19:[function(require,module,exports){ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -var PositionStats = (function () { - function PositionStats(scale) { - this.scale = scale; - this.AB = 0; - this.AD = 0; - this.A2 = 0; - } - PositionStats.prototype.addVariable = function (v) { - var ai = this.scale / v.scale; - var bi = v.offset / v.scale; - var wi = v.weight; - this.AB += wi * ai * bi; - this.AD += wi * ai * v.desiredPosition; - this.A2 += wi * ai * ai; - }; - PositionStats.prototype.getPosn = function () { - return (this.AD - this.AB) / this.A2; - }; - return PositionStats; -}()); -exports.PositionStats = PositionStats; -var Constraint = (function () { - function Constraint(left, right, gap, equality) { - if (equality === void 0) { equality = false; } - this.left = left; - this.right = right; - this.gap = gap; - this.equality = equality; - this.active = false; - this.unsatisfiable = false; - this.left = left; - this.right = right; - this.gap = gap; - this.equality = equality; - } - Constraint.prototype.slack = function () { - return this.unsatisfiable ? Number.MAX_VALUE - : this.right.scale * this.right.position() - this.gap - - this.left.scale * this.left.position(); - }; - return Constraint; -}()); -exports.Constraint = Constraint; -var Variable = (function () { - function Variable(desiredPosition, weight, scale) { - if (weight === void 0) { weight = 1; } - if (scale === void 0) { scale = 1; } - this.desiredPosition = desiredPosition; - this.weight = weight; - this.scale = scale; - this.offset = 0; - } - Variable.prototype.dfdv = function () { - return 2.0 * this.weight * (this.position() - this.desiredPosition); - }; - Variable.prototype.position = function () { - return (this.block.ps.scale * this.block.posn + this.offset) / this.scale; - }; - Variable.prototype.visitNeighbours = function (prev, f) { - var ff = function (c, next) { return c.active && prev !== next && f(c, next); }; - this.cOut.forEach(function (c) { return ff(c, c.right); }); - this.cIn.forEach(function (c) { return ff(c, c.left); }); - }; - return Variable; -}()); -exports.Variable = Variable; -var Block = (function () { - function Block(v) { - this.vars = []; - v.offset = 0; - this.ps = new PositionStats(v.scale); - this.addVariable(v); - } - Block.prototype.addVariable = function (v) { - v.block = this; - this.vars.push(v); - this.ps.addVariable(v); - this.posn = this.ps.getPosn(); - }; - Block.prototype.updateWeightedPosition = function () { - this.ps.AB = this.ps.AD = this.ps.A2 = 0; - for (var i = 0, n = this.vars.length; i < n; ++i) - this.ps.addVariable(this.vars[i]); - this.posn = this.ps.getPosn(); - }; - Block.prototype.compute_lm = function (v, u, postAction) { - var _this = this; - var dfdv = v.dfdv(); - v.visitNeighbours(u, function (c, next) { - var _dfdv = _this.compute_lm(next, v, postAction); - if (next === c.right) { - dfdv += _dfdv * c.left.scale; - c.lm = _dfdv; - } - else { - dfdv += _dfdv * c.right.scale; - c.lm = -_dfdv; - } - postAction(c); - }); - return dfdv / v.scale; - }; - Block.prototype.populateSplitBlock = function (v, prev) { - var _this = this; - v.visitNeighbours(prev, function (c, next) { - next.offset = v.offset + (next === c.right ? c.gap : -c.gap); - _this.addVariable(next); - _this.populateSplitBlock(next, v); - }); - }; - Block.prototype.traverse = function (visit, acc, v, prev) { - var _this = this; - if (v === void 0) { v = this.vars[0]; } - if (prev === void 0) { prev = null; } - v.visitNeighbours(prev, function (c, next) { - acc.push(visit(c)); - _this.traverse(visit, acc, next, v); - }); - }; - Block.prototype.findMinLM = function () { - var m = null; - this.compute_lm(this.vars[0], null, function (c) { - if (!c.equality && (m === null || c.lm < m.lm)) - m = c; - }); - return m; - }; - Block.prototype.findMinLMBetween = function (lv, rv) { - this.compute_lm(lv, null, function () { }); - var m = null; - this.findPath(lv, null, rv, function (c, next) { - if (!c.equality && c.right === next && (m === null || c.lm < m.lm)) - m = c; - }); - return m; - }; - Block.prototype.findPath = function (v, prev, to, visit) { - var _this = this; - var endFound = false; - v.visitNeighbours(prev, function (c, next) { - if (!endFound && (next === to || _this.findPath(next, v, to, visit))) { - endFound = true; - visit(c, next); - } - }); - return endFound; - }; - Block.prototype.isActiveDirectedPathBetween = function (u, v) { - if (u === v) - return true; - var i = u.cOut.length; - while (i--) { - var c = u.cOut[i]; - if (c.active && this.isActiveDirectedPathBetween(c.right, v)) - return true; - } - return false; - }; - Block.split = function (c) { - c.active = false; - return [Block.createSplitBlock(c.left), Block.createSplitBlock(c.right)]; - }; - Block.createSplitBlock = function (startVar) { - var b = new Block(startVar); - b.populateSplitBlock(startVar, null); - return b; - }; - Block.prototype.splitBetween = function (vl, vr) { - var c = this.findMinLMBetween(vl, vr); - if (c !== null) { - var bs = Block.split(c); - return { constraint: c, lb: bs[0], rb: bs[1] }; - } - return null; - }; - Block.prototype.mergeAcross = function (b, c, dist) { - c.active = true; - for (var i = 0, n = b.vars.length; i < n; ++i) { - var v = b.vars[i]; - v.offset += dist; - this.addVariable(v); - } - this.posn = this.ps.getPosn(); - }; - Block.prototype.cost = function () { - var sum = 0, i = this.vars.length; - while (i--) { - var v = this.vars[i], d = v.position() - v.desiredPosition; - sum += d * d * v.weight; - } - return sum; - }; - return Block; -}()); -exports.Block = Block; -var Blocks = (function () { - function Blocks(vs) { - this.vs = vs; - var n = vs.length; - this.list = new Array(n); - while (n--) { - var b = new Block(vs[n]); - this.list[n] = b; - b.blockInd = n; - } - } - Blocks.prototype.cost = function () { - var sum = 0, i = this.list.length; - while (i--) - sum += this.list[i].cost(); - return sum; - }; - Blocks.prototype.insert = function (b) { - b.blockInd = this.list.length; - this.list.push(b); - }; - Blocks.prototype.remove = function (b) { - var last = this.list.length - 1; - var swapBlock = this.list[last]; - this.list.length = last; - if (b !== swapBlock) { - this.list[b.blockInd] = swapBlock; - swapBlock.blockInd = b.blockInd; - } - }; - Blocks.prototype.merge = function (c) { - var l = c.left.block, r = c.right.block; - var dist = c.right.offset - c.left.offset - c.gap; - if (l.vars.length < r.vars.length) { - r.mergeAcross(l, c, dist); - this.remove(l); - } - else { - l.mergeAcross(r, c, -dist); - this.remove(r); - } - }; - Blocks.prototype.forEach = function (f) { - this.list.forEach(f); - }; - Blocks.prototype.updateBlockPositions = function () { - this.list.forEach(function (b) { return b.updateWeightedPosition(); }); - }; - Blocks.prototype.split = function (inactive) { - var _this = this; - this.updateBlockPositions(); - this.list.forEach(function (b) { - var v = b.findMinLM(); - if (v !== null && v.lm < Solver.LAGRANGIAN_TOLERANCE) { - b = v.left.block; - Block.split(v).forEach(function (nb) { return _this.insert(nb); }); - _this.remove(b); - inactive.push(v); - } - }); - }; - return Blocks; -}()); -exports.Blocks = Blocks; -var Solver = (function () { - function Solver(vs, cs) { - this.vs = vs; - this.cs = cs; - this.vs = vs; - vs.forEach(function (v) { - v.cIn = [], v.cOut = []; - }); - this.cs = cs; - cs.forEach(function (c) { - c.left.cOut.push(c); - c.right.cIn.push(c); - }); - this.inactive = cs.map(function (c) { c.active = false; return c; }); - this.bs = null; - } - Solver.prototype.cost = function () { - return this.bs.cost(); - }; - Solver.prototype.setStartingPositions = function (ps) { - this.inactive = this.cs.map(function (c) { c.active = false; return c; }); - this.bs = new Blocks(this.vs); - this.bs.forEach(function (b, i) { return b.posn = ps[i]; }); - }; - Solver.prototype.setDesiredPositions = function (ps) { - this.vs.forEach(function (v, i) { return v.desiredPosition = ps[i]; }); - }; - Solver.prototype.mostViolated = function () { - var minSlack = Number.MAX_VALUE, v = null, l = this.inactive, n = l.length, deletePoint = n; - for (var i = 0; i < n; ++i) { - var c = l[i]; - if (c.unsatisfiable) - continue; - var slack = c.slack(); - if (c.equality || slack < minSlack) { - minSlack = slack; - v = c; - deletePoint = i; - if (c.equality) - break; - } - } - if (deletePoint !== n && - (minSlack < Solver.ZERO_UPPERBOUND && !v.active || v.equality)) { - l[deletePoint] = l[n - 1]; - l.length = n - 1; - } - return v; - }; - Solver.prototype.satisfy = function () { - if (this.bs == null) { - this.bs = new Blocks(this.vs); - } - this.bs.split(this.inactive); - var v = null; - while ((v = this.mostViolated()) && (v.equality || v.slack() < Solver.ZERO_UPPERBOUND && !v.active)) { - var lb = v.left.block, rb = v.right.block; - if (lb !== rb) { - this.bs.merge(v); - } - else { - if (lb.isActiveDirectedPathBetween(v.right, v.left)) { - v.unsatisfiable = true; - continue; - } - var split = lb.splitBetween(v.left, v.right); - if (split !== null) { - this.bs.insert(split.lb); - this.bs.insert(split.rb); - this.bs.remove(lb); - this.inactive.push(split.constraint); - } - else { - v.unsatisfiable = true; - continue; - } - if (v.slack() >= 0) { - this.inactive.push(v); - } - else { - this.bs.merge(v); - } - } - } - }; - Solver.prototype.solve = function () { - this.satisfy(); - var lastcost = Number.MAX_VALUE, cost = this.bs.cost(); - while (Math.abs(lastcost - cost) > 0.0001) { - this.satisfy(); - lastcost = cost; - cost = this.bs.cost(); - } - return cost; - }; - Solver.LAGRANGIAN_TOLERANCE = -1e-4; - Solver.ZERO_UPPERBOUND = -1e-10; - return Solver; -}()); -exports.Solver = Solver; -function removeOverlapInOneDimension(spans, lowerBound, upperBound) { - var vs = spans.map(function (s) { return new Variable(s.desiredCenter); }); - var cs = []; - var n = spans.length; - for (var i = 0; i < n - 1; i++) { - var left = spans[i], right = spans[i + 1]; - cs.push(new Constraint(vs[i], vs[i + 1], (left.size + right.size) / 2)); - } - var leftMost = vs[0], rightMost = vs[n - 1], leftMostSize = spans[0].size / 2, rightMostSize = spans[n - 1].size / 2; - var vLower = null, vUpper = null; - if (lowerBound) { - vLower = new Variable(lowerBound, leftMost.weight * 1000); - vs.push(vLower); - cs.push(new Constraint(vLower, leftMost, leftMostSize)); - } - if (upperBound) { - vUpper = new Variable(upperBound, rightMost.weight * 1000); - vs.push(vUpper); - cs.push(new Constraint(rightMost, vUpper, rightMostSize)); - } - var solver = new Solver(vs, cs); - solver.solve(); - return { - newCenters: vs.slice(0, spans.length).map(function (v) { return v.position(); }), - lowerBound: vLower ? vLower.position() : leftMost.position() - leftMostSize, - upperBound: vUpper ? vUpper.position() : rightMost.position() + rightMostSize - }; -} -exports.removeOverlapInOneDimension = removeOverlapInOneDimension; - -},{}]},{},[1])(1) -}); - -//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIm5vZGVfbW9kdWxlcy9icm93c2VyLXBhY2svX3ByZWx1ZGUuanMiLCJkaXN0L2luZGV4LmpzIiwiZGlzdC9zcmMvYWRhcHRvci5qcyIsImRpc3Qvc3JjL2JhdGNoLmpzIiwiZGlzdC9zcmMvZDNhZGFwdG9yLmpzIiwiZGlzdC9zcmMvZDN2M2FkYXB0b3IuanMiLCJkaXN0L3NyYy9kM3Y0YWRhcHRvci5qcyIsImRpc3Qvc3JjL2Rlc2NlbnQuanMiLCJkaXN0L3NyYy9nZW9tLmpzIiwiZGlzdC9zcmMvZ3JpZHJvdXRlci5qcyIsImRpc3Qvc3JjL2hhbmRsZWRpc2Nvbm5lY3RlZC5qcyIsImRpc3Qvc3JjL2xheW91dC5qcyIsImRpc3Qvc3JjL2xheW91dDNkLmpzIiwiZGlzdC9zcmMvbGlua2xlbmd0aHMuanMiLCJkaXN0L3NyYy9wb3dlcmdyYXBoLmpzIiwiZGlzdC9zcmMvcHF1ZXVlLmpzIiwiZGlzdC9zcmMvcmJ0cmVlLmpzIiwiZGlzdC9zcmMvcmVjdGFuZ2xlLmpzIiwiZGlzdC9zcmMvc2hvcnRlc3RwYXRocy5qcyIsImRpc3Qvc3JjL3Zwc2MuanMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7QUNBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNyQkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3JEQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3hGQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2hCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDakVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDN0RBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3RWQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN2YUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDcmlCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzFNQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzVpQkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDbEhBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN2SEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUM1VEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNoS0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3JZQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDbmRBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDekhBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBIiwiZmlsZSI6ImdlbmVyYXRlZC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzQ29udGVudCI6WyIoZnVuY3Rpb24oKXtmdW5jdGlvbiByKGUsbix0KXtmdW5jdGlvbiBvKGksZil7aWYoIW5baV0pe2lmKCFlW2ldKXt2YXIgYz1cImZ1bmN0aW9uXCI9PXR5cGVvZiByZXF1aXJlJiZyZXF1aXJlO2lmKCFmJiZjKXJldHVybiBjKGksITApO2lmKHUpcmV0dXJuIHUoaSwhMCk7dmFyIGE9bmV3IEVycm9yKFwiQ2Fubm90IGZpbmQgbW9kdWxlICdcIitpK1wiJ1wiKTt0aHJvdyBhLmNvZGU9XCJNT0RVTEVfTk9UX0ZPVU5EXCIsYX12YXIgcD1uW2ldPXtleHBvcnRzOnt9fTtlW2ldWzBdLmNhbGwocC5leHBvcnRzLGZ1bmN0aW9uKHIpe3ZhciBuPWVbaV1bMV1bcl07cmV0dXJuIG8obnx8cil9LHAscC5leHBvcnRzLHIsZSxuLHQpfXJldHVybiBuW2ldLmV4cG9ydHN9Zm9yKHZhciB1PVwiZnVuY3Rpb25cIj09dHlwZW9mIHJlcXVpcmUmJnJlcXVpcmUsaT0wO2k8dC5sZW5ndGg7aSsrKW8odFtpXSk7cmV0dXJuIG99cmV0dXJuIHJ9KSgpIiwiXCJ1c2Ugc3RyaWN0XCI7XG5mdW5jdGlvbiBfX2V4cG9ydChtKSB7XG4gICAgZm9yICh2YXIgcCBpbiBtKSBpZiAoIWV4cG9ydHMuaGFzT3duUHJvcGVydHkocCkpIGV4cG9ydHNbcF0gPSBtW3BdO1xufVxuT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsIFwiX19lc01vZHVsZVwiLCB7IHZhbHVlOiB0cnVlIH0pO1xuX19leHBvcnQocmVxdWlyZShcIi4vc3JjL2FkYXB0b3JcIikpO1xuX19leHBvcnQocmVxdWlyZShcIi4vc3JjL2QzYWRhcHRvclwiKSk7XG5fX2V4cG9ydChyZXF1aXJlKFwiLi9zcmMvZGVzY2VudFwiKSk7XG5fX2V4cG9ydChyZXF1aXJlKFwiLi9zcmMvZ2VvbVwiKSk7XG5fX2V4cG9ydChyZXF1aXJlKFwiLi9zcmMvZ3JpZHJvdXRlclwiKSk7XG5fX2V4cG9ydChyZXF1aXJlKFwiLi9zcmMvaGFuZGxlZGlzY29ubmVjdGVkXCIpKTtcbl9fZXhwb3J0KHJlcXVpcmUoXCIuL3NyYy9sYXlvdXRcIikpO1xuX19leHBvcnQocmVxdWlyZShcIi4vc3JjL2xheW91dDNkXCIpKTtcbl9fZXhwb3J0KHJlcXVpcmUoXCIuL3NyYy9saW5rbGVuZ3Roc1wiKSk7XG5fX2V4cG9ydChyZXF1aXJlKFwiLi9zcmMvcG93ZXJncmFwaFwiKSk7XG5fX2V4cG9ydChyZXF1aXJlKFwiLi9zcmMvcHF1ZXVlXCIpKTtcbl9fZXhwb3J0KHJlcXVpcmUoXCIuL3NyYy9yYnRyZWVcIikpO1xuX19leHBvcnQocmVxdWlyZShcIi4vc3JjL3JlY3RhbmdsZVwiKSk7XG5fX2V4cG9ydChyZXF1aXJlKFwiLi9zcmMvc2hvcnRlc3RwYXRoc1wiKSk7XG5fX2V4cG9ydChyZXF1aXJlKFwiLi9zcmMvdnBzY1wiKSk7XG5fX2V4cG9ydChyZXF1aXJlKFwiLi9zcmMvYmF0Y2hcIikpO1xuLy8jIHNvdXJjZU1hcHBpbmdVUkw9ZGF0YTphcHBsaWNhdGlvbi9qc29uO2Jhc2U2NCxleUoyWlhKemFXOXVJam96TENKbWFXeGxJam9pYVc1a1pYZ3Vhbk1pTENKemIzVnlZMlZTYjI5MElqb2lJaXdpYzI5MWNtTmxjeUk2V3lJdUxpOVhaV0pEYjJ4aEwybHVaR1Y0TG5SeklsMHNJbTVoYldWeklqcGJYU3dpYldGd2NHbHVaM01pT2lJN096czdPMEZCUVVFc2JVTkJRVFpDTzBGQlF6ZENMSEZEUVVFclFqdEJRVU12UWl4dFEwRkJOa0k3UVVGRE4wSXNaME5CUVRCQ08wRkJRekZDTEhORFFVRm5RenRCUVVOb1F5dzRRMEZCZDBNN1FVRkRlRU1zYTBOQlFUUkNPMEZCUXpWQ0xHOURRVUU0UWp0QlFVTTVRaXgxUTBGQmFVTTdRVUZEYWtNc2MwTkJRV2RETzBGQlEyaERMR3REUVVFMFFqdEJRVU0xUWl4clEwRkJORUk3UVVGRE5VSXNjVU5CUVN0Q08wRkJReTlDTEhsRFFVRnRRenRCUVVOdVF5eG5RMEZCTUVJN1FVRkRNVUlzYVVOQlFUSkNJbjA9IiwiXCJ1c2Ugc3RyaWN0XCI7XG52YXIgX19leHRlbmRzID0gKHRoaXMgJiYgdGhpcy5fX2V4dGVuZHMpIHx8IChmdW5jdGlvbiAoKSB7XG4gICAgdmFyIGV4dGVuZFN0YXRpY3MgPSBmdW5jdGlvbiAoZCwgYikge1xuICAgICAgICBleHRlbmRTdGF0aWNzID0gT2JqZWN0LnNldFByb3RvdHlwZU9mIHx8XG4gICAgICAgICAgICAoeyBfX3Byb3RvX186IFtdIH0gaW5zdGFuY2VvZiBBcnJheSAmJiBmdW5jdGlvbiAoZCwgYikgeyBkLl9fcHJvdG9fXyA9IGI7IH0pIHx8XG4gICAgICAgICAgICBmdW5jdGlvbiAoZCwgYikgeyBmb3IgKHZhciBwIGluIGIpIGlmIChiLmhhc093blByb3BlcnR5KHApKSBkW3BdID0gYltwXTsgfTtcbiAgICAgICAgcmV0dXJuIGV4dGVuZFN0YXRpY3MoZCwgYik7XG4gICAgfTtcbiAgICByZXR1cm4gZnVuY3Rpb24gKGQsIGIpIHtcbiAgICAgICAgZXh0ZW5kU3RhdGljcyhkLCBiKTtcbiAgICAgICAgZnVuY3Rpb24gX18oKSB7IHRoaXMuY29uc3RydWN0b3IgPSBkOyB9XG4gICAgICAgIGQucHJvdG90eXBlID0gYiA9PT0gbnVsbCA/IE9iamVjdC5jcmVhdGUoYikgOiAoX18ucHJvdG90eXBlID0gYi5wcm90b3R5cGUsIG5ldyBfXygpKTtcbiAgICB9O1xufSkoKTtcbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCBcIl9fZXNNb2R1bGVcIiwgeyB2YWx1ZTogdHJ1ZSB9KTtcbnZhciBsYXlvdXRfMSA9IHJlcXVpcmUoXCIuL2xheW91dFwiKTtcbnZhciBMYXlvdXRBZGFwdG9yID0gKGZ1bmN0aW9uIChfc3VwZXIpIHtcbiAgICBfX2V4dGVuZHMoTGF5b3V0QWRhcHRvciwgX3N1cGVyKTtcbiAgICBmdW5jdGlvbiBMYXlvdXRBZGFwdG9yKG9wdGlvbnMpIHtcbiAgICAgICAgdmFyIF90aGlzID0gX3N1cGVyLmNhbGwodGhpcykgfHwgdGhpcztcbiAgICAgICAgdmFyIHNlbGYgPSBfdGhpcztcbiAgICAgICAgdmFyIG8gPSBvcHRpb25zO1xuICAgICAgICBpZiAoby50cmlnZ2VyKSB7XG4gICAgICAgICAgICBfdGhpcy50cmlnZ2VyID0gby50cmlnZ2VyO1xuICAgICAgICB9XG4gICAgICAgIGlmIChvLmtpY2spIHtcbiAgICAgICAgICAgIF90aGlzLmtpY2sgPSBvLmtpY2s7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKG8uZHJhZykge1xuICAgICAgICAgICAgX3RoaXMuZHJhZyA9IG8uZHJhZztcbiAgICAgICAgfVxuICAgICAgICBpZiAoby5vbikge1xuICAgICAgICAgICAgX3RoaXMub24gPSBvLm9uO1xuICAgICAgICB9XG4gICAgICAgIF90aGlzLmRyYWdzdGFydCA9IF90aGlzLmRyYWdTdGFydCA9IGxheW91dF8xLkxheW91dC5kcmFnU3RhcnQ7XG4gICAgICAgIF90aGlzLmRyYWdlbmQgPSBfdGhpcy5kcmFnRW5kID0gbGF5b3V0XzEuTGF5b3V0LmRyYWdFbmQ7XG4gICAgICAgIHJldHVybiBfdGhpcztcbiAgICB9XG4gICAgTGF5b3V0QWRhcHRvci5wcm90b3R5cGUudHJpZ2dlciA9IGZ1bmN0aW9uIChlKSB7IH07XG4gICAgO1xuICAgIExheW91dEFkYXB0b3IucHJvdG90eXBlLmtpY2sgPSBmdW5jdGlvbiAoKSB7IH07XG4gICAgO1xuICAgIExheW91dEFkYXB0b3IucHJvdG90eXBlLmRyYWcgPSBmdW5jdGlvbiAoKSB7IH07XG4gICAgO1xuICAgIExheW91dEFkYXB0b3IucHJvdG90eXBlLm9uID0gZnVuY3Rpb24gKGV2ZW50VHlwZSwgbGlzdGVuZXIpIHsgcmV0dXJuIHRoaXM7IH07XG4gICAgO1xuICAgIHJldHVybiBMYXlvdXRBZGFwdG9yO1xufShsYXlvdXRfMS5MYXlvdXQpKTtcbmV4cG9ydHMuTGF5b3V0QWRhcHRvciA9IExheW91dEFkYXB0b3I7XG5mdW5jdGlvbiBhZGFwdG9yKG9wdGlvbnMpIHtcbiAgICByZXR1cm4gbmV3IExheW91dEFkYXB0b3Iob3B0aW9ucyk7XG59XG5leHBvcnRzLmFkYXB0b3IgPSBhZGFwdG9yO1xuLy8jIHNvdXJjZU1hcHBpbmdVUkw9ZGF0YTphcHBsaWNhdGlvbi9qc29uO2Jhc2U2NCxleUoyWlhKemFXOXVJam96TENKbWFXeGxJam9pWVdSaGNIUnZjaTVxY3lJc0luTnZkWEpqWlZKdmIzUWlPaUlpTENKemIzVnlZMlZ6SWpwYklpNHVMeTR1TDFkbFlrTnZiR0V2YzNKakwyRmtZWEIwYjNJdWRITWlYU3dpYm1GdFpYTWlPbHRkTENKdFlYQndhVzVuY3lJNklqczdPenM3T3pzN096czdPenM3TzBGQlFVRXNiVU5CUVdsRU8wRkJSVGRETzBsQlFXMURMR2xEUVVGTk8wbEJZWEpETEhWQ1FVRmhMRTlCUVU4N1VVRkJjRUlzV1VGRFNTeHBRa0ZCVHl4VFFYbENWanRSUVhKQ1J5eEpRVUZKTEVsQlFVa3NSMEZCUnl4TFFVRkpMRU5CUVVNN1VVRkRhRUlzU1VGQlNTeERRVUZETEVkQlFVY3NUMEZCVHl4RFFVRkRPMUZCUldoQ0xFbEJRVXNzUTBGQlF5eERRVUZETEU5QlFVOHNSVUZCUnp0WlFVTmlMRXRCUVVrc1EwRkJReXhQUVVGUExFZEJRVWNzUTBGQlF5eERRVUZETEU5QlFVOHNRMEZCUXp0VFFVTTFRanRSUVVWRUxFbEJRVXNzUTBGQlF5eERRVUZETEVsQlFVa3NSVUZCUlR0WlFVTlVMRXRCUVVrc1EwRkJReXhKUVVGSkxFZEJRVWNzUTBGQlF5eERRVUZETEVsQlFVa3NRMEZCUXp0VFFVTjBRanRSUVVWRUxFbEJRVXNzUTBGQlF5eERRVUZETEVsQlFVa3NSVUZCUlR0WlFVTlVMRXRCUVVrc1EwRkJReXhKUVVGSkxFZEJRVWNzUTBGQlF5eERRVUZETEVsQlFVa3NRMEZCUXp0VFFVTjBRanRSUVVWRUxFbEJRVXNzUTBGQlF5eERRVUZETEVWQlFVVXNSVUZCUlR0WlFVTlFMRXRCUVVrc1EwRkJReXhGUVVGRkxFZEJRVWNzUTBGQlF5eERRVUZETEVWQlFVVXNRMEZCUXp0VFFVTnNRanRSUVVWRUxFdEJRVWtzUTBGQlF5eFRRVUZUTEVkQlFVY3NTMEZCU1N4RFFVRkRMRk5CUVZNc1IwRkJSeXhsUVVGTkxFTkJRVU1zVTBGQlV5eERRVUZETzFGQlEyNUVMRXRCUVVrc1EwRkJReXhQUVVGUExFZEJRVWNzUzBGQlNTeERRVUZETEU5QlFVOHNSMEZCUnl4bFFVRk5MRU5CUVVNc1QwRkJUeXhEUVVGRE96dEpRVU5xUkN4RFFVRkRPMGxCY0VORUxDdENRVUZQTEVkQlFWQXNWVUZCVVN4RFFVRlJMRWxCUVVjc1EwRkJRenRKUVVGQkxFTkJRVU03U1VGRGNrSXNORUpCUVVrc1IwRkJTaXhqUVVGUkxFTkJRVU03U1VGQlFTeERRVUZETzBsQlExWXNORUpCUVVrc1IwRkJTaXhqUVVGUkxFTkJRVU03U1VGQlFTeERRVUZETzBsQlExWXNNRUpCUVVVc1IwRkJSaXhWUVVGSExGTkJRVFpDTEVWQlFVVXNVVUZCYjBJc1NVRkJWeXhQUVVGUExFbEJRVWtzUTBGQlF5eERRVUZETEVOQlFVTTdTVUZCUVN4RFFVRkRPMGxCYTBOd1JpeHZRa0ZCUXp0QlFVRkVMRU5CUVVNc1FVRjRRMFFzUTBGQmJVTXNaVUZCVFN4SFFYZERlRU03UVVGNFExa3NjME5CUVdFN1FVRTJRekZDTEZOQlFXZENMRTlCUVU4c1EwRkJSU3hQUVVGUE8wbEJRelZDTEU5QlFVOHNTVUZCU1N4aFFVRmhMRU5CUVVVc1QwRkJUeXhEUVVGRkxFTkJRVU03UVVGRGVFTXNRMEZCUXp0QlFVWkVMREJDUVVWREluMD0iLCJcInVzZSBzdHJpY3RcIjtcbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCBcIl9fZXNNb2R1bGVcIiwgeyB2YWx1ZTogdHJ1ZSB9KTtcbnZhciBsYXlvdXRfMSA9IHJlcXVpcmUoXCIuL2xheW91dFwiKTtcbnZhciBncmlkcm91dGVyXzEgPSByZXF1aXJlKFwiLi9ncmlkcm91dGVyXCIpO1xuZnVuY3Rpb24gZ3JpZGlmeShwZ0xheW91dCwgbnVkZ2VHYXAsIG1hcmdpbiwgZ3JvdXBNYXJnaW4pIHtcbiAgICBwZ0xheW91dC5jb2xhLnN0YXJ0KDAsIDAsIDAsIDEwLCBmYWxzZSk7XG4gICAgdmFyIGdyaWRyb3V0ZXIgPSByb3V0ZShwZ0xheW91dC5jb2xhLm5vZGVzKCksIHBnTGF5b3V0LmNvbGEuZ3JvdXBzKCksIG1hcmdpbiwgZ3JvdXBNYXJnaW4pO1xuICAgIHJldHVybiBncmlkcm91dGVyLnJvdXRlRWRnZXMocGdMYXlvdXQucG93ZXJHcmFwaC5wb3dlckVkZ2VzLCBudWRnZUdhcCwgZnVuY3Rpb24gKGUpIHsgcmV0dXJuIGUuc291cmNlLnJvdXRlck5vZGUuaWQ7IH0sIGZ1bmN0aW9uIChlKSB7IHJldHVybiBlLnRhcmdldC5yb3V0ZXJOb2RlLmlkOyB9KTtcbn1cbmV4cG9ydHMuZ3JpZGlmeSA9IGdyaWRpZnk7XG5mdW5jdGlvbiByb3V0ZShub2RlcywgZ3JvdXBzLCBtYXJnaW4sIGdyb3VwTWFyZ2luKSB7XG4gICAgbm9kZXMuZm9yRWFjaChmdW5jdGlvbiAoZCkge1xuICAgICAgICBkLnJvdXRlck5vZGUgPSB7XG4gICAgICAgICAgICBuYW1lOiBkLm5hbWUsXG4gICAgICAgICAgICBib3VuZHM6IGQuYm91bmRzLmluZmxhdGUoLW1hcmdpbilcbiAgICAgICAgfTtcbiAgICB9KTtcbiAgICBncm91cHMuZm9yRWFjaChmdW5jdGlvbiAoZCkge1xuICAgICAgICBkLnJvdXRlck5vZGUgPSB7XG4gICAgICAgICAgICBib3VuZHM6IGQuYm91bmRzLmluZmxhdGUoLWdyb3VwTWFyZ2luKSxcbiAgICAgICAgICAgIGNoaWxkcmVuOiAodHlwZW9mIGQuZ3JvdXBzICE9PSAndW5kZWZpbmVkJyA/IGQuZ3JvdXBzLm1hcChmdW5jdGlvbiAoYykgeyByZXR1cm4gbm9kZXMubGVuZ3RoICsgYy5pZDsgfSkgOiBbXSlcbiAgICAgICAgICAgICAgICAuY29uY2F0KHR5cGVvZiBkLmxlYXZlcyAhPT0gJ3VuZGVmaW5lZCcgPyBkLmxlYXZlcy5tYXAoZnVuY3Rpb24gKGMpIHsgcmV0dXJuIGMuaW5kZXg7IH0pIDogW10pXG4gICAgICAgIH07XG4gICAgfSk7XG4gICAgdmFyIGdyaWRSb3V0ZXJOb2RlcyA9IG5vZGVzLmNvbmNhdChncm91cHMpLm1hcChmdW5jdGlvbiAoZCwgaSkge1xuICAgICAgICBkLnJvdXRlck5vZGUuaWQgPSBpO1xuICAgICAgICByZXR1cm4gZC5yb3V0ZXJOb2RlO1xuICAgIH0pO1xuICAgIHJldHVybiBuZXcgZ3JpZHJvdXRlcl8xLkdyaWRSb3V0ZXIoZ3JpZFJvdXRlck5vZGVzLCB7XG4gICAgICAgIGdldENoaWxkcmVuOiBmdW5jdGlvbiAodikgeyByZXR1cm4gdi5jaGlsZHJlbjsgfSxcbiAgICAgICAgZ2V0Qm91bmRzOiBmdW5jdGlvbiAodikgeyByZXR1cm4gdi5ib3VuZHM7IH1cbiAgICB9LCBtYXJnaW4gLSBncm91cE1hcmdpbik7XG59XG5mdW5jdGlvbiBwb3dlckdyYXBoR3JpZExheW91dChncmFwaCwgc2l6ZSwgZ3JvdXBwYWRkaW5nKSB7XG4gICAgdmFyIHBvd2VyR3JhcGg7XG4gICAgZ3JhcGgubm9kZXMuZm9yRWFjaChmdW5jdGlvbiAodiwgaSkgeyByZXR1cm4gdi5pbmRleCA9IGk7IH0pO1xuICAgIG5ldyBsYXlvdXRfMS5MYXlvdXQoKVxuICAgICAgICAuYXZvaWRPdmVybGFwcyhmYWxzZSlcbiAgICAgICAgLm5vZGVzKGdyYXBoLm5vZGVzKVxuICAgICAgICAubGlua3MoZ3JhcGgubGlua3MpXG4gICAgICAgIC5wb3dlckdyYXBoR3JvdXBzKGZ1bmN0aW9uIChkKSB7XG4gICAgICAgIHBvd2VyR3JhcGggPSBkO1xuICAgICAgICBwb3dlckdyYXBoLmdyb3Vwcy5mb3JFYWNoKGZ1bmN0aW9uICh2KSB7IHJldHVybiB2LnBhZGRpbmcgPSBncm91cHBhZGRpbmc7IH0pO1xuICAgIH0pO1xuICAgIHZhciBuID0gZ3JhcGgubm9kZXMubGVuZ3RoO1xuICAgIHZhciBlZGdlcyA9IFtdO1xuICAgIHZhciB2cyA9IGdyYXBoLm5vZGVzLnNsaWNlKDApO1xuICAgIHZzLmZvckVhY2goZnVuY3Rpb24gKHYsIGkpIHsgcmV0dXJuIHYuaW5kZXggPSBpOyB9KTtcbiAgICBwb3dlckdyYXBoLmdyb3Vwcy5mb3JFYWNoKGZ1bmN0aW9uIChnKSB7XG4gICAgICAgIHZhciBzb3VyY2VJbmQgPSBnLmluZGV4ID0gZy5pZCArIG47XG4gICAgICAgIHZzLnB1c2goZyk7XG4gICAgICAgIGlmICh0eXBlb2YgZy5sZWF2ZXMgIT09ICd1bmRlZmluZWQnKVxuICAgICAgICAgICAgZy5sZWF2ZXMuZm9yRWFjaChmdW5jdGlvbiAodikgeyByZXR1cm4gZWRnZXMucHVzaCh7IHNvdXJjZTogc291cmNlSW5kLCB0YXJnZXQ6IHYuaW5kZXggfSk7IH0pO1xuICAgICAgICBpZiAodHlwZW9mIGcuZ3JvdXBzICE9PSAndW5kZWZpbmVkJylcbiAgICAgICAgICAgIGcuZ3JvdXBzLmZvckVhY2goZnVuY3Rpb24gKGdnKSB7IHJldHVybiBlZGdlcy5wdXNoKHsgc291cmNlOiBzb3VyY2VJbmQsIHRhcmdldDogZ2cuaWQgKyBuIH0pOyB9KTtcbiAgICB9KTtcbiAgICBwb3dlckdyYXBoLnBvd2VyRWRnZXMuZm9yRWFjaChmdW5jdGlvbiAoZSkge1xuICAgICAgICBlZGdlcy5wdXNoKHsgc291cmNlOiBlLnNvdXJjZS5pbmRleCwgdGFyZ2V0OiBlLnRhcmdldC5pbmRleCB9KTtcbiAgICB9KTtcbiAgICBuZXcgbGF5b3V0XzEuTGF5b3V0KClcbiAgICAgICAgLnNpemUoc2l6ZSlcbiAgICAgICAgLm5vZGVzKHZzKVxuICAgICAgICAubGlua3MoZWRnZXMpXG4gICAgICAgIC5hdm9pZE92ZXJsYXBzKGZhbHNlKVxuICAgICAgICAubGlua0Rpc3RhbmNlKDMwKVxuICAgICAgICAuc3ltbWV0cmljRGlmZkxpbmtMZW5ndGhzKDUpXG4gICAgICAgIC5jb252ZXJnZW5jZVRocmVzaG9sZCgxZS00KVxuICAgICAgICAuc3RhcnQoMTAwLCAwLCAwLCAwLCBmYWxzZSk7XG4gICAgcmV0dXJuIHtcbiAgICAgICAgY29sYTogbmV3IGxheW91dF8xLkxheW91dCgpXG4gICAgICAgICAgICAuY29udmVyZ2VuY2VUaHJlc2hvbGQoMWUtMylcbiAgICAgICAgICAgIC5zaXplKHNpemUpXG4gICAgICAgICAgICAuYXZvaWRPdmVybGFwcyh0cnVlKVxuICAgICAgICAgICAgLm5vZGVzKGdyYXBoLm5vZGVzKVxuICAgICAgICAgICAgLmxpbmtzKGdyYXBoLmxpbmtzKVxuICAgICAgICAgICAgLmdyb3VwQ29tcGFjdG5lc3MoMWUtNClcbiAgICAgICAgICAgIC5saW5rRGlzdGFuY2UoMzApXG4gICAgICAgICAgICAuc3ltbWV0cmljRGlmZkxpbmtMZW5ndGhzKDUpXG4gICAgICAgICAgICAucG93ZXJHcmFwaEdyb3VwcyhmdW5jdGlvbiAoZCkge1xuICAgICAgICAgICAgcG93ZXJHcmFwaCA9IGQ7XG4gICAgICAgICAgICBwb3dlckdyYXBoLmdyb3Vwcy5mb3JFYWNoKGZ1bmN0aW9uICh2KSB7XG4gICAgICAgICAgICAgICAgdi5wYWRkaW5nID0gZ3JvdXBwYWRkaW5nO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH0pLnN0YXJ0KDUwLCAwLCAxMDAsIDAsIGZhbHNlKSxcbiAgICAgICAgcG93ZXJHcmFwaDogcG93ZXJHcmFwaFxuICAgIH07XG59XG5leHBvcnRzLnBvd2VyR3JhcGhHcmlkTGF5b3V0ID0gcG93ZXJHcmFwaEdyaWRMYXlvdXQ7XG4vLyMgc291cmNlTWFwcGluZ1VSTD1kYXRhOmFwcGxpY2F0aW9uL2pzb247YmFzZTY0LGV5SjJaWEp6YVc5dUlqb3pMQ0ptYVd4bElqb2lZbUYwWTJndWFuTWlMQ0p6YjNWeVkyVlNiMjkwSWpvaUlpd2ljMjkxY21ObGN5STZXeUl1TGk4dUxpOVhaV0pEYjJ4aEwzTnlZeTlpWVhSamFDNTBjeUpkTENKdVlXMWxjeUk2VzEwc0ltMWhjSEJwYm1keklqb2lPenRCUVVGQkxHMURRVUV5UXp0QlFVTXpReXd5UTBGQmRVTTdRVUZSZGtNc1UwRkJaMElzVDBGQlR5eERRVUZETEZGQlFWRXNSVUZCUlN4UlFVRm5RaXhGUVVGRkxFMUJRV01zUlVGQlJTeFhRVUZ0UWp0SlFVTnVSaXhSUVVGUkxFTkJRVU1zU1VGQlNTeERRVUZETEV0QlFVc3NRMEZCUXl4RFFVRkRMRVZCUVVVc1EwRkJReXhGUVVGRkxFTkJRVU1zUlVGQlJTeEZRVUZGTEVWQlFVVXNTMEZCU3l4RFFVRkRMRU5CUVVNN1NVRkRlRU1zU1VGQlNTeFZRVUZWTEVkQlFVY3NTMEZCU3l4RFFVRkRMRkZCUVZFc1EwRkJReXhKUVVGSkxFTkJRVU1zUzBGQlN5eEZRVUZGTEVWQlFVVXNVVUZCVVN4RFFVRkRMRWxCUVVrc1EwRkJReXhOUVVGTkxFVkJRVVVzUlVGQlJTeE5RVUZOTEVWQlFVVXNWMEZCVnl4RFFVRkRMRU5CUVVNN1NVRkRNMFlzVDBGQlR5eFZRVUZWTEVOQlFVTXNWVUZCVlN4RFFVRk5MRkZCUVZFc1EwRkJReXhWUVVGVkxFTkJRVU1zVlVGQlZTeEZRVUZGTEZGQlFWRXNSVUZCUlN4VlFVRkJMRU5CUVVNc1NVRkJSeXhQUVVGQkxFTkJRVU1zUTBGQlF5eE5RVUZOTEVOQlFVTXNWVUZCVlN4RFFVRkRMRVZCUVVVc1JVRkJkRUlzUTBGQmMwSXNSVUZCUlN4VlFVRkJMRU5CUVVNc1NVRkJSeXhQUVVGQkxFTkJRVU1zUTBGQlF5eE5RVUZOTEVOQlFVTXNWVUZCVlN4RFFVRkRMRVZCUVVVc1JVRkJkRUlzUTBGQmMwSXNRMEZCUXl4RFFVRkRPMEZCUTNoSkxFTkJRVU03UVVGS1JDd3dRa0ZKUXp0QlFVVkVMRk5CUVZNc1MwRkJTeXhEUVVGRExFdEJRVXNzUlVGQlJTeE5RVUZOTEVWQlFVVXNUVUZCWXl4RlFVRkZMRmRCUVcxQ08wbEJRemRFTEV0QlFVc3NRMEZCUXl4UFFVRlBMRU5CUVVNc1ZVRkJRU3hEUVVGRE8xRkJRMWdzUTBGQlF5eERRVUZETEZWQlFWVXNSMEZCVVR0WlFVTm9RaXhKUVVGSkxFVkJRVVVzUTBGQlF5eERRVUZETEVsQlFVazdXVUZEV2l4TlFVRk5MRVZCUVVVc1EwRkJReXhEUVVGRExFMUJRVTBzUTBGQlF5eFBRVUZQTEVOQlFVTXNRMEZCUXl4TlFVRk5MRU5CUVVNN1UwRkRjRU1zUTBGQlF6dEpRVU5PTEVOQlFVTXNRMEZCUXl4RFFVRkRPMGxCUTBnc1RVRkJUU3hEUVVGRExFOUJRVThzUTBGQlF5eFZRVUZCTEVOQlFVTTdVVUZEV2l4RFFVRkRMRU5CUVVNc1ZVRkJWU3hIUVVGUk8xbEJRMmhDTEUxQlFVMHNSVUZCUlN4RFFVRkRMRU5CUVVNc1RVRkJUU3hEUVVGRExFOUJRVThzUTBGQlF5eERRVUZETEZkQlFWY3NRMEZCUXp0WlFVTjBReXhSUVVGUkxFVkJRVVVzUTBGQlF5eFBRVUZQTEVOQlFVTXNRMEZCUXl4TlFVRk5MRXRCUVVzc1YwRkJWeXhEUVVGRExFTkJRVU1zUTBGQlF5eERRVUZETEVOQlFVTXNUVUZCVFN4RFFVRkRMRWRCUVVjc1EwRkJReXhWUVVGQkxFTkJRVU1zU1VGQlJ5eFBRVUZCTEV0QlFVc3NRMEZCUXl4TlFVRk5MRWRCUVVjc1EwRkJReXhEUVVGRExFVkJRVVVzUlVGQmJrSXNRMEZCYlVJc1EwRkJReXhEUVVGRExFTkJRVU1zUTBGQlF5eEZRVUZGTEVOQlFVTTdhVUpCUTI1R0xFMUJRVTBzUTBGQlF5eFBRVUZQTEVOQlFVTXNRMEZCUXl4TlFVRk5MRXRCUVVzc1YwRkJWeXhEUVVGRExFTkJRVU1zUTBGQlF5eERRVUZETEVOQlFVTXNUVUZCVFN4RFFVRkRMRWRCUVVjc1EwRkJReXhWUVVGQkxFTkJRVU1zU1VGQlJ5eFBRVUZCTEVOQlFVTXNRMEZCUXl4TFFVRkxMRVZCUVZBc1EwRkJUeXhEUVVGRExFTkJRVU1zUTBGQlF5eERRVUZETEVWQlFVVXNRMEZCUXp0VFFVTm9SaXhEUVVGRE8wbEJRMDRzUTBGQlF5eERRVUZETEVOQlFVTTdTVUZEU0N4SlFVRkpMR1ZCUVdVc1IwRkJSeXhMUVVGTExFTkJRVU1zVFVGQlRTeERRVUZETEUxQlFVMHNRMEZCUXl4RFFVRkRMRWRCUVVjc1EwRkJReXhWUVVGRExFTkJRVU1zUlVGQlJTeERRVUZETzFGQlEyaEVMRU5CUVVNc1EwRkJReXhWUVVGVkxFTkJRVU1zUlVGQlJTeEhRVUZITEVOQlFVTXNRMEZCUXp0UlFVTndRaXhQUVVGUExFTkJRVU1zUTBGQlF5eFZRVUZWTEVOQlFVTTdTVUZEZUVJc1EwRkJReXhEUVVGRExFTkJRVU03U1VGRFNDeFBRVUZQTEVsQlFVa3NkVUpCUVZVc1EwRkJReXhsUVVGbExFVkJRVVU3VVVGRGJrTXNWMEZCVnl4RlFVRkZMRlZCUVVNc1EwRkJUU3hKUVVGTExFOUJRVUVzUTBGQlF5eERRVUZETEZGQlFWRXNSVUZCVml4RFFVRlZPMUZCUTI1RExGTkJRVk1zUlVGQlJTeFZRVUZCTEVOQlFVTXNTVUZCU1N4UFFVRkJMRU5CUVVNc1EwRkJReXhOUVVGTkxFVkJRVklzUTBGQlVUdExRVU16UWl4RlFVRkZMRTFCUVUwc1IwRkJSeXhYUVVGWExFTkJRVU1zUTBGQlF6dEJRVU0zUWl4RFFVRkRPMEZCUlVRc1UwRkJaMElzYjBKQlFXOUNMRU5CUTJoRExFdEJRVFpETEVWQlF6ZERMRWxCUVdNc1JVRkRaQ3haUVVGdlFqdEpRVWR3UWl4SlFVRkpMRlZCUVZVc1EwRkJRenRKUVVObUxFdEJRVXNzUTBGQlF5eExRVUZMTEVOQlFVTXNUMEZCVHl4RFFVRkRMRlZCUVVNc1EwRkJReXhGUVVGRExFTkJRVU1zU1VGQlN5eFBRVUZOTEVOQlFVVXNRMEZCUXl4TFFVRkxMRWRCUVVjc1EwRkJReXhGUVVGc1FpeERRVUZyUWl4RFFVRkRMRU5CUVVNN1NVRkRha1FzU1VGQlNTeGxRVUZOTEVWQlFVVTdVMEZEVUN4aFFVRmhMRU5CUVVNc1MwRkJTeXhEUVVGRE8xTkJRM0JDTEV0QlFVc3NRMEZCUXl4TFFVRkxMRU5CUVVNc1MwRkJTeXhEUVVGRE8xTkJRMnhDTEV0QlFVc3NRMEZCUXl4TFFVRkxMRU5CUVVNc1MwRkJTeXhEUVVGRE8xTkJRMnhDTEdkQ1FVRm5RaXhEUVVGRExGVkJRVlVzUTBGQlF6dFJRVU42UWl4VlFVRlZMRWRCUVVjc1EwRkJReXhEUVVGRE8xRkJRMllzVlVGQlZTeERRVUZETEUxQlFVMHNRMEZCUXl4UFFVRlBMRU5CUVVNc1ZVRkJRU3hEUVVGRExFbEJRVWNzVDBGQlFTeERRVUZETEVOQlFVTXNUMEZCVHl4SFFVRkhMRmxCUVZrc1JVRkJlRUlzUTBGQmQwSXNRMEZCUXl4RFFVRkRPMGxCUXpWRUxFTkJRVU1zUTBGQlF5eERRVUZETzBsQlNWQXNTVUZCU1N4RFFVRkRMRWRCUVVjc1MwRkJTeXhEUVVGRExFdEJRVXNzUTBGQlF5eE5RVUZOTEVOQlFVTTdTVUZETTBJc1NVRkJTU3hMUVVGTExFZEJRVWNzUlVGQlJTeERRVUZETzBsQlEyWXNTVUZCU1N4RlFVRkZMRWRCUVVjc1MwRkJTeXhEUVVGRExFdEJRVXNzUTBGQlF5eExRVUZMTEVOQlFVTXNRMEZCUXl4RFFVRkRMRU5CUVVNN1NVRkRPVUlzUlVGQlJTeERRVUZETEU5QlFVOHNRMEZCUXl4VlFVRkRMRU5CUVVNc1JVRkJSU3hEUVVGRExFbEJRVXNzVDBGQlRTeERRVUZGTEVOQlFVTXNTMEZCU3l4SFFVRkhMRU5CUVVNc1JVRkJiRUlzUTBGQmEwSXNRMEZCUXl4RFFVRkRPMGxCUTNwRExGVkJRVlVzUTBGQlF5eE5RVUZOTEVOQlFVTXNUMEZCVHl4RFFVRkRMRlZCUVVFc1EwRkJRenRSUVVOMlFpeEpRVUZKTEZOQlFWTXNSMEZCUnl4RFFVRkRMRU5CUVVNc1MwRkJTeXhIUVVGSExFTkJRVU1zUTBGQlF5eEZRVUZGTEVkQlFVY3NRMEZCUXl4RFFVRkRPMUZCUTI1RExFVkJRVVVzUTBGQlF5eEpRVUZKTEVOQlFVTXNRMEZCUXl4RFFVRkRMRU5CUVVNN1VVRkRXQ3hKUVVGSkxFOUJRVThzUTBGQlF5eERRVUZETEUxQlFVMHNTMEZCU3l4WFFVRlhPMWxCUXk5Q0xFTkJRVU1zUTBGQlF5eE5RVUZOTEVOQlFVTXNUMEZCVHl4RFFVRkRMRlZCUVVFc1EwRkJReXhKUVVGSkxFOUJRVUVzUzBGQlN5eERRVUZETEVsQlFVa3NRMEZCUXl4RlFVRkZMRTFCUVUwc1JVRkJSU3hUUVVGVExFVkJRVVVzVFVGQlRTeEZRVUZGTEVOQlFVTXNRMEZCUXl4TFFVRkxMRVZCUVVVc1EwRkJReXhGUVVGc1JDeERRVUZyUkN4RFFVRkRMRU5CUVVNN1VVRkRPVVVzU1VGQlNTeFBRVUZQTEVOQlFVTXNRMEZCUXl4TlFVRk5MRXRCUVVzc1YwRkJWenRaUVVNdlFpeERRVUZETEVOQlFVTXNUVUZCVFN4RFFVRkRMRTlCUVU4c1EwRkJReXhWUVVGQkxFVkJRVVVzU1VGQlNTeFBRVUZCTEV0QlFVc3NRMEZCUXl4SlFVRkpMRU5CUVVNc1JVRkJSU3hOUVVGTkxFVkJRVVVzVTBGQlV5eEZRVUZGTEUxQlFVMHNSVUZCUlN4RlFVRkZMRU5CUVVNc1JVRkJSU3hIUVVGSExFTkJRVU1zUlVGQlJTeERRVUZETEVWQlFYQkVMRU5CUVc5RUxFTkJRVU1zUTBGQlF6dEpRVU55Uml4RFFVRkRMRU5CUVVNc1EwRkJRenRKUVVOSUxGVkJRVlVzUTBGQlF5eFZRVUZWTEVOQlFVTXNUMEZCVHl4RFFVRkRMRlZCUVVFc1EwRkJRenRSUVVNelFpeExRVUZMTEVOQlFVTXNTVUZCU1N4RFFVRkRMRVZCUVVVc1RVRkJUU3hGUVVGRkxFTkJRVU1zUTBGQlF5eE5RVUZOTEVOQlFVTXNTMEZCU3l4RlFVRkZMRTFCUVUwc1JVRkJSU3hEUVVGRExFTkJRVU1zVFVGQlRTeERRVUZETEV0QlFVc3NSVUZCUlN4RFFVRkRMRU5CUVVNN1NVRkRia1VzUTBGQlF5eERRVUZETEVOQlFVTTdTVUZIU0N4SlFVRkpMR1ZCUVUwc1JVRkJSVHRUUVVOUUxFbEJRVWtzUTBGQlF5eEpRVUZKTEVOQlFVTTdVMEZEVml4TFFVRkxMRU5CUVVNc1JVRkJSU3hEUVVGRE8xTkJRMVFzUzBGQlN5eERRVUZETEV0QlFVc3NRMEZCUXp0VFFVTmFMR0ZCUVdFc1EwRkJReXhMUVVGTExFTkJRVU03VTBGRGNFSXNXVUZCV1N4RFFVRkRMRVZCUVVVc1EwRkJRenRUUVVOb1FpeDNRa0ZCZDBJc1EwRkJReXhEUVVGRExFTkJRVU03VTBGRE0wSXNiMEpCUVc5Q0xFTkJRVU1zU1VGQlNTeERRVUZETzFOQlF6RkNMRXRCUVVzc1EwRkJReXhIUVVGSExFVkJRVVVzUTBGQlF5eEZRVUZGTEVOQlFVTXNSVUZCUlN4RFFVRkRMRVZCUVVVc1MwRkJTeXhEUVVGRExFTkJRVU03U1VGTGFFTXNUMEZCVHp0UlFVTklMRWxCUVVrc1JVRkRRU3hKUVVGSkxHVkJRVTBzUlVGQlJUdGhRVU5ZTEc5Q1FVRnZRaXhEUVVGRExFbEJRVWtzUTBGQlF6dGhRVU14UWl4SlFVRkpMRU5CUVVNc1NVRkJTU3hEUVVGRE8yRkJRMVlzWVVGQllTeERRVUZETEVsQlFVa3NRMEZCUXp0aFFVTnVRaXhMUVVGTExFTkJRVU1zUzBGQlN5eERRVUZETEV0QlFVc3NRMEZCUXp0aFFVTnNRaXhMUVVGTExFTkJRVU1zUzBGQlN5eERRVUZETEV0QlFVc3NRMEZCUXp0aFFVVnNRaXhuUWtGQlowSXNRMEZCUXl4SlFVRkpMRU5CUVVNN1lVRkRkRUlzV1VGQldTeERRVUZETEVWQlFVVXNRMEZCUXp0aFFVTm9RaXgzUWtGQmQwSXNRMEZCUXl4RFFVRkRMRU5CUVVNN1lVRkRNMElzWjBKQlFXZENMRU5CUVVNc1ZVRkJWU3hEUVVGRE8xbEJRM3BDTEZWQlFWVXNSMEZCUnl4RFFVRkRMRU5CUVVNN1dVRkRaaXhWUVVGVkxFTkJRVU1zVFVGQlRTeERRVUZETEU5QlFVOHNRMEZCUXl4VlFVRlZMRU5CUVVNN1owSkJRMnBETEVOQlFVTXNRMEZCUXl4UFFVRlBMRWRCUVVjc1dVRkJXU3hEUVVGQk8xbEJRelZDTEVOQlFVTXNRMEZCUXl4RFFVRkRPMUZCUTFBc1EwRkJReXhEUVVGRExFTkJRVU1zUzBGQlN5eERRVUZETEVWQlFVVXNSVUZCUlN4RFFVRkRMRVZCUVVVc1IwRkJSeXhGUVVGRkxFTkJRVU1zUlVGQlJTeExRVUZMTEVOQlFVTTdVVUZEYkVNc1ZVRkJWU3hGUVVGRkxGVkJRVlU3UzBGRGVrSXNRMEZCUXp0QlFVTk9MRU5CUVVNN1FVRnlSVVFzYjBSQmNVVkRJbjA9IiwiXCJ1c2Ugc3RyaWN0XCI7XG5PYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgXCJfX2VzTW9kdWxlXCIsIHsgdmFsdWU6IHRydWUgfSk7XG52YXIgZDN2MyA9IHJlcXVpcmUoXCIuL2QzdjNhZGFwdG9yXCIpO1xudmFyIGQzdjQgPSByZXF1aXJlKFwiLi9kM3Y0YWRhcHRvclwiKTtcbjtcbmZ1bmN0aW9uIGQzYWRhcHRvcihkM0NvbnRleHQpIHtcbiAgICBpZiAoIWQzQ29udGV4dCB8fCBpc0QzVjMoZDNDb250ZXh0KSkge1xuICAgICAgICByZXR1cm4gbmV3IGQzdjMuRDNTdHlsZUxheW91dEFkYXB0b3IoKTtcbiAgICB9XG4gICAgcmV0dXJuIG5ldyBkM3Y0LkQzU3R5bGVMYXlvdXRBZGFwdG9yKGQzQ29udGV4dCk7XG59XG5leHBvcnRzLmQzYWRhcHRvciA9IGQzYWRhcHRvcjtcbmZ1bmN0aW9uIGlzRDNWMyhkM0NvbnRleHQpIHtcbiAgICB2YXIgdjNleHAgPSAvXjNcXC4vO1xuICAgIHJldHVybiBkM0NvbnRleHQudmVyc2lvbiAmJiBkM0NvbnRleHQudmVyc2lvbi5tYXRjaCh2M2V4cCkgIT09IG51bGw7XG59XG4vLyMgc291cmNlTWFwcGluZ1VSTD1kYXRhOmFwcGxpY2F0aW9uL2pzb247YmFzZTY0LGV5SjJaWEp6YVc5dUlqb3pMQ0ptYVd4bElqb2laRE5oWkdGd2RHOXlMbXB6SWl3aWMyOTFjbU5sVW05dmRDSTZJaUlzSW5OdmRYSmpaWE1pT2xzaUxpNHZMaTR2VjJWaVEyOXNZUzl6Y21NdlpETmhaR0Z3ZEc5eUxuUnpJbDBzSW01aGJXVnpJanBiWFN3aWJXRndjR2x1WjNNaU9pSTdPMEZCUVVFc2IwTkJRWEZETzBGQlEzSkRMRzlEUVVGeFF6dEJRVWRWTEVOQlFVTTdRVUUwUW1oRUxGTkJRV2RDTEZOQlFWTXNRMEZCUXl4VFFVRjNRenRKUVVNNVJDeEpRVUZKTEVOQlFVTXNVMEZCVXl4SlFVRkpMRTFCUVUwc1EwRkJReXhUUVVGVExFTkJRVU1zUlVGQlJUdFJRVU5xUXl4UFFVRlBMRWxCUVVrc1NVRkJTU3hEUVVGRExHOUNRVUZ2UWl4RlFVRkZMRU5CUVVNN1MwRkRNVU03U1VGRFJDeFBRVUZQTEVsQlFVa3NTVUZCU1N4RFFVRkRMRzlDUVVGdlFpeERRVUZETEZOQlFWTXNRMEZCUXl4RFFVRkRPMEZCUTNCRUxFTkJRVU03UVVGTVJDdzRRa0ZMUXp0QlFVVkVMRk5CUVZNc1RVRkJUU3hEUVVGRExGTkJRWFZETzBsQlEyNUVMRWxCUVUwc1MwRkJTeXhIUVVGSExFMUJRVTBzUTBGQlF6dEpRVU55UWl4UFFVRmhMRk5CUVZVc1EwRkJReXhQUVVGUExFbEJRVlVzVTBGQlZTeERRVUZETEU5QlFVOHNRMEZCUXl4TFFVRkxMRU5CUVVNc1MwRkJTeXhEUVVGRExFdEJRVXNzU1VGQlNTeERRVUZETzBGQlEzUkdMRU5CUVVNaWZRPT0iLCJcInVzZSBzdHJpY3RcIjtcbnZhciBfX2V4dGVuZHMgPSAodGhpcyAmJiB0aGlzLl9fZXh0ZW5kcykgfHwgKGZ1bmN0aW9uICgpIHtcbiAgICB2YXIgZXh0ZW5kU3RhdGljcyA9IGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgICAgIGV4dGVuZFN0YXRpY3MgPSBPYmplY3Quc2V0UHJvdG90eXBlT2YgfHxcbiAgICAgICAgICAgICh7IF9fcHJvdG9fXzogW10gfSBpbnN0YW5jZW9mIEFycmF5ICYmIGZ1bmN0aW9uIChkLCBiKSB7IGQuX19wcm90b19fID0gYjsgfSkgfHxcbiAgICAgICAgICAgIGZ1bmN0aW9uIChkLCBiKSB7IGZvciAodmFyIHAgaW4gYikgaWYgKGIuaGFzT3duUHJvcGVydHkocCkpIGRbcF0gPSBiW3BdOyB9O1xuICAgICAgICByZXR1cm4gZXh0ZW5kU3RhdGljcyhkLCBiKTtcbiAgICB9O1xuICAgIHJldHVybiBmdW5jdGlvbiAoZCwgYikge1xuICAgICAgICBleHRlbmRTdGF0aWNzKGQsIGIpO1xuICAgICAgICBmdW5jdGlvbiBfXygpIHsgdGhpcy5jb25zdHJ1Y3RvciA9IGQ7IH1cbiAgICAgICAgZC5wcm90b3R5cGUgPSBiID09PSBudWxsID8gT2JqZWN0LmNyZWF0ZShiKSA6IChfXy5wcm90b3R5cGUgPSBiLnByb3RvdHlwZSwgbmV3IF9fKCkpO1xuICAgIH07XG59KSgpO1xuT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsIFwiX19lc01vZHVsZVwiLCB7IHZhbHVlOiB0cnVlIH0pO1xudmFyIGxheW91dF8xID0gcmVxdWlyZShcIi4vbGF5b3V0XCIpO1xudmFyIEQzU3R5bGVMYXlvdXRBZGFwdG9yID0gKGZ1bmN0aW9uIChfc3VwZXIpIHtcbiAgICBfX2V4dGVuZHMoRDNTdHlsZUxheW91dEFkYXB0b3IsIF9zdXBlcik7XG4gICAgZnVuY3Rpb24gRDNTdHlsZUxheW91dEFkYXB0b3IoKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IF9zdXBlci5jYWxsKHRoaXMpIHx8IHRoaXM7XG4gICAgICAgIF90aGlzLmV2ZW50ID0gZDMuZGlzcGF0Y2gobGF5b3V0XzEuRXZlbnRUeXBlW2xheW91dF8xLkV2ZW50VHlwZS5zdGFydF0sIGxheW91dF8xLkV2ZW50VHlwZVtsYXlvdXRfMS5FdmVudFR5cGUudGlja10sIGxheW91dF8xLkV2ZW50VHlwZVtsYXlvdXRfMS5FdmVudFR5cGUuZW5kXSk7XG4gICAgICAgIHZhciBkM2xheW91dCA9IF90aGlzO1xuICAgICAgICB2YXIgZHJhZztcbiAgICAgICAgX3RoaXMuZHJhZyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIGlmICghZHJhZykge1xuICAgICAgICAgICAgICAgIHZhciBkcmFnID0gZDMuYmVoYXZpb3IuZHJhZygpXG4gICAgICAgICAgICAgICAgICAgIC5vcmlnaW4obGF5b3V0XzEuTGF5b3V0LmRyYWdPcmlnaW4pXG4gICAgICAgICAgICAgICAgICAgIC5vbihcImRyYWdzdGFydC5kM2FkYXB0b3JcIiwgbGF5b3V0XzEuTGF5b3V0LmRyYWdTdGFydClcbiAgICAgICAgICAgICAgICAgICAgLm9uKFwiZHJhZy5kM2FkYXB0b3JcIiwgZnVuY3Rpb24gKGQpIHtcbiAgICAgICAgICAgICAgICAgICAgbGF5b3V0XzEuTGF5b3V0LmRyYWcoZCwgZDMuZXZlbnQpO1xuICAgICAgICAgICAgICAgICAgICBkM2xheW91dC5yZXN1bWUoKTtcbiAgICAgICAgICAgICAgICB9KVxuICAgICAgICAgICAgICAgICAgICAub24oXCJkcmFnZW5kLmQzYWRhcHRvclwiLCBsYXlvdXRfMS5MYXlvdXQuZHJhZ0VuZCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoIWFyZ3VtZW50cy5sZW5ndGgpXG4gICAgICAgICAgICAgICAgcmV0dXJuIGRyYWc7XG4gICAgICAgICAgICB0aGlzXG4gICAgICAgICAgICAgICAgLmNhbGwoZHJhZyk7XG4gICAgICAgIH07XG4gICAgICAgIHJldHVybiBfdGhpcztcbiAgICB9XG4gICAgRDNTdHlsZUxheW91dEFkYXB0b3IucHJvdG90eXBlLnRyaWdnZXIgPSBmdW5jdGlvbiAoZSkge1xuICAgICAgICB2YXIgZDNldmVudCA9IHsgdHlwZTogbGF5b3V0XzEuRXZlbnRUeXBlW2UudHlwZV0sIGFscGhhOiBlLmFscGhhLCBzdHJlc3M6IGUuc3RyZXNzIH07XG4gICAgICAgIHRoaXMuZXZlbnRbZDNldmVudC50eXBlXShkM2V2ZW50KTtcbiAgICB9O1xuICAgIEQzU3R5bGVMYXlvdXRBZGFwdG9yLnByb3RvdHlwZS5raWNrID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICBkMy50aW1lcihmdW5jdGlvbiAoKSB7IHJldHVybiBfc3VwZXIucHJvdG90eXBlLnRpY2suY2FsbChfdGhpcyk7IH0pO1xuICAgIH07XG4gICAgRDNTdHlsZUxheW91dEFkYXB0b3IucHJvdG90eXBlLm9uID0gZnVuY3Rpb24gKGV2ZW50VHlwZSwgbGlzdGVuZXIpIHtcbiAgICAgICAgaWYgKHR5cGVvZiBldmVudFR5cGUgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICB0aGlzLmV2ZW50Lm9uKGV2ZW50VHlwZSwgbGlzdGVuZXIpO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgdGhpcy5ldmVudC5vbihsYXlvdXRfMS5FdmVudFR5cGVbZXZlbnRUeXBlXSwgbGlzdGVuZXIpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH07XG4gICAgcmV0dXJuIEQzU3R5bGVMYXlvdXRBZGFwdG9yO1xufShsYXlvdXRfMS5MYXlvdXQpKTtcbmV4cG9ydHMuRDNTdHlsZUxheW91dEFkYXB0b3IgPSBEM1N0eWxlTGF5b3V0QWRhcHRvcjtcbmZ1bmN0aW9uIGQzYWRhcHRvcigpIHtcbiAgICByZXR1cm4gbmV3IEQzU3R5bGVMYXlvdXRBZGFwdG9yKCk7XG59XG5leHBvcnRzLmQzYWRhcHRvciA9IGQzYWRhcHRvcjtcbi8vIyBzb3VyY2VNYXBwaW5nVVJMPWRhdGE6YXBwbGljYXRpb24vanNvbjtiYXNlNjQsZXlKMlpYSnphVzl1SWpvekxDSm1hV3hsSWpvaVpETjJNMkZrWVhCMGIzSXVhbk1pTENKemIzVnlZMlZTYjI5MElqb2lJaXdpYzI5MWNtTmxjeUk2V3lJdUxpOHVMaTlYWldKRGIyeGhMM055WXk5a00zWXpZV1JoY0hSdmNpNTBjeUpkTENKdVlXMWxjeUk2VzEwc0ltMWhjSEJwYm1keklqb2lPenM3T3pzN096czdPenM3T3pzN1FVRk5RU3h0UTBGQmEwUTdRVUZIT1VNN1NVRkJNRU1zZDBOQlFVMDdTVUZuUWpWRE8xRkJRVUVzV1VGRFNTeHBRa0ZCVHl4VFFYVkNWanRSUVhaRFJDeFhRVUZMTEVkQlFVY3NSVUZCUlN4RFFVRkRMRkZCUVZFc1EwRkJReXhyUWtGQlV5eERRVUZETEd0Q1FVRlRMRU5CUVVNc1MwRkJTeXhEUVVGRExFVkJRVVVzYTBKQlFWTXNRMEZCUXl4clFrRkJVeXhEUVVGRExFbEJRVWtzUTBGQlF5eEZRVUZGTEd0Q1FVRlRMRU5CUVVNc2EwSkJRVk1zUTBGQlF5eEhRVUZITEVOQlFVTXNRMEZCUXl4RFFVRkRPMUZCYTBKcVJ5eEpRVUZKTEZGQlFWRXNSMEZCUnl4TFFVRkpMRU5CUVVNN1VVRkRjRUlzU1VGQlNTeEpRVUZKTEVOQlFVTTdVVUZEVkN4TFFVRkpMRU5CUVVNc1NVRkJTU3hIUVVGSE8xbEJRMUlzU1VGQlNTeERRVUZETEVsQlFVa3NSVUZCUlR0blFrRkRVQ3hKUVVGSkxFbEJRVWtzUjBGQlJ5eEZRVUZGTEVOQlFVTXNVVUZCVVN4RFFVRkRMRWxCUVVrc1JVRkJSVHR4UWtGRGVFSXNUVUZCVFN4RFFVRkRMR1ZCUVUwc1EwRkJReXhWUVVGVkxFTkJRVU03Y1VKQlEzcENMRVZCUVVVc1EwRkJReXh4UWtGQmNVSXNSVUZCUlN4bFFVRk5MRU5CUVVNc1UwRkJVeXhEUVVGRE8zRkNRVU16UXl4RlFVRkZMRU5CUVVNc1owSkJRV2RDTEVWQlFVVXNWVUZCUVN4RFFVRkRPMjlDUVVOdVFpeGxRVUZOTEVOQlFVTXNTVUZCU1N4RFFVRkRMRU5CUVVNc1JVRkJUeXhGUVVGRkxFTkJRVU1zUzBGQlN5eERRVUZETEVOQlFVTTdiMEpCUXpsQ0xGRkJRVkVzUTBGQlF5eE5RVUZOTEVWQlFVVXNRMEZCUXp0blFrRkRkRUlzUTBGQlF5eERRVUZETzNGQ1FVTkVMRVZCUVVVc1EwRkJReXh0UWtGQmJVSXNSVUZCUlN4bFFVRk5MRU5CUVVNc1QwRkJUeXhEUVVGRExFTkJRVU03WVVGRGFFUTdXVUZGUkN4SlFVRkpMRU5CUVVNc1UwRkJVeXhEUVVGRExFMUJRVTA3WjBKQlFVVXNUMEZCVHl4SlFVRkpMRU5CUVVNN1dVRkhia01zU1VGQlNUdHBRa0ZGUXl4SlFVRkpMRU5CUVVNc1NVRkJTU3hEUVVGRExFTkJRVU03VVVGRGNFSXNRMEZCUXl4RFFVRkJPenRKUVVOTUxFTkJRVU03U1VGeVEwUXNjME5CUVU4c1IwRkJVQ3hWUVVGUkxFTkJRVkU3VVVGRFdpeEpRVUZKTEU5QlFVOHNSMEZCUnl4RlFVRkZMRWxCUVVrc1JVRkJSU3hyUWtGQlV5eERRVUZETEVOQlFVTXNRMEZCUXl4SlFVRkpMRU5CUVVNc1JVRkJSU3hMUVVGTExFVkJRVVVzUTBGQlF5eERRVUZETEV0QlFVc3NSVUZCUlN4TlFVRk5MRVZCUVVVc1EwRkJReXhEUVVGRExFMUJRVTBzUlVGQlJTeERRVUZETzFGQlF6VkZMRWxCUVVrc1EwRkJReXhMUVVGTExFTkJRVU1zVDBGQlR5eERRVUZETEVsQlFVa3NRMEZCUXl4RFFVRkRMRTlCUVU4c1EwRkJReXhEUVVGRE8wbEJRM1JETEVOQlFVTTdTVUZIUkN4dFEwRkJTU3hIUVVGS08xRkJRVUVzYVVKQlJVTTdVVUZFUnl4RlFVRkZMRU5CUVVNc1MwRkJTeXhEUVVGRExHTkJRVTBzVDBGQlFTeHBRa0ZCVFN4SlFVRkpMRmxCUVVVc1JVRkJXaXhEUVVGWkxFTkJRVU1zUTBGQlF6dEpRVU5xUXl4RFFVRkRPMGxCWjBORUxHbERRVUZGTEVkQlFVWXNWVUZCUnl4VFFVRTJRaXhGUVVGRkxGRkJRVzlDTzFGQlEyeEVMRWxCUVVrc1QwRkJUeXhUUVVGVExFdEJRVXNzVVVGQlVTeEZRVUZGTzFsQlF5OUNMRWxCUVVrc1EwRkJReXhMUVVGTExFTkJRVU1zUlVGQlJTeERRVUZETEZOQlFWTXNSVUZCUlN4UlFVRlJMRU5CUVVNc1EwRkJRenRUUVVOMFF6dGhRVUZOTzFsQlEwZ3NTVUZCU1N4RFFVRkRMRXRCUVVzc1EwRkJReXhGUVVGRkxFTkJRVU1zYTBKQlFWTXNRMEZCUXl4VFFVRlRMRU5CUVVNc1JVRkJSU3hSUVVGUkxFTkJRVU1zUTBGQlF6dFRRVU5xUkR0UlFVTkVMRTlCUVU4c1NVRkJTU3hEUVVGRE8wbEJRMmhDTEVOQlFVTTdTVUZEVEN3eVFrRkJRenRCUVVGRUxFTkJRVU1zUVVGdVJFUXNRMEZCTUVNc1pVRkJUU3hIUVcxRUwwTTdRVUZ1UkZrc2IwUkJRVzlDTzBGQmFVVnFReXhUUVVGblFpeFRRVUZUTzBsQlEzSkNMRTlCUVU4c1NVRkJTU3h2UWtGQmIwSXNSVUZCUlN4RFFVRkRPMEZCUTNSRExFTkJRVU03UVVGR1JDdzRRa0ZGUXlKOSIsIlwidXNlIHN0cmljdFwiO1xudmFyIF9fZXh0ZW5kcyA9ICh0aGlzICYmIHRoaXMuX19leHRlbmRzKSB8fCAoZnVuY3Rpb24gKCkge1xuICAgIHZhciBleHRlbmRTdGF0aWNzID0gZnVuY3Rpb24gKGQsIGIpIHtcbiAgICAgICAgZXh0ZW5kU3RhdGljcyA9IE9iamVjdC5zZXRQcm90b3R5cGVPZiB8fFxuICAgICAgICAgICAgKHsgX19wcm90b19fOiBbXSB9IGluc3RhbmNlb2YgQXJyYXkgJiYgZnVuY3Rpb24gKGQsIGIpIHsgZC5fX3Byb3RvX18gPSBiOyB9KSB8fFxuICAgICAgICAgICAgZnVuY3Rpb24gKGQsIGIpIHsgZm9yICh2YXIgcCBpbiBiKSBpZiAoYi5oYXNPd25Qcm9wZXJ0eShwKSkgZFtwXSA9IGJbcF07IH07XG4gICAgICAgIHJldHVybiBleHRlbmRTdGF0aWNzKGQsIGIpO1xuICAgIH07XG4gICAgcmV0dXJuIGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgICAgIGV4dGVuZFN0YXRpY3MoZCwgYik7XG4gICAgICAgIGZ1bmN0aW9uIF9fKCkgeyB0aGlzLmNvbnN0cnVjdG9yID0gZDsgfVxuICAgICAgICBkLnByb3RvdHlwZSA9IGIgPT09IG51bGwgPyBPYmplY3QuY3JlYXRlKGIpIDogKF9fLnByb3RvdHlwZSA9IGIucHJvdG90eXBlLCBuZXcgX18oKSk7XG4gICAgfTtcbn0pKCk7XG5PYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgXCJfX2VzTW9kdWxlXCIsIHsgdmFsdWU6IHRydWUgfSk7XG52YXIgbGF5b3V0XzEgPSByZXF1aXJlKFwiLi9sYXlvdXRcIik7XG52YXIgRDNTdHlsZUxheW91dEFkYXB0b3IgPSAoZnVuY3Rpb24gKF9zdXBlcikge1xuICAgIF9fZXh0ZW5kcyhEM1N0eWxlTGF5b3V0QWRhcHRvciwgX3N1cGVyKTtcbiAgICBmdW5jdGlvbiBEM1N0eWxlTGF5b3V0QWRhcHRvcihkM0NvbnRleHQpIHtcbiAgICAgICAgdmFyIF90aGlzID0gX3N1cGVyLmNhbGwodGhpcykgfHwgdGhpcztcbiAgICAgICAgX3RoaXMuZDNDb250ZXh0ID0gZDNDb250ZXh0O1xuICAgICAgICBfdGhpcy5ldmVudCA9IGQzQ29udGV4dC5kaXNwYXRjaChsYXlvdXRfMS5FdmVudFR5cGVbbGF5b3V0XzEuRXZlbnRUeXBlLnN0YXJ0XSwgbGF5b3V0XzEuRXZlbnRUeXBlW2xheW91dF8xLkV2ZW50VHlwZS50aWNrXSwgbGF5b3V0XzEuRXZlbnRUeXBlW2xheW91dF8xLkV2ZW50VHlwZS5lbmRdKTtcbiAgICAgICAgdmFyIGQzbGF5b3V0ID0gX3RoaXM7XG4gICAgICAgIHZhciBkcmFnO1xuICAgICAgICBfdGhpcy5kcmFnID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgaWYgKCFkcmFnKSB7XG4gICAgICAgICAgICAgICAgdmFyIGRyYWcgPSBkM0NvbnRleHQuZHJhZygpXG4gICAgICAgICAgICAgICAgICAgIC5zdWJqZWN0KGxheW91dF8xLkxheW91dC5kcmFnT3JpZ2luKVxuICAgICAgICAgICAgICAgICAgICAub24oXCJzdGFydC5kM2FkYXB0b3JcIiwgbGF5b3V0XzEuTGF5b3V0LmRyYWdTdGFydClcbiAgICAgICAgICAgICAgICAgICAgLm9uKFwiZHJhZy5kM2FkYXB0b3JcIiwgZnVuY3Rpb24gKGQpIHtcbiAgICAgICAgICAgICAgICAgICAgbGF5b3V0XzEuTGF5b3V0LmRyYWcoZCwgZDNDb250ZXh0LmV2ZW50KTtcbiAgICAgICAgICAgICAgICAgICAgZDNsYXlvdXQucmVzdW1lKCk7XG4gICAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgICAgICAgICAgLm9uKFwiZW5kLmQzYWRhcHRvclwiLCBsYXlvdXRfMS5MYXlvdXQuZHJhZ0VuZCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoIWFyZ3VtZW50cy5sZW5ndGgpXG4gICAgICAgICAgICAgICAgcmV0dXJuIGRyYWc7XG4gICAgICAgICAgICBhcmd1bWVudHNbMF0uY2FsbChkcmFnKTtcbiAgICAgICAgfTtcbiAgICAgICAgcmV0dXJuIF90aGlzO1xuICAgIH1cbiAgICBEM1N0eWxlTGF5b3V0QWRhcHRvci5wcm90b3R5cGUudHJpZ2dlciA9IGZ1bmN0aW9uIChlKSB7XG4gICAgICAgIHZhciBkM2V2ZW50ID0geyB0eXBlOiBsYXlvdXRfMS5FdmVudFR5cGVbZS50eXBlXSwgYWxwaGE6IGUuYWxwaGEsIHN0cmVzczogZS5zdHJlc3MgfTtcbiAgICAgICAgdGhpcy5ldmVudC5jYWxsKGQzZXZlbnQudHlwZSwgZDNldmVudCk7XG4gICAgfTtcbiAgICBEM1N0eWxlTGF5b3V0QWRhcHRvci5wcm90b3R5cGUua2ljayA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgdmFyIHQgPSB0aGlzLmQzQ29udGV4dC50aW1lcihmdW5jdGlvbiAoKSB7IHJldHVybiBfc3VwZXIucHJvdG90eXBlLnRpY2suY2FsbChfdGhpcykgJiYgdC5zdG9wKCk7IH0pO1xuICAgIH07XG4gICAgRDNTdHlsZUxheW91dEFkYXB0b3IucHJvdG90eXBlLm9uID0gZnVuY3Rpb24gKGV2ZW50VHlwZSwgbGlzdGVuZXIpIHtcbiAgICAgICAgaWYgKHR5cGVvZiBldmVudFR5cGUgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICB0aGlzLmV2ZW50Lm9uKGV2ZW50VHlwZSwgbGlzdGVuZXIpO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgdGhpcy5ldmVudC5vbihsYXlvdXRfMS5FdmVudFR5cGVbZXZlbnRUeXBlXSwgbGlzdGVuZXIpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH07XG4gICAgcmV0dXJuIEQzU3R5bGVMYXlvdXRBZGFwdG9yO1xufShsYXlvdXRfMS5MYXlvdXQpKTtcbmV4cG9ydHMuRDNTdHlsZUxheW91dEFkYXB0b3IgPSBEM1N0eWxlTGF5b3V0QWRhcHRvcjtcbi8vIyBzb3VyY2VNYXBwaW5nVVJMPWRhdGE6YXBwbGljYXRpb24vanNvbjtiYXNlNjQsZXlKMlpYSnphVzl1SWpvekxDSm1hV3hsSWpvaVpETjJOR0ZrWVhCMGIzSXVhbk1pTENKemIzVnlZMlZTYjI5MElqb2lJaXdpYzI5MWNtTmxjeUk2V3lJdUxpOHVMaTlYWldKRGIyeGhMM055WXk5a00zWTBZV1JoY0hSdmNpNTBjeUpkTENKdVlXMWxjeUk2VzEwc0ltMWhjSEJwYm1keklqb2lPenM3T3pzN096czdPenM3T3pzN1FVRkhRU3h0UTBGQmFVUTdRVUZWYWtRN1NVRkJNRU1zZDBOQlFVMDdTVUZwUWpWRExEaENRVUZ2UWl4VFFVRnZRanRSUVVGNFF5eFpRVU5KTEdsQ1FVRlBMRk5CZVVKV08xRkJNVUp0UWl4bFFVRlRMRWRCUVZRc1UwRkJVeXhEUVVGWE8xRkJSWEJETEV0QlFVa3NRMEZCUXl4TFFVRkxMRWRCUVVjc1UwRkJVeXhEUVVGRExGRkJRVkVzUTBGQlF5eHJRa0ZCVXl4RFFVRkRMR3RDUVVGVExFTkJRVU1zUzBGQlN5eERRVUZETEVWQlFVVXNhMEpCUVZNc1EwRkJReXhyUWtGQlV5eERRVUZETEVsQlFVa3NRMEZCUXl4RlFVRkZMR3RDUVVGVExFTkJRVU1zYTBKQlFWTXNRMEZCUXl4SFFVRkhMRU5CUVVNc1EwRkJReXhEUVVGRE8xRkJSMnBJTEVsQlFVa3NVVUZCVVN4SFFVRkhMRXRCUVVrc1EwRkJRenRSUVVOd1FpeEpRVUZKTEVsQlFVa3NRMEZCUXp0UlFVTlVMRXRCUVVrc1EwRkJReXhKUVVGSkxFZEJRVWM3V1VGRFVpeEpRVUZKTEVOQlFVTXNTVUZCU1N4RlFVRkZPMmRDUVVOUUxFbEJRVWtzU1VGQlNTeEhRVUZITEZOQlFWTXNRMEZCUXl4SlFVRkpMRVZCUVVVN2NVSkJRM1JDTEU5QlFVOHNRMEZCUXl4bFFVRk5MRU5CUVVNc1ZVRkJWU3hEUVVGRE8zRkNRVU14UWl4RlFVRkZMRU5CUVVNc2FVSkJRV2xDTEVWQlFVVXNaVUZCVFN4RFFVRkRMRk5CUVZNc1EwRkJRenR4UWtGRGRrTXNSVUZCUlN4RFFVRkRMR2RDUVVGblFpeEZRVUZGTEZWQlFVRXNRMEZCUXp0dlFrRkRia0lzWlVGQlRTeERRVUZETEVsQlFVa3NRMEZCVFN4RFFVRkRMRVZCUVVVc1UwRkJVeXhEUVVGRExFdEJRVXNzUTBGQlF5eERRVUZETzI5Q1FVTnlReXhSUVVGUkxFTkJRVU1zVFVGQlRTeEZRVUZGTEVOQlFVTTdaMEpCUTNSQ0xFTkJRVU1zUTBGQlF6dHhRa0ZEUkN4RlFVRkZMRU5CUVVNc1pVRkJaU3hGUVVGRkxHVkJRVTBzUTBGQlF5eFBRVUZQTEVOQlFVTXNRMEZCUXp0aFFVTTFRenRaUVVWRUxFbEJRVWtzUTBGQlF5eFRRVUZUTEVOQlFVTXNUVUZCVFR0blFrRkJSU3hQUVVGUExFbEJRVWtzUTBGQlF6dFpRVXR1UXl4VFFVRlRMRU5CUVVNc1EwRkJReXhEUVVGRExFTkJRVU1zU1VGQlNTeERRVUZETEVsQlFVa3NRMEZCUXl4RFFVRkRPMUZCUXpWQ0xFTkJRVU1zUTBGQlFUczdTVUZEVEN4RFFVRkRPMGxCZWtORUxITkRRVUZQTEVkQlFWQXNWVUZCVVN4RFFVRlJPMUZCUTFvc1NVRkJTU3hQUVVGUExFZEJRVWNzUlVGQlJTeEpRVUZKTEVWQlFVVXNhMEpCUVZNc1EwRkJReXhEUVVGRExFTkJRVU1zU1VGQlNTeERRVUZETEVWQlFVVXNTMEZCU3l4RlFVRkZMRU5CUVVNc1EwRkJReXhMUVVGTExFVkJRVVVzVFVGQlRTeEZRVUZGTEVOQlFVTXNRMEZCUXl4TlFVRk5MRVZCUVVVc1EwRkJRenRSUVVjMVJTeEpRVUZKTEVOQlFVTXNTMEZCU3l4RFFVRkRMRWxCUVVrc1EwRkJReXhQUVVGUExFTkJRVU1zU1VGQlNTeEZRVUZQTEU5QlFVOHNRMEZCUXl4RFFVRkRPMGxCUTJoRUxFTkJRVU03U1VGSFJDeHRRMEZCU1N4SFFVRktPMUZCUVVFc2FVSkJSVU03VVVGRVJ5eEpRVUZKTEVOQlFVTXNSMEZCUnl4SlFVRkpMRU5CUVVNc1UwRkJVeXhEUVVGRExFdEJRVXNzUTBGQlF5eGpRVUZOTEU5QlFVRXNhVUpCUVUwc1NVRkJTU3haUVVGRkxFbEJRVWtzUTBGQlF5eERRVUZETEVsQlFVa3NSVUZCUlN4RlFVRjRRaXhEUVVGM1FpeERRVUZETEVOQlFVTTdTVUZEYWtVc1EwRkJRenRKUVd0RFJDeHBRMEZCUlN4SFFVRkdMRlZCUVVjc1UwRkJOa0lzUlVGQlJTeFJRVUZ2UWp0UlFVTnNSQ3hKUVVGSkxFOUJRVThzVTBGQlV5eExRVUZMTEZGQlFWRXNSVUZCUlR0WlFVTXZRaXhKUVVGSkxFTkJRVU1zUzBGQlN5eERRVUZETEVWQlFVVXNRMEZCUXl4VFFVRlRMRVZCUVVVc1VVRkJVU3hEUVVGRExFTkJRVU03VTBGRGRFTTdZVUZCVFR0WlFVTklMRWxCUVVrc1EwRkJReXhMUVVGTExFTkJRVU1zUlVGQlJTeERRVUZETEd0Q1FVRlRMRU5CUVVNc1UwRkJVeXhEUVVGRExFVkJRVVVzVVVGQlVTeERRVUZETEVOQlFVTTdVMEZEYWtRN1VVRkRSQ3hQUVVGUExFbEJRVWtzUTBGQlF6dEpRVU5vUWl4RFFVRkRPMGxCUTB3c01rSkJRVU03UVVGQlJDeERRVUZETEVGQmRFUkVMRU5CUVRCRExHVkJRVTBzUjBGelJDOURPMEZCZEVSWkxHOUVRVUZ2UWlKOSIsIlwidXNlIHN0cmljdFwiO1xuT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsIFwiX19lc01vZHVsZVwiLCB7IHZhbHVlOiB0cnVlIH0pO1xudmFyIExvY2tzID0gKGZ1bmN0aW9uICgpIHtcbiAgICBmdW5jdGlvbiBMb2NrcygpIHtcbiAgICAgICAgdGhpcy5sb2NrcyA9IHt9O1xuICAgIH1cbiAgICBMb2Nrcy5wcm90b3R5cGUuYWRkID0gZnVuY3Rpb24gKGlkLCB4KSB7XG4gICAgICAgIHRoaXMubG9ja3NbaWRdID0geDtcbiAgICB9O1xuICAgIExvY2tzLnByb3RvdHlwZS5jbGVhciA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdGhpcy5sb2NrcyA9IHt9O1xuICAgIH07XG4gICAgTG9ja3MucHJvdG90eXBlLmlzRW1wdHkgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGZvciAodmFyIGwgaW4gdGhpcy5sb2NrcylcbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgfTtcbiAgICBMb2Nrcy5wcm90b3R5cGUuYXBwbHkgPSBmdW5jdGlvbiAoZikge1xuICAgICAgICBmb3IgKHZhciBsIGluIHRoaXMubG9ja3MpIHtcbiAgICAgICAgICAgIGYoTnVtYmVyKGwpLCB0aGlzLmxvY2tzW2xdKTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgcmV0dXJuIExvY2tzO1xufSgpKTtcbmV4cG9ydHMuTG9ja3MgPSBMb2NrcztcbnZhciBEZXNjZW50ID0gKGZ1bmN0aW9uICgpIHtcbiAgICBmdW5jdGlvbiBEZXNjZW50KHgsIEQsIEcpIHtcbiAgICAgICAgaWYgKEcgPT09IHZvaWQgMCkgeyBHID0gbnVsbDsgfVxuICAgICAgICB0aGlzLkQgPSBEO1xuICAgICAgICB0aGlzLkcgPSBHO1xuICAgICAgICB0aGlzLnRocmVzaG9sZCA9IDAuMDAwMTtcbiAgICAgICAgdGhpcy5udW1HcmlkU25hcE5vZGVzID0gMDtcbiAgICAgICAgdGhpcy5zbmFwR3JpZFNpemUgPSAxMDA7XG4gICAgICAgIHRoaXMuc25hcFN0cmVuZ3RoID0gMTAwMDtcbiAgICAgICAgdGhpcy5zY2FsZVNuYXBCeU1heEggPSBmYWxzZTtcbiAgICAgICAgdGhpcy5yYW5kb20gPSBuZXcgUHNldWRvUmFuZG9tKCk7XG4gICAgICAgIHRoaXMucHJvamVjdCA9IG51bGw7XG4gICAgICAgIHRoaXMueCA9IHg7XG4gICAgICAgIHRoaXMuayA9IHgubGVuZ3RoO1xuICAgICAgICB2YXIgbiA9IHRoaXMubiA9IHhbMF0ubGVuZ3RoO1xuICAgICAgICB0aGlzLkggPSBuZXcgQXJyYXkodGhpcy5rKTtcbiAgICAgICAgdGhpcy5nID0gbmV3IEFycmF5KHRoaXMuayk7XG4gICAgICAgIHRoaXMuSGQgPSBuZXcgQXJyYXkodGhpcy5rKTtcbiAgICAgICAgdGhpcy5hID0gbmV3IEFycmF5KHRoaXMuayk7XG4gICAgICAgIHRoaXMuYiA9IG5ldyBBcnJheSh0aGlzLmspO1xuICAgICAgICB0aGlzLmMgPSBuZXcgQXJyYXkodGhpcy5rKTtcbiAgICAgICAgdGhpcy5kID0gbmV3IEFycmF5KHRoaXMuayk7XG4gICAgICAgIHRoaXMuZSA9IG5ldyBBcnJheSh0aGlzLmspO1xuICAgICAgICB0aGlzLmlhID0gbmV3IEFycmF5KHRoaXMuayk7XG4gICAgICAgIHRoaXMuaWIgPSBuZXcgQXJyYXkodGhpcy5rKTtcbiAgICAgICAgdGhpcy54dG1wID0gbmV3IEFycmF5KHRoaXMuayk7XG4gICAgICAgIHRoaXMubG9ja3MgPSBuZXcgTG9ja3MoKTtcbiAgICAgICAgdGhpcy5taW5EID0gTnVtYmVyLk1BWF9WQUxVRTtcbiAgICAgICAgdmFyIGkgPSBuLCBqO1xuICAgICAgICB3aGlsZSAoaS0tKSB7XG4gICAgICAgICAgICBqID0gbjtcbiAgICAgICAgICAgIHdoaWxlICgtLWogPiBpKSB7XG4gICAgICAgICAgICAgICAgdmFyIGQgPSBEW2ldW2pdO1xuICAgICAgICAgICAgICAgIGlmIChkID4gMCAmJiBkIDwgdGhpcy5taW5EKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMubWluRCA9IGQ7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGlmICh0aGlzLm1pbkQgPT09IE51bWJlci5NQVhfVkFMVUUpXG4gICAgICAgICAgICB0aGlzLm1pbkQgPSAxO1xuICAgICAgICBpID0gdGhpcy5rO1xuICAgICAgICB3aGlsZSAoaS0tKSB7XG4gICAgICAgICAgICB0aGlzLmdbaV0gPSBuZXcgQXJyYXkobik7XG4gICAgICAgICAgICB0aGlzLkhbaV0gPSBuZXcgQXJyYXkobik7XG4gICAgICAgICAgICBqID0gbjtcbiAgICAgICAgICAgIHdoaWxlIChqLS0pIHtcbiAgICAgICAgICAgICAgICB0aGlzLkhbaV1bal0gPSBuZXcgQXJyYXkobik7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLkhkW2ldID0gbmV3IEFycmF5KG4pO1xuICAgICAgICAgICAgdGhpcy5hW2ldID0gbmV3IEFycmF5KG4pO1xuICAgICAgICAgICAgdGhpcy5iW2ldID0gbmV3IEFycmF5KG4pO1xuICAgICAgICAgICAgdGhpcy5jW2ldID0gbmV3IEFycmF5KG4pO1xuICAgICAgICAgICAgdGhpcy5kW2ldID0gbmV3IEFycmF5KG4pO1xuICAgICAgICAgICAgdGhpcy5lW2ldID0gbmV3IEFycmF5KG4pO1xuICAgICAgICAgICAgdGhpcy5pYVtpXSA9IG5ldyBBcnJheShuKTtcbiAgICAgICAgICAgIHRoaXMuaWJbaV0gPSBuZXcgQXJyYXkobik7XG4gICAgICAgICAgICB0aGlzLnh0bXBbaV0gPSBuZXcgQXJyYXkobik7XG4gICAgICAgIH1cbiAgICB9XG4gICAgRGVzY2VudC5jcmVhdGVTcXVhcmVNYXRyaXggPSBmdW5jdGlvbiAobiwgZikge1xuICAgICAgICB2YXIgTSA9IG5ldyBBcnJheShuKTtcbiAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBuOyArK2kpIHtcbiAgICAgICAgICAgIE1baV0gPSBuZXcgQXJyYXkobik7XG4gICAgICAgICAgICBmb3IgKHZhciBqID0gMDsgaiA8IG47ICsraikge1xuICAgICAgICAgICAgICAgIE1baV1bal0gPSBmKGksIGopO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiBNO1xuICAgIH07XG4gICAgRGVzY2VudC5wcm90b3R5cGUub2Zmc2V0RGlyID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICB2YXIgdSA9IG5ldyBBcnJheSh0aGlzLmspO1xuICAgICAgICB2YXIgbCA9IDA7XG4gICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgdGhpcy5rOyArK2kpIHtcbiAgICAgICAgICAgIHZhciB4ID0gdVtpXSA9IHRoaXMucmFuZG9tLmdldE5leHRCZXR3ZWVuKDAuMDEsIDEpIC0gMC41O1xuICAgICAgICAgICAgbCArPSB4ICogeDtcbiAgICAgICAgfVxuICAgICAgICBsID0gTWF0aC5zcXJ0KGwpO1xuICAgICAgICByZXR1cm4gdS5tYXAoZnVuY3Rpb24gKHgpIHsgcmV0dXJuIHggKj0gX3RoaXMubWluRCAvIGw7IH0pO1xuICAgIH07XG4gICAgRGVzY2VudC5wcm90b3R5cGUuY29tcHV0ZURlcml2YXRpdmVzID0gZnVuY3Rpb24gKHgpIHtcbiAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgdmFyIG4gPSB0aGlzLm47XG4gICAgICAgIGlmIChuIDwgMSlcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgdmFyIGk7XG4gICAgICAgIHZhciBkID0gbmV3IEFycmF5KHRoaXMuayk7XG4gICAgICAgIHZhciBkMiA9IG5ldyBBcnJheSh0aGlzLmspO1xuICAgICAgICB2YXIgSHV1ID0gbmV3IEFycmF5KHRoaXMuayk7XG4gICAgICAgIHZhciBtYXhIID0gMDtcbiAgICAgICAgZm9yICh2YXIgdV8xID0gMDsgdV8xIDwgbjsgKyt1XzEpIHtcbiAgICAgICAgICAgIGZvciAoaSA9IDA7IGkgPCB0aGlzLms7ICsraSlcbiAgICAgICAgICAgICAgICBIdXVbaV0gPSB0aGlzLmdbaV1bdV8xXSA9IDA7XG4gICAgICAgICAgICBmb3IgKHZhciB2ID0gMDsgdiA8IG47ICsrdikge1xuICAgICAgICAgICAgICAgIGlmICh1XzEgPT09IHYpXG4gICAgICAgICAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgICAgICAgIHZhciBtYXhEaXNwbGFjZXMgPSBuO1xuICAgICAgICAgICAgICAgIHZhciBkaXN0YW5jZVNxdWFyZWQgPSAwO1xuICAgICAgICAgICAgICAgIHdoaWxlIChtYXhEaXNwbGFjZXMtLSkge1xuICAgICAgICAgICAgICAgICAgICBkaXN0YW5jZVNxdWFyZWQgPSAwO1xuICAgICAgICAgICAgICAgICAgICBmb3IgKGkgPSAwOyBpIDwgdGhpcy5rOyArK2kpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBkeF8xID0gZFtpXSA9IHhbaV1bdV8xXSAtIHhbaV1bdl07XG4gICAgICAgICAgICAgICAgICAgICAgICBkaXN0YW5jZVNxdWFyZWQgKz0gZDJbaV0gPSBkeF8xICogZHhfMTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBpZiAoZGlzdGFuY2VTcXVhcmVkID4gMWUtOSlcbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICB2YXIgcmQgPSB0aGlzLm9mZnNldERpcigpO1xuICAgICAgICAgICAgICAgICAgICBmb3IgKGkgPSAwOyBpIDwgdGhpcy5rOyArK2kpXG4gICAgICAgICAgICAgICAgICAgICAgICB4W2ldW3ZdICs9IHJkW2ldO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB2YXIgZGlzdGFuY2UgPSBNYXRoLnNxcnQoZGlzdGFuY2VTcXVhcmVkKTtcbiAgICAgICAgICAgICAgICB2YXIgaWRlYWxEaXN0YW5jZSA9IHRoaXMuRFt1XzFdW3ZdO1xuICAgICAgICAgICAgICAgIHZhciB3ZWlnaHQgPSB0aGlzLkcgIT0gbnVsbCA/IHRoaXMuR1t1XzFdW3ZdIDogMTtcbiAgICAgICAgICAgICAgICBpZiAod2VpZ2h0ID4gMSAmJiBkaXN0YW5jZSA+IGlkZWFsRGlzdGFuY2UgfHwgIWlzRmluaXRlKGlkZWFsRGlzdGFuY2UpKSB7XG4gICAgICAgICAgICAgICAgICAgIGZvciAoaSA9IDA7IGkgPCB0aGlzLms7ICsraSlcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuSFtpXVt1XzFdW3ZdID0gMDtcbiAgICAgICAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmICh3ZWlnaHQgPiAxKSB7XG4gICAgICAgICAgICAgICAgICAgIHdlaWdodCA9IDE7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHZhciBpZGVhbERpc3RTcXVhcmVkID0gaWRlYWxEaXN0YW5jZSAqIGlkZWFsRGlzdGFuY2UsIGdzID0gMiAqIHdlaWdodCAqIChkaXN0YW5jZSAtIGlkZWFsRGlzdGFuY2UpIC8gKGlkZWFsRGlzdFNxdWFyZWQgKiBkaXN0YW5jZSksIGRpc3RhbmNlQ3ViZWQgPSBkaXN0YW5jZVNxdWFyZWQgKiBkaXN0YW5jZSwgaHMgPSAyICogLXdlaWdodCAvIChpZGVhbERpc3RTcXVhcmVkICogZGlzdGFuY2VDdWJlZCk7XG4gICAgICAgICAgICAgICAgaWYgKCFpc0Zpbml0ZShncykpXG4gICAgICAgICAgICAgICAgICAgIGNvbnNvbGUubG9nKGdzKTtcbiAgICAgICAgICAgICAgICBmb3IgKGkgPSAwOyBpIDwgdGhpcy5rOyArK2kpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5nW2ldW3VfMV0gKz0gZFtpXSAqIGdzO1xuICAgICAgICAgICAgICAgICAgICBIdXVbaV0gLT0gdGhpcy5IW2ldW3VfMV1bdl0gPSBocyAqICgyICogZGlzdGFuY2VDdWJlZCArIGlkZWFsRGlzdGFuY2UgKiAoZDJbaV0gLSBkaXN0YW5jZVNxdWFyZWQpKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBmb3IgKGkgPSAwOyBpIDwgdGhpcy5rOyArK2kpXG4gICAgICAgICAgICAgICAgbWF4SCA9IE1hdGgubWF4KG1heEgsIHRoaXMuSFtpXVt1XzFdW3VfMV0gPSBIdXVbaV0pO1xuICAgICAgICB9XG4gICAgICAgIHZhciByID0gdGhpcy5zbmFwR3JpZFNpemUgLyAyO1xuICAgICAgICB2YXIgZyA9IHRoaXMuc25hcEdyaWRTaXplO1xuICAgICAgICB2YXIgdyA9IHRoaXMuc25hcFN0cmVuZ3RoO1xuICAgICAgICB2YXIgayA9IHcgLyAociAqIHIpO1xuICAgICAgICB2YXIgbnVtTm9kZXMgPSB0aGlzLm51bUdyaWRTbmFwTm9kZXM7XG4gICAgICAgIGZvciAodmFyIHUgPSAwOyB1IDwgbnVtTm9kZXM7ICsrdSkge1xuICAgICAgICAgICAgZm9yIChpID0gMDsgaSA8IHRoaXMuazsgKytpKSB7XG4gICAgICAgICAgICAgICAgdmFyIHhpdSA9IHRoaXMueFtpXVt1XTtcbiAgICAgICAgICAgICAgICB2YXIgbSA9IHhpdSAvIGc7XG4gICAgICAgICAgICAgICAgdmFyIGYgPSBtICUgMTtcbiAgICAgICAgICAgICAgICB2YXIgcSA9IG0gLSBmO1xuICAgICAgICAgICAgICAgIHZhciBhID0gTWF0aC5hYnMoZik7XG4gICAgICAgICAgICAgICAgdmFyIGR4ID0gKGEgPD0gMC41KSA/IHhpdSAtIHEgKiBnIDpcbiAgICAgICAgICAgICAgICAgICAgKHhpdSA+IDApID8geGl1IC0gKHEgKyAxKSAqIGcgOiB4aXUgLSAocSAtIDEpICogZztcbiAgICAgICAgICAgICAgICBpZiAoLXIgPCBkeCAmJiBkeCA8PSByKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmICh0aGlzLnNjYWxlU25hcEJ5TWF4SCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5nW2ldW3VdICs9IG1heEggKiBrICogZHg7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLkhbaV1bdV1bdV0gKz0gbWF4SCAqIGs7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmdbaV1bdV0gKz0gayAqIGR4O1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5IW2ldW3VdW3VdICs9IGs7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKCF0aGlzLmxvY2tzLmlzRW1wdHkoKSkge1xuICAgICAgICAgICAgdGhpcy5sb2Nrcy5hcHBseShmdW5jdGlvbiAodSwgcCkge1xuICAgICAgICAgICAgICAgIGZvciAoaSA9IDA7IGkgPCBfdGhpcy5rOyArK2kpIHtcbiAgICAgICAgICAgICAgICAgICAgX3RoaXMuSFtpXVt1XVt1XSArPSBtYXhIO1xuICAgICAgICAgICAgICAgICAgICBfdGhpcy5nW2ldW3VdIC09IG1heEggKiAocFtpXSAtIHhbaV1bdV0pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBEZXNjZW50LmRvdFByb2QgPSBmdW5jdGlvbiAoYSwgYikge1xuICAgICAgICB2YXIgeCA9IDAsIGkgPSBhLmxlbmd0aDtcbiAgICAgICAgd2hpbGUgKGktLSlcbiAgICAgICAgICAgIHggKz0gYVtpXSAqIGJbaV07XG4gICAgICAgIHJldHVybiB4O1xuICAgIH07XG4gICAgRGVzY2VudC5yaWdodE11bHRpcGx5ID0gZnVuY3Rpb24gKG0sIHYsIHIpIHtcbiAgICAgICAgdmFyIGkgPSBtLmxlbmd0aDtcbiAgICAgICAgd2hpbGUgKGktLSlcbiAgICAgICAgICAgIHJbaV0gPSBEZXNjZW50LmRvdFByb2QobVtpXSwgdik7XG4gICAgfTtcbiAgICBEZXNjZW50LnByb3RvdHlwZS5jb21wdXRlU3RlcFNpemUgPSBmdW5jdGlvbiAoZCkge1xuICAgICAgICB2YXIgbnVtZXJhdG9yID0gMCwgZGVub21pbmF0b3IgPSAwO1xuICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IHRoaXMuazsgKytpKSB7XG4gICAgICAgICAgICBudW1lcmF0b3IgKz0gRGVzY2VudC5kb3RQcm9kKHRoaXMuZ1tpXSwgZFtpXSk7XG4gICAgICAgICAgICBEZXNjZW50LnJpZ2h0TXVsdGlwbHkodGhpcy5IW2ldLCBkW2ldLCB0aGlzLkhkW2ldKTtcbiAgICAgICAgICAgIGRlbm9taW5hdG9yICs9IERlc2NlbnQuZG90UHJvZChkW2ldLCB0aGlzLkhkW2ldKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoZGVub21pbmF0b3IgPT09IDAgfHwgIWlzRmluaXRlKGRlbm9taW5hdG9yKSlcbiAgICAgICAgICAgIHJldHVybiAwO1xuICAgICAgICByZXR1cm4gMSAqIG51bWVyYXRvciAvIGRlbm9taW5hdG9yO1xuICAgIH07XG4gICAgRGVzY2VudC5wcm90b3R5cGUucmVkdWNlU3RyZXNzID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB0aGlzLmNvbXB1dGVEZXJpdmF0aXZlcyh0aGlzLngpO1xuICAgICAgICB2YXIgYWxwaGEgPSB0aGlzLmNvbXB1dGVTdGVwU2l6ZSh0aGlzLmcpO1xuICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IHRoaXMuazsgKytpKSB7XG4gICAgICAgICAgICB0aGlzLnRha2VEZXNjZW50U3RlcCh0aGlzLnhbaV0sIHRoaXMuZ1tpXSwgYWxwaGEpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzLmNvbXB1dGVTdHJlc3MoKTtcbiAgICB9O1xuICAgIERlc2NlbnQuY29weSA9IGZ1bmN0aW9uIChhLCBiKSB7XG4gICAgICAgIHZhciBtID0gYS5sZW5ndGgsIG4gPSBiWzBdLmxlbmd0aDtcbiAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBtOyArK2kpIHtcbiAgICAgICAgICAgIGZvciAodmFyIGogPSAwOyBqIDwgbjsgKytqKSB7XG4gICAgICAgICAgICAgICAgYltpXVtqXSA9IGFbaV1bal07XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9O1xuICAgIERlc2NlbnQucHJvdG90eXBlLnN0ZXBBbmRQcm9qZWN0ID0gZnVuY3Rpb24gKHgwLCByLCBkLCBzdGVwU2l6ZSkge1xuICAgICAgICBEZXNjZW50LmNvcHkoeDAsIHIpO1xuICAgICAgICB0aGlzLnRha2VEZXNjZW50U3RlcChyWzBdLCBkWzBdLCBzdGVwU2l6ZSk7XG4gICAgICAgIGlmICh0aGlzLnByb2plY3QpXG4gICAgICAgICAgICB0aGlzLnByb2plY3RbMF0oeDBbMF0sIHgwWzFdLCByWzBdKTtcbiAgICAgICAgdGhpcy50YWtlRGVzY2VudFN0ZXAoclsxXSwgZFsxXSwgc3RlcFNpemUpO1xuICAgICAgICBpZiAodGhpcy5wcm9qZWN0KVxuICAgICAgICAgICAgdGhpcy5wcm9qZWN0WzFdKHJbMF0sIHgwWzFdLCByWzFdKTtcbiAgICAgICAgZm9yICh2YXIgaSA9IDI7IGkgPCB0aGlzLms7IGkrKylcbiAgICAgICAgICAgIHRoaXMudGFrZURlc2NlbnRTdGVwKHJbaV0sIGRbaV0sIHN0ZXBTaXplKTtcbiAgICB9O1xuICAgIERlc2NlbnQubUFwcGx5ID0gZnVuY3Rpb24gKG0sIG4sIGYpIHtcbiAgICAgICAgdmFyIGkgPSBtO1xuICAgICAgICB3aGlsZSAoaS0tID4gMCkge1xuICAgICAgICAgICAgdmFyIGogPSBuO1xuICAgICAgICAgICAgd2hpbGUgKGotLSA+IDApXG4gICAgICAgICAgICAgICAgZihpLCBqKTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgRGVzY2VudC5wcm90b3R5cGUubWF0cml4QXBwbHkgPSBmdW5jdGlvbiAoZikge1xuICAgICAgICBEZXNjZW50Lm1BcHBseSh0aGlzLmssIHRoaXMubiwgZik7XG4gICAgfTtcbiAgICBEZXNjZW50LnByb3RvdHlwZS5jb21wdXRlTmV4dFBvc2l0aW9uID0gZnVuY3Rpb24gKHgwLCByKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgICAgIHRoaXMuY29tcHV0ZURlcml2YXRpdmVzKHgwKTtcbiAgICAgICAgdmFyIGFscGhhID0gdGhpcy5jb21wdXRlU3RlcFNpemUodGhpcy5nKTtcbiAgICAgICAgdGhpcy5zdGVwQW5kUHJvamVjdCh4MCwgciwgdGhpcy5nLCBhbHBoYSk7XG4gICAgICAgIGlmICh0aGlzLnByb2plY3QpIHtcbiAgICAgICAgICAgIHRoaXMubWF0cml4QXBwbHkoZnVuY3Rpb24gKGksIGopIHsgcmV0dXJuIF90aGlzLmVbaV1bal0gPSB4MFtpXVtqXSAtIHJbaV1bal07IH0pO1xuICAgICAgICAgICAgdmFyIGJldGEgPSB0aGlzLmNvbXB1dGVTdGVwU2l6ZSh0aGlzLmUpO1xuICAgICAgICAgICAgYmV0YSA9IE1hdGgubWF4KDAuMiwgTWF0aC5taW4oYmV0YSwgMSkpO1xuICAgICAgICAgICAgdGhpcy5zdGVwQW5kUHJvamVjdCh4MCwgciwgdGhpcy5lLCBiZXRhKTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgRGVzY2VudC5wcm90b3R5cGUucnVuID0gZnVuY3Rpb24gKGl0ZXJhdGlvbnMpIHtcbiAgICAgICAgdmFyIHN0cmVzcyA9IE51bWJlci5NQVhfVkFMVUUsIGNvbnZlcmdlZCA9IGZhbHNlO1xuICAgICAgICB3aGlsZSAoIWNvbnZlcmdlZCAmJiBpdGVyYXRpb25zLS0gPiAwKSB7XG4gICAgICAgICAgICB2YXIgcyA9IHRoaXMucnVuZ2VLdXR0YSgpO1xuICAgICAgICAgICAgY29udmVyZ2VkID0gTWF0aC5hYnMoc3RyZXNzIC8gcyAtIDEpIDwgdGhpcy50aHJlc2hvbGQ7XG4gICAgICAgICAgICBzdHJlc3MgPSBzO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBzdHJlc3M7XG4gICAgfTtcbiAgICBEZXNjZW50LnByb3RvdHlwZS5ydW5nZUt1dHRhID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICB0aGlzLmNvbXB1dGVOZXh0UG9zaXRpb24odGhpcy54LCB0aGlzLmEpO1xuICAgICAgICBEZXNjZW50Lm1pZCh0aGlzLngsIHRoaXMuYSwgdGhpcy5pYSk7XG4gICAgICAgIHRoaXMuY29tcHV0ZU5leHRQb3NpdGlvbih0aGlzLmlhLCB0aGlzLmIpO1xuICAgICAgICBEZXNjZW50Lm1pZCh0aGlzLngsIHRoaXMuYiwgdGhpcy5pYik7XG4gICAgICAgIHRoaXMuY29tcHV0ZU5leHRQb3NpdGlvbih0aGlzLmliLCB0aGlzLmMpO1xuICAgICAgICB0aGlzLmNvbXB1dGVOZXh0UG9zaXRpb24odGhpcy5jLCB0aGlzLmQpO1xuICAgICAgICB2YXIgZGlzcCA9IDA7XG4gICAgICAgIHRoaXMubWF0cml4QXBwbHkoZnVuY3Rpb24gKGksIGopIHtcbiAgICAgICAgICAgIHZhciB4ID0gKF90aGlzLmFbaV1bal0gKyAyLjAgKiBfdGhpcy5iW2ldW2pdICsgMi4wICogX3RoaXMuY1tpXVtqXSArIF90aGlzLmRbaV1bal0pIC8gNi4wLCBkID0gX3RoaXMueFtpXVtqXSAtIHg7XG4gICAgICAgICAgICBkaXNwICs9IGQgKiBkO1xuICAgICAgICAgICAgX3RoaXMueFtpXVtqXSA9IHg7XG4gICAgICAgIH0pO1xuICAgICAgICByZXR1cm4gZGlzcDtcbiAgICB9O1xuICAgIERlc2NlbnQubWlkID0gZnVuY3Rpb24gKGEsIGIsIG0pIHtcbiAgICAgICAgRGVzY2VudC5tQXBwbHkoYS5sZW5ndGgsIGFbMF0ubGVuZ3RoLCBmdW5jdGlvbiAoaSwgaikge1xuICAgICAgICAgICAgcmV0dXJuIG1baV1bal0gPSBhW2ldW2pdICsgKGJbaV1bal0gLSBhW2ldW2pdKSAvIDIuMDtcbiAgICAgICAgfSk7XG4gICAgfTtcbiAgICBEZXNjZW50LnByb3RvdHlwZS50YWtlRGVzY2VudFN0ZXAgPSBmdW5jdGlvbiAoeCwgZCwgc3RlcFNpemUpIHtcbiAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCB0aGlzLm47ICsraSkge1xuICAgICAgICAgICAgeFtpXSA9IHhbaV0gLSBzdGVwU2l6ZSAqIGRbaV07XG4gICAgICAgIH1cbiAgICB9O1xuICAgIERlc2NlbnQucHJvdG90eXBlLmNvbXB1dGVTdHJlc3MgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBzdHJlc3MgPSAwO1xuICAgICAgICBmb3IgKHZhciB1ID0gMCwgbk1pbnVzMSA9IHRoaXMubiAtIDE7IHUgPCBuTWludXMxOyArK3UpIHtcbiAgICAgICAgICAgIGZvciAodmFyIHYgPSB1ICsgMSwgbiA9IHRoaXMubjsgdiA8IG47ICsrdikge1xuICAgICAgICAgICAgICAgIHZhciBsID0gMDtcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IHRoaXMuazsgKytpKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBkeCA9IHRoaXMueFtpXVt1XSAtIHRoaXMueFtpXVt2XTtcbiAgICAgICAgICAgICAgICAgICAgbCArPSBkeCAqIGR4O1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBsID0gTWF0aC5zcXJ0KGwpO1xuICAgICAgICAgICAgICAgIHZhciBkID0gdGhpcy5EW3VdW3ZdO1xuICAgICAgICAgICAgICAgIGlmICghaXNGaW5pdGUoZCkpXG4gICAgICAgICAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgICAgICAgIHZhciBybCA9IGQgLSBsO1xuICAgICAgICAgICAgICAgIHZhciBkMiA9IGQgKiBkO1xuICAgICAgICAgICAgICAgIHN0cmVzcyArPSBybCAqIHJsIC8gZDI7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHN0cmVzcztcbiAgICB9O1xuICAgIERlc2NlbnQuemVyb0Rpc3RhbmNlID0gMWUtMTA7XG4gICAgcmV0dXJuIERlc2NlbnQ7XG59KCkpO1xuZXhwb3J0cy5EZXNjZW50ID0gRGVzY2VudDtcbnZhciBQc2V1ZG9SYW5kb20gPSAoZnVuY3Rpb24gKCkge1xuICAgIGZ1bmN0aW9uIFBzZXVkb1JhbmRvbShzZWVkKSB7XG4gICAgICAgIGlmIChzZWVkID09PSB2b2lkIDApIHsgc2VlZCA9IDE7IH1cbiAgICAgICAgdGhpcy5zZWVkID0gc2VlZDtcbiAgICAgICAgdGhpcy5hID0gMjE0MDEzO1xuICAgICAgICB0aGlzLmMgPSAyNTMxMDExO1xuICAgICAgICB0aGlzLm0gPSAyMTQ3NDgzNjQ4O1xuICAgICAgICB0aGlzLnJhbmdlID0gMzI3Njc7XG4gICAgfVxuICAgIFBzZXVkb1JhbmRvbS5wcm90b3R5cGUuZ2V0TmV4dCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdGhpcy5zZWVkID0gKHRoaXMuc2VlZCAqIHRoaXMuYSArIHRoaXMuYykgJSB0aGlzLm07XG4gICAgICAgIHJldHVybiAodGhpcy5zZWVkID4+IDE2KSAvIHRoaXMucmFuZ2U7XG4gICAgfTtcbiAgICBQc2V1ZG9SYW5kb20ucHJvdG90eXBlLmdldE5leHRCZXR3ZWVuID0gZnVuY3Rpb24gKG1pbiwgbWF4KSB7XG4gICAgICAgIHJldHVybiBtaW4gKyB0aGlzLmdldE5leHQoKSAqIChtYXggLSBtaW4pO1xuICAgIH07XG4gICAgcmV0dXJuIFBzZXVkb1JhbmRvbTtcbn0oKSk7XG5leHBvcnRzLlBzZXVkb1JhbmRvbSA9IFBzZXVkb1JhbmRvbTtcbi8vIyBzb3VyY2VNYXBwaW5nVVJMPWRhdGE6YXBwbGljYXRpb24vanNvbjtiYXNlNjQsZXlKMlpYSnphVzl1SWpvekxDSm1hV3hsSWpvaVpHVnpZMlZ1ZEM1cWN5SXNJbk52ZFhKalpWSnZiM1FpT2lJaUxDSnpiM1Z5WTJWeklqcGJJaTR1THk0dUwxZGxZa052YkdFdmMzSmpMMlJsYzJObGJuUXVkSE1pWFN3aWJtRnRaWE1pT2x0ZExDSnRZWEJ3YVc1bmN5STZJanM3UVVGSlNUdEpRVUZCTzFGQlEwa3NWVUZCU3l4SFFVRTJRaXhGUVVGRkxFTkJRVU03U1VGdlEzcERMRU5CUVVNN1NVRTNRa2NzYlVKQlFVY3NSMEZCU0N4VlFVRkpMRVZCUVZVc1JVRkJSU3hEUVVGWE8xRkJTWFpDTEVsQlFVa3NRMEZCUXl4TFFVRkxMRU5CUVVNc1JVRkJSU3hEUVVGRExFZEJRVWNzUTBGQlF5eERRVUZETzBsQlEzWkNMRU5CUVVNN1NVRkpSQ3h4UWtGQlN5eEhRVUZNTzFGQlEwa3NTVUZCU1N4RFFVRkRMRXRCUVVzc1IwRkJSeXhGUVVGRkxFTkJRVU03U1VGRGNFSXNRMEZCUXp0SlFVdEVMSFZDUVVGUExFZEJRVkE3VVVGRFNTeExRVUZMTEVsQlFVa3NRMEZCUXl4SlFVRkpMRWxCUVVrc1EwRkJReXhMUVVGTE8xbEJRVVVzVDBGQlR5eExRVUZMTEVOQlFVTTdVVUZEZGtNc1QwRkJUeXhKUVVGSkxFTkJRVU03U1VGRGFFSXNRMEZCUXp0SlFVdEVMSEZDUVVGTExFZEJRVXdzVlVGQlRTeERRVUZ2UXp0UlFVTjBReXhMUVVGTExFbEJRVWtzUTBGQlF5eEpRVUZKTEVsQlFVa3NRMEZCUXl4TFFVRkxMRVZCUVVVN1dVRkRkRUlzUTBGQlF5eERRVUZETEUxQlFVMHNRMEZCUXl4RFFVRkRMRU5CUVVNc1JVRkJSU3hKUVVGSkxFTkJRVU1zUzBGQlN5eERRVUZETEVOQlFVTXNRMEZCUXl4RFFVRkRMRU5CUVVNN1UwRkRMMEk3U1VGRFRDeERRVUZETzBsQlEwd3NXVUZCUXp0QlFVRkVMRU5CUVVNc1FVRnlRMFFzU1VGeFEwTTdRVUZ5UTFrc2MwSkJRVXM3UVVGcFJHeENPMGxCTmtSSkxHbENRVUZaTEVOQlFXRXNSVUZCVXl4RFFVRmhMRVZCUVZNc1EwRkJiVUk3VVVGQmJrSXNhMEpCUVVFc1JVRkJRU3hSUVVGdFFqdFJRVUY2UXl4TlFVRkRMRWRCUVVRc1EwRkJReXhEUVVGWk8xRkJRVk1zVFVGQlF5eEhRVUZFTEVOQlFVTXNRMEZCYTBJN1VVRTFSSEJGTEdOQlFWTXNSMEZCVnl4TlFVRk5MRU5CUVVNN1VVRXlRek5DTEhGQ1FVRm5RaXhIUVVGWExFTkJRVU1zUTBGQlF6dFJRVU0zUWl4cFFrRkJXU3hIUVVGWExFZEJRVWNzUTBGQlF6dFJRVU16UWl4cFFrRkJXU3hIUVVGWExFbEJRVWtzUTBGQlF6dFJRVU0xUWl4dlFrRkJaU3hIUVVGWkxFdEJRVXNzUTBGQlF6dFJRVVZvUXl4WFFVRk5MRWRCUVVjc1NVRkJTU3haUVVGWkxFVkJRVVVzUTBGQlF6dFJRVVUzUWl4WlFVRlBMRWRCUVRCRUxFbEJRVWtzUTBGQlF6dFJRVmQ2UlN4SlFVRkpMRU5CUVVNc1EwRkJReXhIUVVGSExFTkJRVU1zUTBGQlF6dFJRVU5ZTEVsQlFVa3NRMEZCUXl4RFFVRkRMRWRCUVVjc1EwRkJReXhEUVVGRExFMUJRVTBzUTBGQlF6dFJRVU5zUWl4SlFVRkpMRU5CUVVNc1IwRkJSeXhKUVVGSkxFTkJRVU1zUTBGQlF5eEhRVUZITEVOQlFVTXNRMEZCUXl4RFFVRkRMRU5CUVVNc1EwRkJReXhOUVVGTkxFTkJRVU03VVVGRE4wSXNTVUZCU1N4RFFVRkRMRU5CUVVNc1IwRkJSeXhKUVVGSkxFdEJRVXNzUTBGQlF5eEpRVUZKTEVOQlFVTXNRMEZCUXl4RFFVRkRMRU5CUVVNN1VVRkRNMElzU1VGQlNTeERRVUZETEVOQlFVTXNSMEZCUnl4SlFVRkpMRXRCUVVzc1EwRkJReXhKUVVGSkxFTkJRVU1zUTBGQlF5eERRVUZETEVOQlFVTTdVVUZETTBJc1NVRkJTU3hEUVVGRExFVkJRVVVzUjBGQlJ5eEpRVUZKTEV0QlFVc3NRMEZCUXl4SlFVRkpMRU5CUVVNc1EwRkJReXhEUVVGRExFTkJRVU03VVVGRE5VSXNTVUZCU1N4RFFVRkRMRU5CUVVNc1IwRkJSeXhKUVVGSkxFdEJRVXNzUTBGQlF5eEpRVUZKTEVOQlFVTXNRMEZCUXl4RFFVRkRMRU5CUVVNN1VVRkRNMElzU1VGQlNTeERRVUZETEVOQlFVTXNSMEZCUnl4SlFVRkpMRXRCUVVzc1EwRkJReXhKUVVGSkxFTkJRVU1zUTBGQlF5eERRVUZETEVOQlFVTTdVVUZETTBJc1NVRkJTU3hEUVVGRExFTkJRVU1zUjBGQlJ5eEpRVUZKTEV0QlFVc3NRMEZCUXl4SlFVRkpMRU5CUVVNc1EwRkJReXhEUVVGRExFTkJRVU03VVVGRE0wSXNTVUZCU1N4RFFVRkRMRU5CUVVNc1IwRkJSeXhKUVVGSkxFdEJRVXNzUTBGQlF5eEpRVUZKTEVOQlFVTXNRMEZCUXl4RFFVRkRMRU5CUVVNN1VVRkRNMElzU1VGQlNTeERRVUZETEVOQlFVTXNSMEZCUnl4SlFVRkpMRXRCUVVzc1EwRkJReXhKUVVGSkxFTkJRVU1zUTBGQlF5eERRVUZETEVOQlFVTTdVVUZETTBJc1NVRkJTU3hEUVVGRExFVkJRVVVzUjBGQlJ5eEpRVUZKTEV0QlFVc3NRMEZCUXl4SlFVRkpMRU5CUVVNc1EwRkJReXhEUVVGRExFTkJRVU03VVVGRE5VSXNTVUZCU1N4RFFVRkRMRVZCUVVVc1IwRkJSeXhKUVVGSkxFdEJRVXNzUTBGQlF5eEpRVUZKTEVOQlFVTXNRMEZCUXl4RFFVRkRMRU5CUVVNN1VVRkROVUlzU1VGQlNTeERRVUZETEVsQlFVa3NSMEZCUnl4SlFVRkpMRXRCUVVzc1EwRkJReXhKUVVGSkxFTkJRVU1zUTBGQlF5eERRVUZETEVOQlFVTTdVVUZET1VJc1NVRkJTU3hEUVVGRExFdEJRVXNzUjBGQlJ5eEpRVUZKTEV0QlFVc3NSVUZCUlN4RFFVRkRPMUZCUTNwQ0xFbEJRVWtzUTBGQlF5eEpRVUZKTEVkQlFVY3NUVUZCVFN4RFFVRkRMRk5CUVZNc1EwRkJRenRSUVVNM1FpeEpRVUZKTEVOQlFVTXNSMEZCUnl4RFFVRkRMRVZCUVVVc1EwRkJReXhEUVVGRE8xRkJRMklzVDBGQlR5eERRVUZETEVWQlFVVXNSVUZCUlR0WlFVTlNMRU5CUVVNc1IwRkJSeXhEUVVGRExFTkJRVU03V1VGRFRpeFBRVUZQTEVWQlFVVXNRMEZCUXl4SFFVRkhMRU5CUVVNc1JVRkJSVHRuUWtGRFdpeEpRVUZKTEVOQlFVTXNSMEZCUnl4RFFVRkRMRU5CUVVNc1EwRkJReXhEUVVGRExFTkJRVU1zUTBGQlF5eERRVUZETEVOQlFVTTdaMEpCUTJoQ0xFbEJRVWtzUTBGQlF5eEhRVUZITEVOQlFVTXNTVUZCU1N4RFFVRkRMRWRCUVVjc1NVRkJTU3hEUVVGRExFbEJRVWtzUlVGQlJUdHZRa0ZEZUVJc1NVRkJTU3hEUVVGRExFbEJRVWtzUjBGQlJ5eERRVUZETEVOQlFVTTdhVUpCUTJwQ08yRkJRMG83VTBGRFNqdFJRVU5FTEVsQlFVa3NTVUZCU1N4RFFVRkRMRWxCUVVrc1MwRkJTeXhOUVVGTkxFTkJRVU1zVTBGQlV6dFpRVUZGTEVsQlFVa3NRMEZCUXl4SlFVRkpMRWRCUVVjc1EwRkJReXhEUVVGRE8xRkJRMnhFTEVOQlFVTXNSMEZCUnl4SlFVRkpMRU5CUVVNc1EwRkJReXhEUVVGRE8xRkJRMWdzVDBGQlR5eERRVUZETEVWQlFVVXNSVUZCUlR0WlFVTlNMRWxCUVVrc1EwRkJReXhEUVVGRExFTkJRVU1zUTBGQlF5eERRVUZETEVkQlFVY3NTVUZCU1N4TFFVRkxMRU5CUVVNc1EwRkJReXhEUVVGRExFTkJRVU03V1VGRGVrSXNTVUZCU1N4RFFVRkRMRU5CUVVNc1EwRkJReXhEUVVGRExFTkJRVU1zUjBGQlJ5eEpRVUZKTEV0QlFVc3NRMEZCUXl4RFFVRkRMRU5CUVVNc1EwRkJRenRaUVVONlFpeERRVUZETEVkQlFVY3NRMEZCUXl4RFFVRkRPMWxCUTA0c1QwRkJUeXhEUVVGRExFVkJRVVVzUlVGQlJUdG5Ra0ZEVWl4SlFVRkpMRU5CUVVNc1EwRkJReXhEUVVGRExFTkJRVU1zUTBGQlF5eERRVUZETEVOQlFVTXNRMEZCUXl4SFFVRkhMRWxCUVVrc1MwRkJTeXhEUVVGRExFTkJRVU1zUTBGQlF5eERRVUZETzJGQlF5OUNPMWxCUTBRc1NVRkJTU3hEUVVGRExFVkJRVVVzUTBGQlF5eERRVUZETEVOQlFVTXNSMEZCUnl4SlFVRkpMRXRCUVVzc1EwRkJReXhEUVVGRExFTkJRVU1zUTBGQlF6dFpRVU14UWl4SlFVRkpMRU5CUVVNc1EwRkJReXhEUVVGRExFTkJRVU1zUTBGQlF5eEhRVUZITEVsQlFVa3NTMEZCU3l4RFFVRkRMRU5CUVVNc1EwRkJReXhEUVVGRE8xbEJRM3BDTEVsQlFVa3NRMEZCUXl4RFFVRkRMRU5CUVVNc1EwRkJReXhEUVVGRExFZEJRVWNzU1VGQlNTeExRVUZMTEVOQlFVTXNRMEZCUXl4RFFVRkRMRU5CUVVNN1dVRkRla0lzU1VGQlNTeERRVUZETEVOQlFVTXNRMEZCUXl4RFFVRkRMRU5CUVVNc1IwRkJSeXhKUVVGSkxFdEJRVXNzUTBGQlF5eERRVUZETEVOQlFVTXNRMEZCUXp0WlFVTjZRaXhKUVVGSkxFTkJRVU1zUTBGQlF5eERRVUZETEVOQlFVTXNRMEZCUXl4SFFVRkhMRWxCUVVrc1MwRkJTeXhEUVVGRExFTkJRVU1zUTBGQlF5eERRVUZETzFsQlEzcENMRWxCUVVrc1EwRkJReXhEUVVGRExFTkJRVU1zUTBGQlF5eERRVUZETEVkQlFVY3NTVUZCU1N4TFFVRkxMRU5CUVVNc1EwRkJReXhEUVVGRExFTkJRVU03V1VGRGVrSXNTVUZCU1N4RFFVRkRMRVZCUVVVc1EwRkJReXhEUVVGRExFTkJRVU1zUjBGQlJ5eEpRVUZKTEV0QlFVc3NRMEZCUXl4RFFVRkRMRU5CUVVNc1EwRkJRenRaUVVNeFFpeEpRVUZKTEVOQlFVTXNSVUZCUlN4RFFVRkRMRU5CUVVNc1EwRkJReXhIUVVGSExFbEJRVWtzUzBGQlN5eERRVUZETEVOQlFVTXNRMEZCUXl4RFFVRkRPMWxCUXpGQ0xFbEJRVWtzUTBGQlF5eEpRVUZKTEVOQlFVTXNRMEZCUXl4RFFVRkRMRWRCUVVjc1NVRkJTU3hMUVVGTExFTkJRVU1zUTBGQlF5eERRVUZETEVOQlFVTTdVMEZETDBJN1NVRkRUQ3hEUVVGRE8wbEJSV0VzTUVKQlFXdENMRWRCUVdoRExGVkJRV2xETEVOQlFWTXNSVUZCUlN4RFFVRnRRenRSUVVNelJTeEpRVUZKTEVOQlFVTXNSMEZCUnl4SlFVRkpMRXRCUVVzc1EwRkJReXhEUVVGRExFTkJRVU1zUTBGQlF6dFJRVU55UWl4TFFVRkxMRWxCUVVrc1EwRkJReXhIUVVGSExFTkJRVU1zUlVGQlJTeERRVUZETEVkQlFVY3NRMEZCUXl4RlFVRkZMRVZCUVVVc1EwRkJReXhGUVVGRk8xbEJRM2hDTEVOQlFVTXNRMEZCUXl4RFFVRkRMRU5CUVVNc1IwRkJSeXhKUVVGSkxFdEJRVXNzUTBGQlF5eERRVUZETEVOQlFVTXNRMEZCUXp0WlFVTndRaXhMUVVGTExFbEJRVWtzUTBGQlF5eEhRVUZITEVOQlFVTXNSVUZCUlN4RFFVRkRMRWRCUVVjc1EwRkJReXhGUVVGRkxFVkJRVVVzUTBGQlF5eEZRVUZGTzJkQ1FVTjRRaXhEUVVGRExFTkJRVU1zUTBGQlF5eERRVUZETEVOQlFVTXNRMEZCUXl4RFFVRkRMRWRCUVVjc1EwRkJReXhEUVVGRExFTkJRVU1zUlVGQlJTeERRVUZETEVOQlFVTXNRMEZCUXp0aFFVTnlRanRUUVVOS08xRkJRMFFzVDBGQlR5eERRVUZETEVOQlFVTTdTVUZEWWl4RFFVRkRPMGxCUlU4c01rSkJRVk1zUjBGQmFrSTdVVUZCUVN4cFFrRlRRenRSUVZKSExFbEJRVWtzUTBGQlF5eEhRVUZITEVsQlFVa3NTMEZCU3l4RFFVRkRMRWxCUVVrc1EwRkJReXhEUVVGRExFTkJRVU1zUTBGQlF6dFJRVU14UWl4SlFVRkpMRU5CUVVNc1IwRkJSeXhEUVVGRExFTkJRVU03VVVGRFZpeExRVUZMTEVsQlFVa3NRMEZCUXl4SFFVRkhMRU5CUVVNc1JVRkJSU3hEUVVGRExFZEJRVWNzU1VGQlNTeERRVUZETEVOQlFVTXNSVUZCUlN4RlFVRkZMRU5CUVVNc1JVRkJSVHRaUVVNM1FpeEpRVUZKTEVOQlFVTXNSMEZCUnl4RFFVRkRMRU5CUVVNc1EwRkJReXhEUVVGRExFZEJRVWNzU1VGQlNTeERRVUZETEUxQlFVMHNRMEZCUXl4alFVRmpMRU5CUVVNc1NVRkJTU3hGUVVGRkxFTkJRVU1zUTBGQlF5eEhRVUZITEVkQlFVY3NRMEZCUXp0WlFVTjZSQ3hEUVVGRExFbEJRVWtzUTBGQlF5eEhRVUZITEVOQlFVTXNRMEZCUXp0VFFVTmtPMUZCUTBRc1EwRkJReXhIUVVGSExFbEJRVWtzUTBGQlF5eEpRVUZKTEVOQlFVTXNRMEZCUXl4RFFVRkRMRU5CUVVNN1VVRkRha0lzVDBGQlR5eERRVUZETEVOQlFVTXNSMEZCUnl4RFFVRkRMRlZCUVVFc1EwRkJReXhKUVVGSExFOUJRVUVzUTBGQlF5eEpRVUZKTEV0QlFVa3NRMEZCUXl4SlFVRkpMRWRCUVVjc1EwRkJReXhGUVVGc1FpeERRVUZyUWl4RFFVRkRMRU5CUVVNN1NVRkRla01zUTBGQlF6dEpRVWROTEc5RFFVRnJRaXhIUVVGNlFpeFZRVUV3UWl4RFFVRmhPMUZCUVhaRExHbENRU3RIUXp0UlFUbEhSeXhKUVVGTkxFTkJRVU1zUjBGQlJ5eEpRVUZKTEVOQlFVTXNRMEZCUXl4RFFVRkRPMUZCUTJwQ0xFbEJRVWtzUTBGQlF5eEhRVUZITEVOQlFVTTdXVUZCUlN4UFFVRlBPMUZCUTJ4Q0xFbEJRVWtzUTBGQlV5eERRVUZETzFGQlQyUXNTVUZCU1N4RFFVRkRMRWRCUVVjc1NVRkJTU3hMUVVGTExFTkJRVk1zU1VGQlNTeERRVUZETEVOQlFVTXNRMEZCUXl4RFFVRkRPMUZCUTJ4RExFbEJRVWtzUlVGQlJTeEhRVUZITEVsQlFVa3NTMEZCU3l4RFFVRlRMRWxCUVVrc1EwRkJReXhEUVVGRExFTkJRVU1zUTBGQlF6dFJRVU51UXl4SlFVRkpMRWRCUVVjc1IwRkJSeXhKUVVGSkxFdEJRVXNzUTBGQlV5eEpRVUZKTEVOQlFVTXNRMEZCUXl4RFFVRkRMRU5CUVVNN1VVRkRjRU1zU1VGQlNTeEpRVUZKTEVkQlFVY3NRMEZCUXl4RFFVRkRPMUZCUjJJc1MwRkJTeXhKUVVGSkxFZEJRVU1zUjBGQlJ5eERRVUZETEVWQlFVVXNSMEZCUXl4SFFVRkhMRU5CUVVNc1JVRkJSU3hGUVVGRkxFZEJRVU1zUlVGQlJUdFpRVVY0UWl4TFFVRkxMRU5CUVVNc1IwRkJSeXhEUVVGRExFVkJRVVVzUTBGQlF5eEhRVUZITEVsQlFVa3NRMEZCUXl4RFFVRkRMRVZCUVVVc1JVRkJSU3hEUVVGRE8yZENRVUZGTEVkQlFVY3NRMEZCUXl4RFFVRkRMRU5CUVVNc1IwRkJSeXhKUVVGSkxFTkJRVU1zUTBGQlF5eERRVUZETEVOQlFVTXNRMEZCUXl4RFFVRkRMRWRCUVVNc1EwRkJReXhIUVVGSExFTkJRVU1zUTBGQlF6dFpRVWQyUkN4TFFVRkxMRWxCUVVrc1EwRkJReXhIUVVGSExFTkJRVU1zUlVGQlJTeERRVUZETEVkQlFVY3NRMEZCUXl4RlFVRkZMRVZCUVVVc1EwRkJReXhGUVVGRk8yZENRVU40UWl4SlFVRkpMRWRCUVVNc1MwRkJTeXhEUVVGRE8yOUNRVUZGTEZOQlFWTTdaMEpCU1hSQ0xFbEJRVWtzV1VGQldTeEhRVUZITEVOQlFVTXNRMEZCUXp0blFrRkRja0lzU1VGQlNTeGxRVUZsTEVkQlFVY3NRMEZCUXl4RFFVRkRPMmRDUVVONFFpeFBRVUZQTEZsQlFWa3NSVUZCUlN4RlFVRkZPMjlDUVVOdVFpeGxRVUZsTEVkQlFVY3NRMEZCUXl4RFFVRkRPMjlDUVVOd1FpeExRVUZMTEVOQlFVTXNSMEZCUnl4RFFVRkRMRVZCUVVVc1EwRkJReXhIUVVGSExFbEJRVWtzUTBGQlF5eERRVUZETEVWQlFVVXNSVUZCUlN4RFFVRkRMRVZCUVVVN2QwSkJRM3BDTEVsQlFVMHNTVUZCUlN4SFFVRkhMRU5CUVVNc1EwRkJReXhEUVVGRExFTkJRVU1zUjBGQlJ5eERRVUZETEVOQlFVTXNRMEZCUXl4RFFVRkRMRU5CUVVNc1IwRkJReXhEUVVGRExFZEJRVWNzUTBGQlF5eERRVUZETEVOQlFVTXNRMEZCUXl4RFFVRkRMRU5CUVVNc1EwRkJReXhEUVVGRE8zZENRVU53UXl4bFFVRmxMRWxCUVVrc1JVRkJSU3hEUVVGRExFTkJRVU1zUTBGQlF5eEhRVUZITEVsQlFVVXNSMEZCUnl4SlFVRkZMRU5CUVVNN2NVSkJRM1JETzI5Q1FVTkVMRWxCUVVrc1pVRkJaU3hIUVVGSExFbEJRVWs3ZDBKQlFVVXNUVUZCVFR0dlFrRkRiRU1zU1VGQlRTeEZRVUZGTEVkQlFVY3NTVUZCU1N4RFFVRkRMRk5CUVZNc1JVRkJSU3hEUVVGRE8yOUNRVU0xUWl4TFFVRkxMRU5CUVVNc1IwRkJSeXhEUVVGRExFVkJRVVVzUTBGQlF5eEhRVUZITEVsQlFVa3NRMEZCUXl4RFFVRkRMRVZCUVVVc1JVRkJSU3hEUVVGRE8zZENRVUZGTEVOQlFVTXNRMEZCUXl4RFFVRkRMRU5CUVVNc1EwRkJReXhEUVVGRExFTkJRVU1zU1VGQlNTeEZRVUZGTEVOQlFVTXNRMEZCUXl4RFFVRkRMRU5CUVVNN2FVSkJRMnBFTzJkQ1FVTkVMRWxCUVUwc1VVRkJVU3hIUVVGSExFbEJRVWtzUTBGQlF5eEpRVUZKTEVOQlFVTXNaVUZCWlN4RFFVRkRMRU5CUVVNN1owSkJRelZETEVsQlFVMHNZVUZCWVN4SFFVRkhMRWxCUVVrc1EwRkJReXhEUVVGRExFTkJRVU1zUjBGQlF5eERRVUZETEVOQlFVTXNRMEZCUXl4RFFVRkRMRU5CUVVNN1owSkJTVzVETEVsQlFVa3NUVUZCVFN4SFFVRkhMRWxCUVVrc1EwRkJReXhEUVVGRExFbEJRVWtzU1VGQlNTeERRVUZETEVOQlFVTXNRMEZCUXl4SlFVRkpMRU5CUVVNc1EwRkJReXhEUVVGRExFZEJRVU1zUTBGQlF5eERRVUZETEVOQlFVTXNRMEZCUXl4RFFVRkRMRU5CUVVNc1EwRkJReXhEUVVGRExFTkJRVU03WjBKQlJ5OURMRWxCUVVrc1RVRkJUU3hIUVVGSExFTkJRVU1zU1VGQlNTeFJRVUZSTEVkQlFVY3NZVUZCWVN4SlFVRkpMRU5CUVVNc1VVRkJVU3hEUVVGRExHRkJRV0VzUTBGQlF5eEZRVUZGTzI5Q1FVTndSU3hMUVVGTExFTkJRVU1zUjBGQlJ5eERRVUZETEVWQlFVVXNRMEZCUXl4SFFVRkhMRWxCUVVrc1EwRkJReXhEUVVGRExFVkJRVVVzUlVGQlJTeERRVUZETzNkQ1FVRkZMRWxCUVVrc1EwRkJReXhEUVVGRExFTkJRVU1zUTBGQlF5eERRVUZETEVOQlFVTXNSMEZCUXl4RFFVRkRMRU5CUVVNc1EwRkJReXhEUVVGRExFZEJRVWNzUTBGQlF5eERRVUZETzI5Q1FVTnFSQ3hUUVVGVE8ybENRVU5hTzJkQ1FVZEVMRWxCUVVrc1RVRkJUU3hIUVVGSExFTkJRVU1zUlVGQlJUdHZRa0ZEV2l4TlFVRk5MRWRCUVVjc1EwRkJReXhEUVVGRE8ybENRVU5rTzJkQ1FVTkVMRWxCUVUwc1owSkJRV2RDTEVkQlFVY3NZVUZCWVN4SFFVRkhMR0ZCUVdFc1JVRkRiRVFzUlVGQlJTeEhRVUZITEVOQlFVTXNSMEZCUnl4TlFVRk5MRWRCUVVjc1EwRkJReXhSUVVGUkxFZEJRVWNzWVVGQllTeERRVUZETEVkQlFVY3NRMEZCUXl4blFrRkJaMElzUjBGQlJ5eFJRVUZSTEVOQlFVTXNSVUZETlVVc1lVRkJZU3hIUVVGSExHVkJRV1VzUjBGQlJ5eFJRVUZSTEVWQlF6RkRMRVZCUVVVc1IwRkJSeXhEUVVGRExFZEJRVWNzUTBGQlF5eE5RVUZOTEVkQlFVY3NRMEZCUXl4blFrRkJaMElzUjBGQlJ5eGhRVUZoTEVOQlFVTXNRMEZCUXp0blFrRkRNVVFzU1VGQlNTeERRVUZETEZGQlFWRXNRMEZCUXl4RlFVRkZMRU5CUVVNN2IwSkJRMklzVDBGQlR5eERRVUZETEVkQlFVY3NRMEZCUXl4RlFVRkZMRU5CUVVNc1EwRkJRenRuUWtGRGNFSXNTMEZCU3l4RFFVRkRMRWRCUVVjc1EwRkJReXhGUVVGRkxFTkJRVU1zUjBGQlJ5eEpRVUZKTEVOQlFVTXNRMEZCUXl4RlFVRkZMRVZCUVVVc1EwRkJReXhGUVVGRk8yOUNRVU42UWl4SlFVRkpMRU5CUVVNc1EwRkJReXhEUVVGRExFTkJRVU1zUTBGQlF5eERRVUZETEVkQlFVTXNRMEZCUXl4SlFVRkpMRU5CUVVNc1EwRkJReXhEUVVGRExFTkJRVU1zUjBGQlJ5eEZRVUZGTEVOQlFVTTdiMEpCUXpGQ0xFZEJRVWNzUTBGQlF5eERRVUZETEVOQlFVTXNTVUZCU1N4SlFVRkpMRU5CUVVNc1EwRkJReXhEUVVGRExFTkJRVU1zUTBGQlF5eERRVUZETEVkQlFVTXNRMEZCUXl4RFFVRkRMRU5CUVVNc1EwRkJReXhIUVVGSExFVkJRVVVzUjBGQlJ5eERRVUZETEVOQlFVTXNSMEZCUnl4aFFVRmhMRWRCUVVjc1lVRkJZU3hIUVVGSExFTkJRVU1zUlVGQlJTeERRVUZETEVOQlFVTXNRMEZCUXl4SFFVRkhMR1ZCUVdVc1EwRkJReXhEUVVGRExFTkJRVU03YVVKQlEzQkhPMkZCUTBvN1dVRkRSQ3hMUVVGTExFTkJRVU1zUjBGQlJ5eERRVUZETEVWQlFVVXNRMEZCUXl4SFFVRkhMRWxCUVVrc1EwRkJReXhEUVVGRExFVkJRVVVzUlVGQlJTeERRVUZETzJkQ1FVRkZMRWxCUVVrc1IwRkJSeXhKUVVGSkxFTkJRVU1zUjBGQlJ5eERRVUZETEVsQlFVa3NSVUZCUlN4SlFVRkpMRU5CUVVNc1EwRkJReXhEUVVGRExFTkJRVU1zUTBGQlF5eERRVUZETEVkQlFVTXNRMEZCUXl4RFFVRkRMRWRCUVVNc1EwRkJReXhIUVVGSExFZEJRVWNzUTBGQlF5eERRVUZETEVOQlFVTXNRMEZCUXl4RFFVRkRPMU5CUTJoR08xRkJSVVFzU1VGQlNTeERRVUZETEVkQlFVY3NTVUZCU1N4RFFVRkRMRmxCUVZrc1IwRkJReXhEUVVGRExFTkJRVU03VVVGRE5VSXNTVUZCU1N4RFFVRkRMRWRCUVVjc1NVRkJTU3hEUVVGRExGbEJRVmtzUTBGQlF6dFJRVU14UWl4SlFVRkpMRU5CUVVNc1IwRkJSeXhKUVVGSkxFTkJRVU1zV1VGQldTeERRVUZETzFGQlF6RkNMRWxCUVVrc1EwRkJReXhIUVVGSExFTkJRVU1zUjBGQlJ5eERRVUZETEVOQlFVTXNSMEZCUnl4RFFVRkRMRU5CUVVNc1EwRkJRenRSUVVOd1FpeEpRVUZKTEZGQlFWRXNSMEZCUnl4SlFVRkpMRU5CUVVNc1owSkJRV2RDTEVOQlFVTTdVVUZGY2tNc1MwRkJTeXhKUVVGSkxFTkJRVU1zUjBGQlZ5eERRVUZETEVWQlFVVXNRMEZCUXl4SFFVRkhMRkZCUVZFc1JVRkJSU3hGUVVGRkxFTkJRVU1zUlVGQlJUdFpRVU4yUXl4TFFVRkxMRU5CUVVNc1IwRkJSeXhEUVVGRExFVkJRVVVzUTBGQlF5eEhRVUZITEVsQlFVa3NRMEZCUXl4RFFVRkRMRVZCUVVVc1JVRkJSU3hEUVVGRExFVkJRVVU3WjBKQlEzcENMRWxCUVVrc1IwRkJSeXhIUVVGSExFbEJRVWtzUTBGQlF5eERRVUZETEVOQlFVTXNRMEZCUXl4RFFVRkRMRU5CUVVNc1EwRkJReXhEUVVGRExFTkJRVU03WjBKQlEzWkNMRWxCUVVrc1EwRkJReXhIUVVGSExFZEJRVWNzUjBGQlJ5eERRVUZETEVOQlFVTTdaMEpCUTJoQ0xFbEJRVWtzUTBGQlF5eEhRVUZITEVOQlFVTXNSMEZCUnl4RFFVRkRMRU5CUVVNN1owSkJRMlFzU1VGQlNTeERRVUZETEVkQlFVY3NRMEZCUXl4SFFVRkhMRU5CUVVNc1EwRkJRenRuUWtGRFpDeEpRVUZKTEVOQlFVTXNSMEZCUnl4SlFVRkpMRU5CUVVNc1IwRkJSeXhEUVVGRExFTkJRVU1zUTBGQlF5eERRVUZETzJkQ1FVTndRaXhKUVVGSkxFVkJRVVVzUjBGQlJ5eERRVUZETEVOQlFVTXNTVUZCU1N4SFFVRkhMRU5CUVVNc1EwRkJReXhEUVVGRExFTkJRVU1zUjBGQlJ5eEhRVUZITEVOQlFVTXNSMEZCUnl4RFFVRkRMRU5CUVVNc1EwRkJRenR2UWtGREwwSXNRMEZCUXl4SFFVRkhMRWRCUVVjc1EwRkJReXhEUVVGRExFTkJRVU1zUTBGQlF5eERRVUZETEVkQlFVY3NSMEZCUnl4RFFVRkRMRU5CUVVNc1IwRkJSeXhEUVVGRExFTkJRVU1zUjBGQlJ5eERRVUZETEVOQlFVTXNRMEZCUXl4RFFVRkRMRWRCUVVjc1IwRkJSeXhEUVVGRExFTkJRVU1zUjBGQlJ5eERRVUZETEVOQlFVTXNSMEZCUnl4RFFVRkRMRU5CUVVNN1owSkJRM1JFTEVsQlFVa3NRMEZCUXl4RFFVRkRMRWRCUVVjc1JVRkJSU3hKUVVGSkxFVkJRVVVzU1VGQlNTeERRVUZETEVWQlFVVTdiMEpCUTNCQ0xFbEJRVWtzU1VGQlNTeERRVUZETEdWQlFXVXNSVUZCUlR0M1FrRkRkRUlzU1VGQlNTeERRVUZETEVOQlFVTXNRMEZCUXl4RFFVRkRMRU5CUVVNc1EwRkJReXhEUVVGRExFTkJRVU1zU1VGQlNTeEpRVUZKTEVkQlFVY3NRMEZCUXl4SFFVRkhMRVZCUVVVc1EwRkJRenQzUWtGRE9VSXNTVUZCU1N4RFFVRkRMRU5CUVVNc1EwRkJReXhEUVVGRExFTkJRVU1zUTBGQlF5eERRVUZETEVOQlFVTXNRMEZCUXl4RFFVRkRMRU5CUVVNc1NVRkJTU3hKUVVGSkxFZEJRVWNzUTBGQlF5eERRVUZETzNGQ1FVTXZRanQ1UWtGQlRUdDNRa0ZEU0N4SlFVRkpMRU5CUVVNc1EwRkJReXhEUVVGRExFTkJRVU1zUTBGQlF5eERRVUZETEVOQlFVTXNRMEZCUXl4SlFVRkpMRU5CUVVNc1IwRkJSeXhGUVVGRkxFTkJRVU03ZDBKQlEzWkNMRWxCUVVrc1EwRkJReXhEUVVGRExFTkJRVU1zUTBGQlF5eERRVUZETEVOQlFVTXNRMEZCUXl4RFFVRkRMRU5CUVVNc1EwRkJReXhEUVVGRExFbEJRVWtzUTBGQlF5eERRVUZETzNGQ1FVTjRRanRwUWtGRFNqdGhRVU5LTzFOQlEwbzdVVUZEUkN4SlFVRkpMRU5CUVVNc1NVRkJTU3hEUVVGRExFdEJRVXNzUTBGQlF5eFBRVUZQTEVWQlFVVXNSVUZCUlR0WlFVTjJRaXhKUVVGSkxFTkJRVU1zUzBGQlN5eERRVUZETEV0QlFVc3NRMEZCUXl4VlFVRkRMRU5CUVVNc1JVRkJSU3hEUVVGRE8yZENRVU5zUWl4TFFVRkxMRU5CUVVNc1IwRkJSeXhEUVVGRExFVkJRVVVzUTBGQlF5eEhRVUZITEV0QlFVa3NRMEZCUXl4RFFVRkRMRVZCUVVVc1JVRkJSU3hEUVVGRExFVkJRVVU3YjBKQlEzcENMRXRCUVVrc1EwRkJReXhEUVVGRExFTkJRVU1zUTBGQlF5eERRVUZETEVOQlFVTXNRMEZCUXl4RFFVRkRMRU5CUVVNc1EwRkJReXhEUVVGRExFbEJRVWtzU1VGQlNTeERRVUZETzI5Q1FVTjRRaXhMUVVGSkxFTkJRVU1zUTBGQlF5eERRVUZETEVOQlFVTXNRMEZCUXl4RFFVRkRMRU5CUVVNc1EwRkJReXhKUVVGSkxFbEJRVWtzUjBGQlJ5eERRVUZETEVOQlFVTXNRMEZCUXl4RFFVRkRMRU5CUVVNc1IwRkJSeXhEUVVGRExFTkJRVU1zUTBGQlF5eERRVUZETEVOQlFVTXNRMEZCUXl4RFFVRkRMRU5CUVVNc1EwRkJRenRwUWtGRE0wTTdXVUZEVEN4RFFVRkRMRU5CUVVNc1EwRkJRenRUUVVOT08wbEJVMHdzUTBGQlF6dEpRVVZqTEdWQlFVOHNSMEZCZEVJc1ZVRkJkVUlzUTBGQlZ5eEZRVUZGTEVOQlFWYzdVVUZETTBNc1NVRkJTU3hEUVVGRExFZEJRVWNzUTBGQlF5eEZRVUZGTEVOQlFVTXNSMEZCUnl4RFFVRkRMRU5CUVVNc1RVRkJUU3hEUVVGRE8xRkJRM2hDTEU5QlFVOHNRMEZCUXl4RlFVRkZPMWxCUVVVc1EwRkJReXhKUVVGSkxFTkJRVU1zUTBGQlF5eERRVUZETEVOQlFVTXNSMEZCUnl4RFFVRkRMRU5CUVVNc1EwRkJReXhEUVVGRExFTkJRVU03VVVGRE4wSXNUMEZCVHl4RFFVRkRMRU5CUVVNN1NVRkRZaXhEUVVGRE8wbEJSMk1zY1VKQlFXRXNSMEZCTlVJc1ZVRkJOa0lzUTBGQllTeEZRVUZGTEVOQlFWY3NSVUZCUlN4RFFVRlhPMUZCUTJoRkxFbEJRVWtzUTBGQlF5eEhRVUZITEVOQlFVTXNRMEZCUXl4TlFVRk5MRU5CUVVNN1VVRkRha0lzVDBGQlR5eERRVUZETEVWQlFVVTdXVUZCUlN4RFFVRkRMRU5CUVVNc1EwRkJReXhEUVVGRExFZEJRVWNzVDBGQlR5eERRVUZETEU5QlFVOHNRMEZCUXl4RFFVRkRMRU5CUVVNc1EwRkJReXhEUVVGRExFVkJRVVVzUTBGQlF5eERRVUZETEVOQlFVTTdTVUZEYUVRc1EwRkJRenRKUVV0TkxHbERRVUZsTEVkQlFYUkNMRlZCUVhWQ0xFTkJRV0U3VVVGRGFFTXNTVUZCU1N4VFFVRlRMRWRCUVVjc1EwRkJReXhGUVVGRkxGZEJRVmNzUjBGQlJ5eERRVUZETEVOQlFVTTdVVUZEYmtNc1MwRkJTeXhKUVVGSkxFTkJRVU1zUjBGQlJ5eERRVUZETEVWQlFVVXNRMEZCUXl4SFFVRkhMRWxCUVVrc1EwRkJReXhEUVVGRExFVkJRVVVzUlVGQlJTeERRVUZETEVWQlFVVTdXVUZETjBJc1UwRkJVeXhKUVVGSkxFOUJRVThzUTBGQlF5eFBRVUZQTEVOQlFVTXNTVUZCU1N4RFFVRkRMRU5CUVVNc1EwRkJReXhEUVVGRExFTkJRVU1zUlVGQlJTeERRVUZETEVOQlFVTXNRMEZCUXl4RFFVRkRMRU5CUVVNc1EwRkJRenRaUVVNNVF5eFBRVUZQTEVOQlFVTXNZVUZCWVN4RFFVRkRMRWxCUVVrc1EwRkJReXhEUVVGRExFTkJRVU1zUTBGQlF5eERRVUZETEVWQlFVVXNRMEZCUXl4RFFVRkRMRU5CUVVNc1EwRkJReXhGUVVGRkxFbEJRVWtzUTBGQlF5eEZRVUZGTEVOQlFVTXNRMEZCUXl4RFFVRkRMRU5CUVVNc1EwRkJRenRaUVVOdVJDeFhRVUZYTEVsQlFVa3NUMEZCVHl4RFFVRkRMRTlCUVU4c1EwRkJReXhEUVVGRExFTkJRVU1zUTBGQlF5eERRVUZETEVWQlFVVXNTVUZCU1N4RFFVRkRMRVZCUVVVc1EwRkJReXhEUVVGRExFTkJRVU1zUTBGQlF5eERRVUZETzFOQlEzQkVPMUZCUTBRc1NVRkJTU3hYUVVGWExFdEJRVXNzUTBGQlF5eEpRVUZKTEVOQlFVTXNVVUZCVVN4RFFVRkRMRmRCUVZjc1EwRkJRenRaUVVGRkxFOUJRVThzUTBGQlF5eERRVUZETzFGQlF6RkVMRTlCUVU4c1EwRkJReXhIUVVGSExGTkJRVk1zUjBGQlJ5eFhRVUZYTEVOQlFVTTdTVUZEZGtNc1EwRkJRenRKUVVWTkxEaENRVUZaTEVkQlFXNUNPMUZCUTBrc1NVRkJTU3hEUVVGRExHdENRVUZyUWl4RFFVRkRMRWxCUVVrc1EwRkJReXhEUVVGRExFTkJRVU1zUTBGQlF6dFJRVU5vUXl4SlFVRkpMRXRCUVVzc1IwRkJSeXhKUVVGSkxFTkJRVU1zWlVGQlpTeERRVUZETEVsQlFVa3NRMEZCUXl4RFFVRkRMRU5CUVVNc1EwRkJRenRSUVVONlF5eExRVUZMTEVsQlFVa3NRMEZCUXl4SFFVRkhMRU5CUVVNc1JVRkJSU3hEUVVGRExFZEJRVWNzU1VGQlNTeERRVUZETEVOQlFVTXNSVUZCUlN4RlFVRkZMRU5CUVVNc1JVRkJSVHRaUVVNM1FpeEpRVUZKTEVOQlFVTXNaVUZCWlN4RFFVRkRMRWxCUVVrc1EwRkJReXhEUVVGRExFTkJRVU1zUTBGQlF5eERRVUZETEVWQlFVVXNTVUZCU1N4RFFVRkRMRU5CUVVNc1EwRkJReXhEUVVGRExFTkJRVU1zUlVGQlJTeExRVUZMTEVOQlFVTXNRMEZCUXp0VFFVTnlSRHRSUVVORUxFOUJRVThzU1VGQlNTeERRVUZETEdGQlFXRXNSVUZCUlN4RFFVRkRPMGxCUTJoRExFTkJRVU03U1VGRll5eFpRVUZKTEVkQlFXNUNMRlZCUVc5Q0xFTkJRV0VzUlVGQlJTeERRVUZoTzFGQlF6VkRMRWxCUVVrc1EwRkJReXhIUVVGSExFTkJRVU1zUTBGQlF5eE5RVUZOTEVWQlFVVXNRMEZCUXl4SFFVRkhMRU5CUVVNc1EwRkJReXhEUVVGRExFTkJRVU1zUTBGQlF5eE5RVUZOTEVOQlFVTTdVVUZEYkVNc1MwRkJTeXhKUVVGSkxFTkJRVU1zUjBGQlJ5eERRVUZETEVWQlFVVXNRMEZCUXl4SFFVRkhMRU5CUVVNc1JVRkJSU3hGUVVGRkxFTkJRVU1zUlVGQlJUdFpRVU40UWl4TFFVRkxMRWxCUVVrc1EwRkJReXhIUVVGSExFTkJRVU1zUlVGQlJTeERRVUZETEVkQlFVY3NRMEZCUXl4RlFVRkZMRVZCUVVVc1EwRkJReXhGUVVGRk8yZENRVU40UWl4RFFVRkRMRU5CUVVNc1EwRkJReXhEUVVGRExFTkJRVU1zUTBGQlF5eERRVUZETEVkQlFVY3NRMEZCUXl4RFFVRkRMRU5CUVVNc1EwRkJReXhEUVVGRExFTkJRVU1zUTBGQlF5eERRVUZETzJGQlEzSkNPMU5CUTBvN1NVRkRUQ3hEUVVGRE8wbEJVVThzWjBOQlFXTXNSMEZCZEVJc1ZVRkJkVUlzUlVGQll5eEZRVUZGTEVOQlFXRXNSVUZCUlN4RFFVRmhMRVZCUVVVc1VVRkJaMEk3VVVGRGFrWXNUMEZCVHl4RFFVRkRMRWxCUVVrc1EwRkJReXhGUVVGRkxFVkJRVVVzUTBGQlF5eERRVUZETEVOQlFVTTdVVUZEY0VJc1NVRkJTU3hEUVVGRExHVkJRV1VzUTBGQlF5eERRVUZETEVOQlFVTXNRMEZCUXl4RFFVRkRMRVZCUVVVc1EwRkJReXhEUVVGRExFTkJRVU1zUTBGQlF5eEZRVUZGTEZGQlFWRXNRMEZCUXl4RFFVRkRPMUZCUXpORExFbEJRVWtzU1VGQlNTeERRVUZETEU5QlFVODdXVUZCUlN4SlFVRkpMRU5CUVVNc1QwRkJUeXhEUVVGRExFTkJRVU1zUTBGQlF5eERRVUZETEVWQlFVVXNRMEZCUXl4RFFVRkRMRU5CUVVNc1JVRkJSU3hGUVVGRkxFTkJRVU1zUTBGQlF5eERRVUZETEVWQlFVVXNRMEZCUXl4RFFVRkRMRU5CUVVNc1EwRkJReXhEUVVGRExFTkJRVU03VVVGRGRFUXNTVUZCU1N4RFFVRkRMR1ZCUVdVc1EwRkJReXhEUVVGRExFTkJRVU1zUTBGQlF5eERRVUZETEVWQlFVVXNRMEZCUXl4RFFVRkRMRU5CUVVNc1EwRkJReXhGUVVGRkxGRkJRVkVzUTBGQlF5eERRVUZETzFGQlF6TkRMRWxCUVVrc1NVRkJTU3hEUVVGRExFOUJRVTg3V1VGQlJTeEpRVUZKTEVOQlFVTXNUMEZCVHl4RFFVRkRMRU5CUVVNc1EwRkJReXhEUVVGRExFTkJRVU1zUTBGQlF5eERRVUZETEVOQlFVTXNSVUZCUlN4RlFVRkZMRU5CUVVNc1EwRkJReXhEUVVGRExFVkJRVVVzUTBGQlF5eERRVUZETEVOQlFVTXNRMEZCUXl4RFFVRkRMRU5CUVVNN1VVRkhja1FzUzBGQlN5eEpRVUZKTEVOQlFVTXNSMEZCUnl4RFFVRkRMRVZCUVVVc1EwRkJReXhIUVVGSExFbEJRVWtzUTBGQlF5eERRVUZETEVWQlFVVXNRMEZCUXl4RlFVRkZPMWxCUXpOQ0xFbEJRVWtzUTBGQlF5eGxRVUZsTEVOQlFVTXNRMEZCUXl4RFFVRkRMRU5CUVVNc1EwRkJReXhGUVVGRkxFTkJRVU1zUTBGQlF5eERRVUZETEVOQlFVTXNSVUZCUlN4UlFVRlJMRU5CUVVNc1EwRkJRenRKUVZWdVJDeERRVUZETzBsQlJXTXNZMEZCVFN4SFFVRnlRaXhWUVVGelFpeERRVUZUTEVWQlFVVXNRMEZCVXl4RlFVRkZMRU5CUVdkRE8xRkJRM2hGTEVsQlFVa3NRMEZCUXl4SFFVRkhMRU5CUVVNc1EwRkJRenRSUVVGRExFOUJRVThzUTBGQlF5eEZRVUZGTEVkQlFVY3NRMEZCUXl4RlFVRkZPMWxCUTNaQ0xFbEJRVWtzUTBGQlF5eEhRVUZITEVOQlFVTXNRMEZCUXp0WlFVRkRMRTlCUVU4c1EwRkJReXhGUVVGRkxFZEJRVWNzUTBGQlF6dG5Ra0ZCUlN4RFFVRkRMRU5CUVVNc1EwRkJReXhGUVVGRkxFTkJRVU1zUTBGQlF5eERRVUZETzFOQlEzUkRPMGxCUTB3c1EwRkJRenRKUVVOUExEWkNRVUZYTEVkQlFXNUNMRlZCUVc5Q0xFTkJRV2RETzFGQlEyaEVMRTlCUVU4c1EwRkJReXhOUVVGTkxFTkJRVU1zU1VGQlNTeERRVUZETEVOQlFVTXNSVUZCUlN4SlFVRkpMRU5CUVVNc1EwRkJReXhGUVVGRkxFTkJRVU1zUTBGQlF5eERRVUZETzBsQlEzUkRMRU5CUVVNN1NVRkZUeXh4UTBGQmJVSXNSMEZCTTBJc1ZVRkJORUlzUlVGQll5eEZRVUZGTEVOQlFXRTdVVUZCZWtRc2FVSkJaVU03VVVGa1J5eEpRVUZKTEVOQlFVTXNhMEpCUVd0Q0xFTkJRVU1zUlVGQlJTeERRVUZETEVOQlFVTTdVVUZETlVJc1NVRkJTU3hMUVVGTExFZEJRVWNzU1VGQlNTeERRVUZETEdWQlFXVXNRMEZCUXl4SlFVRkpMRU5CUVVNc1EwRkJReXhEUVVGRExFTkJRVU03VVVGRGVrTXNTVUZCU1N4RFFVRkRMR05CUVdNc1EwRkJReXhGUVVGRkxFVkJRVVVzUTBGQlF5eEZRVUZGTEVsQlFVa3NRMEZCUXl4RFFVRkRMRVZCUVVVc1MwRkJTeXhEUVVGRExFTkJRVU03VVVGTk1VTXNTVUZCU1N4SlFVRkpMRU5CUVVNc1QwRkJUeXhGUVVGRk8xbEJRMlFzU1VGQlNTeERRVUZETEZkQlFWY3NRMEZCUXl4VlFVRkRMRU5CUVVNc1JVRkJSU3hEUVVGRExFbEJRVXNzVDBGQlFTeExRVUZKTEVOQlFVTXNRMEZCUXl4RFFVRkRMRU5CUVVNc1EwRkJReXhEUVVGRExFTkJRVU1zUTBGQlF5eEhRVUZITEVWQlFVVXNRMEZCUXl4RFFVRkRMRU5CUVVNc1EwRkJReXhEUVVGRExFTkJRVU1zUjBGQlJ5eERRVUZETEVOQlFVTXNRMEZCUXl4RFFVRkRMRU5CUVVNc1EwRkJReXhEUVVGRExFVkJRV3BETEVOQlFXbERMRU5CUVVNc1EwRkJRenRaUVVNNVJDeEpRVUZKTEVsQlFVa3NSMEZCUnl4SlFVRkpMRU5CUVVNc1pVRkJaU3hEUVVGRExFbEJRVWtzUTBGQlF5eERRVUZETEVOQlFVTXNRMEZCUXp0WlFVTjRReXhKUVVGSkxFZEJRVWNzU1VGQlNTeERRVUZETEVkQlFVY3NRMEZCUXl4SFFVRkhMRVZCUVVVc1NVRkJTU3hEUVVGRExFZEJRVWNzUTBGQlF5eEpRVUZKTEVWQlFVVXNRMEZCUXl4RFFVRkRMRU5CUVVNc1EwRkJRenRaUVVONFF5eEpRVUZKTEVOQlFVTXNZMEZCWXl4RFFVRkRMRVZCUVVVc1JVRkJSU3hEUVVGRExFVkJRVVVzU1VGQlNTeERRVUZETEVOQlFVTXNSVUZCUlN4SlFVRkpMRU5CUVVNc1EwRkJRenRUUVVNMVF6dEpRVU5NTEVOQlFVTTdTVUZGVFN4eFFrRkJSeXhIUVVGV0xGVkJRVmNzVlVGQmEwSTdVVUZEZWtJc1NVRkJTU3hOUVVGTkxFZEJRVWNzVFVGQlRTeERRVUZETEZOQlFWTXNSVUZCUlN4VFFVRlRMRWRCUVVjc1MwRkJTeXhEUVVGRE8xRkJRMnBFTEU5QlFVOHNRMEZCUXl4VFFVRlRMRWxCUVVrc1ZVRkJWU3hGUVVGRkxFZEJRVWNzUTBGQlF5eEZRVUZGTzFsQlEyNURMRWxCUVVrc1EwRkJReXhIUVVGSExFbEJRVWtzUTBGQlF5eFZRVUZWTEVWQlFVVXNRMEZCUXp0WlFVTXhRaXhUUVVGVExFZEJRVWNzU1VGQlNTeERRVUZETEVkQlFVY3NRMEZCUXl4TlFVRk5MRWRCUVVjc1EwRkJReXhIUVVGSExFTkJRVU1zUTBGQlF5eEhRVUZITEVsQlFVa3NRMEZCUXl4VFFVRlRMRU5CUVVNN1dVRkRkRVFzVFVGQlRTeEhRVUZITEVOQlFVTXNRMEZCUXp0VFFVTmtPMUZCUTBRc1QwRkJUeXhOUVVGTkxFTkJRVU03U1VGRGJFSXNRMEZCUXp0SlFVVk5MRFJDUVVGVkxFZEJRV3BDTzFGQlFVRXNhVUpCWlVNN1VVRmtSeXhKUVVGSkxFTkJRVU1zYlVKQlFXMUNMRU5CUVVNc1NVRkJTU3hEUVVGRExFTkJRVU1zUlVGQlJTeEpRVUZKTEVOQlFVTXNRMEZCUXl4RFFVRkRMRU5CUVVNN1VVRkRla01zVDBGQlR5eERRVUZETEVkQlFVY3NRMEZCUXl4SlFVRkpMRU5CUVVNc1EwRkJReXhGUVVGRkxFbEJRVWtzUTBGQlF5eERRVUZETEVWQlFVVXNTVUZCU1N4RFFVRkRMRVZCUVVVc1EwRkJReXhEUVVGRE8xRkJRM0pETEVsQlFVa3NRMEZCUXl4dFFrRkJiVUlzUTBGQlF5eEpRVUZKTEVOQlFVTXNSVUZCUlN4RlFVRkZMRWxCUVVrc1EwRkJReXhEUVVGRExFTkJRVU1zUTBGQlF6dFJRVU14UXl4UFFVRlBMRU5CUVVNc1IwRkJSeXhEUVVGRExFbEJRVWtzUTBGQlF5eERRVUZETEVWQlFVVXNTVUZCU1N4RFFVRkRMRU5CUVVNc1JVRkJSU3hKUVVGSkxFTkJRVU1zUlVGQlJTeERRVUZETEVOQlFVTTdVVUZEY2tNc1NVRkJTU3hEUVVGRExHMUNRVUZ0UWl4RFFVRkRMRWxCUVVrc1EwRkJReXhGUVVGRkxFVkJRVVVzU1VGQlNTeERRVUZETEVOQlFVTXNRMEZCUXl4RFFVRkRPMUZCUXpGRExFbEJRVWtzUTBGQlF5eHRRa0ZCYlVJc1EwRkJReXhKUVVGSkxFTkJRVU1zUTBGQlF5eEZRVUZGTEVsQlFVa3NRMEZCUXl4RFFVRkRMRU5CUVVNc1EwRkJRenRSUVVONlF5eEpRVUZKTEVsQlFVa3NSMEZCUnl4RFFVRkRMRU5CUVVNN1VVRkRZaXhKUVVGSkxFTkJRVU1zVjBGQlZ5eERRVUZETEZWQlFVTXNRMEZCUXl4RlFVRkZMRU5CUVVNN1dVRkRiRUlzU1VGQlNTeERRVUZETEVkQlFVY3NRMEZCUXl4TFFVRkpMRU5CUVVNc1EwRkJReXhEUVVGRExFTkJRVU1zUTBGQlF5eERRVUZETEVOQlFVTXNRMEZCUXl4SFFVRkhMRWRCUVVjc1IwRkJSeXhMUVVGSkxFTkJRVU1zUTBGQlF5eERRVUZETEVOQlFVTXNRMEZCUXl4RFFVRkRMRU5CUVVNc1EwRkJReXhIUVVGSExFZEJRVWNzUjBGQlJ5eExRVUZKTEVOQlFVTXNRMEZCUXl4RFFVRkRMRU5CUVVNc1EwRkJReXhEUVVGRExFTkJRVU1zUTBGQlF5eEhRVUZITEV0QlFVa3NRMEZCUXl4RFFVRkRMRU5CUVVNc1EwRkJReXhEUVVGRExFTkJRVU1zUTBGQlF5eERRVUZETEVOQlFVTXNSMEZCUnl4SFFVRkhMRVZCUTJwR0xFTkJRVU1zUjBGQlJ5eExRVUZKTEVOQlFVTXNRMEZCUXl4RFFVRkRMRU5CUVVNc1EwRkJReXhEUVVGRExFTkJRVU1zUTBGQlF5eEhRVUZITEVOQlFVTXNRMEZCUXp0WlFVTjZRaXhKUVVGSkxFbEJRVWtzUTBGQlF5eEhRVUZITEVOQlFVTXNRMEZCUXp0WlFVTmtMRXRCUVVrc1EwRkJReXhEUVVGRExFTkJRVU1zUTBGQlF5eERRVUZETEVOQlFVTXNRMEZCUXl4RFFVRkRMRWRCUVVjc1EwRkJReXhEUVVGRE8xRkJRM0pDTEVOQlFVTXNRMEZCUXl4RFFVRkRPMUZCUTBnc1QwRkJUeXhKUVVGSkxFTkJRVU03U1VGRGFFSXNRMEZCUXp0SlFVVmpMRmRCUVVjc1IwRkJiRUlzVlVGQmJVSXNRMEZCWVN4RlFVRkZMRU5CUVdFc1JVRkJSU3hEUVVGaE8xRkJRekZFTEU5QlFVOHNRMEZCUXl4TlFVRk5MRU5CUVVNc1EwRkJReXhEUVVGRExFMUJRVTBzUlVGQlJTeERRVUZETEVOQlFVTXNRMEZCUXl4RFFVRkRMRU5CUVVNc1RVRkJUU3hGUVVGRkxGVkJRVU1zUTBGQlF5eEZRVUZGTEVOQlFVTTdXVUZEZGtNc1QwRkJRU3hEUVVGRExFTkJRVU1zUTBGQlF5eERRVUZETEVOQlFVTXNRMEZCUXl4RFFVRkRMRWRCUVVjc1EwRkJReXhEUVVGRExFTkJRVU1zUTBGQlF5eERRVUZETEVOQlFVTXNRMEZCUXl4SFFVRkhMRU5CUVVNc1EwRkJReXhEUVVGRExFTkJRVU1zUTBGQlF5eERRVUZETEVOQlFVTXNRMEZCUXl4SFFVRkhMRU5CUVVNc1EwRkJReXhEUVVGRExFTkJRVU1zUTBGQlF5eERRVUZETEVOQlFVTXNRMEZCUXl4SFFVRkhMRWRCUVVjN1VVRkJOME1zUTBGQk5rTXNRMEZCUXl4RFFVRkRPMGxCUTNaRUxFTkJRVU03U1VGRlRTeHBRMEZCWlN4SFFVRjBRaXhWUVVGMVFpeERRVUZYTEVWQlFVVXNRMEZCVnl4RlFVRkZMRkZCUVdkQ08xRkJRemRFTEV0QlFVc3NTVUZCU1N4RFFVRkRMRWRCUVVjc1EwRkJReXhGUVVGRkxFTkJRVU1zUjBGQlJ5eEpRVUZKTEVOQlFVTXNRMEZCUXl4RlFVRkZMRVZCUVVVc1EwRkJReXhGUVVGRk8xbEJRemRDTEVOQlFVTXNRMEZCUXl4RFFVRkRMRU5CUVVNc1IwRkJSeXhEUVVGRExFTkJRVU1zUTBGQlF5eERRVUZETEVkQlFVY3NVVUZCVVN4SFFVRkhMRU5CUVVNc1EwRkJReXhEUVVGRExFTkJRVU1zUTBGQlF6dFRRVU5xUXp0SlFVTk1MRU5CUVVNN1NVRkZUU3dyUWtGQllTeEhRVUZ3UWp0UlFVTkpMRWxCUVVrc1RVRkJUU3hIUVVGSExFTkJRVU1zUTBGQlF6dFJRVU5tTEV0QlFVc3NTVUZCU1N4RFFVRkRMRWRCUVVjc1EwRkJReXhGUVVGRkxFOUJRVThzUjBGQlJ5eEpRVUZKTEVOQlFVTXNRMEZCUXl4SFFVRkhMRU5CUVVNc1JVRkJSU3hEUVVGRExFZEJRVWNzVDBGQlR5eEZRVUZGTEVWQlFVVXNRMEZCUXl4RlFVRkZPMWxCUTNCRUxFdEJRVXNzU1VGQlNTeERRVUZETEVkQlFVY3NRMEZCUXl4SFFVRkhMRU5CUVVNc1JVRkJSU3hEUVVGRExFZEJRVWNzU1VGQlNTeERRVUZETEVOQlFVTXNSVUZCUlN4RFFVRkRMRWRCUVVjc1EwRkJReXhGUVVGRkxFVkJRVVVzUTBGQlF5eEZRVUZGTzJkQ1FVTjRReXhKUVVGSkxFTkJRVU1zUjBGQlJ5eERRVUZETEVOQlFVTTdaMEpCUTFZc1MwRkJTeXhKUVVGSkxFTkJRVU1zUjBGQlJ5eERRVUZETEVWQlFVVXNRMEZCUXl4SFFVRkhMRWxCUVVrc1EwRkJReXhEUVVGRExFVkJRVVVzUlVGQlJTeERRVUZETEVWQlFVVTdiMEpCUXpkQ0xFbEJRVWtzUlVGQlJTeEhRVUZITEVsQlFVa3NRMEZCUXl4RFFVRkRMRU5CUVVNc1EwRkJReXhEUVVGRExFTkJRVU1zUTBGQlF5eERRVUZETEVkQlFVY3NTVUZCU1N4RFFVRkRMRU5CUVVNc1EwRkJReXhEUVVGRExFTkJRVU1zUTBGQlF5eERRVUZETEVOQlFVTXNRMEZCUXp0dlFrRkRja01zUTBGQlF5eEpRVUZKTEVWQlFVVXNSMEZCUnl4RlFVRkZMRU5CUVVNN2FVSkJRMmhDTzJkQ1FVTkVMRU5CUVVNc1IwRkJSeXhKUVVGSkxFTkJRVU1zU1VGQlNTeERRVUZETEVOQlFVTXNRMEZCUXl4RFFVRkRPMmRDUVVOcVFpeEpRVUZKTEVOQlFVTXNSMEZCUnl4SlFVRkpMRU5CUVVNc1EwRkJReXhEUVVGRExFTkJRVU1zUTBGQlF5eERRVUZETEVOQlFVTXNRMEZCUXl4RFFVRkRPMmRDUVVOeVFpeEpRVUZKTEVOQlFVTXNVVUZCVVN4RFFVRkRMRU5CUVVNc1EwRkJRenR2UWtGQlJTeFRRVUZUTzJkQ1FVTXpRaXhKUVVGSkxFVkJRVVVzUjBGQlJ5eERRVUZETEVkQlFVY3NRMEZCUXl4RFFVRkRPMmRDUVVObUxFbEJRVWtzUlVGQlJTeEhRVUZITEVOQlFVTXNSMEZCUnl4RFFVRkRMRU5CUVVNN1owSkJRMllzVFVGQlRTeEpRVUZKTEVWQlFVVXNSMEZCUnl4RlFVRkZMRWRCUVVjc1JVRkJSU3hEUVVGRE8yRkJRekZDTzFOQlEwbzdVVUZEUkN4UFFVRlBMRTFCUVUwc1EwRkJRenRKUVVOc1FpeERRVUZETzBsQmNGaGpMRzlDUVVGWkxFZEJRVmNzUzBGQlN5eERRVUZETzBsQmNWaG9SQ3hqUVVGRE8wTkJRVUVzUVVFdldVUXNTVUVyV1VNN1FVRXZXVmtzTUVKQlFVODdRVUZyV25CQ08wbEJUVWtzYzBKQlFXMUNMRWxCUVdkQ08xRkJRV2hDTEhGQ1FVRkJMRVZCUVVFc1VVRkJaMEk3VVVGQmFFSXNVMEZCU1N4SFFVRktMRWxCUVVrc1EwRkJXVHRSUVV3elFpeE5RVUZETEVkQlFWY3NUVUZCVFN4RFFVRkRPMUZCUTI1Q0xFMUJRVU1zUjBGQlZ5eFBRVUZQTEVOQlFVTTdVVUZEY0VJc1RVRkJReXhIUVVGWExGVkJRVlVzUTBGQlF6dFJRVU4yUWl4VlFVRkxMRWRCUVZjc1MwRkJTeXhEUVVGRE8wbEJSVk1zUTBGQlF6dEpRVWQ0UXl3NFFrRkJUeXhIUVVGUU8xRkJRMGtzU1VGQlNTeERRVUZETEVsQlFVa3NSMEZCUnl4RFFVRkRMRWxCUVVrc1EwRkJReXhKUVVGSkxFZEJRVWNzU1VGQlNTeERRVUZETEVOQlFVTXNSMEZCUnl4SlFVRkpMRU5CUVVNc1EwRkJReXhEUVVGRExFZEJRVWNzU1VGQlNTeERRVUZETEVOQlFVTXNRMEZCUXp0UlFVTnVSQ3hQUVVGUExFTkJRVU1zU1VGQlNTeERRVUZETEVsQlFVa3NTVUZCU1N4RlFVRkZMRU5CUVVNc1IwRkJSeXhKUVVGSkxFTkJRVU1zUzBGQlN5eERRVUZETzBsQlF6RkRMRU5CUVVNN1NVRkhSQ3h4UTBGQll5eEhRVUZrTEZWQlFXVXNSMEZCVnl4RlFVRkZMRWRCUVZjN1VVRkRia01zVDBGQlR5eEhRVUZITEVkQlFVY3NTVUZCU1N4RFFVRkRMRTlCUVU4c1JVRkJSU3hIUVVGSExFTkJRVU1zUjBGQlJ5eEhRVUZITEVkQlFVY3NRMEZCUXl4RFFVRkRPMGxCUXpsRExFTkJRVU03U1VGRFRDeHRRa0ZCUXp0QlFVRkVMRU5CUVVNc1FVRnNRa1FzU1VGclFrTTdRVUZzUWxrc2IwTkJRVmtpZlE9PSIsIlwidXNlIHN0cmljdFwiO1xudmFyIF9fZXh0ZW5kcyA9ICh0aGlzICYmIHRoaXMuX19leHRlbmRzKSB8fCAoZnVuY3Rpb24gKCkge1xuICAgIHZhciBleHRlbmRTdGF0aWNzID0gZnVuY3Rpb24gKGQsIGIpIHtcbiAgICAgICAgZXh0ZW5kU3RhdGljcyA9IE9iamVjdC5zZXRQcm90b3R5cGVPZiB8fFxuICAgICAgICAgICAgKHsgX19wcm90b19fOiBbXSB9IGluc3RhbmNlb2YgQXJyYXkgJiYgZnVuY3Rpb24gKGQsIGIpIHsgZC5fX3Byb3RvX18gPSBiOyB9KSB8fFxuICAgICAgICAgICAgZnVuY3Rpb24gKGQsIGIpIHsgZm9yICh2YXIgcCBpbiBiKSBpZiAoYi5oYXNPd25Qcm9wZXJ0eShwKSkgZFtwXSA9IGJbcF07IH07XG4gICAgICAgIHJldHVybiBleHRlbmRTdGF0aWNzKGQsIGIpO1xuICAgIH07XG4gICAgcmV0dXJuIGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgICAgIGV4dGVuZFN0YXRpY3MoZCwgYik7XG4gICAgICAgIGZ1bmN0aW9uIF9fKCkgeyB0aGlzLmNvbnN0cnVjdG9yID0gZDsgfVxuICAgICAgICBkLnByb3RvdHlwZSA9IGIgPT09IG51bGwgPyBPYmplY3QuY3JlYXRlKGIpIDogKF9fLnByb3RvdHlwZSA9IGIucHJvdG90eXBlLCBuZXcgX18oKSk7XG4gICAgfTtcbn0pKCk7XG5PYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgXCJfX2VzTW9kdWxlXCIsIHsgdmFsdWU6IHRydWUgfSk7XG52YXIgcmVjdGFuZ2xlXzEgPSByZXF1aXJlKFwiLi9yZWN0YW5nbGVcIik7XG52YXIgUG9pbnQgPSAoZnVuY3Rpb24gKCkge1xuICAgIGZ1bmN0aW9uIFBvaW50KCkge1xuICAgIH1cbiAgICByZXR1cm4gUG9pbnQ7XG59KCkpO1xuZXhwb3J0cy5Qb2ludCA9IFBvaW50O1xudmFyIExpbmVTZWdtZW50ID0gKGZ1bmN0aW9uICgpIHtcbiAgICBmdW5jdGlvbiBMaW5lU2VnbWVudCh4MSwgeTEsIHgyLCB5Mikge1xuICAgICAgICB0aGlzLngxID0geDE7XG4gICAgICAgIHRoaXMueTEgPSB5MTtcbiAgICAgICAgdGhpcy54MiA9IHgyO1xuICAgICAgICB0aGlzLnkyID0geTI7XG4gICAgfVxuICAgIHJldHVybiBMaW5lU2VnbWVudDtcbn0oKSk7XG5leHBvcnRzLkxpbmVTZWdtZW50ID0gTGluZVNlZ21lbnQ7XG52YXIgUG9seVBvaW50ID0gKGZ1bmN0aW9uIChfc3VwZXIpIHtcbiAgICBfX2V4dGVuZHMoUG9seVBvaW50LCBfc3VwZXIpO1xuICAgIGZ1bmN0aW9uIFBvbHlQb2ludCgpIHtcbiAgICAgICAgcmV0dXJuIF9zdXBlciAhPT0gbnVsbCAmJiBfc3VwZXIuYXBwbHkodGhpcywgYXJndW1lbnRzKSB8fCB0aGlzO1xuICAgIH1cbiAgICByZXR1cm4gUG9seVBvaW50O1xufShQb2ludCkpO1xuZXhwb3J0cy5Qb2x5UG9pbnQgPSBQb2x5UG9pbnQ7XG5mdW5jdGlvbiBpc0xlZnQoUDAsIFAxLCBQMikge1xuICAgIHJldHVybiAoUDEueCAtIFAwLngpICogKFAyLnkgLSBQMC55KSAtIChQMi54IC0gUDAueCkgKiAoUDEueSAtIFAwLnkpO1xufVxuZXhwb3J0cy5pc0xlZnQgPSBpc0xlZnQ7XG5mdW5jdGlvbiBhYm92ZShwLCB2aSwgdmopIHtcbiAgICByZXR1cm4gaXNMZWZ0KHAsIHZpLCB2aikgPiAwO1xufVxuZnVuY3Rpb24gYmVsb3cocCwgdmksIHZqKSB7XG4gICAgcmV0dXJuIGlzTGVmdChwLCB2aSwgdmopIDwgMDtcbn1cbmZ1bmN0aW9uIENvbnZleEh1bGwoUykge1xuICAgIHZhciBQID0gUy5zbGljZSgwKS5zb3J0KGZ1bmN0aW9uIChhLCBiKSB7IHJldHVybiBhLnggIT09IGIueCA/IGIueCAtIGEueCA6IGIueSAtIGEueTsgfSk7XG4gICAgdmFyIG4gPSBTLmxlbmd0aCwgaTtcbiAgICB2YXIgbWlubWluID0gMDtcbiAgICB2YXIgeG1pbiA9IFBbMF0ueDtcbiAgICBmb3IgKGkgPSAxOyBpIDwgbjsgKytpKSB7XG4gICAgICAgIGlmIChQW2ldLnggIT09IHhtaW4pXG4gICAgICAgICAgICBicmVhaztcbiAgICB9XG4gICAgdmFyIG1pbm1heCA9IGkgLSAxO1xuICAgIHZhciBIID0gW107XG4gICAgSC5wdXNoKFBbbWlubWluXSk7XG4gICAgaWYgKG1pbm1heCA9PT0gbiAtIDEpIHtcbiAgICAgICAgaWYgKFBbbWlubWF4XS55ICE9PSBQW21pbm1pbl0ueSlcbiAgICAgICAgICAgIEgucHVzaChQW21pbm1heF0pO1xuICAgIH1cbiAgICBlbHNlIHtcbiAgICAgICAgdmFyIG1heG1pbiwgbWF4bWF4ID0gbiAtIDE7XG4gICAgICAgIHZhciB4bWF4ID0gUFtuIC0gMV0ueDtcbiAgICAgICAgZm9yIChpID0gbiAtIDI7IGkgPj0gMDsgaS0tKVxuICAgICAgICAgICAgaWYgKFBbaV0ueCAhPT0geG1heClcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgbWF4bWluID0gaSArIDE7XG4gICAgICAgIGkgPSBtaW5tYXg7XG4gICAgICAgIHdoaWxlICgrK2kgPD0gbWF4bWluKSB7XG4gICAgICAgICAgICBpZiAoaXNMZWZ0KFBbbWlubWluXSwgUFttYXhtaW5dLCBQW2ldKSA+PSAwICYmIGkgPCBtYXhtaW4pXG4gICAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICB3aGlsZSAoSC5sZW5ndGggPiAxKSB7XG4gICAgICAgICAgICAgICAgaWYgKGlzTGVmdChIW0gubGVuZ3RoIC0gMl0sIEhbSC5sZW5ndGggLSAxXSwgUFtpXSkgPiAwKVxuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICBlbHNlXG4gICAgICAgICAgICAgICAgICAgIEgubGVuZ3RoIC09IDE7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoaSAhPSBtaW5taW4pXG4gICAgICAgICAgICAgICAgSC5wdXNoKFBbaV0pO1xuICAgICAgICB9XG4gICAgICAgIGlmIChtYXhtYXggIT0gbWF4bWluKVxuICAgICAgICAgICAgSC5wdXNoKFBbbWF4bWF4XSk7XG4gICAgICAgIHZhciBib3QgPSBILmxlbmd0aDtcbiAgICAgICAgaSA9IG1heG1pbjtcbiAgICAgICAgd2hpbGUgKC0taSA+PSBtaW5tYXgpIHtcbiAgICAgICAgICAgIGlmIChpc0xlZnQoUFttYXhtYXhdLCBQW21pbm1heF0sIFBbaV0pID49IDAgJiYgaSA+IG1pbm1heClcbiAgICAgICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICAgIHdoaWxlIChILmxlbmd0aCA+IGJvdCkge1xuICAgICAgICAgICAgICAgIGlmIChpc0xlZnQoSFtILmxlbmd0aCAtIDJdLCBIW0gubGVuZ3RoIC0gMV0sIFBbaV0pID4gMClcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgZWxzZVxuICAgICAgICAgICAgICAgICAgICBILmxlbmd0aCAtPSAxO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKGkgIT0gbWlubWluKVxuICAgICAgICAgICAgICAgIEgucHVzaChQW2ldKTtcbiAgICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gSDtcbn1cbmV4cG9ydHMuQ29udmV4SHVsbCA9IENvbnZleEh1bGw7XG5mdW5jdGlvbiBjbG9ja3dpc2VSYWRpYWxTd2VlcChwLCBQLCBmKSB7XG4gICAgUC5zbGljZSgwKS5zb3J0KGZ1bmN0aW9uIChhLCBiKSB7IHJldHVybiBNYXRoLmF0YW4yKGEueSAtIHAueSwgYS54IC0gcC54KSAtIE1hdGguYXRhbjIoYi55IC0gcC55LCBiLnggLSBwLngpOyB9KS5mb3JFYWNoKGYpO1xufVxuZXhwb3J0cy5jbG9ja3dpc2VSYWRpYWxTd2VlcCA9IGNsb2Nrd2lzZVJhZGlhbFN3ZWVwO1xuZnVuY3Rpb24gbmV4dFBvbHlQb2ludChwLCBwcykge1xuICAgIGlmIChwLnBvbHlJbmRleCA9PT0gcHMubGVuZ3RoIC0gMSlcbiAgICAgICAgcmV0dXJuIHBzWzBdO1xuICAgIHJldHVybiBwc1twLnBvbHlJbmRleCArIDFdO1xufVxuZnVuY3Rpb24gcHJldlBvbHlQb2ludChwLCBwcykge1xuICAgIGlmIChwLnBvbHlJbmRleCA9PT0gMClcbiAgICAgICAgcmV0dXJuIHBzW3BzLmxlbmd0aCAtIDFdO1xuICAgIHJldHVybiBwc1twLnBvbHlJbmRleCAtIDFdO1xufVxuZnVuY3Rpb24gdGFuZ2VudF9Qb2ludFBvbHlDKFAsIFYpIHtcbiAgICB2YXIgVmNsb3NlZCA9IFYuc2xpY2UoMCk7XG4gICAgVmNsb3NlZC5wdXNoKFZbMF0pO1xuICAgIHJldHVybiB7IHJ0YW46IFJ0YW5nZW50X1BvaW50UG9seUMoUCwgVmNsb3NlZCksIGx0YW46IEx0YW5nZW50X1BvaW50UG9seUMoUCwgVmNsb3NlZCkgfTtcbn1cbmZ1bmN0aW9uIFJ0YW5nZW50X1BvaW50UG9seUMoUCwgVikge1xuICAgIHZhciBuID0gVi5sZW5ndGggLSAxO1xuICAgIHZhciBhLCBiLCBjO1xuICAgIHZhciB1cEEsIGRuQztcbiAgICBpZiAoYmVsb3coUCwgVlsxXSwgVlswXSkgJiYgIWFib3ZlKFAsIFZbbiAtIDFdLCBWWzBdKSlcbiAgICAgICAgcmV0dXJuIDA7XG4gICAgZm9yIChhID0gMCwgYiA9IG47Oykge1xuICAgICAgICBpZiAoYiAtIGEgPT09IDEpXG4gICAgICAgICAgICBpZiAoYWJvdmUoUCwgVlthXSwgVltiXSkpXG4gICAgICAgICAgICAgICAgcmV0dXJuIGE7XG4gICAgICAgICAgICBlbHNlXG4gICAgICAgICAgICAgICAgcmV0dXJuIGI7XG4gICAgICAgIGMgPSBNYXRoLmZsb29yKChhICsgYikgLyAyKTtcbiAgICAgICAgZG5DID0gYmVsb3coUCwgVltjICsgMV0sIFZbY10pO1xuICAgICAgICBpZiAoZG5DICYmICFhYm92ZShQLCBWW2MgLSAxXSwgVltjXSkpXG4gICAgICAgICAgICByZXR1cm4gYztcbiAgICAgICAgdXBBID0gYWJvdmUoUCwgVlthICsgMV0sIFZbYV0pO1xuICAgICAgICBpZiAodXBBKSB7XG4gICAgICAgICAgICBpZiAoZG5DKVxuICAgICAgICAgICAgICAgIGIgPSBjO1xuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgaWYgKGFib3ZlKFAsIFZbYV0sIFZbY10pKVxuICAgICAgICAgICAgICAgICAgICBiID0gYztcbiAgICAgICAgICAgICAgICBlbHNlXG4gICAgICAgICAgICAgICAgICAgIGEgPSBjO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgaWYgKCFkbkMpXG4gICAgICAgICAgICAgICAgYSA9IGM7XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICBpZiAoYmVsb3coUCwgVlthXSwgVltjXSkpXG4gICAgICAgICAgICAgICAgICAgIGIgPSBjO1xuICAgICAgICAgICAgICAgIGVsc2VcbiAgICAgICAgICAgICAgICAgICAgYSA9IGM7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG59XG5mdW5jdGlvbiBMdGFuZ2VudF9Qb2ludFBvbHlDKFAsIFYpIHtcbiAgICB2YXIgbiA9IFYubGVuZ3RoIC0gMTtcbiAgICB2YXIgYSwgYiwgYztcbiAgICB2YXIgZG5BLCBkbkM7XG4gICAgaWYgKGFib3ZlKFAsIFZbbiAtIDFdLCBWWzBdKSAmJiAhYmVsb3coUCwgVlsxXSwgVlswXSkpXG4gICAgICAgIHJldHVybiAwO1xuICAgIGZvciAoYSA9IDAsIGIgPSBuOzspIHtcbiAgICAgICAgaWYgKGIgLSBhID09PSAxKVxuICAgICAgICAgICAgaWYgKGJlbG93KFAsIFZbYV0sIFZbYl0pKVxuICAgICAgICAgICAgICAgIHJldHVybiBhO1xuICAgICAgICAgICAgZWxzZVxuICAgICAgICAgICAgICAgIHJldHVybiBiO1xuICAgICAgICBjID0gTWF0aC5mbG9vcigoYSArIGIpIC8gMik7XG4gICAgICAgIGRuQyA9IGJlbG93KFAsIFZbYyArIDFdLCBWW2NdKTtcbiAgICAgICAgaWYgKGFib3ZlKFAsIFZbYyAtIDFdLCBWW2NdKSAmJiAhZG5DKVxuICAgICAgICAgICAgcmV0dXJuIGM7XG4gICAgICAgIGRuQSA9IGJlbG93KFAsIFZbYSArIDFdLCBWW2FdKTtcbiAgICAgICAgaWYgKGRuQSkge1xuICAgICAgICAgICAgaWYgKCFkbkMpXG4gICAgICAgICAgICAgICAgYiA9IGM7XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICBpZiAoYmVsb3coUCwgVlthXSwgVltjXSkpXG4gICAgICAgICAgICAgICAgICAgIGIgPSBjO1xuICAgICAgICAgICAgICAgIGVsc2VcbiAgICAgICAgICAgICAgICAgICAgYSA9IGM7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICBpZiAoZG5DKVxuICAgICAgICAgICAgICAgIGEgPSBjO1xuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgaWYgKGFib3ZlKFAsIFZbYV0sIFZbY10pKVxuICAgICAgICAgICAgICAgICAgICBiID0gYztcbiAgICAgICAgICAgICAgICBlbHNlXG4gICAgICAgICAgICAgICAgICAgIGEgPSBjO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxufVxuZnVuY3Rpb24gdGFuZ2VudF9Qb2x5UG9seUMoViwgVywgdDEsIHQyLCBjbXAxLCBjbXAyKSB7XG4gICAgdmFyIGl4MSwgaXgyO1xuICAgIGl4MSA9IHQxKFdbMF0sIFYpO1xuICAgIGl4MiA9IHQyKFZbaXgxXSwgVyk7XG4gICAgdmFyIGRvbmUgPSBmYWxzZTtcbiAgICB3aGlsZSAoIWRvbmUpIHtcbiAgICAgICAgZG9uZSA9IHRydWU7XG4gICAgICAgIHdoaWxlICh0cnVlKSB7XG4gICAgICAgICAgICBpZiAoaXgxID09PSBWLmxlbmd0aCAtIDEpXG4gICAgICAgICAgICAgICAgaXgxID0gMDtcbiAgICAgICAgICAgIGlmIChjbXAxKFdbaXgyXSwgVltpeDFdLCBWW2l4MSArIDFdKSlcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICsraXgxO1xuICAgICAgICB9XG4gICAgICAgIHdoaWxlICh0cnVlKSB7XG4gICAgICAgICAgICBpZiAoaXgyID09PSAwKVxuICAgICAgICAgICAgICAgIGl4MiA9IFcubGVuZ3RoIC0gMTtcbiAgICAgICAgICAgIGlmIChjbXAyKFZbaXgxXSwgV1tpeDJdLCBXW2l4MiAtIDFdKSlcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIC0taXgyO1xuICAgICAgICAgICAgZG9uZSA9IGZhbHNlO1xuICAgICAgICB9XG4gICAgfVxuICAgIHJldHVybiB7IHQxOiBpeDEsIHQyOiBpeDIgfTtcbn1cbmV4cG9ydHMudGFuZ2VudF9Qb2x5UG9seUMgPSB0YW5nZW50X1BvbHlQb2x5QztcbmZ1bmN0aW9uIExSdGFuZ2VudF9Qb2x5UG9seUMoViwgVykge1xuICAgIHZhciBybCA9IFJMdGFuZ2VudF9Qb2x5UG9seUMoVywgVik7XG4gICAgcmV0dXJuIHsgdDE6IHJsLnQyLCB0MjogcmwudDEgfTtcbn1cbmV4cG9ydHMuTFJ0YW5nZW50X1BvbHlQb2x5QyA9IExSdGFuZ2VudF9Qb2x5UG9seUM7XG5mdW5jdGlvbiBSTHRhbmdlbnRfUG9seVBvbHlDKFYsIFcpIHtcbiAgICByZXR1cm4gdGFuZ2VudF9Qb2x5UG9seUMoViwgVywgUnRhbmdlbnRfUG9pbnRQb2x5QywgTHRhbmdlbnRfUG9pbnRQb2x5QywgYWJvdmUsIGJlbG93KTtcbn1cbmV4cG9ydHMuUkx0YW5nZW50X1BvbHlQb2x5QyA9IFJMdGFuZ2VudF9Qb2x5UG9seUM7XG5mdW5jdGlvbiBMTHRhbmdlbnRfUG9seVBvbHlDKFYsIFcpIHtcbiAgICByZXR1cm4gdGFuZ2VudF9Qb2x5UG9seUMoViwgVywgTHRhbmdlbnRfUG9pbnRQb2x5QywgTHRhbmdlbnRfUG9pbnRQb2x5QywgYmVsb3csIGJlbG93KTtcbn1cbmV4cG9ydHMuTEx0YW5nZW50X1BvbHlQb2x5QyA9IExMdGFuZ2VudF9Qb2x5UG9seUM7XG5mdW5jdGlvbiBSUnRhbmdlbnRfUG9seVBvbHlDKFYsIFcpIHtcbiAgICByZXR1cm4gdGFuZ2VudF9Qb2x5UG9seUMoViwgVywgUnRhbmdlbnRfUG9pbnRQb2x5QywgUnRhbmdlbnRfUG9pbnRQb2x5QywgYWJvdmUsIGFib3ZlKTtcbn1cbmV4cG9ydHMuUlJ0YW5nZW50X1BvbHlQb2x5QyA9IFJSdGFuZ2VudF9Qb2x5UG9seUM7XG52YXIgQmlUYW5nZW50ID0gKGZ1bmN0aW9uICgpIHtcbiAgICBmdW5jdGlvbiBCaVRhbmdlbnQodDEsIHQyKSB7XG4gICAgICAgIHRoaXMudDEgPSB0MTtcbiAgICAgICAgdGhpcy50MiA9IHQyO1xuICAgIH1cbiAgICByZXR1cm4gQmlUYW5nZW50O1xufSgpKTtcbmV4cG9ydHMuQmlUYW5nZW50ID0gQmlUYW5nZW50O1xudmFyIEJpVGFuZ2VudHMgPSAoZnVuY3Rpb24gKCkge1xuICAgIGZ1bmN0aW9uIEJpVGFuZ2VudHMoKSB7XG4gICAgfVxuICAgIHJldHVybiBCaVRhbmdlbnRzO1xufSgpKTtcbmV4cG9ydHMuQmlUYW5nZW50cyA9IEJpVGFuZ2VudHM7XG52YXIgVFZHUG9pbnQgPSAoZnVuY3Rpb24gKF9zdXBlcikge1xuICAgIF9fZXh0ZW5kcyhUVkdQb2ludCwgX3N1cGVyKTtcbiAgICBmdW5jdGlvbiBUVkdQb2ludCgpIHtcbiAgICAgICAgcmV0dXJuIF9zdXBlciAhPT0gbnVsbCAmJiBfc3VwZXIuYXBwbHkodGhpcywgYXJndW1lbnRzKSB8fCB0aGlzO1xuICAgIH1cbiAgICByZXR1cm4gVFZHUG9pbnQ7XG59KFBvaW50KSk7XG5leHBvcnRzLlRWR1BvaW50ID0gVFZHUG9pbnQ7XG52YXIgVmlzaWJpbGl0eVZlcnRleCA9IChmdW5jdGlvbiAoKSB7XG4gICAgZnVuY3Rpb24gVmlzaWJpbGl0eVZlcnRleChpZCwgcG9seWlkLCBwb2x5dmVydGlkLCBwKSB7XG4gICAgICAgIHRoaXMuaWQgPSBpZDtcbiAgICAgICAgdGhpcy5wb2x5aWQgPSBwb2x5aWQ7XG4gICAgICAgIHRoaXMucG9seXZlcnRpZCA9IHBvbHl2ZXJ0aWQ7XG4gICAgICAgIHRoaXMucCA9IHA7XG4gICAgICAgIHAudnYgPSB0aGlzO1xuICAgIH1cbiAgICByZXR1cm4gVmlzaWJpbGl0eVZlcnRleDtcbn0oKSk7XG5leHBvcnRzLlZpc2liaWxpdHlWZXJ0ZXggPSBWaXNpYmlsaXR5VmVydGV4O1xudmFyIFZpc2liaWxpdHlFZGdlID0gKGZ1bmN0aW9uICgpIHtcbiAgICBmdW5jdGlvbiBWaXNpYmlsaXR5RWRnZShzb3VyY2UsIHRhcmdldCkge1xuICAgICAgICB0aGlzLnNvdXJjZSA9IHNvdXJjZTtcbiAgICAgICAgdGhpcy50YXJnZXQgPSB0YXJnZXQ7XG4gICAgfVxuICAgIFZpc2liaWxpdHlFZGdlLnByb3RvdHlwZS5sZW5ndGggPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBkeCA9IHRoaXMuc291cmNlLnAueCAtIHRoaXMudGFyZ2V0LnAueDtcbiAgICAgICAgdmFyIGR5ID0gdGhpcy5zb3VyY2UucC55IC0gdGhpcy50YXJnZXQucC55O1xuICAgICAgICByZXR1cm4gTWF0aC5zcXJ0KGR4ICogZHggKyBkeSAqIGR5KTtcbiAgICB9O1xuICAgIHJldHVybiBWaXNpYmlsaXR5RWRnZTtcbn0oKSk7XG5leHBvcnRzLlZpc2liaWxpdHlFZGdlID0gVmlzaWJpbGl0eUVkZ2U7XG52YXIgVGFuZ2VudFZpc2liaWxpdHlHcmFwaCA9IChmdW5jdGlvbiAoKSB7XG4gICAgZnVuY3Rpb24gVGFuZ2VudFZpc2liaWxpdHlHcmFwaChQLCBnMCkge1xuICAgICAgICB0aGlzLlAgPSBQO1xuICAgICAgICB0aGlzLlYgPSBbXTtcbiAgICAgICAgdGhpcy5FID0gW107XG4gICAgICAgIGlmICghZzApIHtcbiAgICAgICAgICAgIHZhciBuID0gUC5sZW5ndGg7XG4gICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IG47IGkrKykge1xuICAgICAgICAgICAgICAgIHZhciBwID0gUFtpXTtcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBqID0gMDsgaiA8IHAubGVuZ3RoOyArK2opIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIHBqID0gcFtqXSwgdnYgPSBuZXcgVmlzaWJpbGl0eVZlcnRleCh0aGlzLlYubGVuZ3RoLCBpLCBqLCBwaik7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuVi5wdXNoKHZ2KTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGogPiAwKVxuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5FLnB1c2gobmV3IFZpc2liaWxpdHlFZGdlKHBbaiAtIDFdLnZ2LCB2dikpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAocC5sZW5ndGggPiAxKVxuICAgICAgICAgICAgICAgICAgICB0aGlzLkUucHVzaChuZXcgVmlzaWJpbGl0eUVkZ2UocFswXS52diwgcFtwLmxlbmd0aCAtIDFdLnZ2KSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IG4gLSAxOyBpKyspIHtcbiAgICAgICAgICAgICAgICB2YXIgUGkgPSBQW2ldO1xuICAgICAgICAgICAgICAgIGZvciAodmFyIGogPSBpICsgMTsgaiA8IG47IGorKykge1xuICAgICAgICAgICAgICAgICAgICB2YXIgUGogPSBQW2pdLCB0ID0gdGFuZ2VudHMoUGksIFBqKTtcbiAgICAgICAgICAgICAgICAgICAgZm9yICh2YXIgcSBpbiB0KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgYyA9IHRbcV0sIHNvdXJjZSA9IFBpW2MudDFdLCB0YXJnZXQgPSBQaltjLnQyXTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuYWRkRWRnZUlmVmlzaWJsZShzb3VyY2UsIHRhcmdldCwgaSwgaik7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICB0aGlzLlYgPSBnMC5WLnNsaWNlKDApO1xuICAgICAgICAgICAgdGhpcy5FID0gZzAuRS5zbGljZSgwKTtcbiAgICAgICAgfVxuICAgIH1cbiAgICBUYW5nZW50VmlzaWJpbGl0eUdyYXBoLnByb3RvdHlwZS5hZGRFZGdlSWZWaXNpYmxlID0gZnVuY3Rpb24gKHUsIHYsIGkxLCBpMikge1xuICAgICAgICBpZiAoIXRoaXMuaW50ZXJzZWN0c1BvbHlzKG5ldyBMaW5lU2VnbWVudCh1LngsIHUueSwgdi54LCB2LnkpLCBpMSwgaTIpKSB7XG4gICAgICAgICAgICB0aGlzLkUucHVzaChuZXcgVmlzaWJpbGl0eUVkZ2UodS52diwgdi52dikpO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBUYW5nZW50VmlzaWJpbGl0eUdyYXBoLnByb3RvdHlwZS5hZGRQb2ludCA9IGZ1bmN0aW9uIChwLCBpMSkge1xuICAgICAgICB2YXIgbiA9IHRoaXMuUC5sZW5ndGg7XG4gICAgICAgIHRoaXMuVi5wdXNoKG5ldyBWaXNpYmlsaXR5VmVydGV4KHRoaXMuVi5sZW5ndGgsIG4sIDAsIHApKTtcbiAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBuOyArK2kpIHtcbiAgICAgICAgICAgIGlmIChpID09PSBpMSlcbiAgICAgICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICAgIHZhciBwb2x5ID0gdGhpcy5QW2ldLCB0ID0gdGFuZ2VudF9Qb2ludFBvbHlDKHAsIHBvbHkpO1xuICAgICAgICAgICAgdGhpcy5hZGRFZGdlSWZWaXNpYmxlKHAsIHBvbHlbdC5sdGFuXSwgaTEsIGkpO1xuICAgICAgICAgICAgdGhpcy5hZGRFZGdlSWZWaXNpYmxlKHAsIHBvbHlbdC5ydGFuXSwgaTEsIGkpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBwLnZ2O1xuICAgIH07XG4gICAgVGFuZ2VudFZpc2liaWxpdHlHcmFwaC5wcm90b3R5cGUuaW50ZXJzZWN0c1BvbHlzID0gZnVuY3Rpb24gKGwsIGkxLCBpMikge1xuICAgICAgICBmb3IgKHZhciBpID0gMCwgbiA9IHRoaXMuUC5sZW5ndGg7IGkgPCBuOyArK2kpIHtcbiAgICAgICAgICAgIGlmIChpICE9IGkxICYmIGkgIT0gaTIgJiYgaW50ZXJzZWN0cyhsLCB0aGlzLlBbaV0pLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgfTtcbiAgICByZXR1cm4gVGFuZ2VudFZpc2liaWxpdHlHcmFwaDtcbn0oKSk7XG5leHBvcnRzLlRhbmdlbnRWaXNpYmlsaXR5R3JhcGggPSBUYW5nZW50VmlzaWJpbGl0eUdyYXBoO1xuZnVuY3Rpb24gaW50ZXJzZWN0cyhsLCBQKSB7XG4gICAgdmFyIGludHMgPSBbXTtcbiAgICBmb3IgKHZhciBpID0gMSwgbiA9IFAubGVuZ3RoOyBpIDwgbjsgKytpKSB7XG4gICAgICAgIHZhciBpbnQgPSByZWN0YW5nbGVfMS5SZWN0YW5nbGUubGluZUludGVyc2VjdGlvbihsLngxLCBsLnkxLCBsLngyLCBsLnkyLCBQW2kgLSAxXS54LCBQW2kgLSAxXS55LCBQW2ldLngsIFBbaV0ueSk7XG4gICAgICAgIGlmIChpbnQpXG4gICAgICAgICAgICBpbnRzLnB1c2goaW50KTtcbiAgICB9XG4gICAgcmV0dXJuIGludHM7XG59XG5mdW5jdGlvbiB0YW5nZW50cyhWLCBXKSB7XG4gICAgdmFyIG0gPSBWLmxlbmd0aCAtIDEsIG4gPSBXLmxlbmd0aCAtIDE7XG4gICAgdmFyIGJ0ID0gbmV3IEJpVGFuZ2VudHMoKTtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8PSBtOyArK2kpIHtcbiAgICAgICAgZm9yICh2YXIgaiA9IDA7IGogPD0gbjsgKytqKSB7XG4gICAgICAgICAgICB2YXIgdjEgPSBWW2kgPT0gMCA/IG0gOiBpIC0gMV07XG4gICAgICAgICAgICB2YXIgdjIgPSBWW2ldO1xuICAgICAgICAgICAgdmFyIHYzID0gVltpID09IG0gPyAwIDogaSArIDFdO1xuICAgICAgICAgICAgdmFyIHcxID0gV1tqID09IDAgPyBuIDogaiAtIDFdO1xuICAgICAgICAgICAgdmFyIHcyID0gV1tqXTtcbiAgICAgICAgICAgIHZhciB3MyA9IFdbaiA9PSBuID8gMCA6IGogKyAxXTtcbiAgICAgICAgICAgIHZhciB2MXYydzIgPSBpc0xlZnQodjEsIHYyLCB3Mik7XG4gICAgICAgICAgICB2YXIgdjJ3MXcyID0gaXNMZWZ0KHYyLCB3MSwgdzIpO1xuICAgICAgICAgICAgdmFyIHYydzJ3MyA9IGlzTGVmdCh2MiwgdzIsIHczKTtcbiAgICAgICAgICAgIHZhciB3MXcydjIgPSBpc0xlZnQodzEsIHcyLCB2Mik7XG4gICAgICAgICAgICB2YXIgdzJ2MXYyID0gaXNMZWZ0KHcyLCB2MSwgdjIpO1xuICAgICAgICAgICAgdmFyIHcydjJ2MyA9IGlzTGVmdCh3MiwgdjIsIHYzKTtcbiAgICAgICAgICAgIGlmICh2MXYydzIgPj0gMCAmJiB2MncxdzIgPj0gMCAmJiB2MncydzMgPCAwXG4gICAgICAgICAgICAgICAgJiYgdzF3MnYyID49IDAgJiYgdzJ2MXYyID49IDAgJiYgdzJ2MnYzIDwgMCkge1xuICAgICAgICAgICAgICAgIGJ0LmxsID0gbmV3IEJpVGFuZ2VudChpLCBqKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2UgaWYgKHYxdjJ3MiA8PSAwICYmIHYydzF3MiA8PSAwICYmIHYydzJ3MyA+IDBcbiAgICAgICAgICAgICAgICAmJiB3MXcydjIgPD0gMCAmJiB3MnYxdjIgPD0gMCAmJiB3MnYydjMgPiAwKSB7XG4gICAgICAgICAgICAgICAgYnQucnIgPSBuZXcgQmlUYW5nZW50KGksIGopO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSBpZiAodjF2MncyIDw9IDAgJiYgdjJ3MXcyID4gMCAmJiB2MncydzMgPD0gMFxuICAgICAgICAgICAgICAgICYmIHcxdzJ2MiA+PSAwICYmIHcydjF2MiA8IDAgJiYgdzJ2MnYzID49IDApIHtcbiAgICAgICAgICAgICAgICBidC5ybCA9IG5ldyBCaVRhbmdlbnQoaSwgaik7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIGlmICh2MXYydzIgPj0gMCAmJiB2MncxdzIgPCAwICYmIHYydzJ3MyA+PSAwXG4gICAgICAgICAgICAgICAgJiYgdzF3MnYyIDw9IDAgJiYgdzJ2MXYyID4gMCAmJiB3MnYydjMgPD0gMCkge1xuICAgICAgICAgICAgICAgIGJ0LmxyID0gbmV3IEJpVGFuZ2VudChpLCBqKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gYnQ7XG59XG5leHBvcnRzLnRhbmdlbnRzID0gdGFuZ2VudHM7XG5mdW5jdGlvbiBpc1BvaW50SW5zaWRlUG9seShwLCBwb2x5KSB7XG4gICAgZm9yICh2YXIgaSA9IDEsIG4gPSBwb2x5Lmxlbmd0aDsgaSA8IG47ICsraSlcbiAgICAgICAgaWYgKGJlbG93KHBvbHlbaSAtIDFdLCBwb2x5W2ldLCBwKSlcbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICByZXR1cm4gdHJ1ZTtcbn1cbmZ1bmN0aW9uIGlzQW55UEluUShwLCBxKSB7XG4gICAgcmV0dXJuICFwLmV2ZXJ5KGZ1bmN0aW9uICh2KSB7IHJldHVybiAhaXNQb2ludEluc2lkZVBvbHkodiwgcSk7IH0pO1xufVxuZnVuY3Rpb24gcG9seXNPdmVybGFwKHAsIHEpIHtcbiAgICBpZiAoaXNBbnlQSW5RKHAsIHEpKVxuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICBpZiAoaXNBbnlQSW5RKHEsIHApKVxuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICBmb3IgKHZhciBpID0gMSwgbiA9IHAubGVuZ3RoOyBpIDwgbjsgKytpKSB7XG4gICAgICAgIHZhciB2ID0gcFtpXSwgdSA9IHBbaSAtIDFdO1xuICAgICAgICBpZiAoaW50ZXJzZWN0cyhuZXcgTGluZVNlZ21lbnQodS54LCB1LnksIHYueCwgdi55KSwgcSkubGVuZ3RoID4gMClcbiAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cbiAgICByZXR1cm4gZmFsc2U7XG59XG5leHBvcnRzLnBvbHlzT3ZlcmxhcCA9IHBvbHlzT3ZlcmxhcDtcbi8vIyBzb3VyY2VNYXBwaW5nVVJMPWRhdGE6YXBwbGljYXRpb24vanNvbjtiYXNlNjQsZXlKMlpYSnphVzl1SWpvekxDSm1hV3hsSWpvaVoyVnZiUzVxY3lJc0luTnZkWEpqWlZKdmIzUWlPaUlpTENKemIzVnlZMlZ6SWpwYklpNHVMeTR1TDFkbFlrTnZiR0V2YzNKakwyZGxiMjB1ZEhNaVhTd2libUZ0WlhNaU9sdGRMQ0p0WVhCd2FXNW5jeUk2SWpzN096czdPenM3T3pzN096czdPMEZCUVVFc2VVTkJRWEZETzBGQlEycERPMGxCUVVFN1NVRkhRU3hEUVVGRE8wbEJRVVFzV1VGQlF6dEJRVUZFTEVOQlFVTXNRVUZJUkN4SlFVZERPMEZCU0Zrc2MwSkJRVXM3UVVGTGJFSTdTVUZEU1N4eFFrRkJiVUlzUlVGQlZTeEZRVUZUTEVWQlFWVXNSVUZCVXl4RlFVRlZMRVZCUVZNc1JVRkJWVHRSUVVGdVJTeFBRVUZGTEVkQlFVWXNSVUZCUlN4RFFVRlJPMUZCUVZNc1QwRkJSU3hIUVVGR0xFVkJRVVVzUTBGQlVUdFJRVUZUTEU5QlFVVXNSMEZCUml4RlFVRkZMRU5CUVZFN1VVRkJVeXhQUVVGRkxFZEJRVVlzUlVGQlJTeERRVUZSTzBsQlFVa3NRMEZCUXp0SlFVTXZSaXhyUWtGQlF6dEJRVUZFTEVOQlFVTXNRVUZHUkN4SlFVVkRPMEZCUmxrc2EwTkJRVmM3UVVGSmVFSTdTVUZCSzBJc05rSkJRVXM3U1VGQmNFTTdPMGxCUlVFc1EwRkJRenRKUVVGRUxHZENRVUZETzBGQlFVUXNRMEZCUXl4QlFVWkVMRU5CUVN0Q0xFdEJRVXNzUjBGRmJrTTdRVUZHV1N3NFFrRkJVenRCUVZWMFFpeFRRVUZuUWl4TlFVRk5MRU5CUVVNc1JVRkJVeXhGUVVGRkxFVkJRVk1zUlVGQlJTeEZRVUZUTzBsQlEyeEVMRTlCUVU4c1EwRkJReXhGUVVGRkxFTkJRVU1zUTBGQlF5eEhRVUZITEVWQlFVVXNRMEZCUXl4RFFVRkRMRU5CUVVNc1IwRkJSeXhEUVVGRExFVkJRVVVzUTBGQlF5eERRVUZETEVkQlFVY3NSVUZCUlN4RFFVRkRMRU5CUVVNc1EwRkJReXhIUVVGSExFTkJRVU1zUlVGQlJTeERRVUZETEVOQlFVTXNSMEZCUnl4RlFVRkZMRU5CUVVNc1EwRkJReXhEUVVGRExFZEJRVWNzUTBGQlF5eEZRVUZGTEVOQlFVTXNRMEZCUXl4SFFVRkhMRVZCUVVVc1EwRkJReXhEUVVGRExFTkJRVU1zUTBGQlF6dEJRVU42UlN4RFFVRkRPMEZCUmtRc2QwSkJSVU03UVVGRlJDeFRRVUZUTEV0QlFVc3NRMEZCUXl4RFFVRlJMRVZCUVVVc1JVRkJVeXhGUVVGRkxFVkJRVk03U1VGRGVrTXNUMEZCVHl4TlFVRk5MRU5CUVVNc1EwRkJReXhGUVVGRkxFVkJRVVVzUlVGQlJTeEZRVUZGTEVOQlFVTXNSMEZCUnl4RFFVRkRMRU5CUVVNN1FVRkRha01zUTBGQlF6dEJRVVZFTEZOQlFWTXNTMEZCU3l4RFFVRkRMRU5CUVZFc1JVRkJSU3hGUVVGVExFVkJRVVVzUlVGQlV6dEpRVU42UXl4UFFVRlBMRTFCUVUwc1EwRkJReXhEUVVGRExFVkJRVVVzUlVGQlJTeEZRVUZGTEVWQlFVVXNRMEZCUXl4SFFVRkhMRU5CUVVNc1EwRkJRenRCUVVOcVF5eERRVUZETzBGQlUwUXNVMEZCWjBJc1ZVRkJWU3hEUVVGRExFTkJRVlU3U1VGRGFrTXNTVUZCU1N4RFFVRkRMRWRCUVVjc1EwRkJReXhEUVVGRExFdEJRVXNzUTBGQlF5eERRVUZETEVOQlFVTXNRMEZCUXl4SlFVRkpMRU5CUVVNc1ZVRkJReXhEUVVGRExFVkJRVVVzUTBGQlF5eEpRVUZMTEU5QlFVRXNRMEZCUXl4RFFVRkRMRU5CUVVNc1MwRkJTeXhEUVVGRExFTkJRVU1zUTBGQlF5eERRVUZETEVOQlFVTXNRMEZCUXl4RFFVRkRMRU5CUVVNc1EwRkJReXhIUVVGSExFTkJRVU1zUTBGQlF5eERRVUZETEVOQlFVTXNRMEZCUXl4RFFVRkRMRU5CUVVNc1EwRkJReXhEUVVGRExFZEJRVWNzUTBGQlF5eERRVUZETEVOQlFVTXNSVUZCYmtNc1EwRkJiVU1zUTBGQlF5eERRVUZETzBsQlEzWkZMRWxCUVVrc1EwRkJReXhIUVVGSExFTkJRVU1zUTBGQlF5eE5RVUZOTEVWQlFVVXNRMEZCUXl4RFFVRkRPMGxCUTNCQ0xFbEJRVWtzVFVGQlRTeEhRVUZITEVOQlFVTXNRMEZCUXp0SlFVTm1MRWxCUVVrc1NVRkJTU3hIUVVGSExFTkJRVU1zUTBGQlF5eERRVUZETEVOQlFVTXNRMEZCUXl4RFFVRkRMRU5CUVVNN1NVRkRiRUlzUzBGQlN5eERRVUZETEVkQlFVY3NRMEZCUXl4RlFVRkZMRU5CUVVNc1IwRkJSeXhEUVVGRExFVkJRVVVzUlVGQlJTeERRVUZETEVWQlFVVTdVVUZEY0VJc1NVRkJTU3hEUVVGRExFTkJRVU1zUTBGQlF5eERRVUZETEVOQlFVTXNRMEZCUXl4TFFVRkxMRWxCUVVrN1dVRkJSU3hOUVVGTk8wdEJRemxDTzBsQlEwUXNTVUZCU1N4TlFVRk5MRWRCUVVjc1EwRkJReXhIUVVGSExFTkJRVU1zUTBGQlF6dEpRVU51UWl4SlFVRkpMRU5CUVVNc1IwRkJXU3hGUVVGRkxFTkJRVU03U1VGRGNFSXNRMEZCUXl4RFFVRkRMRWxCUVVrc1EwRkJReXhEUVVGRExFTkJRVU1zVFVGQlRTeERRVUZETEVOQlFVTXNRMEZCUXp0SlFVTnNRaXhKUVVGSkxFMUJRVTBzUzBGQlN5eERRVUZETEVkQlFVY3NRMEZCUXl4RlFVRkZPMUZCUTJ4Q0xFbEJRVWtzUTBGQlF5eERRVUZETEUxQlFVMHNRMEZCUXl4RFFVRkRMRU5CUVVNc1MwRkJTeXhEUVVGRExFTkJRVU1zVFVGQlRTeERRVUZETEVOQlFVTXNRMEZCUXp0WlFVTXpRaXhEUVVGRExFTkJRVU1zU1VGQlNTeERRVUZETEVOQlFVTXNRMEZCUXl4TlFVRk5MRU5CUVVNc1EwRkJReXhEUVVGRE8wdEJRM3BDTzFOQlFVMDdVVUZGU0N4SlFVRkpMRTFCUVUwc1JVRkJSU3hOUVVGTkxFZEJRVWNzUTBGQlF5eEhRVUZITEVOQlFVTXNRMEZCUXp0UlFVTXpRaXhKUVVGSkxFbEJRVWtzUjBGQlJ5eERRVUZETEVOQlFVTXNRMEZCUXl4SFFVRkhMRU5CUVVNc1EwRkJReXhEUVVGRExFTkJRVU1zUTBGQlF6dFJRVU4wUWl4TFFVRkxMRU5CUVVNc1IwRkJSeXhEUVVGRExFZEJRVWNzUTBGQlF5eEZRVUZGTEVOQlFVTXNTVUZCU1N4RFFVRkRMRVZCUVVVc1EwRkJReXhGUVVGRk8xbEJRM1pDTEVsQlFVa3NRMEZCUXl4RFFVRkRMRU5CUVVNc1EwRkJReXhEUVVGRExFTkJRVU1zUzBGQlN5eEpRVUZKTzJkQ1FVRkZMRTFCUVUwN1VVRkRMMElzVFVGQlRTeEhRVUZITEVOQlFVTXNSMEZCUnl4RFFVRkRMRU5CUVVNN1VVRkhaaXhEUVVGRExFZEJRVWNzVFVGQlRTeERRVUZETzFGQlExZ3NUMEZCVHl4RlFVRkZMRU5CUVVNc1NVRkJTU3hOUVVGTkxFVkJRVVU3V1VGRmJFSXNTVUZCU1N4TlFVRk5MRU5CUVVNc1EwRkJReXhEUVVGRExFMUJRVTBzUTBGQlF5eEZRVUZGTEVOQlFVTXNRMEZCUXl4TlFVRk5MRU5CUVVNc1JVRkJSU3hEUVVGRExFTkJRVU1zUTBGQlF5eERRVUZETEVOQlFVTXNTVUZCU1N4RFFVRkRMRWxCUVVrc1EwRkJReXhIUVVGSExFMUJRVTA3WjBKQlEzSkVMRk5CUVZNN1dVRkZZaXhQUVVGUExFTkJRVU1zUTBGQlF5eE5RVUZOTEVkQlFVY3NRMEZCUXl4RlFVTnVRanRuUWtGRlNTeEpRVUZKTEUxQlFVMHNRMEZCUXl4RFFVRkRMRU5CUVVNc1EwRkJReXhEUVVGRExFMUJRVTBzUjBGQlJ5eERRVUZETEVOQlFVTXNSVUZCUlN4RFFVRkRMRU5CUVVNc1EwRkJReXhEUVVGRExFMUJRVTBzUjBGQlJ5eERRVUZETEVOQlFVTXNSVUZCUlN4RFFVRkRMRU5CUVVNc1EwRkJReXhEUVVGRExFTkJRVU1zUjBGQlJ5eERRVUZETzI5Q1FVTnNSQ3hOUVVGTk96dHZRa0ZGVGl4RFFVRkRMRU5CUVVNc1RVRkJUU3hKUVVGSkxFTkJRVU1zUTBGQlF6dGhRVU55UWp0WlFVTkVMRWxCUVVrc1EwRkJReXhKUVVGSkxFMUJRVTA3WjBKQlFVVXNRMEZCUXl4RFFVRkRMRWxCUVVrc1EwRkJReXhEUVVGRExFTkJRVU1zUTBGQlF5eERRVUZETEVOQlFVTXNRMEZCUXp0VFFVTnFRenRSUVVkRUxFbEJRVWtzVFVGQlRTeEpRVUZKTEUxQlFVMDdXVUZEYUVJc1EwRkJReXhEUVVGRExFbEJRVWtzUTBGQlF5eERRVUZETEVOQlFVTXNUVUZCVFN4RFFVRkRMRU5CUVVNc1EwRkJRenRSUVVOMFFpeEpRVUZKTEVkQlFVY3NSMEZCUnl4RFFVRkRMRU5CUVVNc1RVRkJUU3hEUVVGRE8xRkJRMjVDTEVOQlFVTXNSMEZCUnl4TlFVRk5MRU5CUVVNN1VVRkRXQ3hQUVVGUExFVkJRVVVzUTBGQlF5eEpRVUZKTEUxQlFVMHNSVUZCUlR0WlFVVnNRaXhKUVVGSkxFMUJRVTBzUTBGQlF5eERRVUZETEVOQlFVTXNUVUZCVFN4RFFVRkRMRVZCUVVVc1EwRkJReXhEUVVGRExFMUJRVTBzUTBGQlF5eEZRVUZGTEVOQlFVTXNRMEZCUXl4RFFVRkRMRU5CUVVNc1EwRkJReXhKUVVGSkxFTkJRVU1zU1VGQlNTeERRVUZETEVkQlFVY3NUVUZCVFR0blFrRkRja1FzVTBGQlV6dFpRVVZpTEU5QlFVOHNRMEZCUXl4RFFVRkRMRTFCUVUwc1IwRkJSeXhIUVVGSExFVkJRM0pDTzJkQ1FVVkpMRWxCUVVrc1RVRkJUU3hEUVVGRExFTkJRVU1zUTBGQlF5eERRVUZETEVOQlFVTXNUVUZCVFN4SFFVRkhMRU5CUVVNc1EwRkJReXhGUVVGRkxFTkJRVU1zUTBGQlF5eERRVUZETEVOQlFVTXNUVUZCVFN4SFFVRkhMRU5CUVVNc1EwRkJReXhGUVVGRkxFTkJRVU1zUTBGQlF5eERRVUZETEVOQlFVTXNRMEZCUXl4SFFVRkhMRU5CUVVNN2IwSkJRMnhFTEUxQlFVMDdPMjlDUVVWT0xFTkJRVU1zUTBGQlF5eE5RVUZOTEVsQlFVa3NRMEZCUXl4RFFVRkRPMkZCUTNKQ08xbEJRMFFzU1VGQlNTeERRVUZETEVsQlFVa3NUVUZCVFR0blFrRkJSU3hEUVVGRExFTkJRVU1zU1VGQlNTeERRVUZETEVOQlFVTXNRMEZCUXl4RFFVRkRMRU5CUVVNc1EwRkJReXhEUVVGRE8xTkJRMnBETzB0QlEwbzdTVUZEUkN4UFFVRlBMRU5CUVVNc1EwRkJRenRCUVVOaUxFTkJRVU03UVVFNVJFUXNaME5CT0VSRE8wRkJSMFFzVTBGQlowSXNiMEpCUVc5Q0xFTkJRVU1zUTBGQlVTeEZRVUZGTEVOQlFWVXNSVUZCUlN4RFFVRnhRanRKUVVNMVJTeERRVUZETEVOQlFVTXNTMEZCU3l4RFFVRkRMRU5CUVVNc1EwRkJReXhEUVVGRExFbEJRVWtzUTBGRFdDeFZRVUZETEVOQlFVTXNSVUZCUlN4RFFVRkRMRWxCUVVzc1QwRkJRU3hKUVVGSkxFTkJRVU1zUzBGQlN5eERRVUZETEVOQlFVTXNRMEZCUXl4RFFVRkRMRWRCUVVjc1EwRkJReXhEUVVGRExFTkJRVU1zUlVGQlJTeERRVUZETEVOQlFVTXNRMEZCUXl4SFFVRkhMRU5CUVVNc1EwRkJReXhEUVVGRExFTkJRVU1zUjBGQlJ5eEpRVUZKTEVOQlFVTXNTMEZCU3l4RFFVRkRMRU5CUVVNc1EwRkJReXhEUVVGRExFZEJRVWNzUTBGQlF5eERRVUZETEVOQlFVTXNSVUZCUlN4RFFVRkRMRU5CUVVNc1EwRkJReXhIUVVGSExFTkJRVU1zUTBGQlF5eERRVUZETEVOQlFVTXNSVUZCYmtVc1EwRkJiVVVzUTBGRE5VVXNRMEZCUXl4UFFVRlBMRU5CUVVNc1EwRkJReXhEUVVGRExFTkJRVU03UVVGRGNrSXNRMEZCUXp0QlFVcEVMRzlFUVVsRE8wRkJSVVFzVTBGQlV5eGhRVUZoTEVOQlFVTXNRMEZCV1N4RlFVRkZMRVZCUVdVN1NVRkRhRVFzU1VGQlNTeERRVUZETEVOQlFVTXNVMEZCVXl4TFFVRkxMRVZCUVVVc1EwRkJReXhOUVVGTkxFZEJRVWNzUTBGQlF6dFJRVUZGTEU5QlFVOHNSVUZCUlN4RFFVRkRMRU5CUVVNc1EwRkJReXhEUVVGRE8wbEJRMmhFTEU5QlFVOHNSVUZCUlN4RFFVRkRMRU5CUVVNc1EwRkJReXhUUVVGVExFZEJRVWNzUTBGQlF5eERRVUZETEVOQlFVTTdRVUZETDBJc1EwRkJRenRCUVVWRUxGTkJRVk1zWVVGQllTeERRVUZETEVOQlFWa3NSVUZCUlN4RlFVRmxPMGxCUTJoRUxFbEJRVWtzUTBGQlF5eERRVUZETEZOQlFWTXNTMEZCU3l4RFFVRkRPMUZCUVVVc1QwRkJUeXhGUVVGRkxFTkJRVU1zUlVGQlJTeERRVUZETEUxQlFVMHNSMEZCUnl4RFFVRkRMRU5CUVVNc1EwRkJRenRKUVVOb1JDeFBRVUZQTEVWQlFVVXNRMEZCUXl4RFFVRkRMRU5CUVVNc1UwRkJVeXhIUVVGSExFTkJRVU1zUTBGQlF5eERRVUZETzBGQlF5OUNMRU5CUVVNN1FVRlJSQ3hUUVVGVExHdENRVUZyUWl4RFFVRkRMRU5CUVZFc1JVRkJSU3hEUVVGVk8wbEJSelZETEVsQlFVa3NUMEZCVHl4SFFVRkhMRU5CUVVNc1EwRkJReXhMUVVGTExFTkJRVU1zUTBGQlF5eERRVUZETEVOQlFVTTdTVUZEZWtJc1QwRkJUeXhEUVVGRExFbEJRVWtzUTBGQlF5eERRVUZETEVOQlFVTXNRMEZCUXl4RFFVRkRMRU5CUVVNc1EwRkJRenRKUVVWdVFpeFBRVUZQTEVWQlFVVXNTVUZCU1N4RlFVRkZMRzFDUVVGdFFpeERRVUZETEVOQlFVTXNSVUZCUlN4UFFVRlBMRU5CUVVNc1JVRkJSU3hKUVVGSkxFVkJRVVVzYlVKQlFXMUNMRU5CUVVNc1EwRkJReXhGUVVGRkxFOUJRVThzUTBGQlF5eEZRVUZGTEVOQlFVTTdRVUZETlVZc1EwRkJRenRCUVZORUxGTkJRVk1zYlVKQlFXMUNMRU5CUVVNc1EwRkJVU3hGUVVGRkxFTkJRVlU3U1VGRE4wTXNTVUZCU1N4RFFVRkRMRWRCUVVjc1EwRkJReXhEUVVGRExFMUJRVTBzUjBGQlJ5eERRVUZETEVOQlFVTTdTVUZIY2tJc1NVRkJTU3hEUVVGVExFVkJRVVVzUTBGQlV5eEZRVUZGTEVOQlFWTXNRMEZCUXp0SlFVTndReXhKUVVGSkxFZEJRVmtzUlVGQlJTeEhRVUZaTEVOQlFVTTdTVUZKTDBJc1NVRkJTU3hMUVVGTExFTkJRVU1zUTBGQlF5eEZRVUZGTEVOQlFVTXNRMEZCUXl4RFFVRkRMRU5CUVVNc1JVRkJSU3hEUVVGRExFTkJRVU1zUTBGQlF5eERRVUZETEVOQlFVTXNTVUZCU1N4RFFVRkRMRXRCUVVzc1EwRkJReXhEUVVGRExFVkJRVVVzUTBGQlF5eERRVUZETEVOQlFVTXNSMEZCUnl4RFFVRkRMRU5CUVVNc1JVRkJSU3hEUVVGRExFTkJRVU1zUTBGQlF5eERRVUZETEVOQlFVTTdVVUZEYWtRc1QwRkJUeXhEUVVGRExFTkJRVU03U1VGRllpeExRVUZMTEVOQlFVTXNSMEZCUnl4RFFVRkRMRVZCUVVVc1EwRkJReXhIUVVGSExFTkJRVU1zU1VGQlN6dFJRVU5zUWl4SlFVRkpMRU5CUVVNc1IwRkJSeXhEUVVGRExFdEJRVXNzUTBGQlF6dFpRVU5ZTEVsQlFVa3NTMEZCU3l4RFFVRkRMRU5CUVVNc1JVRkJSU3hEUVVGRExFTkJRVU1zUTBGQlF5eERRVUZETEVWQlFVVXNRMEZCUXl4RFFVRkRMRU5CUVVNc1EwRkJReXhEUVVGRE8yZENRVU53UWl4UFFVRlBMRU5CUVVNc1EwRkJRenM3WjBKQlJWUXNUMEZCVHl4RFFVRkRMRU5CUVVNN1VVRkZha0lzUTBGQlF5eEhRVUZITEVsQlFVa3NRMEZCUXl4TFFVRkxMRU5CUVVNc1EwRkJReXhEUVVGRExFZEJRVWNzUTBGQlF5eERRVUZETEVkQlFVY3NRMEZCUXl4RFFVRkRMRU5CUVVNN1VVRkROVUlzUjBGQlJ5eEhRVUZITEV0QlFVc3NRMEZCUXl4RFFVRkRMRVZCUVVVc1EwRkJReXhEUVVGRExFTkJRVU1zUjBGQlJ5eERRVUZETEVOQlFVTXNSVUZCUlN4RFFVRkRMRU5CUVVNc1EwRkJReXhEUVVGRExFTkJRVU1zUTBGQlF6dFJRVU12UWl4SlFVRkpMRWRCUVVjc1NVRkJTU3hEUVVGRExFdEJRVXNzUTBGQlF5eERRVUZETEVWQlFVVXNRMEZCUXl4RFFVRkRMRU5CUVVNc1IwRkJSeXhEUVVGRExFTkJRVU1zUlVGQlJTeERRVUZETEVOQlFVTXNRMEZCUXl4RFFVRkRMRU5CUVVNN1dVRkRhRU1zVDBGQlR5eERRVUZETEVOQlFVTTdVVUZKWWl4SFFVRkhMRWRCUVVjc1MwRkJTeXhEUVVGRExFTkJRVU1zUlVGQlJTeERRVUZETEVOQlFVTXNRMEZCUXl4SFFVRkhMRU5CUVVNc1EwRkJReXhGUVVGRkxFTkJRVU1zUTBGQlF5eERRVUZETEVOQlFVTXNRMEZCUXl4RFFVRkRPMUZCUXk5Q0xFbEJRVWtzUjBGQlJ5eEZRVUZGTzFsQlEwd3NTVUZCU1N4SFFVRkhPMmRDUVVOSUxFTkJRVU1zUjBGQlJ5eERRVUZETEVOQlFVTTdhVUpCUTB3N1owSkJRMFFzU1VGQlNTeExRVUZMTEVOQlFVTXNRMEZCUXl4RlFVRkZMRU5CUVVNc1EwRkJReXhEUVVGRExFTkJRVU1zUlVGQlJTeERRVUZETEVOQlFVTXNRMEZCUXl4RFFVRkRMRU5CUVVNN2IwSkJRM0JDTEVOQlFVTXNSMEZCUnl4RFFVRkRMRU5CUVVNN08yOUNRVVZPTEVOQlFVTXNSMEZCUnl4RFFVRkRMRU5CUVVNN1lVRkRZanRUUVVOS08yRkJRMGs3V1VGRFJDeEpRVUZKTEVOQlFVTXNSMEZCUnp0blFrRkRTaXhEUVVGRExFZEJRVWNzUTBGQlF5eERRVUZETzJsQ1FVTk1PMmRDUVVORUxFbEJRVWtzUzBGQlN5eERRVUZETEVOQlFVTXNSVUZCUlN4RFFVRkRMRU5CUVVNc1EwRkJReXhEUVVGRExFVkJRVVVzUTBGQlF5eERRVUZETEVOQlFVTXNRMEZCUXl4RFFVRkRPMjlDUVVOd1FpeERRVUZETEVkQlFVY3NRMEZCUXl4RFFVRkRPenR2UWtGRlRpeERRVUZETEVkQlFVY3NRMEZCUXl4RFFVRkRPMkZCUTJJN1UwRkRTanRMUVVOS08wRkJRMHdzUTBGQlF6dEJRVkZFTEZOQlFWTXNiVUpCUVcxQ0xFTkJRVU1zUTBGQlVTeEZRVUZGTEVOQlFWVTdTVUZETjBNc1NVRkJTU3hEUVVGRExFZEJRVWNzUTBGQlF5eERRVUZETEUxQlFVMHNSMEZCUnl4RFFVRkRMRU5CUVVNN1NVRkZja0lzU1VGQlNTeERRVUZUTEVWQlFVVXNRMEZCVXl4RlFVRkZMRU5CUVZNc1EwRkJRenRKUVVOd1F5eEpRVUZKTEVkQlFWa3NSVUZCUlN4SFFVRlpMRU5CUVVNN1NVRkpMMElzU1VGQlNTeExRVUZMTEVOQlFVTXNRMEZCUXl4RlFVRkZMRU5CUVVNc1EwRkJReXhEUVVGRExFZEJRVWNzUTBGQlF5eERRVUZETEVWQlFVVXNRMEZCUXl4RFFVRkRMRU5CUVVNc1EwRkJReXhEUVVGRExFbEJRVWtzUTBGQlF5eExRVUZMTEVOQlFVTXNRMEZCUXl4RlFVRkZMRU5CUVVNc1EwRkJReXhEUVVGRExFTkJRVU1zUlVGQlJTeERRVUZETEVOQlFVTXNRMEZCUXl4RFFVRkRMRU5CUVVNN1VVRkRha1FzVDBGQlR5eERRVUZETEVOQlFVTTdTVUZGWWl4TFFVRkxMRU5CUVVNc1IwRkJSeXhEUVVGRExFVkJRVVVzUTBGQlF5eEhRVUZITEVOQlFVTXNTVUZCU3p0UlFVTnNRaXhKUVVGSkxFTkJRVU1zUjBGQlJ5eERRVUZETEV0QlFVc3NRMEZCUXp0WlFVTllMRWxCUVVrc1MwRkJTeXhEUVVGRExFTkJRVU1zUlVGQlJTeERRVUZETEVOQlFVTXNRMEZCUXl4RFFVRkRMRVZCUVVVc1EwRkJReXhEUVVGRExFTkJRVU1zUTBGQlF5eERRVUZETzJkQ1FVTndRaXhQUVVGUExFTkJRVU1zUTBGQlF6czdaMEpCUlZRc1QwRkJUeXhEUVVGRExFTkJRVU03VVVGRmFrSXNRMEZCUXl4SFFVRkhMRWxCUVVrc1EwRkJReXhMUVVGTExFTkJRVU1zUTBGQlF5eERRVUZETEVkQlFVY3NRMEZCUXl4RFFVRkRMRWRCUVVjc1EwRkJReXhEUVVGRExFTkJRVU03VVVGRE5VSXNSMEZCUnl4SFFVRkhMRXRCUVVzc1EwRkJReXhEUVVGRExFVkJRVVVzUTBGQlF5eERRVUZETEVOQlFVTXNSMEZCUnl4RFFVRkRMRU5CUVVNc1JVRkJSU3hEUVVGRExFTkJRVU1zUTBGQlF5eERRVUZETEVOQlFVTXNRMEZCUXp0UlFVTXZRaXhKUVVGSkxFdEJRVXNzUTBGQlF5eERRVUZETEVWQlFVVXNRMEZCUXl4RFFVRkRMRU5CUVVNc1IwRkJSeXhEUVVGRExFTkJRVU1zUlVGQlJTeERRVUZETEVOQlFVTXNRMEZCUXl4RFFVRkRMRU5CUVVNc1NVRkJTU3hEUVVGRExFZEJRVWM3V1VGRGFFTXNUMEZCVHl4RFFVRkRMRU5CUVVNN1VVRkpZaXhIUVVGSExFZEJRVWNzUzBGQlN5eERRVUZETEVOQlFVTXNSVUZCUlN4RFFVRkRMRU5CUVVNc1EwRkJReXhIUVVGSExFTkJRVU1zUTBGQlF5eEZRVUZGTEVOQlFVTXNRMEZCUXl4RFFVRkRMRU5CUVVNc1EwRkJReXhEUVVGRE8xRkJReTlDTEVsQlFVa3NSMEZCUnl4RlFVRkZPMWxCUTB3c1NVRkJTU3hEUVVGRExFZEJRVWM3WjBKQlEwb3NRMEZCUXl4SFFVRkhMRU5CUVVNc1EwRkJRenRwUWtGRFREdG5Ra0ZEUkN4SlFVRkpMRXRCUVVzc1EwRkJReXhEUVVGRExFVkJRVVVzUTBGQlF5eERRVUZETEVOQlFVTXNRMEZCUXl4RlFVRkZMRU5CUVVNc1EwRkJReXhEUVVGRExFTkJRVU1zUTBGQlF6dHZRa0ZEY0VJc1EwRkJReXhIUVVGSExFTkJRVU1zUTBGQlF6czdiMEpCUlU0c1EwRkJReXhIUVVGSExFTkJRVU1zUTBGQlF6dGhRVU5pTzFOQlEwbzdZVUZEU1R0WlFVTkVMRWxCUVVrc1IwRkJSenRuUWtGRFNDeERRVUZETEVkQlFVY3NRMEZCUXl4RFFVRkRPMmxDUVVOTU8yZENRVU5FTEVsQlFVa3NTMEZCU3l4RFFVRkRMRU5CUVVNc1JVRkJSU3hEUVVGRExFTkJRVU1zUTBGQlF5eERRVUZETEVWQlFVVXNRMEZCUXl4RFFVRkRMRU5CUVVNc1EwRkJReXhEUVVGRE8yOUNRVU53UWl4RFFVRkRMRWRCUVVjc1EwRkJReXhEUVVGRE96dHZRa0ZGVGl4RFFVRkRMRWRCUVVjc1EwRkJReXhEUVVGRE8yRkJRMkk3VTBGRFNqdExRVU5LTzBGQlEwd3NRMEZCUXp0QlFWTkVMRk5CUVdkQ0xHbENRVUZwUWl4RFFVRkRMRU5CUVZVc1JVRkJSU3hEUVVGVkxFVkJRVVVzUlVGQmIwTXNSVUZCUlN4RlFVRnZReXhGUVVGRkxFbEJRU3RETEVWQlFVVXNTVUZCSzBNN1NVRkRiRThzU1VGQlNTeEhRVUZYTEVWQlFVVXNSMEZCVnl4RFFVRkRPMGxCUnpkQ0xFZEJRVWNzUjBGQlJ5eEZRVUZGTEVOQlFVTXNRMEZCUXl4RFFVRkRMRU5CUVVNc1EwRkJReXhGUVVGRkxFTkJRVU1zUTBGQlF5eERRVUZETzBsQlEyeENMRWRCUVVjc1IwRkJSeXhGUVVGRkxFTkJRVU1zUTBGQlF5eERRVUZETEVkQlFVY3NRMEZCUXl4RlFVRkZMRU5CUVVNc1EwRkJReXhEUVVGRE8wbEJSM0JDTEVsQlFVa3NTVUZCU1N4SFFVRkhMRXRCUVVzc1EwRkJRenRKUVVOcVFpeFBRVUZQTEVOQlFVTXNTVUZCU1N4RlFVRkZPMUZCUTFZc1NVRkJTU3hIUVVGSExFbEJRVWtzUTBGQlF6dFJRVU5hTEU5QlFVOHNTVUZCU1N4RlFVRkZPMWxCUTFRc1NVRkJTU3hIUVVGSExFdEJRVXNzUTBGQlF5eERRVUZETEUxQlFVMHNSMEZCUnl4RFFVRkRPMmRDUVVGRkxFZEJRVWNzUjBGQlJ5eERRVUZETEVOQlFVTTdXVUZEYkVNc1NVRkJTU3hKUVVGSkxFTkJRVU1zUTBGQlF5eERRVUZETEVkQlFVY3NRMEZCUXl4RlFVRkZMRU5CUVVNc1EwRkJReXhIUVVGSExFTkJRVU1zUlVGQlJTeERRVUZETEVOQlFVTXNSMEZCUnl4SFFVRkhMRU5CUVVNc1EwRkJReXhEUVVGRE8yZENRVUZGTEUxQlFVMDdXVUZETlVNc1JVRkJSU3hIUVVGSExFTkJRVU03VTBGRFZEdFJRVU5FTEU5QlFVOHNTVUZCU1N4RlFVRkZPMWxCUTFRc1NVRkJTU3hIUVVGSExFdEJRVXNzUTBGQlF6dG5Ra0ZCUlN4SFFVRkhMRWRCUVVjc1EwRkJReXhEUVVGRExFMUJRVTBzUjBGQlJ5eERRVUZETEVOQlFVTTdXVUZEYkVNc1NVRkJTU3hKUVVGSkxFTkJRVU1zUTBGQlF5eERRVUZETEVkQlFVY3NRMEZCUXl4RlFVRkZMRU5CUVVNc1EwRkJReXhIUVVGSExFTkJRVU1zUlVGQlJTeERRVUZETEVOQlFVTXNSMEZCUnl4SFFVRkhMRU5CUVVNc1EwRkJReXhEUVVGRE8yZENRVUZGTEUxQlFVMDdXVUZETlVNc1JVRkJSU3hIUVVGSExFTkJRVU03V1VGRFRpeEpRVUZKTEVkQlFVY3NTMEZCU3l4RFFVRkRPMU5CUTJoQ08wdEJRMG83U1VGRFJDeFBRVUZQTEVWQlFVVXNSVUZCUlN4RlFVRkZMRWRCUVVjc1JVRkJSU3hGUVVGRkxFVkJRVVVzUjBGQlJ5eEZRVUZGTEVOQlFVTTdRVUZEYUVNc1EwRkJRenRCUVhoQ1JDdzRRMEYzUWtNN1FVRkZSQ3hUUVVGblFpeHRRa0ZCYlVJc1EwRkJReXhEUVVGVkxFVkJRVVVzUTBGQlZUdEpRVU4wUkN4SlFVRkpMRVZCUVVVc1IwRkJSeXh0UWtGQmJVSXNRMEZCUXl4RFFVRkRMRVZCUVVVc1EwRkJReXhEUVVGRExFTkJRVU03U1VGRGJrTXNUMEZCVHl4RlFVRkZMRVZCUVVVc1JVRkJSU3hGUVVGRkxFTkJRVU1zUlVGQlJTeEZRVUZGTEVWQlFVVXNSVUZCUlN4RlFVRkZMRU5CUVVNc1JVRkJSU3hGUVVGRkxFTkJRVU03UVVGRGNFTXNRMEZCUXp0QlFVaEVMR3RFUVVkRE8wRkJSVVFzVTBGQlowSXNiVUpCUVcxQ0xFTkJRVU1zUTBGQlZTeEZRVUZGTEVOQlFWVTdTVUZEZEVRc1QwRkJUeXhwUWtGQmFVSXNRMEZCUXl4RFFVRkRMRVZCUVVVc1EwRkJReXhGUVVGRkxHMUNRVUZ0UWl4RlFVRkZMRzFDUVVGdFFpeEZRVUZGTEV0QlFVc3NSVUZCUlN4TFFVRkxMRU5CUVVNc1EwRkJRenRCUVVNelJpeERRVUZETzBGQlJrUXNhMFJCUlVNN1FVRkZSQ3hUUVVGblFpeHRRa0ZCYlVJc1EwRkJReXhEUVVGVkxFVkJRVVVzUTBGQlZUdEpRVU4wUkN4UFFVRlBMR2xDUVVGcFFpeERRVUZETEVOQlFVTXNSVUZCUlN4RFFVRkRMRVZCUVVVc2JVSkJRVzFDTEVWQlFVVXNiVUpCUVcxQ0xFVkJRVVVzUzBGQlN5eEZRVUZGTEV0QlFVc3NRMEZCUXl4RFFVRkRPMEZCUXpOR0xFTkJRVU03UVVGR1JDeHJSRUZGUXp0QlFVVkVMRk5CUVdkQ0xHMUNRVUZ0UWl4RFFVRkRMRU5CUVZVc1JVRkJSU3hEUVVGVk8wbEJRM1JFTEU5QlFVOHNhVUpCUVdsQ0xFTkJRVU1zUTBGQlF5eEZRVUZGTEVOQlFVTXNSVUZCUlN4dFFrRkJiVUlzUlVGQlJTeHRRa0ZCYlVJc1JVRkJSU3hMUVVGTExFVkJRVVVzUzBGQlN5eERRVUZETEVOQlFVTTdRVUZETTBZc1EwRkJRenRCUVVaRUxHdEVRVVZETzBGQlJVUTdTVUZEU1N4dFFrRkJiVUlzUlVGQlZTeEZRVUZUTEVWQlFWVTdVVUZCTjBJc1QwRkJSU3hIUVVGR0xFVkJRVVVzUTBGQlVUdFJRVUZUTEU5QlFVVXNSMEZCUml4RlFVRkZMRU5CUVZFN1NVRkJTU3hEUVVGRE8wbEJRM3BFTEdkQ1FVRkRPMEZCUVVRc1EwRkJReXhCUVVaRUxFbEJSVU03UVVGR1dTdzRRa0ZCVXp0QlFVbDBRanRKUVVGQk8wbEJTMEVzUTBGQlF6dEpRVUZFTEdsQ1FVRkRPMEZCUVVRc1EwRkJReXhCUVV4RUxFbEJTME03UVVGTVdTeG5RMEZCVlR0QlFVOTJRanRKUVVFNFFpdzBRa0ZCU3p0SlFVRnVRenM3U1VGRlFTeERRVUZETzBsQlFVUXNaVUZCUXp0QlFVRkVMRU5CUVVNc1FVRkdSQ3hEUVVFNFFpeExRVUZMTEVkQlJXeERPMEZCUmxrc05FSkJRVkU3UVVGSmNrSTdTVUZEU1N3d1FrRkRWeXhGUVVGVkxFVkJRMVlzVFVGQll5eEZRVU5rTEZWQlFXdENMRVZCUTJ4Q0xFTkJRVmM3VVVGSVdDeFBRVUZGTEVkQlFVWXNSVUZCUlN4RFFVRlJPMUZCUTFZc1YwRkJUU3hIUVVGT0xFMUJRVTBzUTBGQlVUdFJRVU5rTEdWQlFWVXNSMEZCVml4VlFVRlZMRU5CUVZFN1VVRkRiRUlzVFVGQlF5eEhRVUZFTEVOQlFVTXNRMEZCVlR0UlFVVnNRaXhEUVVGRExFTkJRVU1zUlVGQlJTeEhRVUZITEVsQlFVa3NRMEZCUXp0SlFVTm9RaXhEUVVGRE8wbEJRMHdzZFVKQlFVTTdRVUZCUkN4RFFVRkRMRUZCVkVRc1NVRlRRenRCUVZSWkxEUkRRVUZuUWp0QlFWYzNRanRKUVVOSkxIZENRVU5YTEUxQlFYZENMRVZCUTNoQ0xFMUJRWGRDTzFGQlJIaENMRmRCUVUwc1IwRkJUaXhOUVVGTkxFTkJRV3RDTzFGQlEzaENMRmRCUVUwc1IwRkJUaXhOUVVGTkxFTkJRV3RDTzBsQlFVa3NRMEZCUXp0SlFVTjRReXdyUWtGQlRTeEhRVUZPTzFGQlEwa3NTVUZCU1N4RlFVRkZMRWRCUVVjc1NVRkJTU3hEUVVGRExFMUJRVTBzUTBGQlF5eERRVUZETEVOQlFVTXNRMEZCUXl4SFFVRkhMRWxCUVVrc1EwRkJReXhOUVVGTkxFTkJRVU1zUTBGQlF5eERRVUZETEVOQlFVTXNRMEZCUXp0UlFVTXpReXhKUVVGSkxFVkJRVVVzUjBGQlJ5eEpRVUZKTEVOQlFVTXNUVUZCVFN4RFFVRkRMRU5CUVVNc1EwRkJReXhEUVVGRExFZEJRVWNzU1VGQlNTeERRVUZETEUxQlFVMHNRMEZCUXl4RFFVRkRMRU5CUVVNc1EwRkJReXhEUVVGRE8xRkJRek5ETEU5QlFVOHNTVUZCU1N4RFFVRkRMRWxCUVVrc1EwRkJReXhGUVVGRkxFZEJRVWNzUlVGQlJTeEhRVUZITEVWQlFVVXNSMEZCUnl4RlFVRkZMRU5CUVVNc1EwRkJRenRKUVVONFF5eERRVUZETzBsQlEwd3NjVUpCUVVNN1FVRkJSQ3hEUVVGRExFRkJWRVFzU1VGVFF6dEJRVlJaTEhkRFFVRmpPMEZCVnpOQ08wbEJSMGtzWjBOQlFXMUNMRU5CUVdVc1JVRkJSU3hGUVVGdFJEdFJRVUZ3UlN4TlFVRkRMRWRCUVVRc1EwRkJReXhEUVVGak8xRkJSbXhETEUxQlFVTXNSMEZCZFVJc1JVRkJSU3hEUVVGRE8xRkJRek5DTEUxQlFVTXNSMEZCY1VJc1JVRkJSU3hEUVVGRE8xRkJSWEpDTEVsQlFVa3NRMEZCUXl4RlFVRkZMRVZCUVVVN1dVRkRUQ3hKUVVGSkxFTkJRVU1zUjBGQlJ5eERRVUZETEVOQlFVTXNUVUZCVFN4RFFVRkRPMWxCUldwQ0xFdEJRVXNzU1VGQlNTeERRVUZETEVkQlFVY3NRMEZCUXl4RlFVRkZMRU5CUVVNc1IwRkJSeXhEUVVGRExFVkJRVVVzUTBGQlF5eEZRVUZGTEVWQlFVVTdaMEpCUTNoQ0xFbEJRVWtzUTBGQlF5eEhRVUZITEVOQlFVTXNRMEZCUXl4RFFVRkRMRU5CUVVNc1EwRkJRenRuUWtGRllpeExRVUZMTEVsQlFVa3NRMEZCUXl4SFFVRkhMRU5CUVVNc1JVRkJSU3hEUVVGRExFZEJRVWNzUTBGQlF5eERRVUZETEUxQlFVMHNSVUZCUlN4RlFVRkZMRU5CUVVNc1JVRkJSVHR2UWtGREwwSXNTVUZCU1N4RlFVRkZMRWRCUVVjc1EwRkJReXhEUVVGRExFTkJRVU1zUTBGQlF5eEZRVU5VTEVWQlFVVXNSMEZCUnl4SlFVRkpMR2RDUVVGblFpeERRVUZETEVsQlFVa3NRMEZCUXl4RFFVRkRMRU5CUVVNc1RVRkJUU3hGUVVGRkxFTkJRVU1zUlVGQlJTeERRVUZETEVWQlFVVXNSVUZCUlN4RFFVRkRMRU5CUVVNN2IwSkJRM1pFTEVsQlFVa3NRMEZCUXl4RFFVRkRMRU5CUVVNc1NVRkJTU3hEUVVGRExFVkJRVVVzUTBGQlF5eERRVUZETzI5Q1FVbG9RaXhKUVVGSkxFTkJRVU1zUjBGQlJ5eERRVUZETzNkQ1FVRkZMRWxCUVVrc1EwRkJReXhEUVVGRExFTkJRVU1zU1VGQlNTeERRVUZETEVsQlFVa3NZMEZCWXl4RFFVRkRMRU5CUVVNc1EwRkJReXhEUVVGRExFZEJRVWNzUTBGQlF5eERRVUZETEVOQlFVTXNSVUZCUlN4RlFVRkZMRVZCUVVVc1EwRkJReXhEUVVGRExFTkJRVU03YVVKQlF5OUVPMmRDUVVWRUxFbEJRVWtzUTBGQlF5eERRVUZETEUxQlFVMHNSMEZCUnl4RFFVRkRPMjlDUVVGRkxFbEJRVWtzUTBGQlF5eERRVUZETEVOQlFVTXNTVUZCU1N4RFFVRkRMRWxCUVVrc1kwRkJZeXhEUVVGRExFTkJRVU1zUTBGQlF5eERRVUZETEVOQlFVTXNRMEZCUXl4RlFVRkZMRVZCUVVVc1EwRkJReXhEUVVGRExFTkJRVU1zUTBGQlF5eE5RVUZOTEVkQlFVY3NRMEZCUXl4RFFVRkRMRU5CUVVNc1JVRkJSU3hEUVVGRExFTkJRVU1zUTBGQlF6dGhRVU5zUmp0WlFVTkVMRXRCUVVzc1NVRkJTU3hEUVVGRExFZEJRVWNzUTBGQlF5eEZRVUZGTEVOQlFVTXNSMEZCUnl4RFFVRkRMRWRCUVVjc1EwRkJReXhGUVVGRkxFTkJRVU1zUlVGQlJTeEZRVUZGTzJkQ1FVTTFRaXhKUVVGSkxFVkJRVVVzUjBGQlJ5eERRVUZETEVOQlFVTXNRMEZCUXl4RFFVRkRMRU5CUVVNN1owSkJRMlFzUzBGQlN5eEpRVUZKTEVOQlFVTXNSMEZCUnl4RFFVRkRMRWRCUVVjc1EwRkJReXhGUVVGRkxFTkJRVU1zUjBGQlJ5eERRVUZETEVWQlFVVXNRMEZCUXl4RlFVRkZMRVZCUVVVN2IwSkJRelZDTEVsQlFVa3NSVUZCUlN4SFFVRkhMRU5CUVVNc1EwRkJReXhEUVVGRExFTkJRVU1zUlVGRFZDeERRVUZETEVkQlFVY3NVVUZCVVN4RFFVRkRMRVZCUVVVc1JVRkJSU3hGUVVGRkxFTkJRVU1zUTBGQlF6dHZRa0ZEZWtJc1MwRkJTeXhKUVVGSkxFTkJRVU1zU1VGQlNTeERRVUZETEVWQlFVVTdkMEpCUTJJc1NVRkJTU3hEUVVGRExFZEJRVWNzUTBGQlF5eERRVUZETEVOQlFVTXNRMEZCUXl4RlFVTlNMRTFCUVUwc1IwRkJSeXhGUVVGRkxFTkJRVU1zUTBGQlF5eERRVUZETEVWQlFVVXNRMEZCUXl4RlFVRkZMRTFCUVUwc1IwRkJSeXhGUVVGRkxFTkJRVU1zUTBGQlF5eERRVUZETEVWQlFVVXNRMEZCUXl4RFFVRkRPM2RDUVVONlF5eEpRVUZKTEVOQlFVTXNaMEpCUVdkQ0xFTkJRVU1zVFVGQlRTeEZRVUZGTEUxQlFVMHNSVUZCUlN4RFFVRkRMRVZCUVVVc1EwRkJReXhEUVVGRExFTkJRVU03Y1VKQlF5OURPMmxDUVVOS08yRkJRMG83VTBGRFNqdGhRVUZOTzFsQlEwZ3NTVUZCU1N4RFFVRkRMRU5CUVVNc1IwRkJSeXhGUVVGRkxFTkJRVU1zUTBGQlF5eERRVUZETEV0QlFVc3NRMEZCUXl4RFFVRkRMRU5CUVVNc1EwRkJRenRaUVVOMlFpeEpRVUZKTEVOQlFVTXNRMEZCUXl4SFFVRkhMRVZCUVVVc1EwRkJReXhEUVVGRExFTkJRVU1zUzBGQlN5eERRVUZETEVOQlFVTXNRMEZCUXl4RFFVRkRPMU5CUXpGQ08wbEJRMHdzUTBGQlF6dEpRVU5FTEdsRVFVRm5RaXhIUVVGb1FpeFZRVUZwUWl4RFFVRlhMRVZCUVVVc1EwRkJWeXhGUVVGRkxFVkJRVlVzUlVGQlJTeEZRVUZWTzFGQlF6ZEVMRWxCUVVrc1EwRkJReXhKUVVGSkxFTkJRVU1zWlVGQlpTeERRVUZETEVsQlFVa3NWMEZCVnl4RFFVRkRMRU5CUVVNc1EwRkJReXhEUVVGRExFVkJRVVVzUTBGQlF5eERRVUZETEVOQlFVTXNSVUZCUlN4RFFVRkRMRU5CUVVNc1EwRkJReXhGUVVGRkxFTkJRVU1zUTBGQlF5eERRVUZETEVOQlFVTXNSVUZCUlN4RlFVRkZMRVZCUVVVc1JVRkJSU3hEUVVGRExFVkJRVVU3V1VGRGNFVXNTVUZCU1N4RFFVRkRMRU5CUVVNc1EwRkJReXhKUVVGSkxFTkJRVU1zU1VGQlNTeGpRVUZqTEVOQlFVTXNRMEZCUXl4RFFVRkRMRVZCUVVVc1JVRkJSU3hEUVVGRExFTkJRVU1zUlVGQlJTeERRVUZETEVOQlFVTXNRMEZCUXp0VFFVTXZRenRKUVVOTUxFTkJRVU03U1VGRFJDeDVRMEZCVVN4SFFVRlNMRlZCUVZNc1EwRkJWeXhGUVVGRkxFVkJRVlU3VVVGRE5VSXNTVUZCU1N4RFFVRkRMRWRCUVVjc1NVRkJTU3hEUVVGRExFTkJRVU1zUTBGQlF5eE5RVUZOTEVOQlFVTTdVVUZEZEVJc1NVRkJTU3hEUVVGRExFTkJRVU1zUTBGQlF5eEpRVUZKTEVOQlFVTXNTVUZCU1N4blFrRkJaMElzUTBGQlF5eEpRVUZKTEVOQlFVTXNRMEZCUXl4RFFVRkRMRTFCUVUwc1JVRkJSU3hEUVVGRExFVkJRVVVzUTBGQlF5eEZRVUZGTEVOQlFVTXNRMEZCUXl4RFFVRkRMRU5CUVVNN1VVRkRNVVFzUzBGQlN5eEpRVUZKTEVOQlFVTXNSMEZCUnl4RFFVRkRMRVZCUVVVc1EwRkJReXhIUVVGSExFTkJRVU1zUlVGQlJTeEZRVUZGTEVOQlFVTXNSVUZCUlR0WlFVTjRRaXhKUVVGSkxFTkJRVU1zUzBGQlN5eEZRVUZGTzJkQ1FVRkZMRk5CUVZNN1dVRkRka0lzU1VGQlNTeEpRVUZKTEVkQlFVY3NTVUZCU1N4RFFVRkRMRU5CUVVNc1EwRkJReXhEUVVGRExFTkJRVU1zUlVGRGFFSXNRMEZCUXl4SFFVRkhMR3RDUVVGclFpeERRVUZETEVOQlFVTXNSVUZCUlN4SlFVRkpMRU5CUVVNc1EwRkJRenRaUVVOd1F5eEpRVUZKTEVOQlFVTXNaMEpCUVdkQ0xFTkJRVU1zUTBGQlF5eEZRVUZGTEVsQlFVa3NRMEZCUXl4RFFVRkRMRU5CUVVNc1NVRkJTU3hEUVVGRExFVkJRVVVzUlVGQlJTeEZRVUZGTEVOQlFVTXNRMEZCUXl4RFFVRkRPMWxCUXpsRExFbEJRVWtzUTBGQlF5eG5Ra0ZCWjBJc1EwRkJReXhEUVVGRExFVkJRVVVzU1VGQlNTeERRVUZETEVOQlFVTXNRMEZCUXl4SlFVRkpMRU5CUVVNc1JVRkJSU3hGUVVGRkxFVkJRVVVzUTBGQlF5eERRVUZETEVOQlFVTTdVMEZEYWtRN1VVRkRSQ3hQUVVGUExFTkJRVU1zUTBGQlF5eEZRVUZGTEVOQlFVTTdTVUZEYUVJc1EwRkJRenRKUVVOUExHZEVRVUZsTEVkQlFYWkNMRlZCUVhkQ0xFTkJRV01zUlVGQlJTeEZRVUZWTEVWQlFVVXNSVUZCVlR0UlFVTXhSQ3hMUVVGTExFbEJRVWtzUTBGQlF5eEhRVUZITEVOQlFVTXNSVUZCUlN4RFFVRkRMRWRCUVVjc1NVRkJTU3hEUVVGRExFTkJRVU1zUTBGQlF5eE5RVUZOTEVWQlFVVXNRMEZCUXl4SFFVRkhMRU5CUVVNc1JVRkJSU3hGUVVGRkxFTkJRVU1zUlVGQlJUdFpRVU16UXl4SlFVRkpMRU5CUVVNc1NVRkJTU3hGUVVGRkxFbEJRVWtzUTBGQlF5eEpRVUZKTEVWQlFVVXNTVUZCU1N4VlFVRlZMRU5CUVVNc1EwRkJReXhGUVVGRkxFbEJRVWtzUTBGQlF5eERRVUZETEVOQlFVTXNRMEZCUXl4RFFVRkRMRU5CUVVNc1EwRkJReXhOUVVGTkxFZEJRVWNzUTBGQlF5eEZRVUZGTzJkQ1FVTXpSQ3hQUVVGUExFbEJRVWtzUTBGQlF6dGhRVU5tTzFOQlEwbzdVVUZEUkN4UFFVRlBMRXRCUVVzc1EwRkJRenRKUVVOcVFpeERRVUZETzBsQlEwd3NOa0pCUVVNN1FVRkJSQ3hEUVVGRExFRkJhRVZFTEVsQlowVkRPMEZCYUVWWkxIZEVRVUZ6UWp0QlFXdEZia01zVTBGQlV5eFZRVUZWTEVOQlFVTXNRMEZCWXl4RlFVRkZMRU5CUVZVN1NVRkRNVU1zU1VGQlNTeEpRVUZKTEVkQlFVY3NSVUZCUlN4RFFVRkRPMGxCUTJRc1MwRkJTeXhKUVVGSkxFTkJRVU1zUjBGQlJ5eERRVUZETEVWQlFVVXNRMEZCUXl4SFFVRkhMRU5CUVVNc1EwRkJReXhOUVVGTkxFVkJRVVVzUTBGQlF5eEhRVUZITEVOQlFVTXNSVUZCUlN4RlFVRkZMRU5CUVVNc1JVRkJSVHRSUVVOMFF5eEpRVUZKTEVkQlFVY3NSMEZCUnl4eFFrRkJVeXhEUVVGRExHZENRVUZuUWl4RFFVTm9ReXhEUVVGRExFTkJRVU1zUlVGQlJTeEZRVUZGTEVOQlFVTXNRMEZCUXl4RlFVRkZMRVZCUTFZc1EwRkJReXhEUVVGRExFVkJRVVVzUlVGQlJTeERRVUZETEVOQlFVTXNSVUZCUlN4RlFVTldMRU5CUVVNc1EwRkJReXhEUVVGRExFZEJRVWNzUTBGQlF5eERRVUZETEVOQlFVTXNRMEZCUXl4RlFVRkZMRU5CUVVNc1EwRkJReXhEUVVGRExFZEJRVWNzUTBGQlF5eERRVUZETEVOQlFVTXNRMEZCUXl4RlFVTjBRaXhEUVVGRExFTkJRVU1zUTBGQlF5eERRVUZETEVOQlFVTXNRMEZCUXl4RlFVRkZMRU5CUVVNc1EwRkJReXhEUVVGRExFTkJRVU1zUTBGQlF5eERRVUZETEVOQlEySXNRMEZCUXp0UlFVTk9MRWxCUVVrc1IwRkJSenRaUVVGRkxFbEJRVWtzUTBGQlF5eEpRVUZKTEVOQlFVTXNSMEZCUnl4RFFVRkRMRU5CUVVNN1MwRkRNMEk3U1VGRFJDeFBRVUZQTEVsQlFVa3NRMEZCUXp0QlFVTm9RaXhEUVVGRE8wRkJSVVFzVTBGQlowSXNVVUZCVVN4RFFVRkRMRU5CUVZVc1JVRkJSU3hEUVVGVk8wbEJSVE5ETEVsQlFVa3NRMEZCUXl4SFFVRkhMRU5CUVVNc1EwRkJReXhOUVVGTkxFZEJRVWNzUTBGQlF5eEZRVUZGTEVOQlFVTXNSMEZCUnl4RFFVRkRMRU5CUVVNc1RVRkJUU3hIUVVGSExFTkJRVU1zUTBGQlF6dEpRVU4yUXl4SlFVRkpMRVZCUVVVc1IwRkJSeXhKUVVGSkxGVkJRVlVzUlVGQlJTeERRVUZETzBsQlF6RkNMRXRCUVVzc1NVRkJTU3hEUVVGRExFZEJRVWNzUTBGQlF5eEZRVUZGTEVOQlFVTXNTVUZCU1N4RFFVRkRMRVZCUVVVc1JVRkJSU3hEUVVGRExFVkJRVVU3VVVGRGVrSXNTMEZCU3l4SlFVRkpMRU5CUVVNc1IwRkJSeXhEUVVGRExFVkJRVVVzUTBGQlF5eEpRVUZKTEVOQlFVTXNSVUZCUlN4RlFVRkZMRU5CUVVNc1JVRkJSVHRaUVVONlFpeEpRVUZKTEVWQlFVVXNSMEZCUnl4RFFVRkRMRU5CUVVNc1EwRkJReXhKUVVGSkxFTkJRVU1zUTBGQlF5eERRVUZETEVOQlFVTXNRMEZCUXl4RFFVRkRMRU5CUVVNc1EwRkJReXhEUVVGRExFZEJRVWNzUTBGQlF5eERRVUZETEVOQlFVTTdXVUZETDBJc1NVRkJTU3hGUVVGRkxFZEJRVWNzUTBGQlF5eERRVUZETEVOQlFVTXNRMEZCUXl4RFFVRkRPMWxCUTJRc1NVRkJTU3hGUVVGRkxFZEJRVWNzUTBGQlF5eERRVUZETEVOQlFVTXNTVUZCU1N4RFFVRkRMRU5CUVVNc1EwRkJReXhEUVVGRExFTkJRVU1zUTBGQlF5eERRVUZETEVOQlFVTXNRMEZCUXl4SFFVRkhMRU5CUVVNc1EwRkJReXhEUVVGRE8xbEJReTlDTEVsQlFVa3NSVUZCUlN4SFFVRkhMRU5CUVVNc1EwRkJReXhEUVVGRExFbEJRVWtzUTBGQlF5eERRVUZETEVOQlFVTXNRMEZCUXl4RFFVRkRMRU5CUVVNc1EwRkJReXhEUVVGRExFTkJRVU1zUjBGQlJ5eERRVUZETEVOQlFVTXNRMEZCUXp0WlFVTXZRaXhKUVVGSkxFVkJRVVVzUjBGQlJ5eERRVUZETEVOQlFVTXNRMEZCUXl4RFFVRkRMRU5CUVVNN1dVRkRaQ3hKUVVGSkxFVkJRVVVzUjBGQlJ5eERRVUZETEVOQlFVTXNRMEZCUXl4SlFVRkpMRU5CUVVNc1EwRkJReXhEUVVGRExFTkJRVU1zUTBGQlF5eERRVUZETEVOQlFVTXNRMEZCUXl4RFFVRkRMRWRCUVVjc1EwRkJReXhEUVVGRExFTkJRVU03V1VGREwwSXNTVUZCU1N4TlFVRk5MRWRCUVVjc1RVRkJUU3hEUVVGRExFVkJRVVVzUlVGQlJTeEZRVUZGTEVWQlFVVXNSVUZCUlN4RFFVRkRMRU5CUVVNN1dVRkRhRU1zU1VGQlNTeE5RVUZOTEVkQlFVY3NUVUZCVFN4RFFVRkRMRVZCUVVVc1JVRkJSU3hGUVVGRkxFVkJRVVVzUlVGQlJTeERRVUZETEVOQlFVTTdXVUZEYUVNc1NVRkJTU3hOUVVGTkxFZEJRVWNzVFVGQlRTeERRVUZETEVWQlFVVXNSVUZCUlN4RlFVRkZMRVZCUVVVc1JVRkJSU3hEUVVGRExFTkJRVU03V1VGRGFFTXNTVUZCU1N4TlFVRk5MRWRCUVVjc1RVRkJUU3hEUVVGRExFVkJRVVVzUlVGQlJTeEZRVUZGTEVWQlFVVXNSVUZCUlN4RFFVRkRMRU5CUVVNN1dVRkRhRU1zU1VGQlNTeE5RVUZOTEVkQlFVY3NUVUZCVFN4RFFVRkRMRVZCUVVVc1JVRkJSU3hGUVVGRkxFVkJRVVVzUlVGQlJTeERRVUZETEVOQlFVTTdXVUZEYUVNc1NVRkJTU3hOUVVGTkxFZEJRVWNzVFVGQlRTeERRVUZETEVWQlFVVXNSVUZCUlN4RlFVRkZMRVZCUVVVc1JVRkJSU3hEUVVGRExFTkJRVU03V1VGRGFFTXNTVUZCU1N4TlFVRk5MRWxCUVVrc1EwRkJReXhKUVVGSkxFMUJRVTBzU1VGQlNTeERRVUZETEVsQlFVa3NUVUZCVFN4SFFVRkhMRU5CUVVNN2JVSkJRM0pETEUxQlFVMHNTVUZCU1N4RFFVRkRMRWxCUVVrc1RVRkJUU3hKUVVGSkxFTkJRVU1zU1VGQlNTeE5RVUZOTEVkQlFVY3NRMEZCUXl4RlFVRkZPMmRDUVVONlF5eEZRVUZGTEVOQlFVTXNSVUZCUlN4SFFVRkhMRWxCUVVrc1UwRkJVeXhEUVVGRExFTkJRVU1zUlVGQlJTeERRVUZETEVOQlFVTXNRMEZCUXp0aFFVTnVRenRwUWtGQlRTeEpRVUZKTEUxQlFVMHNTVUZCU1N4RFFVRkRMRWxCUVVrc1RVRkJUU3hKUVVGSkxFTkJRVU1zU1VGQlNTeE5RVUZOTEVkQlFVY3NRMEZCUXp0dFFrRkROVU1zVFVGQlRTeEpRVUZKTEVOQlFVTXNTVUZCU1N4TlFVRk5MRWxCUVVrc1EwRkJReXhKUVVGSkxFMUJRVTBzUjBGQlJ5eERRVUZETEVWQlFVVTdaMEpCUTNwRExFVkJRVVVzUTBGQlF5eEZRVUZGTEVkQlFVY3NTVUZCU1N4VFFVRlRMRU5CUVVNc1EwRkJReXhGUVVGRkxFTkJRVU1zUTBGQlF5eERRVUZETzJGQlEyNURPMmxDUVVGTkxFbEJRVWtzVFVGQlRTeEpRVUZKTEVOQlFVTXNTVUZCU1N4TlFVRk5MRWRCUVVjc1EwRkJReXhKUVVGSkxFMUJRVTBzU1VGQlNTeERRVUZETzIxQ1FVTTFReXhOUVVGTkxFbEJRVWtzUTBGQlF5eEpRVUZKTEUxQlFVMHNSMEZCUnl4RFFVRkRMRWxCUVVrc1RVRkJUU3hKUVVGSkxFTkJRVU1zUlVGQlJUdG5Ra0ZEZWtNc1JVRkJSU3hEUVVGRExFVkJRVVVzUjBGQlJ5eEpRVUZKTEZOQlFWTXNRMEZCUXl4RFFVRkRMRVZCUVVVc1EwRkJReXhEUVVGRExFTkJRVU03WVVGRGJrTTdhVUpCUVUwc1NVRkJTU3hOUVVGTkxFbEJRVWtzUTBGQlF5eEpRVUZKTEUxQlFVMHNSMEZCUnl4RFFVRkRMRWxCUVVrc1RVRkJUU3hKUVVGSkxFTkJRVU03YlVKQlF6VkRMRTFCUVUwc1NVRkJTU3hEUVVGRExFbEJRVWtzVFVGQlRTeEhRVUZITEVOQlFVTXNTVUZCU1N4TlFVRk5MRWxCUVVrc1EwRkJReXhGUVVGRk8yZENRVU42UXl4RlFVRkZMRU5CUVVNc1JVRkJSU3hIUVVGSExFbEJRVWtzVTBGQlV5eERRVUZETEVOQlFVTXNSVUZCUlN4RFFVRkRMRU5CUVVNc1EwRkJRenRoUVVOdVF6dFRRVU5LTzB0QlEwbzdTVUZEUkN4UFFVRlBMRVZCUVVVc1EwRkJRenRCUVVOa0xFTkJRVU03UVVGc1EwUXNORUpCYTBORE8wRkJSVVFzVTBGQlV5eHBRa0ZCYVVJc1EwRkJReXhEUVVGUkxFVkJRVVVzU1VGQllUdEpRVU01UXl4TFFVRkxMRWxCUVVrc1EwRkJReXhIUVVGSExFTkJRVU1zUlVGQlJTeERRVUZETEVkQlFVY3NTVUZCU1N4RFFVRkRMRTFCUVUwc1JVRkJSU3hEUVVGRExFZEJRVWNzUTBGQlF5eEZRVUZGTEVWQlFVVXNRMEZCUXp0UlFVTjJReXhKUVVGSkxFdEJRVXNzUTBGQlF5eEpRVUZKTEVOQlFVTXNRMEZCUXl4SFFVRkhMRU5CUVVNc1EwRkJReXhGUVVGRkxFbEJRVWtzUTBGQlF5eERRVUZETEVOQlFVTXNSVUZCUlN4RFFVRkRMRU5CUVVNN1dVRkJSU3hQUVVGUExFdEJRVXNzUTBGQlF6dEpRVU55UkN4UFFVRlBMRWxCUVVrc1EwRkJRenRCUVVOb1FpeERRVUZETzBGQlJVUXNVMEZCVXl4VFFVRlRMRU5CUVVNc1EwRkJWU3hGUVVGRkxFTkJRVlU3U1VGRGNrTXNUMEZCVHl4RFFVRkRMRU5CUVVNc1EwRkJReXhMUVVGTExFTkJRVU1zVlVGQlFTeERRVUZETEVsQlFVa3NUMEZCUVN4RFFVRkRMR2xDUVVGcFFpeERRVUZETEVOQlFVTXNSVUZCUlN4RFFVRkRMRU5CUVVNc1JVRkJlRUlzUTBGQmQwSXNRMEZCUXl4RFFVRkRPMEZCUTI1RUxFTkJRVU03UVVGRlJDeFRRVUZuUWl4WlFVRlpMRU5CUVVNc1EwRkJWU3hGUVVGRkxFTkJRVlU3U1VGREwwTXNTVUZCU1N4VFFVRlRMRU5CUVVNc1EwRkJReXhGUVVGRkxFTkJRVU1zUTBGQlF6dFJRVUZGTEU5QlFVOHNTVUZCU1N4RFFVRkRPMGxCUTJwRExFbEJRVWtzVTBGQlV5eERRVUZETEVOQlFVTXNSVUZCUlN4RFFVRkRMRU5CUVVNN1VVRkJSU3hQUVVGUExFbEJRVWtzUTBGQlF6dEpRVU5xUXl4TFFVRkxMRWxCUVVrc1EwRkJReXhIUVVGSExFTkJRVU1zUlVGQlJTeERRVUZETEVkQlFVY3NRMEZCUXl4RFFVRkRMRTFCUVUwc1JVRkJSU3hEUVVGRExFZEJRVWNzUTBGQlF5eEZRVUZGTEVWQlFVVXNRMEZCUXl4RlFVRkZPMUZCUTNSRExFbEJRVWtzUTBGQlF5eEhRVUZITEVOQlFVTXNRMEZCUXl4RFFVRkRMRU5CUVVNc1JVRkJSU3hEUVVGRExFZEJRVWNzUTBGQlF5eERRVUZETEVOQlFVTXNSMEZCUnl4RFFVRkRMRU5CUVVNc1EwRkJRenRSUVVNelFpeEpRVUZKTEZWQlFWVXNRMEZCUXl4SlFVRkpMRmRCUVZjc1EwRkJReXhEUVVGRExFTkJRVU1zUTBGQlF5eEZRVUZGTEVOQlFVTXNRMEZCUXl4RFFVRkRMRVZCUVVVc1EwRkJReXhEUVVGRExFTkJRVU1zUlVGQlJTeERRVUZETEVOQlFVTXNRMEZCUXl4RFFVRkRMRVZCUVVVc1EwRkJReXhEUVVGRExFTkJRVU1zVFVGQlRTeEhRVUZITEVOQlFVTTdXVUZCUlN4UFFVRlBMRWxCUVVrc1EwRkJRenRMUVVOc1JqdEpRVU5FTEU5QlFVOHNTMEZCU3l4RFFVRkRPMEZCUTJwQ0xFTkJRVU03UVVGU1JDeHZRMEZSUXlKOSIsIlwidXNlIHN0cmljdFwiO1xuT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsIFwiX19lc01vZHVsZVwiLCB7IHZhbHVlOiB0cnVlIH0pO1xudmFyIHJlY3RhbmdsZV8xID0gcmVxdWlyZShcIi4vcmVjdGFuZ2xlXCIpO1xudmFyIHZwc2NfMSA9IHJlcXVpcmUoXCIuL3Zwc2NcIik7XG52YXIgc2hvcnRlc3RwYXRoc18xID0gcmVxdWlyZShcIi4vc2hvcnRlc3RwYXRoc1wiKTtcbnZhciBOb2RlV3JhcHBlciA9IChmdW5jdGlvbiAoKSB7XG4gICAgZnVuY3Rpb24gTm9kZVdyYXBwZXIoaWQsIHJlY3QsIGNoaWxkcmVuKSB7XG4gICAgICAgIHRoaXMuaWQgPSBpZDtcbiAgICAgICAgdGhpcy5yZWN0ID0gcmVjdDtcbiAgICAgICAgdGhpcy5jaGlsZHJlbiA9IGNoaWxkcmVuO1xuICAgICAgICB0aGlzLmxlYWYgPSB0eXBlb2YgY2hpbGRyZW4gPT09ICd1bmRlZmluZWQnIHx8IGNoaWxkcmVuLmxlbmd0aCA9PT0gMDtcbiAgICB9XG4gICAgcmV0dXJuIE5vZGVXcmFwcGVyO1xufSgpKTtcbmV4cG9ydHMuTm9kZVdyYXBwZXIgPSBOb2RlV3JhcHBlcjtcbnZhciBWZXJ0ID0gKGZ1bmN0aW9uICgpIHtcbiAgICBmdW5jdGlvbiBWZXJ0KGlkLCB4LCB5LCBub2RlLCBsaW5lKSB7XG4gICAgICAgIGlmIChub2RlID09PSB2b2lkIDApIHsgbm9kZSA9IG51bGw7IH1cbiAgICAgICAgaWYgKGxpbmUgPT09IHZvaWQgMCkgeyBsaW5lID0gbnVsbDsgfVxuICAgICAgICB0aGlzLmlkID0gaWQ7XG4gICAgICAgIHRoaXMueCA9IHg7XG4gICAgICAgIHRoaXMueSA9IHk7XG4gICAgICAgIHRoaXMubm9kZSA9IG5vZGU7XG4gICAgICAgIHRoaXMubGluZSA9IGxpbmU7XG4gICAgfVxuICAgIHJldHVybiBWZXJ0O1xufSgpKTtcbmV4cG9ydHMuVmVydCA9IFZlcnQ7XG52YXIgTG9uZ2VzdENvbW1vblN1YnNlcXVlbmNlID0gKGZ1bmN0aW9uICgpIHtcbiAgICBmdW5jdGlvbiBMb25nZXN0Q29tbW9uU3Vic2VxdWVuY2UocywgdCkge1xuICAgICAgICB0aGlzLnMgPSBzO1xuICAgICAgICB0aGlzLnQgPSB0O1xuICAgICAgICB2YXIgbWYgPSBMb25nZXN0Q29tbW9uU3Vic2VxdWVuY2UuZmluZE1hdGNoKHMsIHQpO1xuICAgICAgICB2YXIgdHIgPSB0LnNsaWNlKDApLnJldmVyc2UoKTtcbiAgICAgICAgdmFyIG1yID0gTG9uZ2VzdENvbW1vblN1YnNlcXVlbmNlLmZpbmRNYXRjaChzLCB0cik7XG4gICAgICAgIGlmIChtZi5sZW5ndGggPj0gbXIubGVuZ3RoKSB7XG4gICAgICAgICAgICB0aGlzLmxlbmd0aCA9IG1mLmxlbmd0aDtcbiAgICAgICAgICAgIHRoaXMuc2kgPSBtZi5zaTtcbiAgICAgICAgICAgIHRoaXMudGkgPSBtZi50aTtcbiAgICAgICAgICAgIHRoaXMucmV2ZXJzZWQgPSBmYWxzZTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIHRoaXMubGVuZ3RoID0gbXIubGVuZ3RoO1xuICAgICAgICAgICAgdGhpcy5zaSA9IG1yLnNpO1xuICAgICAgICAgICAgdGhpcy50aSA9IHQubGVuZ3RoIC0gbXIudGkgLSBtci5sZW5ndGg7XG4gICAgICAgICAgICB0aGlzLnJldmVyc2VkID0gdHJ1ZTtcbiAgICAgICAgfVxuICAgIH1cbiAgICBMb25nZXN0Q29tbW9uU3Vic2VxdWVuY2UuZmluZE1hdGNoID0gZnVuY3Rpb24gKHMsIHQpIHtcbiAgICAgICAgdmFyIG0gPSBzLmxlbmd0aDtcbiAgICAgICAgdmFyIG4gPSB0Lmxlbmd0aDtcbiAgICAgICAgdmFyIG1hdGNoID0geyBsZW5ndGg6IDAsIHNpOiAtMSwgdGk6IC0xIH07XG4gICAgICAgIHZhciBsID0gbmV3IEFycmF5KG0pO1xuICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IG07IGkrKykge1xuICAgICAgICAgICAgbFtpXSA9IG5ldyBBcnJheShuKTtcbiAgICAgICAgICAgIGZvciAodmFyIGogPSAwOyBqIDwgbjsgaisrKVxuICAgICAgICAgICAgICAgIGlmIChzW2ldID09PSB0W2pdKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciB2ID0gbFtpXVtqXSA9IChpID09PSAwIHx8IGogPT09IDApID8gMSA6IGxbaSAtIDFdW2ogLSAxXSArIDE7XG4gICAgICAgICAgICAgICAgICAgIGlmICh2ID4gbWF0Y2gubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBtYXRjaC5sZW5ndGggPSB2O1xuICAgICAgICAgICAgICAgICAgICAgICAgbWF0Y2guc2kgPSBpIC0gdiArIDE7XG4gICAgICAgICAgICAgICAgICAgICAgICBtYXRjaC50aSA9IGogLSB2ICsgMTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICA7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2VcbiAgICAgICAgICAgICAgICAgICAgbFtpXVtqXSA9IDA7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIG1hdGNoO1xuICAgIH07XG4gICAgTG9uZ2VzdENvbW1vblN1YnNlcXVlbmNlLnByb3RvdHlwZS5nZXRTZXF1ZW5jZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMubGVuZ3RoID49IDAgPyB0aGlzLnMuc2xpY2UodGhpcy5zaSwgdGhpcy5zaSArIHRoaXMubGVuZ3RoKSA6IFtdO1xuICAgIH07XG4gICAgcmV0dXJuIExvbmdlc3RDb21tb25TdWJzZXF1ZW5jZTtcbn0oKSk7XG5leHBvcnRzLkxvbmdlc3RDb21tb25TdWJzZXF1ZW5jZSA9IExvbmdlc3RDb21tb25TdWJzZXF1ZW5jZTtcbnZhciBHcmlkUm91dGVyID0gKGZ1bmN0aW9uICgpIHtcbiAgICBmdW5jdGlvbiBHcmlkUm91dGVyKG9yaWdpbmFsbm9kZXMsIGFjY2Vzc29yLCBncm91cFBhZGRpbmcpIHtcbiAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgaWYgKGdyb3VwUGFkZGluZyA9PT0gdm9pZCAwKSB7IGdyb3VwUGFkZGluZyA9IDEyOyB9XG4gICAgICAgIHRoaXMub3JpZ2luYWxub2RlcyA9IG9yaWdpbmFsbm9kZXM7XG4gICAgICAgIHRoaXMuZ3JvdXBQYWRkaW5nID0gZ3JvdXBQYWRkaW5nO1xuICAgICAgICB0aGlzLmxlYXZlcyA9IG51bGw7XG4gICAgICAgIHRoaXMubm9kZXMgPSBvcmlnaW5hbG5vZGVzLm1hcChmdW5jdGlvbiAodiwgaSkgeyByZXR1cm4gbmV3IE5vZGVXcmFwcGVyKGksIGFjY2Vzc29yLmdldEJvdW5kcyh2KSwgYWNjZXNzb3IuZ2V0Q2hpbGRyZW4odikpOyB9KTtcbiAgICAgICAgdGhpcy5sZWF2ZXMgPSB0aGlzLm5vZGVzLmZpbHRlcihmdW5jdGlvbiAodikgeyByZXR1cm4gdi5sZWFmOyB9KTtcbiAgICAgICAgdGhpcy5ncm91cHMgPSB0aGlzLm5vZGVzLmZpbHRlcihmdW5jdGlvbiAoZykgeyByZXR1cm4gIWcubGVhZjsgfSk7XG4gICAgICAgIHRoaXMuY29scyA9IHRoaXMuZ2V0R3JpZExpbmVzKCd4Jyk7XG4gICAgICAgIHRoaXMucm93cyA9IHRoaXMuZ2V0R3JpZExpbmVzKCd5Jyk7XG4gICAgICAgIHRoaXMuZ3JvdXBzLmZvckVhY2goZnVuY3Rpb24gKHYpIHtcbiAgICAgICAgICAgIHJldHVybiB2LmNoaWxkcmVuLmZvckVhY2goZnVuY3Rpb24gKGMpIHsgcmV0dXJuIF90aGlzLm5vZGVzW2NdLnBhcmVudCA9IHY7IH0pO1xuICAgICAgICB9KTtcbiAgICAgICAgdGhpcy5yb290ID0geyBjaGlsZHJlbjogW10gfTtcbiAgICAgICAgdGhpcy5ub2Rlcy5mb3JFYWNoKGZ1bmN0aW9uICh2KSB7XG4gICAgICAgICAgICBpZiAodHlwZW9mIHYucGFyZW50ID09PSAndW5kZWZpbmVkJykge1xuICAgICAgICAgICAgICAgIHYucGFyZW50ID0gX3RoaXMucm9vdDtcbiAgICAgICAgICAgICAgICBfdGhpcy5yb290LmNoaWxkcmVuLnB1c2godi5pZCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB2LnBvcnRzID0gW107XG4gICAgICAgIH0pO1xuICAgICAgICB0aGlzLmJhY2tUb0Zyb250ID0gdGhpcy5ub2Rlcy5zbGljZSgwKTtcbiAgICAgICAgdGhpcy5iYWNrVG9Gcm9udC5zb3J0KGZ1bmN0aW9uICh4LCB5KSB7IHJldHVybiBfdGhpcy5nZXREZXB0aCh4KSAtIF90aGlzLmdldERlcHRoKHkpOyB9KTtcbiAgICAgICAgdmFyIGZyb250VG9CYWNrR3JvdXBzID0gdGhpcy5iYWNrVG9Gcm9udC5zbGljZSgwKS5yZXZlcnNlKCkuZmlsdGVyKGZ1bmN0aW9uIChnKSB7IHJldHVybiAhZy5sZWFmOyB9KTtcbiAgICAgICAgZnJvbnRUb0JhY2tHcm91cHMuZm9yRWFjaChmdW5jdGlvbiAodikge1xuICAgICAgICAgICAgdmFyIHIgPSByZWN0YW5nbGVfMS5SZWN0YW5nbGUuZW1wdHkoKTtcbiAgICAgICAgICAgIHYuY2hpbGRyZW4uZm9yRWFjaChmdW5jdGlvbiAoYykgeyByZXR1cm4gciA9IHIudW5pb24oX3RoaXMubm9kZXNbY10ucmVjdCk7IH0pO1xuICAgICAgICAgICAgdi5yZWN0ID0gci5pbmZsYXRlKF90aGlzLmdyb3VwUGFkZGluZyk7XG4gICAgICAgIH0pO1xuICAgICAgICB2YXIgY29sTWlkcyA9IHRoaXMubWlkUG9pbnRzKHRoaXMuY29scy5tYXAoZnVuY3Rpb24gKHIpIHsgcmV0dXJuIHIucG9zOyB9KSk7XG4gICAgICAgIHZhciByb3dNaWRzID0gdGhpcy5taWRQb2ludHModGhpcy5yb3dzLm1hcChmdW5jdGlvbiAocikgeyByZXR1cm4gci5wb3M7IH0pKTtcbiAgICAgICAgdmFyIHJvd3ggPSBjb2xNaWRzWzBdLCByb3dYID0gY29sTWlkc1tjb2xNaWRzLmxlbmd0aCAtIDFdO1xuICAgICAgICB2YXIgY29seSA9IHJvd01pZHNbMF0sIGNvbFkgPSByb3dNaWRzW3Jvd01pZHMubGVuZ3RoIC0gMV07XG4gICAgICAgIHZhciBobGluZXMgPSB0aGlzLnJvd3MubWFwKGZ1bmN0aW9uIChyKSB7IHJldHVybiAoeyB4MTogcm93eCwgeDI6IHJvd1gsIHkxOiByLnBvcywgeTI6IHIucG9zIH0pOyB9KVxuICAgICAgICAgICAgLmNvbmNhdChyb3dNaWRzLm1hcChmdW5jdGlvbiAobSkgeyByZXR1cm4gKHsgeDE6IHJvd3gsIHgyOiByb3dYLCB5MTogbSwgeTI6IG0gfSk7IH0pKTtcbiAgICAgICAgdmFyIHZsaW5lcyA9IHRoaXMuY29scy5tYXAoZnVuY3Rpb24gKGMpIHsgcmV0dXJuICh7IHgxOiBjLnBvcywgeDI6IGMucG9zLCB5MTogY29seSwgeTI6IGNvbFkgfSk7IH0pXG4gICAgICAgICAgICAuY29uY2F0KGNvbE1pZHMubWFwKGZ1bmN0aW9uIChtKSB7IHJldHVybiAoeyB4MTogbSwgeDI6IG0sIHkxOiBjb2x5LCB5MjogY29sWSB9KTsgfSkpO1xuICAgICAgICB2YXIgbGluZXMgPSBobGluZXMuY29uY2F0KHZsaW5lcyk7XG4gICAgICAgIGxpbmVzLmZvckVhY2goZnVuY3Rpb24gKGwpIHsgcmV0dXJuIGwudmVydHMgPSBbXTsgfSk7XG4gICAgICAgIHRoaXMudmVydHMgPSBbXTtcbiAgICAgICAgdGhpcy5lZGdlcyA9IFtdO1xuICAgICAgICBobGluZXMuZm9yRWFjaChmdW5jdGlvbiAoaCkge1xuICAgICAgICAgICAgcmV0dXJuIHZsaW5lcy5mb3JFYWNoKGZ1bmN0aW9uICh2KSB7XG4gICAgICAgICAgICAgICAgdmFyIHAgPSBuZXcgVmVydChfdGhpcy52ZXJ0cy5sZW5ndGgsIHYueDEsIGgueTEpO1xuICAgICAgICAgICAgICAgIGgudmVydHMucHVzaChwKTtcbiAgICAgICAgICAgICAgICB2LnZlcnRzLnB1c2gocCk7XG4gICAgICAgICAgICAgICAgX3RoaXMudmVydHMucHVzaChwKTtcbiAgICAgICAgICAgICAgICB2YXIgaSA9IF90aGlzLmJhY2tUb0Zyb250Lmxlbmd0aDtcbiAgICAgICAgICAgICAgICB3aGlsZSAoaS0tID4gMCkge1xuICAgICAgICAgICAgICAgICAgICB2YXIgbm9kZSA9IF90aGlzLmJhY2tUb0Zyb250W2ldLCByID0gbm9kZS5yZWN0O1xuICAgICAgICAgICAgICAgICAgICB2YXIgZHggPSBNYXRoLmFicyhwLnggLSByLmN4KCkpLCBkeSA9IE1hdGguYWJzKHAueSAtIHIuY3koKSk7XG4gICAgICAgICAgICAgICAgICAgIGlmIChkeCA8IHIud2lkdGgoKSAvIDIgJiYgZHkgPCByLmhlaWdodCgpIC8gMikge1xuICAgICAgICAgICAgICAgICAgICAgICAgcC5ub2RlID0gbm9kZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH0pO1xuICAgICAgICBsaW5lcy5mb3JFYWNoKGZ1bmN0aW9uIChsLCBsaSkge1xuICAgICAgICAgICAgX3RoaXMubm9kZXMuZm9yRWFjaChmdW5jdGlvbiAodiwgaSkge1xuICAgICAgICAgICAgICAgIHYucmVjdC5saW5lSW50ZXJzZWN0aW9ucyhsLngxLCBsLnkxLCBsLngyLCBsLnkyKS5mb3JFYWNoKGZ1bmN0aW9uIChpbnRlcnNlY3QsIGopIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIHAgPSBuZXcgVmVydChfdGhpcy52ZXJ0cy5sZW5ndGgsIGludGVyc2VjdC54LCBpbnRlcnNlY3QueSwgdiwgbCk7XG4gICAgICAgICAgICAgICAgICAgIF90aGlzLnZlcnRzLnB1c2gocCk7XG4gICAgICAgICAgICAgICAgICAgIGwudmVydHMucHVzaChwKTtcbiAgICAgICAgICAgICAgICAgICAgdi5wb3J0cy5wdXNoKHApO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB2YXIgaXNIb3JpeiA9IE1hdGguYWJzKGwueTEgLSBsLnkyKSA8IDAuMTtcbiAgICAgICAgICAgIHZhciBkZWx0YSA9IGZ1bmN0aW9uIChhLCBiKSB7IHJldHVybiBpc0hvcml6ID8gYi54IC0gYS54IDogYi55IC0gYS55OyB9O1xuICAgICAgICAgICAgbC52ZXJ0cy5zb3J0KGRlbHRhKTtcbiAgICAgICAgICAgIGZvciAodmFyIGkgPSAxOyBpIDwgbC52ZXJ0cy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgIHZhciB1ID0gbC52ZXJ0c1tpIC0gMV0sIHYgPSBsLnZlcnRzW2ldO1xuICAgICAgICAgICAgICAgIGlmICh1Lm5vZGUgJiYgdS5ub2RlID09PSB2Lm5vZGUgJiYgdS5ub2RlLmxlYWYpXG4gICAgICAgICAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgICAgICAgIF90aGlzLmVkZ2VzLnB1c2goeyBzb3VyY2U6IHUuaWQsIHRhcmdldDogdi5pZCwgbGVuZ3RoOiBNYXRoLmFicyhkZWx0YSh1LCB2KSkgfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgIH1cbiAgICBHcmlkUm91dGVyLnByb3RvdHlwZS5hdmcgPSBmdW5jdGlvbiAoYSkgeyByZXR1cm4gYS5yZWR1Y2UoZnVuY3Rpb24gKHgsIHkpIHsgcmV0dXJuIHggKyB5OyB9KSAvIGEubGVuZ3RoOyB9O1xuICAgIEdyaWRSb3V0ZXIucHJvdG90eXBlLmdldEdyaWRMaW5lcyA9IGZ1bmN0aW9uIChheGlzKSB7XG4gICAgICAgIHZhciBjb2x1bW5zID0gW107XG4gICAgICAgIHZhciBscyA9IHRoaXMubGVhdmVzLnNsaWNlKDAsIHRoaXMubGVhdmVzLmxlbmd0aCk7XG4gICAgICAgIHdoaWxlIChscy5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgICB2YXIgb3ZlcmxhcHBpbmcgPSBscy5maWx0ZXIoZnVuY3Rpb24gKHYpIHsgcmV0dXJuIHYucmVjdFsnb3ZlcmxhcCcgKyBheGlzLnRvVXBwZXJDYXNlKCldKGxzWzBdLnJlY3QpOyB9KTtcbiAgICAgICAgICAgIHZhciBjb2wgPSB7XG4gICAgICAgICAgICAgICAgbm9kZXM6IG92ZXJsYXBwaW5nLFxuICAgICAgICAgICAgICAgIHBvczogdGhpcy5hdmcob3ZlcmxhcHBpbmcubWFwKGZ1bmN0aW9uICh2KSB7IHJldHVybiB2LnJlY3RbJ2MnICsgYXhpc10oKTsgfSkpXG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgY29sdW1ucy5wdXNoKGNvbCk7XG4gICAgICAgICAgICBjb2wubm9kZXMuZm9yRWFjaChmdW5jdGlvbiAodikgeyByZXR1cm4gbHMuc3BsaWNlKGxzLmluZGV4T2YodiksIDEpOyB9KTtcbiAgICAgICAgfVxuICAgICAgICBjb2x1bW5zLnNvcnQoZnVuY3Rpb24gKGEsIGIpIHsgcmV0dXJuIGEucG9zIC0gYi5wb3M7IH0pO1xuICAgICAgICByZXR1cm4gY29sdW1ucztcbiAgICB9O1xuICAgIEdyaWRSb3V0ZXIucHJvdG90eXBlLmdldERlcHRoID0gZnVuY3Rpb24gKHYpIHtcbiAgICAgICAgdmFyIGRlcHRoID0gMDtcbiAgICAgICAgd2hpbGUgKHYucGFyZW50ICE9PSB0aGlzLnJvb3QpIHtcbiAgICAgICAgICAgIGRlcHRoKys7XG4gICAgICAgICAgICB2ID0gdi5wYXJlbnQ7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGRlcHRoO1xuICAgIH07XG4gICAgR3JpZFJvdXRlci5wcm90b3R5cGUubWlkUG9pbnRzID0gZnVuY3Rpb24gKGEpIHtcbiAgICAgICAgdmFyIGdhcCA9IGFbMV0gLSBhWzBdO1xuICAgICAgICB2YXIgbWlkcyA9IFthWzBdIC0gZ2FwIC8gMl07XG4gICAgICAgIGZvciAodmFyIGkgPSAxOyBpIDwgYS5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgbWlkcy5wdXNoKChhW2ldICsgYVtpIC0gMV0pIC8gMik7XG4gICAgICAgIH1cbiAgICAgICAgbWlkcy5wdXNoKGFbYS5sZW5ndGggLSAxXSArIGdhcCAvIDIpO1xuICAgICAgICByZXR1cm4gbWlkcztcbiAgICB9O1xuICAgIEdyaWRSb3V0ZXIucHJvdG90eXBlLmZpbmRMaW5lYWdlID0gZnVuY3Rpb24gKHYpIHtcbiAgICAgICAgdmFyIGxpbmVhZ2UgPSBbdl07XG4gICAgICAgIGRvIHtcbiAgICAgICAgICAgIHYgPSB2LnBhcmVudDtcbiAgICAgICAgICAgIGxpbmVhZ2UucHVzaCh2KTtcbiAgICAgICAgfSB3aGlsZSAodiAhPT0gdGhpcy5yb290KTtcbiAgICAgICAgcmV0dXJuIGxpbmVhZ2UucmV2ZXJzZSgpO1xuICAgIH07XG4gICAgR3JpZFJvdXRlci5wcm90b3R5cGUuZmluZEFuY2VzdG9yUGF0aEJldHdlZW4gPSBmdW5jdGlvbiAoYSwgYikge1xuICAgICAgICB2YXIgYWEgPSB0aGlzLmZpbmRMaW5lYWdlKGEpLCBiYSA9IHRoaXMuZmluZExpbmVhZ2UoYiksIGkgPSAwO1xuICAgICAgICB3aGlsZSAoYWFbaV0gPT09IGJhW2ldKVxuICAgICAgICAgICAgaSsrO1xuICAgICAgICByZXR1cm4geyBjb21tb25BbmNlc3RvcjogYWFbaSAtIDFdLCBsaW5lYWdlczogYWEuc2xpY2UoaSkuY29uY2F0KGJhLnNsaWNlKGkpKSB9O1xuICAgIH07XG4gICAgR3JpZFJvdXRlci5wcm90b3R5cGUuc2libGluZ09ic3RhY2xlcyA9IGZ1bmN0aW9uIChhLCBiKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgICAgIHZhciBwYXRoID0gdGhpcy5maW5kQW5jZXN0b3JQYXRoQmV0d2VlbihhLCBiKTtcbiAgICAgICAgdmFyIGxpbmVhZ2VMb29rdXAgPSB7fTtcbiAgICAgICAgcGF0aC5saW5lYWdlcy5mb3JFYWNoKGZ1bmN0aW9uICh2KSB7IHJldHVybiBsaW5lYWdlTG9va3VwW3YuaWRdID0ge307IH0pO1xuICAgICAgICB2YXIgb2JzdGFjbGVzID0gcGF0aC5jb21tb25BbmNlc3Rvci5jaGlsZHJlbi5maWx0ZXIoZnVuY3Rpb24gKHYpIHsgcmV0dXJuICEodiBpbiBsaW5lYWdlTG9va3VwKTsgfSk7XG4gICAgICAgIHBhdGgubGluZWFnZXNcbiAgICAgICAgICAgIC5maWx0ZXIoZnVuY3Rpb24gKHYpIHsgcmV0dXJuIHYucGFyZW50ICE9PSBwYXRoLmNvbW1vbkFuY2VzdG9yOyB9KVxuICAgICAgICAgICAgLmZvckVhY2goZnVuY3Rpb24gKHYpIHsgcmV0dXJuIG9ic3RhY2xlcyA9IG9ic3RhY2xlcy5jb25jYXQodi5wYXJlbnQuY2hpbGRyZW4uZmlsdGVyKGZ1bmN0aW9uIChjKSB7IHJldHVybiBjICE9PSB2LmlkOyB9KSk7IH0pO1xuICAgICAgICByZXR1cm4gb2JzdGFjbGVzLm1hcChmdW5jdGlvbiAodikgeyByZXR1cm4gX3RoaXMubm9kZXNbdl07IH0pO1xuICAgIH07XG4gICAgR3JpZFJvdXRlci5nZXRTZWdtZW50U2V0cyA9IGZ1bmN0aW9uIChyb3V0ZXMsIHgsIHkpIHtcbiAgICAgICAgdmFyIHZzZWdtZW50cyA9IFtdO1xuICAgICAgICBmb3IgKHZhciBlaSA9IDA7IGVpIDwgcm91dGVzLmxlbmd0aDsgZWkrKykge1xuICAgICAgICAgICAgdmFyIHJvdXRlID0gcm91dGVzW2VpXTtcbiAgICAgICAgICAgIGZvciAodmFyIHNpID0gMDsgc2kgPCByb3V0ZS5sZW5ndGg7IHNpKyspIHtcbiAgICAgICAgICAgICAgICB2YXIgcyA9IHJvdXRlW3NpXTtcbiAgICAgICAgICAgICAgICBzLmVkZ2VpZCA9IGVpO1xuICAgICAgICAgICAgICAgIHMuaSA9IHNpO1xuICAgICAgICAgICAgICAgIHZhciBzZHggPSBzWzFdW3hdIC0gc1swXVt4XTtcbiAgICAgICAgICAgICAgICBpZiAoTWF0aC5hYnMoc2R4KSA8IDAuMSkge1xuICAgICAgICAgICAgICAgICAgICB2c2VnbWVudHMucHVzaChzKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgdnNlZ21lbnRzLnNvcnQoZnVuY3Rpb24gKGEsIGIpIHsgcmV0dXJuIGFbMF1beF0gLSBiWzBdW3hdOyB9KTtcbiAgICAgICAgdmFyIHZzZWdtZW50c2V0cyA9IFtdO1xuICAgICAgICB2YXIgc2VnbWVudHNldCA9IG51bGw7XG4gICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgdnNlZ21lbnRzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICB2YXIgcyA9IHZzZWdtZW50c1tpXTtcbiAgICAgICAgICAgIGlmICghc2VnbWVudHNldCB8fCBNYXRoLmFicyhzWzBdW3hdIC0gc2VnbWVudHNldC5wb3MpID4gMC4xKSB7XG4gICAgICAgICAgICAgICAgc2VnbWVudHNldCA9IHsgcG9zOiBzWzBdW3hdLCBzZWdtZW50czogW10gfTtcbiAgICAgICAgICAgICAgICB2c2VnbWVudHNldHMucHVzaChzZWdtZW50c2V0KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHNlZ21lbnRzZXQuc2VnbWVudHMucHVzaChzKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdnNlZ21lbnRzZXRzO1xuICAgIH07XG4gICAgR3JpZFJvdXRlci5udWRnZVNlZ3MgPSBmdW5jdGlvbiAoeCwgeSwgcm91dGVzLCBzZWdtZW50cywgbGVmdE9mLCBnYXApIHtcbiAgICAgICAgdmFyIG4gPSBzZWdtZW50cy5sZW5ndGg7XG4gICAgICAgIGlmIChuIDw9IDEpXG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIHZhciB2cyA9IHNlZ21lbnRzLm1hcChmdW5jdGlvbiAocykgeyByZXR1cm4gbmV3IHZwc2NfMS5WYXJpYWJsZShzWzBdW3hdKTsgfSk7XG4gICAgICAgIHZhciBjcyA9IFtdO1xuICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IG47IGkrKykge1xuICAgICAgICAgICAgZm9yICh2YXIgaiA9IDA7IGogPCBuOyBqKyspIHtcbiAgICAgICAgICAgICAgICBpZiAoaSA9PT0gailcbiAgICAgICAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICAgICAgdmFyIHMxID0gc2VnbWVudHNbaV0sIHMyID0gc2VnbWVudHNbal0sIGUxID0gczEuZWRnZWlkLCBlMiA9IHMyLmVkZ2VpZCwgbGluZCA9IC0xLCByaW5kID0gLTE7XG4gICAgICAgICAgICAgICAgaWYgKHggPT0gJ3gnKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChsZWZ0T2YoZTEsIGUyKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHMxWzBdW3ldIDwgczFbMV1beV0pIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBsaW5kID0gaiwgcmluZCA9IGk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBsaW5kID0gaSwgcmluZCA9IGo7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChsZWZ0T2YoZTEsIGUyKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHMxWzBdW3ldIDwgczFbMV1beV0pIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBsaW5kID0gaSwgcmluZCA9IGo7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBsaW5kID0gaiwgcmluZCA9IGk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYgKGxpbmQgPj0gMCkge1xuICAgICAgICAgICAgICAgICAgICBjcy5wdXNoKG5ldyB2cHNjXzEuQ29uc3RyYWludCh2c1tsaW5kXSwgdnNbcmluZF0sIGdhcCkpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICB2YXIgc29sdmVyID0gbmV3IHZwc2NfMS5Tb2x2ZXIodnMsIGNzKTtcbiAgICAgICAgc29sdmVyLnNvbHZlKCk7XG4gICAgICAgIHZzLmZvckVhY2goZnVuY3Rpb24gKHYsIGkpIHtcbiAgICAgICAgICAgIHZhciBzID0gc2VnbWVudHNbaV07XG4gICAgICAgICAgICB2YXIgcG9zID0gdi5wb3NpdGlvbigpO1xuICAgICAgICAgICAgc1swXVt4XSA9IHNbMV1beF0gPSBwb3M7XG4gICAgICAgICAgICB2YXIgcm91dGUgPSByb3V0ZXNbcy5lZGdlaWRdO1xuICAgICAgICAgICAgaWYgKHMuaSA+IDApXG4gICAgICAgICAgICAgICAgcm91dGVbcy5pIC0gMV1bMV1beF0gPSBwb3M7XG4gICAgICAgICAgICBpZiAocy5pIDwgcm91dGUubGVuZ3RoIC0gMSlcbiAgICAgICAgICAgICAgICByb3V0ZVtzLmkgKyAxXVswXVt4XSA9IHBvcztcbiAgICAgICAgfSk7XG4gICAgfTtcbiAgICBHcmlkUm91dGVyLm51ZGdlU2VnbWVudHMgPSBmdW5jdGlvbiAocm91dGVzLCB4LCB5LCBsZWZ0T2YsIGdhcCkge1xuICAgICAgICB2YXIgdnNlZ21lbnRzZXRzID0gR3JpZFJvdXRlci5nZXRTZWdtZW50U2V0cyhyb3V0ZXMsIHgsIHkpO1xuICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IHZzZWdtZW50c2V0cy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgdmFyIHNzID0gdnNlZ21lbnRzZXRzW2ldO1xuICAgICAgICAgICAgdmFyIGV2ZW50cyA9IFtdO1xuICAgICAgICAgICAgZm9yICh2YXIgaiA9IDA7IGogPCBzcy5zZWdtZW50cy5sZW5ndGg7IGorKykge1xuICAgICAgICAgICAgICAgIHZhciBzID0gc3Muc2VnbWVudHNbal07XG4gICAgICAgICAgICAgICAgZXZlbnRzLnB1c2goeyB0eXBlOiAwLCBzOiBzLCBwb3M6IE1hdGgubWluKHNbMF1beV0sIHNbMV1beV0pIH0pO1xuICAgICAgICAgICAgICAgIGV2ZW50cy5wdXNoKHsgdHlwZTogMSwgczogcywgcG9zOiBNYXRoLm1heChzWzBdW3ldLCBzWzFdW3ldKSB9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGV2ZW50cy5zb3J0KGZ1bmN0aW9uIChhLCBiKSB7IHJldHVybiBhLnBvcyAtIGIucG9zICsgYS50eXBlIC0gYi50eXBlOyB9KTtcbiAgICAgICAgICAgIHZhciBvcGVuID0gW107XG4gICAgICAgICAgICB2YXIgb3BlbkNvdW50ID0gMDtcbiAgICAgICAgICAgIGV2ZW50cy5mb3JFYWNoKGZ1bmN0aW9uIChlKSB7XG4gICAgICAgICAgICAgICAgaWYgKGUudHlwZSA9PT0gMCkge1xuICAgICAgICAgICAgICAgICAgICBvcGVuLnB1c2goZS5zKTtcbiAgICAgICAgICAgICAgICAgICAgb3BlbkNvdW50Kys7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBvcGVuQ291bnQtLTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYgKG9wZW5Db3VudCA9PSAwKSB7XG4gICAgICAgICAgICAgICAgICAgIEdyaWRSb3V0ZXIubnVkZ2VTZWdzKHgsIHksIHJvdXRlcywgb3BlbiwgbGVmdE9mLCBnYXApO1xuICAgICAgICAgICAgICAgICAgICBvcGVuID0gW107XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIEdyaWRSb3V0ZXIucHJvdG90eXBlLnJvdXRlRWRnZXMgPSBmdW5jdGlvbiAoZWRnZXMsIG51ZGdlR2FwLCBzb3VyY2UsIHRhcmdldCkge1xuICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICB2YXIgcm91dGVQYXRocyA9IGVkZ2VzLm1hcChmdW5jdGlvbiAoZSkgeyByZXR1cm4gX3RoaXMucm91dGUoc291cmNlKGUpLCB0YXJnZXQoZSkpOyB9KTtcbiAgICAgICAgdmFyIG9yZGVyID0gR3JpZFJvdXRlci5vcmRlckVkZ2VzKHJvdXRlUGF0aHMpO1xuICAgICAgICB2YXIgcm91dGVzID0gcm91dGVQYXRocy5tYXAoZnVuY3Rpb24gKGUpIHsgcmV0dXJuIEdyaWRSb3V0ZXIubWFrZVNlZ21lbnRzKGUpOyB9KTtcbiAgICAgICAgR3JpZFJvdXRlci5udWRnZVNlZ21lbnRzKHJvdXRlcywgJ3gnLCAneScsIG9yZGVyLCBudWRnZUdhcCk7XG4gICAgICAgIEdyaWRSb3V0ZXIubnVkZ2VTZWdtZW50cyhyb3V0ZXMsICd5JywgJ3gnLCBvcmRlciwgbnVkZ2VHYXApO1xuICAgICAgICBHcmlkUm91dGVyLnVucmV2ZXJzZUVkZ2VzKHJvdXRlcywgcm91dGVQYXRocyk7XG4gICAgICAgIHJldHVybiByb3V0ZXM7XG4gICAgfTtcbiAgICBHcmlkUm91dGVyLnVucmV2ZXJzZUVkZ2VzID0gZnVuY3Rpb24gKHJvdXRlcywgcm91dGVQYXRocykge1xuICAgICAgICByb3V0ZXMuZm9yRWFjaChmdW5jdGlvbiAoc2VnbWVudHMsIGkpIHtcbiAgICAgICAgICAgIHZhciBwYXRoID0gcm91dGVQYXRoc1tpXTtcbiAgICAgICAgICAgIGlmIChwYXRoLnJldmVyc2VkKSB7XG4gICAgICAgICAgICAgICAgc2VnbWVudHMucmV2ZXJzZSgpO1xuICAgICAgICAgICAgICAgIHNlZ21lbnRzLmZvckVhY2goZnVuY3Rpb24gKHNlZ21lbnQpIHtcbiAgICAgICAgICAgICAgICAgICAgc2VnbWVudC5yZXZlcnNlKCk7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgIH07XG4gICAgR3JpZFJvdXRlci5hbmdsZUJldHdlZW4yTGluZXMgPSBmdW5jdGlvbiAobGluZTEsIGxpbmUyKSB7XG4gICAgICAgIHZhciBhbmdsZTEgPSBNYXRoLmF0YW4yKGxpbmUxWzBdLnkgLSBsaW5lMVsxXS55LCBsaW5lMVswXS54IC0gbGluZTFbMV0ueCk7XG4gICAgICAgIHZhciBhbmdsZTIgPSBNYXRoLmF0YW4yKGxpbmUyWzBdLnkgLSBsaW5lMlsxXS55LCBsaW5lMlswXS54IC0gbGluZTJbMV0ueCk7XG4gICAgICAgIHZhciBkaWZmID0gYW5nbGUxIC0gYW5nbGUyO1xuICAgICAgICBpZiAoZGlmZiA+IE1hdGguUEkgfHwgZGlmZiA8IC1NYXRoLlBJKSB7XG4gICAgICAgICAgICBkaWZmID0gYW5nbGUyIC0gYW5nbGUxO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBkaWZmO1xuICAgIH07XG4gICAgR3JpZFJvdXRlci5pc0xlZnQgPSBmdW5jdGlvbiAoYSwgYiwgYykge1xuICAgICAgICByZXR1cm4gKChiLnggLSBhLngpICogKGMueSAtIGEueSkgLSAoYi55IC0gYS55KSAqIChjLnggLSBhLngpKSA8PSAwO1xuICAgIH07XG4gICAgR3JpZFJvdXRlci5nZXRPcmRlciA9IGZ1bmN0aW9uIChwYWlycykge1xuICAgICAgICB2YXIgb3V0Z29pbmcgPSB7fTtcbiAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBwYWlycy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgdmFyIHAgPSBwYWlyc1tpXTtcbiAgICAgICAgICAgIGlmICh0eXBlb2Ygb3V0Z29pbmdbcC5sXSA9PT0gJ3VuZGVmaW5lZCcpXG4gICAgICAgICAgICAgICAgb3V0Z29pbmdbcC5sXSA9IHt9O1xuICAgICAgICAgICAgb3V0Z29pbmdbcC5sXVtwLnJdID0gdHJ1ZTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gZnVuY3Rpb24gKGwsIHIpIHsgcmV0dXJuIHR5cGVvZiBvdXRnb2luZ1tsXSAhPT0gJ3VuZGVmaW5lZCcgJiYgb3V0Z29pbmdbbF1bcl07IH07XG4gICAgfTtcbiAgICBHcmlkUm91dGVyLm9yZGVyRWRnZXMgPSBmdW5jdGlvbiAoZWRnZXMpIHtcbiAgICAgICAgdmFyIGVkZ2VPcmRlciA9IFtdO1xuICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGVkZ2VzLmxlbmd0aCAtIDE7IGkrKykge1xuICAgICAgICAgICAgZm9yICh2YXIgaiA9IGkgKyAxOyBqIDwgZWRnZXMubGVuZ3RoOyBqKyspIHtcbiAgICAgICAgICAgICAgICB2YXIgZSA9IGVkZ2VzW2ldLCBmID0gZWRnZXNbal0sIGxjcyA9IG5ldyBMb25nZXN0Q29tbW9uU3Vic2VxdWVuY2UoZSwgZik7XG4gICAgICAgICAgICAgICAgdmFyIHUsIHZpLCB2ajtcbiAgICAgICAgICAgICAgICBpZiAobGNzLmxlbmd0aCA9PT0gMClcbiAgICAgICAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICAgICAgaWYgKGxjcy5yZXZlcnNlZCkge1xuICAgICAgICAgICAgICAgICAgICBmLnJldmVyc2UoKTtcbiAgICAgICAgICAgICAgICAgICAgZi5yZXZlcnNlZCA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgIGxjcyA9IG5ldyBMb25nZXN0Q29tbW9uU3Vic2VxdWVuY2UoZSwgZik7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmICgobGNzLnNpIDw9IDAgfHwgbGNzLnRpIDw9IDApICYmXG4gICAgICAgICAgICAgICAgICAgIChsY3Muc2kgKyBsY3MubGVuZ3RoID49IGUubGVuZ3RoIHx8IGxjcy50aSArIGxjcy5sZW5ndGggPj0gZi5sZW5ndGgpKSB7XG4gICAgICAgICAgICAgICAgICAgIGVkZ2VPcmRlci5wdXNoKHsgbDogaSwgcjogaiB9KTtcbiAgICAgICAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmIChsY3Muc2kgKyBsY3MubGVuZ3RoID49IGUubGVuZ3RoIHx8IGxjcy50aSArIGxjcy5sZW5ndGggPj0gZi5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgICAgdSA9IGVbbGNzLnNpICsgMV07XG4gICAgICAgICAgICAgICAgICAgIHZqID0gZVtsY3Muc2kgLSAxXTtcbiAgICAgICAgICAgICAgICAgICAgdmkgPSBmW2xjcy50aSAtIDFdO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgdSA9IGVbbGNzLnNpICsgbGNzLmxlbmd0aCAtIDJdO1xuICAgICAgICAgICAgICAgICAgICB2aSA9IGVbbGNzLnNpICsgbGNzLmxlbmd0aF07XG4gICAgICAgICAgICAgICAgICAgIHZqID0gZltsY3MudGkgKyBsY3MubGVuZ3RoXTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYgKEdyaWRSb3V0ZXIuaXNMZWZ0KHUsIHZpLCB2aikpIHtcbiAgICAgICAgICAgICAgICAgICAgZWRnZU9yZGVyLnB1c2goeyBsOiBqLCByOiBpIH0pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgZWRnZU9yZGVyLnB1c2goeyBsOiBpLCByOiBqIH0pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gR3JpZFJvdXRlci5nZXRPcmRlcihlZGdlT3JkZXIpO1xuICAgIH07XG4gICAgR3JpZFJvdXRlci5tYWtlU2VnbWVudHMgPSBmdW5jdGlvbiAocGF0aCkge1xuICAgICAgICBmdW5jdGlvbiBjb3B5UG9pbnQocCkge1xuICAgICAgICAgICAgcmV0dXJuIHsgeDogcC54LCB5OiBwLnkgfTtcbiAgICAgICAgfVxuICAgICAgICB2YXIgaXNTdHJhaWdodCA9IGZ1bmN0aW9uIChhLCBiLCBjKSB7IHJldHVybiBNYXRoLmFicygoYi54IC0gYS54KSAqIChjLnkgLSBhLnkpIC0gKGIueSAtIGEueSkgKiAoYy54IC0gYS54KSkgPCAwLjAwMTsgfTtcbiAgICAgICAgdmFyIHNlZ21lbnRzID0gW107XG4gICAgICAgIHZhciBhID0gY29weVBvaW50KHBhdGhbMF0pO1xuICAgICAgICBmb3IgKHZhciBpID0gMTsgaSA8IHBhdGgubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIHZhciBiID0gY29weVBvaW50KHBhdGhbaV0pLCBjID0gaSA8IHBhdGgubGVuZ3RoIC0gMSA/IHBhdGhbaSArIDFdIDogbnVsbDtcbiAgICAgICAgICAgIGlmICghYyB8fCAhaXNTdHJhaWdodChhLCBiLCBjKSkge1xuICAgICAgICAgICAgICAgIHNlZ21lbnRzLnB1c2goW2EsIGJdKTtcbiAgICAgICAgICAgICAgICBhID0gYjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gc2VnbWVudHM7XG4gICAgfTtcbiAgICBHcmlkUm91dGVyLnByb3RvdHlwZS5yb3V0ZSA9IGZ1bmN0aW9uIChzLCB0KSB7XG4gICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgICAgIHZhciBzb3VyY2UgPSB0aGlzLm5vZGVzW3NdLCB0YXJnZXQgPSB0aGlzLm5vZGVzW3RdO1xuICAgICAgICB0aGlzLm9ic3RhY2xlcyA9IHRoaXMuc2libGluZ09ic3RhY2xlcyhzb3VyY2UsIHRhcmdldCk7XG4gICAgICAgIHZhciBvYnN0YWNsZUxvb2t1cCA9IHt9O1xuICAgICAgICB0aGlzLm9ic3RhY2xlcy5mb3JFYWNoKGZ1bmN0aW9uIChvKSB7IHJldHVybiBvYnN0YWNsZUxvb2t1cFtvLmlkXSA9IG87IH0pO1xuICAgICAgICB0aGlzLnBhc3NhYmxlRWRnZXMgPSB0aGlzLmVkZ2VzLmZpbHRlcihmdW5jdGlvbiAoZSkge1xuICAgICAgICAgICAgdmFyIHUgPSBfdGhpcy52ZXJ0c1tlLnNvdXJjZV0sIHYgPSBfdGhpcy52ZXJ0c1tlLnRhcmdldF07XG4gICAgICAgICAgICByZXR1cm4gISh1Lm5vZGUgJiYgdS5ub2RlLmlkIGluIG9ic3RhY2xlTG9va3VwXG4gICAgICAgICAgICAgICAgfHwgdi5ub2RlICYmIHYubm9kZS5pZCBpbiBvYnN0YWNsZUxvb2t1cCk7XG4gICAgICAgIH0pO1xuICAgICAgICBmb3IgKHZhciBpID0gMTsgaSA8IHNvdXJjZS5wb3J0cy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgdmFyIHUgPSBzb3VyY2UucG9ydHNbMF0uaWQ7XG4gICAgICAgICAgICB2YXIgdiA9IHNvdXJjZS5wb3J0c1tpXS5pZDtcbiAgICAgICAgICAgIHRoaXMucGFzc2FibGVFZGdlcy5wdXNoKHtcbiAgICAgICAgICAgICAgICBzb3VyY2U6IHUsXG4gICAgICAgICAgICAgICAgdGFyZ2V0OiB2LFxuICAgICAgICAgICAgICAgIGxlbmd0aDogMFxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICAgICAgZm9yICh2YXIgaSA9IDE7IGkgPCB0YXJnZXQucG9ydHMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIHZhciB1ID0gdGFyZ2V0LnBvcnRzWzBdLmlkO1xuICAgICAgICAgICAgdmFyIHYgPSB0YXJnZXQucG9ydHNbaV0uaWQ7XG4gICAgICAgICAgICB0aGlzLnBhc3NhYmxlRWRnZXMucHVzaCh7XG4gICAgICAgICAgICAgICAgc291cmNlOiB1LFxuICAgICAgICAgICAgICAgIHRhcmdldDogdixcbiAgICAgICAgICAgICAgICBsZW5ndGg6IDBcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgICAgIHZhciBnZXRTb3VyY2UgPSBmdW5jdGlvbiAoZSkgeyByZXR1cm4gZS5zb3VyY2U7IH0sIGdldFRhcmdldCA9IGZ1bmN0aW9uIChlKSB7IHJldHVybiBlLnRhcmdldDsgfSwgZ2V0TGVuZ3RoID0gZnVuY3Rpb24gKGUpIHsgcmV0dXJuIGUubGVuZ3RoOyB9O1xuICAgICAgICB2YXIgc2hvcnRlc3RQYXRoQ2FsY3VsYXRvciA9IG5ldyBzaG9ydGVzdHBhdGhzXzEuQ2FsY3VsYXRvcih0aGlzLnZlcnRzLmxlbmd0aCwgdGhpcy5wYXNzYWJsZUVkZ2VzLCBnZXRTb3VyY2UsIGdldFRhcmdldCwgZ2V0TGVuZ3RoKTtcbiAgICAgICAgdmFyIGJlbmRQZW5hbHR5ID0gZnVuY3Rpb24gKHUsIHYsIHcpIHtcbiAgICAgICAgICAgIHZhciBhID0gX3RoaXMudmVydHNbdV0sIGIgPSBfdGhpcy52ZXJ0c1t2XSwgYyA9IF90aGlzLnZlcnRzW3ddO1xuICAgICAgICAgICAgdmFyIGR4ID0gTWF0aC5hYnMoYy54IC0gYS54KSwgZHkgPSBNYXRoLmFicyhjLnkgLSBhLnkpO1xuICAgICAgICAgICAgaWYgKGEubm9kZSA9PT0gc291cmNlICYmIGEubm9kZSA9PT0gYi5ub2RlIHx8IGIubm9kZSA9PT0gdGFyZ2V0ICYmIGIubm9kZSA9PT0gYy5ub2RlKVxuICAgICAgICAgICAgICAgIHJldHVybiAwO1xuICAgICAgICAgICAgcmV0dXJuIGR4ID4gMSAmJiBkeSA+IDEgPyAxMDAwIDogMDtcbiAgICAgICAgfTtcbiAgICAgICAgdmFyIHNob3J0ZXN0UGF0aCA9IHNob3J0ZXN0UGF0aENhbGN1bGF0b3IuUGF0aEZyb21Ob2RlVG9Ob2RlV2l0aFByZXZDb3N0KHNvdXJjZS5wb3J0c1swXS5pZCwgdGFyZ2V0LnBvcnRzWzBdLmlkLCBiZW5kUGVuYWx0eSk7XG4gICAgICAgIHZhciBwYXRoUG9pbnRzID0gc2hvcnRlc3RQYXRoLnJldmVyc2UoKS5tYXAoZnVuY3Rpb24gKHZpKSB7IHJldHVybiBfdGhpcy52ZXJ0c1t2aV07IH0pO1xuICAgICAgICBwYXRoUG9pbnRzLnB1c2godGhpcy5ub2Rlc1t0YXJnZXQuaWRdLnBvcnRzWzBdKTtcbiAgICAgICAgcmV0dXJuIHBhdGhQb2ludHMuZmlsdGVyKGZ1bmN0aW9uICh2LCBpKSB7XG4gICAgICAgICAgICByZXR1cm4gIShpIDwgcGF0aFBvaW50cy5sZW5ndGggLSAxICYmIHBhdGhQb2ludHNbaSArIDFdLm5vZGUgPT09IHNvdXJjZSAmJiB2Lm5vZGUgPT09IHNvdXJjZVxuICAgICAgICAgICAgICAgIHx8IGkgPiAwICYmIHYubm9kZSA9PT0gdGFyZ2V0ICYmIHBhdGhQb2ludHNbaSAtIDFdLm5vZGUgPT09IHRhcmdldCk7XG4gICAgICAgIH0pO1xuICAgIH07XG4gICAgR3JpZFJvdXRlci5nZXRSb3V0ZVBhdGggPSBmdW5jdGlvbiAocm91dGUsIGNvcm5lcnJhZGl1cywgYXJyb3d3aWR0aCwgYXJyb3doZWlnaHQpIHtcbiAgICAgICAgdmFyIHJlc3VsdCA9IHtcbiAgICAgICAgICAgIHJvdXRlcGF0aDogJ00gJyArIHJvdXRlWzBdWzBdLnggKyAnICcgKyByb3V0ZVswXVswXS55ICsgJyAnLFxuICAgICAgICAgICAgYXJyb3dwYXRoOiAnJ1xuICAgICAgICB9O1xuICAgICAgICBpZiAocm91dGUubGVuZ3RoID4gMSkge1xuICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCByb3V0ZS5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgIHZhciBsaSA9IHJvdXRlW2ldO1xuICAgICAgICAgICAgICAgIHZhciB4ID0gbGlbMV0ueCwgeSA9IGxpWzFdLnk7XG4gICAgICAgICAgICAgICAgdmFyIGR4ID0geCAtIGxpWzBdLng7XG4gICAgICAgICAgICAgICAgdmFyIGR5ID0geSAtIGxpWzBdLnk7XG4gICAgICAgICAgICAgICAgaWYgKGkgPCByb3V0ZS5sZW5ndGggLSAxKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChNYXRoLmFicyhkeCkgPiAwKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB4IC09IGR4IC8gTWF0aC5hYnMoZHgpICogY29ybmVycmFkaXVzO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgeSAtPSBkeSAvIE1hdGguYWJzKGR5KSAqIGNvcm5lcnJhZGl1cztcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICByZXN1bHQucm91dGVwYXRoICs9ICdMICcgKyB4ICsgJyAnICsgeSArICcgJztcbiAgICAgICAgICAgICAgICAgICAgdmFyIGwgPSByb3V0ZVtpICsgMV07XG4gICAgICAgICAgICAgICAgICAgIHZhciB4MCA9IGxbMF0ueCwgeTAgPSBsWzBdLnk7XG4gICAgICAgICAgICAgICAgICAgIHZhciB4MSA9IGxbMV0ueDtcbiAgICAgICAgICAgICAgICAgICAgdmFyIHkxID0gbFsxXS55O1xuICAgICAgICAgICAgICAgICAgICBkeCA9IHgxIC0geDA7XG4gICAgICAgICAgICAgICAgICAgIGR5ID0geTEgLSB5MDtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGFuZ2xlID0gR3JpZFJvdXRlci5hbmdsZUJldHdlZW4yTGluZXMobGksIGwpIDwgMCA/IDEgOiAwO1xuICAgICAgICAgICAgICAgICAgICB2YXIgeDIsIHkyO1xuICAgICAgICAgICAgICAgICAgICBpZiAoTWF0aC5hYnMoZHgpID4gMCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgeDIgPSB4MCArIGR4IC8gTWF0aC5hYnMoZHgpICogY29ybmVycmFkaXVzO1xuICAgICAgICAgICAgICAgICAgICAgICAgeTIgPSB5MDtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHgyID0geDA7XG4gICAgICAgICAgICAgICAgICAgICAgICB5MiA9IHkwICsgZHkgLyBNYXRoLmFicyhkeSkgKiBjb3JuZXJyYWRpdXM7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgdmFyIGN4ID0gTWF0aC5hYnMoeDIgLSB4KTtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGN5ID0gTWF0aC5hYnMoeTIgLSB5KTtcbiAgICAgICAgICAgICAgICAgICAgcmVzdWx0LnJvdXRlcGF0aCArPSAnQSAnICsgY3ggKyAnICcgKyBjeSArICcgMCAwICcgKyBhbmdsZSArICcgJyArIHgyICsgJyAnICsgeTIgKyAnICc7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICB2YXIgYXJyb3d0aXAgPSBbeCwgeV07XG4gICAgICAgICAgICAgICAgICAgIHZhciBhcnJvd2Nvcm5lcjEsIGFycm93Y29ybmVyMjtcbiAgICAgICAgICAgICAgICAgICAgaWYgKE1hdGguYWJzKGR4KSA+IDApIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHggLT0gZHggLyBNYXRoLmFicyhkeCkgKiBhcnJvd2hlaWdodDtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFycm93Y29ybmVyMSA9IFt4LCB5ICsgYXJyb3d3aWR0aF07XG4gICAgICAgICAgICAgICAgICAgICAgICBhcnJvd2Nvcm5lcjIgPSBbeCwgeSAtIGFycm93d2lkdGhdO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgeSAtPSBkeSAvIE1hdGguYWJzKGR5KSAqIGFycm93aGVpZ2h0O1xuICAgICAgICAgICAgICAgICAgICAgICAgYXJyb3djb3JuZXIxID0gW3ggKyBhcnJvd3dpZHRoLCB5XTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFycm93Y29ybmVyMiA9IFt4IC0gYXJyb3d3aWR0aCwgeV07XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgcmVzdWx0LnJvdXRlcGF0aCArPSAnTCAnICsgeCArICcgJyArIHkgKyAnICc7XG4gICAgICAgICAgICAgICAgICAgIGlmIChhcnJvd2hlaWdodCA+IDApIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlc3VsdC5hcnJvd3BhdGggPSAnTSAnICsgYXJyb3d0aXBbMF0gKyAnICcgKyBhcnJvd3RpcFsxXSArICcgTCAnICsgYXJyb3djb3JuZXIxWzBdICsgJyAnICsgYXJyb3djb3JuZXIxWzFdXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgKyAnIEwgJyArIGFycm93Y29ybmVyMlswXSArICcgJyArIGFycm93Y29ybmVyMlsxXTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIHZhciBsaSA9IHJvdXRlWzBdO1xuICAgICAgICAgICAgdmFyIHggPSBsaVsxXS54LCB5ID0gbGlbMV0ueTtcbiAgICAgICAgICAgIHZhciBkeCA9IHggLSBsaVswXS54O1xuICAgICAgICAgICAgdmFyIGR5ID0geSAtIGxpWzBdLnk7XG4gICAgICAgICAgICB2YXIgYXJyb3d0aXAgPSBbeCwgeV07XG4gICAgICAgICAgICB2YXIgYXJyb3djb3JuZXIxLCBhcnJvd2Nvcm5lcjI7XG4gICAgICAgICAgICBpZiAoTWF0aC5hYnMoZHgpID4gMCkge1xuICAgICAgICAgICAgICAgIHggLT0gZHggLyBNYXRoLmFicyhkeCkgKiBhcnJvd2hlaWdodDtcbiAgICAgICAgICAgICAgICBhcnJvd2Nvcm5lcjEgPSBbeCwgeSArIGFycm93d2lkdGhdO1xuICAgICAgICAgICAgICAgIGFycm93Y29ybmVyMiA9IFt4LCB5IC0gYXJyb3d3aWR0aF07XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICB5IC09IGR5IC8gTWF0aC5hYnMoZHkpICogYXJyb3doZWlnaHQ7XG4gICAgICAgICAgICAgICAgYXJyb3djb3JuZXIxID0gW3ggKyBhcnJvd3dpZHRoLCB5XTtcbiAgICAgICAgICAgICAgICBhcnJvd2Nvcm5lcjIgPSBbeCAtIGFycm93d2lkdGgsIHldO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmVzdWx0LnJvdXRlcGF0aCArPSAnTCAnICsgeCArICcgJyArIHkgKyAnICc7XG4gICAgICAgICAgICBpZiAoYXJyb3doZWlnaHQgPiAwKSB7XG4gICAgICAgICAgICAgICAgcmVzdWx0LmFycm93cGF0aCA9ICdNICcgKyBhcnJvd3RpcFswXSArICcgJyArIGFycm93dGlwWzFdICsgJyBMICcgKyBhcnJvd2Nvcm5lcjFbMF0gKyAnICcgKyBhcnJvd2Nvcm5lcjFbMV1cbiAgICAgICAgICAgICAgICAgICAgKyAnIEwgJyArIGFycm93Y29ybmVyMlswXSArICcgJyArIGFycm93Y29ybmVyMlsxXTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH07XG4gICAgcmV0dXJuIEdyaWRSb3V0ZXI7XG59KCkpO1xuZXhwb3J0cy5HcmlkUm91dGVyID0gR3JpZFJvdXRlcjtcbi8vIyBzb3VyY2VNYXBwaW5nVVJMPWRhdGE6YXBwbGljYXRpb24vanNvbjtiYXNlNjQsZXlKMlpYSnphVzl1SWpvekxDSm1hV3hsSWpvaVozSnBaSEp2ZFhSbGNpNXFjeUlzSW5OdmRYSmpaVkp2YjNRaU9pSWlMQ0p6YjNWeVkyVnpJanBiSWk0dUx5NHVMMWRsWWtOdmJHRXZjM0pqTDJkeWFXUnliM1YwWlhJdWRITWlYU3dpYm1GdFpYTWlPbHRkTENKdFlYQndhVzVuY3lJNklqczdRVUZEUVN4NVEwRkJjVU03UVVGRGNrTXNLMEpCUVcxRU8wRkJRMjVFTEdsRVFVRXdRenRCUVV0MFF6dEpRVWxKTEhGQ1FVRnRRaXhGUVVGVkxFVkJRVk1zU1VGQlpTeEZRVUZUTEZGQlFXdENPMUZCUVRkRUxFOUJRVVVzUjBGQlJpeEZRVUZGTEVOQlFWRTdVVUZCVXl4VFFVRkpMRWRCUVVvc1NVRkJTU3hEUVVGWE8xRkJRVk1zWVVGQlVTeEhRVUZTTEZGQlFWRXNRMEZCVlR0UlFVTTFSU3hKUVVGSkxFTkJRVU1zU1VGQlNTeEhRVUZITEU5QlFVOHNVVUZCVVN4TFFVRkxMRmRCUVZjc1NVRkJTU3hSUVVGUkxFTkJRVU1zVFVGQlRTeExRVUZMTEVOQlFVTXNRMEZCUXp0SlFVTjZSU3hEUVVGRE8wbEJRMHdzYTBKQlFVTTdRVUZCUkN4RFFVRkRMRUZCVUVRc1NVRlBRenRCUVZCWkxHdERRVUZYTzBGQlVYaENPMGxCUTBrc1kwRkJiVUlzUlVGQlZTeEZRVUZUTEVOQlFWRXNSVUZCVXl4RFFVRlRMRVZCUVZNc1NVRkJkMElzUlVGQlV5eEpRVUZYTzFGQlFUVkRMSEZDUVVGQkxFVkJRVUVzVjBGQmQwSTdVVUZCVXl4eFFrRkJRU3hGUVVGQkxGZEJRVmM3VVVGQmJFY3NUMEZCUlN4SFFVRkdMRVZCUVVVc1EwRkJVVHRSUVVGVExFMUJRVU1zUjBGQlJDeERRVUZETEVOQlFVODdVVUZCVXl4TlFVRkRMRWRCUVVRc1EwRkJReXhEUVVGUk8xRkJRVk1zVTBGQlNTeEhRVUZLTEVsQlFVa3NRMEZCYjBJN1VVRkJVeXhUUVVGSkxFZEJRVW9zU1VGQlNTeERRVUZQTzBsQlFVY3NRMEZCUXp0SlFVTTNTQ3hYUVVGRE8wRkJRVVFzUTBGQlF5eEJRVVpFTEVsQlJVTTdRVUZHV1N4dlFrRkJTVHRCUVVscVFqdEpRVXRKTEd0RFFVRnRRaXhEUVVGTkxFVkJRVk1zUTBGQlRUdFJRVUZ5UWl4TlFVRkRMRWRCUVVRc1EwRkJReXhEUVVGTE8xRkJRVk1zVFVGQlF5eEhRVUZFTEVOQlFVTXNRMEZCU3p0UlFVTndReXhKUVVGSkxFVkJRVVVzUjBGQlJ5eDNRa0ZCZDBJc1EwRkJReXhUUVVGVExFTkJRVU1zUTBGQlF5eEZRVUZGTEVOQlFVTXNRMEZCUXl4RFFVRkRPMUZCUTJ4RUxFbEJRVWtzUlVGQlJTeEhRVUZITEVOQlFVTXNRMEZCUXl4TFFVRkxMRU5CUVVNc1EwRkJReXhEUVVGRExFTkJRVU1zVDBGQlR5eEZRVUZGTEVOQlFVTTdVVUZET1VJc1NVRkJTU3hGUVVGRkxFZEJRVWNzZDBKQlFYZENMRU5CUVVNc1UwRkJVeXhEUVVGRExFTkJRVU1zUlVGQlJTeEZRVUZGTEVOQlFVTXNRMEZCUXp0UlFVTnVSQ3hKUVVGSkxFVkJRVVVzUTBGQlF5eE5RVUZOTEVsQlFVa3NSVUZCUlN4RFFVRkRMRTFCUVUwc1JVRkJSVHRaUVVONFFpeEpRVUZKTEVOQlFVTXNUVUZCVFN4SFFVRkhMRVZCUVVVc1EwRkJReXhOUVVGTkxFTkJRVU03V1VGRGVFSXNTVUZCU1N4RFFVRkRMRVZCUVVVc1IwRkJSeXhGUVVGRkxFTkJRVU1zUlVGQlJTeERRVUZETzFsQlEyaENMRWxCUVVrc1EwRkJReXhGUVVGRkxFZEJRVWNzUlVGQlJTeERRVUZETEVWQlFVVXNRMEZCUXp0WlFVTm9RaXhKUVVGSkxFTkJRVU1zVVVGQlVTeEhRVUZITEV0QlFVc3NRMEZCUXp0VFFVTjZRanRoUVVGTk8xbEJRMGdzU1VGQlNTeERRVUZETEUxQlFVMHNSMEZCUnl4RlFVRkZMRU5CUVVNc1RVRkJUU3hEUVVGRE8xbEJRM2hDTEVsQlFVa3NRMEZCUXl4RlFVRkZMRWRCUVVjc1JVRkJSU3hEUVVGRExFVkJRVVVzUTBGQlF6dFpRVU5vUWl4SlFVRkpMRU5CUVVNc1JVRkJSU3hIUVVGSExFTkJRVU1zUTBGQlF5eE5RVUZOTEVkQlFVY3NSVUZCUlN4RFFVRkRMRVZCUVVVc1IwRkJSeXhGUVVGRkxFTkJRVU1zVFVGQlRTeERRVUZETzFsQlEzWkRMRWxCUVVrc1EwRkJReXhSUVVGUkxFZEJRVWNzU1VGQlNTeERRVUZETzFOQlEzaENPMGxCUTB3c1EwRkJRenRKUVVOakxHdERRVUZUTEVkQlFYaENMRlZCUVRSQ0xFTkJRVTBzUlVGQlJTeERRVUZOTzFGQlEzUkRMRWxCUVVrc1EwRkJReXhIUVVGSExFTkJRVU1zUTBGQlF5eE5RVUZOTEVOQlFVTTdVVUZEYWtJc1NVRkJTU3hEUVVGRExFZEJRVWNzUTBGQlF5eERRVUZETEUxQlFVMHNRMEZCUXp0UlFVTnFRaXhKUVVGSkxFdEJRVXNzUjBGQlJ5eEZRVUZGTEUxQlFVMHNSVUZCUlN4RFFVRkRMRVZCUVVVc1JVRkJSU3hGUVVGRkxFTkJRVU1zUTBGQlF5eEZRVUZGTEVWQlFVVXNSVUZCUlN4RFFVRkRMRU5CUVVNc1JVRkJSU3hEUVVGRE8xRkJRekZETEVsQlFVa3NRMEZCUXl4SFFVRkhMRWxCUVVrc1MwRkJTeXhEUVVGRExFTkJRVU1zUTBGQlF5eERRVUZETzFGQlEzSkNMRXRCUVVzc1NVRkJTU3hEUVVGRExFZEJRVWNzUTBGQlF5eEZRVUZGTEVOQlFVTXNSMEZCUnl4RFFVRkRMRVZCUVVVc1EwRkJReXhGUVVGRkxFVkJRVVU3V1VGRGVFSXNRMEZCUXl4RFFVRkRMRU5CUVVNc1EwRkJReXhIUVVGSExFbEJRVWtzUzBGQlN5eERRVUZETEVOQlFVTXNRMEZCUXl4RFFVRkRPMWxCUTNCQ0xFdEJRVXNzU1VGQlNTeERRVUZETEVkQlFVY3NRMEZCUXl4RlFVRkZMRU5CUVVNc1IwRkJSeXhEUVVGRExFVkJRVVVzUTBGQlF5eEZRVUZGTzJkQ1FVTjBRaXhKUVVGSkxFTkJRVU1zUTBGQlF5eERRVUZETEVOQlFVTXNTMEZCU3l4RFFVRkRMRU5CUVVNc1EwRkJReXhEUVVGRExFVkJRVVU3YjBKQlEyWXNTVUZCU1N4RFFVRkRMRWRCUVVjc1EwRkJReXhEUVVGRExFTkJRVU1zUTBGQlF5eERRVUZETEVOQlFVTXNRMEZCUXl4SFFVRkhMRU5CUVVNc1EwRkJReXhMUVVGTExFTkJRVU1zU1VGQlNTeERRVUZETEV0QlFVc3NRMEZCUXl4RFFVRkRMRU5CUVVNc1EwRkJReXhEUVVGRExFTkJRVU1zUTBGQlF5eERRVUZETEVOQlFVTXNRMEZCUXl4RFFVRkRMRU5CUVVNc1IwRkJSeXhEUVVGRExFTkJRVU1zUTBGQlF5eERRVUZETEVkQlFVY3NRMEZCUXl4RFFVRkRMRWRCUVVjc1EwRkJReXhEUVVGRE8yOUNRVU5xUlN4SlFVRkpMRU5CUVVNc1IwRkJSeXhMUVVGTExFTkJRVU1zVFVGQlRTeEZRVUZGTzNkQ1FVTnNRaXhMUVVGTExFTkJRVU1zVFVGQlRTeEhRVUZITEVOQlFVTXNRMEZCUXp0M1FrRkRha0lzUzBGQlN5eERRVUZETEVWQlFVVXNSMEZCUnl4RFFVRkRMRWRCUVVjc1EwRkJReXhIUVVGSExFTkJRVU1zUTBGQlF6dDNRa0ZEY2tJc1MwRkJTeXhEUVVGRExFVkJRVVVzUjBGQlJ5eERRVUZETEVkQlFVY3NRMEZCUXl4SFFVRkhMRU5CUVVNc1EwRkJRenR4UWtGRGVFSTdiMEpCUVVFc1EwRkJRenRwUWtGRFREczdiMEpCUVUwc1EwRkJReXhEUVVGRExFTkJRVU1zUTBGQlF5eERRVUZETEVOQlFVTXNRMEZCUXl4SFFVRkhMRU5CUVVNc1EwRkJRenRUUVVNeFFqdFJRVU5FTEU5QlFVOHNTMEZCU3l4RFFVRkRPMGxCUTJwQ0xFTkJRVU03U1VGRFJDdzRRMEZCVnl4SFFVRllPMUZCUTBrc1QwRkJUeXhKUVVGSkxFTkJRVU1zVFVGQlRTeEpRVUZKTEVOQlFVTXNRMEZCUXl4RFFVRkRMRU5CUVVNc1NVRkJTU3hEUVVGRExFTkJRVU1zUTBGQlF5eExRVUZMTEVOQlFVTXNTVUZCU1N4RFFVRkRMRVZCUVVVc1JVRkJSU3hKUVVGSkxFTkJRVU1zUlVGQlJTeEhRVUZITEVsQlFVa3NRMEZCUXl4TlFVRk5MRU5CUVVNc1EwRkJReXhEUVVGRExFTkJRVU1zUlVGQlJTeERRVUZETzBsQlEyaEdMRU5CUVVNN1NVRkRUQ3dyUWtGQlF6dEJRVUZFTEVOQlFVTXNRVUV6UTBRc1NVRXlRME03UVVFelExa3NORVJCUVhkQ08wRkJhVVJ5UXp0SlFYTkVTU3h2UWtGQmJVSXNZVUZCY1VJc1JVRkJSU3hSUVVFMFFpeEZRVUZUTEZsQlFYbENPMUZCUVhoSExHbENRV3RJUXp0UlFXeElPRVVzTmtKQlFVRXNSVUZCUVN4cFFrRkJlVUk3VVVGQmNrWXNhMEpCUVdFc1IwRkJZaXhoUVVGaExFTkJRVkU3VVVGQmRVTXNhVUpCUVZrc1IwRkJXaXhaUVVGWkxFTkJRV0U3VVVGeVJIaEhMRmRCUVUwc1IwRkJhMElzU1VGQlNTeERRVUZETzFGQmMwUjZRaXhKUVVGSkxFTkJRVU1zUzBGQlN5eEhRVUZITEdGQlFXRXNRMEZCUXl4SFFVRkhMRU5CUVVNc1ZVRkJReXhEUVVGRExFVkJRVVVzUTBGQlF5eEpRVUZMTEU5QlFVRXNTVUZCU1N4WFFVRlhMRU5CUVVNc1EwRkJReXhGUVVGRkxGRkJRVkVzUTBGQlF5eFRRVUZUTEVOQlFVTXNRMEZCUXl4RFFVRkRMRVZCUVVVc1VVRkJVU3hEUVVGRExGZEJRVmNzUTBGQlF5eERRVUZETEVOQlFVTXNRMEZCUXl4RlFVRnNSU3hEUVVGclJTeERRVUZETEVOQlFVTTdVVUZETjBjc1NVRkJTU3hEUVVGRExFMUJRVTBzUjBGQlJ5eEpRVUZKTEVOQlFVTXNTMEZCU3l4RFFVRkRMRTFCUVUwc1EwRkJReXhWUVVGQkxFTkJRVU1zU1VGQlJ5eFBRVUZCTEVOQlFVTXNRMEZCUXl4SlFVRkpMRVZCUVU0c1EwRkJUU3hEUVVGRExFTkJRVU03VVVGRE5VTXNTVUZCU1N4RFFVRkRMRTFCUVUwc1IwRkJSeXhKUVVGSkxFTkJRVU1zUzBGQlN5eERRVUZETEUxQlFVMHNRMEZCUXl4VlFVRkJMRU5CUVVNc1NVRkJSeXhQUVVGQkxFTkJRVU1zUTBGQlF5eERRVUZETEVsQlFVa3NSVUZCVUN4RFFVRlBMRU5CUVVNc1EwRkJRenRSUVVNM1F5eEpRVUZKTEVOQlFVTXNTVUZCU1N4SFFVRkhMRWxCUVVrc1EwRkJReXhaUVVGWkxFTkJRVU1zUjBGQlJ5eERRVUZETEVOQlFVTTdVVUZEYmtNc1NVRkJTU3hEUVVGRExFbEJRVWtzUjBGQlJ5eEpRVUZKTEVOQlFVTXNXVUZCV1N4RFFVRkRMRWRCUVVjc1EwRkJReXhEUVVGRE8xRkJSMjVETEVsQlFVa3NRMEZCUXl4TlFVRk5MRU5CUVVNc1QwRkJUeXhEUVVGRExGVkJRVUVzUTBGQlF6dFpRVU5xUWl4UFFVRkJMRU5CUVVNc1EwRkJReXhSUVVGUkxFTkJRVU1zVDBGQlR5eERRVUZETEZWQlFVRXNRMEZCUXl4SlFVRkhMRTlCUVVFc1MwRkJTU3hEUVVGRExFdEJRVXNzUTBGQlV5eERRVUZETEVOQlFVTXNRMEZCUXl4TlFVRk5MRWRCUVVjc1EwRkJReXhGUVVGb1F5eERRVUZuUXl4RFFVRkRPMUZCUVhoRUxFTkJRWGRFTEVOQlFVTXNRMEZCUXp0UlFVYzVSQ3hKUVVGSkxFTkJRVU1zU1VGQlNTeEhRVUZITEVWQlFVVXNVVUZCVVN4RlFVRkZMRVZCUVVVc1JVRkJSU3hEUVVGRE8xRkJRemRDTEVsQlFVa3NRMEZCUXl4TFFVRkxMRU5CUVVNc1QwRkJUeXhEUVVGRExGVkJRVUVzUTBGQlF6dFpRVU5vUWl4SlFVRkpMRTlCUVU4c1EwRkJReXhEUVVGRExFMUJRVTBzUzBGQlN5eFhRVUZYTEVWQlFVVTdaMEpCUTJwRExFTkJRVU1zUTBGQlF5eE5RVUZOTEVkQlFVY3NTMEZCU1N4RFFVRkRMRWxCUVVrc1EwRkJRenRuUWtGRGNrSXNTMEZCU1N4RFFVRkRMRWxCUVVrc1EwRkJReXhSUVVGUkxFTkJRVU1zU1VGQlNTeERRVUZETEVOQlFVTXNRMEZCUXl4RlFVRkZMRU5CUVVNc1EwRkJRenRoUVVOcVF6dFpRVTlFTEVOQlFVTXNRMEZCUXl4TFFVRkxMRWRCUVVjc1JVRkJSU3hEUVVGQk8xRkJRMmhDTEVOQlFVTXNRMEZCUXl4RFFVRkRPMUZCUjBnc1NVRkJTU3hEUVVGRExGZEJRVmNzUjBGQlJ5eEpRVUZKTEVOQlFVTXNTMEZCU3l4RFFVRkRMRXRCUVVzc1EwRkJReXhEUVVGRExFTkJRVU1zUTBGQlF6dFJRVU4yUXl4SlFVRkpMRU5CUVVNc1YwRkJWeXhEUVVGRExFbEJRVWtzUTBGQlF5eFZRVUZETEVOQlFVTXNSVUZCUlN4RFFVRkRMRWxCUVVzc1QwRkJRU3hMUVVGSkxFTkJRVU1zVVVGQlVTeERRVUZETEVOQlFVTXNRMEZCUXl4SFFVRkhMRXRCUVVrc1EwRkJReXhSUVVGUkxFTkJRVU1zUTBGQlF5eERRVUZETEVWQlFXNURMRU5CUVcxRExFTkJRVU1zUTBGQlF6dFJRVXR5UlN4SlFVRkpMR2xDUVVGcFFpeEhRVUZITEVsQlFVa3NRMEZCUXl4WFFVRlhMRU5CUVVNc1MwRkJTeXhEUVVGRExFTkJRVU1zUTBGQlF5eERRVUZETEU5QlFVOHNSVUZCUlN4RFFVRkRMRTFCUVUwc1EwRkJReXhWUVVGQkxFTkJRVU1zU1VGQlJ5eFBRVUZCTEVOQlFVTXNRMEZCUXl4RFFVRkRMRWxCUVVrc1JVRkJVQ3hEUVVGUExFTkJRVU1zUTBGQlF6dFJRVU5vUml4cFFrRkJhVUlzUTBGQlF5eFBRVUZQTEVOQlFVTXNWVUZCUVN4RFFVRkRPMWxCUTNaQ0xFbEJRVWtzUTBGQlF5eEhRVUZITEhGQ1FVRlRMRU5CUVVNc1MwRkJTeXhGUVVGRkxFTkJRVU03V1VGRE1VSXNRMEZCUXl4RFFVRkRMRkZCUVZFc1EwRkJReXhQUVVGUExFTkJRVU1zVlVGQlFTeERRVUZETEVsQlFVY3NUMEZCUVN4RFFVRkRMRWRCUVVjc1EwRkJReXhEUVVGRExFdEJRVXNzUTBGQlF5eExRVUZKTEVOQlFVTXNTMEZCU3l4RFFVRkRMRU5CUVVNc1EwRkJReXhEUVVGRExFbEJRVWtzUTBGQlF5eEZRVUV2UWl4RFFVRXJRaXhEUVVGRExFTkJRVU03V1VGRGVFUXNRMEZCUXl4RFFVRkRMRWxCUVVrc1IwRkJSeXhEUVVGRExFTkJRVU1zVDBGQlR5eERRVUZETEV0QlFVa3NRMEZCUXl4WlFVRlpMRU5CUVVNc1EwRkJRenRSUVVNeFF5eERRVUZETEVOQlFVTXNRMEZCUXp0UlFVVklMRWxCUVVrc1QwRkJUeXhIUVVGSExFbEJRVWtzUTBGQlF5eFRRVUZUTEVOQlFVTXNTVUZCU1N4RFFVRkRMRWxCUVVrc1EwRkJReXhIUVVGSExFTkJRVU1zVlVGQlFTeERRVUZETEVsQlFVY3NUMEZCUVN4RFFVRkRMRU5CUVVNc1IwRkJSeXhGUVVGTUxFTkJRVXNzUTBGQlF5eERRVUZETEVOQlFVTTdVVUZEZGtRc1NVRkJTU3hQUVVGUExFZEJRVWNzU1VGQlNTeERRVUZETEZOQlFWTXNRMEZCUXl4SlFVRkpMRU5CUVVNc1NVRkJTU3hEUVVGRExFZEJRVWNzUTBGQlF5eFZRVUZCTEVOQlFVTXNTVUZCUnl4UFFVRkJMRU5CUVVNc1EwRkJReXhIUVVGSExFVkJRVXdzUTBGQlN5eERRVUZETEVOQlFVTXNRMEZCUXp0UlFVZDJSQ3hKUVVGSkxFbEJRVWtzUjBGQlJ5eFBRVUZQTEVOQlFVTXNRMEZCUXl4RFFVRkRMRVZCUVVVc1NVRkJTU3hIUVVGSExFOUJRVThzUTBGQlF5eFBRVUZQTEVOQlFVTXNUVUZCVFN4SFFVRkhMRU5CUVVNc1EwRkJReXhEUVVGRE8xRkJRekZFTEVsQlFVa3NTVUZCU1N4SFFVRkhMRTlCUVU4c1EwRkJReXhEUVVGRExFTkJRVU1zUlVGQlJTeEpRVUZKTEVkQlFVY3NUMEZCVHl4RFFVRkRMRTlCUVU4c1EwRkJReXhOUVVGTkxFZEJRVWNzUTBGQlF5eERRVUZETEVOQlFVTTdVVUZITVVRc1NVRkJTU3hOUVVGTkxFZEJRVWNzU1VGQlNTeERRVUZETEVsQlFVa3NRMEZCUXl4SFFVRkhMRU5CUVVNc1ZVRkJRU3hEUVVGRExFbEJRVWNzVDBGQlFTeERRVUZMTEVWQlFVVXNSVUZCUlN4RlFVRkZMRWxCUVVrc1JVRkJSU3hGUVVGRkxFVkJRVVVzU1VGQlNTeEZRVUZGTEVWQlFVVXNSVUZCUlN4RFFVRkRMRU5CUVVNc1IwRkJSeXhGUVVGRkxFVkJRVVVzUlVGQlJTeERRVUZETEVOQlFVTXNSMEZCUnl4RlFVRkZMRU5CUVVFc1JVRkJha1FzUTBGQmFVUXNRMEZCUXp0aFFVTTFSU3hOUVVGTkxFTkJRVU1zVDBGQlR5eERRVUZETEVkQlFVY3NRMEZCUXl4VlFVRkJMRU5CUVVNc1NVRkJSeXhQUVVGQkxFTkJRVXNzUlVGQlJTeEZRVUZGTEVWQlFVVXNTVUZCU1N4RlFVRkZMRVZCUVVVc1JVRkJSU3hKUVVGSkxFVkJRVVVzUlVGQlJTeEZRVUZGTEVOQlFVTXNSVUZCUlN4RlFVRkZMRVZCUVVVc1EwRkJReXhGUVVGRkxFTkJRVUVzUlVGQmVrTXNRMEZCZVVNc1EwRkJReXhEUVVGRExFTkJRVU03VVVGSGVFVXNTVUZCU1N4TlFVRk5MRWRCUVVjc1NVRkJTU3hEUVVGRExFbEJRVWtzUTBGQlF5eEhRVUZITEVOQlFVTXNWVUZCUVN4RFFVRkRMRWxCUVVjc1QwRkJRU3hEUVVGTExFVkJRVVVzUlVGQlJTeEZRVUZGTEVOQlFVTXNRMEZCUXl4SFFVRkhMRVZCUVVVc1JVRkJSU3hGUVVGRkxFTkJRVU1zUTBGQlF5eEhRVUZITEVWQlFVVXNSVUZCUlN4RlFVRkZMRWxCUVVrc1JVRkJSU3hGUVVGRkxFVkJRVVVzU1VGQlNTeEZRVUZGTEVOQlFVRXNSVUZCYWtRc1EwRkJhVVFzUTBGQlF6dGhRVU0xUlN4TlFVRk5MRU5CUVVNc1QwRkJUeXhEUVVGRExFZEJRVWNzUTBGQlF5eFZRVUZCTEVOQlFVTXNTVUZCUnl4UFFVRkJMRU5CUVVzc1JVRkJSU3hGUVVGRkxFVkJRVVVzUTBGQlF5eEZRVUZGTEVWQlFVVXNSVUZCUlN4RFFVRkRMRVZCUVVVc1JVRkJSU3hGUVVGRkxFbEJRVWtzUlVGQlJTeEZRVUZGTEVWQlFVVXNTVUZCU1N4RlFVRkZMRU5CUVVFc1JVRkJla01zUTBGQmVVTXNRMEZCUXl4RFFVRkRMRU5CUVVNN1VVRkhlRVVzU1VGQlNTeExRVUZMTEVkQlFVY3NUVUZCVFN4RFFVRkRMRTFCUVUwc1EwRkJReXhOUVVGTkxFTkJRVU1zUTBGQlF6dFJRVWRzUXl4TFFVRkxMRU5CUVVNc1QwRkJUeXhEUVVGRExGVkJRVUVzUTBGQlF5eEpRVUZITEU5QlFVRXNRMEZCUXl4RFFVRkRMRXRCUVVzc1IwRkJSeXhGUVVGRkxFVkJRVm9zUTBGQldTeERRVUZETEVOQlFVTTdVVUZIYUVNc1NVRkJTU3hEUVVGRExFdEJRVXNzUjBGQlJ5eEZRVUZGTEVOQlFVTTdVVUZEYUVJc1NVRkJTU3hEUVVGRExFdEJRVXNzUjBGQlJ5eEZRVUZGTEVOQlFVTTdVVUZIYUVJc1RVRkJUU3hEUVVGRExFOUJRVThzUTBGQlF5eFZRVUZCTEVOQlFVTTdXVUZEV2l4UFFVRkJMRTFCUVUwc1EwRkJReXhQUVVGUExFTkJRVU1zVlVGQlFTeERRVUZETzJkQ1FVTmFMRWxCUVVrc1EwRkJReXhIUVVGSExFbEJRVWtzU1VGQlNTeERRVUZETEV0QlFVa3NRMEZCUXl4TFFVRkxMRU5CUVVNc1RVRkJUU3hGUVVGRkxFTkJRVU1zUTBGQlF5eEZRVUZGTEVWQlFVVXNRMEZCUXl4RFFVRkRMRVZCUVVVc1EwRkJReXhEUVVGRE8yZENRVU5vUkN4RFFVRkRMRU5CUVVNc1MwRkJTeXhEUVVGRExFbEJRVWtzUTBGQlF5eERRVUZETEVOQlFVTXNRMEZCUXp0blFrRkRhRUlzUTBGQlF5eERRVUZETEV0QlFVc3NRMEZCUXl4SlFVRkpMRU5CUVVNc1EwRkJReXhEUVVGRExFTkJRVU03WjBKQlEyaENMRXRCUVVrc1EwRkJReXhMUVVGTExFTkJRVU1zU1VGQlNTeERRVUZETEVOQlFVTXNRMEZCUXl4RFFVRkRPMmRDUVVkdVFpeEpRVUZKTEVOQlFVTXNSMEZCUnl4TFFVRkpMRU5CUVVNc1YwRkJWeXhEUVVGRExFMUJRVTBzUTBGQlF6dG5Ra0ZEYUVNc1QwRkJUeXhEUVVGRExFVkJRVVVzUjBGQlJ5eERRVUZETEVWQlFVVTdiMEpCUTFvc1NVRkJTU3hKUVVGSkxFZEJRVWNzUzBGQlNTeERRVUZETEZkQlFWY3NRMEZCUXl4RFFVRkRMRU5CUVVNc1JVRkRNVUlzUTBGQlF5eEhRVUZITEVsQlFVa3NRMEZCUXl4SlFVRkpMRU5CUVVNN2IwSkJRMnhDTEVsQlFVa3NSVUZCUlN4SFFVRkhMRWxCUVVrc1EwRkJReXhIUVVGSExFTkJRVU1zUTBGQlF5eERRVUZETEVOQlFVTXNSMEZCUnl4RFFVRkRMRU5CUVVNc1JVRkJSU3hGUVVGRkxFTkJRVU1zUlVGRE0wSXNSVUZCUlN4SFFVRkhMRWxCUVVrc1EwRkJReXhIUVVGSExFTkJRVU1zUTBGQlF5eERRVUZETEVOQlFVTXNSMEZCUnl4RFFVRkRMRU5CUVVNc1JVRkJSU3hGUVVGRkxFTkJRVU1zUTBGQlF6dHZRa0ZEYUVNc1NVRkJTU3hGUVVGRkxFZEJRVWNzUTBGQlF5eERRVUZETEV0QlFVc3NSVUZCUlN4SFFVRkhMRU5CUVVNc1NVRkJTU3hGUVVGRkxFZEJRVWNzUTBGQlF5eERRVUZETEUxQlFVMHNSVUZCUlN4SFFVRkhMRU5CUVVNc1JVRkJSVHQzUWtGRGNrTXNRMEZCUlN4RFFVRkRMRWxCUVVrc1IwRkJSeXhKUVVGSkxFTkJRVU03ZDBKQlEzSkNMRTFCUVUwN2NVSkJRMVE3YVVKQlEwbzdXVUZEVEN4RFFVRkRMRU5CUVVNN1VVRnNRa1lzUTBGclFrVXNRMEZEUkN4RFFVRkRPMUZCUlU0c1MwRkJTeXhEUVVGRExFOUJRVThzUTBGQlF5eFZRVUZETEVOQlFVTXNSVUZCUlN4RlFVRkZPMWxCUldoQ0xFdEJRVWtzUTBGQlF5eExRVUZMTEVOQlFVTXNUMEZCVHl4RFFVRkRMRlZCUVVNc1EwRkJReXhGUVVGRkxFTkJRVU03WjBKQlEzQkNMRU5CUVVNc1EwRkJReXhKUVVGSkxFTkJRVU1zYVVKQlFXbENMRU5CUVVNc1EwRkJReXhEUVVGRExFVkJRVVVzUlVGQlJTeERRVUZETEVOQlFVTXNSVUZCUlN4RlFVRkZMRU5CUVVNc1EwRkJReXhGUVVGRkxFVkJRVVVzUTBGQlF5eERRVUZETEVWQlFVVXNRMEZCUXl4RFFVRkRMRTlCUVU4c1EwRkJReXhWUVVGRExGTkJRVk1zUlVGQlJTeERRVUZETzI5Q1FVVnNSU3hKUVVGSkxFTkJRVU1zUjBGQlJ5eEpRVUZKTEVsQlFVa3NRMEZCUXl4TFFVRkpMRU5CUVVNc1MwRkJTeXhEUVVGRExFMUJRVTBzUlVGQlJTeFRRVUZUTEVOQlFVTXNRMEZCUXl4RlFVRkZMRk5CUVZNc1EwRkJReXhEUVVGRExFVkJRVVVzUTBGQlF5eEZRVUZGTEVOQlFVTXNRMEZCUXl4RFFVRkRPMjlDUVVOd1JTeExRVUZKTEVOQlFVTXNTMEZCU3l4RFFVRkRMRWxCUVVrc1EwRkJReXhEUVVGRExFTkJRVU1zUTBGQlF6dHZRa0ZEYmtJc1EwRkJReXhEUVVGRExFdEJRVXNzUTBGQlF5eEpRVUZKTEVOQlFVTXNRMEZCUXl4RFFVRkRMRU5CUVVNN2IwSkJRMmhDTEVOQlFVTXNRMEZCUXl4TFFVRkxMRU5CUVVNc1NVRkJTU3hEUVVGRExFTkJRVU1zUTBGQlF5eERRVUZETzJkQ1FVTndRaXhEUVVGRExFTkJRVU1zUTBGQlF6dFpRVU5RTEVOQlFVTXNRMEZCUXl4RFFVRkRPMWxCUjBnc1NVRkJTU3hQUVVGUExFZEJRVWNzU1VGQlNTeERRVUZETEVkQlFVY3NRMEZCUXl4RFFVRkRMRU5CUVVNc1JVRkJSU3hIUVVGSExFTkJRVU1zUTBGQlF5eEZRVUZGTEVOQlFVTXNSMEZCUnl4SFFVRkhMRU5CUVVNN1dVRkRNVU1zU1VGQlNTeExRVUZMTEVkQlFVY3NWVUZCUXl4RFFVRkRMRVZCUVVVc1EwRkJReXhKUVVGTExFOUJRVUVzVDBGQlR5eERRVUZETEVOQlFVTXNRMEZCUXl4RFFVRkRMRU5CUVVNc1EwRkJReXhIUVVGSExFTkJRVU1zUTBGQlF5eERRVUZETEVOQlFVTXNRMEZCUXl4RFFVRkRMRU5CUVVNc1EwRkJReXhEUVVGRExFZEJRVWNzUTBGQlF5eERRVUZETEVOQlFVTXNSVUZCTDBJc1EwRkJLMElzUTBGQlF6dFpRVU4wUkN4RFFVRkRMRU5CUVVNc1MwRkJTeXhEUVVGRExFbEJRVWtzUTBGQlF5eExRVUZMTEVOQlFVTXNRMEZCUXp0WlFVTndRaXhMUVVGTExFbEJRVWtzUTBGQlF5eEhRVUZITEVOQlFVTXNSVUZCUlN4RFFVRkRMRWRCUVVjc1EwRkJReXhEUVVGRExFdEJRVXNzUTBGQlF5eE5RVUZOTEVWQlFVVXNRMEZCUXl4RlFVRkZMRVZCUVVVN1owSkJRM0pETEVsQlFVa3NRMEZCUXl4SFFVRkhMRU5CUVVNc1EwRkJReXhMUVVGTExFTkJRVU1zUTBGQlF5eEhRVUZITEVOQlFVTXNRMEZCUXl4RlFVRkZMRU5CUVVNc1IwRkJSeXhEUVVGRExFTkJRVU1zUzBGQlN5eERRVUZETEVOQlFVTXNRMEZCUXl4RFFVRkRPMmRDUVVOMlF5eEpRVUZKTEVOQlFVTXNRMEZCUXl4SlFVRkpMRWxCUVVrc1EwRkJReXhEUVVGRExFbEJRVWtzUzBGQlN5eERRVUZETEVOQlFVTXNTVUZCU1N4SlFVRkpMRU5CUVVNc1EwRkJReXhKUVVGSkxFTkJRVU1zU1VGQlNUdHZRa0ZCUlN4VFFVRlRPMmRDUVVONlJDeExRVUZKTEVOQlFVTXNTMEZCU3l4RFFVRkRMRWxCUVVrc1EwRkJReXhGUVVGRkxFMUJRVTBzUlVGQlJTeERRVUZETEVOQlFVTXNSVUZCUlN4RlFVRkZMRTFCUVUwc1JVRkJSU3hEUVVGRExFTkJRVU1zUlVGQlJTeEZRVUZGTEUxQlFVMHNSVUZCUlN4SlFVRkpMRU5CUVVNc1IwRkJSeXhEUVVGRExFdEJRVXNzUTBGQlF5eERRVUZETEVWQlFVVXNRMEZCUXl4RFFVRkRMRU5CUVVNc1JVRkJSU3hEUVVGRExFTkJRVU03WVVGRGJFWTdVVUZEVEN4RFFVRkRMRU5CUVVNc1EwRkJRenRKUVVsUUxFTkJRVU03U1VFMVNrOHNkMEpCUVVjc1IwRkJXQ3hWUVVGWkxFTkJRVU1zU1VGQlNTeFBRVUZQTEVOQlFVTXNRMEZCUXl4TlFVRk5MRU5CUVVNc1ZVRkJReXhEUVVGRExFVkJRVVVzUTBGQlF5eEpRVUZMTEU5QlFVRXNRMEZCUXl4SFFVRkhMRU5CUVVNc1JVRkJUQ3hEUVVGTExFTkJRVU1zUjBGQlJ5eERRVUZETEVOQlFVTXNUVUZCVFN4RFFVRkJMRU5CUVVNc1EwRkJRenRKUVVsMFJDeHBRMEZCV1N4SFFVRndRaXhWUVVGeFFpeEpRVUZKTzFGQlEzSkNMRWxCUVVrc1QwRkJUeXhIUVVGSExFVkJRVVVzUTBGQlF6dFJRVU5xUWl4SlFVRkpMRVZCUVVVc1IwRkJSeXhKUVVGSkxFTkJRVU1zVFVGQlRTeERRVUZETEV0QlFVc3NRMEZCUXl4RFFVRkRMRVZCUVVVc1NVRkJTU3hEUVVGRExFMUJRVTBzUTBGQlF5eE5RVUZOTEVOQlFVTXNRMEZCUXp0UlFVTnNSQ3hQUVVGUExFVkJRVVVzUTBGQlF5eE5RVUZOTEVkQlFVY3NRMEZCUXl4RlFVRkZPMWxCUld4Q0xFbEJRVWtzVjBGQlZ5eEhRVUZITEVWQlFVVXNRMEZCUXl4TlFVRk5MRU5CUVVNc1ZVRkJRU3hEUVVGRExFbEJRVWNzVDBGQlFTeERRVUZETEVOQlFVTXNTVUZCU1N4RFFVRkRMRk5CUVZNc1IwRkJSeXhKUVVGSkxFTkJRVU1zVjBGQlZ5eEZRVUZGTEVOQlFVTXNRMEZCUXl4RlFVRkZMRU5CUVVNc1EwRkJReXhEUVVGRExFTkJRVU1zU1VGQlNTeERRVUZETEVWQlFXeEVMRU5CUVd0RUxFTkJRVU1zUTBGQlF6dFpRVU53Uml4SlFVRkpMRWRCUVVjc1IwRkJSenRuUWtGRFRpeExRVUZMTEVWQlFVVXNWMEZCVnp0blFrRkRiRUlzUjBGQlJ5eEZRVUZGTEVsQlFVa3NRMEZCUXl4SFFVRkhMRU5CUVVNc1YwRkJWeXhEUVVGRExFZEJRVWNzUTBGQlF5eFZRVUZCTEVOQlFVTXNTVUZCUnl4UFFVRkJMRU5CUVVNc1EwRkJReXhKUVVGSkxFTkJRVU1zUjBGQlJ5eEhRVUZITEVsQlFVa3NRMEZCUXl4RlFVRkZMRVZCUVhCQ0xFTkJRVzlDTEVOQlFVTXNRMEZCUXp0aFFVTXpSQ3hEUVVGRE8xbEJRMFlzVDBGQlR5eERRVUZETEVsQlFVa3NRMEZCUXl4SFFVRkhMRU5CUVVNc1EwRkJRenRaUVVOc1FpeEhRVUZITEVOQlFVTXNTMEZCU3l4RFFVRkRMRTlCUVU4c1EwRkJReXhWUVVGQkxFTkJRVU1zU1VGQlJ5eFBRVUZCTEVWQlFVVXNRMEZCUXl4TlFVRk5MRU5CUVVNc1JVRkJSU3hEUVVGRExFOUJRVThzUTBGQlF5eERRVUZETEVOQlFVTXNSVUZCUlN4RFFVRkRMRU5CUVVNc1JVRkJNMElzUTBGQk1rSXNRMEZCUXl4RFFVRkRPMU5CUTNSRU8xRkJRMFFzVDBGQlR5eERRVUZETEVsQlFVa3NRMEZCUXl4VlFVRkRMRU5CUVVNc1JVRkJSU3hEUVVGRExFbEJRVXNzVDBGQlFTeERRVUZETEVOQlFVTXNSMEZCUnl4SFFVRkhMRU5CUVVNc1EwRkJReXhIUVVGSExFVkJRV0lzUTBGQllTeERRVUZETEVOQlFVRTdVVUZEY2tNc1QwRkJUeXhQUVVGUExFTkJRVU03U1VGRGJrSXNRMEZCUXp0SlFVZFBMRFpDUVVGUkxFZEJRV2hDTEZWQlFXbENMRU5CUVVNN1VVRkRaQ3hKUVVGSkxFdEJRVXNzUjBGQlJ5eERRVUZETEVOQlFVTTdVVUZEWkN4UFFVRlBMRU5CUVVNc1EwRkJReXhOUVVGTkxFdEJRVXNzU1VGQlNTeERRVUZETEVsQlFVa3NSVUZCUlR0WlFVTXpRaXhMUVVGTExFVkJRVVVzUTBGQlF6dFpRVU5TTEVOQlFVTXNSMEZCUnl4RFFVRkRMRU5CUVVNc1RVRkJUU3hEUVVGRE8xTkJRMmhDTzFGQlEwUXNUMEZCVHl4TFFVRkxMRU5CUVVNN1NVRkRha0lzUTBGQlF6dEpRVWRQTERoQ1FVRlRMRWRCUVdwQ0xGVkJRV3RDTEVOQlFVTTdVVUZEWml4SlFVRkpMRWRCUVVjc1IwRkJSeXhEUVVGRExFTkJRVU1zUTBGQlF5eERRVUZETEVkQlFVY3NRMEZCUXl4RFFVRkRMRU5CUVVNc1EwRkJReXhEUVVGRE8xRkJRM1JDTEVsQlFVa3NTVUZCU1N4SFFVRkhMRU5CUVVNc1EwRkJReXhEUVVGRExFTkJRVU1zUTBGQlF5eEhRVUZITEVkQlFVY3NSMEZCUnl4RFFVRkRMRU5CUVVNc1EwRkJRenRSUVVNMVFpeExRVUZMTEVsQlFVa3NRMEZCUXl4SFFVRkhMRU5CUVVNc1JVRkJSU3hEUVVGRExFZEJRVWNzUTBGQlF5eERRVUZETEUxQlFVMHNSVUZCUlN4RFFVRkRMRVZCUVVVc1JVRkJSVHRaUVVNdlFpeEpRVUZKTEVOQlFVTXNTVUZCU1N4RFFVRkRMRU5CUVVNc1EwRkJReXhEUVVGRExFTkJRVU1zUTBGQlF5eEhRVUZITEVOQlFVTXNRMEZCUXl4RFFVRkRMRWRCUVVjc1EwRkJReXhEUVVGRExFTkJRVU1zUjBGQlJ5eERRVUZETEVOQlFVTXNRMEZCUXp0VFFVTndRenRSUVVORUxFbEJRVWtzUTBGQlF5eEpRVUZKTEVOQlFVTXNRMEZCUXl4RFFVRkRMRU5CUVVNc1EwRkJReXhOUVVGTkxFZEJRVWNzUTBGQlF5eERRVUZETEVkQlFVY3NSMEZCUnl4SFFVRkhMRU5CUVVNc1EwRkJReXhEUVVGRE8xRkJRM0pETEU5QlFVOHNTVUZCU1N4RFFVRkRPMGxCUTJoQ0xFTkJRVU03U1VGMVNFOHNaME5CUVZjc1IwRkJia0lzVlVGQmIwSXNRMEZCUXp0UlFVTnFRaXhKUVVGSkxFOUJRVThzUjBGQlJ5eERRVUZETEVOQlFVTXNRMEZCUXl4RFFVRkRPMUZCUTJ4Q0xFZEJRVWM3V1VGRFF5eERRVUZETEVkQlFVY3NRMEZCUXl4RFFVRkRMRTFCUVUwc1EwRkJRenRaUVVOaUxFOUJRVThzUTBGQlF5eEpRVUZKTEVOQlFVTXNRMEZCUXl4RFFVRkRMRU5CUVVNN1UwRkRia0lzVVVGQlVTeERRVUZETEV0QlFVc3NTVUZCU1N4RFFVRkRMRWxCUVVrc1JVRkJSVHRSUVVNeFFpeFBRVUZQTEU5QlFVOHNRMEZCUXl4UFFVRlBMRVZCUVVVc1EwRkJRenRKUVVNM1FpeERRVUZETzBsQlIwOHNORU5CUVhWQ0xFZEJRUzlDTEZWQlFXZERMRU5CUVVNc1JVRkJSU3hEUVVGRE8xRkJRMmhETEVsQlFVa3NSVUZCUlN4SFFVRkhMRWxCUVVrc1EwRkJReXhYUVVGWExFTkJRVU1zUTBGQlF5eERRVUZETEVWQlFVVXNSVUZCUlN4SFFVRkhMRWxCUVVrc1EwRkJReXhYUVVGWExFTkJRVU1zUTBGQlF5eERRVUZETEVWQlFVVXNRMEZCUXl4SFFVRkhMRU5CUVVNc1EwRkJRenRSUVVNNVJDeFBRVUZQTEVWQlFVVXNRMEZCUXl4RFFVRkRMRU5CUVVNc1MwRkJTeXhGUVVGRkxFTkJRVU1zUTBGQlF5eERRVUZETzFsQlFVVXNRMEZCUXl4RlFVRkZMRU5CUVVNN1VVRkZOVUlzVDBGQlR5eEZRVUZGTEdOQlFXTXNSVUZCUlN4RlFVRkZMRU5CUVVNc1EwRkJReXhIUVVGSExFTkJRVU1zUTBGQlF5eEZRVUZGTEZGQlFWRXNSVUZCUlN4RlFVRkZMRU5CUVVNc1MwRkJTeXhEUVVGRExFTkJRVU1zUTBGQlF5eERRVUZETEUxQlFVMHNRMEZCUXl4RlFVRkZMRU5CUVVNc1MwRkJTeXhEUVVGRExFTkJRVU1zUTBGQlF5eERRVUZETEVWQlFVVXNRMEZCUXp0SlFVTndSaXhEUVVGRE8wbEJTVVFzY1VOQlFXZENMRWRCUVdoQ0xGVkJRV2xDTEVOQlFVTXNSVUZCUlN4RFFVRkRPMUZCUVhKQ0xHbENRVmRETzFGQlZrY3NTVUZCU1N4SlFVRkpMRWRCUVVjc1NVRkJTU3hEUVVGRExIVkNRVUYxUWl4RFFVRkRMRU5CUVVNc1JVRkJSU3hEUVVGRExFTkJRVU1zUTBGQlF6dFJRVU01UXl4SlFVRkpMR0ZCUVdFc1IwRkJSeXhGUVVGRkxFTkJRVU03VVVGRGRrSXNTVUZCU1N4RFFVRkRMRkZCUVZFc1EwRkJReXhQUVVGUExFTkJRVU1zVlVGQlFTeERRVUZETEVsQlFVY3NUMEZCUVN4aFFVRmhMRU5CUVVNc1EwRkJReXhEUVVGRExFVkJRVVVzUTBGQlF5eEhRVUZITEVWQlFVVXNSVUZCZUVJc1EwRkJkMElzUTBGQlF5eERRVUZETzFGQlEzQkVMRWxCUVVrc1UwRkJVeXhIUVVGSExFbEJRVWtzUTBGQlF5eGpRVUZqTEVOQlFVTXNVVUZCVVN4RFFVRkRMRTFCUVUwc1EwRkJReXhWUVVGQkxFTkJRVU1zU1VGQlJ5eFBRVUZCTEVOQlFVTXNRMEZCUXl4RFFVRkRMRWxCUVVrc1lVRkJZU3hEUVVGRExFVkJRWEpDTEVOQlFYRkNMRU5CUVVNc1EwRkJRenRSUVVVdlJTeEpRVUZKTEVOQlFVTXNVVUZCVVR0aFFVTlNMRTFCUVUwc1EwRkJReXhWUVVGQkxFTkJRVU1zU1VGQlJ5eFBRVUZCTEVOQlFVTXNRMEZCUXl4TlFVRk5MRXRCUVVzc1NVRkJTU3hEUVVGRExHTkJRV01zUlVGQmFFTXNRMEZCWjBNc1EwRkJRenRoUVVNMVF5eFBRVUZQTEVOQlFVTXNWVUZCUVN4RFFVRkRMRWxCUVVjc1QwRkJRU3hUUVVGVExFZEJRVWNzVTBGQlV5eERRVUZETEUxQlFVMHNRMEZCUXl4RFFVRkRMRU5CUVVNc1RVRkJUU3hEUVVGRExGRkJRVkVzUTBGQlF5eE5RVUZOTEVOQlFVTXNWVUZCUVN4RFFVRkRMRWxCUVVjc1QwRkJRU3hEUVVGRExFdEJRVXNzUTBGQlF5eERRVUZETEVWQlFVVXNSVUZCVml4RFFVRlZMRU5CUVVNc1EwRkJReXhGUVVGMFJTeERRVUZ6UlN4RFFVRkRMRU5CUVVNN1VVRkZla1lzVDBGQlR5eFRRVUZUTEVOQlFVTXNSMEZCUnl4RFFVRkRMRlZCUVVFc1EwRkJReXhKUVVGSExFOUJRVUVzUzBGQlNTeERRVUZETEV0QlFVc3NRMEZCUXl4RFFVRkRMRU5CUVVNc1JVRkJZaXhEUVVGaExFTkJRVU1zUTBGQlF6dEpRVU0xUXl4RFFVRkRPMGxCU1Uwc2VVSkJRV01zUjBGQmNrSXNWVUZCYzBJc1RVRkJUU3hGUVVGRkxFTkJRVU1zUlVGQlJTeERRVUZETzFGQlJUbENMRWxCUVVrc1UwRkJVeXhIUVVGSExFVkJRVVVzUTBGQlF6dFJRVU51UWl4TFFVRkxMRWxCUVVrc1JVRkJSU3hIUVVGSExFTkJRVU1zUlVGQlJTeEZRVUZGTEVkQlFVY3NUVUZCVFN4RFFVRkRMRTFCUVUwc1JVRkJSU3hGUVVGRkxFVkJRVVVzUlVGQlJUdFpRVU4yUXl4SlFVRkpMRXRCUVVzc1IwRkJSeXhOUVVGTkxFTkJRVU1zUlVGQlJTeERRVUZETEVOQlFVTTdXVUZEZGtJc1MwRkJTeXhKUVVGSkxFVkJRVVVzUjBGQlJ5eERRVUZETEVWQlFVVXNSVUZCUlN4SFFVRkhMRXRCUVVzc1EwRkJReXhOUVVGTkxFVkJRVVVzUlVGQlJTeEZRVUZGTEVWQlFVVTdaMEpCUTNSRExFbEJRVWtzUTBGQlF5eEhRVUZSTEV0QlFVc3NRMEZCUXl4RlFVRkZMRU5CUVVNc1EwRkJRenRuUWtGRGRrSXNRMEZCUXl4RFFVRkRMRTFCUVUwc1IwRkJSeXhGUVVGRkxFTkJRVU03WjBKQlEyUXNRMEZCUXl4RFFVRkRMRU5CUVVNc1IwRkJSeXhGUVVGRkxFTkJRVU03WjBKQlExUXNTVUZCU1N4SFFVRkhMRWRCUVVjc1EwRkJReXhEUVVGRExFTkJRVU1zUTBGQlF5eERRVUZETEVOQlFVTXNRMEZCUXl4SFFVRkhMRU5CUVVNc1EwRkJReXhEUVVGRExFTkJRVU1zUTBGQlF5eERRVUZETEVOQlFVTXNRMEZCUXp0blFrRkROVUlzU1VGQlNTeEpRVUZKTEVOQlFVTXNSMEZCUnl4RFFVRkRMRWRCUVVjc1EwRkJReXhIUVVGSExFZEJRVWNzUlVGQlJUdHZRa0ZEY2tJc1UwRkJVeXhEUVVGRExFbEJRVWtzUTBGQlF5eERRVUZETEVOQlFVTXNRMEZCUXp0cFFrRkRja0k3WVVGRFNqdFRRVU5LTzFGQlEwUXNVMEZCVXl4RFFVRkRMRWxCUVVrc1EwRkJReXhWUVVGRExFTkJRVU1zUlVGQlJTeERRVUZETEVsQlFVc3NUMEZCUVN4RFFVRkRMRU5CUVVNc1EwRkJReXhEUVVGRExFTkJRVU1zUTBGQlF5eERRVUZETEVkQlFVY3NRMEZCUXl4RFFVRkRMRU5CUVVNc1EwRkJReXhEUVVGRExFTkJRVU1zUTBGQlF5eEZRVUZxUWl4RFFVRnBRaXhEUVVGRExFTkJRVU03VVVGSE5VTXNTVUZCU1N4WlFVRlpMRWRCUVVjc1JVRkJSU3hEUVVGRE8xRkJRM1JDTEVsQlFVa3NWVUZCVlN4SFFVRkhMRWxCUVVrc1EwRkJRenRSUVVOMFFpeExRVUZMTEVsQlFVa3NRMEZCUXl4SFFVRkhMRU5CUVVNc1JVRkJSU3hEUVVGRExFZEJRVWNzVTBGQlV5eERRVUZETEUxQlFVMHNSVUZCUlN4RFFVRkRMRVZCUVVVc1JVRkJSVHRaUVVOMlF5eEpRVUZKTEVOQlFVTXNSMEZCUnl4VFFVRlRMRU5CUVVNc1EwRkJReXhEUVVGRExFTkJRVU03V1VGRGNrSXNTVUZCU1N4RFFVRkRMRlZCUVZVc1NVRkJTU3hKUVVGSkxFTkJRVU1zUjBGQlJ5eERRVUZETEVOQlFVTXNRMEZCUXl4RFFVRkRMRU5CUVVNc1EwRkJReXhEUVVGRExFTkJRVU1zUjBGQlJ5eFZRVUZWTEVOQlFVTXNSMEZCUnl4RFFVRkRMRWRCUVVjc1IwRkJSeXhGUVVGRk8yZENRVU42UkN4VlFVRlZMRWRCUVVjc1JVRkJSU3hIUVVGSExFVkJRVVVzUTBGQlF5eERRVUZETEVOQlFVTXNRMEZCUXl4RFFVRkRMRU5CUVVNc1EwRkJReXhGUVVGRkxGRkJRVkVzUlVGQlJTeEZRVUZGTEVWQlFVVXNRMEZCUXp0blFrRkROVU1zV1VGQldTeERRVUZETEVsQlFVa3NRMEZCUXl4VlFVRlZMRU5CUVVNc1EwRkJRenRoUVVOcVF6dFpRVU5FTEZWQlFWVXNRMEZCUXl4UlFVRlJMRU5CUVVNc1NVRkJTU3hEUVVGRExFTkJRVU1zUTBGQlF5eERRVUZETzFOQlF5OUNPMUZCUTBRc1QwRkJUeXhaUVVGWkxFTkJRVU03U1VGRGVFSXNRMEZCUXp0SlFWTk5MRzlDUVVGVExFZEJRV2hDTEZWQlFXbENMRU5CUVZNc1JVRkJSU3hEUVVGVExFVkJRVVVzVFVGQlRTeEZRVUZGTEZGQlFWRXNSVUZCUlN4TlFVRk5MRVZCUVVVc1IwRkJWenRSUVVONFJTeEpRVUZKTEVOQlFVTXNSMEZCUnl4UlFVRlJMRU5CUVVNc1RVRkJUU3hEUVVGRE8xRkJRM2hDTEVsQlFVa3NRMEZCUXl4SlFVRkpMRU5CUVVNN1dVRkJSU3hQUVVGUE8xRkJRMjVDTEVsQlFVa3NSVUZCUlN4SFFVRkhMRkZCUVZFc1EwRkJReXhIUVVGSExFTkJRVU1zVlVGQlFTeERRVUZETEVsQlFVa3NUMEZCUVN4SlFVRkpMR1ZCUVZFc1EwRkJReXhEUVVGRExFTkJRVU1zUTBGQlF5eERRVUZETEVOQlFVTXNRMEZCUXl4RFFVRkRMRU5CUVVNc1JVRkJja0lzUTBGQmNVSXNRMEZCUXl4RFFVRkRPMUZCUTJ4RUxFbEJRVWtzUlVGQlJTeEhRVUZITEVWQlFVVXNRMEZCUXp0UlFVTmFMRXRCUVVzc1NVRkJTU3hEUVVGRExFZEJRVWNzUTBGQlF5eEZRVUZGTEVOQlFVTXNSMEZCUnl4RFFVRkRMRVZCUVVVc1EwRkJReXhGUVVGRkxFVkJRVVU3V1VGRGVFSXNTMEZCU3l4SlFVRkpMRU5CUVVNc1IwRkJSeXhEUVVGRExFVkJRVVVzUTBGQlF5eEhRVUZITEVOQlFVTXNSVUZCUlN4RFFVRkRMRVZCUVVVc1JVRkJSVHRuUWtGRGVFSXNTVUZCU1N4RFFVRkRMRXRCUVVzc1EwRkJRenR2UWtGQlJTeFRRVUZUTzJkQ1FVTjBRaXhKUVVGSkxFVkJRVVVzUjBGQlJ5eFJRVUZSTEVOQlFVTXNRMEZCUXl4RFFVRkRMRVZCUTJoQ0xFVkJRVVVzUjBGQlJ5eFJRVUZSTEVOQlFVTXNRMEZCUXl4RFFVRkRMRVZCUTJoQ0xFVkJRVVVzUjBGQlJ5eEZRVUZGTEVOQlFVTXNUVUZCVFN4RlFVTmtMRVZCUVVVc1IwRkJSeXhGUVVGRkxFTkJRVU1zVFVGQlRTeEZRVU5rTEVsQlFVa3NSMEZCUnl4RFFVRkRMRU5CUVVNc1JVRkRWQ3hKUVVGSkxFZEJRVWNzUTBGQlF5eERRVUZETEVOQlFVTTdaMEpCVFdRc1NVRkJTU3hEUVVGRExFbEJRVWtzUjBGQlJ5eEZRVUZGTzI5Q1FVTldMRWxCUVVrc1RVRkJUU3hEUVVGRExFVkJRVVVzUlVGQlJTeEZRVUZGTEVOQlFVTXNSVUZCUlR0M1FrRkZhRUlzU1VGQlNTeEZRVUZGTEVOQlFVTXNRMEZCUXl4RFFVRkRMRU5CUVVNc1EwRkJReXhEUVVGRExFZEJRVWNzUlVGQlJTeERRVUZETEVOQlFVTXNRMEZCUXl4RFFVRkRMRU5CUVVNc1EwRkJReXhGUVVGRk96UkNRVU55UWl4SlFVRkpMRWRCUVVjc1EwRkJReXhGUVVGRkxFbEJRVWtzUjBGQlJ5eERRVUZETEVOQlFVTTdlVUpCUTNSQ096WkNRVUZOT3pSQ1FVTklMRWxCUVVrc1IwRkJSeXhEUVVGRExFVkJRVVVzU1VGQlNTeEhRVUZITEVOQlFVTXNRMEZCUXp0NVFrRkRkRUk3Y1VKQlEwbzdhVUpCUTBvN2NVSkJRVTA3YjBKQlEwZ3NTVUZCU1N4TlFVRk5MRU5CUVVNc1JVRkJSU3hGUVVGRkxFVkJRVVVzUTBGQlF5eEZRVUZGTzNkQ1FVTm9RaXhKUVVGSkxFVkJRVVVzUTBGQlF5eERRVUZETEVOQlFVTXNRMEZCUXl4RFFVRkRMRU5CUVVNc1IwRkJSeXhGUVVGRkxFTkJRVU1zUTBGQlF5eERRVUZETEVOQlFVTXNRMEZCUXl4RFFVRkRMRVZCUVVVN05FSkJRM0pDTEVsQlFVa3NSMEZCUnl4RFFVRkRMRVZCUVVVc1NVRkJTU3hIUVVGSExFTkJRVU1zUTBGQlF6dDVRa0ZEZEVJN05rSkJRVTA3TkVKQlEwZ3NTVUZCU1N4SFFVRkhMRU5CUVVNc1JVRkJSU3hKUVVGSkxFZEJRVWNzUTBGQlF5eERRVUZETzNsQ1FVTjBRanR4UWtGRFNqdHBRa0ZEU2p0blFrRkRSQ3hKUVVGSkxFbEJRVWtzU1VGQlNTeERRVUZETEVWQlFVVTdiMEpCUlZnc1JVRkJSU3hEUVVGRExFbEJRVWtzUTBGQlF5eEpRVUZKTEdsQ1FVRlZMRU5CUVVNc1JVRkJSU3hEUVVGRExFbEJRVWtzUTBGQlF5eEZRVUZGTEVWQlFVVXNRMEZCUXl4SlFVRkpMRU5CUVVNc1JVRkJSU3hIUVVGSExFTkJRVU1zUTBGQlF5eERRVUZETzJsQ1FVTndSRHRoUVVOS08xTkJRMG83VVVGRFJDeEpRVUZKTEUxQlFVMHNSMEZCUnl4SlFVRkpMR0ZCUVUwc1EwRkJReXhGUVVGRkxFVkJRVVVzUlVGQlJTeERRVUZETEVOQlFVTTdVVUZEYUVNc1RVRkJUU3hEUVVGRExFdEJRVXNzUlVGQlJTeERRVUZETzFGQlEyWXNSVUZCUlN4RFFVRkRMRTlCUVU4c1EwRkJReXhWUVVGRExFTkJRVU1zUlVGQlJTeERRVUZETzFsQlExb3NTVUZCU1N4RFFVRkRMRWRCUVVjc1VVRkJVU3hEUVVGRExFTkJRVU1zUTBGQlF5eERRVUZETzFsQlEzQkNMRWxCUVVrc1IwRkJSeXhIUVVGSExFTkJRVU1zUTBGQlF5eFJRVUZSTEVWQlFVVXNRMEZCUXp0WlFVTjJRaXhEUVVGRExFTkJRVU1zUTBGQlF5eERRVUZETEVOQlFVTXNRMEZCUXl4RFFVRkRMRWRCUVVjc1EwRkJReXhEUVVGRExFTkJRVU1zUTBGQlF5eERRVUZETEVOQlFVTXNRMEZCUXl4SFFVRkhMRWRCUVVjc1EwRkJRenRaUVVONFFpeEpRVUZKTEV0QlFVc3NSMEZCUnl4TlFVRk5MRU5CUVVNc1EwRkJReXhEUVVGRExFMUJRVTBzUTBGQlF5eERRVUZETzFsQlF6ZENMRWxCUVVrc1EwRkJReXhEUVVGRExFTkJRVU1zUjBGQlJ5eERRVUZETzJkQ1FVRkZMRXRCUVVzc1EwRkJReXhEUVVGRExFTkJRVU1zUTBGQlF5eEhRVUZITEVOQlFVTXNRMEZCUXl4RFFVRkRMRU5CUVVNc1EwRkJReXhEUVVGRExFTkJRVU1zUTBGQlF5eEhRVUZITEVkQlFVY3NRMEZCUXp0WlFVTjRReXhKUVVGSkxFTkJRVU1zUTBGQlF5eERRVUZETEVkQlFVY3NTMEZCU3l4RFFVRkRMRTFCUVUwc1IwRkJSeXhEUVVGRE8yZENRVUZGTEV0QlFVc3NRMEZCUXl4RFFVRkRMRU5CUVVNc1EwRkJReXhIUVVGSExFTkJRVU1zUTBGQlF5eERRVUZETEVOQlFVTXNRMEZCUXl4RFFVRkRMRU5CUVVNc1EwRkJReXhIUVVGSExFZEJRVWNzUTBGQlF6dFJRVU16UkN4RFFVRkRMRU5CUVVNc1EwRkJRenRKUVVOUUxFTkJRVU03U1VGRlRTeDNRa0ZCWVN4SFFVRndRaXhWUVVGeFFpeE5RVUZOTEVWQlFVVXNRMEZCVXl4RlFVRkZMRU5CUVZNc1JVRkJSU3hOUVVFeVF5eEZRVUZGTEVkQlFWYzdVVUZEZGtjc1NVRkJTU3haUVVGWkxFZEJRVWNzVlVGQlZTeERRVUZETEdOQlFXTXNRMEZCUXl4TlFVRk5MRVZCUVVVc1EwRkJReXhGUVVGRkxFTkJRVU1zUTBGQlF5eERRVUZETzFGQlJUTkVMRXRCUVVzc1NVRkJTU3hEUVVGRExFZEJRVWNzUTBGQlF5eEZRVUZGTEVOQlFVTXNSMEZCUnl4WlFVRlpMRU5CUVVNc1RVRkJUU3hGUVVGRkxFTkJRVU1zUlVGQlJTeEZRVUZGTzFsQlF6RkRMRWxCUVVrc1JVRkJSU3hIUVVGSExGbEJRVmtzUTBGQlF5eERRVUZETEVOQlFVTXNRMEZCUXp0WlFVTjZRaXhKUVVGSkxFMUJRVTBzUjBGQlJ5eEZRVUZGTEVOQlFVTTdXVUZEYUVJc1MwRkJTeXhKUVVGSkxFTkJRVU1zUjBGQlJ5eERRVUZETEVWQlFVVXNRMEZCUXl4SFFVRkhMRVZCUVVVc1EwRkJReXhSUVVGUkxFTkJRVU1zVFVGQlRTeEZRVUZGTEVOQlFVTXNSVUZCUlN4RlFVRkZPMmRDUVVONlF5eEpRVUZKTEVOQlFVTXNSMEZCUnl4RlFVRkZMRU5CUVVNc1VVRkJVU3hEUVVGRExFTkJRVU1zUTBGQlF5eERRVUZETzJkQ1FVTjJRaXhOUVVGTkxFTkJRVU1zU1VGQlNTeERRVUZETEVWQlFVVXNTVUZCU1N4RlFVRkZMRU5CUVVNc1JVRkJSU3hEUVVGRExFVkJRVVVzUTBGQlF5eEZRVUZGTEVkQlFVY3NSVUZCUlN4SlFVRkpMRU5CUVVNc1IwRkJSeXhEUVVGRExFTkJRVU1zUTBGQlF5eERRVUZETEVOQlFVTXNRMEZCUXl4RFFVRkRMRU5CUVVNc1JVRkJSU3hEUVVGRExFTkJRVU1zUTBGQlF5eERRVUZETEVOQlFVTXNRMEZCUXl4RFFVRkRMRU5CUVVNc1JVRkJSU3hEUVVGRExFTkJRVU03WjBKQlEyaEZMRTFCUVUwc1EwRkJReXhKUVVGSkxFTkJRVU1zUlVGQlJTeEpRVUZKTEVWQlFVVXNRMEZCUXl4RlFVRkZMRU5CUVVNc1JVRkJSU3hEUVVGRExFVkJRVVVzUjBGQlJ5eEZRVUZGTEVsQlFVa3NRMEZCUXl4SFFVRkhMRU5CUVVNc1EwRkJReXhEUVVGRExFTkJRVU1zUTBGQlF5eERRVUZETEVOQlFVTXNRMEZCUXl4RlFVRkZMRU5CUVVNc1EwRkJReXhEUVVGRExFTkJRVU1zUTBGQlF5eERRVUZETEVOQlFVTXNRMEZCUXl4RlFVRkZMRU5CUVVNc1EwRkJRenRoUVVOdVJUdFpRVU5FTEUxQlFVMHNRMEZCUXl4SlFVRkpMRU5CUVVNc1ZVRkJReXhEUVVGRExFVkJRVVVzUTBGQlF5eEpRVUZMTEU5QlFVRXNRMEZCUXl4RFFVRkRMRWRCUVVjc1IwRkJSeXhEUVVGRExFTkJRVU1zUjBGQlJ5eEhRVUZITEVOQlFVTXNRMEZCUXl4SlFVRkpMRWRCUVVjc1EwRkJReXhEUVVGRExFbEJRVWtzUlVGQkwwSXNRMEZCSzBJc1EwRkJReXhEUVVGRE8xbEJRM1pFTEVsQlFVa3NTVUZCU1N4SFFVRkhMRVZCUVVVc1EwRkJRenRaUVVOa0xFbEJRVWtzVTBGQlV5eEhRVUZITEVOQlFVTXNRMEZCUXp0WlFVTnNRaXhOUVVGTkxFTkJRVU1zVDBGQlR5eERRVUZETEZWQlFVRXNRMEZCUXp0blFrRkRXaXhKUVVGSkxFTkJRVU1zUTBGQlF5eEpRVUZKTEV0QlFVc3NRMEZCUXl4RlFVRkZPMjlDUVVOa0xFbEJRVWtzUTBGQlF5eEpRVUZKTEVOQlFVTXNRMEZCUXl4RFFVRkRMRU5CUVVNc1EwRkJReXhEUVVGRE8yOUNRVU5tTEZOQlFWTXNSVUZCUlN4RFFVRkRPMmxDUVVObU8zRkNRVUZOTzI5Q1FVTklMRk5CUVZNc1JVRkJSU3hEUVVGRE8ybENRVU5tTzJkQ1FVTkVMRWxCUVVrc1UwRkJVeXhKUVVGSkxFTkJRVU1zUlVGQlJUdHZRa0ZEYUVJc1ZVRkJWU3hEUVVGRExGTkJRVk1zUTBGQlF5eERRVUZETEVWQlFVVXNRMEZCUXl4RlFVRkZMRTFCUVUwc1JVRkJSU3hKUVVGSkxFVkJRVVVzVFVGQlRTeEZRVUZGTEVkQlFVY3NRMEZCUXl4RFFVRkRPMjlDUVVOMFJDeEpRVUZKTEVkQlFVY3NSVUZCUlN4RFFVRkRPMmxDUVVOaU8xbEJRMHdzUTBGQlF5eERRVUZETEVOQlFVTTdVMEZEVGp0SlFVTk1MRU5CUVVNN1NVRlRSQ3dyUWtGQlZTeEhRVUZXTEZWQlFXbENMRXRCUVdFc1JVRkJSU3hSUVVGblFpeEZRVUZGTEUxQlFUSkNMRVZCUVVVc1RVRkJNa0k3VVVGQk1VY3NhVUpCVVVNN1VVRlFSeXhKUVVGSkxGVkJRVlVzUjBGQlJ5eExRVUZMTEVOQlFVTXNSMEZCUnl4RFFVRkRMRlZCUVVFc1EwRkJReXhKUVVGSExFOUJRVUVzUzBGQlNTeERRVUZETEV0QlFVc3NRMEZCUXl4TlFVRk5MRU5CUVVNc1EwRkJReXhEUVVGRExFVkJRVVVzVFVGQlRTeERRVUZETEVOQlFVTXNRMEZCUXl4RFFVRkRMRVZCUVdoRExFTkJRV2RETEVOQlFVTXNRMEZCUXp0UlFVTnFSU3hKUVVGSkxFdEJRVXNzUjBGQlJ5eFZRVUZWTEVOQlFVTXNWVUZCVlN4RFFVRkRMRlZCUVZVc1EwRkJReXhEUVVGRE8xRkJRemxETEVsQlFVa3NUVUZCVFN4SFFVRkhMRlZCUVZVc1EwRkJReXhIUVVGSExFTkJRVU1zVlVGQlZTeERRVUZETEVsQlFVa3NUMEZCVHl4VlFVRlZMRU5CUVVNc1dVRkJXU3hEUVVGRExFTkJRVU1zUTBGQlF5eERRVUZETEVOQlFVTXNRMEZCUXl4RFFVRkRMRU5CUVVNN1VVRkRha1lzVlVGQlZTeERRVUZETEdGQlFXRXNRMEZCUXl4TlFVRk5MRVZCUVVVc1IwRkJSeXhGUVVGRkxFZEJRVWNzUlVGQlJTeExRVUZMTEVWQlFVVXNVVUZCVVN4RFFVRkRMRU5CUVVNN1VVRkROVVFzVlVGQlZTeERRVUZETEdGQlFXRXNRMEZCUXl4TlFVRk5MRVZCUVVVc1IwRkJSeXhGUVVGRkxFZEJRVWNzUlVGQlJTeExRVUZMTEVWQlFVVXNVVUZCVVN4RFFVRkRMRU5CUVVNN1VVRkROVVFzVlVGQlZTeERRVUZETEdOQlFXTXNRMEZCUXl4TlFVRk5MRVZCUVVVc1ZVRkJWU3hEUVVGRExFTkJRVU03VVVGRE9VTXNUMEZCVHl4TlFVRk5MRU5CUVVNN1NVRkRiRUlzUTBGQlF6dEpRVWxOTEhsQ1FVRmpMRWRCUVhKQ0xGVkJRWE5DTEUxQlFVMHNSVUZCUlN4VlFVRlZPMUZCUTNCRExFMUJRVTBzUTBGQlF5eFBRVUZQTEVOQlFVTXNWVUZCUXl4UlFVRlJMRVZCUVVVc1EwRkJRenRaUVVOMlFpeEpRVUZKTEVsQlFVa3NSMEZCUnl4VlFVRlZMRU5CUVVNc1EwRkJReXhEUVVGRExFTkJRVU03V1VGRGVrSXNTVUZCVlN4SlFVRkxMRU5CUVVNc1VVRkJVU3hGUVVGRk8yZENRVU4wUWl4UlFVRlJMRU5CUVVNc1QwRkJUeXhGUVVGRkxFTkJRVU03WjBKQlEyNUNMRkZCUVZFc1EwRkJReXhQUVVGUExFTkJRVU1zVlVGQlZTeFBRVUZQTzI5Q1FVTTVRaXhQUVVGUExFTkJRVU1zVDBGQlR5eEZRVUZGTEVOQlFVTTdaMEpCUTNSQ0xFTkJRVU1zUTBGQlF5eERRVUZETzJGQlEwNDdVVUZEVEN4RFFVRkRMRU5CUVVNc1EwRkJRenRKUVVOUUxFTkJRVU03U1VGRlRTdzJRa0ZCYTBJc1IwRkJla0lzVlVGQk1FSXNTMEZCWXl4RlFVRkZMRXRCUVdNN1VVRkRjRVFzU1VGQlNTeE5RVUZOTEVkQlFVY3NTVUZCU1N4RFFVRkRMRXRCUVVzc1EwRkJReXhMUVVGTExFTkJRVU1zUTBGQlF5eERRVUZETEVOQlFVTXNRMEZCUXl4SFFVRkhMRXRCUVVzc1EwRkJReXhEUVVGRExFTkJRVU1zUTBGQlF5eERRVUZETEVWQlF6TkRMRXRCUVVzc1EwRkJReXhEUVVGRExFTkJRVU1zUTBGQlF5eERRVUZETEVkQlFVY3NTMEZCU3l4RFFVRkRMRU5CUVVNc1EwRkJReXhEUVVGRExFTkJRVU1zUTBGQlF5eERRVUZETzFGQlF6ZENMRWxCUVVrc1RVRkJUU3hIUVVGSExFbEJRVWtzUTBGQlF5eExRVUZMTEVOQlFVTXNTMEZCU3l4RFFVRkRMRU5CUVVNc1EwRkJReXhEUVVGRExFTkJRVU1zUjBGQlJ5eExRVUZMTEVOQlFVTXNRMEZCUXl4RFFVRkRMRU5CUVVNc1EwRkJReXhGUVVNelF5eExRVUZMTEVOQlFVTXNRMEZCUXl4RFFVRkRMRU5CUVVNc1EwRkJReXhIUVVGSExFdEJRVXNzUTBGQlF5eERRVUZETEVOQlFVTXNRMEZCUXl4RFFVRkRMRU5CUVVNc1EwRkJRenRSUVVNM1FpeEpRVUZKTEVsQlFVa3NSMEZCUnl4TlFVRk5MRWRCUVVjc1RVRkJUU3hEUVVGRE8xRkJRek5DTEVsQlFVa3NTVUZCU1N4SFFVRkhMRWxCUVVrc1EwRkJReXhGUVVGRkxFbEJRVWtzU1VGQlNTeEhRVUZITEVOQlFVTXNTVUZCU1N4RFFVRkRMRVZCUVVVc1JVRkJSVHRaUVVOdVF5eEpRVUZKTEVkQlFVY3NUVUZCVFN4SFFVRkhMRTFCUVUwc1EwRkJRenRUUVVNeFFqdFJRVU5FTEU5QlFVOHNTVUZCU1N4RFFVRkRPMGxCUTJoQ0xFTkJRVU03U1VGSFl5eHBRa0ZCVFN4SFFVRnlRaXhWUVVGelFpeERRVUZETEVWQlFVVXNRMEZCUXl4RlFVRkZMRU5CUVVNN1VVRkRla0lzVDBGQlR5eERRVUZETEVOQlFVTXNRMEZCUXl4RFFVRkRMRU5CUVVNc1IwRkJSeXhEUVVGRExFTkJRVU1zUTBGQlF5eERRVUZETEVkQlFVY3NRMEZCUXl4RFFVRkRMRU5CUVVNc1EwRkJReXhIUVVGSExFTkJRVU1zUTBGQlF5eERRVUZETEVOQlFVTXNSMEZCUnl4RFFVRkRMRU5CUVVNc1EwRkJReXhEUVVGRExFZEJRVWNzUTBGQlF5eERRVUZETEVOQlFVTXNRMEZCUXl4SFFVRkhMRU5CUVVNc1EwRkJReXhEUVVGRExFTkJRVU1zUjBGQlJ5eERRVUZETEVOQlFVTXNRMEZCUXl4RFFVRkRMRU5CUVVNc1NVRkJTU3hEUVVGRExFTkJRVU03U1VGRGVFVXNRMEZCUXp0SlFVbGpMRzFDUVVGUkxFZEJRWFpDTEZWQlFYZENMRXRCUVdsRE8xRkJRM0pFTEVsQlFVa3NVVUZCVVN4SFFVRkhMRVZCUVVVc1EwRkJRenRSUVVOc1FpeExRVUZMTEVsQlFVa3NRMEZCUXl4SFFVRkhMRU5CUVVNc1JVRkJSU3hEUVVGRExFZEJRVWNzUzBGQlN5eERRVUZETEUxQlFVMHNSVUZCUlN4RFFVRkRMRVZCUVVVc1JVRkJSVHRaUVVOdVF5eEpRVUZKTEVOQlFVTXNSMEZCUnl4TFFVRkxMRU5CUVVNc1EwRkJReXhEUVVGRExFTkJRVU03V1VGRGFrSXNTVUZCU1N4UFFVRlBMRkZCUVZFc1EwRkJReXhEUVVGRExFTkJRVU1zUTBGQlF5eERRVUZETEV0QlFVc3NWMEZCVnp0blFrRkJSU3hSUVVGUkxFTkJRVU1zUTBGQlF5eERRVUZETEVOQlFVTXNRMEZCUXl4SFFVRkhMRVZCUVVVc1EwRkJRenRaUVVNM1JDeFJRVUZSTEVOQlFVTXNRMEZCUXl4RFFVRkRMRU5CUVVNc1EwRkJReXhEUVVGRExFTkJRVU1zUTBGQlF5eERRVUZETEVOQlFVTXNSMEZCUnl4SlFVRkpMRU5CUVVNN1UwRkROMEk3VVVGRFJDeFBRVUZQTEZWQlFVTXNRMEZCUXl4RlFVRkZMRU5CUVVNc1NVRkJTeXhQUVVGQkxFOUJRVThzVVVGQlVTeERRVUZETEVOQlFVTXNRMEZCUXl4TFFVRkxMRmRCUVZjc1NVRkJTU3hSUVVGUkxFTkJRVU1zUTBGQlF5eERRVUZETEVOQlFVTXNRMEZCUXl4RFFVRkRMRVZCUVhCRUxFTkJRVzlFTEVOQlFVTTdTVUZETVVVc1EwRkJRenRKUVVsTkxIRkNRVUZWTEVkQlFXcENMRlZCUVd0Q0xFdEJRVXM3VVVGRGJrSXNTVUZCU1N4VFFVRlRMRWRCUVVjc1JVRkJSU3hEUVVGRE8xRkJRMjVDTEV0QlFVc3NTVUZCU1N4RFFVRkRMRWRCUVVjc1EwRkJReXhGUVVGRkxFTkJRVU1zUjBGQlJ5eExRVUZMTEVOQlFVTXNUVUZCVFN4SFFVRkhMRU5CUVVNc1JVRkJSU3hEUVVGRExFVkJRVVVzUlVGQlJUdFpRVU4yUXl4TFFVRkxMRWxCUVVrc1EwRkJReXhIUVVGSExFTkJRVU1zUjBGQlJ5eERRVUZETEVWQlFVVXNRMEZCUXl4SFFVRkhMRXRCUVVzc1EwRkJReXhOUVVGTkxFVkJRVVVzUTBGQlF5eEZRVUZGTEVWQlFVVTdaMEpCUTNaRExFbEJRVWtzUTBGQlF5eEhRVUZITEV0QlFVc3NRMEZCUXl4RFFVRkRMRU5CUVVNc1JVRkRXaXhEUVVGRExFZEJRVWNzUzBGQlN5eERRVUZETEVOQlFVTXNRMEZCUXl4RlFVTmFMRWRCUVVjc1IwRkJSeXhKUVVGSkxIZENRVUYzUWl4RFFVRkRMRU5CUVVNc1JVRkJSU3hEUVVGRExFTkJRVU1zUTBGQlF6dG5Ra0ZETjBNc1NVRkJTU3hEUVVGRExFVkJRVVVzUlVGQlJTeEZRVUZGTEVWQlFVVXNRMEZCUXp0blFrRkRaQ3hKUVVGSkxFZEJRVWNzUTBGQlF5eE5RVUZOTEV0QlFVc3NRMEZCUXp0dlFrRkRhRUlzVTBGQlV6dG5Ra0ZEWWl4SlFVRkpMRWRCUVVjc1EwRkJReXhSUVVGUkxFVkJRVVU3YjBKQlIyUXNRMEZCUXl4RFFVRkRMRTlCUVU4c1JVRkJSU3hEUVVGRE8yOUNRVU5hTEVOQlFVTXNRMEZCUXl4UlFVRlJMRWRCUVVjc1NVRkJTU3hEUVVGRE8yOUNRVU5zUWl4SFFVRkhMRWRCUVVjc1NVRkJTU3gzUWtGQmQwSXNRMEZCUXl4RFFVRkRMRVZCUVVVc1EwRkJReXhEUVVGRExFTkJRVU03YVVKQlF6VkRPMmRDUVVORUxFbEJRVWtzUTBGQlF5eEhRVUZITEVOQlFVTXNSVUZCUlN4SlFVRkpMRU5CUVVNc1NVRkJTU3hIUVVGSExFTkJRVU1zUlVGQlJTeEpRVUZKTEVOQlFVTXNRMEZCUXp0dlFrRkROVUlzUTBGQlF5eEhRVUZITEVOQlFVTXNSVUZCUlN4SFFVRkhMRWRCUVVjc1EwRkJReXhOUVVGTkxFbEJRVWtzUTBGQlF5eERRVUZETEUxQlFVMHNTVUZCU1N4SFFVRkhMRU5CUVVNc1JVRkJSU3hIUVVGSExFZEJRVWNzUTBGQlF5eE5RVUZOTEVsQlFVa3NRMEZCUXl4RFFVRkRMRTFCUVUwc1EwRkJReXhGUVVGRk8yOUNRVVYwUlN4VFFVRlRMRU5CUVVNc1NVRkJTU3hEUVVGRExFVkJRVVVzUTBGQlF5eEZRVUZGTEVOQlFVTXNSVUZCUlN4RFFVRkRMRVZCUVVVc1EwRkJReXhGUVVGRkxFTkJRVU1zUTBGQlF6dHZRa0ZETDBJc1UwRkJVenRwUWtGRFdqdG5Ra0ZEUkN4SlFVRkpMRWRCUVVjc1EwRkJReXhGUVVGRkxFZEJRVWNzUjBGQlJ5eERRVUZETEUxQlFVMHNTVUZCU1N4RFFVRkRMRU5CUVVNc1RVRkJUU3hKUVVGSkxFZEJRVWNzUTBGQlF5eEZRVUZGTEVkQlFVY3NSMEZCUnl4RFFVRkRMRTFCUVUwc1NVRkJTU3hEUVVGRExFTkJRVU1zVFVGQlRTeEZRVUZGTzI5Q1FVMXdSU3hEUVVGRExFZEJRVWNzUTBGQlF5eERRVUZETEVkQlFVY3NRMEZCUXl4RlFVRkZMRWRCUVVjc1EwRkJReXhEUVVGRExFTkJRVU03YjBKQlEyeENMRVZCUVVVc1IwRkJSeXhEUVVGRExFTkJRVU1zUjBGQlJ5eERRVUZETEVWQlFVVXNSMEZCUnl4RFFVRkRMRU5CUVVNc1EwRkJRenR2UWtGRGJrSXNSVUZCUlN4SFFVRkhMRU5CUVVNc1EwRkJReXhIUVVGSExFTkJRVU1zUlVGQlJTeEhRVUZITEVOQlFVTXNRMEZCUXl4RFFVRkRPMmxDUVVOMFFqdHhRa0ZCVFR0dlFrRkRTQ3hEUVVGRExFZEJRVWNzUTBGQlF5eERRVUZETEVkQlFVY3NRMEZCUXl4RlFVRkZMRWRCUVVjc1IwRkJSeXhEUVVGRExFMUJRVTBzUjBGQlJ5eERRVUZETEVOQlFVTXNRMEZCUXp0dlFrRkRMMElzUlVGQlJTeEhRVUZITEVOQlFVTXNRMEZCUXl4SFFVRkhMRU5CUVVNc1JVRkJSU3hIUVVGSExFZEJRVWNzUTBGQlF5eE5RVUZOTEVOQlFVTXNRMEZCUXp0dlFrRkROVUlzUlVGQlJTeEhRVUZITEVOQlFVTXNRMEZCUXl4SFFVRkhMRU5CUVVNc1JVRkJSU3hIUVVGSExFZEJRVWNzUTBGQlF5eE5RVUZOTEVOQlFVTXNRMEZCUXp0cFFrRkRMMEk3WjBKQlEwUXNTVUZCU1N4VlFVRlZMRU5CUVVNc1RVRkJUU3hEUVVGRExFTkJRVU1zUlVGQlJTeEZRVUZGTEVWQlFVVXNSVUZCUlN4RFFVRkRMRVZCUVVVN2IwSkJRemxDTEZOQlFWTXNRMEZCUXl4SlFVRkpMRU5CUVVNc1JVRkJSU3hEUVVGRExFVkJRVVVzUTBGQlF5eEZRVUZGTEVOQlFVTXNSVUZCUlN4RFFVRkRMRVZCUVVVc1EwRkJReXhEUVVGRE8ybENRVU5zUXp0eFFrRkJUVHR2UWtGRFNDeFRRVUZUTEVOQlFVTXNTVUZCU1N4RFFVRkRMRVZCUVVVc1EwRkJReXhGUVVGRkxFTkJRVU1zUlVGQlJTeERRVUZETEVWQlFVVXNRMEZCUXl4RlFVRkZMRU5CUVVNc1EwRkJRenRwUWtGRGJFTTdZVUZEU2p0VFFVTktPMUZCUlVRc1QwRkJUeXhWUVVGVkxFTkJRVU1zVVVGQlVTeERRVUZETEZOQlFWTXNRMEZCUXl4RFFVRkRPMGxCUXpGRExFTkJRVU03U1VGTFRTeDFRa0ZCV1N4SFFVRnVRaXhWUVVGdlFpeEpRVUZoTzFGQlF6ZENMRk5CUVZNc1UwRkJVeXhEUVVGRExFTkJRVkU3V1VGRGRrSXNUMEZCWXl4RlFVRkZMRU5CUVVNc1JVRkJSU3hEUVVGRExFTkJRVU1zUTBGQlF5eEZRVUZGTEVOQlFVTXNSVUZCUlN4RFFVRkRMRU5CUVVNc1EwRkJReXhGUVVGRkxFTkJRVU03VVVGRGNrTXNRMEZCUXp0UlFVTkVMRWxCUVVrc1ZVRkJWU3hIUVVGSExGVkJRVU1zUTBGQlF5eEZRVUZGTEVOQlFVTXNSVUZCUlN4RFFVRkRMRWxCUVVzc1QwRkJRU3hKUVVGSkxFTkJRVU1zUjBGQlJ5eERRVUZETEVOQlFVTXNRMEZCUXl4RFFVRkRMRU5CUVVNc1IwRkJSeXhEUVVGRExFTkJRVU1zUTBGQlF5eERRVUZETEVkQlFVY3NRMEZCUXl4RFFVRkRMRU5CUVVNc1EwRkJReXhIUVVGSExFTkJRVU1zUTBGQlF5eERRVUZETEVOQlFVTXNSMEZCUnl4RFFVRkRMRU5CUVVNc1EwRkJReXhEUVVGRExFZEJRVWNzUTBGQlF5eERRVUZETEVOQlFVTXNRMEZCUXl4SFFVRkhMRU5CUVVNc1EwRkJReXhEUVVGRExFTkJRVU1zUjBGQlJ5eERRVUZETEVOQlFVTXNRMEZCUXl4RFFVRkRMRU5CUVVNc1IwRkJSeXhMUVVGTExFVkJRWFpGTEVOQlFYVkZMRU5CUVVNN1VVRkRkRWNzU1VGQlNTeFJRVUZSTEVkQlFVY3NSVUZCUlN4RFFVRkRPMUZCUTJ4Q0xFbEJRVWtzUTBGQlF5eEhRVUZITEZOQlFWTXNRMEZCUXl4SlFVRkpMRU5CUVVNc1EwRkJReXhEUVVGRExFTkJRVU1zUTBGQlF6dFJRVU16UWl4TFFVRkxMRWxCUVVrc1EwRkJReXhIUVVGSExFTkJRVU1zUlVGQlJTeERRVUZETEVkQlFVY3NTVUZCU1N4RFFVRkRMRTFCUVUwc1JVRkJSU3hEUVVGRExFVkJRVVVzUlVGQlJUdFpRVU5zUXl4SlFVRkpMRU5CUVVNc1IwRkJSeXhUUVVGVExFTkJRVU1zU1VGQlNTeERRVUZETEVOQlFVTXNRMEZCUXl4RFFVRkRMRVZCUVVVc1EwRkJReXhIUVVGSExFTkJRVU1zUjBGQlJ5eEpRVUZKTEVOQlFVTXNUVUZCVFN4SFFVRkhMRU5CUVVNc1EwRkJReXhEUVVGRExFTkJRVU1zU1VGQlNTeERRVUZETEVOQlFVTXNSMEZCUnl4RFFVRkRMRU5CUVVNc1EwRkJReXhEUVVGRExFTkJRVU1zU1VGQlNTeERRVUZETzFsQlEzcEZMRWxCUVVrc1EwRkJReXhEUVVGRExFbEJRVWtzUTBGQlF5eFZRVUZWTEVOQlFVTXNRMEZCUXl4RlFVRkZMRU5CUVVNc1JVRkJSU3hEUVVGRExFTkJRVU1zUlVGQlJUdG5Ra0ZETlVJc1VVRkJVU3hEUVVGRExFbEJRVWtzUTBGQlF5eERRVUZETEVOQlFVTXNSVUZCUlN4RFFVRkRMRU5CUVVNc1EwRkJReXhEUVVGRE8yZENRVU4wUWl4RFFVRkRMRWRCUVVjc1EwRkJReXhEUVVGRE8yRkJRMVE3VTBGRFNqdFJRVU5FTEU5QlFVOHNVVUZCVVN4RFFVRkRPMGxCUTNCQ0xFTkJRVU03U1VGSlJDd3dRa0ZCU3l4SFFVRk1MRlZCUVUwc1EwRkJVeXhGUVVGRkxFTkJRVk03VVVGQk1VSXNhVUpCTkVSRE8xRkJNMFJITEVsQlFVa3NUVUZCVFN4SFFVRkhMRWxCUVVrc1EwRkJReXhMUVVGTExFTkJRVk1zUTBGQlF5eERRVUZETEVWQlFVVXNUVUZCVFN4SFFVRkhMRWxCUVVrc1EwRkJReXhMUVVGTExFTkJRVk1zUTBGQlF5eERRVUZETEVOQlFVTTdVVUZEYmtVc1NVRkJTU3hEUVVGRExGTkJRVk1zUjBGQlJ5eEpRVUZKTEVOQlFVTXNaMEpCUVdkQ0xFTkJRVU1zVFVGQlRTeEZRVUZGTEUxQlFVMHNRMEZCUXl4RFFVRkRPMUZCUlhaRUxFbEJRVWtzWTBGQll5eEhRVUZITEVWQlFVVXNRMEZCUXp0UlFVTjRRaXhKUVVGSkxFTkJRVU1zVTBGQlV5eERRVUZETEU5QlFVOHNRMEZCUXl4VlFVRkJMRU5CUVVNc1NVRkJTU3hQUVVGQkxHTkJRV01zUTBGQlF5eERRVUZETEVOQlFVTXNSVUZCUlN4RFFVRkRMRWRCUVVjc1EwRkJReXhGUVVGNFFpeERRVUYzUWl4RFFVRkRMRU5CUVVNN1VVRkRkRVFzU1VGQlNTeERRVUZETEdGQlFXRXNSMEZCUnl4SlFVRkpMRU5CUVVNc1MwRkJTeXhEUVVGRExFMUJRVTBzUTBGQlF5eFZRVUZCTEVOQlFVTTdXVUZEY0VNc1NVRkJTU3hEUVVGRExFZEJRVWNzUzBGQlNTeERRVUZETEV0QlFVc3NRMEZCUXl4RFFVRkRMRU5CUVVNc1RVRkJUU3hEUVVGRExFVkJRM2hDTEVOQlFVTXNSMEZCUnl4TFFVRkpMRU5CUVVNc1MwRkJTeXhEUVVGRExFTkJRVU1zUTBGQlF5eE5RVUZOTEVOQlFVTXNRMEZCUXp0WlFVTTNRaXhQUVVGUExFTkJRVU1zUTBGQlF5eERRVUZETEVOQlFVTXNTVUZCU1N4SlFVRkpMRU5CUVVNc1EwRkJReXhKUVVGSkxFTkJRVU1zUlVGQlJTeEpRVUZKTEdOQlFXTTdiVUpCUTNaRExFTkJRVU1zUTBGQlF5eEpRVUZKTEVsQlFVa3NRMEZCUXl4RFFVRkRMRWxCUVVrc1EwRkJReXhGUVVGRkxFbEJRVWtzWTBGQll5eERRVUZETEVOQlFVTTdVVUZEYkVRc1EwRkJReXhEUVVGRExFTkJRVU03VVVGSFNDeExRVUZMTEVsQlFVa3NRMEZCUXl4SFFVRkhMRU5CUVVNc1JVRkJSU3hEUVVGRExFZEJRVWNzVFVGQlRTeERRVUZETEV0QlFVc3NRMEZCUXl4TlFVRk5MRVZCUVVVc1EwRkJReXhGUVVGRkxFVkJRVVU3V1VGRE1VTXNTVUZCU1N4RFFVRkRMRWRCUVVjc1RVRkJUU3hEUVVGRExFdEJRVXNzUTBGQlF5eERRVUZETEVOQlFVTXNRMEZCUXl4RlFVRkZMRU5CUVVNN1dVRkRNMElzU1VGQlNTeERRVUZETEVkQlFVY3NUVUZCVFN4RFFVRkRMRXRCUVVzc1EwRkJReXhEUVVGRExFTkJRVU1zUTBGQlF5eEZRVUZGTEVOQlFVTTdXVUZETTBJc1NVRkJTU3hEUVVGRExHRkJRV0VzUTBGQlF5eEpRVUZKTEVOQlFVTTdaMEpCUTNCQ0xFMUJRVTBzUlVGQlJTeERRVUZETzJkQ1FVTlVMRTFCUVUwc1JVRkJSU3hEUVVGRE8yZENRVU5VTEUxQlFVMHNSVUZCUlN4RFFVRkRPMkZCUTFvc1EwRkJReXhEUVVGRE8xTkJRMDQ3VVVGRFJDeExRVUZMTEVsQlFVa3NRMEZCUXl4SFFVRkhMRU5CUVVNc1JVRkJSU3hEUVVGRExFZEJRVWNzVFVGQlRTeERRVUZETEV0QlFVc3NRMEZCUXl4TlFVRk5MRVZCUVVVc1EwRkJReXhGUVVGRkxFVkJRVVU3V1VGRE1VTXNTVUZCU1N4RFFVRkRMRWRCUVVjc1RVRkJUU3hEUVVGRExFdEJRVXNzUTBGQlF5eERRVUZETEVOQlFVTXNRMEZCUXl4RlFVRkZMRU5CUVVNN1dVRkRNMElzU1VGQlNTeERRVUZETEVkQlFVY3NUVUZCVFN4RFFVRkRMRXRCUVVzc1EwRkJReXhEUVVGRExFTkJRVU1zUTBGQlF5eEZRVUZGTEVOQlFVTTdXVUZETTBJc1NVRkJTU3hEUVVGRExHRkJRV0VzUTBGQlF5eEpRVUZKTEVOQlFVTTdaMEpCUTNCQ0xFMUJRVTBzUlVGQlJTeERRVUZETzJkQ1FVTlVMRTFCUVUwc1JVRkJSU3hEUVVGRE8yZENRVU5VTEUxQlFVMHNSVUZCUlN4RFFVRkRPMkZCUTFvc1EwRkJReXhEUVVGRE8xTkJRMDQ3VVVGRlJDeEpRVUZKTEZOQlFWTXNSMEZCUnl4VlFVRkJMRU5CUVVNc1NVRkJSeXhQUVVGQkxFTkJRVU1zUTBGQlF5eE5RVUZOTEVWQlFWSXNRMEZCVVN4RlFVTjRRaXhUUVVGVExFZEJRVWNzVlVGQlFTeERRVUZETEVsQlFVY3NUMEZCUVN4RFFVRkRMRU5CUVVNc1RVRkJUU3hGUVVGU0xFTkJRVkVzUlVGRGVFSXNVMEZCVXl4SFFVRkhMRlZCUVVFc1EwRkJReXhKUVVGSExFOUJRVUVzUTBGQlF5eERRVUZETEUxQlFVMHNSVUZCVWl4RFFVRlJMRU5CUVVNN1VVRkZOMElzU1VGQlNTeHpRa0ZCYzBJc1IwRkJSeXhKUVVGSkxEQkNRVUZWTEVOQlFVTXNTVUZCU1N4RFFVRkRMRXRCUVVzc1EwRkJReXhOUVVGTkxFVkJRVVVzU1VGQlNTeERRVUZETEdGQlFXRXNSVUZCUlN4VFFVRlRMRVZCUVVVc1UwRkJVeXhGUVVGRkxGTkJRVk1zUTBGQlF5eERRVUZETzFGQlEzQklMRWxCUVVrc1YwRkJWeXhIUVVGSExGVkJRVU1zUTBGQlF5eEZRVUZGTEVOQlFVTXNSVUZCUlN4RFFVRkRPMWxCUTNSQ0xFbEJRVWtzUTBGQlF5eEhRVUZITEV0QlFVa3NRMEZCUXl4TFFVRkxMRU5CUVVNc1EwRkJReXhEUVVGRExFVkJRVVVzUTBGQlF5eEhRVUZITEV0QlFVa3NRMEZCUXl4TFFVRkxMRU5CUVVNc1EwRkJReXhEUVVGRExFVkJRVVVzUTBGQlF5eEhRVUZITEV0QlFVa3NRMEZCUXl4TFFVRkxMRU5CUVVNc1EwRkJReXhEUVVGRExFTkJRVU03V1VGRE5VUXNTVUZCU1N4RlFVRkZMRWRCUVVjc1NVRkJTU3hEUVVGRExFZEJRVWNzUTBGQlF5eERRVUZETEVOQlFVTXNRMEZCUXl4SFFVRkhMRU5CUVVNc1EwRkJReXhEUVVGRExFTkJRVU1zUlVGQlJTeEZRVUZGTEVkQlFVY3NTVUZCU1N4RFFVRkRMRWRCUVVjc1EwRkJReXhEUVVGRExFTkJRVU1zUTBGQlF5eEhRVUZITEVOQlFVTXNRMEZCUXl4RFFVRkRMRU5CUVVNc1EwRkJRenRaUVVWMlJDeEpRVUZKTEVOQlFVTXNRMEZCUXl4SlFVRkpMRXRCUVVzc1RVRkJUU3hKUVVGSkxFTkJRVU1zUTBGQlF5eEpRVUZKTEV0QlFVc3NRMEZCUXl4RFFVRkRMRWxCUVVrc1NVRkJTU3hEUVVGRExFTkJRVU1zU1VGQlNTeExRVUZMTEUxQlFVMHNTVUZCU1N4RFFVRkRMRU5CUVVNc1NVRkJTU3hMUVVGTExFTkJRVU1zUTBGQlF5eEpRVUZKTzJkQ1FVTm9SaXhQUVVGUExFTkJRVU1zUTBGQlF6dFpRVU5pTEU5QlFVOHNSVUZCUlN4SFFVRkhMRU5CUVVNc1NVRkJTU3hGUVVGRkxFZEJRVWNzUTBGQlF5eERRVUZETEVOQlFVTXNRMEZCUXl4SlFVRkpMRU5CUVVNc1EwRkJReXhEUVVGRExFTkJRVU1zUTBGQlF6dFJRVU4yUXl4RFFVRkRMRU5CUVVNN1VVRkhSaXhKUVVGSkxGbEJRVmtzUjBGQlJ5eHpRa0ZCYzBJc1EwRkJReXc0UWtGQk9FSXNRMEZEY0VVc1RVRkJUU3hEUVVGRExFdEJRVXNzUTBGQlF5eERRVUZETEVOQlFVTXNRMEZCUXl4RlFVRkZMRVZCUVVVc1RVRkJUU3hEUVVGRExFdEJRVXNzUTBGQlF5eERRVUZETEVOQlFVTXNRMEZCUXl4RlFVRkZMRVZCUTNSRExGZEJRVmNzUTBGQlF5eERRVUZETzFGQlIycENMRWxCUVVrc1ZVRkJWU3hIUVVGSExGbEJRVmtzUTBGQlF5eFBRVUZQTEVWQlFVVXNRMEZCUXl4SFFVRkhMRU5CUVVNc1ZVRkJRU3hGUVVGRkxFbEJRVWtzVDBGQlFTeExRVUZKTEVOQlFVTXNTMEZCU3l4RFFVRkRMRVZCUVVVc1EwRkJReXhGUVVGa0xFTkJRV01zUTBGQlF5eERRVUZETzFGQlEyeEZMRlZCUVZVc1EwRkJReXhKUVVGSkxFTkJRVU1zU1VGQlNTeERRVUZETEV0QlFVc3NRMEZCUXl4TlFVRk5MRU5CUVVNc1JVRkJSU3hEUVVGRExFTkJRVU1zUzBGQlN5eERRVUZETEVOQlFVTXNRMEZCUXl4RFFVRkRMRU5CUVVNN1VVRkhhRVFzVDBGQlR5eFZRVUZWTEVOQlFVTXNUVUZCVFN4RFFVRkRMRlZCUVVNc1EwRkJReXhGUVVGRkxFTkJRVU03V1VGRE1VSXNUMEZCUVN4RFFVRkRMRU5CUVVNc1EwRkJReXhIUVVGSExGVkJRVlVzUTBGQlF5eE5RVUZOTEVkQlFVY3NRMEZCUXl4SlFVRkpMRlZCUVZVc1EwRkJReXhEUVVGRExFZEJRVWNzUTBGQlF5eERRVUZETEVOQlFVTXNTVUZCU1N4TFFVRkxMRTFCUVUwc1NVRkJTU3hEUVVGRExFTkJRVU1zU1VGQlNTeExRVUZMTEUxQlFVMDdiVUpCUXpsRkxFTkJRVU1zUjBGQlJ5eERRVUZETEVsQlFVa3NRMEZCUXl4RFFVRkRMRWxCUVVrc1MwRkJTeXhOUVVGTkxFbEJRVWtzVlVGQlZTeERRVUZETEVOQlFVTXNSMEZCUnl4RFFVRkRMRU5CUVVNc1EwRkJReXhKUVVGSkxFdEJRVXNzVFVGQlRTeERRVUZETzFGQlJIWkZMRU5CUTNWRkxFTkJRVU1zUTBGQlF6dEpRVU5xUml4RFFVRkRPMGxCUlUwc2RVSkJRVmtzUjBGQmJrSXNWVUZCYjBJc1MwRkJaMElzUlVGQlJTeFpRVUZ2UWl4RlFVRkZMRlZCUVd0Q0xFVkJRVVVzVjBGQmJVSTdVVUZETDBZc1NVRkJTU3hOUVVGTkxFZEJRVWM3V1VGRFZDeFRRVUZUTEVWQlFVVXNTVUZCU1N4SFFVRkhMRXRCUVVzc1EwRkJReXhEUVVGRExFTkJRVU1zUTBGQlF5eERRVUZETEVOQlFVTXNRMEZCUXl4RFFVRkRMRWRCUVVjc1IwRkJSeXhIUVVGSExFdEJRVXNzUTBGQlF5eERRVUZETEVOQlFVTXNRMEZCUXl4RFFVRkRMRU5CUVVNc1EwRkJReXhEUVVGRExFZEJRVWNzUjBGQlJ6dFpRVU16UkN4VFFVRlRMRVZCUVVVc1JVRkJSVHRUUVVOb1FpeERRVUZETzFGQlEwWXNTVUZCU1N4TFFVRkxMRU5CUVVNc1RVRkJUU3hIUVVGSExFTkJRVU1zUlVGQlJUdFpRVU5zUWl4TFFVRkxMRWxCUVVrc1EwRkJReXhIUVVGSExFTkJRVU1zUlVGQlJTeERRVUZETEVkQlFVY3NTMEZCU3l4RFFVRkRMRTFCUVUwc1JVRkJSU3hEUVVGRExFVkJRVVVzUlVGQlJUdG5Ra0ZEYmtNc1NVRkJTU3hGUVVGRkxFZEJRVWNzUzBGQlN5eERRVUZETEVOQlFVTXNRMEZCUXl4RFFVRkRPMmRDUVVOc1FpeEpRVUZKTEVOQlFVTXNSMEZCUnl4RlFVRkZMRU5CUVVNc1EwRkJReXhEUVVGRExFTkJRVU1zUTBGQlF5eEZRVUZGTEVOQlFVTXNSMEZCUnl4RlFVRkZMRU5CUVVNc1EwRkJReXhEUVVGRExFTkJRVU1zUTBGQlF5eERRVUZETzJkQ1FVTTNRaXhKUVVGSkxFVkJRVVVzUjBGQlJ5eERRVUZETEVkQlFVY3NSVUZCUlN4RFFVRkRMRU5CUVVNc1EwRkJReXhEUVVGRExFTkJRVU1zUTBGQlF6dG5Ra0ZEY2tJc1NVRkJTU3hGUVVGRkxFZEJRVWNzUTBGQlF5eEhRVUZITEVWQlFVVXNRMEZCUXl4RFFVRkRMRU5CUVVNc1EwRkJReXhEUVVGRExFTkJRVU03WjBKQlEzSkNMRWxCUVVrc1EwRkJReXhIUVVGSExFdEJRVXNzUTBGQlF5eE5RVUZOTEVkQlFVY3NRMEZCUXl4RlFVRkZPMjlDUVVOMFFpeEpRVUZKTEVsQlFVa3NRMEZCUXl4SFFVRkhMRU5CUVVNc1JVRkJSU3hEUVVGRExFZEJRVWNzUTBGQlF5eEZRVUZGTzNkQ1FVTnNRaXhEUVVGRExFbEJRVWtzUlVGQlJTeEhRVUZITEVsQlFVa3NRMEZCUXl4SFFVRkhMRU5CUVVNc1JVRkJSU3hEUVVGRExFZEJRVWNzV1VGQldTeERRVUZETzNGQ1FVTjZRenQ1UWtGQlRUdDNRa0ZEU0N4RFFVRkRMRWxCUVVrc1JVRkJSU3hIUVVGSExFbEJRVWtzUTBGQlF5eEhRVUZITEVOQlFVTXNSVUZCUlN4RFFVRkRMRWRCUVVjc1dVRkJXU3hEUVVGRE8zRkNRVU42UXp0dlFrRkRSQ3hOUVVGTkxFTkJRVU1zVTBGQlV5eEpRVUZKTEVsQlFVa3NSMEZCUnl4RFFVRkRMRWRCUVVjc1IwRkJSeXhIUVVGSExFTkJRVU1zUjBGQlJ5eEhRVUZITEVOQlFVTTdiMEpCUXpkRExFbEJRVWtzUTBGQlF5eEhRVUZITEV0QlFVc3NRMEZCUXl4RFFVRkRMRWRCUVVjc1EwRkJReXhEUVVGRExFTkJRVU03YjBKQlEzSkNMRWxCUVVrc1JVRkJSU3hIUVVGSExFTkJRVU1zUTBGQlF5eERRVUZETEVOQlFVTXNRMEZCUXl4RFFVRkRMRVZCUVVVc1JVRkJSU3hIUVVGSExFTkJRVU1zUTBGQlF5eERRVUZETEVOQlFVTXNRMEZCUXl4RFFVRkRMRU5CUVVNN2IwSkJRemRDTEVsQlFVa3NSVUZCUlN4SFFVRkhMRU5CUVVNc1EwRkJReXhEUVVGRExFTkJRVU1zUTBGQlF5eERRVUZETEVOQlFVTTdiMEpCUTJoQ0xFbEJRVWtzUlVGQlJTeEhRVUZITEVOQlFVTXNRMEZCUXl4RFFVRkRMRU5CUVVNc1EwRkJReXhEUVVGRExFTkJRVU03YjBKQlEyaENMRVZCUVVVc1IwRkJSeXhGUVVGRkxFZEJRVWNzUlVGQlJTeERRVUZETzI5Q1FVTmlMRVZCUVVVc1IwRkJSeXhGUVVGRkxFZEJRVWNzUlVGQlJTeERRVUZETzI5Q1FVTmlMRWxCUVVrc1MwRkJTeXhIUVVGSExGVkJRVlVzUTBGQlF5eHJRa0ZCYTBJc1EwRkJReXhGUVVGRkxFVkJRVVVzUTBGQlF5eERRVUZETEVkQlFVY3NRMEZCUXl4RFFVRkRMRU5CUVVNc1EwRkJReXhEUVVGRExFTkJRVU1zUTBGQlF5eERRVUZETEVOQlFVTXNRMEZCUXp0dlFrRkZOMFFzU1VGQlNTeEZRVUZGTEVWQlFVVXNSVUZCUlN4RFFVRkRPMjlDUVVOWUxFbEJRVWtzU1VGQlNTeERRVUZETEVkQlFVY3NRMEZCUXl4RlFVRkZMRU5CUVVNc1IwRkJSeXhEUVVGRExFVkJRVVU3ZDBKQlEyeENMRVZCUVVVc1IwRkJSeXhGUVVGRkxFZEJRVWNzUlVGQlJTeEhRVUZITEVsQlFVa3NRMEZCUXl4SFFVRkhMRU5CUVVNc1JVRkJSU3hEUVVGRExFZEJRVWNzV1VGQldTeERRVUZETzNkQ1FVTXpReXhGUVVGRkxFZEJRVWNzUlVGQlJTeERRVUZETzNGQ1FVTllPM2xDUVVGTk8zZENRVU5JTEVWQlFVVXNSMEZCUnl4RlFVRkZMRU5CUVVNN2QwSkJRMUlzUlVGQlJTeEhRVUZITEVWQlFVVXNSMEZCUnl4RlFVRkZMRWRCUVVjc1NVRkJTU3hEUVVGRExFZEJRVWNzUTBGQlF5eEZRVUZGTEVOQlFVTXNSMEZCUnl4WlFVRlpMRU5CUVVNN2NVSkJRemxETzI5Q1FVTkVMRWxCUVVrc1JVRkJSU3hIUVVGSExFbEJRVWtzUTBGQlF5eEhRVUZITEVOQlFVTXNSVUZCUlN4SFFVRkhMRU5CUVVNc1EwRkJReXhEUVVGRE8yOUNRVU14UWl4SlFVRkpMRVZCUVVVc1IwRkJSeXhKUVVGSkxFTkJRVU1zUjBGQlJ5eERRVUZETEVWQlFVVXNSMEZCUnl4RFFVRkRMRU5CUVVNc1EwRkJRenR2UWtGRE1VSXNUVUZCVFN4RFFVRkRMRk5CUVZNc1NVRkJTU3hKUVVGSkxFZEJRVWNzUlVGQlJTeEhRVUZITEVkQlFVY3NSMEZCUnl4RlFVRkZMRWRCUVVjc1QwRkJUeXhIUVVGSExFdEJRVXNzUjBGQlJ5eEhRVUZITEVkQlFVY3NSVUZCUlN4SFFVRkhMRWRCUVVjc1IwRkJSeXhGUVVGRkxFZEJRVWNzUjBGQlJ5eERRVUZETzJsQ1FVTXhSanR4UWtGQlRUdHZRa0ZEU0N4SlFVRkpMRkZCUVZFc1IwRkJSeXhEUVVGRExFTkJRVU1zUlVGQlJTeERRVUZETEVOQlFVTXNRMEZCUXp0dlFrRkRkRUlzU1VGQlNTeFpRVUZaTEVWQlFVVXNXVUZCV1N4RFFVRkRPMjlDUVVNdlFpeEpRVUZKTEVsQlFVa3NRMEZCUXl4SFFVRkhMRU5CUVVNc1JVRkJSU3hEUVVGRExFZEJRVWNzUTBGQlF5eEZRVUZGTzNkQ1FVTnNRaXhEUVVGRExFbEJRVWtzUlVGQlJTeEhRVUZITEVsQlFVa3NRMEZCUXl4SFFVRkhMRU5CUVVNc1JVRkJSU3hEUVVGRExFZEJRVWNzVjBGQlZ5eERRVUZETzNkQ1FVTnlReXhaUVVGWkxFZEJRVWNzUTBGQlF5eERRVUZETEVWQlFVVXNRMEZCUXl4SFFVRkhMRlZCUVZVc1EwRkJReXhEUVVGRE8zZENRVU51UXl4WlFVRlpMRWRCUVVjc1EwRkJReXhEUVVGRExFVkJRVVVzUTBGQlF5eEhRVUZITEZWQlFWVXNRMEZCUXl4RFFVRkRPM0ZDUVVOMFF6dDVRa0ZCVFR0M1FrRkRTQ3hEUVVGRExFbEJRVWtzUlVGQlJTeEhRVUZITEVsQlFVa3NRMEZCUXl4SFFVRkhMRU5CUVVNc1JVRkJSU3hEUVVGRExFZEJRVWNzVjBGQlZ5eERRVUZETzNkQ1FVTnlReXhaUVVGWkxFZEJRVWNzUTBGQlF5eERRVUZETEVkQlFVY3NWVUZCVlN4RlFVRkZMRU5CUVVNc1EwRkJReXhEUVVGRE8zZENRVU51UXl4WlFVRlpMRWRCUVVjc1EwRkJReXhEUVVGRExFZEJRVWNzVlVGQlZTeEZRVUZGTEVOQlFVTXNRMEZCUXl4RFFVRkRPM0ZDUVVOMFF6dHZRa0ZEUkN4TlFVRk5MRU5CUVVNc1UwRkJVeXhKUVVGSkxFbEJRVWtzUjBGQlJ5eERRVUZETEVkQlFVY3NSMEZCUnl4SFFVRkhMRU5CUVVNc1IwRkJSeXhIUVVGSExFTkJRVU03YjBKQlF6ZERMRWxCUVVrc1YwRkJWeXhIUVVGSExFTkJRVU1zUlVGQlJUdDNRa0ZEYWtJc1RVRkJUU3hEUVVGRExGTkJRVk1zUjBGQlJ5eEpRVUZKTEVkQlFVY3NVVUZCVVN4RFFVRkRMRU5CUVVNc1EwRkJReXhIUVVGSExFZEJRVWNzUjBGQlJ5eFJRVUZSTEVOQlFVTXNRMEZCUXl4RFFVRkRMRWRCUVVjc1MwRkJTeXhIUVVGSExGbEJRVmtzUTBGQlF5eERRVUZETEVOQlFVTXNSMEZCUnl4SFFVRkhMRWRCUVVjc1dVRkJXU3hEUVVGRExFTkJRVU1zUTBGQlF6czRRa0ZEZWtjc1MwRkJTeXhIUVVGSExGbEJRVmtzUTBGQlF5eERRVUZETEVOQlFVTXNSMEZCUnl4SFFVRkhMRWRCUVVjc1dVRkJXU3hEUVVGRExFTkJRVU1zUTBGQlF5eERRVUZETzNGQ1FVTnlSRHRwUWtGRFNqdGhRVU5LTzFOQlEwbzdZVUZCVFR0WlFVTklMRWxCUVVrc1JVRkJSU3hIUVVGSExFdEJRVXNzUTBGQlF5eERRVUZETEVOQlFVTXNRMEZCUXp0WlFVTnNRaXhKUVVGSkxFTkJRVU1zUjBGQlJ5eEZRVUZGTEVOQlFVTXNRMEZCUXl4RFFVRkRMRU5CUVVNc1EwRkJReXhGUVVGRkxFTkJRVU1zUjBGQlJ5eEZRVUZGTEVOQlFVTXNRMEZCUXl4RFFVRkRMRU5CUVVNc1EwRkJReXhEUVVGRE8xbEJRemRDTEVsQlFVa3NSVUZCUlN4SFFVRkhMRU5CUVVNc1IwRkJSeXhGUVVGRkxFTkJRVU1zUTBGQlF5eERRVUZETEVOQlFVTXNRMEZCUXl4RFFVRkRPMWxCUTNKQ0xFbEJRVWtzUlVGQlJTeEhRVUZITEVOQlFVTXNSMEZCUnl4RlFVRkZMRU5CUVVNc1EwRkJReXhEUVVGRExFTkJRVU1zUTBGQlF5eERRVUZETzFsQlEzSkNMRWxCUVVrc1VVRkJVU3hIUVVGSExFTkJRVU1zUTBGQlF5eEZRVUZGTEVOQlFVTXNRMEZCUXl4RFFVRkRPMWxCUTNSQ0xFbEJRVWtzV1VGQldTeEZRVUZGTEZsQlFWa3NRMEZCUXp0WlFVTXZRaXhKUVVGSkxFbEJRVWtzUTBGQlF5eEhRVUZITEVOQlFVTXNSVUZCUlN4RFFVRkRMRWRCUVVjc1EwRkJReXhGUVVGRk8yZENRVU5zUWl4RFFVRkRMRWxCUVVrc1JVRkJSU3hIUVVGSExFbEJRVWtzUTBGQlF5eEhRVUZITEVOQlFVTXNSVUZCUlN4RFFVRkRMRWRCUVVjc1YwRkJWeXhEUVVGRE8yZENRVU55UXl4WlFVRlpMRWRCUVVjc1EwRkJReXhEUVVGRExFVkJRVVVzUTBGQlF5eEhRVUZITEZWQlFWVXNRMEZCUXl4RFFVRkRPMmRDUVVOdVF5eFpRVUZaTEVkQlFVY3NRMEZCUXl4RFFVRkRMRVZCUVVVc1EwRkJReXhIUVVGSExGVkJRVlVzUTBGQlF5eERRVUZETzJGQlEzUkRPMmxDUVVGTk8yZENRVU5JTEVOQlFVTXNTVUZCU1N4RlFVRkZMRWRCUVVjc1NVRkJTU3hEUVVGRExFZEJRVWNzUTBGQlF5eEZRVUZGTEVOQlFVTXNSMEZCUnl4WFFVRlhMRU5CUVVNN1owSkJRM0pETEZsQlFWa3NSMEZCUnl4RFFVRkRMRU5CUVVNc1IwRkJSeXhWUVVGVkxFVkJRVVVzUTBGQlF5eERRVUZETEVOQlFVTTdaMEpCUTI1RExGbEJRVmtzUjBGQlJ5eERRVUZETEVOQlFVTXNSMEZCUnl4VlFVRlZMRVZCUVVVc1EwRkJReXhEUVVGRExFTkJRVU03WVVGRGRFTTdXVUZEUkN4TlFVRk5MRU5CUVVNc1UwRkJVeXhKUVVGSkxFbEJRVWtzUjBGQlJ5eERRVUZETEVkQlFVY3NSMEZCUnl4SFFVRkhMRU5CUVVNc1IwRkJSeXhIUVVGSExFTkJRVU03V1VGRE4wTXNTVUZCU1N4WFFVRlhMRWRCUVVjc1EwRkJReXhGUVVGRk8yZENRVU5xUWl4TlFVRk5MRU5CUVVNc1UwRkJVeXhIUVVGSExFbEJRVWtzUjBGQlJ5eFJRVUZSTEVOQlFVTXNRMEZCUXl4RFFVRkRMRWRCUVVjc1IwRkJSeXhIUVVGSExGRkJRVkVzUTBGQlF5eERRVUZETEVOQlFVTXNSMEZCUnl4TFFVRkxMRWRCUVVjc1dVRkJXU3hEUVVGRExFTkJRVU1zUTBGQlF5eEhRVUZITEVkQlFVY3NSMEZCUnl4WlFVRlpMRU5CUVVNc1EwRkJReXhEUVVGRE8zTkNRVU42Unl4TFFVRkxMRWRCUVVjc1dVRkJXU3hEUVVGRExFTkJRVU1zUTBGQlF5eEhRVUZITEVkQlFVY3NSMEZCUnl4WlFVRlpMRU5CUVVNc1EwRkJReXhEUVVGRExFTkJRVU03WVVGRGNrUTdVMEZEU2p0UlFVTkVMRTlCUVU4c1RVRkJUU3hEUVVGRE8wbEJRMnhDTEVOQlFVTTdTVUZEVEN4cFFrRkJRenRCUVVGRUxFTkJRVU1zUVVGNmJFSkVMRWxCZVd4Q1F6dEJRWHBzUWxrc1owTkJRVlVpZlE9PSIsIlwidXNlIHN0cmljdFwiO1xuT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsIFwiX19lc01vZHVsZVwiLCB7IHZhbHVlOiB0cnVlIH0pO1xudmFyIHBhY2tpbmdPcHRpb25zID0ge1xuICAgIFBBRERJTkc6IDEwLFxuICAgIEdPTERFTl9TRUNUSU9OOiAoMSArIE1hdGguc3FydCg1KSkgLyAyLFxuICAgIEZMT0FUX0VQU0lMT046IDAuMDAwMSxcbiAgICBNQVhfSU5FUkFUSU9OUzogMTAwXG59O1xuZnVuY3Rpb24gYXBwbHlQYWNraW5nKGdyYXBocywgdywgaCwgbm9kZV9zaXplLCBkZXNpcmVkX3JhdGlvLCBjZW50ZXJHcmFwaCkge1xuICAgIGlmIChkZXNpcmVkX3JhdGlvID09PSB2b2lkIDApIHsgZGVzaXJlZF9yYXRpbyA9IDE7IH1cbiAgICBpZiAoY2VudGVyR3JhcGggPT09IHZvaWQgMCkgeyBjZW50ZXJHcmFwaCA9IHRydWU7IH1cbiAgICB2YXIgaW5pdF94ID0gMCwgaW5pdF95ID0gMCwgc3ZnX3dpZHRoID0gdywgc3ZnX2hlaWdodCA9IGgsIGRlc2lyZWRfcmF0aW8gPSB0eXBlb2YgZGVzaXJlZF9yYXRpbyAhPT0gJ3VuZGVmaW5lZCcgPyBkZXNpcmVkX3JhdGlvIDogMSwgbm9kZV9zaXplID0gdHlwZW9mIG5vZGVfc2l6ZSAhPT0gJ3VuZGVmaW5lZCcgPyBub2RlX3NpemUgOiAwLCByZWFsX3dpZHRoID0gMCwgcmVhbF9oZWlnaHQgPSAwLCBtaW5fd2lkdGggPSAwLCBnbG9iYWxfYm90dG9tID0gMCwgbGluZSA9IFtdO1xuICAgIGlmIChncmFwaHMubGVuZ3RoID09IDApXG4gICAgICAgIHJldHVybjtcbiAgICBjYWxjdWxhdGVfYmIoZ3JhcGhzKTtcbiAgICBhcHBseShncmFwaHMsIGRlc2lyZWRfcmF0aW8pO1xuICAgIGlmIChjZW50ZXJHcmFwaCkge1xuICAgICAgICBwdXRfbm9kZXNfdG9fcmlnaHRfcG9zaXRpb25zKGdyYXBocyk7XG4gICAgfVxuICAgIGZ1bmN0aW9uIGNhbGN1bGF0ZV9iYihncmFwaHMpIHtcbiAgICAgICAgZ3JhcGhzLmZvckVhY2goZnVuY3Rpb24gKGcpIHtcbiAgICAgICAgICAgIGNhbGN1bGF0ZV9zaW5nbGVfYmIoZyk7XG4gICAgICAgIH0pO1xuICAgICAgICBmdW5jdGlvbiBjYWxjdWxhdGVfc2luZ2xlX2JiKGdyYXBoKSB7XG4gICAgICAgICAgICB2YXIgbWluX3ggPSBOdW1iZXIuTUFYX1ZBTFVFLCBtaW5feSA9IE51bWJlci5NQVhfVkFMVUUsIG1heF94ID0gMCwgbWF4X3kgPSAwO1xuICAgICAgICAgICAgZ3JhcGguYXJyYXkuZm9yRWFjaChmdW5jdGlvbiAodikge1xuICAgICAgICAgICAgICAgIHZhciB3ID0gdHlwZW9mIHYud2lkdGggIT09ICd1bmRlZmluZWQnID8gdi53aWR0aCA6IG5vZGVfc2l6ZTtcbiAgICAgICAgICAgICAgICB2YXIgaCA9IHR5cGVvZiB2LmhlaWdodCAhPT0gJ3VuZGVmaW5lZCcgPyB2LmhlaWdodCA6IG5vZGVfc2l6ZTtcbiAgICAgICAgICAgICAgICB3IC89IDI7XG4gICAgICAgICAgICAgICAgaCAvPSAyO1xuICAgICAgICAgICAgICAgIG1heF94ID0gTWF0aC5tYXgodi54ICsgdywgbWF4X3gpO1xuICAgICAgICAgICAgICAgIG1pbl94ID0gTWF0aC5taW4odi54IC0gdywgbWluX3gpO1xuICAgICAgICAgICAgICAgIG1heF95ID0gTWF0aC5tYXgodi55ICsgaCwgbWF4X3kpO1xuICAgICAgICAgICAgICAgIG1pbl95ID0gTWF0aC5taW4odi55IC0gaCwgbWluX3kpO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICBncmFwaC53aWR0aCA9IG1heF94IC0gbWluX3g7XG4gICAgICAgICAgICBncmFwaC5oZWlnaHQgPSBtYXhfeSAtIG1pbl95O1xuICAgICAgICB9XG4gICAgfVxuICAgIGZ1bmN0aW9uIHB1dF9ub2Rlc190b19yaWdodF9wb3NpdGlvbnMoZ3JhcGhzKSB7XG4gICAgICAgIGdyYXBocy5mb3JFYWNoKGZ1bmN0aW9uIChnKSB7XG4gICAgICAgICAgICB2YXIgY2VudGVyID0geyB4OiAwLCB5OiAwIH07XG4gICAgICAgICAgICBnLmFycmF5LmZvckVhY2goZnVuY3Rpb24gKG5vZGUpIHtcbiAgICAgICAgICAgICAgICBjZW50ZXIueCArPSBub2RlLng7XG4gICAgICAgICAgICAgICAgY2VudGVyLnkgKz0gbm9kZS55O1xuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICBjZW50ZXIueCAvPSBnLmFycmF5Lmxlbmd0aDtcbiAgICAgICAgICAgIGNlbnRlci55IC89IGcuYXJyYXkubGVuZ3RoO1xuICAgICAgICAgICAgdmFyIGNvcm5lciA9IHsgeDogY2VudGVyLnggLSBnLndpZHRoIC8gMiwgeTogY2VudGVyLnkgLSBnLmhlaWdodCAvIDIgfTtcbiAgICAgICAgICAgIHZhciBvZmZzZXQgPSB7IHg6IGcueCAtIGNvcm5lci54ICsgc3ZnX3dpZHRoIC8gMiAtIHJlYWxfd2lkdGggLyAyLCB5OiBnLnkgLSBjb3JuZXIueSArIHN2Z19oZWlnaHQgLyAyIC0gcmVhbF9oZWlnaHQgLyAyIH07XG4gICAgICAgICAgICBnLmFycmF5LmZvckVhY2goZnVuY3Rpb24gKG5vZGUpIHtcbiAgICAgICAgICAgICAgICBub2RlLnggKz0gb2Zmc2V0Lng7XG4gICAgICAgICAgICAgICAgbm9kZS55ICs9IG9mZnNldC55O1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH0pO1xuICAgIH1cbiAgICBmdW5jdGlvbiBhcHBseShkYXRhLCBkZXNpcmVkX3JhdGlvKSB7XG4gICAgICAgIHZhciBjdXJyX2Jlc3RfZiA9IE51bWJlci5QT1NJVElWRV9JTkZJTklUWTtcbiAgICAgICAgdmFyIGN1cnJfYmVzdCA9IDA7XG4gICAgICAgIGRhdGEuc29ydChmdW5jdGlvbiAoYSwgYikgeyByZXR1cm4gYi5oZWlnaHQgLSBhLmhlaWdodDsgfSk7XG4gICAgICAgIG1pbl93aWR0aCA9IGRhdGEucmVkdWNlKGZ1bmN0aW9uIChhLCBiKSB7XG4gICAgICAgICAgICByZXR1cm4gYS53aWR0aCA8IGIud2lkdGggPyBhLndpZHRoIDogYi53aWR0aDtcbiAgICAgICAgfSk7XG4gICAgICAgIHZhciBsZWZ0ID0geDEgPSBtaW5fd2lkdGg7XG4gICAgICAgIHZhciByaWdodCA9IHgyID0gZ2V0X2VudGlyZV93aWR0aChkYXRhKTtcbiAgICAgICAgdmFyIGl0ZXJhdGlvbkNvdW50ZXIgPSAwO1xuICAgICAgICB2YXIgZl94MSA9IE51bWJlci5NQVhfVkFMVUU7XG4gICAgICAgIHZhciBmX3gyID0gTnVtYmVyLk1BWF9WQUxVRTtcbiAgICAgICAgdmFyIGZsYWcgPSAtMTtcbiAgICAgICAgdmFyIGR4ID0gTnVtYmVyLk1BWF9WQUxVRTtcbiAgICAgICAgdmFyIGRmID0gTnVtYmVyLk1BWF9WQUxVRTtcbiAgICAgICAgd2hpbGUgKChkeCA+IG1pbl93aWR0aCkgfHwgZGYgPiBwYWNraW5nT3B0aW9ucy5GTE9BVF9FUFNJTE9OKSB7XG4gICAgICAgICAgICBpZiAoZmxhZyAhPSAxKSB7XG4gICAgICAgICAgICAgICAgdmFyIHgxID0gcmlnaHQgLSAocmlnaHQgLSBsZWZ0KSAvIHBhY2tpbmdPcHRpb25zLkdPTERFTl9TRUNUSU9OO1xuICAgICAgICAgICAgICAgIHZhciBmX3gxID0gc3RlcChkYXRhLCB4MSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoZmxhZyAhPSAwKSB7XG4gICAgICAgICAgICAgICAgdmFyIHgyID0gbGVmdCArIChyaWdodCAtIGxlZnQpIC8gcGFja2luZ09wdGlvbnMuR09MREVOX1NFQ1RJT047XG4gICAgICAgICAgICAgICAgdmFyIGZfeDIgPSBzdGVwKGRhdGEsIHgyKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGR4ID0gTWF0aC5hYnMoeDEgLSB4Mik7XG4gICAgICAgICAgICBkZiA9IE1hdGguYWJzKGZfeDEgLSBmX3gyKTtcbiAgICAgICAgICAgIGlmIChmX3gxIDwgY3Vycl9iZXN0X2YpIHtcbiAgICAgICAgICAgICAgICBjdXJyX2Jlc3RfZiA9IGZfeDE7XG4gICAgICAgICAgICAgICAgY3Vycl9iZXN0ID0geDE7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoZl94MiA8IGN1cnJfYmVzdF9mKSB7XG4gICAgICAgICAgICAgICAgY3Vycl9iZXN0X2YgPSBmX3gyO1xuICAgICAgICAgICAgICAgIGN1cnJfYmVzdCA9IHgyO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKGZfeDEgPiBmX3gyKSB7XG4gICAgICAgICAgICAgICAgbGVmdCA9IHgxO1xuICAgICAgICAgICAgICAgIHgxID0geDI7XG4gICAgICAgICAgICAgICAgZl94MSA9IGZfeDI7XG4gICAgICAgICAgICAgICAgZmxhZyA9IDE7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICByaWdodCA9IHgyO1xuICAgICAgICAgICAgICAgIHgyID0geDE7XG4gICAgICAgICAgICAgICAgZl94MiA9IGZfeDE7XG4gICAgICAgICAgICAgICAgZmxhZyA9IDA7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoaXRlcmF0aW9uQ291bnRlcisrID4gMTAwKSB7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgc3RlcChkYXRhLCBjdXJyX2Jlc3QpO1xuICAgIH1cbiAgICBmdW5jdGlvbiBzdGVwKGRhdGEsIG1heF93aWR0aCkge1xuICAgICAgICBsaW5lID0gW107XG4gICAgICAgIHJlYWxfd2lkdGggPSAwO1xuICAgICAgICByZWFsX2hlaWdodCA9IDA7XG4gICAgICAgIGdsb2JhbF9ib3R0b20gPSBpbml0X3k7XG4gICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgZGF0YS5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgdmFyIG8gPSBkYXRhW2ldO1xuICAgICAgICAgICAgcHV0X3JlY3QobywgbWF4X3dpZHRoKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gTWF0aC5hYnMoZ2V0X3JlYWxfcmF0aW8oKSAtIGRlc2lyZWRfcmF0aW8pO1xuICAgIH1cbiAgICBmdW5jdGlvbiBwdXRfcmVjdChyZWN0LCBtYXhfd2lkdGgpIHtcbiAgICAgICAgdmFyIHBhcmVudCA9IHVuZGVmaW5lZDtcbiAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBsaW5lLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICBpZiAoKGxpbmVbaV0uc3BhY2VfbGVmdCA+PSByZWN0LmhlaWdodCkgJiYgKGxpbmVbaV0ueCArIGxpbmVbaV0ud2lkdGggKyByZWN0LndpZHRoICsgcGFja2luZ09wdGlvbnMuUEFERElORyAtIG1heF93aWR0aCkgPD0gcGFja2luZ09wdGlvbnMuRkxPQVRfRVBTSUxPTikge1xuICAgICAgICAgICAgICAgIHBhcmVudCA9IGxpbmVbaV07XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgbGluZS5wdXNoKHJlY3QpO1xuICAgICAgICBpZiAocGFyZW50ICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgIHJlY3QueCA9IHBhcmVudC54ICsgcGFyZW50LndpZHRoICsgcGFja2luZ09wdGlvbnMuUEFERElORztcbiAgICAgICAgICAgIHJlY3QueSA9IHBhcmVudC5ib3R0b207XG4gICAgICAgICAgICByZWN0LnNwYWNlX2xlZnQgPSByZWN0LmhlaWdodDtcbiAgICAgICAgICAgIHJlY3QuYm90dG9tID0gcmVjdC55O1xuICAgICAgICAgICAgcGFyZW50LnNwYWNlX2xlZnQgLT0gcmVjdC5oZWlnaHQgKyBwYWNraW5nT3B0aW9ucy5QQURESU5HO1xuICAgICAgICAgICAgcGFyZW50LmJvdHRvbSArPSByZWN0LmhlaWdodCArIHBhY2tpbmdPcHRpb25zLlBBRERJTkc7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICByZWN0LnkgPSBnbG9iYWxfYm90dG9tO1xuICAgICAgICAgICAgZ2xvYmFsX2JvdHRvbSArPSByZWN0LmhlaWdodCArIHBhY2tpbmdPcHRpb25zLlBBRERJTkc7XG4gICAgICAgICAgICByZWN0LnggPSBpbml0X3g7XG4gICAgICAgICAgICByZWN0LmJvdHRvbSA9IHJlY3QueTtcbiAgICAgICAgICAgIHJlY3Quc3BhY2VfbGVmdCA9IHJlY3QuaGVpZ2h0O1xuICAgICAgICB9XG4gICAgICAgIGlmIChyZWN0LnkgKyByZWN0LmhlaWdodCAtIHJlYWxfaGVpZ2h0ID4gLXBhY2tpbmdPcHRpb25zLkZMT0FUX0VQU0lMT04pXG4gICAgICAgICAgICByZWFsX2hlaWdodCA9IHJlY3QueSArIHJlY3QuaGVpZ2h0IC0gaW5pdF95O1xuICAgICAgICBpZiAocmVjdC54ICsgcmVjdC53aWR0aCAtIHJlYWxfd2lkdGggPiAtcGFja2luZ09wdGlvbnMuRkxPQVRfRVBTSUxPTilcbiAgICAgICAgICAgIHJlYWxfd2lkdGggPSByZWN0LnggKyByZWN0LndpZHRoIC0gaW5pdF94O1xuICAgIH1cbiAgICA7XG4gICAgZnVuY3Rpb24gZ2V0X2VudGlyZV93aWR0aChkYXRhKSB7XG4gICAgICAgIHZhciB3aWR0aCA9IDA7XG4gICAgICAgIGRhdGEuZm9yRWFjaChmdW5jdGlvbiAoZCkgeyByZXR1cm4gd2lkdGggKz0gZC53aWR0aCArIHBhY2tpbmdPcHRpb25zLlBBRERJTkc7IH0pO1xuICAgICAgICByZXR1cm4gd2lkdGg7XG4gICAgfVxuICAgIGZ1bmN0aW9uIGdldF9yZWFsX3JhdGlvKCkge1xuICAgICAgICByZXR1cm4gKHJlYWxfd2lkdGggLyByZWFsX2hlaWdodCk7XG4gICAgfVxufVxuZXhwb3J0cy5hcHBseVBhY2tpbmcgPSBhcHBseVBhY2tpbmc7XG5mdW5jdGlvbiBzZXBhcmF0ZUdyYXBocyhub2RlcywgbGlua3MpIHtcbiAgICB2YXIgbWFya3MgPSB7fTtcbiAgICB2YXIgd2F5cyA9IHt9O1xuICAgIHZhciBncmFwaHMgPSBbXTtcbiAgICB2YXIgY2x1c3RlcnMgPSAwO1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbGlua3MubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgdmFyIGxpbmsgPSBsaW5rc1tpXTtcbiAgICAgICAgdmFyIG4xID0gbGluay5zb3VyY2U7XG4gICAgICAgIHZhciBuMiA9IGxpbmsudGFyZ2V0O1xuICAgICAgICBpZiAod2F5c1tuMS5pbmRleF0pXG4gICAgICAgICAgICB3YXlzW24xLmluZGV4XS5wdXNoKG4yKTtcbiAgICAgICAgZWxzZVxuICAgICAgICAgICAgd2F5c1tuMS5pbmRleF0gPSBbbjJdO1xuICAgICAgICBpZiAod2F5c1tuMi5pbmRleF0pXG4gICAgICAgICAgICB3YXlzW24yLmluZGV4XS5wdXNoKG4xKTtcbiAgICAgICAgZWxzZVxuICAgICAgICAgICAgd2F5c1tuMi5pbmRleF0gPSBbbjFdO1xuICAgIH1cbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IG5vZGVzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHZhciBub2RlID0gbm9kZXNbaV07XG4gICAgICAgIGlmIChtYXJrc1tub2RlLmluZGV4XSlcbiAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICBleHBsb3JlX25vZGUobm9kZSwgdHJ1ZSk7XG4gICAgfVxuICAgIGZ1bmN0aW9uIGV4cGxvcmVfbm9kZShuLCBpc19uZXcpIHtcbiAgICAgICAgaWYgKG1hcmtzW24uaW5kZXhdICE9PSB1bmRlZmluZWQpXG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIGlmIChpc19uZXcpIHtcbiAgICAgICAgICAgIGNsdXN0ZXJzKys7XG4gICAgICAgICAgICBncmFwaHMucHVzaCh7IGFycmF5OiBbXSB9KTtcbiAgICAgICAgfVxuICAgICAgICBtYXJrc1tuLmluZGV4XSA9IGNsdXN0ZXJzO1xuICAgICAgICBncmFwaHNbY2x1c3RlcnMgLSAxXS5hcnJheS5wdXNoKG4pO1xuICAgICAgICB2YXIgYWRqYWNlbnQgPSB3YXlzW24uaW5kZXhdO1xuICAgICAgICBpZiAoIWFkamFjZW50KVxuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICBmb3IgKHZhciBqID0gMDsgaiA8IGFkamFjZW50Lmxlbmd0aDsgaisrKSB7XG4gICAgICAgICAgICBleHBsb3JlX25vZGUoYWRqYWNlbnRbal0sIGZhbHNlKTtcbiAgICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gZ3JhcGhzO1xufVxuZXhwb3J0cy5zZXBhcmF0ZUdyYXBocyA9IHNlcGFyYXRlR3JhcGhzO1xuLy8jIHNvdXJjZU1hcHBpbmdVUkw9ZGF0YTphcHBsaWNhdGlvbi9qc29uO2Jhc2U2NCxleUoyWlhKemFXOXVJam96TENKbWFXeGxJam9pYUdGdVpHeGxaR2x6WTI5dWJtVmpkR1ZrTG1weklpd2ljMjkxY21ObFVtOXZkQ0k2SWlJc0luTnZkWEpqWlhNaU9sc2lMaTR2TGk0dlYyVmlRMjlzWVM5emNtTXZhR0Z1Wkd4bFpHbHpZMjl1Ym1WamRHVmtMblJ6SWwwc0ltNWhiV1Z6SWpwYlhTd2liV0Z3Y0dsdVozTWlPaUk3TzBGQlFVa3NTVUZCU1N4alFVRmpMRWRCUVVjN1NVRkRha0lzVDBGQlR5eEZRVUZGTEVWQlFVVTdTVUZEV0N4alFVRmpMRVZCUVVVc1EwRkJReXhEUVVGRExFZEJRVWNzU1VGQlNTeERRVUZETEVsQlFVa3NRMEZCUXl4RFFVRkRMRU5CUVVNc1EwRkJReXhIUVVGSExFTkJRVU03U1VGRGRFTXNZVUZCWVN4RlFVRkZMRTFCUVUwN1NVRkRja0lzWTBGQll5eEZRVUZGTEVkQlFVYzdRMEZEZEVJc1EwRkJRenRCUVVkR0xGTkJRV2RDTEZsQlFWa3NRMEZCUXl4TlFVRnBRaXhGUVVGRkxFTkJRVU1zUlVGQlJTeERRVUZETEVWQlFVVXNVMEZCVXl4RlFVRkZMR0ZCUVdsQ0xFVkJRVVVzVjBGQmEwSTdTVUZCY2tNc09FSkJRVUVzUlVGQlFTeHBRa0ZCYVVJN1NVRkJSU3cwUWtGQlFTeEZRVUZCTEd0Q1FVRnJRanRKUVVWc1J5eEpRVUZKTEUxQlFVMHNSMEZCUnl4RFFVRkRMRVZCUTFZc1RVRkJUU3hIUVVGSExFTkJRVU1zUlVGRlZpeFRRVUZUTEVkQlFVY3NRMEZCUXl4RlFVTmlMRlZCUVZVc1IwRkJSeXhEUVVGRExFVkJSV1FzWVVGQllTeEhRVUZITEU5QlFVOHNZVUZCWVN4TFFVRkxMRmRCUVZjc1EwRkJReXhEUVVGRExFTkJRVU1zWVVGQllTeERRVUZETEVOQlFVTXNRMEZCUXl4RFFVRkRMRVZCUTNoRkxGTkJRVk1zUjBGQlJ5eFBRVUZQTEZOQlFWTXNTMEZCU3l4WFFVRlhMRU5CUVVNc1EwRkJReXhEUVVGRExGTkJRVk1zUTBGQlF5eERRVUZETEVOQlFVTXNRMEZCUXl4RlFVVTFSQ3hWUVVGVkxFZEJRVWNzUTBGQlF5eEZRVU5rTEZkQlFWY3NSMEZCUnl4RFFVRkRMRVZCUTJZc1UwRkJVeXhIUVVGSExFTkJRVU1zUlVGRllpeGhRVUZoTEVkQlFVY3NRMEZCUXl4RlFVTnFRaXhKUVVGSkxFZEJRVWNzUlVGQlJTeERRVUZETzBsQlJXUXNTVUZCU1N4TlFVRk5MRU5CUVVNc1RVRkJUU3hKUVVGSkxFTkJRVU03VVVGRGJFSXNUMEZCVHp0SlFWVllMRmxCUVZrc1EwRkJReXhOUVVGTkxFTkJRVU1zUTBGQlF6dEpRVU55UWl4TFFVRkxMRU5CUVVNc1RVRkJUU3hGUVVGRkxHRkJRV0VzUTBGQlF5eERRVUZETzBsQlF6ZENMRWxCUVVjc1YwRkJWeXhGUVVGRk8xRkJRMW9zTkVKQlFUUkNMRU5CUVVNc1RVRkJUU3hEUVVGRExFTkJRVU03UzBGRGVFTTdTVUZIUkN4VFFVRlRMRmxCUVZrc1EwRkJReXhOUVVGTk8xRkJSWGhDTEUxQlFVMHNRMEZCUXl4UFFVRlBMRU5CUVVNc1ZVRkJWU3hEUVVGRE8xbEJRM1JDTEcxQ1FVRnRRaXhEUVVGRExFTkJRVU1zUTBGQlF5eERRVUZCTzFGQlF6RkNMRU5CUVVNc1EwRkJReXhEUVVGRE8xRkJSVWdzVTBGQlV5eHRRa0ZCYlVJc1EwRkJReXhMUVVGTE8xbEJRemxDTEVsQlFVa3NTMEZCU3l4SFFVRkhMRTFCUVUwc1EwRkJReXhUUVVGVExFVkJRVVVzUzBGQlN5eEhRVUZITEUxQlFVMHNRMEZCUXl4VFFVRlRMRVZCUTJ4RUxFdEJRVXNzUjBGQlJ5eERRVUZETEVWQlFVVXNTMEZCU3l4SFFVRkhMRU5CUVVNc1EwRkJRenRaUVVWNlFpeExRVUZMTEVOQlFVTXNTMEZCU3l4RFFVRkRMRTlCUVU4c1EwRkJReXhWUVVGVkxFTkJRVU03WjBKQlF6TkNMRWxCUVVrc1EwRkJReXhIUVVGSExFOUJRVThzUTBGQlF5eERRVUZETEV0QlFVc3NTMEZCU3l4WFFVRlhMRU5CUVVNc1EwRkJReXhEUVVGRExFTkJRVU1zUTBGQlF5eExRVUZMTEVOQlFVTXNRMEZCUXl4RFFVRkRMRk5CUVZNc1EwRkJRenRuUWtGRE4wUXNTVUZCU1N4RFFVRkRMRWRCUVVjc1QwRkJUeXhEUVVGRExFTkJRVU1zVFVGQlRTeExRVUZMTEZkQlFWY3NRMEZCUXl4RFFVRkRMRU5CUVVNc1EwRkJReXhEUVVGRExFMUJRVTBzUTBGQlF5eERRVUZETEVOQlFVTXNVMEZCVXl4RFFVRkRPMmRDUVVNdlJDeERRVUZETEVsQlFVa3NRMEZCUXl4RFFVRkRPMmRDUVVOUUxFTkJRVU1zU1VGQlNTeERRVUZETEVOQlFVTTdaMEpCUTFBc1MwRkJTeXhIUVVGSExFbEJRVWtzUTBGQlF5eEhRVUZITEVOQlFVTXNRMEZCUXl4RFFVRkRMRU5CUVVNc1IwRkJSeXhEUVVGRExFVkJRVVVzUzBGQlN5eERRVUZETEVOQlFVTTdaMEpCUTJwRExFdEJRVXNzUjBGQlJ5eEpRVUZKTEVOQlFVTXNSMEZCUnl4RFFVRkRMRU5CUVVNc1EwRkJReXhEUVVGRExFZEJRVWNzUTBGQlF5eEZRVUZGTEV0QlFVc3NRMEZCUXl4RFFVRkRPMmRDUVVOcVF5eExRVUZMTEVkQlFVY3NTVUZCU1N4RFFVRkRMRWRCUVVjc1EwRkJReXhEUVVGRExFTkJRVU1zUTBGQlF5eEhRVUZITEVOQlFVTXNSVUZCUlN4TFFVRkxMRU5CUVVNc1EwRkJRenRuUWtGRGFrTXNTMEZCU3l4SFFVRkhMRWxCUVVrc1EwRkJReXhIUVVGSExFTkJRVU1zUTBGQlF5eERRVUZETEVOQlFVTXNSMEZCUnl4RFFVRkRMRVZCUVVVc1MwRkJTeXhEUVVGRExFTkJRVU03V1VGRGNrTXNRMEZCUXl4RFFVRkRMRU5CUVVNN1dVRkZTQ3hMUVVGTExFTkJRVU1zUzBGQlN5eEhRVUZITEV0QlFVc3NSMEZCUnl4TFFVRkxMRU5CUVVNN1dVRkROVUlzUzBGQlN5eERRVUZETEUxQlFVMHNSMEZCUnl4TFFVRkxMRWRCUVVjc1MwRkJTeXhEUVVGRE8xRkJRMnBETEVOQlFVTTdTVUZEVEN4RFFVRkRPMGxCZFVORUxGTkJRVk1zTkVKQlFUUkNMRU5CUVVNc1RVRkJUVHRSUVVONFF5eE5RVUZOTEVOQlFVTXNUMEZCVHl4RFFVRkRMRlZCUVZVc1EwRkJRenRaUVVWMFFpeEpRVUZKTEUxQlFVMHNSMEZCUnl4RlFVRkZMRU5CUVVNc1JVRkJSU3hEUVVGRExFVkJRVVVzUTBGQlF5eEZRVUZGTEVOQlFVTXNSVUZCUlN4RFFVRkRPMWxCUlRWQ0xFTkJRVU1zUTBGQlF5eExRVUZMTEVOQlFVTXNUMEZCVHl4RFFVRkRMRlZCUVZVc1NVRkJTVHRuUWtGRE1VSXNUVUZCVFN4RFFVRkRMRU5CUVVNc1NVRkJTU3hKUVVGSkxFTkJRVU1zUTBGQlF5eERRVUZETzJkQ1FVTnVRaXhOUVVGTkxFTkJRVU1zUTBGQlF5eEpRVUZKTEVsQlFVa3NRMEZCUXl4RFFVRkRMRU5CUVVNN1dVRkRka0lzUTBGQlF5eERRVUZETEVOQlFVTTdXVUZGU0N4TlFVRk5MRU5CUVVNc1EwRkJReXhKUVVGSkxFTkJRVU1zUTBGQlF5eExRVUZMTEVOQlFVTXNUVUZCVFN4RFFVRkRPMWxCUXpOQ0xFMUJRVTBzUTBGQlF5eERRVUZETEVsQlFVa3NRMEZCUXl4RFFVRkRMRXRCUVVzc1EwRkJReXhOUVVGTkxFTkJRVU03V1VGSE0wSXNTVUZCU1N4TlFVRk5MRWRCUVVjc1JVRkJSU3hEUVVGRExFVkJRVVVzVFVGQlRTeERRVUZETEVOQlFVTXNSMEZCUnl4RFFVRkRMRU5CUVVNc1MwRkJTeXhIUVVGSExFTkJRVU1zUlVGQlJTeERRVUZETEVWQlFVVXNUVUZCVFN4RFFVRkRMRU5CUVVNc1IwRkJSeXhEUVVGRExFTkJRVU1zVFVGQlRTeEhRVUZITEVOQlFVTXNSVUZCUlN4RFFVRkRPMWxCUTNaRkxFbEJRVWtzVFVGQlRTeEhRVUZITEVWQlFVVXNRMEZCUXl4RlFVRkZMRU5CUVVNc1EwRkJReXhEUVVGRExFZEJRVWNzVFVGQlRTeERRVUZETEVOQlFVTXNSMEZCUnl4VFFVRlRMRWRCUVVjc1EwRkJReXhIUVVGSExGVkJRVlVzUjBGQlJ5eERRVUZETEVWQlFVVXNRMEZCUXl4RlFVRkZMRU5CUVVNc1EwRkJReXhEUVVGRExFZEJRVWNzVFVGQlRTeERRVUZETEVOQlFVTXNSMEZCUnl4VlFVRlZMRWRCUVVjc1EwRkJReXhIUVVGSExGZEJRVmNzUjBGQlJ5eERRVUZETEVWQlFVTXNRMEZCUXp0WlFVZDZTQ3hEUVVGRExFTkJRVU1zUzBGQlN5eERRVUZETEU5QlFVOHNRMEZCUXl4VlFVRlZMRWxCUVVrN1owSkJRekZDTEVsQlFVa3NRMEZCUXl4RFFVRkRMRWxCUVVrc1RVRkJUU3hEUVVGRExFTkJRVU1zUTBGQlF6dG5Ra0ZEYmtJc1NVRkJTU3hEUVVGRExFTkJRVU1zU1VGQlNTeE5RVUZOTEVOQlFVTXNRMEZCUXl4RFFVRkRPMWxCUTNaQ0xFTkJRVU1zUTBGQlF5eERRVUZETzFGQlExQXNRMEZCUXl4RFFVRkRMRU5CUVVNN1NVRkRVQ3hEUVVGRE8wbEJTVVFzVTBGQlV5eExRVUZMTEVOQlFVTXNTVUZCU1N4RlFVRkZMR0ZCUVdFN1VVRkRPVUlzU1VGQlNTeFhRVUZYTEVkQlFVY3NUVUZCVFN4RFFVRkRMR2xDUVVGcFFpeERRVUZETzFGQlF6TkRMRWxCUVVrc1UwRkJVeXhIUVVGSExFTkJRVU1zUTBGQlF6dFJRVU5zUWl4SlFVRkpMRU5CUVVNc1NVRkJTU3hEUVVGRExGVkJRVlVzUTBGQlF5eEZRVUZGTEVOQlFVTXNTVUZCU1N4UFFVRlBMRU5CUVVNc1EwRkJReXhOUVVGTkxFZEJRVWNzUTBGQlF5eERRVUZETEUxQlFVMHNRMEZCUXl4RFFVRkRMRU5CUVVNc1EwRkJReXhEUVVGRE8xRkJSVE5FTEZOQlFWTXNSMEZCUnl4SlFVRkpMRU5CUVVNc1RVRkJUU3hEUVVGRExGVkJRVlVzUTBGQlF5eEZRVUZGTEVOQlFVTTdXVUZEYkVNc1QwRkJUeXhEUVVGRExFTkJRVU1zUzBGQlN5eEhRVUZITEVOQlFVTXNRMEZCUXl4TFFVRkxMRU5CUVVNc1EwRkJReXhEUVVGRExFTkJRVU1zUTBGQlF5eExRVUZMTEVOQlFVTXNRMEZCUXl4RFFVRkRMRU5CUVVNc1EwRkJReXhMUVVGTExFTkJRVU03VVVGRGFrUXNRMEZCUXl4RFFVRkRMRU5CUVVNN1VVRkZTQ3hKUVVGSkxFbEJRVWtzUjBGQlJ5eEZRVUZGTEVkQlFVY3NVMEZCVXl4RFFVRkRPMUZCUXpGQ0xFbEJRVWtzUzBGQlN5eEhRVUZITEVWQlFVVXNSMEZCUnl4blFrRkJaMElzUTBGQlF5eEpRVUZKTEVOQlFVTXNRMEZCUXp0UlFVTjRReXhKUVVGSkxHZENRVUZuUWl4SFFVRkhMRU5CUVVNc1EwRkJRenRSUVVWNlFpeEpRVUZKTEVsQlFVa3NSMEZCUnl4TlFVRk5MRU5CUVVNc1UwRkJVeXhEUVVGRE8xRkJRelZDTEVsQlFVa3NTVUZCU1N4SFFVRkhMRTFCUVUwc1EwRkJReXhUUVVGVExFTkJRVU03VVVGRE5VSXNTVUZCU1N4SlFVRkpMRWRCUVVjc1EwRkJReXhEUVVGRExFTkJRVU03VVVGSFpDeEpRVUZKTEVWQlFVVXNSMEZCUnl4TlFVRk5MRU5CUVVNc1UwRkJVeXhEUVVGRE8xRkJRekZDTEVsQlFVa3NSVUZCUlN4SFFVRkhMRTFCUVUwc1EwRkJReXhUUVVGVExFTkJRVU03VVVGRk1VSXNUMEZCVHl4RFFVRkRMRVZCUVVVc1IwRkJSeXhUUVVGVExFTkJRVU1zU1VGQlNTeEZRVUZGTEVkQlFVY3NZMEZCWXl4RFFVRkRMR0ZCUVdFc1JVRkJSVHRaUVVVeFJDeEpRVUZKTEVsQlFVa3NTVUZCU1N4RFFVRkRMRVZCUVVVN1owSkJRMWdzU1VGQlNTeEZRVUZGTEVkQlFVY3NTMEZCU3l4SFFVRkhMRU5CUVVNc1MwRkJTeXhIUVVGSExFbEJRVWtzUTBGQlF5eEhRVUZITEdOQlFXTXNRMEZCUXl4alFVRmpMRU5CUVVNN1owSkJRMmhGTEVsQlFVa3NTVUZCU1N4SFFVRkhMRWxCUVVrc1EwRkJReXhKUVVGSkxFVkJRVVVzUlVGQlJTeERRVUZETEVOQlFVTTdZVUZETjBJN1dVRkRSQ3hKUVVGSkxFbEJRVWtzU1VGQlNTeERRVUZETEVWQlFVVTdaMEpCUTFnc1NVRkJTU3hGUVVGRkxFZEJRVWNzU1VGQlNTeEhRVUZITEVOQlFVTXNTMEZCU3l4SFFVRkhMRWxCUVVrc1EwRkJReXhIUVVGSExHTkJRV01zUTBGQlF5eGpRVUZqTEVOQlFVTTdaMEpCUXk5RUxFbEJRVWtzU1VGQlNTeEhRVUZITEVsQlFVa3NRMEZCUXl4SlFVRkpMRVZCUVVVc1JVRkJSU3hEUVVGRExFTkJRVU03WVVGRE4wSTdXVUZGUkN4RlFVRkZMRWRCUVVjc1NVRkJTU3hEUVVGRExFZEJRVWNzUTBGQlF5eEZRVUZGTEVkQlFVY3NSVUZCUlN4RFFVRkRMRU5CUVVNN1dVRkRka0lzUlVGQlJTeEhRVUZITEVsQlFVa3NRMEZCUXl4SFFVRkhMRU5CUVVNc1NVRkJTU3hIUVVGSExFbEJRVWtzUTBGQlF5eERRVUZETzFsQlJUTkNMRWxCUVVrc1NVRkJTU3hIUVVGSExGZEJRVmNzUlVGQlJUdG5Ra0ZEY0VJc1YwRkJWeXhIUVVGSExFbEJRVWtzUTBGQlF6dG5Ra0ZEYmtJc1UwRkJVeXhIUVVGSExFVkJRVVVzUTBGQlF6dGhRVU5zUWp0WlFVVkVMRWxCUVVrc1NVRkJTU3hIUVVGSExGZEJRVmNzUlVGQlJUdG5Ra0ZEY0VJc1YwRkJWeXhIUVVGSExFbEJRVWtzUTBGQlF6dG5Ra0ZEYmtJc1UwRkJVeXhIUVVGSExFVkJRVVVzUTBGQlF6dGhRVU5zUWp0WlFVVkVMRWxCUVVrc1NVRkJTU3hIUVVGSExFbEJRVWtzUlVGQlJUdG5Ra0ZEWWl4SlFVRkpMRWRCUVVjc1JVRkJSU3hEUVVGRE8yZENRVU5XTEVWQlFVVXNSMEZCUnl4RlFVRkZMRU5CUVVNN1owSkJRMUlzU1VGQlNTeEhRVUZITEVsQlFVa3NRMEZCUXp0blFrRkRXaXhKUVVGSkxFZEJRVWNzUTBGQlF5eERRVUZETzJGQlExbzdhVUpCUVUwN1owSkJRMGdzUzBGQlN5eEhRVUZITEVWQlFVVXNRMEZCUXp0blFrRkRXQ3hGUVVGRkxFZEJRVWNzUlVGQlJTeERRVUZETzJkQ1FVTlNMRWxCUVVrc1IwRkJSeXhKUVVGSkxFTkJRVU03WjBKQlExb3NTVUZCU1N4SFFVRkhMRU5CUVVNc1EwRkJRenRoUVVOYU8xbEJSVVFzU1VGQlNTeG5Ra0ZCWjBJc1JVRkJSU3hIUVVGSExFZEJRVWNzUlVGQlJUdG5Ra0ZETVVJc1RVRkJUVHRoUVVOVU8xTkJRMG83VVVGRlJDeEpRVUZKTEVOQlFVTXNTVUZCU1N4RlFVRkZMRk5CUVZNc1EwRkJReXhEUVVGRE8wbEJRekZDTEVOQlFVTTdTVUZKUkN4VFFVRlRMRWxCUVVrc1EwRkJReXhKUVVGSkxFVkJRVVVzVTBGQlV6dFJRVU42UWl4SlFVRkpMRWRCUVVjc1JVRkJSU3hEUVVGRE8xRkJRMVlzVlVGQlZTeEhRVUZITEVOQlFVTXNRMEZCUXp0UlFVTm1MRmRCUVZjc1IwRkJSeXhEUVVGRExFTkJRVU03VVVGRGFFSXNZVUZCWVN4SFFVRkhMRTFCUVUwc1EwRkJRenRSUVVWMlFpeExRVUZMTEVsQlFVa3NRMEZCUXl4SFFVRkhMRU5CUVVNc1JVRkJSU3hEUVVGRExFZEJRVWNzU1VGQlNTeERRVUZETEUxQlFVMHNSVUZCUlN4RFFVRkRMRVZCUVVVc1JVRkJSVHRaUVVOc1F5eEpRVUZKTEVOQlFVTXNSMEZCUnl4SlFVRkpMRU5CUVVNc1EwRkJReXhEUVVGRExFTkJRVU03V1VGRGFFSXNVVUZCVVN4RFFVRkRMRU5CUVVNc1JVRkJSU3hUUVVGVExFTkJRVU1zUTBGQlF6dFRRVU14UWp0UlFVVkVMRTlCUVU4c1NVRkJTU3hEUVVGRExFZEJRVWNzUTBGQlF5eGpRVUZqTEVWQlFVVXNSMEZCUnl4aFFVRmhMRU5CUVVNc1EwRkJRenRKUVVOMFJDeERRVUZETzBsQlIwUXNVMEZCVXl4UlFVRlJMRU5CUVVNc1NVRkJTU3hGUVVGRkxGTkJRVk03VVVGSE4wSXNTVUZCU1N4TlFVRk5MRWRCUVVjc1UwRkJVeXhEUVVGRE8xRkJSWFpDTEV0QlFVc3NTVUZCU1N4RFFVRkRMRWRCUVVjc1EwRkJReXhGUVVGRkxFTkJRVU1zUjBGQlJ5eEpRVUZKTEVOQlFVTXNUVUZCVFN4RlFVRkZMRU5CUVVNc1JVRkJSU3hGUVVGRk8xbEJRMnhETEVsQlFVa3NRMEZCUXl4SlFVRkpMRU5CUVVNc1EwRkJReXhEUVVGRExFTkJRVU1zVlVGQlZTeEpRVUZKTEVsQlFVa3NRMEZCUXl4TlFVRk5MRU5CUVVNc1NVRkJTU3hEUVVGRExFbEJRVWtzUTBGQlF5eERRVUZETEVOQlFVTXNRMEZCUXl4RFFVRkRMRWRCUVVjc1NVRkJTU3hEUVVGRExFTkJRVU1zUTBGQlF5eERRVUZETEV0QlFVc3NSMEZCUnl4SlFVRkpMRU5CUVVNc1MwRkJTeXhIUVVGSExHTkJRV01zUTBGQlF5eFBRVUZQTEVkQlFVY3NVMEZCVXl4RFFVRkRMRWxCUVVrc1kwRkJZeXhEUVVGRExHRkJRV0VzUlVGQlJUdG5Ra0ZEZEVvc1RVRkJUU3hIUVVGSExFbEJRVWtzUTBGQlF5eERRVUZETEVOQlFVTXNRMEZCUXp0blFrRkRha0lzVFVGQlRUdGhRVU5VTzFOQlEwbzdVVUZGUkN4SlFVRkpMRU5CUVVNc1NVRkJTU3hEUVVGRExFbEJRVWtzUTBGQlF5eERRVUZETzFGQlJXaENMRWxCUVVrc1RVRkJUU3hMUVVGTExGTkJRVk1zUlVGQlJUdFpRVU4wUWl4SlFVRkpMRU5CUVVNc1EwRkJReXhIUVVGSExFMUJRVTBzUTBGQlF5eERRVUZETEVkQlFVY3NUVUZCVFN4RFFVRkRMRXRCUVVzc1IwRkJSeXhqUVVGakxFTkJRVU1zVDBGQlR5eERRVUZETzFsQlF6RkVMRWxCUVVrc1EwRkJReXhEUVVGRExFZEJRVWNzVFVGQlRTeERRVUZETEUxQlFVMHNRMEZCUXp0WlFVTjJRaXhKUVVGSkxFTkJRVU1zVlVGQlZTeEhRVUZITEVsQlFVa3NRMEZCUXl4TlFVRk5MRU5CUVVNN1dVRkRPVUlzU1VGQlNTeERRVUZETEUxQlFVMHNSMEZCUnl4SlFVRkpMRU5CUVVNc1EwRkJReXhEUVVGRE8xbEJRM0pDTEUxQlFVMHNRMEZCUXl4VlFVRlZMRWxCUVVrc1NVRkJTU3hEUVVGRExFMUJRVTBzUjBGQlJ5eGpRVUZqTEVOQlFVTXNUMEZCVHl4RFFVRkRPMWxCUXpGRUxFMUJRVTBzUTBGQlF5eE5RVUZOTEVsQlFVa3NTVUZCU1N4RFFVRkRMRTFCUVUwc1IwRkJSeXhqUVVGakxFTkJRVU1zVDBGQlR5eERRVUZETzFOQlEzcEVPMkZCUVUwN1dVRkRTQ3hKUVVGSkxFTkJRVU1zUTBGQlF5eEhRVUZITEdGQlFXRXNRMEZCUXp0WlFVTjJRaXhoUVVGaExFbEJRVWtzU1VGQlNTeERRVUZETEUxQlFVMHNSMEZCUnl4alFVRmpMRU5CUVVNc1QwRkJUeXhEUVVGRE8xbEJRM1JFTEVsQlFVa3NRMEZCUXl4RFFVRkRMRWRCUVVjc1RVRkJUU3hEUVVGRE8xbEJRMmhDTEVsQlFVa3NRMEZCUXl4TlFVRk5MRWRCUVVjc1NVRkJTU3hEUVVGRExFTkJRVU1zUTBGQlF6dFpRVU55UWl4SlFVRkpMRU5CUVVNc1ZVRkJWU3hIUVVGSExFbEJRVWtzUTBGQlF5eE5RVUZOTEVOQlFVTTdVMEZEYWtNN1VVRkZSQ3hKUVVGSkxFbEJRVWtzUTBGQlF5eERRVUZETEVkQlFVY3NTVUZCU1N4RFFVRkRMRTFCUVUwc1IwRkJSeXhYUVVGWExFZEJRVWNzUTBGQlF5eGpRVUZqTEVOQlFVTXNZVUZCWVR0WlFVRkZMRmRCUVZjc1IwRkJSeXhKUVVGSkxFTkJRVU1zUTBGQlF5eEhRVUZITEVsQlFVa3NRMEZCUXl4TlFVRk5MRWRCUVVjc1RVRkJUU3hEUVVGRE8xRkJRM0JJTEVsQlFVa3NTVUZCU1N4RFFVRkRMRU5CUVVNc1IwRkJSeXhKUVVGSkxFTkJRVU1zUzBGQlN5eEhRVUZITEZWQlFWVXNSMEZCUnl4RFFVRkRMR05CUVdNc1EwRkJReXhoUVVGaE8xbEJRVVVzVlVGQlZTeEhRVUZITEVsQlFVa3NRMEZCUXl4RFFVRkRMRWRCUVVjc1NVRkJTU3hEUVVGRExFdEJRVXNzUjBGQlJ5eE5RVUZOTEVOQlFVTTdTVUZEY0Vnc1EwRkJRenRKUVVGQkxFTkJRVU03U1VGRlJpeFRRVUZUTEdkQ1FVRm5RaXhEUVVGRExFbEJRVWs3VVVGRE1VSXNTVUZCU1N4TFFVRkxMRWRCUVVjc1EwRkJReXhEUVVGRE8xRkJRMlFzU1VGQlNTeERRVUZETEU5QlFVOHNRMEZCUXl4VlFVRlZMRU5CUVVNc1NVRkJTU3hQUVVGUExFdEJRVXNzU1VGQlNTeERRVUZETEVOQlFVTXNTMEZCU3l4SFFVRkhMR05CUVdNc1EwRkJReXhQUVVGUExFTkJRVU1zUTBGQlF5eERRVUZETEVOQlFVTXNRMEZCUXp0UlFVTnFSaXhQUVVGUExFdEJRVXNzUTBGQlF6dEpRVU5xUWl4RFFVRkRPMGxCUlVRc1UwRkJVeXhqUVVGak8xRkJRMjVDTEU5QlFVOHNRMEZCUXl4VlFVRlZMRWRCUVVjc1YwRkJWeXhEUVVGRExFTkJRVU03U1VGRGRFTXNRMEZCUXp0QlFVTk1MRU5CUVVNN1FVRXhVRVFzYjBOQk1GQkRPMEZCVFVRc1UwRkJaMElzWTBGQll5eERRVUZETEV0QlFVc3NSVUZCUlN4TFFVRkxPMGxCUTNaRExFbEJRVWtzUzBGQlN5eEhRVUZITEVWQlFVVXNRMEZCUXp0SlFVTm1MRWxCUVVrc1NVRkJTU3hIUVVGSExFVkJRVVVzUTBGQlF6dEpRVU5rTEVsQlFVa3NUVUZCVFN4SFFVRkhMRVZCUVVVc1EwRkJRenRKUVVOb1FpeEpRVUZKTEZGQlFWRXNSMEZCUnl4RFFVRkRMRU5CUVVNN1NVRkZha0lzUzBGQlN5eEpRVUZKTEVOQlFVTXNSMEZCUnl4RFFVRkRMRVZCUVVVc1EwRkJReXhIUVVGSExFdEJRVXNzUTBGQlF5eE5RVUZOTEVWQlFVVXNRMEZCUXl4RlFVRkZMRVZCUVVVN1VVRkRia01zU1VGQlNTeEpRVUZKTEVkQlFVY3NTMEZCU3l4RFFVRkRMRU5CUVVNc1EwRkJReXhEUVVGRE8xRkJRM0JDTEVsQlFVa3NSVUZCUlN4SFFVRkhMRWxCUVVrc1EwRkJReXhOUVVGTkxFTkJRVU03VVVGRGNrSXNTVUZCU1N4RlFVRkZMRWRCUVVjc1NVRkJTU3hEUVVGRExFMUJRVTBzUTBGQlF6dFJRVU55UWl4SlFVRkpMRWxCUVVrc1EwRkJReXhGUVVGRkxFTkJRVU1zUzBGQlN5eERRVUZETzFsQlEyUXNTVUZCU1N4RFFVRkRMRVZCUVVVc1EwRkJReXhMUVVGTExFTkJRVU1zUTBGQlF5eEpRVUZKTEVOQlFVTXNSVUZCUlN4RFFVRkRMRU5CUVVNN08xbEJSWGhDTEVsQlFVa3NRMEZCUXl4RlFVRkZMRU5CUVVNc1MwRkJTeXhEUVVGRExFZEJRVWNzUTBGQlF5eEZRVUZGTEVOQlFVTXNRMEZCUXp0UlFVVXhRaXhKUVVGSkxFbEJRVWtzUTBGQlF5eEZRVUZGTEVOQlFVTXNTMEZCU3l4RFFVRkRPMWxCUTJRc1NVRkJTU3hEUVVGRExFVkJRVVVzUTBGQlF5eExRVUZMTEVOQlFVTXNRMEZCUXl4SlFVRkpMRU5CUVVNc1JVRkJSU3hEUVVGRExFTkJRVU03TzFsQlJYaENMRWxCUVVrc1EwRkJReXhGUVVGRkxFTkJRVU1zUzBGQlN5eERRVUZETEVkQlFVY3NRMEZCUXl4RlFVRkZMRU5CUVVNc1EwRkJRenRMUVVNM1FqdEpRVVZFTEV0QlFVc3NTVUZCU1N4RFFVRkRMRWRCUVVjc1EwRkJReXhGUVVGRkxFTkJRVU1zUjBGQlJ5eExRVUZMTEVOQlFVTXNUVUZCVFN4RlFVRkZMRU5CUVVNc1JVRkJSU3hGUVVGRk8xRkJRMjVETEVsQlFVa3NTVUZCU1N4SFFVRkhMRXRCUVVzc1EwRkJReXhEUVVGRExFTkJRVU1zUTBGQlF6dFJRVU53UWl4SlFVRkpMRXRCUVVzc1EwRkJReXhKUVVGSkxFTkJRVU1zUzBGQlN5eERRVUZETzFsQlFVVXNVMEZCVXp0UlFVTm9ReXhaUVVGWkxFTkJRVU1zU1VGQlNTeEZRVUZGTEVsQlFVa3NRMEZCUXl4RFFVRkRPMHRCUXpWQ08wbEJSVVFzVTBGQlV5eFpRVUZaTEVOQlFVTXNRMEZCUXl4RlFVRkZMRTFCUVUwN1VVRkRNMElzU1VGQlNTeExRVUZMTEVOQlFVTXNRMEZCUXl4RFFVRkRMRXRCUVVzc1EwRkJReXhMUVVGTExGTkJRVk03V1VGQlJTeFBRVUZQTzFGQlEzcERMRWxCUVVrc1RVRkJUU3hGUVVGRk8xbEJRMUlzVVVGQlVTeEZRVUZGTEVOQlFVTTdXVUZEV0N4TlFVRk5MRU5CUVVNc1NVRkJTU3hEUVVGRExFVkJRVVVzUzBGQlN5eEZRVUZGTEVWQlFVVXNSVUZCUlN4RFFVRkRMRU5CUVVNN1UwRkRPVUk3VVVGRFJDeExRVUZMTEVOQlFVTXNRMEZCUXl4RFFVRkRMRXRCUVVzc1EwRkJReXhIUVVGSExGRkJRVkVzUTBGQlF6dFJRVU14UWl4TlFVRk5MRU5CUVVNc1VVRkJVU3hIUVVGSExFTkJRVU1zUTBGQlF5eERRVUZETEV0QlFVc3NRMEZCUXl4SlFVRkpMRU5CUVVNc1EwRkJReXhEUVVGRExFTkJRVU03VVVGRGJrTXNTVUZCU1N4UlFVRlJMRWRCUVVjc1NVRkJTU3hEUVVGRExFTkJRVU1zUTBGQlF5eExRVUZMTEVOQlFVTXNRMEZCUXp0UlFVTTNRaXhKUVVGSkxFTkJRVU1zVVVGQlVUdFpRVUZGTEU5QlFVODdVVUZGZEVJc1MwRkJTeXhKUVVGSkxFTkJRVU1zUjBGQlJ5eERRVUZETEVWQlFVVXNRMEZCUXl4SFFVRkhMRkZCUVZFc1EwRkJReXhOUVVGTkxFVkJRVVVzUTBGQlF5eEZRVUZGTEVWQlFVVTdXVUZEZEVNc1dVRkJXU3hEUVVGRExGRkJRVkVzUTBGQlF5eERRVUZETEVOQlFVTXNSVUZCUlN4TFFVRkxMRU5CUVVNc1EwRkJRenRUUVVOd1F6dEpRVU5NTEVOQlFVTTdTVUZGUkN4UFFVRlBMRTFCUVUwc1EwRkJRenRCUVVOc1FpeERRVUZETzBGQk5VTkVMSGREUVRSRFF5SjkiLCJcInVzZSBzdHJpY3RcIjtcbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCBcIl9fZXNNb2R1bGVcIiwgeyB2YWx1ZTogdHJ1ZSB9KTtcbnZhciBwb3dlcmdyYXBoID0gcmVxdWlyZShcIi4vcG93ZXJncmFwaFwiKTtcbnZhciBsaW5rbGVuZ3Roc18xID0gcmVxdWlyZShcIi4vbGlua2xlbmd0aHNcIik7XG52YXIgZGVzY2VudF8xID0gcmVxdWlyZShcIi4vZGVzY2VudFwiKTtcbnZhciByZWN0YW5nbGVfMSA9IHJlcXVpcmUoXCIuL3JlY3RhbmdsZVwiKTtcbnZhciBzaG9ydGVzdHBhdGhzXzEgPSByZXF1aXJlKFwiLi9zaG9ydGVzdHBhdGhzXCIpO1xudmFyIGdlb21fMSA9IHJlcXVpcmUoXCIuL2dlb21cIik7XG52YXIgaGFuZGxlZGlzY29ubmVjdGVkXzEgPSByZXF1aXJlKFwiLi9oYW5kbGVkaXNjb25uZWN0ZWRcIik7XG52YXIgRXZlbnRUeXBlO1xuKGZ1bmN0aW9uIChFdmVudFR5cGUpIHtcbiAgICBFdmVudFR5cGVbRXZlbnRUeXBlW1wic3RhcnRcIl0gPSAwXSA9IFwic3RhcnRcIjtcbiAgICBFdmVudFR5cGVbRXZlbnRUeXBlW1widGlja1wiXSA9IDFdID0gXCJ0aWNrXCI7XG4gICAgRXZlbnRUeXBlW0V2ZW50VHlwZVtcImVuZFwiXSA9IDJdID0gXCJlbmRcIjtcbn0pKEV2ZW50VHlwZSA9IGV4cG9ydHMuRXZlbnRUeXBlIHx8IChleHBvcnRzLkV2ZW50VHlwZSA9IHt9KSk7XG47XG5mdW5jdGlvbiBpc0dyb3VwKGcpIHtcbiAgICByZXR1cm4gdHlwZW9mIGcubGVhdmVzICE9PSAndW5kZWZpbmVkJyB8fCB0eXBlb2YgZy5ncm91cHMgIT09ICd1bmRlZmluZWQnO1xufVxudmFyIExheW91dCA9IChmdW5jdGlvbiAoKSB7XG4gICAgZnVuY3Rpb24gTGF5b3V0KCkge1xuICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICB0aGlzLl9jYW52YXNTaXplID0gWzEsIDFdO1xuICAgICAgICB0aGlzLl9saW5rRGlzdGFuY2UgPSAyMDtcbiAgICAgICAgdGhpcy5fZGVmYXVsdE5vZGVTaXplID0gMTA7XG4gICAgICAgIHRoaXMuX2xpbmtMZW5ndGhDYWxjdWxhdG9yID0gbnVsbDtcbiAgICAgICAgdGhpcy5fbGlua1R5cGUgPSBudWxsO1xuICAgICAgICB0aGlzLl9hdm9pZE92ZXJsYXBzID0gZmFsc2U7XG4gICAgICAgIHRoaXMuX2hhbmRsZURpc2Nvbm5lY3RlZCA9IHRydWU7XG4gICAgICAgIHRoaXMuX3J1bm5pbmcgPSBmYWxzZTtcbiAgICAgICAgdGhpcy5fbm9kZXMgPSBbXTtcbiAgICAgICAgdGhpcy5fZ3JvdXBzID0gW107XG4gICAgICAgIHRoaXMuX3Jvb3RHcm91cCA9IG51bGw7XG4gICAgICAgIHRoaXMuX2xpbmtzID0gW107XG4gICAgICAgIHRoaXMuX2NvbnN0cmFpbnRzID0gW107XG4gICAgICAgIHRoaXMuX2Rpc3RhbmNlTWF0cml4ID0gbnVsbDtcbiAgICAgICAgdGhpcy5fZGVzY2VudCA9IG51bGw7XG4gICAgICAgIHRoaXMuX2RpcmVjdGVkTGlua0NvbnN0cmFpbnRzID0gbnVsbDtcbiAgICAgICAgdGhpcy5fdGhyZXNob2xkID0gMC4wMTtcbiAgICAgICAgdGhpcy5fdmlzaWJpbGl0eUdyYXBoID0gbnVsbDtcbiAgICAgICAgdGhpcy5fZ3JvdXBDb21wYWN0bmVzcyA9IDFlLTY7XG4gICAgICAgIHRoaXMuZXZlbnQgPSBudWxsO1xuICAgICAgICB0aGlzLmxpbmtBY2Nlc3NvciA9IHtcbiAgICAgICAgICAgIGdldFNvdXJjZUluZGV4OiBMYXlvdXQuZ2V0U291cmNlSW5kZXgsXG4gICAgICAgICAgICBnZXRUYXJnZXRJbmRleDogTGF5b3V0LmdldFRhcmdldEluZGV4LFxuICAgICAgICAgICAgc2V0TGVuZ3RoOiBMYXlvdXQuc2V0TGlua0xlbmd0aCxcbiAgICAgICAgICAgIGdldFR5cGU6IGZ1bmN0aW9uIChsKSB7IHJldHVybiB0eXBlb2YgX3RoaXMuX2xpbmtUeXBlID09PSBcImZ1bmN0aW9uXCIgPyBfdGhpcy5fbGlua1R5cGUobCkgOiAwOyB9XG4gICAgICAgIH07XG4gICAgfVxuICAgIExheW91dC5wcm90b3R5cGUub24gPSBmdW5jdGlvbiAoZSwgbGlzdGVuZXIpIHtcbiAgICAgICAgaWYgKCF0aGlzLmV2ZW50KVxuICAgICAgICAgICAgdGhpcy5ldmVudCA9IHt9O1xuICAgICAgICBpZiAodHlwZW9mIGUgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICB0aGlzLmV2ZW50W0V2ZW50VHlwZVtlXV0gPSBsaXN0ZW5lcjtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIHRoaXMuZXZlbnRbZV0gPSBsaXN0ZW5lcjtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9O1xuICAgIExheW91dC5wcm90b3R5cGUudHJpZ2dlciA9IGZ1bmN0aW9uIChlKSB7XG4gICAgICAgIGlmICh0aGlzLmV2ZW50ICYmIHR5cGVvZiB0aGlzLmV2ZW50W2UudHlwZV0gIT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgICAgICB0aGlzLmV2ZW50W2UudHlwZV0oZSk7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIExheW91dC5wcm90b3R5cGUua2ljayA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgd2hpbGUgKCF0aGlzLnRpY2soKSlcbiAgICAgICAgICAgIDtcbiAgICB9O1xuICAgIExheW91dC5wcm90b3R5cGUudGljayA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgaWYgKHRoaXMuX2FscGhhIDwgdGhpcy5fdGhyZXNob2xkKSB7XG4gICAgICAgICAgICB0aGlzLl9ydW5uaW5nID0gZmFsc2U7XG4gICAgICAgICAgICB0aGlzLnRyaWdnZXIoeyB0eXBlOiBFdmVudFR5cGUuZW5kLCBhbHBoYTogdGhpcy5fYWxwaGEgPSAwLCBzdHJlc3M6IHRoaXMuX2xhc3RTdHJlc3MgfSk7XG4gICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgfVxuICAgICAgICB2YXIgbiA9IHRoaXMuX25vZGVzLmxlbmd0aCwgbSA9IHRoaXMuX2xpbmtzLmxlbmd0aDtcbiAgICAgICAgdmFyIG8sIGk7XG4gICAgICAgIHRoaXMuX2Rlc2NlbnQubG9ja3MuY2xlYXIoKTtcbiAgICAgICAgZm9yIChpID0gMDsgaSA8IG47ICsraSkge1xuICAgICAgICAgICAgbyA9IHRoaXMuX25vZGVzW2ldO1xuICAgICAgICAgICAgaWYgKG8uZml4ZWQpIHtcbiAgICAgICAgICAgICAgICBpZiAodHlwZW9mIG8ucHggPT09ICd1bmRlZmluZWQnIHx8IHR5cGVvZiBvLnB5ID09PSAndW5kZWZpbmVkJykge1xuICAgICAgICAgICAgICAgICAgICBvLnB4ID0gby54O1xuICAgICAgICAgICAgICAgICAgICBvLnB5ID0gby55O1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB2YXIgcCA9IFtvLnB4LCBvLnB5XTtcbiAgICAgICAgICAgICAgICB0aGlzLl9kZXNjZW50LmxvY2tzLmFkZChpLCBwKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICB2YXIgczEgPSB0aGlzLl9kZXNjZW50LnJ1bmdlS3V0dGEoKTtcbiAgICAgICAgaWYgKHMxID09PSAwKSB7XG4gICAgICAgICAgICB0aGlzLl9hbHBoYSA9IDA7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSBpZiAodHlwZW9mIHRoaXMuX2xhc3RTdHJlc3MgIT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgICAgICB0aGlzLl9hbHBoYSA9IHMxO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuX2xhc3RTdHJlc3MgPSBzMTtcbiAgICAgICAgdGhpcy51cGRhdGVOb2RlUG9zaXRpb25zKCk7XG4gICAgICAgIHRoaXMudHJpZ2dlcih7IHR5cGU6IEV2ZW50VHlwZS50aWNrLCBhbHBoYTogdGhpcy5fYWxwaGEsIHN0cmVzczogdGhpcy5fbGFzdFN0cmVzcyB9KTtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH07XG4gICAgTGF5b3V0LnByb3RvdHlwZS51cGRhdGVOb2RlUG9zaXRpb25zID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgeCA9IHRoaXMuX2Rlc2NlbnQueFswXSwgeSA9IHRoaXMuX2Rlc2NlbnQueFsxXTtcbiAgICAgICAgdmFyIG8sIGkgPSB0aGlzLl9ub2Rlcy5sZW5ndGg7XG4gICAgICAgIHdoaWxlIChpLS0pIHtcbiAgICAgICAgICAgIG8gPSB0aGlzLl9ub2Rlc1tpXTtcbiAgICAgICAgICAgIG8ueCA9IHhbaV07XG4gICAgICAgICAgICBvLnkgPSB5W2ldO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBMYXlvdXQucHJvdG90eXBlLm5vZGVzID0gZnVuY3Rpb24gKHYpIHtcbiAgICAgICAgaWYgKCF2KSB7XG4gICAgICAgICAgICBpZiAodGhpcy5fbm9kZXMubGVuZ3RoID09PSAwICYmIHRoaXMuX2xpbmtzLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICAgICAgICB2YXIgbiA9IDA7XG4gICAgICAgICAgICAgICAgdGhpcy5fbGlua3MuZm9yRWFjaChmdW5jdGlvbiAobCkge1xuICAgICAgICAgICAgICAgICAgICBuID0gTWF0aC5tYXgobiwgbC5zb3VyY2UsIGwudGFyZ2V0KTtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICB0aGlzLl9ub2RlcyA9IG5ldyBBcnJheSgrK24pO1xuICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbjsgKytpKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuX25vZGVzW2ldID0ge307XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIHRoaXMuX25vZGVzO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuX25vZGVzID0gdjtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfTtcbiAgICBMYXlvdXQucHJvdG90eXBlLmdyb3VwcyA9IGZ1bmN0aW9uICh4KSB7XG4gICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgICAgIGlmICgheClcbiAgICAgICAgICAgIHJldHVybiB0aGlzLl9ncm91cHM7XG4gICAgICAgIHRoaXMuX2dyb3VwcyA9IHg7XG4gICAgICAgIHRoaXMuX3Jvb3RHcm91cCA9IHt9O1xuICAgICAgICB0aGlzLl9ncm91cHMuZm9yRWFjaChmdW5jdGlvbiAoZykge1xuICAgICAgICAgICAgaWYgKHR5cGVvZiBnLnBhZGRpbmcgPT09IFwidW5kZWZpbmVkXCIpXG4gICAgICAgICAgICAgICAgZy5wYWRkaW5nID0gMTtcbiAgICAgICAgICAgIGlmICh0eXBlb2YgZy5sZWF2ZXMgIT09IFwidW5kZWZpbmVkXCIpIHtcbiAgICAgICAgICAgICAgICBnLmxlYXZlcy5mb3JFYWNoKGZ1bmN0aW9uICh2LCBpKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgdiA9PT0gJ251bWJlcicpXG4gICAgICAgICAgICAgICAgICAgICAgICAoZy5sZWF2ZXNbaV0gPSBfdGhpcy5fbm9kZXNbdl0pLnBhcmVudCA9IGc7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAodHlwZW9mIGcuZ3JvdXBzICE9PSBcInVuZGVmaW5lZFwiKSB7XG4gICAgICAgICAgICAgICAgZy5ncm91cHMuZm9yRWFjaChmdW5jdGlvbiAoZ2ksIGkpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBnaSA9PT0gJ251bWJlcicpXG4gICAgICAgICAgICAgICAgICAgICAgICAoZy5ncm91cHNbaV0gPSBfdGhpcy5fZ3JvdXBzW2dpXSkucGFyZW50ID0gZztcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgICAgIHRoaXMuX3Jvb3RHcm91cC5sZWF2ZXMgPSB0aGlzLl9ub2Rlcy5maWx0ZXIoZnVuY3Rpb24gKHYpIHsgcmV0dXJuIHR5cGVvZiB2LnBhcmVudCA9PT0gJ3VuZGVmaW5lZCc7IH0pO1xuICAgICAgICB0aGlzLl9yb290R3JvdXAuZ3JvdXBzID0gdGhpcy5fZ3JvdXBzLmZpbHRlcihmdW5jdGlvbiAoZykgeyByZXR1cm4gdHlwZW9mIGcucGFyZW50ID09PSAndW5kZWZpbmVkJzsgfSk7XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH07XG4gICAgTGF5b3V0LnByb3RvdHlwZS5wb3dlckdyYXBoR3JvdXBzID0gZnVuY3Rpb24gKGYpIHtcbiAgICAgICAgdmFyIGcgPSBwb3dlcmdyYXBoLmdldEdyb3Vwcyh0aGlzLl9ub2RlcywgdGhpcy5fbGlua3MsIHRoaXMubGlua0FjY2Vzc29yLCB0aGlzLl9yb290R3JvdXApO1xuICAgICAgICB0aGlzLmdyb3VwcyhnLmdyb3Vwcyk7XG4gICAgICAgIGYoZyk7XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH07XG4gICAgTGF5b3V0LnByb3RvdHlwZS5hdm9pZE92ZXJsYXBzID0gZnVuY3Rpb24gKHYpIHtcbiAgICAgICAgaWYgKCFhcmd1bWVudHMubGVuZ3RoKVxuICAgICAgICAgICAgcmV0dXJuIHRoaXMuX2F2b2lkT3ZlcmxhcHM7XG4gICAgICAgIHRoaXMuX2F2b2lkT3ZlcmxhcHMgPSB2O1xuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9O1xuICAgIExheW91dC5wcm90b3R5cGUuaGFuZGxlRGlzY29ubmVjdGVkID0gZnVuY3Rpb24gKHYpIHtcbiAgICAgICAgaWYgKCFhcmd1bWVudHMubGVuZ3RoKVxuICAgICAgICAgICAgcmV0dXJuIHRoaXMuX2hhbmRsZURpc2Nvbm5lY3RlZDtcbiAgICAgICAgdGhpcy5faGFuZGxlRGlzY29ubmVjdGVkID0gdjtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfTtcbiAgICBMYXlvdXQucHJvdG90eXBlLmZsb3dMYXlvdXQgPSBmdW5jdGlvbiAoYXhpcywgbWluU2VwYXJhdGlvbikge1xuICAgICAgICBpZiAoIWFyZ3VtZW50cy5sZW5ndGgpXG4gICAgICAgICAgICBheGlzID0gJ3knO1xuICAgICAgICB0aGlzLl9kaXJlY3RlZExpbmtDb25zdHJhaW50cyA9IHtcbiAgICAgICAgICAgIGF4aXM6IGF4aXMsXG4gICAgICAgICAgICBnZXRNaW5TZXBhcmF0aW9uOiB0eXBlb2YgbWluU2VwYXJhdGlvbiA9PT0gJ251bWJlcicgPyBmdW5jdGlvbiAoKSB7IHJldHVybiBtaW5TZXBhcmF0aW9uOyB9IDogbWluU2VwYXJhdGlvblxuICAgICAgICB9O1xuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9O1xuICAgIExheW91dC5wcm90b3R5cGUubGlua3MgPSBmdW5jdGlvbiAoeCkge1xuICAgICAgICBpZiAoIWFyZ3VtZW50cy5sZW5ndGgpXG4gICAgICAgICAgICByZXR1cm4gdGhpcy5fbGlua3M7XG4gICAgICAgIHRoaXMuX2xpbmtzID0geDtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfTtcbiAgICBMYXlvdXQucHJvdG90eXBlLmNvbnN0cmFpbnRzID0gZnVuY3Rpb24gKGMpIHtcbiAgICAgICAgaWYgKCFhcmd1bWVudHMubGVuZ3RoKVxuICAgICAgICAgICAgcmV0dXJuIHRoaXMuX2NvbnN0cmFpbnRzO1xuICAgICAgICB0aGlzLl9jb25zdHJhaW50cyA9IGM7XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH07XG4gICAgTGF5b3V0LnByb3RvdHlwZS5kaXN0YW5jZU1hdHJpeCA9IGZ1bmN0aW9uIChkKSB7XG4gICAgICAgIGlmICghYXJndW1lbnRzLmxlbmd0aClcbiAgICAgICAgICAgIHJldHVybiB0aGlzLl9kaXN0YW5jZU1hdHJpeDtcbiAgICAgICAgdGhpcy5fZGlzdGFuY2VNYXRyaXggPSBkO1xuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9O1xuICAgIExheW91dC5wcm90b3R5cGUuc2l6ZSA9IGZ1bmN0aW9uICh4KSB7XG4gICAgICAgIGlmICgheClcbiAgICAgICAgICAgIHJldHVybiB0aGlzLl9jYW52YXNTaXplO1xuICAgICAgICB0aGlzLl9jYW52YXNTaXplID0geDtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfTtcbiAgICBMYXlvdXQucHJvdG90eXBlLmRlZmF1bHROb2RlU2l6ZSA9IGZ1bmN0aW9uICh4KSB7XG4gICAgICAgIGlmICgheClcbiAgICAgICAgICAgIHJldHVybiB0aGlzLl9kZWZhdWx0Tm9kZVNpemU7XG4gICAgICAgIHRoaXMuX2RlZmF1bHROb2RlU2l6ZSA9IHg7XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH07XG4gICAgTGF5b3V0LnByb3RvdHlwZS5ncm91cENvbXBhY3RuZXNzID0gZnVuY3Rpb24gKHgpIHtcbiAgICAgICAgaWYgKCF4KVxuICAgICAgICAgICAgcmV0dXJuIHRoaXMuX2dyb3VwQ29tcGFjdG5lc3M7XG4gICAgICAgIHRoaXMuX2dyb3VwQ29tcGFjdG5lc3MgPSB4O1xuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9O1xuICAgIExheW91dC5wcm90b3R5cGUubGlua0Rpc3RhbmNlID0gZnVuY3Rpb24gKHgpIHtcbiAgICAgICAgaWYgKCF4KSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5fbGlua0Rpc3RhbmNlO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuX2xpbmtEaXN0YW5jZSA9IHR5cGVvZiB4ID09PSBcImZ1bmN0aW9uXCIgPyB4IDogK3g7XG4gICAgICAgIHRoaXMuX2xpbmtMZW5ndGhDYWxjdWxhdG9yID0gbnVsbDtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfTtcbiAgICBMYXlvdXQucHJvdG90eXBlLmxpbmtUeXBlID0gZnVuY3Rpb24gKGYpIHtcbiAgICAgICAgdGhpcy5fbGlua1R5cGUgPSBmO1xuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9O1xuICAgIExheW91dC5wcm90b3R5cGUuY29udmVyZ2VuY2VUaHJlc2hvbGQgPSBmdW5jdGlvbiAoeCkge1xuICAgICAgICBpZiAoIXgpXG4gICAgICAgICAgICByZXR1cm4gdGhpcy5fdGhyZXNob2xkO1xuICAgICAgICB0aGlzLl90aHJlc2hvbGQgPSB0eXBlb2YgeCA9PT0gXCJmdW5jdGlvblwiID8geCA6ICt4O1xuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9O1xuICAgIExheW91dC5wcm90b3R5cGUuYWxwaGEgPSBmdW5jdGlvbiAoeCkge1xuICAgICAgICBpZiAoIWFyZ3VtZW50cy5sZW5ndGgpXG4gICAgICAgICAgICByZXR1cm4gdGhpcy5fYWxwaGE7XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgeCA9ICt4O1xuICAgICAgICAgICAgaWYgKHRoaXMuX2FscGhhKSB7XG4gICAgICAgICAgICAgICAgaWYgKHggPiAwKVxuICAgICAgICAgICAgICAgICAgICB0aGlzLl9hbHBoYSA9IHg7XG4gICAgICAgICAgICAgICAgZWxzZVxuICAgICAgICAgICAgICAgICAgICB0aGlzLl9hbHBoYSA9IDA7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIGlmICh4ID4gMCkge1xuICAgICAgICAgICAgICAgIGlmICghdGhpcy5fcnVubmluZykge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLl9ydW5uaW5nID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy50cmlnZ2VyKHsgdHlwZTogRXZlbnRUeXBlLnN0YXJ0LCBhbHBoYTogdGhpcy5fYWxwaGEgPSB4IH0pO1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmtpY2soKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gdGhpcztcbiAgICAgICAgfVxuICAgIH07XG4gICAgTGF5b3V0LnByb3RvdHlwZS5nZXRMaW5rTGVuZ3RoID0gZnVuY3Rpb24gKGxpbmspIHtcbiAgICAgICAgcmV0dXJuIHR5cGVvZiB0aGlzLl9saW5rRGlzdGFuY2UgPT09IFwiZnVuY3Rpb25cIiA/ICsodGhpcy5fbGlua0Rpc3RhbmNlKGxpbmspKSA6IHRoaXMuX2xpbmtEaXN0YW5jZTtcbiAgICB9O1xuICAgIExheW91dC5zZXRMaW5rTGVuZ3RoID0gZnVuY3Rpb24gKGxpbmssIGxlbmd0aCkge1xuICAgICAgICBsaW5rLmxlbmd0aCA9IGxlbmd0aDtcbiAgICB9O1xuICAgIExheW91dC5wcm90b3R5cGUuZ2V0TGlua1R5cGUgPSBmdW5jdGlvbiAobGluaykge1xuICAgICAgICByZXR1cm4gdHlwZW9mIHRoaXMuX2xpbmtUeXBlID09PSBcImZ1bmN0aW9uXCIgPyB0aGlzLl9saW5rVHlwZShsaW5rKSA6IDA7XG4gICAgfTtcbiAgICBMYXlvdXQucHJvdG90eXBlLnN5bW1ldHJpY0RpZmZMaW5rTGVuZ3RocyA9IGZ1bmN0aW9uIChpZGVhbExlbmd0aCwgdykge1xuICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICBpZiAodyA9PT0gdm9pZCAwKSB7IHcgPSAxOyB9XG4gICAgICAgIHRoaXMubGlua0Rpc3RhbmNlKGZ1bmN0aW9uIChsKSB7IHJldHVybiBpZGVhbExlbmd0aCAqIGwubGVuZ3RoOyB9KTtcbiAgICAgICAgdGhpcy5fbGlua0xlbmd0aENhbGN1bGF0b3IgPSBmdW5jdGlvbiAoKSB7IHJldHVybiBsaW5rbGVuZ3Roc18xLnN5bW1ldHJpY0RpZmZMaW5rTGVuZ3RocyhfdGhpcy5fbGlua3MsIF90aGlzLmxpbmtBY2Nlc3Nvciwgdyk7IH07XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH07XG4gICAgTGF5b3V0LnByb3RvdHlwZS5qYWNjYXJkTGlua0xlbmd0aHMgPSBmdW5jdGlvbiAoaWRlYWxMZW5ndGgsIHcpIHtcbiAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgaWYgKHcgPT09IHZvaWQgMCkgeyB3ID0gMTsgfVxuICAgICAgICB0aGlzLmxpbmtEaXN0YW5jZShmdW5jdGlvbiAobCkgeyByZXR1cm4gaWRlYWxMZW5ndGggKiBsLmxlbmd0aDsgfSk7XG4gICAgICAgIHRoaXMuX2xpbmtMZW5ndGhDYWxjdWxhdG9yID0gZnVuY3Rpb24gKCkgeyByZXR1cm4gbGlua2xlbmd0aHNfMS5qYWNjYXJkTGlua0xlbmd0aHMoX3RoaXMuX2xpbmtzLCBfdGhpcy5saW5rQWNjZXNzb3IsIHcpOyB9O1xuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9O1xuICAgIExheW91dC5wcm90b3R5cGUuc3RhcnQgPSBmdW5jdGlvbiAoaW5pdGlhbFVuY29uc3RyYWluZWRJdGVyYXRpb25zLCBpbml0aWFsVXNlckNvbnN0cmFpbnRJdGVyYXRpb25zLCBpbml0aWFsQWxsQ29uc3RyYWludHNJdGVyYXRpb25zLCBncmlkU25hcEl0ZXJhdGlvbnMsIGtlZXBSdW5uaW5nLCBjZW50ZXJHcmFwaCkge1xuICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICBpZiAoaW5pdGlhbFVuY29uc3RyYWluZWRJdGVyYXRpb25zID09PSB2b2lkIDApIHsgaW5pdGlhbFVuY29uc3RyYWluZWRJdGVyYXRpb25zID0gMDsgfVxuICAgICAgICBpZiAoaW5pdGlhbFVzZXJDb25zdHJhaW50SXRlcmF0aW9ucyA9PT0gdm9pZCAwKSB7IGluaXRpYWxVc2VyQ29uc3RyYWludEl0ZXJhdGlvbnMgPSAwOyB9XG4gICAgICAgIGlmIChpbml0aWFsQWxsQ29uc3RyYWludHNJdGVyYXRpb25zID09PSB2b2lkIDApIHsgaW5pdGlhbEFsbENvbnN0cmFpbnRzSXRlcmF0aW9ucyA9IDA7IH1cbiAgICAgICAgaWYgKGdyaWRTbmFwSXRlcmF0aW9ucyA9PT0gdm9pZCAwKSB7IGdyaWRTbmFwSXRlcmF0aW9ucyA9IDA7IH1cbiAgICAgICAgaWYgKGtlZXBSdW5uaW5nID09PSB2b2lkIDApIHsga2VlcFJ1bm5pbmcgPSB0cnVlOyB9XG4gICAgICAgIGlmIChjZW50ZXJHcmFwaCA9PT0gdm9pZCAwKSB7IGNlbnRlckdyYXBoID0gdHJ1ZTsgfVxuICAgICAgICB2YXIgaSwgaiwgbiA9IHRoaXMubm9kZXMoKS5sZW5ndGgsIE4gPSBuICsgMiAqIHRoaXMuX2dyb3Vwcy5sZW5ndGgsIG0gPSB0aGlzLl9saW5rcy5sZW5ndGgsIHcgPSB0aGlzLl9jYW52YXNTaXplWzBdLCBoID0gdGhpcy5fY2FudmFzU2l6ZVsxXTtcbiAgICAgICAgdmFyIHggPSBuZXcgQXJyYXkoTiksIHkgPSBuZXcgQXJyYXkoTik7XG4gICAgICAgIHZhciBHID0gbnVsbDtcbiAgICAgICAgdmFyIGFvID0gdGhpcy5fYXZvaWRPdmVybGFwcztcbiAgICAgICAgdGhpcy5fbm9kZXMuZm9yRWFjaChmdW5jdGlvbiAodiwgaSkge1xuICAgICAgICAgICAgdi5pbmRleCA9IGk7XG4gICAgICAgICAgICBpZiAodHlwZW9mIHYueCA9PT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgICAgICAgICB2LnggPSB3IC8gMiwgdi55ID0gaCAvIDI7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB4W2ldID0gdi54LCB5W2ldID0gdi55O1xuICAgICAgICB9KTtcbiAgICAgICAgaWYgKHRoaXMuX2xpbmtMZW5ndGhDYWxjdWxhdG9yKVxuICAgICAgICAgICAgdGhpcy5fbGlua0xlbmd0aENhbGN1bGF0b3IoKTtcbiAgICAgICAgdmFyIGRpc3RhbmNlcztcbiAgICAgICAgaWYgKHRoaXMuX2Rpc3RhbmNlTWF0cml4KSB7XG4gICAgICAgICAgICBkaXN0YW5jZXMgPSB0aGlzLl9kaXN0YW5jZU1hdHJpeDtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIGRpc3RhbmNlcyA9IChuZXcgc2hvcnRlc3RwYXRoc18xLkNhbGN1bGF0b3IoTiwgdGhpcy5fbGlua3MsIExheW91dC5nZXRTb3VyY2VJbmRleCwgTGF5b3V0LmdldFRhcmdldEluZGV4LCBmdW5jdGlvbiAobCkgeyByZXR1cm4gX3RoaXMuZ2V0TGlua0xlbmd0aChsKTsgfSkpLkRpc3RhbmNlTWF0cml4KCk7XG4gICAgICAgICAgICBHID0gZGVzY2VudF8xLkRlc2NlbnQuY3JlYXRlU3F1YXJlTWF0cml4KE4sIGZ1bmN0aW9uICgpIHsgcmV0dXJuIDI7IH0pO1xuICAgICAgICAgICAgdGhpcy5fbGlua3MuZm9yRWFjaChmdW5jdGlvbiAobCkge1xuICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgbC5zb3VyY2UgPT0gXCJudW1iZXJcIilcbiAgICAgICAgICAgICAgICAgICAgbC5zb3VyY2UgPSBfdGhpcy5fbm9kZXNbbC5zb3VyY2VdO1xuICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgbC50YXJnZXQgPT0gXCJudW1iZXJcIilcbiAgICAgICAgICAgICAgICAgICAgbC50YXJnZXQgPSBfdGhpcy5fbm9kZXNbbC50YXJnZXRdO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB0aGlzLl9saW5rcy5mb3JFYWNoKGZ1bmN0aW9uIChlKSB7XG4gICAgICAgICAgICAgICAgdmFyIHUgPSBMYXlvdXQuZ2V0U291cmNlSW5kZXgoZSksIHYgPSBMYXlvdXQuZ2V0VGFyZ2V0SW5kZXgoZSk7XG4gICAgICAgICAgICAgICAgR1t1XVt2XSA9IEdbdl1bdV0gPSBlLndlaWdodCB8fCAxO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICAgICAgdmFyIEQgPSBkZXNjZW50XzEuRGVzY2VudC5jcmVhdGVTcXVhcmVNYXRyaXgoTiwgZnVuY3Rpb24gKGksIGopIHtcbiAgICAgICAgICAgIHJldHVybiBkaXN0YW5jZXNbaV1bal07XG4gICAgICAgIH0pO1xuICAgICAgICBpZiAodGhpcy5fcm9vdEdyb3VwICYmIHR5cGVvZiB0aGlzLl9yb290R3JvdXAuZ3JvdXBzICE9PSAndW5kZWZpbmVkJykge1xuICAgICAgICAgICAgdmFyIGkgPSBuO1xuICAgICAgICAgICAgdmFyIGFkZEF0dHJhY3Rpb24gPSBmdW5jdGlvbiAoaSwgaiwgc3RyZW5ndGgsIGlkZWFsRGlzdGFuY2UpIHtcbiAgICAgICAgICAgICAgICBHW2ldW2pdID0gR1tqXVtpXSA9IHN0cmVuZ3RoO1xuICAgICAgICAgICAgICAgIERbaV1bal0gPSBEW2pdW2ldID0gaWRlYWxEaXN0YW5jZTtcbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICB0aGlzLl9ncm91cHMuZm9yRWFjaChmdW5jdGlvbiAoZykge1xuICAgICAgICAgICAgICAgIGFkZEF0dHJhY3Rpb24oaSwgaSArIDEsIF90aGlzLl9ncm91cENvbXBhY3RuZXNzLCAwLjEpO1xuICAgICAgICAgICAgICAgIHhbaV0gPSAwLCB5W2krK10gPSAwO1xuICAgICAgICAgICAgICAgIHhbaV0gPSAwLCB5W2krK10gPSAwO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZVxuICAgICAgICAgICAgdGhpcy5fcm9vdEdyb3VwID0geyBsZWF2ZXM6IHRoaXMuX25vZGVzLCBncm91cHM6IFtdIH07XG4gICAgICAgIHZhciBjdXJDb25zdHJhaW50cyA9IHRoaXMuX2NvbnN0cmFpbnRzIHx8IFtdO1xuICAgICAgICBpZiAodGhpcy5fZGlyZWN0ZWRMaW5rQ29uc3RyYWludHMpIHtcbiAgICAgICAgICAgIHRoaXMubGlua0FjY2Vzc29yLmdldE1pblNlcGFyYXRpb24gPSB0aGlzLl9kaXJlY3RlZExpbmtDb25zdHJhaW50cy5nZXRNaW5TZXBhcmF0aW9uO1xuICAgICAgICAgICAgY3VyQ29uc3RyYWludHMgPSBjdXJDb25zdHJhaW50cy5jb25jYXQobGlua2xlbmd0aHNfMS5nZW5lcmF0ZURpcmVjdGVkRWRnZUNvbnN0cmFpbnRzKG4sIHRoaXMuX2xpbmtzLCB0aGlzLl9kaXJlY3RlZExpbmtDb25zdHJhaW50cy5heGlzLCAodGhpcy5saW5rQWNjZXNzb3IpKSk7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5hdm9pZE92ZXJsYXBzKGZhbHNlKTtcbiAgICAgICAgdGhpcy5fZGVzY2VudCA9IG5ldyBkZXNjZW50XzEuRGVzY2VudChbeCwgeV0sIEQpO1xuICAgICAgICB0aGlzLl9kZXNjZW50LmxvY2tzLmNsZWFyKCk7XG4gICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbjsgKytpKSB7XG4gICAgICAgICAgICB2YXIgbyA9IHRoaXMuX25vZGVzW2ldO1xuICAgICAgICAgICAgaWYgKG8uZml4ZWQpIHtcbiAgICAgICAgICAgICAgICBvLnB4ID0gby54O1xuICAgICAgICAgICAgICAgIG8ucHkgPSBvLnk7XG4gICAgICAgICAgICAgICAgdmFyIHAgPSBbby54LCBvLnldO1xuICAgICAgICAgICAgICAgIHRoaXMuX2Rlc2NlbnQubG9ja3MuYWRkKGksIHApO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHRoaXMuX2Rlc2NlbnQudGhyZXNob2xkID0gdGhpcy5fdGhyZXNob2xkO1xuICAgICAgICB0aGlzLmluaXRpYWxMYXlvdXQoaW5pdGlhbFVuY29uc3RyYWluZWRJdGVyYXRpb25zLCB4LCB5KTtcbiAgICAgICAgaWYgKGN1ckNvbnN0cmFpbnRzLmxlbmd0aCA+IDApXG4gICAgICAgICAgICB0aGlzLl9kZXNjZW50LnByb2plY3QgPSBuZXcgcmVjdGFuZ2xlXzEuUHJvamVjdGlvbih0aGlzLl9ub2RlcywgdGhpcy5fZ3JvdXBzLCB0aGlzLl9yb290R3JvdXAsIGN1ckNvbnN0cmFpbnRzKS5wcm9qZWN0RnVuY3Rpb25zKCk7XG4gICAgICAgIHRoaXMuX2Rlc2NlbnQucnVuKGluaXRpYWxVc2VyQ29uc3RyYWludEl0ZXJhdGlvbnMpO1xuICAgICAgICB0aGlzLnNlcGFyYXRlT3ZlcmxhcHBpbmdDb21wb25lbnRzKHcsIGgsIGNlbnRlckdyYXBoKTtcbiAgICAgICAgdGhpcy5hdm9pZE92ZXJsYXBzKGFvKTtcbiAgICAgICAgaWYgKGFvKSB7XG4gICAgICAgICAgICB0aGlzLl9ub2Rlcy5mb3JFYWNoKGZ1bmN0aW9uICh2LCBpKSB7IHYueCA9IHhbaV0sIHYueSA9IHlbaV07IH0pO1xuICAgICAgICAgICAgdGhpcy5fZGVzY2VudC5wcm9qZWN0ID0gbmV3IHJlY3RhbmdsZV8xLlByb2plY3Rpb24odGhpcy5fbm9kZXMsIHRoaXMuX2dyb3VwcywgdGhpcy5fcm9vdEdyb3VwLCBjdXJDb25zdHJhaW50cywgdHJ1ZSkucHJvamVjdEZ1bmN0aW9ucygpO1xuICAgICAgICAgICAgdGhpcy5fbm9kZXMuZm9yRWFjaChmdW5jdGlvbiAodiwgaSkgeyB4W2ldID0gdi54LCB5W2ldID0gdi55OyB9KTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLl9kZXNjZW50LkcgPSBHO1xuICAgICAgICB0aGlzLl9kZXNjZW50LnJ1bihpbml0aWFsQWxsQ29uc3RyYWludHNJdGVyYXRpb25zKTtcbiAgICAgICAgaWYgKGdyaWRTbmFwSXRlcmF0aW9ucykge1xuICAgICAgICAgICAgdGhpcy5fZGVzY2VudC5zbmFwU3RyZW5ndGggPSAxMDAwO1xuICAgICAgICAgICAgdGhpcy5fZGVzY2VudC5zbmFwR3JpZFNpemUgPSB0aGlzLl9ub2Rlc1swXS53aWR0aDtcbiAgICAgICAgICAgIHRoaXMuX2Rlc2NlbnQubnVtR3JpZFNuYXBOb2RlcyA9IG47XG4gICAgICAgICAgICB0aGlzLl9kZXNjZW50LnNjYWxlU25hcEJ5TWF4SCA9IG4gIT0gTjtcbiAgICAgICAgICAgIHZhciBHMCA9IGRlc2NlbnRfMS5EZXNjZW50LmNyZWF0ZVNxdWFyZU1hdHJpeChOLCBmdW5jdGlvbiAoaSwgaikge1xuICAgICAgICAgICAgICAgIGlmIChpID49IG4gfHwgaiA+PSBuKVxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gR1tpXVtqXTtcbiAgICAgICAgICAgICAgICByZXR1cm4gMDtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgdGhpcy5fZGVzY2VudC5HID0gRzA7XG4gICAgICAgICAgICB0aGlzLl9kZXNjZW50LnJ1bihncmlkU25hcEl0ZXJhdGlvbnMpO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMudXBkYXRlTm9kZVBvc2l0aW9ucygpO1xuICAgICAgICB0aGlzLnNlcGFyYXRlT3ZlcmxhcHBpbmdDb21wb25lbnRzKHcsIGgsIGNlbnRlckdyYXBoKTtcbiAgICAgICAgcmV0dXJuIGtlZXBSdW5uaW5nID8gdGhpcy5yZXN1bWUoKSA6IHRoaXM7XG4gICAgfTtcbiAgICBMYXlvdXQucHJvdG90eXBlLmluaXRpYWxMYXlvdXQgPSBmdW5jdGlvbiAoaXRlcmF0aW9ucywgeCwgeSkge1xuICAgICAgICBpZiAodGhpcy5fZ3JvdXBzLmxlbmd0aCA+IDAgJiYgaXRlcmF0aW9ucyA+IDApIHtcbiAgICAgICAgICAgIHZhciBuID0gdGhpcy5fbm9kZXMubGVuZ3RoO1xuICAgICAgICAgICAgdmFyIGVkZ2VzID0gdGhpcy5fbGlua3MubWFwKGZ1bmN0aW9uIChlKSB7IHJldHVybiAoeyBzb3VyY2U6IGUuc291cmNlLmluZGV4LCB0YXJnZXQ6IGUudGFyZ2V0LmluZGV4IH0pOyB9KTtcbiAgICAgICAgICAgIHZhciB2cyA9IHRoaXMuX25vZGVzLm1hcChmdW5jdGlvbiAodikgeyByZXR1cm4gKHsgaW5kZXg6IHYuaW5kZXggfSk7IH0pO1xuICAgICAgICAgICAgdGhpcy5fZ3JvdXBzLmZvckVhY2goZnVuY3Rpb24gKGcsIGkpIHtcbiAgICAgICAgICAgICAgICB2cy5wdXNoKHsgaW5kZXg6IGcuaW5kZXggPSBuICsgaSB9KTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgdGhpcy5fZ3JvdXBzLmZvckVhY2goZnVuY3Rpb24gKGcsIGkpIHtcbiAgICAgICAgICAgICAgICBpZiAodHlwZW9mIGcubGVhdmVzICE9PSAndW5kZWZpbmVkJylcbiAgICAgICAgICAgICAgICAgICAgZy5sZWF2ZXMuZm9yRWFjaChmdW5jdGlvbiAodikgeyByZXR1cm4gZWRnZXMucHVzaCh7IHNvdXJjZTogZy5pbmRleCwgdGFyZ2V0OiB2LmluZGV4IH0pOyB9KTtcbiAgICAgICAgICAgICAgICBpZiAodHlwZW9mIGcuZ3JvdXBzICE9PSAndW5kZWZpbmVkJylcbiAgICAgICAgICAgICAgICAgICAgZy5ncm91cHMuZm9yRWFjaChmdW5jdGlvbiAoZ2cpIHsgcmV0dXJuIGVkZ2VzLnB1c2goeyBzb3VyY2U6IGcuaW5kZXgsIHRhcmdldDogZ2cuaW5kZXggfSk7IH0pO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICBuZXcgTGF5b3V0KClcbiAgICAgICAgICAgICAgICAuc2l6ZSh0aGlzLnNpemUoKSlcbiAgICAgICAgICAgICAgICAubm9kZXModnMpXG4gICAgICAgICAgICAgICAgLmxpbmtzKGVkZ2VzKVxuICAgICAgICAgICAgICAgIC5hdm9pZE92ZXJsYXBzKGZhbHNlKVxuICAgICAgICAgICAgICAgIC5saW5rRGlzdGFuY2UodGhpcy5saW5rRGlzdGFuY2UoKSlcbiAgICAgICAgICAgICAgICAuc3ltbWV0cmljRGlmZkxpbmtMZW5ndGhzKDUpXG4gICAgICAgICAgICAgICAgLmNvbnZlcmdlbmNlVGhyZXNob2xkKDFlLTQpXG4gICAgICAgICAgICAgICAgLnN0YXJ0KGl0ZXJhdGlvbnMsIDAsIDAsIDAsIGZhbHNlKTtcbiAgICAgICAgICAgIHRoaXMuX25vZGVzLmZvckVhY2goZnVuY3Rpb24gKHYpIHtcbiAgICAgICAgICAgICAgICB4W3YuaW5kZXhdID0gdnNbdi5pbmRleF0ueDtcbiAgICAgICAgICAgICAgICB5W3YuaW5kZXhdID0gdnNbdi5pbmRleF0ueTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgdGhpcy5fZGVzY2VudC5ydW4oaXRlcmF0aW9ucyk7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIExheW91dC5wcm90b3R5cGUuc2VwYXJhdGVPdmVybGFwcGluZ0NvbXBvbmVudHMgPSBmdW5jdGlvbiAod2lkdGgsIGhlaWdodCwgY2VudGVyR3JhcGgpIHtcbiAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgaWYgKGNlbnRlckdyYXBoID09PSB2b2lkIDApIHsgY2VudGVyR3JhcGggPSB0cnVlOyB9XG4gICAgICAgIGlmICghdGhpcy5fZGlzdGFuY2VNYXRyaXggJiYgdGhpcy5faGFuZGxlRGlzY29ubmVjdGVkKSB7XG4gICAgICAgICAgICB2YXIgeF8xID0gdGhpcy5fZGVzY2VudC54WzBdLCB5XzEgPSB0aGlzLl9kZXNjZW50LnhbMV07XG4gICAgICAgICAgICB0aGlzLl9ub2Rlcy5mb3JFYWNoKGZ1bmN0aW9uICh2LCBpKSB7IHYueCA9IHhfMVtpXSwgdi55ID0geV8xW2ldOyB9KTtcbiAgICAgICAgICAgIHZhciBncmFwaHMgPSBoYW5kbGVkaXNjb25uZWN0ZWRfMS5zZXBhcmF0ZUdyYXBocyh0aGlzLl9ub2RlcywgdGhpcy5fbGlua3MpO1xuICAgICAgICAgICAgaGFuZGxlZGlzY29ubmVjdGVkXzEuYXBwbHlQYWNraW5nKGdyYXBocywgd2lkdGgsIGhlaWdodCwgdGhpcy5fZGVmYXVsdE5vZGVTaXplLCAoaGVpZ2h0IC8gd2lkdGgpLCBjZW50ZXJHcmFwaCk7XG4gICAgICAgICAgICB0aGlzLl9ub2Rlcy5mb3JFYWNoKGZ1bmN0aW9uICh2LCBpKSB7XG4gICAgICAgICAgICAgICAgX3RoaXMuX2Rlc2NlbnQueFswXVtpXSA9IHYueCwgX3RoaXMuX2Rlc2NlbnQueFsxXVtpXSA9IHYueTtcbiAgICAgICAgICAgICAgICBpZiAodi5ib3VuZHMpIHtcbiAgICAgICAgICAgICAgICAgICAgdi5ib3VuZHMuc2V0WENlbnRyZSh2LngpO1xuICAgICAgICAgICAgICAgICAgICB2LmJvdW5kcy5zZXRZQ2VudHJlKHYueSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIExheW91dC5wcm90b3R5cGUucmVzdW1lID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5hbHBoYSgwLjEpO1xuICAgIH07XG4gICAgTGF5b3V0LnByb3RvdHlwZS5zdG9wID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5hbHBoYSgwKTtcbiAgICB9O1xuICAgIExheW91dC5wcm90b3R5cGUucHJlcGFyZUVkZ2VSb3V0aW5nID0gZnVuY3Rpb24gKG5vZGVNYXJnaW4pIHtcbiAgICAgICAgaWYgKG5vZGVNYXJnaW4gPT09IHZvaWQgMCkgeyBub2RlTWFyZ2luID0gMDsgfVxuICAgICAgICB0aGlzLl92aXNpYmlsaXR5R3JhcGggPSBuZXcgZ2VvbV8xLlRhbmdlbnRWaXNpYmlsaXR5R3JhcGgodGhpcy5fbm9kZXMubWFwKGZ1bmN0aW9uICh2KSB7XG4gICAgICAgICAgICByZXR1cm4gdi5ib3VuZHMuaW5mbGF0ZSgtbm9kZU1hcmdpbikudmVydGljZXMoKTtcbiAgICAgICAgfSkpO1xuICAgIH07XG4gICAgTGF5b3V0LnByb3RvdHlwZS5yb3V0ZUVkZ2UgPSBmdW5jdGlvbiAoZWRnZSwgYWgsIGRyYXcpIHtcbiAgICAgICAgaWYgKGFoID09PSB2b2lkIDApIHsgYWggPSA1OyB9XG4gICAgICAgIHZhciBsaW5lRGF0YSA9IFtdO1xuICAgICAgICB2YXIgdmcyID0gbmV3IGdlb21fMS5UYW5nZW50VmlzaWJpbGl0eUdyYXBoKHRoaXMuX3Zpc2liaWxpdHlHcmFwaC5QLCB7IFY6IHRoaXMuX3Zpc2liaWxpdHlHcmFwaC5WLCBFOiB0aGlzLl92aXNpYmlsaXR5R3JhcGguRSB9KSwgcG9ydDEgPSB7IHg6IGVkZ2Uuc291cmNlLngsIHk6IGVkZ2Uuc291cmNlLnkgfSwgcG9ydDIgPSB7IHg6IGVkZ2UudGFyZ2V0LngsIHk6IGVkZ2UudGFyZ2V0LnkgfSwgc3RhcnQgPSB2ZzIuYWRkUG9pbnQocG9ydDEsIGVkZ2Uuc291cmNlLmluZGV4KSwgZW5kID0gdmcyLmFkZFBvaW50KHBvcnQyLCBlZGdlLnRhcmdldC5pbmRleCk7XG4gICAgICAgIHZnMi5hZGRFZGdlSWZWaXNpYmxlKHBvcnQxLCBwb3J0MiwgZWRnZS5zb3VyY2UuaW5kZXgsIGVkZ2UudGFyZ2V0LmluZGV4KTtcbiAgICAgICAgaWYgKHR5cGVvZiBkcmF3ICE9PSAndW5kZWZpbmVkJykge1xuICAgICAgICAgICAgZHJhdyh2ZzIpO1xuICAgICAgICB9XG4gICAgICAgIHZhciBzb3VyY2VJbmQgPSBmdW5jdGlvbiAoZSkgeyByZXR1cm4gZS5zb3VyY2UuaWQ7IH0sIHRhcmdldEluZCA9IGZ1bmN0aW9uIChlKSB7IHJldHVybiBlLnRhcmdldC5pZDsgfSwgbGVuZ3RoID0gZnVuY3Rpb24gKGUpIHsgcmV0dXJuIGUubGVuZ3RoKCk7IH0sIHNwQ2FsYyA9IG5ldyBzaG9ydGVzdHBhdGhzXzEuQ2FsY3VsYXRvcih2ZzIuVi5sZW5ndGgsIHZnMi5FLCBzb3VyY2VJbmQsIHRhcmdldEluZCwgbGVuZ3RoKSwgc2hvcnRlc3RQYXRoID0gc3BDYWxjLlBhdGhGcm9tTm9kZVRvTm9kZShzdGFydC5pZCwgZW5kLmlkKTtcbiAgICAgICAgaWYgKHNob3J0ZXN0UGF0aC5sZW5ndGggPT09IDEgfHwgc2hvcnRlc3RQYXRoLmxlbmd0aCA9PT0gdmcyLlYubGVuZ3RoKSB7XG4gICAgICAgICAgICB2YXIgcm91dGUgPSByZWN0YW5nbGVfMS5tYWtlRWRnZUJldHdlZW4oZWRnZS5zb3VyY2UuaW5uZXJCb3VuZHMsIGVkZ2UudGFyZ2V0LmlubmVyQm91bmRzLCBhaCk7XG4gICAgICAgICAgICBsaW5lRGF0YSA9IFtyb3V0ZS5zb3VyY2VJbnRlcnNlY3Rpb24sIHJvdXRlLmFycm93U3RhcnRdO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgdmFyIG4gPSBzaG9ydGVzdFBhdGgubGVuZ3RoIC0gMiwgcCA9IHZnMi5WW3Nob3J0ZXN0UGF0aFtuXV0ucCwgcSA9IHZnMi5WW3Nob3J0ZXN0UGF0aFswXV0ucCwgbGluZURhdGEgPSBbZWRnZS5zb3VyY2UuaW5uZXJCb3VuZHMucmF5SW50ZXJzZWN0aW9uKHAueCwgcC55KV07XG4gICAgICAgICAgICBmb3IgKHZhciBpID0gbjsgaSA+PSAwOyAtLWkpXG4gICAgICAgICAgICAgICAgbGluZURhdGEucHVzaCh2ZzIuVltzaG9ydGVzdFBhdGhbaV1dLnApO1xuICAgICAgICAgICAgbGluZURhdGEucHVzaChyZWN0YW5nbGVfMS5tYWtlRWRnZVRvKHEsIGVkZ2UudGFyZ2V0LmlubmVyQm91bmRzLCBhaCkpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBsaW5lRGF0YTtcbiAgICB9O1xuICAgIExheW91dC5nZXRTb3VyY2VJbmRleCA9IGZ1bmN0aW9uIChlKSB7XG4gICAgICAgIHJldHVybiB0eXBlb2YgZS5zb3VyY2UgPT09ICdudW1iZXInID8gZS5zb3VyY2UgOiBlLnNvdXJjZS5pbmRleDtcbiAgICB9O1xuICAgIExheW91dC5nZXRUYXJnZXRJbmRleCA9IGZ1bmN0aW9uIChlKSB7XG4gICAgICAgIHJldHVybiB0eXBlb2YgZS50YXJnZXQgPT09ICdudW1iZXInID8gZS50YXJnZXQgOiBlLnRhcmdldC5pbmRleDtcbiAgICB9O1xuICAgIExheW91dC5saW5rSWQgPSBmdW5jdGlvbiAoZSkge1xuICAgICAgICByZXR1cm4gTGF5b3V0LmdldFNvdXJjZUluZGV4KGUpICsgXCItXCIgKyBMYXlvdXQuZ2V0VGFyZ2V0SW5kZXgoZSk7XG4gICAgfTtcbiAgICBMYXlvdXQuZHJhZ1N0YXJ0ID0gZnVuY3Rpb24gKGQpIHtcbiAgICAgICAgaWYgKGlzR3JvdXAoZCkpIHtcbiAgICAgICAgICAgIExheW91dC5zdG9yZU9mZnNldChkLCBMYXlvdXQuZHJhZ09yaWdpbihkKSk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICBMYXlvdXQuc3RvcE5vZGUoZCk7XG4gICAgICAgICAgICBkLmZpeGVkIHw9IDI7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIExheW91dC5zdG9wTm9kZSA9IGZ1bmN0aW9uICh2KSB7XG4gICAgICAgIHYucHggPSB2Lng7XG4gICAgICAgIHYucHkgPSB2Lnk7XG4gICAgfTtcbiAgICBMYXlvdXQuc3RvcmVPZmZzZXQgPSBmdW5jdGlvbiAoZCwgb3JpZ2luKSB7XG4gICAgICAgIGlmICh0eXBlb2YgZC5sZWF2ZXMgIT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgICAgICBkLmxlYXZlcy5mb3JFYWNoKGZ1bmN0aW9uICh2KSB7XG4gICAgICAgICAgICAgICAgdi5maXhlZCB8PSAyO1xuICAgICAgICAgICAgICAgIExheW91dC5zdG9wTm9kZSh2KTtcbiAgICAgICAgICAgICAgICB2Ll9kcmFnR3JvdXBPZmZzZXRYID0gdi54IC0gb3JpZ2luLng7XG4gICAgICAgICAgICAgICAgdi5fZHJhZ0dyb3VwT2Zmc2V0WSA9IHYueSAtIG9yaWdpbi55O1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHR5cGVvZiBkLmdyb3VwcyAhPT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgICAgIGQuZ3JvdXBzLmZvckVhY2goZnVuY3Rpb24gKGcpIHsgcmV0dXJuIExheW91dC5zdG9yZU9mZnNldChnLCBvcmlnaW4pOyB9KTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgTGF5b3V0LmRyYWdPcmlnaW4gPSBmdW5jdGlvbiAoZCkge1xuICAgICAgICBpZiAoaXNHcm91cChkKSkge1xuICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICB4OiBkLmJvdW5kcy5jeCgpLFxuICAgICAgICAgICAgICAgIHk6IGQuYm91bmRzLmN5KClcbiAgICAgICAgICAgIH07XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICByZXR1cm4gZDtcbiAgICAgICAgfVxuICAgIH07XG4gICAgTGF5b3V0LmRyYWcgPSBmdW5jdGlvbiAoZCwgcG9zaXRpb24pIHtcbiAgICAgICAgaWYgKGlzR3JvdXAoZCkpIHtcbiAgICAgICAgICAgIGlmICh0eXBlb2YgZC5sZWF2ZXMgIT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgICAgICAgICAgZC5sZWF2ZXMuZm9yRWFjaChmdW5jdGlvbiAodikge1xuICAgICAgICAgICAgICAgICAgICBkLmJvdW5kcy5zZXRYQ2VudHJlKHBvc2l0aW9uLngpO1xuICAgICAgICAgICAgICAgICAgICBkLmJvdW5kcy5zZXRZQ2VudHJlKHBvc2l0aW9uLnkpO1xuICAgICAgICAgICAgICAgICAgICB2LnB4ID0gdi5fZHJhZ0dyb3VwT2Zmc2V0WCArIHBvc2l0aW9uLng7XG4gICAgICAgICAgICAgICAgICAgIHYucHkgPSB2Ll9kcmFnR3JvdXBPZmZzZXRZICsgcG9zaXRpb24ueTtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICh0eXBlb2YgZC5ncm91cHMgIT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgICAgICAgICAgZC5ncm91cHMuZm9yRWFjaChmdW5jdGlvbiAoZykgeyByZXR1cm4gTGF5b3V0LmRyYWcoZywgcG9zaXRpb24pOyB9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIGQucHggPSBwb3NpdGlvbi54O1xuICAgICAgICAgICAgZC5weSA9IHBvc2l0aW9uLnk7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIExheW91dC5kcmFnRW5kID0gZnVuY3Rpb24gKGQpIHtcbiAgICAgICAgaWYgKGlzR3JvdXAoZCkpIHtcbiAgICAgICAgICAgIGlmICh0eXBlb2YgZC5sZWF2ZXMgIT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgICAgICAgICAgZC5sZWF2ZXMuZm9yRWFjaChmdW5jdGlvbiAodikge1xuICAgICAgICAgICAgICAgICAgICBMYXlvdXQuZHJhZ0VuZCh2KTtcbiAgICAgICAgICAgICAgICAgICAgZGVsZXRlIHYuX2RyYWdHcm91cE9mZnNldFg7XG4gICAgICAgICAgICAgICAgICAgIGRlbGV0ZSB2Ll9kcmFnR3JvdXBPZmZzZXRZO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHR5cGVvZiBkLmdyb3VwcyAhPT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgICAgICAgICBkLmdyb3Vwcy5mb3JFYWNoKExheW91dC5kcmFnRW5kKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIGQuZml4ZWQgJj0gfjY7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIExheW91dC5tb3VzZU92ZXIgPSBmdW5jdGlvbiAoZCkge1xuICAgICAgICBkLmZpeGVkIHw9IDQ7XG4gICAgICAgIGQucHggPSBkLngsIGQucHkgPSBkLnk7XG4gICAgfTtcbiAgICBMYXlvdXQubW91c2VPdXQgPSBmdW5jdGlvbiAoZCkge1xuICAgICAgICBkLmZpeGVkICY9IH40O1xuICAgIH07XG4gICAgcmV0dXJuIExheW91dDtcbn0oKSk7XG5leHBvcnRzLkxheW91dCA9IExheW91dDtcbi8vIyBzb3VyY2VNYXBwaW5nVVJMPWRhdGE6YXBwbGljYXRpb24vanNvbjtiYXNlNjQsZXlKMlpYSnphVzl1SWpvekxDSm1hV3hsSWpvaWJHRjViM1YwTG1weklpd2ljMjkxY21ObFVtOXZkQ0k2SWlJc0luTnZkWEpqWlhNaU9sc2lMaTR2TGk0dlYyVmlRMjlzWVM5emNtTXZiR0Y1YjNWMExuUnpJbDBzSW01aGJXVnpJanBiWFN3aWJXRndjR2x1WjNNaU9pSTdPMEZCUVVFc2VVTkJRVEJETzBGQlF6RkRMRFpEUVVFclNEdEJRVU12U0N4eFEwRkJhVU03UVVGRGFrTXNlVU5CUVRoRk8wRkJRemxGTEdsRVFVRXdRenRCUVVNeFF5d3JRa0ZCZFVRN1FVRkRka1FzTWtSQlFXbEZPMEZCVHpkRUxFbEJRVmtzVTBGQk9FSTdRVUZCTVVNc1YwRkJXU3hUUVVGVE8wbEJRVWNzTWtOQlFVc3NRMEZCUVR0SlFVRkZMSGxEUVVGSkxFTkJRVUU3U1VGQlJTeDFRMEZCUnl4RFFVRkJPMEZCUVVNc1EwRkJReXhGUVVFNVFpeFRRVUZUTEVkQlFWUXNhVUpCUVZNc1MwRkJWQ3hwUWtGQlV5eFJRVUZ4UWp0QlFVRkJMRU5CUVVNN1FVRXJRek5ETEZOQlFWTXNUMEZCVHl4RFFVRkRMRU5CUVUwN1NVRkRia0lzVDBGQlR5eFBRVUZQTEVOQlFVTXNRMEZCUXl4TlFVRk5MRXRCUVVzc1YwRkJWeXhKUVVGSkxFOUJRVThzUTBGQlF5eERRVUZETEUxQlFVMHNTMEZCU3l4WFFVRlhMRU5CUVVNN1FVRkRPVVVzUTBGQlF6dEJRWGRDUkR0SlFVRkJPMUZCUVVFc2FVSkJhM2xDUXp0UlFXcDVRbGNzWjBKQlFWY3NSMEZCUnl4RFFVRkRMRU5CUVVNc1JVRkJSU3hEUVVGRExFTkJRVU1zUTBGQlF6dFJRVU55UWl4clFrRkJZU3hIUVVGNVF5eEZRVUZGTEVOQlFVTTdVVUZEZWtRc2NVSkJRV2RDTEVkQlFWY3NSVUZCUlN4RFFVRkRPMUZCUXpsQ0xEQkNRVUZ4UWl4SFFVRkhMRWxCUVVrc1EwRkJRenRSUVVNM1FpeGpRVUZUTEVkQlFVY3NTVUZCU1N4RFFVRkRPMUZCUTJwQ0xHMUNRVUZqTEVkQlFVY3NTMEZCU3l4RFFVRkRPMUZCUTNaQ0xIZENRVUZ0UWl4SFFVRkhMRWxCUVVrc1EwRkJRenRSUVVjelFpeGhRVUZSTEVkQlFVY3NTMEZCU3l4RFFVRkRPMUZCUTJwQ0xGZEJRVTBzUjBGQlJ5eEZRVUZGTEVOQlFVTTdVVUZEV2l4WlFVRlBMRWRCUVVjc1JVRkJSU3hEUVVGRE8xRkJRMklzWlVGQlZTeEhRVUZITEVsQlFVa3NRMEZCUXp0UlFVTnNRaXhYUVVGTkxFZEJRVEJDTEVWQlFVVXNRMEZCUXp0UlFVTnVReXhwUWtGQldTeEhRVUZITEVWQlFVVXNRMEZCUXp0UlFVTnNRaXh2UWtGQlpTeEhRVUZITEVsQlFVa3NRMEZCUXp0UlFVTjJRaXhoUVVGUkxFZEJRVmtzU1VGQlNTeERRVUZETzFGQlEzcENMRFpDUVVGM1FpeEhRVUZITEVsQlFVa3NRMEZCUXp0UlFVTm9ReXhsUVVGVkxFZEJRVWNzU1VGQlNTeERRVUZETzFGQlEyeENMSEZDUVVGblFpeEhRVUZITEVsQlFVa3NRMEZCUXp0UlFVTjRRaXh6UWtGQmFVSXNSMEZCUnl4SlFVRkpMRU5CUVVNN1VVRkhka0lzVlVGQlN5eEhRVUZITEVsQlFVa3NRMEZCUXp0UlFXdFdka0lzYVVKQlFWa3NSMEZCTWtJN1dVRkRia01zWTBGQll5eEZRVUZGTEUxQlFVMHNRMEZCUXl4alFVRmpPMWxCUTNKRExHTkJRV01zUlVGQlJTeE5RVUZOTEVOQlFVTXNZMEZCWXp0WlFVTnlReXhUUVVGVExFVkJRVVVzVFVGQlRTeERRVUZETEdGQlFXRTdXVUZETDBJc1QwRkJUeXhGUVVGRkxGVkJRVUVzUTBGQlF5eEpRVUZKTEU5QlFVRXNUMEZCVHl4TFFVRkpMRU5CUVVNc1UwRkJVeXhMUVVGTExGVkJRVlVzUTBGQlF5eERRVUZETEVOQlFVTXNTMEZCU1N4RFFVRkRMRk5CUVZNc1EwRkJReXhEUVVGRExFTkJRVU1zUTBGQlF5eERRVUZETEVOQlFVTXNRMEZCUXl4RlFVRTFSQ3hEUVVFMFJEdFRRVU0zUlN4RFFVRkRPMGxCYldKT0xFTkJRVU03U1VGMGQwSlZMRzFDUVVGRkxFZEJRVlFzVlVGQlZTeERRVUZ4UWl4RlFVRkZMRkZCUVdsRE8xRkJSVGxFTEVsQlFVa3NRMEZCUXl4SlFVRkpMRU5CUVVNc1MwRkJTenRaUVVGRkxFbEJRVWtzUTBGQlF5eExRVUZMTEVkQlFVY3NSVUZCUlN4RFFVRkRPMUZCUTJwRExFbEJRVWtzVDBGQlR5eERRVUZETEV0QlFVc3NVVUZCVVN4RlFVRkZPMWxCUTNaQ0xFbEJRVWtzUTBGQlF5eExRVUZMTEVOQlFVTXNVMEZCVXl4RFFVRkRMRU5CUVVNc1EwRkJReXhEUVVGRExFZEJRVWNzVVVGQlVTeERRVUZETzFOQlEzWkRPMkZCUVUwN1dVRkRTQ3hKUVVGSkxFTkJRVU1zUzBGQlN5eERRVUZETEVOQlFVTXNRMEZCUXl4SFFVRkhMRkZCUVZFc1EwRkJRenRUUVVNMVFqdFJRVU5FTEU5QlFVOHNTVUZCU1N4RFFVRkRPMGxCUTJoQ0xFTkJRVU03U1VGSlV5eDNRa0ZCVHl4SFFVRnFRaXhWUVVGclFpeERRVUZSTzFGQlEzUkNMRWxCUVVrc1NVRkJTU3hEUVVGRExFdEJRVXNzU1VGQlNTeFBRVUZQTEVsQlFVa3NRMEZCUXl4TFFVRkxMRU5CUVVNc1EwRkJReXhEUVVGRExFbEJRVWtzUTBGQlF5eExRVUZMTEZkQlFWY3NSVUZCUlR0WlFVTjZSQ3hKUVVGSkxFTkJRVU1zUzBGQlN5eERRVUZETEVOQlFVTXNRMEZCUXl4SlFVRkpMRU5CUVVNc1EwRkJReXhEUVVGRExFTkJRVU1zUTBGQlF6dFRRVU42UWp0SlFVTk1MRU5CUVVNN1NVRkxVeXh4UWtGQlNTeEhRVUZrTzFGQlEwa3NUMEZCVHl4RFFVRkRMRWxCUVVrc1EwRkJReXhKUVVGSkxFVkJRVVU3V1VGQlF5eERRVUZETzBsQlEzcENMRU5CUVVNN1NVRkxVeXh4UWtGQlNTeEhRVUZrTzFGQlEwa3NTVUZCU1N4SlFVRkpMRU5CUVVNc1RVRkJUU3hIUVVGSExFbEJRVWtzUTBGQlF5eFZRVUZWTEVWQlFVVTdXVUZETDBJc1NVRkJTU3hEUVVGRExGRkJRVkVzUjBGQlJ5eExRVUZMTEVOQlFVTTdXVUZEZEVJc1NVRkJTU3hEUVVGRExFOUJRVThzUTBGQlF5eEZRVUZGTEVsQlFVa3NSVUZCUlN4VFFVRlRMRU5CUVVNc1IwRkJSeXhGUVVGRkxFdEJRVXNzUlVGQlJTeEpRVUZKTEVOQlFVTXNUVUZCVFN4SFFVRkhMRU5CUVVNc1JVRkJSU3hOUVVGTkxFVkJRVVVzU1VGQlNTeERRVUZETEZkQlFWY3NSVUZCUlN4RFFVRkRMRU5CUVVNN1dVRkRlRVlzVDBGQlR5eEpRVUZKTEVOQlFVTTdVMEZEWmp0UlFVTkVMRWxCUVUwc1EwRkJReXhIUVVGSExFbEJRVWtzUTBGQlF5eE5RVUZOTEVOQlFVTXNUVUZCVFN4RlFVTjBRaXhEUVVGRExFZEJRVWNzU1VGQlNTeERRVUZETEUxQlFVMHNRMEZCUXl4TlFVRk5MRU5CUVVNN1VVRkROMElzU1VGQlNTeERRVUZETEVWQlFVVXNRMEZCUXl4RFFVRkRPMUZCUlZRc1NVRkJTU3hEUVVGRExGRkJRVkVzUTBGQlF5eExRVUZMTEVOQlFVTXNTMEZCU3l4RlFVRkZMRU5CUVVNN1VVRkROVUlzUzBGQlN5eERRVUZETEVkQlFVY3NRMEZCUXl4RlFVRkZMRU5CUVVNc1IwRkJSeXhEUVVGRExFVkJRVVVzUlVGQlJTeERRVUZETEVWQlFVVTdXVUZEY0VJc1EwRkJReXhIUVVGSExFbEJRVWtzUTBGQlF5eE5RVUZOTEVOQlFVTXNRMEZCUXl4RFFVRkRMRU5CUVVNN1dVRkRia0lzU1VGQlNTeERRVUZETEVOQlFVTXNTMEZCU3l4RlFVRkZPMmRDUVVOVUxFbEJRVWtzVDBGQlR5eERRVUZETEVOQlFVTXNSVUZCUlN4TFFVRkxMRmRCUVZjc1NVRkJTU3hQUVVGUExFTkJRVU1zUTBGQlF5eEZRVUZGTEV0QlFVc3NWMEZCVnl4RlFVRkZPMjlDUVVNMVJDeERRVUZETEVOQlFVTXNSVUZCUlN4SFFVRkhMRU5CUVVNc1EwRkJReXhEUVVGRExFTkJRVU03YjBKQlExZ3NRMEZCUXl4RFFVRkRMRVZCUVVVc1IwRkJSeXhEUVVGRExFTkJRVU1zUTBGQlF5eERRVUZETzJsQ1FVTmtPMmRDUVVORUxFbEJRVWtzUTBGQlF5eEhRVUZITEVOQlFVTXNRMEZCUXl4RFFVRkRMRVZCUVVVc1JVRkJSU3hEUVVGRExFTkJRVU1zUlVGQlJTeERRVUZETEVOQlFVTTdaMEpCUTNKQ0xFbEJRVWtzUTBGQlF5eFJRVUZSTEVOQlFVTXNTMEZCU3l4RFFVRkRMRWRCUVVjc1EwRkJReXhEUVVGRExFVkJRVVVzUTBGQlF5eERRVUZETEVOQlFVTTdZVUZEYWtNN1UwRkRTanRSUVVWRUxFbEJRVWtzUlVGQlJTeEhRVUZITEVsQlFVa3NRMEZCUXl4UlFVRlJMRU5CUVVNc1ZVRkJWU3hGUVVGRkxFTkJRVU03VVVGRmNFTXNTVUZCU1N4RlFVRkZMRXRCUVVzc1EwRkJReXhGUVVGRk8xbEJRMVlzU1VGQlNTeERRVUZETEUxQlFVMHNSMEZCUnl4RFFVRkRMRU5CUVVNN1UwRkRia0k3WVVGQlRTeEpRVUZKTEU5QlFVOHNTVUZCU1N4RFFVRkRMRmRCUVZjc1MwRkJTeXhYUVVGWExFVkJRVVU3V1VGRGFFUXNTVUZCU1N4RFFVRkRMRTFCUVUwc1IwRkJSeXhGUVVGRkxFTkJRVU03VTBGRGNFSTdVVUZEUkN4SlFVRkpMRU5CUVVNc1YwRkJWeXhIUVVGSExFVkJRVVVzUTBGQlF6dFJRVVYwUWl4SlFVRkpMRU5CUVVNc2JVSkJRVzFDTEVWQlFVVXNRMEZCUXp0UlFVVXpRaXhKUVVGSkxFTkJRVU1zVDBGQlR5eERRVUZETEVWQlFVVXNTVUZCU1N4RlFVRkZMRk5CUVZNc1EwRkJReXhKUVVGSkxFVkJRVVVzUzBGQlN5eEZRVUZGTEVsQlFVa3NRMEZCUXl4TlFVRk5MRVZCUVVVc1RVRkJUU3hGUVVGRkxFbEJRVWtzUTBGQlF5eFhRVUZYTEVWQlFVVXNRMEZCUXl4RFFVRkRPMUZCUTNKR0xFOUJRVThzUzBGQlN5eERRVUZETzBsQlEycENMRU5CUVVNN1NVRkhUeXh2UTBGQmJVSXNSMEZCTTBJN1VVRkRTU3hKUVVGTkxFTkJRVU1zUjBGQlJ5eEpRVUZKTEVOQlFVTXNVVUZCVVN4RFFVRkRMRU5CUVVNc1EwRkJReXhEUVVGRExFTkJRVU1zUlVGQlJTeERRVUZETEVkQlFVY3NTVUZCU1N4RFFVRkRMRkZCUVZFc1EwRkJReXhEUVVGRExFTkJRVU1zUTBGQlF5eERRVUZETEVOQlFVTTdVVUZEY2tRc1NVRkJTU3hEUVVGRExFVkJRVVVzUTBGQlF5eEhRVUZITEVsQlFVa3NRMEZCUXl4TlFVRk5MRU5CUVVNc1RVRkJUU3hEUVVGRE8xRkJRemxDTEU5QlFVOHNRMEZCUXl4RlFVRkZMRVZCUVVVN1dVRkRVaXhEUVVGRExFZEJRVWNzU1VGQlNTeERRVUZETEUxQlFVMHNRMEZCUXl4RFFVRkRMRU5CUVVNc1EwRkJRenRaUVVOdVFpeERRVUZETEVOQlFVTXNRMEZCUXl4SFFVRkhMRU5CUVVNc1EwRkJReXhEUVVGRExFTkJRVU1zUTBGQlF6dFpRVU5ZTEVOQlFVTXNRMEZCUXl4RFFVRkRMRWRCUVVjc1EwRkJReXhEUVVGRExFTkJRVU1zUTBGQlF5eERRVUZETzFOQlEyUTdTVUZEVEN4RFFVRkRPMGxCVjBRc2MwSkJRVXNzUjBGQlRDeFZRVUZOTEVOQlFVODdVVUZEVkN4SlFVRkpMRU5CUVVNc1EwRkJReXhGUVVGRk8xbEJRMG9zU1VGQlNTeEpRVUZKTEVOQlFVTXNUVUZCVFN4RFFVRkRMRTFCUVUwc1MwRkJTeXhEUVVGRExFbEJRVWtzU1VGQlNTeERRVUZETEUxQlFVMHNRMEZCUXl4TlFVRk5MRWRCUVVjc1EwRkJReXhGUVVGRk8yZENRVWR3UkN4SlFVRkpMRU5CUVVNc1IwRkJSeXhEUVVGRExFTkJRVU03WjBKQlExWXNTVUZCU1N4RFFVRkRMRTFCUVUwc1EwRkJReXhQUVVGUExFTkJRVU1zVlVGQlZTeERRVUZETzI5Q1FVTXpRaXhEUVVGRExFZEJRVWNzU1VGQlNTeERRVUZETEVkQlFVY3NRMEZCUXl4RFFVRkRMRVZCUVZVc1EwRkJReXhEUVVGRExFMUJRVTBzUlVGQlZTeERRVUZETEVOQlFVTXNUVUZCVFN4RFFVRkRMRU5CUVVNN1owSkJRM2hFTEVOQlFVTXNRMEZCUXl4RFFVRkRPMmRDUVVOSUxFbEJRVWtzUTBGQlF5eE5RVUZOTEVkQlFVY3NTVUZCU1N4TFFVRkxMRU5CUVVNc1JVRkJSU3hEUVVGRExFTkJRVU1zUTBGQlF6dG5Ra0ZETjBJc1MwRkJTeXhKUVVGSkxFTkJRVU1zUjBGQlJ5eERRVUZETEVWQlFVVXNRMEZCUXl4SFFVRkhMRU5CUVVNc1JVRkJSU3hGUVVGRkxFTkJRVU1zUlVGQlJUdHZRa0ZEZUVJc1NVRkJTU3hEUVVGRExFMUJRVTBzUTBGQlF5eERRVUZETEVOQlFVTXNSMEZCUnl4RlFVRkZMRU5CUVVNN2FVSkJRM1pDTzJGQlEwbzdXVUZEUkN4UFFVRlBMRWxCUVVrc1EwRkJReXhOUVVGTkxFTkJRVU03VTBGRGRFSTdVVUZEUkN4SlFVRkpMRU5CUVVNc1RVRkJUU3hIUVVGSExFTkJRVU1zUTBGQlF6dFJRVU5vUWl4UFFVRlBMRWxCUVVrc1EwRkJRenRKUVVOb1FpeERRVUZETzBsQlUwUXNkVUpCUVUwc1IwRkJUaXhWUVVGUExFTkJRV2RDTzFGQlFYWkNMR2xDUVhWQ1F6dFJRWFJDUnl4SlFVRkpMRU5CUVVNc1EwRkJRenRaUVVGRkxFOUJRVThzU1VGQlNTeERRVUZETEU5QlFVOHNRMEZCUXp0UlFVTTFRaXhKUVVGSkxFTkJRVU1zVDBGQlR5eEhRVUZITEVOQlFVTXNRMEZCUXp0UlFVTnFRaXhKUVVGSkxFTkJRVU1zVlVGQlZTeEhRVUZITEVWQlFVVXNRMEZCUXp0UlFVTnlRaXhKUVVGSkxFTkJRVU1zVDBGQlR5eERRVUZETEU5QlFVOHNRMEZCUXl4VlFVRkJMRU5CUVVNN1dVRkRiRUlzU1VGQlNTeFBRVUZQTEVOQlFVTXNRMEZCUXl4UFFVRlBMRXRCUVVzc1YwRkJWenRuUWtGRGFFTXNRMEZCUXl4RFFVRkRMRTlCUVU4c1IwRkJSeXhEUVVGRExFTkJRVU03V1VGRGJFSXNTVUZCU1N4UFFVRlBMRU5CUVVNc1EwRkJReXhOUVVGTkxFdEJRVXNzVjBGQlZ5eEZRVUZGTzJkQ1FVTnFReXhEUVVGRExFTkJRVU1zVFVGQlRTeERRVUZETEU5QlFVOHNRMEZCUXl4VlFVRkRMRU5CUVVNc1JVRkJSU3hEUVVGRE8yOUNRVU5zUWl4SlFVRkpMRTlCUVU4c1EwRkJReXhMUVVGTExGRkJRVkU3ZDBKQlEzSkNMRU5CUVVNc1EwRkJReXhEUVVGRExFMUJRVTBzUTBGQlF5eERRVUZETEVOQlFVTXNSMEZCUnl4TFFVRkpMRU5CUVVNc1RVRkJUU3hEUVVGRExFTkJRVU1zUTBGQlF5eERRVUZETEVOQlFVTXNUVUZCVFN4SFFVRkhMRU5CUVVNc1EwRkJRVHRuUWtGRGFrUXNRMEZCUXl4RFFVRkRMRU5CUVVNN1lVRkRUanRaUVVORUxFbEJRVWtzVDBGQlR5eERRVUZETEVOQlFVTXNUVUZCVFN4TFFVRkxMRmRCUVZjc1JVRkJSVHRuUWtGRGFrTXNRMEZCUXl4RFFVRkRMRTFCUVUwc1EwRkJReXhQUVVGUExFTkJRVU1zVlVGQlF5eEZRVUZGTEVWQlFVVXNRMEZCUXp0dlFrRkRia0lzU1VGQlNTeFBRVUZQTEVWQlFVVXNTMEZCU3l4UlFVRlJPM2RDUVVOMFFpeERRVUZETEVOQlFVTXNRMEZCUXl4TlFVRk5MRU5CUVVNc1EwRkJReXhEUVVGRExFZEJRVWNzUzBGQlNTeERRVUZETEU5QlFVOHNRMEZCUXl4RlFVRkZMRU5CUVVNc1EwRkJReXhEUVVGRExFMUJRVTBzUjBGQlJ5eERRVUZETEVOQlFVRTdaMEpCUTI1RUxFTkJRVU1zUTBGQlF5eERRVUZETzJGQlEwNDdVVUZEVEN4RFFVRkRMRU5CUVVNc1EwRkJRenRSUVVOSUxFbEJRVWtzUTBGQlF5eFZRVUZWTEVOQlFVTXNUVUZCVFN4SFFVRkhMRWxCUVVrc1EwRkJReXhOUVVGTkxFTkJRVU1zVFVGQlRTeERRVUZETEZWQlFVRXNRMEZCUXl4SlFVRkpMRTlCUVVFc1QwRkJUeXhEUVVGRExFTkJRVU1zVFVGQlRTeExRVUZMTEZkQlFWY3NSVUZCTDBJc1EwRkJLMElzUTBGQlF5eERRVUZETzFGQlEyeEdMRWxCUVVrc1EwRkJReXhWUVVGVkxFTkJRVU1zVFVGQlRTeEhRVUZITEVsQlFVa3NRMEZCUXl4UFFVRlBMRU5CUVVNc1RVRkJUU3hEUVVGRExGVkJRVUVzUTBGQlF5eEpRVUZKTEU5QlFVRXNUMEZCVHl4RFFVRkRMRU5CUVVNc1RVRkJUU3hMUVVGTExGZEJRVmNzUlVGQkwwSXNRMEZCSzBJc1EwRkJReXhEUVVGRE8xRkJRMjVHTEU5QlFVOHNTVUZCU1N4RFFVRkRPMGxCUTJoQ0xFTkJRVU03U1VGRlJDeHBRMEZCWjBJc1IwRkJhRUlzVlVGQmFVSXNRMEZCVnp0UlFVTjRRaXhKUVVGSkxFTkJRVU1zUjBGQlJ5eFZRVUZWTEVOQlFVTXNVMEZCVXl4RFFVRkRMRWxCUVVrc1EwRkJReXhOUVVGTkxFVkJRVVVzU1VGQlNTeERRVUZETEUxQlFVMHNSVUZCUlN4SlFVRkpMRU5CUVVNc1dVRkJXU3hGUVVGRkxFbEJRVWtzUTBGQlF5eFZRVUZWTEVOQlFVTXNRMEZCUXp0UlFVTXpSaXhKUVVGSkxFTkJRVU1zVFVGQlRTeERRVUZETEVOQlFVTXNRMEZCUXl4TlFVRk5MRU5CUVVNc1EwRkJRenRSUVVOMFFpeERRVUZETEVOQlFVTXNRMEZCUXl4RFFVRkRMRU5CUVVNN1VVRkRUQ3hQUVVGUExFbEJRVWtzUTBGQlF6dEpRVU5vUWl4RFFVRkRPMGxCVlVRc09FSkJRV0VzUjBGQllpeFZRVUZqTEVOQlFWYzdVVUZEY2tJc1NVRkJTU3hEUVVGRExGTkJRVk1zUTBGQlF5eE5RVUZOTzFsQlFVVXNUMEZCVHl4SlFVRkpMRU5CUVVNc1kwRkJZeXhEUVVGRE8xRkJRMnhFTEVsQlFVa3NRMEZCUXl4alFVRmpMRWRCUVVjc1EwRkJReXhEUVVGRE8xRkJRM2hDTEU5QlFVOHNTVUZCU1N4RFFVRkRPMGxCUTJoQ0xFTkJRVU03U1VGWlJDeHRRMEZCYTBJc1IwRkJiRUlzVlVGQmJVSXNRMEZCVnp0UlFVTXhRaXhKUVVGSkxFTkJRVU1zVTBGQlV5eERRVUZETEUxQlFVMDdXVUZCUlN4UFFVRlBMRWxCUVVrc1EwRkJReXh0UWtGQmJVSXNRMEZCUXp0UlFVTjJSQ3hKUVVGSkxFTkJRVU1zYlVKQlFXMUNMRWRCUVVjc1EwRkJReXhEUVVGRE8xRkJRemRDTEU5QlFVOHNTVUZCU1N4RFFVRkRPMGxCUTJoQ0xFTkJRVU03U1VGUlJDd3lRa0ZCVlN4SFFVRldMRlZCUVZjc1NVRkJXU3hGUVVGRkxHRkJRWGRETzFGQlF6ZEVMRWxCUVVrc1EwRkJReXhUUVVGVExFTkJRVU1zVFVGQlRUdFpRVUZGTEVsQlFVa3NSMEZCUnl4SFFVRkhMRU5CUVVNN1VVRkRiRU1zU1VGQlNTeERRVUZETEhkQ1FVRjNRaXhIUVVGSE8xbEJRelZDTEVsQlFVa3NSVUZCUlN4SlFVRkpPMWxCUTFZc1owSkJRV2RDTEVWQlFVVXNUMEZCVHl4aFFVRmhMRXRCUVVzc1VVRkJVU3hEUVVGRExFTkJRVU1zUTBGQlF5eGpRVUZqTEU5QlFVOHNZVUZCWVN4RFFVRkJMRU5CUVVNc1EwRkJReXhEUVVGRExFTkJRVU1zUTBGQlF5eGhRVUZoTzFOQlF6ZEhMRU5CUVVNN1VVRkRSaXhQUVVGUExFbEJRVWtzUTBGQlF6dEpRVU5vUWl4RFFVRkRPMGxCVTBRc2MwSkJRVXNzUjBGQlRDeFZRVUZOTEVOQlFUUkNPMUZCUXpsQ0xFbEJRVWtzUTBGQlF5eFRRVUZUTEVOQlFVTXNUVUZCVFR0WlFVRkZMRTlCUVU4c1NVRkJTU3hEUVVGRExFMUJRVTBzUTBGQlF6dFJRVU14UXl4SlFVRkpMRU5CUVVNc1RVRkJUU3hIUVVGSExFTkJRVU1zUTBGQlF6dFJRVU5vUWl4UFFVRlBMRWxCUVVrc1EwRkJRenRKUVVOb1FpeERRVUZETzBsQlZVUXNORUpCUVZjc1IwRkJXQ3hWUVVGWkxFTkJRV003VVVGRGRFSXNTVUZCU1N4RFFVRkRMRk5CUVZNc1EwRkJReXhOUVVGTk8xbEJRVVVzVDBGQlR5eEpRVUZKTEVOQlFVTXNXVUZCV1N4RFFVRkRPMUZCUTJoRUxFbEJRVWtzUTBGQlF5eFpRVUZaTEVkQlFVY3NRMEZCUXl4RFFVRkRPMUZCUTNSQ0xFOUJRVThzU1VGQlNTeERRVUZETzBsQlEyaENMRU5CUVVNN1NVRlhSQ3dyUWtGQll5eEhRVUZrTEZWQlFXVXNRMEZCVHp0UlFVTnNRaXhKUVVGSkxFTkJRVU1zVTBGQlV5eERRVUZETEUxQlFVMDdXVUZCUlN4UFFVRlBMRWxCUVVrc1EwRkJReXhsUVVGbExFTkJRVU03VVVGRGJrUXNTVUZCU1N4RFFVRkRMR1ZCUVdVc1IwRkJSeXhEUVVGRExFTkJRVU03VVVGRGVrSXNUMEZCVHl4SlFVRkpMRU5CUVVNN1NVRkRhRUlzUTBGQlF6dEpRVlZFTEhGQ1FVRkpMRWRCUVVvc1ZVRkJTeXhEUVVGcFFqdFJRVU5zUWl4SlFVRkpMRU5CUVVNc1EwRkJRenRaUVVGRkxFOUJRVThzU1VGQlNTeERRVUZETEZkQlFWY3NRMEZCUXp0UlFVTm9ReXhKUVVGSkxFTkJRVU1zVjBGQlZ5eEhRVUZITEVOQlFVTXNRMEZCUXp0UlFVTnlRaXhQUVVGUExFbEJRVWtzUTBGQlF6dEpRVU5vUWl4RFFVRkRPMGxCVTBRc1owTkJRV1VzUjBGQlppeFZRVUZuUWl4RFFVRlBPMUZCUTI1Q0xFbEJRVWtzUTBGQlF5eERRVUZETzFsQlFVVXNUMEZCVHl4SlFVRkpMRU5CUVVNc1owSkJRV2RDTEVOQlFVTTdVVUZEY2tNc1NVRkJTU3hEUVVGRExHZENRVUZuUWl4SFFVRkhMRU5CUVVNc1EwRkJRenRSUVVNeFFpeFBRVUZQTEVsQlFVa3NRMEZCUXp0SlFVTm9RaXhEUVVGRE8wbEJVMFFzYVVOQlFXZENMRWRCUVdoQ0xGVkJRV2xDTEVOQlFVODdVVUZEY0VJc1NVRkJTU3hEUVVGRExFTkJRVU03V1VGQlJTeFBRVUZQTEVsQlFVa3NRMEZCUXl4cFFrRkJhVUlzUTBGQlF6dFJRVU4wUXl4SlFVRkpMRU5CUVVNc2FVSkJRV2xDTEVkQlFVY3NRMEZCUXl4RFFVRkRPMUZCUXpOQ0xFOUJRVThzU1VGQlNTeERRVUZETzBsQlEyaENMRU5CUVVNN1NVRlRSQ3cyUWtGQldTeEhRVUZhTEZWQlFXRXNRMEZCVHp0UlFVTm9RaXhKUVVGSkxFTkJRVU1zUTBGQlF5eEZRVUZGTzFsQlEwb3NUMEZCVHl4SlFVRkpMRU5CUVVNc1lVRkJZU3hEUVVGRE8xTkJRemRDTzFGQlEwUXNTVUZCU1N4RFFVRkRMR0ZCUVdFc1IwRkJSeXhQUVVGUExFTkJRVU1zUzBGQlN5eFZRVUZWTEVOQlFVTXNRMEZCUXl4RFFVRkRMRU5CUVVNc1EwRkJReXhEUVVGRExFTkJRVU1zUTBGQlF5eERRVUZETEVOQlFVTTdVVUZEZEVRc1NVRkJTU3hEUVVGRExIRkNRVUZ4UWl4SFFVRkhMRWxCUVVrc1EwRkJRenRSUVVOc1F5eFBRVUZQTEVsQlFVa3NRMEZCUXp0SlFVTm9RaXhEUVVGRE8wbEJSVVFzZVVKQlFWRXNSMEZCVWl4VlFVRlRMRU5CUVc5Q08xRkJRM3BDTEVsQlFVa3NRMEZCUXl4VFFVRlRMRWRCUVVjc1EwRkJReXhEUVVGRE8xRkJRMjVDTEU5QlFVOHNTVUZCU1N4RFFVRkRPMGxCUTJoQ0xFTkJRVU03U1VGSlJDeHhRMEZCYjBJc1IwRkJjRUlzVlVGQmNVSXNRMEZCVlR0UlFVTXpRaXhKUVVGSkxFTkJRVU1zUTBGQlF6dFpRVUZGTEU5QlFVOHNTVUZCU1N4RFFVRkRMRlZCUVZVc1EwRkJRenRSUVVNdlFpeEpRVUZKTEVOQlFVTXNWVUZCVlN4SFFVRkhMRTlCUVU4c1EwRkJReXhMUVVGTExGVkJRVlVzUTBGQlF5eERRVUZETEVOQlFVTXNRMEZCUXl4RFFVRkRMRU5CUVVNc1EwRkJReXhEUVVGRExFTkJRVU1zUTBGQlF6dFJRVU51UkN4UFFVRlBMRWxCUVVrc1EwRkJRenRKUVVOb1FpeERRVUZETzBsQlNVUXNjMEpCUVVzc1IwRkJUQ3hWUVVGTkxFTkJRVlU3VVVGRFdpeEpRVUZKTEVOQlFVTXNVMEZCVXl4RFFVRkRMRTFCUVUwN1dVRkJSU3hQUVVGUExFbEJRVWtzUTBGQlF5eE5RVUZOTEVOQlFVTTdZVUZEY2tNN1dVRkRSQ3hEUVVGRExFZEJRVWNzUTBGQlF5eERRVUZETEVOQlFVTTdXVUZEVUN4SlFVRkpMRWxCUVVrc1EwRkJReXhOUVVGTkxFVkJRVVU3WjBKQlEySXNTVUZCU1N4RFFVRkRMRWRCUVVjc1EwRkJRenR2UWtGQlJTeEpRVUZKTEVOQlFVTXNUVUZCVFN4SFFVRkhMRU5CUVVNc1EwRkJRenM3YjBKQlEzUkNMRWxCUVVrc1EwRkJReXhOUVVGTkxFZEJRVWNzUTBGQlF5eERRVUZETzJGQlEzaENPMmxDUVVGTkxFbEJRVWtzUTBGQlF5eEhRVUZITEVOQlFVTXNSVUZCUlR0blFrRkRaQ3hKUVVGSkxFTkJRVU1zU1VGQlNTeERRVUZETEZGQlFWRXNSVUZCUlR0dlFrRkRhRUlzU1VGQlNTeERRVUZETEZGQlFWRXNSMEZCUnl4SlFVRkpMRU5CUVVNN2IwSkJRM0pDTEVsQlFVa3NRMEZCUXl4UFFVRlBMRU5CUVVNc1JVRkJSU3hKUVVGSkxFVkJRVVVzVTBGQlV5eERRVUZETEV0QlFVc3NSVUZCUlN4TFFVRkxMRVZCUVVVc1NVRkJTU3hEUVVGRExFMUJRVTBzUjBGQlJ5eERRVUZETEVWQlFVTXNRMEZCUXl4RFFVRkRPMjlDUVVNdlJDeEpRVUZKTEVOQlFVTXNTVUZCU1N4RlFVRkZMRU5CUVVNN2FVSkJRMlk3WVVGRFNqdFpRVU5FTEU5QlFVOHNTVUZCU1N4RFFVRkRPMU5CUTJZN1NVRkRUQ3hEUVVGRE8wbEJSVVFzT0VKQlFXRXNSMEZCWWl4VlFVRmpMRWxCUVhsQ08xRkJRMjVETEU5QlFVOHNUMEZCVHl4SlFVRkpMRU5CUVVNc1lVRkJZU3hMUVVGTExGVkJRVlVzUTBGQlF5eERRVUZETEVOQlFVTXNRMEZCUXl4RFFVRXJRaXhKUVVGSkxFTkJRVU1zWVVGQll5eERRVUZETEVsQlFVa3NRMEZCUXl4RFFVRkRMRU5CUVVNc1EwRkJReXhEUVVGVExFbEJRVWtzUTBGQlF5eGhRVUZoTEVOQlFVTTdTVUZET1Vrc1EwRkJRenRKUVVWTkxHOUNRVUZoTEVkQlFYQkNMRlZCUVhGQ0xFbEJRWFZDTEVWQlFVVXNUVUZCWXp0UlFVTjRSQ3hKUVVGSkxFTkJRVU1zVFVGQlRTeEhRVUZITEUxQlFVMHNRMEZCUXp0SlFVTjZRaXhEUVVGRE8wbEJSVVFzTkVKQlFWY3NSMEZCV0N4VlFVRlpMRWxCUVhsQ08xRkJRMnBETEU5QlFVOHNUMEZCVHl4SlFVRkpMRU5CUVVNc1UwRkJVeXhMUVVGTExGVkJRVlVzUTBGQlF5eERRVUZETEVOQlFVTXNTVUZCU1N4RFFVRkRMRk5CUVZNc1EwRkJReXhKUVVGSkxFTkJRVU1zUTBGQlF5eERRVUZETEVOQlFVTXNRMEZCUXl4RFFVRkRPMGxCUXpORkxFTkJRVU03U1VGdFFrUXNlVU5CUVhkQ0xFZEJRWGhDTEZWQlFYbENMRmRCUVcxQ0xFVkJRVVVzUTBGQllUdFJRVUV6UkN4cFFrRkpRenRSUVVvMlF5eHJRa0ZCUVN4RlFVRkJMRXRCUVdFN1VVRkRka1FzU1VGQlNTeERRVUZETEZsQlFWa3NRMEZCUXl4VlFVRkJMRU5CUVVNc1NVRkJTU3hQUVVGQkxGZEJRVmNzUjBGQlJ5eERRVUZETEVOQlFVTXNUVUZCVFN4RlFVRjBRaXhEUVVGelFpeERRVUZETEVOQlFVTTdVVUZETDBNc1NVRkJTU3hEUVVGRExIRkNRVUZ4UWl4SFFVRkhMR05CUVUwc1QwRkJRU3h6UTBGQmQwSXNRMEZCUXl4TFFVRkpMRU5CUVVNc1RVRkJUU3hGUVVGRkxFdEJRVWtzUTBGQlF5eFpRVUZaTEVWQlFVVXNRMEZCUXl4RFFVRkRMRVZCUVRORUxFTkJRVEpFTEVOQlFVTTdVVUZETDBZc1QwRkJUeXhKUVVGSkxFTkJRVU03U1VGRGFFSXNRMEZCUXp0SlFWbEVMRzFEUVVGclFpeEhRVUZzUWl4VlFVRnRRaXhYUVVGdFFpeEZRVUZGTEVOQlFXRTdVVUZCY2tRc2FVSkJTVU03VVVGS2RVTXNhMEpCUVVFc1JVRkJRU3hMUVVGaE8xRkJRMnBFTEVsQlFVa3NRMEZCUXl4WlFVRlpMRU5CUVVNc1ZVRkJRU3hEUVVGRExFbEJRVWtzVDBGQlFTeFhRVUZYTEVkQlFVY3NRMEZCUXl4RFFVRkRMRTFCUVUwc1JVRkJkRUlzUTBGQmMwSXNRMEZCUXl4RFFVRkRPMUZCUXk5RExFbEJRVWtzUTBGQlF5eHhRa0ZCY1VJc1IwRkJSeXhqUVVGTkxFOUJRVUVzWjBOQlFXdENMRU5CUVVNc1MwRkJTU3hEUVVGRExFMUJRVTBzUlVGQlJTeExRVUZKTEVOQlFVTXNXVUZCV1N4RlFVRkZMRU5CUVVNc1EwRkJReXhGUVVGeVJDeERRVUZ4UkN4RFFVRkRPMUZCUTNwR0xFOUJRVThzU1VGQlNTeERRVUZETzBsQlEyaENMRU5CUVVNN1NVRlpSQ3h6UWtGQlN5eEhRVUZNTEZWQlEwa3NPRUpCUVRCRExFVkJRekZETEN0Q1FVRXlReXhGUVVNelF5d3JRa0ZCTWtNc1JVRkRNME1zYTBKQlFUaENMRVZCUXpsQ0xGZEJRV3RDTEVWQlEyeENMRmRCUVd0Q08xRkJUblJDTEdsQ1FYTktRenRSUVhKS1J5d3JRMEZCUVN4RlFVRkJMR3REUVVFd1F6dFJRVU14UXl4blJFRkJRU3hGUVVGQkxHMURRVUV5UXp0UlFVTXpReXhuUkVGQlFTeEZRVUZCTEcxRFFVRXlRenRSUVVNelF5eHRRMEZCUVN4RlFVRkJMSE5DUVVFNFFqdFJRVU01UWl3MFFrRkJRU3hGUVVGQkxHdENRVUZyUWp0UlFVTnNRaXcwUWtGQlFTeEZRVUZCTEd0Q1FVRnJRanRSUVVWc1FpeEpRVUZKTEVOQlFWTXNSVUZEVkN4RFFVRlRMRVZCUTFRc1EwRkJReXhIUVVGblFpeEpRVUZKTEVOQlFVTXNTMEZCU3l4RlFVRkhMRU5CUVVNc1RVRkJUU3hGUVVOeVF5eERRVUZETEVkQlFVY3NRMEZCUXl4SFFVRkhMRU5CUVVNc1IwRkJSeXhKUVVGSkxFTkJRVU1zVDBGQlR5eERRVUZETEUxQlFVMHNSVUZETDBJc1EwRkJReXhIUVVGSExFbEJRVWtzUTBGQlF5eE5RVUZOTEVOQlFVTXNUVUZCVFN4RlFVTjBRaXhEUVVGRExFZEJRVWNzU1VGQlNTeERRVUZETEZkQlFWY3NRMEZCUXl4RFFVRkRMRU5CUVVNc1JVRkRka0lzUTBGQlF5eEhRVUZITEVsQlFVa3NRMEZCUXl4WFFVRlhMRU5CUVVNc1EwRkJReXhEUVVGRExFTkJRVU03VVVGRk5VSXNTVUZCU1N4RFFVRkRMRWRCUVVjc1NVRkJTU3hMUVVGTExFTkJRVU1zUTBGQlF5eERRVUZETEVWQlFVVXNRMEZCUXl4SFFVRkhMRWxCUVVrc1MwRkJTeXhEUVVGRExFTkJRVU1zUTBGQlF5eERRVUZETzFGQlJYWkRMRWxCUVVrc1EwRkJReXhIUVVGSExFbEJRVWtzUTBGQlF6dFJRVVZpTEVsQlFVa3NSVUZCUlN4SFFVRkhMRWxCUVVrc1EwRkJReXhqUVVGakxFTkJRVU03VVVGRk4wSXNTVUZCU1N4RFFVRkRMRTFCUVUwc1EwRkJReXhQUVVGUExFTkJRVU1zVlVGQlF5eERRVUZETEVWQlFVVXNRMEZCUXp0WlFVTnlRaXhEUVVGRExFTkJRVU1zUzBGQlN5eEhRVUZITEVOQlFVTXNRMEZCUXp0WlFVTmFMRWxCUVVrc1QwRkJUeXhEUVVGRExFTkJRVU1zUTBGQlF5eExRVUZMTEZkQlFWY3NSVUZCUlR0blFrRkROVUlzUTBGQlF5eERRVUZETEVOQlFVTXNSMEZCUnl4RFFVRkRMRWRCUVVjc1EwRkJReXhGUVVGRkxFTkJRVU1zUTBGQlF5eERRVUZETEVkQlFVY3NRMEZCUXl4SFFVRkhMRU5CUVVNc1EwRkJRenRoUVVNMVFqdFpRVU5FTEVOQlFVTXNRMEZCUXl4RFFVRkRMRU5CUVVNc1IwRkJSeXhEUVVGRExFTkJRVU1zUTBGQlF5eEZRVUZGTEVOQlFVTXNRMEZCUXl4RFFVRkRMRU5CUVVNc1IwRkJSeXhEUVVGRExFTkJRVU1zUTBGQlF5eERRVUZETzFGQlF6TkNMRU5CUVVNc1EwRkJReXhEUVVGRE8xRkJSVWdzU1VGQlNTeEpRVUZKTEVOQlFVTXNjVUpCUVhGQ08xbEJRVVVzU1VGQlNTeERRVUZETEhGQ1FVRnhRaXhGUVVGRkxFTkJRVU03VVVGTE4wUXNTVUZCU1N4VFFVRlRMRU5CUVVNN1VVRkRaQ3hKUVVGSkxFbEJRVWtzUTBGQlF5eGxRVUZsTEVWQlFVVTdXVUZGZEVJc1UwRkJVeXhIUVVGSExFbEJRVWtzUTBGQlF5eGxRVUZsTEVOQlFVTTdVMEZEY0VNN1lVRkJUVHRaUVVWSUxGTkJRVk1zUjBGQlJ5eERRVUZETEVsQlFVa3NNRUpCUVZVc1EwRkJReXhEUVVGRExFVkJRVVVzU1VGQlNTeERRVUZETEUxQlFVMHNSVUZCUlN4TlFVRk5MRU5CUVVNc1kwRkJZeXhGUVVGRkxFMUJRVTBzUTBGQlF5eGpRVUZqTEVWQlFVVXNWVUZCUVN4RFFVRkRMRWxCUVVjc1QwRkJRU3hMUVVGSkxFTkJRVU1zWVVGQllTeERRVUZETEVOQlFVTXNRMEZCUXl4RlFVRnlRaXhEUVVGeFFpeERRVUZETEVOQlFVTXNRMEZCUXl4alFVRmpMRVZCUVVVc1EwRkJRenRaUVVsMlNTeERRVUZETEVkQlFVY3NhVUpCUVU4c1EwRkJReXhyUWtGQmEwSXNRMEZCUXl4RFFVRkRMRVZCUVVVc1kwRkJUU3hQUVVGQkxFTkJRVU1zUlVGQlJDeERRVUZETEVOQlFVTXNRMEZCUXp0WlFVTXpReXhKUVVGSkxFTkJRVU1zVFVGQlRTeERRVUZETEU5QlFVOHNRMEZCUXl4VlFVRkJMRU5CUVVNN1owSkJRMnBDTEVsQlFVa3NUMEZCVHl4RFFVRkRMRU5CUVVNc1RVRkJUU3hKUVVGSkxGRkJRVkU3YjBKQlFVVXNRMEZCUXl4RFFVRkRMRTFCUVUwc1IwRkJSeXhMUVVGSkxFTkJRVU1zVFVGQlRTeERRVUZUTEVOQlFVTXNRMEZCUXl4TlFVRk5MRU5CUVVNc1EwRkJRenRuUWtGRE1VVXNTVUZCU1N4UFFVRlBMRU5CUVVNc1EwRkJReXhOUVVGTkxFbEJRVWtzVVVGQlVUdHZRa0ZCUlN4RFFVRkRMRU5CUVVNc1RVRkJUU3hIUVVGSExFdEJRVWtzUTBGQlF5eE5RVUZOTEVOQlFWTXNRMEZCUXl4RFFVRkRMRTFCUVUwc1EwRkJReXhEUVVGRE8xbEJRemxGTEVOQlFVTXNRMEZCUXl4RFFVRkRPMWxCUTBnc1NVRkJTU3hEUVVGRExFMUJRVTBzUTBGQlF5eFBRVUZQTEVOQlFVTXNWVUZCUVN4RFFVRkRPMmRDUVVOcVFpeEpRVUZOTEVOQlFVTXNSMEZCUnl4TlFVRk5MRU5CUVVNc1kwRkJZeXhEUVVGRExFTkJRVU1zUTBGQlF5eEZRVUZGTEVOQlFVTXNSMEZCUnl4TlFVRk5MRU5CUVVNc1kwRkJZeXhEUVVGRExFTkJRVU1zUTBGQlF5eERRVUZETzJkQ1FVTnFSU3hEUVVGRExFTkJRVU1zUTBGQlF5eERRVUZETEVOQlFVTXNRMEZCUXl4RFFVRkRMRWRCUVVjc1EwRkJReXhEUVVGRExFTkJRVU1zUTBGQlF5eERRVUZETEVOQlFVTXNRMEZCUXl4SFFVRkhMRU5CUVVNc1EwRkJReXhOUVVGTkxFbEJRVWtzUTBGQlF5eERRVUZETzFsQlEzUkRMRU5CUVVNc1EwRkJReXhEUVVGRE8xTkJRMDQ3VVVGRlJDeEpRVUZKTEVOQlFVTXNSMEZCUnl4cFFrRkJUeXhEUVVGRExHdENRVUZyUWl4RFFVRkRMRU5CUVVNc1JVRkJSU3hWUVVGVkxFTkJRVU1zUlVGQlJTeERRVUZETzFsQlEyaEVMRTlCUVU4c1UwRkJVeXhEUVVGRExFTkJRVU1zUTBGQlF5eERRVUZETEVOQlFVTXNRMEZCUXl4RFFVRkRPMUZCUXpOQ0xFTkJRVU1zUTBGQlF5eERRVUZETzFGQlJVZ3NTVUZCU1N4SlFVRkpMRU5CUVVNc1ZVRkJWU3hKUVVGSkxFOUJRVThzU1VGQlNTeERRVUZETEZWQlFWVXNRMEZCUXl4TlFVRk5MRXRCUVVzc1YwRkJWeXhGUVVGRk8xbEJRMnhGTEVsQlFVa3NRMEZCUXl4SFFVRkhMRU5CUVVNc1EwRkJRenRaUVVOV0xFbEJRVWtzWVVGQllTeEhRVUZITEZWQlFVTXNRMEZCUXl4RlFVRkZMRU5CUVVNc1JVRkJSU3hSUVVGUkxFVkJRVVVzWVVGQllUdG5Ra0ZET1VNc1EwRkJReXhEUVVGRExFTkJRVU1zUTBGQlF5eERRVUZETEVOQlFVTXNRMEZCUXl4SFFVRkhMRU5CUVVNc1EwRkJReXhEUVVGRExFTkJRVU1zUTBGQlF5eERRVUZETEVOQlFVTXNSMEZCUnl4UlFVRlJMRU5CUVVNN1owSkJRemRDTEVOQlFVTXNRMEZCUXl4RFFVRkRMRU5CUVVNc1EwRkJReXhEUVVGRExFTkJRVU1zUjBGQlJ5eERRVUZETEVOQlFVTXNRMEZCUXl4RFFVRkRMRU5CUVVNc1EwRkJReXhEUVVGRExFZEJRVWNzWVVGQllTeERRVUZETzFsQlEzUkRMRU5CUVVNc1EwRkJRenRaUVVOR0xFbEJRVWtzUTBGQlF5eFBRVUZQTEVOQlFVTXNUMEZCVHl4RFFVRkRMRlZCUVVFc1EwRkJRenRuUWtGRGJFSXNZVUZCWVN4RFFVRkRMRU5CUVVNc1JVRkJSU3hEUVVGRExFZEJRVWNzUTBGQlF5eEZRVUZGTEV0QlFVa3NRMEZCUXl4cFFrRkJhVUlzUlVGQlJTeEhRVUZITEVOQlFVTXNRMEZCUXp0blFrRnBRbkpFTEVOQlFVTXNRMEZCUXl4RFFVRkRMRU5CUVVNc1IwRkJSeXhEUVVGRExFVkJRVVVzUTBGQlF5eERRVUZETEVOQlFVTXNSVUZCUlN4RFFVRkRMRWRCUVVjc1EwRkJReXhEUVVGRE8yZENRVU55UWl4RFFVRkRMRU5CUVVNc1EwRkJReXhEUVVGRExFZEJRVWNzUTBGQlF5eEZRVUZGTEVOQlFVTXNRMEZCUXl4RFFVRkRMRVZCUVVVc1EwRkJReXhIUVVGSExFTkJRVU1zUTBGQlF6dFpRVU42UWl4RFFVRkRMRU5CUVVNc1EwRkJRenRUUVVOT096dFpRVUZOTEVsQlFVa3NRMEZCUXl4VlFVRlZMRWRCUVVjc1JVRkJSU3hOUVVGTkxFVkJRVVVzU1VGQlNTeERRVUZETEUxQlFVMHNSVUZCUlN4TlFVRk5MRVZCUVVVc1JVRkJSU3hGUVVGRkxFTkJRVU03VVVGRk4wUXNTVUZCU1N4alFVRmpMRWRCUVVjc1NVRkJTU3hEUVVGRExGbEJRVmtzU1VGQlNTeEZRVUZGTEVOQlFVTTdVVUZETjBNc1NVRkJTU3hKUVVGSkxFTkJRVU1zZDBKQlFYZENMRVZCUVVVN1dVRkRla0lzU1VGQlNTeERRVUZETEZsQlFXRXNRMEZCUXl4blFrRkJaMElzUjBGQlJ5eEpRVUZKTEVOQlFVTXNkMEpCUVhkQ0xFTkJRVU1zWjBKQlFXZENMRU5CUVVNN1dVRkRNMFlzWTBGQll5eEhRVUZITEdOQlFXTXNRMEZCUXl4TlFVRk5MRU5CUVVNc05rTkJRU3RDTEVOQlFVTXNRMEZCUXl4RlFVRkZMRWxCUVVrc1EwRkJReXhOUVVGTkxFVkJRVVVzU1VGQlNTeERRVUZETEhkQ1FVRjNRaXhEUVVGRExFbEJRVWtzUlVGQlR5eERRVUZETEVsQlFVa3NRMEZCUXl4WlFVRlpMRU5CUVVNc1EwRkJReXhEUVVGRExFTkJRVU03VTBGSGVrbzdVVUZGUkN4SlFVRkpMRU5CUVVNc1lVRkJZU3hEUVVGRExFdEJRVXNzUTBGQlF5eERRVUZETzFGQlF6RkNMRWxCUVVrc1EwRkJReXhSUVVGUkxFZEJRVWNzU1VGQlNTeHBRa0ZCVHl4RFFVRkRMRU5CUVVNc1EwRkJReXhGUVVGRkxFTkJRVU1zUTBGQlF5eEZRVUZGTEVOQlFVTXNRMEZCUXl4RFFVRkRPMUZCUlhaRExFbEJRVWtzUTBGQlF5eFJRVUZSTEVOQlFVTXNTMEZCU3l4RFFVRkRMRXRCUVVzc1JVRkJSU3hEUVVGRE8xRkJRelZDTEV0QlFVc3NTVUZCU1N4RFFVRkRMRWRCUVVjc1EwRkJReXhGUVVGRkxFTkJRVU1zUjBGQlJ5eERRVUZETEVWQlFVVXNSVUZCUlN4RFFVRkRMRVZCUVVVN1dVRkRlRUlzU1VGQlNTeERRVUZETEVkQlFVY3NTVUZCU1N4RFFVRkRMRTFCUVUwc1EwRkJReXhEUVVGRExFTkJRVU1zUTBGQlF6dFpRVU4yUWl4SlFVRkpMRU5CUVVNc1EwRkJReXhMUVVGTExFVkJRVVU3WjBKQlExUXNRMEZCUXl4RFFVRkRMRVZCUVVVc1IwRkJSeXhEUVVGRExFTkJRVU1zUTBGQlF5eERRVUZETzJkQ1FVTllMRU5CUVVNc1EwRkJReXhGUVVGRkxFZEJRVWNzUTBGQlF5eERRVUZETEVOQlFVTXNRMEZCUXp0blFrRkRXQ3hKUVVGSkxFTkJRVU1zUjBGQlJ5eERRVUZETEVOQlFVTXNRMEZCUXl4RFFVRkRMRVZCUVVVc1EwRkJReXhEUVVGRExFTkJRVU1zUTBGQlF5eERRVUZETzJkQ1FVTnVRaXhKUVVGSkxFTkJRVU1zVVVGQlVTeERRVUZETEV0QlFVc3NRMEZCUXl4SFFVRkhMRU5CUVVNc1EwRkJReXhGUVVGRkxFTkJRVU1zUTBGQlF5eERRVUZETzJGQlEycERPMU5CUTBvN1VVRkRSQ3hKUVVGSkxFTkJRVU1zVVVGQlVTeERRVUZETEZOQlFWTXNSMEZCUnl4SlFVRkpMRU5CUVVNc1ZVRkJWU3hEUVVGRE8xRkJTekZETEVsQlFVa3NRMEZCUXl4aFFVRmhMRU5CUVVNc09FSkJRVGhDTEVWQlFVVXNRMEZCUXl4RlFVRkZMRU5CUVVNc1EwRkJReXhEUVVGRE8xRkJSM3BFTEVsQlFVa3NZMEZCWXl4RFFVRkRMRTFCUVUwc1IwRkJSeXhEUVVGRE8xbEJRVVVzU1VGQlNTeERRVUZETEZGQlFWRXNRMEZCUXl4UFFVRlBMRWRCUVVjc1NVRkJTU3h6UWtGQlZTeERRVUZETEVsQlFVa3NRMEZCUXl4TlFVRk5MRVZCUVVVc1NVRkJTU3hEUVVGRExFOUJRVThzUlVGQlJTeEpRVUZKTEVOQlFVTXNWVUZCVlN4RlFVRkZMR05CUVdNc1EwRkJReXhEUVVGRExHZENRVUZuUWl4RlFVRkZMRU5CUVVNN1VVRkRja29zU1VGQlNTeERRVUZETEZGQlFWRXNRMEZCUXl4SFFVRkhMRU5CUVVNc0swSkJRU3RDTEVOQlFVTXNRMEZCUXp0UlFVTnVSQ3hKUVVGSkxFTkJRVU1zTmtKQlFUWkNMRU5CUVVNc1EwRkJReXhGUVVGRkxFTkJRVU1zUlVGQlJTeFhRVUZYTEVOQlFVTXNRMEZCUXp0UlFVZDBSQ3hKUVVGSkxFTkJRVU1zWVVGQllTeERRVUZETEVWQlFVVXNRMEZCUXl4RFFVRkRPMUZCUTNaQ0xFbEJRVWtzUlVGQlJTeEZRVUZGTzFsQlEwb3NTVUZCU1N4RFFVRkRMRTFCUVUwc1EwRkJReXhQUVVGUExFTkJRVU1zVlVGQlZTeERRVUZETEVWQlFVVXNRMEZCUXl4SlFVRkpMRU5CUVVNc1EwRkJReXhEUVVGRExFZEJRVWNzUTBGQlF5eERRVUZETEVOQlFVTXNRMEZCUXl4RlFVRkZMRU5CUVVNc1EwRkJReXhEUVVGRExFZEJRVWNzUTBGQlF5eERRVUZETEVOQlFVTXNRMEZCUXl4RFFVRkRMRU5CUVVNc1EwRkJReXhEUVVGRExFTkJRVU03V1VGRGFrVXNTVUZCU1N4RFFVRkRMRkZCUVZFc1EwRkJReXhQUVVGUExFZEJRVWNzU1VGQlNTeHpRa0ZCVlN4RFFVRkRMRWxCUVVrc1EwRkJReXhOUVVGTkxFVkJRVVVzU1VGQlNTeERRVUZETEU5QlFVOHNSVUZCUlN4SlFVRkpMRU5CUVVNc1ZVRkJWU3hGUVVGRkxHTkJRV01zUlVGQlJTeEpRVUZKTEVOQlFVTXNRMEZCUXl4blFrRkJaMElzUlVGQlJTeERRVUZETzFsQlF6VklMRWxCUVVrc1EwRkJReXhOUVVGTkxFTkJRVU1zVDBGQlR5eERRVUZETEZWQlFWVXNRMEZCUXl4RlFVRkZMRU5CUVVNc1NVRkJTU3hEUVVGRExFTkJRVU1zUTBGQlF5eERRVUZETEVkQlFVY3NRMEZCUXl4RFFVRkRMRU5CUVVNc1JVRkJSU3hEUVVGRExFTkJRVU1zUTBGQlF5eERRVUZETEVkQlFVY3NRMEZCUXl4RFFVRkRMRU5CUVVNc1EwRkJReXhEUVVGRExFTkJRVU1zUTBGQlF5eERRVUZETzFOQlEzQkZPMUZCUjBRc1NVRkJTU3hEUVVGRExGRkJRVkVzUTBGQlF5eERRVUZETEVkQlFVY3NRMEZCUXl4RFFVRkRPMUZCUTNCQ0xFbEJRVWtzUTBGQlF5eFJRVUZSTEVOQlFVTXNSMEZCUnl4RFFVRkRMQ3RDUVVFclFpeERRVUZETEVOQlFVTTdVVUZGYmtRc1NVRkJTU3hyUWtGQmEwSXNSVUZCUlR0WlFVTndRaXhKUVVGSkxFTkJRVU1zVVVGQlVTeERRVUZETEZsQlFWa3NSMEZCUnl4SlFVRkpMRU5CUVVNN1dVRkRiRU1zU1VGQlNTeERRVUZETEZGQlFWRXNRMEZCUXl4WlFVRlpMRWRCUVVjc1NVRkJTU3hEUVVGRExFMUJRVTBzUTBGQlF5eERRVUZETEVOQlFVTXNRMEZCUXl4TFFVRkxMRU5CUVVNN1dVRkRiRVFzU1VGQlNTeERRVUZETEZGQlFWRXNRMEZCUXl4blFrRkJaMElzUjBGQlJ5eERRVUZETEVOQlFVTTdXVUZEYmtNc1NVRkJTU3hEUVVGRExGRkJRVkVzUTBGQlF5eGxRVUZsTEVkQlFVY3NRMEZCUXl4SlFVRkpMRU5CUVVNc1EwRkJRenRaUVVOMlF5eEpRVUZKTEVWQlFVVXNSMEZCUnl4cFFrRkJUeXhEUVVGRExHdENRVUZyUWl4RFFVRkRMRU5CUVVNc1JVRkJReXhWUVVGRExFTkJRVU1zUlVGQlJTeERRVUZETzJkQ1FVTjJReXhKUVVGSkxFTkJRVU1zU1VGQlNTeERRVUZETEVsQlFVa3NRMEZCUXl4SlFVRkpMRU5CUVVNN2IwSkJRVVVzVDBGQlR5eERRVUZETEVOQlFVTXNRMEZCUXl4RFFVRkRMRU5CUVVNc1EwRkJReXhEUVVGRExFTkJRVU03WjBKQlEzSkRMRTlCUVU4c1EwRkJReXhEUVVGQk8xbEJRMW9zUTBGQlF5eERRVUZETEVOQlFVTTdXVUZEU0N4SlFVRkpMRU5CUVVNc1VVRkJVU3hEUVVGRExFTkJRVU1zUjBGQlJ5eEZRVUZGTEVOQlFVTTdXVUZEY2tJc1NVRkJTU3hEUVVGRExGRkJRVkVzUTBGQlF5eEhRVUZITEVOQlFVTXNhMEpCUVd0Q0xFTkJRVU1zUTBGQlF6dFRRVU42UXp0UlFVVkVMRWxCUVVrc1EwRkJReXh0UWtGQmJVSXNSVUZCUlN4RFFVRkRPMUZCUXpOQ0xFbEJRVWtzUTBGQlF5dzJRa0ZCTmtJc1EwRkJReXhEUVVGRExFVkJRVVVzUTBGQlF5eEZRVUZGTEZkQlFWY3NRMEZCUXl4RFFVRkRPMUZCUTNSRUxFOUJRVThzVjBGQlZ5eERRVUZETEVOQlFVTXNRMEZCUXl4SlFVRkpMRU5CUVVNc1RVRkJUU3hGUVVGRkxFTkJRVU1zUTBGQlF5eERRVUZETEVsQlFVa3NRMEZCUXp0SlFVTTVReXhEUVVGRE8wbEJSVThzT0VKQlFXRXNSMEZCY2tJc1ZVRkJjMElzVlVGQmEwSXNSVUZCUlN4RFFVRlhMRVZCUVVVc1EwRkJWenRSUVVNNVJDeEpRVUZKTEVsQlFVa3NRMEZCUXl4UFFVRlBMRU5CUVVNc1RVRkJUU3hIUVVGSExFTkJRVU1zU1VGQlNTeFZRVUZWTEVkQlFVY3NRMEZCUXl4RlFVRkZPMWxCUnpORExFbEJRVWtzUTBGQlF5eEhRVUZITEVsQlFVa3NRMEZCUXl4TlFVRk5MRU5CUVVNc1RVRkJUU3hEUVVGRE8xbEJRek5DTEVsQlFVa3NTMEZCU3l4SFFVRkhMRWxCUVVrc1EwRkJReXhOUVVGTkxFTkJRVU1zUjBGQlJ5eERRVUZETEZWQlFVRXNRMEZCUXl4SlFVRkpMRTlCUVVFc1EwRkJTeXhGUVVGRkxFMUJRVTBzUlVGQlV5eERRVUZETEVOQlFVTXNUVUZCVHl4RFFVRkRMRXRCUVVzc1JVRkJSU3hOUVVGTkxFVkJRVk1zUTBGQlF5eERRVUZETEUxQlFVOHNRMEZCUXl4TFFVRkxMRVZCUVVVc1EwRkJRU3hGUVVGMlJTeERRVUYxUlN4RFFVRkRMRU5CUVVNN1dVRkRNVWNzU1VGQlNTeEZRVUZGTEVkQlFVY3NTVUZCU1N4RFFVRkRMRTFCUVUwc1EwRkJReXhIUVVGSExFTkJRVU1zVlVGQlFTeERRVUZETEVsQlFVa3NUMEZCUVN4RFFVRkxMRVZCUVVVc1MwRkJTeXhGUVVGRkxFTkJRVU1zUTBGQlF5eExRVUZMTEVWQlFVVXNRMEZCUVN4RlFVRjJRaXhEUVVGMVFpeERRVUZETEVOQlFVTTdXVUZEZGtRc1NVRkJTU3hEUVVGRExFOUJRVThzUTBGQlF5eFBRVUZQTEVOQlFVTXNWVUZCUXl4RFFVRkRMRVZCUVVVc1EwRkJRenRuUWtGRGRFSXNSVUZCUlN4RFFVRkRMRWxCUVVrc1EwRkJUU3hGUVVGRkxFdEJRVXNzUlVGQlJTeERRVUZETEVOQlFVTXNTMEZCU3l4SFFVRkhMRU5CUVVNc1IwRkJSeXhEUVVGRExFVkJRVVVzUTBGQlF5eERRVUZETzFsQlF6ZERMRU5CUVVNc1EwRkJReXhEUVVGRE8xbEJRMGdzU1VGQlNTeERRVUZETEU5QlFVOHNRMEZCUXl4UFFVRlBMRU5CUVVNc1ZVRkJReXhEUVVGRExFVkJRVVVzUTBGQlF6dG5Ra0ZEZEVJc1NVRkJTU3hQUVVGUExFTkJRVU1zUTBGQlF5eE5RVUZOTEV0QlFVc3NWMEZCVnp0dlFrRkRMMElzUTBGQlF5eERRVUZETEUxQlFVMHNRMEZCUXl4UFFVRlBMRU5CUVVNc1ZVRkJRU3hEUVVGRExFbEJRVWtzVDBGQlFTeExRVUZMTEVOQlFVTXNTVUZCU1N4RFFVRkRMRVZCUVVVc1RVRkJUU3hGUVVGRkxFTkJRVU1zUTBGQlF5eExRVUZMTEVWQlFVVXNUVUZCVFN4RlFVRkZMRU5CUVVNc1EwRkJReXhMUVVGTExFVkJRVVVzUTBGQlF5eEZRVUZvUkN4RFFVRm5SQ3hEUVVGRExFTkJRVU03WjBKQlF6VkZMRWxCUVVrc1QwRkJUeXhEUVVGRExFTkJRVU1zVFVGQlRTeExRVUZMTEZkQlFWYzdiMEpCUXk5Q0xFTkJRVU1zUTBGQlF5eE5RVUZOTEVOQlFVTXNUMEZCVHl4RFFVRkRMRlZCUVVFc1JVRkJSU3hKUVVGSkxFOUJRVUVzUzBGQlN5eERRVUZETEVsQlFVa3NRMEZCUXl4RlFVRkZMRTFCUVUwc1JVRkJSU3hEUVVGRExFTkJRVU1zUzBGQlN5eEZRVUZGTEUxQlFVMHNSVUZCUlN4RlFVRkZMRU5CUVVNc1MwRkJTeXhGUVVGRkxFTkJRVU1zUlVGQmFrUXNRMEZCYVVRc1EwRkJReXhEUVVGRE8xbEJRMnhHTEVOQlFVTXNRMEZCUXl4RFFVRkRPMWxCUjBnc1NVRkJTU3hOUVVGTkxFVkJRVVU3YVVKQlExQXNTVUZCU1N4RFFVRkRMRWxCUVVrc1EwRkJReXhKUVVGSkxFVkJRVVVzUTBGQlF6dHBRa0ZEYWtJc1MwRkJTeXhEUVVGRExFVkJRVVVzUTBGQlF6dHBRa0ZEVkN4TFFVRkxMRU5CUVVNc1MwRkJTeXhEUVVGRE8ybENRVU5hTEdGQlFXRXNRMEZCUXl4TFFVRkxMRU5CUVVNN2FVSkJRM0JDTEZsQlFWa3NRMEZCUXl4SlFVRkpMRU5CUVVNc1dVRkJXU3hGUVVGRkxFTkJRVU03YVVKQlEycERMSGRDUVVGM1FpeERRVUZETEVOQlFVTXNRMEZCUXp0cFFrRkRNMElzYjBKQlFXOUNMRU5CUVVNc1NVRkJTU3hEUVVGRE8ybENRVU14UWl4TFFVRkxMRU5CUVVNc1ZVRkJWU3hGUVVGRkxFTkJRVU1zUlVGQlJTeERRVUZETEVWQlFVVXNRMEZCUXl4RlFVRkZMRXRCUVVzc1EwRkJReXhEUVVGRE8xbEJSWFpETEVsQlFVa3NRMEZCUXl4TlFVRk5MRU5CUVVNc1QwRkJUeXhEUVVGRExGVkJRVUVzUTBGQlF6dG5Ra0ZEYWtJc1EwRkJReXhEUVVGRExFTkJRVU1zUTBGQlF5eExRVUZMTEVOQlFVTXNSMEZCUnl4RlFVRkZMRU5CUVVNc1EwRkJReXhEUVVGRExFdEJRVXNzUTBGQlF5eERRVUZETEVOQlFVTXNRMEZCUXp0blFrRkRNMElzUTBGQlF5eERRVUZETEVOQlFVTXNRMEZCUXl4TFFVRkxMRU5CUVVNc1IwRkJSeXhGUVVGRkxFTkJRVU1zUTBGQlF5eERRVUZETEV0QlFVc3NRMEZCUXl4RFFVRkRMRU5CUVVNc1EwRkJRenRaUVVNdlFpeERRVUZETEVOQlFVTXNRMEZCUXp0VFFVTk9PMkZCUVUwN1dVRkRTQ3hKUVVGSkxFTkJRVU1zVVVGQlVTeERRVUZETEVkQlFVY3NRMEZCUXl4VlFVRlZMRU5CUVVNc1EwRkJRenRUUVVOcVF6dEpRVU5NTEVOQlFVTTdTVUZIVHl3NFEwRkJOa0lzUjBGQmNrTXNWVUZCYzBNc1MwRkJZU3hGUVVGRkxFMUJRV01zUlVGQlJTeFhRVUV5UWp0UlFVRm9SeXhwUWtGbFF6dFJRV1p2UlN3MFFrRkJRU3hGUVVGQkxHdENRVUV5UWp0UlFVVTFSaXhKUVVGSkxFTkJRVU1zU1VGQlNTeERRVUZETEdWQlFXVXNTVUZCU1N4SlFVRkpMRU5CUVVNc2JVSkJRVzFDTEVWQlFVVTdXVUZEYmtRc1NVRkJTU3hIUVVGRExFZEJRVWNzU1VGQlNTeERRVUZETEZGQlFWRXNRMEZCUXl4RFFVRkRMRU5CUVVNc1EwRkJReXhEUVVGRExFVkJRVVVzUjBGQlF5eEhRVUZITEVsQlFVa3NRMEZCUXl4UlFVRlJMRU5CUVVNc1EwRkJReXhEUVVGRExFTkJRVU1zUTBGQlF5eERRVUZETzFsQlEyNUVMRWxCUVVrc1EwRkJReXhOUVVGTkxFTkJRVU1zVDBGQlR5eERRVUZETEZWQlFWVXNRMEZCUXl4RlFVRkZMRU5CUVVNc1NVRkJTU3hEUVVGRExFTkJRVU1zUTBGQlF5eEhRVUZITEVkQlFVTXNRMEZCUXl4RFFVRkRMRU5CUVVNc1JVRkJSU3hEUVVGRExFTkJRVU1zUTBGQlF5eEhRVUZITEVkQlFVTXNRMEZCUXl4RFFVRkRMRU5CUVVNc1EwRkJReXhEUVVGRExFTkJRVU1zUTBGQlF5eERRVUZETzFsQlEycEZMRWxCUVVrc1RVRkJUU3hIUVVGSExHMURRVUZqTEVOQlFVTXNTVUZCU1N4RFFVRkRMRTFCUVUwc1JVRkJSU3hKUVVGSkxFTkJRVU1zVFVGQlRTeERRVUZETEVOQlFVTTdXVUZEZEVRc2FVTkJRVmtzUTBGQlF5eE5RVUZOTEVWQlFVVXNTMEZCU3l4RlFVRkZMRTFCUVUwc1JVRkJSU3hKUVVGSkxFTkJRVU1zWjBKQlFXZENMRVZCUVVVc1EwRkJReXhOUVVGTkxFZEJRVWNzUzBGQlN5eERRVUZETEVWQlFVVXNWMEZCVnl4RFFVRkRMRU5CUVVNN1dVRkRNVVlzU1VGQlNTeERRVUZETEUxQlFVMHNRMEZCUXl4UFFVRlBMRU5CUVVNc1ZVRkJReXhEUVVGRExFVkJRVVVzUTBGQlF6dG5Ra0ZEY2tJc1MwRkJTU3hEUVVGRExGRkJRVkVzUTBGQlF5eERRVUZETEVOQlFVTXNRMEZCUXl4RFFVRkRMRU5CUVVNc1EwRkJReXhEUVVGRExFZEJRVWNzUTBGQlF5eERRVUZETEVOQlFVTXNSVUZCUlN4TFFVRkpMRU5CUVVNc1VVRkJVU3hEUVVGRExFTkJRVU1zUTBGQlF5eERRVUZETEVOQlFVTXNRMEZCUXl4RFFVRkRMRU5CUVVNc1IwRkJSeXhEUVVGRExFTkJRVU1zUTBGQlF5eERRVUZETzJkQ1FVTjZSQ3hKUVVGSkxFTkJRVU1zUTBGQlF5eE5RVUZOTEVWQlFVVTdiMEpCUTFZc1EwRkJReXhEUVVGRExFMUJRVTBzUTBGQlF5eFZRVUZWTEVOQlFVTXNRMEZCUXl4RFFVRkRMRU5CUVVNc1EwRkJReXhEUVVGRE8yOUNRVU42UWl4RFFVRkRMRU5CUVVNc1RVRkJUU3hEUVVGRExGVkJRVlVzUTBGQlF5eERRVUZETEVOQlFVTXNRMEZCUXl4RFFVRkRMRU5CUVVNN2FVSkJRelZDTzFsQlEwd3NRMEZCUXl4RFFVRkRMRU5CUVVNN1UwRkRUanRKUVVOTUxFTkJRVU03U1VGRlJDeDFRa0ZCVFN4SFFVRk9PMUZCUTBrc1QwRkJUeXhKUVVGSkxFTkJRVU1zUzBGQlN5eERRVUZETEVkQlFVY3NRMEZCUXl4RFFVRkRPMGxCUXpOQ0xFTkJRVU03U1VGRlJDeHhRa0ZCU1N4SFFVRktPMUZCUTBrc1QwRkJUeXhKUVVGSkxFTkJRVU1zUzBGQlN5eERRVUZETEVOQlFVTXNRMEZCUXl4RFFVRkRPMGxCUTNwQ0xFTkJRVU03U1VGSlJDeHRRMEZCYTBJc1IwRkJiRUlzVlVGQmJVSXNWVUZCYzBJN1VVRkJkRUlzTWtKQlFVRXNSVUZCUVN4alFVRnpRanRSUVVOeVF5eEpRVUZKTEVOQlFVTXNaMEpCUVdkQ0xFZEJRVWNzU1VGQlNTdzJRa0ZCYzBJc1EwRkRPVU1zU1VGQlNTeERRVUZETEUxQlFVMHNRMEZCUXl4SFFVRkhMRU5CUVVNc1ZVRkJWU3hEUVVGRE8xbEJRM1pDTEU5QlFVOHNRMEZCUXl4RFFVRkRMRTFCUVUwc1EwRkJReXhQUVVGUExFTkJRVU1zUTBGQlF5eFZRVUZWTEVOQlFVTXNRMEZCUXl4UlFVRlJMRVZCUVVVc1EwRkJRenRSUVVOd1JDeERRVUZETEVOQlFVTXNRMEZCUXl4RFFVRkRPMGxCUTFvc1EwRkJRenRKUVZkRUxEQkNRVUZUTEVkQlFWUXNWVUZCVlN4SlFVRkpMRVZCUVVVc1JVRkJZeXhGUVVGRkxFbEJRVWs3VVVGQmNFSXNiVUpCUVVFc1JVRkJRU3hOUVVGak8xRkJRekZDTEVsQlFVa3NVVUZCVVN4SFFVRkhMRVZCUVVVc1EwRkJRenRSUVVsc1FpeEpRVUZKTEVkQlFVY3NSMEZCUnl4SlFVRkpMRFpDUVVGelFpeERRVUZETEVsQlFVa3NRMEZCUXl4blFrRkJaMElzUTBGQlF5eERRVUZETEVWQlFVVXNSVUZCUlN4RFFVRkRMRVZCUVVVc1NVRkJTU3hEUVVGRExHZENRVUZuUWl4RFFVRkRMRU5CUVVNc1JVRkJSU3hEUVVGRExFVkJRVVVzU1VGQlNTeERRVUZETEdkQ1FVRm5RaXhEUVVGRExFTkJRVU1zUlVGQlJTeERRVUZETEVWQlEzSklMRXRCUVVzc1IwRkJZU3hGUVVGRkxFTkJRVU1zUlVGQlJTeEpRVUZKTEVOQlFVTXNUVUZCVFN4RFFVRkRMRU5CUVVNc1JVRkJSU3hEUVVGRExFVkJRVVVzU1VGQlNTeERRVUZETEUxQlFVMHNRMEZCUXl4RFFVRkRMRVZCUVVVc1JVRkRlRVFzUzBGQlN5eEhRVUZoTEVWQlFVVXNRMEZCUXl4RlFVRkZMRWxCUVVrc1EwRkJReXhOUVVGTkxFTkJRVU1zUTBGQlF5eEZRVUZGTEVOQlFVTXNSVUZCUlN4SlFVRkpMRU5CUVVNc1RVRkJUU3hEUVVGRExFTkJRVU1zUlVGQlJTeEZRVU40UkN4TFFVRkxMRWRCUVVjc1IwRkJSeXhEUVVGRExGRkJRVkVzUTBGQlF5eExRVUZMTEVWQlFVVXNTVUZCU1N4RFFVRkRMRTFCUVUwc1EwRkJReXhMUVVGTExFTkJRVU1zUlVGRE9VTXNSMEZCUnl4SFFVRkhMRWRCUVVjc1EwRkJReXhSUVVGUkxFTkJRVU1zUzBGQlN5eEZRVUZGTEVsQlFVa3NRMEZCUXl4TlFVRk5MRU5CUVVNc1MwRkJTeXhEUVVGRExFTkJRVU03VVVGRGFrUXNSMEZCUnl4RFFVRkRMR2RDUVVGblFpeERRVUZETEV0QlFVc3NSVUZCUlN4TFFVRkxMRVZCUVVVc1NVRkJTU3hEUVVGRExFMUJRVTBzUTBGQlF5eExRVUZMTEVWQlFVVXNTVUZCU1N4RFFVRkRMRTFCUVUwc1EwRkJReXhMUVVGTExFTkJRVU1zUTBGQlF6dFJRVU42UlN4SlFVRkpMRTlCUVU4c1NVRkJTU3hMUVVGTExGZEJRVmNzUlVGQlJUdFpRVU0zUWl4SlFVRkpMRU5CUVVNc1IwRkJSeXhEUVVGRExFTkJRVU03VTBGRFlqdFJRVU5FTEVsQlFVa3NVMEZCVXl4SFFVRkhMRlZCUVVFc1EwRkJReXhKUVVGSkxFOUJRVUVzUTBGQlF5eERRVUZETEUxQlFVMHNRMEZCUXl4RlFVRkZMRVZCUVZnc1EwRkJWeXhGUVVGRkxGTkJRVk1zUjBGQlJ5eFZRVUZCTEVOQlFVTXNTVUZCU1N4UFFVRkJMRU5CUVVNc1EwRkJReXhOUVVGTkxFTkJRVU1zUlVGQlJTeEZRVUZZTEVOQlFWY3NSVUZCUlN4TlFVRk5MRWRCUVVjc1ZVRkJRU3hEUVVGRExFbEJRVWtzVDBGQlFTeERRVUZETEVOQlFVTXNUVUZCVFN4RlFVRkZMRVZCUVZZc1EwRkJWU3hGUVVOd1JpeE5RVUZOTEVkQlFVY3NTVUZCU1N3d1FrRkJWU3hEUVVGRExFZEJRVWNzUTBGQlF5eERRVUZETEVOQlFVTXNUVUZCVFN4RlFVRkZMRWRCUVVjc1EwRkJReXhEUVVGRExFVkJRVVVzVTBGQlV5eEZRVUZGTEZOQlFWTXNSVUZCUlN4TlFVRk5MRU5CUVVNc1JVRkRNVVVzV1VGQldTeEhRVUZITEUxQlFVMHNRMEZCUXl4clFrRkJhMElzUTBGQlF5eExRVUZMTEVOQlFVTXNSVUZCUlN4RlFVRkZMRWRCUVVjc1EwRkJReXhGUVVGRkxFTkJRVU1zUTBGQlF6dFJRVU12UkN4SlFVRkpMRmxCUVZrc1EwRkJReXhOUVVGTkxFdEJRVXNzUTBGQlF5eEpRVUZKTEZsQlFWa3NRMEZCUXl4TlFVRk5MRXRCUVVzc1IwRkJSeXhEUVVGRExFTkJRVU1zUTBGQlF5eE5RVUZOTEVWQlFVVTdXVUZEYmtVc1NVRkJTU3hMUVVGTExFZEJRVWNzTWtKQlFXVXNRMEZCUXl4SlFVRkpMRU5CUVVNc1RVRkJUU3hEUVVGRExGZEJRVmNzUlVGQlJTeEpRVUZKTEVOQlFVTXNUVUZCVFN4RFFVRkRMRmRCUVZjc1JVRkJSU3hGUVVGRkxFTkJRVU1zUTBGQlF6dFpRVU5zUml4UlFVRlJMRWRCUVVjc1EwRkJReXhMUVVGTExFTkJRVU1zYTBKQlFXdENMRVZCUVVVc1MwRkJTeXhEUVVGRExGVkJRVlVzUTBGQlF5eERRVUZETzFOQlF6TkVPMkZCUVUwN1dVRkRTQ3hKUVVGSkxFTkJRVU1zUjBGQlJ5eFpRVUZaTEVOQlFVTXNUVUZCVFN4SFFVRkhMRU5CUVVNc1JVRkRNMElzUTBGQlF5eEhRVUZITEVkQlFVY3NRMEZCUXl4RFFVRkRMRU5CUVVNc1dVRkJXU3hEUVVGRExFTkJRVU1zUTBGQlF5eERRVUZETEVOQlFVTXNRMEZCUXl4RlFVTTFRaXhEUVVGRExFZEJRVWNzUjBGQlJ5eERRVUZETEVOQlFVTXNRMEZCUXl4WlFVRlpMRU5CUVVNc1EwRkJReXhEUVVGRExFTkJRVU1zUTBGQlF5eERRVUZETEVWQlF6VkNMRkZCUVZFc1IwRkJSeXhEUVVGRExFbEJRVWtzUTBGQlF5eE5RVUZOTEVOQlFVTXNWMEZCVnl4RFFVRkRMR1ZCUVdVc1EwRkJReXhEUVVGRExFTkJRVU1zUTBGQlF5eEZRVUZGTEVOQlFVTXNRMEZCUXl4RFFVRkRMRU5CUVVNc1EwRkJReXhEUVVGRE8xbEJRMjVGTEV0QlFVc3NTVUZCU1N4RFFVRkRMRWRCUVVjc1EwRkJReXhGUVVGRkxFTkJRVU1zU1VGQlNTeERRVUZETEVWQlFVVXNSVUZCUlN4RFFVRkRPMmRDUVVOMlFpeFJRVUZSTEVOQlFVTXNTVUZCU1N4RFFVRkRMRWRCUVVjc1EwRkJReXhEUVVGRExFTkJRVU1zV1VGQldTeERRVUZETEVOQlFVTXNRMEZCUXl4RFFVRkRMRU5CUVVNc1EwRkJReXhEUVVGRExFTkJRVU03V1VGRE5VTXNVVUZCVVN4RFFVRkRMRWxCUVVrc1EwRkJReXh6UWtGQlZTeERRVUZETEVOQlFVTXNSVUZCUlN4SlFVRkpMRU5CUVVNc1RVRkJUU3hEUVVGRExGZEJRVmNzUlVGQlJTeEZRVUZGTEVOQlFVTXNRMEZCUXl4RFFVRkRPMU5CUXpkRU8xRkJZVVFzVDBGQlR5eFJRVUZSTEVOQlFVTTdTVUZEY0VJc1EwRkJRenRKUVVkTkxIRkNRVUZqTEVkQlFYSkNMRlZCUVhOQ0xFTkJRWE5DTzFGQlEzaERMRTlCUVU4c1QwRkJUeXhEUVVGRExFTkJRVU1zVFVGQlRTeExRVUZMTEZGQlFWRXNRMEZCUXl4RFFVRkRMRU5CUVZNc1EwRkJReXhEUVVGRExFMUJRVTBzUTBGQlF5eERRVUZETEVOQlFWRXNRMEZCUXl4RFFVRkRMRTFCUVU4c1EwRkJReXhMUVVGTExFTkJRVU03U1VGRGNFWXNRMEZCUXp0SlFVZE5MSEZDUVVGakxFZEJRWEpDTEZWQlFYTkNMRU5CUVhOQ08xRkJRM2hETEU5QlFVOHNUMEZCVHl4RFFVRkRMRU5CUVVNc1RVRkJUU3hMUVVGTExGRkJRVkVzUTBGQlF5eERRVUZETEVOQlFWTXNRMEZCUXl4RFFVRkRMRTFCUVUwc1EwRkJReXhEUVVGRExFTkJRVkVzUTBGQlF5eERRVUZETEUxQlFVOHNRMEZCUXl4TFFVRkxMRU5CUVVNN1NVRkRjRVlzUTBGQlF6dEpRVWROTEdGQlFVMHNSMEZCWWl4VlFVRmpMRU5CUVhOQ08xRkJRMmhETEU5QlFVOHNUVUZCVFN4RFFVRkRMR05CUVdNc1EwRkJReXhEUVVGRExFTkJRVU1zUjBGQlJ5eEhRVUZITEVkQlFVY3NUVUZCVFN4RFFVRkRMR05CUVdNc1EwRkJReXhEUVVGRExFTkJRVU1zUTBGQlF6dEpRVU55UlN4RFFVRkRPMGxCVFUwc1owSkJRVk1zUjBGQmFFSXNWVUZCYVVJc1EwRkJaVHRSUVVNMVFpeEpRVUZKTEU5QlFVOHNRMEZCUXl4RFFVRkRMRU5CUVVNc1JVRkJSVHRaUVVOYUxFMUJRVTBzUTBGQlF5eFhRVUZYTEVOQlFVTXNRMEZCUXl4RlFVRkZMRTFCUVUwc1EwRkJReXhWUVVGVkxFTkJRVU1zUTBGQlF5eERRVUZETEVOQlFVTXNRMEZCUXp0VFFVTXZRenRoUVVGTk8xbEJRMGdzVFVGQlRTeERRVUZETEZGQlFWRXNRMEZCUXl4RFFVRkRMRU5CUVVNc1EwRkJRenRaUVVOdVFpeERRVUZETEVOQlFVTXNTMEZCU3l4SlFVRkpMRU5CUVVNc1EwRkJRenRUUVVOb1FqdEpRVU5NTEVOQlFVTTdTVUZKWXl4bFFVRlJMRWRCUVhaQ0xGVkJRWGRDTEVOQlFVODdVVUZEY2tJc1EwRkJSU3hEUVVGRExFVkJRVVVzUjBGQlJ5eERRVUZETEVOQlFVTXNRMEZCUXl4RFFVRkRPMUZCUTFvc1EwRkJSU3hEUVVGRExFVkJRVVVzUjBGQlJ5eERRVUZETEVOQlFVTXNRMEZCUXl4RFFVRkRPMGxCUTNSQ0xFTkJRVU03U1VGSll5eHJRa0ZCVnl4SFFVRXhRaXhWUVVFeVFpeERRVUZSTEVWQlFVVXNUVUZCWjBNN1VVRkRha1VzU1VGQlNTeFBRVUZQTEVOQlFVTXNRMEZCUXl4TlFVRk5MRXRCUVVzc1YwRkJWeXhGUVVGRk8xbEJRMnBETEVOQlFVTXNRMEZCUXl4TlFVRk5MRU5CUVVNc1QwRkJUeXhEUVVGRExGVkJRVUVzUTBGQlF6dG5Ra0ZEWkN4RFFVRkRMRU5CUVVNc1MwRkJTeXhKUVVGSkxFTkJRVU1zUTBGQlF6dG5Ra0ZEWWl4TlFVRk5MRU5CUVVNc1VVRkJVU3hEUVVGRExFTkJRVU1zUTBGQlF5eERRVUZETzJkQ1FVTmlMRU5CUVVVc1EwRkJReXhwUWtGQmFVSXNSMEZCUnl4RFFVRkRMRU5CUVVNc1EwRkJReXhIUVVGSExFMUJRVTBzUTBGQlF5eERRVUZETEVOQlFVTTdaMEpCUTNSRExFTkJRVVVzUTBGQlF5eHBRa0ZCYVVJc1IwRkJSeXhEUVVGRExFTkJRVU1zUTBGQlF5eEhRVUZITEUxQlFVMHNRMEZCUXl4RFFVRkRMRU5CUVVNN1dVRkRhRVFzUTBGQlF5eERRVUZETEVOQlFVTTdVMEZEVGp0UlFVTkVMRWxCUVVrc1QwRkJUeXhEUVVGRExFTkJRVU1zVFVGQlRTeExRVUZMTEZkQlFWY3NSVUZCUlR0WlFVTnFReXhEUVVGRExFTkJRVU1zVFVGQlRTeERRVUZETEU5QlFVOHNRMEZCUXl4VlFVRkJMRU5CUVVNc1NVRkJTU3hQUVVGQkxFMUJRVTBzUTBGQlF5eFhRVUZYTEVOQlFVTXNRMEZCUXl4RlFVRkZMRTFCUVUwc1EwRkJReXhGUVVFM1FpeERRVUUyUWl4RFFVRkRMRU5CUVVNN1UwRkRlRVE3U1VGRFRDeERRVUZETzBsQlIwMHNhVUpCUVZVc1IwRkJha0lzVlVGQmEwSXNRMEZCWlR0UlFVTTNRaXhKUVVGSkxFOUJRVThzUTBGQlF5eERRVUZETEVOQlFVTXNSVUZCUlR0WlFVTmFMRTlCUVU4N1owSkJRMGdzUTBGQlF5eEZRVUZGTEVOQlFVTXNRMEZCUXl4TlFVRk5MRU5CUVVNc1JVRkJSU3hGUVVGRk8yZENRVU5vUWl4RFFVRkRMRVZCUVVVc1EwRkJReXhEUVVGRExFMUJRVTBzUTBGQlF5eEZRVUZGTEVWQlFVVTdZVUZEYmtJc1EwRkJRenRUUVVOTU8yRkJRVTA3V1VGRFNDeFBRVUZQTEVOQlFVTXNRMEZCUXp0VFFVTmFPMGxCUTB3c1EwRkJRenRKUVVsTkxGZEJRVWtzUjBGQldDeFZRVUZaTEVOQlFXVXNSVUZCUlN4UlFVRnJRenRSUVVNelJDeEpRVUZKTEU5QlFVOHNRMEZCUXl4RFFVRkRMRU5CUVVNc1JVRkJSVHRaUVVOYUxFbEJRVWtzVDBGQlR5eERRVUZETEVOQlFVTXNUVUZCVFN4TFFVRkxMRmRCUVZjc1JVRkJSVHRuUWtGRGFrTXNRMEZCUXl4RFFVRkRMRTFCUVUwc1EwRkJReXhQUVVGUExFTkJRVU1zVlVGQlFTeERRVUZETzI5Q1FVTmtMRU5CUVVNc1EwRkJReXhOUVVGTkxFTkJRVU1zVlVGQlZTeERRVUZETEZGQlFWRXNRMEZCUXl4RFFVRkRMRU5CUVVNc1EwRkJRenR2UWtGRGFFTXNRMEZCUXl4RFFVRkRMRTFCUVUwc1EwRkJReXhWUVVGVkxFTkJRVU1zVVVGQlVTeERRVUZETEVOQlFVTXNRMEZCUXl4RFFVRkRPMjlDUVVNeFFpeERRVUZGTEVOQlFVTXNSVUZCUlN4SFFVRlRMRU5CUVVVc1EwRkJReXhwUWtGQmFVSXNSMEZCUnl4UlFVRlJMRU5CUVVNc1EwRkJReXhEUVVGRE8yOUNRVU5vUkN4RFFVRkZMRU5CUVVNc1JVRkJSU3hIUVVGVExFTkJRVVVzUTBGQlF5eHBRa0ZCYVVJc1IwRkJSeXhSUVVGUkxFTkJRVU1zUTBGQlF5eERRVUZETzJkQ1FVTXhSQ3hEUVVGRExFTkJRVU1zUTBGQlF6dGhRVU5PTzFsQlEwUXNTVUZCU1N4UFFVRlBMRU5CUVVNc1EwRkJReXhOUVVGTkxFdEJRVXNzVjBGQlZ5eEZRVUZGTzJkQ1FVTnFReXhEUVVGRExFTkJRVU1zVFVGQlRTeERRVUZETEU5QlFVOHNRMEZCUXl4VlFVRkJMRU5CUVVNc1NVRkJTU3hQUVVGQkxFMUJRVTBzUTBGQlF5eEpRVUZKTEVOQlFVTXNRMEZCUXl4RlFVRkZMRkZCUVZFc1EwRkJReXhGUVVGNFFpeERRVUYzUWl4RFFVRkRMRU5CUVVNN1lVRkRia1E3VTBGRFNqdGhRVUZOTzFsQlEwY3NRMEZCUlN4RFFVRkRMRVZCUVVVc1IwRkJSeXhSUVVGUkxFTkJRVU1zUTBGQlF5eERRVUZETzFsQlEyNUNMRU5CUVVVc1EwRkJReXhGUVVGRkxFZEJRVWNzVVVGQlVTeERRVUZETEVOQlFVTXNRMEZCUXp0VFFVTTFRanRKUVVOTUxFTkJRVU03U1VGSlRTeGpRVUZQTEVkQlFXUXNWVUZCWlN4RFFVRkRPMUZCUTFvc1NVRkJTU3hQUVVGUExFTkJRVU1zUTBGQlF5eERRVUZETEVWQlFVVTdXVUZEV2l4SlFVRkpMRTlCUVU4c1EwRkJReXhEUVVGRExFMUJRVTBzUzBGQlN5eFhRVUZYTEVWQlFVVTdaMEpCUTJwRExFTkJRVU1zUTBGQlF5eE5RVUZOTEVOQlFVTXNUMEZCVHl4RFFVRkRMRlZCUVVFc1EwRkJRenR2UWtGRFpDeE5RVUZOTEVOQlFVTXNUMEZCVHl4RFFVRkRMRU5CUVVNc1EwRkJReXhEUVVGRE8yOUNRVU5zUWl4UFFVRmhMRU5CUVVVc1EwRkJReXhwUWtGQmFVSXNRMEZCUXp0dlFrRkRiRU1zVDBGQllTeERRVUZGTEVOQlFVTXNhVUpCUVdsQ0xFTkJRVU03WjBKQlEzUkRMRU5CUVVNc1EwRkJReXhEUVVGRE8yRkJRMDQ3V1VGRFJDeEpRVUZKTEU5QlFVOHNRMEZCUXl4RFFVRkRMRTFCUVUwc1MwRkJTeXhYUVVGWExFVkJRVVU3WjBKQlEycERMRU5CUVVNc1EwRkJReXhOUVVGTkxFTkJRVU1zVDBGQlR5eERRVUZETEUxQlFVMHNRMEZCUXl4UFFVRlBMRU5CUVVNc1EwRkJRenRoUVVOd1F6dFRRVU5LTzJGQlFVMDdXVUZEU0N4RFFVRkRMRU5CUVVNc1MwRkJTeXhKUVVGSkxFTkJRVU1zUTBGQlF5eERRVUZETzFOQlJXcENPMGxCUTB3c1EwRkJRenRKUVVkTkxHZENRVUZUTEVkQlFXaENMRlZCUVdsQ0xFTkJRVU03VVVGRFpDeERRVUZETEVOQlFVTXNTMEZCU3l4SlFVRkpMRU5CUVVNc1EwRkJRenRSUVVOaUxFTkJRVU1zUTBGQlF5eEZRVUZGTEVkQlFVY3NRMEZCUXl4RFFVRkRMRU5CUVVNc1JVRkJSU3hEUVVGRExFTkJRVU1zUlVGQlJTeEhRVUZITEVOQlFVTXNRMEZCUXl4RFFVRkRMRU5CUVVNN1NVRkRNMElzUTBGQlF6dEpRVWROTEdWQlFWRXNSMEZCWml4VlFVRm5RaXhEUVVGRE8xRkJRMklzUTBGQlF5eERRVUZETEV0QlFVc3NTVUZCU1N4RFFVRkRMRU5CUVVNc1EwRkJRenRKUVVOc1FpeERRVUZETzBsQlEwd3NZVUZCUXp0QlFVRkVMRU5CUVVNc1FVRnNlVUpFTEVsQmEzbENRenRCUVd4NVFsa3NkMEpCUVUwaWZRPT0iLCJcInVzZSBzdHJpY3RcIjtcbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCBcIl9fZXNNb2R1bGVcIiwgeyB2YWx1ZTogdHJ1ZSB9KTtcbnZhciBzaG9ydGVzdHBhdGhzXzEgPSByZXF1aXJlKFwiLi9zaG9ydGVzdHBhdGhzXCIpO1xudmFyIGRlc2NlbnRfMSA9IHJlcXVpcmUoXCIuL2Rlc2NlbnRcIik7XG52YXIgcmVjdGFuZ2xlXzEgPSByZXF1aXJlKFwiLi9yZWN0YW5nbGVcIik7XG52YXIgbGlua2xlbmd0aHNfMSA9IHJlcXVpcmUoXCIuL2xpbmtsZW5ndGhzXCIpO1xudmFyIExpbmszRCA9IChmdW5jdGlvbiAoKSB7XG4gICAgZnVuY3Rpb24gTGluazNEKHNvdXJjZSwgdGFyZ2V0KSB7XG4gICAgICAgIHRoaXMuc291cmNlID0gc291cmNlO1xuICAgICAgICB0aGlzLnRhcmdldCA9IHRhcmdldDtcbiAgICB9XG4gICAgTGluazNELnByb3RvdHlwZS5hY3R1YWxMZW5ndGggPSBmdW5jdGlvbiAoeCkge1xuICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICByZXR1cm4gTWF0aC5zcXJ0KHgucmVkdWNlKGZ1bmN0aW9uIChjLCB2KSB7XG4gICAgICAgICAgICB2YXIgZHggPSB2W190aGlzLnRhcmdldF0gLSB2W190aGlzLnNvdXJjZV07XG4gICAgICAgICAgICByZXR1cm4gYyArIGR4ICogZHg7XG4gICAgICAgIH0sIDApKTtcbiAgICB9O1xuICAgIHJldHVybiBMaW5rM0Q7XG59KCkpO1xuZXhwb3J0cy5MaW5rM0QgPSBMaW5rM0Q7XG52YXIgTm9kZTNEID0gKGZ1bmN0aW9uICgpIHtcbiAgICBmdW5jdGlvbiBOb2RlM0QoeCwgeSwgeikge1xuICAgICAgICBpZiAoeCA9PT0gdm9pZCAwKSB7IHggPSAwOyB9XG4gICAgICAgIGlmICh5ID09PSB2b2lkIDApIHsgeSA9IDA7IH1cbiAgICAgICAgaWYgKHogPT09IHZvaWQgMCkgeyB6ID0gMDsgfVxuICAgICAgICB0aGlzLnggPSB4O1xuICAgICAgICB0aGlzLnkgPSB5O1xuICAgICAgICB0aGlzLnogPSB6O1xuICAgIH1cbiAgICByZXR1cm4gTm9kZTNEO1xufSgpKTtcbmV4cG9ydHMuTm9kZTNEID0gTm9kZTNEO1xudmFyIExheW91dDNEID0gKGZ1bmN0aW9uICgpIHtcbiAgICBmdW5jdGlvbiBMYXlvdXQzRChub2RlcywgbGlua3MsIGlkZWFsTGlua0xlbmd0aCkge1xuICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICBpZiAoaWRlYWxMaW5rTGVuZ3RoID09PSB2b2lkIDApIHsgaWRlYWxMaW5rTGVuZ3RoID0gMTsgfVxuICAgICAgICB0aGlzLm5vZGVzID0gbm9kZXM7XG4gICAgICAgIHRoaXMubGlua3MgPSBsaW5rcztcbiAgICAgICAgdGhpcy5pZGVhbExpbmtMZW5ndGggPSBpZGVhbExpbmtMZW5ndGg7XG4gICAgICAgIHRoaXMuY29uc3RyYWludHMgPSBudWxsO1xuICAgICAgICB0aGlzLnVzZUphY2NhcmRMaW5rTGVuZ3RocyA9IHRydWU7XG4gICAgICAgIHRoaXMucmVzdWx0ID0gbmV3IEFycmF5KExheW91dDNELmspO1xuICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IExheW91dDNELms7ICsraSkge1xuICAgICAgICAgICAgdGhpcy5yZXN1bHRbaV0gPSBuZXcgQXJyYXkobm9kZXMubGVuZ3RoKTtcbiAgICAgICAgfVxuICAgICAgICBub2Rlcy5mb3JFYWNoKGZ1bmN0aW9uICh2LCBpKSB7XG4gICAgICAgICAgICBmb3IgKHZhciBfaSA9IDAsIF9hID0gTGF5b3V0M0QuZGltczsgX2kgPCBfYS5sZW5ndGg7IF9pKyspIHtcbiAgICAgICAgICAgICAgICB2YXIgZGltID0gX2FbX2ldO1xuICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgdltkaW1dID09ICd1bmRlZmluZWQnKVxuICAgICAgICAgICAgICAgICAgICB2W2RpbV0gPSBNYXRoLnJhbmRvbSgpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgX3RoaXMucmVzdWx0WzBdW2ldID0gdi54O1xuICAgICAgICAgICAgX3RoaXMucmVzdWx0WzFdW2ldID0gdi55O1xuICAgICAgICAgICAgX3RoaXMucmVzdWx0WzJdW2ldID0gdi56O1xuICAgICAgICB9KTtcbiAgICB9XG4gICAgO1xuICAgIExheW91dDNELnByb3RvdHlwZS5saW5rTGVuZ3RoID0gZnVuY3Rpb24gKGwpIHtcbiAgICAgICAgcmV0dXJuIGwuYWN0dWFsTGVuZ3RoKHRoaXMucmVzdWx0KTtcbiAgICB9O1xuICAgIExheW91dDNELnByb3RvdHlwZS5zdGFydCA9IGZ1bmN0aW9uIChpdGVyYXRpb25zKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgICAgIGlmIChpdGVyYXRpb25zID09PSB2b2lkIDApIHsgaXRlcmF0aW9ucyA9IDEwMDsgfVxuICAgICAgICB2YXIgbiA9IHRoaXMubm9kZXMubGVuZ3RoO1xuICAgICAgICB2YXIgbGlua0FjY2Vzc29yID0gbmV3IExpbmtBY2Nlc3NvcigpO1xuICAgICAgICBpZiAodGhpcy51c2VKYWNjYXJkTGlua0xlbmd0aHMpXG4gICAgICAgICAgICBsaW5rbGVuZ3Roc18xLmphY2NhcmRMaW5rTGVuZ3Rocyh0aGlzLmxpbmtzLCBsaW5rQWNjZXNzb3IsIDEuNSk7XG4gICAgICAgIHRoaXMubGlua3MuZm9yRWFjaChmdW5jdGlvbiAoZSkgeyByZXR1cm4gZS5sZW5ndGggKj0gX3RoaXMuaWRlYWxMaW5rTGVuZ3RoOyB9KTtcbiAgICAgICAgdmFyIGRpc3RhbmNlTWF0cml4ID0gKG5ldyBzaG9ydGVzdHBhdGhzXzEuQ2FsY3VsYXRvcihuLCB0aGlzLmxpbmtzLCBmdW5jdGlvbiAoZSkgeyByZXR1cm4gZS5zb3VyY2U7IH0sIGZ1bmN0aW9uIChlKSB7IHJldHVybiBlLnRhcmdldDsgfSwgZnVuY3Rpb24gKGUpIHsgcmV0dXJuIGUubGVuZ3RoOyB9KSkuRGlzdGFuY2VNYXRyaXgoKTtcbiAgICAgICAgdmFyIEQgPSBkZXNjZW50XzEuRGVzY2VudC5jcmVhdGVTcXVhcmVNYXRyaXgobiwgZnVuY3Rpb24gKGksIGopIHsgcmV0dXJuIGRpc3RhbmNlTWF0cml4W2ldW2pdOyB9KTtcbiAgICAgICAgdmFyIEcgPSBkZXNjZW50XzEuRGVzY2VudC5jcmVhdGVTcXVhcmVNYXRyaXgobiwgZnVuY3Rpb24gKCkgeyByZXR1cm4gMjsgfSk7XG4gICAgICAgIHRoaXMubGlua3MuZm9yRWFjaChmdW5jdGlvbiAoX2EpIHtcbiAgICAgICAgICAgIHZhciBzb3VyY2UgPSBfYS5zb3VyY2UsIHRhcmdldCA9IF9hLnRhcmdldDtcbiAgICAgICAgICAgIHJldHVybiBHW3NvdXJjZV1bdGFyZ2V0XSA9IEdbdGFyZ2V0XVtzb3VyY2VdID0gMTtcbiAgICAgICAgfSk7XG4gICAgICAgIHRoaXMuZGVzY2VudCA9IG5ldyBkZXNjZW50XzEuRGVzY2VudCh0aGlzLnJlc3VsdCwgRCk7XG4gICAgICAgIHRoaXMuZGVzY2VudC50aHJlc2hvbGQgPSAxZS0zO1xuICAgICAgICB0aGlzLmRlc2NlbnQuRyA9IEc7XG4gICAgICAgIGlmICh0aGlzLmNvbnN0cmFpbnRzKVxuICAgICAgICAgICAgdGhpcy5kZXNjZW50LnByb2plY3QgPSBuZXcgcmVjdGFuZ2xlXzEuUHJvamVjdGlvbih0aGlzLm5vZGVzLCBudWxsLCBudWxsLCB0aGlzLmNvbnN0cmFpbnRzKS5wcm9qZWN0RnVuY3Rpb25zKCk7XG4gICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgdGhpcy5ub2Rlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgdmFyIHYgPSB0aGlzLm5vZGVzW2ldO1xuICAgICAgICAgICAgaWYgKHYuZml4ZWQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmRlc2NlbnQubG9ja3MuYWRkKGksIFt2LngsIHYueSwgdi56XSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5kZXNjZW50LnJ1bihpdGVyYXRpb25zKTtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfTtcbiAgICBMYXlvdXQzRC5wcm90b3R5cGUudGljayA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdGhpcy5kZXNjZW50LmxvY2tzLmNsZWFyKCk7XG4gICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgdGhpcy5ub2Rlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgdmFyIHYgPSB0aGlzLm5vZGVzW2ldO1xuICAgICAgICAgICAgaWYgKHYuZml4ZWQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmRlc2NlbnQubG9ja3MuYWRkKGksIFt2LngsIHYueSwgdi56XSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRoaXMuZGVzY2VudC5ydW5nZUt1dHRhKCk7XG4gICAgfTtcbiAgICBMYXlvdXQzRC5kaW1zID0gWyd4JywgJ3knLCAneiddO1xuICAgIExheW91dDNELmsgPSBMYXlvdXQzRC5kaW1zLmxlbmd0aDtcbiAgICByZXR1cm4gTGF5b3V0M0Q7XG59KCkpO1xuZXhwb3J0cy5MYXlvdXQzRCA9IExheW91dDNEO1xudmFyIExpbmtBY2Nlc3NvciA9IChmdW5jdGlvbiAoKSB7XG4gICAgZnVuY3Rpb24gTGlua0FjY2Vzc29yKCkge1xuICAgIH1cbiAgICBMaW5rQWNjZXNzb3IucHJvdG90eXBlLmdldFNvdXJjZUluZGV4ID0gZnVuY3Rpb24gKGUpIHsgcmV0dXJuIGUuc291cmNlOyB9O1xuICAgIExpbmtBY2Nlc3Nvci5wcm90b3R5cGUuZ2V0VGFyZ2V0SW5kZXggPSBmdW5jdGlvbiAoZSkgeyByZXR1cm4gZS50YXJnZXQ7IH07XG4gICAgTGlua0FjY2Vzc29yLnByb3RvdHlwZS5nZXRMZW5ndGggPSBmdW5jdGlvbiAoZSkgeyByZXR1cm4gZS5sZW5ndGg7IH07XG4gICAgTGlua0FjY2Vzc29yLnByb3RvdHlwZS5zZXRMZW5ndGggPSBmdW5jdGlvbiAoZSwgbCkgeyBlLmxlbmd0aCA9IGw7IH07XG4gICAgcmV0dXJuIExpbmtBY2Nlc3Nvcjtcbn0oKSk7XG4vLyMgc291cmNlTWFwcGluZ1VSTD1kYXRhOmFwcGxpY2F0aW9uL2pzb247YmFzZTY0LGV5SjJaWEp6YVc5dUlqb3pMQ0ptYVd4bElqb2liR0Y1YjNWME0yUXVhbk1pTENKemIzVnlZMlZTYjI5MElqb2lJaXdpYzI5MWNtTmxjeUk2V3lJdUxpOHVMaTlYWldKRGIyeGhMM055WXk5c1lYbHZkWFF6WkM1MGN5SmRMQ0p1WVcxbGN5STZXMTBzSW0xaGNIQnBibWR6SWpvaU96dEJRVUZCTEdsRVFVRXdRenRCUVVNeFF5eHhRMEZCYVVNN1FVRkRha01zZVVOQlFUUkVPMEZCUlRWRUxEWkRRVUZ2UlR0QlFVVndSVHRKUVVWUkxHZENRVUZ0UWl4TlFVRmpMRVZCUVZNc1RVRkJZenRSUVVGeVF5eFhRVUZOTEVkQlFVNHNUVUZCVFN4RFFVRlJPMUZCUVZNc1YwRkJUU3hIUVVGT0xFMUJRVTBzUTBGQlVUdEpRVUZKTEVOQlFVTTdTVUZETjBRc05rSkJRVmtzUjBGQldpeFZRVUZoTEVOQlFXRTdVVUZCTVVJc2FVSkJUVU03VVVGTVJ5eFBRVUZQTEVsQlFVa3NRMEZCUXl4SlFVRkpMRU5CUTFvc1EwRkJReXhEUVVGRExFMUJRVTBzUTBGQlF5eFZRVUZETEVOQlFWTXNSVUZCUlN4RFFVRlhPMWxCUXpWQ0xFbEJRVTBzUlVGQlJTeEhRVUZITEVOQlFVTXNRMEZCUXl4TFFVRkpMRU5CUVVNc1RVRkJUU3hEUVVGRExFZEJRVWNzUTBGQlF5eERRVUZETEV0QlFVa3NRMEZCUXl4TlFVRk5MRU5CUVVNc1EwRkJRenRaUVVNelF5eFBRVUZQTEVOQlFVTXNSMEZCUnl4RlFVRkZMRWRCUVVjc1JVRkJSU3hEUVVGRE8xRkJRM1pDTEVOQlFVTXNSVUZCUlN4RFFVRkRMRU5CUVVNc1EwRkJReXhEUVVGRE8wbEJRMllzUTBGQlF6dEpRVU5NTEdGQlFVTTdRVUZCUkN4RFFVRkRMRUZCVmt3c1NVRlZTenRCUVZaUkxIZENRVUZOTzBGQlYyWTdTVUZUU1N4blFrRkRWeXhEUVVGaExFVkJRMklzUTBGQllTeEZRVU5pTEVOQlFXRTdVVUZHWWl4clFrRkJRU3hGUVVGQkxFdEJRV0U3VVVGRFlpeHJRa0ZCUVN4RlFVRkJMRXRCUVdFN1VVRkRZaXhyUWtGQlFTeEZRVUZCTEV0QlFXRTdVVUZHWWl4TlFVRkRMRWRCUVVRc1EwRkJReXhEUVVGWk8xRkJRMklzVFVGQlF5eEhRVUZFTEVOQlFVTXNRMEZCV1R0UlFVTmlMRTFCUVVNc1IwRkJSQ3hEUVVGRExFTkJRVms3U1VGQlNTeERRVUZETzBsQlEycERMR0ZCUVVNN1FVRkJSQ3hEUVVGRExFRkJZa1FzU1VGaFF6dEJRV0paTEhkQ1FVRk5PMEZCWTI1Q08wbEJUVWtzYTBKQlFXMUNMRXRCUVdVc1JVRkJVeXhMUVVGbExFVkJRVk1zWlVGQk1rSTdVVUZCT1VZc2FVSkJZVU03VVVGaWEwVXNaME5CUVVFc1JVRkJRU3h0UWtGQk1rSTdVVUZCTTBVc1ZVRkJTeXhIUVVGTUxFdEJRVXNzUTBGQlZUdFJRVUZUTEZWQlFVc3NSMEZCVEN4TFFVRkxMRU5CUVZVN1VVRkJVeXh2UWtGQlpTeEhRVUZtTEdWQlFXVXNRMEZCV1R0UlFVWTVSaXhuUWtGQlZ5eEhRVUZWTEVsQlFVa3NRMEZCUXp0UlFYRkNNVUlzTUVKQlFYRkNMRWRCUVZrc1NVRkJTU3hEUVVGRE8xRkJiRUpzUXl4SlFVRkpMRU5CUVVNc1RVRkJUU3hIUVVGSExFbEJRVWtzUzBGQlN5eERRVUZETEZGQlFWRXNRMEZCUXl4RFFVRkRMRU5CUVVNc1EwRkJRenRSUVVOd1F5eExRVUZMTEVsQlFVa3NRMEZCUXl4SFFVRkhMRU5CUVVNc1JVRkJSU3hEUVVGRExFZEJRVWNzVVVGQlVTeERRVUZETEVOQlFVTXNSVUZCUlN4RlFVRkZMRU5CUVVNc1JVRkJSVHRaUVVOcVF5eEpRVUZKTEVOQlFVTXNUVUZCVFN4RFFVRkRMRU5CUVVNc1EwRkJReXhIUVVGSExFbEJRVWtzUzBGQlN5eERRVUZETEV0QlFVc3NRMEZCUXl4TlFVRk5MRU5CUVVNc1EwRkJRenRUUVVNMVF6dFJRVU5FTEV0QlFVc3NRMEZCUXl4UFFVRlBMRU5CUVVNc1ZVRkJReXhEUVVGRExFVkJRVVVzUTBGQlF6dFpRVU5tTEV0QlFXZENMRlZCUVdFc1JVRkJZaXhMUVVGQkxGRkJRVkVzUTBGQlF5eEpRVUZKTEVWQlFXSXNZMEZCWVN4RlFVRmlMRWxCUVdFc1JVRkJSVHRuUWtGQk1VSXNTVUZCU1N4SFFVRkhMRk5CUVVFN1owSkJRMUlzU1VGQlNTeFBRVUZQTEVOQlFVTXNRMEZCUXl4SFFVRkhMRU5CUVVNc1NVRkJTU3hYUVVGWE8yOUNRVUZGTEVOQlFVTXNRMEZCUXl4SFFVRkhMRU5CUVVNc1IwRkJSeXhKUVVGSkxFTkJRVU1zVFVGQlRTeEZRVUZGTEVOQlFVTTdZVUZETlVRN1dVRkRSQ3hMUVVGSkxFTkJRVU1zVFVGQlRTeERRVUZETEVOQlFVTXNRMEZCUXl4RFFVRkRMRU5CUVVNc1EwRkJReXhIUVVGSExFTkJRVU1zUTBGQlF5eERRVUZETEVOQlFVTTdXVUZEZUVJc1MwRkJTU3hEUVVGRExFMUJRVTBzUTBGQlF5eERRVUZETEVOQlFVTXNRMEZCUXl4RFFVRkRMRU5CUVVNc1IwRkJSeXhEUVVGRExFTkJRVU1zUTBGQlF5eERRVUZETzFsQlEzaENMRXRCUVVrc1EwRkJReXhOUVVGTkxFTkJRVU1zUTBGQlF5eERRVUZETEVOQlFVTXNRMEZCUXl4RFFVRkRMRWRCUVVjc1EwRkJReXhEUVVGRExFTkJRVU1zUTBGQlF6dFJRVU0xUWl4RFFVRkRMRU5CUVVNc1EwRkJRenRKUVVOUUxFTkJRVU03U1VGQlFTeERRVUZETzBsQlJVWXNOa0pCUVZVc1IwRkJWaXhWUVVGWExFTkJRVk03VVVGRGFFSXNUMEZCVHl4RFFVRkRMRU5CUVVNc1dVRkJXU3hEUVVGRExFbEJRVWtzUTBGQlF5eE5RVUZOTEVOQlFVTXNRMEZCUXp0SlFVTjJReXhEUVVGRE8wbEJTMFFzZDBKQlFVc3NSMEZCVEN4VlFVRk5MRlZCUVhkQ08xRkJRVGxDTEdsQ1FYVkRRenRSUVhaRFN5d3lRa0ZCUVN4RlFVRkJMR2RDUVVGM1FqdFJRVU14UWl4SlFVRk5MRU5CUVVNc1IwRkJSeXhKUVVGSkxFTkJRVU1zUzBGQlN5eERRVUZETEUxQlFVMHNRMEZCUXp0UlFVVTFRaXhKUVVGSkxGbEJRVmtzUjBGQlJ5eEpRVUZKTEZsQlFWa3NSVUZCUlN4RFFVRkRPMUZCUlhSRExFbEJRVWtzU1VGQlNTeERRVUZETEhGQ1FVRnhRanRaUVVNeFFpeG5RMEZCYTBJc1EwRkJReXhKUVVGSkxFTkJRVU1zUzBGQlN5eEZRVUZGTEZsQlFWa3NSVUZCUlN4SFFVRkhMRU5CUVVNc1EwRkJRenRSUVVWMFJDeEpRVUZKTEVOQlFVTXNTMEZCU3l4RFFVRkRMRTlCUVU4c1EwRkJReXhWUVVGQkxFTkJRVU1zU1VGQlNTeFBRVUZCTEVOQlFVTXNRMEZCUXl4TlFVRk5MRWxCUVVrc1MwRkJTU3hEUVVGRExHVkJRV1VzUlVGQmFFTXNRMEZCWjBNc1EwRkJReXhEUVVGRE8xRkJSekZFTEVsQlFVMHNZMEZCWXl4SFFVRkhMRU5CUVVNc1NVRkJTU3d3UWtGQlZTeERRVUZETEVOQlFVTXNSVUZCUlN4SlFVRkpMRU5CUVVNc1MwRkJTeXhGUVVOb1JDeFZRVUZCTEVOQlFVTXNTVUZCUnl4UFFVRkJMRU5CUVVNc1EwRkJReXhOUVVGTkxFVkJRVklzUTBGQlVTeEZRVUZGTEZWQlFVRXNRMEZCUXl4SlFVRkhMRTlCUVVFc1EwRkJReXhEUVVGRExFMUJRVTBzUlVGQlVpeERRVUZSTEVWQlFVVXNWVUZCUVN4RFFVRkRMRWxCUVVrc1QwRkJRU3hEUVVGRExFTkJRVU1zVFVGQlRTeEZRVUZTTEVOQlFWRXNRMEZCUXl4RFFVRkRMRU5CUVVNc1kwRkJZeXhGUVVGRkxFTkJRVU03VVVGRmFrVXNTVUZCVFN4RFFVRkRMRWRCUVVjc2FVSkJRVThzUTBGQlF5eHJRa0ZCYTBJc1EwRkJReXhEUVVGRExFVkJRVVVzVlVGQlF5eERRVUZETEVWQlFVVXNRMEZCUXl4SlFVRkxMRTlCUVVFc1kwRkJZeXhEUVVGRExFTkJRVU1zUTBGQlF5eERRVUZETEVOQlFVTXNRMEZCUXl4RlFVRndRaXhEUVVGdlFpeERRVUZETEVOQlFVTTdVVUZKZUVVc1NVRkJTU3hEUVVGRExFZEJRVWNzYVVKQlFVOHNRMEZCUXl4clFrRkJhMElzUTBGQlF5eERRVUZETEVWQlFVVXNZMEZCWXl4UFFVRlBMRU5CUVVNc1EwRkJRU3hEUVVGRExFTkJRVU1zUTBGQlF5eERRVUZETzFGQlEyaEZMRWxCUVVrc1EwRkJReXhMUVVGTExFTkJRVU1zVDBGQlR5eERRVUZETEZWQlFVTXNSVUZCYTBJN1owSkJRV2hDTEd0Q1FVRk5MRVZCUVVVc2EwSkJRVTA3V1VGQlR5eFBRVUZCTEVOQlFVTXNRMEZCUXl4TlFVRk5MRU5CUVVNc1EwRkJReXhOUVVGTkxFTkJRVU1zUjBGQlJ5eERRVUZETEVOQlFVTXNUVUZCVFN4RFFVRkRMRU5CUVVNc1RVRkJUU3hEUVVGRExFZEJRVWNzUTBGQlF6dFJRVUY2UXl4RFFVRjVReXhEUVVGRExFTkJRVU03VVVGRmRFWXNTVUZCU1N4RFFVRkRMRTlCUVU4c1IwRkJSeXhKUVVGSkxHbENRVUZQTEVOQlFVTXNTVUZCU1N4RFFVRkRMRTFCUVUwc1JVRkJSU3hEUVVGRExFTkJRVU1zUTBGQlF6dFJRVU16UXl4SlFVRkpMRU5CUVVNc1QwRkJUeXhEUVVGRExGTkJRVk1zUjBGQlJ5eEpRVUZKTEVOQlFVTTdVVUZET1VJc1NVRkJTU3hEUVVGRExFOUJRVThzUTBGQlF5eERRVUZETEVkQlFVY3NRMEZCUXl4RFFVRkRPMUZCU1c1Q0xFbEJRVWtzU1VGQlNTeERRVUZETEZkQlFWYzdXVUZEYUVJc1NVRkJTU3hEUVVGRExFOUJRVThzUTBGQlF5eFBRVUZQTEVkQlFVY3NTVUZCU1N4elFrRkJWU3hEUVVGakxFbEJRVWtzUTBGQlF5eExRVUZMTEVWQlFVVXNTVUZCU1N4RlFVRkZMRWxCUVVrc1JVRkJSU3hKUVVGSkxFTkJRVU1zVjBGQlZ5eERRVUZETEVOQlFVTXNaMEpCUVdkQ0xFVkJRVVVzUTBGQlF6dFJRVVZ3U0N4TFFVRkxMRWxCUVVrc1EwRkJReXhIUVVGSExFTkJRVU1zUlVGQlJTeERRVUZETEVkQlFVY3NTVUZCU1N4RFFVRkRMRXRCUVVzc1EwRkJReXhOUVVGTkxFVkJRVVVzUTBGQlF5eEZRVUZGTEVWQlFVVTdXVUZEZUVNc1NVRkJTU3hEUVVGRExFZEJRVWNzU1VGQlNTeERRVUZETEV0QlFVc3NRMEZCUXl4RFFVRkRMRU5CUVVNc1EwRkJRenRaUVVOMFFpeEpRVUZKTEVOQlFVTXNRMEZCUXl4TFFVRkxMRVZCUVVVN1owSkJRMVFzU1VGQlNTeERRVUZETEU5QlFVOHNRMEZCUXl4TFFVRkxMRU5CUVVNc1IwRkJSeXhEUVVGRExFTkJRVU1zUlVGQlJTeERRVUZETEVOQlFVTXNRMEZCUXl4RFFVRkRMRVZCUVVVc1EwRkJReXhEUVVGRExFTkJRVU1zUlVGQlJTeERRVUZETEVOQlFVTXNRMEZCUXl4RFFVRkRMRU5CUVVNc1EwRkJRenRoUVVNNVF6dFRRVU5LTzFGQlJVUXNTVUZCU1N4RFFVRkRMRTlCUVU4c1EwRkJReXhIUVVGSExFTkJRVU1zVlVGQlZTeERRVUZETEVOQlFVTTdVVUZETjBJc1QwRkJUeXhKUVVGSkxFTkJRVU03U1VGRGFFSXNRMEZCUXp0SlFVVkVMSFZDUVVGSkxFZEJRVW83VVVGRFNTeEpRVUZKTEVOQlFVTXNUMEZCVHl4RFFVRkRMRXRCUVVzc1EwRkJReXhMUVVGTExFVkJRVVVzUTBGQlF6dFJRVU16UWl4TFFVRkxMRWxCUVVrc1EwRkJReXhIUVVGSExFTkJRVU1zUlVGQlJTeERRVUZETEVkQlFVY3NTVUZCU1N4RFFVRkRMRXRCUVVzc1EwRkJReXhOUVVGTkxFVkJRVVVzUTBGQlF5eEZRVUZGTEVWQlFVVTdXVUZEZUVNc1NVRkJTU3hEUVVGRExFZEJRVWNzU1VGQlNTeERRVUZETEV0QlFVc3NRMEZCUXl4RFFVRkRMRU5CUVVNc1EwRkJRenRaUVVOMFFpeEpRVUZKTEVOQlFVTXNRMEZCUXl4TFFVRkxMRVZCUVVVN1owSkJRMVFzU1VGQlNTeERRVUZETEU5QlFVOHNRMEZCUXl4TFFVRkxMRU5CUVVNc1IwRkJSeXhEUVVGRExFTkJRVU1zUlVGQlJTeERRVUZETEVOQlFVTXNRMEZCUXl4RFFVRkRMRVZCUVVVc1EwRkJReXhEUVVGRExFTkJRVU1zUlVGQlJTeERRVUZETEVOQlFVTXNRMEZCUXl4RFFVRkRMRU5CUVVNc1EwRkJRenRoUVVNNVF6dFRRVU5LTzFGQlEwUXNUMEZCVHl4SlFVRkpMRU5CUVVNc1QwRkJUeXhEUVVGRExGVkJRVlVzUlVGQlJTeERRVUZETzBsQlEzSkRMRU5CUVVNN1NVRTNSVTBzWVVGQlNTeEhRVUZITEVOQlFVTXNSMEZCUnl4RlFVRkZMRWRCUVVjc1JVRkJSU3hIUVVGSExFTkJRVU1zUTBGQlF6dEpRVU4yUWl4VlFVRkRMRWRCUVVjc1VVRkJVU3hEUVVGRExFbEJRVWtzUTBGQlF5eE5RVUZOTEVOQlFVTTdTVUUyUlhCRExHVkJRVU03UTBGQlFTeEJRUzlGUkN4SlFTdEZRenRCUVM5RldTdzBRa0ZCVVR0QlFXbEdja0k3U1VGQlFUdEpRVXRCTEVOQlFVTTdTVUZLUnl4eFEwRkJZeXhIUVVGa0xGVkJRV1VzUTBGQlRTeEpRVUZaTEU5QlFVOHNRMEZCUXl4RFFVRkRMRTFCUVUwc1EwRkJReXhEUVVGRExFTkJRVU03U1VGRGJrUXNjVU5CUVdNc1IwRkJaQ3hWUVVGbExFTkJRVTBzU1VGQldTeFBRVUZQTEVOQlFVTXNRMEZCUXl4TlFVRk5MRU5CUVVNc1EwRkJReXhEUVVGRE8wbEJRMjVFTEdkRFFVRlRMRWRCUVZRc1ZVRkJWU3hEUVVGTkxFbEJRVmtzVDBGQlR5eERRVUZETEVOQlFVTXNUVUZCVFN4RFFVRkRMRU5CUVVNc1EwRkJRenRKUVVNNVF5eG5RMEZCVXl4SFFVRlVMRlZCUVZVc1EwRkJUU3hGUVVGRkxFTkJRVk1zU1VGQlNTeERRVUZETEVOQlFVTXNUVUZCVFN4SFFVRkhMRU5CUVVNc1EwRkJReXhEUVVGRExFTkJRVU03U1VGRGJFUXNiVUpCUVVNN1FVRkJSQ3hEUVVGRExFRkJURVFzU1VGTFF5SjkiLCJcInVzZSBzdHJpY3RcIjtcbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCBcIl9fZXNNb2R1bGVcIiwgeyB2YWx1ZTogdHJ1ZSB9KTtcbmZ1bmN0aW9uIHVuaW9uQ291bnQoYSwgYikge1xuICAgIHZhciB1ID0ge307XG4gICAgZm9yICh2YXIgaSBpbiBhKVxuICAgICAgICB1W2ldID0ge307XG4gICAgZm9yICh2YXIgaSBpbiBiKVxuICAgICAgICB1W2ldID0ge307XG4gICAgcmV0dXJuIE9iamVjdC5rZXlzKHUpLmxlbmd0aDtcbn1cbmZ1bmN0aW9uIGludGVyc2VjdGlvbkNvdW50KGEsIGIpIHtcbiAgICB2YXIgbiA9IDA7XG4gICAgZm9yICh2YXIgaSBpbiBhKVxuICAgICAgICBpZiAodHlwZW9mIGJbaV0gIT09ICd1bmRlZmluZWQnKVxuICAgICAgICAgICAgKytuO1xuICAgIHJldHVybiBuO1xufVxuZnVuY3Rpb24gZ2V0TmVpZ2hib3VycyhsaW5rcywgbGEpIHtcbiAgICB2YXIgbmVpZ2hib3VycyA9IHt9O1xuICAgIHZhciBhZGROZWlnaGJvdXJzID0gZnVuY3Rpb24gKHUsIHYpIHtcbiAgICAgICAgaWYgKHR5cGVvZiBuZWlnaGJvdXJzW3VdID09PSAndW5kZWZpbmVkJylcbiAgICAgICAgICAgIG5laWdoYm91cnNbdV0gPSB7fTtcbiAgICAgICAgbmVpZ2hib3Vyc1t1XVt2XSA9IHt9O1xuICAgIH07XG4gICAgbGlua3MuZm9yRWFjaChmdW5jdGlvbiAoZSkge1xuICAgICAgICB2YXIgdSA9IGxhLmdldFNvdXJjZUluZGV4KGUpLCB2ID0gbGEuZ2V0VGFyZ2V0SW5kZXgoZSk7XG4gICAgICAgIGFkZE5laWdoYm91cnModSwgdik7XG4gICAgICAgIGFkZE5laWdoYm91cnModiwgdSk7XG4gICAgfSk7XG4gICAgcmV0dXJuIG5laWdoYm91cnM7XG59XG5mdW5jdGlvbiBjb21wdXRlTGlua0xlbmd0aHMobGlua3MsIHcsIGYsIGxhKSB7XG4gICAgdmFyIG5laWdoYm91cnMgPSBnZXROZWlnaGJvdXJzKGxpbmtzLCBsYSk7XG4gICAgbGlua3MuZm9yRWFjaChmdW5jdGlvbiAobCkge1xuICAgICAgICB2YXIgYSA9IG5laWdoYm91cnNbbGEuZ2V0U291cmNlSW5kZXgobCldO1xuICAgICAgICB2YXIgYiA9IG5laWdoYm91cnNbbGEuZ2V0VGFyZ2V0SW5kZXgobCldO1xuICAgICAgICBsYS5zZXRMZW5ndGgobCwgMSArIHcgKiBmKGEsIGIpKTtcbiAgICB9KTtcbn1cbmZ1bmN0aW9uIHN5bW1ldHJpY0RpZmZMaW5rTGVuZ3RocyhsaW5rcywgbGEsIHcpIHtcbiAgICBpZiAodyA9PT0gdm9pZCAwKSB7IHcgPSAxOyB9XG4gICAgY29tcHV0ZUxpbmtMZW5ndGhzKGxpbmtzLCB3LCBmdW5jdGlvbiAoYSwgYikgeyByZXR1cm4gTWF0aC5zcXJ0KHVuaW9uQ291bnQoYSwgYikgLSBpbnRlcnNlY3Rpb25Db3VudChhLCBiKSk7IH0sIGxhKTtcbn1cbmV4cG9ydHMuc3ltbWV0cmljRGlmZkxpbmtMZW5ndGhzID0gc3ltbWV0cmljRGlmZkxpbmtMZW5ndGhzO1xuZnVuY3Rpb24gamFjY2FyZExpbmtMZW5ndGhzKGxpbmtzLCBsYSwgdykge1xuICAgIGlmICh3ID09PSB2b2lkIDApIHsgdyA9IDE7IH1cbiAgICBjb21wdXRlTGlua0xlbmd0aHMobGlua3MsIHcsIGZ1bmN0aW9uIChhLCBiKSB7XG4gICAgICAgIHJldHVybiBNYXRoLm1pbihPYmplY3Qua2V5cyhhKS5sZW5ndGgsIE9iamVjdC5rZXlzKGIpLmxlbmd0aCkgPCAxLjEgPyAwIDogaW50ZXJzZWN0aW9uQ291bnQoYSwgYikgLyB1bmlvbkNvdW50KGEsIGIpO1xuICAgIH0sIGxhKTtcbn1cbmV4cG9ydHMuamFjY2FyZExpbmtMZW5ndGhzID0gamFjY2FyZExpbmtMZW5ndGhzO1xuZnVuY3Rpb24gZ2VuZXJhdGVEaXJlY3RlZEVkZ2VDb25zdHJhaW50cyhuLCBsaW5rcywgYXhpcywgbGEpIHtcbiAgICB2YXIgY29tcG9uZW50cyA9IHN0cm9uZ2x5Q29ubmVjdGVkQ29tcG9uZW50cyhuLCBsaW5rcywgbGEpO1xuICAgIHZhciBub2RlcyA9IHt9O1xuICAgIGNvbXBvbmVudHMuZm9yRWFjaChmdW5jdGlvbiAoYywgaSkge1xuICAgICAgICByZXR1cm4gYy5mb3JFYWNoKGZ1bmN0aW9uICh2KSB7IHJldHVybiBub2Rlc1t2XSA9IGk7IH0pO1xuICAgIH0pO1xuICAgIHZhciBjb25zdHJhaW50cyA9IFtdO1xuICAgIGxpbmtzLmZvckVhY2goZnVuY3Rpb24gKGwpIHtcbiAgICAgICAgdmFyIHVpID0gbGEuZ2V0U291cmNlSW5kZXgobCksIHZpID0gbGEuZ2V0VGFyZ2V0SW5kZXgobCksIHUgPSBub2Rlc1t1aV0sIHYgPSBub2Rlc1t2aV07XG4gICAgICAgIGlmICh1ICE9PSB2KSB7XG4gICAgICAgICAgICBjb25zdHJhaW50cy5wdXNoKHtcbiAgICAgICAgICAgICAgICBheGlzOiBheGlzLFxuICAgICAgICAgICAgICAgIGxlZnQ6IHVpLFxuICAgICAgICAgICAgICAgIHJpZ2h0OiB2aSxcbiAgICAgICAgICAgICAgICBnYXA6IGxhLmdldE1pblNlcGFyYXRpb24obClcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgfSk7XG4gICAgcmV0dXJuIGNvbnN0cmFpbnRzO1xufVxuZXhwb3J0cy5nZW5lcmF0ZURpcmVjdGVkRWRnZUNvbnN0cmFpbnRzID0gZ2VuZXJhdGVEaXJlY3RlZEVkZ2VDb25zdHJhaW50cztcbmZ1bmN0aW9uIHN0cm9uZ2x5Q29ubmVjdGVkQ29tcG9uZW50cyhudW1WZXJ0aWNlcywgZWRnZXMsIGxhKSB7XG4gICAgdmFyIG5vZGVzID0gW107XG4gICAgdmFyIGluZGV4ID0gMDtcbiAgICB2YXIgc3RhY2sgPSBbXTtcbiAgICB2YXIgY29tcG9uZW50cyA9IFtdO1xuICAgIGZ1bmN0aW9uIHN0cm9uZ0Nvbm5lY3Qodikge1xuICAgICAgICB2LmluZGV4ID0gdi5sb3dsaW5rID0gaW5kZXgrKztcbiAgICAgICAgc3RhY2sucHVzaCh2KTtcbiAgICAgICAgdi5vblN0YWNrID0gdHJ1ZTtcbiAgICAgICAgZm9yICh2YXIgX2kgPSAwLCBfYSA9IHYub3V0OyBfaSA8IF9hLmxlbmd0aDsgX2krKykge1xuICAgICAgICAgICAgdmFyIHcgPSBfYVtfaV07XG4gICAgICAgICAgICBpZiAodHlwZW9mIHcuaW5kZXggPT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgICAgICAgICAgc3Ryb25nQ29ubmVjdCh3KTtcbiAgICAgICAgICAgICAgICB2Lmxvd2xpbmsgPSBNYXRoLm1pbih2Lmxvd2xpbmssIHcubG93bGluayk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIGlmICh3Lm9uU3RhY2spIHtcbiAgICAgICAgICAgICAgICB2Lmxvd2xpbmsgPSBNYXRoLm1pbih2Lmxvd2xpbmssIHcuaW5kZXgpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGlmICh2Lmxvd2xpbmsgPT09IHYuaW5kZXgpIHtcbiAgICAgICAgICAgIHZhciBjb21wb25lbnQgPSBbXTtcbiAgICAgICAgICAgIHdoaWxlIChzdGFjay5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICB3ID0gc3RhY2sucG9wKCk7XG4gICAgICAgICAgICAgICAgdy5vblN0YWNrID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgY29tcG9uZW50LnB1c2godyk7XG4gICAgICAgICAgICAgICAgaWYgKHcgPT09IHYpXG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY29tcG9uZW50cy5wdXNoKGNvbXBvbmVudC5tYXAoZnVuY3Rpb24gKHYpIHsgcmV0dXJuIHYuaWQ7IH0pKTtcbiAgICAgICAgfVxuICAgIH1cbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IG51bVZlcnRpY2VzOyBpKyspIHtcbiAgICAgICAgbm9kZXMucHVzaCh7IGlkOiBpLCBvdXQ6IFtdIH0pO1xuICAgIH1cbiAgICBmb3IgKHZhciBfaSA9IDAsIGVkZ2VzXzEgPSBlZGdlczsgX2kgPCBlZGdlc18xLmxlbmd0aDsgX2krKykge1xuICAgICAgICB2YXIgZSA9IGVkZ2VzXzFbX2ldO1xuICAgICAgICB2YXIgdl8xID0gbm9kZXNbbGEuZ2V0U291cmNlSW5kZXgoZSldLCB3ID0gbm9kZXNbbGEuZ2V0VGFyZ2V0SW5kZXgoZSldO1xuICAgICAgICB2XzEub3V0LnB1c2godyk7XG4gICAgfVxuICAgIGZvciAodmFyIF9hID0gMCwgbm9kZXNfMSA9IG5vZGVzOyBfYSA8IG5vZGVzXzEubGVuZ3RoOyBfYSsrKSB7XG4gICAgICAgIHZhciB2ID0gbm9kZXNfMVtfYV07XG4gICAgICAgIGlmICh0eXBlb2Ygdi5pbmRleCA9PT0gJ3VuZGVmaW5lZCcpXG4gICAgICAgICAgICBzdHJvbmdDb25uZWN0KHYpO1xuICAgIH1cbiAgICByZXR1cm4gY29tcG9uZW50cztcbn1cbmV4cG9ydHMuc3Ryb25nbHlDb25uZWN0ZWRDb21wb25lbnRzID0gc3Ryb25nbHlDb25uZWN0ZWRDb21wb25lbnRzO1xuLy8jIHNvdXJjZU1hcHBpbmdVUkw9ZGF0YTphcHBsaWNhdGlvbi9qc29uO2Jhc2U2NCxleUoyWlhKemFXOXVJam96TENKbWFXeGxJam9pYkdsdWEyeGxibWQwYUhNdWFuTWlMQ0p6YjNWeVkyVlNiMjkwSWpvaUlpd2ljMjkxY21ObGN5STZXeUl1TGk4dUxpOVhaV0pEYjJ4aEwzTnlZeTlzYVc1cmJHVnVaM1JvY3k1MGN5SmRMQ0p1WVcxbGN5STZXMTBzSW0xaGNIQnBibWR6SWpvaU96dEJRVlZKTEZOQlFWTXNWVUZCVlN4RFFVRkRMRU5CUVUwc1JVRkJSU3hEUVVGTk8wbEJRemxDTEVsQlFVa3NRMEZCUXl4SFFVRkhMRVZCUVVVc1EwRkJRenRKUVVOWUxFdEJRVXNzU1VGQlNTeERRVUZETEVsQlFVa3NRMEZCUXp0UlFVRkZMRU5CUVVNc1EwRkJReXhEUVVGRExFTkJRVU1zUjBGQlJ5eEZRVUZGTEVOQlFVTTdTVUZETTBJc1MwRkJTeXhKUVVGSkxFTkJRVU1zU1VGQlNTeERRVUZETzFGQlFVVXNRMEZCUXl4RFFVRkRMRU5CUVVNc1EwRkJReXhIUVVGSExFVkJRVVVzUTBGQlF6dEpRVU16UWl4UFFVRlBMRTFCUVUwc1EwRkJReXhKUVVGSkxFTkJRVU1zUTBGQlF5eERRVUZETEVOQlFVTXNUVUZCVFN4RFFVRkRPMEZCUTJwRExFTkJRVU03UVVGSFJDeFRRVUZUTEdsQ1FVRnBRaXhEUVVGRExFTkJRVmNzUlVGQlJTeERRVUZYTzBsQlF5OURMRWxCUVVrc1EwRkJReXhIUVVGSExFTkJRVU1zUTBGQlF6dEpRVU5XTEV0QlFVc3NTVUZCU1N4RFFVRkRMRWxCUVVrc1EwRkJRenRSUVVGRkxFbEJRVWtzVDBGQlR5eERRVUZETEVOQlFVTXNRMEZCUXl4RFFVRkRMRXRCUVVzc1YwRkJWenRaUVVGRkxFVkJRVVVzUTBGQlF5eERRVUZETzBsQlEzUkVMRTlCUVU4c1EwRkJReXhEUVVGRE8wRkJRMklzUTBGQlF6dEJRVVZFTEZOQlFWTXNZVUZCWVN4RFFVRlBMRXRCUVdFc1JVRkJSU3hGUVVGelFqdEpRVU01UkN4SlFVRkpMRlZCUVZVc1IwRkJSeXhGUVVGRkxFTkJRVU03U1VGRGNFSXNTVUZCU1N4aFFVRmhMRWRCUVVjc1ZVRkJReXhEUVVGRExFVkJRVVVzUTBGQlF6dFJRVU55UWl4SlFVRkpMRTlCUVU4c1ZVRkJWU3hEUVVGRExFTkJRVU1zUTBGQlF5eExRVUZMTEZkQlFWYzdXVUZEY0VNc1ZVRkJWU3hEUVVGRExFTkJRVU1zUTBGQlF5eEhRVUZITEVWQlFVVXNRMEZCUXp0UlFVTjJRaXhWUVVGVkxFTkJRVU1zUTBGQlF5eERRVUZETEVOQlFVTXNRMEZCUXl4RFFVRkRMRWRCUVVjc1JVRkJSU3hEUVVGRE8wbEJRekZDTEVOQlFVTXNRMEZCUXp0SlFVTkdMRXRCUVVzc1EwRkJReXhQUVVGUExFTkJRVU1zVlVGQlFTeERRVUZETzFGQlExZ3NTVUZCU1N4RFFVRkRMRWRCUVVjc1JVRkJSU3hEUVVGRExHTkJRV01zUTBGQlF5eERRVUZETEVOQlFVTXNSVUZCUlN4RFFVRkRMRWRCUVVjc1JVRkJSU3hEUVVGRExHTkJRV01zUTBGQlF5eERRVUZETEVOQlFVTXNRMEZCUXp0UlFVTjJSQ3hoUVVGaExFTkJRVU1zUTBGQlF5eEZRVUZGTEVOQlFVTXNRMEZCUXl4RFFVRkRPMUZCUTNCQ0xHRkJRV0VzUTBGQlF5eERRVUZETEVWQlFVVXNRMEZCUXl4RFFVRkRMRU5CUVVNN1NVRkRlRUlzUTBGQlF5eERRVUZETEVOQlFVTTdTVUZEU0N4UFFVRlBMRlZCUVZVc1EwRkJRenRCUVVOMFFpeERRVUZETzBGQlIwUXNVMEZCVXl4clFrRkJhMElzUTBGQlR5eExRVUZoTEVWQlFVVXNRMEZCVXl4RlFVRkZMRU5CUVRaQ0xFVkJRVVVzUlVGQk5FSTdTVUZEYmtnc1NVRkJTU3hWUVVGVkxFZEJRVWNzWVVGQllTeERRVUZETEV0QlFVc3NSVUZCUlN4RlFVRkZMRU5CUVVNc1EwRkJRenRKUVVNeFF5eExRVUZMTEVOQlFVTXNUMEZCVHl4RFFVRkRMRlZCUVVFc1EwRkJRenRSUVVOWUxFbEJRVWtzUTBGQlF5eEhRVUZITEZWQlFWVXNRMEZCUXl4RlFVRkZMRU5CUVVNc1kwRkJZeXhEUVVGRExFTkJRVU1zUTBGQlF5eERRVUZETEVOQlFVTTdVVUZEZWtNc1NVRkJTU3hEUVVGRExFZEJRVWNzVlVGQlZTeERRVUZETEVWQlFVVXNRMEZCUXl4alFVRmpMRU5CUVVNc1EwRkJReXhEUVVGRExFTkJRVU1zUTBGQlF6dFJRVU42UXl4RlFVRkZMRU5CUVVNc1UwRkJVeXhEUVVGRExFTkJRVU1zUlVGQlJTeERRVUZETEVkQlFVY3NRMEZCUXl4SFFVRkhMRU5CUVVNc1EwRkJReXhEUVVGRExFVkJRVVVzUTBGQlF5eERRVUZETEVOQlFVTXNRMEZCUXp0SlFVTnlReXhEUVVGRExFTkJRVU1zUTBGQlF6dEJRVU5RTEVOQlFVTTdRVUZMUkN4VFFVRm5RaXgzUWtGQmQwSXNRMEZCVHl4TFFVRmhMRVZCUVVVc1JVRkJORUlzUlVGQlJTeERRVUZoTzBsQlFXSXNhMEpCUVVFc1JVRkJRU3hMUVVGaE8wbEJRM0pITEd0Q1FVRnJRaXhEUVVGRExFdEJRVXNzUlVGQlJTeERRVUZETEVWQlFVVXNWVUZCUXl4RFFVRkRMRVZCUVVVc1EwRkJReXhKUVVGTExFOUJRVUVzU1VGQlNTeERRVUZETEVsQlFVa3NRMEZCUXl4VlFVRlZMRU5CUVVNc1EwRkJReXhGUVVGRkxFTkJRVU1zUTBGQlF5eEhRVUZITEdsQ1FVRnBRaXhEUVVGRExFTkJRVU1zUlVGQlJTeERRVUZETEVOQlFVTXNRMEZCUXl4RlFVRnlSQ3hEUVVGeFJDeEZRVUZGTEVWQlFVVXNRMEZCUXl4RFFVRkRPMEZCUTNSSExFTkJRVU03UVVGR1JDdzBSRUZGUXp0QlFVdEVMRk5CUVdkQ0xHdENRVUZyUWl4RFFVRlBMRXRCUVdFc1JVRkJSU3hGUVVFMFFpeEZRVUZGTEVOQlFXRTdTVUZCWWl4clFrRkJRU3hGUVVGQkxFdEJRV0U3U1VGREwwWXNhMEpCUVd0Q0xFTkJRVU1zUzBGQlN5eEZRVUZGTEVOQlFVTXNSVUZCUlN4VlFVRkRMRU5CUVVNc1JVRkJSU3hEUVVGRE8xRkJRemxDTEU5QlFVRXNTVUZCU1N4RFFVRkRMRWRCUVVjc1EwRkJReXhOUVVGTkxFTkJRVU1zU1VGQlNTeERRVUZETEVOQlFVTXNRMEZCUXl4RFFVRkRMRTFCUVUwc1JVRkJSU3hOUVVGTkxFTkJRVU1zU1VGQlNTeERRVUZETEVOQlFVTXNRMEZCUXl4RFFVRkRMRTFCUVUwc1EwRkJReXhIUVVGSExFZEJRVWNzUTBGQlF5eERRVUZETEVOQlFVTXNRMEZCUXl4RFFVRkRMRU5CUVVNc1EwRkJReXhwUWtGQmFVSXNRMEZCUXl4RFFVRkRMRVZCUVVVc1EwRkJReXhEUVVGRExFZEJRVWNzVlVGQlZTeERRVUZETEVOQlFVTXNSVUZCUlN4RFFVRkRMRU5CUVVNN1NVRkJOMGNzUTBGQk5rY3NSVUZETTBjc1JVRkJSU3hEUVVGRExFTkJRVU03UVVGRFpDeERRVUZETzBGQlNrUXNaMFJCU1VNN1FVRnZRa1FzVTBGQlowSXNLMEpCUVN0Q0xFTkJRVThzUTBGQlV5eEZRVUZGTEV0QlFXRXNSVUZCUlN4SlFVRlpMRVZCUTNoR0xFVkJRWGxDTzBsQlJYcENMRWxCUVVrc1ZVRkJWU3hIUVVGSExESkNRVUV5UWl4RFFVRkRMRU5CUVVNc1JVRkJSU3hMUVVGTExFVkJRVVVzUlVGQlJTeERRVUZETEVOQlFVTTdTVUZETTBRc1NVRkJTU3hMUVVGTExFZEJRVWNzUlVGQlJTeERRVUZETzBsQlEyWXNWVUZCVlN4RFFVRkRMRTlCUVU4c1EwRkJReXhWUVVGRExFTkJRVU1zUlVGQlF5eERRVUZETzFGQlEyNUNMRTlCUVVFc1EwRkJReXhEUVVGRExFOUJRVThzUTBGQlF5eFZRVUZCTEVOQlFVTXNTVUZCU1N4UFFVRkJMRXRCUVVzc1EwRkJReXhEUVVGRExFTkJRVU1zUjBGQlJ5eERRVUZETEVWQlFWb3NRMEZCV1N4RFFVRkRPMGxCUVRWQ0xFTkJRVFJDTEVOQlF5OUNMRU5CUVVNN1NVRkRSaXhKUVVGSkxGZEJRVmNzUjBGQlZTeEZRVUZGTEVOQlFVTTdTVUZETlVJc1MwRkJTeXhEUVVGRExFOUJRVThzUTBGQlF5eFZRVUZCTEVOQlFVTTdVVUZEV0N4SlFVRkpMRVZCUVVVc1IwRkJSeXhGUVVGRkxFTkJRVU1zWTBGQll5eERRVUZETEVOQlFVTXNRMEZCUXl4RlFVRkZMRVZCUVVVc1IwRkJSeXhGUVVGRkxFTkJRVU1zWTBGQll5eERRVUZETEVOQlFVTXNRMEZCUXl4RlFVTndSQ3hEUVVGRExFZEJRVWNzUzBGQlN5eERRVUZETEVWQlFVVXNRMEZCUXl4RlFVRkZMRU5CUVVNc1IwRkJSeXhMUVVGTExFTkJRVU1zUlVGQlJTeERRVUZETEVOQlFVTTdVVUZEYWtNc1NVRkJTU3hEUVVGRExFdEJRVXNzUTBGQlF5eEZRVUZGTzFsQlExUXNWMEZCVnl4RFFVRkRMRWxCUVVrc1EwRkJRenRuUWtGRFlpeEpRVUZKTEVWQlFVVXNTVUZCU1R0blFrRkRWaXhKUVVGSkxFVkJRVVVzUlVGQlJUdG5Ra0ZEVWl4TFFVRkxMRVZCUVVVc1JVRkJSVHRuUWtGRFZDeEhRVUZITEVWQlFVVXNSVUZCUlN4RFFVRkRMR2RDUVVGblFpeERRVUZETEVOQlFVTXNRMEZCUXp0aFFVTTVRaXhEUVVGRExFTkJRVU03VTBGRFRqdEpRVU5NTEVOQlFVTXNRMEZCUXl4RFFVRkRPMGxCUTBnc1QwRkJUeXhYUVVGWExFTkJRVU03UVVGRGRrSXNRMEZCUXp0QlFYUkNSQ3d3UlVGelFrTTdRVUZSUkN4VFFVRm5RaXd5UWtGQk1rSXNRMEZCVHl4WFFVRnRRaXhGUVVGRkxFdEJRV0VzUlVGQlJTeEZRVUZ6UWp0SlFVTjRSeXhKUVVGSkxFdEJRVXNzUjBGQlJ5eEZRVUZGTEVOQlFVTTdTVUZEWml4SlFVRkpMRXRCUVVzc1IwRkJSeXhEUVVGRExFTkJRVU03U1VGRFpDeEpRVUZKTEV0QlFVc3NSMEZCUnl4RlFVRkZMRU5CUVVNN1NVRkRaaXhKUVVGSkxGVkJRVlVzUjBGQlJ5eEZRVUZGTEVOQlFVTTdTVUZEY0VJc1UwRkJVeXhoUVVGaExFTkJRVU1zUTBGQlF6dFJRVVZ3UWl4RFFVRkRMRU5CUVVNc1MwRkJTeXhIUVVGSExFTkJRVU1zUTBGQlF5eFBRVUZQTEVkQlFVY3NTMEZCU3l4RlFVRkZMRU5CUVVNN1VVRkRPVUlzUzBGQlN5eERRVUZETEVsQlFVa3NRMEZCUXl4RFFVRkRMRU5CUVVNc1EwRkJRenRSUVVOa0xFTkJRVU1zUTBGQlF5eFBRVUZQTEVkQlFVY3NTVUZCU1N4RFFVRkRPMUZCUjJwQ0xFdEJRV01zVlVGQlN5eEZRVUZNTEV0QlFVRXNRMEZCUXl4RFFVRkRMRWRCUVVjc1JVRkJUQ3hqUVVGTExFVkJRVXdzU1VGQlN5eEZRVUZGTzFsQlFXaENMRWxCUVVrc1EwRkJReXhUUVVGQk8xbEJRMDRzU1VGQlNTeFBRVUZQTEVOQlFVTXNRMEZCUXl4TFFVRkxMRXRCUVVzc1YwRkJWeXhGUVVGRk8yZENRVVZvUXl4aFFVRmhMRU5CUVVNc1EwRkJReXhEUVVGRExFTkJRVU03WjBKQlEycENMRU5CUVVNc1EwRkJReXhQUVVGUExFZEJRVWNzU1VGQlNTeERRVUZETEVkQlFVY3NRMEZCUXl4RFFVRkRMRU5CUVVNc1QwRkJUeXhGUVVGRkxFTkJRVU1zUTBGQlF5eFBRVUZQTEVOQlFVTXNRMEZCUXp0aFFVTTVRenRwUWtGQlRTeEpRVUZKTEVOQlFVTXNRMEZCUXl4UFFVRlBMRVZCUVVVN1owSkJSV3hDTEVOQlFVTXNRMEZCUXl4UFFVRlBMRWRCUVVjc1NVRkJTU3hEUVVGRExFZEJRVWNzUTBGQlF5eERRVUZETEVOQlFVTXNUMEZCVHl4RlFVRkZMRU5CUVVNc1EwRkJReXhMUVVGTExFTkJRVU1zUTBGQlF6dGhRVU0xUXp0VFFVTktPMUZCUjBRc1NVRkJTU3hEUVVGRExFTkJRVU1zVDBGQlR5eExRVUZMTEVOQlFVTXNRMEZCUXl4TFFVRkxMRVZCUVVVN1dVRkZka0lzU1VGQlNTeFRRVUZUTEVkQlFVY3NSVUZCUlN4RFFVRkRPMWxCUTI1Q0xFOUJRVThzUzBGQlN5eERRVUZETEUxQlFVMHNSVUZCUlR0blFrRkRha0lzUTBGQlF5eEhRVUZITEV0QlFVc3NRMEZCUXl4SFFVRkhMRVZCUVVVc1EwRkJRenRuUWtGRGFFSXNRMEZCUXl4RFFVRkRMRTlCUVU4c1IwRkJSeXhMUVVGTExFTkJRVU03WjBKQlJXeENMRk5CUVZNc1EwRkJReXhKUVVGSkxFTkJRVU1zUTBGQlF5eERRVUZETEVOQlFVTTdaMEpCUTJ4Q0xFbEJRVWtzUTBGQlF5eExRVUZMTEVOQlFVTTdiMEpCUVVVc1RVRkJUVHRoUVVOMFFqdFpRVVZFTEZWQlFWVXNRMEZCUXl4SlFVRkpMRU5CUVVNc1UwRkJVeXhEUVVGRExFZEJRVWNzUTBGQlF5eFZRVUZCTEVOQlFVTXNTVUZCU1N4UFFVRkJMRU5CUVVNc1EwRkJReXhGUVVGRkxFVkJRVW9zUTBGQlNTeERRVUZETEVOQlFVTXNRMEZCUXp0VFFVTTNRenRKUVVOTUxFTkJRVU03U1VGRFJDeExRVUZMTEVsQlFVa3NRMEZCUXl4SFFVRkhMRU5CUVVNc1JVRkJSU3hEUVVGRExFZEJRVWNzVjBGQlZ5eEZRVUZGTEVOQlFVTXNSVUZCUlN4RlFVRkZPMUZCUTJ4RExFdEJRVXNzUTBGQlF5eEpRVUZKTEVOQlFVTXNSVUZCUXl4RlFVRkZMRVZCUVVVc1EwRkJReXhGUVVGRkxFZEJRVWNzUlVGQlJTeEZRVUZGTEVWQlFVTXNRMEZCUXl4RFFVRkRPMHRCUTJoRE8wbEJRMFFzUzBGQll5eFZRVUZMTEVWQlFVd3NaVUZCU3l4RlFVRk1MRzFDUVVGTExFVkJRVXdzU1VGQlN5eEZRVUZGTzFGQlFXaENMRWxCUVVrc1EwRkJReXhqUVVGQk8xRkJRMDRzU1VGQlNTeEhRVUZETEVkQlFVY3NTMEZCU3l4RFFVRkRMRVZCUVVVc1EwRkJReXhqUVVGakxFTkJRVU1zUTBGQlF5eERRVUZETEVOQlFVTXNSVUZETDBJc1EwRkJReXhIUVVGSExFdEJRVXNzUTBGQlF5eEZRVUZGTEVOQlFVTXNZMEZCWXl4RFFVRkRMRU5CUVVNc1EwRkJReXhEUVVGRExFTkJRVU03VVVGRGNFTXNSMEZCUXl4RFFVRkRMRWRCUVVjc1EwRkJReXhKUVVGSkxFTkJRVU1zUTBGQlF5eERRVUZETEVOQlFVTTdTMEZEYWtJN1NVRkRSQ3hMUVVGakxGVkJRVXNzUlVGQlRDeGxRVUZMTEVWQlFVd3NiVUpCUVVzc1JVRkJUQ3hKUVVGTE8xRkJRV1FzU1VGQlNTeERRVUZETEdOQlFVRTdVVUZCVnl4SlFVRkpMRTlCUVU4c1EwRkJReXhEUVVGRExFdEJRVXNzUzBGQlN5eFhRVUZYTzFsQlFVVXNZVUZCWVN4RFFVRkRMRU5CUVVNc1EwRkJReXhEUVVGRE8wdEJRVUU3U1VGRE1VVXNUMEZCVHl4VlFVRlZMRU5CUVVNN1FVRkRkRUlzUTBGQlF6dEJRV2hFUkN4clJVRm5SRU1pZlE9PSIsIlwidXNlIHN0cmljdFwiO1xuT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsIFwiX19lc01vZHVsZVwiLCB7IHZhbHVlOiB0cnVlIH0pO1xudmFyIFBvd2VyRWRnZSA9IChmdW5jdGlvbiAoKSB7XG4gICAgZnVuY3Rpb24gUG93ZXJFZGdlKHNvdXJjZSwgdGFyZ2V0LCB0eXBlKSB7XG4gICAgICAgIHRoaXMuc291cmNlID0gc291cmNlO1xuICAgICAgICB0aGlzLnRhcmdldCA9IHRhcmdldDtcbiAgICAgICAgdGhpcy50eXBlID0gdHlwZTtcbiAgICB9XG4gICAgcmV0dXJuIFBvd2VyRWRnZTtcbn0oKSk7XG5leHBvcnRzLlBvd2VyRWRnZSA9IFBvd2VyRWRnZTtcbnZhciBDb25maWd1cmF0aW9uID0gKGZ1bmN0aW9uICgpIHtcbiAgICBmdW5jdGlvbiBDb25maWd1cmF0aW9uKG4sIGVkZ2VzLCBsaW5rQWNjZXNzb3IsIHJvb3RHcm91cCkge1xuICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICB0aGlzLmxpbmtBY2Nlc3NvciA9IGxpbmtBY2Nlc3NvcjtcbiAgICAgICAgdGhpcy5tb2R1bGVzID0gbmV3IEFycmF5KG4pO1xuICAgICAgICB0aGlzLnJvb3RzID0gW107XG4gICAgICAgIGlmIChyb290R3JvdXApIHtcbiAgICAgICAgICAgIHRoaXMuaW5pdE1vZHVsZXNGcm9tR3JvdXAocm9vdEdyb3VwKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIHRoaXMucm9vdHMucHVzaChuZXcgTW9kdWxlU2V0KCkpO1xuICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBuOyArK2kpXG4gICAgICAgICAgICAgICAgdGhpcy5yb290c1swXS5hZGQodGhpcy5tb2R1bGVzW2ldID0gbmV3IE1vZHVsZShpKSk7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5SID0gZWRnZXMubGVuZ3RoO1xuICAgICAgICBlZGdlcy5mb3JFYWNoKGZ1bmN0aW9uIChlKSB7XG4gICAgICAgICAgICB2YXIgcyA9IF90aGlzLm1vZHVsZXNbbGlua0FjY2Vzc29yLmdldFNvdXJjZUluZGV4KGUpXSwgdCA9IF90aGlzLm1vZHVsZXNbbGlua0FjY2Vzc29yLmdldFRhcmdldEluZGV4KGUpXSwgdHlwZSA9IGxpbmtBY2Nlc3Nvci5nZXRUeXBlKGUpO1xuICAgICAgICAgICAgcy5vdXRnb2luZy5hZGQodHlwZSwgdCk7XG4gICAgICAgICAgICB0LmluY29taW5nLmFkZCh0eXBlLCBzKTtcbiAgICAgICAgfSk7XG4gICAgfVxuICAgIENvbmZpZ3VyYXRpb24ucHJvdG90eXBlLmluaXRNb2R1bGVzRnJvbUdyb3VwID0gZnVuY3Rpb24gKGdyb3VwKSB7XG4gICAgICAgIHZhciBtb2R1bGVTZXQgPSBuZXcgTW9kdWxlU2V0KCk7XG4gICAgICAgIHRoaXMucm9vdHMucHVzaChtb2R1bGVTZXQpO1xuICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGdyb3VwLmxlYXZlcy5sZW5ndGg7ICsraSkge1xuICAgICAgICAgICAgdmFyIG5vZGUgPSBncm91cC5sZWF2ZXNbaV07XG4gICAgICAgICAgICB2YXIgbW9kdWxlID0gbmV3IE1vZHVsZShub2RlLmlkKTtcbiAgICAgICAgICAgIHRoaXMubW9kdWxlc1tub2RlLmlkXSA9IG1vZHVsZTtcbiAgICAgICAgICAgIG1vZHVsZVNldC5hZGQobW9kdWxlKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoZ3JvdXAuZ3JvdXBzKSB7XG4gICAgICAgICAgICBmb3IgKHZhciBqID0gMDsgaiA8IGdyb3VwLmdyb3Vwcy5sZW5ndGg7ICsraikge1xuICAgICAgICAgICAgICAgIHZhciBjaGlsZCA9IGdyb3VwLmdyb3Vwc1tqXTtcbiAgICAgICAgICAgICAgICB2YXIgZGVmaW5pdGlvbiA9IHt9O1xuICAgICAgICAgICAgICAgIGZvciAodmFyIHByb3AgaW4gY2hpbGQpXG4gICAgICAgICAgICAgICAgICAgIGlmIChwcm9wICE9PSBcImxlYXZlc1wiICYmIHByb3AgIT09IFwiZ3JvdXBzXCIgJiYgY2hpbGQuaGFzT3duUHJvcGVydHkocHJvcCkpXG4gICAgICAgICAgICAgICAgICAgICAgICBkZWZpbml0aW9uW3Byb3BdID0gY2hpbGRbcHJvcF07XG4gICAgICAgICAgICAgICAgbW9kdWxlU2V0LmFkZChuZXcgTW9kdWxlKC0xIC0gaiwgbmV3IExpbmtTZXRzKCksIG5ldyBMaW5rU2V0cygpLCB0aGlzLmluaXRNb2R1bGVzRnJvbUdyb3VwKGNoaWxkKSwgZGVmaW5pdGlvbikpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiBtb2R1bGVTZXQ7XG4gICAgfTtcbiAgICBDb25maWd1cmF0aW9uLnByb3RvdHlwZS5tZXJnZSA9IGZ1bmN0aW9uIChhLCBiLCBrKSB7XG4gICAgICAgIGlmIChrID09PSB2b2lkIDApIHsgayA9IDA7IH1cbiAgICAgICAgdmFyIGluSW50ID0gYS5pbmNvbWluZy5pbnRlcnNlY3Rpb24oYi5pbmNvbWluZyksIG91dEludCA9IGEub3V0Z29pbmcuaW50ZXJzZWN0aW9uKGIub3V0Z29pbmcpO1xuICAgICAgICB2YXIgY2hpbGRyZW4gPSBuZXcgTW9kdWxlU2V0KCk7XG4gICAgICAgIGNoaWxkcmVuLmFkZChhKTtcbiAgICAgICAgY2hpbGRyZW4uYWRkKGIpO1xuICAgICAgICB2YXIgbSA9IG5ldyBNb2R1bGUodGhpcy5tb2R1bGVzLmxlbmd0aCwgb3V0SW50LCBpbkludCwgY2hpbGRyZW4pO1xuICAgICAgICB0aGlzLm1vZHVsZXMucHVzaChtKTtcbiAgICAgICAgdmFyIHVwZGF0ZSA9IGZ1bmN0aW9uIChzLCBpLCBvKSB7XG4gICAgICAgICAgICBzLmZvckFsbChmdW5jdGlvbiAobXMsIGxpbmt0eXBlKSB7XG4gICAgICAgICAgICAgICAgbXMuZm9yQWxsKGZ1bmN0aW9uIChuKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBubHMgPSBuW2ldO1xuICAgICAgICAgICAgICAgICAgICBubHMuYWRkKGxpbmt0eXBlLCBtKTtcbiAgICAgICAgICAgICAgICAgICAgbmxzLnJlbW92ZShsaW5rdHlwZSwgYSk7XG4gICAgICAgICAgICAgICAgICAgIG5scy5yZW1vdmUobGlua3R5cGUsIGIpO1xuICAgICAgICAgICAgICAgICAgICBhW29dLnJlbW92ZShsaW5rdHlwZSwgbik7XG4gICAgICAgICAgICAgICAgICAgIGJbb10ucmVtb3ZlKGxpbmt0eXBlLCBuKTtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9O1xuICAgICAgICB1cGRhdGUob3V0SW50LCBcImluY29taW5nXCIsIFwib3V0Z29pbmdcIik7XG4gICAgICAgIHVwZGF0ZShpbkludCwgXCJvdXRnb2luZ1wiLCBcImluY29taW5nXCIpO1xuICAgICAgICB0aGlzLlIgLT0gaW5JbnQuY291bnQoKSArIG91dEludC5jb3VudCgpO1xuICAgICAgICB0aGlzLnJvb3RzW2tdLnJlbW92ZShhKTtcbiAgICAgICAgdGhpcy5yb290c1trXS5yZW1vdmUoYik7XG4gICAgICAgIHRoaXMucm9vdHNba10uYWRkKG0pO1xuICAgICAgICByZXR1cm4gbTtcbiAgICB9O1xuICAgIENvbmZpZ3VyYXRpb24ucHJvdG90eXBlLnJvb3RNZXJnZXMgPSBmdW5jdGlvbiAoaykge1xuICAgICAgICBpZiAoayA9PT0gdm9pZCAwKSB7IGsgPSAwOyB9XG4gICAgICAgIHZhciBycyA9IHRoaXMucm9vdHNba10ubW9kdWxlcygpO1xuICAgICAgICB2YXIgbiA9IHJzLmxlbmd0aDtcbiAgICAgICAgdmFyIG1lcmdlcyA9IG5ldyBBcnJheShuICogKG4gLSAxKSk7XG4gICAgICAgIHZhciBjdHIgPSAwO1xuICAgICAgICBmb3IgKHZhciBpID0gMCwgaV8gPSBuIC0gMTsgaSA8IGlfOyArK2kpIHtcbiAgICAgICAgICAgIGZvciAodmFyIGogPSBpICsgMTsgaiA8IG47ICsraikge1xuICAgICAgICAgICAgICAgIHZhciBhID0gcnNbaV0sIGIgPSByc1tqXTtcbiAgICAgICAgICAgICAgICBtZXJnZXNbY3RyXSA9IHsgaWQ6IGN0ciwgbkVkZ2VzOiB0aGlzLm5FZGdlcyhhLCBiKSwgYTogYSwgYjogYiB9O1xuICAgICAgICAgICAgICAgIGN0cisrO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiBtZXJnZXM7XG4gICAgfTtcbiAgICBDb25maWd1cmF0aW9uLnByb3RvdHlwZS5ncmVlZHlNZXJnZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCB0aGlzLnJvb3RzLmxlbmd0aDsgKytpKSB7XG4gICAgICAgICAgICBpZiAodGhpcy5yb290c1tpXS5tb2R1bGVzKCkubGVuZ3RoIDwgMilcbiAgICAgICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICAgIHZhciBtcyA9IHRoaXMucm9vdE1lcmdlcyhpKS5zb3J0KGZ1bmN0aW9uIChhLCBiKSB7IHJldHVybiBhLm5FZGdlcyA9PSBiLm5FZGdlcyA/IGEuaWQgLSBiLmlkIDogYS5uRWRnZXMgLSBiLm5FZGdlczsgfSk7XG4gICAgICAgICAgICB2YXIgbSA9IG1zWzBdO1xuICAgICAgICAgICAgaWYgKG0ubkVkZ2VzID49IHRoaXMuUilcbiAgICAgICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICAgIHRoaXMubWVyZ2UobS5hLCBtLmIsIGkpO1xuICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIENvbmZpZ3VyYXRpb24ucHJvdG90eXBlLm5FZGdlcyA9IGZ1bmN0aW9uIChhLCBiKSB7XG4gICAgICAgIHZhciBpbkludCA9IGEuaW5jb21pbmcuaW50ZXJzZWN0aW9uKGIuaW5jb21pbmcpLCBvdXRJbnQgPSBhLm91dGdvaW5nLmludGVyc2VjdGlvbihiLm91dGdvaW5nKTtcbiAgICAgICAgcmV0dXJuIHRoaXMuUiAtIGluSW50LmNvdW50KCkgLSBvdXRJbnQuY291bnQoKTtcbiAgICB9O1xuICAgIENvbmZpZ3VyYXRpb24ucHJvdG90eXBlLmdldEdyb3VwSGllcmFyY2h5ID0gZnVuY3Rpb24gKHJldGFyZ2V0ZWRFZGdlcykge1xuICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICB2YXIgZ3JvdXBzID0gW107XG4gICAgICAgIHZhciByb290ID0ge307XG4gICAgICAgIHRvR3JvdXBzKHRoaXMucm9vdHNbMF0sIHJvb3QsIGdyb3Vwcyk7XG4gICAgICAgIHZhciBlcyA9IHRoaXMuYWxsRWRnZXMoKTtcbiAgICAgICAgZXMuZm9yRWFjaChmdW5jdGlvbiAoZSkge1xuICAgICAgICAgICAgdmFyIGEgPSBfdGhpcy5tb2R1bGVzW2Uuc291cmNlXTtcbiAgICAgICAgICAgIHZhciBiID0gX3RoaXMubW9kdWxlc1tlLnRhcmdldF07XG4gICAgICAgICAgICByZXRhcmdldGVkRWRnZXMucHVzaChuZXcgUG93ZXJFZGdlKHR5cGVvZiBhLmdpZCA9PT0gXCJ1bmRlZmluZWRcIiA/IGUuc291cmNlIDogZ3JvdXBzW2EuZ2lkXSwgdHlwZW9mIGIuZ2lkID09PSBcInVuZGVmaW5lZFwiID8gZS50YXJnZXQgOiBncm91cHNbYi5naWRdLCBlLnR5cGUpKTtcbiAgICAgICAgfSk7XG4gICAgICAgIHJldHVybiBncm91cHM7XG4gICAgfTtcbiAgICBDb25maWd1cmF0aW9uLnByb3RvdHlwZS5hbGxFZGdlcyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIGVzID0gW107XG4gICAgICAgIENvbmZpZ3VyYXRpb24uZ2V0RWRnZXModGhpcy5yb290c1swXSwgZXMpO1xuICAgICAgICByZXR1cm4gZXM7XG4gICAgfTtcbiAgICBDb25maWd1cmF0aW9uLmdldEVkZ2VzID0gZnVuY3Rpb24gKG1vZHVsZXMsIGVzKSB7XG4gICAgICAgIG1vZHVsZXMuZm9yQWxsKGZ1bmN0aW9uIChtKSB7XG4gICAgICAgICAgICBtLmdldEVkZ2VzKGVzKTtcbiAgICAgICAgICAgIENvbmZpZ3VyYXRpb24uZ2V0RWRnZXMobS5jaGlsZHJlbiwgZXMpO1xuICAgICAgICB9KTtcbiAgICB9O1xuICAgIHJldHVybiBDb25maWd1cmF0aW9uO1xufSgpKTtcbmV4cG9ydHMuQ29uZmlndXJhdGlvbiA9IENvbmZpZ3VyYXRpb247XG5mdW5jdGlvbiB0b0dyb3Vwcyhtb2R1bGVzLCBncm91cCwgZ3JvdXBzKSB7XG4gICAgbW9kdWxlcy5mb3JBbGwoZnVuY3Rpb24gKG0pIHtcbiAgICAgICAgaWYgKG0uaXNMZWFmKCkpIHtcbiAgICAgICAgICAgIGlmICghZ3JvdXAubGVhdmVzKVxuICAgICAgICAgICAgICAgIGdyb3VwLmxlYXZlcyA9IFtdO1xuICAgICAgICAgICAgZ3JvdXAubGVhdmVzLnB1c2gobS5pZCk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICB2YXIgZyA9IGdyb3VwO1xuICAgICAgICAgICAgbS5naWQgPSBncm91cHMubGVuZ3RoO1xuICAgICAgICAgICAgaWYgKCFtLmlzSXNsYW5kKCkgfHwgbS5pc1ByZWRlZmluZWQoKSkge1xuICAgICAgICAgICAgICAgIGcgPSB7IGlkOiBtLmdpZCB9O1xuICAgICAgICAgICAgICAgIGlmIChtLmlzUHJlZGVmaW5lZCgpKVxuICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBwcm9wIGluIG0uZGVmaW5pdGlvbilcbiAgICAgICAgICAgICAgICAgICAgICAgIGdbcHJvcF0gPSBtLmRlZmluaXRpb25bcHJvcF07XG4gICAgICAgICAgICAgICAgaWYgKCFncm91cC5ncm91cHMpXG4gICAgICAgICAgICAgICAgICAgIGdyb3VwLmdyb3VwcyA9IFtdO1xuICAgICAgICAgICAgICAgIGdyb3VwLmdyb3Vwcy5wdXNoKG0uZ2lkKTtcbiAgICAgICAgICAgICAgICBncm91cHMucHVzaChnKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRvR3JvdXBzKG0uY2hpbGRyZW4sIGcsIGdyb3Vwcyk7XG4gICAgICAgIH1cbiAgICB9KTtcbn1cbnZhciBNb2R1bGUgPSAoZnVuY3Rpb24gKCkge1xuICAgIGZ1bmN0aW9uIE1vZHVsZShpZCwgb3V0Z29pbmcsIGluY29taW5nLCBjaGlsZHJlbiwgZGVmaW5pdGlvbikge1xuICAgICAgICBpZiAob3V0Z29pbmcgPT09IHZvaWQgMCkgeyBvdXRnb2luZyA9IG5ldyBMaW5rU2V0cygpOyB9XG4gICAgICAgIGlmIChpbmNvbWluZyA9PT0gdm9pZCAwKSB7IGluY29taW5nID0gbmV3IExpbmtTZXRzKCk7IH1cbiAgICAgICAgaWYgKGNoaWxkcmVuID09PSB2b2lkIDApIHsgY2hpbGRyZW4gPSBuZXcgTW9kdWxlU2V0KCk7IH1cbiAgICAgICAgdGhpcy5pZCA9IGlkO1xuICAgICAgICB0aGlzLm91dGdvaW5nID0gb3V0Z29pbmc7XG4gICAgICAgIHRoaXMuaW5jb21pbmcgPSBpbmNvbWluZztcbiAgICAgICAgdGhpcy5jaGlsZHJlbiA9IGNoaWxkcmVuO1xuICAgICAgICB0aGlzLmRlZmluaXRpb24gPSBkZWZpbml0aW9uO1xuICAgIH1cbiAgICBNb2R1bGUucHJvdG90eXBlLmdldEVkZ2VzID0gZnVuY3Rpb24gKGVzKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgICAgIHRoaXMub3V0Z29pbmcuZm9yQWxsKGZ1bmN0aW9uIChtcywgZWRnZXR5cGUpIHtcbiAgICAgICAgICAgIG1zLmZvckFsbChmdW5jdGlvbiAodGFyZ2V0KSB7XG4gICAgICAgICAgICAgICAgZXMucHVzaChuZXcgUG93ZXJFZGdlKF90aGlzLmlkLCB0YXJnZXQuaWQsIGVkZ2V0eXBlKSk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfSk7XG4gICAgfTtcbiAgICBNb2R1bGUucHJvdG90eXBlLmlzTGVhZiA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuY2hpbGRyZW4uY291bnQoKSA9PT0gMDtcbiAgICB9O1xuICAgIE1vZHVsZS5wcm90b3R5cGUuaXNJc2xhbmQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLm91dGdvaW5nLmNvdW50KCkgPT09IDAgJiYgdGhpcy5pbmNvbWluZy5jb3VudCgpID09PSAwO1xuICAgIH07XG4gICAgTW9kdWxlLnByb3RvdHlwZS5pc1ByZWRlZmluZWQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0eXBlb2YgdGhpcy5kZWZpbml0aW9uICE9PSBcInVuZGVmaW5lZFwiO1xuICAgIH07XG4gICAgcmV0dXJuIE1vZHVsZTtcbn0oKSk7XG5leHBvcnRzLk1vZHVsZSA9IE1vZHVsZTtcbmZ1bmN0aW9uIGludGVyc2VjdGlvbihtLCBuKSB7XG4gICAgdmFyIGkgPSB7fTtcbiAgICBmb3IgKHZhciB2IGluIG0pXG4gICAgICAgIGlmICh2IGluIG4pXG4gICAgICAgICAgICBpW3ZdID0gbVt2XTtcbiAgICByZXR1cm4gaTtcbn1cbnZhciBNb2R1bGVTZXQgPSAoZnVuY3Rpb24gKCkge1xuICAgIGZ1bmN0aW9uIE1vZHVsZVNldCgpIHtcbiAgICAgICAgdGhpcy50YWJsZSA9IHt9O1xuICAgIH1cbiAgICBNb2R1bGVTZXQucHJvdG90eXBlLmNvdW50ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gT2JqZWN0LmtleXModGhpcy50YWJsZSkubGVuZ3RoO1xuICAgIH07XG4gICAgTW9kdWxlU2V0LnByb3RvdHlwZS5pbnRlcnNlY3Rpb24gPSBmdW5jdGlvbiAob3RoZXIpIHtcbiAgICAgICAgdmFyIHJlc3VsdCA9IG5ldyBNb2R1bGVTZXQoKTtcbiAgICAgICAgcmVzdWx0LnRhYmxlID0gaW50ZXJzZWN0aW9uKHRoaXMudGFibGUsIG90aGVyLnRhYmxlKTtcbiAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9O1xuICAgIE1vZHVsZVNldC5wcm90b3R5cGUuaW50ZXJzZWN0aW9uQ291bnQgPSBmdW5jdGlvbiAob3RoZXIpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuaW50ZXJzZWN0aW9uKG90aGVyKS5jb3VudCgpO1xuICAgIH07XG4gICAgTW9kdWxlU2V0LnByb3RvdHlwZS5jb250YWlucyA9IGZ1bmN0aW9uIChpZCkge1xuICAgICAgICByZXR1cm4gaWQgaW4gdGhpcy50YWJsZTtcbiAgICB9O1xuICAgIE1vZHVsZVNldC5wcm90b3R5cGUuYWRkID0gZnVuY3Rpb24gKG0pIHtcbiAgICAgICAgdGhpcy50YWJsZVttLmlkXSA9IG07XG4gICAgfTtcbiAgICBNb2R1bGVTZXQucHJvdG90eXBlLnJlbW92ZSA9IGZ1bmN0aW9uIChtKSB7XG4gICAgICAgIGRlbGV0ZSB0aGlzLnRhYmxlW20uaWRdO1xuICAgIH07XG4gICAgTW9kdWxlU2V0LnByb3RvdHlwZS5mb3JBbGwgPSBmdW5jdGlvbiAoZikge1xuICAgICAgICBmb3IgKHZhciBtaWQgaW4gdGhpcy50YWJsZSkge1xuICAgICAgICAgICAgZih0aGlzLnRhYmxlW21pZF0pO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBNb2R1bGVTZXQucHJvdG90eXBlLm1vZHVsZXMgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciB2cyA9IFtdO1xuICAgICAgICB0aGlzLmZvckFsbChmdW5jdGlvbiAobSkge1xuICAgICAgICAgICAgaWYgKCFtLmlzUHJlZGVmaW5lZCgpKVxuICAgICAgICAgICAgICAgIHZzLnB1c2gobSk7XG4gICAgICAgIH0pO1xuICAgICAgICByZXR1cm4gdnM7XG4gICAgfTtcbiAgICByZXR1cm4gTW9kdWxlU2V0O1xufSgpKTtcbmV4cG9ydHMuTW9kdWxlU2V0ID0gTW9kdWxlU2V0O1xudmFyIExpbmtTZXRzID0gKGZ1bmN0aW9uICgpIHtcbiAgICBmdW5jdGlvbiBMaW5rU2V0cygpIHtcbiAgICAgICAgdGhpcy5zZXRzID0ge307XG4gICAgICAgIHRoaXMubiA9IDA7XG4gICAgfVxuICAgIExpbmtTZXRzLnByb3RvdHlwZS5jb3VudCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMubjtcbiAgICB9O1xuICAgIExpbmtTZXRzLnByb3RvdHlwZS5jb250YWlucyA9IGZ1bmN0aW9uIChpZCkge1xuICAgICAgICB2YXIgcmVzdWx0ID0gZmFsc2U7XG4gICAgICAgIHRoaXMuZm9yQWxsTW9kdWxlcyhmdW5jdGlvbiAobSkge1xuICAgICAgICAgICAgaWYgKCFyZXN1bHQgJiYgbS5pZCA9PSBpZCkge1xuICAgICAgICAgICAgICAgIHJlc3VsdCA9IHRydWU7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH07XG4gICAgTGlua1NldHMucHJvdG90eXBlLmFkZCA9IGZ1bmN0aW9uIChsaW5rdHlwZSwgbSkge1xuICAgICAgICB2YXIgcyA9IGxpbmt0eXBlIGluIHRoaXMuc2V0cyA/IHRoaXMuc2V0c1tsaW5rdHlwZV0gOiB0aGlzLnNldHNbbGlua3R5cGVdID0gbmV3IE1vZHVsZVNldCgpO1xuICAgICAgICBzLmFkZChtKTtcbiAgICAgICAgKyt0aGlzLm47XG4gICAgfTtcbiAgICBMaW5rU2V0cy5wcm90b3R5cGUucmVtb3ZlID0gZnVuY3Rpb24gKGxpbmt0eXBlLCBtKSB7XG4gICAgICAgIHZhciBtcyA9IHRoaXMuc2V0c1tsaW5rdHlwZV07XG4gICAgICAgIG1zLnJlbW92ZShtKTtcbiAgICAgICAgaWYgKG1zLmNvdW50KCkgPT09IDApIHtcbiAgICAgICAgICAgIGRlbGV0ZSB0aGlzLnNldHNbbGlua3R5cGVdO1xuICAgICAgICB9XG4gICAgICAgIC0tdGhpcy5uO1xuICAgIH07XG4gICAgTGlua1NldHMucHJvdG90eXBlLmZvckFsbCA9IGZ1bmN0aW9uIChmKSB7XG4gICAgICAgIGZvciAodmFyIGxpbmt0eXBlIGluIHRoaXMuc2V0cykge1xuICAgICAgICAgICAgZih0aGlzLnNldHNbbGlua3R5cGVdLCBOdW1iZXIobGlua3R5cGUpKTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgTGlua1NldHMucHJvdG90eXBlLmZvckFsbE1vZHVsZXMgPSBmdW5jdGlvbiAoZikge1xuICAgICAgICB0aGlzLmZvckFsbChmdW5jdGlvbiAobXMsIGx0KSB7IHJldHVybiBtcy5mb3JBbGwoZik7IH0pO1xuICAgIH07XG4gICAgTGlua1NldHMucHJvdG90eXBlLmludGVyc2VjdGlvbiA9IGZ1bmN0aW9uIChvdGhlcikge1xuICAgICAgICB2YXIgcmVzdWx0ID0gbmV3IExpbmtTZXRzKCk7XG4gICAgICAgIHRoaXMuZm9yQWxsKGZ1bmN0aW9uIChtcywgbHQpIHtcbiAgICAgICAgICAgIGlmIChsdCBpbiBvdGhlci5zZXRzKSB7XG4gICAgICAgICAgICAgICAgdmFyIGkgPSBtcy5pbnRlcnNlY3Rpb24ob3RoZXIuc2V0c1tsdF0pLCBuID0gaS5jb3VudCgpO1xuICAgICAgICAgICAgICAgIGlmIChuID4gMCkge1xuICAgICAgICAgICAgICAgICAgICByZXN1bHQuc2V0c1tsdF0gPSBpO1xuICAgICAgICAgICAgICAgICAgICByZXN1bHQubiArPSBuO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfTtcbiAgICByZXR1cm4gTGlua1NldHM7XG59KCkpO1xuZXhwb3J0cy5MaW5rU2V0cyA9IExpbmtTZXRzO1xuZnVuY3Rpb24gaW50ZXJzZWN0aW9uQ291bnQobSwgbikge1xuICAgIHJldHVybiBPYmplY3Qua2V5cyhpbnRlcnNlY3Rpb24obSwgbikpLmxlbmd0aDtcbn1cbmZ1bmN0aW9uIGdldEdyb3Vwcyhub2RlcywgbGlua3MsIGxhLCByb290R3JvdXApIHtcbiAgICB2YXIgbiA9IG5vZGVzLmxlbmd0aCwgYyA9IG5ldyBDb25maWd1cmF0aW9uKG4sIGxpbmtzLCBsYSwgcm9vdEdyb3VwKTtcbiAgICB3aGlsZSAoYy5ncmVlZHlNZXJnZSgpKVxuICAgICAgICA7XG4gICAgdmFyIHBvd2VyRWRnZXMgPSBbXTtcbiAgICB2YXIgZyA9IGMuZ2V0R3JvdXBIaWVyYXJjaHkocG93ZXJFZGdlcyk7XG4gICAgcG93ZXJFZGdlcy5mb3JFYWNoKGZ1bmN0aW9uIChlKSB7XG4gICAgICAgIHZhciBmID0gZnVuY3Rpb24gKGVuZCkge1xuICAgICAgICAgICAgdmFyIGcgPSBlW2VuZF07XG4gICAgICAgICAgICBpZiAodHlwZW9mIGcgPT0gXCJudW1iZXJcIilcbiAgICAgICAgICAgICAgICBlW2VuZF0gPSBub2Rlc1tnXTtcbiAgICAgICAgfTtcbiAgICAgICAgZihcInNvdXJjZVwiKTtcbiAgICAgICAgZihcInRhcmdldFwiKTtcbiAgICB9KTtcbiAgICByZXR1cm4geyBncm91cHM6IGcsIHBvd2VyRWRnZXM6IHBvd2VyRWRnZXMgfTtcbn1cbmV4cG9ydHMuZ2V0R3JvdXBzID0gZ2V0R3JvdXBzO1xuLy8jIHNvdXJjZU1hcHBpbmdVUkw9ZGF0YTphcHBsaWNhdGlvbi9qc29uO2Jhc2U2NCxleUoyWlhKemFXOXVJam96TENKbWFXeGxJam9pY0c5M1pYSm5jbUZ3YUM1cWN5SXNJbk52ZFhKalpWSnZiM1FpT2lJaUxDSnpiM1Z5WTJWeklqcGJJaTR1THk0dUwxZGxZa052YkdFdmMzSmpMM0J2ZDJWeVozSmhjR2d1ZEhNaVhTd2libUZ0WlhNaU9sdGRMQ0p0WVhCd2FXNW5jeUk2SWpzN1FVRlBTVHRKUVVOSkxHMUNRVU5YTEUxQlFWY3NSVUZEV0N4TlFVRlhMRVZCUTFnc1NVRkJXVHRSUVVaYUxGZEJRVTBzUjBGQlRpeE5RVUZOTEVOQlFVczdVVUZEV0N4WFFVRk5MRWRCUVU0c1RVRkJUU3hEUVVGTE8xRkJRMWdzVTBGQlNTeEhRVUZLTEVsQlFVa3NRMEZCVVR0SlFVRkpMRU5CUVVNN1NVRkRhRU1zWjBKQlFVTTdRVUZCUkN4RFFVRkRMRUZCVEVRc1NVRkxRenRCUVV4WkxEaENRVUZUTzBGQlQzUkNPMGxCVTBrc2RVSkJRVmtzUTBGQlV5eEZRVUZGTEV0QlFXRXNSVUZCVlN4WlFVRnZReXhGUVVGRkxGTkJRV2xDTzFGQlFYSkhMR2xDUVd0Q1F6dFJRV3hDTmtNc2FVSkJRVmtzUjBGQldpeFpRVUZaTEVOQlFYZENPMUZCUXpsRkxFbEJRVWtzUTBGQlF5eFBRVUZQTEVkQlFVY3NTVUZCU1N4TFFVRkxMRU5CUVVNc1EwRkJReXhEUVVGRExFTkJRVU03VVVGRE5VSXNTVUZCU1N4RFFVRkRMRXRCUVVzc1IwRkJSeXhGUVVGRkxFTkJRVU03VVVGRGFFSXNTVUZCU1N4VFFVRlRMRVZCUVVVN1dVRkRXQ3hKUVVGSkxFTkJRVU1zYjBKQlFXOUNMRU5CUVVNc1UwRkJVeXhEUVVGRExFTkJRVU03VTBGRGVFTTdZVUZCVFR0WlFVTklMRWxCUVVrc1EwRkJReXhMUVVGTExFTkJRVU1zU1VGQlNTeERRVUZETEVsQlFVa3NVMEZCVXl4RlFVRkZMRU5CUVVNc1EwRkJRenRaUVVOcVF5eExRVUZMTEVsQlFVa3NRMEZCUXl4SFFVRkhMRU5CUVVNc1JVRkJSU3hEUVVGRExFZEJRVWNzUTBGQlF5eEZRVUZGTEVWQlFVVXNRMEZCUXp0blFrRkRkRUlzU1VGQlNTeERRVUZETEV0QlFVc3NRMEZCUXl4RFFVRkRMRU5CUVVNc1EwRkJReXhIUVVGSExFTkJRVU1zU1VGQlNTeERRVUZETEU5QlFVOHNRMEZCUXl4RFFVRkRMRU5CUVVNc1IwRkJSeXhKUVVGSkxFMUJRVTBzUTBGQlF5eERRVUZETEVOQlFVTXNRMEZCUXl4RFFVRkRPMU5CUXpGRU8xRkJRMFFzU1VGQlNTeERRVUZETEVOQlFVTXNSMEZCUnl4TFFVRkxMRU5CUVVNc1RVRkJUU3hEUVVGRE8xRkJRM1JDTEV0QlFVc3NRMEZCUXl4UFFVRlBMRU5CUVVNc1ZVRkJRU3hEUVVGRE8xbEJRMWdzU1VGQlNTeERRVUZETEVkQlFVY3NTMEZCU1N4RFFVRkRMRTlCUVU4c1EwRkJReXhaUVVGWkxFTkJRVU1zWTBGQll5eERRVUZETEVOQlFVTXNRMEZCUXl4RFFVRkRMRVZCUTJoRUxFTkJRVU1zUjBGQlJ5eExRVUZKTEVOQlFVTXNUMEZCVHl4RFFVRkRMRmxCUVZrc1EwRkJReXhqUVVGakxFTkJRVU1zUTBGQlF5eERRVUZETEVOQlFVTXNSVUZEYUVRc1NVRkJTU3hIUVVGSExGbEJRVmtzUTBGQlF5eFBRVUZQTEVOQlFVTXNRMEZCUXl4RFFVRkRMRU5CUVVNN1dVRkRia01zUTBGQlF5eERRVUZETEZGQlFWRXNRMEZCUXl4SFFVRkhMRU5CUVVNc1NVRkJTU3hGUVVGRkxFTkJRVU1zUTBGQlF5eERRVUZETzFsQlEzaENMRU5CUVVNc1EwRkJReXhSUVVGUkxFTkJRVU1zUjBGQlJ5eERRVUZETEVsQlFVa3NSVUZCUlN4RFFVRkRMRU5CUVVNc1EwRkJRenRSUVVNMVFpeERRVUZETEVOQlFVTXNRMEZCUXp0SlFVTlFMRU5CUVVNN1NVRkZUeXcwUTBGQmIwSXNSMEZCTlVJc1ZVRkJOa0lzUzBGQlN6dFJRVU01UWl4SlFVRkpMRk5CUVZNc1IwRkJSeXhKUVVGSkxGTkJRVk1zUlVGQlJTeERRVUZETzFGQlEyaERMRWxCUVVrc1EwRkJReXhMUVVGTExFTkJRVU1zU1VGQlNTeERRVUZETEZOQlFWTXNRMEZCUXl4RFFVRkRPMUZCUXpOQ0xFdEJRVXNzU1VGQlNTeERRVUZETEVkQlFVY3NRMEZCUXl4RlFVRkZMRU5CUVVNc1IwRkJSeXhMUVVGTExFTkJRVU1zVFVGQlRTeERRVUZETEUxQlFVMHNSVUZCUlN4RlFVRkZMRU5CUVVNc1JVRkJSVHRaUVVNeFF5eEpRVUZKTEVsQlFVa3NSMEZCUnl4TFFVRkxMRU5CUVVNc1RVRkJUU3hEUVVGRExFTkJRVU1zUTBGQlF5eERRVUZETzFsQlF6TkNMRWxCUVVrc1RVRkJUU3hIUVVGSExFbEJRVWtzVFVGQlRTeERRVUZETEVsQlFVa3NRMEZCUXl4RlFVRkZMRU5CUVVNc1EwRkJRenRaUVVOcVF5eEpRVUZKTEVOQlFVTXNUMEZCVHl4RFFVRkRMRWxCUVVrc1EwRkJReXhGUVVGRkxFTkJRVU1zUjBGQlJ5eE5RVUZOTEVOQlFVTTdXVUZETDBJc1UwRkJVeXhEUVVGRExFZEJRVWNzUTBGQlF5eE5RVUZOTEVOQlFVTXNRMEZCUXp0VFFVTjZRanRSUVVORUxFbEJRVWtzUzBGQlN5eERRVUZETEUxQlFVMHNSVUZCUlR0WlFVTmtMRXRCUVVzc1NVRkJTU3hEUVVGRExFZEJRVWNzUTBGQlF5eEZRVUZGTEVOQlFVTXNSMEZCUnl4TFFVRkxMRU5CUVVNc1RVRkJUU3hEUVVGRExFMUJRVTBzUlVGQlJTeEZRVUZGTEVOQlFVTXNSVUZCUlR0blFrRkRNVU1zU1VGQlNTeExRVUZMTEVkQlFVY3NTMEZCU3l4RFFVRkRMRTFCUVUwc1EwRkJReXhEUVVGRExFTkJRVU1zUTBGQlF6dG5Ra0ZGTlVJc1NVRkJTU3hWUVVGVkxFZEJRVWNzUlVGQlJTeERRVUZETzJkQ1FVTndRaXhMUVVGTExFbEJRVWtzU1VGQlNTeEpRVUZKTEV0QlFVczdiMEpCUTJ4Q0xFbEJRVWtzU1VGQlNTeExRVUZMTEZGQlFWRXNTVUZCU1N4SlFVRkpMRXRCUVVzc1VVRkJVU3hKUVVGSkxFdEJRVXNzUTBGQlF5eGpRVUZqTEVOQlFVTXNTVUZCU1N4RFFVRkRPM2RDUVVOd1JTeFZRVUZWTEVOQlFVTXNTVUZCU1N4RFFVRkRMRWRCUVVjc1MwRkJTeXhEUVVGRExFbEJRVWtzUTBGQlF5eERRVUZETzJkQ1FVVjJReXhUUVVGVExFTkJRVU1zUjBGQlJ5eERRVUZETEVsQlFVa3NUVUZCVFN4RFFVRkRMRU5CUVVNc1EwRkJReXhIUVVGRExFTkJRVU1zUlVGQlJTeEpRVUZKTEZGQlFWRXNSVUZCUlN4RlFVRkZMRWxCUVVrc1VVRkJVU3hGUVVGRkxFVkJRVVVzU1VGQlNTeERRVUZETEc5Q1FVRnZRaXhEUVVGRExFdEJRVXNzUTBGQlF5eEZRVUZGTEZWQlFWVXNRMEZCUXl4RFFVRkRMRU5CUVVNN1lVRkRha2c3VTBGRFNqdFJRVU5FTEU5QlFVOHNVMEZCVXl4RFFVRkRPMGxCUTNCQ0xFTkJRVU03U1VGSFJpdzJRa0ZCU3l4SFFVRk1MRlZCUVUwc1EwRkJVeXhGUVVGRkxFTkJRVk1zUlVGQlJTeERRVUZoTzFGQlFXSXNhMEpCUVVFc1JVRkJRU3hMUVVGaE8xRkJRM0pETEVsQlFVa3NTMEZCU3l4SFFVRkhMRU5CUVVNc1EwRkJReXhSUVVGUkxFTkJRVU1zV1VGQldTeERRVUZETEVOQlFVTXNRMEZCUXl4UlFVRlJMRU5CUVVNc1JVRkRNME1zVFVGQlRTeEhRVUZITEVOQlFVTXNRMEZCUXl4UlFVRlJMRU5CUVVNc1dVRkJXU3hEUVVGRExFTkJRVU1zUTBGQlF5eFJRVUZSTEVOQlFVTXNRMEZCUXp0UlFVTnFSQ3hKUVVGSkxGRkJRVkVzUjBGQlJ5eEpRVUZKTEZOQlFWTXNSVUZCUlN4RFFVRkRPMUZCUXk5Q0xGRkJRVkVzUTBGQlF5eEhRVUZITEVOQlFVTXNRMEZCUXl4RFFVRkRMRU5CUVVNN1VVRkRhRUlzVVVGQlVTeERRVUZETEVkQlFVY3NRMEZCUXl4RFFVRkRMRU5CUVVNc1EwRkJRenRSUVVOb1FpeEpRVUZKTEVOQlFVTXNSMEZCUnl4SlFVRkpMRTFCUVUwc1EwRkJReXhKUVVGSkxFTkJRVU1zVDBGQlR5eERRVUZETEUxQlFVMHNSVUZCUlN4TlFVRk5MRVZCUVVVc1MwRkJTeXhGUVVGRkxGRkJRVkVzUTBGQlF5eERRVUZETzFGQlEycEZMRWxCUVVrc1EwRkJReXhQUVVGUExFTkJRVU1zU1VGQlNTeERRVUZETEVOQlFVTXNRMEZCUXl4RFFVRkRPMUZCUTNKQ0xFbEJRVWtzVFVGQlRTeEhRVUZITEZWQlFVTXNRMEZCVnl4RlFVRkZMRU5CUVZNc1JVRkJSU3hEUVVGVE8xbEJRek5ETEVOQlFVTXNRMEZCUXl4TlFVRk5MRU5CUVVNc1ZVRkJReXhGUVVGRkxFVkJRVVVzVVVGQlVUdG5Ra0ZEYkVJc1JVRkJSU3hEUVVGRExFMUJRVTBzUTBGQlF5eFZRVUZCTEVOQlFVTTdiMEpCUTFBc1NVRkJTU3hIUVVGSExFZEJRV0VzUTBGQlF5eERRVUZETEVOQlFVTXNRMEZCUXl4RFFVRkRPMjlDUVVONlFpeEhRVUZITEVOQlFVTXNSMEZCUnl4RFFVRkRMRkZCUVZFc1JVRkJSU3hEUVVGRExFTkJRVU1zUTBGQlF6dHZRa0ZEY2tJc1IwRkJSeXhEUVVGRExFMUJRVTBzUTBGQlF5eFJRVUZSTEVWQlFVVXNRMEZCUXl4RFFVRkRMRU5CUVVNN2IwSkJRM2hDTEVkQlFVY3NRMEZCUXl4TlFVRk5MRU5CUVVNc1VVRkJVU3hGUVVGRkxFTkJRVU1zUTBGQlF5eERRVUZETzI5Q1FVTmlMRU5CUVVNc1EwRkJReXhEUVVGRExFTkJRVVVzUTBGQlF5eE5RVUZOTEVOQlFVTXNVVUZCVVN4RlFVRkZMRU5CUVVNc1EwRkJReXhEUVVGRE8yOUNRVU14UWl4RFFVRkRMRU5CUVVNc1EwRkJReXhEUVVGRkxFTkJRVU1zVFVGQlRTeERRVUZETEZGQlFWRXNSVUZCUlN4RFFVRkRMRU5CUVVNc1EwRkJRenRuUWtGRGVrTXNRMEZCUXl4RFFVRkRMRU5CUVVNN1dVRkRVQ3hEUVVGRExFTkJRVU1zUTBGQlF6dFJRVU5RTEVOQlFVTXNRMEZCUXp0UlFVTkdMRTFCUVUwc1EwRkJReXhOUVVGTkxFVkJRVVVzVlVGQlZTeEZRVUZGTEZWQlFWVXNRMEZCUXl4RFFVRkRPMUZCUTNaRExFMUJRVTBzUTBGQlF5eExRVUZMTEVWQlFVVXNWVUZCVlN4RlFVRkZMRlZCUVZVc1EwRkJReXhEUVVGRE8xRkJRM1JETEVsQlFVa3NRMEZCUXl4RFFVRkRMRWxCUVVrc1MwRkJTeXhEUVVGRExFdEJRVXNzUlVGQlJTeEhRVUZITEUxQlFVMHNRMEZCUXl4TFFVRkxMRVZCUVVVc1EwRkJRenRSUVVONlF5eEpRVUZKTEVOQlFVTXNTMEZCU3l4RFFVRkRMRU5CUVVNc1EwRkJReXhEUVVGRExFMUJRVTBzUTBGQlF5eERRVUZETEVOQlFVTXNRMEZCUXp0UlFVTjRRaXhKUVVGSkxFTkJRVU1zUzBGQlN5eERRVUZETEVOQlFVTXNRMEZCUXl4RFFVRkRMRTFCUVUwc1EwRkJReXhEUVVGRExFTkJRVU1zUTBGQlF6dFJRVU40UWl4SlFVRkpMRU5CUVVNc1MwRkJTeXhEUVVGRExFTkJRVU1zUTBGQlF5eERRVUZETEVkQlFVY3NRMEZCUXl4RFFVRkRMRU5CUVVNc1EwRkJRenRSUVVOeVFpeFBRVUZQTEVOQlFVTXNRMEZCUXp0SlFVTmlMRU5CUVVNN1NVRkZUeXhyUTBGQlZTeEhRVUZzUWl4VlFVRnRRaXhEUVVGaE8xRkJRV0lzYTBKQlFVRXNSVUZCUVN4TFFVRmhPMUZCVFRWQ0xFbEJRVWtzUlVGQlJTeEhRVUZITEVsQlFVa3NRMEZCUXl4TFFVRkxMRU5CUVVNc1EwRkJReXhEUVVGRExFTkJRVU1zVDBGQlR5eEZRVUZGTEVOQlFVTTdVVUZEYWtNc1NVRkJTU3hEUVVGRExFZEJRVWNzUlVGQlJTeERRVUZETEUxQlFVMHNRMEZCUXp0UlFVTnNRaXhKUVVGSkxFMUJRVTBzUjBGQlJ5eEpRVUZKTEV0QlFVc3NRMEZCUXl4RFFVRkRMRWRCUVVjc1EwRkJReXhEUVVGRExFZEJRVWNzUTBGQlF5eERRVUZETEVOQlFVTXNRMEZCUXp0UlFVTndReXhKUVVGSkxFZEJRVWNzUjBGQlJ5eERRVUZETEVOQlFVTTdVVUZEV2l4TFFVRkxMRWxCUVVrc1EwRkJReXhIUVVGSExFTkJRVU1zUlVGQlJTeEZRVUZGTEVkQlFVY3NRMEZCUXl4SFFVRkhMRU5CUVVNc1JVRkJSU3hEUVVGRExFZEJRVWNzUlVGQlJTeEZRVUZGTEVWQlFVVXNRMEZCUXl4RlFVRkZPMWxCUTNKRExFdEJRVXNzU1VGQlNTeERRVUZETEVkQlFVY3NRMEZCUXl4SFFVRkRMRU5CUVVNc1JVRkJSU3hEUVVGRExFZEJRVWNzUTBGQlF5eEZRVUZGTEVWQlFVVXNRMEZCUXl4RlFVRkZPMmRDUVVNeFFpeEpRVUZKTEVOQlFVTXNSMEZCUnl4RlFVRkZMRU5CUVVNc1EwRkJReXhEUVVGRExFVkJRVVVzUTBGQlF5eEhRVUZITEVWQlFVVXNRMEZCUXl4RFFVRkRMRU5CUVVNc1EwRkJRenRuUWtGRGVrSXNUVUZCVFN4RFFVRkRMRWRCUVVjc1EwRkJReXhIUVVGSExFVkJRVVVzUlVGQlJTeEZRVUZGTEVkQlFVY3NSVUZCUlN4TlFVRk5MRVZCUVVVc1NVRkJTU3hEUVVGRExFMUJRVTBzUTBGQlF5eERRVUZETEVWQlFVVXNRMEZCUXl4RFFVRkRMRVZCUVVVc1EwRkJReXhGUVVGRkxFTkJRVU1zUlVGQlJTeERRVUZETEVWQlFVVXNRMEZCUXl4RlFVRkZMRU5CUVVNN1owSkJRMnBGTEVkQlFVY3NSVUZCUlN4RFFVRkRPMkZCUTFRN1UwRkRTanRSUVVORUxFOUJRVThzVFVGQlRTeERRVUZETzBsQlEyeENMRU5CUVVNN1NVRkZSQ3h0UTBGQlZ5eEhRVUZZTzFGQlEwa3NTMEZCU3l4SlFVRkpMRU5CUVVNc1IwRkJSeXhEUVVGRExFVkJRVVVzUTBGQlF5eEhRVUZITEVsQlFVa3NRMEZCUXl4TFFVRkxMRU5CUVVNc1RVRkJUU3hGUVVGRkxFVkJRVVVzUTBGQlF5eEZRVUZGTzFsQlJYaERMRWxCUVVrc1NVRkJTU3hEUVVGRExFdEJRVXNzUTBGQlF5eERRVUZETEVOQlFVTXNRMEZCUXl4UFFVRlBMRVZCUVVVc1EwRkJReXhOUVVGTkxFZEJRVWNzUTBGQlF6dG5Ra0ZCUlN4VFFVRlRPMWxCUjJwRUxFbEJRVWtzUlVGQlJTeEhRVUZITEVsQlFVa3NRMEZCUXl4VlFVRlZMRU5CUVVNc1EwRkJReXhEUVVGRExFTkJRVU1zU1VGQlNTeERRVUZETEZWQlFVTXNRMEZCUXl4RlFVRkZMRU5CUVVNc1NVRkJTeXhQUVVGQkxFTkJRVU1zUTBGQlF5eE5RVUZOTEVsQlFVa3NRMEZCUXl4RFFVRkRMRTFCUVUwc1EwRkJReXhEUVVGRExFTkJRVU1zUTBGQlF5eERRVUZETEVWQlFVVXNSMEZCUnl4RFFVRkRMRU5CUVVNc1JVRkJSU3hEUVVGRExFTkJRVU1zUTBGQlF5eERRVUZETEVOQlFVTXNUVUZCVFN4SFFVRkhMRU5CUVVNc1EwRkJReXhOUVVGTkxFVkJRWGhFTEVOQlFYZEVMRU5CUVVNc1EwRkJRenRaUVVOeVJ5eEpRVUZKTEVOQlFVTXNSMEZCUnl4RlFVRkZMRU5CUVVNc1EwRkJReXhEUVVGRExFTkJRVU03V1VGRFpDeEpRVUZKTEVOQlFVTXNRMEZCUXl4TlFVRk5MRWxCUVVrc1NVRkJTU3hEUVVGRExFTkJRVU03WjBKQlFVVXNVMEZCVXp0WlFVTnFReXhKUVVGSkxFTkJRVU1zUzBGQlN5eERRVUZETEVOQlFVTXNRMEZCUXl4RFFVRkRMRVZCUVVVc1EwRkJReXhEUVVGRExFTkJRVU1zUlVGQlJTeERRVUZETEVOQlFVTXNRMEZCUXp0WlFVTjRRaXhQUVVGUExFbEJRVWtzUTBGQlF6dFRRVU5tTzBsQlEwd3NRMEZCUXp0SlFVVlBMRGhDUVVGTkxFZEJRV1FzVlVGQlpTeERRVUZUTEVWQlFVVXNRMEZCVXp0UlFVTXZRaXhKUVVGSkxFdEJRVXNzUjBGQlJ5eERRVUZETEVOQlFVTXNVVUZCVVN4RFFVRkRMRmxCUVZrc1EwRkJReXhEUVVGRExFTkJRVU1zVVVGQlVTeERRVUZETEVWQlF6TkRMRTFCUVUwc1IwRkJSeXhEUVVGRExFTkJRVU1zVVVGQlVTeERRVUZETEZsQlFWa3NRMEZCUXl4RFFVRkRMRU5CUVVNc1VVRkJVU3hEUVVGRExFTkJRVU03VVVGRGFrUXNUMEZCVHl4SlFVRkpMRU5CUVVNc1EwRkJReXhIUVVGSExFdEJRVXNzUTBGQlF5eExRVUZMTEVWQlFVVXNSMEZCUnl4TlFVRk5MRU5CUVVNc1MwRkJTeXhGUVVGRkxFTkJRVU03U1VGRGJrUXNRMEZCUXp0SlFVVkVMSGxEUVVGcFFpeEhRVUZxUWl4VlFVRnJRaXhsUVVFMFFqdFJRVUU1UXl4cFFrRmxRenRSUVdSSExFbEJRVWtzVFVGQlRTeEhRVUZITEVWQlFVVXNRMEZCUXp0UlFVTm9RaXhKUVVGSkxFbEJRVWtzUjBGQlJ5eEZRVUZGTEVOQlFVTTdVVUZEWkN4UlFVRlJMRU5CUVVNc1NVRkJTU3hEUVVGRExFdEJRVXNzUTBGQlF5eERRVUZETEVOQlFVTXNSVUZCUlN4SlFVRkpMRVZCUVVVc1RVRkJUU3hEUVVGRExFTkJRVU03VVVGRGRFTXNTVUZCU1N4RlFVRkZMRWRCUVVjc1NVRkJTU3hEUVVGRExGRkJRVkVzUlVGQlJTeERRVUZETzFGQlEzcENMRVZCUVVVc1EwRkJReXhQUVVGUExFTkJRVU1zVlVGQlFTeERRVUZETzFsQlExSXNTVUZCU1N4RFFVRkRMRWRCUVVjc1MwRkJTU3hEUVVGRExFOUJRVThzUTBGQlF5eERRVUZETEVOQlFVTXNUVUZCVFN4RFFVRkRMRU5CUVVNN1dVRkRMMElzU1VGQlNTeERRVUZETEVkQlFVY3NTMEZCU1N4RFFVRkRMRTlCUVU4c1EwRkJReXhEUVVGRExFTkJRVU1zVFVGQlRTeERRVUZETEVOQlFVTTdXVUZETDBJc1pVRkJaU3hEUVVGRExFbEJRVWtzUTBGQlF5eEpRVUZKTEZOQlFWTXNRMEZET1VJc1QwRkJUeXhEUVVGRExFTkJRVU1zUjBGQlJ5eExRVUZMTEZkQlFWY3NRMEZCUXl4RFFVRkRMRU5CUVVNc1EwRkJReXhEUVVGRExFMUJRVTBzUTBGQlF5eERRVUZETEVOQlFVTXNUVUZCVFN4RFFVRkRMRU5CUVVNc1EwRkJReXhIUVVGSExFTkJRVU1zUlVGRGRrUXNUMEZCVHl4RFFVRkRMRU5CUVVNc1IwRkJSeXhMUVVGTExGZEJRVmNzUTBGQlF5eERRVUZETEVOQlFVTXNRMEZCUXl4RFFVRkRMRTFCUVUwc1EwRkJReXhEUVVGRExFTkJRVU1zVFVGQlRTeERRVUZETEVOQlFVTXNRMEZCUXl4SFFVRkhMRU5CUVVNc1JVRkRka1FzUTBGQlF5eERRVUZETEVsQlFVa3NRMEZEVkN4RFFVRkRMRU5CUVVNN1VVRkRVQ3hEUVVGRExFTkJRVU1zUTBGQlF6dFJRVU5JTEU5QlFVOHNUVUZCVFN4RFFVRkRPMGxCUTJ4Q0xFTkJRVU03U1VGRlJDeG5RMEZCVVN4SFFVRlNPMUZCUTBrc1NVRkJTU3hGUVVGRkxFZEJRVWNzUlVGQlJTeERRVUZETzFGQlExb3NZVUZCWVN4RFFVRkRMRkZCUVZFc1EwRkJReXhKUVVGSkxFTkJRVU1zUzBGQlN5eERRVUZETEVOQlFVTXNRMEZCUXl4RlFVRkZMRVZCUVVVc1EwRkJReXhEUVVGRE8xRkJRekZETEU5QlFVOHNSVUZCUlN4RFFVRkRPMGxCUTJRc1EwRkJRenRKUVVWTkxITkNRVUZSTEVkQlFXWXNWVUZCWjBJc1QwRkJhMElzUlVGQlJTeEZRVUZsTzFGQlF5OURMRTlCUVU4c1EwRkJReXhOUVVGTkxFTkJRVU1zVlVGQlFTeERRVUZETzFsQlExb3NRMEZCUXl4RFFVRkRMRkZCUVZFc1EwRkJReXhGUVVGRkxFTkJRVU1zUTBGQlF6dFpRVU5tTEdGQlFXRXNRMEZCUXl4UlFVRlJMRU5CUVVNc1EwRkJReXhEUVVGRExGRkJRVkVzUlVGQlJTeEZRVUZGTEVOQlFVTXNRMEZCUXp0UlFVTXpReXhEUVVGRExFTkJRVU1zUTBGQlF6dEpRVU5RTEVOQlFVTTdTVUZEVEN4dlFrRkJRenRCUVVGRUxFTkJRVU1zUVVGNFNrUXNTVUYzU2tNN1FVRjRTbGtzYzBOQlFXRTdRVUV3U2pGQ0xGTkJRVk1zVVVGQlVTeERRVUZETEU5QlFXdENMRVZCUVVVc1MwRkJTeXhGUVVGRkxFMUJRVTA3U1VGREwwTXNUMEZCVHl4RFFVRkRMRTFCUVUwc1EwRkJReXhWUVVGQkxFTkJRVU03VVVGRFdpeEpRVUZKTEVOQlFVTXNRMEZCUXl4TlFVRk5MRVZCUVVVc1JVRkJSVHRaUVVOYUxFbEJRVWtzUTBGQlF5eExRVUZMTEVOQlFVTXNUVUZCVFR0blFrRkJSU3hMUVVGTExFTkJRVU1zVFVGQlRTeEhRVUZITEVWQlFVVXNRMEZCUXp0WlFVTnlReXhMUVVGTExFTkJRVU1zVFVGQlRTeERRVUZETEVsQlFVa3NRMEZCUXl4RFFVRkRMRU5CUVVNc1JVRkJSU3hEUVVGRExFTkJRVU03VTBGRE0wSTdZVUZCVFR0WlFVTklMRWxCUVVrc1EwRkJReXhIUVVGSExFdEJRVXNzUTBGQlF6dFpRVU5rTEVOQlFVTXNRMEZCUXl4SFFVRkhMRWRCUVVjc1RVRkJUU3hEUVVGRExFMUJRVTBzUTBGQlF6dFpRVU4wUWl4SlFVRkpMRU5CUVVNc1EwRkJReXhEUVVGRExGRkJRVkVzUlVGQlJTeEpRVUZKTEVOQlFVTXNRMEZCUXl4WlFVRlpMRVZCUVVVc1JVRkJSVHRuUWtGRGJrTXNRMEZCUXl4SFFVRkhMRVZCUVVVc1JVRkJSU3hGUVVGRkxFTkJRVU1zUTBGQlF5eEhRVUZITEVWQlFVVXNRMEZCUXp0blFrRkRiRUlzU1VGQlNTeERRVUZETEVOQlFVTXNXVUZCV1N4RlFVRkZPMjlDUVVWb1FpeExRVUZMTEVsQlFVa3NTVUZCU1N4SlFVRkpMRU5CUVVNc1EwRkJReXhWUVVGVk8zZENRVU42UWl4RFFVRkRMRU5CUVVNc1NVRkJTU3hEUVVGRExFZEJRVWNzUTBGQlF5eERRVUZETEZWQlFWVXNRMEZCUXl4SlFVRkpMRU5CUVVNc1EwRkJRenRuUWtGRGNrTXNTVUZCU1N4RFFVRkRMRXRCUVVzc1EwRkJReXhOUVVGTk8yOUNRVUZGTEV0QlFVc3NRMEZCUXl4TlFVRk5MRWRCUVVjc1JVRkJSU3hEUVVGRE8yZENRVU55UXl4TFFVRkxMRU5CUVVNc1RVRkJUU3hEUVVGRExFbEJRVWtzUTBGQlF5eERRVUZETEVOQlFVTXNSMEZCUnl4RFFVRkRMRU5CUVVNN1owSkJRM3BDTEUxQlFVMHNRMEZCUXl4SlFVRkpMRU5CUVVNc1EwRkJReXhEUVVGRExFTkJRVU03WVVGRGJFSTdXVUZEUkN4UlFVRlJMRU5CUVVNc1EwRkJReXhEUVVGRExGRkJRVkVzUlVGQlJTeERRVUZETEVWQlFVVXNUVUZCVFN4RFFVRkRMRU5CUVVNN1UwRkRia003U1VGRFRDeERRVUZETEVOQlFVTXNRMEZCUXp0QlFVTlFMRU5CUVVNN1FVRkZSRHRKUVVkSkxHZENRVU5YTEVWQlFWVXNSVUZEVml4UlFVRnRReXhGUVVOdVF5eFJRVUZ0UXl4RlFVTnVReXhSUVVGeFF5eEZRVU55UXl4VlFVRm5RanRSUVVob1FpeDVRa0ZCUVN4RlFVRkJMR1ZCUVhsQ0xGRkJRVkVzUlVGQlJUdFJRVU51UXl4NVFrRkJRU3hGUVVGQkxHVkJRWGxDTEZGQlFWRXNSVUZCUlR0UlFVTnVReXg1UWtGQlFTeEZRVUZCTEdWQlFUQkNMRk5CUVZNc1JVRkJSVHRSUVVoeVF5eFBRVUZGTEVkQlFVWXNSVUZCUlN4RFFVRlJPMUZCUTFZc1lVRkJVU3hIUVVGU0xGRkJRVkVzUTBGQk1rSTdVVUZEYmtNc1lVRkJVU3hIUVVGU0xGRkJRVkVzUTBGQk1rSTdVVUZEYmtNc1lVRkJVU3hIUVVGU0xGRkJRVkVzUTBGQk5rSTdVVUZEY2tNc1pVRkJWU3hIUVVGV0xGVkJRVlVzUTBGQlRUdEpRVUZKTEVOQlFVTTdTVUZGYUVNc2VVSkJRVkVzUjBGQlVpeFZRVUZUTEVWQlFXVTdVVUZCZUVJc2FVSkJUVU03VVVGTVJ5eEpRVUZKTEVOQlFVTXNVVUZCVVN4RFFVRkRMRTFCUVUwc1EwRkJReXhWUVVGRExFVkJRVVVzUlVGQlJTeFJRVUZSTzFsQlF6bENMRVZCUVVVc1EwRkJReXhOUVVGTkxFTkJRVU1zVlVGQlFTeE5RVUZOTzJkQ1FVTmFMRVZCUVVVc1EwRkJReXhKUVVGSkxFTkJRVU1zU1VGQlNTeFRRVUZUTEVOQlFVTXNTMEZCU1N4RFFVRkRMRVZCUVVVc1JVRkJSU3hOUVVGTkxFTkJRVU1zUlVGQlJTeEZRVUZGTEZGQlFWRXNRMEZCUXl4RFFVRkRMRU5CUVVNN1dVRkRla1FzUTBGQlF5eERRVUZETEVOQlFVTTdVVUZEVUN4RFFVRkRMRU5CUVVNc1EwRkJRenRKUVVOUUxFTkJRVU03U1VGRlJDeDFRa0ZCVFN4SFFVRk9PMUZCUTBrc1QwRkJUeXhKUVVGSkxFTkJRVU1zVVVGQlVTeERRVUZETEV0QlFVc3NSVUZCUlN4TFFVRkxMRU5CUVVNc1EwRkJRenRKUVVOMlF5eERRVUZETzBsQlJVUXNlVUpCUVZFc1IwRkJVanRSUVVOSkxFOUJRVThzU1VGQlNTeERRVUZETEZGQlFWRXNRMEZCUXl4TFFVRkxMRVZCUVVVc1MwRkJTeXhEUVVGRExFbEJRVWtzU1VGQlNTeERRVUZETEZGQlFWRXNRMEZCUXl4TFFVRkxMRVZCUVVVc1MwRkJTeXhEUVVGRExFTkJRVU03U1VGRGRFVXNRMEZCUXp0SlFVVkVMRFpDUVVGWkxFZEJRVm83VVVGRFNTeFBRVUZQTEU5QlFVOHNTVUZCU1N4RFFVRkRMRlZCUVZVc1MwRkJTeXhYUVVGWExFTkJRVU03U1VGRGJFUXNRMEZCUXp0SlFVTk1MR0ZCUVVNN1FVRkJSQ3hEUVVGRExFRkJOMEpFTEVsQk5rSkRPMEZCTjBKWkxIZENRVUZOTzBGQkswSnVRaXhUUVVGVExGbEJRVmtzUTBGQlF5eERRVUZOTEVWQlFVVXNRMEZCVFR0SlFVTm9ReXhKUVVGSkxFTkJRVU1zUjBGQlJ5eEZRVUZGTEVOQlFVTTdTVUZEV0N4TFFVRkxMRWxCUVVrc1EwRkJReXhKUVVGSkxFTkJRVU03VVVGQlJTeEpRVUZKTEVOQlFVTXNTVUZCU1N4RFFVRkRPMWxCUVVVc1EwRkJReXhEUVVGRExFTkJRVU1zUTBGQlF5eEhRVUZITEVOQlFVTXNRMEZCUXl4RFFVRkRMRU5CUVVNc1EwRkJRenRKUVVONlF5eFBRVUZQTEVOQlFVTXNRMEZCUXp0QlFVTmlMRU5CUVVNN1FVRkZSRHRKUVVGQk8xRkJRMGtzVlVGQlN5eEhRVUZSTEVWQlFVVXNRMEZCUXp0SlFXdERjRUlzUTBGQlF6dEpRV3BEUnl4NVFrRkJTeXhIUVVGTU8xRkJRMGtzVDBGQlR5eE5RVUZOTEVOQlFVTXNTVUZCU1N4RFFVRkRMRWxCUVVrc1EwRkJReXhMUVVGTExFTkJRVU1zUTBGQlF5eE5RVUZOTEVOQlFVTTdTVUZETVVNc1EwRkJRenRKUVVORUxHZERRVUZaTEVkQlFWb3NWVUZCWVN4TFFVRm5RanRSUVVONlFpeEpRVUZKTEUxQlFVMHNSMEZCUnl4SlFVRkpMRk5CUVZNc1JVRkJSU3hEUVVGRE8xRkJRemRDTEUxQlFVMHNRMEZCUXl4TFFVRkxMRWRCUVVjc1dVRkJXU3hEUVVGRExFbEJRVWtzUTBGQlF5eExRVUZMTEVWQlFVVXNTMEZCU3l4RFFVRkRMRXRCUVVzc1EwRkJReXhEUVVGRE8xRkJRM0pFTEU5QlFVOHNUVUZCVFN4RFFVRkRPMGxCUTJ4Q0xFTkJRVU03U1VGRFJDeHhRMEZCYVVJc1IwRkJha0lzVlVGQmEwSXNTMEZCWjBJN1VVRkRPVUlzVDBGQlR5eEpRVUZKTEVOQlFVTXNXVUZCV1N4RFFVRkRMRXRCUVVzc1EwRkJReXhEUVVGRExFdEJRVXNzUlVGQlJTeERRVUZETzBsQlF6VkRMRU5CUVVNN1NVRkRSQ3cwUWtGQlVTeEhRVUZTTEZWQlFWTXNSVUZCVlR0UlFVTm1MRTlCUVU4c1JVRkJSU3hKUVVGSkxFbEJRVWtzUTBGQlF5eExRVUZMTEVOQlFVTTdTVUZETlVJc1EwRkJRenRKUVVORUxIVkNRVUZITEVkQlFVZ3NWVUZCU1N4RFFVRlRPMUZCUTFRc1NVRkJTU3hEUVVGRExFdEJRVXNzUTBGQlF5eERRVUZETEVOQlFVTXNSVUZCUlN4RFFVRkRMRWRCUVVjc1EwRkJReXhEUVVGRE8wbEJRM3BDTEVOQlFVTTdTVUZEUkN3d1FrRkJUU3hIUVVGT0xGVkJRVThzUTBGQlV6dFJRVU5hTEU5QlFVOHNTVUZCU1N4RFFVRkRMRXRCUVVzc1EwRkJReXhEUVVGRExFTkJRVU1zUlVGQlJTeERRVUZETEVOQlFVTTdTVUZETlVJc1EwRkJRenRKUVVORUxEQkNRVUZOTEVkQlFVNHNWVUZCVHl4RFFVRnpRanRSUVVONlFpeExRVUZMTEVsQlFVa3NSMEZCUnl4SlFVRkpMRWxCUVVrc1EwRkJReXhMUVVGTExFVkJRVVU3V1VGRGVFSXNRMEZCUXl4RFFVRkRMRWxCUVVrc1EwRkJReXhMUVVGTExFTkJRVU1zUjBGQlJ5eERRVUZETEVOQlFVTXNRMEZCUXp0VFFVTjBRanRKUVVOTUxFTkJRVU03U1VGRFJDd3lRa0ZCVHl4SFFVRlFPMUZCUTBrc1NVRkJTU3hGUVVGRkxFZEJRVWNzUlVGQlJTeERRVUZETzFGQlExb3NTVUZCU1N4RFFVRkRMRTFCUVUwc1EwRkJReXhWUVVGQkxFTkJRVU03V1VGRFZDeEpRVUZKTEVOQlFVTXNRMEZCUXl4RFFVRkRMRmxCUVZrc1JVRkJSVHRuUWtGRGFrSXNSVUZCUlN4RFFVRkRMRWxCUVVrc1EwRkJReXhEUVVGRExFTkJRVU1zUTBGQlF6dFJRVU51UWl4RFFVRkRMRU5CUVVNc1EwRkJRenRSUVVOSUxFOUJRVThzUlVGQlJTeERRVUZETzBsQlEyUXNRMEZCUXp0SlFVTk1MR2RDUVVGRE8wRkJRVVFzUTBGQlF5eEJRVzVEUkN4SlFXMURRenRCUVc1RFdTdzRRa0ZCVXp0QlFYRkRkRUk3U1VGQlFUdFJRVU5KTEZOQlFVa3NSMEZCVVN4RlFVRkZMRU5CUVVNN1VVRkRaaXhOUVVGRExFZEJRVmNzUTBGQlF5eERRVUZETzBsQlowUnNRaXhEUVVGRE8wbEJMME5ITEhkQ1FVRkxMRWRCUVV3N1VVRkRTU3hQUVVGUExFbEJRVWtzUTBGQlF5eERRVUZETEVOQlFVTTdTVUZEYkVJc1EwRkJRenRKUVVORUxESkNRVUZSTEVkQlFWSXNWVUZCVXl4RlFVRlZPMUZCUTJZc1NVRkJTU3hOUVVGTkxFZEJRVWNzUzBGQlN5eERRVUZETzFGQlEyNUNMRWxCUVVrc1EwRkJReXhoUVVGaExFTkJRVU1zVlVGQlFTeERRVUZETzFsQlEyaENMRWxCUVVrc1EwRkJReXhOUVVGTkxFbEJRVWtzUTBGQlF5eERRVUZETEVWQlFVVXNTVUZCU1N4RlFVRkZMRVZCUVVVN1owSkJRM1pDTEUxQlFVMHNSMEZCUnl4SlFVRkpMRU5CUVVNN1lVRkRha0k3VVVGRFRDeERRVUZETEVOQlFVTXNRMEZCUXp0UlFVTklMRTlCUVU4c1RVRkJUU3hEUVVGRE8wbEJRMnhDTEVOQlFVTTdTVUZEUkN4elFrRkJSeXhIUVVGSUxGVkJRVWtzVVVGQlowSXNSVUZCUlN4RFFVRlRPMUZCUXpOQ0xFbEJRVWtzUTBGQlF5eEhRVUZqTEZGQlFWRXNTVUZCU1N4SlFVRkpMRU5CUVVNc1NVRkJTU3hEUVVGRExFTkJRVU1zUTBGQlF5eEpRVUZKTEVOQlFVTXNTVUZCU1N4RFFVRkRMRkZCUVZFc1EwRkJReXhEUVVGRExFTkJRVU1zUTBGQlF5eEpRVUZKTEVOQlFVTXNTVUZCU1N4RFFVRkRMRkZCUVZFc1EwRkJReXhIUVVGSExFbEJRVWtzVTBGQlV5eEZRVUZGTEVOQlFVTTdVVUZEZGtjc1EwRkJReXhEUVVGRExFZEJRVWNzUTBGQlF5eERRVUZETEVOQlFVTXNRMEZCUXp0UlFVTlVMRVZCUVVVc1NVRkJTU3hEUVVGRExFTkJRVU1zUTBGQlF6dEpRVU5pTEVOQlFVTTdTVUZEUkN4NVFrRkJUU3hIUVVGT0xGVkJRVThzVVVGQlowSXNSVUZCUlN4RFFVRlRPMUZCUXpsQ0xFbEJRVWtzUlVGQlJTeEhRVUZqTEVsQlFVa3NRMEZCUXl4SlFVRkpMRU5CUVVNc1VVRkJVU3hEUVVGRExFTkJRVU03VVVGRGVFTXNSVUZCUlN4RFFVRkRMRTFCUVUwc1EwRkJReXhEUVVGRExFTkJRVU1zUTBGQlF6dFJRVU5pTEVsQlFVa3NSVUZCUlN4RFFVRkRMRXRCUVVzc1JVRkJSU3hMUVVGTExFTkJRVU1zUlVGQlJUdFpRVU5zUWl4UFFVRlBMRWxCUVVrc1EwRkJReXhKUVVGSkxFTkJRVU1zVVVGQlVTeERRVUZETEVOQlFVTTdVMEZET1VJN1VVRkRSQ3hGUVVGRkxFbEJRVWtzUTBGQlF5eERRVUZETEVOQlFVTTdTVUZEWWl4RFFVRkRPMGxCUTBRc2VVSkJRVTBzUjBGQlRpeFZRVUZQTEVOQlFUUkRPMUZCUXk5RExFdEJRVXNzU1VGQlNTeFJRVUZSTEVsQlFVa3NTVUZCU1N4RFFVRkRMRWxCUVVrc1JVRkJSVHRaUVVNMVFpeERRVUZETEVOQlFWa3NTVUZCU1N4RFFVRkRMRWxCUVVrc1EwRkJReXhSUVVGUkxFTkJRVU1zUlVGQlJTeE5RVUZOTEVOQlFVTXNVVUZCVVN4RFFVRkRMRU5CUVVNc1EwRkJRenRUUVVOMlJEdEpRVU5NTEVOQlFVTTdTVUZEUkN4blEwRkJZU3hIUVVGaUxGVkJRV01zUTBGQmMwSTdVVUZEYUVNc1NVRkJTU3hEUVVGRExFMUJRVTBzUTBGQlF5eFZRVUZETEVWQlFVVXNSVUZCUlN4RlFVRkZMRWxCUVVzc1QwRkJRU3hGUVVGRkxFTkJRVU1zVFVGQlRTeERRVUZETEVOQlFVTXNRMEZCUXl4RlFVRmFMRU5CUVZrc1EwRkJReXhEUVVGRE8wbEJRekZETEVOQlFVTTdTVUZEUkN3clFrRkJXU3hIUVVGYUxGVkJRV0VzUzBGQlpUdFJRVU40UWl4SlFVRkpMRTFCUVUwc1IwRkJZU3hKUVVGSkxGRkJRVkVzUlVGQlJTeERRVUZETzFGQlEzUkRMRWxCUVVrc1EwRkJReXhOUVVGTkxFTkJRVU1zVlVGQlF5eEZRVUZGTEVWQlFVVXNSVUZCUlR0WlFVTm1MRWxCUVVrc1JVRkJSU3hKUVVGSkxFdEJRVXNzUTBGQlF5eEpRVUZKTEVWQlFVVTdaMEpCUTJ4Q0xFbEJRVWtzUTBGQlF5eEhRVUZITEVWQlFVVXNRMEZCUXl4WlFVRlpMRU5CUVVNc1MwRkJTeXhEUVVGRExFbEJRVWtzUTBGQlF5eEZRVUZGTEVOQlFVTXNRMEZCUXl4RlFVTnVReXhEUVVGRExFZEJRVWNzUTBGQlF5eERRVUZETEV0QlFVc3NSVUZCUlN4RFFVRkRPMmRDUVVOc1FpeEpRVUZKTEVOQlFVTXNSMEZCUnl4RFFVRkRMRVZCUVVVN2IwSkJRMUFzVFVGQlRTeERRVUZETEVsQlFVa3NRMEZCUXl4RlFVRkZMRU5CUVVNc1IwRkJSeXhEUVVGRExFTkJRVU03YjBKQlEzQkNMRTFCUVUwc1EwRkJReXhEUVVGRExFbEJRVWtzUTBGQlF5eERRVUZETzJsQ1FVTnFRanRoUVVOS08xRkJRMHdzUTBGQlF5eERRVUZETEVOQlFVTTdVVUZEU0N4UFFVRlBMRTFCUVUwc1EwRkJRenRKUVVOc1FpeERRVUZETzBsQlEwd3NaVUZCUXp0QlFVRkVMRU5CUVVNc1FVRnNSRVFzU1VGclJFTTdRVUZzUkZrc05FSkJRVkU3UVVGdlJISkNMRk5CUVZNc2FVSkJRV2xDTEVOQlFVTXNRMEZCVFN4RlFVRkZMRU5CUVUwN1NVRkRja01zVDBGQlR5eE5RVUZOTEVOQlFVTXNTVUZCU1N4RFFVRkRMRmxCUVZrc1EwRkJReXhEUVVGRExFVkJRVVVzUTBGQlF5eERRVUZETEVOQlFVTXNRMEZCUXl4TlFVRk5MRU5CUVVFN1FVRkRha1FzUTBGQlF6dEJRVVZFTEZOQlFXZENMRk5CUVZNc1EwRkJUeXhMUVVGWkxFVkJRVVVzUzBGQllTeEZRVUZGTEVWQlFUQkNMRVZCUVVVc1UwRkJhVUk3U1VGRGRFY3NTVUZCU1N4RFFVRkRMRWRCUVVjc1MwRkJTeXhEUVVGRExFMUJRVTBzUlVGRGFFSXNRMEZCUXl4SFFVRkhMRWxCUVVrc1lVRkJZU3hEUVVGRExFTkJRVU1zUlVGQlJTeExRVUZMTEVWQlFVVXNSVUZCUlN4RlFVRkZMRk5CUVZNc1EwRkJReXhEUVVGRE8wbEJRMjVFTEU5QlFVOHNRMEZCUXl4RFFVRkRMRmRCUVZjc1JVRkJSVHRSUVVGRExFTkJRVU03U1VGRGVFSXNTVUZCU1N4VlFVRlZMRWRCUVdkQ0xFVkJRVVVzUTBGQlF6dEpRVU5xUXl4SlFVRkpMRU5CUVVNc1IwRkJSeXhEUVVGRExFTkJRVU1zYVVKQlFXbENMRU5CUVVNc1ZVRkJWU3hEUVVGRExFTkJRVU03U1VGRGVFTXNWVUZCVlN4RFFVRkRMRTlCUVU4c1EwRkJReXhWUVVGVkxFTkJRVU03VVVGRE1VSXNTVUZCU1N4RFFVRkRMRWRCUVVjc1ZVRkJReXhIUVVGSE8xbEJRMUlzU1VGQlNTeERRVUZETEVkQlFVY3NRMEZCUXl4RFFVRkRMRWRCUVVjc1EwRkJReXhEUVVGRE8xbEJRMllzU1VGQlNTeFBRVUZQTEVOQlFVTXNTVUZCU1N4UlFVRlJPMmRDUVVGRkxFTkJRVU1zUTBGQlF5eEhRVUZITEVOQlFVTXNSMEZCUnl4TFFVRkxMRU5CUVVNc1EwRkJReXhEUVVGRExFTkJRVU03VVVGRGFFUXNRMEZCUXl4RFFVRkRPMUZCUTBZc1EwRkJReXhEUVVGRExGRkJRVkVzUTBGQlF5eERRVUZETzFGQlExb3NRMEZCUXl4RFFVRkRMRkZCUVZFc1EwRkJReXhEUVVGRE8wbEJRMmhDTEVOQlFVTXNRMEZCUXl4RFFVRkRPMGxCUTBnc1QwRkJUeXhGUVVGRkxFMUJRVTBzUlVGQlJTeERRVUZETEVWQlFVVXNWVUZCVlN4RlFVRkZMRlZCUVZVc1JVRkJSU3hEUVVGRE8wRkJRMnBFTEVOQlFVTTdRVUZtUkN3NFFrRmxReUo5IiwiXCJ1c2Ugc3RyaWN0XCI7XG5PYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgXCJfX2VzTW9kdWxlXCIsIHsgdmFsdWU6IHRydWUgfSk7XG52YXIgUGFpcmluZ0hlYXAgPSAoZnVuY3Rpb24gKCkge1xuICAgIGZ1bmN0aW9uIFBhaXJpbmdIZWFwKGVsZW0pIHtcbiAgICAgICAgdGhpcy5lbGVtID0gZWxlbTtcbiAgICAgICAgdGhpcy5zdWJoZWFwcyA9IFtdO1xuICAgIH1cbiAgICBQYWlyaW5nSGVhcC5wcm90b3R5cGUudG9TdHJpbmcgPSBmdW5jdGlvbiAoc2VsZWN0b3IpIHtcbiAgICAgICAgdmFyIHN0ciA9IFwiXCIsIG5lZWRDb21tYSA9IGZhbHNlO1xuICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IHRoaXMuc3ViaGVhcHMubGVuZ3RoOyArK2kpIHtcbiAgICAgICAgICAgIHZhciBzdWJoZWFwID0gdGhpcy5zdWJoZWFwc1tpXTtcbiAgICAgICAgICAgIGlmICghc3ViaGVhcC5lbGVtKSB7XG4gICAgICAgICAgICAgICAgbmVlZENvbW1hID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAobmVlZENvbW1hKSB7XG4gICAgICAgICAgICAgICAgc3RyID0gc3RyICsgXCIsXCI7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBzdHIgPSBzdHIgKyBzdWJoZWFwLnRvU3RyaW5nKHNlbGVjdG9yKTtcbiAgICAgICAgICAgIG5lZWRDb21tYSA9IHRydWU7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHN0ciAhPT0gXCJcIikge1xuICAgICAgICAgICAgc3RyID0gXCIoXCIgKyBzdHIgKyBcIilcIjtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gKHRoaXMuZWxlbSA/IHNlbGVjdG9yKHRoaXMuZWxlbSkgOiBcIlwiKSArIHN0cjtcbiAgICB9O1xuICAgIFBhaXJpbmdIZWFwLnByb3RvdHlwZS5mb3JFYWNoID0gZnVuY3Rpb24gKGYpIHtcbiAgICAgICAgaWYgKCF0aGlzLmVtcHR5KCkpIHtcbiAgICAgICAgICAgIGYodGhpcy5lbGVtLCB0aGlzKTtcbiAgICAgICAgICAgIHRoaXMuc3ViaGVhcHMuZm9yRWFjaChmdW5jdGlvbiAocykgeyByZXR1cm4gcy5mb3JFYWNoKGYpOyB9KTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgUGFpcmluZ0hlYXAucHJvdG90eXBlLmNvdW50ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5lbXB0eSgpID8gMCA6IDEgKyB0aGlzLnN1YmhlYXBzLnJlZHVjZShmdW5jdGlvbiAobiwgaCkge1xuICAgICAgICAgICAgcmV0dXJuIG4gKyBoLmNvdW50KCk7XG4gICAgICAgIH0sIDApO1xuICAgIH07XG4gICAgUGFpcmluZ0hlYXAucHJvdG90eXBlLm1pbiA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuZWxlbTtcbiAgICB9O1xuICAgIFBhaXJpbmdIZWFwLnByb3RvdHlwZS5lbXB0eSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuZWxlbSA9PSBudWxsO1xuICAgIH07XG4gICAgUGFpcmluZ0hlYXAucHJvdG90eXBlLmNvbnRhaW5zID0gZnVuY3Rpb24gKGgpIHtcbiAgICAgICAgaWYgKHRoaXMgPT09IGgpXG4gICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCB0aGlzLnN1YmhlYXBzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICBpZiAodGhpcy5zdWJoZWFwc1tpXS5jb250YWlucyhoKSlcbiAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgfTtcbiAgICBQYWlyaW5nSGVhcC5wcm90b3R5cGUuaXNIZWFwID0gZnVuY3Rpb24gKGxlc3NUaGFuKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgICAgIHJldHVybiB0aGlzLnN1YmhlYXBzLmV2ZXJ5KGZ1bmN0aW9uIChoKSB7IHJldHVybiBsZXNzVGhhbihfdGhpcy5lbGVtLCBoLmVsZW0pICYmIGguaXNIZWFwKGxlc3NUaGFuKTsgfSk7XG4gICAgfTtcbiAgICBQYWlyaW5nSGVhcC5wcm90b3R5cGUuaW5zZXJ0ID0gZnVuY3Rpb24gKG9iaiwgbGVzc1RoYW4pIHtcbiAgICAgICAgcmV0dXJuIHRoaXMubWVyZ2UobmV3IFBhaXJpbmdIZWFwKG9iaiksIGxlc3NUaGFuKTtcbiAgICB9O1xuICAgIFBhaXJpbmdIZWFwLnByb3RvdHlwZS5tZXJnZSA9IGZ1bmN0aW9uIChoZWFwMiwgbGVzc1RoYW4pIHtcbiAgICAgICAgaWYgKHRoaXMuZW1wdHkoKSlcbiAgICAgICAgICAgIHJldHVybiBoZWFwMjtcbiAgICAgICAgZWxzZSBpZiAoaGVhcDIuZW1wdHkoKSlcbiAgICAgICAgICAgIHJldHVybiB0aGlzO1xuICAgICAgICBlbHNlIGlmIChsZXNzVGhhbih0aGlzLmVsZW0sIGhlYXAyLmVsZW0pKSB7XG4gICAgICAgICAgICB0aGlzLnN1YmhlYXBzLnB1c2goaGVhcDIpO1xuICAgICAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICBoZWFwMi5zdWJoZWFwcy5wdXNoKHRoaXMpO1xuICAgICAgICAgICAgcmV0dXJuIGhlYXAyO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBQYWlyaW5nSGVhcC5wcm90b3R5cGUucmVtb3ZlTWluID0gZnVuY3Rpb24gKGxlc3NUaGFuKSB7XG4gICAgICAgIGlmICh0aGlzLmVtcHR5KCkpXG4gICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgZWxzZVxuICAgICAgICAgICAgcmV0dXJuIHRoaXMubWVyZ2VQYWlycyhsZXNzVGhhbik7XG4gICAgfTtcbiAgICBQYWlyaW5nSGVhcC5wcm90b3R5cGUubWVyZ2VQYWlycyA9IGZ1bmN0aW9uIChsZXNzVGhhbikge1xuICAgICAgICBpZiAodGhpcy5zdWJoZWFwcy5sZW5ndGggPT0gMClcbiAgICAgICAgICAgIHJldHVybiBuZXcgUGFpcmluZ0hlYXAobnVsbCk7XG4gICAgICAgIGVsc2UgaWYgKHRoaXMuc3ViaGVhcHMubGVuZ3RoID09IDEpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLnN1YmhlYXBzWzBdO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgdmFyIGZpcnN0UGFpciA9IHRoaXMuc3ViaGVhcHMucG9wKCkubWVyZ2UodGhpcy5zdWJoZWFwcy5wb3AoKSwgbGVzc1RoYW4pO1xuICAgICAgICAgICAgdmFyIHJlbWFpbmluZyA9IHRoaXMubWVyZ2VQYWlycyhsZXNzVGhhbik7XG4gICAgICAgICAgICByZXR1cm4gZmlyc3RQYWlyLm1lcmdlKHJlbWFpbmluZywgbGVzc1RoYW4pO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBQYWlyaW5nSGVhcC5wcm90b3R5cGUuZGVjcmVhc2VLZXkgPSBmdW5jdGlvbiAoc3ViaGVhcCwgbmV3VmFsdWUsIHNldEhlYXBOb2RlLCBsZXNzVGhhbikge1xuICAgICAgICB2YXIgbmV3SGVhcCA9IHN1YmhlYXAucmVtb3ZlTWluKGxlc3NUaGFuKTtcbiAgICAgICAgc3ViaGVhcC5lbGVtID0gbmV3SGVhcC5lbGVtO1xuICAgICAgICBzdWJoZWFwLnN1YmhlYXBzID0gbmV3SGVhcC5zdWJoZWFwcztcbiAgICAgICAgaWYgKHNldEhlYXBOb2RlICE9PSBudWxsICYmIG5ld0hlYXAuZWxlbSAhPT0gbnVsbCkge1xuICAgICAgICAgICAgc2V0SGVhcE5vZGUoc3ViaGVhcC5lbGVtLCBzdWJoZWFwKTtcbiAgICAgICAgfVxuICAgICAgICB2YXIgcGFpcmluZ05vZGUgPSBuZXcgUGFpcmluZ0hlYXAobmV3VmFsdWUpO1xuICAgICAgICBpZiAoc2V0SGVhcE5vZGUgIT09IG51bGwpIHtcbiAgICAgICAgICAgIHNldEhlYXBOb2RlKG5ld1ZhbHVlLCBwYWlyaW5nTm9kZSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRoaXMubWVyZ2UocGFpcmluZ05vZGUsIGxlc3NUaGFuKTtcbiAgICB9O1xuICAgIHJldHVybiBQYWlyaW5nSGVhcDtcbn0oKSk7XG5leHBvcnRzLlBhaXJpbmdIZWFwID0gUGFpcmluZ0hlYXA7XG52YXIgUHJpb3JpdHlRdWV1ZSA9IChmdW5jdGlvbiAoKSB7XG4gICAgZnVuY3Rpb24gUHJpb3JpdHlRdWV1ZShsZXNzVGhhbikge1xuICAgICAgICB0aGlzLmxlc3NUaGFuID0gbGVzc1RoYW47XG4gICAgfVxuICAgIFByaW9yaXR5UXVldWUucHJvdG90eXBlLnRvcCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgaWYgKHRoaXMuZW1wdHkoKSkge1xuICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRoaXMucm9vdC5lbGVtO1xuICAgIH07XG4gICAgUHJpb3JpdHlRdWV1ZS5wcm90b3R5cGUucHVzaCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIGFyZ3MgPSBbXTtcbiAgICAgICAgZm9yICh2YXIgX2kgPSAwOyBfaSA8IGFyZ3VtZW50cy5sZW5ndGg7IF9pKyspIHtcbiAgICAgICAgICAgIGFyZ3NbX2ldID0gYXJndW1lbnRzW19pXTtcbiAgICAgICAgfVxuICAgICAgICB2YXIgcGFpcmluZ05vZGU7XG4gICAgICAgIGZvciAodmFyIGkgPSAwLCBhcmc7IGFyZyA9IGFyZ3NbaV07ICsraSkge1xuICAgICAgICAgICAgcGFpcmluZ05vZGUgPSBuZXcgUGFpcmluZ0hlYXAoYXJnKTtcbiAgICAgICAgICAgIHRoaXMucm9vdCA9IHRoaXMuZW1wdHkoKSA/XG4gICAgICAgICAgICAgICAgcGFpcmluZ05vZGUgOiB0aGlzLnJvb3QubWVyZ2UocGFpcmluZ05vZGUsIHRoaXMubGVzc1RoYW4pO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBwYWlyaW5nTm9kZTtcbiAgICB9O1xuICAgIFByaW9yaXR5UXVldWUucHJvdG90eXBlLmVtcHR5ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gIXRoaXMucm9vdCB8fCAhdGhpcy5yb290LmVsZW07XG4gICAgfTtcbiAgICBQcmlvcml0eVF1ZXVlLnByb3RvdHlwZS5pc0hlYXAgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLnJvb3QuaXNIZWFwKHRoaXMubGVzc1RoYW4pO1xuICAgIH07XG4gICAgUHJpb3JpdHlRdWV1ZS5wcm90b3R5cGUuZm9yRWFjaCA9IGZ1bmN0aW9uIChmKSB7XG4gICAgICAgIHRoaXMucm9vdC5mb3JFYWNoKGYpO1xuICAgIH07XG4gICAgUHJpb3JpdHlRdWV1ZS5wcm90b3R5cGUucG9wID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBpZiAodGhpcy5lbXB0eSgpKSB7XG4gICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgfVxuICAgICAgICB2YXIgb2JqID0gdGhpcy5yb290Lm1pbigpO1xuICAgICAgICB0aGlzLnJvb3QgPSB0aGlzLnJvb3QucmVtb3ZlTWluKHRoaXMubGVzc1RoYW4pO1xuICAgICAgICByZXR1cm4gb2JqO1xuICAgIH07XG4gICAgUHJpb3JpdHlRdWV1ZS5wcm90b3R5cGUucmVkdWNlS2V5ID0gZnVuY3Rpb24gKGhlYXBOb2RlLCBuZXdLZXksIHNldEhlYXBOb2RlKSB7XG4gICAgICAgIGlmIChzZXRIZWFwTm9kZSA9PT0gdm9pZCAwKSB7IHNldEhlYXBOb2RlID0gbnVsbDsgfVxuICAgICAgICB0aGlzLnJvb3QgPSB0aGlzLnJvb3QuZGVjcmVhc2VLZXkoaGVhcE5vZGUsIG5ld0tleSwgc2V0SGVhcE5vZGUsIHRoaXMubGVzc1RoYW4pO1xuICAgIH07XG4gICAgUHJpb3JpdHlRdWV1ZS5wcm90b3R5cGUudG9TdHJpbmcgPSBmdW5jdGlvbiAoc2VsZWN0b3IpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMucm9vdC50b1N0cmluZyhzZWxlY3Rvcik7XG4gICAgfTtcbiAgICBQcmlvcml0eVF1ZXVlLnByb3RvdHlwZS5jb3VudCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMucm9vdC5jb3VudCgpO1xuICAgIH07XG4gICAgcmV0dXJuIFByaW9yaXR5UXVldWU7XG59KCkpO1xuZXhwb3J0cy5Qcmlvcml0eVF1ZXVlID0gUHJpb3JpdHlRdWV1ZTtcbi8vIyBzb3VyY2VNYXBwaW5nVVJMPWRhdGE6YXBwbGljYXRpb24vanNvbjtiYXNlNjQsZXlKMlpYSnphVzl1SWpvekxDSm1hV3hsSWpvaWNIRjFaWFZsTG1weklpd2ljMjkxY21ObFVtOXZkQ0k2SWlJc0luTnZkWEpqWlhNaU9sc2lMaTR2TGk0dlYyVmlRMjlzWVM5emNtTXZjSEYxWlhWbExuUnpJbDBzSW01aGJXVnpJanBiWFN3aWJXRndjR2x1WjNNaU9pSTdPMEZCUTBFN1NVRkpTU3h4UWtGQmJVSXNTVUZCVHp0UlFVRlFMRk5CUVVrc1IwRkJTaXhKUVVGSkxFTkJRVWM3VVVGRGRFSXNTVUZCU1N4RFFVRkRMRkZCUVZFc1IwRkJSeXhGUVVGRkxFTkJRVU03U1VGRGRrSXNRMEZCUXp0SlFVVk5MRGhDUVVGUkxFZEJRV1lzVlVGQlowSXNVVUZCVVR0UlFVTndRaXhKUVVGSkxFZEJRVWNzUjBGQlJ5eEZRVUZGTEVWQlFVVXNVMEZCVXl4SFFVRkhMRXRCUVVzc1EwRkJRenRSUVVOb1F5eExRVUZMTEVsQlFVa3NRMEZCUXl4SFFVRkhMRU5CUVVNc1JVRkJSU3hEUVVGRExFZEJRVWNzU1VGQlNTeERRVUZETEZGQlFWRXNRMEZCUXl4TlFVRk5MRVZCUVVVc1JVRkJSU3hEUVVGRExFVkJRVVU3V1VGRE0wTXNTVUZCU1N4UFFVRlBMRWRCUVcxQ0xFbEJRVWtzUTBGQlF5eFJRVUZSTEVOQlFVTXNRMEZCUXl4RFFVRkRMRU5CUVVNN1dVRkRMME1zU1VGQlNTeERRVUZETEU5QlFVOHNRMEZCUXl4SlFVRkpMRVZCUVVVN1owSkJRMllzVTBGQlV5eEhRVUZITEV0QlFVc3NRMEZCUXp0blFrRkRiRUlzVTBGQlV6dGhRVU5hTzFsQlEwUXNTVUZCU1N4VFFVRlRMRVZCUVVVN1owSkJRMWdzUjBGQlJ5eEhRVUZITEVkQlFVY3NSMEZCUnl4SFFVRkhMRU5CUVVNN1lVRkRia0k3V1VGRFJDeEhRVUZITEVkQlFVY3NSMEZCUnl4SFFVRkhMRTlCUVU4c1EwRkJReXhSUVVGUkxFTkJRVU1zVVVGQlVTeERRVUZETEVOQlFVTTdXVUZEZGtNc1UwRkJVeXhIUVVGSExFbEJRVWtzUTBGQlF6dFRRVU53UWp0UlFVTkVMRWxCUVVrc1IwRkJSeXhMUVVGTExFVkJRVVVzUlVGQlJUdFpRVU5hTEVkQlFVY3NSMEZCUnl4SFFVRkhMRWRCUVVjc1IwRkJSeXhIUVVGSExFZEJRVWNzUTBGQlF6dFRRVU42UWp0UlFVTkVMRTlCUVU4c1EwRkJReXhKUVVGSkxFTkJRVU1zU1VGQlNTeERRVUZETEVOQlFVTXNRMEZCUXl4UlFVRlJMRU5CUVVNc1NVRkJTU3hEUVVGRExFbEJRVWtzUTBGQlF5eERRVUZETEVOQlFVTXNRMEZCUXl4RlFVRkZMRU5CUVVNc1IwRkJSeXhIUVVGSExFTkJRVU03U1VGRGVFUXNRMEZCUXp0SlFVVk5MRFpDUVVGUExFZEJRV1FzVlVGQlpTeERRVUZETzFGQlExb3NTVUZCU1N4RFFVRkRMRWxCUVVrc1EwRkJReXhMUVVGTExFVkJRVVVzUlVGQlJUdFpRVU5tTEVOQlFVTXNRMEZCUXl4SlFVRkpMRU5CUVVNc1NVRkJTU3hGUVVGRkxFbEJRVWtzUTBGQlF5eERRVUZETzFsQlEyNUNMRWxCUVVrc1EwRkJReXhSUVVGUkxFTkJRVU1zVDBGQlR5eERRVUZETEZWQlFVRXNRMEZCUXl4SlFVRkpMRTlCUVVFc1EwRkJReXhEUVVGRExFOUJRVThzUTBGQlF5eERRVUZETEVOQlFVTXNSVUZCV2l4RFFVRlpMRU5CUVVNc1EwRkJRenRUUVVNMVF6dEpRVU5NTEVOQlFVTTdTVUZGVFN3eVFrRkJTeXhIUVVGYU8xRkJRMGtzVDBGQlR5eEpRVUZKTEVOQlFVTXNTMEZCU3l4RlFVRkZMRU5CUVVNc1EwRkJReXhEUVVGRExFTkJRVU1zUTBGQlF5eERRVUZETEVOQlFVTXNRMEZCUXl4SFFVRkhMRWxCUVVrc1EwRkJReXhSUVVGUkxFTkJRVU1zVFVGQlRTeERRVUZETEZWQlFVTXNRMEZCVXl4RlFVRkZMRU5CUVdsQ08xbEJRelZGTEU5QlFVOHNRMEZCUXl4SFFVRkhMRU5CUVVNc1EwRkJReXhMUVVGTExFVkJRVVVzUTBGQlF6dFJRVU42UWl4RFFVRkRMRVZCUVVVc1EwRkJReXhEUVVGRExFTkJRVU03U1VGRFZpeERRVUZETzBsQlJVMHNlVUpCUVVjc1IwRkJWanRSUVVOSkxFOUJRVThzU1VGQlNTeERRVUZETEVsQlFVa3NRMEZCUXp0SlFVTnlRaXhEUVVGRE8wbEJSVTBzTWtKQlFVc3NSMEZCV2p0UlFVTkpMRTlCUVU4c1NVRkJTU3hEUVVGRExFbEJRVWtzU1VGQlNTeEpRVUZKTEVOQlFVTTdTVUZETjBJc1EwRkJRenRKUVVWTkxEaENRVUZSTEVkQlFXWXNWVUZCWjBJc1EwRkJhVUk3VVVGRE4wSXNTVUZCU1N4SlFVRkpMRXRCUVVzc1EwRkJRenRaUVVGRkxFOUJRVThzU1VGQlNTeERRVUZETzFGQlF6VkNMRXRCUVVzc1NVRkJTU3hEUVVGRExFZEJRVWNzUTBGQlF5eEZRVUZGTEVOQlFVTXNSMEZCUnl4SlFVRkpMRU5CUVVNc1VVRkJVU3hEUVVGRExFMUJRVTBzUlVGQlJTeERRVUZETEVWQlFVVXNSVUZCUlR0WlFVTXpReXhKUVVGSkxFbEJRVWtzUTBGQlF5eFJRVUZSTEVOQlFVTXNRMEZCUXl4RFFVRkRMRU5CUVVNc1VVRkJVU3hEUVVGRExFTkJRVU1zUTBGQlF6dG5Ra0ZCUlN4UFFVRlBMRWxCUVVrc1EwRkJRenRUUVVOcVJEdFJRVU5FTEU5QlFVOHNTMEZCU3l4RFFVRkRPMGxCUTJwQ0xFTkJRVU03U1VGRlRTdzBRa0ZCVFN4SFFVRmlMRlZCUVdNc1VVRkJhVU03VVVGQkwwTXNhVUpCUlVNN1VVRkVSeXhQUVVGUExFbEJRVWtzUTBGQlF5eFJRVUZSTEVOQlFVTXNTMEZCU3l4RFFVRkRMRlZCUVVFc1EwRkJReXhKUVVGSExFOUJRVUVzVVVGQlVTeERRVUZETEV0QlFVa3NRMEZCUXl4SlFVRkpMRVZCUVVVc1EwRkJReXhEUVVGRExFbEJRVWtzUTBGQlF5eEpRVUZKTEVOQlFVTXNRMEZCUXl4TlFVRk5MRU5CUVVNc1VVRkJVU3hEUVVGRExFVkJRV3BFTEVOQlFXbEVMRU5CUVVNc1EwRkJRenRKUVVOMFJpeERRVUZETzBsQlJVMHNORUpCUVUwc1IwRkJZaXhWUVVGakxFZEJRVThzUlVGQlJTeFJRVUZSTzFGQlF6TkNMRTlCUVU4c1NVRkJTU3hEUVVGRExFdEJRVXNzUTBGQlF5eEpRVUZKTEZkQlFWY3NRMEZCU1N4SFFVRkhMRU5CUVVNc1JVRkJSU3hSUVVGUkxFTkJRVU1zUTBGQlF6dEpRVU42UkN4RFFVRkRPMGxCUlUwc01rSkJRVXNzUjBGQldpeFZRVUZoTEV0QlFYRkNMRVZCUVVVc1VVRkJVVHRSUVVONFF5eEpRVUZKTEVsQlFVa3NRMEZCUXl4TFFVRkxMRVZCUVVVN1dVRkJSU3hQUVVGUExFdEJRVXNzUTBGQlF6dGhRVU14UWl4SlFVRkpMRXRCUVVzc1EwRkJReXhMUVVGTExFVkJRVVU3V1VGQlJTeFBRVUZQTEVsQlFVa3NRMEZCUXp0aFFVTXZRaXhKUVVGSkxGRkJRVkVzUTBGQlF5eEpRVUZKTEVOQlFVTXNTVUZCU1N4RlFVRkZMRXRCUVVzc1EwRkJReXhKUVVGSkxFTkJRVU1zUlVGQlJUdFpRVU4wUXl4SlFVRkpMRU5CUVVNc1VVRkJVU3hEUVVGRExFbEJRVWtzUTBGQlF5eExRVUZMTEVOQlFVTXNRMEZCUXp0WlFVTXhRaXhQUVVGUExFbEJRVWtzUTBGQlF6dFRRVU5tTzJGQlFVMDdXVUZEU0N4TFFVRkxMRU5CUVVNc1VVRkJVU3hEUVVGRExFbEJRVWtzUTBGQlF5eEpRVUZKTEVOQlFVTXNRMEZCUXp0WlFVTXhRaXhQUVVGUExFdEJRVXNzUTBGQlF6dFRRVU5vUWp0SlFVTk1MRU5CUVVNN1NVRkZUU3dyUWtGQlV5eEhRVUZvUWl4VlFVRnBRaXhSUVVGcFF6dFJRVU01UXl4SlFVRkpMRWxCUVVrc1EwRkJReXhMUVVGTExFVkJRVVU3V1VGQlJTeFBRVUZQTEVsQlFVa3NRMEZCUXpzN1dVRkRla0lzVDBGQlR5eEpRVUZKTEVOQlFVTXNWVUZCVlN4RFFVRkRMRkZCUVZFc1EwRkJReXhEUVVGRE8wbEJRekZETEVOQlFVTTdTVUZGVFN4blEwRkJWU3hIUVVGcVFpeFZRVUZyUWl4UlFVRnBRenRSUVVNdlF5eEpRVUZKTEVsQlFVa3NRMEZCUXl4UlFVRlJMRU5CUVVNc1RVRkJUU3hKUVVGSkxFTkJRVU03V1VGQlJTeFBRVUZQTEVsQlFVa3NWMEZCVnl4RFFVRkpMRWxCUVVrc1EwRkJReXhEUVVGRE8yRkJRekZFTEVsQlFVa3NTVUZCU1N4RFFVRkRMRkZCUVZFc1EwRkJReXhOUVVGTkxFbEJRVWtzUTBGQlF5eEZRVUZGTzFsQlFVVXNUMEZCVHl4SlFVRkpMRU5CUVVNc1VVRkJVU3hEUVVGRExFTkJRVU1zUTBGQlF5eERRVUZETzFOQlFVVTdZVUZETTBRN1dVRkRSQ3hKUVVGSkxGTkJRVk1zUjBGQlJ5eEpRVUZKTEVOQlFVTXNVVUZCVVN4RFFVRkRMRWRCUVVjc1JVRkJSU3hEUVVGRExFdEJRVXNzUTBGQlF5eEpRVUZKTEVOQlFVTXNVVUZCVVN4RFFVRkRMRWRCUVVjc1JVRkJSU3hGUVVGRkxGRkJRVkVzUTBGQlF5eERRVUZETzFsQlEzcEZMRWxCUVVrc1UwRkJVeXhIUVVGSExFbEJRVWtzUTBGQlF5eFZRVUZWTEVOQlFVTXNVVUZCVVN4RFFVRkRMRU5CUVVNN1dVRkRNVU1zVDBGQlR5eFRRVUZUTEVOQlFVTXNTMEZCU3l4RFFVRkRMRk5CUVZNc1JVRkJSU3hSUVVGUkxFTkJRVU1zUTBGQlF6dFRRVU12UXp0SlFVTk1MRU5CUVVNN1NVRkRUU3hwUTBGQlZ5eEhRVUZzUWl4VlFVRnRRaXhQUVVGMVFpeEZRVUZGTEZGQlFWY3NSVUZCUlN4WFFVRTBReXhGUVVGRkxGRkJRV2xETzFGQlEzQkpMRWxCUVVrc1QwRkJUeXhIUVVGSExFOUJRVThzUTBGQlF5eFRRVUZUTEVOQlFVTXNVVUZCVVN4RFFVRkRMRU5CUVVNN1VVRkZNVU1zVDBGQlR5eERRVUZETEVsQlFVa3NSMEZCUnl4UFFVRlBMRU5CUVVNc1NVRkJTU3hEUVVGRE8xRkJRelZDTEU5QlFVOHNRMEZCUXl4UlFVRlJMRWRCUVVjc1QwRkJUeXhEUVVGRExGRkJRVkVzUTBGQlF6dFJRVU53UXl4SlFVRkpMRmRCUVZjc1MwRkJTeXhKUVVGSkxFbEJRVWtzVDBGQlR5eERRVUZETEVsQlFVa3NTMEZCU3l4SlFVRkpMRVZCUVVVN1dVRkRMME1zVjBGQlZ5eERRVUZETEU5QlFVOHNRMEZCUXl4SlFVRkpMRVZCUVVVc1QwRkJUeXhEUVVGRExFTkJRVU03VTBGRGRFTTdVVUZEUkN4SlFVRkpMRmRCUVZjc1IwRkJSeXhKUVVGSkxGZEJRVmNzUTBGQlF5eFJRVUZSTEVOQlFVTXNRMEZCUXp0UlFVTTFReXhKUVVGSkxGZEJRVmNzUzBGQlN5eEpRVUZKTEVWQlFVVTdXVUZEZEVJc1YwRkJWeXhEUVVGRExGRkJRVkVzUlVGQlJTeFhRVUZYTEVOQlFVTXNRMEZCUXp0VFFVTjBRenRSUVVORUxFOUJRVThzU1VGQlNTeERRVUZETEV0QlFVc3NRMEZCUXl4WFFVRlhMRVZCUVVVc1VVRkJVU3hEUVVGRExFTkJRVU03U1VGRE4wTXNRMEZCUXp0SlFVTk1MR3RDUVVGRE8wRkJRVVFzUTBGQlF5eEJRWHBIUkN4SlFYbEhRenRCUVhwSFdTeHJRMEZCVnp0QlFUaEhlRUk3U1VGRlNTeDFRa0ZCYjBJc1VVRkJhVU03VVVGQmFrTXNZVUZCVVN4SFFVRlNMRkZCUVZFc1EwRkJlVUk3U1VGQlNTeERRVUZETzBsQlMyNUVMREpDUVVGSExFZEJRVlk3VVVGRFNTeEpRVUZKTEVsQlFVa3NRMEZCUXl4TFFVRkxMRVZCUVVVc1JVRkJSVHRaUVVGRkxFOUJRVThzU1VGQlNTeERRVUZETzFOQlFVVTdVVUZEYkVNc1QwRkJUeXhKUVVGSkxFTkJRVU1zU1VGQlNTeERRVUZETEVsQlFVa3NRMEZCUXp0SlFVTXhRaXhEUVVGRE8wbEJTMDBzTkVKQlFVa3NSMEZCV0R0UlFVRlpMR05CUVZrN1lVRkJXaXhWUVVGWkxFVkJRVm9zY1VKQlFWa3NSVUZCV2l4SlFVRlpPMWxCUVZvc2VVSkJRVms3TzFGQlEzQkNMRWxCUVVrc1YwRkJWeXhEUVVGRE8xRkJRMmhDTEV0QlFVc3NTVUZCU1N4RFFVRkRMRWRCUVVjc1EwRkJReXhGUVVGRkxFZEJRVWNzUlVGQlJTeEhRVUZITEVkQlFVTXNTVUZCU1N4RFFVRkRMRU5CUVVNc1EwRkJReXhGUVVGRkxFVkJRVVVzUTBGQlF5eEZRVUZGTzFsQlEyNURMRmRCUVZjc1IwRkJSeXhKUVVGSkxGZEJRVmNzUTBGQlF5eEhRVUZITEVOQlFVTXNRMEZCUXp0WlFVTnVReXhKUVVGSkxFTkJRVU1zU1VGQlNTeEhRVUZITEVsQlFVa3NRMEZCUXl4TFFVRkxMRVZCUVVVc1EwRkJReXhEUVVGRE8yZENRVU4wUWl4WFFVRlhMRU5CUVVNc1EwRkJReXhEUVVGRExFbEJRVWtzUTBGQlF5eEpRVUZKTEVOQlFVTXNTMEZCU3l4RFFVRkRMRmRCUVZjc1JVRkJSU3hKUVVGSkxFTkJRVU1zVVVGQlVTeERRVUZETEVOQlFVTTdVMEZEYWtVN1VVRkRSQ3hQUVVGUExGZEJRVmNzUTBGQlF6dEpRVU4yUWl4RFFVRkRPMGxCUzAwc05rSkJRVXNzUjBGQldqdFJRVU5KTEU5QlFVOHNRMEZCUXl4SlFVRkpMRU5CUVVNc1NVRkJTU3hKUVVGSkxFTkJRVU1zU1VGQlNTeERRVUZETEVsQlFVa3NRMEZCUXl4SlFVRkpMRU5CUVVNN1NVRkRla01zUTBGQlF6dEpRVXROTERoQ1FVRk5MRWRCUVdJN1VVRkRTU3hQUVVGUExFbEJRVWtzUTBGQlF5eEpRVUZKTEVOQlFVTXNUVUZCVFN4RFFVRkRMRWxCUVVrc1EwRkJReXhSUVVGUkxFTkJRVU1zUTBGQlF6dEpRVU16UXl4RFFVRkRPMGxCUzAwc0swSkJRVThzUjBGQlpDeFZRVUZsTEVOQlFVTTdVVUZEV2l4SlFVRkpMRU5CUVVNc1NVRkJTU3hEUVVGRExFOUJRVThzUTBGQlF5eERRVUZETEVOQlFVTXNRMEZCUXp0SlFVTjZRaXhEUVVGRE8wbEJTVTBzTWtKQlFVY3NSMEZCVmp0UlFVTkpMRWxCUVVrc1NVRkJTU3hEUVVGRExFdEJRVXNzUlVGQlJTeEZRVUZGTzFsQlEyUXNUMEZCVHl4SlFVRkpMRU5CUVVNN1UwRkRaanRSUVVORUxFbEJRVWtzUjBGQlJ5eEhRVUZITEVsQlFVa3NRMEZCUXl4SlFVRkpMRU5CUVVNc1IwRkJSeXhGUVVGRkxFTkJRVU03VVVGRE1VSXNTVUZCU1N4RFFVRkRMRWxCUVVrc1IwRkJSeXhKUVVGSkxFTkJRVU1zU1VGQlNTeERRVUZETEZOQlFWTXNRMEZCUXl4SlFVRkpMRU5CUVVNc1VVRkJVU3hEUVVGRExFTkJRVU03VVVGREwwTXNUMEZCVHl4SFFVRkhMRU5CUVVNN1NVRkRaaXhEUVVGRE8wbEJTVTBzYVVOQlFWTXNSMEZCYUVJc1ZVRkJhVUlzVVVGQmQwSXNSVUZCUlN4TlFVRlRMRVZCUVVVc1YwRkJiVVE3VVVGQmJrUXNORUpCUVVFc1JVRkJRU3hyUWtGQmJVUTdVVUZEY2tjc1NVRkJTU3hEUVVGRExFbEJRVWtzUjBGQlJ5eEpRVUZKTEVOQlFVTXNTVUZCU1N4RFFVRkRMRmRCUVZjc1EwRkJReXhSUVVGUkxFVkJRVVVzVFVGQlRTeEZRVUZGTEZkQlFWY3NSVUZCUlN4SlFVRkpMRU5CUVVNc1VVRkJVU3hEUVVGRExFTkJRVU03U1VGRGNFWXNRMEZCUXp0SlFVTk5MR2REUVVGUkxFZEJRV1lzVlVGQlowSXNVVUZCVVR0UlFVTndRaXhQUVVGUExFbEJRVWtzUTBGQlF5eEpRVUZKTEVOQlFVTXNVVUZCVVN4RFFVRkRMRkZCUVZFc1EwRkJReXhEUVVGRE8wbEJRM2hETEVOQlFVTTdTVUZMVFN3MlFrRkJTeXhIUVVGYU8xRkJRMGtzVDBGQlR5eEpRVUZKTEVOQlFVTXNTVUZCU1N4RFFVRkRMRXRCUVVzc1JVRkJSU3hEUVVGRE8wbEJRemRDTEVOQlFVTTdTVUZEVEN4dlFrRkJRenRCUVVGRUxFTkJRVU1zUVVGNFJVUXNTVUYzUlVNN1FVRjRSVmtzYzBOQlFXRWlmUT09IiwiXCJ1c2Ugc3RyaWN0XCI7XG52YXIgX19leHRlbmRzID0gKHRoaXMgJiYgdGhpcy5fX2V4dGVuZHMpIHx8IChmdW5jdGlvbiAoKSB7XG4gICAgdmFyIGV4dGVuZFN0YXRpY3MgPSBmdW5jdGlvbiAoZCwgYikge1xuICAgICAgICBleHRlbmRTdGF0aWNzID0gT2JqZWN0LnNldFByb3RvdHlwZU9mIHx8XG4gICAgICAgICAgICAoeyBfX3Byb3RvX186IFtdIH0gaW5zdGFuY2VvZiBBcnJheSAmJiBmdW5jdGlvbiAoZCwgYikgeyBkLl9fcHJvdG9fXyA9IGI7IH0pIHx8XG4gICAgICAgICAgICBmdW5jdGlvbiAoZCwgYikgeyBmb3IgKHZhciBwIGluIGIpIGlmIChiLmhhc093blByb3BlcnR5KHApKSBkW3BdID0gYltwXTsgfTtcbiAgICAgICAgcmV0dXJuIGV4dGVuZFN0YXRpY3MoZCwgYik7XG4gICAgfTtcbiAgICByZXR1cm4gZnVuY3Rpb24gKGQsIGIpIHtcbiAgICAgICAgZXh0ZW5kU3RhdGljcyhkLCBiKTtcbiAgICAgICAgZnVuY3Rpb24gX18oKSB7IHRoaXMuY29uc3RydWN0b3IgPSBkOyB9XG4gICAgICAgIGQucHJvdG90eXBlID0gYiA9PT0gbnVsbCA/IE9iamVjdC5jcmVhdGUoYikgOiAoX18ucHJvdG90eXBlID0gYi5wcm90b3R5cGUsIG5ldyBfXygpKTtcbiAgICB9O1xufSkoKTtcbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCBcIl9fZXNNb2R1bGVcIiwgeyB2YWx1ZTogdHJ1ZSB9KTtcbnZhciBUcmVlQmFzZSA9IChmdW5jdGlvbiAoKSB7XG4gICAgZnVuY3Rpb24gVHJlZUJhc2UoKSB7XG4gICAgICAgIHRoaXMuZmluZEl0ZXIgPSBmdW5jdGlvbiAoZGF0YSkge1xuICAgICAgICAgICAgdmFyIHJlcyA9IHRoaXMuX3Jvb3Q7XG4gICAgICAgICAgICB2YXIgaXRlciA9IHRoaXMuaXRlcmF0b3IoKTtcbiAgICAgICAgICAgIHdoaWxlIChyZXMgIT09IG51bGwpIHtcbiAgICAgICAgICAgICAgICB2YXIgYyA9IHRoaXMuX2NvbXBhcmF0b3IoZGF0YSwgcmVzLmRhdGEpO1xuICAgICAgICAgICAgICAgIGlmIChjID09PSAwKSB7XG4gICAgICAgICAgICAgICAgICAgIGl0ZXIuX2N1cnNvciA9IHJlcztcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGl0ZXI7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBpdGVyLl9hbmNlc3RvcnMucHVzaChyZXMpO1xuICAgICAgICAgICAgICAgICAgICByZXMgPSByZXMuZ2V0X2NoaWxkKGMgPiAwKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgfTtcbiAgICB9XG4gICAgVHJlZUJhc2UucHJvdG90eXBlLmNsZWFyID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB0aGlzLl9yb290ID0gbnVsbDtcbiAgICAgICAgdGhpcy5zaXplID0gMDtcbiAgICB9O1xuICAgIDtcbiAgICBUcmVlQmFzZS5wcm90b3R5cGUuZmluZCA9IGZ1bmN0aW9uIChkYXRhKSB7XG4gICAgICAgIHZhciByZXMgPSB0aGlzLl9yb290O1xuICAgICAgICB3aGlsZSAocmVzICE9PSBudWxsKSB7XG4gICAgICAgICAgICB2YXIgYyA9IHRoaXMuX2NvbXBhcmF0b3IoZGF0YSwgcmVzLmRhdGEpO1xuICAgICAgICAgICAgaWYgKGMgPT09IDApIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gcmVzLmRhdGE7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICByZXMgPSByZXMuZ2V0X2NoaWxkKGMgPiAwKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gbnVsbDtcbiAgICB9O1xuICAgIDtcbiAgICBUcmVlQmFzZS5wcm90b3R5cGUubG93ZXJCb3VuZCA9IGZ1bmN0aW9uIChkYXRhKSB7XG4gICAgICAgIHJldHVybiB0aGlzLl9ib3VuZChkYXRhLCB0aGlzLl9jb21wYXJhdG9yKTtcbiAgICB9O1xuICAgIDtcbiAgICBUcmVlQmFzZS5wcm90b3R5cGUudXBwZXJCb3VuZCA9IGZ1bmN0aW9uIChkYXRhKSB7XG4gICAgICAgIHZhciBjbXAgPSB0aGlzLl9jb21wYXJhdG9yO1xuICAgICAgICBmdW5jdGlvbiByZXZlcnNlX2NtcChhLCBiKSB7XG4gICAgICAgICAgICByZXR1cm4gY21wKGIsIGEpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzLl9ib3VuZChkYXRhLCByZXZlcnNlX2NtcCk7XG4gICAgfTtcbiAgICA7XG4gICAgVHJlZUJhc2UucHJvdG90eXBlLm1pbiA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIHJlcyA9IHRoaXMuX3Jvb3Q7XG4gICAgICAgIGlmIChyZXMgPT09IG51bGwpIHtcbiAgICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICB9XG4gICAgICAgIHdoaWxlIChyZXMubGVmdCAhPT0gbnVsbCkge1xuICAgICAgICAgICAgcmVzID0gcmVzLmxlZnQ7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHJlcy5kYXRhO1xuICAgIH07XG4gICAgO1xuICAgIFRyZWVCYXNlLnByb3RvdHlwZS5tYXggPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciByZXMgPSB0aGlzLl9yb290O1xuICAgICAgICBpZiAocmVzID09PSBudWxsKSB7XG4gICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgfVxuICAgICAgICB3aGlsZSAocmVzLnJpZ2h0ICE9PSBudWxsKSB7XG4gICAgICAgICAgICByZXMgPSByZXMucmlnaHQ7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHJlcy5kYXRhO1xuICAgIH07XG4gICAgO1xuICAgIFRyZWVCYXNlLnByb3RvdHlwZS5pdGVyYXRvciA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIG5ldyBJdGVyYXRvcih0aGlzKTtcbiAgICB9O1xuICAgIDtcbiAgICBUcmVlQmFzZS5wcm90b3R5cGUuZWFjaCA9IGZ1bmN0aW9uIChjYikge1xuICAgICAgICB2YXIgaXQgPSB0aGlzLml0ZXJhdG9yKCksIGRhdGE7XG4gICAgICAgIHdoaWxlICgoZGF0YSA9IGl0Lm5leHQoKSkgIT09IG51bGwpIHtcbiAgICAgICAgICAgIGNiKGRhdGEpO1xuICAgICAgICB9XG4gICAgfTtcbiAgICA7XG4gICAgVHJlZUJhc2UucHJvdG90eXBlLnJlYWNoID0gZnVuY3Rpb24gKGNiKSB7XG4gICAgICAgIHZhciBpdCA9IHRoaXMuaXRlcmF0b3IoKSwgZGF0YTtcbiAgICAgICAgd2hpbGUgKChkYXRhID0gaXQucHJldigpKSAhPT0gbnVsbCkge1xuICAgICAgICAgICAgY2IoZGF0YSk7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIDtcbiAgICBUcmVlQmFzZS5wcm90b3R5cGUuX2JvdW5kID0gZnVuY3Rpb24gKGRhdGEsIGNtcCkge1xuICAgICAgICB2YXIgY3VyID0gdGhpcy5fcm9vdDtcbiAgICAgICAgdmFyIGl0ZXIgPSB0aGlzLml0ZXJhdG9yKCk7XG4gICAgICAgIHdoaWxlIChjdXIgIT09IG51bGwpIHtcbiAgICAgICAgICAgIHZhciBjID0gdGhpcy5fY29tcGFyYXRvcihkYXRhLCBjdXIuZGF0YSk7XG4gICAgICAgICAgICBpZiAoYyA9PT0gMCkge1xuICAgICAgICAgICAgICAgIGl0ZXIuX2N1cnNvciA9IGN1cjtcbiAgICAgICAgICAgICAgICByZXR1cm4gaXRlcjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGl0ZXIuX2FuY2VzdG9ycy5wdXNoKGN1cik7XG4gICAgICAgICAgICBjdXIgPSBjdXIuZ2V0X2NoaWxkKGMgPiAwKTtcbiAgICAgICAgfVxuICAgICAgICBmb3IgKHZhciBpID0gaXRlci5fYW5jZXN0b3JzLmxlbmd0aCAtIDE7IGkgPj0gMDsgLS1pKSB7XG4gICAgICAgICAgICBjdXIgPSBpdGVyLl9hbmNlc3RvcnNbaV07XG4gICAgICAgICAgICBpZiAoY21wKGRhdGEsIGN1ci5kYXRhKSA+IDApIHtcbiAgICAgICAgICAgICAgICBpdGVyLl9jdXJzb3IgPSBjdXI7XG4gICAgICAgICAgICAgICAgaXRlci5fYW5jZXN0b3JzLmxlbmd0aCA9IGk7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGl0ZXI7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgaXRlci5fYW5jZXN0b3JzLmxlbmd0aCA9IDA7XG4gICAgICAgIHJldHVybiBpdGVyO1xuICAgIH07XG4gICAgO1xuICAgIHJldHVybiBUcmVlQmFzZTtcbn0oKSk7XG5leHBvcnRzLlRyZWVCYXNlID0gVHJlZUJhc2U7XG52YXIgSXRlcmF0b3IgPSAoZnVuY3Rpb24gKCkge1xuICAgIGZ1bmN0aW9uIEl0ZXJhdG9yKHRyZWUpIHtcbiAgICAgICAgdGhpcy5fdHJlZSA9IHRyZWU7XG4gICAgICAgIHRoaXMuX2FuY2VzdG9ycyA9IFtdO1xuICAgICAgICB0aGlzLl9jdXJzb3IgPSBudWxsO1xuICAgIH1cbiAgICBJdGVyYXRvci5wcm90b3R5cGUuZGF0YSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX2N1cnNvciAhPT0gbnVsbCA/IHRoaXMuX2N1cnNvci5kYXRhIDogbnVsbDtcbiAgICB9O1xuICAgIDtcbiAgICBJdGVyYXRvci5wcm90b3R5cGUubmV4dCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgaWYgKHRoaXMuX2N1cnNvciA9PT0gbnVsbCkge1xuICAgICAgICAgICAgdmFyIHJvb3QgPSB0aGlzLl90cmVlLl9yb290O1xuICAgICAgICAgICAgaWYgKHJvb3QgIT09IG51bGwpIHtcbiAgICAgICAgICAgICAgICB0aGlzLl9taW5Ob2RlKHJvb3QpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgaWYgKHRoaXMuX2N1cnNvci5yaWdodCA9PT0gbnVsbCkge1xuICAgICAgICAgICAgICAgIHZhciBzYXZlO1xuICAgICAgICAgICAgICAgIGRvIHtcbiAgICAgICAgICAgICAgICAgICAgc2F2ZSA9IHRoaXMuX2N1cnNvcjtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHRoaXMuX2FuY2VzdG9ycy5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX2N1cnNvciA9IHRoaXMuX2FuY2VzdG9ycy5wb3AoKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX2N1cnNvciA9IG51bGw7XG4gICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0gd2hpbGUgKHRoaXMuX2N1cnNvci5yaWdodCA9PT0gc2F2ZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICB0aGlzLl9hbmNlc3RvcnMucHVzaCh0aGlzLl9jdXJzb3IpO1xuICAgICAgICAgICAgICAgIHRoaXMuX21pbk5vZGUodGhpcy5fY3Vyc29yLnJpZ2h0KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdGhpcy5fY3Vyc29yICE9PSBudWxsID8gdGhpcy5fY3Vyc29yLmRhdGEgOiBudWxsO1xuICAgIH07XG4gICAgO1xuICAgIEl0ZXJhdG9yLnByb3RvdHlwZS5wcmV2ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBpZiAodGhpcy5fY3Vyc29yID09PSBudWxsKSB7XG4gICAgICAgICAgICB2YXIgcm9vdCA9IHRoaXMuX3RyZWUuX3Jvb3Q7XG4gICAgICAgICAgICBpZiAocm9vdCAhPT0gbnVsbCkge1xuICAgICAgICAgICAgICAgIHRoaXMuX21heE5vZGUocm9vdCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICBpZiAodGhpcy5fY3Vyc29yLmxlZnQgPT09IG51bGwpIHtcbiAgICAgICAgICAgICAgICB2YXIgc2F2ZTtcbiAgICAgICAgICAgICAgICBkbyB7XG4gICAgICAgICAgICAgICAgICAgIHNhdmUgPSB0aGlzLl9jdXJzb3I7XG4gICAgICAgICAgICAgICAgICAgIGlmICh0aGlzLl9hbmNlc3RvcnMubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9jdXJzb3IgPSB0aGlzLl9hbmNlc3RvcnMucG9wKCk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9jdXJzb3IgPSBudWxsO1xuICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9IHdoaWxlICh0aGlzLl9jdXJzb3IubGVmdCA9PT0gc2F2ZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICB0aGlzLl9hbmNlc3RvcnMucHVzaCh0aGlzLl9jdXJzb3IpO1xuICAgICAgICAgICAgICAgIHRoaXMuX21heE5vZGUodGhpcy5fY3Vyc29yLmxlZnQpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzLl9jdXJzb3IgIT09IG51bGwgPyB0aGlzLl9jdXJzb3IuZGF0YSA6IG51bGw7XG4gICAgfTtcbiAgICA7XG4gICAgSXRlcmF0b3IucHJvdG90eXBlLl9taW5Ob2RlID0gZnVuY3Rpb24gKHN0YXJ0KSB7XG4gICAgICAgIHdoaWxlIChzdGFydC5sZWZ0ICE9PSBudWxsKSB7XG4gICAgICAgICAgICB0aGlzLl9hbmNlc3RvcnMucHVzaChzdGFydCk7XG4gICAgICAgICAgICBzdGFydCA9IHN0YXJ0LmxlZnQ7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5fY3Vyc29yID0gc3RhcnQ7XG4gICAgfTtcbiAgICA7XG4gICAgSXRlcmF0b3IucHJvdG90eXBlLl9tYXhOb2RlID0gZnVuY3Rpb24gKHN0YXJ0KSB7XG4gICAgICAgIHdoaWxlIChzdGFydC5yaWdodCAhPT0gbnVsbCkge1xuICAgICAgICAgICAgdGhpcy5fYW5jZXN0b3JzLnB1c2goc3RhcnQpO1xuICAgICAgICAgICAgc3RhcnQgPSBzdGFydC5yaWdodDtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLl9jdXJzb3IgPSBzdGFydDtcbiAgICB9O1xuICAgIDtcbiAgICByZXR1cm4gSXRlcmF0b3I7XG59KCkpO1xuZXhwb3J0cy5JdGVyYXRvciA9IEl0ZXJhdG9yO1xudmFyIE5vZGUgPSAoZnVuY3Rpb24gKCkge1xuICAgIGZ1bmN0aW9uIE5vZGUoZGF0YSkge1xuICAgICAgICB0aGlzLmRhdGEgPSBkYXRhO1xuICAgICAgICB0aGlzLmxlZnQgPSBudWxsO1xuICAgICAgICB0aGlzLnJpZ2h0ID0gbnVsbDtcbiAgICAgICAgdGhpcy5yZWQgPSB0cnVlO1xuICAgIH1cbiAgICBOb2RlLnByb3RvdHlwZS5nZXRfY2hpbGQgPSBmdW5jdGlvbiAoZGlyKSB7XG4gICAgICAgIHJldHVybiBkaXIgPyB0aGlzLnJpZ2h0IDogdGhpcy5sZWZ0O1xuICAgIH07XG4gICAgO1xuICAgIE5vZGUucHJvdG90eXBlLnNldF9jaGlsZCA9IGZ1bmN0aW9uIChkaXIsIHZhbCkge1xuICAgICAgICBpZiAoZGlyKSB7XG4gICAgICAgICAgICB0aGlzLnJpZ2h0ID0gdmFsO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgdGhpcy5sZWZ0ID0gdmFsO1xuICAgICAgICB9XG4gICAgfTtcbiAgICA7XG4gICAgcmV0dXJuIE5vZGU7XG59KCkpO1xudmFyIFJCVHJlZSA9IChmdW5jdGlvbiAoX3N1cGVyKSB7XG4gICAgX19leHRlbmRzKFJCVHJlZSwgX3N1cGVyKTtcbiAgICBmdW5jdGlvbiBSQlRyZWUoY29tcGFyYXRvcikge1xuICAgICAgICB2YXIgX3RoaXMgPSBfc3VwZXIuY2FsbCh0aGlzKSB8fCB0aGlzO1xuICAgICAgICBfdGhpcy5fcm9vdCA9IG51bGw7XG4gICAgICAgIF90aGlzLl9jb21wYXJhdG9yID0gY29tcGFyYXRvcjtcbiAgICAgICAgX3RoaXMuc2l6ZSA9IDA7XG4gICAgICAgIHJldHVybiBfdGhpcztcbiAgICB9XG4gICAgUkJUcmVlLnByb3RvdHlwZS5pbnNlcnQgPSBmdW5jdGlvbiAoZGF0YSkge1xuICAgICAgICB2YXIgcmV0ID0gZmFsc2U7XG4gICAgICAgIGlmICh0aGlzLl9yb290ID09PSBudWxsKSB7XG4gICAgICAgICAgICB0aGlzLl9yb290ID0gbmV3IE5vZGUoZGF0YSk7XG4gICAgICAgICAgICByZXQgPSB0cnVlO1xuICAgICAgICAgICAgdGhpcy5zaXplKys7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICB2YXIgaGVhZCA9IG5ldyBOb2RlKHVuZGVmaW5lZCk7XG4gICAgICAgICAgICB2YXIgZGlyID0gZmFsc2U7XG4gICAgICAgICAgICB2YXIgbGFzdCA9IGZhbHNlO1xuICAgICAgICAgICAgdmFyIGdwID0gbnVsbDtcbiAgICAgICAgICAgIHZhciBnZ3AgPSBoZWFkO1xuICAgICAgICAgICAgdmFyIHAgPSBudWxsO1xuICAgICAgICAgICAgdmFyIG5vZGUgPSB0aGlzLl9yb290O1xuICAgICAgICAgICAgZ2dwLnJpZ2h0ID0gdGhpcy5fcm9vdDtcbiAgICAgICAgICAgIHdoaWxlICh0cnVlKSB7XG4gICAgICAgICAgICAgICAgaWYgKG5vZGUgPT09IG51bGwpIHtcbiAgICAgICAgICAgICAgICAgICAgbm9kZSA9IG5ldyBOb2RlKGRhdGEpO1xuICAgICAgICAgICAgICAgICAgICBwLnNldF9jaGlsZChkaXIsIG5vZGUpO1xuICAgICAgICAgICAgICAgICAgICByZXQgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICB0aGlzLnNpemUrKztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSBpZiAoUkJUcmVlLmlzX3JlZChub2RlLmxlZnQpICYmIFJCVHJlZS5pc19yZWQobm9kZS5yaWdodCkpIHtcbiAgICAgICAgICAgICAgICAgICAgbm9kZS5yZWQgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICBub2RlLmxlZnQucmVkID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgICAgIG5vZGUucmlnaHQucmVkID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmIChSQlRyZWUuaXNfcmVkKG5vZGUpICYmIFJCVHJlZS5pc19yZWQocCkpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGRpcjIgPSBnZ3AucmlnaHQgPT09IGdwO1xuICAgICAgICAgICAgICAgICAgICBpZiAobm9kZSA9PT0gcC5nZXRfY2hpbGQobGFzdCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGdncC5zZXRfY2hpbGQoZGlyMiwgUkJUcmVlLnNpbmdsZV9yb3RhdGUoZ3AsICFsYXN0KSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBnZ3Auc2V0X2NoaWxkKGRpcjIsIFJCVHJlZS5kb3VibGVfcm90YXRlKGdwLCAhbGFzdCkpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHZhciBjbXAgPSB0aGlzLl9jb21wYXJhdG9yKG5vZGUuZGF0YSwgZGF0YSk7XG4gICAgICAgICAgICAgICAgaWYgKGNtcCA9PT0gMCkge1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgbGFzdCA9IGRpcjtcbiAgICAgICAgICAgICAgICBkaXIgPSBjbXAgPCAwO1xuICAgICAgICAgICAgICAgIGlmIChncCAhPT0gbnVsbCkge1xuICAgICAgICAgICAgICAgICAgICBnZ3AgPSBncDtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZ3AgPSBwO1xuICAgICAgICAgICAgICAgIHAgPSBub2RlO1xuICAgICAgICAgICAgICAgIG5vZGUgPSBub2RlLmdldF9jaGlsZChkaXIpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy5fcm9vdCA9IGhlYWQucmlnaHQ7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5fcm9vdC5yZWQgPSBmYWxzZTtcbiAgICAgICAgcmV0dXJuIHJldDtcbiAgICB9O1xuICAgIDtcbiAgICBSQlRyZWUucHJvdG90eXBlLnJlbW92ZSA9IGZ1bmN0aW9uIChkYXRhKSB7XG4gICAgICAgIGlmICh0aGlzLl9yb290ID09PSBudWxsKSB7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgICAgdmFyIGhlYWQgPSBuZXcgTm9kZSh1bmRlZmluZWQpO1xuICAgICAgICB2YXIgbm9kZSA9IGhlYWQ7XG4gICAgICAgIG5vZGUucmlnaHQgPSB0aGlzLl9yb290O1xuICAgICAgICB2YXIgcCA9IG51bGw7XG4gICAgICAgIHZhciBncCA9IG51bGw7XG4gICAgICAgIHZhciBmb3VuZCA9IG51bGw7XG4gICAgICAgIHZhciBkaXIgPSB0cnVlO1xuICAgICAgICB3aGlsZSAobm9kZS5nZXRfY2hpbGQoZGlyKSAhPT0gbnVsbCkge1xuICAgICAgICAgICAgdmFyIGxhc3QgPSBkaXI7XG4gICAgICAgICAgICBncCA9IHA7XG4gICAgICAgICAgICBwID0gbm9kZTtcbiAgICAgICAgICAgIG5vZGUgPSBub2RlLmdldF9jaGlsZChkaXIpO1xuICAgICAgICAgICAgdmFyIGNtcCA9IHRoaXMuX2NvbXBhcmF0b3IoZGF0YSwgbm9kZS5kYXRhKTtcbiAgICAgICAgICAgIGRpciA9IGNtcCA+IDA7XG4gICAgICAgICAgICBpZiAoY21wID09PSAwKSB7XG4gICAgICAgICAgICAgICAgZm91bmQgPSBub2RlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKCFSQlRyZWUuaXNfcmVkKG5vZGUpICYmICFSQlRyZWUuaXNfcmVkKG5vZGUuZ2V0X2NoaWxkKGRpcikpKSB7XG4gICAgICAgICAgICAgICAgaWYgKFJCVHJlZS5pc19yZWQobm9kZS5nZXRfY2hpbGQoIWRpcikpKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBzciA9IFJCVHJlZS5zaW5nbGVfcm90YXRlKG5vZGUsIGRpcik7XG4gICAgICAgICAgICAgICAgICAgIHAuc2V0X2NoaWxkKGxhc3QsIHNyKTtcbiAgICAgICAgICAgICAgICAgICAgcCA9IHNyO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIGlmICghUkJUcmVlLmlzX3JlZChub2RlLmdldF9jaGlsZCghZGlyKSkpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIHNpYmxpbmcgPSBwLmdldF9jaGlsZCghbGFzdCk7XG4gICAgICAgICAgICAgICAgICAgIGlmIChzaWJsaW5nICE9PSBudWxsKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoIVJCVHJlZS5pc19yZWQoc2libGluZy5nZXRfY2hpbGQoIWxhc3QpKSAmJiAhUkJUcmVlLmlzX3JlZChzaWJsaW5nLmdldF9jaGlsZChsYXN0KSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwLnJlZCA9IGZhbHNlO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNpYmxpbmcucmVkID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBub2RlLnJlZCA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgZGlyMiA9IGdwLnJpZ2h0ID09PSBwO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChSQlRyZWUuaXNfcmVkKHNpYmxpbmcuZ2V0X2NoaWxkKGxhc3QpKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBncC5zZXRfY2hpbGQoZGlyMiwgUkJUcmVlLmRvdWJsZV9yb3RhdGUocCwgbGFzdCkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbHNlIGlmIChSQlRyZWUuaXNfcmVkKHNpYmxpbmcuZ2V0X2NoaWxkKCFsYXN0KSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZ3Auc2V0X2NoaWxkKGRpcjIsIFJCVHJlZS5zaW5nbGVfcm90YXRlKHAsIGxhc3QpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGdwYyA9IGdwLmdldF9jaGlsZChkaXIyKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBncGMucmVkID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBub2RlLnJlZCA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZ3BjLmxlZnQucmVkID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZ3BjLnJpZ2h0LnJlZCA9IGZhbHNlO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGlmIChmb3VuZCAhPT0gbnVsbCkge1xuICAgICAgICAgICAgZm91bmQuZGF0YSA9IG5vZGUuZGF0YTtcbiAgICAgICAgICAgIHAuc2V0X2NoaWxkKHAucmlnaHQgPT09IG5vZGUsIG5vZGUuZ2V0X2NoaWxkKG5vZGUubGVmdCA9PT0gbnVsbCkpO1xuICAgICAgICAgICAgdGhpcy5zaXplLS07XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5fcm9vdCA9IGhlYWQucmlnaHQ7XG4gICAgICAgIGlmICh0aGlzLl9yb290ICE9PSBudWxsKSB7XG4gICAgICAgICAgICB0aGlzLl9yb290LnJlZCA9IGZhbHNlO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBmb3VuZCAhPT0gbnVsbDtcbiAgICB9O1xuICAgIDtcbiAgICBSQlRyZWUuaXNfcmVkID0gZnVuY3Rpb24gKG5vZGUpIHtcbiAgICAgICAgcmV0dXJuIG5vZGUgIT09IG51bGwgJiYgbm9kZS5yZWQ7XG4gICAgfTtcbiAgICBSQlRyZWUuc2luZ2xlX3JvdGF0ZSA9IGZ1bmN0aW9uIChyb290LCBkaXIpIHtcbiAgICAgICAgdmFyIHNhdmUgPSByb290LmdldF9jaGlsZCghZGlyKTtcbiAgICAgICAgcm9vdC5zZXRfY2hpbGQoIWRpciwgc2F2ZS5nZXRfY2hpbGQoZGlyKSk7XG4gICAgICAgIHNhdmUuc2V0X2NoaWxkKGRpciwgcm9vdCk7XG4gICAgICAgIHJvb3QucmVkID0gdHJ1ZTtcbiAgICAgICAgc2F2ZS5yZWQgPSBmYWxzZTtcbiAgICAgICAgcmV0dXJuIHNhdmU7XG4gICAgfTtcbiAgICBSQlRyZWUuZG91YmxlX3JvdGF0ZSA9IGZ1bmN0aW9uIChyb290LCBkaXIpIHtcbiAgICAgICAgcm9vdC5zZXRfY2hpbGQoIWRpciwgUkJUcmVlLnNpbmdsZV9yb3RhdGUocm9vdC5nZXRfY2hpbGQoIWRpciksICFkaXIpKTtcbiAgICAgICAgcmV0dXJuIFJCVHJlZS5zaW5nbGVfcm90YXRlKHJvb3QsIGRpcik7XG4gICAgfTtcbiAgICByZXR1cm4gUkJUcmVlO1xufShUcmVlQmFzZSkpO1xuZXhwb3J0cy5SQlRyZWUgPSBSQlRyZWU7XG4vLyMgc291cmNlTWFwcGluZ1VSTD1kYXRhOmFwcGxpY2F0aW9uL2pzb247YmFzZTY0LGV5SjJaWEp6YVc5dUlqb3pMQ0ptYVd4bElqb2ljbUowY21WbExtcHpJaXdpYzI5MWNtTmxVbTl2ZENJNklpSXNJbk52ZFhKalpYTWlPbHNpTGk0dkxpNHZWMlZpUTI5c1lTOXpjbU12Y21KMGNtVmxMblJ6SWwwc0ltNWhiV1Z6SWpwYlhTd2liV0Z3Y0dsdVozTWlPaUk3T3pzN096czdPenM3T3pzN096dEJRWFZDU1R0SlFVRkJPMUZCTkVKSkxHRkJRVkVzUjBGQlJ5eFZRVUZWTEVsQlFVazdXVUZEY2tJc1NVRkJTU3hIUVVGSExFZEJRVWNzU1VGQlNTeERRVUZETEV0QlFVc3NRMEZCUXp0WlFVTnlRaXhKUVVGSkxFbEJRVWtzUjBGQlJ5eEpRVUZKTEVOQlFVTXNVVUZCVVN4RlFVRkZMRU5CUVVNN1dVRkZNMElzVDBGQlR5eEhRVUZITEV0QlFVc3NTVUZCU1N4RlFVRkZPMmRDUVVOcVFpeEpRVUZKTEVOQlFVTXNSMEZCUnl4SlFVRkpMRU5CUVVNc1YwRkJWeXhEUVVGRExFbEJRVWtzUlVGQlJTeEhRVUZITEVOQlFVTXNTVUZCU1N4RFFVRkRMRU5CUVVNN1owSkJRM3BETEVsQlFVa3NRMEZCUXl4TFFVRkxMRU5CUVVNc1JVRkJSVHR2UWtGRFZDeEpRVUZKTEVOQlFVTXNUMEZCVHl4SFFVRkhMRWRCUVVjc1EwRkJRenR2UWtGRGJrSXNUMEZCVHl4SlFVRkpMRU5CUVVNN2FVSkJRMlk3Y1VKQlEwazdiMEpCUTBRc1NVRkJTU3hEUVVGRExGVkJRVlVzUTBGQlF5eEpRVUZKTEVOQlFVTXNSMEZCUnl4RFFVRkRMRU5CUVVNN2IwSkJRekZDTEVkQlFVY3NSMEZCUnl4SFFVRkhMRU5CUVVNc1UwRkJVeXhEUVVGRExFTkJRVU1zUjBGQlJ5eERRVUZETEVOQlFVTXNRMEZCUXp0cFFrRkRPVUk3WVVGRFNqdFpRVVZFTEU5QlFVOHNTVUZCU1N4RFFVRkRPMUZCUTJoQ0xFTkJRVU1zUTBGQlF6dEpRU3RHVGl4RFFVRkRPMGxCZGtsSExIZENRVUZMTEVkQlFVdzdVVUZEU1N4SlFVRkpMRU5CUVVNc1MwRkJTeXhIUVVGSExFbEJRVWtzUTBGQlF6dFJRVU5zUWl4SlFVRkpMRU5CUVVNc1NVRkJTU3hIUVVGSExFTkJRVU1zUTBGQlF6dEpRVU5zUWl4RFFVRkRPMGxCUVVFc1EwRkJRenRKUVVkR0xIVkNRVUZKTEVkQlFVb3NWVUZCU3l4SlFVRkpPMUZCUTB3c1NVRkJTU3hIUVVGSExFZEJRVWNzU1VGQlNTeERRVUZETEV0QlFVc3NRMEZCUXp0UlFVVnlRaXhQUVVGUExFZEJRVWNzUzBGQlN5eEpRVUZKTEVWQlFVVTdXVUZEYWtJc1NVRkJTU3hEUVVGRExFZEJRVWNzU1VGQlNTeERRVUZETEZkQlFWY3NRMEZCUXl4SlFVRkpMRVZCUVVVc1IwRkJSeXhEUVVGRExFbEJRVWtzUTBGQlF5eERRVUZETzFsQlEzcERMRWxCUVVrc1EwRkJReXhMUVVGTExFTkJRVU1zUlVGQlJUdG5Ra0ZEVkN4UFFVRlBMRWRCUVVjc1EwRkJReXhKUVVGSkxFTkJRVU03WVVGRGJrSTdhVUpCUTBrN1owSkJRMFFzUjBGQlJ5eEhRVUZITEVkQlFVY3NRMEZCUXl4VFFVRlRMRU5CUVVNc1EwRkJReXhIUVVGSExFTkJRVU1zUTBGQlF5eERRVUZETzJGQlF6bENPMU5CUTBvN1VVRkZSQ3hQUVVGUExFbEJRVWtzUTBGQlF6dEpRVU5vUWl4RFFVRkRPMGxCUVVFc1EwRkJRenRKUVhWQ1JpdzJRa0ZCVlN4SFFVRldMRlZCUVZjc1NVRkJTVHRSUVVOWUxFOUJRVThzU1VGQlNTeERRVUZETEUxQlFVMHNRMEZCUXl4SlFVRkpMRVZCUVVVc1NVRkJTU3hEUVVGRExGZEJRVmNzUTBGQlF5eERRVUZETzBsQlF5OURMRU5CUVVNN1NVRkJRU3hEUVVGRE8wbEJSMFlzTmtKQlFWVXNSMEZCVml4VlFVRlhMRWxCUVVrN1VVRkRXQ3hKUVVGSkxFZEJRVWNzUjBGQlJ5eEpRVUZKTEVOQlFVTXNWMEZCVnl4RFFVRkRPMUZCUlROQ0xGTkJRVk1zVjBGQlZ5eERRVUZETEVOQlFVTXNSVUZCUlN4RFFVRkRPMWxCUTNKQ0xFOUJRVThzUjBGQlJ5eERRVUZETEVOQlFVTXNSVUZCUlN4RFFVRkRMRU5CUVVNc1EwRkJRenRSUVVOeVFpeERRVUZETzFGQlJVUXNUMEZCVHl4SlFVRkpMRU5CUVVNc1RVRkJUU3hEUVVGRExFbEJRVWtzUlVGQlJTeFhRVUZYTEVOQlFVTXNRMEZCUXp0SlFVTXhReXhEUVVGRE8wbEJRVUVzUTBGQlF6dEpRVWRHTEhOQ1FVRkhMRWRCUVVnN1VVRkRTU3hKUVVGSkxFZEJRVWNzUjBGQlJ5eEpRVUZKTEVOQlFVTXNTMEZCU3l4RFFVRkRPMUZCUTNKQ0xFbEJRVWtzUjBGQlJ5eExRVUZMTEVsQlFVa3NSVUZCUlR0WlFVTmtMRTlCUVU4c1NVRkJTU3hEUVVGRE8xTkJRMlk3VVVGRlJDeFBRVUZQTEVkQlFVY3NRMEZCUXl4SlFVRkpMRXRCUVVzc1NVRkJTU3hGUVVGRk8xbEJRM1JDTEVkQlFVY3NSMEZCUnl4SFFVRkhMRU5CUVVNc1NVRkJTU3hEUVVGRE8xTkJRMnhDTzFGQlJVUXNUMEZCVHl4SFFVRkhMRU5CUVVNc1NVRkJTU3hEUVVGRE8wbEJRM0JDTEVOQlFVTTdTVUZCUVN4RFFVRkRPMGxCUjBZc2MwSkJRVWNzUjBGQlNEdFJRVU5KTEVsQlFVa3NSMEZCUnl4SFFVRkhMRWxCUVVrc1EwRkJReXhMUVVGTExFTkJRVU03VVVGRGNrSXNTVUZCU1N4SFFVRkhMRXRCUVVzc1NVRkJTU3hGUVVGRk8xbEJRMlFzVDBGQlR5eEpRVUZKTEVOQlFVTTdVMEZEWmp0UlFVVkVMRTlCUVU4c1IwRkJSeXhEUVVGRExFdEJRVXNzUzBGQlN5eEpRVUZKTEVWQlFVVTdXVUZEZGtJc1IwRkJSeXhIUVVGSExFZEJRVWNzUTBGQlF5eExRVUZMTEVOQlFVTTdVMEZEYmtJN1VVRkZSQ3hQUVVGUExFZEJRVWNzUTBGQlF5eEpRVUZKTEVOQlFVTTdTVUZEY0VJc1EwRkJRenRKUVVGQkxFTkJRVU03U1VGSlJpd3lRa0ZCVVN4SFFVRlNPMUZCUTBrc1QwRkJUeXhKUVVGSkxGRkJRVkVzUTBGQlF5eEpRVUZKTEVOQlFVTXNRMEZCUXp0SlFVTTVRaXhEUVVGRE8wbEJRVUVzUTBGQlF6dEpRVWRHTEhWQ1FVRkpMRWRCUVVvc1ZVRkJTeXhGUVVGRk8xRkJRMGdzU1VGQlNTeEZRVUZGTEVkQlFVY3NTVUZCU1N4RFFVRkRMRkZCUVZFc1JVRkJSU3hGUVVGRkxFbEJRVWtzUTBGQlF6dFJRVU12UWl4UFFVRlBMRU5CUVVNc1NVRkJTU3hIUVVGSExFVkJRVVVzUTBGQlF5eEpRVUZKTEVWQlFVVXNRMEZCUXl4TFFVRkxMRWxCUVVrc1JVRkJSVHRaUVVOb1F5eEZRVUZGTEVOQlFVTXNTVUZCU1N4RFFVRkRMRU5CUVVNN1UwRkRXanRKUVVOTUxFTkJRVU03U1VGQlFTeERRVUZETzBsQlIwWXNkMEpCUVVzc1IwRkJUQ3hWUVVGTkxFVkJRVVU3VVVGRFNpeEpRVUZKTEVWQlFVVXNSMEZCUnl4SlFVRkpMRU5CUVVNc1VVRkJVU3hGUVVGRkxFVkJRVVVzU1VGQlNTeERRVUZETzFGQlF5OUNMRTlCUVU4c1EwRkJReXhKUVVGSkxFZEJRVWNzUlVGQlJTeERRVUZETEVsQlFVa3NSVUZCUlN4RFFVRkRMRXRCUVVzc1NVRkJTU3hGUVVGRk8xbEJRMmhETEVWQlFVVXNRMEZCUXl4SlFVRkpMRU5CUVVNc1EwRkJRenRUUVVOYU8wbEJRMHdzUTBGQlF6dEpRVUZCTEVOQlFVTTdTVUZIUml4NVFrRkJUU3hIUVVGT0xGVkJRVThzU1VGQlNTeEZRVUZGTEVkQlFVYzdVVUZEV2l4SlFVRkpMRWRCUVVjc1IwRkJSeXhKUVVGSkxFTkJRVU1zUzBGQlN5eERRVUZETzFGQlEzSkNMRWxCUVVrc1NVRkJTU3hIUVVGSExFbEJRVWtzUTBGQlF5eFJRVUZSTEVWQlFVVXNRMEZCUXp0UlFVVXpRaXhQUVVGUExFZEJRVWNzUzBGQlN5eEpRVUZKTEVWQlFVVTdXVUZEYWtJc1NVRkJTU3hEUVVGRExFZEJRVWNzU1VGQlNTeERRVUZETEZkQlFWY3NRMEZCUXl4SlFVRkpMRVZCUVVVc1IwRkJSeXhEUVVGRExFbEJRVWtzUTBGQlF5eERRVUZETzFsQlEzcERMRWxCUVVrc1EwRkJReXhMUVVGTExFTkJRVU1zUlVGQlJUdG5Ra0ZEVkN4SlFVRkpMRU5CUVVNc1QwRkJUeXhIUVVGSExFZEJRVWNzUTBGQlF6dG5Ra0ZEYmtJc1QwRkJUeXhKUVVGSkxFTkJRVU03WVVGRFpqdFpRVU5FTEVsQlFVa3NRMEZCUXl4VlFVRlZMRU5CUVVNc1NVRkJTU3hEUVVGRExFZEJRVWNzUTBGQlF5eERRVUZETzFsQlF6RkNMRWRCUVVjc1IwRkJSeXhIUVVGSExFTkJRVU1zVTBGQlV5eERRVUZETEVOQlFVTXNSMEZCUnl4RFFVRkRMRU5CUVVNc1EwRkJRenRUUVVNNVFqdFJRVVZFTEV0QlFVc3NTVUZCU1N4RFFVRkRMRWRCUVVjc1NVRkJTU3hEUVVGRExGVkJRVlVzUTBGQlF5eE5RVUZOTEVkQlFVY3NRMEZCUXl4RlFVRkZMRU5CUVVNc1NVRkJTU3hEUVVGRExFVkJRVVVzUlVGQlJTeERRVUZETEVWQlFVVTdXVUZEYkVRc1IwRkJSeXhIUVVGSExFbEJRVWtzUTBGQlF5eFZRVUZWTEVOQlFVTXNRMEZCUXl4RFFVRkRMRU5CUVVNN1dVRkRla0lzU1VGQlNTeEhRVUZITEVOQlFVTXNTVUZCU1N4RlFVRkZMRWRCUVVjc1EwRkJReXhKUVVGSkxFTkJRVU1zUjBGQlJ5eERRVUZETEVWQlFVVTdaMEpCUTNwQ0xFbEJRVWtzUTBGQlF5eFBRVUZQTEVkQlFVY3NSMEZCUnl4RFFVRkRPMmRDUVVOdVFpeEpRVUZKTEVOQlFVTXNWVUZCVlN4RFFVRkRMRTFCUVUwc1IwRkJSeXhEUVVGRExFTkJRVU03WjBKQlF6TkNMRTlCUVU4c1NVRkJTU3hEUVVGRE8yRkJRMlk3VTBGRFNqdFJRVVZFTEVsQlFVa3NRMEZCUXl4VlFVRlZMRU5CUVVNc1RVRkJUU3hIUVVGSExFTkJRVU1zUTBGQlF6dFJRVU16UWl4UFFVRlBMRWxCUVVrc1EwRkJRenRKUVVOb1FpeERRVUZETzBsQlFVRXNRMEZCUXp0SlFVTk9MR1ZCUVVNN1FVRkJSQ3hEUVVGRExFRkJOVWxFTEVsQk5FbERPMEZCTlVsWkxEUkNRVUZSTzBGQk5rbHlRanRKUVVsSkxHdENRVUZaTEVsQlFVazdVVUZEV2l4SlFVRkpMRU5CUVVNc1MwRkJTeXhIUVVGSExFbEJRVWtzUTBGQlF6dFJRVU5zUWl4SlFVRkpMRU5CUVVNc1ZVRkJWU3hIUVVGSExFVkJRVVVzUTBGQlF6dFJRVU55UWl4SlFVRkpMRU5CUVVNc1QwRkJUeXhIUVVGSExFbEJRVWtzUTBGQlF6dEpRVU40UWl4RFFVRkRPMGxCUlVRc2RVSkJRVWtzUjBGQlNqdFJRVU5KTEU5QlFVOHNTVUZCU1N4RFFVRkRMRTlCUVU4c1MwRkJTeXhKUVVGSkxFTkJRVU1zUTBGQlF5eERRVUZETEVsQlFVa3NRMEZCUXl4UFFVRlBMRU5CUVVNc1NVRkJTU3hEUVVGRExFTkJRVU1zUTBGQlF5eEpRVUZKTEVOQlFVTTdTVUZETlVRc1EwRkJRenRKUVVGQkxFTkJRVU03U1VGSlJpeDFRa0ZCU1N4SFFVRktPMUZCUTBrc1NVRkJTU3hKUVVGSkxFTkJRVU1zVDBGQlR5eExRVUZMTEVsQlFVa3NSVUZCUlR0WlFVTjJRaXhKUVVGSkxFbEJRVWtzUjBGQlJ5eEpRVUZKTEVOQlFVTXNTMEZCU3l4RFFVRkRMRXRCUVVzc1EwRkJRenRaUVVNMVFpeEpRVUZKTEVsQlFVa3NTMEZCU3l4SlFVRkpMRVZCUVVVN1owSkJRMllzU1VGQlNTeERRVUZETEZGQlFWRXNRMEZCUXl4SlFVRkpMRU5CUVVNc1EwRkJRenRoUVVOMlFqdFRRVU5LTzJGQlEwazdXVUZEUkN4SlFVRkpMRWxCUVVrc1EwRkJReXhQUVVGUExFTkJRVU1zUzBGQlN5eExRVUZMTEVsQlFVa3NSVUZCUlR0blFrRkhOMElzU1VGQlNTeEpRVUZKTEVOQlFVTTdaMEpCUTFRc1IwRkJSenR2UWtGRFF5eEpRVUZKTEVkQlFVY3NTVUZCU1N4RFFVRkRMRTlCUVU4c1EwRkJRenR2UWtGRGNFSXNTVUZCU1N4SlFVRkpMRU5CUVVNc1ZVRkJWU3hEUVVGRExFMUJRVTBzUlVGQlJUdDNRa0ZEZUVJc1NVRkJTU3hEUVVGRExFOUJRVThzUjBGQlJ5eEpRVUZKTEVOQlFVTXNWVUZCVlN4RFFVRkRMRWRCUVVjc1JVRkJSU3hEUVVGRE8zRkNRVU40UXp0NVFrRkRTVHQzUWtGRFJDeEpRVUZKTEVOQlFVTXNUMEZCVHl4SFFVRkhMRWxCUVVrc1EwRkJRenQzUWtGRGNFSXNUVUZCVFR0eFFrRkRWRHRwUWtGRFNpeFJRVUZSTEVsQlFVa3NRMEZCUXl4UFFVRlBMRU5CUVVNc1MwRkJTeXhMUVVGTExFbEJRVWtzUlVGQlJUdGhRVU42UXp0cFFrRkRTVHRuUWtGRlJDeEpRVUZKTEVOQlFVTXNWVUZCVlN4RFFVRkRMRWxCUVVrc1EwRkJReXhKUVVGSkxFTkJRVU1zVDBGQlR5eERRVUZETEVOQlFVTTdaMEpCUTI1RExFbEJRVWtzUTBGQlF5eFJRVUZSTEVOQlFVTXNTVUZCU1N4RFFVRkRMRTlCUVU4c1EwRkJReXhMUVVGTExFTkJRVU1zUTBGQlF6dGhRVU55UXp0VFFVTktPMUZCUTBRc1QwRkJUeXhKUVVGSkxFTkJRVU1zVDBGQlR5eExRVUZMTEVsQlFVa3NRMEZCUXl4RFFVRkRMRU5CUVVNc1NVRkJTU3hEUVVGRExFOUJRVThzUTBGQlF5eEpRVUZKTEVOQlFVTXNRMEZCUXl4RFFVRkRMRWxCUVVrc1EwRkJRenRKUVVNMVJDeERRVUZETzBsQlFVRXNRMEZCUXp0SlFVbEdMSFZDUVVGSkxFZEJRVW83VVVGRFNTeEpRVUZKTEVsQlFVa3NRMEZCUXl4UFFVRlBMRXRCUVVzc1NVRkJTU3hGUVVGRk8xbEJRM1pDTEVsQlFVa3NTVUZCU1N4SFFVRkhMRWxCUVVrc1EwRkJReXhMUVVGTExFTkJRVU1zUzBGQlN5eERRVUZETzFsQlF6VkNMRWxCUVVrc1NVRkJTU3hMUVVGTExFbEJRVWtzUlVGQlJUdG5Ra0ZEWml4SlFVRkpMRU5CUVVNc1VVRkJVU3hEUVVGRExFbEJRVWtzUTBGQlF5eERRVUZETzJGQlEzWkNPMU5CUTBvN1lVRkRTVHRaUVVORUxFbEJRVWtzU1VGQlNTeERRVUZETEU5QlFVOHNRMEZCUXl4SlFVRkpMRXRCUVVzc1NVRkJTU3hGUVVGRk8yZENRVU0xUWl4SlFVRkpMRWxCUVVrc1EwRkJRenRuUWtGRFZDeEhRVUZITzI5Q1FVTkRMRWxCUVVrc1IwRkJSeXhKUVVGSkxFTkJRVU1zVDBGQlR5eERRVUZETzI5Q1FVTndRaXhKUVVGSkxFbEJRVWtzUTBGQlF5eFZRVUZWTEVOQlFVTXNUVUZCVFN4RlFVRkZPM2RDUVVONFFpeEpRVUZKTEVOQlFVTXNUMEZCVHl4SFFVRkhMRWxCUVVrc1EwRkJReXhWUVVGVkxFTkJRVU1zUjBGQlJ5eEZRVUZGTEVOQlFVTTdjVUpCUTNoRE8zbENRVU5KTzNkQ1FVTkVMRWxCUVVrc1EwRkJReXhQUVVGUExFZEJRVWNzU1VGQlNTeERRVUZETzNkQ1FVTndRaXhOUVVGTk8zRkNRVU5VTzJsQ1FVTktMRkZCUVZFc1NVRkJTU3hEUVVGRExFOUJRVThzUTBGQlF5eEpRVUZKTEV0QlFVc3NTVUZCU1N4RlFVRkZPMkZCUTNoRE8ybENRVU5KTzJkQ1FVTkVMRWxCUVVrc1EwRkJReXhWUVVGVkxFTkJRVU1zU1VGQlNTeERRVUZETEVsQlFVa3NRMEZCUXl4UFFVRlBMRU5CUVVNc1EwRkJRenRuUWtGRGJrTXNTVUZCU1N4RFFVRkRMRkZCUVZFc1EwRkJReXhKUVVGSkxFTkJRVU1zVDBGQlR5eERRVUZETEVsQlFVa3NRMEZCUXl4RFFVRkRPMkZCUTNCRE8xTkJRMG83VVVGRFJDeFBRVUZQTEVsQlFVa3NRMEZCUXl4UFFVRlBMRXRCUVVzc1NVRkJTU3hEUVVGRExFTkJRVU1zUTBGQlF5eEpRVUZKTEVOQlFVTXNUMEZCVHl4RFFVRkRMRWxCUVVrc1EwRkJReXhEUVVGRExFTkJRVU1zU1VGQlNTeERRVUZETzBsQlF6VkVMRU5CUVVNN1NVRkJRU3hEUVVGRE8wbEJSVVlzTWtKQlFWRXNSMEZCVWl4VlFVRlRMRXRCUVVzN1VVRkRWaXhQUVVGUExFdEJRVXNzUTBGQlF5eEpRVUZKTEV0QlFVc3NTVUZCU1N4RlFVRkZPMWxCUTNoQ0xFbEJRVWtzUTBGQlF5eFZRVUZWTEVOQlFVTXNTVUZCU1N4RFFVRkRMRXRCUVVzc1EwRkJReXhEUVVGRE8xbEJRelZDTEV0QlFVc3NSMEZCUnl4TFFVRkxMRU5CUVVNc1NVRkJTU3hEUVVGRE8xTkJRM1JDTzFGQlEwUXNTVUZCU1N4RFFVRkRMRTlCUVU4c1IwRkJSeXhMUVVGTExFTkJRVU03U1VGRGVrSXNRMEZCUXp0SlFVRkJMRU5CUVVNN1NVRkZSaXd5UWtGQlVTeEhRVUZTTEZWQlFWTXNTMEZCU3p0UlFVTldMRTlCUVU4c1MwRkJTeXhEUVVGRExFdEJRVXNzUzBGQlN5eEpRVUZKTEVWQlFVVTdXVUZEZWtJc1NVRkJTU3hEUVVGRExGVkJRVlVzUTBGQlF5eEpRVUZKTEVOQlFVTXNTMEZCU3l4RFFVRkRMRU5CUVVNN1dVRkROVUlzUzBGQlN5eEhRVUZITEV0QlFVc3NRMEZCUXl4TFFVRkxMRU5CUVVNN1UwRkRka0k3VVVGRFJDeEpRVUZKTEVOQlFVTXNUMEZCVHl4SFFVRkhMRXRCUVVzc1EwRkJRenRKUVVONlFpeERRVUZETzBsQlFVRXNRMEZCUXp0SlFVTk9MR1ZCUVVNN1FVRkJSQ3hEUVVGRExFRkJPVVpFTEVsQk9FWkRPMEZCT1VaWkxEUkNRVUZSTzBGQlowZHlRanRKUVV0SkxHTkJRVmtzU1VGQlNUdFJRVU5hTEVsQlFVa3NRMEZCUXl4SlFVRkpMRWRCUVVjc1NVRkJTU3hEUVVGRE8xRkJRMnBDTEVsQlFVa3NRMEZCUXl4SlFVRkpMRWRCUVVjc1NVRkJTU3hEUVVGRE8xRkJRMnBDTEVsQlFVa3NRMEZCUXl4TFFVRkxMRWRCUVVjc1NVRkJTU3hEUVVGRE8xRkJRMnhDTEVsQlFVa3NRMEZCUXl4SFFVRkhMRWRCUVVjc1NVRkJTU3hEUVVGRE8wbEJRM0JDTEVOQlFVTTdTVUZGUkN4M1FrRkJVeXhIUVVGVUxGVkJRVlVzUjBGQlJ6dFJRVU5VTEU5QlFVOHNSMEZCUnl4RFFVRkRMRU5CUVVNc1EwRkJReXhKUVVGSkxFTkJRVU1zUzBGQlN5eERRVUZETEVOQlFVTXNRMEZCUXl4SlFVRkpMRU5CUVVNc1NVRkJTU3hEUVVGRE8wbEJRM2hETEVOQlFVTTdTVUZCUVN4RFFVRkRPMGxCUlVZc2QwSkJRVk1zUjBGQlZDeFZRVUZWTEVkQlFVY3NSVUZCUlN4SFFVRkhPMUZCUTJRc1NVRkJTU3hIUVVGSExFVkJRVVU3V1VGRFRDeEpRVUZKTEVOQlFVTXNTMEZCU3l4SFFVRkhMRWRCUVVjc1EwRkJRenRUUVVOd1FqdGhRVU5KTzFsQlEwUXNTVUZCU1N4RFFVRkRMRWxCUVVrc1IwRkJSeXhIUVVGSExFTkJRVU03VTBGRGJrSTdTVUZEVEN4RFFVRkRPMGxCUVVFc1EwRkJRenRKUVVOT0xGZEJRVU03UVVGQlJDeERRVUZETEVGQmVFSkVMRWxCZDBKRE8wRkJSVVE3U1VGQkswSXNNRUpCUVZFN1NVRkxia01zWjBKQlFWa3NWVUZCYTBNN1VVRkJPVU1zV1VGRFNTeHBRa0ZCVHl4VFFVbFdPMUZCU0Vjc1MwRkJTU3hEUVVGRExFdEJRVXNzUjBGQlJ5eEpRVUZKTEVOQlFVTTdVVUZEYkVJc1MwRkJTU3hEUVVGRExGZEJRVmNzUjBGQlJ5eFZRVUZWTEVOQlFVTTdVVUZET1VJc1MwRkJTU3hEUVVGRExFbEJRVWtzUjBGQlJ5eERRVUZETEVOQlFVTTdPMGxCUTJ4Q0xFTkJRVU03U1VGSFJDeDFRa0ZCVFN4SFFVRk9MRlZCUVU4c1NVRkJTVHRSUVVOUUxFbEJRVWtzUjBGQlJ5eEhRVUZITEV0QlFVc3NRMEZCUXp0UlFVVm9RaXhKUVVGSkxFbEJRVWtzUTBGQlF5eExRVUZMTEV0QlFVc3NTVUZCU1N4RlFVRkZPMWxCUlhKQ0xFbEJRVWtzUTBGQlF5eExRVUZMTEVkQlFVY3NTVUZCU1N4SlFVRkpMRU5CUVVNc1NVRkJTU3hEUVVGRExFTkJRVU03V1VGRE5VSXNSMEZCUnl4SFFVRkhMRWxCUVVrc1EwRkJRenRaUVVOWUxFbEJRVWtzUTBGQlF5eEpRVUZKTEVWQlFVVXNRMEZCUXp0VFFVTm1PMkZCUTBrN1dVRkRSQ3hKUVVGSkxFbEJRVWtzUjBGQlJ5eEpRVUZKTEVsQlFVa3NRMEZCUXl4VFFVRlRMRU5CUVVNc1EwRkJRenRaUVVVdlFpeEpRVUZKTEVkQlFVY3NSMEZCUnl4TFFVRkxMRU5CUVVNN1dVRkRhRUlzU1VGQlNTeEpRVUZKTEVkQlFVY3NTMEZCU3l4RFFVRkRPMWxCUjJwQ0xFbEJRVWtzUlVGQlJTeEhRVUZITEVsQlFVa3NRMEZCUXp0WlFVTmtMRWxCUVVrc1IwRkJSeXhIUVVGSExFbEJRVWtzUTBGQlF6dFpRVU5tTEVsQlFVa3NRMEZCUXl4SFFVRkhMRWxCUVVrc1EwRkJRenRaUVVOaUxFbEJRVWtzU1VGQlNTeEhRVUZITEVsQlFVa3NRMEZCUXl4TFFVRkxMRU5CUVVNN1dVRkRkRUlzUjBGQlJ5eERRVUZETEV0QlFVc3NSMEZCUnl4SlFVRkpMRU5CUVVNc1MwRkJTeXhEUVVGRE8xbEJSM1pDTEU5QlFVOHNTVUZCU1N4RlFVRkZPMmRDUVVOVUxFbEJRVWtzU1VGQlNTeExRVUZMTEVsQlFVa3NSVUZCUlR0dlFrRkZaaXhKUVVGSkxFZEJRVWNzU1VGQlNTeEpRVUZKTEVOQlFVTXNTVUZCU1N4RFFVRkRMRU5CUVVNN2IwSkJRM1JDTEVOQlFVTXNRMEZCUXl4VFFVRlRMRU5CUVVNc1IwRkJSeXhGUVVGRkxFbEJRVWtzUTBGQlF5eERRVUZETzI5Q1FVTjJRaXhIUVVGSExFZEJRVWNzU1VGQlNTeERRVUZETzI5Q1FVTllMRWxCUVVrc1EwRkJReXhKUVVGSkxFVkJRVVVzUTBGQlF6dHBRa0ZEWmp0eFFrRkRTU3hKUVVGSkxFMUJRVTBzUTBGQlF5eE5RVUZOTEVOQlFVTXNTVUZCU1N4RFFVRkRMRWxCUVVrc1EwRkJReXhKUVVGSkxFMUJRVTBzUTBGQlF5eE5RVUZOTEVOQlFVTXNTVUZCU1N4RFFVRkRMRXRCUVVzc1EwRkJReXhGUVVGRk8yOUNRVVUxUkN4SlFVRkpMRU5CUVVNc1IwRkJSeXhIUVVGSExFbEJRVWtzUTBGQlF6dHZRa0ZEYUVJc1NVRkJTU3hEUVVGRExFbEJRVWtzUTBGQlF5eEhRVUZITEVkQlFVY3NTMEZCU3l4RFFVRkRPMjlDUVVOMFFpeEpRVUZKTEVOQlFVTXNTMEZCU3l4RFFVRkRMRWRCUVVjc1IwRkJSeXhMUVVGTExFTkJRVU03YVVKQlF6RkNPMmRDUVVkRUxFbEJRVWtzVFVGQlRTeERRVUZETEUxQlFVMHNRMEZCUXl4SlFVRkpMRU5CUVVNc1NVRkJTU3hOUVVGTkxFTkJRVU1zVFVGQlRTeERRVUZETEVOQlFVTXNRMEZCUXl4RlFVRkZPMjlDUVVONlF5eEpRVUZKTEVsQlFVa3NSMEZCUnl4SFFVRkhMRU5CUVVNc1MwRkJTeXhMUVVGTExFVkJRVVVzUTBGQlF6dHZRa0ZGTlVJc1NVRkJTU3hKUVVGSkxFdEJRVXNzUTBGQlF5eERRVUZETEZOQlFWTXNRMEZCUXl4SlFVRkpMRU5CUVVNc1JVRkJSVHQzUWtGRE5VSXNSMEZCUnl4RFFVRkRMRk5CUVZNc1EwRkJReXhKUVVGSkxFVkJRVVVzVFVGQlRTeERRVUZETEdGQlFXRXNRMEZCUXl4RlFVRkZMRVZCUVVVc1EwRkJReXhKUVVGSkxFTkJRVU1zUTBGQlF5eERRVUZETzNGQ1FVTjRSRHQ1UWtGRFNUdDNRa0ZEUkN4SFFVRkhMRU5CUVVNc1UwRkJVeXhEUVVGRExFbEJRVWtzUlVGQlJTeE5RVUZOTEVOQlFVTXNZVUZCWVN4RFFVRkRMRVZCUVVVc1JVRkJSU3hEUVVGRExFbEJRVWtzUTBGQlF5eERRVUZETEVOQlFVTTdjVUpCUTNoRU8ybENRVU5LTzJkQ1FVVkVMRWxCUVVrc1IwRkJSeXhIUVVGSExFbEJRVWtzUTBGQlF5eFhRVUZYTEVOQlFVTXNTVUZCU1N4RFFVRkRMRWxCUVVrc1JVRkJSU3hKUVVGSkxFTkJRVU1zUTBGQlF6dG5Ra0ZITlVNc1NVRkJTU3hIUVVGSExFdEJRVXNzUTBGQlF5eEZRVUZGTzI5Q1FVTllMRTFCUVUwN2FVSkJRMVE3WjBKQlJVUXNTVUZCU1N4SFFVRkhMRWRCUVVjc1EwRkJRenRuUWtGRFdDeEhRVUZITEVkQlFVY3NSMEZCUnl4SFFVRkhMRU5CUVVNc1EwRkJRenRuUWtGSFpDeEpRVUZKTEVWQlFVVXNTMEZCU3l4SlFVRkpMRVZCUVVVN2IwSkJRMklzUjBGQlJ5eEhRVUZITEVWQlFVVXNRMEZCUXp0cFFrRkRXanRuUWtGRFJDeEZRVUZGTEVkQlFVY3NRMEZCUXl4RFFVRkRPMmRDUVVOUUxFTkJRVU1zUjBGQlJ5eEpRVUZKTEVOQlFVTTdaMEpCUTFRc1NVRkJTU3hIUVVGSExFbEJRVWtzUTBGQlF5eFRRVUZUTEVOQlFVTXNSMEZCUnl4RFFVRkRMRU5CUVVNN1lVRkRPVUk3V1VGSFJDeEpRVUZKTEVOQlFVTXNTMEZCU3l4SFFVRkhMRWxCUVVrc1EwRkJReXhMUVVGTExFTkJRVU03VTBGRE0wSTdVVUZIUkN4SlFVRkpMRU5CUVVNc1MwRkJTeXhEUVVGRExFZEJRVWNzUjBGQlJ5eExRVUZMTEVOQlFVTTdVVUZGZGtJc1QwRkJUeXhIUVVGSExFTkJRVU03U1VGRFppeERRVUZETzBsQlFVRXNRMEZCUXp0SlFVZEdMSFZDUVVGTkxFZEJRVTRzVlVGQlR5eEpRVUZKTzFGQlExQXNTVUZCU1N4SlFVRkpMRU5CUVVNc1MwRkJTeXhMUVVGTExFbEJRVWtzUlVGQlJUdFpRVU55UWl4UFFVRlBMRXRCUVVzc1EwRkJRenRUUVVOb1FqdFJRVVZFTEVsQlFVa3NTVUZCU1N4SFFVRkhMRWxCUVVrc1NVRkJTU3hEUVVGRExGTkJRVk1zUTBGQlF5eERRVUZETzFGQlF5OUNMRWxCUVVrc1NVRkJTU3hIUVVGSExFbEJRVWtzUTBGQlF6dFJRVU5vUWl4SlFVRkpMRU5CUVVNc1MwRkJTeXhIUVVGSExFbEJRVWtzUTBGQlF5eExRVUZMTEVOQlFVTTdVVUZEZUVJc1NVRkJTU3hEUVVGRExFZEJRVWNzU1VGQlNTeERRVUZETzFGQlEySXNTVUZCU1N4RlFVRkZMRWRCUVVjc1NVRkJTU3hEUVVGRE8xRkJRMlFzU1VGQlNTeExRVUZMTEVkQlFVY3NTVUZCU1N4RFFVRkRPMUZCUTJwQ0xFbEJRVWtzUjBGQlJ5eEhRVUZITEVsQlFVa3NRMEZCUXp0UlFVVm1MRTlCUVU4c1NVRkJTU3hEUVVGRExGTkJRVk1zUTBGQlF5eEhRVUZITEVOQlFVTXNTMEZCU3l4SlFVRkpMRVZCUVVVN1dVRkRha01zU1VGQlNTeEpRVUZKTEVkQlFVY3NSMEZCUnl4RFFVRkRPMWxCUjJZc1JVRkJSU3hIUVVGSExFTkJRVU1zUTBGQlF6dFpRVU5RTEVOQlFVTXNSMEZCUnl4SlFVRkpMRU5CUVVNN1dVRkRWQ3hKUVVGSkxFZEJRVWNzU1VGQlNTeERRVUZETEZOQlFWTXNRMEZCUXl4SFFVRkhMRU5CUVVNc1EwRkJRenRaUVVVelFpeEpRVUZKTEVkQlFVY3NSMEZCUnl4SlFVRkpMRU5CUVVNc1YwRkJWeXhEUVVGRExFbEJRVWtzUlVGQlJTeEpRVUZKTEVOQlFVTXNTVUZCU1N4RFFVRkRMRU5CUVVNN1dVRkZOVU1zUjBGQlJ5eEhRVUZITEVkQlFVY3NSMEZCUnl4RFFVRkRMRU5CUVVNN1dVRkhaQ3hKUVVGSkxFZEJRVWNzUzBGQlN5eERRVUZETEVWQlFVVTdaMEpCUTFnc1MwRkJTeXhIUVVGSExFbEJRVWtzUTBGQlF6dGhRVU5vUWp0WlFVZEVMRWxCUVVrc1EwRkJReXhOUVVGTkxFTkJRVU1zVFVGQlRTeERRVUZETEVsQlFVa3NRMEZCUXl4SlFVRkpMRU5CUVVNc1RVRkJUU3hEUVVGRExFMUJRVTBzUTBGQlF5eEpRVUZKTEVOQlFVTXNVMEZCVXl4RFFVRkRMRWRCUVVjc1EwRkJReXhEUVVGRExFVkJRVVU3WjBKQlF6ZEVMRWxCUVVrc1RVRkJUU3hEUVVGRExFMUJRVTBzUTBGQlF5eEpRVUZKTEVOQlFVTXNVMEZCVXl4RFFVRkRMRU5CUVVNc1IwRkJSeXhEUVVGRExFTkJRVU1zUlVGQlJUdHZRa0ZEY2tNc1NVRkJTU3hGUVVGRkxFZEJRVWNzVFVGQlRTeERRVUZETEdGQlFXRXNRMEZCUXl4SlFVRkpMRVZCUVVVc1IwRkJSeXhEUVVGRExFTkJRVU03YjBKQlEzcERMRU5CUVVNc1EwRkJReXhUUVVGVExFTkJRVU1zU1VGQlNTeEZRVUZGTEVWQlFVVXNRMEZCUXl4RFFVRkRPMjlDUVVOMFFpeERRVUZETEVkQlFVY3NSVUZCUlN4RFFVRkRPMmxDUVVOV08zRkNRVU5KTEVsQlFVa3NRMEZCUXl4TlFVRk5MRU5CUVVNc1RVRkJUU3hEUVVGRExFbEJRVWtzUTBGQlF5eFRRVUZUTEVOQlFVTXNRMEZCUXl4SFFVRkhMRU5CUVVNc1EwRkJReXhGUVVGRk8yOUNRVU16UXl4SlFVRkpMRTlCUVU4c1IwRkJSeXhEUVVGRExFTkJRVU1zVTBGQlV5eERRVUZETEVOQlFVTXNTVUZCU1N4RFFVRkRMRU5CUVVNN2IwSkJRMnBETEVsQlFVa3NUMEZCVHl4TFFVRkxMRWxCUVVrc1JVRkJSVHQzUWtGRGJFSXNTVUZCU1N4RFFVRkRMRTFCUVUwc1EwRkJReXhOUVVGTkxFTkJRVU1zVDBGQlR5eERRVUZETEZOQlFWTXNRMEZCUXl4RFFVRkRMRWxCUVVrc1EwRkJReXhEUVVGRExFbEJRVWtzUTBGQlF5eE5RVUZOTEVOQlFVTXNUVUZCVFN4RFFVRkRMRTlCUVU4c1EwRkJReXhUUVVGVExFTkJRVU1zU1VGQlNTeERRVUZETEVOQlFVTXNSVUZCUlRzMFFrRkZja1lzUTBGQlF5eERRVUZETEVkQlFVY3NSMEZCUnl4TFFVRkxMRU5CUVVNN05FSkJRMlFzVDBGQlR5eERRVUZETEVkQlFVY3NSMEZCUnl4SlFVRkpMRU5CUVVNN05FSkJRMjVDTEVsQlFVa3NRMEZCUXl4SFFVRkhMRWRCUVVjc1NVRkJTU3hEUVVGRE8zbENRVU51UWpzMlFrRkRTVHMwUWtGRFJDeEpRVUZKTEVsQlFVa3NSMEZCUnl4RlFVRkZMRU5CUVVNc1MwRkJTeXhMUVVGTExFTkJRVU1zUTBGQlF6czBRa0ZGTVVJc1NVRkJTU3hOUVVGTkxFTkJRVU1zVFVGQlRTeERRVUZETEU5QlFVOHNRMEZCUXl4VFFVRlRMRU5CUVVNc1NVRkJTU3hEUVVGRExFTkJRVU1zUlVGQlJUdG5RMEZEZUVNc1JVRkJSU3hEUVVGRExGTkJRVk1zUTBGQlF5eEpRVUZKTEVWQlFVVXNUVUZCVFN4RFFVRkRMR0ZCUVdFc1EwRkJReXhEUVVGRExFVkJRVVVzU1VGQlNTeERRVUZETEVOQlFVTXNRMEZCUXpzMlFrRkRja1E3YVVOQlEwa3NTVUZCU1N4TlFVRk5MRU5CUVVNc1RVRkJUU3hEUVVGRExFOUJRVThzUTBGQlF5eFRRVUZUTEVOQlFVTXNRMEZCUXl4SlFVRkpMRU5CUVVNc1EwRkJReXhGUVVGRk8yZERRVU01UXl4RlFVRkZMRU5CUVVNc1UwRkJVeXhEUVVGRExFbEJRVWtzUlVGQlJTeE5RVUZOTEVOQlFVTXNZVUZCWVN4RFFVRkRMRU5CUVVNc1JVRkJSU3hKUVVGSkxFTkJRVU1zUTBGQlF5eERRVUZET3paQ1FVTnlSRHMwUWtGSFJDeEpRVUZKTEVkQlFVY3NSMEZCUnl4RlFVRkZMRU5CUVVNc1UwRkJVeXhEUVVGRExFbEJRVWtzUTBGQlF5eERRVUZET3pSQ1FVTTNRaXhIUVVGSExFTkJRVU1zUjBGQlJ5eEhRVUZITEVsQlFVa3NRMEZCUXpzMFFrRkRaaXhKUVVGSkxFTkJRVU1zUjBGQlJ5eEhRVUZITEVsQlFVa3NRMEZCUXpzMFFrRkRhRUlzUjBGQlJ5eERRVUZETEVsQlFVa3NRMEZCUXl4SFFVRkhMRWRCUVVjc1MwRkJTeXhEUVVGRE96UkNRVU55UWl4SFFVRkhMRU5CUVVNc1MwRkJTeXhEUVVGRExFZEJRVWNzUjBGQlJ5eExRVUZMTEVOQlFVTTdlVUpCUTNwQ08zRkNRVU5LTzJsQ1FVTktPMkZCUTBvN1UwRkRTanRSUVVkRUxFbEJRVWtzUzBGQlN5eExRVUZMTEVsQlFVa3NSVUZCUlR0WlFVTm9RaXhMUVVGTExFTkJRVU1zU1VGQlNTeEhRVUZITEVsQlFVa3NRMEZCUXl4SlFVRkpMRU5CUVVNN1dVRkRka0lzUTBGQlF5eERRVUZETEZOQlFWTXNRMEZCUXl4RFFVRkRMRU5CUVVNc1MwRkJTeXhMUVVGTExFbEJRVWtzUlVGQlJTeEpRVUZKTEVOQlFVTXNVMEZCVXl4RFFVRkRMRWxCUVVrc1EwRkJReXhKUVVGSkxFdEJRVXNzU1VGQlNTeERRVUZETEVOQlFVTXNRMEZCUXp0WlFVTnNSU3hKUVVGSkxFTkJRVU1zU1VGQlNTeEZRVUZGTEVOQlFVTTdVMEZEWmp0UlFVZEVMRWxCUVVrc1EwRkJReXhMUVVGTExFZEJRVWNzU1VGQlNTeERRVUZETEV0QlFVc3NRMEZCUXp0UlFVTjRRaXhKUVVGSkxFbEJRVWtzUTBGQlF5eExRVUZMTEV0QlFVc3NTVUZCU1N4RlFVRkZPMWxCUTNKQ0xFbEJRVWtzUTBGQlF5eExRVUZMTEVOQlFVTXNSMEZCUnl4SFFVRkhMRXRCUVVzc1EwRkJRenRUUVVNeFFqdFJRVVZFTEU5QlFVOHNTMEZCU3l4TFFVRkxMRWxCUVVrc1EwRkJRenRKUVVNeFFpeERRVUZETzBsQlFVRXNRMEZCUXp0SlFVVkxMR0ZCUVUwc1IwRkJZaXhWUVVGakxFbEJRVWs3VVVGRFpDeFBRVUZQTEVsQlFVa3NTMEZCU3l4SlFVRkpMRWxCUVVrc1NVRkJTU3hEUVVGRExFZEJRVWNzUTBGQlF6dEpRVU55UXl4RFFVRkRPMGxCUlUwc2IwSkJRV0VzUjBGQmNFSXNWVUZCY1VJc1NVRkJTU3hGUVVGRkxFZEJRVWM3VVVGRE1VSXNTVUZCU1N4SlFVRkpMRWRCUVVjc1NVRkJTU3hEUVVGRExGTkJRVk1zUTBGQlF5eERRVUZETEVkQlFVY3NRMEZCUXl4RFFVRkRPMUZCUldoRExFbEJRVWtzUTBGQlF5eFRRVUZUTEVOQlFVTXNRMEZCUXl4SFFVRkhMRVZCUVVVc1NVRkJTU3hEUVVGRExGTkJRVk1zUTBGQlF5eEhRVUZITEVOQlFVTXNRMEZCUXl4RFFVRkRPMUZCUXpGRExFbEJRVWtzUTBGQlF5eFRRVUZUTEVOQlFVTXNSMEZCUnl4RlFVRkZMRWxCUVVrc1EwRkJReXhEUVVGRE8xRkJSVEZDTEVsQlFVa3NRMEZCUXl4SFFVRkhMRWRCUVVjc1NVRkJTU3hEUVVGRE8xRkJRMmhDTEVsQlFVa3NRMEZCUXl4SFFVRkhMRWRCUVVjc1MwRkJTeXhEUVVGRE8xRkJSV3BDTEU5QlFVOHNTVUZCU1N4RFFVRkRPMGxCUTJoQ0xFTkJRVU03U1VGRlRTeHZRa0ZCWVN4SFFVRndRaXhWUVVGeFFpeEpRVUZKTEVWQlFVVXNSMEZCUnp0UlFVTXhRaXhKUVVGSkxFTkJRVU1zVTBGQlV5eERRVUZETEVOQlFVTXNSMEZCUnl4RlFVRkZMRTFCUVUwc1EwRkJReXhoUVVGaExFTkJRVU1zU1VGQlNTeERRVUZETEZOQlFWTXNRMEZCUXl4RFFVRkRMRWRCUVVjc1EwRkJReXhGUVVGRkxFTkJRVU1zUjBGQlJ5eERRVUZETEVOQlFVTXNRMEZCUXp0UlFVTjJSU3hQUVVGUExFMUJRVTBzUTBGQlF5eGhRVUZoTEVOQlFVTXNTVUZCU1N4RlFVRkZMRWRCUVVjc1EwRkJReXhEUVVGRE8wbEJRek5ETEVOQlFVTTdTVUZEVEN4aFFVRkRPMEZCUVVRc1EwRkJReXhCUVhKTlJDeERRVUVyUWl4UlFVRlJMRWRCY1UxMFF6dEJRWEpOV1N4M1FrRkJUU0o5IiwiXCJ1c2Ugc3RyaWN0XCI7XG52YXIgX19leHRlbmRzID0gKHRoaXMgJiYgdGhpcy5fX2V4dGVuZHMpIHx8IChmdW5jdGlvbiAoKSB7XG4gICAgdmFyIGV4dGVuZFN0YXRpY3MgPSBmdW5jdGlvbiAoZCwgYikge1xuICAgICAgICBleHRlbmRTdGF0aWNzID0gT2JqZWN0LnNldFByb3RvdHlwZU9mIHx8XG4gICAgICAgICAgICAoeyBfX3Byb3RvX186IFtdIH0gaW5zdGFuY2VvZiBBcnJheSAmJiBmdW5jdGlvbiAoZCwgYikgeyBkLl9fcHJvdG9fXyA9IGI7IH0pIHx8XG4gICAgICAgICAgICBmdW5jdGlvbiAoZCwgYikgeyBmb3IgKHZhciBwIGluIGIpIGlmIChiLmhhc093blByb3BlcnR5KHApKSBkW3BdID0gYltwXTsgfTtcbiAgICAgICAgcmV0dXJuIGV4dGVuZFN0YXRpY3MoZCwgYik7XG4gICAgfTtcbiAgICByZXR1cm4gZnVuY3Rpb24gKGQsIGIpIHtcbiAgICAgICAgZXh0ZW5kU3RhdGljcyhkLCBiKTtcbiAgICAgICAgZnVuY3Rpb24gX18oKSB7IHRoaXMuY29uc3RydWN0b3IgPSBkOyB9XG4gICAgICAgIGQucHJvdG90eXBlID0gYiA9PT0gbnVsbCA/IE9iamVjdC5jcmVhdGUoYikgOiAoX18ucHJvdG90eXBlID0gYi5wcm90b3R5cGUsIG5ldyBfXygpKTtcbiAgICB9O1xufSkoKTtcbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCBcIl9fZXNNb2R1bGVcIiwgeyB2YWx1ZTogdHJ1ZSB9KTtcbnZhciB2cHNjXzEgPSByZXF1aXJlKFwiLi92cHNjXCIpO1xudmFyIHJidHJlZV8xID0gcmVxdWlyZShcIi4vcmJ0cmVlXCIpO1xuZnVuY3Rpb24gY29tcHV0ZUdyb3VwQm91bmRzKGcpIHtcbiAgICBnLmJvdW5kcyA9IHR5cGVvZiBnLmxlYXZlcyAhPT0gXCJ1bmRlZmluZWRcIiA/XG4gICAgICAgIGcubGVhdmVzLnJlZHVjZShmdW5jdGlvbiAociwgYykgeyByZXR1cm4gYy5ib3VuZHMudW5pb24ocik7IH0sIFJlY3RhbmdsZS5lbXB0eSgpKSA6XG4gICAgICAgIFJlY3RhbmdsZS5lbXB0eSgpO1xuICAgIGlmICh0eXBlb2YgZy5ncm91cHMgIT09IFwidW5kZWZpbmVkXCIpXG4gICAgICAgIGcuYm91bmRzID0gZy5ncm91cHMucmVkdWNlKGZ1bmN0aW9uIChyLCBjKSB7IHJldHVybiBjb21wdXRlR3JvdXBCb3VuZHMoYykudW5pb24ocik7IH0sIGcuYm91bmRzKTtcbiAgICBnLmJvdW5kcyA9IGcuYm91bmRzLmluZmxhdGUoZy5wYWRkaW5nKTtcbiAgICByZXR1cm4gZy5ib3VuZHM7XG59XG5leHBvcnRzLmNvbXB1dGVHcm91cEJvdW5kcyA9IGNvbXB1dGVHcm91cEJvdW5kcztcbnZhciBSZWN0YW5nbGUgPSAoZnVuY3Rpb24gKCkge1xuICAgIGZ1bmN0aW9uIFJlY3RhbmdsZSh4LCBYLCB5LCBZKSB7XG4gICAgICAgIHRoaXMueCA9IHg7XG4gICAgICAgIHRoaXMuWCA9IFg7XG4gICAgICAgIHRoaXMueSA9IHk7XG4gICAgICAgIHRoaXMuWSA9IFk7XG4gICAgfVxuICAgIFJlY3RhbmdsZS5lbXB0eSA9IGZ1bmN0aW9uICgpIHsgcmV0dXJuIG5ldyBSZWN0YW5nbGUoTnVtYmVyLlBPU0lUSVZFX0lORklOSVRZLCBOdW1iZXIuTkVHQVRJVkVfSU5GSU5JVFksIE51bWJlci5QT1NJVElWRV9JTkZJTklUWSwgTnVtYmVyLk5FR0FUSVZFX0lORklOSVRZKTsgfTtcbiAgICBSZWN0YW5nbGUucHJvdG90eXBlLmN4ID0gZnVuY3Rpb24gKCkgeyByZXR1cm4gKHRoaXMueCArIHRoaXMuWCkgLyAyOyB9O1xuICAgIFJlY3RhbmdsZS5wcm90b3R5cGUuY3kgPSBmdW5jdGlvbiAoKSB7IHJldHVybiAodGhpcy55ICsgdGhpcy5ZKSAvIDI7IH07XG4gICAgUmVjdGFuZ2xlLnByb3RvdHlwZS5vdmVybGFwWCA9IGZ1bmN0aW9uIChyKSB7XG4gICAgICAgIHZhciB1eCA9IHRoaXMuY3goKSwgdnggPSByLmN4KCk7XG4gICAgICAgIGlmICh1eCA8PSB2eCAmJiByLnggPCB0aGlzLlgpXG4gICAgICAgICAgICByZXR1cm4gdGhpcy5YIC0gci54O1xuICAgICAgICBpZiAodnggPD0gdXggJiYgdGhpcy54IDwgci5YKVxuICAgICAgICAgICAgcmV0dXJuIHIuWCAtIHRoaXMueDtcbiAgICAgICAgcmV0dXJuIDA7XG4gICAgfTtcbiAgICBSZWN0YW5nbGUucHJvdG90eXBlLm92ZXJsYXBZID0gZnVuY3Rpb24gKHIpIHtcbiAgICAgICAgdmFyIHV5ID0gdGhpcy5jeSgpLCB2eSA9IHIuY3koKTtcbiAgICAgICAgaWYgKHV5IDw9IHZ5ICYmIHIueSA8IHRoaXMuWSlcbiAgICAgICAgICAgIHJldHVybiB0aGlzLlkgLSByLnk7XG4gICAgICAgIGlmICh2eSA8PSB1eSAmJiB0aGlzLnkgPCByLlkpXG4gICAgICAgICAgICByZXR1cm4gci5ZIC0gdGhpcy55O1xuICAgICAgICByZXR1cm4gMDtcbiAgICB9O1xuICAgIFJlY3RhbmdsZS5wcm90b3R5cGUuc2V0WENlbnRyZSA9IGZ1bmN0aW9uIChjeCkge1xuICAgICAgICB2YXIgZHggPSBjeCAtIHRoaXMuY3goKTtcbiAgICAgICAgdGhpcy54ICs9IGR4O1xuICAgICAgICB0aGlzLlggKz0gZHg7XG4gICAgfTtcbiAgICBSZWN0YW5nbGUucHJvdG90eXBlLnNldFlDZW50cmUgPSBmdW5jdGlvbiAoY3kpIHtcbiAgICAgICAgdmFyIGR5ID0gY3kgLSB0aGlzLmN5KCk7XG4gICAgICAgIHRoaXMueSArPSBkeTtcbiAgICAgICAgdGhpcy5ZICs9IGR5O1xuICAgIH07XG4gICAgUmVjdGFuZ2xlLnByb3RvdHlwZS53aWR0aCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuWCAtIHRoaXMueDtcbiAgICB9O1xuICAgIFJlY3RhbmdsZS5wcm90b3R5cGUuaGVpZ2h0ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5ZIC0gdGhpcy55O1xuICAgIH07XG4gICAgUmVjdGFuZ2xlLnByb3RvdHlwZS51bmlvbiA9IGZ1bmN0aW9uIChyKSB7XG4gICAgICAgIHJldHVybiBuZXcgUmVjdGFuZ2xlKE1hdGgubWluKHRoaXMueCwgci54KSwgTWF0aC5tYXgodGhpcy5YLCByLlgpLCBNYXRoLm1pbih0aGlzLnksIHIueSksIE1hdGgubWF4KHRoaXMuWSwgci5ZKSk7XG4gICAgfTtcbiAgICBSZWN0YW5nbGUucHJvdG90eXBlLmxpbmVJbnRlcnNlY3Rpb25zID0gZnVuY3Rpb24gKHgxLCB5MSwgeDIsIHkyKSB7XG4gICAgICAgIHZhciBzaWRlcyA9IFtbdGhpcy54LCB0aGlzLnksIHRoaXMuWCwgdGhpcy55XSxcbiAgICAgICAgICAgIFt0aGlzLlgsIHRoaXMueSwgdGhpcy5YLCB0aGlzLlldLFxuICAgICAgICAgICAgW3RoaXMuWCwgdGhpcy5ZLCB0aGlzLngsIHRoaXMuWV0sXG4gICAgICAgICAgICBbdGhpcy54LCB0aGlzLlksIHRoaXMueCwgdGhpcy55XV07XG4gICAgICAgIHZhciBpbnRlcnNlY3Rpb25zID0gW107XG4gICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgNDsgKytpKSB7XG4gICAgICAgICAgICB2YXIgciA9IFJlY3RhbmdsZS5saW5lSW50ZXJzZWN0aW9uKHgxLCB5MSwgeDIsIHkyLCBzaWRlc1tpXVswXSwgc2lkZXNbaV1bMV0sIHNpZGVzW2ldWzJdLCBzaWRlc1tpXVszXSk7XG4gICAgICAgICAgICBpZiAociAhPT0gbnVsbClcbiAgICAgICAgICAgICAgICBpbnRlcnNlY3Rpb25zLnB1c2goeyB4OiByLngsIHk6IHIueSB9KTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gaW50ZXJzZWN0aW9ucztcbiAgICB9O1xuICAgIFJlY3RhbmdsZS5wcm90b3R5cGUucmF5SW50ZXJzZWN0aW9uID0gZnVuY3Rpb24gKHgyLCB5Mikge1xuICAgICAgICB2YXIgaW50cyA9IHRoaXMubGluZUludGVyc2VjdGlvbnModGhpcy5jeCgpLCB0aGlzLmN5KCksIHgyLCB5Mik7XG4gICAgICAgIHJldHVybiBpbnRzLmxlbmd0aCA+IDAgPyBpbnRzWzBdIDogbnVsbDtcbiAgICB9O1xuICAgIFJlY3RhbmdsZS5wcm90b3R5cGUudmVydGljZXMgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiBbXG4gICAgICAgICAgICB7IHg6IHRoaXMueCwgeTogdGhpcy55IH0sXG4gICAgICAgICAgICB7IHg6IHRoaXMuWCwgeTogdGhpcy55IH0sXG4gICAgICAgICAgICB7IHg6IHRoaXMuWCwgeTogdGhpcy5ZIH0sXG4gICAgICAgICAgICB7IHg6IHRoaXMueCwgeTogdGhpcy5ZIH1cbiAgICAgICAgXTtcbiAgICB9O1xuICAgIFJlY3RhbmdsZS5saW5lSW50ZXJzZWN0aW9uID0gZnVuY3Rpb24gKHgxLCB5MSwgeDIsIHkyLCB4MywgeTMsIHg0LCB5NCkge1xuICAgICAgICB2YXIgZHgxMiA9IHgyIC0geDEsIGR4MzQgPSB4NCAtIHgzLCBkeTEyID0geTIgLSB5MSwgZHkzNCA9IHk0IC0geTMsIGRlbm9taW5hdG9yID0gZHkzNCAqIGR4MTIgLSBkeDM0ICogZHkxMjtcbiAgICAgICAgaWYgKGRlbm9taW5hdG9yID09IDApXG4gICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgdmFyIGR4MzEgPSB4MSAtIHgzLCBkeTMxID0geTEgLSB5MywgbnVtYSA9IGR4MzQgKiBkeTMxIC0gZHkzNCAqIGR4MzEsIGEgPSBudW1hIC8gZGVub21pbmF0b3IsIG51bWIgPSBkeDEyICogZHkzMSAtIGR5MTIgKiBkeDMxLCBiID0gbnVtYiAvIGRlbm9taW5hdG9yO1xuICAgICAgICBpZiAoYSA+PSAwICYmIGEgPD0gMSAmJiBiID49IDAgJiYgYiA8PSAxKSB7XG4gICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgIHg6IHgxICsgYSAqIGR4MTIsXG4gICAgICAgICAgICAgICAgeTogeTEgKyBhICogZHkxMlxuICAgICAgICAgICAgfTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gbnVsbDtcbiAgICB9O1xuICAgIFJlY3RhbmdsZS5wcm90b3R5cGUuaW5mbGF0ZSA9IGZ1bmN0aW9uIChwYWQpIHtcbiAgICAgICAgcmV0dXJuIG5ldyBSZWN0YW5nbGUodGhpcy54IC0gcGFkLCB0aGlzLlggKyBwYWQsIHRoaXMueSAtIHBhZCwgdGhpcy5ZICsgcGFkKTtcbiAgICB9O1xuICAgIHJldHVybiBSZWN0YW5nbGU7XG59KCkpO1xuZXhwb3J0cy5SZWN0YW5nbGUgPSBSZWN0YW5nbGU7XG5mdW5jdGlvbiBtYWtlRWRnZUJldHdlZW4oc291cmNlLCB0YXJnZXQsIGFoKSB7XG4gICAgdmFyIHNpID0gc291cmNlLnJheUludGVyc2VjdGlvbih0YXJnZXQuY3goKSwgdGFyZ2V0LmN5KCkpIHx8IHsgeDogc291cmNlLmN4KCksIHk6IHNvdXJjZS5jeSgpIH0sIHRpID0gdGFyZ2V0LnJheUludGVyc2VjdGlvbihzb3VyY2UuY3goKSwgc291cmNlLmN5KCkpIHx8IHsgeDogdGFyZ2V0LmN4KCksIHk6IHRhcmdldC5jeSgpIH0sIGR4ID0gdGkueCAtIHNpLngsIGR5ID0gdGkueSAtIHNpLnksIGwgPSBNYXRoLnNxcnQoZHggKiBkeCArIGR5ICogZHkpLCBhbCA9IGwgLSBhaDtcbiAgICByZXR1cm4ge1xuICAgICAgICBzb3VyY2VJbnRlcnNlY3Rpb246IHNpLFxuICAgICAgICB0YXJnZXRJbnRlcnNlY3Rpb246IHRpLFxuICAgICAgICBhcnJvd1N0YXJ0OiB7IHg6IHNpLnggKyBhbCAqIGR4IC8gbCwgeTogc2kueSArIGFsICogZHkgLyBsIH1cbiAgICB9O1xufVxuZXhwb3J0cy5tYWtlRWRnZUJldHdlZW4gPSBtYWtlRWRnZUJldHdlZW47XG5mdW5jdGlvbiBtYWtlRWRnZVRvKHMsIHRhcmdldCwgYWgpIHtcbiAgICB2YXIgdGkgPSB0YXJnZXQucmF5SW50ZXJzZWN0aW9uKHMueCwgcy55KTtcbiAgICBpZiAoIXRpKVxuICAgICAgICB0aSA9IHsgeDogdGFyZ2V0LmN4KCksIHk6IHRhcmdldC5jeSgpIH07XG4gICAgdmFyIGR4ID0gdGkueCAtIHMueCwgZHkgPSB0aS55IC0gcy55LCBsID0gTWF0aC5zcXJ0KGR4ICogZHggKyBkeSAqIGR5KTtcbiAgICByZXR1cm4geyB4OiB0aS54IC0gYWggKiBkeCAvIGwsIHk6IHRpLnkgLSBhaCAqIGR5IC8gbCB9O1xufVxuZXhwb3J0cy5tYWtlRWRnZVRvID0gbWFrZUVkZ2VUbztcbnZhciBOb2RlID0gKGZ1bmN0aW9uICgpIHtcbiAgICBmdW5jdGlvbiBOb2RlKHYsIHIsIHBvcykge1xuICAgICAgICB0aGlzLnYgPSB2O1xuICAgICAgICB0aGlzLnIgPSByO1xuICAgICAgICB0aGlzLnBvcyA9IHBvcztcbiAgICAgICAgdGhpcy5wcmV2ID0gbWFrZVJCVHJlZSgpO1xuICAgICAgICB0aGlzLm5leHQgPSBtYWtlUkJUcmVlKCk7XG4gICAgfVxuICAgIHJldHVybiBOb2RlO1xufSgpKTtcbnZhciBFdmVudCA9IChmdW5jdGlvbiAoKSB7XG4gICAgZnVuY3Rpb24gRXZlbnQoaXNPcGVuLCB2LCBwb3MpIHtcbiAgICAgICAgdGhpcy5pc09wZW4gPSBpc09wZW47XG4gICAgICAgIHRoaXMudiA9IHY7XG4gICAgICAgIHRoaXMucG9zID0gcG9zO1xuICAgIH1cbiAgICByZXR1cm4gRXZlbnQ7XG59KCkpO1xuZnVuY3Rpb24gY29tcGFyZUV2ZW50cyhhLCBiKSB7XG4gICAgaWYgKGEucG9zID4gYi5wb3MpIHtcbiAgICAgICAgcmV0dXJuIDE7XG4gICAgfVxuICAgIGlmIChhLnBvcyA8IGIucG9zKSB7XG4gICAgICAgIHJldHVybiAtMTtcbiAgICB9XG4gICAgaWYgKGEuaXNPcGVuKSB7XG4gICAgICAgIHJldHVybiAtMTtcbiAgICB9XG4gICAgaWYgKGIuaXNPcGVuKSB7XG4gICAgICAgIHJldHVybiAxO1xuICAgIH1cbiAgICByZXR1cm4gMDtcbn1cbmZ1bmN0aW9uIG1ha2VSQlRyZWUoKSB7XG4gICAgcmV0dXJuIG5ldyByYnRyZWVfMS5SQlRyZWUoZnVuY3Rpb24gKGEsIGIpIHsgcmV0dXJuIGEucG9zIC0gYi5wb3M7IH0pO1xufVxudmFyIHhSZWN0ID0ge1xuICAgIGdldENlbnRyZTogZnVuY3Rpb24gKHIpIHsgcmV0dXJuIHIuY3goKTsgfSxcbiAgICBnZXRPcGVuOiBmdW5jdGlvbiAocikgeyByZXR1cm4gci55OyB9LFxuICAgIGdldENsb3NlOiBmdW5jdGlvbiAocikgeyByZXR1cm4gci5ZOyB9LFxuICAgIGdldFNpemU6IGZ1bmN0aW9uIChyKSB7IHJldHVybiByLndpZHRoKCk7IH0sXG4gICAgbWFrZVJlY3Q6IGZ1bmN0aW9uIChvcGVuLCBjbG9zZSwgY2VudGVyLCBzaXplKSB7IHJldHVybiBuZXcgUmVjdGFuZ2xlKGNlbnRlciAtIHNpemUgLyAyLCBjZW50ZXIgKyBzaXplIC8gMiwgb3BlbiwgY2xvc2UpOyB9LFxuICAgIGZpbmROZWlnaGJvdXJzOiBmaW5kWE5laWdoYm91cnNcbn07XG52YXIgeVJlY3QgPSB7XG4gICAgZ2V0Q2VudHJlOiBmdW5jdGlvbiAocikgeyByZXR1cm4gci5jeSgpOyB9LFxuICAgIGdldE9wZW46IGZ1bmN0aW9uIChyKSB7IHJldHVybiByLng7IH0sXG4gICAgZ2V0Q2xvc2U6IGZ1bmN0aW9uIChyKSB7IHJldHVybiByLlg7IH0sXG4gICAgZ2V0U2l6ZTogZnVuY3Rpb24gKHIpIHsgcmV0dXJuIHIuaGVpZ2h0KCk7IH0sXG4gICAgbWFrZVJlY3Q6IGZ1bmN0aW9uIChvcGVuLCBjbG9zZSwgY2VudGVyLCBzaXplKSB7IHJldHVybiBuZXcgUmVjdGFuZ2xlKG9wZW4sIGNsb3NlLCBjZW50ZXIgLSBzaXplIC8gMiwgY2VudGVyICsgc2l6ZSAvIDIpOyB9LFxuICAgIGZpbmROZWlnaGJvdXJzOiBmaW5kWU5laWdoYm91cnNcbn07XG5mdW5jdGlvbiBnZW5lcmF0ZUdyb3VwQ29uc3RyYWludHMocm9vdCwgZiwgbWluU2VwLCBpc0NvbnRhaW5lZCkge1xuICAgIGlmIChpc0NvbnRhaW5lZCA9PT0gdm9pZCAwKSB7IGlzQ29udGFpbmVkID0gZmFsc2U7IH1cbiAgICB2YXIgcGFkZGluZyA9IHJvb3QucGFkZGluZywgZ24gPSB0eXBlb2Ygcm9vdC5ncm91cHMgIT09ICd1bmRlZmluZWQnID8gcm9vdC5ncm91cHMubGVuZ3RoIDogMCwgbG4gPSB0eXBlb2Ygcm9vdC5sZWF2ZXMgIT09ICd1bmRlZmluZWQnID8gcm9vdC5sZWF2ZXMubGVuZ3RoIDogMCwgY2hpbGRDb25zdHJhaW50cyA9ICFnbiA/IFtdXG4gICAgICAgIDogcm9vdC5ncm91cHMucmVkdWNlKGZ1bmN0aW9uIChjY3MsIGcpIHsgcmV0dXJuIGNjcy5jb25jYXQoZ2VuZXJhdGVHcm91cENvbnN0cmFpbnRzKGcsIGYsIG1pblNlcCwgdHJ1ZSkpOyB9LCBbXSksIG4gPSAoaXNDb250YWluZWQgPyAyIDogMCkgKyBsbiArIGduLCB2cyA9IG5ldyBBcnJheShuKSwgcnMgPSBuZXcgQXJyYXkobiksIGkgPSAwLCBhZGQgPSBmdW5jdGlvbiAociwgdikgeyByc1tpXSA9IHI7IHZzW2krK10gPSB2OyB9O1xuICAgIGlmIChpc0NvbnRhaW5lZCkge1xuICAgICAgICB2YXIgYiA9IHJvb3QuYm91bmRzLCBjID0gZi5nZXRDZW50cmUoYiksIHMgPSBmLmdldFNpemUoYikgLyAyLCBvcGVuID0gZi5nZXRPcGVuKGIpLCBjbG9zZSA9IGYuZ2V0Q2xvc2UoYiksIG1pbiA9IGMgLSBzICsgcGFkZGluZyAvIDIsIG1heCA9IGMgKyBzIC0gcGFkZGluZyAvIDI7XG4gICAgICAgIHJvb3QubWluVmFyLmRlc2lyZWRQb3NpdGlvbiA9IG1pbjtcbiAgICAgICAgYWRkKGYubWFrZVJlY3Qob3BlbiwgY2xvc2UsIG1pbiwgcGFkZGluZyksIHJvb3QubWluVmFyKTtcbiAgICAgICAgcm9vdC5tYXhWYXIuZGVzaXJlZFBvc2l0aW9uID0gbWF4O1xuICAgICAgICBhZGQoZi5tYWtlUmVjdChvcGVuLCBjbG9zZSwgbWF4LCBwYWRkaW5nKSwgcm9vdC5tYXhWYXIpO1xuICAgIH1cbiAgICBpZiAobG4pXG4gICAgICAgIHJvb3QubGVhdmVzLmZvckVhY2goZnVuY3Rpb24gKGwpIHsgcmV0dXJuIGFkZChsLmJvdW5kcywgbC52YXJpYWJsZSk7IH0pO1xuICAgIGlmIChnbilcbiAgICAgICAgcm9vdC5ncm91cHMuZm9yRWFjaChmdW5jdGlvbiAoZykge1xuICAgICAgICAgICAgdmFyIGIgPSBnLmJvdW5kcztcbiAgICAgICAgICAgIGFkZChmLm1ha2VSZWN0KGYuZ2V0T3BlbihiKSwgZi5nZXRDbG9zZShiKSwgZi5nZXRDZW50cmUoYiksIGYuZ2V0U2l6ZShiKSksIGcubWluVmFyKTtcbiAgICAgICAgfSk7XG4gICAgdmFyIGNzID0gZ2VuZXJhdGVDb25zdHJhaW50cyhycywgdnMsIGYsIG1pblNlcCk7XG4gICAgaWYgKGduKSB7XG4gICAgICAgIHZzLmZvckVhY2goZnVuY3Rpb24gKHYpIHsgdi5jT3V0ID0gW10sIHYuY0luID0gW107IH0pO1xuICAgICAgICBjcy5mb3JFYWNoKGZ1bmN0aW9uIChjKSB7IGMubGVmdC5jT3V0LnB1c2goYyksIGMucmlnaHQuY0luLnB1c2goYyk7IH0pO1xuICAgICAgICByb290Lmdyb3Vwcy5mb3JFYWNoKGZ1bmN0aW9uIChnKSB7XG4gICAgICAgICAgICB2YXIgZ2FwQWRqdXN0bWVudCA9IChnLnBhZGRpbmcgLSBmLmdldFNpemUoZy5ib3VuZHMpKSAvIDI7XG4gICAgICAgICAgICBnLm1pblZhci5jSW4uZm9yRWFjaChmdW5jdGlvbiAoYykgeyByZXR1cm4gYy5nYXAgKz0gZ2FwQWRqdXN0bWVudDsgfSk7XG4gICAgICAgICAgICBnLm1pblZhci5jT3V0LmZvckVhY2goZnVuY3Rpb24gKGMpIHsgYy5sZWZ0ID0gZy5tYXhWYXI7IGMuZ2FwICs9IGdhcEFkanVzdG1lbnQ7IH0pO1xuICAgICAgICB9KTtcbiAgICB9XG4gICAgcmV0dXJuIGNoaWxkQ29uc3RyYWludHMuY29uY2F0KGNzKTtcbn1cbmZ1bmN0aW9uIGdlbmVyYXRlQ29uc3RyYWludHMocnMsIHZhcnMsIHJlY3QsIG1pblNlcCkge1xuICAgIHZhciBpLCBuID0gcnMubGVuZ3RoO1xuICAgIHZhciBOID0gMiAqIG47XG4gICAgY29uc29sZS5hc3NlcnQodmFycy5sZW5ndGggPj0gbik7XG4gICAgdmFyIGV2ZW50cyA9IG5ldyBBcnJheShOKTtcbiAgICBmb3IgKGkgPSAwOyBpIDwgbjsgKytpKSB7XG4gICAgICAgIHZhciByID0gcnNbaV07XG4gICAgICAgIHZhciB2ID0gbmV3IE5vZGUodmFyc1tpXSwgciwgcmVjdC5nZXRDZW50cmUocikpO1xuICAgICAgICBldmVudHNbaV0gPSBuZXcgRXZlbnQodHJ1ZSwgdiwgcmVjdC5nZXRPcGVuKHIpKTtcbiAgICAgICAgZXZlbnRzW2kgKyBuXSA9IG5ldyBFdmVudChmYWxzZSwgdiwgcmVjdC5nZXRDbG9zZShyKSk7XG4gICAgfVxuICAgIGV2ZW50cy5zb3J0KGNvbXBhcmVFdmVudHMpO1xuICAgIHZhciBjcyA9IG5ldyBBcnJheSgpO1xuICAgIHZhciBzY2FubGluZSA9IG1ha2VSQlRyZWUoKTtcbiAgICBmb3IgKGkgPSAwOyBpIDwgTjsgKytpKSB7XG4gICAgICAgIHZhciBlID0gZXZlbnRzW2ldO1xuICAgICAgICB2YXIgdiA9IGUudjtcbiAgICAgICAgaWYgKGUuaXNPcGVuKSB7XG4gICAgICAgICAgICBzY2FubGluZS5pbnNlcnQodik7XG4gICAgICAgICAgICByZWN0LmZpbmROZWlnaGJvdXJzKHYsIHNjYW5saW5lKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIHNjYW5saW5lLnJlbW92ZSh2KTtcbiAgICAgICAgICAgIHZhciBtYWtlQ29uc3RyYWludCA9IGZ1bmN0aW9uIChsLCByKSB7XG4gICAgICAgICAgICAgICAgdmFyIHNlcCA9IChyZWN0LmdldFNpemUobC5yKSArIHJlY3QuZ2V0U2l6ZShyLnIpKSAvIDIgKyBtaW5TZXA7XG4gICAgICAgICAgICAgICAgY3MucHVzaChuZXcgdnBzY18xLkNvbnN0cmFpbnQobC52LCByLnYsIHNlcCkpO1xuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIHZhciB2aXNpdE5laWdoYm91cnMgPSBmdW5jdGlvbiAoZm9yd2FyZCwgcmV2ZXJzZSwgbWtjb24pIHtcbiAgICAgICAgICAgICAgICB2YXIgdSwgaXQgPSB2W2ZvcndhcmRdLml0ZXJhdG9yKCk7XG4gICAgICAgICAgICAgICAgd2hpbGUgKCh1ID0gaXRbZm9yd2FyZF0oKSkgIT09IG51bGwpIHtcbiAgICAgICAgICAgICAgICAgICAgbWtjb24odSwgdik7XG4gICAgICAgICAgICAgICAgICAgIHVbcmV2ZXJzZV0ucmVtb3ZlKHYpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICB2aXNpdE5laWdoYm91cnMoXCJwcmV2XCIsIFwibmV4dFwiLCBmdW5jdGlvbiAodSwgdikgeyByZXR1cm4gbWFrZUNvbnN0cmFpbnQodSwgdik7IH0pO1xuICAgICAgICAgICAgdmlzaXROZWlnaGJvdXJzKFwibmV4dFwiLCBcInByZXZcIiwgZnVuY3Rpb24gKHUsIHYpIHsgcmV0dXJuIG1ha2VDb25zdHJhaW50KHYsIHUpOyB9KTtcbiAgICAgICAgfVxuICAgIH1cbiAgICBjb25zb2xlLmFzc2VydChzY2FubGluZS5zaXplID09PSAwKTtcbiAgICByZXR1cm4gY3M7XG59XG5mdW5jdGlvbiBmaW5kWE5laWdoYm91cnModiwgc2NhbmxpbmUpIHtcbiAgICB2YXIgZiA9IGZ1bmN0aW9uIChmb3J3YXJkLCByZXZlcnNlKSB7XG4gICAgICAgIHZhciBpdCA9IHNjYW5saW5lLmZpbmRJdGVyKHYpO1xuICAgICAgICB2YXIgdTtcbiAgICAgICAgd2hpbGUgKCh1ID0gaXRbZm9yd2FyZF0oKSkgIT09IG51bGwpIHtcbiAgICAgICAgICAgIHZhciB1b3ZlcnZYID0gdS5yLm92ZXJsYXBYKHYucik7XG4gICAgICAgICAgICBpZiAodW92ZXJ2WCA8PSAwIHx8IHVvdmVydlggPD0gdS5yLm92ZXJsYXBZKHYucikpIHtcbiAgICAgICAgICAgICAgICB2W2ZvcndhcmRdLmluc2VydCh1KTtcbiAgICAgICAgICAgICAgICB1W3JldmVyc2VdLmluc2VydCh2KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICh1b3ZlcnZYIDw9IDApIHtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH07XG4gICAgZihcIm5leHRcIiwgXCJwcmV2XCIpO1xuICAgIGYoXCJwcmV2XCIsIFwibmV4dFwiKTtcbn1cbmZ1bmN0aW9uIGZpbmRZTmVpZ2hib3Vycyh2LCBzY2FubGluZSkge1xuICAgIHZhciBmID0gZnVuY3Rpb24gKGZvcndhcmQsIHJldmVyc2UpIHtcbiAgICAgICAgdmFyIHUgPSBzY2FubGluZS5maW5kSXRlcih2KVtmb3J3YXJkXSgpO1xuICAgICAgICBpZiAodSAhPT0gbnVsbCAmJiB1LnIub3ZlcmxhcFgodi5yKSA+IDApIHtcbiAgICAgICAgICAgIHZbZm9yd2FyZF0uaW5zZXJ0KHUpO1xuICAgICAgICAgICAgdVtyZXZlcnNlXS5pbnNlcnQodik7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIGYoXCJuZXh0XCIsIFwicHJldlwiKTtcbiAgICBmKFwicHJldlwiLCBcIm5leHRcIik7XG59XG5mdW5jdGlvbiBnZW5lcmF0ZVhDb25zdHJhaW50cyhycywgdmFycykge1xuICAgIHJldHVybiBnZW5lcmF0ZUNvbnN0cmFpbnRzKHJzLCB2YXJzLCB4UmVjdCwgMWUtNik7XG59XG5leHBvcnRzLmdlbmVyYXRlWENvbnN0cmFpbnRzID0gZ2VuZXJhdGVYQ29uc3RyYWludHM7XG5mdW5jdGlvbiBnZW5lcmF0ZVlDb25zdHJhaW50cyhycywgdmFycykge1xuICAgIHJldHVybiBnZW5lcmF0ZUNvbnN0cmFpbnRzKHJzLCB2YXJzLCB5UmVjdCwgMWUtNik7XG59XG5leHBvcnRzLmdlbmVyYXRlWUNvbnN0cmFpbnRzID0gZ2VuZXJhdGVZQ29uc3RyYWludHM7XG5mdW5jdGlvbiBnZW5lcmF0ZVhHcm91cENvbnN0cmFpbnRzKHJvb3QpIHtcbiAgICByZXR1cm4gZ2VuZXJhdGVHcm91cENvbnN0cmFpbnRzKHJvb3QsIHhSZWN0LCAxZS02KTtcbn1cbmV4cG9ydHMuZ2VuZXJhdGVYR3JvdXBDb25zdHJhaW50cyA9IGdlbmVyYXRlWEdyb3VwQ29uc3RyYWludHM7XG5mdW5jdGlvbiBnZW5lcmF0ZVlHcm91cENvbnN0cmFpbnRzKHJvb3QpIHtcbiAgICByZXR1cm4gZ2VuZXJhdGVHcm91cENvbnN0cmFpbnRzKHJvb3QsIHlSZWN0LCAxZS02KTtcbn1cbmV4cG9ydHMuZ2VuZXJhdGVZR3JvdXBDb25zdHJhaW50cyA9IGdlbmVyYXRlWUdyb3VwQ29uc3RyYWludHM7XG5mdW5jdGlvbiByZW1vdmVPdmVybGFwcyhycykge1xuICAgIHZhciB2cyA9IHJzLm1hcChmdW5jdGlvbiAocikgeyByZXR1cm4gbmV3IHZwc2NfMS5WYXJpYWJsZShyLmN4KCkpOyB9KTtcbiAgICB2YXIgY3MgPSBnZW5lcmF0ZVhDb25zdHJhaW50cyhycywgdnMpO1xuICAgIHZhciBzb2x2ZXIgPSBuZXcgdnBzY18xLlNvbHZlcih2cywgY3MpO1xuICAgIHNvbHZlci5zb2x2ZSgpO1xuICAgIHZzLmZvckVhY2goZnVuY3Rpb24gKHYsIGkpIHsgcmV0dXJuIHJzW2ldLnNldFhDZW50cmUodi5wb3NpdGlvbigpKTsgfSk7XG4gICAgdnMgPSBycy5tYXAoZnVuY3Rpb24gKHIpIHsgcmV0dXJuIG5ldyB2cHNjXzEuVmFyaWFibGUoci5jeSgpKTsgfSk7XG4gICAgY3MgPSBnZW5lcmF0ZVlDb25zdHJhaW50cyhycywgdnMpO1xuICAgIHNvbHZlciA9IG5ldyB2cHNjXzEuU29sdmVyKHZzLCBjcyk7XG4gICAgc29sdmVyLnNvbHZlKCk7XG4gICAgdnMuZm9yRWFjaChmdW5jdGlvbiAodiwgaSkgeyByZXR1cm4gcnNbaV0uc2V0WUNlbnRyZSh2LnBvc2l0aW9uKCkpOyB9KTtcbn1cbmV4cG9ydHMucmVtb3ZlT3ZlcmxhcHMgPSByZW1vdmVPdmVybGFwcztcbnZhciBJbmRleGVkVmFyaWFibGUgPSAoZnVuY3Rpb24gKF9zdXBlcikge1xuICAgIF9fZXh0ZW5kcyhJbmRleGVkVmFyaWFibGUsIF9zdXBlcik7XG4gICAgZnVuY3Rpb24gSW5kZXhlZFZhcmlhYmxlKGluZGV4LCB3KSB7XG4gICAgICAgIHZhciBfdGhpcyA9IF9zdXBlci5jYWxsKHRoaXMsIDAsIHcpIHx8IHRoaXM7XG4gICAgICAgIF90aGlzLmluZGV4ID0gaW5kZXg7XG4gICAgICAgIHJldHVybiBfdGhpcztcbiAgICB9XG4gICAgcmV0dXJuIEluZGV4ZWRWYXJpYWJsZTtcbn0odnBzY18xLlZhcmlhYmxlKSk7XG5leHBvcnRzLkluZGV4ZWRWYXJpYWJsZSA9IEluZGV4ZWRWYXJpYWJsZTtcbnZhciBQcm9qZWN0aW9uID0gKGZ1bmN0aW9uICgpIHtcbiAgICBmdW5jdGlvbiBQcm9qZWN0aW9uKG5vZGVzLCBncm91cHMsIHJvb3RHcm91cCwgY29uc3RyYWludHMsIGF2b2lkT3ZlcmxhcHMpIHtcbiAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgaWYgKHJvb3RHcm91cCA9PT0gdm9pZCAwKSB7IHJvb3RHcm91cCA9IG51bGw7IH1cbiAgICAgICAgaWYgKGNvbnN0cmFpbnRzID09PSB2b2lkIDApIHsgY29uc3RyYWludHMgPSBudWxsOyB9XG4gICAgICAgIGlmIChhdm9pZE92ZXJsYXBzID09PSB2b2lkIDApIHsgYXZvaWRPdmVybGFwcyA9IGZhbHNlOyB9XG4gICAgICAgIHRoaXMubm9kZXMgPSBub2RlcztcbiAgICAgICAgdGhpcy5ncm91cHMgPSBncm91cHM7XG4gICAgICAgIHRoaXMucm9vdEdyb3VwID0gcm9vdEdyb3VwO1xuICAgICAgICB0aGlzLmF2b2lkT3ZlcmxhcHMgPSBhdm9pZE92ZXJsYXBzO1xuICAgICAgICB0aGlzLnZhcmlhYmxlcyA9IG5vZGVzLm1hcChmdW5jdGlvbiAodiwgaSkge1xuICAgICAgICAgICAgcmV0dXJuIHYudmFyaWFibGUgPSBuZXcgSW5kZXhlZFZhcmlhYmxlKGksIDEpO1xuICAgICAgICB9KTtcbiAgICAgICAgaWYgKGNvbnN0cmFpbnRzKVxuICAgICAgICAgICAgdGhpcy5jcmVhdGVDb25zdHJhaW50cyhjb25zdHJhaW50cyk7XG4gICAgICAgIGlmIChhdm9pZE92ZXJsYXBzICYmIHJvb3RHcm91cCAmJiB0eXBlb2Ygcm9vdEdyb3VwLmdyb3VwcyAhPT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgICAgIG5vZGVzLmZvckVhY2goZnVuY3Rpb24gKHYpIHtcbiAgICAgICAgICAgICAgICBpZiAoIXYud2lkdGggfHwgIXYuaGVpZ2h0KSB7XG4gICAgICAgICAgICAgICAgICAgIHYuYm91bmRzID0gbmV3IFJlY3RhbmdsZSh2LngsIHYueCwgdi55LCB2LnkpO1xuICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHZhciB3MiA9IHYud2lkdGggLyAyLCBoMiA9IHYuaGVpZ2h0IC8gMjtcbiAgICAgICAgICAgICAgICB2LmJvdW5kcyA9IG5ldyBSZWN0YW5nbGUodi54IC0gdzIsIHYueCArIHcyLCB2LnkgLSBoMiwgdi55ICsgaDIpO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICBjb21wdXRlR3JvdXBCb3VuZHMocm9vdEdyb3VwKTtcbiAgICAgICAgICAgIHZhciBpID0gbm9kZXMubGVuZ3RoO1xuICAgICAgICAgICAgZ3JvdXBzLmZvckVhY2goZnVuY3Rpb24gKGcpIHtcbiAgICAgICAgICAgICAgICBfdGhpcy52YXJpYWJsZXNbaV0gPSBnLm1pblZhciA9IG5ldyBJbmRleGVkVmFyaWFibGUoaSsrLCB0eXBlb2YgZy5zdGlmZm5lc3MgIT09IFwidW5kZWZpbmVkXCIgPyBnLnN0aWZmbmVzcyA6IDAuMDEpO1xuICAgICAgICAgICAgICAgIF90aGlzLnZhcmlhYmxlc1tpXSA9IGcubWF4VmFyID0gbmV3IEluZGV4ZWRWYXJpYWJsZShpKyssIHR5cGVvZiBnLnN0aWZmbmVzcyAhPT0gXCJ1bmRlZmluZWRcIiA/IGcuc3RpZmZuZXNzIDogMC4wMSk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgIH1cbiAgICBQcm9qZWN0aW9uLnByb3RvdHlwZS5jcmVhdGVTZXBhcmF0aW9uID0gZnVuY3Rpb24gKGMpIHtcbiAgICAgICAgcmV0dXJuIG5ldyB2cHNjXzEuQ29uc3RyYWludCh0aGlzLm5vZGVzW2MubGVmdF0udmFyaWFibGUsIHRoaXMubm9kZXNbYy5yaWdodF0udmFyaWFibGUsIGMuZ2FwLCB0eXBlb2YgYy5lcXVhbGl0eSAhPT0gXCJ1bmRlZmluZWRcIiA/IGMuZXF1YWxpdHkgOiBmYWxzZSk7XG4gICAgfTtcbiAgICBQcm9qZWN0aW9uLnByb3RvdHlwZS5tYWtlRmVhc2libGUgPSBmdW5jdGlvbiAoYykge1xuICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICBpZiAoIXRoaXMuYXZvaWRPdmVybGFwcylcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgdmFyIGF4aXMgPSAneCcsIGRpbSA9ICd3aWR0aCc7XG4gICAgICAgIGlmIChjLmF4aXMgPT09ICd4JylcbiAgICAgICAgICAgIGF4aXMgPSAneScsIGRpbSA9ICdoZWlnaHQnO1xuICAgICAgICB2YXIgdnMgPSBjLm9mZnNldHMubWFwKGZ1bmN0aW9uIChvKSB7IHJldHVybiBfdGhpcy5ub2Rlc1tvLm5vZGVdOyB9KS5zb3J0KGZ1bmN0aW9uIChhLCBiKSB7IHJldHVybiBhW2F4aXNdIC0gYltheGlzXTsgfSk7XG4gICAgICAgIHZhciBwID0gbnVsbDtcbiAgICAgICAgdnMuZm9yRWFjaChmdW5jdGlvbiAodikge1xuICAgICAgICAgICAgaWYgKHApIHtcbiAgICAgICAgICAgICAgICB2YXIgbmV4dFBvcyA9IHBbYXhpc10gKyBwW2RpbV07XG4gICAgICAgICAgICAgICAgaWYgKG5leHRQb3MgPiB2W2F4aXNdKSB7XG4gICAgICAgICAgICAgICAgICAgIHZbYXhpc10gPSBuZXh0UG9zO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHAgPSB2O1xuICAgICAgICB9KTtcbiAgICB9O1xuICAgIFByb2plY3Rpb24ucHJvdG90eXBlLmNyZWF0ZUFsaWdubWVudCA9IGZ1bmN0aW9uIChjKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgICAgIHZhciB1ID0gdGhpcy5ub2Rlc1tjLm9mZnNldHNbMF0ubm9kZV0udmFyaWFibGU7XG4gICAgICAgIHRoaXMubWFrZUZlYXNpYmxlKGMpO1xuICAgICAgICB2YXIgY3MgPSBjLmF4aXMgPT09ICd4JyA/IHRoaXMueENvbnN0cmFpbnRzIDogdGhpcy55Q29uc3RyYWludHM7XG4gICAgICAgIGMub2Zmc2V0cy5zbGljZSgxKS5mb3JFYWNoKGZ1bmN0aW9uIChvKSB7XG4gICAgICAgICAgICB2YXIgdiA9IF90aGlzLm5vZGVzW28ubm9kZV0udmFyaWFibGU7XG4gICAgICAgICAgICBjcy5wdXNoKG5ldyB2cHNjXzEuQ29uc3RyYWludCh1LCB2LCBvLm9mZnNldCwgdHJ1ZSkpO1xuICAgICAgICB9KTtcbiAgICB9O1xuICAgIFByb2plY3Rpb24ucHJvdG90eXBlLmNyZWF0ZUNvbnN0cmFpbnRzID0gZnVuY3Rpb24gKGNvbnN0cmFpbnRzKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgICAgIHZhciBpc1NlcCA9IGZ1bmN0aW9uIChjKSB7IHJldHVybiB0eXBlb2YgYy50eXBlID09PSAndW5kZWZpbmVkJyB8fCBjLnR5cGUgPT09ICdzZXBhcmF0aW9uJzsgfTtcbiAgICAgICAgdGhpcy54Q29uc3RyYWludHMgPSBjb25zdHJhaW50c1xuICAgICAgICAgICAgLmZpbHRlcihmdW5jdGlvbiAoYykgeyByZXR1cm4gYy5heGlzID09PSBcInhcIiAmJiBpc1NlcChjKTsgfSlcbiAgICAgICAgICAgIC5tYXAoZnVuY3Rpb24gKGMpIHsgcmV0dXJuIF90aGlzLmNyZWF0ZVNlcGFyYXRpb24oYyk7IH0pO1xuICAgICAgICB0aGlzLnlDb25zdHJhaW50cyA9IGNvbnN0cmFpbnRzXG4gICAgICAgICAgICAuZmlsdGVyKGZ1bmN0aW9uIChjKSB7IHJldHVybiBjLmF4aXMgPT09IFwieVwiICYmIGlzU2VwKGMpOyB9KVxuICAgICAgICAgICAgLm1hcChmdW5jdGlvbiAoYykgeyByZXR1cm4gX3RoaXMuY3JlYXRlU2VwYXJhdGlvbihjKTsgfSk7XG4gICAgICAgIGNvbnN0cmFpbnRzXG4gICAgICAgICAgICAuZmlsdGVyKGZ1bmN0aW9uIChjKSB7IHJldHVybiBjLnR5cGUgPT09ICdhbGlnbm1lbnQnOyB9KVxuICAgICAgICAgICAgLmZvckVhY2goZnVuY3Rpb24gKGMpIHsgcmV0dXJuIF90aGlzLmNyZWF0ZUFsaWdubWVudChjKTsgfSk7XG4gICAgfTtcbiAgICBQcm9qZWN0aW9uLnByb3RvdHlwZS5zZXR1cFZhcmlhYmxlc0FuZEJvdW5kcyA9IGZ1bmN0aW9uICh4MCwgeTAsIGRlc2lyZWQsIGdldERlc2lyZWQpIHtcbiAgICAgICAgdGhpcy5ub2Rlcy5mb3JFYWNoKGZ1bmN0aW9uICh2LCBpKSB7XG4gICAgICAgICAgICBpZiAodi5maXhlZCkge1xuICAgICAgICAgICAgICAgIHYudmFyaWFibGUud2VpZ2h0ID0gdi5maXhlZFdlaWdodCA/IHYuZml4ZWRXZWlnaHQgOiAxMDAwO1xuICAgICAgICAgICAgICAgIGRlc2lyZWRbaV0gPSBnZXREZXNpcmVkKHYpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgdi52YXJpYWJsZS53ZWlnaHQgPSAxO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdmFyIHcgPSAodi53aWR0aCB8fCAwKSAvIDIsIGggPSAodi5oZWlnaHQgfHwgMCkgLyAyO1xuICAgICAgICAgICAgdmFyIGl4ID0geDBbaV0sIGl5ID0geTBbaV07XG4gICAgICAgICAgICB2LmJvdW5kcyA9IG5ldyBSZWN0YW5nbGUoaXggLSB3LCBpeCArIHcsIGl5IC0gaCwgaXkgKyBoKTtcbiAgICAgICAgfSk7XG4gICAgfTtcbiAgICBQcm9qZWN0aW9uLnByb3RvdHlwZS54UHJvamVjdCA9IGZ1bmN0aW9uICh4MCwgeTAsIHgpIHtcbiAgICAgICAgaWYgKCF0aGlzLnJvb3RHcm91cCAmJiAhKHRoaXMuYXZvaWRPdmVybGFwcyB8fCB0aGlzLnhDb25zdHJhaW50cykpXG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIHRoaXMucHJvamVjdCh4MCwgeTAsIHgwLCB4LCBmdW5jdGlvbiAodikgeyByZXR1cm4gdi5weDsgfSwgdGhpcy54Q29uc3RyYWludHMsIGdlbmVyYXRlWEdyb3VwQ29uc3RyYWludHMsIGZ1bmN0aW9uICh2KSB7IHJldHVybiB2LmJvdW5kcy5zZXRYQ2VudHJlKHhbdi52YXJpYWJsZS5pbmRleF0gPSB2LnZhcmlhYmxlLnBvc2l0aW9uKCkpOyB9LCBmdW5jdGlvbiAoZykge1xuICAgICAgICAgICAgdmFyIHhtaW4gPSB4W2cubWluVmFyLmluZGV4XSA9IGcubWluVmFyLnBvc2l0aW9uKCk7XG4gICAgICAgICAgICB2YXIgeG1heCA9IHhbZy5tYXhWYXIuaW5kZXhdID0gZy5tYXhWYXIucG9zaXRpb24oKTtcbiAgICAgICAgICAgIHZhciBwMiA9IGcucGFkZGluZyAvIDI7XG4gICAgICAgICAgICBnLmJvdW5kcy54ID0geG1pbiAtIHAyO1xuICAgICAgICAgICAgZy5ib3VuZHMuWCA9IHhtYXggKyBwMjtcbiAgICAgICAgfSk7XG4gICAgfTtcbiAgICBQcm9qZWN0aW9uLnByb3RvdHlwZS55UHJvamVjdCA9IGZ1bmN0aW9uICh4MCwgeTAsIHkpIHtcbiAgICAgICAgaWYgKCF0aGlzLnJvb3RHcm91cCAmJiAhdGhpcy55Q29uc3RyYWludHMpXG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIHRoaXMucHJvamVjdCh4MCwgeTAsIHkwLCB5LCBmdW5jdGlvbiAodikgeyByZXR1cm4gdi5weTsgfSwgdGhpcy55Q29uc3RyYWludHMsIGdlbmVyYXRlWUdyb3VwQ29uc3RyYWludHMsIGZ1bmN0aW9uICh2KSB7IHJldHVybiB2LmJvdW5kcy5zZXRZQ2VudHJlKHlbdi52YXJpYWJsZS5pbmRleF0gPSB2LnZhcmlhYmxlLnBvc2l0aW9uKCkpOyB9LCBmdW5jdGlvbiAoZykge1xuICAgICAgICAgICAgdmFyIHltaW4gPSB5W2cubWluVmFyLmluZGV4XSA9IGcubWluVmFyLnBvc2l0aW9uKCk7XG4gICAgICAgICAgICB2YXIgeW1heCA9IHlbZy5tYXhWYXIuaW5kZXhdID0gZy5tYXhWYXIucG9zaXRpb24oKTtcbiAgICAgICAgICAgIHZhciBwMiA9IGcucGFkZGluZyAvIDI7XG4gICAgICAgICAgICBnLmJvdW5kcy55ID0geW1pbiAtIHAyO1xuICAgICAgICAgICAgO1xuICAgICAgICAgICAgZy5ib3VuZHMuWSA9IHltYXggKyBwMjtcbiAgICAgICAgfSk7XG4gICAgfTtcbiAgICBQcm9qZWN0aW9uLnByb3RvdHlwZS5wcm9qZWN0RnVuY3Rpb25zID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICByZXR1cm4gW1xuICAgICAgICAgICAgZnVuY3Rpb24gKHgwLCB5MCwgeCkgeyByZXR1cm4gX3RoaXMueFByb2plY3QoeDAsIHkwLCB4KTsgfSxcbiAgICAgICAgICAgIGZ1bmN0aW9uICh4MCwgeTAsIHkpIHsgcmV0dXJuIF90aGlzLnlQcm9qZWN0KHgwLCB5MCwgeSk7IH1cbiAgICAgICAgXTtcbiAgICB9O1xuICAgIFByb2plY3Rpb24ucHJvdG90eXBlLnByb2plY3QgPSBmdW5jdGlvbiAoeDAsIHkwLCBzdGFydCwgZGVzaXJlZCwgZ2V0RGVzaXJlZCwgY3MsIGdlbmVyYXRlQ29uc3RyYWludHMsIHVwZGF0ZU5vZGVCb3VuZHMsIHVwZGF0ZUdyb3VwQm91bmRzKSB7XG4gICAgICAgIHRoaXMuc2V0dXBWYXJpYWJsZXNBbmRCb3VuZHMoeDAsIHkwLCBkZXNpcmVkLCBnZXREZXNpcmVkKTtcbiAgICAgICAgaWYgKHRoaXMucm9vdEdyb3VwICYmIHRoaXMuYXZvaWRPdmVybGFwcykge1xuICAgICAgICAgICAgY29tcHV0ZUdyb3VwQm91bmRzKHRoaXMucm9vdEdyb3VwKTtcbiAgICAgICAgICAgIGNzID0gY3MuY29uY2F0KGdlbmVyYXRlQ29uc3RyYWludHModGhpcy5yb290R3JvdXApKTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLnNvbHZlKHRoaXMudmFyaWFibGVzLCBjcywgc3RhcnQsIGRlc2lyZWQpO1xuICAgICAgICB0aGlzLm5vZGVzLmZvckVhY2godXBkYXRlTm9kZUJvdW5kcyk7XG4gICAgICAgIGlmICh0aGlzLnJvb3RHcm91cCAmJiB0aGlzLmF2b2lkT3ZlcmxhcHMpIHtcbiAgICAgICAgICAgIHRoaXMuZ3JvdXBzLmZvckVhY2godXBkYXRlR3JvdXBCb3VuZHMpO1xuICAgICAgICAgICAgY29tcHV0ZUdyb3VwQm91bmRzKHRoaXMucm9vdEdyb3VwKTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgUHJvamVjdGlvbi5wcm90b3R5cGUuc29sdmUgPSBmdW5jdGlvbiAodnMsIGNzLCBzdGFydGluZywgZGVzaXJlZCkge1xuICAgICAgICB2YXIgc29sdmVyID0gbmV3IHZwc2NfMS5Tb2x2ZXIodnMsIGNzKTtcbiAgICAgICAgc29sdmVyLnNldFN0YXJ0aW5nUG9zaXRpb25zKHN0YXJ0aW5nKTtcbiAgICAgICAgc29sdmVyLnNldERlc2lyZWRQb3NpdGlvbnMoZGVzaXJlZCk7XG4gICAgICAgIHNvbHZlci5zb2x2ZSgpO1xuICAgIH07XG4gICAgcmV0dXJuIFByb2plY3Rpb247XG59KCkpO1xuZXhwb3J0cy5Qcm9qZWN0aW9uID0gUHJvamVjdGlvbjtcbi8vIyBzb3VyY2VNYXBwaW5nVVJMPWRhdGE6YXBwbGljYXRpb24vanNvbjtiYXNlNjQsZXlKMlpYSnphVzl1SWpvekxDSm1hV3hsSWpvaWNtVmpkR0Z1WjJ4bExtcHpJaXdpYzI5MWNtTmxVbTl2ZENJNklpSXNJbk52ZFhKalpYTWlPbHNpTGk0dkxpNHZWMlZpUTI5c1lTOXpjbU12Y21WamRHRnVaMnhsTG5SeklsMHNJbTVoYldWeklqcGJYU3dpYldGd2NHbHVaM01pT2lJN096czdPenM3T3pzN096czdPenRCUVVGQkxDdENRVUZ0UkR0QlFVTnVSQ3h0UTBGQkswSTdRVUZyUWpOQ0xGTkJRV2RDTEd0Q1FVRnJRaXhEUVVGRExFTkJRV3RDTzBsQlEycEVMRU5CUVVNc1EwRkJReXhOUVVGTkxFZEJRVWNzVDBGQlR5eERRVUZETEVOQlFVTXNUVUZCVFN4TFFVRkxMRmRCUVZjc1EwRkJReXhEUVVGRE8xRkJRM2hETEVOQlFVTXNRMEZCUXl4TlFVRk5MRU5CUVVNc1RVRkJUU3hEUVVGRExGVkJRVU1zUTBGQldTeEZRVUZGTEVOQlFVTXNTVUZCU3l4UFFVRkJMRU5CUVVNc1EwRkJReXhOUVVGTkxFTkJRVU1zUzBGQlN5eERRVUZETEVOQlFVTXNRMEZCUXl4RlFVRnFRaXhEUVVGcFFpeEZRVUZGTEZOQlFWTXNRMEZCUXl4TFFVRkxMRVZCUVVVc1EwRkJReXhEUVVGRExFTkJRVU03VVVGRE5VVXNVMEZCVXl4RFFVRkRMRXRCUVVzc1JVRkJSU3hEUVVGRE8wbEJRM1JDTEVsQlFVa3NUMEZCVHl4RFFVRkRMRU5CUVVNc1RVRkJUU3hMUVVGTExGZEJRVmM3VVVGREwwSXNRMEZCUXl4RFFVRkRMRTFCUVUwc1IwRkJZeXhEUVVGRExFTkJRVU1zVFVGQlRTeERRVUZETEUxQlFVMHNRMEZCUXl4VlFVRkRMRU5CUVZrc1JVRkJSU3hEUVVGRExFbEJRVXNzVDBGQlFTeHJRa0ZCYTBJc1EwRkJReXhEUVVGRExFTkJRVU1zUTBGQlF5eExRVUZMTEVOQlFVTXNRMEZCUXl4RFFVRkRMRVZCUVRsQ0xFTkJRVGhDTEVWQlFVVXNRMEZCUXl4RFFVRkRMRTFCUVUwc1EwRkJReXhEUVVGRE8wbEJRM3BITEVOQlFVTXNRMEZCUXl4TlFVRk5MRWRCUVVjc1EwRkJReXhEUVVGRExFMUJRVTBzUTBGQlF5eFBRVUZQTEVOQlFVTXNRMEZCUXl4RFFVRkRMRTlCUVU4c1EwRkJReXhEUVVGRE8wbEJRM1pETEU5QlFVOHNRMEZCUXl4RFFVRkRMRTFCUVUwc1EwRkJRenRCUVVOd1FpeERRVUZETzBGQlVrUXNaMFJCVVVNN1FVRkZSRHRKUVVOSkxHMUNRVU5YTEVOQlFWTXNSVUZEVkN4RFFVRlRMRVZCUTFRc1EwRkJVeXhGUVVOVUxFTkJRVk03VVVGSVZDeE5RVUZETEVkQlFVUXNRMEZCUXl4RFFVRlJPMUZCUTFRc1RVRkJReXhIUVVGRUxFTkJRVU1zUTBGQlVUdFJRVU5VTEUxQlFVTXNSMEZCUkN4RFFVRkRMRU5CUVZFN1VVRkRWQ3hOUVVGRExFZEJRVVFzUTBGQlF5eERRVUZSTzBsQlFVa3NRMEZCUXp0SlFVVnNRaXhsUVVGTExFZEJRVm9zWTBGQk5FSXNUMEZCVHl4SlFVRkpMRk5CUVZNc1EwRkJReXhOUVVGTkxFTkJRVU1zYVVKQlFXbENMRVZCUVVVc1RVRkJUU3hEUVVGRExHbENRVUZwUWl4RlFVRkZMRTFCUVUwc1EwRkJReXhwUWtGQmFVSXNSVUZCUlN4TlFVRk5MRU5CUVVNc2FVSkJRV2xDTEVOQlFVTXNRMEZCUXl4RFFVRkRMRU5CUVVNN1NVRkZNMG9zYzBKQlFVVXNSMEZCUml4alFVRmxMRTlCUVU4c1EwRkJReXhKUVVGSkxFTkJRVU1zUTBGQlF5eEhRVUZITEVsQlFVa3NRMEZCUXl4RFFVRkRMRU5CUVVNc1IwRkJSeXhEUVVGRExFTkJRVU1zUTBGQlF5eERRVUZETzBsQlJUbERMSE5DUVVGRkxFZEJRVVlzWTBGQlpTeFBRVUZQTEVOQlFVTXNTVUZCU1N4RFFVRkRMRU5CUVVNc1IwRkJSeXhKUVVGSkxFTkJRVU1zUTBGQlF5eERRVUZETEVkQlFVY3NRMEZCUXl4RFFVRkRMRU5CUVVNc1EwRkJRenRKUVVVNVF5dzBRa0ZCVVN4SFFVRlNMRlZCUVZNc1EwRkJXVHRSUVVOcVFpeEpRVUZKTEVWQlFVVXNSMEZCUnl4SlFVRkpMRU5CUVVNc1JVRkJSU3hGUVVGRkxFVkJRVVVzUlVGQlJTeEhRVUZITEVOQlFVTXNRMEZCUXl4RlFVRkZMRVZCUVVVc1EwRkJRenRSUVVOb1F5eEpRVUZKTEVWQlFVVXNTVUZCU1N4RlFVRkZMRWxCUVVrc1EwRkJReXhEUVVGRExFTkJRVU1zUjBGQlJ5eEpRVUZKTEVOQlFVTXNRMEZCUXp0WlFVRkZMRTlCUVU4c1NVRkJTU3hEUVVGRExFTkJRVU1zUjBGQlJ5eERRVUZETEVOQlFVTXNRMEZCUXl4RFFVRkRPMUZCUTJ4RUxFbEJRVWtzUlVGQlJTeEpRVUZKTEVWQlFVVXNTVUZCU1N4SlFVRkpMRU5CUVVNc1EwRkJReXhIUVVGSExFTkJRVU1zUTBGQlF5eERRVUZETzFsQlFVVXNUMEZCVHl4RFFVRkRMRU5CUVVNc1EwRkJReXhIUVVGSExFbEJRVWtzUTBGQlF5eERRVUZETEVOQlFVTTdVVUZEYkVRc1QwRkJUeXhEUVVGRExFTkJRVU03U1VGRFlpeERRVUZETzBsQlJVUXNORUpCUVZFc1IwRkJVaXhWUVVGVExFTkJRVms3VVVGRGFrSXNTVUZCU1N4RlFVRkZMRWRCUVVjc1NVRkJTU3hEUVVGRExFVkJRVVVzUlVGQlJTeEZRVUZGTEVWQlFVVXNSMEZCUnl4RFFVRkRMRU5CUVVNc1JVRkJSU3hGUVVGRkxFTkJRVU03VVVGRGFFTXNTVUZCU1N4RlFVRkZMRWxCUVVrc1JVRkJSU3hKUVVGSkxFTkJRVU1zUTBGQlF5eERRVUZETEVkQlFVY3NTVUZCU1N4RFFVRkRMRU5CUVVNN1dVRkJSU3hQUVVGUExFbEJRVWtzUTBGQlF5eERRVUZETEVkQlFVY3NRMEZCUXl4RFFVRkRMRU5CUVVNc1EwRkJRenRSUVVOc1JDeEpRVUZKTEVWQlFVVXNTVUZCU1N4RlFVRkZMRWxCUVVrc1NVRkJTU3hEUVVGRExFTkJRVU1zUjBGQlJ5eERRVUZETEVOQlFVTXNRMEZCUXp0WlFVRkZMRTlCUVU4c1EwRkJReXhEUVVGRExFTkJRVU1zUjBGQlJ5eEpRVUZKTEVOQlFVTXNRMEZCUXl4RFFVRkRPMUZCUTJ4RUxFOUJRVThzUTBGQlF5eERRVUZETzBsQlEySXNRMEZCUXp0SlFVVkVMRGhDUVVGVkxFZEJRVllzVlVGQlZ5eEZRVUZWTzFGQlEycENMRWxCUVVrc1JVRkJSU3hIUVVGSExFVkJRVVVzUjBGQlJ5eEpRVUZKTEVOQlFVTXNSVUZCUlN4RlFVRkZMRU5CUVVNN1VVRkRlRUlzU1VGQlNTeERRVUZETEVOQlFVTXNTVUZCU1N4RlFVRkZMRU5CUVVNN1VVRkRZaXhKUVVGSkxFTkJRVU1zUTBGQlF5eEpRVUZKTEVWQlFVVXNRMEZCUXp0SlFVTnFRaXhEUVVGRE8wbEJSVVFzT0VKQlFWVXNSMEZCVml4VlFVRlhMRVZCUVZVN1VVRkRha0lzU1VGQlNTeEZRVUZGTEVkQlFVY3NSVUZCUlN4SFFVRkhMRWxCUVVrc1EwRkJReXhGUVVGRkxFVkJRVVVzUTBGQlF6dFJRVU40UWl4SlFVRkpMRU5CUVVNc1EwRkJReXhKUVVGSkxFVkJRVVVzUTBGQlF6dFJRVU5pTEVsQlFVa3NRMEZCUXl4RFFVRkRMRWxCUVVrc1JVRkJSU3hEUVVGRE8wbEJRMnBDTEVOQlFVTTdTVUZGUkN4NVFrRkJTeXhIUVVGTU8xRkJRMGtzVDBGQlR5eEpRVUZKTEVOQlFVTXNRMEZCUXl4SFFVRkhMRWxCUVVrc1EwRkJReXhEUVVGRExFTkJRVU03U1VGRE0wSXNRMEZCUXp0SlFVVkVMREJDUVVGTkxFZEJRVTQ3VVVGRFNTeFBRVUZQTEVsQlFVa3NRMEZCUXl4RFFVRkRMRWRCUVVjc1NVRkJTU3hEUVVGRExFTkJRVU1zUTBGQlF6dEpRVU16UWl4RFFVRkRPMGxCUlVRc2VVSkJRVXNzUjBGQlRDeFZRVUZOTEVOQlFWazdVVUZEWkN4UFFVRlBMRWxCUVVrc1UwRkJVeXhEUVVGRExFbEJRVWtzUTBGQlF5eEhRVUZITEVOQlFVTXNTVUZCU1N4RFFVRkRMRU5CUVVNc1JVRkJSU3hEUVVGRExFTkJRVU1zUTBGQlF5eERRVUZETEVWQlFVVXNTVUZCU1N4RFFVRkRMRWRCUVVjc1EwRkJReXhKUVVGSkxFTkJRVU1zUTBGQlF5eEZRVUZGTEVOQlFVTXNRMEZCUXl4RFFVRkRMRU5CUVVNc1JVRkJSU3hKUVVGSkxFTkJRVU1zUjBGQlJ5eERRVUZETEVsQlFVa3NRMEZCUXl4RFFVRkRMRVZCUVVVc1EwRkJReXhEUVVGRExFTkJRVU1zUTBGQlF5eEZRVUZGTEVsQlFVa3NRMEZCUXl4SFFVRkhMRU5CUVVNc1NVRkJTU3hEUVVGRExFTkJRVU1zUlVGQlJTeERRVUZETEVOQlFVTXNRMEZCUXl4RFFVRkRMRU5CUVVNc1EwRkJRenRKUVVOeVNDeERRVUZETzBsQlYwUXNjVU5CUVdsQ0xFZEJRV3BDTEZWQlFXdENMRVZCUVZVc1JVRkJSU3hGUVVGVkxFVkJRVVVzUlVGQlZTeEZRVUZGTEVWQlFWVTdVVUZETlVRc1NVRkJTU3hMUVVGTExFZEJRVWNzUTBGQlF5eERRVUZETEVsQlFVa3NRMEZCUXl4RFFVRkRMRVZCUVVVc1NVRkJTU3hEUVVGRExFTkJRVU1zUlVGQlJTeEpRVUZKTEVOQlFVTXNRMEZCUXl4RlFVRkZMRWxCUVVrc1EwRkJReXhEUVVGRExFTkJRVU03V1VGRGNrTXNRMEZCUXl4SlFVRkpMRU5CUVVNc1EwRkJReXhGUVVGRkxFbEJRVWtzUTBGQlF5eERRVUZETEVWQlFVVXNTVUZCU1N4RFFVRkRMRU5CUVVNc1JVRkJSU3hKUVVGSkxFTkJRVU1zUTBGQlF5eERRVUZETzFsQlEyaERMRU5CUVVNc1NVRkJTU3hEUVVGRExFTkJRVU1zUlVGQlJTeEpRVUZKTEVOQlFVTXNRMEZCUXl4RlFVRkZMRWxCUVVrc1EwRkJReXhEUVVGRExFVkJRVVVzU1VGQlNTeERRVUZETEVOQlFVTXNRMEZCUXp0WlFVTndReXhEUVVGRExFbEJRVWtzUTBGQlF5eERRVUZETEVWQlFVVXNTVUZCU1N4RFFVRkRMRU5CUVVNc1JVRkJSU3hKUVVGSkxFTkJRVU1zUTBGQlF5eEZRVUZGTEVsQlFVa3NRMEZCUXl4RFFVRkRMRU5CUVVNc1EwRkJReXhEUVVGRE8xRkJRM1JETEVsQlFVa3NZVUZCWVN4SFFVRkhMRVZCUVVVc1EwRkJRenRSUVVOMlFpeExRVUZMTEVsQlFVa3NRMEZCUXl4SFFVRkhMRU5CUVVNc1JVRkJSU3hEUVVGRExFZEJRVWNzUTBGQlF5eEZRVUZGTEVWQlFVVXNRMEZCUXl4RlFVRkZPMWxCUTNoQ0xFbEJRVWtzUTBGQlF5eEhRVUZITEZOQlFWTXNRMEZCUXl4blFrRkJaMElzUTBGQlF5eEZRVUZGTEVWQlFVVXNSVUZCUlN4RlFVRkZMRVZCUVVVc1JVRkJSU3hGUVVGRkxFVkJRVVVzUzBGQlN5eERRVUZETEVOQlFVTXNRMEZCUXl4RFFVRkRMRU5CUVVNc1EwRkJReXhGUVVGRkxFdEJRVXNzUTBGQlF5eERRVUZETEVOQlFVTXNRMEZCUXl4RFFVRkRMRU5CUVVNc1JVRkJSU3hMUVVGTExFTkJRVU1zUTBGQlF5eERRVUZETEVOQlFVTXNRMEZCUXl4RFFVRkRMRVZCUVVVc1MwRkJTeXhEUVVGRExFTkJRVU1zUTBGQlF5eERRVUZETEVOQlFVTXNRMEZCUXl4RFFVRkRMRU5CUVVNN1dVRkRka2NzU1VGQlNTeERRVUZETEV0QlFVc3NTVUZCU1R0blFrRkJSU3hoUVVGaExFTkJRVU1zU1VGQlNTeERRVUZETEVWQlFVVXNRMEZCUXl4RlFVRkZMRU5CUVVNc1EwRkJReXhEUVVGRExFVkJRVVVzUTBGQlF5eEZRVUZGTEVOQlFVTXNRMEZCUXl4RFFVRkRMRVZCUVVVc1EwRkJReXhEUVVGRE8xTkJRekZFTzFGQlEwUXNUMEZCVHl4aFFVRmhMRU5CUVVNN1NVRkRla0lzUTBGQlF6dEpRVlZFTEcxRFFVRmxMRWRCUVdZc1ZVRkJaMElzUlVGQlZTeEZRVUZGTEVWQlFWVTdVVUZEYkVNc1NVRkJTU3hKUVVGSkxFZEJRVWNzU1VGQlNTeERRVUZETEdsQ1FVRnBRaXhEUVVGRExFbEJRVWtzUTBGQlF5eEZRVUZGTEVWQlFVVXNSVUZCUlN4SlFVRkpMRU5CUVVNc1JVRkJSU3hGUVVGRkxFVkJRVVVzUlVGQlJTeEZRVUZGTEVWQlFVVXNRMEZCUXl4RFFVRkRPMUZCUTJoRkxFOUJRVThzU1VGQlNTeERRVUZETEUxQlFVMHNSMEZCUnl4RFFVRkRMRU5CUVVNc1EwRkJReXhEUVVGRExFbEJRVWtzUTBGQlF5eERRVUZETEVOQlFVTXNRMEZCUXl4RFFVRkRMRU5CUVVNc1NVRkJTU3hEUVVGRE8wbEJRelZETEVOQlFVTTdTVUZGUkN3MFFrRkJVU3hIUVVGU08xRkJRMGtzVDBGQlR6dFpRVU5JTEVWQlFVVXNRMEZCUXl4RlFVRkZMRWxCUVVrc1EwRkJReXhEUVVGRExFVkJRVVVzUTBGQlF5eEZRVUZGTEVsQlFVa3NRMEZCUXl4RFFVRkRMRVZCUVVVN1dVRkRlRUlzUlVGQlJTeERRVUZETEVWQlFVVXNTVUZCU1N4RFFVRkRMRU5CUVVNc1JVRkJSU3hEUVVGRExFVkJRVVVzU1VGQlNTeERRVUZETEVOQlFVTXNSVUZCUlR0WlFVTjRRaXhGUVVGRkxFTkJRVU1zUlVGQlJTeEpRVUZKTEVOQlFVTXNRMEZCUXl4RlFVRkZMRU5CUVVNc1JVRkJSU3hKUVVGSkxFTkJRVU1zUTBGQlF5eEZRVUZGTzFsQlEzaENMRVZCUVVVc1EwRkJReXhGUVVGRkxFbEJRVWtzUTBGQlF5eERRVUZETEVWQlFVVXNRMEZCUXl4RlFVRkZMRWxCUVVrc1EwRkJReXhEUVVGRExFVkJRVVU3VTBGQlF5eERRVUZETzBsQlEyeERMRU5CUVVNN1NVRkZUU3d3UWtGQlowSXNSMEZCZGtJc1ZVRkRTU3hGUVVGVkxFVkJRVVVzUlVGQlZTeEZRVU4wUWl4RlFVRlZMRVZCUVVVc1JVRkJWU3hGUVVOMFFpeEZRVUZWTEVWQlFVVXNSVUZCVlN4RlFVTjBRaXhGUVVGVkxFVkJRVVVzUlVGQlZUdFJRVU4wUWl4SlFVRkpMRWxCUVVrc1IwRkJSeXhGUVVGRkxFZEJRVWNzUlVGQlJTeEZRVUZGTEVsQlFVa3NSMEZCUnl4RlFVRkZMRWRCUVVjc1JVRkJSU3hGUVVNNVFpeEpRVUZKTEVkQlFVY3NSVUZCUlN4SFFVRkhMRVZCUVVVc1JVRkJSU3hKUVVGSkxFZEJRVWNzUlVGQlJTeEhRVUZITEVWQlFVVXNSVUZET1VJc1YwRkJWeXhIUVVGSExFbEJRVWtzUjBGQlJ5eEpRVUZKTEVkQlFVY3NTVUZCU1N4SFFVRkhMRWxCUVVrc1EwRkJRenRSUVVNMVF5eEpRVUZKTEZkQlFWY3NTVUZCU1N4RFFVRkRPMWxCUVVVc1QwRkJUeXhKUVVGSkxFTkJRVU03VVVGRGJFTXNTVUZCU1N4SlFVRkpMRWRCUVVjc1JVRkJSU3hIUVVGSExFVkJRVVVzUlVGQlJTeEpRVUZKTEVkQlFVY3NSVUZCUlN4SFFVRkhMRVZCUVVVc1JVRkRPVUlzU1VGQlNTeEhRVUZITEVsQlFVa3NSMEZCUnl4SlFVRkpMRWRCUVVjc1NVRkJTU3hIUVVGSExFbEJRVWtzUlVGRGFFTXNRMEZCUXl4SFFVRkhMRWxCUVVrc1IwRkJSeXhYUVVGWExFVkJRM1JDTEVsQlFVa3NSMEZCUnl4SlFVRkpMRWRCUVVjc1NVRkJTU3hIUVVGSExFbEJRVWtzUjBGQlJ5eEpRVUZKTEVWQlEyaERMRU5CUVVNc1IwRkJSeXhKUVVGSkxFZEJRVWNzVjBGQlZ5eERRVUZETzFGQlF6TkNMRWxCUVVrc1EwRkJReXhKUVVGSkxFTkJRVU1zU1VGQlNTeERRVUZETEVsQlFVa3NRMEZCUXl4SlFVRkpMRU5CUVVNc1NVRkJTU3hEUVVGRExFbEJRVWtzUTBGQlF5eEpRVUZKTEVOQlFVTXNSVUZCUlR0WlFVTjBReXhQUVVGUE8yZENRVU5JTEVOQlFVTXNSVUZCUlN4RlFVRkZMRWRCUVVjc1EwRkJReXhIUVVGSExFbEJRVWs3WjBKQlEyaENMRU5CUVVNc1JVRkJSU3hGUVVGRkxFZEJRVWNzUTBGQlF5eEhRVUZITEVsQlFVazdZVUZEYmtJc1EwRkJRenRUUVVOTU8xRkJRMFFzVDBGQlR5eEpRVUZKTEVOQlFVTTdTVUZEYUVJc1EwRkJRenRKUVVWRUxESkNRVUZQTEVkQlFWQXNWVUZCVVN4SFFVRlhPMUZCUTJZc1QwRkJUeXhKUVVGSkxGTkJRVk1zUTBGQlF5eEpRVUZKTEVOQlFVTXNRMEZCUXl4SFFVRkhMRWRCUVVjc1JVRkJSU3hKUVVGSkxFTkJRVU1zUTBGQlF5eEhRVUZITEVkQlFVY3NSVUZCUlN4SlFVRkpMRU5CUVVNc1EwRkJReXhIUVVGSExFZEJRVWNzUlVGQlJTeEpRVUZKTEVOQlFVTXNRMEZCUXl4SFFVRkhMRWRCUVVjc1EwRkJReXhEUVVGRE8wbEJRMnBHTEVOQlFVTTdTVUZEVEN4blFrRkJRenRCUVVGRUxFTkJRVU1zUVVGNFNFUXNTVUYzU0VNN1FVRjRTRmtzT0VKQlFWTTdRVUZ4U1hSQ0xGTkJRV2RDTEdWQlFXVXNRMEZCUXl4TlFVRnBRaXhGUVVGRkxFMUJRV2xDTEVWQlFVVXNSVUZCVlR0SlFVVTFSU3hKUVVGTkxFVkJRVVVzUjBGQlJ5eE5RVUZOTEVOQlFVTXNaVUZCWlN4RFFVRkRMRTFCUVUwc1EwRkJReXhGUVVGRkxFVkJRVVVzUlVGQlJTeE5RVUZOTEVOQlFVTXNSVUZCUlN4RlFVRkZMRU5CUVVNc1NVRkJTU3hGUVVGRkxFTkJRVU1zUlVGQlJTeE5RVUZOTEVOQlFVTXNSVUZCUlN4RlFVRkZMRVZCUVVVc1EwRkJReXhGUVVGRkxFMUJRVTBzUTBGQlF5eEZRVUZGTEVWQlFVVXNSVUZCUlN4RlFVTTNSaXhGUVVGRkxFZEJRVWNzVFVGQlRTeERRVUZETEdWQlFXVXNRMEZCUXl4TlFVRk5MRU5CUVVNc1JVRkJSU3hGUVVGRkxFVkJRVVVzVFVGQlRTeERRVUZETEVWQlFVVXNSVUZCUlN4RFFVRkRMRWxCUVVrc1JVRkJSU3hEUVVGRExFVkJRVVVzVFVGQlRTeERRVUZETEVWQlFVVXNSVUZCUlN4RlFVRkZMRU5CUVVNc1JVRkJSU3hOUVVGTkxFTkJRVU1zUlVGQlJTeEZRVUZGTEVWQlFVVXNSVUZETTBZc1JVRkJSU3hIUVVGSExFVkJRVVVzUTBGQlF5eERRVUZETEVkQlFVY3NSVUZCUlN4RFFVRkRMRU5CUVVNc1JVRkRhRUlzUlVGQlJTeEhRVUZITEVWQlFVVXNRMEZCUXl4RFFVRkRMRWRCUVVjc1JVRkJSU3hEUVVGRExFTkJRVU1zUlVGRGFFSXNRMEZCUXl4SFFVRkhMRWxCUVVrc1EwRkJReXhKUVVGSkxFTkJRVU1zUlVGQlJTeEhRVUZITEVWQlFVVXNSMEZCUnl4RlFVRkZMRWRCUVVjc1JVRkJSU3hEUVVGRExFVkJRVVVzUlVGQlJTeEhRVUZITEVOQlFVTXNSMEZCUnl4RlFVRkZMRU5CUVVNN1NVRkRiRVFzVDBGQlR6dFJRVU5JTEd0Q1FVRnJRaXhGUVVGRkxFVkJRVVU3VVVGRGRFSXNhMEpCUVd0Q0xFVkJRVVVzUlVGQlJUdFJRVU4wUWl4VlFVRlZMRVZCUVVVc1JVRkJSU3hEUVVGRExFVkJRVVVzUlVGQlJTeERRVUZETEVOQlFVTXNSMEZCUnl4RlFVRkZMRWRCUVVjc1JVRkJSU3hIUVVGSExFTkJRVU1zUlVGQlJTeERRVUZETEVWQlFVVXNSVUZCUlN4RFFVRkRMRU5CUVVNc1IwRkJSeXhGUVVGRkxFZEJRVWNzUlVGQlJTeEhRVUZITEVOQlFVTXNSVUZCUlR0TFFVTXZSQ3hEUVVGQk8wRkJRMHdzUTBGQlF6dEJRVnBFTERCRFFWbERPMEZCVjBRc1UwRkJaMElzVlVGQlZTeERRVUZETEVOQlFUSkNMRVZCUVVVc1RVRkJhVUlzUlVGQlJTeEZRVUZWTzBsQlEycEdMRWxCUVVrc1JVRkJSU3hIUVVGSExFMUJRVTBzUTBGQlF5eGxRVUZsTEVOQlFVTXNRMEZCUXl4RFFVRkRMRU5CUVVNc1JVRkJSU3hEUVVGRExFTkJRVU1zUTBGQlF5eERRVUZETEVOQlFVTTdTVUZETVVNc1NVRkJTU3hEUVVGRExFVkJRVVU3VVVGQlJTeEZRVUZGTEVkQlFVY3NSVUZCUlN4RFFVRkRMRVZCUVVVc1RVRkJUU3hEUVVGRExFVkJRVVVzUlVGQlJTeEZRVUZGTEVOQlFVTXNSVUZCUlN4TlFVRk5MRU5CUVVNc1JVRkJSU3hGUVVGRkxFVkJRVVVzUTBGQlF6dEpRVU5xUkN4SlFVRkpMRVZCUVVVc1IwRkJSeXhGUVVGRkxFTkJRVU1zUTBGQlF5eEhRVUZITEVOQlFVTXNRMEZCUXl4RFFVRkRMRVZCUTJZc1JVRkJSU3hIUVVGSExFVkJRVVVzUTBGQlF5eERRVUZETEVkQlFVY3NRMEZCUXl4RFFVRkRMRU5CUVVNc1JVRkRaaXhEUVVGRExFZEJRVWNzU1VGQlNTeERRVUZETEVsQlFVa3NRMEZCUXl4RlFVRkZMRWRCUVVjc1JVRkJSU3hIUVVGSExFVkJRVVVzUjBGQlJ5eEZRVUZGTEVOQlFVTXNRMEZCUXp0SlFVTnlReXhQUVVGUExFVkJRVVVzUTBGQlF5eEZRVUZGTEVWQlFVVXNRMEZCUXl4RFFVRkRMRWRCUVVjc1JVRkJSU3hIUVVGSExFVkJRVVVzUjBGQlJ5eERRVUZETEVWQlFVVXNRMEZCUXl4RlFVRkZMRVZCUVVVc1EwRkJReXhEUVVGRExFZEJRVWNzUlVGQlJTeEhRVUZITEVWQlFVVXNSMEZCUnl4RFFVRkRMRVZCUVVVc1EwRkJRenRCUVVNMVJDeERRVUZETzBGQlVFUXNaME5CVDBNN1FVRkZSRHRKUVVsSkxHTkJRVzFDTEVOQlFWY3NSVUZCVXl4RFFVRlpMRVZCUVZNc1IwRkJWenRSUVVGd1JDeE5RVUZETEVkQlFVUXNRMEZCUXl4RFFVRlZPMUZCUVZNc1RVRkJReXhIUVVGRUxFTkJRVU1zUTBGQlZ6dFJRVUZUTEZGQlFVY3NSMEZCU0N4SFFVRkhMRU5CUVZFN1VVRkRia1VzU1VGQlNTeERRVUZETEVsQlFVa3NSMEZCUnl4VlFVRlZMRVZCUVVVc1EwRkJRenRSUVVONlFpeEpRVUZKTEVOQlFVTXNTVUZCU1N4SFFVRkhMRlZCUVZVc1JVRkJSU3hEUVVGRE8wbEJRemRDTEVOQlFVTTdTVUZEVEN4WFFVRkRPMEZCUVVRc1EwRkJReXhCUVZKRUxFbEJVVU03UVVGRlJEdEpRVU5KTEdWQlFXMUNMRTFCUVdVc1JVRkJVeXhEUVVGUExFVkJRVk1zUjBGQlZ6dFJRVUZ1UkN4WFFVRk5MRWRCUVU0c1RVRkJUU3hEUVVGVE8xRkJRVk1zVFVGQlF5eEhRVUZFTEVOQlFVTXNRMEZCVFR0UlFVRlRMRkZCUVVjc1IwRkJTQ3hIUVVGSExFTkJRVkU3U1VGQlJ5eERRVUZETzBsQlF6bEZMRmxCUVVNN1FVRkJSQ3hEUVVGRExFRkJSa1FzU1VGRlF6dEJRVVZFTEZOQlFWTXNZVUZCWVN4RFFVRkRMRU5CUVZFc1JVRkJSU3hEUVVGUk8wbEJRM0pETEVsQlFVa3NRMEZCUXl4RFFVRkRMRWRCUVVjc1IwRkJSeXhEUVVGRExFTkJRVU1zUjBGQlJ5eEZRVUZGTzFGQlEyWXNUMEZCVHl4RFFVRkRMRU5CUVVNN1MwRkRXanRKUVVORUxFbEJRVWtzUTBGQlF5eERRVUZETEVkQlFVY3NSMEZCUnl4RFFVRkRMRU5CUVVNc1IwRkJSeXhGUVVGRk8xRkJRMllzVDBGQlR5eERRVUZETEVOQlFVTXNRMEZCUXp0TFFVTmlPMGxCUTBRc1NVRkJTU3hEUVVGRExFTkJRVU1zVFVGQlRTeEZRVUZGTzFGQlJWWXNUMEZCVHl4RFFVRkRMRU5CUVVNc1EwRkJRenRMUVVOaU8wbEJRMFFzU1VGQlNTeERRVUZETEVOQlFVTXNUVUZCVFN4RlFVRkZPMUZCUlZZc1QwRkJUeXhEUVVGRExFTkJRVU03UzBGRFdqdEpRVU5FTEU5QlFVOHNRMEZCUXl4RFFVRkRPMEZCUTJJc1EwRkJRenRCUVVWRUxGTkJRVk1zVlVGQlZUdEpRVU5tTEU5QlFVOHNTVUZCU1N4bFFVRk5MRU5CUVU4c1ZVRkJReXhEUVVGRExFVkJRVVVzUTBGQlF5eEpRVUZMTEU5QlFVRXNRMEZCUXl4RFFVRkRMRWRCUVVjc1IwRkJSeXhEUVVGRExFTkJRVU1zUjBGQlJ5eEZRVUZpTEVOQlFXRXNRMEZCUXl4RFFVRkRPMEZCUTNKRUxFTkJRVU03UVVGWFJDeEpRVUZKTEV0QlFVc3NSMEZCYTBJN1NVRkRka0lzVTBGQlV5eEZRVUZGTEZWQlFVRXNRMEZCUXl4SlFVRkhMRTlCUVVFc1EwRkJReXhEUVVGRExFVkJRVVVzUlVGQlJTeEZRVUZPTEVOQlFVMDdTVUZEY2tJc1QwRkJUeXhGUVVGRkxGVkJRVUVzUTBGQlF5eEpRVUZITEU5QlFVRXNRMEZCUXl4RFFVRkRMRU5CUVVNc1JVRkJTQ3hEUVVGSE8wbEJRMmhDTEZGQlFWRXNSVUZCUlN4VlFVRkJMRU5CUVVNc1NVRkJSeXhQUVVGQkxFTkJRVU1zUTBGQlF5eERRVUZETEVWQlFVZ3NRMEZCUnp0SlFVTnFRaXhQUVVGUExFVkJRVVVzVlVGQlFTeERRVUZETEVsQlFVY3NUMEZCUVN4RFFVRkRMRU5CUVVNc1MwRkJTeXhGUVVGRkxFVkJRVlFzUTBGQlV6dEpRVU4wUWl4UlFVRlJMRVZCUVVVc1ZVRkJReXhKUVVGSkxFVkJRVVVzUzBGQlN5eEZRVUZGTEUxQlFVMHNSVUZCUlN4SlFVRkpMRWxCUVVzc1QwRkJRU3hKUVVGSkxGTkJRVk1zUTBGQlF5eE5RVUZOTEVkQlFVY3NTVUZCU1N4SFFVRkhMRU5CUVVNc1JVRkJSU3hOUVVGTkxFZEJRVWNzU1VGQlNTeEhRVUZITEVOQlFVTXNSVUZCUlN4SlFVRkpMRVZCUVVVc1MwRkJTeXhEUVVGRExFVkJRV2hGTEVOQlFXZEZPMGxCUTNwSExHTkJRV01zUlVGQlJTeGxRVUZsTzBOQlEyeERMRU5CUVVNN1FVRkZSaXhKUVVGSkxFdEJRVXNzUjBGQmEwSTdTVUZEZGtJc1UwRkJVeXhGUVVGRkxGVkJRVUVzUTBGQlF5eEpRVUZITEU5QlFVRXNRMEZCUXl4RFFVRkRMRVZCUVVVc1JVRkJSU3hGUVVGT0xFTkJRVTA3U1VGRGNrSXNUMEZCVHl4RlFVRkZMRlZCUVVFc1EwRkJReXhKUVVGSExFOUJRVUVzUTBGQlF5eERRVUZETEVOQlFVTXNSVUZCU0N4RFFVRkhPMGxCUTJoQ0xGRkJRVkVzUlVGQlJTeFZRVUZCTEVOQlFVTXNTVUZCUnl4UFFVRkJMRU5CUVVNc1EwRkJReXhEUVVGRExFVkJRVWdzUTBGQlJ6dEpRVU5xUWl4UFFVRlBMRVZCUVVVc1ZVRkJRU3hEUVVGRExFbEJRVWNzVDBGQlFTeERRVUZETEVOQlFVTXNUVUZCVFN4RlFVRkZMRVZCUVZZc1EwRkJWVHRKUVVOMlFpeFJRVUZSTEVWQlFVVXNWVUZCUXl4SlFVRkpMRVZCUVVVc1MwRkJTeXhGUVVGRkxFMUJRVTBzUlVGQlJTeEpRVUZKTEVsQlFVc3NUMEZCUVN4SlFVRkpMRk5CUVZNc1EwRkJReXhKUVVGSkxFVkJRVVVzUzBGQlN5eEZRVUZGTEUxQlFVMHNSMEZCUnl4SlFVRkpMRWRCUVVjc1EwRkJReXhGUVVGRkxFMUJRVTBzUjBGQlJ5eEpRVUZKTEVkQlFVY3NRMEZCUXl4RFFVRkRMRVZCUVdoRkxFTkJRV2RGTzBsQlEzcEhMR05CUVdNc1JVRkJSU3hsUVVGbE8wTkJRMnhETEVOQlFVTTdRVUZGUml4VFFVRlRMSGRDUVVGM1FpeERRVUZETEVsQlFYRkNMRVZCUVVVc1EwRkJaMElzUlVGQlJTeE5RVUZqTEVWQlFVVXNWMEZCTkVJN1NVRkJOVUlzTkVKQlFVRXNSVUZCUVN4dFFrRkJORUk3U1VGRmJrZ3NTVUZCU1N4UFFVRlBMRWRCUVVjc1NVRkJTU3hEUVVGRExFOUJRVThzUlVGRGRFSXNSVUZCUlN4SFFVRkhMRTlCUVU4c1NVRkJTU3hEUVVGRExFMUJRVTBzUzBGQlN5eFhRVUZYTEVOQlFVTXNRMEZCUXl4RFFVRkRMRWxCUVVrc1EwRkJReXhOUVVGTkxFTkJRVU1zVFVGQlRTeERRVUZETEVOQlFVTXNRMEZCUXl4RFFVRkRMRVZCUTJoRkxFVkJRVVVzUjBGQlJ5eFBRVUZQTEVsQlFVa3NRMEZCUXl4TlFVRk5MRXRCUVVzc1YwRkJWeXhEUVVGRExFTkJRVU1zUTBGQlF5eEpRVUZKTEVOQlFVTXNUVUZCVFN4RFFVRkRMRTFCUVUwc1EwRkJReXhEUVVGRExFTkJRVU1zUTBGQlF5eEZRVU5vUlN4blFrRkJaMElzUjBGQmFVSXNRMEZCUXl4RlFVRkZMRU5CUVVNc1EwRkJReXhEUVVGRExFVkJRVVU3VVVGRGVrTXNRMEZCUXl4RFFVRkRMRWxCUVVrc1EwRkJReXhOUVVGTkxFTkJRVU1zVFVGQlRTeERRVUZETEZWQlFVTXNSMEZCYVVJc1JVRkJSU3hEUVVGRExFbEJRVXNzVDBGQlFTeEhRVUZITEVOQlFVTXNUVUZCVFN4RFFVRkRMSGRDUVVGM1FpeERRVUZETEVOQlFVTXNSVUZCUlN4RFFVRkRMRVZCUVVVc1RVRkJUU3hGUVVGRkxFbEJRVWtzUTBGQlF5eERRVUZETEVWQlFYaEVMRU5CUVhkRUxFVkJRVVVzUlVGQlJTeERRVUZETEVWQlF6VkhMRU5CUVVNc1IwRkJSeXhEUVVGRExGZEJRVmNzUTBGQlF5eERRVUZETEVOQlFVTXNRMEZCUXl4RFFVRkRMRU5CUVVNc1EwRkJReXhEUVVGRExFTkJRVU1zUjBGQlJ5eEZRVUZGTEVkQlFVY3NSVUZCUlN4RlFVTnVReXhGUVVGRkxFZEJRV1VzU1VGQlNTeExRVUZMTEVOQlFVTXNRMEZCUXl4RFFVRkRMRVZCUXpkQ0xFVkJRVVVzUjBGQlowSXNTVUZCU1N4TFFVRkxMRU5CUVVNc1EwRkJReXhEUVVGRExFVkJRemxDTEVOQlFVTXNSMEZCUnl4RFFVRkRMRVZCUTB3c1IwRkJSeXhIUVVGSExGVkJRVU1zUTBGQlF5eEZRVUZGTEVOQlFVTXNTVUZCVHl4RlFVRkZMRU5CUVVNc1EwRkJReXhEUVVGRExFZEJRVWNzUTBGQlF5eERRVUZETEVOQlFVTXNSVUZCUlN4RFFVRkRMRU5CUVVNc1JVRkJSU3hEUVVGRExFZEJRVWNzUTBGQlF5eERRVUZCTEVOQlFVTXNRMEZCUXl4RFFVRkRPMGxCUXk5RExFbEJRVWtzVjBGQlZ5eEZRVUZGTzFGQlJXSXNTVUZCU1N4RFFVRkRMRWRCUVdNc1NVRkJTU3hEUVVGRExFMUJRVTBzUlVGRE1VSXNRMEZCUXl4SFFVRkhMRU5CUVVNc1EwRkJReXhUUVVGVExFTkJRVU1zUTBGQlF5eERRVUZETEVWQlFVVXNRMEZCUXl4SFFVRkhMRU5CUVVNc1EwRkJReXhQUVVGUExFTkJRVU1zUTBGQlF5eERRVUZETEVkQlFVY3NRMEZCUXl4RlFVTjRReXhKUVVGSkxFZEJRVWNzUTBGQlF5eERRVUZETEU5QlFVOHNRMEZCUXl4RFFVRkRMRU5CUVVNc1JVRkJSU3hMUVVGTExFZEJRVWNzUTBGQlF5eERRVUZETEZGQlFWRXNRMEZCUXl4RFFVRkRMRU5CUVVNc1JVRkRNVU1zUjBGQlJ5eEhRVUZITEVOQlFVTXNSMEZCUnl4RFFVRkRMRWRCUVVjc1QwRkJUeXhIUVVGSExFTkJRVU1zUlVGQlJTeEhRVUZITEVkQlFVY3NRMEZCUXl4SFFVRkhMRU5CUVVNc1IwRkJSeXhQUVVGUExFZEJRVWNzUTBGQlF5eERRVUZETzFGQlEzcEVMRWxCUVVrc1EwRkJReXhOUVVGTkxFTkJRVU1zWlVGQlpTeEhRVUZITEVkQlFVY3NRMEZCUXp0UlFVTnNReXhIUVVGSExFTkJRVU1zUTBGQlF5eERRVUZETEZGQlFWRXNRMEZCUXl4SlFVRkpMRVZCUVVVc1MwRkJTeXhGUVVGRkxFZEJRVWNzUlVGQlJTeFBRVUZQTEVOQlFVTXNSVUZCUlN4SlFVRkpMRU5CUVVNc1RVRkJUU3hEUVVGRExFTkJRVU03VVVGRGVFUXNTVUZCU1N4RFFVRkRMRTFCUVUwc1EwRkJReXhsUVVGbExFZEJRVWNzUjBGQlJ5eERRVUZETzFGQlEyeERMRWRCUVVjc1EwRkJReXhEUVVGRExFTkJRVU1zVVVGQlVTeERRVUZETEVsQlFVa3NSVUZCUlN4TFFVRkxMRVZCUVVVc1IwRkJSeXhGUVVGRkxFOUJRVThzUTBGQlF5eEZRVUZGTEVsQlFVa3NRMEZCUXl4TlFVRk5MRU5CUVVNc1EwRkJRenRMUVVNelJEdEpRVU5FTEVsQlFVa3NSVUZCUlR0UlFVRkZMRWxCUVVrc1EwRkJReXhOUVVGTkxFTkJRVU1zVDBGQlR5eERRVUZETEZWQlFVRXNRMEZCUXl4SlFVRkpMRTlCUVVFc1IwRkJSeXhEUVVGRExFTkJRVU1zUTBGQlF5eE5RVUZOTEVWQlFVVXNRMEZCUXl4RFFVRkRMRkZCUVZFc1EwRkJReXhGUVVGNlFpeERRVUY1UWl4RFFVRkRMRU5CUVVNN1NVRkROVVFzU1VGQlNTeEZRVUZGTzFGQlFVVXNTVUZCU1N4RFFVRkRMRTFCUVUwc1EwRkJReXhQUVVGUExFTkJRVU1zVlVGQlFTeERRVUZETzFsQlEzcENMRWxCUVVrc1EwRkJReXhIUVVGakxFTkJRVU1zUTBGQlF5eE5RVUZOTEVOQlFVTTdXVUZETlVJc1IwRkJSeXhEUVVGRExFTkJRVU1zUTBGQlF5eFJRVUZSTEVOQlFVTXNRMEZCUXl4RFFVRkRMRTlCUVU4c1EwRkJReXhEUVVGRExFTkJRVU1zUlVGQlJTeERRVUZETEVOQlFVTXNVVUZCVVN4RFFVRkRMRU5CUVVNc1EwRkJReXhGUVVGRkxFTkJRVU1zUTBGQlF5eFRRVUZUTEVOQlFVTXNRMEZCUXl4RFFVRkRMRVZCUVVVc1EwRkJReXhEUVVGRExFOUJRVThzUTBGQlF5eERRVUZETEVOQlFVTXNRMEZCUXl4RlFVRkZMRU5CUVVNc1EwRkJReXhOUVVGTkxFTkJRVU1zUTBGQlF6dFJRVU42Uml4RFFVRkRMRU5CUVVNc1EwRkJRenRKUVVOSUxFbEJRVWtzUlVGQlJTeEhRVUZITEcxQ1FVRnRRaXhEUVVGRExFVkJRVVVzUlVGQlJTeEZRVUZGTEVWQlFVVXNRMEZCUXl4RlFVRkZMRTFCUVUwc1EwRkJReXhEUVVGRE8wbEJRMmhFTEVsQlFVa3NSVUZCUlN4RlFVRkZPMUZCUTBvc1JVRkJSU3hEUVVGRExFOUJRVThzUTBGQlF5eFZRVUZCTEVOQlFVTXNTVUZCVFN4RFFVRkRMRU5CUVVNc1NVRkJTU3hIUVVGSExFVkJRVVVzUlVGQlJTeERRVUZETEVOQlFVTXNSMEZCUnl4SFFVRkhMRVZCUVVVc1EwRkJRU3hEUVVGRExFTkJRVU1zUTBGQlF5eERRVUZETzFGQlF6ZERMRVZCUVVVc1EwRkJReXhQUVVGUExFTkJRVU1zVlVGQlFTeERRVUZETEVsQlFVMHNRMEZCUXl4RFFVRkRMRWxCUVVrc1EwRkJReXhKUVVGSkxFTkJRVU1zU1VGQlNTeERRVUZETEVOQlFVTXNRMEZCUXl4RlFVRkZMRU5CUVVNc1EwRkJReXhMUVVGTExFTkJRVU1zUjBGQlJ5eERRVUZETEVsQlFVa3NRMEZCUXl4RFFVRkRMRU5CUVVNc1EwRkJRU3hEUVVGRExFTkJRVU1zUTBGQlF5eERRVUZETzFGQlF6bEVMRWxCUVVrc1EwRkJReXhOUVVGTkxFTkJRVU1zVDBGQlR5eERRVUZETEZWQlFVRXNRMEZCUXp0WlFVTnFRaXhKUVVGSkxHRkJRV0VzUjBGQlJ5eERRVUZETEVOQlFVTXNRMEZCUXl4UFFVRlBMRWRCUVVjc1EwRkJReXhEUVVGRExFOUJRVThzUTBGQlF5eERRVUZETEVOQlFVTXNUVUZCVFN4RFFVRkRMRU5CUVVNc1IwRkJSeXhEUVVGRExFTkJRVU03V1VGRE1VUXNRMEZCUXl4RFFVRkRMRTFCUVUwc1EwRkJReXhIUVVGSExFTkJRVU1zVDBGQlR5eERRVUZETEZWQlFVRXNRMEZCUXl4SlFVRkpMRTlCUVVFc1EwRkJReXhEUVVGRExFZEJRVWNzU1VGQlNTeGhRVUZoTEVWQlFYUkNMRU5CUVhOQ0xFTkJRVU1zUTBGQlF6dFpRVU5zUkN4RFFVRkRMRU5CUVVNc1RVRkJUU3hEUVVGRExFbEJRVWtzUTBGQlF5eFBRVUZQTEVOQlFVTXNWVUZCUVN4RFFVRkRMRWxCUVUwc1EwRkJReXhEUVVGRExFbEJRVWtzUjBGQlJ5eERRVUZETEVOQlFVTXNUVUZCVFN4RFFVRkRMRU5CUVVNc1EwRkJReXhEUVVGRExFZEJRVWNzU1VGQlNTeGhRVUZoTEVOQlFVTXNRMEZCUXl4RFFVRkRMRU5CUVVNc1EwRkJRenRSUVVNdlJTeERRVUZETEVOQlFVTXNRMEZCUXp0TFFVTk9PMGxCUTBRc1QwRkJUeXhuUWtGQlowSXNRMEZCUXl4TlFVRk5MRU5CUVVNc1JVRkJSU3hEUVVGRExFTkJRVU03UVVGRGRrTXNRMEZCUXp0QlFVVkVMRk5CUVZNc2JVSkJRVzFDTEVOQlFVTXNSVUZCWlN4RlFVRkZMRWxCUVdkQ0xFVkJRekZFTEVsQlFXMUNMRVZCUVVVc1RVRkJZenRKUVVWdVF5eEpRVUZKTEVOQlFVTXNSVUZCUlN4RFFVRkRMRWRCUVVjc1JVRkJSU3hEUVVGRExFMUJRVTBzUTBGQlF6dEpRVU55UWl4SlFVRkpMRU5CUVVNc1IwRkJSeXhEUVVGRExFZEJRVWNzUTBGQlF5eERRVUZETzBsQlEyUXNUMEZCVHl4RFFVRkRMRTFCUVUwc1EwRkJReXhKUVVGSkxFTkJRVU1zVFVGQlRTeEpRVUZKTEVOQlFVTXNRMEZCUXl4RFFVRkRPMGxCUTJwRExFbEJRVWtzVFVGQlRTeEhRVUZITEVsQlFVa3NTMEZCU3l4RFFVRlJMRU5CUVVNc1EwRkJReXhEUVVGRE8wbEJRMnBETEV0QlFVc3NRMEZCUXl4SFFVRkhMRU5CUVVNc1JVRkJSU3hEUVVGRExFZEJRVWNzUTBGQlF5eEZRVUZGTEVWQlFVVXNRMEZCUXl4RlFVRkZPMUZCUTNCQ0xFbEJRVWtzUTBGQlF5eEhRVUZITEVWQlFVVXNRMEZCUXl4RFFVRkRMRU5CUVVNc1EwRkJRenRSUVVOa0xFbEJRVWtzUTBGQlF5eEhRVUZITEVsQlFVa3NTVUZCU1N4RFFVRkRMRWxCUVVrc1EwRkJReXhEUVVGRExFTkJRVU1zUlVGQlJTeERRVUZETEVWQlFVVXNTVUZCU1N4RFFVRkRMRk5CUVZNc1EwRkJReXhEUVVGRExFTkJRVU1zUTBGQlF5eERRVUZETzFGQlEyaEVMRTFCUVUwc1EwRkJReXhEUVVGRExFTkJRVU1zUjBGQlJ5eEpRVUZKTEV0QlFVc3NRMEZCUXl4SlFVRkpMRVZCUVVVc1EwRkJReXhGUVVGRkxFbEJRVWtzUTBGQlF5eFBRVUZQTEVOQlFVTXNRMEZCUXl4RFFVRkRMRU5CUVVNc1EwRkJRenRSUVVOb1JDeE5RVUZOTEVOQlFVTXNRMEZCUXl4SFFVRkhMRU5CUVVNc1EwRkJReXhIUVVGSExFbEJRVWtzUzBGQlN5eERRVUZETEV0QlFVc3NSVUZCUlN4RFFVRkRMRVZCUVVVc1NVRkJTU3hEUVVGRExGRkJRVkVzUTBGQlF5eERRVUZETEVOQlFVTXNRMEZCUXl4RFFVRkRPMHRCUTNwRU8wbEJRMFFzVFVGQlRTeERRVUZETEVsQlFVa3NRMEZCUXl4aFFVRmhMRU5CUVVNc1EwRkJRenRKUVVNelFpeEpRVUZKTEVWQlFVVXNSMEZCUnl4SlFVRkpMRXRCUVVzc1JVRkJZeXhEUVVGRE8wbEJRMnBETEVsQlFVa3NVVUZCVVN4SFFVRkhMRlZCUVZVc1JVRkJSU3hEUVVGRE8wbEJRelZDTEV0QlFVc3NRMEZCUXl4SFFVRkhMRU5CUVVNc1JVRkJSU3hEUVVGRExFZEJRVWNzUTBGQlF5eEZRVUZGTEVWQlFVVXNRMEZCUXl4RlFVRkZPMUZCUTNCQ0xFbEJRVWtzUTBGQlF5eEhRVUZITEUxQlFVMHNRMEZCUXl4RFFVRkRMRU5CUVVNc1EwRkJRenRSUVVOc1FpeEpRVUZKTEVOQlFVTXNSMEZCUnl4RFFVRkRMRU5CUVVNc1EwRkJReXhEUVVGRE8xRkJRMW9zU1VGQlNTeERRVUZETEVOQlFVTXNUVUZCVFN4RlFVRkZPMWxCUTFZc1VVRkJVU3hEUVVGRExFMUJRVTBzUTBGQlF5eERRVUZETEVOQlFVTXNRMEZCUXp0WlFVTnVRaXhKUVVGSkxFTkJRVU1zWTBGQll5eERRVUZETEVOQlFVTXNSVUZCUlN4UlFVRlJMRU5CUVVNc1EwRkJRenRUUVVOd1F6dGhRVUZOTzFsQlJVZ3NVVUZCVVN4RFFVRkRMRTFCUVUwc1EwRkJReXhEUVVGRExFTkJRVU1zUTBGQlF6dFpRVU51UWl4SlFVRkpMR05CUVdNc1IwRkJSeXhWUVVGRExFTkJRVU1zUlVGQlJTeERRVUZETzJkQ1FVTjBRaXhKUVVGSkxFZEJRVWNzUjBGQlJ5eERRVUZETEVsQlFVa3NRMEZCUXl4UFFVRlBMRU5CUVVNc1EwRkJReXhEUVVGRExFTkJRVU1zUTBGQlF5eEhRVUZITEVsQlFVa3NRMEZCUXl4UFFVRlBMRU5CUVVNc1EwRkJReXhEUVVGRExFTkJRVU1zUTBGQlF5eERRVUZETEVkQlFVY3NRMEZCUXl4SFFVRkhMRTFCUVUwc1EwRkJRenRuUWtGREwwUXNSVUZCUlN4RFFVRkRMRWxCUVVrc1EwRkJReXhKUVVGSkxHbENRVUZWTEVOQlFVTXNRMEZCUXl4RFFVRkRMRU5CUVVNc1JVRkJSU3hEUVVGRExFTkJRVU1zUTBGQlF5eEZRVUZGTEVkQlFVY3NRMEZCUXl4RFFVRkRMRU5CUVVNN1dVRkRNME1zUTBGQlF5eERRVUZETzFsQlEwWXNTVUZCU1N4bFFVRmxMRWRCUVVjc1ZVRkJReXhQUVVGUExFVkJRVVVzVDBGQlR5eEZRVUZGTEV0QlFVczdaMEpCUXpGRExFbEJRVWtzUTBGQlF5eEZRVUZGTEVWQlFVVXNSMEZCUnl4RFFVRkRMRU5CUVVNc1QwRkJUeXhEUVVGRExFTkJRVU1zVVVGQlVTeEZRVUZGTEVOQlFVTTdaMEpCUTJ4RExFOUJRVThzUTBGQlF5eERRVUZETEVkQlFVY3NSVUZCUlN4RFFVRkRMRTlCUVU4c1EwRkJReXhGUVVGRkxFTkJRVU1zUzBGQlN5eEpRVUZKTEVWQlFVVTdiMEpCUTJwRExFdEJRVXNzUTBGQlF5eERRVUZETEVWQlFVVXNRMEZCUXl4RFFVRkRMRU5CUVVNN2IwSkJRMW9zUTBGQlF5eERRVUZETEU5QlFVOHNRMEZCUXl4RFFVRkRMRTFCUVUwc1EwRkJReXhEUVVGRExFTkJRVU1zUTBGQlF6dHBRa0ZEZUVJN1dVRkRUQ3hEUVVGRExFTkJRVU03V1VGRFJpeGxRVUZsTEVOQlFVTXNUVUZCVFN4RlFVRkZMRTFCUVUwc1JVRkJSU3hWUVVGRExFTkJRVU1zUlVGQlJTeERRVUZETEVsQlFVc3NUMEZCUVN4alFVRmpMRU5CUVVNc1EwRkJReXhGUVVGRkxFTkJRVU1zUTBGQlF5eEZRVUZ3UWl4RFFVRnZRaXhEUVVGRExFTkJRVU03V1VGRGFFVXNaVUZCWlN4RFFVRkRMRTFCUVUwc1JVRkJSU3hOUVVGTkxFVkJRVVVzVlVGQlF5eERRVUZETEVWQlFVVXNRMEZCUXl4SlFVRkxMRTlCUVVFc1kwRkJZeXhEUVVGRExFTkJRVU1zUlVGQlJTeERRVUZETEVOQlFVTXNSVUZCY0VJc1EwRkJiMElzUTBGQlF5eERRVUZETzFOQlEyNUZPMHRCUTBvN1NVRkRSQ3hQUVVGUExFTkJRVU1zVFVGQlRTeERRVUZETEZGQlFWRXNRMEZCUXl4SlFVRkpMRXRCUVVzc1EwRkJReXhEUVVGRExFTkJRVU03U1VGRGNFTXNUMEZCVHl4RlFVRkZMRU5CUVVNN1FVRkRaQ3hEUVVGRE8wRkJSVVFzVTBGQlV5eGxRVUZsTEVOQlFVTXNRMEZCVHl4RlFVRkZMRkZCUVhOQ08wbEJRM0JFTEVsQlFVa3NRMEZCUXl4SFFVRkhMRlZCUVVNc1QwRkJUeXhGUVVGRkxFOUJRVTg3VVVGRGNrSXNTVUZCU1N4RlFVRkZMRWRCUVVjc1VVRkJVU3hEUVVGRExGRkJRVkVzUTBGQlF5eERRVUZETEVOQlFVTXNRMEZCUXp0UlFVTTVRaXhKUVVGSkxFTkJRVU1zUTBGQlF6dFJRVU5PTEU5QlFVOHNRMEZCUXl4RFFVRkRMRWRCUVVjc1JVRkJSU3hEUVVGRExFOUJRVThzUTBGQlF5eEZRVUZGTEVOQlFVTXNTMEZCU3l4SlFVRkpMRVZCUVVVN1dVRkRha01zU1VGQlNTeFBRVUZQTEVkQlFVY3NRMEZCUXl4RFFVRkRMRU5CUVVNc1EwRkJReXhSUVVGUkxFTkJRVU1zUTBGQlF5eERRVUZETEVOQlFVTXNRMEZCUXl4RFFVRkRPMWxCUTJoRExFbEJRVWtzVDBGQlR5eEpRVUZKTEVOQlFVTXNTVUZCU1N4UFFVRlBMRWxCUVVrc1EwRkJReXhEUVVGRExFTkJRVU1zUTBGQlF5eFJRVUZSTEVOQlFVTXNRMEZCUXl4RFFVRkRMRU5CUVVNc1EwRkJReXhGUVVGRk8yZENRVU01UXl4RFFVRkRMRU5CUVVNc1QwRkJUeXhEUVVGRExFTkJRVU1zVFVGQlRTeERRVUZETEVOQlFVTXNRMEZCUXl4RFFVRkRPMmRDUVVOeVFpeERRVUZETEVOQlFVTXNUMEZCVHl4RFFVRkRMRU5CUVVNc1RVRkJUU3hEUVVGRExFTkJRVU1zUTBGQlF5eERRVUZETzJGQlEzaENPMWxCUTBRc1NVRkJTU3hQUVVGUExFbEJRVWtzUTBGQlF5eEZRVUZGTzJkQ1FVTmtMRTFCUVUwN1lVRkRWRHRUUVVOS08wbEJRMHdzUTBGQlF5eERRVUZCTzBsQlEwUXNRMEZCUXl4RFFVRkRMRTFCUVUwc1JVRkJSU3hOUVVGTkxFTkJRVU1zUTBGQlF6dEpRVU5zUWl4RFFVRkRMRU5CUVVNc1RVRkJUU3hGUVVGRkxFMUJRVTBzUTBGQlF5eERRVUZETzBGQlEzUkNMRU5CUVVNN1FVRkZSQ3hUUVVGVExHVkJRV1VzUTBGQlF5eERRVUZQTEVWQlFVVXNVVUZCYzBJN1NVRkRjRVFzU1VGQlNTeERRVUZETEVkQlFVY3NWVUZCUXl4UFFVRlBMRVZCUVVVc1QwRkJUenRSUVVOeVFpeEpRVUZKTEVOQlFVTXNSMEZCUnl4UlFVRlJMRU5CUVVNc1VVRkJVU3hEUVVGRExFTkJRVU1zUTBGQlF5eERRVUZETEU5QlFVOHNRMEZCUXl4RlFVRkZMRU5CUVVNN1VVRkRlRU1zU1VGQlNTeERRVUZETEV0QlFVc3NTVUZCU1N4SlFVRkpMRU5CUVVNc1EwRkJReXhEUVVGRExFTkJRVU1zVVVGQlVTeERRVUZETEVOQlFVTXNRMEZCUXl4RFFVRkRMRU5CUVVNc1IwRkJSeXhEUVVGRExFVkJRVVU3V1VGRGNrTXNRMEZCUXl4RFFVRkRMRTlCUVU4c1EwRkJReXhEUVVGRExFMUJRVTBzUTBGQlF5eERRVUZETEVOQlFVTXNRMEZCUXp0WlFVTnlRaXhEUVVGRExFTkJRVU1zVDBGQlR5eERRVUZETEVOQlFVTXNUVUZCVFN4RFFVRkRMRU5CUVVNc1EwRkJReXhEUVVGRE8xTkJRM2hDTzBsQlEwd3NRMEZCUXl4RFFVRkJPMGxCUTBRc1EwRkJReXhEUVVGRExFMUJRVTBzUlVGQlJTeE5RVUZOTEVOQlFVTXNRMEZCUXp0SlFVTnNRaXhEUVVGRExFTkJRVU1zVFVGQlRTeEZRVUZGTEUxQlFVMHNRMEZCUXl4RFFVRkRPMEZCUTNSQ0xFTkJRVU03UVVGRlJDeFRRVUZuUWl4dlFrRkJiMElzUTBGQlF5eEZRVUZsTEVWQlFVVXNTVUZCWjBJN1NVRkRiRVVzVDBGQlR5eHRRa0ZCYlVJc1EwRkJReXhGUVVGRkxFVkJRVVVzU1VGQlNTeEZRVUZGTEV0QlFVc3NSVUZCUlN4SlFVRkpMRU5CUVVNc1EwRkJRenRCUVVOMFJDeERRVUZETzBGQlJrUXNiMFJCUlVNN1FVRkZSQ3hUUVVGblFpeHZRa0ZCYjBJc1EwRkJReXhGUVVGbExFVkJRVVVzU1VGQlowSTdTVUZEYkVVc1QwRkJUeXh0UWtGQmJVSXNRMEZCUXl4RlFVRkZMRVZCUVVVc1NVRkJTU3hGUVVGRkxFdEJRVXNzUlVGQlJTeEpRVUZKTEVOQlFVTXNRMEZCUXp0QlFVTjBSQ3hEUVVGRE8wRkJSa1FzYjBSQlJVTTdRVUZGUkN4VFFVRm5RaXg1UWtGQmVVSXNRMEZCUXl4SlFVRnhRanRKUVVNelJDeFBRVUZQTEhkQ1FVRjNRaXhEUVVGRExFbEJRVWtzUlVGQlJTeExRVUZMTEVWQlFVVXNTVUZCU1N4RFFVRkRMRU5CUVVNN1FVRkRka1FzUTBGQlF6dEJRVVpFTERoRVFVVkRPMEZCUlVRc1UwRkJaMElzZVVKQlFYbENMRU5CUVVNc1NVRkJjVUk3U1VGRE0wUXNUMEZCVHl4M1FrRkJkMElzUTBGQlF5eEpRVUZKTEVWQlFVVXNTMEZCU3l4RlFVRkZMRWxCUVVrc1EwRkJReXhEUVVGRE8wRkJRM1pFTEVOQlFVTTdRVUZHUkN3NFJFRkZRenRCUVVWRUxGTkJRV2RDTEdOQlFXTXNRMEZCUXl4RlFVRmxPMGxCUXpGRExFbEJRVWtzUlVGQlJTeEhRVUZITEVWQlFVVXNRMEZCUXl4SFFVRkhMRU5CUVVNc1ZVRkJRU3hEUVVGRExFbEJRVWtzVDBGQlFTeEpRVUZKTEdWQlFWRXNRMEZCUXl4RFFVRkRMRU5CUVVNc1JVRkJSU3hGUVVGRkxFTkJRVU1zUlVGQmNFSXNRMEZCYjBJc1EwRkJReXhEUVVGRE8wbEJRek5ETEVsQlFVa3NSVUZCUlN4SFFVRkhMRzlDUVVGdlFpeERRVUZETEVWQlFVVXNSVUZCUlN4RlFVRkZMRU5CUVVNc1EwRkJRenRKUVVOMFF5eEpRVUZKTEUxQlFVMHNSMEZCUnl4SlFVRkpMR0ZCUVUwc1EwRkJReXhGUVVGRkxFVkJRVVVzUlVGQlJTeERRVUZETEVOQlFVTTdTVUZEYUVNc1RVRkJUU3hEUVVGRExFdEJRVXNzUlVGQlJTeERRVUZETzBsQlEyWXNSVUZCUlN4RFFVRkRMRTlCUVU4c1EwRkJReXhWUVVGRExFTkJRVU1zUlVGQlJTeERRVUZETEVsQlFVc3NUMEZCUVN4RlFVRkZMRU5CUVVNc1EwRkJReXhEUVVGRExFTkJRVU1zVlVGQlZTeERRVUZETEVOQlFVTXNRMEZCUXl4UlFVRlJMRVZCUVVVc1EwRkJReXhGUVVFNVFpeERRVUU0UWl4RFFVRkRMRU5CUVVNN1NVRkRja1FzUlVGQlJTeEhRVUZITEVWQlFVVXNRMEZCUXl4SFFVRkhMRU5CUVVNc1ZVRkJRU3hEUVVGRExFbEJRVWNzVDBGQlFTeEpRVUZKTEdWQlFWRXNRMEZCUXl4RFFVRkRMRU5CUVVNc1JVRkJSU3hGUVVGRkxFTkJRVU1zUlVGQmNFSXNRMEZCYjBJc1EwRkJReXhEUVVGRE8wbEJRM1JETEVWQlFVVXNSMEZCUnl4dlFrRkJiMElzUTBGQlF5eEZRVUZGTEVWQlFVVXNSVUZCUlN4RFFVRkRMRU5CUVVNN1NVRkRiRU1zVFVGQlRTeEhRVUZITEVsQlFVa3NZVUZCVFN4RFFVRkRMRVZCUVVVc1JVRkJSU3hGUVVGRkxFTkJRVU1zUTBGQlF6dEpRVU0xUWl4TlFVRk5MRU5CUVVNc1MwRkJTeXhGUVVGRkxFTkJRVU03U1VGRFppeEZRVUZGTEVOQlFVTXNUMEZCVHl4RFFVRkRMRlZCUVVNc1EwRkJReXhGUVVGRkxFTkJRVU1zU1VGQlN5eFBRVUZCTEVWQlFVVXNRMEZCUXl4RFFVRkRMRU5CUVVNc1EwRkJReXhWUVVGVkxFTkJRVU1zUTBGQlF5eERRVUZETEZGQlFWRXNSVUZCUlN4RFFVRkRMRVZCUVRsQ0xFTkJRVGhDTEVOQlFVTXNRMEZCUXp0QlFVTjZSQ3hEUVVGRE8wRkJXRVFzZDBOQlYwTTdRVUZoUkR0SlFVRnhReXh0UTBGQlVUdEpRVU42UXl4NVFrRkJiVUlzUzBGQllTeEZRVUZGTEVOQlFWTTdVVUZCTTBNc1dVRkRTU3hyUWtGQlRTeERRVUZETEVWQlFVVXNRMEZCUXl4RFFVRkRMRk5CUTJRN1VVRkdhMElzVjBGQlN5eEhRVUZNTEV0QlFVc3NRMEZCVVRzN1NVRkZhRU1zUTBGQlF6dEpRVU5NTEhOQ1FVRkRPMEZCUVVRc1EwRkJReXhCUVVwRUxFTkJRWEZETEdWQlFWRXNSMEZKTlVNN1FVRktXU3d3UTBGQlpUdEJRVTAxUWp0SlFVdEpMRzlDUVVGdlFpeExRVUZyUWl4RlFVTXhRaXhOUVVGNVFpeEZRVU42UWl4VFFVRnBReXhGUVVONlF5eFhRVUYzUWl4RlFVTm9RaXhoUVVFNFFqdFJRVW94UXl4cFFrRTRRa003VVVFMVFsY3NNRUpCUVVFc1JVRkJRU3huUWtGQmFVTTdVVUZEZWtNc05FSkJRVUVzUlVGQlFTeHJRa0ZCZDBJN1VVRkRhRUlzT0VKQlFVRXNSVUZCUVN4eFFrRkJPRUk3VVVGS2RFSXNWVUZCU3l4SFFVRk1MRXRCUVVzc1EwRkJZVHRSUVVNeFFpeFhRVUZOTEVkQlFVNHNUVUZCVFN4RFFVRnRRanRSUVVONlFpeGpRVUZUTEVkQlFWUXNVMEZCVXl4RFFVRjNRanRSUVVWcVF5eHJRa0ZCWVN4SFFVRmlMR0ZCUVdFc1EwRkJhVUk3VVVGRmRFTXNTVUZCU1N4RFFVRkRMRk5CUVZNc1IwRkJSeXhMUVVGTExFTkJRVU1zUjBGQlJ5eERRVUZETEZWQlFVTXNRMEZCUXl4RlFVRkZMRU5CUVVNN1dVRkROVUlzVDBGQlR5eERRVUZETEVOQlFVTXNVVUZCVVN4SFFVRkhMRWxCUVVrc1pVRkJaU3hEUVVGRExFTkJRVU1zUlVGQlJTeERRVUZETEVOQlFVTXNRMEZCUXp0UlFVTnNSQ3hEUVVGRExFTkJRVU1zUTBGQlF6dFJRVVZJTEVsQlFVa3NWMEZCVnp0WlFVRkZMRWxCUVVrc1EwRkJReXhwUWtGQmFVSXNRMEZCUXl4WFFVRlhMRU5CUVVNc1EwRkJRenRSUVVWeVJDeEpRVUZKTEdGQlFXRXNTVUZCU1N4VFFVRlRMRWxCUVVrc1QwRkJUeXhUUVVGVExFTkJRVU1zVFVGQlRTeExRVUZMTEZkQlFWY3NSVUZCUlR0WlFVTjJSU3hMUVVGTExFTkJRVU1zVDBGQlR5eERRVUZETEZWQlFVRXNRMEZCUXp0blFrRkRNVUlzU1VGQlNTeERRVUZETEVOQlFVTXNRMEZCUXl4TFFVRkxMRWxCUVVrc1EwRkJReXhEUVVGRExFTkJRVU1zVFVGQlRTeEZRVU42UWp0dlFrRkZReXhEUVVGRExFTkJRVU1zVFVGQlRTeEhRVUZITEVsQlFVa3NVMEZCVXl4RFFVRkRMRU5CUVVNc1EwRkJReXhEUVVGRExFVkJRVVVzUTBGQlF5eERRVUZETEVOQlFVTXNSVUZCUlN4RFFVRkRMRU5CUVVNc1EwRkJReXhGUVVGRkxFTkJRVU1zUTBGQlF5eERRVUZETEVOQlFVTXNRMEZCUXp0dlFrRkROME1zVDBGQlR6dHBRa0ZEVUR0blFrRkRZeXhKUVVGSkxFVkJRVVVzUjBGQlJ5eERRVUZETEVOQlFVTXNTMEZCU3l4SFFVRkhMRU5CUVVNc1JVRkJSU3hGUVVGRkxFZEJRVWNzUTBGQlF5eERRVUZETEUxQlFVMHNSMEZCUnl4RFFVRkRMRU5CUVVNN1owSkJRM2hETEVOQlFVTXNRMEZCUXl4TlFVRk5MRWRCUVVjc1NVRkJTU3hUUVVGVExFTkJRVU1zUTBGQlF5eERRVUZETEVOQlFVTXNSMEZCUnl4RlFVRkZMRVZCUVVVc1EwRkJReXhEUVVGRExFTkJRVU1zUjBGQlJ5eEZRVUZGTEVWQlFVVXNRMEZCUXl4RFFVRkRMRU5CUVVNc1IwRkJSeXhGUVVGRkxFVkJRVVVzUTBGQlF5eERRVUZETEVOQlFVTXNSMEZCUnl4RlFVRkZMRU5CUVVNc1EwRkJRenRaUVVOeVJTeERRVUZETEVOQlFVTXNRMEZCUXp0WlFVTklMR3RDUVVGclFpeERRVUZETEZOQlFWTXNRMEZCUXl4RFFVRkRPMWxCUXpsQ0xFbEJRVWtzUTBGQlF5eEhRVUZITEV0QlFVc3NRMEZCUXl4TlFVRk5MRU5CUVVNN1dVRkRja0lzVFVGQlRTeERRVUZETEU5QlFVOHNRMEZCUXl4VlFVRkJMRU5CUVVNN1owSkJRMW9zUzBGQlNTeERRVUZETEZOQlFWTXNRMEZCUXl4RFFVRkRMRU5CUVVNc1IwRkJSeXhEUVVGRExFTkJRVU1zVFVGQlRTeEhRVUZITEVsQlFVa3NaVUZCWlN4RFFVRkRMRU5CUVVNc1JVRkJSU3hGUVVGRkxFOUJRVThzUTBGQlF5eERRVUZETEZOQlFWTXNTMEZCU3l4WFFVRlhMRU5CUVVNc1EwRkJReXhEUVVGRExFTkJRVU1zUTBGQlF5eFRRVUZUTEVOQlFVTXNRMEZCUXl4RFFVRkRMRWxCUVVrc1EwRkJReXhEUVVGRE8yZENRVU5xU0N4TFFVRkpMRU5CUVVNc1UwRkJVeXhEUVVGRExFTkJRVU1zUTBGQlF5eEhRVUZITEVOQlFVTXNRMEZCUXl4TlFVRk5MRWRCUVVjc1NVRkJTU3hsUVVGbExFTkJRVU1zUTBGQlF5eEZRVUZGTEVWQlFVVXNUMEZCVHl4RFFVRkRMRU5CUVVNc1UwRkJVeXhMUVVGTExGZEJRVmNzUTBGQlF5eERRVUZETEVOQlFVTXNRMEZCUXl4RFFVRkRMRk5CUVZNc1EwRkJReXhEUVVGRExFTkJRVU1zU1VGQlNTeERRVUZETEVOQlFVTTdXVUZEY2tnc1EwRkJReXhEUVVGRExFTkJRVU03VTBGRFRqdEpRVU5NTEVOQlFVTTdTVUZIVHl4eFEwRkJaMElzUjBGQmVFSXNWVUZCZVVJc1EwRkJUVHRSUVVNelFpeFBRVUZQTEVsQlFVa3NhVUpCUVZVc1EwRkRha0lzU1VGQlNTeERRVUZETEV0QlFVc3NRMEZCUXl4RFFVRkRMRU5CUVVNc1NVRkJTU3hEUVVGRExFTkJRVU1zVVVGQlVTeEZRVU16UWl4SlFVRkpMRU5CUVVNc1MwRkJTeXhEUVVGRExFTkJRVU1zUTBGQlF5eExRVUZMTEVOQlFVTXNRMEZCUXl4UlFVRlJMRVZCUXpWQ0xFTkJRVU1zUTBGQlF5eEhRVUZITEVWQlEwd3NUMEZCVHl4RFFVRkRMRU5CUVVNc1VVRkJVU3hMUVVGTExGZEJRVmNzUTBGQlF5eERRVUZETEVOQlFVTXNRMEZCUXl4RFFVRkRMRkZCUVZFc1EwRkJReXhEUVVGRExFTkJRVU1zUzBGQlN5eERRVUZETEVOQlFVTTdTVUZEYUVVc1EwRkJRenRKUVVkUExHbERRVUZaTEVkQlFYQkNMRlZCUVhGQ0xFTkJRVTA3VVVGQk0wSXNhVUpCYVVKRE8xRkJhRUpITEVsQlFVa3NRMEZCUXl4SlFVRkpMRU5CUVVNc1lVRkJZVHRaUVVGRkxFOUJRVTg3VVVGRmFFTXNTVUZCU1N4SlFVRkpMRWRCUVVjc1IwRkJSeXhGUVVGRkxFZEJRVWNzUjBGQlJ5eFBRVUZQTEVOQlFVTTdVVUZET1VJc1NVRkJTU3hEUVVGRExFTkJRVU1zU1VGQlNTeExRVUZMTEVkQlFVYzdXVUZCUlN4SlFVRkpMRWRCUVVjc1IwRkJSeXhGUVVGRkxFZEJRVWNzUjBGQlJ5eFJRVUZSTEVOQlFVTTdVVUZETDBNc1NVRkJTU3hGUVVGRkxFZEJRV2RDTEVOQlFVTXNRMEZCUXl4UFFVRlBMRU5CUVVNc1IwRkJSeXhEUVVGRExGVkJRVUVzUTBGQlF5eEpRVUZKTEU5QlFVRXNTMEZCU1N4RFFVRkRMRXRCUVVzc1EwRkJReXhEUVVGRExFTkJRVU1zU1VGQlNTeERRVUZETEVWQlFXeENMRU5CUVd0Q0xFTkJRVU1zUTBGQlF5eEpRVUZKTEVOQlFVTXNWVUZCUXl4RFFVRkRMRVZCUVVVc1EwRkJReXhKUVVGTExFOUJRVUVzUTBGQlF5eERRVUZETEVsQlFVa3NRMEZCUXl4SFFVRkhMRU5CUVVNc1EwRkJReXhKUVVGSkxFTkJRVU1zUlVGQmFrSXNRMEZCYVVJc1EwRkJReXhEUVVGRE8xRkJReTlHTEVsQlFVa3NRMEZCUXl4SFFVRmpMRWxCUVVrc1EwRkJRenRSUVVONFFpeEZRVUZGTEVOQlFVTXNUMEZCVHl4RFFVRkRMRlZCUVVFc1EwRkJRenRaUVVWU0xFbEJRVWtzUTBGQlF5eEZRVUZGTzJkQ1FVTklMRWxCUVVrc1QwRkJUeXhIUVVGSExFTkJRVU1zUTBGQlF5eEpRVUZKTEVOQlFVTXNSMEZCUnl4RFFVRkRMRU5CUVVNc1IwRkJSeXhEUVVGRExFTkJRVU03WjBKQlF5OUNMRWxCUVVrc1QwRkJUeXhIUVVGSExFTkJRVU1zUTBGQlF5eEpRVUZKTEVOQlFVTXNSVUZCUlR0dlFrRkRia0lzUTBGQlF5eERRVUZETEVsQlFVa3NRMEZCUXl4SFFVRkhMRTlCUVU4c1EwRkJRenRwUWtGRGNrSTdZVUZEU2p0WlFVTkVMRU5CUVVNc1IwRkJSeXhEUVVGRExFTkJRVU03VVVGRFZpeERRVUZETEVOQlFVTXNRMEZCUXp0SlFVTlFMRU5CUVVNN1NVRkZUeXh2UTBGQlpTeEhRVUYyUWl4VlFVRjNRaXhEUVVGTk8xRkJRVGxDTEdsQ1FWRkRPMUZCVUVjc1NVRkJTU3hEUVVGRExFZEJRVWNzU1VGQlNTeERRVUZETEV0QlFVc3NRMEZCUXl4RFFVRkRMRU5CUVVNc1QwRkJUeXhEUVVGRExFTkJRVU1zUTBGQlF5eERRVUZETEVsQlFVa3NRMEZCUXl4RFFVRkRMRkZCUVZFc1EwRkJRenRSUVVNdlF5eEpRVUZKTEVOQlFVTXNXVUZCV1N4RFFVRkRMRU5CUVVNc1EwRkJReXhEUVVGRE8xRkJRM0pDTEVsQlFVa3NSVUZCUlN4SFFVRkhMRU5CUVVNc1EwRkJReXhKUVVGSkxFdEJRVXNzUjBGQlJ5eERRVUZETEVOQlFVTXNRMEZCUXl4SlFVRkpMRU5CUVVNc1dVRkJXU3hEUVVGRExFTkJRVU1zUTBGQlF5eEpRVUZKTEVOQlFVTXNXVUZCV1N4RFFVRkRPMUZCUTJoRkxFTkJRVU1zUTBGQlF5eFBRVUZQTEVOQlFVTXNTMEZCU3l4RFFVRkRMRU5CUVVNc1EwRkJReXhEUVVGRExFOUJRVThzUTBGQlF5eFZRVUZCTEVOQlFVTTdXVUZEZUVJc1NVRkJTU3hEUVVGRExFZEJRVWNzUzBGQlNTeERRVUZETEV0QlFVc3NRMEZCUXl4RFFVRkRMRU5CUVVNc1NVRkJTU3hEUVVGRExFTkJRVU1zVVVGQlVTeERRVUZETzFsQlEzQkRMRVZCUVVVc1EwRkJReXhKUVVGSkxFTkJRVU1zU1VGQlNTeHBRa0ZCVlN4RFFVRkRMRU5CUVVNc1JVRkJSU3hEUVVGRExFVkJRVVVzUTBGQlF5eERRVUZETEUxQlFVMHNSVUZCUlN4SlFVRkpMRU5CUVVNc1EwRkJReXhEUVVGRE8xRkJRMnhFTEVOQlFVTXNRMEZCUXl4RFFVRkRPMGxCUTFBc1EwRkJRenRKUVVWUExITkRRVUZwUWl4SFFVRjZRaXhWUVVFd1FpeFhRVUZyUWp0UlFVRTFReXhwUWtGWFF6dFJRVlpITEVsQlFVa3NTMEZCU3l4SFFVRkhMRlZCUVVFc1EwRkJReXhKUVVGSkxFOUJRVUVzVDBGQlR5eERRVUZETEVOQlFVTXNTVUZCU1N4TFFVRkxMRmRCUVZjc1NVRkJTU3hEUVVGRExFTkJRVU1zU1VGQlNTeExRVUZMTEZsQlFWa3NSVUZCZUVRc1EwRkJkMFFzUTBGQlF6dFJRVU14UlN4SlFVRkpMRU5CUVVNc1dVRkJXU3hIUVVGSExGZEJRVmM3WVVGRE1VSXNUVUZCVFN4RFFVRkRMRlZCUVVFc1EwRkJReXhKUVVGSkxFOUJRVUVzUTBGQlF5eERRVUZETEVsQlFVa3NTMEZCU3l4SFFVRkhMRWxCUVVrc1MwRkJTeXhEUVVGRExFTkJRVU1zUTBGQlF5eEZRVUV4UWl4RFFVRXdRaXhEUVVGRE8yRkJRM1pETEVkQlFVY3NRMEZCUXl4VlFVRkJMRU5CUVVNc1NVRkJTU3hQUVVGQkxFdEJRVWtzUTBGQlF5eG5Ra0ZCWjBJc1EwRkJReXhEUVVGRExFTkJRVU1zUlVGQmVFSXNRMEZCZDBJc1EwRkJReXhEUVVGRE8xRkJRM2hETEVsQlFVa3NRMEZCUXl4WlFVRlpMRWRCUVVjc1YwRkJWenRoUVVNeFFpeE5RVUZOTEVOQlFVTXNWVUZCUVN4RFFVRkRMRWxCUVVrc1QwRkJRU3hEUVVGRExFTkJRVU1zU1VGQlNTeExRVUZMTEVkQlFVY3NTVUZCU1N4TFFVRkxMRU5CUVVNc1EwRkJReXhEUVVGRExFVkJRVEZDTEVOQlFUQkNMRU5CUVVNN1lVRkRka01zUjBGQlJ5eERRVUZETEZWQlFVRXNRMEZCUXl4SlFVRkpMRTlCUVVFc1MwRkJTU3hEUVVGRExHZENRVUZuUWl4RFFVRkRMRU5CUVVNc1EwRkJReXhGUVVGNFFpeERRVUYzUWl4RFFVRkRMRU5CUVVNN1VVRkRlRU1zVjBGQlZ6dGhRVU5PTEUxQlFVMHNRMEZCUXl4VlFVRkJMRU5CUVVNc1NVRkJTU3hQUVVGQkxFTkJRVU1zUTBGQlF5eEpRVUZKTEV0QlFVc3NWMEZCVnl4RlFVRjBRaXhEUVVGelFpeERRVUZETzJGQlEyNURMRTlCUVU4c1EwRkJReXhWUVVGQkxFTkJRVU1zU1VGQlNTeFBRVUZCTEV0QlFVa3NRMEZCUXl4bFFVRmxMRU5CUVVNc1EwRkJReXhEUVVGRExFVkJRWFpDTEVOQlFYVkNMRU5CUVVNc1EwRkJRenRKUVVNdlF5eERRVUZETzBsQlJVOHNORU5CUVhWQ0xFZEJRUzlDTEZWQlFXZERMRVZCUVZrc1JVRkJSU3hGUVVGWkxFVkJRVVVzVDBGQmFVSXNSVUZCUlN4VlFVRnZRenRSUVVNdlJ5eEpRVUZKTEVOQlFVTXNTMEZCU3l4RFFVRkRMRTlCUVU4c1EwRkJReXhWUVVGRExFTkJRVU1zUlVGQlJTeERRVUZETzFsQlEzQkNMRWxCUVVrc1EwRkJReXhEUVVGRExFdEJRVXNzUlVGQlJUdG5Ra0ZEVkN4RFFVRkRMRU5CUVVNc1VVRkJVU3hEUVVGRExFMUJRVTBzUjBGQlJ5eERRVUZETEVOQlFVTXNWMEZCVnl4RFFVRkRMRU5CUVVNc1EwRkJReXhEUVVGRExFTkJRVU1zVjBGQlZ5eERRVUZETEVOQlFVTXNRMEZCUXl4SlFVRkpMRU5CUVVNN1owSkJRM3BFTEU5QlFVOHNRMEZCUXl4RFFVRkRMRU5CUVVNc1IwRkJSeXhWUVVGVkxFTkJRVU1zUTBGQlF5eERRVUZETEVOQlFVTTdZVUZET1VJN2FVSkJRVTA3WjBKQlEwZ3NRMEZCUXl4RFFVRkRMRkZCUVZFc1EwRkJReXhOUVVGTkxFZEJRVWNzUTBGQlF5eERRVUZETzJGQlEzcENPMWxCUTBRc1NVRkJTU3hEUVVGRExFZEJRVWNzUTBGQlF5eERRVUZETEVOQlFVTXNTMEZCU3l4SlFVRkpMRU5CUVVNc1EwRkJReXhIUVVGSExFTkJRVU1zUlVGQlJTeERRVUZETEVkQlFVY3NRMEZCUXl4RFFVRkRMRU5CUVVNc1RVRkJUU3hKUVVGSkxFTkJRVU1zUTBGQlF5eEhRVUZITEVOQlFVTXNRMEZCUXp0WlFVTndSQ3hKUVVGSkxFVkJRVVVzUjBGQlJ5eEZRVUZGTEVOQlFVTXNRMEZCUXl4RFFVRkRMRVZCUVVVc1JVRkJSU3hIUVVGSExFVkJRVVVzUTBGQlF5eERRVUZETEVOQlFVTXNRMEZCUXp0WlFVTXpRaXhEUVVGRExFTkJRVU1zVFVGQlRTeEhRVUZITEVsQlFVa3NVMEZCVXl4RFFVRkRMRVZCUVVVc1IwRkJSeXhEUVVGRExFVkJRVVVzUlVGQlJTeEhRVUZITEVOQlFVTXNSVUZCUlN4RlFVRkZMRWRCUVVjc1EwRkJReXhGUVVGRkxFVkJRVVVzUjBGQlJ5eERRVUZETEVOQlFVTXNRMEZCUXp0UlFVTTNSQ3hEUVVGRExFTkJRVU1zUTBGQlF6dEpRVU5RTEVOQlFVTTdTVUZGUkN3MlFrRkJVU3hIUVVGU0xGVkJRVk1zUlVGQldTeEZRVUZGTEVWQlFWa3NSVUZCUlN4RFFVRlhPMUZCUXpWRExFbEJRVWtzUTBGQlF5eEpRVUZKTEVOQlFVTXNVMEZCVXl4SlFVRkpMRU5CUVVNc1EwRkJReXhKUVVGSkxFTkJRVU1zWVVGQllTeEpRVUZKTEVsQlFVa3NRMEZCUXl4WlFVRlpMRU5CUVVNN1dVRkJSU3hQUVVGUE8xRkJRekZGTEVsQlFVa3NRMEZCUXl4UFFVRlBMRU5CUVVNc1JVRkJSU3hGUVVGRkxFVkJRVVVzUlVGQlJTeEZRVUZGTEVWQlFVVXNRMEZCUXl4RlFVRkZMRlZCUVVFc1EwRkJReXhKUVVGSExFOUJRVUVzUTBGQlF5eERRVUZETEVWQlFVVXNSVUZCU2l4RFFVRkpMRVZCUVVVc1NVRkJTU3hEUVVGRExGbEJRVmtzUlVGQlJTeDVRa0ZCZVVJc1JVRkRPVVVzVlVGQlFTeERRVUZETEVsQlFVa3NUMEZCUVN4RFFVRkRMRU5CUVVNc1RVRkJUU3hEUVVGRExGVkJRVlVzUTBGQlF5eERRVUZETEVOQlFXMUNMRU5CUVVNc1EwRkJReXhSUVVGVExFTkJRVU1zUzBGQlN5eERRVUZETEVkQlFVY3NRMEZCUXl4RFFVRkRMRkZCUVZFc1EwRkJReXhSUVVGUkxFVkJRVVVzUTBGQlF5eEZRVUZ1Uml4RFFVRnRSaXhGUVVONFJpeFZRVUZCTEVOQlFVTTdXVUZEUnl4SlFVRkpMRWxCUVVrc1IwRkJSeXhEUVVGRExFTkJRVzFDTEVOQlFVTXNRMEZCUXl4TlFVRlBMRU5CUVVNc1MwRkJTeXhEUVVGRExFZEJRVWNzUTBGQlF5eERRVUZETEUxQlFVMHNRMEZCUXl4UlFVRlJMRVZCUVVVc1EwRkJRenRaUVVOMFJTeEpRVUZKTEVsQlFVa3NSMEZCUnl4RFFVRkRMRU5CUVcxQ0xFTkJRVU1zUTBGQlF5eE5RVUZQTEVOQlFVTXNTMEZCU3l4RFFVRkRMRWRCUVVjc1EwRkJReXhEUVVGRExFMUJRVTBzUTBGQlF5eFJRVUZSTEVWQlFVVXNRMEZCUXp0WlFVTjBSU3hKUVVGSkxFVkJRVVVzUjBGQlJ5eERRVUZETEVOQlFVTXNUMEZCVHl4SFFVRkhMRU5CUVVNc1EwRkJRenRaUVVOMlFpeERRVUZETEVOQlFVTXNUVUZCVFN4RFFVRkRMRU5CUVVNc1IwRkJSeXhKUVVGSkxFZEJRVWNzUlVGQlJTeERRVUZETzFsQlEzWkNMRU5CUVVNc1EwRkJReXhOUVVGTkxFTkJRVU1zUTBGQlF5eEhRVUZITEVsQlFVa3NSMEZCUnl4RlFVRkZMRU5CUVVNN1VVRkRNMElzUTBGQlF5eERRVUZETEVOQlFVTTdTVUZEV0N4RFFVRkRPMGxCUlVRc05rSkJRVkVzUjBGQlVpeFZRVUZUTEVWQlFWa3NSVUZCUlN4RlFVRlpMRVZCUVVVc1EwRkJWenRSUVVNMVF5eEpRVUZKTEVOQlFVTXNTVUZCU1N4RFFVRkRMRk5CUVZNc1NVRkJTU3hEUVVGRExFbEJRVWtzUTBGQlF5eFpRVUZaTzFsQlFVVXNUMEZCVHp0UlFVTnNSQ3hKUVVGSkxFTkJRVU1zVDBGQlR5eERRVUZETEVWQlFVVXNSVUZCUlN4RlFVRkZMRVZCUVVVc1JVRkJSU3hGUVVGRkxFTkJRVU1zUlVGQlJTeFZRVUZCTEVOQlFVTXNTVUZCUnl4UFFVRkJMRU5CUVVNc1EwRkJReXhGUVVGRkxFVkJRVW9zUTBGQlNTeEZRVUZGTEVsQlFVa3NRMEZCUXl4WlFVRlpMRVZCUVVVc2VVSkJRWGxDTEVWQlF6bEZMRlZCUVVFc1EwRkJReXhKUVVGSkxFOUJRVUVzUTBGQlF5eERRVUZETEUxQlFVMHNRMEZCUXl4VlFVRlZMRU5CUVVNc1EwRkJReXhEUVVGdFFpeERRVUZETEVOQlFVTXNVVUZCVXl4RFFVRkRMRXRCUVVzc1EwRkJReXhIUVVGSExFTkJRVU1zUTBGQlF5eFJRVUZSTEVOQlFVTXNVVUZCVVN4RlFVRkZMRU5CUVVNc1JVRkJia1lzUTBGQmJVWXNSVUZEZUVZc1ZVRkJRU3hEUVVGRE8xbEJRMGNzU1VGQlNTeEpRVUZKTEVkQlFVY3NRMEZCUXl4RFFVRnRRaXhEUVVGRExFTkJRVU1zVFVGQlR5eERRVUZETEV0QlFVc3NRMEZCUXl4SFFVRkhMRU5CUVVNc1EwRkJReXhOUVVGTkxFTkJRVU1zVVVGQlVTeEZRVUZGTEVOQlFVTTdXVUZEZEVVc1NVRkJTU3hKUVVGSkxFZEJRVWNzUTBGQlF5eERRVUZ0UWl4RFFVRkRMRU5CUVVNc1RVRkJUeXhEUVVGRExFdEJRVXNzUTBGQlF5eEhRVUZITEVOQlFVTXNRMEZCUXl4TlFVRk5MRU5CUVVNc1VVRkJVU3hGUVVGRkxFTkJRVU03V1VGRGRFVXNTVUZCU1N4RlFVRkZMRWRCUVVjc1EwRkJReXhEUVVGRExFOUJRVThzUjBGQlJ5eERRVUZETEVOQlFVTTdXVUZEZGtJc1EwRkJReXhEUVVGRExFMUJRVTBzUTBGQlF5eERRVUZETEVkQlFVY3NTVUZCU1N4SFFVRkhMRVZCUVVVc1EwRkJRenRaUVVGQkxFTkJRVU03V1VGRGVFSXNRMEZCUXl4RFFVRkRMRTFCUVUwc1EwRkJReXhEUVVGRExFZEJRVWNzU1VGQlNTeEhRVUZITEVWQlFVVXNRMEZCUXp0UlFVTXpRaXhEUVVGRExFTkJRVU1zUTBGQlF6dEpRVU5ZTEVOQlFVTTdTVUZGUkN4eFEwRkJaMElzUjBGQmFFSTdVVUZCUVN4cFFrRkxRenRSUVVwSExFOUJRVTg3V1VGRFNDeFZRVUZETEVWQlFVVXNSVUZCUlN4RlFVRkZMRVZCUVVVc1EwRkJReXhKUVVGTExFOUJRVUVzUzBGQlNTeERRVUZETEZGQlFWRXNRMEZCUXl4RlFVRkZMRVZCUVVVc1JVRkJSU3hGUVVGRkxFTkJRVU1zUTBGQlF5eEZRVUY0UWl4RFFVRjNRanRaUVVOMlF5eFZRVUZETEVWQlFVVXNSVUZCUlN4RlFVRkZMRVZCUVVVc1EwRkJReXhKUVVGTExFOUJRVUVzUzBGQlNTeERRVUZETEZGQlFWRXNRMEZCUXl4RlFVRkZMRVZCUVVVc1JVRkJSU3hGUVVGRkxFTkJRVU1zUTBGQlF5eEZRVUY0UWl4RFFVRjNRanRUUVVNeFF5eERRVUZETzBsQlEwNHNRMEZCUXp0SlFVVlBMRFJDUVVGUExFZEJRV1lzVlVGQlowSXNSVUZCV1N4RlFVRkZMRVZCUVZrc1JVRkJSU3hMUVVGbExFVkJRVVVzVDBGQmFVSXNSVUZETVVVc1ZVRkJiME1zUlVGRGNFTXNSVUZCWjBJc1JVRkRhRUlzYlVKQlFYbEVMRVZCUTNwRUxHZENRVUYxUXl4RlFVTjJReXhwUWtGQk9FTTdVVUZGT1VNc1NVRkJTU3hEUVVGRExIVkNRVUYxUWl4RFFVRkRMRVZCUVVVc1JVRkJSU3hGUVVGRkxFVkJRVVVzVDBGQlR5eEZRVUZGTEZWQlFWVXNRMEZCUXl4RFFVRkRPMUZCUXpGRUxFbEJRVWtzU1VGQlNTeERRVUZETEZOQlFWTXNTVUZCU1N4SlFVRkpMRU5CUVVNc1lVRkJZU3hGUVVGRk8xbEJRM1JETEd0Q1FVRnJRaXhEUVVGRExFbEJRVWtzUTBGQlF5eFRRVUZUTEVOQlFVTXNRMEZCUXp0WlFVTnVReXhGUVVGRkxFZEJRVWNzUlVGQlJTeERRVUZETEUxQlFVMHNRMEZCUXl4dFFrRkJiVUlzUTBGQlF5eEpRVUZKTEVOQlFVTXNVMEZCVXl4RFFVRkRMRU5CUVVNc1EwRkJRenRUUVVOMlJEdFJRVU5FTEVsQlFVa3NRMEZCUXl4TFFVRkxMRU5CUVVNc1NVRkJTU3hEUVVGRExGTkJRVk1zUlVGQlJTeEZRVUZGTEVWQlFVVXNTMEZCU3l4RlFVRkZMRTlCUVU4c1EwRkJReXhEUVVGRE8xRkJReTlETEVsQlFVa3NRMEZCUXl4TFFVRkxMRU5CUVVNc1QwRkJUeXhEUVVGRExHZENRVUZuUWl4RFFVRkRMRU5CUVVNN1VVRkRja01zU1VGQlNTeEpRVUZKTEVOQlFVTXNVMEZCVXl4SlFVRkpMRWxCUVVrc1EwRkJReXhoUVVGaExFVkJRVVU3V1VGRGRFTXNTVUZCU1N4RFFVRkRMRTFCUVUwc1EwRkJReXhQUVVGUExFTkJRVU1zYVVKQlFXbENMRU5CUVVNc1EwRkJRenRaUVVOMlF5eHJRa0ZCYTBJc1EwRkJReXhKUVVGSkxFTkJRVU1zVTBGQlV5eERRVUZETEVOQlFVTTdVMEZEZEVNN1NVRkRUQ3hEUVVGRE8wbEJSVThzTUVKQlFVc3NSMEZCWWl4VlFVRmpMRVZCUVdNc1JVRkJSU3hGUVVGblFpeEZRVUZGTEZGQlFXdENMRVZCUVVVc1QwRkJhVUk3VVVGRGFrWXNTVUZCU1N4TlFVRk5MRWRCUVVjc1NVRkJTU3hoUVVGTkxFTkJRVU1zUlVGQlJTeEZRVUZGTEVWQlFVVXNRMEZCUXl4RFFVRkRPMUZCUTJoRExFMUJRVTBzUTBGQlF5eHZRa0ZCYjBJc1EwRkJReXhSUVVGUkxFTkJRVU1zUTBGQlF6dFJRVU4wUXl4TlFVRk5MRU5CUVVNc2JVSkJRVzFDTEVOQlFVTXNUMEZCVHl4RFFVRkRMRU5CUVVNN1VVRkRjRU1zVFVGQlRTeERRVUZETEV0QlFVc3NSVUZCUlN4RFFVRkRPMGxCUTI1Q0xFTkJRVU03U1VGRFRDeHBRa0ZCUXp0QlFVRkVMRU5CUVVNc1FVRnNTMFFzU1VGclMwTTdRVUZzUzFrc1owTkJRVlVpZlE9PSIsIlwidXNlIHN0cmljdFwiO1xuT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsIFwiX19lc01vZHVsZVwiLCB7IHZhbHVlOiB0cnVlIH0pO1xudmFyIHBxdWV1ZV8xID0gcmVxdWlyZShcIi4vcHF1ZXVlXCIpO1xudmFyIE5laWdoYm91ciA9IChmdW5jdGlvbiAoKSB7XG4gICAgZnVuY3Rpb24gTmVpZ2hib3VyKGlkLCBkaXN0YW5jZSkge1xuICAgICAgICB0aGlzLmlkID0gaWQ7XG4gICAgICAgIHRoaXMuZGlzdGFuY2UgPSBkaXN0YW5jZTtcbiAgICB9XG4gICAgcmV0dXJuIE5laWdoYm91cjtcbn0oKSk7XG52YXIgTm9kZSA9IChmdW5jdGlvbiAoKSB7XG4gICAgZnVuY3Rpb24gTm9kZShpZCkge1xuICAgICAgICB0aGlzLmlkID0gaWQ7XG4gICAgICAgIHRoaXMubmVpZ2hib3VycyA9IFtdO1xuICAgIH1cbiAgICByZXR1cm4gTm9kZTtcbn0oKSk7XG52YXIgUXVldWVFbnRyeSA9IChmdW5jdGlvbiAoKSB7XG4gICAgZnVuY3Rpb24gUXVldWVFbnRyeShub2RlLCBwcmV2LCBkKSB7XG4gICAgICAgIHRoaXMubm9kZSA9IG5vZGU7XG4gICAgICAgIHRoaXMucHJldiA9IHByZXY7XG4gICAgICAgIHRoaXMuZCA9IGQ7XG4gICAgfVxuICAgIHJldHVybiBRdWV1ZUVudHJ5O1xufSgpKTtcbnZhciBDYWxjdWxhdG9yID0gKGZ1bmN0aW9uICgpIHtcbiAgICBmdW5jdGlvbiBDYWxjdWxhdG9yKG4sIGVzLCBnZXRTb3VyY2VJbmRleCwgZ2V0VGFyZ2V0SW5kZXgsIGdldExlbmd0aCkge1xuICAgICAgICB0aGlzLm4gPSBuO1xuICAgICAgICB0aGlzLmVzID0gZXM7XG4gICAgICAgIHRoaXMubmVpZ2hib3VycyA9IG5ldyBBcnJheSh0aGlzLm4pO1xuICAgICAgICB2YXIgaSA9IHRoaXMubjtcbiAgICAgICAgd2hpbGUgKGktLSlcbiAgICAgICAgICAgIHRoaXMubmVpZ2hib3Vyc1tpXSA9IG5ldyBOb2RlKGkpO1xuICAgICAgICBpID0gdGhpcy5lcy5sZW5ndGg7XG4gICAgICAgIHdoaWxlIChpLS0pIHtcbiAgICAgICAgICAgIHZhciBlID0gdGhpcy5lc1tpXTtcbiAgICAgICAgICAgIHZhciB1ID0gZ2V0U291cmNlSW5kZXgoZSksIHYgPSBnZXRUYXJnZXRJbmRleChlKTtcbiAgICAgICAgICAgIHZhciBkID0gZ2V0TGVuZ3RoKGUpO1xuICAgICAgICAgICAgdGhpcy5uZWlnaGJvdXJzW3VdLm5laWdoYm91cnMucHVzaChuZXcgTmVpZ2hib3VyKHYsIGQpKTtcbiAgICAgICAgICAgIHRoaXMubmVpZ2hib3Vyc1t2XS5uZWlnaGJvdXJzLnB1c2gobmV3IE5laWdoYm91cih1LCBkKSk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgQ2FsY3VsYXRvci5wcm90b3R5cGUuRGlzdGFuY2VNYXRyaXggPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBEID0gbmV3IEFycmF5KHRoaXMubik7XG4gICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgdGhpcy5uOyArK2kpIHtcbiAgICAgICAgICAgIERbaV0gPSB0aGlzLmRpamtzdHJhTmVpZ2hib3VycyhpKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gRDtcbiAgICB9O1xuICAgIENhbGN1bGF0b3IucHJvdG90eXBlLkRpc3RhbmNlc0Zyb21Ob2RlID0gZnVuY3Rpb24gKHN0YXJ0KSB7XG4gICAgICAgIHJldHVybiB0aGlzLmRpamtzdHJhTmVpZ2hib3VycyhzdGFydCk7XG4gICAgfTtcbiAgICBDYWxjdWxhdG9yLnByb3RvdHlwZS5QYXRoRnJvbU5vZGVUb05vZGUgPSBmdW5jdGlvbiAoc3RhcnQsIGVuZCkge1xuICAgICAgICByZXR1cm4gdGhpcy5kaWprc3RyYU5laWdoYm91cnMoc3RhcnQsIGVuZCk7XG4gICAgfTtcbiAgICBDYWxjdWxhdG9yLnByb3RvdHlwZS5QYXRoRnJvbU5vZGVUb05vZGVXaXRoUHJldkNvc3QgPSBmdW5jdGlvbiAoc3RhcnQsIGVuZCwgcHJldkNvc3QpIHtcbiAgICAgICAgdmFyIHEgPSBuZXcgcHF1ZXVlXzEuUHJpb3JpdHlRdWV1ZShmdW5jdGlvbiAoYSwgYikgeyByZXR1cm4gYS5kIDw9IGIuZDsgfSksIHUgPSB0aGlzLm5laWdoYm91cnNbc3RhcnRdLCBxdSA9IG5ldyBRdWV1ZUVudHJ5KHUsIG51bGwsIDApLCB2aXNpdGVkRnJvbSA9IHt9O1xuICAgICAgICBxLnB1c2gocXUpO1xuICAgICAgICB3aGlsZSAoIXEuZW1wdHkoKSkge1xuICAgICAgICAgICAgcXUgPSBxLnBvcCgpO1xuICAgICAgICAgICAgdSA9IHF1Lm5vZGU7XG4gICAgICAgICAgICBpZiAodS5pZCA9PT0gZW5kKSB7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB2YXIgaSA9IHUubmVpZ2hib3Vycy5sZW5ndGg7XG4gICAgICAgICAgICB3aGlsZSAoaS0tKSB7XG4gICAgICAgICAgICAgICAgdmFyIG5laWdoYm91ciA9IHUubmVpZ2hib3Vyc1tpXSwgdiA9IHRoaXMubmVpZ2hib3Vyc1tuZWlnaGJvdXIuaWRdO1xuICAgICAgICAgICAgICAgIGlmIChxdS5wcmV2ICYmIHYuaWQgPT09IHF1LnByZXYubm9kZS5pZClcbiAgICAgICAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICAgICAgdmFyIHZpZHVpZCA9IHYuaWQgKyAnLCcgKyB1LmlkO1xuICAgICAgICAgICAgICAgIGlmICh2aWR1aWQgaW4gdmlzaXRlZEZyb20gJiYgdmlzaXRlZEZyb21bdmlkdWlkXSA8PSBxdS5kKVxuICAgICAgICAgICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICAgICAgICB2YXIgY2MgPSBxdS5wcmV2ID8gcHJldkNvc3QocXUucHJldi5ub2RlLmlkLCB1LmlkLCB2LmlkKSA6IDAsIHQgPSBxdS5kICsgbmVpZ2hib3VyLmRpc3RhbmNlICsgY2M7XG4gICAgICAgICAgICAgICAgdmlzaXRlZEZyb21bdmlkdWlkXSA9IHQ7XG4gICAgICAgICAgICAgICAgcS5wdXNoKG5ldyBRdWV1ZUVudHJ5KHYsIHF1LCB0KSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgdmFyIHBhdGggPSBbXTtcbiAgICAgICAgd2hpbGUgKHF1LnByZXYpIHtcbiAgICAgICAgICAgIHF1ID0gcXUucHJldjtcbiAgICAgICAgICAgIHBhdGgucHVzaChxdS5ub2RlLmlkKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gcGF0aDtcbiAgICB9O1xuICAgIENhbGN1bGF0b3IucHJvdG90eXBlLmRpamtzdHJhTmVpZ2hib3VycyA9IGZ1bmN0aW9uIChzdGFydCwgZGVzdCkge1xuICAgICAgICBpZiAoZGVzdCA9PT0gdm9pZCAwKSB7IGRlc3QgPSAtMTsgfVxuICAgICAgICB2YXIgcSA9IG5ldyBwcXVldWVfMS5Qcmlvcml0eVF1ZXVlKGZ1bmN0aW9uIChhLCBiKSB7IHJldHVybiBhLmQgPD0gYi5kOyB9KSwgaSA9IHRoaXMubmVpZ2hib3Vycy5sZW5ndGgsIGQgPSBuZXcgQXJyYXkoaSk7XG4gICAgICAgIHdoaWxlIChpLS0pIHtcbiAgICAgICAgICAgIHZhciBub2RlID0gdGhpcy5uZWlnaGJvdXJzW2ldO1xuICAgICAgICAgICAgbm9kZS5kID0gaSA9PT0gc3RhcnQgPyAwIDogTnVtYmVyLlBPU0lUSVZFX0lORklOSVRZO1xuICAgICAgICAgICAgbm9kZS5xID0gcS5wdXNoKG5vZGUpO1xuICAgICAgICB9XG4gICAgICAgIHdoaWxlICghcS5lbXB0eSgpKSB7XG4gICAgICAgICAgICB2YXIgdSA9IHEucG9wKCk7XG4gICAgICAgICAgICBkW3UuaWRdID0gdS5kO1xuICAgICAgICAgICAgaWYgKHUuaWQgPT09IGRlc3QpIHtcbiAgICAgICAgICAgICAgICB2YXIgcGF0aCA9IFtdO1xuICAgICAgICAgICAgICAgIHZhciB2ID0gdTtcbiAgICAgICAgICAgICAgICB3aGlsZSAodHlwZW9mIHYucHJldiAhPT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgICAgICAgICAgICAgcGF0aC5wdXNoKHYucHJldi5pZCk7XG4gICAgICAgICAgICAgICAgICAgIHYgPSB2LnByZXY7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJldHVybiBwYXRoO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaSA9IHUubmVpZ2hib3Vycy5sZW5ndGg7XG4gICAgICAgICAgICB3aGlsZSAoaS0tKSB7XG4gICAgICAgICAgICAgICAgdmFyIG5laWdoYm91ciA9IHUubmVpZ2hib3Vyc1tpXTtcbiAgICAgICAgICAgICAgICB2YXIgdiA9IHRoaXMubmVpZ2hib3Vyc1tuZWlnaGJvdXIuaWRdO1xuICAgICAgICAgICAgICAgIHZhciB0ID0gdS5kICsgbmVpZ2hib3VyLmRpc3RhbmNlO1xuICAgICAgICAgICAgICAgIGlmICh1LmQgIT09IE51bWJlci5NQVhfVkFMVUUgJiYgdi5kID4gdCkge1xuICAgICAgICAgICAgICAgICAgICB2LmQgPSB0O1xuICAgICAgICAgICAgICAgICAgICB2LnByZXYgPSB1O1xuICAgICAgICAgICAgICAgICAgICBxLnJlZHVjZUtleSh2LnEsIHYsIGZ1bmN0aW9uIChlLCBxKSB7IHJldHVybiBlLnEgPSBxOyB9KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGQ7XG4gICAgfTtcbiAgICByZXR1cm4gQ2FsY3VsYXRvcjtcbn0oKSk7XG5leHBvcnRzLkNhbGN1bGF0b3IgPSBDYWxjdWxhdG9yO1xuLy8jIHNvdXJjZU1hcHBpbmdVUkw9ZGF0YTphcHBsaWNhdGlvbi9qc29uO2Jhc2U2NCxleUoyWlhKemFXOXVJam96TENKbWFXeGxJam9pYzJodmNuUmxjM1J3WVhSb2N5NXFjeUlzSW5OdmRYSmpaVkp2YjNRaU9pSWlMQ0p6YjNWeVkyVnpJanBiSWk0dUx5NHVMMWRsWWtOdmJHRXZjM0pqTDNOb2IzSjBaWE4wY0dGMGFITXVkSE1pWFN3aWJtRnRaWE1pT2x0ZExDSnRZWEJ3YVc1bmN5STZJanM3UVVGQlFTeHRRMEZCYlVRN1FVRkZia1E3U1VGRFNTeHRRa0ZCYlVJc1JVRkJWU3hGUVVGVExGRkJRV2RDTzFGQlFXNURMRTlCUVVVc1IwRkJSaXhGUVVGRkxFTkJRVkU3VVVGQlV5eGhRVUZSTEVkQlFWSXNVVUZCVVN4RFFVRlJPMGxCUVVrc1EwRkJRenRKUVVNdlJDeG5Ra0ZCUXp0QlFVRkVMRU5CUVVNc1FVRkdSQ3hKUVVWRE8wRkJSVVE3U1VGRFNTeGpRVUZ0UWl4RlFVRlZPMUZCUVZZc1QwRkJSU3hIUVVGR0xFVkJRVVVzUTBGQlVUdFJRVU42UWl4SlFVRkpMRU5CUVVNc1ZVRkJWU3hIUVVGSExFVkJRVVVzUTBGQlF6dEpRVU42UWl4RFFVRkRPMGxCUzB3c1YwRkJRenRCUVVGRUxFTkJRVU1zUVVGU1JDeEpRVkZETzBGQlJVUTdTVUZEU1N4dlFrRkJiVUlzU1VGQlZTeEZRVUZUTEVsQlFXZENMRVZCUVZNc1EwRkJVenRSUVVGeVJDeFRRVUZKTEVkQlFVb3NTVUZCU1N4RFFVRk5PMUZCUVZNc1UwRkJTU3hIUVVGS0xFbEJRVWtzUTBGQldUdFJRVUZUTEUxQlFVTXNSMEZCUkN4RFFVRkRMRU5CUVZFN1NVRkJSeXhEUVVGRE8wbEJRMmhHTEdsQ1FVRkRPMEZCUVVRc1EwRkJReXhCUVVaRUxFbEJSVU03UVVGVFJEdEpRVWRKTEc5Q1FVRnRRaXhEUVVGVExFVkJRVk1zUlVGQlZTeEZRVUZGTEdOQlFXMURMRVZCUVVVc1kwRkJiVU1zUlVGQlJTeFRRVUU0UWp0UlFVRjBTU3hOUVVGRExFZEJRVVFzUTBGQlF5eERRVUZSTzFGQlFWTXNUMEZCUlN4SFFVRkdMRVZCUVVVc1EwRkJVVHRSUVVNelF5eEpRVUZKTEVOQlFVTXNWVUZCVlN4SFFVRkhMRWxCUVVrc1MwRkJTeXhEUVVGRExFbEJRVWtzUTBGQlF5eERRVUZETEVOQlFVTXNRMEZCUXp0UlFVTndReXhKUVVGSkxFTkJRVU1zUjBGQlJ5eEpRVUZKTEVOQlFVTXNRMEZCUXl4RFFVRkRPMUZCUVVNc1QwRkJUeXhEUVVGRExFVkJRVVU3V1VGQlJTeEpRVUZKTEVOQlFVTXNWVUZCVlN4RFFVRkRMRU5CUVVNc1EwRkJReXhIUVVGSExFbEJRVWtzU1VGQlNTeERRVUZETEVOQlFVTXNRMEZCUXl4RFFVRkRPMUZCUlRkRUxFTkJRVU1zUjBGQlJ5eEpRVUZKTEVOQlFVTXNSVUZCUlN4RFFVRkRMRTFCUVUwc1EwRkJRenRSUVVGRExFOUJRVThzUTBGQlF5eEZRVUZGTEVWQlFVVTdXVUZETlVJc1NVRkJTU3hEUVVGRExFZEJRVWNzU1VGQlNTeERRVUZETEVWQlFVVXNRMEZCUXl4RFFVRkRMRU5CUVVNc1EwRkJRenRaUVVOdVFpeEpRVUZKTEVOQlFVTXNSMEZCVnl4alFVRmpMRU5CUVVNc1EwRkJReXhEUVVGRExFVkJRVVVzUTBGQlF5eEhRVUZYTEdOQlFXTXNRMEZCUXl4RFFVRkRMRU5CUVVNc1EwRkJRenRaUVVOcVJTeEpRVUZKTEVOQlFVTXNSMEZCUnl4VFFVRlRMRU5CUVVNc1EwRkJReXhEUVVGRExFTkJRVU03V1VGRGNrSXNTVUZCU1N4RFFVRkRMRlZCUVZVc1EwRkJReXhEUVVGRExFTkJRVU1zUTBGQlF5eFZRVUZWTEVOQlFVTXNTVUZCU1N4RFFVRkRMRWxCUVVrc1UwRkJVeXhEUVVGRExFTkJRVU1zUlVGQlJTeERRVUZETEVOQlFVTXNRMEZCUXl4RFFVRkRPMWxCUTNoRUxFbEJRVWtzUTBGQlF5eFZRVUZWTEVOQlFVTXNRMEZCUXl4RFFVRkRMRU5CUVVNc1ZVRkJWU3hEUVVGRExFbEJRVWtzUTBGQlF5eEpRVUZKTEZOQlFWTXNRMEZCUXl4RFFVRkRMRVZCUVVVc1EwRkJReXhEUVVGRExFTkJRVU1zUTBGQlF6dFRRVU16UkR0SlFVTk1MRU5CUVVNN1NVRlZSQ3h0UTBGQll5eEhRVUZrTzFGQlEwa3NTVUZCU1N4RFFVRkRMRWRCUVVjc1NVRkJTU3hMUVVGTExFTkJRVU1zU1VGQlNTeERRVUZETEVOQlFVTXNRMEZCUXl4RFFVRkRPMUZCUXpGQ0xFdEJRVXNzU1VGQlNTeERRVUZETEVkQlFVY3NRMEZCUXl4RlFVRkZMRU5CUVVNc1IwRkJSeXhKUVVGSkxFTkJRVU1zUTBGQlF5eEZRVUZGTEVWQlFVVXNRMEZCUXl4RlFVRkZPMWxCUXpkQ0xFTkJRVU1zUTBGQlF5eERRVUZETEVOQlFVTXNSMEZCUnl4SlFVRkpMRU5CUVVNc2EwSkJRV3RDTEVOQlFVTXNRMEZCUXl4RFFVRkRMRU5CUVVNN1UwRkRja003VVVGRFJDeFBRVUZQTEVOQlFVTXNRMEZCUXp0SlFVTmlMRU5CUVVNN1NVRlJSQ3h6UTBGQmFVSXNSMEZCYWtJc1ZVRkJhMElzUzBGQllUdFJRVU16UWl4UFFVRlBMRWxCUVVrc1EwRkJReXhyUWtGQmEwSXNRMEZCUXl4TFFVRkxMRU5CUVVNc1EwRkJRenRKUVVNeFF5eERRVUZETzBsQlJVUXNkVU5CUVd0Q0xFZEJRV3hDTEZWQlFXMUNMRXRCUVdFc1JVRkJSU3hIUVVGWE8xRkJRM3BETEU5QlFVOHNTVUZCU1N4RFFVRkRMR3RDUVVGclFpeERRVUZETEV0QlFVc3NSVUZCUlN4SFFVRkhMRU5CUVVNc1EwRkJRenRKUVVNdlF5eERRVUZETzBsQlMwUXNiVVJCUVRoQ0xFZEJRVGxDTEZWQlEwa3NTMEZCWVN4RlFVTmlMRWRCUVZjc1JVRkRXQ3hSUVVFNFF6dFJRVVU1UXl4SlFVRkpMRU5CUVVNc1IwRkJSeXhKUVVGSkxITkNRVUZoTEVOQlFXRXNWVUZCUXl4RFFVRkRMRVZCUVVVc1EwRkJReXhKUVVGTExFOUJRVUVzUTBGQlF5eERRVUZETEVOQlFVTXNTVUZCU1N4RFFVRkRMRU5CUVVNc1EwRkJReXhGUVVGV0xFTkJRVlVzUTBGQlF5eEZRVU4yUkN4RFFVRkRMRWRCUVZNc1NVRkJTU3hEUVVGRExGVkJRVlVzUTBGQlF5eExRVUZMTEVOQlFVTXNSVUZEYUVNc1JVRkJSU3hIUVVGbExFbEJRVWtzVlVGQlZTeERRVUZETEVOQlFVTXNSVUZCUXl4SlFVRkpMRVZCUVVNc1EwRkJReXhEUVVGRExFVkJRM3BETEZkQlFWY3NSMEZCUnl4RlFVRkZMRU5CUVVNN1VVRkRja0lzUTBGQlF5eERRVUZETEVsQlFVa3NRMEZCUXl4RlFVRkZMRU5CUVVNc1EwRkJRenRSUVVOWUxFOUJRVTBzUTBGQlF5eERRVUZETEVOQlFVTXNTMEZCU3l4RlFVRkZMRVZCUVVVN1dVRkRaQ3hGUVVGRkxFZEJRVWNzUTBGQlF5eERRVUZETEVkQlFVY3NSVUZCUlN4RFFVRkRPMWxCUTJJc1EwRkJReXhIUVVGSExFVkJRVVVzUTBGQlF5eEpRVUZKTEVOQlFVTTdXVUZEV2l4SlFVRkpMRU5CUVVNc1EwRkJReXhGUVVGRkxFdEJRVXNzUjBGQlJ5eEZRVUZGTzJkQ1FVTmtMRTFCUVUwN1lVRkRWRHRaUVVORUxFbEJRVWtzUTBGQlF5eEhRVUZITEVOQlFVTXNRMEZCUXl4VlFVRlZMRU5CUVVNc1RVRkJUU3hEUVVGRE8xbEJRVU1zVDBGQlR5eERRVUZETEVWQlFVVXNSVUZCUlR0blFrRkRja01zU1VGQlNTeFRRVUZUTEVkQlFVY3NRMEZCUXl4RFFVRkRMRlZCUVZVc1EwRkJReXhEUVVGRExFTkJRVU1zUlVGRE0wSXNRMEZCUXl4SFFVRkhMRWxCUVVrc1EwRkJReXhWUVVGVkxFTkJRVU1zVTBGQlV5eERRVUZETEVWQlFVVXNRMEZCUXl4RFFVRkRPMmRDUVVkMFF5eEpRVUZKTEVWQlFVVXNRMEZCUXl4SlFVRkpMRWxCUVVrc1EwRkJReXhEUVVGRExFVkJRVVVzUzBGQlN5eEZRVUZGTEVOQlFVTXNTVUZCU1N4RFFVRkRMRWxCUVVrc1EwRkJReXhGUVVGRk8yOUNRVUZGTEZOQlFWTTdaMEpCU1d4RUxFbEJRVWtzVFVGQlRTeEhRVUZITEVOQlFVTXNRMEZCUXl4RlFVRkZMRWRCUVVjc1IwRkJSeXhIUVVGSExFTkJRVU1zUTBGQlF5eEZRVUZGTEVOQlFVTTdaMEpCUXk5Q0xFbEJRVWNzVFVGQlRTeEpRVUZKTEZkQlFWY3NTVUZCU1N4WFFVRlhMRU5CUVVNc1RVRkJUU3hEUVVGRExFbEJRVWtzUlVGQlJTeERRVUZETEVOQlFVTTdiMEpCUTI1RUxGTkJRVk03WjBKQlJXSXNTVUZCU1N4RlFVRkZMRWRCUVVjc1JVRkJSU3hEUVVGRExFbEJRVWtzUTBGQlF5eERRVUZETEVOQlFVTXNVVUZCVVN4RFFVRkRMRVZCUVVVc1EwRkJReXhKUVVGSkxFTkJRVU1zU1VGQlNTeERRVUZETEVWQlFVVXNSVUZCUlN4RFFVRkRMRU5CUVVNc1JVRkJSU3hGUVVGRkxFTkJRVU1zUTBGQlF5eEZRVUZGTEVOQlFVTXNRMEZCUXl4RFFVRkRMRU5CUVVNc1EwRkJReXhGUVVONFJDeERRVUZETEVkQlFVY3NSVUZCUlN4RFFVRkRMRU5CUVVNc1IwRkJSeXhUUVVGVExFTkJRVU1zVVVGQlVTeEhRVUZITEVWQlFVVXNRMEZCUXp0blFrRkhka01zVjBGQlZ5eERRVUZETEUxQlFVMHNRMEZCUXl4SFFVRkhMRU5CUVVNc1EwRkJRenRuUWtGRGVFSXNRMEZCUXl4RFFVRkRMRWxCUVVrc1EwRkJReXhKUVVGSkxGVkJRVlVzUTBGQlF5eERRVUZETEVWQlFVVXNSVUZCUlN4RlFVRkZMRU5CUVVNc1EwRkJReXhEUVVGRExFTkJRVU03WVVGRGNFTTdVMEZEU2p0UlFVTkVMRWxCUVVrc1NVRkJTU3hIUVVGWkxFVkJRVVVzUTBGQlF6dFJRVU4yUWl4UFFVRlBMRVZCUVVVc1EwRkJReXhKUVVGSkxFVkJRVVU3V1VGRFdpeEZRVUZGTEVkQlFVY3NSVUZCUlN4RFFVRkRMRWxCUVVrc1EwRkJRenRaUVVOaUxFbEJRVWtzUTBGQlF5eEpRVUZKTEVOQlFVTXNSVUZCUlN4RFFVRkRMRWxCUVVrc1EwRkJReXhGUVVGRkxFTkJRVU1zUTBGQlF6dFRRVU42UWp0UlFVTkVMRTlCUVU4c1NVRkJTU3hEUVVGRE8wbEJRMmhDTEVOQlFVTTdTVUZGVHl4MVEwRkJhMElzUjBGQk1VSXNWVUZCTWtJc1MwRkJZU3hGUVVGRkxFbEJRV2xDTzFGQlFXcENMSEZDUVVGQkxFVkJRVUVzVVVGQlowSXNRMEZCUXp0UlFVTjJSQ3hKUVVGSkxFTkJRVU1zUjBGQlJ5eEpRVUZKTEhOQ1FVRmhMRU5CUVU4c1ZVRkJReXhEUVVGRExFVkJRVVVzUTBGQlF5eEpRVUZMTEU5QlFVRXNRMEZCUXl4RFFVRkRMRU5CUVVNc1NVRkJTU3hEUVVGRExFTkJRVU1zUTBGQlF5eEZRVUZXTEVOQlFWVXNRMEZCUXl4RlFVTnFSQ3hEUVVGRExFZEJRVWNzU1VGQlNTeERRVUZETEZWQlFWVXNRMEZCUXl4TlFVRk5MRVZCUXpGQ0xFTkJRVU1zUjBGQllTeEpRVUZKTEV0QlFVc3NRMEZCUXl4RFFVRkRMRU5CUVVNc1EwRkJRenRSUVVNdlFpeFBRVUZQTEVOQlFVTXNSVUZCUlN4RlFVRkZPMWxCUTFJc1NVRkJTU3hKUVVGSkxFZEJRVk1zU1VGQlNTeERRVUZETEZWQlFWVXNRMEZCUXl4RFFVRkRMRU5CUVVNc1EwRkJRenRaUVVOd1F5eEpRVUZKTEVOQlFVTXNRMEZCUXl4SFFVRkhMRU5CUVVNc1MwRkJTeXhMUVVGTExFTkJRVU1zUTBGQlF5eERRVUZETEVOQlFVTXNRMEZCUXl4RFFVRkRMRU5CUVVNc1RVRkJUU3hEUVVGRExHbENRVUZwUWl4RFFVRkRPMWxCUTNCRUxFbEJRVWtzUTBGQlF5eERRVUZETEVkQlFVY3NRMEZCUXl4RFFVRkRMRWxCUVVrc1EwRkJReXhKUVVGSkxFTkJRVU1zUTBGQlF6dFRRVU42UWp0UlFVTkVMRTlCUVU4c1EwRkJReXhEUVVGRExFTkJRVU1zUzBGQlN5eEZRVUZGTEVWQlFVVTdXVUZGWml4SlFVRkpMRU5CUVVNc1IwRkJSeXhEUVVGRExFTkJRVU1zUjBGQlJ5eEZRVUZGTEVOQlFVTTdXVUZEYUVJc1EwRkJReXhEUVVGRExFTkJRVU1zUTBGQlF5eEZRVUZGTEVOQlFVTXNSMEZCUnl4RFFVRkRMRU5CUVVNc1EwRkJReXhEUVVGRE8xbEJRMlFzU1VGQlNTeERRVUZETEVOQlFVTXNSVUZCUlN4TFFVRkxMRWxCUVVrc1JVRkJSVHRuUWtGRFppeEpRVUZKTEVsQlFVa3NSMEZCWVN4RlFVRkZMRU5CUVVNN1owSkJRM2hDTEVsQlFVa3NRMEZCUXl4SFFVRkhMRU5CUVVNc1EwRkJRenRuUWtGRFZpeFBRVUZQTEU5QlFVOHNRMEZCUXl4RFFVRkRMRWxCUVVrc1MwRkJTeXhYUVVGWExFVkJRVVU3YjBKQlEyeERMRWxCUVVrc1EwRkJReXhKUVVGSkxFTkJRVU1zUTBGQlF5eERRVUZETEVsQlFVa3NRMEZCUXl4RlFVRkZMRU5CUVVNc1EwRkJRenR2UWtGRGNrSXNRMEZCUXl4SFFVRkhMRU5CUVVNc1EwRkJReXhKUVVGSkxFTkJRVU03YVVKQlEyUTdaMEpCUTBRc1QwRkJUeXhKUVVGSkxFTkJRVU03WVVGRFpqdFpRVU5FTEVOQlFVTXNSMEZCUnl4RFFVRkRMRU5CUVVNc1ZVRkJWU3hEUVVGRExFMUJRVTBzUTBGQlF6dFpRVUZETEU5QlFVOHNRMEZCUXl4RlFVRkZMRVZCUVVVN1owSkJRMnBETEVsQlFVa3NVMEZCVXl4SFFVRkhMRU5CUVVNc1EwRkJReXhWUVVGVkxFTkJRVU1zUTBGQlF5eERRVUZETEVOQlFVTTdaMEpCUTJoRExFbEJRVWtzUTBGQlF5eEhRVUZITEVsQlFVa3NRMEZCUXl4VlFVRlZMRU5CUVVNc1UwRkJVeXhEUVVGRExFVkJRVVVzUTBGQlF5eERRVUZETzJkQ1FVTjBReXhKUVVGSkxFTkJRVU1zUjBGQlJ5eERRVUZETEVOQlFVTXNRMEZCUXl4SFFVRkhMRk5CUVZNc1EwRkJReXhSUVVGUkxFTkJRVU03WjBKQlEycERMRWxCUVVrc1EwRkJReXhEUVVGRExFTkJRVU1zUzBGQlN5eE5RVUZOTEVOQlFVTXNVMEZCVXl4SlFVRkpMRU5CUVVNc1EwRkJReXhEUVVGRExFZEJRVWNzUTBGQlF5eEZRVUZGTzI5Q1FVTnlReXhEUVVGRExFTkJRVU1zUTBGQlF5eEhRVUZITEVOQlFVTXNRMEZCUXp0dlFrRkRVaXhEUVVGRExFTkJRVU1zU1VGQlNTeEhRVUZITEVOQlFVTXNRMEZCUXp0dlFrRkRXQ3hEUVVGRExFTkJRVU1zVTBGQlV5eERRVUZETEVOQlFVTXNRMEZCUXl4RFFVRkRMRVZCUVVVc1EwRkJReXhGUVVGRkxGVkJRVU1zUTBGQlF5eEZRVUZETEVOQlFVTXNTVUZCUnl4UFFVRkJMRU5CUVVNc1EwRkJReXhEUVVGRExFZEJRVWNzUTBGQlF5eEZRVUZRTEVOQlFVOHNRMEZCUXl4RFFVRkRPMmxDUVVOMlF6dGhRVU5LTzFOQlEwbzdVVUZEUkN4UFFVRlBMRU5CUVVNc1EwRkJRenRKUVVOaUxFTkJRVU03U1VGRFRDeHBRa0ZCUXp0QlFVRkVMRU5CUVVNc1FVRnFTVVFzU1VGcFNVTTdRVUZxU1Zrc1owTkJRVlVpZlE9PSIsIlwidXNlIHN0cmljdFwiO1xuT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsIFwiX19lc01vZHVsZVwiLCB7IHZhbHVlOiB0cnVlIH0pO1xudmFyIFBvc2l0aW9uU3RhdHMgPSAoZnVuY3Rpb24gKCkge1xuICAgIGZ1bmN0aW9uIFBvc2l0aW9uU3RhdHMoc2NhbGUpIHtcbiAgICAgICAgdGhpcy5zY2FsZSA9IHNjYWxlO1xuICAgICAgICB0aGlzLkFCID0gMDtcbiAgICAgICAgdGhpcy5BRCA9IDA7XG4gICAgICAgIHRoaXMuQTIgPSAwO1xuICAgIH1cbiAgICBQb3NpdGlvblN0YXRzLnByb3RvdHlwZS5hZGRWYXJpYWJsZSA9IGZ1bmN0aW9uICh2KSB7XG4gICAgICAgIHZhciBhaSA9IHRoaXMuc2NhbGUgLyB2LnNjYWxlO1xuICAgICAgICB2YXIgYmkgPSB2Lm9mZnNldCAvIHYuc2NhbGU7XG4gICAgICAgIHZhciB3aSA9IHYud2VpZ2h0O1xuICAgICAgICB0aGlzLkFCICs9IHdpICogYWkgKiBiaTtcbiAgICAgICAgdGhpcy5BRCArPSB3aSAqIGFpICogdi5kZXNpcmVkUG9zaXRpb247XG4gICAgICAgIHRoaXMuQTIgKz0gd2kgKiBhaSAqIGFpO1xuICAgIH07XG4gICAgUG9zaXRpb25TdGF0cy5wcm90b3R5cGUuZ2V0UG9zbiA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuICh0aGlzLkFEIC0gdGhpcy5BQikgLyB0aGlzLkEyO1xuICAgIH07XG4gICAgcmV0dXJuIFBvc2l0aW9uU3RhdHM7XG59KCkpO1xuZXhwb3J0cy5Qb3NpdGlvblN0YXRzID0gUG9zaXRpb25TdGF0cztcbnZhciBDb25zdHJhaW50ID0gKGZ1bmN0aW9uICgpIHtcbiAgICBmdW5jdGlvbiBDb25zdHJhaW50KGxlZnQsIHJpZ2h0LCBnYXAsIGVxdWFsaXR5KSB7XG4gICAgICAgIGlmIChlcXVhbGl0eSA9PT0gdm9pZCAwKSB7IGVxdWFsaXR5ID0gZmFsc2U7IH1cbiAgICAgICAgdGhpcy5sZWZ0ID0gbGVmdDtcbiAgICAgICAgdGhpcy5yaWdodCA9IHJpZ2h0O1xuICAgICAgICB0aGlzLmdhcCA9IGdhcDtcbiAgICAgICAgdGhpcy5lcXVhbGl0eSA9IGVxdWFsaXR5O1xuICAgICAgICB0aGlzLmFjdGl2ZSA9IGZhbHNlO1xuICAgICAgICB0aGlzLnVuc2F0aXNmaWFibGUgPSBmYWxzZTtcbiAgICAgICAgdGhpcy5sZWZ0ID0gbGVmdDtcbiAgICAgICAgdGhpcy5yaWdodCA9IHJpZ2h0O1xuICAgICAgICB0aGlzLmdhcCA9IGdhcDtcbiAgICAgICAgdGhpcy5lcXVhbGl0eSA9IGVxdWFsaXR5O1xuICAgIH1cbiAgICBDb25zdHJhaW50LnByb3RvdHlwZS5zbGFjayA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMudW5zYXRpc2ZpYWJsZSA/IE51bWJlci5NQVhfVkFMVUVcbiAgICAgICAgICAgIDogdGhpcy5yaWdodC5zY2FsZSAqIHRoaXMucmlnaHQucG9zaXRpb24oKSAtIHRoaXMuZ2FwXG4gICAgICAgICAgICAgICAgLSB0aGlzLmxlZnQuc2NhbGUgKiB0aGlzLmxlZnQucG9zaXRpb24oKTtcbiAgICB9O1xuICAgIHJldHVybiBDb25zdHJhaW50O1xufSgpKTtcbmV4cG9ydHMuQ29uc3RyYWludCA9IENvbnN0cmFpbnQ7XG52YXIgVmFyaWFibGUgPSAoZnVuY3Rpb24gKCkge1xuICAgIGZ1bmN0aW9uIFZhcmlhYmxlKGRlc2lyZWRQb3NpdGlvbiwgd2VpZ2h0LCBzY2FsZSkge1xuICAgICAgICBpZiAod2VpZ2h0ID09PSB2b2lkIDApIHsgd2VpZ2h0ID0gMTsgfVxuICAgICAgICBpZiAoc2NhbGUgPT09IHZvaWQgMCkgeyBzY2FsZSA9IDE7IH1cbiAgICAgICAgdGhpcy5kZXNpcmVkUG9zaXRpb24gPSBkZXNpcmVkUG9zaXRpb247XG4gICAgICAgIHRoaXMud2VpZ2h0ID0gd2VpZ2h0O1xuICAgICAgICB0aGlzLnNjYWxlID0gc2NhbGU7XG4gICAgICAgIHRoaXMub2Zmc2V0ID0gMDtcbiAgICB9XG4gICAgVmFyaWFibGUucHJvdG90eXBlLmRmZHYgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiAyLjAgKiB0aGlzLndlaWdodCAqICh0aGlzLnBvc2l0aW9uKCkgLSB0aGlzLmRlc2lyZWRQb3NpdGlvbik7XG4gICAgfTtcbiAgICBWYXJpYWJsZS5wcm90b3R5cGUucG9zaXRpb24gPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiAodGhpcy5ibG9jay5wcy5zY2FsZSAqIHRoaXMuYmxvY2sucG9zbiArIHRoaXMub2Zmc2V0KSAvIHRoaXMuc2NhbGU7XG4gICAgfTtcbiAgICBWYXJpYWJsZS5wcm90b3R5cGUudmlzaXROZWlnaGJvdXJzID0gZnVuY3Rpb24gKHByZXYsIGYpIHtcbiAgICAgICAgdmFyIGZmID0gZnVuY3Rpb24gKGMsIG5leHQpIHsgcmV0dXJuIGMuYWN0aXZlICYmIHByZXYgIT09IG5leHQgJiYgZihjLCBuZXh0KTsgfTtcbiAgICAgICAgdGhpcy5jT3V0LmZvckVhY2goZnVuY3Rpb24gKGMpIHsgcmV0dXJuIGZmKGMsIGMucmlnaHQpOyB9KTtcbiAgICAgICAgdGhpcy5jSW4uZm9yRWFjaChmdW5jdGlvbiAoYykgeyByZXR1cm4gZmYoYywgYy5sZWZ0KTsgfSk7XG4gICAgfTtcbiAgICByZXR1cm4gVmFyaWFibGU7XG59KCkpO1xuZXhwb3J0cy5WYXJpYWJsZSA9IFZhcmlhYmxlO1xudmFyIEJsb2NrID0gKGZ1bmN0aW9uICgpIHtcbiAgICBmdW5jdGlvbiBCbG9jayh2KSB7XG4gICAgICAgIHRoaXMudmFycyA9IFtdO1xuICAgICAgICB2Lm9mZnNldCA9IDA7XG4gICAgICAgIHRoaXMucHMgPSBuZXcgUG9zaXRpb25TdGF0cyh2LnNjYWxlKTtcbiAgICAgICAgdGhpcy5hZGRWYXJpYWJsZSh2KTtcbiAgICB9XG4gICAgQmxvY2sucHJvdG90eXBlLmFkZFZhcmlhYmxlID0gZnVuY3Rpb24gKHYpIHtcbiAgICAgICAgdi5ibG9jayA9IHRoaXM7XG4gICAgICAgIHRoaXMudmFycy5wdXNoKHYpO1xuICAgICAgICB0aGlzLnBzLmFkZFZhcmlhYmxlKHYpO1xuICAgICAgICB0aGlzLnBvc24gPSB0aGlzLnBzLmdldFBvc24oKTtcbiAgICB9O1xuICAgIEJsb2NrLnByb3RvdHlwZS51cGRhdGVXZWlnaHRlZFBvc2l0aW9uID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB0aGlzLnBzLkFCID0gdGhpcy5wcy5BRCA9IHRoaXMucHMuQTIgPSAwO1xuICAgICAgICBmb3IgKHZhciBpID0gMCwgbiA9IHRoaXMudmFycy5sZW5ndGg7IGkgPCBuOyArK2kpXG4gICAgICAgICAgICB0aGlzLnBzLmFkZFZhcmlhYmxlKHRoaXMudmFyc1tpXSk7XG4gICAgICAgIHRoaXMucG9zbiA9IHRoaXMucHMuZ2V0UG9zbigpO1xuICAgIH07XG4gICAgQmxvY2sucHJvdG90eXBlLmNvbXB1dGVfbG0gPSBmdW5jdGlvbiAodiwgdSwgcG9zdEFjdGlvbikge1xuICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICB2YXIgZGZkdiA9IHYuZGZkdigpO1xuICAgICAgICB2LnZpc2l0TmVpZ2hib3Vycyh1LCBmdW5jdGlvbiAoYywgbmV4dCkge1xuICAgICAgICAgICAgdmFyIF9kZmR2ID0gX3RoaXMuY29tcHV0ZV9sbShuZXh0LCB2LCBwb3N0QWN0aW9uKTtcbiAgICAgICAgICAgIGlmIChuZXh0ID09PSBjLnJpZ2h0KSB7XG4gICAgICAgICAgICAgICAgZGZkdiArPSBfZGZkdiAqIGMubGVmdC5zY2FsZTtcbiAgICAgICAgICAgICAgICBjLmxtID0gX2RmZHY7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICBkZmR2ICs9IF9kZmR2ICogYy5yaWdodC5zY2FsZTtcbiAgICAgICAgICAgICAgICBjLmxtID0gLV9kZmR2O1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcG9zdEFjdGlvbihjKTtcbiAgICAgICAgfSk7XG4gICAgICAgIHJldHVybiBkZmR2IC8gdi5zY2FsZTtcbiAgICB9O1xuICAgIEJsb2NrLnByb3RvdHlwZS5wb3B1bGF0ZVNwbGl0QmxvY2sgPSBmdW5jdGlvbiAodiwgcHJldikge1xuICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICB2LnZpc2l0TmVpZ2hib3VycyhwcmV2LCBmdW5jdGlvbiAoYywgbmV4dCkge1xuICAgICAgICAgICAgbmV4dC5vZmZzZXQgPSB2Lm9mZnNldCArIChuZXh0ID09PSBjLnJpZ2h0ID8gYy5nYXAgOiAtYy5nYXApO1xuICAgICAgICAgICAgX3RoaXMuYWRkVmFyaWFibGUobmV4dCk7XG4gICAgICAgICAgICBfdGhpcy5wb3B1bGF0ZVNwbGl0QmxvY2sobmV4dCwgdik7XG4gICAgICAgIH0pO1xuICAgIH07XG4gICAgQmxvY2sucHJvdG90eXBlLnRyYXZlcnNlID0gZnVuY3Rpb24gKHZpc2l0LCBhY2MsIHYsIHByZXYpIHtcbiAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgaWYgKHYgPT09IHZvaWQgMCkgeyB2ID0gdGhpcy52YXJzWzBdOyB9XG4gICAgICAgIGlmIChwcmV2ID09PSB2b2lkIDApIHsgcHJldiA9IG51bGw7IH1cbiAgICAgICAgdi52aXNpdE5laWdoYm91cnMocHJldiwgZnVuY3Rpb24gKGMsIG5leHQpIHtcbiAgICAgICAgICAgIGFjYy5wdXNoKHZpc2l0KGMpKTtcbiAgICAgICAgICAgIF90aGlzLnRyYXZlcnNlKHZpc2l0LCBhY2MsIG5leHQsIHYpO1xuICAgICAgICB9KTtcbiAgICB9O1xuICAgIEJsb2NrLnByb3RvdHlwZS5maW5kTWluTE0gPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBtID0gbnVsbDtcbiAgICAgICAgdGhpcy5jb21wdXRlX2xtKHRoaXMudmFyc1swXSwgbnVsbCwgZnVuY3Rpb24gKGMpIHtcbiAgICAgICAgICAgIGlmICghYy5lcXVhbGl0eSAmJiAobSA9PT0gbnVsbCB8fCBjLmxtIDwgbS5sbSkpXG4gICAgICAgICAgICAgICAgbSA9IGM7XG4gICAgICAgIH0pO1xuICAgICAgICByZXR1cm4gbTtcbiAgICB9O1xuICAgIEJsb2NrLnByb3RvdHlwZS5maW5kTWluTE1CZXR3ZWVuID0gZnVuY3Rpb24gKGx2LCBydikge1xuICAgICAgICB0aGlzLmNvbXB1dGVfbG0obHYsIG51bGwsIGZ1bmN0aW9uICgpIHsgfSk7XG4gICAgICAgIHZhciBtID0gbnVsbDtcbiAgICAgICAgdGhpcy5maW5kUGF0aChsdiwgbnVsbCwgcnYsIGZ1bmN0aW9uIChjLCBuZXh0KSB7XG4gICAgICAgICAgICBpZiAoIWMuZXF1YWxpdHkgJiYgYy5yaWdodCA9PT0gbmV4dCAmJiAobSA9PT0gbnVsbCB8fCBjLmxtIDwgbS5sbSkpXG4gICAgICAgICAgICAgICAgbSA9IGM7XG4gICAgICAgIH0pO1xuICAgICAgICByZXR1cm4gbTtcbiAgICB9O1xuICAgIEJsb2NrLnByb3RvdHlwZS5maW5kUGF0aCA9IGZ1bmN0aW9uICh2LCBwcmV2LCB0bywgdmlzaXQpIHtcbiAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgdmFyIGVuZEZvdW5kID0gZmFsc2U7XG4gICAgICAgIHYudmlzaXROZWlnaGJvdXJzKHByZXYsIGZ1bmN0aW9uIChjLCBuZXh0KSB7XG4gICAgICAgICAgICBpZiAoIWVuZEZvdW5kICYmIChuZXh0ID09PSB0byB8fCBfdGhpcy5maW5kUGF0aChuZXh0LCB2LCB0bywgdmlzaXQpKSkge1xuICAgICAgICAgICAgICAgIGVuZEZvdW5kID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICB2aXNpdChjLCBuZXh0KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgICAgIHJldHVybiBlbmRGb3VuZDtcbiAgICB9O1xuICAgIEJsb2NrLnByb3RvdHlwZS5pc0FjdGl2ZURpcmVjdGVkUGF0aEJldHdlZW4gPSBmdW5jdGlvbiAodSwgdikge1xuICAgICAgICBpZiAodSA9PT0gdilcbiAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICB2YXIgaSA9IHUuY091dC5sZW5ndGg7XG4gICAgICAgIHdoaWxlIChpLS0pIHtcbiAgICAgICAgICAgIHZhciBjID0gdS5jT3V0W2ldO1xuICAgICAgICAgICAgaWYgKGMuYWN0aXZlICYmIHRoaXMuaXNBY3RpdmVEaXJlY3RlZFBhdGhCZXR3ZWVuKGMucmlnaHQsIHYpKVxuICAgICAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9O1xuICAgIEJsb2NrLnNwbGl0ID0gZnVuY3Rpb24gKGMpIHtcbiAgICAgICAgYy5hY3RpdmUgPSBmYWxzZTtcbiAgICAgICAgcmV0dXJuIFtCbG9jay5jcmVhdGVTcGxpdEJsb2NrKGMubGVmdCksIEJsb2NrLmNyZWF0ZVNwbGl0QmxvY2soYy5yaWdodCldO1xuICAgIH07XG4gICAgQmxvY2suY3JlYXRlU3BsaXRCbG9jayA9IGZ1bmN0aW9uIChzdGFydFZhcikge1xuICAgICAgICB2YXIgYiA9IG5ldyBCbG9jayhzdGFydFZhcik7XG4gICAgICAgIGIucG9wdWxhdGVTcGxpdEJsb2NrKHN0YXJ0VmFyLCBudWxsKTtcbiAgICAgICAgcmV0dXJuIGI7XG4gICAgfTtcbiAgICBCbG9jay5wcm90b3R5cGUuc3BsaXRCZXR3ZWVuID0gZnVuY3Rpb24gKHZsLCB2cikge1xuICAgICAgICB2YXIgYyA9IHRoaXMuZmluZE1pbkxNQmV0d2Vlbih2bCwgdnIpO1xuICAgICAgICBpZiAoYyAhPT0gbnVsbCkge1xuICAgICAgICAgICAgdmFyIGJzID0gQmxvY2suc3BsaXQoYyk7XG4gICAgICAgICAgICByZXR1cm4geyBjb25zdHJhaW50OiBjLCBsYjogYnNbMF0sIHJiOiBic1sxXSB9O1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBudWxsO1xuICAgIH07XG4gICAgQmxvY2sucHJvdG90eXBlLm1lcmdlQWNyb3NzID0gZnVuY3Rpb24gKGIsIGMsIGRpc3QpIHtcbiAgICAgICAgYy5hY3RpdmUgPSB0cnVlO1xuICAgICAgICBmb3IgKHZhciBpID0gMCwgbiA9IGIudmFycy5sZW5ndGg7IGkgPCBuOyArK2kpIHtcbiAgICAgICAgICAgIHZhciB2ID0gYi52YXJzW2ldO1xuICAgICAgICAgICAgdi5vZmZzZXQgKz0gZGlzdDtcbiAgICAgICAgICAgIHRoaXMuYWRkVmFyaWFibGUodik7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5wb3NuID0gdGhpcy5wcy5nZXRQb3NuKCk7XG4gICAgfTtcbiAgICBCbG9jay5wcm90b3R5cGUuY29zdCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIHN1bSA9IDAsIGkgPSB0aGlzLnZhcnMubGVuZ3RoO1xuICAgICAgICB3aGlsZSAoaS0tKSB7XG4gICAgICAgICAgICB2YXIgdiA9IHRoaXMudmFyc1tpXSwgZCA9IHYucG9zaXRpb24oKSAtIHYuZGVzaXJlZFBvc2l0aW9uO1xuICAgICAgICAgICAgc3VtICs9IGQgKiBkICogdi53ZWlnaHQ7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHN1bTtcbiAgICB9O1xuICAgIHJldHVybiBCbG9jaztcbn0oKSk7XG5leHBvcnRzLkJsb2NrID0gQmxvY2s7XG52YXIgQmxvY2tzID0gKGZ1bmN0aW9uICgpIHtcbiAgICBmdW5jdGlvbiBCbG9ja3ModnMpIHtcbiAgICAgICAgdGhpcy52cyA9IHZzO1xuICAgICAgICB2YXIgbiA9IHZzLmxlbmd0aDtcbiAgICAgICAgdGhpcy5saXN0ID0gbmV3IEFycmF5KG4pO1xuICAgICAgICB3aGlsZSAobi0tKSB7XG4gICAgICAgICAgICB2YXIgYiA9IG5ldyBCbG9jayh2c1tuXSk7XG4gICAgICAgICAgICB0aGlzLmxpc3Rbbl0gPSBiO1xuICAgICAgICAgICAgYi5ibG9ja0luZCA9IG47XG4gICAgICAgIH1cbiAgICB9XG4gICAgQmxvY2tzLnByb3RvdHlwZS5jb3N0ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgc3VtID0gMCwgaSA9IHRoaXMubGlzdC5sZW5ndGg7XG4gICAgICAgIHdoaWxlIChpLS0pXG4gICAgICAgICAgICBzdW0gKz0gdGhpcy5saXN0W2ldLmNvc3QoKTtcbiAgICAgICAgcmV0dXJuIHN1bTtcbiAgICB9O1xuICAgIEJsb2Nrcy5wcm90b3R5cGUuaW5zZXJ0ID0gZnVuY3Rpb24gKGIpIHtcbiAgICAgICAgYi5ibG9ja0luZCA9IHRoaXMubGlzdC5sZW5ndGg7XG4gICAgICAgIHRoaXMubGlzdC5wdXNoKGIpO1xuICAgIH07XG4gICAgQmxvY2tzLnByb3RvdHlwZS5yZW1vdmUgPSBmdW5jdGlvbiAoYikge1xuICAgICAgICB2YXIgbGFzdCA9IHRoaXMubGlzdC5sZW5ndGggLSAxO1xuICAgICAgICB2YXIgc3dhcEJsb2NrID0gdGhpcy5saXN0W2xhc3RdO1xuICAgICAgICB0aGlzLmxpc3QubGVuZ3RoID0gbGFzdDtcbiAgICAgICAgaWYgKGIgIT09IHN3YXBCbG9jaykge1xuICAgICAgICAgICAgdGhpcy5saXN0W2IuYmxvY2tJbmRdID0gc3dhcEJsb2NrO1xuICAgICAgICAgICAgc3dhcEJsb2NrLmJsb2NrSW5kID0gYi5ibG9ja0luZDtcbiAgICAgICAgfVxuICAgIH07XG4gICAgQmxvY2tzLnByb3RvdHlwZS5tZXJnZSA9IGZ1bmN0aW9uIChjKSB7XG4gICAgICAgIHZhciBsID0gYy5sZWZ0LmJsb2NrLCByID0gYy5yaWdodC5ibG9jaztcbiAgICAgICAgdmFyIGRpc3QgPSBjLnJpZ2h0Lm9mZnNldCAtIGMubGVmdC5vZmZzZXQgLSBjLmdhcDtcbiAgICAgICAgaWYgKGwudmFycy5sZW5ndGggPCByLnZhcnMubGVuZ3RoKSB7XG4gICAgICAgICAgICByLm1lcmdlQWNyb3NzKGwsIGMsIGRpc3QpO1xuICAgICAgICAgICAgdGhpcy5yZW1vdmUobCk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICBsLm1lcmdlQWNyb3NzKHIsIGMsIC1kaXN0KTtcbiAgICAgICAgICAgIHRoaXMucmVtb3ZlKHIpO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBCbG9ja3MucHJvdG90eXBlLmZvckVhY2ggPSBmdW5jdGlvbiAoZikge1xuICAgICAgICB0aGlzLmxpc3QuZm9yRWFjaChmKTtcbiAgICB9O1xuICAgIEJsb2Nrcy5wcm90b3R5cGUudXBkYXRlQmxvY2tQb3NpdGlvbnMgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHRoaXMubGlzdC5mb3JFYWNoKGZ1bmN0aW9uIChiKSB7IHJldHVybiBiLnVwZGF0ZVdlaWdodGVkUG9zaXRpb24oKTsgfSk7XG4gICAgfTtcbiAgICBCbG9ja3MucHJvdG90eXBlLnNwbGl0ID0gZnVuY3Rpb24gKGluYWN0aXZlKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgICAgIHRoaXMudXBkYXRlQmxvY2tQb3NpdGlvbnMoKTtcbiAgICAgICAgdGhpcy5saXN0LmZvckVhY2goZnVuY3Rpb24gKGIpIHtcbiAgICAgICAgICAgIHZhciB2ID0gYi5maW5kTWluTE0oKTtcbiAgICAgICAgICAgIGlmICh2ICE9PSBudWxsICYmIHYubG0gPCBTb2x2ZXIuTEFHUkFOR0lBTl9UT0xFUkFOQ0UpIHtcbiAgICAgICAgICAgICAgICBiID0gdi5sZWZ0LmJsb2NrO1xuICAgICAgICAgICAgICAgIEJsb2NrLnNwbGl0KHYpLmZvckVhY2goZnVuY3Rpb24gKG5iKSB7IHJldHVybiBfdGhpcy5pbnNlcnQobmIpOyB9KTtcbiAgICAgICAgICAgICAgICBfdGhpcy5yZW1vdmUoYik7XG4gICAgICAgICAgICAgICAgaW5hY3RpdmUucHVzaCh2KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfTtcbiAgICByZXR1cm4gQmxvY2tzO1xufSgpKTtcbmV4cG9ydHMuQmxvY2tzID0gQmxvY2tzO1xudmFyIFNvbHZlciA9IChmdW5jdGlvbiAoKSB7XG4gICAgZnVuY3Rpb24gU29sdmVyKHZzLCBjcykge1xuICAgICAgICB0aGlzLnZzID0gdnM7XG4gICAgICAgIHRoaXMuY3MgPSBjcztcbiAgICAgICAgdGhpcy52cyA9IHZzO1xuICAgICAgICB2cy5mb3JFYWNoKGZ1bmN0aW9uICh2KSB7XG4gICAgICAgICAgICB2LmNJbiA9IFtdLCB2LmNPdXQgPSBbXTtcbiAgICAgICAgfSk7XG4gICAgICAgIHRoaXMuY3MgPSBjcztcbiAgICAgICAgY3MuZm9yRWFjaChmdW5jdGlvbiAoYykge1xuICAgICAgICAgICAgYy5sZWZ0LmNPdXQucHVzaChjKTtcbiAgICAgICAgICAgIGMucmlnaHQuY0luLnB1c2goYyk7XG4gICAgICAgIH0pO1xuICAgICAgICB0aGlzLmluYWN0aXZlID0gY3MubWFwKGZ1bmN0aW9uIChjKSB7IGMuYWN0aXZlID0gZmFsc2U7IHJldHVybiBjOyB9KTtcbiAgICAgICAgdGhpcy5icyA9IG51bGw7XG4gICAgfVxuICAgIFNvbHZlci5wcm90b3R5cGUuY29zdCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuYnMuY29zdCgpO1xuICAgIH07XG4gICAgU29sdmVyLnByb3RvdHlwZS5zZXRTdGFydGluZ1Bvc2l0aW9ucyA9IGZ1bmN0aW9uIChwcykge1xuICAgICAgICB0aGlzLmluYWN0aXZlID0gdGhpcy5jcy5tYXAoZnVuY3Rpb24gKGMpIHsgYy5hY3RpdmUgPSBmYWxzZTsgcmV0dXJuIGM7IH0pO1xuICAgICAgICB0aGlzLmJzID0gbmV3IEJsb2Nrcyh0aGlzLnZzKTtcbiAgICAgICAgdGhpcy5icy5mb3JFYWNoKGZ1bmN0aW9uIChiLCBpKSB7IHJldHVybiBiLnBvc24gPSBwc1tpXTsgfSk7XG4gICAgfTtcbiAgICBTb2x2ZXIucHJvdG90eXBlLnNldERlc2lyZWRQb3NpdGlvbnMgPSBmdW5jdGlvbiAocHMpIHtcbiAgICAgICAgdGhpcy52cy5mb3JFYWNoKGZ1bmN0aW9uICh2LCBpKSB7IHJldHVybiB2LmRlc2lyZWRQb3NpdGlvbiA9IHBzW2ldOyB9KTtcbiAgICB9O1xuICAgIFNvbHZlci5wcm90b3R5cGUubW9zdFZpb2xhdGVkID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgbWluU2xhY2sgPSBOdW1iZXIuTUFYX1ZBTFVFLCB2ID0gbnVsbCwgbCA9IHRoaXMuaW5hY3RpdmUsIG4gPSBsLmxlbmd0aCwgZGVsZXRlUG9pbnQgPSBuO1xuICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IG47ICsraSkge1xuICAgICAgICAgICAgdmFyIGMgPSBsW2ldO1xuICAgICAgICAgICAgaWYgKGMudW5zYXRpc2ZpYWJsZSlcbiAgICAgICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICAgIHZhciBzbGFjayA9IGMuc2xhY2soKTtcbiAgICAgICAgICAgIGlmIChjLmVxdWFsaXR5IHx8IHNsYWNrIDwgbWluU2xhY2spIHtcbiAgICAgICAgICAgICAgICBtaW5TbGFjayA9IHNsYWNrO1xuICAgICAgICAgICAgICAgIHYgPSBjO1xuICAgICAgICAgICAgICAgIGRlbGV0ZVBvaW50ID0gaTtcbiAgICAgICAgICAgICAgICBpZiAoYy5lcXVhbGl0eSlcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGRlbGV0ZVBvaW50ICE9PSBuICYmXG4gICAgICAgICAgICAobWluU2xhY2sgPCBTb2x2ZXIuWkVST19VUFBFUkJPVU5EICYmICF2LmFjdGl2ZSB8fCB2LmVxdWFsaXR5KSkge1xuICAgICAgICAgICAgbFtkZWxldGVQb2ludF0gPSBsW24gLSAxXTtcbiAgICAgICAgICAgIGwubGVuZ3RoID0gbiAtIDE7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHY7XG4gICAgfTtcbiAgICBTb2x2ZXIucHJvdG90eXBlLnNhdGlzZnkgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGlmICh0aGlzLmJzID09IG51bGwpIHtcbiAgICAgICAgICAgIHRoaXMuYnMgPSBuZXcgQmxvY2tzKHRoaXMudnMpO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuYnMuc3BsaXQodGhpcy5pbmFjdGl2ZSk7XG4gICAgICAgIHZhciB2ID0gbnVsbDtcbiAgICAgICAgd2hpbGUgKCh2ID0gdGhpcy5tb3N0VmlvbGF0ZWQoKSkgJiYgKHYuZXF1YWxpdHkgfHwgdi5zbGFjaygpIDwgU29sdmVyLlpFUk9fVVBQRVJCT1VORCAmJiAhdi5hY3RpdmUpKSB7XG4gICAgICAgICAgICB2YXIgbGIgPSB2LmxlZnQuYmxvY2ssIHJiID0gdi5yaWdodC5ibG9jaztcbiAgICAgICAgICAgIGlmIChsYiAhPT0gcmIpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmJzLm1lcmdlKHYpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgaWYgKGxiLmlzQWN0aXZlRGlyZWN0ZWRQYXRoQmV0d2Vlbih2LnJpZ2h0LCB2LmxlZnQpKSB7XG4gICAgICAgICAgICAgICAgICAgIHYudW5zYXRpc2ZpYWJsZSA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB2YXIgc3BsaXQgPSBsYi5zcGxpdEJldHdlZW4odi5sZWZ0LCB2LnJpZ2h0KTtcbiAgICAgICAgICAgICAgICBpZiAoc3BsaXQgIT09IG51bGwpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5icy5pbnNlcnQoc3BsaXQubGIpO1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmJzLmluc2VydChzcGxpdC5yYik7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuYnMucmVtb3ZlKGxiKTtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5pbmFjdGl2ZS5wdXNoKHNwbGl0LmNvbnN0cmFpbnQpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgdi51bnNhdGlzZmlhYmxlID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmICh2LnNsYWNrKCkgPj0gMCkge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmluYWN0aXZlLnB1c2godik7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmJzLm1lcmdlKHYpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH07XG4gICAgU29sdmVyLnByb3RvdHlwZS5zb2x2ZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdGhpcy5zYXRpc2Z5KCk7XG4gICAgICAgIHZhciBsYXN0Y29zdCA9IE51bWJlci5NQVhfVkFMVUUsIGNvc3QgPSB0aGlzLmJzLmNvc3QoKTtcbiAgICAgICAgd2hpbGUgKE1hdGguYWJzKGxhc3Rjb3N0IC0gY29zdCkgPiAwLjAwMDEpIHtcbiAgICAgICAgICAgIHRoaXMuc2F0aXNmeSgpO1xuICAgICAgICAgICAgbGFzdGNvc3QgPSBjb3N0O1xuICAgICAgICAgICAgY29zdCA9IHRoaXMuYnMuY29zdCgpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBjb3N0O1xuICAgIH07XG4gICAgU29sdmVyLkxBR1JBTkdJQU5fVE9MRVJBTkNFID0gLTFlLTQ7XG4gICAgU29sdmVyLlpFUk9fVVBQRVJCT1VORCA9IC0xZS0xMDtcbiAgICByZXR1cm4gU29sdmVyO1xufSgpKTtcbmV4cG9ydHMuU29sdmVyID0gU29sdmVyO1xuZnVuY3Rpb24gcmVtb3ZlT3ZlcmxhcEluT25lRGltZW5zaW9uKHNwYW5zLCBsb3dlckJvdW5kLCB1cHBlckJvdW5kKSB7XG4gICAgdmFyIHZzID0gc3BhbnMubWFwKGZ1bmN0aW9uIChzKSB7IHJldHVybiBuZXcgVmFyaWFibGUocy5kZXNpcmVkQ2VudGVyKTsgfSk7XG4gICAgdmFyIGNzID0gW107XG4gICAgdmFyIG4gPSBzcGFucy5sZW5ndGg7XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBuIC0gMTsgaSsrKSB7XG4gICAgICAgIHZhciBsZWZ0ID0gc3BhbnNbaV0sIHJpZ2h0ID0gc3BhbnNbaSArIDFdO1xuICAgICAgICBjcy5wdXNoKG5ldyBDb25zdHJhaW50KHZzW2ldLCB2c1tpICsgMV0sIChsZWZ0LnNpemUgKyByaWdodC5zaXplKSAvIDIpKTtcbiAgICB9XG4gICAgdmFyIGxlZnRNb3N0ID0gdnNbMF0sIHJpZ2h0TW9zdCA9IHZzW24gLSAxXSwgbGVmdE1vc3RTaXplID0gc3BhbnNbMF0uc2l6ZSAvIDIsIHJpZ2h0TW9zdFNpemUgPSBzcGFuc1tuIC0gMV0uc2l6ZSAvIDI7XG4gICAgdmFyIHZMb3dlciA9IG51bGwsIHZVcHBlciA9IG51bGw7XG4gICAgaWYgKGxvd2VyQm91bmQpIHtcbiAgICAgICAgdkxvd2VyID0gbmV3IFZhcmlhYmxlKGxvd2VyQm91bmQsIGxlZnRNb3N0LndlaWdodCAqIDEwMDApO1xuICAgICAgICB2cy5wdXNoKHZMb3dlcik7XG4gICAgICAgIGNzLnB1c2gobmV3IENvbnN0cmFpbnQodkxvd2VyLCBsZWZ0TW9zdCwgbGVmdE1vc3RTaXplKSk7XG4gICAgfVxuICAgIGlmICh1cHBlckJvdW5kKSB7XG4gICAgICAgIHZVcHBlciA9IG5ldyBWYXJpYWJsZSh1cHBlckJvdW5kLCByaWdodE1vc3Qud2VpZ2h0ICogMTAwMCk7XG4gICAgICAgIHZzLnB1c2godlVwcGVyKTtcbiAgICAgICAgY3MucHVzaChuZXcgQ29uc3RyYWludChyaWdodE1vc3QsIHZVcHBlciwgcmlnaHRNb3N0U2l6ZSkpO1xuICAgIH1cbiAgICB2YXIgc29sdmVyID0gbmV3IFNvbHZlcih2cywgY3MpO1xuICAgIHNvbHZlci5zb2x2ZSgpO1xuICAgIHJldHVybiB7XG4gICAgICAgIG5ld0NlbnRlcnM6IHZzLnNsaWNlKDAsIHNwYW5zLmxlbmd0aCkubWFwKGZ1bmN0aW9uICh2KSB7IHJldHVybiB2LnBvc2l0aW9uKCk7IH0pLFxuICAgICAgICBsb3dlckJvdW5kOiB2TG93ZXIgPyB2TG93ZXIucG9zaXRpb24oKSA6IGxlZnRNb3N0LnBvc2l0aW9uKCkgLSBsZWZ0TW9zdFNpemUsXG4gICAgICAgIHVwcGVyQm91bmQ6IHZVcHBlciA/IHZVcHBlci5wb3NpdGlvbigpIDogcmlnaHRNb3N0LnBvc2l0aW9uKCkgKyByaWdodE1vc3RTaXplXG4gICAgfTtcbn1cbmV4cG9ydHMucmVtb3ZlT3ZlcmxhcEluT25lRGltZW5zaW9uID0gcmVtb3ZlT3ZlcmxhcEluT25lRGltZW5zaW9uO1xuLy8jIHNvdXJjZU1hcHBpbmdVUkw9ZGF0YTphcHBsaWNhdGlvbi9qc29uO2Jhc2U2NCxleUoyWlhKemFXOXVJam96TENKbWFXeGxJam9pZG5Cell5NXFjeUlzSW5OdmRYSmpaVkp2YjNRaU9pSWlMQ0p6YjNWeVkyVnpJanBiSWk0dUx5NHVMMWRsWWtOdmJHRXZjM0pqTDNad2MyTXVkSE1pWFN3aWJtRnRaWE1pT2x0ZExDSnRZWEJ3YVc1bmN5STZJanM3UVVGQlNUdEpRVXRKTEhWQ1FVRnRRaXhMUVVGaE8xRkJRV0lzVlVGQlN5eEhRVUZNTEV0QlFVc3NRMEZCVVR0UlFVcG9ReXhQUVVGRkxFZEJRVmNzUTBGQlF5eERRVUZETzFGQlEyWXNUMEZCUlN4SFFVRlhMRU5CUVVNc1EwRkJRenRSUVVObUxFOUJRVVVzUjBGQlZ5eERRVUZETEVOQlFVTTdTVUZGYjBJc1EwRkJRenRKUVVWd1F5eHRRMEZCVnl4SFFVRllMRlZCUVZrc1EwRkJWenRSUVVOdVFpeEpRVUZKTEVWQlFVVXNSMEZCUnl4SlFVRkpMRU5CUVVNc1MwRkJTeXhIUVVGSExFTkJRVU1zUTBGQlF5eExRVUZMTEVOQlFVTTdVVUZET1VJc1NVRkJTU3hGUVVGRkxFZEJRVWNzUTBGQlF5eERRVUZETEUxQlFVMHNSMEZCUnl4RFFVRkRMRU5CUVVNc1MwRkJTeXhEUVVGRE8xRkJRelZDTEVsQlFVa3NSVUZCUlN4SFFVRkhMRU5CUVVNc1EwRkJReXhOUVVGTkxFTkJRVU03VVVGRGJFSXNTVUZCU1N4RFFVRkRMRVZCUVVVc1NVRkJTU3hGUVVGRkxFZEJRVWNzUlVGQlJTeEhRVUZITEVWQlFVVXNRMEZCUXp0UlFVTjRRaXhKUVVGSkxFTkJRVU1zUlVGQlJTeEpRVUZKTEVWQlFVVXNSMEZCUnl4RlFVRkZMRWRCUVVjc1EwRkJReXhEUVVGRExHVkJRV1VzUTBGQlF6dFJRVU4yUXl4SlFVRkpMRU5CUVVNc1JVRkJSU3hKUVVGSkxFVkJRVVVzUjBGQlJ5eEZRVUZGTEVkQlFVY3NSVUZCUlN4RFFVRkRPMGxCUXpWQ0xFTkJRVU03U1VGRlJDd3JRa0ZCVHl4SFFVRlFPMUZCUTBrc1QwRkJUeXhEUVVGRExFbEJRVWtzUTBGQlF5eEZRVUZGTEVkQlFVY3NTVUZCU1N4RFFVRkRMRVZCUVVVc1EwRkJReXhIUVVGSExFbEJRVWtzUTBGQlF5eEZRVUZGTEVOQlFVTTdTVUZEZWtNc1EwRkJRenRKUVVOTUxHOUNRVUZETzBGQlFVUXNRMEZCUXl4QlFXNUNSQ3hKUVcxQ1F6dEJRVzVDV1N4elEwRkJZVHRCUVhGQ01VSTdTVUZMU1N4dlFrRkJiVUlzU1VGQll5eEZRVUZUTEV0QlFXVXNSVUZCVXl4SFFVRlhMRVZCUVZNc1VVRkJlVUk3VVVGQmVrSXNlVUpCUVVFc1JVRkJRU3huUWtGQmVVSTdVVUZCTlVZc1UwRkJTU3hIUVVGS0xFbEJRVWtzUTBGQlZUdFJRVUZUTEZWQlFVc3NSMEZCVEN4TFFVRkxMRU5CUVZVN1VVRkJVeXhSUVVGSExFZEJRVWdzUjBGQlJ5eERRVUZSTzFGQlFWTXNZVUZCVVN4SFFVRlNMRkZCUVZFc1EwRkJhVUk3VVVGSUwwY3NWMEZCVFN4SFFVRlpMRXRCUVVzc1EwRkJRenRSUVVONFFpeHJRa0ZCWVN4SFFVRlpMRXRCUVVzc1EwRkJRenRSUVVjelFpeEpRVUZKTEVOQlFVTXNTVUZCU1N4SFFVRkhMRWxCUVVrc1EwRkJRenRSUVVOcVFpeEpRVUZKTEVOQlFVTXNTMEZCU3l4SFFVRkhMRXRCUVVzc1EwRkJRenRSUVVOdVFpeEpRVUZKTEVOQlFVTXNSMEZCUnl4SFFVRkhMRWRCUVVjc1EwRkJRenRSUVVObUxFbEJRVWtzUTBGQlF5eFJRVUZSTEVkQlFVY3NVVUZCVVN4RFFVRkRPMGxCUXpkQ0xFTkJRVU03U1VGRlJDd3dRa0ZCU3l4SFFVRk1PMUZCUTBrc1QwRkJUeXhKUVVGSkxFTkJRVU1zWVVGQllTeERRVUZETEVOQlFVTXNRMEZCUXl4TlFVRk5MRU5CUVVNc1UwRkJVenRaUVVONFF5eERRVUZETEVOQlFVTXNTVUZCU1N4RFFVRkRMRXRCUVVzc1EwRkJReXhMUVVGTExFZEJRVWNzU1VGQlNTeERRVUZETEV0QlFVc3NRMEZCUXl4UlFVRlJMRVZCUVVVc1IwRkJSeXhKUVVGSkxFTkJRVU1zUjBGQlJ6dHJRa0ZEYmtRc1NVRkJTU3hEUVVGRExFbEJRVWtzUTBGQlF5eExRVUZMTEVkQlFVY3NTVUZCU1N4RFFVRkRMRWxCUVVrc1EwRkJReXhSUVVGUkxFVkJRVVVzUTBGQlF6dEpRVU5xUkN4RFFVRkRPMGxCUTB3c2FVSkJRVU03UVVGQlJDeERRVUZETEVGQmFrSkVMRWxCYVVKRE8wRkJha0paTEdkRFFVRlZPMEZCYlVKMlFqdEpRVTFKTEd0Q1FVRnRRaXhsUVVGMVFpeEZRVUZUTEUxQlFXdENMRVZCUVZNc1MwRkJhVUk3VVVGQk5VTXNkVUpCUVVFc1JVRkJRU3hWUVVGclFqdFJRVUZUTEhOQ1FVRkJMRVZCUVVFc1UwRkJhVUk3VVVGQk5VVXNiMEpCUVdVc1IwRkJaaXhsUVVGbExFTkJRVkU3VVVGQlV5eFhRVUZOTEVkQlFVNHNUVUZCVFN4RFFVRlpPMUZCUVZNc1ZVRkJTeXhIUVVGTUxFdEJRVXNzUTBGQldUdFJRVXd2Uml4WFFVRk5MRWRCUVZjc1EwRkJReXhEUVVGRE8wbEJTeXRGTEVOQlFVTTdTVUZGYmtjc2RVSkJRVWtzUjBGQlNqdFJRVU5KTEU5QlFVOHNSMEZCUnl4SFFVRkhMRWxCUVVrc1EwRkJReXhOUVVGTkxFZEJRVWNzUTBGQlF5eEpRVUZKTEVOQlFVTXNVVUZCVVN4RlFVRkZMRWRCUVVjc1NVRkJTU3hEUVVGRExHVkJRV1VzUTBGQlF5eERRVUZETzBsQlEzaEZMRU5CUVVNN1NVRkZSQ3d5UWtGQlVTeEhRVUZTTzFGQlEwa3NUMEZCVHl4RFFVRkRMRWxCUVVrc1EwRkJReXhMUVVGTExFTkJRVU1zUlVGQlJTeERRVUZETEV0QlFVc3NSMEZCUnl4SlFVRkpMRU5CUVVNc1MwRkJTeXhEUVVGRExFbEJRVWtzUjBGQlJ5eEpRVUZKTEVOQlFVTXNUVUZCVFN4RFFVRkRMRWRCUVVjc1NVRkJTU3hEUVVGRExFdEJRVXNzUTBGQlF6dEpRVU01UlN4RFFVRkRPMGxCUjBRc2EwTkJRV1VzUjBGQlppeFZRVUZuUWl4SlFVRmpMRVZCUVVVc1EwRkJNRU03VVVGRGRFVXNTVUZCU1N4RlFVRkZMRWRCUVVjc1ZVRkJReXhEUVVGRExFVkJRVVVzU1VGQlNTeEpRVUZMTEU5QlFVRXNRMEZCUXl4RFFVRkRMRTFCUVUwc1NVRkJTU3hKUVVGSkxFdEJRVXNzU1VGQlNTeEpRVUZKTEVOQlFVTXNRMEZCUXl4RFFVRkRMRVZCUVVVc1NVRkJTU3hEUVVGRExFVkJRWFpETEVOQlFYVkRMRU5CUVVNN1VVRkRPVVFzU1VGQlNTeERRVUZETEVsQlFVa3NRMEZCUXl4UFFVRlBMRU5CUVVNc1ZVRkJRU3hEUVVGRExFbEJRVWNzVDBGQlFTeEZRVUZGTEVOQlFVTXNRMEZCUXl4RlFVRkZMRU5CUVVNc1EwRkJReXhMUVVGTExFTkJRVU1zUlVGQlpDeERRVUZqTEVOQlFVTXNRMEZCUXp0UlFVTjBReXhKUVVGSkxFTkJRVU1zUjBGQlJ5eERRVUZETEU5QlFVOHNRMEZCUXl4VlFVRkJMRU5CUVVNc1NVRkJSeXhQUVVGQkxFVkJRVVVzUTBGQlF5eERRVUZETEVWQlFVVXNRMEZCUXl4RFFVRkRMRWxCUVVrc1EwRkJReXhGUVVGaUxFTkJRV0VzUTBGQlF5eERRVUZETzBsQlEzaERMRU5CUVVNN1NVRkRUQ3hsUVVGRE8wRkJRVVFzUTBGQlF5eEJRWFJDUkN4SlFYTkNRenRCUVhSQ1dTdzBRa0ZCVVR0QlFYZENja0k3U1VGTlNTeGxRVUZaTEVOQlFWYzdVVUZNZGtJc1UwRkJTU3hIUVVGbExFVkJRVVVzUTBGQlF6dFJRVTFzUWl4RFFVRkRMRU5CUVVNc1RVRkJUU3hIUVVGSExFTkJRVU1zUTBGQlF6dFJRVU5pTEVsQlFVa3NRMEZCUXl4RlFVRkZMRWRCUVVjc1NVRkJTU3hoUVVGaExFTkJRVU1zUTBGQlF5eERRVUZETEV0QlFVc3NRMEZCUXl4RFFVRkRPMUZCUTNKRExFbEJRVWtzUTBGQlF5eFhRVUZYTEVOQlFVTXNRMEZCUXl4RFFVRkRMRU5CUVVNN1NVRkRlRUlzUTBGQlF6dEpRVVZQTERKQ1FVRlhMRWRCUVc1Q0xGVkJRVzlDTEVOQlFWYzdVVUZETTBJc1EwRkJReXhEUVVGRExFdEJRVXNzUjBGQlJ5eEpRVUZKTEVOQlFVTTdVVUZEWml4SlFVRkpMRU5CUVVNc1NVRkJTU3hEUVVGRExFbEJRVWtzUTBGQlF5eERRVUZETEVOQlFVTXNRMEZCUXp0UlFVTnNRaXhKUVVGSkxFTkJRVU1zUlVGQlJTeERRVUZETEZkQlFWY3NRMEZCUXl4RFFVRkRMRU5CUVVNc1EwRkJRenRSUVVOMlFpeEpRVUZKTEVOQlFVTXNTVUZCU1N4SFFVRkhMRWxCUVVrc1EwRkJReXhGUVVGRkxFTkJRVU1zVDBGQlR5eEZRVUZGTEVOQlFVTTdTVUZEYkVNc1EwRkJRenRKUVVkRUxITkRRVUZ6UWl4SFFVRjBRanRSUVVOSkxFbEJRVWtzUTBGQlF5eEZRVUZGTEVOQlFVTXNSVUZCUlN4SFFVRkhMRWxCUVVrc1EwRkJReXhGUVVGRkxFTkJRVU1zUlVGQlJTeEhRVUZITEVsQlFVa3NRMEZCUXl4RlFVRkZMRU5CUVVNc1JVRkJSU3hIUVVGSExFTkJRVU1zUTBGQlF6dFJRVU42UXl4TFFVRkxMRWxCUVVrc1EwRkJReXhIUVVGSExFTkJRVU1zUlVGQlJTeERRVUZETEVkQlFVY3NTVUZCU1N4RFFVRkRMRWxCUVVrc1EwRkJReXhOUVVGTkxFVkJRVVVzUTBGQlF5eEhRVUZITEVOQlFVTXNSVUZCUlN4RlFVRkZMRU5CUVVNN1dVRkROVU1zU1VGQlNTeERRVUZETEVWQlFVVXNRMEZCUXl4WFFVRlhMRU5CUVVNc1NVRkJTU3hEUVVGRExFbEJRVWtzUTBGQlF5eERRVUZETEVOQlFVTXNRMEZCUXl4RFFVRkRPMUZCUTNSRExFbEJRVWtzUTBGQlF5eEpRVUZKTEVkQlFVY3NTVUZCU1N4RFFVRkRMRVZCUVVVc1EwRkJReXhQUVVGUExFVkJRVVVzUTBGQlF6dEpRVU5zUXl4RFFVRkRPMGxCUlU4c01FSkJRVlVzUjBGQmJFSXNWVUZCYlVJc1EwRkJWeXhGUVVGRkxFTkJRVmNzUlVGQlJTeFZRVUZwUXp0UlFVRTVSU3hwUWtGalF6dFJRV0pITEVsQlFVa3NTVUZCU1N4SFFVRkhMRU5CUVVNc1EwRkJReXhKUVVGSkxFVkJRVVVzUTBGQlF6dFJRVU53UWl4RFFVRkRMRU5CUVVNc1pVRkJaU3hEUVVGRExFTkJRVU1zUlVGQlJTeFZRVUZETEVOQlFVTXNSVUZCUlN4SlFVRkpPMWxCUTNwQ0xFbEJRVWtzUzBGQlN5eEhRVUZITEV0QlFVa3NRMEZCUXl4VlFVRlZMRU5CUVVNc1NVRkJTU3hGUVVGRkxFTkJRVU1zUlVGQlJTeFZRVUZWTEVOQlFVTXNRMEZCUXp0WlFVTnFSQ3hKUVVGSkxFbEJRVWtzUzBGQlN5eERRVUZETEVOQlFVTXNTMEZCU3l4RlFVRkZPMmRDUVVOc1FpeEpRVUZKTEVsQlFVa3NTMEZCU3l4SFFVRkhMRU5CUVVNc1EwRkJReXhKUVVGSkxFTkJRVU1zUzBGQlN5eERRVUZETzJkQ1FVTTNRaXhEUVVGRExFTkJRVU1zUlVGQlJTeEhRVUZITEV0QlFVc3NRMEZCUXp0aFFVTm9RanRwUWtGQlRUdG5Ra0ZEU0N4SlFVRkpMRWxCUVVrc1MwRkJTeXhIUVVGSExFTkJRVU1zUTBGQlF5eExRVUZMTEVOQlFVTXNTMEZCU3l4RFFVRkRPMmRDUVVNNVFpeERRVUZETEVOQlFVTXNSVUZCUlN4SFFVRkhMRU5CUVVNc1MwRkJTeXhEUVVGRE8yRkJRMnBDTzFsQlEwUXNWVUZCVlN4RFFVRkRMRU5CUVVNc1EwRkJReXhEUVVGRE8xRkJRMnhDTEVOQlFVTXNRMEZCUXl4RFFVRkRPMUZCUTBnc1QwRkJUeXhKUVVGSkxFZEJRVWNzUTBGQlF5eERRVUZETEV0QlFVc3NRMEZCUXp0SlFVTXhRaXhEUVVGRE8wbEJSVThzYTBOQlFXdENMRWRCUVRGQ0xGVkJRVEpDTEVOQlFWY3NSVUZCUlN4SlFVRmpPMUZCUVhSRUxHbENRVTFETzFGQlRFY3NRMEZCUXl4RFFVRkRMR1ZCUVdVc1EwRkJReXhKUVVGSkxFVkJRVVVzVlVGQlF5eERRVUZETEVWQlFVVXNTVUZCU1R0WlFVTTFRaXhKUVVGSkxFTkJRVU1zVFVGQlRTeEhRVUZITEVOQlFVTXNRMEZCUXl4TlFVRk5MRWRCUVVjc1EwRkJReXhKUVVGSkxFdEJRVXNzUTBGQlF5eERRVUZETEV0QlFVc3NRMEZCUXl4RFFVRkRMRU5CUVVNc1EwRkJReXhEUVVGRExFZEJRVWNzUTBGQlF5eERRVUZETEVOQlFVTXNRMEZCUXl4RFFVRkRMRU5CUVVNc1IwRkJSeXhEUVVGRExFTkJRVU03V1VGRE4wUXNTMEZCU1N4RFFVRkRMRmRCUVZjc1EwRkJReXhKUVVGSkxFTkJRVU1zUTBGQlF6dFpRVU4yUWl4TFFVRkpMRU5CUVVNc2EwSkJRV3RDTEVOQlFVTXNTVUZCU1N4RlFVRkZMRU5CUVVNc1EwRkJReXhEUVVGRE8xRkJRM0pETEVOQlFVTXNRMEZCUXl4RFFVRkRPMGxCUTFBc1EwRkJRenRKUVVkRUxIZENRVUZSTEVkQlFWSXNWVUZCVXl4TFFVRTJRaXhGUVVGRkxFZEJRVlVzUlVGQlJTeERRVUV3UWl4RlFVRkZMRWxCUVcxQ08xRkJRVzVITEdsQ1FVdERPMUZCVEcxRUxHdENRVUZCTEVWQlFVRXNTVUZCWXl4SlFVRkpMRU5CUVVNc1NVRkJTU3hEUVVGRExFTkJRVU1zUTBGQlF6dFJRVUZGTEhGQ1FVRkJMRVZCUVVFc1YwRkJiVUk3VVVGREwwWXNRMEZCUXl4RFFVRkRMR1ZCUVdVc1EwRkJReXhKUVVGSkxFVkJRVVVzVlVGQlF5eERRVUZETEVWQlFVVXNTVUZCU1R0WlFVTTFRaXhIUVVGSExFTkJRVU1zU1VGQlNTeERRVUZETEV0QlFVc3NRMEZCUXl4RFFVRkRMRU5CUVVNc1EwRkJReXhEUVVGRE8xbEJRMjVDTEV0QlFVa3NRMEZCUXl4UlFVRlJMRU5CUVVNc1MwRkJTeXhGUVVGRkxFZEJRVWNzUlVGQlJTeEpRVUZKTEVWQlFVVXNRMEZCUXl4RFFVRkRMRU5CUVVNN1VVRkRka01zUTBGQlF5eERRVUZETEVOQlFVTTdTVUZEVUN4RFFVRkRPMGxCUzBRc2VVSkJRVk1zUjBGQlZEdFJRVU5KTEVsQlFVa3NRMEZCUXl4SFFVRmxMRWxCUVVrc1EwRkJRenRSUVVONlFpeEpRVUZKTEVOQlFVTXNWVUZCVlN4RFFVRkRMRWxCUVVrc1EwRkJReXhKUVVGSkxFTkJRVU1zUTBGQlF5eERRVUZETEVWQlFVVXNTVUZCU1N4RlFVRkZMRlZCUVVFc1EwRkJRenRaUVVOcVF5eEpRVUZKTEVOQlFVTXNRMEZCUXl4RFFVRkRMRkZCUVZFc1NVRkJTU3hEUVVGRExFTkJRVU1zUzBGQlN5eEpRVUZKTEVsQlFVa3NRMEZCUXl4RFFVRkRMRVZCUVVVc1IwRkJSeXhEUVVGRExFTkJRVU1zUlVGQlJTeERRVUZETzJkQ1FVRkZMRU5CUVVNc1IwRkJSeXhEUVVGRExFTkJRVU03VVVGRE1VUXNRMEZCUXl4RFFVRkRMRU5CUVVNN1VVRkRTQ3hQUVVGUExFTkJRVU1zUTBGQlF6dEpRVU5pTEVOQlFVTTdTVUZGVHl4blEwRkJaMElzUjBGQmVFSXNWVUZCZVVJc1JVRkJXU3hGUVVGRkxFVkJRVms3VVVGREwwTXNTVUZCU1N4RFFVRkRMRlZCUVZVc1EwRkJReXhGUVVGRkxFVkJRVVVzU1VGQlNTeEZRVUZGTEdOQlFVOHNRMEZCUXl4RFFVRkRMRU5CUVVNN1VVRkRjRU1zU1VGQlNTeERRVUZETEVkQlFVY3NTVUZCU1N4RFFVRkRPMUZCUTJJc1NVRkJTU3hEUVVGRExGRkJRVkVzUTBGQlF5eEZRVUZGTEVWQlFVVXNTVUZCU1N4RlFVRkZMRVZCUVVVc1JVRkJSU3hWUVVGRExFTkJRVU1zUlVGQlJTeEpRVUZKTzFsQlEyaERMRWxCUVVrc1EwRkJReXhEUVVGRExFTkJRVU1zVVVGQlVTeEpRVUZKTEVOQlFVTXNRMEZCUXl4TFFVRkxMRXRCUVVzc1NVRkJTU3hKUVVGSkxFTkJRVU1zUTBGQlF5eExRVUZMTEVsQlFVa3NTVUZCU1N4RFFVRkRMRU5CUVVNc1JVRkJSU3hIUVVGSExFTkJRVU1zUTBGQlF5eEZRVUZGTEVOQlFVTTdaMEpCUVVVc1EwRkJReXhIUVVGSExFTkJRVU1zUTBGQlF6dFJRVU01UlN4RFFVRkRMRU5CUVVNc1EwRkJRenRSUVVOSUxFOUJRVThzUTBGQlF5eERRVUZETzBsQlEySXNRMEZCUXp0SlFVVlBMSGRDUVVGUkxFZEJRV2hDTEZWQlFXbENMRU5CUVZjc1JVRkJSU3hKUVVGakxFVkJRVVVzUlVGQldTeEZRVUZGTEV0QlFUSkRPMUZCUVhaSExHbENRVlZETzFGQlZFY3NTVUZCU1N4UlFVRlJMRWRCUVVjc1MwRkJTeXhEUVVGRE8xRkJRM0pDTEVOQlFVTXNRMEZCUXl4bFFVRmxMRU5CUVVNc1NVRkJTU3hGUVVGRkxGVkJRVU1zUTBGQlF5eEZRVUZGTEVsQlFVazdXVUZETlVJc1NVRkJTU3hEUVVGRExGRkJRVkVzU1VGQlNTeERRVUZETEVsQlFVa3NTMEZCU3l4RlFVRkZMRWxCUVVrc1MwRkJTU3hEUVVGRExGRkJRVkVzUTBGQlF5eEpRVUZKTEVWQlFVVXNRMEZCUXl4RlFVRkZMRVZCUVVVc1JVRkJSU3hMUVVGTExFTkJRVU1zUTBGQlF5eEZRVU51UlR0blFrRkRTU3hSUVVGUkxFZEJRVWNzU1VGQlNTeERRVUZETzJkQ1FVTm9RaXhMUVVGTExFTkJRVU1zUTBGQlF5eEZRVUZGTEVsQlFVa3NRMEZCUXl4RFFVRkRPMkZCUTJ4Q08xRkJRMHdzUTBGQlF5eERRVUZETEVOQlFVTTdVVUZEU0N4UFFVRlBMRkZCUVZFc1EwRkJRenRKUVVOd1FpeERRVUZETzBsQlNVUXNNa05CUVRKQ0xFZEJRVE5DTEZWQlFUUkNMRU5CUVZjc1JVRkJSU3hEUVVGWE8xRkJRMmhFTEVsQlFVa3NRMEZCUXl4TFFVRkxMRU5CUVVNN1dVRkJSU3hQUVVGUExFbEJRVWtzUTBGQlF6dFJRVU42UWl4SlFVRkpMRU5CUVVNc1IwRkJSeXhEUVVGRExFTkJRVU1zU1VGQlNTeERRVUZETEUxQlFVMHNRMEZCUXp0UlFVTjBRaXhQUVVGTkxFTkJRVU1zUlVGQlJTeEZRVUZGTzFsQlExQXNTVUZCU1N4RFFVRkRMRWRCUVVjc1EwRkJReXhEUVVGRExFbEJRVWtzUTBGQlF5eERRVUZETEVOQlFVTXNRMEZCUXp0WlFVTnNRaXhKUVVGSkxFTkJRVU1zUTBGQlF5eE5RVUZOTEVsQlFVa3NTVUZCU1N4RFFVRkRMREpDUVVFeVFpeERRVUZETEVOQlFVTXNRMEZCUXl4TFFVRkxMRVZCUVVVc1EwRkJReXhEUVVGRE8yZENRVU40UkN4UFFVRlBMRWxCUVVrc1EwRkJRenRUUVVOdVFqdFJRVU5FTEU5QlFVOHNTMEZCU3l4RFFVRkRPMGxCUTJwQ0xFTkJRVU03U1VGSFRTeFhRVUZMTEVkQlFWb3NWVUZCWVN4RFFVRmhPMUZCUzNSQ0xFTkJRVU1zUTBGQlF5eE5RVUZOTEVkQlFVY3NTMEZCU3l4RFFVRkRPMUZCUTJwQ0xFOUJRVThzUTBGQlF5eExRVUZMTEVOQlFVTXNaMEpCUVdkQ0xFTkJRVU1zUTBGQlF5eERRVUZETEVsQlFVa3NRMEZCUXl4RlFVRkZMRXRCUVVzc1EwRkJReXhuUWtGQlowSXNRMEZCUXl4RFFVRkRMRU5CUVVNc1MwRkJTeXhEUVVGRExFTkJRVU1zUTBGQlF6dEpRVU0zUlN4RFFVRkRPMGxCUldNc2MwSkJRV2RDTEVkQlFTOUNMRlZCUVdkRExGRkJRV3RDTzFGQlF6bERMRWxCUVVrc1EwRkJReXhIUVVGSExFbEJRVWtzUzBGQlN5eERRVUZETEZGQlFWRXNRMEZCUXl4RFFVRkRPMUZCUXpWQ0xFTkJRVU1zUTBGQlF5eHJRa0ZCYTBJc1EwRkJReXhSUVVGUkxFVkJRVVVzU1VGQlNTeERRVUZETEVOQlFVTTdVVUZEY2tNc1QwRkJUeXhEUVVGRExFTkJRVU03U1VGRFlpeERRVUZETzBsQlIwUXNORUpCUVZrc1IwRkJXaXhWUVVGaExFVkJRVmtzUlVGQlJTeEZRVUZaTzFGQlMyNURMRWxCUVVrc1EwRkJReXhIUVVGSExFbEJRVWtzUTBGQlF5eG5Ra0ZCWjBJc1EwRkJReXhGUVVGRkxFVkJRVVVzUlVGQlJTeERRVUZETEVOQlFVTTdVVUZEZEVNc1NVRkJTU3hEUVVGRExFdEJRVXNzU1VGQlNTeEZRVUZGTzFsQlExb3NTVUZCU1N4RlFVRkZMRWRCUVVjc1MwRkJTeXhEUVVGRExFdEJRVXNzUTBGQlF5eERRVUZETEVOQlFVTXNRMEZCUXp0WlFVTjRRaXhQUVVGUExFVkJRVVVzVlVGQlZTeEZRVUZGTEVOQlFVTXNSVUZCUlN4RlFVRkZMRVZCUVVVc1JVRkJSU3hEUVVGRExFTkJRVU1zUTBGQlF5eEZRVUZGTEVWQlFVVXNSVUZCUlN4RlFVRkZMRU5CUVVNc1EwRkJReXhEUVVGRExFVkJRVVVzUTBGQlF6dFRRVU5zUkR0UlFVVkVMRTlCUVU4c1NVRkJTU3hEUVVGRE8wbEJRMmhDTEVOQlFVTTdTVUZGUkN3eVFrRkJWeXhIUVVGWUxGVkJRVmtzUTBGQlVTeEZRVUZGTEVOQlFXRXNSVUZCUlN4SlFVRlpPMUZCUXpkRExFTkJRVU1zUTBGQlF5eE5RVUZOTEVkQlFVY3NTVUZCU1N4RFFVRkRPMUZCUTJoQ0xFdEJRVXNzU1VGQlNTeERRVUZETEVkQlFVY3NRMEZCUXl4RlFVRkZMRU5CUVVNc1IwRkJSeXhEUVVGRExFTkJRVU1zU1VGQlNTeERRVUZETEUxQlFVMHNSVUZCUlN4RFFVRkRMRWRCUVVjc1EwRkJReXhGUVVGRkxFVkJRVVVzUTBGQlF5eEZRVUZGTzFsQlF6TkRMRWxCUVVrc1EwRkJReXhIUVVGSExFTkJRVU1zUTBGQlF5eEpRVUZKTEVOQlFVTXNRMEZCUXl4RFFVRkRMRU5CUVVNN1dVRkRiRUlzUTBGQlF5eERRVUZETEUxQlFVMHNTVUZCU1N4SlFVRkpMRU5CUVVNN1dVRkRha0lzU1VGQlNTeERRVUZETEZkQlFWY3NRMEZCUXl4RFFVRkRMRU5CUVVNc1EwRkJRenRUUVVOMlFqdFJRVU5FTEVsQlFVa3NRMEZCUXl4SlFVRkpMRWRCUVVjc1NVRkJTU3hEUVVGRExFVkJRVVVzUTBGQlF5eFBRVUZQTEVWQlFVVXNRMEZCUXp0SlFVTnNReXhEUVVGRE8wbEJSVVFzYjBKQlFVa3NSMEZCU2p0UlFVTkpMRWxCUVVrc1IwRkJSeXhIUVVGSExFTkJRVU1zUlVGQlJTeERRVUZETEVkQlFVY3NTVUZCU1N4RFFVRkRMRWxCUVVrc1EwRkJReXhOUVVGTkxFTkJRVU03VVVGRGJFTXNUMEZCVHl4RFFVRkRMRVZCUVVVc1JVRkJSVHRaUVVOU0xFbEJRVWtzUTBGQlF5eEhRVUZITEVsQlFVa3NRMEZCUXl4SlFVRkpMRU5CUVVNc1EwRkJReXhEUVVGRExFVkJRMmhDTEVOQlFVTXNSMEZCUnl4RFFVRkRMRU5CUVVNc1VVRkJVU3hGUVVGRkxFZEJRVWNzUTBGQlF5eERRVUZETEdWQlFXVXNRMEZCUXp0WlFVTjZReXhIUVVGSExFbEJRVWtzUTBGQlF5eEhRVUZITEVOQlFVTXNSMEZCUnl4RFFVRkRMRU5CUVVNc1RVRkJUU3hEUVVGRE8xTkJRek5DTzFGQlEwUXNUMEZCVHl4SFFVRkhMRU5CUVVNN1NVRkRaaXhEUVVGRE8wbEJVMHdzV1VGQlF6dEJRVUZFTEVOQlFVTXNRVUZzUzBRc1NVRnJTME03UVVGc1Mxa3NjMEpCUVVzN1FVRnZTMnhDTzBsQlIwa3NaMEpCUVcxQ0xFVkJRV003VVVGQlpDeFBRVUZGTEVkQlFVWXNSVUZCUlN4RFFVRlpPMUZCUXpkQ0xFbEJRVWtzUTBGQlF5eEhRVUZITEVWQlFVVXNRMEZCUXl4TlFVRk5MRU5CUVVNN1VVRkRiRUlzU1VGQlNTeERRVUZETEVsQlFVa3NSMEZCUnl4SlFVRkpMRXRCUVVzc1EwRkJReXhEUVVGRExFTkJRVU1zUTBGQlF6dFJRVU42UWl4UFFVRlBMRU5CUVVNc1JVRkJSU3hGUVVGRk8xbEJRMUlzU1VGQlNTeERRVUZETEVkQlFVY3NTVUZCU1N4TFFVRkxMRU5CUVVNc1JVRkJSU3hEUVVGRExFTkJRVU1zUTBGQlF5eERRVUZETEVOQlFVTTdXVUZEZWtJc1NVRkJTU3hEUVVGRExFbEJRVWtzUTBGQlF5eERRVUZETEVOQlFVTXNSMEZCUnl4RFFVRkRMRU5CUVVNN1dVRkRha0lzUTBGQlF5eERRVUZETEZGQlFWRXNSMEZCUnl4RFFVRkRMRU5CUVVNN1UwRkRiRUk3U1VGRFRDeERRVUZETzBsQlJVUXNjVUpCUVVrc1IwRkJTanRSUVVOSkxFbEJRVWtzUjBGQlJ5eEhRVUZITEVOQlFVTXNSVUZCUlN4RFFVRkRMRWRCUVVjc1NVRkJTU3hEUVVGRExFbEJRVWtzUTBGQlF5eE5RVUZOTEVOQlFVTTdVVUZEYkVNc1QwRkJUeXhEUVVGRExFVkJRVVU3V1VGQlJTeEhRVUZITEVsQlFVa3NTVUZCU1N4RFFVRkRMRWxCUVVrc1EwRkJReXhEUVVGRExFTkJRVU1zUTBGQlF5eEpRVUZKTEVWQlFVVXNRMEZCUXp0UlFVTjJReXhQUVVGUExFZEJRVWNzUTBGQlF6dEpRVU5tTEVOQlFVTTdTVUZGUkN4MVFrRkJUU3hIUVVGT0xGVkJRVThzUTBGQlVUdFJRVWxZTEVOQlFVTXNRMEZCUXl4UlFVRlJMRWRCUVVjc1NVRkJTU3hEUVVGRExFbEJRVWtzUTBGQlF5eE5RVUZOTEVOQlFVTTdVVUZET1VJc1NVRkJTU3hEUVVGRExFbEJRVWtzUTBGQlF5eEpRVUZKTEVOQlFVTXNRMEZCUXl4RFFVRkRMRU5CUVVNN1NVRkxkRUlzUTBGQlF6dEpRVVZFTEhWQ1FVRk5MRWRCUVU0c1ZVRkJUeXhEUVVGUk8xRkJTMWdzU1VGQlNTeEpRVUZKTEVkQlFVY3NTVUZCU1N4RFFVRkRMRWxCUVVrc1EwRkJReXhOUVVGTkxFZEJRVWNzUTBGQlF5eERRVUZETzFGQlEyaERMRWxCUVVrc1UwRkJVeXhIUVVGSExFbEJRVWtzUTBGQlF5eEpRVUZKTEVOQlFVTXNTVUZCU1N4RFFVRkRMRU5CUVVNN1VVRkRhRU1zU1VGQlNTeERRVUZETEVsQlFVa3NRMEZCUXl4TlFVRk5MRWRCUVVjc1NVRkJTU3hEUVVGRE8xRkJRM2hDTEVsQlFVa3NRMEZCUXl4TFFVRkxMRk5CUVZNc1JVRkJSVHRaUVVOcVFpeEpRVUZKTEVOQlFVTXNTVUZCU1N4RFFVRkRMRU5CUVVNc1EwRkJReXhSUVVGUkxFTkJRVU1zUjBGQlJ5eFRRVUZUTEVOQlFVTTdXVUZEYkVNc1UwRkJVeXhEUVVGRExGRkJRVkVzUjBGQlJ5eERRVUZETEVOQlFVTXNVVUZCVVN4RFFVRkRPMU5CU1c1RE8wbEJRMHdzUTBGQlF6dEpRVWxFTEhOQ1FVRkxMRWRCUVV3c1ZVRkJUU3hEUVVGaE8xRkJRMllzU1VGQlNTeERRVUZETEVkQlFVY3NRMEZCUXl4RFFVRkRMRWxCUVVrc1EwRkJReXhMUVVGTExFVkJRVVVzUTBGQlF5eEhRVUZITEVOQlFVTXNRMEZCUXl4TFFVRkxMRU5CUVVNc1MwRkJTeXhEUVVGRE8xRkJTWGhETEVsQlFVa3NTVUZCU1N4SFFVRkhMRU5CUVVNc1EwRkJReXhMUVVGTExFTkJRVU1zVFVGQlRTeEhRVUZITEVOQlFVTXNRMEZCUXl4SlFVRkpMRU5CUVVNc1RVRkJUU3hIUVVGSExFTkJRVU1zUTBGQlF5eEhRVUZITEVOQlFVTTdVVUZEYkVRc1NVRkJTU3hEUVVGRExFTkJRVU1zU1VGQlNTeERRVUZETEUxQlFVMHNSMEZCUnl4RFFVRkRMRU5CUVVNc1NVRkJTU3hEUVVGRExFMUJRVTBzUlVGQlJUdFpRVU12UWl4RFFVRkRMRU5CUVVNc1YwRkJWeXhEUVVGRExFTkJRVU1zUlVGQlJTeERRVUZETEVWQlFVVXNTVUZCU1N4RFFVRkRMRU5CUVVNN1dVRkRNVUlzU1VGQlNTeERRVUZETEUxQlFVMHNRMEZCUXl4RFFVRkRMRU5CUVVNc1EwRkJRenRUUVVOc1FqdGhRVUZOTzFsQlEwZ3NRMEZCUXl4RFFVRkRMRmRCUVZjc1EwRkJReXhEUVVGRExFVkJRVVVzUTBGQlF5eEZRVUZGTEVOQlFVTXNTVUZCU1N4RFFVRkRMRU5CUVVNN1dVRkRNMElzU1VGQlNTeERRVUZETEUxQlFVMHNRMEZCUXl4RFFVRkRMRU5CUVVNc1EwRkJRenRUUVVOc1FqdEpRVXRNTEVOQlFVTTdTVUZGUkN4M1FrRkJUeXhIUVVGUUxGVkJRVkVzUTBGQlowTTdVVUZEY0VNc1NVRkJTU3hEUVVGRExFbEJRVWtzUTBGQlF5eFBRVUZQTEVOQlFVTXNRMEZCUXl4RFFVRkRMRU5CUVVNN1NVRkRla0lzUTBGQlF6dEpRVWRFTEhGRFFVRnZRaXhIUVVGd1FqdFJRVU5KTEVsQlFVa3NRMEZCUXl4SlFVRkpMRU5CUVVNc1QwRkJUeXhEUVVGRExGVkJRVUVzUTBGQlF5eEpRVUZITEU5QlFVRXNRMEZCUXl4RFFVRkRMSE5DUVVGelFpeEZRVUZGTEVWQlFURkNMRU5CUVRCQ0xFTkJRVU1zUTBGQlF6dEpRVU4wUkN4RFFVRkRPMGxCUjBRc2MwSkJRVXNzUjBGQlRDeFZRVUZOTEZGQlFYTkNPMUZCUVRWQ0xHbENRV1ZETzFGQlpFY3NTVUZCU1N4RFFVRkRMRzlDUVVGdlFpeEZRVUZGTEVOQlFVTTdVVUZETlVJc1NVRkJTU3hEUVVGRExFbEJRVWtzUTBGQlF5eFBRVUZQTEVOQlFVTXNWVUZCUVN4RFFVRkRPMWxCUTJZc1NVRkJTU3hEUVVGRExFZEJRVWNzUTBGQlF5eERRVUZETEZOQlFWTXNSVUZCUlN4RFFVRkRPMWxCUTNSQ0xFbEJRVWtzUTBGQlF5eExRVUZMTEVsQlFVa3NTVUZCU1N4RFFVRkRMRU5CUVVNc1JVRkJSU3hIUVVGSExFMUJRVTBzUTBGQlF5eHZRa0ZCYjBJc1JVRkJSVHRuUWtGRGJFUXNRMEZCUXl4SFFVRkhMRU5CUVVNc1EwRkJReXhKUVVGSkxFTkJRVU1zUzBGQlN5eERRVUZETzJkQ1FVTnFRaXhMUVVGTExFTkJRVU1zUzBGQlN5eERRVUZETEVOQlFVTXNRMEZCUXl4RFFVRkRMRTlCUVU4c1EwRkJReXhWUVVGQkxFVkJRVVVzU1VGQlJTeFBRVUZCTEV0QlFVa3NRMEZCUXl4TlFVRk5MRU5CUVVNc1JVRkJSU3hEUVVGRExFVkJRV1lzUTBGQlpTeERRVUZETEVOQlFVTTdaMEpCUXpWRExFdEJRVWtzUTBGQlF5eE5RVUZOTEVOQlFVTXNRMEZCUXl4RFFVRkRMRU5CUVVNN1owSkJRMllzVVVGQlVTeERRVUZETEVsQlFVa3NRMEZCUXl4RFFVRkRMRU5CUVVNc1EwRkJRenRoUVV0d1FqdFJRVU5NTEVOQlFVTXNRMEZCUXl4RFFVRkRPMGxCUTFBc1EwRkJRenRKUVc5Q1RDeGhRVUZETzBGQlFVUXNRMEZCUXl4QlFXeElSQ3hKUVd0SVF6dEJRV3hJV1N4M1FrRkJUVHRCUVc5SWJrSTdTVUZQU1N4blFrRkJiVUlzUlVGQll5eEZRVUZUTEVWQlFXZENPMUZCUVhaRExFOUJRVVVzUjBGQlJpeEZRVUZGTEVOQlFWazdVVUZCVXl4UFFVRkZMRWRCUVVZc1JVRkJSU3hEUVVGak8xRkJRM1JFTEVsQlFVa3NRMEZCUXl4RlFVRkZMRWRCUVVjc1JVRkJSU3hEUVVGRE8xRkJRMklzUlVGQlJTeERRVUZETEU5QlFVOHNRMEZCUXl4VlFVRkJMRU5CUVVNN1dVRkRVaXhEUVVGRExFTkJRVU1zUjBGQlJ5eEhRVUZITEVWQlFVVXNSVUZCUlN4RFFVRkRMRU5CUVVNc1NVRkJTU3hIUVVGSExFVkJRVVVzUTBGQlF6dFJRVWsxUWl4RFFVRkRMRU5CUVVNc1EwRkJRenRSUVVOSUxFbEJRVWtzUTBGQlF5eEZRVUZGTEVkQlFVY3NSVUZCUlN4RFFVRkRPMUZCUTJJc1JVRkJSU3hEUVVGRExFOUJRVThzUTBGQlF5eFZRVUZCTEVOQlFVTTdXVUZEVWl4RFFVRkRMRU5CUVVNc1NVRkJTU3hEUVVGRExFbEJRVWtzUTBGQlF5eEpRVUZKTEVOQlFVTXNRMEZCUXl4RFFVRkRMRU5CUVVNN1dVRkRjRUlzUTBGQlF5eERRVUZETEV0QlFVc3NRMEZCUXl4SFFVRkhMRU5CUVVNc1NVRkJTU3hEUVVGRExFTkJRVU1zUTBGQlF5eERRVUZETzFGQlNYaENMRU5CUVVNc1EwRkJReXhEUVVGRE8xRkJRMGdzU1VGQlNTeERRVUZETEZGQlFWRXNSMEZCUnl4RlFVRkZMRU5CUVVNc1IwRkJSeXhEUVVGRExGVkJRVUVzUTBGQlF5eEpRVUZMTEVOQlFVTXNRMEZCUXl4TlFVRk5MRWRCUVVjc1MwRkJTeXhEUVVGRExFTkJRVU1zVDBGQlR5eERRVUZETEVOQlFVTXNRMEZCUXl4RFFVRkRMRU5CUVVNc1EwRkJRenRSUVVNMVJDeEpRVUZKTEVOQlFVTXNSVUZCUlN4SFFVRkhMRWxCUVVrc1EwRkJRenRKUVVOdVFpeERRVUZETzBsQlJVUXNjVUpCUVVrc1IwRkJTanRSUVVOSkxFOUJRVThzU1VGQlNTeERRVUZETEVWQlFVVXNRMEZCUXl4SlFVRkpMRVZCUVVVc1EwRkJRenRKUVVNeFFpeERRVUZETzBsQlNVUXNjVU5CUVc5Q0xFZEJRWEJDTEZWQlFYRkNMRVZCUVZrN1VVRkROMElzU1VGQlNTeERRVUZETEZGQlFWRXNSMEZCUnl4SlFVRkpMRU5CUVVNc1JVRkJSU3hEUVVGRExFZEJRVWNzUTBGQlF5eFZRVUZCTEVOQlFVTXNTVUZCU3l4RFFVRkRMRU5CUVVNc1RVRkJUU3hIUVVGSExFdEJRVXNzUTBGQlF5eERRVUZETEU5QlFVOHNRMEZCUXl4RFFVRkRMRU5CUVVNc1EwRkJReXhEUVVGRExFTkJRVU03VVVGRGFrVXNTVUZCU1N4RFFVRkRMRVZCUVVVc1IwRkJSeXhKUVVGSkxFMUJRVTBzUTBGQlF5eEpRVUZKTEVOQlFVTXNSVUZCUlN4RFFVRkRMRU5CUVVNN1VVRkRPVUlzU1VGQlNTeERRVUZETEVWQlFVVXNRMEZCUXl4UFFVRlBMRU5CUVVNc1ZVRkJReXhEUVVGRExFVkJRVVVzUTBGQlF5eEpRVUZMTEU5QlFVRXNRMEZCUXl4RFFVRkRMRWxCUVVrc1IwRkJSeXhGUVVGRkxFTkJRVU1zUTBGQlF5eERRVUZETEVWQlFXUXNRMEZCWXl4RFFVRkRMRU5CUVVNN1NVRkRPVU1zUTBGQlF6dEpRVVZFTEc5RFFVRnRRaXhIUVVGdVFpeFZRVUZ2UWl4RlFVRlpPMUZCUXpWQ0xFbEJRVWtzUTBGQlF5eEZRVUZGTEVOQlFVTXNUMEZCVHl4RFFVRkRMRlZCUVVNc1EwRkJReXhGUVVGRkxFTkJRVU1zU1VGQlN5eFBRVUZCTEVOQlFVTXNRMEZCUXl4bFFVRmxMRWRCUVVjc1JVRkJSU3hEUVVGRExFTkJRVU1zUTBGQlF5eEZRVUY2UWl4RFFVRjVRaXhEUVVGRExFTkJRVU03U1VGRGVrUXNRMEZCUXp0SlFUSkNUeXcyUWtGQldTeEhRVUZ3UWp0UlFVTkpMRWxCUVVrc1VVRkJVU3hIUVVGSExFMUJRVTBzUTBGQlF5eFRRVUZUTEVWQlF6TkNMRU5CUVVNc1IwRkJaU3hKUVVGSkxFVkJRM0JDTEVOQlFVTXNSMEZCUnl4SlFVRkpMRU5CUVVNc1VVRkJVU3hGUVVOcVFpeERRVUZETEVkQlFVY3NRMEZCUXl4RFFVRkRMRTFCUVUwc1JVRkRXaXhYUVVGWExFZEJRVWNzUTBGQlF5eERRVUZETzFGQlEzQkNMRXRCUVVzc1NVRkJTU3hEUVVGRExFZEJRVWNzUTBGQlF5eEZRVUZGTEVOQlFVTXNSMEZCUnl4RFFVRkRMRVZCUVVVc1JVRkJSU3hEUVVGRExFVkJRVVU3V1VGRGVFSXNTVUZCU1N4RFFVRkRMRWRCUVVjc1EwRkJReXhEUVVGRExFTkJRVU1zUTBGQlF5eERRVUZETzFsQlEySXNTVUZCU1N4RFFVRkRMRU5CUVVNc1lVRkJZVHRuUWtGQlJTeFRRVUZUTzFsQlF6bENMRWxCUVVrc1MwRkJTeXhIUVVGSExFTkJRVU1zUTBGQlF5eExRVUZMTEVWQlFVVXNRMEZCUXp0WlFVTjBRaXhKUVVGSkxFTkJRVU1zUTBGQlF5eFJRVUZSTEVsQlFVa3NTMEZCU3l4SFFVRkhMRkZCUVZFc1JVRkJSVHRuUWtGRGFFTXNVVUZCVVN4SFFVRkhMRXRCUVVzc1EwRkJRenRuUWtGRGFrSXNRMEZCUXl4SFFVRkhMRU5CUVVNc1EwRkJRenRuUWtGRFRpeFhRVUZYTEVkQlFVY3NRMEZCUXl4RFFVRkRPMmRDUVVOb1FpeEpRVUZKTEVOQlFVTXNRMEZCUXl4UlFVRlJPMjlDUVVGRkxFMUJRVTA3WVVGRGVrSTdVMEZEU2p0UlFVTkVMRWxCUVVrc1YwRkJWeXhMUVVGTExFTkJRVU03V1VGRGFrSXNRMEZCUXl4UlFVRlJMRWRCUVVjc1RVRkJUU3hEUVVGRExHVkJRV1VzU1VGQlNTeERRVUZETEVOQlFVTXNRMEZCUXl4TlFVRk5MRWxCUVVrc1EwRkJReXhEUVVGRExGRkJRVkVzUTBGQlF5eEZRVU5zUlR0WlFVTkpMRU5CUVVNc1EwRkJReXhYUVVGWExFTkJRVU1zUjBGQlJ5eERRVUZETEVOQlFVTXNRMEZCUXl4SFFVRkhMRU5CUVVNc1EwRkJReXhEUVVGRE8xbEJRekZDTEVOQlFVTXNRMEZCUXl4TlFVRk5MRWRCUVVjc1EwRkJReXhIUVVGSExFTkJRVU1zUTBGQlF6dFRRVU53UWp0UlFVTkVMRTlCUVU4c1EwRkJReXhEUVVGRE8wbEJRMklzUTBGQlF6dEpRVWxFTEhkQ1FVRlBMRWRCUVZBN1VVRkRTU3hKUVVGSkxFbEJRVWtzUTBGQlF5eEZRVUZGTEVsQlFVa3NTVUZCU1N4RlFVRkZPMWxCUTJwQ0xFbEJRVWtzUTBGQlF5eEZRVUZGTEVkQlFVY3NTVUZCU1N4TlFVRk5MRU5CUVVNc1NVRkJTU3hEUVVGRExFVkJRVVVzUTBGQlF5eERRVUZETzFOQlEycERPMUZCU1VRc1NVRkJTU3hEUVVGRExFVkJRVVVzUTBGQlF5eExRVUZMTEVOQlFVTXNTVUZCU1N4RFFVRkRMRkZCUVZFc1EwRkJReXhEUVVGRE8xRkJRemRDTEVsQlFVa3NRMEZCUXl4SFFVRmxMRWxCUVVrc1EwRkJRenRSUVVONlFpeFBRVUZQTEVOQlFVTXNRMEZCUXl4SFFVRkhMRWxCUVVrc1EwRkJReXhaUVVGWkxFVkJRVVVzUTBGQlF5eEpRVUZKTEVOQlFVTXNRMEZCUXl4RFFVRkRMRkZCUVZFc1NVRkJTU3hEUVVGRExFTkJRVU1zUzBGQlN5eEZRVUZGTEVkQlFVY3NUVUZCVFN4RFFVRkRMR1ZCUVdVc1NVRkJTU3hEUVVGRExFTkJRVU1zUTBGQlF5eE5RVUZOTEVOQlFVTXNSVUZCUlR0WlFVTnFSeXhKUVVGSkxFVkJRVVVzUjBGQlJ5eERRVUZETEVOQlFVTXNTVUZCU1N4RFFVRkRMRXRCUVVzc1JVRkJSU3hGUVVGRkxFZEJRVWNzUTBGQlF5eERRVUZETEV0QlFVc3NRMEZCUXl4TFFVRkxMRU5CUVVNN1dVRk5NVU1zU1VGQlNTeEZRVUZGTEV0QlFVc3NSVUZCUlN4RlFVRkZPMmRDUVVOWUxFbEJRVWtzUTBGQlF5eEZRVUZGTEVOQlFVTXNTMEZCU3l4RFFVRkRMRU5CUVVNc1EwRkJReXhEUVVGRE8yRkJRM0JDTzJsQ1FVRk5PMmRDUVVOSUxFbEJRVWtzUlVGQlJTeERRVUZETERKQ1FVRXlRaXhEUVVGRExFTkJRVU1zUTBGQlF5eExRVUZMTEVWQlFVVXNRMEZCUXl4RFFVRkRMRWxCUVVrc1EwRkJReXhGUVVGRk8yOUNRVVZxUkN4RFFVRkRMRU5CUVVNc1lVRkJZU3hIUVVGSExFbEJRVWtzUTBGQlF6dHZRa0ZEZGtJc1UwRkJVenRwUWtGRFdqdG5Ra0ZGUkN4SlFVRkpMRXRCUVVzc1IwRkJSeXhGUVVGRkxFTkJRVU1zV1VGQldTeERRVUZETEVOQlFVTXNRMEZCUXl4SlFVRkpMRVZCUVVVc1EwRkJReXhEUVVGRExFdEJRVXNzUTBGQlF5eERRVUZETzJkQ1FVTTNReXhKUVVGSkxFdEJRVXNzUzBGQlN5eEpRVUZKTEVWQlFVVTdiMEpCUTJoQ0xFbEJRVWtzUTBGQlF5eEZRVUZGTEVOQlFVTXNUVUZCVFN4RFFVRkRMRXRCUVVzc1EwRkJReXhGUVVGRkxFTkJRVU1zUTBGQlF6dHZRa0ZEZWtJc1NVRkJTU3hEUVVGRExFVkJRVVVzUTBGQlF5eE5RVUZOTEVOQlFVTXNTMEZCU3l4RFFVRkRMRVZCUVVVc1EwRkJReXhEUVVGRE8yOUNRVU42UWl4SlFVRkpMRU5CUVVNc1JVRkJSU3hEUVVGRExFMUJRVTBzUTBGQlF5eEZRVUZGTEVOQlFVTXNRMEZCUXp0dlFrRkRia0lzU1VGQlNTeERRVUZETEZGQlFWRXNRMEZCUXl4SlFVRkpMRU5CUVVNc1MwRkJTeXhEUVVGRExGVkJRVlVzUTBGQlF5eERRVUZETzJsQ1FVTjRRenR4UWtGQlRUdHZRa0ZKU0N4RFFVRkRMRU5CUVVNc1lVRkJZU3hIUVVGSExFbEJRVWtzUTBGQlF6dHZRa0ZEZGtJc1UwRkJVenRwUWtGRFdqdG5Ra0ZEUkN4SlFVRkpMRU5CUVVNc1EwRkJReXhMUVVGTExFVkJRVVVzU1VGQlNTeERRVUZETEVWQlFVVTdiMEpCUzJoQ0xFbEJRVWtzUTBGQlF5eFJRVUZSTEVOQlFVTXNTVUZCU1N4RFFVRkRMRU5CUVVNc1EwRkJReXhEUVVGRE8ybENRVU42UWp0eFFrRkJUVHR2UWtGSlNDeEpRVUZKTEVOQlFVTXNSVUZCUlN4RFFVRkRMRXRCUVVzc1EwRkJReXhEUVVGRExFTkJRVU1zUTBGQlF6dHBRa0ZEY0VJN1lVRkRTanRUUVUxS08wbEJTVXdzUTBGQlF6dEpRVWRFTEhOQ1FVRkxMRWRCUVV3N1VVRkRTU3hKUVVGSkxFTkJRVU1zVDBGQlR5eEZRVUZGTEVOQlFVTTdVVUZEWml4SlFVRkpMRkZCUVZFc1IwRkJSeXhOUVVGTkxFTkJRVU1zVTBGQlV5eEZRVUZGTEVsQlFVa3NSMEZCUnl4SlFVRkpMRU5CUVVNc1JVRkJSU3hEUVVGRExFbEJRVWtzUlVGQlJTeERRVUZETzFGQlEzWkVMRTlCUVU4c1NVRkJTU3hEUVVGRExFZEJRVWNzUTBGQlF5eFJRVUZSTEVkQlFVY3NTVUZCU1N4RFFVRkRMRWRCUVVjc1RVRkJUU3hGUVVGRk8xbEJRM1pETEVsQlFVa3NRMEZCUXl4UFFVRlBMRVZCUVVVc1EwRkJRenRaUVVObUxGRkJRVkVzUjBGQlJ5eEpRVUZKTEVOQlFVTTdXVUZEYUVJc1NVRkJTU3hIUVVGSExFbEJRVWtzUTBGQlF5eEZRVUZGTEVOQlFVTXNTVUZCU1N4RlFVRkZMRU5CUVVNN1UwRkRla0k3VVVGRFJDeFBRVUZQTEVsQlFVa3NRMEZCUXp0SlFVTm9RaXhEUVVGRE8wbEJjRXROTERKQ1FVRnZRaXhIUVVGSExFTkJRVU1zU1VGQlNTeERRVUZETzBsQlF6ZENMSE5DUVVGbExFZEJRVWNzUTBGQlF5eExRVUZMTEVOQlFVTTdTVUZ2UzNCRExHRkJRVU03UTBGQlFTeEJRWHBMUkN4SlFYbExRenRCUVhwTFdTeDNRa0ZCVFR0QlFXbE1ia0lzVTBGQlowSXNNa0pCUVRKQ0xFTkJRVU1zUzBGQlowUXNSVUZCUlN4VlFVRnRRaXhGUVVGRkxGVkJRVzFDTzBsQlIyeEpMRWxCUVUwc1JVRkJSU3hIUVVGbExFdEJRVXNzUTBGQlF5eEhRVUZITEVOQlFVTXNWVUZCUVN4RFFVRkRMRWxCUVVrc1QwRkJRU3hKUVVGSkxGRkJRVkVzUTBGQlF5eERRVUZETEVOQlFVTXNZVUZCWVN4RFFVRkRMRVZCUVRkQ0xFTkJRVFpDTEVOQlFVTXNRMEZCUXp0SlFVTnlSU3hKUVVGTkxFVkJRVVVzUjBGQmFVSXNSVUZCUlN4RFFVRkRPMGxCUXpWQ0xFbEJRVTBzUTBGQlF5eEhRVUZITEV0QlFVc3NRMEZCUXl4TlFVRk5MRU5CUVVNN1NVRkRka0lzUzBGQlN5eEpRVUZKTEVOQlFVTXNSMEZCUnl4RFFVRkRMRVZCUVVVc1EwRkJReXhIUVVGSExFTkJRVU1zUjBGQlJ5eERRVUZETEVWQlFVVXNRMEZCUXl4RlFVRkZMRVZCUVVVN1VVRkROVUlzU1VGQlRTeEpRVUZKTEVkQlFVY3NTMEZCU3l4RFFVRkRMRU5CUVVNc1EwRkJReXhGUVVGRkxFdEJRVXNzUjBGQlJ5eExRVUZMTEVOQlFVTXNRMEZCUXl4SFFVRkhMRU5CUVVNc1EwRkJReXhEUVVGRE8xRkJRelZETEVWQlFVVXNRMEZCUXl4SlFVRkpMRU5CUVVNc1NVRkJTU3hWUVVGVkxFTkJRVU1zUlVGQlJTeERRVUZETEVOQlFVTXNRMEZCUXl4RlFVRkZMRVZCUVVVc1EwRkJReXhEUVVGRExFZEJRVWNzUTBGQlF5eERRVUZETEVWQlFVVXNRMEZCUXl4SlFVRkpMRU5CUVVNc1NVRkJTU3hIUVVGSExFdEJRVXNzUTBGQlF5eEpRVUZKTEVOQlFVTXNSMEZCUnl4RFFVRkRMRU5CUVVNc1EwRkJReXhEUVVGRE8wdEJRek5GTzBsQlEwUXNTVUZCVFN4UlFVRlJMRWRCUVVjc1JVRkJSU3hEUVVGRExFTkJRVU1zUTBGQlF5eEZRVU5zUWl4VFFVRlRMRWRCUVVjc1JVRkJSU3hEUVVGRExFTkJRVU1zUjBGQlJ5eERRVUZETEVOQlFVTXNSVUZEY2tJc1dVRkJXU3hIUVVGSExFdEJRVXNzUTBGQlF5eERRVUZETEVOQlFVTXNRMEZCUXl4SlFVRkpMRWRCUVVjc1EwRkJReXhGUVVOb1F5eGhRVUZoTEVkQlFVY3NTMEZCU3l4RFFVRkRMRU5CUVVNc1IwRkJSeXhEUVVGRExFTkJRVU1zUTBGQlF5eEpRVUZKTEVkQlFVY3NRMEZCUXl4RFFVRkRPMGxCUXpGRExFbEJRVWtzVFVGQlRTeEhRVUZoTEVsQlFVa3NSVUZCUlN4TlFVRk5MRWRCUVdFc1NVRkJTU3hEUVVGRE8wbEJRM0pFTEVsQlFVa3NWVUZCVlN4RlFVRkZPMUZCUTFvc1RVRkJUU3hIUVVGSExFbEJRVWtzVVVGQlVTeERRVUZETEZWQlFWVXNSVUZCUlN4UlFVRlJMRU5CUVVNc1RVRkJUU3hIUVVGSExFbEJRVWtzUTBGQlF5eERRVUZETzFGQlF6RkVMRVZCUVVVc1EwRkJReXhKUVVGSkxFTkJRVU1zVFVGQlRTeERRVUZETEVOQlFVTTdVVUZEYUVJc1JVRkJSU3hEUVVGRExFbEJRVWtzUTBGQlF5eEpRVUZKTEZWQlFWVXNRMEZCUXl4TlFVRk5MRVZCUVVVc1VVRkJVU3hGUVVGRkxGbEJRVmtzUTBGQlF5eERRVUZETEVOQlFVTTdTMEZETTBRN1NVRkRSQ3hKUVVGSkxGVkJRVlVzUlVGQlJUdFJRVU5hTEUxQlFVMHNSMEZCUnl4SlFVRkpMRkZCUVZFc1EwRkJReXhWUVVGVkxFVkJRVVVzVTBGQlV5eERRVUZETEUxQlFVMHNSMEZCUnl4SlFVRkpMRU5CUVVNc1EwRkJRenRSUVVNelJDeEZRVUZGTEVOQlFVTXNTVUZCU1N4RFFVRkRMRTFCUVUwc1EwRkJReXhEUVVGRE8xRkJRMmhDTEVWQlFVVXNRMEZCUXl4SlFVRkpMRU5CUVVNc1NVRkJTU3hWUVVGVkxFTkJRVU1zVTBGQlV5eEZRVUZGTEUxQlFVMHNSVUZCUlN4aFFVRmhMRU5CUVVNc1EwRkJReXhEUVVGRE8wdEJRemRFTzBsQlEwUXNTVUZCU1N4TlFVRk5MRWRCUVVjc1NVRkJTU3hOUVVGTkxFTkJRVU1zUlVGQlJTeEZRVUZGTEVWQlFVVXNRMEZCUXl4RFFVRkRPMGxCUTJoRExFMUJRVTBzUTBGQlF5eExRVUZMTEVWQlFVVXNRMEZCUXp0SlFVTm1MRTlCUVU4N1VVRkRTQ3hWUVVGVkxFVkJRVVVzUlVGQlJTeERRVUZETEV0QlFVc3NRMEZCUXl4RFFVRkRMRVZCUVVVc1MwRkJTeXhEUVVGRExFMUJRVTBzUTBGQlF5eERRVUZETEVkQlFVY3NRMEZCUXl4VlFVRkJMRU5CUVVNc1NVRkJTU3hQUVVGQkxFTkJRVU1zUTBGQlF5eFJRVUZSTEVWQlFVVXNSVUZCV2l4RFFVRlpMRU5CUVVNN1VVRkROVVFzVlVGQlZTeEZRVUZGTEUxQlFVMHNRMEZCUXl4RFFVRkRMRU5CUVVNc1RVRkJUU3hEUVVGRExGRkJRVkVzUlVGQlJTeERRVUZETEVOQlFVTXNRMEZCUXl4UlFVRlJMRU5CUVVNc1VVRkJVU3hGUVVGRkxFZEJRVWNzV1VGQldUdFJRVU16UlN4VlFVRlZMRVZCUVVVc1RVRkJUU3hEUVVGRExFTkJRVU1zUTBGQlF5eE5RVUZOTEVOQlFVTXNVVUZCVVN4RlFVRkZMRU5CUVVNc1EwRkJReXhEUVVGRExGTkJRVk1zUTBGQlF5eFJRVUZSTEVWQlFVVXNSMEZCUnl4aFFVRmhPMHRCUTJoR0xFTkJRVU03UVVGRFRpeERRVUZETzBGQmFFTkVMR3RGUVdkRFF5SjkiXX0= - - -/***/ }), - -/***/ "./node_modules/@eastdesire/jscolor/jscolor.js": -/*!*****************************************************!*\ - !*** ./node_modules/@eastdesire/jscolor/jscolor.js ***! - \*****************************************************/ -/***/ (function(module) { - -/** - * jscolor - JavaScript Color Picker - * - * @link http://jscolor.com - * @license For open source use: GPLv3 - * For commercial use: JSColor Commercial License - * @author Jan Odvarko - East Desire - * - * See usage examples at http://jscolor.com/examples/ - */ - - -(function (global, factory) { - - 'use strict'; - - if ( true && typeof module.exports === 'object') { - // Export jscolor as a module - module.exports = global.document ? - factory (global) : - function (win) { - if (!win.document) { - throw new Error('jscolor needs a window with document'); - } - return factory(win); - } - return; - } - - // Default use (no module export) - factory(global); - -})(typeof window !== 'undefined' ? window : this, function (window) { // BEGIN factory - -// BEGIN jscolor code - - -'use strict'; - - -var jscolor = (function () { // BEGIN jscolor - -var jsc = { - - - initialized : false, - - instances : [], // created instances of jscolor - - readyQueue : [], // functions waiting to be called after init - - - register : function () { - if (typeof window !== 'undefined' && window.document) { - window.document.addEventListener('DOMContentLoaded', jsc.pub.init, false); - } - }, - - - installBySelector : function (selector, rootNode) { - rootNode = rootNode ? jsc.node(rootNode) : window.document; - if (!rootNode) { - throw new Error('Missing root node'); - } - - var elms = rootNode.querySelectorAll(selector); - - // for backward compatibility with DEPRECATED installation/configuration using className - var matchClass = new RegExp('(^|\\s)(' + jsc.pub.lookupClass + ')(\\s*(\\{[^}]*\\})|\\s|$)', 'i'); - - for (var i = 0; i < elms.length; i += 1) { - - if (elms[i].jscolor && elms[i].jscolor instanceof jsc.pub) { - continue; // jscolor already installed on this element - } - - if (elms[i].type !== undefined && elms[i].type.toLowerCase() == 'color' && jsc.isColorAttrSupported) { - continue; // skips inputs of type 'color' if supported by the browser - } - - var dataOpts, m; - - if ( - (dataOpts = jsc.getDataAttr(elms[i], 'jscolor')) !== null || - (elms[i].className && (m = elms[i].className.match(matchClass))) // installation using className (DEPRECATED) - ) { - var targetElm = elms[i]; - - var optsStr = ''; - if (dataOpts !== null) { - optsStr = dataOpts; - - } else if (m) { // installation using className (DEPRECATED) - console.warn('Installation using class name is DEPRECATED. Use data-jscolor="" attribute instead.' + jsc.docsRef); - if (m[4]) { - optsStr = m[4]; - } - } - - var opts = null; - if (optsStr.trim()) { - try { - opts = jsc.parseOptionsStr(optsStr); - } catch (e) { - console.warn(e + '\n' + optsStr); - } - } - - try { - new jsc.pub(targetElm, opts); - } catch (e) { - console.warn(e); - } - } - } - }, - - - parseOptionsStr : function (str) { - var opts = null; - - try { - opts = JSON.parse(str); - - } catch (eParse) { - if (!jsc.pub.looseJSON) { - throw new Error('Could not parse jscolor options as JSON: ' + eParse); - } else { - // loose JSON syntax is enabled -> try to evaluate the options string as JavaScript object - try { - opts = (new Function ('var opts = (' + str + '); return typeof opts === "object" ? opts : {};'))(); - } catch (eEval) { - throw new Error('Could not evaluate jscolor options: ' + eEval); - } - } - } - return opts; - }, - - - getInstances : function () { - var inst = []; - for (var i = 0; i < jsc.instances.length; i += 1) { - // if the targetElement still exists, the instance is considered "alive" - if (jsc.instances[i] && jsc.instances[i].targetElement) { - inst.push(jsc.instances[i]); - } - } - return inst; - }, - - - createEl : function (tagName) { - var el = window.document.createElement(tagName); - jsc.setData(el, 'gui', true); - return el; - }, - - - node : function (nodeOrSelector) { - if (!nodeOrSelector) { - return null; - } - - if (typeof nodeOrSelector === 'string') { - // query selector - var sel = nodeOrSelector; - var el = null; - try { - el = window.document.querySelector(sel); - } catch (e) { - console.warn(e); - return null; - } - if (!el) { - console.warn('No element matches the selector: %s', sel); - } - return el; - } - - if (jsc.isNode(nodeOrSelector)) { - // DOM node - return nodeOrSelector; - } - - console.warn('Invalid node of type %s: %s', typeof nodeOrSelector, nodeOrSelector); - return null; - }, - - - // See https://stackoverflow.com/questions/384286/ - isNode : function (val) { - if (typeof Node === 'object') { - return val instanceof Node; - } - return val && typeof val === 'object' && typeof val.nodeType === 'number' && typeof val.nodeName === 'string'; - }, - - - nodeName : function (node) { - if (node && node.nodeName) { - return node.nodeName.toLowerCase(); - } - return false; - }, - - - removeChildren : function (node) { - while (node.firstChild) { - node.removeChild(node.firstChild); - } - }, - - - isTextInput : function (el) { - return el && jsc.nodeName(el) === 'input' && el.type.toLowerCase() === 'text'; - }, - - - isButton : function (el) { - if (!el) { - return false; - } - var n = jsc.nodeName(el); - return ( - (n === 'button') || - (n === 'input' && ['button', 'submit', 'reset'].indexOf(el.type.toLowerCase()) > -1) - ); - }, - - - isButtonEmpty : function (el) { - switch (jsc.nodeName(el)) { - case 'input': return (!el.value || el.value.trim() === ''); - case 'button': return (el.textContent.trim() === ''); - } - return null; // could not determine element's text - }, - - - // See https://github.com/WICG/EventListenerOptions/blob/gh-pages/explainer.md - isPassiveEventSupported : (function () { - var supported = false; - - try { - var opts = Object.defineProperty({}, 'passive', { - get: function () { supported = true; } - }); - window.addEventListener('testPassive', null, opts); - window.removeEventListener('testPassive', null, opts); - } catch (e) {} - - return supported; - })(), - - - isColorAttrSupported : (function () { - var elm = window.document.createElement('input'); - if (elm.setAttribute) { - elm.setAttribute('type', 'color'); - if (elm.type.toLowerCase() == 'color') { - return true; - } - } - return false; - })(), - - - dataProp : '_data_jscolor', - - - // usage: - // setData(obj, prop, value) - // setData(obj, {prop:value, ...}) - // - setData : function () { - var obj = arguments[0]; - - if (arguments.length === 3) { - // setting a single property - var data = obj.hasOwnProperty(jsc.dataProp) ? obj[jsc.dataProp] : (obj[jsc.dataProp] = {}); - var prop = arguments[1]; - var value = arguments[2]; - - data[prop] = value; - return true; - - } else if (arguments.length === 2 && typeof arguments[1] === 'object') { - // setting multiple properties - var data = obj.hasOwnProperty(jsc.dataProp) ? obj[jsc.dataProp] : (obj[jsc.dataProp] = {}); - var map = arguments[1]; - - for (var prop in map) { - if (map.hasOwnProperty(prop)) { - data[prop] = map[prop]; - } - } - return true; - } - - throw new Error('Invalid arguments'); - }, - - - // usage: - // removeData(obj, prop, [prop...]) - // - removeData : function () { - var obj = arguments[0]; - if (!obj.hasOwnProperty(jsc.dataProp)) { - return true; // data object does not exist - } - for (var i = 1; i < arguments.length; i += 1) { - var prop = arguments[i]; - delete obj[jsc.dataProp][prop]; - } - return true; - }, - - - getData : function (obj, prop, setDefault) { - if (!obj.hasOwnProperty(jsc.dataProp)) { - // data object does not exist - if (setDefault !== undefined) { - obj[jsc.dataProp] = {}; // create data object - } else { - return undefined; // no value to return - } - } - var data = obj[jsc.dataProp]; - - if (!data.hasOwnProperty(prop) && setDefault !== undefined) { - data[prop] = setDefault; - } - return data[prop]; - }, - - - getDataAttr : function (el, name) { - var attrName = 'data-' + name; - var attrValue = el.getAttribute(attrName); - return attrValue; - }, - - - setDataAttr : function (el, name, value) { - var attrName = 'data-' + name; - el.setAttribute(attrName, value); - }, - - - _attachedGroupEvents : {}, - - - attachGroupEvent : function (groupName, el, evnt, func) { - if (!jsc._attachedGroupEvents.hasOwnProperty(groupName)) { - jsc._attachedGroupEvents[groupName] = []; - } - jsc._attachedGroupEvents[groupName].push([el, evnt, func]); - el.addEventListener(evnt, func, false); - }, - - - detachGroupEvents : function (groupName) { - if (jsc._attachedGroupEvents.hasOwnProperty(groupName)) { - for (var i = 0; i < jsc._attachedGroupEvents[groupName].length; i += 1) { - var evt = jsc._attachedGroupEvents[groupName][i]; - evt[0].removeEventListener(evt[1], evt[2], false); - } - delete jsc._attachedGroupEvents[groupName]; - } - }, - - - preventDefault : function (e) { - if (e.preventDefault) { e.preventDefault(); } - e.returnValue = false; - }, - - - triggerEvent : function (el, eventName, bubbles, cancelable) { - if (!el) { - return; - } - - var ev = null; - - if (typeof Event === 'function') { - ev = new Event(eventName, { - bubbles: bubbles, - cancelable: cancelable - }); - } else { - // IE - ev = window.document.createEvent('Event'); - ev.initEvent(eventName, bubbles, cancelable); - } - - if (!ev) { - return false; - } - - // so that we know that the event was triggered internally - jsc.setData(ev, 'internal', true); - - el.dispatchEvent(ev); - return true; - }, - - - triggerInputEvent : function (el, eventName, bubbles, cancelable) { - if (!el) { - return; - } - if (jsc.isTextInput(el)) { - jsc.triggerEvent(el, eventName, bubbles, cancelable); - } - }, - - - eventKey : function (ev) { - var keys = { - 9: 'Tab', - 13: 'Enter', - 27: 'Escape', - }; - if (typeof ev.code === 'string') { - return ev.code; - } else if (ev.keyCode !== undefined && keys.hasOwnProperty(ev.keyCode)) { - return keys[ev.keyCode]; - } - return null; - }, - - - strList : function (str) { - if (!str) { - return []; - } - return str.replace(/^\s+|\s+$/g, '').split(/\s+/); - }, - - - // The className parameter (str) can only contain a single class name - hasClass : function (elm, className) { - if (!className) { - return false; - } - if (elm.classList !== undefined) { - return elm.classList.contains(className); - } - // polyfill - return -1 != (' ' + elm.className.replace(/\s+/g, ' ') + ' ').indexOf(' ' + className + ' '); - }, - - - // The className parameter (str) can contain multiple class names separated by whitespace - addClass : function (elm, className) { - var classNames = jsc.strList(className); - - if (elm.classList !== undefined) { - for (var i = 0; i < classNames.length; i += 1) { - elm.classList.add(classNames[i]); - } - return; - } - // polyfill - for (var i = 0; i < classNames.length; i += 1) { - if (!jsc.hasClass(elm, classNames[i])) { - elm.className += (elm.className ? ' ' : '') + classNames[i]; - } - } - }, - - - // The className parameter (str) can contain multiple class names separated by whitespace - removeClass : function (elm, className) { - var classNames = jsc.strList(className); - - if (elm.classList !== undefined) { - for (var i = 0; i < classNames.length; i += 1) { - elm.classList.remove(classNames[i]); - } - return; - } - // polyfill - for (var i = 0; i < classNames.length; i += 1) { - var repl = new RegExp( - '^\\s*' + classNames[i] + '\\s*|' + - '\\s*' + classNames[i] + '\\s*$|' + - '\\s+' + classNames[i] + '(\\s+)', - 'g' - ); - elm.className = elm.className.replace(repl, '$1'); - } - }, - - - getCompStyle : function (elm) { - var compStyle = window.getComputedStyle ? window.getComputedStyle(elm) : elm.currentStyle; - - // Note: In Firefox, getComputedStyle returns null in a hidden iframe, - // that's why we need to check if the returned value is non-empty - if (!compStyle) { - return {}; - } - return compStyle; - }, - - - // Note: - // Setting a property to NULL reverts it to the state before it was first set - // with the 'reversible' flag enabled - // - setStyle : function (elm, styles, important, reversible) { - // using '' for standard priority (IE10 apparently doesn't like value undefined) - var priority = important ? 'important' : ''; - var origStyle = null; - - for (var prop in styles) { - if (styles.hasOwnProperty(prop)) { - var setVal = null; - - if (styles[prop] === null) { - // reverting a property value - - if (!origStyle) { - // get the original style object, but dont't try to create it if it doesn't exist - origStyle = jsc.getData(elm, 'origStyle'); - } - if (origStyle && origStyle.hasOwnProperty(prop)) { - // we have property's original value -> use it - setVal = origStyle[prop]; - } - - } else { - // setting a property value - - if (reversible) { - if (!origStyle) { - // get the original style object and if it doesn't exist, create it - origStyle = jsc.getData(elm, 'origStyle', {}); - } - if (!origStyle.hasOwnProperty(prop)) { - // original property value not yet stored -> store it - origStyle[prop] = elm.style[prop]; - } - } - setVal = styles[prop]; - } - - if (setVal !== null) { - elm.style.setProperty(prop, setVal, priority); - } - } - } - }, - - - hexColor : function (r, g, b) { - return '#' + ( - ('0' + Math.round(r).toString(16)).slice(-2) + - ('0' + Math.round(g).toString(16)).slice(-2) + - ('0' + Math.round(b).toString(16)).slice(-2) - ).toUpperCase(); - }, - - - hexaColor : function (r, g, b, a) { - return '#' + ( - ('0' + Math.round(r).toString(16)).slice(-2) + - ('0' + Math.round(g).toString(16)).slice(-2) + - ('0' + Math.round(b).toString(16)).slice(-2) + - ('0' + Math.round(a * 255).toString(16)).slice(-2) - ).toUpperCase(); - }, - - - rgbColor : function (r, g, b) { - return 'rgb(' + - Math.round(r) + ',' + - Math.round(g) + ',' + - Math.round(b) + - ')'; - }, - - - rgbaColor : function (r, g, b, a) { - return 'rgba(' + - Math.round(r) + ',' + - Math.round(g) + ',' + - Math.round(b) + ',' + - (Math.round((a===undefined || a===null ? 1 : a) * 100) / 100) + - ')'; - }, - - - linearGradient : (function () { - - function getFuncName () { - var stdName = 'linear-gradient'; - var prefixes = ['', '-webkit-', '-moz-', '-o-', '-ms-']; - var helper = window.document.createElement('div'); - - for (var i = 0; i < prefixes.length; i += 1) { - var tryFunc = prefixes[i] + stdName; - var tryVal = tryFunc + '(to right, rgba(0,0,0,0), rgba(0,0,0,0))'; - - helper.style.background = tryVal; - if (helper.style.background) { // CSS background successfully set -> function name is supported - return tryFunc; - } - } - return stdName; // fallback to standard 'linear-gradient' without vendor prefix - } - - var funcName = getFuncName(); - - return function () { - return funcName + '(' + Array.prototype.join.call(arguments, ', ') + ')'; - }; - - })(), - - - setBorderRadius : function (elm, value) { - jsc.setStyle(elm, {'border-radius' : value || '0'}); - }, - - - setBoxShadow : function (elm, value) { - jsc.setStyle(elm, {'box-shadow': value || 'none'}); - }, - - - getElementPos : function (e, relativeToViewport) { - var x=0, y=0; - var rect = e.getBoundingClientRect(); - x = rect.left; - y = rect.top; - if (!relativeToViewport) { - var viewPos = jsc.getViewPos(); - x += viewPos[0]; - y += viewPos[1]; - } - return [x, y]; - }, - - - getElementSize : function (e) { - return [e.offsetWidth, e.offsetHeight]; - }, - - - // get pointer's X/Y coordinates relative to viewport - getAbsPointerPos : function (e) { - var x = 0, y = 0; - if (typeof e.changedTouches !== 'undefined' && e.changedTouches.length) { - // touch devices - x = e.changedTouches[0].clientX; - y = e.changedTouches[0].clientY; - } else if (typeof e.clientX === 'number') { - x = e.clientX; - y = e.clientY; - } - return { x: x, y: y }; - }, - - - // get pointer's X/Y coordinates relative to target element - getRelPointerPos : function (e) { - var target = e.target || e.srcElement; - var targetRect = target.getBoundingClientRect(); - - var x = 0, y = 0; - - var clientX = 0, clientY = 0; - if (typeof e.changedTouches !== 'undefined' && e.changedTouches.length) { - // touch devices - clientX = e.changedTouches[0].clientX; - clientY = e.changedTouches[0].clientY; - } else if (typeof e.clientX === 'number') { - clientX = e.clientX; - clientY = e.clientY; - } - - x = clientX - targetRect.left; - y = clientY - targetRect.top; - return { x: x, y: y }; - }, - - - getViewPos : function () { - var doc = window.document.documentElement; - return [ - (window.pageXOffset || doc.scrollLeft) - (doc.clientLeft || 0), - (window.pageYOffset || doc.scrollTop) - (doc.clientTop || 0) - ]; - }, - - - getViewSize : function () { - var doc = window.document.documentElement; - return [ - (window.innerWidth || doc.clientWidth), - (window.innerHeight || doc.clientHeight), - ]; - }, - - - // r: 0-255 - // g: 0-255 - // b: 0-255 - // - // returns: [ 0-360, 0-100, 0-100 ] - // - RGB_HSV : function (r, g, b) { - r /= 255; - g /= 255; - b /= 255; - var n = Math.min(Math.min(r,g),b); - var v = Math.max(Math.max(r,g),b); - var m = v - n; - if (m === 0) { return [ null, 0, 100 * v ]; } - var h = r===n ? 3+(b-g)/m : (g===n ? 5+(r-b)/m : 1+(g-r)/m); - return [ - 60 * (h===6?0:h), - 100 * (m/v), - 100 * v - ]; - }, - - - // h: 0-360 - // s: 0-100 - // v: 0-100 - // - // returns: [ 0-255, 0-255, 0-255 ] - // - HSV_RGB : function (h, s, v) { - var u = 255 * (v / 100); - - if (h === null) { - return [ u, u, u ]; - } - - h /= 60; - s /= 100; - - var i = Math.floor(h); - var f = i%2 ? h-i : 1-(h-i); - var m = u * (1 - s); - var n = u * (1 - s * f); - switch (i) { - case 6: - case 0: return [u,n,m]; - case 1: return [n,u,m]; - case 2: return [m,u,n]; - case 3: return [m,n,u]; - case 4: return [n,m,u]; - case 5: return [u,m,n]; - } - }, - - - parseColorString : function (str) { - var ret = { - rgba: null, - format: null // 'hex' | 'hexa' | 'rgb' | 'rgba' - }; - - var m; - - if (m = str.match(/^\W*([0-9A-F]{3,8})\W*$/i)) { - // HEX notation - - if (m[1].length === 8) { - // 8-char notation (= with alpha) - ret.format = 'hexa'; - ret.rgba = [ - parseInt(m[1].slice(0,2),16), - parseInt(m[1].slice(2,4),16), - parseInt(m[1].slice(4,6),16), - parseInt(m[1].slice(6,8),16) / 255 - ]; - - } else if (m[1].length === 6) { - // 6-char notation - ret.format = 'hex'; - ret.rgba = [ - parseInt(m[1].slice(0,2),16), - parseInt(m[1].slice(2,4),16), - parseInt(m[1].slice(4,6),16), - null - ]; - - } else if (m[1].length === 3) { - // 3-char notation - ret.format = 'hex'; - ret.rgba = [ - parseInt(m[1].charAt(0) + m[1].charAt(0),16), - parseInt(m[1].charAt(1) + m[1].charAt(1),16), - parseInt(m[1].charAt(2) + m[1].charAt(2),16), - null - ]; - - } else { - return false; - } - - return ret; - } - - if (m = str.match(/^\W*rgba?\(([^)]*)\)\W*$/i)) { - // rgb(...) or rgba(...) notation - - var par = m[1].split(','); - var re = /^\s*(\d+|\d*\.\d+|\d+\.\d*)\s*$/; - var mR, mG, mB, mA; - if ( - par.length >= 3 && - (mR = par[0].match(re)) && - (mG = par[1].match(re)) && - (mB = par[2].match(re)) - ) { - ret.format = 'rgb'; - ret.rgba = [ - parseFloat(mR[1]) || 0, - parseFloat(mG[1]) || 0, - parseFloat(mB[1]) || 0, - null - ]; - - if ( - par.length >= 4 && - (mA = par[3].match(re)) - ) { - ret.format = 'rgba'; - ret.rgba[3] = parseFloat(mA[1]) || 0; - } - return ret; - } - } - - return false; - }, - - - parsePaletteValue : function (mixed) { - var vals = []; - - if (typeof mixed === 'string') { // input is a string of space separated color values - // rgb() and rgba() may contain spaces too, so let's find all color values by regex - mixed.replace(/#[0-9A-F]{3}([0-9A-F]{3})?|rgba?\(([^)]*)\)/ig, function (val) { - vals.push(val); - }); - } else if (Array.isArray(mixed)) { // input is an array of color values - vals = mixed; - } - - // convert all values into uniform color format - - var colors = []; - - for (var i = 0; i < vals.length; i++) { - var color = jsc.parseColorString(vals[i]); - if (color) { - colors.push(color); - } - } - - return colors; - }, - - - containsTranparentColor : function (colors) { - for (var i = 0; i < colors.length; i++) { - var a = colors[i].rgba[3]; - if (a !== null && a < 1.0) { - return true; - } - } - return false; - }, - - - isAlphaFormat : function (format) { - switch (format.toLowerCase()) { - case 'hexa': - case 'rgba': - return true; - } - return false; - }, - - - // Canvas scaling for retina displays - // - // adapted from https://www.html5rocks.com/en/tutorials/canvas/hidpi/ - // - scaleCanvasForHighDPR : function (canvas) { - var dpr = window.devicePixelRatio || 1; - canvas.width *= dpr; - canvas.height *= dpr; - var ctx = canvas.getContext('2d'); - ctx.scale(dpr, dpr); - }, - - - genColorPreviewCanvas : function (color, separatorPos, specWidth, scaleForHighDPR) { - - var sepW = Math.round(jsc.pub.previewSeparator.length); - var sqSize = jsc.pub.chessboardSize; - var sqColor1 = jsc.pub.chessboardColor1; - var sqColor2 = jsc.pub.chessboardColor2; - - var cWidth = specWidth ? specWidth : sqSize * 2; - var cHeight = sqSize * 2; - - var canvas = jsc.createEl('canvas'); - var ctx = canvas.getContext('2d'); - - canvas.width = cWidth; - canvas.height = cHeight; - if (scaleForHighDPR) { - jsc.scaleCanvasForHighDPR(canvas); - } - - // transparency chessboard - background - ctx.fillStyle = sqColor1; - ctx.fillRect(0, 0, cWidth, cHeight); - - // transparency chessboard - squares - ctx.fillStyle = sqColor2; - for (var x = 0; x < cWidth; x += sqSize * 2) { - ctx.fillRect(x, 0, sqSize, sqSize); - ctx.fillRect(x + sqSize, sqSize, sqSize, sqSize); - } - - if (color) { - // actual color in foreground - ctx.fillStyle = color; - ctx.fillRect(0, 0, cWidth, cHeight); - } - - var start = null; - switch (separatorPos) { - case 'left': - start = 0; - ctx.clearRect(0, 0, sepW/2, cHeight); - break; - case 'right': - start = cWidth - sepW; - ctx.clearRect(cWidth - (sepW/2), 0, sepW/2, cHeight); - break; - } - if (start !== null) { - ctx.lineWidth = 1; - for (var i = 0; i < jsc.pub.previewSeparator.length; i += 1) { - ctx.beginPath(); - ctx.strokeStyle = jsc.pub.previewSeparator[i]; - ctx.moveTo(0.5 + start + i, 0); - ctx.lineTo(0.5 + start + i, cHeight); - ctx.stroke(); - } - } - - return { - canvas: canvas, - width: cWidth, - height: cHeight, - }; - }, - - - // if position or width is not set => fill the entire element (0%-100%) - genColorPreviewGradient : function (color, position, width) { - var params = []; - - if (position && width) { - params = [ - 'to ' + {'left':'right', 'right':'left'}[position], - color + ' 0%', - color + ' ' + width + 'px', - 'rgba(0,0,0,0) ' + (width + 1) + 'px', - 'rgba(0,0,0,0) 100%', - ]; - } else { - params = [ - 'to right', - color + ' 0%', - color + ' 100%', - ]; - } - - return jsc.linearGradient.apply(this, params); - }, - - - redrawPosition : function () { - - if (!jsc.picker || !jsc.picker.owner) { - return; // picker is not shown - } - - var thisObj = jsc.picker.owner; - - if (thisObj.container !== window.document.body) { - - jsc._drawPosition(thisObj, 0, 0, 'relative', false); - - } else { - - var tp, vp; - - if (thisObj.fixed) { - // Fixed elements are positioned relative to viewport, - // therefore we can ignore the scroll offset - tp = jsc.getElementPos(thisObj.targetElement, true); // target pos - vp = [0, 0]; // view pos - } else { - tp = jsc.getElementPos(thisObj.targetElement); // target pos - vp = jsc.getViewPos(); // view pos - } - - var ts = jsc.getElementSize(thisObj.targetElement); // target size - var vs = jsc.getViewSize(); // view size - var pd = jsc.getPickerDims(thisObj); - var ps = [pd.borderW, pd.borderH]; // picker outer size - var a, b, c; - switch (thisObj.position.toLowerCase()) { - case 'left': a=1; b=0; c=-1; break; - case 'right':a=1; b=0; c=1; break; - case 'top': a=0; b=1; c=-1; break; - default: a=0; b=1; c=1; break; - } - var l = (ts[b]+ps[b])/2; - - // compute picker position - if (!thisObj.smartPosition) { - var pp = [ - tp[a], - tp[b]+ts[b]-l+l*c - ]; - } else { - var pp = [ - -vp[a]+tp[a]+ps[a] > vs[a] ? - (-vp[a]+tp[a]+ts[a]/2 > vs[a]/2 && tp[a]+ts[a]-ps[a] >= 0 ? tp[a]+ts[a]-ps[a] : tp[a]) : - tp[a], - -vp[b]+tp[b]+ts[b]+ps[b]-l+l*c > vs[b] ? - (-vp[b]+tp[b]+ts[b]/2 > vs[b]/2 && tp[b]+ts[b]-l-l*c >= 0 ? tp[b]+ts[b]-l-l*c : tp[b]+ts[b]-l+l*c) : - (tp[b]+ts[b]-l+l*c >= 0 ? tp[b]+ts[b]-l+l*c : tp[b]+ts[b]-l-l*c) - ]; - } - - var x = pp[a]; - var y = pp[b]; - var positionValue = thisObj.fixed ? 'fixed' : 'absolute'; - var contractShadow = - (pp[0] + ps[0] > tp[0] || pp[0] < tp[0] + ts[0]) && - (pp[1] + ps[1] < tp[1] + ts[1]); - - jsc._drawPosition(thisObj, x, y, positionValue, contractShadow); - - } - - }, - - - _drawPosition : function (thisObj, x, y, positionValue, contractShadow) { - var vShadow = contractShadow ? 0 : thisObj.shadowBlur; // px - - jsc.picker.wrap.style.position = positionValue; - jsc.picker.wrap.style.left = x + 'px'; - jsc.picker.wrap.style.top = y + 'px'; - - jsc.setBoxShadow( - jsc.picker.boxS, - thisObj.shadow ? - new jsc.BoxShadow(0, vShadow, thisObj.shadowBlur, 0, thisObj.shadowColor) : - null); - }, - - - getPickerDims : function (thisObj) { - var w = 2 * thisObj.controlBorderWidth + thisObj.width; - var h = 2 * thisObj.controlBorderWidth + thisObj.height; - - var sliderSpace = 2 * thisObj.controlBorderWidth + 2 * jsc.getControlPadding(thisObj) + thisObj.sliderSize; - - if (jsc.getSliderChannel(thisObj)) { - w += sliderSpace; - } - if (thisObj.hasAlphaChannel()) { - w += sliderSpace; - } - - var pal = jsc.getPaletteDims(thisObj, w); - - if (pal.height) { - h += pal.height + thisObj.padding; - } - if (thisObj.closeButton) { - h += 2 * thisObj.controlBorderWidth + thisObj.padding + thisObj.buttonHeight; - } - - var pW = w + (2 * thisObj.padding); - var pH = h + (2 * thisObj.padding); - - return { - contentW: w, - contentH: h, - paddedW: pW, - paddedH: pH, - borderW: pW + (2 * thisObj.borderWidth), - borderH: pH + (2 * thisObj.borderWidth), - palette: pal, - }; - }, - - - getPaletteDims : function (thisObj, width) { - var cols = 0, rows = 0, cellW = 0, cellH = 0, height = 0; - var sampleCount = thisObj._palette ? thisObj._palette.length : 0; - - if (sampleCount) { - cols = thisObj.paletteCols; - rows = cols > 0 ? Math.ceil(sampleCount / cols) : 0; - - // color sample's dimensions (includes border) - cellW = Math.max(1, Math.floor((width - ((cols - 1) * thisObj.paletteSpacing)) / cols)); - cellH = thisObj.paletteHeight ? Math.min(thisObj.paletteHeight, cellW) : cellW; - } - - if (rows) { - height = - rows * cellH + - (rows - 1) * thisObj.paletteSpacing; - } - - return { - cols: cols, - rows: rows, - cellW: cellW, - cellH: cellH, - width: width, - height: height, - }; - }, - - - getControlPadding : function (thisObj) { - return Math.max( - thisObj.padding / 2, - (2 * thisObj.pointerBorderWidth + thisObj.pointerThickness) - thisObj.controlBorderWidth - ); - }, - - - getPadYChannel : function (thisObj) { - switch (thisObj.mode.charAt(1).toLowerCase()) { - case 'v': return 'v'; break; - } - return 's'; - }, - - - getSliderChannel : function (thisObj) { - if (thisObj.mode.length > 2) { - switch (thisObj.mode.charAt(2).toLowerCase()) { - case 's': return 's'; break; - case 'v': return 'v'; break; - } - } - return null; - }, - - - // calls function specified in picker's property - triggerCallback : function (thisObj, prop) { - if (!thisObj[prop]) { - return; // callback func not specified - } - var callback = null; - - if (typeof thisObj[prop] === 'string') { - // string with code - try { - callback = new Function (thisObj[prop]); - } catch (e) { - console.error(e); - } - } else { - // function - callback = thisObj[prop]; - } - - if (callback) { - callback.call(thisObj); - } - }, - - - // Triggers a color change related event(s) on all picker instances. - // It is possible to specify multiple events separated with a space. - triggerGlobal : function (eventNames) { - var inst = jsc.getInstances(); - for (var i = 0; i < inst.length; i += 1) { - inst[i].trigger(eventNames); - } - }, - - - _pointerMoveEvent : { - mouse: 'mousemove', - touch: 'touchmove' - }, - _pointerEndEvent : { - mouse: 'mouseup', - touch: 'touchend' - }, - - - _pointerOrigin : null, - - - onDocumentKeyUp : function (e) { - if (['Tab', 'Escape'].indexOf(jsc.eventKey(e)) !== -1) { - if (jsc.picker && jsc.picker.owner) { - jsc.picker.owner.tryHide(); - } - } - }, - - - onWindowResize : function (e) { - jsc.redrawPosition(); - }, - - - onWindowScroll : function (e) { - jsc.redrawPosition(); - }, - - - onParentScroll : function (e) { - // hide the picker when one of the parent elements is scrolled - if (jsc.picker && jsc.picker.owner) { - jsc.picker.owner.tryHide(); - } - }, - - - onDocumentMouseDown : function (e) { - var target = e.target || e.srcElement; - - if (target.jscolor && target.jscolor instanceof jsc.pub) { // clicked targetElement -> show picker - if (target.jscolor.showOnClick && !target.disabled) { - target.jscolor.show(); - } - } else if (jsc.getData(target, 'gui')) { // clicked jscolor's GUI element - var control = jsc.getData(target, 'control'); - if (control) { - // jscolor's control - jsc.onControlPointerStart(e, target, jsc.getData(target, 'control'), 'mouse'); - } - } else { - // mouse is outside the picker's controls -> hide the color picker! - if (jsc.picker && jsc.picker.owner) { - jsc.picker.owner.tryHide(); - } - } - }, - - - onPickerTouchStart : function (e) { - var target = e.target || e.srcElement; - - if (jsc.getData(target, 'control')) { - jsc.onControlPointerStart(e, target, jsc.getData(target, 'control'), 'touch'); - } - }, - - - onControlPointerStart : function (e, target, controlName, pointerType) { - var thisObj = jsc.getData(target, 'instance'); - - jsc.preventDefault(e); - - var registerDragEvents = function (doc, offset) { - jsc.attachGroupEvent('drag', doc, jsc._pointerMoveEvent[pointerType], - jsc.onDocumentPointerMove(e, target, controlName, pointerType, offset)); - jsc.attachGroupEvent('drag', doc, jsc._pointerEndEvent[pointerType], - jsc.onDocumentPointerEnd(e, target, controlName, pointerType)); - }; - - registerDragEvents(window.document, [0, 0]); - - if (window.parent && window.frameElement) { - var rect = window.frameElement.getBoundingClientRect(); - var ofs = [-rect.left, -rect.top]; - registerDragEvents(window.parent.window.document, ofs); - } - - var abs = jsc.getAbsPointerPos(e); - var rel = jsc.getRelPointerPos(e); - jsc._pointerOrigin = { - x: abs.x - rel.x, - y: abs.y - rel.y - }; - - switch (controlName) { - case 'pad': - // if the value slider is at the bottom, move it up - if (jsc.getSliderChannel(thisObj) === 'v' && thisObj.channels.v === 0) { - thisObj.fromHSVA(null, null, 100, null); - } - jsc.setPad(thisObj, e, 0, 0); - break; - - case 'sld': - jsc.setSld(thisObj, e, 0); - break; - - case 'asld': - jsc.setASld(thisObj, e, 0); - break; - } - thisObj.trigger('input'); - }, - - - onDocumentPointerMove : function (e, target, controlName, pointerType, offset) { - return function (e) { - var thisObj = jsc.getData(target, 'instance'); - switch (controlName) { - case 'pad': - jsc.setPad(thisObj, e, offset[0], offset[1]); - break; - - case 'sld': - jsc.setSld(thisObj, e, offset[1]); - break; - - case 'asld': - jsc.setASld(thisObj, e, offset[1]); - break; - } - thisObj.trigger('input'); - } - }, - - - onDocumentPointerEnd : function (e, target, controlName, pointerType) { - return function (e) { - var thisObj = jsc.getData(target, 'instance'); - jsc.detachGroupEvents('drag'); - - // Always trigger changes AFTER detaching outstanding mouse handlers, - // in case some color change that occured in user-defined onChange/onInput handler - // intruded into current mouse events - thisObj.trigger('input'); - thisObj.trigger('change'); - }; - }, - - - onPaletteSampleClick : function (e) { - var target = e.currentTarget; - var thisObj = jsc.getData(target, 'instance'); - var color = jsc.getData(target, 'color'); - - // when format is flexible, use the original format of this color sample - if (thisObj.format.toLowerCase() === 'any') { - thisObj._setFormat(color.format); // adapt format - if (!jsc.isAlphaFormat(thisObj.getFormat())) { - color.rgba[3] = 1.0; // when switching to a format that doesn't support alpha, set full opacity - } - } - - // if this color doesn't specify alpha, use alpha of 1.0 (if applicable) - if (color.rgba[3] === null) { - if (thisObj.paletteSetsAlpha === true || (thisObj.paletteSetsAlpha === 'auto' && thisObj._paletteHasTransparency)) { - color.rgba[3] = 1.0; - } - } - - thisObj.fromRGBA.apply(thisObj, color.rgba); - - thisObj.trigger('input'); - thisObj.trigger('change'); - - if (thisObj.hideOnPaletteClick) { - thisObj.hide(); - } - }, - - - setPad : function (thisObj, e, ofsX, ofsY) { - var pointerAbs = jsc.getAbsPointerPos(e); - var x = ofsX + pointerAbs.x - jsc._pointerOrigin.x - thisObj.padding - thisObj.controlBorderWidth; - var y = ofsY + pointerAbs.y - jsc._pointerOrigin.y - thisObj.padding - thisObj.controlBorderWidth; - - var xVal = x * (360 / (thisObj.width - 1)); - var yVal = 100 - (y * (100 / (thisObj.height - 1))); - - switch (jsc.getPadYChannel(thisObj)) { - case 's': thisObj.fromHSVA(xVal, yVal, null, null); break; - case 'v': thisObj.fromHSVA(xVal, null, yVal, null); break; - } - }, - - - setSld : function (thisObj, e, ofsY) { - var pointerAbs = jsc.getAbsPointerPos(e); - var y = ofsY + pointerAbs.y - jsc._pointerOrigin.y - thisObj.padding - thisObj.controlBorderWidth; - var yVal = 100 - (y * (100 / (thisObj.height - 1))); - - switch (jsc.getSliderChannel(thisObj)) { - case 's': thisObj.fromHSVA(null, yVal, null, null); break; - case 'v': thisObj.fromHSVA(null, null, yVal, null); break; - } - }, - - - setASld : function (thisObj, e, ofsY) { - var pointerAbs = jsc.getAbsPointerPos(e); - var y = ofsY + pointerAbs.y - jsc._pointerOrigin.y - thisObj.padding - thisObj.controlBorderWidth; - var yVal = 1.0 - (y * (1.0 / (thisObj.height - 1))); - - if (yVal < 1.0) { - // if format is flexible and the current format doesn't support alpha, switch to a suitable one - var fmt = thisObj.getFormat(); - if (thisObj.format.toLowerCase() === 'any' && !jsc.isAlphaFormat(fmt)) { - thisObj._setFormat(fmt === 'hex' ? 'hexa' : 'rgba'); - } - } - - thisObj.fromHSVA(null, null, null, yVal); - }, - - - createPadCanvas : function () { - - var ret = { - elm: null, - draw: null - }; - - var canvas = jsc.createEl('canvas'); - var ctx = canvas.getContext('2d'); - - var drawFunc = function (width, height, type) { - canvas.width = width; - canvas.height = height; - - ctx.clearRect(0, 0, canvas.width, canvas.height); - - var hGrad = ctx.createLinearGradient(0, 0, canvas.width, 0); - hGrad.addColorStop(0 / 6, '#F00'); - hGrad.addColorStop(1 / 6, '#FF0'); - hGrad.addColorStop(2 / 6, '#0F0'); - hGrad.addColorStop(3 / 6, '#0FF'); - hGrad.addColorStop(4 / 6, '#00F'); - hGrad.addColorStop(5 / 6, '#F0F'); - hGrad.addColorStop(6 / 6, '#F00'); - - ctx.fillStyle = hGrad; - ctx.fillRect(0, 0, canvas.width, canvas.height); - - var vGrad = ctx.createLinearGradient(0, 0, 0, canvas.height); - switch (type.toLowerCase()) { - case 's': - vGrad.addColorStop(0, 'rgba(255,255,255,0)'); - vGrad.addColorStop(1, 'rgba(255,255,255,1)'); - break; - case 'v': - vGrad.addColorStop(0, 'rgba(0,0,0,0)'); - vGrad.addColorStop(1, 'rgba(0,0,0,1)'); - break; - } - ctx.fillStyle = vGrad; - ctx.fillRect(0, 0, canvas.width, canvas.height); - }; - - ret.elm = canvas; - ret.draw = drawFunc; - - return ret; - }, - - - createSliderGradient : function () { - - var ret = { - elm: null, - draw: null - }; - - var canvas = jsc.createEl('canvas'); - var ctx = canvas.getContext('2d'); - - var drawFunc = function (width, height, color1, color2) { - canvas.width = width; - canvas.height = height; - - ctx.clearRect(0, 0, canvas.width, canvas.height); - - var grad = ctx.createLinearGradient(0, 0, 0, canvas.height); - grad.addColorStop(0, color1); - grad.addColorStop(1, color2); - - ctx.fillStyle = grad; - ctx.fillRect(0, 0, canvas.width, canvas.height); - }; - - ret.elm = canvas; - ret.draw = drawFunc; - - return ret; - }, - - - createASliderGradient : function () { - - var ret = { - elm: null, - draw: null - }; - - var canvas = jsc.createEl('canvas'); - var ctx = canvas.getContext('2d'); - - var drawFunc = function (width, height, color) { - canvas.width = width; - canvas.height = height; - - ctx.clearRect(0, 0, canvas.width, canvas.height); - - var sqSize = canvas.width / 2; - var sqColor1 = jsc.pub.chessboardColor1; - var sqColor2 = jsc.pub.chessboardColor2; - - // dark gray background - ctx.fillStyle = sqColor1; - ctx.fillRect(0, 0, canvas.width, canvas.height); - - if (sqSize > 0) { // to avoid infinite loop - for (var y = 0; y < canvas.height; y += sqSize * 2) { - // light gray squares - ctx.fillStyle = sqColor2; - ctx.fillRect(0, y, sqSize, sqSize); - ctx.fillRect(sqSize, y + sqSize, sqSize, sqSize); - } - } - - var grad = ctx.createLinearGradient(0, 0, 0, canvas.height); - grad.addColorStop(0, color); - grad.addColorStop(1, 'rgba(0,0,0,0)'); - - ctx.fillStyle = grad; - ctx.fillRect(0, 0, canvas.width, canvas.height); - }; - - ret.elm = canvas; - ret.draw = drawFunc; - - return ret; - }, - - - BoxShadow : (function () { - var BoxShadow = function (hShadow, vShadow, blur, spread, color, inset) { - this.hShadow = hShadow; - this.vShadow = vShadow; - this.blur = blur; - this.spread = spread; - this.color = color; - this.inset = !!inset; - }; - - BoxShadow.prototype.toString = function () { - var vals = [ - Math.round(this.hShadow) + 'px', - Math.round(this.vShadow) + 'px', - Math.round(this.blur) + 'px', - Math.round(this.spread) + 'px', - this.color - ]; - if (this.inset) { - vals.push('inset'); - } - return vals.join(' '); - }; - - return BoxShadow; - })(), - - - flags : { - leaveValue : 1 << 0, - leaveAlpha : 1 << 1, - leavePreview : 1 << 2, - }, - - - enumOpts : { - format: ['auto', 'any', 'hex', 'hexa', 'rgb', 'rgba'], - previewPosition: ['left', 'right'], - mode: ['hsv', 'hvs', 'hs', 'hv'], - position: ['left', 'right', 'top', 'bottom'], - alphaChannel: ['auto', true, false], - paletteSetsAlpha: ['auto', true, false], - }, - - - deprecatedOpts : { - // : ( can be null) - 'styleElement': 'previewElement', - 'onFineChange': 'onInput', - 'overwriteImportant': 'forceStyle', - 'closable': 'closeButton', - 'insetWidth': 'controlBorderWidth', - 'insetColor': 'controlBorderColor', - 'refine': null, - }, - - - docsRef : ' ' + 'See https://jscolor.com/docs/', - - - // - // Usage: - // var myPicker = new JSColor( [, ]) - // - // (constructor is accessible via both 'jscolor' and 'JSColor' name) - // - - pub : function (targetElement, opts) { - - var THIS = this; - - if (!opts) { - opts = {}; - } - - this.channels = { - r: 255, // red [0-255] - g: 255, // green [0-255] - b: 255, // blue [0-255] - h: 0, // hue [0-360] - s: 0, // saturation [0-100] - v: 100, // value (brightness) [0-100] - a: 1.0, // alpha (opacity) [0.0 - 1.0] - }; - - // General options - // - this.format = 'auto'; // 'auto' | 'any' | 'hex' | 'hexa' | 'rgb' | 'rgba' - Format of the input/output value - this.value = undefined; // INITIAL color value in any supported format. To change it later, use method fromString(), fromHSVA(), fromRGBA() or channel() - this.alpha = undefined; // INITIAL alpha value. To change it later, call method channel('A', ) - this.random = false; // whether to randomize the initial color. Either true | false, or an array of ranges: [minV, maxV, minS, maxS, minH, maxH, minA, maxA] - this.onChange = undefined; // called when color changes. Value can be either a function or a string with JS code. - this.onInput = undefined; // called repeatedly as the color is being changed, e.g. while dragging a slider. Value can be either a function or a string with JS code. - this.valueElement = undefined; // element that will be used to display and input the color value - this.alphaElement = undefined; // element that will be used to display and input the alpha (opacity) value - this.previewElement = undefined; // element that will preview the picked color using CSS background - this.previewPosition = 'left'; // 'left' | 'right' - position of the color preview in previewElement - this.previewSize = 32; // (px) width of the color preview displayed in previewElement - this.previewPadding = 8; // (px) space between color preview and content of the previewElement - this.required = true; // whether the associated text input must always contain a color value. If false, the input can be left empty. - this.hash = true; // whether to prefix the HEX color code with # symbol (only applicable for HEX format) - this.uppercase = true; // whether to show the HEX color code in upper case (only applicable for HEX format) - this.forceStyle = true; // whether to overwrite CSS style of the previewElement using !important flag - - // Color Picker options - // - this.width = 181; // width of the color spectrum (in px) - this.height = 101; // height of the color spectrum (in px) - this.mode = 'HSV'; // 'HSV' | 'HVS' | 'HS' | 'HV' - layout of the color picker controls - this.alphaChannel = 'auto'; // 'auto' | true | false - if alpha channel is enabled, the alpha slider will be visible. If 'auto', it will be determined according to color format - this.position = 'bottom'; // 'left' | 'right' | 'top' | 'bottom' - position relative to the target element - this.smartPosition = true; // automatically change picker position when there is not enough space for it - this.showOnClick = true; // whether to show the picker when user clicks its target element - this.hideOnLeave = true; // whether to automatically hide the picker when user leaves its target element (e.g. upon clicking the document) - this.palette = []; // colors to be displayed in the palette, specified as an array or a string of space separated color values (in any supported format) - this.paletteCols = 10; // number of columns in the palette - this.paletteSetsAlpha = 'auto'; // 'auto' | true | false - if true, palette colors that don't specify alpha will set alpha to 1.0 - this.paletteHeight = 16; // maximum height (px) of a row in the palette - this.paletteSpacing = 4; // distance (px) between color samples in the palette - this.hideOnPaletteClick = false; // when set to true, clicking the palette will also hide the color picker - this.sliderSize = 16; // px - this.crossSize = 8; // px - this.closeButton = false; // whether to display the Close button - this.closeText = 'Close'; - this.buttonColor = 'rgba(0,0,0,1)'; // CSS color - this.buttonHeight = 18; // px - this.padding = 12; // px - this.backgroundColor = 'rgba(255,255,255,1)'; // CSS color - this.borderWidth = 1; // px - this.borderColor = 'rgba(187,187,187,1)'; // CSS color - this.borderRadius = 8; // px - this.controlBorderWidth = 1; // px - this.controlBorderColor = 'rgba(187,187,187,1)'; // CSS color - this.shadow = true; // whether to display a shadow - this.shadowBlur = 15; // px - this.shadowColor = 'rgba(0,0,0,0.2)'; // CSS color - this.pointerColor = 'rgba(76,76,76,1)'; // CSS color - this.pointerBorderWidth = 1; // px - this.pointerBorderColor = 'rgba(255,255,255,1)'; // CSS color - this.pointerThickness = 2; // px - this.zIndex = 5000; - this.container = undefined; // where to append the color picker (BODY element by default) - - // Experimental - // - this.minS = 0; // min allowed saturation (0 - 100) - this.maxS = 100; // max allowed saturation (0 - 100) - this.minV = 0; // min allowed value (brightness) (0 - 100) - this.maxV = 100; // max allowed value (brightness) (0 - 100) - this.minA = 0.0; // min allowed alpha (opacity) (0.0 - 1.0) - this.maxA = 1.0; // max allowed alpha (opacity) (0.0 - 1.0) - - - // Getter: option(name) - // Setter: option(name, value) - // option({name:value, ...}) - // - this.option = function () { - if (!arguments.length) { - throw new Error('No option specified'); - } - - if (arguments.length === 1 && typeof arguments[0] === 'string') { - // getting a single option - try { - return getOption(arguments[0]); - } catch (e) { - console.warn(e); - } - return false; - - } else if (arguments.length >= 2 && typeof arguments[0] === 'string') { - // setting a single option - try { - if (!setOption(arguments[0], arguments[1])) { - return false; - } - } catch (e) { - console.warn(e); - return false; - } - this.redraw(); // immediately redraws the picker, if it's displayed - this.exposeColor(); // in case some preview-related or format-related option was changed - return true; - - } else if (arguments.length === 1 && typeof arguments[0] === 'object') { - // setting multiple options - var opts = arguments[0]; - var success = true; - for (var opt in opts) { - if (opts.hasOwnProperty(opt)) { - try { - if (!setOption(opt, opts[opt])) { - success = false; - } - } catch (e) { - console.warn(e); - success = false; - } - } - } - this.redraw(); // immediately redraws the picker, if it's displayed - this.exposeColor(); // in case some preview-related or format-related option was changed - return success; - } - - throw new Error('Invalid arguments'); - } - - - // Getter: channel(name) - // Setter: channel(name, value) - // - this.channel = function (name, value) { - if (typeof name !== 'string') { - throw new Error('Invalid value for channel name: ' + name); - } - - if (value === undefined) { - // getting channel value - if (!this.channels.hasOwnProperty(name.toLowerCase())) { - console.warn('Getting unknown channel: ' + name); - return false; - } - return this.channels[name.toLowerCase()]; - - } else { - // setting channel value - var res = false; - switch (name.toLowerCase()) { - case 'r': res = this.fromRGBA(value, null, null, null); break; - case 'g': res = this.fromRGBA(null, value, null, null); break; - case 'b': res = this.fromRGBA(null, null, value, null); break; - case 'h': res = this.fromHSVA(value, null, null, null); break; - case 's': res = this.fromHSVA(null, value, null, null); break; - case 'v': res = this.fromHSVA(null, null, value, null); break; - case 'a': res = this.fromHSVA(null, null, null, value); break; - default: - console.warn('Setting unknown channel: ' + name); - return false; - } - if (res) { - this.redraw(); // immediately redraws the picker, if it's displayed - return true; - } - } - - return false; - } - - - // Triggers given input event(s) by: - // - executing on callback specified as picker's option - // - triggering standard DOM event listeners attached to the value element - // - // It is possible to specify multiple events separated with a space. - // - this.trigger = function (eventNames) { - var evs = jsc.strList(eventNames); - for (var i = 0; i < evs.length; i += 1) { - var ev = evs[i].toLowerCase(); - - // trigger a callback - var callbackProp = null; - switch (ev) { - case 'input': callbackProp = 'onInput'; break; - case 'change': callbackProp = 'onChange'; break; - } - if (callbackProp) { - jsc.triggerCallback(this, callbackProp); - } - - // trigger standard DOM event listeners on the value element - jsc.triggerInputEvent(this.valueElement, ev, true, true); - } - }; - - - // h: 0-360 - // s: 0-100 - // v: 0-100 - // a: 0.0-1.0 - // - this.fromHSVA = function (h, s, v, a, flags) { // null = don't change - if (h === undefined) { h = null; } - if (s === undefined) { s = null; } - if (v === undefined) { v = null; } - if (a === undefined) { a = null; } - - if (h !== null) { - if (isNaN(h)) { return false; } - this.channels.h = Math.max(0, Math.min(360, h)); - } - if (s !== null) { - if (isNaN(s)) { return false; } - this.channels.s = Math.max(0, Math.min(100, this.maxS, s), this.minS); - } - if (v !== null) { - if (isNaN(v)) { return false; } - this.channels.v = Math.max(0, Math.min(100, this.maxV, v), this.minV); - } - if (a !== null) { - if (isNaN(a)) { return false; } - this.channels.a = this.hasAlphaChannel() ? - Math.max(0, Math.min(1, this.maxA, a), this.minA) : - 1.0; // if alpha channel is disabled, the color should stay 100% opaque - } - - var rgb = jsc.HSV_RGB( - this.channels.h, - this.channels.s, - this.channels.v - ); - this.channels.r = rgb[0]; - this.channels.g = rgb[1]; - this.channels.b = rgb[2]; - - this.exposeColor(flags); - return true; - }; - - - // r: 0-255 - // g: 0-255 - // b: 0-255 - // a: 0.0-1.0 - // - this.fromRGBA = function (r, g, b, a, flags) { // null = don't change - if (r === undefined) { r = null; } - if (g === undefined) { g = null; } - if (b === undefined) { b = null; } - if (a === undefined) { a = null; } - - if (r !== null) { - if (isNaN(r)) { return false; } - r = Math.max(0, Math.min(255, r)); - } - if (g !== null) { - if (isNaN(g)) { return false; } - g = Math.max(0, Math.min(255, g)); - } - if (b !== null) { - if (isNaN(b)) { return false; } - b = Math.max(0, Math.min(255, b)); - } - if (a !== null) { - if (isNaN(a)) { return false; } - this.channels.a = this.hasAlphaChannel() ? - Math.max(0, Math.min(1, this.maxA, a), this.minA) : - 1.0; // if alpha channel is disabled, the color should stay 100% opaque - } - - var hsv = jsc.RGB_HSV( - r===null ? this.channels.r : r, - g===null ? this.channels.g : g, - b===null ? this.channels.b : b - ); - if (hsv[0] !== null) { - this.channels.h = Math.max(0, Math.min(360, hsv[0])); - } - if (hsv[2] !== 0) { // fully black color stays black through entire saturation range, so let's not change saturation - this.channels.s = Math.max(0, this.minS, Math.min(100, this.maxS, hsv[1])); - } - this.channels.v = Math.max(0, this.minV, Math.min(100, this.maxV, hsv[2])); - - // update RGB according to final HSV, as some values might be trimmed - var rgb = jsc.HSV_RGB(this.channels.h, this.channels.s, this.channels.v); - this.channels.r = rgb[0]; - this.channels.g = rgb[1]; - this.channels.b = rgb[2]; - - this.exposeColor(flags); - return true; - }; - - - // DEPRECATED. Use .fromHSVA() instead - // - this.fromHSV = function (h, s, v, flags) { - console.warn('fromHSV() method is DEPRECATED. Using fromHSVA() instead.' + jsc.docsRef); - return this.fromHSVA(h, s, v, null, flags); - }; - - - // DEPRECATED. Use .fromRGBA() instead - // - this.fromRGB = function (r, g, b, flags) { - console.warn('fromRGB() method is DEPRECATED. Using fromRGBA() instead.' + jsc.docsRef); - return this.fromRGBA(r, g, b, null, flags); - }; - - - this.fromString = function (str, flags) { - if (!this.required && str.trim() === '') { - // setting empty string to an optional color input - this.setPreviewElementBg(null); - this.setValueElementValue(''); - return true; - } - - var color = jsc.parseColorString(str); - if (!color) { - return false; // could not parse - } - if (this.format.toLowerCase() === 'any') { - this._setFormat(color.format); // adapt format - if (!jsc.isAlphaFormat(this.getFormat())) { - color.rgba[3] = 1.0; // when switching to a format that doesn't support alpha, set full opacity - } - } - this.fromRGBA( - color.rgba[0], - color.rgba[1], - color.rgba[2], - color.rgba[3], - flags - ); - return true; - }; - - - this.randomize = function (minV, maxV, minS, maxS, minH, maxH, minA, maxA) { - if (minV === undefined) { minV = 0; } - if (maxV === undefined) { maxV = 100; } - if (minS === undefined) { minS = 0; } - if (maxS === undefined) { maxS = 100; } - if (minH === undefined) { minH = 0; } - if (maxH === undefined) { maxH = 359; } - if (minA === undefined) { minA = 1; } - if (maxA === undefined) { maxA = 1; } - - this.fromHSVA( - minH + Math.floor(Math.random() * (maxH - minH + 1)), - minS + Math.floor(Math.random() * (maxS - minS + 1)), - minV + Math.floor(Math.random() * (maxV - minV + 1)), - ((100 * minA) + Math.floor(Math.random() * (100 * (maxA - minA) + 1))) / 100 - ); - }; - - - this.toString = function (format) { - if (format === undefined) { - format = this.getFormat(); // format not specified -> use the current format - } - switch (format.toLowerCase()) { - case 'hex': return this.toHEXString(); break; - case 'hexa': return this.toHEXAString(); break; - case 'rgb': return this.toRGBString(); break; - case 'rgba': return this.toRGBAString(); break; - } - return false; - }; - - - this.toHEXString = function () { - return jsc.hexColor( - this.channels.r, - this.channels.g, - this.channels.b - ); - }; - - - this.toHEXAString = function () { - return jsc.hexaColor( - this.channels.r, - this.channels.g, - this.channels.b, - this.channels.a - ); - }; - - - this.toRGBString = function () { - return jsc.rgbColor( - this.channels.r, - this.channels.g, - this.channels.b - ); - }; - - - this.toRGBAString = function () { - return jsc.rgbaColor( - this.channels.r, - this.channels.g, - this.channels.b, - this.channels.a - ); - }; - - - this.toGrayscale = function () { - return ( - 0.213 * this.channels.r + - 0.715 * this.channels.g + - 0.072 * this.channels.b - ); - }; - - - this.toCanvas = function () { - return jsc.genColorPreviewCanvas(this.toRGBAString()).canvas; - }; - - - this.toDataURL = function () { - return this.toCanvas().toDataURL(); - }; - - - this.toBackground = function () { - return jsc.pub.background(this.toRGBAString()); - }; - - - this.isLight = function () { - return this.toGrayscale() > 255 / 2; - }; - - - this.hide = function () { - if (isPickerOwner()) { - detachPicker(); - } - }; - - - this.show = function () { - drawPicker(); - }; - - - this.redraw = function () { - if (isPickerOwner()) { - drawPicker(); - } - }; - - - this.getFormat = function () { - return this._currentFormat; - }; - - - this._setFormat = function (format) { - this._currentFormat = format.toLowerCase(); - }; - - - this.hasAlphaChannel = function () { - if (this.alphaChannel === 'auto') { - return ( - this.format.toLowerCase() === 'any' || // format can change on the fly (e.g. from hex to rgba), so let's consider the alpha channel enabled - jsc.isAlphaFormat(this.getFormat()) || // the current format supports alpha channel - this.alpha !== undefined || // initial alpha value is set, so we're working with alpha channel - this.alphaElement !== undefined // the alpha value is redirected, so we're working with alpha channel - ); - } - - return this.alphaChannel; // the alpha channel is explicitly set - }; - - - this.processValueInput = function (str) { - if (!this.fromString(str)) { - // could not parse the color value - let's just expose the current color - this.exposeColor(); - } - }; - - - this.processAlphaInput = function (str) { - if (!this.fromHSVA(null, null, null, parseFloat(str))) { - // could not parse the alpha value - let's just expose the current color - this.exposeColor(); - } - }; - - - this.exposeColor = function (flags) { - var colorStr = this.toString(); - var fmt = this.getFormat(); - - // reflect current color in data- attribute - jsc.setDataAttr(this.targetElement, 'current-color', colorStr); - - if (!(flags & jsc.flags.leaveValue) && this.valueElement) { - if (fmt === 'hex' || fmt === 'hexa') { - if (!this.uppercase) { colorStr = colorStr.toLowerCase(); } - if (!this.hash) { colorStr = colorStr.replace(/^#/, ''); } - } - this.setValueElementValue(colorStr); - } - - if (!(flags & jsc.flags.leaveAlpha) && this.alphaElement) { - var alphaVal = Math.round(this.channels.a * 100) / 100; - this.setAlphaElementValue(alphaVal); - } - - if (!(flags & jsc.flags.leavePreview) && this.previewElement) { - var previewPos = null; // 'left' | 'right' (null -> fill the entire element) - - if ( - jsc.isTextInput(this.previewElement) || // text input - (jsc.isButton(this.previewElement) && !jsc.isButtonEmpty(this.previewElement)) // button with text - ) { - previewPos = this.previewPosition; - } - - this.setPreviewElementBg(this.toRGBAString()); - } - - if (isPickerOwner()) { - redrawPad(); - redrawSld(); - redrawASld(); - } - }; - - - this.setPreviewElementBg = function (color) { - if (!this.previewElement) { - return; - } - - var position = null; // color preview position: null | 'left' | 'right' - var width = null; // color preview width: px | null = fill the entire element - if ( - jsc.isTextInput(this.previewElement) || // text input - (jsc.isButton(this.previewElement) && !jsc.isButtonEmpty(this.previewElement)) // button with text - ) { - position = this.previewPosition; - width = this.previewSize; - } - - var backgrounds = []; - - if (!color) { - // there is no color preview to display -> let's remove any previous background image - backgrounds.push({ - image: 'none', - position: 'left top', - size: 'auto', - repeat: 'no-repeat', - origin: 'padding-box', - }); - } else { - // CSS gradient for background color preview - backgrounds.push({ - image: jsc.genColorPreviewGradient( - color, - position, - width ? width - jsc.pub.previewSeparator.length : null - ), - position: 'left top', - size: 'auto', - repeat: position ? 'repeat-y' : 'repeat', - origin: 'padding-box', - }); - - // data URL of generated PNG image with a gray transparency chessboard - var preview = jsc.genColorPreviewCanvas( - 'rgba(0,0,0,0)', - position ? {'left':'right', 'right':'left'}[position] : null, - width, - true - ); - backgrounds.push({ - image: 'url(\'' + preview.canvas.toDataURL() + '\')', - position: (position || 'left') + ' top', - size: preview.width + 'px ' + preview.height + 'px', - repeat: position ? 'repeat-y' : 'repeat', - origin: 'padding-box', - }); - } - - var bg = { - image: [], - position: [], - size: [], - repeat: [], - origin: [], - }; - for (var i = 0; i < backgrounds.length; i += 1) { - bg.image.push(backgrounds[i].image); - bg.position.push(backgrounds[i].position); - bg.size.push(backgrounds[i].size); - bg.repeat.push(backgrounds[i].repeat); - bg.origin.push(backgrounds[i].origin); - } - - // set previewElement's background-images - var sty = { - 'background-image': bg.image.join(', '), - 'background-position': bg.position.join(', '), - 'background-size': bg.size.join(', '), - 'background-repeat': bg.repeat.join(', '), - 'background-origin': bg.origin.join(', '), - }; - jsc.setStyle(this.previewElement, sty, this.forceStyle); - - - // set/restore previewElement's padding - var padding = { - left: null, - right: null, - }; - if (position) { - padding[position] = (this.previewSize + this.previewPadding) + 'px'; - } - - var sty = { - 'padding-left': padding.left, - 'padding-right': padding.right, - }; - jsc.setStyle(this.previewElement, sty, this.forceStyle, true); - }; - - - this.setValueElementValue = function (str) { - if (this.valueElement) { - if (jsc.nodeName(this.valueElement) === 'input') { - this.valueElement.value = str; - } else { - this.valueElement.innerHTML = str; - } - } - }; - - - this.setAlphaElementValue = function (str) { - if (this.alphaElement) { - if (jsc.nodeName(this.alphaElement) === 'input') { - this.alphaElement.value = str; - } else { - this.alphaElement.innerHTML = str; - } - } - }; - - - this._processParentElementsInDOM = function () { - if (this._parentElementsProcessed) { return; } - this._parentElementsProcessed = true; - - var elm = this.targetElement; - do { - // If the target element or one of its parent nodes has fixed position, - // then use fixed positioning instead - var compStyle = jsc.getCompStyle(elm); - if (compStyle.position && compStyle.position.toLowerCase() === 'fixed') { - this.fixed = true; - } - - if (elm !== this.targetElement) { - // Ensure to attach onParentScroll only once to each parent element - // (multiple targetElements can share the same parent nodes) - // - // Note: It's not just offsetParents that can be scrollable, - // that's why we loop through all parent nodes - if (!jsc.getData(elm, 'hasScrollListener')) { - elm.addEventListener('scroll', jsc.onParentScroll, false); - jsc.setData(elm, 'hasScrollListener', true); - } - } - } while ((elm = elm.parentNode) && jsc.nodeName(elm) !== 'body'); - }; - - - this.tryHide = function () { - if (this.hideOnLeave) { - this.hide(); - } - }; - - - this.set__palette = function (val) { - this.palette = val; - this._palette = jsc.parsePaletteValue(val); - this._paletteHasTransparency = jsc.containsTranparentColor(this._palette); - }; - - - function setOption (option, value) { - if (typeof option !== 'string') { - throw new Error('Invalid value for option name: ' + option); - } - - // enum option - if (jsc.enumOpts.hasOwnProperty(option)) { - if (typeof value === 'string') { // enum string values are case insensitive - value = value.toLowerCase(); - } - if (jsc.enumOpts[option].indexOf(value) === -1) { - throw new Error('Option \'' + option + '\' has invalid value: ' + value); - } - } - - // deprecated option - if (jsc.deprecatedOpts.hasOwnProperty(option)) { - var oldOpt = option; - var newOpt = jsc.deprecatedOpts[option]; - if (newOpt) { - // if we have a new name for this option, let's log a warning and use the new name - console.warn('Option \'%s\' is DEPRECATED, using \'%s\' instead.' + jsc.docsRef, oldOpt, newOpt); - option = newOpt; - } else { - // new name not available for the option - throw new Error('Option \'' + option + '\' is DEPRECATED'); - } - } - - var setter = 'set__' + option; - - if (typeof THIS[setter] === 'function') { // a setter exists for this option - THIS[setter](value); - return true; - - } else if (option in THIS) { // option exists as a property - THIS[option] = value; - return true; - } - - throw new Error('Unrecognized configuration option: ' + option); - } - - - function getOption (option) { - if (typeof option !== 'string') { - throw new Error('Invalid value for option name: ' + option); - } - - // deprecated option - if (jsc.deprecatedOpts.hasOwnProperty(option)) { - var oldOpt = option; - var newOpt = jsc.deprecatedOpts[option]; - if (newOpt) { - // if we have a new name for this option, let's log a warning and use the new name - console.warn('Option \'%s\' is DEPRECATED, using \'%s\' instead.' + jsc.docsRef, oldOpt, newOpt); - option = newOpt; - } else { - // new name not available for the option - throw new Error('Option \'' + option + '\' is DEPRECATED'); - } - } - - var getter = 'get__' + option; - - if (typeof THIS[getter] === 'function') { // a getter exists for this option - return THIS[getter](value); - - } else if (option in THIS) { // option exists as a property - return THIS[option]; - } - - throw new Error('Unrecognized configuration option: ' + option); - } - - - function detachPicker () { - jsc.removeClass(THIS.targetElement, jsc.pub.activeClassName); - jsc.picker.wrap.parentNode.removeChild(jsc.picker.wrap); - delete jsc.picker.owner; - } - - - function drawPicker () { - - // At this point, when drawing the picker, we know what the parent elements are - // and we can do all related DOM operations, such as registering events on them - // or checking their positioning - THIS._processParentElementsInDOM(); - - if (!jsc.picker) { - jsc.picker = { - owner: null, // owner picker instance - wrap : jsc.createEl('div'), - box : jsc.createEl('div'), - boxS : jsc.createEl('div'), // shadow area - boxB : jsc.createEl('div'), // border - pad : jsc.createEl('div'), - padB : jsc.createEl('div'), // border - padM : jsc.createEl('div'), // mouse/touch area - padCanvas : jsc.createPadCanvas(), - cross : jsc.createEl('div'), - crossBY : jsc.createEl('div'), // border Y - crossBX : jsc.createEl('div'), // border X - crossLY : jsc.createEl('div'), // line Y - crossLX : jsc.createEl('div'), // line X - sld : jsc.createEl('div'), // slider - sldB : jsc.createEl('div'), // border - sldM : jsc.createEl('div'), // mouse/touch area - sldGrad : jsc.createSliderGradient(), - sldPtrS : jsc.createEl('div'), // slider pointer spacer - sldPtrIB : jsc.createEl('div'), // slider pointer inner border - sldPtrMB : jsc.createEl('div'), // slider pointer middle border - sldPtrOB : jsc.createEl('div'), // slider pointer outer border - asld : jsc.createEl('div'), // alpha slider - asldB : jsc.createEl('div'), // border - asldM : jsc.createEl('div'), // mouse/touch area - asldGrad : jsc.createASliderGradient(), - asldPtrS : jsc.createEl('div'), // slider pointer spacer - asldPtrIB : jsc.createEl('div'), // slider pointer inner border - asldPtrMB : jsc.createEl('div'), // slider pointer middle border - asldPtrOB : jsc.createEl('div'), // slider pointer outer border - pal : jsc.createEl('div'), // palette - btn : jsc.createEl('div'), - btnT : jsc.createEl('span'), // text - }; - - jsc.picker.pad.appendChild(jsc.picker.padCanvas.elm); - jsc.picker.padB.appendChild(jsc.picker.pad); - jsc.picker.cross.appendChild(jsc.picker.crossBY); - jsc.picker.cross.appendChild(jsc.picker.crossBX); - jsc.picker.cross.appendChild(jsc.picker.crossLY); - jsc.picker.cross.appendChild(jsc.picker.crossLX); - jsc.picker.padB.appendChild(jsc.picker.cross); - jsc.picker.box.appendChild(jsc.picker.padB); - jsc.picker.box.appendChild(jsc.picker.padM); - - jsc.picker.sld.appendChild(jsc.picker.sldGrad.elm); - jsc.picker.sldB.appendChild(jsc.picker.sld); - jsc.picker.sldB.appendChild(jsc.picker.sldPtrOB); - jsc.picker.sldPtrOB.appendChild(jsc.picker.sldPtrMB); - jsc.picker.sldPtrMB.appendChild(jsc.picker.sldPtrIB); - jsc.picker.sldPtrIB.appendChild(jsc.picker.sldPtrS); - jsc.picker.box.appendChild(jsc.picker.sldB); - jsc.picker.box.appendChild(jsc.picker.sldM); - - jsc.picker.asld.appendChild(jsc.picker.asldGrad.elm); - jsc.picker.asldB.appendChild(jsc.picker.asld); - jsc.picker.asldB.appendChild(jsc.picker.asldPtrOB); - jsc.picker.asldPtrOB.appendChild(jsc.picker.asldPtrMB); - jsc.picker.asldPtrMB.appendChild(jsc.picker.asldPtrIB); - jsc.picker.asldPtrIB.appendChild(jsc.picker.asldPtrS); - jsc.picker.box.appendChild(jsc.picker.asldB); - jsc.picker.box.appendChild(jsc.picker.asldM); - - jsc.picker.box.appendChild(jsc.picker.pal); - - jsc.picker.btn.appendChild(jsc.picker.btnT); - jsc.picker.box.appendChild(jsc.picker.btn); - - jsc.picker.boxB.appendChild(jsc.picker.box); - jsc.picker.wrap.appendChild(jsc.picker.boxS); - jsc.picker.wrap.appendChild(jsc.picker.boxB); - - jsc.picker.wrap.addEventListener('touchstart', jsc.onPickerTouchStart, - jsc.isPassiveEventSupported ? {passive: false} : false); - } - - var p = jsc.picker; - - var displaySlider = !!jsc.getSliderChannel(THIS); - var displayAlphaSlider = THIS.hasAlphaChannel(); - var pickerDims = jsc.getPickerDims(THIS); - var crossOuterSize = (2 * THIS.pointerBorderWidth + THIS.pointerThickness + 2 * THIS.crossSize); - var controlPadding = jsc.getControlPadding(THIS); - var borderRadius = Math.min( - THIS.borderRadius, - Math.round(THIS.padding * Math.PI)); // px - var padCursor = 'crosshair'; - - // wrap - p.wrap.className = 'jscolor-picker-wrap'; - p.wrap.style.clear = 'both'; - p.wrap.style.width = pickerDims.borderW + 'px'; - p.wrap.style.height = pickerDims.borderH + 'px'; - p.wrap.style.zIndex = THIS.zIndex; - - // picker - p.box.className = 'jscolor-picker'; - p.box.style.width = pickerDims.paddedW + 'px'; - p.box.style.height = pickerDims.paddedH + 'px'; - p.box.style.position = 'relative'; - - // picker shadow - p.boxS.className = 'jscolor-picker-shadow'; - p.boxS.style.position = 'absolute'; - p.boxS.style.left = '0'; - p.boxS.style.top = '0'; - p.boxS.style.width = '100%'; - p.boxS.style.height = '100%'; - jsc.setBorderRadius(p.boxS, borderRadius + 'px'); - - // picker border - p.boxB.className = 'jscolor-picker-border'; - p.boxB.style.position = 'relative'; - p.boxB.style.border = THIS.borderWidth + 'px solid'; - p.boxB.style.borderColor = THIS.borderColor; - p.boxB.style.background = THIS.backgroundColor; - jsc.setBorderRadius(p.boxB, borderRadius + 'px'); - - // IE hack: - // If the element is transparent, IE will trigger the event on the elements under it, - // e.g. on Canvas or on elements with border - p.padM.style.background = 'rgba(255,0,0,.2)'; - p.sldM.style.background = 'rgba(0,255,0,.2)'; - p.asldM.style.background = 'rgba(0,0,255,.2)'; - - p.padM.style.opacity = - p.sldM.style.opacity = - p.asldM.style.opacity = - '0'; - - // pad - p.pad.style.position = 'relative'; - p.pad.style.width = THIS.width + 'px'; - p.pad.style.height = THIS.height + 'px'; - - // pad - color spectrum (HSV and HVS) - p.padCanvas.draw(THIS.width, THIS.height, jsc.getPadYChannel(THIS)); - - // pad border - p.padB.style.position = 'absolute'; - p.padB.style.left = THIS.padding + 'px'; - p.padB.style.top = THIS.padding + 'px'; - p.padB.style.border = THIS.controlBorderWidth + 'px solid'; - p.padB.style.borderColor = THIS.controlBorderColor; - - // pad mouse area - p.padM.style.position = 'absolute'; - p.padM.style.left = 0 + 'px'; - p.padM.style.top = 0 + 'px'; - p.padM.style.width = (THIS.padding + 2 * THIS.controlBorderWidth + THIS.width + controlPadding) + 'px'; - p.padM.style.height = (2 * THIS.controlBorderWidth + 2 * THIS.padding + THIS.height) + 'px'; - p.padM.style.cursor = padCursor; - jsc.setData(p.padM, { - instance: THIS, - control: 'pad', - }) - - // pad cross - p.cross.style.position = 'absolute'; - p.cross.style.left = - p.cross.style.top = - '0'; - p.cross.style.width = - p.cross.style.height = - crossOuterSize + 'px'; - - // pad cross border Y and X - p.crossBY.style.position = - p.crossBX.style.position = - 'absolute'; - p.crossBY.style.background = - p.crossBX.style.background = - THIS.pointerBorderColor; - p.crossBY.style.width = - p.crossBX.style.height = - (2 * THIS.pointerBorderWidth + THIS.pointerThickness) + 'px'; - p.crossBY.style.height = - p.crossBX.style.width = - crossOuterSize + 'px'; - p.crossBY.style.left = - p.crossBX.style.top = - (Math.floor(crossOuterSize / 2) - Math.floor(THIS.pointerThickness / 2) - THIS.pointerBorderWidth) + 'px'; - p.crossBY.style.top = - p.crossBX.style.left = - '0'; - - // pad cross line Y and X - p.crossLY.style.position = - p.crossLX.style.position = - 'absolute'; - p.crossLY.style.background = - p.crossLX.style.background = - THIS.pointerColor; - p.crossLY.style.height = - p.crossLX.style.width = - (crossOuterSize - 2 * THIS.pointerBorderWidth) + 'px'; - p.crossLY.style.width = - p.crossLX.style.height = - THIS.pointerThickness + 'px'; - p.crossLY.style.left = - p.crossLX.style.top = - (Math.floor(crossOuterSize / 2) - Math.floor(THIS.pointerThickness / 2)) + 'px'; - p.crossLY.style.top = - p.crossLX.style.left = - THIS.pointerBorderWidth + 'px'; - - - // slider - p.sld.style.overflow = 'hidden'; - p.sld.style.width = THIS.sliderSize + 'px'; - p.sld.style.height = THIS.height + 'px'; - - // slider gradient - p.sldGrad.draw(THIS.sliderSize, THIS.height, '#000', '#000'); - - // slider border - p.sldB.style.display = displaySlider ? 'block' : 'none'; - p.sldB.style.position = 'absolute'; - p.sldB.style.left = (THIS.padding + THIS.width + 2 * THIS.controlBorderWidth + 2 * controlPadding) + 'px'; - p.sldB.style.top = THIS.padding + 'px'; - p.sldB.style.border = THIS.controlBorderWidth + 'px solid'; - p.sldB.style.borderColor = THIS.controlBorderColor; - - // slider mouse area - p.sldM.style.display = displaySlider ? 'block' : 'none'; - p.sldM.style.position = 'absolute'; - p.sldM.style.left = (THIS.padding + THIS.width + 2 * THIS.controlBorderWidth + controlPadding) + 'px'; - p.sldM.style.top = 0 + 'px'; - p.sldM.style.width = ( - (THIS.sliderSize + 2 * controlPadding + 2 * THIS.controlBorderWidth) + - (displayAlphaSlider ? 0 : Math.max(0, THIS.padding - controlPadding)) // remaining padding to the right edge - ) + 'px'; - p.sldM.style.height = (2 * THIS.controlBorderWidth + 2 * THIS.padding + THIS.height) + 'px'; - p.sldM.style.cursor = 'default'; - jsc.setData(p.sldM, { - instance: THIS, - control: 'sld', - }); - - // slider pointer inner and outer border - p.sldPtrIB.style.border = - p.sldPtrOB.style.border = - THIS.pointerBorderWidth + 'px solid ' + THIS.pointerBorderColor; - - // slider pointer outer border - p.sldPtrOB.style.position = 'absolute'; - p.sldPtrOB.style.left = -(2 * THIS.pointerBorderWidth + THIS.pointerThickness) + 'px'; - p.sldPtrOB.style.top = '0'; - - // slider pointer middle border - p.sldPtrMB.style.border = THIS.pointerThickness + 'px solid ' + THIS.pointerColor; - - // slider pointer spacer - p.sldPtrS.style.width = THIS.sliderSize + 'px'; - p.sldPtrS.style.height = jsc.pub.sliderInnerSpace + 'px'; - - - // alpha slider - p.asld.style.overflow = 'hidden'; - p.asld.style.width = THIS.sliderSize + 'px'; - p.asld.style.height = THIS.height + 'px'; - - // alpha slider gradient - p.asldGrad.draw(THIS.sliderSize, THIS.height, '#000'); - - // alpha slider border - p.asldB.style.display = displayAlphaSlider ? 'block' : 'none'; - p.asldB.style.position = 'absolute'; - p.asldB.style.left = ( - (THIS.padding + THIS.width + 2 * THIS.controlBorderWidth + controlPadding) + - (displaySlider ? (THIS.sliderSize + 3 * controlPadding + 2 * THIS.controlBorderWidth) : 0) - ) + 'px'; - p.asldB.style.top = THIS.padding + 'px'; - p.asldB.style.border = THIS.controlBorderWidth + 'px solid'; - p.asldB.style.borderColor = THIS.controlBorderColor; - - // alpha slider mouse area - p.asldM.style.display = displayAlphaSlider ? 'block' : 'none'; - p.asldM.style.position = 'absolute'; - p.asldM.style.left = ( - (THIS.padding + THIS.width + 2 * THIS.controlBorderWidth + controlPadding) + - (displaySlider ? (THIS.sliderSize + 2 * controlPadding + 2 * THIS.controlBorderWidth) : 0) - ) + 'px'; - p.asldM.style.top = 0 + 'px'; - p.asldM.style.width = ( - (THIS.sliderSize + 2 * controlPadding + 2 * THIS.controlBorderWidth) + - Math.max(0, THIS.padding - controlPadding) // remaining padding to the right edge - ) + 'px'; - p.asldM.style.height = (2 * THIS.controlBorderWidth + 2 * THIS.padding + THIS.height) + 'px'; - p.asldM.style.cursor = 'default'; - jsc.setData(p.asldM, { - instance: THIS, - control: 'asld', - }) - - // alpha slider pointer inner and outer border - p.asldPtrIB.style.border = - p.asldPtrOB.style.border = - THIS.pointerBorderWidth + 'px solid ' + THIS.pointerBorderColor; - - // alpha slider pointer outer border - p.asldPtrOB.style.position = 'absolute'; - p.asldPtrOB.style.left = -(2 * THIS.pointerBorderWidth + THIS.pointerThickness) + 'px'; - p.asldPtrOB.style.top = '0'; - - // alpha slider pointer middle border - p.asldPtrMB.style.border = THIS.pointerThickness + 'px solid ' + THIS.pointerColor; - - // alpha slider pointer spacer - p.asldPtrS.style.width = THIS.sliderSize + 'px'; - p.asldPtrS.style.height = jsc.pub.sliderInnerSpace + 'px'; - - - // palette - p.pal.className = 'jscolor-palette'; - p.pal.style.display = pickerDims.palette.rows ? 'block' : 'none'; - p.pal.style.position = 'absolute'; - p.pal.style.left = THIS.padding + 'px'; - p.pal.style.top = (2 * THIS.controlBorderWidth + 2 * THIS.padding + THIS.height) + 'px'; - - // palette's color samples - - p.pal.innerHTML = ''; - - var chessboard = jsc.genColorPreviewCanvas('rgba(0,0,0,0)'); - - var si = 0; // color sample's index - for (var r = 0; r < pickerDims.palette.rows; r++) { - for (var c = 0; c < pickerDims.palette.cols && si < THIS._palette.length; c++, si++) { - var sampleColor = THIS._palette[si]; - var sampleCssColor = jsc.rgbaColor.apply(null, sampleColor.rgba); - - var sc = jsc.createEl('div'); // color sample's color - sc.style.width = (pickerDims.palette.cellW - 2 * THIS.controlBorderWidth) + 'px'; - sc.style.height = (pickerDims.palette.cellH - 2 * THIS.controlBorderWidth) + 'px'; - sc.style.backgroundColor = sampleCssColor; - - var sw = jsc.createEl('div'); // color sample's wrap - sw.className = 'jscolor-palette-sample'; - sw.style.display = 'block'; - sw.style.position = 'absolute'; - sw.style.left = ( - pickerDims.palette.cols <= 1 ? 0 : - Math.round(10 * (c * ((pickerDims.contentW - pickerDims.palette.cellW) / (pickerDims.palette.cols - 1)))) / 10 - ) + 'px'; - sw.style.top = (r * (pickerDims.palette.cellH + THIS.paletteSpacing)) + 'px'; - sw.style.border = THIS.controlBorderWidth + 'px solid'; - sw.style.borderColor = THIS.controlBorderColor; - sw.style.cursor = 'pointer'; - if (sampleColor.rgba[3] !== null && sampleColor.rgba[3] < 1.0) { // only create chessboard background if the sample has transparency - sw.style.backgroundImage = 'url(\'' + chessboard.canvas.toDataURL() + '\')'; - sw.style.backgroundRepeat = 'repeat'; - sw.style.backgroundPosition = 'center center'; - } - jsc.setData(sw, { - instance: THIS, - control: 'palette-sample', - color: sampleColor, - }) - sw.addEventListener('click', jsc.onPaletteSampleClick, false); - sw.appendChild(sc); - p.pal.appendChild(sw); - } - } - - - // the Close button - function setBtnBorder () { - var insetColors = THIS.controlBorderColor.split(/\s+/); - var outsetColor = insetColors.length < 2 ? insetColors[0] : insetColors[1] + ' ' + insetColors[0] + ' ' + insetColors[0] + ' ' + insetColors[1]; - p.btn.style.borderColor = outsetColor; - } - var btnPadding = 15; // px - p.btn.className = 'jscolor-btn-close'; - p.btn.style.display = THIS.closeButton ? 'block' : 'none'; - p.btn.style.position = 'absolute'; - p.btn.style.left = THIS.padding + 'px'; - p.btn.style.bottom = THIS.padding + 'px'; - p.btn.style.padding = '0 ' + btnPadding + 'px'; - p.btn.style.maxWidth = (pickerDims.contentW - 2 * THIS.controlBorderWidth - 2 * btnPadding) + 'px'; - p.btn.style.overflow = 'hidden'; - p.btn.style.height = THIS.buttonHeight + 'px'; - p.btn.style.whiteSpace = 'nowrap'; - p.btn.style.border = THIS.controlBorderWidth + 'px solid'; - setBtnBorder(); - p.btn.style.color = THIS.buttonColor; - p.btn.style.font = '12px sans-serif'; - p.btn.style.textAlign = 'center'; - p.btn.style.cursor = 'pointer'; - p.btn.onmousedown = function () { - THIS.hide(); - }; - p.btnT.style.lineHeight = THIS.buttonHeight + 'px'; - p.btnT.innerHTML = ''; - p.btnT.appendChild(window.document.createTextNode(THIS.closeText)); - - // reposition the pointers - redrawPad(); - redrawSld(); - redrawASld(); - - // If we are changing the owner without first closing the picker, - // make sure to first deal with the old owner - if (jsc.picker.owner && jsc.picker.owner !== THIS) { - jsc.removeClass(jsc.picker.owner.targetElement, jsc.pub.activeClassName); - } - - // Set a new picker owner - jsc.picker.owner = THIS; - - // The redrawPosition() method needs picker.owner to be set, that's why we call it here, - // after setting the owner - jsc.redrawPosition(); - - if (p.wrap.parentNode !== THIS.container) { - THIS.container.appendChild(p.wrap); - } - - jsc.addClass(THIS.targetElement, jsc.pub.activeClassName); - } - - - function redrawPad () { - // redraw the pad pointer - var yChannel = jsc.getPadYChannel(THIS); - var x = Math.round((THIS.channels.h / 360) * (THIS.width - 1)); - var y = Math.round((1 - THIS.channels[yChannel] / 100) * (THIS.height - 1)); - var crossOuterSize = (2 * THIS.pointerBorderWidth + THIS.pointerThickness + 2 * THIS.crossSize); - var ofs = -Math.floor(crossOuterSize / 2); - jsc.picker.cross.style.left = (x + ofs) + 'px'; - jsc.picker.cross.style.top = (y + ofs) + 'px'; - - // redraw the slider - switch (jsc.getSliderChannel(THIS)) { - case 's': - var rgb1 = jsc.HSV_RGB(THIS.channels.h, 100, THIS.channels.v); - var rgb2 = jsc.HSV_RGB(THIS.channels.h, 0, THIS.channels.v); - var color1 = 'rgb(' + - Math.round(rgb1[0]) + ',' + - Math.round(rgb1[1]) + ',' + - Math.round(rgb1[2]) + ')'; - var color2 = 'rgb(' + - Math.round(rgb2[0]) + ',' + - Math.round(rgb2[1]) + ',' + - Math.round(rgb2[2]) + ')'; - jsc.picker.sldGrad.draw(THIS.sliderSize, THIS.height, color1, color2); - break; - case 'v': - var rgb = jsc.HSV_RGB(THIS.channels.h, THIS.channels.s, 100); - var color1 = 'rgb(' + - Math.round(rgb[0]) + ',' + - Math.round(rgb[1]) + ',' + - Math.round(rgb[2]) + ')'; - var color2 = '#000'; - jsc.picker.sldGrad.draw(THIS.sliderSize, THIS.height, color1, color2); - break; - } - - // redraw the alpha slider - jsc.picker.asldGrad.draw(THIS.sliderSize, THIS.height, THIS.toHEXString()); - } - - - function redrawSld () { - var sldChannel = jsc.getSliderChannel(THIS); - if (sldChannel) { - // redraw the slider pointer - var y = Math.round((1 - THIS.channels[sldChannel] / 100) * (THIS.height - 1)); - jsc.picker.sldPtrOB.style.top = (y - (2 * THIS.pointerBorderWidth + THIS.pointerThickness) - Math.floor(jsc.pub.sliderInnerSpace / 2)) + 'px'; - } - - // redraw the alpha slider - jsc.picker.asldGrad.draw(THIS.sliderSize, THIS.height, THIS.toHEXString()); - } - - - function redrawASld () { - var y = Math.round((1 - THIS.channels.a) * (THIS.height - 1)); - jsc.picker.asldPtrOB.style.top = (y - (2 * THIS.pointerBorderWidth + THIS.pointerThickness) - Math.floor(jsc.pub.sliderInnerSpace / 2)) + 'px'; - } - - - function isPickerOwner () { - return jsc.picker && jsc.picker.owner === THIS; - } - - - function onValueKeyDown (ev) { - if (jsc.eventKey(ev) === 'Enter') { - if (THIS.valueElement) { - THIS.processValueInput(THIS.valueElement.value); - } - THIS.tryHide(); - } - } - - - function onAlphaKeyDown (ev) { - if (jsc.eventKey(ev) === 'Enter') { - if (THIS.alphaElement) { - THIS.processAlphaInput(THIS.alphaElement.value); - } - THIS.tryHide(); - } - } - - - function onValueChange (ev) { - if (jsc.getData(ev, 'internal')) { - return; // skip if the event was internally triggered by jscolor - } - - var oldVal = THIS.valueElement.value; - - THIS.processValueInput(THIS.valueElement.value); // this might change the value - - jsc.triggerCallback(THIS, 'onChange'); - - if (THIS.valueElement.value !== oldVal) { - // value was additionally changed -> let's trigger the change event again, even though it was natively dispatched - jsc.triggerInputEvent(THIS.valueElement, 'change', true, true); - } - } - - - function onAlphaChange (ev) { - if (jsc.getData(ev, 'internal')) { - return; // skip if the event was internally triggered by jscolor - } - - var oldVal = THIS.alphaElement.value; - - THIS.processAlphaInput(THIS.alphaElement.value); // this might change the value - - jsc.triggerCallback(THIS, 'onChange'); - - // triggering valueElement's onChange (because changing alpha changes the entire color, e.g. with rgba format) - jsc.triggerInputEvent(THIS.valueElement, 'change', true, true); - - if (THIS.alphaElement.value !== oldVal) { - // value was additionally changed -> let's trigger the change event again, even though it was natively dispatched - jsc.triggerInputEvent(THIS.alphaElement, 'change', true, true); - } - } - - - function onValueInput (ev) { - if (jsc.getData(ev, 'internal')) { - return; // skip if the event was internally triggered by jscolor - } - - if (THIS.valueElement) { - THIS.fromString(THIS.valueElement.value, jsc.flags.leaveValue); - } - - jsc.triggerCallback(THIS, 'onInput'); - - // triggering valueElement's onInput - // (not needed, it was dispatched normally by the browser) - } - - - function onAlphaInput (ev) { - if (jsc.getData(ev, 'internal')) { - return; // skip if the event was internally triggered by jscolor - } - - if (THIS.alphaElement) { - THIS.fromHSVA(null, null, null, parseFloat(THIS.alphaElement.value), jsc.flags.leaveAlpha); - } - - jsc.triggerCallback(THIS, 'onInput'); - - // triggering valueElement's onInput (because changing alpha changes the entire color, e.g. with rgba format) - jsc.triggerInputEvent(THIS.valueElement, 'input', true, true); - } - - - // let's process the DEPRECATED 'options' property (this will be later removed) - if (jsc.pub.options) { - // let's set custom default options, if specified - for (var opt in jsc.pub.options) { - if (jsc.pub.options.hasOwnProperty(opt)) { - try { - setOption(opt, jsc.pub.options[opt]); - } catch (e) { - console.warn(e); - } - } - } - } - - - // let's apply configuration presets - // - var presetsArr = []; - - if (opts.preset) { - if (typeof opts.preset === 'string') { - presetsArr = opts.preset.split(/\s+/); - } else if (Array.isArray(opts.preset)) { - presetsArr = opts.preset.slice(); // slice() to clone - } else { - console.warn('Unrecognized preset value'); - } - } - - // always use the 'default' preset. If it's not listed, append it to the end. - if (presetsArr.indexOf('default') === -1) { - presetsArr.push('default'); - } - - // let's apply the presets in reverse order, so that should there be any overlapping options, - // the formerly listed preset will override the latter - for (var i = presetsArr.length - 1; i >= 0; i -= 1) { - var pres = presetsArr[i]; - if (!pres) { - continue; // preset is empty string - } - if (!jsc.pub.presets.hasOwnProperty(pres)) { - console.warn('Unknown preset: %s', pres); - continue; - } - for (var opt in jsc.pub.presets[pres]) { - if (jsc.pub.presets[pres].hasOwnProperty(opt)) { - try { - setOption(opt, jsc.pub.presets[pres][opt]); - } catch (e) { - console.warn(e); - } - } - } - } - - - // let's set specific options for this color picker - var nonProperties = [ - // these options won't be set as instance properties - 'preset', - ]; - for (var opt in opts) { - if (opts.hasOwnProperty(opt)) { - if (nonProperties.indexOf(opt) === -1) { - try { - setOption(opt, opts[opt]); - } catch (e) { - console.warn(e); - } - } - } - } - - - // - // Install the color picker on chosen element(s) - // - - - // Determine picker's container element - if (this.container === undefined) { - this.container = window.document.body; // default container is BODY element - - } else { // explicitly set to custom element - this.container = jsc.node(this.container); - } - - if (!this.container) { - throw new Error('Cannot instantiate color picker without a container element'); - } - - - // Fetch the target element - this.targetElement = jsc.node(targetElement); - - if (!this.targetElement) { - // temporarily customized error message to help with migrating from versions prior to 2.2 - if (typeof targetElement === 'string' && /^[a-zA-Z][\w:.-]*$/.test(targetElement)) { - // targetElement looks like valid ID - var possiblyId = targetElement; - throw new Error('If \'' + possiblyId + '\' is supposed to be an ID, please use \'#' + possiblyId + '\' or any valid CSS selector.'); - } - - throw new Error('Cannot instantiate color picker without a target element'); - } - - if (this.targetElement.jscolor && this.targetElement.jscolor instanceof jsc.pub) { - throw new Error('Color picker already installed on this element'); - } - - - // link this instance with the target element - this.targetElement.jscolor = this; - jsc.addClass(this.targetElement, jsc.pub.className); - - // register this instance - jsc.instances.push(this); - - - // if target is BUTTON - if (jsc.isButton(this.targetElement)) { - - if (this.targetElement.type.toLowerCase() !== 'button') { - // on buttons, always force type to be 'button', e.g. in situations the target