General Information
- The due date is Thursday 17 December 2020, before 23:55.
- Submissions must be done via BlackBoard.
Beware that BlackBoard's clock may differ slightly from yours.
All results must be uploaded to BlackBoard, including a report that details your solution.
- The assignment must be made in groups of maximum 2 people.
It is understood that all partners will understand the complete
assignment (and will be able to answer questions about it).
Clearly identify who did what.
- Grading will be done based on correctness and completeness
of the solution. Do not forget to document your requirements,
assumptions, design, implementation and modelling and
simulation results in detail!
- Contact Joeri Exelmans if you have any questions or problems.
Goals
This assignment will make you familiar with Statechart modelling, simulation, and code synthesis (and a bit of testing).
Problem statement
In a factory, employees work in shifts. For beginning employees, these shifts change ever so often, making sure they stay motivated for their work.
In this assignment, you will design a Statechart model specifying the reactive behaviour of a simplified dashboard that manages beginning employees. This is also known as "operator assistance".
Note that incremental development is good practice: start modelling and trying out (after simulation and subsequently, code synthesis)
small parts of the desired behaviour (satisfying only some of the requirements) in isolation. These can be saved and loaded later to incremental
build the full solution Statechart.
The model and its visual representation must both be discussed and included in your report.
The application's reactive behaviour (Python code) will be synthesized from the Statechart.
(Behaviour) Requirements
- In the following, seconds are used as time units. This "scaling" is done to make it easier for you to test the application (in "real time").
- The employee can be at home or at work. Initially, the employee is at home. When at home, the employee can go to work.
- While at work, the GUI shows 3 buttons, one for every shift type.
The shift types are: Unloading, Assembly and Loading. While at home, these buttons are hidden.
- When arriving at work or after every completed shift, the employee is assigned a random shift type.
An assigned shift is visible as the corresponding button being highlighted in blue.
- Before the assigned shift starts, the employee has a 4 second grace period, during which two actions may be taken:
- Optionally select a different shift type, by clicking the corresponding button. The clicked button should then become the one highlighted in blue.
- Alternatively, during this grace period, the employee can decide to 'call it a day', and go home.
After going home, and before going to work again, we assume a good night's sleep, modeled by increasing the employee's energy by 50%. Obviously, the energy can never exceed 100%.
- When the grace period is over, the shift starts.
The assigned or chosen shift (i.e. button that was highlighted blue), now turns to green,
indicating that this is the shift the employee is currently working.
- A shift takes 10 seconds. There is no way for an employee to manually end a shift sooner or later than the 10-second duration. For every completed shift, the employee receives 10 units of pay.
- While working a shift, the employee is able to perform actions specific to that shift. During the shift, the actions should be visible as buttons at the bottom of the UI window.
The buttons should disappear again when the shift is over. To perform an action, the user should press and hold that action's button for at least 500 ms with the mouse.
- For the different shift types, the actions are as follows:
- Unloading: 'Walk', 'Pickup', 'Drop' and 'Toilet Break'
- The employee can be at the stock (warehouse) or at the truck. The action 'Walk' moves the employee from the one to the other.
- The employee can be carrying nothing, or can be carrying 1 unit of material. When at the truck, the action 'Pickup' picks up 1 unit of material.
When at the stock, the action 'Drop' drops the material, and adds 1 unit of material to the stock. The action 'Pickup' has no effect if the employee is already carrying material,
or when at the stock. Likewise, the action 'Drop' has no effect when at the truck, or when not carrying anything.
- At the start of the shift, the employee is located at the stock and is not carrying anything. To correctly unload 1 unit of material, the employee should perform the actions
'Walk', 'Pickup', 'Walk', 'Drop'. At any time, the employee may walk back and forth without purpose: E.g. the sequence of actions 'Walk', 'Pickup', 'Walk', 'Walk', 'Walk', 'Drop' also
unloads 1 item of material.
- To help you, we offer the following state machine, implementing most of "Unloading":
You will probably want to embed these states and transitions at some level in your state hierarchy. Note that you may still have to add actions to some of the transitions, and that it does not yet implement the 'Toilet break' action.
- The 'Toilet Break' action is only allowed (i.e., only has effect) when the employee is at the stock and not carrying anything. More on this topic below.
- Loading: Just like Unloading, but instead the 'Pickup' action should be performed at the stock (picking up finished product) and the 'Drop' action should be performed at the truck.
- Assembly: only a single action; 'Assemble'. This action causes 1 unit of material to be converted to one unit of finished product.
- When performing the 'Toilet Break' action (in Unloading or Loading), the set of actions should change to only a single action called 'Done', which ends the toilet break and resumes the
Loading or Unloading shift. Toilet breaks do not extend the duration of the shift. For simplicity, when a shift ends while the employee is having a toilet break, the toilet break also ends
automatically, simultaneously.
- While working a shift, the employee's energy drops with 2% per second, except while on a toilet break.
- A new shift cannot start if the employee's energy is below 25%. The employee can then only go home.
- Through the API (see below), you have the possibility to show status messages in the UI. This will make it clear what is going on. You can display multiple status message simultaneously by
showing multiple lines of text (see API). Decide for yourself what info you show on which line. You should indicate:
- Whether the employee is at home or at work
- While at work, whether the employee should select a shift type, has too low energy to work a shift, or is working a shift
- When working a load/unload shift, whether the employee is:
- at the stock or at the truck;
- carrying the material, the finished product or nothing at all.
- You are of course allowed to show even more info text, but this is not required.
- You are encouraged (but not required!) to use SCTUnit to test some of the above requirements by building a testing harnass.
This may help you spot errors (and regressions) quickly, especially as your model grows in size.
An often-used methodology is to "test-driven development", where you write a test for some of the functionality up front,
and then try to implement it in your statechart, see if the tests pass, and iterate.
Hint: to model the "press a button for x time to complete an action", you can add an orthogonal component that checks the pressed duration. The component then translates this to the correct
internal event.
Interface (API)
interface util
operation getRandomInteger(smallerThan: integer): integer
- Generate an integer larger or equal to 0 and smaller than given number.
interface employee
in event goToWork
- Received when the "Go to Work" button is clicked.
in event goHome
- Received when the "Go Home" button is clicked.
in event shiftClicked: integer
- Received when one of the shift buttons is clicked. The event parameter is an integer: 0 for "Loading", 1 for "Assembly", 2 for "Unloading.
operation getEnergy(): integer
- Returns the energy of the employee, as shown in UI.
operation increaseEnergy(delta: integer)
- Increases the energy of the employee. Use a negative delta to decrease.
operation getPay(): integer
- Returns the employee's amount of money, as shown in UI.
operation increasePay(delta: integer)
- Increases the employee's amount of money. Use a negative delta to decrease.
interface factory
operation getMaterial(): integer
- Returns stock count, units of material, as shown in UI.
operation increaseMaterial(delta: integer)
- Increase stock count, units of material. Use a negative delta to decrease.
operation getFinished(): integer
- Returns stock count, units of finished product, as shown in UI.
operation increaseFinished(delta: integer)
- Increase stock count, units of finished product. Use a negative delta to decrease.
interface ui
operation setActions(actions: string)
- Sets the list of actions to display as buttons. The 'actions' parameter is a comma-separated list of the action names, e.g. "Walk,Drop,Toilet break" will create 3 buttons. Use the empty string to hide all buttons.
in event actionPressed: string
- Raised when user presses an action with the left mouse button. The event parameter is the name of the action, e.g. "Walk".
in event actionReleased: string
- Raised when user releases an action with the left mouse button. The event parameter is the name of the action, e.g. "Walk".
operation setMsg(msg: string)
- Sets the message to be displayed at the current line. The line can be 0 to 5. Initially, the current line is 0.
operation pushMsg()
- Increases the current line number.
operation popMsg()
- Removes the message at the current line and decreases the current line number.
operation shiftsHide()
- Hides the shift type buttons (Unload/Assembly/Load). Initially, these buttons are already hidden.
operation shiftsShow()
- Shows the shift type buttons (Unload/Assembly/Load).
operation shiftHighlightAssigned(n: integer)
- Highlights the n-th shift button in blue. See 'shiftClicked' for the mapping from n (integer) to shift type. Any previous highlight is cleared.
operation shiftHighlightActive(n: integer)
- Highlights the n-th shift button in green. See 'shiftClicked' for the mapping from n (integer) to shift type. Any previous highlight is cleared.
operation shiftHighlightClear()
- Clears any previous highlight of the shift buttons.
Note: If you build a SCTUnit test, you have to provide "mock"s for the operations that are called by your statechart.
This, however, is completely impractical in YAKINDU for getter-operations (getEnergy, getPay, getMaterial, getFinished),
as you would have to re-define the mock implementation each time after the statechart is has called its respective setter (increaseEnergy, increasePay, increaseMaterial, increaseFinished).
The only workaround here, is to create internal variables in your statechart, to replace the getter functions.
You then no longer have to use the getter functions, but when updating the internal variables, but you still have to call the setter functions, in order to update the values shown in the GUI.
For instance, this is how you would increase pay: pay += 10; increasePay(10);
Note 2: You cannot use the YAKINDU trigger 'every'. You can instead use an 'after' trigger with a self-transition.
But, beware that a self-transition on a state triggers the enter- and exit-actions of that state as well...
Starting point
As you should only focus on the reactive behaviour of the dashboard, we have provided a starting point for you, which you can download here: mosis2020.zip.
To start, import the mosis2020 directory as an existing project into your YAKINDU workspace.
The directory contains:
- Statechart.ysc: The YAKINDU statechart model. This is the only file you should edit.
- Statechart.sgen: The YAKINDU code generator model.
- srcgen/statechart.py: This file is the generated code from the statechart model. It is overwritten every time code is generated.
- run.py: The Python3 script that runs the GUI with your generated code.
- lib/*: Most of the implementation of the GUI resides here.
YAKINDU usually generates code automatically every time you save your statechart model.
You can manually trigger code generation by right-clicking the Statechart.sgen file in YAKINDU, followed by "Generate Code Artifacts".
You can test your model with the GUI before it is finished.
You can download the examples discussed in class (the traffic light) here: https://reactivesystemsmodeling.github.io/.
Note that (1) these use Java instead of Python and (2) code generation for examples 4-10 no longer works with the current version (4) of YAKINDU. You can still view, edit, simulate and run the unit tests for all of the models.
Practical information
You will use YAKINDU Statechart Tools.
You will need a (temporary) license. Since you are students, you can get a professional license for free.
Just sign up with your university e-mail. This is probably the fastest way to get a license.
The standard (non-professional) license, which is free for non-commercial use, is actually harder to obtain because you have to provide proof of your identity.
Alternatively, you can build the tool from source, but this may be difficult.
Follow the installation instructions presented on the website. to install the tool and run it.
To hand in your project, please export it to a zip-file using the functionality that YAKINDU (and any Eclipse installation) offers.
Also, please include your model as an image in your report. Use the functionality YAKINDU offers to export your model to an image.
Additionally, a report must be added in which you detail your workflow and implemented functionalities.
It is good practice to model and simulate different parts of the overall solution in isolation (incremental, bottom-up design).
Additionally, while doing this incremental design, test the requirements (using sctunit) as you go along; this ensures your increments are always correct with respect to the requirements
you have implemented.
You are encouraged to use all functionality that Statecharts offer, such as history states, after events, and orthogonal components.
Maintained by Hans Vangheluwe. |
Last Modified: 2021/09/28 22:28:58. |
|