001 package aima.gui.applications.search.map; 002 003 import java.text.DecimalFormat; 004 import java.util.List; 005 006 import aima.basic.Agent; 007 import aima.gui.framework.AgentAppController; 008 import aima.search.framework.SearchFactory; 009 import aima.search.map.AdaptableHeuristicFunction; 010 import aima.search.map.DynAttributeNames; 011 import aima.search.map.Scenario; 012 013 /** 014 * Provides a useful base class for agent application controller implementations 015 * in the context of route planning agent application development. To get it 016 * ready to work, all you need to do is, to provide implementations for the four 017 * abstract methods. See {@link RoutePlanningAgentAppDemo} for an example. 018 * 019 * @author R. Lunde 020 */ 021 public abstract class AbstractMapAgentController extends AgentAppController { 022 /** A scenario. */ 023 protected Scenario scenario; 024 /** 025 * Some location names. For route planning problems, only one location 026 * should be specified. 027 */ 028 protected List<String> destinations; 029 /** Search method to be used. */ 030 protected aima.search.framework.Search search; 031 /** Heuristic function to be used when performing informed search. */ 032 protected AdaptableHeuristicFunction heuristic; 033 034 /** Clears the model's tour history. */ 035 @Override 036 public void clearAgent() { 037 ((MapAgentModel) model).clearTourHistory(); 038 frame.modelChanged(); 039 } 040 041 /** 042 * Template method, which performs necessary preparations for running the 043 * agent. The behavior is strongly influenced by the primitive operations 044 * {@link #selectScenarioAndDest(int, int)}, {@link #prepareModel()} and 045 * {@link #createHeuristic(int)}. 046 */ 047 @Override 048 public void prepareAgent() { 049 MapAgentFrame.SelectionState state = frame.getSelection(); 050 selectScenarioAndDest(state.getValue(MapAgentFrame.SCENARIO_SEL), state 051 .getValue(MapAgentFrame.DESTINATION_SEL)); 052 prepareModel(); 053 search = SearchFactory.getInstance().createSearch( 054 state.getValue(MapAgentFrame.SEARCH_SEL), 055 state.getValue(MapAgentFrame.SEARCH_MODE_SEL)); 056 heuristic = createHeuristic(state.getValue(MapAgentFrame.HEURISTIC_SEL)); 057 scenario.getEnv().registerView(model); 058 } 059 060 /** 061 * Template method, which calls {@link #startAgent()} and then updates the 062 * status bar of the frame. 063 */ 064 @Override 065 public void runAgent() { 066 startAgent(); 067 List agents = scenario.getEnv().getAgents(); 068 if (agents.size() == 1) { 069 Agent agent = (Agent) agents.get(0); 070 String status = (String) agent 071 .getAttribute(DynAttributeNames.AGENT_STATUS); 072 Double travelDistance = (Double) agent 073 .getAttribute(DynAttributeNames.AGENT_TRAVEL_DISTANCE); 074 StringBuffer statusMsg = new StringBuffer(); 075 if (status != null) 076 statusMsg.append("Agent status: " + status); 077 else 078 statusMsg.append("Task completed"); 079 if (travelDistance != null) { 080 DecimalFormat f = new DecimalFormat("#0.0"); 081 statusMsg.append("; travel distance: " + f.format(travelDistance)); 082 } 083 statusMsg.append("."); 084 frame.setStatus(statusMsg.toString()); 085 } 086 } 087 088 // /////////////////////////////////////////////////////////////// 089 // abstract methods 090 091 /** 092 * Primitive operation, responsible for assigning values to attributes 093 * {@link #scenario} and {@link #destinations}. 094 */ 095 abstract protected void selectScenarioAndDest(int scenarioIdx, int destIdx); 096 097 /** 098 * Primitive operation, responsible for preparing the model. Scenario and 099 * destinations are already selected when this method is called. 100 */ 101 abstract protected void prepareModel(); 102 103 /** 104 * Factory method, responsible for creating a heuristic function. 105 */ 106 abstract protected AdaptableHeuristicFunction createHeuristic(int heuIdx); 107 108 /** 109 * Primitive operation, responsible for creating and starting the agent. 110 * Scenario, destinations are selected before as well as search method and 111 * search heuristic. 112 */ 113 protected abstract void startAgent(); 114 115 }