Kaynağa Gözat

Galaxy updated to use yaml for saving.

This required changes to test-galaxy.
(so it would understand yaml, and so it would understand
BUGZ_LOG()).

Right now, we're able to load data (I saw it load), but
the save is messed up.  I think I'm going to get away from
the weird way of doing it, and stick with something simpler.

Weird way being encode/decode for Galaxy object.

I don't want to have to declare an operator= for galaxy.
Steve Thielemann 3 yıl önce
ebeveyn
işleme
06d3ef69c1
11 değiştirilmiş dosya ile 276 ekleme ve 20 silme
  1. 3 2
      CMakeLists.txt
  2. 37 1
      director.cpp
  3. 4 1
      director.h
  4. 165 0
      galaxy.cpp
  5. 24 1
      galaxy.h
  6. 1 1
      logging.h
  7. 1 0
      pch.hpp
  8. 5 14
      session.cpp
  9. 9 0
      test-galaxy.cpp
  10. 22 0
      utils.cpp
  11. 5 0
      utils.h

+ 3 - 2
CMakeLists.txt

@@ -55,9 +55,10 @@ 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)
+add_executable(test-galaxy test-galaxy.cpp galaxy.cpp utils.cpp)
 add_dependencies(test-galaxy gtest)
-target_link_libraries(test-galaxy gtest_main)
+## target_link_libraries(test-galaxy gtest_main)
+target_link_libraries(test-galaxy gtest_main ${Boost_LIBRARIES} yaml-cpp)
 
 enable_testing()
 add_test(NAME test-galaxy

+ 37 - 1
director.cpp

@@ -109,6 +109,7 @@ void Director::server_line(const std::string &line,
     to_client("\rTradeWars Proxy v2++ READY (~ or ESC to activate)\n\r");
     if (game) {
       // TODO:  Save galaxy data
+      galaxy.save();
     }
     game = 0;
     // reset "active game" -- we're at the TWGS main menu
@@ -120,11 +121,15 @@ void Director::server_line(const std::string &line,
       game = ch;
       BUGZ_LOG(warning) << "GAME " << game << " activated!";
       // TODO:  Load game data
+      galaxy.game = game;
+      galaxy.username = username;
+      galaxy.load();
     }
     // not needed (handled by above Game Server check).
     if (ch == 'Q') {
       if (game) {
         // TODO:  Save galaxy data
+        galaxy.save();
       }
       game = 0;
     }
@@ -150,6 +155,22 @@ void Director::server_line(const std::string &line,
    This is where all of the server lines are gleaned for all the
    information that we can get out of them.
 
+    // When activating the computer 
+    SP: [Command [TL=00:00:00]:[926] (?=Help)? : ]
+    Sector: 926
+    CI: [c]
+    SL: [Command [TL=00:00:00]:[926] (?=Help)? : C]
+    SL: [<Computer>]
+    SL: []
+    SL: [<Computer activated>]
+    SL: []
+    SP: [Computer command [TL=00:00:00]:[926] (?=Help)? ]
+
+    // deactivating the computer
+    SL: [Computer command [TL=00:00:00]:[926] (?=Help)? Q]
+    SL: []
+    SL: [<Computer deactivated>]
+    SL: []
     */
 
     if (startswith(line, " Items     Status  Trading % of max OnBoard"))
@@ -342,7 +363,7 @@ void Director::SL_cimline(const std::string &line) {
       }
     }
     BUGZ_LOG(fatal) << "warpcim: " << sw;
-
+    galaxy.add_warp(sw);
   } else {
     // portcim
     struct port p = parse_portcim(line);
@@ -350,6 +371,7 @@ void Director::SL_cimline(const std::string &line) {
       BUGZ_LOG(fatal) << "portcim:  FAIL [" << line << "]";
     else
       BUGZ_LOG(fatal) << "portcim: " << p;
+    galaxy.add_port(p);
   }
 }
 
@@ -407,6 +429,7 @@ void Director::SL_sectorline(const std::string &line) {
        sw.add(stoi(w));
      }
      BUGZ_LOG(fatal) << "WARPS: " << sw;
+     galaxy.add_warp(sw);
    }
   }
 }
