From ce8bbe4c67170312d570bc1c3d84009ad2f2fb2c Mon Sep 17 00:00:00 2001 From: Spythere Date: Sat, 7 Feb 2026 20:54:03 +0100 Subject: [PATCH] chore(profile): updated api objects; replaced mock data with api results --- src/typings/api.ts | 45 +++----- src/utils/calcUtils.ts | 5 + src/views/PlayerProfileView.vue | 177 ++++++++++++++++++++++++++------ 3 files changed, 167 insertions(+), 60 deletions(-) create mode 100644 src/utils/calcUtils.ts diff --git a/src/typings/api.ts b/src/typings/api.ts index 93124f5..c481717 100644 --- a/src/typings/api.ts +++ b/src/typings/api.ts @@ -30,7 +30,7 @@ export namespace API { export namespace PlayerActivity { export interface Data { dispatcher: API.ActiveSceneries.Data[]; - driver: API.ActiveTrains.Data; + driver: API.ActiveTrains.Data | null; } export type Response = Data; @@ -77,6 +77,9 @@ export namespace API { } export interface Data { + dispatcherId: number | null; + dispatcherName: string | null; + dispatcherLevel: number | null; services: Services | null; issuedTimetables: IssuedTimetables | null; } @@ -85,32 +88,19 @@ export namespace API { } export namespace DriverStats { - export interface SumStats { - routeDistance: number; - confirmedStopsCount: number; - allStopsCount: number; - currentDistance: number; - } - - export interface CountStats { - fulfilled: number; - terminated: number; - _all: number; - } - - export interface MaxStats { - routeDistance: number; - } - - export interface AvdStats { - routeDistance: number; - } - export interface Data { - _sum: SumStats; - _count: CountStats; - _max: MaxStats; - _avg: AvdStats; + driverName: string | null; + driverId: number | null; + driverLevel: number | null; + countAll: number; + countTerminated: number; + countFulfilled: number; + routeDistanceTotal: number | null; + routeDistanceAvg: number | null; + routeDistanceMax: number | null; + currentDistanceTotal: number | null; + confirmedStopsTotal: number | null; + allStopsTotal: number | null; } export type Response = Data; @@ -118,9 +108,6 @@ export namespace API { export namespace PlayerInfo { export interface Data { - playerName: string | null; - playerId: number | null; - currentActivity: PlayerActivity.Data; dispatcherStats: DispatcherStats.Data; dispatcherStatsLastMonth: DispatcherStats.Data; diff --git a/src/utils/calcUtils.ts b/src/utils/calcUtils.ts new file mode 100644 index 0000000..7541073 --- /dev/null +++ b/src/utils/calcUtils.ts @@ -0,0 +1,5 @@ +export function getCountPercentage(partCount: number, allCount: number, fixedDigits: number) { + if (allCount == 0) return 0; + + return ((partCount / allCount) * 100).toFixed(fixedDigits); +} diff --git a/src/views/PlayerProfileView.vue b/src/views/PlayerProfileView.vue index bb8b409..dd39449 100644 --- a/src/views/PlayerProfileView.vue +++ b/src/views/PlayerProfileView.vue @@ -7,17 +7,35 @@ v-if="playerTD2Info" :src="`https://td2.info.pl/index.php?action=dlattach;attach=${playerTD2Info.avatar};type=avatar`" alt="player image" - width="100" height="100" @error="(e) => ((e.target as any).src = '/images/default-avatar.jpg')" /> -

{{ playerInfo.playerName }}

+

{{ playerName }}

-

12 poziom maszynisty

-

12 poziom dyżurnego

+

{{ playerTD2Info.levels.driver }} poziom maszynisty

+

{{ playerTD2Info.levels.dispatcher }} poziom dyżurnego

-

Ostatnia aktywność: 02.02.2026 (DR)

+
+ +
+ ONLINE JAKO DR: + {{ + playerInfo.currentActivity.dispatcher + .map((d) => `${d.stationName} (${d.stationHash})`) + .join(', ') + }} +
+ +
+ ONLINE JAKO MASZYNISTA: + {{ playerInfo.currentActivity.driver }} +
+
@@ -28,27 +46,104 @@

STATYSTYKI MASZYNISTY


-
522 / 619 (95.39%) - wypełnione rozkłady jazdy
-
- 16091 / 17149 (95.39%) - zatwierdzony kilometraż w RJ +
+
+ + {{ playerInfo.driverStats.countFulfilled }} / + {{ playerInfo.driverStats.countAll }} ({{ + getCountPercentage( + playerInfo.driverStats.countFulfilled, + playerInfo.driverStats.countAll, + 2 + ) + }}%) + + - wypełnione rozkłady jazdy +
+
+ + {{ playerInfo.driverStats.currentDistanceTotal?.toFixed(2) }} / + {{ playerInfo.driverStats.routeDistanceTotal?.toFixed(2) }} ({{ + getCountPercentage( + playerInfo.driverStats.currentDistanceTotal || 0, + playerInfo.driverStats.routeDistanceTotal || 0, + 2 + ) + }}%) + + - zatwierdzony kilometraż w RJ +
+
+ + {{ playerInfo.driverStats.confirmedStopsTotal }} / + {{ playerInfo.driverStats.allStopsTotal }} ({{ + getCountPercentage( + playerInfo.driverStats.confirmedStopsTotal || 0, + playerInfo.driverStats.allStopsTotal || 0, + 2 + ) + }}%) + + - potwierdzonych stacji w RJ +
+
+ {{ playerInfo.driverStats.routeDistanceMax || 0 }}km - + najdłuższy rozkład jazdy +
+
+ + {{ playerInfo.driverStats.routeDistanceAvg?.toFixed(2) || 0 }}km + + - średnia długość wszystkich rozkładów +
-
- 2420 / 2537 (95.39%) - potwierdzonych stacji w RJ + +
+ Ten użytkownik nie posiada statystyk maszynisty zarejestrowanych przez Stacjownik!
-
237.13km - najdłuższy rozkład jazdy
-
60.39km - średnia długość wszystkich rozkładów
-
+
user icon

STATYSTYKI DYŻURNEGO RUCHU


-
25 - służby jako dyżurny ruchu
-
6 godz. 13 min. - najdłuższa służba
-
14 - wystawione RJ jako dyżurny ruchu
-
80.81km - najdłuższy wystawiony RJ
-
670.80km - suma długości wystawionych RJ
+
+ {{ playerInfo.dispatcherStats.services.count }} - służby + jako dyżurny ruchu +
+
+ {{ + humanizeDuration(playerInfo.dispatcherStats.services.durationMax) + }} + - najdłuższa służba +
+ +
+
+ {{ playerInfo.dispatcherStats.issuedTimetables.count }} + - wystawione RJ jako dyżurny ruchu +
+
+ + {{ playerInfo.dispatcherStats.issuedTimetables.distanceMax }}km + + - najdłuższy wystawiony RJ +
+
+ + {{ playerInfo.dispatcherStats.issuedTimetables.distanceSum.toFixed(2) }}km + + - suma długości wystawionych RJ +
+
+ +
+ Ten dyżurny nie wystawił jeszcze żadnego rozkładu jazdy +
@@ -60,7 +155,9 @@
train icon
-

55

+
+

{{ playerInfo.driverStatsLastMonth.countAll }}

+
ROZKŁADÓW
JAZDY @@ -69,7 +166,11 @@
spawn icon
-

5500

+
+

+ {{ playerInfo.driverStatsLastMonth.currentDistanceTotal || 0 }} +

+
POKONANYCH
KILOMETRÓW @@ -78,7 +179,11 @@
user icon
-

15

+
+

+ {{ playerInfo.dispatcherStatsLastMonth.services?.count || 0 }} +

+
SŁUŻB
DYŻURNEGO @@ -87,7 +192,11 @@
timetable icon
-

12

+
+

+ {{ playerInfo.dispatcherStatsLastMonth.issuedTimetables?.count || 0 }} +

+
WYSTAWIONYCH
ROZKŁADÓW @@ -172,6 +281,7 @@ import { API, Td2API } from '../typings/api'; import { humanizeDuration } from '../composables/time'; import { useI18n } from 'vue-i18n'; import axios from 'axios'; +import { getCountPercentage } from '../utils/calcUtils'; type JournalEntryType = 'Timetable' | 'Dispatcher' | 'IssuedTimetable'; @@ -185,6 +295,8 @@ const { t } = useI18n(); const apiStore = useApiStore(); const route = useRoute(); +const playerName = ref(''); + const playerInfo = ref(null); const playerJournal = ref(null); const playerTD2Info = ref(null); @@ -197,7 +309,7 @@ const activeFilterTypes = reactive>({ watch( computed(() => route.query.playerId), - (v) => { + () => { fetchAllData(); } ); @@ -207,7 +319,7 @@ onMounted(() => { }); const combinedJournal = computed(() => { - if (!playerJournal.value || !playerInfo.value) return []; + if (!playerJournal.value || !playerName.value) return []; const list = [ ...playerJournal.value.timetables, @@ -217,7 +329,7 @@ const combinedJournal = computed(() => { .reduce((acc, v) => { // Timetable or dispatcher type if ('trainNo' in v) { - const isIssued = v.authorName == playerInfo.value!.playerName; + const isIssued = v.authorName == playerName.value; if (!isIssued && !activeFilterTypes['Timetable']) return acc; if (isIssued && !activeFilterTypes['IssuedTimetable']) return acc; @@ -253,9 +365,16 @@ async function fetchAllData() { const playerInfoResponse = await fetchPlayerInfoData(playerId); - if (!playerInfoResponse || !playerInfoResponse.playerName) return; + if (!playerInfoResponse) return; - const playerTd2InfoResponse = await fetchPlayerTD2Info(playerInfoResponse.playerName); + playerName.value = + playerInfoResponse.driverStats.driverName || + playerInfoResponse.dispatcherStats.dispatcherName || + ''; + + if (!playerName.value) return; + + const playerTd2InfoResponse = await fetchPlayerTD2Info(playerName.value); const playerJournalResponse = await fetchPlayerJournal(playerId); playerInfo.value = playerInfoResponse; @@ -273,10 +392,6 @@ async function fetchPlayerInfoData(playerId: string) { } }); - if (response.data.playerName == null || response.data.playerId == null) { - return null; - } - return response.data; } catch (error) { console.error(error);