diff --git a/src/c3nav/mapdata/views.py b/src/c3nav/mapdata/views.py index 2fe06914..d8399b74 100644 --- a/src/c3nav/mapdata/views.py +++ b/src/c3nav/mapdata/views.py @@ -21,6 +21,7 @@ from c3nav.mapdata.render.engines import ImageRenderEngine from c3nav.mapdata.render.engines.base import FillAttribs, StrokeAttribs from c3nav.mapdata.render.renderer import MapRenderer from c3nav.mapdata.utils.cache import CachePackage, MapHistory +from c3nav.mapdata.utils.locations import visible_locations_for_request from c3nav.mapdata.utils.tiles import (build_access_cache_key, build_base_cache_key, build_tile_access_cookie, build_tile_etag, get_tile_bounds, parse_tile_access_cookie) @@ -219,11 +220,13 @@ def preview_route(request, slug, slug2): from c3nav.mapdata.utils.geometry import unwrap_geom origin = check_location(slug, None) destination = check_location(slug2, None) + visible_locations = visible_locations_for_request(request) try: route = Router.load().get_route(origin=origin, destination=destination, permissions=set(), - options=RouteOptions()) + options=RouteOptions(), + visible_locations=visible_locations) except NotYetRoutable: raise Http404() except LocationUnreachable: diff --git a/src/c3nav/routing/api/positioning.py b/src/c3nav/routing/api/positioning.py index 45379fda..6f5f1449 100644 --- a/src/c3nav/routing/api/positioning.py +++ b/src/c3nav/routing/api/positioning.py @@ -52,7 +52,7 @@ def get_position(request, parameters: LocateRequestSchema): raise return { - "location": location.serialize(simple_geometry=True) if location else None, + "location": location } @@ -94,7 +94,7 @@ def locate_test(request): return { "ranges": msg.parsed.model_dump(mode="json")["ranges"], "datetime": msg.datetime, - "location": location.serialize(simple_geometry=True) if location else None + "location": location } diff --git a/src/c3nav/routing/api/routing.py b/src/c3nav/routing/api/routing.py index 91870812..4b606daf 100644 --- a/src/c3nav/routing/api/routing.py +++ b/src/c3nav/routing/api/routing.py @@ -3,6 +3,7 @@ from typing import Annotated, Any, Optional, Union from django.core.exceptions import ValidationError from django.conf import settings +from django.db.models import Model from django.urls import reverse from django.utils.translation import gettext_lazy as _ from ninja import Field as APIField @@ -212,11 +213,14 @@ def get_route(request, parameters: RouteParametersSchema): if parameters.options_override is not None: _new_update_route_options(options, parameters.options_override) + visible_locations = visible_locations_for_request(request) + try: route = Router.load().get_route(origin=form.cleaned_data['origin'], destination=form.cleaned_data['destination'], permissions=AccessPermission.get_for_request(request), - options=options) + options=options, + visible_locations=visible_locations) except NotYetRoutable: return NoRouteResponse( request=parameters, @@ -256,7 +260,7 @@ def get_route(request, parameters: RouteParametersSchema): 'destination': parameters.destination, 'options': options.serialize_string(), }), - result=route.serialize(locations=visible_locations_for_request(request)), + result=route.serialize(), ) diff --git a/src/c3nav/routing/route.py b/src/c3nav/routing/route.py index 43287396..25d70355 100644 --- a/src/c3nav/routing/route.py +++ b/src/c3nav/routing/route.py @@ -21,7 +21,8 @@ def describe_location(location, locations): class Route: def __init__(self, router, origin, destination, path_nodes, options, - origin_addition, destination_addition, origin_xyz, destination_xyz): + origin_addition, destination_addition, origin_xyz, destination_xyz, + visible_locations): self.router = router self.origin = origin self.destination = destination @@ -31,8 +32,9 @@ class Route: self.destination_addition = destination_addition self.origin_xyz = origin_xyz self.destination_xyz = destination_xyz + self.visible_locations = visible_locations - def serialize(self, locations): + def serialize(self): # todo: move this into schema nodes = [[node, None] for node in self.path_nodes] if self.origin_addition and any(self.origin_addition): nodes.insert(0, (self.origin_addition[0], None)) @@ -161,6 +163,20 @@ class Route: distance_str = '%d m' % distance summary = '%s (%s)' % (duration_str, distance_str) + return OrderedDict(( + ('origin', describe_location(self.origin, self.visible_locations)), + ('destination', describe_location(self.destination, self.visible_locations)), + ('distance', round(distance, 2)), + ('duration', round(duration)), + ('distance_str', distance_str), + ('duration_str', duration_str), + ('summary', summary), + ('options_summary', self.options_summary), + ('items', tuple(item.serialize(locations=self.visible_locations) for item in items)), + )) + + @property + def options_summary(self): options_summary = [ { 'fastest': _('fastest route'), @@ -183,19 +199,7 @@ class Route: if len(options_summary) == 1: options_summary.append(_('default options')) - options_summary = ', '.join(str(s) for s in options_summary) - - return OrderedDict(( - ('origin', describe_location(self.origin, locations)), - ('destination', describe_location(self.destination, locations)), - ('distance', round(distance, 2)), - ('duration', round(duration)), - ('distance_str', distance_str), - ('duration_str', duration_str), - ('summary', summary), - ('options_summary', options_summary), - ('items', tuple(item.serialize(locations=locations) for item in items)), - )) + return ', '.join(str(s) for s in options_summary) class RouteItem: @@ -232,7 +236,7 @@ class RouteItem: def new_level(self): return not self.last_item or self.level.pk != self.last_item.level.pk - def serialize(self, locations): + def serialize(self): # todo: move this into schema result = OrderedDict(( ('id', self.node.pk), ('coordinates', (self.node.x, self.node.y, self.node.altitude)), @@ -243,10 +247,10 @@ class RouteItem: result['waytype'] = self.waytype.serialize(detailed=False) if self.new_space: - result['space'] = describe_location(self.space, locations) + result['space'] = describe_location(self.space, self.route.visible_locations) if self.new_level: - result['level'] = describe_location(self.level, locations) + result['level'] = describe_location(self.level, self.route.visible_locations) result['descriptions'] = [(icon, instruction) for (icon, instruction) in self.descriptions] return result diff --git a/src/c3nav/routing/router.py b/src/c3nav/routing/router.py index 3bb171f7..022a17ee 100644 --- a/src/c3nav/routing/router.py +++ b/src/c3nav/routing/router.py @@ -484,7 +484,7 @@ class Router: pk: restriction for pk, restriction in self.restrictions.items() if pk not in permissions }) - def get_route(self, origin, destination, permissions, options): + def get_route(self, origin, destination, permissions, options, visible_locations): restrictions = self.get_restrictions(permissions) # get possible origins and destinations @@ -527,7 +527,8 @@ class Router: destination_xyz = destination.xyz if isinstance(destination, RouterPoint) else None return Route(self, origin, destination, path_nodes, options, - origin_addition, destination_addition, origin_xyz, destination_xyz) + origin_addition, destination_addition, origin_xyz, destination_xyz, + visible_locations) CustomLocationDescription = namedtuple('CustomLocationDescription', ('space', 'altitude',