feature: stations stats

This commit is contained in:
2024-05-05 13:34:43 +02:00
parent f29c160000
commit 405aab96bd
8 changed files with 178 additions and 94 deletions
-11
View File
@@ -29,11 +29,6 @@
<img src="/images/icon-dispatcher.svg" alt="icon dispatcher" />
<span class="text--primary">{{ onlineDispatchersCount }}</span>
<!-- <span class="g-tooltip">
<b class="text--primary">{{ factorU }}U</b>
<div class="content">Test</div>
</span> -->
<span class="text--grayed"> / </span>
<span class="text--primary">{{ onlineTrainsCount }}</span>
<img src="/images/icon-train.svg" alt="icon train" />
@@ -103,12 +98,6 @@ export default defineComponent({
return this.store.activeSceneryList.filter(
(scenery) => scenery.region == this.store.region.id && scenery.dispatcherId != -1
).length;
},
factorU() {
return this.onlineDispatchersCount == 0
? '-'
: (this.onlineTrainsCount / this.onlineDispatchersCount).toFixed(2);
}
},
components: { StatusIndicator, Clock, RegionDropdown }
@@ -405,13 +405,6 @@ export default defineComponent({
width: 100%;
}
.g-tooltip > .content {
z-index: 100;
color: white;
left: 110%;
}
img {
width: 1.1em;
}
+1 -1
View File
@@ -390,7 +390,7 @@ export default defineComponent({
$rowCol: #424242;
.station_table {
height: 90vh;
height: calc(100vh - 150px);
min-height: 550px;
overflow: auto;
font-weight: 500;
@@ -0,0 +1,150 @@
<template>
<div class="stations-stats">
<div class="separator" />
<div>
Współczynnik Ugla
<a
href="https://td2.info.pl/dyskusje/wspolczynnik-ugla-czy-to-ma-sens/msg81011/#msg81011"
target="_blank"
data-tooltip="(?) Współczynnik ruchu na serwerze (liczba maszynistów online dzielona na liczbę dyżurnych ruchu)"
>(?)</a
>:
<b :style="calculateFactorStyle()">
{{ uFactor.toFixed(2) }}
</b>
| Średnia liczba rozkładów jazdy na dyżurnego:
<b>{{ avgTimetableCount.toFixed(2) }}</b>
</div>
<div>
Dostępne szlaki 1-torowe:
<b>{{ trackCount.oneWayElectric }}</b> (zelektr.) /
<b>{{ trackCount.oneWayOther }}</b> (niezelektr.) | Dostępne szlaki 2-torowe:
<b>{{ trackCount.twoWayElectric }}</b> (zelektr.) /
<b>{{ trackCount.twoWayOther }}</b> (niezelektr.) | Otwarte spawny:
<b>{{ spawnCount.passenger }}</b> - PAS / <b>{{ spawnCount.freight }}</b> - TOW /
<b>{{ spawnCount.loco }}</b> - LUZ / <b>{{ spawnCount.all }}</b> - ALL
</div>
</div>
</template>
<script lang="ts">
import { defineComponent } from 'vue';
import { useMainStore } from '../../store/mainStore';
export default defineComponent({
data() {
return {
mainStore: useMainStore()
};
},
methods: {
calculateFactorStyle() {
if (this.uFactor == 0) return '';
const norm = this.uFactor == 0 ? 1 : Math.max(Math.min(1 / this.uFactor / 2, 1), 0);
const lerp = 120 * norm;
return `color: hsl(${lerp}, 100%, 60%)`;
}
},
computed: {
uFactor() {
const activeDispatchers = this.mainStore.activeSceneryList.filter(
(scenery) => scenery.region == this.mainStore.region.id && scenery.dispatcherId != -1
);
const activeTrains = this.mainStore.trainList.filter(
(train) => train.region == this.mainStore.region.id
);
return activeDispatchers.length != 0 ? activeTrains.length / activeDispatchers.length : 0;
},
avgTimetableCount() {
const scheduledTrainsTotal = this.mainStore.activeSceneryList.reduce<number>((acc, sc) => {
if (sc.region != this.mainStore.region.id) return acc;
acc += sc.scheduledTrainCount.all;
return acc;
}, 0);
return this.mainStore.activeSceneryList.length != 0
? scheduledTrainsTotal / this.mainStore.activeSceneryList.length
: 0;
},
trackCount() {
return this.mainStore.allStationInfo
.filter(
(st) =>
st.onlineInfo?.dispatcherId != -1 &&
st.onlineInfo?.region == this.mainStore.region.id &&
st.generalInfo?.routes
)
.reduce(
(acc, st) => {
[...st.generalInfo!.routes.single, ...st.generalInfo!.routes.double].forEach((r) => {
if (r.isInternal) return;
const keyName: keyof typeof acc = `${r.routeTracks == 2 ? 'twoWay' : 'oneWay'}${r.isElectric ? 'Electric' : 'Other'}`;
acc[keyName] += 1;
});
return acc;
},
{ oneWayElectric: 0, oneWayOther: 0, twoWayElectric: 0, twoWayOther: 0 }
);
},
spawnCount() {
return this.mainStore.activeSceneryList.reduce(
(acc, scenery) => {
scenery.spawns.forEach((spawn) => {
if (/EZT|POS|OSOB/i.test(spawn.spawnName)) acc['passenger'] += 1;
if (/TOW/i.test(spawn.spawnName)) acc['freight'] += 1;
if (/LUZ/i.test(spawn.spawnName)) acc['loco'] += 1;
if (/ALL/i.test(spawn.spawnName)) acc['all'] += 1;
});
return acc;
},
{ passenger: 0, freight: 0, loco: 0, all: 0 }
);
}
}
});
</script>
<style lang="scss" scoped>
.separator {
width: 100%;
height: 2px;
margin: 0.5em 0;
background-color: #ddd;
}
.stations-stats {
text-align: center;
color: #ddd;
}
[data-factor-low='true'] {
color: #ddd;
}
[data-factor-mediocre='true'] {
color: lightgreen;
}
[data-factor-high='true'] {
color: greenyellow;
}
[data-factor-highest='true'] {
color: rgb(22, 245, 22);
}
</style>
+1 -4
View File
@@ -32,10 +32,7 @@ export const useMainStore = defineStore('mainStore', {
modalLastClickedTarget: null,
mousePos: { x: 0, y: 0 },
popUpData: { key: null, content: '' },
stations: [] as Station[],
trainsOnline: [] as Train[]
popUpData: { key: null, content: '' }
}) as MainStoreState,
getters: {
-2
View File
@@ -17,8 +17,6 @@ export interface MainStoreState {
modalLastClickedTarget: EventTarget | null;
mousePos: { x: number; y: number };
popUpData: { key: PopUpType | null; content: string };
stations: Station[];
trainsOnline: Train[];
}
export interface StationJSONData {
+20
View File
@@ -298,3 +298,23 @@ a.a-button {
}
}
}
// Basic tooltip
[data-tooltip]:hover::after,
[data-tooltip]:focus::after {
position: absolute;
transform: translate(10px, -50%);
content: attr(data-tooltip);
color: white;
background-color: #171717;
border-radius: 0.5em;
padding: 0.5em;
margin: 0 0.25em;
max-width: 300px;
z-index: 100;
}
[data-tooltip] {
cursor: help;
}
+6 -69
View File
@@ -22,13 +22,7 @@
<Donation :isModalOpen="isDonationModalOpen" @toggleModal="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>
<StationsStats />
</div>
</section>
</template>
@@ -40,56 +34,28 @@ import StationFilterCard from '../components/StationsView/StationFilterCard.vue'
import { useStationFiltersStore } from '../store/stationFiltersStore';
import { useMainStore } from '../store/mainStore';
import Donation from '../components/Global/Donation.vue';
import StationsStats from '../components/StationsView/StationsStats.vue';
export default defineComponent({
components: {
StationTable,
StationFilterCard,
StationsStats,
Donation
},
data: () => ({
filterCardOpen: false,
modalHidden: true,
STORAGE_KEY: 'options_saved',
focusedStationName: '',
filterStore: useStationFiltersStore(),
store: useMainStore(),
isDonationModalOpen: false,
isDonationModalOpen: false
filterStore: useStationFiltersStore(),
store: useMainStore()
}),
mounted() {
this.filterStore.setupFilters();
},
computed: {
avgTimetableCount() {
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 [];
}
},
methods: {
toggleDonationModal(value: boolean) {
this.isDonationModalOpen = value;
@@ -102,30 +68,6 @@ export default defineComponent({
@import '../styles/variables.scss';
@import '../styles/responsive.scss';
@keyframes blinkAnim {
0%,
100% {
opacity: 1;
}
50% {
opacity: 0;
}
}
.indicator-anim {
&-enter-active,
&-leave-active {
transition: all 0.25s ease-in-out;
}
&-enter,
&-leave-to {
transform: translateY(100%);
opacity: 0;
}
}
.stations-view {
position: relative;
display: flex;
@@ -148,11 +90,6 @@ export default defineComponent({
margin-bottom: 0.5em;
}
.stations-stats {
text-align: center;
color: #ccc;
}
button.btn-donation {
$btnColor: #254069;