    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}