Système de Persistance¶
Sauvegarde et chargement des données de jeu.
Architecture¶
flowchart TB
subgraph Application
Game[Game Server]
API[REST API]
end
subgraph Persistence Layer
Repo[Repository Interface]
Mongo[MongoDB Adapter]
Memory[In-Memory Adapter]
end
subgraph Storage
DB[(MongoDB)]
Cache[Memory Cache]
end
Game --> Repo
API --> Repo
Repo --> Mongo
Repo --> Memory
Mongo --> DB
Memory --> Cache
style Repo fill:#7c3aed,color:#fff
Données Persistées¶
| Donnée | Collection | Description |
|---|---|---|
| Joueurs | players |
Profils, statistiques |
| Scores | highscores |
Meilleurs scores |
| Sessions | sessions |
Parties en cours |
| Config | config |
Configuration serveur |
Repository Pattern¶
Interface abstraite pour la persistance.
// Port (Interface)
template<typename T>
class IRepository {
public:
virtual ~IRepository() = default;
virtual std::optional<T> findById(const std::string& id) = 0;
virtual std::vector<T> findAll() = 0;
virtual void save(const T& entity) = 0;
virtual void update(const T& entity) = 0;
virtual void remove(const std::string& id) = 0;
};
// Spécialisations
class IPlayerRepository : public IRepository<Player> {
public:
virtual std::optional<Player> findByUsername(
const std::string& username) = 0;
virtual std::vector<Player> findTopPlayers(int limit) = 0;
};
class IScoreRepository : public IRepository<Score> {
public:
virtual std::vector<Score> getLeaderboard(int limit) = 0;
virtual std::vector<Score> getPlayerScores(
const std::string& playerId) = 0;
};
Modèles de Données¶
Player¶
struct Player {
std::string id;
std::string username;
std::string passwordHash;
int totalScore = 0;
int gamesPlayed = 0;
int highScore = 0;
std::chrono::system_clock::time_point createdAt;
std::chrono::system_clock::time_point lastLogin;
// Sérialisation BSON
bsoncxx::document::value toBson() const {
using bsoncxx::builder::basic::kvp;
using bsoncxx::builder::basic::make_document;
return make_document(
kvp("_id", bsoncxx::oid{id}),
kvp("username", username),
kvp("passwordHash", passwordHash),
kvp("totalScore", totalScore),
kvp("gamesPlayed", gamesPlayed),
kvp("highScore", highScore),
kvp("createdAt", bsoncxx::types::b_date{createdAt}),
kvp("lastLogin", bsoncxx::types::b_date{lastLogin})
);
}
static Player fromBson(const bsoncxx::document::view& doc) {
Player p;
p.id = doc["_id"].get_oid().value.to_string();
p.username = std::string(doc["username"].get_string().value);
p.passwordHash = std::string(doc["passwordHash"].get_string().value);
p.totalScore = doc["totalScore"].get_int32().value;
p.gamesPlayed = doc["gamesPlayed"].get_int32().value;
p.highScore = doc["highScore"].get_int32().value;
return p;
}
};
Score¶
struct Score {
std::string id;
std::string playerId;
std::string playerName;
int score;
int wave;
int enemiesKilled;
std::chrono::milliseconds duration;
std::chrono::system_clock::time_point timestamp;
bsoncxx::document::value toBson() const;
static Score fromBson(const bsoncxx::document::view& doc);
};
Flux de Données¶
sequenceDiagram
participant Client
participant Server
participant Repo as Repository
participant DB as MongoDB
Note over Client,Server: Fin de partie
Server->>Repo: saveScore(score)
Repo->>DB: insertOne(score.toBson())
DB-->>Repo: acknowledgment
Server->>Repo: updatePlayer(player)
Repo->>DB: updateOne(filter, update)
DB-->>Repo: acknowledgment
Server-->>Client: GameOverPacket
Documentation¶
🍃 MongoDB
Implémentation MongoDB