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 * @version StudentSct 1.3 (Student Sectioning)<br> 020 * Copyright (C) 2007 - 2016 Tomáš Müller<br> 021 * <a href="mailto:muller@unitime.org">muller@unitime.org</a><br> 022 * <a href="http://muller.unitime.org">http://muller.unitime.org</a><br> 023 * <br> 024 * This library is free software; you can redistribute it and/or modify 025 * it under the terms of the GNU Lesser General Public License as 026 * published by the Free Software Foundation; either version 3 of the 027 * License, or (at your option) any later version. <br> 028 * <br> 029 * This library is distributed in the hope that it will be useful, but 030 * WITHOUT ANY WARRANTY; without even the implied warranty of 031 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 032 * Lesser General Public License for more details. <br> 033 * <br> 034 * You should have received a copy of the GNU Lesser General Public 035 * License along with this library; if not see 036 * <a href='http://www.gnu.org/licenses/'>http://www.gnu.org/licenses/</a>. 037 */ 038public class Unavailability implements SctAssignment { 039 private Section iSection; 040 private Student iStudent; 041 private boolean iAllowOverlap; 042 private boolean iTeachingAssignment = true; 043 private Long iCourseId; 044 045 /** 046 * Constructor 047 * @param student student 048 * @param section section that the student is teaching 049 * @param canOverlap true if student can have classes during the time, but the overlapping time should be minimized 050 */ 051 public Unavailability(Student student, Section section, boolean canOverlap) { 052 iStudent = student; 053 iSection = section; 054 iAllowOverlap = canOverlap; 055 iStudent.getUnavailabilities().add(this); 056 iSection.getUnavailabilities().add(this); 057 } 058 059 /** 060 * Student 061 */ 062 public Student getStudent() { return iStudent; } 063 064 /** 065 * Section 066 */ 067 public Section getSection() { return iSection; } 068 069 /** 070 * Optional course id (within the course of {@link Unavailability#getSection()} 071 */ 072 public Long getCourseId() { return iCourseId; } 073 074 /** 075 * Optional course id (within the course of {@link Unavailability#getSection()} 076 */ 077 public void setCourseId(Long courseId) { iCourseId = courseId; } 078 079 /** 080 * Is this a teaching assignment 081 */ 082 public boolean isTeachingAssignment() { return iTeachingAssignment; } 083 084 /** 085 * Is this a teaching assignment, defaults to true 086 */ 087 public void setTeachingAssignment(boolean ta) { iTeachingAssignment = ta; } 088 089 /** 090 * Course name taken from the {@link Unavailability#getSection()} and optional {@link Unavailability#getCourseId()}. 091 * Name of the controlling course is used when no course id is set. 092 */ 093 public String getCourseName() { 094 if (getSection().getSubpart() == null) return ""; 095 Offering offering = getSection().getSubpart().getConfig().getOffering(); 096 if (getCourseId() != null) 097 for (Course course: offering.getCourses()) 098 if (course.getId() == getCourseId()) 099 return course.getName(); 100 return offering.getName(); 101 } 102 103 /** 104 * Section name using {@link Section#getName(long)} when the optional course id is provided, 105 * using {@link Section#getName()} otherwise. 106 */ 107 public String getSectionName() { 108 if (getSection().getSubpart() == null) return getSection().getName(); 109 if (getCourseId() != null) 110 return getSection().getSubpart().getName() + " " + getSection().getName(getCourseId()); 111 return getSection().getSubpart().getName() + " " +getSection().getName(); 112 } 113 114 @Override 115 public long getId() { 116 return getSection().getId(); 117 } 118 119 @Override 120 public TimeLocation getTime() { return getSection().getTime(); } 121 122 /** 123 * Can student have classes during this unavailability? The overlapping time should be minimized in this case 124 * (like with lower priority free time requests). 125 */ 126 @Override 127 public boolean isAllowOverlap() { return iAllowOverlap; } 128 129 @Override 130 public List<RoomLocation> getRooms() { 131 return getSection().getRooms(); 132 } 133 134 @Override 135 public int getNrRooms() { 136 return getSection().getNrRooms(); 137 } 138 139 @Override 140 public boolean isOverlapping(SctAssignment assignment) { 141 if (isAllowOverlap() || assignment.isAllowOverlap()) return false; 142 if (getTime() == null || assignment.getTime() == null) return false; 143 if (assignment instanceof Section && getTime().hasIntersection(assignment.getTime())) return true; 144 return false; 145 } 146 147 @Override 148 public boolean isOverlapping(Set<? extends SctAssignment> assignments) { 149 if (isAllowOverlap()) return false; 150 if (getTime() == null) return false; 151 for (SctAssignment assignment : assignments) { 152 if (assignment.isAllowOverlap()) continue; 153 if (assignment.getTime() == null) continue; 154 if (assignment instanceof Section && getTime().hasIntersection(assignment.getTime())) return true; 155 } 156 return false; 157 } 158 159 @Override 160 public void assigned(Assignment<Request, Enrollment> assignment, Enrollment enrollment) { 161 } 162 163 @Override 164 public void unassigned(Assignment<Request, Enrollment> assignment, Enrollment enrollment) { 165 } 166 167 /** 168 * Not used, always null 169 */ 170 @Override 171 public Set<Enrollment> getEnrollments(Assignment<Request, Enrollment> assignment) { 172 return null; 173 } 174 175 @Override 176 public int compareById(SctAssignment a) { 177 if (a instanceof Unavailability) { 178 return Long.valueOf(getId()).compareTo(((Unavailability)a).getId()); 179 } else { 180 return 1; 181 } 182 } 183 184 /** 185 * Create dummy enrollment of this unavailability 186 * @return created enrollment (warning: the returned enrollment has no request) 187 **/ 188 public Enrollment createEnrollment() { 189 HashSet<SctAssignment> assignments = new HashSet<SctAssignment>(); 190 assignments.add(this); 191 return new Enrollment(null, 0, null, assignments, null); 192 } 193 194 @Override 195 public boolean equals(Object o) { 196 if (o == null || !(o instanceof Unavailability)) return false; 197 return getId() == ((Unavailability)o).getId(); 198 } 199 200 @Override 201 public int hashCode() { 202 return (int) (getId() ^ (getId() >>> 32)); 203 } 204}