Merge pull request #58 from 0hAodha/insightsRefresh

Fix insights page refresh
This commit is contained in:
2023-03-19 15:08:06 +00:00
committed by GitHub
4 changed files with 318 additions and 61 deletions

View File

@ -10,7 +10,7 @@
<li><p>Darts: {{ this.insights["numDarts"] }}</p></li>
</ul>
</div>
<div id="trainTotalChart">
<div v-if="readyToRender" id="trainTotalChart">
<pieChart id="trainPie" />
</div>
</div>
@ -19,13 +19,10 @@
<p>Number of actively running trains: {{ this.insights["numRunningTrains"] }}</p>
<p>Percentage late: {{ this.insights["percentageLate"] }}%</p>
<p>Percentage early or ontime: {{ this.insights["percentageNotLate"] }}%</p>
<div id="statsDiv">
<div v-if="readyToRender" id="statsDiv">
<BarChart id="lateGraph" />
</div>
<p v-if="this.latestTrain['TrainCode']">Latest train: {{ this.latestTrain["TrainCode"][0] }}, {{ this.insights["latestTime"] }} mins late</p>
<p v-if="this.earliestTrain['TrainCode']">Earliest train: {{ this.earliestTrain["TrainCode"][0] }}, {{ this.insights["earliestTime"] * -1 }} mins early</p>
<h1 style="padding-left: 10px;">Station Insights</h1>
<div id="stationTotal">
<div id="stationTotalText">
@ -36,7 +33,7 @@
</ul>
</div>
<div id="stationTotalChart">
<pieChart id="stationPie" />
<pieChart v-if="readyToRender" id="stationPie" />
</div>
</div>
</div>
@ -72,12 +69,15 @@
</template>
<script>
import {store} from '../store/store'
import { store } from '../store/store'
import { getFunctions, httpsCallable, connectFunctionsEmulator } from "firebase/functions";
import { createToast } from 'mosha-vue-toastify';
import 'mosha-vue-toastify/dist/style.css'
import Navbar from '../components/Navbar.vue'
import BarChart from '../components/BarChart.vue'
import pieChart from '../components/pieChart.vue'
import app from '../api/firebase';
export default {
name: "InsightsPage",
@ -90,19 +90,25 @@ export default {
})
}
let loader = this.$loading.show({
loader: 'dots',
container: this.$refs.container,
canCancel: false
});
return {
insights: {},
latestTrain: {},
earliestTrain: {},
rawData: {},
orderedTrains: [],
topEarliestLatest: [],
showTopEarliestLatest: false,
readyToRender: false,
store,
toastMessage: "",
toastBackground: "",
toast
toast,
loader
}
},
@ -113,16 +119,23 @@ export default {
},
created() {
// check if no insight data exists
if (!store.orderedTrains.length > 0) {
this.showToast("Error fetching live data", "red")
let host = window.location.hostname
if (host === '127.0.0.1' || host === 'localhost') {
this.postTrainAndStationData();
}
else {
this.getTrainAndStationData();
}
}
else {
this.insights = store.insights
this.latestTrain = store.latestTrain
this.earliestTrain = store.earliestTrain
this.rawData = store.rawData
this.orderedTrains = store.orderedTrains
this.topEarliestLatest = this.orderedTrains.slice(0, 3).concat(this.orderedTrains.slice(-3))
this.loader.hide();
this.readyToRender = true
}
},
@ -131,6 +144,108 @@ export default {
this.toastMessage = message
this.toastBackground = backgroundColour
this.toast()
},
postTrainAndStationData() {
const functions = getFunctions(app);
let host = window.location.hostname
if (host === '127.0.0.1' || host === 'localhost') {
connectFunctionsEmulator(functions, host, 5001);
}
const postTrainData = httpsCallable(functions, 'postLiveTrainData');
postTrainData().then(() => {
const postStationData = httpsCallable(functions, 'postStationData');
postStationData().then(() => {
this.getTrainAndStationData()
})
})
.catch((error) => {
this.showToast(error.message, "red")
})
},
// condensed version
getTrainAndStationData() {
const functions = getFunctions(app);
let host = window.location.hostname
if (host === '127.0.0.1' || host == 'localhost') {
connectFunctionsEmulator(functions, host, 5001);
}
const getTrainData = httpsCallable(functions, 'getLiveTrainData');
getTrainData().then((response) => {
try {
if (!response.data) throw new Error("Error fetching live train data from the database")
var unorderedTrains = [];
var insights = {
"totalNumTrains": 0,
"numRunningTrains": 0,
"numLateRunningTrains": 0,
"numTrains": 0,
"numDarts": 0,
"totalNumStations": 0,
"numTrainStations": 0,
"numDartStations": 0
};
for (var i=0; i<response.data.length; i++) {
let train = response.data[i];
insights["totalNumTrains"] += 1
if (train["TrainType"][0] == "Train") insights["numTrains"] += 1;
else if (train["TrainType"][0] == "DART") insights["numDarts"] += 1;
train["PublicMessage"][0] = train["PublicMessage"][0].replace(/\\n/g, ". ");
let publicMessage = train["PublicMessage"][0];
// check if the train is running
if (train["TrainStatus"][0] == "R") {
insights["numRunningTrains"] += 1;
let startTimeStr = publicMessage.indexOf("(");
let timeEnd = publicMessage.indexOf(" ", startTimeStr+1);
let num = parseInt(publicMessage.substring(startTimeStr+1, timeEnd))
unorderedTrains.push({"time": num, "jsonIndex": i})
// check if the train is late
if (publicMessage[startTimeStr+1] != "-" && publicMessage[startTimeStr+1] != "0") {
insights["numLateRunningTrains"] += 1;
}
}
}
insights["percentageLate"] = ((insights["numLateRunningTrains"] / insights["numRunningTrains"]) * 100).toFixed(2);
insights["percentageNotLate"] = (100 - insights["percentageLate"]).toFixed(2);
store.setRawData(response.data);
store.setOrderedTrains(unorderedTrains);
const getStationData = httpsCallable(functions, 'getStationData');
getStationData().then((response) => {
if (!response.data) throw new Error("Error fetching station from the database");
for (var i=0; i<response.data.length; i++) {
let station = response.data[i];
insights["totalNumStations"] += 1
if (station["StationType"][0] == "DART") insights["numDartStations"] += 1;
else if (station["StationType"][0] == "Train") insights["numTrainStations"] += 1;
}
store.setInsights(insights);
this.insights = insights
this.rawData = store.rawData
this.orderedTrains = store.orderedTrains
this.topEarliestLatest = this.orderedTrains.slice(0, 3).concat(this.orderedTrains.slice(-3))
this.loader.hide();
this.readyToRender = true
})
}
catch {
this.loader.hide()
this.showToast(error.message, "red")
}
})
.catch((error) => {
this.loader.hide()
this.showToast("Error fetching live data", "red")
})
}
}
}

