Example #1
0
        private async Task RunOneGame(OneRoundTempData round)
        {
            await round.Semaphore.WaitAsync();

            int[] teams;
            int   gameId = -1;

            try {
                teams = round.SelectPlayers(simulator.NumPlayers);

                {
                    await using var cmd = new NpgsqlCommand("insert into Game (round, teams, start_time) VALUES (@round, @teams, @starttime) RETURNING id", conn);
                    cmd.Parameters.AddWithValue("round", round.Round);
                    cmd.Parameters.AddWithValue("teams", NpgsqlTypes.NpgsqlDbType.Array | NpgsqlTypes.NpgsqlDbType.Integer,
                                                teams);
                    Int64 unixTimestamp = (Int64)(DateTime.UtcNow.Subtract(new DateTime(1970, 1, 1))).TotalMilliseconds;
                    cmd.Parameters.AddWithValue("starttime", unixTimestamp);
                    gameId = (int)await cmd.ExecuteScalarAsync();
                }
            } finally {
                round.Semaphore.Release();
            }

            Console.WriteLine("Simulating game between " + String.Join(", ", teams));

            GameLaunchParams launch = new GameLaunchParams();

            launch.Practice = false;
            foreach (int team in teams)
            {
                launch.Teams.Add(new TeamData {
                    Id         = team,
                    BinaryPath = round.Teams[team].BinaryPath
                });
            }
            var result = await simulator.Launch(launch);

            double[] eloDeltas = Elo.ComputeEloDelta(teams.Select(t => round.Teams[t].StartingElo).ToArray(), result.Points.ToArray(), round.EloKFactor);

            await round.Semaphore.WaitAsync();

            try {
                round.UpdateRatings(teams, eloDeltas, gameId, false);

                {
                    await using var cmd = new NpgsqlCommand(
                                    "update Game set end_time = @endtime, scores = @scores, result_path = @resultpath, " +
                                    "elo_deltas = @elodeltas where id = @id", conn);
                    Int64 unixTimestamp = (Int64)(DateTime.UtcNow.Subtract(new DateTime(1970, 1, 1))).TotalMilliseconds;
                    cmd.Parameters.AddWithValue("endtime", unixTimestamp);
                    cmd.Parameters.AddWithValue("scores", NpgsqlTypes.NpgsqlDbType.Array | NpgsqlTypes.NpgsqlDbType.Double, result.Points.ToArray());
                    cmd.Parameters.AddWithValue("elodeltas", NpgsqlTypes.NpgsqlDbType.Array | NpgsqlTypes.NpgsqlDbType.Double, eloDeltas);
                    cmd.Parameters.AddWithValue("id", gameId);
                    cmd.Parameters.AddWithValue("resultpath", result.ResultPath);
                    await cmd.ExecuteNonQueryAsync();
                }
            } finally {
                round.Semaphore.Release();
            }
        }
Example #2
0
        private async Task RunRoundLoop(OneRoundTempData round)
        {
            Console.WriteLine($"Simulating tournament round with {round.Teams.Count} teams with {numThreads} threads.");
            Task[] tasks = new Task[numThreads];
            for (int i = 0; i < tasks.Length; i++)
            {
                tasks[i] = Task.CompletedTask;
            }
            // Parallelization.
            while (round.NumGames < round.Teams.Count * round.DesiredNumGamesPerTeam / 2)
            {
                var completed = await Task.WhenAny(tasks);

                tasks[Array.IndexOf(tasks, completed)] = RunOneGame(round);
                round.NumGames++;
            }
            await Task.WhenAll(tasks);

            await FinishRound();
        }
Example #3
0
        private async Task <OneRoundTempData> RecoverRoundData()
        {
            var result      = new OneRoundTempData();
            var activeRound = await GetCurrentActiveRound();

            if (!activeRound.HasValue)
            {
                throw new Exception("Attempting to simulate non-active round.");
            }
            var(round, numGamesPerTeam, maxTeams, eloKFactor) = activeRound.Value;
            result.Round = round;
            result.DesiredNumGamesPerTeam = numGamesPerTeam;
            result.MaxTeams   = maxTeams;
            result.EloKFactor = eloKFactor;
            // Read the snapshot binary path and teams of the current round.
            {
                await using var cmd = new NpgsqlCommand("select team, binary_path from Round where round = @round", conn);
                cmd.Parameters.AddWithValue("round", result.Round);
                await using var reader = await cmd.ExecuteReaderAsync();

                while (await reader.ReadAsync())
                {
                    int    team       = reader.GetInt32(0);
                    string binaryPath = reader.GetString(1);
                    result.Teams[team] = new OneTeamTempData {
                        Id          = team,
                        BinaryPath  = binaryPath,
                        StartingElo = 1500,
                        PendingElo  = 1500,
                    };
                }
            }

            // Read elo from previous round.
            {
                await using var cmd = new NpgsqlCommand("select team, elo from Round where round = @round", conn);
                cmd.Parameters.AddWithValue("round", result.Round - 1);
                await using var reader = await cmd.ExecuteReaderAsync();

                while (await reader.ReadAsync())
                {
                    int    team = reader.GetInt32(0);
                    double elo  = reader.GetDouble(1);
                    if (result.Teams.ContainsKey(team))
                    {
                        result.Teams[team].StartingElo = elo;
                        result.Teams[team].PendingElo  = elo;
                    }
                }
            }

            // Recover previous games
            {
                await using var cmd = new NpgsqlCommand("select teams, id, elo_deltas from Game where round = @round and end_time != 0 ORDER BY id ASC", conn);
                cmd.Parameters.AddWithValue("round", result.Round);
                await using var reader = await cmd.ExecuteReaderAsync();

                while (await reader.ReadAsync())
                {
                    var teams     = (int[])reader.GetValue(0);
                    var gameId    = reader.GetInt32(1);
                    var eloDeltas = (double[])reader.GetValue(2);
                    result.UpdateRatings(teams, eloDeltas, gameId, true);
                    result.NumGames++;
                }
            }
            return(result);
        }