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
-
+
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 @@
-
55
+
+
{{ playerInfo.driverStatsLastMonth.countAll }}
+
ROZKŁADÓW
JAZDY
@@ -69,7 +166,11 @@
-
5500
+
+
+ {{ playerInfo.driverStatsLastMonth.currentDistanceTotal || 0 }}
+
+
POKONANYCH
KILOMETRÓW
@@ -78,7 +179,11 @@
-
15
+
+
+ {{ playerInfo.dispatcherStatsLastMonth.services?.count || 0 }}
+
+
SŁUŻB
DYŻURNEGO
@@ -87,7 +192,11 @@
-
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);