#
# TODO should update the achievement?
fun add_achievement(achievement: Achievement) do
- var key = self.key / achievement.key
- if game.store.has_key(key) then return
stats.inc("achievements")
- achievement.save_in(self.key)
- save
+ achievement.owner = self
+ achievement.save
end
+ # Is `a` unlocked for this `Player`?
+ fun has_achievement(a: Achievement): Bool do return load_achievement(a.id) != null
+
# Load the event from its `id`.
#
# Looks for the event save file in game data.
# Returns `null` if the event cannot be found.
fun load_achievement(id: String): nullable Achievement do
- var key = self.key / "achievements" / id
- if not game.store.has_key(key) then return null
- var json = game.store.load_object(key)
- return new Achievement.from_json(game, json)
+ var req = new JsonObject
+ req["id"] = id
+ req["game"] = game.key
+ req["owner"] = key
+ var obj = game.db.collection("achievements").find(req)
+ if obj isa JsonObject then
+ return new Achievement.from_json(game, obj)
+ end
+ return null
end
# List all events registered in this entity.
#
# To add events see `add_event`.
fun load_achievements: MapRead[String, Achievement] do
+ var req = new JsonObject
+ req["game"] = game.key
+ req["owner"] = key
var res = new HashMap[String, Achievement]
- var key = self.key / "achievements"
- if not game.store.has_collection(key) then return res
- var coll = game.store.list_collection(key)
- for id in coll do
- res[id.to_s] = load_achievement(id.to_s).as(not null)
+ for obj in game.db.collection("achievements").find_all(req) do
+ var achievement = new Achievement.from_json(game, obj)
+ res[achievement.id] = achievement
end
return res
end
class Achievement
super GameEntity
+ redef var collection_name = "achievements"
redef var game
- redef var key is lazy do
+ redef fun key do
var owner = self.owner
if owner == null then return id
return "{owner.key}-{id}"
end
redef class Player
-
- # Is `a` unlocked for this `Player`?
- fun has_achievement(a: Achievement): Bool do
- return load_achievement(a.id) != null
- end
-
# Unlocks an achievement for this Player based on a GithubEvent.
#
# Register the achievement and adds the achievement reward to the player
nitcoins += a.reward
add_achievement(a)
trigger_unlock_event(a, event)
+ save
end
# Create a new event that marks the achievement unlocking.
#
# To add events see `add_event`.
fun load_events: Array[GameEvent] do
- var key = key / "events"
+ var req = new JsonObject
+ req["game"] = game.key
+ req["owner"] = key
var res = new Array[GameEvent]
- if not game.store.has_collection(key) then return res
- var coll = game.store.list_collection(key)
- for id in coll do
- var name = id.to_s
- res.add load_event(name).as(not null)
+ for obj in game.db.collection("events").find_all(req) do
+ res.add new GameEvent.from_json(game, obj)
end
(new EventTimeComparator).sort(res)
return res
# Looks for the event save file in game data.
# Returns `null` if the event cannot be found.
fun load_event(id: String): nullable GameEvent do
- var key = key / "events" / id
- if not game.store.has_key(key) then return null
- var json = game.store.load_object(key)
- return new GameEvent.from_json(game, json)
+ var req = new JsonObject
+ req["game"] = game.key
+ req["owner"] = key
+ req["internal_id"] = id
+ var res = game.db.collection("events").find(req)
+ if res != null then return new GameEvent.from_json(game, res)
+ return null
end
end
class GameEvent
super GameEntity
+ redef var collection_name = "events"
redef var game
# the `GameReactor` abstraction.
module game
-intrude import json::store
+import mongodb
import github::events
# An entity within a `Game`.
# The game instance containing `self`.
fun game: Game is abstract
- # Uniq key used for data storage.
- fun key: String is abstract
+ # Collection `self` should be saved in.
+ fun collection_name: String is abstract
- # Saves the `self` state in game data.
- #
- # Date are stored under `self.key`.
- fun save do game.store.store_object(key, to_json)
+ # Uniq key of this entity within the collection.
+ fun key: String is abstract
- # Saves `self` state under `key` data.
- #
- # Data are stored under `key / self.key`.
- fun save_in(key: String) do
- game.store.store_object(key / self.key, to_json)
- end
+ # Saves `self` in db.
+ fun save do game.db.collection(collection_name).save(to_json)
# Json representation of `self`.
- fun to_json: JsonObject do return new JsonObject
+ fun to_json: JsonObject do
+ var json = new JsonObject
+ json["_id"] = key
+ return json
+ end
# Pretty print `self` to be displayed in a terminal.
fun pretty: String is abstract
# Game name
var name: String = repo.full_name is lazy
- # Directory where game data are stored.
- var game_dir: String is lazy do return "nitrpg_data" / repo.full_name
-
redef var key = name is lazy
- # Used for data storage.
- #
- # File are stored in `game_dir`.
- var store: JsonStore is lazy do return new JsonStore(game_dir)
+ # Mongo server url where this game data are stored.
+ var mongo_url = "mongodb://localhost:27017" is writable
+
+ # Mongo db client.
+ var client = new MongoClient(mongo_url) is lazy
+
+ # Mongo db name where this game data are stored.
+ var db_name = "nitrpg" is writable
+
+ # Mongo db instance for this game.
+ var db: MongoDb is lazy do return client.database(db_name)
+
+ redef var collection_name = "games"
# Init the Game and try to load saved data.
- init do if store.has_key(key) then from_json(store.load_object(key))
+ init do
+ var req = new JsonObject
+ req["name"] = repo.full_name
+ var res = db.collection("games").find(req)
+ if res != null then from_json(res)
+ end
# Init `self` from a JsonObject.
#
# Returns `null` if the player cannot be found.
# In this case, the player can be created with `add_player`.
fun load_player(name: String): nullable Player do
- var key = "players" / name
- if not store.has_key(key) then return null
- var json = store.load_object(key)
- return new Player.from_json(self, json)
+ var req = new JsonObject
+ req["name"] = name
+ req["game"] = game.key
+ var res = db.collection("players").find(req)
+ if res != null then return new Player.from_json(self, res)
+ return null
end
# List known players.
#
# To add players see `add_player`.
fun load_players: MapRead[String, Player] do
+ var req = new JsonObject
+ req["game"] = game.key
var res = new HashMap[String, Player]
- if not store.has_collection("players") then return res
- var coll = store.list_collection("players")
- for id in coll do
- var name = id.to_s
- res[name] = load_player(name).as(not null)
+ for obj in db.collection("players").find_all(req) do
+ var player = new Player.from_json(self, obj)
+ res[player.name] = player
end
return res
end
end
# Erase all saved data for this game.
- fun clear do store.clear
+ fun clear do db.collection(collection_name).remove(to_json)
# Verbosity level used fo stdout.
#
class Player
super GameEntity
+ # Stored in collection `players`.
+ redef var collection_name = "players"
+
redef var game
# FIXME contructor should be private
redef var stats is lazy do return new GameStatsManager(game, self)
- redef fun save do
- super
- stats.save_in(self.key)
- end
-
redef fun pretty do
var res = new FlatBuffer
res.append super
res.append stats.pretty
return res.write_to_string
end
+
+ redef fun save do
+ super
+ stats.save
+ end
end
redef class Player
redef var stats is lazy do return new GameStatsManager(game, self)
- redef fun save do
- super
- stats.save_in(self.key)
- end
-
redef fun nitcoins do return stats["nitcoins"]
redef fun nitcoins=(nc) do stats["nitcoins"] = nc
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.
# 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
+ 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
- var json = game.store.load_object(key)
- return new GameStats.from_json(game, period, owner, json)
end
redef fun [](key) do return overall[key]
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)
+ redef fun save do
+ overall.save
+ yearly.save
+ monthly.save
+ daily.save
+ weekly.save
end
redef fun pretty do return overall.pretty
redef var game
+ redef var collection_name = "statistics"
+
# The period these stats are about.
var period: String
redef class GameEntity
+ # Path to this entity from root.
+ fun path: String do return collection_name / key
+
# URL to this game entity page.
- fun url: String do return game.url / key
+ fun url: String do return game.url / path
end
redef class Game
# This must be set before any access to `url`.
var root_url: String is noinit, writable
- redef fun url do return "{root_url}/games" / key
+ redef fun url do return "{root_url}/{path}"
# Return a HTML link to this Game.
fun link: String do return "<a href=\"{url}\">{name}</a>"