View File

@ -129,6 +129,12 @@ export default {
})
}
let loader = this.$loading.show({
loader: 'dots',
container: this.$refs.container,
canCancel: false
});
return {
center: fromLonLat([-7.5029786, 53.4494762]),
projection: 'EPSG:3857',
@ -149,6 +155,7 @@ export default {
toastMessage: "",
toastBackground: "",
toast,
loader,
showMainlandStations: true,
showDARTStations: true,
@ -223,7 +230,6 @@ export default {
})
.catch((error) => {
this.readyToDisplayMap = true
console.log(error.message)
})
},
@ -335,16 +341,13 @@ export default {
if (host === '127.0.0.1' || host == 'localhost') {
connectFunctionsEmulator(functions, host, 5001);
}
const getTrainData = httpsCallable(functions, 'getLiveTrainData');
let loader = this.$loading.show({
loader: 'dots',
container: this.$refs.container,
canCancel: false
});
getTrainData().then((response) => {
try {
if (!response.data) throw new Error("Error fetching live train data from the database")
var unorderedTrains = [];
var currentMessages = [];
var insights = {
"totalNumTrains": 0,
"numRunningTrains": 0,
@ -356,13 +359,6 @@ export default {
"numDartStations": 0
};
var unorderedTrains = [];
var currentMessages = [];
var latest = null;
var earliest = null;
var currLatestTime = null;
var currEarliestTime = null;
// create an array of coordinates and hashmap with the key-values {index: JSON obj}
for (var i=0; i<response.data.length; i++) {
let train = response.data[i];
@ -370,7 +366,7 @@ export default {
this.trainCoordinates[i] = fromLonLat([train["TrainLongitude"][0], train["TrainLatitude"][0]])
insights["totalNumTrains"] += 1
// filling showTrains with the default value - true
// fill showTrains with the default value - true
this.showTrains[i] = true;
if (train["TrainType"][0] == "Train") insights["numTrains"] += 1;
else if (train["TrainType"][0] == "DART") insights["numDarts"] += 1;
@ -391,35 +387,15 @@ export default {
// check if the train is late
if (publicMessage[startTimeStr+1] != "-" && publicMessage[startTimeStr+1] != "0") {
insights["numLateRunningTrains"] += 1;
if (!latest) latest = train;
// check for a new latest train
if (num > currLatestTime) {
latest = train;
currLatestTime = num;
}
}
// train is early or ontime
else {
if (!earliest) earliest = train;
// check for a new earliest train (early trains are -x mins late)
if (num < currEarliestTime) {
earliest = train;
currEarliestTime = num;
}
}
}
}
insights["percentageLate"] = ((insights["numLateRunningTrains"] / insights["numRunningTrains"]) * 100).toFixed(2);
insights["percentageNotLate"] = (100 - insights["percentageLate"]).toFixed(2);
insights["latestTime"] = currLatestTime;
insights["earliestTime"] = currEarliestTime;
this.publicMessages = currentMessages;
// assign the results to the Vue Store
store.setEarliestTrain(earliest);
store.setLatestTrain(latest);
store.setRawData(response.data);
store.setOrderedTrains(unorderedTrains);
@ -440,18 +416,18 @@ export default {
}
store.setInsights(insights);
loader.hide();
this.loader.hide()
// request the user's preferences
this.getPreferences()
})
}
catch (error) {
loader.hide()
this.loader.hide()
this.showToast(error.message, "red")
}
})
.catch((error) => {
loader.hide()
this.loader.hide()
this.showToast("Error fetching live data", "red")
})
},

