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