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