    001package net.sf.cpsolver.studentsct.model;
    002
    003import java.util.List;
    004
    005import net.sf.cpsolver.ifs.model.Variable;
    006
    007/**
    008 * Representation of a request of a student for a course(s) or a free time. This
    009 * can be either {@link CourseRequest} or {@link FreeTimeRequest}. Each request
    010 * contains id, priority, weight, and a student. A request can be also marked as
    011 * alternative. <br>
    012 * <br>
    013 * For each student, all non-alternative requests should be satisfied (an
    014 * enrollment is assigned to a request). If not, an alternative request can be
    015 * assigned instead of a non-alternative course request. In the case when only
    016 * one of two requests can be assigned, the one with the lowest priority is
    017 * preferred. <br>
    018 * <br>
    019 *
    020 * @version StudentSct 1.2 (Student Sectioning)<br>
    021 *          Copyright (C) 2007 - 2010 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 abstract class Request extends Variable<Request, Enrollment> {
    040    private long iId = -1;
    041    private int iPriority = 0;
    042    private boolean iAlternative = false;
    043    private Student iStudent = null;
    044    private double iWeight = 1.0;
    045    /** True means that method {@link Request#values()} will cache its results. */
    046    public static boolean sCacheValues = false;
    047
    048    /**
    049     * Constructor
    050     *
    051     * @param id
    052     *            course/free time request unique id
    053     * @param priority
    054     *            request priority -- if there is a choice, request with lower
    055     *            priority is more preferred to be assigned
    056     * @param alternative
    057     *            true if the request is alternative (alternative request can be
    058     *            assigned instead of a non-alternative course requests, if it
    059     *            is left unassigned)
    060     * @param student
    061     *            student to which this request belongs
    062     */
    063    public Request(long id, int priority, boolean alternative, Student student) {
    064        iId = id;
    065        iPriority = priority;
    066        iAlternative = alternative;
    067        iStudent = student;
    068        iStudent.getRequests().add(this);
    069    }
    070
    071    /** Request id */
    072    @Override
    073    public long getId() {
    074        return iId;
    075    }
    076
    077    /**
    078     * Request priority -- if there is a choice, request with lower priority is
    079     * more preferred to be assigned
    080     */
    081    public int getPriority() {
    082        return iPriority;
    083    }
    084
    085    /** Set request priority */
    086    public void setPriority(int priority) {
    087        iPriority = priority;
    088    }
    089
    090    /**
    091     * True, if the request is alternative (alternative request can be assigned
    092     * instead of a non-alternative course requests, if it is left unassigned)
    093     */
    094    public boolean isAlternative() {
    095        return iAlternative;
    096    }
    097
    098    /** Student to which this request belongs */
    099    public Student getStudent() {
    100        return iStudent;
    101    }
    102
    103    /**
    104     * Compare to requests, non-alternative requests go first, otherwise use
    105     * priority (a request with lower priority goes first)
    106     */
    107    @Override
    108    public int compareTo(Request r) {
    109        if (getStudent().getId() == r.getStudent().getId())
    110            return (isAlternative() != r.isAlternative() ? isAlternative() ? 1 : -1 : getPriority() < r.getPriority() ? -1 : 1);
    111        else
    112            return getStudent().compareTo(r.getStudent());
    113    }
    114
    115    /** Compute available enrollments */
    116    public abstract List<Enrollment> computeEnrollments();
    117
    118    /**
    119     * Domain of this variable -- list of available enrollments. Method
    120     * {@link Request#computeEnrollments()} is used.
    121     */
    122    @Override
    123    public List<Enrollment> values() {
    124        List<Enrollment> values = super.values();
    125        if (values != null)
    126            return values;
    127        values = computeEnrollments();
    128        if (sCacheValues)
    129            setValues(values);
    130        return values;
    131    }
    132
    133    /**
    134     * Assign given enrollment to this request. This method also calls
    135     * {@link Assignment#assigned(Enrollment)} on for all the assignments of the
    136     * enrollment.
    137     */
    138    @Override
    139    public void assign(long iteration, Enrollment enrollment) {
    140        super.assign(iteration, enrollment);
    141        for (Assignment a : enrollment.getAssignments()) {
    142            a.assigned(enrollment);
    143        }
    144        if (enrollment.getConfig() != null)
    145            enrollment.getConfig().assigned(enrollment);
    146        if (enrollment.getCourse() != null)
    147            enrollment.getCourse().assigned(enrollment);
    148        if (enrollment.getReservation() != null)
    149            enrollment.getReservation().assigned(enrollment);
    150    }
    151
    152    /**
    153     * Unassign currently assigned enrollment from this request. This method
    154     * also calls {@link Assignment#unassigned(Enrollment)} on for all the
    155     * assignments of the current enrollment.
    156     */
    157    @Override
    158    public void unassign(long iteration) {
    159        if (getAssignment() != null) {
    160            Enrollment enrollment = getAssignment();
    161            for (Assignment a : enrollment.getAssignments()) {
    162                a.unassigned(enrollment);
    163            }
    164            if (enrollment.getConfig() != null)
    165                enrollment.getConfig().unassigned(enrollment);
    166            if (enrollment.getCourse() != null)
    167                enrollment.getCourse().unassigned(enrollment);
    168            if (enrollment.getReservation() != null)
    169                enrollment.getReservation().unassigned(enrollment);
    170        }
    171        super.unassign(iteration);
    172    }
    173
    174    /** Get bound, i.e., the value of the best possible enrollment */
    175    public abstract double getBound();
    176
    177    /**
    178     * Request weight, set by default to 1.0, defines the amount of space which
    179     * will be taken in the section by this request.
    180     */
    181    public double getWeight() {
    182        return iWeight;
    183    }
    184
    185    /**
    186     * Set request weight. It defines the amount of space which will be taken in
    187     * the section by this request.
    188     */
    189    public void setWeight(double weight) {
    190        iWeight = weight;
    191    }
    192
    193    /** Return true if request is assigned. */
    194    public boolean isAssigned() {
    195        return getAssignment() != null;
    196    }
    197
    198    @Override
    199    public int hashCode() {
    200        return (int) (iId ^ (iId >>> 32) ^ getStudent().getId() ^ (getStudent().getId() >>> 32));
    201    }
    202
    203    @Override
    204    public boolean equals(Object o) {
    205        if (o == null || !(o instanceof Request)) return false;
    206        return getId() == ((Request)o).getId() && getStudent().getId() == ((Request)o).getStudent().getId();
    207    }
    208
    209}