Skip to content

Commit

Permalink
Remove unused routing instruction code
Browse files Browse the repository at this point in the history
  • Loading branch information
PaulPickhardt committed Sep 9, 2024
1 parent e764ffd commit 25ad79a
Show file tree
Hide file tree
Showing 7 changed files with 13 additions and 329 deletions.
1 change: 0 additions & 1 deletion lib/ride/services/audio.dart
Original file line number Diff line number Diff line change
Expand Up @@ -576,7 +576,6 @@ class Audio {
int roundedDistance = (ride!.calcDistanceToNextSG! / 25).ceil() * 25;
InstructionText instructionText = InstructionText(
text: "In $roundedDistance meter $sgType",
type: InstructionTextType.signalGroup,
distanceToNextSg: ride!.calcDistanceToNextSG!,
);

Expand Down
45 changes: 1 addition & 44 deletions lib/routing/models/instruction.dart
Original file line number Diff line number Diff line change
@@ -1,24 +1,7 @@
/// An enum for the type of the custom instruction
/// This type is derived from the InstructionTextType.
enum InstructionType {
directionOnly,
signalGroupOnly,
directionAndSignalGroup,
}

/// An enum for the type of the instruction text.
enum InstructionTextType {
direction,
signalGroup,
}

class InstructionText {
/// The instruction text.
String text;

/// The type of the instruction text.
final InstructionTextType type;

/// The countdown of the instruction
/// Only used for InstructionTextType signalGroup.
int? countdown;
Expand All @@ -29,36 +12,10 @@ class InstructionText {
/// The distance to the next signal group.
double distanceToNextSg = 0;

InstructionText({required this.text, required this.type, this.countdown, required this.distanceToNextSg});
InstructionText({required this.text, this.countdown, required this.distanceToNextSg});

/// Adds a countdown to the instructionText as well as the current timestamp.
void addCountdown(int countdown) {
this.countdown = countdown;
}
}

class Instruction {
/// The instruction latitude.
final double lat;

/// The instruction longitude.
final double lon;

/// The instruction text.
List<InstructionText> text;

/// If the instruction has already been executed.
bool executed = false;

/// The instruction type.
InstructionType instructionType;

/// The ID of the corresponding signal group.
String? signalGroupId;

/// If the instruction has already been concatenated.
bool alreadyConcatenated = false;

Instruction(
{required this.lat, required this.lon, required this.text, required this.instructionType, this.signalGroupId});
}
210 changes: 0 additions & 210 deletions lib/routing/services/routing.dart
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import 'dart:convert';

import 'package:collection/collection.dart';
import 'package:flutter/foundation.dart';
import 'package:latlong2/latlong.dart';
import 'package:priobike/home/models/profile.dart';
Expand All @@ -12,8 +11,6 @@ import 'package:priobike/positioning/services/positioning.dart';
import 'package:priobike/routing/messages/graphhopper.dart';
import 'package:priobike/routing/messages/sgselector.dart';
import 'package:priobike/routing/models/crossing.dart';
import 'package:priobike/routing/models/instruction.dart';
import 'package:priobike/routing/models/navigation.dart';
import 'package:priobike/routing/models/poi.dart';
import 'package:priobike/routing/models/route.dart' as r;
import 'package:priobike/routing/models/sg.dart';
Expand Down Expand Up @@ -533,213 +530,6 @@ class Routing with ChangeNotifier {
notifyListeners();
}

/// Find the waypoint x meters before the current instruction
/// DistanceToInstructionPoint x must be given as an argument.
LatLng? findWaypointMetersBeforeInstruction(int distanceToInstructionPoint, SGSelectorResponse sgSelectorResponse,
int currentNavigationNodeIdx, LatLng? lastInstructionPoint, bool? isFirstInstruction) {
double totalDistanceToInstructionPoint = 0;
LatLng p2 = LatLng(
sgSelectorResponse.route[currentNavigationNodeIdx].lat, sgSelectorResponse.route[currentNavigationNodeIdx].lon);
LatLng p1;
// Iterating backwards from the current navigation node until the first matching node.
for (var j = currentNavigationNodeIdx - 1; j >= 0; j--) {
p1 = LatLng(sgSelectorResponse.route[j].lat, sgSelectorResponse.route[j].lon);

var distanceToPreviousNavigationNode = Snapper.vincenty.distance(p1, p2);
totalDistanceToInstructionPoint += distanceToPreviousNavigationNode;

if (lastInstructionPoint?.latitude == p1.latitude && lastInstructionPoint?.longitude == p1.longitude) {
// there is already an instruction at this instruction point
return null;
}

if (totalDistanceToInstructionPoint == distanceToInstructionPoint) {
return p1;
} else if (totalDistanceToInstructionPoint > distanceToInstructionPoint) {
var distanceBefore = totalDistanceToInstructionPoint - distanceToPreviousNavigationNode;
var remainingDistance = distanceToInstructionPoint - distanceBefore;
// calculate point c between a and b such that distance between b and c is remainingDistance
double bearing = Snapper.vincenty.bearing(p2, p1);
LatLng c = Snapper.vincenty.offset(p2, remainingDistance, bearing);
return c;
}
p2 = p1;
}
return null;
}

/// Get the text of all GraphHopper instructions that belong to a specific waypoint.
String getGHInstructionTextForWaypoint(GHRouteResponsePath path, NavigationNode waypoint) {
List<GHInstruction> instructionList = [];

// Get the GraphHopper coordinates that matches lat and long of current waypoint.
final ghCoordinate = path.points.coordinates
.firstWhereOrNull((element) => element.lat == waypoint.lat && element.lon == waypoint.lon);

if (ghCoordinate != null) {
final index = path.points.coordinates.indexOf(ghCoordinate);

// Get all GraphHopper instructions that match the index of the coordinate.
for (final instruction in path.instructions) {
if (instruction.interval.first == index) {
// Skip waypoint instructions and "Dem Straßenverlauf folgen" instruction after a waypoint.
final isWaypoint = instruction.text.startsWith("Wegpunkt");

int instructionIndex = path.instructions.indexOf(instruction);
final previousInstruction = instructionIndex > 0 ? path.instructions[instructionIndex - 1] : null;
final isFollowTheRouteInstructionAfterWaypoint = instruction.text.startsWith("Dem Straßenverlauf") &&
previousInstruction != null &&
previousInstruction.text.startsWith("Wegpunkt");

if (!isWaypoint && !isFollowTheRouteInstructionAfterWaypoint) {
instructionList.add(instruction);
}
}
}
}

// Compose all ghInstructions for waypoint to a single instruction text.
String completeInstructionText = "";
for (int i = 0; i < instructionList.length; i++) {
completeInstructionText += instructionList[i].text;
if (i < instructionList.length - 1) {
completeInstructionText += " und ";
}
}

return completeInstructionText;
}

/// Get the signal group id that belongs to a specific waypoint.
String? getSignalGroupIdForWaypoint(NavigationNode waypoint, bool hasGHInstruction, double? distance) {
if (!hasGHInstruction && waypoint.distanceToNextSignal == 0.0 && waypoint.signalGroupId != null) {
// if waypoint does not belong to a GHInstruction check if there is a sg at the exact point
return waypoint.signalGroupId;
} else if (hasGHInstruction &&
waypoint.distanceToNextSignal != null &&
waypoint.distanceToNextSignal! <= distance!) {
// if waypoint belongs to a GHInstruction check if there is a sg near the point
return waypoint.signalGroupId;
}
return null;
}

/// Create the instruction text based on the type of instruction.
List<InstructionText> createInstructionText(
bool isFirstCall,
InstructionType instructionType,
String ghInstructionText,
String? signalGroupId,
String laneType,
double distanceToNextSg,
int distanceToNextInstruction) {
String prefix = isFirstCall ? "In $distanceToNextInstruction Metern" : "";
String sgType = (laneType == "Radfahrer") ? "Radampel" : "Ampel";

switch (instructionType) {
case InstructionType.directionOnly:
return [
InstructionText(
text: "$prefix $ghInstructionText",
type: InstructionTextType.direction,
distanceToNextSg: distanceToNextSg)
];
case InstructionType.signalGroupOnly:
return [
InstructionText(
text: "$prefix $sgType", type: InstructionTextType.signalGroup, distanceToNextSg: distanceToNextSg)
];
case InstructionType.directionAndSignalGroup:
return [
InstructionText(
text: "$prefix $ghInstructionText",
type: InstructionTextType.direction,
distanceToNextSg: distanceToNextSg),
InstructionText(text: sgType, type: InstructionTextType.signalGroup, distanceToNextSg: distanceToNextSg)
];
default:
return [];
}
}

/// Get sgType for a specific signal group id.
String getSGTypeForSignalGroupId(String signalGroupId, SGSelectorResponse sgSelectorResponse) {
final signalGroup = sgSelectorResponse.signalGroups[signalGroupId];
return signalGroup!.id;
}

/// Get the actual position of the signal group.
getActualSgPosition(String sgId, SGSelectorResponse sgSelectorResponse) {
final length = sgSelectorResponse.signalGroups[sgId]!.geometry!.length;
final idx = round((length / 2), decimals: 0).toInt();
return sgSelectorResponse.signalGroups[sgId]!.geometry![idx];
}

/// Determine the instruction type after concatenation.
InstructionType getInstructionTypeAfterConcatenation(
InstructionType originalInstructionType, InstructionType addedInstructionType) {
switch (originalInstructionType) {
case InstructionType.signalGroupOnly:
if (addedInstructionType == InstructionType.directionOnly ||
addedInstructionType == InstructionType.directionAndSignalGroup) {
return InstructionType.directionAndSignalGroup;
}
return InstructionType.signalGroupOnly;
case InstructionType.directionOnly:
if (addedInstructionType == InstructionType.signalGroupOnly ||
addedInstructionType == InstructionType.directionAndSignalGroup) {
return InstructionType.directionAndSignalGroup;
}
return InstructionType.directionOnly;
case InstructionType.directionAndSignalGroup:
return InstructionType.directionAndSignalGroup;
}
}

/// Concatenate the current instruction with the previous one.
void concatenateInstructions(InstructionType instructionType, String ghInstructionText, String? signalGroupId,
List<Instruction> instructions, String laneType, int? distanceToActualInstructionPoint) {
if (instructions.last.instructionType == InstructionType.signalGroupOnly &&
instructionType == InstructionType.signalGroupOnly &&
instructions.last.signalGroupId == signalGroupId) {
// Do not concatenate two information about the same signal group.
return;
}
var previousDistToSg = instructions.last.text.last.distanceToNextSg;
var textToConcatenate =
createInstructionText(false, instructionType, ghInstructionText, signalGroupId, laneType, previousDistToSg, 0);
for (int i = 0; i < textToConcatenate.length; i++) {
if (distanceToActualInstructionPoint != null && i == 0) {
textToConcatenate[i].text = "und dann in $distanceToActualInstructionPoint Metern ${textToConcatenate[i].text}";
} else if (i > 0 && instructionType != InstructionType.directionOnly) {
textToConcatenate[i].text = " ${textToConcatenate[i].text}";
} else {
textToConcatenate[i].text = "und dann ${textToConcatenate[i].text}";
}

instructions.last.text.add(textToConcatenate[i]);
}
if (signalGroupId != null) {
instructions.last.signalGroupId = signalGroupId;
}
instructions.last.alreadyConcatenated = true;
instructions.last.instructionType =
getInstructionTypeAfterConcatenation(instructions.last.instructionType, instructionType);
}

/// Determine the type of instruction to be created.
InstructionType? getInstructionType(String ghInstructionText, String? signalGroupId) {
if (ghInstructionText.isNotEmpty && signalGroupId != null) {
return InstructionType.directionAndSignalGroup;
} else if (ghInstructionText.isNotEmpty) {
return InstructionType.directionOnly;
} else if (signalGroupId != null) {
return InstructionType.signalGroupOnly;
} else {
return null;
}
}

/// Select a route.
Future<void> switchToRoute(int idx) async {
if (idx < 0 || idx >= allRoutes!.length) return;
Expand Down
22 changes: 11 additions & 11 deletions lib/settings/services/settings.dart
Original file line number Diff line number Diff line change
Expand Up @@ -457,15 +457,15 @@ class Settings with ChangeNotifier {
}

static const speechRateKey = "priobike.settings.speechRate";
static const defaultSpeechRateFast = SpeechRate.normal;
static const defaultSpeechRate = SpeechRate.normal;

Future<bool> setSpeechRateFast(SpeechRate speechRate, [SharedPreferences? storage]) async {
Future<bool> setSpeechRate(SpeechRate speechRate, [SharedPreferences? storage]) async {
storage ??= await SharedPreferences.getInstance();
final prev = this.speechRate;
this.speechRate = speechRate;
final bool success = await storage.setString(speechRateKey, speechRate.name);
if (!success) {
log.e("Failed to set speechRateFast to $speechRate");
log.e("Failed to set speechRate to $speechRate");
this.speechRate = prev;
} else {
notifyListeners();
Expand Down Expand Up @@ -495,7 +495,7 @@ class Settings with ChangeNotifier {
this.enableSimulatorMode = defaultSimulatorMode,
this.enableLiveTrackingMode = defaultLiveTrackingMode,
this.isIncreasedSpeedPrecisionInSpeedometerEnabled = defaultIsIncreasedSpeedPrecisionInSpeedometerEnabled,
this.speechRate = defaultSpeechRateFast,
this.speechRate = defaultSpeechRate,
});

/// Load the internal settings from the shared preferences.
Expand Down Expand Up @@ -538,13 +538,7 @@ class Settings with ChangeNotifier {
/* Do nothing and use the default value given by the constructor. */
}
try {
audioSpeedAdvisoryInstructionsEnabled =
storage.getBool(audioInstructionsEnabledKey) ?? defaultAudioInstructionsEnabled;
} catch (e) {
/* Do nothing and use the default value given by the constructor. */
}
try {
speechRate = SpeechRate.values.byName(storage.getString(speechRateKey) ?? defaultSpeechRateFast.name);
speechRate = SpeechRate.values.byName(storage.getString(speechRateKey) ?? defaultSpeechRate.name);
} catch (e) {
/* Do nothing and use the default value given by the constructor. */
}
Expand Down Expand Up @@ -588,6 +582,12 @@ class Settings with ChangeNotifier {
} catch (e) {
/* Do nothing and use the default value given by the constructor. */
}
try {
audioSpeedAdvisoryInstructionsEnabled =
storage.getBool(audioInstructionsEnabledKey) ?? defaultAudioInstructionsEnabled;
} catch (e) {
/* Do nothing and use the default value given by the constructor. */
}

hasLoaded = true;
notifyListeners();
Expand Down
2 changes: 1 addition & 1 deletion lib/settings/views/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -215,7 +215,7 @@ class SettingsViewState extends State<SettingsView> {
/// A callback that is executed when a tracking submission policy is selected.
Future<void> onSelectSpeechRate(SpeechRate speechRate) async {
// Tell the settings service that we selected the new tracking submission policy.
await settings.setSpeechRateFast(speechRate);
await settings.setSpeechRate(speechRate);

if (mounted) Navigator.pop(context);
}
Expand Down
Loading

0 comments on commit 25ad79a

Please sign in to comment.