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    }