001package net.sf.cpsolver.studentsct.constraint;
002
003import java.util.Set;
004
005import net.sf.cpsolver.ifs.model.Constraint;
006import net.sf.cpsolver.studentsct.model.Enrollment;
007import net.sf.cpsolver.studentsct.model.Request;
008import net.sf.cpsolver.studentsct.model.Student;
009
010/**
011 * This constraints ensures that a student is not enrolled into sections that
012 * are overlapping in time.
013 * 
014 * <br>
015 * <br>
016 * 
017 * @version StudentSct 1.2 (Student Sectioning)<br>
018 *          Copyright (C) 2007 - 2010 Tomáš Müller<br>
019 *          <a href="mailto:muller@unitime.org">muller@unitime.org</a><br>
020 *          <a href="http://muller.unitime.org">http://muller.unitime.org</a><br>
021 * <br>
022 *          This library is free software; you can redistribute it and/or modify
023 *          it under the terms of the GNU Lesser General Public License as
024 *          published by the Free Software Foundation; either version 3 of the
025 *          License, or (at your option) any later version. <br>
026 * <br>
027 *          This library is distributed in the hope that it will be useful, but
028 *          WITHOUT ANY WARRANTY; without even the implied warranty of
029 *          MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
030 *          Lesser General Public License for more details. <br>
031 * <br>
032 *          You should have received a copy of the GNU Lesser General Public
033 *          License along with this library; if not see
034 *          <a href='http://www.gnu.org/licenses/'>http://www.gnu.org/licenses/</a>.
035 */
036public class StudentConflict extends Constraint<Request, Enrollment> {
037    
038    /**
039     * Constructor
040     * @param student student for which the constraint is created
041     */
042    public StudentConflict(Student student) {
043        super();
044        for (Request request : student.getRequests())
045            addVariable(request);
046    }
047
048    /**
049     * A given enrollment is conflicting when the student is enrolled into
050     * another course / free time request that has an assignment that is
051     * overlapping with one or more assignments of the given section. See
052     * {@link Enrollment#isOverlapping(Enrollment)} for more details. All such
053     * overlapping enrollments are added into the provided set of conflicts.
054     * 
055     * @param enrollment
056     *            {@link Enrollment} that is being considered
057     * @param conflicts
058     *            resultant list of conflicting enrollments
059     */
060    @Override
061    public void computeConflicts(Enrollment enrollment, Set<Enrollment> conflicts) {
062        // for all assigned course requests -> if overlapping with this
063        // enrollment -> conflict
064        for (Request request : assignedVariables()) {
065            if (request.equals(enrollment.getRequest()))
066                continue;
067            if (enrollment.isOverlapping(request.getAssignment()))
068                conflicts.add(request.getAssignment());
069        }
070
071        // if this enrollment cannot be assigned (student already has a full
072        // schedule) -> unassignd a lowest priority request
073        if (!enrollment.getAssignments().isEmpty() && !enrollment.getStudent().canAssign(enrollment.getRequest())) {
074            Enrollment lowestPriorityEnrollment = null;
075            int lowestPriority = -1;
076            for (Request request : assignedVariables()) {
077                if (request.equals(enrollment.getRequest()))
078                    continue;
079                if (lowestPriority < request.getPriority()) {
080                    lowestPriority = request.getPriority();
081                    lowestPriorityEnrollment = request.getAssignment();
082                }
083            }
084            if (lowestPriorityEnrollment != null)
085                conflicts.add(lowestPriorityEnrollment);
086        }
087    }
088
089    /** Two enrollments are consistent if they are not overlapping in time */
090    @Override
091    public boolean isConsistent(Enrollment e1, Enrollment e2) {
092        return !e1.isOverlapping(e2);
093    }
094
095    /**
096     * A given enrollment is conflicting when the student is enrolled into
097     * another course / free time request that has an assignment that is
098     * overlapping with one or more assignments of the given section. See
099     * {@link Enrollment#isOverlapping(Enrollment)} for more details.
100     * 
101     * @param enrollment
102     *            {@link Enrollment} that is being considered
103     * @return true, if the student is enrolled into another enrollment of a
104     *         different request that is overlapping in time with the given
105     *         enrollment
106     */
107    @Override
108    public boolean inConflict(Enrollment enrollment) {
109        // for all assigned course requests -> if overlapping with this
110        // enrollment -> conflict
111        for (Request request : assignedVariables()) {
112            if (request.equals(enrollment.getRequest()))
113                continue;
114            if (enrollment.isOverlapping(request.getAssignment()))
115                return true;
116        }
117
118        // if this enrollment cannot be assigned (student already has a full
119        // schedule) -> conflict
120        if (!enrollment.getStudent().canAssign(enrollment.getRequest()))
121            return true;
122
123        // nothing above -> no conflict
124        return false;
125    }
126
127    @Override
128    public String toString() {
129        return "StudentConflicts";
130    }
131}