UNPKG

text-to-map

Version:

Text To Map usiluje o lepší, strojově zpracovatelné využití částí vyhlášek s výčtem ulic a dalších lokací. Jde o rozšiřitelnou sadu konceptů a nástrojů, které zajistí hladký převod výčtu ulic a jejich rozsahů v lidsky srozumitelném jazyce do strojově zpra

176 lines 24.2 kB
import { existsSync, mkdirSync } from "fs"; import { tmpdir } from "os"; import { dirname, join } from "path"; import { fileURLToPath } from "url"; import { MunicipalityType } from "../db/types"; const appName = "text-to-map"; export const getAppDataDirPath = () => join(process.env.APPDATA || (process.platform == "darwin" ? process.env.HOME + "/Library/Preferences" : process.env.HOME + "/.local/share"), appName); export const prepareOptions = (options) => { const dataDir = options.dataDir ?? getAppDataDirPath(); if (!existsSync(dataDir)) { mkdirSync(dataDir); } const tmpAppDir = join(tmpdir(), appName); if (!existsSync(tmpAppDir)) { mkdirSync(tmpAppDir); } const __filename = fileURLToPath(import.meta.url); const __dirname = dirname(__filename); const defaults = { tmpDir: tmpAppDir, dataDir: dataDir, dbFilePath: join(dataDir, "address_points.db"), dbInitFilePath: join(__dirname, "..", "address_points_init.db"), addressPointsAtomUrl: "https://atom.cuzk.cz/RUIAN-CSV-ADR-ST/RUIAN-CSV-ADR-ST.xml", addressPointsZipFileName: "ruian_csv.zip", addressPointsCsvFolderName: "CSV", streetsAtomUrl: "https://atom.cuzk.cz/RUIAN-OBCE-SHP/RUIAN-OBCE-SHP.xml", streetZipFolderName: "streets", streetDbfFileName: "UL_L.dbf", polygonShpFileName: "OBEC_P.shp", districtPolygonShpFileName: "MOMC_P.shp", districtPolygonDbfFileName: "MOMC_P.dbf", schoolsJsonldUrl: "https://lkod-ftp.msmt.gov.cz/00022985/88a7c12b-6084-4e47-8b50-46097c6e683f/RSSZ-cela-CR.jsonld", schoolsJsonldFileName: "school-register.jsonld", regionsCsvUrl: "https://www.czso.cz/documents/10180/23208674/struktura_uzemi_cr.csv", regionsSchemaUrl: "https://www.czso.cz/documents/10180/23208674/struktura_uzemi_cr-metadata.json", regionsCsvFileName: "struktura_uzemi_cr.csv", }; return { ...defaults, ...options, }; }; const cityPatterns = [ /^[sS]tatutární město +(.*)$/, /^[oO]bec +(.*)$/, /^[mM]ěsto +(.*)$/, /^[mM]ěstys +(.*)$/, ]; const districtPatterns = [ /^[mM]ěstská část +(.*)$/, /^[mM]ěstský obvod +(.*)$/, /^[sS]tatutární město +.*, [mM]ěstská část +(.*)$/, /^[sS]tatutární město +.*, [mM]ěstský obvod +(.*)$/, ]; export const extractMunicipalityName = (founder) => { const patterns = founder.municipalityType === MunicipalityType.City ? cityPatterns : districtPatterns; const correctPattern = patterns.filter((pattern) => pattern.test(founder.name)); if (correctPattern.length > 0) { const result = correctPattern[0].exec(founder.name); if (typeof result[1] !== "undefined") { return result[1] .replace(" - ", "-") .replace(/\s{2,}/g, " ") .trim(); } } return founder.name; }; export const sanitizeMunicipalityName = (name) => { return name .replace(" - ", "-") .replace(/\s{2,}/g, " ") .trim(); }; export const findClosestString = (str, arr, maxDistance) => { let closestStr = ""; let closestDistance = Number.MAX_SAFE_INTEGER; for (let i = 0; i < arr.length; i++) { const currentStr = arr[i]; const distance = interpunctionDistance(str, currentStr); if (distance < closestDistance) { closestStr = currentStr; closestDistance = distance; } // exact match found, exit loop if (closestDistance === 0) { break; } } if (maxDistance !== undefined && closestDistance > maxDistance) { return ""; } return closestStr; }; const interpunctionDistance = (str1, str2) => { let distance = levenshteinDistance(str1, str2); const interpunctionMistakes = { a: ["á"], á: ["a"], e: ["é", "ě"], é: ["e", "ě"], ě: ["e", "é"], i: ["í"], í: ["i"], y: ["ý"], ý: ["y"], o: ["ó"], ó: ["o"], u: ["ú", "ů"], ů: ["u", "ú"], ú: ["u", "ů"], c: ["č"], č: ["c"], d: ["ď"], ď: ["d"], n: ["ň"], ň: ["n"], r: ["ř"], ř: ["r"], s: ["š"], š: ["s"], t: ["ť"], ť: ["t"], z: ["ž"], ž: ["z"], }; const str1Chars = str1.split(""); const str2Chars = str2.split(""); for (let i = 0; i < str1Chars.length; i++) { const char1 = str1Chars[i]; const char2 = str2Chars[i]; if (interpunctionMistakes[char1] && interpunctionMistakes[char1].includes(char2)) { // Subtract a penalty from the distance for interpunction mistakes distance -= 0.5; } } return distance; }; const levenshteinDistance = (str1, str2) => { const matrix = Array(str2.length + 1) .fill(null) .map(() => Array(str1.length + 1).fill(null)); for (let i = 0; i <= str1.length; i++) { matrix[0][i] = i; } for (let j = 0; j <= str2.length; j++) { matrix[j][0] = j; } for (let j = 1; j <= str2.length; j++) { for (let i = 1; i <= str1.length; i++) { if (str1[i - 1] === str2[j - 1]) { matrix[j][i] = matrix[j - 1][i - 1]; } else { matrix[j][i] = Math.min(matrix[j][i - 1], // deletion matrix[j - 1][i], // insertion matrix[j - 1][i - 1] // substitution ) + 1; } } } return matrix[str2.length][str1.length]; }; export function roundToNDecimalPlaces(toRound, decimalPlaces) { return (Math.round(toRound * Math.pow(10, decimalPlaces)) / Math.pow(10, decimalPlaces)); } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaGVscGVycy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy91dGlscy9oZWxwZXJzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxVQUFVLEVBQUUsU0FBUyxFQUFFLE1BQU0sSUFBSSxDQUFDO0FBQzNDLE9BQU8sRUFBRSxNQUFNLEVBQUUsTUFBTSxJQUFJLENBQUM7QUFDNUIsT0FBTyxFQUFFLE9BQU8sRUFBRSxJQUFJLEVBQUUsTUFBTSxNQUFNLENBQUM7QUFDckMsT0FBTyxFQUFFLGFBQWEsRUFBRSxNQUFNLEtBQUssQ0FBQztBQUNwQyxPQUFPLEVBQVcsZ0JBQWdCLEVBQUUsTUFBTSxhQUFhLENBQUM7QUFFeEQsTUFBTSxPQUFPLEdBQUcsYUFBYSxDQUFDO0FBeUI5QixNQUFNLENBQUMsTUFBTSxpQkFBaUIsR0FBRyxHQUFXLEVBQUUsQ0FDNUMsSUFBSSxDQUNGLE9BQU8sQ0FBQyxHQUFHLENBQUMsT0FBTztJQUNqQixDQUFDLE9BQU8sQ0FBQyxRQUFRLElBQUksUUFBUTtRQUMzQixDQUFDLENBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxJQUFJLEdBQUcsc0JBQXNCO1FBQzNDLENBQUMsQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDLElBQUksR0FBRyxlQUFlLENBQUMsRUFDekMsT0FBTyxDQUNSLENBQUM7QUFFSixNQUFNLENBQUMsTUFBTSxjQUFjLEdBQUcsQ0FDNUIsT0FBbUMsRUFDZCxFQUFFO0lBQ3ZCLE1BQU0sT0FBTyxHQUFHLE9BQU8sQ0FBQyxPQUFPLElBQUksaUJBQWlCLEVBQUUsQ0FBQztJQUN2RCxJQUFJLENBQUMsVUFBVSxDQUFDLE9BQU8sQ0FBQyxFQUFFO1FBQ3hCLFNBQVMsQ0FBQyxPQUFPLENBQUMsQ0FBQztLQUNwQjtJQUVELE1BQU0sU0FBUyxHQUFHLElBQUksQ0FBQyxNQUFNLEVBQUUsRUFBRSxPQUFPLENBQUMsQ0FBQztJQUMxQyxJQUFJLENBQUMsVUFBVSxDQUFDLFNBQVMs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Q0FBQyxHQUFHLENBQUM7UUFDUixDQUFDLEVBQUUsQ0FBQyxHQUFHLENBQUM7UUFDUixDQUFDLEVBQUUsQ0FBQyxHQUFHLENBQUM7UUFDUixDQUFDLEVBQUUsQ0FBQyxHQUFHLENBQUM7UUFDUixDQUFDLEVBQUUsQ0FBQyxHQUFHLEVBQUUsR0FBRyxDQUFDO1FBQ2IsQ0FBQyxFQUFFLENBQUMsR0FBRyxFQUFFLEdBQUcsQ0FBQztRQUNiLENBQUMsRUFBRSxDQUFDLEdBQUcsRUFBRSxHQUFHLENBQUM7UUFDYixDQUFDLEVBQUUsQ0FBQyxHQUFHLENBQUM7UUFDUixDQUFDLEVBQUUsQ0FBQyxHQUFHLENBQUM7UUFDUixDQUFDLEVBQUUsQ0FBQyxHQUFHLENBQUM7UUFDUixDQUFDLEVBQUUsQ0FBQyxHQUFHLENBQUM7UUFDUixDQUFDLEVBQUUsQ0FBQyxHQUFHLENBQUM7UUFDUixDQUFDLEVBQUUsQ0FBQyxHQUFHLENBQUM7UUFDUixDQUFDLEVBQUUsQ0FBQyxHQUFHLENBQUM7UUFDUixDQUFDLEVBQUUsQ0FBQyxHQUFHLENBQUM7UUFDUixDQUFDLEVBQUUsQ0FBQyxHQUFHLENBQUM7UUFDUixDQUFDLEVBQUUsQ0FBQyxHQUFHLENBQUM7UUFDUixDQUFDLEVBQUUsQ0FBQyxHQUFHLENBQUM7UUFDUixDQUFDLEVBQUUsQ0FBQyxHQUFHLENBQUM7UUFDUixDQUFDLEVBQUUsQ0FBQyxHQUFHLENBQUM7UUFDUixDQUFDLEVBQUUsQ0FBQyxHQUFHLENBQUM7S0FDVCxDQUFDO0lBRUYsTUFBTSxTQUFTLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxFQUFFLENBQUMsQ0FBQztJQUNqQyxNQUFNLFNBQVMsR0FBRyxJQUFJLENBQUMsS0FBSyxDQUFDLEVBQUUsQ0FBQyxDQUFDO0lBRWpDLEtBQUssSUFBSSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsR0FBRyxTQUFTLENBQUMsTUFBTSxFQUFFLENBQUMsRUFBRSxFQUFFO1FBQ3pDLE1BQU0sS0FBSyxHQUFHLFNBQVMsQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUMzQixNQUFNLEtBQUssR0FBRyxTQUFTLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFFM0IsSUFDRSxxQkFBcUIsQ0FBQyxLQUFLLENBQUM7WUFDNUIscUJBQXFCLENBQUMsS0FBSyxDQUFDLENBQUMsUUFBUSxDQUFDLEtBQUssQ0FBQyxFQUM1QztZQUNBLGtFQUFrRTtZQUNsRSxRQUFRLElBQUksR0FBRyxDQUFDO1NBQ2pCO0tBQ0Y7SUFFRCxPQUFPLFFBQVEsQ0FBQztBQUNsQixDQUFDLENBQUM7QUFFRixNQUFNLG1CQUFtQixHQUFHLENBQUMsSUFBWSxFQUFFLElBQVksRUFBVSxFQUFFO0lBQ2pFLE1BQU0sTUFBTSxHQUFlLEtBQUssQ0FBQyxJQUFJLENBQUMsTUFBTSxHQUFHLENBQUMsQ0FBQztTQUM5QyxJQUFJLENBQUMsSUFBSSxDQUFDO1NBQ1YsR0FBRyxDQUFDLEdBQUcsRUFBRSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsTUFBTSxHQUFHLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDO0lBRWhELEtBQUssSUFBSSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsSUFBSSxJQUFJLENBQUMsTUFBTSxFQUFFLENBQUMsRUFBRSxFQUFFO1FBQ3JDLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUM7S0FDbEI7SUFFRCxLQUFLLElBQUksQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLElBQUksSUFBSSxDQUFDLE1BQU0sRUFBRSxDQUFDLEVBQUUsRUFBRTtRQUNyQyxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDO0tBQ2xCO0lBRUQsS0FBSyxJQUFJLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxJQUFJLElBQUksQ0FBQyxNQUFNLEVBQUUsQ0FBQyxFQUFFLEVBQUU7UUFDckMsS0FBSyxJQUFJLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxJQUFJLElBQUksQ0FBQyxNQUFNLEVBQUUsQ0FBQyxFQUFFLEVBQUU7WUFDckMsSUFBSSxJQUFJLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxLQUFLLElBQUksQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLEVBQUU7Z0JBQy9CLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsR0FBRyxNQUFNLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQzthQUNyQztpQkFBTTtnQkFDTCxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO29CQUNWLElBQUksQ0FBQyxHQUFHLENBQ04sTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsRUFBRSxXQUFXO29CQUM3QixNQUFNLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLFlBQVk7b0JBQzlCLE1BQU0sQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLGVBQWU7cUJBQ3JDLEdBQUcsQ0FBQyxDQUFDO2FBQ1Q7U0FDRjtLQUNGO0lBRUQsT0FBTyxNQUFNLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsQ0FBQztBQUMxQyxDQUFDLENBQUM7QUFFRixNQUFNLFVBQVUscUJBQXFCLENBQ25DLE9BQWUsRUFDZixhQUFxQjtJQUVyQixPQUFPLENBQ0wsSUFBSSxDQUFDLEtBQUssQ0FBQyxPQUFPLEdBQUcsSUFBSSxDQUFDLEdBQUcsQ0FBQyxFQUFFLEVBQUUsYUFBYSxDQUFDLENBQUM7UUFDakQsSUFBSSxDQUFDLEdBQUcsQ0FBQyxFQUFFLEVBQUUsYUFBYSxDQUFDLENBQzVCLENBQUM7QUFDSixDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgZXhpc3RzU3luYywgbWtkaXJTeW5jIH0gZnJvbSBcImZzXCI7XHJcbmltcG9ydCB7IHRtcGRpciB9IGZyb20gXCJvc1wiO1xyXG5pbXBvcnQgeyBkaXJuYW1lLCBqb2luIH0gZnJvbSBcInBhdGhcIjtcclxuaW1wb3J0IHsgZmlsZVVSTFRvUGF0aCB9IGZyb20gXCJ1cmxcIjtcclxuaW1wb3J0IHsgRm91bmRlciwgTXVuaWNpcGFsaXR5VHlwZSB9IGZyb20gXCIuLi9kYi90eXBlc1wiO1xyXG5cclxuY29uc3QgYXBwTmFtZSA9IFwidGV4dC10by1tYXBcIjtcclxuXHJcbmV4cG9ydCBpbnRlcmZhY2UgT3BlbkRhdGFTeW5jT3B0aW9ucyB7XHJcbiAgdG1wRGlyOiBzdHJpbmc7XHJcbiAgZGF0YURpcjogc3RyaW5nO1xyXG4gIGRiRmlsZVBhdGg6IHN0cmluZztcclxuICBkYkluaXRGaWxlUGF0aDogc3RyaW5nO1xyXG4gIGFkZHJlc3NQb2ludHNBdG9tVXJsOiBzdHJpbmc7XHJcbiAgYWRkcmVzc1BvaW50c1ppcEZpbGVOYW1lOiBzdHJpbmc7XHJcbiAgYWRkcmVzc1BvaW50c0NzdkZvbGRlck5hbWU6IHN0cmluZztcclxuICBzdHJlZXRzQXRvbVVybDogc3RyaW5nO1xyXG4gIHN0cmVldFppcEZvbGRlck5hbWU6IHN0cmluZztcclxuICBzdHJlZXREYmZGaWxlTmFtZTogc3RyaW5nO1xyXG4gIHBvbHlnb25TaHBGaWxlTmFtZTogc3RyaW5nO1xyXG4gIGRpc3RyaWN0UG9seWdvblNocEZpbGVOYW1lOiBzdHJpbmc7XHJcbiAgZGlzdHJpY3RQb2x5Z29uRGJmRmlsZU5hbWU6IHN0cmluZztcclxuICBzY2hvb2xzSnNvbmxkVXJsOiBzdHJpbmc7XHJcbiAgc2Nob29sc0pzb25sZEZpbGVOYW1lOiBzdHJpbmc7XHJcbiAgcmVnaW9uc0NzdlVybDogc3RyaW5nO1xyXG4gIHJlZ2lvbnNTY2hlbWFVcmw6IHN0cmluZztcclxuICByZWdpb25zQ3N2RmlsZU5hbWU6IHN0cmluZztcclxufVxyXG5cclxuZXhwb3J0IHR5cGUgT3BlbkRhdGFTeW5jT3B0aW9uc1BhcnRpYWwgPSBQYXJ0aWFsPE9wZW5EYXRhU3luY09wdGlvbnM+O1xyXG5cclxuZXhwb3J0IGNvbnN0IGdldEFwcERhdGFEaXJQYXRoID0gKCk6IHN0cmluZyA9PlxyXG4gIGpvaW4oXHJcbiAgICBwcm9jZXNzLmVudi5BUFBEQVRBIHx8XHJcbiAgICAgIChwcm9jZXNzLnBsYXRmb3JtID09IFwiZGFyd2luXCJcclxuICAgICAgICA/IHByb2Nlc3MuZW52LkhPTUUgKyBcIi9MaWJyYXJ5L1ByZWZlcmVuY2VzXCJcclxuICAgICAgICA6IHByb2Nlc3MuZW52LkhPTUUgKyBcIi8ubG9jYWwvc2hhcmVcIiksXHJcbiAgICBhcHBOYW1lXHJcbiAgKTtcclxuXHJcbmV4cG9ydCBjb25zdCBwcmVwYXJlT3B0aW9ucyA9IChcclxuICBvcHRpb25zOiBPcGVuRGF0YVN5bmNPcHRpb25zUGFydGlhbFxyXG4pOiBPcGVuRGF0YVN5bmNPcHRpb25zID0+IHtcclxuICBjb25zdCBkYXRhRGlyID0gb3B0aW9ucy5kYXRhRGlyID8/IGdldEFwcERhdGFEaXJQYXRoKCk7XHJcbiAgaWYgKCFleGlzdHNTeW5jKGRhdGFEaXIpKSB7XHJcbiAgICBta2RpclN5bmMoZGF0YURpcik7XHJcbiAgfVxyXG5cclxuICBjb25zdCB0bXBBcHBEaXIgPSBqb2luKHRtcGRpcigpLCBhcHBOYW1lKTtcclxuICBpZiAoIWV4aXN0c1N5bmModG1wQXBwRGlyKSkge1xyXG4gICAgbWtkaXJTeW5jKHRtcEFwcERpcik7XHJcbiAgfVxyXG5cclxuICBjb25zdCBfX2ZpbGVuYW1lID0gZmlsZVVSTFRvUGF0aChpbXBvcnQubWV0YS51cmwpO1xyXG4gIGNvbnN0IF9fZGlybmFtZSA9IGRpcm5hbWUoX19maWxlbmFtZSk7XHJcblxyXG4gIGNvbnN0IGRlZmF1bHRzOiBPcGVuRGF0YVN5bmNPcHRpb25zID0ge1xyXG4gICAgdG1wRGlyOiB0bXBBcHBEaXIsXHJcbiAgICBkYXRhRGlyOiBkYXRhRGlyLFxyXG4gICAgZGJGaWxlUGF0aDogam9pbihkYXRhRGlyLCBcImFkZHJlc3NfcG9pbnRzLmRiXCIpLFxyXG4gICAgZGJJbml0RmlsZVBhdGg6IGpvaW4oX19kaXJuYW1lLCBcIi4uXCIsIFwiYWRkcmVzc19wb2ludHNfaW5pdC5kYlwiKSxcclxuICAgIGFkZHJlc3NQb2ludHNBdG9tVXJsOlxyXG4gICAgICBcImh0dHBzOi8vYXRvbS5jdXprLmN6L1JVSUFOLUNTVi1BRFItU1QvUlVJQU4tQ1NWLUFEUi1TVC54bWxcIixcclxuICAgIGFkZHJlc3NQb2ludHNaaXBGaWxlTmFtZTogXCJydWlhbl9jc3YuemlwXCIsXHJcbiAgICBhZGRyZXNzUG9pbnRzQ3N2Rm9sZGVyTmFtZTogXCJDU1ZcIixcclxuICAgIHN0cmVldHNBdG9tVXJsOiBcImh0dHBzOi8vYXRvbS5jdXprLmN6L1JVSUFOLU9CQ0UtU0hQL1JVSUFOLU9CQ0UtU0hQLnhtbFwiLFxyXG4gICAgc3RyZWV0WmlwRm9sZGVyTmFtZTogXCJzdHJlZXRzXCIsXHJcbiAgICBzdHJlZXREYmZGaWxlTmFtZTogXCJVTF9MLmRiZlwiLFxyXG4gICAgcG9seWdvblNocEZpbGVOYW1lOiBcIk9CRUNfUC5zaHBcIixcclxuICAgIGRpc3RyaWN0UG9seWdvblNocEZpbGVOYW1lOiBcIk1PTUNfUC5zaHBcIixcclxuICAgIGRpc3RyaWN0UG9seWdvbkRiZkZpbGVOYW1lOiBcIk1PTUNfUC5kYmZcIixcclxuICAgIHNjaG9vbHNKc29ubGRVcmw6IFwiaHR0cHM6Ly9sa29kLWZ0cC5tc210Lmdvdi5jei8wMDAyMjk4NS84OGE3YzEyYi02MDg0LTRlNDctOGI1MC00NjA5N2M2ZTY4M2YvUlNTWi1jZWxhLUNSLmpzb25sZFwiLFxyXG4gICAgc2Nob29sc0pzb25sZEZpbGVOYW1lOiBcInNjaG9vbC1yZWdpc3Rlci5qc29ubGRcIixcclxuICAgIHJlZ2lvbnNDc3ZVcmw6XHJcbiAgICAgIFwiaHR0cHM6Ly93d3cuY3pzby5jei9kb2N1bWVudHMvMTAxODAvMjMyMDg2NzQvc3RydWt0dXJhX3V6ZW1pX2NyLmNzdlwiLFxyXG4gICAgcmVnaW9uc1NjaGVtYVVybDpcclxuICAgICAgXCJodHRwczovL3d3dy5jenNvLmN6L2RvY3VtZW50cy8xMDE4MC8yMzIwODY3NC9zdHJ1a3R1cmFfdXplbWlfY3ItbWV0YWRhdGEuanNvblwiLFxyXG4gICAgcmVnaW9uc0NzdkZpbGVOYW1lOiBcInN0cnVrdHVyYV91emVtaV9jci5jc3ZcIixcclxuICB9O1xyXG5cclxuICByZXR1cm4ge1xyXG4gICAgLi4uZGVmYXVsdHMsXHJcbiAgICAuLi5vcHRpb25zLFxyXG4gIH07XHJcbn07XHJcblxyXG5jb25zdCBjaXR5UGF0dGVybnMgPSBbXHJcbiAgL15bc1NddGF0dXTDoXJuw60gbcSbc3RvICsoLiopJC8sXHJcbiAgL15bb09dYmVjICsoLiopJC8sXHJcbiAgL15bbU1dxJtzdG8gKyguKikkLyxcclxuICAvXlttTV3Em3N0eXMgKyguKikkLyxcclxuXTtcclxuXHJcbmNvbnN0IGRpc3RyaWN0UGF0dGVybnMgPSBbXHJcbiAgL15bbU1dxJtzdHNrw6EgxI3DoXN0ICsoLiopJC8sXHJcbiAgL15bbU1dxJtzdHNrw70gb2J2b2QgKyguKikkLyxcclxuICAvXltzU110YXR1dMOhcm7DrSBtxJtzdG8gKy4qLCBbbU1dxJtzdHNrw6EgxI3DoXN0ICsoLiopJC8sXHJcbiAgL15bc1NddGF0dXTDoXJuw60gbcSbc3RvICsuKiwgW21NXcSbc3Rza8O9IG9idm9kICsoLiopJC8sXHJcbl07XHJcblxyXG5leHBvcnQgY29uc3QgZXh0cmFjdE11bmljaXBhbGl0eU5hbWUgPSAoZm91bmRlcjogRm91bmRlcik6IHN0cmluZyA9PiB7XHJcbiAgY29uc3QgcGF0dGVybnMgPVxyXG4gICAgZm91bmRlci5tdW5pY2lwYWxpdHlUeXBlID09PSBNdW5pY2lwYWxpdHlUeXBlLkNpdHlcclxuICAgICAgPyBjaXR5UGF0dGVybnNcclxuICAgICAgOiBkaXN0cmljdFBhdHRlcm5zO1xyXG4gIGNvbnN0IGNvcnJlY3RQYXR0ZXJuID0gcGF0dGVybnMuZmlsdGVyKChwYXR0ZXJuKSA9PlxyXG4gICAgcGF0dGVybi50ZXN0KGZvdW5kZXIubmFtZSlcclxuICApO1xyXG4gIGlmIChjb3JyZWN0UGF0dGVybi5sZW5ndGggPiAwKSB7XHJcbiAgICBjb25zdCByZXN1bHQgPSBjb3JyZWN0UGF0dGVyblswXS5leGVjKGZvdW5kZXIubmFtZSk7XHJcbiAgICBpZiAodHlwZW9mIHJlc3VsdFsxXSAhPT0gXCJ1bmRlZmluZWRcIikge1xyXG4gICAgICByZXR1cm4gcmVzdWx0WzFdXHJcbiAgICAgICAgLnJlcGxhY2UoXCIgLSBcIiwgXCItXCIpXHJcbiAgICAgICAgLnJlcGxhY2UoL1xcc3syLH0vZywgXCIgXCIpXHJcbiAgICAgICAgLnRyaW0oKTtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIHJldHVybiBmb3VuZGVyLm5hbWU7XHJcbn07XHJcblxyXG5leHBvcnQgY29uc3Qgc2FuaXRpemVNdW5pY2lwYWxpdHlOYW1lID0gKG5hbWU6IHN0cmluZyk6IHN0cmluZyA9PiB7XHJcbiAgcmV0dXJuIG5hbWVcclxuICAgIC5yZXBsYWNlKFwiIC0gXCIsIFwiLVwiKVxyXG4gICAgLnJlcGxhY2UoL1xcc3syLH0vZywgXCIgXCIpXHJcbiAgICAudHJpbSgpO1xyXG59O1xyXG5cclxuZXhwb3J0IGNvbnN0IGZpbmRDbG9zZXN0U3RyaW5nID0gKFxyXG4gIHN0cjogc3RyaW5nLFxyXG4gIGFycjogc3RyaW5nW10sXHJcbiAgbWF4RGlzdGFuY2U/OiBudW1iZXJcclxuKTogc3RyaW5nIHwgbnVsbCA9PiB7XHJcbiAgbGV0IGNsb3Nlc3RTdHIgPSBcIlwiO1xyXG4gIGxldCBjbG9zZXN0RGlzdGFuY2UgPSBOdW1iZXIuTUFYX1NBRkVfSU5URUdFUjtcclxuXHJcbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBhcnIubGVuZ3RoOyBpKyspIHtcclxuICAgIGNvbnN0IGN1cnJlbnRTdHIgPSBhcnJbaV07XHJcbiAgICBjb25zdCBkaXN0YW5jZSA9IGludGVycHVuY3Rpb25EaXN0YW5jZShzdHIsIGN1cnJlbnRTdHIpO1xyXG5cclxuICAgIGlmIChkaXN0YW5jZSA8IGNsb3Nlc3REaXN0YW5jZSkge1xyXG4gICAgICBjbG9zZXN0U3RyID0gY3VycmVudFN0cjtcclxuICAgICAgY2xvc2VzdERpc3RhbmNlID0gZGlzdGFuY2U7XHJcbiAgICB9XHJcblxyXG4gICAgLy8gZXhhY3QgbWF0Y2ggZm91bmQsIGV4aXQgbG9vcFxyXG4gICAgaWYgKGNsb3Nlc3REaXN0YW5jZSA9PT0gMCkge1xyXG4gICAgICBicmVhaztcclxuICAgIH1cclxuICB9XHJcblxyXG4gIGlmIChtYXhEaXN0YW5jZSAhPT0gdW5kZWZpbmVkICYmIGNsb3Nlc3REaXN0YW5jZSA+IG1heERpc3RhbmNlKSB7XHJcbiAgICByZXR1cm4gXCJcIjtcclxuICB9XHJcblxyXG4gIHJldHVybiBjbG9zZXN0U3RyO1xyXG59O1xyXG5cclxuY29uc3QgaW50ZXJwdW5jdGlvbkRpc3RhbmNlID0gKHN0cjE6IHN0cmluZywgc3RyMjogc3RyaW5nKTogbnVtYmVyID0+IHtcclxuICBsZXQgZGlzdGFuY2UgPSBsZXZlbnNodGVpbkRpc3RhbmNlKHN0cjEsIHN0cjIpO1xyXG5cclxuICBjb25zdCBpbnRlcnB1bmN0aW9uTWlzdGFrZXMgPSB7XHJcbiAgICBhOiBbXCLDoVwiXSxcclxuICAgIMOhOiBbXCJhXCJdLFxyXG4gICAgZTogW1wiw6lcIiwgXCLEm1wiXSxcclxuICAgIMOpOiBbXCJlXCIsIFwixJtcIl0sXHJcbiAgICDEmzogW1wiZVwiLCBcIsOpXCJdLFxyXG4gICAgaTogW1wiw61cIl0sXHJcbiAgICDDrTogW1wiaVwiXSxcclxuICAgIHk6IFtcIsO9XCJdLFxyXG4gICAgw706IFtcInlcIl0sXHJcbiAgICBvOiBbXCLDs1wiXSxcclxuICAgIMOzOiBbXCJvXCJdLFxyXG4gICAgdTogW1wiw7pcIiwgXCLFr1wiXSxcclxuICAgIMWvOiBbXCJ1XCIsIFwiw7pcIl0sXHJcbiAgICDDujogW1widVwiLCBcIsWvXCJdLFxyXG4gICAgYzogW1wixI1cIl0sXHJcbiAgICDEjTogW1wiY1wiXSxcclxuICAgIGQ6IFtcIsSPXCJdLFxyXG4gICAgxI86IFtcImRcIl0sXHJcbiAgICBuOiBbXCLFiFwiXSxcclxuICAgIMWIOiBbXCJuXCJdLFxyXG4gICAgcjogW1wixZlcIl0sXHJcbiAgICDFmTogW1wiclwiXSxcclxuICAgIHM6IFtcIsWhXCJdLFxyXG4gICAgxaE6IFtcInNcIl0sXHJcbiAgICB0OiBbXCLFpVwiXSxcclxuICAgIMWlOiBbXCJ0XCJdLFxyXG4gICAgejogW1wixb5cIl0sXHJcbiAgICDFvjogW1wielwiXSxcclxuICB9O1xyXG5cclxuICBjb25zdCBzdHIxQ2hhcnMgPSBzdHIxLnNwbGl0KFwiXCIpO1xyXG4gIGNvbnN0IHN0cjJDaGFycyA9IHN0cjIuc3BsaXQoXCJcIik7XHJcblxyXG4gIGZvciAobGV0IGkgPSAwOyBpIDwgc3RyMUNoYXJzLmxlbmd0aDsgaSsrKSB7XHJcbiAgICBjb25zdCBjaGFyMSA9IHN0cjFDaGFyc1tpXTtcclxuICAgIGNvbnN0IGNoYXIyID0gc3RyMkNoYXJzW2ldO1xyXG5cclxuICAgIGlmIChcclxuICAgICAgaW50ZXJwdW5jdGlvbk1pc3Rha2VzW2NoYXIxXSAmJlxyXG4gICAgICBpbnRlcnB1bmN0aW9uTWlzdGFrZXNbY2hhcjFdLmluY2x1ZGVzKGNoYXIyKVxyXG4gICAgKSB7XHJcbiAgICAgIC8vIFN1YnRyYWN0IGEgcGVuYWx0eSBmcm9tIHRoZSBkaXN0YW5jZSBmb3IgaW50ZXJwdW5jdGlvbiBtaXN0YWtlc1xyXG4gICAgICBkaXN0YW5jZSAtPSAwLjU7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICByZXR1cm4gZGlzdGFuY2U7XHJcbn07XHJcblxyXG5jb25zdCBsZXZlbnNodGVpbkRpc3RhbmNlID0gKHN0cjE6IHN0cmluZywgc3RyMjogc3RyaW5nKTogbnVtYmVyID0+IHtcclxuICBjb25zdCBtYXRyaXg6IG51bWJlcltdW10gPSBBcnJheShzdHIyLmxlbmd0aCArIDEpXHJcbiAgICAuZmlsbChudWxsKVxyXG4gICAgLm1hcCgoKSA9PiBBcnJheShzdHIxLmxlbmd0aCArIDEpLmZpbGwobnVsbCkpO1xyXG5cclxuICBmb3IgKGxldCBpID0gMDsgaSA8PSBzdHIxLmxlbmd0aDsgaSsrKSB7XHJcbiAgICBtYXRyaXhbMF1baV0gPSBpO1xyXG4gIH1cclxuXHJcbiAgZm9yIChsZXQgaiA9IDA7IGogPD0gc3RyMi5sZW5ndGg7IGorKykge1xyXG4gICAgbWF0cml4W2pdWzBdID0gajtcclxuICB9XHJcblxyXG4gIGZvciAobGV0IGogPSAxOyBqIDw9IHN0cjIubGVuZ3RoOyBqKyspIHtcclxuICAgIGZvciAobGV0IGkgPSAxOyBpIDw9IHN0cjEubGVuZ3RoOyBpKyspIHtcclxuICAgICAgaWYgKHN0cjFbaSAtIDFdID09PSBzdHIyW2ogLSAxXSkge1xyXG4gICAgICAgIG1hdHJpeFtqXVtpXSA9IG1hdHJpeFtqIC0gMV1baSAtIDFdO1xyXG4gICAgICB9IGVsc2Uge1xyXG4gICAgICAgIG1hdHJpeFtqXVtpXSA9XHJcbiAgICAgICAgICBNYXRoLm1pbihcclxuICAgICAgICAgICAgbWF0cml4W2pdW2kgLSAxXSwgLy8gZGVsZXRpb25cclxuICAgICAgICAgICAgbWF0cml4W2ogLSAxXVtpXSwgLy8gaW5zZXJ0aW9uXHJcbiAgICAgICAgICAgIG1hdHJpeFtqIC0gMV1baSAtIDFdIC8vIHN1YnN0aXR1dGlvblxyXG4gICAgICAgICAgKSArIDE7XHJcbiAgICAgIH1cclxuICAgIH1cclxuICB9XHJcblxyXG4gIHJldHVybiBtYXRyaXhbc3RyMi5sZW5ndGhdW3N0cjEubGVuZ3RoXTtcclxufTtcclxuXHJcbmV4cG9ydCBmdW5jdGlvbiByb3VuZFRvTkRlY2ltYWxQbGFjZXMoXHJcbiAgdG9Sb3VuZDogbnVtYmVyLFxyXG4gIGRlY2ltYWxQbGFjZXM6IG51bWJlclxyXG4pOiBudW1iZXIge1xyXG4gIHJldHVybiAoXHJcbiAgICBNYXRoLnJvdW5kKHRvUm91bmQgKiBNYXRoLnBvdygxMCwgZGVjaW1hbFBsYWNlcykpIC9cclxuICAgIE1hdGgucG93KDEwLCBkZWNpbWFsUGxhY2VzKVxyXG4gICk7XHJcbn1cclxuIl19