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