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}