    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}