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