104.131.42.27
Restart project4:
Issue Report:
Cause of Project 4 Malfunction:
I uploaded both the complete `dynamic-web` folder (which contains Project 4) and a standalone version of Project 4 to the server, and subsequently ran the same code for both instances. This resulted in a port conflict. I resolved this by using `pm2` to terminate and remove all running projects. I then reopened the port specifically for the project located within the `dynamic-web` folder, while simultaneously modifying the `server.js` and `main.js` files.
Repair final project:
The current version of server.js still imports fs and path, and contains a large amount of loadDemoData logic, which should not be kept.
The database is currently storing user IP/request logs, but this should be replaced with a favorites feature for users.
My project is not just a webpage, but a project that uses a webpage to explain the entire system.
I built a clear and intuitive UI using HTML/CSS, and when the frontend (app.js) sends requests, my Node.js backend (server.js) not only acts as a bridge to communicate with the official MTA API, but also processes the data and sends usable information back to the user in a readable way.
I introduced NeDB to provide persistent data storage, allowing users to save their favorite subway lines/stations instead of storing temporary request logs.
server.js
MTA Data Middleware(22-63)
Leveraging official MTA data and AI, I completed the process of translating binary code into JSON documents.
“GtfsRealtimeBindings.transit_realtime.feedMessage.decode(...)
Data Cleaning & Transformation(41-55)
if(entity.tripUpdate && ...)Filtered for useful train information.
/api/favorites POST
When a user clicks "Add to Favorites" on the webpage, `db.insert(req.body)` saves the data to the `favorites.db` file on the server's hard drive.
/api/favorites GET
When the user clicks the "My Favorites" button, `db.find({})` retrieves and lists the saved data from the file.
app.js
With the assistance of AI, I implemented a progressively enhanced web page—moving from HTML to CSS and finally to JS—demonstrating the specific role each file plays as the user interacts with the page.
HTMLBtn:Display the raw structure on the page.
CSSBtn:Toggle the style using `body.classList.add("styled")`.
JSBtn:Activate Listener
await()The subsequent code will not be executed until the complete, usable data has been transmitted.
// 1. Declare this as an asynchronous function.
serverBtn.addEventListener("click", async () => {
// 2. Write logic just like synchronous code: wait for the data to return.
const response = await fetch(`/api/mta?feed=${latestFeed}`);
// 3. Proceed to the next step only after the JSON parsing is complete.
const data = await response.json();
// 4.Render
renderResults(data.arrivals);
});