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