@@ -416,6 +439,19 @@ void Director::SL_portline(const std::string &line) {
     SL_parser = nullptr;
     return;
   }
+  /*
+  SL: [ Items     Status  Trading % of max OnBoard]
+  SL: [ -----     ------  ------- -------- -------]
+  SL: [Fuel Ore   Buying    3000    100%       0]
+  SL: [Organics   Buying    3000    100%       0]
+  SL: [Equipment  Buying    3000    100%       0]
+  SL: []
+  SL: [Commerce report for: 03:51:56 PM Mon Oct 24, 2033     You can buy:]
+  SL: [A  Cargo holds     :    650 credits / next hold                0]
+  SL: [B  Fighters        :    233 credits per fighter               75]
+  SL: [C  Shield Points   :    116 credits per point                100]
+  SL: []
+   */
   BUGZ_LOG(info) << "portline : " << line;
   if (in(line, "%")) {
   // size_t pos = line.find('%');

+ 4 - 1
director.h

@@ -1,6 +1,7 @@
 #ifndef DIRECTOR_H
 #define DIRECTOR_H
 #include "session_common.h"
+#include "galaxy.h"
 
 class Dispatch;
 
@@ -47,7 +48,9 @@ class Director {
   int count;
 
   int current_sector;
-  
+  Galaxy galaxy;
+  std::string username;
+
  private:
   StringFunc SL_parser;
   StringFunc SF_cimline, SF_sectorline, SF_portline, SF_warpline;

+ 165 - 0
galaxy.cpp

@@ -1,9 +1,15 @@
 #include "galaxy.h"
 
+#include <algorithm>  // sort
 #include <boost/format.hpp>
 #include <exception>
 #include <ostream>
+#include <set>
 #include <string>
+#include <fstream>
+
+#include "logging.h"
+#include "yaml-cpp/yaml.h"
 
 // c++ default exceptions list
 // https://en.cppreference.com/w/cpp/error/exception
@@ -66,6 +72,43 @@ std::ostream &operator<<(std::ostream &os, const sector_warps &warps) {
   }
   return os;
 }
+
+bool sector_sort(sector_type st1, sector_type st2) {
+  /* Sort sectors, put 0's at the end. */
+  if (st1 == 0) return false;
+  if (st2 == 0) return false;
+  return (st1 < st2);
+}
+
+void sector_warps::sort(void) {
+  std::sort(&warps[0], &warps[MAX_WARPS], sector_sort);
+}
+
+bool sector_warps::operator==(const sector_warps &rhs) const {
+  /*
+  Comapre if the sector_warps are the same.
+  They do not need to be in the same order.
+  */
+  std::set<sector_type> contains;
+  if (sector == rhs.sector) {
+    int x;
+    for (x = 0; x < MAX_WARPS; ++x) {
+      if (warps[x] == 0) break;
+      contains.insert(warps[x]);
+    }
+    for (x = 0; x < MAX_WARPS; ++x) {
+      if (warps[0] == 0) break;
+      auto pos = contains.find(rhs.warps[x]);
+      if (pos == contains.end()) return false;
+      contains.erase(pos);
+    }
+    return contains.empty();
+  }
+
+  // sector number doesn't match!
+  return false;
+}
+
 #define GTEST_COUT std::cerr << "[          ] [ INFO ]"
 // #define GTEST_DEBUG
 
@@ -140,3 +183,125 @@ struct port parse_portcim(const std::string line) {
     return p;
   }
 }
