mirror of
https://github.com/Spythere/pojazdownik.git
synced 2026-05-03 05:18:10 +00:00
refactor: calculating stock speed limit
This commit is contained in:
@@ -2,10 +2,7 @@
|
|||||||
<div class="stock-specs">
|
<div class="stock-specs">
|
||||||
<div v-if="store.chosenStorageStockName || chosenRealComposition">
|
<div v-if="store.chosenStorageStockName || chosenRealComposition">
|
||||||
<b v-if="store.chosenStorageStockName">
|
<b v-if="store.chosenStorageStockName">
|
||||||
<span
|
<span class="text--accent" :title="store.chosenStorageStockName.length > 41 ? store.chosenStorageStockName : ''">
|
||||||
class="text--accent"
|
|
||||||
:title="store.chosenStorageStockName.length > 41 ? store.chosenStorageStockName : ''"
|
|
||||||
>
|
|
||||||
<BookmarkCheck :size="19" />
|
<BookmarkCheck :size="19" />
|
||||||
{{ store.chosenStorageStockName.slice(0, 40) }}
|
{{ store.chosenStorageStockName.slice(0, 40) }}
|
||||||
{{ store.chosenStorageStockName.length > 41 ? '...' : '' }}
|
{{ store.chosenStorageStockName.length > 41 ? '...' : '' }}
|
||||||
@@ -16,11 +13,7 @@
|
|||||||
|
|
||||||
<b class="real-stock-info" v-if="chosenRealComposition">
|
<b class="real-stock-info" v-if="chosenRealComposition">
|
||||||
<span class="text--accent">
|
<span class="text--accent">
|
||||||
<img
|
<img class="real-stock-icon" :src="getIconURL(chosenRealComposition.type)" :alt="chosenRealComposition.type" />
|
||||||
class="real-stock-icon"
|
|
||||||
:src="getIconURL(chosenRealComposition.type)"
|
|
||||||
:alt="chosenRealComposition.type"
|
|
||||||
/>
|
|
||||||
{{ chosenRealComposition.number }} {{ chosenRealComposition.name }}
|
{{ chosenRealComposition.number }} {{ chosenRealComposition.name }}
|
||||||
</span>
|
</span>
|
||||||
</b>
|
</b>
|
||||||
@@ -30,14 +23,11 @@
|
|||||||
{{ $t('stocklist.mass') }}
|
{{ $t('stocklist.mass') }}
|
||||||
<span class="text--accent">{{ (store.totalWeight / 1000).toFixed(1) }}t</span>
|
<span class="text--accent">{{ (store.totalWeight / 1000).toFixed(1) }}t</span>
|
||||||
({{ $t('stocklist.mass-accepted') }}:
|
({{ $t('stocklist.mass-accepted') }}:
|
||||||
<span class="text--accent">{{
|
<span class="text--accent">{{ store.acceptableWeight ? `${~~(store.acceptableWeight / 1000)}t` : '-' }}</span
|
||||||
store.acceptableWeight ? `${~~(store.acceptableWeight / 1000)}t` : '-'
|
|
||||||
}}</span
|
|
||||||
>) - {{ $t('stocklist.length') }}:
|
>) - {{ $t('stocklist.length') }}:
|
||||||
<span class="text--accent">{{ store.totalLength }}m</span>
|
<span class="text--accent">{{ store.totalLength }}m</span>
|
||||||
- {{ $t('stocklist.vmax') }}
|
- {{ $t('stocklist.vmax') }} <span tabindex="0" :data-tooltip="$t('stocklist.disclaimer')">(?)</span>:
|
||||||
<span tabindex="0" :data-tooltip="$t('stocklist.disclaimer')">(?)</span>:
|
<span class="text--accent">{{ isFinite(store.maxStockSpeed) ? store.maxStockSpeed : '--' }} km/h</span>
|
||||||
<span class="text--accent">{{ store.maxStockSpeed }} km/h</span>
|
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -1,153 +0,0 @@
|
|||||||
{
|
|
||||||
"EU07": {
|
|
||||||
"passenger": {
|
|
||||||
"650000": 125
|
|
||||||
},
|
|
||||||
"cargo": {
|
|
||||||
"2000000": 70
|
|
||||||
},
|
|
||||||
"none": 110
|
|
||||||
},
|
|
||||||
"4E": {
|
|
||||||
"passenger": {
|
|
||||||
"650000": 125
|
|
||||||
},
|
|
||||||
"cargo": {
|
|
||||||
"2000000": 70
|
|
||||||
},
|
|
||||||
"none": 110
|
|
||||||
},
|
|
||||||
"EU07E": {
|
|
||||||
"passenger": {
|
|
||||||
"650000": 125
|
|
||||||
},
|
|
||||||
"cargo": {
|
|
||||||
"2000000": 70
|
|
||||||
},
|
|
||||||
"none": 110
|
|
||||||
},
|
|
||||||
"EP07": {
|
|
||||||
"passenger": {
|
|
||||||
"650000": 125
|
|
||||||
},
|
|
||||||
"cargo": null,
|
|
||||||
"none": 110
|
|
||||||
},
|
|
||||||
"EP08": {
|
|
||||||
"passenger": {
|
|
||||||
"650000": 140
|
|
||||||
},
|
|
||||||
"cargo": null,
|
|
||||||
"none": 110
|
|
||||||
},
|
|
||||||
"EP09": {
|
|
||||||
"passenger": {
|
|
||||||
"650000": 160
|
|
||||||
},
|
|
||||||
"cargo": null,
|
|
||||||
"none": 160
|
|
||||||
},
|
|
||||||
"ET22": {
|
|
||||||
"passenger": {
|
|
||||||
"650000": 125
|
|
||||||
},
|
|
||||||
"cargo": {
|
|
||||||
"1200000": 100,
|
|
||||||
"3100000": 70
|
|
||||||
},
|
|
||||||
"none": 125
|
|
||||||
},
|
|
||||||
"201E": {
|
|
||||||
"passenger": {
|
|
||||||
"650000": 125
|
|
||||||
},
|
|
||||||
"cargo": {
|
|
||||||
"1200000": 100,
|
|
||||||
"3100000": 70
|
|
||||||
},
|
|
||||||
"none": 125
|
|
||||||
},
|
|
||||||
"ET41": {
|
|
||||||
"passenger": {
|
|
||||||
"700000": 125
|
|
||||||
},
|
|
||||||
"cargo": {
|
|
||||||
"4000000": 70
|
|
||||||
},
|
|
||||||
"none": 110
|
|
||||||
},
|
|
||||||
"SM42": {
|
|
||||||
"passenger": {
|
|
||||||
"95000": 90,
|
|
||||||
"200000": 80,
|
|
||||||
"300000": 70,
|
|
||||||
"450000": 60,
|
|
||||||
"750000": 50,
|
|
||||||
"1130000": 40,
|
|
||||||
"1720000": 30,
|
|
||||||
"2400000": 20
|
|
||||||
},
|
|
||||||
"cargo": {
|
|
||||||
"95000": 90,
|
|
||||||
"200000": 80,
|
|
||||||
"300000": 70,
|
|
||||||
"450000": 60,
|
|
||||||
"750000": 50,
|
|
||||||
"1130000": 40,
|
|
||||||
"1720000": 30,
|
|
||||||
"2400000": 20
|
|
||||||
},
|
|
||||||
"none": 90
|
|
||||||
},
|
|
||||||
"M62": {
|
|
||||||
"passenger": {
|
|
||||||
"500000": 100,
|
|
||||||
"800000": 80,
|
|
||||||
"1200000": 60,
|
|
||||||
"2000000": 40,
|
|
||||||
"3000000": 20
|
|
||||||
},
|
|
||||||
"cargo": {
|
|
||||||
"500000": 100,
|
|
||||||
"800000": 80,
|
|
||||||
"1200000": 60,
|
|
||||||
"2000000": 40,
|
|
||||||
"3000000": 20
|
|
||||||
},
|
|
||||||
"none": 100
|
|
||||||
},
|
|
||||||
"ST44": {
|
|
||||||
"passenger": {
|
|
||||||
"500000": 100,
|
|
||||||
"800000": 80,
|
|
||||||
"1200000": 60,
|
|
||||||
"2000000": 40,
|
|
||||||
"3000000": 20
|
|
||||||
},
|
|
||||||
"cargo": {
|
|
||||||
"500000": 100,
|
|
||||||
"800000": 80,
|
|
||||||
"1200000": 60,
|
|
||||||
"2000000": 40,
|
|
||||||
"3000000": 20
|
|
||||||
},
|
|
||||||
"none": 100
|
|
||||||
},
|
|
||||||
"CTLR4C": {
|
|
||||||
"passenger": {
|
|
||||||
"500000": 100,
|
|
||||||
"800000": 80,
|
|
||||||
"1200000": 60,
|
|
||||||
"2000000": 40,
|
|
||||||
"3000000": 20
|
|
||||||
},
|
|
||||||
"cargo": {
|
|
||||||
"500000": 100,
|
|
||||||
"800000": 80,
|
|
||||||
"1200000": 60,
|
|
||||||
"2000000": 40,
|
|
||||||
"3000000": 20
|
|
||||||
},
|
|
||||||
"none": 100
|
|
||||||
}
|
|
||||||
}
|
|
||||||
+1
-3
@@ -25,13 +25,11 @@ import {
|
|||||||
totalWeight,
|
totalWeight,
|
||||||
} from './utils/vehicleUtils';
|
} from './utils/vehicleUtils';
|
||||||
|
|
||||||
import i18n from './i18n-setup';
|
|
||||||
import http from './http';
|
import http from './http';
|
||||||
|
|
||||||
import realCompositionsJSON from './data/realCompositions.json';
|
import realCompositionsJSON from './data/realCompositions.json';
|
||||||
|
|
||||||
export const useStore = defineStore({
|
export const useStore = defineStore('store', {
|
||||||
id: 'store',
|
|
||||||
state: () => ({
|
state: () => ({
|
||||||
chosenCar: null as ICarWagon | null,
|
chosenCar: null as ICarWagon | null,
|
||||||
chosenLoco: null as ILocomotive | null,
|
chosenLoco: null as ILocomotive | null,
|
||||||
|
|||||||
@@ -28,12 +28,14 @@ export interface ILocomotive {
|
|||||||
constructionType: string;
|
constructionType: string;
|
||||||
cabinType: string;
|
cabinType: string;
|
||||||
maxSpeed: number;
|
maxSpeed: number;
|
||||||
|
maxSpeedLoco: number;
|
||||||
weight: number;
|
weight: number;
|
||||||
length: number;
|
length: number;
|
||||||
coldStart: boolean;
|
coldStart: boolean;
|
||||||
doubleManned: boolean;
|
doubleManned: boolean;
|
||||||
sponsorOnlyTimestamp: number;
|
sponsorOnlyTimestamp: number;
|
||||||
teamOnly: boolean;
|
teamOnly: boolean;
|
||||||
|
massSpeeds: VehicleGroupMassSpeeds | null;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ICarWagon {
|
export interface ICarWagon {
|
||||||
@@ -42,11 +44,13 @@ export interface ICarWagon {
|
|||||||
constructionType: string;
|
constructionType: string;
|
||||||
loadable: boolean;
|
loadable: boolean;
|
||||||
maxSpeed: number;
|
maxSpeed: number;
|
||||||
|
maxSpeedLoaded: number;
|
||||||
weight: number;
|
weight: number;
|
||||||
length: number;
|
length: number;
|
||||||
cargoTypes: ICargo[];
|
cargoTypes: ICargo[];
|
||||||
sponsorOnlyTimestamp: number;
|
sponsorOnlyTimestamp: number;
|
||||||
teamOnly: boolean;
|
teamOnly: boolean;
|
||||||
|
massSpeeds: VehicleGroupMassSpeeds | null;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IStock {
|
export interface IStock {
|
||||||
@@ -83,10 +87,13 @@ export interface IVehicleGroup {
|
|||||||
id: number;
|
id: number;
|
||||||
name: string;
|
name: string;
|
||||||
speed: number;
|
speed: number;
|
||||||
|
speedLoaded?: number;
|
||||||
|
speedLoco?: number;
|
||||||
length: number;
|
length: number;
|
||||||
weight: number;
|
weight: number;
|
||||||
cargoTypes: IVehicleCargoType[] | null;
|
cargoTypes: IVehicleCargoType[] | null;
|
||||||
locoProps: IVehicleLocoProps | null;
|
locoProps: IVehicleLocoProps | null;
|
||||||
|
massSpeeds: VehicleGroupMassSpeeds | null;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IVehicleCargoType {
|
export interface IVehicleCargoType {
|
||||||
@@ -99,6 +106,12 @@ export interface IVehicleLocoProps {
|
|||||||
doubleManned: boolean;
|
doubleManned: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface VehicleGroupMassSpeeds {
|
||||||
|
passenger: Record<string, number> | null;
|
||||||
|
cargo: Record<string, number> | null;
|
||||||
|
none: number | null;
|
||||||
|
}
|
||||||
|
|
||||||
export interface StorageStockEntry {
|
export interface StorageStockEntry {
|
||||||
id: string;
|
id: string;
|
||||||
createdAt: number;
|
createdAt: number;
|
||||||
|
|||||||
@@ -1,29 +1,47 @@
|
|||||||
import speedLimits from '../constants/speedLimits.json';
|
|
||||||
import massLimits from '../constants/massLimits.json';
|
import massLimits from '../constants/massLimits.json';
|
||||||
|
import { IStock } from '../types/common.types';
|
||||||
|
|
||||||
export type SpeedLimitLocoType = keyof typeof speedLimits;
|
|
||||||
export type MassLimitLocoType = keyof typeof massLimits;
|
export type MassLimitLocoType = keyof typeof massLimits;
|
||||||
|
|
||||||
export function calculateSpeedLimit(
|
export function calculateSpeedLimit(stockList: IStock[], isPassenger: boolean, stockMass: number) {
|
||||||
locoType: SpeedLimitLocoType,
|
// Check the whole consist speed limit
|
||||||
stockTotalWeight: number,
|
const stockMaxSpeed = stockList.reduce((acc, vehicle, i) => {
|
||||||
stockCount: number,
|
let vehicleSpeed = vehicle.vehicleRef.maxSpeed;
|
||||||
isTrainPassenger: boolean
|
|
||||||
) {
|
|
||||||
if (speedLimits[locoType] === undefined) return 0;
|
|
||||||
|
|
||||||
if (stockCount == 1) return speedLimits[locoType]['none'];
|
if (
|
||||||
|
vehicle.vehicleRef.group == 'wagon-freight' &&
|
||||||
|
vehicle.cargo !== undefined &&
|
||||||
|
vehicle.vehicleRef.maxSpeedLoaded
|
||||||
|
) {
|
||||||
|
vehicleSpeed = vehicle.vehicleRef.maxSpeedLoaded;
|
||||||
|
}
|
||||||
|
|
||||||
const stockType = isTrainPassenger ? 'passenger' : 'cargo';
|
return Math.min(vehicleSpeed, acc);
|
||||||
const speedTable = speedLimits[locoType][stockType];
|
}, Infinity);
|
||||||
|
|
||||||
if (!speedTable) return undefined;
|
// Check the head vehicle speed limit
|
||||||
|
const headVehicle = stockList[0];
|
||||||
|
|
||||||
let speedLimit = 0;
|
// Omit speed check for head vehicle if there's no data for it
|
||||||
for (const mass in speedTable)
|
if (!headVehicle || !headVehicle.vehicleRef.massSpeeds) return stockMaxSpeed;
|
||||||
if (stockTotalWeight > Number(mass)) speedLimit = (speedTable as any)[mass];
|
|
||||||
|
|
||||||
return speedLimit;
|
const massSpeeds =
|
||||||
|
headVehicle.vehicleRef.massSpeeds[
|
||||||
|
stockList.length == 1 ? 'none' : isPassenger ? 'passenger' : 'cargo'
|
||||||
|
];
|
||||||
|
|
||||||
|
// Omit speed check if there's no data on mass speeds
|
||||||
|
if (!massSpeeds) return stockMaxSpeed;
|
||||||
|
|
||||||
|
// 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) => stockMass >= Number(massKey));
|
||||||
|
|
||||||
|
const massMaxSpeed = massKey ? massSpeeds[massKey] : Infinity;
|
||||||
|
|
||||||
|
return Math.min(massMaxSpeed, stockMaxSpeed);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function calculateMassLimit(locoType: MassLimitLocoType, isTrainPassenger: boolean) {
|
export function calculateMassLimit(locoType: MassLimitLocoType, isTrainPassenger: boolean) {
|
||||||
|
|||||||
@@ -35,11 +35,14 @@ export function locoDataList(vehiclesData: IVehicleData[] | undefined) {
|
|||||||
teamOnly: data.restrictions?.teamOnly ?? false,
|
teamOnly: data.restrictions?.teamOnly ?? false,
|
||||||
|
|
||||||
maxSpeed: data.group.speed,
|
maxSpeed: data.group.speed,
|
||||||
|
maxSpeedLoco: data.group.speedLoco ?? data.group.speed,
|
||||||
length: data.group.length,
|
length: data.group.length,
|
||||||
weight: data.group.weight,
|
weight: data.group.weight,
|
||||||
|
|
||||||
coldStart: data.group.locoProps?.coldStart ?? false,
|
coldStart: data.group.locoProps?.coldStart ?? false,
|
||||||
doubleManned: data.group.locoProps?.doubleManned ?? false,
|
doubleManned: data.group.locoProps?.doubleManned ?? false,
|
||||||
|
|
||||||
|
massSpeeds: data.group.massSpeeds,
|
||||||
});
|
});
|
||||||
|
|
||||||
return acc;
|
return acc;
|
||||||
@@ -63,8 +66,12 @@ export function carDataList(vehiclesData: IVehicleData[] | undefined) {
|
|||||||
teamOnly: data.restrictions?.teamOnly ?? false,
|
teamOnly: data.restrictions?.teamOnly ?? false,
|
||||||
|
|
||||||
maxSpeed: data.group.speed,
|
maxSpeed: data.group.speed,
|
||||||
|
maxSpeedLoaded: data.group.speedLoaded ?? data.group.speed,
|
||||||
|
|
||||||
length: data.group.length,
|
length: data.group.length,
|
||||||
weight: data.group.weight,
|
weight: data.group.weight,
|
||||||
|
|
||||||
|
massSpeeds: data.group.massSpeeds,
|
||||||
});
|
});
|
||||||
|
|
||||||
return acc;
|
return acc;
|
||||||
@@ -83,27 +90,7 @@ export function totalLength(stockList: IStock[]) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function maxStockSpeed(stockList: IStock[]) {
|
export function maxStockSpeed(stockList: IStock[]) {
|
||||||
const stockSpeedLimit = stockList.reduce(
|
return calculateSpeedLimit(stockList, isTrainPassenger(stockList), totalWeight(stockList));
|
||||||
(acc, stock) => (stock.vehicleRef.maxSpeed < acc || acc == 0 ? stock.vehicleRef.maxSpeed : acc),
|
|
||||||
0
|
|
||||||
);
|
|
||||||
const headingLoco =
|
|
||||||
stockList[0] && isTractionUnit(stockList[0].vehicleRef) ? stockList[0] : undefined;
|
|
||||||
|
|
||||||
if (!headingLoco) return stockSpeedLimit;
|
|
||||||
|
|
||||||
const locoType = headingLoco.vehicleRef.type.split('-')[0];
|
|
||||||
|
|
||||||
if (/^(EN|2EN|SN)/.test(locoType)) return stockSpeedLimit;
|
|
||||||
|
|
||||||
const speedLimitByMass = calculateSpeedLimit(
|
|
||||||
locoType as SpeedLimitLocoType,
|
|
||||||
totalWeight(stockList),
|
|
||||||
stockList.length,
|
|
||||||
isTrainPassenger(stockList)
|
|
||||||
);
|
|
||||||
|
|
||||||
return speedLimitByMass ? Math.min(stockSpeedLimit, speedLimitByMass) : stockSpeedLimit;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function acceptableWeight(stockList: IStock[]) {
|
export function acceptableWeight(stockList: IStock[]) {
|
||||||
|
|||||||
Reference in New Issue
Block a user