JMU
Programming Assignment 3


1 Summary

For PA2 you were hired by the (fictitious) company zmedia to develop the statemachine diagram for their zplayer. They have used your diagram to create the final model for version 1 of the zplayer and have hired you to implement their design.

2 Documents and Code

zmedia has provided you with the following statemachine diagram for version 1 of the zplayer. You must implement this version.

zmedia has also provided you with their command-line user interface library (named zui). You must use it essentially "as is" (though you may make minor modifications, for example, to change the way errors are handled).

You must not use zui to display the lines of the bookz. (Indeed, bookz_lib should probably not need to be changed at all.)

3 Additional Specifications/Constraints

In addition to conforming to the documents provided by zmedia (and all related course policies), your code must satisfy the following additional specifications/constraints.
  1. Your code must be compiled with the following options:
    -pedantic
    -pedantic-errors
    -Wall
    -std=c99
  2. When your program terminates, the state of the terminal must be identical to the state it was in before the program was executed.
  3. Though we have already started discussing concurrent processes, you must not use multiple processes. (You'll do that for the next programming assignment.)
  4. You must use the (variant of) the State Pattern discussed in the readings and lectures.

4 Allowed Deviations

If you want, you may move display_all from an effect of the go transition to an action in the Playing state. However, before you do so, you must understand the difference between the two and the implications this may have if you need to modify the zplayer in the future.

5 Submission

The .zip file you submit must be named pa3.zip.

You must not submit any data files.

6 Help/Hints

You may find the following hints helpful.

6.1 OpeningSource

You may want to "play with" the source code for OpeningSource (the example from lectures and the readings) before you start writing the code for the zplayer. It's available at:

6.2 The makefile

You will probably want to use a variable (rather than a literal) to hold the compiler options. This will both shorten your makefile and make it easier to change the options if necessary. For example:
CFLAGS = -pedantic -pedantic-errors -Wall -std=c99

cc $(CFLAGS) -c example.c -o example.o

will compile (only) the file example.c using the specified options.

6.3 Representing Events

In the readings and lectures, an enum was created to represent the events. This was to provide a layer of abstraction between the hardware and the program.

For this assignment there is no reason for this layer of abstraction (since the program will be running on the hardware it is being written for). Hence, it makes sense to use individual characters for the events.

Some of the events are described in the use case descriptions (e.g., 'b' is the "bye" event). You will (probably) also need to have events for "failure" and "success". You must use 'F' and 'S' for these events. (The use of uppercase letters will help distinguish user-generated events from system-generated events.) You may need to introduce other events as well. You should be thoughtful and consistent when doing so.

6.4 File Names

The files that represent the states should be named in the obvious way.

You may change the name statemodel to controller if you find it more intuitive.

6.5 zplayer.c

zplayer.c should contain very little code. In particular, it should be something like the following.
#include "statemodel.h"
#include "zui.h"

int 
main(void)
{
  char key;

  // Setup the controller states
  setup_states();

  // Setup the terminal
  zui_init();

  while (1)
    {
      zui_prompt("Button: ");
      key = zui_getkey();
      handle_event(key);
    }

  // Reset the terminal
  zui_reset();
  exit(0);
}

Obviously, you can't uset the code above "as is" because it never terminates. So, you will need to do something to fix that defect. You may decide that some of the above code actually needs to be moved into one or more states.

6.6 The State Model/Controller

The statemodel (or controller, if you prefer) should do the following.
  1. Define the initial state (to "On");
  2. Have a function named setup_states() (which is called by main()) that calls the "setup" function for each of the individual states.
  3. Have a handle_event() function that is passed a char (representing the event).

The handle_event() function should look something like the following (assuming there is a variable with file scope named current_state).

void
handle_event(char current_event)
{
  state* next_state = NULL;

  switch(current_event)
    {
    case 'b':
      next_state = current_state->bye_button_pressed();
      break;
    case 'g':
      next_state = current_state->go_button_pressed();
      break;
    case 'l':
      next_state = current_state->load_button_pressed();
      break;

    case 'F':
      next_state = current_state->load_failure();
      break;
    case 'S':
      next_state = current_state->load_success();
      break;
      
    default:
      next_state = NULL;
      break;
    }    

  if (next_state != NULL)
    {
      current_state = next_state; // Change states
      current_state->entry_to();  // enter the new state
    }
}

Copyright 2017