    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}