Merge pull request 'Permafix-optimization-refiner' (#9) from Permafix-optimization-refiner into main

Reviewed-on: remoll/fast-network-navigation#9
This commit is contained in:
Helldragon67 2024-07-17 10:32:32 +00:00
commit f590ebb5ed
18 changed files with 1151 additions and 10950 deletions

28
.vscode/launch.json vendored
View File

@ -1,28 +0,0 @@
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"name": "frontend",
"cwd": "frontend",
"request": "launch",
"type": "dart"
},
{
"name": "frontend (profile mode)",
"cwd": "frontend",
"request": "launch",
"type": "dart",
"flutterMode": "profile"
},
{
"name": "frontend (release mode)",
"cwd": "frontend",
"request": "launch",
"type": "dart",
"flutterMode": "release"
},
]
}

1
backend/.gitignore vendored
View File

@ -1,5 +1,6 @@
# osm-cache # osm-cache
cache/ cache/
apicache/
# Byte-compiled / optimized / DLL files # Byte-compiled / optimized / DLL files
__pycache__/ __pycache__/
*.py[cod] *.py[cod]

View File

@ -10,5 +10,11 @@ fastapi = "*"
osmpythontools = "*" osmpythontools = "*"
pydantic = "*" pydantic = "*"
shapely = "*" shapely = "*"
networkx = "*"
geopy = "*"
requests = ">=2.20.1"
mwparserfromhell = ">=0.5.2"
packaging = "*"
pywikibot = "*"
[dev-packages] [dev-packages]

860
backend/Pipfile.lock generated
View File

