-
Franck Dary authoredFranck Dary authored
Strategy.cpp 3.45 KiB
#include "Strategy.hpp"
#include "Config.hpp"
Strategy::Strategy(std::vector<std::string> definition)
{
std::regex blockRegex("(?:(?:\\s|\\t)*)Block(?:(?:\\s|\\t)*):(?:(?:\\s|\\t)*)End\\{(.*)\\}(?:(?:\\s|\\t)*)");
for (auto & line : definition)
if (!util::doIfNameMatch(blockRegex, line, [this](auto sm)
{
blocks.emplace_back(util::split(sm.str(1), ' '));
}))
{
if (blocks.empty())
util::myThrow(fmt::format("invalid line '{}', expeced 'Block : End{}'",line,"{...}"));
blocks.back().addMovement(line);
}
if (blocks.empty())
util::myThrow("empty strategy");
for (auto & block : blocks)
if (block.empty())
util::myThrow("there is an empty block");
}
Strategy::Movement Strategy::getMovement(const Config & c, const std::string & transition)
{
auto movement = blocks[currentBlock].getMovement(c, transition);
if (blocks[currentBlock].isFinished(c, movement))
{
currentBlock++;
if (currentBlock >= blocks.size())
return endMovement;
movement.first = blocks[currentBlock].getInitialState();
movement.second = -c.getWordIndex();
}
return movement;
}
Strategy::Movement Strategy::Block::getMovement(const Config & c, const std::string & transition)
{
std::string transitionPrefix(util::split(transition, ' ')[0]);
auto currentState = c.getState();
for (auto & movement : movements)
{
auto fromState = std::get<0>(movement);
auto toState = std::get<1>(movement);
auto trans = std::get<2>(movement);
auto mov = std::get<3>(movement);
if (fromState == currentState and (trans == transitionPrefix or trans == "*"))
return std::make_pair(toState, mov);
}
util::myThrow(fmt::format("no movement found for state '{}' and transitionPrefix '{}'", currentState, transitionPrefix));
return endMovement;
}
const std::string Strategy::getInitialState() const
{
return blocks.at(0).getInitialState();
}
void Strategy::reset()
{
currentBlock = 0;
}
Strategy::Block::Block(std::vector<std::string> endConditionsStr)
{
for (auto & cond : endConditionsStr)
endConditions.emplace_back(str2condition(cond));
}
void Strategy::Block::addMovement(std::string definition)
{
std::regex regex("(?:(?:\\s|\\t)*)(\\S+)(?:(?:\\s|\\t)+)(\\S+)(?:(?:\\s|\\t)+)(\\S+)(?:(?:\\s|\\t)+)(\\S+)(?:(?:\\s|\\t)*)");
auto errorMessage = fmt::format("invalid definition '{}' expected fromState toState transitionNamePrefix wordIndexMovement", definition);
if (!util::doIfNameMatch(regex, definition, [this, &errorMessage](auto sm)
{
try
{
movements.emplace_back(std::make_tuple(sm.str(1), sm.str(2), sm.str(3), std::stoi(sm.str(4))));
} catch (std::exception & e) {util::myThrow(fmt::format("caught '{}' in {}", e.what(), errorMessage));}
}))
util::myThrow(errorMessage);
}
Strategy::Block::EndCondition Strategy::Block::str2condition(const std::string & s)
{
if (s == "cannotMove")
return EndCondition::CannotMove;
else
util::myThrow(fmt::format("invalid EndCondition '{}'", s));
return EndCondition::CannotMove;
}
const std::string Strategy::Block::getInitialState() const
{
return std::get<0>(movements.at(0));
}
bool Strategy::Block::empty()
{
return movements.empty();
}
bool Strategy::Block::isFinished(const Config & c, const Movement & movement)
{
for (auto & condition : endConditions)
if (condition == EndCondition::CannotMove)
{
if (c.canMoveWordIndex(movement.second))
return false;
}
return true;
}