How to Build Product Simulations with Flash MX

A white e-paper by Jonathan Kaye, David Castillo, and Emily Castillo

Note: The Flash MX plug-in is required to view some of the figures. If you are having trouble seeing all the figures, click here to visit Macromedia's site to download the latest player (394Kb).

Overview
This technical paper introduces how to apply engineering best practices, such as statecharts (Harel) and the UCM architecture, to the construction of realistic device simulations. In the process of describing the methodologies, it teaches

  • Why simulation-based training is about effective training, not building a simulator
  • Four principal tasks involved in constructing a simulator
  • Basic principles of statecharts
  • Basic principles of the UCM architecture
  • How to design modular code based on statecharts and the UCM architecture
Portions of this paper have been excerpted from "Flash MX for Interactive Simulation,” by Jonathan Kaye and David Castillo, to be published in November, 2002 by Delmar Learning.

The objective of training is to shape learners into proficient or master performers, such as towards the goal of operating a device properly, negotiating a sale, coordinating a team, or performing other tasks and procedures.  Effective training involves equipping learners with foundational knowledge and operational skills relevant to all the situations in which they are expected to perform.

Most people would agree that they prefer to learn by doing, rather than reading documents or watching videos, particularly for tasks that involve using equipment.  Interactive, computerized device simulations, such as flight simulators, enable learning-by-doing when it is impractical or inconvenient to use the real device.  Device simulations can be used as part of training customers or employees to achieve competency performing tasks or procedures, helping potential customers evaluate products to buy, assisting product designers with rapid prototyping, games, and other applications.

While there is a lot of talk today in the e-learning world about the need for more interactivity and simulation, few if any tell you exactly how to build them.  Designing and programming device simulations of even moderate complexity can be quite challenging.  However, with today’s software development tools such as Flash MX, designing and programming even complex, highly-realistic simulations is not as difficult as you might imagine, provided that you have a good methodology for managing the complexity of system development.

This technical paper introduces such a methodology, based on real engineering best practices, namely statecharts (Harel, 1987) and the UCM architecture (akin to MVC and MVP).  This methodology is valuable because it not only can make your development more efficient but also can standardize the way in which you design, implement, and document your simulations. Furthermore, it is an effective way for subject matter experts, designers, and developers to work together. It ensures that if you need to extend or change the functionality of the simulator six months or more after the original work was done, your developers will understand exactly how and where to make the changes, even if they were not the original developers.

The paper is organized as follows.  It starts by examining the critical issue of why device simulation is not the same as simulation-based training.  Following this, the paper elucidates four primary tasks that allow you to manage the complexity of building a device.  Next, it teaches the basic principles of statecharts and the UCM architecture, and argues how they are applied to the tasks.  Lastly, it sketches an example application of the methodology in the design and implementation of a simple multi-modal analog/digital watch, and briefly demonstrates more advanced applications.

Simulation-Based Training is About the Training, Not About the Simulation

In terms of time and money, an inordinate emphasis on creating a realistic device simulator distracts from the real purpose and potential impact of device simulators to e-learning: performance improvement.

Several times we have met with potential clients who start the conversation by saying that they need a simulator for their device.  Our initial reaction, though admittedly a bad business practice, is to tell them that they do not need a simulator.  Our reasoning is that if the client is focused on building a device simulator, they are focused on the wrong thing.  A device simulator will only be successful as part of an effective training program, one in which from the outset has clearly identified training goals, performance objectives, and metrics by which the learner can be evaluated.

Before you put any effort into constructing a device simulator, therefore, you must

  • Articulate specific training goals
  • Identify clearly how the simulator fits into those goals
  • Write out performance objectives for each task or procedure that the learner must accomplish to attain proficiency, and
  • Describe how you will measure whether or not the learner has met the objectives.

It is critical to answer these questions first because the answers will determine how much device functionality, and to what level, you need to build. Good instructional designers can help you answer the questions.

Four Primary Tasks in Building Device Simulators

