001 package net.sf.cpsolver.exam.reports;
002
003 import java.text.DecimalFormat;
004 import java.util.Enumeration;
005 import java.util.Vector;
006
007 import net.sf.cpsolver.exam.model.Exam;
008 import net.sf.cpsolver.exam.model.ExamModel;
009 import net.sf.cpsolver.exam.model.ExamPlacement;
010 import net.sf.cpsolver.ifs.util.CSVFile;
011 import net.sf.cpsolver.ifs.util.CSVFile.CSVField;
012
013 /**
014 * Export student back-to-back conflicts between pairs of exams into a CSV file.
015 * <br><br>
016 * Usage:<br>
017 * <code>
018 * new ExamStudentBackToBackConflicts(model).report().save(file);
019 * </code>
020 * <br><br>
021 *
022 * @version
023 * ExamTT 1.1 (Examination Timetabling)<br>
024 * Copyright (C) 2008 Tomáš Müller<br>
025 * <a href="mailto:muller@unitime.org">muller@unitime.org</a><br>
026 * Lazenska 391, 76314 Zlin, Czech Republic<br>
027 * <br>
028 * This library is free software; you can redistribute it and/or
029 * modify it under the terms of the GNU Lesser General Public
030 * License as published by the Free Software Foundation; either
031 * version 2.1 of the License, or (at your option) any later version.
032 * <br><br>
033 * This library is distributed in the hope that it will be useful,
034 * but WITHOUT ANY WARRANTY; without even the implied warranty of
035 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
036 * Lesser General Public License for more details.
037 * <br><br>
038 * You should have received a copy of the GNU Lesser General Public
039 * License along with this library; if not, write to the Free Software
040 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
041 */
042 public class ExamStudentBackToBackConflicts {
043 private ExamModel iModel = null;
044
045 /**
046 * Constructor
047 * @param model examination timetabling model
048 */
049 public ExamStudentBackToBackConflicts(ExamModel model) {
050 iModel = model;
051 }
052
053 /**
054 * generate report
055 */
056 public CSVFile report() {
057 CSVFile csv = new CSVFile();
058 csv.setHeader(new CSVField[] {
059 new CSVField("Exam 1"),
060 new CSVField("Enrl 1"),
061 new CSVField("Period 1"),
062 new CSVField("Date 1"),
063 new CSVField("Time 1"),
064 new CSVField("Exam 2"),
065 new CSVField("Enrl 2"),
066 new CSVField("Back-To-Back"),
067 new CSVField("Back-To-Back [%]"),
068 new CSVField("Distance")
069 });
070 DecimalFormat df = new DecimalFormat("0.0");
071 for (Enumeration e=iModel.variables().elements();e.hasMoreElements();) {
072 Exam ex1 = (Exam)e.nextElement();
073 ExamPlacement p1 = (ExamPlacement)ex1.getAssignment();
074 if (p1==null || p1.getPeriod().next()==null) continue;
075 if (!iModel.isDayBreakBackToBack() && p1.getPeriod().getDay()!=p1.getPeriod().next().getDay()) continue;
076 for (Enumeration f=iModel.variables().elements();f.hasMoreElements();) {
077 Exam ex2 = (Exam)f.nextElement();
078 ExamPlacement p2 = (ExamPlacement)ex2.getAssignment();
079 if (p2==null || !p2.getPeriod().equals(p1.getPeriod().next())) continue;
080 Vector students = (Vector)ex1.getJointEnrollments().get(ex2);
081 if (students==null || students.isEmpty()) continue;
082 String distStr = "";
083 if (iModel.getBackToBackDistance()>=0) {
084 int dist = p1.getDistance(p2);
085 if (dist>0) distStr=String.valueOf(dist);
086 }
087 csv.addLine(new CSVField[] {
088 new CSVField(ex1.getName()),
089 new CSVField(ex1.getStudents().size()),
090 new CSVField(p1.getPeriod().getIndex()+1),
091 new CSVField(p1.getPeriod().getDayStr()),
092 new CSVField(p1.getPeriod().getTimeStr()),
093 new CSVField(ex2.getName()),
094 new CSVField(ex2.getStudents().size()),
095 new CSVField(students.size()),
096 new CSVField(df.format(100.0*students.size()/Math.min(ex1.getStudents().size(),ex2.getStudents().size()))),
097 new CSVField(distStr)
098 });
099 }
100 }
101 return csv;
102 }
103 }