Skip to content
Snippets Groups Projects
Strategy.cpp 3.45 KiB
Newer Older
Franck Dary's avatar
Franck Dary committed
#include "Strategy.hpp"
#include "Config.hpp"
Franck Dary's avatar
Franck Dary committed
Strategy::Strategy(std::vector<std::string> definition)
Franck Dary's avatar
Franck Dary committed
  std::regex blockRegex("(?:(?:\\s|\\t)*)Block(?:(?:\\s|\\t)*):(?:(?:\\s|\\t)*)End\\{(.*)\\}(?:(?:\\s|\\t)*)");
Franck Dary's avatar
Franck Dary committed
  for (auto & line : definition)
    if (!util::doIfNameMatch(blockRegex, line, [this](auto sm)
      {
        blocks.emplace_back(util::split(sm.str(1), ' '));
      }))
Franck Dary's avatar
Franck Dary committed
    {
Franck Dary's avatar
Franck Dary committed
      if (blocks.empty())
        util::myThrow(fmt::format("invalid line '{}', expeced 'Block : End{}'",line,"{...}"));
      blocks.back().addMovement(line);
Franck Dary's avatar
Franck Dary committed
    }

Franck Dary's avatar
Franck Dary committed
  if (blocks.empty())
    util::myThrow("empty strategy");
  for (auto & block : blocks)
    if (block.empty())
      util::myThrow("there is an empty block");
Franck Dary's avatar
Franck Dary committed
Strategy::Movement Strategy::getMovement(const Config & c, const std::string & transition)
Franck Dary's avatar
Franck Dary committed
{
Franck Dary's avatar
Franck Dary committed
  auto movement = blocks[currentBlock].getMovement(c, transition);
Franck Dary's avatar
Franck Dary committed

Franck Dary's avatar
Franck Dary committed
  if (blocks[currentBlock].isFinished(c, movement))
Franck Dary's avatar
Franck Dary committed
  {
Franck Dary's avatar
Franck Dary committed
    currentBlock++;
    if (currentBlock >= blocks.size())
      return endMovement;
    movement.first = blocks[currentBlock].getInitialState();
    movement.second = -c.getWordIndex();
Franck Dary's avatar
Franck Dary committed
  return movement;
Franck Dary's avatar
Franck Dary committed
}

Franck Dary's avatar
Franck Dary committed
Strategy::Movement Strategy::Block::getMovement(const Config & c, const std::string & transition)
Franck Dary's avatar
Franck Dary committed
{
Franck Dary's avatar
Franck Dary committed
  std::string transitionPrefix(util::split(transition, ' ')[0]);
  auto currentState = c.getState();
Franck Dary's avatar
Franck Dary committed

Franck Dary's avatar
Franck Dary committed
  for (auto & movement : movements)
Franck Dary's avatar
Franck Dary committed
    auto fromState = std::get<0>(movement);
    auto toState = std::get<1>(movement);
    auto trans = std::get<2>(movement);
    auto mov = std::get<3>(movement);
Franck Dary's avatar
Franck Dary committed

Franck Dary's avatar
Franck Dary committed
    if (fromState == currentState and (trans == transitionPrefix or trans == "*"))
      return std::make_pair(toState, mov);
  }
Franck Dary's avatar
Franck Dary committed

Franck Dary's avatar
Franck Dary committed
  util::myThrow(fmt::format("no movement found for state '{}' and transitionPrefix '{}'", currentState, transitionPrefix));
Franck Dary's avatar
Franck Dary committed
  return endMovement;
}

Franck Dary's avatar
Franck Dary committed
const std::string Strategy::getInitialState() const
Franck Dary's avatar
Franck Dary committed
  return blocks.at(0).getInitialState();
}
Franck Dary's avatar
Franck Dary committed
void Strategy::reset()
{
  currentBlock = 0;
}
Franck Dary's avatar
Franck Dary committed

Franck Dary's avatar
Franck Dary committed
Strategy::Block::Block(std::vector<std::string> endConditionsStr)
{
  for (auto & cond : endConditionsStr)
    endConditions.emplace_back(str2condition(cond));
}
Franck Dary's avatar
Franck Dary committed

Franck Dary's avatar
Franck Dary committed
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);
Franck Dary's avatar
Franck Dary committed
  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);
}
Franck Dary's avatar
Franck Dary committed
Strategy::Block::EndCondition Strategy::Block::str2condition(const std::string & s)
{
  if (s == "cannotMove")
    return EndCondition::CannotMove;
  else
    util::myThrow(fmt::format("invalid EndCondition '{}'", s));
Franck Dary's avatar
Franck Dary committed
  return EndCondition::CannotMove;
}
Franck Dary's avatar
Franck Dary committed
const std::string Strategy::Block::getInitialState() const
{
  return std::get<0>(movements.at(0));
Franck Dary's avatar
Franck Dary committed
bool Strategy::Block::empty()
Franck Dary's avatar
Franck Dary committed
  return movements.empty();
Franck Dary's avatar
Franck Dary committed
bool Strategy::Block::isFinished(const Config & c, const Movement & movement)
Franck Dary's avatar
Franck Dary committed
  for (auto & condition : endConditions)
    if (condition == EndCondition::CannotMove)
    {
      if (c.canMoveWordIndex(movement.second))
        return false;
    }

  return true;