001package org.cpsolver.studentsct.report; 002 003import java.text.DecimalFormat; 004import java.util.Comparator; 005import java.util.TreeSet; 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.Config; 012import org.cpsolver.studentsct.model.Course; 013import org.cpsolver.studentsct.model.CourseRequest; 014import org.cpsolver.studentsct.model.Enrollment; 015import org.cpsolver.studentsct.model.Offering; 016import org.cpsolver.studentsct.model.Request; 017import org.cpsolver.studentsct.model.RequestGroup; 018import org.cpsolver.studentsct.model.Section; 019import org.cpsolver.studentsct.model.Subpart; 020 021/** 022 * This reports lists all request groups (including course name and group name) and the current spreads. 023 * For each group, the current average spread (see {@link RequestGroup#getAverageSpread(Assignment)}) 024 * is listed together with all the classes that the students of the group are enrolled into and their 025 * spreads (see {@link RequestGroup#getSectionSpread(Assignment, Section)}).<br> 026 * <br> 027 * The average spread corresponds with the probability of two students of the group to attend the same section. 028 * The section spread is a break down of the average spread by each section.<br> 029 * <br> 030 * 031 * 032 * @version StudentSct 1.3 (Student Sectioning)<br> 033 * Copyright (C) 2015 Tomáš Müller<br> 034 * <a href="mailto:muller@unitime.org">muller@unitime.org</a><br> 035 * <a href="http://muller.unitime.org">http://muller.unitime.org</a><br> 036 * <br> 037 * This library is free software; you can redistribute it and/or modify 038 * it under the terms of the GNU Lesser General Public License as 039 * published by the Free Software Foundation; either version 3 of the 040 * License, or (at your option) any later version. <br> 041 * <br> 042 * This library is distributed in the hope that it will be useful, but 043 * WITHOUT ANY WARRANTY; without even the implied warranty of 044 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 045 * Lesser General Public License for more details. <br> 046 * <br> 047 * You should have received a copy of the GNU Lesser General Public 048 * License along with this library; if not see 049 * <a href='http://www.gnu.org/licenses/'>http://www.gnu.org/licenses/</a>. 050 */ 051public class RequestGroupTable extends AbstractStudentSectioningReport { 052 private static DecimalFormat sDF = new DecimalFormat("0.000"); 053 054 /** 055 * Constructor 056 * 057 * @param model student sectioning model 058 */ 059 public RequestGroupTable(StudentSectioningModel model) { 060 super(model); 061 } 062 063 @Override 064 public CSVFile createTable(Assignment<Request, Enrollment> assignment, DataProperties properties) { 065 CSVFile csv = new CSVFile(); 066 csv.setHeader(new CSVFile.CSVField[] { 067 new CSVFile.CSVField("Group"), 068 new CSVFile.CSVField("Course"), 069 new CSVFile.CSVField("Total\nSpread"), 070 new CSVFile.CSVField("Group\nEnrollment"), 071 new CSVFile.CSVField("Class"), 072 new CSVFile.CSVField("Meeting Time"), 073 new CSVFile.CSVField("Class\nSpread"), 074 new CSVFile.CSVField("Class\nEnrollment"), 075 new CSVFile.CSVField("Class\nLimit") 076 }); 077 078 TreeSet<RequestGroup> groups = new TreeSet<RequestGroup>(new Comparator<RequestGroup>() { 079 @Override 080 public int compare(RequestGroup g1, RequestGroup g2) { 081 int cmp = g1.getName().compareTo(g2.getName()); 082 if (cmp != 0) return cmp; 083 cmp = g1.getCourse().getName().compareTo(g2.getCourse().getName()); 084 if (cmp != 0) return cmp; 085 if (g1.getId() < g2.getId()) return -1; 086 if (g1.getId() > g2.getId()) return 1; 087 return (g1.getCourse().getId() < g2.getCourse().getId() ? -1 : g1.getCourse().getId() > g2.getCourse().getId() ? 1 : 0); 088 } 089 }); 090 091 for (Offering offering: getModel().getOfferings()) 092 for (Course course: offering.getCourses()) 093 groups.addAll(course.getRequestGroups()); 094 095 for (RequestGroup group: groups) { 096 int nbrMatches = 0; 097 for (CourseRequest cr: group.getRequests()) { 098 if (matches(cr)) nbrMatches ++; 099 } 100 if (nbrMatches == 0) continue; 101 double groupEnrollment = group.getEnrollmentWeight(assignment, null); 102 double groupSpread = group.getAverageSpread(assignment); 103 for (Config config: group.getCourse().getOffering().getConfigs()) 104 for (Subpart subpart: config.getSubparts()) 105 for (Section section: subpart.getSections()) { 106 double s = group.getSectionWeight(assignment, section, null); 107 if (s > 0.00001) { 108 csv.addLine(new CSVFile.CSVField[] { 109 new CSVFile.CSVField(group.getName()), 110 new CSVFile.CSVField(group.getCourse().getName()), 111 new CSVFile.CSVField(sDF.format(100.0 * groupSpread)), 112 new CSVFile.CSVField(Math.round(groupEnrollment)), 113 new CSVFile.CSVField(section.getSubpart().getName() + " " + section.getName(group.getCourse().getId())), 114 new CSVFile.CSVField(section.getTime() == null ? "" : section.getTime().getDayHeader() + " " + section.getTime().getStartTimeHeader(isUseAmPm()) + " - " + section.getTime().getEndTimeHeader(isUseAmPm())), 115 new CSVFile.CSVField(sDF.format(100.0 * group.getSectionSpread(assignment, section))), 116 new CSVFile.CSVField(Math.round(group.getSectionWeight(assignment, section, null))), 117 new CSVFile.CSVField(section.getLimit()) 118 }); 119 } 120 } 121 } 122 123 return csv; 124 } 125 126}