diff --git a/ConsoleApp/Program.cs b/ConsoleApp/Program.cs index cf39300..71cdda7 100644 --- a/ConsoleApp/Program.cs +++ b/ConsoleApp/Program.cs @@ -1,6 +1,7 @@ using System; using System.Linq; using Game.Domain; +using MongoDB.Driver; namespace ConsoleApp { @@ -9,11 +10,13 @@ class Program private readonly IUserRepository userRepo; private readonly IGameRepository gameRepo; private readonly Random random = new Random(); + private readonly string mongoConnectionString = Environment.GetEnvironmentVariable("PROJECT5100_MONGO_CONNECTION_STRING") ?? "mongodb://localhost:27017?maxConnecting=100"; private Program(string[] args) { - userRepo = new InMemoryUserRepository(); - gameRepo = new InMemoryGameRepository(); + var db = new MongoClient(mongoConnectionString).GetDatabase("game"); + userRepo = new MongoUserRepository(db); + gameRepo = new MongoGameRepository(db); } public static void Main(string[] args) diff --git a/Game/Domain/GameEntity.cs b/Game/Domain/GameEntity.cs index ec7b5ec..c048836 100644 --- a/Game/Domain/GameEntity.cs +++ b/Game/Domain/GameEntity.cs @@ -1,11 +1,13 @@ using System; using System.Collections.Generic; using System.Linq; +using MongoDB.Bson.Serialization.Attributes; namespace Game.Domain { public class GameEntity { + [BsonElement] private readonly List players; public GameEntity(int turnsCount) @@ -13,6 +15,7 @@ public GameEntity(int turnsCount) { } + [BsonConstructor] public GameEntity(Guid id, GameStatus status, int turnsCount, int currentTurnIndex, List players) { Id = id; @@ -22,6 +25,7 @@ public GameEntity(Guid id, GameStatus status, int turnsCount, int currentTurnInd this.players = players; } + [BsonElement] public Guid Id { get; @@ -29,12 +33,16 @@ public Guid Id private set; } + [BsonElement] public IReadOnlyList Players => players.AsReadOnly(); + [BsonElement] public int TurnsCount { get; } + [BsonElement] public int CurrentTurnIndex { get; private set; } + [BsonElement] public GameStatus Status { get; private set; } public void AddPlayer(UserEntity user) @@ -59,6 +67,7 @@ public void Cancel() Status = GameStatus.Canceled; } + [BsonElement] public bool HaveDecisionOfEveryPlayer => Players.All(p => p.Decision.HasValue); public void SetPlayerDecision(Guid userId, PlayerDecision decision) diff --git a/Game/Domain/MongoGameRepository.cs b/Game/Domain/MongoGameRepository.cs index 86873d4..935f7ea 100644 --- a/Game/Domain/MongoGameRepository.cs +++ b/Game/Domain/MongoGameRepository.cs @@ -8,38 +8,45 @@ namespace Game.Domain public class MongoGameRepository : IGameRepository { public const string CollectionName = "games"; + private readonly IMongoCollection gameCollection; public MongoGameRepository(IMongoDatabase db) { + gameCollection = db.GetCollection(CollectionName); } public GameEntity Insert(GameEntity game) { - throw new NotImplementedException(); + gameCollection.InsertOne(game); + return game; } public GameEntity FindById(Guid gameId) { - throw new NotImplementedException(); + var result = gameCollection.Find(game => game.Id == gameId); + return result.FirstOrDefault(); } public void Update(GameEntity game) { - throw new NotImplementedException(); + gameCollection.ReplaceOne(gameInDb => gameInDb.Id == game.Id, game); } // Возвращает не более чем limit игр со статусом GameStatus.WaitingToStart public IList FindWaitingToStart(int limit) { - //TODO: Используй Find и Limit - throw new NotImplementedException(); + return gameCollection + .Find(game => game.Status == GameStatus.WaitingToStart) + .Limit(limit) + .ToList(); } // Обновляет игру, если она находится в статусе GameStatus.WaitingToStart public bool TryUpdateWaitingToStart(GameEntity game) { - //TODO: Для проверки успешности используй IsAcknowledged и ModifiedCount из результата - throw new NotImplementedException(); + var result = gameCollection + .ReplaceOne(gameInDb => gameInDb.Id == game.Id && gameInDb.Status == GameStatus.WaitingToStart, game); + return result.IsAcknowledged && result.ModifiedCount != 0; } } } \ No newline at end of file diff --git a/Game/Domain/MongoUserRepositoty.cs b/Game/Domain/MongoUserRepositoty.cs index 51aeba5..e5994b6 100644 --- a/Game/Domain/MongoUserRepositoty.cs +++ b/Game/Domain/MongoUserRepositoty.cs @@ -1,5 +1,7 @@ using System; using MongoDB.Driver; +using System.Linq; +using MongoDB.Bson; namespace Game.Domain { @@ -11,43 +13,60 @@ public class MongoUserRepository : IUserRepository public MongoUserRepository(IMongoDatabase database) { userCollection = database.GetCollection(CollectionName); + userCollection.Indexes.CreateOne(new CreateIndexModel( + Builders.IndexKeys.Ascending(u => u.Login), + new CreateIndexOptions { Unique = true })); } public UserEntity Insert(UserEntity user) { - //TODO: Ищи в документации InsertXXX. - throw new NotImplementedException(); + userCollection.InsertOne(user); + return user; } public UserEntity FindById(Guid id) { - //TODO: Ищи в документации FindXXX - throw new NotImplementedException(); + var result = userCollection.Find(user => user.Id == id); + return result.FirstOrDefault(); } public UserEntity GetOrCreateByLogin(string login) { - //TODO: Это Find или Insert - throw new NotImplementedException(); + var searchResult = userCollection.Find(user => user.Login == login).FirstOrDefault(); + if (searchResult is not null) + return searchResult; + + var userEntity = new UserEntity(Guid.NewGuid()) + { + Login = login + }; + Insert(userEntity); + return userEntity; } public void Update(UserEntity user) { - //TODO: Ищи в документации ReplaceXXX - throw new NotImplementedException(); + userCollection.ReplaceOne(userInDb => userInDb.Id == user.Id, user); } public void Delete(Guid id) { - throw new NotImplementedException(); + userCollection.DeleteOne(user => user.Id == id); } // Для вывода списка всех пользователей (упорядоченных по логину) // страницы нумеруются с единицы public PageList GetPage(int pageNumber, int pageSize) { - //TODO: Тебе понадобятся SortBy, Skip и Limit - throw new NotImplementedException(); + var allUsers = userCollection.Find(user => true); + var totalCount = userCollection.CountDocuments(user => true); + var items = allUsers + .SortBy(user => user.Login) + .Skip(pageSize * (pageNumber - 1)) + .Limit(pageSize) + .ToList(); + + return new PageList(items, totalCount, pageNumber, pageSize); } // Не нужно реализовывать этот метод diff --git a/Game/Domain/Player.cs b/Game/Domain/Player.cs index 9c4f838..59aadf1 100644 --- a/Game/Domain/Player.cs +++ b/Game/Domain/Player.cs @@ -1,4 +1,5 @@ using System; +using MongoDB.Bson.Serialization.Attributes; namespace Game.Domain { @@ -7,17 +8,20 @@ namespace Game.Domain /// public class Player { + [BsonConstructor] public Player(Guid userId, string name) { UserId = userId; Name = name; } - + + [BsonElement] public Guid UserId { get; } /// /// Снэпшот имени игрока на момент старта игры. Считайте, что это такое требование к игре. /// + [BsonElement] public string Name { get; } ///