001 package ttsolver.model;
002
003 import ifs.util.FastVector;
004 import java.util.*;
005 import edu.purdue.smas.timetable.data.pattern.TimePatternModel;
006 import edu.purdue.smas.timetable.util.Constants;
007
008 /**
009 * Time part of placement.
010 *
011 * @author <a href="mailto:muller@ktiml.mff.cuni.cz">Tomáš Müller</a>
012 * @version 1.0
013 */
014
015 public class TimeLocation {
016 private int iStartSlot;
017 private int[] iStartSlots;
018 private int[] iSlots;
019
020 private int iPreference;
021 private double iNormalizedPreference;
022
023 private TimePatternModel iTimePatternModel = null;
024 private String iText=null;
025 private int iHashCode;
026
027 private int iDayCode;
028 private int iTimeCode;
029 private int iLength;
030
031 /** Constructor
032 * @param timePatternModel time pattern model
033 * @param day day in time pattern model
034 * @param time time in time pattern model
035 */
036 public TimeLocation(TimePatternModel timePatternModel, int day, int time) {
037 iTimePatternModel = timePatternModel;
038 iText = iTimePatternModel.getText(day, time);
039 iLength = iTimePatternModel.getNrHalfHoursPerMeeting();
040 iDayCode = iTimePatternModel.getDayCode(day);
041 iNormalizedPreference = iTimePatternModel.getNormalizedPreference(day,time);
042 Collection slots = iTimePatternModel.getSlots(day, time);
043 iSlots = new int[slots.size()]; int i=0;
044 for (Iterator it=slots.iterator();it.hasNext();) iSlots[i++]=((Integer)it.next()).intValue();
045 Collection startSlots = iTimePatternModel.getStartSlots(day, time);
046 iStartSlots = new int[startSlots.size()]; i=0;
047 for (Iterator it=startSlots.iterator();it.hasNext();) iStartSlots[i++]=((Integer)it.next()).intValue();
048 iStartSlot = iStartSlots[0] % Constants.SLOTS_PER_DAY;
049 String prologPref = iTimePatternModel.getPreference(day, time).getProlog();
050 iPreference = (prologPref.equalsIgnoreCase("R")?0:Integer.parseInt(iTimePatternModel.getPreference(day, time).getProlog()));
051 iHashCode = combine(combine(day, time),combine(iTimePatternModel.getNrMeetings(),iTimePatternModel.getNrDays()));
052 iTimeCode = 0;
053 for (int h=0;h<iLength;h++)
054 iTimeCode |= (1<<(iStartSlot+h));
055 }
056
057 /** Constructor
058 * @param dayCode days (combination of 1 for Monday, 2 for Tuesday, ...)
059 * @param startTime start slot
060 * @param length number of slots
061 * @param pref time preference
062 */
063 public TimeLocation(int dayCode, int startTime, int length, int pref) {
064 iPreference = pref;
065 iNormalizedPreference = pref;
066 iStartSlot = startTime;
067 iDayCode = dayCode;
068 iLength = length;
069 int nrDays = 0;
070 for (int i=0;i<Constants.DAY_CODES.length;i++) {
071 if ((iDayCode & Constants.DAY_CODES[i])==0) continue;
072 nrDays++;
073 }
074 iSlots = new int[nrDays*length];
075 iStartSlots = new int[nrDays];
076 int idxStartSlots = 0, idxSlots = 0;
077 for (int i=0;i<Constants.DAY_CODES.length;i++) {
078 if ((iDayCode & Constants.DAY_CODES[i])==0) continue;
079 int slot = (i*Constants.SLOTS_PER_DAY)+iStartSlot;
080 iStartSlots[idxStartSlots++]=slot;
081 for (int j=0;j<length;j++)
082 iSlots[idxSlots++]=slot+j;
083 }
084 iHashCode = combine(combine(dayCode, iStartSlot),combine(iLength,nrDays));
085 iTimeCode = 0;
086 for (int h=0;h<iLength;h++)
087 iTimeCode |= (1<<(iStartSlot+h));
088 iText = getDayHeader()+" "+getStartTimeHeader();
089 }
090
091 /** Number of meetings */
092 public int getNrMeetings() {
093 return iStartSlots.length;
094 }
095
096 private static int combine(int a, int b) {
097 int ret = 0;
098 for (int i=0;i<15;i++) ret = ret | ((a & (1<<i))<<i) | ((b & (1<<i))<<(i+1));
099 return ret;
100 }
101
102 /** Days (combination of 1 for Monday, 2 for Tuesday, ...) */
103 public int getDayCode() { return iDayCode; }
104 /** Days for printing purposes */
105 public String getDayHeader() {
106 StringBuffer sb = new StringBuffer();
107 for (int i=0;i<edu.purdue.smas.timetable.util.Constants.DAY_CODES.length;i++)
108 if ((iDayCode & edu.purdue.smas.timetable.util.Constants.DAY_CODES[i])!=0)
109 sb.append(edu.purdue.smas.timetable.util.Constants.DAY_NAMES_SHORT[i]);
110 return sb.toString();
111 }
112 /** Start time for printing purposes */
113 public String getStartTimeHeader() {
114 int h = (iStartSlot+15)/2;
115 int m = ((iStartSlot+15)%2==0?0:30);
116 return (h>12?h-12:h)+":"+(m<10?"0":"")+m+" "+(h>=12?"pm":"am");
117 }
118 /** End time for printing purposes */
119 public String getEndTimeHeader() {
120 int h = (iStartSlot+15)/2;
121 int m = ((iStartSlot+15)%2==0?0:30);
122 int x = (h * 60) + m + (iLength*25);
123 m = x % 60;
124 h = x / 60;
125 return (h>12?h-12:h)+":"+(m<10?"0":"")+m+" "+(h>=12?"pm":"am");
126 }
127 /** Start slot */
128 public int getStartSlot() { return iStartSlot; }
129 /** Used slots in a day (combination of 1..first, 2..second,...) */
130 public int getTimeCode() { return iTimeCode; }
131
132 /** true if days overlap */
133 public boolean shareDays(TimeLocation anotherLocation) {
134 return ((iDayCode & anotherLocation.iDayCode)!=0);
135 }
136 /** true if hours overlap */
137 public boolean shareHours(TimeLocation anotherLocation) {
138 return ((iTimeCode & anotherLocation.iTimeCode)!=0);
139 }
140 /** true if overlap */
141 public boolean hasIntersection(TimeLocation anotherLocation) {
142 return shareDays(anotherLocation) && shareHours(anotherLocation);
143 }
144
145 /** Set of overlapping slots */
146 public Collection getIntersection(TimeLocation anotherLocation) { //called only in JenrlConstraint.toString() -- no caching needed
147 Vector ret = new FastVector();
148 for (int i=0;i<getSlots().length;i++)
149 for (int j=0;j<anotherLocation.getSlots().length;j++)
150 if (getSlots()[i]==anotherLocation.getSlots()[j]) ret.addElement(new Integer(getSlots()[i]));
151 return ret;
152 }
153
154 /** Used slots */
155 public int[] getSlots() { return iSlots; }
156 /** Used start slots (for each meeting) */
157 public int[] getStartSlots() { return iStartSlots; }
158 /** Text representation */
159 public String getText() { return iText; }
160 /** Preference */
161 public int getPreference() { return iPreference; }
162 /** Length */
163 public int getLength() { return iLength; }
164 /** Length */
165 public int getNrHalfHoursPerMeeting() { return iLength; }
166 /** Normalized preference */
167 public double getNormalizedPreference() { return iNormalizedPreference;}
168 /** Time pattern model (can be null) */
169 public TimePatternModel getModel() { return iTimePatternModel; }
170 private static Vector toVector(int[] x) {
171 if (x==null) return null;
172 Vector ret = new FastVector(x.length);
173 for (int i=0;i<x.length;i++) ret.add(new Integer(x[i]));
174 return ret;
175 }
176
177 public String toString() { return "TimeLocation{text="+getText()+", pref="+iPreference+", normPref="+getNormalizedPreference()+(iTimePatternModel!=null?", tansform="+iTimePatternModel.getTransformPreference()+", treshold="+iTimePatternModel.getTresholdPreference():"")+", slots="+toVector(iSlots)+"}"; }
178 public int hashCode() {
179 return iHashCode;
180 }
181 }