An interactive device simulator is a reproduction of the device that looks and behaves like the device under the prescribed conditions.  The simulation must therefore permit the operator to view and manipulate the device within some limits, and the device must react appropriately.

Figure 1.  Using a device in the context of a training session.

You can decompose the behavior of a device into two essential layers, illustrated in Figure 1, much the same as the real device.  One layer, the user interface layer, displays the current state of the device to the user and translates user interaction into meaningful functional changes to the device behavior. The second layer contains the actual functioning of the device, apart from the interface.  We refer to this as the model layer.

For example, in a digital wristwatch, the user interface layer is comprised of the buttons and the display, whereas the model layer contains the mechanism used to keep time.  In a software application that interfaces with a database, the user interface layer is a window to what is stored in the database, but the model layer behavior is the result of the mechanisms for storing, maintaining, and retrieving records in the database.

Figure 2.  Additional features of a simulated device.

For simulated devices, the instructor or CBT presentation needs to put the device instantly into various configurations without having to manually flip switches, buttons, etc.  Also, to explain how the device works, the presentation may want to use different “interfaces” to the same underlying functionality, such as schematics and other mental models.  Where appropriate, simulators should support these types of abstractions, as illustrated in Figure 2.

Building a robust and scaleable simulator using good design practices can be decomposed into four principal tasks:

  • Separating the interface functionality (interface layer) from the underlying device functionality (model layer)
  • Simulating user interface element functionality,
  • Coordinating the user interface elements, and
  • Simulating the model layer behaviors.

Each of these tasks will be discussed in the sections that follow.

Separating the Interface from the Underlying Device Behavior

For all but the simplest of devices, it is a wise practice to develop the functionality of user interface distinct from the underlying device behaviors.  This type of design promotes modularity and good organization.  For example, suppose you are planning to simulate the device illustrated in Figure 3.

Figure 3. Visual representation for a mock device panel.

The panel in Figure 3 represents a moderately complex user interface, within which dials, gauges, and knobs act on the underlying system and reflect the values of the system.  The panel is sufficiently complex in itself, apart from the underlying device functionality.  Imagine now that this panel is one of 15 software screens available on the device!

The behavior of the interface involves taking in user input (switch changes, button presses, joystick and knob movements, etc.), reading the underlying behavior of the device, and displaying ongoing results, such as through the dials, lamps, and gauges.  The behavior of the device, however, is different.  Its behavior is a result of the current settings, parameters, and conditions.  Therefore, to make the task of building the simulator more manageable, you should isolate the development of each, and then provide a mechanism, such as the UCM architecture, by which the levels communicate relevant information.

Simulating User Interface Element Functionality

A user interface element on a device is a button, dial, knob, joystick, gauge, slider, etc.  For software applications, you may have listboxes, scrolling panes, data grids, radio buttons, among others.  Simulating these elements is usually straightforward, though obviously it depends on the complexity of the element.

Since most elements you find in interfaces are used more than once, at least if not on the same device then on similar devices in the product line, it makes sense to create Flash MX components for these elements.  You can find source code for many components on web sites such as the Macromedia Exchange, flashcomponents.net, and others.  Figure 4 shows several elements common to engineered devices. These elements are described in our forthcoming book.

Figure 4. Sample device interface elements. To examine the elements in more detail, right-click on the figure and use Flash's zoom feature to inspect the desired elements. You can purchase these by buying our book or by clicking here

Creating the user interface elements for a particular device, in an ideal world, would be pulling out elements of the right type from a component library and customizing the visuals to match your device.  Flash MX components can make this a reality.

If you have to develop your own interface elements for a device, focus on creating the behavior of that element, without bundling in the effect of the element on the specific device.  Make the element announce, via a listener or other notification mechanism, when there has been a meaningful interaction with the element (for more information about listeners, see the Further Information section).  This modular approach results in an easy to understand design for your code.

