    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    }