I have a state machine design that needs to support playback. We have states that perform actions and sometimes need to generate random numbers. In case the program shuts down while in the middle of the FSM's execution, the program needs to playback the whole FSM using the same random numbers as before.
For a basic example, let's say I had three states: A, B, and C. The FSM will call a state's Execute() function. At the end of the function, the state will post an event, and the FSM will determine which state to go to next. In state A, it will call rand(). If the number is even, it will post an event to go to state B, otherwise state C should be the next state.
void StateA::Execute(IEventQueue& rQueue)
{
int num = rand();
if( num % 2 == 0 )
{
rQueue.PostEvent("GoToStateB");
}
else
{
rQueue.PostEvent("GoToStateC");
}
}
If the random number is 69, then it should go to state C. While in state C, it's possible that the program might quit. When the program starts up again, it should playback the state machine. Obviously, for this to work correctly, it can't generate a completely new random number, it needs to use 69 again for accurate playback.
I have a file stream interface that I can use for saving data to a file, but the code is a little ugly:
void StateA::Execute(IEventQueue& rQueue, IFileStream& rStream)
{
int num = 0;
// fails if there's no more data to read
bool bSuccess = rStream.ReadInt(num);
if (!bSucess)
{
num = rand();
rStream.WriteInt(num);
}
// same code as before
}
My only problem with this solution is that I don't care for having to check the stream for data first and then conditionally write to the same stream.
I thought about hiding it like this:
void StateA::Execute(IEventQueue& rQueue, IStream& rStream)
{
int num = 0;
num = rand();
rStream & num;
// same code as before
}
Inside IStream, operator& (probably not the best use of overloading) would actually try to read an int from the stream. If that stream was empty, it would then write it instead. Like before, the behavior would be: read first until the end of stream, and then start appending.
So I guess my question is: is there a common idiom for this type of playback that I might be overlooking? Does anyone have alternate suggestions? I feel like I'm starting to over-complicate the design a bit.
Thanks!
Why have the states interact directly with the filestream? Single Responsibility says we should have a class who's job it is to provide the proper number based on some logic.
struct INumberSource {
virtual int GenNextNumber() = 0;
}
// My job is to provide numbers from an RNG
struct RNGNumberSource : public INumberSource {
virtual int GenNextNumber() {
return rand();
}
}
// My job is to write any numbers sourced through me to a file
// I delegate to another source to get an actual number
class FileStreamTrackingNumberSource : INumberSource {
public:
FileStreamTrackingNumberSource(INumberSource& source, IFileStream& stream)
: altSource(source), fileStream(stream) { }
virtual int GenNextNumber() {
int num = altSource.GenNextNumber();
fileStream.WriteInt(num);
return num;
}
private:
INumberSource altSource;
IFileStream& fileStream;
}
// My job is to source numbers from a file stream delegating to an
// alternate source when I run out
class FileStreamNumberSource : public INumberSource {
public:
FileStreamNumberSource(INumberSource& source, IFileStream& stream)
: altSource(source), fileStream(stream), failedRead(false) { }
virtual int GenNextNumber() {
int num = 0;
if(failedRead || !(failedRead = fileStream.ReadInt(num))) {
num = altSource.GenNextNumber();
}
return num;
}
private:
INumberSource& altSource;
IFileStream& fileStream;
bool failedRead;
}
So in your case you would provide an IFileStream and RNGNumberSource to a FileStreamTrackingNumberSource and provide that and the same IFileStream to a FileStreamNumberSource. That FileStreamNumberSource is what you would give to your State's INumberSource parameter.
Assuming you only needed the number to choose the next state then your state code could look like this:
void StateA::Execute(IEventQueue& rQueue, INumberSource& numberSource)
{
if( numberSource.GenNextNumber() % 2 == 0 )
{
rQueue.PostEvent("GoToStateB");
}
else
{
rQueue.PostEvent("GoToStateC");
}
}
I suspect you should have two files: one that records the events you are playing, and the other that you read "re-play" events from. If the re-play file is longer than the "recording" file, then that is the one you use for a re-play.
I also would not use operator overloading as you suggested. Perhaps just use a ternary operator.
I'm not sure I understand the rationale behind "playback", but can't you simply wrap the whole "random-number or read-from-file" logic behind a class or function?
UPDATE
On the subject of "playback" and your design in general, I'm not sure it's normal for a FSM to generate its own stimulus (i.e. the random numbers which in turn trigger state transitions). Normally, the stimulus is provided externally. If you re-factor with this in mind, then you no longer have this messy problem!
Related
I recently read Clean Code, and one concept they discouraged was passing variables that signal behavior into functions (i.e. a flag, if TRUE, do one thing, if FALSE, do another). The book says instead you should write two functions.
At the same time, duplicating chunks of code isn't ideal.
I've written a simple plaintext brute force password cracker (for a school project), which prints out each password.
I'd like a way to turn off the print portion of the code, so the user has the option of running it with printing or without (to decrease runtime).
My initial solution was like this:
bool bruteForce(bool printFlag)
{
for (all letter combinations)
if (printFlag)
fwrite(pw, sizeof(char), sizeof(pw) - 1, stdout);
...
}
However, if I do this it might run slower. Maybe it won't make much of a difference and I'm overthinking it?
What would best practices be in this situation? Use a flag or make a separate function with print functionality?
There are many different opinion on subject like this.
My understanding from the book, is that you should avoid function with bolean parameter in such situation:
void module(bool enable) // Bad
// Good:
void enableModule();
void disableModule();
this is mostly a question of readability.
You should avoid duplicating code, in your situation, depending the rest of the structure of your class, perhaps you can have a class variable to enable / disable the flag printing as a separate function:
class x {
public:
bool bruteForce();
void enableFlagPrinting() { m_printFlag = true; }
void disableFlagPrinting() { m_printFlag = false; }
private:
m_printFlag = false;
}
Depending the rest of your code, you can make bruteForce itself as a class with all the parameters it can have.
class BruteForce {
public:
bool start();
void enableFlagPrinting() { m_printFlag = true; }
void disableFlagPrinting() { m_printFlag = false; }
private:
m_printFlag = false;
}
used as
BruteForce bf;
bf.enableFlagPrinting();
bf.start();
However, if I do this it might run slower. Maybe it won't make much of a difference and I'm overthinking it?
Given it's only an additional bool comparison, this is performed very fast and I doubt it will make any significant difference compared to the rest of the code, although you could duplicate code if it is really necessary, as long as it is well encapsulated:
class BruteForce {
public:
bool start()
{
if (m_printFlag) bruteForceWithFlags();
else bruteForceWithoutFlags();
}
void enableFlagPrinting() { m_printFlag = true; }
void disableFlagPrinting() { m_printFlag = false; }
private:
void bruteForceWithFlags();
void bruteForceWithoutFlags();
m_printFlag = false;
}
it's a trade-off speed / maintenability, from experience I suggest you to go for the maintenability :P.
If you are mainly concerned about performance, start reconsidering where you put your if:
bool bruteForce(bool printFlag) {
for (all letter combinations)
if (printFlag)
fwrite(pw, sizeof(char), sizeof(pw) - 1, stdout);
...
}
What about this:
bool bruteForce(bool printFlag) {
if(printFlag)
for (all letter combinations)
fwrite(pw, sizeof(char), sizeof(pw) - 1, stdout);
...
else
for (all letter combinations)
...
}
How many times is the if potentially evaluated now? 1 vs #(all letter combinations).
This won't improve your performance so as they are acceptable, anyway.
Once you did it, if the ... part is long, put it in a separate function band do not repeat the code. Don't care of it if it's one line.
Finally, if you want to remove the boolean flag, well, add a second function. That's not a problem at all.
I prefer to add null-ostream discarding
#include <iostream>
#include <string>
#include <algorithm>
int
main(int argc, char* argv[]) {
bool verbose = true;
std::ostream out(0);
if (verbose)
out.rdbuf(std::cout.rdbuf());
out << "hello" << std::endl;
return 0;
}
I need to implement some abstract protocol client-server conversation parsing library with C++. I don't have file containing the whole client-server conversation, but have to parse it on the fly. I have to implement following interface:
class parsing_class
{
public:
void on_data( const char* data, size_t len );
//other functions
private:
size_t pos_;// current position in the data flow
bool first_part_parsed_;
bool second_part_parsed_;
//... some more bool markers or something like vector< bool >
};
The data is passed to my class through on_data function. Data chunk length varies from one call to another. I know protocol's packet format and know how conversation should be organized, so I can judge by current pos_ whether i have enough data to parse Nth part.
Now the implementation is like following:
void parsing_class::on_data( const char* data, size_t len )
{
pos_ += len;
if( pos > FIRST_PART_SIZE and !first_part_parsed_ )
parse_first_part( data, len );
if( pos > SECOND_PART_SIZE and !second_part_parsed_ )
parse_second_part( data, len );
//and so on..
}
What I want is some tips how to optimize this algorithm. Maybe to avoid these numerous if ( on_data may be called very many times and each time it will have to go through all switches ).
You don't need all those bool and pos_, as they seem to only keep the state of what of the conversation has passed so that you can continue with the next part.
How about the following: write yourself a parse function for each of the parts of the conversation
bool parse_part_one(const char *data) {
... // parse the data
next_fun = parse_part_two;
return true;
}
bool parse_part_two(const char *data) {
... // parse the data
next_fun = parse_part_thee;
return true;
}
...
and in your class you add a pointer to the current parse function, starting at one. Now, in on_data all you do is to call the next parse function
bool success = next_fun(data);
Because each function sets the pointer to the next parse function, the next call of on_data will invoke the next parse function automatically. No tests required of where in the conversation you are.
If the value of len is critical (which I assume it would be) then pass that along as well and return false to indicate that the part could not be parsed (don't update next_fun in that case either).
I need to write tests(using google testing framework) for small study program that was written not by me. (it's just small console game which can get modes from command line or just get it in runtime)
There is a problem: I can't change the souce code but there is in almost all methods used cout and cin. and my question is "how to answer on requests (cin) of programm while testing (something like get data for cin from string )?".
Assuming you can control main() (or some other function called before the functions to be tested) you can change where std::cin reads from and where std::cout writes to:
int main(int ac, char* av[]) {
std::streambuf* orig = std::cin.rdbuf();
std::istringstream input("whatever");
std::cin.rdbuf(input.rdbuf());
// tests go here
std::cin.rdbuf(orig);
}
(likewise for std::cout)
This example saves the original stream buffer of std::cin so it can be replaced before leaving main(). It then sets up std::cin to read from a string stream. It can be any other stream buffer as well.
My understanding is you need to perform the following:
Launch / start target executable (the game).
Send test data to target executable.
Obtain output from target executable.
Compare output with expected results.
The standard C++ language has no standard facilities for communicating with other programs. You will need help from the operating system (which you didn't specify).
Using only C++ or without OS specific calls, I suggest:
Writing test input to a file.
Run the executable, piping the test input file as input and piping
the output to a results file.
Read and analyze the result file.
Otherwise, search your OS API to find out how to write to the I/O redirection drivers.
I know you said you can't modify the code, but I'll answer this as if you can. The real world typically allows (small) modifications to accommodate testing.
One way is to wrap your calls that require external inputs (DB, user input, sockets, etc...) in function calls that are virtual so you can mock them out. (Example below). But first, a book recommendation on testing. Working Effectively with Legacy Code is a great book for testing techniques that aren't just limited to legacy code.
class Foo {
public:
bool DoesSomething()
{
string usersInput;
cin >> usersInput;
if (usersInput == "foo") { return true; }
else { return false; }
}
};
Would turn into:
class Foo
{
public:
bool DoesSomething() {
string usersInput = getUserInput();
if (usersInput == "foo") { return true; }
else { return false; }
}
protected:
virtual std::string getUserInput() {
string usersInput;
cin >> usersInput;
return usersInput;
}
};
class MockFoo : public Foo {
public:
void setUserInput(std::string input) { m_input = input }
std::string getUserInput() {
return m_input;
}
};
TEST(TestUsersInput)
{
MockFoo foo;
foo.setUserInput("SomeInput");
CHECK_EQUAL(false, foo.DoesSomething());
foo.setUserInput("foo");
CHECK_EQUAL(true, foo.DoesSomething());
}
You can improve testability of your classes by not using cin and cout directly. Instead use istream& and ostream& to pass in the input source and output sink as parameters. This is a case of dependency injection. If you do that, you can pass in a std::stringstream instead of cin, so that you can provide specified input and get at the output from your test framework.
That said, you can achieve a similar effect by turning cin and cout into stringstreams (at least temporarily). To do this, set up a std::stringbuf (or "borrow" one from a std::stringstream) and use cin.rdbuf(my_stringbuf_ptr) to change the streambuf used by cin. You may want to revert this change in test teardown. To do that you can use code like:
stringbuf test_input("One line of input with no newline", ios_base::in);
stringbuf test_output(ios_base::out);
streambuf * const cin_buf = cin.rdbuf(&test_input);
streambuf * const cout_buf = cout.rdbuf(&test_output);
test_func(); // uses cin and cout
cout.rdbuf(cout_buf);
cin.rdbuf(cin_buf);
string test_output_text = test_output.str();
I'm programming in C++ and have a method which uses a static variable. The method isn't working as I think it should; upon investigation, I found that my static variable is being highlighted in red in two places and blue in other places. Below is the code:
int GameModeState::changeJob(int number)
{
static int job = 1; //red
if (number == 1)
{
job = (job+1); //First one is red, second one is blue
return job; //blue
} else {
return job; //blue
}
}
I'm calling this method with other methods, one shown for example:
int GameModeState::getJob()
{
int currentJob = (changeJob(2));
return currentJob;
}
I want a method like getJob() to simply return the current value of job, while another method, when calling changeJob(number) is changeJob(1), to increment job's value by one. (Hence the if/else statement in changeJob(number)).
Since the job variables are highlighted differently, I'm thinking the compiler is saying that it views the two separately somehow? I'm getting stuck with job being some even value.
EDIT I also have Awesomium... I believe that is the only addition to the compiler, but I'm not completely sure.
MOAR EDIT In another class, I have a method which should determine the current job's number and do something based on if the number is even or odd (since right now there are only two jobs)
void ZoneMovementState::_changeZone(const String& message, const Awesomium::JSValue& input, Awesomium::JSValue& output)
{
//Awesomium::JSValue::Object object = input.getObject();
//String zoneFilename = Convert::toString(object[L"zoneFilename"].toString());
// If the number from getJob is even, the player is currently a geologist
if (GameModeState::getJob()%2 == 0)
{
ZoneParser::getSingleton().load("../media/zones/geology_zone.xml", false);
} else {
ZoneParser::getSingleton().load("../media/zones/farm_zone.xml", false);
}
transitionHandler->go();
}
Ignore the two commented out lines; they deal with JS, which I'm not working on for now.
In the program, I can access the farm_zone until I increment job's value using the below method in GameModeState:
void GameModeState::_openNotebook(const String& message, const Awesomium::JSValue& input, Awesomium::JSValue& output)
{
mNotebookTransition->go();
static int currentJob = changeJob(1);
}
.... So I figured out my problem. While going through the code to show you guys, I realized that the static for currentJob was probably unneeded... once I removed it, my code works as it should now.
Thanks for the help guys!
Part of the problem here is you're using a static local for what very likely should just be a member variable. A static local maintains it's value across all calls to a function in all threads in a process. It's much more likely that you want it to persist for all calls to changeJob in a particular GameModeState instance (else why make it a member functon to begin with?).
To do this you'll need to define a member variable on GameModeState initialize it in the constructor and then access it in the method. For example
class GameModeState {
int job;
GameModeState() : job(1) {}
int changeJob(int number);
};
int GameModeState::changeJob(int number) {
if (number == 1) {
job = (job+1);
return job;
} else {
return job;
}
}
Note: I'm not entirely sure why you're seeing the color's your are seeing. Visual Studio by default won't color member variables a particular color in C++ so it's very likely another add-in you are using.
Nah, highlighting doesn't mean anything. That is, the editor doesn't call the compiler before deciding how/what/when to highlight. So that is not your problem. Sorry 'bout that :-)
You can prove this to yourself by going to Tools->Options->TextEditor and noticing that you can change the highlighting by choosing a different text-editing model.
I'm keeping track of a player's "job" by setting his job to a number, and incrementing it by one if he changes job, and determining which job he currently is by whether the number is even or odd. (Only two jobs right now). However, I know there are better ways of doing this, and soon I'll need to implement for a third and fourth job, so I cannot keep using the even/odd check.
Here's my code for reference: (Please note that I only include relevant code)
GameModeState.cpp
// If changeJob's parameter number is 1, it increments the job. If number is 2, it only returns the current job
int GameModeState::changeJob(int number)
{
// Default job is even (landman)
static int job = 1;
if (number == 1)
{
job = (job+1);
return job;
}
else
{
return job;
}
}
int GameModeState::getJob()
{
int currentJob = (changeJob(2));
return currentJob;
}
// If the player opens the "stat sheet", it changes their job
void GameModeState::_statSheet(const String& message, const Awesomium::JSValue& input, Awesomium::JSValue& output)
{
changeJob(1);
}
GameModeState.h
class GameModeState : public GameState::State
{
public:
/// Changes the player's job if number is 1, or returns current job if number is 2
static int changeJob(int number);
/// Returns the current job number by calling changeJob appropriately
static int getJob();
private:
// Opening the player sheet will change the player's job
void _statSheet(const String& message, const Awesomium::JSValue& input, Awesomium::JSValue& output);
};
ZoneMovementState.cpp (This is where I check for current job)
#include "GameModeState.h"
#include <EnergyGraphics/ZoneParser.h>
void ZoneMovementState::_changeZone(const String& message, const Awesomium::JSValue& input, Awesomium::JSValue& output)
{
// If the number from getJob is even, the player is currently a geologist
if (GameModeState::getJob()%2 == 0)
{
ZoneParser::getSingleton().load("../media/zones/geology_zone.xml", false);
}
else //otherwise they are a landman
{
ZoneParser::getSingleton().load("../media/zones/landman_zone.xml", false);
}
transitionHandler->go();
}
I'm thinking either arrays or enums of the jobs will be the better way to deal with this, but I'm not sure how to implement this into my code. If you know a better way, please include examples or at least a point in the right direction. I will greatly appreciate it!
Don't use static variables to save anything like that inside a class. Use a member variable instead.
IMO the easiest way to do something like that and make it extensible is using a enum:
enum PlayerJob
JOB_NONE = 0,
JOB_GEOLOGIST,
JOB_LANDMAN,
...
NUM_JOBS // this element is optional but can be useful for range checking.
};
...
PlayerJob job = JOB_NONE;
...
switch(job)
{
case JOB_NONE:
break;
case JOB_GEOLOGIST:
...
break;
...
default:
error("Unhandled palyer job: %d", job);
break;
}
Also I'd think about somehow organizing such "job relevant" stuff into some kind of array or list or whatever to make it easier to call "job specific" things:
std::map<PlayerJob,std::string> jobzones;
jobzones.push_back(JOB_GEOLOGIST, "geozone.xml");
...
transitToZone(jobzones[job]);
Enums are nice, you may also think about using a std::stack or something similar for the GameState, so that you can push/pop etc.
You may want to look at the State pattern.