001package org.cpsolver.studentsct.check; 002 003import java.text.DecimalFormat; 004 005import org.cpsolver.ifs.assignment.Assignment; 006import org.cpsolver.studentsct.StudentSectioningModel; 007import org.cpsolver.studentsct.model.Config; 008import org.cpsolver.studentsct.model.Enrollment; 009import org.cpsolver.studentsct.model.Offering; 010import org.cpsolver.studentsct.model.Request; 011import org.cpsolver.studentsct.model.Section; 012import org.cpsolver.studentsct.model.Subpart; 013 014 015/** 016 * This class looks and reports cases when a section limit is exceeded. 017 * 018 * <br> 019 * <br> 020 * 021 * Usage: if (new SectionLimitCheck(model).check()) ... 022 * 023 * <br> 024 * <br> 025 * 026 * @author Tomáš Müller 027 * @version StudentSct 1.3 (Student Sectioning)<br> 028 * Copyright (C) 2007 - 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 SectionLimitCheck { 047 private static org.apache.logging.log4j.Logger sLog = org.apache.logging.log4j.LogManager.getLogger(SectionLimitCheck.class); 048 private static DecimalFormat sDF = new DecimalFormat("0.000"); 049 private StudentSectioningModel iModel; 050 051 /** 052 * Constructor 053 * 054 * @param model 055 * student sectioning model 056 */ 057 public SectionLimitCheck(StudentSectioningModel model) { 058 iModel = model; 059 } 060 061 /** Return student sectioning model 062 * @return problem model 063 **/ 064 public StudentSectioningModel getModel() { 065 return iModel; 066 } 067 068 /** 069 * Check for sections that have more students enrolled than it is allowed, 070 * i.e., the sum of requests weights is above the section limit 071 * @param assignment current assignment 072 * @return false, if there is such a case 073 */ 074 public boolean check(Assignment<Request, Enrollment> assignment) { 075 sLog.info("Checking section limits..."); 076 boolean ret = true; 077 for (Offering offering : getModel().getOfferings()) { 078 if (offering.isDummy()) continue; 079 for (Config config : offering.getConfigs()) { 080 for (Subpart subpart : config.getSubparts()) { 081 for (Section section : subpart.getSections()) { 082 if (section.getLimit() < 0) 083 continue; 084 double used = section.getEnrollmentWeight(assignment, null); 085 if (used - section.getMaxEnrollmentWeight(assignment) > section.getLimit()) { 086 sLog.error("Section " + section.getName() + " exceeds its limit " + sDF.format(used) + ">" 087 + section.getLimit() + " for more than one student (W:" 088 + section.getMaxEnrollmentWeight(assignment) + ")"); 089 ret = false; 090 } else if (Math.round(used) > section.getLimit()) { 091 sLog.debug("Section " + section.getName() + " exceeds its limit " + sDF.format(used) + ">" 092 + section.getLimit() + " for less than one student (W:" 093 + section.getMaxEnrollmentWeight(assignment) + ")"); 094 } 095 } 096 } 097 } 098 } 099 return ret; 100 } 101 102}