Compare commits

..

13 Commits

14 changed files with 1542 additions and 8264 deletions
-6962
View File
File diff suppressed because it is too large Load Diff
+7 -7
View File
@@ -1,6 +1,6 @@
{
"name": "stacjownik",
"version": "1.30.4",
"version": "1.30.5",
"private": true,
"type": "module",
"scripts": {
@@ -17,7 +17,7 @@
},
"dependencies": {
"core-js": "^3.42.0",
"dotenv": "^16.5.0",
"dotenv": "^17.2.2",
"pinia": "^3.0.2",
"sass": "^1.87.0",
"showdown": "^2.1.0",
@@ -26,17 +26,17 @@
"vue-router": "^4.4.0"
},
"devDependencies": {
"@types/node": "^22.15.15",
"@types/node": "^24.3.1",
"@types/showdown": "^2.0.6",
"@vite-pwa/assets-generator": "^1.0.0",
"@vitejs/plugin-vue": "^5.1.0",
"@vue/tsconfig": "^0.7.0",
"@vitejs/plugin-vue": "^6.0.1",
"@vue/tsconfig": "^0.8.1",
"axios": "^1.9.0",
"prettier": "^3.3.3",
"typescript": "^5.5.4",
"vite": "^6.3.5",
"vite": "^7.1.4",
"vite-plugin-pwa": "^1.0.0",
"vue-tsc": "^2.0.28"
"vue-tsc": "^3.0.6"
},
"browserslist": [
"> 1%",
@@ -43,8 +43,12 @@
<span :class="{ 'no-catenary': !route.isElectric, internal: route.isInternal }">
{{ route.routeName }}
</span>
<span v-if="route.routeSpeed" class="speed">{{ route.routeSpeed }}</span>
<span v-if="route.routeSpeedExit" class="speed">| {{ route.routeSpeedExit }}</span>
<span v-if="route.routeSpeed" class="speed">
<span>{{ route.routeSpeed }}</span>
<span v-if="route.routeSpeedExit && route.routeSpeedExit != route.routeSpeed">
| {{ route.routeSpeedExit }}
</span>
</span>
<span v-if="route.routeLength" class="length">
{{ (route.routeLength / 1000).toFixed(1) + 'km' }}
</span>
@@ -156,7 +160,7 @@ ul.routes-list {
-moz-user-select: none;
-webkit-user-select: none;
span {
& > span {
padding: 0.2em;
background-color: #007599;
font-weight: bold;
@@ -87,7 +87,8 @@ export default defineComponent({
const stop = train.timetableData?.followingStops.find(
(stop) =>
stop.stopNameRAW.toLowerCase() == name.toLowerCase() ||
this.station?.generalInfo?.checkpoints.includes(stop.stopNameRAW)
this.station?.generalInfo?.checkpoints.includes(stop.stopNameRAW) ||
this.onlineScenery?.missingCheckpoints.includes(stop.stopNameRAW)
);
const sceneryName =
+35 -13
View File
@@ -54,6 +54,18 @@
>
</template>
</div>
<div class="timetable-checkpoints" v-else-if="onlineScenery">
<template v-for="(ch, i) in onlineScenery.missingCheckpoints" :key="i">
<template v-if="i > 0">&bull;</template>
<router-link
class="checkpoint-item"
:class="{ current: chosenCheckpoint === ch }"
:to="`/scenery?station=${onlineScenery.name}&checkpoint=${ch}`"
>{{ ch }}</router-link
>
</template>
</div>
</div>
<div class="timetable-list">
@@ -287,6 +299,7 @@ export default defineComponent({
const chosenCheckpoint = ref(
props.station?.generalInfo?.checkpoints[0] ??
props.onlineScenery?.missingCheckpoints[0] ??
props.station?.name ??
route.query['station']?.toString() ??
''
@@ -365,21 +378,30 @@ export default defineComponent({
methods: {
loadSelectedOption() {
if (!this.station) return;
if (!this.station.generalInfo) {
this.chosenCheckpoint = this.station.name;
return;
}
const queryCheckpoint = this.$route.query['checkpoint']?.toString();
this.chosenCheckpoint =
this.station.generalInfo.checkpoints.find(
(ch) => ch.toLocaleLowerCase() === queryCheckpoint?.toLocaleLowerCase()
) ??
this.station.generalInfo.checkpoints[0] ??
this.station.name;
let checkpointsListRef: string[] | null = null;
let sceneryName = '';
if (this.station && this.station.generalInfo) {
checkpointsListRef = this.station.generalInfo.checkpoints;
sceneryName = this.station.name;
} else if (this.onlineScenery) {
checkpointsListRef = this.onlineScenery.missingCheckpoints;
sceneryName = this.onlineScenery.name;
} else if (this.station) {
this.chosenCheckpoint = this.station.name;
sceneryName = this.station.name;
}
if (checkpointsListRef) {
this.chosenCheckpoint =
checkpointsListRef.find(
(ch) => ch.toLocaleLowerCase() === queryCheckpoint?.toLocaleLowerCase()
) ??
checkpointsListRef[0] ??
sceneryName;
}
},
setCheckpoint(cp: string) {
+2 -1
View File
@@ -111,7 +111,7 @@
</div>
<div
v-if="!train.online && train.lastSeen >= Date.now() - 60000"
v-if="!train.online && train.lastSeen <= Date.now() - 60000"
class="train-badge offline"
>
<i class="fa-solid fa-user-slash"></i>
@@ -397,6 +397,7 @@ export default defineComponent({
.status-badges {
display: flex;
flex-wrap: wrap;
margin-left: 0.25em;
gap: 0.25em;
@@ -43,6 +43,8 @@
id="search-active-driver"
:placeholder="$t(`options.search-driver`)"
v-model="searchedDriver"
@focus="preventKeyDown = true"
@blur="preventKeyDown = false"
/>
<button class="btn btn--action search-exit" @click="onInputClear('driver')">
+37 -26
View File
@@ -12,8 +12,16 @@
:data-delayed="stop.departureDelay > 0"
:data-stop-type="stop.type"
:data-is-active="stop.isActive"
:data-track-count-departure="stop.departureLineInfo?.routeTracks ?? 2"
:data-track-count-arrival="stop.arrivalLineInfo?.routeTracks ?? 2"
:data-track-count-departure="
stop.departureLineInfo?.routeTracks ??
stop.nextPointRef?.arrivalLineInfo?.routeTracks ??
2
"
:data-track-count-arrival="
stop.arrivalLineInfo?.routeTracks ??
scheduleStops[i - 1]?.departureLineInfo?.routeTracks ??
2
"
>
<span class="stop_info">
<span class="distance">
@@ -60,7 +68,8 @@
<span>
|
{{
stop.departureLineInfo.routeSpeedExit
stop.departureLineInfo.routeSpeedExit &&
stop.departureLineInfo.routeSpeedExit != stop.departureLineInfo.routeSpeed
? `${stop.departureLineInfo.routeSpeedExit} (${stop.departureLineInfo.routeSpeed})`
: stop.departureLineInfo.routeSpeed
}}</span
@@ -113,10 +122,16 @@
<span> {{ stop.nextPointRef.arrivalLine }}</span>
<span v-if="stop.nextPointRef.arrivalLineInfo">
<span> | {{ stop.nextPointRef.arrivalLineInfo!.routeSpeed }}</span>
<span v-if="stop.nextPointRef.arrivalLineInfo!.routeSpeedExit"
>({{ stop.nextPointRef.arrivalLineInfo!.routeSpeedExit }})</span
<span> | {{ stop.nextPointRef.arrivalLineInfo.routeSpeed }}</span>
<span
v-if="
stop.nextPointRef.arrivalLineInfo.routeSpeedExit &&
stop.nextPointRef.arrivalLineInfo.routeSpeedExit !=
stop.nextPointRef.arrivalLineInfo.routeSpeed
"
>
({{ stop.nextPointRef.arrivalLineInfo.routeSpeedExit }})
</span>
<img
:src="
@@ -186,26 +201,28 @@ export default defineComponent({
const sceneryData =
this.store.stationList?.find((sc) => sc.name == pathEl.stationName) ?? null;
if (!sceneryData || !sceneryData.generalInfo) return null;
const activeScenery = this.apiStore.activeData?.activeSceneries?.find(
(sc) => sc.stationName == pathEl.stationName
);
const arrivalLineData = pathEl.arrivalRouteExt
? (sceneryData.generalInfo.routes.all.find(
(rt) => rt.routeName == pathEl.arrivalRouteExt
) ?? null)
const arrivalLineData = sceneryData?.generalInfo
? pathEl.arrivalRouteExt
? (sceneryData.generalInfo.routes.all.find(
(rt) => rt.routeName == pathEl.arrivalRouteExt
) ?? null)
: null
: null;
const departureLineData = pathEl.departureRouteExt
? (sceneryData.generalInfo.routes.all.find(
(rt) => rt.routeName == pathEl.departureRouteExt
) ?? null)
const departureLineData = sceneryData?.generalInfo
? pathEl.departureRouteExt
? (sceneryData.generalInfo.routes.all.find(
(rt) => rt.routeName == pathEl.departureRouteExt
) ?? null)
: null
: null;
return {
generalInfo: sceneryData.generalInfo,
generalInfo: sceneryData?.generalInfo ?? null,
isOnline:
activeScenery &&
(activeScenery.isOnline == 1 || activeScenery.lastSeen >= Date.now() - 60000),
@@ -234,7 +251,7 @@ export default defineComponent({
let isActive = false;
if (pathData?.departureLineData) {
// arrivalLineInfo = pathData.departureLineData;
arrivalLineInfo = pathData.departureLineData;
departureLineInfo = pathData.departureLineData;
}
@@ -245,22 +262,16 @@ export default defineComponent({
isExternal = true;
departureLineInfo = pathData?.arrivalLineData ?? null;
if (pathData?.arrivalLineData) {
arrivalLineInfo = pathData.arrivalLineData;
}
arrivalLineInfo = pathData.arrivalLineData;
}
let correctedDepartureLineData: StationRoutesInfo | null = null;
const internalRouteInfo = stop.departureLine
? pathData?.generalInfo.routes.all.find(
? pathData?.generalInfo?.routes.all.find(
(route) => route.isInternal && route.routeName == stop.departureLine
)
: undefined;
if (internalRouteInfo) {
correctedDepartureLineData = internalRouteInfo;
departureLineInfo = internalRouteInfo;
}
+4 -4
View File
@@ -142,7 +142,7 @@
"title": "Control type",
"SPK": "SPK",
"SCS": "SCS",
"SCS-SPK": "SCS/SPK",
"SCS-SPK": "SCS + SPK",
"SPE": "SPE",
"ręczne": "manual",
"ręczne+SPK": "manual + SPK",
@@ -153,7 +153,7 @@
"abbrevs": {
"SPK": "SPK",
"SCS": "SCS",
"SCS-SPK": "S/S",
"SCS-SPK": "S+S",
"SPE": "SPE",
"ręczne": "R",
"ręczne+SPK": "R",
@@ -343,8 +343,8 @@
"ASDEK": "ASDEK program available (defect detection of moving rolling stock)",
"TWB-all": "This scenery has two-way route blockade on all routes",
"TWB-routes": "This scenery has two-way route blockade on following routes: ",
"default": "Scenery available in game package",
"nonDefault": "Sceneria available to download from forum site",
"default": "Scenery available in the game package",
"nonDefault": "Scenery available to download from the forum site",
"req-level": "all dispatcher levels | requries {lvl} dispatcher lvl | requires {lvl} dispatcher lvl",
"non-public": "Non-public scenery",
"unavailable": "Unavailable scenery",
+3 -3
View File
@@ -139,7 +139,7 @@
"title": "Sterowanie",
"SPK": "SPK",
"SCS": "SCS",
"SCS-SPK": "SCS/SPK",
"SCS-SPK": "SCS + SPK",
"SPE": "SPE",
"ręczne": "ręczne",
"ręczne+SPK": "ręczne z SPK",
@@ -150,7 +150,7 @@
"abbrevs": {
"SPK": "SPK",
"SCS": "SCS",
"SCS-SPK": "S/S",
"SCS-SPK": "S+S",
"SPE": "SPE",
"ręczne": "R",
"ręczne+SPK": "R",
@@ -340,7 +340,7 @@
"SUP": "Wymaga programu SUP do kontroli systemu RASP-UZK",
"ASDEK": "Dostępny program ASDEK do detekcji stanów awaryjnych taboru w ruchu",
"default": "Sceneria dostępna domyślnie w paczce z grą",
"nonDefault": "Sceneria dostępna do pobrania ze strony forum",
"nonDefault": "Sceneria dostępna do pobrania z forum symulatora",
"req-level": "ogólnodostępna | od {lvl} poz. DR | od {lvl} poz. DR",
"non-public": "Sceneria niepubliczna",
"unavailable": "Sceneria niedostępna",
+50 -6
View File
@@ -13,6 +13,7 @@ import { useApiStore } from './apiStore';
import { MainStoreState } from './typings';
const checkpointsTrains: Map<string, CheckpointTrain[]> = new Map();
const unknownSceneryCheckpoints: Map<string, Set<string>> = new Map();
const sceneriesTrains: Map<string, Train[]> = new Map();
export const useMainStore = defineStore('mainStore', {
@@ -42,6 +43,7 @@ export const useMainStore = defineStore('mainStore', {
checkpointsTrains.clear();
sceneriesTrains.clear();
unknownSceneryCheckpoints.clear();
const dateNow = new Date();
@@ -133,8 +135,13 @@ export const useMainStore = defineStore('mainStore', {
// Checkpoints trains map
if (trainObj.timetableData) {
let currentSceneryIndex = 0;
const timetablePath = trainObj.timetableData.timetablePath;
let currentSceneryIndex = 0;
let currentSceneryData: Station | null =
this.stationList.find(
(s) => s.name == timetablePath[currentSceneryIndex].stationName
) ?? null;
trainObj.timetableData.followingStops.forEach((stop, i) => {
if (/strong|podg|pe/.test(stop.stopName)) {
@@ -153,16 +160,41 @@ export const useMainStore = defineStore('mainStore', {
timetablePathElement: timetablePath[currentSceneryIndex]
};
// Adding missing sceneries checkpoints as a fallback when scenery data is missing (and "generalInfo" is unavailable)
if (!currentSceneryData) {
const sceneryCheckpointsSet = unknownSceneryCheckpoints.get(
checkpointTrain.timetablePathElement.stationName
);
if (!sceneryCheckpointsSet) {
unknownSceneryCheckpoints.set(
checkpointTrain.timetablePathElement.stationName,
new Set([stop.stopNameRAW])
);
} else {
sceneryCheckpointsSet.add(stop.stopNameRAW);
}
}
// Adding trains to their corresponding checkpoints
if (checkpointsTrains.has(stop.stopNameRAW.toLowerCase())) {
checkpointsTrains.set(stop.stopNameRAW.toLowerCase(), [
...checkpointsTrains.get(stop.stopNameRAW.toLowerCase())!,
checkpointTrain
]);
} else checkpointsTrains.set(stop.stopNameRAW.toLowerCase(), [checkpointTrain]);
} else {
checkpointsTrains.set(stop.stopNameRAW.toLowerCase(), [checkpointTrain]);
}
}
if (timetablePath[currentSceneryIndex].departureRouteExt == stop.departureLine)
if (timetablePath[currentSceneryIndex].departureRouteExt == stop.departureLine) {
currentSceneryIndex++;
currentSceneryData =
this.stationList.find(
(s) => s.name == timetablePath[currentSceneryIndex].stationName
) ?? null;
}
});
}
@@ -222,7 +254,9 @@ export const useMainStore = defineStore('mainStore', {
all: 0,
confirmed: 0,
unconfirmed: 0
}
},
missingCheckpoints: []
});
});
@@ -266,7 +300,9 @@ export const useMainStore = defineStore('mainStore', {
all: 0,
confirmed: 0,
unconfirmed: 0
}
},
missingCheckpoints: []
});
return list;
@@ -277,7 +313,7 @@ export const useMainStore = defineStore('mainStore', {
for (let i = 0, n = allActiveSceneries.length; i < n; i++) {
const scenery = allActiveSceneries[i];
const station = this.stationList.find((s) => s.name === scenery.name);
let station = this.stationList.find((s) => s.name === scenery.name);
let checkpointsSet: Set<string> = new Set();
@@ -293,6 +329,14 @@ export const useMainStore = defineStore('mainStore', {
scenery.stationTrains =
sceneriesTrains.get(scenery.name)?.filter((sc) => sc.region == this.region.id) ?? [];
// Missing checkpoints as a fallback for sceneries without generalInfo & checkpoints property
const missingCheckpointsToAdd = unknownSceneryCheckpoints.get(scenery.name);
if (missingCheckpointsToAdd) {
checkpoints.push(...missingCheckpointsToAdd);
scenery.missingCheckpoints.push(...missingCheckpointsToAdd);
}
const uniqueTrainIds: string[] = [];
checkpoints.forEach((cp) => {
const scheduledTrains = checkpointsTrains.get(cp.toLowerCase());
+1 -1
View File
@@ -36,6 +36,6 @@
}
&.SCS-SPK {
color: white;
color: #aefff8;
}
}
+1
View File
@@ -170,6 +170,7 @@ export interface ActiveScenery {
confirmed: number;
unconfirmed: number;
};
missingCheckpoints: string[];
}
export interface ScenerySpawn {
+1391 -1237
View File
File diff suppressed because it is too large Load Diff