Merge: nitrpg: periodize stats
authorJean Privat <jean@pryen.org>
Fri, 24 Apr 2015 06:03:14 +0000 (13:03 +0700)
committerJean Privat <jean@pryen.org>
Fri, 24 Apr 2015 06:03:14 +0000 (13:03 +0700)
This will be used to display periodic stats about players and games.

Pull-Request: #1292
Reviewed-by: Jean Privat <jean@pryen.org>

contrib/nitrpg/src/achievements.nit
contrib/nitrpg/src/events.nit
contrib/nitrpg/src/game.nit
contrib/nitrpg/src/statistics.nit
lib/counter.nit

index eeae17e..99cc0c2 100644 (file)
@@ -35,7 +35,7 @@ redef class GameEntity
                var key = self.key / achievement.key
                if game.store.has_key(key) then return
                stats.inc("achievements")
-               achievement.save_in(self)
+               achievement.save_in(self.key)
                save
        end
 
index 227469a..dde2c55 100644 (file)
@@ -25,7 +25,7 @@ import game
 redef class GameEntity
 
        # Saves `event` in `self`.
-       fun add_event(event: GameEvent) do event.save_in(self)
+       fun add_event(event: GameEvent) do event.save_in(self.key)
 
        # List all events registered in this entity.
        #
index d1dff3e..1ab143e 100644 (file)
@@ -43,11 +43,11 @@ interface GameEntity
        # Date are stored under `self.key`.
        fun save do game.store.store_object(key, to_json)
 
-       # Saves `self` state into `target` key data.
+       # Saves `self` state under `key` data.
        #
-       # Data are stored under `target.key / self.key`.
-       fun save_in(target: GameEntity) do
-               game.store.store_object(target.key / key, to_json)
+       # Data are stored under `key / self.key`.
+       fun save_in(key: String) do
+               game.store.store_object(key / self.key, to_json)
        end
 
        # Json representation of `self`.
index 7b493c6..e8afccc 100644 (file)
@@ -26,27 +26,17 @@ import counter
 
 redef class GameEntity
 
-       # Statistics for this entity.
-       fun stats: GameStats is abstract
-
-       # Load statistics for this `MEntity` if any.
-       fun load_statistics: nullable GameStats do
-               var key = self.key / "statistics"
-               if not game.store.has_key(key) then return null
-               var json = game.store.load_object(key)
-               return new GameStats.from_json(game, json)
-       end
+       # Statistics manager for this entity.
+       fun stats: GameStatsManager is abstract
 end
 
 redef class Game
 
-       redef var stats is lazy do
-               return load_statistics or else new GameStats(game)
-       end
+       redef var stats is lazy do return new GameStatsManager(game, self)
 
        redef fun save do
                super
-               stats.save_in(self)
+               stats.save_in(self.key)
        end
 
        redef fun pretty do
@@ -60,15 +50,16 @@ end
 
 redef class Player
 
-       redef var stats is lazy do
-               return load_statistics or else new GameStats(game)
-       end
+       redef var stats is lazy do return new GameStatsManager(game, self)
 
        redef fun save do
                super
-               stats.save_in(self)
+               stats.save_in(self.key)
        end
 
+       redef fun nitcoins do return stats["nitcoins"]
+       redef fun nitcoins=(nc) do stats["nitcoins"] = nc
+
        redef fun pretty do
                var res = new FlatBuffer
                res.append super
@@ -78,6 +69,98 @@ redef class Player
        end
 end
 
+# Store game stats for defined period.
+class GameStatsManager
+       super GameEntity
+       super Counter[String]
+
+       redef var game
+
+       # The GameEntity monitored by these statistics.
+       var owner: GameEntity
+
+       redef var key = "stats"
+
+       # Returns the `GameStats` instance for the overall statistics.
+       var overall: GameStats is lazy do
+               return load_stats_for("all")
+       end
+
+       # Returns the `GameStats` instance for the current year statistics.
+       var yearly: GameStats is lazy do
+               var date = new Tm.gmtime
+               var key = date.strftime("%Y")
+               return load_stats_for(key)
+       end
+
+       # Returns the `GameStats` instance for the current month statistics.
+       var monthly: GameStats is lazy do
+               var date = new Tm.gmtime
+               var key = date.strftime("%Y-%m")
+               return load_stats_for(key)
+       end
+
+       # Returns the `GameStats` instance for the current day statistics.
+       var daily: GameStats is lazy do
+               var date = new Tm.gmtime
+               var key = date.strftime("%Y-%m-%d")
+               return load_stats_for(key)
+       end
+
+       # Returns the `GameStats` instance for the current week statistics.
+       var weekly: GameStats is lazy do
+               var date = new Tm.gmtime
+               var key = date.strftime("%Y-W%U")
+               return load_stats_for(key)
+       end
+
+       # Load statistics for a `period` key.
+       fun load_stats_for(period: String): GameStats do
+               var key = owner.key / self.key / period
+               if not game.store.has_key(key) then
+                       return new GameStats(game, period)
+               end
+               var json = game.store.load_object(key)
+               return new GameStats.from_json(game, period, json)
+       end
+
+       redef fun [](key) do return overall[key]
+
+       redef fun []=(key, value) do
+               overall[key] = value
+               yearly[key] = value
+               monthly[key] = value
+               daily[key] = value
+               weekly[key] = value
+       end
+
+       redef fun inc(e) do
+               overall.inc(e)
+               yearly.inc(e)
+               monthly.inc(e)
+               daily.inc(e)
+               weekly.inc(e)
+       end
+
+       redef fun dec(e) do
+               overall.dec(e)
+               yearly.dec(e)
+               monthly.dec(e)
+               daily.dec(e)
+               weekly.dec(e)
+       end
+
+       redef fun save_in(key) do
+               overall.save_in(key / self.key)
+               yearly.save_in(key / self.key)
+               monthly.save_in(key / self.key)
+               daily.save_in(key / self.key)
+               weekly.save_in(key / self.key)
+       end
+
+       redef fun pretty do return overall.pretty
+end
+
 # Game statistics structure that can be saved as a `GameEntity`.
 class GameStats
        super GameEntity
@@ -85,11 +168,13 @@ class GameStats
 
        redef var game
 
-       redef var key = "statistics"
+       # The pedriod these stats are about.
+       var period: String
+
+       redef fun key do return period
 
-       # Load `self` from saved data
-       init from_json(game: Game, json: JsonObject) do
-               self.game = game
+       # Load `self` from saved data.
+       init from_json(game: Game, period: String, json: JsonObject) do
                for k, v in json do self[k] = v.as(Int)
        end
 
@@ -99,15 +184,6 @@ class GameStats
                return obj
        end
 
-       # Decrements the value of `key` statistic entry by 1.
-       fun dec(key: String) do
-               if not has_key(key) then
-                       self[key] = 0
-               else
-                       self[key] -= 1
-               end
-       end
-
        redef fun pretty do
                var res = new FlatBuffer
                for k, v in self do
index 6545b73..6d5729d 100644 (file)
@@ -93,6 +93,22 @@ class Counter[E]
                for e in es do inc(e)
        end
 
+       # Decrement the value of `e` by 1
+       fun dec(e: E) do
+               if not has_key(e) then
+                       self.map[e] = 0
+               else
+                       self.map[e] = self[e] - 1
+                       sum += - 1
+               end
+       end
+
+       # Decrement the value for each element of `es`
+       fun dec_all(es: Collection[E])
+       do
+               for e in es do dec(e)
+       end
+
        # A new Counter initialized with `inc_all`.
        init from(es: Collection[E])
        do