@wemap/geo 11.0.0-alpha.6 → 11.0.0

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.
Files changed (39) hide show
  1. package/dist/index.js +1400 -414
  2. package/dist/index.js.map +1 -1
  3. package/dist/index.mjs +1400 -414
  4. package/dist/index.mjs.map +1 -1
  5. package/index.ts +9 -19
  6. package/package.json +6 -5
  7. package/src/Utils.ts +4 -4
  8. package/src/coordinates/Coordinates.ts +16 -7
  9. package/src/coordinates/Level.spec.ts +6 -1
  10. package/src/coordinates/Level.ts +15 -6
  11. package/src/graph/GeoGraph.spec.ts +278 -0
  12. package/src/graph/GeoGraph.ts +170 -0
  13. package/src/graph/GeoGraphEdge.spec.ts +51 -0
  14. package/src/graph/GeoGraphEdge.ts +98 -0
  15. package/src/graph/GeoGraphItinerary.spec.ts +14 -0
  16. package/src/graph/GeoGraphItinerary.ts +61 -0
  17. package/src/graph/GeoGraphProjection.ts +24 -0
  18. package/src/graph/{MapMatching.spec.ts → GeoGraphProjectionHandler.spec.ts} +74 -73
  19. package/src/graph/{MapMatching.ts → GeoGraphProjectionHandler.ts} +39 -44
  20. package/src/graph/GeoGraphRouter.spec.ts +297 -0
  21. package/src/graph/GeoGraphRouter.ts +267 -0
  22. package/src/graph/GeoGraphVertex.spec.ts +54 -0
  23. package/src/graph/GeoGraphVertex.ts +139 -0
  24. package/src/{router → graph}/NoRouteFoundError.ts +9 -14
  25. package/src/types.ts +3 -3
  26. package/tests/CommonTest.ts +69 -75
  27. package/src/graph/GraphEdge.spec.ts +0 -74
  28. package/src/graph/GraphEdge.ts +0 -134
  29. package/src/graph/GraphNode.spec.ts +0 -202
  30. package/src/graph/GraphNode.ts +0 -174
  31. package/src/graph/GraphProjection.ts +0 -23
  32. package/src/graph/GraphUtils.ts +0 -21
  33. package/src/graph/Network.spec.ts +0 -148
  34. package/src/graph/Network.ts +0 -177
  35. package/src/router/GraphItinerary.spec.ts +0 -14
  36. package/src/router/GraphItinerary.ts +0 -80
  37. package/src/router/GraphRouter.spec.ts +0 -298
  38. package/src/router/GraphRouter.ts +0 -283
  39. package/src/router/GraphRouterOptions.ts +0 -14
