/********************************************************
* Copyright (C) 2008 Course Scheduler Team
*
* This program is free software; you can redistribute it and/or modify it under the terms of
* the GNU General Public License as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with this program;
* if not, write to:
* Free Software Foundation, Inc.
* 59 Temple Place, Suite 330,
* Boston, MA 02111-1307 USA
********************************************************/
/*********************************************************
* Course Scheduler
* File: Section.java
*
* Contains classes:
*
* Section:
*
* Purpose: To store section information for
* databasing the courses
*
* @author Mike Reinhold
*********************************************************/
package Scheduler; //define the package for this class
/********************************************************
* Import Serializable class to allow for class to be
* serialized for storage
* Import LinkedList class for storage of section corequisites
* Import Iterator class for walking through LinkedList with ease
*********************************************************/
import java.io.Serializable; //import Serializable class
import java.util.ArrayList;
import java.util.List;
/********************************************************
* Class: Section
*
* @purpose To store Section information for databasing
* the Sections
*
* @see Cloneable, Serializable, Comparable
*********************************************************/
public class Section implements Cloneable, Serializable, Comparable<Section>{
//implements clone, compareTo, serialize, and deserialize methods
private static final String[] invalidTimes = new String[]{"TBA", "", " ", "12:00-12:00am"};
private static ArrayList<String> invalid; {
invalid = new ArrayList<String>();
for(String item: invalidTimes){
invalid.add(item);
}
}
/********************************************************
* The following are private fields for the Section Instance
*********************************************************/
private int crn; //course request number of section
private String section; //section identifier
private Prof instructor; //section instructor
private Period period; //section meeting period
private String location; //section meeting location
private int seats; //section open seats
private boolean isClosed; //section is closed
private String courseID; //course identifier
private String perceivedCourse; //perceived course
private String credit; //course credit value
private String title; //course title
private String notes; //course special notes
private double rating; //section rating
CourseType type; //type of the section
private boolean secondary; //secondary signal
private Period secPeriod; //secondary period
private String secLocation; //secondary location
private List<String> instructorList; //list of instructor names, used to retrieve the actual instructor
/********************************************************
* The following are public static constants in the Section
* class
*********************************************************/
/********************************************************
* UPDATE SERIAL VERSION IN VERSION WHEN THIS FILE CHANGES
********************************************************/
protected static final long versionID = 2013010900044L;//serial ID
protected static final long serialVersionUID =1L +
Version.section.id;//serial ID
/********************************************************
* @purpose Sets Section defaults and creates space for the fields
*********************************************************/
public Section(){
crn = 0; //set the default values for a new section
courseID = new String(""); //to the logical vaues, 0 for crn, empty
section = new String(""); //strings for the courseID and section id.
credit = "4"; //Most courses are 4 credit, the title and
title = new String(""); //instructor should be empty, the days by
instructor = new Prof(); //are false, the time Period is also
period = new Period(); //there are no open seats, the section is
location = new String(""); //closed
perceivedCourse = new String("");
seats = 0;
isClosed = true;
notes = new String();
rating = 0;
secondary = false;
secPeriod = new Period();
secLocation = new String();
instructorList = new ArrayList<>();
}
/*********************************************************
* @purpose Create another Section that is the same as this
* Section
*
@param Section other: the section to clone
*********************************************************/
public Section(Section other){
this.setCRN(other.getCRN()); //build a new Section based on the
this.setCourseID(new String(other.getCourseID()));
this.setPeriod(other.getPeriodPer().clone()); //other section by setting the fields
this.setSection(new String(other.getSection())); //of the new instance to the fields of
this.setCredit(other.getCredit()); //the other instance. This uses the set
this.setTitle(new String(other.getTitle())); //and get methods of each item.
this.setInstructor(new Prof(other.getInstructor()));
this.setLocation(new String(other.getLocation()));
this.setSeats(other.getSeats());
this.setNotes(new String(other.getNotes()));
this.setRating(other.getRating());
this.setType(other.getType());
this.setSecondary(other.hasSecondary());
this.setSecPeriod(other.getSecPeriodPer().clone());
this.setSecLocation(new String(other.getSecLocation()));
this.setInstructorList(new ArrayList<>(other.getInstructorList()));
}
/*********************************************************
* @purpose Clone the instance of Section
*
* @return Section: a deep clone of this instance
*********************************************************/
@Override
public Section clone(){
return new Section(this); //deep clone this instance and return
}
/*********************************************************
* @purpose return this Section as a string
*
* @return String: the section as a string
*********************************************************/
@Override
public String toString(){
return new String(this.perceivedCourse + " " + this.section +
" [" + this.instructor + "]"); //return section as a string
}
/**
* @return the instructorList
*/
public List<String> getInstructorList() {
return instructorList;
}
/**
* @param instructorList the instructorList to set
*/
public void setInstructorList(List<String> instructorList) {
this.instructorList = instructorList;
}
/*********************************************************
* @purpose Returns if the section is closed
*
* @return boolean: if the section is closed
*********************************************************/
public boolean isClosed(){
return this.isClosed; //return if closed
}
/*********************************************************
* @purpose Sets the section CRN
*
* @param int requestNum: the CRN to associate with the section
*********************************************************/
public void setCRN(int requestNum){
this.crn = requestNum; //set crn
}
/*********************************************************
* @purpose Set course ID for the instance
*
* @param String courseID: the course ID as a string
*********************************************************/
public void setCourseID(String courseID){
this.courseID = courseID; //set to courseID
}
/*********************************************************
* @purpose Set the section ID for the section
*
* @param String section: the section ID as a string
*********************************************************/
@SuppressWarnings("fallthrough")
public void setSection(String section){
this.section = section; //set to section
char end = section.charAt(section.length()-1);
switch(end){
case 'L':{}
case 'D':{}
case 'W':{}
case 'C':{this.perceivedCourse = new String(this.courseID + end + ""); break;}
default:{this.perceivedCourse = new String(this.courseID);}
}
}
/*********************************************************
* @purpose Set the instance's credit value
*
* @param int credits: the number of credits for the section
*********************************************************/
public void setCredit(String credits){
this.credit = credits; //set credit value
}
/*********************************************************
* @purpose set the section's title
*
* @param String title: the title of the section
*********************************************************/
public void setTitle(String title){
this.title = title; //set to title
}
/*********************************************************
* @purpose Set the section instance's instructor
*
* @param Prof prof: the instructor for the course
*********************************************************/
public void setInstructor(Prof prof){
this.instructor = prof; //set to prof
}
/*********************************************************
* @purpose set the days the section uses
*
* @param Boolean[] days: a string array where days[monday] is monday
* etc. and days[monday] is true when the section meets on
* Monday
*
* @return boolean: if the days were set
*********************************************************/
public boolean setDays(boolean[] days){
if (days.length != Day.friday.value()+1){ //verify that the days array is of valid size
return false; //if invalid return false for changes made
}
this.period.setDays(days); //boolean array of days
return true;
}
/*********************************************************
* @purpose set the section instance's period
*
* @param String period: the period as a string in the from of
* HH:MM-HH:MMam or HH:MM-HH:MMpm
*
* @return boolean: if the period was successfully set
*********************************************************/
public boolean setPeriod(String period){
this.period = new Period(); //get new period
return this.period.setPeriod(period); //set to new period based on string
}
/*********************************************************
* @purpose set the section instance's period
*
* @param Period period: the period to set to
*********************************************************/
public void setPeriod(Period period){
this.period = period; //set the period
}
/*********************************************************
* @purpose Set the location of the section
*
* @param String locale: the section location
*********************************************************/
public void setLocation(String locale){
this.location = locale; //set location for the section to string
} //for the location
/*********************************************************
* @purpose set the number of open seats in the section
*
* @param int open: the number of open seats in the section
*
* @return boolean: if the int open is valid
*********************************************************/
public boolean setSeats(int open){
if (open >= 0){ //validate the number of open seats as positive
this.seats = open; //set number of seats
this.isClosed = open == 0 ? true : false; //set the isClosed bool based on the number of seats
return true; //return valid change
}
return false; //return invalid change
}
/*********************************************************
* @purpose Return the course request number
*
* @return int: the instance crn
*********************************************************/
public int getCRN(){
return this.crn; //return the value of the crn
}
/*********************************************************
* @purpose Returns the section course ID
*
* @return String: the course ID of the section
*********************************************************/
public String getCourseID(){
return this.courseID; //get the course id
}
/*********************************************************
* @purpose Returns the section ID of the current section
*
* @return String: the section ID of the instance
*********************************************************/
public String getSection(){
return this.section; //return section id
}
/*********************************************************
* @purpose Returns the section's credit value
*
* @return int: the section's credit value
*********************************************************/
public String getCredit(){
return this.credit; //return value of credit
}
/*********************************************************
* @purpose Return the section's title
*
* @return String: the title of the section
*********************************************************/
public String getTitle(){
return this.title; //return title
}
/*********************************************************
* @purpose return the section's instructor
*
* @return Prof: the instructor of the section
*********************************************************/
public Prof getInstructor(){
return this.instructor; //return instructor
}
/*********************************************************
* @purpose Returns the days that the section meets as a
* boolean array
*
* @return boolean[]: the days that the class meets where
* days[monday] is true if the section meets on monday
*********************************************************/
public boolean[] getDaysBool(){
return this.period.getDays(); //return clone of days bool array
}
/*********************************************************
* @purpose Returns if the section meets on the specified day
*
* @param int day: the day to return if meeting
*
* @return boolean: if the section meets on that day
*********************************************************/
public boolean sectionMeetsOnDay(Day day){
if (day.value() < Day.monday.value() || day.value() > Day.friday.value()){//return if the section meets on a specific
return false; //day is invalid return false
}
return this.period.getDays()[day.value()]; //day is valid return if section meets
}
/*********************************************************
* @purpose Returns the days that the section meets as a
* string array where if the class meets in monday then
* result[Section.monday] = "M" and if not is " "
* etc
*
* @return String[]: Containing which days the section meets
*********************************************************/
public String[] getDaysStrArr(){
String[] result = new String[Day.values().length];//return the days that the section meets
result[Day.monday.value()] = this.period.getDays()[Day.monday.value()] ? "M" : " "; //as a string arrawy where " " means the
result[Day.tuesday.value()] = this.period.getDays()[Day.tuesday.value()] ? "T" : " ";//section does not meet, and a character
result[Day.wednesday.value()] = this.period.getDays()[Day.wednesday.value()] ? "W" : " ";//representing the day means that the
result[Day.thursday.value()] = this.period.getDays()[Day.thursday.value()] ? "R" : " ";//section does meet. Returned as a new
result[Day.friday.value()] = this.period.getDays()[Day.friday.value()] ? "F" : " "; //string array
return result;
}
/*********************************************************
* @purpose Returns the days that the section meets as a
* single string. Example for monday, thursday, friday
* returns "M RF".
*
* @return String: The days of the week that the section meets
*********************************************************/
public String getDaysStr(){
String[] temp = getDaysStrArr(); //return the days the section meets as
String res = new String(); //a single string by concat-ing the
res = temp[Day.monday.value()] + temp[Day.tuesday.value()] +//chars that represent the days
temp[Day.wednesday.value()] + temp[Day.thursday.value()] +
temp[Day.friday.value()]; //together
return res;
}
/*********************************************************
* @purpose Return a the section's period
*
* @return Period: This section's period
*********************************************************/
public Period getPeriodPer(){ //returns the section's period
return this.period;
}
/*********************************************************
* @purpose Return the period as a string
*
* @return String: the period as a string
*********************************************************/
public String getPeriodStr(){
return this.period.toString(); //returns the period's string
} //representation
/*********************************************************
* @purpose Return the location of the section
*
* @return String: The location of the section
*********************************************************/
public String getLocation(){
return this.location; //return the section's location
}
/*********************************************************
* @purpose Returns the number of open seats in a section
*
* @return int: The number of open seats
*********************************************************/
public int getSeats(){
return this.seats; //return the number of open seats
}
/*********************************************************
* @purpose Returns the number of open seats in a section
*
* @return String: The number of open seats
*********************************************************/
public String getSeatsStr(){
return (this.seats == 0) ? "Closed" : Integer.toString(this.seats); //return the number of open seats
} //return the number of open seats as a string
/*********************************************************
* @purpose Returns the comparison between this section
* and the item based first on course id and then second
* on section id.
*
* @param Section item: the sectionto compare this item to
*
* @return int: the result of the comparison, LESS, EQUAL, MORE
*********************************************************/
public int compareTo(Section item){
int courseComp = this.getCourseID().compareTo(item.getCourseID());
int sectionComp = this.getSection().compareTo(item.getSection());
return (courseComp == Compare.equal.value()) ? sectionComp : courseComp;
} //compare Sections by course ID then by section id
/*********************************************************
* @purpose Sets the special section notes
*
* @param String notes: The special notes for the section
*********************************************************/
public void setNotes(String notes){
this.notes = notes; //setnotes
}
/*********************************************************
* @purpose Returns the special notes for the section
*
* @return String: the special notes
*********************************************************/
public String getNotes(){
return this.notes; //return the notes
}
/*********************************************************
* @purpose Return the perceived course ID
*
* @return String: The perceived courseID
*********************************************************/
public String getPerceivedCourse(){
return this.perceivedCourse; //return the perceived course id
}
/*********************************************************
* @purpose Set the perceived course id
*
* @param String perceived course: The perceived courseID
*********************************************************/
public void setPerceivedCourse(String perceivedCourse) {
this.perceivedCourse = perceivedCourse;
}
/*********************************************************
* @purpose Determine if one section conflicts with another
* on a time basis
*
* @param Section other: the section to compare this section to
*
* @return boolean: if the sections conflict
*********************************************************/
public boolean conflictsWith(Section other){
boolean conflict = false; //boolean for if conflict
if(this.hasSecondary() && other.hasSecondary()){//if secondary sessions
conflict |= this.getSecPeriodPer().conflictsWith(other.getSecPeriodPer());//set conflict
}
if(this.hasSecondary()){ //for secondary vs regular
conflict |= this.getSecPeriodPer().conflictsWith(other.getPeriodPer());//set conflict
}
if(other.hasSecondary()){ //for regular vs secondary
conflict |= this.getPeriodPer().conflictsWith(other.getSecPeriodPer());//set conflict
}
//for conflict regular vs regular || other
return conflict || this.getPeriodPer().conflictsWith(other.getPeriodPer()); //return period confliction
}
/*********************************************************
* @purpose returns the rating for the section
*
* @return double: the course rating
*********************************************************/
public double getRating() {
return this.rating; //return value of the rating
}
/*********************************************************
* @purpose sets the section rating to the specified value
*
* @param double rating: the double to set this sections rating to
*********************************************************/
public void setRating(double rating) {
this.rating = rating; //sets the value of the rating
}
/********************************************************
* @purpose rerates the section
*********************************************************/
public void reRate(){
Rate.reRate(this); //rerate the section
}
/********************************************************
* @purpose compares two sections via their rating
*
* @param Section other: the section to compare to this section
*
* @return int: the comparison as Compare.(result).value()
*********************************************************/
public int compareRating(Section other){
return (this.rating == other.rating) ? Compare.equal.value() :
((this.rating < other.rating) ? Compare.less.value() : Compare.more.value());
} //return the comparison based on rating
/********************************************************
* @purpose compares two sections via their time
*
* @param Section other: the section to compare to this section
*
* @return int: the comparison as Compare.(result).value()
*********************************************************/
public int compareTime(Section other){
return this.getPeriodPer().getStartTime().compareTo(
other.getPeriodPer().getStartTime());
} //return the comparison based on start time
/********************************************************
* @purpose Returns if the section has a secondary time
*
* @return boolean: if the section has a secondary time
*********************************************************/
public boolean hasSecondary() {
return secondary; //return the time
}
/********************************************************
* @purpose Sets if the section has a secondary time
*
* @param boolean secondary: if the section has a secondary time
*********************************************************/
public void setSecondary(boolean secondary) {
this.secondary = secondary; //set that the section has a second time
}
/********************************************************
* @purpose Returns the secondary period
*
* @return Period: the secondary period
*********************************************************/
public Period getSecPeriodPer() {
return secPeriod; //return the period
}
/********************************************************
* @purpose Returns the second period as a string
*
* @return String: the second period's period string
*********************************************************/
public String getSecPeriodStr(){
return secPeriod.toString(); //return the period string
}
/********************************************************
* @purpose Sets the secondary period
*
* @return Period secPeriod: the period to set to
*********************************************************/
public void setSecPeriod(Period secPeriod) {
this.secPeriod = secPeriod; //set the period
}
/********************************************************
* @purpose Sets the secondary period to the specified string
*
* @param String secPeriod: the string to construct the period from
*
* @return boolean: if the operation was a success
*********************************************************/
public boolean setSecPeriod(String secPeriod) {
this.secPeriod = new Period(); //create new period
return this.secPeriod.setPeriod(secPeriod); //set period and return if success
}
/********************************************************
* @purpose Sets the Secondary days array for the second period
*
* @param boolean[] days: sets the days array for the second period
*
* @return boolean: if the operation was a success
*********************************************************/
public boolean setSecDays(boolean[] days){
if (days.length != Day.friday.value()+1){ //verify that the days array is of valid size
return false; //if invalid return false for changes made
}
this.secPeriod.setDays(days); //boolean array of days
return true;
}
/********************************************************
* @purpose Returns the location for the second period
*
* @return String: the location for the second period
*********************************************************/
public String getSecLocation() {
return secLocation; //return location
}
/********************************************************
* @purpose Sets the secondary period's locations
*
* @param String secLocation: the location to set it to
*********************************************************/
public void setSecLocation(String secLocation) {
this.secLocation = secLocation; //set location
}
/********************************************************
* @purpose Returns the days for the secondary period
*
* @param boolean[]: the days for the secoindary period
*********************************************************/
public boolean[] getSecDaysBool(){
return this.secPeriod.getDays(); //return days
}
/*********************************************************
* @purpose Returns the days that the section meets as a
* single string. Example for monday, thursday, friday
* returns "M RF".
*
* @return String: The days of the week that the section meets
*********************************************************/
public String getSecDaysStr(){
String[] temp = getSecDaysStrArr(); //return the days the section meets as
String res = new String(); //a single string by concat-ing the
res = temp[Day.monday.value()] + temp[Day.tuesday.value()] +//chars that represent the days
temp[Day.wednesday.value()] + temp[Day.thursday.value()] +
temp[Day.friday.value()]; //together
return res;
}
/*********************************************************
* @purpose Returns the days that the section meets as a
* string array where if the class meets in monday then
* result[Section.monday] = "M" and if not is " "
* etc
*
* @return String[]: Containing which days the section meets
*********************************************************/
public String[] getSecDaysStrArr(){
String[] result = new String[Day.values().length];//return the days that the section meets
result[Day.monday.value()] = this.secPeriod.getDays()[Day.monday.value()] ? "M" : " "; //as a string arrawy where " " means the
result[Day.tuesday.value()] = this.secPeriod.getDays()[Day.tuesday.value()] ? "T" : " ";//section does not meet, and a character
result[Day.wednesday.value()] = this.secPeriod.getDays()[Day.wednesday.value()] ? "W" : " ";//representing the day means that the
result[Day.thursday.value()] = this.secPeriod.getDays()[Day.thursday.value()] ? "R" : " ";//section does meet. Returned as a new
result[Day.friday.value()] = this.secPeriod.getDays()[Day.friday.value()] ? "F" : " "; //string array
return result;
}
public boolean hasValidTime(boolean secondary){
boolean sec = true;
if(secondary){
String secStr = secPeriod.toString();
sec = !(invalid.contains(secStr));
}
String str = period.toString();
return sec && !(invalid.contains(str));
}
public CourseType getType() {
return type;
}
public void setType(CourseType type) {
this.type = type;
}
public boolean fitsType(CourseType type){
switch(type){
case all:{
return true;
}
case campusAndDistance:{
if(this.type == CourseType.distanceGrad || this.type == CourseType.campusGrad){
return true;
}
break;
}
case underAndCampus:{
if(this.type == CourseType.undergrad || this.type == CourseType.campusGrad){
return true;
}
break;
}
case underAndDistance:{
if(this.type == CourseType.undergrad || this.type == CourseType.distanceGrad){
return true;
}
break;
}
default:{
if(type == this.type){
return true;
}
break;
}
}
return false;
}
@Override
public boolean equals(Object o){
Section other;
try{
other = (Section)o;
}
catch(ClassCastException ex){
return false;
}
return new String(other.getCourseID() + other.getSection()).equals(getCourseID() + getSection());
}
public String getDescription(){
return toString() + " (" + getPeriodStr() + ")";
}
public static Section getConflictAsSection(Section one, Section two){
int startComp = two.getPeriodPer().getStartTime().compareTo(one.getPeriodPer().getStartTime());
int endComp = two.getPeriodPer().getEndTime().compareTo(one.getPeriodPer().getEndTime());
String period;
if(startComp == Compare.less.value()){
period = two.getPeriodPer().getStartTime().toString() + (two.getPeriodPer().getStartTime().getAm() ? " am" : " pm");
}
else{
period = one.getPeriodPer().getStartTime().toString() + (one.getPeriodPer().getStartTime().getAm() ? " am" : " pm");
}
if(endComp == Compare.more.value()){
Time end = two.getPeriodPer().getEndTime();
period += " - " + end.toString() + (end.getAm() ? " am" : " pm");
}
else{
Time end = one.getPeriodPer().getEndTime();
period += " - " + end.toString() + (end.getAm() ? " am" : " pm");
}
Section toReturn = new Section();
toReturn.setPeriod(period);
toReturn.setSecPeriod("");
boolean[] days = new boolean[Day.values().length];
boolean[] first = one.getDaysBool(), second = two.getDaysBool();
for(Day day: Day.values()){
days[day.value()] = first[day.value()] && second[day.value()];
}
toReturn.setDays(days);
return toReturn;
}
}