mirror of
https://github.com/Spythere/stacjownik.git
synced 2026-05-03 05:18:11 +00:00
chore(profile): updated api objects; replaced mock data with api results
This commit is contained in:
+16
-29
@@ -30,7 +30,7 @@ export namespace API {
|
|||||||
export namespace PlayerActivity {
|
export namespace PlayerActivity {
|
||||||
export interface Data {
|
export interface Data {
|
||||||
dispatcher: API.ActiveSceneries.Data[];
|
dispatcher: API.ActiveSceneries.Data[];
|
||||||
driver: API.ActiveTrains.Data;
|
driver: API.ActiveTrains.Data | null;
|
||||||
}
|
}
|
||||||
|
|
||||||
export type Response = Data;
|
export type Response = Data;
|
||||||
@@ -77,6 +77,9 @@ export namespace API {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface Data {
|
export interface Data {
|
||||||
|
dispatcherId: number | null;
|
||||||
|
dispatcherName: string | null;
|
||||||
|
dispatcherLevel: number | null;
|
||||||
services: Services | null;
|
services: Services | null;
|
||||||
issuedTimetables: IssuedTimetables | null;
|
issuedTimetables: IssuedTimetables | null;
|
||||||
}
|
}
|
||||||
@@ -85,32 +88,19 @@ export namespace API {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export namespace DriverStats {
|
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 {
|
export interface Data {
|
||||||
_sum: SumStats;
|
driverName: string | null;
|
||||||
_count: CountStats;
|
driverId: number | null;
|
||||||
_max: MaxStats;
|
driverLevel: number | null;
|
||||||
_avg: AvdStats;
|
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;
|
export type Response = Data;
|
||||||
@@ -118,9 +108,6 @@ export namespace API {
|
|||||||
|
|
||||||
export namespace PlayerInfo {
|
export namespace PlayerInfo {
|
||||||
export interface Data {
|
export interface Data {
|
||||||
playerName: string | null;
|
|
||||||
playerId: number | null;
|
|
||||||
|
|
||||||
currentActivity: PlayerActivity.Data;
|
currentActivity: PlayerActivity.Data;
|
||||||
dispatcherStats: DispatcherStats.Data;
|
dispatcherStats: DispatcherStats.Data;
|
||||||
dispatcherStatsLastMonth: DispatcherStats.Data;
|
dispatcherStatsLastMonth: DispatcherStats.Data;
|
||||||
|
|||||||
@@ -0,0 +1,5 @@
|
|||||||
|
export function getCountPercentage(partCount: number, allCount: number, fixedDigits: number) {
|
||||||
|
if (allCount == 0) return 0;
|
||||||
|
|
||||||
|
return ((partCount / allCount) * 100).toFixed(fixedDigits);
|
||||||
|
}
|
||||||
+146
-31
@@ -7,17 +7,35 @@
|
|||||||
v-if="playerTD2Info"
|
v-if="playerTD2Info"
|
||||||
:src="`https://td2.info.pl/index.php?action=dlattach;attach=${playerTD2Info.avatar};type=avatar`"
|
:src="`https://td2.info.pl/index.php?action=dlattach;attach=${playerTD2Info.avatar};type=avatar`"
|
||||||
alt="player image"
|
alt="player image"
|
||||||
width="100"
|
|
||||||
height="100"
|
height="100"
|
||||||
@error="(e) => ((e.target as any).src = '/images/default-avatar.jpg')"
|
@error="(e) => ((e.target as any).src = '/images/default-avatar.jpg')"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<h3>{{ playerInfo.playerName }}</h3>
|
<h3>{{ playerName }}</h3>
|
||||||
|
|
||||||
<p>12 poziom maszynisty</p>
|
<p v-if="playerTD2Info != null">{{ playerTD2Info.levels.driver }} poziom maszynisty</p>
|
||||||
<p>12 poziom dyżurnego</p>
|
<p v-if="playerTD2Info != null">{{ playerTD2Info.levels.dispatcher }} poziom dyżurnego</p>
|
||||||
|
|
||||||
<p>Ostatnia aktywność: 02.02.2026 (DR)</p>
|
<div v-if="combinedJournal.length > 0">
|
||||||
|
<!-- <p>Ostatnia aktywność:</p> -->
|
||||||
|
<div v-if="playerInfo.currentActivity.dispatcher.length > 0">
|
||||||
|
<b class="text--primary">ONLINE JAKO DR:</b>
|
||||||
|
{{
|
||||||
|
playerInfo.currentActivity.dispatcher
|
||||||
|
.map((d) => `${d.stationName} (${d.stationHash})`)
|
||||||
|
.join(', ')
|
||||||
|
}}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div
|
||||||
|
v-if="
|
||||||
|
playerInfo.currentActivity.driver && playerInfo.currentActivity.driver.length > 0
|
||||||
|
"
|
||||||
|
>
|
||||||
|
<b>ONLINE JAKO MASZYNISTA:</b>
|
||||||
|
{{ playerInfo.currentActivity.driver }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<!-- <p>Stacjosponsor od 01.01.2024</p> -->
|
<!-- <p>Stacjosponsor od 01.01.2024</p> -->
|
||||||
</div>
|
</div>
|
||||||
@@ -28,27 +46,104 @@
|
|||||||
<h3>STATYSTYKI MASZYNISTY</h3>
|
<h3>STATYSTYKI MASZYNISTY</h3>
|
||||||
<hr />
|
<hr />
|
||||||
|
|
||||||
<div><b class="text--primary">522 / 619 (95.39%)</b> - wypełnione rozkłady jazdy</div>
|
<div v-if="playerInfo.driverStats.countAll > 0">
|
||||||
<div>
|
<div>
|
||||||
<b class="text--primary">16091 / 17149 (95.39%)</b> - zatwierdzony kilometraż w RJ
|
<b class="text--primary">
|
||||||
|
{{ playerInfo.driverStats.countFulfilled }} /
|
||||||
|
{{ playerInfo.driverStats.countAll }} ({{
|
||||||
|
getCountPercentage(
|
||||||
|
playerInfo.driverStats.countFulfilled,
|
||||||
|
playerInfo.driverStats.countAll,
|
||||||
|
2
|
||||||
|
)
|
||||||
|
}}%)
|
||||||
|
</b>
|
||||||
|
- wypełnione rozkłady jazdy
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<b class="text--primary">
|
||||||
|
{{ playerInfo.driverStats.currentDistanceTotal?.toFixed(2) }} /
|
||||||
|
{{ playerInfo.driverStats.routeDistanceTotal?.toFixed(2) }} ({{
|
||||||
|
getCountPercentage(
|
||||||
|
playerInfo.driverStats.currentDistanceTotal || 0,
|
||||||
|
playerInfo.driverStats.routeDistanceTotal || 0,
|
||||||
|
2
|
||||||
|
)
|
||||||
|
}}%)
|
||||||
|
</b>
|
||||||
|
- zatwierdzony kilometraż w RJ
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<b class="text--primary">
|
||||||
|
{{ playerInfo.driverStats.confirmedStopsTotal }} /
|
||||||
|
{{ playerInfo.driverStats.allStopsTotal }} ({{
|
||||||
|
getCountPercentage(
|
||||||
|
playerInfo.driverStats.confirmedStopsTotal || 0,
|
||||||
|
playerInfo.driverStats.allStopsTotal || 0,
|
||||||
|
2
|
||||||
|
)
|
||||||
|
}}%)
|
||||||
|
</b>
|
||||||
|
- potwierdzonych stacji w RJ
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<b class="text--primary">{{ playerInfo.driverStats.routeDistanceMax || 0 }}km</b> -
|
||||||
|
najdłuższy rozkład jazdy
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<b class="text--primary">
|
||||||
|
{{ playerInfo.driverStats.routeDistanceAvg?.toFixed(2) || 0 }}km
|
||||||
|
</b>
|
||||||
|
- średnia długość wszystkich rozkładów
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
|
||||||
<b class="text--primary">2420 / 2537 (95.39%)</b> - potwierdzonych stacji w RJ
|
<div class="text--grayed" v-else>
|
||||||
|
Ten użytkownik nie posiada statystyk maszynisty zarejestrowanych przez Stacjownik!
|
||||||
</div>
|
</div>
|
||||||
<div><b class="text--primary">237.13km</b> - najdłuższy rozkład jazdy</div>
|
|
||||||
<div><b class="text--primary">60.39km</b> - średnia długość wszystkich rozkładów</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="stats-dispatcher">
|
<div
|
||||||
|
class="stats-dispatcher"
|
||||||
|
v-if="playerInfo.dispatcherStats && playerInfo.dispatcherStats.services?.count"
|
||||||
|
>
|
||||||
<img src="/images/icon-user.svg" width="35" alt="user icon" />
|
<img src="/images/icon-user.svg" width="35" alt="user icon" />
|
||||||
<h3>STATYSTYKI DYŻURNEGO RUCHU</h3>
|
<h3>STATYSTYKI DYŻURNEGO RUCHU</h3>
|
||||||
<hr />
|
<hr />
|
||||||
|
|
||||||
<div><b class="text--primary">25</b> - służby jako dyżurny ruchu</div>
|
<div>
|
||||||
<div><b class="text--primary">6 godz. 13 min.</b> - najdłuższa służba</div>
|
<b class="text--primary">{{ playerInfo.dispatcherStats.services.count }}</b> - służby
|
||||||
<div><b class="text--primary">14</b> - wystawione RJ jako dyżurny ruchu</div>
|
jako dyżurny ruchu
|
||||||
<div><b class="text--primary">80.81km</b> - najdłuższy wystawiony RJ</div>
|
</div>
|
||||||
<div><b class="text--primary">670.80km</b> - suma długości wystawionych RJ</div>
|
<div>
|
||||||
|
<b class="text--primary">{{
|
||||||
|
humanizeDuration(playerInfo.dispatcherStats.services.durationMax)
|
||||||
|
}}</b>
|
||||||
|
- najdłuższa służba
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div v-if="playerInfo.dispatcherStats.issuedTimetables">
|
||||||
|
<div>
|
||||||
|
<b class="text--primary">{{ playerInfo.dispatcherStats.issuedTimetables.count }}</b>
|
||||||
|
- wystawione RJ jako dyżurny ruchu
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<b class="text--primary">
|
||||||
|
{{ playerInfo.dispatcherStats.issuedTimetables.distanceMax }}km
|
||||||
|
</b>
|
||||||
|
- najdłuższy wystawiony RJ
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<b class="text--primary">
|
||||||
|
{{ playerInfo.dispatcherStats.issuedTimetables.distanceSum.toFixed(2) }}km
|
||||||
|
</b>
|
||||||
|
- suma długości wystawionych RJ
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="text--grayed" v-else>
|
||||||
|
Ten dyżurny nie wystawił jeszcze żadnego rozkładu jazdy
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -60,7 +155,9 @@
|
|||||||
<div class="month-stats-box">
|
<div class="month-stats-box">
|
||||||
<div class="month-stat">
|
<div class="month-stat">
|
||||||
<div><img src="/images/icon-train.svg" width="30" alt="train icon" /></div>
|
<div><img src="/images/icon-train.svg" width="30" alt="train icon" /></div>
|
||||||
<div><h3 class="text--primary">55</h3></div>
|
<div>
|
||||||
|
<h3 class="text--primary">{{ playerInfo.driverStatsLastMonth.countAll }}</h3>
|
||||||
|
</div>
|
||||||
<div>
|
<div>
|
||||||
ROZKŁADÓW <br />
|
ROZKŁADÓW <br />
|
||||||
JAZDY
|
JAZDY
|
||||||
@@ -69,7 +166,11 @@
|
|||||||
|
|
||||||
<div class="month-stat">
|
<div class="month-stat">
|
||||||
<div><img src="/images/icon-spawn.svg" width="30" alt="spawn icon" /></div>
|
<div><img src="/images/icon-spawn.svg" width="30" alt="spawn icon" /></div>
|
||||||
<div><h3 class="text--primary">5500</h3></div>
|
<div>
|
||||||
|
<h3 class="text--primary">
|
||||||
|
{{ playerInfo.driverStatsLastMonth.currentDistanceTotal || 0 }}
|
||||||
|
</h3>
|
||||||
|
</div>
|
||||||
<div>
|
<div>
|
||||||
POKONANYCH <br />
|
POKONANYCH <br />
|
||||||
KILOMETRÓW
|
KILOMETRÓW
|
||||||
@@ -78,7 +179,11 @@
|
|||||||
|
|
||||||
<div class="month-stat">
|
<div class="month-stat">
|
||||||
<div><img src="/images/icon-user.svg" width="30" alt="user icon" /></div>
|
<div><img src="/images/icon-user.svg" width="30" alt="user icon" /></div>
|
||||||
<div><h3 class="text--primary">15</h3></div>
|
<div>
|
||||||
|
<h3 class="text--primary">
|
||||||
|
{{ playerInfo.dispatcherStatsLastMonth.services?.count || 0 }}
|
||||||
|
</h3>
|
||||||
|
</div>
|
||||||
<div>
|
<div>
|
||||||
SŁUŻB <br />
|
SŁUŻB <br />
|
||||||
DYŻURNEGO
|
DYŻURNEGO
|
||||||
@@ -87,7 +192,11 @@
|
|||||||
|
|
||||||
<div class="month-stat">
|
<div class="month-stat">
|
||||||
<div><img src="/images/icon-timetable.svg" width="30" alt="timetable icon" /></div>
|
<div><img src="/images/icon-timetable.svg" width="30" alt="timetable icon" /></div>
|
||||||
<div><h3 class="text--primary">12</h3></div>
|
<div>
|
||||||
|
<h3 class="text--primary">
|
||||||
|
{{ playerInfo.dispatcherStatsLastMonth.issuedTimetables?.count || 0 }}
|
||||||
|
</h3>
|
||||||
|
</div>
|
||||||
<div>
|
<div>
|
||||||
WYSTAWIONYCH <br />
|
WYSTAWIONYCH <br />
|
||||||
ROZKŁADÓW
|
ROZKŁADÓW
|
||||||
@@ -172,6 +281,7 @@ import { API, Td2API } from '../typings/api';
|
|||||||
import { humanizeDuration } from '../composables/time';
|
import { humanizeDuration } from '../composables/time';
|
||||||
import { useI18n } from 'vue-i18n';
|
import { useI18n } from 'vue-i18n';
|
||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
|
import { getCountPercentage } from '../utils/calcUtils';
|
||||||
|
|
||||||
type JournalEntryType = 'Timetable' | 'Dispatcher' | 'IssuedTimetable';
|
type JournalEntryType = 'Timetable' | 'Dispatcher' | 'IssuedTimetable';
|
||||||
|
|
||||||
@@ -185,6 +295,8 @@ const { t } = useI18n();
|
|||||||
const apiStore = useApiStore();
|
const apiStore = useApiStore();
|
||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
|
|
||||||
|
const playerName = ref('');
|
||||||
|
|
||||||
const playerInfo = ref<API.PlayerInfo.Data | null>(null);
|
const playerInfo = ref<API.PlayerInfo.Data | null>(null);
|
||||||
const playerJournal = ref<API.PlayerJournal.Data | null>(null);
|
const playerJournal = ref<API.PlayerJournal.Data | null>(null);
|
||||||
const playerTD2Info = ref<Td2API.UsersInfoByName.UserInfo | null>(null);
|
const playerTD2Info = ref<Td2API.UsersInfoByName.UserInfo | null>(null);
|
||||||
@@ -197,7 +309,7 @@ const activeFilterTypes = reactive<Record<JournalEntryType, boolean>>({
|
|||||||
|
|
||||||
watch(
|
watch(
|
||||||
computed(() => route.query.playerId),
|
computed(() => route.query.playerId),
|
||||||
(v) => {
|
() => {
|
||||||
fetchAllData();
|
fetchAllData();
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
@@ -207,7 +319,7 @@ onMounted(() => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
const combinedJournal = computed<JournalEntry[]>(() => {
|
const combinedJournal = computed<JournalEntry[]>(() => {
|
||||||
if (!playerJournal.value || !playerInfo.value) return [];
|
if (!playerJournal.value || !playerName.value) return [];
|
||||||
|
|
||||||
const list = [
|
const list = [
|
||||||
...playerJournal.value.timetables,
|
...playerJournal.value.timetables,
|
||||||
@@ -217,7 +329,7 @@ const combinedJournal = computed<JournalEntry[]>(() => {
|
|||||||
.reduce<JournalEntry[]>((acc, v) => {
|
.reduce<JournalEntry[]>((acc, v) => {
|
||||||
// Timetable or dispatcher type
|
// Timetable or dispatcher type
|
||||||
if ('trainNo' in v) {
|
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['Timetable']) return acc;
|
||||||
if (isIssued && !activeFilterTypes['IssuedTimetable']) return acc;
|
if (isIssued && !activeFilterTypes['IssuedTimetable']) return acc;
|
||||||
@@ -253,9 +365,16 @@ async function fetchAllData() {
|
|||||||
|
|
||||||
const playerInfoResponse = await fetchPlayerInfoData(playerId);
|
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);
|
const playerJournalResponse = await fetchPlayerJournal(playerId);
|
||||||
|
|
||||||
playerInfo.value = playerInfoResponse;
|
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;
|
return response.data;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(error);
|
console.error(error);
|
||||||
|
|||||||
Reference in New Issue
Block a user