171
src/store/new.js Normal file
View File

@ -0,0 +1,171 @@
import { reactive } from 'vue'
import { fromLonLat } from 'ol/proj.js';
import { getFunctions, httpsCallable, connectFunctionsEmulator } from "firebase/functions";
import app from '../api/firebase';
export const store = reactive({
// map and insights data
insights: {},
latestTrain: {},
earliestTrain: {},
orderedTrains: [],
selectedTrain: {},
selectedStation: {},
allTrainsJSON: {},
// side bar
displaySelectedTrain: false,
displayedSelectedStation: false,
// login status
loggedIn: false,
isWaitingForLoginStatus: true,
setOrderedTrains(unorderedTrains) {
// sort in ascending order
unorderedTrains.sort((a, b) => {
return a.time - b.time
})
this.orderedTrains = unorderedTrains
},
// method to populate the database for local testing
postTrainAndStationData(host) {
const functions = getFunctions(app);
if (host === '127.0.0.1' || host === 'localhost') {
connectFunctionsEmulator(functions, host, 5001);
}
const postTrainData = httpsCallable(functions, 'postLiveTrainData');
postTrainData().then(() => {
const postStationData = httpsCallable(functions, 'postStationData');
postStationData().then(() => {
this.getTrainAndStationData(host)
})
})
.catch((error) => {
console.log(error.message)
//this.showToast(error.message, "red")
})
},
// method to fetch live train and station data from Firestore
getTrainAndStationData(host) {
const functions = getFunctions(app);
if (host === '127.0.0.1' || host == 'localhost') {
connectFunctionsEmulator(functions, host, 5001);
}
const getTrainData = httpsCallable(functions, 'getLiveTrainData');
getTrainData().then((response) => {
try {
if (!response.data) throw new Error("Error fetching live train data from the database")
var insights = {
"totalNumTrains": 0,
"numRunningTrains": 0,
"numLateRunningTrains": 0,
"numTrains": 0,
"numDarts": 0,
"totalNumStations": 0,
"numTrainStations": 0,
"numDartStations": 0
};
var unorderedTrains = [];
var currentMessages = [];
var latest = null;
var earliest = null;
var currLatestTime = null;
var currEarliestTime = null;
for (var i=0; i<response.data.length; i++) {
let train = response.data[i];
this.allTrains[i] = train;
this.trainCoordinates[i] = fromLonLat([train["TrainLongitude"][0], train["TrainLatitude"][0]])
insights["totalNumTrains"] += 1
// fill showTrains with the default value - true
this.showTrains[i] = true;
if (train["TrainType"][0] == "Train") insights["numTrains"] += 1;
else if (train["TrainType"][0] == "DART") insights["numDarts"] += 1;
// filter out \n in public messages
train["PublicMessage"][0] = train["PublicMessage"][0].replace(/\\n/g, ". ");
let publicMessage = train["PublicMessage"][0];
currentMessages.push(publicMessage);
// check if the train is running
if (train["TrainStatus"][0] == "R") {
insights["numRunningTrains"] += 1;
let startTimeStr = publicMessage.indexOf("(");
let timeEnd = publicMessage.indexOf(" ", startTimeStr+1);
let num = parseInt(publicMessage.substring(startTimeStr+1, timeEnd))
unorderedTrains.push({"time": num, "jsonIndex": i})
// check if the train is late
if (publicMessage[startTimeStr+1] != "-" && publicMessage[startTimeStr+1] != "0") {
insights["numLateRunningTrains"] += 1;
if (!latest) latest = train;
// check for a new latest train
if (num > currLatestTime) {
latest = train;
currLatestTime = num;
}
}
// train is early or ontime
else {
if (!earliest) earliest = train;
// check for a new earliest train (early trains are -x mins late)
if (num < currEarliestTime) {
earliest = train;
currEarliestTime = num;
}
}
}
}
// assign results after looping through JSON
insights["percentageLate"] = ((insights["numLateRunningTrains"] / insights["numRunningTrains"]) * 100).toFixed(2);
insights["percentageNotLate"] = (100 - insights["percentageLate"]).toFixed(2);
insights["latestTime"] = currLatestTime;
insights["earliestTime"] = currEarliestTime;
this.publicMessages = currentMessages;
// assign the results to the Vue Store
store.setEarliestTrain(earliest);
store.setLatestTrain(latest);
store.setRawData(response.data);
store.setOrderedTrains(unorderedTrains);
const getStationData = httpsCallable(functions, 'getStationData');
getStationData().then((response) => {
if (!response.data) throw new Error("Error fetching station from the database");
for (var i=0; i<response.data.length; i++) {
let station = response.data[i];
this.allStations[i] = station;
this.stationCoordinates[i] = fromLonLat([station["StationLongitude"][0], station["StationLatitude"][0]])
insights["totalNumStations"] += 1
// setting the station to show on the map by default - true
this.showStations[i] = true;
if (station["StationType"][0] == "DART") insights["numDartStations"] += 1;
else if (station["StationType"][0] == "Train") insights["numTrainStations"] += 1;
store.setInsights(insights);
loader.hide();
// request the user's preferences
this.getPreferences()
}
})
}
catch (error) {
//loader.hide()
//this.showToast(error.message, "red")
}
})
.catch((error) => {
//loader.hide()
//this.showToast("Error fetching live data", "red")
})
}
})

View File

@ -1,15 +1,18 @@
import { reactive } from 'vue'
export const store = reactive({
// map and insights data
insights: {},
latestTrain: {},
earliestTrain: {},
orderedTrains: [],
selectedTrain: {},
selectedStation: {},
rawData: {},
// side bar
displaySelectedTrain: false,
displayedSelectedStation: false,
// login status
loggedIn: false,
isWaitingForLoginStatus: true,
@ -17,14 +20,6 @@ export const store = reactive({
this.insights = insights
},
setLatestTrain(latestTrain) {
this.latestTrain = latestTrain
},
setEarliestTrain(earliestTrain) {
this.earliestTrain = earliestTrain
},
setRawData(rawData) {
this.rawData = rawData
},