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 * @version CourseTT 1.3 (University Course Timetabling)<br> 021 * Copyright (C) 2006 - 2014 Tomáš Müller<br> 022 * <a href="mailto:muller@unitime.org">muller@unitime.org</a><br> 023 * <a href="http://muller.unitime.org">http://muller.unitime.org</a><br> 024 * <br> 025 * This library is free software; you can redistribute it and/or modify 026 * it under the terms of the GNU Lesser General Public License as 027 * published by the Free Software Foundation; either version 3 of the 028 * License, or (at your option) any later version. <br> 029 * <br> 030 * This library is distributed in the hope that it will be useful, but 031 * WITHOUT ANY WARRANTY; without even the implied warranty of 032 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 033 * Lesser General Public License for more details. <br> 034 * <br> 035 * You should have received a copy of the GNU Lesser General Public 036 * License along with this library; if not see 037 * <a href='http://www.gnu.org/licenses/'>http://www.gnu.org/licenses/</a>. 038 */ 039 040public class Configuration { 041 private Long iConfigId = null; 042 private Long iOfferingId = null; 043 private HashMap<Long, Set<Lecture>> iTopLectures = new HashMap<Long, Set<Lecture>>(); 044 private List<Configuration> iAltConfigurations = null; 045 private int iLimit = -1; 046 private Set<Long> iSubpartIds = null; 047 048 public Configuration(Long offeringId, Long configId, int limit) { 049 iOfferingId = offeringId; 050 iConfigId = configId; 051 iLimit = limit; 052 } 053 054 public Long getOfferingId() { 055 return iOfferingId; 056 } 057 058 public Long getConfigId() { 059 return iConfigId; 060 } 061 062 public void addTopLecture(Lecture lecture) { 063 Set<Lecture> lectures = iTopLectures.get(lecture.getSchedulingSubpartId()); 064 if (lectures == null) { 065 lectures = new HashSet<Lecture>(); 066 iTopLectures.put(lecture.getSchedulingSubpartId(), lectures); 067 } 068 lectures.add(lecture); 069 iSubpartIds = null; 070 } 071 072 public Map<Long, Set<Lecture>> getTopLectures() { 073 return iTopLectures; 074 } 075 076 public Set<Long> getTopSubpartIds() { 077 return iTopLectures.keySet(); 078 } 079 080 public Set<Lecture> getTopLectures(Long subpartId) { 081 return iTopLectures.get(subpartId); 082 } 083 084 public void setAltConfigurations(List<Configuration> altConfigurations) { 085 iAltConfigurations = altConfigurations; 086 } 087 088 public void addAltConfiguration(Configuration configuration) { 089 if (iAltConfigurations == null) 090 iAltConfigurations = new ArrayList<Configuration>(); 091 iAltConfigurations.add(configuration); 092 } 093 094 public List<Configuration> getAltConfigurations() { 095 return iAltConfigurations; 096 } 097 098 public Set<Student> students() { 099 Set<Student> students = new HashSet<Student>(); 100 for (Set<Lecture> lectures: iTopLectures.values()) { 101 for (Lecture l : lectures) { 102 students.addAll(l.students()); 103 } 104 } 105 return students; 106 } 107 108 public boolean hasConflict(Assignment<Lecture, Placement> assignment, Student student) { 109 for (Lecture lecture : student.getLectures()) { 110 Placement placement = assignment.getValue(lecture); 111 if (placement == null || !this.equals(lecture.getConfiguration())) 112 continue; 113 if (student.countConflictPlacements(placement) > 0) 114 return true; 115 for (Lecture x : student.getLectures()) { 116 if (assignment.getValue(x) == null || x.equals(lecture)) 117 continue; 118 JenrlConstraint jenrl = lecture.jenrlConstraint(x); 119 if (jenrl != null && jenrl.isInConflict(assignment)) 120 return true; 121 } 122 } 123 return false; 124 } 125 126 public int getLimit() { 127 if (iLimit < 0) { 128 double totalWeight = 0.0; 129 for (Student s : students()) { 130 totalWeight += s.getOfferingWeight(getOfferingId()); 131 } 132 iLimit = (int) Math.round(totalWeight); 133 } 134 return iLimit; 135 } 136 137 @Override 138 public int hashCode() { 139 return getConfigId().hashCode(); 140 } 141 142 @Override 143 public boolean equals(Object o) { 144 if (o == null || !(o instanceof Configuration)) 145 return false; 146 return getConfigId().equals(((Configuration) o).getConfigId()); 147 } 148 149 public Set<Long> getSubpartIds() { 150 if (iSubpartIds == null) { 151 Set<Long> subparts = new HashSet<Long>(); 152 Queue<Lecture> queue = new LinkedList<Lecture>(); 153 for (Map.Entry<Long, Set<Lecture>> e: getTopLectures().entrySet()) { 154 subparts.add(e.getKey()); 155 queue.addAll(e.getValue()); 156 } 157 Lecture lecture = null; 158 while ((lecture = queue.poll()) != null) { 159 if (lecture.getChildren() != null) 160 for (Map.Entry<Long, List<Lecture>> e: lecture.getChildren().entrySet()) { 161 subparts.add(e.getKey()); 162 queue.addAll(e.getValue()); 163 } 164 } 165 iSubpartIds = subparts; 166 } 167 return iSubpartIds; 168 } 169 170 public int countSubparts() { 171 return getSubpartIds().size(); 172 } 173}