Extending SpeckSim

Extending SpeckSim

Almost every aspect of SpeckSim can be changed and extended, this section will detail what can be changed, how to do it, and highlight the points to watch out for.

Extension classes can be loaded into SpeckSim with the "-l" cammand line option, like so:

java -jar -Djava.library.path= SpeckSim.jar -l foo.bar.MySpeckClass,foo.bar.MyMovementModel

The list of classes to be loaded must be comma-separated.

SpeckSim overview

Before the specifics of extending are explained, you'll need a brief overview of how SpeckSim works. This is a very rough diagram of how the different parts of the simulator fit together



The SpeckSim main class maintains a queue of events that are executed in order. These events are usually placed in the queue by the specks resident in the simulator, but there is no firm restriction to this effect. At some point, an event is executed that causes the current state of the simulator to be copied into the a SimulatorState object. Statistics are calculated from the updated state object and the GUI is updated.
The important thing to take from all this is how important the state object is. StatisticGatherers and StateRenderers operate only on the state, and so all needed data must be present.
At any rate, javadoc for the entire system can be found .

Adding new Speck behaviours

The is very bare, in order to permit a wide array of implementations. Things are made a bit easier by extending the , but by far the easiest way to add a custom speck behaviour is to take an existing one and make whatever changes are necessary.
The most suitable candidate for this treatment is the . This speck implementation has very simple behaviour - it periodically broadcasts it's own ID number while maintaining a list of other IDs that it has received recently - but still demonstrates all the important points of speck behaviour:

The is extensively commented, so any explanation here will probably be duplication. For an explanation of the annotations applied to some of the fields, head on over to the Configuration section.

Once you have your Speck implementation ready, it can be added into SpeckSim simply by specifying the full class name on the command-line as described above. Alternatively, it can be loaded programatically with a static call to SpeckFactory.register( class name );

Customising Speck communications

Specks communicate by means of that define the limits of their broadcasts. Again, the minimum interface is very sparse, so there's not much to discuss.

You can see a simple example of a MessageShell in the .
You can test your custom MessageShells using the ShellTest application that's also included in the SpeckSim jar. Run it with:

java -Djava.library.path= SpeckSim.jar -st -l foo.bar.MyMessageShell

where foo.bar.MyMessageShell is the name of your new implementation (Which is also on the classpath).
Custom MessageShells will be referenced by a Speck implementation (Remember, unless you're sure about what you're doing, it should be a static reference) and so no special call is needed to include them in SpeckSim.

Specifying Speck movement

The position and motion of all specks are dictated by the . As ever, examples are roughly three thousand times more effective at explaining things than a load of text, so without further ado:

Movement models also have the opportunity to produce some data to be placed in the object. In this way you can provide the data needed to visualise your fluid flow field or whatever you've cooked up. On the other hand, you can always just pass null if you don't want to bother.

As with Speck implementations, simply specify the class name on the command line or call MovementModelManager.register( class name ) to include your model in SpeckSim.

Calculating statistics

Calculating new statistics is simply a matter of implementing the interface. The only thing to watch out for here is to make sure that the indices of the statistics returned match up with the indices of the name array. See for a simple example.
Once again, add your StatisticsModules into specksim either by adding the class name to the command line, or calling StatisticsGatherer.register( class name ).

A well behaved StatisticsModule will take account of the will of any StateFilters (see below) by calling isIncluded( int index ). Note that this method belongs to the StatisticsModule abstract superclass, and is distinct from SimulatorState.isIncluded( int index ). This allows SpeckSim to automatically generate both filtered and unfiltered statistics automatically.

Visualising new behaviour

Statistics are all well and good, but visualising data is far more compelling. The basic interface for visualising is the , but I suggest you instead extend . This will handle some of the fine details of maintaining a display list and so on.

Remember to check if a particular speck's details should be rendered with a call to state.isIncluded( int index ).
As ever, a simple example is the .
StateRenderers are added to SpeckSim by, you've guessed it, adding the class name to the command line or by calling SpeckVisualiser.loadRenderer( classname ).

Avoiding duplication of processing

Now that you've implemented your own statistics and visualisations, you might have noticed that you're duplicating some processing work. This, clearly, is a waste of resources, and you wish there was some way to do the processing once and then access the results in both StatisticModules and StateVisualisers.
Rejoice! Implement the processing in a , and the results will be made available for statistics and visualisation.
Continuing on with the Neighbourly examples, see .
The only thing to watch out for when implementing a StateProcessor is to make sure that you call processState() whenever the results are requested. You should not worry about calling processState() too many times, the processing will only occur once for every time the SimulatorState object is changed.

Once again, implementors should be sure to check is a particular speck should be processed with a call to state.isIncluded( int index ).

Add a StateProcessor to SpeckSim by specifying the class name on the command line or by calling SimulatorState.register( classname ).

Interacting with the visualisation

Whilst the configuration system is handy for making sweeping changes to all specks, it is sometime useful to be able to make changes to individual specks. This can be achieved by using a . These allow you to attach some code that is alerted whenever the selection of the visualisation changes
See for an example.
Like the StateRenderers, GLSelectionListeners are added to SpeckSim by specifying their classname on the command line or by calling SpeckVisualiser.loadSelectionListener( classname ).

Filtering the state

By default, all modules that consume the state (Statistic gathereres, visualisers, state processors) will operate on all available data. It is sometimes desirable to process some subset of the state objects. For instance, you might want to gather statistics on only those specks within a certain quadrant of the field, or only the state from a particular flavour of speck.
This can be achieved by using s. These customisable modules make a decision on some aspect of the state object, and well-behaved state consuming modules will honour this decision. All that is required for the state consuming modules to take account of the wishes of the StateFilters is to check whether or not to process a given state element with a call to .
Examples may be found in the , which filters based on the type of speck, and the , which filters based on the leader id of specks.
StateFilters are added to the simulator with a call to , or by specifying the classname on the command line.