Skip to content
Snippets Groups Projects
Strategy.cpp 3.72 KiB
Newer Older
  • Learn to ignore specific revisions
  • Franck Dary's avatar
    Franck Dary committed
    #include "Strategy.hpp"
    
    Franck Dary's avatar
    Franck Dary committed
    
    Strategy::Strategy(const std::vector<std::string_view> & lines)
    {
      if (!util::doIfNameMatch(std::regex("Strategy : ((incremental)|(sequential))"), lines[0], [this](auto sm)
      {type = sm[1] == "sequential" ? Type::Sequential : Type::Incremental;}))
      util::myThrow(fmt::format("Invalid strategy identifier '{}'", lines[0]));
    
      for (unsigned int i = 1; i < lines.size(); i++)
      {
        auto splited = util::split(lines[i], ' ');
    
    Franck Dary's avatar
    Franck Dary committed
        std::pair<std::string, std::string> key;
        std::string value;
    
    Franck Dary's avatar
    Franck Dary committed
        int movement;
    
    Franck Dary's avatar
    Franck Dary committed
    
    
    Franck Dary's avatar
    Franck Dary committed
        if (splited.size() == 3)
    
    Franck Dary's avatar
    Franck Dary committed
        {
          key = std::pair<std::string,std::string>(splited[0], "");
          value = splited[1];
    
    Franck Dary's avatar
    Franck Dary committed
          movement = std::stoi(std::string(splited[2]));
    
          if (defaultCycle.empty())
            initialState = splited[0];
    
    Franck Dary's avatar
    Franck Dary committed
          defaultCycle.emplace_back(value);
        }
    
    Franck Dary's avatar
    Franck Dary committed
        else if (splited.size() == 4)
    
    Franck Dary's avatar
    Franck Dary committed
        {
    
    Franck Dary's avatar
    Franck Dary committed
          key = std::pair<std::string,std::string>(splited[0], splited[2]);
    
    Franck Dary's avatar
    Franck Dary committed
          value = splited[1];
    
    Franck Dary's avatar
    Franck Dary committed
          movement = std::stoi(std::string(splited[3]));
    
    Franck Dary's avatar
    Franck Dary committed
        }
    
    Franck Dary's avatar
    Franck Dary committed
        else
          util::myThrow(fmt::format("Invalid strategy line '{}'", lines[i]));
    
    Franck Dary's avatar
    Franck Dary committed
    
        if (edges.count(key))
          util::myThrow(fmt::format("Edge {} {} defined twice", key.first, key.second));
    
    Franck Dary's avatar
    Franck Dary committed
        edges[key] = std::make_pair(value, movement);
    
    Franck Dary's avatar
    Franck Dary committed
        isDone[key.first] = false;
    
    Franck Dary's avatar
    Franck Dary committed
    
      if (edges.empty())
        util::myThrow("Strategy is empty");
      defaultCycle.pop_back();
      std::reverse(defaultCycle.begin(), defaultCycle.end());
    
    Franck Dary's avatar
    Franck Dary committed
    }
    
    std::pair<std::string, int> Strategy::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]);
    
    
    Franck Dary's avatar
    Franck Dary committed
      if (c.stateIsDone())
        isDone[c.getState()] = true;
    
      while (defaultCycle.size() && isDone[defaultCycle.back()])
        defaultCycle.pop_back();
    
      if (type == Type::Sequential)
    
    Franck Dary's avatar
    Franck Dary committed
        return getMovementSequential(c, transitionPrefix);
    
    Franck Dary's avatar
    Franck Dary committed
    
    
    Franck Dary's avatar
    Franck Dary committed
      return getMovementIncremental(c, transitionPrefix);
    
    Franck Dary's avatar
    Franck Dary committed
    }
    
    std::pair<std::string, int> Strategy::getMovementSequential(const Config & c, const std::string & transition)
    {
      auto foundSpecific = edges.find(std::make_pair(c.getState(), transition));
      auto foundGeneric = edges.find(std::make_pair(c.getState(), ""));
    
      std::string target;
    
    Franck Dary's avatar
    Franck Dary committed
      int movement = -1;
    
    Franck Dary's avatar
    Franck Dary committed
    
      if (foundSpecific != edges.end())
    
    Franck Dary's avatar
    Franck Dary committed
      {
        target = foundSpecific->second.first;
        movement = foundSpecific->second.second;
      }
    
    Franck Dary's avatar
    Franck Dary committed
      else if (foundGeneric != edges.end())
    
    Franck Dary's avatar
    Franck Dary committed
      {
        target = foundGeneric->second.first;
        movement = foundGeneric->second.second;
      }
    
    Franck Dary's avatar
    Franck Dary committed
    
      if (target.empty())
        util::myThrow(fmt::format("no suitable movement found for current state '{}' and transition '{}'", c.getState(), transition));
    
      if (!c.stateIsDone())
    
        return {c.getState(), c.canMoveWordIndex(movement) ? movement : 0};
    
    Franck Dary's avatar
    Franck Dary committed
    
      if (!isDone[target])
        return {target, -c.getWordIndex()};
    
      return endMovement;
    }
    
    std::pair<std::string, int> Strategy::getMovementIncremental(const Config & c, const std::string & transition)
    
    Franck Dary's avatar
    Franck Dary committed
    {
      auto foundSpecific = edges.find(std::make_pair(c.getState(), transition));
      auto foundGeneric = edges.find(std::make_pair(c.getState(), ""));
    
    
    Franck Dary's avatar
    Franck Dary committed
      std::string target;
    
    Franck Dary's avatar
    Franck Dary committed
      int movement;
    
    Franck Dary's avatar
    Franck Dary committed
    
    
    Franck Dary's avatar
    Franck Dary committed
      if (foundSpecific != edges.end())
    
    Franck Dary's avatar
    Franck Dary committed
      {
        target = foundSpecific->second.first;
        movement = foundSpecific->second.second;
      }
    
    Franck Dary's avatar
    Franck Dary committed
      else if (foundGeneric != edges.end())
    
    Franck Dary's avatar
    Franck Dary committed
      {
        target = foundGeneric->second.first;
        movement = foundGeneric->second.second;
      }
    
    Franck Dary's avatar
    Franck Dary committed
    
      if (target.empty())
        util::myThrow(fmt::format("no suitable movement found for current state '{}' and transition '{}'", c.getState(), transition));
    
    Franck Dary's avatar
    Franck Dary committed
      if (!isDone[target])
    
    Franck Dary's avatar
    Franck Dary committed
        return {target, target == defaultCycle.back() ? movement : 0};
    
    Franck Dary's avatar
    Franck Dary committed
      if (defaultCycle.empty())
        return endMovement;
    
    Franck Dary's avatar
    Franck Dary committed
      return {defaultCycle.back(), movement};
    
    const std::string Strategy::getInitialState() const
    {
      return initialState;
    }