From 9c09bc6c4a1dab425d5a355a42058a9bb63123f1 Mon Sep 17 00:00:00 2001
From: Franck Dary <franck.dary@lis-lab.fr>
Date: Wed, 8 Jan 2020 15:00:51 +0100
Subject: [PATCH] Defined the Strategy class

---
 common/include/util.hpp                    |  2 +-
 common/src/util.cpp                        |  6 ++--
 reading_machine/include/ReadingMachine.hpp |  3 +-
 reading_machine/include/Strategy.hpp       | 19 ++++++++++++
 reading_machine/src/ReadingMachine.cpp     | 34 +++++++++++----------
 reading_machine/src/Strategy.cpp           | 35 +++++++++++++++++++++-
 6 files changed, 79 insertions(+), 20 deletions(-)

diff --git a/common/include/util.hpp b/common/include/util.hpp
index 4afb1c6..2d00f79 100644
--- a/common/include/util.hpp
+++ b/common/include/util.hpp
@@ -77,7 +77,7 @@ bool isEmpty(const boost::flyweight<T> & s)
   return isEmpty(s.get());
 }
 
-bool doIfNameMatch(const std::regex & reg, const std::string & name, const std::function<void(const std::smatch &)> & f);
+bool doIfNameMatch(const std::regex & reg, std::string_view name, const std::function<void(const std::smatch &)> & f);
 
 };
 
diff --git a/common/src/util.cpp b/common/src/util.cpp
index d6362cc..1542c89 100644
--- a/common/src/util.cpp
+++ b/common/src/util.cpp
@@ -111,10 +111,12 @@ std::string util::int2HumanStr(int number)
   return result;
 }
 
-bool util::doIfNameMatch(const std::regex & reg, const std::string & name, const std::function<void(const std::smatch &)> & f)
+bool util::doIfNameMatch(const std::regex & reg, std::string_view name, const std::function<void(const std::smatch &)> & f)
 {
   std::smatch sm;
-  std::regex_match(name, sm, reg);
+  std::string sname(name);
+  std::regex_match(sname, sm, reg);
+
   if (sm.empty())
     return false;
 
diff --git a/reading_machine/include/ReadingMachine.hpp b/reading_machine/include/ReadingMachine.hpp
index 339e25a..dc4be73 100644
--- a/reading_machine/include/ReadingMachine.hpp
+++ b/reading_machine/include/ReadingMachine.hpp
@@ -3,14 +3,15 @@
 
 #include <memory>
 #include "Classifier.hpp"
+#include "Strategy.hpp"
 
 class ReadingMachine
 {
   private :
 
   std::string name;
-  std::function<std::pair<std::string, int>(const Config & config)> strategy;
   std::unique_ptr<Classifier> classifier;
+  std::unique_ptr<Strategy> strategy;
 
   public :
 
diff --git a/reading_machine/include/Strategy.hpp b/reading_machine/include/Strategy.hpp
index bd42d4f..60dbfa9 100644
--- a/reading_machine/include/Strategy.hpp
+++ b/reading_machine/include/Strategy.hpp
@@ -3,4 +3,23 @@
 
 #include "Config.hpp"
 
+class Strategy
+{
+  private :
+
+  enum Type
+  {
+    Incremental,
+    Sequential
+  };
+
+  Type type;
+  std::map<std::pair<std::string, std::string>, std::string> edges;
+
+  public :
+
+  Strategy(const std::vector<std::string_view> & lines);
+  std::pair<std::string, int> getMovement(const Config & c, const std::string & transition);
+};
+
 #endif
diff --git a/reading_machine/src/ReadingMachine.cpp b/reading_machine/src/ReadingMachine.cpp
index 9528bb8..cc484eb 100644
--- a/reading_machine/src/ReadingMachine.cpp
+++ b/reading_machine/src/ReadingMachine.cpp
@@ -1,32 +1,36 @@
 #include "ReadingMachine.hpp"
 #include "util.hpp"
-#include "Strategy.hpp"
 
 ReadingMachine::ReadingMachine(const std::string & filename)
 {
-  std::regex nameRegex("Name : (.+)[\n]");
-  std::regex strategyRegex("Strategy : (.+)[\n]");
-  std::regex classifierRegex("Classifier : (.+) (.+) (.+)[\n]");
-
   std::FILE * file = std::fopen(filename.c_str(), "r");
 
   char buffer[1024];
+  std::string fileContent;
   while (!std::feof(file))
   {
     if (buffer != std::fgets(buffer, 1024, file))
       break;
 
-    try
-    {
-      if (util::doIfNameMatch(nameRegex, buffer, [this](auto sm){name = sm[1];}))
-        continue;
-      if (util::doIfNameMatch(strategyRegex, buffer, [this](auto sm){}))
-        continue;
-      if (util::doIfNameMatch(classifierRegex, buffer, [this](auto sm){classifier.reset(new Classifier(sm[1], sm[2], sm[3]));}))
-        continue;
-    } catch(std::exception & e) {util::myThrow(fmt::format("during reading of '{}' : {}", filename, e.what()));}
+    fileContent += buffer;
   }
-
   std::fclose(file);
+
+  auto lines = util::split(fileContent, '\n');
+
+  try
+  {
+    unsigned int curLine = 0;
+    if (!util::doIfNameMatch(std::regex("Name : (.+)"), lines[curLine++], [this](auto sm){name = sm[1];}))
+      util::myThrow("No name specified");
+
+    while (util::doIfNameMatch(std::regex("Classifier : (.+) (.+) (.+)"), lines[curLine++], [this](auto sm){classifier.reset(new Classifier(sm[1], sm[2], sm[3]));}));
+    if (!classifier.get())
+      util::myThrow("No Classifier specified");
+
+    std::vector<std::string_view> restOfFile(lines.begin()+curLine-1, lines.end());
+    strategy.reset(new Strategy(restOfFile));
+
+  } catch(std::exception & e) {util::myThrow(fmt::format("during reading of '{}' : {}", filename, e.what()));}
 }
 
diff --git a/reading_machine/src/Strategy.cpp b/reading_machine/src/Strategy.cpp
index 4beb7af..2d5e9ae 100644
--- a/reading_machine/src/Strategy.cpp
+++ b/reading_machine/src/Strategy.cpp
@@ -1,3 +1,36 @@
 #include "Strategy.hpp"
-#include "util.hpp"
+
+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], ' ');
+    if (splited.size() == 2)
+      edges[std::pair<std::string,std::string>(splited[0], "")] = splited[1];
+    else if (splited.size() == 3)
+      edges[std::pair<std::string,std::string>(splited[0], splited[1])] = splited[2];
+    else
+      util::myThrow(fmt::format("Invalid strategy line '{}'", lines[i]));
+  }
+}
+
+std::pair<std::string, int> Strategy::getMovement(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(), ""));
+
+  if (foundSpecific != edges.end())
+    return {foundSpecific->second, 1};
+
+  if (foundGeneric != edges.end())
+    return {foundGeneric->second, 1};
+
+  util::myThrow(fmt::format("no suitable movement found for current state '{}' and transition '{}'", c.getState(), transition));
+
+  return {"", 0};
+}
 
-- 
GitLab