#include <iostream.h>
#include <conio.h>
#include <fstream.h>
#include <stdlib.h>
#include <dos.h> // for "delay"
#include <ctype.h> // for "toupper"
#include <stdio.h> // for "getchar"
#define TRUE 1
#define FALSE 0
const int MAXPHOTOCELLNUMBER = 16;
const int MAXTURNOUTS = 6;
const int CLOCKWISE = 1;
const int COUNTERCLOCKWISE = 0;
const int BATCH = 1;
const int INTERACTIVE = 0;
const int MAXTRAINS = 10;
char turnouts[MAXTURNOUTS];
char tempturnouts[MAXTURNOUTS];
int trackmanager[MAXPHOTOCELLNUMBER];
int trackchange[MAXPHOTOCELLNUMBER];
int tomanager[MAXTURNOUTS];
int tochange[MAXTURNOUTS];
class Train{
public:
Train();
int speed;
int maxspeed;
int directionaroundtrack;
char direction;
int phas;
int pnext;
int headlightbool;
int taillightbool;
int id;
int tohas;
char lastcommand[15];
int blockingpc;
int blockingto;
};
//********** Node definition - Used by the "List" class
class Node {
public:
Node(int, int, char);
int photocell;
int turnout;
int changedirection;
char switchdirection;
Node * link;
};
Node::Node(int pc = 0, int to = -1, char sd = 'n'){
//*************************************************************
// Constructor - initialize the node
//*************************************************************
photocell = pc;
turnout = to;
switchdirection = sd;
}
//********** List class
class List {
public:
List(); // Create the list
void Add(int pc, int to, char sd);
void FindNext(int&, int&);
int FindCount();
//void Delete(string keyval);
void Print();
void Load();
void Save();
void clear();
private:
Node *top; // pointer to top of the list.
}; // List
Train::Train(){
direction = 'f';
directionaroundtrack = COUNTERCLOCKWISE;
phas = 12;
pnext = 6;
tohas = -1;
id = -1;
blockingto = -1;
blockingpc = -1;
}
List::List() {
//************************************************
// Create a new list
//************************************************
top = new Node(-1,-1,'s');
if (top==NULL){
cout << "Out of Memory... Program will close down";
getch();
exit(123);
}
top->link = top; // circle header list
} // List
//page
void List::Add (int pc, int to, char sd){
//*******************************************************************
// Creates a new node on the list from data in
// "keyval" and "commentval".
//*******************************************************************
Node *x; // points to new node
x = new Node(pc, to ,sd);
if (x==NULL){
cout << "Out of memory... Program will shut down";
getch();
exit(123);
}
x-> link = top->link;
top-> link = x;
} // Add
/*void List::Delete(string keyval) {
//*******************************************************************
// Deletes the node with "keyval" from this list.
//*******************************************************************
Node *prev, *p; // used for tag along
prev=top;
p=top-> link;
while (p!=top){
if (p->key == keyval){
prev-> link =p -> link;
delete p;
cout << keyval << " was deleted";
return;
}
prev=p;
p=p->link;
}
cout << keyval << " was not found in list";
getch();
} // Delete
*/
//page
void List::Print() {
//***********************************************************************
// Prints (shows) the contents of the list onto the screen.
//***********************************************************************
Node *p;
int nlines; // line counter
int items; // counts number of items in list
char opt;
// clrscr();
cout << " L I S T D A T A\n\n";
p = top->link;
nlines = 2;
items = 0;
while (p != top) {
// List the next item
nlines++; items++;
cout << p->photocell << " " << p->turnout << " " << p->changedirection
<< " " << p->switchdirection << "\n";
// Check if screen is full
if (nlines % 22 == 0) {
cout << "\nMore? "; opt = getch();
opt = toupper(opt);
if (opt == 'N') return;
}
// Advance to next item in the list
p = p->link;
} //while
cout << "\nThere are " << items << " items in the list.";
cout << " Press <cr> to continue... ";
getch();
cout << endl;
} //Print
int List::FindCount() {
Node *p;
int items = 0; // counts number of items in list
p = top->link;
while (p != top) {
// List the next item
items++;
p = p->link;
} //while
return items;
} //findcount
int FindCountList(List list){
return list.FindCount();
}
/*
//page
void AddTo(List &list){
//************************************************************************
// Requests data from user and adds this data to the list.
// Continues until an "empty" key field is input.
//************************************************************************
string keyval, commentval;
// clrscr();
do {
cout << "\nEnter KEY value (return to quit) "; get_line(cin, keyval);
if (keyval != "") {
cout << "Enter COMMENT field "; get_line(cin, commentval);
// Add to the list
list.Add(keyval, commentval);
} // if
} while (keyval != "");
} //Add
*/
/*
//page
void DeleteFrom(List &list){
//************************************************************************
// Deletes the node specified by the user. The key field of the
// node is input from the user.
//************************************************************************
string keyval, commentval;
clrscr();
do {
cout << "\nEnter KEY value to delete (return to quit) ";
get_line(cin, keyval);
if (keyval != "") {
// delete from the list
list.Delete(keyval);
} // if
} while (keyval != "");
} //Delete
*/
/*
//page
void Load(List &list) {
//***********************************************************************
// Adds to the existing list by loading data from a file and adding
// this data to the list.
//***********************************************************************
ifstream df;
string fname;
string line1, line2;
char tempname[80];
int done;
char ans;
//********** Obtain the input data file
do {
done = 1;
cout << "\nEnter name of file to load "; getline(cin, fname);
//--- Insure file exists
cp_cstring(tempname, fname, 80);
df.open(tempname, ios::in);
if (!df) {
done = 0;
cout << "\n" << fname << " does not exist. Try again (y/n)? ";
ans = getchar();
ans = toupper(ans);
if (ans == 'N') {
cout << "\nLoad not performed.\n";
return;
}; // if
}; //if
} while (!done);
getline(df,line1);
if (df.eof()){
cerr << "File is empty...";
getch();
df.close();
return;
}
getline(df,line2);
if (df.eof()){
cerr << "comment value is blank";
getch();
df.close();
return;
}
while (!df.eof()){
list.Add(line1,line2);
getline(df,line1);
if (df.eof())
break;
getline(df,line2);
}// end while
cout << "File has been loaded onto list... Press <Enter>";
getch();
df.close();
} //Load
*/
//int fexists(string filename){
/************************************************************************
returns true if the file already exists
*************************************************************************/
/* ifstream df;
char temp[80];
cp_cstring(temp,filename,80);
df.open(temp, ios::in);
if (df) {df.close(); return 1;}
else {df.close(); return 0;}
}
*/
//page
/*
void List::Save() {
//***********************************************************************
// Saves the current list unto a file. The file name is requested
// from the user.
//***********************************************************************
Node *p;
ofstream fout;
char fname[80]; // temp for filename
string filename;
char ans;
clrscr();
do {
cout << "Enter the filename to save to: ";
get_line(cin, filename);
if (!fexists(filename)) break;
cout << filename << " already exists. Overwrite? ";
cin >> ans;
if (ans=='Y' || ans=='y') break;
readln();
}
while (1);
cp_cstring (fname,filename,80);
fout.open(fname);
p = top->link;
while (p != top) {
// List the next item
fout << p->key << endl << p->comment << "\n";
p = p->link;
} //while
fout << endl;
fout.close();
cout << "Save done... Press <Enter>";
getch();
} //Save
*/
List CW[MAXPHOTOCELLNUMBER];
List CC[MAXPHOTOCELLNUMBER];
Train TrainList[MAXTRAINS];
void List::clear() {
/**************************************************************************
clears all members of the current list
***************************************************************************/
Node *p,*prev; // for tag along
prev=top;
p = top->link;
top-> link = top;
while (p != top) {
// Advance to next item in the list
prev=p;
p = p->link;
delete prev;
} //while
cout << "List has been cleared... Press <Enter>" << endl;
getch();
}// end clear
void toggledir(int & dir){
if (dir == CLOCKWISE)
dir = COUNTERCLOCKWISE;
else
dir = CLOCKWISE;
}
void toggleto(int to){
if (tomanager[to] != 0){
cout << "Cannot toggle turnout "<< to << " because it is under os control" << endl;
return;
}
if (turnouts[to] == 's'){
turnouts[to] = 'c';
tempturnouts[to] = 'c';
}
else
{
turnouts[to] = 's';
tempturnouts[to] = 's';
}
}
Train * FindTrain(int id1){
for (int i = 0; i< MAXTRAINS; i++){
if (TrainList[i].id == id1)
return &TrainList[i];
}
return NULL;
}
void toggletempto(int to){
if (tempturnouts[to] == 's'){
tempturnouts[to] = 'c';
}
else
{
tempturnouts[to] = 's';
}
}
void AddNewTrain(int id1, int & next){
if (id1 > 0 && FindTrain(id1) == NULL){
if (trackmanager[12] == 0 && trackmanager[6] == 0){
Train T;
T.id = id1;
TrainList[next] = T;
next++;
trackmanager[12] = id1;
trackmanager[6] = id1;
}
else
cout << "Cannot Add Train right now Train blocking " << endl;
}
else{
cerr << "Error invalid id number--must be positive and unique" << endl;
return;
}
}
void List::FindNext(int & nextphotocell, int & nextto){
Node * p;
p = top->link;
if (p->turnout == -1){
nextphotocell = p->photocell;
nextto = p->turnout;
}
else
{
if (p->switchdirection == tempturnouts[p->turnout]){
nextphotocell = p->photocell;
nextto = p->turnout;
}
else
{
if (p->link == top){
nextphotocell = -1; //p->photocell;
nextto = p->turnout;
}
else{
p = p->link;
if (p->switchdirection == tempturnouts[p->turnout]){
nextphotocell = p->photocell;
nextto = p->turnout;
}
else{
nextphotocell = -1;
nextto = -1;
}
}
}
}
}
void GetNext(Train *thistrain, int read, int & pc, int & to){
if (thistrain->directionaroundtrack == CLOCKWISE)
CW[read].FindNext(pc, to);
else
CC[read].FindNext(pc, to);
}
void ToggleMode(int& mode){
if (mode == BATCH){
mode = INTERACTIVE;
cout << "mode changed to interactive" << endl;
}
else{
mode = BATCH;
cout << "mode changed to batch " << endl;
}
}
void PrintTurnoutStatus(){
for (int i= 0 ; i< MAXTURNOUTS;i++)
cout << "turnout " << i << " is " << turnouts[i] << endl;
}
int CheckResourceAvail(int pc, int to){
if (trackmanager[pc] == 0){
if (to != -1){
if (tomanager[to] == 0){
return TRUE;
}
else{
return FALSE;
}
}
else {
return TRUE;
}
}
else {
return FALSE;
}
}
void UpdateResources(Train * T, int pc, int to){
trackmanager[T->phas] = 0;
tomanager[T->tohas] = 0;
T->phas = T->pnext;
T->pnext = pc;
T->tohas = to;
trackmanager[T->phas] = T->id;
trackmanager[T->pnext] = T->id;
if (to != -1){
tomanager[to] = T->id;
}
}
void PrintResourceTables(){
cout << "TrackMananger" << endl;
for (int j= 0; j < MAXPHOTOCELLNUMBER; j++){
cout << "photocell " << j << " is: " << trackmanager[j] << endl;
}
cout << "PressKey" << endl;
getch();
cout << "TO Manager" << endl;
for (j = 0; j< MAXTURNOUTS; j++){
cout << "turnout " << j << " is: " << tomanager[j] << endl;
}
cout << "PressKey" << endl;
getch();
}
void PrintTrackGraphs(){
for (int i = 0; i<MAXPHOTOCELLNUMBER; i++){
CW[i].Print();
CC[i].Print();
}
}
void SetUpToTables(){
turnouts[0] = 's';
turnouts[1] = 's';
turnouts[2] = 's';
turnouts[3] = 'c';
turnouts[4] = 'c';
turnouts[5] = 'c';
tempturnouts[0] = 's';
tempturnouts[1] = 's';
tempturnouts[2] = 's';
tempturnouts[3] = 'c';
tempturnouts[4] = 'c';
tempturnouts[5] = 'c';
}
void SetUpToAllocationTables(){
for (int j = 0; j<MAXPHOTOCELLNUMBER; j++)
trackmanager[j] = 0;
for (j = 0; j< MAXTURNOUTS; j++)
tomanager[j] = 0;
for (j = 0; j< MAXPHOTOCELLNUMBER; j++)
trackchange[j] = 0;
for (j = 0; j< MAXTURNOUTS; j++)
tochange[j] = 0;
}
void SetUpTrackGraphs(){
CW[0].Add(2,1,'s');
CW[1].Add(2,1,'c');
CW[2].Add(7,-1,'n');
CW[3].Add(1,0,'s');
CW[4].Add(5,-1,'n');
CW[5].Add(6,-1,'n');
CW[6].Add(12,-1,'n');
CW[7].Add(15,2,'s');
CW[8].Add(0,-1,'n');
CW[9].Add(3,-1,'n');
// CW[10].Add(-1,-1,'n');
CW[11].Add(6,-1,'n');
CW[12].Add(15,2,'c');
CW[13].Add(8,4,'s');
CW[13].Add(9,4,'c');
CW[14].Add(11,-1,'n');
CW[15].Add(13,3,'s');
CW[15].Add(14,3,'c');
CC[0].Add(8,-1,'n');
CC[1].Add(3,0,'s');
CC[2].Add(1,1,'c');
CC[2].Add(0,1,'s');
CC[3].Add(9,-1,'n');
CC[4].Add(6,-1,'n');
CC[5].Add(4,-1,'n');
CC[6].Add(5,-1,'n');
CC[7].Add(2,-1,'s');
CC[8].Add(13,4,'s');
CC[9].Add(13,4,'c');
// CC[10].Add(-1,-1,-1,'n');
CC[11].Add(14,-1,'n');
CC[12].Add(6,-1,'n');
CC[13].Add(15,3,'s');
CC[14].Add(15,3,'c');
CC[15].Add(7,2,'s');
CC[15].Add(12,2,'c');
}
void PrintMenu(){
cout << endl;
cout << "-1: to exit program" << endl;
cout << "0-15: to signal that turnout has been covered" << endl;
cout << "16: to toggle a turnout" << endl;
cout << "17: to toggle the direction of a train" << endl;
cout << "18: to add a new train to the course" << endl;
cout << "19: to toggle the mode between BATCH and INTERACTIVE" << endl;
cout << "20: to print the turnout status" << endl;
cout << "21: for the menu" << endl;
}
void swap(int & x, int & y){
int temp = x;
x = y;
y = temp;
}
//page
void main() {
int dir = CLOCKWISE;
int pc;
int to;
int next = 0;
int read;
int thistrainid;
int resgood;
int good = TRUE;
int mode = INTERACTIVE;
int id;
SetUpToTables();
SetUpToAllocationTables();
SetUpTrackGraphs();
Train * thistrain;
cout << "Welcome to Train OS Version 0.1" << endl;
cout << "Enter Command Number 21 for menu" << endl;
cout << "Please enter id for the initial train on the track: ";
cin >> id;
AddNewTrain(id, next);
cout << "Enter command number (21 for menu): " ;
cin >> read;
while (read != -1){
if (read == 6){
thistrainid = trackmanager[6];
thistrain = FindTrain(thistrainid);
if (thistrain == NULL){
cerr << "Error in operating system Train Was not found";
getch();
exit(123);
}
if (thistrain->phas == 11){
to = -1;
pc = 5;
}
else if (thistrain->phas == 12 ){
to = -1;
pc = 4;
}
else if (thistrain->phas == 5 ){
to = -1;
pc = 11;
}
else if (thistrain->phas == 4 ){
to = -1;
pc = 12;
}
toggledir(thistrain->directionaroundtrack);
}
else if (read == 16){
cout << "Which turnout: " ;
cin >> to;
toggleto(to);
cout << "turnout " << to << " is " << turnouts[to] << endl;
if (tochange[to] != 0){
cout << "system is checking to see if any trains can be woken up" << endl;
id = tochange[to];
thistrain = FindTrain(id);
GetNext(thistrain, thistrain->pnext, pc, to);
cout << "Next PC: " << pc << " Next TO: " << to << endl;
goto here;
}
cout << "Enter command number (21 for menu): " ;
cin >> read;
continue;
}
else if (read == 17){
cout << "Which train id to switch direction: " << endl;
cin >> id;
thistrain = FindTrain(id);
if (thistrain == NULL){
cerr << "Error in operating system Train Was not found";
getch();
exit(124);
}
toggledir(thistrain->directionaroundtrack);
swap(thistrain->phas, thistrain->pnext);
cout << "direction switched to " << thistrain->directionaroundtrack << endl;
cout << "Enter command number (21 for menu): " ;
cin >> read;
continue;
}
else if (read == 18){
cout << "New Train id: " ;
cin >> id;
AddNewTrain(id, next);
cout << "Enter command number (21 for menu): " ;
cin >> read;
continue;
}
else if (read == 19){
ToggleMode(mode);
cout << "Enter command number (21 for menu): " ;
cin >> read;
continue;
}
else if (read == 20){
PrintTurnoutStatus();
cout << "Enter command number (21 for menu): " ;
cin >> read;
continue;
}
else if (read == 21){
PrintMenu();
cout << "Enter command number (21 for menu): " ;
cin >> read;
continue;
}
else{
thistrainid = trackmanager[read];
thistrain = FindTrain(thistrainid);
if (thistrain == NULL){
cerr << "Error in operating system Train Was not found" << endl;
getch();
exit(125);
}
GetNext(thistrain, read, pc, to);
}
cout << "Train " << thistrain->id << " Next PC: " << pc << " Next to: " << to << endl;
here:
if (pc == -1 && mode == BATCH){
toggletempto(to);
GetNext(thistrain, read, pc, to);
cout << "Next PC after adjustment: " << pc << " Next to: " << to << endl;
resgood = CheckResourceAvail(pc, to);
if (resgood){
cout << "System found that toggling turnout in batch mode is safe...toggling to " << to;
toggleto(to);
if (tochange[to] != 0){
cout << "Checking if system can wake up any trains" << endl;
}
UpdateResources(thistrain, pc, to);
}
else{
cout << "Resources Not Available" << endl;
PrintResourceTables();
}
}
else if (pc == -1 && mode == INTERACTIVE){
cout << "stop the train due to turnout in position that makes" << endl
<< "further travel impossible. Please toggle turnout " << to << endl;
tochange[to] = thistrain->id;
}
else if (pc != -1){
resgood = CheckResourceAvail(pc, to);
if (resgood){
UpdateResources(thistrain, pc, to);
}
else{
cout << "Resources Not Available" << endl;
PrintResourceTables();
}
}
cout << "Would you like to see the resource tables" << endl;
if (toupper(getch()) == 'Y'){
PrintResourceTables();
}
cout << "Enter command number (21 for menu): " ;
cin >> read;
}
}// main