001package net.sf.cpsolver.exam.reports; 002 003import net.sf.cpsolver.exam.criteria.StudentBackToBackConflicts; 004import net.sf.cpsolver.exam.criteria.StudentDistanceBackToBackConflicts; 005import net.sf.cpsolver.exam.model.Exam; 006import net.sf.cpsolver.exam.model.ExamModel; 007import net.sf.cpsolver.exam.model.ExamOwner; 008import net.sf.cpsolver.exam.model.ExamPeriod; 009import net.sf.cpsolver.exam.model.ExamPlacement; 010import net.sf.cpsolver.exam.model.ExamRoomPlacement; 011import net.sf.cpsolver.exam.model.ExamStudent; 012import net.sf.cpsolver.ifs.util.CSVFile; 013import net.sf.cpsolver.ifs.util.CSVFile.CSVField; 014 015/** 016 * Export student direct, back-to-back, and more than two exams a day conflicts 017 * into a CSV file. <br> 018 * <br> 019 * Usage:<br> 020 * <code> 021 * new ExamStudentConflicts(model).report().save(file); 022 * </code> <br> 023 * <br> 024 * 025 * @version ExamTT 1.2 (Examination Timetabling)<br> 026 * Copyright (C) 2008 - 2010 Tomáš Müller<br> 027 * <a href="mailto:muller@unitime.org">muller@unitime.org</a><br> 028 * <a href="http://muller.unitime.org">http://muller.unitime.org</a><br> 029 * <br> 030 * This library is free software; you can redistribute it and/or modify 031 * it under the terms of the GNU Lesser General Public License as 032 * published by the Free Software Foundation; either version 3 of the 033 * License, or (at your option) any later version. <br> 034 * <br> 035 * This library is distributed in the hope that it will be useful, but 036 * WITHOUT ANY WARRANTY; without even the implied warranty of 037 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 038 * Lesser General Public License for more details. <br> 039 * <br> 040 * You should have received a copy of the GNU Lesser General Public 041 * License along with this library; if not see 042 * <a href='http://www.gnu.org/licenses/'>http://www.gnu.org/licenses/</a>. 043 */ 044public class ExamStudentConflicts { 045 private ExamModel iModel = null; 046 047 /** 048 * Constructor 049 * 050 * @param model 051 * examination timetabling model 052 */ 053 public ExamStudentConflicts(ExamModel model) { 054 iModel = model; 055 } 056 057 /** 058 * generate report 059 */ 060 public CSVFile report() { 061 CSVFile csv = new CSVFile(); 062 csv.setHeader(new CSVField[] { new CSVField("Student"), new CSVField("Type"), new CSVField("Section/Course"), 063 new CSVField("Period"), new CSVField("Day"), new CSVField("Time"), new CSVField("Room"), 064 new CSVField("Distance") }); 065 boolean isDayBreakBackToBack = ((StudentBackToBackConflicts)iModel.getCriterion(StudentBackToBackConflicts.class)).isDayBreakBackToBack(); 066 double backToBackDistance = ((StudentDistanceBackToBackConflicts)iModel.getCriterion(StudentDistanceBackToBackConflicts.class)).getBackToBackDistance(); 067 for (ExamStudent student : iModel.getStudents()) { 068 for (ExamPeriod period : iModel.getPeriods()) { 069 int nrExams = student.getExams(period).size(); 070 if (nrExams > 1) { 071 String sections = ""; 072 String rooms = ""; 073 String periods = String.valueOf(period.getIndex() + 1); 074 String periodDays = period.getDayStr(); 075 String periodTimes = period.getTimeStr(); 076 for (Exam exam : student.getExams(period)) { 077 ExamPlacement placement = exam.getAssignment(); 078 String roomsThisExam = ""; 079 for (ExamRoomPlacement room : placement.getRoomPlacements()) { 080 if (roomsThisExam.length() > 0) 081 roomsThisExam += ", "; 082 roomsThisExam += room.getName(); 083 } 084 boolean first = true; 085 for (ExamOwner cs : exam.getOwners(student)) { 086 if (sections.length() > 0) { 087 sections += "\n"; 088 rooms += "\n"; 089 periods += "\n"; 090 periodDays += "\n"; 091 periodTimes += "\n"; 092 } 093 sections += cs.getName(); 094 if (first) 095 rooms += roomsThisExam; 096 first = false; 097 } 098 if (exam.getOwners(student).isEmpty()) { 099 sections += exam.getName(); 100 rooms += roomsThisExam; 101 } 102 } 103 csv.addLine(new CSVField[] { new CSVField(student.getName()), new CSVField("direct"), 104 new CSVField(sections), new CSVField(periods), new CSVField(periodDays), 105 new CSVField(periodTimes), new CSVField(rooms) }); 106 } 107 if (nrExams > 0) { 108 if (period.next() != null && !student.getExams(period.next()).isEmpty() 109 && (!isDayBreakBackToBack || period.next().getDay() == period.getDay())) { 110 for (Exam ex1 : student.getExams(period)) { 111 for (Exam ex2 : student.getExams(period.next())) { 112 ExamPlacement placement = ex1.getAssignment(); 113 String sections = ""; 114 String rooms = ""; 115 String roomsThisExam = ""; 116 String periods = String.valueOf(period.getIndex() + 1); 117 String periodDays = period.getDayStr(); 118 String periodTimes = period.getTimeStr(); 119 for (ExamRoomPlacement room : placement.getRoomPlacements()) { 120 if (roomsThisExam.length() > 0) 121 roomsThisExam += ", "; 122 roomsThisExam += room.getName(); 123 } 124 boolean first = true; 125 for (ExamOwner cs : ex1.getOwners(student)) { 126 if (sections.length() > 0) { 127 sections += "\n"; 128 rooms += "\n"; 129 periods += "\n"; 130 periodDays += "\n"; 131 periodTimes += "\n"; 132 } 133 sections += cs.getName(); 134 if (first) 135 rooms += roomsThisExam; 136 first = false; 137 } 138 if (ex1.getOwners(student).isEmpty()) { 139 sections += ex1.getName(); 140 rooms += roomsThisExam; 141 } 142 placement = ex2.getAssignment(); 143 roomsThisExam = ""; 144 for (ExamRoomPlacement room : placement.getRoomPlacements()) { 145 if (roomsThisExam.length() > 0) 146 roomsThisExam += ", "; 147 roomsThisExam += room.getName(); 148 } 149 first = true; 150 for (ExamOwner cs : ex2.getOwners(student)) { 151 sections += "\n"; 152 rooms += "\n"; 153 periods += "\n"; 154 periodDays += "\n"; 155 periodTimes += "\n"; 156 sections += cs.getName(); 157 if (first) { 158 rooms += roomsThisExam; 159 periods += String.valueOf(period.next().getIndex() + 1); 160 periodDays += period.next().getDayStr(); 161 periodTimes += period.next().getTimeStr(); 162 } 163 first = false; 164 } 165 if (ex2.getOwners(student).isEmpty()) { 166 sections += "\n"; 167 rooms += "\n"; 168 periods += "\n"; 169 periodDays += "\n"; 170 periodTimes += "\n"; 171 sections += ex2.getName(); 172 rooms += roomsThisExam; 173 periods += String.valueOf(period.next().getIndex() + 1); 174 periodDays += period.next().getDayStr(); 175 periodTimes += period.next().getTimeStr(); 176 rooms += roomsThisExam; 177 } 178 String distStr = ""; 179 if (backToBackDistance >= 0) { 180 double dist = (ex1.getAssignment()).getDistanceInMeters(ex2.getAssignment()); 181 if (dist > 0) 182 distStr = String.valueOf(dist); 183 } 184 csv.addLine(new CSVField[] { new CSVField(student.getName()), 185 new CSVField("back-to-back"), new CSVField(sections), new CSVField(periods), 186 new CSVField(periodDays), new CSVField(periodTimes), new CSVField(rooms), 187 new CSVField(distStr) }); 188 } 189 } 190 } 191 } 192 if (period.next() == null || period.next().getDay() != period.getDay()) { 193 int nrExamsADay = student.getExamsADay(period.getDay()).size(); 194 if (nrExamsADay > 2) { 195 String sections = ""; 196 String periods = ""; 197 String periodDays = ""; 198 String periodTimes = ""; 199 String rooms = ""; 200 for (Exam exam : student.getExamsADay(period.getDay())) { 201 ExamPlacement placement = exam.getAssignment(); 202 String roomsThisExam = ""; 203 for (ExamRoomPlacement room : placement.getRoomPlacements()) { 204 if (roomsThisExam.length() > 0) 205 roomsThisExam += ", "; 206 roomsThisExam += room.getName(); 207 } 208 boolean first = true; 209 for (ExamOwner cs : exam.getOwners(student)) { 210 if (sections.length() > 0) { 211 sections += "\n"; 212 rooms += "\n"; 213 periods += "\n"; 214 periodDays += "\n"; 215 periodTimes += "\n"; 216 } 217 sections += cs.getName(); 218 if (first) { 219 periods += (placement.getPeriod().getIndex() + 1); 220 periodDays += placement.getPeriod().getDayStr(); 221 periodTimes += placement.getPeriod().getTimeStr(); 222 rooms += roomsThisExam; 223 } 224 first = false; 225 } 226 if (exam.getOwners(student).isEmpty()) { 227 if (sections.length() > 0) { 228 sections += "\n"; 229 rooms += "\n"; 230 periods += "\n"; 231 periodDays += "\n"; 232 periodTimes += "\n"; 233 } 234 sections += exam.getName(); 235 periods += (placement.getPeriod().getIndex() + 1); 236 periodDays += placement.getPeriod().getDayStr(); 237 periodTimes += placement.getPeriod().getTimeStr(); 238 rooms += roomsThisExam; 239 } 240 } 241 csv.addLine(new CSVField[] { new CSVField(student.getName()), new CSVField("more-2-day"), 242 new CSVField(sections), new CSVField(periods), new CSVField(periodDays), 243 new CSVField(periodTimes), new CSVField(rooms) }); 244 } 245 } 246 } 247 } 248 return csv; 249 } 250}