diff --git a/back-end/app.js b/back-end/app.js
index 57a7cab..478c09d 100644
--- a/back-end/app.js
+++ b/back-end/app.js
@@ -46,15 +46,19 @@ app.post("/getRoute", async (req, res) => {
const routeFinding = require("./getOptimizedRoute.js");
const busStops = {};
//parse stops into a dictionary of coordinates
- for (let stopkey in req.body.stops) {
- let latitude = req.body.stops[stopkey].latitude
- let longitude = req.body.stops[stopkey].longitude
- let stopID = req.body.stops[stopkey].stopId
- busStops[stopID] = [latitude, longitude]
+ for (let stopKey in req.body.stops) {
+ let latitude = req.body.stops[stopKey].latitude;
+ let longitude = req.body.stops[stopKey].longitude;
+ let stopID = req.body.stops[stopKey].stopId;
+
+ // Initialize the object if it doesn't exist
+ if (!busStops[stopID]) {
+ busStops[stopID] = {};
+ }
+
+ busStops[stopID].geoLoc = [latitude, longitude];
+ busStops[stopID].stopId = stopID;
}
- console.log('<----------Stops---------->')
- console.log(busStops)
-
//parse routes into a dictionary of routes, each holding an
//array of stops
let routes = {};
@@ -87,8 +91,8 @@ app.post("/getRoute", async (req, res) => {
req.body.destination_lat,
req.body.destination_lng,
);
- console.log(optimalRoute.onSameRoute);
- res.send(optimalRoute.onSameRoute);
+ console.log(optimalRoute.originStop.stopId);
+ res.send(optimalRoute);
}
catch(err){
console.log(err);
diff --git a/back-end/getOptimizedRoute.js b/back-end/getOptimizedRoute.js
index 82a4895..1be788b 100644
--- a/back-end/getOptimizedRoute.js
+++ b/back-end/getOptimizedRoute.js
@@ -1,28 +1,28 @@
//this function creates a directed circular graph representation of of bus stops and the routes.
/*in the output graph, the key represents a bus stop, and the value represents all the bus stops that
are directly reachavble from the key bus stop.*/
-async function createGraph(routes, busstops) {
+async function createGraph(routes, busStops) {
let graph = {};
+
// Initialize the graph with all stops and an empty list of routes
- for (let stop in busstops) {
- let stopKey = busstops[stop].toString();
- graph[stopKey] = { routes: [], connections: [] };
+ for (let stopKey in busStops) {
+ graph[stopKey] = { routes: [], connections: [], stopId: busStops[stopKey].stopId, geoLoc: busStops[stopKey].geoLoc };
}
for (let routeId in routes) {
let stops = routes[routeId];
for (let i = 0; i < stops.length; i++) {
- let currentStop = stops[i];
- let nextStop = stops[(i + 1) % stops.length];
- let currentKey = currentStop.toString();
+ let currentStopId = stops[i].stopId;
+ let nextStopId = stops[(i + 1) % stops.length].stopId;
// Add the current route to the list of routes for this stop
- if (!graph[currentKey].routes.includes(routeId)) {
- graph[currentKey].routes.push(routeId);
+ if (!graph[currentStopId].routes.includes(routeId)) {
+ graph[currentStopId].routes.push(routeId);
}
// Add the connection information
- graph[currentKey].connections.push({ coordinates: nextStop, route: graph[currentKey].routes });
+ // Assuming that you only need the next stop's ID
+ graph[currentStopId].connections.push({ stopId: nextStopId, coordinates: stops[i].geoLoc });
}
}
return graph;
@@ -31,25 +31,43 @@ async function createGraph(routes, busstops) {
function getEuclideanDistance (a, b) {
let x1 = a[0];
let y1 = a[1];
- let x2 = b.split(',')[0];
- let y2 = b.split(',')[1];
+ let x2;
+ let y2;
+ try{
+ x2 = b.split(',')[0];
+ y2 = b.split(',')[1];
+ }
+ catch(err){
+ x2 = b[0];
+ y2 = b[1];
+ }
+ console.log('x1: '+x1+', y1: '+y1+', x2: '+x2+', y2: '+y2)
+
return Math.sqrt(Math.pow((x2 - x1), 2) + Math.pow((y2 - y1), 2));
}
//find bus stops that are relatively close in term of walking distance
-async function findAllReachableStops(graph, origin, threshold=0.01) {
+async function findAllReachableStops(graph, origin, threshold=0.008, maxThreshold=0.1) {
let resolvedGraph = await graph; // Waits for the graph Promise to resolve
-
+ console.log('resolvedGraph:',Object.keys(resolvedGraph))
let reachableStops = [];
for (let busstop in resolvedGraph) {
- busstop = busstop.toString();
- let distance = getEuclideanDistance(origin, busstop);
+ console.log('geoloc:', resolvedGraph[busstop].geoLoc)
+ let geoLoc = resolvedGraph[busstop].geoLoc;
+ let busstopId = resolvedGraph[busstop].stopId;
+ let distance = getEuclideanDistance(origin, geoLoc);
+ console.log('distance: '+distance)
if (distance < threshold) {
- console.log('reachable stop found: ' + resolvedGraph[busstop].routes);
- reachableStops.push({ coordinates: busstop, route: resolvedGraph[busstop].route });
+ console.log('reachable stop found for: '+ origin + ', ' + resolvedGraph[busstop].routes);
+ reachableStops.push({ coordinates: geoLoc, route: resolvedGraph[busstop].routes, stopId: busstopId });
}
}
+ //when no stops are found, keep calling itself with larger and larger threshold
+ if (reachableStops.length == 0 && threshold < maxThreshold) {
+ console.log('no reachable stop found, increasing threshold');
+ reachableStops = findAllReachableStops(graph, origin, threshold + 0.002)
+ }
return reachableStops;
}
@@ -67,15 +85,19 @@ async function getWalkingDistance(origin, destination) {
destination = destination.join('%2C');
}
- let res = await fetch(`https://maps.googleapis.com/maps/api/distancematrix/json?units=imperial&origins=${origin}&destinations=${destination}&key=${process.env.EXPRESS_APP_MAP_API_KEY}`)
+ let res = await fetch(`https://maps.googleapis.com/maps/api/distancematrix/json?units=imperial&origins=${origin}&destinations=${destination}&mode=walking&key=${process.env.EXPRESS_APP_MAP_API_KEY}`)
let data = await res.json();
- res = data.rows[0].elements[0].duration.value;
+ res = {
+ distance: data.rows[0].elements[0].distance.value,
+ time: data.rows[0].elements[0].duration.text
+ };
return res;
}
async function isOnSameRoute(graph, stop1, stop2, routes, busstops) {
let resolvedGraph = await graph;
- let sharedRoutes = await resolvedGraph[stop1.coordinates].routes.filter(element => resolvedGraph[stop2.coordinates].routes.includes(element));
+ console.log(Object.keys(resolvedGraph))
+ let sharedRoutes = await resolvedGraph[stop1.stopId].routes.filter(element => resolvedGraph[stop2.stopId].routes.includes(element));
if(sharedRoutes.length == 0){
return false;
}
@@ -91,23 +113,49 @@ async function findOptimalRoute(graph, routes, busstops, origin_lat, origin_lng,
let reachableFromOrigin = await findAllReachableStops(graph, origin);
let reachableFromDestination = await findAllReachableStops(graph, destination);
+ console.log('TOTAL REACHABLE STOPS: '+Number(reachableFromOrigin.length + reachableFromDestination.length))
// Calculate route distances
for (let originStop of reachableFromOrigin) {
for (let destinationStop of reachableFromDestination) {
let onSameRoute = await isOnSameRoute(graph, originStop, destinationStop, routes, busstops);
console.log('on same route result: '+onSameRoute)
if (onSameRoute.length > 0) {
- let distanceToOriginStop = await getWalkingDistance(origin, originStop.coordinates);
- let distanceFromDestinationStop = await getWalkingDistance(destinationStop.coordinates, destination);
- let totalDistance = distanceToOriginStop + distanceFromDestinationStop;
- console.log('fetched from Google Maps API, total distance: '+totalDistance);
+ let distanceToOriginStop
+ let distanceFromDestinationStop
+ let totalDistance
+ let totalTime
+ console.log('TOTAL REACHABLE STOPS2: '+reachableFromOrigin.length + reachableFromDestination.length)
+ if (Number(reachableFromOrigin.length + reachableFromDestination.length) < 20){
+
+ distanceToOriginStop = await getWalkingDistance(origin, originStop.coordinates);
+ distanceFromDestinationStop = await getWalkingDistance(destinationStop.coordinates, destination);
+ totalDistance = distanceToOriginStop.distance + distanceFromDestinationStop.distance;
+ console.log('fetched from Google Maps API, total distance: '+totalDistance);
+ totalTime = Number(distanceToOriginStop.time.split(' ')[0]) + Number(distanceFromDestinationStop.time.split(' ')[0]);
+ console.log('fetched from Google Maps API, total time: '+totalTime);
+ }
+ else{
+ distanceToOriginStop = await getEuclideanDistance(origin, originStop.coordinates);
+ distanceFromDestinationStop = await getEuclideanDistance(destinationStop.coordinates, destination);
+ totalDistance = distanceToOriginStop + distanceFromDestinationStop;
+ console.log('getting euclidean distance, total distance: '+totalDistance);
+
+ }
+
+ // Create an object with route names as keys and {distance, time} as values
+ let routeDetails = {};
+ for (let route of onSameRoute) {
+ routeDetails[route] = {distance: totalDistance, time: totalTime};
+ }
+
// Check if this route is better than the current best
if (totalDistance < minTotalDistance) {
console.log('new optimal route found')
minTotalDistance = totalDistance;
- optimalRoute = { originStop, destinationStop, onSameRoute };
+ optimalRoute = { origin, originStop, destination, destinationStop, onSameRoute: routeDetails };
}
}
+
}
}
@@ -117,6 +165,12 @@ async function findOptimalRoute(graph, routes, busstops, origin_lat, origin_lng,
}
console.log('-------------------------------------')
console.log('optimal route: '+optimalRoute.onSameRoute);
+ for (let route in optimalRoute.onSameRoute) {
+
+ console.log('<-----------Route Name: '+route+'--------------->');
+ console.log('Total Distance: '+optimalRoute.onSameRoute[route].distance);
+ console.log('Total Time: '+optimalRoute.onSameRoute[route].time);
+ }
console.log('origin stop location: '+optimalRoute.originStop.coordinates);
console.log('destination stop location: '+optimalRoute.destinationStop.coordinates);
diff --git a/front-end/src/components/RouteButton.js b/front-end/src/components/RouteButton.js
new file mode 100644
index 0000000..e5a6ed6
--- /dev/null
+++ b/front-end/src/components/RouteButton.js
@@ -0,0 +1,30 @@
+import { useState, useEffect } from 'react';
+function RouteButton({ route }) {
+ const [color, setColor] = useState('rgba(0, 0, 0, 0)');
+ function hexToRGBA(hex, alpha) {
+ if (hex === undefined) {
+ return 'rgba(0, 0, 0, 0)'; // return transparent color if hex is undefined
+ }
+ let r = parseInt(hex.slice(1, 3), 16),
+ g = parseInt(hex.slice(3, 5), 16),
+ b = parseInt(hex.slice(5, 7), 16);
+
+ if (alpha) {
+ return `rgba(${r}, ${g}, ${b}, ${alpha})`;
+ } else {
+ return `rgb(${r}, ${g}, ${b})`;
+ }
+ }
+
+ useEffect(() => {
+ setColor(hexToRGBA(route.color, 0.5));
+ }, [route.color]);
+
+ return (
+
+ );
+ }
+
+export default RouteButton;
\ No newline at end of file
diff --git a/front-end/src/components/RouteMap.js b/front-end/src/components/RouteMap.js
index f1942ab..556b609 100644
--- a/front-end/src/components/RouteMap.js
+++ b/front-end/src/components/RouteMap.js
@@ -1,5 +1,6 @@
import React, { useEffect, useRef } from "react";
import "../css/routeMap.css";
+import SaveRouteButton from "./SaveRouteButton";
function RouteMap({ location1, location2 }) {
const mapRef = useRef(null);
@@ -54,7 +55,13 @@ function RouteMap({ location1, location2 }) {
});
}, [location1, location2]);
- return
;
+ return (
+
+ )
+
}
export default RouteMap;
diff --git a/front-end/src/components/RoutesPage.js b/front-end/src/components/RoutesPage.js
index 8687e99..93745ad 100644
--- a/front-end/src/components/RoutesPage.js
+++ b/front-end/src/components/RoutesPage.js
@@ -65,15 +65,16 @@ function RoutesPage() {
console.log('awaiting data');
return }
if (fromLocation.name === lastLocation1.current.name && toLocation.name === lastLocation2.current.name) {
+ awaitingData.current = false;
return;
}
}
catch(typeError){
console.log('same input, no need to fetch new route');
}
- if (fromLocation.name && toLocation.name) {
+ if (fromLocation.name && toLocation.name && fromLocation.name !== toLocation.name) {
awaitingData.current = true;
- let reachableRoutes = fetch(`http://localhost:4000/getRoute`, {
+ let reachableRoutes = fetch(`/getRoute`, {
method: "POST",
headers: {
'Content-Type': 'application/json'
@@ -97,13 +98,21 @@ function RoutesPage() {
.then((data) => {
lastLocation1.current = fromLocation;
lastLocation2.current = toLocation;
- if (Object.keys(data).length === 0){
+ if (Object.keys(data.onSameRoute).length === 0){
alert('No route found');
return;
}
- setRoutes(data);
+
+ console.log(Object.keys(data.onSameRoute).length)
+ if (Object.keys(data.onSameRoute).length === 7){
+ setRoutes(['You should walk instead!']);
+ }
+ else{
+ setRoutes(data.onSameRoute);
+ window.nyushuttle.startStopLocation = data.originStop.stopId;
+ window.nyushuttle.endStopLocation = data.destinationStop.stopId;
+ }
setShowSubpage(true);
- alert('Starting' + JSON.stringify(data[0]));
return data;
})
.catch((error) => {
diff --git a/front-end/src/components/RoutesSubpage.js b/front-end/src/components/RoutesSubpage.js
index 1d24d8b..733c153 100644
--- a/front-end/src/components/RoutesSubpage.js
+++ b/front-end/src/components/RoutesSubpage.js
@@ -6,6 +6,8 @@ import HeartIcon from "../images/heart-svg.svg";
import HeartIconLoaded from "../images/heart-svg-loaded.svg";
import SaveRouteDialog from "./SaveRouteDialog";
import RouteMap from "./RouteMap";
+import SaveRouteButton from "./SaveRouteButton";
+import ViewRouteButton from "./ViewRouteButton";
import { localStorageSave, localStorageLoad } from '../utils/localStorageSaveLoad';
function RoutesSubpage({ location1, location2, routes }) {
@@ -13,17 +15,9 @@ function RoutesSubpage({ location1, location2, routes }) {
const [isRouteSaved, setIsRouteSaved] = useState(false);
const [displayText, setDisplayText] = useState("Click to save route ->");
const navigate = useNavigate();
- useEffect(() => {
- const loadedRoutes = localStorageLoad('routes');
- if (loadedRoutes && loadedRoutes.some((route) => route.from.name === location1.name && route.to === location2.name)) {
- setIsRouteSaved(true);
- setDisplayText("View saved routes here");
- } else {
- setIsRouteSaved(false);
- }
- }, [location1, location2]);
const openSaveDialog = () => {
+ console.log('clicked')
if (!isRouteSaved) {
setSaveDialogOpen(true);
} else {
@@ -32,40 +26,48 @@ function RoutesSubpage({ location1, location2, routes }) {
localStorageSave('routes', updatedRoutes);
}
};
+ useEffect(() => {
+ const loadedRoutes = localStorageLoad('routes');
+ if (loadedRoutes && loadedRoutes.some((route) => route.from.name === location1.name && route.to === location2.name)) {
+ setIsRouteSaved(true);
+ setDisplayText("View saved routes here");
+ } else {
+ setIsRouteSaved(false);
+ }
+ }, [location1, location2]);
- const closeSaveDialog = () => {
- setSaveDialogOpen(false);
- };
- const toggleRouteSaved = (name) => {
- const loadedRoutes = localStorageLoad('routes') || [];
- const maxId = loadedRoutes.reduce((max, route) => (route._id > max ? route._id : max), 0);
- const newId = maxId + 1;
- const newRoute = {
- _id: newId,
- name: name,
- timestamp: Date.now(),
- from: {
- name: location1.name,
- address: location1.address,
- },
- to: {
- name: location2.name,
- address: location2.address,
- },
- };
- loadedRoutes.push(newRoute);
- localStorageSave('routes', loadedRoutes);
- setIsRouteSaved(true);
- setDisplayText("Saved");
- setTimeout (() => {
- setDisplayText("View saved routes here");
- }, 3000);
- };
-
- const startNavigation = () => {
+ useEffect(() => {
+ if (window.nyushuttle.routes){
+ for ( let route in routes) {
+ for (let routename in window.nyushuttle.routes) {
+ console.log(routename)
+ if (window.nyushuttle.routes[routename][0] === route) {
+ routes[route].color = window.nyushuttle.routes[routename][1];
+ console.log(window.nyushuttle.routes[routename])
+ }
+ }
+ }
+ if(routes[Object.keys(routes)[0]].time){
+ console.log('time calculated')
+ }
+ else{
+ console.log('time not calculated')
+ }
+ }
-};
+ }, [window.nyushuttle.routes]);
+
+ const startNavigation = value => () => {
+ for (let [key, name] of Object.entries(window.nyushuttle.routes)) {
+ if (name[0] === value) {
+ window.nyushuttle.routesSelected = key;
+ window.nyushuttle.navigating = true;
+ break;
+ }
+ }
+ navigate('/map');
+ };
const shuttle = "X";
const shuttleSchedule = "HH:MM";
@@ -77,46 +79,36 @@ function RoutesSubpage({ location1, location2, routes }) {
return (
-
- {displayText}
-
- {!isRouteSaved &&
-
- }
+
- {routes.map((route, index) => (
-
+
+ {Object.keys(routes).map((route, index) => (
+
{route}
-
- Shuttle {route} scheduled at {shuttleSchedule}
+
+ Total Walking Time:{" "}
+ {routes[route].time} min
- {location1.name} to shuttle:{" "}
- {timeToShuttle} min
-
-
- Shuttle to {location2.name}:{" "}
- {timeToDestination2} min
+ Shuttle {route} scheduled at {shuttleSchedule}
+
-
))}
+
- {isSaveDialogOpen && (
-
- )}
);
}
diff --git a/front-end/src/components/SaveRouteButton.js b/front-end/src/components/SaveRouteButton.js
new file mode 100644
index 0000000..2d55aec
--- /dev/null
+++ b/front-end/src/components/SaveRouteButton.js
@@ -0,0 +1,92 @@
+import '../css/routesSubpage.css';
+import { Link } from 'react-router-dom';
+import React, { useState, useEffect } from 'react';
+import HeartIcon from '../images/heart-svg.svg';
+import HeartIconLoaded from '../images/heart-svg-loaded.svg';
+import { localStorageSave, localStorageLoad } from '../utils/localStorageSaveLoad';
+import SaveRouteDialog from "./SaveRouteDialog";
+
+
+function SaveRouteButton (prop) {
+ const [isRouteSaved, setIsRouteSaved] = useState(false);
+ const [isSaveDialogOpen, setSaveDialogOpen] = useState(false);
+
+ const toggleButton = () => {
+
+ console.log(window.nyushuttle.fromLocation.name)
+ }
+ useEffect(() => {
+ setIsRouteSaved(prop.saved);
+ },[prop.saved]);
+
+ const openSaveDialog = () => {
+ setIsRouteSaved(!isRouteSaved);
+ const location1 = window.nyushuttle.fromLocation;
+ const location2 = window.nyushuttle.toLocation;
+ if (!isRouteSaved) {
+ setSaveDialogOpen(true);
+ } else {
+ const loadedRoutes = localStorageLoad('routes') || [];
+ const updatedRoutes = loadedRoutes.filter((route) => route.from.name !== location1.name || route.to.name !== location2.name);
+ localStorageSave('routes', updatedRoutes);
+ }
+ };
+
+ const closeSaveDialog = () => {
+ setSaveDialogOpen(false);
+ };
+
+ const toggleRouteSaved = (name) => {
+ const location1 = window.nyushuttle.fromLocation;
+ const location2 = window.nyushuttle.toLocation;
+ const loadedRoutes = localStorageLoad('routes') || [];
+ const maxId = loadedRoutes.reduce((max, route) => (route._id > max ? route._id : max), 0);
+ const newId = maxId + 1;
+ const newRoute = {
+ _id: newId,
+ name: name,
+ timestamp: Date.now(),
+ from: {
+ name: location1.name,
+ address: location1.address,
+ },
+ to: {
+ name: location2.name,
+ address: location2.address,
+ },
+ };
+ loadedRoutes.push(newRoute);
+ localStorageSave('routes', loadedRoutes);
+ setIsRouteSaved(true);
+ };
+
+ return (
+ <>
+
+
+
+ {isSaveDialogOpen && (
+
+ )}
+ >
+ )
+}
+
+export default SaveRouteButton;
+/*
+
+{displayText}
+
+{!isRouteSaved &&
+
+}*/
\ No newline at end of file
diff --git a/front-end/src/components/ViewRouteButton.js b/front-end/src/components/ViewRouteButton.js
new file mode 100644
index 0000000..5852bc0
--- /dev/null
+++ b/front-end/src/components/ViewRouteButton.js
@@ -0,0 +1,18 @@
+import '../css/routesSubpage.css';
+import { Link } from 'react-router-dom';
+function ViewRouteButton () {
+ return (
+ <>
+
+
+ View Route
+
+
+ >
+
+
+
+ )
+}
+
+export default ViewRouteButton;
\ No newline at end of file
diff --git a/front-end/src/css/routeMap.css b/front-end/src/css/routeMap.css
index d7ff180..4a1b4d5 100644
--- a/front-end/src/css/routeMap.css
+++ b/front-end/src/css/routeMap.css
@@ -1,13 +1,6 @@
-.route_map {
- width: 85%;
- height: 50%;
- border-radius: 20px;
- overflow: hidden;
- filter: grayscale(20%);
- }
.route_map{
- @apply bg-lightTone w-80 opacity-60 border-solid drop-shadow-2xl border-2 border-darkTone rounded-3xl;
+ @apply bg-lightTone h-52 w-full border-solid drop-shadow-2xl border-2 border-darkTone rounded-3xl;
}
.dark .rooute_map{
diff --git a/front-end/src/css/routesPage.css b/front-end/src/css/routesPage.css
index 5c1a8d9..c16145b 100644
--- a/front-end/src/css/routesPage.css
+++ b/front-end/src/css/routesPage.css
@@ -1,5 +1,5 @@
.route-container {
- @apply p-2 pl-4 pr-6 pt-4 pb-5 h-screen bg-lightTone flex flex-col overflow-y-scroll;
+ @apply p-2 pl-4 pr-4 pt-4 pb-5 h-screen bg-lightTone flex flex-col overflow-y-scroll;
}
.dark .route-container{
@@ -7,11 +7,11 @@
}
.input-wrapper{
- @apply flex flex-col items-center;
+ @apply flex flex-col items-center px-4;
}
.location-input {
- @apply my-0.5 w-80;
+ @apply my-0.5 w-full;
}
.location-input label {
diff --git a/front-end/src/css/routesSubpage.css b/front-end/src/css/routesSubpage.css
index a92f0e3..ff1df62 100644
--- a/front-end/src/css/routesSubpage.css
+++ b/front-end/src/css/routesSubpage.css
@@ -1,7 +1,7 @@
/* routesSubpage.css */
.routes-subpage-container{
- @apply h-screen bg-lightTone w-full overflow-y-auto flex flex-col items-center pb-20;
+ @apply h-screen bg-lightTone px-4 w-full pt-3 overflow-y-auto flex flex-col items-center pb-20 my-0;
}
.dark .routes-subpage-container{
@@ -13,11 +13,19 @@ img {
}
.title-container {
- @apply flex justify-items-start w-80;
+ @apply flex justify-items-start w-full;
+}
+
+.save-route-button{
+ @apply text-darkTone text-center w-1/4 text-base mx-0 h-full p-0 rounded-xl;
+}
+
+.view-route-button{
+ @apply bg-darkTone text-lightTone w-full text-base mx-0 h-11 py-2 text-center rounded-xl px-6;
}
.saved-icon {
- @apply w-16 h-16 mb-0 grayscale-0 ;
+ @apply absolute z-50 w-8 h-12 mb-0 top-8 right-5 pb-2 grayscale-0 p-0;
}
.save{
@@ -32,6 +40,10 @@ img {
@apply w-full text-right;
}
+.route-info-container{
+ @apply flex flex-col items-center w-full pt-3;
+}
+
.red{
filter: invert(72%) sepia(45%) saturate(5044%) hue-rotate(319deg) brightness(105%) contrast(82%);
}
@@ -42,12 +54,12 @@ img {
align-items: center;
justify-content: space-between;
padding: 0.5rem;
- width: 90%;
- margin-top: 10px;
- background-color: #fff;
- border: 0.5px solid #4e4a4a;
- border-radius: 8px;
- box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
+ width: 100%;
+ border-radius: 10px;
+ border-style: solid;
+ margin-bottom: 10px;
+ background-color: white;
+ box-shadow: 0 2px 4px rgba(103, 58, 163, 0.5);
}
.dark .route-info {
@@ -59,6 +71,7 @@ img {
flex-direction: column;
justify-content: space-between;
align-items: flex-start;
+ margin-left: 10px;
}
.route-info .text-lg {
@@ -70,10 +83,5 @@ img {
}
.nav-button {
- background-color: #165516;
-
- padding: 1rem;
- border-radius: 12px;
- color: #fff;
- margin: 10px;
+ @apply bg-darkTone text-lightTone text-base my-3 mx-3 h-14 py-2 rounded-xl px-6 w-20;
}
diff --git a/front-end/src/utils/stops.js b/front-end/src/utils/stops.js
index 1cafef4..fd48be6 100644
--- a/front-end/src/utils/stops.js
+++ b/front-end/src/utils/stops.js
@@ -73,7 +73,6 @@ export async function queryStops() {
window.nyushuttle.stops = data.stops;
groupRoutes = data.groupRoutes;
center = data.center;
- console.log(window.nyushuttle.stops)
return true;
} catch (error) {
@@ -137,20 +136,119 @@ function drawRoutes(showStopName) {
if (!Object.keys(window.nyushuttle.routes).length) {
return;
}
+ let clippedRouteIndex = null;
+ if (window.nyushuttle.startStopLocation){
+ clippedRouteIndex = getClippedRoute()
+ }
const routes = window.nyushuttle.routes;
+
Object.keys(routes)
.filter((routeId) => isSelectedRoute(routeId))
.forEach((routeId) => {
- drawRoute(routeId, routes[routeId], showStopName);
+ drawRoute(routeId, routes[routeId], showStopName, clippedRouteIndex);
});
}
-function drawRoute(routeId, route, showStopName) {
+function drawWalkingRoute(direction) {
+ let startLocation, endLocation;
+ let request;
+ let stops = window.nyushuttle.stops;
+
+ if (direction === 'from') { //plot "from" route
+ //becuase for some reason fromLocation.lat and fronLocation.lng are corrupted, use
+ //fromLocation.place_id instead
+ startLocation = {'placeId':window.nyushuttle.fromLocation.place_id};
+ endLocation = {
+ lat: stops['ID' + window.nyushuttle.startStopLocation].latitude,
+ lng: stops['ID' + window.nyushuttle.startStopLocation].longitude
+ };
+ request = {
+ origin: startLocation,
+ destination: endLocation,
+ travelMode: 'WALKING',
+ };
+ } else if (direction === 'to') { //plot "to" route
+ endLocation = {'placeId':window.nyushuttle.toLocation.place_id};
+ startLocation = {
+ lat: stops['ID' + window.nyushuttle.endStopLocation].latitude,
+ lng: stops['ID' + window.nyushuttle.endStopLocation].longitude
+ };
+ request = {
+ origin: startLocation,
+ destination: endLocation,
+ travelMode: 'WALKING',
+ };
+ }
+ let directionsService = new window.google.maps.DirectionsService();
+ directionsService.route(request, function (result, status) {
+ if (status == 'OK') {
+ let directionsRenderer = new window.google.maps.DirectionsRenderer({
+ suppressMarkers: true // Hides the default markers
+ });
+ directionsRenderer.setMap(window.nyushuttle.currentMap);
+ directionsRenderer.setDirections(result);
+
+ // Add custom markers
+ if(direction === 'from') {
+ const startMarker = new window.google.maps.Marker({
+ position: result.routes[0].legs[0].start_location,
+ map: window.nyushuttle.currentMap,
+ icon: {
+ path: window.google.maps.SymbolPath.CIRCLE,
+ scale: 7,
+ fillColor: '#8400a8',
+ fillOpacity: 1.0,
+ strokeColor: '#FF0000',
+ strokeOpacity: 0
+ }
+ });
+ }
+ else{
+ const endMarker = new window.google.maps.Marker({
+ position: result.routes[0].legs[0].end_location,
+ map: window.nyushuttle.currentMap,
+ icon: {
+ path: window.google.maps.SymbolPath.CIRCLE,
+ scale: 7,
+ fillColor: '#8400a8',
+ fillOpacity: 1,
+ strokeColor: '#',
+ strokeOpacity: 0
+ }
+ });
+ }
+ }
+ });
+}
+
+function drawRoute(routeId, route, showStopName, clip=null) {
const routeGroupId = route[2];
const routeColor = correctColorFromARGB(route[1]);
- const routePaths = getRoutePaths(routeId);
+ let routePaths = getRoutePaths(routeId);
+ if (clip) {
+ drawWalkingRoute('from')
+ drawWalkingRoute('to')
+ routePaths = routePaths.slice(clip[0], clip[1])
+ if (routePaths.length == 0){
+ if (clip[0] < 100 && clip[1] > 100){
+ routePaths = routePaths.concat(routePaths.slice(100, clip[1]))
+ }
+ else if (clip[0] < 100 && clip[1] < 100){
+ routePaths = routePaths[0].slice(clip[0], clip[1])
+ }
+ else if (clip[0] >= 100 && clip[1] >= 100){
+ routePaths = routePaths[1].slice(clip[0], clip[1])
+ }
+
+ }
+ drawRoutePath(routePaths, routeColor, routeId, routeGroupId);
+ }
+ else{
+ console.log('noclip')
+ drawRoutePath(routePaths, routeColor, routeId, routeGroupId);
- drawRoutePath(routePaths, routeColor, routeId, routeGroupId);
+ }
+
// routePaths.forEach((path) => {
// updateBoundsWithPoint(path);
// });
@@ -165,6 +263,49 @@ function getRoutePaths(routeId) {
return points[routeId][0].map((point) => new window.google.maps.LatLng(point.lat, point.lng));
}
+function getIndexofStop(r, stopPos) {
+ // Logic to get clipped route
+ let minDist = 9999
+ let index = -1
+ console.log('r: ',r)
+ for (let i=0;i destinationStopIndex){
+ return [destinationStopIndex, originStopIndex]
+ }
+ return [originStopIndex, destinationStopIndex]
+}
+
function drawRoutePath(path, routeColor, routeId, routeGroupId) {
const selected = window.nyushuttle.routesSelected && window.nyushuttle.routesSelected.includes(routeId);
const opacity = getOpacity(selected);
@@ -219,6 +360,22 @@ function drawStopNamesForRoute(route) {
// Logic to draw stop names for the given route
}
+function sliceRouteStops(routeStops, stop1, stop2) {
+ // Retain the first three elements
+ const initialPart = routeStops.slice(0, 3);
+
+ let startIndex = routeStops.findIndex(subarray => subarray[1] === stop1);
+ let endIndex = routeStops.findIndex(subarray => subarray[1] === stop2);
+ if (startIndex > endIndex) {
+ let temp = startIndex;
+ startIndex = endIndex;
+ endIndex = temp;
+ }
+ const slicedPart = routeStops.slice(startIndex, endIndex + 1);
+
+ return [...initialPart, ...slicedPart];
+}
+
function drawStops() {
const stops = window.nyushuttle.stops;
if (!stops) return;
@@ -230,9 +387,11 @@ function drawStops() {
Object.keys(routes)
.filter((routeId) => isSelectedRoute(routeId))
.forEach((routeId) => {
- const routestops = routes[routeId];
- const routeGroupId = routes[routeId][2];
-
+ let routestops = routes[routeId];
+ let routeGroupId = routes[routeId][2];
+ if (window.nyushuttle.startStopLocation && routestops){
+ routestops = sliceRouteStops(routestops, window.nyushuttle.startStopLocation, window.nyushuttle.endStopLocation)
+ }
addRouteMarkersOnMap(routeId, routestops, routeGroupId, showStopName);
});