From 84177544036c1bee1a2be3d125be009772e15f90 Mon Sep 17 00:00:00 2001 From: Spythere Date: Sun, 19 May 2024 19:50:01 +0200 Subject: [PATCH 01/13] refactor: optimization of train schedules --- src/components/App/UpdateModal.vue | 5 +- src/components/SceneryView/SceneryInfo.vue | 2 +- .../SceneryInfo/SceneryInfoUserList.vue | 60 ++++-- .../SceneryView/SceneryTimetable.vue | 185 ++++++++++++------ .../SceneryView/ScheduledTrainStatus.vue | 26 ++- src/components/SceneryView/typings.ts | 13 ++ src/components/SceneryView/utils.ts | 42 ++++ src/components/Tooltip/UsersTooltip.vue | 4 +- src/components/TrainsView/TrainModal.vue | 2 +- src/components/TrainsView/TrainTable.vue | 6 +- src/store/mainStore.ts | 107 ++++++---- src/store/typings.ts | 2 +- src/store/utils.ts | 174 ---------------- src/typings/api.ts | 1 - src/typings/common.ts | 58 +----- 15 files changed, 331 insertions(+), 356 deletions(-) create mode 100644 src/components/SceneryView/typings.ts create mode 100644 src/components/SceneryView/utils.ts diff --git a/src/components/App/UpdateModal.vue b/src/components/App/UpdateModal.vue index 7bf6ea0..23d5124 100644 --- a/src/components/App/UpdateModal.vue +++ b/src/components/App/UpdateModal.vue @@ -60,10 +60,7 @@ export default defineComponent({ htmlChangelog() { if (this.mainStore.appUpdate == null) return ''; - const x = converter.makeHtml(this.mainStore.appUpdate.changelog); - console.log(x); - - return x; + return converter.makeHtml(this.mainStore.appUpdate.changelog); } }, diff --git a/src/components/SceneryView/SceneryInfo.vue b/src/components/SceneryView/SceneryInfo.vue index 1b0a2ef..120daf5 100644 --- a/src/components/SceneryView/SceneryInfo.vue +++ b/src/components/SceneryView/SceneryInfo.vue @@ -72,7 +72,7 @@
- + diff --git a/src/components/SceneryView/SceneryInfo/SceneryInfoUserList.vue b/src/components/SceneryView/SceneryInfo/SceneryInfoUserList.vue index 06db7fb..3f2ab4d 100644 --- a/src/components/SceneryView/SceneryInfo/SceneryInfoUserList.vue +++ b/src/components/SceneryView/SceneryInfo/SceneryInfoUserList.vue @@ -13,13 +13,13 @@
  • {{ train.trainNo }} {{ train.driverName }} @@ -32,7 +32,9 @@ import { PropType, defineComponent } from 'vue'; import modalTrainMixin from '../../../mixins/modalTrainMixin'; import routerMixin from '../../../mixins/routerMixin'; -import { ActiveScenery } from '../../../typings/common'; +import { ActiveScenery, Station, StopStatus } from '../../../typings/common'; +import { getTrainStopStatus } from '../utils'; +import { useMainStore } from '../../../store/mainStore'; export default defineComponent({ mixins: [routerMixin, modalTrainMixin], @@ -41,6 +43,38 @@ export default defineComponent({ onlineScenery: { type: Object as PropType, required: false + }, + station: { + type: Object as PropType + } + }, + + data() { + return { + mainStore: useMainStore() + }; + }, + + computed: { + stationTrains() { + if (!this.onlineScenery) return; + + const name = this.station?.generalInfo?.checkpoints[0] ?? this.onlineScenery.name; + + return this.onlineScenery.stationTrains.map((train) => { + const stop = train.timetableData?.followingStops.find( + (stop) => stop.stopNameRAW.toLowerCase() == name.toLowerCase() + ); + + const status = stop + ? getTrainStopStatus(stop, train.currentStationName, this.onlineScenery!.name) + : 'no-timetable'; + + return { + train, + status + }; + }); } } }); @@ -74,31 +108,31 @@ ul { -webkit-transition: background-color 200ms; } - &.no-timetable .user_train { + &[data-status='no-timetable'] .user_train { background-color: $no-timetable; } - &.departed > &_train { + &[data-status='departed'] > &_train { background-color: $departed; } - &.stopped > &_train { + &[data-status='stopped'] > &_train { background-color: $stopped; } - &.online > &_train { + &[data-status='online'] > &_train { background-color: $online; } - &.terminated > &_train { + &[data-status='terminated'] > &_train { background-color: $terminated; } - &.disconnected > &_train { + &[data-status='disconnected'] > &_train { background-color: $disconnected; } - &.offline { + &[data-status='offline'] { background: firebrick; pointer-events: none; } diff --git a/src/components/SceneryView/SceneryTimetable.vue b/src/components/SceneryView/SceneryTimetable.vue index a1e451f..908a4fa 100644 --- a/src/components/SceneryView/SceneryTimetable.vue +++ b/src/components/SceneryView/SceneryTimetable.vue @@ -40,7 +40,7 @@
    @@ -48,7 +48,7 @@ {{ $t('scenery.offline') }} @@ -56,7 +56,7 @@
    {{ $t('scenery.no-timetables') }} @@ -65,59 +65,56 @@
    - {{ scheduledTrain.category }} - {{ scheduledTrain.trainNo }} + {{ row.train.timetableData!.category }} + {{ row.train.trainNo }} - +  |  - {{ scheduledTrain.driverName }} + {{ row.train.driverName }}
    - {{ scheduledTrain.beginsAt }} - {{ scheduledTrain.terminatesAt }} + {{ row.train.timetableData!.route.replace('|', ' - ') }}
    - +
    - + {{ $t('timetables.begins') }} -
    - {{ timestampToString(scheduledTrain.stopInfo.arrivalTimestamp) }} +
    + {{ timestampToString(row.checkpointStop.arrivalTimestamp) }}
    {{ - timestampToString(scheduledTrain.stopInfo.arrivalTimestamp) + timestampToString(row.checkpointStop.arrivalTimestamp) }}
    - {{ timestampToString(scheduledTrain.stopInfo.arrivalRealTimestamp) }} - ({{ scheduledTrain.stopInfo.arrivalDelay > 0 ? '+' : '' - }}{{ scheduledTrain.stopInfo.arrivalDelay }}) + {{ timestampToString(row.checkpointStop.arrivalRealTimestamp) }} + ({{ row.checkpointStop.arrivalDelay > 0 ? '+' : '' + }}{{ row.checkpointStop.arrivalDelay }})
    @@ -125,41 +122,39 @@ - {{ scheduledTrain.arrivingLine }} + {{ row.arrivingLine }} - {{ scheduledTrain.stopInfo.stopTime || '' }} - {{ - scheduledTrain.stopInfo.stopTime ? scheduledTrain.stopInfo.stopType || 'pt' : '' - }} + {{ row.checkpointStop.stopTime || '' }} + {{ row.checkpointStop.stopTime ? row.checkpointStop.stopType || 'pt' : '' }} - {{ scheduledTrain.departureLine }} + {{ row.departureLine }} - + {{ $t('timetables.terminates') }} -
    - {{ timestampToString(scheduledTrain.stopInfo.departureTimestamp) }} +
    + {{ timestampToString(row.checkpointStop.departureTimestamp) }}
    {{ - timestampToString(scheduledTrain.stopInfo.departureTimestamp) + timestampToString(row.checkpointStop.departureTimestamp) }}
    - {{ timestampToString(scheduledTrain.stopInfo.departureRealTimestamp) }} - ({{ scheduledTrain.stopInfo.departureDelay > 0 ? '+' : '' - }}{{ scheduledTrain.stopInfo.departureDelay }}) + {{ timestampToString(row.checkpointStop.departureRealTimestamp) }} + ({{ row.checkpointStop.departureDelay > 0 ? '+' : '' + }}{{ row.checkpointStop.departureDelay }})
    @@ -183,6 +178,8 @@ import modalTrainMixin from '../../mixins/modalTrainMixin'; import ScheduledTrainStatus from './ScheduledTrainStatus.vue'; import { useApiStore } from '../../store/apiStore'; import { ActiveScenery, Station } from '../../typings/common'; +import { SceneryTimetableRow } from './typings'; +import { getTrainStopStatus, stopStatusPriority } from './utils'; export default defineComponent({ name: 'SceneryTimetable', @@ -204,10 +201,6 @@ export default defineComponent({ listOpen: false }), - mounted() { - this.loadSelectedOption(); - }, - activated() { this.loadSelectedOption(); }, @@ -241,27 +234,105 @@ export default defineComponent({ return url; }, - computedScheduledTrains() { + sceneryTimetables(): SceneryTimetableRow[] { if (!this.station) return []; + if (!this.onlineScenery) return []; - return ( - this.onlineScenery?.scheduledTrains - ?.filter( - (train) => - train.checkpointName.toLocaleLowerCase() == - (this.chosenCheckpoint || this.station!.name).toLocaleLowerCase() && - train.region == this.mainStore.region.id - ) - .sort((a, b) => { - if (a.stopStatusID > b.stopStatusID) return 1; - if (a.stopStatusID < b.stopStatusID) return -1; + return this.onlineScenery.scheduledTrains + .filter( + (ct) => + ct.train.region == this.mainStore.region.id && + this.chosenCheckpoint && + ct.checkpointStop.stopNameRAW.toLowerCase() == this.chosenCheckpoint.toLowerCase() + ) + .map((ct) => { + const trainStopStatus = getTrainStopStatus( + ct.checkpointStop, + ct.train.currentStationName, + this.station!.name + ); - if (a.stopInfo.arrivalTimestamp > b.stopInfo.arrivalTimestamp) return 1; - if (a.stopInfo.arrivalTimestamp < b.stopInfo.arrivalTimestamp) return -1; + const trainStopIndex = + ct.train.timetableData?.followingStops.findIndex( + (stop) => stop.stopName == ct.checkpointStop.stopName + ) ?? -1; - return a.stopInfo.departureTimestamp > b.stopInfo.departureTimestamp ? 1 : -1; - }) || [] - ); + let prevStationName = '', + nextStationName = ''; + + let departureLine: string | null = null; + let arrivingLine: string | null = null; + + let prevDepartureLine: string | null = null, + nextArrivalLine: string | null = null; + + if (trainStopIndex > -1 && ct.train.timetableData?.followingStops !== undefined) { + for (let i = trainStopIndex; i >= 0; i--) { + const stop = ct.train.timetableData.followingStops[i]; + + if ( + /strong|podg\.|pe\./g.test(stop.stopName) && + !prevStationName && + i <= trainStopIndex - 1 + ) + prevStationName = stop.stopNameRAW.replace(/,.*/g, ''); + + if ( + stop.arrivalLine != null && + !arrivingLine && + !/-|_|it|sbl/gi.test(stop.arrivalLine) + ) { + arrivingLine = stop.arrivalLine; + prevDepartureLine = + ct.train.timetableData.followingStops[i - 1]?.departureLine || null; + } + } + + for (let i = trainStopIndex; i < ct.train.timetableData.followingStops.length; i++) { + const stop = ct.train.timetableData.followingStops[i]; + + if ( + /strong|podg\.|pe\./g.test(stop.stopName) && + !nextStationName && + i > trainStopIndex + ) + nextStationName = stop.stopNameRAW.replace(/,.*/g, ''); + + if ( + stop.departureLine && + !departureLine && + !/-|_|it|sbl/gi.test(stop.departureLine) + ) { + departureLine = stop.departureLine; + nextArrivalLine = ct.train.timetableData.followingStops[i + 1]?.arrivalLine || null; + } + } + } + + return { + checkpointStop: ct.checkpointStop, + train: ct.train, + prevDepartureLine, + nextArrivalLine, + departureLine, + arrivingLine, + prevStationName, + nextStationName, + status: trainStopStatus + }; + }) + .sort((a, b) => { + if (stopStatusPriority.indexOf(a.status) - stopStatusPriority.indexOf(b.status) < 0) + return -1; + + if (stopStatusPriority.indexOf(a.status) - stopStatusPriority.indexOf(b.status) > 0) + return 1; + + if (a.checkpointStop.arrivalTimestamp > b.checkpointStop.arrivalTimestamp) return 1; + if (a.checkpointStop.arrivalTimestamp < b.checkpointStop.arrivalTimestamp) return -1; + + return a.checkpointStop.departureTimestamp > b.checkpointStop.departureTimestamp ? 1 : -1; + }); } }, diff --git a/src/components/SceneryView/ScheduledTrainStatus.vue b/src/components/SceneryView/ScheduledTrainStatus.vue index 6d69c01..f315400 100644 --- a/src/components/SceneryView/ScheduledTrainStatus.vue +++ b/src/components/SceneryView/ScheduledTrainStatus.vue @@ -1,7 +1,7 @@