001 package ttsolver.constraint;
002
003 import ifs.model.*;
004 import java.util.Set;
005 import ttsolver.model.*;
006
007 /**
008 * Resource constraint.
009 * <br>
010 * Classes using this resource can not overlap in time. All classes associated with this
011 * resource are considered to use this resource.
012 *
013 * @author <a href="mailto:muller@ktiml.mff.cuni.cz">Tomáš Müller</a>
014 * @version 1.0
015 */
016
017 public class ResourceConstraint extends Constraint {
018 private static org.apache.log4j.Logger sLogger = org.apache.log4j.Logger.getLogger(ResourceConstraint.class);
019 /** table iResource[slot] = lecture using this resource placed in the given time slot (null if empty) */
020 protected Lecture[] iResource;
021 private String iResourceId;
022 private String iName;
023 /** Number of slots per day */
024 protected int iSlotsPerDay;
025 /** Number of days */
026 protected int iDays;
027
028 /** Constructor
029 * @param id resource id
030 * @param name resource name
031 * @param slotsPerDay number of slots per day
032 * @param days number of days
033 */
034 public ResourceConstraint(String id, String name, int slotsPerDay, int days) {
035 iSlotsPerDay = slotsPerDay;
036 iDays = days;
037 iResourceId = id;
038 iName = name;
039 iResource = new Lecture[iSlotsPerDay * iDays];
040 for (int i=0;i<iResource.length;i++)
041 iResource[i]=null;
042 }
043
044 /** Resource id */
045 public String getResourceId() { return iResourceId; }
046 /** Resource name */
047 public String getName() { return iName; }
048 /** Number of slots per day */
049 public int getSlotsPerDay() { return iSlotsPerDay; }
050 /** Number of days */
051 public int getDays() { return iDays; }
052
053 public void computeConflicts(Value value, Set conflicts) {
054 Lecture lecture = (Lecture) value.variable();
055 Placement placement = (Placement) value;
056 for (int i=0; i<placement.getTimeLocation().getSlots().length; i++) {
057 int slot = placement.getTimeLocation().getSlots()[i];
058 Lecture conf = iResource[slot];
059 if (conf!=null && !lecture.equals(conf)) conflicts.add(conf.getAssignment());
060 }
061 }
062
063 public boolean inConflict(Value value) {
064 Placement placement = (Placement) value;
065 for (int i=0; i<placement.getTimeLocation().getSlots().length; i++) {
066 int slot = placement.getTimeLocation().getSlots()[i];
067 if (iResource[slot]!=null) return true;
068 }
069 return false;
070 }
071
072 public boolean isConsistent(Value value1, Value value2) {
073 Placement p1 = (Placement) value1;
074 Placement p2 = (Placement) value2;
075 return !p1.getTimeLocation().hasIntersection(p2.getTimeLocation());
076 }
077
078 public void assigned(long iteration, Value value) {
079 super.assigned(iteration, value);
080 Lecture lecture = (Lecture) value.variable();
081 Placement placement = (Placement) value;
082 for (int i=0; i<placement.getTimeLocation().getSlots().length; i++) {
083 int slot = placement.getTimeLocation().getSlots()[i];
084 iResource[slot] = lecture;
085 }
086 }
087
088 public void unassigned(long iteration, Value value) {
089 super.unassigned(iteration, value);
090 Lecture lecture = (Lecture) value.variable();
091 Placement placement = (Placement) value;
092 for (int i=0; i<placement.getTimeLocation().getSlots().length; i++) {
093 int slot = placement.getTimeLocation().getSlots()[i];
094 iResource[slot] = null;
095 }
096 }
097
098 /** Lookup table getResource()[slot] -> lecture using this resource placed in the given time slot (null if empty) */
099 public Lecture[] getResource() { return iResource; }
100
101 /** Number of useless slots for this resource */
102 public int countUselessSlots() {
103 int ret = 0;
104 for (int d=0;d<iDays;d++) {
105 for (int s=1;s<iSlotsPerDay-1;s++) {
106 int slot = d*iSlotsPerDay+s;
107 if (iResource[slot-1]!=null && iResource[slot]==null && iResource[slot+1]!=null)
108 ret++;
109 }
110 }
111 return ret;
112 }
113
114 /** Resource usage usage */
115 protected void printUsage(StringBuffer sb) {
116 for (int slot=0;slot<getResource().length;slot++) {
117 if (getResource()[slot]!=null) {
118 int day = slot / edu.purdue.smas.timetable.util.Constants.SLOTS_PER_DAY;
119 int time = (7*60)+30 + (30 * (slot % edu.purdue.smas.timetable.util.Constants.SLOTS_PER_DAY));
120 int h = time / 60;
121 int m = time % 60;
122 String d = edu.purdue.smas.timetable.util.Constants.DAY_NAMES_SHORT[day];
123 int slots = ((Placement)((Lecture)getResource()[slot]).getAssignment()).getTimeLocation().getLength();
124 time += (30*slots);
125 int h2 = time / 60;
126 int m2 = time % 60;
127 sb.append(sb.length()==0?"":",\n ").append("["+d+(h>12?h-12:h)+":"+(m<10?"0":"")+m+(h>=12?"pm":"am")+"-"+(h2>12?h2-12:h2)+":"+(m2<10?"0":"")+m2+(h2>=12?"pm":"am")+"]=").append(((Lecture)iResource[slot]).getName());
128 slot+=slots-1;
129 //sb.append(sb.length()==0?"":", ").append("s"+(slot+1)+"=").append(((Lecture)getResource()[slot]).getName());
130 }
131 }
132 }
133
134 public String toString() {
135 StringBuffer sb = new StringBuffer("Resource{name="+getName());
136 printUsage(sb);
137 sb.append("\n }");
138 return sb.toString();
139 }
140 }