Statistics are now saved to disk
authorChristoph Sommer <mail@christoph-sommer.de>
Sun, 15 Apr 2007 22:06:08 +0000 (22:06 +0000)
committerChristoph Sommer <mail@christoph-sommer.de>
Sun, 15 Apr 2007 22:06:08 +0000 (22:06 +0000)
SVN-Revision: 4983

src/scripting/squirrel_util.cpp
src/scripting/squirrel_util.hpp
src/statistics.cpp
src/statistics.hpp
src/worldmap/worldmap.cpp

index f16bb63..d3fde6d 100644 (file)
@@ -389,4 +389,168 @@ HSQUIRRELVM object_to_vm(HSQOBJECT object)
   return object._unVal.pThread;
 }
 
+// begin: serialization functions
+
+void store_float(HSQUIRRELVM vm, const char* name, float val)
+{
+  sq_pushstring(vm, name, -1);
+  sq_pushfloat(vm, val);
+  if(SQ_FAILED(sq_createslot(vm, -3)))
+    throw Scripting::SquirrelError(vm, "Couldn't add float value to table");
+}
+
+void store_int(HSQUIRRELVM vm, const char* name, int val)
+{
+  sq_pushstring(vm, name, -1);
+  sq_pushinteger(vm, val);
+  if(SQ_FAILED(sq_createslot(vm, -3)))
+    throw Scripting::SquirrelError(vm, "Couldn't add int value to table");
+}
+
+void store_string(HSQUIRRELVM vm, const char* name, const std::string& val)
+{
+  sq_pushstring(vm, name, -1);
+  sq_pushstring(vm, val.c_str(), val.length());
+  if(SQ_FAILED(sq_createslot(vm, -3)))
+    throw Scripting::SquirrelError(vm, "Couldn't add float value to table");
+}
+
+void store_bool(HSQUIRRELVM vm, const char* name, bool val)
+{
+  sq_pushstring(vm, name, -1);
+  sq_pushbool(vm, val ? SQTrue : SQFalse);
+  if(SQ_FAILED(sq_createslot(vm, -3)))
+    throw Scripting::SquirrelError(vm, "Couldn't add float value to table");
+}
+
+bool has_float(HSQUIRRELVM vm, const char* name)
+{
+  sq_pushstring(vm, name, -1);
+  if (SQ_FAILED(sq_get(vm, -2))) return false;
+  sq_pop(vm, 1);
+  return true;
+}
+
+bool has_int(HSQUIRRELVM vm, const char* name)
+{
+  return has_float(vm, name);
+}
+
+bool has_string(HSQUIRRELVM vm, const char* name)
+{
+  return has_float(vm, name);
+}
+
+bool has_bool(HSQUIRRELVM vm, const char* name)
+{
+  return has_float(vm, name);
+}
+
+float read_float(HSQUIRRELVM vm, const char* name)
+{
+  sq_pushstring(vm, name, -1);
+  if(SQ_FAILED(sq_get(vm, -2))) {
+    std::ostringstream msg;
+    msg << "Couldn't get float value for '" << name << "' from table";
+    throw Scripting::SquirrelError(vm, msg.str());
+  }
+
+  float result;
+  if(SQ_FAILED(sq_getfloat(vm, -1, &result))) {
+    std::ostringstream msg;
+    msg << "Couldn't get float value for '" << name << "' from table";
+    throw Scripting::SquirrelError(vm, msg.str());
+  }
+  sq_pop(vm, 1);
+
+  return result;
+}
+
+int read_int(HSQUIRRELVM vm, const char* name)
+{
+  sq_pushstring(vm, name, -1);
+  if(SQ_FAILED(sq_get(vm, -2))) {
+    std::ostringstream msg;
+    msg << "Couldn't get int value for '" << name << "' from table";
+    throw Scripting::SquirrelError(vm, msg.str());
+  }
+
+  int result;
+  if(SQ_FAILED(sq_getinteger(vm, -1, &result))) {
+    std::ostringstream msg;
+    msg << "Couldn't get int value for '" << name << "' from table";
+    throw Scripting::SquirrelError(vm, msg.str());
+  }
+  sq_pop(vm, 1);
+
+  return result;
+}
+
+
+std::string read_string(HSQUIRRELVM vm, const char* name)
+{
+  sq_pushstring(vm, name, -1);
+  if(SQ_FAILED(sq_get(vm, -2))) {
+    std::ostringstream msg;
+    msg << "Couldn't get string value for '" << name << "' from table";
+    throw Scripting::SquirrelError(vm, msg.str());
+  }
+
+  const char* result;
+  if(SQ_FAILED(sq_getstring(vm, -1, &result))) {
+    std::ostringstream msg;
+    msg << "Couldn't get string value for '" << name << "' from table";
+    throw Scripting::SquirrelError(vm, msg.str());
+  }
+  sq_pop(vm, 1);
+
+  return std::string(result);
+}
+
+bool read_bool(HSQUIRRELVM vm, const char* name)
+{
+  sq_pushstring(vm, name, -1);
+  if(SQ_FAILED(sq_get(vm, -2))) {
+    std::ostringstream msg;
+    msg << "Couldn't get bool value for '" << name << "' from table";
+    throw Scripting::SquirrelError(vm, msg.str());
+  }
+
+  SQBool result;
+  if(SQ_FAILED(sq_getbool(vm, -1, &result))) {
+    std::ostringstream msg;
+    msg << "Couldn't get bool value for '" << name << "' from table";
+    throw Scripting::SquirrelError(vm, msg.str());
+  }
+  sq_pop(vm, 1);
+
+  return result == SQTrue;
+}
+
+bool get_float(HSQUIRRELVM vm, const char* name, float& val) {
+  if (!has_float(vm, name)) return false;
+  val = read_float(vm, name);
+  return true;
+}
+
+bool get_int(HSQUIRRELVM vm, const char* name, int& val) {
+  if (!has_int(vm, name)) return false;
+  val = read_int(vm, name);
+  return true;
+}
+
+bool get_string(HSQUIRRELVM vm, const char* name, std::string& val) {
+  if (!has_string(vm, name)) return false;
+  val = read_string(vm, name);
+  return true;
+}
+
+bool get_bool(HSQUIRRELVM vm, const char* name, bool& val) {
+  if (!has_bool(vm, name)) return false;
+  val = read_bool(vm, name);
+  return true;
+}
+
+// end: serialization functions
+
 }
