Hello Everyone,
this week is mostly about learning a new framework. And that framework is Boost StateCharts. A convenient API to implement a StateMachine. There is a simple example in the Boost Manual that creates a stop watch, and this example here is probably similar in complexity. But it is different example to flex the mind a little bit, and learn to adapt the framework to new problems.
To get you started I have prepared some convenience and helper functions. The goal is to have a simple traffic lights simulation. I have also provided a trivial implementation, and some hints. Your task is it to implement the statechart based solution.
/* CPP Challenge 2:
* Traffic Lights with Boost Statemachine
*/
#include <iostream>
#include <string>
#include <unistd.h>
#include <boost/statechart/event.hpp>
#include <boost/statechart/state_machine.hpp>
#include <boost/statechart/simple_state.hpp>
#include <boost/statechart/state.hpp>
#include <boost/statechart/transition.hpp>
std::string text_red(const std::string &input)
{
return "\033[1;31m" + input + "\033[0m";
}
std::string text_green(const std::string &input)
{
return "\033[1;32m" + input + "\033[0m";
}
std::string text_yellow(const std::string &input)
{
return "\033[1;33m" + input + "\033[0m";
}
struct Light
{
Light() : isOn_(false) {}
void on() { isOn_ = true; }
void off() { isOn_ = false; }
bool IsOn() const { return isOn_; }
private:
bool isOn_;
};
struct RedLight : Light { };
struct GreenLight : Light { };
struct YellowLight : Light { };
struct Lights
{
RedLight red;
GreenLight green;
YellowLight yellow;
};
std::string showlight(const Light& light)
{
if (light.IsOn()) {
return "[*]";
} else {
return "[ ]";
}
}
void show(const Lights& lights)
{
std::cout << text_red(showlight(lights.red)) << "\n";
std::cout << text_yellow(showlight(lights.yellow)) << "\n";
std::cout << text_green(showlight(lights.green)) << "\n";
}
/*
* Task:
* Create a statemachine, "TrafficLights"
* with two helper functions "Lights lights() const;"
* and "int DelayTime() const", that returns a lights object,
* and the time the machine needs to wait, before processing the next transition.
*
* 4 States: "Stop", "Prepare", "Go" and "Slow"
*
* Stop and Go should wait 5 Seconds, Prepare and Slow 1 Second each.
*/
int main(int argc, const char *argv[])
{
Lights lights;
lights.red.off();
lights.yellow.off();
lights.green.off();
while (true) {
lights.red.on();
lights.yellow.off();
show(lights); sleep(5);
std::cout << std::endl;
lights.yellow.on();
show(lights); sleep(1);
std::cout << std::endl;
lights.red.off();
lights.yellow.off();
lights.green.on();
show(lights); sleep(5);
std::cout << std::endl;
lights.green.off();
lights.yellow.on();
show(lights); sleep(1);
std::cout << std::endl;
}
// This is how the statemachine based main loop should look:
/*TrafficLight lights;
lights.initiate();
while(true) {
lights.process_event(EvTransition());
show(lights.lights());
sleep(lights.DelayTime());
std::cout << std::endl;
}*/
return 0;
}
So have fun with this problem. I already have a solution, and will post it next week. Probably I will protect the solution with a simple password to avoid spoilers. But you can get the password when you ask me via mail.
Cheers
-Richard