001    /**
002     * planningtool - A Planning Tool with Critiquing Support.
003     * 
004     * Copyright (C) 2006 olale
005    
006     * This program is free software; you can redistribute it and/or
007     * modify it under the terms of the GNU General Public License
008     * as published by the Free Software Foundation; either version 2
009     * of the License, or (at your option) any later version.
010    
011     * This program is distributed in the hope that it will be useful,
012     * but WITHOUT ANY WARRANTY; without even the implied warranty of
013     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
014     * GNU General Public License for more details.
015    
016     * You should have received a copy of the GNU General Public License
017     * along with this program; if not, write to the Free Software
018     * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
019    
020     * Contact information: 
021     * E-mail: olale@ida.liu.se
022     *         olale@lysator.liu.se
023     */
024    package se.liu.ida.critiquer.constraints;
025    
026    import java.awt.Graphics2D;
027    import java.util.Calendar;
028    import java.util.HashMap;
029    
030    import se.liu.ida.critiquer.activities.Activity;
031    import se.liu.ida.critiquer.activities.ActivityUtils;
032    import se.liu.ida.critiquer.activities.IncompleteActivityException;
033    import se.liu.ida.critiquer.activities.parameters.Parameter;
034    import se.liu.ida.critiquer.activities.parameters.TimeParameter;
035    import se.liu.ida.critiquer.gui.View;
036    
037    public class TimeCalculator extends StandardConstraint {
038    
039            /**
040         * 
041         */
042            private static final long          serialVersionUID = 1L;
043    
044            /**
045         * If the time to complete a mission does not change for a while, we save
046         * the last calculation in a hashmap here.
047         */
048            private HashMap<Activity, Long> timesToComplete  = new HashMap<Activity, Long>();
049    
050            /**
051         * When in aggressive mode, don't allow slack
052         */
053            private boolean                          aggressive        = false;
054    
055            int                                                      maxSlack                = 10;
056    
057            @Override
058            public <T> void paramChanged(Activity activity, Parameter<T> p) {
059                    Long timeToComplete;
060                    if (activity.isMissionTimeChanged()) {
061                            try {
062                                    timeToComplete = activity.calculateTimeToComplete();
063                                    timesToComplete.put(activity, timeToComplete);
064                            } catch (IncompleteActivityException exception) {
065                                    // TODO Auto-generated catch block
066                                    exception.printStackTrace();
067                            }
068                            activity.setMissionTimeChanged(false);
069                    }
070    
071                    timeToComplete = timesToComplete.get(activity);
072                    if (timeToComplete == null) {
073                            timeToComplete = 0L;
074                    }
075                    Long currentTime = ActivityUtils.getCurrentTimeForActivity(activity);
076                    boolean notEnoughTime = currentTime < timeToComplete;
077                    boolean tooMuchTime = currentTime > timeToComplete + maxSlack;
078                    /**
079             * if (notEnoughTime) { System.out.println("Not enough time for
080             * "+activity+": "+currentTime); } else if (tooMuchTime) {
081             * System.out.println("Too much time for "+activity+": "+currentTime); }
082             */
083                    if (notEnoughTime || (isAggressive() && tooMuchTime)) {
084                            // Ok, ensure there is enough time for the mission to complete
085                            // even if some other event has changed the time parameters
086                            TimeParameter startTime = ActivityUtils.getStartTimeParameter(activity);
087                            TimeParameter endTime = ActivityUtils.getEndTimeParameter(activity);
088                            if (p == endTime) {
089                                    Calendar newTime = (Calendar) endTime.getValue().clone();
090                                    newTime.add(Calendar.MINUTE, -1 * timeToComplete.intValue());
091                                    startTime.setValue(newTime);
092    
093                            } else {
094                                    Calendar newTime = (Calendar) startTime.getValue().clone();
095                                    newTime.add(Calendar.MINUTE, timeToComplete.intValue());
096                                    endTime.setValue(newTime);
097                            }
098                    }
099    
100            }
101    
102            /**
103         * @return Returns the aggressive.
104         */
105            public boolean isAggressive() {
106                    return aggressive;
107            }
108    
109            /**
110         * Set aggressiveness. If aggressive, the constraint will react on and/or
111         * make sure that there is not more time allocated to the activity than what
112         * the activity calculates that it will take with the current resources.
113         * When not aggressive, it will only react on if there is too little time
114         * allocated.
115         * 
116         * @param aggressive
117         *            The aggressive to set.
118         */
119            public void setAggressive(boolean aggressive) {
120                    this.aggressive = aggressive;
121            }
122    
123            /*
124         * (non-Javadoc)
125         * 
126         * @see se.liu.ida.critiquer.constraints.SingletonConstraint#getDescription()
127         */
128            public String getDescription() {
129                    // TODO Auto-generated method stub
130                    return "Calculates the time it takes for activities to complete depending on the agents currently used";
131            }
132    
133            /*
134         * (non-Javadoc)
135         * 
136         * @see se.liu.ida.critiquer.gui.ViewRenderingListener#viewUpdated(se.liu.ida.critiquer.gui.View,
137         *      java.awt.Graphics2D)
138         */
139            public void viewUpdated(View v, Graphics2D g2) {
140                    // TODO Auto-generated method stub
141    
142            }
143    
144            /**
145         * 
146         * This constraint doesn't have any visual appearance yet, so we do not show
147         * it as eligible in any of the views.
148         * 
149         * @see se.liu.ida.critiquer.constraints.StandardConstraint#isApplicableFor(se.liu.ida.critiquer.gui.View)
150         */
151            @Override
152            public boolean isApplicableFor(View view) {
153    
154                    return false;
155            }
156    
157    }