Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: added CAB start and end signaling (#82) #442

Merged
merged 12 commits into from
Dec 12, 2024
Merged
21 changes: 1 addition & 20 deletions das_client/analysis_options.yaml
Original file line number Diff line number Diff line change
@@ -1,32 +1,13 @@
# This file configures the analyzer, which statically analyzes Dart code to
# check for errors, warnings, and lints.
#
# The issues identified by the analyzer are surfaced in the UI of Dart-enabled
# IDEs (https://dart.dev/tools#ides-and-editors). The analyzer can also be
# invoked from the command line by running `flutter analyze`.

# The following line activates a set of recommended lints for Flutter apps,
# packages, and plugins designed to encourage good coding practices.
include: package:flutter_lints/flutter.yaml

linter:
# The lint rules applied to this project can be customized in the
# section below to disable rules from the `package:flutter_lints/flutter.yaml`
# included above or to enable additional rules. A list of all available lints
# and their documentation is published at
# https://dart-lang.github.io/linter/lints/index.html.
#
# Instead of disabling a lint rule for the entire project in the
# section below, it can also be suppressed for a single line of code
# or a specific dart file by using the `// ignore: name_of_lint` and
# `// ignore_for_file: name_of_lint` syntax on the line or in the file
# producing the lint.
rules:
always_use_package_imports: true
prefer_single_quotes: true
prefer_final_in_for_each: true
prefer_final_locals: true
prefer_final_fields: true
always_put_required_named_parameters_first: true

# Additional information about this file can be found at
# https://dart.dev/guides/language/analysis-options
Expand Down
5 changes: 5 additions & 0 deletions das_client/assets/icons/icon_cab_end.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 4 additions & 0 deletions das_client/assets/icons/icon_cab_start.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
51 changes: 50 additions & 1 deletion das_client/integration_test/test/train_journey_table_test.dart
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import 'package:das_client/app/pages/journey/train_journey/widgets/table/additional_speed_restriction_row.dart';
import 'package:das_client/app/pages/journey/train_journey/widgets/table/cab_signaling_row.dart';
import 'package:das_client/app/pages/journey/train_journey/widgets/table/cells/bracket_station_body.dart';
import 'package:das_client/app/pages/journey/train_journey/widgets/table/cells/route_cell_body.dart';
import 'package:das_client/app/pages/journey/train_journey/widgets/table/curve_point_row.dart';
Expand Down Expand Up @@ -150,8 +151,11 @@ void main() {
expect(scrollableFinder, findsOneWidget);

final stopRouteRow = findDASTableRowByText('Bahnhof A');
final nonStoppingPassRouteRow = findDASTableRowByText('Haltestelle B');
expect(stopRouteRow, findsOneWidget);

await tester.dragUntilVisible(findDASTableRowByText('Haltestelle B'), scrollableFinder, const Offset(0, -50));

final nonStoppingPassRouteRow = findDASTableRowByText('Haltestelle B');
expect(nonStoppingPassRouteRow, findsOneWidget);

// check stop circles
Expand Down Expand Up @@ -418,6 +422,51 @@ void main() {
find.descendant(of: blockIntermediateSignalRow, matching: find.byKey(SignalRow.signalLineChangeIconKey));
expect(noLaneChangeIcon2, findsNothing);
});

testWidgets('test if CAB signaling is displayed correctly', (tester) async {
await prepareAndStartApp(tester);

// load train journey by filling out train selection page
await _loadTrainJourney(tester, trainNumber: 'T1');

final scrollableFinder = find.byType(ListView);
expect(scrollableFinder, findsOneWidget);

// CAB segment with start outside train journey and end at 33.8 km
await tester.dragUntilVisible(find.text('29.7').first, scrollableFinder, const Offset(0, -50));
final rowsAtKm33_8 = findDASTableRowByText('33.8');
expect(rowsAtKm33_8, findsExactly(2));
final segment1CABStop = rowsAtKm33_8.last; // end should be after other elements at same location
final segment1CABStopIcon = find.descendant(of: segment1CABStop, matching: find.byKey(CABSignalingRow.cabSignalingEndIconKey));
expect(segment1CABStopIcon, findsOneWidget);

// Track equipment segment without ETCS level 2 should be ignored
await tester.dragUntilVisible(find.text('12.5').first, scrollableFinder, const Offset(0, -50));
final etcsL1LSEnd = findDASTableRowByText('10.1');
expect(etcsL1LSEnd, findsNothing);

// CAB segment between km 12.5 - km 39.9
final rowsAtKm12_5 = findDASTableRowByText('12.5');
expect(rowsAtKm12_5, findsExactly(2));
final segment2CABStart = rowsAtKm12_5.first; // start should be before other elements at same location
final segment2CABStartIcon = find.descendant(of: segment2CABStart, matching: find.byKey(CABSignalingRow.cabSignalingStartIconKey));
expect(segment2CABStartIcon, findsOneWidget);
await tester.dragUntilVisible(find.text('75.3'), scrollableFinder, const Offset(0, -50));
final trackEquipmentTypeChange = findDASTableRowByText('56.8');
expect(trackEquipmentTypeChange, findsNothing); // no CAB signaling at connecting ETCS L2 segments
await tester.dragUntilVisible(find.text('41.5'), scrollableFinder, const Offset(0, -50));
final rothristServicePointRow = findDASTableRowByText('46.2');
expect(rothristServicePointRow, findsOneWidget); // no CAB signaling at connecting ETCS L2 segments
final segment2CABEnd = findDASTableRowByText('39.9');
final segment2CABEndIcon = find.descendant(of: segment2CABEnd, matching: find.byKey(CABSignalingRow.cabSignalingEndIconKey));
expect(segment2CABEndIcon, findsOneWidget);

// CAB segment with end outside train journey and start at 8.3 km
await tester.dragUntilVisible(find.text('9.5'), scrollableFinder, const Offset(0, -50));
final segment3CABStart = findDASTableRowByText('8.3');
final segment3CABStartIcon = find.descendant(of: segment3CABStart, matching: find.byKey(CABSignalingRow.cabSignalingStartIconKey));
expect(segment3CABStartIcon, findsOneWidget);
});
});
}

