Skip to content

Commit 6d434ea

Browse files
authored
Merge pull request #4334 from hove-io/fix_parking_mode_multi_first_section_bis
[Jormun - NAV-3444] fix multiple first and last sections
2 parents 43364f1 + 42ef5ee commit 6d434ea

File tree

7 files changed

+261
-102
lines changed

7 files changed

+261
-102
lines changed

source/jormungandr/jormungandr/interfaces/v1/Journeys.py

+2
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
from jormungandr.interfaces.parsers import default_count_arg_type
3838
from jormungandr.interfaces.v1.ResourceUri import complete_links
3939
from functools import wraps
40+
from jormungandr.park_modes import all_park_modes
4041
from jormungandr.timezone import set_request_timezone
4142
from jormungandr.interfaces.v1.make_links import (
4243
create_external_link,
@@ -567,6 +568,7 @@ def __init__(self):
567568
help="Show more information about the poi if it's available, for instance, show "
568569
"BSS/car park availability in the pois(BSS/car park) of response",
569570
)
571+
570572
parser_get.add_argument(
571573
"_no_shared_section",
572574
type=BooleanType(),

source/jormungandr/jormungandr/interfaces/v1/journey_common.py

+3-4
Original file line numberDiff line numberDiff line change
@@ -241,17 +241,16 @@ def __init__(self, output_type_serializer):
241241
)
242242

