001 package net.sf.cpsolver.studentsct.model;
002
003 import java.util.Enumeration;
004 import java.util.HashSet;
005 import java.util.Vector;
006
007 /**
008 * Representation of a scheduling subpart. Each scheduling subpart contains id, instructional type, name,
009 * instructional offering configuration, and a list of sections. Optionally, parent-child relation between
010 * subparts can be defined.
011 * <br><br>
012 *
013 * @version
014 * StudentSct 1.1 (Student Sectioning)<br>
015 * Copyright (C) 2007 Tomáš Müller<br>
016 * <a href="mailto:muller@unitime.org">muller@unitime.org</a><br>
017 * Lazenska 391, 76314 Zlin, Czech Republic<br>
018 * <br>
019 * This library is free software; you can redistribute it and/or
020 * modify it under the terms of the GNU Lesser General Public
021 * License as published by the Free Software Foundation; either
022 * version 2.1 of the License, or (at your option) any later version.
023 * <br><br>
024 * This library is distributed in the hope that it will be useful,
025 * but WITHOUT ANY WARRANTY; without even the implied warranty of
026 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
027 * Lesser General Public License for more details.
028 * <br><br>
029 * You should have received a copy of the GNU Lesser General Public
030 * License along with this library; if not, write to the Free Software
031 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
032 */
033 public class Subpart implements Comparable {
034 private long iId = -1;
035 private String iInstructionalType = null;
036 private String iName = null;
037 private Vector iSections = new Vector();
038 private Config iConfig = null;
039 private Subpart iParent = null;
040
041 /** Constructor
042 * @param id scheduling subpart unique id
043 * @param itype instructional type
044 * @param name subpart name
045 * @param config instructional offering configuration to which this subpart belongs
046 * @param parent parent subpart, if parent-child relation is defined between subparts
047 */
048 public Subpart(long id, String itype, String name, Config config, Subpart parent) {
049 iId = id;
050 iInstructionalType = itype;
051 iName = name;
052 iConfig = config;
053 iParent = parent;
054 iConfig.getSubparts().addElement(this);
055 }
056
057 /** Subpart id */
058 public long getId() {
059 return iId;
060 }
061
062 /** Instructional type, e.g., Lecture, Recitation or Laboratory */
063 public String getInstructionalType() {
064 return iInstructionalType;
065 }
066
067 /** Subpart name */
068 public String getName() {
069 return iName;
070 }
071
072 /** Instructional offering configuration to which this subpart belongs */
073 public Config getConfig() {
074 return iConfig;
075 }
076
077 /** List of sections */
078 public Vector getSections() {
079 return iSections;
080 }
081
082 /** Parent subpart, if parent-child relation is defined between subparts */
083 public Subpart getParent() {
084 return iParent;
085 }
086
087 public String toString() {
088 return getName();
089 }
090
091 /** True, if this subpart is parent (or parent of a parent etc.) of the given subpart */
092 public boolean isParentOf(Subpart subpart) {
093 if (subpart.getParent()==null) return false;
094 if (subpart.getParent().equals(this)) return true;
095 return isParentOf(subpart.getParent());
096 }
097
098 /** Compare two subparts: put parents first, use ids if there is no parent-child relation*/
099 public int compareTo(Object o) {
100 if (o==null || !(o instanceof Subpart)) {
101 return -1;
102 }
103 Subpart s = (Subpart)o;
104 if (isParentOf(s)) return -1;
105 if (s.isParentOf(this)) return 1;
106 int cmp = getInstructionalType().compareTo(s.getInstructionalType());
107 if (cmp!=0) return cmp;
108 return Double.compare(getId(),s.getId());
109 }
110
111 /** List of available choices of the sections of this subpart. */
112 public HashSet getChoices() {
113 HashSet choices = new HashSet();
114 for (Enumeration e=getSections().elements();e.hasMoreElements();) {
115 choices.add(((Section)e.nextElement()).getChoice());
116 }
117 return choices;
118 }
119
120 /** Minimal penalty from {@link Section#getPenalty()} */
121 public double getMinPenalty() {
122 double min = Double.MAX_VALUE;
123 for (Enumeration e=getSections().elements();e.hasMoreElements();) {
124 Section section = (Section)e.nextElement();
125 min = Math.min(min, section.getPenalty());
126 }
127 return (min==Double.MAX_VALUE?0.0:min);
128 }
129
130 /** Maximal penalty from {@link Section#getPenalty()} */
131 public double getMaxPenalty() {
132 double max = Double.MIN_VALUE;
133 for (Enumeration e=getSections().elements();e.hasMoreElements();) {
134 Section section = (Section)e.nextElement();
135 max = Math.max(max, section.getPenalty());
136 }
137 return (max==Double.MIN_VALUE?0.0:max);
138 }
139
140 /** Return children subparts*/
141 public Vector getChildren() {
142 Vector ret = new Vector(getConfig().getSubparts().size());
143 for (Enumeration e=getConfig().getSubparts().elements();e.hasMoreElements();) {
144 Subpart s = (Subpart)e.nextElement();
145 if (this.equals(s.getParent())) ret.add(s);
146 }
147 return ret;
148 }
149 }