/******************************************************** * 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 Schedule.java * * Contains classes: * * Schedule: * * Purpose: Provides a class for storing course * schedules * * @author Mike Reinhold ********************************************************/ package Scheduler; //declare as member of scheduler package /******************************************************** * Import ArrayList for storing courses * Import Iterator for operations on the array List * Import Serializable for saving schedules ********************************************************/ import java.util.ArrayList; //import arrayList import java.util.Iterator; //import iterator import java.io.Serializable; //import Serializable /******************************************************** * Class: Schedule: * * @purpose Stores schedule information as a series of * sections * * @see Serializable ********************************************************/ public class Schedule implements Serializable, Comparable<Schedule>, Cloneable { /******************************************************** * The following are private fields ********************************************************/ private ArrayList<Section> classes; //classes in this schedule private double rating; //the schedule's rating private String term; //the schedule's term /******************************************************** * UPDATE SERIAL VERSION IN VERSION WHEN THIS FILE CHANGES ********************************************************/ protected static final long versionID = 2008102400050L;//object version id protected static final long serialVersionUID = 1L + Version.schedule.id;//serial id /******************************************************** * (Constructor) * * @purpose Creates a new schedule object ********************************************************/ public Schedule(String term){ classes = new ArrayList<Section>(); //create space for the arraylist rating = 0; //set default rating this.term = term; //set term string } @Override public Schedule clone(){ Schedule clone = new Schedule(this.term); for(Section one: classes){ clone.add(one, one.isClosed()); } return clone; } /******************************************************** * @purpose Adds a section to the schedule based on if it * conflicts with the schedule and if closed courses * are allowed. * * @param Section section: the section to add to the database * @param boolean allowClosed: if closed courses should be allowed * * @return boolean: if the course was added to the Schedule ********************************************************/ public boolean add(Section section, boolean allowClosed){ if (classes.isEmpty()){ //check if the classes list is empty, if (allowClosed || !section.isClosed()){ classes.add(section); //if so add the section and return true this.rating = section.getRating(); //set the rating return true; } return false; } if(allowClosed || !section.isClosed()){//check if section is open or if ignore closed //otherwise, get an iterator over the sections Iterator<Section> used = classes.iterator();//and iterate through the sections checking //if the section to add conflicts with any of while(used.hasNext()){ //the sections in the schedule already if (used.next().conflictsWith(section)){//if there is a conflict, return false return false; } } int num = classes.size(); classes.add(section); //otherwise add the section to the schedule this.rating = (this.rating * num + section.getRating())/(num + 1);//set rating return true; //and return true } //at this point section is closed return false; //return false } /******************************************************** * @purpose Returns the number of sections in the schedule * * @return int: the number of sections in the int *********************************************************/ public int numberSections(){ return classes.size(); //return the number of sections } /******************************************************** * @purpose Returns if one schedule is equal to another, * overrides Object's equals method so that it is used * in the default array contains method * * @param Object other: the object to check for equality * * @return boolean: if the two schedules are the same *********************************************************/ @Override public boolean equals(Object other){ Schedule trick = (Schedule)other; //cast to schedule Iterator<Section> these = this.classes.iterator();//get iterator while(these.hasNext()){ //while there are more sections to check if (!trick.contains(these.next())){ //check for containment return false; //return false since mismatch found } } Iterator<Section> oth = trick.getClassesObj().iterator();//get other iterator while(oth.hasNext()){ //while there are more sectios to check if (!this.contains(oth.next())){ //check for containment return false; //return false since mismatch found } } return true; //no mismatches found return true } /******************************************************** * @purpose Check if the schedule contains the specified section * * @param Section item: the section to check for containment * * @return boolean: if the section is in this schedule *********************************************************/ public boolean contains(Section item){ Iterator<Section> these = this.classes.iterator();//get iterator while(these.hasNext()){ //while more items to check if (these.next().compareTo(item) == Compare.equal.value()){ //check if equal return true; //item found return true } } return false; //item not found return false } /******************************************************** * @purpose Returns the arraylist which contains the sections * that are part of the schedule * * @return ArrayList<Section>: the sections in the schedule *********************************************************/ public ArrayList<Section> getClassesObj(){ return this.classes; //return the array of classes } /******************************************************** * @purpose rerates the schedule *********************************************************/ public void reRate(){ Rate.reRate(this); //reRate the schedule } /******************************************************** * @purpose returns the schedule's rating * * @return double: the rating ********************************************************/ public double getRating() { return rating; //return rating } /******************************************************** * @purpose set the rating to the double passed in * * @param double rating: the rating to set ********************************************************/ public void setRating(double rating) { this.rating = rating; //set this rating } /******************************************************** * @purpose return the term for the schedule * * @return String: the term that the schedule is for ********************************************************/ public String getTerm() { return term; //return the term } /******************************************************** * @purpose set the term the the specified string * * @param String term: the string to set the term to ********************************************************/ public void setTerm(String term) { this.term = term; //set the term } /******************************************************** * @purpose Compares the two schedules for sorting * * @param Schedule other: the schedule to compare this against * * @return int: the value of the comparison ********************************************************/ public int compareTo(Schedule other){ if(hasClosedCourse() && !other.hasClosedCourse()) return Compare.more.value(); if(!hasClosedCourse() && other.hasClosedCourse()) return Compare.less.value(); if(this.rating == other.rating) return Compare.equal.value();//return equality if(this.rating > other.rating) return Compare.less.value();//return the other is less than this return Compare.more.value(); //return the other is more than this } /******************************************************** * @purpose return the schedule as a string for display purposes * * @return String: the string representation of the schedule * in the form "Rating: " schedule.rating(rounded to single decimal place * * @see Override ********************************************************/ @Override public String toString(){ return "Rating: " + (Math.round(this.rating * 10))/10.0;//return the schedule as a string with the rating } //rounded to one decimal place /******************************************************** * @purpose return if the schedule has any closed courses * * @return boolean: if the schedule has any closed sections ********************************************************/ public boolean hasClosedCourse(){ for(Section item: classes){ //for each section in the schedule if(item.isClosed()) return true; //return true if section is closed } return false; //no closed items } /******************************************************** * @purpose return if the schedule contains the specified perceived course * * @param String key: the perceived course to check for containment * * @return boolean: if the schedule contains the course ********************************************************/ public boolean contains(String key){ for(Section item: classes){ //for each section in the list if(item.getPerceivedCourse().compareTo(key) == Compare.equal.value()){ return true; //if found returns true } } return false; //else return false } /******************************************************** * @purpose return if the schedule contains all the linked * courses based on the LinkedCourses dependancy * * @param LinkedCourses links: the dependancy lists * * @return boolean: if the schedule meets the dependancy ********************************************************/ public boolean hasAllLinks(LinkedCourses links){ for(Section course: this.classes){ for(CourseList dependancy: links.links){ if(dependancy.contains(course.getPerceivedCourse())){ for(String item: dependancy){ if(!contains(item)){ return false; } } } } } return true; } /******************************************************** * @purpose return if the schedule contains all the primary courses * * @param ArrayList<String> primary: the primary courses * * @return boolean: if the schedule has all the primary courses ********************************************************/ public boolean allPrimaryUsed(ArrayList<String> primary){ boolean returnVal = true; for(String key: primary){ returnVal &= contains(key); } return returnVal; } public ArrayList<String> missingPrimary(ArrayList<String> primary){ ArrayList<String> missing = new ArrayList<String>(); for(String key: primary){ if(!contains(key)){ missing.add(key); } } return missing; } /******************************************************** * @purpose return if the schedule contains all correct section type * * @param CourseType type: the schedule build type * * @return boolean: if the schedule sections are all the appropriate type ********************************************************/ public boolean allFitTypes(CourseType type){ for(Section item: classes){ if(!item.fitsType(type)){ return false; } } return true; } /******************************************************** * @purpose return if the schedule contains the proper number of sections for each course * * @param int[] numberSelected: the number of sections for each course * @param Course[] possible: the courses possible to add to the schedule * * @return boolean: if the correct number of sections for each course is in the schedule ********************************************************/ public boolean hasAllSections(int[] numberSelected, Course[] possible){ //rewrite this so that it returns true if for each course, the schedule contains the number of selected //sections or none at all for(int pos = 0; pos < possible.length; pos++){ int added = 0; Course curr = possible[pos]; if(contains(curr)){ for(int sec = 0; sec < curr.getNumOfSections(); sec++){ if(classes.contains(curr.getSection(sec))){ added++; } } if(added < numberSelected[pos]){ return false; } } } return true; } public boolean contains(Course item){ for(Section one: classes){ if(one.getPerceivedCourse().equals(item.getPerceivedCourse())) return true; } return false; } public Section findConflictingSection(Section notUsed){ for(Section in: classes){ if(in.conflictsWith(notUsed)){ return in; } } return null; } }