001package org.cpsolver.exam.reports;
002
003import java.text.DecimalFormat;
004import java.util.List;
005
006import org.cpsolver.exam.model.Exam;
007import org.cpsolver.exam.model.ExamModel;
008import org.cpsolver.exam.model.ExamPlacement;
009import org.cpsolver.exam.model.ExamStudent;
010import org.cpsolver.ifs.assignment.Assignment;
011import org.cpsolver.ifs.util.CSVFile;
012import org.cpsolver.ifs.util.CSVFile.CSVField;
013
014
015/**
016 * Export student more than two exams a day conflicts between triplets of exams
017 * into a CSV file. <br>
018 * <br>
019 * Usage:
020 * <pre><code>
021 * &nbsp;&nbsp;&nbsp;&nbsp;new ExamStudentMoreTwoADay(model).report().save(file);
022 * </code></pre>
023 * <br>
024 * 
025 * @author  Tomáš Müller
026 * @version ExamTT 1.3 (Examination Timetabling)<br>
027 *          Copyright (C) 2008 - 2014 Tomáš Müller<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 */
045public class ExamStudentMoreTwoADay {
046    private ExamModel iModel = null;
047
048    /**
049     * Constructor
050     * 
051     * @param model
052     *            examination timetabling model
053     */
054    public ExamStudentMoreTwoADay(ExamModel model) {
055        iModel = model;
056    }
057
058    /**
059     * generate report
060     * @param assignment current assignment
061     * @return resultant report
062     */
063    public CSVFile report(Assignment<Exam, ExamPlacement> assignment) {
064        CSVFile csv = new CSVFile();
065        csv.setHeader(new CSVField[] { new CSVField("Exam 1"), new CSVField("Enrl 1"), new CSVField("Period 1"),
066                new CSVField("Date 1"), new CSVField("Time 1"), new CSVField("Exam 2"), new CSVField("Enrl 2"),
067                new CSVField("Period 2"), new CSVField("Time 2"), new CSVField("Exam 3"), new CSVField("Enrl 3"),
068                new CSVField("Period 3"), new CSVField("Time 3"), new CSVField("More-2-Day"),
069                new CSVField("More-2-Day [%]") });
070        DecimalFormat df = new DecimalFormat("0.0");
071        for (Exam ex1 : iModel.variables()) {
072            ExamPlacement p1 = assignment.getValue(ex1);
073            if (p1 == null)
074                continue;
075            for (Exam ex2 : iModel.variables()) {
076                if (ex2.equals(ex1))
077                    continue;
078                ExamPlacement p2 = assignment.getValue(ex2);
079                if (p2 == null || p2.getPeriod().getDay() != p1.getPeriod().getDay()
080                        || p2.getPeriod().getIndex() < p1.getPeriod().getIndex())
081                    continue;
082                if (p1.getPeriod().equals(p2.getPeriod()) && ex1.getId() >= ex2.getId())
083                    continue;
084                List<ExamStudent> students = ex1.getJointEnrollments().get(ex2);
085                if (students == null || students.isEmpty())
086                    continue;
087                for (Exam ex3 : iModel.variables()) {
088                    if (ex3.equals(ex2) || ex3.equals(ex1))
089                        continue;
090                    ExamPlacement p3 = assignment.getValue(ex3);
091                    if (p3 == null || p3.getPeriod().getDay() != p2.getPeriod().getDay()
092                            || p3.getPeriod().getIndex() < p2.getPeriod().getIndex())
093                        continue;
094                    if (p1.getPeriod().equals(p3.getPeriod()) && ex1.getId() >= ex3.getId())
095                        continue;
096                    if (p2.getPeriod().equals(p3.getPeriod()) && ex2.getId() >= ex3.getId())
097                        continue;
098                    int m2d = 0;
099                    for (ExamStudent h : ex3.getStudents())
100                        if (students.contains(h))
101                            m2d++;
102                    if (m2d == 0)
103                        continue;
104                    csv.addLine(new CSVField[] {
105                            new CSVField(ex1.getName()),
106                            new CSVField(ex1.getStudents().size()),
107                            new CSVField(p1.getPeriod().getIndex() + 1),
108                            new CSVField(p1.getPeriod().getDayStr()),
109                            new CSVField(p1.getPeriod().getTimeStr()),
110                            new CSVField(ex2.getName()),
111                            new CSVField(ex2.getStudents().size()),
112                            new CSVField(p2.getPeriod().getIndex() + 1),
113                            new CSVField(p2.getPeriod().getTimeStr()),
114                            new CSVField(ex3.getName()),
115                            new CSVField(ex3.getStudents().size()),
116                            new CSVField(p3.getPeriod().getIndex() + 1),
117                            new CSVField(p3.getPeriod().getTimeStr()),
118                            new CSVField(m2d),
119                            new CSVField(df.format(100.0
120                                    * m2d
121                                    / Math.min(Math.min(ex1.getStudents().size(), ex2.getStudents().size()), ex3
122                                            .getStudents().size()))) });
123                }
124            }
125        }
126        return csv;
127    }
128}