redef class GameEntity
- # 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
-
- # Save statistics under this `MEntity`.
- fun save_statistics(stats: GameStats) do
- game.store.store_object(key / stats.key, stats.to_json)
- end
+ # Statistics manager for this entity.
+ fun stats: GameStatsManager is abstract
end
redef class Game
- # Statistics for this game instance.
- var stats: GameStats is lazy do
- return load_statistics or else new GameStats(game)
- end
-
- redef fun save do
- super
- save_statistics(stats)
- end
+ redef var stats is lazy do return new GameStatsManager(game, self)
redef fun pretty do
var res = new FlatBuffer
res.append stats.pretty
return res.write_to_string
end
+
+ redef fun save do
+ super
+ stats.save
+ end
end
redef class Player
- # Statistics for this player.
- var stats: GameStats 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
- save_statistics(stats)
- 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 stats.pretty
return res.write_to_string
end
+
+ redef fun save do
+ super
+ stats.save
+ 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
+
+ # Current date to extract stats
+ private var date = new Tm.gmtime
+
+ # Returns the `GameStats` instance for the overall statistics.
+ var overall: GameStats = load_stats_for("all") is lazy
+
+ # Returns the `GameStats` instance for the current year statistics.
+ var yearly: GameStats = load_stats_for(date.strftime("%Y")) is lazy
+
+ # Returns the `GameStats` instance for the current month statistics.
+ var monthly: GameStats = load_stats_for(date.strftime("%Y-%m")) is lazy
+
+ # Returns the `GameStats` instance for the current day statistics.
+ var daily: GameStats = load_stats_for(date.strftime("%Y-%m-%d")) is lazy
+
+ # Returns the `GameStats` instance for the current week statistics.
+ var weekly: GameStats = load_stats_for(date.strftime("%Y-W%U")) is lazy
+
+ # Load statistics for a `period` key.
+ fun load_stats_for(period: String): GameStats do
+ var req = new JsonObject
+ req["period"] = period
+ req["owner"] = owner.key
+ var obj = game.db.collection("statistics").find(req)
+ if obj isa JsonObject then
+ return new GameStats.from_json(game, period, owner, obj)
+ else
+ return new GameStats(game, period, owner)
+ end
+ 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 do
+ overall.save
+ yearly.save
+ monthly.save
+ daily.save
+ weekly.save
+ end
+
+ redef fun pretty do return overall.pretty
end
# Game statistics structure that can be saved as a `GameEntity`.
redef var game
- redef var key = "statistics"
+ redef var collection_name = "statistics"
+
+ # The period these stats are about.
+ var period: String
- # Load `self` from saved data
- init from_json(game: Game, json: JsonObject) do
- self.game = game
- for k, v in json do self[k] = v.as(Int)
+ # The game entity these stats are about.
+ var owner: GameEntity
+
+ redef var key = "{owner.key}-{period}" is lazy
+
+ # Load `self` from saved data.
+ init from_json(game: Game, period: String, owner: GameEntity, json: JsonObject) do
+ init(game, period, owner)
+ var values = json.get_or_null("values")
+ if not values isa JsonObject then return
+ for k, v in values do self[k] = v.as(Int)
end
redef fun to_json do
- var obj = new JsonObject
- for k, v in self do obj[k] = v
+ var obj = super
+ obj["period"] = period
+ obj["owner"] = owner.key
+ var values = new JsonObject
+ values.recover_with(self)
+ obj["values"] = values
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
class StatisticsReactor
super GameReactor
- redef fun react_event(game, e) do
- super # log events
- e.react_stats_event(game)
- end
+ redef fun react_event(game, e) do e.react_stats_event(game)
end
redef class GithubEvent
end
end
end
+
+redef class IssueCommentEvent
+
+ # Count posted comments
+ redef fun react_stats_event(game) do
+ if action == "created" then
+ var player = comment.user.player(game)
+ game.stats.inc("comments")
+ player.stats.inc("comments")
+ # FIXME use a more precise way to locate reviews
+ if comment.is_ack then
+ game.stats.inc("reviews")
+ player.stats.inc("reviews")
+ end
+ game.save
+ player.save
+ end
+ end
+end