/************************************************************************************************************************* File: train.js Purpose: This file contains the class definition for a train to be used in the view. The main reason to use this class instead of just using a raw object gleaned from a JSON string from the server is that this class implements a Draw function that is capable of displaying the train to the view by calling a single line in sketch.js. References: Daniel Shiffman - The Coding Train - "Classes in JavaScript with ES6": https://www.youtube.com/watch?v=T-HGdc8L-7w P5.JS Reference - https://p5js.org/reference/ Written by John McGorey - Spring 2019 - Using Microsoft visual Studio Code 2019 For use in the St. Norbert College CSCI460 Senior Capstone Experience **************************************************************************************************************************/ class Train { constructor(trainInfo) { /*************************************************************************************** Function: constructor Purpose: Takes a train object from the server & converts it into this Train object so that its Draw() function can be used. Input: trainInfo - An object containing the information for the train that is sent as a JSON string from the server. It is marshalled into an object from the string before being passed to this constructor. ****************************************************************************************/ // Get the rail info this.rail_id = trainInfo.rail_id; this.rail_type = trainInfo.rail_type; // Get the postion this.x = trainInfo.x; this.y = trainInfo.y; this.vertical_direction = trainInfo.vertical_direction; this.horizontal_direction = trainInfo.horizontal_direction; this.orientation = trainInfo.orientation; // Set the rest of the train attributes this.id = trainInfo.train_id; this.speed = trainInfo.speed; this.progress = trainInfo.progress; this.status = trainInfo.status; } SetPosition(trainInfo) { /*************************************************************************************** Function: SetPosition Purpose: Takes a train object from the server & pulls out just the information about the train's position Input: trainInfo - An object containing the information for the train that is sent as a JSON string from the server. It is marshalled into an object from the string before being passed to this function. ****************************************************************************************/ this.x = trainInfo.x; this.y = trainInfo.y; this.vertical_direction = trainInfo.vertical_direction; this.horizontal_direction = trainInfo.horizontal_direction; this.orientation = trainInfo.orientation; } UpdateStatus(trainInfo) { /*************************************************************************************** Function: UpdateStatus Purpose: Takes a train object from the server & pulls out just the train's status information from it Input: trainInfo - An object containing the information for the train that is sent as a JSON string from the server. It is marshalled into an object from the string before being passed to this function. ****************************************************************************************/ this.speed = trainInfo.speed; this.progress = trainInfo.progress; this.status = trainInfo.status; } SetRail(trainInfo) { /*************************************************************************************** Function: SetRail Purpose: Takes a train object from the server & pulls out just the information about the rail that the train is on. Input: trainInfo - An object containing the information for the train that is sent as a JSON string from the server. It is marshalled into an object from the string before being passed to this function. ****************************************************************************************/ this.rail_id = trainInfo.rail_id; this.rail_type = trainInfo.rail_type; } Draw() { /*************************************************************************************** Function: Draw Purpose: Draws the train to the canvas according to its properties. The train follows different paths based on the orientation of the rail it is on and depending on whether the rail is a turnout or not, or if the train has derailed. Currently, an active train is displayed as a white circle with it's ID displayed inside of it, and a derailed train is displayed as a red circle. Note: I took a bit of a shortcut on the turnout portion of this Draw function and broke encapsulation by reaching directly into the turnouts array to get the status of the turnout if the Train was on one. This could be solved by restructuring how the Turnout, Train, and Rail objects house their data, but with the way I made my data I backed myself into the corner of having to do it this way. ****************************************************************************************/ // Get the positioning of the train let x = 30 + 50 * this.x; let y = 30 + 50 * this.y; let orientation = this.orientation; let change = 50 * this.progress / 100; // The amount of progress the train has made on the current rail //stroke(55, 55, 55); strokeWeight(1); if (this.rail_type == "rail") { // Draw the train on a rails switch(this.orientation % 4) { case 0: // Left & right if (this.horizontal_direction == 1) // Going right x += change; else // Going left x += 50 - change; // Start on the right and go left break; case 1: // Down Left & Up right if (this.horizontal_direction == 1) {// Going right x += change; y += 50 - change; } else { // Going left x += 50 - change; y += change; } break; case 2: // Up & down if (this.vertical_direction == 1) // Going UP { y += 50 - change; } else { // Going down y += change; } break; case 3: // Up left & down right if (this.horizontal_direction == 1) { // Going right x += change; y += change; } else { // Going left x += 50 - change; y += 50 - change; } break; } } else if (this.rail_type == "turnout") { // Draw the train on a turnout let turnout = turnouts[this.rail_id]; let status = turnout.status; // Get the turnout status, STRAIGHT, CURVED, or MOVING orientation = turnout.orientation; // Get the turnout orientation switch(orientation) { case 0: // \‾ if (status == "STRAIGHT") { if (this.horizontal_direction == 1) x += change; // Start at left & move right else x += 50 - change; // Start at right & move left } else if (status == "CURVED") { if (this.horizontal_direction == 1) { x += change; // Start at left & move right y += change; // Start at top & move down } else { x += 50 - change; // Start at left & move right y += 50 - change; // Start at bottom & move up } } break; case 1: // /_ if (status == "STRAIGHT") { if (this.horizontal_direction == 1) { x += change; // Start at left & go right y += 50; // Move on the bottom of the 'square' } else { x += 50 - change; // Start at right & go left y += 50; // Move on the bottom of the 'square' } } else if (status == "CURVED") { if (this.horizontal_direction == 1) { x += change; // Start at left & go right y += 50 - change; // Start at bottom & go up } else { x += 50 - change; // Start at right & go left y += change; // Start at top & go down } } break; case 2: // |/ if (status == "STRAIGHT") { if (this.vertical_direction == 1) { // Going up y += 50 - change; // Start at bottom & go up } else { // Going down y += change; // Start at top & go down } } else if (status == "CURVED") { if (this.horizontal_direction == 1) { // Going right (& up) x += change; // Start left & go right y += 50 - change; // Start at bottom & go up } else { // Going left (& down) x += 50 - change; // Start right & go left y += change; // Start at top & go down } } break; case 3: // _\ if (status == "STRAIGHT") { if (this.horizontal_direction == 1) { x += change; // Start at left & go Right y += 50; // Move on bottom of the 'square' } else { x += 50 - change; // Start at right & go left y += 50; // Move on the bottom of the 'square' } } else if (status == "CURVED") { if (this.horizontal_direction == 1) { x += change; // Start at left & go right y += change; // Start at top & go down } else { x += 50 - change; // Start at right & go left y += 50 - change; // Start at bottom & go up } } break; case 4: // ‾/ if (status == "STRAIGHT") { if (this.horizontal_direction == 1) { x += change; // Start at left & go right } else { x += 50 - change; // Start at right & go left } } else if (status == "CURVED") { if (this.horizontal_direction == 1) { x += change; // Start at left & go right y += 50 - change; // Start at bottom & go up } else { x += 50 - change; // Start at right & go left y += change; // Start at top & go downs } } break; case 5: // /| if (status == "STRAIGHT") { if (this.vertical_direction == 1) { x += 50; // Rail on right edge of 'box' y += 50 - change; // Start at bottom & go up } else { x += 50; // Rail on right edge of 'box' y += change; // Start at top & go down } } else if (status == "CURVED") { if (this.horizontal_direction == 1) { // Right & up x += change; // Start at left & go right y += 50 - change; // Start at bottom & go up } else { // Left & Down x += 50 - change; // Start at right & go left y += change; // Start at top and go down } } break; case 6: // \| if (status == "STRAIGHT") { if (this.vertical_direction == 1) { // UP y += 50 - change; // Start at bottom & go up x += 50; // Rail aligned to right side of 'box' } else { // DOWN y += change; // Start at top & go down x += 50; // Rail alligned to right side of 'box' } } else if (status == "CURVED") { if (this.horizontal_direction == 1) { // Right & Down x += change; // Start at left & go right y += change; // Start at top & go down } else { // Left & Up x += 50 - change; // Start at right & go left y += 50 - change; // Start at bottom & go up } } break; case 7: // |\ if (status == "STRAIGHT") { if (this.vertical_direction == 1) { // UP y += 50 - change; // Start at bottom & go up } else { // DOWN y += change; // Start at top & go down } } else if (status == "CURVED") { if (this.horizontal_direction == 1) { // Right & Down x += change; // Start at left & go right y += change; // Start at top & go down } else { // Left & Up x += 50 - change; // Start at right & go left y += 50 - change; // Start at bottom & go up } } break; } } // Draw the circle if (this.status !== "DERAILED") // Display the train as a white circle where it is on the track { stroke(0, 0, 0); fill(255, 255, 255); circle(x, y, 25); noFill(); text(this.id + '', x, y); } if (this.status == "DERAILED") { // Display the train as a red circle at the x & y cordinates where it derailed fill(255, 0, 0); circle(x, y, 25); noFill(); text(this.id + '', x, y); } } }