Compare commits
5 Commits
456d486d39
...
backend
| Author | SHA1 | Date | |
|---|---|---|---|
| c5abf60bff | |||
| 75581a9ddc | |||
| 2771b5ea74 | |||
| eeb63fa510 | |||
|
|
06f3129fb9 |
173
public/app.js
173
public/app.js
@@ -1,13 +1,41 @@
|
|||||||
const map = L.map("map").setView([40.7608, -111.8910], 12);
|
|
||||||
|
var streets = L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
|
||||||
|
attribution: '© OpenStreetMap contributors'
|
||||||
|
});
|
||||||
|
|
||||||
L.tileLayer("https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png", {
|
L.tileLayer("https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png", {
|
||||||
attribution: '© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a>',
|
attribution: '© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a>',
|
||||||
}).addTo(map);
|
}).addTo(map);
|
||||||
|
|
||||||
const API_URL = "http://localhost:7653/api/v0/";
|
const API_URL = "http://localhost:7653/api/v0/";
|
||||||
|
const ROUTE_STYLES = {
|
||||||
|
"701": { color: "#0074D9", train: "🔵", stop: "🔹" },
|
||||||
|
"704": { color: "#2ECC40", train: "🟢", stop: "🟩" },
|
||||||
|
"703": { color: "#FF4136", train: "🔴", stop: "🔺" },
|
||||||
|
"750": { color: "#B10DC9", train: "🟣", stop: "🔮" },
|
||||||
|
"720": { color: "#000000", train: "⚪", stop: "🔷" }
|
||||||
|
};
|
||||||
|
|
||||||
const trainEmojiIcon = L.divIcon({ html: "🔵", className: "", iconSize: [64,64], iconAnchor: [16,32], popupAnchor: [0,-32] });
|
|
||||||
const stopsEmojiIcon = L.divIcon({ html: "🫃", className: "", iconSize: [64,64], iconAnchor: [16,32], popupAnchor: [0,-32] });
|
function buildIcon(emoji, bearing) {
|
||||||
|
const svg = `
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32">
|
||||||
|
<text x="50%" y="50%" text-anchor="middle"
|
||||||
|
dominant-baseline="central" font-size="26"
|
||||||
|
font-family="Apple Color Emoji, Segoe UI Emoji, NotoColorEmoji, sans-serif"
|
||||||
|
>
|
||||||
|
${emoji}
|
||||||
|
</text>
|
||||||
|
</svg>`;
|
||||||
|
|
||||||
|
return L.divIcon({
|
||||||
|
html: svg,
|
||||||
|
className: "emoji-icon",
|
||||||
|
iconSize: [32, 32],
|
||||||
|
iconAnchor: [16, 16],
|
||||||
|
popupAnchor: [0, -16]
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
function addMarker(lat, lon, content, icon) {
|
function addMarker(lat, lon, content, icon) {
|
||||||
if (!isNaN(lat) && !isNaN(lon)) {
|
if (!isNaN(lat) && !isNaN(lon)) {
|
||||||
@@ -18,8 +46,13 @@ function addMarker(lat, lon, content, icon) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function getTrainsByRoute(route) {
|
|
||||||
fetch(API_URL + 'vehicles')
|
function drawPolyLine(polylinePoints, color) {
|
||||||
|
L.polyline(polylinePoints, { color, weight: 4, opacity: 0.8 }).addTo(map);
|
||||||
|
}
|
||||||
|
|
||||||
|
function drawLine(route) {
|
||||||
|
fetch(API_URL + "routepaths/" + route)
|
||||||
.then(res => res.json())
|
.then(res => res.json())
|
||||||
.then(data => {
|
.then(data => {
|
||||||
const trains = data.data;
|
const trains = data.data;
|
||||||
@@ -31,6 +64,12 @@ function getTrainsByRoute(route) {
|
|||||||
.catch(err => console.error("Error fetching trains:", err));
|
.catch(err => console.error("Error fetching trains:", err));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function drawLines() {
|
||||||
|
MJR_LINES.forEach(drawLine);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
let stopMarkers = {};
|
||||||
function getStopsByRoute(route) {
|
function getStopsByRoute(route) {
|
||||||
fetch(API_URL + 'stops/' + route)
|
fetch(API_URL + 'stops/' + route)
|
||||||
.then(res => res.json())
|
.then(res => res.json())
|
||||||
@@ -45,5 +84,125 @@ function getStopsByRoute(route) {
|
|||||||
.catch(err => console.error("Error fetching stops:", err));
|
.catch(err => console.error("Error fetching stops:", err));
|
||||||
}
|
}
|
||||||
|
|
||||||
getStopsByRoute("701");
|
let trainMarkers = {};
|
||||||
getTrainsByRoute();
|
let filterType = "all";
|
||||||
|
|
||||||
|
const filterSelect = document.getElementById("filterSelect");
|
||||||
|
if (filterSelect) {
|
||||||
|
filterSelect.addEventListener("change", (e) => {
|
||||||
|
filterType = e.target.value;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function refreshVehicles() {
|
||||||
|
fetch(API_URL + "vehicles")
|
||||||
|
.then(res => res.json())
|
||||||
|
.then(data => {
|
||||||
|
let vehicles = data.data;
|
||||||
|
|
||||||
|
if (filterType === "lrt") {
|
||||||
|
vehicles = vehicles.filter(v => LRT_LINES.includes(v.routeNum) || FRONTRUNNER.includes(v.routeNum));
|
||||||
|
}
|
||||||
|
|
||||||
|
vehicles = vehicles.filter(v => MJR_LINES.includes(v.routeNum));
|
||||||
|
|
||||||
|
Object.keys(trainMarkers).forEach(id => {
|
||||||
|
if (!vehicles.find(v => v.vehicleId == id)) {
|
||||||
|
map.removeLayer(trainMarkers[id]);
|
||||||
|
delete trainMarkers[id];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
vehicles.forEach(v => {
|
||||||
|
const { vehicleId, routeNum, routeName, speed, bearing } = v;
|
||||||
|
const lat = v.location.latitude;
|
||||||
|
const lon = v.location.longitude;
|
||||||
|
const icon = buildIcon(ROUTE_STYLES[routeNum].train, bearing);
|
||||||
|
|
||||||
|
if (!trainMarkers[vehicleId]) {
|
||||||
|
const marker = L.marker([lat, lon], { icon })
|
||||||
|
.bindPopup(`${routeName}<br>Vehicle ${vehicleId}<br>Speed: ${(speed*2.23694).toFixed(1)} mph`)
|
||||||
|
.addTo(map);
|
||||||
|
marker.vehicleData = v;
|
||||||
|
trainMarkers[vehicleId] = marker;
|
||||||
|
} else {
|
||||||
|
if (trainMarkers[vehicleId].slideTo) {
|
||||||
|
trainMarkers[vehicleId].slideTo([lat, lon], { duration: 1000 });
|
||||||
|
} else {
|
||||||
|
trainMarkers[vehicleId].setLatLng([lat, lon]);
|
||||||
|
}
|
||||||
|
trainMarkers[vehicleId].setIcon(icon);
|
||||||
|
trainMarkers[vehicleId].vehicleData = v;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.catch(err => console.error("Error refreshing vehicles:", err));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
let userMarker, accuracyCircle;
|
||||||
|
const ON_BOARD_RADIUS = 50; // meters
|
||||||
|
|
||||||
|
if (navigator.geolocation) {
|
||||||
|
navigator.geolocation.getCurrentPosition(
|
||||||
|
(position) => {
|
||||||
|
const lat = position.coords.latitude;
|
||||||
|
const lon = position.coords.longitude;
|
||||||
|
|
||||||
|
userMarker = L.circleMarker([lat, lon], {
|
||||||
|
radius: 8,
|
||||||
|
fillColor: "#007AFF",
|
||||||
|
color: "#fff",
|
||||||
|
weight: 2,
|
||||||
|
opacity: 1,
|
||||||
|
fillOpacity: 0.9
|
||||||
|
}).addTo(map);
|
||||||
|
userMarker.bindPopup("You are here").openPopup();
|
||||||
|
|
||||||
|
accuracyCircle = L.circle([lat, lon], {
|
||||||
|
radius: position.coords.accuracy,
|
||||||
|
color: "#007AFF",
|
||||||
|
fillColor: "#007AFF",
|
||||||
|
fillOpacity: 0.2
|
||||||
|
}).addTo(map);
|
||||||
|
|
||||||
|
map.setView([lat, lon], 13);
|
||||||
|
},
|
||||||
|
(err) => console.warn("Geolocation error:", err.message),
|
||||||
|
{ enableHighAccuracy: true, timeout: 500, maximumAge: 0 }
|
||||||
|
);
|
||||||
|
|
||||||
|
navigator.geolocation.watchPosition(
|
||||||
|
(position) => {
|
||||||
|
const userLat = position.coords.latitude;
|
||||||
|
const userLon = position.coords.longitude;
|
||||||
|
|
||||||
|
if (userMarker) userMarker.setLatLng([userLat, userLon]);
|
||||||
|
if (accuracyCircle) accuracyCircle.setLatLng([userLat, userLon]).setRadius(position.coords.accuracy);
|
||||||
|
|
||||||
|
const vehicles = Object.values(trainMarkers).map(m => m.vehicleData);
|
||||||
|
let closest = null, minDistance = Infinity;
|
||||||
|
|
||||||
|
vehicles.forEach(v => {
|
||||||
|
const distance = map.distance([userLat, userLon], [v.location.latitude, v.location.longitude]);
|
||||||
|
if (distance < minDistance) {
|
||||||
|
minDistance = distance;
|
||||||
|
closest = v;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (closest && minDistance <= ON_BOARD_RADIUS) {
|
||||||
|
console.log(`User is on vehicle ${closest.vehicleId} (${closest.routeNum})`);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
(err) => console.warn("Geolocation watch error:", err.message),
|
||||||
|
{ enableHighAccuracy: true, maximumAge: 0 }
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
console.warn("Geolocation not supported by this browser.");
|
||||||
|
}
|
||||||
|
|
||||||
|
drawLines();
|
||||||
|
MJR_LINES.forEach(r => getStopsByRoute(r));
|
||||||
|
refreshVehicles();
|
||||||
|
setInterval(refreshVehicles, 1000);
|
||||||
|
|||||||
@@ -6020,7 +6020,7 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"701":
|
"703":
|
||||||
[
|
[
|
||||||
{
|
{
|
||||||
"shape_id": "238255",
|
"shape_id": "238255",
|
||||||
|
|||||||
159
src/dal/postgresDAL.js
Normal file
159
src/dal/postgresDAL.js
Normal file
@@ -0,0 +1,159 @@
|
|||||||
|
import pg from "pg";
|
||||||
|
|
||||||
|
const pool = new pg.Pool({
|
||||||
|
connectionString: "postgresql://nate@localhost:5432/gtfs"
|
||||||
|
});
|
||||||
|
|
||||||
|
async function dbQuery(sql, params = []) {
|
||||||
|
const client = await pool.connect();
|
||||||
|
try {
|
||||||
|
const res = await client.query(sql, params);
|
||||||
|
return res.rows;
|
||||||
|
} finally {
|
||||||
|
client.release();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function toNumber(v) {
|
||||||
|
const n = Number(v);
|
||||||
|
return Number.isFinite(n) ? n : undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export async function getVehicles() {
|
||||||
|
const rows = await dbQuery(
|
||||||
|
`SELECT vehicle_id, route_num, route_name, destination,
|
||||||
|
bearing, speed, latitude, longitude
|
||||||
|
FROM vehicles`
|
||||||
|
);
|
||||||
|
|
||||||
|
return rows.map((v) => ({
|
||||||
|
vehicleId: v.vehicle_id,
|
||||||
|
routeNum: v.route_num,
|
||||||
|
routeName: v.route_name,
|
||||||
|
destination: v.destination,
|
||||||
|
bearing: v.bearing == null ? undefined : toNumber(v.bearing),
|
||||||
|
speed: v.speed == null ? undefined : toNumber(v.speed),
|
||||||
|
location: {
|
||||||
|
latitude: toNumber(v.latitude),
|
||||||
|
longitude: toNumber(v.longitude),
|
||||||
|
},
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function getVehicleById(id) {
|
||||||
|
if (id == null) return null;
|
||||||
|
|
||||||
|
const rows = await dbQuery(
|
||||||
|
`SELECT vehicle_id, route_num, route_name, destination,
|
||||||
|
bearing, speed, latitude, longitude
|
||||||
|
FROM vehicles
|
||||||
|
WHERE vehicle_id = $1`,
|
||||||
|
[String(id)]
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!rows.length) return null;
|
||||||
|
const v = rows[0];
|
||||||
|
|
||||||
|
return {
|
||||||
|
vehicleId: v.vehicle_id,
|
||||||
|
routeNum: v.route_num,
|
||||||
|
routeName: v.route_name,
|
||||||
|
destination: v.destination,
|
||||||
|
bearing: v.bearing == null ? undefined : toNumber(v.bearing),
|
||||||
|
speed: v.speed == null ? undefined : toNumber(v.speed),
|
||||||
|
location: {
|
||||||
|
latitude: toNumber(v.latitude),
|
||||||
|
longitude: toNumber(v.longitude),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export async function getRoutes() {
|
||||||
|
const rows = await dbQuery(`SELECT data FROM routes ORDER BY route_id`);
|
||||||
|
return rows.map((r) => r.data);
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function getRouteById(routeId) {
|
||||||
|
if (routeId == null) return null;
|
||||||
|
|
||||||
|
const rows = await dbQuery(
|
||||||
|
`SELECT data FROM routes WHERE route_id = $1`,
|
||||||
|
[String(routeId)]
|
||||||
|
);
|
||||||
|
|
||||||
|
return rows[0]?.data || null;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export async function getRoutePathsMap() {
|
||||||
|
const rows = await dbQuery(`SELECT route_id, path FROM route_paths`);
|
||||||
|
const map = {};
|
||||||
|
for (const row of rows) {
|
||||||
|
map[String(row.route_id)] = row.path;
|
||||||
|
}
|
||||||
|
return map;
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function getRoutePath(routeId) {
|
||||||
|
if (routeId == null) return null;
|
||||||
|
|
||||||
|
const rows = await dbQuery(
|
||||||
|
`SELECT path FROM route_paths WHERE route_id = $1`,
|
||||||
|
[String(routeId)]
|
||||||
|
);
|
||||||
|
|
||||||
|
return rows[0]?.path || null;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function transformationStationRow(row) {
|
||||||
|
return {
|
||||||
|
stop_id: row.stop_id,
|
||||||
|
stop_code: row.stop_code,
|
||||||
|
stop_name: row.stop_name,
|
||||||
|
stop_desc: row.stop_desc,
|
||||||
|
location: {
|
||||||
|
latitude: toNumber(row.latitude),
|
||||||
|
longitude: toNumber(row.longitude),
|
||||||
|
},
|
||||||
|
stop_url: row.stop_url,
|
||||||
|
location_type: row.location_type,
|
||||||
|
parent_station: row.parent_station,
|
||||||
|
lines: row.lines, // text[]
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function getStationsRaw() {
|
||||||
|
const rows = await dbQuery(`SELECT * FROM stations`);
|
||||||
|
return rows;
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function getStations() {
|
||||||
|
const rows = await dbQuery(`SELECT * FROM stations`);
|
||||||
|
return rows.map(transformationStationRow);
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function getStopsByRoute(routeId) {
|
||||||
|
if (routeId == null) return [];
|
||||||
|
const rows = await dbQuery(
|
||||||
|
`SELECT * FROM stations WHERE lines @> ARRAY[$1]::text[]`,
|
||||||
|
[String(routeId)]
|
||||||
|
);
|
||||||
|
return rows.map(transformationStationRow);
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function getStationById(id) {
|
||||||
|
if (id == null) return null;
|
||||||
|
|
||||||
|
const rows = await dbQuery(
|
||||||
|
`SELECT * FROM stations WHERE stop_id = $1`,
|
||||||
|
[String(id)]
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!rows.length) return null;
|
||||||
|
return transformationStationRow(rows[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -14,6 +14,11 @@ function readJSON(name) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function toNumber(v) {
|
||||||
|
const n = Number(v);
|
||||||
|
return Number.isFinite(n) ? n : undefined;
|
||||||
|
}
|
||||||
|
|
||||||
export function getVehicles() {
|
export function getVehicles() {
|
||||||
const raw = readJSON("vehicles.json");
|
const raw = readJSON("vehicles.json");
|
||||||
|
|
||||||
@@ -26,11 +31,11 @@ export function getVehicles() {
|
|||||||
routeNum: v.routeNum,
|
routeNum: v.routeNum,
|
||||||
routeName: v.routeName,
|
routeName: v.routeName,
|
||||||
destination: v.destination,
|
destination: v.destination,
|
||||||
bearing: v.bearing == null ? undefined : Number(v.bearing),
|
bearing: v.bearing == null ? undefined : toNumber(v.bearing),
|
||||||
speed: v.speed == null ? undefined : Number(v.speed),
|
speed: v.speed == null ? undefined : toNumber(v.speed),
|
||||||
location: {
|
location: {
|
||||||
latitude: loc.latitude == null ? undefined : Number(loc.latitude),
|
latitude: toNumber(loc.latitude),
|
||||||
longitude: loc.longitude == null ? undefined : Number(loc.longitude)
|
longitude: toNumber(loc.longitude)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -59,18 +64,36 @@ export function getRouteById(routeId) {
|
|||||||
return routes.find(r => String(r.route_id) === String(routeId)) || null;
|
return routes.find(r => String(r.route_id) === String(routeId)) || null;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getRoutePathsMap() {
|
function readRoutepathsRaw() {
|
||||||
const raw = readJSON("routepaths.json");
|
const raw = readJSON("routePath.json");
|
||||||
|
|
||||||
if (raw && typeof raw === "object" && !Array.isArray(raw)) return raw;
|
if (!Array.isArray(raw)) return [];
|
||||||
return {};
|
return raw;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getRoutePathsMap() {
|
||||||
|
const raw = readRoutepathsRaw();
|
||||||
|
const map = {};
|
||||||
|
|
||||||
|
for (const item of raw) {
|
||||||
|
if (!item || typeof item !== "object" || Array.isArray(item)) continue;
|
||||||
|
const keys = Object.keys(item);
|
||||||
|
|
||||||
|
if (keys.length !== 1) continue;
|
||||||
|
const k = String(keys[0]);
|
||||||
|
|
||||||
|
if (Array.isArray(item[k])) map[k] = item[k];
|
||||||
|
}
|
||||||
|
|
||||||
|
return map;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getRoutePath(routeId) {
|
export function getRoutePath(routeId) {
|
||||||
if (routeId == null) return null;
|
if (routeId == null) return null;
|
||||||
const map = getRoutePathsMap();
|
const map = getRoutePathsMap();
|
||||||
|
const key = String(routeId);
|
||||||
|
|
||||||
return Object.prototype.hasOwnProperty.call(map, routeId) ? map[routeId] : null;
|
return Object.prototype.hasOwnProperty.call(map, key) ? map[key] : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getStationsRaw() {
|
export function getStationsRaw() {
|
||||||
@@ -93,13 +116,29 @@ export function getStations() {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function transformationStation(s) {
|
||||||
|
return {
|
||||||
|
stop_id: s.stop_id,
|
||||||
|
stop_code: s.stop_code,
|
||||||
|
stop_name: s.stop_name,
|
||||||
|
stop_desc: s.stop_desc,
|
||||||
|
location: { latitude: toNumber(s.stop_lat), longitude: toNumber(s.stop_lon) },
|
||||||
|
stop_url: s.stop_url,
|
||||||
|
location_type: s.location_type,
|
||||||
|
parent_station: s.parent_station,
|
||||||
|
lines: s.lines
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
export function getStopsByRoute(routeId) {
|
export function getStopsByRoute(routeId) {
|
||||||
if (routeId == null) return [];
|
if (routeId == null) return [];
|
||||||
const raw = getStationsRaw();
|
const raw = getStationsRaw();
|
||||||
|
|
||||||
if (raw == null) return [];
|
if (raw == null) return [];
|
||||||
if (typeof raw === "object" && !Array.isArray(raw)) {
|
if (typeof raw === "object" && !Array.isArray(raw)) {
|
||||||
return Array.isArray(raw[routeId]) ? raw[routeId] : [];
|
const arr = raw[routeId];
|
||||||
|
if (!Array.isArray(arr)) return [];
|
||||||
|
return arr.map(transformationStation);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Array.isArray(raw)) {
|
if (Array.isArray(raw)) {
|
||||||
@@ -107,12 +146,12 @@ export function getStopsByRoute(routeId) {
|
|||||||
for (const item of raw) {
|
for (const item of raw) {
|
||||||
if (typeof item === "object" && !Array.isArray(item) && Object.prototype.hasOwnProperty.call(item, routeId)) {
|
if (typeof item === "object" && !Array.isArray(item) && Object.prototype.hasOwnProperty.call(item, routeId)) {
|
||||||
const arr = item[routeId];
|
const arr = item[routeId];
|
||||||
if (Array.isArray(arr)) matchesFromArrayMaps.push(...arr);
|
if (Array.isArray(arr)) matchesFromArrayMaps.push(...arr.map(transformationStation));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (matchesFromArrayMaps.length) return matchesFromArrayMaps;
|
if (matchesFromArrayMaps.length) return matchesFromArrayMaps;
|
||||||
|
|
||||||
return raw.filter(s => Array.isArray(s.lines) && s.lines.map(String).includes(String(routeId)));
|
return raw.filter(s => Array.isArray(s.lines) && s.lines.map(String).includes(String(routeId))).map(transformationStation);
|
||||||
}
|
}
|
||||||
|
|
||||||
return [];
|
return [];
|
||||||
@@ -128,7 +167,7 @@ export function getStationById(id) {
|
|||||||
const arr = raw[key];
|
const arr = raw[key];
|
||||||
if (!Array.isArray(arr)) continue;
|
if (!Array.isArray(arr)) continue;
|
||||||
const found = arr.find(s => String(s.stop_id) === String(id) || String(s.stationId) === String(id));
|
const found = arr.find(s => String(s.stop_id) === String(id) || String(s.stationId) === String(id));
|
||||||
if (found) return found;
|
if (found) return transformationStation(found);
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@@ -139,13 +178,14 @@ export function getStationById(id) {
|
|||||||
for (const item of raw) {
|
for (const item of raw) {
|
||||||
for (const key of Object.keys(item)) {
|
for (const key of Object.keys(item)) {
|
||||||
const arr = item[key];
|
const arr = item[key];
|
||||||
const found = arr.find(s => String(s.stop_id) === String(id) || String(s.stationId) === String(id));
|
const found = arr.find(s => String(s.stop_id) === String(id));
|
||||||
if (found) return found;
|
if (found) return transformationStation(found);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return raw.find(s => String(s.stop_id) === String(id) || String(s.stationId) === String(id)) || null;
|
const found = raw.find(s => String(s.stop_id) === String(id) || String(s.stationId) === String(id));
|
||||||
|
return found ? transformationStation(found) : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
|
|||||||
@@ -14,10 +14,9 @@ router.get("/routes/:routeId", (req, res) => {
|
|||||||
const route = dal.getRouteById(routeId);
|
const route = dal.getRouteById(routeId);
|
||||||
|
|
||||||
if (!route) return res.status(404).json({error: "Route Was Not Found"});
|
if (!route) return res.status(404).json({error: "Route Was Not Found"});
|
||||||
const routePath = dal.getRoutePath(routeId);
|
|
||||||
const stations = dal.getStopsByRoute(routeId);
|
const stations = dal.getStopsByRoute(routeId);
|
||||||
|
|
||||||
res.json({data: {route, routePath, stations}});
|
res.json({data: {route, stations}});
|
||||||
});
|
});
|
||||||
|
|
||||||
router.get("/route/:routeId", (req, res) => {
|
router.get("/route/:routeId", (req, res) => {
|
||||||
@@ -25,10 +24,17 @@ router.get("/route/:routeId", (req, res) => {
|
|||||||
const route = dal.getRouteById(routeId);
|
const route = dal.getRouteById(routeId);
|
||||||
|
|
||||||
if (!route) return res.status(404).json({error: "Route Was Not Found"});
|
if (!route) return res.status(404).json({error: "Route Was Not Found"});
|
||||||
const routePath = dal.getRoutePath(routeId);
|
|
||||||
const stations = dal.getStopsByRoute(routeId);
|
const stations = dal.getStopsByRoute(routeId);
|
||||||
|
|
||||||
res.json({data: {route, routePath, stations}});
|
res.json({data: {route, stations}});
|
||||||
|
});
|
||||||
|
|
||||||
|
router.get("/routepaths/:routeId", (req, res) => {
|
||||||
|
const routeId = req.params.routeId;
|
||||||
|
const rp = dal.getRoutePath(routeId);
|
||||||
|
|
||||||
|
if (!rp) return res.status(404).json({error: "RoutePath Was Not Found"});
|
||||||
|
res.json({meta: {routeId: String(routeId), returned: Array.isArray(rp) ? rp.length : 0}, data: rp});
|
||||||
});
|
});
|
||||||
|
|
||||||
router.get("/routes/:routeId/stations", (req, res) => {
|
router.get("/routes/:routeId/stations", (req, res) => {
|
||||||
|
|||||||
Reference in New Issue
Block a user