For example, if you need to develop a power button, you would build the functionality for button press (and possibly release), as well as a notification mechanism, such as listeners, to tell other routines about these events when they occur.

Coordinating User Interface Elements

The panel in Figure 3 represents a moderately complex user interface.  One way of approaching its design and construction would be to program the device behavior into the individual buttons and knobs directly.  For example, you might have the following code for the power button:

on (release) {
      if (devicePower) turnOnDevice();
      else turnOffDevice();
      devicePower = !devicePower;
}

In this example, the event handler looks at the global system power variable devicePower, instructs the system to power up or shut down, and sets the global variable. Now assume that the power can also be turned on or off by the user plugging in or unplugging the power cord. In the event handler for the power cord plug/unplug action, you would need to manipulate the devicePower variable as well. The devicePower variable might be accessed and manipulated in many other event handlers, making it difficult to know in a specific context which elements are involved and how they are coordinated.

This approach requires that each event handler figures out the context in which an event occurs, to execute the appropriate actions.  It distributes the access and manipulation of system information across the event handlers of the interface.  Because this practice distributes the code that makes the interface work together, it is difficult even with a moderately complex interface to understand and verify the coordination, not to mention extend or modify the interface behavior.

Imagine now that the illumination of a display depends on the switch configurations.  Furthermore, this situation (context) is only relevant when the device is on.  Rather than program that dependency and power condition within the switch handlers, it makes more sense to develop a centralized coordinator that accepts switch changes, inspects the configuration and current context, and tells the display whether or not to illuminate.

Such a better practice in terms of scalability is to concentrate the handling of events within each possible context, and therefore the coordination.  This desirable practice would

  • Control access to the system information in a centralized way
  • Make it easier to program and inspect how the interface is coordinated in each context.

The combination of UCM and statecharts solves both of these issues.

Simulating the Underlying Device Functionality

Once you have separated the simulation of the interface from that of the device, you have begun to make the problem easier.  That is because understanding how devices behave and how to model their function is usually well understood in engineering.  You should be able decompose the device into its mechanical, electrical, chemical, and other types of processes that produce its behavior, and create models (or apply models from the literature) to capture that behavior based on the input conditions and settings.

The models you use should fit the level of detail you need to simulate.  Therefore, for most purposes outside of research applications, you can create simplified forms of complex processes, but sufficient to produce realistic behaviors in the scenarios and under the conditions required.  You do not win any extra points for implementing complex models if the precision is not necessary for the device to allow the learner to meet the performance objectives.

Simulator vendors like to laud that their simulators use “mathematical models.”  They imply that it has a more precise and realistic result.  However, it is almost a meaningless term as far as knowing how well the simulator performs, since the precision is only warranted if the simulator uses the correct model and the correct mathematical expressions, and if the process is amenable to that level of detail.  Furthermore, such complexity (and its associated cost!) may be completely unnecessary for the tasks you need your learners to complete.  Remember, simulation-based training is about improving performance, not about the simulator!

A Framework for Solving the Four Tasks

The methodology we have implemented in Flash MX to address the four tasks combines two well-known engineering methodologies, statecharts and the UCM architecture. This section introduces the methodology using simple examples.

Statecharts

At the heart of building a simulator is conceptualizing, designing, and programming processes that produce behavior.  User interface behaviors consist of processes such as accepting user input, displaying the device configuration, managing software interface pages, and so on. Model layer behaviors consist of processes related to the underlying function of the device. Whether you are simulating the interface layer or the model layer, you have to know which processes should be currently active.  You can do this by

  • Defining a list of “states” of the device in which processes occur, and
  • Keeping track of the current state.

For example, suppose you are working on a device, such as in Figure 3, with which you need to demonstrate the following. When it’s off, the displays are turned off. If the device is off and plugged in, it is recharging its internal battery, otherwise it is not.  When the device is on, it goes through a power ramp-up period, and then at full power its displays are illuminated and it begins to perform calculations on input signals.  A second example of 'different behaviors in different states' is when the device is off, turning a knob has no effect.  When it’s on and at full power, turning a knob has the effect of changing a parameter that affects the computations.

