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 = Long.valueOf(-1); 039 public static Long sNotAvailablePref = Long.valueOf(-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}