use of org.cpsolver.studentsct.model.Subpart in project cpsolver by UniTime.
the class StudentSectioningXMLLoader method loadConfig.
/**
* Load config
* @param configEl config element
* @param offering parent offering
* @param subpartTable subpart table (of the offering)
* @param sectionTable section table (of the offering)
* @param timetable provided timetable
* @return loaded config
*/
protected Config loadConfig(Element configEl, Offering offering, Map<Long, Subpart> subpartTable, Map<Long, Section> sectionTable, Map<Long, Placement> timetable) {
Config config = new Config(Long.parseLong(configEl.attributeValue("id")), Integer.parseInt(configEl.attributeValue("limit", "-1")), configEl.attributeValue("name", "G" + configEl.attributeValue("id")), offering);
Element imEl = configEl.element("instructional-method");
if (imEl != null) {
config.setInstructionalMethodId(Long.parseLong(imEl.attributeValue("id")));
config.setInstructionalMethodName(imEl.attributeValue("name", "M" + imEl.attributeValue("id")));
config.setInstructionalMethodReference(imEl.attributeValue("reference", config.getInstructionalMethodName()));
}
for (Iterator<?> k = configEl.elementIterator("subpart"); k.hasNext(); ) {
Element subpartEl = (Element) k.next();
Subpart subpart = loadSubpart(subpartEl, config, subpartTable, sectionTable, timetable);
subpartTable.put(Long.valueOf(subpart.getId()), subpart);
}
return config;
}
use of org.cpsolver.studentsct.model.Subpart in project cpsolver by UniTime.
the class StudentSectioningXMLSaver method saveRestriction.
/**
* Save restriction
* @param restrictionEl restriction element to be populated
* @param restriction restriction to be saved
*/
protected void saveRestriction(Element restrictionEl, Restriction restriction) {
restrictionEl.addAttribute("id", getId("restriction", restriction.getId()));
if (restriction instanceof IndividualRestriction) {
restrictionEl.addAttribute("type", "individual");
for (Long studentId : ((IndividualRestriction) restriction).getStudentIds()) restrictionEl.addElement("student").addAttribute("id", getId("student", studentId));
} else if (restriction instanceof CurriculumRestriction) {
restrictionEl.addAttribute("type", "curriculum");
CurriculumRestriction cr = (CurriculumRestriction) restriction;
if (cr.getAcademicAreas().size() == 1)
restrictionEl.addAttribute("area", cr.getAcademicAreas().iterator().next());
else {
for (String area : cr.getAcademicAreas()) restrictionEl.addElement("area").addAttribute("code", area);
}
for (String clasf : cr.getClassifications()) restrictionEl.addElement("classification").addAttribute("code", clasf);
for (String major : cr.getMajors()) {
Element majorEl = restrictionEl.addElement("major").addAttribute("code", major);
Set<String> concentrations = cr.getConcentrations(major);
if (concentrations != null)
for (String conc : concentrations) majorEl.addElement("concentration").addAttribute("code", conc);
}
for (String minor : cr.getMinors()) restrictionEl.addElement("minor").addAttribute("code", minor);
} else if (restriction instanceof CourseRestriction) {
restrictionEl.addAttribute("type", "course");
CourseRestriction cr = (CourseRestriction) restriction;
restrictionEl.addAttribute("course", getId("course", cr.getCourse().getId()));
}
for (Config config : restriction.getConfigs()) restrictionEl.addElement("config").addAttribute("id", getId("config", config.getId()));
for (Map.Entry<Subpart, Set<Section>> entry : restriction.getSections().entrySet()) {
for (Section section : entry.getValue()) {
restrictionEl.addElement("section").addAttribute("id", getId("section", section.getId()));
}
}
}
use of org.cpsolver.studentsct.model.Subpart in project cpsolver by UniTime.
the class CourseLimitCheck method check.
/**
* Check for courses where the limit is below the number of students that
* request the course
*
* @return false, if there is such a case
*/
public boolean check() {
sLog.info("Checking for course limits...");
boolean ret = true;
for (Offering offering : getModel().getOfferings()) {
boolean hasUnlimitedSection = false;
if (iFixUnlimited)
for (Config config : offering.getConfigs()) {
for (Subpart subpart : config.getSubparts()) {
for (Section section : subpart.getSections()) {
if (section.getLimit() < 0)
hasUnlimitedSection = true;
}
}
}
int offeringLimit = 0;
int nrStudents = 0;
for (Course course : offering.getCourses()) {
if (course.getLimit() < 0) {
offeringLimit = -1;
continue;
}
if (iFixUnlimited && hasUnlimitedSection) {
sLog.info("Course " + course + " made unlimited.");
course.setLimit(-1);
offeringLimit = -1;
continue;
}
double total = 0;
double lastLike = 0, real = 0;
for (Request request : getModel().variables()) {
if (request instanceof CourseRequest && ((CourseRequest) request).getCourses().contains(course)) {
total += request.getWeight();
if (request.getStudent().isDummy())
lastLike += request.getWeight();
else
real += request.getWeight();
}
}
nrStudents += Math.round(total);
offeringLimit += course.getLimit();
if (Math.round(total) > course.getLimit()) {
sLog.error("Course " + course + " is requested by " + sDF.format(total) + " students, but its limit is only " + course.getLimit());
ret = false;
iCSVFile.addLine(new CSVFile.CSVField[] { new CSVFile.CSVField(course.getName()), new CSVFile.CSVField(course.getLimit()), new CSVFile.CSVField(total), new CSVFile.CSVField(real), new CSVFile.CSVField(lastLike) });
if (iUpZeroLimits && course.getLimit() == 0) {
int oldLimit = course.getLimit();
course.setLimit((int) Math.round(total));
sLog.info(" -- limit of course " + course + " increased to " + course.getLimit() + " (was " + oldLimit + ")");
} else if (iUpNonZeroLimits && course.getLimit() > 0) {
int oldLimit = course.getLimit();
course.setLimit((int) Math.round(total));
sLog.info(" -- limit of course " + course + " increased to " + course.getLimit() + " (was " + oldLimit + ")");
}
}
}
if (iUpZeroLimits && offeringLimit == 0 && nrStudents > 0) {
for (Config config : offering.getConfigs()) {
for (Subpart subpart : config.getSubparts()) {
for (Section section : subpart.getSections()) {
int oldLimit = section.getLimit();
section.setLimit(Math.max(section.getLimit(), (int) Math.ceil(nrStudents / subpart.getSections().size())));
sLog.info(" -- limit of section " + section + " increased to " + section.getLimit() + " (was " + oldLimit + ")");
}
}
}
} else if (iUpNonZeroLimits && offeringLimit >= 0 && nrStudents > offeringLimit) {
double fact = ((double) nrStudents) / offeringLimit;
for (Config config : offering.getConfigs()) {
for (Subpart subpart : config.getSubparts()) {
for (Section section : subpart.getSections()) {
int oldLimit = section.getLimit();
section.setLimit((int) Math.ceil(fact * section.getLimit()));
sLog.info(" -- limit of section " + section + " increased to " + section.getLimit() + " (was " + oldLimit + ")");
}
}
}
}
if (offeringLimit >= 0) {
int totalSectionLimit = 0;
for (Config config : offering.getConfigs()) {
int configLimit = -1;
for (Subpart subpart : config.getSubparts()) {
int subpartLimit = 0;
for (Section section : subpart.getSections()) {
subpartLimit += section.getLimit();
}
if (configLimit < 0)
configLimit = subpartLimit;
else
configLimit = Math.min(configLimit, subpartLimit);
}
totalSectionLimit += configLimit;
}
if (totalSectionLimit < offeringLimit) {
sLog.error("Offering limit of " + offering + " is " + offeringLimit + ", but total section limit is only " + totalSectionLimit);
if (iUpZeroLimits && totalSectionLimit == 0) {
for (Config config : offering.getConfigs()) {
for (Subpart subpart : config.getSubparts()) {
for (Section section : subpart.getSections()) {
int oldLimit = section.getLimit();
section.setLimit(Math.max(section.getLimit(), (int) Math.ceil(((double) offeringLimit) / subpart.getSections().size())));
sLog.info(" -- limit of section " + section + " increased to " + section.getLimit() + " (was " + oldLimit + ")");
}
}
}
} else if (iUpNonZeroLimits && totalSectionLimit > 0) {
double fact = ((double) offeringLimit) / totalSectionLimit;
for (Config config : offering.getConfigs()) {
for (Subpart subpart : config.getSubparts()) {
for (Section section : subpart.getSections()) {
int oldLimit = section.getLimit();
section.setLimit((int) Math.ceil(fact * section.getLimit()));
sLog.info(" -- limit of section " + section + " increased to " + section.getLimit() + " (was " + oldLimit + ")");
}
}
}
}
}
}
}
return ret;
}
use of org.cpsolver.studentsct.model.Subpart in project cpsolver by UniTime.
the class StudentPreferencePenalties method setPenalties.
/**
* Set the computed penalties to all sections of all requests of the given
* student
* @param student given student
* @param distributionType penalty distribution type
*/
public static void setPenalties(Student student, int distributionType) {
if (sDebug)
sLog.debug("Setting penalties for " + student);
StudentPreferencePenalties penalties = new StudentPreferencePenalties(distributionType);
for (Request request : student.getRequests()) {
if (!(request instanceof CourseRequest))
continue;
CourseRequest courseRequest = (CourseRequest) request;
if (sDebug)
sLog.debug("-- " + courseRequest);
for (Course course : courseRequest.getCourses()) {
if (sDebug)
sLog.debug(" -- " + course.getName());
for (Config config : course.getOffering().getConfigs()) {
if (sDebug)
sLog.debug(" -- " + config.getName());
for (Subpart subpart : config.getSubparts()) {
if (sDebug)
sLog.debug(" -- " + subpart.getName());
for (Section section : subpart.getSections()) {
section.setPenalty(penalties.getPenalty(section));
if (sDebug)
sLog.debug(" -- " + section);
}
}
}
}
courseRequest.clearCache();
}
}
use of org.cpsolver.studentsct.model.Subpart in project cpsolver by UniTime.
the class Test method clone.
protected Course clone(Course course, long studentId, Student originalStudent, Map<Long, Section> classTable, StudentSectioningModel model) {
Offering clonedOffering = new Offering(course.getOffering().getId(), course.getOffering().getName());
clonedOffering.setModel(model);
int courseLimit = course.getLimit();
if (courseLimit >= 0) {
courseLimit -= course.getEnrollments(assignment()).size();
if (courseLimit < 0)
courseLimit = 0;
for (Iterator<Enrollment> i = course.getEnrollments(assignment()).iterator(); i.hasNext(); ) {
Enrollment enrollment = i.next();
if (enrollment.getStudent().getId() == studentId) {
courseLimit++;
break;
}
}
}
Course clonedCourse = new Course(course.getId(), course.getSubjectArea(), course.getCourseNumber(), clonedOffering, courseLimit, course.getProjected());
clonedCourse.setNote(course.getNote());
Hashtable<Config, Config> configs = new Hashtable<Config, Config>();
Hashtable<Subpart, Subpart> subparts = new Hashtable<Subpart, Subpart>();
Hashtable<Section, Section> sections = new Hashtable<Section, Section>();
for (Iterator<Config> e = course.getOffering().getConfigs().iterator(); e.hasNext(); ) {
Config config = e.next();
int configLimit = config.getLimit();
int configEnrollment = config.getEnrollments(assignment()).size();
if (configLimit >= 0) {
configLimit -= config.getEnrollments(assignment()).size();
if (configLimit < 0)
configLimit = 0;
for (Iterator<Enrollment> i = config.getEnrollments(assignment()).iterator(); i.hasNext(); ) {
Enrollment enrollment = i.next();
if (enrollment.getStudent().getId() == studentId) {
configLimit++;
configEnrollment--;
break;
}
}
}
OnlineConfig clonedConfig = new OnlineConfig(config.getId(), configLimit, config.getName(), clonedOffering);
clonedConfig.setInstructionalMethodId(config.getInstructionalMethodId());
clonedConfig.setInstructionalMethodName(config.getInstructionalMethodName());
clonedConfig.setInstructionalMethodReference(config.getInstructionalMethodReference());
clonedConfig.setEnrollment(configEnrollment);
configs.put(config, clonedConfig);
for (Iterator<Subpart> f = config.getSubparts().iterator(); f.hasNext(); ) {
Subpart subpart = f.next();
Subpart clonedSubpart = new Subpart(subpart.getId(), subpart.getInstructionalType(), subpart.getName(), clonedConfig, (subpart.getParent() == null ? null : subparts.get(subpart.getParent())));
clonedSubpart.setAllowOverlap(subpart.isAllowOverlap());
clonedSubpart.setCredit(subpart.getCredit());
subparts.put(subpart, clonedSubpart);
for (Iterator<Section> g = subpart.getSections().iterator(); g.hasNext(); ) {
Section section = g.next();
int limit = section.getLimit();
int enrl = section.getEnrollments(assignment()).size();
if (limit >= 0) {
// limited section, deduct enrollments
limit -= section.getEnrollments(assignment()).size();
if (limit < 0)
// over-enrolled, but not unlimited
limit = 0;
if (studentId >= 0)
for (Enrollment enrollment : section.getEnrollments(assignment())) if (enrollment.getStudent().getId() == studentId) {
limit++;
enrl--;
break;
}
}
OnlineSection clonedSection = new OnlineSection(section.getId(), limit, section.getName(course.getId()), clonedSubpart, section.getPlacement(), section.getInstructors(), (section.getParent() == null ? null : sections.get(section.getParent())));
clonedSection.setName(-1l, section.getName(-1l));
clonedSection.setNote(section.getNote());
clonedSection.setSpaceExpected(section.getSpaceExpected());
clonedSection.setSpaceHeld(section.getSpaceHeld());
clonedSection.setEnrollment(enrl);
clonedSection.setCancelled(section.isCancelled());
clonedSection.setEnabled(section.isEnabled());
clonedSection.setOnline(section.isOnline());
if (section.getIgnoreConflictWithSectionIds() != null)
for (Long id : section.getIgnoreConflictWithSectionIds()) clonedSection.addIgnoreConflictWith(id);
if (limit > 0) {
double available = Math.round(section.getSpaceExpected() - limit);
clonedSection.setPenalty(available / section.getLimit());
}
sections.put(section, clonedSection);
classTable.put(section.getId(), clonedSection);
}
}
}
if (course.getOffering().hasReservations()) {
for (Reservation reservation : course.getOffering().getReservations()) {
int reservationLimit = (int) Math.round(reservation.getLimit());
if (reservationLimit >= 0) {
reservationLimit -= reservation.getEnrollments(assignment()).size();
if (reservationLimit < 0)
reservationLimit = 0;
for (Iterator<Enrollment> i = reservation.getEnrollments(assignment()).iterator(); i.hasNext(); ) {
Enrollment enrollment = i.next();
if (enrollment.getStudent().getId() == studentId) {
reservationLimit++;
break;
}
}
if (reservationLimit <= 0 && !reservation.mustBeUsed())
continue;
}
boolean applicable = originalStudent != null && reservation.isApplicable(originalStudent);
if (reservation instanceof CourseReservation)
applicable = (course.getId() == ((CourseReservation) reservation).getCourse().getId());
if (reservation instanceof org.cpsolver.studentsct.reservation.DummyReservation) {
// the student is already enrolled in the course
for (Enrollment enrollment : course.getEnrollments(assignment())) if (enrollment.getStudent().getId() == studentId) {
applicable = true;
break;
}
}
Reservation clonedReservation = new OnlineReservation(0, reservation.getId(), clonedOffering, reservation.getPriority(), reservation.canAssignOverLimit(), reservationLimit, applicable, reservation.mustBeUsed(), reservation.isAllowOverlap(), reservation.isExpired());
for (Config config : reservation.getConfigs()) clonedReservation.addConfig(configs.get(config));
for (Map.Entry<Subpart, Set<Section>> entry : reservation.getSections().entrySet()) {
Set<Section> clonedSections = new HashSet<Section>();
for (Section section : entry.getValue()) clonedSections.add(sections.get(section));
clonedReservation.getSections().put(subparts.get(entry.getKey()), clonedSections);
}
}
}
return clonedCourse;
}
Aggregations