001package net.sf.cpsolver.exam.reports;
002
003import java.text.DecimalFormat;
004import java.util.List;
005
006import net.sf.cpsolver.exam.model.Exam;
007import net.sf.cpsolver.exam.model.ExamModel;
008import net.sf.cpsolver.exam.model.ExamPlacement;
009import net.sf.cpsolver.exam.model.ExamStudent;
010import net.sf.cpsolver.ifs.util.CSVFile;
011import net.sf.cpsolver.ifs.util.CSVFile.CSVField;
012
013/**
014 * Export student more than two exams a day conflicts between triplets of exams
015 * into a CSV file. <br>
016 * <br>
017 * Usage:<br>
018 * <code>
019 * &nbsp;&nbsp;&nbsp;&nbsp;new ExamStudentMoreTwoADay(model).report().save(file);
020 * </code> <br>
021 * <br>
022 * 
023 * @version ExamTT 1.2 (Examination Timetabling)<br>
024 *          Copyright (C) 2008 - 2010 Tomáš Müller<br>
025 *          <a href="mailto:muller@unitime.org">muller@unitime.org</a><br>
026 *          <a href="http://muller.unitime.org">http://muller.unitime.org</a><br>
027 * <br>
028 *          This library is free software; you can redistribute it and/or modify
029 *          it under the terms of the GNU Lesser General Public License as
030 *          published by the Free Software Foundation; either version 3 of the
031 *          License, or (at your option) any later version. <br>
032 * <br>
033 *          This library is distributed in the hope that it will be useful, but
034 *          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. <br>
037 * <br>
038 *          You should have received a copy of the GNU Lesser General Public
039 *          License along with this library; if not see
040 *          <a href='http://www.gnu.org/licenses/'>http://www.gnu.org/licenses/</a>.
041 */
042public class ExamStudentMoreTwoADay {
043    private ExamModel iModel = null;
044
045    /**
046     * Constructor
047     * 
048     * @param model
049     *            examination timetabling model
050     */
051    public ExamStudentMoreTwoADay(ExamModel model) {
052        iModel = model;
053    }
054
055    /**
056     * generate report
057     */
058    public CSVFile report() {
059        CSVFile csv = new CSVFile();
060        csv.setHeader(new CSVField[] { new CSVField("Exam 1"), new CSVField("Enrl 1"), new CSVField("Period 1"),
061                new CSVField("Date 1"), new CSVField("Time 1"), new CSVField("Exam 2"), new CSVField("Enrl 2"),
062                new CSVField("Period 2"), new CSVField("Time 2"), new CSVField("Exam 3"), new CSVField("Enrl 3"),
063                new CSVField("Period 3"), new CSVField("Time 3"), new CSVField("More-2-Day"),
064                new CSVField("More-2-Day [%]") });
065        DecimalFormat df = new DecimalFormat("0.0");
066        for (Exam ex1 : iModel.variables()) {
067            ExamPlacement p1 = ex1.getAssignment();
068            if (p1 == null)
069                continue;
070            for (Exam ex2 : iModel.variables()) {
071                if (ex2.equals(ex1))
072                    continue;
073                ExamPlacement p2 = ex2.getAssignment();
074                if (p2 == null || p2.getPeriod().getDay() != p1.getPeriod().getDay()
075                        || p2.getPeriod().getIndex() < p1.getPeriod().getIndex())
076                    continue;
077                if (p1.getPeriod().equals(p2.getPeriod()) && ex1.getId() >= ex2.getId())
078                    continue;
079                List<ExamStudent> students = ex1.getJointEnrollments().get(ex2);
080                if (students == null || students.isEmpty())
081                    continue;
082                for (Exam ex3 : iModel.variables()) {
083                    if (ex3.equals(ex2) || ex3.equals(ex1))
084                        continue;
085                    ExamPlacement p3 = ex3.getAssignment();
086                    if (p3 == null || p3.getPeriod().getDay() != p2.getPeriod().getDay()
087                            || p3.getPeriod().getIndex() < p2.getPeriod().getIndex())
088                        continue;
089                    if (p1.getPeriod().equals(p3.getPeriod()) && ex1.getId() >= ex3.getId())
090                        continue;
091                    if (p2.getPeriod().equals(p3.getPeriod()) && ex2.getId() >= ex3.getId())
092                        continue;
093                    int m2d = 0;
094                    for (ExamStudent h : ex3.getStudents())
095                        if (students.contains(h))
096                            m2d++;
097                    if (m2d == 0)
098                        continue;
099                    csv.addLine(new CSVField[] {
100                            new CSVField(ex1.getName()),
101                            new CSVField(ex1.getStudents().size()),
102                            new CSVField(p1.getPeriod().getIndex() + 1),
103                            new CSVField(p1.getPeriod().getDayStr()),
104                            new CSVField(p1.getPeriod().getTimeStr()),
105                            new CSVField(ex2.getName()),
106                            new CSVField(ex2.getStudents().size()),
107                            new CSVField(p2.getPeriod().getIndex() + 1),
108                            new CSVField(p2.getPeriod().getTimeStr()),
109                            new CSVField(ex3.getName()),
110                            new CSVField(ex3.getStudents().size()),
111                            new CSVField(p3.getPeriod().getIndex() + 1),
112                            new CSVField(p3.getPeriod().getTimeStr()),
113                            new CSVField(m2d),
114                            new CSVField(df.format(100.0
115                                    * m2d
116                                    / Math.min(Math.min(ex1.getStudents().size(), ex2.getStudents().size()), ex3
117                                            .getStudents().size()))) });
118                }
119            }
120        }
121        return csv;
122    }
123}