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 * 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}