index 5ebb44a..da61b26 100644 (file)
@@ -80,6 +80,28 @@ namespace Scripting
     }
   }
 
+  // begin serialization functions
+  void store_float(HSQUIRRELVM vm, const char* name, float val);
+  void store_int(HSQUIRRELVM vm, const char* name, int val);
+  void store_string(HSQUIRRELVM vm, const char* name, const std::string& val);
+  void store_bool(HSQUIRRELVM vm, const char* name, bool val);
+
+  bool has_float(HSQUIRRELVM vm, const char* name);
+  bool has_int(HSQUIRRELVM vm, const char* name);
+  bool has_string(HSQUIRRELVM vm, const char* name);
+  bool has_bool(HSQUIRRELVM vm, const char* name);
+
+  bool get_float(HSQUIRRELVM vm, const char* name, float& val);
+  bool get_int(HSQUIRRELVM vm, const char* name, int& val);
+  bool get_string(HSQUIRRELVM vm, const char* name, std::string& val);
+  bool get_bool(HSQUIRRELVM vm, const char* name, bool& val);
+
+  float read_float(HSQUIRRELVM vm, const char* name);
+  int read_int(HSQUIRRELVM vm, const char* name);
+  std::string read_string(HSQUIRRELVM vm, const char* name);
+  bool read_bool(HSQUIRRELVM vm, const char* name);
+  // end serialization functions
+
 }
 
 #endif
index 0b9aa03..5eb0cef 100644 (file)
@@ -32,6 +32,7 @@
 #include "main.hpp"
 #include "statistics.hpp"
 #include "log.hpp"
