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