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.simulation;
025    
026    import java.awt.Graphics2D;
027    import java.text.DateFormat;
028    import java.util.ArrayList;
029    import java.util.Calendar;
030    import java.util.Collections;
031    import java.util.Comparator;
032    import java.util.HashMap;
033    import java.util.List;
034    
035    import se.liu.ida.critiquer.activities.Activity;
036    import se.liu.ida.critiquer.activities.ActivityUtils;
037    import se.liu.ida.critiquer.activities.TransportationActivity;
038    import se.liu.ida.critiquer.gui.GeoView;
039    import se.liu.ida.critiquer.mics.Comparer;
040    import se.liu.ida.critiquer.mics.ReferenceHolder;
041    import se.liu.ida.critiquer.mics.Utils;
042    import se.liu.ida.critiquer.resources.Agent;
043    import se.liu.ida.critiquer.scenarios.standard.AgentParameterName;
044    
045    /**
046     * @author olale
047     * 
048     */
049    public class DefaultAgentSimulationState implements AgentSimulationState {
050    
051            /**
052             * 
053             */
054            public static final String FUEL_LEVEL = "fuel level";
055    
056            /**
057         * 
058         */
059            private static final long          serialVersionUID   = 1L;
060    
061            private HashMap<String, Object> state                       = new HashMap<String, Object>();
062    
063            private Agent                              agent;
064    
065            private SimulationEngine                engine;
066    
067            /**
068         * This is the list of all activities this agent participates in, sorted in
069         * temporal order
070         */
071            private ArrayList<Activity>        activitiesForAgent = new ArrayList<Activity>();
072    
073            /**
074         * This is the list of activities that have already been simulated
075         */
076            private ArrayList<Activity>        consumedActivities = new ArrayList<Activity>();
077    
078            /**
079         * 
080         */
081            public DefaultAgentSimulationState(Agent agent) {
082                    this.agent = agent;
083            }
084    
085            /*
086         * (non-Javadoc)
087         * 
088         * @see se.liu.ida.critiquer.resources.AgentSimulationState#setPropertyMap(java.util.HashMap)
089         */
090    
091            public <T> void setProperty(String key, T value) {
092                    state.put(key, value);
093            }
094    
095            /*
096         * (non-Javadoc)
097         * 
098         * @see se.liu.ida.critiquer.resources.AgentSimulationState#getProperty(java.lang.String,
099         *      java.lang.Class)
100         */
101            @SuppressWarnings("unchecked")
102            public <C> C getProperty(String name, Class<C> type) {
103                    C returnValue = null;
104                    if (state.containsKey(name)) {
105                            Object value = state.get(name);
106                            if (value.getClass() == type) {
107                                    returnValue = (C) value;
108                            }
109                    }
110                    return returnValue;
111    
112            }
113    
114            /*
115         * (non-Javadoc)
116         * 
117         * @see se.liu.ida.critiquer.resources.AgentSimulationState#renderState(se.liu.ida.critiquer.simulation.GeoView,
118         *      java.awt.Graphics2D)
119         */
120            public void renderState(GeoView view, Graphics2D g2) {
121                    // TODO Auto-generated method stub
122    
123            }
124    
125            /**
126         * @see se.liu.ida.critiquer.simulation.AgentSimulationState#getAgent()
127         */
128            public Agent getAgent() {
129    
130                    return agent;
131            }
132    
133            /**
134         * 
135         * Called every time the simulation engine starts a simulation
136         * 
137         * @see se.liu.ida.critiquer.simulation.SimulationElement#initSimulation()
138         */
139            public void initSimulation(SimulationEngine engine) {
140                    this.engine=engine;
141                    setProperties();
142                    activitiesForAgent = agent.getActivitiesForAgent();
143    
144                    sortActivities(activitiesForAgent);
145            }
146    
147            private void sortActivities(List<Activity> activities) {
148                    Collections.sort(activities, new Comparator<Activity>() {
149    
150                            public int compare(Activity a1, Activity a2) {
151                                    Calendar t1 = ActivityUtils.getStartTimeParameter(a1).getValue();
152                                    Calendar t2 = ActivityUtils.getStartTimeParameter(a2).getValue();
153                                    return t1.compareTo(t2);
154                            }
155    
156                    });
157            }
158    
159            /**
160         * 
161         * Step forward or backwards in time to the absolute time <code>time</code>
162         * 
163         * @param time
164         *            the destination time
165         */
166            public void stepTo(Calendar time) {
167                    setProperties();
168                    ArrayList<Activity> activities = activitiesForAgent;
169                    for (Activity activity : activities) {
170                            Calendar endTime = ActivityUtils.getEndTimeParameter(activity).getValue();
171                            if (time.after(endTime)) {
172                                    consumeActivity(activity);
173                            } else {
174                                    break;
175                            }       
176                    }
177            }
178    
179            /**
180         * 
181         * Move forward in the simulation with the agent
182         * 
183         * @see se.liu.ida.critiquer.simulation.SimulationElement#stepForward(int)
184         */
185            public void stepForward(int step) {
186                    Calendar nextTime = (Calendar) engine.getCurrentTime().clone();
187                    nextTime.add(Calendar.MINUTE, step);
188                    stepTo(nextTime);
189    
190            }
191    
192            
193            /**
194             * Set the properties that define this state.
195             *
196             */
197            protected void setProperties() {
198                    setProperty(FUEL_LEVEL, agent.getParamByClassAndName(Integer.class, AgentParameterName.FUEL_CAPACITY).getValue());
199                    //setProperty("time since rest", 0);
200            }
201    
202            /**
203         * When <code>activity</code> has finished, calculate how properties are
204         * modified
205         * 
206         * @param activity
207         */
208            protected void consumeActivity(Activity activity) {
209                    if (activity instanceof TransportationActivity) {
210                            TransportationActivity transportActivity = (TransportationActivity) activity;
211                            // distance in meters
212                            double distanceInPixels = transportActivity.getStart().distanceTo(transportActivity.getEnd());
213                            // Distance in 100 kilometers
214                            double distance = ReferenceHolder.simulationView.getScale()*distanceInPixels/100000;
215                            // fuel consumption in liters per 100 kilometers
216                            Integer fuelConsumption = getAgent().getParamByClassAndName(Integer.class, AgentParameterName.FUEL_CONSUMPTION).getValue();
217                            Integer fuelLevel = getProperty(FUEL_LEVEL, Integer.class);
218                    
219                            int newFuelLevel = (int) (fuelLevel-fuelConsumption*distance);
220                            System.out.println("New fuel level: "+newFuelLevel);
221                            setProperty(FUEL_LEVEL,new Integer(newFuelLevel));
222                    
223                            
224                    }
225            }
226    
227            /**
228         * @see se.liu.ida.critiquer.simulation.SimulationElement#stepBackward(int)
229         */
230            public void stepBackward(int step) {
231                    Calendar previousTime = (Calendar) engine.getCurrentTime().clone();
232                    previousTime.add(Calendar.MINUTE, step);
233                    stepTo(previousTime);
234            }
235    
236    }