001package org.cpsolver.studentsct.model; 002 003import java.util.ArrayList; 004import java.util.HashSet; 005import java.util.List; 006import java.util.Set; 007 008import org.cpsolver.coursett.model.RoomLocation; 009import org.cpsolver.coursett.model.TimeLocation; 010import org.cpsolver.ifs.assignment.Assignment; 011import org.cpsolver.studentsct.StudentSectioningModel; 012 013 014 015/** 016 * Representation of a request of a student for free time. This class directly 017 * implements {@link SctAssignment} API, with the appropriate free time. <br> 018 * <br> 019 * 020 * @version StudentSct 1.3 (Student Sectioning)<br> 021 * Copyright (C) 2007 - 2014 Tomáš Müller<br> 022 * <a href="mailto:muller@unitime.org">muller@unitime.org</a><br> 023 * <a href="http://muller.unitime.org">http://muller.unitime.org</a><br> 024 * <br> 025 * This library is free software; you can redistribute it and/or modify 026 * it under the terms of the GNU Lesser General Public License as 027 * published by the Free Software Foundation; either version 3 of the 028 * License, or (at your option) any later version. <br> 029 * <br> 030 * This library is distributed in the hope that it will be useful, but 031 * WITHOUT ANY WARRANTY; without even the implied warranty of 032 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 033 * Lesser General Public License for more details. <br> 034 * <br> 035 * You should have received a copy of the GNU Lesser General Public 036 * License along with this library; if not see 037 * <a href='http://www.gnu.org/licenses/'>http://www.gnu.org/licenses/</a>. 038 */ 039public class FreeTimeRequest extends Request implements SctAssignment { 040 private TimeLocation iTime = null; 041 042 /** 043 * Constructor 044 * 045 * @param id 046 * request unique id 047 * @param priority 048 * request priority 049 * @param alternative 050 * true if the request is alternative (alternative request can be 051 * assigned instead of a non-alternative course requests, if it 052 * is left unassigned) 053 * @param student 054 * appropriate student 055 * @param time 056 * appropriate time location that is requested to be free 057 */ 058 public FreeTimeRequest(long id, int priority, boolean alternative, Student student, TimeLocation time) { 059 super(id, priority, alternative, student); 060 iTime = time; 061 } 062 063 /** Return requested time to be free */ 064 @Override 065 public TimeLocation getTime() { 066 return iTime; 067 } 068 069 /** Assignment API: free time request has no rooms */ 070 @Override 071 public int getNrRooms() { 072 return 0; 073 } 074 075 /** Assignment API: free time request has no rooms */ 076 @Override 077 public List<RoomLocation> getRooms() { 078 return new ArrayList<RoomLocation>(0); 079 } 080 081 /** 082 * True, if this assignment is overlapping in time and space with the given 083 * assignment. 084 */ 085 @Override 086 public boolean isOverlapping(SctAssignment assignment) { 087 if (isAllowOverlap() || assignment.isAllowOverlap()) return false; 088 if (getTime() == null || assignment.getTime() == null) 089 return false; 090 if (assignment instanceof FreeTimeRequest) 091 return false; 092 return getTime().hasIntersection(assignment.getTime()); 093 } 094 095 /** 096 * True, if this assignment is overlapping in time and space with the given 097 * set of assignments. 098 */ 099 @Override 100 public boolean isOverlapping(Set<? extends SctAssignment> assignments) { 101 if (isAllowOverlap()) 102 return false; 103 if (getTime() == null) 104 return false; 105 for (SctAssignment assignment : assignments) { 106 if (assignment.isAllowOverlap()) 107 continue; 108 if (assignment.getTime() == null) 109 continue; 110 if (assignment instanceof FreeTimeRequest) 111 return false; 112 if (getTime().hasIntersection(assignment.getTime())) 113 return true; 114 } 115 return false; 116 } 117 118 /** Create enrollment of this request 119 * @return created enrollment 120 **/ 121 public Enrollment createEnrollment() { 122 HashSet<SctAssignment> assignments = new HashSet<SctAssignment>(); 123 assignments.add(this); 124 return new Enrollment(this, 0, null, assignments, null); 125 } 126 127 /** 128 * Create all possible enrollments of this request -- there is only one 129 * possible enrollment: {@link FreeTimeRequest#createEnrollment()} 130 */ 131 @Override 132 public List<Enrollment> computeEnrollments(Assignment<Request, Enrollment> assignment) { 133 List<Enrollment> enrollments = new ArrayList<Enrollment>(1); 134 enrollments.add(createEnrollment()); 135 return enrollments; 136 } 137 138 /** Enrollment with this assignment was assigned to a {@link Request}. */ 139 @Override 140 public void assigned(Assignment<Request, Enrollment> assignment, Enrollment enrollment) { 141 ((FreeTimeRequestContext)getContext(assignment)).assigned(assignment, enrollment); 142 } 143 144 /** Enrollment with this assignment was unassigned from a {@link Request}. */ 145 @Override 146 public void unassigned(Assignment<Request, Enrollment> assignment, Enrollment enrollment) { 147 ((FreeTimeRequestContext)getContext(assignment)).unassigned(assignment, enrollment); 148 } 149 150 /** Return the list of assigned enrollments that contains this assignment. */ 151 @Override 152 public Set<Enrollment> getEnrollments(Assignment<Request, Enrollment> assignment) { 153 return ((FreeTimeRequestContext)getContext(assignment)).getEnrollments(); 154 } 155 156 /** 157 * Request name: A for alternative, 1 + priority, Free Time, long name of 158 * requested time 159 */ 160 @Override 161 public String getName() { 162 return (isAlternative() ? "A" : "") + (1 + getPriority() + (isAlternative() ? -getStudent().nrRequests() : 0)) 163 + ". Free Time " + getTime().getDayHeader() + " " + getTime().getStartTimeHeader(true) + " - " + getTime().getEndTimeHeader(true); 164 } 165 166 @Override 167 public String toString() { 168 return getName(); 169 } 170 171 /** Estimated bound for this request */ 172 @Override 173 public double getBound() { 174 return - getWeight() * ((StudentSectioningModel)getModel()).getStudentWeights().getBound(this); 175 } 176 177 /** Free time request generally allow overlaps. */ 178 @Override 179 public boolean isAllowOverlap() { 180 return (getModel() == null ? true : ((StudentSectioningModel)getModel()).getStudentWeights().isFreeTimeAllowOverlaps()); 181 } 182 183 /** Sections first, then by {@link FreeTimeRequest#getId()} */ 184 @Override 185 public int compareById(SctAssignment a) { 186 if (a instanceof FreeTimeRequest) { 187 return Long.valueOf(getId()).compareTo(((FreeTimeRequest)a).getId()); 188 } else { 189 return 1; 190 } 191 } 192 193 @Override 194 public int hashCode() { 195 return super.hashCode() ^ getTime().hashCode(); 196 } 197 198 199 @Override 200 public boolean equals(Object o) { 201 return super.equals(o) && (o instanceof FreeTimeRequest) && getTime().equals(((FreeTimeRequest)o).getTime()); 202 } 203 204 public class FreeTimeRequestContext extends RequestContext { 205 private HashSet<Enrollment> iEnrollments = new HashSet<Enrollment>(); 206 207 public FreeTimeRequestContext(Assignment<Request, Enrollment> assignment) { 208 super(assignment); 209 Enrollment enrollment = assignment.getValue(FreeTimeRequest.this); 210 if (enrollment != null) 211 assigned(assignment, enrollment); 212 } 213 214 /** Enrollment with this assignment was assigned to a {@link Request}. 215 * @param assignment current assignment 216 * @param enrollment assigned enrollment 217 **/ 218 public void assigned(Assignment<Request, Enrollment> assignment, Enrollment enrollment) { 219 iEnrollments.add(enrollment); 220 } 221 222 /** Enrollment with this assignment was unassigned from a {@link Request}. 223 * @param assignment current assignment 224 * @param enrollment unassigned enrollment 225 */ 226 public void unassigned(Assignment<Request, Enrollment> assignment, Enrollment enrollment) { 227 iEnrollments.remove(enrollment); 228 } 229 230 /** Return the list of assigned enrollments that contains this assignment. 231 * @return current enrollments 232 **/ 233 public Set<Enrollment> getEnrollments() { 234 return iEnrollments; 235 } 236 237 } 238 239 @Override 240 public RequestContext createAssignmentContext(Assignment<Request, Enrollment> assignment) { 241 return new FreeTimeRequestContext(assignment); 242 } 243 244 @Override 245 public float getMinCredit() { 246 return 0; 247 } 248 249 @Override 250 public RequestPriority getRequestPriority() { 251 return RequestPriority.Normal; 252 } 253}