001 package net.sf.cpsolver.exam.reports;
002
003 import java.text.DecimalFormat;
004
005 import net.sf.cpsolver.exam.criteria.StudentBackToBackConflicts;
006 import net.sf.cpsolver.exam.criteria.StudentDirectConflicts;
007 import net.sf.cpsolver.exam.criteria.StudentDistanceBackToBackConflicts;
008 import net.sf.cpsolver.exam.criteria.StudentMoreThan2ADayConflicts;
009 import net.sf.cpsolver.exam.criteria.StudentNotAvailableConflicts;
010 import net.sf.cpsolver.exam.model.Exam;
011 import net.sf.cpsolver.exam.model.ExamModel;
012 import net.sf.cpsolver.exam.model.ExamPlacement;
013 import net.sf.cpsolver.ifs.util.CSVFile;
014 import net.sf.cpsolver.ifs.util.CSVFile.CSVField;
015
016 /**
017 * Export student direct, back-to-back, and more than two exams a day conflicts
018 * summarized for each exam into a CSV file. <br>
019 * <br>
020 * Usage:<br>
021 * <code>
022 * new ExamStudentConflictsPerExam(model).report().save(file);
023 * </code> <br>
024 * <br>
025 *
026 * @version ExamTT 1.2 (Examination Timetabling)<br>
027 * Copyright (C) 2008 - 2010 Tomas Muller<br>
028 * <a href="mailto:muller@unitime.org">muller@unitime.org</a><br>
029 * <a href="http://muller.unitime.org">http://muller.unitime.org</a><br>
030 * <br>
031 * This library is free software; you can redistribute it and/or modify
032 * it under the terms of the GNU Lesser General Public License as
033 * published by the Free Software Foundation; either version 3 of the
034 * License, or (at your option) any later version. <br>
035 * <br>
036 * This library is distributed in the hope that it will be useful, but
037 * WITHOUT ANY WARRANTY; without even the implied warranty of
038 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
039 * Lesser General Public License for more details. <br>
040 * <br>
041 * You should have received a copy of the GNU Lesser General Public
042 * License along with this library; if not see
043 * <a href='http://www.gnu.org/licenses/'>http://www.gnu.org/licenses/</a>.
044 */
045 public class ExamStudentConflictsPerExam {
046 private ExamModel iModel = null;
047
048 /**
049 * Constructor
050 *
051 * @param model
052 * examination timetabling model
053 */
054 public ExamStudentConflictsPerExam(ExamModel model) {
055 iModel = model;
056 }
057
058 /**
059 * generate report
060 */
061 public CSVFile report() {
062 CSVFile csv = new CSVFile();
063 csv.setHeader(new CSVField[] { new CSVField("Exam"), new CSVField("Enrl"), new CSVField("Direct"),
064 new CSVField("Direct [%]"), new CSVField("More-2-Day"), new CSVField("More-2-Day [%]"),
065 new CSVField("Back-To-Back"), new CSVField("Back-To-Back [%]"), new CSVField("Dist Back-To-Back"),
066 new CSVField("Dist Back-To-Back [%]") });
067 DecimalFormat df = new DecimalFormat("0.0");
068 for (Exam exam : iModel.variables()) {
069 ExamPlacement placement = exam.getAssignment();
070 if (placement == null)
071 continue;
072 int dc = (int)iModel.getCriterion(StudentDirectConflicts.class).getValue(placement, null) +
073 (int)iModel.getCriterion(StudentNotAvailableConflicts.class).getValue(placement, null);
074 int btb = (int)iModel.getCriterion(StudentBackToBackConflicts.class).getValue(placement, null);
075 int dbtb = (int)iModel.getCriterion(StudentDistanceBackToBackConflicts.class).getValue(placement, null);
076 int m2d = (int)iModel.getCriterion(StudentMoreThan2ADayConflicts.class).getValue(placement, null);
077 if (dc == 0 && m2d == 0 && btb == 0 && dbtb == 0)
078 continue;
079 /*
080 * String section = ""; for (Enumeration
081 * f=exam.getCourseSections().elements();f.hasMoreElements();) {
082 * ExamCourseSection cs = (ExamCourseSection)f.nextElement(); if
083 * (section.length()>0) section+="\n"; section += cs.getName(); }
084 */
085 csv.addLine(new CSVField[] {
086 new CSVField(exam.getName()),
087 new CSVField(exam.getStudents().size()),
088 new CSVField(dc),
089 new CSVField(df.format(100.0 * dc / exam.getStudents().size())),
090 new CSVField(m2d),
091 new CSVField(df.format(100.0 * m2d / exam.getStudents().size())),
092 new CSVField(btb),
093 new CSVField(df.format(100.0 * btb / exam.getStudents().size())),
094 new CSVField(dbtb),
095 new CSVField(df.format(100.0 * dbtb / exam.getStudents().size())) });
096 }
097 return csv;
098 }
099 }