chore: added a display of the timetable max speed in the active train info & tooltip

This commit is contained in:
2025-09-14 15:10:48 +02:00
parent bf9799e0c3
commit 6d1ef26ac1
4 changed files with 78 additions and 91 deletions
+12 -3
View File
@@ -9,6 +9,17 @@
<div class="text--primary">
<b>{{ trainInfo.stockList[0] }}</b> &bull; {{ trainInfo.length }}m &bull;
{{ (trainInfo.mass / 1000).toFixed(2) }}t
<span v-if="trainInfo.timetableData">
&bull; vRJ:
{{
trainInfo.timetableData?.trainMaxSpeed ||
getStockSpeedLimit(trainInfo.stockList, trainInfo.mass)
}}km/h
</span>
<span v-else class="text--grayed font--italic">
&bull; vMax:
{{ getStockSpeedLimit(trainInfo.stockList, trainInfo.mass) }}km/h
</span>
</div>
<div class="text--grayed">
@@ -46,9 +57,7 @@ export default defineComponent({
return this.mainStore.trainList.find((t) => t.id === this.tooltipStore.content);
},
lastSceneryStatus() {
}
lastSceneryStatus() {}
}
});
</script>
+7 -51
View File
@@ -135,7 +135,11 @@
<img src="/images/icon-speed.svg" alt="speed icon" />
{{ train.speed }} km/h
<span v-if="stockSpeedLimit != Infinity">
<span v-if="train.timetableData">
&bull; vRJ: {{ train.timetableData.trainMaxSpeed }} km/h
</span>
<span v-else-if="stockSpeedLimit != Infinity">
&bull;
<em
class="text--grayed"
@@ -219,57 +223,9 @@ export default defineComponent({
computed: {
stockSpeedLimit() {
let isPassenger = true;
// Check the whole consist speed limit
const vehicleMaxSpeed = this.train.stockList.reduce((acc, stockName, i) => {
const [vehicleName, vehicleCargo] = stockName.split(':');
const vehicleData = this.apiStore.vehiclesData?.find((v) => v.name == vehicleName);
if (!vehicleData) return acc;
let vehicleSpeed = vehicleData.group.speed;
if (vehicleData.type == 'wagon-freight') {
isPassenger = false;
if (vehicleCargo !== undefined && vehicleData.group.speedLoaded) {
vehicleSpeed = vehicleData.group.speedLoaded;
}
}
return Math.min(vehicleSpeed, acc);
}, Infinity);
// Check the head vehicle speed limit
const headLocoName = this.train.stockList[0];
const headLocoVehicleData = this.apiStore.vehiclesData?.find((v) => v.name == headLocoName);
// Omit speed check for head vehicle if there's no data for it
if (!headLocoName || !headLocoVehicleData || !headLocoVehicleData.group.massSpeeds)
return vehicleMaxSpeed;
const massSpeeds =
headLocoVehicleData.group.massSpeeds[
this.train.stockList.length == 1 ? 'none' : isPassenger ? 'passenger' : 'cargo'
];
// Omit speed check if there's no data on mass speeds
if (!massSpeeds) return vehicleMaxSpeed;
// Number type for locomotives alone
if (typeof massSpeeds === 'number') return massSpeeds;
// Record type for passenger or cargo, find the closest range
const massKey = Object.keys(massSpeeds).findLast(
(massKey) => this.train.mass >= Number(massKey)
);
const massMaxSpeed = massKey ? massSpeeds[massKey] : Infinity;
return Math.min(massMaxSpeed, vehicleMaxSpeed);
return this.getStockSpeedLimit(this.train.stockList, this.train.mass);
},
journalRouteLocation() {
return {
path: '/journal/timetables',
+53 -37
View File
@@ -1,45 +1,10 @@
import { defineComponent } from 'vue';
import { Train, TrainStop } from '../typings/common';
import { useApiStore } from '../store/apiStore';
export default defineComponent({
data: () => ({
STATS: {
main: [
{
name: 'speed',
unit: 'km/h'
},
{
name: 'length',
unit: 'm'
},
{
name: 'mass',
unit: 't',
multiplier: 0.001
}
],
position: [
{
name: 'scenery',
prop: 'currentStationName'
},
{
name: 'route',
prop: 'connectedTrack'
},
{
name: 'signal',
prop: 'signal'
},
{
name: 'distance',
prop: 'distance',
unit: 'm'
}
]
}
apiStore: useApiStore()
}),
methods: {
@@ -150,6 +115,57 @@ export default defineComponent({
if (distance < 1000) return `${distance}m`;
return `${(distance / 1000).toPrecision(2)}km`;
},
getStockSpeedLimit(stockList: string[], trainMass: number) {
let isPassenger = true;
// Check the whole consist speed limit
const vehicleMaxSpeed = stockList.reduce((acc, stockName, i) => {
const [vehicleName, vehicleCargo] = stockName.split(':');
const vehicleData = this.apiStore.vehiclesData?.find((v) => v.name == vehicleName);
if (!vehicleData) return acc;
let vehicleSpeed = vehicleData.group.speed;
if (vehicleData.type == 'wagon-freight') {
isPassenger = false;
if (vehicleCargo !== undefined && vehicleData.group.speedLoaded) {
vehicleSpeed = vehicleData.group.speedLoaded;
}
}
return Math.min(vehicleSpeed, acc);
}, Infinity);
// Check the head vehicle speed limit
const headLocoName = stockList[0];
const headLocoVehicleData = this.apiStore.vehiclesData?.find((v) => v.name == headLocoName);
// Omit speed check for head vehicle if there's no data for it
if (!headLocoName || !headLocoVehicleData || !headLocoVehicleData.group.massSpeeds)
return vehicleMaxSpeed;
const massSpeeds =
headLocoVehicleData.group.massSpeeds[
stockList.length == 1 ? 'none' : isPassenger ? 'passenger' : 'cargo'
];
// Omit speed check if there's no data on mass speeds
if (!massSpeeds) return vehicleMaxSpeed;
// Number type for locomotives alone
if (typeof massSpeeds === 'number') return massSpeeds;
// Record type for passenger or cargo, find the closest range
const massKey = Object.keys(massSpeeds).findLast((massKey) => trainMass >= Number(massKey));
const massMaxSpeed = massKey ? massSpeeds[massKey] : Infinity;
return Math.min(massMaxSpeed, vehicleMaxSpeed);
}
}
});
+6
View File
@@ -225,6 +225,12 @@ ul {
}
}
.font {
&--italic {
font-style: italic;
}
}
button,
a.a-button {
cursor: pointer;