    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}