+#include "scripting/squirrel_util.hpp"
 
 namespace {
   const int nv_coins = std::numeric_limits<int>::min();
@@ -57,6 +58,7 @@ Statistics::~Statistics()
 {
 }
 
+/*
 void
 Statistics::parse(const lisp::Lisp& reader)
 {
@@ -80,6 +82,42 @@ Statistics::write(lisp::Writer& writer)
   writer.write_int("secrets-found", secrets);
   writer.write_int("secrets-found-total", total_secrets);
 }
+*/
+
+void
+Statistics::serialize_to_squirrel(HSQUIRRELVM vm)
+{
+  // TODO: there's some bug in the unserialization routines that breaks stuff when an empty statistics table is written, so -- as a workaround -- let's make sure we will actually write something first
+  if (!((coins != nv_coins) || (total_coins != nv_coins) || (badguys != nv_badguys) || (total_badguys != nv_badguys) || (time != nv_time) || (secrets != nv_secrets) || (total_secrets != nv_secrets))) return;
+
+  sq_pushstring(vm, "statistics", -1);
+  sq_newtable(vm);
+  if (coins != nv_coins) Scripting::store_int(vm, "coins-collected", coins);
+  if (total_coins != nv_coins) Scripting::store_int(vm, "coins-collected-total", total_coins);
+  if (badguys != nv_badguys) Scripting::store_int(vm, "badguys-killed", badguys);
+  if (total_badguys != nv_badguys) Scripting::store_int(vm, "badguys-killed-total", total_badguys);
+  if (time != nv_time) Scripting::store_float(vm, "time-needed", time);
+  if (secrets != nv_secrets) Scripting::store_int(vm, "secrets-found", secrets);
+  if (total_secrets != nv_secrets) Scripting::store_int(vm, "secrets-found-total", total_secrets);
+  sq_createslot(vm, -3);
+}
+
+void
+Statistics::unserialize_from_squirrel(HSQUIRRELVM vm)
+{
+  sq_pushstring(vm, "statistics", -1);
+  if(SQ_FAILED(sq_get(vm, -2))) {
+    return;
+  }
+  Scripting::get_int(vm, "coins-collected", coins);
+  Scripting::get_int(vm, "coins-collected-total", total_coins);
+  Scripting::get_int(vm, "badguys-killed", badguys);
+  Scripting::get_int(vm, "badguys-killed-total", total_badguys);
+  Scripting::get_float(vm, "time-needed", time);
+  Scripting::get_int(vm, "secrets-found", secrets);
+  Scripting::get_int(vm, "secrets-found-total", total_secrets);
+  sq_pop(vm, 1);
+}
 
 //define TOTAL_DISPLAY_TIME  3400
 //define FADING_TIME          600
@@ -267,6 +305,15 @@ Statistics::draw_endseq_panel(DrawingContext& context, Statistics* best_stats, S
 }
 
 void
+Statistics::zero()
+{
+  reset();
+  total_coins = 0;
+  total_badguys = 0;
+  total_secrets = 0;
+}
+
+void
 Statistics::reset()
 {
   coins = 0;
index d282e0e..4aca2ad 100644 (file)
@@ -22,6 +22,7 @@
 #ifndef SUPERTUX_STATISTICS_H
 #define SUPERTUX_STATISTICS_H
 
+#include <squirrel.h>
 #include "timer.hpp"
 
 namespace lisp { class Writer; }
@@ -48,14 +49,25 @@ public:
   ~Statistics();
 
   /// read statistics from lisp file
-  void parse(const lisp::Lisp& lisp);
+  //void parse(const lisp::Lisp& lisp);
   /// write statistics to lisp file
-  void write(lisp::Writer& writer);
+  //void write(lisp::Writer& writer);
+
+  /**
+   * serialize statistics object as squirrel table "statistics"
+   */
+  void serialize_to_squirrel(HSQUIRRELVM vm);
+
+  /**
+   * unserialize statistics object from squirrel table "statistics"
+   */
+  void unserialize_from_squirrel(HSQUIRRELVM vm);
 
   void draw_worldmap_info(DrawingContext& context); /**< draw worldmap stat HUD */
   void draw_message_info(DrawingContext& context, std::string title); /**< draw stats at level start */
   void draw_endseq_panel(DrawingContext& context, Statistics* best_stats, Surface* backdrop); /**< draw panel shown during level's end sequence */
 
+  void zero(); /**< Set stats to zero */
   void reset(); /**< Set stats (but not totals) to zero */
   void merge(Statistics& stats); /**< Given another Statistics object finds the best of each one */
   void operator+=(const Statistics& o); /**< Add two Statistics objects */
index 0477ed8..8cc033f 100644 (file)
@@ -371,7 +371,7 @@ WorldMap::get_level_title(LevelTile& level)
 
 void WorldMap::calculate_total_stats()
 {
-  total_stats.reset();
+  total_stats.zero();
   for(LevelTiles::iterator i = levels.begin(); i != levels.end(); ++i) {
     LevelTile* level = *i;
     if (level->solved) {
@@ -885,100 +885,6 @@ WorldMap::leave()
   sq_pop(global_vm, 1);
 }
 
-static void store_float(HSQUIRRELVM vm, const char* name, float val)
-{
-  sq_pushstring(vm, name, -1);
-  sq_pushfloat(vm, val);
-  if(SQ_FAILED(sq_createslot(vm, -3)))
-    throw Scripting::SquirrelError(vm, "Couldn't add float value to table");
-}
-
-/*
-static void store_int(HSQUIRRELVM vm, const char* name, int val)
-{
-  sq_pushstring(vm, name, -1);
-  sq_pushinteger(vm, val);
-  if(SQ_FAILED(sq_createslot(vm, -3)))
-    throw Scripting::SquirrelError(vm, "Couldn't add float value to table");
-}
-*/
-
-static void store_string(HSQUIRRELVM vm, const char* name, const std::string& val)
-{
-  sq_pushstring(vm, name, -1);
-  sq_pushstring(vm, val.c_str(), val.length());
-  if(SQ_FAILED(sq_createslot(vm, -3)))
-    throw Scripting::SquirrelError(vm, "Couldn't add float value to table");
-}
-
-static void store_bool(HSQUIRRELVM vm, const char* name, bool val)
-{
-  sq_pushstring(vm, name, -1);
-  sq_pushbool(vm, val ? SQTrue : SQFalse);
-  if(SQ_FAILED(sq_createslot(vm, -3)))
-    throw Scripting::SquirrelError(vm, "Couldn't add float value to table");
-}
-
-static float read_float(HSQUIRRELVM vm, const char* name)
-{
-  sq_pushstring(vm, name, -1);
-  if(SQ_FAILED(sq_get(vm, -2))) {
-    std::ostringstream msg;
-    msg << "Couldn't get float value for '" << name << "' from table";
-    throw Scripting::SquirrelError(vm, msg.str());
-  }
-
-  float result;
-  if(SQ_FAILED(sq_getfloat(vm, -1, &result))) {
-    std::ostringstream msg;
-    msg << "Couldn't get float value for '" << name << "' from table";
-    throw Scripting::SquirrelError(vm, msg.str());
-  }
-  sq_pop(vm, 1);
-
-  return result;
-}
-
-static std::string read_string(HSQUIRRELVM vm, const char* name)
-{
-  sq_pushstring(vm, name, -1);
-  if(SQ_FAILED(sq_get(vm, -2))) {
-    std::ostringstream msg;
-    msg << "Couldn't get string value for '" << name << "' from table";
-    throw Scripting::SquirrelError(vm, msg.str());
-  }
-
-  const char* result;
-  if(SQ_FAILED(sq_getstring(vm, -1, &result))) {
-    std::ostringstream msg;
-    msg << "Couldn't get string value for '" << name << "' from table";
-    throw Scripting::SquirrelError(vm, msg.str());
-  }
-  sq_pop(vm, 1);
-
-  return std::string(result);
-}
-
-static bool read_bool(HSQUIRRELVM vm, const char* name)
-{
-  sq_pushstring(vm, name, -1);
-  if(SQ_FAILED(sq_get(vm, -2))) {
-    std::ostringstream msg;
-    msg << "Couldn't get bool value for '" << name << "' from table";
-    throw Scripting::SquirrelError(vm, msg.str());
-  }
-
-  SQBool result;
-  if(SQ_FAILED(sq_getbool(vm, -1, &result))) {
-    std::ostringstream msg;
-    msg << "Couldn't get bool value for '" << name << "' from table";
-    throw Scripting::SquirrelError(vm, msg.str());
-  }
-  sq_pop(vm, 1);
-
-  return result == SQTrue;
-}
-
 void
 WorldMap::save_state()
 {
@@ -1036,14 +942,16 @@ WorldMap::save_state()
          sq_newtable(vm);
 
          store_bool(vm, "solved", level->solved);
-         // TODO write statistics
-         // i->statistics.write(writer);
+         level->statistics.serialize_to_squirrel(vm);
 
          sq_createslot(vm, -3);
     }
 
     sq_createslot(vm, -3);
 
+    // overall statistics...
+    total_stats.serialize_to_squirrel(vm);
+
     // push world into worlds table
     sq_createslot(vm, -3);
   } catch(std::exception& ) {
@@ -1106,12 +1014,17 @@ WorldMap::load_state()
       if(SQ_SUCCEEDED(sq_get(vm, -2))) {
         level->solved = read_bool(vm, "solved");
         level->sprite->set_action(level->solved ? "solved" : "default");
-        // i->statistics.parse(*level);
+        level->statistics.unserialize_from_squirrel(vm);
         sq_pop(vm, 1);
       }
     }
+
+    // leave state table
     sq_pop(vm, 1);
 
+    // load overall statistics
+    total_stats.unserialize_from_squirrel(vm);
+
   } catch(std::exception& e) {
     log_debug << "Not loading worldmap state: " << e.what() << std::endl;
   }