text-to-map 1.0.6 → 1.0.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/address_points_init.db +0 -0
- package/dist/bin/address-points.js +2 -1
- package/dist/bin/clear-all.js +3 -2
- package/dist/bin/constants.d.ts +2 -0
- package/dist/bin/constants.js +3 -0
- package/dist/bin/parse-ordinance.js +28 -2
- package/dist/bin/regions.js +2 -1
- package/dist/bin/schools.js +2 -1
- package/dist/bin/streets.js +2 -1
- package/dist/bin/sync-all.js +2 -1
- package/dist/db/address-points.d.ts +2 -2
- package/dist/db/address-points.js +5 -1
- package/dist/db/db.js +2 -0
- package/dist/db/founders.d.ts +3 -3
- package/dist/db/founders.js +26 -4
- package/dist/db/schools.d.ts +2 -1
- package/dist/db/schools.js +6 -2
- package/dist/index.d.ts +4 -4
- package/dist/index.js +2 -2
- package/dist/open-data-sync/address-points.d.ts +3 -3
- package/dist/open-data-sync/regions.d.ts +2 -2
- package/dist/open-data-sync/schools.d.ts +3 -3
- package/dist/open-data-sync/schools.js +2 -2
- package/dist/open-data-sync/streets.d.ts +2 -2
- package/dist/open-data-sync/streets.js +1 -1
- package/dist/street-markdown/municipality.js +31 -8
- package/dist/street-markdown/smd-line-parser.d.ts +1 -1
- package/dist/street-markdown/smd-line-parser.js +18 -8
- package/dist/street-markdown/smd.d.ts +9 -7
- package/dist/street-markdown/smd.js +177 -136
- package/dist/street-markdown/token-definition.js +6 -6
- package/dist/street-markdown/types.d.ts +31 -3
- package/dist/utils/helpers.d.ts +4 -20
- package/dist/utils/helpers.js +17 -16
- package/package.json +1 -1
|
Binary file
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { downloadAndImportAddressPoints } from "../open-data-sync/address-points";
|
|
2
|
+
import { defaultBinOptions } from "./constants";
|
|
2
3
|
console.time("downloadAndImportAllLatestAddressPoints");
|
|
3
|
-
downloadAndImportAddressPoints(
|
|
4
|
+
downloadAndImportAddressPoints(defaultBinOptions)
|
|
4
5
|
.then(() => {
|
|
5
6
|
console.timeEnd("downloadAndImportAllLatestAddressPoints");
|
|
6
7
|
})
|
package/dist/bin/clear-all.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { deleteDb } from "../open-data-sync/address-points";
|
|
2
2
|
import { deleteSchoolsXmlFile } from "../open-data-sync/schools";
|
|
3
|
-
|
|
4
|
-
|
|
3
|
+
import { defaultBinOptions } from "./constants";
|
|
4
|
+
deleteDb(defaultBinOptions);
|
|
5
|
+
deleteSchoolsXmlFile(defaultBinOptions);
|
|
5
6
|
console.log("Everything cleared, ready for a new sync.");
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { readFileSync, writeFileSync } from "fs";
|
|
2
|
-
import { parseOrdinanceToAddressPoints } from "../street-markdown/smd";
|
|
2
|
+
import { getNewMunicipality, parseOrdinanceToAddressPoints, } from "../street-markdown/smd";
|
|
3
|
+
import { defaultBinOptions } from "./constants";
|
|
3
4
|
// take first node argument as a file name
|
|
4
5
|
if (process.argv.length < 3) {
|
|
5
6
|
console.error("Missing file name argument");
|
|
@@ -8,7 +9,32 @@ if (process.argv.length < 3) {
|
|
|
8
9
|
const fileName = process.argv[2];
|
|
9
10
|
const fileContent = readFileSync(fileName);
|
|
10
11
|
const lines = fileContent.toString().split("\n");
|
|
11
|
-
|
|
12
|
+
let errorCount = 0;
|
|
13
|
+
const errorLines = [];
|
|
14
|
+
let warningCount = 0;
|
|
15
|
+
const reportErrors = ({ lineNumber, line, errors, }) => {
|
|
16
|
+
errors.forEach((error) => console.error(error));
|
|
17
|
+
console.error(`Invalid street definition on line ${lineNumber}: ${line}`);
|
|
18
|
+
errorCount++;
|
|
19
|
+
errorLines.push(`line ${lineNumber}: ${line}`);
|
|
20
|
+
};
|
|
21
|
+
const reportWarnings = ({ lineNumber, errors: warnings, }) => {
|
|
22
|
+
warnings.forEach((error) => {
|
|
23
|
+
console.error(`Line ${lineNumber}: ${error.message}`);
|
|
24
|
+
});
|
|
25
|
+
warningCount++;
|
|
26
|
+
};
|
|
27
|
+
console.time("downloadAndImportAllLatestAddressPoints");
|
|
28
|
+
const { municipality } = getNewMunicipality("Česká Lípa", defaultBinOptions);
|
|
29
|
+
const addressPoints = parseOrdinanceToAddressPoints(lines, defaultBinOptions, {
|
|
30
|
+
// currentMunicipality: municipality,
|
|
31
|
+
}, reportErrors, reportWarnings);
|
|
32
|
+
console.timeEnd("downloadAndImportAllLatestAddressPoints");
|
|
33
|
+
console.log(`Parsed ${lines.length} lines, ${errorCount} errors, ${warningCount} warnings.`);
|
|
34
|
+
if (errorCount > 0) {
|
|
35
|
+
console.log("Errors:");
|
|
36
|
+
errorLines.forEach((line) => console.log(line));
|
|
37
|
+
}
|
|
12
38
|
if (process.argv.length >= 4) {
|
|
13
39
|
const outputFileName = process.argv[3];
|
|
14
40
|
const output = JSON.stringify(addressPoints);
|
package/dist/bin/regions.js
CHANGED
package/dist/bin/schools.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { downloadAndImportSchools } from "../open-data-sync/schools";
|
|
2
|
-
|
|
2
|
+
import { defaultBinOptions } from "./constants";
|
|
3
|
+
downloadAndImportSchools(defaultBinOptions, true)
|
|
3
4
|
.then(() => {
|
|
4
5
|
console.log("Completed");
|
|
5
6
|
})
|
package/dist/bin/streets.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { downloadAndImportStreets } from "../open-data-sync/streets";
|
|
2
|
+
import { defaultBinOptions } from "./constants";
|
|
2
3
|
console.time("downloadAndImportAllStreets");
|
|
3
|
-
downloadAndImportStreets(
|
|
4
|
+
downloadAndImportStreets(defaultBinOptions)
|
|
4
5
|
.then(() => {
|
|
5
6
|
console.timeEnd("downloadAndImportAllStreets");
|
|
6
7
|
})
|
package/dist/bin/sync-all.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { AddressPoint, FullStreetNumber, RangeSpec, SeriesType, SmdLine, WholeMunicipalitySmdLine } from "../street-markdown/types";
|
|
1
|
+
import { AddressPoint, FullStreetNumber, RangeSpec, SeriesType, SmdError, SmdLine, WholeMunicipalitySmdLine } from "../street-markdown/types";
|
|
2
2
|
import { Founder, Municipality } from "./types";
|
|
3
3
|
export declare const Column: {
|
|
4
4
|
admCode: number;
|
|
@@ -31,7 +31,7 @@ export declare const insertStreets: (buffer: string[][]) => number;
|
|
|
31
31
|
export declare const getAddressPointById: (addressPointId: number) => AddressPoint | null;
|
|
32
32
|
export declare const checkStreetExists: (streetName: string, founder: Founder) => {
|
|
33
33
|
exists: boolean;
|
|
34
|
-
errors:
|
|
34
|
+
errors: SmdError[];
|
|
35
35
|
};
|
|
36
36
|
export declare const findAddressPoints: (smdLine: SmdLine | WholeMunicipalitySmdLine, municipality: Municipality) => AddressPoint[];
|
|
37
37
|
export declare const isInRange: (number: number | null, letter: string | null, range: RangeSpec) => boolean;
|
|
@@ -153,7 +153,11 @@ export const checkStreetExists = (streetName, founder) => {
|
|
|
153
153
|
}
|
|
154
154
|
else {
|
|
155
155
|
const closest = findClosestString(streetName, allStreets);
|
|
156
|
-
errors.push(
|
|
156
|
+
errors.push({
|
|
157
|
+
message: `Ulice '${streetName}' v této obci neexistuje, mysleli jste '${closest}'?`,
|
|
158
|
+
startOffset: 0,
|
|
159
|
+
endOffset: streetName.length + 1,
|
|
160
|
+
});
|
|
157
161
|
}
|
|
158
162
|
return { exists: false, errors };
|
|
159
163
|
};
|
package/dist/db/db.js
CHANGED
|
@@ -23,6 +23,8 @@ export const getDb = (config = {}) => {
|
|
|
23
23
|
const dbSettings = options.verbose ? { verbose: console.log } : {};
|
|
24
24
|
_db = new Database(options.filePath, dbSettings);
|
|
25
25
|
_db.pragma("journal_mode = WAL");
|
|
26
|
+
// @ts-ignore
|
|
27
|
+
_db.filePath = options.filePath;
|
|
26
28
|
}
|
|
27
29
|
return _db;
|
|
28
30
|
};
|
package/dist/db/founders.d.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { Founder, MunicipalityType } from "./types";
|
|
2
|
-
import { DbMunicipalityResult } from "../street-markdown/types";
|
|
2
|
+
import { DbMunicipalityResult, SmdError } from "../street-markdown/types";
|
|
3
3
|
export declare const insertFounders: (founders: Founder[]) => number;
|
|
4
|
-
export declare const findFounder: (
|
|
4
|
+
export declare const findFounder: (nameWithHashtag: string) => {
|
|
5
5
|
founder: Founder;
|
|
6
|
-
errors:
|
|
6
|
+
errors: SmdError[];
|
|
7
7
|
};
|
|
8
8
|
export declare const getFounderCityCode: (founder: Founder) => number;
|
|
9
9
|
export declare const findMunicipalityByNameAndType: (name: string, type: MunicipalityType) => DbMunicipalityResult;
|
package/dist/db/founders.js
CHANGED
|
@@ -2,6 +2,7 @@ import { MunicipalityType, } from "./types";
|
|
|
2
2
|
import { generatePlaceholders, getDb, insertAutoincrementRow, insertMultipleRows, } from "./db";
|
|
3
3
|
import { extractMunicipalityName, findClosestString, sanitizeMunicipalityName, } from "../utils/helpers";
|
|
4
4
|
import distance from "@turf/distance";
|
|
5
|
+
import { wholeLineError } from "../street-markdown/smd";
|
|
5
6
|
const cityTypeCode = 261;
|
|
6
7
|
const cityDistrictTypeCode = 263;
|
|
7
8
|
export const insertFounders = (founders) => {
|
|
@@ -61,11 +62,12 @@ export const insertFounders = (founders) => {
|
|
|
61
62
|
}
|
|
62
63
|
const founderId = insertAutoincrementRow([
|
|
63
64
|
sanitizeMunicipalityName(founder.name),
|
|
65
|
+
sanitizeMunicipalityName(extractedMunicipalityName),
|
|
64
66
|
founder.ico,
|
|
65
67
|
String(founder.originalType),
|
|
66
68
|
cityCode,
|
|
67
69
|
cityDistrictCode,
|
|
68
|
-
], "founder", ["name", "ico", "founder_type_code", "city_code", "city_district_code"]);
|
|
70
|
+
], "founder", ["name", "short_name", "ico", "founder_type_code", "city_code", "city_district_code"]);
|
|
69
71
|
// founder table has unique (name, ico) with on conflict ignore, so possibly
|
|
70
72
|
// the row has not been inserted
|
|
71
73
|
if (founderId !== null) {
|
|
@@ -177,9 +179,18 @@ const findMunicipalitiesAndPositionsByNameAndType = (name, type) => {
|
|
|
177
179
|
lng: row.wgs84_longitude,
|
|
178
180
|
}));
|
|
179
181
|
};
|
|
180
|
-
|
|
182
|
+
const extractFounderName = (line) => {
|
|
183
|
+
if (line[0] === "#") {
|
|
184
|
+
return line.substring(1).trim();
|
|
185
|
+
}
|
|
186
|
+
else {
|
|
187
|
+
return line.trim();
|
|
188
|
+
}
|
|
189
|
+
};
|
|
190
|
+
export const findFounder = (nameWithHashtag) => {
|
|
181
191
|
const errors = [];
|
|
182
192
|
const db = getDb();
|
|
193
|
+
const name = extractFounderName(nameWithHashtag);
|
|
183
194
|
const exactMatchStatement = db.prepare(`SELECT f.id, f.name, f.ico, f.founder_type_code, f.city_code, f.city_district_code FROM founder f
|
|
184
195
|
LEFT JOIN city c ON c.code = f.city_code
|
|
185
196
|
LEFT JOIN city_district d ON d.code = f.city_district_code
|
|
@@ -196,7 +207,14 @@ export const findFounder = (name) => {
|
|
|
196
207
|
const bestMatch = findClosestString(name, namesList);
|
|
197
208
|
const bestMatchRow = allFounderNames.find((foundersNames) => foundersNames.founderName === bestMatch ||
|
|
198
209
|
foundersNames.municipalityName === bestMatch);
|
|
199
|
-
|
|
210
|
+
if (!bestMatchRow) {
|
|
211
|
+
errors.push(wholeLineError(`Nenašli jsme žádné zřizovatele, nejspíš jste zapomněli inicializovat databázi.`, nameWithHashtag));
|
|
212
|
+
return {
|
|
213
|
+
founder: null,
|
|
214
|
+
errors,
|
|
215
|
+
};
|
|
216
|
+
}
|
|
217
|
+
errors.push(wholeLineError(`Zřizovatel '${name}' neexistuje, mysleli jste '${bestMatch}'?`, nameWithHashtag));
|
|
200
218
|
const findByIdStatement = db.prepare(`SELECT f.id, f.name, f.ico, f.founder_type_code, f.city_code, f.city_district_code FROM founder f
|
|
201
219
|
WHERE f.id = ?`);
|
|
202
220
|
return {
|
|
@@ -281,7 +299,11 @@ export const findMunicipalityByNameAndType = (name, type) => {
|
|
|
281
299
|
const namesList = allNames.map((row) => row.name);
|
|
282
300
|
const bestMatch = findClosestString(name, namesList);
|
|
283
301
|
const bestMatchRow = allNames.find((municipality) => municipality.name === bestMatch);
|
|
284
|
-
errors.push(
|
|
302
|
+
errors.push({
|
|
303
|
+
message: `Obec ani městská část '${name}' neexistuje, mysleli jste '${bestMatch}'?`,
|
|
304
|
+
startOffset: 0,
|
|
305
|
+
endOffset: 0,
|
|
306
|
+
});
|
|
285
307
|
return {
|
|
286
308
|
municipality: { code: bestMatchRow.code, type },
|
|
287
309
|
errors,
|
package/dist/db/schools.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
|
+
import { SmdError } from "../street-markdown/types";
|
|
1
2
|
import { School } from "./types";
|
|
2
3
|
export declare const insertSchools: (schools: School[]) => number;
|
|
3
4
|
export declare const findSchool: (name: string, schools: School[]) => {
|
|
4
5
|
school: School | null;
|
|
5
|
-
errors:
|
|
6
|
+
errors: SmdError[];
|
|
6
7
|
};
|
package/dist/db/schools.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { wholeLineError } from "../street-markdown/smd";
|
|
1
2
|
import { findClosestString } from "../utils/helpers";
|
|
2
3
|
import { getDb, insertMultipleRows } from "./db";
|
|
3
4
|
export const insertSchools = (schools) => {
|
|
@@ -35,7 +36,10 @@ export const insertSchools = (schools) => {
|
|
|
35
36
|
};
|
|
36
37
|
export const findSchool = (name, schools) => {
|
|
37
38
|
if (schools.length === 0) {
|
|
38
|
-
return {
|
|
39
|
+
return {
|
|
40
|
+
school: null,
|
|
41
|
+
errors: [wholeLineError("Aktuální zřizovatel nemá žádné školy.", name)],
|
|
42
|
+
};
|
|
39
43
|
}
|
|
40
44
|
let school = null;
|
|
41
45
|
const errors = [];
|
|
@@ -46,7 +50,7 @@ export const findSchool = (name, schools) => {
|
|
|
46
50
|
const namesList = schools.map((school) => school.name);
|
|
47
51
|
const bestMatch = findClosestString(name, namesList);
|
|
48
52
|
school = schools.find((school) => bestMatch === school.name);
|
|
49
|
-
errors.push(
|
|
53
|
+
errors.push(wholeLineError(`Škola s názvem '${name}' neexistuje, mysleli jste '${bestMatch}'?`, name));
|
|
50
54
|
return { school, errors };
|
|
51
55
|
};
|
|
52
56
|
const filterOutDuplicates = (schools) => {
|
package/dist/index.d.ts
CHANGED
|
@@ -2,9 +2,9 @@ import { downloadAndImportAddressPoints, deleteDb } from "./open-data-sync/addre
|
|
|
2
2
|
import { downloadAndImportRegions } from "./open-data-sync/regions";
|
|
3
3
|
import { downloadAndImportSchools } from "./open-data-sync/schools";
|
|
4
4
|
import { downloadAndImportStreets } from "./open-data-sync/streets";
|
|
5
|
-
import {
|
|
6
|
-
import { OpenDataSyncOptions } from "./utils/helpers";
|
|
5
|
+
import { OpenDataSyncOptionsPartial } from "./utils/helpers";
|
|
7
6
|
export * from "./street-markdown/types";
|
|
7
|
+
export * from "./street-markdown/smd";
|
|
8
8
|
/**
|
|
9
9
|
* Download and import all open data to SQLite DB. The DB file will be located
|
|
10
10
|
* in the `dataDir` folder.
|
|
@@ -16,5 +16,5 @@ export * from "./street-markdown/types";
|
|
|
16
16
|
* await downloadAndImportEverything({ tmpDir: "./tmp", dataDir: "./data" });
|
|
17
17
|
* ```
|
|
18
18
|
*/
|
|
19
|
-
export declare function downloadAndImportEverything(options?:
|
|
20
|
-
export { downloadAndImportAddressPoints, deleteDb, downloadAndImportSchools, downloadAndImportStreets, downloadAndImportRegions,
|
|
19
|
+
export declare function downloadAndImportEverything(options?: OpenDataSyncOptionsPartial, syncStreets?: boolean): Promise<void>;
|
|
20
|
+
export { downloadAndImportAddressPoints, deleteDb, downloadAndImportSchools, downloadAndImportStreets, downloadAndImportRegions, };
|
package/dist/index.js
CHANGED
|
@@ -11,8 +11,8 @@ import { downloadAndImportAddressPoints, deleteDb, } from "./open-data-sync/addr
|
|
|
11
11
|
import { downloadAndImportRegions } from "./open-data-sync/regions";
|
|
12
12
|
import { downloadAndImportSchools } from "./open-data-sync/schools";
|
|
13
13
|
import { downloadAndImportStreets } from "./open-data-sync/streets";
|
|
14
|
-
import { parseOrdinanceToAddressPoints } from "./street-markdown/smd";
|
|
15
14
|
export * from "./street-markdown/types";
|
|
15
|
+
export * from "./street-markdown/smd";
|
|
16
16
|
/**
|
|
17
17
|
* Download and import all open data to SQLite DB. The DB file will be located
|
|
18
18
|
* in the `dataDir` folder.
|
|
@@ -34,4 +34,4 @@ export function downloadAndImportEverything(options = {}, syncStreets = true) {
|
|
|
34
34
|
}
|
|
35
35
|
});
|
|
36
36
|
}
|
|
37
|
-
export { downloadAndImportAddressPoints, deleteDb, downloadAndImportSchools, downloadAndImportStreets, downloadAndImportRegions,
|
|
37
|
+
export { downloadAndImportAddressPoints, deleteDb, downloadAndImportSchools, downloadAndImportStreets, downloadAndImportRegions, };
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import {
|
|
2
|
-
export declare const downloadAndImportAddressPoints: (options?:
|
|
3
|
-
export declare const deleteDb: (options?:
|
|
1
|
+
import { OpenDataSyncOptionsPartial } from "../utils/helpers";
|
|
2
|
+
export declare const downloadAndImportAddressPoints: (options?: OpenDataSyncOptionsPartial) => Promise<void>;
|
|
3
|
+
export declare const deleteDb: (options?: OpenDataSyncOptionsPartial) => void;
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import {
|
|
2
|
-
export declare const downloadAndImportRegions: (options?:
|
|
1
|
+
import { OpenDataSyncOptionsPartial } from "../utils/helpers";
|
|
2
|
+
export declare const downloadAndImportRegions: (options?: OpenDataSyncOptionsPartial) => Promise<void>;
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import {
|
|
2
|
-
export declare const downloadAndImportSchools: (options:
|
|
3
|
-
export declare const deleteSchoolsXmlFile: (options?:
|
|
1
|
+
import { OpenDataSyncOptionsPartial } from "../utils/helpers";
|
|
2
|
+
export declare const downloadAndImportSchools: (options: OpenDataSyncOptionsPartial, saveFoundersToCsv?: boolean, saveSchoolsWithoutRuianToCsv?: boolean) => Promise<void>;
|
|
3
|
+
export declare const deleteSchoolsXmlFile: (options?: OpenDataSyncOptionsPartial) => void;
|
|
@@ -303,10 +303,10 @@ const importDataToDb = (options, saveFoundersToCsv = false, saveSchoolsWithoutRu
|
|
|
303
303
|
const getXmlFilePath = (options) => {
|
|
304
304
|
return join(options.tmpDir, options.schoolsXmlFileName);
|
|
305
305
|
};
|
|
306
|
-
export const downloadAndImportSchools = (options) => __awaiter(void 0, void 0, void 0, function* () {
|
|
306
|
+
export const downloadAndImportSchools = (options, saveFoundersToCsv = false, saveSchoolsWithoutRuianToCsv = false) => __awaiter(void 0, void 0, void 0, function* () {
|
|
307
307
|
const runOptions = prepareOptions(options);
|
|
308
308
|
yield downloadXml(runOptions);
|
|
309
|
-
yield importDataToDb(runOptions,
|
|
309
|
+
yield importDataToDb(runOptions, saveFoundersToCsv, saveSchoolsWithoutRuianToCsv);
|
|
310
310
|
deleteSchoolsXmlFile(runOptions);
|
|
311
311
|
});
|
|
312
312
|
export const deleteSchoolsXmlFile = (options = {}) => {
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import {
|
|
2
|
-
export declare const downloadAndImportStreets: (options:
|
|
1
|
+
import { OpenDataSyncOptionsPartial } from "../utils/helpers";
|
|
2
|
+
export declare const downloadAndImportStreets: (options: OpenDataSyncOptionsPartial) => Promise<void>;
|
|
@@ -23,7 +23,7 @@ const prepareFolders = (options) => {
|
|
|
23
23
|
}
|
|
24
24
|
};
|
|
25
25
|
const getTempFolder = (options) => {
|
|
26
|
-
return join(options.tmpDir, options.
|
|
26
|
+
return join(options.tmpDir, options.streetZipFolderName);
|
|
27
27
|
};
|
|
28
28
|
const downloadZipAndParseDbfFile = (url, index, options) => __awaiter(void 0, void 0, void 0, function* () {
|
|
29
29
|
const response = yield fetch(url);
|
|
@@ -1,35 +1,58 @@
|
|
|
1
1
|
import { findMunicipalityByNameAndType } from "../db/founders";
|
|
2
2
|
import { MunicipalityType } from "../db/types";
|
|
3
|
+
const municipalitySwitchStartPattern = /^navíc ulice /;
|
|
3
4
|
const municipalitySwitchPattern = /^navíc ulice (z )?(?<type>městské části|městského obvodu|obce|města) (?<name>.+):$/;
|
|
5
|
+
const wholeMunicipalityStartPattern = /^území /;
|
|
4
6
|
const wholeMunicipalityPattern = /^území (?<type>městské části|městského obvodu|obce|města) (?<name>.+)$/;
|
|
5
7
|
export const isMunicipalitySwitch = (line) => {
|
|
6
|
-
return
|
|
8
|
+
return municipalitySwitchStartPattern.test(line);
|
|
7
9
|
};
|
|
8
10
|
export const getSwitchMunicipality = (line) => {
|
|
9
11
|
const match = municipalitySwitchPattern.exec(line);
|
|
10
12
|
if (match === null) {
|
|
11
|
-
|
|
13
|
+
return {
|
|
14
|
+
errors: [
|
|
15
|
+
{
|
|
16
|
+
message: "Neplatný zápis pro dočasnou změnu obce v definici ulic. Správný zápis je: navíc ulice <typ> <název obce>. Např.: 'navíc ulice obce Mokrá Lhota:' (název obce musí být v 1. pádě).",
|
|
17
|
+
startOffset: 0,
|
|
18
|
+
endOffset: line.length + 1,
|
|
19
|
+
},
|
|
20
|
+
],
|
|
21
|
+
municipality: null,
|
|
22
|
+
};
|
|
12
23
|
}
|
|
13
24
|
const { type, name } = match.groups;
|
|
14
|
-
return getMunicipalityResult(type, name);
|
|
25
|
+
return getMunicipalityResult(type, name, line);
|
|
15
26
|
};
|
|
16
27
|
export const isWholeMunicipality = (line) => {
|
|
17
|
-
return
|
|
28
|
+
return wholeMunicipalityStartPattern.test(line);
|
|
18
29
|
};
|
|
19
30
|
export const getWholeMunicipality = (line) => {
|
|
20
31
|
const match = wholeMunicipalityPattern.exec(line);
|
|
21
32
|
if (match === null) {
|
|
22
|
-
return {
|
|
33
|
+
return {
|
|
34
|
+
errors: [
|
|
35
|
+
{
|
|
36
|
+
message: "Neplatný zápis pro přidání celé obce. Správný zápis je: území <typ> <název obce>. Např.: 'území obce Kladno' (název obce musí být v 1. pádě).",
|
|
37
|
+
startOffset: 0,
|
|
38
|
+
endOffset: line.length + 1,
|
|
39
|
+
},
|
|
40
|
+
],
|
|
41
|
+
municipality: null,
|
|
42
|
+
};
|
|
23
43
|
}
|
|
24
44
|
const { type, name } = match.groups;
|
|
25
|
-
return getMunicipalityResult(type, name);
|
|
45
|
+
return getMunicipalityResult(type, name, line);
|
|
26
46
|
};
|
|
27
|
-
const getMunicipalityResult = (type, name) => {
|
|
47
|
+
const getMunicipalityResult = (type, name, line) => {
|
|
28
48
|
const typeValue = getMunicipalityType(type);
|
|
29
49
|
const { municipality, errors } = findMunicipalityByNameAndType(name, typeValue);
|
|
50
|
+
const startOffset = line.indexOf(name);
|
|
51
|
+
const endOffset = startOffset + name.length + 1;
|
|
30
52
|
return {
|
|
31
53
|
municipality,
|
|
32
|
-
errors,
|
|
54
|
+
errors: errors.map((error) => (Object.assign(Object.assign({}, error), { startOffset,
|
|
55
|
+
endOffset }))),
|
|
33
56
|
};
|
|
34
57
|
};
|
|
35
58
|
const getMunicipalityType = (type) => {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import { SmdParser } from "./smd-parser";
|
|
2
2
|
import { ProcessedSmdLines } from "./types";
|
|
3
3
|
export declare const smdParser: SmdParser;
|
|
4
|
-
export declare const parseLine: (text: string) => ProcessedSmdLines;
|
|
4
|
+
export declare const parseLine: (text: string, showDebug?: boolean) => ProcessedSmdLines;
|
|
@@ -1,29 +1,39 @@
|
|
|
1
1
|
import { Lexer } from "chevrotain";
|
|
2
2
|
import { SmdParser } from "./smd-parser";
|
|
3
|
-
// const token_definition = require("token_definition");
|
|
4
3
|
import { tokenVocabulary, smdTokens, resetTokenState, prepareLine, } from "./token-definition";
|
|
5
4
|
const printLexingResultInfo = (lexingResult) => {
|
|
6
|
-
// console.error(JSON.stringify(lexingResult, null, "\t"));
|
|
7
5
|
const tokens = lexingResult.tokens.map((token) => "'" + token.image + "' (" + token.tokenType.name + ")");
|
|
8
6
|
console.error(tokens);
|
|
9
7
|
};
|
|
10
8
|
const smdLexer = new Lexer(smdTokens, { positionTracking: "onlyOffset" });
|
|
11
9
|
export const smdParser = new SmdParser(tokenVocabulary);
|
|
12
|
-
export const parseLine = (text) => {
|
|
10
|
+
export const parseLine = (text, showDebug = false) => {
|
|
13
11
|
resetTokenState(); // this is needed to reset the token state between lines
|
|
14
12
|
const errors = [];
|
|
15
13
|
const lexingResult = smdLexer.tokenize(prepareLine(text));
|
|
16
14
|
if (lexingResult.errors.length > 0) {
|
|
17
|
-
errors.push(...lexingResult.errors.map((error) =>
|
|
18
|
-
|
|
15
|
+
errors.push(...lexingResult.errors.map((error) => ({
|
|
16
|
+
message: `Neočekávaný znak na tomto místě.`,
|
|
17
|
+
startOffset: error.offset,
|
|
18
|
+
endOffset: error.offset + error.length + 1,
|
|
19
|
+
})));
|
|
20
|
+
if (showDebug) {
|
|
21
|
+
printLexingResultInfo(lexingResult);
|
|
22
|
+
}
|
|
19
23
|
return { smdLines: [], errors };
|
|
20
24
|
}
|
|
21
|
-
// printLexingResultInfo(lexingResult);
|
|
22
25
|
smdParser.input = lexingResult.tokens;
|
|
23
26
|
const smdLines = smdParser.street();
|
|
24
27
|
if (smdParser.errors.length > 0) {
|
|
25
|
-
errors.push(...smdParser.errors.map((error) =>
|
|
26
|
-
|
|
28
|
+
errors.push(...smdParser.errors.map((error) => ({
|
|
29
|
+
message: `Nesprávný zápis pravidla - nevynechali jste něco?`,
|
|
30
|
+
startOffset: error.token.startOffset,
|
|
31
|
+
endOffset: error.token.endOffset,
|
|
32
|
+
})));
|
|
33
|
+
if (showDebug) {
|
|
34
|
+
printLexingResultInfo(lexingResult);
|
|
35
|
+
}
|
|
36
|
+
return { smdLines: [], errors };
|
|
27
37
|
}
|
|
28
38
|
return { smdLines, errors };
|
|
29
39
|
};
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import { Founder } from "../db/types";
|
|
2
|
-
import {
|
|
3
|
-
import { Municipality } from "./types";
|
|
4
|
-
|
|
5
|
-
founder: Founder | null;
|
|
6
|
-
}
|
|
7
|
-
export declare const parseOrdinanceToAddressPoints: (lines: string[], options?: OpenDataSyncOptions) => Municipality[];
|
|
2
|
+
import { OpenDataSyncOptionsPartial } from "../utils/helpers";
|
|
3
|
+
import { ErrorCallbackParams, Municipality, MunicipalityWithFounder, ProcessLineCallbackParams, School, SmdError, SmdState } from "./types";
|
|
4
|
+
export declare const parseOrdinanceToAddressPoints: (lines: string[], options?: OpenDataSyncOptionsPartial, initialState?: Partial<SmdState>, onError?: (params: ErrorCallbackParams) => void, onWarning?: (params: ErrorCallbackParams) => void, onProcessedLine?: (params: ProcessLineCallbackParams) => void) => Municipality[];
|
|
8
5
|
export declare const convertMunicipality: (municipality: MunicipalityWithFounder) => Municipality;
|
|
9
|
-
export {
|
|
6
|
+
export declare const getNewMunicipality: (name: string, options?: OpenDataSyncOptionsPartial) => {
|
|
7
|
+
municipality: MunicipalityWithFounder;
|
|
8
|
+
errors: SmdError[];
|
|
9
|
+
};
|
|
10
|
+
export declare const getNewSchool: (name: string, founder: Founder | null, lineNumber: number, onError: (params: ErrorCallbackParams) => void, options?: OpenDataSyncOptionsPartial) => School;
|
|
11
|
+
export declare const wholeLineError: (message: string, line: string) => SmdError;
|
|
@@ -2,32 +2,194 @@ import { checkStreetExists, findAddressPoints, getAddressPointById, } from "../d
|
|
|
2
2
|
import { setDbConfig } from "../db/db";
|
|
3
3
|
import { findFounder } from "../db/founders";
|
|
4
4
|
import { findSchool } from "../db/schools";
|
|
5
|
-
import { founderToMunicipality
|
|
5
|
+
import { founderToMunicipality } from "../db/types";
|
|
6
6
|
import { prepareOptions } from "../utils/helpers";
|
|
7
7
|
import { getSwitchMunicipality, getWholeMunicipality, isMunicipalitySwitch, isWholeMunicipality, } from "./municipality";
|
|
8
8
|
import { parseLine } from "./smd-line-parser";
|
|
9
9
|
import { isAddressPoint, } from "./types";
|
|
10
|
-
const
|
|
10
|
+
export const parseOrdinanceToAddressPoints = (lines, options = {}, initialState = {}, onError = () => { }, onWarning = () => { }, onProcessedLine = () => { }) => {
|
|
11
|
+
const readyOptions = prepareOptions(options);
|
|
12
|
+
setDbConfig({
|
|
13
|
+
filePath: readyOptions.dbFilePath,
|
|
14
|
+
initFilePath: readyOptions.dbInitFilePath,
|
|
15
|
+
});
|
|
16
|
+
const state = Object.assign({ currentMunicipality: null, currentFilterMunicipality: null, currentSchool: null, municipalities: [] }, initialState);
|
|
17
|
+
let lineNumber = 1;
|
|
18
|
+
for (const rawLine of lines) {
|
|
19
|
+
const line = cleanLine(rawLine);
|
|
20
|
+
processOneLine({
|
|
21
|
+
line,
|
|
22
|
+
state,
|
|
23
|
+
lineNumber,
|
|
24
|
+
onError,
|
|
25
|
+
onWarning,
|
|
26
|
+
});
|
|
27
|
+
onProcessedLine({ lineNumber, line });
|
|
28
|
+
lineNumber++;
|
|
29
|
+
}
|
|
30
|
+
if (state.currentSchool != null) {
|
|
31
|
+
if (state.currentMunicipality == null) {
|
|
32
|
+
return [];
|
|
33
|
+
}
|
|
34
|
+
state.currentMunicipality.schools.push(mapSchoolForExport(state.currentSchool));
|
|
35
|
+
}
|
|
36
|
+
if (state.currentMunicipality != null) {
|
|
37
|
+
state.municipalities.push(convertMunicipality(state.currentMunicipality));
|
|
38
|
+
}
|
|
39
|
+
return state.municipalities;
|
|
40
|
+
};
|
|
41
|
+
const filterOutSchoolAddressPoint = (addressPoints, school) => {
|
|
42
|
+
const schoolPosition = school.position;
|
|
43
|
+
return schoolPosition && isAddressPoint(schoolPosition)
|
|
44
|
+
? (addressPoints = addressPoints.filter((ap) => ap.id !== schoolPosition.id))
|
|
45
|
+
: addressPoints;
|
|
46
|
+
};
|
|
47
|
+
export const convertMunicipality = (municipality) => {
|
|
48
|
+
return {
|
|
49
|
+
municipalityName: municipality.municipalityName,
|
|
50
|
+
schools: municipality.schools,
|
|
51
|
+
};
|
|
52
|
+
};
|
|
53
|
+
const processOneLine = (params) => {
|
|
54
|
+
const { line, state } = params;
|
|
55
|
+
if (line[0] === "#") {
|
|
56
|
+
processMunicipalityLine(params);
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
if (line === "") {
|
|
60
|
+
// end of school
|
|
61
|
+
processEmptyLine(params);
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
if (line[0] === "!") {
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
if (state.currentSchool === null) {
|
|
68
|
+
processSchoolLine(params);
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
if (isMunicipalitySwitch(line)) {
|
|
72
|
+
processMunicipalitySwitchLine(params);
|
|
73
|
+
}
|
|
74
|
+
else if (isWholeMunicipality(line)) {
|
|
75
|
+
processWholeMunicipalityLine(params);
|
|
76
|
+
}
|
|
77
|
+
else {
|
|
78
|
+
processAddressPointLine(params);
|
|
79
|
+
}
|
|
80
|
+
};
|
|
81
|
+
const processMunicipalityLine = ({ line, state, onError }) => {
|
|
82
|
+
if (state.currentSchool !== null) {
|
|
83
|
+
state.currentMunicipality.schools.push(state.currentSchool);
|
|
84
|
+
state.currentSchool = null;
|
|
85
|
+
}
|
|
86
|
+
if (state.currentMunicipality !== null) {
|
|
87
|
+
state.municipalities.push(convertMunicipality(state.currentMunicipality));
|
|
88
|
+
}
|
|
89
|
+
const { municipality, errors } = getNewMunicipality(line);
|
|
90
|
+
state.currentMunicipality = municipality;
|
|
91
|
+
state.currentFilterMunicipality = founderToMunicipality(state.currentMunicipality.founder);
|
|
92
|
+
state.currentSchool = null;
|
|
93
|
+
};
|
|
94
|
+
const processEmptyLine = ({ state }) => {
|
|
95
|
+
if (state.currentSchool !== null) {
|
|
96
|
+
state.currentMunicipality.schools.push(state.currentSchool);
|
|
97
|
+
state.currentSchool = null;
|
|
98
|
+
}
|
|
99
|
+
};
|
|
100
|
+
const processSchoolLine = ({ line, lineNumber, state, onError, }) => {
|
|
101
|
+
if (state.currentMunicipality === null) {
|
|
102
|
+
onError({
|
|
103
|
+
lineNumber,
|
|
104
|
+
line,
|
|
105
|
+
errors: [
|
|
106
|
+
wholeLineError("Definici školy musí předcházet definice zřizovatele (uvozená '#', např. '# Strakonice').", line),
|
|
107
|
+
],
|
|
108
|
+
});
|
|
109
|
+
return;
|
|
110
|
+
}
|
|
111
|
+
state.currentSchool = getNewSchool(line, state.currentMunicipality.founder, lineNumber, onError);
|
|
112
|
+
state.currentFilterMunicipality = founderToMunicipality(state.currentMunicipality.founder);
|
|
113
|
+
};
|
|
114
|
+
const processMunicipalitySwitchLine = ({ line, state, lineNumber, onError, }) => {
|
|
115
|
+
const { municipality, errors } = getSwitchMunicipality(line);
|
|
116
|
+
if (errors.length > 0) {
|
|
117
|
+
onError({ lineNumber, line, errors });
|
|
118
|
+
}
|
|
119
|
+
else {
|
|
120
|
+
state.currentFilterMunicipality = municipality;
|
|
121
|
+
}
|
|
122
|
+
};
|
|
123
|
+
const processWholeMunicipalityLine = ({ line, state, lineNumber, onError, }) => {
|
|
124
|
+
const { municipality, errors } = getWholeMunicipality(line);
|
|
125
|
+
if (errors.length > 0) {
|
|
126
|
+
onError({ lineNumber, line, errors });
|
|
127
|
+
}
|
|
128
|
+
else {
|
|
129
|
+
const addressPoints = findAddressPoints({ wholeMunicipality: true, street: "", numberSpec: [] }, municipality);
|
|
130
|
+
state.currentSchool.addresses.push(...filterOutSchoolAddressPoint(addressPoints, state.currentSchool).map(mapAddressPointForExport));
|
|
131
|
+
}
|
|
132
|
+
};
|
|
133
|
+
const processAddressPointLine = ({ line, state, lineNumber, onError, onWarning, }) => {
|
|
134
|
+
const { smdLines, errors } = parseLine(line);
|
|
135
|
+
if (errors.length > 0) {
|
|
136
|
+
onError({ lineNumber, line, errors });
|
|
137
|
+
}
|
|
138
|
+
else {
|
|
139
|
+
smdLines.forEach((smdLine) => {
|
|
140
|
+
const { exists, errors } = checkStreetExists(smdLine.street, state.currentMunicipality.founder);
|
|
141
|
+
if (errors.length > 0) {
|
|
142
|
+
onWarning({ lineNumber, line, errors });
|
|
143
|
+
}
|
|
144
|
+
if (exists) {
|
|
145
|
+
let addressPoints = findAddressPoints(smdLine, state.currentFilterMunicipality);
|
|
146
|
+
state.currentSchool.addresses.push(...filterOutSchoolAddressPoint(addressPoints, state.currentSchool).map(mapAddressPointForExport));
|
|
147
|
+
}
|
|
148
|
+
});
|
|
149
|
+
}
|
|
150
|
+
};
|
|
151
|
+
export const getNewMunicipality = (name, options) => {
|
|
152
|
+
if (options) {
|
|
153
|
+
options = prepareOptions(options);
|
|
154
|
+
setDbConfig({
|
|
155
|
+
filePath: options.dbFilePath,
|
|
156
|
+
initFilePath: options.dbInitFilePath,
|
|
157
|
+
});
|
|
158
|
+
}
|
|
11
159
|
const { founder, errors } = findFounder(name);
|
|
12
160
|
if (errors.length > 0) {
|
|
13
161
|
errors.forEach(console.error);
|
|
14
162
|
}
|
|
15
163
|
return {
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
164
|
+
municipality: {
|
|
165
|
+
municipalityName: founder ? founder.name : "Neznámá obec",
|
|
166
|
+
founder,
|
|
167
|
+
schools: [],
|
|
168
|
+
},
|
|
169
|
+
errors,
|
|
19
170
|
};
|
|
20
171
|
};
|
|
21
|
-
const getNewSchool = (name, founder) => {
|
|
172
|
+
export const getNewSchool = (name, founder, lineNumber, onError, options) => {
|
|
173
|
+
if (options) {
|
|
174
|
+
options = prepareOptions(options);
|
|
175
|
+
setDbConfig({
|
|
176
|
+
filePath: options.dbFilePath,
|
|
177
|
+
initFilePath: options.dbInitFilePath,
|
|
178
|
+
});
|
|
179
|
+
}
|
|
22
180
|
let exportSchool = {
|
|
23
|
-
name
|
|
181
|
+
name,
|
|
24
182
|
izo: "",
|
|
25
183
|
addresses: [],
|
|
26
184
|
};
|
|
27
185
|
if (founder !== null) {
|
|
28
|
-
const { school } = findSchool(name, founder.schools);
|
|
186
|
+
const { school, errors } = findSchool(name, founder.schools);
|
|
187
|
+
if (errors.length > 0) {
|
|
188
|
+
onError({ lineNumber, line: name, errors });
|
|
189
|
+
}
|
|
29
190
|
if (school) {
|
|
30
|
-
|
|
191
|
+
exportSchool.name = school.name;
|
|
192
|
+
exportSchool.izo = school.izo || "";
|
|
31
193
|
if (school.locations.length > 0) {
|
|
32
194
|
const position = getAddressPointById(school.locations[0].addressPointId);
|
|
33
195
|
if (position !== null) {
|
|
@@ -49,134 +211,13 @@ const mapSchoolForExport = (school) => ({
|
|
|
49
211
|
name: school.name,
|
|
50
212
|
izo: school.izo,
|
|
51
213
|
addresses: school.addresses,
|
|
52
|
-
position: mapAddressPointForExport(school.position),
|
|
214
|
+
position: school.position ? mapAddressPointForExport(school.position) : null,
|
|
53
215
|
});
|
|
54
216
|
const cleanLine = (line) => {
|
|
55
217
|
return line.trim().replace(/–/g, "-");
|
|
56
218
|
};
|
|
57
|
-
export const
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
});
|
|
63
|
-
let errorCount = 0;
|
|
64
|
-
const errorLines = [];
|
|
65
|
-
let warningCount = 0;
|
|
66
|
-
let lineNumber = 1;
|
|
67
|
-
let municipalities = [];
|
|
68
|
-
let currentMunicipality = null;
|
|
69
|
-
let currentFilterMunicipality = null;
|
|
70
|
-
let currentSchool = null;
|
|
71
|
-
const reportErrors = (line, errors) => {
|
|
72
|
-
errors.forEach(console.error);
|
|
73
|
-
console.error(`Invalid street definition on line ${lineNumber}: ${line}`);
|
|
74
|
-
errorCount++;
|
|
75
|
-
errorLines.push(`line ${lineNumber}: ${line}`);
|
|
76
|
-
};
|
|
77
|
-
lines.forEach((rawLine) => {
|
|
78
|
-
let line = cleanLine(rawLine);
|
|
79
|
-
if (line[0] === "#") {
|
|
80
|
-
// a new municipality
|
|
81
|
-
if (currentSchool !== null) {
|
|
82
|
-
currentMunicipality.schools.push(currentSchool);
|
|
83
|
-
currentSchool = null;
|
|
84
|
-
}
|
|
85
|
-
if (currentMunicipality !== null) {
|
|
86
|
-
municipalities.push(convertMunicipality(currentMunicipality));
|
|
87
|
-
}
|
|
88
|
-
currentMunicipality = getNewMunicipality(line.substring(1).trim());
|
|
89
|
-
currentFilterMunicipality = founderToMunicipality(currentMunicipality.founder);
|
|
90
|
-
currentSchool = null;
|
|
91
|
-
}
|
|
92
|
-
else if (line === "") {
|
|
93
|
-
// empty line (end of school)
|
|
94
|
-
if (currentSchool !== null) {
|
|
95
|
-
currentMunicipality.schools.push(currentSchool);
|
|
96
|
-
currentSchool = null;
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
else {
|
|
100
|
-
if (currentSchool === null) {
|
|
101
|
-
if (currentMunicipality === null) {
|
|
102
|
-
throw new Error("No municipality defined on line " + lineNumber);
|
|
103
|
-
}
|
|
104
|
-
currentSchool = getNewSchool(line, currentMunicipality.founder);
|
|
105
|
-
currentFilterMunicipality = founderToMunicipality(currentMunicipality.founder);
|
|
106
|
-
}
|
|
107
|
-
else {
|
|
108
|
-
if (line[0] !== "!") {
|
|
109
|
-
if (isMunicipalitySwitch(line)) {
|
|
110
|
-
const { municipality, errors } = getSwitchMunicipality(line);
|
|
111
|
-
if (errors.length > 0) {
|
|
112
|
-
reportErrors(line, errors);
|
|
113
|
-
}
|
|
114
|
-
else {
|
|
115
|
-
currentFilterMunicipality = municipality;
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
else if (isWholeMunicipality(line)) {
|
|
119
|
-
const { municipality, errors } = getWholeMunicipality(line);
|
|
120
|
-
if (errors.length > 0) {
|
|
121
|
-
reportErrors(line, errors);
|
|
122
|
-
}
|
|
123
|
-
else {
|
|
124
|
-
const addressPoints = findAddressPoints({ wholeMunicipality: true, street: "", numberSpec: [] }, municipality);
|
|
125
|
-
currentSchool.addresses.push(...filterOutSchoolAddressPoint(addressPoints, currentSchool).map(mapAddressPointForExport));
|
|
126
|
-
}
|
|
127
|
-
}
|
|
128
|
-
else {
|
|
129
|
-
// address point
|
|
130
|
-
const { smdLines, errors } = parseLine(line);
|
|
131
|
-
if (errors.length > 0) {
|
|
132
|
-
reportErrors(line, errors);
|
|
133
|
-
}
|
|
134
|
-
else {
|
|
135
|
-
smdLines.forEach((smdLine) => {
|
|
136
|
-
const { exists, errors } = checkStreetExists(smdLine.street, currentMunicipality.founder);
|
|
137
|
-
if (errors.length > 0) {
|
|
138
|
-
errors.map((error) => {
|
|
139
|
-
console.error(`Line ${lineNumber}: ${error}`);
|
|
140
|
-
});
|
|
141
|
-
warningCount++;
|
|
142
|
-
}
|
|
143
|
-
if (exists) {
|
|
144
|
-
let addressPoints = findAddressPoints(smdLine, currentFilterMunicipality);
|
|
145
|
-
currentSchool.addresses.push(...filterOutSchoolAddressPoint(addressPoints, currentSchool).map(mapAddressPointForExport));
|
|
146
|
-
}
|
|
147
|
-
});
|
|
148
|
-
}
|
|
149
|
-
}
|
|
150
|
-
}
|
|
151
|
-
}
|
|
152
|
-
}
|
|
153
|
-
lineNumber++;
|
|
154
|
-
});
|
|
155
|
-
if (currentSchool != null) {
|
|
156
|
-
if (currentMunicipality == null) {
|
|
157
|
-
currentMunicipality = getNewMunicipality("");
|
|
158
|
-
}
|
|
159
|
-
currentMunicipality.schools.push(mapSchoolForExport(currentSchool));
|
|
160
|
-
}
|
|
161
|
-
if (currentMunicipality != null) {
|
|
162
|
-
municipalities.push(convertMunicipality(currentMunicipality));
|
|
163
|
-
}
|
|
164
|
-
console.log(`Parsed ${lineNumber} lines, ${errorCount} errors, ${warningCount} warnings.`);
|
|
165
|
-
if (errorCount > 0) {
|
|
166
|
-
console.log("Errors:");
|
|
167
|
-
errorLines.forEach((line) => console.log(line));
|
|
168
|
-
}
|
|
169
|
-
return municipalities;
|
|
170
|
-
};
|
|
171
|
-
const filterOutSchoolAddressPoint = (addressPoints, school) => {
|
|
172
|
-
const schoolPosition = school.position;
|
|
173
|
-
return schoolPosition && isAddressPoint(schoolPosition)
|
|
174
|
-
? (addressPoints = addressPoints.filter((ap) => ap.id !== schoolPosition.id))
|
|
175
|
-
: addressPoints;
|
|
176
|
-
};
|
|
177
|
-
export const convertMunicipality = (municipality) => {
|
|
178
|
-
return {
|
|
179
|
-
municipalityName: municipality.municipalityName,
|
|
180
|
-
schools: municipality.schools,
|
|
181
|
-
};
|
|
182
|
-
};
|
|
219
|
+
export const wholeLineError = (message, line) => ({
|
|
220
|
+
message,
|
|
221
|
+
startOffset: 0,
|
|
222
|
+
endOffset: line.length + 1,
|
|
223
|
+
});
|
|
@@ -109,11 +109,11 @@ const Space = createToken({
|
|
|
109
109
|
longer_alt: [MainSeparator, Separator],
|
|
110
110
|
group: Lexer.SKIPPED,
|
|
111
111
|
});
|
|
112
|
-
const Colon = createToken({
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
});
|
|
112
|
+
// const Colon = createToken({
|
|
113
|
+
// name: "Colon",
|
|
114
|
+
// pattern: /:/,
|
|
115
|
+
// group: Lexer.SKIPPED,
|
|
116
|
+
// });
|
|
117
117
|
const smdTokens = [
|
|
118
118
|
MainSeparator,
|
|
119
119
|
Separator,
|
|
@@ -130,7 +130,7 @@ const smdTokens = [
|
|
|
130
130
|
Hyphen,
|
|
131
131
|
Slash,
|
|
132
132
|
Space,
|
|
133
|
-
Colon,
|
|
133
|
+
// Colon,
|
|
134
134
|
StreetName,
|
|
135
135
|
];
|
|
136
136
|
MainSeparator.LABEL = "' - '";
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { Municipality as DbMunicipality } from "../db/types";
|
|
2
1
|
import { AddressPoint as CzechAddressPoint } from "czech-address";
|
|
2
|
+
import { Municipality as DbMunicipality, Founder } from "../db/types";
|
|
3
3
|
export interface ProcessedSmdLines {
|
|
4
4
|
smdLines: SmdLine[];
|
|
5
|
-
errors:
|
|
5
|
+
errors: SmdError[];
|
|
6
6
|
}
|
|
7
7
|
export interface SmdLine {
|
|
8
8
|
street: string;
|
|
@@ -67,5 +67,33 @@ export interface Municipality {
|
|
|
67
67
|
}
|
|
68
68
|
export interface DbMunicipalityResult {
|
|
69
69
|
municipality: DbMunicipality;
|
|
70
|
-
errors:
|
|
70
|
+
errors: SmdError[];
|
|
71
|
+
}
|
|
72
|
+
export interface MunicipalityWithFounder extends Municipality {
|
|
73
|
+
founder: Founder | null;
|
|
74
|
+
}
|
|
75
|
+
export interface SmdState {
|
|
76
|
+
currentMunicipality: MunicipalityWithFounder;
|
|
77
|
+
currentFilterMunicipality: DbMunicipality;
|
|
78
|
+
currentSchool: School;
|
|
79
|
+
municipalities: Municipality[];
|
|
80
|
+
}
|
|
81
|
+
export interface ProcessLineCallbackParams {
|
|
82
|
+
lineNumber: number;
|
|
83
|
+
line: string;
|
|
84
|
+
}
|
|
85
|
+
export interface ErrorCallbackParams extends ProcessLineCallbackParams {
|
|
86
|
+
errors: SmdError[];
|
|
87
|
+
}
|
|
88
|
+
export interface ProcessLineParams {
|
|
89
|
+
line: string;
|
|
90
|
+
state: SmdState;
|
|
91
|
+
lineNumber: number;
|
|
92
|
+
onError: (params: ErrorCallbackParams) => void;
|
|
93
|
+
onWarning: (params: ErrorCallbackParams) => void;
|
|
94
|
+
}
|
|
95
|
+
export interface SmdError {
|
|
96
|
+
startOffset: number;
|
|
97
|
+
endOffset: number;
|
|
98
|
+
message: string;
|
|
71
99
|
}
|
package/dist/utils/helpers.d.ts
CHANGED
|
@@ -1,22 +1,5 @@
|
|
|
1
1
|
import { Founder } from "../db/types";
|
|
2
2
|
export interface OpenDataSyncOptions {
|
|
3
|
-
tmpDir?: string;
|
|
4
|
-
dataDir?: string;
|
|
5
|
-
dbFilePath?: string;
|
|
6
|
-
dbInitFilePath?: string;
|
|
7
|
-
addressPointsAtomUrl?: string;
|
|
8
|
-
addressPointsZipFileName?: string;
|
|
9
|
-
addressPointsCsvFolderName?: string;
|
|
10
|
-
streetsAtomUrl?: string;
|
|
11
|
-
streetZipFolderName?: string;
|
|
12
|
-
streetDbfFileName?: string;
|
|
13
|
-
schoolsXmlUrl?: string;
|
|
14
|
-
schoolsXmlFileName?: string;
|
|
15
|
-
regionsCsvUrl?: string;
|
|
16
|
-
regionsSchemaUrl?: string;
|
|
17
|
-
regionsCsvFileName?: string;
|
|
18
|
-
}
|
|
19
|
-
export interface OpenDataSyncOptionsNotEmpty {
|
|
20
3
|
tmpDir: string;
|
|
21
4
|
dataDir: string;
|
|
22
5
|
dbFilePath: string;
|
|
@@ -25,7 +8,7 @@ export interface OpenDataSyncOptionsNotEmpty {
|
|
|
25
8
|
addressPointsZipFileName: string;
|
|
26
9
|
addressPointsCsvFolderName: string;
|
|
27
10
|
streetsAtomUrl: string;
|
|
28
|
-
|
|
11
|
+
streetZipFolderName: string;
|
|
29
12
|
streetDbfFileName: string;
|
|
30
13
|
schoolsXmlUrl: string;
|
|
31
14
|
schoolsXmlFileName: string;
|
|
@@ -33,9 +16,10 @@ export interface OpenDataSyncOptionsNotEmpty {
|
|
|
33
16
|
regionsSchemaUrl: string;
|
|
34
17
|
regionsCsvFileName: string;
|
|
35
18
|
}
|
|
19
|
+
export type OpenDataSyncOptionsPartial = Partial<OpenDataSyncOptions>;
|
|
36
20
|
export declare const getAppDataDirPath: () => string;
|
|
37
|
-
export declare const prepareOptions: (options:
|
|
38
|
-
export declare const initDb: (options:
|
|
21
|
+
export declare const prepareOptions: (options: OpenDataSyncOptionsPartial) => OpenDataSyncOptions;
|
|
22
|
+
export declare const initDb: (options: OpenDataSyncOptions) => void;
|
|
39
23
|
export declare const extractMunicipalityName: (founder: Founder) => string;
|
|
40
24
|
export declare const sanitizeMunicipalityName: (name: string) => string;
|
|
41
25
|
export declare const findClosestString: (str: string, arr: string[]) => string;
|
package/dist/utils/helpers.js
CHANGED
|
@@ -10,7 +10,7 @@ export const getAppDataDirPath = () => join(process.env.APPDATA ||
|
|
|
10
10
|
? process.env.HOME + "/Library/Preferences"
|
|
11
11
|
: process.env.HOME + "/.local/share"), appName);
|
|
12
12
|
export const prepareOptions = (options) => {
|
|
13
|
-
var _a
|
|
13
|
+
var _a;
|
|
14
14
|
const dataDir = (_a = options.dataDir) !== null && _a !== void 0 ? _a : getAppDataDirPath();
|
|
15
15
|
if (!existsSync(dataDir)) {
|
|
16
16
|
mkdirSync(dataDir);
|
|
@@ -21,23 +21,24 @@ export const prepareOptions = (options) => {
|
|
|
21
21
|
}
|
|
22
22
|
const __filename = fileURLToPath(import.meta.url);
|
|
23
23
|
const __dirname = dirname(__filename);
|
|
24
|
-
|
|
25
|
-
tmpDir:
|
|
24
|
+
const defaults = {
|
|
25
|
+
tmpDir: tmpAppDir,
|
|
26
26
|
dataDir: dataDir,
|
|
27
|
-
dbFilePath:
|
|
28
|
-
dbInitFilePath:
|
|
29
|
-
addressPointsAtomUrl:
|
|
30
|
-
addressPointsZipFileName:
|
|
31
|
-
addressPointsCsvFolderName:
|
|
32
|
-
streetsAtomUrl:
|
|
33
|
-
|
|
34
|
-
streetDbfFileName:
|
|
35
|
-
schoolsXmlUrl:
|
|
36
|
-
schoolsXmlFileName:
|
|
37
|
-
regionsCsvUrl:
|
|
38
|
-
regionsSchemaUrl:
|
|
39
|
-
regionsCsvFileName:
|
|
27
|
+
dbFilePath: join(dataDir, "address_points.db"),
|
|
28
|
+
dbInitFilePath: join(__dirname, "..", "address_points_init.db"),
|
|
29
|
+
addressPointsAtomUrl: "https://atom.cuzk.cz/RUIAN-CSV-ADR-ST/RUIAN-CSV-ADR-ST.xml",
|
|
30
|
+
addressPointsZipFileName: "ruian_csv.zip",
|
|
31
|
+
addressPointsCsvFolderName: "CSV",
|
|
32
|
+
streetsAtomUrl: "https://atom.cuzk.cz/RUIAN-OBCE-SHP/RUIAN-OBCE-SHP.xml",
|
|
33
|
+
streetZipFolderName: "streets",
|
|
34
|
+
streetDbfFileName: "UL_L.dbf",
|
|
35
|
+
schoolsXmlUrl: "https://rejstriky.msmt.cz/opendata/vrejcelk.xml",
|
|
36
|
+
schoolsXmlFileName: "school-register.xml",
|
|
37
|
+
regionsCsvUrl: "https://www.czso.cz/documents/10180/23208674/struktura_uzemi_cr.csv",
|
|
38
|
+
regionsSchemaUrl: "https://www.czso.cz/documents/10180/23208674/struktura_uzemi_cr-metadata.json",
|
|
39
|
+
regionsCsvFileName: "struktura_uzemi_cr.csv",
|
|
40
40
|
};
|
|
41
|
+
return Object.assign(Object.assign({}, defaults), options);
|
|
41
42
|
};
|
|
42
43
|
export const initDb = (options) => {
|
|
43
44
|
setDbConfig({
|
package/package.json
CHANGED
|
@@ -48,7 +48,7 @@
|
|
|
48
48
|
},
|
|
49
49
|
"name": "text-to-map",
|
|
50
50
|
"description": "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ě zpracovatelného, uchopitelného formátu.",
|
|
51
|
-
"version": "1.0.
|
|
51
|
+
"version": "1.0.8",
|
|
52
52
|
"main": "dist/index.js",
|
|
53
53
|
"types": "dist/index.d.ts",
|
|
54
54
|
"files": [
|