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 * @version StudentSct 1.3 (Student Sectioning)<br> 027 * Copyright (C) 2007 - 2014 Tomáš Müller<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 SectionLimitCheck { 046 private static org.apache.logging.log4j.Logger sLog = org.apache.logging.log4j.LogManager.getLogger(SectionLimitCheck.class); 047 private static DecimalFormat sDF = new DecimalFormat("0.000"); 048 private StudentSectioningModel iModel; 049 050 /** 051 * Constructor 052 * 053 * @param model 054 * student sectioning model 055 */ 056 public SectionLimitCheck(StudentSectioningModel model) { 057 iModel = model; 058 } 059 060 /** Return student sectioning model 061 * @return problem model 062 **/ 063 public StudentSectioningModel getModel() { 064 return iModel; 065 } 066 067 /** 068 * Check for sections that have more students enrolled than it is allowed, 069 * i.e., the sum of requests weights is above the section limit 070 * @param assignment current assignment 071 * @return false, if there is such a case 072 */ 073 public boolean check(Assignment<Request, Enrollment> assignment) { 074 sLog.info("Checking section limits..."); 075 boolean ret = true; 076 for (Offering offering : getModel().getOfferings()) { 077 for (Config config : offering.getConfigs()) { 078 for (Subpart subpart : config.getSubparts()) { 079 for (Section section : subpart.getSections()) { 080 if (section.getLimit() < 0) 081 continue; 082 double used = section.getEnrollmentWeight(assignment, null); 083 if (used - section.getMaxEnrollmentWeight(assignment) > section.getLimit()) { 084 sLog.error("Section " + section.getName() + " exceeds its limit " + sDF.format(used) + ">" 085 + section.getLimit() + " for more than one student (W:" 086 + section.getMaxEnrollmentWeight(assignment) + ")"); 087 ret = false; 088 } else if (Math.round(used) > section.getLimit()) { 089 sLog.debug("Section " + section.getName() + " exceeds its limit " + sDF.format(used) + ">" 090 + section.getLimit() + " for less than one student (W:" 091 + section.getMaxEnrollmentWeight(assignment) + ")"); 092 } 093 } 094 } 095 } 096 } 097 return ret; 098 } 099 100}