package/dist/index.js CHANGED
@@ -80,18 +80,27 @@ const _Level = class {
80
80
  if (str === null) {
81
81
  return null;
82
82
  }
83
- if (typeof str !== "string") {
84
- throw Error(`argument must be a string, got ${typeof str}`);
83
+ if (typeof str !== "string" || !str.length) {
84
+ throw Error(`argument must be a non empty string, got ${typeof str}`);
85
85
  }
86
86
  if (!isNaN(Number(str))) {
87
87
  return parseFloat(str);
88
88
  }
89
89
  const splited = str.split(";");
90
- if (splited.length === 2) {
91
- const low = Number(splited[0]);
92
- const up = Number(splited[1]);
90
+ if (splited.length > 1) {
91
+ const levels = splited.map((str2) => Number(str2));
92
+ const low = Math.min(...levels);
93
+ const up = Math.max(...levels);
93
94
  this.checkType([low, up]);
94
- return [parseFloat(splited[0]), parseFloat(splited[1])];
95
+ return [low, up];
96
+ } else {
97
+ const rangeSeparator = str.substring(1).indexOf("-") + 1;
98
+ if (rangeSeparator > 0) {
99
+ const low = Number(str.substring(0, rangeSeparator));
100
+ const up = Number(str.substring(rangeSeparator + 1));
101
+ this.checkType([low, up]);
102
+ return [low, up];
103
+ }
95
104
  }
96
105
  throw Error(`Cannot parse following level: ${str}`);
97
106
  }
@@ -483,9 +492,9 @@ class Coordinates {
483
492
  }
484
493
  toJson() {
485
494
  return {
486
- lat: this.lat,
487
- lng: this.lng,
488
- ...this.alt !== null && { alt: this.alt },
495
+ lat: Number(this.lat.toFixed(8)),
496
+ lng: Number(this.lng.toFixed(8)),
497
+ ...this.alt !== null && { alt: Number(this.alt.toFixed(3)) },
489
498
  ...this.level !== null && { level: this.level }
490
499
  };
491
500
  }
@@ -494,12 +503,21 @@ class Coordinates {
494
503
  }
495
504
  toCompressedJson() {
496
505
  if (this.level !== null) {
497
- return [this.lat, this.lng, this.alt, this.level];
506
+ return [
507
+ Number(this.lat.toFixed(8)),
508
+ Number(this.lng.toFixed(8)),
509
+ this.alt === null ? null : Number(this.alt.toFixed(3)),
510
+ this.level
511
+ ];
498
512
  }
499
513
  if (this.alt !== null) {
500
- return [this.lat, this.lng, this.alt];
514
+ return [
515
+ Number(this.lat.toFixed(8)),
516
+ Number(this.lng.toFixed(8)),
517
+ Number(this.alt.toFixed(3))
518
+ ];
501
519
  }
502
- return [this.lat, this.lng];
520
+ return [Number(this.lat.toFixed(8)), Number(this.lng.toFixed(8))];
503
521
  }
504
522
  static fromCompressedJson(json) {
505
523
  const coords = new Coordinates(json[0], json[1]);
@@ -1095,158 +1113,1118 @@ class AbsoluteHeading {
1095
1113
  return new AbsoluteHeading(this.heading, this.time, this.accuracy);
1096
1114
  }
1097
1115
  }
1098
- class GraphNode {
1099
- constructor(coords, builtFrom = null) {
1100
- __publicField(this, "coords");
1101
- __publicField(this, "edges", []);
1102
- __publicField(this, "builtFrom");
1103
- __publicField(this, "io", false);
1104
- this.coords = coords;
1105
- this.builtFrom = builtFrom;
1106
- }
1107
- distanceTo(other) {
1108
- return this.coords.distanceTo(other.coords);
1109
- }
1110
- bearingTo(other) {
1111
- return this.coords.bearingTo(other.coords);
1112
- }
1113
- equals(other) {
1114
- return this.coords.equals(other.coords) && this.builtFrom === other.builtFrom;
1115
- }
1116
- clone() {
1117
- const node = new GraphNode(this.coords, this.builtFrom);
1118
- node.edges = this.edges.slice(0);
1119
- node.io = this.io;
1120
- return node;
1121
- }
1122
- toJson() {
1123
- return this.coords.toCompressedJson();
1124
- }
1125
- static fromJson(json, builtFrom = null) {
1126
- return new GraphNode(Coordinates.fromCompressedJson(json), builtFrom);
1127
- }
1128
- _generateLevelFromEdges() {
1129
- let tmpLevel = null;
1130
- for (let i = 0; i < this.edges.length; i++) {
1131
- const edge = this.edges[i];
1132
- if (edge.level !== null) {
1133
- if (tmpLevel === null) {
1134
- tmpLevel = Level.clone(edge.level);
1116
+ var commonjsGlobal = typeof globalThis !== "undefined" ? globalThis : typeof window !== "undefined" ? window : typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : {};
1117
+ var uaParser = { exports: {} };
1118
+ (function(module2, exports2) {
1119
+ (function(window2, undefined$1) {
1120
+ var LIBVERSION = "1.0.33", EMPTY = "", UNKNOWN = "?", FUNC_TYPE = "function", UNDEF_TYPE = "undefined", OBJ_TYPE = "object", STR_TYPE = "string", MAJOR = "major", MODEL = "model", NAME = "name", TYPE = "type", VENDOR = "vendor", VERSION = "version", ARCHITECTURE = "architecture", CONSOLE = "console", MOBILE = "mobile", TABLET = "tablet", SMARTTV = "smarttv", WEARABLE = "wearable", EMBEDDED = "embedded", UA_MAX_LENGTH = 350;
1121
+ var AMAZON = "Amazon", APPLE = "Apple", ASUS = "ASUS", BLACKBERRY = "BlackBerry", BROWSER = "Browser", CHROME = "Chrome", EDGE = "Edge", FIREFOX = "Firefox", GOOGLE = "Google", HUAWEI = "Huawei", LG = "LG", MICROSOFT = "Microsoft", MOTOROLA = "Motorola", OPERA = "Opera", SAMSUNG = "Samsung", SHARP = "Sharp", SONY = "Sony", XIAOMI = "Xiaomi", ZEBRA = "Zebra", FACEBOOK = "Facebook";
1122
+ var extend = function(regexes2, extensions) {
1123
+ var mergedRegexes = {};
1124
+ for (var i in regexes2) {
1125
+ if (extensions[i] && extensions[i].length % 2 === 0) {
1126
+ mergedRegexes[i] = extensions[i].concat(regexes2[i]);
1135
1127
  } else {
1136
- tmpLevel = Level.intersection(tmpLevel, edge.level);
1137
- if (tmpLevel === null) {
1138
- throw Error("Something bad happend during parsing: We cannot retrieve node level from adjacent ways: " + this.coords);
1139
- }
1128
+ mergedRegexes[i] = regexes2[i];
1140
1129
  }
1141
1130
  }
1142
- }
1143
- this.coords.level = tmpLevel;
1144
- }
1145
- _inferNodeLevelByRecursion() {
1146
- const { level } = this.coords;
1147
- if (level === null || !Level.isRange(level)) {
1148
- return;
1149
- }
1150
- if (this.edges.length > 1) {
1151
- return;
1152
- }
1153
- const lookForLevel = (node, visitedNodes) => {
1154
- visitedNodes.push(node);
1155
- if (node.coords.level === null) {
1156
- return null;
1131
+ return mergedRegexes;
1132
+ }, enumerize = function(arr) {
1133
+ var enums = {};
1134
+ for (var i = 0; i < arr.length; i++) {
1135
+ enums[arr[i].toUpperCase()] = arr[i];
1157
1136
  }
1158
- if (!Level.isRange(node.coords.level)) {
1159
- return node.coords.level;
1137
+ return enums;
1138
+ }, has = function(str1, str2) {
1139
+ return typeof str1 === STR_TYPE ? lowerize(str2).indexOf(lowerize(str1)) !== -1 : false;
1140
+ }, lowerize = function(str) {
1141
+ return str.toLowerCase();
1142
+ }, majorize = function(version) {
1143
+ return typeof version === STR_TYPE ? version.replace(/[^\d\.]/g, EMPTY).split(".")[0] : undefined$1;
1144
+ }, trim = function(str, len) {
1145
+ if (typeof str === STR_TYPE) {
1146
+ str = str.replace(/^\s\s*/, EMPTY);
1147
+ return typeof len === UNDEF_TYPE ? str : str.substring(0, UA_MAX_LENGTH);
1160
1148
  }
1161
- let tmpLevel = null;
1162
- for (let i = 0; i < node.edges.length; i++) {
1163
- const edge = node.edges[i];
1164
- const otherNode = edge.node1 === node ? edge.node2 : edge.node1;
1165
- if (!visitedNodes.includes(otherNode)) {
1166
- tmpLevel = Level.union(lookForLevel(otherNode, visitedNodes), tmpLevel);
1149
+ };
1150
+ var rgxMapper = function(ua, arrays) {
1151
+ var i = 0, j, k, p, q, matches, match;
1152
+ while (i < arrays.length && !matches) {
1153
+ var regex = arrays[i], props = arrays[i + 1];
1154
+ j = k = 0;
1155
+ while (j < regex.length && !matches) {
1156
+ matches = regex[j++].exec(ua);
1157
+ if (!!matches) {
1158
+ for (p = 0; p < props.length; p++) {
1159
+ match = matches[++k];
1160
+ q = props[p];
1161
+ if (typeof q === OBJ_TYPE && q.length > 0) {
1162
+ if (q.length === 2) {
1163
+ if (typeof q[1] == FUNC_TYPE) {
1164
+ this[q[0]] = q[1].call(this, match);
1165
+ } else {
1166
+ this[q[0]] = q[1];
1167
+ }
1168
+ } else if (q.length === 3) {
1169
+ if (typeof q[1] === FUNC_TYPE && !(q[1].exec && q[1].test)) {
1170
+ this[q[0]] = match ? q[1].call(this, match, q[2]) : undefined$1;
1171
+ } else {
1172
+ this[q[0]] = match ? match.replace(q[1], q[2]) : undefined$1;
1173
+ }
1174
+ } else if (q.length === 4) {
1175
+ this[q[0]] = match ? q[3].call(this, match.replace(q[1], q[2])) : undefined$1;
1176
+ }
1177
+ } else {
1178
+ this[q] = match ? match : undefined$1;
1179
+ }
1180
+ }
1181
+ }
1167
1182
  }
1183
+ i += 2;
1168
1184
  }
1169
- return tmpLevel;
1185
+ }, strMapper = function(str, map) {
1186
+ for (var i in map) {
1187
+ if (typeof map[i] === OBJ_TYPE && map[i].length > 0) {
1188
+ for (var j = 0; j < map[i].length; j++) {
1189
+ if (has(map[i][j], str)) {
1190
+ return i === UNKNOWN ? undefined$1 : i;
1191
+ }
1192
+ }
1193
+ } else if (has(map[i], str)) {
1194
+ return i === UNKNOWN ? undefined$1 : i;
1195
+ }
1196
+ }
1197
+ return str;
1170
1198
  };
1171
- const othersLevels = lookForLevel(this, []);
1172
- if (othersLevels !== null) {
1173
- if (!Level.isRange(othersLevels)) {
1174
- this.coords.level = othersLevels === level[0] ? level[1] : level[0];
1175
- return;
1199
+ var oldSafariMap = {
1200
+ "1.0": "/8",
1201
+ "1.2": "/1",
1202
+ "1.3": "/3",
1203
+ "2.0": "/412",
1204
+ "2.0.2": "/416",
1205
+ "2.0.3": "/417",
1206
+ "2.0.4": "/419",
1207
+ "?": "/"
1208
+ }, windowsVersionMap = {
1209
+ "ME": "4.90",
1210
+ "NT 3.11": "NT3.51",
1211
+ "NT 4.0": "NT4.0",
1212
+ "2000": "NT 5.0",
1213
+ "XP": ["NT 5.1", "NT 5.2"],
1214
+ "Vista": "NT 6.0",
1215
+ "7": "NT 6.1",
1216
+ "8": "NT 6.2",
1217
+ "8.1": "NT 6.3",
1218
+ "10": ["NT 6.4", "NT 10.0"],
1219
+ "RT": "ARM"
1220
+ };
1221
+ var regexes = {
1222
+ browser: [
1223
+ [
1224
+ /\b(?:crmo|crios)\/([\w\.]+)/i
1225
+ ],
1226
+ [VERSION, [NAME, "Chrome"]],
1227
+ [
1228
+ /edg(?:e|ios|a)?\/([\w\.]+)/i
1229
+ ],
1230
+ [VERSION, [NAME, "Edge"]],
1231
+ [
1232
+ /(opera mini)\/([-\w\.]+)/i,
1233
+ /(opera [mobiletab]{3,6})\b.+version\/([-\w\.]+)/i,
1234
+ /(opera)(?:.+version\/|[\/ ]+)([\w\.]+)/i
1235
+ ],
1236
+ [NAME, VERSION],
1237
+ [
1238
+ /opios[\/ ]+([\w\.]+)/i
1239
+ ],
1240
+ [VERSION, [NAME, OPERA + " Mini"]],
1241
+ [
1242
+ /\bopr\/([\w\.]+)/i
1243
+ ],
1244
+ [VERSION, [NAME, OPERA]],
1245
+ [
1246
+ /(kindle)\/([\w\.]+)/i,
1247
+ /(lunascape|maxthon|netfront|jasmine|blazer)[\/ ]?([\w\.]*)/i,
1248
+ /(avant |iemobile|slim)(?:browser)?[\/ ]?([\w\.]*)/i,
1249
+ /(ba?idubrowser)[\/ ]?([\w\.]+)/i,
1250
+ /(?:ms|\()(ie) ([\w\.]+)/i,
1251
+ /(flock|rockmelt|midori|epiphany|silk|skyfire|ovibrowser|bolt|iron|vivaldi|iridium|phantomjs|bowser|quark|qupzilla|falkon|rekonq|puffin|brave|whale|qqbrowserlite|qq|duckduckgo)\/([-\w\.]+)/i,
1252
+ /(weibo)__([\d\.]+)/i
1253
+ ],
1254
+ [NAME, VERSION],
1255
+ [
1256
+ /(?:\buc? ?browser|(?:juc.+)ucweb)[\/ ]?([\w\.]+)/i
1257
+ ],
1258
+ [VERSION, [NAME, "UC" + BROWSER]],
1259
+ [
1260
+ /microm.+\bqbcore\/([\w\.]+)/i,
1261
+ /\bqbcore\/([\w\.]+).+microm/i
1262
+ ],
1263
+ [VERSION, [NAME, "WeChat(Win) Desktop"]],
1264
+ [
1265
+ /micromessenger\/([\w\.]+)/i
1266
+ ],
1267
+ [VERSION, [NAME, "WeChat"]],
1268
+ [
1269
+ /konqueror\/([\w\.]+)/i
1270
+ ],
1271
+ [VERSION, [NAME, "Konqueror"]],
1272
+ [
1273
+ /trident.+rv[: ]([\w\.]{1,9})\b.+like gecko/i
1274
+ ],
1275
+ [VERSION, [NAME, "IE"]],
1276
+ [
1277
+ /yabrowser\/([\w\.]+)/i
1278
+ ],
1279
+ [VERSION, [NAME, "Yandex"]],
1280
+ [
1281
+ /(avast|avg)\/([\w\.]+)/i
1282
+ ],
1283
+ [[NAME, /(.+)/, "$1 Secure " + BROWSER], VERSION],
1284
+ [
1285
+ /\bfocus\/([\w\.]+)/i
1286
+ ],
1287
+ [VERSION, [NAME, FIREFOX + " Focus"]],
1288
+ [
1289
+ /\bopt\/([\w\.]+)/i
1290
+ ],
1291
+ [VERSION, [NAME, OPERA + " Touch"]],
1292
+ [
1293
+ /coc_coc\w+\/([\w\.]+)/i
1294
+ ],
1295
+ [VERSION, [NAME, "Coc Coc"]],
1296
+ [
1297
+ /dolfin\/([\w\.]+)/i
1298
+ ],
1299
+ [VERSION, [NAME, "Dolphin"]],
1300
+ [
1301
+ /coast\/([\w\.]+)/i
1302
+ ],
1303
+ [VERSION, [NAME, OPERA + " Coast"]],
1304
+ [
1305
+ /miuibrowser\/([\w\.]+)/i
1306
+ ],
1307
+ [VERSION, [NAME, "MIUI " + BROWSER]],
1308
+ [
1309
+ /fxios\/([-\w\.]+)/i
1310
+ ],
1311
+ [VERSION, [NAME, FIREFOX]],
1312
+ [
1313
+ /\bqihu|(qi?ho?o?|360)browser/i
1314
+ ],
1315
+ [[NAME, "360 " + BROWSER]],
1316
+ [
1317
+ /(oculus|samsung|sailfish|huawei)browser\/([\w\.]+)/i
1318
+ ],
1319
+ [[NAME, /(.+)/, "$1 " + BROWSER], VERSION],
1320
+ [
1321
+ /(comodo_dragon)\/([\w\.]+)/i
1322
+ ],
1323
+ [[NAME, /_/g, " "], VERSION],
1324
+ [
1325
+ /(electron)\/([\w\.]+) safari/i,
1326
+ /(tesla)(?: qtcarbrowser|\/(20\d\d\.[-\w\.]+))/i,
1327
+ /m?(qqbrowser|baiduboxapp|2345Explorer)[\/ ]?([\w\.]+)/i
1328
+ ],
1329
+ [NAME, VERSION],
1330
+ [
1331
+ /(metasr)[\/ ]?([\w\.]+)/i,
1332
+ /(lbbrowser)/i,
1333
+ /\[(linkedin)app\]/i
1334
+ ],
1335
+ [NAME],
1336
+ [
1337
+ /((?:fban\/fbios|fb_iab\/fb4a)(?!.+fbav)|;fbav\/([\w\.]+);)/i
1338
+ ],
1339
+ [[NAME, FACEBOOK], VERSION],
1340
+ [
1341
+ /safari (line)\/([\w\.]+)/i,
1342
+ /\b(line)\/([\w\.]+)\/iab/i,
1343
+ /(chromium|instagram)[\/ ]([-\w\.]+)/i
1344
+ ],
1345
+ [NAME, VERSION],
1346
+ [
1347
+ /\bgsa\/([\w\.]+) .*safari\//i
1348
+ ],
1349
+ [VERSION, [NAME, "GSA"]],
1350
+ [
1351
+ /headlesschrome(?:\/([\w\.]+)| )/i
1352
+ ],
1353
+ [VERSION, [NAME, CHROME + " Headless"]],
1354
+ [
1355
+ / wv\).+(chrome)\/([\w\.]+)/i
1356
+ ],
1357
+ [[NAME, CHROME + " WebView"], VERSION],
1358
+ [
1359
+ /droid.+ version\/([\w\.]+)\b.+(?:mobile safari|safari)/i
1360
+ ],
1361
+ [VERSION, [NAME, "Android " + BROWSER]],
1362
+ [
1363
+ /(chrome|omniweb|arora|[tizenoka]{5} ?browser)\/v?([\w\.]+)/i
1364
+ ],
1365
+ [NAME, VERSION],
1366
+ [
1367
+ /version\/([\w\.\,]+) .*mobile\/\w+ (safari)/i
1368
+ ],
1369
+ [VERSION, [NAME, "Mobile Safari"]],
1370
+ [
1371
+ /version\/([\w(\.|\,)]+) .*(mobile ?safari|safari)/i
1372
+ ],
1373
+ [VERSION, NAME],
1374
+ [
1375
+ /webkit.+?(mobile ?safari|safari)(\/[\w\.]+)/i
1376
+ ],
1377
+ [NAME, [VERSION, strMapper, oldSafariMap]],
1378
+ [
1379
+ /(webkit|khtml)\/([\w\.]+)/i
1380
+ ],
1381
+ [NAME, VERSION],
1382
+ [
1383
+ /(navigator|netscape\d?)\/([-\w\.]+)/i
1384
+ ],
1385
+ [[NAME, "Netscape"], VERSION],
1386
+ [
1387
+ /mobile vr; rv:([\w\.]+)\).+firefox/i
1388
+ ],
1389
+ [VERSION, [NAME, FIREFOX + " Reality"]],
1390
+ [
1391
+ /ekiohf.+(flow)\/([\w\.]+)/i,
1392
+ /(swiftfox)/i,
1393
+ /(icedragon|iceweasel|camino|chimera|fennec|maemo browser|minimo|conkeror|klar)[\/ ]?([\w\.\+]+)/i,
1394
+ /(seamonkey|k-meleon|icecat|iceape|firebird|phoenix|palemoon|basilisk|waterfox)\/([-\w\.]+)$/i,
1395
+ /(firefox)\/([\w\.]+)/i,
1396
+ /(mozilla)\/([\w\.]+) .+rv\:.+gecko\/\d+/i,
1397
+ /(polaris|lynx|dillo|icab|doris|amaya|w3m|netsurf|sleipnir|obigo|mosaic|(?:go|ice|up)[\. ]?browser)[-\/ ]?v?([\w\.]+)/i,
1398
+ /(links) \(([\w\.]+)/i
1399
+ ],
1400
+ [NAME, VERSION],
1401
+ [
1402
+ /(cobalt)\/([\w\.]+)/i
1403
+ ],
1404
+ [NAME, [VERSION, /master.|lts./, ""]]
1405
+ ],
1406
+ cpu: [
1407
+ [
1408
+ /(?:(amd|x(?:(?:86|64)[-_])?|wow|win)64)[;\)]/i
1409
+ ],
1410
+ [[ARCHITECTURE, "amd64"]],
1411
+ [
1412
+ /(ia32(?=;))/i
1413
+ ],
1414
+ [[ARCHITECTURE, lowerize]],
1415
+ [
1416
+ /((?:i[346]|x)86)[;\)]/i
1417
+ ],
1418
+ [[ARCHITECTURE, "ia32"]],
1419
+ [
1420
+ /\b(aarch64|arm(v?8e?l?|_?64))\b/i
1421
+ ],
1422
+ [[ARCHITECTURE, "arm64"]],
1423
+ [
1424
+ /\b(arm(?:v[67])?ht?n?[fl]p?)\b/i
1425
+ ],
1426
+ [[ARCHITECTURE, "armhf"]],
1427
+ [
1428
+ /windows (ce|mobile); ppc;/i
1429
+ ],
1430
+ [[ARCHITECTURE, "arm"]],
1431
+ [
1432
+ /((?:ppc|powerpc)(?:64)?)(?: mac|;|\))/i
1433
+ ],
1434
+ [[ARCHITECTURE, /ower/, EMPTY, lowerize]],
1435
+ [
1436
+ /(sun4\w)[;\)]/i
1437
+ ],
1438
+ [[ARCHITECTURE, "sparc"]],
1439
+ [
1440
+ /((?:avr32|ia64(?=;))|68k(?=\))|\barm(?=v(?:[1-7]|[5-7]1)l?|;|eabi)|(?=atmel )avr|(?:irix|mips|sparc)(?:64)?\b|pa-risc)/i
1441
+ ],
1442
+ [[ARCHITECTURE, lowerize]]
1443
+ ],
1444
+ device: [
1445
+ [
1446
+ /\b(sch-i[89]0\d|shw-m380s|sm-[ptx]\w{2,4}|gt-[pn]\d{2,4}|sgh-t8[56]9|nexus 10)/i
1447
+ ],
1448
+ [MODEL, [VENDOR, SAMSUNG], [TYPE, TABLET]],
1449
+ [
1450
+ /\b((?:s[cgp]h|gt|sm)-\w+|galaxy nexus)/i,
1451
+ /samsung[- ]([-\w]+)/i,
1452
+ /sec-(sgh\w+)/i
1453
+ ],
1454
+ [MODEL, [VENDOR, SAMSUNG], [TYPE, MOBILE]],
1455
+ [
1456
+ /\((ip(?:hone|od)[\w ]*);/i
1457
+ ],
1458
+ [MODEL, [VENDOR, APPLE], [TYPE, MOBILE]],
1459
+ [
1460
+ /\((ipad);[-\w\),; ]+apple/i,
1461
+ /applecoremedia\/[\w\.]+ \((ipad)/i,
1462
+ /\b(ipad)\d\d?,\d\d?[;\]].+ios/i
1463
+ ],
1464
+ [MODEL, [VENDOR, APPLE], [TYPE, TABLET]],
1465
+ [
1466
+ /(macintosh);/i
1467
+ ],
1468
+ [MODEL, [VENDOR, APPLE]],
1469
+ [
1470
+ /\b((?:ag[rs][23]?|bah2?|sht?|btv)-a?[lw]\d{2})\b(?!.+d\/s)/i
1471
+ ],
1472
+ [MODEL, [VENDOR, HUAWEI], [TYPE, TABLET]],
1473
+ [
1474
+ /(?:huawei|honor)([-\w ]+)[;\)]/i,
1475
+ /\b(nexus 6p|\w{2,4}e?-[atu]?[ln][\dx][012359c][adn]?)\b(?!.+d\/s)/i
1476
+ ],
1477
+ [MODEL, [VENDOR, HUAWEI], [TYPE, MOBILE]],
1478
+ [
1479
+ /\b(poco[\w ]+)(?: bui|\))/i,
1480
+ /\b; (\w+) build\/hm\1/i,
1481
+ /\b(hm[-_ ]?note?[_ ]?(?:\d\w)?) bui/i,
1482
+ /\b(redmi[\-_ ]?(?:note|k)?[\w_ ]+)(?: bui|\))/i,
1483
+ /\b(mi[-_ ]?(?:a\d|one|one[_ ]plus|note lte|max|cc)?[_ ]?(?:\d?\w?)[_ ]?(?:plus|se|lite)?)(?: bui|\))/i
1484
+ ],
1485
+ [[MODEL, /_/g, " "], [VENDOR, XIAOMI], [TYPE, MOBILE]],
1486
+ [
1487
+ /\b(mi[-_ ]?(?:pad)(?:[\w_ ]+))(?: bui|\))/i
1488
+ ],
1489
+ [[MODEL, /_/g, " "], [VENDOR, XIAOMI], [TYPE, TABLET]],
1490
+ [
1491
+ /; (\w+) bui.+ oppo/i,
1492
+ /\b(cph[12]\d{3}|p(?:af|c[al]|d\w|e[ar])[mt]\d0|x9007|a101op)\b/i
1493
+ ],
1494
+ [MODEL, [VENDOR, "OPPO"], [TYPE, MOBILE]],
1495
+ [
1496
+ /vivo (\w+)(?: bui|\))/i,
1497
+ /\b(v[12]\d{3}\w?[at])(?: bui|;)/i
1498
+ ],
1499
+ [MODEL, [VENDOR, "Vivo"], [TYPE, MOBILE]],
1500
+ [
1501
+ /\b(rmx[12]\d{3})(?: bui|;|\))/i
1502
+ ],
1503
+ [MODEL, [VENDOR, "Realme"], [TYPE, MOBILE]],
1504
+ [
1505
+ /\b(milestone|droid(?:[2-4x]| (?:bionic|x2|pro|razr))?:?( 4g)?)\b[\w ]+build\//i,
1506
+ /\bmot(?:orola)?[- ](\w*)/i,
1507
+ /((?:moto[\w\(\) ]+|xt\d{3,4}|nexus 6)(?= bui|\)))/i
1508
+ ],
1509
+ [MODEL, [VENDOR, MOTOROLA], [TYPE, MOBILE]],
1510
+ [
1511
+ /\b(mz60\d|xoom[2 ]{0,2}) build\//i
1512
+ ],
1513
+ [MODEL, [VENDOR, MOTOROLA], [TYPE, TABLET]],
1514
+ [
1515
+ /((?=lg)?[vl]k\-?\d{3}) bui| 3\.[-\w; ]{10}lg?-([06cv9]{3,4})/i
1516
+ ],
1517
+ [MODEL, [VENDOR, LG], [TYPE, TABLET]],
1518
+ [
1519
+ /(lm(?:-?f100[nv]?|-[\w\.]+)(?= bui|\))|nexus [45])/i,
1520
+ /\blg[-e;\/ ]+((?!browser|netcast|android tv)\w+)/i,
1521
+ /\blg-?([\d\w]+) bui/i
1522
+ ],
1523
+ [MODEL, [VENDOR, LG], [TYPE, MOBILE]],
1524
+ [
1525
+ /(ideatab[-\w ]+)/i,
1526
+ /lenovo ?(s[56]000[-\w]+|tab(?:[\w ]+)|yt[-\d\w]{6}|tb[-\d\w]{6})/i
1527
+ ],
1528
+ [MODEL, [VENDOR, "Lenovo"], [TYPE, TABLET]],
1529
+ [
1530
+ /(?:maemo|nokia).*(n900|lumia \d+)/i,
1531
+ /nokia[-_ ]?([-\w\.]*)/i
1532
+ ],
1533
+ [[MODEL, /_/g, " "], [VENDOR, "Nokia"], [TYPE, MOBILE]],
1534
+ [
1535
+ /(pixel c)\b/i
1536
+ ],
1537
+ [MODEL, [VENDOR, GOOGLE], [TYPE, TABLET]],
1538
+ [
1539
+ /droid.+; (pixel[\daxl ]{0,6})(?: bui|\))/i
1540
+ ],
1541
+ [MODEL, [VENDOR, GOOGLE], [TYPE, MOBILE]],
1542
+ [
1543
+ /droid.+ (a?\d[0-2]{2}so|[c-g]\d{4}|so[-gl]\w+|xq-a\w[4-7][12])(?= bui|\).+chrome\/(?![1-6]{0,1}\d\.))/i
1544
+ ],
1545
+ [MODEL, [VENDOR, SONY], [TYPE, MOBILE]],
1546
+ [
1547
+ /sony tablet [ps]/i,
1548
+ /\b(?:sony)?sgp\w+(?: bui|\))/i
1549
+ ],
1550
+ [[MODEL, "Xperia Tablet"], [VENDOR, SONY], [TYPE, TABLET]],
1551
+ [
1552
+ / (kb2005|in20[12]5|be20[12][59])\b/i,
1553
+ /(?:one)?(?:plus)? (a\d0\d\d)(?: b|\))/i
1554
+ ],
1555
+ [MODEL, [VENDOR, "OnePlus"], [TYPE, MOBILE]],
1556
+ [
1557
+ /(alexa)webm/i,
1558
+ /(kf[a-z]{2}wi)( bui|\))/i,
1559
+ /(kf[a-z]+)( bui|\)).+silk\//i
1560
+ ],
1561
+ [MODEL, [VENDOR, AMAZON], [TYPE, TABLET]],
1562
+ [
1563
+ /((?:sd|kf)[0349hijorstuw]+)( bui|\)).+silk\//i
1564
+ ],
1565
+ [[MODEL, /(.+)/g, "Fire Phone $1"], [VENDOR, AMAZON], [TYPE, MOBILE]],
1566
+ [
1567
+ /(playbook);[-\w\),; ]+(rim)/i
1568
+ ],
1569
+ [MODEL, VENDOR, [TYPE, TABLET]],
1570
+ [
1571
+ /\b((?:bb[a-f]|st[hv])100-\d)/i,
1572
+ /\(bb10; (\w+)/i
1573
+ ],
1574
+ [MODEL, [VENDOR, BLACKBERRY], [TYPE, MOBILE]],
1575
+ [
1576
+ /(?:\b|asus_)(transfo[prime ]{4,10} \w+|eeepc|slider \w+|nexus 7|padfone|p00[cj])/i
1577
+ ],
1578
+ [MODEL, [VENDOR, ASUS], [TYPE, TABLET]],
1579
+ [
1580
+ / (z[bes]6[027][012][km][ls]|zenfone \d\w?)\b/i
1581
+ ],
1582
+ [MODEL, [VENDOR, ASUS], [TYPE, MOBILE]],
1583
+ [
1584
+ /(nexus 9)/i
1585
+ ],
1586
+ [MODEL, [VENDOR, "HTC"], [TYPE, TABLET]],
1587
+ [
1588
+ /(htc)[-;_ ]{1,2}([\w ]+(?=\)| bui)|\w+)/i,
1589
+ /(zte)[- ]([\w ]+?)(?: bui|\/|\))/i,
1590
+ /(alcatel|geeksphone|nexian|panasonic|sony(?!-bra))[-_ ]?([-\w]*)/i
1591
+ ],
1592
+ [VENDOR, [MODEL, /_/g, " "], [TYPE, MOBILE]],
1593
+ [
1594
+ /droid.+; ([ab][1-7]-?[0178a]\d\d?)/i
1595
+ ],
1596
+ [MODEL, [VENDOR, "Acer"], [TYPE, TABLET]],
1597
+ [
1598
+ /droid.+; (m[1-5] note) bui/i,
1599
+ /\bmz-([-\w]{2,})/i
1600
+ ],
1601
+ [MODEL, [VENDOR, "Meizu"], [TYPE, MOBILE]],
1602
+ [
1603
+ /\b(sh-?[altvz]?\d\d[a-ekm]?)/i
1604
+ ],
1605
+ [MODEL, [VENDOR, SHARP], [TYPE, MOBILE]],
1606
+ [
1607
+ /(blackberry|benq|palm(?=\-)|sonyericsson|acer|asus|dell|meizu|motorola|polytron)[-_ ]?([-\w]*)/i,
1608
+ /(hp) ([\w ]+\w)/i,
1609
+ /(asus)-?(\w+)/i,
1610
+ /(microsoft); (lumia[\w ]+)/i,
1611
+ /(lenovo)[-_ ]?([-\w]+)/i,
1612
+ /(jolla)/i,
1613
+ /(oppo) ?([\w ]+) bui/i
1614
+ ],
1615
+ [VENDOR, MODEL, [TYPE, MOBILE]],
1616
+ [
1617
+ /(archos) (gamepad2?)/i,
1618
+ /(hp).+(touchpad(?!.+tablet)|tablet)/i,
1619
+ /(kindle)\/([\w\.]+)/i,
1620
+ /(nook)[\w ]+build\/(\w+)/i,
1621
+ /(dell) (strea[kpr\d ]*[\dko])/i,
1622
+ /(le[- ]+pan)[- ]+(\w{1,9}) bui/i,
1623
+ /(trinity)[- ]*(t\d{3}) bui/i,
1624
+ /(gigaset)[- ]+(q\w{1,9}) bui/i,
1625
+ /(vodafone) ([\w ]+)(?:\)| bui)/i
1626
+ ],
1627
+ [VENDOR, MODEL, [TYPE, TABLET]],
1628
+ [
1629
+ /(surface duo)/i
1630
+ ],
1631
+ [MODEL, [VENDOR, MICROSOFT], [TYPE, TABLET]],
1632
+ [
1633
+ /droid [\d\.]+; (fp\du?)(?: b|\))/i
1634
+ ],
1635
+ [MODEL, [VENDOR, "Fairphone"], [TYPE, MOBILE]],
1636
+ [
1637
+ /(u304aa)/i
1638
+ ],
1639
+ [MODEL, [VENDOR, "AT&T"], [TYPE, MOBILE]],
1640
+ [
1641
+ /\bsie-(\w*)/i
1642
+ ],
1643
+ [MODEL, [VENDOR, "Siemens"], [TYPE, MOBILE]],
1644
+ [
1645
+ /\b(rct\w+) b/i
1646
+ ],
1647
+ [MODEL, [VENDOR, "RCA"], [TYPE, TABLET]],
1648
+ [
1649
+ /\b(venue[\d ]{2,7}) b/i
1650
+ ],
1651
+ [MODEL, [VENDOR, "Dell"], [TYPE, TABLET]],
1652
+ [
1653
+ /\b(q(?:mv|ta)\w+) b/i
1654
+ ],
1655
+ [MODEL, [VENDOR, "Verizon"], [TYPE, TABLET]],
1656
+ [
1657
+ /\b(?:barnes[& ]+noble |bn[rt])([\w\+ ]*) b/i
1658
+ ],
1659
+ [MODEL, [VENDOR, "Barnes & Noble"], [TYPE, TABLET]],
1660
+ [
1661
+ /\b(tm\d{3}\w+) b/i
1662
+ ],
1663
+ [MODEL, [VENDOR, "NuVision"], [TYPE, TABLET]],
1664
+ [
1665
+ /\b(k88) b/i
1666
+ ],
1667
+ [MODEL, [VENDOR, "ZTE"], [TYPE, TABLET]],
1668
+ [
1669
+ /\b(nx\d{3}j) b/i
1670
+ ],
1671
+ [MODEL, [VENDOR, "ZTE"], [TYPE, MOBILE]],
1672
+ [
1673
+ /\b(gen\d{3}) b.+49h/i
1674
+ ],
1675
+ [MODEL, [VENDOR, "Swiss"], [TYPE, MOBILE]],
1676
+ [
1677
+ /\b(zur\d{3}) b/i
1678
+ ],
1679
+ [MODEL, [VENDOR, "Swiss"], [TYPE, TABLET]],
1680
+ [
1681
+ /\b((zeki)?tb.*\b) b/i
1682
+ ],
1683
+ [MODEL, [VENDOR, "Zeki"], [TYPE, TABLET]],
1684
+ [
1685
+ /\b([yr]\d{2}) b/i,
1686
+ /\b(dragon[- ]+touch |dt)(\w{5}) b/i
1687
+ ],
1688
+ [[VENDOR, "Dragon Touch"], MODEL, [TYPE, TABLET]],
1689
+ [
1690
+ /\b(ns-?\w{0,9}) b/i
1691
+ ],
1692
+ [MODEL, [VENDOR, "Insignia"], [TYPE, TABLET]],
1693
+ [
1694
+ /\b((nxa|next)-?\w{0,9}) b/i
1695
+ ],
1696
+ [MODEL, [VENDOR, "NextBook"], [TYPE, TABLET]],
1697
+ [
1698
+ /\b(xtreme\_)?(v(1[045]|2[015]|[3469]0|7[05])) b/i
1699
+ ],
1700
+ [[VENDOR, "Voice"], MODEL, [TYPE, MOBILE]],
1701
+ [
1702
+ /\b(lvtel\-)?(v1[12]) b/i
1703
+ ],
1704
+ [[VENDOR, "LvTel"], MODEL, [TYPE, MOBILE]],
1705
+ [
1706
+ /\b(ph-1) /i
1707
+ ],
1708
+ [MODEL, [VENDOR, "Essential"], [TYPE, MOBILE]],
1709
+ [
1710
+ /\b(v(100md|700na|7011|917g).*\b) b/i
1711
+ ],
1712
+ [MODEL, [VENDOR, "Envizen"], [TYPE, TABLET]],
1713
+ [
1714
+ /\b(trio[-\w\. ]+) b/i
1715
+ ],
1716
+ [MODEL, [VENDOR, "MachSpeed"], [TYPE, TABLET]],
1717
+ [
1718
+ /\btu_(1491) b/i
1719
+ ],
1720
+ [MODEL, [VENDOR, "Rotor"], [TYPE, TABLET]],
1721
+ [
1722
+ /(shield[\w ]+) b/i
1723
+ ],
1724
+ [MODEL, [VENDOR, "Nvidia"], [TYPE, TABLET]],
1725
+ [
1726
+ /(sprint) (\w+)/i
1727
+ ],
1728
+ [VENDOR, MODEL, [TYPE, MOBILE]],
1729
+ [
1730
+ /(kin\.[onetw]{3})/i
1731
+ ],
1732
+ [[MODEL, /\./g, " "], [VENDOR, MICROSOFT], [TYPE, MOBILE]],
1733
+ [
1734
+ /droid.+; (cc6666?|et5[16]|mc[239][23]x?|vc8[03]x?)\)/i
1735
+ ],
1736
+ [MODEL, [VENDOR, ZEBRA], [TYPE, TABLET]],
1737
+ [
1738
+ /droid.+; (ec30|ps20|tc[2-8]\d[kx])\)/i
1739
+ ],
1740
+ [MODEL, [VENDOR, ZEBRA], [TYPE, MOBILE]],
1741
+ [
1742
+ /(ouya)/i,
1743
+ /(nintendo) ([wids3utch]+)/i
1744
+ ],
1745
+ [VENDOR, MODEL, [TYPE, CONSOLE]],
1746
+ [
1747
+ /droid.+; (shield) bui/i
1748
+ ],
1749
+ [MODEL, [VENDOR, "Nvidia"], [TYPE, CONSOLE]],
1750
+ [
1751
+ /(playstation [345portablevi]+)/i
1752
+ ],
1753
+ [MODEL, [VENDOR, SONY], [TYPE, CONSOLE]],
1754
+ [
1755
+ /\b(xbox(?: one)?(?!; xbox))[\); ]/i
1756
+ ],
1757
+ [MODEL, [VENDOR, MICROSOFT], [TYPE, CONSOLE]],
1758
+ [
1759
+ /smart-tv.+(samsung)/i
1760
+ ],
1761
+ [VENDOR, [TYPE, SMARTTV]],
1762
+ [
1763
+ /hbbtv.+maple;(\d+)/i
1764
+ ],
1765
+ [[MODEL, /^/, "SmartTV"], [VENDOR, SAMSUNG], [TYPE, SMARTTV]],
1766
+ [
1767
+ /(nux; netcast.+smarttv|lg (netcast\.tv-201\d|android tv))/i
1768
+ ],
1769
+ [[VENDOR, LG], [TYPE, SMARTTV]],
1770
+ [
1771
+ /(apple) ?tv/i
1772
+ ],
1773
+ [VENDOR, [MODEL, APPLE + " TV"], [TYPE, SMARTTV]],
1774
+ [
1775
+ /crkey/i
1776
+ ],
1777
+ [[MODEL, CHROME + "cast"], [VENDOR, GOOGLE], [TYPE, SMARTTV]],
1778
+ [
1779
+ /droid.+aft(\w)( bui|\))/i
1780
+ ],
1781
+ [MODEL, [VENDOR, AMAZON], [TYPE, SMARTTV]],
1782
+ [
1783
+ /\(dtv[\);].+(aquos)/i,
1784
+ /(aquos-tv[\w ]+)\)/i
1785
+ ],
1786
+ [MODEL, [VENDOR, SHARP], [TYPE, SMARTTV]],
1787
+ [
1788
+ /(bravia[\w ]+)( bui|\))/i
1789
+ ],
1790
+ [MODEL, [VENDOR, SONY], [TYPE, SMARTTV]],
1791
+ [
1792
+ /(mitv-\w{5}) bui/i
1793
+ ],
1794
+ [MODEL, [VENDOR, XIAOMI], [TYPE, SMARTTV]],
1795
+ [
1796
+ /\b(roku)[\dx]*[\)\/]((?:dvp-)?[\d\.]*)/i,
1797
+ /hbbtv\/\d+\.\d+\.\d+ +\([\w ]*; *(\w[^;]*);([^;]*)/i
1798
+ ],
1799
+ [[VENDOR, trim], [MODEL, trim], [TYPE, SMARTTV]],
1800
+ [
1801
+ /\b(android tv|smart[- ]?tv|opera tv|tv; rv:)\b/i
1802
+ ],
1803
+ [[TYPE, SMARTTV]],
1804
+ [
1805
+ /((pebble))app/i
1806
+ ],
1807
+ [VENDOR, MODEL, [TYPE, WEARABLE]],
1808
+ [
1809
+ /droid.+; (glass) \d/i
1810
+ ],
1811
+ [MODEL, [VENDOR, GOOGLE], [TYPE, WEARABLE]],
1812
+ [
1813
+ /droid.+; (wt63?0{2,3})\)/i
1814
+ ],
1815
+ [MODEL, [VENDOR, ZEBRA], [TYPE, WEARABLE]],
1816
+ [
1817
+ /(quest( 2)?)/i
1818
+ ],
1819
+ [MODEL, [VENDOR, FACEBOOK], [TYPE, WEARABLE]],
1820
+ [
1821
+ /(tesla)(?: qtcarbrowser|\/[-\w\.]+)/i
1822
+ ],
1823
+ [VENDOR, [TYPE, EMBEDDED]],
1824
+ [
1825
+ /droid .+?; ([^;]+?)(?: bui|\) applew).+? mobile safari/i
1826
+ ],
1827
+ [MODEL, [TYPE, MOBILE]],
1828
+ [
1829
+ /droid .+?; ([^;]+?)(?: bui|\) applew).+?(?! mobile) safari/i
1830
+ ],
1831
+ [MODEL, [TYPE, TABLET]],
1832
+ [
1833
+ /\b((tablet|tab)[;\/]|focus\/\d(?!.+mobile))/i
1834
+ ],
1835
+ [[TYPE, TABLET]],
1836
+ [
1837
+ /(phone|mobile(?:[;\/]| [ \w\/\.]*safari)|pda(?=.+windows ce))/i
1838
+ ],
1839
+ [[TYPE, MOBILE]],
1840
+ [
1841
+ /(android[-\w\. ]{0,9});.+buil/i
1842
+ ],
1843
+ [MODEL, [VENDOR, "Generic"]]
1844
+ ],
1845
+ engine: [
1846
+ [
1847
+ /windows.+ edge\/([\w\.]+)/i
1848
+ ],
1849
+ [VERSION, [NAME, EDGE + "HTML"]],
1850
+ [
1851
+ /webkit\/537\.36.+chrome\/(?!27)([\w\.]+)/i
1852
+ ],
1853
+ [VERSION, [NAME, "Blink"]],
1854
+ [
1855
+ /(presto)\/([\w\.]+)/i,
1856
+ /(webkit|trident|netfront|netsurf|amaya|lynx|w3m|goanna)\/([\w\.]+)/i,
1857
+ /ekioh(flow)\/([\w\.]+)/i,
1858
+ /(khtml|tasman|links)[\/ ]\(?([\w\.]+)/i,
1859
+ /(icab)[\/ ]([23]\.[\d\.]+)/i
1860
+ ],
1861
+ [NAME, VERSION],
1862
+ [
1863
+ /rv\:([\w\.]{1,9})\b.+(gecko)/i
1864
+ ],
1865
+ [VERSION, NAME]
1866
+ ],
1867
+ os: [
1868
+ [
1869
+ /microsoft (windows) (vista|xp)/i
1870
+ ],
1871
+ [NAME, VERSION],
1872
+ [
1873
+ /(windows) nt 6\.2; (arm)/i,
1874
+ /(windows (?:phone(?: os)?|mobile))[\/ ]?([\d\.\w ]*)/i,
1875
+ /(windows)[\/ ]?([ntce\d\. ]+\w)(?!.+xbox)/i
1876
+ ],
1877
+ [NAME, [VERSION, strMapper, windowsVersionMap]],
1878
+ [
1879
+ /(win(?=3|9|n)|win 9x )([nt\d\.]+)/i
1880
+ ],
1881
+ [[NAME, "Windows"], [VERSION, strMapper, windowsVersionMap]],
1882
+ [
1883
+ /ip[honead]{2,4}\b(?:.*os ([\w]+) like mac|; opera)/i,
1884
+ /cfnetwork\/.+darwin/i
1885
+ ],
1886
+ [[VERSION, /_/g, "."], [NAME, "iOS"]],
1887
+ [
1888
+ /(mac os x) ?([\w\. ]*)/i,
1889
+ /(macintosh|mac_powerpc\b)(?!.+haiku)/i
1890
+ ],
1891
+ [[NAME, "Mac OS"], [VERSION, /_/g, "."]],
1892
+ [
1893
+ /droid ([\w\.]+)\b.+(android[- ]x86|harmonyos)/i
1894
+ ],
1895
+ [VERSION, NAME],
1896
+ [
1897
+ /(android|webos|qnx|bada|rim tablet os|maemo|meego|sailfish)[-\/ ]?([\w\.]*)/i,
1898
+ /(blackberry)\w*\/([\w\.]*)/i,
1899
+ /(tizen|kaios)[\/ ]([\w\.]+)/i,
1900
+ /\((series40);/i
1901
+ ],
1902
+ [NAME, VERSION],
1903
+ [
1904
+ /\(bb(10);/i
1905
+ ],
1906
+ [VERSION, [NAME, BLACKBERRY]],
1907
+ [
1908
+ /(?:symbian ?os|symbos|s60(?=;)|series60)[-\/ ]?([\w\.]*)/i
1909
+ ],
1910
+ [VERSION, [NAME, "Symbian"]],
1911
+ [
1912
+ /mozilla\/[\d\.]+ \((?:mobile|tablet|tv|mobile; [\w ]+); rv:.+ gecko\/([\w\.]+)/i
1913
+ ],
1914
+ [VERSION, [NAME, FIREFOX + " OS"]],
1915
+ [
1916
+ /web0s;.+rt(tv)/i,
1917
+ /\b(?:hp)?wos(?:browser)?\/([\w\.]+)/i
1918
+ ],
1919
+ [VERSION, [NAME, "webOS"]],
1920
+ [
1921
+ /crkey\/([\d\.]+)/i
1922
+ ],
1923
+ [VERSION, [NAME, CHROME + "cast"]],
1924
+ [
1925
+ /(cros) [\w]+ ([\w\.]+\w)/i
1926
+ ],
1927
+ [[NAME, "Chromium OS"], VERSION],
1928
+ [
1929
+ /(nintendo|playstation) ([wids345portablevuch]+)/i,
1930
+ /(xbox); +xbox ([^\);]+)/i,
1931
+ /\b(joli|palm)\b ?(?:os)?\/?([\w\.]*)/i,
1932
+ /(mint)[\/\(\) ]?(\w*)/i,
1933
+ /(mageia|vectorlinux)[; ]/i,
1934
+ /([kxln]?ubuntu|debian|suse|opensuse|gentoo|arch(?= linux)|slackware|fedora|mandriva|centos|pclinuxos|red ?hat|zenwalk|linpus|raspbian|plan 9|minix|risc os|contiki|deepin|manjaro|elementary os|sabayon|linspire)(?: gnu\/linux)?(?: enterprise)?(?:[- ]linux)?(?:-gnu)?[-\/ ]?(?!chrom|package)([-\w\.]*)/i,
1935
+ /(hurd|linux) ?([\w\.]*)/i,
1936
+ /(gnu) ?([\w\.]*)/i,
1937
+ /\b([-frentopcghs]{0,5}bsd|dragonfly)[\/ ]?(?!amd|[ix346]{1,2}86)([\w\.]*)/i,
1938
+ /(haiku) (\w+)/i
1939
+ ],
1940
+ [NAME, VERSION],
1941
+ [
1942
+ /(sunos) ?([\w\.\d]*)/i
1943
+ ],
1944
+ [[NAME, "Solaris"], VERSION],
1945
+ [
1946
+ /((?:open)?solaris)[-\/ ]?([\w\.]*)/i,
1947
+ /(aix) ((\d)(?=\.|\)| )[\w\.])*/i,
1948
+ /\b(beos|os\/2|amigaos|morphos|openvms|fuchsia|hp-ux)/i,
1949
+ /(unix) ?([\w\.]*)/i
1950
+ ],
1951
+ [NAME, VERSION]
1952
+ ]
1953
+ };
1954
+ var UAParser = function(ua, extensions) {
1955
+ if (typeof ua === OBJ_TYPE) {
1956
+ extensions = ua;
1957
+ ua = undefined$1;
1958
+ }
1959
+ if (!(this instanceof UAParser)) {
1960
+ return new UAParser(ua, extensions).getResult();
1961
+ }
1962
+ var _ua = ua || (typeof window2 !== UNDEF_TYPE && window2.navigator && window2.navigator.userAgent ? window2.navigator.userAgent : EMPTY);
1963
+ var _rgxmap = extensions ? extend(regexes, extensions) : regexes;
1964
+ this.getBrowser = function() {
1965
+ var _browser = {};
1966
+ _browser[NAME] = undefined$1;
1967
+ _browser[VERSION] = undefined$1;
1968
+ rgxMapper.call(_browser, _ua, _rgxmap.browser);
1969
+ _browser.major = majorize(_browser.version);
1970
+ return _browser;
1971
+ };
1972
+ this.getCPU = function() {
1973
+ var _cpu = {};
1974
+ _cpu[ARCHITECTURE] = undefined$1;
1975
+ rgxMapper.call(_cpu, _ua, _rgxmap.cpu);
1976
+ return _cpu;
1977
+ };
1978
+ this.getDevice = function() {
1979
+ var _device = {};
1980
+ _device[VENDOR] = undefined$1;
1981
+ _device[MODEL] = undefined$1;
1982
+ _device[TYPE] = undefined$1;
1983
+ rgxMapper.call(_device, _ua, _rgxmap.device);
1984
+ return _device;
1985
+ };
1986
+ this.getEngine = function() {
1987
+ var _engine = {};
1988
+ _engine[NAME] = undefined$1;
1989
+ _engine[VERSION] = undefined$1;
1990
+ rgxMapper.call(_engine, _ua, _rgxmap.engine);
1991
+ return _engine;
1992
+ };
1993
+ this.getOS = function() {
1994
+ var _os = {};
1995
+ _os[NAME] = undefined$1;
1996
+ _os[VERSION] = undefined$1;
1997
+ rgxMapper.call(_os, _ua, _rgxmap.os);
1998
+ return _os;
1999
+ };
2000
+ this.getResult = function() {
2001
+ return {
2002
+ ua: this.getUA(),
2003
+ browser: this.getBrowser(),
2004
+ engine: this.getEngine(),
2005
+ os: this.getOS(),
2006
+ device: this.getDevice(),
2007
+ cpu: this.getCPU()
2008
+ };
2009
+ };
2010
+ this.getUA = function() {
2011
+ return _ua;
2012
+ };
2013
+ this.setUA = function(ua2) {
2014
+ _ua = typeof ua2 === STR_TYPE && ua2.length > UA_MAX_LENGTH ? trim(ua2, UA_MAX_LENGTH) : ua2;
2015
+ return this;
2016
+ };
2017
+ this.setUA(_ua);
2018
+ return this;
2019
+ };
2020
+ UAParser.VERSION = LIBVERSION;
2021
+ UAParser.BROWSER = enumerize([NAME, VERSION, MAJOR]);
2022
+ UAParser.CPU = enumerize([ARCHITECTURE]);
2023
+ UAParser.DEVICE = enumerize([MODEL, VENDOR, TYPE, CONSOLE, MOBILE, SMARTTV, TABLET, WEARABLE, EMBEDDED]);
2024
+ UAParser.ENGINE = UAParser.OS = enumerize([NAME, VERSION]);
2025
+ {
2026
+ if (module2.exports) {
2027
+ exports2 = module2.exports = UAParser;
2028
+ }
2029
+ exports2.UAParser = UAParser;
2030
+ }
2031
+ var $ = typeof window2 !== UNDEF_TYPE && (window2.jQuery || window2.Zepto);
2032
+ if ($ && !$.ua) {
2033
+ var parser = new UAParser();
2034
+ $.ua = parser.getResult();
2035
+ $.ua.get = function() {
2036
+ return parser.getUA();
2037
+ };
2038
+ $.ua.set = function(ua) {
2039
+ parser.setUA(ua);
2040
+ var result = parser.getResult();
2041
+ for (var prop in result) {
2042
+ $.ua[prop] = result[prop];
2043
+ }
2044
+ };
2045
+ }
2046
+ })(typeof window === "object" ? window : commonjsGlobal);
2047
+ })(uaParser, uaParser.exports);
2048
+ var __defProp2 = Object.defineProperty;
2049
+ var __defNormalProp2 = (obj, key, value) => key in obj ? __defProp2(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
2050
+ var __publicField2 = (obj, key, value) => {
2051
+ __defNormalProp2(obj, typeof key !== "symbol" ? key + "" : key, value);
2052
+ return value;
2053
+ };
2054
+ const Browser = {
2055
+ UNKNOWN: "Unknown",
2056
+ SAFARI: "Safari",
2057
+ FIREFOX: "Firefox",
2058
+ OPERA: "Opera",
2059
+ CHROME: "Chrome",
2060
+ IOS_WEBVIEW: "iOS-webview"
2061
+ };
2062
+ class BrowserUtils {
2063
+ static getName() {
2064
+ if (!this._name) {
2065
+ if (typeof navigator === "undefined" || !navigator) {
2066
+ this._name = Browser.UNKNOWN;
2067
+ } else {
2068
+ const { userAgent } = navigator;
2069
+ if (userAgent.match(/Firefox/i)) {
2070
+ this._name = Browser.FIREFOX;
2071
+ } else if (userAgent.match(/(Opera|OPR)/i)) {
2072
+ this._name = Browser.OPERA;
2073
+ } else if (userAgent.match(/Chrome/i)) {
2074
+ this._name = Browser.CHROME;
2075
+ } else if (userAgent.match(/Safari/i)) {
2076
+ this._name = Browser.SAFARI;
2077
+ } else if (userAgent.match(/(iPhone|iPod|iPad).*AppleWebKit(?!.*Version)/i)) {
2078
+ this._name = Browser.IOS_WEBVIEW;
2079
+ } else {
2080
+ this._name = Browser.UNKNOWN;
2081
+ }
1176
2082
  }
1177
- throw Error("Level of: " + this.coords.toString() + " cannot be decided");
1178
2083
  }
2084
+ return this._name;
1179
2085
  }
1180
- _inferNodeLevelByNeighboors() {
1181
- const { level } = this.coords;
1182
- if (level === null || !Level.isRange(level)) {
1183
- return true;
2086
+ static get isMobile() {
2087
+ if (this._isMobile === null) {
2088
+ this._isMobile = false;
2089
+ if (typeof navigator !== "undefined" && navigator) {
2090
+ const userAgent = navigator.userAgent || navigator.vendor;
2091
+ if (userAgent && (/(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows ce|xda|xiino|android|ipad|playbook|silk/i.test(userAgent) || /1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i.test(userAgent.substr(0, 4)))) {
2092
+ this._isMobile = true;
2093
+ }
2094
+ }
1184
2095
  }
1185
- let tmpLevel = null;
1186
- for (let i = 0; i < this.edges.length; i++) {
1187
- const edge = this.edges[i];
1188
- const otherNode = edge.node1 === this ? edge.node2 : edge.node1;
1189
- tmpLevel = Level.union(otherNode.coords.level, tmpLevel);
2096
+ return this._isMobile;
2097
+ }
2098
+ static clearCache() {
2099
+ this._name = null;
2100
+ this._isMobile = null;
2101
+ }
2102
+ }
2103
+ __publicField2(BrowserUtils, "_name", null);
2104
+ __publicField2(BrowserUtils, "_isMobile", null);
2105
+ const _GraphVertex = class {
2106
+ constructor(params = {}) {
2107
+ __publicField2(this, "name", null);
2108
+ __publicField2(this, "data", null);
2109
+ __publicField2(this, "id");
2110
+ __publicField2(this, "edges", []);
2111
+ Object.assign(this, params);
2112
+ if (typeof params.id === "number") {
2113
+ this.id = params.id;
2114
+ GraphEdge.currentUniqueId = Math.max(GraphEdge.currentUniqueId, params.id + 1);
2115
+ } else {
2116
+ this.id = _GraphVertex.currentUniqueId++;
1190
2117
  }
1191
- if (tmpLevel === null || !Level.isRange(tmpLevel)) {
1192
- this.coords.level = tmpLevel === level[0] ? level[1] : level[0];
2118
+ }
2119
+ };
2120
+ let GraphVertex = _GraphVertex;
2121
+ __publicField2(GraphVertex, "currentUniqueId", 0);
2122
+ const _GraphEdge = class {
2123
+ constructor(vertex1, vertex2, params = {}) {
2124
+ __publicField2(this, "name", null);
2125
+ __publicField2(this, "data", null);
2126
+ __publicField2(this, "id");
2127
+ __publicField2(this, "_vertex1");
2128
+ __publicField2(this, "_vertex2");
2129
+ Object.assign(this, params);
2130
+ this.vertex1 = vertex1;
2131
+ this.vertex2 = vertex2;
2132
+ if (typeof params.id === "number") {
2133
+ this.id = params.id;
2134
+ _GraphEdge.currentUniqueId = Math.max(_GraphEdge.currentUniqueId, params.id + 1);
2135
+ } else {
2136
+ this.id = GraphVertex.currentUniqueId++;
1193
2137
  }
1194
- return true;
1195
2138
  }
1196
- _checkIO() {
1197
- this.io = this.coords.level !== null && this.edges.some((edge) => edge.level === null);
1198
- return true;
2139
+ get vertex1() {
2140
+ return this._vertex1;
2141
+ }
2142
+ set vertex1(vertex) {
2143
+ if (this._vertex1 && this._vertex2 !== this._vertex1) {
2144
+ this._vertex1.edges = this._vertex1.edges.filter((edge) => edge !== this);
2145
+ }
2146
+ vertex.edges.push(this);
2147
+ this._vertex1 = vertex;
2148
+ }
2149
+ get vertex2() {
2150
+ return this._vertex2;
2151
+ }
2152
+ set vertex2(vertex) {
2153
+ if (this._vertex2 && this._vertex2 !== this._vertex1) {
2154
+ this._vertex2.edges = this._vertex2.edges.filter((edge) => edge !== this);
2155
+ }
2156
+ vertex.edges.push(this);
2157
+ this._vertex2 = vertex;
2158
+ }
2159
+ static getEdgeByVertices(edges, vertex1, vertex2) {
2160
+ return edges.find(
2161
+ (edge) => vertex1 === edge.vertex1 && vertex2 === edge.vertex2 || vertex2 === edge.vertex1 && vertex1 === edge.vertex2
2162
+ );
2163
+ }
2164
+ };
2165
+ let GraphEdge = _GraphEdge;
2166
+ __publicField2(GraphEdge, "currentUniqueId", 0);
2167
+ class Graph {
2168
+ constructor(vertices, edges) {
2169
+ __publicField2(this, "vertices");
2170
+ __publicField2(this, "edges");
2171
+ this.vertices = Array.isArray(vertices) ? vertices : [];
2172
+ this.edges = Array.isArray(edges) ? edges : [];
2173
+ }
2174
+ getEdgeByVertices(vertex1, vertex2) {
2175
+ return GraphEdge.getEdgeByVertices(this.edges, vertex1, vertex2);
2176
+ }
2177
+ getVertexByName(name) {
2178
+ return this.vertices.find((vertex) => vertex.name === name);
1199
2179
  }
1200
- static generateNodesLevels(nodes) {
1201
- nodes.forEach((node) => node._generateLevelFromEdges());
1202
- nodes.forEach((node) => node._inferNodeLevelByNeighboors());
1203
- nodes.forEach((node) => node._inferNodeLevelByRecursion());
1204
- nodes.forEach((node) => node._checkIO());
2180
+ getEdgeByName(name) {
2181
+ return this.edges.find((edge) => edge.name === name);
2182
+ }
2183
+ toDetailedString() {
2184
+ let output = `--- Network ---
2185
+ Vertices: ${this.vertices.length}
2186
+ Edges: ${this.edges.length}
2187
+ ---
2188
+ Vertices
2189
+ `;
2190
+ this.vertices.forEach((vertex) => {
2191
+ output += `${vertex.id} [edges: ${vertex.edges.length}]
2192
+ `;
2193
+ });
2194
+ output += "---\nEdges\n";
2195
+ this.edges.forEach((edge) => {
2196
+ output += `${edge.id} `;
2197
+ output += `[${edge.vertex1.id} -- ${edge.vertex2.id}]
2198
+ `;
2199
+ });
2200
+ output += "---";
2201
+ return output;
1205
2202
  }
1206
2203
  }
1207
- class GraphEdge {
1208
- constructor(node1, node2, level = null, builtFrom = null) {
1209
- __publicField(this, "_node1");
1210
- __publicField(this, "_node2");
2204
+ class GeoGraphEdge extends GraphEdge {
2205
+ constructor(vertex1, vertex2, params) {
2206
+ super(vertex1, vertex2, params);
1211
2207
  __publicField(this, "_level", null);
1212
2208
  __publicField(this, "_bearing", null);
1213
2209
  __publicField(this, "_length", null);
1214
2210
  __publicField(this, "_computedSizeAndBearing", false);
1215
- __publicField(this, "builtFrom");
1216
2211
  __publicField(this, "isOneway", false);
1217
- this.node1 = node1;
1218
- this.node2 = node2;
1219
- this.level = level;
1220
- this.builtFrom = builtFrom;
1221
- }
1222
- get node1() {
1223
- return this._node1;
2212
+ Object.assign(this, params);
1224
2213
  }
1225
- set node1(node) {
1226
- if (!(node instanceof GraphNode)) {
1227
- throw new TypeError("node1 is not a GraphNode");
1228
- }
1229
- if (this._node1 instanceof GraphNode && this._node2 !== this._node1) {
1230
- this._node1.edges = this._node1.edges.filter((edge) => edge !== this);
1231
- }
1232
- node.edges.push(this);
1233
- this._node1 = node;
2214
+ set vertex1(vertex) {
2215
+ super.vertex1 = vertex;
1234
2216
  this._computedSizeAndBearing = false;
1235
2217
  }
1236
- get node2() {
1237
- return this._node2;
2218
+ get vertex1() {
2219
+ return this._vertex1;
1238
2220
  }
1239
- set node2(node) {
1240
- if (!(node instanceof GraphNode)) {
1241
- throw new TypeError("node2 is not a GraphNode");
1242
- }
1243
- if (this._node2 instanceof GraphNode && this._node2 !== this._node1) {
1244
- this._node2.edges = this._node2.edges.filter((edge) => edge !== this);
1245
- }
1246
- node.edges.push(this);
1247
- this._node2 = node;
2221
+ set vertex2(vertex) {
2222
+ super.vertex2 = vertex;
1248
2223
  this._computedSizeAndBearing = false;
1249
2224
  }
2225
+ get vertex2() {
2226
+ return this._vertex2;
2227
+ }
1250
2228
  get level() {
1251
2229
  return this._level;
1252
2230
  }
@@ -1267,159 +2245,206 @@ class GraphEdge {
1267
2245
  return this._length;
1268
2246
  }
1269
2247
  _computeSizeAndBearing() {
1270
- this._length = this.node1.distanceTo(this.node2);
1271
- this._bearing = this.node1.bearingTo(this.node2);
2248
+ this._length = this.vertex1.distanceTo(this.vertex2);
2249
+ this._bearing = this.vertex1.bearingTo(this.vertex2);
1272
2250
  this._computedSizeAndBearing = true;
1273
2251
  }
1274
- equals(other) {
1275
- if (this === other) {
2252
+ static getEdgeByVertices(edges, vertex1, vertex2) {
2253
+ return super.getEdgeByVertices(edges, vertex1, vertex2);
2254
+ }
2255
+ }
2256
+ class GeoGraphVertex extends GraphVertex {
2257
+ constructor(coords, params) {
2258
+ super(params);
2259
+ __publicField(this, "coords");
2260
+ __publicField(this, "io", false);
2261
+ this.coords = coords;
2262
+ }
2263
+ distanceTo(other) {
2264
+ return this.coords.distanceTo(other.coords);
2265
+ }
2266
+ bearingTo(other) {
2267
+ return this.coords.bearingTo(other.coords);
2268
+ }
2269
+ toJson() {
2270
+ return this.coords.toCompressedJson();
2271
+ }
2272
+ static fromJson(json) {
2273
+ return new GeoGraphVertex(Coordinates.fromCompressedJson(json));
2274
+ }
2275
+ inferVertexLevelFromEdges() {
2276
+ let tmpLevel = null;
2277
+ for (let i = 0; i < this.edges.length; i++) {
2278
+ const edge = this.edges[i];
2279
+ if (edge.level !== null) {
2280
+ if (tmpLevel === null) {
2281
+ tmpLevel = Level.clone(edge.level);
2282
+ } else {
2283
+ tmpLevel = Level.intersection(tmpLevel, edge.level);
2284
+ if (tmpLevel === null) {
2285
+ throw Error("Something bad happend during parsing: We cannot retrieve vertex level from adjacent ways: " + this.coords);
2286
+ }
2287
+ }
2288
+ }
2289
+ }
2290
+ this.coords.level = tmpLevel;
2291
+ }
2292
+ inferVertexLevelByNeighboors() {
2293
+ const { level } = this.coords;
2294
+ if (level === null || !Level.isRange(level)) {
1276
2295
  return true;
1277
2296
  }
1278
- if (!(other instanceof GraphEdge)) {
1279
- return false;
2297
+ let tmpLevel = null;
2298
+ for (let i = 0; i < this.edges.length; i++) {
2299
+ const edge = this.edges[i];
2300
+ const otherVertex = edge.vertex1 === this ? edge.vertex2 : edge.vertex1;
2301
+ tmpLevel = Level.union(otherVertex.coords.level, tmpLevel);
2302
+ }
2303
+ if (tmpLevel === null || !Level.isRange(tmpLevel)) {
2304
+ this.coords.level = tmpLevel === level[0] ? level[1] : level[0];
1280
2305
  }
1281
- return other.node1.equals(this.node1) && other.node2.equals(this.node2) && Level.equals(other.level, this.level) && other.isOneway === this.isOneway && other.builtFrom === this.builtFrom;
2306
+ return true;
1282
2307
  }
1283
- clone() {
1284
- const edge = new GraphEdge(this.node1, this.node2, this.level, this.builtFrom);
1285
- edge.isOneway = this.isOneway;
1286
- return edge;
2308
+ inferVertexLevelByRecursion() {
2309
+ const { level } = this.coords;
2310
+ if (level === null || !Level.isRange(level)) {
2311
+ return;
2312
+ }
2313
+ if (this.edges.length > 1) {
2314
+ return;
2315
+ }
2316
+ const lookForLevel = (vertex, visitedVertices) => {
2317
+ visitedVertices.push(vertex);
2318
+ if (vertex.coords.level === null) {
2319
+ return null;
2320
+ }
2321
+ if (!Level.isRange(vertex.coords.level)) {
2322
+ return vertex.coords.level;
2323
+ }
2324
+ let tmpLevel = null;
2325
+ for (let i = 0; i < vertex.edges.length; i++) {
2326
+ const edge = vertex.edges[i];
2327
+ const otherVertex = edge.vertex1 === vertex ? edge.vertex2 : edge.vertex1;
2328
+ if (!visitedVertices.includes(otherVertex)) {
2329
+ tmpLevel = Level.union(lookForLevel(otherVertex, visitedVertices), tmpLevel);
2330
+ }
2331
+ }
2332
+ return tmpLevel;
2333
+ };
2334
+ const othersLevels = lookForLevel(this, []);
2335
+ if (othersLevels !== null) {
2336
+ if (!Level.isRange(othersLevels)) {
2337
+ this.coords.level = othersLevels === level[0] ? level[1] : level[0];
2338
+ return;
2339
+ }
2340
+ throw Error("Level of: " + this.coords.toString() + " cannot be decided");
2341
+ }
1287
2342
  }
1288
2343
  }
1289
- function getEdgeByNodes(edges, node1, node2) {
1290
- return edges.find(
1291
- (edge) => node1 === edge.node1 && node2 === edge.node2 || node2 === edge.node1 && node1 === edge.node2
1292
- );
1293
- }
1294
- function getNodeByCoords(nodes, coords) {
1295
- return nodes.find((node) => node.coords.equals(coords));
1296
- }
1297
- const GraphUtils = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
1298
- __proto__: null,
1299
- getEdgeByNodes,
1300
- getNodeByCoords
1301
- }, Symbol.toStringTag, { value: "Module" }));
1302
- class Network {
1303
- constructor(nodes, edges) {
1304
- __publicField(this, "nodes");
1305
- __publicField(this, "edges");
1306
- this.nodes = Array.isArray(nodes) ? nodes : [];
1307
- this.edges = Array.isArray(edges) ? edges : [];
2344
+ class GeoGraph extends Graph {
2345
+ constructor(vertices, edges, generateVerticesLevels = false) {
2346
+ super(vertices, edges);
2347
+ generateVerticesLevels && this.generateVerticesLevels();
1308
2348
  }
1309
- getNodeByCoords(coords) {
1310
- return this.nodes.find((node) => node.coords.equals(coords));
2349
+ getVertexByCoords(coords) {
2350
+ return GeoGraph.getVertexByCoords(this.vertices, coords);
1311
2351
  }
1312
- getEdgeByNodes(node1, node2) {
1313
- return getEdgeByNodes(this.edges, node1, node2);
2352
+ static getVertexByCoords(vertices, coords) {
2353
+ return vertices.find((vertex) => vertex.coords.equals(coords));
2354
+ }
2355
+ getVertexByName(name) {
2356
+ return super.getVertexByName(name);
2357
+ }
2358
+ getEdgeByName(name) {
2359
+ return super.getEdgeByName(name);
1314
2360
  }
1315
2361
  getBoundingBox(extendedMeasure) {
1316
- if (!this.nodes.length) {
2362
+ if (!this.vertices.length) {
1317
2363
  return null;
1318
2364
  }
1319
- const boundingBox = BoundingBox.fromCoordinates(this.nodes.map((node) => node.coords));
2365
+ const boundingBox = BoundingBox.fromCoordinates(this.vertices.map((vertex) => vertex.coords));
1320
2366
  if (extendedMeasure) {
1321
2367
  boundingBox.extendsWithMeasure(extendedMeasure);
1322
2368
  }
1323
2369
  return boundingBox;
1324
2370
  }
1325
- toDetailedString(_nodeToStringFn, _edgeToStringFn) {
1326
- let nodeToStringFn = _nodeToStringFn;
1327
- if (!nodeToStringFn) {
1328
- nodeToStringFn = (node) => `${node.builtFrom}`;
1329
- }
1330
- let edgeToStringFn = _edgeToStringFn;
1331
- if (!_edgeToStringFn) {
1332
- edgeToStringFn = (edge) => `${edge.builtFrom}`;
1333
- }
1334
- let output = `--- Network ---
1335
- Nodes: ${this.nodes.length}
1336
- Edges: ${this.edges.length}
1337
- ---
1338
- Nodes
1339
- `;
1340
- this.nodes.forEach((node) => {
1341
- output += `${nodeToStringFn(node)} [edges: ${node.edges.length}]
1342
- `;
1343
- });
1344
- output += "---\nEdges\n";
1345
- this.edges.forEach((edge) => {
1346
- output += `${edgeToStringFn(edge)} `;
1347
- output += `[${nodeToStringFn(edge.node1)} -- ${nodeToStringFn(edge.node2)}]
1348
- `;
1349
- });
1350
- output += "---";
1351
- return output;
1352
- }
1353
2371
  toCompressedJson() {
1354
2372
  return {
1355
- nodes: this.nodes.map((node) => node.toJson()),
2373
+ vertices: this.vertices.map((vertex) => vertex.toJson()),
1356
2374
  edges: this.edges.map((edge) => {
1357
- const node1Idx = this.nodes.indexOf(edge.node1);
1358
- const node2Idx = this.nodes.indexOf(edge.node2);
2375
+ const vertex1Idx = this.vertices.indexOf(edge.vertex1);
2376
+ const vertex2Idx = this.vertices.indexOf(edge.vertex2);
1359
2377
  if (edge.isOneway) {
1360
- return [node1Idx, node2Idx, edge.level, true];
2378
+ return [vertex1Idx, vertex2Idx, edge.level, true];
1361
2379
  }
1362
- if (edge.level) {
1363
- return [node1Idx, node2Idx, edge.level];
2380
+ if (edge.level !== null) {
2381
+ return [vertex1Idx, vertex2Idx, edge.level];
1364
2382
  }
1365
- return [node1Idx, node2Idx];
2383
+ return [vertex1Idx, vertex2Idx];
1366
2384
  })
1367
2385
  };
1368
2386
  }
1369
2387
  static fromCompressedJson(json) {
1370
- const network = new Network();
1371
- network.nodes = json.nodes.map((node) => GraphNode.fromJson(node, null));
1372
- network.edges = json.edges.map((jsonEdge) => {
1373
- const edge = new GraphEdge(
1374
- network.nodes[jsonEdge[0]],
1375
- network.nodes[jsonEdge[1]],
1376
- jsonEdge[2],
1377
- null
2388
+ const geograph = new GeoGraph();
2389
+ geograph.vertices = json.vertices.map((vertex) => GeoGraphVertex.fromJson(vertex));
2390
+ geograph.edges = json.edges.map((jsonEdge) => {
2391
+ const edge = new GeoGraphEdge(
2392
+ geograph.vertices[jsonEdge[0]],
2393
+ geograph.vertices[jsonEdge[1]],
2394
+ { level: jsonEdge.length > 2 ? jsonEdge[2] : null }
1378
2395
  );
1379
2396
  if (jsonEdge.length > 3 && jsonEdge[3]) {
1380
2397
  edge.isOneway = true;
1381
2398
  }
1382
2399
  return edge;
1383
2400
  });
1384
- return network;
2401
+ return geograph;
1385
2402
  }
1386
2403
  static fromCoordinates(segments) {
1387
- const network = new Network();
1388
- const getOrCreateNode = (coords) => {
1389
- const node = network.nodes.find((otherNode) => otherNode.coords.equals(coords));
1390
- if (node) {
1391
- return node;
2404
+ const geograph = new GeoGraph();
2405
+ const getOrCreateVertex = (coords) => {
2406
+ const vertex = geograph.vertices.find((otherVertex) => otherVertex.coords.equals(coords));
2407
+ if (vertex) {
2408
+ return vertex;
1392
2409
  }
1393
- const newNode = new GraphNode(coords, null);
1394
- network.nodes.push(newNode);
1395
- return newNode;
2410
+ const newVertex = new GeoGraphVertex(coords);
2411
+ geograph.vertices.push(newVertex);
2412
+ return newVertex;
1396
2413
  };
1397
- const createEdgeFromNodes = (node1, node2) => new GraphEdge(
1398
- node1,
1399
- node2,
1400
- Level.union(node1.coords.level, node2.coords.level),
1401
- null
2414
+ const createEdgeFromVertices = (vertex1, vertex2) => new GeoGraphEdge(
2415
+ vertex1,
2416
+ vertex2,
2417
+ { level: Level.union(vertex1.coords.level, vertex2.coords.level) }
1402
2418
  );
1403
2419
  for (const segment of segments) {
1404
- let previousNode = null;
2420
+ let previousVertex = null;
1405
2421
  for (const coords of segment) {
1406
- const currentNode = getOrCreateNode(coords);
1407
- if (previousNode) {
1408
- const edge = createEdgeFromNodes(currentNode, previousNode);
1409
- network.edges.push(edge);
2422
+ const currentVertex = getOrCreateVertex(coords);
2423
+ if (previousVertex) {
2424
+ const edge = createEdgeFromVertices(currentVertex, previousVertex);
2425
+ geograph.edges.push(edge);
1410
2426
  }
1411
- previousNode = currentNode;
2427
+ previousVertex = currentVertex;
1412
2428
  }
1413
2429
  }
1414
- return network;
2430
+ return geograph;
1415
2431
  }
1416
2432
  getEdgesAtLevel(targetLevel, useMultiLevelEdges = true) {
1417
2433
  return this.edges.filter(
1418
2434
  ({ level }) => useMultiLevelEdges ? Level.intersect(targetLevel, level) : Level.contains(targetLevel, level)
1419
2435
  );
1420
2436
  }
2437
+ generateVerticesLevels() {
2438
+ const { vertices } = this;
2439
+ vertices.forEach((vertex) => vertex.inferVertexLevelFromEdges());
2440
+ vertices.forEach((vertex) => vertex.inferVertexLevelByNeighboors());
2441
+ vertices.forEach((vertex) => vertex.inferVertexLevelByRecursion());
2442
+ vertices.forEach((vertex) => {
2443
+ vertex.io = vertex.coords.level !== null && vertex.edges.some((edge) => edge.level === null);
2444
+ });
2445
+ }
1421
2446
  }
1422
- class GraphProjection {
2447
+ class GeoGraphProjection {
1423
2448
  constructor(origin, distanceFromNearestElement, coords, nearestElement) {
1424
2449
  __publicField(this, "origin");
1425
2450
  __publicField(this, "distanceFromNearestElement");
@@ -1431,12 +2456,12 @@ class GraphProjection {
1431
2456
  this.nearestElement = nearestElement;
1432
2457
  }
1433
2458
  }
1434
- const _MapMatching = class {
1435
- constructor(network = null) {
1436
- __publicField(this, "network", null);
2459
+ const _GeoGraphProjectionHandler = class {
2460
+ constructor(graph = null) {
2461
+ __publicField(this, "graph", null);
1437
2462
  __publicField(this, "_maxDistance", Number.MAX_VALUE);
1438
2463
  __publicField(this, "_maxAngleBearing", Math.PI);
1439
- this.network = network;
2464
+ this.graph = graph;
1440
2465
  }
1441
2466
  set maxAngleBearing(maxAngleBearing) {
1442
2467
  this._maxAngleBearing = maxAngleBearing;
@@ -1455,14 +2480,14 @@ const _MapMatching = class {
1455
2480
  return [false, false, false];
1456
2481
  }
1457
2482
  let checkEdge = Level.intersect(location.level, edge.level);
1458
- let checkNode1 = Level.intersect(location.level, edge.node1.coords.level);
1459
- let checkNode2 = Level.intersect(location.level, edge.node2.coords.level);
1460
- checkNode1 = checkNode1 || edge.node1.io && location.level === null;
1461
- checkNode2 = checkNode2 || edge.node2.io && location.level === null;
2483
+ let checkNode1 = Level.intersect(location.level, edge.vertex1.coords.level);
2484
+ let checkNode2 = Level.intersect(location.level, edge.vertex2.coords.level);
2485
+ checkNode1 = checkNode1 || edge.vertex1.io && location.level === null;
2486
+ checkNode2 = checkNode2 || edge.vertex2.io && location.level === null;
1462
2487
  if (!useMultiLevelSegments) {
1463
2488
  checkEdge = checkEdge && !Level.isRange(edge.level);
1464
- checkNode1 = checkNode1 && !Level.isRange(edge.node1.coords.level);
1465
- checkNode2 = checkNode2 && !Level.isRange(edge.node2.coords.level);
2489
+ checkNode1 = checkNode1 && !Level.isRange(edge.vertex1.coords.level);
2490
+ checkNode2 = checkNode2 && !Level.isRange(edge.vertex2.coords.level);
1466
2491
  }
1467
2492
  if (useBearing) {
1468
2493
  if (checkEdge) {
@@ -1487,11 +2512,8 @@ const _MapMatching = class {
1487
2512
  }
1488
2513
  }
1489
2514
  getProjection(location, useDistance = false, useBearing = false, useMultiLevelSegments = true, acceptEdgeFn = () => true) {
1490
- if (this.network === null) {
1491
- throw new Error("Network has not been set yet");
1492
- }
1493
- if (!(location instanceof Coordinates)) {
1494
- throw new TypeError("location is not an instance of Coordinates");
2515
+ if (this.graph === null) {
2516
+ throw new Error("Graph has not been set yet");
1495
2517
  }
1496
2518
  if (useBearing && (!("bearing" in location && location.bearing !== null) || !this._maxAngleBearing)) {
1497
2519
  return null;
@@ -1502,7 +2524,7 @@ const _MapMatching = class {
1502
2524
  const isProjectionBetter = (distanceOfNewProjection) => {
1503
2525
  return distanceOfNewProjection < distanceFromNearestElement && (!useDistance || distanceOfNewProjection <= this._maxDistance);
1504
2526
  };
1505
- for (const edge of this.network.edges) {
2527
+ for (const edge of this.graph.edges) {
1506
2528
  const [checkEdge, checkNode1, checkNode2] = this._shouldProjectOnEdgeAndNodes(
1507
2529
  edge,
1508
2530
  location,
@@ -1511,38 +2533,38 @@ const _MapMatching = class {
1511
2533
  acceptEdgeFn
1512
2534
  );
1513
2535
  if (checkNode1) {
1514
- const distNode1 = location.distanceTo(edge.node1.coords);
2536
+ const distNode1 = location.distanceTo(edge.vertex1.coords);
1515
2537
  if (isProjectionBetter(distNode1) || distNode1 <= EPS_MM) {
1516
2538
  distanceFromNearestElement = distNode1;
1517
- nearestElement = edge.node1;
1518
- _MapMatching._assignLatLngLevel(edge.node1.coords, projection);
1519
- _MapMatching._handleLevelsWithIONodes(projection, location, edge.node1);
2539
+ nearestElement = edge.vertex1;
2540
+ _GeoGraphProjectionHandler._assignLatLngLevel(edge.vertex1.coords, projection);
2541
+ _GeoGraphProjectionHandler._handleLevelsWithIONodes(projection, location, edge.vertex1);
1520
2542
  if (distNode1 <= EPS_MM) {
1521
2543
  break;
1522
2544
  }
1523
2545
  }
1524
2546
  }
1525
2547
  if (checkNode2) {
1526
- const distNode2 = location.distanceTo(edge.node2.coords);
2548
+ const distNode2 = location.distanceTo(edge.vertex2.coords);
1527
2549
  if (isProjectionBetter(distNode2) || distNode2 <= EPS_MM) {
1528
2550
  distanceFromNearestElement = distNode2;
1529
- nearestElement = edge.node2;
1530
- _MapMatching._assignLatLngLevel(edge.node2.coords, projection);
1531
- _MapMatching._handleLevelsWithIONodes(projection, location, edge.node2);
2551
+ nearestElement = edge.vertex2;
2552
+ _GeoGraphProjectionHandler._assignLatLngLevel(edge.vertex2.coords, projection);
2553
+ _GeoGraphProjectionHandler._handleLevelsWithIONodes(projection, location, edge.vertex2);
1532
2554
  if (distNode2 <= EPS_MM) {
1533
2555
  break;
1534
2556
  }
1535
2557
  }
1536
2558
  }
1537
2559
  if (checkEdge) {
1538
- const segmentProjection = location.getSegmentProjection(edge.node1.coords, edge.node2.coords);
2560
+ const segmentProjection = location.getSegmentProjection(edge.vertex1.coords, edge.vertex2.coords);
1539
2561
  if (segmentProjection) {
1540
2562
  const distEdge = location.distanceTo(segmentProjection);
1541
2563
  if (isProjectionBetter(distEdge)) {
1542
2564
  distanceFromNearestElement = distEdge;
1543
2565
  nearestElement = edge;
1544
- _MapMatching._assignLatLngLevel(segmentProjection, projection);
1545
- _MapMatching._updateProjectionLevelFromEdge(edge, projection);
2566
+ _GeoGraphProjectionHandler._assignLatLngLevel(segmentProjection, projection);
2567
+ _GeoGraphProjectionHandler._updateProjectionLevelFromEdge(edge, projection);
1546
2568
  }
1547
2569
  }
1548
2570
  }
@@ -1553,7 +2575,7 @@ const _MapMatching = class {
1553
2575
  if (projection instanceof UserPosition && projection.accuracy !== null) {
1554
2576
  projection.accuracy += distanceFromNearestElement;
1555
2577
  }
1556
- return new GraphProjection(
2578
+ return new GeoGraphProjection(
1557
2579
  location,
1558
2580
  distanceFromNearestElement,
1559
2581
  projection,
@@ -1561,74 +2583,59 @@ const _MapMatching = class {
1561
2583
  );
1562
2584
  }
1563
2585
  };
1564
- let MapMatching = _MapMatching;
1565
- __publicField(MapMatching, "_updateProjectionLevelFromEdge", (_edge, _projection) => {
2586
+ let GeoGraphProjectionHandler = _GeoGraphProjectionHandler;
2587
+ __publicField(GeoGraphProjectionHandler, "_updateProjectionLevelFromEdge", (_edge, _projection) => {
1566
2588
  _projection.level = Level.clone(_edge.level);
1567
2589
  });
1568
- class GraphItinerary {
1569
- constructor(start, end, nodes, edges, edgesWeights) {
1570
- __publicField(this, "start");
1571
- __publicField(this, "end");
1572
- __publicField(this, "nodes");
1573
- __publicField(this, "edges");
1574
- __publicField(this, "edgesWeights");
2590
+ class GeoGraphItinerary extends GeoGraph {
2591
+ constructor(start, end, vertices, edges, edgesWeights) {
2592
+ super(vertices, edges);
1575
2593
  this.start = start;
1576
2594
  this.end = end;
1577
- this.nodes = nodes;
1578
- this.edges = edges;
1579
2595
  this.edgesWeights = edgesWeights;
1580
2596
  }
1581
- static fromNetworkNodes(start, end, networkNodes, edgesWeights) {
1582
- const nodes = networkNodes.map((node) => {
1583
- const newNode = node.clone();
1584
- newNode.edges = [];
1585
- if (newNode.io) {
1586
- newNode.coords = newNode.coords.clone();
1587
- newNode.coords.level = null;
1588
- }
1589
- return newNode;
2597
+ static fromGraphVertices(start, end, networkVertices, edgesWeights) {
2598
+ const vertices = networkVertices.map((vertex) => {
2599
+ return new GeoGraphVertex(
2600
+ vertex.coords.clone(),
2601
+ { name: vertex.name, id: vertex.id, data: vertex.data, io: vertex.io }
2602
+ );
1590
2603
  });
1591
2604
  const edges = [];
1592
- networkNodes.forEach((node, idx, arr) => {
2605
+ networkVertices.forEach((vertex, idx, arr) => {
1593
2606
  if (idx === 0) {
1594
2607
  return;
1595
2608
  }
1596
- const prevNode = arr[idx - 1];
1597
- const edge = getEdgeByNodes(prevNode.edges, prevNode, node);
2609
+ const prevVertex = arr[idx - 1];
2610
+ const edge = GeoGraphEdge.getEdgeByVertices(prevVertex.edges, prevVertex, vertex);
1598
2611
  if (!edge) {
1599
2612
  Logger__default.default.error("Cannot retrieve edge to create itinerary");
1600
2613
  return;
1601
2614
  }
1602
- const newEdge = new GraphEdge(
1603
- nodes[idx - 1],
1604
- nodes[idx],
1605
- edge.level,
1606
- edge.builtFrom
1607
- );
1608
- newEdge.isOneway = edge.isOneway;
1609
- edges.push(newEdge);
2615
+ edges.push(new GeoGraphEdge(
2616
+ vertices[idx - 1],
2617
+ vertices[idx],
2618
+ { name: edge.name, id: edge.id, data: edge.data, level: edge.level, isOneway: edge.isOneway }
2619
+ ));
1610
2620
  });
1611
- return new GraphItinerary(start, end, nodes, edges, edgesWeights);
2621
+ return new GeoGraphItinerary(start, end, vertices, edges, edgesWeights);
1612
2622
  }
1613
2623
  }
1614
2624
  class NoRouteFoundError extends Error {
1615
- constructor(start, end, details) {
2625
+ constructor(start, end, details = null) {
1616
2626
  super();
1617
- __publicField(this, "details");
1618
- __publicField(this, "end");
1619
- __publicField(this, "start");
1620
2627
  this.start = start;
1621
2628
  this.end = end;
1622
2629
  this.details = details;
1623
2630
  }
1624
2631
  get startStr() {
1625
- if (this.start instanceof GraphNode) {
2632
+ if (this.start instanceof GeoGraphVertex) {
1626
2633
  return `GraphNode ${this.start.coords.toString()}`;
1627
2634
  }
1628
2635
  return this.start.toString();
1629
2636
  }
1630
2637
  get endStr() {
1631
- if (this.end instanceof GraphNode) {
2638
+ if (this.end instanceof GeoGraphVertex) {
1632
2639
  return `GraphNode ${this.end.coords.toString()}`;
1633
2640
  }
1634
2641
  return this.end.toString();
@@ -1641,159 +2648,142 @@ class NoRouteFoundError extends Error {
1641
2648
  return message;
1642
2649
  }
1643
2650
  }
1644
- class GraphRouterOptions {
1645
- constructor() {
1646
- __publicField(this, "projectionMaxDistance", 50);
1647
- __publicField(this, "weightEdgeFn", (edge) => edge.length);
1648
- __publicField(this, "acceptEdgeFn", () => true);
1649
- }
1650
- }
1651
- class GraphRouter {
1652
- constructor(network) {
2651
+ const DEFAULT_OPTIONS = {
2652
+ projectionMaxDistance: 50,
2653
+ weightEdgeFn: (edge) => edge.length,
2654
+ acceptEdgeFn: () => true
2655
+ };
2656
+ class GeoGraphRouter {
2657
+ constructor(graph) {
1653
2658
  __publicField(this, "_mapMatching");
1654
- __publicField(this, "_network");
2659
+ __publicField(this, "_graph");
1655
2660
  __publicField(this, "disabledEdges", /* @__PURE__ */ new Set());
1656
- this._network = network;
1657
- this._mapMatching = new MapMatching(network);
2661
+ this._graph = graph;
2662
+ this._mapMatching = new GeoGraphProjectionHandler(graph);
1658
2663
  }
1659
- getShortestPath(start, end, options = new GraphRouterOptions()) {
1660
- if (!(start instanceof GraphNode) && !(start instanceof Coordinates)) {
1661
- throw new Error("Unknown start type");
1662
- }
1663
- if (!(end instanceof GraphNode) && !(end instanceof Coordinates)) {
1664
- throw new Error("Unknown end type");
1665
- }
2664
+ getShortestPath(start, end, options = DEFAULT_OPTIONS) {
1666
2665
  const { acceptEdgeFn, weightEdgeFn, projectionMaxDistance } = options;
1667
2666
  this._mapMatching.maxDistance = projectionMaxDistance;
1668
- const createdNodes = [];
1669
- const retrieveOrCreateNearestNode = (point) => {
1670
- if (point instanceof GraphNode) {
2667
+ const createdVertices = [];
2668
+ const retrieveOrCreateNearestVertex = (point) => {
2669
+ if (point instanceof GeoGraphVertex) {
1671
2670
  return point;
1672
2671
  }
1673
- const closeNode = this._network.getNodeByCoords(point);
1674
- if (closeNode) {
1675
- return closeNode;
2672
+ const closeVertex = this._graph.getVertexByCoords(point);
2673
+ if (closeVertex) {
2674
+ return closeVertex;
1676
2675
  }
1677
2676
  const proj = this._mapMatching.getProjection(point, true, false, false, acceptEdgeFn);
1678
2677
  if (!proj) {
1679
- let message = `Point ${point.toString()} is too far from the network > ${this._mapMatching.maxDistance.toFixed(0)} meters.`;
2678
+ let message = `Point ${point.toString()} is too far from the graph > ${this._mapMatching.maxDistance.toFixed(0)} meters.`;
1680
2679
  if (point.level !== null) {
1681
- message += ` If it is a multi-level map, please verify if you have a network at level ${Level.toString(point.level)}.`;
2680
+ message += ` If it is a multi-level map, please verify if you have a graph at level ${Level.toString(point.level)}.`;
1682
2681
  }
1683
2682
  throw new NoRouteFoundError(start, end, message);
1684
2683
  }
1685
- if (proj.nearestElement instanceof GraphNode) {
2684
+ if (proj.nearestElement instanceof GeoGraphVertex) {
1686
2685
  return proj.nearestElement;
1687
2686
  }
1688
- const nodeCreated = this.createNodeInsideEdge(
2687
+ const vertexCreated = this.createVertexInsideEdge(
1689
2688
  proj.nearestElement,
1690
2689
  proj.coords
1691
2690
  );
1692
- createdNodes.push(nodeCreated);
1693
- return nodeCreated;
2691
+ createdVertices.push(vertexCreated);
2692
+ return vertexCreated;
1694
2693
  };
1695
- const removeCreatedNodes = () => {
1696
- while (createdNodes.length) {
1697
- this.removeNodeFromPreviouslyCreatedEdge(createdNodes.pop());
2694
+ const removeCreatedVertices = () => {
2695
+ while (createdVertices.length) {
2696
+ this.removeVertexFromPreviouslyCreatedEdge(createdVertices.pop());
1698
2697
  }
1699
2698
  };
1700
- const startNode = retrieveOrCreateNearestNode(start);
1701
- const endNode = retrieveOrCreateNearestNode(end);
1702
- const startCoords = start instanceof GraphNode ? start.coords : start;
1703
- const endCoords = end instanceof GraphNode ? end.coords : end;
2699
+ const startVertex = retrieveOrCreateNearestVertex(start);
2700
+ const endVertex = retrieveOrCreateNearestVertex(end);
2701
+ const startCoords = start instanceof GeoGraphVertex ? start.coords : start;
2702
+ const endCoords = end instanceof GeoGraphVertex ? end.coords : end;
1704
2703
  let graphItinerary;
1705
- if (startNode === endNode) {
1706
- graphItinerary = GraphItinerary.fromNetworkNodes(
2704
+ if (startVertex === endVertex) {
2705
+ graphItinerary = GeoGraphItinerary.fromGraphVertices(
1707
2706
  startCoords,
1708
2707
  endCoords,
1709
- [startNode],
2708
+ [startVertex],
1710
2709
  []
1711
2710
  );
1712
2711
  } else {
1713
- graphItinerary = this.getShortestPathBetweenGraphNodes(
1714
- startNode,
1715
- endNode,
1716
- acceptEdgeFn,
1717
- weightEdgeFn
2712
+ graphItinerary = this.getShortestPathBetweenGeoGraphVertices(
2713
+ startVertex,
2714
+ endVertex,
2715
+ weightEdgeFn,
2716
+ acceptEdgeFn
1718
2717
  );
1719
2718
  }
1720
2719
  graphItinerary.start = startCoords;
1721
2720
  graphItinerary.end = endCoords;
1722
- removeCreatedNodes();
1723
- if (!graphItinerary.nodes.length) {
2721
+ removeCreatedVertices();
2722
+ if (!graphItinerary.vertices.length) {
1724
2723
  throw new NoRouteFoundError(start, end);
1725
2724
  }
1726
2725
  return graphItinerary;
1727
2726
  }
1728
- createNodeInsideEdge(edge, point) {
1729
- const a = edge.node1;
1730
- const b = edge.node2;
1731
- const m = new GraphNode(point, null);
1732
- m.coords.level = edge.level;
1733
- const u = edge.clone();
1734
- u.node1 = a;
1735
- u.node2 = m;
1736
- const v = edge.clone();
1737
- v.node1 = m;
1738
- v.node2 = b;
2727
+ createVertexInsideEdge(edge, point) {
2728
+ const a = edge.vertex1;
2729
+ const b = edge.vertex2;
2730
+ const m = new GeoGraphVertex(point, { name: `proj on ${edge.name || null} (tmp)` });
2731
+ const newEdgesParams = { name: `splitted ${edge.name || null} (tmp)`, data: edge.data, isOneway: edge.isOneway, level: edge.level };
2732
+ const u = new GeoGraphEdge(a, m, newEdgesParams);
2733
+ const v = new GeoGraphEdge(m, b, newEdgesParams);
1739
2734
  a.edges = a.edges.filter((_edge) => _edge !== edge);
1740
2735
  b.edges = b.edges.filter((_edge) => _edge !== edge);
1741
- this._network.nodes.push(m);
1742
- this._network.edges.push(u, v);
1743
- this._network.edges = this._network.edges.filter(
2736
+ this._graph.vertices.push(m);
2737
+ this._graph.edges.push(u, v);
2738
+ this._graph.edges = this._graph.edges.filter(
1744
2739
  (_edge) => _edge !== edge
1745
2740
  );
1746
2741
  return m;
1747
2742
  }
1748
- removeNodeFromPreviouslyCreatedEdge(_node) {
1749
- const u = _node.edges[0];
1750
- const v = _node.edges[1];
1751
- u.node1.edges = u.node1.edges.filter((edge) => edge !== u);
1752
- v.node1.edges = v.node1.edges.filter((edge) => edge !== v);
1753
- const oldEdge = u.clone();
1754
- oldEdge.node1 = u.node1;
1755
- oldEdge.node2 = v.node2;
1756
- this._network.edges.push(oldEdge);
1757
- this._network.nodes = this._network.nodes.filter((node) => node !== _node);
1758
- this._network.edges = this._network.edges.filter(
2743
+ removeVertexFromPreviouslyCreatedEdge(_vertex) {
2744
+ const u = _vertex.edges[0];
2745
+ const v = _vertex.edges[1];
2746
+ u.vertex1.edges = u.vertex1.edges.filter((edge) => edge !== u);
2747
+ v.vertex1.edges = v.vertex1.edges.filter((edge) => edge !== v);
2748
+ const oldEdgeName = u.name.substring("splitted ".length, u.name.length - " (tmp)".length);
2749
+ const oldEdgeParams = { name: oldEdgeName, data: u.data, isOneway: u.isOneway, level: u.level };
2750
+ const oldEdge = new GeoGraphEdge(u.vertex1, v.vertex2, oldEdgeParams);
2751
+ this._graph.edges.push(oldEdge);
2752
+ this._graph.vertices = this._graph.vertices.filter((vertex) => vertex !== _vertex);
2753
+ this._graph.edges = this._graph.edges.filter(
1759
2754
  (edge) => edge !== u && edge !== v
1760
2755
  );
1761
2756
  }
1762
- getShortestPathBetweenGraphNodes(start, end, acceptEdgeFn, weightFn) {
1763
- const distanceMap = {}, checking = {}, vertexList = {}, vertexNodes = {}, parentVertices = {}, path = [];
1764
- let vertexId = 1;
1765
- this._network.nodes.forEach((vertex) => {
1766
- vertex.uniqueRouterId = vertexId;
1767
- vertexNodes[vertexId] = vertex;
1768
- distanceMap[vertexId] = Infinity;
1769
- checking[vertexId] = null;
1770
- vertexList[vertexId] = true;
1771
- vertexId++;
2757
+ getShortestPathBetweenGeoGraphVertices(start, end, weightFn, acceptEdgeFn) {
2758
+ const distanceMap = {}, checking = {}, vertexList = {}, vertices = {}, parentVertices = {}, path = [];
2759
+ this._graph.vertices.forEach((vertex) => {
2760
+ vertices[vertex.id] = vertex;
2761
+ distanceMap[vertex.id] = Infinity;
2762
+ checking[vertex.id] = null;
2763
+ vertexList[vertex.id] = true;
1772
2764
  });
1773
- const startVertex = Object.values(vertexNodes).find((vertex) => start.equals(vertex));
1774
- const endVertex = Object.values(vertexNodes).find((vertex) => end.equals(vertex));
1775
- distanceMap[startVertex.uniqueRouterId] = 0;
2765
+ distanceMap[start.id] = 0;
1776
2766
  while (Object.keys(vertexList).length > 0) {
1777
2767
  const keys = Object.keys(vertexList).map(Number);
1778
2768
  const current = Number(
1779
- keys.reduce((_checking, vertexId2) => {
1780
- return distanceMap[_checking] > distanceMap[vertexId2] ? vertexId2 : _checking;
2769
+ keys.reduce((_checking, vertexId) => {
2770
+ return distanceMap[_checking] > distanceMap[vertexId] ? vertexId : _checking;
1781
2771
  }, keys[0])
1782
2772
  );
1783
- this._network.edges.filter((edge) => {
1784
- if (!acceptEdgeFn(edge) || this.disabledEdges.has(edge)) {
2773
+ this._graph.edges.filter((edge) => {
2774
+ if (acceptEdgeFn && !acceptEdgeFn(edge) || this.disabledEdges.has(edge)) {
1785
2775
  return false;
1786
2776
  }
1787
- const from = edge.node1.uniqueRouterId, to = edge.node2.uniqueRouterId;
2777
+ const from = edge.vertex1.id, to = edge.vertex2.id;
1788
2778
  return from === current || to === current;
1789
2779
  }).forEach((edge) => {
1790
2780
  let to, from, reversed = false;
1791
- if (edge.node1.uniqueRouterId === current) {
1792
- to = edge.node2.uniqueRouterId;
1793
- from = edge.node1.uniqueRouterId;
2781
+ if (edge.vertex1.id === current) {
2782
+ to = edge.vertex2.id;
2783
+ from = edge.vertex1.id;
1794
2784
  } else {
1795
- to = edge.node1.uniqueRouterId;
1796
- from = edge.node2.uniqueRouterId;
2785
+ to = edge.vertex1.id;
2786
+ from = edge.vertex2.id;
1797
2787
  reversed = true;
1798
2788
  }
1799
2789
  if (edge.isOneway && reversed) {
@@ -1809,38 +2799,34 @@ class GraphRouter {
1809
2799
  delete vertexList[current];
1810
2800
  }
1811
2801
  const edgesWeights = [];
1812
- let endId = endVertex.uniqueRouterId;
1813
- while (parentVertices[endId]) {
1814
- path.unshift(vertexNodes[endId]);
2802
+ let endId = end.id;
2803
+ while (typeof parentVertices[endId] !== "undefined") {
2804
+ path.unshift(vertices[endId]);
1815
2805
  edgesWeights.unshift(distanceMap[endId] - distanceMap[parentVertices[endId]]);
1816
2806
  endId = parentVertices[endId];
1817
2807
  }
1818
2808
  if (path.length !== 0) {
1819
2809
  path.unshift(start);
1820
2810
  }
1821
- this._network.nodes.forEach((vertex) => {
1822
- delete vertex.uniqueRouterId;
1823
- });
1824
- return GraphItinerary.fromNetworkNodes(start.coords, end.coords, path, edgesWeights);
2811
+ return GeoGraphItinerary.fromGraphVertices(start.coords, end.coords, path, edgesWeights);
1825
2812
  }
1826
2813
  }
2814
+ __publicField(GeoGraphRouter, "DEFAULT_OPTIONS", DEFAULT_OPTIONS);
1827
2815
  exports.AbsoluteHeading = AbsoluteHeading;
1828
2816
  exports.Attitude = Attitude;
1829
2817
  exports.BoundingBox = BoundingBox;
1830
2818
  exports.Constants = Constants;
1831
2819
  exports.Coordinates = Coordinates;
2820
+ exports.GeoGraph = GeoGraph;
2821
+ exports.GeoGraphEdge = GeoGraphEdge;
2822
+ exports.GeoGraphItinerary = GeoGraphItinerary;
2823
+ exports.GeoGraphProjection = GeoGraphProjection;
2824
+ exports.GeoGraphProjectionHandler = GeoGraphProjectionHandler;
2825
+ exports.GeoGraphRouter = GeoGraphRouter;
2826
+ exports.GeoGraphVertex = GeoGraphVertex;
1832
2827
  exports.GeoRef = GeoRef;
1833
2828
  exports.GeoRelativePosition = GeoRelativePosition;
1834
- exports.GraphEdge = GraphEdge;
1835
- exports.GraphItinerary = GraphItinerary;
1836
- exports.GraphNode = GraphNode;
1837
- exports.GraphProjection = GraphProjection;
1838
- exports.GraphRouter = GraphRouter;
1839
- exports.GraphRouterOptions = GraphRouterOptions;
1840
- exports.GraphUtils = GraphUtils;
1841
2829
  exports.Level = Level;
1842
- exports.MapMatching = MapMatching;
1843
- exports.Network = Network;
1844
2830
  exports.NoRouteFoundError = NoRouteFoundError;
1845
2831
  exports.RelativePosition = RelativePosition;
1846
2832
  exports.UserPosition = UserPosition;