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