@ -1,7 +1,7 @@
{ {
"_meta": { "_meta": {
"hash": { "hash": {
"sha256": "0f88c01cde3be9a6332acec33fa0ccf13b6e122a6df8ee5cfefa52ba1e98034f" "sha256": "b089081defe09c4ffad85fd22c5de336c76b31e7f6f67e5969b731bdaa58e528"
}, },
"pipfile-spec": 6, "pipfile-spec": 6,
"requires": {}, "requires": {},
@ -40,11 +40,107 @@
}, },
"certifi": { "certifi": {
"hashes": [ "hashes": [
"sha256:3cd43f1c6fa7dedc5899d69d3ad0398fd018ad1a17fba83ddaf78aa46c747516", "sha256:5a1e7645bc0ec61a09e26c36f6106dd4cf40c6db3a1fb6352b0244e7fb057c7b",
"sha256:ddc6c8ce995e6987e7faf5e3f1b02b302836a0e5d98ece18392cb1a36c72ad56" "sha256:c198e21b1289c2ab85ee4e67bb4b4ef3ead0892059901a8d5b622f24a1101e90"
], ],
"markers": "python_version >= '3.6'", "markers": "python_version >= '3.6'",
"version": "==2024.6.2" "version": "==2024.7.4"
},
"charset-normalizer": {
"hashes": [
"sha256:06435b539f889b1f6f4ac1758871aae42dc3a8c0e24ac9e60c2384973ad73027",
"sha256:06a81e93cd441c56a9b65d8e1d043daeb97a3d0856d177d5c90ba85acb3db087",
"sha256:0a55554a2fa0d408816b3b5cedf0045f4b8e1a6065aec45849de2d6f3f8e9786",
"sha256:0b2b64d2bb6d3fb9112bafa732def486049e63de9618b5843bcdd081d8144cd8",
"sha256:10955842570876604d404661fbccbc9c7e684caf432c09c715ec38fbae45ae09",
"sha256:122c7fa62b130ed55f8f285bfd56d5f4b4a5b503609d181f9ad85e55c89f4185",
"sha256:1ceae2f17a9c33cb48e3263960dc5fc8005351ee19db217e9b1bb15d28c02574",
"sha256:1d3193f4a680c64b4b6a9115943538edb896edc190f0b222e73761716519268e",
"sha256:1f79682fbe303db92bc2b1136016a38a42e835d932bab5b3b1bfcfbf0640e519",
"sha256:2127566c664442652f024c837091890cb1942c30937add288223dc895793f898",
"sha256:22afcb9f253dac0696b5a4be4a1c0f8762f8239e21b99680099abd9b2b1b2269",
"sha256:25baf083bf6f6b341f4121c2f3c548875ee6f5339300e08be3f2b2ba1721cdd3",
"sha256:2e81c7b9c8979ce92ed306c249d46894776a909505d8f5a4ba55b14206e3222f",
"sha256:3287761bc4ee9e33561a7e058c72ac0938c4f57fe49a09eae428fd88aafe7bb6",
"sha256:34d1c8da1e78d2e001f363791c98a272bb734000fcef47a491c1e3b0505657a8",
"sha256:37e55c8e51c236f95b033f6fb391d7d7970ba5fe7ff453dad675e88cf303377a",
"sha256:3d47fa203a7bd9c5b6cee4736ee84ca03b8ef23193c0d1ca99b5089f72645c73",
"sha256:3e4d1f6587322d2788836a99c69062fbb091331ec940e02d12d179c1d53e25fc",
"sha256:42cb296636fcc8b0644486d15c12376cb9fa75443e00fb25de0b8602e64c1714",
"sha256:45485e01ff4d3630ec0d9617310448a8702f70e9c01906b0d0118bdf9d124cf2",
"sha256:4a78b2b446bd7c934f5dcedc588903fb2f5eec172f3d29e52a9096a43722adfc",
"sha256:4ab2fe47fae9e0f9dee8c04187ce5d09f48eabe611be8259444906793ab7cbce",
"sha256:4d0d1650369165a14e14e1e47b372cfcb31d6ab44e6e33cb2d4e57265290044d",
"sha256:549a3a73da901d5bc3ce8d24e0600d1fa85524c10287f6004fbab87672bf3e1e",
"sha256:55086ee1064215781fff39a1af09518bc9255b50d6333f2e4c74ca09fac6a8f6",
"sha256:572c3763a264ba47b3cf708a44ce965d98555f618ca42c926a9c1616d8f34269",
"sha256:573f6eac48f4769d667c4442081b1794f52919e7edada77495aaed9236d13a96",
"sha256:5b4c145409bef602a690e7cfad0a15a55c13320ff7a3ad7ca59c13bb8ba4d45d",
"sha256:6463effa3186ea09411d50efc7d85360b38d5f09b870c48e4600f63af490e56a",
"sha256:65f6f63034100ead094b8744b3b97965785388f308a64cf8d7c34f2f2e5be0c4",
"sha256:663946639d296df6a2bb2aa51b60a2454ca1cb29835324c640dafb5ff2131a77",
"sha256:6897af51655e3691ff853668779c7bad41579facacf5fd7253b0133308cf000d",
"sha256:68d1f8a9e9e37c1223b656399be5d6b448dea850bed7d0f87a8311f1ff3dabb0",
"sha256:6ac7ffc7ad6d040517be39eb591cac5ff87416c2537df6ba3cba3bae290c0fed",
"sha256:6b3251890fff30ee142c44144871185dbe13b11bab478a88887a639655be1068",
"sha256:6c4caeef8fa63d06bd437cd4bdcf3ffefe6738fb1b25951440d80dc7df8c03ac",
"sha256:6ef1d82a3af9d3eecdba2321dc1b3c238245d890843e040e41e470ffa64c3e25",
"sha256:753f10e867343b4511128c6ed8c82f7bec3bd026875576dfd88483c5c73b2fd8",
"sha256:7cd13a2e3ddeed6913a65e66e94b51d80a041145a026c27e6bb76c31a853c6ab",
"sha256:7ed9e526742851e8d5cc9e6cf41427dfc6068d4f5a3bb03659444b4cabf6bc26",
"sha256:7f04c839ed0b6b98b1a7501a002144b76c18fb1c1850c8b98d458ac269e26ed2",
"sha256:802fe99cca7457642125a8a88a084cef28ff0cf9407060f7b93dca5aa25480db",
"sha256:80402cd6ee291dcb72644d6eac93785fe2c8b9cb30893c1af5b8fdd753b9d40f",
"sha256:8465322196c8b4d7ab6d1e049e4c5cb460d0394da4a27d23cc242fbf0034b6b5",
"sha256:86216b5cee4b06df986d214f664305142d9c76df9b6512be2738aa72a2048f99",
"sha256:87d1351268731db79e0f8e745d92493ee2841c974128ef629dc518b937d9194c",
"sha256:8bdb58ff7ba23002a4c5808d608e4e6c687175724f54a5dade5fa8c67b604e4d",
"sha256:8c622a5fe39a48f78944a87d4fb8a53ee07344641b0562c540d840748571b811",
"sha256:8d756e44e94489e49571086ef83b2bb8ce311e730092d2c34ca8f7d925cb20aa",
"sha256:8f4a014bc36d3c57402e2977dada34f9c12300af536839dc38c0beab8878f38a",
"sha256:9063e24fdb1e498ab71cb7419e24622516c4a04476b17a2dab57e8baa30d6e03",
"sha256:90d558489962fd4918143277a773316e56c72da56ec7aa3dc3dbbe20fdfed15b",
"sha256:923c0c831b7cfcb071580d3f46c4baf50f174be571576556269530f4bbd79d04",
"sha256:95f2a5796329323b8f0512e09dbb7a1860c46a39da62ecb2324f116fa8fdc85c",
"sha256:96b02a3dc4381e5494fad39be677abcb5e6634bf7b4fa83a6dd3112607547001",
"sha256:9f96df6923e21816da7e0ad3fd47dd8f94b2a5ce594e00677c0013018b813458",
"sha256:a10af20b82360ab00827f916a6058451b723b4e65030c5a18577c8b2de5b3389",
"sha256:a50aebfa173e157099939b17f18600f72f84eed3049e743b68ad15bd69b6bf99",
"sha256:a981a536974bbc7a512cf44ed14938cf01030a99e9b3a06dd59578882f06f985",
"sha256:a9a8e9031d613fd2009c182b69c7b2c1ef8239a0efb1df3f7c8da66d5dd3d537",
"sha256:ae5f4161f18c61806f411a13b0310bea87f987c7d2ecdbdaad0e94eb2e404238",
"sha256:aed38f6e4fb3f5d6bf81bfa990a07806be9d83cf7bacef998ab1a9bd660a581f",
"sha256:b01b88d45a6fcb69667cd6d2f7a9aeb4bf53760d7fc536bf679ec94fe9f3ff3d",
"sha256:b261ccdec7821281dade748d088bb6e9b69e6d15b30652b74cbbac25e280b796",
"sha256:b2b0a0c0517616b6869869f8c581d4eb2dd83a4d79e0ebcb7d373ef9956aeb0a",
"sha256:b4a23f61ce87adf89be746c8a8974fe1c823c891d8f86eb218bb957c924bb143",
"sha256:bd8f7df7d12c2db9fab40bdd87a7c09b1530128315d047a086fa3ae3435cb3a8",
"sha256:beb58fe5cdb101e3a055192ac291b7a21e3b7ef4f67fa1d74e331a7f2124341c",
"sha256:c002b4ffc0be611f0d9da932eb0f704fe2602a9a949d1f738e4c34c75b0863d5",
"sha256:c083af607d2515612056a31f0a8d9e0fcb5876b7bfc0abad3ecd275bc4ebc2d5",
"sha256:c180f51afb394e165eafe4ac2936a14bee3eb10debc9d9e4db8958fe36afe711",
"sha256:c235ebd9baae02f1b77bcea61bce332cb4331dc3617d254df3323aa01ab47bd4",
"sha256:cd70574b12bb8a4d2aaa0094515df2463cb429d8536cfb6c7ce983246983e5a6",
"sha256:d0eccceffcb53201b5bfebb52600a5fb483a20b61da9dbc885f8b103cbe7598c",
"sha256:d965bba47ddeec8cd560687584e88cf699fd28f192ceb452d1d7ee807c5597b7",
"sha256:db364eca23f876da6f9e16c9da0df51aa4f104a972735574842618b8c6d999d4",
"sha256:ddbb2551d7e0102e7252db79ba445cdab71b26640817ab1e3e3648dad515003b",
"sha256:deb6be0ac38ece9ba87dea880e438f25ca3eddfac8b002a2ec3d9183a454e8ae",
"sha256:e06ed3eb3218bc64786f7db41917d4e686cc4856944f53d5bdf83a6884432e12",
"sha256:e27ad930a842b4c5eb8ac0016b0a54f5aebbe679340c26101df33424142c143c",
"sha256:e537484df0d8f426ce2afb2d0f8e1c3d0b114b83f8850e5f2fbea0e797bd82ae",
"sha256:eb00ed941194665c332bf8e078baf037d6c35d7c4f3102ea2d4f16ca94a26dc8",
"sha256:eb6904c354526e758fda7167b33005998fb68c46fbc10e013ca97f21ca5c8887",
"sha256:eb8821e09e916165e160797a6c17edda0679379a4be5c716c260e836e122f54b",
"sha256:efcb3f6676480691518c177e3b465bcddf57cea040302f9f4e6e191af91174d4",
"sha256:f27273b60488abe721a075bcca6d7f3964f9f6f067c8c4c605743023d7d3944f",
"sha256:f30c3cb33b24454a82faecaf01b19c18562b1e89558fb6c56de4d9118a032fd5",
"sha256:fb69256e180cb6c8a894fee62b3afebae785babc1ee98b81cdf68bbca1987f33",
"sha256:fd1abc0d89e30cc4e02e4064dc67fcc51bd941eb395c502aac3ec19fab46b519",
"sha256:ff8fa367d09b717b2a17a052544193ad76cd49979c805768879cb63d9ca50561"
],
"markers": "python_full_version >= '3.7.0'",
"version": "==3.3.2"
}, },
"click": { "click": {
"hashes": [ "hashes": [
@ -130,20 +226,20 @@
}, },
"exceptiongroup": { "exceptiongroup": {
"hashes": [ "hashes": [
"sha256:5258b9ed329c5bbdd31a309f53cbfb0b155341807f6ff7606a1e801a891b29ad", "sha256:3111b9d131c238bec2f8f516e123e14ba243563fb135d3fe885990585aa7795b",
"sha256:a4785e48b045528f5bfe627b6ad554ff32def154f42372786903b7abcfe1aa16" "sha256:47c2edf7c6738fafb49fd34290706d1a1a2f4d1c6df275526b62cbb4aa5393cc"
], ],
"markers": "python_version < '3.11'", "markers": "python_version < '3.11'",
"version": "==1.2.1" "version": "==1.2.2"
}, },
"fastapi": { "fastapi": {
"hashes": [ "hashes": [
"sha256:97ecbf994be0bcbdadedf88c3150252bed7b2087075ac99735403b1b76cc8fc0", "sha256:4f51cfa25d72f9fbc3280832e84b32494cf186f50158d364a8765aabf22587bf",
"sha256:b9db9dd147c91cb8b769f7183535773d8741dd46f9dc6676cd82eab510228cd7" "sha256:ddd1ac34cb1f76c2e2d7f8545a4bcb5463bce4834e81abf0b189e0c359ab2413"
], ],
"index": "pypi", "index": "pypi",
"markers": "python_version >= '3.8'", "markers": "python_version >= '3.8'",
"version": "==0.111.0" "version": "==0.111.1"
}, },
"fastapi-cli": { "fastapi-cli": {
"hashes": [ "hashes": [
@ -155,51 +251,59 @@
}, },
"fonttools": { "fonttools": {
"hashes": [ "hashes": [
"sha256:099634631b9dd271d4a835d2b2a9e042ccc94ecdf7e2dd9f7f34f7daf333358d", "sha256:02569e9a810f9d11f4ae82c391ebc6fb5730d95a0657d24d754ed7763fb2d122",
"sha256:0c555e039d268445172b909b1b6bdcba42ada1cf4a60e367d68702e3f87e5f64", "sha256:0679a30b59d74b6242909945429dbddb08496935b82f91ea9bf6ad240ec23397",
"sha256:1e677bfb2b4bd0e5e99e0f7283e65e47a9814b0486cb64a41adf9ef110e078f2", "sha256:10f5e6c3510b79ea27bb1ebfcc67048cde9ec67afa87c7dd7efa5c700491ac7f",
"sha256:2367d47816cc9783a28645bc1dac07f8ffc93e0f015e8c9fc674a5b76a6da6e4", "sha256:2af40ae9cdcb204fc1d8f26b190aa16534fcd4f0df756268df674a270eab575d",
"sha256:28d072169fe8275fb1a0d35e3233f6df36a7e8474e56cb790a7258ad822b6fd6", "sha256:32f029c095ad66c425b0ee85553d0dc326d45d7059dbc227330fc29b43e8ba60",
"sha256:31f0e3147375002aae30696dd1dc596636abbd22fca09d2e730ecde0baad1d6b", "sha256:35250099b0cfb32d799fb5d6c651220a642fe2e3c7d2560490e6f1d3f9ae9169",
"sha256:3e0ad3c6ea4bd6a289d958a1eb922767233f00982cf0fe42b177657c86c80a8f", "sha256:3b3c8ebafbee8d9002bd8f1195d09ed2bd9ff134ddec37ee8f6a6375e6a4f0e8",
"sha256:45b4afb069039f0366a43a5d454bc54eea942bfb66b3fc3e9a2c07ef4d617380", "sha256:4824c198f714ab5559c5be10fd1adf876712aa7989882a4ec887bf1ef3e00e31",
"sha256:4a2a6ba400d386e904fd05db81f73bee0008af37799a7586deaa4aef8cd5971e", "sha256:5ff7e5e9bad94e3a70c5cd2fa27f20b9bb9385e10cddab567b85ce5d306ea923",
"sha256:4f520d9ac5b938e6494f58a25c77564beca7d0199ecf726e1bd3d56872c59749", "sha256:651390c3b26b0c7d1f4407cad281ee7a5a85a31a110cbac5269de72a51551ba2",
"sha256:52a6e0a7a0bf611c19bc8ec8f7592bdae79c8296c70eb05917fd831354699b20", "sha256:6e08f572625a1ee682115223eabebc4c6a2035a6917eac6f60350aba297ccadb",
"sha256:5a4788036201c908079e89ae3f5399b33bf45b9ea4514913f4dbbe4fac08efe0", "sha256:6ed170b5e17da0264b9f6fae86073be3db15fa1bd74061c8331022bca6d09bab",
"sha256:6b4f04b1fbc01a3569d63359f2227c89ab294550de277fd09d8fca6185669fa4", "sha256:73379d3ffdeecb376640cd8ed03e9d2d0e568c9d1a4e9b16504a834ebadc2dfb",
"sha256:715b41c3e231f7334cbe79dfc698213dcb7211520ec7a3bc2ba20c8515e8a3b5", "sha256:75a157d8d26c06e64ace9df037ee93a4938a4606a38cb7ffaf6635e60e253b7a",
"sha256:73121a9b7ff93ada888aaee3985a88495489cc027894458cb1a736660bdfb206", "sha256:791b31ebbc05197d7aa096bbc7bd76d591f05905d2fd908bf103af4488e60670",
"sha256:74ae2441731a05b44d5988d3ac2cf784d3ee0a535dbed257cbfff4be8bb49eb9", "sha256:7b6b35e52ddc8fb0db562133894e6ef5b4e54e1283dff606fda3eed938c36fc8",
"sha256:7d6166192dcd925c78a91d599b48960e0a46fe565391c79fe6de481ac44d20ac", "sha256:84ec3fb43befb54be490147b4a922b5314e16372a643004f182babee9f9c3407",
"sha256:7f193f060391a455920d61684a70017ef5284ccbe6023bb056e15e5ac3de11d1", "sha256:8959a59de5af6d2bec27489e98ef25a397cfa1774b375d5787509c06659b3671",
"sha256:907fa0b662dd8fc1d7c661b90782ce81afb510fc4b7aa6ae7304d6c094b27bce", "sha256:9dfdae43b7996af46ff9da520998a32b105c7f098aeea06b2226b30e74fbba88",
"sha256:93156dd7f90ae0a1b0e8871032a07ef3178f553f0c70c386025a808f3a63b1f4", "sha256:9e6ceba2a01b448e36754983d376064730690401da1dd104ddb543519470a15f",
"sha256:93bc9e5aaa06ff928d751dc6be889ff3e7d2aa393ab873bc7f6396a99f6fbb12", "sha256:9efd176f874cb6402e607e4cc9b4a9cd584d82fc34a4b0c811970b32ba62501f",
"sha256:95db0c6581a54b47c30860d013977b8a14febc206c8b5ff562f9fe32738a8aca", "sha256:a1c7c5aa18dd3b17995898b4a9b5929d69ef6ae2af5b96d585ff4005033d82f0",
"sha256:973d030180eca8255b1bce6ffc09ef38a05dcec0e8320cc9b7bcaa65346f341d", "sha256:aae7bd54187e8bf7fd69f8ab87b2885253d3575163ad4d669a262fe97f0136cb",
"sha256:9cd7a6beec6495d1dffb1033d50a3f82dfece23e9eb3c20cd3c2444d27514068", "sha256:b21952c092ffd827504de7e66b62aba26fdb5f9d1e435c52477e6486e9d128b2",
"sha256:9fe9096a60113e1d755e9e6bda15ef7e03391ee0554d22829aa506cdf946f796", "sha256:b96cd370a61f4d083c9c0053bf634279b094308d52fdc2dd9a22d8372fdd590d",
"sha256:a209d2e624ba492df4f3bfad5996d1f76f03069c6133c60cd04f9a9e715595ec", "sha256:becc5d7cb89c7b7afa8321b6bb3dbee0eec2b57855c90b3e9bf5fb816671fa7c",
"sha256:a239afa1126b6a619130909c8404070e2b473dd2b7fc4aacacd2e763f8597fea", "sha256:bee32ea8765e859670c4447b0817514ca79054463b6b79784b08a8df3a4d78e3",
"sha256:ba9f09ff17f947392a855e3455a846f9855f6cf6bec33e9a427d3c1d254c712f", "sha256:c6e7170d675d12eac12ad1a981d90f118c06cf680b42a2d74c6c931e54b50719",
"sha256:bb7273789f69b565d88e97e9e1da602b4ee7ba733caf35a6c2affd4334d4f005", "sha256:c818c058404eb2bba05e728d38049438afd649e3c409796723dfc17cd3f08749",
"sha256:bd5bc124fae781a4422f61b98d1d7faa47985f663a64770b78f13d2c072410c2", "sha256:c8696544c964500aa9439efb6761947393b70b17ef4e82d73277413f291260a4",
"sha256:bff98816cb144fb7b85e4b5ba3888a33b56ecef075b0e95b95bcd0a5fbf20f06", "sha256:c9cd19cf4fe0595ebdd1d4915882b9440c3a6d30b008f3cc7587c1da7b95be5f",
"sha256:c4ee5a24e281fbd8261c6ab29faa7fd9a87a12e8c0eed485b705236c65999109", "sha256:d4d0096cb1ac7a77b3b41cd78c9b6bc4a400550e21dc7a92f2b5ab53ed74eb02",
"sha256:c93ed66d32de1559b6fc348838c7572d5c0ac1e4a258e76763a5caddd8944002", "sha256:d92d3c2a1b39631a6131c2fa25b5406855f97969b068e7e08413325bc0afba58",
"sha256:d1a24f51a3305362b94681120c508758a88f207fa0a681c16b5a4172e9e6c7a9", "sha256:da33440b1413bad53a8674393c5d29ce64d8c1a15ef8a77c642ffd900d07bfe1",
"sha256:d8f191a17369bd53a5557a5ee4bab91d5330ca3aefcdf17fab9a497b0e7cff7a", "sha256:e013aae589c1c12505da64a7d8d023e584987e51e62006e1bb30d72f26522c41",
"sha256:daaef7390e632283051e3cf3e16aff2b68b247e99aea916f64e578c0449c9c68", "sha256:e128778a8e9bc11159ce5447f76766cefbd876f44bd79aff030287254e4752c4",
"sha256:e40013572bfb843d6794a3ce076c29ef4efd15937ab833f520117f8eccc84fd6", "sha256:e54f1bba2f655924c1138bbc7fa91abd61f45c68bd65ab5ed985942712864bbb",
"sha256:eceef49f457253000e6a2d0f7bd08ff4e9fe96ec4ffce2dbcb32e34d9c1b8161", "sha256:e5b708073ea3d684235648786f5f6153a48dc8762cdfe5563c57e80787c29fbb",
"sha256:ee595d7ba9bba130b2bec555a40aafa60c26ce68ed0cf509983e0f12d88674fd", "sha256:e8bf06b94694251861ba7fdeea15c8ec0967f84c3d4143ae9daf42bbc7717fe3",
"sha256:ef50ec31649fbc3acf6afd261ed89d09eb909b97cc289d80476166df8438524d", "sha256:f08df60fbd8d289152079a65da4e66a447efc1d5d5a4d3f299cdd39e3b2e4a7d",
"sha256:fa1f3e34373aa16045484b4d9d352d4c6b5f9f77ac77a178252ccbc851e8b2ee", "sha256:f1f8758a2ad110bd6432203a344269f445a2907dc24ef6bccfd0ac4e14e0d71d",
"sha256:fca66d9ff2ac89b03f5aa17e0b21a97c21f3491c46b583bb131eb32c7bab33af" "sha256:f677ce218976496a587ab17140da141557beb91d2a5c1a14212c994093f2eae2"
], ],
"markers": "python_version >= '3.8'", "markers": "python_version >= '3.8'",
"version": "==4.53.0" "version": "==4.53.1"
},
"geographiclib": {
"hashes": [
"sha256:6b7225248e45ff7edcee32becc4e0a1504c606ac5ee163a5656d482e0cd38734",
"sha256:f7f41c85dc3e1c2d3d935ec86660dc3b2c848c83e17f9a9e51ba9d5146a15859"
],
"markers": "python_version >= '3.7'",
"version": "==2.0"
}, },
"geojson": { "geojson": {
"hashes": [ "hashes": [
@ -209,6 +313,15 @@
"markers": "python_version >= '3.7'", "markers": "python_version >= '3.7'",
"version": "==3.1.0" "version": "==3.1.0"
}, },
"geopy": {
"hashes": [
"sha256:50283d8e7ad07d89be5cb027338c6365a32044df3ae2556ad3f52f4840b3d0d1",
"sha256:ae8b4bc5c1131820f4d75fce9d4aaaca0c85189b3aa5d64c3dcaf5e3b7b882a7"
],
"index": "pypi",
"markers": "python_version >= '3.7'",
"version": "==2.4.1"
},
"h11": { "h11": {
"hashes": [ "hashes": [
"sha256:8f19fbbe99e72420ff35c00b27a34cb9937e902a8b810e2c88300c6f0a3b699d", "sha256:8f19fbbe99e72420ff35c00b27a34cb9937e902a8b810e2c88300c6f0a3b699d",
@ -624,38 +737,38 @@
}, },
"matplotlib": { "matplotlib": {
"hashes": [ "hashes": [
"sha256:063af8587fceeac13b0936c42a2b6c732c2ab1c98d38abc3337e430e1ff75e38", "sha256:0000354e32efcfd86bda75729716b92f5c2edd5b947200be9881f0a671565c33",
"sha256:06a478f0d67636554fa78558cfbcd7b9dba85b51f5c3b5a0c9be49010cf5f321", "sha256:0c584210c755ae921283d21d01f03a49ef46d1afa184134dd0f95b0202ee6f03",
"sha256:0a490715b3b9984fa609116481b22178348c1a220a4499cda79132000a79b4db", "sha256:0e835c6988edc3d2d08794f73c323cc62483e13df0194719ecb0723b564e0b5c",
"sha256:0fc51eaa5262553868461c083d9adadb11a6017315f3a757fc45ec6ec5f02888", "sha256:0fc001516ffcf1a221beb51198b194d9230199d6842c540108e4ce109ac05cc0",
"sha256:13beb4840317d45ffd4183a778685e215939be7b08616f431c7795276e067463", "sha256:11fed08f34fa682c2b792942f8902e7aefeed400da71f9e5816bea40a7ce28fe",
"sha256:290d304e59be2b33ef5c2d768d0237f5bd132986bdcc66f80bc9bcc300066a03", "sha256:208cbce658b72bf6a8e675058fbbf59f67814057ae78165d8a2f87c45b48d0ff",
"sha256:2bcee1dffaf60fe7656183ac2190bd630842ff87b3153afb3e384d966b57fe56", "sha256:2315837485ca6188a4b632c5199900e28d33b481eb083663f6a44cfc8987ded3",
"sha256:2e7f03e5cbbfacdd48c8ea394d365d91ee8f3cae7e6ec611409927b5ed997ee4", "sha256:26040c8f5121cd1ad712abffcd4b5222a8aec3a0fe40bc8542c94331deb8780d",
"sha256:3f988bafb0fa39d1074ddd5bacd958c853e11def40800c5824556eb630f94d3b", "sha256:3fda72d4d472e2ccd1be0e9ccb6bf0d2eaf635e7f8f51d737ed7e465ac020cb3",
"sha256:52146fc3bd7813cc784562cb93a15788be0b2875c4655e2cc6ea646bfa30344b", "sha256:421851f4f57350bcf0811edd754a708d2275533e84f52f6760b740766c6747a7",
"sha256:550cdda3adbd596078cca7d13ed50b77879104e2e46392dcd7c75259d8f00e85", "sha256:44a21d922f78ce40435cb35b43dd7d573cf2a30138d5c4b709d19f00e3907fd7",
"sha256:616fabf4981a3b3c5a15cd95eba359c8489c4e20e03717aea42866d8d0465956", "sha256:4db17fea0ae3aceb8e9ac69c7e3051bae0b3d083bfec932240f9bf5d0197a049",
"sha256:76cce0f31b351e3551d1f3779420cf8f6ec0d4a8cf9c0237a3b549fd28eb4abb", "sha256:565d572efea2b94f264dd86ef27919515aa6d629252a169b42ce5f570db7f37b",
"sha256:7ff2e239c26be4f24bfa45860c20ffccd118d270c5b5d081fa4ea409b5469fcd", "sha256:591d3a88903a30a6d23b040c1e44d1afdd0d778758d07110eb7596f811f31842",
"sha256:8146ce83cbc5dc71c223a74a1996d446cd35cfb6a04b683e1446b7e6c73603b7", "sha256:6d397fd8ccc64af2ec0af1f0efc3bacd745ebfb9d507f3f552e8adb689ed730a",
"sha256:81c40af649d19c85f8073e25e5806926986806fa6d54be506fbf02aef47d5a89", "sha256:7ccd6270066feb9a9d8e0705aa027f1ff39f354c72a87efe8fa07632f30fc6bb",
"sha256:9a2fa6d899e17ddca6d6526cf6e7ba677738bf2a6a9590d702c277204a7c6152", "sha256:82cd5acf8f3ef43f7532c2f230249720f5dc5dd40ecafaf1c60ac8200d46d7eb",
"sha256:a5be985db2596d761cdf0c2eaf52396f26e6a64ab46bd8cd810c48972349d1be", "sha256:83c6a792f1465d174c86d06f3ae85a8fe36e6f5964633ae8106312ec0921fdf5",
"sha256:af4001b7cae70f7eaacfb063db605280058246de590fa7874f00f62259f2df7e", "sha256:84b3ba8429935a444f1fdc80ed930babbe06725bcf09fbeb5c8757a2cd74af04",
"sha256:bd4f2831168afac55b881db82a7730992aa41c4f007f1913465fb182d6fb20c0", "sha256:a0c977c5c382f6696caf0bd277ef4f936da7e2aa202ff66cad5f0ac1428ee15b",
"sha256:bdd1ecbe268eb3e7653e04f451635f0fb0f77f07fd070242b44c076c9106da84", "sha256:a973c53ad0668c53e0ed76b27d2eeeae8799836fd0d0caaa4ecc66bf4e6676c0",
"sha256:c53aeb514ccbbcbab55a27f912d79ea30ab21ee0531ee2c09f13800efb272674", "sha256:ab38a4f3772523179b2f772103d8030215b318fef6360cb40558f585bf3d017f",
"sha256:c79f3a585f1368da6049318bdf1f85568d8d04b2e89fc24b7e02cc9b62017382", "sha256:b3fce58971b465e01b5c538f9d44915640c20ec5ff31346e963c9e1cd66fa812",
"sha256:cd53c79fd02f1c1808d2cfc87dd3cf4dbc63c5244a58ee7944497107469c8d8a", "sha256:b918770bf3e07845408716e5bbda17eadfc3fcbd9307dc67f37d6cf834bb3d98",
"sha256:d38e85a1a6d732f645f1403ce5e6727fd9418cd4574521d5803d3d94911038e5", "sha256:d12cb1837cffaac087ad6b44399d5e22b78c729de3cdae4629e252067b705e2b",
"sha256:d91a4ffc587bacf5c4ce4ecfe4bcd23a4b675e76315f2866e588686cc97fccdf", "sha256:dc23f48ab630474264276be156d0d7710ac6c5a09648ccdf49fef9200d8cbe80",
"sha256:e6d29ea6c19e34b30fb7d88b7081f869a03014f66fe06d62cc77d5a6ea88ed7a", "sha256:dd2a59ff4b83d33bca3b5ec58203cc65985367812cb8c257f3e101632be86d92",
"sha256:eaf3978060a106fab40c328778b148f590e27f6fa3cd15a19d6892575bce387d", "sha256:de06b19b8db95dd33d0dc17c926c7c9ebed9f572074b6fac4f65068a6814d010",
"sha256:fe428e191ea016bb278758c8ee82a8129c51d81d8c4bc0846c09e7e8e9057241" "sha256:f1f2e5d29e9435c97ad4c36fb6668e89aee13d48c75893e25cef064675038ac9"
], ],
"markers": "python_version >= '3.9'", "markers": "python_version >= '3.9'",
"version": "==3.9.0" "version": "==3.9.1"
}, },
"mdurl": { "mdurl": {
"hashes": [ "hashes": [
@ -665,6 +778,48 @@
"markers": "python_version >= '3.7'", "markers": "python_version >= '3.7'",
"version": "==0.1.2" "version": "==0.1.2"
}, },
"mwparserfromhell": {
"hashes": [
"sha256:007d0859e5467241b73c6e974df039a074609ce4e2b9df8c2263a8920554d032",
"sha256:03e03b8bec729af850457d045b04d0c9d3e296ff8bf66b455f754cccb29c3bea",
"sha256:063c1e79befd1f55d77c358e0f5006f5ecf88ddf218ff6af55188d686139330e",
"sha256:1915fe4f5e5ae34f16242d4cd98da2adc81a810ab94105ec2af3dc95d7ce74aa",
"sha256:1960bcc5115ea57427df130150edf1dbfc2fb03465e548e630bb6eb37976d793",
"sha256:19e9a4bcd85707c83172405eb2a9a046eff9d38dd7f1a56a5e5ecbbfef4a640a",
"sha256:1d2422659abb29191a0fa096cf8bead837ac3ecd343065569b2acc7a84ecf866",
"sha256:2b75fae6d01c8fda19dbf127175122d7aa2964ef6454690e6868bbc3d80a7bc1",
"sha256:50c482e703d2d51401f7e36a71ae9493901f170225940196292f97398713dde5",
"sha256:54e2dd30edc1a358408d14343b30dcca0b4613227781e4bbee968bd4395d94ff",
"sha256:59633d3cc09993af75ced8dfbd6800e1e38e64620851a095575621548448875c",
"sha256:6a89edf53f15877223d923e122e9a97f3f7b85f56dc56d91a3d77b89c9dd4126",
"sha256:6b11dea3bcdebe4554933169eade815e9d6b898175faa5a20a744524fd99210f",
"sha256:71afec1e9784ba576e95d6f34845582d3c733a3a52ba770dd8a9c3a40e5b649f",
"sha256:746bad799179684994ecee72a26352e0bbe2b697f6a7e35dc5ad151606bcb8ab",
"sha256:910d36bc70e8bea758380e75c12fd47626b295abec9f73a6099d8f937a649e77",
"sha256:9136696d6b29838adcf8f428e3f7028b2c6e788fc05fe1beeb4b135429c356df",
"sha256:a58251a5d5c77abdfd061624dc05667c2774e93e8178a2fbd1a3b45f8673f1a9",
"sha256:cdc46c115b2495d4025920b7b30a6885a96d2b797ccc4009bf3cc02940ae55d3",
"sha256:d2febd92a55a3f19b461833267726cb81429c3d6cb0006ad1691dfa849789e5d",
"sha256:d6995b9cfe6ec79556db0232a39210ac11aa69ee304cfc95b29c51be381e202b",
"sha256:dbe5976b1b524e26aa2eb71b6219960f2578f56b536c68e0a79deb63e3b7f710",
"sha256:e28ffa9a7e0748ec64002a84234201ef69c2d4a710508baf9cc25f4ee274c6bd",
"sha256:ebc70f8a24aa60e54728be740f1c12a4acb1b12d1cc947d87b067cc1c83339fd",
"sha256:fd05481adc0806f4b8f8f8cb309ec56924b17ce386cb1c2f73919d8a012e6b16",
"sha256:fff66e97f7c02aa0fd57ff8f702977a9c5a1d72ef55b64ee9b146291e4c41057"
],
"index": "pypi",
"markers": "python_version >= '3.8'",
"version": "==0.6.6"
},
"networkx": {
"hashes": [
"sha256:0c127d8b2f4865f59ae9cb8aafcd60b5c70f3241ebd66f7defad7c4ab90126c9",
"sha256:28575580c6ebdaf4505b22c6256a2b9de86b316dc63ba9e93abde3d78dfdbcf2"
],
"index": "pypi",
"markers": "python_version >= '3.10'",
"version": "==3.3"
},
"numpy": { "numpy": {
"hashes": [ "hashes": [
"sha256:04494f6ec467ccb5369d1808570ae55f6ed9b5809d7f035059000a37b8d7e86f", "sha256:04494f6ec467ccb5369d1808570ae55f6ed9b5809d7f035059000a37b8d7e86f",
@ -717,58 +872,6 @@
"markers": "python_version >= '3.9'", "markers": "python_version >= '3.9'",
"version": "==2.0.0" "version": "==2.0.0"
}, },
"orjson": {
"hashes": [
"sha256:03b565c3b93f5d6e001db48b747d31ea3819b89abf041ee10ac6988886d18e01",
"sha256:099e81a5975237fda3100f918839af95f42f981447ba8f47adb7b6a3cdb078fa",
"sha256:10c0eb7e0c75e1e486c7563fe231b40fdd658a035ae125c6ba651ca3b07936f5",
"sha256:1146bf85ea37ac421594107195db8bc77104f74bc83e8ee21a2e58596bfb2f04",
"sha256:1670fe88b116c2745a3a30b0f099b699a02bb3482c2591514baf5433819e4f4d",
"sha256:185c394ef45b18b9a7d8e8f333606e2e8194a50c6e3c664215aae8cf42c5385e",
"sha256:1ad1de7fef79736dde8c3554e75361ec351158a906d747bd901a52a5c9c8d24b",
"sha256:235dadefb793ad12f7fa11e98a480db1f7c6469ff9e3da5e73c7809c700d746b",
"sha256:28afa96f496474ce60d3340fe8d9a263aa93ea01201cd2bad844c45cd21f5268",
"sha256:2d97531cdfe9bdd76d492e69800afd97e5930cb0da6a825646667b2c6c6c0211",
"sha256:338fd4f071b242f26e9ca802f443edc588fa4ab60bfa81f38beaedf42eda226c",
"sha256:36a10f43c5f3a55c2f680efe07aa93ef4a342d2960dd2b1b7ea2dd764fe4a37c",
"sha256:3d21b9983da032505f7050795e98b5d9eee0df903258951566ecc358f6696969",
"sha256:51bbcdea96cdefa4a9b4461e690c75ad4e33796530d182bdd5c38980202c134a",
"sha256:53ed1c879b10de56f35daf06dbc4a0d9a5db98f6ee853c2dbd3ee9d13e6f302f",
"sha256:545d493c1f560d5ccfc134803ceb8955a14c3fcb47bbb4b2fee0232646d0b932",
"sha256:584c902ec19ab7928fd5add1783c909094cc53f31ac7acfada817b0847975f26",
"sha256:5a35455cc0b0b3a1eaf67224035f5388591ec72b9b6136d66b49a553ce9eb1e6",
"sha256:5df58d206e78c40da118a8c14fc189207fffdcb1f21b3b4c9c0c18e839b5a214",
"sha256:64c9cc089f127e5875901ac05e5c25aa13cfa5dbbbd9602bda51e5c611d6e3e2",
"sha256:68f85ecae7af14a585a563ac741b0547a3f291de81cd1e20903e79f25170458f",
"sha256:6970ed7a3126cfed873c5d21ece1cd5d6f83ca6c9afb71bbae21a0b034588d96",
"sha256:6b68742c469745d0e6ca5724506858f75e2f1e5b59a4315861f9e2b1df77775a",
"sha256:7a5baef8a4284405d96c90c7c62b755e9ef1ada84c2406c24a9ebec86b89f46d",
"sha256:7d10cc1b594951522e35a3463da19e899abe6ca95f3c84c69e9e901e0bd93d38",
"sha256:85c89131d7b3218db1b24c4abecea92fd6c7f9fab87441cfc342d3acc725d807",
"sha256:8a11d459338f96a9aa7f232ba95679fc0c7cedbd1b990d736467894210205c09",
"sha256:8c13ca5e2ddded0ce6a927ea5a9f27cae77eee4c75547b4297252cb20c4d30e6",
"sha256:9cd684927af3e11b6e754df80b9ffafd9fb6adcaa9d3e8fdd5891be5a5cad51e",
"sha256:b2efbd67feff8c1f7728937c0d7f6ca8c25ec81373dc8db4ef394c1d93d13dc5",
"sha256:b39e006b00c57125ab974362e740c14a0c6a66ff695bff44615dcf4a70ce2b86",
"sha256:b6c8e30adfa52c025f042a87f450a6b9ea29649d828e0fec4858ed5e6caecf63",
"sha256:be79e2393679eda6a590638abda16d167754393f5d0850dcbca2d0c3735cebe2",
"sha256:c05f16701ab2a4ca146d0bca950af254cb7c02f3c01fca8efbbad82d23b3d9d4",
"sha256:c4057c3b511bb8aef605616bd3f1f002a697c7e4da6adf095ca5b84c0fd43595",
"sha256:c4a65310ccb5c9910c47b078ba78e2787cb3878cdded1702ac3d0da71ddc5228",
"sha256:ca0b3a94ac8d3886c9581b9f9de3ce858263865fdaa383fbc31c310b9eac07c9",
"sha256:cc28e90a7cae7fcba2493953cff61da5a52950e78dc2dacfe931a317ee3d8de7",
"sha256:cdf7365063e80899ae3a697def1277c17a7df7ccfc979990a403dfe77bb54d40",
"sha256:d69858c32f09c3e1ce44b617b3ebba1aba030e777000ebdf72b0d8e365d0b2b3",
"sha256:dbead71dbe65f959b7bd8cf91e0e11d5338033eba34c114f69078d59827ee139",
"sha256:dcbe82b35d1ac43b0d84072408330fd3295c2896973112d495e7234f7e3da2e1",
"sha256:dfc91d4720d48e2a709e9c368d5125b4b5899dced34b5400c3837dadc7d6271b",
"sha256:eded5138cc565a9d618e111c6d5c2547bbdd951114eb822f7f6309e04db0fb47",
"sha256:f4324929c2dd917598212bfd554757feca3e5e0fa60da08be11b4aa8b90013c1",
"sha256:fb66215277a230c456f9038d5e2d84778141643207f85336ef8d2a9da26bd7ca"
],
"markers": "python_version >= '3.8'",
"version": "==3.10.5"
},
"osmpythontools": { "osmpythontools": {
"hashes": [ "hashes": [
"sha256:13ff721f760fdad5dd78b4d1461d286b78bba96ee151a7301ee8c11a0c258be9" "sha256:13ff721f760fdad5dd78b4d1461d286b78bba96ee151a7301ee8c11a0c258be9"
@ -781,6 +884,7 @@
"sha256:026ed72c8ed3fcce5bf8950572258698927fd1dbda10a5e981cdf0ac37f4f002", "sha256:026ed72c8ed3fcce5bf8950572258698927fd1dbda10a5e981cdf0ac37f4f002",
"sha256:5b8f2217dbdbd2f7f384c41c628544e6d52f2d0f53c6d0c3ea61aa5d1d7ff124" "sha256:5b8f2217dbdbd2f7f384c41c628544e6d52f2d0f53c6d0c3ea61aa5d1d7ff124"
], ],
"index": "pypi",
"markers": "python_version >= '3.8'", "markers": "python_version >= '3.8'",
"version": "==24.1" "version": "==24.1"
}, },
@ -821,172 +925,193 @@
}, },
"pillow": { "pillow": {
"hashes": [ "hashes": [
"sha256:048ad577748b9fa4a99a0548c64f2cb8d672d5bf2e643a739ac8faff1164238c", "sha256:02a2be69f9c9b8c1e97cf2713e789d4e398c751ecfd9967c18d0ce304efbf885",
"sha256:048eeade4c33fdf7e08da40ef402e748df113fd0b4584e32c4af74fe78baaeb2", "sha256:030abdbe43ee02e0de642aee345efa443740aa4d828bfe8e2eb11922ea6a21ea",
"sha256:0ba26351b137ca4e0db0342d5d00d2e355eb29372c05afd544ebf47c0956ffeb", "sha256:06b2f7898047ae93fad74467ec3d28fe84f7831370e3c258afa533f81ef7f3df",
"sha256:0ea2a783a2bdf2a561808fe4a7a12e9aa3799b701ba305de596bc48b8bdfce9d", "sha256:0755ffd4a0c6f267cccbae2e9903d95477ca2f77c4fcf3a3a09570001856c8a5",
"sha256:1530e8f3a4b965eb6a7785cf17a426c779333eb62c9a7d1bbcf3ffd5bf77a4aa", "sha256:0a9ec697746f268507404647e531e92889890a087e03681a3606d9b920fbee3c",
"sha256:16563993329b79513f59142a6b02055e10514c1a8e86dca8b48a893e33cf91e3", "sha256:0ae24a547e8b711ccaaf99c9ae3cd975470e1a30caa80a6aaee9a2f19c05701d",
"sha256:19aeb96d43902f0a783946a0a87dbdad5c84c936025b8419da0a0cd7724356b1", "sha256:134ace6dc392116566980ee7436477d844520a26a4b1bd4053f6f47d096997fd",
"sha256:1a1d1915db1a4fdb2754b9de292642a39a7fb28f1736699527bb649484fb966a", "sha256:166c1cd4d24309b30d61f79f4a9114b7b2313d7450912277855ff5dfd7cd4a06",
"sha256:1b87bd9d81d179bd8ab871603bd80d8645729939f90b71e62914e816a76fc6bd", "sha256:1b5dea9831a90e9d0721ec417a80d4cbd7022093ac38a568db2dd78363b00908",
"sha256:1dfc94946bc60ea375cc39cff0b8da6c7e5f8fcdc1d946beb8da5c216156ddd8", "sha256:1d846aea995ad352d4bdcc847535bd56e0fd88d36829d2c90be880ef1ee4668a",
"sha256:2034f6759a722da3a3dbd91a81148cf884e91d1b747992ca288ab88c1de15999", "sha256:1ef61f5dd14c300786318482456481463b9d6b91ebe5ef12f405afbba77ed0be",
"sha256:261ddb7ca91fcf71757979534fb4c128448b5b4c55cb6152d280312062f69599", "sha256:297e388da6e248c98bc4a02e018966af0c5f92dfacf5a5ca22fa01cb3179bca0",
"sha256:2ed854e716a89b1afcedea551cd85f2eb2a807613752ab997b9974aaa0d56936", "sha256:298478fe4f77a4408895605f3482b6cc6222c018b2ce565c2b6b9c354ac3229b",
"sha256:3102045a10945173d38336f6e71a8dc71bcaeed55c3123ad4af82c52807b9375", "sha256:29dbdc4207642ea6aad70fbde1a9338753d33fb23ed6956e706936706f52dd80",
"sha256:339894035d0ede518b16073bdc2feef4c991ee991a29774b33e515f1d308e08d", "sha256:2db98790afc70118bd0255c2eeb465e9767ecf1f3c25f9a1abb8ffc8cfd1fe0a",
"sha256:412444afb8c4c7a6cc11a47dade32982439925537e483be7c0ae0cf96c4f6a0b", "sha256:32cda9e3d601a52baccb2856b8ea1fc213c90b340c542dcef77140dfa3278a9e",
"sha256:4203efca580f0dd6f882ca211f923168548f7ba334c189e9eab1178ab840bf60", "sha256:37fb69d905be665f68f28a8bba3c6d3223c8efe1edf14cc4cfa06c241f8c81d9",
"sha256:45ebc7b45406febf07fef35d856f0293a92e7417ae7933207e90bf9090b70572", "sha256:416d3a5d0e8cfe4f27f574362435bc9bae57f679a7158e0096ad2beb427b8696",
"sha256:4b5ec25d8b17217d635f8935dbc1b9aa5907962fae29dff220f2659487891cd3", "sha256:43efea75eb06b95d1631cb784aa40156177bf9dd5b4b03ff38979e048258bc6b",
"sha256:4c8e73e99da7db1b4cad7f8d682cf6abad7844da39834c288fbfa394a47bbced", "sha256:4b35b21b819ac1dbd1233317adeecd63495f6babf21b7b2512d244ff6c6ce309",
"sha256:4e6f7d1c414191c1199f8996d3f2282b9ebea0945693fb67392c75a3a320941f", "sha256:4d9667937cfa347525b319ae34375c37b9ee6b525440f3ef48542fcf66f2731e",
"sha256:4eaa22f0d22b1a7e93ff0a596d57fdede2e550aecffb5a1ef1106aaece48e96b", "sha256:5161eef006d335e46895297f642341111945e2c1c899eb406882a6c61a4357ab",
"sha256:50b8eae8f7334ec826d6eeffaeeb00e36b5e24aa0b9df322c247539714c6df19", "sha256:543f3dc61c18dafb755773efc89aae60d06b6596a63914107f75459cf984164d",
"sha256:50fd3f6b26e3441ae07b7c979309638b72abc1a25da31a81a7fbd9495713ef4f", "sha256:551d3fd6e9dc15e4c1eb6fc4ba2b39c0c7933fa113b220057a34f4bb3268a060",
"sha256:51243f1ed5161b9945011a7360e997729776f6e5d7005ba0c6879267d4c5139d", "sha256:59291fb29317122398786c2d44427bbd1a6d7ff54017075b22be9d21aa59bd8d",
"sha256:5d512aafa1d32efa014fa041d38868fda85028e3f930a96f85d49c7d8ddc0383", "sha256:5b001114dd152cfd6b23befeb28d7aee43553e2402c9f159807bf55f33af8a8d",
"sha256:5f77cf66e96ae734717d341c145c5949c63180842a545c47a0ce7ae52ca83795", "sha256:5b4815f2e65b30f5fbae9dfffa8636d992d49705723fe86a3661806e069352d4",
"sha256:6b02471b72526ab8a18c39cb7967b72d194ec53c1fd0a70b050565a0f366d355", "sha256:5dc6761a6efc781e6a1544206f22c80c3af4c8cf461206d46a1e6006e4429ff3",
"sha256:6fb1b30043271ec92dc65f6d9f0b7a830c210b8a96423074b15c7bc999975f57", "sha256:5e84b6cc6a4a3d76c153a6b19270b3526a5a8ed6b09501d3af891daa2a9de7d6",
"sha256:7161ec49ef0800947dc5570f86568a7bb36fa97dd09e9827dc02b718c5643f09", "sha256:6209bb41dc692ddfee4942517c19ee81b86c864b626dbfca272ec0f7cff5d9fb",
"sha256:72d622d262e463dfb7595202d229f5f3ab4b852289a1cd09650362db23b9eb0b", "sha256:673655af3eadf4df6b5457033f086e90299fdd7a47983a13827acf7459c15d94",
"sha256:74d28c17412d9caa1066f7a31df8403ec23d5268ba46cd0ad2c50fb82ae40462", "sha256:6c762a5b0997f5659a5ef2266abc1d8851ad7749ad9a6a5506eb23d314e4f46b",
"sha256:78618cdbccaa74d3f88d0ad6cb8ac3007f1a6fa5c6f19af64b55ca170bfa1edf", "sha256:7086cc1d5eebb91ad24ded9f58bec6c688e9f0ed7eb3dbbf1e4800280a896496",
"sha256:793b4e24db2e8742ca6423d3fde8396db336698c55cd34b660663ee9e45ed37f", "sha256:73664fe514b34c8f02452ffb73b7a92c6774e39a647087f83d67f010eb9a0cf0",
"sha256:798232c92e7665fe82ac085f9d8e8ca98826f8e27859d9a96b41d519ecd2e49a", "sha256:76a911dfe51a36041f2e756b00f96ed84677cdeb75d25c767f296c1c1eda1319",
"sha256:81d09caa7b27ef4e61cb7d8fbf1714f5aec1c6b6c5270ee53504981e6e9121ad", "sha256:780c072c2e11c9b2c7ca37f9a2ee8ba66f44367ac3e5c7832afcfe5104fd6d1b",
"sha256:8ab74c06ffdab957d7670c2a5a6e1a70181cd10b727cd788c4dd9005b6a8acd9", "sha256:7928ecbf1ece13956b95d9cbcfc77137652b02763ba384d9ab508099a2eca856",
"sha256:8eb0908e954d093b02a543dc963984d6e99ad2b5e36503d8a0aaf040505f747d", "sha256:7970285ab628a3779aecc35823296a7869f889b8329c16ad5a71e4901a3dc4ef",
"sha256:90b9e29824800e90c84e4022dd5cc16eb2d9605ee13f05d47641eb183cd73d45", "sha256:7a8d4bade9952ea9a77d0c3e49cbd8b2890a399422258a77f357b9cc9be8d680",
"sha256:9797a6c8fe16f25749b371c02e2ade0efb51155e767a971c61734b1bf6293994", "sha256:7c1ee6f42250df403c5f103cbd2768a28fe1a0ea1f0f03fe151c8741e1469c8b",
"sha256:9d2455fbf44c914840c793e89aa82d0e1763a14253a000743719ae5946814b2d", "sha256:7dfecdbad5c301d7b5bde160150b4db4c659cee2b69589705b6f8a0c509d9f42",
"sha256:9d3bea1c75f8c53ee4d505c3e67d8c158ad4df0d83170605b50b64025917f338", "sha256:812f7342b0eee081eaec84d91423d1b4650bb9828eb53d8511bcef8ce5aecf1e",
"sha256:9e2ec1e921fd07c7cda7962bad283acc2f2a9ccc1b971ee4b216b75fad6f0463", "sha256:866b6942a92f56300012f5fbac71f2d610312ee65e22f1aa2609e491284e5597",
"sha256:9e91179a242bbc99be65e139e30690e081fe6cb91a8e77faf4c409653de39451", "sha256:86dcb5a1eb778d8b25659d5e4341269e8590ad6b4e8b44d9f4b07f8d136c414a",
"sha256:a0eaa93d054751ee9964afa21c06247779b90440ca41d184aeb5d410f20ff591", "sha256:87dd88ded2e6d74d31e1e0a99a726a6765cda32d00ba72dc37f0651f306daaa8",
"sha256:a2c405445c79c3f5a124573a051062300936b0281fee57637e706453e452746c", "sha256:8bc1a764ed8c957a2e9cacf97c8b2b053b70307cf2996aafd70e91a082e70df3",
"sha256:aa7e402ce11f0885305bfb6afb3434b3cd8f53b563ac065452d9d5654c7b86fd", "sha256:8d4d5063501b6dd4024b8ac2f04962d661222d120381272deea52e3fc52d3736",
"sha256:aff76a55a8aa8364d25400a210a65ff59d0168e0b4285ba6bf2bd83cf675ba32", "sha256:8f0aef4ef59694b12cadee839e2ba6afeab89c0f39a3adc02ed51d109117b8da",
"sha256:b09b86b27a064c9624d0a6c54da01c1beaf5b6cadfa609cf63789b1d08a797b9", "sha256:930044bb7679ab003b14023138b50181899da3f25de50e9dbee23b61b4de2126",
"sha256:b14f16f94cbc61215115b9b1236f9c18403c15dd3c52cf629072afa9d54c1cbf", "sha256:950be4d8ba92aca4b2bb0741285a46bfae3ca699ef913ec8416c1b78eadd64cd",
"sha256:b50811d664d392f02f7761621303eba9d1b056fb1868c8cdf4231279645c25f5", "sha256:961a7293b2457b405967af9c77dcaa43cc1a8cd50d23c532e62d48ab6cdd56f5",
"sha256:b7bc2176354defba3edc2b9a777744462da2f8e921fbaf61e52acb95bafa9828", "sha256:9b885f89040bb8c4a1573566bbb2f44f5c505ef6e74cec7ab9068c900047f04b",
"sha256:c78e1b00a87ce43bb37642c0812315b411e856a905d58d597750eb79802aaaa3", "sha256:9f4727572e2918acaa9077c919cbbeb73bd2b3ebcfe033b72f858fc9fbef0026",
"sha256:c83341b89884e2b2e55886e8fbbf37c3fa5efd6c8907124aeb72f285ae5696e5", "sha256:a02364621fe369e06200d4a16558e056fe2805d3468350df3aef21e00d26214b",
"sha256:ca2870d5d10d8726a27396d3ca4cf7976cec0f3cb706debe88e3a5bd4610f7d2", "sha256:a985e028fc183bf12a77a8bbf36318db4238a3ded7fa9df1b9a133f1cb79f8fc",
"sha256:ccce24b7ad89adb5a1e34a6ba96ac2530046763912806ad4c247356a8f33a67b", "sha256:ac1452d2fbe4978c2eec89fb5a23b8387aba707ac72810d9490118817d9c0b46",
"sha256:cd5e14fbf22a87321b24c88669aad3a51ec052eb145315b3da3b7e3cc105b9a2", "sha256:b15e02e9bb4c21e39876698abf233c8c579127986f8207200bc8a8f6bb27acf2",
"sha256:ce49c67f4ea0609933d01c0731b34b8695a7a748d6c8d186f95e7d085d2fe475", "sha256:b2724fdb354a868ddf9a880cb84d102da914e99119211ef7ecbdc613b8c96b3c",
"sha256:d33891be6df59d93df4d846640f0e46f1a807339f09e79a8040bc887bdcd7ed3", "sha256:bbc527b519bd3aa9d7f429d152fea69f9ad37c95f0b02aebddff592688998abe",
"sha256:d3b2348a78bc939b4fed6552abfd2e7988e0f81443ef3911a4b8498ca084f6eb", "sha256:bcd5e41a859bf2e84fdc42f4edb7d9aba0a13d29a2abadccafad99de3feff984",
"sha256:d886f5d353333b4771d21267c7ecc75b710f1a73d72d03ca06df49b09015a9ef", "sha256:bd2880a07482090a3bcb01f4265f1936a903d70bc740bfcb1fd4e8a2ffe5cf5a",
"sha256:d93480005693d247f8346bc8ee28c72a2191bdf1f6b5db469c096c0c867ac015", "sha256:bee197b30783295d2eb680b311af15a20a8b24024a19c3a26431ff83eb8d1f70",
"sha256:dc1a390a82755a8c26c9964d457d4c9cbec5405896cba94cf51f36ea0d855002", "sha256:bf2342ac639c4cf38799a44950bbc2dfcb685f052b9e262f446482afaf4bffca",
"sha256:dd78700f5788ae180b5ee8902c6aea5a5726bac7c364b202b4b3e3ba2d293170", "sha256:c76e5786951e72ed3686e122d14c5d7012f16c8303a674d18cdcd6d89557fc5b",
"sha256:e46f38133e5a060d46bd630faa4d9fa0202377495df1f068a8299fd78c84de84", "sha256:cbed61494057c0f83b83eb3a310f0bf774b09513307c434d4366ed64f4128a91",
"sha256:e4b878386c4bf293578b48fc570b84ecfe477d3b77ba39a6e87150af77f40c57", "sha256:cfdd747216947628af7b259d274771d84db2268ca062dd5faf373639d00113a3",
"sha256:f0d0591a0aeaefdaf9a5e545e7485f89910c977087e7de2b6c388aec32011e9f", "sha256:d7480af14364494365e89d6fddc510a13e5a2c3584cb19ef65415ca57252fb84",
"sha256:fdcbb4068117dfd9ce0138d068ac512843c52295ed996ae6dd1faf537b6dbc27", "sha256:dbc6ae66518ab3c5847659e9988c3b60dc94ffb48ef9168656e0019a93dbf8a1",
"sha256:ff61bfd9253c3915e6d41c651d5f962da23eda633cf02262990094a18a55371a" "sha256:dc3e2db6ba09ffd7d02ae9141cfa0ae23393ee7687248d46a7507b75d610f4f5",
"sha256:dfe91cb65544a1321e631e696759491ae04a2ea11d36715eca01ce07284738be",
"sha256:e4d49b85c4348ea0b31ea63bc75a9f3857869174e2bf17e7aba02945cd218e6f",
"sha256:e4db64794ccdf6cb83a59d73405f63adbe2a1887012e308828596100a0b2f6cc",
"sha256:e553cad5179a66ba15bb18b353a19020e73a7921296a7979c4a2b7f6a5cd57f9",
"sha256:e88d5e6ad0d026fba7bdab8c3f225a69f063f116462c49892b0149e21b6c0a0e",
"sha256:ecd85a8d3e79cd7158dec1c9e5808e821feea088e2f69a974db5edf84dc53141",
"sha256:f5b92f4d70791b4a67157321c4e8225d60b119c5cc9aee8ecf153aace4aad4ef",
"sha256:f5f0c3e969c8f12dd2bb7e0b15d5c468b51e5017e01e2e867335c81903046a22",
"sha256:f7baece4ce06bade126fb84b8af1c33439a76d8a6fd818970215e0560ca28c27",
"sha256:ff25afb18123cea58a591ea0244b92eb1e61a1fd497bf6d6384f09bc3262ec3e",
"sha256:ff337c552345e95702c5fde3158acb0625111017d0e5f24bf3acdb9cc16b90d1"
], ],
"markers": "python_version >= '3.8'", "markers": "python_version >= '3.8'",
"version": "==10.3.0" "version": "==10.4.0"
}, },
"pydantic": { "pydantic": {
"hashes": [ "hashes": [
"sha256:0c84efd9548d545f63ac0060c1e4d39bb9b14db8b3c0652338aecc07b5adec52", "sha256:6f62c13d067b0755ad1c21a34bdd06c0c12625a22b0fc09c6b149816604f7c2a",
"sha256:ee8538d41ccb9c0a9ad3e0e5f07bf15ed8015b481ced539a1759d8cc89ae90d0" "sha256:73ee9fddd406dc318b885c7a2eab8a6472b68b8fb5ba8150949fc3db939f23c8"
], ],
"index": "pypi", "index": "pypi",
"markers": "python_version >= '3.8'", "markers": "python_version >= '3.8'",
"version": "==2.7.4" "version": "==2.8.2"
}, },
"pydantic-core": { "pydantic-core": {
"hashes": [ "hashes": [
"sha256:01dd777215e2aa86dfd664daed5957704b769e726626393438f9c87690ce78c3", "sha256:035ede2e16da7281041f0e626459bcae33ed998cca6a0a007a5ebb73414ac72d",
"sha256:0eb2a4f660fcd8e2b1c90ad566db2b98d7f3f4717c64fe0a83e0adb39766d5b8", "sha256:04024d270cf63f586ad41fff13fde4311c4fc13ea74676962c876d9577bcc78f",
"sha256:0fbbdc827fe5e42e4d196c746b890b3d72876bdbf160b0eafe9f0334525119c8", "sha256:0827505a5c87e8aa285dc31e9ec7f4a17c81a813d45f70b1d9164e03a813a686",
"sha256:123c3cec203e3f5ac7b000bd82235f1a3eced8665b63d18be751f115588fea30", "sha256:084659fac3c83fd674596612aeff6041a18402f1e1bc19ca39e417d554468482",
"sha256:14601cdb733d741b8958224030e2bfe21a4a881fb3dd6fbb21f071cabd48fa0a", "sha256:10d4204d8ca33146e761c79f83cc861df20e7ae9f6487ca290a97702daf56006",
"sha256:18f469a3d2a2fdafe99296a87e8a4c37748b5080a26b806a707f25a902c040a8", "sha256:11b71d67b4725e7e2a9f6e9c0ac1239bbc0c48cce3dc59f98635efc57d6dac83",
"sha256:19894b95aacfa98e7cb093cd7881a0c76f55731efad31073db4521e2b6ff5b7d", "sha256:150906b40ff188a3260cbee25380e7494ee85048584998c1e66df0c7a11c17a6",
"sha256:1b4de2e51bbcb61fdebd0ab86ef28062704f62c82bbf4addc4e37fa4b00b7cbc", "sha256:175873691124f3d0da55aeea1d90660a6ea7a3cfea137c38afa0a5ffabe37b88",
"sha256:1d886dc848e60cb7666f771e406acae54ab279b9f1e4143babc9c2258213daa2", "sha256:177f55a886d74f1808763976ac4efd29b7ed15c69f4d838bbd74d9d09cf6fa86",
"sha256:1f4d26ceb5eb9eed4af91bebeae4b06c3fb28966ca3a8fb765208cf6b51102ab", "sha256:19c0fa39fa154e7e0b7f82f88ef85faa2a4c23cc65aae2f5aea625e3c13c735a",
"sha256:21a5e440dbe315ab9825fcd459b8814bb92b27c974cbc23c3e8baa2b76890077", "sha256:1eedfeb6089ed3fad42e81a67755846ad4dcc14d73698c120a82e4ccf0f1f9f6",
"sha256:293afe532740370aba8c060882f7d26cfd00c94cae32fd2e212a3a6e3b7bc15e", "sha256:225b67a1f6d602de0ce7f6c1c3ae89a4aa25d3de9be857999e9124f15dab486a",
"sha256:2f5966897e5461f818e136b8451d0551a2e77259eb0f73a837027b47dc95dab9", "sha256:242b8feb3c493ab78be289c034a1f659e8826e2233786e36f2893a950a719bb6",
"sha256:2fd41f6eff4c20778d717af1cc50eca52f5afe7805ee530a4fbd0bae284f16e9", "sha256:254ec27fdb5b1ee60684f91683be95e5133c994cc54e86a0b0963afa25c8f8a6",
"sha256:2fdf2156aa3d017fddf8aea5adfba9f777db1d6022d392b682d2a8329e087cef", "sha256:25e9185e2d06c16ee438ed39bf62935ec436474a6ac4f9358524220f1b236e43",
"sha256:3c40d4eaad41f78e3bbda31b89edc46a3f3dc6e171bf0ecf097ff7a0ffff7cb1", "sha256:26ab812fa0c845df815e506be30337e2df27e88399b985d0bb4e3ecfe72df31c",
"sha256:43d447dd2ae072a0065389092a231283f62d960030ecd27565672bd40746c507", "sha256:26ca695eeee5f9f1aeeb211ffc12f10bcb6f71e2989988fda61dabd65db878d4",
"sha256:44a688331d4a4e2129140a8118479443bd6f1905231138971372fcde37e43528", "sha256:26dc97754b57d2fd00ac2b24dfa341abffc380b823211994c4efac7f13b9e90e",
"sha256:44c7486a4228413c317952e9d89598bcdfb06399735e49e0f8df643e1ccd0558", "sha256:270755f15174fb983890c49881e93f8f1b80f0b5e3a3cc1394a255706cabd203",
"sha256:44cd83ab6a51da80fb5adbd9560e26018e2ac7826f9626bc06ca3dc074cd198b", "sha256:2aafc5a503855ea5885559eae883978c9b6d8c8993d67766ee73d82e841300dd",
"sha256:46387e38bd641b3ee5ce247563b60c5ca098da9c56c75c157a05eaa0933ed154", "sha256:2d036c7187b9422ae5b262badb87a20a49eb6c5238b2004e96d4da1231badef1",
"sha256:4701b19f7e3a06ea655513f7938de6f108123bf7c86bbebb1196eb9bd35cf724", "sha256:33499e85e739a4b60c9dac710c20a08dc73cb3240c9a0e22325e671b27b70d24",
"sha256:4748321b5078216070b151d5271ef3e7cc905ab170bbfd27d5c83ee3ec436695", "sha256:37eee5b638f0e0dcd18d21f59b679686bbd18917b87db0193ae36f9c23c355fc",
"sha256:4b06beb3b3f1479d32befd1f3079cc47b34fa2da62457cdf6c963393340b56e9", "sha256:38cf1c40a921d05c5edc61a785c0ddb4bed67827069f535d794ce6bcded919fc",
"sha256:4d0dcc59664fcb8974b356fe0a18a672d6d7cf9f54746c05f43275fc48636851", "sha256:3acae97ffd19bf091c72df4d726d552c473f3576409b2a7ca36b2f535ffff4a3",
"sha256:4e99bc050fe65c450344421017f98298a97cefc18c53bb2f7b3531eb39bc7805", "sha256:3c5ebac750d9d5f2706654c638c041635c385596caf68f81342011ddfa1e5598",
"sha256:509daade3b8649f80d4e5ff21aa5673e4ebe58590b25fe42fac5f0f52c6f034a", "sha256:3d482efec8b7dc6bfaedc0f166b2ce349df0011f5d2f1f25537ced4cfc34fd98",
"sha256:51991a89639a912c17bef4b45c87bd83593aee0437d8102556af4885811d59f5", "sha256:407653af5617f0757261ae249d3fba09504d7a71ab36ac057c938572d1bc9331",
"sha256:53db086f9f6ab2b4061958d9c276d1dbe3690e8dd727d6abf2321d6cce37fa94", "sha256:40a783fb7ee353c50bd3853e626f15677ea527ae556429453685ae32280c19c2",
"sha256:564d7922e4b13a16b98772441879fcdcbe82ff50daa622d681dd682175ea918c", "sha256:41e81317dd6a0127cabce83c0c9c3fbecceae981c8391e6f1dec88a77c8a569a",
"sha256:574d92eac874f7f4db0ca653514d823a0d22e2354359d0759e3f6a406db5d55d", "sha256:41f4c96227a67a013e7de5ff8f20fb496ce573893b7f4f2707d065907bffdbd6",
"sha256:578e24f761f3b425834f297b9935e1ce2e30f51400964ce4801002435a1b41ef", "sha256:469f29f9093c9d834432034d33f5fe45699e664f12a13bf38c04967ce233d688",
"sha256:59ff3e89f4eaf14050c8022011862df275b552caef8082e37b542b066ce1ff26", "sha256:4745f4ac52cc6686390c40eaa01d48b18997cb130833154801a442323cc78f91",
"sha256:5f09baa656c904807e832cf9cce799c6460c450c4ad80803517032da0cd062e2", "sha256:4868f6bd7c9d98904b748a2653031fc9c2f85b6237009d475b1008bfaeb0a5aa",
"sha256:6891a2ae0e8692679c07728819b6e2b822fb30ca7445f67bbf6509b25a96332c", "sha256:4aa223cd1e36b642092c326d694d8bf59b71ddddc94cdb752bbbb1c5c91d833b",
"sha256:6a750aec7bf431517a9fd78cb93c97b9b0c496090fee84a47a0d23668976b4b0", "sha256:4dd484681c15e6b9a977c785a345d3e378d72678fd5f1f3c0509608da24f2ac0",
"sha256:6f5c4d41b2771c730ea1c34e458e781b18cc668d194958e0112455fff4e402b2", "sha256:4f2790949cf385d985a31984907fecb3896999329103df4e4983a4a41e13e840",
"sha256:77450e6d20016ec41f43ca4a6c63e9fdde03f0ae3fe90e7c27bdbeaece8b1ed4", "sha256:512ecfbefef6dac7bc5eaaf46177b2de58cdf7acac8793fe033b24ece0b9566c",
"sha256:81b5efb2f126454586d0f40c4d834010979cb80785173d1586df845a632e4e6d", "sha256:516d9227919612425c8ef1c9b869bbbee249bc91912c8aaffb66116c0b447ebd",
"sha256:823be1deb01793da05ecb0484d6c9e20baebb39bd42b5d72636ae9cf8350dbd2", "sha256:53e431da3fc53360db73eedf6f7124d1076e1b4ee4276b36fb25514544ceb4a3",
"sha256:834b5230b5dfc0c1ec37b2fda433b271cbbc0e507560b5d1588e2cc1148cf1ce", "sha256:595ba5be69b35777474fa07f80fc260ea71255656191adb22a8c53aba4479231",
"sha256:847a35c4d58721c5dc3dba599878ebbdfd96784f3fb8bb2c356e123bdcd73f34", "sha256:5b5ff4911aea936a47d9376fd3ab17e970cc543d1b68921886e7f64bd28308d1",
"sha256:86110d7e1907ab36691f80b33eb2da87d780f4739ae773e5fc83fb272f88825f", "sha256:5d41e6daee2813ecceea8eda38062d69e280b39df793f5a942fa515b8ed67953",
"sha256:8951eee36c57cd128f779e641e21eb40bc5073eb28b2d23f33eb0ef14ffb3f5d", "sha256:5e999ba8dd90e93d57410c5e67ebb67ffcaadcea0ad973240fdfd3a135506250",
"sha256:8a7164fe2005d03c64fd3b85649891cd4953a8de53107940bf272500ba8a788b", "sha256:5f239eb799a2081495ea659d8d4a43a8f42cd1fe9ff2e7e436295c38a10c286a",
"sha256:8b8bab4c97248095ae0c4455b5a1cd1cdd96e4e4769306ab19dda135ea4cdb07", "sha256:635fee4e041ab9c479e31edda27fcf966ea9614fff1317e280d99eb3e5ab6fe2",
"sha256:90afc12421df2b1b4dcc975f814e21bc1754640d502a2fbcc6d41e77af5ec312", "sha256:65db0f2eefcaad1a3950f498aabb4875c8890438bc80b19362cf633b87a8ab20",
"sha256:938cb21650855054dc54dfd9120a851c974f95450f00683399006aa6e8abb057", "sha256:6b507132dcfc0dea440cce23ee2182c0ce7aba7054576efc65634f080dbe9434",
"sha256:942ba11e7dfb66dc70f9ae66b33452f51ac7bb90676da39a7345e99ffb55402d", "sha256:6b9d9bb600328a1ce523ab4f454859e9d439150abb0906c5a1983c146580ebab",
"sha256:972658f4a72d02b8abfa2581d92d59f59897d2e9f7e708fdabe922f9087773af", "sha256:70c8daf4faca8da5a6d655f9af86faf6ec2e1768f4b8b9d0226c02f3d6209703",
"sha256:97736815b9cc893b2b7f663628e63f436018b75f44854c8027040e05230eeddb", "sha256:77bf3ac639c1ff567ae3b47f8d4cc3dc20f9966a2a6dd2311dcc055d3d04fb8a",
"sha256:98906207f29bc2c459ff64fa007afd10a8c8ac080f7e4d5beff4c97086a3dabd", "sha256:784c1214cb6dd1e3b15dd8b91b9a53852aed16671cc3fbe4786f4f1db07089e2",
"sha256:99457f184ad90235cfe8461c4d70ab7dd2680e28821c29eca00252ba90308c78", "sha256:7eb6a0587eded33aeefea9f916899d42b1799b7b14b8f8ff2753c0ac1741edac",
"sha256:a0d829524aaefdebccb869eed855e2d04c21d2d7479b6cada7ace5448416597b", "sha256:7ed1b0132f24beeec5a78b67d9388656d03e6a7c837394f99257e2d55b461611",
"sha256:a2fdd81edd64342c85ac7cf2753ccae0b79bf2dfa063785503cb85a7d3593223", "sha256:8ad4aeb3e9a97286573c03df758fc7627aecdd02f1da04516a86dc159bf70121",
"sha256:a55b5b16c839df1070bc113c1f7f94a0af4433fcfa1b41799ce7606e5c79ce0a", "sha256:964faa8a861d2664f0c7ab0c181af0bea66098b1919439815ca8803ef136fc4e",
"sha256:a642295cd0c8df1b86fc3dced1d067874c353a188dc8e0f744626d49e9aa51c4", "sha256:9dc1b507c12eb0481d071f3c1808f0529ad41dc415d0ca11f7ebfc666e66a18b",
"sha256:ab86ce7c8f9bea87b9d12c7f0af71102acbf5ecbc66c17796cff45dae54ef9a5", "sha256:9ebfef07dbe1d93efb94b4700f2d278494e9162565a54f124c404a5656d7ff09",
"sha256:abc267fa9837245cc28ea6929f19fa335f3dc330a35d2e45509b6566dc18be23", "sha256:a45f84b09ac9c3d35dfcf6a27fd0634d30d183205230a0ebe8373a0e8cfa0906",
"sha256:ae1d6df168efb88d7d522664693607b80b4080be6750c913eefb77e34c12c71a", "sha256:a4f55095ad087474999ee28d3398bae183a66be4823f753cd7d67dd0153427c9",
"sha256:b2ebef0e0b4454320274f5e83a41844c63438fdc874ea40a8b5b4ecb7693f1c4", "sha256:a6d511cc297ff0883bc3708b465ff82d7560193169a8b93260f74ecb0a5e08a7",
"sha256:b48ece5bde2e768197a2d0f6e925f9d7e3e826f0ad2271120f8144a9db18d5c8", "sha256:a8ad4c766d3f33ba8fd692f9aa297c9058970530a32c728a2c4bfd2616d3358b",
"sha256:b7cdf28938ac6b8b49ae5e92f2735056a7ba99c9b110a474473fd71185c1af5d", "sha256:aa2f457b4af386254372dfa78a2eda2563680d982422641a85f271c859df1987",
"sha256:bb4462bd43c2460774914b8525f79b00f8f407c945d50881568f294c1d9b4443", "sha256:b03f7941783b4c4a26051846dea594628b38f6940a2fdc0df00b221aed39314c",
"sha256:bc4ff9805858bd54d1a20efff925ccd89c9d2e7cf4986144b30802bf78091c3e", "sha256:b0dae11d8f5ded51699c74d9548dcc5938e0804cc8298ec0aa0da95c21fff57b",
"sha256:c1322d7dd74713dcc157a2b7898a564ab091ca6c58302d5c7b4c07296e3fd00f", "sha256:b91ced227c41aa29c672814f50dbb05ec93536abf8f43cd14ec9521ea09afe4e",
"sha256:c67598100338d5d985db1b3d21f3619ef392e185e71b8d52bceacc4a7771ea7e", "sha256:bc633a9fe1eb87e250b5c57d389cf28998e4292336926b0b6cdaee353f89a237",
"sha256:ca26a1e73c48cfc54c4a76ff78df3727b9d9f4ccc8dbee4ae3f73306a591676d", "sha256:bebb4d6715c814597f85297c332297c6ce81e29436125ca59d1159b07f423eb1",
"sha256:d323a01da91851a4f17bf592faf46149c9169d68430b3146dcba2bb5e5719abc", "sha256:c336a6d235522a62fef872c6295a42ecb0c4e1d0f1a3e500fe949415761b8a19",
"sha256:dc1803ac5c32ec324c5261c7209e8f8ce88e83254c4e1aebdc8b0a39f9ddb443", "sha256:c6514f963b023aeee506678a1cf821fe31159b925c4b76fe2afa94cc70b3222b",
"sha256:e00a3f196329e08e43d99b79b286d60ce46bed10f2280d25a1718399457e06be", "sha256:c693e916709c2465b02ca0ad7b387c4f8423d1db7b4649c551f27a529181c5ad",
"sha256:e85637bc8fe81ddb73fda9e56bab24560bdddfa98aa64f87aaa4e4b6730c23d2", "sha256:c81131869240e3e568916ef4c307f8b99583efaa60a8112ef27a366eefba8ef0",
"sha256:e858ac0a25074ba4bce653f9b5d0a85b7456eaddadc0ce82d3878c22489fa4ee", "sha256:d02a72df14dfdbaf228424573a07af10637bd490f0901cee872c4f434a735b94",
"sha256:eae237477a873ab46e8dd748e515c72c0c804fb380fbe6c85533c7de51f23a8f", "sha256:d2a8fa9d6d6f891f3deec72f5cc668e6f66b188ab14bb1ab52422fe8e644f312",
"sha256:ebef0dd9bf9b812bf75bda96743f2a6c5734a02092ae7f721c048d156d5fabae", "sha256:d2b27e6af28f07e2f195552b37d7d66b150adbaa39a6d327766ffd695799780f",
"sha256:ec3beeada09ff865c344ff3bc2f427f5e6c26401cc6113d77e372c3fdac73864", "sha256:d2fe69c5434391727efa54b47a1e7986bb0186e72a41b203df8f5b0a19a4f669",
"sha256:f76d0ad001edd426b92233d45c746fd08f467d56100fd8f30e9ace4b005266e4", "sha256:d3f3ed29cd9f978c604708511a1f9c2fdcb6c38b9aae36a51905b8811ee5cbf1",
"sha256:f85d05aa0918283cf29a30b547b4df2fbb56b45b135f9e35b6807cb28bc47951", "sha256:d573faf8eb7e6b1cbbcb4f5b247c60ca8be39fe2c674495df0eb4318303137fe",
"sha256:f9899c94762343f2cc2fc64c13e7cae4c3cc65cdfc87dd810a31654c9b7358cc" "sha256:e0bbdd76ce9aa5d4209d65f2b27fc6e5ef1312ae6c5333c26db3f5ade53a1e99",
"sha256:e7c4ea22b6739b162c9ecaaa41d718dfad48a244909fe7ef4b54c0b530effc5a",
"sha256:e93e1a4b4b33daed65d781a57a522ff153dcf748dee70b40c7258c5861e1768a",
"sha256:e97fdf088d4b31ff4ba35db26d9cc472ac7ef4a2ff2badeabf8d727b3377fc52",
"sha256:e9fa4c9bf273ca41f940bceb86922a7667cd5bf90e95dbb157cbb8441008482c",
"sha256:eaad4ff2de1c3823fddf82f41121bdf453d922e9a238642b1dedb33c4e4f98ad",
"sha256:f1f62b2413c3a0e846c3b838b2ecd6c7a19ec6793b2a522745b0869e37ab5bc1",
"sha256:f6d6cff3538391e8486a431569b77921adfcdef14eb18fbf19b7c0a5294d4e6a",
"sha256:f9aa05d09ecf4c75157197f27cdc9cfaeb7c5f15021c6373932bf3e124af029f",
"sha256:fa2fddcb7107e0d1808086ca306dcade7df60a13a6c347a7acf1ec139aa6789a",
"sha256:faa6b09ee09433b87992fb5a2859efd1c264ddc37280d2dd5db502126d0e7f27"
], ],
"markers": "python_version >= '3.8'", "markers": "python_version >= '3.8'",
"version": "==2.18.4" "version": "==2.20.1"
}, },
"pygments": { "pygments": {
"hashes": [ "hashes": [
@ -1034,6 +1159,15 @@
], ],
"version": "==2024.1" "version": "==2024.1"
}, },
"pywikibot": {
"hashes": [
"sha256:3f4fbc57f1765aa0fa1ccf84125bcfa475cae95b9cc0291867b751f3d4ac8fa2",
"sha256:a26d918cf88ef56fdb1421b65b09def200cc28031cdc922d72a4198fbfddd225"
],
"index": "pypi",
"markers": "python_full_version >= '3.7.0'",
"version": "==9.2.1"
},
"pyyaml": { "pyyaml": {
"hashes": [ "hashes": [
"sha256:04ac92ad1925b2cff1db0cfebffb6ffc43457495c9b3c39d3fcae417d7125dc5", "sha256:04ac92ad1925b2cff1db0cfebffb6ffc43457495c9b3c39d3fcae417d7125dc5",
@ -1090,6 +1224,15 @@
], ],
"version": "==6.0.1" "version": "==6.0.1"
}, },
"requests": {
"hashes": [
"sha256:55365417734eb18255590a9ff9eb97e9e1da868d4ccd6402399eaf68af20a760",
"sha256:70761cfe03c773ceb22aa2f671b4757976145175cdfca038c02654d061d6dcc6"
],
"index": "pypi",
"markers": "python_version >= '3.8'",
"version": "==2.32.3"
},
"rich": { "rich": {
"hashes": [ "hashes": [
"sha256:4edbae314f59eb482f54e9e30bf00d33350aaa94f4bfcd4e9e3110e64d0d7222", "sha256:4edbae314f59eb482f54e9e30bf00d33350aaa94f4bfcd4e9e3110e64d0d7222",
@ -1100,83 +1243,78 @@
}, },
"scipy": { "scipy": {
"hashes": [ "hashes": [
"sha256:017367484ce5498445aade74b1d5ab377acdc65e27095155e448c88497755a5d", "sha256:076c27284c768b84a45dcf2e914d4000aac537da74236a0d45d82c6fa4b7b3c0",
"sha256:095a87a0312b08dfd6a6155cbbd310a8c51800fc931b8c0b84003014b874ed3c", "sha256:07e179dc0205a50721022344fb85074f772eadbda1e1b3eecdc483f8033709b7",
"sha256:20335853b85e9a49ff7572ab453794298bcf0354d8068c5f6775a0eabf350aca", "sha256:176c6f0d0470a32f1b2efaf40c3d37a24876cebf447498a4cefb947a79c21e9d",
"sha256:27e52b09c0d3a1d5b63e1105f24177e544a222b43611aaf5bc44d4a0979e32f9", "sha256:42470ea0195336df319741e230626b6225a740fd9dce9642ca13e98f667047c0",
"sha256:2831f0dc9c5ea9edd6e51e6e769b655f08ec6db6e2e10f86ef39bd32eb11da54", "sha256:4c4161597c75043f7154238ef419c29a64ac4a7c889d588ea77690ac4d0d9b20",
"sha256:2ac65fb503dad64218c228e2dc2d0a0193f7904747db43014645ae139c8fad16", "sha256:5b083c8940028bb7e0b4172acafda6df762da1927b9091f9611b0bcd8676f2bc",
"sha256:392e4ec766654852c25ebad4f64e4e584cf19820b980bc04960bca0b0cd6eaa2", "sha256:64b2ff514a98cf2bb734a9f90d32dc89dc6ad4a4a36a312cd0d6327170339eb0",
"sha256:436bbb42a94a8aeef855d755ce5a465479c721e9d684de76bf61a62e7c2b81d5", "sha256:65df4da3c12a2bb9ad52b86b4dcf46813e869afb006e58be0f516bc370165159",
"sha256:45484bee6d65633752c490404513b9ef02475b4284c4cfab0ef946def50b3f59", "sha256:687af0a35462402dd851726295c1a5ae5f987bd6e9026f52e9505994e2f84ef6",
"sha256:54f430b00f0133e2224c3ba42b805bfd0086fe488835effa33fa291561932326", "sha256:6a9c9a9b226d9a21e0a208bdb024c3982932e43811b62d202aaf1bb59af264b1",
"sha256:5713f62f781eebd8d597eb3f88b8bf9274e79eeabf63afb4a737abc6c84ad37b", "sha256:6d056a8709ccda6cf36cdd2eac597d13bc03dba38360f418560a93050c76a16e",
"sha256:5d72782f39716b2b3509cd7c33cdc08c96f2f4d2b06d51e52fb45a19ca0c86a1", "sha256:7d3da42fbbbb860211a811782504f38ae7aaec9de8764a9bef6b262de7a2b50f",
"sha256:637e98dcf185ba7f8e663e122ebf908c4702420477ae52a04f9908707456ba4d", "sha256:7e911933d54ead4d557c02402710c2396529540b81dd554fc1ba270eb7308484",
"sha256:8335549ebbca860c52bf3d02f80784e91a004b71b059e3eea9678ba994796a24", "sha256:94c164a9e2498e68308e6e148646e486d979f7fcdb8b4cf34b5441894bdb9caf",
"sha256:949ae67db5fa78a86e8fa644b9a6b07252f449dcf74247108c50e1d20d2b4627", "sha256:9e3154691b9f7ed73778d746da2df67a19d046a6c8087c8b385bc4cdb2cfca74",
"sha256:a014c2b3697bde71724244f63de2476925596c24285c7a637364761f8710891c", "sha256:9eee2989868e274aae26125345584254d97c56194c072ed96cb433f32f692ed8",
"sha256:a78b4b3345f1b6f68a763c6e25c0c9a23a9fd0f39f5f3d200efe8feda560a5fa", "sha256:a01cc03bcdc777c9da3cfdcc74b5a75caffb48a6c39c8450a9a05f82c4250a14",
"sha256:cdd7dacfb95fea358916410ec61bbc20440f7860333aee6d882bb8046264e949", "sha256:a7d46c3e0aea5c064e734c3eac5cf9eb1f8c4ceee756262f2c7327c4c2691c86",
"sha256:cfa31f1def5c819b19ecc3a8b52d28ffdcc7ed52bb20c9a7589669dd3c250989", "sha256:ad36af9626d27a4326c8e884917b7ec321d8a1841cd6dacc67d2a9e90c2f0359",
"sha256:d533654b7d221a6a97304ab63c41c96473ff04459e404b83275b60aa8f4b7004", "sha256:b5923f48cb840380f9854339176ef21763118a7300a88203ccd0bdd26e58527b",
"sha256:d605e9c23906d1994f55ace80e0125c587f96c020037ea6aa98d01b4bd2e222f", "sha256:bbc0471b5f22c11c389075d091d3885693fd3f5e9a54ce051b46308bc787e5d4",
"sha256:de3ade0e53bc1f21358aa74ff4830235d716211d7d077e340c7349bc3542e884", "sha256:bff2438ea1330e06e53c424893ec0072640dac00f29c6a43a575cbae4c99b2b9",
"sha256:e89369d27f9e7b0884ae559a3a956e77c02114cc60a6058b4e5011572eea9299", "sha256:c40003d880f39c11c1edbae8144e3813904b10514cd3d3d00c277ae996488cdb",
"sha256:eccfa1906eacc02de42d70ef4aecea45415f5be17e72b61bafcfd329bdc52e94", "sha256:d91db2c41dd6c20646af280355d41dfa1ec7eead235642178bd57635a3f82209",
"sha256:f26264b282b9da0952a024ae34710c2aff7d27480ee91a2e82b7b7073c24722f" "sha256:f0a50da861a7ec4573b7c716b2ebdcdf142b66b756a0d392c236ae568b3a93fb"
], ],
"index": "pypi", "index": "pypi",
"markers": "python_version >= '3.9'", "markers": "python_version >= '3.10'",
"version": "==1.13.1" "version": "==1.14.0"
}, },
"shapely": { "shapely": {
"hashes": [ "hashes": [
"sha256:011b77153906030b795791f2fdfa2d68f1a8d7e40bce78b029782ade3afe4f2f", "sha256:03bd7b5fa5deb44795cc0a503999d10ae9d8a22df54ae8d4a4cd2e8a93466195",
"sha256:03152442d311a5e85ac73b39680dd64a9892fa42bb08fd83b3bab4fe6999bfa0", "sha256:06efe39beafde3a18a21dde169d32f315c57da962826a6d7d22630025200c5e6",
"sha256:05ffd6491e9e8958b742b0e2e7c346635033d0a5f1a0ea083547fcc854e5d5cf", "sha256:0f8e71bb9a46814019f6644c4e2560a09d44b80100e46e371578f35eaaa9da1c",
"sha256:0776c92d584f72f1e584d2e43cfc5542c2f3dd19d53f70df0900fda643f4bae6", "sha256:1b65365cfbf657604e50d15161ffcc68de5cdb22a601bbf7823540ab4918a98d",
"sha256:263bcf0c24d7a57c80991e64ab57cba7a3906e31d2e21b455f493d4aab534aaa", "sha256:1e5cb5ee72f1bc7ace737c9ecd30dc174a5295fae412972d3879bac2e82c8fae",
"sha256:2fbdc1140a7d08faa748256438291394967aa54b40009f54e8d9825e75ef6113", "sha256:21f64e647a025b61b19585d2247137b3a38a35314ea68c66aaf507a1c03ef6fe",
"sha256:30982f79f21bb0ff7d7d4a4e531e3fcaa39b778584c2ce81a147f95be1cd58c9", "sha256:2e119444bc27ca33e786772b81760f2028d930ac55dafe9bc50ef538b794a8e1",
"sha256:31c19a668b5a1eadab82ff070b5a260478ac6ddad3a5b62295095174a8d26398", "sha256:2ff9521991ed9e201c2e923da014e766c1aa04771bc93e6fe97c27dcf0d40ace",
"sha256:3f9103abd1678cb1b5f7e8e1af565a652e036844166c91ec031eeb25c5ca8af0", "sha256:30e8737983c9d954cd17feb49eb169f02f1da49e24e5171122cf2c2b62d65c95",
"sha256:41388321a73ba1a84edd90d86ecc8bfed55e6a1e51882eafb019f45895ec0f65", "sha256:35110e80070d664781ec7955c7de557456b25727a0257b354830abb759bf8311",
"sha256:4310b5494271e18580d61022c0857eb85d30510d88606fa3b8314790df7f367d", "sha256:3ac7dc1350700c139c956b03d9c3df49a5b34aaf91d024d1510a09717ea39199",
"sha256:464157509ce4efa5ff285c646a38b49f8c5ef8d4b340f722685b09bb033c5ccf", "sha256:401cb794c5067598f50518e5a997e270cd7642c4992645479b915c503866abed",
"sha256:485246fcdb93336105c29a5cfbff8a226949db37b7473c89caa26c9bae52a242", "sha256:4461509afdb15051e73ab178fae79974387f39c47ab635a7330d7fee02c68a3f",
"sha256:489c19152ec1f0e5c5e525356bcbf7e532f311bff630c9b6bc2db6f04da6a8b9", "sha256:45211276900c4790d6bfc6105cbf1030742da67594ea4161a9ce6812a6721e68",
"sha256:4f2ab0faf8188b9f99e6a273b24b97662194160cc8ca17cf9d1fb6f18d7fb93f", "sha256:49b299b91557b04acb75e9732645428470825061f871a2edc36b9417d66c1fc5",
"sha256:55a38dcd1cee2f298d8c2ebc60fc7d39f3b4535684a1e9e2f39a80ae88b0cea7", "sha256:4c83a36f12ec8dee2066946d98d4d841ab6512a6ed7eb742e026a64854019b5f",
"sha256:58b0ecc505bbe49a99551eea3f2e8a9b3b24b3edd2a4de1ac0dc17bc75c9ec07", "sha256:5bbfb048a74cf273db9091ff3155d373020852805a37dfc846ab71dde4be93ec",
"sha256:5af4cd0d8cf2912bd95f33586600cac9c4b7c5053a036422b97cfe4728d2eb53", "sha256:6c6b78c0007a34ce7144f98b7418800e0a6a5d9a762f2244b00ea560525290c9",
"sha256:5bbd974193e2cc274312da16b189b38f5f128410f3377721cadb76b1e8ca5328", "sha256:7545a39c55cad1562be302d74c74586f79e07b592df8ada56b79a209731c0219",
"sha256:5c4849916f71dc44e19ed370421518c0d86cf73b26e8656192fcfcda08218fbd", "sha256:798090b426142df2c5258779c1d8d5734ec6942f778dab6c6c30cfe7f3bf64ff",
"sha256:5dc736127fac70009b8d309a0eeb74f3e08979e530cf7017f2f507ef62e6cfb8", "sha256:7e8cf5c252fac1ea51b3162be2ec3faddedc82c256a1160fc0e8ddbec81b06d2",
"sha256:63f3a80daf4f867bd80f5c97fbe03314348ac1b3b70fb1c0ad255a69e3749879", "sha256:7fed9dbfbcfec2682d9a047b9699db8dcc890dfca857ecba872c42185fc9e64e",
"sha256:674d7baf0015a6037d5758496d550fc1946f34bfc89c1bf247cabdc415d7747e", "sha256:8203a8b2d44dcb366becbc8c3d553670320e4acf0616c39e218c9561dd738d92",
"sha256:6cd4ccecc5ea5abd06deeaab52fcdba372f649728050c6143cc405ee0c166679", "sha256:89d34787c44f77a7d37d55ae821f3a784fa33592b9d217a45053a93ade899375",
"sha256:790a168a808bd00ee42786b8ba883307c0e3684ebb292e0e20009588c426da47", "sha256:89e640c2cd37378480caf2eeda9a51be64201f01f786d127e78eaeff091ec897",
"sha256:7d56ce3e2a6a556b59a288771cf9d091470116867e578bebced8bfc4147fbfd7", "sha256:8af6f7260f809c0862741ad08b1b89cb60c130ae30efab62320bbf4ee9cc71fa",
"sha256:841f93a0e31e4c64d62ea570d81c35de0f6cea224568b2430d832967536308e6", "sha256:93be600cbe2fbaa86c8eb70656369f2f7104cd231f0d6585c7d0aa555d6878b8",
"sha256:8de4578e838a9409b5b134a18ee820730e507b2d21700c14b71a2b0757396acc", "sha256:9a4492a2b2ccbeaebf181e7310d2dfff4fdd505aef59d6cb0f217607cb042fb3",
"sha256:92a41d936f7d6743f343be265ace93b7c57f5b231e21b9605716f5a47c2879e7", "sha256:b5870633f8e684bf6d1ae4df527ddcb6f3895f7b12bced5c13266ac04f47d231",
"sha256:9831816a5d34d5170aa9ed32a64982c3d6f4332e7ecfe62dc97767e163cb0b17", "sha256:b714a840402cde66fd7b663bb08cacb7211fa4412ea2a209688f671e0d0631fd",
"sha256:994c244e004bc3cfbea96257b883c90a86e8cbd76e069718eb4c6b222a56f78b", "sha256:bff2366bc786bfa6cb353d6b47d0443c570c32776612e527ee47b6df63fcfe32",
"sha256:9dab4c98acfb5fb85f5a20548b5c0abe9b163ad3525ee28822ffecb5c40e724c", "sha256:d5251c28a29012e92de01d2e84f11637eb1d48184ee8f22e2df6c8c578d26760",
"sha256:b79bbd648664aa6f44ef018474ff958b6b296fed5c2d42db60078de3cffbc8aa", "sha256:e91ee179af539100eb520281ba5394919067c6b51824e6ab132ad4b3b3e76dd0",
"sha256:c3e700abf4a37b7b8b90532fa6ed5c38a9bfc777098bc9fbae5ec8e618ac8f30", "sha256:f5456dd522800306ba3faef77c5ba847ec30a0bd73ab087a25e0acdd4db2514f",
"sha256:c52ed79f683f721b69a10fb9e3d940a468203f5054927215586c5d49a072de8d", "sha256:ff7731fea5face9ec08a861ed351734a79475631b7540ceb0b66fb9732a5f529",
"sha256:c75c98380b1ede1cae9a252c6dc247e6279403fae38c77060a5e6186c95073ac", "sha256:ff9e520af0c5a578e174bca3c18713cd47a6c6a15b6cf1f50ac17dc8bb8db6a2"
"sha256:d2b4431f522b277c79c34b65da128029a9955e4481462cbf7ebec23aab61fc58",
"sha256:ddf4a9bfaac643e62702ed662afc36f6abed2a88a21270e891038f9a19bc08fc",
"sha256:de0205cb21ad5ddaef607cda9a3191eadd1e7a62a756ea3a356369675230ac35",
"sha256:ec555c9d0db12d7fd777ba3f8b75044c73e576c720a851667432fabb7057da6c",
"sha256:fb5cdcbbe3080181498931b52a91a21a781a35dcb859da741c0345c6402bf00c"
], ],
"index": "pypi", "index": "pypi",
"markers": "python_version >= '3.7'", "markers": "python_version >= '3.7'",
"version": "==2.0.4" "version": "==2.0.5"
}, },
"shellingham": { "shellingham": {
"hashes": [ "hashes": [
@ -1326,6 +1464,14 @@
"markers": "python_version >= '3.8'", "markers": "python_version >= '3.8'",
"version": "==5.10.0" "version": "==5.10.0"
}, },
"urllib3": {
"hashes": [
"sha256:a448b2f64d686155468037e1ace9f2d2199776e17f0a46610480d311f73e3472",
"sha256:dd505485549a7a552833da5e6063639d0d177c04f23bc3864e41e5dc5f612168"
],
"markers": "python_version >= '3.8'",
"version": "==2.2.2"
},
"uvicorn": { "uvicorn": {
"extras": [ "extras": [
"standard" "standard"

View File

@ -8,4 +8,5 @@ geological
'tourism'='alpine_hut' 'tourism'='alpine_hut'
'tourism'='viewpoint' 'tourism'='viewpoint'
'tourism'='zoo' 'tourism'='zoo'
'tourism'='artwork'
'waterway'='waterfall' 'waterway'='waterfall'

View File

@ -1,8 +1,11 @@
'tourism'='museum' 'tourism'='museum'
'tourism'='attraction' 'tourism'='attraction'
'tourism'='gallery' 'tourism'='gallery'
'tourism'='artwork'
historic historic
'amenity'='planetarium' 'amenity'='planetarium'
'amenity'='place_of_worship' 'amenity'='place_of_worship'
'amenity'='fountain' 'amenity'='fountain'
'water'='reflecting_pool' 'water'='reflecting_pool'
# 'tourism'='attraction' might be a bit too broad
# historic as well

View File

@ -3,6 +3,10 @@ import json, os
from typing import List, Tuple, Optional from typing import List, Tuple, Optional
from OSMPythonTools.overpass import Overpass, overpassQueryBuilder from OSMPythonTools.overpass import Overpass, overpassQueryBuilder
from pywikibot import ItemPage, Site
from pywikibot import config
config.put_throttle = 0
config.maxlag = 0
from structs.landmarks import Landmark, LandmarkType from structs.landmarks import Landmark, LandmarkType
from structs.preferences import Preferences, Preference from structs.preferences import Preferences, Preference
@ -43,31 +47,6 @@ def generate_landmarks(preferences: Preferences, coordinates: Tuple[float, float
return L, take_most_important(L) return L, take_most_important(L)
"""def generate_landmarks(preferences: Preferences, city_country: str = None, coordinates: Tuple[float, float] = None) -> Tuple[List[Landmark], List[Landmark]] :
l_sights, l_nature, l_shop = get_amenities()
L = []
# List for sightseeing
if preferences.sightseeing.score != 0 :
L1 = get_landmarks(l_sights, SIGHTSEEING, city_country=city_country, coordinates=coordinates)
correct_score(L1, preferences.sightseeing)
L += L1
# List for nature
if preferences.nature.score != 0 :
L2 = get_landmarks(l_nature, NATURE, city_country=city_country, coordinates=coordinates)
correct_score(L2, preferences.nature)
L += L2
# List for shopping
if preferences.shopping.score != 0 :
L3 = get_landmarks(l_shop, SHOPPING, city_country=city_country, coordinates=coordinates)
correct_score(L3, preferences.shopping)
L += L3
return remove_duplicates(L), take_most_important(L)
"""
# Helper function to gather the amenities list # Helper function to gather the amenities list
def get_amenities() -> List[List[str]] : def get_amenities() -> List[List[str]] :
@ -87,6 +66,7 @@ def get_list(path: str) -> List[str] :
amenities = [] amenities = []
for line in content : for line in content :
if not line.startswith('#') :
amenities.append(line.strip('\n')) amenities.append(line.strip('\n'))
return amenities return amenities
@ -173,7 +153,7 @@ def correct_score(L: List[Landmark], preference: Preference) :
raise TypeError(f"LandmarkType {preference.type} does not match the type of Landmark {L[0].name}") raise TypeError(f"LandmarkType {preference.type} does not match the type of Landmark {L[0].name}")
for elem in L : for elem in L :
elem.attractiveness = int(elem.attractiveness*preference.score/500) # arbitrary computation elem.attractiveness = int(elem.attractiveness*preference.score/5) # arbitrary computation
# Function to count elements within a certain radius of a location # Function to count elements within a certain radius of a location
@ -192,20 +172,24 @@ def count_elements_within_radius(coordinates: Tuple[float, float], radius: int)
try : try :
overpass = Overpass() overpass = Overpass()
radius_result = overpass.query(radius_query) radius_result = overpass.query(radius_query)
return radius_result.countElements() N_elem = radius_result.countWays() + radius_result.countRelations()
#print(f"There are {N_elem} ways/relations within 50m")
if N_elem is None :
return 0
return N_elem
except : except :
return None return 0
# Creates a bounding box around given coordinates # Creates a bounding box around given coordinates, side_length in meters
def create_bbox(coordinates: Tuple[float, float], side_length: int) -> Tuple[float, float, float, float]: def create_bbox(coordinates: Tuple[float, float], side_length: int) -> Tuple[float, float, float, float]:
lat = coordinates[0] lat = coordinates[0]
lon = coordinates[1] lon = coordinates[1]
# Half the side length in km (since it's a square bbox) # Half the side length in km (since it's a square bbox)
half_side_length_km = side_length / 2.0 half_side_length_km = side_length / 2 / 1000
# Convert distance to degrees # Convert distance to degrees
lat_diff = half_side_length_km / 111 # 1 degree latitude is approximately 111 km lat_diff = half_side_length_km / 111 # 1 degree latitude is approximately 111 km
@ -264,102 +248,61 @@ def get_landmarks(list_amenity: list, landmarktype: LandmarkType, coordinates: T
else : else :
osm_type = elem.type() # Add type : 'way' or 'relation' osm_type = elem.type() # Add type : 'way' or 'relation'
osm_id = elem.id() # Add OSM id osm_id = elem.id() # Add OSM id
elem_type = landmarktype # Add the landmark type as 'sightseeing elem_type = landmarktype # Add the landmark type as 'sightseeing,
n_tags = len(elem.tags().keys()) # Add number of tags n_tags = len(elem.tags().keys()) # Add number of tags
# remove specific tags
skip = False
for tag in elem.tags().keys() :
if "pay" in tag :
n_tags -= 1 # discard payment options for tags
if "disused" in tag :
skip = True # skip disused amenities
break
if "wikipedia" in tag :
n_tags += 3 # wikipedia entries count more
if tag == "wikidata" :
Q = elem.tag('wikidata')
site = Site("wikidata", "wikidata")
item = ItemPage(site, Q)
item.get()
n_languages = len(item.labels)
n_tags += n_languages/10
if elem_type != LandmarkType(landmark_type="nature") :
if "leisure" in tag and elem.tag('leisure') == "park":
elem_type = LandmarkType(landmark_type="nature")
if amenity not in ["'shop'='department_store'", "'shop'='mall'"] :
if "shop" in tag :
skip = True
break
if tag == "building" and elem.tag('building') in ['retail', 'supermarket', 'parking']:
skip = True
break
if skip:
continue
# Add score of given landmark based on the number of surrounding elements. Penalty for churches as there are A LOT # Add score of given landmark based on the number of surrounding elements. Penalty for churches as there are A LOT
if amenity == "'amenity'='place_of_worship'" : if amenity == "'amenity'='place_of_worship'" :
score = int((count_elements_within_radius(location, radius) + n_tags*tag_coeff )*church_coeff) #score = int((count_elements_within_radius(location, radius) + (n_tags*tag_coeff) )*church_coeff)
score = int((count_elements_within_radius(location, radius) + ((n_tags**1.2)*tag_coeff) )*church_coeff)
elif amenity == "'leisure'='park'" : elif amenity == "'leisure'='park'" :
score = int((count_elements_within_radius(location, radius) + n_tags*tag_coeff )*park_coeff) score = int((count_elements_within_radius(location, radius) + ((n_tags**1.2)*tag_coeff) )*park_coeff)
else : else :
score = count_elements_within_radius(location, radius) + n_tags*tag_coeff score = int(count_elements_within_radius(location, radius) + ((n_tags**1.2)*tag_coeff))
if score is not None : if score is not None :
# Generate the landmark and append it to the list # Generate the landmark and append it to the list
landmark = Landmark(name=name, type=elem_type, location=location, osm_type=osm_type, osm_id=osm_id, attractiveness=score, must_do=False, n_tags=n_tags) #print(f"There are {n_tags} tags on this Landmark. Total score : {score}\n")
landmark = Landmark(name=name, type=elem_type, location=location, osm_type=osm_type, osm_id=osm_id, attractiveness=score, must_do=False, n_tags=int(n_tags))
L.append(landmark) L.append(landmark)
return L return L
"""def get_landmarks(list_amenity: list, landmarktype: LandmarkType, city_country: str = None, coordinates: Tuple[float, float] = None) -> List[Landmark] :
if city_country is None and coordinates is None :
raise ValueError("Either one of 'city_country' and 'coordinates' arguments must be specified")
if city_country is not None and coordinates is not None :
raise ValueError("Cannot specify both 'city_country' and 'coordinates' at the same time, please choose either one")
# Read the parameters from the file
with open (os.path.dirname(os.path.abspath(__file__)) + '/parameters/landmarks_manager.params', "r") as f :
parameters = json.loads(f.read())
tag_coeff = parameters['tag coeff']
park_coeff = parameters['park coeff']
church_coeff = parameters['church coeff']
radius = parameters['radius close to']
bbox_side = parameters['city bbox side']
# If city_country is specified :
if city_country is not None :
nominatim = Nominatim()
areaId = nominatim.query(city_country).areaId()
bbox = None
# If coordinates are specified :
elif coordinates is not None :
bbox = create_bbox(coordinates, bbox_side)
areaId = None
else :
raise ValueError("Argument number is not corresponding.")
# Initialize some variables
N = 0
L = []
overpass = Overpass()
for amenity in list_amenity :
query = overpassQueryBuilder(area=areaId, bbox=bbox, elementType=['way', 'relation'], selector=amenity, includeCenter=True, out='body')
result = overpass.query(query)
N += result.countElements()
for elem in result.elements():
name = elem.tag('name') # Add name
location = (elem.centerLat(), elem.centerLon()) # Add coordinates (lat, lon)
# skip if unprecise location
if name is None or location[0] is None:
continue
# skip if unused
if 'disused:leisure' in elem.tags().keys():
continue
# skip if part of another building
if 'building:part' in elem.tags().keys() and elem.tag('building:part') == 'yes':
continue
else :
osm_type = elem.type() # Add type : 'way' or 'relation'
osm_id = elem.id() # Add OSM id
elem_type = landmarktype # Add the landmark type as 'sightseeing
n_tags = len(elem.tags().keys()) # Add number of tags
# Add score of given landmark based on the number of surrounding elements. Penalty for churches as there are A LOT
if amenity == "'amenity'='place_of_worship'" :
score = int((count_elements_within_radius(location, radius) + n_tags*tag_coeff )*church_coeff)
elif amenity == "'leisure'='park'" :
score = int((count_elements_within_radius(location, radius) + n_tags*tag_coeff )*park_coeff)
else :
score = count_elements_within_radius(location, radius) + n_tags*tag_coeff
if score is not None :
# Generate the landmark and append it to the list
landmark = Landmark(name=name, type=elem_type, location=location, osm_type=osm_type, osm_id=osm_id, attractiveness=score, must_do=False, n_tags=n_tags)
L.append(landmark)
return L
"""

View File

@ -1,23 +0,0 @@
import fastapi
from dataclasses import dataclass
@dataclass
class Destination:
name: str
location: tuple
attractiveness: int
d = Destination()
def get_route() -> list[Destination]:
return {"route": "Hello World"}
endpoint = ("/get_route", get_route)
end
if __name__ == "__main__":
fastapi.run()

View File

@ -344,6 +344,8 @@ def link_list_simple(ordered_visit: List[Landmark])-> List[Landmark] :
elem.next_uuid = next.uuid elem.next_uuid = next.uuid
d = get_distance(elem.location, next.location, detour_factor, speed)[1] d = get_distance(elem.location, next.location, detour_factor, speed)[1]
elem.time_to_reach_next = d elem.time_to_reach_next = d
if elem.name not in ['start', 'finish'] :
elem.must_do = True
L.append(elem) L.append(elem)
j += 1 j += 1
total_dist += d total_dist += d

446
backend/src/optimizer_v4.py Normal file
View File

@ -0,0 +1,446 @@
import numpy as np
import json, os
from typing import List, Tuple
from scipy.optimize import linprog
from collections import defaultdict, deque
from geopy.distance import geodesic
from structs.landmarks import Landmark
# Function to print the result
def print_res(L: List[Landmark]):
print('The following order is suggested : ')
dist = 0
for elem in L :
if elem.time_to_reach_next is not None :
print('- ' + elem.name + ', time to reach next = ' + str(elem.time_to_reach_next))
dist += elem.time_to_reach_next
else :
print('- ' + elem.name)
print("\nMinutes walked : " + str(dist))
print(f"Visited {len(L)-2} landmarks")
# Prevent the use of a particular solution
def prevent_config(resx):
for i, elem in enumerate(resx):
resx[i] = round(elem)
N = len(resx) # Number of edges
L = int(np.sqrt(N)) # Number of landmarks
nonzeroind = np.nonzero(resx)[0] # the return is a little funky so I use the [0]
nonzero_tup = np.unravel_index(nonzeroind, (L,L))
ind_a = nonzero_tup[0].tolist()
vertices_visited = ind_a
vertices_visited.remove(0)
ones = [1]*L
h = [0]*N
for i in range(L) :
if i in vertices_visited :
h[i*L:i*L+L] = ones
return h, [len(vertices_visited)-1]
# Prevents the creation of the same circle (both directions)
def prevent_circle(circle_vertices: list, L: int) :
l1 = [0]*L*L
l2 = [0]*L*L
for i, node in enumerate(circle_vertices[:-1]) :
next = circle_vertices[i+1]
l1[node*L + next] = 1
l2[next*L + node] = 1
s = circle_vertices[0]
g = circle_vertices[-1]
l1[g*L + s] = 1
l2[s*L + g] = 1
return np.vstack((l1, l2)), [0, 0]
# Returns the order of visit as well as any circles if there are some
def is_connected(resx) :
# first round the results to have only 0-1 values
for i, elem in enumerate(resx):
resx[i] = round(elem)
N = len(resx) # length of res
L = int(np.sqrt(N)) # number of landmarks. CAST INTO INT but should not be a problem because N = L**2 by def.
n_edges = resx.sum() # number of edges
nonzeroind = np.nonzero(resx)[0] # the return is a little funny so I use the [0]
nonzero_tup = np.unravel_index(nonzeroind, (L,L))
ind_a = nonzero_tup[0].tolist()
ind_b = nonzero_tup[1].tolist()
# Step 1: Create a graph representation
graph = defaultdict(list)
for a, b in zip(ind_a, ind_b):
graph[a].append(b)
# Step 2: Function to perform BFS/DFS to extract journeys
def get_journey(start):
journey_nodes = []
visited = set()
stack = deque([start])
while stack:
node = stack.pop()
if node not in visited:
visited.add(node)
journey_nodes.append(node)
for neighbor in graph[node]:
if neighbor not in visited:
stack.append(neighbor)
return journey_nodes
# Step 3: Extract all journeys
all_journeys_nodes = []
visited_nodes = set()
for node in ind_a:
if node not in visited_nodes:
journey_nodes = get_journey(node)
all_journeys_nodes.append(journey_nodes)
visited_nodes.update(journey_nodes)
for l in all_journeys_nodes :
if 0 in l :
order = l
all_journeys_nodes.remove(l)
break
if len(all_journeys_nodes) == 0 :
return order, None
return order, all_journeys_nodes
# Function that returns the time in minutes from one location to another
def get_time(p1: Tuple[float, float], p2: Tuple[float, float], detour: float, speed: float) :
# Compute the straight-line distance in km
if p1 == p2 :
return 0
else:
dist = geodesic(p1, p2).kilometers
# Consider the detour factor for average cityto deterline walking distance (in km)
walk_dist = dist*detour
# Time to walk this distance (in minutes)
walk_time = walk_dist/speed*60
return round(walk_time)
# Initialize A and c. Compute the distances from all landmarks to each other and store attractiveness
# We want to maximize the sightseeing : max(c) st. A*x < b and A_eq*x = b_eq
def init_ub_dist(landmarks: List[Landmark], max_steps: int):
with open (os.path.dirname(os.path.abspath(__file__)) + '/parameters/optimizer.params', "r") as f :
parameters = json.loads(f.read())
detour = parameters['detour factor']
speed = parameters['average walking speed']
# Objective function coefficients. a*x1 + b*x2 + c*x3 + ...
c = []
# Coefficients of inequality constraints (left-hand side)
A_ub = []
for spot1 in landmarks :
dist_table = [0]*len(landmarks)
c.append(-spot1.attractiveness)
for j, spot2 in enumerate(landmarks) :
t = get_time(spot1.location, spot2.location, detour, speed)
dist_table[j] = t
closest = sorted(dist_table)[:22]
for i, dist in enumerate(dist_table) :
if dist not in closest :
dist_table[i] = 32700
A_ub += dist_table
c = c*len(landmarks)
return c, A_ub, [max_steps]
# Constraint to respect only one travel per landmark. Also caps the total number of visited landmarks
def respect_number(L: int, max_landmarks: int):
ones = [1]*L
zeros = [0]*L
A = ones + zeros*(L-1)
b = [1]
for i in range(L-1) :
h_new = zeros*i + ones + zeros*(L-1-i)
A = np.vstack((A, h_new))
b.append(1)
if max_landmarks is None :
# Read the parameters from the file
with open (os.path.dirname(os.path.abspath(__file__)) + '/parameters/optimizer.params', "r") as f :
parameters = json.loads(f.read())
max_landmarks = parameters['max landmarks']
A = np.vstack((A, ones*L))
b.append(max_landmarks+1)
return A, b
# Constraint to not have d14 and d41 simultaneously. Does not prevent cyclic paths with more elements
def break_sym(L):
upper_ind = np.triu_indices(L,0,L)
up_ind_x = upper_ind[0]
up_ind_y = upper_ind[1]
A = [0]*L*L # useless row to prevent overhead ? better solution welcomed
# A[up_ind_x[0]*L + up_ind_y[0]] = 1
# A[up_ind_y[0]*L + up_ind_x[0]] = 1
b = [1]
for i, _ in enumerate(up_ind_x[1:]) :
l = [0]*L*L
if up_ind_x[i] != up_ind_y[i] :
l[up_ind_x[i]*L + up_ind_y[i]] = 1
l[up_ind_y[i]*L + up_ind_x[i]] = 1
A = np.vstack((A,l))
b.append(1)
return A, b
# Constraint to not stay in position. Removes d11, d22, d33, etc.
def init_eq_not_stay(L: int):
l = [0]*L*L
for i in range(L) :
for j in range(L) :
if j == i :
l[j + i*L] = 1
l = np.array(np.array(l), dtype=np.int8)
return [l], [0]
# Go through the landmarks and force the optimizer to use landmarks marked as must_do
def respect_user_must_do(landmarks: List[Landmark]) :
L = len(landmarks)
A = [0]*L*L
b = [0]
for i, elem in enumerate(landmarks[1:]) :
if elem.must_do is True and elem.name not in ['finish', 'start']:
l = [0]*L*L
l[i*L:i*L+L] = [1]*L # set mandatory departures from landmarks tagged as 'must_do'
A = np.vstack((A,l))
b.append(1)
return A, b
# Constraint to ensure start at start and finish at goal
def respect_start_finish(L: int):
l_start = [1]*L + [0]*L*(L-1) # sets departures only for start (horizontal ones)
l_start[L-1] = 0 # prevents the jump from start to finish
l_goal = [0]*L*L # sets arrivals only for finish (vertical ones)
l_L = [0]*L*(L-1) + [1]*L # prevents arrivals at start and departures from goal
for k in range(L-1) : # sets only vertical ones for goal (go to)
l_L[k*L] = 1
if k != 0 :
l_goal[k*L+L-1] = 1
A = np.vstack((l_start, l_goal))
b = [1, 1]
A = np.vstack((A,l_L))
b.append(0)
return A, b
# Constraint to tie the problem together. Necessary but not sufficient to avoid circles
def respect_order(L: int):
A = [0]*L*L # useless row to reduce overhead ? better solution is welcome
b = [0]
for i in range(L-1) : # Prevent stacked ones
if i == 0 or i == L-1: # Don't touch start or finish
continue
else :
l = [0]*L
l[i] = -1
l = l*L
for j in range(L) :
l[i*L + j] = 1
A = np.vstack((A,l))
b.append(0)
return A, b
# Computes the time to reach from each landmark to the next
def link_list(order: List[int], landmarks: List[Landmark])->List[Landmark] :
# Read the parameters from the file
with open (os.path.dirname(os.path.abspath(__file__)) + '/parameters/optimizer.params', "r") as f :
parameters = json.loads(f.read())
detour_factor = parameters['detour factor']
speed = parameters['average walking speed']
L = []
j = 0
total_dist = 0
while j < len(order)-1 :
elem = landmarks[order[j]]
next = landmarks[order[j+1]]
d = get_time(elem.location, next.location, detour_factor, speed)
elem.time_to_reach_next = d
elem.must_do = True
elem.location = (round(elem.location[0], 5), round(elem.location[1], 5))
L.append(elem)
j += 1
total_dist += d
next.location = (round(next.location[0], 5), round(next.location[1], 5))
L.append(next)
return L, total_dist
# Same as link_list but does it on a already ordered list
def link_list_simple(ordered_visit: List[Landmark])-> List[Landmark] :
# Read the parameters from the file
with open (os.path.dirname(os.path.abspath(__file__)) + '/parameters/optimizer.params', "r") as f :
parameters = json.loads(f.read())
detour_factor = parameters['detour factor']
speed = parameters['average walking speed']
L = []
j = 0
total_dist = 0
while j < len(ordered_visit)-1 :
elem = ordered_visit[j]
next = ordered_visit[j+1]
elem.next_uuid = next.uuid
d = get_time(elem.location, next.location, detour_factor, speed)
elem.time_to_reach_next = d
if elem.name not in ['start', 'finish'] :
elem.must_do = True
L.append(elem)
j += 1
total_dist += d
L.append(next)
return L, total_dist
# Main optimization pipeline
def solve_optimization (landmarks :List[Landmark], max_steps: int, printing_details: bool, max_landmarks = None) :
L = len(landmarks)
# SET CONSTRAINTS FOR INEQUALITY
c, A_ub, b_ub = init_ub_dist(landmarks, max_steps) # Add the distances from each landmark to the other
A, b = respect_number(L, max_landmarks) # Respect max number of visits (no more possible stops than landmarks).
A_ub = np.vstack((A_ub, A), dtype=np.int16)
b_ub += b
A, b = break_sym(L) # break the 'zig-zag' symmetry
A_ub = np.vstack((A_ub, A), dtype=np.int16)
b_ub += b
# SET CONSTRAINTS FOR EQUALITY
A_eq, b_eq = init_eq_not_stay(L) # Force solution not to stay in same place
A, b = respect_user_must_do(landmarks) # Check if there are user_defined must_see. Also takes care of start/goal
A_eq = np.vstack((A_eq, A), dtype=np.int8)
b_eq += b
A, b = respect_start_finish(L) # Force start and finish positions
A_eq = np.vstack((A_eq, A), dtype=np.int8)
b_eq += b
A, b = respect_order(L) # Respect order of visit (only works when max_steps is limiting factor)
A_eq = np.vstack((A_eq, A), dtype=np.int8)
b_eq += b
# SET BOUNDS FOR DECISION VARIABLE (x can only be 0 or 1)
x_bounds = [(0, 1)]*L*L
# Solve linear programming problem
res = linprog(c, A_ub=A_ub, b_ub=b_ub, A_eq=A_eq, b_eq = b_eq, bounds=x_bounds, method='highs', integrality=3)
# Raise error if no solution is found
if not res.success :
raise ArithmeticError("No solution could be found, the problem is overconstrained. Please adapt your must_dos")
# If there is a solution, we're good to go, just check for connectiveness
else :
order, circles = is_connected(res.x)
#nodes, edges = is_connected(res.x)
i = 0
timeout = 80
while circles is not None and i < timeout:
A, b = prevent_config(res.x)
A_ub = np.vstack((A_ub, A))
b_ub += b
#A_ub, b_ub = prevent_circle(order, len(landmarks), A_ub, b_ub)
for circle in circles :
A, b = prevent_circle(circle, len(landmarks))
A_eq = np.vstack((A_eq, A))
b_eq += b
res = linprog(c, A_ub=A_ub, b_ub=b_ub, A_eq=A_eq, b_eq = b_eq, bounds=x_bounds, method='highs', integrality=3)
if not res.success :
print("Solving failed because of overconstrained problem")
return None
order, circles = is_connected(res.x)
#nodes, edges = is_connected(res.x)
if circles is None :
break
print(i)
i += 1
if i == timeout :
raise TimeoutError(f"Optimization took too long. No solution found after {timeout} iterations.")
# Add the times to reach and stop optimizing
L, _ = link_list(order, landmarks)
if printing_details is True :
if i != 0 :
print(f"Neded to recompute paths {i} times because of unconnected loops...")
print_res(L)
print("\nTotal score : " + str(int(-res.fun)))
return L

View File

@ -1,8 +1,8 @@
{ {
"city bbox side" : 10, "city bbox side" : 5000,
"radius close to" : 27.5, "radius close to" : 50,
"church coeff" : 0.6, "church coeff" : 0.8,
"park coeff" : 1.5, "park coeff" : 1.2,
"tag coeff" : 100, "tag coeff" : 10,
"N important" : 40 "N important" : 40
} }

View File

@ -1,5 +1,5 @@
{ {
"detour factor" : 1.4, "detour factor" : 1.4,
"average walking speed" : 4.8, "average walking speed" : 4.8,
"max landmarks" : 10 "max landmarks" : 7
} }

View File

@ -1,17 +1,15 @@
from collections import defaultdict
from heapq import heappop, heappush
from itertools import permutations
import os, json import os, json
from shapely import buffer, LineString, Point, Polygon, MultiPoint, convex_hull, concave_hull, LinearRing from shapely import buffer, LineString, Point, Polygon, MultiPoint, concave_hull
from typing import List, Tuple from typing import List, Tuple
from math import pi from math import pi
from structs.landmarks import Landmark from structs.landmarks import Landmark
from landmarks_manager import take_most_important from landmarks_manager import take_most_important
from optimizer import solve_optimization, link_list_simple, print_res, get_distance from optimizer_v4 import solve_optimization, link_list_simple, print_res, get_time
# Create corridor from tour
def create_corridor(landmarks: List[Landmark], width: float) : def create_corridor(landmarks: List[Landmark], width: float) :
corrected_width = (180*width)/(6371000*pi) corrected_width = (180*width)/(6371000*pi)
@ -22,6 +20,7 @@ def create_corridor(landmarks: List[Landmark], width: float) :
return obj return obj
# Create linestring from tour
def create_linestring(landmarks: List[Landmark])->List[Point] : def create_linestring(landmarks: List[Landmark])->List[Point] :
points = [] points = []
@ -32,11 +31,13 @@ def create_linestring(landmarks: List[Landmark])->List[Point] :
return LineString(points) return LineString(points)
# Check if some coordinates are in area. Used for the corridor
def is_in_area(area: Polygon, coordinates) -> bool : def is_in_area(area: Polygon, coordinates) -> bool :
point = Point(coordinates) point = Point(coordinates)
return point.within(area) return point.within(area)
# Function to determine if two landmarks are close to each other
def is_close_to(location1: Tuple[float], location2: Tuple[float]): def is_close_to(location1: Tuple[float], location2: Tuple[float]):
"""Determine if two locations are close by rounding their coordinates to 3 decimals.""" """Determine if two locations are close by rounding their coordinates to 3 decimals."""
absx = abs(location1[0] - location2[0]) absx = abs(location1[0] - location2[0])
@ -46,6 +47,7 @@ def is_close_to(location1: Tuple[float], location2: Tuple[float]):
#return (round(location1[0], 3), round(location1[1], 3)) == (round(location2[0], 3), round(location2[1], 3)) #return (round(location1[0], 3), round(location1[1], 3)) == (round(location2[0], 3), round(location2[1], 3))
# Rearrange some landmarks in the order of visit to group visit
def rearrange(landmarks: List[Landmark]) -> List[Landmark]: def rearrange(landmarks: List[Landmark]) -> List[Landmark]:
i = 1 i = 1
@ -62,66 +64,9 @@ def rearrange(landmarks: List[Landmark]) -> List[Landmark]:
return landmarks return landmarks
"""
def find_shortest_path(landmarks: List[Landmark]) -> List[Landmark]:
# Read from data # Simple nearest neighbour planner to try to fix the path
with open (os.path.dirname(os.path.abspath(__file__)) + '/parameters/optimizer.params', "r") as f : def find_shortest_path_through_all_landmarks(landmarks: List[Landmark]) -> Tuple[List[Landmark], Polygon]:
parameters = json.loads(f.read())
detour = parameters['detour factor']
speed = parameters['average walking speed']
# Step 1: Build the graph
graph = defaultdict(list)
for i in range(len(landmarks)):
for j in range(len(landmarks)):
if i != j:
distance = get_distance(landmarks[i].location, landmarks[j].location, detour, speed)[1]
graph[i].append((distance, j))
# Step 2: Dijkstra's algorithm to find the shortest path from start to finish
start_idx = next(i for i, lm in enumerate(landmarks) if lm.name == 'start')
finish_idx = next(i for i, lm in enumerate(landmarks) if lm.name == 'finish')
distances = {i: float('inf') for i in range(len(landmarks))}
previous_nodes = {i: None for i in range(len(landmarks))}
distances[start_idx] = 0
priority_queue = [(0, start_idx)]
while priority_queue:
current_distance, current_index = heappop(priority_queue)
if current_distance > distances[current_index]:
continue
for neighbor_distance, neighbor_index in graph[current_index]:
distance = current_distance + neighbor_distance
if distance < distances[neighbor_index]:
distances[neighbor_index] = distance
previous_nodes[neighbor_index] = current_index
heappush(priority_queue, (distance, neighbor_index))
# Step 3: Backtrack from finish to start to find the path
path = []
current_index = finish_idx
while current_index is not None:
path.append(landmarks[current_index])
current_index = previous_nodes[current_index]
path.reverse()
return path
"""
"""
def total_path_distance(path: List[Landmark], detour, speed) -> float:
total_distance = 0
for i in range(len(path) - 1):
total_distance += get_distance(path[i].location, path[i + 1].location, detour, speed)[1]
return total_distance
"""
def find_shortest_path_through_all_landmarks(landmarks: List[Landmark]) -> List[Landmark]:
# Read from data # Read from data
with open (os.path.dirname(os.path.abspath(__file__)) + '/parameters/optimizer.params', "r") as f : with open (os.path.dirname(os.path.abspath(__file__)) + '/parameters/optimizer.params', "r") as f :
@ -148,7 +93,7 @@ def find_shortest_path_through_all_landmarks(landmarks: List[Landmark]) -> List[
# Step 4: Use nearest neighbor heuristic to visit all landmarks # Step 4: Use nearest neighbor heuristic to visit all landmarks
while unvisited_landmarks: while unvisited_landmarks:
nearest_landmark = min(unvisited_landmarks, key=lambda lm: get_distance(current_landmark.location, lm.location, detour, speed)[1]) nearest_landmark = min(unvisited_landmarks, key=lambda lm: get_time(current_landmark.location, lm.location, detour, speed))
path.append(nearest_landmark) path.append(nearest_landmark)
coordinates.append(nearest_landmark.location) coordinates.append(nearest_landmark.location)
current_landmark = nearest_landmark current_landmark = nearest_landmark
@ -162,6 +107,8 @@ def find_shortest_path_through_all_landmarks(landmarks: List[Landmark]) -> List[
return path, path_poly return path, path_poly
# Returns a list of minor landmarks around the planned path to enhance experience
def get_minor_landmarks(all_landmarks: List[Landmark], visited_landmarks: List[Landmark], width: float) -> List[Landmark] : def get_minor_landmarks(all_landmarks: List[Landmark], visited_landmarks: List[Landmark], width: float) -> List[Landmark] :
second_order_landmarks = [] second_order_landmarks = []
@ -178,58 +125,31 @@ def get_minor_landmarks(all_landmarks: List[Landmark], visited_landmarks: List[L
return take_most_important(second_order_landmarks, len(visited_landmarks)) return take_most_important(second_order_landmarks, len(visited_landmarks))
# Try fix the shortest path using shapely
def fix_using_polygon(tour: List[Landmark])-> List[Landmark] :
"""def refine_optimization(landmarks: List[Landmark], base_tour: List[Landmark], max_time: int, print_infos: bool) -> List[Landmark] : coords = []
coords_dict = {}
for landmark in tour :
coords.append(landmark.location)
if landmark.name != 'finish' :
coords_dict[landmark.location] = landmark
minor_landmarks = get_minor_landmarks(landmarks, base_tour, 200) tour_poly = Polygon(coords)
if print_infos : print("There are " + str(len(minor_landmarks)) + " minor landmarks around the predicted path") better_tour_poly = tour_poly.buffer(0)
try :
xs, ys = better_tour_poly.exterior.xy
full_set = base_tour[:-1] + minor_landmarks # create full set of possible landmarks (without finish) if len(xs) != len(tour) :
full_set.append(base_tour[-1]) # add finish back
new_tour = solve_optimization(full_set, max_time, print_infos)
return new_tour"""
def refine_optimization(landmarks: List[Landmark], base_tour: List[Landmark], max_time: int, print_infos: bool) -> List[Landmark] :
# Read from the file
with open (os.path.dirname(os.path.abspath(__file__)) + '/parameters/optimizer.params', "r") as f :
parameters = json.loads(f.read())
max_landmarks = parameters['max landmarks']
if len(base_tour)-2 >= max_landmarks :
return base_tour
minor_landmarks = get_minor_landmarks(landmarks, base_tour, 200)
if print_infos : print("Using " + str(len(minor_landmarks)) + " minor landmarks around the predicted path")
# full set of visitable landmarks
full_set = base_tour[:-1] + minor_landmarks # create full set of possible landmarks (without finish)
full_set.append(base_tour[-1]) # add finish back
# get a new tour
new_tour = solve_optimization(full_set, max_time, False)
new_tour, new_dist = link_list_simple(new_tour)
"""#if base_tour[0].location == base_tour[-1].location :
if False :
coords = [] # Coordinates of the new tour
coords_dict = {} # maps the location of an element to the element itself. Used to access the elements back once we get the geometry
# Iterate through the new tour without finish
for elem in new_tour[:-1] :
coords.append(Point(elem.location))
coords_dict[elem.location] = elem # if start = goal, only finish remains
# Create a concave polygon using the coordinates
better_tour_poly = concave_hull(MultiPoint(coords)) # Create concave hull with "core" of tour leaving out start and finish better_tour_poly = concave_hull(MultiPoint(coords)) # Create concave hull with "core" of tour leaving out start and finish
xs, ys = better_tour_poly.exterior.xy xs, ys = better_tour_poly.exterior.xy
except :
better_tour_poly = concave_hull(MultiPoint(coords)) # Create concave hull with "core" of tour leaving out start and finish
xs, ys = better_tour_poly.exterior.xy
# reverse the xs and ys # reverse the xs and ys
xs.reverse() xs.reverse()
ys.reverse() ys.reverse()
@ -239,8 +159,9 @@ def refine_optimization(landmarks: List[Landmark], base_tour: List[Landmark], ma
# Loop through the polygon and generate the better (ordered) tour # Loop through the polygon and generate the better (ordered) tour
for i,x in enumerate(xs[:-1]) : for i,x in enumerate(xs[:-1]) :
better_tour.append(coords_dict[tuple((x,ys[i]))]) y = ys[i]
name_index[coords_dict[tuple((x,ys[i]))].name] = i better_tour.append(coords_dict[tuple((x,y))])
name_index[coords_dict[tuple((x,y))].name] = i
# Scroll the list to have start in front again # Scroll the list to have start in front again
@ -248,46 +169,76 @@ def refine_optimization(landmarks: List[Landmark], base_tour: List[Landmark], ma
better_tour = better_tour[start_index:] + better_tour[:start_index] better_tour = better_tour[start_index:] + better_tour[:start_index]
# Append the finish back and correct the time to reach # Append the finish back and correct the time to reach
better_tour.append(new_tour[-1]) better_tour.append(tour[-1])
# Rearrange only if polygon # Rearrange only if polygon still not simple
if not better_tour_poly.is_simple :
better_tour = rearrange(better_tour) better_tour = rearrange(better_tour)
# Add the time to reach return better_tour
better_tour = add_time_to_reach_simple(better_tour)
"""
""" # Second stage of the optimization. Use linear programming again to refine the path
if not better_poly.is_simple : def refine_optimization(landmarks: List[Landmark], base_tour: List[Landmark], max_time: int, detour: int, print_infos: bool) -> List[Landmark] :
coords_dict = {} # Read from the file
better_tour2 = [] with open (os.path.dirname(os.path.abspath(__file__)) + '/parameters/optimizer.params', "r") as f :
for elem in better_tour : parameters = json.loads(f.read())
coords_dict[elem.location] = elem max_landmarks = parameters['max landmarks'] + 4
better_poly2 = better_poly.buffer(0) # No need to refine if no detour is taken
new_coords = better_poly2.exterior.coords[:] # if detour == 0 :
start_coords = base_tour[0].location if False :
start_index = new_coords. new_tour = base_tour
#for point in new_coords : else :
""" minor_landmarks = get_minor_landmarks(landmarks, base_tour, 200)
if print_infos : print("Using " + str(len(minor_landmarks)) + " minor landmarks around the predicted path")
# full set of visitable landmarks
full_set = base_tour[:-1] + minor_landmarks # create full set of possible landmarks (without finish)
full_set.append(base_tour[-1]) # add finish back
# get a new tour
new_tour = solve_optimization(full_set, max_time+detour, False, max_landmarks)
if new_tour is None :
new_tour = base_tour
# Link the new tour
new_tour, new_dist = link_list_simple(new_tour)
# If the tour contains only one landmark, return
if len(new_tour) < 4 :
return new_tour
# Find shortest path using the nearest neighbor heuristic
better_tour, better_poly = find_shortest_path_through_all_landmarks(new_tour) better_tour, better_poly = find_shortest_path_through_all_landmarks(new_tour)
# Fix the tour using Polygons if the path looks weird
if base_tour[0].location == base_tour[-1].location and not better_poly.is_valid :
better_tour = fix_using_polygon(better_tour)
# Link the tour again
better_tour, better_dist = link_list_simple(better_tour) better_tour, better_dist = link_list_simple(better_tour)
# Choose the better tour depending on walked distance
if new_dist < better_dist : if new_dist < better_dist :
final_tour = new_tour final_tour = new_tour
else : else :
final_tour = better_tour final_tour = better_tour
if print_infos : if print_infos :
print("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n") print("\n\n\nRefined tour (result of second stage optimization): ")
print("\nRefined tour (result of second stage optimization): ") print_res(final_tour)
print_res(final_tour, len(full_set)) total_score = 0
for elem in final_tour :
total_score += elem.attractiveness
print("\nTotal score : " + str(total_score))
return final_tour return final_tour

View File

@ -7,8 +7,6 @@ from uuid import uuid4
# Output to frontend # Output to frontend
class Landmark(BaseModel) : class Landmark(BaseModel) :
# Unique ID of a given landmark
uuid: str = Field(default_factory=uuid4) # TODO implement this ASAP
# Properties of the landmark # Properties of the landmark
name : str name : str
@ -22,6 +20,9 @@ class Landmark(BaseModel) :
description : Optional[str] = None # TODO future description : Optional[str] = None # TODO future
duration : Optional[int] = 0 # TODO future duration : Optional[int] = 0 # TODO future
# Unique ID of a given landmark
uuid: str = Field(default_factory=uuid4) # TODO implement this ASAP
# Additional properties depending on specific tour # Additional properties depending on specific tour
must_do : bool must_do : bool
is_secondary : Optional[bool] = False # TODO future is_secondary : Optional[bool] = False # TODO future

View File

@ -4,7 +4,7 @@ from typing import List
from landmarks_manager import generate_landmarks from landmarks_manager import generate_landmarks
from fastapi.encoders import jsonable_encoder from fastapi.encoders import jsonable_encoder
from optimizer import solve_optimization from optimizer_v4 import solve_optimization
from refiner import refine_optimization from refiner import refine_optimization
from structs.landmarks import Landmark from structs.landmarks import Landmark
from structs.landmarktype import LandmarkType from structs.landmarktype import LandmarkType
@ -23,7 +23,8 @@ def write_data(L: List[Landmark], file_name: str):
data.to_json(file_name, indent = 2, force_ascii=False) data.to_json(file_name, indent = 2, force_ascii=False)
def test3(city_country: str) -> List[Landmark]:
def test4(coordinates: tuple[float, float]) -> List[Landmark]:
preferences = Preferences( preferences = Preferences(
@ -38,52 +39,12 @@ def test3(city_country: str) -> List[Landmark]:
shopping=Preference( shopping=Preference(
name='shopping', name='shopping',
type=LandmarkType(landmark_type='shopping'), type=LandmarkType(landmark_type='shopping'),
score = 5)) score = 0))
coordinates = None
landmarks, landmarks_short = generate_landmarks(preferences=preferences, city_country=city_country, coordinates=coordinates)
#write_data(landmarks)
start = Landmark(name='start', type=LandmarkType(landmark_type='start'), location=(48.2044576, 16.3870242), osm_type='start', osm_id=0, attractiveness=0, must_do=True, n_tags = 0)
finish = Landmark(name='finish', type=LandmarkType(landmark_type='finish'), location=(48.2044576, 16.3870242), osm_type='finish', osm_id=0, attractiveness=0, must_do=True, n_tags = 0)
test = landmarks_short
test.insert(0, start)
test.append(finish)
max_walking_time = 2 # hours
visiting_list = solve_optimization(test, max_walking_time*60, True)
def test4(coordinates: tuple[float, float]) -> List[Landmark]:
preferences = Preferences(
sightseeing=Preference(
name='sightseeing',
type=LandmarkType(landmark_type='sightseeing'),
score = 5),
nature=Preference(
name='nature',
type=LandmarkType(landmark_type='nature'),
score = 5),
shopping=Preference(
name='shopping',
type=LandmarkType(landmark_type='shopping'),
score = 5))
# Create start and finish # Create start and finish
start = Landmark(name='start', type=LandmarkType(landmark_type='start'), location=coordinates, osm_type='start', osm_id=0, attractiveness=0, must_do=True, n_tags = 0) start = Landmark(name='start', type=LandmarkType(landmark_type='start'), location=coordinates, osm_type='start', osm_id=0, attractiveness=0, must_do=False, n_tags = 0)
finish = Landmark(name='finish', type=LandmarkType(landmark_type='finish'), location=coordinates, osm_type='finish', osm_id=0, attractiveness=0, must_do=True, n_tags = 0) finish = Landmark(name='finish', type=LandmarkType(landmark_type='finish'), location=coordinates, osm_type='finish', osm_id=0, attractiveness=0, must_do=False, n_tags = 0)
#finish = Landmark(name='finish', type=LandmarkType(landmark_type='finish'), location=(48.8777055, 2.3640967), osm_type='finish', osm_id=0, attractiveness=0, must_do=True, n_tags = 0) #finish = Landmark(name='finish', type=LandmarkType(landmark_type='finish'), location=(48.8777055, 2.3640967), osm_type='finish', osm_id=0, attractiveness=0, must_do=True, n_tags = 0)
#start = Landmark(name='start', type=LandmarkType(landmark_type='start'), location=(48.847132, 2.312359), osm_type='start', osm_id=0, attractiveness=0, must_do=True, n_tags = 0) #start = Landmark(name='start', type=LandmarkType(landmark_type='start'), location=(48.847132, 2.312359), osm_type='start', osm_id=0, attractiveness=0, must_do=True, n_tags = 0)
#finish = Landmark(name='finish', type=LandmarkType(landmark_type='finish'), location=(48.843185, 2.344533), osm_type='finish', osm_id=0, attractiveness=0, must_do=True, n_tags = 0) #finish = Landmark(name='finish', type=LandmarkType(landmark_type='finish'), location=(48.843185, 2.344533), osm_type='finish', osm_id=0, attractiveness=0, must_do=True, n_tags = 0)
@ -91,26 +52,29 @@ def test4(coordinates: tuple[float, float]) -> List[Landmark]:
# Generate the landmarks from the start location # Generate the landmarks from the start location
landmarks, landmarks_short = generate_landmarks(preferences=preferences, coordinates=start.location) landmarks, landmarks_short = generate_landmarks(preferences=preferences, coordinates=start.location)
#write_data(landmarks, "landmarks.txt") #write_data(landmarks, "landmarks_Wien.txt")
# Insert start and finish to the landmarks list # Insert start and finish to the landmarks list
landmarks_short.insert(0, start) landmarks_short.insert(0, start)
landmarks_short.append(finish) landmarks_short.append(finish)
# TODO use these parameters in another way max_walking_time = 180 # minutes
max_walking_time = 2 # hours detour = 0 # minutes
detour = 30 # minutes
# First stage optimization # First stage optimization
base_tour = solve_optimization(landmarks_short, max_walking_time*60, True) base_tour = solve_optimization(landmarks_short, max_walking_time, True)
# Second stage using linear optimization
refined_tour = refine_optimization(landmarks, base_tour, max_walking_time, detour, True)
# Second stage optimization
refined_tour = refine_optimization(landmarks, base_tour, max_walking_time*60+detour, True)
return refined_tour return refined_tour
test4(tuple((48.8344400, 2.3220540))) # Café Chez César #test4(tuple((48.8344400, 2.3220540))) # Café Chez César
#test4(tuple((48.8375946, 2.2949904))) # Point random #test4(tuple((48.8375946, 2.2949904))) # Point random
#test4(tuple((47.377859, 8.540585))) # Zurich HB #test4(tuple((47.377859, 8.540585))) # Zurich HB
#test3('Vienna, Austria') #test4(tuple((45.7576485, 4.8330241))) # Lyon Bellecour
test4(tuple((48.5848435, 7.7332974))) # Strasbourg Gare
#test4(tuple((48.2067858, 16.3692340))) # Vienne

0
backend/throttle.ctrl Normal file
View File

File diff suppressed because it is too large Load Diff

View File

@ -1,482 +0,0 @@
{
"0":{
"name":"Atelier Brancusi",
"type":{
"landmark_type":"sightseeing"
},
"location":[
48.8614029,
2.3519903
],
"osm_type":"way",
"osm_id":55503399,
"attractiveness":13,
"must_do":false,
"n_tags":13,
"time_to_reach":0
},
"1":{
"name":"Musée de Cluny",
"type":{
"landmark_type":"sightseeing"
},
"location":[
48.8506604,
2.3437398
],
"osm_type":"way",
"osm_id":56640163,
"attractiveness":18,
"must_do":false,
"n_tags":18,
"time_to_reach":0
},
"2":{
"name":"Musée du Luxembourg",
"type":{
"landmark_type":"sightseeing"
},
"location":[
48.8485965,
2.3340156
],
"osm_type":"way",
"osm_id":170226810,
"attractiveness":15,
"must_do":false,
"n_tags":15,
"time_to_reach":0
},
"3":{
"name":"Musée national Eugène Delacroix",
"type":{
"landmark_type":"sightseeing"
},
"location":[
48.8546662,
2.3353836
],
"osm_type":"way",
"osm_id":395785603,
"attractiveness":15,
"must_do":false,
"n_tags":15,
"time_to_reach":0
},
"4":{
"name":"Hôtel de Sully",
"type":{
"landmark_type":"sightseeing"
},
"location":[
48.854635,
2.3638126
],
"osm_type":"relation",
"osm_id":403146,
"attractiveness":14,
"must_do":false,
"n_tags":13,
"time_to_reach":0
},
"5":{
"name":"Hôtel de la Monnaie",
"type":{
"landmark_type":"sightseeing"
},
"location":[
48.856403,
2.3388625
],
"osm_type":"relation",
"osm_id":967664,
"attractiveness":11,
"must_do":false,
"n_tags":11,
"time_to_reach":0
},
"6":{
"name":"Musée Bourdelle",
"type":{
"landmark_type":"sightseeing"
},
"location":[
48.8432078,
2.3186583
],
"osm_type":"relation",
"osm_id":1212876,
"attractiveness":23,
"must_do":false,
"n_tags":23,
"time_to_reach":0
},
"7":{
"name":"Musée Carnavalet",
"type":{
"landmark_type":"sightseeing"
},
"location":[
48.8576819,
2.3627147
],
"osm_type":"relation",
"osm_id":2405955,
"attractiveness":25,
"must_do":false,
"n_tags":25,
"time_to_reach":0
},
"8":{
"name":"Pont Neuf",
"type":{
"landmark_type":"sightseeing"
},
"location":[
48.8565248,
2.3408132
],
"osm_type":"way",
"osm_id":53574149,
"attractiveness":16,
"must_do":false,
"n_tags":15,
"time_to_reach":0
},
"9":{
"name":"Jardin du Luxembourg",
"type":{
"landmark_type":"sightseeing"
},
"location":[
48.8467137,
2.3363649
],
"osm_type":"way",
"osm_id":128206209,
"attractiveness":35,
"must_do":false,
"n_tags":23,
"time_to_reach":0
},
"10":{
"name":"Cathédrale Notre-Dame de Paris",
"type":{
"landmark_type":"sightseeing"
},
"location":[
48.8529372,
2.3498701
],
"osm_type":"way",
"osm_id":201611261,
"attractiveness":55,
"must_do":false,
"n_tags":54,
"time_to_reach":0
},
"11":{
"name":"Maison à l'enseigne du Faucheur",
"type":{
"landmark_type":"sightseeing"
},
"location":[
48.8558553,
2.3568266
],
"osm_type":"way",
"osm_id":1123456865,
"attractiveness":13,
"must_do":false,
"n_tags":11,
"time_to_reach":0
},
"12":{
"name":"Maison à l'enseigne du Mouton",
"type":{
"landmark_type":"sightseeing"
},
"location":[
48.8558431,
2.3568914
],
"osm_type":"way",
"osm_id":1123456866,
"attractiveness":13,
"must_do":false,
"n_tags":11,
"time_to_reach":0
},
"13":{
"name":"Palais de Justice de Paris",
"type":{
"landmark_type":"sightseeing"
},
"location":[
48.8556537,
2.3446072
],
"osm_type":"relation",
"osm_id":536982,
"attractiveness":24,
"must_do":false,
"n_tags":24,
"time_to_reach":0
},
"14":{
"name":"Mémorial des Martyrs de la Déportation",
"type":{
"landmark_type":"sightseeing"
},
"location":[
48.8517365,
2.3524734
],
"osm_type":"relation",
"osm_id":9396191,
"attractiveness":21,
"must_do":false,
"n_tags":21,
"time_to_reach":0
},
"15":{
"name":"Fontaine des Innocents",
"type":{
"landmark_type":"sightseeing"
},
"location":[
48.8606368,
2.3480233
],
"osm_type":"way",
"osm_id":52469222,
"attractiveness":16,
"must_do":false,
"n_tags":15,
"time_to_reach":0
},
"16":{
"name":"Hôtel de Sens",
"type":{
"landmark_type":"sightseeing"
},
"location":[
48.8535257,
2.3588733
],
"osm_type":"way",
"osm_id":55541122,
"attractiveness":21,
"must_do":false,
"n_tags":20,
"time_to_reach":0
},
"17":{
"name":"Hôtel d'Ourscamp",
"type":{
"landmark_type":"sightseeing"
},
"location":[
48.8555465,
2.3571206
],
"osm_type":"way",
"osm_id":55620201,
"attractiveness":10,
"must_do":false,
"n_tags":9,
"time_to_reach":0
},
"18":{
"name":"Hôtel de Choiseul-Praslin",
"type":{
"landmark_type":"sightseeing"
},
"location":[
48.8478008,
2.3203873
],
"osm_type":"way",
"osm_id":65756922,
"attractiveness":12,
"must_do":false,
"n_tags":12,
"time_to_reach":0
},
"19":{
"name":"Chapelle Notre-Dame-des-Anges",
"type":{
"landmark_type":"sightseeing"
},
"location":[
48.8462836,
2.3235558
],
"osm_type":"way",
"osm_id":219378497,
"attractiveness":16,
"must_do":false,
"n_tags":16,
"time_to_reach":0
},
"20":{
"name":"Fontaine du Palmier",
"type":{
"landmark_type":"sightseeing"
},
"location":[
48.8575005,
2.3472864
],
"osm_type":"way",
"osm_id":261092850,
"attractiveness":23,
"must_do":false,
"n_tags":14,
"time_to_reach":0
},
"21":{
"name":"Église Saint-Séverin",
"type":{
"landmark_type":"sightseeing"
},
"location":[
48.8520913,
2.3457237
],
"osm_type":"way",
"osm_id":19740659,
"attractiveness":15,
"must_do":false,
"n_tags":25,
"time_to_reach":0
},
"22":{
"name":"Église Orthodoxe Roumaine des Saints Archanges",
"type":{
"landmark_type":"sightseeing"
},
"location":[
48.849488,
2.3471975
],
"osm_type":"way",
"osm_id":55366403,
"attractiveness":10,
"must_do":false,
"n_tags":16,
"time_to_reach":0
},
"23":{
"name":"Église Saint-Merri",
"type":{
"landmark_type":"sightseeing"
},
"location":[
48.8590777,
2.3508448
],
"osm_type":"way",
"osm_id":55742120,
"attractiveness":16,
"must_do":false,
"n_tags":26,
"time_to_reach":0
},
"24":{
"name":"Église Saint-Germain des Prés",
"type":{
"landmark_type":"sightseeing"
},
"location":[
48.8539667,
2.334463
],
"osm_type":"way",
"osm_id":62287173,
"attractiveness":12,
"must_do":false,
"n_tags":21,
"time_to_reach":0
},
"25":{
"name":"Square de la Tour Saint-Jacques",
"type":{
"landmark_type":"nature"
},
"location":[
48.857913,
2.3487608
],
"osm_type":"way",
"osm_id":15895172,
"attractiveness":19,
"must_do":false,
"n_tags":12,
"time_to_reach":0
},
"26":{
"name":"Square Jean XXIII",
"type":{
"landmark_type":"nature"
},
"location":[
48.8523775,
2.3503406
],
"osm_type":"way",
"osm_id":20444455,
"attractiveness":23,
"must_do":false,
"n_tags":15,
"time_to_reach":0
},
"27":{
"name":"Square Félix Desruelles",
"type":{
"landmark_type":"nature"
},
"location":[
48.8536974,
2.3345069
],
"osm_type":"way",
"osm_id":62287123,
"attractiveness":12,
"must_do":false,
"n_tags":7,
"time_to_reach":0
},
"28":{
"name":"Jardin des Rosiers Joseph-Migneret",
"type":{
"landmark_type":"nature"
},
"location":[
48.8572946,
2.3602516
],
"osm_type":"way",
"osm_id":365878540,
"attractiveness":14,
"must_do":false,
"n_tags":8,
"time_to_reach":0
},
"29":{
"name":"Jardin du Père-Armand-David",
"type":{
"landmark_type":"nature"
},
"location":[
48.8478674,
2.3220972
],
"osm_type":"way",
"osm_id":588324415,
"attractiveness":10,
"must_do":false,
"n_tags":7,
"time_to_reach":0
}
}