Expand Down
2 changes: 1 addition & 1 deletion das_client/ios/Podfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -68,4 +68,4 @@ SPEC CHECKSUMS:

PODFILE CHECKSUM: d9dad56c0cd0b4fd8b4fe3034a53fd42a0b990f6

COCOAPODS: 1.15.2
COCOAPODS: 1.16.1
2 changes: 1 addition & 1 deletion das_client/lib/app/bloc/train_journey_cubit.dart
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ class TrainJourneyCubit extends Cubit<TrainJourneyState> {

void reset() {
if (state is BaseTrainJourneyState) {
Fimber.i('Reseting TrainJourney cubit in state $state');
Fimber.i('Resetting TrainJourney cubit in state $state');
emit(SelectingTrainJourneyState(
trainNumber: (state as BaseTrainJourneyState).trainNumber,
date: DateTime.now(),
Expand Down
2 changes: 1 addition & 1 deletion das_client/lib/app/bloc/train_journey_state.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ part of 'train_journey_cubit.dart';
sealed class TrainJourneyState {}

final class SelectingTrainJourneyState extends TrainJourneyState {
SelectingTrainJourneyState({this.ru, this.trainNumber, required this.date, this.errorCode});
SelectingTrainJourneyState({required this.date, this.ru, this.trainNumber, this.errorCode});

final String? trainNumber;
final Ru? ru;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import 'package:design_system_flutter/design_system_flutter.dart';
import 'package:flutter/material.dart';

class ADLNotification extends StatelessWidget {
const ADLNotification({super.key, required this.message, this.margin});
const ADLNotification({required this.message, super.key, this.margin});

final String message;
final EdgeInsetsGeometry? margin;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,14 @@ import 'package:flutter/material.dart';
import 'package:flutter_svg/flutter_svg.dart';

class AdditionalSpeedRestrictionRow extends BaseRowBuilder<AdditionalSpeedRestrictionData> {
static const Key additionalSpeedRestrictionIconKey = Key('addition_speed_restrction_icon_key');
static const Key additionalSpeedRestrictionIconKey = Key('addition_speed_restriction_icon_key');
static const Color additionalSpeedRestrictionColor = SBBColors.orange;
static const double rowHeight = 44.0;

AdditionalSpeedRestrictionRow({
super.height = 44.0,
required super.metadata,
required super.data,
super.height = rowHeight,
}) : super(rowColor: additionalSpeedRestrictionColor);

@override
Expand All @@ -33,11 +34,12 @@ class AdditionalSpeedRestrictionRow extends BaseRowBuilder<AdditionalSpeedRestri
@override
DASTableCell iconsCell2(BuildContext context) {
return DASTableCell(
child: SvgPicture.asset(
AppAssets.iconAdditionalSpeedRestriction,
key: additionalSpeedRestrictionIconKey,
),
alignment: Alignment.center);
child: SvgPicture.asset(
AppAssets.iconAdditionalSpeedRestriction,
key: additionalSpeedRestrictionIconKey,
),
alignment: Alignment.center,
);
}

@override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,14 @@ import 'package:das_client/model/journey/metadata.dart';
import 'package:flutter/material.dart';

class BaseRowBuilder<T extends BaseData> extends DASTableRowBuilder {
static const double rowHeight = 44.0;

const BaseRowBuilder({
super.height = 44.0,
this.defaultAlignment = Alignment.bottomCenter,
this.rowColor,
required this.metadata,
required this.data,
super.height = rowHeight,
this.defaultAlignment = Alignment.bottomCenter,
this.rowColor,
});

final Alignment defaultAlignment;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import 'package:das_client/app/pages/journey/train_journey/widgets/table/base_row_builder.dart';
import 'package:das_client/app/widgets/assets.dart';
import 'package:das_client/app/widgets/table/das_table_cell.dart';
import 'package:das_client/model/journey/cab_signaling.dart';
import 'package:flutter/material.dart';
import 'package:flutter_svg/flutter_svg.dart';

class CABSignalingRow extends BaseRowBuilder<CABSignaling> {
static const Key cabSignalingStartIconKey = Key('cab_signaling_start_icon_key');
static const Key cabSignalingEndIconKey = Key('cab_signaling_end_icon_key');

CABSignalingRow({
required super.metadata,
required super.data,
});

@override
DASTableCell iconsCell1(BuildContext context) {
return DASTableCell(
child: SvgPicture.asset(
key: data.isStart ? cabSignalingStartIconKey : cabSignalingEndIconKey,
data.isStart ? AppAssets.iconCabStart : AppAssets.iconCabEnd,
),
alignment: Alignment.center,
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@ class BracketStationBody extends StatelessWidget {
static const double _bracketStationFontSize = 12.0;

const BracketStationBody({
super.key,
required this.bracketStation,
required this.height
required this.height,
super.key,
});

final BracketStation bracketStation;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,11 +54,7 @@ class RouteCellBody extends StatelessWidget {
final isDarkTheme = SBBBaseStyle.of(context).brightness == Brightness.dark;
final lineColor = isDarkTheme ? SBBColors.white : SBBColors.black;
return Positioned(
key: isRouteStart
? routeStartKey
: isRouteEnd
? routeEndKey
: null,
key: _routeKey(),
top: isRouteStart ? height - sbbDefaultSpacing : -sbbDefaultSpacing,
bottom: isRouteEnd ? sbbDefaultSpacing : -sbbDefaultSpacing,
right: 0,
Expand Down Expand Up @@ -87,6 +83,13 @@ class RouteCellBody extends StatelessWidget {
),
);
}

Key? _routeKey() {
if (!isRouteStart && !isRouteEnd) {
return null;
}
return isRouteStart ? routeStartKey : routeEndKey;
}
}

class _RouteCircle extends StatelessWidget {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,12 @@ import 'package:flutter_svg/flutter_svg.dart';

class ProtectionSectionRow extends BaseRowBuilder<ProtectionSection> {
static const Key protectionSectionKey = Key('protection_section_key');
static const double rowHeight = 44.0;

ProtectionSectionRow({
super.height = 44.0,
required super.metadata,
required super.data,
super.height = rowHeight,
}) : super(rowColor: SBBColors.peach);

@override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,12 @@ import 'package:flutter_svg/flutter_svg.dart';
class ServicePointRow extends BaseRowBuilder<ServicePoint> {
static const Key stopOnRequestKey = Key('stop_on_request_key');

static const double rowHeight = 64.0;

ServicePointRow({
super.height = 64.0,
required super.metadata,
required super.data,
super.height = rowHeight,
}) : super(rowColor: metadata.nextStop == data ? SBBColors.royal.withOpacity(0.2) : Colors.transparent);

@override
Expand Down Expand Up @@ -49,7 +51,7 @@ class ServicePointRow extends BaseRowBuilder<ServicePoint> {
if (data.bracketStation != null)
BracketStationBody(
bracketStation: data.bracketStation!,
height: height!,
height: height,
),
if (!data.mandatoryStop)
Align(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import 'package:das_client/app/bloc/train_journey_cubit.dart';
import 'package:das_client/app/i18n/i18n.dart';
import 'package:das_client/app/pages/journey/train_journey/widgets/table/additional_speed_restriction_row.dart';
import 'package:das_client/app/pages/journey/train_journey/widgets/table/connection_track_row.dart';
import 'package:das_client/app/pages/journey/train_journey/widgets/table/cab_signaling_row.dart';
import 'package:das_client/app/pages/journey/train_journey/widgets/table/curve_point_row.dart';
import 'package:das_client/app/pages/journey/train_journey/widgets/table/protection_section_row.dart';
import 'package:das_client/app/pages/journey/train_journey/widgets/table/service_point_row.dart';
Expand All @@ -12,6 +13,7 @@ import 'package:das_client/app/widgets/table/das_table_column.dart';
import 'package:das_client/app/widgets/table/das_table_row.dart';
import 'package:das_client/model/journey/additional_speed_restriction_data.dart';
import 'package:das_client/model/journey/connection_track.dart';
import 'package:das_client/model/journey/cab_signaling.dart';
import 'package:das_client/model/journey/curve_point.dart';
import 'package:das_client/model/journey/datatype.dart';
import 'package:das_client/model/journey/journey.dart';
Expand Down Expand Up @@ -73,6 +75,11 @@ class TrainJourney extends StatelessWidget {
return ConnectionTrackRow(metadata: journey.metadata, data: rowData as ConnectionTrack).build(context);
case Datatype.speedChange:
return SpeedChangeRow(metadata: journey.metadata, data: rowData as SpeedChange).build(context);
case Datatype.cabSignaling:
return CABSignalingRow(
metadata: journey.metadata,
data: rowData as CABSignaling,
).build(context);
}
});
}
Expand Down
2 changes: 1 addition & 1 deletion das_client/lib/app/widgets/app_version_text.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import 'package:flutter/material.dart';
import 'package:package_info_plus/package_info_plus.dart';

class AppVersionText extends StatelessWidget {
const AppVersionText({super.key, required this.color});
const AppVersionText({required this.color, super.key});

final Color color;

Expand Down
2 changes: 2 additions & 0 deletions das_client/lib/app/widgets/assets.dart
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,6 @@ class AppAssets {
static const iconAdditionalSpeedRestriction = '$_iconsDir/icon_additional_speed_restriction.svg';
static const iconCurveStart = '$_iconsDir/icon_curve_start.svg';
static const iconSignalLaneChange = '$_iconsDir/icon_signal_line_change.svg';
static const iconCabStart = '$_iconsDir/icon_cab_start.svg';
static const iconCabEnd = '$_iconsDir/icon_cab_end.svg';
}
2 changes: 1 addition & 1 deletion das_client/lib/app/widgets/device_id_text.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import 'package:design_system_flutter/design_system_flutter.dart';
import 'package:flutter/material.dart';

class DeviceIdText extends StatelessWidget {
const DeviceIdText({super.key, required this.color});
const DeviceIdText({required this.color, super.key});

final Color color;

Expand Down
2 changes: 1 addition & 1 deletion das_client/lib/app/widgets/header.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import 'package:design_system_flutter/design_system_flutter.dart';
import 'package:flutter/material.dart';

class Header extends StatelessWidget {
const Header({super.key, required this.child});
const Header({required this.child, super.key});

final Widget child;

Expand Down
Loading
Loading