243243
parser_get.add_argument(
244-
"park_mode[]",
244+
"park_mode",
245245
type=OptionValue(park_modes.all_park_modes),
246246
dest="park_mode",
247-
action="append",
248247
help='Force the park mode for the first or last section of a journey\n'
249248
'Need to be set with one of the first_section_mode[] or last_section_mode[] corresponding to vehicles that could be parked\n'
250249
'Note: Only work with the first or last section mode being a bike for the moment\n'
251250
'Eg: If you want to park a bike at the departure, you need:\n'
252-
'`first_section_mode[]=bike&park_mode[]=on_street`'
251+
'`first_section_mode[]=bike&park_mode=on_street`'
253252
'Eg: If you want to park a bike at the arrival, you need:\n'
254-
'`last_section_mode[]=bike&park_mode[]=on_street`',
253+
'`last_section_mode[]=bike&park_mode=on_street`',
255254
)
256255
# for retrocompatibility purpose, we duplicate (without []):
257256
parser_get.add_argument(

source/jormungandr/jormungandr/scenarios/distributed.py

+6
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@
2929

3030
from __future__ import absolute_import, print_function, unicode_literals, division
3131

32+
from jormungandr.park_modes import ParkMode
33+
3234
try:
3335
from typing import Dict, Text, Any, Tuple
3436
except ImportError:
@@ -182,6 +184,10 @@ def _compute_journeys(
182184
context.streetnetwork_path_pool.add_feed_publishers(request, requested_direct_path_modes, res)
183185
return res
184186

187+
# if the parkmode is set to "on street" we need to subtract additional time to the max_bike_duration_to_pt
188+
if ParkMode.on_street.name == request.get("park_mode", ""):
189+
request["max_bike_duration_to_pt"] += request.get("on_street_bike_parking_duration", 0)
190+
185191
# We'd like to get the duration of a direct path to do some optimizations in ProximitiesByCrowflyPool and
186192
# FallbackDurationsPool.
187193
# Note :direct_paths_by_mode is a dict of mode vs future of a direct paths, this line is not blocking

source/jormungandr/jormungandr/scenarios/helper_classes/fallback_durations.py

+8
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929

3030
from __future__ import absolute_import
3131

32+
from jormungandr.park_modes import ParkMode
3233
import jormungandr.street_network.utils
3334
from navitiacommon import response_pb2
3435
from collections import namedtuple, defaultdict
@@ -337,6 +338,13 @@ def is_access_point(pt_object):
337338
for idx, r in routing_response:
338339
pt_object = places_isochrone[idx]
339340
duration = self._get_duration(r, pt_object)
341+
342+
extra_duration = 0
343+
if FallbackModes.bike.name == self._mode and ParkMode.on_street.name == (
344+
self._request.get("park_mode") or ""
345+
):
346+
extra_duration = self._request["on_street_bike_parking_duration"]
347+
duration += extra_duration
340348
# in this case, the pt_object can be either a stop point or an access point
341349
if is_stop_point(pt_object):
342350
self._update_fb_durations(fallback_durations, pt_object, duration, r)

source/jormungandr/jormungandr/scenarios/helper_classes/helper_utils.py

+95-61
Original file line numberDiff line numberDiff line change
@@ -205,16 +205,21 @@ def _make_bike_park(begin_date_time, duration):
205205
return bike_park_section
206206

207207

208-
def _make_bike_park_street_network(origin, begin_date_time, destination, end_date_time, duration):
208+
def _make_bike_park_street_network(origin, begin_date_time, destination, end_date_time, duration, length):
209209
bike_park_to_sp_section = response_pb2.Section()
210210
bike_park_to_sp_section.id = "Street_network_section_2"
211211
bike_park_to_sp_section.origin.CopyFrom(origin)
212212
bike_park_to_sp_section.destination.CopyFrom(destination)
213213
bike_park_to_sp_section.type = response_pb2.STREET_NETWORK
214214
bike_park_to_sp_section.street_network.mode = response_pb2.Walking
215+
bike_park_to_sp_section.street_network.street_information.extend(
216+
[response_pb2.StreetInformation(geojson_offset=0, cycle_path_type=0, length=length)]
217+
)
218+
bike_park_to_sp_section.street_network.duration = duration
215219
bike_park_to_sp_section.begin_date_time = begin_date_time
216-
bike_park_to_sp_section.end_date_time = end_date_time + duration
220+
bike_park_to_sp_section.end_date_time = bike_park_to_sp_section.begin_date_time + duration
217221
bike_park_to_sp_section.duration = duration
222+
bike_park_to_sp_section.street_network.length = length
218223
return bike_park_to_sp_section
219224

220225

@@ -417,19 +422,23 @@ def add_poi_access_point_in_sections(fallback_type, via_poi_access, sections):
417422
poi_access.is_entrance = True
418423

419424

420-
def _update_journey(journey, park_section, street_mode_section, to_replace, new_fallbacks):
425+
def _update_journey(journey, park_section, street_mode_section, to_replace):
421426
journey.duration += park_section.duration + street_mode_section.duration
422427
journey.durations.total += park_section.duration + street_mode_section.duration
423428
journey.arrival_date_time += park_section.duration + street_mode_section.duration
424429
journey.sections.remove(to_replace)
425430
journey.sections.extend([street_mode_section, park_section])
426-
journey.sections.extend(new_fallbacks)
427431
journey.nb_sections += 2
428432

429433

430-
def walking_time(cord1, cord2, walking_speed):
434+
def _get_coords_from_pt_object(pt_object):
435+
coord = get_pt_object_coord(pt_object)
436+
return coord
437+
438+
439+
def _get_walking_information(object_1, object_2, walking_speed):
431440
"""
432-
Calculate the walking time between two coordinates.
441+
Calculate the walking time and the distance between two coordinates.
433442
434443
Args:
435444
cord1 (tuple): The (latitude, longitude) of the starting point.
@@ -438,12 +447,16 @@ def walking_time(cord1, cord2, walking_speed):
438447
439448
Returns:
440449
float: The walking time in secondes.
450+
float: The distance in meters
441451
"""
452+
cord1 = get_pt_object_coord(object_1)
453+
cord2 = get_pt_object_coord(object_2)
454+
442455
distance = crowfly_distance_between(cord1, cord2)
443-
return get_manhattan_duration(distance, walking_speed)
456+
return get_manhattan_duration(distance, walking_speed), round(distance)
444457

445458

446-
def _get_place(kwargs, uri):
459+
def _get_place(kwargs, pt_object):
447460
"""
448461
Retrieve a place instance based on the provided URI.
449462
@@ -457,6 +470,8 @@ def _get_place(kwargs, uri):
457470
Returns:
458471
PlaceByUri: An instance of PlaceByUri after waiting for the result.
459472
"""
473+
coord = _get_coords_from_pt_object(pt_object)
474+
uri = "{};{}".format(coord.lon, coord.lat)
460475
place_by_uri_instance = PlaceByUri(kwargs["future_manager"], kwargs["instance"], uri, kwargs["request_id"])
461476
return place_by_uri_instance.wait_and_get()
462477

@@ -465,30 +480,30 @@ def _update_fallback_with_bike_mode(
465480
journey, fallback_dp, fallback_period_extremity, fallback_type, via_pt_access, via_poi_access, **kwargs
466481
):
467482
"""
468-
Updates the journey with bike mode fallback sections.
469-
470-
This function updates the journey sections with bike mode fallback sections based on the fallback type
471-
(BEGINNING_FALLBACK or ENDING_FALLBACK). It aligns the fallback direct path datetime, updates the section IDs,
472-
and creates the necessary links between the fallback and public transport parts. It also handles the addition
473-
of POI access points in the sections.
474-
475-
Args:
476-
journey (Journey): The journey object to be updated.
477-
fallback_dp (DirectPath): The direct path object for the fallback.
478-
fallback_period_extremity (datetime): The extremity datetime for the fallback period.
479-
fallback_type (StreetNetworkPathType): The type of fallback (BEGINNING_FALLBACK or ENDING_FALLBACK).
480-
via_pt_access (PtObject): The public transport access point object.
481-
via_poi_access (POIObject): The point of interest access point object.
482-
**kwargs: Additional keyword arguments, including:
483-
- origin_mode (list): The mode of origin (e.g., ["bike"]).
484-
- destination_mode (list): The mode of destination (e.g., ["bike"]).
485-
- future_manager (FutureManager): The future manager instance.
486-
- instance (Instance): The instance object.
487-
- request_id (str): The request ID.
488-
- additional_time (timedelta): The additional time to be added to the sections.
489-
490-
Returns:
491-
None
483+
Updates the journey with bike mode fallback sections.
484+
access_point
485+
This function updates the journey sections with bike mode fallback sections based on the fallback type
486+
(BEGINNING_FALLBACK or ENDING_FALLBACK). It aligns the fallback direct path datetime, updates the section IDs,
487+
and creates the necessary links between the fallback and public transport parts. It also handles the addition
488+
of POI access points in the sections.
489+
490+
Args:
491+
journey (Journey): The journey object to be updated.
492+
fallback_dp (DirectPath): The direct path object for the fallback.
493+
fallback_period_extremity (datetime): The extremity datetime for the fallback period.
494+
fallback_type (StreetNetworkPathType): The type of fallback (BEGINNING_FALLBACK or ENDING_FALLBACK).
495+
via_pt_access (PtObject): The public transport access point object.
496+
via_poi_access (POIObject): The point of interest access point object.
497+
**kwargs: Additional keyword arguments, including:
498+
- origin_mode (list): The mode of origin (e.g., ["bike"]).
499+
- destination_mode (list): The mode of destination (e.g., ["bike"]).
500+
- future_manager (FutureManager): The future manager instance.
501+
- instance (Instance): The instance object.
502+
- request_id (str): The request ID.
503+
- additional_time (timedelta): The additional time to be added to the sections.
504+
505+
Returns:
506+
None
492507
"""
493508
# Validate required arguments
494509
if not all(kwargs.get(key) for key in ("future_manager", "instance", "request_id")):
@@ -500,76 +515,97 @@ def _update_fallback_with_bike_mode(
500515
fallback_sections = aligned_fallback.journeys[0].sections
501516
_rename_fallback_sections_ids(fallback_sections)
502517

503-
# We have to create the link between the fallback and the pt part manually here
504-
if fallback_type == StreetNetworkPathType.BEGINNING_FALLBACK and "bike" in kwargs["origin_mode"]:
505-
address = _get_place(kwargs, fallback_sections[-1].destination.uri)
506-
walktime = walking_time(
507-
address.address.coord,
508-
journey.sections[0].destination.stop_point.coord,
518+
if (
519+
fallback_type == StreetNetworkPathType.BEGINNING_FALLBACK
520+
and fallback_sections[-1].street_network.mode is response_pb2.Bike
521+
):
522+
523+
place = _get_place(kwargs, fallback_sections[-1].destination)
524+
walktime, walking_distance = _get_walking_information(
525+
place,
526+
journey.sections[0].destination,
509527
kwargs["instance"].walking_speed,
510528
)
511-
fallback_sections[-1].destination.CopyFrom(address)
512-
for s in journey.sections:
513-
s.begin_date_time += kwargs["additional_time"] + walktime
514-
s.end_date_time += kwargs["additional_time"] + walktime
529+
530+
fallback_sections[-1].destination.CopyFrom(place)
531+
fallback_sections[-1].end_date_time -= kwargs["additional_time"] + walktime
532+
fallback_sections[-1].begin_date_time -= kwargs["additional_time"] + walktime
515533
park_section = _make_bike_park(fallback_sections[-1].end_date_time, kwargs["additional_time"])
534+
journey.durations.walking += walktime
516535
street_mode_section = _make_bike_park_street_network(
517536
fallback_sections[-1].destination,
518537
park_section.end_date_time,
519538
journey.sections[0].destination,
520539
(fallback_sections[-1].end_date_time + park_section.duration) - journey.sections[0].end_date_time,
521540
walktime,
541+
walking_distance,
522542
)
523543
street_mode_section.street_network.coordinates.extend(
524544
[journey.sections[0].destination.stop_point.coord, fallback_sections[-1].destination.address.coord]
525545
)
526-
_update_journey(journey, park_section, street_mode_section, journey.sections[0], fallback_sections)
527-
if fallback_type == StreetNetworkPathType.BEGINNING_FALLBACK and "bike" not in kwargs["origin_mode"]:
546+
_update_journey(journey, park_section, street_mode_section, journey.sections[0])
547+
if (
548+
fallback_type == StreetNetworkPathType.BEGINNING_FALLBACK
549+
and fallback_sections[-1].street_network.mode is not response_pb2.Bike
550+
):
528551
section_to_replace = journey.sections[0]
529552
journey.sections.remove(section_to_replace)
530553
fallback_sections[-1].destination.CopyFrom(journey.sections[0].origin)
531-
journey.sections.extend(fallback_sections)
532-
elif fallback_type == StreetNetworkPathType.ENDING_FALLBACK and "bike" in kwargs["destination_mode"]:
533-
walktime = walking_time(
534-
journey.sections[-1].origin.stop_point.coord,
535-
fallback_sections[0].origin.address.coord,
554+
elif (
555+
fallback_type == StreetNetworkPathType.ENDING_FALLBACK
556+
and fallback_sections[0].street_network.mode is response_pb2.Bike
557+
):
558+
walktime, walking_distance = _get_walking_information(
559+
journey.sections[-1].origin,
560+
fallback_sections[0].origin,
536561
kwargs["instance"].walking_speed,
537562
)
538-
address = _get_place(kwargs, fallback_sections[0].origin.uri)
539-
fallback_sections[0].origin.CopyFrom(address)
563+
journey.durations.walking += walktime
564+
place = _get_place(kwargs, fallback_sections[0].origin)
565+
fallback_sections[0].origin.CopyFrom(place)
540566
street_mode_section = _make_bike_park_street_network(
541567
journey.sections[-1].origin,
542568
fallback_sections[0].begin_date_time,
543569
fallback_sections[0].origin,
544570
(fallback_sections[0].begin_date_time + kwargs["additional_time"])
545571
- journey.sections[-1].begin_date_time,
546572
walktime,
573+
walking_distance,
547574
)
548575
park_section = _make_bike_park(street_mode_section.begin_date_time, kwargs["additional_time"])
549576
fallback_sections[0].begin_date_time += kwargs["additional_time"]
550577
street_mode_section.street_network.coordinates.extend(
551578
[journey.sections[-1].origin.stop_point.coord, fallback_sections[0].origin.address.coord]
552579
)
553-
_update_journey(journey, park_section, street_mode_section, journey.sections[-1], fallback_sections)
554-
elif fallback_type == StreetNetworkPathType.ENDING_FALLBACK and "bike" not in kwargs["destination_mode"]:
580+
_update_journey(journey, park_section, street_mode_section, journey.sections[-1])
581+
elif (
582+
fallback_type == StreetNetworkPathType.ENDING_FALLBACK
583+
and fallback_sections[0].street_network.mode is not response_pb2.Bike
584+
):
555585
section_to_replace = journey.sections[-1]
556586
journey.sections.remove(section_to_replace)
557587
fallback_sections[0].origin.CopyFrom(journey.sections[-1].destination)
558-
journey.sections.extend(fallback_sections)
559588

560589
add_poi_access_point_in_sections(fallback_type, via_poi_access, fallback_sections)
561590

562591
if isinstance(via_pt_access, type_pb2.PtObject) and via_pt_access.embedded_type == type_pb2.ACCESS_POINT:
563592
if fallback_type == StreetNetworkPathType.BEGINNING_FALLBACK:
564-
journey.sections[-1].vias.add().CopyFrom(via_pt_access.access_point)
565593
target_section = next((s for s in journey.sections if s.id == "Street_network_section_2"), None)
566594
if target_section:
567-
target_section.vias.extend(journey.sections[-1].vias)
595+
target_section.vias.add().CopyFrom(via_pt_access.access_point)
568596
target_section.street_network.path_items.extend(
569-
[journey.sections[-1].street_network.path_items[-1]]
597+
[fallback_sections[-1].street_network.path_items[-1]]
570598
)
599+
fallback_sections[-1].street_network.path_items.pop()
600+
target_section.duration += via_pt_access.access_point.traversal_time
601+
target_section.length += via_pt_access.access_point.length
602+
fallback_sections[-1].duration -= via_pt_access.access_point.traversal_time
603+
else:
604+
fallback_sections[-1].vias.add().CopyFrom(via_pt_access.access_point)
605+
571606
else:
572-
journey.sections[0].vias.add().CopyFrom(via_pt_access.access_point)
607+
fallback_sections[0].vias.add().CopyFrom(via_pt_access.access_point)
608+
journey.sections.extend(fallback_sections)
573609
journey.sections.sort(key=cmp_to_key(SectionSorter()))
574610

575611

@@ -821,9 +857,7 @@ def _build_fallback(
821857
fallback_dp_copy, fallback_type, requested_obj, via_poi_access, language
822858
)
823859

824-
if request["park_mode"] == [ParkMode.on_street.name] and (
825-
request["origin_mode"] == ["bike"] or request["destination_mode"] == ["bike"]
826-
):
860+
if request["park_mode"] == ParkMode.on_street.name:
827861
_update_fallback_with_bike_mode(
828862
pt_journey,
829863
fallback_dp_copy,

0 commit comments

Comments
 (0)