예제 #1
0
        public async Task AddEventAsync(GameId gameId, GameEvent gameEvent, CancellationToken cancellationToken)
        {
            if (gameId == null)
            {
                throw new ArgumentNullException(nameof(gameId));
            }

            if (gameEvent == null)
            {
                throw new ArgumentNullException(nameof(gameEvent));
            }

            cancellationToken.ThrowIfCancellationRequested();

            using var connection = await _connectionFactory.CreateAndOpenAsync(cancellationToken);

            using var transaction = connection.BeginTransaction();

            int surrogateGameId;

            {
                var command = new CommandDefinition(
                    commandText: "SELECT id FROM game WHERE game_id = @gameId;",
                    parameters: new { gameId },
                    transaction,
                    cancellationToken: cancellationToken
                    );

                surrogateGameId = await connection.QuerySingleAsync <int>(command);
            }

            // Couldn't figure out how to support INSERT with composite types with Dapper, so ADO.NET to the rescue.
            using (var command = connection.CreateCommand())
            {
                var commandText = @"
                        INSERT INTO
                            game_event (game_id, idx, by_player_id, card_drawn, card_used, chip, coord, next_player_id, sequences, winner)
                        VALUES
                            (@gameId, @idx, @byPlayerId, @cardDrawn, @cardUsed, @chip, @coord, @nextPlayerId, @sequences, @winner);";

                command.CommandText = commandText;
                command.Parameters.AddWithValue("@gameId", surrogateGameId);
                command.Parameters.AddWithValue("@idx", gameEvent.Index);
                command.Parameters.AddWithValue("@byPlayerId", gameEvent.ByPlayerId.Value);
                command.Parameters.AddWithValue("@cardDrawn", CardComposite.FromCard(gameEvent.CardDrawn) as object ?? DBNull.Value);
                command.Parameters.AddWithValue("@cardUsed", CardComposite.FromCard(gameEvent.CardUsed) !);
                command.Parameters.AddWithValue("@chip", gameEvent.Chip as object ?? DBNull.Value);
                command.Parameters.AddWithValue("@coord", CoordComposite.FromCoord(gameEvent.Coord));
                command.Parameters.AddWithValue("@nextPlayerId", gameEvent.NextPlayerId?.Value as object ?? DBNull.Value);
                command.Parameters.AddWithValue("@sequences", gameEvent.Sequences.Select(SequenceComposite.FromSequence).ToArray());
                command.Parameters.AddWithValue("@winner", gameEvent.Winner as object ?? DBNull.Value);
                command.Transaction = transaction;

                await command.ExecuteNonQueryAsync(cancellationToken);
            }

            await transaction.CommitAsync(cancellationToken);
        }
예제 #2
0
        public async Task <GameId> PersistNewGameAsync(NewGame newGame, CancellationToken cancellationToken)
        {
            if (newGame == null)
            {
                throw new ArgumentNullException(nameof(newGame));
            }

            cancellationToken.ThrowIfCancellationRequested();

            GameId gameId;

            using (var connection = await _connectionFactory.CreateAndOpenAsync(cancellationToken))
            {
                using var transaction = connection.BeginTransaction();

                try
                {
                    int surrogateGameId = default;
                    int firstPlayerId   = default;

                    {
                        var commandText = @"
                            INSERT INTO
                                game (board_type, num_sequences_to_win, seed, version)
                            VALUES
                                (@boardType, @numSequencesToWin, @seed, @version)
                            RETURNING id, game_id;";

                        var parameters = new
                        {
                            boardType         = (int)newGame.BoardType,
                            numSequencesToWin = newGame.NumberOfSequencesToWin,
                            seed    = newGame.Seed,
                            version = 1
                        };

                        var command = new CommandDefinition(
                            commandText,
                            parameters,
                            transaction,
                            cancellationToken: cancellationToken
                            );

                        var result = await connection.QuerySingleAsync <insert_into_game>(command);

                        surrogateGameId = result.id;
                        gameId          = result.game_id;
                    }

                    for (int i = 0; i < newGame.PlayerList.Players.Count; i++)
                    {
                        var commandText = @"
                            INSERT INTO
                                game_player (game_id, player_id, player_type)
                            VALUES
                                (@gameId, @playerId, @playerType::player_type)
                            RETURNING id;";

                        var player = newGame.PlayerList.Players[i];

                        var parameters = new
                        {
                            gameId     = surrogateGameId,
                            playerId   = player.Handle,
                            playerType = player.Type.ToString().ToLowerInvariant(),
                        };

                        var command = new CommandDefinition(
                            commandText,
                            parameters,
                            transaction,
                            cancellationToken: cancellationToken
                            );

                        var result = await connection.QuerySingleAsync <int>(command);

                        if (newGame.FirstPlayerIndex == i)
                        {
                            firstPlayerId = result;
                        }
                    }

                    {
                        var commandText = @"
                            UPDATE game
                               SET first_player_id = @firstPlayerId
                             WHERE id = @gameId;";

                        var parameters = new { firstPlayerId, gameId = surrogateGameId };

                        var command = new CommandDefinition(
                            commandText,
                            parameters,
                            transaction,
                            cancellationToken: cancellationToken
                            );

                        await connection.ExecuteAsync(command);
                    }

                    await transaction.CommitAsync(cancellationToken);
                }
                catch
                {
                    await transaction.RollbackAsync(cancellationToken);

                    throw;
                }
            }

            return(gameId);
        }