refactor: types & performance

This commit is contained in:
2024-05-04 14:43:34 +02:00
parent 7dd1c06f3f
commit a2de0e2030
32 changed files with 349 additions and 400 deletions
+2 -2
View File
@@ -65,12 +65,12 @@ export default defineComponent({
immediate: true, immediate: true,
handler(regionQuery: string) { handler(regionQuery: string) {
if (regionQuery) { if (regionQuery) {
this.store.region.id = this.store.region =
regionsJSON.find( regionsJSON.find(
(reg) => (reg) =>
reg.id == regionQuery.toLocaleLowerCase() || reg.id == regionQuery.toLocaleLowerCase() ||
reg.value.toLocaleLowerCase() == regionQuery.toLocaleLowerCase() reg.value.toLocaleLowerCase() == regionQuery.toLocaleLowerCase()
)?.id || 'eu'; ) ?? regionsJSON[0];
} }
} }
} }
@@ -72,13 +72,11 @@
<script lang="ts"> <script lang="ts">
import { defineComponent, PropType } from 'vue'; import { defineComponent, PropType } from 'vue';
import dateMixin from '../../mixins/dateMixin'; import dateMixin from '../../mixins/dateMixin';
import Station from '../../scripts/interfaces/Station';
import Loading from '../Global/Loading.vue'; import Loading from '../Global/Loading.vue';
import styleMixin from '../../mixins/styleMixin'; import styleMixin from '../../mixins/styleMixin';
import listObserverMixin from '../../mixins/listObserverMixin'; import listObserverMixin from '../../mixins/listObserverMixin';
import { ActiveScenery } from '../../store/typings';
import { API } from '../../typings/api'; import { API } from '../../typings/api';
import { Status } from '../../typings/common'; import { ActiveScenery, Station, Status } from '../../typings/common';
import { useApiStore } from '../../store/apiStore'; import { useApiStore } from '../../store/apiStore';
export default defineComponent({ export default defineComponent({
+1 -2
View File
@@ -14,8 +14,7 @@
<script lang="ts"> <script lang="ts">
import { PropType, defineComponent } from 'vue'; import { PropType, defineComponent } from 'vue';
import Station from '../../scripts/interfaces/Station'; import { ActiveScenery, Station } from '../../typings/common';
import { ActiveScenery } from '../../store/typings';
export default defineComponent({ export default defineComponent({
props: { props: {
+1 -2
View File
@@ -89,8 +89,7 @@ import SceneryInfoIcons from './SceneryInfo/SceneryInfoIcons.vue';
import SceneryInfoUserList from './SceneryInfo/SceneryInfoUserList.vue'; import SceneryInfoUserList from './SceneryInfo/SceneryInfoUserList.vue';
import SceneryInfoSpawnList from './SceneryInfo/SceneryInfoSpawnList.vue'; import SceneryInfoSpawnList from './SceneryInfo/SceneryInfoSpawnList.vue';
import SceneryInfoRoutes from './SceneryInfo/SceneryInfoRoutes.vue'; import SceneryInfoRoutes from './SceneryInfo/SceneryInfoRoutes.vue';
import Station from '../../scripts/interfaces/Station'; import { ActiveScenery, Station } from '../../typings/common';
import { ActiveScenery } from '../../store/typings';
export default defineComponent({ export default defineComponent({
components: { components: {
@@ -49,8 +49,8 @@ import dateMixin from '../../../mixins/dateMixin';
import routerMixin from '../../../mixins/routerMixin'; import routerMixin from '../../../mixins/routerMixin';
import styleMixin from '../../../mixins/styleMixin'; import styleMixin from '../../../mixins/styleMixin';
import StationStatusBadge from '../../Global/StationStatusBadge.vue'; import StationStatusBadge from '../../Global/StationStatusBadge.vue';
import { ActiveScenery } from '../../../store/typings';
import donatorMixin from '../../../mixins/donatorMixin'; import donatorMixin from '../../../mixins/donatorMixin';
import { ActiveScenery } from '../../../typings/common';
export default defineComponent({ export default defineComponent({
mixins: [styleMixin, dateMixin, routerMixin, donatorMixin], mixins: [styleMixin, dateMixin, routerMixin, donatorMixin],
@@ -89,7 +89,7 @@
<script lang="ts"> <script lang="ts">
import { PropType, defineComponent } from 'vue'; import { PropType, defineComponent } from 'vue';
import styleMixin from '../../../mixins/styleMixin'; import styleMixin from '../../../mixins/styleMixin';
import Station from '../../../scripts/interfaces/Station'; import { Station } from '../../../typings/common';
export default defineComponent({ export default defineComponent({
mixins: [styleMixin], mixins: [styleMixin],
@@ -52,7 +52,7 @@
<script lang="ts"> <script lang="ts">
import { PropType, defineComponent } from 'vue'; import { PropType, defineComponent } from 'vue';
import Station from '../../../scripts/interfaces/Station'; import { Station } from '../../../typings/common';
export default defineComponent({ export default defineComponent({
props: { props: {
@@ -30,7 +30,7 @@
<script lang="ts"> <script lang="ts">
import { PropType, defineComponent } from 'vue'; import { PropType, defineComponent } from 'vue';
import { ActiveScenery } from '../../../store/typings'; import { ActiveScenery } from '../../../typings/common';
export default defineComponent({ export default defineComponent({
props: { props: {
@@ -1,83 +0,0 @@
<template>
<section class="info-stats" :class="!station.onlineInfo ? 'no-stats' : ''">
<span class="likes">
<img src="/images/icon-like" alt="Likes count icon" />
<span>{{ station.onlineInfo?.dispatcherRate || '0' }}</span>
</span>
<span class="users">
<img src="/images/icon-user" alt="Users count icon" />
<span>{{ station.onlineInfo?.currentUsers || '0' }}</span>
/
<span>{{ station.onlineInfo?.maxUsers || '0' }}</span>
</span>
<span class="spawns">
<img src="/images/icon-spawn" alt="Spawns count icon" />
<span>{{ station.onlineInfo?.spawns.length || '0' }}</span>
</span>
<span class="schedules">
<img src="/images/icon-timetable" alt="Timetables count icon" />
<span>
<span style="color: #eee">{{ station.onlineInfo?.scheduledTrains?.length || '0' }}</span>
/
<span style="color: #bbb"
>{{
station.onlineInfo?.scheduledTrains?.filter((train) => train.stopInfo.confirmed)
.length || '0'
}}
</span>
</span>
</span>
</section>
</template>
<script lang="ts">
import { PropType, defineComponent } from 'vue';
import Station from '../../../scripts/interfaces/Station';
export default defineComponent({
props: {
station: {
type: Object as PropType<Station>,
required: true
}
}
});
</script>
<style lang="scss" scoped>
@import '../../../styles/variables.scss';
.info-stats {
padding: 1rem 0;
display: flex;
flex-wrap: wrap;
justify-content: center;
font-size: 1.65em;
&.no-stats {
opacity: 0.5;
}
& > span {
display: flex;
align-items: center;
margin: 0.3em;
}
.likes,
.spawns {
color: $accentCol;
}
span > img {
width: 1.2em;
margin-right: 0.5em;
}
}
</style>
@@ -32,7 +32,7 @@
import { PropType, defineComponent } from 'vue'; import { PropType, defineComponent } from 'vue';
import modalTrainMixin from '../../../mixins/modalTrainMixin'; import modalTrainMixin from '../../../mixins/modalTrainMixin';
import routerMixin from '../../../mixins/routerMixin'; import routerMixin from '../../../mixins/routerMixin';
import { ActiveScenery } from '../../../store/typings'; import { ActiveScenery } from '../../../typings/common';
export default defineComponent({ export default defineComponent({
mixins: [routerMixin, modalTrainMixin], mixins: [routerMixin, modalTrainMixin],
@@ -14,14 +14,6 @@
</span> </span>
<span class="header_links" v-if="station"> <span class="header_links" v-if="station">
<!-- <a
:href="`https://pragotron-td2.web.app/board?name=${station.name}`"
target="_blank"
:title="$t('scenery.pragotron-link')"
>
<img src="/images/icon-pragotron.svg" alt="icon-pragotron" />
</a> -->
<a :href="tabliceZbiorczeHref" target="_blank" :title="$t('scenery.tablice-link')"> <a :href="tabliceZbiorczeHref" target="_blank" :title="$t('scenery.tablice-link')">
<img src="/images/icon-tablice.ico" alt="icon-tablice" /> <img src="/images/icon-tablice.ico" alt="icon-tablice" />
</a> </a>
@@ -186,12 +178,11 @@ import { useRoute } from 'vue-router';
import Loading from '../Global/Loading.vue'; import Loading from '../Global/Loading.vue';
import dateMixin from '../../mixins/dateMixin'; import dateMixin from '../../mixins/dateMixin';
import routerMixin from '../../mixins/routerMixin'; import routerMixin from '../../mixins/routerMixin';
import Station from '../../scripts/interfaces/Station';
import { useMainStore } from '../../store/mainStore'; import { useMainStore } from '../../store/mainStore';
import modalTrainMixin from '../../mixins/modalTrainMixin'; import modalTrainMixin from '../../mixins/modalTrainMixin';
import ScheduledTrainStatus from './ScheduledTrainStatus.vue'; import ScheduledTrainStatus from './ScheduledTrainStatus.vue';
import { ActiveScenery } from '../../store/typings';
import { useApiStore } from '../../store/apiStore'; import { useApiStore } from '../../store/apiStore';
import { ActiveScenery, Station } from '../../typings/common';
export default defineComponent({ export default defineComponent({
name: 'SceneryTimetable', name: 'SceneryTimetable',
@@ -71,12 +71,10 @@
import { defineComponent, PropType } from 'vue'; import { defineComponent, PropType } from 'vue';
import dateMixin from '../../mixins/dateMixin'; import dateMixin from '../../mixins/dateMixin';
import Station from '../../scripts/interfaces/Station';
import Loading from '../Global/Loading.vue'; import Loading from '../Global/Loading.vue';
import listObserverMixin from '../../mixins/listObserverMixin'; import listObserverMixin from '../../mixins/listObserverMixin';
import { ActiveScenery } from '../../store/typings';
import { API } from '../../typings/api'; import { API } from '../../typings/api';
import { Status } from '../../typings/common'; import { ActiveScenery, Station, Status } from '../../typings/common';
import { useApiStore } from '../../store/apiStore'; import { useApiStore } from '../../store/apiStore';
export default defineComponent({ export default defineComponent({
@@ -11,7 +11,7 @@
<script lang="ts"> <script lang="ts">
import { defineComponent, PropType } from 'vue'; import { defineComponent, PropType } from 'vue';
import { ScheduledTrain, StopStatus } from '../../store/typings'; import { ScheduledTrain, StopStatus } from '../../typings/common';
interface ScheduledTrainComp extends ScheduledTrain { interface ScheduledTrainComp extends ScheduledTrain {
stopStatusIndicator: string; stopStatusIndicator: string;
+21 -23
View File
@@ -1,6 +1,10 @@
<template> <template>
<section class="station_table"> <section class="station_table">
<div class="table_wrapper"> <Loading
v-if="apiStore.dataStatuses.connection == Status.Loading && displayedStations.length == 0"
/>
<div class="table_wrapper" v-else-if="displayedStations.length > 0">
<table> <table>
<thead> <thead>
<tr> <tr>
@@ -50,7 +54,7 @@
<tbody> <tbody>
<tr <tr
v-for="station in stations" v-for="station in displayedStations"
:class="{ 'last-selected': lastSelectedStationName == station.name }" :class="{ 'last-selected': lastSelectedStationName == station.name }"
:key="station.name" :key="station.name"
@click.left="setScenery(station.name)" @click.left="setScenery(station.name)"
@@ -283,12 +287,11 @@
</tr> </tr>
</tbody> </tbody>
</table> </table>
</div>
<Loading v-if="apiStore.dataStatuses.connection == Status.Loading && stations.length == 0" /> <div class="no-stations" v-else>
{{ $t('sceneries.no-stations') }} (region: <b>{{ mainStore.region.name }}</b
<div class="no-stations" v-else-if="stations.length == 0"> >)
{{ $t('sceneries.no-stations') }}
</div>
</div> </div>
</section> </section>
</template> </template>
@@ -297,24 +300,16 @@
import { defineComponent, PropType } from 'vue'; import { defineComponent, PropType } from 'vue';
import dateMixin from '../../mixins/dateMixin'; import dateMixin from '../../mixins/dateMixin';
import styleMixin from '../../mixins/styleMixin'; import styleMixin from '../../mixins/styleMixin';
import Station from '../../scripts/interfaces/Station';
import { useStationFiltersStore } from '../../store/stationFiltersStore'; import { useStationFiltersStore } from '../../store/stationFiltersStore';
import { useMainStore } from '../../store/mainStore'; import { useMainStore } from '../../store/mainStore';
import Loading from '../Global/Loading.vue'; import Loading from '../Global/Loading.vue';
import { HeadIdsTypes, headIconsIds, headIds } from '../../scripts/data/stationHeaderNames'; import { HeadIdsTypes, headIconsIds, headIds } from '../../scripts/data/stationHeaderNames';
import StationStatusBadge from '../Global/StationStatusBadge.vue'; import StationStatusBadge from '../Global/StationStatusBadge.vue';
import { Status } from '../../typings/common'; import { Station, Status } from '../../typings/common';
import { useApiStore } from '../../store/apiStore'; import { useApiStore } from '../../store/apiStore';
import popupMixin from '../../mixins/popupMixin'; import popupMixin from '../../mixins/popupMixin';
export default defineComponent({ export default defineComponent({
props: {
stations: {
type: Array as PropType<Station[]>,
required: true
}
},
emits: ['toggleDonationModal'], emits: ['toggleDonationModal'],
components: { Loading, StationStatusBadge }, components: { Loading, StationStatusBadge },
mixins: [styleMixin, dateMixin, popupMixin], mixins: [styleMixin, dateMixin, popupMixin],
@@ -328,6 +323,10 @@ export default defineComponent({
computed: { computed: {
sorterActive() { sorterActive() {
return this.stationFiltersStore.sorterActive; return this.stationFiltersStore.sorterActive;
},
displayedStations() {
return this.stationFiltersStore.filteredStationList;
} }
}, },
@@ -347,7 +346,8 @@ export default defineComponent({
methods: { methods: {
setScenery(name: string) { setScenery(name: string) {
const station = this.stations.find((station) => station.name === name); const station = this.displayedStations.find((station) => station.name === name);
if (!station) return; if (!station) return;
this.lastSelectedStationName = station.name; this.lastSelectedStationName = station.name;
@@ -389,12 +389,11 @@ export default defineComponent({
$rowCol: #424242; $rowCol: #424242;
.table_wrapper { .station_table {
overflow: auto;
overflow-y: scroll;
font-weight: 500;
height: 90vh; height: 90vh;
min-height: 550px; min-height: 550px;
overflow: auto;
font-weight: 500;
} }
.no-stations { .no-stations {
@@ -402,9 +401,8 @@ $rowCol: #424242;
font-size: 1.5em; font-size: 1.5em;
padding: 1em; padding: 1em;
margin: 1em 0;
background: #333; background: #1a1a1a;
} }
table { table {
+1 -1
View File
@@ -163,12 +163,12 @@
import { defineComponent } from 'vue'; import { defineComponent } from 'vue';
import styleMixin from '../../mixins/styleMixin'; import styleMixin from '../../mixins/styleMixin';
import trainInfoMixin from '../../mixins/trainInfoMixin'; import trainInfoMixin from '../../mixins/trainInfoMixin';
import Train from '../../scripts/interfaces/Train';
import ProgressBar from '../Global/ProgressBar.vue'; import ProgressBar from '../Global/ProgressBar.vue';
import { useMainStore } from '../../store/mainStore'; import { useMainStore } from '../../store/mainStore';
import { useApiStore } from '../../store/apiStore'; import { useApiStore } from '../../store/apiStore';
import StockList from '../Global/StockList.vue'; import StockList from '../Global/StockList.vue';
import modalTrainMixin from '../../mixins/modalTrainMixin'; import modalTrainMixin from '../../mixins/modalTrainMixin';
import { Train } from '../../typings/common';
export default defineComponent({ export default defineComponent({
mixins: [trainInfoMixin, styleMixin, modalTrainMixin], mixins: [trainInfoMixin, styleMixin, modalTrainMixin],
+1 -1
View File
@@ -13,7 +13,7 @@ import { defineComponent } from 'vue';
import modalTrainMixin from '../../mixins/modalTrainMixin'; import modalTrainMixin from '../../mixins/modalTrainMixin';
import TrainInfo from './TrainInfo.vue'; import TrainInfo from './TrainInfo.vue';
import TrainSchedule from './TrainSchedule.vue'; import TrainSchedule from './TrainSchedule.vue';
import Train from '../../scripts/interfaces/Train'; import { Train } from '../../typings/common';
export default defineComponent({ export default defineComponent({
components: { TrainInfo, TrainSchedule }, components: { TrainInfo, TrainSchedule },
+1 -1
View File
@@ -81,11 +81,11 @@
<script lang="ts"> <script lang="ts">
import { defineComponent, PropType } from 'vue'; import { defineComponent, PropType } from 'vue';
import dateMixin from '../../mixins/dateMixin'; import dateMixin from '../../mixins/dateMixin';
import Train from '../../scripts/interfaces/Train';
import StopLabel from './StopLabel.vue'; import StopLabel from './StopLabel.vue';
import StockList from '../Global/StockList.vue'; import StockList from '../Global/StockList.vue';
import { useMainStore } from '../../store/mainStore'; import { useMainStore } from '../../store/mainStore';
import { useApiStore } from '../../store/apiStore'; import { useApiStore } from '../../store/apiStore';
import { Train } from '../../typings/common';
export interface TrainScheduleStop { export interface TrainScheduleStop {
nameHtml: string; nameHtml: string;
+1 -2
View File
@@ -30,11 +30,10 @@
<script lang="ts"> <script lang="ts">
import { defineComponent, inject, PropType, Ref } from 'vue'; import { defineComponent, inject, PropType, Ref } from 'vue';
import modalTrainMixin from '../../mixins/modalTrainMixin'; import modalTrainMixin from '../../mixins/modalTrainMixin';
import Train from '../../scripts/interfaces/Train';
import { useMainStore } from '../../store/mainStore'; import { useMainStore } from '../../store/mainStore';
import Loading from '../Global/Loading.vue'; import Loading from '../Global/Loading.vue';
import TrainInfo from './TrainInfo.vue'; import TrainInfo from './TrainInfo.vue';
import { Status } from '../../typings/common'; import { Status, Train } from '../../typings/common';
import { useApiStore } from '../../store/apiStore'; import { useApiStore } from '../../store/apiStore';
export default defineComponent({ export default defineComponent({
+1 -2
View File
@@ -1,6 +1,5 @@
import { TrainFilter, TrainFilterId } from '../components/TrainsView/typings'; import { TrainFilter, TrainFilterId } from '../components/TrainsView/typings';
import Train from '../scripts/interfaces/Train'; import { Train, TrainStop } from '../typings/common';
import { TrainStop } from '../store/typings';
function confirmedPercentage(stops: TrainStop[] | undefined) { function confirmedPercentage(stops: TrainStop[] | undefined) {
if (!stops) return -1; if (!stops) return -1;
+3 -4
View File
@@ -1,6 +1,5 @@
import { defineComponent } from 'vue'; import { defineComponent } from 'vue';
import Train from '../scripts/interfaces/Train'; import { Train, TrainStop } from '../typings/common';
import { TrainStop } from '../store/typings';
export default defineComponent({ export default defineComponent({
data: () => ({ data: () => ({
@@ -51,8 +50,8 @@ export default defineComponent({
return diffMins < 1 return diffMins < 1
? this.$t('trains.last-seen-now') ? this.$t('trains.last-seen-now')
: diffMins < 2 : diffMins < 2
? this.$t('trains.last-seen-min') ? this.$t('trains.last-seen-min')
: this.$t('trains.last-seen-ago', { minutes: diffMins }); : this.$t('trains.last-seen-ago', { minutes: diffMins });
}, },
displayTrainPosition(train: Train) { displayTrainPosition(train: Train) {
-34
View File
@@ -1,34 +0,0 @@
import { Availability, ActiveScenery } from '../../store/typings';
import { StationRoutes } from './StationRoutes';
export default interface Station {
name: string;
generalInfo?: {
name: string;
url: string;
abbr: string;
hash?: string;
reqLevel: number;
// supportersOnly: boolean;
lines: string;
project: string;
projectUrl?: string;
signalType: string;
controlType: string;
SUP: boolean;
ASDEK: boolean;
authors?: string[];
availability: Availability;
routes: StationRoutes;
checkpoints: string[];
};
onlineInfo?: ActiveScenery;
}
-15
View File
@@ -1,15 +0,0 @@
import { StationRoutesInfo } from '../../store/typings';
export interface StationRoutes {
single: StationRoutesInfo[];
double: StationRoutesInfo[];
singleElectrifiedNames: string[];
singleOtherNames: string[];
doubleElectrifiedNames: string[];
doubleOtherNames: string[];
sblNames: string[];
minRouteSpeed: number;
maxRouteSpeed: number;
}
-38
View File
@@ -1,38 +0,0 @@
import { TrainStop } from '../../store/typings';
export default interface Train {
trainId: string;
mass: number;
length: number;
speed: number;
signal: string;
distance: number;
connectedTrack: string;
driverId: number;
trainNo: number;
driverName: string;
driverLevel: number;
currentStationName: string;
currentStationHash: string;
locoType: string;
online: boolean;
lastSeen: number;
region: string;
stockList: string[];
isTimeout: boolean;
isSupporter: boolean;
timetableData?: {
timetableId: number;
category: string;
route: string;
followingStops: TrainStop[];
TWR: boolean;
SKR: boolean;
routeDistance: number;
sceneries: string[];
sceneryNames: string[];
};
}
+1 -1
View File
@@ -1,7 +1,7 @@
import { Filter } from '../../components/StationsView/typings'; import { Filter } from '../../components/StationsView/typings';
import { Status } from '../../typings/common'; import { Status } from '../../typings/common';
import { HeadIdsTypes } from '../data/stationHeaderNames'; import { HeadIdsTypes } from '../data/stationHeaderNames';
import Station from '../interfaces/Station'; import { Station } from '../../typings/common';
const dispatcherStatusPriority = [ const dispatcherStatusPriority = [
Status.ActiveDispatcher.UNKNOWN, Status.ActiveDispatcher.UNKNOWN,
+44 -12
View File
@@ -1,18 +1,21 @@
import { defineStore } from 'pinia'; import { defineStore } from 'pinia';
import Train from '../scripts/interfaces/Train';
import { parseSpawns, getScheduledTrains, getStationTrains } from './utils'; import { parseSpawns, getScheduledTrains, getStationTrains } from './utils';
import { ActiveScenery, ScheduledTrain, StoreState } from './typings'; import {
ActiveScenery,
import { Status } from '../typings/common'; ScheduledTrain,
import Station from '../scripts/interfaces/Station'; Station,
StationRoutes,
Status,
Train
} from '../typings/common';
import { useApiStore } from './apiStore'; import { useApiStore } from './apiStore';
import { StationRoutes } from '../scripts/interfaces/StationRoutes'; import { MainStoreState } from './typings';
export const useMainStore = defineStore('store', { export const useMainStore = defineStore('mainStore', {
state: () => state: () =>
({ ({
region: { id: 'eu', value: 'PL1' }, region: { id: 'eu', value: 'PL1', name: 'PL1' },
isOffline: false, isOffline: false,
isNewUpdate: false, isNewUpdate: false,
@@ -29,8 +32,11 @@ export const useMainStore = defineStore('store', {
modalLastClickedTarget: null, modalLastClickedTarget: null,
mousePos: { x: 0, y: 0 }, mousePos: { x: 0, y: 0 },
popUpData: { key: null, content: '' } popUpData: { key: null, content: '' },
}) as StoreState,
stations: [] as Station[],
trainsOnline: [] as Train[]
}) as MainStoreState,
getters: { getters: {
trainList(): Train[] { trainList(): Train[] {
@@ -96,6 +102,7 @@ export const useMainStore = defineStore('store', {
}); });
}, },
// computed active sceneries
activeSceneryList(state): ActiveScenery[] { activeSceneryList(state): ActiveScenery[] {
const apiStore = useApiStore(); const apiStore = useApiStore();
@@ -156,8 +163,8 @@ export const useMainStore = defineStore('store', {
scenery.dispatcherStatus == Status.ActiveDispatcher.NO_LIMIT scenery.dispatcherStatus == Status.ActiveDispatcher.NO_LIMIT
? Date.now() + 25500000 ? Date.now() + 25500000
: scenery.dispatcherStatus > 5 : scenery.dispatcherStatus > 5
? scenery.dispatcherStatus ? scenery.dispatcherStatus
: null; : null;
list.push({ list.push({
name: scenery.stationName, name: scenery.stationName,
@@ -231,6 +238,7 @@ export const useMainStore = defineStore('store', {
return allActiveSceneries; return allActiveSceneries;
}, },
// computed station data
stationList(): Station[] { stationList(): Station[] {
const apiStore = useApiStore(); const apiStore = useApiStore();
@@ -283,6 +291,30 @@ export const useMainStore = defineStore('store', {
} }
}; };
}); });
},
allStationInfo(): Station[] {
const onlineUnsavedStations = this.activeSceneryList
.filter(
(scenery) =>
this.stationList.findIndex((st) => st.name == scenery.name) == -1 &&
scenery.region == this.region.id
)
.map((os) => ({
name: os.name,
generalInfo: undefined,
onlineInfo: os
}));
return [
...onlineUnsavedStations,
...this.stationList.map((st) => ({
...st,
onlineInfo: this.activeSceneryList.find(
(os) => os.name == st.name && os.region == this.region.id
)
}))
];
} }
} }
}); });
+1 -19
View File
@@ -77,26 +77,8 @@ export const useStationFiltersStore = defineStore('stationFiltersStore', {
filteredStationList: (state) => { filteredStationList: (state) => {
const store = useMainStore(); const store = useMainStore();
const savedStationNames = store.stationList.map((s) => s.name);
const onlineUnsavedStations = store.activeSceneryList return store.allStationInfo
.filter((os) => !savedStationNames.includes(os.name) && os.region == store.region.id)
.map((os) => ({
name: os.name,
generalInfo: undefined,
onlineInfo: os
}));
return [
...onlineUnsavedStations,
...store.stationList.map((station) => ({
...station,
// append to 'onlineInfo' object for filtering legacy reasons - to optimize later (hopefully)
onlineInfo: store.activeSceneryList.find(
(os) => os.name == station.name && os.region == store.region.id
)
}))
]
.filter((station) => filterStations(station, state.filters)) .filter((station) => filterStations(station, state.filters))
.sort((a, b) => sortStations(a, b, state.sorterActive)); .sort((a, b) => sortStations(a, b, state.sorterActive));
} }
+5 -128
View File
@@ -1,18 +1,11 @@
import { API } from '../typings/api'; import { API } from '../typings/api';
import { Status } from '../typings/common'; import { Availability, Station, StationRoutesInfo, Status, Train } from '../typings/common';
export const popupKeys = ['DonatorPopUp', 'TrainCommentsPopUp', 'VehiclePreviewPopUp'] as const; export const popupKeys = ['DonatorPopUp', 'TrainCommentsPopUp', 'VehiclePreviewPopUp'] as const;
export type Availability = 'default' | 'unavailable' | 'nonPublic' | 'abandoned' | 'nonDefault';
export type PopUpType = (typeof popupKeys)[number]; export type PopUpType = (typeof popupKeys)[number];
export interface RegionCounters { export interface MainStoreState {
stationCount: number; region: { id: string; value: string; name: string };
trainsCount: number;
timetablesCount: number;
}
export interface StoreState {
region: { id: string; value: string };
isOffline: boolean; isOffline: boolean;
isNewUpdate: boolean; isNewUpdate: boolean;
dispatcherStatsName: string; dispatcherStatsName: string;
@@ -24,17 +17,8 @@ export interface StoreState {
modalLastClickedTarget: EventTarget | null; modalLastClickedTarget: EventTarget | null;
mousePos: { x: number; y: number }; mousePos: { x: number; y: number };
popUpData: { key: PopUpType | null; content: string }; popUpData: { key: PopUpType | null; content: string };
} stations: Station[];
trainsOnline: Train[];
export interface StationRoutesInfo {
routeName: string;
isElectric: boolean;
isInternal: boolean;
isRouteSBL: boolean;
routeLength: number;
routeSpeed: number;
routeTracks: number;
hidden?: boolean;
} }
export interface StationJSONData { export interface StationJSONData {
@@ -62,110 +46,3 @@ export interface StationJSONData {
availability: Availability; availability: Availability;
} }
export interface ActiveScenery {
name: string;
hash: string;
region: string;
maxUsers: number;
currentUsers: number;
spawns: { spawnName: string; spawnLength: number; isElectrified: boolean }[];
dispatcherName: string;
dispatcherRate: number;
dispatcherId: number;
dispatcherExp: number;
dispatcherIsSupporter: boolean;
dispatcherStatus: Status.ActiveDispatcher | number;
dispatcherTimestamp: number | null;
isOnline: boolean;
stationTrains?: StationTrain[];
scheduledTrains?: ScheduledTrain[];
scheduledTrainCount: {
all: number;
confirmed: number;
unconfirmed: number;
};
}
export interface StationTrain {
driverName: string;
driverId: number;
trainNo: number;
trainId: string;
stopStatus: string;
}
export interface ScheduledTrain {
checkpointName: string;
trainId: string;
trainNo: number;
driverName: string;
driverId: number;
currentStationName: string;
currentStationHash: string;
category: string;
stopInfo: TrainStop;
terminatesAt: string;
beginsAt: string;
prevStationName: string;
nextStationName: string;
arrivingLine: string | null;
departureLine: string | null;
prevDepartureLine: string | null;
nextArrivalLine: string | null;
signal: string;
connectedTrack: string;
stopLabel: string;
stopStatus: StopStatus;
stopStatusID: number;
region: string;
}
export enum StopStatus {
ARRIVING = 'arriving',
DEPARTED = 'departed',
DEPARTED_AWAY = 'departed-away',
ONLINE = 'online',
STOPPED = 'stopped',
TERMINATED = 'terminated'
}
export interface TrainStop {
stopName: string;
stopNameRAW: string;
stopType: string;
stopDistance: number;
mainStop: boolean;
arrivalLine: string | null;
arrivalTimestamp: number;
arrivalRealTimestamp: number;
arrivalDelay: number;
departureLine: string | null;
departureTimestamp: number;
departureRealTimestamp: number;
departureDelay: number;
pointId: number;
comments?: string;
beginsHere: boolean;
terminatesHere: boolean;
confirmed: boolean;
stopped: boolean;
stopTime: number | null;
}
+8 -3
View File
@@ -1,6 +1,11 @@
import Station from '../scripts/interfaces/Station'; import {
import Train from '../scripts/interfaces/Train'; TrainStop,
import { ScheduledTrain, StationTrain, StopStatus, TrainStop } from './typings'; StopStatus,
Train,
ScheduledTrain,
Station,
StationTrain
} from '../typings/common';
export function getLocoURL(locoType: string): string { export function getLocoURL(locoType: string): string {
return `https://rj.td2.info.pl/dist/img/thumbnails/${ return `https://rj.td2.info.pl/dist/img/thumbnails/${
+1 -1
View File
@@ -128,8 +128,8 @@ export namespace API {
export type Response = Data[]; export type Response = Data[];
export interface Data { export interface Data {
id: string;
trainNo: number; trainNo: number;
mass: number; mass: number;
length: number; length: number;
speed: number; speed: number;
+209
View File
@@ -1,3 +1,14 @@
export type Availability = 'default' | 'unavailable' | 'nonPublic' | 'abandoned' | 'nonDefault';
export enum StopStatus {
ARRIVING = 'arriving',
DEPARTED = 'departed',
DEPARTED_AWAY = 'departed-away',
ONLINE = 'online',
STOPPED = 'stopped',
TERMINATED = 'terminated'
}
export namespace Status { export namespace Status {
export enum ActiveDispatcher { export enum ActiveDispatcher {
FREE = -3, FREE = -3,
@@ -20,3 +31,201 @@ export namespace Status {
Warning = 3 Warning = 3
} }
} }
export interface RegionCounters {
stationCount: number;
trainsCount: number;
timetablesCount: number;
}
export interface Train {
id: string;
trainId: string;
mass: number;
length: number;
speed: number;
signal: string;
distance: number;
connectedTrack: string;
driverId: number;
trainNo: number;
driverName: string;
driverLevel: number;
currentStationName: string;
currentStationHash: string;
locoType: string;
online: boolean;
lastSeen: number;
region: string;
stockList: string[];
isTimeout: boolean;
isSupporter: boolean;
timetableData?: {
timetableId: number;
category: string;
route: string;
followingStops: TrainStop[];
TWR: boolean;
SKR: boolean;
routeDistance: number;
sceneries: string[];
sceneryNames: string[];
};
}
export interface Station {
name: string;
generalInfo?: {
name: string;
url: string;
abbr: string;
hash?: string;
reqLevel: number;
// supportersOnly: boolean;
lines: string;
project: string;
projectUrl?: string;
signalType: string;
controlType: string;
SUP: boolean;
ASDEK: boolean;
authors?: string[];
availability: Availability;
routes: StationRoutes;
checkpoints: string[];
};
onlineInfo?: ActiveScenery;
}
export interface StationRoutes {
single: StationRoutesInfo[];
double: StationRoutesInfo[];
singleElectrifiedNames: string[];
singleOtherNames: string[];
doubleElectrifiedNames: string[];
doubleOtherNames: string[];
sblNames: string[];
minRouteSpeed: number;
maxRouteSpeed: number;
}
export interface StationRoutesInfo {
routeName: string;
isElectric: boolean;
isInternal: boolean;
isRouteSBL: boolean;
routeLength: number;
routeSpeed: number;
routeTracks: number;
hidden?: boolean;
}
export interface ActiveScenery {
name: string;
hash: string;
region: string;
maxUsers: number;
currentUsers: number;
spawns: { spawnName: string; spawnLength: number; isElectrified: boolean }[];
dispatcherName: string;
dispatcherRate: number;
dispatcherId: number;
dispatcherExp: number;
dispatcherIsSupporter: boolean;
dispatcherStatus: Status.ActiveDispatcher | number;
dispatcherTimestamp: number | null;
isOnline: boolean;
stationTrains?: StationTrain[];
scheduledTrains?: ScheduledTrain[];
scheduledTrainCount: {
all: number;
confirmed: number;
unconfirmed: number;
};
}
export interface StationTrain {
driverName: string;
driverId: number;
trainNo: number;
trainId: string;
stopStatus: string;
}
export interface ScheduledTrain {
checkpointName: string;
trainId: string;
trainNo: number;
driverName: string;
driverId: number;
currentStationName: string;
currentStationHash: string;
category: string;
stopInfo: TrainStop;
terminatesAt: string;
beginsAt: string;
prevStationName: string;
nextStationName: string;
arrivingLine: string | null;
departureLine: string | null;
prevDepartureLine: string | null;
nextArrivalLine: string | null;
signal: string;
connectedTrack: string;
stopLabel: string;
stopStatus: StopStatus;
stopStatusID: number;
region: string;
}
export interface TrainStop {
stopName: string;
stopNameRAW: string;
stopType: string;
stopDistance: number;
mainStop: boolean;
arrivalLine: string | null;
arrivalTimestamp: number;
arrivalRealTimestamp: number;
arrivalDelay: number;
departureLine: string | null;
departureTimestamp: number;
departureRealTimestamp: number;
departureDelay: number;
pointId: number;
comments?: string;
beginsHere: boolean;
terminatesHere: boolean;
confirmed: boolean;
stopped: boolean;
stopTime: number | null;
}
+37 -3
View File
@@ -20,7 +20,15 @@
</div> </div>
<Donation :isModalOpen="isDonationModalOpen" @toggleModal="toggleDonationModal" /> <Donation :isModalOpen="isDonationModalOpen" @toggleModal="toggleDonationModal" />
<StationTable :stations="computedStationList" @toggleDonationModal="toggleDonationModal" /> <StationTable @toggleDonationModal="toggleDonationModal" />
<div class="stations-stats">
<hr style="margin: 0.5em 0" />
Średnia liczba rozkładów jazdy na dyżurnego: <b>{{ avgTimetableCount }}</b> | Dostępne
szlaki 1-torowe: <b>{{ oneWayTracks }}</b> (zelektr.) / <b>{{ 0 }}</b> (spalinowe) |
Dostępne szlaki 2-torowe: <b>{{ 0 }}</b> (zelektr.) / <b>{{ 0 }}</b> (spalinowe) | Otwarte
spawny: <b>{{ 0 }}</b> (PAS.) / <b>{{ 0 }}</b> (TOW.) / <b>{{ 0 }}</b> (LUZ.)
</div>
</div> </div>
</section> </section>
</template> </template>
@@ -56,8 +64,29 @@ export default defineComponent({
}, },
computed: { computed: {
computedStationList() { avgTimetableCount() {
return this.filterStore.filteredStationList; const scheduledTrainsTotal = this.store.activeSceneryList.reduce<number>((acc, sc) => {
if (sc.region != 'eu') return acc;
acc += sc.scheduledTrainCount.all;
return acc;
}, 0);
return (
this.store.activeSceneryList.length != 0
? scheduledTrainsTotal / this.store.activeSceneryList.length
: 0
).toFixed(2);
},
oneWayTracks() {
// return this.computedStationList
// .filter((st) => st.onlineInfo && st.generalInfo?.routes.single)
// .map((st) => st.generalInfo!.routes.single.map((r) => r.routeName))
// .join(', ');
return [];
} }
}, },
@@ -119,6 +148,11 @@ export default defineComponent({
margin-bottom: 0.5em; margin-bottom: 0.5em;
} }
.stations-stats {
text-align: center;
color: #ccc;
}
button.btn-donation { button.btn-donation {
$btnColor: #254069; $btnColor: #254069;
+1 -1
View File
@@ -20,11 +20,11 @@ import { computed, ComputedRef, defineComponent, provide, reactive, ref, watch }
import TrainOptions from '../components/TrainsView/TrainOptions.vue'; import TrainOptions from '../components/TrainsView/TrainOptions.vue';
import TrainTable from '../components/TrainsView/TrainTable.vue'; import TrainTable from '../components/TrainsView/TrainTable.vue';
import modalTrainMixin from '../mixins/modalTrainMixin'; import modalTrainMixin from '../mixins/modalTrainMixin';
import Train from '../scripts/interfaces/Train';
import { useMainStore } from '../store/mainStore'; import { useMainStore } from '../store/mainStore';
import { TrainFilter, trainFilters } from '../components/TrainsView/typings'; import { TrainFilter, trainFilters } from '../components/TrainsView/typings';
import { filteredTrainList } from '../managers/trainFilterManager'; import { filteredTrainList } from '../managers/trainFilterManager';
import TrainStats from '../components/TrainsView/TrainStats.vue'; import TrainStats from '../components/TrainsView/TrainStats.vue';
import { Train } from '../typings/common';
export default defineComponent({ export default defineComponent({
components: { components: {