001package net.sf.cpsolver.studentsct.model; 002 003import java.util.List; 004 005import net.sf.cpsolver.ifs.model.Variable; 006 007/** 008 * Representation of a request of a student for a course(s) or a free time. This 009 * can be either {@link CourseRequest} or {@link FreeTimeRequest}. Each request 010 * contains id, priority, weight, and a student. A request can be also marked as 011 * alternative. <br> 012 * <br> 013 * For each student, all non-alternative requests should be satisfied (an 014 * enrollment is assigned to a request). If not, an alternative request can be 015 * assigned instead of a non-alternative course request. In the case when only 016 * one of two requests can be assigned, the one with the lowest priority is 017 * preferred. <br> 018 * <br> 019 * 020 * @version StudentSct 1.2 (Student Sectioning)<br> 021 * Copyright (C) 2007 - 2010 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 abstract class Request extends Variable<Request, Enrollment> { 040 private long iId = -1; 041 private int iPriority = 0; 042 private boolean iAlternative = false; 043 private Student iStudent = null; 044 private double iWeight = 1.0; 045 /** True means that method {@link Request#values()} will cache its results. */ 046 public static boolean sCacheValues = false; 047 048 /** 049 * Constructor 050 * 051 * @param id 052 * course/free time request unique id 053 * @param priority 054 * request priority -- if there is a choice, request with lower 055 * priority is more preferred to be assigned 056 * @param alternative 057 * true if the request is alternative (alternative request can be 058 * assigned instead of a non-alternative course requests, if it 059 * is left unassigned) 060 * @param student 061 * student to which this request belongs 062 */ 063 public Request(long id, int priority, boolean alternative, Student student) { 064 iId = id; 065 iPriority = priority; 066 iAlternative = alternative; 067 iStudent = student; 068 iStudent.getRequests().add(this); 069 } 070 071 /** Request id */ 072 @Override 073 public long getId() { 074 return iId; 075 } 076 077 /** 078 * Request priority -- if there is a choice, request with lower priority is 079 * more preferred to be assigned 080 */ 081 public int getPriority() { 082 return iPriority; 083 } 084 085 /** Set request priority */ 086 public void setPriority(int priority) { 087 iPriority = priority; 088 } 089 090 /** 091 * True, if the request is alternative (alternative request can be assigned 092 * instead of a non-alternative course requests, if it is left unassigned) 093 */ 094 public boolean isAlternative() { 095 return iAlternative; 096 } 097 098 /** Student to which this request belongs */ 099 public Student getStudent() { 100 return iStudent; 101 } 102 103 /** 104 * Compare to requests, non-alternative requests go first, otherwise use 105 * priority (a request with lower priority goes first) 106 */ 107 @Override 108 public int compareTo(Request r) { 109 if (getStudent().getId() == r.getStudent().getId()) 110 return (isAlternative() != r.isAlternative() ? isAlternative() ? 1 : -1 : getPriority() < r.getPriority() ? -1 : 1); 111 else 112 return getStudent().compareTo(r.getStudent()); 113 } 114 115 /** Compute available enrollments */ 116 public abstract List<Enrollment> computeEnrollments(); 117 118 /** 119 * Domain of this variable -- list of available enrollments. Method 120 * {@link Request#computeEnrollments()} is used. 121 */ 122 @Override 123 public List<Enrollment> values() { 124 List<Enrollment> values = super.values(); 125 if (values != null) 126 return values; 127 values = computeEnrollments(); 128 if (sCacheValues) 129 setValues(values); 130 return values; 131 } 132 133 /** 134 * Assign given enrollment to this request. This method also calls 135 * {@link Assignment#assigned(Enrollment)} on for all the assignments of the 136 * enrollment. 137 */ 138 @Override 139 public void assign(long iteration, Enrollment enrollment) { 140 super.assign(iteration, enrollment); 141 for (Assignment a : enrollment.getAssignments()) { 142 a.assigned(enrollment); 143 } 144 if (enrollment.getConfig() != null) 145 enrollment.getConfig().assigned(enrollment); 146 if (enrollment.getCourse() != null) 147 enrollment.getCourse().assigned(enrollment); 148 if (enrollment.getReservation() != null) 149 enrollment.getReservation().assigned(enrollment); 150 } 151 152 /** 153 * Unassign currently assigned enrollment from this request. This method 154 * also calls {@link Assignment#unassigned(Enrollment)} on for all the 155 * assignments of the current enrollment. 156 */ 157 @Override 158 public void unassign(long iteration) { 159 if (getAssignment() != null) { 160 Enrollment enrollment = getAssignment(); 161 for (Assignment a : enrollment.getAssignments()) { 162 a.unassigned(enrollment); 163 } 164 if (enrollment.getConfig() != null) 165 enrollment.getConfig().unassigned(enrollment); 166 if (enrollment.getCourse() != null) 167 enrollment.getCourse().unassigned(enrollment); 168 if (enrollment.getReservation() != null) 169 enrollment.getReservation().unassigned(enrollment); 170 } 171 super.unassign(iteration); 172 } 173 174 /** Get bound, i.e., the value of the best possible enrollment */ 175 public abstract double getBound(); 176 177 /** 178 * Request weight, set by default to 1.0, defines the amount of space which 179 * will be taken in the section by this request. 180 */ 181 public double getWeight() { 182 return iWeight; 183 } 184 185 /** 186 * Set request weight. It defines the amount of space which will be taken in 187 * the section by this request. 188 */ 189 public void setWeight(double weight) { 190 iWeight = weight; 191 } 192 193 /** Return true if request is assigned. */ 194 public boolean isAssigned() { 195 return getAssignment() != null; 196 } 197 198 @Override 199 public int hashCode() { 200 return (int) (iId ^ (iId >>> 32) ^ getStudent().getId() ^ (getStudent().getId() >>> 32)); 201 } 202 203 @Override 204 public boolean equals(Object o) { 205 if (o == null || !(o instanceof Request)) return false; 206 return getId() == ((Request)o).getId() && getStudent().getId() == ((Request)o).getStudent().getId(); 207 } 208 209}