Restrukturyzacja pobierania danych, zmiany w wyglądzie

This commit is contained in:
2020-09-10 21:25:10 +02:00
parent 5adb990361
commit 4ef90e655d
17 changed files with 553 additions and 225 deletions
+22 -17
View File
@@ -13,9 +13,9 @@
<Clock />
<div class="counter">
<img src="@/assets/icon-dispatcher.svg" alt="icon dispatcher" />
<span>{{onlineInfo.stationCount}}</span>
<span>{{data.stationCount}}</span>
<span>{{onlineInfo.trainCount}}</span>
<span>{{data.trainCount}}</span>
<img src="@/assets/icon-train.svg" alt="icon train" />
</div>
</span>
@@ -40,10 +40,10 @@
</footer>
<transition name="message-anim" mode="out-in">
<span :key="connState">
<div class="message loading" v-if="connState == 0">Pobieranie danych...</div>
<span :key="data.dataConnectionStatus">
<div class="message loading" v-if="data.dataConnectionStatus == 0">Pobieranie danych...</div>
<div class="message error" v-if="connState == 1">
<div class="message error" v-if="data.dataConnectionStatus == 1">
<img :src="ErrorIcon" alt="Error" />
Brak odpowiedzi ze strony serwera!
</div>
@@ -67,20 +67,25 @@ import Clock from "@/components/App/Clock.vue";
export default class App extends Vue {
ErrorIcon = require("@/assets/icon-error.svg");
@Getter("getOnlineInfo") onlineInfo;
@Getter("getConnectionState") connState;
@Action("synchronizeData") synchronizeData;
@Action("initStations") initStations;
@Getter("getAllData") data;
@Action("fetchOnlineStations") fetchStations;
@Action("fetchTrainsData") fetchTrainsData;
// @Getter("getOnlineInfo") onlineInfo;
// @Getter("getConnectionState") connState;
async mounted() {
this.initStations();
this.fetchTrainsData();
// @Action("initStations") initStations;
setInterval(this.fetchStations, 15000);
setInterval(this.fetchTrainsData, 10000);
// @Action("fetchOnlineStations") fetchStations;
// @Action("fetchTrainsData") fetchTrainsData;
mounted() {
this.synchronizeData();
// this.initStations();
// this.fetchTrainsData();
// setInterval(this.fetchStations, 15000);
// setInterval(this.fetchTrainsData, 45000);
}
}
</script>
@@ -161,10 +166,10 @@ export default class App extends Vue {
background: $bgCol;
color: white;
font-size: calc(1rem + 2.1vw);
font-size: calc(1.1rem + 2.1vw);
@include smallScreen() {
font-size: 2rem;
font-size: 2.5rem;
}
}
+1 -1
View File
@@ -34,7 +34,7 @@ export default Vue.extend({
align-items: center;
@include smallScreen() {
font-size: 0.65rem;
font-size: 0.95rem;
}
}
</style>
+2 -2
View File
@@ -165,8 +165,8 @@ export default class FilterCard extends Vue {
box-shadow: 0 0 15px 5px #474747;
@include smallScreen() {
width: 85vw;
font-size: calc(0.3em + 1vw);
width: 100%;
font-size: calc(0.7em + 1.1vw);
}
@include bigScreen {
+34 -8
View File
@@ -124,11 +124,12 @@
<div class="users-content">
<div
class="user"
v-for="train in stationInfo.trains"
v-for="train in stationInfo.stationTrains"
:key="train.trainNo + train.driverName"
:class="{'no-timetable': !hasTimetable(train.trainNo)}"
>
<a
:href="'https://rj.td2.info.pl/train#' + train.trainNo + ';eu'"
:href="`https://rj.td2.info.pl/train#${train.trainNo};eu`"
target="_blank"
rel="noopener noreferrer"
>
@@ -140,7 +141,7 @@
<span
class="user borderless"
v-if="!stationInfo.trains || stationInfo.trains.length == 0"
v-if="!stationInfo.stationTrains || stationInfo.stationTrains.length == 0"
>BRAK</span>
</div>
</div>
@@ -174,16 +175,19 @@
</span>
<span class="general-confirmed">
<span style="color: lime" v-if="timetable.confirmed">Odprawiony</span>
<span
style="color: gold"
v-if="timetable.stopped || (timetable.beginsHere && !timetable.confirmed)"
v-else-if="timetable.currentStationName == stationInfo.stationName"
>Na stacji</span>
<span style="color: #FF4646" v-else-if="timetable.stopped">Postój</span>
<span style="color: #aaa" v-else-if="!timetable.confirmed">W drodze</span>
<span
style="color: red"
v-else-if="(timetable.terminatesHere && timetable.confirmed)"
v-else-if="(timetable.terminatesHere && timetable.confimed)"
>Skończył bieg</span>
<span style="color: lime" v-else>Odprawiony</span>
</span>
</span>
@@ -220,6 +224,8 @@
<script lang="ts">
import { Component, Prop, Watch } from "vue-property-decorator";
import { Getter } from "vuex-class";
import styleMixin from "@/mixins/styleMixin";
import Station from "@/scripts/interfaces/Station";
@@ -228,8 +234,8 @@ import Station from "@/scripts/interfaces/Station";
export default class StationCard extends styleMixin {
@Prop() stationInfo!: Station;
@Prop() exit!: void;
@Getter('getTrainList') trains;
history: any[] = [];
cardMode: number = 0;
get computedExp(): string {
@@ -239,6 +245,7 @@ export default class StationCard extends styleMixin {
: `${this.stationInfo.dispatcherExp}`;
}
get computedScheduledTrains() {
return this.stationInfo.scheduledTrains.sort((a, b) => {
if (a.arrivalTime > b.arrivalTime) return 1;
@@ -248,6 +255,10 @@ export default class StationCard extends styleMixin {
})
}
hasTimetable(trainNo: number) {
return this.trains.find(train => train.timetableData && train.trainNo === trainNo);
}
timestampToTime(timestamp: number) {
return new Date(timestamp).toLocaleTimeString('pl-PL', {
hour: '2-digit',
@@ -286,10 +297,16 @@ export default class StationCard extends styleMixin {
&-exit {
z-index: 3;
display: flex;
align-items: center;
img {
margin: 0.1em 0.3em;
font-size: 1.6em;
margin: 0.1em 0.1em;
}
.schedule-icon {
font-size: 1.4em;
}
}
@@ -451,6 +468,15 @@ export default class StationCard extends styleMixin {
margin: 0;
padding: 0;
}
&.no-timetable {
border: 1px solid #aaa;
a {
color: #aaa;
pointer-events: none;
}
}
}
}
}
@@ -144,8 +144,6 @@
import Vue from "vue";
import { Component, Prop } from "vue-property-decorator";
import { Getter } from "vuex-class";
import Station from "@/scripts/interfaces/Station";
import Train from "@/scripts/interfaces/Train";
+26 -18
View File
@@ -77,7 +77,7 @@ export default class TrainStats extends Vue {
).toFixed(2);
const minMax = this.trains.reduce((acc, train) => {
if (train.noTimetable) return acc;
if (!train.timetableData) return acc;
acc[0] =
acc[0] === undefined || train.speed < acc[0] ? train.speed : acc[0];
@@ -94,21 +94,21 @@ export default class TrainStats extends Vue {
if (this.trains.length == 0) return { avg: "0", min: "0", max: "0" };
const avg = (
this.trains.reduce((acc, train) => acc + train.routeDistance, 0) /
this.trains.reduce((acc, train) => train.timetableData ? acc + train.timetableData.routeDistance : acc, 0) /
this.trains.length
).toFixed(2);
const minMax = this.trains.reduce((acc, train) => {
if (train.noTimetable) return acc;
if (!train.timetableData) return acc;
acc[0] =
acc[0] === undefined || train.routeDistance < acc[0]
? train.routeDistance
acc[0] === undefined || train.timetableData.routeDistance < acc[0]
? train.timetableData.routeDistance
: acc[0];
acc[1] =
acc[1] === undefined || train.routeDistance > acc[1]
? train.routeDistance
acc[1] === undefined || train.timetableData.routeDistance > acc[1]
? train.timetableData.routeDistance
: acc[1];
return acc;
}, [] as any);
@@ -118,11 +118,11 @@ export default class TrainStats extends Vue {
get categoryList(): Map<string, number> {
const map = this.trains.reduce((acc, train) => {
if (train.noTimetable || !train.category) return acc;
if (!train.timetableData || !train.timetableData.category) return acc;
acc.set(
train.category,
acc.get(train.category) ? acc.get(train.category) + 1 : 1
train.timetableData.category,
acc.get(train.timetableData.category) ? acc.get(train.timetableData.category) + 1 : 1
);
return acc;
@@ -133,7 +133,7 @@ export default class TrainStats extends Vue {
get locoList(): any[] {
const map = this.trains.reduce((acc, train) => {
if (train.noTimetable || !train.locoType) return acc;
if (!train.timetableData || !train.locoType) return acc;
acc.set(
train.locoType,
@@ -151,8 +151,8 @@ export default class TrainStats extends Vue {
}
get specialTrainCount(): [number, number] {
const twrList = this.trains.filter((train) => train.TWR);
const skrList = this.trains.filter((train) => train.SKR);
const twrList = this.trains.filter((train) => train.timetableData && train.timetableData.TWR);
const skrList = this.trains.filter((train) => train.timetableData && train.timetableData.SKR);
return [twrList.length, skrList.length];
}
@@ -177,18 +177,18 @@ export default class TrainStats extends Vue {
.train-stats {
padding: 0.3em 0;
font-size: 0.9em;
font-size: 1.1em;
position: relative;
}
.button {
font-size: 1.1em;
font-size: 1em;
padding: 0.5em;
}
.content {
font-size: 1.2em;
font-size: 1.1em;
color: #ddd;
}
@@ -199,7 +199,7 @@ export default class TrainStats extends Vue {
.stats-body {
position: absolute;
display: inline-block;
max-width: 800px;
max-width: 700px;
background: rgba(black, 0.85);
border-radius: 0 1em 1em 1em;
@@ -213,6 +213,8 @@ export default class TrainStats extends Vue {
}
.category {
font-size: 0.9em;
margin-right: 0.4em;
margin-bottom: 0.4em;
@@ -256,11 +258,17 @@ export default class TrainStats extends Vue {
@include smallScreen {
.button {
font-size: 0.9rem;
font-size: 0.85rem;
}
.stats-body {
display: block;
font-size: 0.9em;
// position: fixed;
// top: 0;
// left: 0;
width: 100%;
// height: 100%;
border-radius: 0 0 1em 1em;
}
+7 -10
View File
@@ -8,31 +8,31 @@
<div class="info-top">
<div class="info-category">
<span>
<strong>{{ train.category }}</strong>
<strong>{{ train.timetableData.category }}</strong>
{{ train.trainNo }} |
</span>
<span style=" color: gold;">{{ train.routeDistance }} km</span>
<span style=" color: gold;">{{ train.timetableData.routeDistance }} km</span>
</div>
<div class="info-warnings">
<span class="warning twr" v-if="train.TWR">TWR</span>
<span class="warning skr" v-if="train.SKR">SKR</span>
<span class="warning twr" v-if="train.timetableData.TWR">TWR</span>
<span class="warning skr" v-if="train.timetableData.SKR">SKR</span>
</div>
<div class="info-route">
<a :href="'https://rj.td2.info.pl/train#' + train.trainNo + ';eu'" target="_blank">
<strong>
{{
train.route && train.route.replace("|", " - ")
train.timetableData.route.replace("|", " - ")
}}
</strong>
</a>
</div>
<div class="info-stations">
<span v-if="train.followingStops.length > 2">
<span v-if="train.timetableData.followingStops.length > 2">
Przez:
<span v-html="generateStopList(train.followingStops)"></span>
<span v-html="generateStopList(train.timetableData.followingStops)"></span>
</span>
</div>
</div>
@@ -114,7 +114,6 @@
<script lang="ts">
import { Vue, Component, Prop } from "vue-property-decorator";
import { Getter } from "vuex-class";
const unknownTrainImage = require("@/assets/unknown.png");
@@ -125,8 +124,6 @@ import Station from "@/scripts/interfaces/Station";
export default class TrainTable extends Vue {
@Prop() readonly computedTrains!: Train[];
@Getter("getAllStations") stations!: Station[];
speedIcon: string = require("@/assets/icon-speed.svg");
massIcon: string = require("@/assets/icon-mass.svg");
lengthIcon: string = require("@/assets/icon-length.svg");
+2 -3
View File
@@ -1720,7 +1720,7 @@
"stationName": "Sól",
"stationURL": "https://td2.info.pl/scenerie/sol/",
"stationLines": "139",
"reqLevel": "0",
"reqLevel": "2",
"supportersOnly": "NIE",
"signalType": "współczesna",
"controlType": "SPK",
@@ -1784,8 +1784,7 @@
}
},
"default": false,
"nonPublic": false,
"unavailable": true
"nonPublic": false
},
{
"stationName": "Głęboszów",
+9 -3
View File
@@ -1,3 +1,5 @@
import Train from '@/scripts/interfaces/Train';
export default interface Station {
stationName: string;
stationHash: string;
@@ -23,20 +25,24 @@ export default interface Station {
online: boolean;
occupiedTo: string;
statusTimestamp: number;
stationTrains: Train[];
scheduledTrains: {
trainNo: number;
driverName: string;
category: string;
driverId: number;
currentStationName: string;
stopName: string;
stopType: string;
arrivalLine?: string;
arrivalTime: number;
arrivalDelay: number;
departureLine?: string;
departureTime: number;
beginsHere: boolean;
terminatesHere: boolean;
departureDelay: number;
confirmed: boolean;
stopped: boolean;
stopTime: number;
beginsHere: boolean;
terminatesHere: boolean;
}[];
}
+16
View File
@@ -0,0 +1,16 @@
export default interface Timetable {
trainNo: number;
driverName: string;
category: string;
stopName: string;
stopType: string;
arrivalTime: number;
arrivalDelay: number;
departureTime: number;
departureDelay: number;
confirmed: boolean;
stopped: boolean;
stopTime: number;
beginsHere: boolean;
terminatesHere: boolean;
}
+24 -26
View File
@@ -9,33 +9,31 @@ export default interface Train {
trainNo: number;
driverName: string;
currentStationName: string;
route: string | null;
timetableId: number | null;
category: string | null;
followingStops: {
stopName: string;
stopType: string;
arrivalLine?: string;
arrivalTime: number;
arrivalDelay: number;
departureLine?: string;
departureTime: number;
beginsHere: boolean;
terminatesHere: boolean;
departureDelay: number;
confirmed: boolean;
stopped: boolean;
stopTime: number;
arrivalScenery?: string;
departureScenery?: string;
}[];
TWR: boolean | null;
SKR: boolean | null;
noTimetable: boolean;
locoURL: string;
locoType: string;
routeDistance: number;
online: boolean;
timetableData?: {
timetableId: number;
category: string;
route: string;
followingStops: {
stopName: string;
stopType: string;
arrivalLine?: string;
arrivalTime: number;
arrivalDelay: number;
departureLine?: string;
departureTime: number;
beginsHere: boolean;
terminatesHere: boolean;
departureDelay: number;
confirmed: boolean;
stopped: boolean;
stopTime: number;
}[];
TWR: boolean;
SKR: boolean;
routeDistance: number;
};
}
+5 -6
View File
@@ -1,13 +1,12 @@
import Vue from "vue";
import Vuex from "vuex";
import Vue from 'vue';
import Vuex from 'vuex';
import Store from '@/store/store';
import StationsModule from "@/store/modules/stationsModule";
import TrainsModule from "@/store/modules/trainsModule";
Vue.use(Vuex);
const store = new Vuex.Store({
modules: {
StationsModule,
TrainsModule,
Store,
},
});
export default store;
+13 -41
View File
@@ -4,11 +4,9 @@ import axios from 'axios';
import data from '@/data/stations.json';
import Station from '@/scripts/interfaces/Station';
const stationsOnlineURL =
'https://api.td2.info.pl:9640/?method=getStationsOnline';
const stationsOnlineURL = 'https://api.td2.info.pl:9640/?method=getStationsOnline';
const trainsOnlineURL = 'https://api.td2.info.pl:9640/?method=getTrainsOnline';
const dispatchersOnlineURL =
'https://api.td2.info.pl:9640/?method=readFromSWDR&value=getDispatcherStatusList%3B1';
const dispatchersOnlineURL = 'https://api.td2.info.pl:9640/?method=readFromSWDR&value=getDispatcherStatusList%3B1';
enum ConnState {
Loading = 0,
@@ -17,8 +15,7 @@ enum ConnState {
}
interface TimetableResponseData {
stopPoints:
{
stopPoints: {
arrivalTime: string;
arrivalDelay: number;
departureTime: string;
@@ -57,10 +54,6 @@ let onlineTrainsData: {
};
}[];
const queryStations = axios.get(stationsOnlineURL);
const queryTrains = axios.get(trainsOnlineURL);
const queryDispatchers = axios.get(dispatchersOnlineURL);
const getStationLabel = (stationStatus: any) => {
if (!stationStatus) return 'NIEZALOGOWANY';
@@ -97,9 +90,7 @@ const getStationLabel = (stationStatus: any) => {
const getOpenSpawns = (spawnString: string) => {
if (!spawnString) return '';
return spawnString
.split(';')
.map(v => (v.split(',')[6] ? v.split(',')[6] : v.split(',')[0]));
return spawnString.split(';').map(v => (v.split(',')[6] ? v.split(',')[6] : v.split(',')[0]));
};
@Module
@@ -134,9 +125,7 @@ export default class StationsModule extends VuexModule {
@Mutation
private updateStations(updatedStations) {
this.stations = this.stations.reduce((acc, station) => {
const onlineStationData = updatedStations.find(
uStation => uStation.stationName === station.stationName
);
const onlineStationData = updatedStations.find(uStation => uStation.stationName === station.stationName);
if (!onlineStationData) {
acc.push({
@@ -152,7 +141,6 @@ export default class StationsModule extends VuexModule {
dispatcherId: 0,
occupiedTo: 'WOLNA',
statusTimestamp: 0,
scheduledTrains: [],
online: false,
});
@@ -174,9 +162,7 @@ export default class StationsModule extends VuexModule {
// Dodawanie do listy online potencjalnych scenerii niewpisanych do bazy
updatedStations.forEach((updated: any) => {
const alreadyInList: any = this.stations.find(
station => station.stationName === updated.stationName
);
const alreadyInList: any = this.stations.find(station => station.stationName === updated.stationName);
if (!alreadyInList) {
this.stations.push({
@@ -189,9 +175,7 @@ export default class StationsModule extends VuexModule {
this.stationCount = this.stations.filter(station => station.online).length;
this.trainCount = onlineTrainsData.filter(
train => train.isOnline && train.region === 'eu'
).length;
this.trainCount = onlineTrainsData.filter(train => train.isOnline && train.region === 'eu').length;
this.stationsConnectionState = ConnState.Connected;
}
@@ -233,11 +217,7 @@ export default class StationsModule extends VuexModule {
commit: 'updateStations',
})
async fetchOnlineStations() {
return await Promise.all([
axios.get(stationsOnlineURL),
axios.get(trainsOnlineURL),
axios.get(dispatchersOnlineURL),
])
return await Promise.all([axios.get(stationsOnlineURL), axios.get(trainsOnlineURL), axios.get(dispatchersOnlineURL)])
.then(async response => {
onlineStationsData = response[0].data.message;
onlineTrainsData = await response[1].data.message;
@@ -247,22 +227,13 @@ export default class StationsModule extends VuexModule {
onlineStationsData
.filter(station => station.region === 'eu' && station.isOnline)
.map(async station => {
const stationStatus = onlineDispatchersData.find(
status => status[0] == station.stationHash && status[1] == 'eu'
);
const stationStatus = onlineDispatchersData.find(status => status[0] == station.stationHash && status[1] == 'eu');
const statusLabel = getStationLabel(stationStatus);
const statusTimestamp = stationStatus ? stationStatus[3] : -1;
const trains = onlineTrainsData.filter(
train =>
train.region === 'eu' &&
train.isOnline &&
train.station.stationName === station.stationName
);
const trains = onlineTrainsData.filter(train => train.region === 'eu' && train.isOnline && train.station.stationName === station.stationName);
const stationData = data.find(
s => s.stationName === station.stationName
) || {
const stationData = data.find(s => s.stationName === station.stationName) || {
stationName: station.stationName,
stationURL: '',
};
@@ -285,8 +256,9 @@ export default class StationsModule extends VuexModule {
);
return updatedStations;
})
.catch(() => {
.catch(err => {
this.context.commit('setConnectionState', ConnState.Error);
console.log(err);
});
}
}
+9 -26
View File
@@ -65,13 +65,9 @@ interface TimetableData {
const getTimestamp = (date: string) => (date ? new Date(date).getTime() : 0);
const getTimetableURL = (trainNo: number) =>
`https://api.td2.info.pl:9640/?method=readFromSWDR&value=getTimetable%3B${trainNo}%3Beu`;
const getTimetableURL = (trainNo: number) => `https://api.td2.info.pl:9640/?method=readFromSWDR&value=getTimetable%3B${trainNo}%3Beu`;
const getLocoURL = (locoType: string) =>
`https://rj.td2.info.pl/dist/img/thumbnails/${
locoType.includes('EN') ? locoType + 'rb' : locoType
}.png`;
const getLocoURL = (locoType: string) => `https://rj.td2.info.pl/dist/img/thumbnails/${locoType.includes('EN') ? locoType + 'rb' : locoType}.png`;
@Module
export default class TrainsModule extends VuexModule {
@@ -93,17 +89,12 @@ export default class TrainsModule extends VuexModule {
return await Promise.all(
onlineTrainsData.map(async train => {
const timetableResponseData: TimetableResponseData | null = (
await axios.get(getTimetableURL(train.trainNo))
).data.message;
const timetableResponseData: TimetableResponseData | null = (await axios.get(getTimetableURL(train.trainNo))).data.message;
let timetableData: TimetableData | null = null;
if (timetableResponseData && timetableResponseData.trainInfo) {
const routeDistance: number =
timetableResponseData.stopPoints[
timetableResponseData.stopPoints.length - 1
].pointDistance;
const routeDistance: number = timetableResponseData.stopPoints[timetableResponseData.stopPoints.length - 1].pointDistance;
timetableData = {
...timetableResponseData.trainInfo,
@@ -112,18 +103,12 @@ export default class TrainsModule extends VuexModule {
};
}
const locoType = train.dataCon.split(';')
? train.dataCon.split(';')[0]
: train.dataCon;
const locoType = train.dataCon.split(';') ? train.dataCon.split(';')[0] : train.dataCon;
const followingStops = timetableResponseData?.stopPoints.reduce(
(acc, point) => {
const stopObj: any = {};
if (
!point.pointName.includes('Południowy') &&
(point.pointName.includes('strong') ||
point.pointName.includes('podg.'))
) {
if (!point.pointName.includes('Południowy') && (point.pointName.includes('strong') || point.pointName.includes('podg.'))) {
if (point.pointName.includes('strong')) {
stopObj.stopName = point.pointNameRAW;
@@ -137,13 +122,11 @@ export default class TrainsModule extends VuexModule {
stopObj.departureTime = getTimestamp(point.departureTime);
stopObj.arrivalDelay = point.arrivalDelay;
stopObj.departureDelay = point.departureDelay;
stopObj.beginsHere =
getTimestamp(point.arrivalTime) == 0 ? true : false;
stopObj.terminatesHere =
getTimestamp(point.departureTime) == 0 ? true : false;
stopObj.beginsHere = getTimestamp(point.arrivalTime) == 0 ? true : false;
stopObj.terminatesHere = getTimestamp(point.departureTime) == 0 ? true : false;
stopObj.confirmed = point.confirmed;
stopObj.stopped = point.stopped;
stopObj.stopTime = point.pointStopTime;
stopObj.currentStationName = train.station.stationName;
acc.push(stopObj);
}
+361
View File
@@ -0,0 +1,361 @@
import { Module, VuexModule, Mutation, Action } from 'vuex-module-decorators';
import axios from 'axios';
import JSONStationData from '@/data/stations.json';
import Station from '@/scripts/interfaces/Station';
import Train from '@/scripts/interfaces/Train';
import Timetable from '@/scripts/interfaces/Timetable';
enum Status {
Loading = 0,
Error = 1,
Loaded = 2,
}
const URLs = {
stations: 'https://api.td2.info.pl:9640/?method=getStationsOnline',
trains: 'https://api.td2.info.pl:9640/?method=getTrainsOnline',
dispatchers: 'https://api.td2.info.pl:9640/?method=readFromSWDR&value=getDispatcherStatusList%3B1',
};
const timetableURL = (trainNo: number) => `https://api.td2.info.pl:9640/?method=readFromSWDR&value=getTimetable%3B${trainNo}%3Beu`;
const getLocoURL = (locoType: string) => `https://rj.td2.info.pl/dist/img/thumbnails/${locoType.includes('EN') ? locoType + 'rb' : locoType}.png`;
const getStationLabel = (stationStatus: any) => {
if (!stationStatus) return 'NIEZALOGOWANY';
const statusCode = stationStatus[2];
const statusTimestamp = stationStatus[3];
switch (statusCode) {
case 0:
if (statusTimestamp - Date.now() > 21000000) return 'BEZ LIMITU';
return `DO ${new Date(statusTimestamp).toLocaleTimeString('en-US', {
hour12: false,
hour: '2-digit',
minute: '2-digit',
})}`;
case 1:
return 'Z/W';
case 2:
if (statusTimestamp == 0) return 'KOŃCZY';
break;
case 3:
return 'BRAK MIEJSCA';
default:
break;
}
return 'NIEDOSTĘPNY';
};
const getOpenSpawns = (spawnString: string) => (spawnString ? spawnString.split(';').map(v => (v.split(',')[6] ? v.split(',')[6] : v.split(',')[0])) : '');
const getTimestamp = (date: string) => (date ? new Date(date).getTime() : 0);
@Module
export default class Store extends VuexModule {
private trainCount: number = 0;
private stationCount: number = 0;
// private stationsConnectionStatus: Status = Status.Loading;
// private trainsConnectionStatus: Status = Status.Loading;
// private dataConnectionStatus: Status = Status.Loading;
private dataConnectionStatus: Status = Status.Loading;
private stationList: Station[] = [];
private trainList: Train[] = [];
//GETTERS
get getAllData() {
return {
stationList: this.stationList,
trainList: this.trainList,
trainCount: this.trainCount,
stationCount: this.stationCount,
dataConnectionStatus: this.dataConnectionStatus,
};
}
get getStationList() {
return this.stationList;
}
get getTrainList() {
return this.trainList;
}
//ACTIONS
@Action
async synchronizeData() {
this.context.commit('setJSONData');
this.context.dispatch('fetchOnlineData');
setInterval(() => this.context.dispatch('fetchOnlineData'), 20000);
}
@Action({ commit: 'updateTimetableData' })
async fetchTimetableData() {
return await Promise.all(
this.trainList.map(async train => {
const timetable = await (await axios.get(timetableURL(train.trainNo))).data.message;
const trainInfo = timetable.trainInfo;
let timetableData;
if (timetable && trainInfo) {
timetableData = {};
const followingStops = timetable.stopPoints.reduce((acc, point) => {
const stopObj: any = {};
if (!point.pointName.includes('Południowy') && (point.pointName.includes('strong') || point.pointName.includes('podg.'))) {
if (point.pointName.includes('strong')) {
stopObj.stopName = point.pointNameRAW;
stopObj.stopType = point.pointStopType;
} else {
stopObj.stopName = point.pointNameRAW.split(',')[0];
stopObj.stopType = 'podg.';
}
stopObj.arrivalTime = getTimestamp(point.arrivalTime);
stopObj.departureTime = getTimestamp(point.departureTime);
stopObj.arrivalDelay = point.arrivalDelay;
stopObj.departureDelay = point.departureDelay;
stopObj.beginsHere = getTimestamp(point.arrivalTime) == 0 ? true : false;
stopObj.terminatesHere = getTimestamp(point.departureTime) == 0 ? true : false;
stopObj.confirmed = point.confirmed;
stopObj.stopped = point.stopped;
acc.push(stopObj);
}
return acc;
}, []);
timetableData = {
trainNo: train.trainNo,
driverName: train.driverName,
driverId: train.driverId,
currentStationName: train.currentStationName,
timetableId: trainInfo.timetableId,
category: trainInfo.trainCategoryCode,
route: trainInfo.route,
TWR: trainInfo.twr,
SKR: trainInfo.skr,
routeDistance: timetable.stopPoints[timetable.stopPoints.length - 1].pointDistance,
followingStops,
};
}
return timetableData;
})
);
}
@Action
async fetchOnlineData() {
Promise.all([axios.get(URLs.stations), axios.get(URLs.trains), axios.get(URLs.dispatchers)])
.then(async response => {
const onlineStationsData = response[0].data.message;
const onlineTrainsData = await response[1].data.message;
const onlineDispatchersData = await response[2].data.message;
let updatedStationList = onlineStationsData.reduce((acc, station) => {
if (station.region !== 'eu' || !station.isOnline) return acc;
const stationStatus = onlineDispatchersData.find(status => status[0] == station.stationHash && status[1] == 'eu');
const statusLabel = getStationLabel(stationStatus);
const statusTimestamp = stationStatus ? stationStatus[3] : -1;
const stationTrains = onlineTrainsData.filter(train => train.region === 'eu' && train.isOnline && train.station.stationName === station.stationName);
acc.push({
stationName: station.stationName,
stationHash: station.stationHash,
maxUsers: station.maxUsers,
currentUsers: station.currentUsers,
spawnString: getOpenSpawns(station.spawnString),
dispatcherName: station.dispatcherName,
dispatcherRate: station.dispatcherRate,
dispatcherId: station.dispatcherId,
dispatcherExp: station.dispatcherExp,
occupiedTo: statusLabel,
stationTrains,
statusTimestamp,
});
return acc;
}, []);
let updatedTrainList = await Promise.all(
onlineTrainsData
.filter(train => train.region === 'eu')
.map(async train => {
const locoType = train.dataCon.split(';') ? train.dataCon.split(';')[0] : train.dataCon;
return {
trainNo: train.trainNo,
mass: train.dataMass,
length: train.dataLength,
speed: train.dataSpeed,
distance: train.dataDistance,
signal: train.dataSignal,
online: train.isOnline,
driverId: train.driverId,
driverName: train.driverName,
currentStationName: train.station.stationName,
connectedTrack: train.dataSceneryConnection,
locoType,
locoURL: getLocoURL(locoType),
};
})
);
this.context.commit('updateOnlineStations', updatedStationList);
this.context.commit('updateOnlineTrains', updatedTrainList);
this.context.dispatch('fetchTimetableData');
})
.catch(err => {
this.context.commit('setDataConnectionStatus', Status.Error);
});
}
//MUTATIONS
@Mutation
private setDataConnectionStatus(status: Status) {
this.dataConnectionStatus = status;
}
@Mutation setJSONData() {
this.stationList = JSONStationData.map(stationData => ({
stationProject: '',
spawnString: '',
stationHash: '',
maxUsers: 0,
currentUsers: 0,
dispatcherName: '',
dispatcherRate: 0,
dispatcherExp: -1,
dispatcherId: 0,
online: false,
occupiedTo: 'WOLNA',
statusTimestamp: 0,
stationTrains: [],
scheduledTrains: [],
...stationData,
}));
}
@Mutation
private updateOnlineStations(updatedStationList: any[]) {
this.stationList = this.stationList.reduce((acc, station) => {
const onlineStationData = updatedStationList.find(updatedStation => updatedStation.stationName === station.stationName);
if (!onlineStationData) {
acc.push({
...station,
stationProject: '',
spawnString: '',
stationHash: '',
maxUsers: 0,
currentUsers: 0,
dispatcherName: '',
dispatcherRate: 0,
dispatcherExp: -1,
dispatcherId: 0,
occupiedTo: 'WOLNA',
statusTimestamp: 0,
online: false,
});
} else
acc.push({
...station,
...onlineStationData,
online: true,
});
return acc;
}, [] as Station[]);
// Dodawanie do listy online potencjalnych scenerii niewpisanych do bazy
updatedStationList.forEach(updatedStation => {
const alreadyInList: any = this.stationList.find(station => station.stationName === updatedStation.stationName);
if (!alreadyInList) {
this.stationList.push({
...updatedStation,
online: true,
reqLevel: '-1',
});
}
});
this.stationCount = this.stationList.filter(station => station.online).length;
this.dataConnectionStatus = Status.Loaded;
}
@Mutation
private updateOnlineTrains(updatedTrainList) {
this.trainList =
this.trainList.length == 0
? updatedTrainList
: this.trainList.reduce((acc, train) => {
const onlineTrainData = updatedTrainList.find(updatedTrain => train.trainNo === updatedTrain.trainNo);
if (onlineTrainData) acc.push({ ...train, ...onlineTrainData });
return acc;
}, [] as Train[]);
this.trainCount = this.trainList.filter(train => train.online).length;
this.dataConnectionStatus = Status.Loaded;
}
@Mutation
private updateTimetableData(timetableList: any[]) {
this.stationList = this.stationList.map(station => {
const scheduledTrains = timetableList.reduce((acc, timetableData: any) => {
const scheduledIndex = timetableData
? timetableData.followingStops.findIndex(
(stop: any) =>
station.stationName.toLowerCase().includes(stop.stopName) ||
station.stationName.toLowerCase().includes(stop.stopName.toLowerCase().split(',')[0]) ||
(station.stationName.toLowerCase().includes(stop.stopName.toLowerCase().split(' ')[0]) && station.stationName.toLowerCase().includes('lcs'))
)
: -1;
if (scheduledIndex >= 0) {
const scheduledData = timetableData.followingStops[scheduledIndex];
acc.push({
...scheduledData,
trainNo: timetableData.trainNo,
driverName: timetableData.driverName,
driverId: timetableData.driverId,
currentStationName: timetableData.currentStationName,
});
}
return acc;
}, []);
return { ...station, scheduledTrains };
});
this.trainList = this.trainList.reduce((acc, train) => {
const timetableData = timetableList.find(data => data && data.trainNo === train.trainNo);
if (timetableData) acc.push({ ...train, timetableData });
return acc;
}, [] as Train[]);
}
}
+16 -54
View File
@@ -93,8 +93,7 @@ export default class StationsView extends Vue {
inputs = inputData;
@Getter("getStationList") stations!: Station[];
@Getter("trainsDataList") trains!: Train[];
@Getter("getStationList") stationList!: Station[];
toggleCardsState(name: string): void {
if (name == "filter") {
@@ -120,52 +119,14 @@ export default class StationsView extends Vue {
this.filters = { ...filterInitStates };
}
get scheduledTrains() {
const reducedList = this.stations.reduce((acc, station) => {
if (!acc[station.stationName]) acc[station.stationName] = [];
this.trains
.filter((train) => !train.noTimetable)
.forEach((train) => {
const foundIndex = train.followingStops.findIndex(
(stop) =>
(station.stationName
.toLowerCase()
.includes(stop.stopName) ||
station.stationName
.toLowerCase()
.includes(stop.stopName.toLowerCase().split(",")[0]) ||
(station.stationName
.toLowerCase()
.includes(stop.stopName.toLowerCase().split(" ")[0]) &&
station.stationName.toLowerCase().includes("lcs"))) &&
!acc[station.stationName].find((t) => t.trainNo === train.trainNo)
);
if (foundIndex < 0) return acc;
const foundStop = train.followingStops[foundIndex];
acc[station.stationName].push({
trainNo: train.trainNo,
driverName: train.driverName,
driverId: train.driverId,
category: train.category,
...foundStop
});
});
return acc;
}, {});
return reducedList;
}
get computedStations() {
const dir: number = this.sorterActive.dir;
const scheduledTrainList = this.scheduledTrains;
// const scheduledTrainList = this.scheduledTrains;
return this.stations
return this.stationList
.filter((station) => {
if (!station.reqLevel || station.reqLevel == "-1") return true;
@@ -270,21 +231,15 @@ export default class StationsView extends Vue {
if (a.stationName.toLowerCase() >= b.stationName.toLowerCase()) return dir;
return -dir;
})
.map((station) => ({
...station,
scheduledTrains: scheduledTrainList[station.stationName],
}));
}
mounted() {
const storage = window.localStorage;
console.log(storage.getItem(this.STORAGE_KEY));
if (storage.getItem(this.STORAGE_KEY) !== "true") return;
this.inputs.options.forEach(option => {
const value = storage.getItem(option.name) === "true" ? true : false;
console.log(option.name, value);
this.changeFilterValue({ name: option.name, value: value ? 0 : 1 });
@@ -298,6 +253,13 @@ export default class StationsView extends Vue {
this.changeFilterValue({ name: slider.name, value });
slider.value = value;
})
window.addEventListener('keydown', (e: KeyboardEvent) => {
if (e.keyCode == 27 && this.focusedStationName != "") {
this.focusedStationName = "";
}
})
}
closeCard() {
@@ -322,6 +284,8 @@ export default class StationsView extends Vue {
padding: 1rem 0;
min-height: 100%;
font-size: calc(0.6rem + 0.9vw);
position: relative;
}
@@ -342,8 +306,6 @@ export default class StationsView extends Vue {
}
.options {
font-size: calc(0.6rem + 0.9vw);
&-actions {
display: flex;
}
@@ -357,7 +319,7 @@ export default class StationsView extends Vue {
border: none;
color: #e0e0e0;
font-size: 0.75em;
font-size: 0.65em;
padding: 0.3em;
@@ -395,7 +357,7 @@ export default class StationsView extends Vue {
}
.action-btn {
font-size: 0.8rem;
font-size: 0.75rem;
}
}
+6 -8
View File
@@ -40,10 +40,7 @@ import axios from "axios";
},
})
export default class TrainsView extends Vue {
@Getter("trainsDataList") trains!: Train[];
@Action("fetchTrainsData") fetchTrainsData;
@Getter("getTrainList") trains!: Train[];
@Prop() readonly passedSearchedTrain!: string;
sorterActive: { id: string; dir: number } = { id: "timetable", dir: 1 };
@@ -62,12 +59,11 @@ export default class TrainsView extends Vue {
this.sorterActive = sorter;
}
get computedTrains() {
return this.trains
.filter(
(train) =>
!train.noTimetable &&
train.timetableData &&
(this.searchedTrain.length > 0
? train.trainNo.toString().includes(this.searchedTrain)
: true) &&
@@ -85,7 +81,9 @@ export default class TrainsView extends Vue {
break;
case "distance":
if (a.routeDistance > b.routeDistance) return this.sorterActive.dir;
if (!a.timetableData || !b.timetableData) return 0;
if (a.timetableData.routeDistance > b.timetableData.routeDistance) return this.sorterActive.dir;
else return -this.sorterActive.dir;
break;
@@ -128,7 +126,7 @@ export default class TrainsView extends Vue {
padding: 0 0.5rem;
font-size: calc(0.3rem + 0.4vw);
font-size: calc(0.4rem + 0.4vw);
}
.options-wrapper {