001package org.cpsolver.studentsct.model; 002 003import java.util.HashSet; 004import java.util.List; 005import java.util.Set; 006 007import org.cpsolver.coursett.model.RoomLocation; 008import org.cpsolver.coursett.model.TimeLocation; 009import org.cpsolver.ifs.assignment.Assignment; 010 011/** 012 * Representation of an unavailability. This is typically used when the student is 013 * also an instructor and he/she is teaching during some time (and hence not available 014 * for attending classes as a student). An unavailability can be marked as can overlap 015 * in time, in which case the time overlap is allowed but the overlapping time is to 016 * be minimized.<br> 017 * <br> 018 * 019 * @author Tomáš Müller 020 * @version StudentSct 1.3 (Student Sectioning)<br> 021 * Copyright (C) 2007 - 2016 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 Unavailability implements SctAssignment { 040 private Section iSection; 041 private Student iStudent; 042 private boolean iAllowOverlap; 043 private boolean iTeachingAssignment = true; 044 private Long iCourseId; 045 046 /** 047 * Constructor 048 * @param student student 049 * @param section section that the student is teaching 050 * @param canOverlap true if student can have classes during the time, but the overlapping time should be minimized 051 */ 052 public Unavailability(Student student, Section section, boolean canOverlap) { 053 iStudent = student; 054 iSection = section; 055 iAllowOverlap = canOverlap; 056 iStudent.getUnavailabilities().add(this); 057 iSection.getUnavailabilities().add(this); 058 } 059 060 /** 061 * Student 062 */ 063 public Student getStudent() { return iStudent; } 064 065 /** 066 * Section 067 */ 068 public Section getSection() { return iSection; } 069 070 /** 071 * Optional course id (within the course of {@link Unavailability#getSection()} 072 */ 073 public Long getCourseId() { return iCourseId; } 074 075 /** 076 * Optional course id (within the course of {@link Unavailability#getSection()} 077 */ 078 public void setCourseId(Long courseId) { iCourseId = courseId; } 079 080 /** 081 * Is this a teaching assignment 082 */ 083 public boolean isTeachingAssignment() { return iTeachingAssignment; } 084 085 /** 086 * Is this a teaching assignment, defaults to true 087 */ 088 public void setTeachingAssignment(boolean ta) { iTeachingAssignment = ta; } 089 090 /** 091 * Course name taken from the {@link Unavailability#getSection()} and optional {@link Unavailability#getCourseId()}. 092 * Name of the controlling course is used when no course id is set. 093 */ 094 public String getCourseName() { 095 if (getSection().getSubpart() == null) return ""; 096 Offering offering = getSection().getSubpart().getConfig().getOffering(); 097 if (getCourseId() != null) 098 for (Course course: offering.getCourses()) 099 if (course.getId() == getCourseId()) 100 return course.getName(); 101 return offering.getName(); 102 } 103 104 /** 105 * Section name using {@link Section#getName(long)} when the optional course id is provided, 106 * using {@link Section#getName()} otherwise. 107 */ 108 public String getSectionName() { 109 if (getSection().getSubpart() == null) return getSection().getName(); 110 if (getCourseId() != null) 111 return getSection().getSubpart().getName() + " " + getSection().getName(getCourseId()); 112 return getSection().getSubpart().getName() + " " +getSection().getName(); 113 } 114 115 @Override 116 public long getId() { 117 return getSection().getId(); 118 } 119 120 @Override 121 public TimeLocation getTime() { return getSection().getTime(); } 122 123 /** 124 * Can student have classes during this unavailability? The overlapping time should be minimized in this case 125 * (like with lower priority free time requests). 126 */ 127 @Override 128 public boolean isAllowOverlap() { return iAllowOverlap; } 129 130 @Override 131 public List<RoomLocation> getRooms() { 132 return getSection().getRooms(); 133 } 134 135 @Override 136 public int getNrRooms() { 137 return getSection().getNrRooms(); 138 } 139 140 @Override 141 public boolean isOverlapping(SctAssignment assignment) { 142 if (isAllowOverlap() || assignment.isAllowOverlap()) return false; 143 if (getTime() == null || assignment.getTime() == null) return false; 144 if (assignment instanceof Section && getTime().hasIntersection(assignment.getTime())) return true; 145 return false; 146 } 147 148 @Override 149 public boolean isOverlapping(Set<? extends SctAssignment> assignments) { 150 if (isAllowOverlap()) return false; 151 if (getTime() == null) return false; 152 for (SctAssignment assignment : assignments) { 153 if (assignment.isAllowOverlap()) continue; 154 if (assignment.getTime() == null) continue; 155 if (assignment instanceof Section && getTime().hasIntersection(assignment.getTime())) return true; 156 } 157 return false; 158 } 159 160 @Override 161 public void assigned(Assignment<Request, Enrollment> assignment, Enrollment enrollment) { 162 } 163 164 @Override 165 public void unassigned(Assignment<Request, Enrollment> assignment, Enrollment enrollment) { 166 } 167 168 /** 169 * Not used, always null 170 */ 171 @Override 172 public Set<Enrollment> getEnrollments(Assignment<Request, Enrollment> assignment) { 173 return null; 174 } 175 176 @Override 177 public int compareById(SctAssignment a) { 178 if (a instanceof Unavailability) { 179 return Long.valueOf(getId()).compareTo(((Unavailability)a).getId()); 180 } else { 181 return 1; 182 } 183 } 184 185 /** 186 * Create dummy enrollment of this unavailability 187 * @return created enrollment (warning: the returned enrollment has no request) 188 **/ 189 public Enrollment createEnrollment() { 190 HashSet<SctAssignment> assignments = new HashSet<SctAssignment>(); 191 assignments.add(this); 192 return new Enrollment(null, 0, null, assignments, null); 193 } 194 195 @Override 196 public boolean equals(Object o) { 197 if (o == null || !(o instanceof Unavailability)) return false; 198 return getId() == ((Unavailability)o).getId(); 199 } 200 201 @Override 202 public int hashCode() { 203 return (int) (getId() ^ (getId() >>> 32)); 204 } 205 206 @Override 207 public String toString() { 208 if (getSection().getSubpart() == null) return getSection().getName(); 209 return getCourseName() + " " + getSectionName(); 210 } 211}