Skip to content

Commit

Permalink
Merge pull request #78 from agiledev-students-fall2023/Jaden's-Branch
Browse files Browse the repository at this point in the history
Manually merged @r8btx's changes with mine to resolve conflicts
  • Loading branch information
r8btx authored Nov 22, 2023
2 parents 331516d + 28d5454 commit 73aa270
Show file tree
Hide file tree
Showing 5 changed files with 115 additions and 74 deletions.
18 changes: 0 additions & 18 deletions back-end/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,22 +6,4 @@ const app = express(); // instantiate an Express object
const cors = require('cors');
app.use(cors());

const url = 'https://nyu.passiogo.com/';

const buses = require('./buses.js');



app.get('/buses', async (req, res) => {
res.set('Access-Control-Allow-Origin', '*');
try {
console.log('buses route entered')
const busData = await buses.getBuses();
console.log('bus data fetched')
res.json(busData['buses']);
} catch (error) {
res.status(500).send('An error occurred while fetching the buses data');
}
});

module.exports = app;
30 changes: 0 additions & 30 deletions back-end/buses.js

This file was deleted.

13 changes: 3 additions & 10 deletions front-end/src/components/Map.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@ import '../css/map.css';
import { useEffect, useState, useRef } from 'react';
import RealTimeDataWebSocket from '../utils/websocket';
import { loadGoogleMapsAPI, initializeMap, getCoordinates, generateTwoUniqueRandomInts } from '../utils/mapUtility';
import { queryTransportations } from '../utils/transportData';
import { updateTransportMarkers } from '../utils/transportMarker';