+
+Galaxy::Galaxy() {}
+Galaxy::~Galaxy() { BUGZ_LOG(fatal) << "Galaxy::~Galaxy()"; }
+
+void Galaxy::add_warp(sector_warps sw) {
+  auto pos = warps.find(sw.sector);
+
+  if (pos == warps.end()) {
+    // not found
+    sw.sort();
+    warps[sw.sector] = sw;
+    BUGZ_LOG(info) << "add_warp NEW " << sw.sector;
+  } else {
+    // found!
+    if (pos->second == sw) {
+      BUGZ_LOG(trace) << "add_warp: Yup, I already know about " << sw.sector;
+    } else {
+      BUGZ_LOG(info) << "add_warp:  Warps don't match! Updating...";
+      BUGZ_LOG(warning) << "Have: " << pos->second;
+      BUGZ_LOG(warning) << "Got : " << sw;
+      warps[sw.sector] = sw;
+    }
+  }
+}
+
+void Galaxy::add_port(sector_type sector, int port_class) {}
+void Galaxy::add_port(port p) {}
+
+namespace YAML {
+template <>
+struct convert<Galaxy> {
+  static Node encode(const Galaxy &rhs) {
+    Node node;
+    for (auto const &config_iter : rhs.config) {
+      node["config"][config_iter.first] = config_iter.second;
+    }
+
+    for (auto const &warp : rhs.warps) {
+      for (int x = 0; x < MAX_WARPS; ++x) {
+        if (warp.second.warps[x] == 0) break;
+        node["warps"][warp.first].push_back(warp.second.warps[x]);
+      }
+    }
+
+    /*
+    node.push_back(rhs.x);
+    node.push_back(rhs.y);
+    node.push_back(rhs.z);
+    return node;
+    */
+    return node;
+  }
+
+  static bool decode(const Node &node, Galaxy &rhs) {
+    if (!node.IsMap()) return false;
+    if (node["config"]) {
+    } else {
+      BUGZ_LOG(fatal) << "YAML missing config section.";
+    }
+    if (node["ports"]) {
+    } else {
+      BUGZ_LOG(fatal) << "YAML missing ports section.";
+    }
+
+    if (node["warps"]) {
+      const Node &warps = node["warps"];
+      if (warps.IsMap()) {
+        for (auto const warp_iter : warps) {
+          sector_warps sw;
+          sw.sector = warp_iter.first.as<int>();
+          for (auto const sector_iter : warp_iter.second) {
+            sw.add(sector_iter.as<int>());
+          }
+          BUGZ_LOG(fatal) << "YAML warp: " << sw;
+          rhs.add_warp(sw);
+        }
+      }
+    } else {
+      BUGZ_LOG(fatal) << "YAML missing warps section.";
+    }
+    /*
+    if(!node.IsSequence() || node.size() != 3) {
+      return false;
+    }
+
+    rhs.x = node[0].as<double>();
+    rhs.y = node[1].as<double>();
+    rhs.z = node[2].as<double>();
+    */
+    return true;
+  }
+};
+}  // namespace YAML
+
+void Galaxy::load(void) {
+  std::string filename =
+      str(boost::format("galaxy-%1%-%2%.json") % game % username);
+  // reset ?
+  config.clear();
+  ports.clear();
+  warps.clear();
+  if (file_exists(filename)) {
+    YAML::Node data = YAML::LoadFile(filename);
+    Galaxy g = data["galaxy"].as<Galaxy>();
+    BUGZ_LOG(fatal) << "YAML: config keys: " << g.config.size();
+    BUGZ_LOG(fatal) << "YAML:   warp keys: " << g.warps.size();
+    BUGZ_LOG(fatal) << "YAML:   port keys: " << g.ports.size();
+    // *this = data.as<Galaxy>();
+  } else {
+    BUGZ_LOG(fatal) << "Missing YAML: " << filename;
+  }
+}
+
+void Galaxy::save(void) {
+  std::string filename =
+      str(boost::format("galaxy-%1%-%2%.json") % game % username);
+  YAML::Node data;
+  data["galaxy"] = *this;
+  std::ofstream fout(filename);
+  fout << data << std::endl;
+  BUGZ_LOG(fatal) << "YAML: " << filename;
+}

+ 24 - 1
galaxy.h

@@ -1,3 +1,6 @@
+#ifndef GALAXY_H
+#define GALAXY_H
+
 #include <array>
 #include <cstdint>
 #include <iostream>
@@ -7,6 +10,7 @@
 #include <string>
 #include <vector>
 
+
 enum PRODUCT { FUEL = 0, ORG = 1, EQUIP = 2 };
 
 // Class 0 : Special
