001    package aima.gui.applications.search.map;
002    
003    import java.util.ArrayList;
004    import java.util.List;
005    
006    import aima.basic.Agent;
007    import aima.gui.framework.AgentAppModel;
008    import aima.search.map.DynAttributeNames;
009    import aima.search.map.Map;
010    import aima.search.map.Point2D;
011    import aima.search.map.Scenario;
012    
013    /**
014     * Provides a ready-to-use implementation of a model for route planning agent
015     * applications. It is based on a scenario description and a list of
016     * destinations. Some features are not used. Subclasses can support those
017     * features by overriding the methods {@link #hasInfos(String)}, and
018     * {@link #hasObjects(String)}.
019     * 
020     * @author R. Lunde
021     */
022    public class MapAgentModel extends AgentAppModel {
023            /** A scenario. */
024            protected Scenario scenario;
025            /** A list of location names, possibly null. */
026            protected List<String> destinations;
027    
028            /** Stores the locations, the agent has already visited. */
029            private final ArrayList<String> tourHistory = new ArrayList<String>();
030    
031            /** Returns a list of all already visited agent locations. */
032            public List<String> getTourHistory() {
033                    return tourHistory;
034            }
035    
036            /** Clears the list of already visited locations. */
037            public void clearTourHistory() {
038                    tourHistory.clear();
039            }
040    
041            /**
042             * Reacts on environment changes and updates the tour history. The command
043             * string is always send to all registered model change listeners. If the
044             * command is a location name (with attached position info) or
045             * {@link aima.basic.Agent#NO_OP}, the
046             * agent's current location is added to the tour history and all listeners
047             * are informed about the change.
048             */
049            @Override
050            public void envChanged(String command) {
051                    for (AgentAppModel.ModelChangedListener listener : listeners)
052                            listener.logMessage(command);
053                    if (getLocCoords(command) != null || command.equals(Agent.NO_OP)) {
054                            String loc = (String) getAgent().getAttribute(
055                                            DynAttributeNames.AGENT_LOCATION);
056                            tourHistory.add(loc);
057                            fireModelChanged();
058                    }
059            }
060            
061            /**
062             * Assigns values to the attributes {@link #scenario} and
063             * {@link #destinations}, clears the history and informs all interested
064             * listeners about the model change.
065             * 
066             * @param s
067             *            A scenario or null.
068             * @param d
069             *            List of location names or null.
070             */
071            public void prepare(Scenario s, List<String> d) {
072                    scenario = s;
073                    destinations = d;
074                    clearTourHistory();
075                    fireModelChanged();
076            }
077    
078            /** Checks whether there is a scenario available. */
079            public boolean isEmpty() {
080                    return scenario == null;
081            }
082    
083            /**
084             * Returns all location names mentioned in the environment map or in the
085             * agent map.
086             */
087            public List<String> getLocations() {
088                    List<String> result = scenario.getEnvMap().getLocations();
089                    if (!result.containsAll(scenario.getAgentMap().getLocations())) {
090                            result = new ArrayList<String>(result);
091                            for (String loc : scenario.getAgentMap().getLocations())
092                                    if (!result.contains(loc))
093                                            result.add(loc);
094                    }
095                    return result;
096            }
097    
098            /** Returns the map used by the agent. */
099            public Map getAgentMap() {
100                    return scenario.getAgentMap();
101            }
102    
103            /** Returns the map used by the environment. */
104            public Map getEnvMap() {
105                    return scenario.getEnvMap();
106            }
107    
108            /** Returns the agent. */
109            public Agent getAgent() {
110                    return (Agent) scenario.getEnv().getAgents().get(0);
111            }
112    
113            /** Checks whether a given location is the initial location of the agent. */
114            public boolean isStart(String loc) {
115                    return scenario.getInitAgentLocation() == loc;
116            }
117    
118            /** Checks whether a given location is one of the specified destinations. */
119            public boolean isDestination(String loc) {
120                    return destinations != null && destinations.contains(loc);
121            }
122    
123            /**
124             * Returns the coordinates of the specified location.
125             */
126            public Point2D getLocCoords(String loc) {
127                    return scenario.getEnvMap().getPosition(loc);
128            }
129    
130            /**
131             * Checks whether special informations can be perceived at the location.
132             * This implementation always returns false.
133             */
134    
135            public boolean hasInfos(String loc) {
136                    return false; // not implemented yet
137            }
138    
139            /**
140             * Checks whether interesting objects can be perceived at the location.
141             * This implementation always returns false.
142             */
143            public boolean hasObjects(String loc) {
144                    return false; // not implemented yet
145            }
146    }