Browse Source

Initial setup of scripts.

Steve Thielemann 3 years ago
parent
commit
9e17ed53d6
12 changed files with 383 additions and 182 deletions
  1. 2 2
      CMakeLists.txt
  2. 21 0
      buysell.cpp
  3. 155 0
      buysell.h
  4. 107 9
      director.cpp
  5. 21 4
      director.h
  6. 0 19
      galaxy.cpp
  7. 1 147
      galaxy.h
  8. 3 1
      logging.h
  9. 34 0
      scripts.cpp
  10. 31 0
      scripts.h
  11. 7 0
      utils.cpp
  12. 1 0
      utils.h

+ 2 - 2
CMakeLists.txt

@@ -55,7 +55,7 @@ option(gtest_build_samples "Build gtest's sample programs." OFF)
 option(gtest_disable_pthreads "Disable uses of pthreads in gtest." OFF)
 
 ### TESTS
-add_executable(test-galaxy test-galaxy.cpp galaxy.cpp utils.cpp)
+add_executable(test-galaxy test-galaxy.cpp galaxy.cpp utils.cpp buysell.cpp)
 add_dependencies(test-galaxy gtest)
 ## target_link_libraries(test-galaxy gtest_main)
 target_link_libraries(test-galaxy gtest_main ${Boost_LIBRARIES} yaml-cpp)
