// ----------------------------------------------------------------------------------
// Learning Team D
// Members:
// Tyson DeWitt
// Ryan Edwards
// Andrew Soren
// Pablo Urbanowicz
// Richard Williams
// CS 1410 8 am
// Learning Team Assignment # 2
// Mr. Rague
// Due: 03/03/09
// Version: 1.3
// ----------------------------------------------------------------------------------
// This program allows the user to input various data relating to a
// possible student's schedule in a possible university.
// ----------------------------------------------------------------------------------
//
// ----------------------------------------------------------------------------------
// Change Control Section
// ----------------------------------------------------------------------------------
// Team Member: Andrew Soren
// Version: 1.0
// Date: 02/28/09
// Created class CCourse or Part One of the assignment.
//
// Team Member: Ryan Edwards
// Version: 1.1
// Date: 02/28/09
// Created and added class CDocument or Part Two of the assignment to code.
//
// Team Member: Richard Williams
// Version: 1.2
// Date: 03/01/09
// Created and added class CView or Part Three of the assignment to code.
//
// Team Member: Pablo Urbanowicz
// Version: 1.3
// Date: 03/02/09
// Created and added main function or Part Four of the assignment to code.
// Also modified CView class by adding a constructor to accept CDocument object
//
// Team Member: Pablo Urbanowicz
// Version: 1.4
// Date: 03/03/09
// Added comments throughout the code, general tidying up.
//
// Team Member: Andrew Soren
// version: 1.5
// Date: 03/03/09
// Modified the inCCourse method to call strCourse (thus receiving a string), test
// the received string, and to go back through the loop (so the user can re-enter
// the data) if the string exceeds 80 characters.
// ----------------------------------------------------------------------------------
//
// Required libraries
#include <iostream>
#include <iomanip>
#include <string>
#include <math.h>
#include <sstream>
#include <vector>
using namespace std;
// -----------------------------------------------------------------
// This class represents a course that can is taught at a university.
// It holds information about each course, such as the year and time
// being taught, etc.
//
// Version 1.1
// -----------------------------------------------------------------
class CCourse
{
private:
int year, // Stores the calendar year
room, // Room number
beginTime, // Start time
endTime, // End time
meetingDays; // Days class meets on
string term, // Term of course
courseNumber, // Sourse number
sectionNumber, // Section number
building; // Building name
string & toUPPER(string & str); // Convert strings to all upper case
int checkAP(int & h, int & m, char & t); // Used to check validity of entered times
void inBTime(); // Inputs beginning time
void inETime(); // Inputs end time
string dispMeetDay(); // Converts/displays meetingDays into string/human readable form.
string dispTime(int mTime); // Converts beginTime and endTime to a string - used when displaying
public:
CCourse(int yr = 2009, int rm = 100, int bT = 1200, int eT = 1200, int mD = 0, string trm = "SPRING", string cNum = "def101", string sNum = "def", string b = "Office")
:year(yr), room(rm), beginTime(bT), endTime(eT), term(trm), courseNumber(cNum), sectionNumber(sNum), building(b), meetingDays(mD)
{} // Constructor - sets defaults for everything
string inCCourse(); // Input method which calls all other input methods
void inYear(); // Prompt asks for user to input a year
void inYear(int yer); // Allows the programmer/developer to use a different method than the above
void inRoom(); // Prompt asks for user to input a room number
void inRoom(int rom); // Allows programmer/developer to use different method than the above
void inTime(); // Prompt akss user to input start and end times
void inTime(int bTime, int eTime); // Allows programmer to use alternate method than above
void inMeetDays(); // Prompt asks user to input days for class
void inMeetDays(int days); // Allows programmer to use alternate method than above (not recommended - at all)
void inTerm(); // Prompt asks user for term
void inTerm(string tr); // Allows use of alternate method than above
void inCNum(); // Prompt asks user for course number
void inCNum(string crsNum); // Alternate from above available
void inSNum(); // Prompt asks user for section number
void inSNum(string secNum); // Alternate from above
void inBuilding(); // Prompt user for building name
void inBuilding(string build); // Alternate method
void dispCourse(); // Display the CCourse data to the console
string strCourse(); // Convert CCourse data into an 80 character string
};
// -----------------------------------------------------------------
// This class represents a list of courses that are taught at a
// university.
//
// Version 1.2
// -----------------------------------------------------------------
class CDocument
{
public:
CDocument(): list() {} //Default constructor
vector <string> list; //Vector to hold the list of courses(strings)
void createList(); //Initializes the list to being clear
void insertItem(string, int); //Allows user to insert a course in the list
bool deleteItem(int); //Allows user to delete a course in the list
int frontOfList(); //Returns location of first course in the list
int backOfList(); //Returns location of last course in the list
bool moveToNextItem(int); //Determines whether user switch to next item or not
bool moveToPrevItem(int); //Determines whether the user can switch to previous item or not
void showCurrentItem(int); //Displays the current item on the list
};
// -----------------------------------------------------------------
// This class allows the list of courses to be displayed on the
// screen
//
// Version 1.1
// -----------------------------------------------------------------
class CView
{
private:
vector <string> cvlist; //Holds the list of courses
public:
CView(CDocument list) : cvlist(list.list) {}; //Constructor, sets cvlist to the list in the CDocument class
void ViewPage(); //Shows first page of list and gives user menu to switch between pages
void NextPage(int); //Goes to the next page of the document
};
// -----------------------------------------------------------------
// This function displays a menu when it is called from the
// main function
//
// Version 1.0
// -----------------------------------------------------------------
void showMenu()
{
//Display menu
cout << "\n(I) Insert a new course in the list" << endl;
cout << "(E) Delete a course from the list" << endl;
cout << "(F) Move to the beginning of the list" << endl;
cout << "(B) Move to the end of the list" << endl;
cout << "(N) Move to the next course in the list" << endl;
cout << "(P) Move to the previous course in the list" << endl;
cout << "(R) Display the current course in the list" << endl;
cout << "(S) Save changes and return to the main menu" << endl << endl;
}
// -----------------------------------------------------------------
// This function uses the CCourse, CDocument, and CView classes to
// manage and view the contents of a list of CCourse type items.
//
// Version 1.2
// -----------------------------------------------------------------
int main()
{
string data; //Holds information about the course inputted by user
int countCourses = 0; //Keeps track of how many courses are on the list
int userChoice; //Holds user's choice for root menu
char command='x'; //Holds user's choice for build course menu
CCourse course; //Creates an instance of CCourse to hold course's information
CDocument theList; //Creates an instance of CDocument to hold courses in a list
theList.createList(); //Clears the contents of the list just created
int lineNum = -1; //Holds the current line being worked on
bool response; //Holds boolean value of whether it was possible to move to the next or previous line in the list
bool response2; //Holds boolean value of whether it was possible to move to delete a line in the list
//Display an introduction
cout << "This program allows a user to create a list of courses offered at a university," << endl;
cout << "including information about each course,such as: the year and term being taught,course number, time, etc." << endl << endl;
do
{
//Root menu, prompt user for choice
cout << "1) Build course list" << endl;
cout << "2) View course list" << endl;
cout << "3) Quit application" << endl << endl;
cout << "Please select an option: ";
cin >> userChoice;
switch(userChoice)
{
case 1:
{
//Shows "build course list" menu
showMenu();
//While the command is not 's' or stop
while(command != 's')
{
//Prompt user
cout << "If at any time you would like to see the menu again, type the letter M below" << endl;
cout << "Please select an option by typing the letter next to the choice: ";
cin >> command;
switch (command)
{
case 'I':
case 'i':
{
//No more than 100 courses can be inputted
if(countCourses <= 99)
{
cout << "\nYou will now be prompted to enter the course information.\n" << endl;
//Get information of course from user, and return all data put in as a string
data = course.inCCourse();
//Calls CCourse function to return string of all data put in a single line
// data = course.strCourse();
//Insert the string just received into the list
theList.insertItem(data,lineNum);
cout << endl;
//Add one to the number courses on the list
countCourses +=1;
//Add one to the current line number
lineNum += 1;
}
//When user has tried to input more than 100 courses
if(countCourses > 99)
cout << "Sorry, but you have exceeded the maximum of 100 courses." << endl << endl;
break;
}
case 'E':
case 'e':
{
//Get boolean value to see if it was possible to remove the course from the list or not
response2 = theList.deleteItem(lineNum);
//If it was removed
if(response2==true)
{
//Subtract one from the current line
lineNum-=1;
//Subtract one from the total courses on the list
countCourses -=1;
}
break;
}
case 'F':
case 'f':
{
//Current line value gets switched with first position on the list
lineNum = theList.frontOfList();
//Display confirmation movement has occurred
cout << "\nMovement to front of the list done" << endl << endl;
break;
}
case 'B':
case 'b':
{
//Current line value gets switched with last position on the list
lineNum = theList.backOfList();
//Display confirmation that movement has occurred
cout << "\nMovement to end of the list done" << endl << endl;
break;
}
case 'N':
case 'n':
{
//Get boolean value to see if it is possible to move to next course on the list
response = theList.moveToNextItem(lineNum+1);
if(response==true)
{
//Add one to current line to point to next item
lineNum +=1;
//Display confirmation
cout << "\nMovement to next item on list done" << endl << endl;
}
break;
}
case 'P':
case 'p':
{
//Get boolean value to see if it is possible to move to previous course on the list
response = theList.moveToPrevItem(lineNum-1);
if(response==true)
{
//Subtract from current line to point to previous item
lineNum -=1;
//Display confirmation
cout << "\nMovement to previous item on list done" << endl << endl;
}
break;
}
case 'R':
case 'r':
{
//Show the item which the current line number points to
theList.showCurrentItem(lineNum);
break;
}
case 'M':
case 'm':
{
//Display menu on screen
showMenu();
break;
}
case 'S':
case 's':
{
//Print a space, command is stop
cout << endl;
break;
}
default:
{
//If not a valid choice
cout << "Invalid choice. Please try again" << endl;
break;
}
}
}
command='x';
break;
}
case 2:
{
cout << endl;
//Create an instance of the CView class with the CDocument theList
CView list2(theList);
//Call funcction in CView to view pages
list2.ViewPage();
cout << endl;
break;
}
case 3:
//Quit program
break;
default:
//Invalid choice
cout << "\nInvalid choice. You must select a value in the range of 1-3" << endl << endl;
break;
}
}
while(userChoice != 3);
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
string & CCourse::toUPPER(string & str) // converts strings to all upper case
{
for(unsigned int i=0; i < str.length(); i++)
{
str[i] = toupper(str[i]);
}
return str;
}
string CCourse::inCCourse() // input method used to call all input methods at once
{
int error=0;
string data;
while(error==0)
{
inYear(); // Input year
inTerm(); // Input Term
inCNum(); // Input course Number
inSNum(); // Input sectionNumber
inBuilding(); // Input building name
inRoom(); // Input room number
inTime(); // Input beginning and end time
inMeetDays(); // Input meeting days
data = strCourse(); // if all the data above added together as a string is less than 80 characters
if(data.length() < 80){ // unset the error flag, to exit the loop.
// cout << "Data is good" << endl;
error=1;}
else // else, inform the user that the data exceeds 80 characters, and have them re-enter the data
{
cout << "The total characters you have entered exceeds the maximum allowed " << endl;
cout << "of 80 characters. Please re-input the data." << endl;
error=0;
}
}
return data;
}
void CCourse::inYear() // Year input method (simple, I know. Could be better?)
{
cout << "Input the calendar year: ";
cin >> year;
}
void CCourse::inYear(int yer)
{
year = yer;
}
void CCourse::inRoom() // Room input (see Year)
{
cout << "Input the room number: ";
cin >> room;
}
void CCourse::inRoom(int rom)
{
room=rom;
}
void CCourse::inBTime() // Input beginningTime
{
int hour, min, check=0; // initilize error flag
char time;
while(check==0)
{
cout << "Input the beginning time (ex: '10:00a'): ";
cin >> hour >> time >> min >> time;
if(hour>12 || min>59) // Minor error checking for hours and minutes
{
cout<< "Invalid time. Please try again." << endl;
hour=0;
min=0;
continue;
}
beginTime = checkAP(hour, min, time); // Checks the status of 'time' (AM or PM)
if(beginTime < 2400) // CheckAP returns 2400 if there is an error
check=1; // if there's an error, don't unset the error flag
}
}
void CCourse::inETime() // Same as above, but replace "beginTime" with "endTime"
{
int hour, min, check=0;
char time;
while(check==0)
{
cout << "Input the end time (ex: '12:00p'): ";
cin >> hour >> time >> min >> time;
if(hour>12 || min>59){
cout<< "Invalid time. Please try again." << endl;
hour=0;
min=0;
continue;
}
endTime = checkAP(hour, min, time);
if(endTime < 2400)
check=1;
}
}
void CCourse::inTime(int bTime, int eTime)
{
beginTime = bTime;
endTime = eTime;
}
void CCourse::inTime() // Calls input methods for beginTime and endTime
{
inBTime();
inETime();
}
void CCourse::inTerm() // Input method for term - minor error checking
{
int error=0;
while(error==0) // Loop until correct data provided
{
cout << "Input the term: ";
cin >> term;
term = toUPPER(term);
if(!(term.compare("WINTER")) || !(term.compare("SPRING")) || !(term.compare("SUMMER")) || !(term.compare("FALL")))
error=1; // unset error flag if term matches WINTER, SPRING, SUMMER, or FALL
else
cout << "Please use valid terms (WINTER, SPRING, SUMMER, FALL)" << endl;
}
// cout << term << endl;
}
void CCourse::inTerm(string tr)
{
term=tr;
}
void CCourse::inCNum() // Input course number (simple, I know. Does it need improvement?)
{
cout<< "Input the course number: ";
cin >> courseNumber;
}
void CCourse::inCNum(string crsNum)
{
courseNumber = crsNum;
}
void CCourse::inSNum() // Input section number (see inCNum)
{
cout << "Input the section number: ";
cin >> sectionNumber;
}
void CCourse::inSNum(string secNum)
{
sectionNumber=secNum;
}
void CCourse::inBuilding() // Input building name. This should also clear the buffer.
{
cout << "Input the building name: ";
cin.clear();
cin.ignore(25, '\n');
getline(cin, building);
}
void CCourse::inBuilding(string build)
{
building=build;
}
void CCourse::inMeetDays() // this is largely gathered by talking with my dad (excluding error checking)
{ // the display uses bit compares, thus my method of storage
string input; // User input is stored by this string
char days[] = "MTWRFS"; // char array. User input is compared against this.
meetingDays = 0; // Make sure that you start with a clean slate (it has problems otherwise)
int counter, error=0; // error flag
while(error==0) // loop until correct data is received
{
cout << "Input the days the class meets (ex:'MWF' or 'tr'): ";
cin >> input;
input = toUPPER(input); // convert to upper case
for(unsigned int i=0; i < input.length(); i++)
{
counter = 0;
while(counter < 7) // Used a while loop instead of for loop due to error checking
{
if(counter>=6) // if counter reaches 6, the character being checked (from user input) does not match a day of the week)
{
cout << "Invalid day" << endl;
meetingDays=0; // reset meetingDays in preparation to receive new user input
error=0; // set error flag (just to be sure)
break; // exit the loop now
}
else if(input[i]==days[counter])
{
meetingDays += static_cast<int>(pow(2.0,(static_cast<double>(counter))));
error=1; // receive good data, disable the error flag
break; // exit the loop (don't increase the counter)
}
counter++;
}
if(error==0) // exit the loop so the user can input good data
break;
}
// cout << input << " " << days << " " << meetingDays << endl;
}
}
void CCourse::inMeetDays(int days)
{
meetingDays=days;
}
string CCourse::dispMeetDay() // used to display meetingDays
{
string days=""; // create an empty string
if((1 & meetingDays) == 1) // if bit '1' is on,
days += 'M'; // add "M" to days
if((2 & meetingDays) == 2) // if bit '2' is on,
days += 'T'; // add "T" to days
if((4 & meetingDays) == 4) // if bit '4' is on,
days += 'W'; // add "W" to days
if((8 & meetingDays) == 8) // if bit '8' is on
days += 'R'; // add "R" (thuRsday) to days
if((16 & meetingDays) == 16) // if bit '16' is on,
days += 'F'; // add "F" to days
if((32 & meetingDays) == 32) // if bit 32 is on,
days += 'S'; // add "S" (Saturday, just in case) to days
// cout << days << endl;
return days;
}
void CCourse::dispCourse() // Simply outputs to the console
{
cout << year << " " << term << " " << courseNumber << " " << sectionNumber << " " << building << " " << room << " " << dispTime(beginTime) << " " << dispTime(endTime) << " " << dispMeetDay() << endl;
}
string CCourse::strCourse() // This outputs all the CCourse data/variables into a string
{
stringstream out;
string courseData;
out << year << ", " << term << ", " << courseNumber << ", " << sectionNumber << ", " << building << ", " << room << ", " << dispTime(beginTime) << ", " << dispTime(endTime) << ", " << dispMeetDay();
courseData = out.str();
// courseData.resize(79);
return courseData;
}
int CCourse::checkAP(int & h, int & m, char & t) // used for checking whether it's morning or afternoon
{
int checker;
switch(t)
{
case 'a': // If AM,
case 'A':
checker = h*100; // convert to military time
checker+=m; // add minutes
if(checker>=1200) // If user entered 12am,
checker-=1200; // then subtract 1200, to get 12 midnight
break;
case 'p': // if PM,
case 'P':
h+=12; // add 12 hours
checker = h*100; // so that conversion to military time is correct
checker+=m; // add minutes
if(checker>=2400) // If user entered 12pm,
checker-=1200; // subtract 1200 to get 12 noon.
break;
default: // User did not enter a valid "AM" or "PM" specifier
cout << "You didn't specify am or pm" << endl;
return 2400; // It should never reachre 2400 or higher normally, so use this as the error flag
break;
}
return checker;
}
string CCourse::dispTime(int mTime) // Displays beginTime and endTime (which are stored in military time)
{ // into standard time format (with AM and PM specifiers)
stringstream out;
int hour, min; // string time should be changed somewhere in here. If it remains
string time="If you see this, that's bad"; // unchanged, something went wrong. This should not happen.
if(mTime < 100) // If mTime < 100 (thus less than 1 am)
{
mTime += 1200; // add 1200 to it to convert back to 12 midnight
min = mTime % 100; // get minutes by getting remainder
hour = mTime / 100; // get hours by division
out << hour << ":" << setfill('0') << setw(2) << min << "a"; // output to stringstream object (with an "am" designation), to insert into a string later
}
else if(mTime >= 1300) // If mTime >= 1300 (thus more than or equal to 1 pm)
{
mTime -= 1200; // subtract 1200, to convert it back to standard time units
min = mTime % 100; // same as above (line 354)
hour = mTime / 100; // same as above (line 355)
out << hour << ":" << setfill('0') << setw(2) << min << "p"; // same as above (line 356), with a "pm" designation
}
else if(mTime >= 100 && mTime < 1200) // if mTime is greater than or equal to 1 am, but less than 12 pm
{ // it's already in the correct units,
min = mTime % 100; // but still needs minutes
hour = mTime / 100; // and hours
out << hour << ":" << setfill('0') << setw(2) << min << "a"; // same as above (line 356)
}
else if(mTime >= 1200 && mTime < 1300) // If it's 12 in the afternoon, or later (but not yet 1 pm or later)
{ // do essentially the same as above
min = mTime % 100;
hour = mTime / 100;
out << hour << ":" << setfill('0') << setw(2) << min << "p"; // but designate as "pm"
}
time = out.str();
return time;
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void CDocument::createList()
{
//Clear all values on the list
list.clear();
}
void CDocument::insertItem(string courseData, int line)
{
//Insert an item on the list
list.insert(list.begin()+(line+1),courseData);
}
bool CDocument::deleteItem(int line)
{
//If the size of the list is less than or equal to 0 or the line is less than 0
//a course can't be deleted
if((line-1)<0 && list.size()<=0)
{
cout << "\nThere are no courses to delete" << endl << endl;
return false;
}
//Delete a course from the list and display which line was deleted
else
{
list.erase(list.begin()+(line));
cout << "\nLine #" << line+1 << " was deleted" << endl << endl;
return true;
}
}
int CDocument::frontOfList()
{
//Position of first course
return 0;
}
int CDocument::backOfList()
{
//Position of last course
return ((int)list.size()-1);
}
bool CDocument::moveToNextItem(int line)
{
//If the current line is larger than the size of the list or the size of the list is less than or equal to 0
//then you can't move to a next line (return false)
if(line>(int)list.size()-1 || (int)list.size()<=0)
{
cout << "\nYou're at the end of the list\n" << endl;
return false;
}
//It is possible to go to the next course in list
else
return true;
}
bool CDocument::moveToPrevItem(int line)
{
//If current is less than then you can't go to previous line
if(line < 0)
{
cout << "\nYou're at the beginning of the list\n" << endl;
return false;
}
//It is possible to go to previous course in list
else
return true;
}
void CDocument::showCurrentItem(int line)
{
//If current is greater than 0 then display course in that position
if(line >= 0)
{
cout << "\n" << list[line] << "\n" << endl;
}
//If current line is less than 0 and the size of the list is greater than 0
//then display course in that position
if(line < 0 && list.size() > 0)
{
cout << "\n" << list[line+1] << "\n" << endl;
}
//If current line is less than 0 and the size of the list is less than or equal to 0
//then there are no courses to display
if(line<0 && list.size()<=0)
{
cout << "\nThere are no courses in the list" << endl << endl;
}
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void CView::ViewPage()
{
//Set the size of the list to 100 lines
cvlist.resize(100);
//Set initial page #1
int page = 1;
//Print what's on page 1
NextPage(page);
//Holds user's choice for menu options
char command = 'x';
while(command != 'Q' && command != 'q')
{
cout << "\n(N) Move to next page on the list" << endl;
cout << "(P) Move to the previous page on the list" << endl;
cout << "(Q) Return to the main menu" << endl << endl;
cout << "Please select an option: ";
cin >> command;
cin.ignore();
//If the page number is ever greater than 5, then it's set back to 5
//as it can't be greater than 5
if(page > 5)
page = 5;
//If the page number is ever less than 0, then it's set back to 1
//as it can't be less than 1
if(page < 0)
page = 1;
switch(command)
{
case 'N':
case 'n':
{
//Add one to page
page++;
cout << endl;
//Display contents of page
NextPage(page);
break;
}
case 'P':
case 'p':
{
//Subtract one from page
page--;
cout << endl;
//Display contents of page
NextPage(page);
break;
}
case 'Q':
case 'q':
{
//Go back to root menu
break;
}
}
}
}
void CView::NextPage(int page)
{
//Display courses 1-20
if(page <= 1)
{
cout << "You are currently on the first page (Courses 1-20)" << endl;
for(int i = 0; i <= 19; i++)
{
//If there isn't a course on that line then skip
if(cvlist[i]=="\0")
continue;
//Otherwise print info
else
cout << cvlist[i] << endl;
}
}
//Display courses 20-39
if(page == 2)
{
cout << "You are currently on the second page (Courses 21-40)" << endl;
for(int i = 20; i <= 39; i++)
{
//If there isn't a course on that line then skip
if(cvlist[i]=="\0")
continue;
//Otherwise print info
else
cout << cvlist[i] << endl;
}
}
//Display courses 40-59
if(page == 3)
{
cout << "You are currently on the third page (Courses 41-60)" << endl;
for(int i = 40; i <= 59; i++)
{
//If there isn't a course on that line then skip
if(cvlist[i]=="\0")
continue;
//Otherwise print info
else
cout << cvlist[i] << endl;
}
}
//Display courses 61-80
if(page == 4)
{
cout << "You are currently on the fourth page (Courses 61-80)" << endl;
for(int i = 60; i <= 79; i++)
{
//If there isn't a course on that line then skip
if(cvlist[i]=="\0")
continue;
//Otherwise print info
else
cout << cvlist[i] << endl;
}
}
//Display courses 81-100
if(page >=5)
{
cout << "You are currently on the last page (Courses 81-100)" << endl;
for(int i = 80; i <= 99; i++)
{
//If there isn't a course on that line then skip
if(cvlist[i]=="\0")
continue;
//Otherwise print info
else
cout << cvlist[i] << endl;
}
}
}