001package org.cpsolver.studentsct.reservation; 002 003import java.util.Collection; 004import java.util.HashMap; 005import java.util.HashSet; 006import java.util.Map; 007import java.util.Set; 008 009import org.cpsolver.studentsct.model.AreaClassificationMajor; 010import org.cpsolver.studentsct.model.Offering; 011import org.cpsolver.studentsct.model.Student; 012 013 014/** 015 * Curriculum reservation. Students are matched based on their academic area. 016 * If classifications and/or majors are included, student must match on them as well. 017 * 018 * <br> 019 * <br> 020 * 021 * @version StudentSct 1.3 (Student Sectioning)<br> 022 * Copyright (C) 2007 - 2014 Tomáš Müller<br> 023 * <a href="mailto:muller@unitime.org">muller@unitime.org</a><br> 024 * <a href="http://muller.unitime.org">http://muller.unitime.org</a><br> 025 * <br> 026 * This library is free software; you can redistribute it and/or modify 027 * it under the terms of the GNU Lesser General Public License as 028 * published by the Free Software Foundation; either version 3 of the 029 * License, or (at your option) any later version. <br> 030 * <br> 031 * This library is distributed in the hope that it will be useful, but 032 * WITHOUT ANY WARRANTY; without even the implied warranty of 033 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 034 * Lesser General Public License for more details. <br> 035 * <br> 036 * You should have received a copy of the GNU Lesser General Public 037 * License along with this library; if not see 038 * <a href='http://www.gnu.org/licenses/'>http://www.gnu.org/licenses/</a>. 039 */ 040public class CurriculumReservation extends Reservation { 041 private double iLimit; 042 private Set<String> iAcadAreas = new HashSet<String>(); 043 private Set<String> iClassifications = new HashSet<String>(); 044 private Set<String> iMajors = new HashSet<String>(); 045 private Set<String> iMinors = new HashSet<String>(); 046 private Map<String, Set<String>> iConcentrations = null; 047 048 /** 049 * Reservation priority (lower than individual and group reservations) 050 */ 051 public static final int DEFAULT_PRIORITY = 500; 052 /** 053 * Curriculum reservation does not need to be used 054 */ 055 public static final boolean DEFAULT_MUST_BE_USED = false; 056 /** 057 * Curriculum reservations can not assign over the limit. 058 */ 059 public static final boolean DEFAULT_CAN_ASSIGN_OVER_LIMIT = false; 060 /** 061 * Overlaps are not allowed for curriculum reservations. 062 */ 063 public static final boolean DEFAULT_ALLOW_OVERLAP = false; 064 065 /** 066 * Constructor 067 * @param id unique id 068 * @param limit reservation limit (-1 for unlimited) 069 * @param offering instructional offering on which the reservation is set 070 * @param acadAreas one or more academic areas 071 * @param classifications zero or more classifications (classifications must match if not empty) 072 * @param majors zero or more majors (majors must match if not empty) 073 * @param minors zero or more majors (minors must match if not empty) 074 */ 075 public CurriculumReservation(long id, double limit, Offering offering, Collection<String> acadAreas, Collection<String> classifications, Collection<String> majors, Collection<String> minors) { 076 super(id, offering, DEFAULT_PRIORITY, DEFAULT_MUST_BE_USED, DEFAULT_CAN_ASSIGN_OVER_LIMIT, DEFAULT_ALLOW_OVERLAP); 077 iLimit = limit; 078 if (acadAreas != null) 079 iAcadAreas.addAll(acadAreas); 080 if (classifications != null) 081 iClassifications.addAll(classifications); 082 if (majors != null) 083 iMajors.addAll(majors); 084 if (minors != null) 085 iMinors.addAll(minors); 086 } 087 088 /** 089 * Constructor 090 * @param id unique id 091 * @param limit reservation limit (-1 for unlimited) 092 * @param offering instructional offering on which the reservation is set 093 * @param acadArea academic area 094 * @param classifications zero or more classifications (classifications must match if not empty) 095 * @param majors zero or more majors (majors must match if not empty) 096 */ 097 @Deprecated 098 public CurriculumReservation(long id, double limit, Offering offering, String acadArea, Collection<String> classifications, Collection<String> majors) { 099 super(id, offering, DEFAULT_PRIORITY, DEFAULT_MUST_BE_USED, DEFAULT_CAN_ASSIGN_OVER_LIMIT, DEFAULT_ALLOW_OVERLAP); 100 iLimit = limit; 101 iAcadAreas.add(acadArea); 102 if (classifications != null) 103 iClassifications.addAll(classifications); 104 if (majors != null) 105 iMajors.addAll(majors); 106 } 107 108 /** 109 * Constructor 110 * @param id unique id 111 * @param limit reservation limit (-1 for unlimited) 112 * @param offering instructional offering on which the reservation is set 113 * @param acadAreas one or more academic areas 114 * @param classifications zero or more classifications (classifications must match if not empty) 115 * @param majors zero or more majors (majors must match if not empty) 116 * @param minors zero or more majors (minors must match if not empty) 117 * @param priority reservation priority 118 * @param mustBeUsed must this reservation be used 119 * @param canAssignOverLimit can assign over class / configuration / course limit 120 * @param allowOverlap does this reservation allow for overlaps 121 */ 122 protected CurriculumReservation(long id, double limit, Offering offering, Collection<String> acadAreas, Collection<String> classifications, Collection<String> majors, Collection<String> minors, 123 int priority, boolean mustBeUsed, boolean canAssignOverLimit, boolean allowOverlap) { 124 super(id, offering, priority, mustBeUsed, canAssignOverLimit, allowOverlap); 125 iLimit = limit; 126 if (acadAreas != null) 127 iAcadAreas.addAll(acadAreas); 128 if (classifications != null) 129 iClassifications.addAll(classifications); 130 if (majors != null) 131 iMajors.addAll(majors); 132 if (minors != null) 133 iMinors.addAll(minors); 134 } 135 136 /** 137 * Constructor 138 * @param id unique id 139 * @param limit reservation limit (-1 for unlimited) 140 * @param offering instructional offering on which the reservation is set 141 * @param acadArea academic area 142 * @param classifications zero or more classifications (classifications must match if not empty) 143 * @param majors zero or more majors (majors must match if not empty) 144 * @param priority reservation priority 145 * @param mustBeUsed must this reservation be used 146 * @param canAssignOverLimit can assign over class / configuration / course limit 147 * @param allowOverlap does this reservation allow for overlaps 148 */ 149 @Deprecated 150 protected CurriculumReservation(long id, double limit, Offering offering, String acadArea, Collection<String> classifications, Collection<String> majors, 151 int priority, boolean mustBeUsed, boolean canAssignOverLimit, boolean allowOverlap) { 152 super(id, offering, priority, mustBeUsed, canAssignOverLimit, allowOverlap); 153 iLimit = limit; 154 iAcadAreas.add(acadArea); 155 if (classifications != null) 156 iClassifications.addAll(classifications); 157 if (majors != null) 158 iMajors.addAll(majors); 159 } 160 161 /** 162 * Reservation limit (-1 for unlimited) 163 */ 164 @Override 165 public double getReservationLimit() { 166 return iLimit; 167 } 168 169 /** 170 * Set reservation limit (-1 for unlimited) 171 * @param limit reservation limit, -1 for unlimited 172 */ 173 public void setReservationLimit(double limit) { 174 iLimit = limit; 175 } 176 177 178 /** 179 * Academic areas 180 * @return selected academic areas 181 */ 182 public Set<String> getAcademicAreas() { 183 return iAcadAreas; 184 } 185 186 /** 187 * Academic area 188 * @return selected academic area 189 */ 190 @Deprecated 191 public String getAcademicArea() { 192 if (getAcademicAreas().isEmpty()) return ""; 193 return getAcademicAreas().iterator().next(); 194 } 195 196 /** 197 * Majors 198 * @return selected majors 199 */ 200 public Set<String> getMajors() { 201 return iMajors; 202 } 203 204 /** 205 * Minors 206 * @return selected minors 207 */ 208 public Set<String> getMinors() { 209 return iMinors; 210 } 211 212 /** 213 * Academic classifications 214 * @return selected academic classifications 215 */ 216 public Set<String> getClassifications() { 217 return iClassifications; 218 } 219 220 /** Concentrations for major */ 221 public Set<String> getConcentrations(String major) { 222 return (iConcentrations == null ? null : iConcentrations.get(major)); 223 } 224 225 /** Add concentration for major */ 226 public void addConcentration(String major, String concentration) { 227 if (iConcentrations == null) iConcentrations = new HashMap<String, Set<String>>(); 228 Set<String> concentrations = iConcentrations.get(major); 229 if (concentrations == null) { 230 concentrations = new HashSet<String>(); 231 iConcentrations.put(major, concentrations); 232 } 233 concentrations.add(concentration); 234 } 235 236 /** 237 * Check the area, classifications and majors 238 */ 239 @Override 240 public boolean isApplicable(Student student) { 241 if (!getMajors().isEmpty() || getMinors().isEmpty()) 242 for (AreaClassificationMajor acm: student.getAreaClassificationMajors()) 243 if (getAcademicAreas().contains(acm.getArea()) && 244 (getClassifications().isEmpty() || getClassifications().contains(acm.getClassification())) && 245 (getMajors().isEmpty() || getMajors().contains(acm.getMajor()))) { 246 Set<String> conc = getConcentrations(acm.getMajor()); 247 if (conc != null && !conc.isEmpty()) { 248 return acm.getConcentration() != null && conc.contains(acm.getConcentration()); 249 } else { 250 return true; 251 } 252 } 253 if (!getMinors().isEmpty()) 254 for (AreaClassificationMajor acm: student.getAreaClassificationMinors()) 255 if (getAcademicAreas().contains(acm.getArea()) && 256 (getClassifications().isEmpty() || getClassifications().contains(acm.getClassification())) && 257 (getMinors().contains(acm.getMajor()))) 258 return true; 259 return false; 260 } 261 262 263}