001package myproject.model;
002
003import java.util.List;
004import java.util.ArrayList;
005import java.util.Observable;
006import myproject.util.Animator;
007
008/**
009 * An example to model for a simple visualization.
010 * The model contains roads organized in a matrix.
011 * See {@link #Model(AnimatorBuilder, int, int)}.
012 */
013public class Model extends Observable {
014        private List<Agent> agents;
015        private Animator animator;
016        private boolean disposed;
017        private double time;
018
019        /** Creates a model to be visualized using the <code>builder</code>.
020         *  If the builder is null, no visualization is performed.
021         *  The number of <code>rows</code> and <code>columns</code>
022         *  indicate the number of {@link Light}s, organized as a 2D
023         *  matrix.  These are separated and surrounded by horizontal and
024         *  vertical {@link Road}s.  For example, calling the constructor with 1
025         *  row and 2 columns generates a model of the form:
026         *  <pre>
027         *     |  |
028         *   --@--@--
029         *     |  |
030         *  </pre>
031         *  where <code>@</code> is a {@link Light}, <code>|</code> is a
032         *  vertical {@link Road} and <code>--</code> is a horizontal {@link Road}.
033         *  Each road has one {@link Car}.
034         *
035         *  <p>
036         *  The {@link AnimatorBuilder} is used to set up an {@link
037         *  Animator}.
038         *  {@link AnimatorBuilder#getAnimator()} is registered as
039         *  an observer of this model.
040         *  <p>
041         */
042        public Model(AnimatorBuilder builder, int rows, int columns) {
043                if (rows < 0 || columns < 0 || (rows == 0 && columns == 0)) {
044                        throw new IllegalArgumentException();
045                }
046                if (builder == null) {
047                        builder = new NullAnimatorBuilder();
048                }
049                this.agents = new ArrayList<Agent>();
050                setup(builder, rows, columns);
051                this.animator = builder.getAnimator();
052                super.addObserver(animator);
053        }
054
055        /**
056         * Run the simulation for <code>duration</code> model seconds.
057         */
058        public void run(double duration) {
059                if (disposed)
060                        throw new IllegalStateException();
061                for (int i=0; i<duration; i++) {
062                        time++;
063                        // iterate through a copy because agents may change during iteration...
064                        for (Agent a : agents.toArray(new Agent[0])) {
065                                a.run(time);
066                        }
067                        super.setChanged();
068                        super.notifyObservers();
069                }
070        }
071
072        /**
073         * Throw away this model.
074         */
075        public void dispose() {
076                animator.dispose();
077                disposed = true;
078        }
079
080        /**
081         * Construct the model, establishing correspondences with the visualizer.
082         */
083        private void setup(AnimatorBuilder builder, int rows, int columns) {
084                List<Road> roads = new ArrayList<Road>();
085                Light[][] intersections = new Light[rows][columns];
086
087                // Add Lights
088                for (int i=0; i<rows; i++) {
089                        for (int j=0; j<columns; j++) {
090                                intersections[i][j] = new Light();
091                                builder.addLight(intersections[i][j], i, j);
092                                agents.add(intersections[i][j]);
093                        }
094                }
095
096                // Add Horizontal Roads
097                boolean eastToWest = false;
098                for (int i=0; i<rows; i++) {
099                        for (int j=0; j<=columns; j++) {
100                                Road l = new Road();
101                                builder.addHorizontalRoad(l, i, j, eastToWest);
102                                roads.add(l);
103                        }
104                        eastToWest = !eastToWest;
105                }
106
107                // Add Vertical Roads
108                boolean southToNorth = false;
109                for (int j=0; j<columns; j++) {
110                        for (int i=0; i<=rows; i++) {
111                                Road l = new Road();
112                                builder.addVerticalRoad(l, i, j, southToNorth);
113                                roads.add(l);
114                        }
115                        southToNorth = !southToNorth;
116                }
117
118                // Add Cars
119                for (Road l : roads) {
120                        Car car = new Car();
121                        agents.add(car);
122                        l.accept(car);
123                }
124        }
125}