001package org.cpsolver.coursett.model; 002 003import java.util.ArrayList; 004import java.util.HashSet; 005import java.util.LinkedList; 006import java.util.HashMap; 007import java.util.List; 008import java.util.Map; 009import java.util.Queue; 010import java.util.Set; 011 012import org.cpsolver.coursett.constraint.JenrlConstraint; 013import org.cpsolver.ifs.assignment.Assignment; 014 015 016/** 017 * Configuration. Each course can have multiple configurations. A student needs 018 * to be enrolled into classes of one of the configurations. 019 * 020 * @author Tomáš Müller 021 * @version CourseTT 1.3 (University Course Timetabling)<br> 022 * Copyright (C) 2006 - 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 */ 040 041public class Configuration { 042 private Long iConfigId = null; 043 private Long iOfferingId = null; 044 private HashMap<Long, Set<Lecture>> iTopLectures = new HashMap<Long, Set<Lecture>>(); 045 private List<Configuration> iAltConfigurations = null; 046 private int iLimit = -1; 047 private Set<Long> iSubpartIds = null; 048 049 public Configuration(Long offeringId, Long configId, int limit) { 050 iOfferingId = offeringId; 051 iConfigId = configId; 052 iLimit = limit; 053 } 054 055 public Long getOfferingId() { 056 return iOfferingId; 057 } 058 059 public Long getConfigId() { 060 return iConfigId; 061 } 062 063 public void addTopLecture(Lecture lecture) { 064 Set<Lecture> lectures = iTopLectures.get(lecture.getSchedulingSubpartId()); 065 if (lectures == null) { 066 lectures = new HashSet<Lecture>(); 067 iTopLectures.put(lecture.getSchedulingSubpartId(), lectures); 068 } 069 lectures.add(lecture); 070 iSubpartIds = null; 071 } 072 073 public Map<Long, Set<Lecture>> getTopLectures() { 074 return iTopLectures; 075 } 076 077 public Set<Long> getTopSubpartIds() { 078 return iTopLectures.keySet(); 079 } 080 081 public Set<Lecture> getTopLectures(Long subpartId) { 082 return iTopLectures.get(subpartId); 083 } 084 085 public void setAltConfigurations(List<Configuration> altConfigurations) { 086 iAltConfigurations = altConfigurations; 087 } 088 089 public void addAltConfiguration(Configuration configuration) { 090 if (iAltConfigurations == null) 091 iAltConfigurations = new ArrayList<Configuration>(); 092 iAltConfigurations.add(configuration); 093 } 094 095 public List<Configuration> getAltConfigurations() { 096 return iAltConfigurations; 097 } 098 099 public Set<Student> students() { 100 Set<Student> students = new HashSet<Student>(); 101 for (Set<Lecture> lectures: iTopLectures.values()) { 102 for (Lecture l : lectures) { 103 students.addAll(l.students()); 104 } 105 } 106 return students; 107 } 108 109 public boolean hasConflict(Assignment<Lecture, Placement> assignment, Student student) { 110 for (Lecture lecture : student.getLectures()) { 111 Placement placement = assignment.getValue(lecture); 112 if (placement == null || !this.equals(lecture.getConfiguration())) 113 continue; 114 if (student.countConflictPlacements(placement) > 0) 115 return true; 116 for (Lecture x : student.getLectures()) { 117 if (assignment.getValue(x) == null || x.equals(lecture)) 118 continue; 119 JenrlConstraint jenrl = lecture.jenrlConstraint(x); 120 if (jenrl != null && jenrl.isInConflict(assignment)) 121 return true; 122 } 123 } 124 return false; 125 } 126 127 public int getLimit() { 128 if (iLimit < 0) { 129 double totalWeight = 0.0; 130 for (Student s : students()) { 131 totalWeight += s.getOfferingWeight(getOfferingId()); 132 } 133 iLimit = (int) Math.round(totalWeight); 134 } 135 return iLimit; 136 } 137 138 @Override 139 public int hashCode() { 140 return getConfigId().hashCode(); 141 } 142 143 @Override 144 public boolean equals(Object o) { 145 if (o == null || !(o instanceof Configuration)) 146 return false; 147 return getConfigId().equals(((Configuration) o).getConfigId()); 148 } 149 150 public Set<Long> getSubpartIds() { 151 if (iSubpartIds == null) { 152 Set<Long> subparts = new HashSet<Long>(); 153 Queue<Lecture> queue = new LinkedList<Lecture>(); 154 for (Map.Entry<Long, Set<Lecture>> e: getTopLectures().entrySet()) { 155 subparts.add(e.getKey()); 156 queue.addAll(e.getValue()); 157 } 158 Lecture lecture = null; 159 while ((lecture = queue.poll()) != null) { 160 if (lecture.getChildren() != null) 161 for (Map.Entry<Long, List<Lecture>> e: lecture.getChildren().entrySet()) { 162 subparts.add(e.getKey()); 163 queue.addAll(e.getValue()); 164 } 165 } 166 iSubpartIds = subparts; 167 } 168 return iSubpartIds; 169 } 170 171 public int countSubparts() { 172 return getSubpartIds().size(); 173 } 174}