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