001    package net.sf.cpsolver.studentsct.constraint;
002    
003    import java.util.Set;
004    
005    import net.sf.cpsolver.ifs.model.Constraint;
006    import net.sf.cpsolver.studentsct.model.Enrollment;
007    import net.sf.cpsolver.studentsct.model.Request;
008    import 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 Tomas Muller<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     */
036    public 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    }