WIP graphhopper georouter
This commit is contained in:
parent
10a9b94588
commit
c759e81c23
|
@ -32,6 +32,8 @@
|
|||
"class-transformer": "^0.5.1",
|
||||
"class-validator": "^0.14.0",
|
||||
"geo-tz": "^7.0.7",
|
||||
"geographiclib-geodesic": "^2.0.0",
|
||||
"got": "^11.8.6",
|
||||
"ioredis": "^5.3.1",
|
||||
"reflect-metadata": "^0.1.13",
|
||||
"rxjs": "^7.2.0"
|
||||
|
@ -2129,6 +2131,17 @@
|
|||
"integrity": "sha512-XJfwUVUKDHF5ugKwIcxEgc9k8b7HbznCp6eUfWgu710hMPNIO4aw4/zB5RogDQz8nd6gyCDpU9O/m6qYEWY6yQ==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@sindresorhus/is": {
|
||||
"version": "4.6.0",
|
||||
"resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.6.0.tgz",
|
||||
"integrity": "sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw==",
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sindresorhus/is?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/@sinonjs/commons": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-2.0.0.tgz",
|
||||
|
@ -2147,6 +2160,17 @@
|
|||
"@sinonjs/commons": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@szmarczak/http-timer": {
|
||||
"version": "4.0.6",
|
||||
"resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-4.0.6.tgz",
|
||||
"integrity": "sha512-4BAffykYOgO+5nzBWYwE3W90sBgLJoUPRWWcL8wlyiM8IB8ipJz3UMJ9KXQd1RKQXpKp8Tutn80HZtWsu2u76w==",
|
||||
"dependencies": {
|
||||
"defer-to-connect": "^2.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/@tsconfig/node10": {
|
||||
"version": "1.0.9",
|
||||
"resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.9.tgz",
|
||||
|
@ -2253,6 +2277,17 @@
|
|||
"@types/node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/cacheable-request": {
|
||||
"version": "6.0.3",
|
||||
"resolved": "https://registry.npmjs.org/@types/cacheable-request/-/cacheable-request-6.0.3.tgz",
|
||||
"integrity": "sha512-IQ3EbTzGxIigb1I3qPZc1rWJnH0BmSKv5QYTalEwweFvyBDLSAe24zP0le/hyi7ecGfZVlIVAg4BZqb8WBwKqw==",
|
||||
"dependencies": {
|
||||
"@types/http-cache-semantics": "*",
|
||||
"@types/keyv": "^3.1.4",
|
||||
"@types/node": "*",
|
||||
"@types/responselike": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/connect": {
|
||||
"version": "3.4.35",
|
||||
"resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.35.tgz",
|
||||
|
@ -2326,6 +2361,11 @@
|
|||
"@types/node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/http-cache-semantics": {
|
||||
"version": "4.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@types/http-cache-semantics/-/http-cache-semantics-4.0.1.tgz",
|
||||
"integrity": "sha512-SZs7ekbP8CN0txVG2xVRH6EgKmEm31BOxA07vkFaETzZz1xh+cbt8BcI0slpymvwhx5dlFnQG2rTlPVQn+iRPQ=="
|
||||
},
|
||||
"node_modules/@types/istanbul-lib-coverage": {
|
||||
"version": "2.0.4",
|
||||
"resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.4.tgz",
|
||||
|
@ -2366,6 +2406,14 @@
|
|||
"integrity": "sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@types/keyv": {
|
||||
"version": "3.1.4",
|
||||
"resolved": "https://registry.npmjs.org/@types/keyv/-/keyv-3.1.4.tgz",
|
||||
"integrity": "sha512-BQ5aZNSCpj7D6K2ksrRCTmKRLEpnPvWDiLPfoGyhZ++8YtiK9d/3DBKPJgry359X/P1PfruyYwvnvwFjuEiEIg==",
|
||||
"dependencies": {
|
||||
"@types/node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/long": {
|
||||
"version": "4.0.2",
|
||||
"resolved": "https://registry.npmjs.org/@types/long/-/long-4.0.2.tgz",
|
||||
|
@ -2406,6 +2454,14 @@
|
|||
"integrity": "sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@types/responselike": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@types/responselike/-/responselike-1.0.0.tgz",
|
||||
"integrity": "sha512-85Y2BjiufFzaMIlvJDvTTB8Fxl2xfLo4HgmHzVBz08w4wDePCTjYw66PdrolO0kzli3yam/YCgRufyo1DdQVTA==",
|
||||
"dependencies": {
|
||||
"@types/node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/semver": {
|
||||
"version": "7.3.13",
|
||||
"resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.3.13.tgz",
|
||||
|
@ -3493,6 +3549,45 @@
|
|||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/cacheable-lookup": {
|
||||
"version": "5.0.4",
|
||||
"resolved": "https://registry.npmjs.org/cacheable-lookup/-/cacheable-lookup-5.0.4.tgz",
|
||||
"integrity": "sha512-2/kNscPhpcxrOigMZzbiWF7dz8ilhb/nIHU3EyZiXWXpeq/au8qJ8VhdftMkty3n7Gj6HIGalQG8oiBNB3AJgA==",
|
||||
"engines": {
|
||||
"node": ">=10.6.0"
|
||||
}
|
||||
},
|
||||
"node_modules/cacheable-request": {
|
||||
"version": "7.0.2",
|
||||
"resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-7.0.2.tgz",
|
||||
"integrity": "sha512-pouW8/FmiPQbuGpkXQ9BAPv/Mo5xDGANgSNXzTzJ8DrKGuXOssM4wIQRjfanNRh3Yu5cfYPvcorqbhg2KIJtew==",
|
||||
"dependencies": {
|
||||
"clone-response": "^1.0.2",
|
||||
"get-stream": "^5.1.0",
|
||||
"http-cache-semantics": "^4.0.0",
|
||||
"keyv": "^4.0.0",
|
||||
"lowercase-keys": "^2.0.0",
|
||||
"normalize-url": "^6.0.1",
|
||||
"responselike": "^2.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/cacheable-request/node_modules/get-stream": {
|
||||
"version": "5.2.0",
|
||||
"resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz",
|
||||
"integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==",
|
||||
"dependencies": {
|
||||
"pump": "^3.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/call-bind": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz",
|
||||
|
@ -3735,6 +3830,17 @@
|
|||
"node": ">=0.8"
|
||||
}
|
||||
},
|
||||
"node_modules/clone-response": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.3.tgz",
|
||||
"integrity": "sha512-ROoL94jJH2dUVML2Y/5PEDNaSHgeOdSDicUyS7izcF63G6sTc/FTjLub4b8Il9S8S0beOfYt0TaA5qvFK+w0wA==",
|
||||
"dependencies": {
|
||||
"mimic-response": "^1.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/cluster-key-slot": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/cluster-key-slot/-/cluster-key-slot-1.1.2.tgz",
|
||||
|
@ -3939,6 +4045,31 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"node_modules/decompress-response": {
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz",
|
||||
"integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==",
|
||||
"dependencies": {
|
||||
"mimic-response": "^3.1.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/decompress-response/node_modules/mimic-response": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz",
|
||||
"integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==",
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/dedent": {
|
||||
"version": "0.7.0",
|
||||
"resolved": "https://registry.npmjs.org/dedent/-/dedent-0.7.0.tgz",
|
||||
|
@ -3972,6 +4103,14 @@
|
|||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/defer-to-connect": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-2.0.1.tgz",
|
||||
"integrity": "sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg==",
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/delayed-stream": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
|
||||
|
@ -4122,7 +4261,6 @@
|
|||
"version": "1.4.4",
|
||||
"resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz",
|
||||
"integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"once": "^1.4.0"
|
||||
}
|
||||
|
@ -5016,6 +5154,11 @@
|
|||
"node": ">= 6"
|
||||
}
|
||||
},
|
||||
"node_modules/geographiclib-geodesic": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/geographiclib-geodesic/-/geographiclib-geodesic-2.0.0.tgz",
|
||||
"integrity": "sha512-qRE11UEF3Zn9VwDFf+Q1ZNn4VW2xwZWeAPiFRrKVSKn2K5lds1jOxhxgFJwbKh5YV58ME6+LGiRtm4A0CjFyiQ=="
|
||||
},
|
||||
"node_modules/get-caller-file": {
|
||||
"version": "2.0.5",
|
||||
"resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz",
|
||||
|
@ -5131,6 +5274,30 @@
|
|||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/got": {
|
||||
"version": "11.8.6",
|
||||
"resolved": "https://registry.npmjs.org/got/-/got-11.8.6.tgz",
|
||||
"integrity": "sha512-6tfZ91bOr7bOXnK7PRDCGBLa1H4U080YHNaAQ2KsMGlLEzRbk44nsZF2E1IeRc3vtJHPVbKCYgdFbaGO2ljd8g==",
|
||||
"dependencies": {
|
||||
"@sindresorhus/is": "^4.0.0",
|
||||
"@szmarczak/http-timer": "^4.0.5",
|
||||
"@types/cacheable-request": "^6.0.1",
|
||||
"@types/responselike": "^1.0.0",
|
||||
"cacheable-lookup": "^5.0.3",
|
||||
"cacheable-request": "^7.0.2",
|
||||
"decompress-response": "^6.0.0",
|
||||
"http2-wrapper": "^1.0.0-beta.5.2",
|
||||
"lowercase-keys": "^2.0.0",
|
||||
"p-cancelable": "^2.0.0",
|
||||
"responselike": "^2.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10.19.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sindresorhus/got?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/graceful-fs": {
|
||||
"version": "4.2.11",
|
||||
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz",
|
||||
|
@ -5188,6 +5355,11 @@
|
|||
"integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/http-cache-semantics": {
|
||||
"version": "4.1.1",
|
||||
"resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz",
|
||||
"integrity": "sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ=="
|
||||
},
|
||||
"node_modules/http-errors": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz",
|
||||
|
@ -5203,6 +5375,18 @@
|
|||
"node": ">= 0.8"
|
||||
}
|
||||
},
|
||||
"node_modules/http2-wrapper": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/http2-wrapper/-/http2-wrapper-1.0.3.tgz",
|
||||
"integrity": "sha512-V+23sDMr12Wnz7iTcDeJr3O6AIxlnvT/bmaAAAP/Xda35C90p9599p0F1eHR/N1KILWSoWVAiOMFjBBXaXSMxg==",
|
||||
"dependencies": {
|
||||
"quick-lru": "^5.1.1",
|
||||
"resolve-alpn": "^1.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10.19.0"
|
||||
}
|
||||
},
|
||||
"node_modules/human-signals": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz",
|
||||
|
@ -6215,6 +6399,11 @@
|
|||
"node": ">=4"
|
||||
}
|
||||
},
|
||||
"node_modules/json-buffer": {
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz",
|
||||
"integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ=="
|
||||
},
|
||||
"node_modules/json-parse-even-better-errors": {
|
||||
"version": "2.3.1",
|
||||
"resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz",
|
||||
|
@ -6263,6 +6452,14 @@
|
|||
"graceful-fs": "^4.1.6"
|
||||
}
|
||||
},
|
||||
"node_modules/keyv": {
|
||||
"version": "4.5.2",
|
||||
"resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.2.tgz",
|
||||
"integrity": "sha512-5MHbFaKn8cNSmVW7BYnijeAVlE4cYA/SVkifVgrh7yotnfhKmjuXpDKjrABLnT0SfHWV21P8ow07OGfRrNDg8g==",
|
||||
"dependencies": {
|
||||
"json-buffer": "3.0.1"
|
||||
}
|
||||
},
|
||||
"node_modules/kleur": {
|
||||
"version": "3.0.3",
|
||||
"resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz",
|
||||
|
@ -6387,6 +6584,14 @@
|
|||
"resolved": "https://registry.npmjs.org/long/-/long-4.0.0.tgz",
|
||||
"integrity": "sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA=="
|
||||
},
|
||||
"node_modules/lowercase-keys": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz",
|
||||
"integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==",
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/lru-cache": {
|
||||
"version": "5.1.1",
|
||||
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz",
|
||||
|
@ -6559,6 +6764,14 @@
|
|||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/mimic-response": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz",
|
||||
"integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==",
|
||||
"engines": {
|
||||
"node": ">=4"
|
||||
}
|
||||
},
|
||||
"node_modules/minimatch": {
|
||||
"version": "3.1.2",
|
||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
|
||||
|
@ -6725,6 +6938,17 @@
|
|||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/normalize-url": {
|
||||
"version": "6.1.0",
|
||||
"resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-6.1.0.tgz",
|
||||
"integrity": "sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==",
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/npm-run-path": {
|
||||
"version": "4.0.1",
|
||||
"resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz",
|
||||
|
@ -6768,7 +6992,6 @@
|
|||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
|
||||
"integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"wrappy": "1"
|
||||
}
|
||||
|
@ -6853,6 +7076,14 @@
|
|||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/p-cancelable": {
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-2.1.1.tgz",
|
||||
"integrity": "sha512-BZOr3nRQHOntUjTrH8+Lh54smKHoHyur8We1V8DSMVrl5A2malOOwuJRnKRDjSnkoeBh4at6BwEnb5I7Jl31wg==",
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/p-limit": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz",
|
||||
|
@ -7279,7 +7510,6 @@
|
|||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz",
|
||||
"integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"end-of-stream": "^1.1.0",
|
||||
"once": "^1.3.1"
|
||||
|
@ -7349,6 +7579,17 @@
|
|||
}
|
||||
]
|
||||
},
|
||||
"node_modules/quick-lru": {
|
||||
"version": "5.1.1",
|
||||
"resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-5.1.1.tgz",
|
||||
"integrity": "sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==",
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/randombytes": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz",
|
||||
|
@ -7492,6 +7733,11 @@
|
|||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/resolve-alpn": {
|
||||
"version": "1.2.1",
|
||||
"resolved": "https://registry.npmjs.org/resolve-alpn/-/resolve-alpn-1.2.1.tgz",
|
||||
"integrity": "sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g=="
|
||||
},
|
||||
"node_modules/resolve-cwd": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz",
|
||||
|
@ -7539,6 +7785,17 @@
|
|||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/responselike": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/responselike/-/responselike-2.0.1.tgz",
|
||||
"integrity": "sha512-4gl03wn3hj1HP3yzgdI7d3lCkF95F21Pz4BPGvKHinyQzALR5CapwC8yIi0Rh58DEMQ/SguC03wFj2k0M/mHhw==",
|
||||
"dependencies": {
|
||||
"lowercase-keys": "^2.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/restore-cursor": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz",
|
||||
|
@ -8956,8 +9213,7 @@
|
|||
"node_modules/wrappy": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
|
||||
"integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==",
|
||||
"dev": true
|
||||
"integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ=="
|
||||
},
|
||||
"node_modules/write-file-atomic": {
|
||||
"version": "4.0.2",
|
||||
|
|
|
@ -54,6 +54,8 @@
|
|||
"class-transformer": "^0.5.1",
|
||||
"class-validator": "^0.14.0",
|
||||
"geo-tz": "^7.0.7",
|
||||
"geographiclib-geodesic": "^2.0.0",
|
||||
"got": "^11.8.6",
|
||||
"ioredis": "^5.3.1",
|
||||
"reflect-metadata": "^0.1.13",
|
||||
"rxjs": "^7.2.0"
|
||||
|
@ -95,6 +97,7 @@
|
|||
".presenter.ts",
|
||||
".profile.ts",
|
||||
".exception.ts",
|
||||
".enum.ts",
|
||||
"main.ts",
|
||||
"prisma-service.ts"
|
||||
],
|
||||
|
@ -113,6 +116,7 @@
|
|||
".presenter.ts",
|
||||
".profile.ts",
|
||||
".exception.ts",
|
||||
".enum.ts",
|
||||
"main.ts",
|
||||
"prisma-service.ts"
|
||||
],
|
||||
|
|
|
@ -0,0 +1,27 @@
|
|||
import { Injectable } from '@nestjs/common';
|
||||
import { IGeodesic } from '../../domain/interfaces/geodesic.interface';
|
||||
import { Geodesic, GeodesicClass } from 'geographiclib-geodesic';
|
||||
|
||||
@Injectable()
|
||||
export class MatcherGeodesic implements IGeodesic {
|
||||
_geod: GeodesicClass;
|
||||
|
||||
constructor() {
|
||||
this._geod = Geodesic.WGS84;
|
||||
}
|
||||
|
||||
inverse(
|
||||
lon1: number,
|
||||
lat1: number,
|
||||
lon2: number,
|
||||
lat2: number,
|
||||
): { azimuth: number; distance: number } {
|
||||
const { azi2: azimuth, s12: distance } = this._geod.Inverse(
|
||||
lat1,
|
||||
lon1,
|
||||
lat2,
|
||||
lon2,
|
||||
);
|
||||
return { azimuth, distance };
|
||||
}
|
||||
}
|
|
@ -3,15 +3,19 @@ import { ICreateGeorouter } from '../../domain/interfaces/georouter-creator.inte
|
|||
import { IGeorouter } from '../../domain/interfaces/georouter.interface';
|
||||
import { GraphhopperGeorouter } from './graphhopper-georouter';
|
||||
import { HttpService } from '@nestjs/axios';
|
||||
import { MatcherGeodesic } from './geodesic';
|
||||
|
||||
@Injectable()
|
||||
export class GeorouterCreator implements ICreateGeorouter {
|
||||
constructor(private readonly httpService: HttpService) {}
|
||||
constructor(
|
||||
private readonly httpService: HttpService,
|
||||
private readonly geodesic: MatcherGeodesic,
|
||||
) {}
|
||||
|
||||
create(type: string, url: string): IGeorouter {
|
||||
switch (type) {
|
||||
case 'graphhopper':
|
||||
return new GraphhopperGeorouter(url, this.httpService);
|
||||
return new GraphhopperGeorouter(url, this.httpService, this.geodesic);
|
||||
default:
|
||||
throw new Error('Unknown geocoder');
|
||||
}
|
||||
|
|
|
@ -4,18 +4,11 @@ import { IGeorouter } from '../../domain/interfaces/georouter.interface';
|
|||
import { GeorouterSettings } from '../../domain/types/georouter-settings.type';
|
||||
import { Path } from '../../domain/types/path.type';
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import {
|
||||
catchError,
|
||||
defer,
|
||||
forkJoin,
|
||||
from,
|
||||
lastValueFrom,
|
||||
map,
|
||||
mergeAll,
|
||||
mergeMap,
|
||||
toArray,
|
||||
} from 'rxjs';
|
||||
import { AxiosError } from 'axios';
|
||||
import { catchError, lastValueFrom, map } from 'rxjs';
|
||||
import { AxiosError, AxiosResponse } from 'axios';
|
||||
import { Route } from '../../domain/entities/route';
|
||||
import { SpacetimePoint } from '../../domain/entities/spacetime-point';
|
||||
import { IGeodesic } from '../../domain/interfaces/geodesic.interface';
|
||||
|
||||
@Injectable()
|
||||
export class GraphhopperGeorouter implements IGeorouter {
|
||||
|
@ -26,10 +19,12 @@ export class GraphhopperGeorouter implements IGeorouter {
|
|||
_withDistance: boolean;
|
||||
_paths: Array<Path>;
|
||||
_httpService: HttpService;
|
||||
_geodesic: IGeodesic;
|
||||
|
||||
constructor(url: string, httpService: HttpService) {
|
||||
constructor(url: string, httpService: HttpService, geodesic: IGeodesic) {
|
||||
this._url = url + '/route?';
|
||||
this._httpService = httpService;
|
||||
this._geodesic = geodesic;
|
||||
}
|
||||
|
||||
async route(
|
||||
|
@ -41,9 +36,7 @@ export class GraphhopperGeorouter implements IGeorouter {
|
|||
this._setWithPoints(settings.withPoints);
|
||||
this._setWithDistance(settings.withDistance);
|
||||
this._paths = paths;
|
||||
const routes = await this._getRoutes();
|
||||
console.log(routes.length);
|
||||
return routes;
|
||||
return await this._getRoutes();
|
||||
}
|
||||
|
||||
_setDefaultUrlArgs(): void {
|
||||
|
@ -63,7 +56,7 @@ export class GraphhopperGeorouter implements IGeorouter {
|
|||
|
||||
_setWithPoints(withPoints: boolean): void {
|
||||
this._withPoints = withPoints;
|
||||
if (withPoints) {
|
||||
if (!withPoints) {
|
||||
this._urlArgs.push('calc_points=false');
|
||||
}
|
||||
}
|
||||
|
@ -87,9 +80,11 @@ export class GraphhopperGeorouter implements IGeorouter {
|
|||
.map((point) => [point.lat, point.lon].join())
|
||||
.join('&point='),
|
||||
].join('');
|
||||
const res = await lastValueFrom(
|
||||
const route = await lastValueFrom(
|
||||
this._httpService.get(url).pipe(
|
||||
map((res) => res.data.paths[0].distance),
|
||||
map((res) =>
|
||||
res.data ? this._createRoute(path.key, res) : undefined,
|
||||
),
|
||||
catchError((error: AxiosError) => {
|
||||
throw new Error(error.message);
|
||||
}),
|
||||
|
@ -97,37 +92,230 @@ export class GraphhopperGeorouter implements IGeorouter {
|
|||
);
|
||||
return <NamedRoute>{
|
||||
key: path.key,
|
||||
route: res,
|
||||
route,
|
||||
};
|
||||
}),
|
||||
);
|
||||
return routes;
|
||||
// const date1 = new Date();
|
||||
// const urls = this._paths.map((path) =>
|
||||
// defer(() =>
|
||||
// this._httpService
|
||||
// .get(
|
||||
// [
|
||||
// this._getUrl(),
|
||||
// '&point=',
|
||||
// path.points
|
||||
// .map((point) => [point.lat, point.lon].join())
|
||||
// .join('&point='),
|
||||
// ].join(''),
|
||||
// )
|
||||
// .pipe(map((res) => res.data.paths[0].distance)),
|
||||
// ),
|
||||
// );
|
||||
// const observables = from(urls);
|
||||
// const routes = observables.pipe(mergeAll(7), toArray());
|
||||
// routes.subscribe(() => {
|
||||
// const date2 = new Date();
|
||||
// console.log(date2.getTime() - date1.getTime());
|
||||
// });
|
||||
// return [];
|
||||
}
|
||||
|
||||
_getUrl(): string {
|
||||
return [this._url, this._urlArgs.join('&')].join('');
|
||||
}
|
||||
|
||||
_createRoute(
|
||||
key: string,
|
||||
response: AxiosResponse<GraphhopperResponse>,
|
||||
): Route {
|
||||
const route = new Route(this._geodesic);
|
||||
if (response.data.paths && response.data.paths[0]) {
|
||||
const shortestPath = response.data.paths[0];
|
||||
route.distance = shortestPath.distance ?? 0;
|
||||
route.duration = shortestPath.time ? shortestPath.time / 1000 : 0;
|
||||
if (shortestPath.points && shortestPath.points.coordinates) {
|
||||
route.setPoints(shortestPath.points.coordinates);
|
||||
if (
|
||||
shortestPath.details &&
|
||||
shortestPath.details.time &&
|
||||
shortestPath.snapped_waypoints &&
|
||||
shortestPath.snapped_waypoints.coordinates
|
||||
) {
|
||||
let instructions: Array<GraphhopperInstruction> = [];
|
||||
if (shortestPath.instructions)
|
||||
instructions = shortestPath.instructions;
|
||||
route.setSpacetimePoints(
|
||||
this._generateSpacetimePoints(
|
||||
shortestPath.points.coordinates,
|
||||
shortestPath.snapped_waypoints.coordinates,
|
||||
shortestPath.details.time,
|
||||
instructions,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
return route;
|
||||
}
|
||||
|
||||
_generateSpacetimePoints(
|
||||
points: Array<Array<number>>,
|
||||
snappedWaypoints: Array<Array<number>>,
|
||||
durations: Array<Array<number>>,
|
||||
instructions: Array<GraphhopperInstruction>,
|
||||
): Array<SpacetimePoint> {
|
||||
const indices = this._getIndices(points, snappedWaypoints);
|
||||
const times = this._getTimes(durations, indices);
|
||||
const distances = this._getDistances(instructions, indices);
|
||||
return indices.map(
|
||||
(index) =>
|
||||
new SpacetimePoint(
|
||||
points[index],
|
||||
times.find((time) => time.index == index)?.duration,
|
||||
distances.find((distance) => distance.index == index)?.distance,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
_getIndices(
|
||||
points: Array<Array<number>>,
|
||||
snappedWaypoints: Array<Array<number>>,
|
||||
): Array<number> {
|
||||
const indices = snappedWaypoints.map((waypoint) =>
|
||||
points.findIndex(
|
||||
(point) => point[0] == waypoint[0] && point[1] == waypoint[1],
|
||||
),
|
||||
);
|
||||
if (indices.find((index) => index == -1) === undefined) return indices;
|
||||
const missedWaypoints = indices
|
||||
.map(
|
||||
(value, index) =>
|
||||
<
|
||||
{
|
||||
index: number;
|
||||
originIndex: number;
|
||||
waypoint: Array<number>;
|
||||
nearest: number;
|
||||
distance: number;
|
||||
}
|
||||
>{
|
||||
index: value,
|
||||
originIndex: index,
|
||||
waypoint: snappedWaypoints[index],
|
||||
nearest: undefined,
|
||||
distance: 999999999,
|
||||
},
|
||||
)
|
||||
.filter((element) => element.index == -1);
|
||||
for (const index in points) {
|
||||
for (const missedWaypoint of missedWaypoints) {
|
||||
const inverse = this._geodesic.inverse(
|
||||
missedWaypoint.waypoint[0],
|
||||
missedWaypoint.waypoint[1],
|
||||
points[index][0],
|
||||
points[index][1],
|
||||
);
|
||||
if (inverse.distance < missedWaypoint.distance) {
|
||||
missedWaypoint.distance = inverse.distance;
|
||||
missedWaypoint.nearest = parseInt(index);
|
||||
}
|
||||
}
|
||||
}
|
||||
for (const missedWaypoint of missedWaypoints) {
|
||||
indices[missedWaypoint.originIndex] = missedWaypoint.nearest;
|
||||
}
|
||||
return indices;
|
||||
}
|
||||
|
||||
_getTimes(
|
||||
durations: Array<Array<number>>,
|
||||
indices: Array<number>,
|
||||
): Array<{ index: number; duration: number }> {
|
||||
const times: Array<{ index: number; duration: number }> = [];
|
||||
let duration = 0;
|
||||
for (const [origin, destination, stepDuration] of durations) {
|
||||
let indexFound = false;
|
||||
const indexAsOrigin = indices.find((index) => index == origin);
|
||||
if (
|
||||
indexAsOrigin !== undefined &&
|
||||
times.find((time) => origin == time.index) == undefined
|
||||
) {
|
||||
times.push({
|
||||
index: indexAsOrigin,
|
||||
duration: Math.round(stepDuration / 1000),
|
||||
});
|
||||
indexFound = true;
|
||||
}
|
||||
if (!indexFound) {
|
||||
const indexAsDestination = indices.find(
|
||||
(index) => index == destination,
|
||||
);
|
||||
if (
|
||||
indexAsDestination !== undefined &&
|
||||
times.find((time) => destination == time.index) == undefined
|
||||
) {
|
||||
times.push({
|
||||
index: indexAsDestination,
|
||||
duration: Math.round((duration + stepDuration) / 1000),
|
||||
});
|
||||
indexFound = true;
|
||||
}
|
||||
}
|
||||
if (!indexFound) {
|
||||
const indexInBetween = indices.find(
|
||||
(index) => origin < index && index < destination,
|
||||
);
|
||||
if (indexInBetween !== undefined) {
|
||||
times.push({
|
||||
index: indexInBetween,
|
||||
duration: Math.round((duration + stepDuration / 2) / 1000),
|
||||
});
|
||||
}
|
||||
}
|
||||
duration += stepDuration;
|
||||
}
|
||||
return times;
|
||||
}
|
||||
|
||||
_getDistances(
|
||||
instructions: Array<GraphhopperInstruction>,
|
||||
indices: Array<number>,
|
||||
): Array<{ index: number; distance: number }> {
|
||||
let distance = 0;
|
||||
const distances: Array<{ index: number; distance: number }> = [
|
||||
{
|
||||
index: 0,
|
||||
distance,
|
||||
},
|
||||
];
|
||||
for (const instruction of instructions) {
|
||||
distance += instruction.distance;
|
||||
if (
|
||||
(instruction.sign == GraphhopperSign.SIGN_WAYPOINT ||
|
||||
instruction.sign == GraphhopperSign.SIGN_FINISH) &&
|
||||
indices.find((index) => index == instruction.interval[0]) !== undefined
|
||||
) {
|
||||
distances.push({
|
||||
index: instruction.interval[0],
|
||||
distance: Math.round(distance),
|
||||
});
|
||||
}
|
||||
}
|
||||
return distances;
|
||||
}
|
||||
}
|
||||
|
||||
type GraphhopperResponse = {
|
||||
paths: [
|
||||
{
|
||||
distance: number;
|
||||
weight: number;
|
||||
time: number;
|
||||
points_encoded: boolean;
|
||||
bbox: Array<number>;
|
||||
points: GraphhopperCoordinates;
|
||||
snapped_waypoints: GraphhopperCoordinates;
|
||||
details: {
|
||||
time: Array<Array<number>>;
|
||||
};
|
||||
instructions: Array<GraphhopperInstruction>;
|
||||
},
|
||||
];
|
||||
};
|
||||
|
||||
type GraphhopperCoordinates = {
|
||||
coordinates: Array<Array<number>>;
|
||||
};
|
||||
|
||||
type GraphhopperInstruction = {
|
||||
distance: number;
|
||||
heading: number;
|
||||
sign: GraphhopperSign;
|
||||
interval: Array<number>;
|
||||
text: string;
|
||||
};
|
||||
|
||||
enum GraphhopperSign {
|
||||
SIGN_START = 0,
|
||||
SIGN_FINISH = 4,
|
||||
SIGN_WAYPOINT = 5,
|
||||
}
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
import { Role } from '../types/role.enum';
|
||||
import { Step } from '../types/step.enum';
|
||||
import { Person } from './person';
|
||||
|
||||
export class Actor {
|
||||
person: Person;
|
||||
role: Role;
|
||||
step: Step;
|
||||
}
|
|
@ -1 +1,55 @@
|
|||
export class Route {}
|
||||
import { IGeodesic } from '../interfaces/geodesic.interface';
|
||||
import { SpacetimePoint } from './spacetime-point';
|
||||
import { Waypoint } from './waypoint';
|
||||
|
||||
export class Route {
|
||||
distance: number;
|
||||
duration: number;
|
||||
fwdAzimuth: number;
|
||||
backAzimuth: number;
|
||||
distanceAzimuth: number;
|
||||
waypoints: Array<Waypoint>;
|
||||
points: Array<Array<number>>;
|
||||
spacetimePoints: Array<SpacetimePoint>;
|
||||
_geodesic: IGeodesic;
|
||||
|
||||
constructor(geodesic: IGeodesic) {
|
||||
this.distance = undefined;
|
||||
this.duration = undefined;
|
||||
this.fwdAzimuth = undefined;
|
||||
this.backAzimuth = undefined;
|
||||
this.distanceAzimuth = undefined;
|
||||
this.waypoints = [];
|
||||
this.points = [];
|
||||
this.spacetimePoints = [];
|
||||
this._geodesic = geodesic;
|
||||
}
|
||||
|
||||
setWaypoints(waypoints: Array<Waypoint>): void {
|
||||
this.waypoints = waypoints;
|
||||
this._setAzimuth(waypoints.map((waypoint) => waypoint.point));
|
||||
}
|
||||
|
||||
setPoints(points: Array<Array<number>>): void {
|
||||
this.points = points;
|
||||
this._setAzimuth(points);
|
||||
}
|
||||
|
||||
setSpacetimePoints(spacetimePoints: Array<SpacetimePoint>): void {
|
||||
this.spacetimePoints = spacetimePoints;
|
||||
}
|
||||
|
||||
_setAzimuth(points: Array<Array<number>>): void {
|
||||
const inverse = this._geodesic.inverse(
|
||||
points[0][0],
|
||||
points[0][1],
|
||||
points[points.length - 1][0],
|
||||
points[points.length - 1][1],
|
||||
);
|
||||
this.fwdAzimuth =
|
||||
inverse.azimuth >= 0 ? inverse.azimuth : 360 - Math.abs(inverse.azimuth);
|
||||
this.backAzimuth =
|
||||
this.fwdAzimuth > 180 ? this.fwdAzimuth - 180 : this.fwdAzimuth + 180;
|
||||
this.distanceAzimuth = inverse.distance;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
export class SpacetimePoint {
|
||||
point: Array<number>;
|
||||
duration: number;
|
||||
distance: number;
|
||||
|
||||
constructor(point: Array<number>, duration: number, distance: number) {
|
||||
this.point = point;
|
||||
this.duration = duration;
|
||||
this.distance = distance;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
import { Actor } from './actor';
|
||||
|
||||
export class Waypoint {
|
||||
point: Array<number>;
|
||||
actors: Array<Actor>;
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
export interface IGeodesic {
|
||||
inverse(
|
||||
lon1: number,
|
||||
lat1: number,
|
||||
lon2: number,
|
||||
lat2: number,
|
||||
): {
|
||||
azimuth: number;
|
||||
distance: number;
|
||||
};
|
||||
}
|
|
@ -17,54 +17,59 @@ export class MatchUseCase {
|
|||
|
||||
async execute(matchQuery: MatchQuery): Promise<ICollection<Match>> {
|
||||
try {
|
||||
const paths = [];
|
||||
for (let i = 0; i < 2000; i++) {
|
||||
paths.push({
|
||||
key: 'route' + i,
|
||||
points: [
|
||||
{
|
||||
lat: 48.110899,
|
||||
lon: -1.68365,
|
||||
},
|
||||
{
|
||||
lat: 48.131105,
|
||||
lon: -1.690067,
|
||||
},
|
||||
{
|
||||
lat: 48.56516,
|
||||
lon: -1.923553,
|
||||
},
|
||||
{
|
||||
lat: 48.622813,
|
||||
lon: -1.997177,
|
||||
},
|
||||
{
|
||||
lat: 48.67846,
|
||||
lon: -1.8554,
|
||||
},
|
||||
],
|
||||
});
|
||||
}
|
||||
const routes = await matchQuery.algorithmSettings.georouter.route(paths, {
|
||||
withDistance: true,
|
||||
withPoints: true,
|
||||
withTime: false,
|
||||
});
|
||||
// const paths = [];
|
||||
// for (let i = 0; i < 1; i++) {
|
||||
// paths.push({
|
||||
// key: 'route' + i,
|
||||
// points: [
|
||||
// {
|
||||
// lat: 48.110899,
|
||||
// lon: -1.68365,
|
||||
// },
|
||||
// {
|
||||
// lat: 48.131105,
|
||||
// lon: -1.690067,
|
||||
// },
|
||||
// {
|
||||
// lat: 48.534769,
|
||||
// lon: -1.894032,
|
||||
// },
|
||||
// {
|
||||
// lat: 48.56516,
|
||||
// lon: -1.923553,
|
||||
// },
|
||||
// {
|
||||
// lat: 48.622813,
|
||||
// lon: -1.997177,
|
||||
// },
|
||||
// {
|
||||
// lat: 48.67846,
|
||||
// lon: -1.8554,
|
||||
// },
|
||||
// ],
|
||||
// });
|
||||
// }
|
||||
// const routes = await matchQuery.algorithmSettings.georouter.route(paths, {
|
||||
// withDistance: false,
|
||||
// withPoints: true,
|
||||
// withTime: true,
|
||||
// });
|
||||
// routes.map((route) => console.log(route.route.spacetimePoints));
|
||||
const match = new Match();
|
||||
match.uuid = 'e23f9725-2c19-49a0-9ef6-17d8b9a5ec85';
|
||||
// this._messager.publish('matcher.match', 'match !');
|
||||
this._messager.publish('matcher.match', 'match !');
|
||||
return {
|
||||
data: [match],
|
||||
total: 1,
|
||||
};
|
||||
} catch (error) {
|
||||
// this._messager.publish(
|
||||
// 'logging.matcher.match.crit',
|
||||
// JSON.stringify({
|
||||
// matchQuery,
|
||||
// error,
|
||||
// }),
|
||||
// );
|
||||
this._messager.publish(
|
||||
'logging.matcher.match.crit',
|
||||
JSON.stringify({
|
||||
matchQuery,
|
||||
error,
|
||||
}),
|
||||
);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,6 +14,7 @@ import { redisStore } from 'cache-manager-ioredis-yet';
|
|||
import { DefaultParamsProvider } from './adapters/secondaries/default-params.provider';
|
||||
import { GeorouterCreator } from './adapters/secondaries/georouter-creator';
|
||||
import { HttpModule } from '@nestjs/axios';
|
||||
import { MatcherGeodesic } from './adapters/secondaries/geodesic';
|
||||
|
||||
@Module({
|
||||
imports: [
|
||||
|
@ -55,6 +56,7 @@ import { HttpModule } from '@nestjs/axios';
|
|||
DefaultParamsProvider,
|
||||
MatchUseCase,
|
||||
GeorouterCreator,
|
||||
MatcherGeodesic,
|
||||
],
|
||||
exports: [],
|
||||
})
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import { ConfigService } from '@nestjs/config';
|
||||
import { Test, TestingModule } from '@nestjs/testing';
|
||||
import { DefaultParamsProvider } from '../../adapters/secondaries/default-params.provider';
|
||||
import { IDefaultParams } from '../../domain/types/default-params.type';
|
||||
import { DefaultParamsProvider } from '../../../../adapters/secondaries/default-params.provider';
|
||||
import { IDefaultParams } from '../../../../domain/types/default-params.type';
|
||||
|
||||
const mockConfigService = {
|
||||
get: jest.fn().mockImplementationOnce(() => 99),
|
|
@ -0,0 +1,14 @@
|
|||
import { MatcherGeodesic } from '../../../../adapters/secondaries/geodesic';
|
||||
|
||||
describe('Matcher geodesic', () => {
|
||||
it('should be defined', () => {
|
||||
const geodesic: MatcherGeodesic = new MatcherGeodesic();
|
||||
expect(geodesic).toBeDefined();
|
||||
});
|
||||
it('should get inverse values', () => {
|
||||
const geodesic: MatcherGeodesic = new MatcherGeodesic();
|
||||
const inv = geodesic.inverse(0, 0, 1, 1);
|
||||
expect(Math.round(inv.azimuth)).toBe(45);
|
||||
expect(Math.round(inv.distance)).toBe(156900);
|
||||
});
|
||||
});
|
|
@ -1,9 +1,11 @@
|
|||
import { Test, TestingModule } from '@nestjs/testing';
|
||||
import { GeorouterCreator } from '../../adapters/secondaries/georouter-creator';
|
||||
import { GraphhopperGeorouter } from '../../adapters/secondaries/graphhopper-georouter';
|
||||
import { GeorouterCreator } from '../../../../adapters/secondaries/georouter-creator';
|
||||
import { GraphhopperGeorouter } from '../../../../adapters/secondaries/graphhopper-georouter';
|
||||
import { HttpService } from '@nestjs/axios';
|
||||
import { MatcherGeodesic } from '../../../../adapters/secondaries/geodesic';
|
||||
|
||||
const mockHttpService = jest.fn();
|
||||
const mockMatcherGeodesic = jest.fn();
|
||||
|
||||
describe('Georouter creator', () => {
|
||||
let georouterCreator: GeorouterCreator;
|
||||
|
@ -17,6 +19,10 @@ describe('Georouter creator', () => {
|
|||
provide: HttpService,
|
||||
useValue: mockHttpService,
|
||||
},
|
||||
{
|
||||
provide: MatcherGeodesic,
|
||||
useValue: mockMatcherGeodesic,
|
||||
},
|
||||
],
|
||||
}).compile();
|
||||
|
|
@ -0,0 +1,268 @@
|
|||
import { Test, TestingModule } from '@nestjs/testing';
|
||||
import { HttpService } from '@nestjs/axios';
|
||||
import { GeorouterCreator } from '../../../../adapters/secondaries/georouter-creator';
|
||||
import { IGeorouter } from '../../../../domain/interfaces/georouter.interface';
|
||||
import { of } from 'rxjs';
|
||||
import { AxiosError } from 'axios';
|
||||
import { MatcherGeodesic } from '../../../../adapters/secondaries/geodesic';
|
||||
|
||||
const mockHttpService = {
|
||||
get: jest
|
||||
.fn()
|
||||
.mockImplementationOnce(() => {
|
||||
throw new AxiosError('Axios error !');
|
||||
})
|
||||
.mockImplementationOnce(() => {
|
||||
return of({
|
||||
status: 200,
|
||||
data: {
|
||||
paths: [
|
||||
{
|
||||
distance: 50000,
|
||||
time: 1800000,
|
||||
snapped_waypoints: {
|
||||
coordinates: [
|
||||
[0, 0],
|
||||
[10, 10],
|
||||
],
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
});
|
||||
})
|
||||
.mockImplementationOnce(() => {
|
||||
return of({
|
||||
status: 200,
|
||||
data: {
|
||||
paths: [
|
||||
{
|
||||
distance: 50000,
|
||||
time: 1800000,
|
||||
points: {
|
||||
coordinates: [
|
||||
[0, 0],
|
||||
[1, 1],
|
||||
[2, 2],
|
||||
[3, 3],
|
||||
[4, 4],
|
||||
[5, 5],
|
||||
[6, 6],
|
||||
[7, 7],
|
||||
[8, 8],
|
||||
[9, 9],
|
||||
[10, 10],
|
||||
],
|
||||
},
|
||||
snapped_waypoints: {
|
||||
coordinates: [
|
||||
[0, 0],
|
||||
[10, 10],
|
||||
],
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
});
|
||||
})
|
||||
.mockImplementationOnce(() => {
|
||||
return of({
|
||||
status: 200,
|
||||
data: {
|
||||
paths: [
|
||||
{
|
||||
distance: 50000,
|
||||
time: 1800000,
|
||||
points: {
|
||||
coordinates: [
|
||||
[0, 0],
|
||||
[1, 1],
|
||||
[2, 2],
|
||||
[3, 3],
|
||||
[4, 4],
|
||||
[5, 5],
|
||||
[6, 6],
|
||||
[7, 7],
|
||||
[8, 8],
|
||||
[9, 9],
|
||||
[10, 10],
|
||||
],
|
||||
},
|
||||
details: {
|
||||
time: [
|
||||
[0, 1, 180000],
|
||||
[1, 2, 180000],
|
||||
[2, 3, 180000],
|
||||
[3, 4, 180000],
|
||||
[4, 5, 180000],
|
||||
[5, 6, 180000],
|
||||
[6, 7, 180000],
|
||||
[7, 9, 360000],
|
||||
[9, 10, 180000],
|
||||
],
|
||||
},
|
||||
snapped_waypoints: {
|
||||
coordinates: [
|
||||
[0, 0],
|
||||
[10, 10],
|
||||
],
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
});
|
||||
}),
|
||||
};
|
||||
|
||||
const mockMatcherGeodesic = {
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
inverse: jest.fn().mockImplementation(() => ({
|
||||
azimuth: 45,
|
||||
distance: 50000,
|
||||
})),
|
||||
};
|
||||
|
||||
describe('Graphhopper Georouter', () => {
|
||||
let georouterCreator: GeorouterCreator;
|
||||
let graphhopperGeorouter: IGeorouter;
|
||||
|
||||
beforeAll(async () => {
|
||||
const module: TestingModule = await Test.createTestingModule({
|
||||
imports: [],
|
||||
providers: [
|
||||
GeorouterCreator,
|
||||
{
|
||||
provide: HttpService,
|
||||
useValue: mockHttpService,
|
||||
},
|
||||
{
|
||||
provide: MatcherGeodesic,
|
||||
useValue: mockMatcherGeodesic,
|
||||
},
|
||||
],
|
||||
}).compile();
|
||||
|
||||
georouterCreator = module.get<GeorouterCreator>(GeorouterCreator);
|
||||
graphhopperGeorouter = georouterCreator.create(
|
||||
'graphhopper',
|
||||
'http://localhost',
|
||||
);
|
||||
});
|
||||
|
||||
it('should be defined', () => {
|
||||
expect(graphhopperGeorouter).toBeDefined();
|
||||
});
|
||||
|
||||
describe('route function', () => {
|
||||
it('should fail on axios error', async () => {
|
||||
await expect(
|
||||
graphhopperGeorouter.route(
|
||||
[
|
||||
{
|
||||
key: 'route1',
|
||||
points: [
|
||||
{
|
||||
lat: 0,
|
||||
lon: 0,
|
||||
},
|
||||
{
|
||||
lat: 1,
|
||||
lon: 1,
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
{
|
||||
withDistance: false,
|
||||
withPoints: false,
|
||||
withTime: false,
|
||||
},
|
||||
),
|
||||
).rejects.toBeInstanceOf(Error);
|
||||
});
|
||||
it('should create one route with all settings to false', async () => {
|
||||
const routes = await graphhopperGeorouter.route(
|
||||
[
|
||||
{
|
||||
key: 'route1',
|
||||
points: [
|
||||
{
|
||||
lat: 0,
|
||||
lon: 0,
|
||||
},
|
||||
{
|
||||
lat: 10,
|
||||
lon: 10,
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
{
|
||||
withDistance: false,
|
||||
withPoints: false,
|
||||
withTime: false,
|
||||
},
|
||||
);
|
||||
expect(routes).toHaveLength(1);
|
||||
expect(routes[0].route.distance).toBe(50000);
|
||||
});
|
||||
it('should create one route with points', async () => {
|
||||
const routes = await graphhopperGeorouter.route(
|
||||
[
|
||||
{
|
||||
key: 'route1',
|
||||
points: [
|
||||
{
|
||||
lat: 0,
|
||||
lon: 0,
|
||||
},
|
||||
{
|
||||
lat: 10,
|
||||
lon: 10,
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
{
|
||||
withDistance: false,
|
||||
withPoints: true,
|
||||
withTime: false,
|
||||
},
|
||||
);
|
||||
expect(routes).toHaveLength(1);
|
||||
expect(routes[0].route.distance).toBe(50000);
|
||||
expect(routes[0].route.duration).toBe(1800);
|
||||
expect(routes[0].route.fwdAzimuth).toBe(45);
|
||||
expect(routes[0].route.backAzimuth).toBe(225);
|
||||
expect(routes[0].route.points.length).toBe(11);
|
||||
});
|
||||
it('should create one route with points and time', async () => {
|
||||
const routes = await graphhopperGeorouter.route(
|
||||
[
|
||||
{
|
||||
key: 'route1',
|
||||
points: [
|
||||
{
|
||||
lat: 0,
|
||||
lon: 0,
|
||||
},
|
||||
{
|
||||
lat: 10,
|
||||
lon: 10,
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
{
|
||||
withDistance: false,
|
||||
withPoints: true,
|
||||
withTime: true,
|
||||
},
|
||||
);
|
||||
expect(routes).toHaveLength(1);
|
||||
expect(routes[0].route.spacetimePoints.length).toBe(2);
|
||||
expect(routes[0].route.spacetimePoints[1].duration).toBe(1800);
|
||||
expect(routes[0].route.spacetimePoints[1].distance).toBeUndefined();
|
||||
});
|
||||
});
|
||||
});
|
|
@ -1,7 +1,7 @@
|
|||
import { AmqpConnection } from '@golevelup/nestjs-rabbitmq';
|
||||
import { ConfigService } from '@nestjs/config';
|
||||
import { Test, TestingModule } from '@nestjs/testing';
|
||||
import { Messager } from '../../adapters/secondaries/messager';
|
||||
import { Messager } from '../../../../adapters/secondaries/messager';
|
||||
|
||||
const mockAmqpConnection = {
|
||||
publish: jest.fn().mockImplementation(),
|
|
@ -1,4 +1,4 @@
|
|||
import { Geography } from '../../domain/entities/geography';
|
||||
import { Geography } from '../../../domain/entities/geography';
|
||||
|
||||
describe('Geography entity', () => {
|
||||
it('should be defined', () => {
|
|
@ -1,13 +1,13 @@
|
|||
import { Test, TestingModule } from '@nestjs/testing';
|
||||
import { Messager } from '../../adapters/secondaries/messager';
|
||||
import { MatchUseCase } from '../../domain/usecases/match.usecase';
|
||||
import { MatchRequest } from '../../domain/dtos/match.request';
|
||||
import { MatchQuery } from '../../queries/match.query';
|
||||
import { AdRepository } from '../../adapters/secondaries/ad.repository';
|
||||
import { Messager } from '../../../adapters/secondaries/messager';
|
||||
import { MatchUseCase } from '../../../domain/usecases/match.usecase';
|
||||
import { MatchRequest } from '../../../domain/dtos/match.request';
|
||||
import { MatchQuery } from '../../../queries/match.query';
|
||||
import { AdRepository } from '../../../adapters/secondaries/ad.repository';
|
||||
import { AutomapperModule } from '@automapper/nestjs';
|
||||
import { classes } from '@automapper/classes';
|
||||
import { IDefaultParams } from '../../domain/types/default-params.type';
|
||||
import { Algorithm } from '../../domain/types/algorithm.enum';
|
||||
import { IDefaultParams } from '../../../domain/types/default-params.type';
|
||||
import { Algorithm } from '../../../domain/types/algorithm.enum';
|
||||
|
||||
const mockAdRepository = {};
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
import { Person } from '../../domain/entities/person';
|
||||
import { Person } from '../../../domain/entities/person';
|
||||
|
||||
const DEFAULT_IDENTIFIER = 0;
|
||||
const MARGIN_DURATION = 900;
|
|
@ -0,0 +1,55 @@
|
|||
import { Route } from '../../../domain/entities/route';
|
||||
import { SpacetimePoint } from '../../../domain/entities/spacetime-point';
|
||||
import { Waypoint } from '../../../domain/entities/waypoint';
|
||||
|
||||
const mockGeodesic = {
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
inverse: jest.fn().mockImplementation((lon1, lat1, lon2, lat2) => {
|
||||
return lon1 == 0
|
||||
? {
|
||||
azimuth: 45,
|
||||
distance: 50000,
|
||||
}
|
||||
: {
|
||||
azimuth: -45,
|
||||
distance: 60000,
|
||||
};
|
||||
}),
|
||||
};
|
||||
|
||||
describe('Route entity', () => {
|
||||
it('should be defined', () => {
|
||||
const route = new Route(mockGeodesic);
|
||||
expect(route).toBeDefined();
|
||||
});
|
||||
it('should set waypoints and geodesic values for a route', () => {
|
||||
const route = new Route(mockGeodesic);
|
||||
const waypoint1: Waypoint = new Waypoint();
|
||||
waypoint1.point = [0, 0];
|
||||
const waypoint2: Waypoint = new Waypoint();
|
||||
waypoint2.point = [10, 10];
|
||||
route.setWaypoints([waypoint1, waypoint2]);
|
||||
expect(route.waypoints.length).toBe(2);
|
||||
expect(route.fwdAzimuth).toBe(45);
|
||||
expect(route.backAzimuth).toBe(225);
|
||||
expect(route.distanceAzimuth).toBe(50000);
|
||||
});
|
||||
it('should set points and geodesic values for a route', () => {
|
||||
const route = new Route(mockGeodesic);
|
||||
route.setPoints([
|
||||
[10, 10],
|
||||
[20, 20],
|
||||
]);
|
||||
expect(route.points.length).toBe(2);
|
||||
expect(route.fwdAzimuth).toBe(315);
|
||||
expect(route.backAzimuth).toBe(135);
|
||||
expect(route.distanceAzimuth).toBe(60000);
|
||||
});
|
||||
it('should set spacetimePoints for a route', () => {
|
||||
const route = new Route(mockGeodesic);
|
||||
const spacetimePoint1 = new SpacetimePoint([0, 0], 0, 0);
|
||||
const spacetimePoint2 = new SpacetimePoint([10, 10], 500, 5000);
|
||||
route.setSpacetimePoints([spacetimePoint1, spacetimePoint2]);
|
||||
expect(route.spacetimePoints.length).toBe(2);
|
||||
});
|
||||
});
|
|
@ -1,4 +1,4 @@
|
|||
import { Time } from '../../domain/entities/time';
|
||||
import { Time } from '../../../domain/entities/time';
|
||||
|
||||
const MARGIN_DURATION = 900;
|
||||
const VALIDITY_DURATION = 365;
|
|
@ -1,141 +0,0 @@
|
|||
import { Test, TestingModule } from '@nestjs/testing';
|
||||
import { HttpService } from '@nestjs/axios';
|
||||
import { NamedRoute } from '../../domain/entities/named-route';
|
||||
import { GeorouterCreator } from '../../adapters/secondaries/georouter-creator';
|
||||
import { IGeorouter } from '../../domain/interfaces/georouter.interface';
|
||||
import { of } from 'rxjs';
|
||||
import { AxiosError } from 'axios';
|
||||
|
||||
const mockHttpService = {
|
||||
get: jest
|
||||
.fn()
|
||||
.mockImplementationOnce(() => {
|
||||
throw new AxiosError('Axios error !');
|
||||
})
|
||||
.mockImplementation(() => {
|
||||
return of({
|
||||
status: 200,
|
||||
data: [new NamedRoute()],
|
||||
});
|
||||
}),
|
||||
};
|
||||
|
||||
describe('Graphhopper Georouter', () => {
|
||||
let georouterCreator: GeorouterCreator;
|
||||
let graphhopperGeorouter: IGeorouter;
|
||||
|
||||
beforeAll(async () => {
|
||||
const module: TestingModule = await Test.createTestingModule({
|
||||
imports: [],
|
||||
providers: [
|
||||
GeorouterCreator,
|
||||
{
|
||||
provide: HttpService,
|
||||
useValue: mockHttpService,
|
||||
},
|
||||
],
|
||||
}).compile();
|
||||
|
||||
georouterCreator = module.get<GeorouterCreator>(GeorouterCreator);
|
||||
graphhopperGeorouter = georouterCreator.create(
|
||||
'graphhopper',
|
||||
'http://localhost',
|
||||
);
|
||||
});
|
||||
|
||||
it('should be defined', () => {
|
||||
expect(graphhopperGeorouter).toBeDefined();
|
||||
});
|
||||
|
||||
describe('route function', () => {
|
||||
it('should fail on axios error', async () => {
|
||||
await expect(
|
||||
graphhopperGeorouter.route(
|
||||
[
|
||||
{
|
||||
key: 'route1',
|
||||
points: [
|
||||
{
|
||||
lat: 49.440041,
|
||||
lon: 1.093912,
|
||||
},
|
||||
{
|
||||
lat: 50.630992,
|
||||
lon: 3.045432,
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
{
|
||||
withDistance: false,
|
||||
withPoints: false,
|
||||
withTime: false,
|
||||
},
|
||||
),
|
||||
).rejects.toBeInstanceOf(Error);
|
||||
});
|
||||
it('should create one route with all settings to false', async () => {
|
||||
const routes = await graphhopperGeorouter.route(
|
||||
[
|
||||
{
|
||||
key: 'route1',
|
||||
points: [
|
||||
{
|
||||
lat: 49.440041,
|
||||
lon: 1.093912,
|
||||
},
|
||||
{
|
||||
lat: 50.630992,
|
||||
lon: 3.045432,
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
{
|
||||
withDistance: false,
|
||||
withPoints: false,
|
||||
withTime: false,
|
||||
},
|
||||
);
|
||||
expect(routes).toHaveLength(1);
|
||||
});
|
||||
it('should create 2 routes with distance, points and time', async () => {
|
||||
const routes = await graphhopperGeorouter.route(
|
||||
[
|
||||
{
|
||||
key: 'route1',
|
||||
points: [
|
||||
{
|
||||
lat: 49.440041,
|
||||
lon: 1.093912,
|
||||
},
|
||||
{
|
||||
lat: 50.630992,
|
||||
lon: 3.045432,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
key: 'route2',
|
||||
points: [
|
||||
{
|
||||
lat: 49.440041,
|
||||
lon: 1.093912,
|
||||
},
|
||||
{
|
||||
lat: 50.630992,
|
||||
lon: 3.045432,
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
{
|
||||
withDistance: true,
|
||||
withPoints: true,
|
||||
withTime: true,
|
||||
},
|
||||
);
|
||||
expect(routes).toHaveLength(2);
|
||||
});
|
||||
});
|
||||
});
|
|
@ -1,9 +1,9 @@
|
|||
import { MatchRequest } from '../../domain/dtos/match.request';
|
||||
import { Role } from '../../domain/types/role.enum';
|
||||
import { TimingFrequency } from '../../domain/types/timing';
|
||||
import { IDefaultParams } from '../../domain/types/default-params.type';
|
||||
import { MatchQuery } from '../../queries/match.query';
|
||||
import { Algorithm } from '../../domain/types/algorithm.enum';
|
||||
import { MatchRequest } from '../../../domain/dtos/match.request';
|
||||
import { Role } from '../../../domain/types/role.enum';
|
||||
import { TimingFrequency } from '../../../domain/types/timing';
|
||||
import { IDefaultParams } from '../../../domain/types/default-params.type';
|
||||
import { MatchQuery } from '../../../queries/match.query';
|
||||
import { Algorithm } from '../../../domain/types/algorithm.enum';
|
||||
|
||||
const defaultParams: IDefaultParams = {
|
||||
DEFAULT_IDENTIFIER: 0,
|
Loading…
Reference in New Issue