001    package net.sf.cpsolver.exam.criteria;
002    
003    import java.util.Set;
004    
005    import net.sf.cpsolver.exam.model.Exam;
006    import net.sf.cpsolver.exam.model.ExamInstructor;
007    import net.sf.cpsolver.exam.model.ExamModel;
008    import net.sf.cpsolver.exam.model.ExamPeriod;
009    import net.sf.cpsolver.exam.model.ExamPlacement;
010    import net.sf.cpsolver.ifs.util.DataProperties;
011    
012    /**
013     * Number of back-to-back distance instructor conflicts. I.e., number of
014     * cases when an exam is attended by an instructor that attends some other
015     * exam at the previous {@link ExamPeriod#prev()} or following
016     * {@link ExamPeriod#next()} period and the distance
017     * {@link ExamPlacement#getDistanceInMeters(ExamPlacement)} between these two exams
018     * is greater than {@link ExamModel#getBackToBackDistance()}. Distance
019     * back-to-back conflicts are only considered between consecutive periods
020     * that are of the same day.
021     * <br><br>
022     * Distance back-to-back instructor conflict weight can be set by problem
023     * property Exams.InstructorDistanceBackToBackConflictWeight, or in the
024     * input xml file, property instructorDistanceBackToBackConflictWeight.
025     * 
026     * <br>
027     * 
028     * @version ExamTT 1.2 (Examination Timetabling)<br>
029     *          Copyright (C) 2008 - 2012 Tomas Muller<br>
030     *          <a href="mailto:muller@unitime.org">muller@unitime.org</a><br>
031     *          <a href="http://muller.unitime.org">http://muller.unitime.org</a><br>
032     * <br>
033     *          This library is free software; you can redistribute it and/or modify
034     *          it under the terms of the GNU Lesser General Public License as
035     *          published by the Free Software Foundation; either version 3 of the
036     *          License, or (at your option) any later version. <br>
037     * <br>
038     *          This library is distributed in the hope that it will be useful, but
039     *          WITHOUT ANY WARRANTY; without even the implied warranty of
040     *          MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
041     *          Lesser General Public License for more details. <br>
042     * <br>
043     *          You should have received a copy of the GNU Lesser General Public
044     *          License along with this library; if not see
045     *          <a href='http://www.gnu.org/licenses/'>http://www.gnu.org/licenses/</a>.
046     */
047    public class InstructorDistanceBackToBackConflicts extends StudentDistanceBackToBackConflicts {
048        
049        @Override
050        public String getWeightName() {
051            return "Exams.InstructorDistanceBackToBackConflictWeight";
052        }
053        
054        @Override
055        public String getXmlWeightName() {
056            return "instructorDistanceBackToBackConflictWeight";
057        }
058    
059        @Override
060        public double getWeightDefault(DataProperties config) {
061            return 25.0;
062        }
063        
064        @Override
065        public double getValue(ExamPlacement value, Set<ExamPlacement> conflicts) {
066            Exam exam = value.variable();
067            double btbDist = getBackToBackDistance();
068            if (btbDist < 0)
069                return 0;
070            int penalty = 0;
071            for (ExamInstructor s : exam.getInstructors()) {
072                if (value.getPeriod().prev() != null) {
073                    if (value.getPeriod().prev().getDay() == value.getPeriod().getDay()) {
074                        for (Exam x : s.getExams(value.getPeriod().prev())) {
075                            if (x.equals(exam))
076                                continue;
077                            if (value.getDistanceInMeters(x.getAssignment()) > btbDist)
078                                penalty++;
079                        }
080                    }
081                }
082                if (value.getPeriod().next() != null) {
083                    if (value.getPeriod().next().getDay() == value.getPeriod().getDay()) {
084                        for (Exam x : s.getExams(value.getPeriod().next())) {
085                            if (x.equals(exam))
086                                continue;
087                            if (value.getDistanceInMeters(x.getAssignment()) > btbDist)
088                                penalty++;
089                        }
090                    }
091                }
092            }
093            return penalty;
094        }
095    
096        @Override
097        public String getName() {
098            return "Instructor Distance Back-To-Back Conflicts";
099        }
100        
101        @Override
102        public String toString() {
103            return (getValue() <= 0.0 ? "" : "iBTBd:" + sDoubleFormat.format(getValue()));
104        }
105        
106        @Override
107        public boolean isPeriodCriterion() { return false; }
108    }