In the example above, the act of clicking the step button would cause the simulation to move forward 3 time steps---the updated display, after the click was processed, would show the state of the simulation at time t = 5.![]()
(The brightly colored rectangles on the street segment tiles are the vehicles, and the label in the lower, left-hand corner shows the current time. The large, predominately white rectangle, on which the ``birds-eye view'' of the simulation is drawn, is a JPanel---this component is referred to as the ``map view panel'' below.)
[When n is greater than 1, the intervening time steps t0 + 1, t0 + 2, ..., t0 + (n - 1) are computed but not displayed.]
[Clarification: the gui that you implement does not need to exactly match the one depicted above. Please feel free to lay things out differently, or use triangles instead of rectangles to represent the vehicles, etc. Also, you're encouraged to extend the scope of the user interface; for a few suggestions, please see the add-ons page.]
* the ``action performed'' method in the ActionListener that's attached to the button... * converts the text in the text field into an int n, * and then passes n to the Controller's ``take n steps'' method the Controller's ``take n steps'' method... calls the Controller's ``take one step'' method n times... each time the Controller's ``take one step'' method is called, it... iterates through the list of agents, in arbitrary order, calling the ``take one step'' method of each agent, in turn each time an agent's ``take one step'' method is called, the agent... ``looks'' at its surroundings, by querying the Environment, decides what its next move should be, and updates its own state (including its position) accordingly note: in most implementations, an agent, when it moves, must... update its own internal location-related fields (e.g., update the pointer that it maintains to the node (in the map graph) that it's sitting on) as well as inform the Environment of its new position after each agent has taken its turn, the Controller's ``take one step'' method increments the Environment's time field. after the Controller's ``take one step'' method has been called n times, the Environment's time field reads t0 + n, where t0 is the value that that field held before the ``take n steps'' method was called, and the simulation has accordingly been advanced forward n time steps; thus, the ``model'' side of the simulation is now in the desired t = t0 + n state * [now it's just a matter of synchronizing the ``view'' side---i.e., the display---with * the model] * * the ``action performed'' method in the ActionListener, after the Controller's * ``take n steps'' method has returned... * updates the string in the gui's time-display label * (after querying the Environment for the current time) * and then asks the map view panel to repaint itself * (this will cause the map view panel's ``paint yourself now'' method to * eventually be called) * * the map view panel's ``paint yourself now'' method... * redraws the entire ``birds-eye-view'' of the traffic simulation, * thus causing the newly computed state of the system to be displayed[We've assumed round-robin updates in the above.]
The starred lines above require a certain degree of familiarity with gui programming in java; it's recommended that you initially concentrate on the unstarred lines.
You can also interpret ``starred line'' as ``the view side of the application'' and ``unstarred line'' as ``the model side of the application.'' In the long run, life is much easier when you keep the two sides of the application segregated---when you keep gui-related code out of the implementations of the Environment, the agents, the graph, etc.
[The idea is that the gui itself remembers nothing at all about the state of the simulation---everything it needs to know about the locations of vehicles, etc. it gets by querying the Environment. Likewise, the Environment should be completely ignorant of the gui. This loose coupling of the two aspects of the application is really the fundamental benefit of imposing a model / view separation.]
[For more information on the model / view approach, please see this short JavaWorld article. Caveat: the ``controllers'' referred to in that article are not analogous to the simulation Controller that's needed in our project.]
As mentioned before, GUI will be covered in lecture and/or section. For additional hints, pointers to relevant documentation, etc., please see the API hints page.
You don't have to exactly follow the architecture outlined above. In fact, a sophisticated implementation would almost certainly differ in several aspects, e.g., it would probably use a loosely coupled, event-driven approach (à la Observer / Observable) to triggering gui refreshes.
Model / view separation is strongly recommended but not mandatory.