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