Miscellaneous notes and clarifications

(We will add to this page as questions arise.)

Things that are required

Different TCAT bus routes

A TCAT bus's route is set when the agent is initialized and does not change thereafter. It must be possible for different buses to have different routes, and it must be possible to assign (at agent initialization) any rectangular circuit on the street map as a bus's route.  The rectangular circuit, being a closed path, could be described by one pair of diagonal corners, or by one designated corner and the rectangle's length and width, etc.

[Please note that the direction of motion also is a critical part of a route's definition---it must be possible for some buses to move clockwise while others move counter-clockwise.]

Generality of the directed graph

Your Map implementation must be a general-purpose directed graph data structure. The idea is that you must implement a framework that is general enough to support simulations that have more complex maps than the example given to you here.

Things that you may be asked to modify during the final demo

At the demo, we will ask you to make specific changes to one or more of the following aspects of your simulation:

Please note that simply randomizing these items is not sufficient; we will be asking for specific changes. For example, the grader might point to a tile and say ``at t = 0, there must be a TCAT bus here.''

GUI and rendering requirements

When you render the street map, please be sure to demarcate the street-segment tiles, so that the graders can easily see the boundaries of each tile. [It would suffice to simply draw a (clearly visible) border around each tile.]

Things that are not required

Simulation & modeling features that are not required

You are not required to model vehicle acceleration, velocity, mass, momentum, fuel, etc. [The speed limits mentioned in the introductory material are likewise not required.]

Agents are expected to follow the traffic rules voluntarily---you are not required to implement a ``monitor'' that prevents agents from making illegal moves.

"Under-the-hood" features that are not required

You are not required to write finely tuned, high-performance code. As long as your application is not egregiously slow, we won't be fussy about efficiency. Likewise, we won't be expecting to see ultra-smooth rendering [/ animation].

Your directed graph data structure does not need to provide methods that delete vertices and edges. Edge weights are likewise not required.  Also, if you choose to use Weiss's graph-related classes, you need not include fields (e.g., Vertex.prev and Vertex.scratch) that pertain only to certain graph algorithms.

You may assume that the directed graph is time-invariant, i.e., you may assume that the map will not change after it's initialized.

GUI features that are not required

Full animation is not mandatory and would involve a dozen or so "screen shots" per second showing intermediate vehicle positions.   However... such animation (i.e., display the t = t0 state, pause a fraction of a second, display the t = t0 + 1 state, pause, display the t = t0 + 2 state, pause, ...) really does ``bring the simulation to life,'' so we would like to encourage you to look into the possibility of supporting it in your application (but only after you've convinced yourself that the required portions of your project are rock-solid). Please see the Assorted API hints page for animation-related references and examples.  (Of course you do have to show/repaint the display with the new configuration after the specified number of internal time steps have occurred.)

Don't worry about producing a highly polished, professional-looking gui. We will be evaluating functionality, not aesthetics.

Model / view separation is strongly recommended but not mandatory.

Miscellaneous

In keeping with CS211 tradition, we will not be overly concerned with your error-checking code when we grade your demo. The emphasis will be on how your program behaves in ``normal'' situations; we will not attempt to give you ``pathological'' or surprising initial configurations.

Other notes

Symbolic constants

The best way to handle a parameter that is fixed at compile time (e.g., the number of tiles per street-segment lane) is to define a corresponding final static variable...
  class StreetSegment {
    public final static int TILES_PER_LANE = 5;

    // ...
  }
...and then, everywhere else in your code, use that variable instead of the actual numeric value (e.g., use StreetSegment.TILES_PER_LANE instead of the numeric literal 5).

Why is this a good idea? Suppose that you instead simply used the numeric literal 5 everywhere...

   // in one of the gui-related classes...
   for (int i = 0; i < 5; i ++) {
     // ...render tile i in the eastbound lane...
     }

   // elsewhere, in one of the initialization-related classes...
   for (int i = 0; i < 5; i ++) {
     // ...create tile i in the eastbound lane...
   }

   // elsewhere, in an optional extension / add-on class...
   for (int i = 0; i < 5; i ++) {
     // ...increment the congestion counter if
     //    tile i in the eastbound lane is occupied...
   }
The "magic number" 5 would thus be sprinkled throughout a large number of your source files. Now, let's consider what would happen if you subsequently decided to change the number of tiles per street-segment lane from 5 to 6... Ouch! You'd have to comb through all of those files, changing 5's into 6's. (And, even worse, what if you overlooked one of the 5's---or mistakenly "damaged" a 5 that didn't have anything to do with street segments?)

With a symbolic constant, on the other hand, life would be much easier. It would simply be a matter of making a rather obvious change to a single line...

  public final static int TILES_PER_LANE = 6;
...in the body of the StreetSegment class.

Aside: in the tiles per street-segment lane case, it would be even better to arrange things so that the number of tiles per lane on a given street segment could be set when the segment is constructed / initialized, e.g.,

  class StreetSegment {
    public final static int DEFAULT_TILES_PER_LANE = 5;

    protected final int tilesPerLane;

    public StreetSegment(int tilesPerLane)
      { this.tilesPerLane = tilesPerLane; }

    public StreetSegment()  
      // use the default...
      { this(DEFAULT_TILES_PER_LANE); }
  }
...elsewhere in the code, you'd refer to the final instance variable tilesPerLane (either directly or via a "getter" method) instead of the final class variable.  This approach would make it much easier to later allow street segments to be of different lengths, rather than all street segments referring to the same default length.