@@ -43,6 +47,8 @@ struct sector_warps {
   void add(sector_type sector);
   // add() that adds warp to end of warps?
   friend std::ostream& operator<<(std::ostream& os, const sector_warps& warps);
+  bool operator==(const sector_warps& rhs) const;
+  void sort(void);
 };
 
 /*
@@ -156,9 +162,26 @@ struct port parse_portcim(const std::string line);
 // SPECIAL = 0
 // STARDOCK = 9
 
-class GameData {
+class Galaxy {
  public:
+ Galaxy();
+ ~Galaxy();
+
   std::map<std::string, std::string> config;
   // warps;
   // ports;
+  std::map<sector_type, port> ports;
+  std::map<sector_type, sector_warps> warps;
+
+  void add_warp(sector_warps);
+  void add_port(sector_type sector, int port_class);
+  void add_port(port);
+
+  void save(void);
+  void load(void);
+
+  char game;
+  std::string username;
 };
+
+#endif

+ 1 - 1
logging.h

@@ -1,7 +1,7 @@
 #include <boost/log/trivial.hpp>
 #include <iomanip>
 
-const char *trim_path(const char *filepath);
+#include "utils.h"
 
 #define BUGZ_LOG(severity)                                                     \
   BOOST_LOG_TRIVIAL(severity)                                                  \

+ 1 - 0
pch.hpp

@@ -13,3 +13,4 @@
 #include <iomanip>
 #include <string>
 #include <map>
+#include "yaml-cpp/yaml.h"

+ 5 - 14
session.cpp

@@ -39,6 +39,9 @@ Session::Session(boost::asio::ip::tcp::socket socket,
   director.to_server = boost::bind(&Session::to_server, this, _1);
   director.to_client = boost::bind(&Session::to_client, this, _1);
   director.post = boost::bind(&Session::post, this, _1);
+  
+  // too soon!
+  // director.username = rlogin_name;
 
   // replace emit_ with below:  if (director.server_line)
   // director.server_line(s);
@@ -97,6 +100,7 @@ void Session::parse_auth(void) {
     rlogin_name = rlogin_auth.c_str() + 1;
   else
     rlogin_name = "?";
+  director.username = rlogin_name;
 }
 
 void Session::on_connect(const boost::system::error_code error) {
@@ -751,17 +755,4 @@ void Server::do_accept(void) {
   });
 }
 
-/**
- * Clean up the trailing ../ in __FILE__
- *
- * This is used by the logging macro.
- *
- * @param filepath
- * @return const char*
- */
-const char *trim_path(const char *filepath) {
-  if (strncmp(filepath, "../", 3) == 0) {
-    filepath += 3;
-  }
-  return filepath;
-}
+

+ 9 - 0
test-galaxy.cpp

@@ -8,6 +8,15 @@
 #include <string>
 #include <vector>
 
+/*
+
+How can I add logging, but not really add/use it?
+
+*/
+
+
+
+
 #define GTEST_COUT std::cerr << "[          ] [ INFO ]"
 
 namespace {

+ 22 - 0
utils.cpp

@@ -4,6 +4,28 @@
 #include <string>
 #include <vector>
 
+/**
+ * Clean up the trailing ../ in __FILE__
+ *
+ * This is used by the logging macro.
+ *
+ * @param filepath
+ * @return const char*
+ */
+const char *trim_path(const char *filepath) {
+  if (strncmp(filepath, "../", 3) == 0) {
+    filepath += 3;
+  }
+  return filepath;
+}
+
+#include <fstream>
+
+bool file_exists(const std::string &name) {
+  std::ifstream f(name.c_str());
+  return f.good();
+}
+
 bool replace(std::string &str, const std::string &from, const std::string &to) {
   size_t start_pos = str.find(from);
   if (start_pos == std::string::npos) return false;

+ 5 - 0
utils.h

@@ -5,6 +5,8 @@
 #include <regex>
 #include <vector>
 
+const char *trim_path(const char *filepath);
+
 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);
@@ -17,4 +19,7 @@ bool startswith(const std::string &line, const std::string &has);
 bool endswith(const std::string &line, const std::string &has);
 bool in(const std::string &line, const std::string &has);
 std::string repr(const std::string &source);
+
+bool file_exists(const std::string &name);
+
 #endif