001    package net.sf.cpsolver.coursett.model;
002    
003    import java.util.HashMap;
004    
005    import net.sf.cpsolver.coursett.Constants;
006    
007    /**
008     * Room availability model.
009     * 
010     * @version CourseTT 1.2 (University Course Timetabling)<br>
011     *          Copyright (C) 2006 - 2010 Tomas Muller<br>
012     *          <a href="mailto:muller@unitime.org">muller@unitime.org</a><br>
013     *          <a href="http://muller.unitime.org">http://muller.unitime.org</a><br>
014     * <br>
015     *          This library is free software; you can redistribute it and/or modify
016     *          it under the terms of the GNU Lesser General Public License as
017     *          published by the Free Software Foundation; either version 3 of the
018     *          License, or (at your option) any later version. <br>
019     * <br>
020     *          This library is distributed in the hope that it will be useful, but
021     *          WITHOUT ANY WARRANTY; without even the implied warranty of
022     *          MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
023     *          Lesser General Public License for more details. <br>
024     * <br>
025     *          You should have received a copy of the GNU Lesser General Public
026     *          License along with this library; if not see
027     *          <a href='http://www.gnu.org/licenses/'>http://www.gnu.org/licenses/</a>.
028     */
029    public class RoomSharingModel {
030            protected int iStep = 1;
031        protected Long[][] iPreference = null;
032        protected Long[] iDepartmentIds = null;
033        protected HashMap<Long, Integer> iDepartmentIdx = null;
034    
035        public static Long sFreeForAllPref = new Long(-1);
036        public static Long sNotAvailablePref = new Long(-2);
037        public static char sFreeForAllPrefChar = '*';
038        public static char sNotAvailablePrefChar = '#';
039    
040        public static Long sDefaultPref = sFreeForAllPref;
041        public static char sDefaultPrefChar = sFreeForAllPrefChar;
042    
043        public char iFreeForAllPrefChar = sFreeForAllPrefChar;
044        public char iNotAvailablePrefChar = sNotAvailablePrefChar;
045    
046        protected RoomSharingModel(int step) {
047            iStep = step;
048        }
049        
050        protected RoomSharingModel() {
051            this(6);
052        }
053    
054        public RoomSharingModel(int step, Long[] managerIds, String pattern, Character freeForAllPrefChar, Character notAvailablePrefChar) {
055            iStep = step;
056            iPreference = new Long[getNrDays()][getNrTimes()];
057            iDepartmentIds = new Long[managerIds.length];
058            iDepartmentIdx = new HashMap<Long, Integer>();
059            for (int i = 0; i < managerIds.length; i++) {
060                iDepartmentIds[i] = managerIds[i];
061                iDepartmentIdx.put(managerIds[i], i);
062            }
063            if (freeForAllPrefChar != null)
064                iFreeForAllPrefChar = freeForAllPrefChar;
065            if (notAvailablePrefChar != null)
066                iNotAvailablePrefChar = notAvailablePrefChar;
067    
068            setPreferences(pattern);
069        }
070        
071        public char getFreeForAllPrefChar() { return iFreeForAllPrefChar; }
072        public void setFreeForAllPrefChar(char c) { iFreeForAllPrefChar = c; }
073    
074        public char getNotAvailablePrefChar() { return iNotAvailablePrefChar; }
075        public void setNotAvailablePrefChar(char c) { iNotAvailablePrefChar = c; }
076    
077        public boolean isFreeForAll(int day, int time) {
078            return sFreeForAllPref.equals(iPreference[day][time]);
079        }
080    
081        public boolean isFreeForAll(int slot) {
082            int day = slot / Constants.SLOTS_PER_DAY;
083            int time = (slot % Constants.SLOTS_PER_DAY) / getStep();
084            return sFreeForAllPref.equals(iPreference[day][time]);
085        }
086    
087        public boolean isNotAvailable(int day, int time) {
088            return sNotAvailablePref.equals(iPreference[day][time]);
089        }
090    
091        public boolean isNotAvailable(int slot) {
092            int day = slot / Constants.SLOTS_PER_DAY;
093            int time = (slot % Constants.SLOTS_PER_DAY) / getStep();
094            return sNotAvailablePref.equals(iPreference[day][time]);
095        }
096    
097        public boolean isAvailable(TimeLocation timeLocation, Long departmentId) {
098            for (int d = 0; d < Constants.NR_DAYS; d++) {
099                if ((Constants.DAY_CODES[d] & timeLocation.getDayCode()) == 0)
100                    continue;
101                int startTime = timeLocation.getStartSlot() / getStep();
102                int endTime = (timeLocation.getStartSlot() + timeLocation.getLength() - 1) / getStep();
103                for (int t = startTime; t <= endTime; t++) {
104                    Long pref = iPreference[d][t];
105                    if (pref.equals(sNotAvailablePref))
106                        return false;
107                    if (pref.equals(sFreeForAllPref))
108                        continue;
109                    if (departmentId != null && !departmentId.equals(pref))
110                        return false;
111                }
112            }
113            return true;
114        }
115    
116        public Long getDepartmentId(int day, int time) {
117            Long pref = iPreference[day][time];
118            if (pref.equals(sFreeForAllPref) || pref.equals(sNotAvailablePref))
119                return null;
120            return pref;
121        }
122    
123        public Long getDepartmentId(int slot) {
124            int day = slot / Constants.SLOTS_PER_DAY;
125            int time = (slot % Constants.SLOTS_PER_DAY) / getStep();
126            return getDepartmentId(day, time);
127        }
128    
129        public Long[] getDepartmentIds() {
130            return iDepartmentIds;
131        }
132    
133        public int getNrDepartments() {
134            return (iDepartmentIds == null ? 0 : iDepartmentIds.length);
135        }
136    
137        public int getIndex(Long departmentId) {
138            Integer idx = iDepartmentIdx.get(departmentId);
139            if (idx == null)
140                return -1;
141            return idx.intValue();
142        }
143    
144        public String getPreferences() {
145            StringBuffer sb = new StringBuffer();
146            for (int d = 0; d < getNrDays(); d++)
147                for (int t = 0; t < getNrTimes(); t++) {
148                    if (iPreference[d][t].equals(sFreeForAllPref))
149                        sb.append(getFreeForAllPrefChar());
150                    else if (iPreference[d][t].equals(sNotAvailablePref))
151                        sb.append(getNotAvailablePrefChar());
152                    else
153                        sb.append((char) ('0' + getIndex(iPreference[d][t])));
154                }
155            return sb.toString();
156        }
157    
158        public void setPreferences(String pattern) {
159            try {
160                int idx = 0;
161                for (int d = 0; d < getNrDays(); d++)
162                    for (int t = 0; t < getNrTimes(); t++) {
163                        char pref = (pattern != null && idx < pattern.length() ? pattern.charAt(idx) : getFreeForAllPrefChar());
164                        idx++;
165                        if (pref == getNotAvailablePrefChar()) {
166                            iPreference[d][t] = sNotAvailablePref;
167                        } else if (pref == getFreeForAllPrefChar()) {
168                            iPreference[d][t] = sFreeForAllPref;
169                        } else {
170                            iPreference[d][t] = iDepartmentIds[(pref - '0')];
171                        }
172                    }
173            } catch (NullPointerException e) {
174            } catch (IndexOutOfBoundsException e) {
175            }
176        }
177    
178        public int getNrDays() {
179            return Constants.NR_DAYS;
180        }
181    
182        public int getNrTimes() {
183            return Constants.SLOTS_PER_DAY / getStep();
184        }
185        
186        public int getStep() {
187            return iStep;
188        }
189    }