One way of thinking about the processes in this device is to first partition behaviors into an OFF and an ON state, and then to partition each of those states into substates that reflect contexts in which different processes occur.  Figure 5 shows a diagrammatic representation of these partitions.

Figure 5. Representation for processes occurring in the off and on states.

In Figure 5, each context (state) is represented as a rounded square, and arrows (“transitions”) between the states signify how it is possible to switch from one context to the next. For example, the transition from OFF to ON occurs when the power event happens.  The black dots with arrows tell which substate should be activated first by default when the parent state becomes active. When a state with substate network is activated, the state tracking mechanism activates the default substate.

Figure 5 is a simple statechart for diagramming a high-level view of the possible states of the device. Statecharts are a visual notation and formal design methodology developed by David Harel in the 1980's, for developing airplane simulators for the Israel Aircraft Industry (see Further Information). Statecharts are extensions of finite state automata, and sometimes referred to as "hierarchical state machines." Statecharts were adopted recently into the Unified Modeling Language (UML).

To design and program the system processes, you attach actions that simulate those processes to the states (contexts) in which the processes occur. For example, you can specify that certain actions are executed when a state becomes active (enter actions), when a state is deactivated (leave actions), or while a state is active (an activity). In this example, suppose you attach an enter action to the FULL POWER state that says "turn the FULL POWER light on," and you attach a leave action that says "turn the FULL POWER light off." When the device finishes its power ramp-up and enters the FULL POWER state, the enter actions are executed. When the FULL POWER state is deactivated, the leave actions are executed.

If you have actions that occur regardless of the particular substate, such as a main power light being on, you can attach those actions to the parent state (ON) and they will execute regardless of which substate is active. Unlike finite state machines, in which only one state can be active at once, statecharts may have several active states. The states also serve to tell you what events are significant or not, such as when knob turning has an effect on the system.

During the course of the simulation, user manipulation or the device control logic itself will trigger transitions that change the currently-active state. In Figure 5, the transition from OFF to ON would be triggered by the user pressing the power button (an event). If the device is ON and runs out of power, the device itself may trigger the power transition (generate an event) and transition into the OFF state. In addition to laying out the possible states, you write out under what conditions transitions occur. This is known as writing an "event-action table." To determine when a state transitions should occur, the event handler evaluates conditions for each transition from the current state, and fires the transition when those conditions have been met. You will notice in Figure 5 that the transition from ON to OFF is attached to the ON state, not its substates. This tells the event handler to fire the transition when it receives the power event, regardless of which substate is currently active. It is an example of what is called "interrupt-driven behavior," certain events or conditions that cause context changes regardless of particular active subcontexts.

Transitions in this statechart only link sibling states, but transitions can link from a substate to a parent sibling state, or traverse arbitrary levels. The statechart processor, which is part of what we call a "state engine," is responsible to ensure that states are deactivated and activated in the order you would expect, and therefore any actions attached to those states are executed in the correct order.

Statecharts provide a graphical notation for describing the actions, activities, and transitions that occur during the course of a simulation. From this description, one implements the structure of simulation in a cookie-cutter fashion. The subject-matter expert, who does not have to know ActionScript or programming, can design the simulator by drawing the statecharts and writing out the event-action tables. These designs are not only the basis for writing the code, but also excellent documentation and validation instruments.

Because the actions, activities, and transitions are concentrated at the place in which they should occur, you have organized the simulator using this methodology such that you know where to look if you need to extend or modify its behavior. Furthermore, the processing is centralized to the current context so that you don't have to worry about how changing the code or behavior in one context will affect the behavior in another context.

To summarize, statecharts give you a mechanism to keep track of the current state and to activate the processes and conditions appropriate for that state. We have presented a brief introduction to basic elements of statecharts, and our Further Information section points to more detail, for the interested reader. Statecharts can be used to address tasks 2 and 4 (modeling the user interface and model layers), and serve as a foundational tool for addressing task 3 (the coordination of the interface elements).

