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