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}