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