001package org.cpsolver.studentsct.report; 002 003import java.util.HashSet; 004import java.util.Map; 005import java.util.Set; 006 007import org.cpsolver.ifs.assignment.Assignment; 008import org.cpsolver.ifs.util.CSVFile; 009import org.cpsolver.ifs.util.DataProperties; 010import org.cpsolver.studentsct.StudentSectioningModel; 011import org.cpsolver.studentsct.model.Choice; 012import org.cpsolver.studentsct.model.Config; 013import org.cpsolver.studentsct.model.Course; 014import org.cpsolver.studentsct.model.CourseRequest; 015import org.cpsolver.studentsct.model.Enrollment; 016import org.cpsolver.studentsct.model.Request; 017import org.cpsolver.studentsct.model.Section; 018import org.cpsolver.studentsct.model.Student; 019import org.cpsolver.studentsct.model.Subpart; 020import org.cpsolver.studentsct.reservation.Reservation; 021 022/** 023 * This reports lists information needed for additional reporting.<br> 024 * <br> 025 * 026 * @version StudentSct 1.3 (Student Sectioning)<br> 027 * Copyright (C) 2015 Tomas Muller<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 TableauReport implements StudentSectioningReport { 046 private StudentSectioningModel iModel = null; 047 048 /** 049 * Constructor 050 * 051 * @param model 052 * student sectioning model 053 */ 054 public TableauReport(StudentSectioningModel model) { 055 iModel = model; 056 } 057 058 /** Return student sectioning model 059 * @return problem model 060 **/ 061 public StudentSectioningModel getModel() { 062 return iModel; 063 } 064 065 @Override 066 public CSVFile create(Assignment<Request, Enrollment> assignment, DataProperties properties) { 067 CSVFile csv = new CSVFile(); 068 boolean simple = properties.getPropertyBoolean("simple", false); 069 if (simple) { 070 csv.setHeader(new CSVFile.CSVField[] { 071 new CSVFile.CSVField("__Student"), 072 new CSVFile.CSVField("Student"), 073 new CSVFile.CSVField("Course"), 074 new CSVFile.CSVField("Course Limit"), 075 new CSVFile.CSVField("Primary"), 076 new CSVFile.CSVField("Priority"), 077 new CSVFile.CSVField("Alternativity"), 078 new CSVFile.CSVField("Enrolled")}); 079 } else { 080 csv.setHeader(new CSVFile.CSVField[] { 081 new CSVFile.CSVField("__Student"), 082 new CSVFile.CSVField("Student"), 083 new CSVFile.CSVField("Course"), 084 new CSVFile.CSVField("Course Limit"), 085 new CSVFile.CSVField("Controlling Course"), 086 new CSVFile.CSVField("Primary"), 087 new CSVFile.CSVField("Priority"), 088 new CSVFile.CSVField("Alternativity"), 089 new CSVFile.CSVField("Enrolled"), 090 new CSVFile.CSVField("Credits"), 091 new CSVFile.CSVField("Sections"), 092 new CSVFile.CSVField("Preferred Sections"), 093 new CSVFile.CSVField("Required Sections"), 094 new CSVFile.CSVField("Instructional Method"), 095 new CSVFile.CSVField("Preferred Instructional Methods"), 096 new CSVFile.CSVField("Required Instructional Methods"), 097 new CSVFile.CSVField("Critical") 098 }); 099 } 100 for (Student student: getModel().getStudents()) { 101 if (student.isDummy()) continue; 102 int regPriority = 1, altPriority = 1; 103 for (Request r: student.getRequests()) { 104 if (r instanceof CourseRequest) { 105 CourseRequest cr = (CourseRequest)r; 106 Enrollment e = cr.getAssignment(assignment); 107 int primary = (cr.isAlternative() ? 0 : 1); 108 int priority = 0; 109 if (cr.isAlternative()) 110 priority = altPriority++; 111 else 112 priority = regPriority++; 113 int alternativity = 0; 114 for (Course course: cr.getCourses()) { 115 int enrolled = (e != null && e.getCourse().equals(course) ? 1 : 0); 116 String sect = null; 117 if (e != null) { 118 sect = ""; 119 Set<String> added = new HashSet<String>(); 120 for (Section s: e.getSections()) { 121 String x = s.getName(e.getCourse().getId()); 122 if (x.indexOf('-') > 0) x = x.substring(0, x.indexOf('-')); 123 if (added.add(x)) sect += (sect.isEmpty() ? "" : ",") + x; 124 } 125 } 126 String imR = "", sctR = ""; 127 Set<String> addedR = new HashSet<String>(); 128 for (Choice ch: cr.getRequiredChoices()) { 129 if (course.getOffering().equals(ch.getOffering())) { 130 if (ch.getConfigId() != null) { 131 for (Config cfg: ch.getOffering().getConfigs()) { 132 if (ch.getConfigId().equals(cfg.getId())) { 133 String im = cfg.getInstructionalMethodReference(); 134 if (im != null && addedR.add(im)) 135 imR += (imR.isEmpty() ? "" : ",") + im; 136 } 137 } 138 } 139 if (ch.getSectionId() != null) { 140 String x = ch.getOffering().getSection(ch.getSectionId()).getName(course.getId()); 141 if (x.indexOf('-') > 0) x = x.substring(0, x.indexOf('-')); 142 if (addedR.add(x)) 143 sctR += (sctR.isEmpty() ? "" : ",") + x; 144 } 145 } 146 } 147 for (Reservation rs: cr.getReservations(course)) { 148 if (rs.mustBeUsed()) { 149 for (Map.Entry<Subpart, Set<Section>> ent: rs.getSections().entrySet()) { 150 for (Section s: ent.getValue()) { 151 String x = s.getName(course.getId()); 152 if (x.indexOf('-') > 0) x = x.substring(0, x.indexOf('-')); 153 if (addedR.add(x)) 154 sctR += (sctR.isEmpty() ? "" : ",") + x; 155 } 156 } 157 if (rs.getSections().isEmpty()) { 158 for (Config cfg: rs.getConfigs()) { 159 String im = cfg.getInstructionalMethodReference(); 160 if (im != null && addedR.add(im)) 161 imR += (imR.isEmpty() ? "" : ",") + im; 162 } 163 } 164 } 165 } 166 String imP = "", sctP = ""; 167 for (Choice ch: cr.getSelectedChoices()) { 168 Set<String> added = new HashSet<String>(); 169 if (course.getOffering().equals(ch.getOffering())) { 170 if (ch.getConfigId() != null) { 171 for (Config cfg: ch.getOffering().getConfigs()) { 172 if (ch.getConfigId().equals(cfg.getId())) { 173 String im = cfg.getInstructionalMethodReference(); 174 if (im != null && added.add(im)) 175 imP += (imP.isEmpty() ? "" : ",") + im; 176 } 177 } 178 } 179 if (ch.getSectionId() != null) { 180 String x = ch.getOffering().getSection(ch.getSectionId()).getName(course.getId()); 181 if (x.indexOf('-') > 0) x = x.substring(0, x.indexOf('-')); 182 if (added.add(x)) 183 sctP += (sctP.isEmpty() ? "" : ",") + x; 184 } 185 } 186 } 187 if (simple) 188 csv.addLine(new CSVFile.CSVField[] { 189 new CSVFile.CSVField(student.getId()), 190 new CSVFile.CSVField(student.getExternalId()), 191 new CSVFile.CSVField(course.getName()), 192 new CSVFile.CSVField(course.getLimit() < 0 ? null : course.getLimit()), 193 new CSVFile.CSVField(primary == 1 ? "Yes" : "No"), 194 new CSVFile.CSVField(priority), 195 new CSVFile.CSVField(alternativity), 196 new CSVFile.CSVField(enrolled == 1 ? "Yes" : "No") 197 }); 198 else 199 csv.addLine(new CSVFile.CSVField[] { 200 new CSVFile.CSVField(student.getId()), 201 new CSVFile.CSVField(student.getExternalId()), 202 new CSVFile.CSVField(course.getName()), 203 new CSVFile.CSVField(course.getLimit() < 0 ? null : course.getLimit()), 204 new CSVFile.CSVField(course.getOffering().getCourses().size() <= 1 ? null : course.getOffering().getName()), 205 new CSVFile.CSVField(primary == 1 ? "Yes" : "No"), 206 new CSVFile.CSVField(priority), 207 new CSVFile.CSVField(alternativity), 208 new CSVFile.CSVField(enrolled == 1 ? "Yes" : "No"), 209 new CSVFile.CSVField(enrolled == 1 ? e.getCredit() : course.getCreditValue() == null ? 0f : course.getCreditValue()), 210 new CSVFile.CSVField(sect), 211 new CSVFile.CSVField(sctP), 212 new CSVFile.CSVField(sctR), 213 new CSVFile.CSVField(e != null ? e.getConfig().getInstructionalMethodReference() : null), 214 new CSVFile.CSVField(imP), 215 new CSVFile.CSVField(imR), 216 new CSVFile.CSVField(cr.isCritical() ? "Yes" : "No") 217 }); 218 alternativity++; 219 } 220 } 221 } 222 } 223 return csv; 224 } 225}