001    package aima.gui.applications;
002    
003    import java.awt.Color;
004    import java.util.ArrayList;
005    import java.util.Hashtable;
006    import java.util.List;
007    
008    import aima.basic.Agent;
009    import aima.basic.vaccum.*;
010    import aima.gui.framework.AgentAppController;
011    import aima.gui.framework.AgentAppFrame;
012    import aima.gui.framework.AgentAppModel;
013    import aima.gui.framework.AgentView;
014    import aima.gui.framework.SimpleAgentAppDemo;
015    
016    /**
017     * Simple graphical application for experiments with vacuum cleaner agents.
018     * It can be used as a template for creating other graphical agent
019     * applications. 
020     * @author R. Lunde
021     */
022    public class VacuumAppDemo extends SimpleAgentAppDemo {
023    
024            /** Returns a <code>VacuumModel</code>. */
025            public AgentAppModel createModel() {
026                    return new VacuumModel();
027            }
028            /** Returns a <code>VacuumFrame</code>. */
029            public AgentAppFrame createFrame() {
030                    return new VacuumFrame();
031            }
032            /** Returns a <code>VacuumController</code>. */
033            public AgentAppController createController() {
034                    return new VacuumController();
035            }
036    
037            
038            /////////////////////////////////////////////////////////////////
039            // inner classes
040            
041            /**
042             * Provides access to the used environment, the names
043             * of the locations (squares) maintained by the environment, and the
044             * current state of all locations.
045             */
046            protected static class VacuumModel extends AgentAppModel {
047                    private TrivialVaccumEnvironment env;
048                    private Agent agent;
049                    public static String DIRTY = "Dirty";
050                    
051                    public void setEnv(TrivialVaccumEnvironment env) { this.env = env; }
052                    public TrivialVaccumEnvironment getEnv() { return env; }
053                    public void setAgent(Agent agent) { this.agent = agent; }
054                    public Agent getAgent() { return agent; }
055                    
056                    /** Returns the names of all locations used. */
057                    public List<String> getLocations() {
058                            List<String> result = new ArrayList<String>();
059                            if (env != null) {
060                                    result.add("A");
061                                    result.add("B");
062                            }
063                            return result;
064                    }
065                    /** Checks whether the specified location is dirty. */
066                    public boolean isDirty(String location) {
067                            return DIRTY.equals(env.getLocationStatus(location));
068                    }
069                    /** Checks whether the agent is currently at the specified location. */
070                    public boolean hasAgent(String location) {
071                            return agent != null && location.equals(env.getAgentLocation(agent));
072                    }
073            }
074            
075            /**
076             * Adds some selectors to the base class and adjusts its size.
077             */
078            protected static class VacuumFrame extends AgentAppFrame {
079                    public static String ENV_SEL = "EnvSelection";
080                    public static String AGENT_SEL = "AgentSelection";
081                    public VacuumFrame() {
082                            setAgentView(new VacuumView());
083                            setSelectors(
084                                            new String[]{ENV_SEL, AGENT_SEL},
085                                            new String[]{"Select Environment", "Select Agent"});
086                            setSelectorItems(ENV_SEL, new String[]{"A/B Environment"}, 0);
087                            setSelectorItems(AGENT_SEL, new String[]{
088                                            "SimpleReflexVaccumAgent",
089                                            "ReflexVaccumAgent",
090                                            "ReflexVaccumAgentWithState",
091                                            "TableDrivenVaccumAgent",
092                                            "ModelBasedTVEVaccumAgent"}, 0);
093                            setTitle("Vacuum Agent Application");
094                            setSize(800, 400);
095                            setUpdateDelay(500);
096                    }
097            }
098            
099            /**
100             * Displays the informations provided by the <code>VacuumModel</code>
101             * on a panel using 2D-graphics.
102             */
103            protected static class VacuumView extends AgentView {
104                    Hashtable<String, int[]> dirtLookup = new Hashtable<String, int[]>();
105                    
106                    int[] getDirt(String location) {
107                            int[] coords = dirtLookup.get(location);
108                            if (coords == null) {
109                                    java.util.Random rand = new java.util.Random();
110                                    int size = rand.nextInt(8)+4;
111                                    coords = new int[2*size];
112                                    for (int i = 0; i < size; i++) {
113                                    coords[2*i] = rand.nextInt(6)+1;
114                                    coords[2*i+1] = rand.nextInt(8)+1;
115                                    }
116                            }
117                            dirtLookup.put(location, coords);
118                            return coords;
119                    }
120                    
121                    /**
122                     * Creates a 2D-graphics showing the agent in its environment.
123                     * Locations are represented as rectangles, dirt as grey ovals,
124                     * and the agent as red circle.
125                     */
126                    public void paint(java.awt.Graphics g) {
127                            VacuumModel vmodel = (VacuumModel) model;
128                            List<String> locations = vmodel.getLocations();
129                            this.adjustTransformation(0, 0, 11*locations.size()-1, 10);
130                        java.awt.Graphics2D g2 = (java.awt.Graphics2D) g;
131                        g2.setColor(Color.white);
132                        g2.fillRect(0, 0, getWidth(), getHeight());
133                        for (int i = 0; i < locations.size(); i++) {
134                            String location = locations.get(i);
135                            g2.setColor(Color.black);
136                            g2.drawRect(x(11*i), y(0), scale(10), scale(10));
137                            if (vmodel.isDirty(location)) {
138                                    int[] coords = getDirt(location); 
139                                    for (int j = 0; j < coords.length; j+=2) {
140                                            g2.setColor(Color.lightGray);
141                                            g2.fillOval(x(11*i+coords[j]), y(coords[j+1]), scale(3), scale(2));
142                                    }
143                            }
144                            g2.setColor(Color.black);
145                            g2.drawString(location, x(11*i)+10, y(0)+20);
146                            if (vmodel.hasAgent(location)) {
147                                    g2.setColor(Color.red);
148                                    g2.fillOval(x(11*i+2), y(2), scale(6), scale(6));
149                            }       
150                        }
151                    }
152            }
153            
154            /**
155             * Defines how to react on user button events.
156             */
157            protected static class VacuumController extends AgentAppController {
158                    /** Does nothing. */
159                    public void clearAgent() {
160                    }
161                    
162                    /**
163                     * Creates a vacuum agent and a corresponding environment based
164                     * on the selection state of the selectors and finally updates
165                     * the model.
166                     */
167                    public void prepareAgent() {
168                            AgentAppFrame.SelectionState selState = frame.getSelection();
169                            TrivialVaccumEnvironment env = null;
170                            Agent agent = null;
171                            switch(selState.getValue(VacuumFrame.ENV_SEL)) {
172                            case 0: env = new TrivialVaccumEnvironment(); break;
173                            }
174                            switch(selState.getValue(VacuumFrame.AGENT_SEL)) {
175                            case 0: agent = new SimpleReflexVaccumAgent(); break;
176                            case 1: agent = new ReflexVaccumAgent(); break;
177                            case 2: agent = new ReflexVaccumAgentWithState(); break;
178                            case 3: agent = new TableDrivenVaccumAgent(); break;
179                            case 4: agent = new ModelBasedTVEVaccumAgent(); break;
180                            }
181                            ((VacuumModel) model).setEnv(env);
182                            ((VacuumModel) model).setAgent(agent);
183                            if (env != null && agent != null) {
184                                    env.addAgent(agent);
185                                    env.registerView(model);
186                                    frame.modelChanged();
187                            }
188                    }
189                    
190                    /** Starts the agent and afterwards updates the status of the frame. */
191                    public void runAgent() {
192                            VacuumModel vmodel = (VacuumModel) model;
193                            frame.logMessage("<simulation-log>");
194                            vmodel.getEnv().stepUntilDone();
195                            frame.logMessage("Performance: " +
196                                            vmodel.getEnv().getAgentperformance(vmodel.getAgent()));
197                            frame.logMessage("</simulation-log>");
198                            frame.setStatus("Task completed.");
199                    }
200            }
201            
202            
203            /////////////////////////////////////////////////////////////////
204            // main method
205            
206            /**
207             * Starts the application.
208             */
209            public static void main(String args[]) {
210                    new VacuumAppDemo().startApplication();
211            }
212    }