#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; }