001package net.sf.cpsolver.coursett.criteria.additional; 002 003import java.util.Collection; 004import java.util.Map; 005 006import net.sf.cpsolver.coursett.criteria.StudentConflict; 007import net.sf.cpsolver.coursett.model.Lecture; 008import net.sf.cpsolver.coursett.model.Placement; 009import net.sf.cpsolver.coursett.model.TimeLocation; 010import net.sf.cpsolver.ifs.solver.Solver; 011import net.sf.cpsolver.ifs.util.DataProperties; 012 013/** 014 * Naive, yet effective approach for modeling student lunch breaks. This criterion 015 * is based on {@link StudentConflict} and it creates a conflict whenever there are 016 * two classes (that share students) overlapping with the lunch time which are one 017 * after the other with a break in between smaller than the requested lunch break. 018 * Lunch time is defined by StudentLunch.StartSlot and StudentLunch.EndStart 019 * properties (default is 11:00 am - 1:30 pm), with lunch break of at least 020 * StudentLunch.Length slots (default is 30 minutes). Such a conflict is weighted 021 * by Comparator.StudentLunchWeight, which defaults to Comparator.StudentConflictWeight. 022 * 023 * <br> 024 * 025 * @version CourseTT 1.2 (University Course Timetabling)<br> 026 * Copyright (C) 2006 - 2011 Tomáš Müller<br> 027 * <a href="mailto:muller@unitime.org">muller@unitime.org</a><br> 028 * <a href="http://muller.unitime.org">http://muller.unitime.org</a><br> 029 * <br> 030 * This library is free software; you can redistribute it and/or modify 031 * it under the terms of the GNU Lesser General Public License as 032 * published by the Free Software Foundation; either version 3 of the 033 * License, or (at your option) any later version. <br> 034 * <br> 035 * This library is distributed in the hope that it will be useful, but 036 * WITHOUT ANY WARRANTY; without even the implied warranty of 037 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 038 * Lesser General Public License for more details. <br> 039 * <br> 040 * You should have received a copy of the GNU Lesser General Public 041 * License along with this library; if not see 042 * <a href='http://www.gnu.org/licenses/'>http://www.gnu.org/licenses/</a>. 043 */ 044 045public class StudentLuchBreak extends StudentConflict { 046 private int iLunchStart, iLunchEnd, iLunchLength; 047 048 @Override 049 public boolean init(Solver<Lecture, Placement> solver) { 050 iLunchStart = solver.getProperties().getPropertyInt("StudentLunch.StartSlot", (11 * 60) / 5); 051 iLunchEnd = solver.getProperties().getPropertyInt("StudentLunch.EndStart", (13 * 60 + 30) / 5); 052 iLunchLength = solver.getProperties().getPropertyInt("StudentLunch.Length", 30 / 5); 053 return super.init(solver); 054 } 055 056 057 @Override 058 public boolean isApplicable(Lecture l1, Lecture l2) { 059 return applicable(l1, l2); 060 } 061 062 @Override 063 public double getWeightDefault(DataProperties config) { 064 return config.getPropertyDouble("Comparator.StudentLunchWeight", config.getPropertyDouble("Comparator.StudentConflictWeight", 1.0)); 065 } 066 067 @Override 068 public String getPlacementSelectionWeightName() { 069 return "Placement.StudentLunchWeight"; 070 } 071 072 public boolean nolunch(Placement p1, Placement p2) { 073 if (p1 == null || p2 == null || overlaps(p1, p2)) return false; 074 if (p1.variable().isCommitted() && p2.variable().isCommitted()) return false; 075 TimeLocation t1 = p1.getTimeLocation(), t2 = p2.getTimeLocation(); 076 if (!t1.shareDays(t2) || !t1.shareWeeks(t2)) return false; 077 int s1 = t1.getStartSlot(), s2 = t2.getStartSlot(); 078 int e1 = t1.getStartSlot() + t1.getNrSlotsPerMeeting(), e2 = t2.getStartSlot() + t2.getNrSlotsPerMeeting(); 079 if (e1 + iLunchLength > s2 && e2 + iLunchLength > s1 && e1 > iLunchStart && iLunchEnd > s1 && e2 > iLunchStart && iLunchEnd > s2) 080 return true; 081 return false; 082 } 083 084 @Override 085 public boolean inConflict(Placement p1, Placement p2) { 086 return nolunch(p1, p2); 087 } 088 089 @Override 090 public void getInfo(Map<String, String> info) { 091 super.getInfo(info); 092 double conf = getValue(); 093 if (conf > 0.0) 094 info.put("Student lunch conflicts", String.valueOf(Math.round(conf))); 095 } 096 097 @Override 098 public void getInfo(Map<String, String> info, Collection<Lecture> variables) { 099 super.getInfo(info, variables); 100 double conf = getValue(variables); 101 if (conf > 0.0) 102 info.put("Student lunch conflicts", String.valueOf(Math.round(conf))); 103 } 104 105}