001package net.sf.cpsolver.coursett.model;
002
003import java.util.HashMap;
004
005import 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 Tomáš Müller<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 */
029public 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}