feat(train): routes planned through the instance's BRouter (ADR 0030, D44)

The routing endpoint plans a route through the waypoints for one of six
profiles, for the people signed in, at most 50 waypoints and 30 plans a
person a minute, nothing kept or logged; refused without BROUTER_URL.
BRouter's GeoJSON is read into points, elevations, climb and descent
above 3 m, turn hints and stretches by surface. Train's running profile
for BRouter, halkyon-run.brf, is a first guess not yet tried on BRouter.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
This commit is contained in:
Tizian 「ティツィアーン」 2026-10-28 23:37:47 +01:00
commit 781576726a
Signed by: raisondetredev
GPG key ID: 07F6FCF405488B64

View file

@ -20,6 +20,12 @@ import 'package:halkyon_train_server/src/generated/future_calls.dart'
as _i59xasdy;
import 'package:halkyon_train_server/src/generated/map/map_source.dart'
as _ip8bmyd2;
import 'package:halkyon_train_server/src/generated/routing/planned_route.dart'
as _ij0vvqxn;
import 'package:halkyon_train_server/src/generated/routing/route_point.dart'
as _is4pcfub;
import 'package:halkyon_train_server/src/generated/routing/route_profile.dart'
as _iex9meso;
import 'package:serverpod/serverpod.dart' as _is;
import 'package:serverpod_test/serverpod_test.dart' as _ist;
import 'package:halkyon_train_server/src/generated/protocol.dart';
@ -160,6 +166,8 @@ class TestEndpoints {
late final _FirmwareEndpoint firmware;
late final _MapEndpoint map;
late final _RoutingEndpoint routing;
}
class _InternalTestEndpoints extends TestEndpoints
@ -177,6 +185,10 @@ class _InternalTestEndpoints extends TestEndpoints
endpoints,
serializationManager,
);
routing = _RoutingEndpoint(
endpoints,
serializationManager,
);
}
}
@ -336,6 +348,80 @@ class _MapEndpoint {
}
}
class _RoutingEndpoint {
_RoutingEndpoint(
this._endpointDispatch,
this._serializationManager,
);
final _is.EndpointDispatch _endpointDispatch;
final _is.SerializationManager _serializationManager;
_ida.Future<bool> offered(_ist.TestSessionBuilder sessionBuilder) async {
return _ist.callAwaitableFunctionAndHandleExceptions(() async {
var _localUniqueSession =
(sessionBuilder as _ist.InternalTestSessionBuilder).internalBuild(
endpoint: 'routing',
method: 'offered',
);
try {
var _localCallContext = await _endpointDispatch.getMethodCallContext(
createSessionCallback: (_) => _localUniqueSession,
endpointPath: 'routing',
methodName: 'offered',
parameters: _ist.testObjectToJson({}),
serializationManager: _serializationManager,
);
var _localReturnValue =
await (_localCallContext.method.call(
_localUniqueSession,
_localCallContext.arguments,
)
as _ida.Future<bool>);
return _localReturnValue;
} finally {
await _localUniqueSession.close();
}
});
}
_ida.Future<_ij0vvqxn.PlannedRoute> plan(
_ist.TestSessionBuilder sessionBuilder,
List<_is4pcfub.RoutePoint> waypoints,
_iex9meso.RouteProfile profile,
) async {
return _ist.callAwaitableFunctionAndHandleExceptions(() async {
var _localUniqueSession =
(sessionBuilder as _ist.InternalTestSessionBuilder).internalBuild(
endpoint: 'routing',
method: 'plan',
);
try {
var _localCallContext = await _endpointDispatch.getMethodCallContext(
createSessionCallback: (_) => _localUniqueSession,
endpointPath: 'routing',
methodName: 'plan',
parameters: _ist.testObjectToJson({
'waypoints': waypoints,
'profile': profile,
}),
serializationManager: _serializationManager,
);
var _localReturnValue =
await (_localCallContext.method.call(
_localUniqueSession,
_localCallContext.arguments,
)
as _ida.Future<_ij0vvqxn.PlannedRoute>);
return _localReturnValue;
} finally {
await _localUniqueSession.close();
}
});
}
}
class _PruningFutureCall {
Future<void> pruneAccounts(_ist.TestSessionBuilder sessionBuilder) async {
var _localUniqueSession =