001package net.sf.cpsolver.exam.reports; 002 003import net.sf.cpsolver.exam.criteria.InstructorBackToBackConflicts; 004import net.sf.cpsolver.exam.criteria.InstructorDistanceBackToBackConflicts; 005import net.sf.cpsolver.exam.model.Exam; 006import net.sf.cpsolver.exam.model.ExamInstructor; 007import net.sf.cpsolver.exam.model.ExamModel; 008import net.sf.cpsolver.exam.model.ExamOwner; 009import net.sf.cpsolver.exam.model.ExamPeriod; 010import net.sf.cpsolver.exam.model.ExamPlacement; 011import net.sf.cpsolver.exam.model.ExamRoomPlacement; 012import net.sf.cpsolver.ifs.util.CSVFile; 013import net.sf.cpsolver.ifs.util.CSVFile.CSVField; 014 015/** 016 * Export instructor direct, back-to-back, and more than two exams a day 017 * conflicts into a CSV file. <br> 018 * <br> 019 * Usage:<br> 020 * <code> 021 * new ExamInstructorConflicts(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 ExamInstructorConflicts { 045 private ExamModel iModel = null; 046 047 /** 048 * Constructor 049 * 050 * @param model 051 * examination timetabling model 052 */ 053 public ExamInstructorConflicts(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("Instructor"), new CSVField("Type"), 063 new CSVField("Section/Course"), new CSVField("Period"), new CSVField("Day"), new CSVField("Time"), 064 new CSVField("Room"), new CSVField("Distance") }); 065 boolean isDayBreakBackToBack = ((InstructorBackToBackConflicts)iModel.getCriterion(InstructorBackToBackConflicts.class)).isDayBreakBackToBack(); 066 double backToBackDistance = ((InstructorDistanceBackToBackConflicts)iModel.getCriterion(InstructorDistanceBackToBackConflicts.class)).getBackToBackDistance(); 067 for (ExamInstructor instructor : iModel.getInstructors()) { 068 for (ExamPeriod period : iModel.getPeriods()) { 069 int nrExams = instructor.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 : instructor.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 owner : exam.getOwners(instructor)) { 086 if (sections.length() > 0) { 087 sections += "\n"; 088 rooms += "\n"; 089 periods += "\n"; 090 periodDays += "\n"; 091 periodTimes += "\n"; 092 } 093 sections += owner.getName(); 094 if (first) 095 rooms += roomsThisExam; 096 first = false; 097 } 098 if (exam.getOwners(instructor).isEmpty()) { 099 sections += exam.getName(); 100 rooms += roomsThisExam; 101 } 102 } 103 csv.addLine(new CSVField[] { new CSVField(instructor.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 && !instructor.getExams(period.next()).isEmpty() 109 && (!isDayBreakBackToBack || period.next().getDay() == period.getDay())) { 110 for (Exam ex1 : instructor.getExams(period)) { 111 for (Exam ex2 : instructor.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 owner : ex1.getOwners(instructor)) { 126 if (sections.length() > 0) { 127 sections += "\n"; 128 rooms += "\n"; 129 periods += "\n"; 130 periodDays += "\n"; 131 periodTimes += "\n"; 132 } 133 sections += owner.getName(); 134 if (first) 135 rooms += roomsThisExam; 136 first = false; 137 } 138 if (ex1.getOwners(instructor).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 owner : ex2.getOwners(instructor)) { 151 sections += "\n"; 152 rooms += "\n"; 153 periods += "\n"; 154 periodDays += "\n"; 155 periodTimes += "\n"; 156 sections += owner.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(instructor).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 } 177 String distStr = ""; 178 if (backToBackDistance >= 0) { 179 double dist = (ex1.getAssignment()).getDistanceInMeters(ex2.getAssignment()); 180 if (dist > 0) 181 distStr = String.valueOf(dist); 182 } 183 csv.addLine(new CSVField[] { new CSVField(instructor.getName()), 184 new CSVField("back-to-back"), new CSVField(sections), new CSVField(periods), 185 new CSVField(periodDays), new CSVField(periodTimes), new CSVField(rooms), 186 new CSVField(distStr) }); 187 } 188 } 189 } 190 } 191 if (period.next() == null || period.next().getDay() != period.getDay()) { 192 int nrExamsADay = instructor.getExamsADay(period.getDay()).size(); 193 if (nrExamsADay > 2) { 194 String sections = ""; 195 String periods = ""; 196 String periodDays = ""; 197 String periodTimes = ""; 198 String rooms = ""; 199 for (Exam exam : instructor.getExamsADay(period.getDay())) { 200 ExamPlacement placement = exam.getAssignment(); 201 String roomsThisExam = ""; 202 for (ExamRoomPlacement room : placement.getRoomPlacements()) { 203 if (roomsThisExam.length() > 0) 204 roomsThisExam += ", "; 205 roomsThisExam += room.getName(); 206 } 207 boolean first = true; 208 for (ExamOwner owner : exam.getOwners(instructor)) { 209 if (sections.length() > 0) { 210 sections += "\n"; 211 rooms += "\n"; 212 periods += "\n"; 213 periodDays += "\n"; 214 periodTimes += "\n"; 215 } 216 sections += owner.getName(); 217 if (first) { 218 periods += (placement.getPeriod().getIndex() + 1); 219 periodDays += placement.getPeriod().getDayStr(); 220 periodTimes += placement.getPeriod().getTimeStr(); 221 rooms += roomsThisExam; 222 } 223 first = false; 224 } 225 if (exam.getOwners(instructor).isEmpty()) { 226 if (sections.length() > 0) { 227 sections += "\n"; 228 rooms += "\n"; 229 periods += "\n"; 230 periodDays += "\n"; 231 periodTimes += "\n"; 232 } 233 sections += exam.getName(); 234 periods += (placement.getPeriod().getIndex() + 1); 235 periodDays += placement.getPeriod().getDayStr(); 236 periodTimes += placement.getPeriod().getTimeStr(); 237 rooms += roomsThisExam; 238 } 239 } 240 csv.addLine(new CSVField[] { new CSVField(instructor.getName()), new CSVField("more-2-day"), 241 new CSVField(sections), new CSVField(periods), new CSVField(periodDays), 242 new CSVField(periodTimes), new CSVField(rooms) }); 243 } 244 } 245 } 246 } 247 return csv; 248 } 249}