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
JavaScript
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