function Map({ line, lineColor }) {
//const API_KEY = '';
const googleMapRef = useRef(null);
const [isApiLoaded, setIsApiLoaded] = useState(false);
const [isMapLoaded, setIsMapLoaded] = useState(false);
Expand Down Expand Up @@ -95,15 +95,8 @@ function Map({ line, lineColor }) {

const fetchTransportData = async () => {
try {
// console.log('fetching transport data');
const response = await fetch('/buses');
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
// console.log('response ok');
const data = await response.json();
console.log('Initial transport data fetched');
setTransportData(data);
const transportations = await queryTransportations(true);
setTransportData(transportations);
} catch (error) {
console.log('error fetching transport data', error);
// Other error handling? message?
Expand Down
77 changes: 77 additions & 0 deletions front-end/src/utils/transportData.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
import axios from 'axios';

const EXCLUDED_ROUTES_QUERY_DELAY = 600000; // 10 mins
const ALERTS_QUERY_DELAY = 120000; // 2 mins
const MIN_QUERY_DELAY = 60000; // 1 min

let lastExcludedRoutesQuery = -EXCLUDED_ROUTES_QUERY_DELAY;
let lastAlertsQuery = -ALERTS_QUERY_DELAY;
let lastQuery = -MIN_QUERY_DELAY;
let lastResults = {};

// Query transportations (real-time update is done through the websocket)
export async function queryTransportations(refresh) {
// Prevent too frequent requests (rate limiting)
if (performance.now() - lastQuery < MIN_QUERY_DELAY) {
return lastResults;
}

// JSON
const json = {
s0: localStorage.agencyId,
sA: 1,
};

const subscribedRoutes = localStorage.subscribedRoutes ? localStorage.subscribedRoutes.split(',') : [];
if (subscribedRoutes.length) {
json.rA = subscribedRoutes.length;
}
subscribedRoutes.forEach((route, index) => {
json['r' + index] = route;
});
const formData = new URLSearchParams({});
formData.append('json', JSON.stringify(json));

// Params for URL
const params = {
getBuses: refresh || performance.now() - lastExcludedRoutesQuery > EXCLUDED_ROUTES_QUERY_DELAY ? 1 : 2,
deviceId: localStorage.deviceId,
};

// Optional parameters
if (refresh) {
params.speed = '1';
}
if (performance.now() - lastAlertsQuery > ALERTS_QUERY_DELAY) {
params.alertCRC = localStorage.alertCRC;
lastAlertsQuery = performance.now();
}

const urlParams = new URLSearchParams(params);
const url = `${localStorage.serviceEndpointSub}/mapGetData.php?${urlParams.toString()}`;

try {
const response = await axios.post(url, formData);
const data = response.data;
if (!data) {
throw new Error('empty response');
}
if (data.excludedRoutes) {
lastExcludedRoutesQuery = performance.now();
// place routes2 implementation here?
}
if (data && ((data.alertCRC && data.alertCRC != localStorage.alertCRC) || data.lastPushId > 0)) {
// query alerts
}

const transportations = data.buses && Object.keys(data.buses).length ? data.buses : {};

lastResults = transportations;
lastQuery = performance.now();

return transportations;
} catch (error) {
console.log('Transportations query error: ' + error.message);
return {};
}
}
51 changes: 35 additions & 16 deletions front-end/src/utils/transportMarker.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
const MAX_ANIMATION_DURATION = 7000;
const busIcons = ['A', 'B', 'C', 'E', 'F', 'G', 'W', 'Cobble Hill'];

export function updateTransportMarkers(transportData, markerRef, map) {
if (!transportData) {
Expand All @@ -16,40 +15,37 @@ export function updateTransportMarkers(transportData, markerRef, map) {

// Process new and existing transport data
Object.keys(transportData).forEach((transport) => {
let lat = parseFloat(transportData[transport][0].latitude);
let lng = parseFloat(transportData[transport][0].longitude);
const transportInfo = transportData[transport][0];
const lat = parseFloat(transportInfo.latitude);
const lng = parseFloat(transportInfo.longitude);
const newPosition = new window.google.maps.LatLng(lat, lng);
const newIcon = generateTransportMarkerIcon(transportInfo.color, transportInfo.calculatedCourse);

if (markerRef.current[transport]) {
// Update the position of the existing marker
const currentPosition = markerRef.current[transport].getPosition();
animateMarker(markerRef.current[transport], currentPosition, newPosition, MAX_ANIMATION_DURATION);

// Update the icon of the existing marker
markerRef.current[transport].setIcon(newIcon);
} else {
// Create a new marker
let route = transportData[transport][0].route; // get last char of route
let routeChar = route.slice(-1);
if (route === 'Ferry Route') { routeChar = 'Ferry_Route'; }
else if (route === 'Cobble Hill') { routeChar = 'Cobble_Hill'; }
let transportMarker = createTransportMarker(newPosition, transportData[transport][0], map, routeChar);
let transportMarker = createTransportMarker(newPosition, transportInfo, map, newIcon);
markerRef.current[transport] = transportMarker;
}
});
}

function createTransportMarker(position, transportInfo, map, route) {
if(route === 'Ferry_Route'){ console.log('ferry'); }

function createTransportMarker(position, transportInfo, map) {
let transportMarker = new window.google.maps.Marker({
position,
map,
title: String(transportInfo.busId),
icon: {
url: 'busIcons/busIcon_route'+route+'.png',
scaledSize: new window.google.maps.Size(30, 30),
},
icon: generateTransportMarkerIcon(transportInfo.color || '#000', transportInfo.calculatedCourse || 0),
});

let infowindow = new window.google.maps.InfoWindow({
content: `<div><strong>No.${transportInfo.busId}</strong><br>Line: ${transportInfo.route}<br>Passengers: ${transportInfo.paxLoad}</div>`,
content: `<div><strong>No.${transportInfo.busId}</strong><br>Line: ${transportInfo.route}</div>`,
});

transportMarker.addListener('click', () => {
Expand Down Expand Up @@ -95,4 +91,27 @@ function animateMarker(marker, startPosition, endPosition, minBusQueryInterval)
}
}

// Generate custom transport marker icon (currently only support buses)
// Original source of bus svg path: www.svgrepo.com
function generateTransportMarkerIcon(color, direction) {
const svg = `<?xml version="1.0" encoding="utf-8"?>
<svg width="24" height="24" xmlns="http://www.w3.org/2000/svg">
<g class="layer" transform="rotate(${direction}, 12, 12)">
<path d="M10,11 L14,11 Q12,5 10,11 z" fill="${color}" transform="translate(0, -7)"/>
</g>
<g class="layer">
<g class="layer">
<circle cx="12" cy="12" fill="${color}" r="9"/>
<circle cx="12" cy="12" fill="#fff" r="8"/>
<path clip-rule="evenodd" d="M7.5 16.63c0 .2.17.37.38.37h.81a.38.38 0 0 0 .36-.32l.2-1.18h5.5l.2 1.18a.38.38 0 0 0 .36.32h.82a.38.38 0 0 0 .37-.37V11l.39-.39a.38.38 0 0 0 .11-.27v-.97a.38.38 0 0 0-.37-.37h-.13v-.5c0-.58-.41-1.09-.98-1.19C14.65 7.17 13.32 7 12 7c-1.32 0-2.65.17-3.52.32-.58.09-.98.6-.98 1.18V9h-.13a.38.38 0 0 0-.37.38v.97c0 .1.04.19.11.26l.39.39v5.63zm2.5-3.38a.75.75 0 1 1-1.5 0 .75.75 0 0 1 1.5 0zm4.75.75a.75.75 0 1 0 0-1.5.75.75 0 0 0 0 1.5zM8.5 8.57v2.93h7V8.57a.37.37 0 0 0-.32-.36A26.46 26.46 0 0 0 12 7.99c-1.3 0-2.6.14-3.18.22a.36.36 0 0 0-.32.36z" fill="${color}" fill-rule="evenodd"/>
</g>
</g>
</svg>`;
const icon = {
url: 'data:image/svg+xml;charset=UTF-8;base64,' + btoa(svg),
scaledSize: new window.google.maps.Size(40, 40),
};
return icon;
}

export default updateTransportMarkers;

0 comments on commit 73aa270

Please sign in to comment.