001package org.cpsolver.ifs.example.tt;
002
003import java.util.HashSet;
004import java.util.Set;
005
006import org.cpsolver.ifs.assignment.Assignment;
007import org.cpsolver.ifs.assignment.context.AssignmentConstraintContext;
008import org.cpsolver.ifs.assignment.context.ConstraintWithContext;
009
010
011/**
012 * Resource constraint
013 * 
014 * @version IFS 1.3 (Iterative Forward Search)<br>
015 *          Copyright (C) 2006 - 2014 Tomáš Müller<br>
016 *          <a href="mailto:muller@unitime.org">muller@unitime.org</a><br>
017 *          <a href="http://muller.unitime.org">http://muller.unitime.org</a><br>
018 * <br>
019 *          This library is free software; you can redistribute it and/or modify
020 *          it under the terms of the GNU Lesser General Public License as
021 *          published by the Free Software Foundation; either version 3 of the
022 *          License, or (at your option) any later version. <br>
023 * <br>
024 *          This library is distributed in the hope that it will be useful, but
025 *          WITHOUT ANY WARRANTY; without even the implied warranty of
026 *          MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
027 *          Lesser General Public License for more details. <br>
028 * <br>
029 *          You should have received a copy of the GNU Lesser General Public
030 *          License along with this library; if not see
031 *          <a href='http://www.gnu.org/licenses/'>http://www.gnu.org/licenses/</a>.
032 */
033public class Resource extends ConstraintWithContext<Activity, Location, Resource.Context> {
034    private String iName = null;
035    private String iResourceId = null;
036    private Set<Integer> iProhibitedSlots = new HashSet<Integer>();
037    private Set<Integer> iDiscouragedSlots = new HashSet<Integer>();
038    private int iType = TYPE_OTHER;
039    
040    public static final int TYPE_ROOM = 0;
041    public static final int TYPE_INSTRUCTOR = 1;
042    public static final int TYPE_CLASS = 2;
043    public static final int TYPE_OTHER = 3;
044
045    public Resource(String id, int type, String name) {
046        super();
047        iResourceId = id;
048        iName = name;
049        iType = type;
050    }
051    
052    public String getResourceId() { return iResourceId; }
053    @Override
054    public String getName() { return iName; }
055    public int getType() { return iType; }
056    public Set<Integer> getProhibitedSlots() { return iProhibitedSlots; }
057    public Set<Integer> getDiscouragedSlots() { return iDiscouragedSlots; }
058    public void addProhibitedSlot(int day, int hour) {
059        iProhibitedSlots.add(((TimetableModel)getModel()).getNrHours()*day+hour);
060    }
061    public void addDiscouragedSlot(int day, int hour) {
062        iDiscouragedSlots.add(((TimetableModel)getModel()).getNrHours()*day+hour);
063    }
064    public boolean isProhibitedSlot(int day, int hour) {
065        return iProhibitedSlots.contains(((TimetableModel)getModel()).getNrHours()*day+hour);
066    }
067    public boolean isDiscouragedSlot(int day, int hour) {
068        return iDiscouragedSlots.contains(((TimetableModel)getModel()).getNrHours()*day+hour);
069    }
070    public void addProhibitedSlot(int slot) {
071        iProhibitedSlots.add(slot);
072    }
073    public void addDiscouragedSlot(int slot) {
074        iDiscouragedSlots.add(slot);
075    }
076    public boolean isProhibitedSlot(int slot) {
077        return iProhibitedSlots.contains(slot);
078    }
079    public boolean isDiscouragedSlot(int slot) {
080        return iDiscouragedSlots.contains(slot);
081    }    
082    public boolean isProhibited(int day, int hour, int length) {
083        int slot = ((TimetableModel)getModel()).getNrHours()*day+hour;
084        for (int i=0;i<length;i++)
085            if (iProhibitedSlots.contains(slot+i)) return true;
086        return false;
087    }
088    
089    @Override
090    public void computeConflicts(Assignment<Activity, Location> assignment, Location location, Set<Location> conflicts) {
091        Activity activity = location.variable();
092        if (!location.containResource(this)) return;
093        Context context = getContext(assignment);
094        for (int i=location.getSlot(); i<location.getSlot()+activity.getLength(); i++) {
095            Activity conf = context.getActivity(i);
096            if (conf!=null && !activity.equals(conf)) 
097                conflicts.add(assignment.getValue(conf));
098        }
099    }
100    
101    @Override
102        public boolean inConflict(Assignment<Activity, Location> assignment, Location location) {
103        Activity activity = location.variable();
104        if (!location.containResource(this)) return false;
105        Context context = getContext(assignment);
106        for (int i=location.getSlot(); i<location.getSlot()+activity.getLength(); i++) {
107            if (context.getActivity(i) != null) return true;
108        }
109        return false;
110    }
111        
112    @Override
113        public boolean isConsistent(Location l1, Location l2) {
114        return !l1.containResource(this) || !l2.containResource(this) || !l1.hasIntersection(l2);
115    }
116    
117    @Override
118    public Context createAssignmentContext(Assignment<Activity, Location> assignment) {
119        return new Context(assignment);
120    }
121    
122    /**
123     * Assignment context
124     */
125    public class Context implements AssignmentConstraintContext<Activity, Location> {
126        private Activity[] iResource;
127        
128        public Context(Assignment<Activity, Location> assignment) {
129            TimetableModel model = (TimetableModel)getModel();
130            iResource = new Activity[model.getNrDays() * model.getNrHours()];
131            for (int i=0;i<iResource.length;i++)
132                    iResource[i] = null;
133            for (Location location: assignment.assignedValues())
134                assigned(assignment, location);
135        }
136
137        @Override
138        public void assigned(Assignment<Activity, Location> assignment, Location location) {
139            Activity activity = location.variable();
140            if (!location.containResource(Resource.this)) return;
141            for (int i=location.getSlot(); i<location.getSlot()+activity.getLength(); i++) {
142                iResource[i] = activity;
143            }
144        }
145        
146        public Activity getActivity(int slot) {
147            return iResource[slot];
148        }
149
150        @Override
151        public void unassigned(Assignment<Activity, Location> assignment, Location location) {
152            Activity activity = location.variable();
153            if (!location.containResource(Resource.this)) return;
154            for (int i=location.getSlot(); i<location.getSlot()+activity.getLength(); i++) {
155                iResource[i] = null;
156            }
157        }
158    }
159}