Merge: nitiwiki: fix multiple trails
[nit.git] / contrib / nitrpg / src / game.nit
index 89c9655..2924e46 100644 (file)
@@ -38,9 +38,18 @@ interface GameEntity
        # Uniq key used for data storage.
        fun key: String is abstract
 
-       # Save `self` as a json object.
+       # Saves the `self` state in game data.
+       #
+       # Date are stored under `self.key`.
        fun save do game.store.store_object(key, to_json)
 
+       # 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
+
        # Json representation of `self`.
        fun to_json: JsonObject  do return new JsonObject
 
@@ -56,20 +65,20 @@ class Game
 
        redef fun game do return self
 
-       # Returns the repo `full_name`.
-       #
-       # Example: `"privat/nit"`
-       redef fun key do return repo.full_name
-
        # We need a `GithubAPI` client to load Github data.
        var api: GithubAPI
 
        # A game takes place in a `github::Repo`.
        var repo: Repo
 
+       # 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`.
@@ -83,6 +92,12 @@ class Game
        # Used to load entities from saved data.
        fun from_json(json: JsonObject) do end
 
+       redef fun to_json do
+               var json = super
+               json["name"] = name
+               return json
+       end
+
        # Create a player from a Github `User`.
        #
        # Or return the existing one from game data.
@@ -171,9 +186,6 @@ end
 class Player
        super GameEntity
 
-       # Key is based on player `name`.
-       redef var key is lazy do return "players" / name
-
        redef var game
 
        # FIXME contructor should be private
@@ -186,6 +198,8 @@ class Player
        # The name is also used to load the user data lazilly from Github API.
        var name: String
 
+       redef var key = name is lazy
+
        # Player amount of nitcoins.
        #
        # Nitcoins is the currency used in nitrpg.
@@ -203,13 +217,13 @@ class Player
        #
        # Used to load players from saved data.
        init from_json(game: Game, json: JsonObject) do
-               self.game = game
-               name = json["name"].to_s
+               init(game, json["name"].to_s)
                nitcoins = json["nitcoins"].as(Int)
        end
 
        redef fun to_json do
                var json = super
+               json["game"] = game.key
                json["name"] = name
                json["nitcoins"] = nitcoins
                return json
@@ -226,11 +240,16 @@ end
 
 redef class User
        # The player linked to `self`.
-       fun player(game: Game): Player is lazy do
-               var player = game.load_player(login)
+       fun player(game: Game): Player do
+               var player = player_cache.get_or_null(game)
+               if player != null then return player
+               player = game.load_player(login)
                if player == null then player = game.add_player(self)
+               player_cache[game] = player
                return player
        end
+
+       private var player_cache = new HashMap[Game, Player]
 end
 
 # A GameReactor reacts to event sent by a `Github::HookListener`.
@@ -278,6 +297,19 @@ end
 
 # utils
 
+# Sort games by descending number of players.
+#
+# The first in the list is the game with the more players.
+class GamePlayersComparator
+       super Comparator
+
+       redef type COMPARED: Game
+
+       redef fun compare(a, b) do
+               return b.load_players.length <=> a.load_players.length
+       end
+end
+
 # Sort players by descending number of nitcoins.
 #
 # The first in the list is the player with the more of nitcoins.