The UCM Architecture

As discussed in the enumeration of tasks, it is good design practice to coordinate the user interface elements and centralize their access to the underlying system information. The UCM architecture, explained by Horrocks (1999) and sketched in Figure 6, supports this type of abstraction. UCM stands for “User Interface – Control Object – Model”, which describes a three-tiered system for conceptualizing the way a software program or device can be decomposed.  UCM is similar in function to other frameworks such as Model-View-Controller (MVC).  The three “layers” are:

  • User interface: A layer for user interface elements (buttons, dials, gauges, and so on).
  • Control object: A layer containing the control object (or, in advanced applications, more than one), which is a mechanism that coordinates the interface elements and mediates the interface and the device’s internal functionality.
  • Model: A layer containing the processes and computations involved in the internal function of the device. The model layer is not concerned with how the device’s behavior is presented to the user, because that is the responsibility of the interface.
Figure 6. Interactive example of UCM architecture. Click on the leftmost button to illustrate communication for power on and power off. During power on, turn the knob to see the simulated communication among levels and the setting of the gauges and display. Notice that the dial (far right) does not reflect the immediate value because it is simulated to change at a specified rate. Though exaggerated for instructional purposes, it is an example of incorporating realistic instrument behavior, if appropriate..

The control object is responsible for coordinating the interface elements and is the central access point for querying or requesting changes to system information.

In Figure 6, press the toggle button on the left to “turn on” the device.  The control object listens to the events of the interface elements, and when it hears that the power button has been pressed, it notifies the model layer to turn the device on. While ON, knob changes are passed to the control object, and then to the underlying system, to effect the parameter change, presumably. At the same time, the gauge and dials request data to display. The control object queries the model layer to satisfy the request. Notice that when it believes that the device is off, the control object knows not to inform the model layer about knob changes or gauge or dial updates, since the device is off.

To accomplish its purpose, the control object has to know what “state” (behavior context) that device interface is in, so that it can make appropriate decisions for handling user interface events and displaying system information. That is where statecharts come in.

The State Engine Data Structure

We have developed a data structure in Flash MX we call a state engine, that implements the runtime behavior of statecharts and incorporates event handling following UCM principles. The state engine can be used as a framework to model any type of process flow behavior that can be conceptualized in terms of processes occurring within a collection of discrete states. While we use it to model the processes in devices at both the interface and model layers, it could easily be applied to branching logic or other types of decision simulations.

Figure 7. Interactive example of UCM architecture and statecharts. Turn the device on with the button second from the left. Use the toggle switch while the device is on to change interface states.

Figure 7 gives example statecharts that simulate the behaviors of the interface and the model layers. By default, the device is on and both the control object state engine and the model layer state engine are in their ON states. The leftmost switch is intended to have an effect on the interface, but not the underlying model, such as changing the current software display screen. Therefore, the control object does not need to notify the model layer when the switch is manipulated.

While the device is on, you can change the knob and it will change the underlying system value, as reflected in the gauge and digitial display. Turn off the device and you will see that the control object tells its state engine to move into the OFF state, and also sends a message to the model layer telling it to power down. It should be clear how it would be easy to simulate instrument and system faults using this methodology; the control object or model layer object would simply have to mangle or cut off the messages being exchanged.

Coding the Examples

Figure 8. Representation for processes occurring in the off and on states.

To give you a sense for how the data structure is applied, consider Figure 8, which is the same as Figure 5. The following ActionScript creates the states and transitions for this statechart.

//states
sOFF = new hstate("OFF", 0, devMgr);
sOFF_mgr = new state_mgr("A", "OFF MGR", 10, sOFF);
sOFF_plugged = new state("PLUGGED", 10, sOFF);
sOFF_notPlugged = new state("NOT PLUGGED", 11, sOFF);
sON = new hstate("ON", 1, devMgr);
sON_mgr = new state_mgr("B", "ON MGR", 0, sON);
sON_ramp = new state("RAMP UP", 0, sON);
sON_full = new state("FULL POWER", 1, sON);

