nowe pobieranie i przetwarzanie statusów dyżurnych

This commit is contained in:
2023-11-07 20:16:58 +01:00
parent edad5306f2
commit cbce9af00b
18 changed files with 1621 additions and 13639 deletions
+4 -2
View File
@@ -96,11 +96,13 @@ export default defineComponent({
computed: {
onlineTrainsCount() {
return this.store.trainList.filter((train) => train.online).length;
return this.store.trainList.filter((train) => train.region == this.store.region.id).length;
},
onlineDispatchersCount() {
return this.store.onlineSceneryList.length;
return this.store.onlineSceneryList.filter(
(scenery) => scenery.region == this.store.region.id
).length;
},
factorU() {
+5 -6
View File
@@ -67,16 +67,15 @@ export default defineComponent({
selectedItem() {
return this.regionList[this.selectedItemIndex] || null;
},
regionList() {
return regionsJSON.map((region) => {
const regionStationCount =
this.store.apiData.stations?.filter(
(station) => station.region == region.id && station.isOnline
).length || 0;
const regionStationCount = this.store.onlineSceneryList.filter(
(scenery) => scenery.region == region.id
).length;
const regionTrainCount =
this.store.apiData.trains?.filter((train) => train.region == region.id && train.online)
.length || 0;
this.store.trainList.filter((train) => train.region == region.id).length || 0;
return {
id: region.id,
+46 -15
View File
@@ -1,7 +1,7 @@
<template>
<span class="status-badge" :class="statusID" v-if="isOnline">
{{ $t(`status.${statusID}`) }}
{{ statusID == 'online' ? timestampToString(statusTimestamp!) : '' }}
<span class="status-badge" :class="statusName" v-if="isOnline">
{{ $t(`status.${statusName}`) }}
{{ dispatcherStatus && dispatcherStatus > 5 ? timestampToString(dispatcherStatus) : '' }}
</span>
<span class="status-badge free" v-else>
@@ -10,22 +10,52 @@
</template>
<script lang="ts">
import { defineComponent } from 'vue';
import { PropType, defineComponent } from 'vue';
import dateMixin from '../../mixins/dateMixin';
import { DispatcherStatus } from '../../scripts/enums/DispatcherStatus';
export default defineComponent({
props: {
statusID: {
type: String
},
statusTimestamp: {
type: Number
dispatcherStatus: {
type: Number as PropType<DispatcherStatus | number>
},
isOnline: {
type: Boolean
}
},
mixins: [dateMixin]
mixins: [dateMixin],
computed: {
statusName() {
if (!this.dispatcherStatus) return 'free';
switch (this.dispatcherStatus) {
case DispatcherStatus.AFK:
return 'afk';
case DispatcherStatus.ENDING:
return 'ending';
case DispatcherStatus.INVALID:
return 'invalid';
case DispatcherStatus.NOT_LOGGED_IN:
return 'not-signed';
case DispatcherStatus.NO_SPACE:
return 'no-space';
case DispatcherStatus.UNAVAILABLE:
return 'unavailable';
case DispatcherStatus.UNKNOWN:
return 'unknown';
default:
return 'online';
}
}
}
});
</script>
@@ -34,10 +64,10 @@ $free: #8a8a8a;
$ending: #e6c300;
$no-limit: #117fc9;
$unav: #ff3d5d;
$brb: #e6a100;
$afk: #e6a100;
$no-space: #222;
$online: #09a116;
$unknown: rgb(185, 60, 60);
$unknown: #b93c3c;
.status-badge {
border-radius: 1rem;
@@ -69,8 +99,8 @@ $unknown: rgb(185, 60, 60);
font-size: 0.85em;
}
&.brb {
background-color: $brb;
&.afk {
background-color: $afk;
color: black;
font-size: 0.95em;
}
@@ -82,7 +112,8 @@ $unknown: rgb(185, 60, 60);
font-size: 0.85em;
}
&.unknown {
&.unknown,
&.invalid {
background-color: $unknown;
font-size: 0.95em;
}
@@ -22,9 +22,8 @@
</div>
<StationStatusBadge
:statusID="onlineScenery?.statusID"
:isOnline="onlineScenery ? true : false"
:statusTimestamp="onlineScenery?.statusTimestamp"
:dispatcherStatus="onlineScenery?.dispatcherStatus"
/>
</section>
</template>
+1 -2
View File
@@ -108,9 +108,8 @@
<td class="station_status">
<StationStatusBadge
:statusID="station.onlineInfo?.statusID"
:isOnline="station.onlineInfo ? true : false"
:statusTimestamp="station.onlineInfo?.statusTimestamp"
:dispatcherStatus="station.onlineInfo?.dispatcherStatus"
/>
</td>
+1438 -13428
View File
File diff suppressed because it is too large Load Diff
+1
View File
@@ -80,6 +80,7 @@
"unavailable": "UNAVAILABLE",
"brb": "AFK",
"no-space": "NO SPACE",
"invalid": "INVALID HASH",
"unknown": "UNKNOWN"
},
"options": {
+1
View File
@@ -68,6 +68,7 @@
"unavailable": "NIEDOSTĘPNY",
"brb": "Z/W",
"no-space": "BRAK MIEJSCA",
"invalid": "NIEWPISANY",
"unknown": "NIEZNANY"
},
"options": {
+9 -11
View File
@@ -1,11 +1,9 @@
export enum DispatcherStatusID {
Unknown = 'unknown',
Outdated = 'outdated',
Unauthorized = 'not-signed',
OnlineNoLimit = 'no-limit',
Afk = 'brb',
Ending = 'ending',
NoSpace = 'no-space',
Unavailable = 'unavailable',
OnlineWithHours = 'online'
}
export enum DispatcherStatus {
INVALID = -2,
UNKNOWN = -1,
AFK = 1,
ENDING = 2,
NO_SPACE = 3,
UNAVAILABLE = 4,
NOT_LOGGED_IN = 5
}
@@ -0,0 +1,21 @@
import { DispatcherStatus } from '../../enums/DispatcherStatus';
export default interface ActiveSceneryAPIData {
dispatcherId: number;
dispatcherName: string;
dispatcherIsSupporter: boolean;
stationName: string;
stationHash: string;
region: string;
maxUsers: number;
currentUsers: number;
spawn: number;
lastSeen: number;
dispatcherExp: number;
nameFromHeader: string;
spawnString: string | null;
networkConnectionString: string;
isOnline: number;
dispatcherRate: number;
dispatcherStatus: DispatcherStatus | number;
}
+15 -5
View File
@@ -7,16 +7,25 @@ import { DriverStatsAPIData } from '../api/DriverStatsAPIData';
import { RollingStockGithubData } from '../github_api/StockInfoGithubData';
import Station from '../Station';
import { ScheduledTrain } from '../ScheduledTrain';
import { DispatcherStatusID } from '../../enums/DispatcherStatus';
import { DispatcherStatus } from '../../enums/DispatcherStatus';
import ActiveSceneryAPIData from '../api/SceneryAPIData';
export type Availability = 'default' | 'unavailable' | 'nonPublic' | 'abandoned' | 'nonDefault';
export interface RegionCounters {
stationCount: number;
trainsCount: number;
timetablesCount: number;
}
export interface StoreState {
stationList: Station[];
apiData: APIData;
rollingStockData?: RollingStockGithubData;
lastDispatcherStatuses: { hash: string; statusTimestamp: number; statusID: DispatcherStatusID }[];
regionOnlineCounters: RegionCounters[];
lastDispatcherStatuses: { hash: string; statusTimestamp: number; statusID: DispatcherStatus }[];
sceneryData: any[][];
@@ -55,6 +64,8 @@ export interface APIData {
stations?: StationAPIData[];
dispatchers?: string[][];
trains?: TrainAPIData[];
activeSceneries?: ActiveSceneryAPIData[];
connectedSocketCount: number;
}
@@ -113,8 +124,7 @@ export interface OnlineScenery {
dispatcherExp: number;
dispatcherIsSupporter: boolean;
statusTimestamp: number;
statusID: DispatcherStatusID;
dispatcherStatus: DispatcherStatus | number;
isOnline: boolean;
@@ -125,5 +135,5 @@ export interface OnlineScenery {
all: number;
confirmed: number;
unconfirmed: number;
}
};
}
@@ -72,7 +72,6 @@ function filterTrainList(
(searchedDriver.length > 0
? train.driverName.toLowerCase().startsWith(searchedDriver.toLowerCase())
: true) &&
(!train.timetableData ? train.online : train.timetableData) &&
isFiltered
);
});
+14 -14
View File
@@ -1,5 +1,5 @@
import { HeadIdsTypes } from '../data/stationHeaderNames';
import { DispatcherStatusID } from '../enums/DispatcherStatus';
import { DispatcherStatus } from '../enums/DispatcherStatus';
import Filter from '../interfaces/Filter';
import Station from '../interfaces/Station';
@@ -19,7 +19,7 @@ export const sortStations = (
break;
case 'status':
diff = (a.onlineInfo?.statusTimestamp || 0) - (b.onlineInfo?.statusTimestamp || 0);
diff = (a.onlineInfo?.dispatcherStatus || 0) - (b.onlineInfo?.dispatcherStatus || 0);
break;
case 'dispatcher':
@@ -81,27 +81,27 @@ export const filterStations = (station: Station, filters: Filter) => {
if (!station.onlineInfo && filters['free']) return false;
if (station.onlineInfo) {
const { statusID, statusTimestamp } = station.onlineInfo;
const { dispatcherStatus } = station.onlineInfo;
const isEnding = statusID == DispatcherStatusID.Ending && filters['endingStatus'];
const isEnding = dispatcherStatus == DispatcherStatus.ENDING && filters['endingStatus'];
const isNotSigned =
(statusID == 'not-signed' || statusID == 'unavailable') && filters['unavailableStatus'];
(dispatcherStatus == DispatcherStatus.NOT_LOGGED_IN ||
dispatcherStatus == DispatcherStatus.UNAVAILABLE) &&
filters['unavailableStatus'];
const isAFK = statusID == 'brb' && filters['afkStatus'];
const isAFK = dispatcherStatus == DispatcherStatus.AFK && filters['afkStatus'];
const isNoSpace = statusID == 'no-space' && filters['noSpaceStatus'];
const isNoSpace = dispatcherStatus == DispatcherStatus.NO_SPACE && filters['noSpaceStatus'];
const isOccupied = station.onlineInfo && filters['occupied'];
const isOnlineInBounds =
(filters['onlineFromHours'] < 8 &&
statusTimestamp > 0 &&
statusTimestamp <= Date.now() + filters['onlineFromHours'] * 3600000) ||
(filters['onlineFromHours'] > 0 && statusTimestamp <= 0) ||
(filters['onlineFromHours'] == 8 && statusID != 'no-limit');
if (isEnding || isNotSigned || isAFK || isNoSpace || isOccupied) return false;
if (isEnding || isOnlineInBounds || isNotSigned || isAFK || isNoSpace || isOccupied)
if (
filters['onlineFromHours'] > 0 &&
dispatcherStatus <= Date.now() + filters['onlineFromHours'] * 3600000
)
return false;
}
+9 -77
View File
@@ -1,51 +1,15 @@
import { DispatcherStatusID } from '../enums/DispatcherStatus';
import { ScheduledTrain, StopStatus } from '../interfaces/ScheduledTrain';
import Station from '../interfaces/Station';
import Train from '../interfaces/Train';
import TrainStop from '../interfaces/TrainStop';
import StationAPIData from '../interfaces/api/StationAPIData';
import { StationTrain, StoreState } from '../interfaces/store/storeTypes';
import ActiveSceneryAPIData from '../interfaces/api/SceneryAPIData';
import { StationTrain } from '../interfaces/store/storeTypes';
export const getLocoURL = (locoType: string): string =>
`https://rj.td2.info.pl/dist/img/thumbnails/${
locoType.includes('EN') ? locoType + 'rb' : locoType
}.png`;
export const getStatusID = (
stationStatus: any[] | undefined,
isSWDROnline: boolean
): DispatcherStatusID => {
if (isSWDROnline && !stationStatus) return DispatcherStatusID.Unauthorized;
if (!stationStatus) return DispatcherStatusID.Unknown;
// if (stationStatus == -1) return DispatcherStatusID.Unauthorized;
const statusCode = stationStatus[2];
const statusTimestamp = stationStatus[3];
switch (statusCode) {
case 0:
if (statusTimestamp - Date.now() > 21000000) return DispatcherStatusID.OnlineNoLimit;
return DispatcherStatusID.OnlineWithHours;
case 1:
return DispatcherStatusID.Afk;
case 2:
if (statusTimestamp == 0) return DispatcherStatusID.Ending;
break;
case 3:
return DispatcherStatusID.NoSpace;
default:
break;
}
return DispatcherStatusID.Unavailable;
};
export const getStatusTimestamp = (stationStatus: any): number => {
if (!stationStatus) return -2;
@@ -218,40 +182,12 @@ export function getCheckpointTrain(
};
}
export function getDispatcherStatus(state: StoreState, onlineStationData: StationAPIData) {
const { dispatchers } = state.apiData;
const prevDispatcherStatus = state.lastDispatcherStatuses.find(
(dispatcher) => dispatcher.hash === onlineStationData.stationHash
);
const stationStatus = dispatchers?.find(
(status: string[]) => status[0] == onlineStationData.stationHash && status[1] == state.region.id
);
const statusTimestamp =
prevDispatcherStatus && !dispatchers
? prevDispatcherStatus.statusTimestamp
: getStatusTimestamp(stationStatus);
const statusID =
prevDispatcherStatus && !dispatchers
? prevDispatcherStatus.statusID
: getStatusID(stationStatus, onlineStationData.isOnline === 1);
return {
hash: onlineStationData.stationHash,
statusID,
statusTimestamp
};
}
export function getScheduledTrains(
trainList: Train[],
stationAPIData: StationAPIData,
sceneryData: ActiveSceneryAPIData,
stationGeneralInfo: Station['generalInfo']
): ScheduledTrain[] {
const stationName = stationAPIData.stationName.toLocaleLowerCase();
const stationName = sceneryData.stationName.toLocaleLowerCase();
stationGeneralInfo?.checkpoints.forEach((cp) => (cp.scheduledTrains.length = 0));
@@ -259,7 +195,7 @@ export function getScheduledTrains(
if (!train.timetableData) return acc;
const timetable = train.timetableData;
if (!timetable.sceneries.includes(stationAPIData.stationHash)) return acc;
if (!timetable.sceneries.includes(sceneryData.stationHash)) return acc;
const stopInfoIndex = timetable.followingStops.findIndex((stop) => {
const stopName = stop.stopNameRAW.toLowerCase();
@@ -277,7 +213,7 @@ export function getScheduledTrains(
if (stopInfoIndex != -1) {
checkpointScheduledTrains.push(
getCheckpointTrain(train, stopInfoIndex, stationAPIData.stationName)
getCheckpointTrain(train, stopInfoIndex, sceneryData.stationName)
);
}
@@ -298,9 +234,7 @@ export function getScheduledTrains(
);
if (index > -1)
checkpointScheduledTrains.push(
getCheckpointTrain(train, index, stationAPIData.stationName)
);
checkpointScheduledTrains.push(getCheckpointTrain(train, index, sceneryData.stationName));
});
acc.push(...checkpointScheduledTrains);
@@ -312,14 +246,12 @@ export function getStationTrains(
trainList: Train[],
scheduledTrainList: ScheduledTrain[],
region: string,
apiStation: StationAPIData
scenery: ActiveSceneryAPIData
): StationTrain[] {
return trainList
.filter(
(train) =>
train?.region === region &&
train.online &&
train.currentStationName === apiStation.stationName
train?.region === region && train.online && train.currentStationName === scenery.stationName
)
.map((train) => ({
driverName: train.driverName,
+3 -1
View File
@@ -26,7 +26,9 @@ export const useStationFiltersStore = defineStore('stationFiltersStore', {
return store.stationList
.map((station) => ({
...station,
onlineInfo: store.onlineSceneryList.find((os) => os.name == station.name)
onlineInfo: store.onlineSceneryList.find(
(os) => os.name == station.name && os.region == store.region.id
)
}))
.filter((station) => filterStations(station, state.filters))
.sort((a, b) => sortStations(a, b, state.sorterActive));
+49 -72
View File
@@ -5,12 +5,7 @@ import { DataStatus } from '../scripts/enums/DataStatus';
import StationRoutes from '../scripts/interfaces/StationRoutes';
import Train from '../scripts/interfaces/Train';
import { URLs } from '../scripts/utils/apiURLs';
import {
getDispatcherStatus,
parseSpawns,
getScheduledTrains,
getStationTrains
} from '../scripts/utils/storeUtils';
import { parseSpawns, getScheduledTrains, getStationTrains } from '../scripts/utils/storeUtils';
import {
APIData,
@@ -22,7 +17,7 @@ import {
import packageInfo from '../../package.json';
import { RollingStockGithubData } from '../scripts/interfaces/github_api/StockInfoGithubData';
import { ScheduledTrain } from '../scripts/interfaces/ScheduledTrain';
import { DispatcherStatusID } from '../scripts/enums/DispatcherStatus';
import { DispatcherStatus } from '../scripts/enums/DispatcherStatus';
export const useStore = defineStore('store', {
state: () =>
@@ -31,6 +26,7 @@ export const useStore = defineStore('store', {
rollingStockData: undefined,
stationList: [],
regionOnlineCounters: [],
routesList: [],
@@ -72,11 +68,7 @@ export const useStore = defineStore('store', {
getters: {
trainList(): Train[] {
return (this.apiData?.trains ?? [])
.filter(
(train) =>
train.region === this.region.id &&
(train.online || train.timetable || train.lastSeen > Date.now() - 180000)
)
.filter((train) => train.online || train.timetable || train.lastSeen > Date.now() - 180000)
.map((train) => {
const stock = train.stockString.split(';');
const locoType = stock ? stock[0] : train.stockString;
@@ -127,75 +119,59 @@ export const useStore = defineStore('store', {
onlineSceneryList(state): OnlineScenery[] {
if (state.isOffline) return [];
if (!state.apiData?.stations) return [];
if (!state.apiData?.activeSceneries) return [];
return (
state.apiData?.stations
// ?.filter((apiStation) => apiStation.region == state.region.id)
.reduce((list, apiStation) => {
if (apiStation.region != state.region.id) return list;
return state.apiData?.activeSceneries.reduce((list, scenery) => {
if (scenery.isOnline !== 1 && Date.now() - scenery.lastSeen > 1000 * 60 * 3) return list;
if (scenery.dispatcherStatus == DispatcherStatus.UNKNOWN) return list;
if (apiStation.isOnline !== 1 && Date.now() - apiStation.lastSeen > 1000 * 60 * 3)
return list;
const station = this.stationList.find((s) => s.name === scenery.stationName);
const dispatcherStatus = getDispatcherStatus(state as StoreState, apiStation);
const scheduledTrains = getScheduledTrains(this.trainList, scenery, station?.generalInfo);
if (dispatcherStatus.statusID == DispatcherStatusID.Unknown) return list;
const stationTrains = getStationTrains(
this.trainList,
scheduledTrains,
this.region.id,
scenery
);
const station = this.stationList.find((s) => s.name === apiStation.stationName);
// Remove checkpoint duplicates
const uniqueScheduledTrains = scheduledTrains.reduce(
(uniqueList, sTrain) =>
uniqueList.find((v) => v.trainId === sTrain.trainId)
? uniqueList
: [...uniqueList, sTrain],
[] as ScheduledTrain[]
);
const scheduledTrains = getScheduledTrains(
this.trainList,
apiStation,
station?.generalInfo
);
list.push({
name: scenery.stationName,
hash: scenery.stationHash,
region: scenery.region,
maxUsers: scenery.maxUsers,
currentUsers: scenery.currentUsers,
spawns: parseSpawns(scenery.spawnString),
dispatcherName: scenery.dispatcherName,
dispatcherRate: scenery.dispatcherRate,
dispatcherId: scenery.dispatcherId,
dispatcherExp: scenery.dispatcherExp,
dispatcherIsSupporter: scenery.dispatcherIsSupporter,
scheduledTrains: scheduledTrains,
stationTrains: stationTrains,
dispatcherStatus: scenery.dispatcherStatus,
const stationTrains = getStationTrains(
this.trainList,
scheduledTrains,
this.region.id,
apiStation
);
isOnline: scenery.isOnline == 1,
// Remove checkpoint duplicates
const uniqueScheduledTrains = scheduledTrains.reduce(
(uniqueList, sTrain) =>
uniqueList.find((v) => v.trainId === sTrain.trainId)
? uniqueList
: [...uniqueList, sTrain],
[] as ScheduledTrain[]
);
scheduledTrainCount: {
all: uniqueScheduledTrains.length,
confirmed: uniqueScheduledTrains.filter((train) => train.stopInfo.confirmed).length,
unconfirmed: uniqueScheduledTrains.filter((train) => !train.stopInfo.confirmed).length
}
});
list.push({
name: apiStation.stationName,
hash: apiStation.stationHash,
region: apiStation.region,
maxUsers: apiStation.maxUsers,
currentUsers: apiStation.currentUsers,
spawns: parseSpawns(apiStation.spawnString),
dispatcherName: apiStation.dispatcherName,
dispatcherRate: apiStation.dispatcherRate,
dispatcherId: apiStation.dispatcherId,
dispatcherExp: apiStation.dispatcherExp,
dispatcherIsSupporter: apiStation.dispatcherIsSupporter,
scheduledTrains: scheduledTrains,
stationTrains: stationTrains,
statusTimestamp: dispatcherStatus.statusTimestamp,
statusID: dispatcherStatus.statusID,
isOnline: apiStation.isOnline == 1,
scheduledTrainCount: {
all: uniqueScheduledTrains.length,
confirmed: uniqueScheduledTrains.filter((train) => train.stopInfo.confirmed).length,
unconfirmed: uniqueScheduledTrains.filter((train) => !train.stopInfo.confirmed)
.length
}
});
return list;
}, [] as OnlineScenery[])
);
return list;
}, [] as OnlineScenery[]);
}
},
actions: {
@@ -287,6 +263,7 @@ export const useStore = defineStore('store', {
socket.on('UPDATE', (data: APIData) => {
this.apiData = data;
this.dataStatuses.connection = DataStatus.Loaded;
this.setStatuses();
});
+3 -1
View File
@@ -134,7 +134,9 @@ export default defineComponent({
onlineSceneryInfo() {
return this.store.onlineSceneryList.find(
(scenery) => scenery.name === this.station?.toString().replace(/_/g, ' ')
(scenery) =>
scenery.name === this.station?.toString().replace(/_/g, ' ') &&
scenery.region == this.store.region.id
);
}
},
+1 -2
View File
@@ -70,7 +70,7 @@ export default defineComponent({
const computedTrains: ComputedRef<Train[]> = computed(() => {
return filteredTrainList(
store.trainList,
store.trainList.filter((train) => train.region == store.region.id),
searchedTrain.value,
searchedDriver.value,
sorterActive,
@@ -83,7 +83,6 @@ export default defineComponent({
currentOptionsActive.value =
sT.length > 0 || sD.length > 0 || sA.id != 'routeDistance' || areFiltersActive;
console.log(sA.id);
});
return {