Merge branch 'feature/backend/initial-deployment'
This commit is contained in:
commit
4a291a69c9
@ -2,6 +2,8 @@ on:
|
||||
pull_request:
|
||||
branches:
|
||||
- main
|
||||
paths:
|
||||
- backend/**
|
||||
|
||||
name: Build and push docker image
|
||||
|
@ -6,6 +6,12 @@ COPY Pipfile Pipfile.lock .
|
||||
RUN pip install pipenv
|
||||
RUN pipenv install --deploy --system
|
||||
|
||||
COPY . /src
|
||||
COPY src src
|
||||
|
||||
CMD ["pipenv", "run", "python", "/app/src/main.py"]
|
||||
EXPOSE 8000
|
||||
|
||||
# Set environment variables used by the deployment. These can be overridden by the user using this image.
|
||||
ENV NUM_WORKERS=1
|
||||
ENV OSM_CACHE_DIR=/cache
|
||||
|
||||
CMD ["pipenv", "run", "fastapi", "run", "src/main.py", '--port 8000', '--workers $NUM_WORKERS']
|
||||
|
@ -7,7 +7,6 @@ name = "pypi"
|
||||
numpy = "*"
|
||||
scipy = "*"
|
||||
fastapi = "*"
|
||||
osmpythontools = "*"
|
||||
pydantic = "*"
|
||||
shapely = "*"
|
||||
networkx = "*"
|
||||
|
511
backend/Pipfile.lock
generated
511
backend/Pipfile.lock
generated
@ -30,14 +30,6 @@
|
||||
"markers": "python_version >= '3.8'",
|
||||
"version": "==4.4.0"
|
||||
},
|
||||
"beautifulsoup4": {
|
||||
"hashes": [
|
||||
"sha256:74e3d1928edc070d21748185c46e3fb33490f22f52a3addee9aee0f4f7781051",
|
||||
"sha256:b80878c9f40111313e55da8ba20bdba06d8fa3969fc68304167741bbf9e082ed"
|
||||
],
|
||||
"markers": "python_full_version >= '3.6.0'",
|
||||
"version": "==4.12.3"
|
||||
},
|
||||
"certifi": {
|
||||
"hashes": [
|
||||
"sha256:5a1e7645bc0ec61a09e26c36f6106dd4cf40c6db3a1fb6352b0244e7fb057c7b",
|
||||
@ -142,6 +134,102 @@
|
||||
"markers": "python_full_version >= '3.7.0'",
|
||||
"version": "==3.3.2"
|
||||
},
|
||||
"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": {
|
||||
"hashes": [
|
||||
"sha256:ae74fb96c20a0277a1d615f1e4d73c8414f5a98db8b799a7931d1582f3390c28",
|
||||
@ -150,64 +238,6 @@
|
||||
"markers": "python_version >= '3.7'",
|
||||
"version": "==8.1.7"
|
||||
},
|
||||
"contourpy": {
|
||||
"hashes": [
|
||||
"sha256:00e5388f71c1a0610e6fe56b5c44ab7ba14165cdd6d695429c5cd94021e390b2",
|
||||
"sha256:10a37ae557aabf2509c79715cd20b62e4c7c28b8cd62dd7d99e5ed3ce28c3fd9",
|
||||
"sha256:11959f0ce4a6f7b76ec578576a0b61a28bdc0696194b6347ba3f1c53827178b9",
|
||||
"sha256:187fa1d4c6acc06adb0fae5544c59898ad781409e61a926ac7e84b8f276dcef4",
|
||||
"sha256:1a07fc092a4088ee952ddae19a2b2a85757b923217b7eed584fdf25f53a6e7ce",
|
||||
"sha256:1cac0a8f71a041aa587410424ad46dfa6a11f6149ceb219ce7dd48f6b02b87a7",
|
||||
"sha256:1d59e739ab0e3520e62a26c60707cc3ab0365d2f8fecea74bfe4de72dc56388f",
|
||||
"sha256:2855c8b0b55958265e8b5888d6a615ba02883b225f2227461aa9127c578a4922",
|
||||
"sha256:2e785e0f2ef0d567099b9ff92cbfb958d71c2d5b9259981cd9bee81bd194c9a4",
|
||||
"sha256:309be79c0a354afff9ff7da4aaed7c3257e77edf6c1b448a779329431ee79d7e",
|
||||
"sha256:39f3ecaf76cd98e802f094e0d4fbc6dc9c45a8d0c4d185f0f6c2234e14e5f75b",
|
||||
"sha256:457499c79fa84593f22454bbd27670227874cd2ff5d6c84e60575c8b50a69619",
|
||||
"sha256:49e70d111fee47284d9dd867c9bb9a7058a3c617274900780c43e38d90fe1205",
|
||||
"sha256:4c75507d0a55378240f781599c30e7776674dbaf883a46d1c90f37e563453480",
|
||||
"sha256:4c863140fafc615c14a4bf4efd0f4425c02230eb8ef02784c9a156461e62c965",
|
||||
"sha256:4d8908b3bee1c889e547867ca4cdc54e5ab6be6d3e078556814a22457f49423c",
|
||||
"sha256:5b9eb0ca724a241683c9685a484da9d35c872fd42756574a7cfbf58af26677fd",
|
||||
"sha256:6022cecf8f44e36af10bd9118ca71f371078b4c168b6e0fab43d4a889985dbb5",
|
||||
"sha256:6150ffa5c767bc6332df27157d95442c379b7dce3a38dff89c0f39b63275696f",
|
||||
"sha256:62828cada4a2b850dbef89c81f5a33741898b305db244904de418cc957ff05dc",
|
||||
"sha256:7b4182299f251060996af5249c286bae9361fa8c6a9cda5efc29fe8bfd6062ec",
|
||||
"sha256:94b34f32646ca0414237168d68a9157cb3889f06b096612afdd296003fdd32fd",
|
||||
"sha256:9ce6889abac9a42afd07a562c2d6d4b2b7134f83f18571d859b25624a331c90b",
|
||||
"sha256:9cffe0f850e89d7c0012a1fb8730f75edd4320a0a731ed0c183904fe6ecfc3a9",
|
||||
"sha256:a12a813949e5066148712a0626895c26b2578874e4cc63160bb007e6df3436fe",
|
||||
"sha256:a1eea9aecf761c661d096d39ed9026574de8adb2ae1c5bd7b33558af884fb2ce",
|
||||
"sha256:a31f94983fecbac95e58388210427d68cd30fe8a36927980fab9c20062645609",
|
||||
"sha256:ac58bdee53cbeba2ecad824fa8159493f0bf3b8ea4e93feb06c9a465d6c87da8",
|
||||
"sha256:af3f4485884750dddd9c25cb7e3915d83c2db92488b38ccb77dd594eac84c4a0",
|
||||
"sha256:b33d2bc4f69caedcd0a275329eb2198f560b325605810895627be5d4b876bf7f",
|
||||
"sha256:b59c0ffceff8d4d3996a45f2bb6f4c207f94684a96bf3d9728dbb77428dd8cb8",
|
||||
"sha256:bb6834cbd983b19f06908b45bfc2dad6ac9479ae04abe923a275b5f48f1a186b",
|
||||
"sha256:bd3db01f59fdcbce5b22afad19e390260d6d0222f35a1023d9adc5690a889364",
|
||||
"sha256:bd7c23df857d488f418439686d3b10ae2fbf9bc256cd045b37a8c16575ea1040",
|
||||
"sha256:c2528d60e398c7c4c799d56f907664673a807635b857df18f7ae64d3e6ce2d9f",
|
||||
"sha256:d31a63bc6e6d87f77d71e1abbd7387ab817a66733734883d1fc0021ed9bfa083",
|
||||
"sha256:d4492d82b3bc7fbb7e3610747b159869468079fe149ec5c4d771fa1f614a14df",
|
||||
"sha256:ddcb8581510311e13421b1f544403c16e901c4e8f09083c881fab2be80ee31ba",
|
||||
"sha256:e1d59258c3c67c865435d8fbeb35f8c59b8bef3d6f46c1f29f6123556af28445",
|
||||
"sha256:eb3315a8a236ee19b6df481fc5f997436e8ade24a9f03dfdc6bd490fea20c6da",
|
||||
"sha256:ef2b055471c0eb466033760a521efb9d8a32b99ab907fc8358481a1dd29e3bd3",
|
||||
"sha256:ef5adb9a3b1d0c645ff694f9bca7702ec2c70f4d734f9922ea34de02294fdf72",
|
||||
"sha256:f32c38afb74bd98ce26de7cc74a67b40afb7b05aae7b42924ea990d51e4dac02",
|
||||
"sha256:fe0ccca550bb8e5abc22f530ec0466136379c01321fd94f30a22231e8a48d985"
|
||||
],
|
||||
"markers": "python_version >= '3.9'",
|
||||
"version": "==1.2.1"
|
||||
},
|
||||
"cycler": {
|
||||
"hashes": [
|
||||
"sha256:85cef7cff222d8644161529808465972e51340599459b8ac3ccbac5a854e0d30",
|
||||
"sha256:88bb128f02ba341da8ef447245a9e138fae777f6a23943da4540077d3601eb1c"
|
||||
],
|
||||
"markers": "python_version >= '3.8'",
|
||||
"version": "==0.12.1"
|
||||
},
|
||||
"dnspython": {
|
||||
"hashes": [
|
||||
"sha256:5ef3b9680161f6fa89daf8ad451b5f1a33b18ae8a1c6778cdf4b43f08c0a6e50",
|
||||
@ -249,7 +279,7 @@
|
||||
"markers": "python_version >= '3.8'",
|
||||
"version": "==0.0.4"
|
||||
},
|
||||
"fonttools": {
|
||||
"geopandas": {
|
||||
"hashes": [
|
||||
"sha256:02569e9a810f9d11f4ae82c391ebc6fb5730d95a0657d24d754ed7763fb2d122",
|
||||
"sha256:0679a30b59d74b6242909945429dbddb08496935b82f91ea9bf6ad240ec23397",
|
||||
@ -403,264 +433,6 @@
|
||||
"markers": "python_version >= '3.7'",
|
||||
"version": "==3.1.4"
|
||||
},
|
||||
"kiwisolver": {
|
||||
"hashes": [
|
||||
"sha256:00bd361b903dc4bbf4eb165f24d1acbee754fce22ded24c3d56eec268658a5cf",
|
||||
"sha256:040c1aebeda72197ef477a906782b5ab0d387642e93bda547336b8957c61022e",
|
||||
"sha256:05703cf211d585109fcd72207a31bb170a0f22144d68298dc5e61b3c946518af",
|
||||
"sha256:06f54715b7737c2fecdbf140d1afb11a33d59508a47bf11bb38ecf21dc9ab79f",
|
||||
"sha256:0dc9db8e79f0036e8173c466d21ef18e1befc02de8bf8aa8dc0813a6dc8a7046",
|
||||
"sha256:0f114aa76dc1b8f636d077979c0ac22e7cd8f3493abbab152f20eb8d3cda71f3",
|
||||
"sha256:11863aa14a51fd6ec28688d76f1735f8f69ab1fabf388851a595d0721af042f5",
|
||||
"sha256:11c7de8f692fc99816e8ac50d1d1aef4f75126eefc33ac79aac02c099fd3db71",
|
||||
"sha256:11d011a7574eb3b82bcc9c1a1d35c1d7075677fdd15de527d91b46bd35e935ee",
|
||||
"sha256:146d14bebb7f1dc4d5fbf74f8a6cb15ac42baadee8912eb84ac0b3b2a3dc6ac3",
|
||||
"sha256:15568384086b6df3c65353820a4473575dbad192e35010f622c6ce3eebd57af9",
|
||||
"sha256:19df6e621f6d8b4b9c4d45f40a66839294ff2bb235e64d2178f7522d9170ac5b",
|
||||
"sha256:1b04139c4236a0f3aff534479b58f6f849a8b351e1314826c2d230849ed48985",
|
||||
"sha256:210ef2c3a1f03272649aff1ef992df2e724748918c4bc2d5a90352849eb40bea",
|
||||
"sha256:2270953c0d8cdab5d422bee7d2007f043473f9d2999631c86a223c9db56cbd16",
|
||||
"sha256:2400873bccc260b6ae184b2b8a4fec0e4082d30648eadb7c3d9a13405d861e89",
|
||||
"sha256:2a40773c71d7ccdd3798f6489aaac9eee213d566850a9533f8d26332d626b82c",
|
||||
"sha256:2c5674c4e74d939b9d91dda0fae10597ac7521768fec9e399c70a1f27e2ea2d9",
|
||||
"sha256:3195782b26fc03aa9c6913d5bad5aeb864bdc372924c093b0f1cebad603dd712",
|
||||
"sha256:31a82d498054cac9f6d0b53d02bb85811185bcb477d4b60144f915f3b3126342",
|
||||
"sha256:32d5cf40c4f7c7b3ca500f8985eb3fb3a7dfc023215e876f207956b5ea26632a",
|
||||
"sha256:346f5343b9e3f00b8db8ba359350eb124b98c99efd0b408728ac6ebf38173958",
|
||||
"sha256:378a214a1e3bbf5ac4a8708304318b4f890da88c9e6a07699c4ae7174c09a68d",
|
||||
"sha256:39b42c68602539407884cf70d6a480a469b93b81b7701378ba5e2328660c847a",
|
||||
"sha256:3a2b053a0ab7a3960c98725cfb0bf5b48ba82f64ec95fe06f1d06c99b552e130",
|
||||
"sha256:3aba7311af82e335dd1e36ffff68aaca609ca6290c2cb6d821a39aa075d8e3ff",
|
||||
"sha256:3cd32d6c13807e5c66a7cbb79f90b553642f296ae4518a60d8d76243b0ad2898",
|
||||
"sha256:3edd2fa14e68c9be82c5b16689e8d63d89fe927e56debd6e1dbce7a26a17f81b",
|
||||
"sha256:4c380469bd3f970ef677bf2bcba2b6b0b4d5c75e7a020fb863ef75084efad66f",
|
||||
"sha256:4e66e81a5779b65ac21764c295087de82235597a2293d18d943f8e9e32746265",
|
||||
"sha256:53abb58632235cd154176ced1ae8f0d29a6657aa1aa9decf50b899b755bc2b93",
|
||||
"sha256:5794cf59533bc3f1b1c821f7206a3617999db9fbefc345360aafe2e067514929",
|
||||
"sha256:59415f46a37f7f2efeec758353dd2eae1b07640d8ca0f0c42548ec4125492635",
|
||||
"sha256:59ec7b7c7e1a61061850d53aaf8e93db63dce0c936db1fda2658b70e4a1be709",
|
||||
"sha256:59edc41b24031bc25108e210c0def6f6c2191210492a972d585a06ff246bb79b",
|
||||
"sha256:5a580c91d686376f0f7c295357595c5a026e6cbc3d77b7c36e290201e7c11ecb",
|
||||
"sha256:5b94529f9b2591b7af5f3e0e730a4e0a41ea174af35a4fd067775f9bdfeee01a",
|
||||
"sha256:5c7b3b3a728dc6faf3fc372ef24f21d1e3cee2ac3e9596691d746e5a536de920",
|
||||
"sha256:5c90ae8c8d32e472be041e76f9d2f2dbff4d0b0be8bd4041770eddb18cf49a4e",
|
||||
"sha256:5e7139af55d1688f8b960ee9ad5adafc4ac17c1c473fe07133ac092310d76544",
|
||||
"sha256:5ff5cf3571589b6d13bfbfd6bcd7a3f659e42f96b5fd1c4830c4cf21d4f5ef45",
|
||||
"sha256:620ced262a86244e2be10a676b646f29c34537d0d9cc8eb26c08f53d98013390",
|
||||
"sha256:6512cb89e334e4700febbffaaa52761b65b4f5a3cf33f960213d5656cea36a77",
|
||||
"sha256:6c08e1312a9cf1074d17b17728d3dfce2a5125b2d791527f33ffbe805200a355",
|
||||
"sha256:6c3bd3cde54cafb87d74d8db50b909705c62b17c2099b8f2e25b461882e544ff",
|
||||
"sha256:6ef7afcd2d281494c0a9101d5c571970708ad911d028137cd558f02b851c08b4",
|
||||
"sha256:7269d9e5f1084a653d575c7ec012ff57f0c042258bf5db0954bf551c158466e7",
|
||||
"sha256:72d40b33e834371fd330fb1472ca19d9b8327acb79a5821d4008391db8e29f20",
|
||||
"sha256:74d1b44c6cfc897df648cc9fdaa09bc3e7679926e6f96df05775d4fb3946571c",
|
||||
"sha256:74db36e14a7d1ce0986fa104f7d5637aea5c82ca6326ed0ec5694280942d1162",
|
||||
"sha256:763773d53f07244148ccac5b084da5adb90bfaee39c197554f01b286cf869228",
|
||||
"sha256:76c6a5964640638cdeaa0c359382e5703e9293030fe730018ca06bc2010c4437",
|
||||
"sha256:76d9289ed3f7501012e05abb8358bbb129149dbd173f1f57a1bf1c22d19ab7cc",
|
||||
"sha256:7931d8f1f67c4be9ba1dd9c451fb0eeca1a25b89e4d3f89e828fe12a519b782a",
|
||||
"sha256:7b8b454bac16428b22560d0a1cf0a09875339cab69df61d7805bf48919415901",
|
||||
"sha256:7e5bab140c309cb3a6ce373a9e71eb7e4873c70c2dda01df6820474f9889d6d4",
|
||||
"sha256:83d78376d0d4fd884e2c114d0621624b73d2aba4e2788182d286309ebdeed770",
|
||||
"sha256:852542f9481f4a62dbb5dd99e8ab7aedfeb8fb6342349a181d4036877410f525",
|
||||
"sha256:85267bd1aa8880a9c88a8cb71e18d3d64d2751a790e6ca6c27b8ccc724bcd5ad",
|
||||
"sha256:88a2df29d4724b9237fc0c6eaf2a1adae0cdc0b3e9f4d8e7dc54b16812d2d81a",
|
||||
"sha256:88b9f257ca61b838b6f8094a62418421f87ac2a1069f7e896c36a7d86b5d4c29",
|
||||
"sha256:8ab3919a9997ab7ef2fbbed0cc99bb28d3c13e6d4b1ad36e97e482558a91be90",
|
||||
"sha256:92dea1ffe3714fa8eb6a314d2b3c773208d865a0e0d35e713ec54eea08a66250",
|
||||
"sha256:9407b6a5f0d675e8a827ad8742e1d6b49d9c1a1da5d952a67d50ef5f4170b18d",
|
||||
"sha256:9408acf3270c4b6baad483865191e3e582b638b1654a007c62e3efe96f09a9a3",
|
||||
"sha256:955e8513d07a283056b1396e9a57ceddbd272d9252c14f154d450d227606eb54",
|
||||
"sha256:9db8ea4c388fdb0f780fe91346fd438657ea602d58348753d9fb265ce1bca67f",
|
||||
"sha256:9eaa8b117dc8337728e834b9c6e2611f10c79e38f65157c4c38e9400286f5cb1",
|
||||
"sha256:a51a263952b1429e429ff236d2f5a21c5125437861baeed77f5e1cc2d2c7c6da",
|
||||
"sha256:a6aa6315319a052b4ee378aa171959c898a6183f15c1e541821c5c59beaa0238",
|
||||
"sha256:aa12042de0171fad672b6c59df69106d20d5596e4f87b5e8f76df757a7c399aa",
|
||||
"sha256:aaf7be1207676ac608a50cd08f102f6742dbfc70e8d60c4db1c6897f62f71523",
|
||||
"sha256:b0157420efcb803e71d1b28e2c287518b8808b7cf1ab8af36718fd0a2c453eb0",
|
||||
"sha256:b3f7e75f3015df442238cca659f8baa5f42ce2a8582727981cbfa15fee0ee205",
|
||||
"sha256:b9098e0049e88c6a24ff64545cdfc50807818ba6c1b739cae221bbbcbc58aad3",
|
||||
"sha256:ba55dce0a9b8ff59495ddd050a0225d58bd0983d09f87cfe2b6aec4f2c1234e4",
|
||||
"sha256:bb86433b1cfe686da83ce32a9d3a8dd308e85c76b60896d58f082136f10bffac",
|
||||
"sha256:bbea0db94288e29afcc4c28afbf3a7ccaf2d7e027489c449cf7e8f83c6346eb9",
|
||||
"sha256:bbf1d63eef84b2e8c89011b7f2235b1e0bf7dacc11cac9431fc6468e99ac77fb",
|
||||
"sha256:c7940c1dc63eb37a67721b10d703247552416f719c4188c54e04334321351ced",
|
||||
"sha256:c9bf3325c47b11b2e51bca0824ea217c7cd84491d8ac4eefd1e409705ef092bd",
|
||||
"sha256:cdc8a402aaee9a798b50d8b827d7ecf75edc5fb35ea0f91f213ff927c15f4ff0",
|
||||
"sha256:ceec1a6bc6cab1d6ff5d06592a91a692f90ec7505d6463a88a52cc0eb58545da",
|
||||
"sha256:cfe6ab8da05c01ba6fbea630377b5da2cd9bcbc6338510116b01c1bc939a2c18",
|
||||
"sha256:d099e745a512f7e3bbe7249ca835f4d357c586d78d79ae8f1dcd4d8adeb9bda9",
|
||||
"sha256:d0ef46024e6a3d79c01ff13801cb19d0cad7fd859b15037aec74315540acc276",
|
||||
"sha256:d2e5a98f0ec99beb3c10e13b387f8db39106d53993f498b295f0c914328b1333",
|
||||
"sha256:da4cfb373035def307905d05041c1d06d8936452fe89d464743ae7fb8371078b",
|
||||
"sha256:da802a19d6e15dffe4b0c24b38b3af68e6c1a68e6e1d8f30148c83864f3881db",
|
||||
"sha256:dced8146011d2bc2e883f9bd68618b8247387f4bbec46d7392b3c3b032640126",
|
||||
"sha256:dfdd7c0b105af050eb3d64997809dc21da247cf44e63dc73ff0fd20b96be55a9",
|
||||
"sha256:e368f200bbc2e4f905b8e71eb38b3c04333bddaa6a2464a6355487b02bb7fb09",
|
||||
"sha256:e391b1f0a8a5a10ab3b9bb6afcfd74f2175f24f8975fb87ecae700d1503cdee0",
|
||||
"sha256:e57e563a57fb22a142da34f38acc2fc1a5c864bc29ca1517a88abc963e60d6ec",
|
||||
"sha256:e5d706eba36b4c4d5bc6c6377bb6568098765e990cfc21ee16d13963fab7b3e7",
|
||||
"sha256:ec20916e7b4cbfb1f12380e46486ec4bcbaa91a9c448b97023fde0d5bbf9e4ff",
|
||||
"sha256:f1d072c2eb0ad60d4c183f3fb44ac6f73fb7a8f16a2694a91f988275cbf352f9",
|
||||
"sha256:f846c260f483d1fd217fe5ed7c173fb109efa6b1fc8381c8b7552c5781756192",
|
||||
"sha256:f91de7223d4c7b793867797bacd1ee53bfe7359bd70d27b7b58a04efbb9436c8",
|
||||
"sha256:faae4860798c31530dd184046a900e652c95513796ef51a12bc086710c2eec4d",
|
||||
"sha256:fc579bf0f502e54926519451b920e875f433aceb4624a3646b3252b5caa9e0b6",
|
||||
"sha256:fcc700eadbbccbf6bc1bcb9dbe0786b4b1cb91ca0dcda336eef5c2beed37b797",
|
||||
"sha256:fd32ea360bcbb92d28933fc05ed09bffcb1704ba3fc7942e81db0fd4f81a7892",
|
||||
"sha256:fdb7adb641a0d13bdcd4ef48e062363d8a9ad4a182ac7647ec88f695e719ae9f"
|
||||
],
|
||||
"markers": "python_version >= '3.7'",
|
||||
"version": "==1.4.5"
|
||||
},
|
||||
"lxml": {
|
||||
"hashes": [
|
||||
"sha256:02437fb7308386867c8b7b0e5bc4cd4b04548b1c5d089ffb8e7b31009b961dc3",
|
||||
"sha256:02f6a8eb6512fdc2fd4ca10a49c341c4e109aa6e9448cc4859af5b949622715a",
|
||||
"sha256:05f8757b03208c3f50097761be2dea0aba02e94f0dc7023ed73a7bb14ff11eb0",
|
||||
"sha256:06668e39e1f3c065349c51ac27ae430719d7806c026fec462e5693b08b95696b",
|
||||
"sha256:07542787f86112d46d07d4f3c4e7c760282011b354d012dc4141cc12a68cef5f",
|
||||
"sha256:08ea0f606808354eb8f2dfaac095963cb25d9d28e27edcc375d7b30ab01abbf6",
|
||||
"sha256:0969e92af09c5687d769731e3f39ed62427cc72176cebb54b7a9d52cc4fa3b73",
|
||||
"sha256:0a028b61a2e357ace98b1615fc03f76eb517cc028993964fe08ad514b1e8892d",
|
||||
"sha256:0b3f5016e00ae7630a4b83d0868fca1e3d494c78a75b1c7252606a3a1c5fc2ad",
|
||||
"sha256:13e69be35391ce72712184f69000cda04fc89689429179bc4c0ae5f0b7a8c21b",
|
||||
"sha256:16a8326e51fcdffc886294c1e70b11ddccec836516a343f9ed0f82aac043c24a",
|
||||
"sha256:19b4e485cd07b7d83e3fe3b72132e7df70bfac22b14fe4bf7a23822c3a35bff5",
|
||||
"sha256:1a2569a1f15ae6c8c64108a2cd2b4a858fc1e13d25846be0666fc144715e32ab",
|
||||
"sha256:1a7aca7964ac4bb07680d5c9d63b9d7028cace3e2d43175cb50bba8c5ad33316",
|
||||
"sha256:1b590b39ef90c6b22ec0be925b211298e810b4856909c8ca60d27ffbca6c12e6",
|
||||
"sha256:1d8a701774dfc42a2f0b8ccdfe7dbc140500d1049e0632a611985d943fcf12df",
|
||||
"sha256:1e275ea572389e41e8b039ac076a46cb87ee6b8542df3fff26f5baab43713bca",
|
||||
"sha256:2304d3c93f2258ccf2cf7a6ba8c761d76ef84948d87bf9664e14d203da2cd264",
|
||||
"sha256:23441e2b5339bc54dc949e9e675fa35efe858108404ef9aa92f0456929ef6fe8",
|
||||
"sha256:23cfafd56887eaed93d07bc4547abd5e09d837a002b791e9767765492a75883f",
|
||||
"sha256:28bf95177400066596cdbcfc933312493799382879da504633d16cf60bba735b",
|
||||
"sha256:2eb2227ce1ff998faf0cd7fe85bbf086aa41dfc5af3b1d80867ecfe75fb68df3",
|
||||
"sha256:2fb0ba3e8566548d6c8e7dd82a8229ff47bd8fb8c2da237607ac8e5a1b8312e5",
|
||||
"sha256:303f540ad2dddd35b92415b74b900c749ec2010e703ab3bfd6660979d01fd4ed",
|
||||
"sha256:339ee4a4704bc724757cd5dd9dc8cf4d00980f5d3e6e06d5847c1b594ace68ab",
|
||||
"sha256:33ce9e786753743159799fdf8e92a5da351158c4bfb6f2db0bf31e7892a1feb5",
|
||||
"sha256:343ab62e9ca78094f2306aefed67dcfad61c4683f87eee48ff2fd74902447726",
|
||||
"sha256:34e17913c431f5ae01d8658dbf792fdc457073dcdfbb31dc0cc6ab256e664a8d",
|
||||
"sha256:364d03207f3e603922d0d3932ef363d55bbf48e3647395765f9bfcbdf6d23632",
|
||||
"sha256:38b67afb0a06b8575948641c1d6d68e41b83a3abeae2ca9eed2ac59892b36706",
|
||||
"sha256:3a745cc98d504d5bd2c19b10c79c61c7c3df9222629f1b6210c0368177589fb8",
|
||||
"sha256:3b019d4ee84b683342af793b56bb35034bd749e4cbdd3d33f7d1107790f8c472",
|
||||
"sha256:3b6a30a9ab040b3f545b697cb3adbf3696c05a3a68aad172e3fd7ca73ab3c835",
|
||||
"sha256:3d1e35572a56941b32c239774d7e9ad724074d37f90c7a7d499ab98761bd80cf",
|
||||
"sha256:3d98de734abee23e61f6b8c2e08a88453ada7d6486dc7cdc82922a03968928db",
|
||||
"sha256:453d037e09a5176d92ec0fd282e934ed26d806331a8b70ab431a81e2fbabf56d",
|
||||
"sha256:45f9494613160d0405682f9eee781c7e6d1bf45f819654eb249f8f46a2c22545",
|
||||
"sha256:4820c02195d6dfb7b8508ff276752f6b2ff8b64ae5d13ebe02e7667e035000b9",
|
||||
"sha256:49095a38eb333aaf44c06052fd2ec3b8f23e19747ca7ec6f6c954ffea6dbf7be",
|
||||
"sha256:4aefd911793b5d2d7a921233a54c90329bf3d4a6817dc465f12ffdfe4fc7b8fe",
|
||||
"sha256:4bc6cb140a7a0ad1f7bc37e018d0ed690b7b6520ade518285dc3171f7a117905",
|
||||
"sha256:4c30a2f83677876465f44c018830f608fa3c6a8a466eb223535035fbc16f3438",
|
||||
"sha256:50127c186f191b8917ea2fb8b206fbebe87fd414a6084d15568c27d0a21d60db",
|
||||
"sha256:50ccb5d355961c0f12f6cf24b7187dbabd5433f29e15147a67995474f27d1776",
|
||||
"sha256:519895c99c815a1a24a926d5b60627ce5ea48e9f639a5cd328bda0515ea0f10c",
|
||||
"sha256:54401c77a63cc7d6dc4b4e173bb484f28a5607f3df71484709fe037c92d4f0ed",
|
||||
"sha256:546cf886f6242dff9ec206331209db9c8e1643ae642dea5fdbecae2453cb50fd",
|
||||
"sha256:55ce6b6d803890bd3cc89975fca9de1dff39729b43b73cb15ddd933b8bc20484",
|
||||
"sha256:56793b7a1a091a7c286b5f4aa1fe4ae5d1446fe742d00cdf2ffb1077865db10d",
|
||||
"sha256:57f0a0bbc9868e10ebe874e9f129d2917750adf008fe7b9c1598c0fbbfdde6a6",
|
||||
"sha256:5b8c041b6265e08eac8a724b74b655404070b636a8dd6d7a13c3adc07882ef30",
|
||||
"sha256:5e097646944b66207023bc3c634827de858aebc226d5d4d6d16f0b77566ea182",
|
||||
"sha256:60499fe961b21264e17a471ec296dcbf4365fbea611bf9e303ab69db7159ce61",
|
||||
"sha256:610b5c77428a50269f38a534057444c249976433f40f53e3b47e68349cca1425",
|
||||
"sha256:625e3ef310e7fa3a761d48ca7ea1f9d8718a32b1542e727d584d82f4453d5eeb",
|
||||
"sha256:657a972f46bbefdbba2d4f14413c0d079f9ae243bd68193cb5061b9732fa54c1",
|
||||
"sha256:69ab77a1373f1e7563e0fb5a29a8440367dec051da6c7405333699d07444f511",
|
||||
"sha256:6a520b4f9974b0a0a6ed73c2154de57cdfd0c8800f4f15ab2b73238ffed0b36e",
|
||||
"sha256:6d68ce8e7b2075390e8ac1e1d3a99e8b6372c694bbe612632606d1d546794207",
|
||||
"sha256:6dcc3d17eac1df7859ae01202e9bb11ffa8c98949dcbeb1069c8b9a75917e01b",
|
||||
"sha256:6dfdc2bfe69e9adf0df4915949c22a25b39d175d599bf98e7ddf620a13678585",
|
||||
"sha256:739e36ef7412b2bd940f75b278749106e6d025e40027c0b94a17ef7968d55d56",
|
||||
"sha256:7429e7faa1a60cad26ae4227f4dd0459efde239e494c7312624ce228e04f6391",
|
||||
"sha256:74da9f97daec6928567b48c90ea2c82a106b2d500f397eeb8941e47d30b1ca85",
|
||||
"sha256:74e4f025ef3db1c6da4460dd27c118d8cd136d0391da4e387a15e48e5c975147",
|
||||
"sha256:75a9632f1d4f698b2e6e2e1ada40e71f369b15d69baddb8968dcc8e683839b18",
|
||||
"sha256:76acba4c66c47d27c8365e7c10b3d8016a7da83d3191d053a58382311a8bf4e1",
|
||||
"sha256:79d1fb9252e7e2cfe4de6e9a6610c7cbb99b9708e2c3e29057f487de5a9eaefa",
|
||||
"sha256:7ce7ad8abebe737ad6143d9d3bf94b88b93365ea30a5b81f6877ec9c0dee0a48",
|
||||
"sha256:7ed07b3062b055d7a7f9d6557a251cc655eed0b3152b76de619516621c56f5d3",
|
||||
"sha256:7ff762670cada8e05b32bf1e4dc50b140790909caa8303cfddc4d702b71ea184",
|
||||
"sha256:8268cbcd48c5375f46e000adb1390572c98879eb4f77910c6053d25cc3ac2c67",
|
||||
"sha256:875a3f90d7eb5c5d77e529080d95140eacb3c6d13ad5b616ee8095447b1d22e7",
|
||||
"sha256:89feb82ca055af0fe797a2323ec9043b26bc371365847dbe83c7fd2e2f181c34",
|
||||
"sha256:8a7e24cb69ee5f32e003f50e016d5fde438010c1022c96738b04fc2423e61706",
|
||||
"sha256:8ab6a358d1286498d80fe67bd3d69fcbc7d1359b45b41e74c4a26964ca99c3f8",
|
||||
"sha256:8b8df03a9e995b6211dafa63b32f9d405881518ff1ddd775db4e7b98fb545e1c",
|
||||
"sha256:8cf85a6e40ff1f37fe0f25719aadf443686b1ac7652593dc53c7ef9b8492b115",
|
||||
"sha256:8e8d351ff44c1638cb6e980623d517abd9f580d2e53bfcd18d8941c052a5a009",
|
||||
"sha256:9164361769b6ca7769079f4d426a41df6164879f7f3568be9086e15baca61466",
|
||||
"sha256:96e85aa09274955bb6bd483eaf5b12abadade01010478154b0ec70284c1b1526",
|
||||
"sha256:981a06a3076997adf7c743dcd0d7a0415582661e2517c7d961493572e909aa1d",
|
||||
"sha256:9cd5323344d8ebb9fb5e96da5de5ad4ebab993bbf51674259dbe9d7a18049525",
|
||||
"sha256:9d6c6ea6a11ca0ff9cd0390b885984ed31157c168565702959c25e2191674a14",
|
||||
"sha256:a02d3c48f9bb1e10c7788d92c0c7db6f2002d024ab6e74d6f45ae33e3d0288a3",
|
||||
"sha256:a233bb68625a85126ac9f1fc66d24337d6e8a0f9207b688eec2e7c880f012ec0",
|
||||
"sha256:a2f6a1bc2460e643785a2cde17293bd7a8f990884b822f7bca47bee0a82fc66b",
|
||||
"sha256:a6d17e0370d2516d5bb9062c7b4cb731cff921fc875644c3d751ad857ba9c5b1",
|
||||
"sha256:a6d2092797b388342c1bc932077ad232f914351932353e2e8706851c870bca1f",
|
||||
"sha256:ab67ed772c584b7ef2379797bf14b82df9aa5f7438c5b9a09624dd834c1c1aaf",
|
||||
"sha256:ac6540c9fff6e3813d29d0403ee7a81897f1d8ecc09a8ff84d2eea70ede1cdbf",
|
||||
"sha256:ae4073a60ab98529ab8a72ebf429f2a8cc612619a8c04e08bed27450d52103c0",
|
||||
"sha256:ae791f6bd43305aade8c0e22f816b34f3b72b6c820477aab4d18473a37e8090b",
|
||||
"sha256:aef5474d913d3b05e613906ba4090433c515e13ea49c837aca18bde190853dff",
|
||||
"sha256:b0b3f2df149efb242cee2ffdeb6674b7f30d23c9a7af26595099afaf46ef4e88",
|
||||
"sha256:b128092c927eaf485928cec0c28f6b8bead277e28acf56800e972aa2c2abd7a2",
|
||||
"sha256:b16db2770517b8799c79aa80f4053cd6f8b716f21f8aca962725a9565ce3ee40",
|
||||
"sha256:b336b0416828022bfd5a2e3083e7f5ba54b96242159f83c7e3eebaec752f1716",
|
||||
"sha256:b47633251727c8fe279f34025844b3b3a3e40cd1b198356d003aa146258d13a2",
|
||||
"sha256:b537bd04d7ccd7c6350cdaaaad911f6312cbd61e6e6045542f781c7f8b2e99d2",
|
||||
"sha256:b5e4ef22ff25bfd4ede5f8fb30f7b24446345f3e79d9b7455aef2836437bc38a",
|
||||
"sha256:b74b9ea10063efb77a965a8d5f4182806fbf59ed068b3c3fd6f30d2ac7bee734",
|
||||
"sha256:bb2dc4898180bea79863d5487e5f9c7c34297414bad54bcd0f0852aee9cfdb87",
|
||||
"sha256:bbc4b80af581e18568ff07f6395c02114d05f4865c2812a1f02f2eaecf0bfd48",
|
||||
"sha256:bcc98f911f10278d1daf14b87d65325851a1d29153caaf146877ec37031d5f36",
|
||||
"sha256:be49ad33819d7dcc28a309b86d4ed98e1a65f3075c6acd3cd4fe32103235222b",
|
||||
"sha256:bec4bd9133420c5c52d562469c754f27c5c9e36ee06abc169612c959bd7dbb07",
|
||||
"sha256:c2faf60c583af0d135e853c86ac2735ce178f0e338a3c7f9ae8f622fd2eb788c",
|
||||
"sha256:c689d0d5381f56de7bd6966a4541bff6e08bf8d3871bbd89a0c6ab18aa699573",
|
||||
"sha256:c7079d5eb1c1315a858bbf180000757db8ad904a89476653232db835c3114001",
|
||||
"sha256:cb3942960f0beb9f46e2a71a3aca220d1ca32feb5a398656be934320804c0df9",
|
||||
"sha256:cd9e78285da6c9ba2d5c769628f43ef66d96ac3085e59b10ad4f3707980710d3",
|
||||
"sha256:cf2a978c795b54c539f47964ec05e35c05bd045db5ca1e8366988c7f2fe6b3ce",
|
||||
"sha256:d14a0d029a4e176795cef99c056d58067c06195e0c7e2dbb293bf95c08f772a3",
|
||||
"sha256:d237ba6664b8e60fd90b8549a149a74fcc675272e0e95539a00522e4ca688b04",
|
||||
"sha256:d26a618ae1766279f2660aca0081b2220aca6bd1aa06b2cf73f07383faf48927",
|
||||
"sha256:d28cb356f119a437cc58a13f8135ab8a4c8ece18159eb9194b0d269ec4e28083",
|
||||
"sha256:d4ed0c7cbecde7194cd3228c044e86bf73e30a23505af852857c09c24e77ec5d",
|
||||
"sha256:d83e2d94b69bf31ead2fa45f0acdef0757fa0458a129734f59f67f3d2eb7ef32",
|
||||
"sha256:d8bbcd21769594dbba9c37d3c819e2d5847656ca99c747ddb31ac1701d0c0ed9",
|
||||
"sha256:d9b342c76003c6b9336a80efcc766748a333573abf9350f4094ee46b006ec18f",
|
||||
"sha256:dc911208b18842a3a57266d8e51fc3cfaccee90a5351b92079beed912a7914c2",
|
||||
"sha256:dfa7c241073d8f2b8e8dbc7803c434f57dbb83ae2a3d7892dd068d99e96efe2c",
|
||||
"sha256:e282aedd63c639c07c3857097fc0e236f984ceb4089a8b284da1c526491e3f3d",
|
||||
"sha256:e290d79a4107d7d794634ce3e985b9ae4f920380a813717adf61804904dc4393",
|
||||
"sha256:e3d9d13603410b72787579769469af730c38f2f25505573a5888a94b62b920f8",
|
||||
"sha256:e481bba1e11ba585fb06db666bfc23dbe181dbafc7b25776156120bf12e0d5a6",
|
||||
"sha256:e49b052b768bb74f58c7dda4e0bdf7b79d43a9204ca584ffe1fb48a6f3c84c66",
|
||||
"sha256:eb00b549b13bd6d884c863554566095bf6fa9c3cecb2e7b399c4bc7904cb33b5",
|
||||
"sha256:ec87c44f619380878bd49ca109669c9f221d9ae6883a5bcb3616785fa8f94c97",
|
||||
"sha256:edcfa83e03370032a489430215c1e7783128808fd3e2e0a3225deee278585196",
|
||||
"sha256:f11ae142f3a322d44513de1018b50f474f8f736bc3cd91d969f464b5bfef8836",
|
||||
"sha256:f2a09f6184f17a80897172863a655467da2b11151ec98ba8d7af89f17bf63dae",
|
||||
"sha256:f5b65529bb2f21ac7861a0e94fdbf5dc0daab41497d18223b46ee8515e5ad297",
|
||||
"sha256:f60fdd125d85bf9c279ffb8e94c78c51b3b6a37711464e1f5f31078b45002421",
|
||||
"sha256:f61efaf4bed1cc0860e567d2ecb2363974d414f7f1f124b1df368bbf183453a6",
|
||||
"sha256:f90e552ecbad426eab352e7b2933091f2be77115bb16f09f78404861c8322981",
|
||||
"sha256:f956196ef61369f1685d14dad80611488d8dc1ef00be57c0c5a03064005b0f30",
|
||||
"sha256:fb91819461b1b56d06fa4bcf86617fac795f6a99d12239fb0c68dbeba41a0a30",
|
||||
"sha256:fbc9d316552f9ef7bba39f4edfad4a734d3d6f93341232a9dddadec4f15d425f",
|
||||
"sha256:ff69a9a0b4b17d78170c73abe2ab12084bdf1691550c5629ad1fe7849433f324",
|
||||
"sha256:ffb2be176fed4457e445fe540617f0252a72a8bc56208fd65a690fdb1f57660b"
|
||||
],
|
||||
"markers": "python_version >= '3.6'",
|
||||
"version": "==5.2.2"
|
||||
},
|
||||
"markdown-it-py": {
|
||||
"hashes": [
|
||||
"sha256:355216845c60bd96232cd8d8c40e8f9765cc86f46880e43a8fd22dc1a1a8cab1",
|
||||
@ -874,10 +646,12 @@
|
||||
},
|
||||
"osmpythontools": {
|
||||
"hashes": [
|
||||
"sha256:13ff721f760fdad5dd78b4d1461d286b78bba96ee151a7301ee8c11a0c258be9"
|
||||
"sha256:22548d86d68d36edff3cf9ab76c45745cda86a4ea0b28442e107d6b42992a426",
|
||||
"sha256:ac67bea77b521941af648ef641ae1d006101948d1112475c256ea23ef31b426a"
|
||||
],
|
||||
"index": "pypi",
|
||||
"version": "==0.3.5"
|
||||
"markers": "python_version >= '3.8'",
|
||||
"version": "==1.9.3"
|
||||
},
|
||||
"packaging": {
|
||||
"hashes": [
|
||||
@ -1121,13 +895,70 @@
|
||||
"markers": "python_version >= '3.8'",
|
||||
"version": "==2.18.0"
|
||||
},
|
||||
"pyparsing": {
|
||||
"pyogrio": {
|
||||
"hashes": [
|
||||
"sha256:a1bac0ce561155ecc3ed78ca94d3c9378656ad4c94c1270de543f621420f94ad",
|
||||
"sha256:f9db75911801ed778fe61bb643079ff86601aca99fcae6345aa67292038fb742"
|
||||
"sha256:019731a856a9abfe909e86f50eb13f8362f6742337caf757c54b7c8acfe75b89",
|
||||
"sha256:083351b258b3e08b6c6085dac560bd321b68de5cb4a66229095da68d5f3d696b",
|
||||
"sha256:13642608a1cd67797ae8b5d792b0518d8ef3eb76506c8232ab5eaa1ea1159dff",
|
||||
"sha256:17420febc17651876d5140b54b24749aa751d482b5f9ef6267b8053e6e962876",
|
||||
"sha256:1a495ca4fb77c69595747dd688f8f17bb7d2ea9cd86603aa71c7fc98cc8b4174",
|
||||
"sha256:2829615cf58b1b24a9f96fea42abedaa1a800dd351c67374cc2f6341138608f3",
|
||||
"sha256:2e98913fa183f7597c609e774820a149e9329fd2a0f8d33978252fbd00ae87e6",
|
||||
"sha256:2f2ec57ab74785db9c2bf47c0a6731e5175595a13f8253f06fa84136adb310a9",
|
||||
"sha256:30cbeeaedb9bced7012487e7438919aa0c7dfba18ac3d4315182b46eb3139b9d",
|
||||
"sha256:3a2fcaa269031dbbc8ebd91243c6452c5d267d6df939c008ab7533413c9cf92d",
|
||||
"sha256:3f964002d445521ad5b8e732a6b5ef0e2d2be7fe566768e5075c1d71398da64a",
|
||||
"sha256:4a289584da6df7ca318947301fe0ba9177e7f863f63110e087c80ac5f3658de8",
|
||||
"sha256:4da0b9deb380bd9a200fee13182c4f95b02b4c554c923e2e0032f32aaf1439ed",
|
||||
"sha256:4e0f90a6c3771ee1f1fea857778b4b6a1b64000d851b819f435f9091b3c38c60",
|
||||
"sha256:6a6fa2e8cf95b3d4a7c0fac48bce6e5037579e28d3eb33b53349d6e11f15e5a8",
|
||||
"sha256:6dc94a67163218581c7df275223488ac9b31dc582ccd756da607c3338908566c",
|
||||
"sha256:796e4f6a4e769b2eb6fea9a10546ea4bdee16182d1e29802b4d6349363c3c1d7",
|
||||
"sha256:7fcafed24371fe6e23bcf5abebbb29269f8d79915f1dd818ac85453657ea714a",
|
||||
"sha256:9440466c0211ac81f3417f274da5903f15546b486f76b2f290e74a56aaf0e737",
|
||||
"sha256:959022f3ad04053f8072dc9a2ad110c46edd9e4f92352061ba835fc91df3ca96",
|
||||
"sha256:d668cb10f2bf6ccd7c402f91e8b06290722dd09dbe265ae95b2c13db29ebeba0",
|
||||
"sha256:e38c3c6d37cf2cc969407e4d051dcb507cfd948eb26c7b0840c4f7d7d4a71bd4",
|
||||
"sha256:f47c9b6818cc0f420015b672d5dcc488530a5ee63e5ba35a184957b21ea3922a",
|
||||
"sha256:f5d80eb846be4fc4e642cbedc1ed0c143e8d241653382ecc76a7620bbd2a5c3a",
|
||||
"sha256:f8bf193269ea9d347ac3ddada960a59f1ab2e4a5c009be95dc70e6505346b2fc",
|
||||
"sha256:fb04bd80964428491951766452f0071b0bc37c7d38c45ef02502dbd83e5d74a0"
|
||||
],
|
||||
"markers": "python_full_version >= '3.6.8'",
|
||||
"version": "==3.1.2"
|
||||
"markers": "python_version >= '3.8'",
|
||||
"version": "==0.9.0"
|
||||
},
|
||||
"pyproj": {
|
||||
"hashes": [
|
||||
"sha256:18faa54a3ca475bfe6255156f2f2874e9a1c8917b0004eee9f664b86ccc513d3",
|
||||
"sha256:1e9fbaf920f0f9b4ee62aab832be3ae3968f33f24e2e3f7fbb8c6728ef1d9746",
|
||||
"sha256:2d6ff73cc6dbbce3766b6c0bce70ce070193105d8de17aa2470009463682a8eb",
|
||||
"sha256:36b64c2cb6ea1cc091f329c5bd34f9c01bb5da8c8e4492c709bda6a09f96808f",
|
||||
"sha256:38a3361941eb72b82bd9a18f60c78b0df8408416f9340521df442cebfc4306e2",
|
||||
"sha256:447db19c7efad70ff161e5e46a54ab9cc2399acebb656b6ccf63e4bc4a04b97a",
|
||||
"sha256:44aa7c704c2b7d8fb3d483bbf75af6cb2350d30a63b144279a09b75fead501bf",
|
||||
"sha256:4ba1f9b03d04d8cab24d6375609070580a26ce76eaed54631f03bab00a9c737b",
|
||||
"sha256:4bc0472302919e59114aa140fd7213c2370d848a7249d09704f10f5b062031fe",
|
||||
"sha256:50100b2726a3ca946906cbaa789dd0749f213abf0cbb877e6de72ca7aa50e1ae",
|
||||
"sha256:5279586013b8d6582e22b6f9e30c49796966770389a9d5b85e25a4223286cd3f",
|
||||
"sha256:6420ea8e7d2a88cb148b124429fba8cd2e0fae700a2d96eab7083c0928a85110",
|
||||
"sha256:65ad699e0c830e2b8565afe42bd58cc972b47d829b2e0e48ad9638386d994915",
|
||||
"sha256:6d227a865356f225591b6732430b1d1781e946893789a609bb34f59d09b8b0f8",
|
||||
"sha256:7a27151ddad8e1439ba70c9b4b2b617b290c39395fa9ddb7411ebb0eb86d6fb0",
|
||||
"sha256:80fafd1f3eb421694857f254a9bdbacd1eb22fc6c24ca74b136679f376f97d35",
|
||||
"sha256:83039e5ae04e5afc974f7d25ee0870a80a6bd6b7957c3aca5613ccbe0d3e72bf",
|
||||
"sha256:8b8acc31fb8702c54625f4d5a2a6543557bec3c28a0ef638778b7ab1d1772132",
|
||||
"sha256:9274880263256f6292ff644ca92c46d96aa7e57a75c6df3f11d636ce845a1877",
|
||||
"sha256:ab7aa4d9ff3c3acf60d4b285ccec134167a948df02347585fdd934ebad8811b4",
|
||||
"sha256:c41e80ddee130450dcb8829af7118f1ab69eaf8169c4bf0ee8d52b72f098dc2f",
|
||||
"sha256:db3aedd458e7f7f21d8176f0a1d924f1ae06d725228302b872885a1c34f3119e",
|
||||
"sha256:e7e13c40183884ec7f94eb8e0f622f08f1d5716150b8d7a134de48c6110fee85",
|
||||
"sha256:ebfbdbd0936e178091309f6cd4fcb4decd9eab12aa513cdd9add89efa3ec2882",
|
||||
"sha256:fd43bd9a9b9239805f406fd82ba6b106bf4838d9ef37c167d3ed70383943ade1",
|
||||
"sha256:fd93c1a0c6c4aedc77c0fe275a9f2aba4d59b8acf88cebfc19fe3c430cfabf4f",
|
||||
"sha256:fffb059ba3bced6f6725961ba758649261d85ed6ce670d3e3b0a26e81cf1aa8d"
|
||||
],
|
||||
"markers": "python_version >= '3.9'",
|
||||
"version": "==3.6.1"
|
||||
},
|
||||
"python-dateutil": {
|
||||
"hashes": [
|
||||
@ -1340,14 +1171,6 @@
|
||||
"markers": "python_version >= '3.7'",
|
||||
"version": "==1.3.1"
|
||||
},
|
||||
"soupsieve": {
|
||||
"hashes": [
|
||||
"sha256:5663d5a7b3bfaeee0bc4372e7fc48f9cff4940b3eec54a6451cc5299f1097690",
|
||||
"sha256:eaa337ff55a1579b6549dc679565eac1e3d000563bcb1c8ab0d0fefbc0c2cdc7"
|
||||
],
|
||||
"markers": "python_version >= '3.8'",
|
||||
"version": "==2.5"
|
||||
},
|
||||
"starlette": {
|
||||
"hashes": [
|
||||
"sha256:6fe59f29268538e5d0d182f2791a479a0c64638e6935d1c6989e63fb2699c6ee",
|
||||
@ -1675,14 +1498,6 @@
|
||||
"sha256:ffefa1374cd508d633646d51a8e9277763a9b78ae71324183693959cf94635a7"
|
||||
],
|
||||
"version": "==12.0"
|
||||
},
|
||||
"xarray": {
|
||||
"hashes": [
|
||||
"sha256:0b91e0bc4dc0296947947640fe31ec6e867ce258d2f7cbc10bedf4a6d68340c7",
|
||||
"sha256:721a7394e8ec3d592b2d8ebe21eed074ac077dc1bb1bd777ce00e41700b4866c"
|
||||
],
|
||||
"markers": "python_version >= '3.9'",
|
||||
"version": "==2024.6.0"
|
||||
}
|
||||
},
|
||||
"develop": {}
|
||||
|
@ -1,2 +0,0 @@
|
||||
'shop'='department_store'
|
||||
'shop'='mall'
|
19
backend/src/constants.py
Normal file
19
backend/src/constants.py
Normal file
@ -0,0 +1,19 @@
|
||||
from pathlib import Path
|
||||
import os
|
||||
import logging
|
||||
|
||||
PARAMETERS_DIR = Path('src/parameters')
|
||||
AMENITY_SELECTORS_PATH = PARAMETERS_DIR / 'amenity_selectors.yaml'
|
||||
LANDMARK_PARAMETERS_PATH = PARAMETERS_DIR / 'landmark_parameters.yaml'
|
||||
OPTIMIZER_PARAMETERS_PATH = PARAMETERS_DIR / 'optimizer_parameters.yaml'
|
||||
|
||||
|
||||
|
||||
cache_dir_string = os.getenv('OSM_CACHE_DIR', './cache')
|
||||
OSM_CACHE_DIR = Path(cache_dir_string)
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
logging.basicConfig(
|
||||
level = logging.INFO,
|
||||
format = '%(asctime)s - %(name)s - %(levelname)s - %(message)s'
|
||||
)
|
151
backend/src/example_landmarks_manager.py
Normal file
151
backend/src/example_landmarks_manager.py
Normal file
@ -0,0 +1,151 @@
|
||||
import yaml
|
||||
import logging
|
||||
from OSMPythonTools import cachingStrategy, overpass
|
||||
from structs.landmarks import Landmark, LandmarkType
|
||||
from structs.preferences import Preferences, Preference
|
||||
import constants
|
||||
|
||||
SIGHTSEEING = LandmarkType(landmark_type='sightseeing')
|
||||
NATURE = LandmarkType(landmark_type='nature')
|
||||
SHOPPING = LandmarkType(landmark_type='shopping')
|
||||
|
||||
|
||||
class LandmarkManager:
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
def __init__(self) -> None:
|
||||
strategy = cachingStrategy.JSON(cacheDir=constants.OSM_CACHE_DIR)
|
||||
self.query_builder = overpass.Overpass()
|
||||
with constants.AMENITY_SELECTORS_PATH.open('r') as f:
|
||||
self.amenity_selectors = yaml.safe_load(f)
|
||||
with constants.LANDMARK_PARAMETERS_PATH.open('r') as f:
|
||||
self.parameters = yaml.safe_load(f)
|
||||
# max_distance = parameters['city_bbox_side']
|
||||
|
||||
|
||||
def get_landmark_lists(self, preferences: Preferences, center_coordinates: tuple[float, float]) -> tuple[list[Landmark], list[Landmark]]:
|
||||
'''
|
||||
Generate a list of landmarks based on the preferences of the user and the center (ie. start) coordinates.
|
||||
The list is then used by the pathfinding algorithm to generate a path that goes through the most interesting landmarks.
|
||||
:param preferences: the preferences specified by the user
|
||||
:param center_coordinates: the coordinates of the starting point
|
||||
'''
|
||||
|
||||
L = []
|
||||
|
||||
# List for sightseeing
|
||||
if preferences.sightseeing.score != 0:
|
||||
score_func = lambda loc, n_tags: int((10 + n_tags * self.parameters['tag_coeff']) * self.parameters['church_coeff'])
|
||||
L1 = self.fetch_landmarks(self.amenity_selectors['sightseeing'], SIGHTSEEING, center_coordinates, self.parameters['city_bbox_side'], score_func)
|
||||
self.correct_score(L1, preferences.sightseeing)
|
||||
L += L1
|
||||
|
||||
# List for nature
|
||||
if preferences.nature.score != 0:
|
||||
score_func = lambda loc, n_tags: int((10 + n_tags * self.parameters['tag_coeff']) * self.parameters['park_coeff'])
|
||||
L2 = self.fetch_landmarks(self.amenity_selectors['nature'], NATURE, center_coordinates, self.parameters['city_bbox_side'], score_func)
|
||||
self.correct_score(L2, preferences.nature)
|
||||
L += L2
|
||||
|
||||
# List for shopping
|
||||
if preferences.shopping.score != 0:
|
||||
score_func = lambda loc, n_tags: int((10 + n_tags * self.parameters['tag_coeff']))
|
||||
L3 = self.fetch_landmarks(self.amenity_selectors['shopping'], SHOPPING, center_coordinates, self.parameters['city_bbox_side'], score_func)
|
||||
self.correct_score(L3, preferences.shopping)
|
||||
L += L3
|
||||
|
||||
# remove duplicates
|
||||
L = list(set(L))
|
||||
L_constrained = self.take_most_important(L, self.parameters['N_important'])
|
||||
self.logger.info(f'Generated {len(L)} landmarks around {center_coordinates}, and constrained to {len(L_constrained)} most important ones.')
|
||||
return L, L_constrained
|
||||
|
||||
|
||||
|
||||
# Take the most important landmarks from the list
|
||||
def take_most_important(self, landmarks: list[Landmark], n_max: int) -> list[Landmark]:
|
||||
|
||||
landmarks_sorted = sorted(landmarks, key=lambda x: x.attractiveness, reverse=True)
|
||||
return landmarks_sorted[:n_max]
|
||||
|
||||
|
||||
|
||||
# Correct the score of a list of landmarks by taking into account preference settings
|
||||
def correct_score(self, L: list[Landmark], preference: Preference):
|
||||
|
||||
if len(L) == 0 :
|
||||
return
|
||||
|
||||
if L[0].type != preference.type :
|
||||
raise TypeError(f"LandmarkType {preference.type} does not match the type of Landmark {L[0].name}")
|
||||
|
||||
for elem in L :
|
||||
elem.attractiveness = int(elem.attractiveness*preference.score/500) # arbitrary computation
|
||||
|
||||
|
||||
# Function to count elements within a certain radius of a location
|
||||
def count_elements_within_radius(self, point: Point, radius: int) -> int:
|
||||
|
||||
center_coordinates = (point.x, point.y)
|
||||
try:
|
||||
landmarks = ox.features_from_point(
|
||||
center_point = center_coordinates,
|
||||
dist = radius,
|
||||
tags = {'building': True} # this is a common tag to give an estimation of the number of elements in the area
|
||||
)
|
||||
return len(landmarks)
|
||||
except ox._errors.InsufficientResponseError:
|
||||
return 0
|
||||
|
||||
|
||||
|
||||
|
||||
def fetch_landmarks(
|
||||
self,
|
||||
amenity_selectors: list[dict],
|
||||
landmarktype: LandmarkType,
|
||||
center_coordinates: tuple[float, float],
|
||||
distance: int,
|
||||
score_function: callable
|
||||
) -> list[Landmark]:
|
||||
|
||||
landmarks = ox.features_from_point(
|
||||
center_point = center_coordinates,
|
||||
dist = distance,
|
||||
tags = amenity_selectors
|
||||
)
|
||||
self.logger.info(f'Fetched {len(landmarks)} landmarks around {center_coordinates}.')
|
||||
|
||||
# cleanup the list
|
||||
# remove rows where name is None
|
||||
landmarks = landmarks[landmarks['name'].notna()]
|
||||
# TODO: remove rows that are part of another building
|
||||
|
||||
ret_landmarks = []
|
||||
for element, description in landmarks.iterrows():
|
||||
osm_type = element[0]
|
||||
osm_id = element[1]
|
||||
location = description['geometry']
|
||||
n_tags = len(description['nodes']) if type(description['nodes']) == list else 1
|
||||
|
||||
if type(location) == Point:
|
||||
location = location
|
||||
elif type(location) == Polygon or type(location) == MultiPolygon:
|
||||
location = location.centroid
|
||||
elif type(location) == LineString:
|
||||
location = location.interpolate(location.length/2)
|
||||
|
||||
score = score_function(location, n_tags)
|
||||
landmark = Landmark(
|
||||
name = description['name'],
|
||||
type = landmarktype,
|
||||
location = (location.x, location.y),
|
||||
osm_type = osm_type,
|
||||
osm_id = osm_id,
|
||||
attractiveness = score,
|
||||
must_do = False,
|
||||
n_tags = n_tags
|
||||
)
|
||||
ret_landmarks.append(landmark)
|
||||
|
||||
return ret_landmarks
|
@ -1,13 +1,12 @@
|
||||
import numpy as np
|
||||
import json, os
|
||||
import yaml
|
||||
|
||||
from typing import List, Tuple
|
||||
from scipy.optimize import linprog
|
||||
from math import radians, sin, cos, acos
|
||||
from shapely import Polygon
|
||||
|
||||
from structs.landmarks import Landmark
|
||||
|
||||
import constants
|
||||
|
||||
# Function to print the result
|
||||
def print_res(L: List[Landmark], L_tot):
|
||||
@ -161,10 +160,11 @@ def get_distance(p1: Tuple[float, float], p2: Tuple[float, float], detour: float
|
||||
# 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']
|
||||
# Read the parameters from the file
|
||||
with constants.OPTIMIZER_PARAMETERS_PATH.open('r') as f:
|
||||
parameters = yaml.safe_load(f)
|
||||
detour = parameters['detour_factor']
|
||||
speed = parameters['average_walking_speed']
|
||||
|
||||
# Objective function coefficients. a*x1 + b*x2 + c*x3 + ...
|
||||
c = []
|
||||
@ -194,9 +194,9 @@ def respect_number(L:int, A_ub, b_ub):
|
||||
b_ub.append(1)
|
||||
|
||||
# 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']
|
||||
with constants.OPTIMIZER_PARAMETERS_PATH.open('r') as f:
|
||||
parameters = yaml.safe_load(f)
|
||||
max_landmarks = parameters['max_landmarks']
|
||||
|
||||
A_ub = np.vstack((A_ub, ones*L))
|
||||
b_ub.append(max_landmarks+1)
|
||||
@ -300,13 +300,14 @@ def respect_order(N: int, A_eq, b_eq):
|
||||
|
||||
|
||||
# Computes the time to reach from each landmark to the next
|
||||
def link_list(order: List[int], landmarks: List[Landmark])->List[Landmark] :
|
||||
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']
|
||||
with constants.OPTIMIZER_PARAMETERS_PATH.open('r') as f:
|
||||
parameters = yaml.safe_load(f)
|
||||
|
||||
detour_factor = parameters['detour_factor']
|
||||
speed = parameters['average_walking_speed']
|
||||
|
||||
L = []
|
||||
j = 0
|
||||
@ -329,10 +330,11 @@ def link_list(order: List[int], landmarks: List[Landmark])->List[Landmark] :
|
||||
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']
|
||||
with constants.OPTIMIZER_PARAMETERS_PATH.open('r') as f:
|
||||
parameters = yaml.safe_load(f)
|
||||
|
||||
detour_factor = parameters['detour_factor']
|
||||
speed = parameters['average_walking_speed']
|
||||
|
||||
L = []
|
||||
j = 0
|
303
backend/src/example_refiner.py
Normal file
303
backend/src/example_refiner.py
Normal file
@ -0,0 +1,303 @@
|
||||
from collections import defaultdict
|
||||
from heapq import heappop, heappush
|
||||
from itertools import permutations
|
||||
import os
|
||||
import yaml
|
||||
|
||||
from shapely import buffer, LineString, Point, Polygon, MultiPoint, concave_hull
|
||||
from typing import List, Tuple
|
||||
from math import pi
|
||||
|
||||
from structs.landmarks import Landmark
|
||||
from landmarks_manager import take_most_important
|
||||
from backend.src.example_optimizer import solve_optimization, link_list_simple, print_res, get_distance
|
||||
import constants
|
||||
|
||||
|
||||
# Create corridor from tour
|
||||
def create_corridor(landmarks: List[Landmark], width: float) :
|
||||
|
||||
corrected_width = (180*width)/(6371000*pi)
|
||||
|
||||
path = create_linestring(landmarks)
|
||||
obj = buffer(path, corrected_width, join_style="mitre", cap_style="square", mitre_limit=2)
|
||||
|
||||
return obj
|
||||
|
||||
|
||||
# Create linestring from tour
|
||||
def create_linestring(landmarks: List[Landmark])->List[Point] :
|
||||
|
||||
points = []
|
||||
|
||||
for landmark in landmarks :
|
||||
points.append(Point(landmark.location))
|
||||
|
||||
return LineString(points)
|
||||
|
||||
|
||||
# Check if some coordinates are in area. Used for the corridor
|
||||
def is_in_area(area: Polygon, coordinates) -> bool :
|
||||
point = Point(coordinates)
|
||||
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]):
|
||||
"""Determine if two locations are close by rounding their coordinates to 3 decimals."""
|
||||
absx = abs(location1[0] - location2[0])
|
||||
absy = abs(location1[1] - location2[1])
|
||||
|
||||
return absx < 0.001 and absy < 0.001
|
||||
#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]:
|
||||
|
||||
i = 1
|
||||
while i < len(landmarks):
|
||||
j = i+1
|
||||
while j < len(landmarks):
|
||||
if is_close_to(landmarks[i].location, landmarks[j].location) and landmarks[i].name not in ['start', 'finish'] and landmarks[j].name not in ['start', 'finish']:
|
||||
# If they are not adjacent, move the j-th element to be adjacent to the i-th element
|
||||
if j != i + 1:
|
||||
landmarks.insert(i + 1, landmarks.pop(j))
|
||||
break # Move to the next i-th element after rearrangement
|
||||
j += 1
|
||||
i += 1
|
||||
|
||||
return landmarks
|
||||
|
||||
|
||||
# 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 the parameters from the file
|
||||
with constants.OPTIMIZER_PARAMETERS_PATH.open('r') as f:
|
||||
parameters = yaml.safe_load(f)
|
||||
|
||||
detour = parameters['detour_factor']
|
||||
speed = parameters['average_walking_speed']
|
||||
|
||||
# Step 1: Find 'start' and 'finish' landmarks
|
||||
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')
|
||||
|
||||
start_landmark = landmarks[start_idx]
|
||||
finish_landmark = landmarks[finish_idx]
|
||||
|
||||
|
||||
# Step 2: Create a list of unvisited landmarks excluding 'start' and 'finish'
|
||||
unvisited_landmarks = [lm for i, lm in enumerate(landmarks) if i not in [start_idx, finish_idx]]
|
||||
|
||||
# Step 3: Initialize the path with the 'start' landmark
|
||||
path = [start_landmark]
|
||||
coordinates = [landmarks[start_idx].location]
|
||||
|
||||
current_landmark = start_landmark
|
||||
|
||||
# Step 4: Use nearest neighbor heuristic to visit all landmarks
|
||||
while unvisited_landmarks:
|
||||
nearest_landmark = min(unvisited_landmarks, key=lambda lm: get_time(current_landmark.location, lm.location, detour, speed))
|
||||
path.append(nearest_landmark)
|
||||
coordinates.append(nearest_landmark.location)
|
||||
current_landmark = nearest_landmark
|
||||
unvisited_landmarks.remove(nearest_landmark)
|
||||
|
||||
# Step 5: Finally add the 'finish' landmark to the path
|
||||
path.append(finish_landmark)
|
||||
coordinates.append(landmarks[finish_idx].location)
|
||||
|
||||
path_poly = Polygon(coordinates)
|
||||
|
||||
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] :
|
||||
|
||||
second_order_landmarks = []
|
||||
visited_names = []
|
||||
area = create_corridor(visited_landmarks, width)
|
||||
|
||||
for visited in visited_landmarks :
|
||||
visited_names.append(visited.name)
|
||||
|
||||
for landmark in all_landmarks :
|
||||
if is_in_area(area, landmark.location) and landmark.name not in visited_names:
|
||||
second_order_landmarks.append(landmark)
|
||||
|
||||
with constants.LANDMARK_PARAMETERS_PATH.open('r') as f:
|
||||
parameters = yaml.safe_load(f)
|
||||
return take_most_important(second_order_landmarks, parameters, len(visited_landmarks))
|
||||
|
||||
|
||||
# Try fix the shortest path using shapely
|
||||
def fix_using_polygon(tour: List[Landmark])-> List[Landmark] :
|
||||
|
||||
coords = []
|
||||
coords_dict = {}
|
||||
for landmark in tour :
|
||||
coords.append(landmark.location)
|
||||
if landmark.name != 'finish' :
|
||||
coords_dict[landmark.location] = landmark
|
||||
|
||||
tour_poly = Polygon(coords)
|
||||
|
||||
better_tour_poly = tour_poly.buffer(0)
|
||||
try :
|
||||
xs, ys = better_tour_poly.exterior.xy
|
||||
|
||||
if len(xs) != len(tour) :
|
||||
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
|
||||
|
||||
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
|
||||
xs.reverse()
|
||||
ys.reverse()
|
||||
|
||||
better_tour = [] # List of ordered visit
|
||||
name_index = {} # Maps the name of a landmark to its index in the concave polygon
|
||||
|
||||
# Loop through the polygon and generate the better (ordered) tour
|
||||
for i,x in enumerate(xs[:-1]) :
|
||||
y = ys[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
|
||||
start_index = name_index['start']
|
||||
better_tour = better_tour[start_index:] + better_tour[:start_index]
|
||||
|
||||
# Append the finish back and correct the time to reach
|
||||
better_tour.append(tour[-1])
|
||||
|
||||
# Rearrange only if polygon still not simple
|
||||
if not better_tour_poly.is_simple :
|
||||
better_tour = rearrange(better_tour)
|
||||
|
||||
return better_tour
|
||||
|
||||
|
||||
# Second stage of the optimization. Use linear programming again to refine the path
|
||||
def refine_optimization(landmarks: List[Landmark], base_tour: List[Landmark], max_time: int, detour: int, print_infos: bool) -> List[Landmark] :
|
||||
|
||||
# Read the parameters from the file
|
||||
with constants.OPTIMIZER_PARAMETERS_PATH.open('r') as f:
|
||||
parameters = yaml.safe_load(f)
|
||||
max_landmarks = parameters['max_landmarks']
|
||||
|
||||
if len(base_tour)-2 >= max_landmarks :
|
||||
return base_tour
|
||||
|
||||
|
||||
# No need to refine if no detour is taken
|
||||
# if detour == 0 :
|
||||
if False :
|
||||
new_tour = base_tour
|
||||
|
||||
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)
|
||||
|
||||
# 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)
|
||||
|
||||
# Choose the better tour depending on walked distance
|
||||
if new_dist < better_dist :
|
||||
final_tour = new_tour
|
||||
else :
|
||||
final_tour = better_tour
|
||||
|
||||
if print_infos :
|
||||
print("\n\n\nRefined tour (result of second stage optimization): ")
|
||||
print_res(final_tour)
|
||||
total_score = 0
|
||||
for elem in final_tour :
|
||||
total_score += elem.attractiveness
|
||||
|
||||
print("\nTotal score : " + str(total_score))
|
||||
|
||||
|
||||
|
||||
return final_tour
|
||||
|
||||
|
80
backend/src/example_tester.py
Normal file
80
backend/src/example_tester.py
Normal file
@ -0,0 +1,80 @@
|
||||
import pandas as pd
|
||||
|
||||
from typing import List
|
||||
from landmarks_manager import LandmarkManager
|
||||
from fastapi.encoders import jsonable_encoder
|
||||
|
||||
from backend.src.example_optimizer import solve_optimization
|
||||
# from refiner import refine_optimization
|
||||
from structs.landmarks import Landmark
|
||||
from structs.landmarktype import LandmarkType
|
||||
from structs.preferences import Preferences, Preference
|
||||
|
||||
|
||||
# Helper function to create a .txt file with results
|
||||
def write_data(L: List[Landmark], file_name: str):
|
||||
|
||||
data = pd.DataFrame()
|
||||
i = 0
|
||||
|
||||
for landmark in L :
|
||||
data[i] = jsonable_encoder(landmark)
|
||||
i += 1
|
||||
|
||||
data.to_json(file_name, indent = 2, force_ascii=False)
|
||||
|
||||
def main(coordinates: tuple[float, float]) -> List[Landmark]:
|
||||
|
||||
manager = LandmarkManager()
|
||||
|
||||
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
|
||||
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)
|
||||
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)
|
||||
|
||||
# Generate the landmarks from the start location
|
||||
landmarks, landmarks_short = manager.get_landmark_lists(preferences=preferences, center_coordinates=start.location)
|
||||
print([l.name for l in landmarks_short])
|
||||
|
||||
#write_data(landmarks, "landmarks.txt")
|
||||
|
||||
# Insert start and finish to the landmarks list
|
||||
landmarks_short.insert(0, start)
|
||||
landmarks_short.append(finish)
|
||||
|
||||
# TODO use these parameters in another way
|
||||
max_walking_time = 3 # hours
|
||||
detour = 30 # minutes
|
||||
|
||||
# First stage optimization
|
||||
base_tour = solve_optimization(landmarks_short, max_walking_time*60, True)
|
||||
|
||||
# Second stage optimization
|
||||
# refined_tour = refine_optimization(landmarks, base_tour, max_walking_time*60+detour, True)
|
||||
|
||||
return base_tour
|
||||
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
start = (48.847132, 2.312359) # Café Chez César
|
||||
# start = (47.377859, 8.540585) # Zurich HB
|
||||
main(start)
|
@ -1,51 +1,45 @@
|
||||
from optimizer import solve_optimization
|
||||
from refiner import refine_optimization
|
||||
from landmarks_manager import generate_landmarks
|
||||
from backend.src.example_optimizer import solve_optimization
|
||||
# from refiner import refine_optimization
|
||||
from landmarks_manager import LandmarkManager
|
||||
from structs.landmarks import Landmark
|
||||
from structs.landmarktype import LandmarkType
|
||||
from structs.preferences import Preferences, Preference
|
||||
from structs.preferences import Preferences
|
||||
from fastapi import FastAPI, Query, Body
|
||||
from typing import List
|
||||
|
||||
app = FastAPI()
|
||||
|
||||
manager = LandmarkManager()
|
||||
|
||||
# TODO: needs a global variable to store the landmarks accross function calls
|
||||
# linked_tour = []
|
||||
|
||||
|
||||
# Assuming frontend is calling like this :
|
||||
#"http://127.0.0.1:8000/process?param1={param1}¶m2={param2}"
|
||||
@app.post("/optimizer_coords/{start_lat}/{start_lon}/{finish_lat}/{finish_lon}")
|
||||
def main1(start_lat: float, start_lon: float, preferences: Preferences = Body(...), finish_lat: float = None, finish_lon: float = None) -> List[Landmark]:
|
||||
|
||||
@app.post("/route/new")
|
||||
def main1(preferences: Preferences, start: tuple[float, float], end: tuple[float, float] = None) -> str:
|
||||
'''
|
||||
Main function to call the optimizer.
|
||||
:param preferences: the preferences specified by the user as the post body
|
||||
:param start: the coordinates of the starting point as a tuple of floats (as url query parameters)
|
||||
:param end: the coordinates of the finishing point as a tuple of floats (as url query parameters)
|
||||
:return: the uuid of the first landmark in the optimized route
|
||||
'''
|
||||
if preferences is None :
|
||||
raise ValueError("Please provide preferences in the form of a 'Preference' BaseModel class.")
|
||||
if bool(start_lat) ^ bool(start_lon) :
|
||||
raise ValueError("Please provide both latitude and longitude for the starting point")
|
||||
if bool(finish_lat) ^ bool(finish_lon) :
|
||||
raise ValueError("Please provide both latitude and longitude for the finish point")
|
||||
if start is None:
|
||||
raise ValueError("Please provide the starting coordinates as a tuple of floats.")
|
||||
if end is None:
|
||||
end = start
|
||||
|
||||
start = Landmark(name='start', type=LandmarkType(landmark_type='start'), location=(start_lat, start_lon), osm_type='start', osm_id=0, attractiveness=0, must_do=True, n_tags = 0)
|
||||
start_landmark = Landmark(name='start', type=LandmarkType(landmark_type='start'), location=(start[0], start[1]), osm_type='start', osm_id=0, attractiveness=0, must_do=True, n_tags = 0)
|
||||
end_landmark = Landmark(name='end', type=LandmarkType(landmark_type='end'), location=(end[0], end[1]), osm_type='end', osm_id=0, attractiveness=0, must_do=True, n_tags = 0)
|
||||
|
||||
if bool(finish_lat) and bool(finish_lon) :
|
||||
finish = Landmark(name='finish', type=LandmarkType(landmark_type='finish'), location=(finish_lat, finish_lon), osm_type='finish', osm_id=0, attractiveness=0, must_do=True, n_tags = 0)
|
||||
else :
|
||||
finish = Landmark(name='finish', type=LandmarkType(landmark_type='finish'), location=(start_lat, start_lon), 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.8375946, 2.2949904), 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.8375946, 2.2949904), osm_type='finish', osm_id=0, attractiveness=0, must_do=True, n_tags = 0)
|
||||
|
||||
# Generate the landmarks from the start location
|
||||
landmarks, landmarks_short = generate_landmarks(preferences=preferences, coordinates=start.location)
|
||||
|
||||
landmarks, landmarks_short = LandmarkManager.get_landmark_lists(preferences=preferences, coordinates=start.location)
|
||||
print([l.name for l in landmarks_short])
|
||||
# insert start and finish to the landmarks list
|
||||
landmarks_short.insert(0, start)
|
||||
landmarks_short.append(finish)
|
||||
landmarks_short.insert(0, start_landmark)
|
||||
landmarks_short.append(end_landmark)
|
||||
|
||||
|
||||
# TODO use these parameters in another way
|
||||
# TODO infer these parameters from the preferences
|
||||
max_walking_time = 4 # hours
|
||||
detour = 30 # minutes
|
||||
|
||||
@ -53,32 +47,11 @@ def main1(start_lat: float, start_lon: float, preferences: Preferences = Body(..
|
||||
base_tour = solve_optimization(landmarks_short, max_walking_time*60, True)
|
||||
|
||||
# Second stage optimization
|
||||
refined_tour = refine_optimization(landmarks, base_tour, max_walking_time*60+detour, True)
|
||||
# refined_tour = refine_optimization(landmarks, base_tour, max_walking_time*60+detour, True)
|
||||
|
||||
|
||||
# TODO: should look something like this
|
||||
# # set time to reach and transform into fully functional linked list
|
||||
# linked_tour += link(refined_tour)
|
||||
# return {
|
||||
# 'city_name': 'Paris',
|
||||
# 'n_stops': len(linked_tour),
|
||||
# 'first_landmark_uuid': linked_tour[0].uuid,
|
||||
# }
|
||||
|
||||
return refined_tour
|
||||
|
||||
|
||||
|
||||
|
||||
# input city, country in the form of 'Paris, France'
|
||||
@app.post("/test2/{city_country}")
|
||||
def test2(city_country: str, preferences: Preferences = Body(...)) -> List[Landmark]:
|
||||
|
||||
landmarks = generate_landmarks(city_country, preferences)
|
||||
|
||||
max_steps = 9000000
|
||||
|
||||
visiting_order = solve_optimization(landmarks, max_steps, True)
|
||||
# linked_tour = ...
|
||||
# return linked_tour[0].uuid
|
||||
return base_tour[0].uuid
|
||||
|
||||
|
||||
|
||||
@ -86,5 +59,3 @@ def test2(city_country: str, preferences: Preferences = Body(...)) -> List[Landm
|
||||
def get_landmark(landmark_uuid: str) -> Landmark:
|
||||
#cherche dans linked_tour et retourne le landmark correspondant
|
||||
pass
|
||||
|
||||
|
||||
|
32
backend/src/parameters/amenity_selectors.yaml
Normal file
32
backend/src/parameters/amenity_selectors.yaml
Normal file
@ -0,0 +1,32 @@
|
||||
nature:
|
||||
leisure: park
|
||||
geological: ''
|
||||
natural:
|
||||
- geyser
|
||||
- hot_spring
|
||||
- arch
|
||||
- volcano
|
||||
- stone
|
||||
tourism:
|
||||
- alpine_hut
|
||||
- viewpoint
|
||||
- zoo
|
||||
waterway: waterfall
|
||||
|
||||
shopping:
|
||||
shop:
|
||||
- department_store
|
||||
- mall
|
||||
|
||||
sightseeing:
|
||||
tourism:
|
||||
- museum
|
||||
- attraction
|
||||
- gallery
|
||||
historic: ''
|
||||
amenity:
|
||||
- planetarium
|
||||
- place_of_worship
|
||||
- fountain
|
||||
water:
|
||||
- reflecting_pool
|
6
backend/src/parameters/landmark_parameters.yaml
Normal file
6
backend/src/parameters/landmark_parameters.yaml
Normal file
@ -0,0 +1,6 @@
|
||||
city_bbox_side: 5000 #m
|
||||
radius_close_to: 30
|
||||
church_coeff: 0.6
|
||||
park_coeff: 1.5
|
||||
tag_coeff: 100
|
||||
N_important: 40
|
3
backend/src/parameters/optimizer_parameters.yaml
Normal file
3
backend/src/parameters/optimizer_parameters.yaml
Normal file
@ -0,0 +1,3 @@
|
||||
detour_factor: 1.4
|
||||
average_walking_speed: 4.8
|
||||
max_landmarks: 40
|
@ -1,6 +1,5 @@
|
||||
from typing import Optional
|
||||
from pydantic import BaseModel, Field
|
||||
|
||||
from .landmarktype import LandmarkType
|
||||
|
||||
from uuid import uuid4
|
||||
@ -29,3 +28,6 @@ class Landmark(BaseModel) :
|
||||
|
||||
time_to_reach_next : Optional[int] = 0 # TODO fix this in existing code
|
||||
next_uuid : Optional[str] = None # TODO implement this ASAP
|
||||
|
||||
def __hash__(self) -> int:
|
||||
return self.uuid.int
|
@ -1,7 +1,7 @@
|
||||
import pandas as pd
|
||||
|
||||
from typing import List
|
||||
from landmarks_manager import generate_landmarks
|
||||
from landmarks_manager import LandmarkManager
|
||||
from fastapi.encoders import jsonable_encoder
|
||||
|
||||
from optimizer_v4 import solve_optimization
|
||||
@ -26,6 +26,7 @@ def write_data(L: List[Landmark], file_name: str):
|
||||
|
||||
def test4(coordinates: tuple[float, float]) -> List[Landmark]:
|
||||
|
||||
manager = LandmarkManager()
|
||||
|
||||
preferences = Preferences(
|
||||
sightseeing=Preference(
|
||||
@ -77,4 +78,4 @@ def test4(coordinates: tuple[float, float]) -> List[Landmark]:
|
||||
#test4(tuple((47.377859, 8.540585))) # Zurich HB
|
||||
#test4(tuple((45.7576485, 4.8330241))) # Lyon Bellecour
|
||||
test4(tuple((48.5848435, 7.7332974))) # Strasbourg Gare
|
||||
#test4(tuple((48.2067858, 16.3692340))) # Vienne
|
||||
#test4(tuple((48.2067858, 16.3692340))) # Vienne
|
||||
|
40
deployment/deployment.yaml
Normal file
40
deployment/deployment.yaml
Normal file
@ -0,0 +1,40 @@
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: nav-backend
|
||||
spec:
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
app: nav-backend
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: nav-backend
|
||||
spec:
|
||||
containers:
|
||||
- name: worker
|
||||
image: backend-image
|
||||
ports:
|
||||
- containerPort: 8000
|
||||
env:
|
||||
- name: NUM_WORKERS
|
||||
value: "3"
|
||||
- name: OSM_CACHE_DIR
|
||||
value: "/osm-cache"
|
||||
volumeMounts:
|
||||
- name: osm-cache
|
||||
mountPath: /osm-cache
|
||||
resources:
|
||||
requests:
|
||||
cpu: 100m
|
||||
memory: 100Mi
|
||||
limits:
|
||||
cpu: 4
|
||||
memory: 10Gi
|
||||
volumes:
|
||||
- name: osm-cache
|
||||
persistentVolumeClaim:
|
||||
claimName: osm-cache
|
||||
|
||||
|
15
deployment/ingress.yaml
Normal file
15
deployment/ingress.yaml
Normal file
@ -0,0 +1,15 @@
|
||||
kind: IngressRoute
|
||||
apiVersion: traefik.io/v1alpha1
|
||||
metadata:
|
||||
name: nav-ingress
|
||||
spec:
|
||||
entryPoints:
|
||||
- websecure
|
||||
routes:
|
||||
- match: Host(`nav.kluster.moll.re`)
|
||||
kind: Rule
|
||||
services:
|
||||
- name: nav-service
|
||||
port: 8000
|
||||
tls:
|
||||
certResolver: default-tls
|
@ -0,0 +1,16 @@
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
|
||||
|
||||
namespace: nav
|
||||
resources:
|
||||
- namespace.yaml
|
||||
- pvc.yaml
|
||||
- deployment.yaml
|
||||
- service.yaml
|
||||
- ingress.yaml
|
||||
|
||||
images:
|
||||
- name: backend-image
|
||||
newName: git.kluster.moll.re/remoll/fast_network_navigation/backend
|
||||
newTag: latest
|
4
deployment/namespace.yaml
Normal file
4
deployment/namespace.yaml
Normal file
@ -0,0 +1,4 @@
|
||||
apiVersion: v1
|
||||
kind: Namespace
|
||||
metadata:
|
||||
name: placeholder
|
11
deployment/pvc.yaml
Normal file
11
deployment/pvc.yaml
Normal file
@ -0,0 +1,11 @@
|
||||
apiVersion: v1
|
||||
kind: PersistentVolumeClaim
|
||||
metadata:
|
||||
name: osm-cache
|
||||
spec:
|
||||
storageClassName: "nfs-client"
|
||||
accessModes:
|
||||
- ReadWriteOnce
|
||||
resources:
|
||||
requests:
|
||||
storage: "5Gi"
|
11
deployment/service.yaml
Normal file
11
deployment/service.yaml
Normal file
@ -0,0 +1,11 @@
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: nav-service
|
||||
spec:
|
||||
selector:
|
||||
app: nav-backend
|
||||
ports:
|
||||
- protocol: TCP
|
||||
port: 8000
|
||||
targetPort: 8000
|
Loading…
x
Reference in New Issue
Block a user