@@ -66,7 +66,7 @@ add_test(NAME test-galaxy
 
 
 # dispatchers.cpp 
-ADD_EXECUTABLE( twproxy twproxy.cpp utils.cpp session.cpp boxes.cpp director.cpp galaxy.cpp dispatchers.cpp )
+ADD_EXECUTABLE( twproxy twproxy.cpp utils.cpp session.cpp boxes.cpp director.cpp galaxy.cpp dispatchers.cpp scripts.cpp buysell.cpp )
 TARGET_LINK_LIBRARIES( twproxy ${Boost_LIBRARIES} pthread yaml-cpp)
 
 target_precompile_headers(twproxy PRIVATE pch.hpp)

+ 21 - 0
buysell.cpp

@@ -0,0 +1,21 @@
+#include "buysell.h"
+
+bool buysell::operator==(const buysell &rhs) const {
+  return ((foe[0] == rhs.foe[0]) && (foe[1] == rhs.foe[1]) &&
+          (foe[2] == rhs.foe[2]));
+}
+
+std::ostream &operator<<(std::ostream &os, const buysell &bs) {
+  os << bs.foe[0] << bs.foe[1] << bs.foe[2];
+  return os;
+}
+
+bool buysell_text::operator==(const buysell_text &rhs) const {
+  return ((txt[0] == rhs.txt[0]) && (txt[1] == rhs.txt[1]) &&
+          (txt[2] == rhs.txt[2]));
+}
+
+std::ostream &operator<<(std::ostream &os, const buysell_text &bst) {
+  os << '"' << bst.txt[0] << bst.txt[1] << bst.txt[2] << '"';
+  return os;
+}

+ 155 - 0
buysell.h

@@ -0,0 +1,155 @@
+#ifndef BUYSELL_H
+#define BUYSELL_H
+
+#include <iostream>
+
+typedef uint8_t port_type;
+
+enum PRODUCT { FUEL = 0, ORG = 1, EQU = 2 };
+
+// Class 0 : Special
+// Class 9 : StarDock BBB
+
+// typedef std::array<bool, 3> buysell;
+struct buysell {
+  bool foe[3];
+  bool operator==(const buysell& rhs) const;
+  friend std::ostream& operator<<(std::ostream& os, const buysell& bs);
+};
+
+// ostream& operator<<(std::ostream& os, const buysell& bs);
+
+// typedef std::array<char, 3> buysell_text;
+struct buysell_text {
+  char txt[3];
+  bool operator==(const buysell_text& rhs) const;
+  friend std::ostream& operator<<(std::ostream& os, const buysell_text& bst);
+};
+
+/*
+1 : "BBS", TTF
+2 : "BSB", TFT
+3 : "SBB", FTT
+4 : "SSB", FFT
+5 : "SBS", FTF
+6 : "BSS", TFF
+7 : "SSS", FFF
+8 : "BBB", TTT
+9 : "BBB", TTT
+*/
+
+/* convert type to buysell flag values, buy = true */
+
+constexpr buysell get_buysell(port_type type) {
+  switch (type) {
+    case 1:  // BBS TTF
+      return {true, true, false};
+    case 2:  // BSB TFT
+      return {true, false, true};
+    case 3:  // SBB FTT
+      return {false, true, true};
+    case 4:  // SSB FFT
+      return {false, false, true};
+    case 5:  // SBS FTF
+      return {false, true, false};
+    case 6:  // BSS TFF
+      return {true, false, false};
+    case 7:  // SSS FFF
+      return {false, false, false};
+    case 8:  // BBB TTT
+    case 9:
+      return {true, true, true};
+    default:
+      throw std::invalid_argument("invalid buysell type");
+  }
+}
+
+constexpr buysell_text text_from_buysell(const buysell market) {
+  buysell_text text{'?', '?', '?'};
+  for (int x = 0; x < 3; ++x) {
+    text.txt[x] = market.foe[x] ? 'B' : 'S';
+  }
+  return text;
+}
+
+constexpr buysell_text text_from_type(port_type type) {
+  switch (type) {
+    case 1:
+      return buysell_text{'B', 'B', 'S'};
+    case 2:
+      return buysell_text{'B', 'S', 'B'};
+    case 3:
+      return buysell_text{'S', 'B', 'B'};
+    case 4:
+      return buysell_text{'S', 'S', 'B'};
+    case 5:
+      return buysell_text{'S', 'B', 'S'};
+    case 6:
+      return buysell_text{'B', 'S', 'S'};
+    case 7:
+      return buysell_text{'S', 'S', 'S'};
+    case 8:
+    case 9:
+      return buysell_text{'B', 'B', 'B'};
+    default:
+      throw std::invalid_argument("invalid text_from_type type");
+  }
+}
+
+constexpr uint8_t type_from_buysell(const buysell market) {
+  if (market.foe[0]) {
+    if (market.foe[1]) {
+      if (market.foe[2]) {
+        return 8;  // BBB TTT
+      } else
+        return 1;  // BBS TTF
+    } else {
+      if (market.foe[2]) {
+        return 2;  // BSB TFT
+      } else
+        return 6;  // BSS TFF
+    }
+  } else {
+    if (market.foe[1]) {
+      if (market.foe[2]) {
+        return 3;  // SBB FTT
+      } else
+        return 5;  // SBS FTF
+    } else {
+      if (market.foe[2]) {
+        return 4;  // SSB FFT
+      } else
+        return 7;  // SSS FFF
+    }
+  }
+}
+
+constexpr buysell invert_buysell(const buysell market) {
+  if (market.foe[0]) {
+    if (market.foe[1]) {
+      if (market.foe[2]) {
+        return {false, false, false};  // BBB TTT
+      } else
+        return {false, false, true};  // BBS TTF
+    } else {
+      if (market.foe[2]) {
+        return {false, true, false};  // BSB TFT
+      } else
+        return {false, true, true};  // BSS TFF
+    }
+  } else {
+    if (market.foe[1]) {
+      if (market.foe[2]) {
+        return {true, false, false};  // SBB FTT
+      } else
+        return {true, false, true};  // SBS FTF
+    } else {
+      if (market.foe[2]) {
+        return {true, true, false};  // SSB FFT
+      } else
+        return {true, true, true};  // SSS FFF
+    }
+  }
+}
+
+#endif

+ 107 - 9
director.cpp

@@ -5,6 +5,7 @@
 #include "boxes.h"
 #include "galaxy.h"
 #include "logging.h"
+#include "scripts.h"
 #include "utils.h"
 
 Director::Director() {
@@ -30,7 +31,7 @@ Director::Director() {
   SF_sectorline = [this](const std::string &s) { this->SL_sectorline(s); };
   SF_portline = [this](const std::string &s) { this->SL_portline(s); };
   SF_warpline = [this](const std::string &s) { this->SL_warpline(s); };
-
+  SF_infoline = [this](const std::string &s) { this->SL_infoline(s); };
   build_menu();
 }
 
@@ -197,6 +198,7 @@ void Director::server_line(const std::string &line,
       SL_parser = SF_portline;
     if (startswith(line, "Sector  : ")) SL_parser = SF_sectorline;
     if (line == ": ") SL_parser = SF_cimline;
+    if (line == "<Info>") SL_parser = SF_infoline;
   }
 
   if (SL_parser) {
@@ -257,7 +259,7 @@ void Director::build_menu(void) {
       "\x1b[32;40mGREEN\x1b[30;42m\xdb\xb2\xb1\xb0 \x1b[0m : ";
   md->lazy = true;
   md->menu = {{"C", "Configure"},
-              {"D", "Display Report"},
+              // {"D", "Display Report"},
               {"E", "Export Data/Save"},
               {"I", "Information"},
               {"P", "Port CIM"},
@@ -329,7 +331,7 @@ void Director::menu_choice(void) {
           config_edit();
           return;
           break;
-        case 'D':  // display report
+        case 'T':  // display trading report
         {
           auto pptv = galaxy.find_best_trades();
           std::string output;
@@ -393,10 +395,15 @@ void Director::menu_choice(void) {
           chain->activate();
           return;
           break;
-        case 'T':  // Trading Report
-          break;
+        // case 'T':  // Trading Report
+        //  break;
         case 'S':  // Scripts
-          break;
+        {
+          init_scripts_menu();
+          chain = scripts_menu;
+          chain->activate();
+          return;
+        } break;
         case 'X':  // Exit
           proxy_deactivate();
           return;
@@ -411,6 +418,71 @@ void Director::menu_choice(void) {
     }
   }
 }
+
+MenuDispatch *Director::init_scripts_menu(void) {
+  MenuDispatch *md;
+  if (scripts_menu) {
+    md = dynamic_cast<MenuDispatch *>(&(*scripts_menu));
+    return md;
+  } else {
+    scripts_menu = std::make_shared<MenuDispatch>(*this);
+    md = static_cast<MenuDispatch *>(&(*scripts_menu));
+    md->menu_box_color = "\x1b[0;32;40m";
+    md->menu_text_color = "\x1b[1;32;40m";
+    md->menu_title = "Scripts Menu";
+    md->menu_options_color = "\x1b[1;32;40m";
+    md->lazy = false;
+    md->menu_prompt = " SCRIPT : ";
+    md->menu = {{"!", "Terror"}, {"T", "Trade"}, {"U", "Upgrade Planet Pants"}};
+    md->setNotify([this]() { this->scripts_done(); });
+    return md;
+  }
+}
+
+void Director::scripts_done(void) {
+  // Was script selected?  If so, run it!
+  // otherwise, back to the menu we go...
+  MenuDispatch *md = dynamic_cast<MenuDispatch *>(&(*scripts_menu));
+  if (md) {
+    if (md->input.empty()) {
+      to_client("Scripts aborted.\n\r");
+      scripts_menu.reset();
+      proxy_deactivate();
+      return;
+    } else {
+      switch (md->input[0]) {
+        case 'T':  // Trade
+          script = std::make_shared<ScriptTrader>(*this);
+          ScriptTrader *ts = static_cast<ScriptTrader *>(&((*script)));
+          chain = script;
+          // Set parameters
+          auto found = galaxy.find_trades(current_sector, false);
+          if (found.empty()) {
+            to_client(
+                "No Trades found.  Port burnt (CONFIG: lower burnt_percent?) "
+                "or no ports around.\n\r");
+            proxy_deactivate();
+            return;
+          }
+          ts->port[0] = found[0].s1;
+          ts->port[1] = found[0].s2;
+          ts->type = found[0].type;
+          chain->activate();
+          return;
+          break;
+      }
+    }
+  }
+
+  proxy_activate();
+
+  // And to end scripts, we do .. what exactly?
+  // DEBUG:  Ok, why does everything work OK if I reset the scripts_menu here??
+  // probably do want to destroy scripts here.  ;)
+  // scripts_menu.reset();
+  // proxy_deactivate();
+}
+
 /**
  * @brief Setup Config Input
  *
@@ -454,7 +526,7 @@ void Director::config_edit(void) {
     to_client(output);
     ++item;
   }
-  to_client("Enter number to edit.\n\r");
+  to_client("Enter number to edit, blank to exit.\n\r");
 
   // setup call to config_input:
   InputDispatch *id = init_config_input();
@@ -523,13 +595,11 @@ void Director::config_have_input(void) {
     // This is a config item edit
     if (id->input.empty()) {
       to_client("No change.\n\r");
-      // cleared by init config_item.clear();
       config_edit();
       return;
     } else {
       BUGZ_LOG(fatal) << "Config EDIT: " << config_item << " = " << id->input;
       galaxy.config[config_item] = id->input;
-      // cleared by init config_item.clear();
       config_edit();
       return;
     }
@@ -744,4 +814,32 @@ void Director::SL_warpline(const std::string &line) {
 
   // process warp line
   BUGZ_LOG(fatal) << "warpline: [" << line << "]";
+}
+
+void Director::SL_infoline(const std::string &line) {
+  static int state;
+
+  if (line == "<Info>") {
+    state = 0;
+    galaxy.meta["info"] = YAML::Node();
+  }
+  if (line.empty()) {
+    ++state;
+    if (state == 2) {
+      SL_parser = nullptr;
+      // process the parsed information in meta["info"]
+    }
+    return;
+  }
+
+  // info to parse:
+  size_t pos = line.find(" : ");
+  if (pos != line.npos) {
+    std::string key = line.substr(0, pos);
+    std::string value = line.substr(pos + 3);
+    trim(key);
+    trim(value);
+    galaxy.meta["info"][key] = value;
+    BUGZ_LOG(fatal) << "Info: " << key << " : " << value;
+  }
 }

+ 21 - 4
director.h

@@ -1,13 +1,23 @@
 #ifndef DIRECTOR_H
 #define DIRECTOR_H
-#include "session_common.h"
 #include "galaxy.h"
+#include "session_common.h"
 
 class Dispatch;
+class MenuDispatch;
 class InputDispatch;
 
 class Director {
  public:
+  /**
+   * This dispatches client_input, server_line and server_prompt.
+   *
+   * Set chain.setNotify() to get a response when it is done.
+   * activate() to begin the chain.
+   *
+   * The chain has to_client, to_server functions that dispatch to those
+   * functions in Dispatch/Director/Session.
+   */
   std::shared_ptr<Dispatch> chain;
 
   StringFunc to_client;
@@ -56,26 +66,33 @@ class Director {
   std::shared_ptr<Dispatch> main_menu;
   std::shared_ptr<Dispatch> cim;
   std::shared_ptr<Dispatch> config_input;
+  std::shared_ptr<Dispatch> scripts_menu;
+  std::shared_ptr<Dispatch> script;
+
+  InputDispatch *init_config_input(void);
+  MenuDispatch *init_scripts_menu(void);
 
   // notifications
   void have_input(void);
   void menu_choice(void);
   void cim_done(void);
+  void scripts_done(void);
 
   void information(void);
+
   void config_edit(void);
   void config_have_input(void);
-  InputDispatch * init_config_input(void);
-  std::string config_item; // current item being edited
+  std::string config_item;  // current item being edited
 
   StringFunc SL_parser;
-  StringFunc SF_cimline, SF_sectorline, SF_portline, SF_warpline;
+  StringFunc SF_cimline, SF_sectorline, SF_portline, SF_warpline, SF_infoline;
 
   void SL_cimline(const std::string &line);
   void SL_thiefline(const std::string &line);
   void SL_sectorline(const std::string &line);
   void SL_portline(const std::string &line);
   void SL_warpline(const std::string &line);
+  void SL_infoline(const std::string &line);
 };
 
 #include "dispatchers.h"

+ 0 - 19
galaxy.cpp

@@ -15,25 +15,6 @@
 // c++ default exceptions list
 // https://en.cppreference.com/w/cpp/error/exception
 
-bool buysell::operator==(const buysell &rhs) const {
-  return ((foe[0] == rhs.foe[0]) && (foe[1] == rhs.foe[1]) &&
-          (foe[2] == rhs.foe[2]));
-}
-
-std::ostream &operator<<(std::ostream &os, const buysell &bs) {
-  os << bs.foe[0] << bs.foe[1] << bs.foe[2];
-  return os;
-}
-
-bool buysell_text::operator==(const buysell_text &rhs) const {
-  return ((txt[0] == rhs.txt[0]) && (txt[1] == rhs.txt[1]) &&
-          (txt[2] == rhs.txt[2]));
-}
-
-std::ostream &operator<<(std::ostream &os, const buysell_text &bst) {
-  os << '"' << bst.txt[0] << bst.txt[1] << bst.txt[2] << '"';
-  return os;
-}
 
 std::ostream &operator<<(std::ostream &os, const port &p) {
   if (p.type == 0) {

+ 1 - 147
galaxy.h

@@ -11,33 +11,12 @@
 #include <string>
 #include <vector>
 
+#include "buysell.h"
 #include "yaml-cpp/yaml.h"
 
-enum PRODUCT { FUEL = 0, ORG = 1, EQU = 2 };
-
-// Class 0 : Special
-// Class 9 : StarDock BBB
-
-// typedef std::array<bool, 3> buysell;
-struct buysell {
-  bool foe[3];
-  bool operator==(const buysell& rhs) const;
-  friend std::ostream& operator<<(std::ostream& os, const buysell& bs);
-};
-
-// ostream& operator<<(std::ostream& os, const buysell& bs);
-
-// typedef std::array<char, 3> buysell_text;
-struct buysell_text {
-  char txt[3];
-  bool operator==(const buysell_text& rhs) const;
-  friend std::ostream& operator<<(std::ostream& os, const buysell_text& bst);
-};
-
 // #define MAX_WARPS 6
 
 typedef uint16_t sector_type;
-typedef uint8_t port_type;
 
 struct sector_warps {
   sector_type sector;  // Yes, for debug
@@ -55,104 +34,6 @@ struct sector_warps {
   // void sort(void);
 };
 
-/*
-1 : "BBS", TTF
-2 : "BSB", TFT
-3 : "SBB", FTT
-4 : "SSB", FFT
-5 : "SBS", FTF
-6 : "BSS", TFF
-7 : "SSS", FFF
-8 : "BBB", TTT
-9 : "BBB", TTT
-*/
-
-/* convert type to buysell flag values, buy = true */
-
-constexpr buysell get_buysell(port_type type) {
-  switch (type) {
-    case 1:  // BBS TTF
-      return {true, true, false};
-    case 2:  // BSB TFT
-      return {true, false, true};
-    case 3:  // SBB FTT
-      return {false, true, true};
-    case 4:  // SSB FFT
-      return {false, false, true};
-    case 5:  // SBS FTF
-      return {false, true, false};
-    case 6:  // BSS TFF
-      return {true, false, false};
-    case 7:  // SSS FFF
-      return {false, false, false};
-    case 8:  // BBB TTT
-    case 9:
-      return {true, true, true};
-    default:
-      throw std::invalid_argument("invalid buysell type");
-  }
-}
-
-constexpr buysell_text text_from_buysell(const buysell market) {
-  buysell_text text{'?', '?', '?'};
-  for (int x = 0; x < 3; ++x) {
-    text.txt[x] = market.foe[x] ? 'B' : 'S';
-  }
-  return text;
-}
-
-constexpr buysell_text text_from_type(port_type type) {
-  switch (type) {
-    case 1:
-      return buysell_text{'B', 'B', 'S'};
-    case 2:
-      return buysell_text{'B', 'S', 'B'};
-    case 3:
-      return buysell_text{'S', 'B', 'B'};
-    case 4:
-      return buysell_text{'S', 'S', 'B'};
-    case 5:
-      return buysell_text{'S', 'B', 'S'};
-    case 6:
-      return buysell_text{'B', 'S', 'S'};
-    case 7:
-      return buysell_text{'S', 'S', 'S'};
-    case 8:
-    case 9:
-      return buysell_text{'B', 'B', 'B'};
-    default:
-      throw std::invalid_argument("invalid text_from_type type");
-  }
-}
-
-constexpr buysell invert_buysell(const buysell market) {
-  if (market.foe[0]) {
-    if (market.foe[1]) {
-      if (market.foe[2]) {
-        return {false, false, false};  // BBB TTT
-      } else
-        return {false, false, true};  // BBS TTF
-    } else {
-      if (market.foe[2]) {
-        return {false, true, false};  // BSB TFT
-      } else
-        return {false, true, true};  // BSS TFF
-    }
-  } else {
-    if (market.foe[1]) {
-      if (market.foe[2]) {
-        return {true, false, false};  // SBB FTT
-      } else
-        return {true, false, true};  // SBS FTF
-    } else {
-      if (market.foe[2]) {
-        return {true, true, false};  // SSB FFT
-      } else
-        return {true, true, true};  // SSS FFF
-    }
-  }
-}
-
 /**
  * Find possible trades with these two port types
  *
@@ -180,33 +61,6 @@ struct port_pair_type {
   sector_type s1, s2;
 };
 
-constexpr uint8_t type_from_buysell(const buysell market) {
-  if (market.foe[0]) {
-    if (market.foe[1]) {
-      if (market.foe[2]) {
-        return 8;  // BBB TTT
-      } else
-        return 1;  // BBS TTF
-    } else {
-      if (market.foe[2]) {
-        return 2;  // BSB TFT
-      } else
-        return 6;  // BSS TFF
-    }
-  } else {
-    if (market.foe[1]) {
-      if (market.foe[2]) {
-        return 3;  // SBB FTT
-      } else
-        return 5;  // SBS FTF
-    } else {
-      if (market.foe[2]) {
-        return 4;  // SSB FFT
-      } else
-        return 7;  // SSS FFF
-    }
-  }
-}
 
 struct port {
   sector_type sector;

+ 3 - 1
logging.h

@@ -1,3 +1,5 @@
+#ifndef LOGGING_H
+#define LOGGING_H
 #include <boost/log/trivial.hpp>
 #include <iomanip>
 
@@ -7,4 +9,4 @@
   BOOST_LOG_TRIVIAL(severity)                                                  \
       << "(" << std::setw(15) << trim_path(__FILE__) << ":" << std::setw(4)    \
       << std::left << __LINE__ << ") "
-      
+#endif      

+ 34 - 0
scripts.cpp

@@ -0,0 +1,34 @@
+#include "scripts.h"
+
+#include "logging.h"
+
+ScriptTrader::ScriptTrader(Director &d) : Dispatch(d) {
+  BUGZ_LOG(fatal) << "ScriptTrader()";
+};
+
+ScriptTrader::~ScriptTrader() { BUGZ_LOG(fatal) << "~ScriptTrader()"; }
+
+void ScriptTrader::activate(void) {
+  // ok, lookup port1 port2
+  auto port_info = director.galaxy.ports.find(port[0]);
+
+  int port0_type = port_info->second.type;
+  port_info = director.galaxy.ports.find(port[1]);
+  int port1_type = port_info->second.type;
+  auto ttr = trade_type_info(port0_type, port1_type);
+  trades = ttr.trades;
+  // Ok, what do we do first here?
+  // I - Info
+  to_server("I");
+}
+
+void ScriptTrader::deactivate(void) {}
+
+void ScriptTrader::server_line(const std::string &line,
+                               const std::string &raw_line) {
+  if (line == "<Info>") {
+  }
+}
+
+void ScriptTrader::server_prompt(const std::string &prompt){};
+void ScriptTrader::client_input(const std::string &cinput){};

+ 31 - 0
scripts.h

@@ -0,0 +1,31 @@
+#ifndef SCRIPTS_H
+#define SCRIPTS_H
+
+#include "buysell.h"
+#include "dispatchers.h"
+#include "galaxy.h"
+
+class ScriptTrader : public Dispatch {
+private:
+public:
+  ScriptTrader(Director &);
+  ~ScriptTrader();  
+
+  // information from the find_best_trades function + others.
+  int port[2];
+  int active;
+  int type;
+  buysell trades;
+  buysell port_buysell[2];
+
+  void activate(void) override;
+  void deactivate(void) override;
+
+  // optional here
+  void server_line(const std::string &line,
+                   const std::string &raw_line) override;
+  void server_prompt(const std::string &prompt) override;
+  void client_input(const std::string &cinput) override;
+};
+
+#endif

+ 7 - 0
utils.cpp

@@ -134,3 +134,10 @@ bool endswith(const std::string &line, const std::string &has) {
   if (line.length() < has.length()) return false;
   return (line.substr(line.length() - has.length()) == has);
 }
+
+void trim(std::string &str) {
+  while (str.substr(0,1) == " ")
+    str.erase(0, 1);
+  while (str.substr(str.length() -1) == " ")
+    str.erase(str.length() -1);
+}

+ 1 - 0
utils.h

@@ -11,6 +11,7 @@ bool replace(std::string &str, const std::string &from, const std::string &to);
 bool replace(std::string &str, const char *from, const char *to);
 void ansi_clean(std::string &str);
 void high_ascii(std::string &str);
+void trim(std::string &str);
 std::smatch ansi_newline(const std::string &str);
 std::string clean_string(const std::string &source);
 std::vector<std::string> split(const std::string &line);