// transitions
sOFF.add_trans(0, new trans (null, 1));
sOFF_plugged.add_trans(0, new trans(null, 11));
sOFF_notPlugged.add_trans(0, new trans(null, 10));

sON.add_trans(0, new trans(null, 0));
sON_ramp.add_trans(0, new trans(null, 1));
sON_full.add_trans(0, new trans(null, 0));

You can see the direct relationship between the statechart and the resulting ActionScript. In this code, hstate is a constructor to create hierarchical states, and state is the constructor for non-hierarchical states. Each hierarchical state requires a state_mgr, a special runtime data structure that keeps track of the currently active state. The event handler is structured as follows.

stEng.eventHandler = function (ev) {
      if (sOFF.isActive()) {
            if (msg == "power") {
                  sOFF.change_state(0); // follow transition 0 from state sOFF
            }
      } else if (sOFF_plugged.isActive()) {
            // event handling for events received while the interface is OFF
...

You code the event handler such that all the event handling relevant to a state is concentrated in a single place. This makes it easy to know where to modify or extend device behavior, and prevents interference between the same or similar events that occur in different contexts (states).

Analog/Digital Watch Example

The methodology we have introduced is a powerful architecture for building scaleable and robust product simulations. The examples so far have been very simple for the purpose of explaining basic concepts.

A more complex example is the multi-modal analog/digital watch, shown in Figure 9. For instructional purposes, we have included a representation of the statechart for the control object (interface) layer, so that you can follow the progress of the watch as you put it through the possible modes.

Figure 9. Interactive example of a multi-modal analog/digital watch designed and programmed with UCM and statecharts. Use the top right button to change modes, and the bottom right button, held for 1 second, to go into the "setting" states.

This watch has four modes: time, date, alternate time, and stopwatch. The top right button transitions among the modes, and the bottom right button, when held for more than one second, transitions into the "setting" substates, for time, date, and alternate time. In the setting substates, the upper right button increases the particular value being set, and the bottom right button advances to the next unit to set. Notice, therefore, that the same button action has two completely different effects on the device, depending on which states are active.

The model layer simply keeps track of the time, date, and stopwatch value, independent of which is being displayed currently. Therefore, the model layer could be thought of as remaining in a single "state". You wouldn't need the statechart methodology to implement this. The control object (handling the user interface level), however, has to display the appropriate values that it requests from the model layer depending on which mode the user selects and which buttons the user pushes. Therefore, the state engine is very handy.

Note: The H enclosed in a circle, in the stopwatch mode, is a special state that sends the statechart into the last state (of its parent) visited, or the default start state if this is the first time entering the parent state. In this way, if you start the stopwatch, which transitions the watch from STOP to RUN, and then advance the modes to return to the stopwatch, you will see that the watch remains in the RUN state.

Some of the behaviors, namely the updating of the time, date, and stopwatch displays, are not shown in the statechart of Figure 9. We define a pulse activity, which is a set of actions executed at a certain frequency (every second, in this case), in the outermost, blue state, to update the watch hands. Therefore, every second, regardless of the active substates, the watch executes a function that sets the position of the hour, minute, and second hand. In a similar way, each mode substate defines a pulse activity to update the digital display with the proper current value. The routines don't interfere with one another because only one of the modes is active at any particular time.

Advanced Application

When you have a simple device to program, you may find that the methodologies sketched here, particularly using our implementation, may be overkill. However, the design principles, namely laying out the behaviors in terms of states and transitions, and writing event-action tables, are very worthwhile to apply regardless of how you implement the final product.

Figure 10. The Newport HT50 Ventilator, Courtesy of Newport Medical Instruments. Click SIMULATOR to see the simulator in isolation, or PRESENTATION to see the simulator used within a marketing presentation.

The purpose of the methodology presented is to give you a standardized, scaleable, and robust way to develop simulators of virtually any scale. From a management point of view, it is a standardized way that allows programming teams and future members of the team to understand and evolve the simulator, which is particularly important on large-scale products and products that are expected to change through their life cycle. While simple devices are usually simple to simulate, simulating moderate to complex devices gets complicated very quickly. Using the methodology we outline gives subject-matter experts, designers, and developers a common vocabulary and tool for working effectively together.

Lest you think that the methodology is only for simple devices, we present an example of a medical ventilator, the HT50 Ventilator (Figure 10). This device was built with the statechart methodology in Flash 5, and has over 150 states, with its deepest hierarchy 8 levels deep. We are currently working on devices with more than twice that number, and, so far as we can tell, we are nowhere near any limitation of either Flash or the state engine implementation. Remember, though, that higher device complexity does not necessarily make a better simulation-based training experience.

Figure 11. A sample training presentation that teaches how to set and add numbers with an abacus. After assessing the student's ability to set numbers properly, it shifts into practice mode, which involves a game to build fluency using the abacus.

Important: This example will not work properly without the online speech generation plug-in from www.speaksforitself.com

As we mentioned in discussing the state engine data structure, it can be used for applications in addition to product simulation. We have used it to build an example training application for an abacus, given in Figure 11. This type of training is great for building fluency with device operation. Both the abacus and a general-purpose "tutorial engine" are implemented using the state engine. This example is explained in detail in our upcoming book.

 

Conclusion

This paper has introduced a scaleable and robust engineering methodology, combining statecharts and the UCM architecture, to help you think about how to design and develop device simulations, though the principles are applicable to other forms of simulation as well.  The methodology helps you to conceptualize and compartmentalize the possible behaviors of a device, and how to logically segment the modeling of the interface from the underlying device functionality.  We invite you to learn more by consulting our Further Information, below, and our web site, www.FlashSim.com, as well as discussing there emerging simulation technologies and their application.

Over the next few years, we are certain to witness an explosion in the creation and use of device simulations for training, product evaluation, product design, and many more applications.  In spite of this paper being about how to build a device simulator, we strongly emphasize focusing on the instruction before considering simulator construction.  Successful applications—those that demonstrate successful performance improvement outcomes—will be those that have harnessed simulator-development technology as part of solidly-designed training programs, not merely applications that demonstrate one can build realistic-looking device simulators.

Further Information

Ian Horrocks’ excellent book, Constructing the User Interface with Statecharts, published in 1999 by Addison-Wesley, is a comprehensive introduction and review of the statechart notation and UCM architecture. You may also be interested in reading David Harel’s original paper on statecharts, which was published in the journal Science of Computer Programming 8 (1987), pp. 231-274. As of this writing, this seminal paper was available electronically from David Harel’s web site, http://www.wisdom.weizmann.ac.il/~harel. More information about statecharts and UML can be found at http://www.uml.org.

You can find more examples, code, and information about our upcoming book, Flash MX for Interactive Simulation, at the book's web site, www.FlashSim.com. FlashSim is also a repository for online resources, books, and discussion centered on simulation in Flash.

For information and tutorials about listeners, we recommend visiting the tutorials area of flashcomponents.net, as well as reading Flash's documentation on its new event model. Unfortunately, the listener mechanism programmed into Flash MX and the change handler mechanism programmed into the FUI Components are limited with respect to the requirements for UCM. However, implementing a sufficient mechanism that allows multiple listeners and informs the listener with event messages is not hard to implement. Consult FlashSim.com for discussion about this.

Contact and Questions

The authors are always interested in hearing about interesting problems or applications in simulation-based training. If you'd like to discuss this article or related topics, we invite you to participate in our discussion boards, or you can email us at jmk@FlashSim.com (Jonathan), david@FlashSim.com (David), and emily@FlashSim.com (Emily).